From d14da7f34ae2322e72cf289c032c4c23b8bf970a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 10:31:57 +0900 Subject: [PATCH 0001/3664] Enable the "win" clients. The win clients are the native windows (NOT sdl!! *twitch*). Things are already looking on the up: only three errors in in_win.c. I'm not looking forward to vid_win.c (ex vid_wgl.c), though. --- config.d/build_control.m4 | 49 +++++++++++---------- libs/video/targets/Makefile.am | 14 +++--- libs/video/targets/{vid_wgl.c => vid_win.c} | 0 3 files changed, 33 insertions(+), 30 deletions(-) rename libs/video/targets/{vid_wgl.c => vid_win.c} (100%) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index baeaa6e12..b47eb10f9 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -5,7 +5,7 @@ dnl ================================================================== QF_WITH_TARGETS( clients, [ --with-clients= compile clients in :], - [fbdev,sdl,svga,x11],dummy + [fbdev,sdl,svga,win,x11],dummy ) QF_WITH_TARGETS( servers, @@ -133,25 +133,28 @@ if test "x$HAVE_SVGA" = xyes; then QF_NEED(libs,[util gamecode ruamoko gib audio image models video console net qw client]) fi fi -#if test "x$mingw" = xyes; then -# if test "x$ENABLE_clients_wgl" = xyes; then -# QW_TARGETS="$QW_TARGETS qw-client-wgl\$(EXEEXT)" -# NQ_TARGETS="$NQ_TARGETS nq-wgl\$(EXEEXT)" -# CL_TARGETS="$CL_TARGETS WGL" -# VID_TARGETS="$VID_TARGETS libQFwgl.la" -# QF_NEED(vid_render, [gl]) -# QF_NEED(models, [gl]) -# QF_NEED(alias, [gl]) -# QF_NEED(brush, [gl]) -# QF_NEED(iqm, [gl]) -# QF_NEED(sprite, [gl]) -# QF_NEED(vid, [common]) -# QF_NEED(qw, [client common]) -# QF_NEED(nq, [client common]) -# QF_NEED(console, [client]) -# QF_NEED(libs,[util gamecode ruamoko gib audio image models video console net qw client]) -# fi -#fi +if test "x$mingw" = xyes; then + if test "x$ENABLE_clients_win" = xyes; then + QW_TARGETS="$QW_TARGETS qw-client-win\$(EXEEXT)" + NQ_TARGETS="$NQ_TARGETS nq-win\$(EXEEXT)" + CL_TARGETS="$CL_TARGETS WIN" + VID_TARGETS="$VID_TARGETS libQFwin.la" + QF_NEED(vid_render, [sw sw32 gl glsl]) + QF_NEED(models, [sw gl glsl]) + QF_NEED(alias, [sw gl glsl]) + QF_NEED(brush, [sw gl glsl]) + QF_NEED(iqm, [sw gl glsl]) + QF_NEED(sprite, [sw gl glsl]) + if test "x$ASM_ARCH" = "xyes"; then + QF_NEED(swrend, [asm]) + fi + QF_NEED(vid, [common win]) + QF_NEED(qw, [client common]) + QF_NEED(nq, [client common]) + QF_NEED(console, [client]) + QF_NEED(libs,[util gamecode ruamoko gib audio image models video console net qw client]) + fi +fi unset SV_TARGETS if test "x$ENABLE_servers_nq" = xyes; then @@ -265,9 +268,9 @@ QF_PROCESS_NEED_LIBS(brush, [gl glsl sw]) QF_PROCESS_NEED_LIBS(iqm, [gl glsl sw]) QF_PROCESS_NEED_LIBS(sprite, [gl glsl sw]) -QF_PROCESS_NEED_LIBS(vid, [common sdl svga x11]) -QF_PROCESS_NEED_LIBS(qw, [client common sdl server], a) -QF_PROCESS_NEED_LIBS(nq, [client common sdl server], a) +QF_PROCESS_NEED_LIBS(vid, [common sdl svga win x11]) +QF_PROCESS_NEED_LIBS(qw, [client common sdl win server], a) +QF_PROCESS_NEED_LIBS(nq, [client common sdl win server], a) if test -n "$CL_TARGETS"; then CD_TARGETS="libQFcd.la" diff --git a/libs/video/targets/Makefile.am b/libs/video/targets/Makefile.am index 98faa6099..6dbb4e7fd 100644 --- a/libs/video/targets/Makefile.am +++ b/libs/video/targets/Makefile.am @@ -10,7 +10,7 @@ lib_LTLIBRARIES= @JOY_TARGETS@ noinst_LTLIBRARIES= @VID_TARGETS@ @vid_libs@ EXTRA_LTLIBRARIES= \ - libQFjs.la libQFfbdev.la libQFsvga.la libQFx11.la libQFsdl.la libQFwgl.la \ + libQFjs.la libQFfbdev.la libQFsvga.la libQFx11.la libQFsdl.la libQFwin.la \ libvid_common.la libvid_sdl.la \ libvid_svga.la libvid_x11.la @@ -94,12 +94,12 @@ libQFsvga_la_DEPENDENCIES= $(svga_libs) # # OpenGL in Win32 # -wgl_libs=libvid_common.la libvid_gl.la -libQFwgl_la_CFLAGS= @PREFER_NON_PIC@ $(WGL_CFLAGS) -libQFwgl_la_SOURCES= in_win.c vid_wgl.c -libQFwgl_la_LDFLAGS= @STATIC@ -libQFwgl_la_LIBADD= $(wgl_libs) -libQFwgl_la_DEPENDENCIES= $(wgl_libs) +win_libs=libvid_common.la libvid_gl.la +libQFwin_la_CFLAGS= @PREFER_NON_PIC@ $(WGL_CFLAGS) +libQFwin_la_SOURCES= in_win.c vid_win.c +libQFwin_la_LDFLAGS= @STATIC@ +libQFwin_la_LIBADD= $(win_libs) +libQFwin_la_DEPENDENCIES= $(win_libs) # # X11 software rendering diff --git a/libs/video/targets/vid_wgl.c b/libs/video/targets/vid_win.c similarity index 100% rename from libs/video/targets/vid_wgl.c rename to libs/video/targets/vid_win.c From 23bd3d99f84e43fd94646bae89386a9c6b619478 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 10:34:49 +0900 Subject: [PATCH 0002/3664] Fix the two unsigned/signed comparison warnings. Now just for the real error in in_win.c: key_dest. --- libs/video/targets/in_win.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index 2a14d7179..377321fbf 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -385,7 +385,7 @@ IN_LL_Shutdown (void) static void IN_MouseEvent (unsigned mstate) { - int i; + unsigned i; if (in_mouse_avail && !dinput) { // perform button actions @@ -424,7 +424,7 @@ IN_LL_ProcessEvents (void) MSG msg; int mx, my; // HDC hdc; - int i; + unsigned i; DIDEVICEOBJECTDATA od; DWORD dwElements; HRESULT hr; From 8153646edabbe4996c259d641e5efb7629e1d978 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 10:42:08 +0900 Subject: [PATCH 0003/3664] Use a callback for in-game keystate detection. Yay bitrot :P --- libs/video/targets/in_win.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index 377321fbf..a3d9795d0 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -81,6 +81,7 @@ static HINSTANCE hInstDI; static qboolean dinput; static qboolean vid_wassuspended = false; +static qboolean win_in_game = false; typedef struct MYDATA { LONG lX; // X axis goes here @@ -349,12 +350,20 @@ in_paste_buffer_f (void) } } +static void +win_keydest_callback (keydest_t key_dest) +{ + win_in_game = key_dest == key_game; +} + void IN_LL_Init (void) { uiWheelMessage = RegisterWindowMessage ("MSWHEEL_ROLLMSG"); IN_StartupMouse (); + + Key_KeydestCallback (win_keydest_callback); Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, "Paste the contents of the C&P buffer to the console"); } @@ -733,7 +742,7 @@ AppActivate (BOOL fActive, BOOL minimize) } } else if ((modestate == MS_WINDOWED) && in_grab->int_val - && key_dest == key_game) { + && win_in_game) { IN_ActivateMouse (); IN_HideMouse (); } From 40af4bb98688edd41fbf075e249b54c526a00569 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 11:25:30 +0900 Subject: [PATCH 0004/3664] Make vid.width/height unsigned and clean up the mess. --- include/QF/plugin/vid_render.h | 2 +- include/QF/vid.h | 8 ++++---- include/r_screen.h | 2 +- libs/video/renderer/gl/gl_screen.c | 2 +- libs/video/renderer/glsl/glsl_screen.c | 2 +- libs/video/renderer/sw/d_fill.c | 4 ++-- libs/video/renderer/sw/d_modech.c | 2 +- libs/video/renderer/sw/draw.c | 8 ++++---- libs/video/renderer/sw/screen.c | 2 +- libs/video/renderer/sw/sw_rmain.c | 2 +- libs/video/renderer/sw32/d_fill.c | 12 ++++++------ libs/video/renderer/sw32/d_modech.c | 2 +- libs/video/renderer/sw32/draw.c | 13 +++++++------ libs/video/renderer/sw32/screen.c | 2 +- libs/video/targets/context_x11.c | 3 ++- libs/video/targets/in_x11.c | 4 ++-- 16 files changed, 36 insertions(+), 34 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index bdec285d1..90b34eec8 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -138,7 +138,7 @@ typedef struct vid_render_funcs_s { void (*SCR_DrawTurtle) (void); void (*SCR_DrawPause) (void); struct tex_s *(*SCR_CaptureBGR) (void); - struct tex_s *(*SCR_ScreenShot) (int width, int height); + struct tex_s *(*SCR_ScreenShot) (unsigned width, unsigned height); void (*SCR_DrawStringToSnap) (const char *s, struct tex_s *tex, int x, int y); diff --git a/include/QF/vid.h b/include/QF/vid.h index 07396b566..9faf1e293 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -48,8 +48,8 @@ typedef struct { unsigned int *colormap32; // 256 * VID_GRADES size int fullbright; // index of first fullbright color int rowbytes; // may be > width if displayed in a window - int width; - int height; + unsigned width; + unsigned height; float aspect; // width / height -- < 1 is taller than wide int numpages; qboolean recalc_refdef; // if true, recalc vid-based stuff @@ -59,8 +59,8 @@ typedef struct { int conrowbytes; int conwidth; int conheight; - int maxwarpwidth; - int maxwarpheight; + unsigned maxwarpwidth; + unsigned maxwarpheight; byte *direct; // direct drawing to framebuffer, if not // NULL int (*surf_cache_size)(int width, int height); diff --git a/include/r_screen.h b/include/r_screen.h index 8d3b08e91..5f7978e01 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -42,7 +42,7 @@ void SCR_DrawTime (void); void SCR_DrawTurtle (void); void SCR_DrawPause (void); struct tex_s *SCR_CaptureBGR (void); -struct tex_s *SCR_ScreenShot (int width, int height); +struct tex_s *SCR_ScreenShot (unsigned width, unsigned height); void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index d463880d8..ce6c257a7 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -81,7 +81,7 @@ gl_SCR_CaptureBGR (void) } tex_t * -gl_SCR_ScreenShot (int width, int height) +gl_SCR_ScreenShot (unsigned width, unsigned height) { unsigned char *src, *dest, *snap; float fracw, frach; diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index 56e481c41..b356a0108 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -228,7 +228,7 @@ glsl_SCR_CaptureBGR (void) } tex_t * -glsl_SCR_ScreenShot (int width, int height) +glsl_SCR_ScreenShot (unsigned width, unsigned height) { return 0; } diff --git a/libs/video/renderer/sw/d_fill.c b/libs/video/renderer/sw/d_fill.c index be9bfd3ab..d38a3def9 100644 --- a/libs/video/renderer/sw/d_fill.c +++ b/libs/video/renderer/sw/d_fill.c @@ -51,9 +51,9 @@ D_FillRect (vrect_t *rect, int color) rheight += ry; ry = 0; } - if (rx + rwidth > vid.width) + if ((unsigned) (rx + rwidth) > vid.width) rwidth = vid.width - rx; - if (ry + rheight > vid.height) + if ((unsigned) (ry + rheight) > vid.height) rheight = vid.height - rx; if (rwidth < 1 || rheight < 1) diff --git a/libs/video/renderer/sw/d_modech.c b/libs/video/renderer/sw/d_modech.c index 1498829e7..40956fc53 100644 --- a/libs/video/renderer/sw/d_modech.c +++ b/libs/video/renderer/sw/d_modech.c @@ -100,7 +100,7 @@ D_ViewChanged (void) r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift); { - int i; + unsigned i; for (i = 0; i < vid.height; i++) { d_scantable[i] = i * rowpixels; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 08110401a..65b13c0c7 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -553,7 +553,7 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, width += x; x = 0; } - if (x + width > vid.width) + if ((unsigned) (x + width) > vid.width) width = vid.width - x; if (width <= 0) return; @@ -562,7 +562,7 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, height += y; y = 0; } - if (y + height > vid.height) + if ((unsigned) (y + height) > vid.height) height = vid.height - y; if (height <= 0) return; @@ -696,7 +696,7 @@ Draw_TileClear (int x, int y, int w, int h) byte *psrc; vrect_t vr; - CLIP (x, y, w, h, vid.width, vid.height); + CLIP (x, y, w, h, (int) vid.width, (int) vid.height); r_rectdesc.rect.x = x; r_rectdesc.rect.y = y; @@ -764,7 +764,7 @@ Draw_Fill (int x, int y, int w, int h, int c) Sys_MaskPrintf (SYS_VID, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); } - CLIP (x, y, w, h, vid.width, vid.height); + CLIP (x, y, w, h, (int) vid.width, (int) vid.height); dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; for (v = 0; v < h; v++, dest += vid.rowbytes) diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index d425f6549..ed4c933f1 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -85,7 +85,7 @@ SCR_CaptureBGR (void) } tex_t * -SCR_ScreenShot (int width, int height) +SCR_ScreenShot (unsigned width, unsigned height) { unsigned char *src, *dest; float fracw, frach; diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 1b5e99a74..8da0a27c8 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -1084,7 +1084,7 @@ static void renderlookup (byte **offs, byte* bufs) { byte *p = (byte*)vid.buffer; - int x, y; + unsigned x, y; for (y = 0; y < vid.height; y++) { for (x = 0; x < vid.width; x++, offs++) p[x] = **offs; diff --git a/libs/video/renderer/sw32/d_fill.c b/libs/video/renderer/sw32/d_fill.c index 220806731..a4843de35 100644 --- a/libs/video/renderer/sw32/d_fill.c +++ b/libs/video/renderer/sw32/d_fill.c @@ -63,9 +63,9 @@ sw32_D_FillRect (vrect_t *rect, int color) rheight += ry; ry = 0; } - if (rx + rwidth > vid.width) + if ((unsigned) (rx + rwidth) > vid.width) rwidth = vid.width - rx; - if (ry + rheight > vid.height) + if ((unsigned) (ry + rheight) > vid.height) rheight = vid.height - rx; if (rwidth < 1 || rheight < 1) @@ -101,9 +101,9 @@ sw32_D_FillRect (vrect_t *rect, int color) rheight += ry; ry = 0; } - if (rx + rwidth > vid.width) + if ((unsigned) (rx + rwidth) > vid.width) rwidth = vid.width - rx; - if (ry + rheight > vid.height) + if ((unsigned) (ry + rheight) > vid.height) rheight = vid.height - rx; if (rwidth < 1 || rheight < 1) @@ -140,9 +140,9 @@ sw32_D_FillRect (vrect_t *rect, int color) rheight += ry; ry = 0; } - if (rx + rwidth > vid.width) + if ((unsigned) (rx + rwidth) > vid.width) rwidth = vid.width - rx; - if (ry + rheight > vid.height) + if ((unsigned) (ry + rheight) > vid.height) rheight = vid.height - rx; if (rwidth < 1 || rheight < 1) diff --git a/libs/video/renderer/sw32/d_modech.c b/libs/video/renderer/sw32/d_modech.c index 7ca3efec3..14d1c690c 100644 --- a/libs/video/renderer/sw32/d_modech.c +++ b/libs/video/renderer/sw32/d_modech.c @@ -87,7 +87,7 @@ sw32_D_ViewChanged (void) r_refdef.vrectbottom - (sw32_d_pix_max << sw32_d_y_aspect_shift); { - int i; + unsigned i; for (i = 0; i < vid.height; i++) { sw32_d_scantable[i] = i * rowpixels; diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c index e07e616ad..b02ee61ac 100644 --- a/libs/video/renderer/sw32/draw.c +++ b/libs/video/renderer/sw32/draw.c @@ -669,7 +669,7 @@ sw32_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, width += x; x = 0; } - if (x + width > vid.width) + if ((unsigned) (x + width) > vid.width) width = vid.width - x; if (width <= 0) return; @@ -678,7 +678,7 @@ sw32_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, height += y; y = 0; } - if (y + height > vid.height) + if ((unsigned) (y + height) > vid.height) height = vid.height - y; if (height <= 0) return; @@ -1112,7 +1112,7 @@ sw32_Draw_TileClear (int x, int y, int w, int h) byte *psrc; vrect_t vr; - CLIP (x, y, w, h, vid.width, vid.height); + CLIP (x, y, w, h, (int) vid.width, (int) vid.height); r_rectdesc.rect.x = x; r_rectdesc.rect.y = y; @@ -1179,7 +1179,7 @@ sw32_Draw_Fill (int x, int y, int w, int h, int c) Sys_MaskPrintf (SYS_VID, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); } - CLIP (x, y, w, h, vid.width, vid.height); + CLIP (x, y, w, h, (int) vid.width, (int) vid.height); switch (sw32_r_pixbytes) { case 1: @@ -1304,7 +1304,8 @@ sw32_Draw_BlendScreen (quat_t color) break; case 2: { - int g1, g2, x, y; + int g1, g2; + unsigned x, y; unsigned short rramp[32], gramp[64], bramp[32], *temp; for (i = 0; i < 32; i++) { r = i << 3; @@ -1331,7 +1332,7 @@ sw32_Draw_BlendScreen (quat_t color) break; case 4: { - int x, y; + unsigned x, y; byte ramp[256][4], *temp; for (i = 0; i < 256; i++) { diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index 63f0ce6e1..74ae6f54d 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -88,7 +88,7 @@ sw32_SCR_CaptureBGR (void) } tex_t * -sw32_SCR_ScreenShot (int width, int height) +sw32_SCR_ScreenShot (unsigned width, unsigned height) { return 0; } diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index dc9ae9a0c..6ad810481 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -339,7 +339,8 @@ check_mouse_event (Display *disp, XEvent *ev, XPointer arg) XMotionEvent *me = &ev->xmotion; if (ev->type != MotionNotify) return False; - if (me->x != viddef.width / 2 || me->y != viddef.height / 2) + if ((unsigned) me->x != viddef.width / 2 + || (unsigned) me->y != viddef.height / 2) return False; return True; } diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index dc689a7d5..afc206eba 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -700,8 +700,8 @@ event_motion (XEvent *event) } else { if (vid_fullscreen->int_val || input_grabbed) { if (!event->xmotion.send_event) { - int dist_x = abs (viddef.width / 2 - event->xmotion.x); - int dist_y = abs (viddef.height / 2 - event->xmotion.y); + unsigned dist_x = abs (viddef.width / 2 - event->xmotion.x); + unsigned dist_y = abs (viddef.height / 2 - event->xmotion.y); in_mouse_x += (event->xmotion.x - p_mouse_x); in_mouse_y += (event->xmotion.y - p_mouse_y); if (dist_x > viddef.width / 4 || dist_y > viddef.height / 4) { From 35999b527f0a3dd46724994b83fa01390329ae2c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 12:11:14 +0900 Subject: [PATCH 0005/3664] Remove a dead prototype. QFGL_ProcAddress has been private since the vid_render plugin hackathon. --- include/QF/GL/funcs.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/QF/GL/funcs.h b/include/QF/GL/funcs.h index dbbb2c679..e00221ca2 100644 --- a/include/QF/GL/funcs.h +++ b/include/QF/GL/funcs.h @@ -44,6 +44,5 @@ qboolean GLF_Init (void); qboolean GLF_FindFunctions (void); -void *QFGL_ProcAddress (void *handle, const char *name, qboolean); #endif // __QF_GL_funcs_h_ From ae6dfd8cb647053899cf05be93901afc79be7302 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 12:13:00 +0900 Subject: [PATCH 0006/3664] Move the mouse activation/deactivation into in_win.c. It now gets handled by the keydest callback (I hope it still works). --- libs/video/targets/in_win.c | 7 +++++++ libs/video/targets/vid_win.c | 19 +------------------ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index a3d9795d0..cb54631f4 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -354,6 +354,13 @@ static void win_keydest_callback (keydest_t key_dest) { win_in_game = key_dest == key_game; + if (win_in_game) { + IN_ActivateMouse (); + IN_HideMouse (); + } else { + IN_DeactivateMouse (); + IN_ShowMouse (); + } } void diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index bec07fe19..6c19b56a0 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -264,19 +264,9 @@ VID_SetMode (unsigned char *palette) // Set either the fullscreen or windowed mode if (!vid_fullscreen->int_val) { - if (in_grab->int_val && key_dest == key_game) { - stat = VID_SetWindowedMode (); - IN_ActivateMouse (); - IN_HideMouse (); - } else { - IN_DeactivateMouse (); - IN_ShowMouse (); - stat = VID_SetWindowedMode (); - } + stat = VID_SetWindowedMode (); } else { stat = VID_SetFullDIBMode (); - IN_ActivateMouse (); - IN_HideMouse (); } VID_UpdateWindowStatus (window_x, window_y); @@ -361,13 +351,6 @@ GL_EndRendering (void) } } else { windowed_mouse = true; - if (key_dest == key_game && !in_mouse_avail && ActiveApp) { - IN_ActivateMouse (); - IN_HideMouse (); - } else if (in_mouse_avail && key_dest != key_game) { - IN_DeactivateMouse (); - IN_ShowMouse (); - } } } } From b0ec63ac563b8f80893569dfb5215120868628df Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 12:13:54 +0900 Subject: [PATCH 0007/3664] Remove a dead var. vid_colormap died with the vid_render plugin birth. --- libs/video/targets/vid.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 46507e26d..34176bc3c 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -48,7 +48,6 @@ /* Software and hardware gamma support */ #define viddef (*r_data->vid) -byte *vid_colormap; cvar_t *vid_gamma; cvar_t *vid_system_gamma; cvar_t *con_width; // FIXME: Try to move with rest of con code From bd537ac1b11ac46b6efd131adc129a8ecd55aede Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 12:15:25 +0900 Subject: [PATCH 0008/3664] Fix vid_win.c compilation. It will not work yet. --- libs/video/targets/vid_win.c | 133 ++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 57 deletions(-) diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 6c19b56a0..51fd83542 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -1,7 +1,7 @@ /* - vid_wgl.c + vid_win.c - Win32 WGL vid component + Win32 vid component Copyright (C) 1996-1997 Id Software, Inc. @@ -52,6 +52,7 @@ #include "r_cvar.h" #include "win32/resources/resource.h" #include "sbar.h" +#include "vid_internal.h" extern const char *gl_renderer; @@ -63,11 +64,12 @@ DEVMODE win_gdevmode; int window_center_x, window_center_y, window_x, window_y, window_width, window_height; -static HGLRC (GLAPIENTRY *qf_wglCreateContext) (HDC); -static BOOL (GLAPIENTRY *qf_wglDeleteContext) (HGLRC); -static HGLRC (GLAPIENTRY *qf_wglGetCurrentContext) (void); -static HDC (GLAPIENTRY *qf_wglGetCurrentDC) (void); -static BOOL (GLAPIENTRY *qf_wglMakeCurrent) (HDC, HGLRC); +static void *libgl_handle; +static HGLRC (GLAPIENTRY *qfwglCreateContext) (HDC); +static BOOL (GLAPIENTRY *qfwglDeleteContext) (HGLRC); +static HGLRC (GLAPIENTRY *qfwglGetCurrentContext) (void); +static HDC (GLAPIENTRY *qfwglGetCurrentDC) (void); +static BOOL (GLAPIENTRY *qfwglMakeCurrent) (HDC, HGLRC); #define MAX_MODE_LIST 30 #define VID_ROW_SIZE 3 @@ -97,7 +99,7 @@ static void GL_Init (void); static void * (WINAPI *glGetProcAddress) (const char *symbol) = NULL; -void * +static void * QFGL_GetProcAddress (void *handle, const char *name) { void *glfunc = NULL; @@ -109,15 +111,25 @@ QFGL_GetProcAddress (void *handle, const char *name) return glfunc; } -void * -QFGL_LoadLibrary (void) +static void * +QFGL_ProcAddress (const char *name, qboolean crit) { - void *handle; + void *glfunc = NULL; - if (!(handle = LoadLibrary (gl_driver->string))) - Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); - glGetProcAddress = (void *(WINAPI *)(const char*)) GetProcAddress (handle, "wglGetProcAddress"); - return handle; + Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); + + glfunc = QFGL_GetProcAddress (libgl_handle, name); + if (glfunc) { + Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); + return glfunc; + } + Sys_MaskPrintf (SYS_VID, "not found\n"); + + if (crit) { + Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", + name); + } + return NULL; } //==================================== @@ -178,7 +190,7 @@ VID_SetWindowedMode ( void ) PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); ReleaseDC (mainwindow, hdc); - vid.numpages = 2; + viddef.numpages = 2; if(hIcon) { SendMessage (mainwindow, WM_SETICON, (WPARAM) TRUE, (LPARAM) hIcon); @@ -231,7 +243,7 @@ VID_SetFullDIBMode ( void ) PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); ReleaseDC (mainwindow, hdc); - vid.numpages = 2; + viddef.numpages = 2; // needed because we're not getting WM_MOVE messages fullscreen on NT window_x = 0; @@ -256,11 +268,11 @@ VID_SetMode (unsigned char *palette) WindowRect.top = WindowRect.left = 0; - WindowRect.right = vid_width->int_val; - WindowRect.bottom = vid_height->int_val; + WindowRect.right = viddef.width; + WindowRect.bottom = viddef.height; - window_width = vid_width->int_val; - window_height = vid_height->int_val; + window_width = viddef.width; + window_height = viddef.height; // Set either the fullscreen or windowed mode if (!vid_fullscreen->int_val) { @@ -284,7 +296,7 @@ VID_SetMode (unsigned char *palette) // ourselves at the top of the z order, then grab the foreground again, // Who knows if it helps, but it probably doesn't hurt SetForegroundWindow (mainwindow); - VID_SetPalette (palette); + viddef.set_palette (palette); while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); @@ -302,12 +314,12 @@ VID_SetMode (unsigned char *palette) // fix the leftover Alt from any Alt-Tab or the like that switched us away IN_ClearStates (); - Sys_Printf ("Video mode %ix%i initialized.\n", vid_width->int_val, - vid_height->int_val); + Sys_Printf ("Video mode %ix%i initialized.\n", + viddef.width, viddef.height); - VID_SetPalette (palette); + viddef.set_palette (palette); - vid.recalc_refdef = 1; + viddef.recalc_refdef = 1; return true; } @@ -333,7 +345,7 @@ GL_Init (void) fullsbardraw = true; } -void +static void GL_EndRendering (void) { if (!scr_skipupdate) { @@ -368,12 +380,12 @@ VID_Shutdown (void) DestroyWindow (hwnd_dialog); #endif - if (vid.initialized) { + if (viddef.initialized) { win_canalttab = false; - hRC = qf_wglGetCurrentContext (); - hDC = qf_wglGetCurrentDC (); + hRC = qfwglGetCurrentContext (); + hDC = qfwglGetCurrentDC (); - qf_wglMakeCurrent (NULL, NULL); + qfwglMakeCurrent (NULL, NULL); // LordHavoc: free textures before closing (may help NVIDIA) for (i = 0; i < 8192; i++) @@ -381,7 +393,7 @@ VID_Shutdown (void) qfglDeleteTextures (8192, temp); if (hRC) - qf_wglDeleteContext (hRC); + qfwglDeleteContext (hRC); if (hDC && mainwindow) ReleaseDC (mainwindow, hDC); @@ -427,6 +439,23 @@ bSetupPixelFormat (HDC hDC) return TRUE; } +static void +wgl_load_gl (void) +{ + viddef.get_proc_address = QFGL_ProcAddress; + viddef.end_rendering = GL_EndRendering; + + if (!(libgl_handle = LoadLibrary (gl_driver->string))) + Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); + glGetProcAddress =(void*)GetProcAddress(libgl_handle, "wglGetProcAddress"); + + qfwglCreateContext = QFGL_ProcAddress ("wglCreateContext", true); + qfwglDeleteContext = QFGL_ProcAddress ("wglDeleteContext", true); + qfwglGetCurrentContext = QFGL_ProcAddress ("wglGetCurrentContext", true); + qfwglGetCurrentDC = QFGL_ProcAddress ("wglGetCurrentDC", true); + qfwglMakeCurrent = QFGL_ProcAddress ("wglMakeCurrent", true); +} + void VID_Init (byte *palette, byte *colormap) { @@ -437,21 +466,12 @@ VID_Init (byte *palette, byte *colormap) DWORD lasterror; WNDCLASS wc; + R_LoadModule (wgl_load_gl, 0); //FIXME VID_SetPalette + vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ROM | CVAR_ARCHIVE, NULL, "Run WGL client at fullscreen"); GLF_Init (); - qf_wglCreateContext = QFGL_ProcAddress (libgl_handle, "wglCreateContext", - true); - qf_wglDeleteContext = QFGL_ProcAddress (libgl_handle, "wglDeleteContext", - true); - qf_wglGetCurrentContext = QFGL_ProcAddress (libgl_handle, - "wglGetCurrentContext", true); - qf_wglGetCurrentDC = QFGL_ProcAddress (libgl_handle, "wglGetCurrentDC", - true); - qf_wglMakeCurrent = QFGL_ProcAddress (libgl_handle, "wglMakeCurrent", - true); - memset (&win_gdevmode, 0, sizeof (win_gdevmode)); hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1)); @@ -493,8 +513,8 @@ VID_Init (byte *palette, byte *colormap) stat = EnumDisplaySettings (NULL, vid_mode, &win_gdevmode); if ((win_gdevmode.dmBitsPerPel == bpp) - && (win_gdevmode.dmPelsWidth == vid.width) - && (win_gdevmode.dmPelsHeight == vid.height)) { + && (win_gdevmode.dmPelsWidth == viddef.width) + && (win_gdevmode.dmPelsHeight == viddef.height)) { win_gdevmode.dmFields = (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT); @@ -509,13 +529,13 @@ VID_Init (byte *palette, byte *colormap) } while (stat); if (!stat) Sys_Error ("Couldn't get requested resolution (%i, %i, %i)", - vid_width->int_val, vid_height->int_val, bpp); + viddef.width, viddef.height, bpp); } - vid.maxwarpwidth = WARP_WIDTH; - vid.maxwarpheight = WARP_HEIGHT; - vid.colormap8 = vid_colormap = colormap; - vid.fullbright = 256 - vid.colormap8[256 * VID_GRADES]; + viddef.maxwarpwidth = WARP_WIDTH; + viddef.maxwarpheight = WARP_HEIGHT; + viddef.colormap8 = colormap; + viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; #ifdef SPLASH_SCREEN if(hwnd_dialog) @@ -527,7 +547,7 @@ VID_Init (byte *palette, byte *colormap) maindc = GetDC (mainwindow); bSetupPixelFormat (maindc); - baseRC = qf_wglCreateContext (maindc); + baseRC = qfwglCreateContext (maindc); if (!baseRC) { lasterror=GetLastError(); if (maindc && mainwindow) @@ -538,10 +558,10 @@ VID_Init (byte *palette, byte *colormap) "Error code: (%lx)", lasterror); } - if (!qf_wglMakeCurrent (maindc, baseRC)) { + if (!qfwglMakeCurrent (maindc, baseRC)) { lasterror = GetLastError (); if (baseRC) - qf_wglDeleteContext (baseRC); + qfwglDeleteContext (baseRC); if (maindc && mainwindow) ReleaseDC (mainwindow, maindc); Sys_Error ("wglMakeCurrent failed (%lx)", lasterror); @@ -550,10 +570,9 @@ VID_Init (byte *palette, byte *colormap) GL_Init (); VID_InitGamma (palette); - VID_Init8bitPalette (); - VID_SetPalette (vid.palette); + viddef.set_palette (viddef.palette); - vid.initialized = true; + viddef.initialized = true; win_canalttab = true; @@ -591,7 +610,7 @@ VID_SetGamma (double gamma) for (i = 0; i < 256; i++) { currentgammaramps[2][i] = currentgammaramps[1][i] = - currentgammaramps[0][i] = gammatable[i] * 256; + currentgammaramps[0][i] = viddef.gammatable[i] * 256; } i = SetDeviceGammaRamp (hdc, ¤tgammaramps[0][0]); From d7e98dcd6d3235035fd45d82d5325ef81f56d61d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 12:16:05 +0900 Subject: [PATCH 0009/3664] Build libvid_win.la. Now libQFwin.la builds. Once I get nq-win and qw-client-win building, the "fun" begins. --- libs/video/targets/Makefile.am | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libs/video/targets/Makefile.am b/libs/video/targets/Makefile.am index 6dbb4e7fd..5c9f216f7 100644 --- a/libs/video/targets/Makefile.am +++ b/libs/video/targets/Makefile.am @@ -12,7 +12,7 @@ noinst_LTLIBRARIES= @VID_TARGETS@ @vid_libs@ EXTRA_LTLIBRARIES= \ libQFjs.la libQFfbdev.la libQFsvga.la libQFx11.la libQFsdl.la libQFwin.la \ libvid_common.la libvid_sdl.la \ - libvid_svga.la libvid_x11.la + libvid_svga.la libvid_win.la libvid_x11.la joy_linux_src= joy_linux.c joy_win_src= joy_win.c @@ -45,6 +45,10 @@ libvid_x11_la_SOURCES= in_x11.c context_x11.c dga_check.c libvid_x11_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) libvid_x11_la_LDFLAGS= @STATIC@ +libvid_win_la_SOURCES= in_win.c +libvid_win_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) +libvid_win_la_LDFLAGS= @STATIC@ + libvid_svga_la_SOURCES= in_svgalib.c libvid_svga_la_CFLAGS= @PREFER_NON_PIC@ $(SVGA_CFLAGS) libvid_svga_la_LDFLAGS= @STATIC@ @@ -94,9 +98,9 @@ libQFsvga_la_DEPENDENCIES= $(svga_libs) # # OpenGL in Win32 # -win_libs=libvid_common.la libvid_gl.la +win_libs=libvid_common.la libvid_win.la libQFwin_la_CFLAGS= @PREFER_NON_PIC@ $(WGL_CFLAGS) -libQFwin_la_SOURCES= in_win.c vid_win.c +libQFwin_la_SOURCES= vid_win.c libQFwin_la_LDFLAGS= @STATIC@ libQFwin_la_LIBADD= $(win_libs) libQFwin_la_DEPENDENCIES= $(win_libs) From bf5eeb873e0a87d26bcbb4a4f9f4d68bf076a5dc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 12:32:18 +0900 Subject: [PATCH 0010/3664] Rename the -wgl targets to -win. And add the necessary libs. Almost there :) --- nq/source/Makefile.am | 19 ++++++++++--------- qw/source/Makefile.am | 19 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/nq/source/Makefile.am b/nq/source/Makefile.am index 4ee91c4fc..00099c5c3 100644 --- a/nq/source/Makefile.am +++ b/nq/source/Makefile.am @@ -36,7 +36,7 @@ AM_CFLAGS= @PTHREAD_CFLAGS@ bin_PROGRAMS= @NQ_TARGETS@ -EXTRA_PROGRAMS= nq-fbdev nq-sdl nq-svga nq-wgl nq-x11 nq-server +EXTRA_PROGRAMS= nq-fbdev nq-sdl nq-svga nq-win nq-x11 nq-server noinst_LIBRARIES= @nq_libs@ EXTRA_LIBRARIES=libnq_client.a libnq_common.a libnq_sdl.a libnq_server.a @@ -144,17 +144,18 @@ nq_x11_DEPENDENCIES= $(nq_x11_libs) # OpenGL-using targets -# ... SGI/Microsoft WGL (Windows OpenGL) -nq_wgl_libs= \ +# ... Microsoft Windows +nq_win_libs= \ $(client_libs) \ $(cl_plugin_LIBS) \ - $(opengl_QFLIBS) \ - $(top_builddir)/libs/video/targets/libQFwgl.la \ + $(top_builddir)/libs/video/renderer/libQFrenderer.la \ + $(top_builddir)/libs/models/libQFmodels.la \ + $(top_builddir)/libs/video/targets/libQFwin.la \ $(client_LIBS) -nq_wgl_SOURCES= sys_win.c -nq_wgl_LDADD= $(nq_wgl_libs) -lgdi32 -lcomctl32 -lwinmm $(NET_LIBS) -nq_wgl_LDFLAGS= $(common_ldflags) -nq_wgl_DEPENDENCIES= $(nq_wgl_libs) +nq_win_SOURCES= sys_win.c +nq_win_LDADD= $(nq_win_libs) -lgdi32 -lcomctl32 -lwinmm $(NET_LIBS) +nq_win_LDFLAGS= $(common_ldflags) +nq_win_DEPENDENCIES= $(nq_win_libs) # Dedicated Server if SYSTYPE_WIN32 diff --git a/qw/source/Makefile.am b/qw/source/Makefile.am index 288aeee72..b404db293 100644 --- a/qw/source/Makefile.am +++ b/qw/source/Makefile.am @@ -37,7 +37,7 @@ AM_CFLAGS= @PTHREAD_CFLAGS@ bin_PROGRAMS= @QW_TARGETS@ EXTRA_PROGRAMS= \ - qw-client-fbdev qw-client-sdl qw-client-svga qw-client-wgl qw-client-x11 \ + qw-client-fbdev qw-client-sdl qw-client-svga qw-client-win qw-client-x11 \ qw-server qw-master noinst_LIBRARIES= @qw_libs@ @@ -172,17 +172,18 @@ qw_client_x11_LDADD= $(qw_client_x11_libs) \ qw_client_x11_LDFLAGS= $(common_ldflags) qw_client_x11_DEPENDENCIES= $(qw_client_x11_libs) -# ... SGI/Microsoft WGL (Windows OpenGL) -qw_client_wgl_libs= \ +# ... Microsoft Windows +qw_client_win_libs= \ $(client_libs) \ $(cl_plugin_LIBS) \ - $(opengl_LIBS) \ - $(top_builddir)/libs/video/targets/libQFwgl.la \ + $(top_builddir)/libs/video/renderer/libQFrenderer.la \ + $(top_builddir)/libs/models/libQFmodels.la \ + $(top_builddir)/libs/video/targets/libQFwin.la \ $(client_LIBS) -qw_client_wgl_SOURCES= cl_sys_win.c -qw_client_wgl_LDADD= $(qw_client_wgl_libs) -lgdi32 -lwinmm $(NET_LIBS) $(LIBCURL_LIBS) -qw_client_wgl_LDFLAGS= $(common_ldflags) -qw_client_wgl_DEPENDENCIES= $(qw_client_wgl_libs) +qw_client_win_SOURCES= cl_sys_win.c +qw_client_win_LDADD= $(qw_client_win_libs) -lgdi32 -lwinmm $(NET_LIBS) $(LIBCURL_LIBS) +qw_client_win_LDFLAGS= $(common_ldflags) +qw_client_win_DEPENDENCIES= $(qw_client_win_libs) # Stuff that doesn't get linked into an executable NEEDS to be mentioned here, # or it won't be distributed with 'make dist' From 4a387c9c36078fcde64a5072b637c906aa85051a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 12:33:31 +0900 Subject: [PATCH 0011/3664] Remove another dead prototype. --- include/QF/GL/funcs.h | 1 - include/QF/GLSL/funcs.h | 1 - 2 files changed, 2 deletions(-) diff --git a/include/QF/GL/funcs.h b/include/QF/GL/funcs.h index e00221ca2..765bb4bab 100644 --- a/include/QF/GL/funcs.h +++ b/include/QF/GL/funcs.h @@ -42,7 +42,6 @@ #undef QFGL_NEED #undef QFGL_WANT -qboolean GLF_Init (void); qboolean GLF_FindFunctions (void); #endif // __QF_GL_funcs_h_ diff --git a/include/QF/GLSL/funcs.h b/include/QF/GLSL/funcs.h index 28ddf90a5..19d1403a1 100644 --- a/include/QF/GLSL/funcs.h +++ b/include/QF/GLSL/funcs.h @@ -43,7 +43,6 @@ #undef QFGL_NEED #undef QFGL_WANT -qboolean EGLF_Init (void); qboolean EGLF_FindFunctions (void); void *QFEGL_ProcAddress (void *handle, const char *name, qboolean); From 4d6fe3694dc1f33427553f48db795b23797e04b0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 12:33:39 +0900 Subject: [PATCH 0012/3664] Add the missing function required for -win. They're just stubs for now, but nq-win.exe and qw-client-win.exe build. I'm 99.999% certain they won't work, though :P --- libs/video/targets/vid_win.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 51fd83542..b8c35396e 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -470,7 +470,6 @@ VID_Init (byte *palette, byte *colormap) vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ROM | CVAR_ARCHIVE, NULL, "Run WGL client at fullscreen"); - GLF_Init (); memset (&win_gdevmode, 0, sizeof (win_gdevmode)); @@ -618,6 +617,22 @@ VID_SetGamma (double gamma) return i; } +void +VID_LockBuffer (void) +{ +} + +void +VID_UnlockBuffer (void) +{ +} + +void +VID_Update (vrect_t *rects) +{ + //FIXME sw +} + #if 0 static void VID_SaveGamma (void) From d6766a07c5d52507a1164631e5f46f772a568121 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 15:43:04 +0900 Subject: [PATCH 0013/3664] Use a saner default video resolution. 320x200 is way too small these days. --- libs/video/targets/vid_fbdev.c | 2 +- libs/video/targets/vid_sdl.c | 6 +----- libs/video/targets/vid_svgalib.c | 2 +- libs/video/targets/vid_x11.c | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/libs/video/targets/vid_fbdev.c b/libs/video/targets/vid_fbdev.c index 5cd81cc47..36e27b0a2 100644 --- a/libs/video/targets/vid_fbdev.c +++ b/libs/video/targets/vid_fbdev.c @@ -444,7 +444,7 @@ VID_Init (byte *palette, byte *colormap) Cmd_AddCommand ("vid_fbset", VID_fbset_f, "No Description"); /* Interpret command-line params */ - VID_GetWindowSize (320, 200); + VID_GetWindowSize (640, 480); modestr = get_mode (viddef.width, viddef.height, 8); diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index b32efbee1..1a367658f 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -54,10 +54,6 @@ HWND mainwindow; #endif -// The original defaults -#define BASEWIDTH 320 -#define BASEHEIGHT 200 - byte *VGA_pagebase; int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0; @@ -248,7 +244,7 @@ VID_Init (byte *palette, byte *colormap) viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; // Set up display mode (width and height) - VID_GetWindowSize (BASEWIDTH, BASEHEIGHT); + VID_GetWindowSize (640, 480); // Set video width, height and flags flags = (SDL_SWSURFACE | SDL_HWPALETTE); diff --git a/libs/video/targets/vid_svgalib.c b/libs/video/targets/vid_svgalib.c index 8849a4eb5..df0a80685 100644 --- a/libs/video/targets/vid_svgalib.c +++ b/libs/video/targets/vid_svgalib.c @@ -374,7 +374,7 @@ VID_Init (byte *palette, byte *colormap) VID_InitModes (); /* Interpret command-line params */ - VID_GetWindowSize (320, 200); + VID_GetWindowSize (640, 480); current_mode = get_mode (vid.width, vid.height, 8); diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 6430b9c06..41a72f642 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -679,7 +679,7 @@ VID_Init (byte *palette, byte *colormap) srandom (getpid ()); - VID_GetWindowSize (320, 200); + VID_GetWindowSize (640, 480); X11_OpenDisplay (); choose_visual (); X11_SetVidMode (viddef.width, viddef.height); From b3a7ed8a620f10b792d65797e36ceb7f1345a971 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jan 2013 21:11:33 +0900 Subject: [PATCH 0014/3664] Use vid_win.c from engoo as a basis. Thanks to leilei being a diehard sw quake fan, and MH being the hacker he is, engoo's vid_win.c drops Scitech's MGL :) (I really did not want to resurrect that). However, I've modified it so it /compiles/ in QF: ripped out the menu code, ripped out the input handling (that's in in_win.c) and started trying to get it to work for vid_render. The clients at least link, but I'm certain they'll segfault (GPF?). --- libs/video/targets/vid_win.c | 2372 +++++++++++++++++++++++++++------- 1 file changed, 1926 insertions(+), 446 deletions(-) diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index b8c35396e..9fde73bf5 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -29,80 +29,57 @@ #endif #include "winquake.h" +#include -#include "QF/cdaudio.h" #include "QF/cmd.h" -#include "QF/console.h" #include "QF/cvar.h" #include "QF/input.h" #include "QF/keys.h" #include "QF/qargs.h" -#include "QF/qendian.h" -#include "QF/quakefs.h" -#include "QF/screen.h" -#include "QF/sound.h" #include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_vid.h" -#include "compat.h" +#include "d_iface.h" +#include "d_local.h" #include "in_win.h" #include "r_cvar.h" -#include "win32/resources/resource.h" -#include "sbar.h" +#include "r_shared.h" #include "vid_internal.h" -extern const char *gl_renderer; +// true if the ddraw driver started up OK +qboolean vid_usingddraw = false; -HWND mainwindow; -qboolean win_canalttab = false; -modestate_t modestate = MS_UNINIT; -RECT window_rect; -DEVMODE win_gdevmode; -int window_center_x, window_center_y, window_x, window_y, window_width, - window_height; +// compatibility +HWND mainwindow = NULL; +qboolean win_canalttab = false; + +// main application window +HWND hWndWinQuake = NULL; +HDC maindc; + +byte gammatable[256]; + +//FIXME?int yeahimconsoled; static void *libgl_handle; -static HGLRC (GLAPIENTRY *qfwglCreateContext) (HDC); -static BOOL (GLAPIENTRY *qfwglDeleteContext) (HGLRC); -static HGLRC (GLAPIENTRY *qfwglGetCurrentContext) (void); -static HDC (GLAPIENTRY *qfwglGetCurrentDC) (void); -static BOOL (GLAPIENTRY *qfwglMakeCurrent) (HDC, HGLRC); +static HGLRC (GLAPIENTRY * qfwglCreateContext) (HDC); +static BOOL (GLAPIENTRY * qfwglDeleteContext) (HGLRC); +static HGLRC (GLAPIENTRY * qfwglGetCurrentContext) (void); +static HDC (GLAPIENTRY * qfwglGetCurrentDC) (void); +static BOOL (GLAPIENTRY * qfwglMakeCurrent) (HDC, HGLRC); -#define MAX_MODE_LIST 30 -#define VID_ROW_SIZE 3 -#define WARP_WIDTH 320 -#define WARP_HEIGHT 200 -#define MAXWIDTH 10000 -#define MAXHEIGHT 10000 -#define BASEWIDTH 320 -#define BASEHEIGHT 200 - -#define MODE_WINDOWED 0 -#define NO_MODE (MODE_WINDOWED - 1) -#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 1) - -static int windowed_mouse; - -static HICON hIcon; -static RECT WindowRect; -static DWORD WindowStyle; - -static qboolean fullsbardraw = true; - -static HDC maindc; - - -static void GL_Init (void); -static void * (WINAPI *glGetProcAddress) (const char *symbol) = NULL; +static void *(WINAPI * glGetProcAddress) (const char *symbol) = NULL; +static void (*choose_visual) (void); +static void (*create_context) (void); static void * QFGL_GetProcAddress (void *handle, const char *name) { - void *glfunc = NULL; + void *glfunc = NULL; if (glGetProcAddress) glfunc = glGetProcAddress (name); @@ -114,7 +91,7 @@ QFGL_GetProcAddress (void *handle, const char *name) static void * QFGL_ProcAddress (const char *name, qboolean crit) { - void *glfunc = NULL; + void *glfunc = NULL; Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); @@ -132,219 +109,6 @@ QFGL_ProcAddress (const char *name, qboolean crit) return NULL; } -//==================================== - -static void -CenterWindow (HWND hWndCenter, int width, int height, BOOL lefttopjustify) -{ - int CenterX, CenterY; - - CenterX = (GetSystemMetrics (SM_CXSCREEN) - width) / 2; - CenterY = (GetSystemMetrics (SM_CYSCREEN) - height) / 2; - if (CenterX > CenterY * 2) - CenterX >>= 1; // dual screens - CenterX = (CenterX < 0) ? 0 : CenterX; - CenterY = (CenterY < 0) ? 0 : CenterY; - SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); -} - -static qboolean -VID_SetWindowedMode ( void ) -{ - HDC hdc; - int width, height; - RECT rect; - - WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | - WS_MINIMIZEBOX | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - - rect = WindowRect; - AdjustWindowRect (&rect, WindowStyle, FALSE); - - width = rect.right - rect.left; - height = rect.bottom - rect.top; - - // Create the window - mainwindow = CreateWindow ("QuakeForge", PACKAGE_NAME, - WindowStyle, rect.left, rect.top, width, height, - NULL, NULL, global_hInstance, NULL); - - if (!mainwindow) - Sys_Error ("Couldn't create DIB window (%lx)", GetLastError ()); - - // Center and show the window - CenterWindow (mainwindow, WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, false); - - ShowWindow (mainwindow, SW_SHOWDEFAULT); - UpdateWindow (mainwindow); - - modestate = MS_WINDOWED; - - // because we have set the background brush for the window to NULL - // (to avoid flickering when re-sizing the window on the desktop), - // we clear the window to black when created, otherwise it will be - // empty while Quake starts up. - hdc = GetDC (mainwindow); - PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); - ReleaseDC (mainwindow, hdc); - - viddef.numpages = 2; - - if(hIcon) { - SendMessage (mainwindow, WM_SETICON, (WPARAM) TRUE, (LPARAM) hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM) FALSE, (LPARAM) hIcon); - } - - return true; -} - -static qboolean -VID_SetFullDIBMode ( void ) -{ - HDC hdc; - int width, height; - RECT rect; - - if (ChangeDisplaySettings (&win_gdevmode, CDS_FULLSCREEN) - != DISP_CHANGE_SUCCESSFUL) - Sys_Error ("Couldn't set fullscreen DIB mode (%lx)", GetLastError()); - - // FIXME: some drivers have broken FS popup window handling until I find a - // way around it, or find some other cause for it this is a way to avoid it - if (COM_CheckParm ("-brokenpopup")) - WindowStyle = 0; - else - WindowStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - - rect = WindowRect; - AdjustWindowRect (&rect, WindowStyle, FALSE); - - width = rect.right - rect.left; - height = rect.bottom - rect.top; - - // Create the DIB window - mainwindow = CreateWindow ("QuakeForge", "GLQuakeWorld", WindowStyle, - rect.left, rect.top, width, height, NULL, NULL, - global_hInstance, NULL); - - if (!mainwindow) - Sys_Error ("Couldn't create DIB window (%lx)",GetLastError()); - - ShowWindow (mainwindow, SW_SHOWDEFAULT); - UpdateWindow (mainwindow); - - // Because we have set the background brush for the window to NULL - // (to avoid flickering when re-sizing the window on the desktop), we - // clear the window to black when created, otherwise it will be empty - // while Quake starts up. - hdc = GetDC (mainwindow); - PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); - ReleaseDC (mainwindow, hdc); - - viddef.numpages = 2; - - // needed because we're not getting WM_MOVE messages fullscreen on NT - window_x = 0; - window_y = 0; - - if (hIcon) { - SendMessage (mainwindow, WM_SETICON, (WPARAM) TRUE, (LPARAM) hIcon); - SendMessage (mainwindow, WM_SETICON, (WPARAM) FALSE, (LPARAM) hIcon); - } - - return true; -} - -static int -VID_SetMode (unsigned char *palette) -{ - qboolean stat = 0; - MSG msg; - - // so Con_Printfs don't mess us up by forcing vid and snd updates - CDAudio_Pause (); - - WindowRect.top = WindowRect.left = 0; - - WindowRect.right = viddef.width; - WindowRect.bottom = viddef.height; - - window_width = viddef.width; - window_height = viddef.height; - - // Set either the fullscreen or windowed mode - if (!vid_fullscreen->int_val) { - stat = VID_SetWindowedMode (); - } else { - stat = VID_SetFullDIBMode (); - } - - VID_UpdateWindowStatus (window_x, window_y); - - CDAudio_Resume (); - - if (!stat) { - Sys_Error ("Couldn't set video mode"); - } - - // Now we try to make sure we get the focus on the mode switch, because - // sometimes in some systems we don't. We grab the foreground, then - // finish setting up, pump all our messages, and sleep for a little while - // to let messages finish bouncing around the system, then we put - // ourselves at the top of the z order, then grab the foreground again, - // Who knows if it helps, but it probably doesn't hurt - SetForegroundWindow (mainwindow); - viddef.set_palette (palette); - - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - - Sleep (100); - - SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, - SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | - SWP_NOCOPYBITS); - - SetForegroundWindow (mainwindow); - - // fix the leftover Alt from any Alt-Tab or the like that switched us away - IN_ClearStates (); - - Sys_Printf ("Video mode %ix%i initialized.\n", - viddef.width, viddef.height); - - viddef.set_palette (palette); - - viddef.recalc_refdef = 1; - - return true; -} - -void -VID_UpdateWindowStatus (int w_x, int w_y) -{ - window_rect.left = window_x = w_x; - window_rect.top = window_y = w_y; - window_rect.right = window_x + window_width; - window_rect.bottom = window_y + window_height; - window_center_x = (window_rect.left + window_rect.right) / 2; - window_center_y = (window_rect.top + window_rect.bottom) / 2; - - IN_UpdateClipCursor (); -} - -static void -GL_Init (void) -{ - GL_Init_Common (); - if (strnicmp (gl_renderer, "PowerVR", 7) == 0) - fullsbardraw = true; -} - static void GL_EndRendering (void) { @@ -352,92 +116,20 @@ GL_EndRendering (void) qfglFinish (); SwapBuffers (maindc); } - // handle the mouse state when windowed if that's changed if (!vid_fullscreen->int_val) { if (!in_grab->int_val) { - if (windowed_mouse) { - IN_DeactivateMouse (); - IN_ShowMouse (); - windowed_mouse = false; - } +//FIXME if (windowed_mouse) { +//FIXME IN_DeactivateMouse (); +//FIXME IN_ShowMouse (); +//FIXME windowed_mouse = false; +//FIXME } } else { - windowed_mouse = true; +//FIXME windowed_mouse = true; } } } -void -VID_Shutdown (void) -{ - HGLRC hRC; - HDC hDC; - int i; - GLuint temp[8192]; - -#ifdef SPLASH_SCREEN - if(hwnd_dialog) - DestroyWindow (hwnd_dialog); -#endif - - if (viddef.initialized) { - win_canalttab = false; - hRC = qfwglGetCurrentContext (); - hDC = qfwglGetCurrentDC (); - - qfwglMakeCurrent (NULL, NULL); - - // LordHavoc: free textures before closing (may help NVIDIA) - for (i = 0; i < 8192; i++) - temp[i] = i + 1; - qfglDeleteTextures (8192, temp); - - if (hRC) - qfwglDeleteContext (hRC); - - if (hDC && mainwindow) - ReleaseDC (mainwindow, hDC); - - if (vid_fullscreen->int_val) - ChangeDisplaySettings (NULL, 0); - - if (maindc && mainwindow) - ReleaseDC (mainwindow, maindc); - - AppActivate (false, false); - } -} - -//========================================================================== - -static BOOL -bSetupPixelFormat (HDC hDC) -{ - PIXELFORMATDESCRIPTOR pfd ; - int pixelformat; - - memset (&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); - pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; - pfd.iPixelType = PFD_TYPE_RGBA; - - pfd.cColorBits = win_gdevmode.dmBitsPerPel ; - - pfd.cDepthBits = 32; - pfd.iLayerType = PFD_MAIN_PLANE; - - if ((pixelformat = ChoosePixelFormat (hDC, &pfd)) == 0) { - MessageBox (NULL, "ChoosePixelFormat failed", "Error", MB_OK); - return FALSE; - } - - if (SetPixelFormat (hDC, pixelformat, &pfd) == FALSE) { - MessageBox (NULL, "SetPixelFormat failed", "Error", MB_OK); - return FALSE; - } - return TRUE; -} static void wgl_load_gl (void) @@ -447,7 +139,8 @@ wgl_load_gl (void) if (!(libgl_handle = LoadLibrary (gl_driver->string))) Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); - glGetProcAddress =(void*)GetProcAddress(libgl_handle, "wglGetProcAddress"); + glGetProcAddress = + (void *) GetProcAddress (libgl_handle, "wglGetProcAddress"); qfwglCreateContext = QFGL_ProcAddress ("wglCreateContext", true); qfwglDeleteContext = QFGL_ProcAddress ("wglDeleteContext", true); @@ -456,142 +149,1945 @@ wgl_load_gl (void) qfwglMakeCurrent = QFGL_ProcAddress ("wglMakeCurrent", true); } -void -VID_Init (byte *palette, byte *colormap) + +/* +============================================================================= + + DIRECTDRAW VIDEO DRIVER + +============================================================================= +*/ + +LPDIRECTDRAW dd_Object = NULL; +HINSTANCE hInstDDraw = NULL; + +LPDIRECTDRAWSURFACE dd_FrontBuffer = NULL; +LPDIRECTDRAWSURFACE dd_BackBuffer = NULL; + +LPDIRECTDRAWCLIPPER dd_Clipper = NULL; + +typedef HRESULT (WINAPI * DIRECTDRAWCREATEPROC) (GUID FAR *, + LPDIRECTDRAW FAR *, + IUnknown FAR *); +DIRECTDRAWCREATEPROC QDirectDrawCreate = NULL; + +unsigned ddpal[256]; + +byte *vidbuf = NULL; + + +int dd_window_width = 640; +int dd_window_height = 480; +RECT SrcRect; +RECT DstRect; + +static void +DD_UpdateRects (int width, int height) { - BOOL stat; - WORD bpp, vid_mode; - HDC hdc; - HGLRC baseRC; - DWORD lasterror; - WNDCLASS wc; + POINT p; - R_LoadModule (wgl_load_gl, 0); //FIXME VID_SetPalette + p.x = 0; + p.y = 0; - vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ROM | CVAR_ARCHIVE, - NULL, "Run WGL client at fullscreen"); - - memset (&win_gdevmode, 0, sizeof (win_gdevmode)); - - hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1)); + // first we need to figure out where on the primary surface our window + // lives + ClientToScreen (hWndWinQuake, &p); + GetClientRect (hWndWinQuake, &DstRect); + OffsetRect (&DstRect, p.x, p.y); + SetRect (&SrcRect, 0, 0, width, height); +} - // Register the frame class - wc.style = 0; +static void +VID_CreateDDrawDriver (int width, int height, byte *palette, void **buffer, + int *rowbytes) +{ + HRESULT hr; + DDSURFACEDESC ddsd; + + vid_usingddraw = false; + dd_window_width = width; + dd_window_height = height; + + vidbuf = (byte *) malloc (width * height); + buffer[0] = vidbuf; + rowbytes[0] = width; + + if (!(hInstDDraw = LoadLibrary ("ddraw.dll"))) + return; + if (!(QDirectDrawCreate = + (DIRECTDRAWCREATEPROC) GetProcAddress (hInstDDraw, + "DirectDrawCreate"))) + return; + + if (FAILED (hr = QDirectDrawCreate (NULL, &dd_Object, NULL))) + return; + if (FAILED (hr = dd_Object->lpVtbl->SetCooperativeLevel (dd_Object, + hWndWinQuake, + DDSCL_NORMAL))) + return; + + // the primary surface in windowed mode is the full screen + memset (&ddsd, 0, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY; + + // ...and create it + if (FAILED (hr = dd_Object->lpVtbl->CreateSurface (dd_Object, &ddsd, + &dd_FrontBuffer, NULL))) + return; + + // not using a clipper will slow things down and switch aero off + if (FAILED (hr = IDirectDraw_CreateClipper (dd_Object, 0, &dd_Clipper, + NULL))) + return; + if (FAILED (hr = IDirectDrawClipper_SetHWnd (dd_Clipper, 0, hWndWinQuake))) + return; + if (FAILED (hr = IDirectDrawSurface_SetClipper (dd_FrontBuffer, + dd_Clipper))) + return; + + // the secondary surface is an offscreen surface that is the currect + // dimensions + // this will be blitted to the correct location on the primary surface + // (which is the full screen) during our draw op + memset (&ddsd, 0, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + ddsd.dwWidth = width; + ddsd.dwHeight = height; + + if (FAILED (hr = IDirectDraw_CreateSurface (dd_Object, &ddsd, + &dd_BackBuffer, NULL))) + return; + + // direct draw is working now + vid_usingddraw = true; + + // create a palette + VID_InitGamma (palette); + viddef.set_palette (palette); + + // create initial rects + DD_UpdateRects (dd_window_width, dd_window_height); +} + + +/* +===================================================================== + + GDI VIDEO DRIVER + +===================================================================== +*/ + +// common bitmap definition +typedef struct dibinfo { + BITMAPINFOHEADER header; + RGBQUAD acolors[256]; +} dibinfo_t; + + +static HGDIOBJ previously_selected_GDI_obj = NULL; +HBITMAP hDIBSection; +byte *pDIBBase = NULL; +HDC hdcDIBSection = NULL; +HDC hdcGDI = NULL; + + +static void +VID_CreateGDIDriver (int width, int height, byte *palette, void **buffer, + int *rowbytes) +{ + dibinfo_t dibheader; + BITMAPINFO *pbmiDIB = (BITMAPINFO *) & dibheader; + int i; + + hdcGDI = GetDC (hWndWinQuake); + memset (&dibheader, 0, sizeof (dibheader)); + + // fill in the bitmap info + pbmiDIB->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + pbmiDIB->bmiHeader.biWidth = width; + pbmiDIB->bmiHeader.biHeight = height; + pbmiDIB->bmiHeader.biPlanes = 1; + pbmiDIB->bmiHeader.biCompression = BI_RGB; + pbmiDIB->bmiHeader.biSizeImage = 0; + pbmiDIB->bmiHeader.biXPelsPerMeter = 0; + pbmiDIB->bmiHeader.biYPelsPerMeter = 0; + pbmiDIB->bmiHeader.biClrUsed = 256; + pbmiDIB->bmiHeader.biClrImportant = 256; + pbmiDIB->bmiHeader.biBitCount = 8; + + // fill in the palette + for (i = 0; i < 256; i++) { + // d_8to24table isn't filled in yet so this is just for testing + dibheader.acolors[i].rgbRed = palette[i * 3]; + dibheader.acolors[i].rgbGreen = palette[i * 3 + 1]; + dibheader.acolors[i].rgbBlue = palette[i * 3 + 2]; + } + + // create the DIB section + hDIBSection = CreateDIBSection (hdcGDI, + pbmiDIB, + DIB_RGB_COLORS, + (void **) &pDIBBase, NULL, 0); + + // set video buffers + if (pbmiDIB->bmiHeader.biHeight > 0) { + // bottom up + buffer[0] = pDIBBase + (height - 1) * width; + rowbytes[0] = -width; + } else { + // top down + buffer[0] = pDIBBase; + rowbytes[0] = width; + } + + // clear the buffer + memset (pDIBBase, 0xff, width * height); + + if ((hdcDIBSection = CreateCompatibleDC (hdcGDI)) == NULL) + Sys_Error ("DIB_Init() - CreateCompatibleDC failed\n"); + + if ((previously_selected_GDI_obj = + SelectObject (hdcDIBSection, hDIBSection)) == NULL) + Sys_Error ("DIB_Init() - SelectObject failed\n"); + + // create a palette + VID_InitGamma (palette); + viddef.set_palette (palette); +} + + +static void +VID_UnloadAllDrivers (void) +{ + // shut down ddraw + if (vidbuf) { + free (vidbuf); + vidbuf = NULL; + } + + if (dd_Clipper) { + IDirectDrawClipper_Release (dd_Clipper); + dd_Clipper = NULL; + } + + if (dd_FrontBuffer) { + IDirectDrawSurface_Release (dd_FrontBuffer); + dd_FrontBuffer = NULL; + } + + if (dd_BackBuffer) { + IDirectDrawSurface_Release (dd_BackBuffer); + dd_BackBuffer = NULL; + } + + if (dd_Object) { + IDirectDraw_Release (dd_Object); + dd_Object = NULL; + } + + if (hInstDDraw) { + FreeLibrary (hInstDDraw); + hInstDDraw = NULL; + } + + QDirectDrawCreate = NULL; + + // shut down gdi + if (hdcDIBSection) { + SelectObject (hdcDIBSection, previously_selected_GDI_obj); + DeleteDC (hdcDIBSection); + hdcDIBSection = NULL; + } + + if (hDIBSection) { + DeleteObject (hDIBSection); + hDIBSection = NULL; + pDIBBase = NULL; + } + + if (hdcGDI) { + // if hdcGDI exists then hWndWinQuake must also be valid + ReleaseDC (hWndWinQuake, hdcGDI); + hdcGDI = NULL; + } + // not using ddraw now + vid_usingddraw = false; +} + + + +// compatibility +qboolean DDActive; + +// not used any more +void +VID_LockBuffer (void) +{ +} + +void +VID_UnlockBuffer (void) +{ +} + +//static int VID_ForceUnlockedAndReturnState (void) {return 0;} +void +VID_ForceLockState (int lk) +{ +} + + +#define MAX_MODE_LIST 36 +#define VID_ROW_SIZE 3 + +extern qboolean Minimized; + +HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); + +int DIBWidth, DIBHeight; +RECT WindowRect; +DWORD WindowStyle, ExWindowStyle; + +int window_center_x, window_center_y, window_width, window_height; +RECT window_rect; + +DEVMODE win_gdevmode; +static qboolean startwindowed = 0, windowed_mode_set; +static int firstupdate = 1; +static qboolean vid_initialized = false, vid_palettized; +static int vid_fulldib_on_focus_mode; +static qboolean force_minimized, in_mode_set, force_mode_set; +static int windowed_mouse; +static qboolean palette_changed, vid_mode_set, hide_window; +static HICON hIcon; + +#define MODE_WINDOWED 0 +#define MODE_SETTABLE_WINDOW 2 +#define NO_MODE (MODE_WINDOWED - 1) +#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) + +cvar_t *vid_ddraw; + +// Note that 0 is MODE_WINDOWED +cvar_t *vid_mode; + +// Note that 0 is MODE_WINDOWED +cvar_t *_vid_default_mode; + +// Note that 3 is MODE_FULLSCREEN_DEFAULT +cvar_t *_vid_default_mode_win; +cvar_t *vid_wait; +cvar_t *vid_nopageflip; +cvar_t *_vid_wait_override; +cvar_t *vid_config_x; +cvar_t *vid_config_y; +cvar_t *vid_stretch_by_2; +cvar_t *_windowed_mouse; +cvar_t *vid_fullscreen_mode; +cvar_t *vid_windowed_mode; +cvar_t *block_switch; +cvar_t *vid_window_x; +cvar_t *vid_window_y; + + +int vid_modenum = NO_MODE; +int vid_testingmode, vid_realmode; +double vid_testendtime; +int vid_default = MODE_WINDOWED; +static int windowed_default; + +modestate_t modestate = MS_UNINIT; + +byte vid_curpal[256 * 3]; + +unsigned short d_8to16table[256]; + +int mode; + +typedef struct { + modestate_t type; + int width; + int height; + int modenum; + int fullscreen; + char modedesc[13]; +} vmode_t; + +static vmode_t modelist[MAX_MODE_LIST]; +static int nummodes; + +int aPage; // Current active display page +int vPage; // Current visible display page +int waitVRT = true; // True to wait for retrace on flip + +static vmode_t badmode; + +static byte backingbuf[48 * 24]; + +void VID_MenuDraw (void); +void VID_MenuKey (int key); + +LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +void AppActivate (BOOL fActive, BOOL minimize); + +// video commands +int VID_NumModes (void); +vmode_t *VID_GetModePtr (int modenum); +void VID_TestMode_f (void); +void VID_ForceMode_f (void); +void VID_Minimize_f (void); +void VID_Fullscreen_f (void); +void VID_Windowed_f (void); +void VID_DescribeModes_f (void); +void VID_DescribeMode_f (void); +void VID_NumModes_f (void); +void VID_DescribeCurrentMode_f (void); +char *VID_GetExtModeDescription (int mode); +char *VID_GetModeDescription (int mode); +char *VID_GetModeDescription2 (int mode); +char *VID_GetModeDescriptionMemCheck (int mode); +void VID_CheckModedescFixup (int mode); + + +/* +================ +VID_RememberWindowPos +================ +*/ +static void __attribute__ ((used)) + VID_RememberWindowPos (void) +{ + RECT rect; + + if (GetWindowRect (hWndWinQuake, &rect)) { + if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && + (rect.top < GetSystemMetrics (SM_CYSCREEN)) && + (rect.right > 0) && (rect.bottom > 0)) { + Cvar_SetValue (vid_window_x, (float) rect.left); + Cvar_SetValue (vid_window_y, (float) rect.top); + } + } +} + + +/* +================ +VID_CheckWindowXY +================ +*/ +static void +VID_CheckWindowXY (void) +{ + if (((int) vid_window_x->value > (GetSystemMetrics (SM_CXSCREEN) - 160)) || + ((int) vid_window_y->value > (GetSystemMetrics (SM_CYSCREEN) - 120)) || + ((int) vid_window_x->value < 0) || ((int) vid_window_y->value < 0)) { + Cvar_SetValue (vid_window_x, 0.0); + Cvar_SetValue (vid_window_y, 0.0); + } +} + + +/* +================ +VID_UpdateWindowStatus +================ +*/ +void +VID_UpdateWindowStatus (int window_x, int window_y) +{ + window_rect.left = window_x; + window_rect.top = window_y; + window_rect.right = window_x + window_width; + window_rect.bottom = window_y + window_height; + window_center_x = (window_rect.left + window_rect.right) / 2; + window_center_y = (window_rect.top + window_rect.bottom) / 2; + IN_UpdateClipCursor (); +} + + +/* +================ +ClearAllStates +================ +*/ +static void +ClearAllStates (void) +{ + int i; + + // send an up event for each key, to make sure the server clears them all + for (i = 0; i < 256; i++) { + Key_Event (i, 0, false); + } + + Key_ClearStates (); + IN_ClearStates (); +} + + +/* +================ +VID_CheckAdequateMem +================ +*/ +static qboolean +VID_CheckAdequateMem (int width, int height) +{ + // there will always be enough ;) + return true; +} + + +static void +VID_InitModes (HINSTANCE hInstance) +{ + WNDCLASS wc; + HDC hdc; + +//FIXME hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2)); + + /* Register the frame class */ + wc.style = CS_OWNDC; wc.lpfnWndProc = (WNDPROC) MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hInstance = global_hInstance; + wc.hInstance = hInstance; wc.hIcon = 0; wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = 0; - wc.lpszClassName = "QuakeForge"; + wc.lpszClassName = "WinQuake"; if (!RegisterClass (&wc)) - Sys_Error ("Couldn't register window class (%lx)", GetLastError ()); + Sys_Error ("Couldn't register window class"); - VID_GetWindowSize (640, 480); + modelist[0].type = MS_WINDOWED; + modelist[0].width = 320; + modelist[0].height = 240; + strcpy (modelist[0].modedesc, "320x240"); + modelist[0].modenum = MODE_WINDOWED; + modelist[0].fullscreen = 0; - if (!vid_fullscreen->int_val) { - hdc = GetDC (NULL); + modelist[1].type = MS_WINDOWED; + modelist[1].width = 640; + modelist[1].height = 480; + strcpy (modelist[1].modedesc, "640x480"); + modelist[1].modenum = MODE_WINDOWED + 1; + modelist[1].fullscreen = 0; - if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) { - Sys_Error ("Can't run in non-RGB mode"); - } + modelist[2].type = MS_WINDOWED; + modelist[2].width = 800; + modelist[2].height = 600; + strcpy (modelist[2].modedesc, "800x600"); + modelist[2].modenum = MODE_WINDOWED + 2; + modelist[2].fullscreen = 0; - ReleaseDC (NULL, hdc); + // automatically stretch the default mode up if > 640x480 desktop + // resolution + hdc = GetDC (NULL); + + if ((GetDeviceCaps (hdc, HORZRES) > 800) + && !COM_CheckParm ("-noautostretch")) { + vid_default = MODE_WINDOWED + 2; + } else if ((GetDeviceCaps (hdc, HORZRES) > 640) + && !COM_CheckParm ("-noautostretch")) { + vid_default = MODE_WINDOWED + 1; } else { - if (COM_CheckParm ("-bpp")) { - bpp = atoi (com_argv[COM_CheckParm ("-bpp") + 1]); - } else { - bpp = 16; - } - vid_mode = 0; - do { - stat = EnumDisplaySettings (NULL, vid_mode, &win_gdevmode); + vid_default = MODE_WINDOWED; + } - if ((win_gdevmode.dmBitsPerPel == bpp) - && (win_gdevmode.dmPelsWidth == viddef.width) - && (win_gdevmode.dmPelsHeight == viddef.height)) { - win_gdevmode.dmFields = (DM_BITSPERPEL | DM_PELSWIDTH - | DM_PELSHEIGHT); + // always start at the lowest mode then switch to the higher one if + // selected + vid_default = MODE_WINDOWED; - if (ChangeDisplaySettings (&win_gdevmode, - CDS_TEST | CDS_FULLSCREEN) - == DISP_CHANGE_SUCCESSFUL) { - break; + windowed_default = vid_default; + ReleaseDC (NULL, hdc); + nummodes = 3; // reserve space for windowed mode +} + + +/* +================= +VID_GetDisplayModes +================= +*/ +static void +VID_GetDisplayModes (void) +{ + DEVMODE devmode; + int i, modenum, existingmode, originalnummodes, lowestres; + BOOL stat; + + // enumerate > 8 bpp modes + originalnummodes = nummodes; + modenum = 0; + lowestres = 99999; + + do { + stat = EnumDisplaySettings (NULL, modenum, &devmode); + + if ((devmode.dmPelsWidth <= MAXWIDTH) + && (devmode.dmPelsHeight <= MAXHEIGHT) + && (devmode.dmPelsWidth >= 320) + && (devmode.dmPelsHeight >= 240) + && (nummodes < MAX_MODE_LIST)) { + devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == + DISP_CHANGE_SUCCESSFUL) { + modelist[nummodes].type = MS_FULLDIB; + modelist[nummodes].width = devmode.dmPelsWidth; + modelist[nummodes].height = devmode.dmPelsHeight; + modelist[nummodes].modenum = 0; + modelist[nummodes].fullscreen = 1; + sprintf (modelist[nummodes].modedesc, "%dx%d", + (int) devmode.dmPelsWidth, + (int) devmode.dmPelsHeight); + + // see is the mode already there + // (same dimensions but different refresh rate) + for (i = originalnummodes, existingmode = 0; + i < nummodes; i++) { + if ((modelist[nummodes].width == modelist[i].width) + && (modelist[nummodes].height == modelist[i].height)) { + existingmode = 1; + break; + } + } + + // if it's not add it to the list + if (!existingmode) { + if (modelist[nummodes].width < lowestres) + lowestres = modelist[nummodes].width; + + nummodes++; } } + } - vid_mode++; - } while (stat); - if (!stat) - Sys_Error ("Couldn't get requested resolution (%i, %i, %i)", - viddef.width, viddef.height, bpp); + modenum++; + } while (stat); + + if (nummodes != originalnummodes) + vid_default = MODE_FULLSCREEN_DEFAULT; + else + Sys_Printf ("No fullscreen DIB modes found\n"); +} + + +static void +VID_DestroyWindow (void) +{ + if (modestate == MS_FULLDIB) + ChangeDisplaySettings (NULL, CDS_FULLSCREEN); + + VID_UnloadAllDrivers (); +} + + +static qboolean +VID_SetWindowedMode (int modenum) +{ + if (!windowed_mode_set) { + if (COM_CheckParm ("-resetwinpos")) { + Cvar_SetValue (vid_window_x, 0.0); + Cvar_SetValue (vid_window_y, 0.0); + } + + windowed_mode_set = true; } + VID_CheckModedescFixup (modenum); + VID_DestroyWindow (); + + WindowRect.top = WindowRect.left = 0; + WindowRect.right = modelist[modenum].width; + WindowRect.bottom = modelist[modenum].height; + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + WindowStyle = WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_SIZEBOX | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | + WS_CLIPCHILDREN | WS_THICKFRAME; + + // WindowStyle = WS_OVERLAPPEDWINDOW|WS_VISIBLE; + ExWindowStyle = 0; + AdjustWindowRectEx (&WindowRect, WindowStyle, FALSE, 0); + + // the first time we're called to set the mode, create the window we'll use + // for the rest of the session + if (!vid_mode_set) { + hWndWinQuake = CreateWindowEx (ExWindowStyle, + "WinQuake", + "WinQuake", + WindowStyle, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + NULL, NULL, global_hInstance, NULL); + + if (!hWndWinQuake) + Sys_Error ("Couldn't create DIB window"); + + // compatibility + mainwindow = hWndWinQuake; + + // done + vid_mode_set = true; + } else { + SetWindowLong (hWndWinQuake, GWL_STYLE, WindowStyle | WS_VISIBLE); + SetWindowLong (hWndWinQuake, GWL_EXSTYLE, ExWindowStyle); + } + + if (!SetWindowPos (hWndWinQuake, + NULL, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + SWP_NOCOPYBITS | SWP_NOZORDER | SWP_HIDEWINDOW)) { + Sys_Error ("Couldn't resize DIB window"); + } + + if (hide_window) + return true; + + // position and show the DIB window + VID_CheckWindowXY (); + SetWindowPos (hWndWinQuake, NULL, (int) vid_window_x->value, + (int) vid_window_y->value, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + + if (force_minimized) + ShowWindow (hWndWinQuake, SW_MINIMIZE); + else + ShowWindow (hWndWinQuake, SW_SHOWDEFAULT); + + UpdateWindow (hWndWinQuake); + modestate = MS_WINDOWED; + vid_fulldib_on_focus_mode = 0; + + viddef.numpages = 1; + viddef.maxwarpwidth = WARP_WIDTH; viddef.maxwarpheight = WARP_HEIGHT; - viddef.colormap8 = colormap; - viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; -#ifdef SPLASH_SCREEN - if(hwnd_dialog) - DestroyWindow (hwnd_dialog); + // viddef.maxlowwidth = LOW_WIDTH; + // viddef.maxlowheight = LOW_HEIGHT; + +// viddef.height = viddef.conheight = DIBHeight; +// viddef.width = viddef.conwidth = DIBWidth; + + viddef.height = viddef.conheight = DIBHeight; + viddef.width = viddef.conwidth = DIBWidth; +//FIXME? if (!yeahimconsoled){ +//FIXME? viddef.vconheight = DIBHeight; +//FIXME? viddef.vconwidth = DIBWidth; +//FIXME? } + SendMessage (hWndWinQuake, WM_SETICON, (WPARAM) TRUE, (LPARAM) hIcon); + SendMessage (hWndWinQuake, WM_SETICON, (WPARAM) FALSE, (LPARAM) hIcon); + + return true; +} + + +static qboolean +VID_SetFullDIBMode (int modenum) +{ + VID_DestroyWindow (); + + win_gdevmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + win_gdevmode.dmPelsWidth = modelist[modenum].width; + win_gdevmode.dmPelsHeight = modelist[modenum].height; + win_gdevmode.dmSize = sizeof (win_gdevmode); + + if (ChangeDisplaySettings (&win_gdevmode, CDS_FULLSCREEN) != + DISP_CHANGE_SUCCESSFUL) + Sys_Error ("Couldn't set fullscreen DIB mode"); + + modestate = MS_FULLDIB; + vid_fulldib_on_focus_mode = modenum; + WindowRect.top = WindowRect.left = 0; + + WindowRect.right = modelist[modenum].width; + WindowRect.bottom = modelist[modenum].height; + + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + ExWindowStyle = 0; + + AdjustWindowRectEx (&WindowRect, WindowStyle, FALSE, 0); + + SetWindowLong (hWndWinQuake, GWL_STYLE, WindowStyle | WS_VISIBLE); + SetWindowLong (hWndWinQuake, GWL_EXSTYLE, ExWindowStyle); + + if (!SetWindowPos (hWndWinQuake, + NULL, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + SWP_NOCOPYBITS | SWP_NOZORDER)) { + Sys_Error ("Couldn't resize DIB window"); + } + // position and show the DIB window + SetWindowPos (hWndWinQuake, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); + ShowWindow (hWndWinQuake, SW_SHOWDEFAULT); + UpdateWindow (hWndWinQuake); + + viddef.numpages = 1; + viddef.maxwarpwidth = WARP_WIDTH; + viddef.maxwarpheight = WARP_HEIGHT; + + // viddef.maxlowwidth = LOW_WIDTH; + // viddef.maxlowheight = LOW_HEIGHT; + +#ifdef SCALED2D + viddef.height = viddef.conheight = DIBHeight; + viddef.width = viddef.conwidth = DIBWidth; + // viddef.vconwidth = 320; + // viddef.vconheight = 200; +//FIXME? if (!yeahimconsoled){ +//FIXME? viddef.vconheight = DIBHeight; +//FIXME? viddef.vconwidth = DIBWidth; +//FIXME? } +#else + viddef.height = viddef.conheight = DIBHeight; + viddef.width = viddef.conwidth = DIBWidth; #endif - VID_SetMode (palette); + return true; +} - maindc = GetDC (mainwindow); - bSetupPixelFormat (maindc); +static int VID_SetMode (int modenum, byte *palette); - baseRC = qfwglCreateContext (maindc); - if (!baseRC) { - lasterror=GetLastError(); - if (maindc && mainwindow) - ReleaseDC (mainwindow, maindc); - Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\n" - "Make sure you are in 65535 color mode, and try running " - "with -window.\n" - "Error code: (%lx)", lasterror); +static void +VID_RestoreOldMode (int original_mode) +{ + static qboolean inerror = false; + + if (inerror) + return; + + in_mode_set = false; + inerror = true; + // make sure mode set happens (video mode changes) + vid_modenum = original_mode - 1; + + if (!VID_SetMode (original_mode, vid_curpal)) { + vid_modenum = MODE_WINDOWED - 1; + + if (!VID_SetMode (windowed_default, vid_curpal)) + Sys_Error ("Can't set any video mode"); } - if (!qfwglMakeCurrent (maindc, baseRC)) { - lasterror = GetLastError (); - if (baseRC) - qfwglDeleteContext (baseRC); - if (maindc && mainwindow) - ReleaseDC (mainwindow, maindc); - Sys_Error ("wglMakeCurrent failed (%lx)", lasterror); + inerror = false; +} + + +static void __attribute__ ((used)) + VID_SetDefaultMode (void) +{ + if (vid_initialized) + VID_SetMode (0, vid_curpal); + + IN_DeactivateMouse (); +} + + +static int +VID_SetMode (int modenum, byte *palette) +{ + int original_mode; // FIXME, temp; + qboolean stat; + MSG msg; + HDC hdc; + + while ((modenum >= nummodes) || (modenum < 0)) { + if (vid_modenum == NO_MODE) { + if (modenum == vid_default) { + modenum = windowed_default; + } else { + modenum = vid_default; + } + + Cvar_SetValue (vid_mode, (float) modenum); + } else { + Cvar_SetValue (vid_mode, (float) vid_modenum); + return 0; + } } - GL_Init (); + if (!force_mode_set && (modenum == vid_modenum)) + return true; - VID_InitGamma (palette); - viddef.set_palette (viddef.palette); + // so Con_Printfs don't mess us up by forcing vid and snd updates +//FIXME? temp = scr_disabled_for_loading; +//FIXME? scr_disabled_for_loading = true; + in_mode_set = true; +//FIXME CDAudio_Pause (); +//FIXME S_ClearBuffer (); - viddef.initialized = true; + if (vid_modenum == NO_MODE) + original_mode = windowed_default; + else + original_mode = vid_modenum; - win_canalttab = true; + // Set either the fullscreen or windowed mode + if (modelist[modenum].type == MS_WINDOWED) { + if (_windowed_mouse->value) { + stat = VID_SetWindowedMode (modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } else { + IN_DeactivateMouse (); + IN_ShowMouse (); + stat = VID_SetWindowedMode (modenum); + } + } else { + stat = VID_SetFullDIBMode (modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } - if (COM_CheckParm ("-nofullsbar")) - fullsbardraw = false; + // shutdown any old driver that was active + VID_UnloadAllDrivers (); + + // because we have set the background brush for the window to NULL (to + // avoid flickering when re-sizing the window on the desktop), we clear + // the window to black when created, otherwise it will be empty while + // Quake starts up. This also prevents a screen flash to while when + // switching drivers. it still flashes, but at least it's black now + hdc = GetDC (hWndWinQuake); + PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); + ReleaseDC (hWndWinQuake, hdc); + + // create the new driver + vid_usingddraw = false; + + // attempt to create a direct draw driver + if (vid_ddraw->value) + VID_CreateDDrawDriver (DIBWidth, DIBHeight, palette, &viddef.buffer, + &viddef.rowbytes); + + // create a gdi driver if directdraw failed or if we preferred not to use + // it + if (!vid_usingddraw) { + // because directdraw may have been partially created we must shut it + // down again first + VID_UnloadAllDrivers (); + + // now create the gdi driver + VID_CreateGDIDriver (DIBWidth, DIBHeight, palette, &viddef.buffer, + &viddef.rowbytes); + } + // if ddraw failed to come up we disable the cvar too + if (vid_ddraw->value && !vid_usingddraw) + Cvar_Set (vid_ddraw, "0"); + + // set the rest of the buffers we need (why not just use one single buffer + // instead of all this crap? oh well, it's Quake...) + viddef.direct = (byte *) viddef.buffer; + viddef.conbuffer = viddef.buffer; + + // more crap for the console + viddef.conrowbytes = viddef.rowbytes; + + window_width = viddef.width; + window_height = viddef.height; + + + VID_UpdateWindowStatus (0, 0); // FIXME right numbers? +//FIXME CDAudio_Resume (); +//FIXME? scr_disabled_for_loading = temp; + + if (!stat) { + VID_RestoreOldMode (original_mode); + return false; + } + + if (hide_window) + return true; + + // now we try to make sure we get the focus on the mode switch, because + // sometimes in some systems we don't. We grab the foreground, then + // finish setting up, pump all our messages, and sleep for a little while + // to let messages finish bouncing around the system, then we put + // ourselves at the top of the z order, then grab the foreground again, + // Who knows if it helps, but it probably doesn't hurt + if (!force_minimized) + SetForegroundWindow (hWndWinQuake); + + hdc = GetDC (NULL); + + if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) + vid_palettized = true; + else + vid_palettized = false; + + viddef.set_palette (palette); + ReleaseDC (NULL, hdc); + vid_modenum = modenum; + Cvar_SetValue (vid_mode, (float) vid_modenum); + + VID_InitBuffers (); + + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + Sleep (100); + + if (!force_minimized) { + SetWindowPos (hWndWinQuake, HWND_TOP, 0, 0, 0, 0, + SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | + SWP_NOCOPYBITS); + + SetForegroundWindow (hWndWinQuake); + } + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + Sys_Printf ("%s\n", VID_GetModeDescription (vid_modenum)); + + viddef.set_palette (palette); + + in_mode_set = false; + + viddef.recalc_refdef = 1; + +//FIXME SCR_StretchInit(); +//FIXME SCR_StretchRefresh(); +//FIXME SCR_CvarCheck(); + return true; +} + + +static void +VID_SetPalette (const byte *palette) +{ + int i; + const byte *pal = palette; + + if (!Minimized) { + if (vid_usingddraw) { + // incoming palette is 3 component + for (i = 0; i < 256; i++, pal += 3) { + PALETTEENTRY *p = (PALETTEENTRY *) & ddpal[i]; + + p->peRed = gammatable[pal[2]]; + p->peGreen = gammatable[pal[1]]; + p->peBlue = gammatable[pal[0]]; + p->peFlags = 255; + } + } else { + RGBQUAD colors[256]; + + if (hdcDIBSection) { + // incoming palette is 3 component + for (i = 0; i < 256; i++, pal += 3) { + PALETTEENTRY *p = (PALETTEENTRY *) & ddpal[i]; + + colors[i].rgbRed = gammatable[pal[0]]; + colors[i].rgbGreen = gammatable[pal[1]]; + colors[i].rgbBlue = gammatable[pal[2]]; + colors[i].rgbReserved = 0; + + p->peRed = gammatable[pal[2]]; + p->peGreen = gammatable[pal[1]]; + p->peBlue = gammatable[pal[0]]; + p->peFlags = 255; + } + + colors[0].rgbRed = 0; + colors[0].rgbGreen = 0; + colors[0].rgbBlue = 0; + colors[255].rgbRed = 0xff; + colors[255].rgbGreen = 0xff; + colors[255].rgbBlue = 0xff; + + if (SetDIBColorTable (hdcDIBSection, 0, 256, colors) == 0) { + Sys_Printf ("DIB_SetPalette() - SetDIBColorTable failed\n"); + } + } + } + } + + memcpy (vid_curpal, palette, sizeof (vid_curpal)); +} + + +#define CVAR_ORIGINAL CVAR_NONE // FIXME +void +VID_Init_Cvars (void) +{ + vid_ddraw = Cvar_Get ("vid_ddraw", "1", CVAR_ORIGINAL, 0, ""); + vid_mode = Cvar_Get ("vid_mode", "0", CVAR_ORIGINAL, 0, ""); + vid_wait = Cvar_Get ("vid_wait", "0", CVAR_ORIGINAL, 0, ""); + vid_nopageflip = + Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + _vid_wait_override = + Cvar_Get ("_vid_wait_override", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + _vid_default_mode = + Cvar_Get ("_vid_default_mode", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + _vid_default_mode_win = + Cvar_Get ("_vid_default_mode_win", "3", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + vid_config_x = + Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_config_y = + Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_stretch_by_2 = + Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + _windowed_mouse = + Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_fullscreen_mode = + Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + vid_windowed_mode = + Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + block_switch = + Cvar_Get ("block_switch", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_window_x = + Cvar_Get ("vid_window_x", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_window_y = + Cvar_Get ("vid_window_y", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); +} + +static void +win_choose_visual (void) +{ +} + +static void +win_create_context (void) +{ } void -VID_Init_Cvars () +VID_Init (byte *palette, byte *colormap) { + choose_visual = win_choose_visual; + create_context = win_create_context; + + R_LoadModule (wgl_load_gl, VID_SetPalette); + + viddef.numpages = 1; + viddef.colormap8 = colormap; + viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; + + VID_GetWindowSize (640, 480); + + VID_InitModes (global_hInstance); + VID_GetDisplayModes (); + choose_visual (); + + create_context (); + VID_InitGamma (palette); + + viddef.maxwarpwidth = WARP_WIDTH; + viddef.maxwarpheight = WARP_HEIGHT; + + // viddef.maxlowwidth = LOW_WIDTH; + // viddef.maxlowheight = LOW_HEIGHT; + vid_testingmode = 0; + + // if (COM_CheckParm("-startwindowed")) + { + startwindowed = 1; + vid_default = windowed_default; + } + +//FIXME? if (hwnd_dialog) +//FIXME? DestroyWindow (hwnd_dialog); + + // sound initialization has to go here, preceded by a windowed mode set, + // so there's a window for DirectSound to work with but we're not yet + // fullscreen so the "hardware already in use" dialog is visible if it + // gets displayed + // keep the window minimized until we're ready for the first real mode set + hide_window = true; + VID_SetMode (MODE_WINDOWED, palette); + hide_window = false; +//FIXME if (firsttime) S_Init (); + vid_initialized = true; + +//FIXME SCR_StretchInit(); + + force_mode_set = true; + VID_SetMode (vid_default, palette); + force_mode_set = false; + vid_realmode = vid_modenum; + viddef.set_palette (palette); + strcpy (badmode.modedesc, "Bad mode"); +} + +#if 0 +Cmd_AddCommand ("vid_testmode", VID_TestMode_f, ""); +Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, ""); +Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, ""); +Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, ""); +Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, ""); +Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f, ""); +Cmd_AddCommand ("vid_windowed", VID_Windowed_f, ""); +Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f, ""); +Cmd_AddCommand ("vid_minimize", VID_Minimize_f, ""); +#endif + + +void +VID_Shutdown (void) +{ + if (vid_initialized) { + if (modestate == MS_FULLDIB) + ChangeDisplaySettings (NULL, CDS_FULLSCREEN); + + PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM) hWndWinQuake, + (LPARAM) 0); + PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM) 0, (LPARAM) 0); + AppActivate (false, false); + + VID_DestroyWindow (); + +//FIXME? if (hwnd_dialog) DestroyWindow (hwnd_dialog); + if (hWndWinQuake) + DestroyWindow (hWndWinQuake); + + vid_testingmode = 0; + vid_initialized = 0; + } +} + + +/* +================ +FlipScreen +================ +*/ +static void +FlipScreen (vrect_t *rects) +{ + int numrects = 0; + + while (rects) { + if (vid_usingddraw) { + int x, y; + HRESULT hr = S_OK; + byte *src = NULL; + unsigned *dst = NULL; + + if (dd_BackBuffer) { + RECT TheRect; + RECT sRect, dRect; + DDSURFACEDESC ddsd; + + memset (&ddsd, 0, sizeof (ddsd)); + ddsd.dwSize = sizeof (DDSURFACEDESC); + + // lock the correct subrect + TheRect.left = rects->x; + TheRect.right = rects->x + rects->width; + TheRect.top = rects->y; + TheRect.bottom = rects->y + rects->height; + + if ((hr = + IDirectDrawSurface_Lock (dd_BackBuffer, &TheRect, &ddsd, + DDLOCK_WRITEONLY | + DDLOCK_SURFACEMEMORYPTR, + NULL)) == DDERR_WASSTILLDRAWING) + return; + + src = (byte *) vidbuf + rects->y * viddef.rowbytes + rects->x; + dst = (unsigned *) ddsd.lpSurface; + + // convert pitch to unsigned int addressable + ddsd.lPitch >>= 2; + + // because we created a 32 bit backbuffer we need to copy from + // the 8 bit memory buffer to it before flipping + if (!(rects->width & 15)) { + for (y = 0; y < rects->height; + y++, src += viddef.rowbytes, dst += ddsd.lPitch) { + byte *psrc = src; + unsigned *pdst = dst; + + for (x = 0; x < rects->width; + x += 16, psrc += 16, pdst += 16) { + pdst[0] = ddpal[psrc[0]]; + pdst[1] = ddpal[psrc[1]]; + pdst[2] = ddpal[psrc[2]]; + pdst[3] = ddpal[psrc[3]]; + + pdst[4] = ddpal[psrc[4]]; + pdst[5] = ddpal[psrc[5]]; + pdst[6] = ddpal[psrc[6]]; + pdst[7] = ddpal[psrc[7]]; + + pdst[8] = ddpal[psrc[8]]; + pdst[9] = ddpal[psrc[9]]; + pdst[10] = ddpal[psrc[10]]; + pdst[11] = ddpal[psrc[11]]; + + pdst[12] = ddpal[psrc[12]]; + pdst[13] = ddpal[psrc[13]]; + pdst[14] = ddpal[psrc[14]]; + pdst[15] = ddpal[psrc[15]]; + } + } + } else if (!(rects->width % 10)) { + for (y = 0; y < rects->height; + y++, src += viddef.rowbytes, dst += ddsd.lPitch) { + byte *psrc = src; + unsigned *pdst = dst; + + for (x = 0; x < rects->width; + x += 10, psrc += 10, pdst += 10) { + pdst[0] = ddpal[psrc[0]]; + pdst[1] = ddpal[psrc[1]]; + pdst[2] = ddpal[psrc[2]]; + pdst[3] = ddpal[psrc[3]]; + pdst[4] = ddpal[psrc[4]]; + + pdst[5] = ddpal[psrc[5]]; + pdst[6] = ddpal[psrc[6]]; + pdst[7] = ddpal[psrc[7]]; + pdst[8] = ddpal[psrc[8]]; + pdst[9] = ddpal[psrc[9]]; + } + } + } else if (!(rects->width & 7)) { + for (y = 0; y < rects->height; + y++, src += viddef.rowbytes, dst += ddsd.lPitch) { + byte *psrc = src; + unsigned *pdst = dst; + + for (x = 0; x < rects->width; + x += 8, psrc += 8, pdst += 8) { + pdst[0] = ddpal[psrc[0]]; + pdst[1] = ddpal[psrc[1]]; + pdst[2] = ddpal[psrc[2]]; + pdst[3] = ddpal[psrc[3]]; + + pdst[4] = ddpal[psrc[4]]; + pdst[5] = ddpal[psrc[5]]; + pdst[6] = ddpal[psrc[6]]; + pdst[7] = ddpal[psrc[7]]; + } + } + } else if (!(rects->width % 5)) { + for (y = 0; y < rects->height; + y++, src += viddef.rowbytes, dst += ddsd.lPitch) { + byte *psrc = src; + unsigned *pdst = dst; + + for (x = 0; x < rects->width; + x += 5, psrc += 5, pdst += 5) { + pdst[0] = ddpal[psrc[0]]; + pdst[1] = ddpal[psrc[1]]; + pdst[2] = ddpal[psrc[2]]; + pdst[3] = ddpal[psrc[3]]; + pdst[4] = ddpal[psrc[4]]; + } + } + } else if (!(rects->width & 3)) { + for (y = 0; y < rects->height; + y++, src += viddef.rowbytes, dst += ddsd.lPitch) { + byte *psrc = src; + unsigned *pdst = dst; + + for (x = 0; x < rects->width; + x += 4, psrc += 4, pdst += 4) { + pdst[0] = ddpal[psrc[0]]; + pdst[1] = ddpal[psrc[1]]; + pdst[2] = ddpal[psrc[2]]; + pdst[3] = ddpal[psrc[3]]; + } + } + } else { + for (y = 0; y < rects->height; + y++, src += viddef.rowbytes, dst += ddsd.lPitch) { + for (x = 0; x < rects->width; x++) { + dst[x] = ddpal[src[x]]; + } + } + } + + IDirectDrawSurface_Unlock (dd_BackBuffer, NULL); + + // correctly offset source + sRect.left = SrcRect.left + rects->x; + sRect.right = SrcRect.left + rects->x + rects->width; + sRect.top = SrcRect.top + rects->y; + sRect.bottom = SrcRect.top + rects->y + rects->height; + + // correctly offset dest + dRect.left = DstRect.left + rects->x; + dRect.right = DstRect.left + rects->x + rects->width; + dRect.top = DstRect.top + rects->y; + dRect.bottom = DstRect.top + rects->y + rects->height; + + // copy to front buffer + IDirectDrawSurface_Blt (dd_FrontBuffer, &dRect, dd_BackBuffer, + &sRect, 0, NULL); + } + } else if (hdcDIBSection) { + BitBlt (hdcGDI, rects->x, rects->y, + rects->x + rects->width, rects->y + rects->height, + hdcDIBSection, rects->x, rects->y, SRCCOPY); + } + + numrects++; + rects = rects->next; + } +} + + +void +D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) +{ + int i, j, reps, repshift; + vrect_t rect; + + if (!vid_initialized) + return; + + if (viddef.aspect > 1.5) { + reps = 2; + repshift = 1; + } else { + reps = 1; + repshift = 0; + } + + if (!viddef.direct) + return; + + for (i = 0; i < (height << repshift); i += reps) { + for (j = 0; j < reps; j++) { + memcpy (&backingbuf[(i + j) * 24], + viddef.direct + x + ((y << repshift) + i + + j) * viddef.rowbytes, width); + + memcpy (viddef.direct + x + + ((y << repshift) + i + j) * viddef.rowbytes, + &pbitmap[(i >> repshift) * width], width); + } + } + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height << repshift; + rect.next = NULL; + + FlipScreen (&rect); +} + + +void +D_EndDirectRect (int x, int y, int width, int height) +{ + int i, j, reps, repshift; + vrect_t rect; + + if (!vid_initialized) + return; + + if (viddef.aspect > 1.5) { + reps = 2; + repshift = 1; + } else { + reps = 1; + repshift = 0; + } + + if (!viddef.direct) + return; + + for (i = 0; i < (height << repshift); i += reps) { + for (j = 0; j < reps; j++) { + memcpy (viddef.direct + x + + ((y << repshift) + i + j) * viddef.rowbytes, + &backingbuf[(i + j) * 24], width); + } + } + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height << repshift; + rect.next = NULL; + + FlipScreen (&rect); +} + + +void +VID_Update (vrect_t *rects) +{ + vrect_t rect; + RECT trect; + + if (!vid_palettized && palette_changed) { + palette_changed = false; + rect.x = 0; + rect.y = 0; + rect.width = viddef.width; + rect.height = viddef.height; + rect.next = NULL; + rects = ▭ + } + + if (firstupdate) { + if (modestate == MS_WINDOWED) { + GetWindowRect (hWndWinQuake, &trect); + + if ((trect.left != (int) vid_window_x->value) || + (trect.top != (int) vid_window_y->value)) { + if (COM_CheckParm ("-resetwinpos")) { + Cvar_SetValue (vid_window_x, 0.0); + Cvar_SetValue (vid_window_y, 0.0); + } + + VID_CheckWindowXY (); + SetWindowPos (hWndWinQuake, NULL, (int) vid_window_x->value, + (int) vid_window_y->value, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | + SWP_DRAWFRAME); + } + } + + if ((_vid_default_mode_win->value != vid_default) && + (!startwindowed + || (_vid_default_mode_win->value < MODE_FULLSCREEN_DEFAULT))) { + firstupdate = 0; + + if (COM_CheckParm ("-resetwinpos")) { + Cvar_SetValue (vid_window_x, 0.0); + Cvar_SetValue (vid_window_y, 0.0); + } + + if ((_vid_default_mode_win->value < 0) || + (_vid_default_mode_win->value >= nummodes)) { + Cvar_SetValue (_vid_default_mode_win, windowed_default); + } + + Cvar_SetValue (vid_mode, _vid_default_mode_win->value); + } + } + // We've drawn the frame; copy it to the screen + FlipScreen (rects); + + // check for a driver change + if ((vid_ddraw->value && !vid_usingddraw) + || (!vid_ddraw->value && vid_usingddraw)) { + // reset the mode + force_mode_set = true; + VID_SetMode ((int) vid_mode->value, vid_curpal); + force_mode_set = false; + + // store back + if (vid_usingddraw) + Sys_Printf ("loaded DirectDraw driver\n"); + else + Sys_Printf ("loaded GDI driver\n"); + } + + if (vid_testingmode) { + if (Sys_DoubleTime () >= vid_testendtime) { + VID_SetMode (vid_realmode, vid_curpal); + vid_testingmode = 0; + } + } else { + if ((int) vid_mode->value != vid_realmode) { + VID_SetMode ((int) vid_mode->value, vid_curpal); + Cvar_SetValue (vid_mode, (float) vid_modenum); + // so if mode set fails, we don't keep on + // trying to set that mode + vid_realmode = vid_modenum; + } + } + + // handle the mouse state when windowed if that's changed + if (modestate == MS_WINDOWED) { + if ((int) _windowed_mouse->value != windowed_mouse) { + if (_windowed_mouse->value) { + IN_ActivateMouse (); + IN_HideMouse (); + } else { + IN_DeactivateMouse (); + IN_ShowMouse (); + } + + windowed_mouse = (int) _windowed_mouse->value; + } + } +} + + +//========================================================================== + + +/* +================ +VID_HandlePause +================ +*/ +static void __attribute__ ((used)) + VID_HandlePause (qboolean pause) +{ + if ((modestate == MS_WINDOWED) && _windowed_mouse->value) { + if (pause) { + IN_DeactivateMouse (); + IN_ShowMouse (); + } else { + IN_ActivateMouse (); + IN_HideMouse (); + } + } +} + + +/* +=================================================================== + +MAIN WINDOW + +=================================================================== +*/ + +typedef struct { + int modenum; + char *desc; + int iscur; + int width; +} modedesc_t; + +#define MAX_COLUMN_SIZE 5 +#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6) +#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) + +//static modedesc_t modedescs[MAX_MODEDESCS]; + +/* +================= +VID_NumModes +================= +*/ +int +VID_NumModes (void) +{ + return nummodes; +} + + +/* +================= +VID_GetModePtr +================= +*/ +vmode_t * +VID_GetModePtr (int modenum) +{ + if ((modenum >= 0) && (modenum < nummodes)) + return &modelist[modenum]; + else + return &badmode; +} + + +/* +================= +VID_CheckModedescFixup +================= +*/ +void +VID_CheckModedescFixup (int mode) +{ +} + + +/* +================= +VID_GetModeDescriptionMemCheck +================= +*/ +char * +VID_GetModeDescriptionMemCheck (int mode) +{ + char *pinfo; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + pv = VID_GetModePtr (mode); + pinfo = pv->modedesc; + + if (VID_CheckAdequateMem (pv->width, pv->height)) { + return pinfo; + } else { + return NULL; + } +} + + +/* +================= +VID_GetModeDescription +================= +*/ +char * +VID_GetModeDescription (int mode) +{ + char *pinfo; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + pv = VID_GetModePtr (mode); + pinfo = pv->modedesc; + return pinfo; +} + + +/* +================= +VID_GetModeDescription2 + +Tacks on "windowed" or "fullscreen" +================= +*/ +char * +VID_GetModeDescription2 (int mode) +{ + static char pinfo[40]; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + pv = VID_GetModePtr (mode); + + if (modelist[mode].type == MS_FULLSCREEN) { + sprintf (pinfo, "%s fullscreen", pv->modedesc); + } else if (modelist[mode].type == MS_FULLDIB) { + sprintf (pinfo, "%s fullscreen", pv->modedesc); + } else { + sprintf (pinfo, "%s windowed", pv->modedesc); + } + + return pinfo; +} + + +// KJB: Added this to return the mode driver name in description for console + +char * +VID_GetExtModeDescription (int mode) +{ + static char pinfo[40]; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + pv = VID_GetModePtr (mode); + + if (modelist[mode].type == MS_FULLDIB) { + sprintf (pinfo, "%s fullscreen", pv->modedesc); + } else { + sprintf (pinfo, "%s windowed", pv->modedesc); + } + + return pinfo; +} + + +/* +================= +VID_DescribeCurrentMode_f +================= +*/ +void +VID_DescribeCurrentMode_f (void) +{ + Sys_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); +} + + +/* +================= +VID_NumModes_f +================= +*/ +void +VID_NumModes_f (void) +{ + if (nummodes == 1) + Sys_Printf ("%d video mode is available\n", nummodes); + else + Sys_Printf ("%d video modes are available\n", nummodes); +} + + +/* +================= +VID_DescribeMode_f +================= +*/ +void +VID_DescribeMode_f (void) +{ + int modenum; + + modenum = atoi (Cmd_Argv (1)); + Sys_Printf ("%s\n", VID_GetExtModeDescription (modenum)); +} + + +/* +================= +VID_DescribeModes_f +================= +*/ +void +VID_DescribeModes_f (void) +{ + int i, lnummodes; + char *pinfo; + qboolean na; + vmode_t *pv; + + na = false; + lnummodes = VID_NumModes (); + + for (i = 0; i < lnummodes; i++) { + pv = VID_GetModePtr (i); + pinfo = VID_GetExtModeDescription (i); + + if (VID_CheckAdequateMem (pv->width, pv->height)) { + Sys_Printf ("%2d: %s\n", i, pinfo); + } else { + Sys_Printf ("**: %s\n", pinfo); + na = true; + } + } + + if (na) { + Sys_Printf ("\n[**: not enough system RAM for mode]\n"); + } +} + + +/* +================= +VID_TestMode_f +================= +*/ +void +VID_TestMode_f (void) +{ + int modenum; + double testduration; + + if (!vid_testingmode) { + modenum = atoi (Cmd_Argv (1)); + + if (VID_SetMode (modenum, vid_curpal)) { + vid_testingmode = 1; + testduration = atof (Cmd_Argv (2)); + + if (testduration == 0) + testduration = 5.0; + + vid_testendtime = Sys_DoubleTime () + testduration; + } + } +} + + +/* +================= +VID_Windowed_f +================= +*/ +void +VID_Windowed_f (void) +{ + VID_SetMode ((int) vid_windowed_mode->value, vid_curpal); +} + + +/* +================= +VID_Fullscreen_f +================= +*/ +void +VID_Fullscreen_f (void) +{ + VID_SetMode ((int) vid_fullscreen_mode->value, vid_curpal); +} + + +/* +================= +VID_Minimize_f +================= +*/ +void +VID_Minimize_f (void) +{ + // we only support minimizing windows; if you're fullscreen, + // switch to windowed first + if (modestate == MS_WINDOWED) + ShowWindow (hWndWinQuake, SW_MINIMIZE); +} + + + +/* +================= +VID_ForceMode_f +================= +*/ +void +VID_ForceMode_f (void) +{ + int modenum; + + if (!vid_testingmode) { + modenum = atoi (Cmd_Argv (1)); + force_mode_set = 1; + VID_SetMode (modenum, vid_curpal); + force_mode_set = 0; + } } void VID_SetCaption (const char *text) { if (text && *text) { - char *temp = strdup (text); + char *temp = strdup (text); - SetWindowText (mainwindow, - (LPSTR) va ("%s: %s", PACKAGE_STRING, temp)); + SetWindowText (mainwindow, (LPSTR) va ("%s: %s", PACKAGE_STRING, temp)); free (temp); } else { SetWindowText (mainwindow, (LPSTR) va ("%s", PACKAGE_STRING)); @@ -604,8 +2100,8 @@ static WORD currentgammaramps[3][256]; qboolean VID_SetGamma (double gamma) { - int i; - HDC hdc = GetDC (NULL); + int i; + HDC hdc = GetDC (NULL); for (i = 0; i < 256; i++) { currentgammaramps[2][i] = currentgammaramps[1][i] = @@ -617,27 +2113,11 @@ VID_SetGamma (double gamma) return i; } -void -VID_LockBuffer (void) -{ -} - -void -VID_UnlockBuffer (void) -{ -} - -void -VID_Update (vrect_t *rects) -{ - //FIXME sw -} - #if 0 static void VID_SaveGamma (void) { - HDC hdc = GetDC (NULL); + HDC hdc = GetDC (NULL); GetDeviceGammaRamp (hdc, &systemgammaramps[0][0]); ReleaseDC (NULL, hdc); @@ -646,7 +2126,7 @@ VID_SaveGamma (void) static void VID_RestoreGamma (void) { - HDC hdc = GetDC (NULL); + HDC hdc = GetDC (NULL); SetDeviceGammaRamp (hdc, &systemgammaramps[0][0]); ReleaseDC (NULL, hdc); From a35f6cadf77c31f6045ce3815340aee60a07c929 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Jan 2013 16:36:00 +0900 Subject: [PATCH 0015/3664] Use the cvar's int_val rather than coverting its value. Let the cvar system to its job :) --- libs/video/targets/vid_win.c | 56 ++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 9fde73bf5..45b0e79e4 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -584,9 +584,9 @@ VID_CheckWindowXY static void VID_CheckWindowXY (void) { - if (((int) vid_window_x->value > (GetSystemMetrics (SM_CXSCREEN) - 160)) || - ((int) vid_window_y->value > (GetSystemMetrics (SM_CYSCREEN) - 120)) || - ((int) vid_window_x->value < 0) || ((int) vid_window_y->value < 0)) { + if ((vid_window_x->int_val > (GetSystemMetrics (SM_CXSCREEN) - 160)) || + (vid_window_y->int_val > (GetSystemMetrics (SM_CYSCREEN) - 120)) || + (vid_window_x->int_val < 0) || (vid_window_y->int_val < 0)) { Cvar_SetValue (vid_window_x, 0.0); Cvar_SetValue (vid_window_y, 0.0); } @@ -859,8 +859,8 @@ VID_SetWindowedMode (int modenum) // position and show the DIB window VID_CheckWindowXY (); - SetWindowPos (hWndWinQuake, NULL, (int) vid_window_x->value, - (int) vid_window_y->value, 0, 0, + SetWindowPos (hWndWinQuake, NULL, vid_window_x->int_val, + vid_window_y->int_val, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); if (force_minimized) @@ -1042,7 +1042,7 @@ VID_SetMode (int modenum, byte *palette) // Set either the fullscreen or windowed mode if (modelist[modenum].type == MS_WINDOWED) { - if (_windowed_mouse->value) { + if (_windowed_mouse->int_val) { stat = VID_SetWindowedMode (modenum); IN_ActivateMouse (); IN_HideMouse (); @@ -1073,7 +1073,7 @@ VID_SetMode (int modenum, byte *palette) vid_usingddraw = false; // attempt to create a direct draw driver - if (vid_ddraw->value) + if (vid_ddraw->int_val) VID_CreateDDrawDriver (DIBWidth, DIBHeight, palette, &viddef.buffer, &viddef.rowbytes); @@ -1089,7 +1089,7 @@ VID_SetMode (int modenum, byte *palette) &viddef.rowbytes); } // if ddraw failed to come up we disable the cvar too - if (vid_ddraw->value && !vid_usingddraw) + if (vid_ddraw->int_val && !vid_usingddraw) Cvar_Set (vid_ddraw, "0"); // set the rest of the buffers we need (why not just use one single buffer @@ -1653,24 +1653,24 @@ VID_Update (vrect_t *rects) if (modestate == MS_WINDOWED) { GetWindowRect (hWndWinQuake, &trect); - if ((trect.left != (int) vid_window_x->value) || - (trect.top != (int) vid_window_y->value)) { + if ((trect.left != vid_window_x->int_val) || + (trect.top != vid_window_y->int_val)) { if (COM_CheckParm ("-resetwinpos")) { Cvar_SetValue (vid_window_x, 0.0); Cvar_SetValue (vid_window_y, 0.0); } VID_CheckWindowXY (); - SetWindowPos (hWndWinQuake, NULL, (int) vid_window_x->value, - (int) vid_window_y->value, 0, 0, + SetWindowPos (hWndWinQuake, NULL, vid_window_x->int_val, + vid_window_y->int_val, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); } } - if ((_vid_default_mode_win->value != vid_default) && + if ((_vid_default_mode_win->int_val != vid_default) && (!startwindowed - || (_vid_default_mode_win->value < MODE_FULLSCREEN_DEFAULT))) { + || (_vid_default_mode_win->int_val < MODE_FULLSCREEN_DEFAULT))) { firstupdate = 0; if (COM_CheckParm ("-resetwinpos")) { @@ -1678,23 +1678,23 @@ VID_Update (vrect_t *rects) Cvar_SetValue (vid_window_y, 0.0); } - if ((_vid_default_mode_win->value < 0) || - (_vid_default_mode_win->value >= nummodes)) { + if ((_vid_default_mode_win->int_val < 0) || + (_vid_default_mode_win->int_val >= nummodes)) { Cvar_SetValue (_vid_default_mode_win, windowed_default); } - Cvar_SetValue (vid_mode, _vid_default_mode_win->value); + Cvar_SetValue (vid_mode, _vid_default_mode_win->int_val); } } // We've drawn the frame; copy it to the screen FlipScreen (rects); // check for a driver change - if ((vid_ddraw->value && !vid_usingddraw) - || (!vid_ddraw->value && vid_usingddraw)) { + if ((vid_ddraw->int_val && !vid_usingddraw) + || (!vid_ddraw->int_val && vid_usingddraw)) { // reset the mode force_mode_set = true; - VID_SetMode ((int) vid_mode->value, vid_curpal); + VID_SetMode (vid_mode->int_val, vid_curpal); force_mode_set = false; // store back @@ -1710,8 +1710,8 @@ VID_Update (vrect_t *rects) vid_testingmode = 0; } } else { - if ((int) vid_mode->value != vid_realmode) { - VID_SetMode ((int) vid_mode->value, vid_curpal); + if (vid_mode->int_val != vid_realmode) { + VID_SetMode (vid_mode->int_val, vid_curpal); Cvar_SetValue (vid_mode, (float) vid_modenum); // so if mode set fails, we don't keep on // trying to set that mode @@ -1721,8 +1721,8 @@ VID_Update (vrect_t *rects) // handle the mouse state when windowed if that's changed if (modestate == MS_WINDOWED) { - if ((int) _windowed_mouse->value != windowed_mouse) { - if (_windowed_mouse->value) { + if (_windowed_mouse->int_val != windowed_mouse) { + if (_windowed_mouse->int_val) { IN_ActivateMouse (); IN_HideMouse (); } else { @@ -1730,7 +1730,7 @@ VID_Update (vrect_t *rects) IN_ShowMouse (); } - windowed_mouse = (int) _windowed_mouse->value; + windowed_mouse = _windowed_mouse->int_val; } } } @@ -1747,7 +1747,7 @@ VID_HandlePause static void __attribute__ ((used)) VID_HandlePause (qboolean pause) { - if ((modestate == MS_WINDOWED) && _windowed_mouse->value) { + if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val) { if (pause) { IN_DeactivateMouse (); IN_ShowMouse (); @@ -2031,7 +2031,7 @@ VID_Windowed_f void VID_Windowed_f (void) { - VID_SetMode ((int) vid_windowed_mode->value, vid_curpal); + VID_SetMode (vid_windowed_mode->int_val, vid_curpal); } @@ -2043,7 +2043,7 @@ VID_Fullscreen_f void VID_Fullscreen_f (void) { - VID_SetMode ((int) vid_fullscreen_mode->value, vid_curpal); + VID_SetMode (vid_fullscreen_mode->int_val, vid_curpal); } From c56a075199fd5e588f6cdeb50cc53b458272ce8e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Jan 2013 12:53:58 +0900 Subject: [PATCH 0016/3664] Get MH's vid_win.c mostly working for sw and sw32. There are still a great many problems, but pixels get to the screen in the right place (for windowed mode, anyway). --- libs/video/targets/vid.c | 7 +++ libs/video/targets/vid_win.c | 86 ++++++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 32 deletions(-) diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 34176bc3c..a398edd08 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -44,6 +44,7 @@ #include "QF/va.h" #include "compat.h" +#include "d_iface.h" #include "vid_internal.h" /* Software and hardware gamma support */ @@ -133,6 +134,12 @@ VID_GetWindowSize (int def_w, int def_h) Cvar_SetFlags (vid_width, vid_width->flags | CVAR_ROM); Cvar_SetFlags (vid_height, vid_height->flags | CVAR_ROM); + viddef.maxwarpwidth = WARP_WIDTH; + viddef.maxwarpheight = WARP_HEIGHT; + + // viddef.maxlowwidth = LOW_WIDTH; + // viddef.maxlowheight = LOW_HEIGHT; + viddef.width = vid_width->int_val; viddef.height = vid_height->int_val; diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 45b0e79e4..28a1b695d 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -59,8 +59,7 @@ qboolean win_canalttab = false; // main application window HWND hWndWinQuake = NULL; HDC maindc; - -byte gammatable[256]; +HGLRC baseRC; //FIXME?int yeahimconsoled; @@ -130,10 +129,46 @@ GL_EndRendering (void) } } +static void +wgl_choose_visual (void) +{ +} + +static void +wgl_create_context (void) +{ + DWORD lasterror; + + Sys_Printf ("maindc: %p\n", maindc); + baseRC = qfwglCreateContext (maindc); + if (!baseRC) { + lasterror=GetLastError(); + if (maindc && mainwindow) + ReleaseDC (mainwindow, maindc); + Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\n" + "Make sure you are in 65535 color mode, and try running " + "with -window.\n" + "Error code: (%lx)", lasterror); + } + + if (!qfwglMakeCurrent (maindc, baseRC)) { + lasterror = GetLastError (); + if (baseRC) + qfwglDeleteContext (baseRC); + if (maindc && mainwindow) + ReleaseDC (mainwindow, maindc); + Sys_Error ("wglMakeCurrent failed (%lx)", lasterror); + } + + viddef.init_gl (); +} static void wgl_load_gl (void) { + choose_visual = wgl_choose_visual; + create_context = wgl_create_context; + viddef.get_proc_address = QFGL_ProcAddress; viddef.end_rendering = GL_EndRendering; @@ -561,7 +596,7 @@ VID_RememberWindowPos ================ */ static void __attribute__ ((used)) - VID_RememberWindowPos (void) +VID_RememberWindowPos (void) { RECT rect; @@ -874,12 +909,6 @@ VID_SetWindowedMode (int modenum) viddef.numpages = 1; - viddef.maxwarpwidth = WARP_WIDTH; - viddef.maxwarpheight = WARP_HEIGHT; - - // viddef.maxlowwidth = LOW_WIDTH; - // viddef.maxlowheight = LOW_HEIGHT; - // viddef.height = viddef.conheight = DIBHeight; // viddef.width = viddef.conwidth = DIBWidth; @@ -943,11 +972,6 @@ VID_SetFullDIBMode (int modenum) UpdateWindow (hWndWinQuake); viddef.numpages = 1; - viddef.maxwarpwidth = WARP_WIDTH; - viddef.maxwarpheight = WARP_HEIGHT; - - // viddef.maxlowwidth = LOW_WIDTH; - // viddef.maxlowheight = LOW_HEIGHT; #ifdef SCALED2D viddef.height = viddef.conheight = DIBHeight; @@ -993,7 +1017,7 @@ VID_RestoreOldMode (int original_mode) static void __attribute__ ((used)) - VID_SetDefaultMode (void) +VID_SetDefaultMode (void) { if (vid_initialized) VID_SetMode (0, vid_curpal); @@ -1063,7 +1087,7 @@ VID_SetMode (int modenum, byte *palette) // because we have set the background brush for the window to NULL (to // avoid flickering when re-sizing the window on the desktop), we clear // the window to black when created, otherwise it will be empty while - // Quake starts up. This also prevents a screen flash to while when + // Quake starts up. This also prevents a screen flash to white when // switching drivers. it still flashes, but at least it's black now hdc = GetDC (hWndWinQuake); PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); @@ -1183,9 +1207,9 @@ VID_SetPalette (const byte *palette) for (i = 0; i < 256; i++, pal += 3) { PALETTEENTRY *p = (PALETTEENTRY *) & ddpal[i]; - p->peRed = gammatable[pal[2]]; - p->peGreen = gammatable[pal[1]]; - p->peBlue = gammatable[pal[0]]; + p->peRed = viddef.gammatable[pal[2]]; + p->peGreen = viddef.gammatable[pal[1]]; + p->peBlue = viddef.gammatable[pal[0]]; p->peFlags = 255; } } else { @@ -1196,14 +1220,14 @@ VID_SetPalette (const byte *palette) for (i = 0; i < 256; i++, pal += 3) { PALETTEENTRY *p = (PALETTEENTRY *) & ddpal[i]; - colors[i].rgbRed = gammatable[pal[0]]; - colors[i].rgbGreen = gammatable[pal[1]]; - colors[i].rgbBlue = gammatable[pal[2]]; + colors[i].rgbRed = viddef.gammatable[pal[0]]; + colors[i].rgbGreen = viddef.gammatable[pal[1]]; + colors[i].rgbBlue = viddef.gammatable[pal[2]]; colors[i].rgbReserved = 0; - p->peRed = gammatable[pal[2]]; - p->peGreen = gammatable[pal[1]]; - p->peBlue = gammatable[pal[0]]; + p->peRed = viddef.gammatable[pal[2]]; + p->peGreen = viddef.gammatable[pal[1]]; + p->peBlue = viddef.gammatable[pal[0]]; p->peFlags = 255; } @@ -1229,6 +1253,8 @@ VID_SetPalette (const byte *palette) void VID_Init_Cvars (void) { + gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, + "The OpenGL library to use. (path optional)"); vid_ddraw = Cvar_Get ("vid_ddraw", "1", CVAR_ORIGINAL, 0, ""); vid_mode = Cvar_Get ("vid_mode", "0", CVAR_ORIGINAL, 0, ""); vid_wait = Cvar_Get ("vid_wait", "0", CVAR_ORIGINAL, 0, ""); @@ -1294,13 +1320,10 @@ VID_Init (byte *palette, byte *colormap) choose_visual (); create_context (); + VID_InitGamma (palette); + viddef.set_palette (palette); - viddef.maxwarpwidth = WARP_WIDTH; - viddef.maxwarpheight = WARP_HEIGHT; - - // viddef.maxlowwidth = LOW_WIDTH; - // viddef.maxlowheight = LOW_HEIGHT; vid_testingmode = 0; // if (COM_CheckParm("-startwindowed")) @@ -1329,7 +1352,6 @@ VID_Init (byte *palette, byte *colormap) VID_SetMode (vid_default, palette); force_mode_set = false; vid_realmode = vid_modenum; - viddef.set_palette (palette); strcpy (badmode.modedesc, "Bad mode"); } @@ -1745,7 +1767,7 @@ VID_HandlePause ================ */ static void __attribute__ ((used)) - VID_HandlePause (qboolean pause) +VID_HandlePause (qboolean pause) { if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val) { if (pause) { From 1740e14d2abb36bc0bf2ec60d393d4ca2e74b071 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Jan 2013 19:57:40 +0900 Subject: [PATCH 0017/3664] Do a const-correctness run on palettes. --- include/QF/image.h | 11 ++++++----- include/QF/pcx.h | 6 +++--- include/QF/vid.h | 2 +- include/vid_internal.h | 2 +- libs/image/pcx.c | 13 +++++++------ libs/models/gl_skin.c | 3 ++- libs/models/glsl_skin.c | 6 +++--- libs/video/renderer/sw/draw.c | 3 ++- libs/video/renderer/sw32/draw.c | 3 ++- libs/video/targets/vid.c | 2 +- tools/wad/script.c | 2 +- 11 files changed, 29 insertions(+), 24 deletions(-) diff --git a/include/QF/image.h b/include/QF/image.h index 33c69c120..47820c856 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -29,15 +29,16 @@ #ifndef __QF_image_h #define __QF_image_h +#include "QF/qtypes.h" #include "QF/quakeio.h" // could not use texture_t as that is used for models. typedef struct tex_s { - int width; - int height; - int format; - unsigned char *palette; // 0 = 32 bit, otherwise 8 - unsigned char data[4]; // variable length + int width; + int height; + int format; + const byte *palette; // 0 = 32 bit, otherwise 8 + byte data[4]; // variable length } tex_t; #define tex_palette 0 diff --git a/include/QF/pcx.h b/include/QF/pcx.h index 6bfeb03e5..641df359c 100644 --- a/include/QF/pcx.h +++ b/include/QF/pcx.h @@ -62,8 +62,8 @@ typedef struct \return A pointer to the newly-coded PCX data. \warning Uses Hunk_TempAlloc() to allocate the output PCX content. */ -pcx_t *EncodePCX (byte *data, int width, int height, int rowbytes, - byte *palette, qboolean flip, int *length); +pcx_t *EncodePCX (const byte *data, int width, int height, int rowbytes, + const byte *palette, qboolean flip, int *length); /** Load a texture from a PCX file. @@ -75,6 +75,6 @@ pcx_t *EncodePCX (byte *data, int width, int height, int rowbytes, \return A pointer to the texture. \warning Uses Hunk_TempAlloc() to allocate the texture. */ -struct tex_s *LoadPCX (QFile *f, qboolean convert, byte *pal); +struct tex_s *LoadPCX (QFile *f, qboolean convert, const byte *pal); #endif // __pcx_h diff --git a/include/QF/vid.h b/include/QF/vid.h index 9faf1e293..d7c2997f4 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -41,7 +41,7 @@ typedef struct { short *zbuffer; void *surfcache; byte *gammatable; // 256 - byte *basepal; // 256 * 3 + const byte *basepal; // 256 * 3 byte *palette; // 256 * 3 byte *colormap8; // 256 * VID_GRADES size unsigned short *colormap16; // 256 * VID_GRADES size diff --git a/include/vid_internal.h b/include/vid_internal.h index 2f2625222..4f1846f99 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -12,7 +12,7 @@ extern unsigned short sw32_8to16table[256]; void VID_GetWindowSize (int def_w, int def_h); -void VID_InitGamma (unsigned char *); +void VID_InitGamma (const byte *); qboolean VID_SetGamma (double); void VID_UpdateGamma (struct cvar_s *); diff --git a/libs/image/pcx.c b/libs/image/pcx.c index 9ca47bc34..468ce24b8 100644 --- a/libs/image/pcx.c +++ b/libs/image/pcx.c @@ -47,7 +47,7 @@ VISIBLE tex_t * -LoadPCX (QFile *f, qboolean convert, byte *pal) +LoadPCX (QFile *f, qboolean convert, const byte *pal) { pcx_t *pcx; int pcx_mark; @@ -141,12 +141,13 @@ LoadPCX (QFile *f, qboolean convert, byte *pal) } VISIBLE pcx_t * -EncodePCX (byte * data, int width, int height, - int rowbytes, byte * palette, qboolean flip, int *length) +EncodePCX (const byte *data, int width, int height, + int rowbytes, const byte *palette, qboolean flip, int *length) { - int i, run, pix, size; - pcx_t *pcx; - byte *pack, *dataend; + int i, run, pix, size; + pcx_t *pcx; + byte *pack; + const byte *dataend; size = width * height * 2 + 1000; if (!(pcx = Hunk_TempAlloc (size))) { diff --git a/libs/models/gl_skin.c b/libs/models/gl_skin.c index 0647d361e..c4191a7fa 100644 --- a/libs/models/gl_skin.c +++ b/libs/models/gl_skin.c @@ -132,7 +132,8 @@ build_skin_32 (tex_t *tex, int texnum, byte *translate, unsigned i, j; int samples = alpha ? gl_alpha_format : gl_solid_format; unsigned frac, fracstep; - byte pixels[512 * 256 * 4], *out, *pal; + byte pixels[512 * 256 * 4], *out; + const byte *pal; byte c; out = pixels; diff --git a/libs/models/glsl_skin.c b/libs/models/glsl_skin.c index c2e5d39c3..8e6d74878 100644 --- a/libs/models/glsl_skin.c +++ b/libs/models/glsl_skin.c @@ -67,7 +67,7 @@ glsl_Skin_ProcessTranslation (int cmap, const byte *translation) for (i = 0, dst = top; i < VID_GRADES; i++, src += 256 - 16) { for (j = 0; j < 16; j++) { byte c = *src++; - byte *in = vid.palette + c * 3; + const byte *in = vid.palette + c * 3; *dst++ = *in++; *dst++ = *in++; *dst++ = *in++; @@ -78,7 +78,7 @@ glsl_Skin_ProcessTranslation (int cmap, const byte *translation) for (i = 0, dst = bottom; i < VID_GRADES; i++, src += 256 - 16) { for (j = 0; j < 16; j++) { byte c = *src++; - byte *in = vid.palette + c * 3; + const byte *in = vid.palette + c * 3; *dst++ = *in++; *dst++ = *in++; *dst++ = *in++; @@ -129,7 +129,7 @@ glsl_Skin_InitTranslations (void) for (i = 0, dst = map, src = vid.colormap8; i < 256 * VID_GRADES; i++) { byte c = *src++; - byte *in = vid.palette + c * 3; + const byte *in = vid.palette + c * 3; *dst++ = *in++; *dst++ = *in++; *dst++ = *in++; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 65b13c0c7..a54e17251 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -805,7 +805,8 @@ void Draw_BlendScreen (quat_t color) { int r, g, b, i; - byte *basepal, *newpal; + const byte *basepal; + byte *newpal; byte pal[768]; basepal = vid.basepal; newpal = pal; diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c index b02ee61ac..3068158cc 100644 --- a/libs/video/renderer/sw32/draw.c +++ b/libs/video/renderer/sw32/draw.c @@ -1275,7 +1275,8 @@ void sw32_Draw_BlendScreen (quat_t color) { int r, g, b, i; - byte *basepal, *newpal; + const byte *basepal; + byte *newpal; byte pal[768]; switch(sw32_r_pixbytes) { diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index a398edd08..e53011918 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -230,7 +230,7 @@ VID_UpdateGamma (cvar_t *vid_gamma) Initialize the vid_gamma Cvar, and set up the palette */ void -VID_InitGamma (unsigned char *pal) +VID_InitGamma (const byte *pal) { int i; double gamma = 1.0; diff --git a/tools/wad/script.c b/tools/wad/script.c index eef6a90e9..a9a9dcd5d 100644 --- a/tools/wad/script.c +++ b/tools/wad/script.c @@ -104,7 +104,7 @@ load_image (const char *name) switch (tex->format) { case tex_palette: for (i = 0, s = tex->data, d = image->data; i < pixels; i++) { - byte *v = tex->palette + *s++ * 3; + const byte *v = tex->palette + *s++ * 3; *d++ = *v++; *d++ = *v++; *d++ = *v++; From 3e27689ca897b6d4dbecfccd88ec0d7c3f4844fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Jan 2013 20:04:34 +0900 Subject: [PATCH 0018/3664] Begin splitting the code into more easily digested chunks. While MH's code certainly does the job, it's rather hard to follow with functions doing different jobs on different calls. --- libs/video/targets/vid_win.c | 124 +++++++++++++++++------------------ 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 28a1b695d..35f8b1cf8 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -234,8 +234,8 @@ DD_UpdateRects (int width, int height) static void -VID_CreateDDrawDriver (int width, int height, byte *palette, void **buffer, - int *rowbytes) +VID_CreateDDrawDriver (int width, int height, const byte *palette, + void **buffer, int *rowbytes) { HRESULT hr; DDSURFACEDESC ddsd; @@ -333,7 +333,7 @@ HDC hdcGDI = NULL; static void -VID_CreateGDIDriver (int width, int height, byte *palette, void **buffer, +VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer, int *rowbytes) { dibinfo_t dibheader; @@ -499,7 +499,7 @@ static qboolean vid_initialized = false, vid_palettized; static int vid_fulldib_on_focus_mode; static qboolean force_minimized, in_mode_set, force_mode_set; static int windowed_mouse; -static qboolean palette_changed, vid_mode_set, hide_window; +static qboolean palette_changed, vid_mode_set; static HICON hIcon; #define MODE_WINDOWED 0 @@ -571,6 +571,8 @@ void VID_MenuKey (int key); LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void AppActivate (BOOL fActive, BOOL minimize); +static int VID_SetMode (int modenum, const byte *palette); + // video commands int VID_NumModes (void); vmode_t *VID_GetModePtr (int modenum); @@ -815,6 +817,59 @@ VID_GetDisplayModes (void) Sys_Printf ("No fullscreen DIB modes found\n"); } +static void +WIN_OpenDisplay (void) +{ + VID_InitModes (global_hInstance); + VID_GetDisplayModes (); + + vid_testingmode = 0; + + // if (COM_CheckParm("-startwindowed")) + { + startwindowed = 1; + vid_default = windowed_default; + } + +//FIXME? if (hwnd_dialog) +//FIXME? DestroyWindow (hwnd_dialog); + + // sound initialization has to go here, preceded by a windowed mode set, + // so there's a window for DirectSound to work with but we're not yet + // fullscreen so the "hardware already in use" dialog is visible if it + // gets displayed + // keep the window minimized until we're ready for the first real mode set + hWndWinQuake = CreateWindowEx (ExWindowStyle, + "WinQuake", + "WinQuake", + WindowStyle, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + NULL, NULL, global_hInstance, NULL); + + if (!hWndWinQuake) + Sys_Error ("Couldn't create DIB window"); + + // compatibility + mainwindow = hWndWinQuake; + + // done + vid_mode_set = true; +//FIXME if (firsttime) S_Init (); +} + +static void +WIN_SetVidMode (unsigned width, unsigned height, const byte *palette) +{ +//FIXME SCR_StretchInit(); + + force_mode_set = true; + VID_SetMode (vid_default, palette); + force_mode_set = false; + vid_realmode = vid_modenum; + strcpy (badmode.modedesc, "Bad mode"); +} static void VID_DestroyWindow (void) @@ -858,23 +913,6 @@ VID_SetWindowedMode (int modenum) // the first time we're called to set the mode, create the window we'll use // for the rest of the session if (!vid_mode_set) { - hWndWinQuake = CreateWindowEx (ExWindowStyle, - "WinQuake", - "WinQuake", - WindowStyle, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - NULL, NULL, global_hInstance, NULL); - - if (!hWndWinQuake) - Sys_Error ("Couldn't create DIB window"); - - // compatibility - mainwindow = hWndWinQuake; - - // done - vid_mode_set = true; } else { SetWindowLong (hWndWinQuake, GWL_STYLE, WindowStyle | WS_VISIBLE); SetWindowLong (hWndWinQuake, GWL_EXSTYLE, ExWindowStyle); @@ -889,9 +927,6 @@ VID_SetWindowedMode (int modenum) Sys_Error ("Couldn't resize DIB window"); } - if (hide_window) - return true; - // position and show the DIB window VID_CheckWindowXY (); SetWindowPos (hWndWinQuake, NULL, vid_window_x->int_val, @@ -990,8 +1025,6 @@ VID_SetFullDIBMode (int modenum) return true; } -static int VID_SetMode (int modenum, byte *palette); - static void VID_RestoreOldMode (int original_mode) { @@ -1027,7 +1060,7 @@ VID_SetDefaultMode (void) static int -VID_SetMode (int modenum, byte *palette) +VID_SetMode (int modenum, const byte *palette) { int original_mode; // FIXME, temp; qboolean stat; @@ -1137,9 +1170,6 @@ VID_SetMode (int modenum, byte *palette) return false; } - if (hide_window) - return true; - // now we try to make sure we get the focus on the mode switch, because // sometimes in some systems we don't. We grab the foreground, then // finish setting up, pump all our messages, and sleep for a little while @@ -1314,45 +1344,15 @@ VID_Init (byte *palette, byte *colormap) viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; VID_GetWindowSize (640, 480); - - VID_InitModes (global_hInstance); - VID_GetDisplayModes (); + WIN_OpenDisplay (); choose_visual (); - + WIN_SetVidMode (viddef.width, viddef.height, palette); create_context (); VID_InitGamma (palette); viddef.set_palette (palette); - vid_testingmode = 0; - - // if (COM_CheckParm("-startwindowed")) - { - startwindowed = 1; - vid_default = windowed_default; - } - -//FIXME? if (hwnd_dialog) -//FIXME? DestroyWindow (hwnd_dialog); - - // sound initialization has to go here, preceded by a windowed mode set, - // so there's a window for DirectSound to work with but we're not yet - // fullscreen so the "hardware already in use" dialog is visible if it - // gets displayed - // keep the window minimized until we're ready for the first real mode set - hide_window = true; - VID_SetMode (MODE_WINDOWED, palette); - hide_window = false; -//FIXME if (firsttime) S_Init (); vid_initialized = true; - -//FIXME SCR_StretchInit(); - - force_mode_set = true; - VID_SetMode (vid_default, palette); - force_mode_set = false; - vid_realmode = vid_modenum; - strcpy (badmode.modedesc, "Bad mode"); } #if 0 From 2336b0bcc81e21943917de0c44e14f69ee80ffb2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Jan 2013 16:02:33 +0900 Subject: [PATCH 0019/3664] Do some more code split-up. --- libs/video/targets/vid_win.c | 103 ++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 35f8b1cf8..247298699 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -73,7 +73,7 @@ static BOOL (GLAPIENTRY * qfwglMakeCurrent) (HDC, HGLRC); static void *(WINAPI * glGetProcAddress) (const char *symbol) = NULL; static void (*choose_visual) (void); -static void (*create_context) (void); +static void (*create_context) (const byte *palette); static void * QFGL_GetProcAddress (void *handle, const char *name) @@ -135,7 +135,7 @@ wgl_choose_visual (void) } static void -wgl_create_context (void) +wgl_create_context (const byte *palette) { DWORD lasterror; @@ -1058,6 +1058,17 @@ VID_SetDefaultMode (void) IN_DeactivateMouse (); } +static void +win_init_bufers (void) +{ + // set the rest of the buffers we need (why not just use one single buffer + // instead of all this crap? oh well, it's Quake...) + viddef.direct = (byte *) viddef.buffer; + viddef.conbuffer = viddef.buffer; + + // more crap for the console + viddef.conrowbytes = viddef.rowbytes; +} static int VID_SetMode (int modenum, const byte *palette) @@ -1114,49 +1125,6 @@ VID_SetMode (int modenum, const byte *palette) IN_HideMouse (); } - // shutdown any old driver that was active - VID_UnloadAllDrivers (); - - // because we have set the background brush for the window to NULL (to - // avoid flickering when re-sizing the window on the desktop), we clear - // the window to black when created, otherwise it will be empty while - // Quake starts up. This also prevents a screen flash to white when - // switching drivers. it still flashes, but at least it's black now - hdc = GetDC (hWndWinQuake); - PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); - ReleaseDC (hWndWinQuake, hdc); - - // create the new driver - vid_usingddraw = false; - - // attempt to create a direct draw driver - if (vid_ddraw->int_val) - VID_CreateDDrawDriver (DIBWidth, DIBHeight, palette, &viddef.buffer, - &viddef.rowbytes); - - // create a gdi driver if directdraw failed or if we preferred not to use - // it - if (!vid_usingddraw) { - // because directdraw may have been partially created we must shut it - // down again first - VID_UnloadAllDrivers (); - - // now create the gdi driver - VID_CreateGDIDriver (DIBWidth, DIBHeight, palette, &viddef.buffer, - &viddef.rowbytes); - } - // if ddraw failed to come up we disable the cvar too - if (vid_ddraw->int_val && !vid_usingddraw) - Cvar_Set (vid_ddraw, "0"); - - // set the rest of the buffers we need (why not just use one single buffer - // instead of all this crap? oh well, it's Quake...) - viddef.direct = (byte *) viddef.buffer; - viddef.conbuffer = viddef.buffer; - - // more crap for the console - viddef.conrowbytes = viddef.rowbytes; - window_width = viddef.width; window_height = viddef.height; @@ -1191,8 +1159,6 @@ VID_SetMode (int modenum, const byte *palette) vid_modenum = modenum; Cvar_SetValue (vid_mode, (float) vid_modenum); - VID_InitBuffers (); - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); DispatchMessage (&msg); @@ -1327,8 +1293,47 @@ win_choose_visual (void) } static void -win_create_context (void) +win_create_context (const byte *palette) { + HDC hdc; + + // shutdown any old driver that was active + VID_UnloadAllDrivers (); + + // because we have set the background brush for the window to NULL (to + // avoid flickering when re-sizing the window on the desktop), we clear + // the window to black when created, otherwise it will be empty while + // Quake starts up. This also prevents a screen flash to white when + // switching drivers. it still flashes, but at least it's black now + hdc = GetDC (hWndWinQuake); + PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); + ReleaseDC (hWndWinQuake, hdc); + + // create the new driver + vid_usingddraw = false; + + // attempt to create a direct draw driver + if (vid_ddraw->int_val) + VID_CreateDDrawDriver (DIBWidth, DIBHeight, palette, &viddef.buffer, + &viddef.rowbytes); + + // create a gdi driver if directdraw failed or if we preferred not to use + // it + if (!vid_usingddraw) { + // because directdraw may have been partially created we must shut it + // down again first + VID_UnloadAllDrivers (); + + // now create the gdi driver + VID_CreateGDIDriver (DIBWidth, DIBHeight, palette, &viddef.buffer, + &viddef.rowbytes); + } + // if ddraw failed to come up we disable the cvar too + if (vid_ddraw->int_val && !vid_usingddraw) + Cvar_Set (vid_ddraw, "0"); + + viddef.do_screen_buffer = win_init_bufers; + VID_InitBuffers (); } void @@ -1347,7 +1352,7 @@ VID_Init (byte *palette, byte *colormap) WIN_OpenDisplay (); choose_visual (); WIN_SetVidMode (viddef.width, viddef.height, palette); - create_context (); + create_context (palette); VID_InitGamma (palette); viddef.set_palette (palette); From 2329fb18853f5778a0f3c93f5d97886ea7ff2ccd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Oct 2016 00:10:30 +0900 Subject: [PATCH 0020/3664] Fix some warnings and bitrot. --- libs/audio/cd_file.c | 2 +- libs/audio/renderer/midi.c | 2 +- libs/video/targets/context_x11.c | 2 +- tools/qfbsp/source/brush.c | 2 +- tools/qfcc/source/flow.c | 2 +- tools/qfcc/source/qc-lex.l | 2 ++ 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index ce0f2b94f..94d394154 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -454,7 +454,7 @@ Mus_VolChange (cvar_t *bgmvolume) static void Mus_gamedir (int phase) { - if (phase); + if (phase) Mus_OggChange (mus_ogglist); } diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index 86898da65..c4f44a050 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -105,7 +105,7 @@ midi_stream_read (void *file, float **buf) int res; byte *data = alloca (size); - res = WildMidi_GetOutput (mf->handle, (char *)data, size); + res = WildMidi_GetOutput (mf->handle, (int8_t *)data, size); if (res <= 0) { stream->error = 1; return 0; diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index dc9ae9a0c..41045fcdf 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -406,7 +406,7 @@ X11_SetVidMode (int width, int height) vid_gamma_avail = true; temp = X11_GetGamma (); - if (temp && temp[0] > 0) { + if (temp && (*temp)[0] > 0) { x_gamma[0] = (*temp)[0]; x_gamma[1] = (*temp)[1]; x_gamma[2] = (*temp)[2]; diff --git a/tools/qfbsp/source/brush.c b/tools/qfbsp/source/brush.c index f27c253b8..940fddfb4 100644 --- a/tools/qfbsp/source/brush.c +++ b/tools/qfbsp/source/brush.c @@ -736,7 +736,7 @@ LoadBrush (const mbrush_t *mb, int hullnum) CreateBrushFaces (); } else if (mb->detail) { face_t *f; - for (f = brush_faces; f; f = f->next); + for (f = brush_faces; f; f = f->next) f->detail = 1; } diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 2c6692f1d..c611fd0a8 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -981,7 +981,7 @@ flow_make_edges (flowgraph_t *graph) flownode_t *node; set_iter_t *succ; - if (graph->edges); + if (graph->edges) free (graph->edges); graph->edges = malloc (graph->num_edges * sizeof (flowedge_t)); for (j = 0, i = 0; i < graph->num_nodes + 2; i++) { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 7d190cb48..14cc1265f 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -442,6 +442,8 @@ keyword_or_id (char *token) #ifdef YY_FLEX_REALLOC_HACK static __attribute__ ((used)) void *(*const yy_flex_realloc_hack)(void *,yy_size_t) = yy_flex_realloc; #else +#ifdef yyunput static __attribute__ ((used)) void (*yyunput_hack)(int, char*) = yyunput; +#endif static __attribute__ ((used)) int (*input_hack)(void) = input; #endif From f522e58d530b895bf268135204f6c8a4b6fed667 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 8 Jun 2018 12:45:57 +0900 Subject: [PATCH 0021/3664] Fix some blender warnings. --- tools/io_mesh_qfmdl/__init__.py | 2 +- tools/io_qfmap/__init__.py | 2 +- tools/io_qfmap/entity.py | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/io_mesh_qfmdl/__init__.py b/tools/io_mesh_qfmdl/__init__.py index 5ee7375ef..03eb35e71 100644 --- a/tools/io_mesh_qfmdl/__init__.py +++ b/tools/io_mesh_qfmdl/__init__.py @@ -128,7 +128,7 @@ class ExportMDL6(bpy.types.Operator, ExportHelper): keywords = self.as_keywords (ignore=("check_existing", "filter_glob")) return export_mdl.export_mdl(self, context, **keywords) -class MDLPanel(bpy.types.Panel): +class OBJECT_PT_MDLPanel(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = 'object' diff --git a/tools/io_qfmap/__init__.py b/tools/io_qfmap/__init__.py index c67158aff..953750b63 100644 --- a/tools/io_qfmap/__init__.py +++ b/tools/io_qfmap/__init__.py @@ -222,7 +222,7 @@ class QFEntityClasses(bpy.types.PropertyGroup): d[sub] = ec self.__class__.ecm = EntityClassMenu.build(menudict) -class QFECPanel(bpy.types.Panel): +class OBJECT_PT_QFECPanel(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = 'scene' diff --git a/tools/io_qfmap/entity.py b/tools/io_qfmap/entity.py index ecf9180c8..23f151f7e 100644 --- a/tools/io_qfmap/entity.py +++ b/tools/io_qfmap/entity.py @@ -77,7 +77,7 @@ def draw_callback(self, context): bgl.glEnd() bgl.glLineWidth(1) -class QFEntityRelations(bpy.types.Panel): +class VIEW3D_PT_QFEntityRelations(bpy.types.Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_label = "Register callback" @@ -100,7 +100,7 @@ class QFEntityRelations(bpy.types.Panel): def draw(self, context): pass -class EntityField_list(bpy.types.UIList): +class OBJECT_UL_EntityField_list(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): layout.label(item.name) @@ -163,7 +163,7 @@ def reflow_text(text, max_width): lines.append(flowed_line) return lines -class EntityPanel(bpy.types.Panel): +class OBJECT_PT_EntityPanel(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = 'object' @@ -198,7 +198,7 @@ class EntityPanel(bpy.types.Panel): sub.prop(qfentity, "flags", text=flags[idx], index=idx) row = layout.row() col = row.column() - col.template_list("EntityField_list", "", qfentity, "fields", + col.template_list("OBJECT_UL_EntityField_list", "", qfentity, "fields", qfentity, "field_idx", rows=3) col = row.column(align=True) col.operator("object.entprop_add", icon='ZOOMIN', text="") From 0de0eb2fc74b608c909f4301a5516cebc22b14f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 8 Jun 2018 13:21:30 +0900 Subject: [PATCH 0022/3664] Fix a bunch of bit-rot. --- config.d/typedefs_structs_compiler.m4 | 6 +++--- include/QF/pr_comp.h | 4 ++-- include/QF/progs.h | 2 +- libs/gamecode/pr_load.c | 2 +- libs/util/plugin.c | 6 ++++-- nq/source/sv_main.c | 2 +- qw/source/cl_slist.c | 2 +- tools/qfcc/source/qp-lex.l | 2 ++ 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/config.d/typedefs_structs_compiler.m4 b/config.d/typedefs_structs_compiler.m4 index 3ba73b7d6..8e6acac2e 100644 --- a/config.d/typedefs_structs_compiler.m4 +++ b/config.d/typedefs_structs_compiler.m4 @@ -74,9 +74,9 @@ AH_VERBATIM([HAVE___ATTRIBUTE__GCC_STRUCT], #endif]) AC_MSG_CHECKING(for __builtin_expect) -AC_TRY_COMPILE( - [long (*foo) (long, long) = __builtin_expect;], - [], +AC_TRY_LINK( + [int x;], + [if (__builtin_expect(!x, 1)) {}], AC_DEFINE(HAVE___BUILTIN_EXPECT) AC_MSG_RESULT(yes), AC_MSG_RESULT(no) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 4cc274f98..7bac7eb01 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -346,8 +346,8 @@ typedef union pr_type_u { string_t string_var; func_t func_var; pr_int_t entity_var; - float vector_var[1]; // really 3, but this structure must be 32 bits - float quat_var[1]; // really 4, but this structure must be 32 bits + float vector_var[0]; // really 3, but this structure must be 32 bits + float quat_var[0]; // really 4, but this structure must be 32 bits pr_int_t integer_var; pointer_t pointer_var; pr_uint_t uinteger_var; diff --git a/include/QF/progs.h b/include/QF/progs.h index 7c8bb3341..1c706ae4c 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -221,7 +221,7 @@ struct edict_s { int entnum; ///< number of this entity float freetime; ///< sv.time when the object was freed void *edata; ///< external per-edict data - pr_type_t v[1]; ///< fields from progs + pr_type_t v[]; ///< fields from progs }; // pr_edict.c diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index b9a6df13a..82864b096 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -177,7 +177,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) // size of edict asked for by progs pr->pr_edict_size = max (1, progs.entityfields) * 4; // size of engine data - pr->pr_edict_size += sizeof (edict_t) - sizeof (pr_type_t); + pr->pr_edict_size += sizeof (edict_t); // round off to next highest whole word address (esp for Alpha) // this ensures that pointers in the engine data area are always // properly aligned diff --git a/libs/util/plugin.c b/libs/util/plugin.c index 31fa725fd..7baa8df72 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -98,11 +98,13 @@ loaded_plugin_delete (void *lp, void *unused) static int pi_close_lib (void *handle) { + if (handle) { #if defined(HAVE_DLOPEN) - return (dlclose (handle) == 0); + return (dlclose (handle) == 0); #elif defined (_WIN32) - return (FreeLibrary (handle) == 0); + return (FreeLibrary (handle) == 0); #endif + } return 1; } diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 25def54ac..b666516f6 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -45,7 +45,7 @@ server_t sv; server_static_t svs; double sv_frametime; -char localmodels[MAX_MODELS][5]; // inline model names for precache +char localmodels[MAX_MODELS][6]; // inline model names for precache int sv_protocol = PROTOCOL_FITZQUAKE; diff --git a/qw/source/cl_slist.c b/qw/source/cl_slist.c index 569b711ce..585e6aa47 100644 --- a/qw/source/cl_slist.c +++ b/qw/source/cl_slist.c @@ -348,7 +348,7 @@ gettoklen (char *str, int req, char delim) int len = 0; start = gettokstart (str, req, delim); - if (start == '\0') { + if (*start == '\0') { return 0; } while (*start != delim && *start != '\0') { diff --git a/tools/qfcc/source/qp-lex.l b/tools/qfcc/source/qp-lex.l index e98b6511b..0bca559c9 100644 --- a/tools/qfcc/source/qp-lex.l +++ b/tools/qfcc/source/qp-lex.l @@ -296,7 +296,9 @@ convert_relop (const char *relop) #ifdef YY_FLEX_REALLOC_HACK static __attribute__ ((used)) void *(*const yy_flex_realloc_hack)(void *,yy_size_t) = yy_flex_realloc; #else +#ifdef yyunput static __attribute__ ((used)) void (*yyunput_hack)(int, char*) = yyunput; +#endif static __attribute__ ((used)) int (*input_hack)(void) = input; #endif From b795beb52004e9d8c8066d22845d7d658fb610ef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Aug 2018 19:31:52 +0900 Subject: [PATCH 0023/3664] Add support for \? to qc strings. And fix up the man page a bit. --- tools/qfcc/doc/man/qfcc.1 | 222 ++++++++++++++++++++++++++++++------ tools/qfcc/source/strpool.c | 4 + 2 files changed, 190 insertions(+), 36 deletions(-) diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index 2857ffedd..a5e2794e0 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -31,49 +31,67 @@ .ds qfcc \fBqfcc\fP .ds cpp \fBcpp\fP .ds progs.src \fIprogs.src\fP + .TH QFCC 1 "28 April, 2004" QuakeForge "QuakeForge Developer's Manual" .\" Please update the above date whenever this man page is modified. + + .SH NAME qfcc \- The QuakeForge Code Compiler + + .SH SYNOPSIS .B qfcc .RI [ options ] .RI [ files ] + + .SH DESCRIPTION \*[qfcc] compiles Ruamoko source into a form that the QuakeForge engine can understand. + + .SH OPTIONS \*[qfcc] takes the following arguments: + .TP .B \-\-advanced Use advanced Ruamoko features. This is the default when using separate compilation. + .TP .B \-C, \-\-code OPTION,... Set code generation options. See \fBCODE GENERATION OPTIONS\fP for details. + .TP .B \-c Only compile, do not link. Can be used in either \fBprogs.src\fP or separate compilation modes. + .TP .B \-\-cpp CPPSPEC \*[cpp] execution command line. See \fBCPP NAME\fP for details. + .TP .B \-D, \-\-define SYMBOL[=VAL] Define a symbol for the preprocessor, if it is in use. + .TP .B \-E Only preprocess. No compilation or linking is done. + .TP .B \-\-extended Allow extended keywords in traditional mode. + .TP .B \-F, \-\-files Generate \fIfiles.dat\fP. This list is created by checking the parameters to the precache_* functions. + .TP .B \-\-frames Generate \fI.frame\fP files. @@ -84,57 +102,71 @@ names with their associated frame numbers. Eg, \fBplayer.qc\fP will produce \fBplayer.frame\fPa. Note that files that do not create frame macros will not generate a frame file. At this time, the file is always written to the current directory. + .TP .B \-g Generate debugging info. Synonym for \fB\-\-code debug\fP. + .TP .B \-h, \-\-help Show summary of options. + .TP .B \-I DIR Add DIR to the list of directories for the preprocessor to search when looking for include files. + .TP .B \-\-include FILE Process FILE as if \fB#include "FILE"\fP appeared as the first line of the primary source file. See the \*[cpp] man page (\fB\-include\fP) for details. + .TP .B \-L DIR Add DIR to the search path used for finding libraries specified with \fB-l\fP. + .TP .B \-l LIB Add libLIB.a to the list of libraries to be used for resolving undefined symbols. \*[qfcc] expects libraries to be \fBpak\fP files of \*[qfcc] object files built using the \fBpak\fP utility. + .TP .B \-M, \-MD, \-MMD Generate dependency info. Dependent on \*[cpp] version, so check \*[cpp]'s documentation. + .TP .B \-\-no\-default\-paths Do not use default paths for include files or libraries. + .TP .B \-N, \-\-notice OPTION,... Set notice options. See \fBNOTICE OPTIONS\fP for details. + .TP .B \-o, \-\-output\-file FILE Specify output file name. In \fBprogs.src\fP mode, this overrides the output file in \*[progs.src]. + .TP .B \-\-progdefs Generate \fIprogdefs.h\fP. Forces \fB\-\-code crc\fP. + .TP .B \-P, \-\-progs\-src FILE File to use instead of \*[progs.src]. No effect in separate compilation mode. + .TP .B \-\-qccx\-escapes Use QCCX escape sequences instead of standard C/QuakeForge sequences in strings. See \fBESCAPE SEQUENCES\fP for details. + .TP .B \-p, \-\-strip\-path NUM Strip NUM leading path elements from file names. @@ -143,21 +175,26 @@ eg. -p 3 will strip the from .I ../../../src/foo.r when embedding the source file name in the output code. + .TP .B \-q, \-\-quiet Inhibit some of \*[qfcc]'s normal output. Specifying this option multiple times further inhibits \*[qfcc]'s output. Counteracts the effects of \fB-v\fP. + .TP .B \-r, \-\-relocatable Incremental linking. Generate a larger object file from other object files and libraries. + .TP .B \-S, \-\-save\-temps Do not delete temporary files. + .TP .B \-s, \-\-source DIR Look for \*[progs.src] in \fBDIR\fP instead of the current directory. + .TP .B \-\-traditional Use traditional QuakeC syntax, semantics and \*(lqbugs\*(rq. @@ -165,32 +202,40 @@ Also implies the \fBv6only\fP, \fBno-short-circuit\fP and \fBno-local-merging\fP code generation options (see \fBCODE GENERATION OPTIONS\fP). This is the default when using \fBprogs.src\fP mode. + .TP .B \-U, \-\-undefine SYMBOL Undefine a preprocessor symbol, if the preprocessor is in use. + .TP .B \-V, \-\-version Show the version of \*[qfcc]. + .TP .B \-v, \-\-verbose Display more output than usual. Specifying this option multiple times further increases \*[qfcc]'s output. Counteracts the effects of \fB-q\fP. + .TP .B \-W, \-\-warn OPTION,... Set warning options. See \fBWARNING OPTIONS\fP for details. + .TP .B \-z Compress object files when writing them. This is especially useful when creating libraries, especially if using the object oriented features, but can be quite slow. This has no effect when creating \fBprogs.dat\fP. + + .SH "CODE GENERATION OPTIONS" Code generation options are processed in the order of their appearance on the command line. Unsupported options are ignored. The following options are supported by \*[qfcc]'s \fB\-\-code\fP argument: + .TP .B cow Allow assignment to initialized globals. @@ -200,15 +245,18 @@ However, \fBqcc\fP never really enforced this. The \fBcow\fP option allows \*[qfcc] to gracefully cope with QuakeC source that assigns values to initialized globals in this manner. (also known as \*(lqcopy on write\*(rq\(emnever mind the bovine connotations) + .TP .B cpp Preprocess all input files with \*[cpp]. This includes the \*[progs.src] file when used. + .TP .B crc Write the CRC of \fBprogdefs.h\fP to \*(lqprogs.dat\*(rq. Default for v6 progs, otherwise defaults to off. However, \fB\-\-progdefs\fP has the effect of forcing this option. + .TP .B debug Generate debug code for QuakeForge engines. @@ -218,12 +266,14 @@ This option tells \*[qfcc] to generate this information. It is written to a secondary file with the extension \*(lqsym\*(rq\(emif your output file is \*(lqprogs.dat\*(rq, the symbol file will be \*(lqprogs.sym\*(rq. + .TP .B fast\-float Use float values directly in \*(lqif\*(rq statements. Defaults to on. This option is always enabled when using version 6 progs (\fBv6only\fP is in effect). + .TP .B local-merging Clump the local variables from all functions into one block of data the size @@ -235,6 +285,7 @@ data. This can be a problem because instructions can access addresses up to 32767 in older servers or 65535 in most modern servers. Defaults to off for traditional mode, and on for advanced mode. + .TP .B short\-circuit Generate short circuit code for logical operators (\fB&&\fP and \fB||\fP). @@ -243,6 +294,7 @@ the code for \fBB\fP will not be executed. Similar for \fBA || B\fP, but if \fBA\fP is true, the expression is known to be true and the code for \fBB\fP will not be executed. Defaults to off for traditional mode, and on for advanced mode. + .TP .B single-cpp In \fBprogs.src\fP mode, when \*[cpp] is used, produce an intermediate file @@ -255,6 +307,7 @@ Without this option, each source file is independent with respect to the preprocessor. Has no effect in separate compilation mode. Defaults to on. + .TP .B vector\-calls When a function is passed a constant vector, this causes the vector to be @@ -263,12 +316,14 @@ instruction. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirely. However, this will generate slower code for such calls. + .TP .B vector\-components Create extra symbols for accessing the components of a vector variable or field. For example, \fBvector vel\fP will also create \fBvel_x\fP, \fBvel_y\fP, and \fBvel_z\fP. Defaults to on for traditional code and off for advanced. + .TP .B v6only Restrict the compiler to only version 6 progs (original Quake/QuakeWorld) @@ -280,64 +335,80 @@ support) that require extensions. Defaults to on for traditional mode and off for advanced mode. .PP Any of the above can be prefixed with \fBno\-\fP to negate its meaning. + + .SH "WARNING OPTIONS" Warning options are processed in the order of their appearance on the command line. Unsupported options are ignored. The following options are supported by \*[qfcc]'s \fB\-\-warn\fP argument: + .TP .B cow Emit a warning when the source assigns a value to a named constant. See the description of the \fBcow\fP code generation option above for a description of what this means. + .TP .B error Promote warnings to errors. + .TP .B executable Emit a warning when non-executable statements (eg, \fB==\fP used for assignment) are encountered. + .TP .B initializer Emit a warning when too many structure/array initializer elements are given. + .TP .B integer-divide Emit a warning when both constants in a division operation are integers. + .TP .B interface\-check Emit a warning when a method is declared in an implementation but not in the interface for a class. + .TP .B precedence Emit a warning when potentially ambiguous logic is used without parentheses. + .TP .B redeclared Emit a warning when a local variable is redeclared. + .TP .B switch Emit a warning when an enum value is not handled in a switch statement that tests an enum. Using a default label will cause all otherwise unhandled enum values to be handled (for good or evil). -.TP + .TP .B traditional Emit a warning when code that should be an error is allowed by traditional \fBqcc\fP. Has effect only in traditional mode. + .TP .B undef\-function Emit a warning when a function is called, but has not yet been defined. + .TP .B unimplemented Emit a warning when a class method has not been implemented. + .TP .B unused Emit a warning for unused local variables. + .TP .B uninited\-var Emit a warning when a variable is read from that has not been initialized to a value. + .TP .B vararg\-integer Emit a warning when a function that takes a variable number of arguments is @@ -345,26 +416,34 @@ passed a constant of an integer type. .PP Any of the above can be prefixed with \fBno\-\fP to negate its meaning. There are also two special options: + .TP .B all Turns on all warning options except \fBerror\fP. + .TP .B none Turns off all warning options except \fBerror\fP. + + .SH "NOTICE OPTIONS" Notices are used to flag code constructs that may have changed semantics but shouldn't be treated as warnings. They are also used for internal debugging purposes, so if you see any cryptic notices, please report them as a bug (normal notices should be fairly self-explanatory). + .TP .B none Silences all notice messages. + .TP .B warn Promote notices to warnings. If warnings are being treated as errors, so will notices. Disabling warnings has no effect on this option. + + .SH "CPP NAME" When preprocessing source files, \*[qfcc] calls \*[cpp] (the C preprocessor) with a configurable command line. @@ -379,19 +458,24 @@ This spec is similar in concept to a \fBprintf\fP string. The name of the program may be either absolute (eg \fB/lib/cpp\fP) or relative as the \fBPATH\fP will be searched. Available substitutions: + .TP .B %d Mainly for defines (\-D, \-U and \-I) but \fB%d\fP will be replaced by all \*[cpp] options that \*[qfcc] passes to \*[cpp] + .TP .B %o This will be replaced by the output file path. Could be either absolute or relative, depending on whether \*[qfcc] is deleting temporary files or not. + .TP .B %i This will be replaced by the input file path. Generally as given to \*[qfcc]. + + .SH "COMPILATION MODES" \*[qfcc] has two, mutually exclusive, modes of operation: \fBprogs.src\fP mode and \*(lqseparate compilation\*(rq mode. @@ -466,99 +550,153 @@ overridden using \fB--traditional\fP. When using \*[cpp], each source file is passed through the preprocessor individually. Each file is truly independent of any other file on the command line. + + .SH "ESCAPE SEQUENCES" \*[qfcc] supports a variety of string escape sequences. This includes those of \fBqcc\fP (which are a subset of those in standard C), standard C and \fBqccx\fP. There are some conflicts between the escape sequences, but \fB\-\-qccx\-escapes\fP selects which set to use. -.TP -.B \(rs\(rs -Backslash. -.TP -.B \(rsn -Line feed. -.TP -.B \(rs" -Double quote. -.TP -.B \(rs\' -Single quote. -.TP -.B \(rs0-7 -Octal character code, up to three digits. This conflicts with \fBqccx\fP. In -\fBqccx\fP, this produces gold digits. Use \fB\-\-qccx\-escapes\fP to select -\fBqccx\fP behaviour. -.TP -.B \(rs8-9 -Produce gold digits. -.TP -.B \(rsx0-9A-Fa-f -Hexadecimal character code, any number of digits, but only the least -significant byte will be used. +.SS Standard escape sequences: +These are the supported escape sequences from standard C, with the addition of +\(rse (escape), which would be nice if it was in standard C. + .TP .B \(rsa Bell character (not in quake engines). Equivalent to \(rsx07. + .TP .B \(rsb Backspace character (not in quake engines). Equivalent to \(rsx08. This conflicts with \fBqccx\fP. In \fBqccx\fP, this toggles bronze characters. Use \fB\-\-qccx\-escapes\fP to select \fBqccx\fP behaviour. + .TP .B \(rse -Escape character (not in quake engines). Equivalent to \(rsx1b (dull 9). +Escape character (not in quake engines). Equivalent to \(rsx1b. Not actually +standard, but it should be. + .TP .B \(rsf Formfeed character (not in quake engines). Equivalent to \(rsx0c. + +.TP +.B \(rsn +Line feed. + .TP .B \(rsr Carriage return. Equivalent to \(rsx0d. + .TP -.B \(rss -Toggle "bold" characters (add 0x80). .B \(rst Tab character. Equivalent to \(rsx09. + .TP .B \(rsv Vertical tab. Equivalent to \(rsx0b. + .TP -.B \(rs^ -Make the next character "bold" (add 0x80). +.B \(rs\(rs +Backslash. + +.TP +.B \(rs\' +Single quote. + +.TP +.B \(rs" +Double quote. + +.TP +.B \(rs? +Question mark. Avoids trigraphs in standard C, but supported for compatibility. + +.TP +.B \(rs0-7 +Octal character code, up to three digits. This conflicts with \fBqccx\fP. In +\fBqccx\fP, this produces gold digits. Use \fB\-\-qccx\-escapes\fP to select +\fBqccx\fP behaviour. + +.TP +.B \(rs8-9 +Produce gold digits. + +.TP +.B \(rsx0-9A-Fa-f +Hexadecimal character code, any number of digits, but only the least +significant byte will be used. + + +.SS Quake character set extension escape sequences: + +.TP +.B \(rsb +Toggle bronze characters. Requires \fB\-\-qccx\-escapes\fP. + +.TP +.B \(rss +Toggle "bold" characters (add 0x80). + .TP .B \(rs[ Gold [ character. Equivalent to \(rsx90. + .TP .B \(rs] Gold ] character. Equivalent to \(rsx91. + .TP .B \(rs. Center dot. Equivalent to \(rsx1c. + .TP .B \(rs< Turn on "bold" characters (add 0x80). This conflicts with \fBqccx\fP. In -\fBqccx\fP, this produces the brown left end. Equivalent to \(rsx1d. Use +\fBqccx\fP, this produces the separator left end. Equivalent to \(rsx1d. Use \fB\-\-qccx\-escapes\fP to select \fBqccx\fP behaviour. + .TP .B \(rs\- -Brown center bit. Equivalent to \(rsx1e. +Separator center. Equivalent to \(rsx1e. + .TP .B \(rs> Turn off "bold" characters (add 0x80). This conflicts with \fBqccx\fP. In -\fBqccx\fP, this produces the brown right end. Equivalent to \(rsx1f. Use +\fBqccx\fP, this produces the separator right end. Equivalent to \(rsx1f. Use \fB\-\-qccx\-escapes\fP to select \fBqccx\fP behaviour. + +.TP +.B \(rs^ +Make the next character "bold" (add 0x80). + +.TP +.B \(rs0-9 +Produce gold digits. Requires \fB\-\-qccx\-escapes\fP (except \(rs8 and \(rs9: +they are always available). + .TP .B \(rs( -Left slider end. Equivalent to \(rsx80. +Slider left end. Equivalent to \(rsx80. + .TP .B \(rs= Slider center. Equivalent to \(rsx81. + .TP .B \(rs) -Right slider end. Equivalent to \(rsx82. +Slider right end. Equivalent to \(rsx82. + .TP .B \(rs{0-255} -Decimal character code. +Decimal character code. Quake specific as qccx added this to allow specifying +the character code directly as \(rs0-\(rs9 were already used for specifying +gold digits. + .P \fB\-\-qccx\-escapes\fP has no effect on sequences that do not conflict. + + .SH TRADITIONAL VS ADVANCED Compared to \fBqcc\fP, \*[qfcc] has many advanced features and is much stricter about type checking. @@ -586,13 +724,17 @@ a lot of data space). Advanced mode is simply \*[qfcc] in its natural state. Using \fB--advanced\fP, \*[qfcc] can be put in to advanced mode while using the \fBprogs.src\fP compilation mode. + + .SH "FAQ" + .TP .B Where did the name Ruamoko come from? In Maori mythology, Ruamoko is the youngest child of Ranginui, the Sky-father, and Papatuanuku, the Earth-mother. Ruamoko is the god of volcanoes and earthquakes. For more information, see the Web site at <\fBhttp://maori.com/kmst1.htm\fP>. + .TP .B qfcc hangs This is almost always caused by qfcc incorrectly invoking \*[cpp]. @@ -600,11 +742,13 @@ Using the \fB--cpp\fP option (refer to the \fBCPP NAME\fP section above), the correct method for invoking \*[cpp] can be specified. Once you have found this, please send the correct \*[cpp] command line, preferably along with the output of \fBconfig.guess\fP, to the team. + .TP .B qfcc is singing a bad 80s rap song to me. What's going on? \*(lqice ice baby\*(rq is QuakeForge-speak for \*(lqInternal Compiler Error\*(rq. It usually means there's a bug in \*[qfcc], so please report it to the team. + .TP .B qfcc is mooing at me. What's wrong with you people? The compiler doesn't like being treated like a slab of beef. @@ -615,11 +759,17 @@ while, but you told it not to do that by passing the \fBcow\fP option to \fB\-\-code\fP, so it has its revenge by mooing out a warning. Or something like that. To disable the warning, pass \fBno-cow\fP to \fB\-\-warn\fP. + + .SH "FILES" .I progs.src + + .SH "SEE ALSO" .BR quakeforge (1), .BR pak (1) + + .SH AUTHORS The original \fBqcc\fP program, for compiling the QuakeC language, was written by Id Software, Inc. diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index 8b32ae71e..0b59d5b9d 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -188,6 +188,10 @@ make_string (char *token, char **end) boldnext = 0; c = '\'' ^ mask; break; + case '?': + boldnext = 0; + c = '?' ^ mask; + break; case '0': case '1': case '2': From 81202d7b296536f82fa7b403a6bbc62ce1eb474f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Aug 2018 19:44:45 +0900 Subject: [PATCH 0024/3664] Add a shutdown builtin to qwaq. --- tools/qwaq/qwaq-bi.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/qwaq/qwaq-bi.c b/tools/qwaq/qwaq-bi.c index 3c5964df7..7e21a9259 100644 --- a/tools/qwaq/qwaq-bi.c +++ b/tools/qwaq/qwaq-bi.c @@ -143,11 +143,18 @@ bi_refresh_3d (progs_t *pr) qc3d = P_FUNCTION (pr, 0); } +static void +bi_shutdown_ (progs_t *pr) +{ + Sys_Shutdown (); +} + static builtin_t builtins[] = { {"printf", bi_printf, -1}, {"refresh", bi_refresh, -1}, {"refresh_2d", bi_refresh_2d, -1}, {"refresh_3d", bi_refresh_3d, -1}, + {"shutdown", bi_shutdown_, -1}, {0} }; From 4f584291375b146b50398b22ead976f74b33b1ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Aug 2018 00:05:00 +0900 Subject: [PATCH 0025/3664] Fix an unhealthy pile of gcc 8 warnings. While some of the warnings were merely annoying, some where actual bugs or unearthed bugs in related code. --- include/QF/model.h | 4 +- include/QF/teamplay.h | 2 +- libs/models/alias/gl_model_alias.c | 35 ++++++------ libs/models/brush/gl_model_brush.c | 4 +- libs/models/brush/model_brush.c | 26 +++++---- libs/models/gl_model_fullbright.c | 2 +- libs/util/pakfile.c | 2 +- libs/util/wadfile.c | 2 +- libs/video/renderer/gl/gl_draw.c | 3 +- nq/source/cl_demo.c | 23 ++++---- nq/source/sbar.c | 2 +- qw/include/server.h | 2 +- qw/source/cl_cmd.c | 38 ++++++++----- qw/source/cl_demo.c | 22 ++++---- qw/source/sbar.c | 2 +- qw/source/sv_init.c | 6 +- qw/source/sv_main.c | 8 +-- qw/source/sv_send.c | 89 ++++++++++++++++-------------- qw/source/teamplay.c | 39 ++++++------- tools/qfspritegen/spritegen.c | 18 +++--- 20 files changed, 178 insertions(+), 151 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index b4d7791cd..641e025ec 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -90,7 +90,7 @@ typedef struct instsurf_s { } instsurf_t; typedef struct texture_s { - char name[16]; + char *name; unsigned int width, height; int gl_texturenum; int gl_fb_texturenum; @@ -445,7 +445,7 @@ mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model); byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); model_t *Mod_FindName (const char *name); int Mod_CalcFullbright (byte *in, byte *out, int pixels); -int Mod_Fullbright (byte * skin, int width, int height, char *name); +int Mod_Fullbright (byte * skin, int width, int height, const char *name); void *Mod_LoadAliasFrame (void *pin, int *posenum, maliasframedesc_t *frame, int extra); diff --git a/include/QF/teamplay.h b/include/QF/teamplay.h index b0b1c01da..bf4ae9445 100644 --- a/include/QF/teamplay.h +++ b/include/QF/teamplay.h @@ -43,7 +43,7 @@ void Team_Init_Cvars (void); void Team_BestWeaponImpulse (void); void Team_Dead (void); void Team_NewMap (void); -const char *Team_ParseSay (const char *); +const char *Team_ParseSay (struct dstring_s *buf, const char *); void Locs_Init (void); void Team_ParseChat (const char *string); void Team_ResetTimers (void); diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index ec304b80d..63618451e 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -38,6 +38,7 @@ # include #endif +#include "QF/dstring.h" #include "QF/image.h" #include "QF/qendian.h" #include "QF/quakefs.h" @@ -56,8 +57,9 @@ gl_Mod_LoadSkin (byte * skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) { byte *pskin; - char name[32], modname[MAX_QPATH + 4]; + char modname[MAX_QPATH + 4]; int fb_texnum = 0, texnum = 0; + dstring_t *name = dstring_new (); pskin = Hunk_AllocName (skinsize, loadname); skindesc->skin = (byte *) pskin - (byte *) pheader; @@ -75,27 +77,26 @@ gl_Mod_LoadSkin (byte * skin, int skinsize, int snum, int gnum, qboolean group, if (!loadmodel->fullbright) { if (group) { - snprintf (name, sizeof (name), "fb_%s_%i_%i", modname, - snum, gnum); + dsprintf (name, "fb_%s_%i_%i", modname, snum, gnum); } else { - snprintf (name, sizeof (name), "fb_%s_%i", modname, snum); + dsprintf (name, "fb_%s_%i", modname, snum); } fb_texnum = Mod_Fullbright (pskin, pheader->mdl.skinwidth, - pheader->mdl.skinheight, name); - Sys_MaskPrintf (SYS_GLT, "%s %d\n", name, fb_texnum); + pheader->mdl.skinheight, name->str); + Sys_MaskPrintf (SYS_GLT, "%s %d\n", name->str, fb_texnum); } if (group) { - snprintf (name, sizeof (name), "%s_%i_%i", modname, snum, - gnum); + dsprintf (name, "%s_%i_%i", modname, snum, gnum); } else { - snprintf (name, sizeof (name), "%s_%i", modname, snum); + dsprintf (name, "%s_%i", modname, snum); } - texnum = GL_LoadTexture (name, pheader->mdl.skinwidth, + texnum = GL_LoadTexture (name->str, pheader->mdl.skinwidth, pheader->mdl.skinheight, pskin, true, false, 1); - Sys_MaskPrintf (SYS_GLT, "%s %d\n", name, texnum); + Sys_MaskPrintf (SYS_GLT, "%s %d\n", name->str, texnum); skindesc->texnum = texnum; skindesc->fb_texnum = fb_texnum; loadmodel->hasfullbrights = fb_texnum; + dstring_delete (name); // alpha param was true for non group skins return skin + skinsize; } @@ -151,10 +152,11 @@ Mod_LoadExternalSkin (maliasskindesc_t *pskindesc, char *filename) void gl_Mod_LoadExternalSkins (model_t *mod) { - char filename[MAX_QPATH + 4], modname[MAX_QPATH + 4]; + char modname[MAX_QPATH + 4]; int i, j; maliasskindesc_t *pskindesc; maliasskingroup_t *pskingroup; + dstring_t *filename = dstring_new (); QFS_StripExtension (mod->name, modname); @@ -162,16 +164,15 @@ gl_Mod_LoadExternalSkins (model_t *mod) pskindesc = ((maliasskindesc_t *) ((byte *) pheader + pheader->skindesc)) + i; if (pskindesc->type == ALIAS_SKIN_SINGLE) { - snprintf (filename, sizeof (filename), "%s_%i", modname, i); - Mod_LoadExternalSkin (pskindesc, filename); + dsprintf (filename, "%s_%i", modname, i); + Mod_LoadExternalSkin (pskindesc, filename->str); } else { pskingroup = (maliasskingroup_t *) ((byte *) pheader + pskindesc->skin); for (j = 0; j < pskingroup->numskins; j++) { - snprintf (filename, sizeof (filename), "%s_%i_%i", - modname, i, j); - Mod_LoadExternalSkin (pskingroup->skindescs + j, filename); + dsprintf (filename, "%s_%i_%i", modname, i, j); + Mod_LoadExternalSkin (pskingroup->skindescs + j, filename->str); } } } diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 18744a529..1485fdd94 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -55,11 +55,11 @@ void gl_Mod_ProcessTexture (texture_t *tx) { - char name[32]; + const char *name; if (!strncmp (tx->name, "sky", 3)) return; - snprintf (name, sizeof (name), "fb_%s", tx->name); + name = va ("fb_%s", tx->name); tx->gl_fb_texturenum = Mod_Fullbright ((byte *) (tx + 1), tx->width, tx->height, name); tx->gl_texturenum = diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 931575534..dd43c1dc8 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -42,6 +42,7 @@ #include "QF/checksum.h" #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/model.h" #include "QF/qendian.h" #include "QF/quakefs.h" @@ -132,25 +133,28 @@ Mod_LeafPVS (mleaf_t *leaf, model_t *model) static void mod_unique_miptex_name (texture_t **textures, texture_t *tx, int ind) { - char name[17]; + char *name; int num = 0, i; - const char *tag; + dstring_t *tag = 0; - strncpy (name, tx->name, 16); - name[16] = 0; + name = tx->name; do { for (i = 0; i < ind; i++) if (textures[i] && !strcmp (textures[i]->name, tx->name)) break; if (i == ind) break; - tag = va ("~%x", num++); - strncpy (tx->name, name, 16); - if (strlen (name) + strlen (tag) <= 15) - strcat (tx->name, tag); - else - strcpy (tx->name + 15 - strlen (tag), tag); + if (!tag) { + tag = dstring_new (); + } + dsprintf (tag, "%s~%x", name, num++); + tx->name = tag->str; } while (1); + + if (tag) { + tx->name = dstring_freeze (tag); + free(name); + } } static void @@ -188,7 +192,7 @@ Mod_LoadTextures (bsp_t *bsp) loadmodel->textures[i] = tx; - memcpy (tx->name, mt->name, sizeof (tx->name)); + tx->name = strndup(mt->name, sizeof (mt->name)); mod_unique_miptex_name (loadmodel->textures, tx, i); tx->width = mt->width; tx->height = mt->height; diff --git a/libs/models/gl_model_fullbright.c b/libs/models/gl_model_fullbright.c index f556c5dd7..3417b6646 100644 --- a/libs/models/gl_model_fullbright.c +++ b/libs/models/gl_model_fullbright.c @@ -59,7 +59,7 @@ Mod_CalcFullbright (byte *in, byte *out, int pixels) } int -Mod_Fullbright (byte *skin, int width, int height, char *name) +Mod_Fullbright (byte *skin, int width, int height, const char *name) { byte *ptexels; int pixels; diff --git a/libs/util/pakfile.c b/libs/util/pakfile.c index 5ddbbb9a2..9cfcb9924 100644 --- a/libs/util/pakfile.c +++ b/libs/util/pakfile.c @@ -161,7 +161,7 @@ pack_create (const char *name) pack_del (pack); return 0; } - strncpy (pack->header.id, "PACK", sizeof (pack->header.id)); + memcpy (pack->header.id, "PACK", sizeof (pack->header.id)); Qwrite (pack->handle, &pack->header, sizeof (pack->header)); diff --git a/libs/util/wadfile.c b/libs/util/wadfile.c index d5bf7c7fd..3175f22c7 100644 --- a/libs/util/wadfile.c +++ b/libs/util/wadfile.c @@ -182,7 +182,7 @@ wad_create (const char *name) wad_del (wad); return 0; } - strncpy (wad->header.id, "WAD2", sizeof (wad->header.id)); + memcpy (wad->header.id, "WAD2", sizeof (wad->header.id)); Qwrite (wad->handle, &wad->header, sizeof (wad->header)); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index f988ddf66..6cebda1fb 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -256,7 +256,8 @@ gl_Draw_CachePic (const char *path, qboolean alpha) } else Sys_Error ("Draw_CachePic: failed to load %s", path); - strncpy (pic->name, path, sizeof (pic->name)); + memset (pic->name, 0, sizeof (pic->name)); + strncpy (pic->name, path, sizeof (pic->name) - 1); // Now lets mark this cache entry as used.. pic->dirty = false; diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 026c59fbb..3b0a1a803 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -56,15 +56,15 @@ typedef struct { double fps; } td_stats_t; -int demo_timeframes_isactive; -int demo_timeframes_index; -char demoname[1024]; -double *demo_timeframes_array; +static int demo_timeframes_isactive; +static int demo_timeframes_index; +static dstring_t *demoname; +static double *demo_timeframes_array; #define CL_TIMEFRAMES_ARRAYBLOCK 4096 -int timedemo_count; -int timedemo_runs; -td_stats_t *timedemo_data; +static int timedemo_count; +static int timedemo_runs; +static td_stats_t *timedemo_data; static void CL_FinishTimeDemo (void); static void CL_TimeFrames_DumpLog (void); @@ -450,7 +450,7 @@ CL_StartDemo (void) CL_Disconnect (); // open the demo file - name = dstring_strdup (demoname); + name = dstring_strdup (demoname->str); QFS_DefaultExtension (name, ".dem"); Sys_Printf ("Playing demo from %s.\n", name->str); @@ -499,7 +499,7 @@ CL_PlayDemo_f (void) switch (Cmd_Argc ()) { case 1: - if (!demoname[0]) + if (!demoname->str[0]) goto playdemo_error; // fall through case 2: @@ -519,7 +519,7 @@ playdemo_error: timedemo_runs = timedemo_count = 1; // make sure looped timedemos stop if (Cmd_Argc () > 1) - strncpy (demoname, Cmd_Argv (1), sizeof (demoname)); + dstring_copystr (demoname, Cmd_Argv (1)); CL_StartDemo (); } @@ -627,7 +627,7 @@ CL_TimeDemo_f (void) timedemo_data = 0; } timedemo_data = calloc (timedemo_runs, sizeof (td_stats_t)); - strncpy (demoname, Cmd_Argv (1), sizeof (demoname)); + dstring_copystr (demoname, Cmd_Argv (1)); CL_StartTimeDemo (); timedemo_runs = timedemo_count = max (count, 1); timedemo_data = calloc (timedemo_runs, sizeof (td_stats_t)); @@ -636,6 +636,7 @@ CL_TimeDemo_f (void) void CL_Demo_Init (void) { + demoname = dstring_newstr (); demo_timeframes_isactive = 0; demo_timeframes_index = 0; demo_timeframes_array = NULL; diff --git a/nq/source/sbar.c b/nq/source/sbar.c index e77ff103a..44d911118 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -352,7 +352,7 @@ draw_num (view_t *view, int x, int y, int num, int digits, int color) static inline void draw_smallnum (view_t *view, int x, int y, int n, int packed, int colored) { - char num[4]; + char num[12]; packed = packed != 0; // ensure 0 or 1 diff --git a/qw/include/server.h b/qw/include/server.h index dbda77e12..642f296f8 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -73,7 +73,7 @@ typedef struct { unsigned int model_player_checksum; unsigned int eyes_player_checksum; - char name[64]; // map name + char *name; // map name char modelname[MAX_QPATH]; // maps/.bsp, for model_precache[0] struct model_s *worldmodel; const char *model_precache[MAX_MODELS]; // NULL terminated diff --git a/qw/source/cl_cmd.c b/qw/source/cl_cmd.c index 1b02d4581..a38dbc875 100644 --- a/qw/source/cl_cmd.c +++ b/qw/source/cl_cmd.c @@ -37,12 +37,33 @@ #include "QF/cbuf.h" #include "QF/cmd.h" +#include "QF/dstring.h" #include "QF/msg.h" #include "QF/sys.h" #include "QF/teamplay.h" #include "client.h" +static void +send_say (const char *str) +{ + static dstring_t *teambuf; + const char *s; + + if (!teambuf) { + teambuf = dstring_newstr (); + } + + s = Team_ParseSay (teambuf, Cmd_Args (1)); + if (*s && *s < 32 && *s != 10) { + // otherwise the server would eat leading characters + // less than 32 or greater than 127 + SZ_Print (&cls.netchan.message, "\""); + SZ_Print (&cls.netchan.message, s); + SZ_Print (&cls.netchan.message, "\""); + } else + SZ_Print (&cls.netchan.message, s); +} /* CL_Cmd_ForwardToServer @@ -70,21 +91,10 @@ CL_Cmd_ForwardToServer (void) if (!strcasecmp (Cmd_Argv (0), "say") || !strcasecmp (Cmd_Argv (0), "say_team")) { - const char *s; - - s = Team_ParseSay (Cmd_Args (1)); - if (*s && *s < 32 && *s != 10) { - // otherwise the server would eat leading characters - // less than 32 or greater than 127 - SZ_Print (&cls.netchan.message, "\""); - SZ_Print (&cls.netchan.message, s); - SZ_Print (&cls.netchan.message, "\""); - } else - SZ_Print (&cls.netchan.message, s); - return; + send_say(Cmd_Args (1)); + } else { + SZ_Print (&cls.netchan.message, Cmd_Args (1)); } - - SZ_Print (&cls.netchan.message, Cmd_Args (1)); } } diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 31ce11620..04ccbdf55 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -69,14 +69,14 @@ typedef struct { double fps; } td_stats_t; -int demo_timeframes_isactive; -int demo_timeframes_index; +static int demo_timeframes_isactive; +static int demo_timeframes_index; static int demotime_cached; static float cached_demotime; static byte cached_newtime; -float nextdemotime; -char demoname[1024]; -double *demo_timeframes_array; +static float nextdemotime; +static dstring_t *demoname; +static double *demo_timeframes_array; #define CL_TIMEFRAMES_ARRAYBLOCK 4096 int timedemo_count; @@ -990,12 +990,12 @@ CL_StartDemo (void) int type; // open the demo file - name = dstring_strdup (demoname); + name = dstring_strdup (demoname->str); QFS_DefaultExtension (name, ".mvd"); cls.demofile = QFS_FOpenFile (name->str); if (!cls.demofile) { - dstring_copystr (name, demoname); + dstring_copystr (name, demoname->str); QFS_DefaultExtension (name, ".qwd"); cls.demofile = QFS_FOpenFile (name->str); } @@ -1050,7 +1050,7 @@ CL_PlayDemo_f (void) { switch (Cmd_Argc ()) { case 1: - if (!demoname[0]) + if (!demoname->str[0]) goto playdemo_error; // fall through case 2: @@ -1072,7 +1072,7 @@ playdemo_error: CL_Disconnect (); if (Cmd_Argc () > 1) - strncpy (demoname, Cmd_Argv (1), sizeof (demoname)); + dstring_copystr (demoname, Cmd_Argv (1)); CL_StartDemo (); } @@ -1182,7 +1182,7 @@ CL_TimeDemo_f (void) timedemo_data = 0; } timedemo_data = calloc (timedemo_runs, sizeof (td_stats_t)); - strncpy (demoname, Cmd_Argv (1), sizeof (demoname)); + dstring_copystr (demoname, Cmd_Argv (1)); CL_StartTimeDemo (); timedemo_runs = timedemo_count = max (count, 1); timedemo_data = calloc (timedemo_runs, sizeof (td_stats_t)); @@ -1191,6 +1191,8 @@ CL_TimeDemo_f (void) void CL_Demo_Init (void) { + demoname = dstring_newstr (); + demo_timeframes_isactive = 0; demo_timeframes_index = 0; demo_timeframes_array = NULL; diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 7234c7f51..34490e43e 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -476,7 +476,7 @@ draw_solo (view_t *view) static inline void draw_smallnum (view_t *view, int x, int y, int n, int packed, int colored) { - char num[4]; + char num[12]; packed = packed != 0; // ensure 0 or 1 diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index b9dbb0aec..7d8c894d1 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -341,6 +341,9 @@ SV_SpawnServer (const char *server) so_buffers = sv.signon_buffers; so_sizes = sv.signon_buffer_size; + if (sv.name) { + free (sv.name); + } memset (&sv, 0, sizeof (sv)); sv.recorders = recorders; @@ -363,7 +366,7 @@ SV_SpawnServer (const char *server) SV_NextSignon (); - strcpy (sv.name, server); + sv.name = strdup(server); // load progs to get entity field count which determines how big each // edict is @@ -384,7 +387,6 @@ SV_SpawnServer (const char *server) sv.time = 1.0; - strncpy (sv.name, server, sizeof (sv.name)); snprintf (sv.modelname, sizeof (sv.modelname), "maps/%s.bsp", server); map_cfg (sv.modelname, 0); sv.worldmodel = Mod_ForName (sv.modelname, true); diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 42a313aa6..685dfd0a7 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -1430,7 +1430,7 @@ SV_AddIP_f (void) // FIXME: this should boot any matching clients for (i = 0; i < MAX_CLIENTS; i++) { client_t *cl = &svs.clients[i]; - char text[1024]; + const char *text; const char *typestr; char timestr[1024]; @@ -1461,9 +1461,9 @@ SV_AddIP_f (void) bantime / 60); else strncpy (timestr, "permanently", sizeof (timestr)); - snprintf (text, sizeof (text), "You are %s %s\n%s", - typestr, timestr, type == ft_ban ? "" : - "\nReconnecting won't help..."); + text = va ("You are %s %s\n%s", + typestr, timestr, type == ft_ban ? "" : + "\nReconnecting won't help..."); MSG_ReliableWrite_Begin (&cl->backbuf, svc_centerprint, strlen (text) + 2); MSG_ReliableWrite_String (&cl->backbuf, text); diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index 58fb00bef..54e53d347 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -148,6 +148,20 @@ SV_EndRedirect (void) } #define MAXPRINTMSG 4096 +static int +find_userid (const char *name) +{ + int i; + + for (i = 0; i < MAX_CLIENTS; i++) { + if (!svs.clients[i].state) + continue; + if (!strcmp (svs.clients[i].name, name)) { + return svs.clients[i].userid; + } + } + return 0; +} /* SV_Printf @@ -158,10 +172,11 @@ SV_EndRedirect (void) void SV_Print (const char *fmt, va_list args) { + static dstring_t *premsg; + static dstring_t *msg; + static dstring_t *msg2; static int pending = 0; // partial line being printed - char premsg[MAXPRINTMSG]; - unsigned char msg[MAXPRINTMSG]; - char msg2[MAXPRINTMSG]; + char msg3[MAXPRINTMSG]; time_t mytime = 0; @@ -169,50 +184,42 @@ SV_Print (const char *fmt, va_list args) qboolean timestamps = false; char *in; - unsigned char *out; - vsnprintf (premsg, sizeof (premsg), fmt, args); - in = premsg; - out = msg; + if (!premsg) { + premsg = dstring_newstr (); + msg = dstring_new (); + msg2 = dstring_new (); + } + dstring_clearstr (msg); - if (!*premsg) + dvsprintf (premsg, fmt, args); + in = premsg->str; + + if (!*premsg->str) return; // expand FFnickFF to nick do { - switch ((byte) *in) { - case 0xFF: { - char *end = strchr (in + 1, 0xFF); - int userid = 0; - int len; - int i; - - if (!end) - end = in + strlen (in); - *end = '\0'; - for (i = 0; i < MAX_CLIENTS; i++) { - if (!svs.clients[i].state) - continue; - if (!strcmp (svs.clients[i].name, in + 1)) { - userid = svs.clients[i].userid; - break; - } - } - len = snprintf ((char *) out, sizeof (msg) - (out - msg), - "%s <%d>", in + 1, userid); - out += len; - in = end + 1; - break; + char *beg = strchr (in, 0xFF); + if (beg) { + char *name = beg + 1; + char *end = strchr (name, 0xFF); + if (!end) { + end = beg + strlen (name); } - default: - *out++ = *in++; + *end = 0; + dstring_appendsubstr (msg, in, beg - in); + dasprintf (msg, "%s <%d>", name, find_userid (name)); + in = end + 1; + } else { + dstring_appendstr (msg, in); + break; } - } while (sizeof (msg) - (out - msg) > 0 && *in); - *out = '\0'; + } while (*in); if (sv_redirected) { // Add to redirected message - dstring_appendstr (&outputbuf, (char *) msg); + dstring_appendstr (&outputbuf, msg->str); } - if (*msg && !con_printf_no_log) { + if (*msg->str && !con_printf_no_log) { // We want to output to console and maybe logfile if (sv_timestamps && sv_timefmt && sv_timefmt->string && sv_timestamps->int_val && !pending) @@ -223,17 +230,17 @@ SV_Print (const char *fmt, va_list args) local = localtime (&mytime); strftime (msg3, sizeof (msg3), sv_timefmt->string, local); - snprintf (msg2, sizeof (msg2), "%s%s", msg3, msg); + dsprintf (msg2, "%s%s", msg3, msg->str); } else { - snprintf (msg2, sizeof (msg2), "%s", msg); + dsprintf (msg2, "%s", msg->str); } - if (msg2[strlen (msg2) - 1] != '\n') { + if (msg2->str[strlen (msg2->str) - 1] != '\n') { pending = 1; } else { pending = 0; } - Con_Printf ("%s", msg2); // also echo to debugging console + Con_Printf ("%s", msg2->str); // also echo to debugging console } } diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index 513fdd4f7..538dc0f1d 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -117,13 +117,12 @@ Team_BestWeaponImpulse (void) in_impulse = best; } - -const char * -Team_ParseSay (const char *s) +//FIXME slow use of dstring +const char * +Team_ParseSay (dstring_t *buf, const char *s) { - char chr, t2[128], t3[128]; + char chr, t2[128], t3[2]; const char *t1; - static char buf[1024]; size_t i, bracket; static location_t *location = NULL; @@ -213,8 +212,9 @@ Team_ParseSay (const char *s) snprintf (t2, sizeof (t2), "%sa:%i", t3, cl.stats[STAT_ARMOR]); - } else + } else { snprintf (t2, sizeof (t2), "%i", cl.stats[STAT_ARMOR]); + } break; case 'A': bracket = 0; @@ -254,29 +254,24 @@ Team_ParseSay (const char *s) t1 = t2; } - if (bracket) - buf[i++] = 0x90; // '[' - - if (t1) { - int len; - - len = strlen (t1); - if (i + len >= sizeof (buf)) - continue; // No more space in buffer, icky. - strncpy (buf + i, t1, len); - i += len; + if (bracket) { + dstring_appendstr (buf, "\x90"); // '[' } - if (bracket) - buf[i++] = 0x91; // ']' + if (t1) { + dstring_appendstr (buf, t1); + } + + if (bracket) { + dstring_appendstr (buf, "\x91"); // ']' + } continue; } - buf[i++] = *s++; + dstring_appendsubstr (buf, s++, 1); } - buf[i] = 0; - return buf; + return buf->str; } void diff --git a/tools/qfspritegen/spritegen.c b/tools/qfspritegen/spritegen.c index b209650d4..5234adc0c 100644 --- a/tools/qfspritegen/spritegen.c +++ b/tools/qfspritegen/spritegen.c @@ -27,6 +27,7 @@ #include #include +#include "QF/dstring.h" #include "QF/image.h" #include "QF/pcx.h" #include "QF/qendian.h" @@ -42,8 +43,8 @@ tex_t *image; dsprite_t sprite; byte *lumpbuffer, *plump; -char spritedir[1024]; -char spriteoutname[1024]; +dstring_t *spritedir; +dstring_t *spriteoutname; int framesmaxs[2]; int framecount; @@ -444,7 +445,7 @@ Cmd_Spritename (void) FinishSprite (); Script_GetToken (&scr, false); - sprintf (spriteoutname, "%s%s.spr", spritedir, Script_Token (&scr)); + dsprintf (spriteoutname, "%s%s.spr", spritedir->str, Script_Token (&scr)); memset (&sprite, 0, sizeof(sprite)); framecount = 0; @@ -472,14 +473,14 @@ FinishSprite (void) if (sprite.numframes == 0) Sys_Error ("no frames\n"); - if (!strlen(spriteoutname)) + if (!spriteoutname->str) Sys_Error ("Didn't name sprite file"); if ((plump - lumpbuffer) > MAX_BUFFER_SIZE) Sys_Error ("Sprite package too big; increase MAX_BUFFER_SIZE"); - spriteouthandle = Qopen (spriteoutname, "wb"); - printf ("saving in %s\n", spriteoutname); + spriteouthandle = Qopen (spriteoutname->str, "wb"); + printf ("saving in %s\n", spriteoutname->str); WriteSprite (spriteouthandle); Qclose (spriteouthandle); @@ -487,7 +488,7 @@ FinishSprite (void) printf ("%d frame(s)\n", sprite.numframes); printf ("%d ungrouped frame(s), including group headers\n", framecount); - spriteoutname[0] = 0; // clear for a new sprite + dstring_clearstr (spriteoutname); // clear for a new sprite } /* @@ -505,6 +506,9 @@ int main (int argc, char **argv) if (argc != 2) Sys_Error ("usage: spritegen file.qc"); + spritedir = dstring_newstr (); + spriteoutname = dstring_newstr (); + i = 1; //SetQdirFromPath (argv[i]); From 027e76b4c9fbc486f31d29c81be5842d52a21856 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Aug 2018 00:09:20 +0900 Subject: [PATCH 0026/3664] Add a doc block to parse_cpp_line. It took me too long to figure it out :P --- tools/qfcc/source/qfcc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index fdf455b5d..e53cdc077 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -589,6 +589,14 @@ load_file (const char *fname) return src; } +/** Parse a cpp line number directive. + + Parses a cpp line directive of the form "# 1 file", setting the line and + file fields of \a script. "#line 1 file" is supported, too. + + \param script the script being parsed + \param filename storage for the parsed filename +*/ static void parse_cpp_line (script_t *script, dstring_t *filename) { From 5dbb7b6d4de6c93385da545a8b2150b16bc2d6f1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Aug 2018 00:11:02 +0900 Subject: [PATCH 0027/3664] Handle all modelgen commands. Just in case someone ever adds models.qc to progs.src. --- tools/qfcc/source/grab.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/grab.c b/tools/qfcc/source/grab.c index 03edaa41a..520c40492 100644 --- a/tools/qfcc/source/grab.c +++ b/tools/qfcc/source/grab.c @@ -69,12 +69,17 @@ static frame_t *frame_list; static frame_t **frame_tail = &frame_list; static frame_t grab_list[] = { - {0, "cd", 0}, - {0, "origin", 0}, - {0, "base", 0}, - {0, "flags", 0}, - {0, "scale", 0}, - {0, "skin", 0}, + {0, "modelname", 0}, + {0, "base", 0}, + {0, "cd", 0}, + {0, "sync", 0}, + {0, "origin", 0}, + {0, "eyeposition", 0}, + {0, "scale", 0}, + {0, "flags", 0}, + {0, "skin", 0}, + {0, "framegroupstart", 0}, + {0, "skingroupstart", 0}, }; static const char * From fbdf560a7aebba62c82d0ee1cabf458fb32ab0b6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Aug 2018 15:55:11 +0900 Subject: [PATCH 0028/3664] Rename print_extra_live to print_flow_vars. --- tools/qfcc/source/dot_flow.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 7c8357611..96dc33cb5 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -197,7 +197,7 @@ print_flow_node_live (dstring_t *dstr, flowgraph_t *graph, flownode_t *node, } static void -print_extra_live (dstring_t *dstr, flowgraph_t *graph, int level) +print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) { int indent = level * 2 + 2; int i; @@ -208,8 +208,9 @@ print_extra_live (dstring_t *dstr, flowgraph_t *graph, int level) "cellspacing=\"0\">\n", indent + 2, ""); for (i = 0; i < graph->func->num_vars; i++) { var = graph->func->vars[i]; - dasprintf (dstr, "%*s(%d) %s\n", indent + 4, "", - var->number, html_string(operand_string (var->op))); + dasprintf (dstr, "%*s(%d) %s %s\n", indent + 4, "", + var->number, html_string(operand_string (var->op)), + set_as_string (var->define)); } dasprintf (dstr, "%*s>];\n", indent + 2, ""); } @@ -299,7 +300,7 @@ print_flow_edge_statements (dstring_t *dstr, flowgraph_t *graph, static flow_dot_t flow_dot_methods[] = { {"", print_flow_node, print_flow_edge}, {"dag", print_flow_node_dag, print_flow_edge_dag}, - {"live", print_flow_node_live, print_flow_edge, print_extra_live}, + {"live", print_flow_node_live, print_flow_edge, print_flow_vars}, {"reaching", print_flow_node_reaching, print_flow_edge}, {"statements", print_flow_node_statements, print_flow_edge_statements}, }; From 5ba13d759b5100db332df16374e5fdd3900da916 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Aug 2018 15:56:03 +0900 Subject: [PATCH 0029/3664] Fix a FIXME. Set of everything got added shortly after that FIXME was added, but I forgot to fix it. --- tools/qfcc/source/flow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index c611fd0a8..39fd7f862 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -838,7 +838,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, flow_add_op_var (use, s->opc); } if (kill) { - //FIXME set of everything + set_everything (kill); } if (operands) { if (!strcmp (s->opcode, "")) From 1b84ea747c79b6d7c873d26103035cff1d62bd52 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Aug 2018 15:56:39 +0900 Subject: [PATCH 0030/3664] Dump statements during flow analysis. --- tools/qfcc/include/options.h | 1 + tools/qfcc/source/flow.c | 2 ++ tools/qfcc/source/options.c | 3 +++ 3 files changed, 6 insertions(+) diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index 4377dab97..b66d9b19a 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -77,6 +77,7 @@ typedef struct { qboolean final; qboolean dags; qboolean expr; + qboolean statements; qboolean reaching; qboolean live; qboolean flow; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 39fd7f862..45dcbf5c9 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1262,6 +1262,8 @@ flow_data_flow (function_t *func) flow_build_statements (func); flow_build_vars (func); graph = flow_build_graph (func); + if (options.block_dot.statements) + dump_dot ("statements", graph, dump_dot_flow_statements); flow_reaching_defs (graph); if (options.block_dot.reaching) dump_dot ("reaching", graph, dump_dot_flow_reaching); diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 4edb03623..a0e7f83a9 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -411,6 +411,8 @@ DecodeArgs (int argc, char **argv) options.block_dot.flow = flag; } else if (!(strcasecmp (temp, "reaching"))) { options.block_dot.reaching = flag; + } else if (!(strcasecmp (temp, "statements"))) { + options.block_dot.statements = flag; } else if (!(strcasecmp (temp, "live"))) { options.block_dot.live = flag; } else if (!(strcasecmp (temp, "post"))) { @@ -428,6 +430,7 @@ DecodeArgs (int argc, char **argv) options.block_dot.expr = true; options.block_dot.flow = true; options.block_dot.reaching = true; + options.block_dot.statements = true; options.block_dot.live = true; options.block_dot.post = true; } From 0f279cd3f0b9f69a91040f04672f28395c3c6df9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Aug 2018 15:57:51 +0900 Subject: [PATCH 0031/3664] Add a comment about fake statement numbers. I had forgotten how they worked (not surprising after 6 years). --- tools/qfcc/source/flow.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 45dcbf5c9..2b45708cc 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -377,6 +377,17 @@ flow_build_vars (function_t *func) set_add (func->global_vars, i); } // create dummy defs for local vars + // defined local vars add their address in local space to the number of + // statements in the function: + // ([num_statements ... num_statements+localsize]) + // with a set element for each def used in the local space + // + // temporary vars add their var number to the size of the local space + // before adding the number of statements in the function: + // ([num_statements+localsize ... num_vars]) + // temporary vars are always accessed as a full var, so only one set + // element per temporary var is needed. This can lead to holes in the + // temporary var set element space, but it does keep things simple for (i = 0; i < func->num_vars; i++) { int offset, size; int j; From f2500650033e2c0aa94d9d3ff517037db481cda3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Aug 2018 16:27:22 +0900 Subject: [PATCH 0032/3664] Add tests for swapping vars and triangle area. Triangle area was meant just to check Kahan's equation, but it found a problem with swapping vars. swap.r currently fails. --- tools/qfcc/test/Makefile.am | 18 +++++++++++++++++- tools/qfcc/test/build-run | 2 +- tools/qfcc/test/swap.r | 15 +++++++++++++++ tools/qfcc/test/triangle.r | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 tools/qfcc/test/swap.r create mode 100644 tools/qfcc/test/triangle.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index c4302f32f..f177d5b9b 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -32,6 +32,8 @@ test_progs_dat=\ state.dat \ structlive.dat \ structptr.dat \ + swap.dat \ + triangle.dat \ vecinit.dat \ while.dat \ voidfor.dat @@ -139,6 +141,20 @@ structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) structptr.run: Makefile build-run $(srcdir)/build-run $@ +swap_dat_SOURCES=swap.r +swap_obj=$(swap_dat_SOURCES:.r=.qfo) +swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(swap_obj) +swap.run: Makefile build-run + $(srcdir)/build-run $@ + +triangle_dat_SOURCES=triangle.r +triangle_obj=$(triangle_dat_SOURCES:.r=.qfo) +triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) +triangle.run: Makefile build-run + $(srcdir)/build-run $@ 1 2 3 + vecinit_dat_SOURCES=vecinit.r vecinit_obj=$(vecinit_dat_SOURCES:.r=.qfo) vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) @@ -163,4 +179,4 @@ voidfor.run: Makefile build-run include ./$(DEPDIR)/*.Qo EXTRA_DIST= test-bi.h build-run -CLEANFILES= *.dat *.sym *.qfo *.run +CLEANFILES= *.dat *.sym *.qfo *.run *.frame diff --git a/tools/qfcc/test/build-run b/tools/qfcc/test/build-run index ddee2ee77..577355a80 100755 --- a/tools/qfcc/test/build-run +++ b/tools/qfcc/test/build-run @@ -6,6 +6,6 @@ shift cat > $script < 0 ? 0 : 1; +} diff --git a/tools/qfcc/test/triangle.r b/tools/qfcc/test/triangle.r new file mode 100644 index 000000000..d2bf03d4b --- /dev/null +++ b/tools/qfcc/test/triangle.r @@ -0,0 +1,32 @@ +void printf (string fmt, ...) = #0; +float (string s) stof = #0; +float (float x) sqrt = #0; + +float +heron (float a, float b, float c) +{ + float s = (a + b + c) / 2; + return sqrt (s*(s-a)*(s-b)*(s-c)); +} + +float +kahan (float a, float b, float c) +{ + float t; + if (a < b) { t = a; a = b; b = t; } + if (b < c) { t = b; b = c; c = t; } + if (a < b) { t = a; a = b; b = t; } + printf ("%f %f %f\n", a, b, c); + return sqrt ((a+(b+c))*(c-(a-b))*(c+(a-b))*(a+(b-c)))/4; +} + +int +main (int argc, string *argv) +{ + float a = stof(argv[1]); + float b = stof(argv[2]); + float c = stof(argv[3]); + printf ("%.9g %.9g %.9g\n", a, b, c); + printf ("%.9g %.9g\n", heron (a, b, c), kahan (a, b, c)); + return 0; +} From 8b8b42bde274a91c984d8586d72645f434bf01fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Aug 2018 20:04:51 +0900 Subject: [PATCH 0033/3664] Fix a typo in a comment. --- tools/qfcc/include/dags.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index 21ac8c943..7b624ea2e 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -60,7 +60,7 @@ typedef struct dagnode_s { struct set_s *parents; ///< empty if root node int cost; ///< cost of this node in temp vars unsigned killed:1; ///< node is unavailable for cse - st_type_t type; ///< type of node (st_node = leaf) + st_type_t type; ///< type of node (st_none = leaf) daglabel_t *label; ///< ident/const if leaf node, or operator etype_t tl; struct operand_s *value; ///< operand holding the value of this node From cdbdf3f0eb7880be0c0f5dd9689bca3e8d4928a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Aug 2018 20:05:16 +0900 Subject: [PATCH 0034/3664] Make print_operand global. --- tools/qfcc/include/statements.h | 1 + tools/qfcc/source/statements.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 75be49d79..565cc9295 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -133,6 +133,7 @@ void sblock_add_statement (sblock_t *sblock, statement_t *statement); sblock_t *make_statements (struct expr_s *expr); void statements_count_temps (sblock_t *sblock); +void print_operand (operand_t *op); void print_statement (statement_t *s); void dump_dot_sblock (void *data, const char *fname); void dot_sblock (struct dstring_s *dstr, sblock_t *sblock, int blockno); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index f331a39f0..7c0fb693f 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -144,7 +144,7 @@ operand_string (operand_t *op) return ("??"); } -static void +void print_operand (operand_t *op) { switch (op->op_type) { From cb366dd825a1db3dedd47115882b8fd62af80e75 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Aug 2018 20:07:11 +0900 Subject: [PATCH 0035/3664] Better flow dot dump "scripting". Not sure I want to keep the statements in the live dump, but the system is more flexible now. --- tools/qfcc/source/dot_flow.c | 82 +++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 96dc33cb5..d702f7b9e 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -51,11 +51,15 @@ #include "statements.h" #include "strpool.h" +typedef struct { + void (*node) (dstring_t *, flowgraph_t *, flownode_t *, int); + void (*edge) (dstring_t *, flowgraph_t *, flowedge_t *, int); + void (*extra) (dstring_t *, flowgraph_t *, int); +} flow_print_t; + typedef struct { const char *type; - void (*print_node) (dstring_t *, flowgraph_t *, flownode_t *, int); - void (*print_edge) (dstring_t *, flowgraph_t *, flowedge_t *, int); - void (*print_extra) (dstring_t *, flowgraph_t *, int); + flow_print_t *print; } flow_dot_t; static void @@ -177,23 +181,17 @@ print_flow_node_live (dstring_t *dstr, flowgraph_t *graph, flownode_t *node, int level) { int indent = level * 2 + 2; - int live; set_t *use = node->live_vars.use; set_t *def = node->live_vars.def; set_t *in = node->live_vars.in; set_t *out = node->live_vars.out; - live = node->live_vars.out && !set_is_empty (node->live_vars.out); - - if (live) { - dasprintf (dstr, "%*sfn_%p [label=\"", indent, "", node); - dasprintf (dstr, "use: %s\\n", set_as_string (use)); - dasprintf (dstr, "def: %s\\n", set_as_string (def)); - dasprintf (dstr, "in: %s\\n", set_as_string (in)); - dasprintf (dstr, "out: %s\"];\n", set_as_string (out)); - } else { - print_flow_node (dstr, graph, node, level); - } + dasprintf (dstr, "%*sfn_%p [label=\"", indent, "", node); + dasprintf (dstr, "use: %s\\n", set_as_string (use)); + dasprintf (dstr, "def: %s\\n", set_as_string (def)); + dasprintf (dstr, "in: %s\\n", set_as_string (in)); + dasprintf (dstr, "out: %s", set_as_string (out)); + dasprintf (dstr, "\"];\n"); } static void @@ -297,12 +295,34 @@ print_flow_edge_statements (dstring_t *dstr, flowgraph_t *graph, dasprintf (dstr, "];\n"); } +static flow_print_t null_print[] = { + { print_flow_node, print_flow_edge }, + { 0 } +}; +static flow_print_t dag_print[] = { + { print_flow_node_dag, print_flow_edge_dag}, + { 0 } +}; +static flow_print_t live_print[] = { + { print_flow_node_live, print_flow_edge, print_flow_vars}, + { print_flow_node_statements, print_flow_edge_statements}, + { 0 } +}; +static flow_print_t reaching_print[] = { + { print_flow_node_reaching, print_flow_edge}, + { 0 } +}; +static flow_print_t statements_print[] = { + { print_flow_node_statements, print_flow_edge_statements}, + { 0 } +}; + static flow_dot_t flow_dot_methods[] = { - {"", print_flow_node, print_flow_edge}, - {"dag", print_flow_node_dag, print_flow_edge_dag}, - {"live", print_flow_node_live, print_flow_edge, print_flow_vars}, - {"reaching", print_flow_node_reaching, print_flow_edge}, - {"statements", print_flow_node_statements, print_flow_edge_statements}, + {"", null_print}, + {"dag", dag_print}, + {"live", live_print}, + {"reaching", reaching_print}, + {"statements", statements_print}, }; static void @@ -316,17 +336,19 @@ print_flowgraph (flow_dot_t *method, flowgraph_t *graph, const char *filename) dasprintf (dstr, " clusterrank=local;\n"); dasprintf (dstr, " rankdir=TB;\n"); dasprintf (dstr, " compound=true;\n"); - for (i = 0; i < graph->num_nodes; i++) { - method->print_node (dstr, graph, graph->nodes[i], 0); + for (flow_print_t *print = method->print; print->node; print++) { + for (i = 0; i < graph->num_nodes; i++) { + print->node (dstr, graph, graph->nodes[i], 0); + } + for (i = 0; i < graph->num_edges; i++) { + if ((int) graph->edges[i].head >= graph->num_nodes + || (int) graph->edges[i].tail >= graph->num_nodes) + continue; // dummy node + print->edge (dstr, graph, &graph->edges[i], 0); + } + if (print->extra) + print->extra (dstr, graph, 0); } - for (i = 0; i < graph->num_edges; i++) { - if ((int) graph->edges[i].head >= graph->num_nodes - || (int) graph->edges[i].tail >= graph->num_nodes) - continue; // dummy node - method->print_edge (dstr, graph, &graph->edges[i], 0); - } - if (method->print_extra) - method->print_extra (dstr, graph, 0); dasprintf (dstr, "}\n"); if (filename) { From 2fcda44ab081ec4425d6f54923109bfd5131bd57 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Aug 2018 20:07:22 +0900 Subject: [PATCH 0036/3664] Kill dag leaf nodes on assignment. Fixes the failing swap test caused by a's original value being used (via t) after being written. --- tools/qfcc/source/dags.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 95c99d10a..5daf3060e 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -475,6 +475,11 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l) internal_error (0, "attempt to attach non-identifer label to dagnode " "identifiers"); if (l->dagnode) { + // if the node is a leaf, then kill its value so no attempt is made + // to reuse it. + if (l->dagnode->type == st_none) { + l->dagnode->killed = 1; + } dagnode_t *node = l->dagnode; set_union (n->edges, node->parents); set_remove (n->edges, n->number); From 1b9149ef31bee1aa1546bcb85d83a8b0322a3dc5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Aug 2018 20:22:29 +0900 Subject: [PATCH 0037/3664] Fix an argument passing error in test-harness. It failed to pass the last argument to the ruamoko program being run. --- tools/qfcc/test/test-harness.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 87cd26c55..b364a7f0c 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -242,11 +242,11 @@ main (int argc, char **argv) PR_PushFrame (&pr); if (argc > 2) - pr_argc = argc - 1; + pr_argc = argc; pr_argv = PR_Zone_Malloc (&pr, (pr_argc + 1) * 4); pr_argv[0] = PR_SetTempString (&pr, name); for (i = 1; i < pr_argc; i++) - pr_argv[i] = PR_SetTempString (&pr, argv[1 + i]); + pr_argv[i] = PR_SetTempString (&pr, argv[i]); pr_argv[i] = 0; if ((dfunc = PR_FindFunction (&pr, ".main")) From b37b0180cb1171d2ca03a0518d1cb5e8178f0d20 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Aug 2018 20:50:06 +0900 Subject: [PATCH 0038/3664] Actually do a test for triangle.r. If the kahan triangle area method breaks, I did something wrong with qfcc's handling of parentheses (ie, floating point math is not truly associative). --- tools/qfcc/test/Makefile.am | 2 +- tools/qfcc/test/triangle.r | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index f177d5b9b..9bb48d112 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -153,7 +153,7 @@ triangle_obj=$(triangle_dat_SOURCES:.r=.qfo) triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) triangle.run: Makefile build-run - $(srcdir)/build-run $@ 1 2 3 + $(srcdir)/build-run $@ 100000 100000 1.00005 50002.4961 vecinit_dat_SOURCES=vecinit.r vecinit_obj=$(vecinit_dat_SOURCES:.r=.qfo) diff --git a/tools/qfcc/test/triangle.r b/tools/qfcc/test/triangle.r index d2bf03d4b..6ef592ace 100644 --- a/tools/qfcc/test/triangle.r +++ b/tools/qfcc/test/triangle.r @@ -16,17 +16,18 @@ kahan (float a, float b, float c) if (a < b) { t = a; a = b; b = t; } if (b < c) { t = b; b = c; c = t; } if (a < b) { t = a; a = b; b = t; } - printf ("%f %f %f\n", a, b, c); - return sqrt ((a+(b+c))*(c-(a-b))*(c+(a-b))*(a+(b-c)))/4; + return sqrt ((a + (b + c))*(c - (a - b))*(c + (a - b))*(a + (b - c)))/4; } int main (int argc, string *argv) { - float a = stof(argv[1]); - float b = stof(argv[2]); - float c = stof(argv[3]); - printf ("%.9g %.9g %.9g\n", a, b, c); - printf ("%.9g %.9g\n", heron (a, b, c), kahan (a, b, c)); - return 0; + float a = stof (argv[1]); + float b = stof (argv[2]); + float c = stof (argv[3]); + float expt = stof (argv[4]); + float h = heron (a, b, c); + float k = kahan (a, b, c); + printf ("%.9g %.9g %d\n", h, k, k == expt); + return k != expt; } From 89daf15215586be13983ce3c3bb0f462668e59f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Aug 2018 15:05:13 +0900 Subject: [PATCH 0039/3664] Fix a c&p error in a doc comment. --- include/QF/vrect.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/vrect.h b/include/QF/vrect.h index 4c0cba107..bb0f99061 100644 --- a/include/QF/vrect.h +++ b/include/QF/vrect.h @@ -100,7 +100,7 @@ vrect_t *VRect_Intersect (const vrect_t *r1, const vrect_t *r2); vrect_t *VRect_HSplit (const vrect_t *r, int y); /** Return two rectangles representing the portions of \a r to the left and - right of \a y. + right of \a x. One of the returned rectangles may be empty. Use VRect_IsEmpty to check. The first rectangle represents the portion of \a r that is to the left of @@ -111,7 +111,7 @@ vrect_t *VRect_HSplit (const vrect_t *r, int y); \param r The rectangle to split. \param x The vertical line by which \a r will be split. \return The two linked rectangles representing the portions to the - left and right of \a y. The returned pointer points to the + left and right of \a x. The returned pointer points to the first (left) rectangle, which links to the second (right) rectangle. \note It is the caller's responsibility to delete the returned From 575a67b2a142b3f280805815ecd3b9f7fbcbee28 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Aug 2018 15:06:08 +0900 Subject: [PATCH 0040/3664] mat4 test case fixes. The tests cases themselves were buggy. --- libs/util/test/test-mat4.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/libs/util/test/test-mat4.c b/libs/util/test/test-mat4.c index 623444a0d..1bd7afcc9 100644 --- a/libs/util/test/test-mat4.c +++ b/libs/util/test/test-mat4.c @@ -58,8 +58,8 @@ static vec3_t test_scales[] = { { 3, 1, 2}, { 3, 2, 1}, }; -#define num_translation_tests \ - (sizeof (test_translations) / sizeof (test_translations[0])) +#define num_scale_tests \ + (sizeof (test_scales) / sizeof (test_scales[0])) // return true if a and b are close enough (yay, floats) static int @@ -143,7 +143,8 @@ test_transform2 (const vec3_t angles, const vec3_t scale, vec3_t x, y; quat_t rotation; mat4_t mat; - vec3_t rot, sc, sh, tr; + quat_t rot; + vec3_t sc, sh, tr; VectorCopy (v, x); AngleQuat (angles, rotation); @@ -171,6 +172,9 @@ fail: VectorExpand (translation), VectorExpand (v)); printf (" (%g %g %g)\n", VectorExpand (x)); printf (" (%g %g %g)\n", VectorExpand (y)); + printf (" (%g %g %g %g) (%g %g %g %g) (%g %g %g) (%g %g %g) (%g %g %g)\n", + QuatExpand (rotation), QuatExpand (rot), VectorExpand (sh), + VectorExpand (sc), VectorExpand (tr)); return 0; } @@ -214,33 +218,41 @@ main (int argc, const char **argv) size_t i, j, k; for (i = 0; i < num_angle_tests; i ++) { - if (!test_angle (test_angles[i])) + if (!test_angle (test_angles[i])) { res = 1; + printf("angle test %zd failed\n", i); + } } for (i = 0; i < num_angle_tests; i ++) { - for (j = 0; j < num_translation_tests; j ++) { + for (j = 0; j < num_scale_tests; j ++) { for (k = 0; k < num_translation_tests; k ++) { if (!test_transform (test_angles[i], test_scales[j], - test_translations[k])) + test_translations[k])) { res = 1; + printf("transform test %zd:%zd:%zd failed\n", i, j, k); + } } } } for (i = 0; i < num_angle_tests; i ++) { - for (j = 0; j < num_translation_tests; j ++) { + for (j = 0; j < num_scale_tests; j ++) { for (k = 0; k < num_translation_tests; k ++) { if (!test_transform2 (test_angles[i], test_scales[j], - test_translations[k])) + test_translations[k])) { res = 1; + printf("transform2 test %zd:%zd:%zd failed\n", i, j, k); + } } } } for (i = 0; i < num_angle_tests; i ++) { - for (j = 0; j < num_translation_tests; j ++) { + for (j = 0; j < num_scale_tests; j ++) { for (k = 0; k < num_translation_tests; k ++) { if (!test_inverse (test_angles[i], test_scales[j], - test_translations[k])) + test_translations[k])) { res = 1; + printf("inverse test %zd:%zd:%zd failed\n", i, j, k); + } } } } From 8fd5be0ee03bd68a36e8cc96118606099ba8ca3c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Sep 2018 20:00:57 +0900 Subject: [PATCH 0041/3664] Fix a pile of sizeof goofs. While scan-build wasn't what I was looking for, it has proven useful anyway: many of the sizeof errors were just noise, but a few were actual bugs (allocating too much or too little memory). --- libs/console/filelist.c | 2 +- libs/gamecode/pr_debug.c | 2 +- libs/gib/gib_classes.c | 2 +- libs/gib/gib_vars.c | 2 +- libs/models/iqm/sw_model_iqm.c | 2 +- libs/util/qargs.c | 2 +- libs/util/riff.c | 2 +- libs/video/renderer/sw32/vid_common_sw32.c | 4 ++-- nq/source/cl_tent.c | 2 +- qtv/source/server.c | 2 +- qw/source/cl_tent.c | 2 +- tools/qfcc/source/class.c | 2 +- tools/qfcc/source/cpp.c | 2 +- tools/qfcc/source/flow.c | 2 +- tools/qfcc/source/switch.c | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libs/console/filelist.c b/libs/console/filelist.c index 73595de82..dd979743a 100644 --- a/libs/console/filelist.c +++ b/libs/console/filelist.c @@ -102,7 +102,7 @@ filelist_print (filelist_t *filelist) if (filelist->count) { qsort (filelist->list, filelist->count, sizeof (char *), filelist_cmp); - list = malloc ((filelist->count + 1) * sizeof (char **)); + list = malloc ((filelist->count + 1) * sizeof (char *)); list[filelist->count] = 0; for (i = 0; i < filelist->count; i++) list[i] = filelist->list[i]; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 602a2cc15..9f5cdc818 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -108,7 +108,7 @@ source_path_f (cvar_t *var) for (i = 2, s = source_path_string; *s; s++) if (*s == ';') i++; - source_paths = malloc (i * sizeof (char **)); + source_paths = malloc (i * sizeof (char *)); source_paths[0] = source_path_string; for (i = 1, s = source_path_string; *s; s++) if (*s == ';') { diff --git a/libs/gib/gib_classes.c b/libs/gib/gib_classes.c index 749e7ff07..8258e7882 100644 --- a/libs/gib/gib_classes.c +++ b/libs/gib/gib_classes.c @@ -445,7 +445,7 @@ ObjectHash_Get_f (gib_object_t *obj, gib_method_t *method, void *data, if ((refs = (ObjRef_t **) Hash_FindList (objh->objects, mesg.argv[1]))) { for (r = refs, len = 0; *r; r++, len++); - reply = malloc (sizeof (char **) * len); + reply = malloc (sizeof (char *) * len); for (r = refs, i = 0; *r; r++, i++) reply[i] = (*r)->obj->handstr; GIB_Reply (obj, mesg, len, reply); diff --git a/libs/gib/gib_vars.c b/libs/gib/gib_vars.c index d8a555673..e8b7f8a3a 100644 --- a/libs/gib/gib_vars.c +++ b/libs/gib/gib_vars.c @@ -51,7 +51,7 @@ GIB_Var_New (const char *key) { gib_var_t *new = calloc (1, sizeof (gib_var_t)); - new->array = calloc (1, sizeof (dstring_t *)); + new->array = calloc (1, sizeof (struct gib_varray_s)); new->key = strdup (key); return new; } diff --git a/libs/models/iqm/sw_model_iqm.c b/libs/models/iqm/sw_model_iqm.c index 2a32ecca0..5b609ca75 100644 --- a/libs/models/iqm/sw_model_iqm.c +++ b/libs/models/iqm/sw_model_iqm.c @@ -153,7 +153,7 @@ sw_iqm_load_textures (iqm_t *iqm) bytes = (iqm->num_verts + 7) / 8; done_verts = alloca (bytes); memset (done_verts, 0, bytes); - sw->skins = malloc (iqm->num_meshes * sizeof (tex_t)); + sw->skins = malloc (iqm->num_meshes * sizeof (tex_t *)); for (i = 0; i < iqm->num_meshes; i++) { for (j = 0; j < i; j++) { if (iqm->meshes[j].material == iqm->meshes[i].material) { diff --git a/libs/util/qargs.c b/libs/util/qargs.c index 5ba36b842..36f23bb69 100644 --- a/libs/util/qargs.c +++ b/libs/util/qargs.c @@ -100,7 +100,7 @@ COM_InitArgv (int argc, const char **argv) safe = false; largv = (const char **) calloc (1, (argc + NUM_SAFE_ARGVS + 1) * - sizeof (const char **)); + sizeof (const char *)); for (com_argc = 0, len = 0; com_argc < argc; com_argc++) { largv[com_argc] = argv[com_argc]; diff --git a/libs/util/riff.c b/libs/util/riff.c index ce3fb2e22..bd7320c96 100644 --- a/libs/util/riff.c +++ b/libs/util/riff.c @@ -161,7 +161,7 @@ read_adtl (dstring_t *list_buf, QFile *f, int len) chunk = &label->ck; break; default: - data = malloc (sizeof (data)); + data = malloc (sizeof (riff_data_t)); data->ck = ck; data->data = read_data (f, ck.len); chunk = &data->ck; diff --git a/libs/video/renderer/sw32/vid_common_sw32.c b/libs/video/renderer/sw32/vid_common_sw32.c index 279ee08d6..943fb2708 100644 --- a/libs/video/renderer/sw32/vid_common_sw32.c +++ b/libs/video/renderer/sw32/vid_common_sw32.c @@ -150,8 +150,8 @@ VID_MakeColormap16 (void *outcolormap, byte *pal) void VID_MakeColormaps (void) { - vid.colormap16 = malloc (256*VID_GRADES * sizeof (short)); - vid.colormap32 = malloc (256*VID_GRADES * sizeof (int)); + vid.colormap16 = malloc (256*VID_GRADES * sizeof (unsigned short)); + vid.colormap32 = malloc (256*VID_GRADES * sizeof (unsigned int)); SYS_CHECKMEM (vid.colormap16 && vid.colormap32); VID_MakeColormap16(vid.colormap16, vid.palette); VID_MakeColormap32(vid.colormap32, vid.palette); diff --git a/nq/source/cl_tent.c b/nq/source/cl_tent.c index 11c5c9fde..8aa7dd2e7 100644 --- a/nq/source/cl_tent.c +++ b/nq/source/cl_tent.c @@ -177,7 +177,7 @@ new_tent_object (void) if (!tent_objects) { int i; - tent_objects = malloc (TEMP_BATCH * sizeof (tent_t)); + tent_objects = malloc (TEMP_BATCH * sizeof (tent_obj_t)); for (i = 0; i < TEMP_BATCH - 1; i++) tent_objects[i].next = &tent_objects[i + 1]; tent_objects[i].next = 0; diff --git a/qtv/source/server.c b/qtv/source/server.c index 6375177a2..c664f36e4 100644 --- a/qtv/source/server.c +++ b/qtv/source/server.c @@ -493,7 +493,7 @@ sv_list_f (void) qtv_printf ("no servers\n"); return; } - list = malloc (count * sizeof (server_t **)); + list = malloc (count * sizeof (server_t *)); for (l = &servers, count = 0; *l; l = &(*l)->next, count++) list[count] = *l; qsort (list, count, sizeof (*list), server_compare); diff --git a/qw/source/cl_tent.c b/qw/source/cl_tent.c index c401defa2..43e5930d0 100644 --- a/qw/source/cl_tent.c +++ b/qw/source/cl_tent.c @@ -181,7 +181,7 @@ new_tent_object (void) if (!tent_objects) { int i; - tent_objects = malloc (TEMP_BATCH * sizeof (tent_t)); + tent_objects = malloc (TEMP_BATCH * sizeof (tent_obj_t)); for (i = 0; i < TEMP_BATCH - 1; i++) tent_objects[i].next = &tent_objects[i + 1]; tent_objects[i].next = 0; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index a7898e5db..6edb3f7da 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1397,7 +1397,7 @@ add_protocol (protocollist_t *protocollist, const char *name) } protocollist->count++; protocollist->list = realloc (protocollist->list, - sizeof (protocol_t) * protocollist->count); + sizeof (protocol_t *) * protocollist->count); protocollist->list[protocollist->count - 1] = protocol; return protocollist; } diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index cfc5de81d..e1c3fb8ce 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -121,7 +121,7 @@ build_cpp_args (const char *in_name, const char *out_name) if (cpp_argv) free (cpp_argv); - cpp_argv = (const char **)malloc ((cpp_argc + 1) * sizeof (char**)); + cpp_argv = (const char **)malloc ((cpp_argc + 1) * sizeof (char *)); for (arg = cpp_argv, cpp_arg = cpp_arg_list; cpp_arg; cpp_arg = cpp_arg->next) { diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 2b45708cc..b23fb1bb0 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -343,7 +343,7 @@ flow_build_vars (function_t *func) if (!num_vars) return; - func->vars = malloc (num_vars * sizeof (daglabel_t *)); + func->vars = malloc (num_vars * sizeof (flowvar_t *)); stuse = set_new (); stdef = set_new (); diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 80321a9ab..718e1ea04 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -213,7 +213,7 @@ new_case_node (expr_t *low, expr_t *high) if (!is_integer_val (low)) internal_error (low, "switch"); size = expr_integer (high) - expr_integer (low) + 1; - node->labels = calloc (size, sizeof (case_node_t *)); + node->labels = calloc (size, sizeof (expr_t *)); } node->left = node->right = 0; return node; From 8f028b8a0da6632a6756b154046bd95e57472f1c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Sep 2018 20:03:19 +0900 Subject: [PATCH 0042/3664] Fix some double frees. --- libs/ruamoko/rua_file.c | 1 + tools/qfcc/source/obj_file.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_file.c b/libs/ruamoko/rua_file.c index 95d21682c..61def0a3f 100644 --- a/libs/ruamoko/rua_file.c +++ b/libs/ruamoko/rua_file.c @@ -166,6 +166,7 @@ bi_File_Open (progs_t *pr) if ((R_INT (pr) = QFile_AllocHandle (pr, file))) return; Qclose (file); + return; error: free (path); R_INT (pr) = 0; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 1c81381f1..b39bea1e7 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -607,7 +607,7 @@ qfo_delete (qfo_t *qfo) } else { int i; for (i = 0; i < qfo->num_spaces; i++) - free (qfo->spaces->d.data); + free (qfo->spaces[i].d.data); free (qfo->relocs); free (qfo->defs); free (qfo->funcs); From 1eb1622420df70485743448336a07d84365e0a8d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Sep 2018 21:27:34 +0900 Subject: [PATCH 0043/3664] Fix some strncat issues. --- libs/video/targets/keys.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libs/video/targets/keys.c b/libs/video/targets/keys.c index ecf3aa4ce..5538f07cb 100644 --- a/libs/video/targets/keys.c +++ b/libs/video/targets/keys.c @@ -850,7 +850,7 @@ Key_In_Bind_f (void) { int c, i; const char *imt, *key, *cmd = 0; - char cmd_buf[1024]; + dstring_t *cmd_buf = 0; c = Cmd_Argc (); @@ -865,17 +865,17 @@ Key_In_Bind_f (void) key = Cmd_Argv (2); if (c >= 4) { - cmd = cmd_buf; - cmd_buf[0] = 0; + cmd_buf = dstring_newstr (); for (i = 3; i < c; i++) { - strncat (cmd_buf, Cmd_Argv (i), sizeof (cmd_buf) - - strlen (cmd_buf)); - if (i != (c - 1)) - strncat (cmd_buf, " ", sizeof (cmd_buf) - strlen (cmd_buf)); + dasprintf (cmd_buf, "%s%s", i > 3 ? " " : "", Cmd_Argv (i)); } + cmd = cmd_buf->str; } Key_In_Bind (imt, key, cmd); + if (cmd_buf) { + dstring_delete (cmd_buf); + } } static void @@ -896,7 +896,7 @@ Key_Bind_f (void) { int c, i; const char *key, *cmd = 0; - char cmd_buf[1024]; + dstring_t *cmd_buf = 0; c = Cmd_Argc (); @@ -908,17 +908,17 @@ Key_Bind_f (void) key = OK_TranslateKeyName (Cmd_Argv (1)); if (c >= 3) { - cmd = cmd_buf; - cmd_buf[0] = 0; + cmd_buf = dstring_newstr (); for (i = 2; i < c; i++) { - strncat (cmd_buf, Cmd_Argv (i), sizeof (cmd_buf) - - strlen (cmd_buf)); - if (i != (c - 1)) - strncat (cmd_buf, " ", sizeof (cmd_buf) - strlen (cmd_buf)); + dasprintf (cmd_buf, "%s%s", i > 2 ? " " : "", Cmd_Argv (i)); } + cmd = cmd_buf->str; } Key_In_Bind ("imt_mod", key, cmd); + if (cmd_buf) { + dstring_delete (cmd_buf); + } } static void From f75ff2d269269b2696f56d67cdb141c1ea693679 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Sep 2018 22:30:44 +0900 Subject: [PATCH 0044/3664] Fix some null argument issues. --- libs/util/qargs.c | 2 +- tools/qfcc/source/cpp.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/util/qargs.c b/libs/util/qargs.c index 36f23bb69..7f385e5a1 100644 --- a/libs/util/qargs.c +++ b/libs/util/qargs.c @@ -106,7 +106,7 @@ COM_InitArgv (int argc, const char **argv) largv[com_argc] = argv[com_argc]; if ((argv[com_argc]) && !strcmp ("-safe", argv[com_argc])) safe = true; - if (com_argc) + if (argv[com_argc]) len += strlen (argv[com_argc]) + 1; } diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index e1c3fb8ce..9bea8741d 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -55,6 +55,7 @@ #include "QF/dstring.h" #include "cpp.h" +#include "diagnostic.h" #include "options.h" typedef struct cpp_arg_s { @@ -205,6 +206,9 @@ preprocess_file (const char *filename, const char *ext) if (cpp_name) { intermediate_file (tempname, filename, ext ? ext : "p", 0); build_cpp_args (filename, tempname->str); + if (!cpp_argv[0]) { + internal_error(0, "cpp_argv[0] is null"); + } #ifdef _WIN32 if (!options.save_temps && !options.preprocess_only) From 59b04dbcca93fd7db7ac44790ee281ec9adfc548 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Sep 2018 19:45:19 +0900 Subject: [PATCH 0045/3664] Make many qfo int fields unsigned. I don't remember why I thought signed was a good idea, but unsigned does make more sense for most fields. --- tools/qfcc/include/obj_file.h | 46 +++++++++++++++--------------- tools/qfcc/source/dump_globals.c | 10 +++---- tools/qfcc/source/linker.c | 49 +++++++++++++++++++------------- tools/qfcc/source/obj_file.c | 20 ++++++------- 4 files changed, 67 insertions(+), 58 deletions(-) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index cd9cd45f6..1fe1d3690 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -83,11 +83,11 @@ typedef enum qfos_type_e { */ typedef struct qfo_space_s { pr_int_t type; ///< code, string, data, entity... - pr_int_t defs; ///< index of first def - pr_int_t num_defs; ///< zero for code or string spaces - pr_int_t data; ///< byte offset in qfo + pr_uint_t defs; ///< index of first def + pr_uint_t num_defs; ///< zero for code or string spaces + pr_uint_t data; ///< byte offset in qfo pr_uint_t data_size; ///< in elements. zero for entity spaces - pr_int_t id; + pr_uint_t id; pr_int_t reserved[2]; } qfo_space_t; @@ -98,13 +98,13 @@ typedef struct qfo_def_s { string_t name; ///< def name pointer_t offset; ///< def offset (address) - pr_int_t relocs; ///< index of first reloc record - pr_int_t num_relocs; ///< number of reloc records + pr_uint_t relocs; ///< index of first reloc record + pr_uint_t num_relocs; ///< number of reloc records pr_uint_t flags; ///< \ref qfcc_qfo_QFOD "QFOD flags" string_t file; ///< source file name - pr_int_t line; ///< source line number + pr_uint_t line; ///< source line number } qfo_def_t; //@} @@ -180,7 +180,7 @@ typedef struct qfo_func_s { string_t name; ///< function name pointer_t type; ///< function type (in type data space) string_t file; ///< source file name - pr_int_t line; ///< source line number + pr_uint_t line; ///< source line number /** \name Function code location. If #code is negative, then the function is a VM builtin function. @@ -191,22 +191,22 @@ typedef struct qfo_func_s { */ pr_int_t code; - pr_int_t def; ///< def that references this function. Index + pr_uint_t def; ///< def that references this function. Index ///< to ::qfo_def_t. The data word pointed to ///< by the def stores the index of this ///< function. - pr_int_t locals_space; ///< space holding the function's local data + pr_uint_t locals_space; ///< space holding the function's local data - pr_int_t line_info; ///< Index to first ::pr_lineno_t line record. + pr_uint_t line_info; ///< Index to first ::pr_lineno_t line record. ///< Zero if there are no records. /** \name Function relocation records. XXX not sure how these work */ //@{ - pr_int_t relocs; ///< Index to first ::qfo_reloc_t reloc record. - pr_int_t num_relocs; ///< Number of reloc records. + pr_uint_t relocs; ///< Index to first ::qfo_reloc_t reloc record. + pr_uint_t num_relocs; ///< Number of reloc records. //@} pr_int_t reserved[2]; } qfo_func_t; @@ -237,8 +237,8 @@ typedef struct qfo_func_s { the referenced field def. */ typedef struct qfo_reloc_s { - pr_int_t space; ///< index of space holding data to be adjusted - pr_int_t offset; ///< offset of the relocation + pr_uint_t space; ///< index of space holding data to be adjusted + pr_uint_t offset; ///< offset of the relocation pr_int_t type; ///< type of the relocation (::reloc_type) pr_uint_t target; ///< def/func/etc this relocation is for } qfo_reloc_t; @@ -248,14 +248,14 @@ typedef struct qfo_reloc_s { typedef struct qfo_mspace_s { qfos_type_t type; qfo_def_t *defs; - int num_defs; + unsigned num_defs; union { dstatement_t *code; pr_type_t *data; char *strings; } d; unsigned data_size; - int id; + unsigned id; } qfo_mspace_t; /** In-memory representation of a QFO object file. @@ -263,16 +263,16 @@ typedef struct qfo_mspace_s { typedef struct qfo_s { void *data; ///< data buffer holding qfo file when read qfo_mspace_t *spaces; - int num_spaces; + unsigned num_spaces; qfo_reloc_t *relocs; - int num_relocs; // includes num_loose_relocs + unsigned num_relocs; // includes num_loose_relocs qfo_def_t *defs; - int num_defs; + unsigned num_defs; qfo_func_t *funcs; - int num_funcs; + unsigned num_funcs; pr_lineno_t *lines; - int num_lines; - int num_loose_relocs; // included in num_relocs + unsigned num_lines; + unsigned num_loose_relocs; // included in num_relocs } qfo_t; enum { diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index dce3bd265..e3ce6f557 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -257,8 +257,8 @@ void qfo_globals (qfo_t *qfo) { qfo_def_t *def; - int i; - int space; + unsigned i; + unsigned space; int count = 0; for (space = 0; space < qfo->num_spaces; space++) { @@ -282,7 +282,7 @@ qfo_relocs (qfo_t *qfo) qfo_reloc_t *reloc; qfo_def_t *def; qfo_func_t *func; - int i; + unsigned i; for (i = 0; i < qfo->num_relocs; i++) { reloc = qfo->relocs + i; @@ -385,8 +385,8 @@ qfo_functions (qfo_t *qfo) { qfo_def_t *def; qfo_func_t *func; - int i, d; - int space; + unsigned i, d; + unsigned space; for (i = 0; i < qfo->num_funcs; i++) { func = &qfo->funcs[i]; diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 772f3fd35..952997374 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -147,7 +147,7 @@ static qfo_t *work; static int work_base[qfo_num_spaces]; static int work_func_base; static defref_t **work_defrefs; -static int num_work_defrefs; +static unsigned num_work_defrefs; static strpool_t *work_strings; static codespace_t *work_code; static defspace_t *work_near_data; @@ -436,7 +436,7 @@ adjust_reloc_offset (qfo_reloc_t *reloc) static int add_relocs (qfo_t *qfo, int start, int count, int target) { - int size; + unsigned size; qfo_reloc_t *ireloc; qfo_reloc_t *oreloc; @@ -448,7 +448,7 @@ add_relocs (qfo_t *qfo, int start, int count, int target) *oreloc = *ireloc; ireloc->type = -1; ireloc->offset = work->num_relocs++; - if (oreloc->space < 0 || oreloc->space >= qfo->num_spaces) { + if (oreloc->space >= qfo->num_spaces) { linker_error ("bad reloc space: %d (%d)", oreloc->space, qfo->num_spaces); oreloc->type = rel_none; @@ -806,7 +806,7 @@ update_type_space_reloc (qfo_mspace_t *space, qfo_reloc_t *reloc) static int process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass) { - int i; + unsigned i; if (pass != 0) return 0; @@ -860,7 +860,7 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass) static void process_funcs (qfo_t *qfo) { - int size; + unsigned size; qfo_func_t *func; qfot_type_t *type; @@ -888,7 +888,7 @@ process_funcs (qfo_t *qfo) static void process_lines (qfo_t *qfo) { - int size; + unsigned size; pr_lineno_t *line; if (!qfo->num_lines) @@ -920,7 +920,7 @@ process_loose_relocs (qfo_t *qfo) qfo->num_loose_relocs * sizeof (qfo_reloc_t)); while (work_num_loose_relocs < size) { reloc = work_loose_relocs + work_num_loose_relocs++; - if (reloc->space < 0 || reloc->space >= qfo->num_spaces) { + if (reloc->space >= qfo->num_spaces) { linker_error ("bad reloc space"); reloc->type = rel_none; continue; @@ -954,7 +954,7 @@ linker_add_qfo (qfo_t *qfo) process_entity_space, process_type_space, }; - int i; + unsigned i; int pass; qfo_mspace_t *space; @@ -1027,7 +1027,8 @@ linker_add_lib (const char *libname) path_t start = {path_head, "."}; path_t *path = &start; const char *path_name = 0; - int i, j; + int i; + unsigned j; int did_something; if (strncmp (libname, "-l", 2) == 0) { @@ -1101,7 +1102,7 @@ static __attribute__ ((used)) void undefined_def (qfo_def_t *def) { qfo_def_t line_def; - pr_int_t i; + pr_uint_t i; qfo_reloc_t *reloc = work->relocs + def->relocs; for (i = 0; i < def->num_relocs; i++, reloc++) { @@ -1113,17 +1114,20 @@ undefined_def (qfo_def_t *def) || reloc->type == rel_op_c_def_ofs) && work->lines) { qfo_func_t *func = work->funcs; - qfo_func_t *best = func; - pr_int_t best_dist = reloc->offset - func->code; + qfo_func_t *best = 0; + pr_uint_t best_dist; pr_lineno_t *line; - while (best_dist && func - work->funcs < work->num_funcs) { - if (func->code <= reloc->offset) { - if (best_dist < 0 - || reloc->offset - func->code < best_dist) { - best = func; - best_dist = reloc->offset - func->code; - } + while (func - work->funcs < work->num_funcs) { + if (func->code < 0) { + continue; + } + if ((pr_uint_t) func->code > reloc->offset) { + continue; + } + if (!best || reloc->offset - func->code < best_dist) { + best = func; + best_dist = reloc->offset - func->code; } func++; } @@ -1195,7 +1199,7 @@ build_qfo (void) { qfo_t *qfo; int size; - int i, j; + unsigned i, j; qfo_reloc_t *reloc; qfo_def_t **defs; @@ -1288,6 +1292,11 @@ build_qfo (void) continue; if (reloc->type != rel_def_def) continue; + if (reloc->target >= qfo->num_defs) { + linker_error ("Invalid reloc target def %d / %d.\n", + reloc->target, qfo->num_defs); + continue; + } def = qfo->defs + reloc->target; QFO_INT (qfo, reloc->space, reloc->offset) = def->offset; } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index b39bea1e7..b7d5a389e 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -394,9 +394,9 @@ qfo_byteswap_space (void *space, int size, qfos_type_t type) int qfo_write (qfo_t *qfo, const char *filename) { - int size; + unsigned size; int space_offset; - int i; + unsigned i; byte *data; qfo_header_t *header; qfo_space_t *spaces; @@ -499,7 +499,7 @@ qfo_read (QFile *file) qfo_header_t *header; qfo_space_t *spaces; qfo_t *qfo; - int i; + unsigned i; size = Qfilesize (file); data = malloc (size); @@ -605,7 +605,7 @@ qfo_delete (qfo_t *qfo) if (qfo->data) { free (qfo->data); } else { - int i; + unsigned i; for (i = 0; i < qfo->num_spaces; i++) free (qfo->spaces[i].d.data); free (qfo->relocs); @@ -715,7 +715,7 @@ convert_def (qfo_t *qfo, const qfo_def_t *def, ddef_t *ddef) static void qfo_relocate_refs (qfo_t *qfo) { - int i; + unsigned i; qfo_reloc_t *reloc; for (i = 0, reloc = qfo->relocs; i < qfo->num_relocs; i++, reloc++) { @@ -788,10 +788,10 @@ qfo_to_progs (qfo_t *qfo, int *size) pr_type_t *type_data; dprograms_t *progs; qfo_def_t *types_def = 0; - int i, j; + unsigned i, j; unsigned locals_size = 0; int locals_start; - int big_locals = 0; + unsigned big_locals = 0; int big_func = 0; *size = RUP (sizeof (dprograms_t), 16); @@ -976,7 +976,7 @@ pr_debug_header_t * qfo_to_sym (qfo_t *qfo, int *size) { pr_debug_header_t *sym; - int i, j; + unsigned i, j; pr_auxfunction_t *auxfuncs; pr_auxfunction_t *aux; pr_lineno_t *linenos; @@ -988,7 +988,7 @@ qfo_to_sym (qfo_t *qfo, int *size) sym->version = PROG_DEBUG_VERSION; for (i = 0; i < qfo->num_funcs; i++) { qfo_func_t *func = qfo->funcs + i; - int num_locals = 0; + unsigned num_locals = 0; if (func->locals_space) num_locals = qfo->spaces[func->locals_space].num_defs; @@ -1017,7 +1017,7 @@ qfo_to_sym (qfo_t *qfo, int *size) for (i = 0, aux = auxfuncs; i < qfo->num_funcs; i++) { qfo_func_t *func = qfo->funcs + i; qfo_def_t *def = 0; - int num_locals = 0; + unsigned num_locals = 0; qfot_type_t *type; if (func->locals_space) { From 59e85b7d5e466f7863d8281a9aacb44863edaf2c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Sep 2018 22:23:57 +0900 Subject: [PATCH 0046/3664] Fix a pile of dead assignments. Some were actual bugs! --- libs/gamecode/pr_strings.c | 1 - libs/gib/gib_builtin.c | 8 ++++---- libs/gib/gib_function.c | 7 +++---- libs/models/brush/model_brush.c | 1 - libs/util/cvar.c | 4 ++-- libs/util/quakefs.c | 2 +- libs/util/riff.c | 2 -- libs/video/renderer/gl/gl_mod_iqm.c | 1 - libs/video/renderer/gl/gl_sky_clip.c | 1 - libs/video/renderer/glsl/glsl_sprite.c | 1 - libs/video/targets/vid_x11.c | 2 -- nq/source/cl_demo.c | 4 ++++ nq/source/host_cmd.c | 1 - qw/source/cl_slist.c | 1 - qw/source/net_packetlog.c | 2 +- qw/source/sv_ents.c | 1 - qw/source/teamplay.c | 2 -- tools/qfbsp/source/merge.c | 1 - tools/qfbsp/source/portals.c | 1 - tools/qfcc/source/dump_globals.c | 2 -- tools/qfcc/source/expr.c | 7 +++++-- tools/qfcc/source/flow.c | 1 - tools/qfcc/source/value.c | 2 +- tools/qflight/source/ltface.c | 5 +---- tools/qflight/source/properties.c | 3 --- 25 files changed, 22 insertions(+), 41 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index f6983469a..ac957e23b 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -841,7 +841,6 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->data.string_var = l; (*fi)->next = new_fmt_item (); - fi = &(*fi)->next; } if (fmt_count != count) { diff --git a/libs/gib/gib_builtin.c b/libs/gib/gib_builtin.c index c3ba2910a..6f6e857bd 100644 --- a/libs/gib/gib_builtin.c +++ b/libs/gib/gib_builtin.c @@ -236,8 +236,8 @@ GIB_Local_f (void) for (i = 3; i < GIB_Argc(); i++) GIB_Return (GIB_Argv(i)); } else for (i = 1; i < GIB_Argc(); i++) - var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &zero, - GIB_Argv (i), &index, true); + GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &zero, + GIB_Argv (i), &index, true); } @@ -261,8 +261,8 @@ GIB_Shared_f (void) for (i = 3; i < GIB_Argc(); i++) GIB_Return (GIB_Argv(i)); } else for (i = 1; i < GIB_Argc(); i++) - var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero, - GIB_Argv (i), &index, true); + GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero, + GIB_Argv (i), &index, true); } static void diff --git a/libs/gib/gib_function.c b/libs/gib/gib_function.c index 72c1d1ea5..5c5403277 100644 --- a/libs/gib/gib_function.c +++ b/libs/gib/gib_function.c @@ -234,11 +234,10 @@ GIB_Function_Prepare_Args_D (cbuf_t * cbuf, dstring_t **args, unsigned int g_fpad_args = args; g_fpad_argc = argc; - i = 1; llist_iterate (arglist, LLIST_ICAST (fpad_iterate)); + llist_iterate (arglist, LLIST_ICAST (fpad_iterate)); - var = - GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &g_fpad_zero, argss, - &g_fpad_ind, true); + var = GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &g_fpad_zero, argss, + &g_fpad_ind, true); var->array = realloc (var->array, sizeof (struct gib_varray_s) * argc); memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s)); var->size = argc; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index dd43c1dc8..33e67b952 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -221,7 +221,6 @@ Mod_LoadTextures (bsp_t *bsp) memset (altanims, 0, sizeof (altanims)); max = tx->name[1]; - altmax = 0; if (max >= 'a' && max <= 'z') max -= 'a' - 'A'; if (max >= '0' && max <= '9') { diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 32e3af26a..64ef200ab 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -356,8 +356,8 @@ set_cvar (const char *cmd, int orflags) Cvar_SetFlags (var, var->flags | orflags); } } else { - var = Cvar_Get (var_name, value, CVAR_USER_CREATED | orflags, NULL, - USER_CVAR); + Cvar_Get (var_name, value, CVAR_USER_CREATED | orflags, NULL, + USER_CVAR); } } diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 5131f7194..edbb39c6c 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1209,7 +1209,7 @@ qfs_file_sort (char **os1, char **os2) s2 = *os2; while (1) { - in1 = in2 = n1 = n2 = 0; + n1 = n2 = 0; if ((in1 = isdigit ((byte) *s1))) n1 = strtol (s1, &s1, 10); diff --git a/libs/util/riff.c b/libs/util/riff.c index bd7320c96..9bbeb461c 100644 --- a/libs/util/riff.c +++ b/libs/util/riff.c @@ -138,7 +138,6 @@ read_adtl (dstring_t *list_buf, QFile *f, int len) //FIXME list = (riff_list_t *) list_buf->str; while (len) { if (!Rread (f, &ck, sizeof (ck))) { - len = 0; break; } len -= sizeof (ck); @@ -392,7 +391,6 @@ riff_read (QFile *f) break; } dstring_append (riff_buf, (char *)&chunk, sizeof (chunk)); - riff = (riff_list_t *) riff_buf->str; chunk = 0; } bail: diff --git a/libs/video/renderer/gl/gl_mod_iqm.c b/libs/video/renderer/gl/gl_mod_iqm.c index 8a6efaade..4c50795b7 100644 --- a/libs/video/renderer/gl/gl_mod_iqm.c +++ b/libs/video/renderer/gl/gl_mod_iqm.c @@ -97,7 +97,6 @@ gl_R_DrawIQMModel (entity_t *ent) iqmframe_t *frame; int i; - model = ent->model; blend = R_IQMGetLerpedFrames (ent, iqm); frame = R_IQMBlendPalette (iqm, ent->pose1, ent->pose2, blend, 0, gl->blend_palette, gl->palette_size); diff --git a/libs/video/renderer/gl/gl_sky_clip.c b/libs/video/renderer/gl/gl_sky_clip.c index 613e8b177..44a560005 100644 --- a/libs/video/renderer/gl/gl_sky_clip.c +++ b/libs/video/renderer/gl/gl_sky_clip.c @@ -370,7 +370,6 @@ process_corners (struct box_def *box) for (i = 0; i < 6; i++) { if (max_visit < box->face_visits[i]) { max_visit = box->face_visits[i]; - center = i; } } diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 83f116ee3..69c67335a 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -143,7 +143,6 @@ R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, if (framenum >= sprite->numframes || framenum < 0) framenum = 0; - numframes = sprite->numframes; framedesc = &sprite->frames[framenum]; if (framedesc->type == SPR_SINGLE) { frame_interval = 0.1; diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 6430b9c06..1050d6adb 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -536,8 +536,6 @@ x11_choose_visual (void) int num_visuals; int template_mask; - template_mask = 0; - // specify a visual id if ((pnum = COM_CheckParm ("-visualid"))) { if (pnum >= com_argc - 1) diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 3b0a1a803..7d47eb627 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -184,6 +184,10 @@ read_demopacket (void) VectorCopy (cl.mviewangles[0], cl.mviewangles[1]); for (i = 0; i < 3; i++) { r = Qread (cls.demofile, &f, 4); + if (r != 4) { + CL_StopPlayback (); + return 0; + } cl.mviewangles[0][i] = LittleFloat (f); } r = Qread (cls.demofile, net_message->message->data, diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 1a827f15b..1e502b7d5 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -692,7 +692,6 @@ Host_Loadgame_f (void) ED_InitGlobals (&sv_pr_state, PL_ObjectForKey (game, "globals")); list = PL_ObjectForKey (game, "entities"); - entnum = 0; count = PL_A_NumObjects (list); if (count > sv.max_edicts) Host_Error ("too many entities in saved game. adjust max_edicts\n"); diff --git a/qw/source/cl_slist.c b/qw/source/cl_slist.c index 585e6aa47..9efafd73b 100644 --- a/qw/source/cl_slist.c +++ b/qw/source/cl_slist.c @@ -119,7 +119,6 @@ SL_Add (server_entry_t *start, const char *ip, const char *desc) { server_entry_t *p; - p = start; if (!start) { // Nothing at beginning of list, // create it start = calloc (1, sizeof (server_entry_t)); diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index 87edf8e45..3ec8078e5 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -635,7 +635,7 @@ Parse_Server_Packet (int has_sequence) break; case svc_playerinfo: Net_LogPrintf ("\n\tPlayer: %d", MSG_ReadByte (&packet)); - mask2 = mask1 = MSG_ReadShort (&packet); + mask1 = MSG_ReadShort (&packet); Net_LogPrintf (" Mask1: %d", mask1); #if 1 Net_LogPrintf (" Origin:"); diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index bb0b2b1b3..f6682337c 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -577,7 +577,6 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg) if (delta->client) { clent = delta->client->edict; spec_track = delta->client->spec_track; - stdver = delta->client->stdver; null_player_state.modelindex = sv_playermodel; full = 0; // normal qw clients don't get real deltas on players } diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index 538dc0f1d..5da9dace2 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -156,7 +156,6 @@ Team_ParseSay (dstring_t *buf, const char *s) case 'S': bracket = 0; t1 = skin->string; - t1 = "FIXME"; break; case 'd': bracket = 0; @@ -475,7 +474,6 @@ Team_ParseChat (const char *string) if (!cl_freply->value) return; - s = strchr (string, ':'); if (!(s = strchr (string, ':'))) return; s++; diff --git a/tools/qfbsp/source/merge.c b/tools/qfbsp/source/merge.c index 8551336df..5692a6d83 100644 --- a/tools/qfbsp/source/merge.c +++ b/tools/qfbsp/source/merge.c @@ -74,7 +74,6 @@ TryMerge (const face_t *f1, const face_t *f2) return NULL; p1 = p2 = NULL; - j = 0; // find a common edge for (i = 0; i < f1p->numpoints; i++) { diff --git a/tools/qfbsp/source/portals.c b/tools/qfbsp/source/portals.c index edad5724a..6b99cefda 100644 --- a/tools/qfbsp/source/portals.c +++ b/tools/qfbsp/source/portals.c @@ -280,7 +280,6 @@ CutNodePortals_r (node_t *node) /// cutting plane and clipping it by all of the planes from the other /// portals on the node. w = BaseWindingForPlane (plane); - side = 0; for (p = node->portals; p; p = p->next[side]) { clipplane = planes[p->planenum]; // copy the plane if (p->nodes[0] == node) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index e3ce6f557..4361b7a57 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -202,8 +202,6 @@ dump_functions (progs_t *pr) name = PR_GetString (pr, func->s_name); - comment = ""; - start = func->first_statement; if (start > 0) comment = va (" @ %x", start); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 36627517f..45aa50882 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1926,13 +1926,17 @@ return_expr (function_t *f, expr_t *e) if (options.warnings.traditional) warning (e, "return from non-void function without a value"); + // force a nil return value in case qf code is being generated e = new_nil_expr (); } else { e = error (e, "return from non-void function without a value"); return e; } } - return new_unary_expr ('r', 0); + // the traditional check above may have set e + if (!e) { + return new_unary_expr ('r', 0); + } } t = get_type (e); @@ -2823,7 +2827,6 @@ message_expr (expr_t *receiver, keywordarg_t *message) return receiver; receiver = cast_expr (&type_id, receiver); //FIXME better way? class = extract_class (current_class); - rec_type = class->type; } else { if (receiver->type == ex_symbol) { if (strcmp (receiver->e.symbol->name, "self") == 0) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index b23fb1bb0..bb398e045 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1050,7 +1050,6 @@ flow_find_dominators (flowgraph_t *graph) changed = 0; for (i = 1; i < graph->num_nodes; i++) { node = graph->nodes[i]; - pred = set_first (node->predecessors); set_empty (work); for (pred = set_first (node->predecessors); pred; pred = set_next (pred)) diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 1eab5ec68..0d323ac99 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -558,7 +558,7 @@ emit_value (ex_value_t *value, def_t *def) memcpy (D_POINTER (void, cn), &val.v, 4 * type_size (type)); - imm = make_def_imm (cn, tab, &val); + make_def_imm (cn, tab, &val); return cn; } diff --git a/tools/qflight/source/ltface.c b/tools/qflight/source/ltface.c index acb157c36..1864b7746 100644 --- a/tools/qflight/source/ltface.c +++ b/tools/qflight/source/ltface.c @@ -488,7 +488,6 @@ SkyLightFace (entity_t *ent, int sun, lightinfo_t *l) // Check each point... VectorCopy (sun_dir, incoming); VectorNormalize (incoming); - angle = DotProduct (incoming, l->facenormal); //anglesense = 0.5; //FIXME // FIXME global @@ -499,11 +498,9 @@ SkyLightFace (entity_t *ent, int sun, lightinfo_t *l) if (!TestSky (l, point->v, sun_dir)) continue; + add = sun_light; - continue; - add *= angle; - add *= options.extrascale; sample = &l->sample[mapnum][point->samplepos]; diff --git a/tools/qflight/source/properties.c b/tools/qflight/source/properties.c index d9286e268..5cf957b7f 100644 --- a/tools/qflight/source/properties.c +++ b/tools/qflight/source/properties.c @@ -237,14 +237,11 @@ set_properties (entity_t *ent, plitem_t *dict) const char *str; if (properties) { - prop = PL_ObjectForKey (properties, ent->classname); if ((p = get_item ("light_name", dict, 0)) && (str = PL_String (p))) prop = PL_ObjectForKey (properties, str); if (!prop) prop = PL_ObjectForKey (properties, ent->classname); - - prop = PL_ObjectForKey (properties, ent->classname); if (!prop) prop = PL_ObjectForKey (properties, "default"); } From 62793b2dc2b599bedd5913c3a7a354e737d67797 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 09:54:16 +0900 Subject: [PATCH 0047/3664] Fix some potentially garbage assignments. These are the ones where I could easily make scan-build happy. They do seem to be potential holes where invalid data in one place could result in use of uninitialized values. --- libs/models/brush/gl_model_brush.c | 6 ++++-- libs/net/nm/net_udp.c | 4 ++-- libs/video/renderer/sw/d_sky.c | 2 ++ libs/video/renderer/sw32/d_sky.c | 6 ++++++ nq/source/host_cmd.c | 1 + 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 1485fdd94..7b7e171ac 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -222,7 +222,7 @@ SubdividePolygon (int numverts, float *verts) vec3_t mins, maxs; vec3_t front[64], back[64]; - if (numverts > 60) + if (numverts < 3 || numverts > 60) Sys_Error ("numverts = %i", numverts); BoundPoly (numverts, verts, mins, maxs); @@ -317,5 +317,7 @@ gl_Mod_SubdivideSurface (msurface_t *fa) numverts++; } - SubdividePolygon (numverts, verts[0]); + if (numverts > 3) { + SubdividePolygon (numverts, verts[0]); + } } diff --git a/libs/net/nm/net_udp.c b/libs/net/nm/net_udp.c index 84f01a3a9..cf2348256 100644 --- a/libs/net/nm/net_udp.c +++ b/libs/net/nm/net_udp.c @@ -387,7 +387,7 @@ PartialIPAddress (const char *in, netadr_t *hostaddr) { char *buff; char *b; - int addr, mask, num, port, run; + unsigned addr, mask, num, port, run; buff = nva (".%s", in); b = buff; @@ -407,7 +407,7 @@ PartialIPAddress (const char *in, netadr_t *hostaddr) } if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0) goto error; - if (num < 0 || num > 255) + if (num > 255) goto error; mask <<= 8; addr = (addr << 8) + num; diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index 6bc7872aa..853a3e0e0 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -72,6 +72,8 @@ D_DrawSkyScans (espan_t *pspan) sstep = 0; // keep compiler happy tstep = 0; // ditto + snext = 0; // ditto + tnext = 0; // ditto do { pdest = (unsigned char *) ((byte *) d_viewbuffer + diff --git a/libs/video/renderer/sw32/d_sky.c b/libs/video/renderer/sw32/d_sky.c index 20e2765b0..6ceb6095a 100644 --- a/libs/video/renderer/sw32/d_sky.c +++ b/libs/video/renderer/sw32/d_sky.c @@ -79,6 +79,8 @@ sw32_D_DrawSkyScans (espan_t *pspan) sstep = 0; // keep compiler happy tstep = 0; // ditto + snext = 0; // ditto + tnext = 0; // ditto do { pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u; @@ -146,6 +148,8 @@ sw32_D_DrawSkyScans (espan_t *pspan) sstep = 0; // keep compiler happy tstep = 0; // ditto + snext = 0; // ditto + tnext = 0; // ditto do { pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u; @@ -213,6 +217,8 @@ sw32_D_DrawSkyScans (espan_t *pspan) sstep = 0; // keep compiler happy tstep = 0; // ditto + snext = 0; // ditto + tnext = 0; // ditto do { pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u; diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 1e502b7d5..5aaf60e73 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -657,6 +657,7 @@ Host_Loadgame_f (void) game = convert_to_game_dict (script); } + memset (spawn_parms, 0, sizeof (spawn_parms)); item = PL_ObjectForKey (game, "spawn_parms"); for (i = 0; i < NUM_SPAWN_PARMS; i++) { if (i >= PL_A_NumObjects (item)) From 3f638d95ba95eae488eca6e5c49327c89705c427 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 10:54:38 +0900 Subject: [PATCH 0048/3664] Remove a possibly spurious break. I'm not certain despair actually meant for the break to be there. It certainly would have sped up the game a bit but at the expense of proper blood trails in the software renderers. --- libs/video/renderer/sw/sw_rpart.c | 1 - libs/video/renderer/sw32/sw32_rpart.c | 1 - 2 files changed, 2 deletions(-) diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index aeb2fa904..601a003c9 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -590,7 +590,6 @@ R_BloodTrail_QF (const entity_t *ent) p->color = 67 + (mtwist_rand (&mt) & 3); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - break; VectorAdd (old_origin, vec, old_origin); } diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 5591b9929..7b910005d 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -603,7 +603,6 @@ R_BloodTrail_QF (const entity_t *ent) p->color = 67 + (mtwist_rand (&mt) & 3); for (j = 0; j < 3; j++) p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - break; VectorAdd (old_origin, vec, old_origin); } From db3df6f8a771fcd7a0ae9a8f64b598c517c83d2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 11:12:04 +0900 Subject: [PATCH 0049/3664] Fix a bunch of dead increments. --- libs/util/riff.c | 2 +- libs/video/renderer/gl/vtxarray.c | 3 --- libs/video/renderer/sw32/d_scan.c | 12 ------------ 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/libs/util/riff.c b/libs/util/riff.c index 9bbeb461c..c4590ce2d 100644 --- a/libs/util/riff.c +++ b/libs/util/riff.c @@ -228,6 +228,7 @@ read_list (riff_d_chunk_t *ck, QFile *f, int len) riff_data_t *data = malloc (sizeof (riff_data_t)); if (!Rread (f, &data->ck, sizeof (data->ck))) { free (data); + len = 0; } else { data->ck.len = LittleLong (data->ck.len); data->data = read_data (f, data->ck.len); @@ -235,7 +236,6 @@ read_list (riff_d_chunk_t *ck, QFile *f, int len) chunk = &data->ck; } } - len = 0; break; } if (chunk) { diff --git a/libs/video/renderer/gl/vtxarray.c b/libs/video/renderer/gl/vtxarray.c index 78e245a55..dda46974b 100644 --- a/libs/video/renderer/gl/vtxarray.c +++ b/libs/video/renderer/gl/vtxarray.c @@ -445,7 +445,6 @@ qfgl_InterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer) case GL_C4UB_V2F: qfgl_VertexPointer (2, GL_FLOAT, stride - 2 * sizeof (GLfloat), ptr); - ptr += 2 * sizeof (GLfloat); break; case GL_V3F: case GL_C4UB_V3F: @@ -459,13 +458,11 @@ qfgl_InterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer) case GL_T2F_C4F_N3F_V3F: qfgl_VertexPointer (3, GL_FLOAT, stride - 3 * sizeof (GLfloat), ptr); - ptr += 3 * sizeof (GLfloat); break; case GL_T4F_V4F: case GL_T4F_C4F_N3F_V4F: qfgl_VertexPointer (4, GL_FLOAT, stride - 4 * sizeof (GLfloat), ptr); - ptr += 4 * sizeof (GLfloat); break; default: break; diff --git a/libs/video/renderer/sw32/d_scan.c b/libs/video/renderer/sw32/d_scan.c index c77f131df..d5c2000ea 100644 --- a/libs/video/renderer/sw32/d_scan.c +++ b/libs/video/renderer/sw32/d_scan.c @@ -515,14 +515,10 @@ sw32_D_DrawSpans (espan_t *pspan) } if (count & 1) pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; } else { pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; } } } while ((pspan = pspan->pnext) != NULL); @@ -657,14 +653,10 @@ sw32_D_DrawSpans (espan_t *pspan) } if (count & 1) pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; } else { pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; } } } while ((pspan = pspan->pnext) != NULL); @@ -800,14 +792,10 @@ sw32_D_DrawSpans (espan_t *pspan) } if (count & 1) pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; } else { pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; } } } while ((pspan = pspan->pnext) != NULL); From 06ab36de3de3d11da1b3b45d0334cdbde70b6d1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 13:38:32 +0900 Subject: [PATCH 0050/3664] Slight cleanup of winding allocation. It seems gcc doesn't care if the & is present when calculating field offsets, but it not being there bothered me very much and might as well use our "standard" macro anyway. --- tools/qfvis/source/qfvis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 7ec7e776c..e32f91d67 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -149,7 +149,7 @@ NewWinding (int points) if (points > MAX_POINTS_ON_WINDING) Sys_Error ("NewWinding: %i points", points); - size = (size_t)(uintptr_t) ((winding_t *) 0)->points[points]; + size = field_offset (winding_t, points[points]); winding = calloc (1, size); return winding; @@ -168,7 +168,7 @@ CopyWinding (const winding_t *w) size_t size; winding_t *copy; - size = (size_t) (uintptr_t) ((winding_t *) 0)->points[w->numpoints]; + size = field_offset (winding_t, points[w->numpoints]); copy = malloc (size); memcpy (copy, w, size); copy->original = false; From fa1514798ba22f933ccf2499924cd76f3567a18a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 13:41:00 +0900 Subject: [PATCH 0051/3664] Print the number of threads used by qfvis. --- tools/qfvis/source/qfvis.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index e32f91d67..a5520927b 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -724,6 +724,7 @@ CalcVis (void) { int i; + printf ("Thread count: %d\n", options.threads); BasePortalVis (); CalcPortalVis (); From aebd9288cd0ec21fd3c9bf9cbec8f1d70bd5411f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 13:41:22 +0900 Subject: [PATCH 0052/3664] Force thread count to 1 when pthreads is unavailable. Don't want the thread count being misreported. --- tools/qfvis/source/qfvis.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index a5520927b..8c2cc6ed3 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -111,6 +111,9 @@ InitThreads (void) stats_lock = malloc (sizeof (pthread_rwlock_t)); if (pthread_rwlock_init (stats_lock, 0)) Sys_Error ("pthread_rwlock_init failed"); +#else + // Unable to run multi-threaded, so force threadcount to 1 + options.threads = 1; #endif } @@ -1112,14 +1115,14 @@ main (int argc, char **argv) dstring_t *portalfile = dstring_new (); QFile *f; - InitThreads (); - start = Sys_DoubleTime (); this_program = argv[0]; DecodeArgs (argc, argv); + InitThreads (); + if (!options.bspfile) { usage (1); Sys_Error ("%s: no bsp file specified.", this_program); From 113e0d82bac43f240720dd6526cebbd71ab1def7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 16:48:19 +0900 Subject: [PATCH 0053/3664] Fix a signed comparison error. Not sure how this fix got lost. --- tools/qfcc/source/linker.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 952997374..4d1c86e31 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -128,8 +128,8 @@ static builtin_sym_t builtin_symbols[] __attribute__ ((used)) = { {".param_6", &type_param, QFOD_NOSAVE | QFOD_GLOBAL}, {".param_7", &type_param, QFOD_NOSAVE | QFOD_GLOBAL}, }; -static const int num_builtins = sizeof (builtin_symbols) - / sizeof (builtin_symbols[0]); +static const unsigned num_builtins = sizeof (builtin_symbols) + / sizeof (builtin_symbols[0]); static defref_t *defrefs_freelist; @@ -638,7 +638,7 @@ linker_find_def (const char *name) void linker_begin (void) { - int i; + unsigned i; linker_current_file = dstring_newstr (); From 71569b45c96926d1822e02f1b8922b304180b6b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 18:09:32 +0900 Subject: [PATCH 0054/3664] Pre-format diagnostic messages. This will make it easier to hook diagnostics enabling unit tests. --- tools/qfcc/source/diagnostic.c | 116 ++++++++++++++++----------------- 1 file changed, 57 insertions(+), 59 deletions(-) diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 2b2347cc2..6f198851e 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -73,10 +73,27 @@ report_function (expr_t *e) } static void -_warning (expr_t *e, const char *fmt, va_list args) +format_message (dstring_t *message, const char *msg_type, expr_t *e, + const char *fmt, va_list args) { string_t file = pr.source_file; int line = pr.source_line; + const char *colon = fmt ? ": " : ""; + + if (e) { + file = e->file; + line = e->line; + } + dsprintf (message, "%s:%d: %s%s", GETSTR (file), line, msg_type, colon); + if (fmt) { + davsprintf (message, fmt, args); + } +} + +static void +_warning (expr_t *e, const char *fmt, va_list args) +{ + dstring_t *message = dstring_new (); report_function (e); if (options.warnings.promote) { @@ -85,13 +102,9 @@ _warning (expr_t *e, const char *fmt, va_list args) pr.error_count++; } - if (e) { - file = e->file; - line = e->line; - } - fprintf (stderr, "%s:%d: warning: ", GETSTR (file), line); - vfprintf (stderr, fmt, args); - fputs ("\n", stderr); + format_message (message, "warning", e, fmt, args); + fprintf (stderr, "%s\n", message->str); + dstring_delete (message); } void @@ -102,19 +115,14 @@ debug (expr_t *e, const char *fmt, ...) if (options.verbosity < 1) return; + report_function (e); va_start (args, fmt); { - string_t file = pr.source_file; - int line = pr.source_line; + dstring_t *message = dstring_new (); - report_function (e); - if (e) { - file = e->file; - line = e->line; - } - fprintf (stderr, "%s:%d: debug: ", GETSTR (file), line); - vfprintf (stderr, fmt, args); - fputs ("\n", stderr); + format_message (message, "debug", e, fmt, args); + fprintf (stderr, "%s\n", message->str); + dstring_delete (message); } va_end (args); } @@ -123,19 +131,17 @@ void bug (expr_t *e, const char *fmt, ...) { va_list args; - string_t file = pr.source_file; - int line = pr.source_line; - - va_start (args, fmt); report_function (e); - if (e) { - file = e->file; - line = e->line; + + va_start (args, fmt); + { + dstring_t *message = dstring_new (); + + format_message (message, "BUG", e, fmt, args); + fprintf (stderr, "%s\n", message->str); + dstring_delete (message); } - fprintf (stderr, "%s:%d: BUG: ", GETSTR (file), line); - vfprintf (stderr, fmt, args); - fputs ("\n", stderr); va_end (args); } @@ -151,17 +157,13 @@ notice (expr_t *e, const char *fmt, ...) if (options.notices.promote) { _warning (e, fmt, args); } else { - string_t file = pr.source_file; - int line = pr.source_line; + dstring_t *message = dstring_new (); report_function (e); - if (e) { - file = e->file; - line = e->line; - } - fprintf (stderr, "%s:%d: notice: ", GETSTR (file), line); - vfprintf (stderr, fmt, args); - fputs ("\n", stderr); + + format_message (message, "notice", e, fmt, args); + fprintf (stderr, "%s\n", message->str); + dstring_delete (message); } va_end (args); return e; @@ -178,33 +180,21 @@ warning (expr_t *e, const char *fmt, ...) return e; } -static void -_error (expr_t *e, const char *err, const char *fmt, va_list args) -{ - string_t file = pr.source_file; - int line = pr.source_line; - - report_function (e); - - if (e) { - file = e->file; - line = e->line; - } - fprintf (stderr, "%s:%d: %s%s", GETSTR (file), line, err, - fmt ? ": " : ""); - if (fmt) - vfprintf (stderr, fmt, args); - fputs ("\n", stderr); - pr.error_count++; -} - void internal_error (expr_t *e, const char *fmt, ...) { va_list args; + report_function (e); + va_start (args, fmt); - _error (e, "internal error", fmt, args); + { + dstring_t *message = dstring_new (); + + format_message (message, "internal error", e, fmt, args); + fprintf (stderr, "%s\n", message->str); + dstring_delete (message); + } va_end (args); abort (); } @@ -214,8 +204,16 @@ error (expr_t *e, const char *fmt, ...) { va_list args; + report_function (e); + va_start (args, fmt); - _error (e, "error", fmt, args); + { + dstring_t *message = dstring_new (); + + format_message (message, "error", e, fmt, args); + fprintf (stderr, "%s\n", message->str); + dstring_delete (message); + } va_end (args); if (!e) From d1cb15664f7535eb62057d0dd84d05f4832d00f9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 22:34:24 +0900 Subject: [PATCH 0055/3664] Fix some spelling issues in a comment. --- tools/qfcc/include/defspace.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index 371af492e..8e7f034d6 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -115,14 +115,14 @@ int defspace_alloc_loc (defspace_t *space, int size); first word of the block and \a size indicating the number of words in the block. - If the block to be freed has 0 words, or if the is partly or fully outside - the defspace (as defined by defspace_t::size), or if the block overlaps - any unallocated space in the defspace, then an internal error will be - generated. However, it is perfectly valid to allocate a large block and - subsequently free a small block from anywhere within the larger block. - This is because when memory is not fragmented, there is no difference - between allocating one large block and allocating several smaller blocks - when allocating the same amount of memory. + If the block to be freed has 0 words, or if the block is partly or fully + outside the defspace (as defined by defspace_t::size), or if the block + overlaps any unallocated space in the defspace, then an internal error + will be generated. However, it is perfectly valid to allocate a large + block and subsequently free a small block from anywhere within the larger + block. This is because when memory is not fragmented, there is no + difference between allocating one large block and allocating several + smaller blocks when allocating the same amount of memory. \param space The space to which the freed block will be returned. \param ofs The first word of the block to be freed. @@ -136,7 +136,7 @@ void defspace_free_loc (defspace_t *space, int ofs, int size); defspace_alloc_loc(). If \a data is null, then the copying stage is skipped and this function - because a synonym for defspace_alloc_loc(). + becomes a synonym for defspace_alloc_loc(). \param space The space to which the data will be added. \param data The data to be copied into the space. From 3a4667318c2063c2e3041aabf0cad293abb7ff7c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 22:36:20 +0900 Subject: [PATCH 0056/3664] Fix the qfcc test autodependencies. --- tools/qfcc/test/Makefile.am | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 9bb48d112..23e366078 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -38,8 +38,7 @@ test_progs_dat=\ while.dat \ voidfor.dat -fail_progs_dat=\ - $E +fail_progs_dat= TESTS=$(test_progs_dat:.dat=.run) XFAIL_TESTS=$(fail_progs_dat:.dat=.run) @@ -56,6 +55,7 @@ chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_alias_obj) chewed-alias.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/chewed-alias.Qo chewed_return_dat_SOURCES=chewed-return.r chewed_return_obj=$(chewed_return_dat_SOURCES:.r=.qfo) @@ -63,6 +63,7 @@ chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_return_obj) chewed-return.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ +include ./$(DEPDIR)/chewed-return.Qo func_expr_dat_SOURCES=func-expr.r func_expr_obj=$(func_expr_dat_SOURCES:.r=.qfo) @@ -70,6 +71,7 @@ func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) func-expr.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/func-expr.Qo func_static_dat_SOURCES=func-static.r func_static_obj=$(func_static_dat_SOURCES:.r=.qfo) @@ -77,6 +79,7 @@ func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) func-static.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/func-static.Qo deadbool_dat_SOURCES=deadbool.r deadbool_obj=$(deadbool_dat_SOURCES:.r=.qfo) @@ -84,6 +87,7 @@ deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(deadbool_obj) deadbool.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/deadbool.Qo infloop_dat_SOURCES=infloop.r infloop_obj=$(infloop_dat_SOURCES:.r=.qfo) @@ -91,6 +95,7 @@ infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(infloop_obj) infloop.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/infloop.Qo modulo_dat_SOURCES=modulo.r modulo_obj=$(modulo_dat_SOURCES:.r=.qfo) @@ -98,6 +103,7 @@ modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(modulo_obj) modulo.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ +include ./$(DEPDIR)/modulo.Qo paramret_dat_SOURCES=paramret.r paramret_obj=$(paramret_dat_SOURCES:.r=.qfo) @@ -105,6 +111,7 @@ paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) paramret.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ +include ./$(DEPDIR)/paramret.Qo return_ivar_dat_SOURCES=return-ivar.r return_ivar_obj=$(return_ivar_dat_SOURCES:.r=.qfo) @@ -112,6 +119,7 @@ return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(return_ivar_obj) return-ivar.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/return-ivar.Qo sendv_dat_SOURCES=sendv.r sendv_obj=$(sendv_dat_SOURCES:.r=.qfo) @@ -119,6 +127,7 @@ sendv.dat$(EXEEXT): $(sendv_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(sendv_obj) sendv.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/sendv.Qo state_dat_SOURCES=state.r state_obj=$(state_dat_SOURCES:.r=.qfo) @@ -126,6 +135,7 @@ state.dat$(EXEEXT): $(state_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(state_obj) state.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/state.Qo structlive_dat_SOURCES=structlive.r structlive_obj=$(structlive_dat_SOURCES:.r=.qfo) @@ -133,6 +143,7 @@ structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structlive_obj) structlive.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/structlive.Qo structptr_dat_SOURCES=structptr.r structptr_obj=$(structptr_dat_SOURCES:.r=.qfo) @@ -140,6 +151,7 @@ structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structptr_obj) structptr.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/structptr.Qo swap_dat_SOURCES=swap.r swap_obj=$(swap_dat_SOURCES:.r=.qfo) @@ -147,6 +159,7 @@ swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(swap_obj) swap.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/swap.Qo triangle_dat_SOURCES=triangle.r triangle_obj=$(triangle_dat_SOURCES:.r=.qfo) @@ -154,6 +167,7 @@ triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) triangle.run: Makefile build-run $(srcdir)/build-run $@ 100000 100000 1.00005 50002.4961 +include ./$(DEPDIR)/triangle.Qo vecinit_dat_SOURCES=vecinit.r vecinit_obj=$(vecinit_dat_SOURCES:.r=.qfo) @@ -161,6 +175,7 @@ vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(vecinit_obj) vecinit.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/vecinit.Qo while_dat_SOURCES=while.r while_obj=$(while_dat_SOURCES:.r=.qfo) @@ -168,6 +183,7 @@ while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(while_obj) while.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/while.Qo voidfor_dat_SOURCES=voidfor.r voidfor_obj=$(voidfor_dat_SOURCES:.r=.qfo) @@ -175,8 +191,8 @@ voidfor.dat$(EXEEXT): $(voidfor_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj) voidfor.run: Makefile build-run $(srcdir)/build-run $@ +include ./$(DEPDIR)/voidfor.Qo -include ./$(DEPDIR)/*.Qo EXTRA_DIST= test-bi.h build-run CLEANFILES= *.dat *.sym *.qfo *.run *.frame From 05fd2d8cddadc248434b5f17759d11874373b31f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Sep 2018 22:37:09 +0900 Subject: [PATCH 0057/3664] Start work on a unit test for defspace. --- tools/qfcc/test/Makefile.am | 23 ++++++- tools/qfcc/test/test-defspace.c | 110 ++++++++++++++++++++++++++++++++ tools/qfcc/test/tw-defspace.c | 1 + tools/qfcc/test/tw-diagnostic.c | 1 + tools/qfcc/test/tw-strpool.c | 1 + 5 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 tools/qfcc/test/test-defspace.c create mode 100644 tools/qfcc/test/tw-defspace.c create mode 100644 tools/qfcc/test/tw-diagnostic.c create mode 100644 tools/qfcc/test/tw-strpool.c diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 23e366078..cf982bd69 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -1,4 +1,9 @@ AUTOMAKE_OPTIONS= foreign + +QFCC_LIBS=@QFCC_LIBS@ +QFCC_DEPS=@QFCC_DEPS@ +QFCC_INCS=@QFCC_INCS@ + AM_CPPFLAGS= -I$(top_srcdir)/include $(QFCC_INCS) QFCC_DEP=$(builddir)/../source/qfcc$(EXEEXT) @@ -18,6 +23,11 @@ QFCC_TEST_LIBS=@QFCC_TEST_LIBS@ QFCC_TEST_DEPS=@QFCC_TEST_DEPS@ QFCC_TEST_INCS=@QFCC_TEST_INCS@ +test_bins=\ + test-defspace + +fail_bins= + test_progs_dat=\ chewed-alias.dat \ chewed-return.dat \ @@ -40,10 +50,17 @@ test_progs_dat=\ fail_progs_dat= -TESTS=$(test_progs_dat:.dat=.run) -XFAIL_TESTS=$(fail_progs_dat:.dat=.run) +test_defspace_src=\ + tw-defspace.c tw-diagnostic.c tw-strpool.c -check_PROGRAMS=test-harness $(test_progs_dat) +TESTS=$(test_bins) $(test_progs_dat:.dat=.run) +XFAIL_TESTS=$(fail_bins) $(fail_progs_dat:.dat=.run) + +check_PROGRAMS=test-harness $(test_progs_dat) $(test_bins) + +test_defspace_SOURCES= test-defspace.c $(test_defspace_src) +test_defspace_LDADD= $(QFCC_LIBS) +test_defspace_DEPENDENCIES= $(QFCC_DEPS) test_harness_SOURCES= test-bi.c test-harness.c test_harness_LDADD= $(QFCC_TEST_LIBS) diff --git a/tools/qfcc/test/test-defspace.c b/tools/qfcc/test/test-defspace.c new file mode 100644 index 000000000..bc5f45077 --- /dev/null +++ b/tools/qfcc/test/test-defspace.c @@ -0,0 +1,110 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include + +#include "class.h" +#include "defspace.h" +#include "expr.h" +#include "function.h" +#include "options.h" +#include "strpool.h" +#include "qfcc.h" + +options_t options; +pr_info_t pr; +function_t *current_func; +class_type_t *current_class; + +const char * +get_class_name (class_type_t *class_type, int prett) +{ + return 0; +} + +expr_t * +new_expr (void) +{ + return calloc(1, sizeof (expr_t)); +} + +static int +check_init_state (const defspace_t *space, const char *name) +{ + int pass = 1; + + if (space->free_locs) { + printf ("%s free_locs not null\n", name); + pass = 0; + } + if (space->defs) { + printf ("%s defs not null\n", name); + pass = 0; + } + if (space->def_tail != &space->defs) { + printf ("%s def_tail not pointing to defs\n", name); + pass = 0; + } + if (space->data) { + printf ("%s data not null\n", name); + pass = 0; + } + if (space->size) { + printf ("%s size not 0\n", name); + pass = 0; + } + if (space->max_size) { + printf ("%s max_size not 0\n", name); + pass = 0; + } + if (!space->grow) { + printf ("%s grow is null\n", name); + pass = 0; + } + if (space->qfo_space) { + printf ("%s qfo_space not 0\n", name); + pass = 0; + } + return pass; +} + +static int +test_init (void) +{ + int pass = 1; + defspace_t *backed = defspace_new (ds_backed); + defspace_t *virtual = defspace_new (ds_virtual); + + if (backed->grow == virtual->grow) { + printf ("expected different grow functions for backed and virtual\n"); + pass = 0; + } + + if (backed->type != ds_backed) { + printf ("backed ds has wrong type\n"); + pass = 0; + } + + if (virtual->type != ds_virtual) { + printf ("virtual ds has wrong type\n"); + pass = 0; + } + + pass &= check_init_state (backed, "backed"); + pass &= check_init_state (virtual, "virtual"); + + return pass; +} + +int +main (int argc, const char **argv) +{ + pr.strings = strpool_new (); + + int pass = 1; + + pass &= test_init (); + + return !pass; +} diff --git a/tools/qfcc/test/tw-defspace.c b/tools/qfcc/test/tw-defspace.c new file mode 100644 index 000000000..c3b950324 --- /dev/null +++ b/tools/qfcc/test/tw-defspace.c @@ -0,0 +1 @@ +#include "../source/defspace.c" diff --git a/tools/qfcc/test/tw-diagnostic.c b/tools/qfcc/test/tw-diagnostic.c new file mode 100644 index 000000000..d84f8ad33 --- /dev/null +++ b/tools/qfcc/test/tw-diagnostic.c @@ -0,0 +1 @@ +#include "../source/diagnostic.c" diff --git a/tools/qfcc/test/tw-strpool.c b/tools/qfcc/test/tw-strpool.c new file mode 100644 index 000000000..74fbb8d75 --- /dev/null +++ b/tools/qfcc/test/tw-strpool.c @@ -0,0 +1 @@ +#include "../source/strpool.c" From 34bcf7faab89298a031677866f248f5531aece88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Oct 2018 12:35:01 +0900 Subject: [PATCH 0058/3664] Do a pure/const/noreturn/format attribute pass. I always wanted these, but as gcc now provides warnings for functions that could do with such attributes, finding all the functions is much easier. --- config.d/compiling.m4 | 4 ++ hw/source/master.c | 4 +- include/QF/GLSL/qf_lightmap.h | 2 +- include/QF/GLSL/qf_textures.h | 2 +- include/QF/cmd.h | 10 ++--- include/QF/console.h | 6 +-- include/QF/crc.h | 4 +- include/QF/cvar.h | 4 +- include/QF/dstring.h | 4 +- include/QF/gib.h | 8 ++-- include/QF/hash.h | 6 +-- include/QF/info.h | 4 +- include/QF/joystick.h | 8 ++-- include/QF/keys.h | 8 ++-- include/QF/llist.h | 4 +- include/QF/locs.h | 4 +- include/QF/math/half.h | 4 +- include/QF/math/matrix3.h | 2 +- include/QF/math/vector.h | 6 +-- include/QF/mathlib.h | 12 +++--- include/QF/model.h | 4 +- include/QF/msg.h | 2 +- include/QF/plugin.h | 2 +- include/QF/plugin/console.h | 2 +- include/QF/progs.h | 30 +++++++------- include/QF/qargs.h | 2 +- include/QF/qendian.h | 12 +++--- include/QF/qfplist.h | 10 ++--- include/QF/quakefs.h | 4 +- include/QF/quakeio.h | 2 +- include/QF/script.h | 2 +- include/QF/set.h | 16 ++++---- include/QF/sys.h | 4 +- include/QF/zone.h | 4 +- include/d_iface.h | 2 +- include/d_local.h | 6 +-- include/exp.h | 2 +- include/gib_buffer.h | 2 +- include/gib_parse.h | 4 +- include/gib_regex.h | 6 +-- include/netchan.h | 8 ++-- include/ops.h | 56 +++++++++++++------------- include/qstring.h | 4 +- include/qw/msg_backbuf.h | 2 +- include/qw/pmove.h | 4 +- include/r_internal.h | 4 +- include/r_local.h | 2 +- include/r_screen.h | 2 +- include/snd_internal.h | 10 ++--- include/world.h | 6 +-- libs/audio/targets/snd_alsa.c | 2 +- libs/console/client.c | 2 +- libs/console/server.c | 2 +- libs/gamecode/pr_strings.c | 4 +- libs/gib/exp.c | 2 +- libs/net/nm/net_dgrm.c | 4 +- libs/net/nm/net_loop.c | 6 +-- libs/net/nm/net_udp.c | 6 +-- libs/net/nm/net_vcr.c | 4 +- libs/util/dstring.c | 2 +- libs/util/set.c | 12 +++--- libs/util/sys.c | 4 +- libs/util/test/test-vrect.c | 2 +- libs/video/renderer/gl/qfgl_ext.c | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 2 +- libs/video/renderer/glsl/glsl_screen.c | 2 +- libs/video/renderer/sw32/screen.c | 2 +- libs/video/targets/keys.c | 2 +- nq/include/host.h | 6 +-- nq/include/server.h | 4 +- nq/source/host_cmd.c | 2 +- nq/source/sv_ded.c | 4 +- nq/source/sv_pr_cmds.c | 2 +- nq/source/world.c | 2 +- qtv/source/qtv.c | 2 +- qw/include/cl_cam.h | 6 +-- qw/include/cl_parse.h | 2 +- qw/include/crudefile.h | 2 +- qw/include/host.h | 4 +- qw/include/server.h | 10 ++--- qw/include/sv_recorder.h | 4 +- qw/source/cl_slist.c | 4 +- qw/source/sv_main.c | 4 +- qw/source/sv_pr_cmds.c | 4 +- qw/source/world.c | 4 +- tools/qfbsp/include/brush.h | 2 +- tools/qfbsp/include/map.h | 2 +- tools/qfbsp/source/outside.c | 2 +- tools/qfbsp/source/portals.c | 8 ++-- tools/qfbsp/source/solidbsp.c | 4 +- tools/qfcc/include/class.h | 16 ++++---- tools/qfcc/include/def.h | 6 +-- tools/qfcc/include/expr.h | 38 ++++++++--------- tools/qfcc/include/qfcc.h | 2 +- tools/qfcc/include/statements.h | 14 +++---- tools/qfcc/include/symtab.h | 2 +- tools/qfcc/include/type.h | 22 +++++----- tools/qfcc/source/class.c | 2 +- tools/qfcc/source/constfold.c | 2 +- tools/qfcc/source/dags.c | 2 +- tools/qfcc/source/diagnostic.c | 4 +- tools/qfcc/source/expr.c | 4 +- tools/qfcc/source/flow.c | 2 +- tools/qfcc/source/method.c | 2 +- tools/qfcc/source/obj_file.c | 2 +- tools/qfcc/source/qc-lex.l | 7 ++++ tools/qfcc/source/qfcc.c | 2 +- tools/qfcc/source/qp-lex.l | 9 ++++- tools/qfcc/source/stub.c | 10 ++--- tools/qfcc/source/switch.c | 6 +-- tools/qfcc/source/type.c | 2 +- tools/qfcc/source/value.c | 4 +- tools/qfcc/test/test-defspace.c | 2 +- tools/qflight/include/light.h | 2 +- tools/qflight/include/noise.h | 8 ++-- tools/qflight/include/options.h | 2 +- tools/qflight/source/vis.c | 2 +- tools/qfvis/include/options.h | 2 +- 118 files changed, 332 insertions(+), 314 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 457882d09..343218d35 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -213,6 +213,10 @@ if test $CC_MAJ -gt 4 -o $CC_MAJ -eq 4 -a $CC_MIN -ge 5; then fi QF_CC_OPTION(-Wtype-limits) QF_CC_OPTION_TEST([-fvisibility=hidden], [VISIBILITY=-fvisibility=hidden]) +QF_CC_OPTION(-Wsuggest-attribute=pure) +QF_CC_OPTION(-Wsuggest-attribute=const) +QF_CC_OPTION(-Wsuggest-attribute=noreturn) +QF_CC_OPTION(-Wsuggest-attribute=format) dnl QuakeForge uses lots of BCPL-style (//) comments, which can cause problems dnl with many compilers that do not support the latest ISO standards. Well, diff --git a/hw/source/master.c b/hw/source/master.c index 4617e3c7d..6e744c4ac 100644 --- a/hw/source/master.c +++ b/hw/source/master.c @@ -121,7 +121,7 @@ FL_Add (filter_t * filter) filter_list = filter; } -static filter_t * +static __attribute__((pure)) filter_t * FL_Find (netadr_t adr) { filter_t *filter; @@ -209,7 +209,7 @@ SVL_Add (server_t *sv) sv_list = sv; } -static server_t * +static __attribute__((pure)) server_t * SVL_Find (netadr_t adr) { server_t *sv; diff --git a/include/QF/GLSL/qf_lightmap.h b/include/QF/GLSL/qf_lightmap.h index ef828d6d8..7619ed890 100644 --- a/include/QF/GLSL/qf_lightmap.h +++ b/include/QF/GLSL/qf_lightmap.h @@ -37,7 +37,7 @@ void glsl_lightmap_init (void); void glsl_R_BuildLightmaps (struct model_s **models, int num_models); void glsl_R_CalcLightmaps (void); extern void (*glsl_R_BuildLightMap) (msurface_t *surf); -int glsl_R_LightmapTexture (void); +int glsl_R_LightmapTexture (void) __attribute__((pure)); void glsl_R_FlushLightmaps (void); #endif//__QF_GLSL_lightmap_h diff --git a/include/QF/GLSL/qf_textures.h b/include/QF/GLSL/qf_textures.h index 1447d797a..5f30fbf68 100644 --- a/include/QF/GLSL/qf_textures.h +++ b/include/QF/GLSL/qf_textures.h @@ -55,7 +55,7 @@ void GLSL_TextureInit (void); scrap_t *GLSL_CreateScrap (int size, int format, int linear); void GLSL_DestroyScrap (scrap_t *scrap); void GLSL_ScrapClear (scrap_t *scrap); -int GLSL_ScrapTexture (scrap_t *scrap); +int GLSL_ScrapTexture (scrap_t *scrap) __attribute__((pure)); subpic_t *GLSL_ScrapSubpic (scrap_t *scrap, int width, int height); //XXX slow! void GLSL_SubpicDelete (subpic_t *subpic); //XXX slow! void GLSL_SubpicUpdate (subpic_t *subpic, byte *data, int batch); diff --git a/include/QF/cmd.h b/include/QF/cmd.h index 85131083e..2ac508b9f 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -60,14 +60,14 @@ int Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *desc int Cmd_RemoveCommand (const char *cmd_name); qboolean Cmd_Exists (const char *cmd_name); -const char *Cmd_CompleteCommand (const char *partial); -int Cmd_CompleteCountPossible (const char *partial); +const char *Cmd_CompleteCommand (const char *partial) __attribute__((pure)); +int Cmd_CompleteCountPossible (const char *partial) __attribute__((pure)); const char **Cmd_CompleteBuildList (const char *partial); -int Cmd_Argc (void); -const char *Cmd_Argv (int arg); -const char *Cmd_Args (int start); +int Cmd_Argc (void) __attribute__((pure)); +const char *Cmd_Argv (int arg) __attribute__((pure)); +const char *Cmd_Args (int start) __attribute__((pure)); struct cbuf_args_s; int Cmd_Command (struct cbuf_args_s *args); int Cmd_ExecuteString (const char *text, cmd_source_t src); diff --git a/include/QF/console.h b/include/QF/console.h index eeb9010d6..4f3bcb3c8 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -92,8 +92,8 @@ extern struct console_data_s con_data; void Con_CheckResize (void); void Con_DrawConsole (void); -void Con_Printf (const char *fmt, ...); -void Con_Print (const char *fmt, va_list args); +void Con_Printf (const char *fmt, ...) __attribute__((format(printf, 1, 2))); +void Con_Print (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); void Con_ToggleConsole_f (void); // wrapper function to attempt to either complete the command line @@ -105,7 +105,7 @@ void Con_BasicCompleteCommandLine (inputline_t *il); // Generic libs/util/console.c function to display a list // formatted in columns on the console void Con_DisplayList(const char **list, int con_linewidth); -extern void (*con_list_print)(const char *fmt, ...); +extern void (*con_list_print)(const char *fmt, ...) __attribute__((format(printf, 1, 2))); inputline_t *Con_CreateInputLine (int lines, int lsize, char prompt); void Con_DestroyInputLine (inputline_t *inputline); diff --git a/include/QF/crc.h b/include/QF/crc.h index 8c3154137..2aa16b616 100644 --- a/include/QF/crc.h +++ b/include/QF/crc.h @@ -38,8 +38,8 @@ void CRC_Init(unsigned short *crcvalue); void CRC_ProcessByte(unsigned short *crcvalue, byte data); void CRC_ProcessBlock (const byte *start, unsigned short *crcvalue, int count); -unsigned short CRC_Value(unsigned short crcvalue); -unsigned short CRC_Block (const byte *start, int count); +unsigned short CRC_Value(unsigned short crcvalue) __attribute__((const)); +unsigned short CRC_Block (const byte *start, int count) __attribute__((pure)); //@} diff --git a/include/QF/cvar.h b/include/QF/cvar.h index 4f182d285..091a13b61 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -122,12 +122,12 @@ void Cvar_WriteVariables (QFile *f); // attempts to match a partial variable name for command line completion // returns NULL if nothing fits -const char *Cvar_CompleteVariable (const char *partial); +const char *Cvar_CompleteVariable (const char *partial) __attribute__((pure)); // Added by EvilTypeGuy - functions for tab completion system // Thanks to Fett erich@heintz.com // Thanks to taniwha -int Cvar_CompleteCountPossible (const char *partial); +int Cvar_CompleteCountPossible (const char *partial) __attribute__((pure)); const char **Cvar_CompleteBuildList (const char *partial); // Returns a pointer to the Cvar, NULL if not found diff --git a/include/QF/dstring.h b/include/QF/dstring.h index 85ea7d61f..1075bc04b 100644 --- a/include/QF/dstring.h +++ b/include/QF/dstring.h @@ -164,14 +164,14 @@ void dstring_clearstr (dstring_t *dstr); /** Formatted printing to dstrings. Existing data is replaced by the formatted string. */ -int dvsprintf (dstring_t *dstr, const char *fmt, va_list args); +int dvsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); int dsprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); //@} //@{ /** Formatted printing to dstrings. Formatted string is appened to the dstring. Embedded nulls in the dstring are ignored. */ -int davsprintf (dstring_t *dstr, const char *fmt, va_list args); +int davsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); int dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); //@} diff --git a/include/QF/gib.h b/include/QF/gib.h index aa97e3b05..34c187ac7 100644 --- a/include/QF/gib.h +++ b/include/QF/gib.h @@ -182,7 +182,7 @@ extern char * const gib_null_string; #define GIB_CanReturn() (GIB_DATA(cbuf_active)->waitret) dstring_t *GIB_Return (const char *str); -void GIB_Error (const char *type, const char *fmt, ...); +void GIB_Error (const char *type, const char *fmt, ...) __attribute__((format(printf, 2, 3))); void GIB_Builtin_Add (const char *name, void (*func) (void)); void GIB_Builtin_Remove (const char *name); qboolean GIB_Builtin_Exists (const char *name); @@ -199,12 +199,12 @@ void GIB_Event_Callback (gib_event_t *event, unsigned int argc, ...); // Interpreter interface (for creating GIB cbufs) -cbuf_interpreter_t *GIB_Interpreter (void); +cbuf_interpreter_t *GIB_Interpreter (void) __attribute__((const)); // Thread interface void GIB_Thread_Execute (void); -unsigned int GIB_Thread_Count (void); +unsigned int GIB_Thread_Count (void) __attribute__((pure)); // Init interface @@ -214,6 +214,6 @@ void GIB_Init (qboolean sandbox); unsigned long int GIB_Handle_New (gib_object_t *data); void GIB_Handle_Free (unsigned long int num); -gib_object_t *GIB_Handle_Get (unsigned long int num); +gib_object_t *GIB_Handle_Get (unsigned long int num) __attribute__((pure)); #endif diff --git a/include/QF/hash.h b/include/QF/hash.h index 5cff9d115..1a8a8f912 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -177,20 +177,20 @@ void Hash_Free (hashtab_t *tab, void *ele); this is the same function as used internally. */ -unsigned long Hash_String (const char *str); +unsigned long Hash_String (const char *str) __attribute__((pure)); /** hash a buffer. \param buf the buffer to hash \param len the size of the buffer \return the hash value of the string. */ -unsigned long Hash_Buffer (const void *buf, int len); +unsigned long Hash_Buffer (const void *buf, int len) __attribute__((pure)); /** get the size of the table \param tab the table in question \return the number of elements in the table. */ -size_t Hash_NumElements (hashtab_t *tab); +size_t Hash_NumElements (hashtab_t *tab) __attribute__((pure)); /** list of all elements in the table. \param tab the table to list diff --git a/include/QF/info.h b/include/QF/info.h index 518a35c23..d57a221f6 100644 --- a/include/QF/info.h +++ b/include/QF/info.h @@ -47,10 +47,10 @@ typedef struct info_key_s { const char *value; } info_key_t; -qboolean Info_FilterForKey (const char *key, const char **filter_list); +qboolean Info_FilterForKey (const char *key, const char **filter_list) __attribute__((pure)); void Info_Print (info_t *info); -int Info_CurrentSize (info_t *info); +int Info_CurrentSize (info_t *info) __attribute__((pure)); info_key_t *Info_Key (info_t *info, const char *key); info_key_t **Info_KeyList (info_t *info); void Info_RemoveKey (info_t *info, const char *key); diff --git a/include/QF/joystick.h b/include/QF/joystick.h index 781f783a9..1eeba5d49 100644 --- a/include/QF/joystick.h +++ b/include/QF/joystick.h @@ -144,11 +144,11 @@ void JOY_Close (void); void JOY_Read (void); -const char *JOY_GetOption_c (int i); -int JOY_GetOption_i (const char *c); +const char *JOY_GetOption_c (int i) __attribute__((pure)); +int JOY_GetOption_i (const char *c) __attribute__((pure)); -const char *JOY_GetDest_c (int i); -int JOY_GetDest_i (const char *c); +const char *JOY_GetDest_c (int i) __attribute__((pure)); +int JOY_GetDest_i (const char *c) __attribute__((pure)); int JOY_GetAxis_i (int dest, const char *c); diff --git a/include/QF/keys.h b/include/QF/keys.h index f79291dc0..ada46a265 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -544,7 +544,7 @@ void Key_Init_Cvars (void); \param imt_name The name of the imt to find. Case insensitive. \return The named imt, or null if not found. */ -imt_t *Key_FindIMT (const char *imt_name); +imt_t *Key_FindIMT (const char *imt_name) __attribute__((pure)); /** Create a new imt and attach it to the specified keydest target. @@ -599,7 +599,7 @@ void Key_ClearStates (void); \param key The key for which to get the binding. \return The command string bound to the key, or null if unbound. */ -const char *Key_GetBinding (imt_t *imt, knum_t key); +const char *Key_GetBinding (imt_t *imt, knum_t key) __attribute__((pure)); /** Bind a command string to a key in the specified input mapping table. @@ -639,7 +639,7 @@ void Key_KeydestCallback (keydest_callback_t *callback); \param keynum The key for which to get the string. \return The string representation of the key. */ -const char *Key_KeynumToString (knum_t keynum); +const char *Key_KeynumToString (knum_t keynum) __attribute__((pure)); /** Get the keynum for the named key. @@ -650,7 +650,7 @@ const char *Key_KeynumToString (knum_t keynum); \param str The name of the key. \return The named key if valid, otherwise -1 */ -int Key_StringToKeynum (const char *str); +int Key_StringToKeynum (const char *str) __attribute__((pure)); struct progs_s; diff --git a/include/QF/llist.h b/include/QF/llist.h index 7253618b2..a7488b312 100644 --- a/include/QF/llist.h +++ b/include/QF/llist.h @@ -53,11 +53,11 @@ void llist_flush (llist_t *list); void llist_delete (llist_t *list); llist_node_t *llist_append (llist_t *list, void *element); llist_node_t *llist_prefix (llist_t *list, void *element); -llist_node_t *llist_getnode (llist_t *list, void *element); +llist_node_t *llist_getnode (llist_t *list, void *element) __attribute__((pure)); llist_node_t *llist_insertafter (llist_node_t *ref, void *element); llist_node_t *llist_insertbefore (llist_node_t *ref, void *element); void *llist_remove (llist_node_t *ref); -unsigned int llist_size (llist_t *llist); +unsigned int llist_size (llist_t *llist) __attribute__((pure)); void llist_iterate (llist_t *list, llist_iterator_t iterate); void *llist_find (llist_t *list, void *comparison); llist_node_t *llist_findnode (llist_t *list, void *comparison); diff --git a/include/QF/locs.h b/include/QF/locs.h index 32cb4ea0d..425e8980d 100644 --- a/include/QF/locs.h +++ b/include/QF/locs.h @@ -36,13 +36,13 @@ typedef struct char *name; } location_t; -location_t *locs_find(const vec3_t target); +location_t *locs_find(const vec3_t target) __attribute__((pure)); void locs_add (const vec3_t location, const char *name); void locs_del (const vec3_t loc); void locs_edit (const vec3_t loc, const char *desc); void locs_load(const char *filename); void locs_mark (const vec3_t loc, const char *desc); -int locs_nearest (const vec3_t loc); +int locs_nearest (const vec3_t loc) __attribute__((pure)); void locs_reset (void); void locs_save (const char *filename, qboolean gz); void map_to_loc (const char *mapname, char *filename); diff --git a/include/QF/math/half.h b/include/QF/math/half.h index 61baf8f09..1fe474cd3 100644 --- a/include/QF/math/half.h +++ b/include/QF/math/half.h @@ -39,8 +39,8 @@ #include "QF/qtypes.h" -int16_t FloatToHalf (float x); -float HalfToFloat (int16_t x); +int16_t FloatToHalf (float x) __attribute__((const)); +float HalfToFloat (int16_t x) __attribute__((const)); //@} diff --git a/include/QF/math/matrix3.h b/include/QF/math/matrix3.h index 7a54938dd..ce2474a99 100644 --- a/include/QF/math/matrix3.h +++ b/include/QF/math/matrix3.h @@ -101,7 +101,7 @@ void Mat3Init (const quat_t rot, const vec3_t scale, mat3_t mat); void Mat3Transpose (const mat3_t a, mat3_t b); -vec_t Mat3Determinant (const mat3_t m); +vec_t Mat3Determinant (const mat3_t m) __attribute__((pure)); int Mat3Inverse (const mat3_t a, mat3_t b); void Mat3Mult (const mat3_t a, const mat3_t b, mat3_t c); void Mat3MultVec (const mat3_t a, const vec3_t b, vec3_t c); diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 994ffee62..73cc1f708 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -171,11 +171,11 @@ extern const vec_t *const vec3_origin; (((a)[2] - (b)[2]) * ((a)[2] - (b)[2]))) #define VectorDistance(a, b) sqrt(VectorDistance_fast(a, b)) -vec_t _DotProduct (const vec3_t v1, const vec3_t v2); +vec_t _DotProduct (const vec3_t v1, const vec3_t v2) __attribute__((pure)); void _VectorAdd (const vec3_t veca, const vec3_t vecb, vec3_t out); void _VectorCopy (const vec3_t in, vec3_t out); -int _VectorCompare (const vec3_t v1, const vec3_t v2); // uses EQUAL_EPSILON -vec_t _VectorLength (const vec3_t v); +int _VectorCompare (const vec3_t v1, const vec3_t v2) __attribute__((pure)); // uses EQUAL_EPSILON +vec_t _VectorLength (const vec3_t v) __attribute__((pure)); void _VectorMA (const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc); void _VectorScale (const vec3_t in, vec_t scale, vec3_t out); diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index 498dbd2d0..c4575705e 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -73,15 +73,15 @@ extern int nanmask; // fall over #define ROLL 2 -int Q_log2(int val); +int Q_log2(int val) __attribute__((const)); void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]); void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]); void FloorDivMod (double numer, double denom, int *quotient, int *rem); -fixed16_t Invert24To16(fixed16_t val); +fixed16_t Invert24To16(fixed16_t val) __attribute__((const)); fixed16_t Mul16_30(fixed16_t multiplier, fixed16_t multiplicand); -int GreatestCommonDivisor (int i1, int i2); +int GreatestCommonDivisor (int i1, int i2) __attribute__((const)); /** Convert quake angles to basis vectors. @@ -139,8 +139,8 @@ void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, void AngleQuat (const vec3_t angles, quat_t q); void VectorVectors (const vec3_t forward, vec3_t right, vec3_t up); int BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, - struct plane_s *plane); -float anglemod (float a); + struct plane_s *plane) __attribute__((pure)); +float anglemod (float a) __attribute__((const)); void RotatePointAroundVector (vec3_t dst, const vec3_t axis, const vec3_t point, float degrees); @@ -174,7 +174,7 @@ void RotatePointAroundVector (vec3_t dst, const vec3_t axis, } while (0) extern plane_t * const frustum; -GNU89INLINE inline qboolean R_CullBox (const vec3_t mins, const vec3_t maxs); +GNU89INLINE inline qboolean R_CullBox (const vec3_t mins, const vec3_t maxs) __attribute__((pure)); GNU89INLINE inline qboolean R_CullSphere (const vec3_t origin, const float radius); #ifndef IMPLEMENT_R_Cull diff --git a/include/QF/model.h b/include/QF/model.h index 641e025ec..6b3fbc3b5 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -433,7 +433,7 @@ typedef struct model_s { // ============================================================================ -extern float RadiusFromBounds (const vec3_t mins, const vec3_t maxs); +extern float RadiusFromBounds (const vec3_t mins, const vec3_t maxs) __attribute__((pure)); void Mod_Init (void); void Mod_Init_Cvars (void); void Mod_ClearAll (void); @@ -441,7 +441,7 @@ model_t *Mod_ForName (const char *name, qboolean crash); void *Mod_Extradata (model_t *mod); // handles caching void Mod_TouchModel (const char *name); -mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model); +mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure)); byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); model_t *Mod_FindName (const char *name); int Mod_CalcFullbright (byte *in, byte *out, int pixels); diff --git a/include/QF/msg.h b/include/QF/msg.h index 63da220e9..6e550a191 100644 --- a/include/QF/msg.h +++ b/include/QF/msg.h @@ -73,7 +73,7 @@ void MSG_BeginReading (qmsg_t *msg); \param msg The message to check. \return The number of bytes that have been read. */ -int MSG_GetReadCount(qmsg_t *msg); +int MSG_GetReadCount(qmsg_t *msg) __attribute__((pure)); /** Read a single byte from the message. diff --git a/include/QF/plugin.h b/include/QF/plugin.h index 995b72750..57a4ba9ff 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -38,7 +38,7 @@ #include #ifdef STATIC_PLUGINS -#define PLUGIN_INFO(type,name) plugin_t *type##_##name##_PluginInfo (void); plugin_t * type##_##name##_PluginInfo (void) +#define PLUGIN_INFO(type,name) plugin_t *type##_##name##_PluginInfo (void); __attribute__((const)) plugin_t * type##_##name##_PluginInfo (void) #else #define PLUGIN_INFO(type,name) plugin_t *PluginInfo (void); __attribute__((visibility ("default"))) plugin_t *PluginInfo (void) #endif diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index e743d20e7..b404728e3 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -34,7 +34,7 @@ #include #include -typedef void (*P_C_Print) (const char *fmt, va_list args); +typedef void (*P_C_Print) (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); typedef void (*P_C_ProcessInput) (void); typedef void (*P_C_KeyEvent) (knum_t key, short unicode, qboolean down); typedef void (*P_C_DrawConsole) (void); diff --git a/include/QF/progs.h b/include/QF/progs.h index 1c706ae4c..72eea81cc 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -228,10 +228,10 @@ struct edict_s { void ED_ClearEdict (progs_t *pr, edict_t *e, int val); edict_t *ED_Alloc (progs_t *pr); void ED_Free (progs_t *pr, edict_t *ed); -edict_t *ED_EdictNum(progs_t *pr, pr_int_t n); -pr_int_t ED_NumForEdict(progs_t *pr, edict_t *e); +edict_t *ED_EdictNum(progs_t *pr, pr_int_t n) __attribute__((pure)); +pr_int_t ED_NumForEdict(progs_t *pr, edict_t *e) __attribute__((pure)); void ED_Count (progs_t *pr); -qboolean PR_EdictValid (progs_t *pr, pr_int_t e); +qboolean PR_EdictValid (progs_t *pr, pr_int_t e) __attribute__((pure)); // pr_debug.c void ED_Print (progs_t *pr, edict_t *ed); @@ -274,8 +274,8 @@ void ED_EntityParseFunction (progs_t *pr); */ //@{ -ddef_t *PR_FieldAtOfs (progs_t *pr, pr_int_t ofs); -ddef_t *PR_GlobalAtOfs (progs_t *pr, pr_int_t ofs); +ddef_t *PR_FieldAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure)); +ddef_t *PR_GlobalAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure)); ddef_t *PR_FindField (progs_t *pr, const char *name); ddef_t *PR_FindGlobal (progs_t *pr, const char *name); @@ -1112,21 +1112,21 @@ int PR_LoadStrings (progs_t *pr); \param num string index to be validated \return true if the index is valid, false otherwise */ -qboolean PR_StringValid (progs_t *pr, string_t num); +qboolean PR_StringValid (progs_t *pr, string_t num) __attribute__((pure)); /** Convert a string index to a C string. \param pr pointer to ::progs_t VM struct \param num string index to be converted \return C pointer to the string. */ -const char *PR_GetString(progs_t *pr, string_t num); +const char *PR_GetString(progs_t *pr, string_t num) __attribute__((pure)); /** Retrieve the dstring_t associated with a mutable string. \param pr pointer to ::progs_t VM struct \param num string index of the mutable string \return the dstring implementing the mutable string */ -struct dstring_s *PR_GetMutableString(progs_t *pr, string_t num); +struct dstring_s *PR_GetMutableString(progs_t *pr, string_t num) __attribute__((pure)); /** Make a permanent progs string from the given C string. Will not create a duplicate permanent string (temporary and mutable strings are not checked). @@ -1450,14 +1450,14 @@ void PR_Debug_Init_Cvars (void); int PR_LoadDebug (progs_t *pr); void PR_Debug_Watch (progs_t *pr, const char *expr); void PR_Debug_Print (progs_t *pr, const char *expr); -pr_auxfunction_t *PR_Get_Lineno_Func (progs_t *pr, pr_lineno_t *lineno); -pr_uint_t PR_Get_Lineno_Addr (progs_t *pr, pr_lineno_t *lineno); -pr_uint_t PR_Get_Lineno_Line (progs_t *pr, pr_lineno_t *lineno); -pr_lineno_t *PR_Find_Lineno (progs_t *pr, pr_uint_t addr); -const char *PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno); +pr_auxfunction_t *PR_Get_Lineno_Func (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); +pr_uint_t PR_Get_Lineno_Addr (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); +pr_uint_t PR_Get_Lineno_Line (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); +pr_lineno_t *PR_Find_Lineno (progs_t *pr, pr_uint_t addr) __attribute__((pure)); +const char *PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); const char *PR_Get_Source_Line (progs_t *pr, pr_uint_t addr); -ddef_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm); -ddef_t *PR_Get_Local_Def (progs_t *pr, pr_int_t offs); +ddef_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) __attribute__((pure)); +ddef_t *PR_Get_Local_Def (progs_t *pr, pr_int_t offs) __attribute__((pure)); void PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents); void PR_DumpState (progs_t *pr); void PR_StackTrace (progs_t *pr); diff --git a/include/QF/qargs.h b/include/QF/qargs.h index 5b4252075..fe4eb98f8 100644 --- a/include/QF/qargs.h +++ b/include/QF/qargs.h @@ -42,7 +42,7 @@ extern const char *com_cmdline; extern struct cvar_s *fs_globalcfg; extern struct cvar_s *fs_usercfg; -int COM_CheckParm (const char *parm); +int COM_CheckParm (const char *parm) __attribute__((pure)); void COM_AddParm (const char *parm); void COM_Init (void); diff --git a/include/QF/qendian.h b/include/QF/qendian.h index 49e60c2aa..d63ca2d0c 100644 --- a/include/QF/qendian.h +++ b/include/QF/qendian.h @@ -75,12 +75,12 @@ extern qboolean bigendien; -uint16_t _ShortSwap (uint16_t l); -uint16_t _ShortNoSwap (uint16_t l); -uint32_t _LongSwap (uint32_t l); -uint32_t _LongNoSwap (uint32_t l); -float _FloatSwap (float f); -float _FloatNoSwap (float f); +uint16_t _ShortSwap (uint16_t l) __attribute__((const)); +uint16_t _ShortNoSwap (uint16_t l) __attribute__((const)); +uint32_t _LongSwap (uint32_t l) __attribute__((const)); +uint32_t _LongNoSwap (uint32_t l) __attribute__((const)); +float _FloatSwap (float f) __attribute__((const)); +float _FloatNoSwap (float f) __attribute__((const)); #ifdef __GNUC__ diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 713eb6dbb..6c5d61202 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -75,7 +75,7 @@ char *PL_WritePropertyList (plitem_t *pl); \param item The object \return the type of the object */ -pltype_t PL_Type (plitem_t *item); +pltype_t PL_Type (plitem_t *item) __attribute__((pure)); /** Retrieve a string from a string object. @@ -85,7 +85,7 @@ pltype_t PL_Type (plitem_t *item); \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ -const char *PL_String (plitem_t *string); +const char *PL_String (plitem_t *string) __attribute__((pure)); /** Retrieve a value from a dictionary object. @@ -117,7 +117,7 @@ plitem_t *PL_RemoveObjectForKey (plitem_t *dict, const char *key); \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ -plitem_t *PL_ObjectAtIndex (plitem_t *array, int index); +plitem_t *PL_ObjectAtIndex (plitem_t *array, int index) __attribute__((pure)); /** Retrieve a list of all keys in a dictionary. @@ -133,7 +133,7 @@ plitem_t *PL_D_AllKeys (plitem_t *dict); \return Returns the number of keys in the dictionary. */ -int PL_D_NumKeys (plitem_t *dict); +int PL_D_NumKeys (plitem_t *dict) __attribute__((pure)); /** Add a key/value pair to a dictionary. @@ -164,7 +164,7 @@ qboolean PL_A_AddObject (plitem_t *array, plitem_t *item); \return number of objects in the array */ -int PL_A_NumObjects (plitem_t *array); +int PL_A_NumObjects (plitem_t *array) __attribute__((pure)); /** Insert an item into an array before the specified location. diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index aab034381..336537495 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -356,7 +356,7 @@ char *QFS_CompressPath (const char *pth); \return Pointer to the beginning of the filename. This points inside \a pathname. */ -const char *QFS_SkipPath (const char *pathname); +const char *QFS_SkipPath (const char *pathname) __attribute__((pure)); /** Return a pointer to the start of the extention part of the path. @@ -366,7 +366,7 @@ const char *QFS_SkipPath (const char *pathname); the returned pointer will point to the terminating nul of the path. */ -const char *QFS_FileExtension (const char *in); +const char *QFS_FileExtension (const char *in) __attribute__((pure)); /** Register a callback function for when the gamedir changes. diff --git a/include/QF/quakeio.h b/include/QF/quakeio.h index 0664bd0b6..d72d8ec29 100644 --- a/include/QF/quakeio.h +++ b/include/QF/quakeio.h @@ -40,7 +40,7 @@ typedef struct QFile_s QFile; int Qrename(const char *old_path, const char *new_path); int Qremove(const char *path); -int Qfilesize (QFile *file); +int Qfilesize (QFile *file) __attribute__((pure)); QFile *Qopen(const char *path, const char *mode); QFile *Qdopen(int fd, const char *mode); QFile *Qfopen (FILE *file, const char *mode); diff --git a/include/QF/script.h b/include/QF/script.h index bc11b0e2a..2fe21c215 100644 --- a/include/QF/script.h +++ b/include/QF/script.h @@ -95,7 +95,7 @@ void Script_UngetToken (script_t *script); /** Return a pointer to the current token. \param script The script_t object being parsed */ -const char *Script_Token (script_t *script); +const char *Script_Token (script_t *script) __attribute__((pure)); //@} diff --git a/include/QF/set.h b/include/QF/set.h index a30840b18..0d50700da 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -256,14 +256,14 @@ set_t *set_everything (set_t *set); \param set The set to test. \return 1 if \a set is empty (non-inverted). */ -int set_is_empty (const set_t *set); +int set_is_empty (const set_t *set) __attribute__((pure)); /** Test if a set is the set of everything. \param set The set to test. \return 1 if \a set is the set of everything (empty inverted set). */ -int set_is_everything (const set_t *set); +int set_is_everything (const set_t *set) __attribute__((pure)); /** Test if two sets are disjoint. @@ -273,7 +273,7 @@ int set_is_everything (const set_t *set); \note The emtpy set is disjoint with itself. */ -int set_is_disjoint (const set_t *s1, const set_t *s2); +int set_is_disjoint (const set_t *s1, const set_t *s2) __attribute__((pure)); /** Test if two sets intersect. @@ -283,7 +283,7 @@ int set_is_disjoint (const set_t *s1, const set_t *s2); \note Equivalent non-empty sets are treated as intersecting. */ -int set_is_intersecting (const set_t *s1, const set_t *s2); +int set_is_intersecting (const set_t *s1, const set_t *s2) __attribute__((pure)); /** Test if two sets are equivalent. @@ -291,7 +291,7 @@ int set_is_intersecting (const set_t *s1, const set_t *s2); \param s2 The second set to test. \return 1 if \a s2 is equivalent to \a s1, 0 if not. */ -int set_is_equivalent (const set_t *s1, const set_t *s2); +int set_is_equivalent (const set_t *s1, const set_t *s2) __attribute__((pure)); /** Test if a set is a subset of another set. @@ -302,7 +302,7 @@ int set_is_equivalent (const set_t *s1, const set_t *s2); \return 1 if \a sub is a subset of \a set, or if the sets are equivalent. */ -int set_is_subset (const set_t *set, const set_t *sub); +int set_is_subset (const set_t *set, const set_t *sub) __attribute__((pure)); /** Test an element for membership in a set. @@ -310,7 +310,7 @@ int set_is_subset (const set_t *set, const set_t *sub); \param x The element to test. \return 1 if the element is a member of the set, otherwise 0. */ -int set_is_member (const set_t *set, unsigned x); +int set_is_member (const set_t *set, unsigned x) __attribute__((pure)); /** Obtain the number of members (or non-members) of a set. @@ -322,7 +322,7 @@ int set_is_member (const set_t *set, unsigned x); \return The number of (non-)members. Both empty sets and sets of evertything will return 0. */ -unsigned set_size (const set_t *set); +unsigned set_size (const set_t *set) __attribute__((pure)); /** Find the first "member" of the set. diff --git a/include/QF/sys.h b/include/QF/sys.h index 8bbb08781..f93432d65 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -62,7 +62,7 @@ int Sys_FileExists (const char *path); int Sys_isdir (const char *path); int Sys_mkdir (const char *path); -typedef void (*sys_printf_t) (const char *fmt, va_list args); +typedef void (*sys_printf_t) (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); typedef void (*sys_error_t) (void *data); void Sys_SetStdPrintf (sys_printf_t func); @@ -71,7 +71,7 @@ void Sys_SetErrPrintf (sys_printf_t func); void Sys_PushErrorHandler (sys_error_t func, void *data); void Sys_PopErrorHandler (void); -void Sys_Print (FILE *stream, const char *fmt, va_list args); +void Sys_Print (FILE *stream, const char *fmt, va_list args) __attribute__((format(printf, 2, 0))); void Sys_Printf (const char *fmt, ...) __attribute__((format(printf,1,2))); void Sys_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); void Sys_FatalError (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); diff --git a/include/QF/zone.h b/include/QF/zone.h index 22c7bc19f..379f4557a 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -107,7 +107,7 @@ void Z_CheckPointer (const memzone_t *zone, const void *ptr, int size); void *Hunk_Alloc (int size); // returns 0 filled memory void *Hunk_AllocName (int size, const char *name); -int Hunk_LowMark (void); +int Hunk_LowMark (void) __attribute__((pure)); void Hunk_FreeToLowMark (int mark); void *Hunk_TempAlloc (int size); void Hunk_Check (void); @@ -138,7 +138,7 @@ void Cache_Remove (cache_user_t *c); void *Cache_TryGet (cache_user_t *c); void *Cache_Get (cache_user_t *c); void Cache_Release (cache_user_t *c); -int Cache_ReadLock (cache_user_t *c); +int Cache_ReadLock (cache_user_t *c) __attribute__((pure)); //@} diff --git a/include/d_iface.h b/include/d_iface.h index f7d6a72a2..4f45aa4fa 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -65,7 +65,7 @@ typedef enum { typedef struct particle_s particle_t; typedef void (*pt_phys_func)(particle_t *); -pt_phys_func R_ParticlePhysics (ptype_t type); +pt_phys_func R_ParticlePhysics (ptype_t type) __attribute__((pure)); // !!! if this is changed, it must be changed in d_ifacea.h too !!! struct particle_s diff --git a/include/d_local.h b/include/d_local.h index cc7c4591c..7143277b1 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -94,11 +94,11 @@ void R_ShowSubDiv (void); extern void (*prealspandrawer)(void); surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel); -extern int D_MipLevelForScale (float scale); +int D_MipLevelForScale (float scale) __attribute__((pure)); #ifdef USE_INTEL_ASM -extern void D_PolysetAff8Start (void); -extern void D_PolysetAff8End (void); +void D_PolysetAff8Start (void); +void D_PolysetAff8End (void); #endif extern short *d_pzbuffer; diff --git a/include/exp.h b/include/exp.h index a3c40a7ca..f4a46514e 100644 --- a/include/exp.h +++ b/include/exp.h @@ -80,7 +80,7 @@ typedef union token_u extern exp_error_t EXP_ERROR; -const char *EXP_GetErrorMsg (void); +const char *EXP_GetErrorMsg (void) __attribute__((pure)); token *EXP_ParseString (char *str); exp_error_t EXP_SimplifyTokens (token *chain); void EXP_RemoveToken (token *tok); diff --git a/include/gib_buffer.h b/include/gib_buffer.h index e3944287e..b0e9219d2 100644 --- a/include/gib_buffer.h +++ b/include/gib_buffer.h @@ -40,7 +40,7 @@ void GIB_Buffer_Push_Sstack (struct cbuf_s *cbuf); void GIB_Buffer_Pop_Sstack (struct cbuf_s *cbuf); dstring_t *GIB_Buffer_Dsarray_Get (struct cbuf_s *cbuf); void GIB_Buffer_Reply_Callback (int argc, const char **argv, void *data); -void GIB_Buffer_Error (cbuf_t *cbuf, const char *type, const char *fmt, va_list args); +void GIB_Buffer_Error (cbuf_t *cbuf, const char *type, const char *fmt, va_list args) __attribute__((format(printf, 3, 0))); extern struct cbuf_interpreter_s gib_interp; diff --git a/include/gib_parse.h b/include/gib_parse.h index a6dae25c0..6c6ee06e4 100644 --- a/include/gib_parse.h +++ b/include/gib_parse.h @@ -43,5 +43,5 @@ gib_tree_t *GIB_Parse_Embedded (gib_tree_t *token); extern qboolean gib_parse_error; void GIB_Parse_Error (const char *msg, unsigned int pos); -const char *GIB_Parse_ErrorMsg (void); -unsigned int GIB_Parse_ErrorPos (void); +const char *GIB_Parse_ErrorMsg (void) __attribute__((pure)); +unsigned int GIB_Parse_ErrorPos (void) __attribute__((pure)); diff --git a/include/gib_regex.h b/include/gib_regex.h index 2970a21c1..aeccd78a1 100644 --- a/include/gib_regex.h +++ b/include/gib_regex.h @@ -39,7 +39,7 @@ typedef struct gib_regex_s { void GIB_Regex_Init (void); regex_t *GIB_Regex_Compile (const char *regex, int cflags); -const char *GIB_Regex_Error (void); -int GIB_Regex_Translate_Options (const char *opstr); -int GIB_Regex_Translate_Runtime_Options (const char *opstr); +const char *GIB_Regex_Error (void) __attribute__((const)); +int GIB_Regex_Translate_Options (const char *opstr) __attribute__((pure)); +int GIB_Regex_Translate_Runtime_Options (const char *opstr) __attribute__((pure)); unsigned int GIB_Regex_Apply_Match (regmatch_t match[10], dstring_t *dstr, unsigned int ofs, const char *replace); diff --git a/include/netchan.h b/include/netchan.h index 5b361009e..556732ba2 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -116,7 +116,7 @@ void NET_SendPacket (int length, const void *data, netadr_t to); \param b The second address to compare. \return True of the addresses match, otherwise false. */ -qboolean NET_CompareAdr (netadr_t a, netadr_t b); +qboolean NET_CompareAdr (netadr_t a, netadr_t b) __attribute__((pure)); /** Compare two network addresses. @@ -126,7 +126,7 @@ qboolean NET_CompareAdr (netadr_t a, netadr_t b); \param b The second address to compare. \return True of the addresses match, otherwise false. */ -qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b); +qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) __attribute__((pure)); /** Convert an address to a string. @@ -362,7 +362,7 @@ void Netchan_Setup (netchan_t *chan, netadr_t adr, int qport, ncqport_e flags); \param chan The netchan representing the connection. \return True if the connection isn't chocked. */ -qboolean Netchan_CanPacket (netchan_t *chan); +qboolean Netchan_CanPacket (netchan_t *chan) __attribute__((pure)); /** Check if a reliable packet can be sent to the connection. @@ -370,7 +370,7 @@ qboolean Netchan_CanPacket (netchan_t *chan); \return True if there is no outstanding reliable packet and the connection isn't chocked. */ -qboolean Netchan_CanReliable (netchan_t *chan); +qboolean Netchan_CanReliable (netchan_t *chan) __attribute__((pure)); /** Send a packet. diff --git a/include/ops.h b/include/ops.h index cc988e56a..8793d5663 100644 --- a/include/ops.h +++ b/include/ops.h @@ -22,34 +22,34 @@ #ifndef __ops_h #define __ops_h -double OP_Not (double op1, double op2); -double OP_Negate (double op1, double op2); -double OP_Add (double op1, double op2); -double OP_Sub (double op1, double op2); -double OP_Mult (double op1, double op2); -double OP_Div (double op1, double op2); -double OP_Exp (double op1, double op2); -double OP_Eq (double op1, double op2); -double OP_Neq (double op1, double op2); -double OP_Or (double op1, double op2); -double OP_And (double op1, double op2); -double OP_GreaterThan (double op1, double op2); -double OP_LessThan (double op1, double op2); -double OP_GreaterThanEqual (double op1, double op2); -double OP_LessThanEqual (double op1, double op2); -double OP_BitAnd (double op1, double op2); -double OP_BitOr (double op1, double op2); -double OP_BitXor (double op1, double op2); -double OP_BitInv (double op1, double op2); +double OP_Not (double op1, double op2) __attribute__((const)); +double OP_Negate (double op1, double op2) __attribute__((const)); +double OP_Add (double op1, double op2) __attribute__((const)); +double OP_Sub (double op1, double op2) __attribute__((const)); +double OP_Mult (double op1, double op2) __attribute__((const)); +double OP_Div (double op1, double op2) __attribute__((const)); +double OP_Exp (double op1, double op2) __attribute__((const)); +double OP_Eq (double op1, double op2) __attribute__((const)); +double OP_Neq (double op1, double op2) __attribute__((const)); +double OP_Or (double op1, double op2) __attribute__((const)); +double OP_And (double op1, double op2) __attribute__((const)); +double OP_GreaterThan (double op1, double op2) __attribute__((const)); +double OP_LessThan (double op1, double op2) __attribute__((const)); +double OP_GreaterThanEqual (double op1, double op2) __attribute__((const)); +double OP_LessThanEqual (double op1, double op2) __attribute__((const)); +double OP_BitAnd (double op1, double op2) __attribute__((const)); +double OP_BitOr (double op1, double op2) __attribute__((const)); +double OP_BitXor (double op1, double op2) __attribute__((const)); +double OP_BitInv (double op1, double op2) __attribute__((const)); -double Func_Sin (double *oplist, unsigned int numops); -double Func_Cos (double *oplist, unsigned int numops); -double Func_Tan (double *oplist, unsigned int numops); -double Func_Asin (double *oplist, unsigned int numops); -double Func_Acos (double *oplist, unsigned int numops); -double Func_Atan (double *oplist, unsigned int numops); -double Func_Sqrt (double *oplist, unsigned int numops); -double Func_Abs (double *oplist, unsigned int numops); +double Func_Sin (double *oplist, unsigned int numops) __attribute__((pure)); +double Func_Cos (double *oplist, unsigned int numops) __attribute__((pure)); +double Func_Tan (double *oplist, unsigned int numops) __attribute__((pure)); +double Func_Asin (double *oplist, unsigned int numops) __attribute__((pure)); +double Func_Acos (double *oplist, unsigned int numops) __attribute__((pure)); +double Func_Atan (double *oplist, unsigned int numops) __attribute__((pure)); +double Func_Sqrt (double *oplist, unsigned int numops) __attribute__((pure)); +double Func_Abs (double *oplist, unsigned int numops) __attribute__((pure)); double Func_Rand (double *oplist, unsigned int numops); -double Func_Trunc (double *oplist, unsigned int numops); +double Func_Trunc (double *oplist, unsigned int numops) __attribute__((pure)); #endif // __ops_h diff --git a/include/qstring.h b/include/qstring.h index acea2f2e2..55b7ff30d 100644 --- a/include/qstring.h +++ b/include/qstring.h @@ -31,8 +31,8 @@ #include #include -const char * Q_strcasestr (const char *haystack, const char *needle); -size_t Q_strnlen (const char *s, size_t maxlen); +const char * Q_strcasestr (const char *haystack, const char *needle) __attribute__((pure)); +size_t Q_strnlen (const char *s, size_t maxlen) __attribute__((pure)); size_t Q_snprintfz (char *dest, size_t size, const char *fmt, ...) __attribute__((format(printf,3,4))); size_t Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list argptr); diff --git a/include/qw/msg_backbuf.h b/include/qw/msg_backbuf.h index 787612d38..12cbb0b06 100644 --- a/include/qw/msg_backbuf.h +++ b/include/qw/msg_backbuf.h @@ -43,7 +43,7 @@ typedef struct backbuf_s { const char *name; } backbuf_t; -int MSG_ReliableCheckSize (backbuf_t *rel, int maxsize, int minsize); +int MSG_ReliableCheckSize (backbuf_t *rel, int maxsize, int minsize) __attribute__((pure)); sizebuf_t *MSG_ReliableCheckBlock(backbuf_t *rel, int maxsize); void MSG_Reliable_FinishWrite(backbuf_t *rel); sizebuf_t *MSG_ReliableWrite_Begin(backbuf_t *rel, int c, int maxsize); diff --git a/include/qw/pmove.h b/include/qw/pmove.h index 285513a75..b8c436e56 100644 --- a/include/qw/pmove.h +++ b/include/qw/pmove.h @@ -106,9 +106,9 @@ void PlayerMove (void); void Pmove_Init (void); void Pmove_Init_Cvars (void); -int PM_HullPointContents (hull_t *hull, int num, const vec3_t p); +int PM_HullPointContents (hull_t *hull, int num, const vec3_t p) __attribute__((pure)); -int PM_PointContents (const vec3_t point); +int PM_PointContents (const vec3_t point) __attribute__((pure)); qboolean PM_TestPlayerPosition (const vec3_t point); trace_t PM_PlayerMove (const vec3_t start, const vec3_t stop); diff --git a/include/r_internal.h b/include/r_internal.h index 3d5e69206..31272a5a8 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -32,7 +32,7 @@ struct plitem_s; void Fog_ParseWorldspawn (struct plitem_s *worldspawn); float *Fog_GetColor (void); -float Fog_GetDensity (void); +float Fog_GetDensity (void) __attribute__((pure)); void Fog_SetupFrame (void); void Fog_EnableGFog (void); void Fog_DisableGFog (void); @@ -63,7 +63,7 @@ void R_NewMap (model_t *worldmodel, model_t **models, int num_models); void R_PushDlights (const vec3_t entorigin); void R_DrawWaterSurfaces (void); -void *D_SurfaceCacheAddress (void); +void *D_SurfaceCacheAddress (void) __attribute__((pure)); int D_SurfaceCacheForRes (int width, int height); void D_FlushCaches (void); void D_DeleteSurfaceCache (void); diff --git a/include/r_local.h b/include/r_local.h index 5f9eb2ef0..189d38d38 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -151,7 +151,7 @@ void R_TransformPlane (plane_t *p, float *normal, float *dist); void R_TransformFrustum (void); void R_SetSkyFrame (void); void R_DrawSurfaceBlock (void); -texture_t *R_TextureAnimation (msurface_t *surf); +texture_t *R_TextureAnimation (msurface_t *surf) __attribute__((pure)); void R_GenSkyTile (void *pdest); void R_SurfPatch (void); diff --git a/include/r_screen.h b/include/r_screen.h index 8d3b08e91..4fb5e91cd 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -71,7 +71,7 @@ extern vrect_t scr_vrect; extern qboolean scr_skipupdate; -float CalcFov (float fov_x, float width, float height); +float CalcFov (float fov_x, float width, float height) __attribute__((const)); void SCR_SetUpToDrawConsole (void); void SCR_ScreenShot_f (void); diff --git a/include/snd_internal.h b/include/snd_internal.h index 0d8f5ba3e..0b1e87a21 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -502,13 +502,13 @@ int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname); \param sfx sound reference \return pointer to sound's wavinfo */ -wavinfo_t *SND_CacheWavinfo (sfx_t *sfx); +wavinfo_t *SND_CacheWavinfo (sfx_t *sfx) __attribute__((pure)); /** Retrieve wavinfo from a streamed sound. \param sfx sound reference \return pointer to sound's wavinfo */ -wavinfo_t *SND_StreamWavinfo (sfx_t *sfx); +wavinfo_t *SND_StreamWavinfo (sfx_t *sfx) __attribute__((pure)); /** Ensure a cached sound is in memory. \param sfx sound reference @@ -522,7 +522,7 @@ sfxbuffer_t *SND_CacheTouch (sfx_t *sfx); \note The sound must be retained with SND_CacheRetain() for the returned buffer to be valid. */ -sfxbuffer_t *SND_CacheGetBuffer (sfx_t *sfx); +sfxbuffer_t *SND_CacheGetBuffer (sfx_t *sfx) __attribute__((pure)); /** Lock a cached sound into memory. After calling this, SND_CacheGetBffer() will return a valid buffer. @@ -541,14 +541,14 @@ void SND_CacheRelease (sfx_t *sfx); \param sfx sound reference \return poitner to sound buffer */ -sfxbuffer_t *SND_StreamGetBuffer (sfx_t *sfx); +sfxbuffer_t *SND_StreamGetBuffer (sfx_t *sfx) __attribute__((pure)); /** Lock a streamed sound into memory. Doesn't actually do anything other than return a pointer to the buffer. \param sfx sound reference \return poitner to sound buffer */ -sfxbuffer_t *SND_StreamRetain (sfx_t *sfx); +sfxbuffer_t *SND_StreamRetain (sfx_t *sfx) __attribute__((pure)); /** Unlock a streamed sound from memory. Doesn't actually do anything. \param sfx sound reference diff --git a/include/world.h b/include/world.h index e6ebc90ee..57bc973a6 100644 --- a/include/world.h +++ b/include/world.h @@ -98,8 +98,8 @@ void SV_LinkEdict (struct edict_s *ent, qboolean touch_triggers); // sets ent->v.absmin and ent->v.absmax // if touchtriggers, calls prog functions for the intersected triggers -int SV_PointContents (const vec3_t p); -int SV_TruePointContents (const vec3_t p); +int SV_PointContents (const vec3_t p) __attribute__((pure)); +int SV_TruePointContents (const vec3_t p) __attribute__((pure)); // returns the CONTENTS_* value from the world at the given point. // does not check any entities at all // the non-true version remaps the water current contents to content_water @@ -123,7 +123,7 @@ trace_t SV_Move (const vec3_t start, const vec3_t mins, const vec3_t maxs, struct edict_s *SV_TestPlayerPosition (struct edict_s *ent, const vec3_t origin); -int SV_HullPointContents (hull_t *hull, int num, const vec3_t p); +int SV_HullPointContents (hull_t *hull, int num, const vec3_t p) __attribute__((pure)); hull_t *SV_HullForEntity (struct edict_s *ent, const vec3_t mins, const vec3_t maxs, vec3_t extents, vec3_t offset); void MOD_TraceLine (hull_t *hull, int num, diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 864055ccc..76450bcc9 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -103,7 +103,7 @@ SNDDMA_Init_Cvars (void) static int SNDDMA_GetDMAPos (void); -static snd_pcm_uframes_t +static __attribute__((const)) snd_pcm_uframes_t round_buffer_size (snd_pcm_uframes_t sz) { snd_pcm_uframes_t mask = ~0; diff --git a/libs/console/client.c b/libs/console/client.c index f31ccada9..ad31462a0 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -360,7 +360,7 @@ Linefeed (void) All console printing must go through this in order to be logged to disk If no console is visible, the notify window will pop up. */ -static void +static __attribute__((format(printf, 1, 0))) void C_Print (const char *fmt, va_list args) { char *s; diff --git a/libs/console/server.c b/libs/console/server.c index 5bf9061ec..83cce7f3d 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -708,7 +708,7 @@ C_Shutdown (void) #endif } -static void +static __attribute__((format(printf, 1, 0))) void C_Print (const char *fmt, va_list args) { static dstring_t *buffer; diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index ac957e23b..b0edefa63 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -144,7 +144,7 @@ free_string_ref (progs_t *pr, strref_t *sr) pr->free_string_refs = sr; } -static string_t +static __attribute__((pure)) string_t string_index (progs_t *pr, strref_t *sr) { long o = (long) (sr - pr->static_strings); @@ -251,7 +251,7 @@ get_strref (progs_t *pr, string_t num) return 0; } -static inline const char * +static inline __attribute__((pure)) const char * get_string (progs_t *pr, string_t num) { if (num < 0) { diff --git a/libs/gib/exp.c b/libs/gib/exp.c index 7f831a122..f56159e71 100644 --- a/libs/gib/exp.c +++ b/libs/gib/exp.c @@ -154,7 +154,7 @@ EXP_FindFuncByStr (const char *str) return 0; } -static int +static __attribute__((pure)) int EXP_ContainsCommas (token * chain) { token *cur; diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 7f7e302c7..20160e228 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -104,7 +104,7 @@ NET_Ban_f (void) { char addrStr[32]; //FIXME: overflow char maskStr[32]; //FIXME: overflow - void (*print) (const char *fmt, ...); + __attribute__((format(printf, 1, 2))) void (*print) (const char *fmt, ...); if (cmd_source == src_command) { if (!sv.active) { @@ -262,7 +262,7 @@ Datagram_CanSendMessage (qsocket_t *sock) } -qboolean +__attribute__((const)) qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock) { return true; diff --git a/libs/net/nm/net_loop.c b/libs/net/nm/net_loop.c index 0323b760d..0624688b9 100644 --- a/libs/net/nm/net_loop.c +++ b/libs/net/nm/net_loop.c @@ -42,7 +42,7 @@ qboolean localconnectpending = false; qsocket_t *loop_client = NULL; qsocket_t *loop_server = NULL; -int +__attribute__((pure)) int Loop_Init (void) { if (cls.state == ca_dedicated) @@ -240,7 +240,7 @@ Loop_SendUnreliableMessage (qsocket_t * sock, sizebuf_t *data) } -qboolean +__attribute__((pure)) qboolean Loop_CanSendMessage (qsocket_t * sock) { if (!sock->driverdata) @@ -249,7 +249,7 @@ Loop_CanSendMessage (qsocket_t * sock) } -qboolean +__attribute__((const)) qboolean Loop_CanSendUnreliableMessage (qsocket_t * sock) { return true; diff --git a/libs/net/nm/net_udp.c b/libs/net/nm/net_udp.c index cf2348256..41cf8b9ec 100644 --- a/libs/net/nm/net_udp.c +++ b/libs/net/nm/net_udp.c @@ -433,7 +433,7 @@ error: return -1; } -int +__attribute__((const)) int UDP_Connect (int socket, netadr_t *addr) { return 0; @@ -651,7 +651,7 @@ UDP_GetAddrFromName (const char *name, netadr_t *addr) return 0; } -int +__attribute__((pure)) int UDP_AddrCompare (netadr_t *addr1, netadr_t *addr2) { if (addr1->family != addr2->family) @@ -666,7 +666,7 @@ UDP_AddrCompare (netadr_t *addr1, netadr_t *addr2) return 0; } -int +__attribute__((pure)) int UDP_GetSocketPort (netadr_t *addr) { return ntohs (addr->port); diff --git a/libs/net/nm/net_vcr.c b/libs/net/nm/net_vcr.c index 603257813..f997d3034 100644 --- a/libs/net/nm/net_vcr.c +++ b/libs/net/nm/net_vcr.c @@ -166,14 +166,14 @@ VCR_SearchForHosts (qboolean xmit) } -qsocket_t * +__attribute__((const)) qsocket_t * VCR_Connect (const char *host) { return NULL; } -qsocket_t * +qsocket_t * VCR_CheckNewConnections (void) { qsocket_t *sock; diff --git a/libs/util/dstring.c b/libs/util/dstring.c index 4e43a0aae..18d83f44a 100644 --- a/libs/util/dstring.c +++ b/libs/util/dstring.c @@ -299,7 +299,7 @@ dstring_clearstr (dstring_t *dstr) dstr->str[0] = 0; } -static int +static __attribute__((format(printf, 3, 0))) int _dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args) { int size; diff --git a/libs/util/set.c b/libs/util/set.c index 4b3b3a033..dfdd55b4e 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -343,7 +343,7 @@ set_everything (set_t *set) return set; } -static inline int +static inline __attribute__((pure)) int _set_is_empty (const set_t *set) { unsigned i; @@ -370,7 +370,7 @@ set_is_everything (const set_t *set) return _set_is_empty (set); } -static int +static __attribute__((pure)) int set_test_n_n (const set_t *s1, const set_t *s2) { unsigned i, end; @@ -394,7 +394,7 @@ set_test_n_n (const set_t *s1, const set_t *s2) return (difference != 0) | ((intersection != 0) << 1); } -static int +static __attribute__((pure)) int set_test_n_i (const set_t *s1, const set_t *s2) { unsigned i, end; @@ -419,7 +419,7 @@ set_test_n_i (const set_t *s1, const set_t *s2) return (difference != 0) | ((intersection != 0) << 1); } -static int +static __attribute__((pure)) int set_test_i_n (const set_t *s1, const set_t *s2) { unsigned i, end; @@ -444,7 +444,7 @@ set_test_i_n (const set_t *s1, const set_t *s2) return (difference != 0) | ((intersection != 0) << 1); } -static int +static __attribute__((pure)) int set_test_i_i (const set_t *s1, const set_t *s2) { unsigned i, end; @@ -470,7 +470,7 @@ set_test_i_i (const set_t *s1, const set_t *s2) return (difference != 0) | ((intersection != 0) << 1); } -static int +static __attribute__((pure)) int set_test (const set_t *s1, const set_t *s2) { if (s1->inverted && s2->inverted) diff --git a/libs/util/sys.c b/libs/util/sys.c index 1b6a9c269..b2e28f71d 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -90,8 +90,8 @@ #include "compat.h" -static void Sys_StdPrintf (const char *fmt, va_list args); -static void Sys_ErrPrintf (const char *fmt, va_list args); +static void Sys_StdPrintf (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); +static void Sys_ErrPrintf (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); VISIBLE cvar_t *sys_nostdout; VISIBLE cvar_t *sys_extrasleep; diff --git a/libs/util/test/test-vrect.c b/libs/util/test/test-vrect.c index b1ba859bc..ab2558e8f 100644 --- a/libs/util/test/test-vrect.c +++ b/libs/util/test/test-vrect.c @@ -134,7 +134,7 @@ print_rects (vrect_t *rect) printf ("\n"); } -static int +static __attribute__((pure)) int compare_rects (vrect_t *r1, vrect_t *r2) { if (!r1 && !r2) diff --git a/libs/video/renderer/gl/qfgl_ext.c b/libs/video/renderer/gl/qfgl_ext.c index fa28797d5..a46472609 100644 --- a/libs/video/renderer/gl/qfgl_ext.c +++ b/libs/video/renderer/gl/qfgl_ext.c @@ -91,7 +91,7 @@ GLF_FindFunctions (void) It takes a bit of care to be fool-proof about parsing an OpenGL extensions string. Don't be fooled by sub-strings, etc. */ -static qboolean +static __attribute__((pure)) qboolean QFGL_ParseExtensionList (const GLubyte *list, const char *name) { const char *start; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index e52402660..f212cbe7a 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -1321,7 +1321,7 @@ glsl_R_InitBsp (void) GLSL_FreeShader (frag_shader); } -static inline int +static inline __attribute__((const)) int is_pow2 (unsigned x) { int count; diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index 56e481c41..eab755325 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -227,7 +227,7 @@ glsl_SCR_CaptureBGR (void) return tex; } -tex_t * +__attribute__((const)) tex_t * glsl_SCR_ScreenShot (int width, int height) { return 0; diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index 63f0ce6e1..bcadb5c9b 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -87,7 +87,7 @@ sw32_SCR_CaptureBGR (void) return tex; } -tex_t * +__attribute__((const)) tex_t * sw32_SCR_ScreenShot (int width, int height) { return 0; diff --git a/libs/video/targets/keys.c b/libs/video/targets/keys.c index 5538f07cb..daa9eeda8 100644 --- a/libs/video/targets/keys.c +++ b/libs/video/targets/keys.c @@ -511,7 +511,7 @@ keyname_t keynames[] = { {NULL, 0} }; -static imt_t * +static __attribute__((pure)) imt_t * key_target_find_imt (keytarget_t *kt, const char *imt_name) { imt_t *imt; diff --git a/nq/include/host.h b/nq/include/host.h index 2e17ca341..8601ea4c2 100644 --- a/nq/include/host.h +++ b/nq/include/host.h @@ -62,10 +62,10 @@ void Host_ServerFrame (void); void Host_InitCommands (void); void Host_Init (void); void Host_Shutdown(void); -void Host_Error (const char *error, ...) __attribute__((format(printf,1,2))); -void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2))); +void Host_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); +void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2), noreturn)); void Host_Frame (float time); -void Host_Quit_f (void); +void Host_Quit_f (void) __attribute__((noreturn)); void Host_ClientCommands (const char *fmt, ...) __attribute__((format(printf,1,2))); void Host_ShutdownServer (qboolean crash); diff --git a/nq/include/server.h b/nq/include/server.h index 0d83a4e7c..4960fee5c 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -255,7 +255,7 @@ void SV_DropClient (qboolean crash); void SV_SendClientMessages (void); void SV_ClearDatagram (void); -int SV_ModelIndex (const char *name); +int SV_ModelIndex (const char *name) __attribute__((pure)); void SV_SetIdealPitch (void); @@ -268,7 +268,7 @@ void SV_ClientPrintf (const char *fmt, ...) __attribute__((format(printf,1,2))); void SV_BroadcastPrintf (const char *fmt, ...) __attribute__((format(printf,1,2))); struct trace_s SV_PushEntity (edict_t *ent, vec3_t push); -int SV_EntCanSupportJump (edict_t *ent); +int SV_EntCanSupportJump (edict_t *ent) __attribute__((pure)); int SV_FlyMove (edict_t *ent, float time, struct trace_s *steptrace); void SV_CheckVelocity (edict_t *ent); qboolean SV_RunThink (edict_t *ent); diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 5aaf60e73..fa75e33e8 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -78,7 +78,7 @@ Host_Status_f (void) int minutes; int hours = 0; int j; - void (*print) (const char *fmt, ...); + __attribute__((format(printf, 1, 2))) void (*print) (const char *fmt, ...); if (cmd_source == src_command) { if (!sv.active) { diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index 37fd93f2b..c22f9cc3a 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -113,7 +113,7 @@ CL_NextDemo (void) { } -int +__attribute__((const)) int CL_ReadFromServer (void) { return 0; @@ -156,7 +156,7 @@ S_UnblockSound (void) } plugin_t *console_client_PluginInfo (void); -plugin_t * +__attribute__((const)) plugin_t * console_client_PluginInfo (void) { return 0; diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index c95669eb4..d6982bc3a 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -1069,7 +1069,7 @@ PF_changeyaw (progs_t *pr) #define MSG_ALL 2 // reliable to all #define MSG_INIT 3 // write to the init string -static sizebuf_t * +static __attribute__((pure)) sizebuf_t * WriteDest (progs_t *pr) { int entnum; diff --git a/nq/source/world.c b/nq/source/world.c index e00208900..6d404f39c 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -705,7 +705,7 @@ ctl_pretest_triggers (edict_t *touch, moveclip_t *clip) return 1; } -static always_inline int +static always_inline __attribute__((pure)) int ctl_pretest_other (edict_t *touch, moveclip_t *clip) { if (SVfloat (touch, solid) == SOLID_NOT) diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 7f12d013f..4980dea9b 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -87,7 +87,7 @@ redirect_t qtv_redirected; client_t *qtv_redirect_client; dstring_t outputbuf = {&dstring_default_mem}; -static void +static __attribute__((format(printf, 1, 0))) void qtv_print (const char *fmt, va_list args) { static int pending; diff --git a/qw/include/cl_cam.h b/qw/include/cl_cam.h index 2bd74f644..0fbb1c0e7 100644 --- a/qw/include/cl_cam.h +++ b/qw/include/cl_cam.h @@ -43,9 +43,9 @@ extern int spec_track; // player# of who we are tracking extern int ideal_track; void Cam_Lock (int playernum); -int Cam_TrackNum (void); -qboolean Cam_DrawViewModel(void); -qboolean Cam_DrawPlayer(int playernum); +int Cam_TrackNum (void) __attribute__((pure)); +qboolean Cam_DrawViewModel(void) __attribute__((pure)); +qboolean Cam_DrawPlayer(int playernum) __attribute__((pure)); void Cam_Track(usercmd_t *cmd); void Cam_FinishMove(usercmd_t *cmd); void Cam_Reset(void); diff --git a/qw/include/cl_parse.h b/qw/include/cl_parse.h index 12bc89e12..4dd3646c6 100644 --- a/qw/include/cl_parse.h +++ b/qw/include/cl_parse.h @@ -52,7 +52,7 @@ void CL_ParseServerMessage (void); void CL_ParseClientdata (void); void CL_NewTranslation (int slot, struct skin_s *skin); qboolean CL_CheckOrDownloadFile (const char *filename); -qboolean CL_IsUploading(void); +qboolean CL_IsUploading(void) __attribute__((pure)); void CL_NextUpload(void); void CL_FinishDownload (void); void CL_FailDownload (void); diff --git a/qw/include/crudefile.h b/qw/include/crudefile.h index 384b6126c..be827be33 100644 --- a/qw/include/crudefile.h +++ b/qw/include/crudefile.h @@ -35,6 +35,6 @@ void CF_Close (int desc); const char * CF_Read (int desc); int CF_Write (int desc, const char *buf); int CF_EOF (int desc); -int CF_Quota (void); +int CF_Quota (void) __attribute__((pure)); #endif // _CRUDEFILE_H diff --git a/qw/include/host.h b/qw/include/host.h index 87404b019..0c1492f47 100644 --- a/qw/include/host.h +++ b/qw/include/host.h @@ -51,8 +51,8 @@ void Host_ServerFrame (void); void Host_InitCommands (void); void Host_Init (void); void Host_Shutdown(void); -void Host_Error (const char *error, ...) __attribute__((format(printf,1,2))); -void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2))); +void Host_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); +void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2), noreturn)); void Host_Frame (float time); void Host_Quit_f (void); void Host_ClientCommands (const char *fmt, ...) __attribute__((format(printf,1,2))); diff --git a/qw/include/server.h b/qw/include/server.h index 642f296f8..abc5fdd9d 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -492,11 +492,11 @@ void SV_Shutdown (void); void SV_Frame (float time); void SV_FinalMessage (const char *message); void SV_DropClient (client_t *drop); -int SV_CalcPing (client_t *cl); +int SV_CalcPing (client_t *cl) __attribute__((pure)); void SV_FullClientUpdate (client_t *client, sizebuf_t *buf); void SV_FullClientUpdateToClient (client_t *client, backbuf_t *backbuf); -int SV_ModelIndex (const char *name); +int SV_ModelIndex (const char *name) __attribute__((pure)); qboolean SV_CheckBottom (struct edict_s *ent); qboolean SV_movestep (struct edict_s *ent, const vec3_t move, @@ -549,12 +549,12 @@ struct trace_s; int SV_FlyMove (struct edict_s *ent, float time, struct trace_s *steptrace); struct trace_s SV_PushEntity (struct edict_s *ent, vec3_t push, unsigned traceflags); -int SV_EntCanSupportJump (struct edict_s *ent); +int SV_EntCanSupportJump (struct edict_s *ent) __attribute__((pure)); // // sv_send.c // -void SV_Print (const char *fmt, va_list args); +void SV_Print (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); void SV_Printf (const char *fmt, ...) __attribute__((format(printf,1,2))); void SV_SendClientMessages (void); void SV_GetStats (struct edict_s *ent, int spectator, int stats[]); @@ -611,7 +611,7 @@ extern struct dstring_s outputbuf; // sv_ccmds.c // void SV_Status_f (void); -const char *SV_Current_Map (void); +const char *SV_Current_Map (void) __attribute__((pure)); void SV_SetLocalinfo (const char *key, const char *value); diff --git a/qw/include/sv_recorder.h b/qw/include/sv_recorder.h index 80b55d419..f8be8b97f 100644 --- a/qw/include/sv_recorder.h +++ b/qw/include/sv_recorder.h @@ -42,12 +42,12 @@ recorder_t *SVR_AddUser (void (*writer)(void *, struct sizebuf_s *, int), int demo, void *user); void SVR_RemoveUser (recorder_t *r); struct sizebuf_s *SVR_WriteBegin (byte type, int to, int size); -struct sizebuf_s *SVR_Datagram (void); +struct sizebuf_s *SVR_Datagram (void) __attribute__((const)); void SVR_ForceFrame (void); void SVR_Pause (recorder_t *r); void SVR_Continue (recorder_t *r); void SVR_SetDelta (recorder_t *r, int delta, int in_frame); void SVR_SendMessages (void); -int SVR_NumRecorders (void); +int SVR_NumRecorders (void) __attribute__((pure)); #endif//__sv_recorder_h diff --git a/qw/source/cl_slist.c b/qw/source/cl_slist.c index 9efafd73b..21497f142 100644 --- a/qw/source/cl_slist.c +++ b/qw/source/cl_slist.c @@ -314,7 +314,7 @@ SL_Shutdown (void) SL_Del_All (all_slist); } -static char * +static __attribute__((pure)) char * gettokstart (char *str, int req, char delim) { char *start = str; @@ -340,7 +340,7 @@ gettokstart (char *str, int req, char delim) return start; } -static int +static __attribute__((pure)) int gettoklen (char *str, int req, char delim) { char *start = 0; diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 685dfd0a7..c69e23594 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -257,7 +257,7 @@ SV_Shutdown (void) Sends a datagram to all the clients informing them of the server crash, then exits */ -static void +static __attribute__((format(printf, 1, 0))) void SV_Error (const char *error, va_list argptr) { static qboolean inerror = false; @@ -1206,7 +1206,7 @@ SV_MaskIPTrim (byte *ip, int mask) } // assumes b has already been masked -static inline qboolean +static inline __attribute__((pure)) qboolean SV_MaskIPCompare (byte *a, byte *b, int mask) { int i; diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 4f832e5a2..46a9cc4e3 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -1061,7 +1061,7 @@ PF_changeyaw (progs_t *pr) #define MSG_INIT 3 // write to the init string #define MSG_MULTICAST 4 // for multicast () -static sizebuf_t * +static __attribute__((pure)) sizebuf_t * WriteDest (progs_t *pr) { int dest; @@ -1094,7 +1094,7 @@ WriteDest (progs_t *pr) return NULL; } -static client_t * +static __attribute__((pure)) client_t * Write_GetClient (progs_t *pr) { edict_t *ent; diff --git a/qw/source/world.c b/qw/source/world.c index ac5dd641b..0664c197e 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -677,7 +677,7 @@ SV_ClipMoveToEntity (edict_t *touched, const vec3_t start, return trace; } -static always_inline int +static always_inline __attribute__((pure)) int ctl_pretest_everything (edict_t *touch, moveclip_t *clip) { if (touch->free) @@ -705,7 +705,7 @@ ctl_pretest_triggers (edict_t *touch, moveclip_t *clip) return 1; } -static always_inline int +static always_inline __attribute__((pure)) int ctl_pretest_other (edict_t *touch, moveclip_t *clip) { if (SVfloat (touch, solid) == SOLID_NOT) diff --git a/tools/qfbsp/include/brush.h b/tools/qfbsp/include/brush.h index 66cdff5a4..f51beab00 100644 --- a/tools/qfbsp/include/brush.h +++ b/tools/qfbsp/include/brush.h @@ -69,7 +69,7 @@ brushset_t *Brush_LoadEntity (entity_t *ent, int hullnum); \param normal Must be canonical. */ -int PlaneTypeForNormal (const vec3_t normal); +int PlaneTypeForNormal (const vec3_t normal) __attribute__((pure)); /** Make the plane canonical. diff --git a/tools/qfbsp/include/map.h b/tools/qfbsp/include/map.h index 1e6c18f29..e531fad8a 100644 --- a/tools/qfbsp/include/map.h +++ b/tools/qfbsp/include/map.h @@ -95,7 +95,7 @@ void PrintEntity (const entity_t *ent); \return The value for the key, or the empty string if the key does not exist in this entity. */ -const char *ValueForKey (const entity_t *ent, const char *key); +const char *ValueForKey (const entity_t *ent, const char *key) __attribute__((pure)); /** Set the value of the entity's key. If the key does not exist, one will be added. diff --git a/tools/qfbsp/source/outside.c b/tools/qfbsp/source/outside.c index 0907d4dee..3002f468b 100644 --- a/tools/qfbsp/source/outside.c +++ b/tools/qfbsp/source/outside.c @@ -41,7 +41,7 @@ int outleafs; \param point The point's location. \return The leaf node in which the point is. */ -static node_t * +static __attribute__((pure)) node_t * PointInLeaf (node_t *node, const vec3_t point) { vec_t d; diff --git a/tools/qfbsp/source/portals.c b/tools/qfbsp/source/portals.c index 6b99cefda..4871aefbe 100644 --- a/tools/qfbsp/source/portals.c +++ b/tools/qfbsp/source/portals.c @@ -422,7 +422,7 @@ int num_realleafs; \param cont The contents for which to check. \return 1 if the node has the specified contents, otherwise 0. */ -static int +static __attribute__((pure)) int HasContents (const node_t *n, int cont) { if (n->contents == cont) @@ -439,7 +439,7 @@ HasContents (const node_t *n, int cont) \param n1 The first node to check. \param n2 The second node to check. */ -static int +static __attribute__((pure)) int ShareContents (const node_t *n1, const node_t *n2) { if (n1->contents) { @@ -461,7 +461,7 @@ ShareContents (const node_t *n1, const node_t *n2) \param n1 The first node to check. \param n2 The second node to check. */ -static int +static __attribute__((pure)) int SameContents (const node_t *n1, const node_t *n2) { if (n1->contents == CONTENTS_SOLID || n2->contents == CONTENTS_SOLID) @@ -471,7 +471,7 @@ SameContents (const node_t *n1, const node_t *n2) if (options.watervis) //FIXME be more picky? return 1; if (n1->detail && n2->detail) - ShareContents (n1, n2); + return ShareContents (n1, n2); if (n1->detail) return HasContents (n1, n2->contents); if (n2->detail) diff --git a/tools/qfbsp/source/solidbsp.c b/tools/qfbsp/source/solidbsp.c index 5e04f3c32..d4c9e0f7d 100644 --- a/tools/qfbsp/source/solidbsp.c +++ b/tools/qfbsp/source/solidbsp.c @@ -121,7 +121,7 @@ FaceSide (const face_t *in, const plane_t *split) \param maxs The maximum coordinate of the boundiing box. \return The chosen surface. */ -static surface_t * +static __attribute__((pure)) surface_t * ChooseMidPlaneFromList (surface_t *surfaces, const vec3_t mins, const vec3_t maxs) { @@ -186,7 +186,7 @@ ChooseMidPlaneFromList (surface_t *surfaces, \return The chosen surface, or NULL if a suitable surface could not be found. */ -static surface_t * +static __attribute__((pure)) surface_t * ChoosePlaneFromList (surface_t *surfaces, const vec3_t mins, const vec3_t maxs, qboolean usefloors, qboolean usedetail) { diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index a2cf55182..323912591 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -107,13 +107,13 @@ struct expr_s; struct method_s; struct symbol_s; -int obj_is_id (const struct type_s *type); -int obj_is_class (const struct type_s *type); -int obj_is_Class (const struct type_s *type); -int obj_is_classptr (const struct type_s *type); +int obj_is_id (const struct type_s *type) __attribute__((pure)); +int obj_is_class (const struct type_s *type) __attribute__((pure)); +int obj_is_Class (const struct type_s *type) __attribute__((pure)); +int obj_is_classptr (const struct type_s *type) __attribute__((pure)); int obj_types_assignable (const struct type_s *dst, const struct type_s *src); -class_t *extract_class (class_type_t *class_type); +class_t *extract_class (class_type_t *class_type) __attribute__((pure)); const char *get_class_name (class_type_t *class_type, int pretty); struct symbol_s *class_symbol (class_type_t *class_type, int external); void class_init (void); @@ -125,7 +125,7 @@ void class_add_ivars (class_t *class, struct symtab_s *ivars); void class_check_ivars (class_t *class, struct symtab_s *ivars); void class_begin (class_type_t *class_type); void class_finish (class_type_t *class_type); -int class_access (class_type_t *current_class, class_t *class); +int class_access (class_type_t *current_class, class_t *class) __attribute__((pure)); struct symbol_s *class_find_ivar (class_t *class, int vis, const char *name); struct symtab_s *class_ivar_scope (class_type_t *class_type, struct symtab_s *parent); @@ -153,8 +153,8 @@ void protocol_add_protocols (protocol_t *protocol, protocollist_t *protocols); struct def_s *protocol_def (protocol_t *protocol); protocollist_t *new_protocol_list (void); protocollist_t *add_protocol (protocollist_t *protocollist, const char *name); -int procollist_find_protocol (protocollist_t *protocollist, protocol_t *proto); -int compare_protocols (protocollist_t *protos1, protocollist_t *protos2); +int procollist_find_protocol (protocollist_t *protocollist, protocol_t *proto) __attribute__((pure)); +int compare_protocols (protocollist_t *protos1, protocollist_t *protos2) __attribute__((pure)); void print_protocollist (struct dstring_s *dstr, protocollist_t *protocollist); struct def_s *emit_protocol (protocol_t *protocol); struct def_s *emit_protocol_list (protocollist_t *protocols, const char *name); diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 7e24506b9..e22ab8c7e 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -254,7 +254,7 @@ void initialize_def (struct symbol_s *sym, struct type_s *type, \return 1 if the defs overlap, 2 if \a d1 fully overlaps \a d2, otherwise 0. */ -int def_overlap (def_t *d1, def_t *d2); +int def_overlap (def_t *d1, def_t *d2) __attribute__((pure)); /** Convenience function for obtaining a def's actual offset. @@ -263,7 +263,7 @@ int def_overlap (def_t *d1, def_t *d2); \param def The def of which to obtain the offset. May be an alias def. \return The actual offset of the def in the def's defspace. */ -int def_offset (def_t *def); +int def_offset (def_t *def) __attribute__((pure)); /** Convenience function for obtaining a def's size. @@ -272,7 +272,7 @@ int def_offset (def_t *def); \param def The def of which to obtain the size. \return The size of the def. */ -int def_size (def_t *def); +int def_size (def_t *def) __attribute__((pure)); /** Visit all defs that alias the given def, including itself. diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5b1c6d1e7..73d3f2399 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -384,7 +384,7 @@ expr_t *new_name_expr (const char *name); (expr_t::e::string_val). */ expr_t *new_string_expr (const char *string_val); -const char *expr_string (expr_t *e); +const char *expr_string (expr_t *e) __attribute__((pure)); /** Create a new float constant expression node. @@ -393,7 +393,7 @@ const char *expr_string (expr_t *e); (expr_t::e::float_val). */ expr_t *new_float_expr (float float_val); -float expr_float (expr_t *e); +float expr_float (expr_t *e) __attribute__((pure)); /** Create a new vector constant expression node. @@ -402,7 +402,7 @@ float expr_float (expr_t *e); (expr_t::e::vector_val). */ expr_t *new_vector_expr (const float *vector_val); -const float *expr_vector (expr_t *e); +const float *expr_vector (expr_t *e) __attribute__((pure)); expr_t *new_vector_list (expr_t *e); /** Create a new entity constant expression node. @@ -449,7 +449,7 @@ expr_t *new_pointer_expr (int val, struct type_s *type, struct def_s *def); (expr_t::e::quaternion_val). */ expr_t *new_quaternion_expr (const float *quaternion_val); -const float *expr_quaternion (expr_t *e); +const float *expr_quaternion (expr_t *e) __attribute__((pure)); /** Create a new integer constant expression node. @@ -458,7 +458,7 @@ const float *expr_quaternion (expr_t *e); (expr_t::e::integer_val). */ expr_t *new_integer_expr (int integer_val); -int expr_integer (expr_t *e); +int expr_integer (expr_t *e) __attribute__((pure)); /** Create a new integer constant expression node. @@ -467,7 +467,7 @@ int expr_integer (expr_t *e); (expr_t::e::integer_val). */ expr_t *new_uinteger_expr (unsigned uinteger_val); -unsigned expr_uinteger (expr_t *e); +unsigned expr_uinteger (expr_t *e) __attribute__((pure)); /** Create a new short constant expression node. @@ -476,14 +476,14 @@ unsigned expr_uinteger (expr_t *e); (expr_t::e::short_val). */ expr_t *new_short_expr (short short_val); -short expr_short (expr_t *e); +short expr_short (expr_t *e) __attribute__((pure)); /** Check of the expression refers to a constant value. \param e The expression to check. \return True if the expression is constant. */ -int is_constant (expr_t *e); +int is_constant (expr_t *e) __attribute__((pure)); /** Return a value expression representing the constant stored in \a e. @@ -500,30 +500,30 @@ expr_t *constant_expr (expr_t *e); \param op The op-code to check. \return True if the op-code is a comparison operator. */ -int is_compare (int op); +int is_compare (int op) __attribute__((const)); /** Check if the op-code is a math operator. \param op The op-code to check. \return True if the op-code is a math operator. */ -int is_math_op (int op); +int is_math_op (int op) __attribute__((const)); /** Check if the op-code is a logic operator. \param op The op-code to check. \return True if the op-code is a logic operator. */ -int is_logic (int op); +int is_logic (int op) __attribute__((const)); -int has_function_call (expr_t *e); +int has_function_call (expr_t *e) __attribute__((pure)); -int is_string_val (expr_t *e); -int is_float_val (expr_t *e); -int is_vector_val (expr_t *e); -int is_quaternion_val (expr_t *e); -int is_integer_val (expr_t *e); -int is_short_val (expr_t *e); +int is_string_val (expr_t *e) __attribute__((pure)); +int is_float_val (expr_t *e) __attribute__((pure)); +int is_vector_val (expr_t *e) __attribute__((pure)); +int is_quaternion_val (expr_t *e) __attribute__((pure)); +int is_integer_val (expr_t *e) __attribute__((pure)); +int is_short_val (expr_t *e) __attribute__((pure)); /** Create a reference to the global .self entity variable. @@ -627,7 +627,7 @@ expr_t *think_expr (struct symbol_s *think_sym); expr_t *assign_expr (expr_t *e1, expr_t *e2); expr_t *cast_expr (struct type_s *t, expr_t *e); -const char *get_op_string (int op); +const char *get_op_string (int op) __attribute__((const)); struct keywordarg_s; struct class_type_s; diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 3aa464185..0bec07d37 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -107,7 +107,7 @@ extern pr_info_t pr; #define POINTER_OFS(s,p) ((pr_type_t *) (p) - (s)->data) -const char *strip_path (const char *filename); +const char *strip_path (const char *filename) __attribute__((pure)); extern FILE *qc_yyin; extern FILE *qp_yyin; diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 565cc9295..356d66b8f 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -111,7 +111,7 @@ struct expr_s; struct type_s; struct dstring_s; -const char *optype_str (op_type_e type); +const char *optype_str (op_type_e type) __attribute__((const)); operand_t *def_operand (struct def_s *def, struct type_s *type); operand_t *value_operand (struct ex_value_s *value); @@ -122,12 +122,12 @@ void free_operand (operand_t *op); sblock_t *new_sblock (void); statement_t *new_statement (st_type_t type, const char *opcode, struct expr_s *expr); -int statement_is_cond (statement_t *s); -int statement_is_goto (statement_t *s); -int statement_is_jumpb (statement_t *s); -int statement_is_call (statement_t *s); -int statement_is_return (statement_t *s); -sblock_t *statement_get_target (statement_t *s); +int statement_is_cond (statement_t *s) __attribute__((pure)); +int statement_is_goto (statement_t *s) __attribute__((pure)); +int statement_is_jumpb (statement_t *s) __attribute__((pure)); +int statement_is_call (statement_t *s) __attribute__((pure)); +int statement_is_return (statement_t *s) __attribute__((pure)); +sblock_t *statement_get_target (statement_t *s) __attribute__((pure)); sblock_t **statement_get_targetlist (statement_t *s); void sblock_add_statement (sblock_t *sblock, statement_t *statement); sblock_t *make_statements (struct expr_s *expr); diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index 0a89a39e7..626d7a484 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -92,7 +92,7 @@ typedef struct symtab_s { struct defspace_s *space; ///< storage for vars in scope symtabs } symtab_t; -const char *symtype_str (sy_type_e type); +const char *symtype_str (sy_type_e type) __attribute__((const)); /** Create a new, empty named symbol. diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 2020e8a95..2e1fa6c87 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -123,7 +123,7 @@ extern struct symtab_s *quaternion_struct; struct dstring_s; -etype_t low_level_type (type_t *type); +etype_t low_level_type (type_t *type) __attribute__((pure)); type_t *new_type (void); void free_type (type_t *type); void chain_type (type_t *type); @@ -150,17 +150,17 @@ void print_type (const type_t *type); const char *encode_params (const type_t *type); void encode_type (struct dstring_s *encoding, const type_t *type); const char *type_get_encoding (const type_t *type); -int is_void (const type_t *type); -int is_enum (const type_t *type); -int is_integral (const type_t *type); -int is_float (const type_t *type); -int is_scalar (const type_t *type); -int is_math (const type_t *type); -int is_pointer (const type_t *type); -int is_struct (const type_t *type); -int is_array (const type_t *type); +int is_void (const type_t *type) __attribute__((pure)); +int is_enum (const type_t *type) __attribute__((pure)); +int is_integral (const type_t *type) __attribute__((pure)); +int is_float (const type_t *type) __attribute__((pure)); +int is_scalar (const type_t *type) __attribute__((pure)); +int is_math (const type_t *type) __attribute__((pure)); +int is_pointer (const type_t *type) __attribute__((pure)); +int is_struct (const type_t *type) __attribute__((pure)); +int is_array (const type_t *type) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); -int type_size (const type_t *type); +int type_size (const type_t *type) __attribute__((pure)); void init_types (void); void chain_initial_types (void); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 6edb3f7da..52b67823d 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -281,7 +281,7 @@ obj_classname (const type_t *type) return str->str; } -static int +static __attribute__((pure)) int category_implements (category_t *cat, protocol_t *protocol) { for (; cat; cat = cat->next) { diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 799b2ff0f..33c156cca 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -60,7 +60,7 @@ cf_cast_expr (type_t *type, expr_t *e) return e; } -static int +static __attribute__((pure)) int valid_op (int op, int *valid_ops) { while (*valid_ops && op != *valid_ops) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 5daf3060e..fc87e31eb 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -208,7 +208,7 @@ leaf_node (dag_t *dag, operand_t *op, expr_t *expr) return node; } -static dagnode_t * +static __attribute__((pure)) dagnode_t * dag_node (operand_t *op) { def_t *def; diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 6f198851e..746a99ac2 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -72,7 +72,7 @@ report_function (expr_t *e) last_func = current_func; } -static void +static __attribute__((format(printf, 4, 0))) void format_message (dstring_t *message, const char *msg_type, expr_t *e, const char *fmt, va_list args) { @@ -90,7 +90,7 @@ format_message (dstring_t *message, const char *msg_type, expr_t *e, } } -static void +static __attribute__((format(printf, 2, 0))) void _warning (expr_t *e, const char *fmt, va_list args) { dstring_t *message = dstring_new (); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 45aa50882..0270ff58f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2462,7 +2462,7 @@ think_expr (symbol_t *think_sym) return new_symbol_expr (think_sym); } -static int +static __attribute__((pure)) int is_indirect (expr_t *e) { if (e->type == ex_block && e->e.block.result) @@ -2480,7 +2480,7 @@ is_indirect (expr_t *e) return 0; } -static inline int +static inline __attribute__((pure)) int is_lvalue (expr_t *e) { if (e->type == ex_symbol) { diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index bb398e045..4170c2970 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -153,7 +153,7 @@ delete_graph (flowgraph_t *graph) FREE (graphs, graph); } -static def_t * +static __attribute__((pure)) def_t * flowvar_get_def (flowvar_t *var) { operand_t *op = var->op; diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index ab1c873a8..e5102a6cf 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -212,7 +212,7 @@ copy_methods (methodlist_t *dst, methodlist_t *src) } } -int +__attribute__((pure)) int method_compare (method_t *m1, method_t *m2) { if (m1->instance != m2->instance) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index b7d5a389e..db4bcc3df 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -643,7 +643,7 @@ get_def_type (qfo_t *qfo, pointer_t type) return ev_invalid; } -static etype_t +static __attribute__((pure)) etype_t get_type_size (qfo_t *qfo, pointer_t type) { qfot_type_t *type_def; diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 14cc1265f..1b234e9e4 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -72,6 +72,13 @@ #define YY_DECL int yylex YY_PROTO(( void )) YY_DECL; +int yyget_lineno (void) __attribute__((pure)); +int yyget_leng (void) __attribute__((pure)); +int yywrap (void) __attribute__((const)); +char *yyget_text (void) __attribute__((pure)); +int yyget_debug (void) __attribute__((pure)); +FILE *yyget_in (void) __attribute__((pure)); +FILE *yyget_out (void) __attribute__((pure)); static int keyword_or_id (char *token); diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index e53cdc077..cf6d1257f 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -460,7 +460,7 @@ finish_link (void) return 0; } -static lang_t +static __attribute__((pure)) lang_t file_language (const char *file, const char *ext) { static ext_lang_t ext_lang[] = { diff --git a/tools/qfcc/source/qp-lex.l b/tools/qfcc/source/qp-lex.l index 0bca559c9..423aaf4e0 100644 --- a/tools/qfcc/source/qp-lex.l +++ b/tools/qfcc/source/qp-lex.l @@ -57,9 +57,16 @@ #define YY_DECL int yylex YY_PROTO(( void )) YY_DECL; +int yyget_lineno (void) __attribute__((pure)); +int yyget_leng (void) __attribute__((pure)); +int yywrap (void) __attribute__((const)); +char *yyget_text (void) __attribute__((pure)); +int yyget_debug (void) __attribute__((pure)); +FILE *yyget_in (void) __attribute__((pure)); +FILE *yyget_out (void) __attribute__((pure)); static int keyword_or_id (const char *token); -static int convert_relop (const char *relop); +static int convert_relop (const char *relop) __attribute__((pure)); %} diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index af6e70131..117b19a8e 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -23,11 +23,11 @@ options_t options; int num_linenos; pr_lineno_t *linenos; pr_info_t pr; -string_t ReuseString (const char *str) {return 0;} +__attribute__((const)) string_t ReuseString (const char *str) {return 0;} void encode_type (struct dstring_s *str, const type_t *type) {} -codespace_t *codespace_new (void) {return 0;} +__attribute__((const)) codespace_t *codespace_new (void) {return 0;} void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {} -int function_parms (function_t *f, byte *parm_size) {return 0;} +__attribute__((const)) int function_parms (function_t *f, byte *parm_size) {return 0;} void def_to_ddef (def_t *def, ddef_t *ddef, int aux) {} -expr_t *warning (expr_t *e, const char *fmt, ...) {return 0;} -expr_t *error (expr_t *e, const char *fmt, ...) {return 0;} +__attribute__((const)) expr_t *warning (expr_t *e, const char *fmt, ...) {return 0;} +__attribute__((const)) expr_t *error (expr_t *e, const char *fmt, ...) {return 0;} diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 718e1ea04..839f7ef4a 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -63,7 +63,7 @@ typedef struct case_node_s { struct case_node_s *left, *right; } case_node_t; -static ex_value_t * +static __attribute__((pure)) ex_value_t * get_value (expr_t *e) { if (e->type == ex_symbol) @@ -73,7 +73,7 @@ get_value (expr_t *e) return e->e.value; } -static uintptr_t +static __attribute__((pure)) uintptr_t get_hash (const void *_cl, void *unused) { case_label_t *cl = (case_label_t *) _cl; @@ -172,7 +172,7 @@ new_switch_block (void) return switch_block; } -static int +static __attribute__((pure)) int label_compare (const void *_a, const void *_b) { const case_label_t **a = (const case_label_t **) _a; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 586a7b1a0..bb1e3d7c2 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -218,7 +218,7 @@ append_type (type_t *type, type_t *new) return type; } -static int +static __attribute__((pure)) int types_same (type_t *a, type_t *b) { int i, count; diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 0d323ac99..ad84f25ae 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -259,7 +259,7 @@ imm_free (void *_imm, void *unused) free (_imm); } -static uintptr_t +static __attribute__((pure)) uintptr_t imm_get_hash (const void *_imm, void *_tab) { immediate_t *imm = (immediate_t *) _imm; @@ -290,7 +290,7 @@ imm_get_hash (const void *_imm, void *_tab) } } -static int +static __attribute__((pure)) int imm_compare (const void *_imm1, const void *_imm2, void *_tab) { immediate_t *imm1 = (immediate_t *) _imm1; diff --git a/tools/qfcc/test/test-defspace.c b/tools/qfcc/test/test-defspace.c index bc5f45077..cf2af5f58 100644 --- a/tools/qfcc/test/test-defspace.c +++ b/tools/qfcc/test/test-defspace.c @@ -17,7 +17,7 @@ pr_info_t pr; function_t *current_func; class_type_t *current_class; -const char * +__attribute__((const))const char * get_class_name (class_type_t *class_type, int prett) { return 0; diff --git a/tools/qflight/include/light.h b/tools/qflight/include/light.h index 0899bc1b8..e06a9157a 100644 --- a/tools/qflight/include/light.h +++ b/tools/qflight/include/light.h @@ -128,7 +128,7 @@ extern vec3_t *surfaceorgs; extern struct entity_s **novislights; extern int num_novislights; -const char *get_tex_name (int texindex); +const char *get_tex_name (int texindex) __attribute__((pure)); //@} diff --git a/tools/qflight/include/noise.h b/tools/qflight/include/noise.h index 0017ab107..30625ae13 100644 --- a/tools/qflight/include/noise.h +++ b/tools/qflight/include/noise.h @@ -33,10 +33,10 @@ */ //@{ -float noise3d (vec3_t v, int num); -float noiseXYZ (float x, float y, float z, int num); -float noise_scaled (vec3_t v, float s, int num); -float noise_perlin (vec3_t v, float p, int num); +float noise3d (vec3_t v, int num) __attribute__((pure)); +float noiseXYZ (float x, float y, float z, int num) __attribute__((pure)); +float noise_scaled (vec3_t v, float s, int num) __attribute__((pure)); +float noise_perlin (vec3_t v, float p, int num) __attribute__((pure)); void snap_vector (vec3_t v_old, vec3_t v_new, float scale); //@} diff --git a/tools/qflight/include/options.h b/tools/qflight/include/options.h index 22443ccae..a90592519 100644 --- a/tools/qflight/include/options.h +++ b/tools/qflight/include/options.h @@ -57,7 +57,7 @@ extern struct dstring_s *bspfile; extern const char *this_program; int DecodeArgs (int argc, char **argv); -void usage (int status); +void usage (int status) __attribute__((noreturn)); //@} diff --git a/tools/qflight/source/vis.c b/tools/qflight/source/vis.c index 44ed4ecca..e8267146c 100644 --- a/tools/qflight/source/vis.c +++ b/tools/qflight/source/vis.c @@ -73,7 +73,7 @@ int num_alllights; entity_t **novislights; int num_novislights; -static dleaf_t * +static __attribute__((pure)) dleaf_t * Light_PointInLeaf (vec3_t point) { int num = 0, side; diff --git a/tools/qfvis/include/options.h b/tools/qfvis/include/options.h index 0af22f520..521a4ef94 100644 --- a/tools/qfvis/include/options.h +++ b/tools/qfvis/include/options.h @@ -40,7 +40,7 @@ typedef struct { extern options_t options; int DecodeArgs (int argc, char **argv); -void usage (int status); +void usage (int status) __attribute__((noreturn)); extern const char *this_program; #endif//__options_h From ba3220e4d16f032d6deb16563ecb67e19a2d437c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Oct 2018 12:36:39 +0900 Subject: [PATCH 0059/3664] Fix a format oops. I had never noticed the error... --- nq/source/host_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index fa75e33e8..31bf539b5 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -90,7 +90,7 @@ Host_Status_f (void) print = SV_ClientPrintf; print ("host: %s\n", Cvar_VariableString ("hostname")); - print ("version: %4.2f\n", PACKAGE_VERSION); + print ("version: %4.2s\n", PACKAGE_VERSION); if (tcpipAvailable) print ("tcp/ip: %s\n", my_tcpip_address); print ("map: %s\n", sv.name); From 6f28ab2a681162d4b5338318343b0d42752dc3de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Oct 2018 12:44:46 +0900 Subject: [PATCH 0060/3664] Add basic quaternion multiplication tests. --- libs/util/test/test-quat.c | 79 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index 58a3e0a2f..ce679771c 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -4,6 +4,15 @@ #include "QF/mathlib.h" +static struct { + quat_t q1; + quat_t q2; + quat_t expect; +} quat_mult_tests[] = { + {{4, 1, 2, 3}, {8, 5, 6, 7}, {-6, 24, 48, 48}}, +}; +#define num_quat_mult_tests (sizeof (quat_mult_tests) / sizeof (quat_mult_tests[0])) + //PITCH YAW ROLL static vec3_t test_angles[] = { {0, 0, 0}, @@ -28,6 +37,41 @@ compare (vec_t a, vec_t b) return diff * diff < 0.001; } +static int +test_quat_mult(const quat_t q1, const quat_t q2, const quat_t expect) +{ + int i; + quat_t r; + + QuatMult (q1, q2, r); + + for (i = 0; i < 4; i++) + if (!compare (r[i], expect[i])) + goto fail; + return 1; +fail: + printf ("%g %g %g %g\n", QuatExpand (q1)); + printf ("%g %g %g %g\n", QuatExpand (q2)); + printf ("%g %g %g %g\n", QuatExpand (r)); + printf ("%g %g %g %g\n", QuatExpand (expect)); + return 0; +} + + +static void +rotate_vec (const quat_t r, const vec3_t v, vec3_t out) +{ + quat_t qv = {0, 0, 0, 0}; + quat_t t; + + VectorCopy (v, qv + 1); + + QuatConj (r, t); + QuatMult (qv, t, t); + QuatMult (r, t, t); + VectorCopy (t + 1, out); +} + static int test_rotation (const vec3_t angles) { @@ -131,12 +175,42 @@ fail: return 0; } +static int +test_rotation3 (const vec3_t angles) +{ + int i; + quat_t quat; + vec3_t v = {1, 1, 1}; + vec3_t a, b; + + AngleQuat (angles, quat); + QuatMultVec (quat, v, a); + rotate_vec (quat, v, b); + + for (i = 0; i < 3; i++) + if (!compare (a[i], b[i])) + goto fail; + return 1; +fail: + printf ("%g %g %g\n", VectorExpand(a)); + printf ("%g %g %g\n", VectorExpand(b)); + return 0; +} + int main (int argc, const char **argv) { int res = 0; size_t i; + for (i = 0; i < num_quat_mult_tests; i ++) { + vec_t *q1 = quat_mult_tests[i].q1; + vec_t *q2 = quat_mult_tests[i].q2; + vec_t *expect = quat_mult_tests[i].expect; + if (!test_quat_mult (q1, q2, expect)) + res = 1; + } + for (i = 0; i < num_angle_tests; i ++) { if (!test_rotation (test_angles[i])) res = 1; @@ -146,5 +220,10 @@ main (int argc, const char **argv) if (!test_rotation2 (test_angles[i])) res = 1; } + + for (i = 0; i < num_angle_tests; i ++) { + if (!test_rotation3 (test_angles[i])) + res = 1; + } return res; } From d95c01be1a60fd83feaeb156e5e1d43dc01cda9d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Oct 2018 12:45:26 +0900 Subject: [PATCH 0061/3664] More defspace tests. --- tools/qfcc/test/Makefile.am | 2 +- tools/qfcc/test/test-defspace.c | 3 +- tools/qfcc/test/test-defspace.h | 6 ++++ tools/qfcc/test/tw-defspace.c | 54 +++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 tools/qfcc/test/test-defspace.h diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index cf982bd69..b1a199fff 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -211,5 +211,5 @@ voidfor.run: Makefile build-run include ./$(DEPDIR)/voidfor.Qo -EXTRA_DIST= test-bi.h build-run +EXTRA_DIST= test-bi.h build-run test-defspace.h CLEANFILES= *.dat *.sym *.qfo *.run *.frame diff --git a/tools/qfcc/test/test-defspace.c b/tools/qfcc/test/test-defspace.c index cf2af5f58..5d14c5013 100644 --- a/tools/qfcc/test/test-defspace.c +++ b/tools/qfcc/test/test-defspace.c @@ -5,13 +5,14 @@ #include #include "class.h" -#include "defspace.h" #include "expr.h" #include "function.h" #include "options.h" #include "strpool.h" #include "qfcc.h" +#include "test-defspace.h" + options_t options; pr_info_t pr; function_t *current_func; diff --git a/tools/qfcc/test/test-defspace.h b/tools/qfcc/test/test-defspace.h new file mode 100644 index 000000000..1735003bf --- /dev/null +++ b/tools/qfcc/test/test-defspace.h @@ -0,0 +1,6 @@ +#include "def.h" +#include "defspace.h" + +int def_list_is_empty (const defspace_t *space); +int def_list_is_valid (const defspace_t *space); +int free_locs_is_valid (const defspace_t *space); diff --git a/tools/qfcc/test/tw-defspace.c b/tools/qfcc/test/tw-defspace.c index c3b950324..c1f599810 100644 --- a/tools/qfcc/test/tw-defspace.c +++ b/tools/qfcc/test/tw-defspace.c @@ -1 +1,55 @@ #include "../source/defspace.c" +#include "test-defspace.h" + +__attribute__((pure)) int +def_list_is_empty (const defspace_t *space) +{ + return (!space->defs && space->def_tail == &space->defs); +} + +__attribute__((pure)) int +def_list_is_valid (const defspace_t *space) +{ + def_t *const *d = &space->defs; + + while (*d) { + d = &(*d)->next; + } + return d == space->def_tail; +} + +int +free_locs_is_valid (const defspace_t *space) +{ + int free_space = 0; + const locref_t *loc; + + for (loc = space->free_locs; loc; loc = loc->next) { + if (loc->ofs < 0) { + printf ("negative offset in free_locs\n"); + return 0; + } + if (loc->size <= 0) { + printf ("zero or negative size in free_locs\n"); + return 0; + } + if (loc->next && loc->ofs > loc->next->ofs) { + printf ("free_locs not in ascending order\n"); + return 0; + } + if (loc->next && loc->ofs + loc->size > loc->next->ofs) { + printf ("overlap in free_locs\n"); + return 0; + } + if (loc->next && loc->ofs + loc->size == loc->next->ofs) { + printf ("adjoining nodes in free_locs\n"); + return 0; + } + free_space += loc->size; + } + if (free_space > space->size) { + printf ("free_locs describes too much free space\n"); + return 0; + } + return 1; +} From 673b45be05fc6bbcabf0a1fe51972ee1fd62a8ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Oct 2018 12:46:13 +0900 Subject: [PATCH 0062/3664] Add diagnostic hooks. --- tools/qfcc/include/diagnostic.h | 6 ++++++ tools/qfcc/source/diagnostic.c | 26 +++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index 51eea07a5..6c28ccd41 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -38,6 +38,12 @@ */ //@{ +typedef void (*diagnostic_hook)(const char *message); +extern diagnostic_hook bug_hook; +extern diagnostic_hook error_hook; +extern diagnostic_hook warning_hook; +extern diagnostic_hook notice_hook; + struct expr_s *error (struct expr_s *e, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); void diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 746a99ac2..aa57ea19f 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -41,6 +41,11 @@ #include "options.h" #include "strpool.h" +diagnostic_hook bug_hook; +diagnostic_hook error_hook; +diagnostic_hook warning_hook; +diagnostic_hook notice_hook; + static void report_function (expr_t *e) { @@ -103,6 +108,11 @@ _warning (expr_t *e, const char *fmt, va_list args) } format_message (message, "warning", e, fmt, args); + if (warning_hook) { + warning_hook (message->str); + } else { + fprintf (stderr, "%s\n", message->str); + } fprintf (stderr, "%s\n", message->str); dstring_delete (message); } @@ -139,7 +149,11 @@ bug (expr_t *e, const char *fmt, ...) dstring_t *message = dstring_new (); format_message (message, "BUG", e, fmt, args); - fprintf (stderr, "%s\n", message->str); + if (bug_hook) { + bug_hook (message->str); + } else { + fprintf (stderr, "%s\n", message->str); + } dstring_delete (message); } va_end (args); @@ -162,6 +176,11 @@ notice (expr_t *e, const char *fmt, ...) report_function (e); format_message (message, "notice", e, fmt, args); + if (notice_hook) { + notice_hook (message->str); + } else { + fprintf (stderr, "%s\n", message->str); + } fprintf (stderr, "%s\n", message->str); dstring_delete (message); } @@ -211,6 +230,11 @@ error (expr_t *e, const char *fmt, ...) dstring_t *message = dstring_new (); format_message (message, "error", e, fmt, args); + if (error_hook) { + error_hook (message->str); + } else { + fprintf (stderr, "%s\n", message->str); + } fprintf (stderr, "%s\n", message->str); dstring_delete (message); } From 4872c56e2dbfd9c7be6030dfdf34e9802879abc4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 10:05:36 +0900 Subject: [PATCH 0063/3664] Mark the end of the v6 opcodes. --- include/QF/pr_comp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 7bac7eb01..89782ce9b 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -140,7 +140,7 @@ typedef enum { OP_OR, OP_BITAND, - OP_BITOR, + OP_BITOR, // end of v6 opcodes OP_ADD_S, OP_LE_S, From 82809eb856c64d86ffadfa44158eed83ec75d380 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 10:06:48 +0900 Subject: [PATCH 0064/3664] Simplify the call to PR_LoadProgsFile. I've decided that setting pr.max_edicts and pr.zone_size as part of the local progs initialization rather than in PR_LoadProgsFile makes more sense. For one, it is unlikely for the limits to change every time progs is reloaded. Also, they seem to be a property of the VM rather than the progs. However, there is nothing stopping the caller from updating max_edicts and zone_size every call. --- include/QF/progs.h | 23 +++++++++-------------- libs/console/menu.c | 5 ++++- libs/gamecode/pr_load.c | 11 ++++------- nq/source/sv_progs.c | 5 +++-- qw/source/sv_progs.c | 5 +++-- tools/qfcc/source/qfprogs.c | 4 +++- tools/qwaq/main.c | 4 +++- tools/qwaq/qwaq.c | 4 +++- 8 files changed, 32 insertions(+), 29 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 72eea81cc..38fed81f5 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -145,27 +145,22 @@ typedef int pr_load_func_t (progs_t *pr); \param pr pointer to ::progs_t VM struct \param file handle of file to read progs data from \param size bytes of \p file to read - \param max_edicts \e number of entities to allocate space for - \param zone minimum size of dynamic memory to allocate space for - dynamic memory (bytes). \note \e All runtime strings (permanent or temporary) are allocated from - the VM's dynamic memory space, so be sure \p zone is of sufficient size. - So far, 1MB has proven more than sufficient for Quakeword, even when using - Ruamoko objects. + the VM's dynamic memory space, so be sure \p zone is of sufficient size + (by setting pr->zone_size prior to calling). So far, 1MB has proven more + than sufficient for Quakeword, even when using Ruamoko objects. + \note If entities are used, ensure pr->max_edicts is set appropriately + prior to calling. */ -void PR_LoadProgsFile (progs_t *pr, struct QFile_s *file, int size, - int max_edicts, int zone); +void PR_LoadProgsFile (progs_t *pr, struct QFile_s *file, int size); /** Convenience wrapper for PR_LoadProgsFile() and PR_RunLoadFuncs(). Searches for the specified file in the Quake filesystem. \param pr pointer to ::progs_t VM struct \param progsname name of the file to load as progs data - \param max_edicts \e number of entities to allocate space for - \param zone minimum size of dynamic memory to allocate space for */ -void PR_LoadProgs (progs_t *pr, const char *progsname, int max_edicts, - int zone); +void PR_LoadProgs (progs_t *pr, const char *progsname); /** Register a primary function to be called after the progs code has been loaded. These functions are remembered across progs loads. They will be @@ -1521,7 +1516,7 @@ struct progs_s { int denorm_found; struct memzone_s *zone; - int zone_size; + int zone_size; ///< set by user /// \name builtin functions //@{ @@ -1593,7 +1588,7 @@ struct progs_s { /// \name edicts //@{ edict_t **edicts; - int max_edicts; + int max_edicts; ///< set by user int *num_edicts; int *reserved_edicts; ///< alloc will start at reserved_edicts+1 void (*unlink) (edict_t *ent); diff --git a/libs/console/menu.c b/libs/console/menu.c index 48df52b7d..e65fff1cb 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -578,6 +578,9 @@ Menu_Init (void) menu_pr_state.load_file = menu_load_file; menu_pr_state.resolve = menu_resolve_globals; + menu_pr_state.max_edicts = 0; + menu_pr_state.zone_size = 1024 * 1024; + menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0); PR_RegisterBuiltins (&menu_pr_state, builtins); @@ -617,7 +620,7 @@ Menu_Load (void) menu_pr_state.progs = 0; if ((file = QFS_FOpenFile (menu_pr_state.progs_name))) { size = Qfilesize (file); - PR_LoadProgsFile (&menu_pr_state, file, size, 0, 1024 * 1024); + PR_LoadProgsFile (&menu_pr_state, file, size); Qclose (file); if (!PR_RunLoadFuncs (&menu_pr_state)) { diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 82864b096..3fe00eb00 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -98,7 +98,7 @@ free_progs_mem (progs_t *pr, void *mem) } VISIBLE void -PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) +PR_LoadProgsFile (progs_t *pr, QFile *file, int size) { size_t i; int mem_size; @@ -166,8 +166,6 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) pr->progs_size += sizeof (void*) - 1; pr->progs_size &= ~(sizeof (void*) - 1); - // size of heap asked for by vm-subsystem - pr->zone_size = zone; // round off to next highest whole word address (esp for Alpha) // this ensures that pointers in the engine data area are always // properly aligned @@ -183,8 +181,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) // properly aligned pr->pr_edict_size += sizeof (void*) - 1; pr->pr_edict_size &= ~(sizeof (void*) - 1); - pr->pr_edictareasize = max_edicts * pr->pr_edict_size; - pr->max_edicts = max_edicts; + pr->pr_edictareasize = pr->max_edicts * pr->pr_edict_size; mem_size = pr->progs_size + pr->zone_size + pr->pr_edictareasize; pr->progs = pr->allocate_progs_mem (pr, mem_size + 1); @@ -379,14 +376,14 @@ PR_RunLoadFuncs (progs_t *pr) PR_LoadProgs */ VISIBLE void -PR_LoadProgs (progs_t *pr, const char *progsname, int max_edicts, int zone) +PR_LoadProgs (progs_t *pr, const char *progsname) { QFile *file; file = QFS_FOpenFile (progsname); pr->progs_name = progsname; if (file) { - PR_LoadProgsFile (pr, file, qfs_filesize, max_edicts, zone); + PR_LoadProgsFile (pr, file, qfs_filesize); Qclose (file); } if (!pr->progs) diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 37b915e9c..c289b6e44 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -498,8 +498,9 @@ SV_LoadProgs (void) if (*sv_progs->string) progs_name = sv_progs->string; - PR_LoadProgs (&sv_pr_state, progs_name, sv.max_edicts, - sv_progs_zone->int_val * 1024); + sv_pr_state.max_edicts = sv.max_edicts; + sv_pr_state.zone_size = sv_progs_zone->int_val * 1024; + PR_LoadProgs (&sv_pr_state, progs_name); if (!sv_pr_state.progs) Host_Error ("SV_LoadProgs: couldn't load %s", progs_name); diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index e11805c17..cad265b11 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -521,8 +521,9 @@ SV_LoadProgs (void) if (*sv_progs->string) progs_name = sv_progs->string; - PR_LoadProgs (&sv_pr_state, progs_name, MAX_EDICTS, - sv_progs_zone->int_val * 1024); + sv_pr_state.max_edicts = MAX_EDICTS; + sv_pr_state.zone_size = sv_progs_zone->int_val * 1024; + PR_LoadProgs (&sv_pr_state, progs_name); if (!sv_pr_state.progs) Sys_Error ("SV_LoadProgs: couldn't load %s", progs_name); diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index d6bf84927..10ddf8abd 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -322,7 +322,9 @@ load_progs (const char *name) convert_qfo (); } else { pr.progs_name = name; - PR_LoadProgsFile (&pr, file, size, 1, 0); + pr.max_edicts = 1; + pr.zone_size = 0; + PR_LoadProgsFile (&pr, file, size); Qclose (file); if (!pr.progs) diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index edb7c0229..570b6a3b7 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -133,7 +133,9 @@ load_progs (const char *name) return 0; } pr.progs_name = name; - PR_LoadProgsFile (&pr, file, size, 1, 1024 * 1024); + pr.max_edicts = 1; + pr.zone_size = 1024*1024; + PR_LoadProgsFile (&pr, file, size); Qclose (file); if (!PR_RunLoadFuncs (&pr)) PR_Error (&pr, "unable to load %s", pr.progs_name); diff --git a/tools/qwaq/qwaq.c b/tools/qwaq/qwaq.c index f1197ccfb..a6294887e 100644 --- a/tools/qwaq/qwaq.c +++ b/tools/qwaq/qwaq.c @@ -144,7 +144,9 @@ load_progs (const char *name) return 0; } pr.progs_name = name; - PR_LoadProgsFile (&pr, file, size, 1, 1024 * 1024); + pr.max_edicts = 1; + pr.zone_size = 1024*1024; + PR_LoadProgsFile (&pr, file, size); Qclose (file); if (!PR_RunLoadFuncs (&pr)) PR_Error (&pr, "unable to load %s", pr.progs_name); From 61185813faa970826dd91ec6479310558d6735f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 10:22:10 +0900 Subject: [PATCH 0065/3664] Cleaner handling of zone_size/zone. --- libs/gamecode/pr_load.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 3fe00eb00..81135dc5a 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -197,8 +197,12 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) if (pr->edicts) *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); - pr->zone = (memzone_t *)((byte *) pr->progs + pr->progs_size - + pr->pr_edictareasize); + if (pr->zone_size) { + //FIXME zone_size needs to be at least as big as memzone_t, but + //memzone_t is opaque so its size is unknown + pr->zone = (memzone_t *)((byte *) pr->progs + pr->progs_size + + pr->pr_edictareasize); + } pr->pr_functions = (dfunction_t *) (base + pr->progs->ofs_functions); @@ -212,8 +216,9 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->globals_size = (pr_type_t*)((byte *) pr->zone + pr->zone_size) - pr->pr_globals; - if (pr->zone_size) + if (pr->zone) { PR_Zone_Init (pr); + } if (pr->function_hash) { Hash_FlushTable (pr->function_hash); From 9501d30a8f88d0776b6b628a79589b8c6f6fac56 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 11:29:12 +0900 Subject: [PATCH 0066/3664] Fix up a missing const attribute. The problem with having such a complex build system :P --- include/QF/plugin.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/plugin.h b/include/QF/plugin.h index 57a4ba9ff..28cb9962f 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -40,7 +40,7 @@ #ifdef STATIC_PLUGINS #define PLUGIN_INFO(type,name) plugin_t *type##_##name##_PluginInfo (void); __attribute__((const)) plugin_t * type##_##name##_PluginInfo (void) #else -#define PLUGIN_INFO(type,name) plugin_t *PluginInfo (void); __attribute__((visibility ("default"))) plugin_t *PluginInfo (void) +#define PLUGIN_INFO(type,name) plugin_t *PluginInfo (void); __attribute__((visibility ("default"),const)) plugin_t *PluginInfo (void) #endif typedef enum { From 364c2d2c2b24e7d86be65cc5ca16cce24c463edd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 13:24:03 +0900 Subject: [PATCH 0067/3664] Add a stack and push and pop instructions. The stack is for data, not return addresses. --- include/QF/pr_comp.h | 60 +++++++ include/QF/progs.h | 14 ++ libs/gamecode/pr_exec.c | 325 +++++++++++++++++++++++++++++++++- libs/gamecode/pr_load.c | 47 +++-- libs/gamecode/pr_opcode.c | 353 ++++++++++++++++++++++++++++++++++++- libs/gamecode/pr_resolve.c | 7 + 6 files changed, 785 insertions(+), 21 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 89782ce9b..c657a7ca1 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -295,6 +295,66 @@ typedef enum { OP_RCALL8, OP_RETURN_V, + + OP_PUSH_S, + OP_PUSH_F, + OP_PUSH_V, + OP_PUSH_ENT, + OP_PUSH_FLD, + OP_PUSH_FN, + OP_PUSH_P, + OP_PUSH_Q, + OP_PUSH_I, + + OP_PUSHB_S, + OP_PUSHB_F, + OP_PUSHB_V, + OP_PUSHB_ENT, + OP_PUSHB_FLD, + OP_PUSHB_FN, + OP_PUSHB_P, + OP_PUSHB_Q, + OP_PUSHB_I, + + OP_PUSHBI_S, + OP_PUSHBI_F, + OP_PUSHBI_V, + OP_PUSHBI_ENT, + OP_PUSHBI_FLD, + OP_PUSHBI_FN, + OP_PUSHBI_P, + OP_PUSHBI_Q, + OP_PUSHBI_I, + + OP_POP_S, + OP_POP_F, + OP_POP_V, + OP_POP_ENT, + OP_POP_FLD, + OP_POP_FN, + OP_POP_P, + OP_POP_Q, + OP_POP_I, + + OP_POPB_S, + OP_POPB_F, + OP_POPB_V, + OP_POPB_ENT, + OP_POPB_FLD, + OP_POPB_FN, + OP_POPB_P, + OP_POPB_Q, + OP_POPB_I, + + OP_POPBI_S, + OP_POPBI_F, + OP_POPBI_V, + OP_POPBI_ENT, + OP_POPBI_FLD, + OP_POPBI_FN, + OP_POPBI_P, + OP_POPBI_Q, + OP_POPBI_I, } pr_opcode_e; typedef struct opcode_s { diff --git a/include/QF/progs.h b/include/QF/progs.h index 38fed81f5..5b834d1f0 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1612,6 +1612,19 @@ struct progs_s { prstack_t pr_stack[MAX_STACK_DEPTH]; int pr_depth; + /// \name progs visible stack + /// Usable by the progs for any purpose. Will not be accessible unless + /// a .stack global is found. Space is allocated from the top of the stack + /// (as is common for hardware). The push and pop instructions will not + /// be considered valid if there is no .stack global. + /// \note The return address and saved locals will not ever be on this + /// stack. + //@{ + pr_type_t *stack; + pointer_t stack_bottom; + int stack_size; ///< set by user + //@} + int localstack[LOCALSTACK_SIZE]; int localstack_used; //@} @@ -1656,6 +1669,7 @@ struct progs_s { struct { float *time; ///< required for OP_STATE pr_int_t *self; ///< required for OP_STATE + pointer_t *stack; ///< required for OP_(PUSH|POP)* } globals; struct { pr_int_t nextthink; ///< required for OP_STATE diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 579992271..65fa0cc35 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -358,13 +358,24 @@ PR_CallFunction (progs_t *pr, func_t fnum) } } +static void +check_stack_pointer (progs_t *pr, pointer_t stack, int size) +{ + if (stack < pr->stack_bottom) { + PR_RunError (pr, "Progs stack overflow"); + } + if (stack > pr->globals_size - size) { + PR_RunError (pr, "Progs stack underflow"); + } +} + /* PR_ExecuteProgram The interpretation main loop */ VISIBLE void -PR_ExecuteProgram (progs_t * pr, func_t fnum) +PR_ExecuteProgram (progs_t *pr, func_t fnum) { int exitdepth, profile, startprofile; pr_uint_t pointer; @@ -859,6 +870,318 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) QuatCopy (OPA.quat_var, ptr->quat_var); break; + case OP_PUSH_F: + case OP_PUSH_FLD: + case OP_PUSH_ENT: + case OP_PUSH_S: + case OP_PUSH_FN: + case OP_PUSH_I: + case OP_PUSH_P: + { + pointer_t stack = *pr->globals.stack - 1; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 1); + } + stk->integer_var = OPA.integer_var; + *pr->globals.stack = stack; + } + break; + case OP_PUSH_V: + { + pointer_t stack = *pr->globals.stack - 3; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 3); + } + memcpy (stk, &OPA, 3 * sizeof (OPC)); + *pr->globals.stack = stack; + } + break; + case OP_PUSH_Q: + { + pointer_t stack = *pr->globals.stack - 4; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + } + memcpy (stk, &OPA, 4 * sizeof (OPC)); + *pr->globals.stack = stack; + } + break; + + case OP_PUSHB_F: + case OP_PUSHB_S: + case OP_PUSHB_ENT: + case OP_PUSHB_FLD: + case OP_PUSHB_FN: + case OP_PUSHB_I: + case OP_PUSHB_P: + { + pointer_t stack = *pr->globals.stack - 1; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + OPB.integer_var; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 1); + PR_BoundsCheck (pr, pointer, ev_integer); + } + + stk->integer_var = ptr->integer_var; + *pr->globals.stack = stack; + } + break; + case OP_PUSHB_V: + { + pointer_t stack = *pr->globals.stack - 3; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + OPB.integer_var; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 3); + PR_BoundsCheck (pr, pointer, ev_integer); + } + + VectorCopy (ptr->vector_var, stk->vector_var); + *pr->globals.stack = stack; + } + break; + case OP_PUSHB_Q: + { + pointer_t stack = *pr->globals.stack - 4; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + OPB.integer_var; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + PR_BoundsCheck (pr, pointer, ev_quat); + } + + QuatCopy (ptr->quat_var, stk->quat_var); + *pr->globals.stack = stack; + } + break; + + case OP_PUSHBI_F: + case OP_PUSHBI_S: + case OP_PUSHBI_ENT: + case OP_PUSHBI_FLD: + case OP_PUSHBI_FN: + case OP_PUSHBI_I: + case OP_PUSHBI_P: + { + pointer_t stack = *pr->globals.stack - 1; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + st->b; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 1); + PR_BoundsCheck (pr, pointer, ev_integer); + } + + stk->integer_var = ptr->integer_var; + *pr->globals.stack = stack; + } + break; + case OP_PUSHBI_V: + { + pointer_t stack = *pr->globals.stack - 3; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + st->b; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 3); + PR_BoundsCheck (pr, pointer, ev_integer); + } + + VectorCopy (ptr->vector_var, stk->vector_var); + *pr->globals.stack = stack; + } + break; + case OP_PUSHBI_Q: + { + pointer_t stack = *pr->globals.stack - 4; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + st->b; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + PR_BoundsCheck (pr, pointer, ev_quat); + } + + QuatCopy (ptr->quat_var, stk->quat_var); + *pr->globals.stack = stack; + } + break; + + case OP_POP_F: + case OP_POP_FLD: + case OP_POP_ENT: + case OP_POP_S: + case OP_POP_FN: + case OP_POP_I: + case OP_POP_P: + { + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 1); + } + stk->integer_var = OPA.integer_var; + *pr->globals.stack = stack + 1; + } + break; + case OP_POP_V: + { + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 3); + } + memcpy (stk, &OPA, 3 * sizeof (OPC)); + *pr->globals.stack = stack + 3; + } + break; + case OP_POP_Q: + { + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + } + memcpy (stk, &OPA, 4 * sizeof (OPC)); + *pr->globals.stack = stack + 4; + } + break; + + case OP_POPB_F: + case OP_POPB_S: + case OP_POPB_ENT: + case OP_POPB_FLD: + case OP_POPB_FN: + case OP_POPB_I: + case OP_POPB_P: + { + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + OPB.integer_var; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 1); + PR_BoundsCheck (pr, pointer, ev_integer); + } + + stk->integer_var = ptr->integer_var; + *pr->globals.stack = stack + 1; + } + break; + case OP_POPB_V: + { + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + OPB.integer_var; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 3); + PR_BoundsCheck (pr, pointer, ev_integer); + } + + VectorCopy (ptr->vector_var, stk->vector_var); + *pr->globals.stack = stack + 3; + } + break; + case OP_POPB_Q: + { + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + OPB.integer_var; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + PR_BoundsCheck (pr, pointer, ev_quat); + } + + QuatCopy (ptr->quat_var, stk->quat_var); + *pr->globals.stack = stack + 4; + } + break; + + case OP_POPBI_F: + case OP_POPBI_S: + case OP_POPBI_ENT: + case OP_POPBI_FLD: + case OP_POPBI_FN: + case OP_POPBI_I: + case OP_POPBI_P: + { + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + st->b; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 1); + PR_BoundsCheck (pr, pointer, ev_integer); + } + + stk->integer_var = ptr->integer_var; + *pr->globals.stack = stack + 1; + } + break; + case OP_POPBI_V: + { + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + st->b; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 3); + PR_BoundsCheck (pr, pointer, ev_integer); + } + + VectorCopy (ptr->vector_var, stk->vector_var); + *pr->globals.stack = stack + 3; + } + break; + case OP_POPBI_Q: + { + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + + pointer = OPA.integer_var + st->b; + ptr = pr->pr_globals + pointer; + + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + PR_BoundsCheck (pr, pointer, ev_quat); + } + + QuatCopy (ptr->quat_var, stk->quat_var); + *pr->globals.stack = stack + 4; + } + break; + // ================== case OP_IFNOT: if (!OPA.integer_var) { diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 81135dc5a..b00efd12e 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -97,6 +97,17 @@ free_progs_mem (progs_t *pr, void *mem) { } +static int +align_size (int size) +{ + // round off to next highest whole word address (esp for Alpha) + // this ensures that pointers in the engine data area are always + // properly aligned + size += sizeof (void*) - 1; + size &= ~(sizeof (void*) - 1); + return size; +} + VISIBLE void PR_LoadProgsFile (progs_t *pr, QFile *file, int size) { @@ -160,33 +171,27 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) // size of progs themselves pr->progs_size = size + offset_tweak; Sys_MaskPrintf (SYS_DEV, "Programs occupy %iK.\n", size / 1024); - // round off to next highest whole word address (esp for Alpha) - // this ensures that pointers in the engine data area are always - // properly aligned - pr->progs_size += sizeof (void*) - 1; - pr->progs_size &= ~(sizeof (void*) - 1); - // round off to next highest whole word address (esp for Alpha) - // this ensures that pointers in the engine data area are always - // properly aligned - pr->zone_size += sizeof (void*) - 1; - pr->zone_size &= ~(sizeof (void*) - 1); + pr->progs_size = align_size (pr->progs_size); + pr->zone_size = align_size (pr->zone_size); + pr->stack_size = align_size (pr->stack_size); // size of edict asked for by progs pr->pr_edict_size = max (1, progs.entityfields) * 4; // size of engine data pr->pr_edict_size += sizeof (edict_t); - // round off to next highest whole word address (esp for Alpha) - // this ensures that pointers in the engine data area are always - // properly aligned - pr->pr_edict_size += sizeof (void*) - 1; - pr->pr_edict_size &= ~(sizeof (void*) - 1); + pr->pr_edict_size = align_size (pr->progs_size); + pr->pr_edictareasize = pr->max_edicts * pr->pr_edict_size; - mem_size = pr->progs_size + pr->zone_size + pr->pr_edictareasize; + mem_size = pr->progs_size + pr->zone_size + pr->pr_edictareasize + + pr->stack_size; + // +1 for a nul terminator pr->progs = pr->allocate_progs_mem (pr, mem_size + 1); if (!pr->progs) return; + // Place a nul at the end of progs memory to ensure any unterminated + // strings within progs memory don't run off the end. ((byte *) pr->progs)[mem_size] = 0; memcpy (pr->progs, &progs, sizeof (progs)); @@ -195,8 +200,10 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) CRC_ProcessBlock (base, &pr->crc, size - sizeof (progs)); base -= sizeof (progs); // offsets are from file start - if (pr->edicts) + if (pr->edicts) { *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); + } + if (pr->zone_size) { //FIXME zone_size needs to be at least as big as memzone_t, but //memzone_t is opaque so its size is unknown @@ -213,9 +220,11 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->pr_statements = (dstatement_t *) (base + pr->progs->ofs_statements); pr->pr_globals = (pr_type_t *) (base + pr->progs->ofs_globals); - - pr->globals_size = (pr_type_t*)((byte *) pr->zone + pr->zone_size) + pr->stack = (pr_type_t *) ((byte *) pr->zone + pr->zone_size); + pr->stack_bottom = pr->stack - pr->pr_globals; + pr->globals_size = (pr_type_t *) ((byte *) pr->stack + pr->stack_size) - pr->pr_globals; + if (pr->zone) { PR_Zone_Init (pr); } diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index d93e7340c..9e970c781 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -44,6 +44,8 @@ #include "QF/progs.h" #include "QF/sys.h" +#include "compat.h" + hashtab_t *opcode_table; VISIBLE int pr_type_size[ev_type_count] = { @@ -1041,6 +1043,282 @@ VISIBLE opcode_t pr_opcodes[] = { "%Ga, %Gb, %Gc", }, + {"", "push.s", OP_PUSH_S, false, + ev_string, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, + {"", "push.f", OP_PUSH_F, false, + ev_float, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, + {"", "push.v", OP_PUSH_V, false, + ev_vector, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, + {"", "push.ent", OP_PUSH_ENT, false, + ev_entity, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, + {"", "push.fld", OP_PUSH_FLD, false, + ev_field, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, + {"", "push.fn", OP_PUSH_FN, false, + ev_func, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, + {"", "push.p", OP_PUSH_P, false, + ev_pointer, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, + {"", "push.q", OP_PUSH_Q, false, + ev_quat, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, + {"", "push.i", OP_PUSH_I, false, + ev_integer, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, + + {"", "pushb.s", OP_PUSHB_S, false, + ev_pointer, ev_integer, ev_string, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "pushb.f", OP_PUSHB_F, false, + ev_pointer, ev_integer, ev_float, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "pushb.v", OP_PUSHB_V, false, + ev_pointer, ev_integer, ev_vector, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "pushb.ent", OP_PUSHB_ENT, false, + ev_pointer, ev_integer, ev_entity, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "pushb.fld", OP_PUSHB_FLD, false, + ev_pointer, ev_integer, ev_field, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "pushb.fn", OP_PUSHB_FN, false, + ev_pointer, ev_integer, ev_func, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "pushb.p", OP_PUSHB_P, false, + ev_pointer, ev_integer, ev_pointer, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "pushb.q", OP_PUSHB_Q, false, + ev_pointer, ev_integer, ev_quat, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "pushb.i", OP_PUSHB_I, false, + ev_pointer, ev_integer, ev_integer, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + + {"", "pushbi.s", OP_PUSHBI_S, false, + ev_pointer, ev_short, ev_string, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "pushbi.f", OP_PUSHBI_F, false, + ev_pointer, ev_short, ev_float, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "pushbi.v", OP_PUSHBI_V, false, + ev_pointer, ev_short, ev_vector, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "pushbi.ent", OP_PUSHBI_ENT, false, + ev_pointer, ev_short, ev_entity, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "pushbi.fld", OP_PUSHBI_FLD, false, + ev_pointer, ev_short, ev_field, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "pushbi.fn", OP_PUSHBI_FN, false, + ev_pointer, ev_short, ev_func, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "pushbi.p", OP_PUSHBI_P, false, + ev_pointer, ev_short, ev_pointer, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "pushbi.q", OP_PUSHBI_Q, false, + ev_pointer, ev_short, ev_quat, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "pushbi.i", OP_PUSHBI_I, false, + ev_pointer, ev_short, ev_integer, + PROG_VERSION, + "*(%Ga + %sb)", + }, + + {"", "pop.s", OP_POP_S, false, + ev_string, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, + {"", "pop.f", OP_POP_F, false, + ev_float, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, + {"", "pop.v", OP_POP_V, false, + ev_vector, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, + {"", "pop.ent", OP_POP_ENT, false, + ev_entity, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, + {"", "pop.fld", OP_POP_FLD, false, + ev_field, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, + {"", "pop.fn", OP_POP_FN, false, + ev_func, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, + {"", "pop.p", OP_POP_P, false, + ev_pointer, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, + {"", "pop.q", OP_POP_Q, false, + ev_quat, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, + {"", "pop.i", OP_POP_I, false, + ev_integer, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, + + {"", "popb.s", OP_POPB_S, false, + ev_pointer, ev_integer, ev_string, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "popb.f", OP_POPB_F, false, + ev_pointer, ev_integer, ev_float, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "popb.v", OP_POPB_V, false, + ev_pointer, ev_integer, ev_vector, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "popb.ent", OP_POPB_ENT, false, + ev_pointer, ev_integer, ev_entity, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "popb.fld", OP_POPB_FLD, false, + ev_pointer, ev_integer, ev_field, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "popb.fn", OP_POPB_FN, false, + ev_pointer, ev_integer, ev_func, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "popb.p", OP_POPB_P, false, + ev_pointer, ev_integer, ev_pointer, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "popb.q", OP_POPB_Q, false, + ev_pointer, ev_integer, ev_quat, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + {"", "popb.i", OP_POPB_I, false, + ev_pointer, ev_integer, ev_integer, + PROG_VERSION, + "*(%Ga + %Gb)", + }, + + {"", "popbi.s", OP_POPBI_S, false, + ev_pointer, ev_short, ev_string, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "popbi.f", OP_POPBI_F, false, + ev_pointer, ev_short, ev_float, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "popbi.v", OP_POPBI_V, false, + ev_pointer, ev_short, ev_vector, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "popbi.ent", OP_POPBI_ENT, false, + ev_pointer, ev_short, ev_entity, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "popbi.fld", OP_POPBI_FLD, false, + ev_pointer, ev_short, ev_field, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "popbi.fn", OP_POPBI_FN, false, + ev_pointer, ev_short, ev_func, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "popbi.p", OP_POPBI_P, false, + ev_pointer, ev_short, ev_pointer, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "popbi.q", OP_POPBI_Q, false, + ev_pointer, ev_short, ev_quat, + PROG_VERSION, + "*(%Ga + %sb)", + }, + {"", "popbi.i", OP_POPBI_I, false, + ev_pointer, ev_short, ev_integer, + PROG_VERSION, + "*(%Ga + %sb)", + }, + // end of table {0}, }; @@ -1192,11 +1470,16 @@ PR_Check_Opcodes (progs_t *pr) opcode_t *op; dstatement_t *st; int state_ok = 0; + int pushpop_ok = 0; pr_uint_t i; if (pr->globals.time && pr->globals.self && pr->fields.nextthink != -1 - && pr->fields.think != -1 && pr->fields.frame != -1) + && pr->fields.think != -1 && pr->fields.frame != -1) { state_ok = 1; + } + if (pr->globals.stack) { + pushpop_ok = 1; + } //FIXME need to decide if I really want to always do static bounds checking // the only problem is that it slows progs load a little, but it's the only @@ -1214,6 +1497,11 @@ PR_Check_Opcodes (progs_t *pr) PR_Error (pr, "PR_Check_Opcodes: %s used with missing fields " "or globals", op->opname); } + if ((strequal(op->name, "") || strequal(op->name, "")) + && !pushpop_ok) { + PR_Error (pr, "PR_Check_Opcodes: %s used with missing .stack " + "globals", op->opname); + } } } else { for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; @@ -1267,6 +1555,69 @@ PR_Check_Opcodes (progs_t *pr) check_global_size (pr, st, op, st->b, st->a); check_global_size (pr, st, op, st->b, st->c); break; + case OP_PUSHB_F: + case OP_PUSHB_S: + case OP_PUSHB_ENT: + case OP_PUSHB_FLD: + case OP_PUSHB_FN: + case OP_PUSHB_I: + case OP_PUSHB_P: + case OP_PUSHB_V: + case OP_PUSHB_Q: + case OP_PUSHBI_F: + case OP_PUSHBI_S: + case OP_PUSHBI_ENT: + case OP_PUSHBI_FLD: + case OP_PUSHBI_FN: + case OP_PUSHBI_I: + case OP_PUSHBI_P: + case OP_PUSHBI_V: + case OP_PUSHBI_Q: + // op->type_c is used for selecting the operator during + // compilation, but is invalid when running + check_global (pr, st, op, op->type_a, st->a, 1); + check_global (pr, st, op, op->type_b, st->b, 1); + check_global (pr, st, op, ev_invalid, st->c, 1); + break; + case OP_POP_F: + case OP_POP_FLD: + case OP_POP_ENT: + case OP_POP_S: + case OP_POP_FN: + case OP_POP_I: + case OP_POP_P: + case OP_POP_V: + case OP_POP_Q: + // don't want to check for denormal floats, otherwise + // OP_POP_* could use the defualt rule + check_global (pr, st, op, op->type_a, st->a, 0); + check_global (pr, st, op, ev_invalid, st->b, 1); + check_global (pr, st, op, ev_invalid, st->c, 1); + break; + case OP_POPB_F: + case OP_POPB_S: + case OP_POPB_ENT: + case OP_POPB_FLD: + case OP_POPB_FN: + case OP_POPB_I: + case OP_POPB_P: + case OP_POPB_V: + case OP_POPB_Q: + case OP_POPBI_F: + case OP_POPBI_S: + case OP_POPBI_ENT: + case OP_POPBI_FLD: + case OP_POPBI_FN: + case OP_POPBI_I: + case OP_POPBI_P: + case OP_POPBI_V: + case OP_POPBI_Q: + // op->type_c is used for selecting the operator during + // compilation, but is invalid when running + check_global (pr, st, op, op->type_a, st->a, 1); + check_global (pr, st, op, op->type_b, st->b, 1); + check_global (pr, st, op, ev_invalid, st->c, 1); + break; default: check_global (pr, st, op, op->type_a, st->a, 1); check_global (pr, st, op, op->type_b, st->b, diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 626540fda..c506c97ac 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -149,6 +149,13 @@ PR_ResolveGlobals (progs_t *pr) || (def = PR_FindGlobal (pr, "self"))) pr->globals.self = &G_INT (pr, def->ofs); } + if (!pr->globals.stack) { + if ((def = PR_FindGlobal (pr, ".stack")) + || (def = PR_FindGlobal (pr, "stack"))) + pr->globals.stack = &G_POINTER (pr, def->ofs); + // the stack is at the very end of the progs memory map + *pr->globals.stack = pr->globals_size; + } if (pr->fields.nextthink == -1) if ((def = PR_FindField (pr, "nextthink"))) pr->fields.nextthink = def->ofs; From 6252faa069ae7c5ae435dd48f4aff32e513d9b1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 13:25:32 +0900 Subject: [PATCH 0068/3664] Fix a size error in OP_LOAD_Q. C&P from OP_LOAD_V :/ --- libs/gamecode/pr_exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 65fa0cc35..56d5b0401 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -733,7 +733,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) "field in an edict"); } ed = PROG_TO_EDICT (pr, OPA.entity_var); - memcpy (&OPC, &ed->v[OPB.integer_var], 3 * sizeof (OPC)); + memcpy (&OPC, &ed->v[OPB.integer_var], 4 * sizeof (OPC)); break; case OP_LOADB_F: From 33cbc500e84c646e9d42b35d080efc2d14501cdb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 13:34:08 +0900 Subject: [PATCH 0069/3664] Fix a segfault when setting up the stack. Yup, putting {}s around even single statements under flow control (if, etc) is a good idea. Wonder if there's a gcc warning for that... --- libs/gamecode/pr_resolve.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index c506c97ac..ba82b48e8 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -151,10 +151,11 @@ PR_ResolveGlobals (progs_t *pr) } if (!pr->globals.stack) { if ((def = PR_FindGlobal (pr, ".stack")) - || (def = PR_FindGlobal (pr, "stack"))) + || (def = PR_FindGlobal (pr, "stack"))) { pr->globals.stack = &G_POINTER (pr, def->ofs); - // the stack is at the very end of the progs memory map - *pr->globals.stack = pr->globals_size; + // the stack is at the very end of the progs memory map + *pr->globals.stack = pr->globals_size; + } } if (pr->fields.nextthink == -1) if ((def = PR_FindField (pr, "nextthink"))) From f673ab9c3d408efec49863cd8b568c2b1483c7e3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 13:39:48 +0900 Subject: [PATCH 0070/3664] Fix misreporting of failed progs load. --- tools/qwaq/main.c | 2 +- tools/qwaq/qwaq.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index 570b6a3b7..15270d5e4 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -157,7 +157,7 @@ main (int argc, char **argv) name = argv[1]; if (!load_progs (name)) - Sys_Error ("couldn't load %s", "qwaq.dat"); + Sys_Error ("couldn't load %s", name); PR_PushFrame (&pr); if (argc > 2) diff --git a/tools/qwaq/qwaq.c b/tools/qwaq/qwaq.c index a6294887e..40576e868 100644 --- a/tools/qwaq/qwaq.c +++ b/tools/qwaq/qwaq.c @@ -169,7 +169,7 @@ main (int argc, const char **argv) name = argv[1]; if (!load_progs (name)) - Sys_Error ("couldn't load %s", "qwaq.dat"); + Sys_Error ("couldn't load %s", name); PR_PushFrame (&pr); if (argc > 2) From a096babb1f2743a78b4e5e1467dddd64b06f8821 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 21:36:29 +0900 Subject: [PATCH 0071/3664] Duplicate memory when creating a qfo from progs. Fixes some double-free bugs when linking after compiling. --- tools/qfcc/source/obj_file.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index db4bcc3df..cdd18f991 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -188,11 +188,13 @@ qfo_count_stuff (qfo_t *qfo, pr_info_t *pr) static void qfo_init_string_space (qfo_t *qfo, qfo_mspace_t *space, strpool_t *strings) { + size_t size = strings->size * sizeof (*strings->strings); strings->qfo_space = space - qfo->spaces; space->type = qfos_string; space->num_defs = 0; space->defs = 0; - space->d.strings = strings->strings; + space->d.strings = malloc (size); + memcpy (space->d.strings, strings->strings, size); space->data_size = strings->size; space->id = qfo_strings_space; } @@ -200,11 +202,13 @@ qfo_init_string_space (qfo_t *qfo, qfo_mspace_t *space, strpool_t *strings) static void qfo_init_code_space (qfo_t *qfo, qfo_mspace_t *space, codespace_t *code) { + size_t size = code->size * sizeof (*code->code); code->qfo_space = space - qfo->spaces; space->type = qfos_code; space->num_defs = 0; space->defs = 0; - space->d.code = code->code; + space->d.code = malloc (size); + memcpy (space->d.code, code->code, size); space->data_size = code->size; space->id = qfo_code_space; } @@ -213,11 +217,13 @@ static void qfo_init_data_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, qfo_mspace_t *space, defspace_t *data) { + size_t size = data->size * sizeof (*data->data); data->qfo_space = space - qfo->spaces; space->type = qfos_data; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = data->data; + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); space->data_size = data->size; } @@ -238,11 +244,13 @@ static void qfo_init_type_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, qfo_mspace_t *space, defspace_t *data) { + size_t size = data->size * sizeof (*data->data); data->qfo_space = space - qfo->spaces; space->type = qfos_type; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = data->data; + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); space->data_size = data->size; space->id = qfo_type_space; } From 3bc664811e9f13503c71451f336e7df94c4520f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Oct 2018 22:03:14 +0900 Subject: [PATCH 0072/3664] Fix lost error count tracking. --- tools/qfcc/source/diagnostic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index aa57ea19f..e2511a837 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -223,6 +223,8 @@ error (expr_t *e, const char *fmt, ...) { va_list args; + pr.error_count++; + report_function (e); va_start (args, fmt); From 3656cb966ca83da9c99d32b782d882f8302e74bd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 09:32:49 +0900 Subject: [PATCH 0073/3664] Fix some bison deprecation warnings. --- tools/qfcc/source/Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index 58011ea08..fb0c42782 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -59,12 +59,12 @@ qfprogs_DEPENDENCIES= $(QFCC_DEPS) BUILT_SOURCES=qc-parse.c qc-parse.h qc-lex.c qp-parse.c qp-parse.h qp-lex.c qc-parse.c: qc-parse.y - $(YACC) $(YFLAGS) -Dapi.prefix=qc_yy $< -o $@ -qc-lex.c: qc-lex.l + $(YACC) $(YFLAGS) -Dapi.prefix={qc_yy} $< -o $@ +qc-lex.c: qc-lex.l qc-parse.h $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqc_yy -o$@ $< qp-parse.c: qp-parse.y - $(YACC) $(YFLAGS) -Dapi.prefix=qp_yy $< -o $@ -qp-lex.c: qp-lex.l + $(YACC) $(YFLAGS) -Dapi.prefix={qp_yy} $< -o $@ +qp-lex.c: qp-lex.l qp-parse.h $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqp_yy -o$@ $< EXTRA_DIST=qc-lex.c qc-parse.c qc-parse.h qfpreqcc \ From 3bd9f96b07adab081c389a608e40ec4904b7ffc4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 13:57:59 +0900 Subject: [PATCH 0074/3664] Make internal error messages a little more helpful. They now include the file and line of the compiler as well. --- tools/qfcc/include/diagnostic.h | 6 ++++-- tools/qfcc/source/diagnostic.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index 6c28ccd41..1c0ee51bc 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -47,8 +47,10 @@ extern diagnostic_hook notice_hook; struct expr_s *error (struct expr_s *e, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); void -internal_error (struct expr_s *e, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3), noreturn)); +_internal_error (struct expr_s *e, const char *file, int line, + const char *fmt, ...) + __attribute__ ((format (printf, 4, 5), noreturn)); +#define internal_error(e, fmt...) _internal_error(e, __FILE__, __LINE__, fmt) struct expr_s *warning (struct expr_s *e, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); struct expr_s *notice (struct expr_s *e, const char *fmt, ...) diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index e2511a837..dbf71142c 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -200,7 +200,7 @@ warning (expr_t *e, const char *fmt, ...) } void -internal_error (expr_t *e, const char *fmt, ...) +_internal_error (expr_t *e, const char *file, int line, const char *fmt, ...) { va_list args; @@ -211,6 +211,7 @@ internal_error (expr_t *e, const char *fmt, ...) dstring_t *message = dstring_new (); format_message (message, "internal error", e, fmt, args); + dasprintf (message, " (%s:%d)", file, line); fprintf (stderr, "%s\n", message->str); dstring_delete (message); } From f8606ebab87d2b20fa442769265f739958d94ca5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 14:00:34 +0900 Subject: [PATCH 0075/3664] Fix a object file segfault when spaces have no data. ie, don't attempt to copy memory from a null pointer (just copy the null pointer). --- tools/qfcc/source/obj_file.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index cdd18f991..1ebd97f4b 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -193,8 +193,11 @@ qfo_init_string_space (qfo_t *qfo, qfo_mspace_t *space, strpool_t *strings) space->type = qfos_string; space->num_defs = 0; space->defs = 0; - space->d.strings = malloc (size); - memcpy (space->d.strings, strings->strings, size); + space->d.strings = 0; + if (strings->strings) { + space->d.strings = malloc (size); + memcpy (space->d.strings, strings->strings, size); + } space->data_size = strings->size; space->id = qfo_strings_space; } @@ -207,8 +210,11 @@ qfo_init_code_space (qfo_t *qfo, qfo_mspace_t *space, codespace_t *code) space->type = qfos_code; space->num_defs = 0; space->defs = 0; - space->d.code = malloc (size); - memcpy (space->d.code, code->code, size); + space->d.code = 0; + if (code->code) { + space->d.code = malloc (size); + memcpy (space->d.code, code->code, size); + } space->data_size = code->size; space->id = qfo_code_space; } @@ -222,8 +228,11 @@ qfo_init_data_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_data; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); + space->d.data = 0; + if (data->data) { + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); + } space->data_size = data->size; } @@ -249,8 +258,11 @@ qfo_init_type_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_type; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); + space->d.data = 0; + if (data->data) { + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); + } space->data_size = data->size; space->id = qfo_type_space; } From b7aa5bb8fe869e6df2b2c8ad29ad26e12cc017ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 14:33:26 +0900 Subject: [PATCH 0076/3664] Fix an oops messing up edict size. --- libs/gamecode/pr_load.c | 2 +- tools/qfcc/source/obj_file.c | 28 ++++++++-------------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index b00efd12e..721b26bd7 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -180,7 +180,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->pr_edict_size = max (1, progs.entityfields) * 4; // size of engine data pr->pr_edict_size += sizeof (edict_t); - pr->pr_edict_size = align_size (pr->progs_size); + pr->pr_edict_size = align_size (pr->pr_edict_size); pr->pr_edictareasize = pr->max_edicts * pr->pr_edict_size; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 1ebd97f4b..cdd18f991 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -193,11 +193,8 @@ qfo_init_string_space (qfo_t *qfo, qfo_mspace_t *space, strpool_t *strings) space->type = qfos_string; space->num_defs = 0; space->defs = 0; - space->d.strings = 0; - if (strings->strings) { - space->d.strings = malloc (size); - memcpy (space->d.strings, strings->strings, size); - } + space->d.strings = malloc (size); + memcpy (space->d.strings, strings->strings, size); space->data_size = strings->size; space->id = qfo_strings_space; } @@ -210,11 +207,8 @@ qfo_init_code_space (qfo_t *qfo, qfo_mspace_t *space, codespace_t *code) space->type = qfos_code; space->num_defs = 0; space->defs = 0; - space->d.code = 0; - if (code->code) { - space->d.code = malloc (size); - memcpy (space->d.code, code->code, size); - } + space->d.code = malloc (size); + memcpy (space->d.code, code->code, size); space->data_size = code->size; space->id = qfo_code_space; } @@ -228,11 +222,8 @@ qfo_init_data_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_data; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = 0; - if (data->data) { - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); - } + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); space->data_size = data->size; } @@ -258,11 +249,8 @@ qfo_init_type_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_type; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = 0; - if (data->data) { - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); - } + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); space->data_size = data->size; space->id = qfo_type_space; } From f58c2fef5aa61d71f35bfda19e26bf0118387577 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 14:33:55 +0900 Subject: [PATCH 0077/3664] Switch QF's quaterions from wxyz to xyzw. After messing with SIMD stuff for a little, I think I now understand why the industry went with xyzw instead of the mathematical wxyz. Anyway, this will make for less pain in the future (assuming I got everything). --- include/QF/math/quaternion.h | 4 +- include/QF/qtypes.h | 2 +- libs/models/iqm/model_iqm.c | 22 ++--- libs/util/mathlib.c | 104 +++++++++++------------ libs/util/test/test-mat3.c | 12 ++- libs/util/test/test-quat.c | 81 +++++++++--------- libs/video/renderer/glsl/glsl_bsp.c | 4 +- libs/video/renderer/glsl/quakeforge.glsl | 4 +- libs/video/renderer/r_iqm.c | 2 +- tools/qfcc/source/constfold.c | 6 +- tools/qfcc/source/expr.c | 61 ++++++++----- tools/qfcc/source/obj_file.c | 28 ++++-- tools/qfcc/source/type.c | 10 +-- tools/qfcc/source/value.c | 4 +- tools/qfcc/test/Makefile.am | 9 ++ tools/qfcc/test/quaternion.r | 73 ++++++++++++++++ tools/qfcc/test/test-harness.c | 5 +- 17 files changed, 272 insertions(+), 159 deletions(-) create mode 100644 tools/qfcc/test/quaternion.r diff --git a/include/QF/math/quaternion.h b/include/QF/math/quaternion.h index c6bec188b..84d7b64b4 100644 --- a/include/QF/math/quaternion.h +++ b/include/QF/math/quaternion.h @@ -58,10 +58,10 @@ extern const vec_t *const quat_origin; } while (0) #define QuatConj(a,b) \ do { \ - (b)[0] = (a)[0]; \ + (b)[0] = -(a)[0]; \ (b)[1] = -(a)[1]; \ (b)[2] = -(a)[2]; \ - (b)[3] = -(a)[3]; \ + (b)[3] = (a)[3]; \ } while (0) #define QuatAdd(a,b,c) \ do { \ diff --git a/include/QF/qtypes.h b/include/QF/qtypes.h index 05c93af59..e328ff2fc 100644 --- a/include/QF/qtypes.h +++ b/include/QF/qtypes.h @@ -76,8 +76,8 @@ typedef vec_t quat_t[4]; ///< A quaternion. typedef vec_t vec5_t[5]; typedef union { struct { - vec_t s; vec3_t v; + vec_t s; } sv; quat_t q; } Quat_t; diff --git a/libs/models/iqm/model_iqm.c b/libs/models/iqm/model_iqm.c index 6eabf7117..6d6e8de0b 100644 --- a/libs/models/iqm/model_iqm.c +++ b/libs/models/iqm/model_iqm.c @@ -118,7 +118,6 @@ get_joints (const iqmheader *hdr, byte *buffer) { iqmjoint *joint; uint32_t i, j; - float t; if (hdr->ofs_joints + hdr->num_joints * sizeof (iqmjoint) > hdr->filesize) return 0; @@ -135,10 +134,6 @@ get_joints (const iqmheader *hdr, byte *buffer) joint[i].translate[j] = LittleFloat (joint[i].translate[j]); for (j = 0; j < 4; j++) joint[i].rotate[j] = LittleFloat (joint[i].rotate[j]); - // iqm quaternions use xyzw but QF quaternions use wxyz - t = joint[i].rotate[3]; - memmove (&joint[i].rotate[1], &joint[i].rotate[0], 3 * sizeof (float)); - joint[i].rotate[0] = t; for (j = 0; j < 3; j++) joint[i].scale[j] = LittleFloat (joint[i].scale[j]); } @@ -442,19 +437,18 @@ load_iqm_anims (model_t *mod, const iqmheader *hdr, byte *buffer) if (p->mask & 0x004) translation[2] += *framedata++ * p->channelscale[2]; - // QF's quaternions are wxyz while IQM's quaternions are xyzw - rotation[1] = p->channeloffset[3]; + rotation[0] = p->channeloffset[3]; if (p->mask & 0x008) - rotation[1] += *framedata++ * p->channelscale[3]; - rotation[2] = p->channeloffset[4]; + rotation[0] += *framedata++ * p->channelscale[3]; + rotation[1] = p->channeloffset[4]; if (p->mask & 0x010) - rotation[2] += *framedata++ * p->channelscale[4]; - rotation[3] = p->channeloffset[5]; + rotation[1] += *framedata++ * p->channelscale[4]; + rotation[2] = p->channeloffset[5]; if (p->mask & 0x020) - rotation[3] += *framedata++ * p->channelscale[5]; - rotation[0] = p->channeloffset[6]; + rotation[2] += *framedata++ * p->channelscale[5]; + rotation[3] = p->channeloffset[6]; if (p->mask & 0x040) - rotation[0] += *framedata++ * p->channelscale[6]; + rotation[3] += *framedata++ * p->channelscale[6]; scale[0] = p->channeloffset[7]; if (p->mask & 0x080) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 9f1053025..a1e11f48b 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -248,11 +248,11 @@ QuatMult (const quat_t q1, const quat_t q2, quat_t out) vec_t s; vec3_t v; - s = q1[0] * q2[0] - DotProduct (q1 + 1, q2 + 1); - CrossProduct (q1 + 1, q2 + 1, v); - VectorMultAdd (v, q1[0], q2 + 1, v); - VectorMultAdd (v, q2[0], q1 + 1, out + 1); - out[0] = s; + s = q1[3] * q2[3] - DotProduct (q1, q2); + CrossProduct (q1, q2, v); + VectorMultAdd (v, q1[3], q2, v); + VectorMultAdd (v, q2[3], q1, out); + out[3] = s; } VISIBLE void @@ -261,12 +261,12 @@ QuatMultVec (const quat_t q, const vec3_t v, vec3_t out) vec_t s; vec3_t tv; - s = -DotProduct (q + 1, v); - CrossProduct (q + 1, v, tv); - VectorMultAdd (tv, q[0], v, tv); - CrossProduct (q + 1, tv, out); - VectorMultSub (out, s, q + 1, out); - VectorMultAdd (out, q[0], tv, out); + s = -DotProduct (q, v); + CrossProduct (q, v, tv); + VectorMultAdd (tv, q[3], v, tv); + CrossProduct (q, tv, out); + VectorMultSub (out, s, q, out); + VectorMultAdd (out, q[3], tv, out); } VISIBLE void @@ -288,19 +288,19 @@ QuatExp (const quat_t a, quat_t b) vec_t r; vec_t c, s; - VectorCopy (a + 1, n); + VectorCopy (a, n); th = VectorNormalize (n); - r = expf (a[0]); + r = expf (a[3]); c = cosf (th); s = sinf (th); - VectorScale (n, r * s, b + 1); - b[0] = r * c; + VectorScale (n, r * s, b); + b[3] = r * c; } VISIBLE void QuatToMatrix (const quat_t q, vec_t *m, int homogenous, int vertical) { - vec_t aa, ab, ac, ad, bb, bc, bd, cc, cd, dd; + vec_t xx, xy, xz, xw, yy, yz, yw, zz, zw, ww; vec_t *_m[4] = { m + (homogenous ? 0 : 0), m + (homogenous ? 4 : 3), @@ -308,28 +308,28 @@ QuatToMatrix (const quat_t q, vec_t *m, int homogenous, int vertical) m + (homogenous ? 12 : 9), }; - aa = q[0] * q[0]; - ab = q[0] * q[1]; - ac = q[0] * q[2]; - ad = q[0] * q[3]; + xx = q[0] * q[0]; + xy = q[0] * q[1]; + xz = q[0] * q[2]; + xw = q[0] * q[3]; - bb = q[1] * q[1]; - bc = q[1] * q[2]; - bd = q[1] * q[3]; + yy = q[1] * q[1]; + yz = q[1] * q[2]; + yw = q[1] * q[3]; - cc = q[2] * q[2]; - cd = q[2] * q[3]; + zz = q[2] * q[2]; + zw = q[2] * q[3]; - dd = q[3] * q[3]; + ww = q[3] * q[3]; if (vertical) { - VectorSet (aa + bb - cc - dd, 2 * (bc + ad), 2 * (bd - ac), _m[0]); - VectorSet (2 * (bc - ad), aa - bb + cc - dd, 2 * (cd + ab), _m[1]); - VectorSet (2 * (bd + ac), 2 * (cd - ab), aa - bb - cc + dd, _m[2]); + VectorSet (ww + xx - yy - zz, 2 * (xy + zw), 2 * (xz - yw), _m[0]); + VectorSet (2 * (xy - zw), ww - xx + yy - zz, 2 * (yz + xw), _m[1]); + VectorSet (2 * (xz + yw), 2 * (yz - xw), ww - xx - yy + zz, _m[2]); } else { - VectorSet (aa + bb - cc - dd, 2 * (bc - ad), 2 * (bd + ac), _m[0]); - VectorSet (2 * (bc + ad), aa - bb + cc - dd, 2 * (cd - ab), _m[1]); - VectorSet (2 * (bd - ac), 2 * (cd + ab), aa - bb - cc + dd, _m[2]); + VectorSet (ww + xx - yy - zz, 2 * (xy - zw), 2 * (xz + yw), _m[0]); + VectorSet (2 * (xy + zw), ww - xx + yy - zz, 2 * (yz - xw), _m[1]); + VectorSet (2 * (xz - yw), 2 * (yz + xw), ww - xx - yy + zz, _m[2]); } if (homogenous) { _m[0][3] = 0; @@ -555,10 +555,10 @@ AngleQuat (const vec3_t angles, quat_t q) sr = sin (alpha); cr = cos (alpha); - QuatSet (cy * cp * cr + sy * sp * sr, - cy * cp * sr - sy * sp * cr, - cy * sp * cr + sy * cp * sr, - sy * cp * cr - cy * sp * sr, + QuatSet (cy * cp * sr - sy * sp * cr, // x + cy * sp * cr + sy * cp * sr, // y + sy * cp * cr - cy * sp * sr, // z + cy * cp * cr + sy * sp * sr, // w q); } @@ -1112,29 +1112,29 @@ Mat3Decompose (const mat3_t mat, quat_t rot, vec3_t shear, vec3_t scale) t = 1 + row[0][0] + row[1][1] + row[2][2]; if (t >= 1e-5) { vec_t s = sqrt (t) * 2; - rot[0] = s / 4; - rot[1] = (row[2][1] - row[1][2]) / s; - rot[2] = (row[0][2] - row[2][0]) / s; - rot[3] = (row[1][0] - row[0][1]) / s; + rot[0] = (row[2][1] - row[1][2]) / s; + rot[1] = (row[0][2] - row[2][0]) / s; + rot[2] = (row[1][0] - row[0][1]) / s; + rot[3] = s / 4; } else { if (row[0][0] > row[1][1] && row[0][0] > row[2][2]) { vec_t s = sqrt (1 + row[0][0] - row[1][1] - row[2][2]) * 2; - rot[0] = (row[2][1] - row[1][2]) / s; - rot[1] = s / 4; - rot[2] = (row[1][0] + row[0][1]) / s; - rot[3] = (row[0][2] + row[2][0]) / s; + rot[0] = s / 4; + rot[1] = (row[1][0] + row[0][1]) / s; + rot[2] = (row[0][2] + row[2][0]) / s; + rot[3] = (row[2][1] - row[1][2]) / s; } else if (row[1][1] > row[2][2]) { vec_t s = sqrt (1 + row[1][1] - row[0][0] - row[2][2]) * 2; - rot[0] = (row[0][2] - row[2][0]) / s; - rot[1] = (row[1][0] + row[0][1]) / s; - rot[2] = s / 4; - rot[3] = (row[2][1] + row[1][2]) / s; + rot[0] = (row[1][0] + row[0][1]) / s; + rot[1] = s / 4; + rot[2] = (row[2][1] + row[1][2]) / s; + rot[3] = (row[0][2] - row[2][0]) / s; } else { vec_t s = sqrt (1 + row[2][2] - row[0][0] - row[1][1]) * 2; - rot[0] = (row[1][0] - row[0][1]) / s; - rot[1] = (row[0][2] + row[2][0]) / s; - rot[2] = (row[2][1] + row[1][2]) / s; - rot[3] = s / 4; + rot[0] = (row[0][2] + row[2][0]) / s; + rot[1] = (row[2][1] + row[1][2]) / s; + rot[2] = s / 4; + rot[3] = (row[1][0] - row[0][1]) / s; } } return 1; diff --git a/libs/util/test/test-mat3.c b/libs/util/test/test-mat3.c index 385200750..f852d281a 100644 --- a/libs/util/test/test-mat3.c +++ b/libs/util/test/test-mat3.c @@ -80,7 +80,8 @@ negate: return 1; fail: - printf ("\n\n(%g %g %g)\n", VectorExpand (angles)); + printf ("\ntest_angle\n"); + printf ("(%g %g %g)\n", VectorExpand (angles)); printf (" [%g %g %g %g]\n", QuatExpand (rotation)); printf (" [%g %g %g %g] [%g %g %g] [%g %g %g]\n", QuatExpand (r), VectorExpand (scale), VectorExpand (shear)); @@ -110,7 +111,8 @@ test_transform (const vec3_t angles, const vec3_t scale) return 1; fail: - printf ("\n\n(%g %g %g) (%g %g %g)\n", VectorExpand (angles), + printf ("\ntest_transform\n"); + printf ("(%g %g %g) (%g %g %g)\n", VectorExpand (angles), VectorExpand (scale)); printf (" (%g %g %g)\n", VectorExpand (x)); printf (" (%g %g %g)\n", VectorExpand (y)); @@ -146,7 +148,8 @@ test_transform2 (const vec3_t angles, const vec3_t scale) return 1; fail: - printf ("\n\n(%g %g %g) (%g %g %g) (%g %g %g)\n", + printf ("\ntest_transform2\n"); + printf ("(%g %g %g) (%g %g %g) (%g %g %g)\n", VectorExpand (angles), VectorExpand (scale), VectorExpand (v)); printf (" (%g %g %g)\n", VectorExpand (x)); printf (" (%g %g %g)\n", VectorExpand (y)); @@ -173,7 +176,8 @@ test_inverse (const vec3_t angles, const vec3_t scale) return 1; fail: - printf ("\n\n(%g %g %g) (%g %g %g)\n", + printf ("\ntest_inverse\n"); + printf ("(%g %g %g) (%g %g %g)\n", VectorExpand (angles), VectorExpand (scale)); printf (" [%g %g %g]\n [%g %g %g]\n [%g %g %g]\n\n", Mat3Expand (mat)); printf (" [%g %g %g]\n [%g %g %g]\n [%g %g %g]\n\n", Mat3Expand (inv)); diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index ce679771c..47539d144 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -9,7 +9,7 @@ static struct { quat_t q2; quat_t expect; } quat_mult_tests[] = { - {{4, 1, 2, 3}, {8, 5, 6, 7}, {-6, 24, 48, 48}}, + {{1, 2, 3, 4}, {5, 6, 7, 8}, {24, 48, 48, -6}}, }; #define num_quat_mult_tests (sizeof (quat_mult_tests) / sizeof (quat_mult_tests[0])) @@ -50,10 +50,10 @@ test_quat_mult(const quat_t q1, const quat_t q2, const quat_t expect) goto fail; return 1; fail: - printf ("%g %g %g %g\n", QuatExpand (q1)); - printf ("%g %g %g %g\n", QuatExpand (q2)); - printf ("%g %g %g %g\n", QuatExpand (r)); - printf ("%g %g %g %g\n", QuatExpand (expect)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (q1)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (q2)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (r)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (expect)); return 0; } @@ -64,12 +64,12 @@ rotate_vec (const quat_t r, const vec3_t v, vec3_t out) quat_t qv = {0, 0, 0, 0}; quat_t t; - VectorCopy (v, qv + 1); + VectorCopy (v, qv); QuatConj (r, t); QuatMult (qv, t, t); QuatMult (r, t, t); - VectorCopy (t + 1, out); + VectorCopy (t, out); } static int @@ -78,54 +78,55 @@ test_rotation (const vec3_t angles) int i; vec3_t forward, right, up; - quat_t quat, f, r, u, t; - quat_t qf = {0, 1, 0, 0}; - quat_t qr = {0, 0, -1, 0}; - quat_t qu = {0, 0, 0, 1}; + quat_t quat, conj, f, r, u, t; + quat_t qf = {1, 0, 0, 0}; + quat_t qr = {0, -1, 0, 0}; + quat_t qu = {0, 0, 1, 0}; AngleVectors (angles, forward, right, up); AngleQuat (angles, quat); + QuatConj (quat, conj); // rotate forward vector - QuatConj (quat, t); - QuatMult (qf, t, t); + QuatMult (qf, conj, t); QuatMult (quat, t, f); // rotate right vector - QuatConj (quat, t); - QuatMult (qr, t, t); + QuatMult (qr, conj, t); QuatMult (quat, t, r); // rotate up vector - QuatConj (quat, t); - QuatMult (qu, t, t); + QuatMult (qu, conj, t); QuatMult (quat, t, u); - if (!compare (f[0], 0)) + if (!compare (f[3], 0)) goto fail; for (i = 0; i < 3; i++) - if (!compare (forward[i], f[i + 1])) + if (!compare (forward[i], f[i])) goto fail; - if (!compare (r[0], 0)) + if (!compare (r[3], 0)) goto fail; for (i = 0; i < 3; i++) - if (!compare (right[i], r[i + 1])) + if (!compare (right[i], r[i])) goto fail; - if (!compare (u[0], 0)) + if (!compare (u[3], 0)) goto fail; for (i = 0; i < 3; i++) - if (!compare (up[i], u[i + 1])) + if (!compare (up[i], u[i])) goto fail; return 1; fail: - printf ("\n\n%g %g %g\n\n", angles[0], angles[1], angles[2]); - printf ("%g %g %g\n", forward[0], forward[1], forward[2]); - printf ("%g %g %g\n", right[0], right[1], right[2]); - printf ("%g %g %g\n\n", up[0], up[1], up[2]); + printf ("\ntest_rotation\n"); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand (angles)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (quat)); + printf ("%11.9g %11.9g %11.9g %11.9g\n\n", QuatExpand (conj)); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand (forward)); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand (right)); + printf ("%11.9g %11.9g %11.9g\n\n", VectorExpand (up)); - printf ("%g %g %g %g\n", f[0], f[1], f[2], f[3]); - printf ("%g %g %g %g\n", r[0], r[1], r[2], r[3]); - printf ("%g %g %g %g\n", u[0], u[1], u[2], u[3]); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (f)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (r)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (u)); return 0; } @@ -164,14 +165,15 @@ test_rotation2 (const vec3_t angles) goto fail; return 1; fail: - printf ("\n\n%g %g %g\n\n", angles[0], angles[1], angles[2]); - printf ("%g %g %g\n", forward[0], forward[1], forward[2]); - printf ("%g %g %g\n", right[0], right[1], right[2]); - printf ("%g %g %g\n\n", up[0], up[1], up[2]); + printf ("\ntest_rotation2\n"); + printf ("\n\n%11.9g %11.9g %11.9g\n\n", angles[0], angles[1], angles[2]); + printf ("%11.9g %11.9g %11.9g\n", forward[0], forward[1], forward[2]); + printf ("%11.9g %11.9g %11.9g\n", right[0], right[1], right[2]); + printf ("%11.9g %11.9g %11.9g\n\n", up[0], up[1], up[2]); - printf ("%g %g %g\n", f[0], f[1], f[2]); - printf ("%g %g %g\n", r[0], r[1], r[2]); - printf ("%g %g %g\n", u[0], u[1], u[2]); + printf ("%11.9g %11.9g %11.9g\n", f[0], f[1], f[2]); + printf ("%11.9g %11.9g %11.9g\n", r[0], r[1], r[2]); + printf ("%11.9g %11.9g %11.9g\n", u[0], u[1], u[2]); return 0; } @@ -192,8 +194,9 @@ test_rotation3 (const vec3_t angles) goto fail; return 1; fail: - printf ("%g %g %g\n", VectorExpand(a)); - printf ("%g %g %g\n", VectorExpand(b)); + printf ("\ntest_rotation3\n"); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand(a)); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand(b)); return 0; } diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index f212cbe7a..682ffb628 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -543,8 +543,8 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) msurface_t *surf; dstring_t *vertices; - QuatSet (sqrt(0.5), 0, 0, sqrt(0.5), sky_fix); // proper skies - QuatSet (1, 0, 0, 0, sky_rotation[0]); + QuatSet (0, 0, sqrt(0.5), sqrt(0.5), sky_fix); // proper skies + QuatSet (0, 0, 0, 1, sky_rotation[0]); QuatCopy (sky_rotation[0], sky_rotation[1]); QuatSet (0, 0, 0, 0, sky_velocity); QuatExp (sky_velocity, sky_velocity); diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index e346b31af..2a912fcb0 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -464,8 +464,8 @@ main (void) m += bonemats[int (vbones.z)] * vweights.z; m += bonemats[int (vbones.w)] * vweights.w; #if 0 - q0 = m[0].yzwx; //swizzle for conversion betwen QF and GL - qe = m[1].yzwx; //swizzle for conversion betwen QF and GL + q0 = m[0]; + qe = m[1]; sh = m[2].xyz; sc = m[3].xyz; diff --git a/libs/video/renderer/r_iqm.c b/libs/video/renderer/r_iqm.c index 4fa961228..224182a79 100644 --- a/libs/video/renderer/r_iqm.c +++ b/libs/video/renderer/r_iqm.c @@ -99,7 +99,7 @@ R_IQMBlendFrames (const iqm_t *iqm, int frame1, int frame2, float blend, } else { #if 0 for (i = 0; i < iqm->num_joints; i++) { - QuatSet (1, 0, 0, 0, frame[i].rt.q0.q); + QuatSet (0, 0, 0, 1, frame[i].rt.q0.q); QuatSet (0, 0, 0, 0, frame[i].rt.qe.q); QuatSet (0, 0, 0, 0, frame[i].shear); QuatSet (1, 1, 1, 0, frame[i].scale); diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 33c156cca..ee754f587 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -593,11 +593,11 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) return e; if (is_float_val (e1)) { - float_quat[0] = expr_float (e1); + QuatSet (0, 0, 0, expr_float (e1), float_quat); q2 = float_quat; q1 = expr_quaternion (e2); } else if (is_float_val (e2)) { - float_quat[0] = expr_float (e2); + QuatSet (0, 0, 0, expr_float (e2), float_quat); q2 = float_quat; q1 = expr_quaternion (e1); } else { @@ -627,7 +627,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) if (get_type (e2) == &type_quaternion) { QuatMult (q1, q2, q); } else { - QuatScale (q1, q2[0], q); + QuatScale (q1, q2[3], q); } e = new_quaternion_expr (q); break; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 0270ff58f..c8aebc5e0 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -163,35 +163,42 @@ convert_vector (expr_t *e) if (e->e.vector.type == &type_quaternion) { // guaranteed to have two or four elements if (e->e.vector.list->next->next) { - // four vals: w, x, y, z - expr_t *w = e->e.vector.list; - expr_t *x = w->next; + // four vals: x, y, z, w + expr_t *x = e->e.vector.list; expr_t *y = x->next; expr_t *z = y->next; - w = fold_constants (cast_expr (&type_float, w)); + expr_t *w = z->next; x = fold_constants (cast_expr (&type_float, x)); y = fold_constants (cast_expr (&type_float, y)); z = fold_constants (cast_expr (&type_float, z)); - if (is_constant (w) && is_constant (x) && is_constant (y) - && is_constant (z)) { - val[0] = expr_float(w); - val[1] = expr_float(x); - val[2] = expr_float(y); - val[3] = expr_float(z); + w = fold_constants (cast_expr (&type_float, w)); + if (is_constant (x) && is_constant (y) && is_constant (z) + && is_constant (w)) { + val[0] = expr_float(x); + val[1] = expr_float(y); + val[2] = expr_float(z); + val[3] = expr_float(w); return new_quaternion_expr (val); } } else { - // s, v - expr_t *s = e->e.vector.list; - expr_t *v = s->next; + // v, s + expr_t *v = e->e.vector.list; + expr_t *s = v->next; - s = fold_constants (cast_expr (&type_float, s)); v = convert_vector (v); - if (is_constant (s) && is_constant (v)) { - val[0] = expr_float (s); - memcpy (val + 1, expr_vector (v), 3 * sizeof (float)); + s = fold_constants (cast_expr (&type_float, s)); + if (is_constant (v) && is_constant (s)) { + memcpy (val, expr_vector (v), 3 * sizeof (float)); + val[3] = expr_float (s); return new_quaternion_expr (val); } + // Either v or is is not constant, so can't convert to a quaternion + // constant. + // Rebuild the list in case v or s is a new expression + s->next = 0; + v->next = s; + e->e.vector.list = v; + return e; } } internal_error (e, "bogus vector expression"); @@ -645,13 +652,23 @@ new_vector_list (expr_t *e) vec->e.vector.list = e; break; case 2: - // quaternion. first expression must be compatible with a float, - // the other must be a vector - if (!type_assignable (&type_float, get_type (e)) - || !type_assignable (&type_vector, get_type(e->next))) { + // quaternion. either float-ish, vector or vector, float-ish + if (type_assignable (&type_float, get_type (e)) + && type_assignable (&type_vector, get_type(e->next))) { + // float-ish, vector + // swap expressions + t = e; + e = e->next; + e->next = t; + t->next = 0; + } else if (type_assignable (&type_vector, get_type (e)) + && type_assignable (&type_float, get_type(e->next))) { + // vector, float-ish + // do nothing + } else { return error (t, "invalid types for vector elements"); } - // s, v + // v, s vec = new_expr (); vec->type = ex_vector; vec->e.vector.type = &type_quaternion; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index cdd18f991..1ebd97f4b 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -193,8 +193,11 @@ qfo_init_string_space (qfo_t *qfo, qfo_mspace_t *space, strpool_t *strings) space->type = qfos_string; space->num_defs = 0; space->defs = 0; - space->d.strings = malloc (size); - memcpy (space->d.strings, strings->strings, size); + space->d.strings = 0; + if (strings->strings) { + space->d.strings = malloc (size); + memcpy (space->d.strings, strings->strings, size); + } space->data_size = strings->size; space->id = qfo_strings_space; } @@ -207,8 +210,11 @@ qfo_init_code_space (qfo_t *qfo, qfo_mspace_t *space, codespace_t *code) space->type = qfos_code; space->num_defs = 0; space->defs = 0; - space->d.code = malloc (size); - memcpy (space->d.code, code->code, size); + space->d.code = 0; + if (code->code) { + space->d.code = malloc (size); + memcpy (space->d.code, code->code, size); + } space->data_size = code->size; space->id = qfo_code_space; } @@ -222,8 +228,11 @@ qfo_init_data_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_data; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); + space->d.data = 0; + if (data->data) { + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); + } space->data_size = data->size; } @@ -249,8 +258,11 @@ qfo_init_type_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_type; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); + space->d.data = 0; + if (data->data) { + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); + } space->data_size = data->size; space->id = qfo_type_space; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index bb1e3d7c2..c81222db0 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -843,8 +843,8 @@ init_types (void) {0, 0} }; static struct_def_t quaternion_struct[] = { - {"s", &type_float}, {"v", &type_vector}, + {"s", &type_float}, {0, 0} }; static struct_def_t type_encoding_struct[] = { @@ -882,16 +882,16 @@ init_types (void) type_quaternion.meta = ty_none; { symbol_t *sym; - sym = new_symbol_type ("w", &type_float); + sym = new_symbol_type ("x", &type_float); sym->s.offset = 0; symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("x", &type_float); + sym = new_symbol_type ("y", &type_float); sym->s.offset = 1; symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("y", &type_float); + sym = new_symbol_type ("z", &type_float); sym->s.offset = 2; symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("z", &type_float); + sym = new_symbol_type ("w", &type_float); sym->s.offset = 3; symtab_addsymbol (type_quaternion.t.symtab, sym); } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index ad84f25ae..f530f3b3a 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -316,9 +316,7 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab) return !memcmp (&imm1->i.pointer, &imm2->i.pointer, sizeof (imm1->i.pointer)); } else if (tab == &quaternion_imm_defs) { - return (VectorCompare (imm1->i.quaternion_val, - imm2->i.quaternion_val) - && imm1->i.quaternion_val[3] == imm2->i.quaternion_val[3]); + return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val); } else if (tab == &integer_imm_defs) { return imm1->i.integer_val == imm2->i.integer_val; } else { diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index b1a199fff..1ecb95fb4 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -37,6 +37,7 @@ test_progs_dat=\ infloop.dat \ modulo.dat \ paramret.dat \ + quaternion.dat \ return-ivar.dat \ sendv.dat \ state.dat \ @@ -130,6 +131,14 @@ paramret.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ include ./$(DEPDIR)/paramret.Qo +quaternion_dat_SOURCES=quaternion.r +quaternion_obj=$(quaternion_dat_SOURCES:.r=.qfo) +quaternion.dat$(EXEEXT): $(quaternion_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(quaternion_obj) +quaternion.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/quaternion.Qo + return_ivar_dat_SOURCES=return-ivar.r return_ivar_obj=$(return_ivar_dat_SOURCES:.r=.qfo) return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/quaternion.r b/tools/qfcc/test/quaternion.r new file mode 100644 index 000000000..f5f2c889a --- /dev/null +++ b/tools/qfcc/test/quaternion.r @@ -0,0 +1,73 @@ +void printf (string fmt, ...) = #0; + +int +test_format () +{ + int fail = 0; + quaternion q = '1 2 3 4'; + vector v = '-1 -2 -3'; + float s = -4; + + if (q.x != 1 || q.y != 2 || q.z != 3 || q.w != 4) { + printf ("q = '1 2 3 4' -> %q\n", q); + fail = 1; + } + if (q.v != '1 2 3' || q.s != 4) { + printf ("q = '1 2 3 4' -> %v, %g\n", q.v, q.s); + fail = 1; + } + q = nil; + if (q.x != 0 || q.y != 0 || q.z != 0 || q.w != 0) { + printf ("q = nil -> %q\n", q); + fail = 1; + } + if (q.v != '0 0 0' || q.s != 0) { + printf ("q = nil -> %v, %g\n", q.v, q.s); + fail = 1; + } + q = [1, [2, 3, 4]]; + if (q.x != 2 || q.y != 3 || q.z != 4 || q.w != 1) { + printf ("q = [1, [2, 3, 4]] -> %q\n", q); + fail = 1; + } + if (q.v != '2 3 4' || q.s != 1) { + printf ("q = [1, [2, 3, 4]] -> %v, %g\n", q.v, q.s); + fail = 1; + } + q = [[5, 6, 7], 8]; + if (q.x != 5 || q.y != 6 || q.z != 7 || q.w != 8) { + printf ("q = [[5, 6, 7], 8] -> %q\n", q); + fail = 1; + } + if (q.v != '5 6 7' || q.s != 8) { + printf ("q = [[5, 6, 7], 8] -> %v, %g\n", q.v, q.s); + fail = 1; + } +/* q = [s, v]; + if (q.x != v.x || q.y != v.y || q.z != v.z || q.w != s) { + printf ("q = [s, v] -> %q (%v)\n", q, v); + fail = 1; + } + if (q.v != v || q.s != s) { + printf ("q = [s, v] -> %v, %g (%v)\n", q.v, q.s, v); + fail = 1; + } + q = [v, s]; + if (q.x != v.x || q.y != v.y || q.z != v.z || q.w != s) { + printf ("q = [v, s] -> %q (%v %s)\n", q, v, s); + fail = 1; + } + if (q.v != v || q.s != s) { + printf ("q = [v, s] -> %v, %g (%v %s)\n", q.v, q.s, v, s); + fail = 1; + }*/ + return fail; +} + +int +main () +{ + int fail = 0; + fail |= test_format (); + return fail; +} diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index b364a7f0c..dcb251037 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -165,7 +165,10 @@ load_progs (const char *name) return 0; } pr.progs_name = name; - PR_LoadProgsFile (&pr, file, size, 16, 1024 * 1024); + pr.max_edicts = 16; + pr.zone_size = 1024 * 1024; + pr.stack_size = 64 * 1024; + PR_LoadProgsFile (&pr, file, size); Qclose (file); if (!PR_RunLoadFuncs (&pr)) PR_Error (&pr, "unable to load %s", pr.progs_name); From 71b3d30aa1b936c0d847bc1b831d73092eede928 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 14:50:55 +0900 Subject: [PATCH 0078/3664] Make the ice a little more informative. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/dot_expr.c | 2 +- tools/qfcc/source/statements.c | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 73d3f2399..f52930730 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -211,6 +211,7 @@ typedef struct expr_s { } expr_t; extern struct type_s *ev_types[]; +extern const char *expr_names[]; /** Report a type mismatch error. diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index accd8485a..43578a1c8 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -52,7 +52,7 @@ #include "qc-parse.h" #include "strpool.h" -static const char *expr_names[] = +const char *expr_names[] = { "error", "state", diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 7c0fb693f..f86ae8d47 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1017,7 +1017,8 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) if (e->type > ex_value) internal_error (e, "bad expression type"); if (!sfuncs[e->type]) - internal_error (e, "unexpected expression type"); + internal_error (e, "unexpected expression type; %s", + expr_names[e->type]); sblock = sfuncs[e->type] (sblock, e, op); return sblock; From 668896aa82bba9b46642825406002157ee876397 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 16:01:11 +0900 Subject: [PATCH 0079/3664] More diagnostic improvements. --- tools/qfcc/include/diagnostic.h | 11 +++++++---- tools/qfcc/source/diagnostic.c | 6 ++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index 1c0ee51bc..99a542762 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -55,10 +55,13 @@ struct expr_s *warning (struct expr_s *e, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); struct expr_s *notice (struct expr_s *e, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -void debug (struct expr_s *e, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); -void bug (struct expr_s *e, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); +void _debug (struct expr_s *e, const char *file, int line, + const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); +#define debug(e, fmt...) _debug(e, __FILE__, __LINE__, fmt) +void _bug (struct expr_s *e, const char *file, int line, const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); +#define bug(e, fmt...) _bug(e, __FILE__, __LINE__, fmt) //@} diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index dbf71142c..67a6644e0 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -118,7 +118,7 @@ _warning (expr_t *e, const char *fmt, va_list args) } void -debug (expr_t *e, const char *fmt, ...) +_debug (expr_t *e, const char *file, int line, const char *fmt, ...) { va_list args; @@ -131,6 +131,7 @@ debug (expr_t *e, const char *fmt, ...) dstring_t *message = dstring_new (); format_message (message, "debug", e, fmt, args); + dasprintf (message, " (%s:%d)", file, line); fprintf (stderr, "%s\n", message->str); dstring_delete (message); } @@ -138,7 +139,7 @@ debug (expr_t *e, const char *fmt, ...) } void -bug (expr_t *e, const char *fmt, ...) +_bug (expr_t *e, const char *file, int line, const char *fmt, ...) { va_list args; @@ -149,6 +150,7 @@ bug (expr_t *e, const char *fmt, ...) dstring_t *message = dstring_new (); format_message (message, "BUG", e, fmt, args); + dasprintf (message, " (%s:%d)", file, line); if (bug_hook) { bug_hook (message->str); } else { From f56d25cda61485d64b4709e179f4788ffa1a72f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 20:46:45 +0900 Subject: [PATCH 0080/3664] Don't double print messages. --- tools/qfcc/source/diagnostic.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 67a6644e0..da2f01969 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -113,7 +113,6 @@ _warning (expr_t *e, const char *fmt, va_list args) } else { fprintf (stderr, "%s\n", message->str); } - fprintf (stderr, "%s\n", message->str); dstring_delete (message); } @@ -183,7 +182,6 @@ notice (expr_t *e, const char *fmt, ...) } else { fprintf (stderr, "%s\n", message->str); } - fprintf (stderr, "%s\n", message->str); dstring_delete (message); } va_end (args); @@ -240,7 +238,6 @@ error (expr_t *e, const char *fmt, ...) } else { fprintf (stderr, "%s\n", message->str); } - fprintf (stderr, "%s\n", message->str); dstring_delete (message); } va_end (args); From e03dfa29b464dd53e81e548ddf3b6b97a22ebafa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 21:09:36 +0900 Subject: [PATCH 0081/3664] Clean up the module .ctor construction a little. --- tools/qfcc/source/class.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 52b67823d..21dc210c6 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1265,6 +1265,7 @@ class_finish_module (void) category_t **ca; def_t *symtab_def; symbol_t *module_sym; + expr_t *module_expr; pr_module_t *module; symbol_t *exec_class_sym; symbol_t *init_sym; @@ -1314,12 +1315,12 @@ class_finish_module (void) init_sym = new_symbol_type (".ctor", &type_function); init_sym = function_symbol (init_sym, 0, 1); + module_expr = address_expr (new_symbol_expr (module_sym), 0, 0); + init_expr = new_block_expr (); append_expr (init_expr, - build_function_call (new_symbol_expr (exec_class_sym), - exec_class_sym->type, - address_expr (new_symbol_expr (module_sym), - 0, 0))); + build_function_call (new_symbol_expr (exec_class_sym), + exec_class_sym->type, module_expr)); save_storage = current_storage; current_storage = sc_static; From 78e0a8dc522429509d36ddae862b781dea13da85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 22:05:17 +0900 Subject: [PATCH 0082/3664] Support assigning non-constant vector expressions. --- tools/qfcc/include/expr.h | 3 +- tools/qfcc/include/type.h | 3 + tools/qfcc/source/Makefile.am | 3 +- tools/qfcc/source/constfold.c | 2 +- tools/qfcc/source/dags.c | 2 +- tools/qfcc/source/def.c | 12 +- tools/qfcc/source/dot_expr.c | 2 +- tools/qfcc/source/expr.c | 222 +++--------------- tools/qfcc/source/expr_assign.c | 396 ++++++++++++++++++++++++++++++++ tools/qfcc/source/flow.c | 2 +- tools/qfcc/source/obj_file.c | 4 +- tools/qfcc/source/qfcc.c | 9 +- tools/qfcc/source/statements.c | 21 +- tools/qfcc/source/switch.c | 2 +- tools/qfcc/source/type.c | 20 ++ tools/qfcc/source/value.c | 82 ++++--- tools/qfcc/test/quaternion.r | 4 +- 17 files changed, 536 insertions(+), 253 deletions(-) create mode 100644 tools/qfcc/source/expr_assign.c diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index f52930730..466a11ec1 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -171,7 +171,8 @@ typedef struct { typedef struct ex_value_s { struct ex_value_s *next; struct daglabel_s *daglabel;///< dag label for this value - etype_t type; + struct type_s *type; + etype_t lltype; union { const char *string_val; ///< string constant float float_val; ///< float constant diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 2e1fa6c87..e886ac444 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -155,10 +155,13 @@ int is_enum (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); int is_float (const type_t *type) __attribute__((pure)); int is_scalar (const type_t *type) __attribute__((pure)); +int is_vector (const type_t *type) __attribute__((pure)); +int is_quaternion (const type_t *type) __attribute__((pure)); int is_math (const type_t *type) __attribute__((pure)); int is_pointer (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); +int is_func (const type_t *type) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); int type_size (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index fb0c42782..b0bf53fb7 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -41,7 +41,8 @@ bin_SCRIPTS= qfpreqcc common_src=\ class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \ diagnostic.c dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c emit.c \ - expr.c expr_binary.c flow.c function.c grab.c idstuff.c linker.c method.c \ + expr.c expr_assign.c expr_binary.c flow.c function.c grab.c idstuff.c \ + linker.c method.c \ obj_file.c \ obj_type.c opcodes.c options.c pragma.c qfcc.c reloc.c shared.c \ statements.c strpool.c struct.c switch.c symtab.c type.c value.c diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index ee754f587..f44cb2b68 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -140,7 +140,7 @@ convert_to_float (expr_t *e) switch (e->type) { case ex_value: - switch (e->e.value->type) { + switch (e->e.value->lltype) { case ev_integer: convert_int (e); return e; diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index fc87e31eb..0f07edbbf 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -356,7 +356,7 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) if (node != child && node != n) set_add (node->edges, n->number); if (op->op_type == op_value - && op->o.value->type == ev_pointer + && op->o.value->lltype == ev_pointer && op->o.value->v.pointer.def) def_visit_all (op->o.value->v.pointer.def, 1, dagnode_set_edges_visit, n); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index c16aa9912..346ee9b9d 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -350,7 +350,7 @@ init_elements (struct def_s *def, expr_t *eles) reloc_def_op (c->e.labelref.label, &loc); continue; } else if (c->type == ex_value) { - if (c->e.value->type == ev_integer + if (c->e.value->lltype == ev_integer && elements[i].type->type == ev_float) convert_int (c); if (get_type (c) != elements[i].type) { @@ -372,7 +372,7 @@ init_elements (struct def_s *def, expr_t *eles) } else { if (c->type != ex_value) internal_error (c, "bogus expression type in init_elements()"); - if (c->e.value->type == ev_string) { + if (c->e.value->lltype == ev_string) { EMIT_STRING (def->space, g->string_var, c->e.value->v.string_val); } else { @@ -407,7 +407,7 @@ init_vector_components (symbol_t *vector_sym, int is_field) expr = sym->s.expr; if (is_field) { if (expr->type != ex_value - || expr->e.value->type != ev_field) { + || expr->e.value->lltype != ev_field) { error (0, "%s redefined", name); sym = 0; } else { @@ -574,8 +574,8 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space, error (0, "non-constant initializier"); return; } - if (init->e.value->type == ev_pointer - || init->e.value->type == ev_field) { + if (init->e.value->lltype == ev_pointer + || init->e.value->lltype == ev_field) { // FIXME offset pointers D_INT (sym->s.def) = init->e.value->v.pointer.val; if (init->e.value->v.pointer.def) @@ -584,7 +584,7 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space, ex_value_t *v = init->e.value; if (is_scalar (sym->type)) v = convert_value (v, sym->type); - if (v->type == ev_string) { + if (v->lltype == ev_string) { EMIT_STRING (sym->s.def->space, D_STRING (sym->s.def), v->v.string_val); } else { diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 43578a1c8..191c8208d 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -386,7 +386,7 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) type_t *type; const char *label = "?!?"; - switch (e->e.value->type) { + switch (e->e.value->lltype) { case ev_string: label = va ("\\\"%s\\\"", quote_string (e->e.value->v.string_val)); break; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c8aebc5e0..a4fbf76ac 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -159,6 +159,13 @@ convert_vector (expr_t *e) val[2] = expr_float(z); return new_vector_expr (val); } + // at least one of x, y, z is not constant, so rebuild the + // list incase any of them are new expressions + z->next = 0; + y->next = z; + x->next = y; + e->e.vector.list = x; + return e; } if (e->e.vector.type == &type_quaternion) { // guaranteed to have two or four elements @@ -180,6 +187,14 @@ convert_vector (expr_t *e) val[3] = expr_float(w); return new_quaternion_expr (val); } + // at least one of x, y, z, w is not constant, so rebuild the + // list incase any of them are new expressions + w->next = 0; + z->next = w; + y->next = z; + x->next = y; + e->e.vector.list = x; + return e; } else { // v, s expr_t *v = e->e.vector.list; @@ -192,7 +207,7 @@ convert_vector (expr_t *e) val[3] = expr_float (s); return new_quaternion_expr (val); } - // Either v or is is not constant, so can't convert to a quaternion + // Either v or s is not constant, so can't convert to a quaternion // constant. // Rebuild the list in case v or s is a new expression s->next = 0; @@ -233,17 +248,7 @@ get_type (expr_t *e) case ex_temp: return e->e.temp.type; case ex_value: - if (e->e.value->type == ev_func) - return e->e.value->v.func_val.type; - if (e->e.value->type == ev_pointer) - return pointer_type (e->e.value->v.pointer.type); - if (e->e.value->type == ev_field) - return field_type (e->e.value->v.pointer.type); - if (e->e.value->type == ev_integer - && options.code.progsversion == PROG_ID_VERSION) { - convert_int (e); - } - return ev_types[e->e.value->type]; + return e->e.value->type; case ex_vector: return e->e.vector.type; } @@ -801,7 +806,7 @@ is_string_val (expr_t *e) { if (e->type == ex_nil) return 1; - if (e->type == ex_value && e->e.value->type == ev_string) + if (e->type == ex_value && e->e.value->lltype == ev_string) return 1; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_string) @@ -814,7 +819,7 @@ expr_string (expr_t *e) { if (e->type == ex_nil) return 0; - if (e->type == ex_value && e->e.value->type == ev_string) + if (e->type == ex_value && e->e.value->lltype == ev_string) return e->e.value->v.string_val; internal_error (e, "not a string constant"); } @@ -824,7 +829,7 @@ is_float_val (expr_t *e) { if (e->type == ex_nil) return 1; - if (e->type == ex_value && e->e.value->type == ev_float) + if (e->type == ex_value && e->e.value->lltype == ev_float) return 1; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_float) @@ -837,7 +842,7 @@ expr_float (expr_t *e) { if (e->type == ex_nil) return 0; - if (e->type == ex_value && e->e.value->type == ev_float) + if (e->type == ex_value && e->e.value->lltype == ev_float) return e->e.value->v.float_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_float) @@ -854,7 +859,7 @@ is_vector_val (expr_t *e) { if (e->type == ex_nil) return 1; - if (e->type == ex_value && e->e.value->type == ev_vector) + if (e->type == ex_value && e->e.value->lltype == ev_vector) return 1; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_vector) @@ -867,7 +872,7 @@ expr_vector (expr_t *e) { if (e->type == ex_nil) return vec3_origin; - if (e->type == ex_value && e->e.value->type == ev_vector) + if (e->type == ex_value && e->e.value->lltype == ev_vector) return e->e.value->v.vector_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_vector) @@ -884,7 +889,7 @@ is_quaternion_val (expr_t *e) { if (e->type == ex_nil) return 1; - if (e->type == ex_value && e->e.value->type == ev_quat) + if (e->type == ex_value && e->e.value->lltype == ev_quat) return 1; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_quat) @@ -897,7 +902,7 @@ expr_quaternion (expr_t *e) { if (e->type == ex_nil) return quat_origin; - if (e->type == ex_value && e->e.value->type == ev_quat) + if (e->type == ex_value && e->e.value->lltype == ev_quat) return e->e.value->v.quaternion_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_quat) @@ -914,7 +919,7 @@ is_integer_val (expr_t *e) { if (e->type == ex_nil) return 1; - if (e->type == ex_value && e->e.value->type == ev_integer) + if (e->type == ex_value && e->e.value->lltype == ev_integer) return 1; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && (e->e.symbol->type->type == ev_integer @@ -928,7 +933,7 @@ expr_integer (expr_t *e) { if (e->type == ex_nil) return 0; - if (e->type == ex_value && e->e.value->type == ev_integer) + if (e->type == ex_value && e->e.value->lltype == ev_integer) return e->e.value->v.integer_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && (e->e.symbol->type->type == ev_integer @@ -946,7 +951,7 @@ expr_uinteger (expr_t *e) { if (e->type == ex_nil) return 0; - if (e->type == ex_value && e->e.value->type == ev_uinteger) + if (e->type == ex_value && e->e.value->lltype == ev_uinteger) return e->e.value->v.uinteger_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_uinteger) @@ -963,7 +968,7 @@ is_short_val (expr_t *e) { if (e->type == ex_nil) return 1; - if (e->type == ex_value && e->e.value->type == ev_short) + if (e->type == ex_value && e->e.value->lltype == ev_short) return 1; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_short) @@ -976,7 +981,7 @@ expr_short (expr_t *e) { if (e->type == ex_nil) return 0; - if (e->type == ex_value && e->e.value->type == ev_short) + if (e->type == ex_value && e->e.value->lltype == ev_short) return e->e.value->v.short_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && e->e.symbol->type->type == ev_short) @@ -1172,7 +1177,8 @@ field_expr (expr_t *e1, expr_t *e2) } def = sym->s.def; e2 = new_field_expr (0, field->type, def); - } else if (e2->type != ex_value || e2->e.value->type != ev_field) { + } else if (e2->type != ex_value + || e2->e.value->lltype != ev_field) { internal_error (e2, "unexpected field exression"); } e2->e.value = new_field_val (e2->e.value->v.pointer.val + field->s.offset, field->type, e2->e.value->v.pointer.def); @@ -2215,7 +2221,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) if (e2) { if (e2->type == ex_error) return e2; - if (e->type == ex_value && e->e.value->type == ev_pointer + if (e->type == ex_value && e->e.value->lltype == ev_pointer && is_short_val (e2)) { e->e.value = new_pointer_val (e->e.value->v.pointer.val + expr_short (e2), t, e->e.value->v.pointer.def); } else { @@ -2479,24 +2485,6 @@ think_expr (symbol_t *think_sym) return new_symbol_expr (think_sym); } -static __attribute__((pure)) int -is_indirect (expr_t *e) -{ - if (e->type == ex_block && e->e.block.result) - return is_indirect (e->e.block.result); - if (e->type == ex_expr && e->e.expr.op == '.') - return 1; - if (!(e->type == ex_uexpr && e->e.expr.op == '.')) - return 0; - e = e->e.expr.e1; - if (e->type != ex_value || e->e.value->type != ev_pointer - || !(POINTER_VAL (e->e.value->v.pointer) >= 0 - && POINTER_VAL (e->e.value->v.pointer) < 65536)) { - return 1; - } - return 0; -} - static inline __attribute__((pure)) int is_lvalue (expr_t *e) { @@ -2527,150 +2515,6 @@ is_lvalue (expr_t *e) return 0; } -expr_t * -assign_expr (expr_t *e1, expr_t *e2) -{ - int op = '='; - type_t *t1, *t2, *type; - expr_t *e; - - convert_name (e1); - convert_name (e2); - e2 = convert_vector (e2); - - if (e1->type == ex_error) - return e1; - if (e2->type == ex_error) - return e2; - - e1 = fold_constants (e1); - e2 = fold_constants (e2); - - if (options.traditional) { - if (e2->type == ex_expr && !e2->paren - && (e2->e.expr.op == AND || e2->e.expr.op == OR)) { - notice (e2, "precedence of `%s' and `%s' inverted for " - "traditional code", get_op_string (op), - get_op_string (e2->e.expr.op)); - e1 = assign_expr (e1, e2->e.expr.e1); - e1->paren = 1; - return binary_expr (e2->e.expr.op, e1, e2->e.expr.e2); - } - } - - if (!is_lvalue (e1)) { - if (options.traditional) - warning (e1, "invalid lvalue in assignment"); - else - return error (e1, "invalid lvalue in assignment"); - } - t1 = get_type (e1); - t2 = get_type (e2); - if (!t1 || !t2) - internal_error (e1, 0); - //XXX func = func ??? - if (t1->type == ev_pointer && is_array (t2)) { - e2 = address_expr (e2, 0, t2->t.fldptr.type); - t2 = get_type (e2); - } - if (e2->type == ex_bool) - e2 = convert_from_bool (e2, t1); - - if (t1->type != ev_void && e2->type == ex_nil) { - t2 = t1; - convert_nil (e2, t2); - } - - e2->rvalue = 1; - - if (!type_assignable (t1, t2)) { - if (options.traditional) { - if (t1->type == ev_func && t2->type == ev_func) { - warning (e1, "assignment between disparate function types"); - } else if (t1->type == ev_float && t2->type == ev_vector) { - warning (e1, "assignment of vector to float"); - e2 = field_expr (e2, new_name_expr ("x")); - } else if (t1->type == ev_vector && t2->type == ev_float) { - warning (e1, "assignment of float to vector"); - e1 = field_expr (e1, new_name_expr ("x")); - } else { - return type_mismatch (e1, e2, op); - } - } else { - return type_mismatch (e1, e2, op); - } - } - type = t1; - if (is_indirect (e1) && is_indirect (e2)) { - if (is_struct (get_type (e2))) { - e1 = address_expr (e1, 0, 0); - e2 = address_expr (e2, 0, 0); - e = new_move_expr (e1, e2, t2, 1); - } else { - expr_t *temp = new_temp_def_expr (t1); - - e = new_block_expr (); - append_expr (e, assign_expr (temp, e2)); - append_expr (e, assign_expr (e1, temp)); - e->e.block.result = temp; - } - return e; - } else if (is_indirect (e1)) { - if (is_struct (get_type (e1))) { - e1 = address_expr (e1, 0, 0); - e2 = address_expr (e2, 0, 0); - return new_move_expr (e1, e2, t1, 1); - } - if (e1->type == ex_expr) { - if (get_type (e1->e.expr.e1) == &type_entity) { - type = e1->e.expr.type; - e1->e.expr.type = pointer_type (type); - e1->e.expr.op = '&'; - } - op = PAS; - } else { - e = e1->e.expr.e1; - if ((e->type != ex_value || e->e.value->type != ev_pointer) - || !(POINTER_VAL (e->e.value->v.pointer) > 0 - && POINTER_VAL (e->e.value->v.pointer) < 65536)) { - e1 = e; - op = PAS; - } - } - } else if (is_indirect (e2)) { - if (is_struct (get_type (e1))) { - e1 = address_expr (e1, 0, 0); - e2 = address_expr (e2, 0, 0); - e2->rvalue = 1; - return new_move_expr (e1, e2, t2, 1); - } - if (e2->type == ex_uexpr) { - e = e2->e.expr.e1; - if ((e->type != ex_value || e->e.value->type != ev_pointer) - || !(POINTER_VAL (e->e.value->v.pointer) > 0 - && POINTER_VAL (e->e.value->v.pointer) < 65536)) { - if (e->type == ex_expr && e->e.expr.op == '&' - && e->e.expr.type->type == ev_pointer - && !is_constant (e)) { - e2 = e; - e2->e.expr.op = '.'; - e2->e.expr.type = t2; - e2->rvalue = 1; - } - } - } - } - if (is_struct (get_type (e1))) { - return new_move_expr (e1, e2, get_type (e1), 0); - } - if (!type) - internal_error (e1, 0); - - e = new_binary_expr (op, e1, e2); - e->e.expr.type = type; - return e; -} - expr_t * cast_expr (type_t *type, expr_t *e) { diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c new file mode 100644 index 000000000..0a1a82b6d --- /dev/null +++ b/tools/qfcc/source/expr_assign.c @@ -0,0 +1,396 @@ +/* + expr_assign.c + + assignment expression construction and manipulations + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2001/06/15 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/alloc.h" +#include "QF/dstring.h" +#include "QF/mathlib.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "qfcc.h" +#include "class.h" +#include "def.h" +#include "defspace.h" +#include "diagnostic.h" +#include "emit.h" +#include "expr.h" +#include "function.h" +#include "idstuff.h" +#include "method.h" +#include "options.h" +#include "reloc.h" +#include "shared.h" +#include "strpool.h" +#include "struct.h" +#include "symtab.h" +#include "type.h" +#include "value.h" +#include "qc-parse.h" + +static expr_t * +check_assign_logic_precedence (expr_t *dst, expr_t *src) +{ + if (src->type == ex_expr && !src->paren && is_logic (src->e.expr.op)) { + // traditional QuakeC gives = higher precedence than && and || + expr_t *assignment; + notice (src, "precedence of `=' and `%s' inverted for " + "traditional code", get_op_string (src->e.expr.op)); + // change {a = (b logic c)} to {(a = b) logic c} + assignment = assign_expr (dst, src->e.expr.e1); + assignment->paren = 1; // protect assignment from binary_expr + return binary_expr (src->e.expr.op, assignment, src->e.expr.e2); + } + return 0; +} + +static expr_t * +check_valid_lvalue (expr_t *expr) +{ + switch (expr->type) { + case ex_symbol: + switch (expr->e.symbol->sy_type) { + case sy_var: + return 0; + case sy_const: + break; + case sy_type: + break; + case sy_expr: + break; + case sy_func: + break; + case sy_class: + break; + } + break; + case ex_temp: + return 0; + case ex_expr: + if (expr->e.expr.op == '.') { + return 0; + } + break; + case ex_uexpr: + if (expr->e.expr.op == '.') { + return 0; + } + if (expr->e.expr.op == 'A') { + return check_valid_lvalue (expr->e.expr.e1); + } + break; + case ex_state: + case ex_bool: + case ex_label: + case ex_labelref: + case ex_block: + case ex_vector: + case ex_nil: + case ex_value: + case ex_error: + break; + } + if (options.traditional) { + warning (expr, "invalid lvalue in assignment"); + return 0; + } + return error (expr, "invalid lvalue in assignment"); +} + +static expr_t * +check_types_compatible (expr_t *dst, expr_t *src) +{ + type_t *dst_type = get_type (dst); + type_t *src_type = get_type (src); + + if (type_assignable (dst_type, src_type)) { + return 0; + } + // traditional qcc is a little sloppy + if (!options.traditional) { + return type_mismatch (dst, src, '='); + } + if (is_func (dst_type) && is_func (src_type)) { + warning (dst, "assignment between disparate function types"); + return 0; + } + if (is_float (dst_type) && is_vector (src_type)) { + warning (dst, "assignment of vector to float"); + src = field_expr (src, new_name_expr ("x")); + return assign_expr (dst, src); + } + if (is_vector (dst_type) && is_float (src_type)) { + warning (dst, "assignment of float to vector"); + dst = field_expr (dst, new_name_expr ("x")); + return assign_expr (dst, src); + } + return type_mismatch (dst, src, '='); +} + +static expr_t * +assign_vector_expr (expr_t *dst, expr_t *src) +{ + expr_t *dx, *sx; + expr_t *dy, *sy; + expr_t *dz, *sz; + expr_t *dw, *sw; + expr_t *ds, *ss; + expr_t *dv, *sv; + expr_t *block; + + if (src->type == ex_vector) { + src = convert_vector (src); + if (src->type != ex_vector) { + // src was constant and thus converted + return assign_expr (dst, src); + } + } + if (src->type == ex_vector && dst->type != ex_vector) { + if (src->e.vector.type == &type_vector) { + // guaranteed to have three elements + sx = src->e.vector.list; + sy = sx->next; + sz = sy->next; + dx = field_expr (dst, new_name_expr ("x")); + dy = field_expr (dst, new_name_expr ("y")); + dz = field_expr (dst, new_name_expr ("z")); + block = new_block_expr (); + append_expr (block, assign_expr (dx, sx)); + append_expr (block, assign_expr (dy, sy)); + append_expr (block, assign_expr (dz, sz)); + block->e.block.result = dst; + return block; + } + if (src->e.vector.type == &type_quaternion) { + // guaranteed to have two or four elements + if (src->e.vector.list->next->next) { + // four vals: x, y, z, w + sx = src->e.vector.list; + sy = sx->next; + sz = sy->next; + sw = sz->next; + dx = field_expr (dst, new_name_expr ("x")); + dy = field_expr (dst, new_name_expr ("y")); + dz = field_expr (dst, new_name_expr ("z")); + dw = field_expr (dst, new_name_expr ("w")); + block = new_block_expr (); + append_expr (block, assign_expr (dx, sx)); + append_expr (block, assign_expr (dy, sy)); + append_expr (block, assign_expr (dz, sz)); + append_expr (block, assign_expr (dw, sw)); + block->e.block.result = dst; + return block; + } else { + // v, s + sv = src->e.vector.list; + ss = sv->next; + dv = field_expr (dst, new_name_expr ("v")); + ds = field_expr (dst, new_name_expr ("s")); + block = new_block_expr (); + append_expr (block, assign_expr (dv, sv)); + append_expr (block, assign_expr (ds, ss)); + block->e.block.result = dst; + return block; + } + } + internal_error (src, "bogus vector expression"); + } + return 0; +} + +static __attribute__((pure)) int +is_const_ptr (expr_t *e) +{ + if ((e->type != ex_value || e->e.value->lltype != ev_pointer) + || !(POINTER_VAL (e->e.value->v.pointer) > 0 + && POINTER_VAL (e->e.value->v.pointer) < 65536)) { + return 1; + } + return 0; +} + +static __attribute__((pure)) int +is_indirect (expr_t *e) +{ + if (e->type == ex_block && e->e.block.result) + return is_indirect (e->e.block.result); + if (e->type == ex_expr && e->e.expr.op == '.') + return 1; + if (!(e->type == ex_uexpr && e->e.expr.op == '.')) + return 0; + return is_const_ptr (e->e.expr.e1); +} + +expr_t * +aassign_expr (expr_t *dst, expr_t *src); +expr_t * +assign_expr (expr_t *dst, expr_t *src) +{ + int op = '='; + expr_t *expr; + type_t *dst_type, *src_type; + + convert_name (dst); + convert_name (src); + + if (dst->type == ex_error) { + return dst; + } + if (src->type == ex_error) { + return src; + } + + if (options.traditional + && (expr = check_assign_logic_precedence (dst, src))) { + return expr; + } + + dst = fold_constants (dst); + src = fold_constants (src); + + if ((expr = check_valid_lvalue (dst))) { + return expr; + } + + dst_type = get_type (dst); + src_type = get_type (src); + if (!dst_type) { + internal_error (dst, "dst_type broke in assign_expr"); + } + if (!src_type) { + internal_error (src, "src_type broke in assign_expr"); + } + + if (is_pointer (dst_type) && is_array (src_type)) { + // assigning an array to a pointer is the same as taking the address of + // the array but using the type of the array elements + src = address_expr (src, 0, src_type->t.fldptr.type); + src_type = get_type (src); + } + if (src->type == ex_bool) { + src = convert_from_bool (src, dst_type); + if (src->type == ex_error) { + return src; + } + src_type = get_type (src); + } + if (!is_void (dst_type) && src->type == ex_nil) { + // nil is a type-agnostic 0 + // FIXME: assignment to compound types? error or memset? + src_type = dst_type; + convert_nil (src, src_type); + } + + if ((expr = check_types_compatible (dst, src))) { + // expr might be a valid expression, but if so, check_types_compatible + // will take care of everything + return expr; + } + + if ((expr = assign_vector_expr (dst, src))) { + return expr; + } + + if (is_indirect (dst) && is_indirect (src)) { + debug (dst, "here"); + if (is_struct (src_type)) { + dst = address_expr (dst, 0, 0); + src = address_expr (src, 0, 0); + expr = new_move_expr (dst, src, src_type, 1); + } else { + expr_t *temp = new_temp_def_expr (dst_type); + + expr = new_block_expr (); + append_expr (expr, assign_expr (temp, src)); + append_expr (expr, assign_expr (dst, temp)); + expr->e.block.result = temp; + } + return expr; + } else if (is_indirect (dst)) { + debug (dst, "here"); + if (is_struct (dst_type)) { + dst = address_expr (dst, 0, 0); + src = address_expr (src, 0, 0); + return new_move_expr (dst, src, dst_type, 1); + } + if (dst->type == ex_expr) { + if (get_type (dst->e.expr.e1) == &type_entity) { + dst_type = dst->e.expr.type; + dst->e.expr.type = pointer_type (dst_type); + dst->e.expr.op = '&'; + } + op = PAS; + } else { + if (is_const_ptr (dst->e.expr.e1)) { + dst = dst->e.expr.e1; + op = PAS; + } + } + } else if (is_indirect (src)) { + debug (dst, "here"); + if (is_struct (dst_type)) { + dst = address_expr (dst, 0, 0); + src = address_expr (src, 0, 0); + src->rvalue = 1; + return new_move_expr (dst, src, src_type, 1); + } + if (src->type == ex_uexpr) { + expr = src->e.expr.e1; + if (is_const_ptr (expr)) { + if (expr->type == ex_expr && expr->e.expr.op == '&' + && expr->e.expr.type->type == ev_pointer + && !is_constant (expr)) { + src = expr; + src->e.expr.op = '.'; + src->e.expr.type = src_type; + src->rvalue = 1; + } + } + } + } + + if (is_struct (dst_type)) { + return new_move_expr (dst, src, dst_type, 0); + } + + expr = new_binary_expr (op, dst, src); + expr->e.expr.type = dst_type; + return expr; +} diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 4170c2970..cd26be5b9 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -830,7 +830,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } else if (!strcmp (s->opcode, "")) { flow_add_op_var (use, s->opc); if (s->opc->op_type == op_value - && s->opc->o.value->type == ev_pointer + && s->opc->o.value->lltype == ev_pointer && s->opc->o.value->v.pointer.def) { operand_t *op; ex_pointer_t *ptr = &s->opc->o.value->v.pointer; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 1ebd97f4b..428b733dc 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -428,8 +428,10 @@ qfo_write (qfo_t *qfo, const char *filename) QFile *file; file = Qopen (filename, options.gzip ? "wbz9" : "wb"); - if (!file) + if (!file) { + perror (va ("failed to open %s for writing", filename)); return -1; + } size = sizeof (qfo_header_t); size += sizeof (qfo_space_t) * qfo->num_spaces; diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index cf6d1257f..0da2caf88 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -396,9 +396,12 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) qfo_t *qfo; class_finish_module (); - qfo = qfo_from_progs (&pr); - err = qfo_write (qfo, obj); - qfo_delete (qfo); + err = pr.error_count; + if (!err) { + qfo = qfo_from_progs (&pr); + err = qfo_write (qfo, obj); + qfo_delete (qfo); + } } return err; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index f86ae8d47..fae48f153 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -83,7 +83,7 @@ operand_string (operand_t *op) case op_def: return op->o.def->name; case op_value: - switch (op->o.value->type) { + switch (op->o.value->lltype) { case ev_string: return va ("\"%s\"", quote_string (op->o.value->v.string_val)); @@ -154,7 +154,7 @@ print_operand (operand_t *op) break; case op_value: printf ("(%s) ", pr_type_name[op->type]); - switch (op->o.value->type) { + switch (op->o.value->lltype) { case ev_string: printf ("\"%s\"", op->o.value->v.string_val); break; @@ -316,7 +316,7 @@ value_operand (ex_value_t *value) { operand_t *op; op = new_operand (op_value); - op->type = value->type; + op->type = value->lltype; op->o.value = value; return op; } @@ -337,8 +337,11 @@ alias_operand (etype_t type, operand_t *op) { operand_t *aop; - if (pr_type_size[type] != pr_type_size[op->type]) - internal_error (0, "aliasing operand with type of diffent size"); + if (pr_type_size[type] != pr_type_size[op->type]) { + internal_error (0, "\naliasing operand with type of diffent size" + " (%d, %d)", pr_type_size[type], + pr_type_size[op->type]); + } aop = new_operand (op_alias); aop->o.alias = op; aop->type = type; @@ -659,7 +662,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) pref = "R"; sblock = statement_subexpr (sblock, param, &arguments[ind]); if (options.code.vector_calls && a->type == ex_value - && a->e.value->type == ev_vector) + && a->e.value->lltype == ev_vector) sblock = vector_call (sblock, a, param, ind, &arguments[ind]); else sblock = statement_subexpr (sblock, a, &arguments[ind]); @@ -673,7 +676,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) sblock = statement_slist (sblock, mov); } else { if (options.code.vector_calls && a->type == ex_value - && a->e.value->type == ev_vector) { + && a->e.value->lltype == ev_vector) { sblock = vector_call (sblock, a, param, ind, 0); } else { operand_t *p = 0; @@ -774,7 +777,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) s->opc = *op; sblock_add_statement (sblock, s); } - } else if (e->type == ex_value && e->e.value->type == ev_pointer) { + } else if (e->type == ex_value && e->e.value->lltype == ev_pointer) { ex_pointer_t *ptr = &e->e.value->v.pointer; *op = def_operand (alias_def (ptr->def, ptr->type, ptr->val), ptr->type); @@ -1017,7 +1020,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) if (e->type > ex_value) internal_error (e, "bad expression type"); if (!sfuncs[e->type]) - internal_error (e, "unexpected expression type; %s", + internal_error (e, "unexpected expression type: %s", expr_names[e->type]); sblock = sfuncs[e->type] (sblock, e, op); diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 839f7ef4a..e37e5628a 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -82,7 +82,7 @@ get_hash (const void *_cl, void *unused) if (!cl->value) return 0; val = get_value (cl->value); - return Hash_Buffer (&val->v, sizeof (val->v)) + val->type; + return Hash_Buffer (&val->v, sizeof (val->v)) + val->lltype; } static int diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index c81222db0..2814d8bfd 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -681,6 +681,18 @@ is_scalar (const type_t *type) return is_float (type) || is_integral (type); } +int +is_vector (const type_t *type) +{ + return type->type == ev_vector; +} + +int +is_quaternion (const type_t *type) +{ + return type->type == ev_quat; +} + int is_math (const type_t *type) { @@ -714,6 +726,14 @@ is_array (const type_t *type) return 0; } +int +is_func (const type_t *type) +{ + if (type->type == ev_func) + return 1; + return 0; +} + int type_assignable (const type_t *dst, const type_t *src) { diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index f530f3b3a..bdaa9c6f3 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -79,7 +79,7 @@ static uintptr_t value_get_hash (const void *_val, void *unused) { const ex_value_t *val = (const ex_value_t *) _val; - return Hash_Buffer (&val->v, sizeof (val->v)) + val->type; + return Hash_Buffer (&val->v, sizeof (val->v)) + val->lltype; } static int @@ -87,7 +87,7 @@ value_compare (const void *_val1, const void *_val2, void *unused) { const ex_value_t *val1 = (const ex_value_t *) _val1; const ex_value_t *val2 = (const ex_value_t *) _val2; - if (val1->type != val2->type) + if (val1->lltype != val2->lltype) return 0; return memcmp (&val1->v, &val2->v, sizeof (val1->v)) == 0; } @@ -100,6 +100,13 @@ new_value (void) return value; } +static void +set_val_type (ex_value_t *val, type_t *type) +{ + val->type = type; + val->lltype = low_level_type (type); +} + static ex_value_t * find_value (const ex_value_t *val) { @@ -119,7 +126,7 @@ new_string_val (const char *string_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_string; + set_val_type (&val, &type_string); if (string_val) val.v.string_val = save_string (string_val); return find_value (&val); @@ -130,7 +137,7 @@ new_float_val (float float_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_float; + set_val_type (&val, &type_float); val.v.float_val = float_val; return find_value (&val); } @@ -140,7 +147,7 @@ new_vector_val (const float *vector_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_vector; + set_val_type (&val, &type_vector); VectorCopy (vector_val, val.v.vector_val); return find_value (&val); } @@ -150,7 +157,7 @@ new_entity_val (int entity_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_entity; + set_val_type (&val, &type_entity); val.v.entity_val = entity_val; return find_value (&val); } @@ -160,7 +167,7 @@ new_field_val (int field_val, type_t *type, def_t *def) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_field; + set_val_type (&val, field_type (type)); val.v.pointer.val = field_val; val.v.pointer.type = type; val.v.pointer.def = def; @@ -172,7 +179,7 @@ new_func_val (int func_val, type_t *type) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_func; + set_val_type (&val, type); val.v.func_val.val = func_val; val.v.func_val.type = type; return find_value (&val); @@ -183,7 +190,7 @@ new_pointer_val (int pointer_val, type_t *type, def_t *def) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_pointer; + set_val_type (&val, pointer_type (type)); val.v.pointer.val = pointer_val; val.v.pointer.type = type; val.v.pointer.def = def; @@ -195,7 +202,7 @@ new_quaternion_val (const float *quaternion_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_quat; + set_val_type (&val, &type_quaternion); QuatCopy (quaternion_val, val.v.quaternion_val); return find_value (&val); } @@ -205,7 +212,7 @@ new_integer_val (int integer_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_integer; + set_val_type (&val, &type_integer); val.v.integer_val = integer_val; return find_value (&val); } @@ -215,7 +222,7 @@ new_uinteger_val (int uinteger_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_uinteger; + set_val_type (&val, &type_uinteger); val.v.uinteger_val = uinteger_val; return find_value (&val); } @@ -225,7 +232,7 @@ new_short_val (short short_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = ev_short; + set_val_type (&val, &type_short); val.v.short_val = short_val; return find_value (&val); } @@ -235,10 +242,13 @@ new_nil_val (type_t *type) { ex_value_t val; memset (&val, 0, sizeof (val)); - val.type = low_level_type (type); - if (val.type == ev_pointer|| val.type == ev_field ) + set_val_type (&val, type); + if (val.lltype == ev_void) { + val.lltype = type_nil->type; + } + if (val.lltype == ev_pointer || val.lltype == ev_field ) val.v.pointer.type = type->t.fldptr.type; - if (val.type == ev_func) + if (val.lltype == ev_func) val.v.func_val.type = type; return find_value (&val); } @@ -333,13 +343,13 @@ ReuseString (const char *str) static float value_as_float (ex_value_t *value) { - if (value->type == ev_uinteger) + if (value->lltype == ev_uinteger) return value->v.uinteger_val; - if (value->type == ev_integer) + if (value->lltype == ev_integer) return value->v.integer_val; - if (value->type == ev_short) + if (value->lltype == ev_short) return value->v.short_val; - if (value->type == ev_float) + if (value->lltype == ev_float) return value->v.float_val; return 0; } @@ -347,13 +357,13 @@ value_as_float (ex_value_t *value) static int value_as_int (ex_value_t *value) { - if (value->type == ev_uinteger) + if (value->lltype == ev_uinteger) return value->v.uinteger_val; - if (value->type == ev_integer) + if (value->lltype == ev_integer) return value->v.integer_val; - if (value->type == ev_short) + if (value->lltype == ev_short) return value->v.short_val; - if (value->type == ev_float) + if (value->lltype == ev_float) return value->v.float_val; return 0; } @@ -361,13 +371,13 @@ value_as_int (ex_value_t *value) static unsigned value_as_uint (ex_value_t *value) { - if (value->type == ev_uinteger) + if (value->lltype == ev_uinteger) return value->v.uinteger_val; - if (value->type == ev_integer) + if (value->lltype == ev_integer) return value->v.integer_val; - if (value->type == ev_short) + if (value->lltype == ev_short) return value->v.short_val; - if (value->type == ev_float) + if (value->lltype == ev_float) return value->v.float_val; return 0; } @@ -375,7 +385,7 @@ value_as_uint (ex_value_t *value) ex_value_t * convert_value (ex_value_t *value, type_t *type) { - if (!is_scalar (type) || !is_scalar (ev_types[value->type])) { + if (!is_scalar (type) || !is_scalar (ev_types[value->lltype])) { error (0, "unable to convert non-scalar value"); return value; } @@ -400,12 +410,12 @@ alias_value (ex_value_t *value, type_t *type) { ex_value_t new; - if (type_size (type) != type_size (ev_types[value->type])) { + if (type_size (type) != type_size (ev_types[value->lltype])) { error (0, "unable to alias different sized values"); return value; } new = *value; - new.type = type->type; + set_val_type (&new, type); return find_value (&new); } @@ -436,9 +446,9 @@ emit_value (ex_value_t *value, def_t *def) clear_immediates (); } cn = 0; - if (val.type == ev_void) - val.type = type_nil->type; - switch (val.type) { +// if (val.type == ev_void) +// val.type = type_nil->type; + switch (val.lltype) { case ev_entity: tab = entity_imm_defs; type = &type_entity; @@ -463,7 +473,7 @@ emit_value (ex_value_t *value, def_t *def) break; } val.v.float_val = val.v.integer_val; - val.type = ev_float; + val.lltype = ev_float; case ev_float: tab = float_imm_defs; type = &type_float; @@ -528,7 +538,7 @@ emit_value (ex_value_t *value, def_t *def) cn->initialized = cn->constant = 1; cn->nosave = 1; // copy the immediate to the global area - switch (val.type) { + switch (val.lltype) { case ev_string: reloc_def_string (cn); break; diff --git a/tools/qfcc/test/quaternion.r b/tools/qfcc/test/quaternion.r index f5f2c889a..6ac67911a 100644 --- a/tools/qfcc/test/quaternion.r +++ b/tools/qfcc/test/quaternion.r @@ -43,7 +43,7 @@ test_format () printf ("q = [[5, 6, 7], 8] -> %v, %g\n", q.v, q.s); fail = 1; } -/* q = [s, v]; + q = [s, v]; if (q.x != v.x || q.y != v.y || q.z != v.z || q.w != s) { printf ("q = [s, v] -> %q (%v)\n", q, v); fail = 1; @@ -60,7 +60,7 @@ test_format () if (q.v != v || q.s != s) { printf ("q = [v, s] -> %v, %g (%v %s)\n", q.v, q.s, v, s); fail = 1; - }*/ + } return fail; } From 4828934e50c3eab8063ac55a150067758524ecf9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Oct 2018 23:39:05 +0900 Subject: [PATCH 0083/3664] Fix a equality check typo. Fixes bad code generation when assigning to vector.x in a function with no parameters and the vector is the first local var. --- tools/qfcc/source/expr_assign.c | 2 +- tools/qfcc/test/vecinit.r | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 0a1a82b6d..6ba4690e2 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -239,7 +239,7 @@ static __attribute__((pure)) int is_const_ptr (expr_t *e) { if ((e->type != ex_value || e->e.value->lltype != ev_pointer) - || !(POINTER_VAL (e->e.value->v.pointer) > 0 + || !(POINTER_VAL (e->e.value->v.pointer) >= 0 && POINTER_VAL (e->e.value->v.pointer) < 65536)) { return 1; } diff --git a/tools/qfcc/test/vecinit.r b/tools/qfcc/test/vecinit.r index 6503b390d..d26a94404 100644 --- a/tools/qfcc/test/vecinit.r +++ b/tools/qfcc/test/vecinit.r @@ -8,6 +8,20 @@ foo (float x, float y, float z) return v; } +float w; +float h; + +vector +bar (void) +{ + vector pos; + + pos.x = w; + pos.y = h; + pos.z = 0; + return pos; +} + int main () { From 2f2edae43b9b5d316ad1d4cbf45c45860a1bee18 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 Oct 2018 09:31:00 +0900 Subject: [PATCH 0084/3664] Make error, warning and notice give compiler file/line too. But only when verbosity > 1 (-vv). --- tools/qfcc/include/diagnostic.h | 28 +++++++++++++++++++--------- tools/qfcc/source/diagnostic.c | 24 +++++++++++++++++------- tools/qfcc/source/stub.c | 4 ++-- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index 99a542762..bd32711f8 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -44,21 +44,31 @@ extern diagnostic_hook error_hook; extern diagnostic_hook warning_hook; extern diagnostic_hook notice_hook; -struct expr_s *error (struct expr_s *e, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); -void -_internal_error (struct expr_s *e, const char *file, int line, - const char *fmt, ...) +struct expr_s *_error (struct expr_s *e, const char *file, int line, + const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); +#define error(e, fmt...) _error(e, __FILE__, __LINE__, fmt) + +void _internal_error (struct expr_s *e, const char *file, int line, + const char *fmt, ...) __attribute__ ((format (printf, 4, 5), noreturn)); #define internal_error(e, fmt...) _internal_error(e, __FILE__, __LINE__, fmt) -struct expr_s *warning (struct expr_s *e, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); -struct expr_s *notice (struct expr_s *e, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); + +struct expr_s *_warning (struct expr_s *e, const char *file, int line, + const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); +#define warning(e, fmt...) _warning(e, __FILE__, __LINE__, fmt) + +struct expr_s *_notice (struct expr_s *e, const char *file, int line, + const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); +#define notice(e, fmt...) _notice(e, __FILE__, __LINE__, fmt) + void _debug (struct expr_s *e, const char *file, int line, const char *fmt, ...) __attribute__ ((format (printf, 4, 5))); #define debug(e, fmt...) _debug(e, __FILE__, __LINE__, fmt) + void _bug (struct expr_s *e, const char *file, int line, const char *fmt, ...) __attribute__ ((format (printf, 4, 5))); #define bug(e, fmt...) _bug(e, __FILE__, __LINE__, fmt) diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index da2f01969..85e2b6d27 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -95,8 +95,9 @@ format_message (dstring_t *message, const char *msg_type, expr_t *e, } } -static __attribute__((format(printf, 2, 0))) void -_warning (expr_t *e, const char *fmt, va_list args) +static __attribute__((format(printf, 4, 0))) void +__warning (expr_t *e, const char *file, int line, + const char *fmt, va_list args) { dstring_t *message = dstring_new (); @@ -108,6 +109,9 @@ _warning (expr_t *e, const char *fmt, va_list args) } format_message (message, "warning", e, fmt, args); + if (options.verbosity > 1) { + dasprintf (message, " (%s:%d)", file, line); + } if (warning_hook) { warning_hook (message->str); } else { @@ -161,7 +165,7 @@ _bug (expr_t *e, const char *file, int line, const char *fmt, ...) } expr_t * -notice (expr_t *e, const char *fmt, ...) +_notice (expr_t *e, const char *file, int line, const char *fmt, ...) { va_list args; @@ -170,13 +174,16 @@ notice (expr_t *e, const char *fmt, ...) va_start (args, fmt); if (options.notices.promote) { - _warning (e, fmt, args); + __warning (e, file, line, fmt, args); } else { dstring_t *message = dstring_new (); report_function (e); format_message (message, "notice", e, fmt, args); + if (options.verbosity > 1) { + dasprintf (message, " (%s:%d)", file, line); + } if (notice_hook) { notice_hook (message->str); } else { @@ -189,12 +196,12 @@ notice (expr_t *e, const char *fmt, ...) } expr_t * -warning (expr_t *e, const char *fmt, ...) +_warning (expr_t *e, const char *file, int line, const char *fmt, ...) { va_list args; va_start (args, fmt); - _warning (e, fmt, args); + __warning (e, file, line, fmt, args); va_end (args); return e; } @@ -220,7 +227,7 @@ _internal_error (expr_t *e, const char *file, int line, const char *fmt, ...) } expr_t * -error (expr_t *e, const char *fmt, ...) +_error (expr_t *e, const char *file, int line, const char *fmt, ...) { va_list args; @@ -233,6 +240,9 @@ error (expr_t *e, const char *fmt, ...) dstring_t *message = dstring_new (); format_message (message, "error", e, fmt, args); + if (options.verbosity > 1) { + dasprintf (message, " (%s:%d)", file, line); + } if (error_hook) { error_hook (message->str); } else { diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index 117b19a8e..c10aff34a 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -29,5 +29,5 @@ __attribute__((const)) codespace_t *codespace_new (void) {return 0;} void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {} __attribute__((const)) int function_parms (function_t *f, byte *parm_size) {return 0;} void def_to_ddef (def_t *def, ddef_t *ddef, int aux) {} -__attribute__((const)) expr_t *warning (expr_t *e, const char *fmt, ...) {return 0;} -__attribute__((const)) expr_t *error (expr_t *e, const char *fmt, ...) {return 0;} +__attribute__((const)) expr_t *_warning (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;} +__attribute__((const)) expr_t *_error (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;} From aaab18c9a7bf8a37f773f88426a103ea909a1c9f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 Oct 2018 12:07:50 +0900 Subject: [PATCH 0085/3664] Nuke a dead field. It looks like ex_temp_t.expr was never really used, and I have no idea what I had intended (not surprising after ~17 years). --- tools/qfcc/include/expr.h | 1 - tools/qfcc/source/expr.c | 1 - 2 files changed, 2 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 466a11ec1..1b0206995 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -91,7 +91,6 @@ typedef struct { } ex_block_t; typedef struct { - struct expr_s *expr; struct operand_s *op; ///< The operand for the temporary variable, if ///< allocated struct type_s *type; ///< The type of the temporary variable. diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index a4fbf76ac..94fda5f37 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -426,7 +426,6 @@ copy_expr (expr_t *e) *n = *e; n->line = pr.source_line; n->file = pr.source_file; - n->e.temp.expr = copy_expr (e->e.temp.expr); return n; case ex_vector: n = new_expr (); From 0f5f2a125a6fa5c00f4f7ed5500eb7e344159bc7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 Oct 2018 23:23:45 +0900 Subject: [PATCH 0086/3664] Use a reliable reference for calculating progs offsets. Now that pr->zone can be null, it cannot be used as a reference. Fixes random crashes when using qfprogs (random due to heap randomization). --- libs/gamecode/pr_load.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 721b26bd7..9fee72574 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -116,6 +116,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) int offset_tweak; dprograms_t progs; byte *base; + byte *heap; if (!pr->file_error) pr->file_error = file_error; @@ -199,6 +200,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) Qread (file, base, size - sizeof (progs)); CRC_ProcessBlock (base, &pr->crc, size - sizeof (progs)); base -= sizeof (progs); // offsets are from file start + heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize); if (pr->edicts) { *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); @@ -207,20 +209,19 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) if (pr->zone_size) { //FIXME zone_size needs to be at least as big as memzone_t, but //memzone_t is opaque so its size is unknown - pr->zone = (memzone_t *)((byte *) pr->progs + pr->progs_size - + pr->pr_edictareasize); + pr->zone = (memzone_t *) heap; } pr->pr_functions = (dfunction_t *) (base + pr->progs->ofs_functions); pr->pr_strings = (char *) base + pr->progs->ofs_strings; - pr->pr_stringsize = (char *) pr->zone + pr->zone_size - (char *) base; + pr->pr_stringsize = (char *) heap + pr->zone_size - (char *) base; pr->pr_globaldefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); pr->pr_fielddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs); pr->pr_statements = (dstatement_t *) (base + pr->progs->ofs_statements); pr->pr_globals = (pr_type_t *) (base + pr->progs->ofs_globals); - pr->stack = (pr_type_t *) ((byte *) pr->zone + pr->zone_size); + pr->stack = (pr_type_t *) ((byte *) heap + pr->zone_size); pr->stack_bottom = pr->stack - pr->pr_globals; pr->globals_size = (pr_type_t *) ((byte *) pr->stack + pr->stack_size) - pr->pr_globals; From 6c53be928bb8588067944d3adf4c66b7e7cc6959 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 Oct 2018 23:32:53 +0900 Subject: [PATCH 0087/3664] Support returning vector expressions. Currently fails due to a scheduling problem when the vector expression contains functions. --- tools/qfcc/include/expr.h | 2 +- tools/qfcc/source/expr.c | 7 ++++++- tools/qfcc/source/expr_assign.c | 2 -- tools/qfcc/test/Makefile.am | 9 +++++++++ tools/qfcc/test/vecexpr.r | 23 +++++++++++++++++++++++ 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 tools/qfcc/test/vecexpr.r diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 1b0206995..08614f2ce 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -625,7 +625,7 @@ expr_t *build_for_statement (expr_t *init, expr_t *test, expr_t *next, expr_t *break_label, expr_t *continue_label); expr_t *build_state_expr (expr_t *e); expr_t *think_expr (struct symbol_s *think_sym); -expr_t *assign_expr (expr_t *e1, expr_t *e2); +expr_t *assign_expr (expr_t *dst, expr_t *src); expr_t *cast_expr (struct type_s *t, expr_t *e); const char *get_op_string (int op) __attribute__((const)); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 94fda5f37..30473cdea 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1999,8 +1999,13 @@ return_expr (function_t *f, expr_t *e) warning (e, "type mismatch for return value of %s", f->sym->name); } else { - if (f->sym->type->t.func.type != t) + if (f->sym->type->t.func.type != t) { e = cast_expr (f->sym->type->t.func.type, e); + t = f->sym->type->t.func.type; + } + } + if (e->type == ex_vector) { + e = assign_expr (new_ret_expr (t), e); } return new_unary_expr ('r', e); } diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 6ba4690e2..730396dfa 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -258,8 +258,6 @@ is_indirect (expr_t *e) return is_const_ptr (e->e.expr.e1); } -expr_t * -aassign_expr (expr_t *dst, expr_t *src); expr_t * assign_expr (expr_t *dst, expr_t *src) { diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 1ecb95fb4..352254f9b 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -45,6 +45,7 @@ test_progs_dat=\ structptr.dat \ swap.dat \ triangle.dat \ + vecexpr.dat \ vecinit.dat \ while.dat \ voidfor.dat @@ -195,6 +196,14 @@ triangle.run: Makefile build-run $(srcdir)/build-run $@ 100000 100000 1.00005 50002.4961 include ./$(DEPDIR)/triangle.Qo +vecexpr_dat_SOURCES=vecexpr.r +vecexpr_obj=$(vecexpr_dat_SOURCES:.r=.qfo) +vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(vecexpr_obj) +vecexpr.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/vecexpr.Qo + vecinit_dat_SOURCES=vecinit.r vecinit_obj=$(vecinit_dat_SOURCES:.r=.qfo) vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/vecexpr.r b/tools/qfcc/test/vecexpr.r new file mode 100644 index 000000000..74bf6e0b1 --- /dev/null +++ b/tools/qfcc/test/vecexpr.r @@ -0,0 +1,23 @@ +vector +t1() +{ + return [1, 2, 3]; +} + +vector +t2(float x) +{ + return [x, x, x]; +} + +vector +t3(float x) +{ + return [x, t2(9).z, x]; +} + +int +main () +{ + return t3(5) == '5 9 5' ? 0 : 1; +} From 2a2754e5811d12d4d19b5f89666a6fec3fdeaed1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 15 Oct 2018 19:48:19 +0900 Subject: [PATCH 0088/3664] More ways to break qfcc :/ --- tools/qfcc/test/vecexpr.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/test/vecexpr.r b/tools/qfcc/test/vecexpr.r index 74bf6e0b1..59cc66b4a 100644 --- a/tools/qfcc/test/vecexpr.r +++ b/tools/qfcc/test/vecexpr.r @@ -19,5 +19,5 @@ t3(float x) int main () { - return t3(5) == '5 9 5' ? 0 : 1; + return t3(5) == [5, 9, 5] ? 0 : 1; } From 302934a1e4042c2579f42f1d6666180386d33a15 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 15 Oct 2018 20:52:46 +0900 Subject: [PATCH 0089/3664] Remove some dead code. --- tools/qfcc/source/expr.c | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 30473cdea..0d82e9629 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2489,36 +2489,6 @@ think_expr (symbol_t *think_sym) return new_symbol_expr (think_sym); } -static inline __attribute__((pure)) int -is_lvalue (expr_t *e) -{ - if (e->type == ex_symbol) { - switch (e->e.symbol->sy_type) { - case sy_var: - return 1; - case sy_const: - return 0; - case sy_type: - return 0; - case sy_expr: - return 0; - case sy_func: - return 0; - case sy_class: - return 0; - } - } - if (e->type == ex_temp) - return 1; - if (e->type == ex_expr && e->e.expr.op == '.') - return 1; - if (e->type == ex_uexpr && e->e.expr.op == '.') - return 1; - if (e->type == ex_uexpr && e->e.expr.op == 'A') - return is_lvalue (e->e.expr.e1); - return 0; -} - expr_t * cast_expr (type_t *type, expr_t *e) { From 1746ce3af564484d032cc81352500d829675d6b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 15 Oct 2018 20:54:05 +0900 Subject: [PATCH 0090/3664] Make int type name reflect its keyword. Makes qc error messages make more sense. --- tools/qfcc/source/type.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 2814d8bfd..cc95de7ee 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -73,8 +73,8 @@ type_t type_field = {ev_field, "field", ty_none, {{&type_void}} }; type_t type_function = { ev_func, "function", ty_none, {{&type_void}} }; type_t type_pointer = { ev_pointer, "pointer", ty_none, {{&type_void}} }; type_t type_quaternion = { ev_quat, "quaternion" }; -type_t type_integer = { ev_integer, "integer" }; -type_t type_uinteger = { ev_uinteger, "uinteger" }; +type_t type_integer = { ev_integer, "int" }; +type_t type_uinteger = { ev_uinteger, "uint" }; type_t type_short = { ev_short, "short" }; type_t *type_nil; From ff5c1cd4c2756000754057e9ebb1f62aa9aaa45f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 15 Oct 2018 22:11:20 +0900 Subject: [PATCH 0091/3664] Clean up redundant type parameter to initialize_def. --- tools/qfcc/include/def.h | 4 +-- tools/qfcc/source/def.c | 28 ++++++++---------- tools/qfcc/source/expr.c | 5 ++-- tools/qfcc/source/function.c | 6 ++-- tools/qfcc/source/qc-parse.y | 57 ++++++++++++++++-------------------- tools/qfcc/source/qp-parse.y | 4 +-- tools/qfcc/source/switch.c | 7 +++-- 7 files changed, 49 insertions(+), 62 deletions(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index e22ab8c7e..db2332cb1 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -237,13 +237,11 @@ void def_to_ddef (def_t *def, ddef_t *ddef, int aux); For \a space and \a storage, see new_def(). \param sym The symbol for which to create and initialize a def. - \param type The type of the def. sym_t::type is set to this. If null, - the default type is used. \param init If not null, the expressions to use to initialize the def. \param space The space from which to allocate space for the def. \param storage The storage class of the def. */ -void initialize_def (struct symbol_s *sym, struct type_s *type, +void initialize_def (struct symbol_s *sym, struct expr_s *init, struct defspace_s *space, storage_class_t storage); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 346ee9b9d..2f5d97c5d 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -484,19 +484,14 @@ init_field_def (def_t *def, expr_t *init, storage_class_t storage) } void -initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space, +initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, storage_class_t storage) { symbol_t *check = symtab_lookup (current_symtab, sym->name); reloc_t *relocs = 0; - if (!type) { - warning (0, "type for %s defaults to %s", sym->name, - type_default->name); - type = type_default; - } if (check && check->table == current_symtab) { - if (check->sy_type != sy_var || check->type != type) { + if (check->sy_type != sy_var || check->type != sym->type) { error (0, "%s redefined", sym->name); } else { // is var and same type @@ -514,7 +509,7 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space, sym = check; } } - sym->type = type; + sym->sy_type = sy_var; if (!sym->table) symtab_addsymbol (current_symtab, sym); // if (storage == sc_global && init && is_scalar (type)) { @@ -535,12 +530,13 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space, sym->s.def = 0; } if (!sym->s.def) { - sym->s.def = new_def (sym->name, type, space, storage); + sym->s.def = new_def (sym->name, sym->type, space, storage); reloc_attach_relocs (relocs, &sym->s.def->relocs); } - if (type == &type_vector && options.code.vector_components) + if (sym->type == &type_vector && options.code.vector_components) init_vector_components (sym, 0); - if (type->type == ev_field && storage != sc_local && storage != sc_param) + if (sym->type->type == ev_field && storage != sc_local + && storage != sc_param) init_field_def (sym->s.def, init, storage); if (storage == sc_extern) { if (init) @@ -553,14 +549,14 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space, if (init->type == ex_error) return; if (init->type == ex_nil) - convert_nil (init, type); - if ((is_array (type) || is_struct (type) - || type == &type_vector || type == &type_quaternion) + convert_nil (init, sym->type); + if ((is_array (sym->type) || is_struct (sym->type) + || sym->type == &type_vector || sym->type == &type_quaternion) && init->type == ex_block && !init->e.block.result) { init_elements (sym->s.def, init); sym->s.def->initialized = 1; } else { - if (!type_assignable (type, get_type (init))) { + if (!type_assignable (sym->type, get_type (init))) { error (init, "type mismatch in initializer"); return; } @@ -589,7 +585,7 @@ initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space, v->v.string_val); } else { memcpy (D_POINTER (void, sym->s.def), &v->v, - type_size (type) * sizeof (pr_type_t)); + type_size (sym->type) * sizeof (pr_type_t)); } } sym->s.def->initialized = sym->s.def->constant = 1; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 0d82e9629..53b17987f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2615,9 +2615,8 @@ super_expr (class_type_t *class_type) sym = symtab_lookup (current_symtab, ".super"); if (!sym || sym->table != current_symtab) { - sym = new_symbol (".super"); - initialize_def (sym, &type_obj_super, 0, current_symtab->space, - sc_local); + sym = new_symbol_type (".super", &type_obj_super); + initialize_def (sym, 0, current_symtab->space, sc_local); } super = new_symbol_expr (sym); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 873f734b6..c5736f8cc 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -463,7 +463,7 @@ build_scope (symbol_t *fsym, symtab_t *parent) if (fsym->type->t.func.num_params < 0) { args = new_symbol_type (".args", &type_va_list); - initialize_def (args, args->type, 0, symtab->space, sc_param); + initialize_def (args, 0, symtab->space, sc_param); } for (p = fsym->params, i = 0; p; p = p->next) { @@ -476,14 +476,14 @@ build_scope (symbol_t *fsym, symtab_t *parent) p->name = save_string (""); } param = new_symbol_type (p->name, p->type); - initialize_def (param, param->type, 0, symtab->space, sc_param); + initialize_def (param, 0, symtab->space, sc_param); i++; } if (args) { while (i < MAX_PARMS) { param = new_symbol_type (va (".par%d", i), &type_param); - initialize_def (param, &type_param, 0, symtab->space, sc_param); + initialize_def (param, 0, symtab->space, sc_param); i++; } } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 2ab9d4144..5ec3ad2f2 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -252,6 +252,17 @@ spec_merge (specifier_t spec, specifier_t new) return spec; } +static specifier_t +default_type (specifier_t spec, symbol_t *sym) +{ + if (!spec.type) { + spec.type = type_default; + warning (0, "type defaults to '%s' in declaration of '%s'", + type_default->name, sym->name); + } + return spec; +} + %} %expect 0 @@ -382,48 +393,35 @@ external_decl_list external_decl : var_decl { - specifier_t spec = $0; - type_t *type; - - if (!spec.type) - spec.type = type_default; - type = find_type (append_type ($1->type, spec.type)); + specifier_t spec = default_type ($0, $1); + $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { - $1->type = type; $1->sy_type = sy_type; symtab_addsymbol (current_symtab, $1); } else { - initialize_def ($1, type, 0, current_symtab->space, - spec.storage); + initialize_def ($1, 0, current_symtab->space, spec.storage); if ($1->s.def) $1->s.def->nosave |= spec.nosave; } } | var_decl var_initializer { - specifier_t spec = $0; - type_t *type; + specifier_t spec = default_type ($0, $1); - if (!spec.type) - spec.type = type_default; - type = find_type (append_type ($1->type, spec.type)); + $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { error (0, "typedef %s is initialized", $1->name); - $1->type = type; $1->sy_type = sy_type; symtab_addsymbol (current_symtab, $1); } else { - initialize_def ($1, type, $2, current_symtab->space, - spec.storage); + initialize_def ($1, $2, current_symtab->space, spec.storage); if ($1->s.def) $1->s.def->nosave |= spec.nosave; } } | function_decl { - specifier_t spec = $0; - if (!spec.type) - spec.type = type_default; + specifier_t spec = default_type ($0, $1); $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; @@ -903,19 +901,16 @@ decl : function_decl {} | var_decl opt_initializer { - specifier_t spec = $0; - type_t *type; - storage_class_t sc = $0.storage; + specifier_t spec = default_type ($0, $1); + storage_class_t sc = spec.storage; struct defspace_s *space = current_symtab->space; - if (!spec.type) - spec.type = type_default; if (sc == sc_static) space = pr.near_data; - type = find_type (append_type ($1->type, spec.type)); - initialize_def ($1, type, $2, space, sc); + $1->type = find_type (append_type ($1->type, spec.type)); + initialize_def ($1, $2, space, sc); if ($1->s.def) - $1->s.def->nosave |= $0.nosave; + $1->s.def->nosave |= spec.nosave; } ; @@ -974,8 +969,7 @@ non_code_func { symbol_t *sym = $0; specifier_t spec = $-1; - initialize_def (sym, sym->type, $2, current_symtab->space, - spec.storage); + initialize_def (sym, $2, current_symtab->space, spec.storage); if (sym->s.def) sym->s.def->nosave |= spec.nosave; } @@ -988,8 +982,7 @@ non_code_func if (sym->sy_type == sy_func) make_function (sym, 0, sym->table->space, spec.storage); } else { - initialize_def (sym, sym->type, 0, current_symtab->space, - spec.storage); + initialize_def (sym, 0, current_symtab->space, spec.storage); if (sym->s.def) sym->s.def->nosave |= spec.nosave; } diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 9731402a5..922068b02 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -207,8 +207,8 @@ declarations { while ($3) { symbol_t *next = $3->next; - initialize_def ($3, $5, 0, current_symtab->space, - current_storage); + $3->type = $5; + initialize_def ($3, 0, current_symtab->space, current_storage); $3 = next; } } diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index e37e5628a..0ff624b95 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -345,9 +345,10 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, tree->labels[i]->e.label.used++; append_expr (table_init, address_expr (tree->labels[i], 0, 0)); } - table_sym = new_symbol (table_name); - initialize_def (table_sym, array_type (&type_integer, high - low + 1), - table_init, pr.near_data, sc_static); + table_sym = new_symbol_type (table_name, + array_type (&type_integer, + high - low + 1)); + initialize_def (table_sym, table_init, pr.near_data, sc_static); table_expr = new_symbol_expr (table_sym); if (tree->left) { From 607ec3124ec2191fc43408bb2b2d94d7d458efa9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 15 Oct 2018 22:12:40 +0900 Subject: [PATCH 0092/3664] More dead code removal. I have no idea why this hung around. It appears to be old array/struct initialization. --- tools/qfcc/source/def.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 2f5d97c5d..1bc1faf81 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -512,17 +512,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, sym->sy_type = sy_var; if (!sym->table) symtab_addsymbol (current_symtab, sym); -// if (storage == sc_global && init && is_scalar (type)) { -// sym->sy_type = sy_const; -// memset (&sym->s.value, 0, sizeof (&sym->s.value)); -// if (init->type != ex_value) { //FIXME arrays/structs -// error (0, "non-constant initializier"); -// } else { -// sym->s.value = init->e.value; -// convert_value (&sym->s.value, sym->type); -// } -// return; -// } + if (sym->s.def && sym->s.def->external) { //FIXME this really is not the right way relocs = sym->s.def->relocs; From 319ecfbbfaef23a807ac0d2cba59afe223754ad0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jun 2019 06:42:31 +0900 Subject: [PATCH 0093/3664] Create a usable dot for vector expressions It leaves a lot to be desired, but it beats "FIXME". --- tools/qfcc/source/dot_expr.c | 37 +++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 191c8208d..175b8c800 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -367,7 +367,42 @@ print_vector (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - dasprintf (dstr, "%*se_%p [label=\"vector FIXME\"];\n", indent, "", e); + if (e->e.vector.type == &type_vector) { + expr_t *x = e->e.vector.list; + expr_t *y = x->next; + expr_t *z = y->next; + _print_expr (dstr, x, level, id, next); + _print_expr (dstr, y, level, id, next); + _print_expr (dstr, z, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, x); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, y); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, z); + } + if (e->e.vector.type == &type_quaternion) { + if (e->e.vector.list->next->next) { + expr_t *x = e->e.vector.list; + expr_t *y = x->next; + expr_t *z = y->next; + expr_t *w = z->next; + _print_expr (dstr, x, level, id, next); + _print_expr (dstr, y, level, id, next); + _print_expr (dstr, z, level, id, next); + _print_expr (dstr, w, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, x); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, y); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, z); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, w); + } else { + expr_t *v = e->e.vector.list; + expr_t *s = v->next; + _print_expr (dstr, v, level, id, next); + _print_expr (dstr, s, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, v); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, s); + } + } + dasprintf (dstr, "%*se_%p [label=\"vector %d\"];\n", indent, "", e, + e->line); } static void From d00a2ef82d6981b56f903a88ed69676924f502f2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jun 2019 06:44:19 +0900 Subject: [PATCH 0094/3664] Convert constant vector expressions in binary expressions Fixes not being able to compare with eg [1, 2, 3] --- tools/qfcc/source/expr_binary.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 2aa963b3a..b3717c1e8 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -726,6 +726,7 @@ binary_expr (int op, expr_t *e1, expr_t *e2) expr_type_t *expr_type; convert_name (e1); + e1 = convert_vector (e1); if (e1->type == ex_block && e1->e.block.is_call && has_function_call (e2) && e1->e.block.result) { e = new_temp_def_expr (get_type (e1->e.block.result)); @@ -735,6 +736,7 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return e1; convert_name (e2); + e2 = convert_vector (e2); if (e2->type == ex_error) return e2; From a5da8da1dcc429761aed55f2da0883a242a6a3c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jun 2019 06:45:48 +0900 Subject: [PATCH 0095/3664] Be more informative for symbol type internal errors --- tools/qfcc/source/statements.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index fae48f153..f78575fe0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -972,8 +972,8 @@ expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op) } else if (sym->sy_type == sy_func) { *op = def_operand (sym->s.func->def, 0); } else { - internal_error (e, "unexpected symbol type: %s", - symtype_str(sym->sy_type)); + internal_error (e, "unexpected symbol type: %s for %s", + symtype_str(sym->sy_type), sym->name); } return sblock; } From 7e31704ebe92adbd7fa162250a673a46ceb7e585 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jun 2019 06:46:38 +0900 Subject: [PATCH 0096/3664] Be more informative for pass by value size errors --- tools/qfcc/source/function.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index c5736f8cc..7f28a77b9 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -427,7 +427,8 @@ check_function (symbol_t *fsym) fsym->type->t.func.type = &type_void;//FIXME better type? } if (type_size (fsym->type->t.func.type) > type_size (&type_param)) { - error (0, "return value too large to be passed by value"); + error (0, "return value too large to be passed by value (%d)", + type_size (&type_param)); fsym->type->t.func.type = &type_void;//FIXME better type? } for (p = params, i = 0; p; p = p->next, i++) { From 4ef4a7e955b5f09fb8c58a0c492b9d664c440e1e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jun 2019 07:01:44 +0900 Subject: [PATCH 0097/3664] Start work on simple names in symbol tables I don't remember what the goal was (stopped working on it eight months ago), but some possibilities include: - better handling of nil (have trouble with assigning into struts) - automatic forward declarations ala C# and jai (I was watching vids about jai at the time) - something for pascal - simply that the default symbol type should not be var (in which case, goal accomplished) --- tools/qfcc/include/symtab.h | 1 + tools/qfcc/source/expr_assign.c | 2 ++ tools/qfcc/source/qc-parse.y | 2 ++ tools/qfcc/source/struct.c | 1 + tools/qfcc/source/symtab.c | 2 ++ 5 files changed, 8 insertions(+) diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index 626d7a484..f338077eb 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -48,6 +48,7 @@ typedef enum vis_e { } vis_t; typedef enum { + sy_name, ///< just a name (referent tbd) sy_var, ///< symbol refers to a variable sy_const, ///< symbol refers to a constant sy_type, ///< symbol refers to a type diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 730396dfa..f6071a9f4 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -87,6 +87,8 @@ check_valid_lvalue (expr_t *expr) switch (expr->type) { case ex_symbol: switch (expr->e.symbol->sy_type) { + case sy_name: + break; case sy_var: return 0; case sy_const: diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 5ec3ad2f2..3e05a55e5 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -650,6 +650,7 @@ struct_decl $0.type = type_default; $1->type = append_type ($1->type, $0.type); $1->type = find_type ($1->type); + $1->sy_type = sy_var; symtab_addsymbol (current_symtab, $1); } | var_decl @@ -658,6 +659,7 @@ struct_decl $0.type = type_default; $1->type = append_type ($1->type, $0.type); $1->type = find_type ($1->type); + $1->sy_type = sy_var; symtab_addsymbol (current_symtab, $1); } | var_decl ':' expr %prec COMMA {} diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 4cb81fa74..ddf30f8ea 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -246,6 +246,7 @@ make_structure (const char *name, int su, struct_def_t *defs, type_t *type) strct = new_symtab (0, stab_struct); while (defs->name) { field = new_symbol_type (defs->name, defs->type); + field->sy_type = sy_var; if (!symtab_addsymbol (strct, field)) internal_error (0, "duplicate symbol: %s", defs->name); defs++; diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 3e18cf615..f26a690e7 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -52,6 +52,7 @@ static symtab_t *symtabs_freelist; static symbol_t *symbols_freelist; static const char *sy_type_names[] = { + "sy_name", "sy_var", "sy_const", "sy_type", @@ -234,5 +235,6 @@ make_symbol (const char *name, type_t *type, defspace_t *space, sym->s.def = new_def (name, type, space, storage); reloc_attach_relocs (relocs, &sym->s.def->relocs); } + sym->sy_type = sy_var; return sym; } From 3327127e3649860724e61b6d436d58c270ae0d95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 13:28:29 +0900 Subject: [PATCH 0098/3664] Fix a typo in a comment --- tools/qfcc/include/def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index db2332cb1..d538d111d 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -71,7 +71,7 @@ typedef struct def_s { def they alias, including relocation records. However, they do keep track of the source file and line that first created the alias. - The relations between a def an any of its aliases are maintained by + The relations between a def and any of its aliases are maintained by a linked list headed by def_t::alias_defs and connected by def_t::next. def_t::alias is used to find the main def via one if its aliases. The order of the aliases in the list is arbitrary: it is the From 398e1cf83ad200cc5870b5edbab406165221f4be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 13:30:06 +0900 Subject: [PATCH 0099/3664] Use output file as base for dot files Ensures the output goes not go into the source directory when using a separate build tree. --- tools/qfcc/source/dot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dot.c b/tools/qfcc/source/dot.c index 1844a1fe9..54d67c241 100644 --- a/tools/qfcc/source/dot.c +++ b/tools/qfcc/source/dot.c @@ -37,7 +37,7 @@ #include "dot.h" #include "function.h" -#include "qfcc.h" +#include "options.h" #include "strpool.h" void @@ -46,7 +46,7 @@ dump_dot (const char *stage, void *data, { char *fname; - fname = nva ("%s.%s.%s.dot", GETSTR (pr.source_file), current_func->name, + fname = nva ("%s.%s.%s.dot", options.output_file, current_func->name, stage); dump_func (data, fname); free (fname); From e27da9c7dbfcff1e78f4ecdc7088868d1d59577a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 13:31:30 +0900 Subject: [PATCH 0100/3664] Avoid folding constants in assign_expr This prevents fold_constants from complaining about attempts to take the address of a vector. --- tools/qfcc/source/expr_assign.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index f6071a9f4..7cf1d8b4d 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -282,8 +282,6 @@ assign_expr (expr_t *dst, expr_t *src) return expr; } - dst = fold_constants (dst); - src = fold_constants (src); if ((expr = check_valid_lvalue (dst))) { return expr; From ebab6574b956fad1437f1394c1b074aaecc7cace Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 13:35:47 +0900 Subject: [PATCH 0101/3664] Allow taking the address of a temporary variable --- tools/qfcc/source/expr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 53b17987f..51f302947 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2219,6 +2219,9 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) return e1; case ex_label: return new_label_ref (&e1->e.label); + case ex_temp: + e = new_unary_expr ('&', e1); + break; default: return error (e1, "invalid type for unary &"); } From e217bdd55f8f4f3119bbd08812df61abe7f9a6da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 13:36:03 +0900 Subject: [PATCH 0102/3664] Assign vector expressions to a temp for return Rather than direct to .return, allowing return of vector expressions with function calls without trashing the vector. --- tools/qfcc/source/expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 51f302947..104963189 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2005,7 +2005,7 @@ return_expr (function_t *f, expr_t *e) } } if (e->type == ex_vector) { - e = assign_expr (new_ret_expr (t), e); + e = assign_expr (new_temp_def_expr (t), e); } return new_unary_expr ('r', e); } From df0316bb13fc2e82cf13d411e403bfdfa0e4a7d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 19:22:29 +0900 Subject: [PATCH 0103/3664] Clean up some comment FIXMEs --- tools/qfcc/include/def.h | 4 +++- tools/qfcc/include/expr.h | 2 +- tools/qfcc/include/function.h | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index d538d111d..79502a7d0 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -222,7 +222,9 @@ void def_to_ddef (def_t *def, ddef_t *ddef, int aux); /** Initialize a def referenced by the given symbol. - The symbol is checked for redefinition. (FIXME check rules) + The symbol is checked for redefinition. A symbol is considered to be + redefined if the previous definition is in the same symbol table and + of a different type or already initialized. If \a type is null, then the def will be given the default type (as specified by ::type_default). diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 08614f2ce..f1987bb8a 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -416,7 +416,7 @@ expr_t *new_entity_expr (int entity_val); /** Create a new field constant expression node. - \param field_val XXX + \param field_val offset? XXX \param type The type of the field. \param def \return The new field constant expression node diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index a1a5c19bf..b4b546fa6 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -105,9 +105,9 @@ extern function_t *current_func; typedef struct param_s { struct param_s *next; const char *selector; - struct type_s *type; //FIXME redundant - const char *name; //FIXME redundant - struct symbol_s *symbol; + struct type_s *type; + const char *name; + struct symbol_s *symbol; //FIXME what is this for? } param_t; struct expr_s; From 6acbdcb3e57a1ef0ca68eac4097a4966c8d8934b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 19:23:10 +0900 Subject: [PATCH 0104/3664] Correct a typo --- tools/qfcc/source/method.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index e5102a6cf..883133b64 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -511,7 +511,7 @@ emit_method_list_item (def_t *def, void *data, int index) pr_method_description_t *desc; if (def->type != &type_obj_method_description) - internal_error (0, "%s: expected method_descripting def", + internal_error (0, "%s: expected method_description def", __FUNCTION__); if (index < 0 || index >= methods->count) internal_error (0, "%s: out of bounds index: %d %d", From f2102187b9b00dde5c100d3c004b17fa079a6a2d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 19:23:49 +0900 Subject: [PATCH 0105/3664] Clean up emit_protocol_list Now it uses emit_structure, which will make it easier should things go wrong. --- tools/qfcc/source/class.c | 64 +++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 21dc210c6..adeb4d4bf 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1470,39 +1470,57 @@ emit_protocol (protocol_t *protocol) return proto_def; } +static void +emit_protocol_next (def_t *def, void *data, int index) +{ + if (def->type != &type_pointer) { + internal_error (0, "%s: expected pointer def", __FUNCTION__); + } + D_INT (def) = 0; +} + +static void +emit_protocol_count (def_t *def, void *data, int index) +{ + protocollist_t *protocols = (protocollist_t *) data; + + if (def->type != &type_integer) { + internal_error (0, "%s: expected integer def", __FUNCTION__); + } + D_INT (def) = protocols->count; +} + +static void +emit_protocol_list_item (def_t *def, void *data, int index) +{ + protocollist_t *protocols = (protocollist_t *) data; + protocol_t *protocol = protocols->list[index]; + + if (!is_array (def->type) || def->type->t.array.type != &type_pointer) { + internal_error (0, "%s: expected array of pointer def", __FUNCTION__); + } + if (index < 0 || index >= protocols->count) { + internal_error (0, "%s: out of bounds index: %d %d", + __FUNCTION__, index, protocols->count); + } + EMIT_DEF (def->space, D_INT(def), emit_protocol (protocol)); +} + def_t * emit_protocol_list (protocollist_t *protocols, const char *name) { - //FIXME use emit_struct static struct_def_t proto_list_struct[] = { - {"next", &type_pointer}, - {"count", &type_integer}, - {"list", 0}, // type will be filled in at run time + {"next", &type_pointer, emit_protocol_next}, + {"count", &type_integer, emit_protocol_count}, + {"list", 0, emit_protocol_list_item}, {0, 0}, }; - type_t *proto_list_type; - def_t *proto_list_def; - defspace_t *space; - pr_protocol_list_t *proto_list; - int i; if (!protocols) return 0; proto_list_struct[2].type = array_type (&type_pointer, protocols->count); - proto_list_type = make_structure (0, 's', proto_list_struct, 0)->type; - proto_list_def = make_symbol (va ("_OBJ_PROTOCOLS_%s", name), - proto_list_type, - pr.far_data, sc_static)->s.def; - proto_list_def->initialized = proto_list_def->constant = 1; - proto_list_def->nosave = 1; - space = proto_list_def->space; - proto_list = &D_STRUCT (pr_protocol_list_t, proto_list_def); - proto_list->next = 0; - proto_list->count = protocols->count; - for (i = 0; i < protocols->count; i++) - EMIT_DEF (space, proto_list->list[i], - emit_protocol (protocols->list[i])); - return proto_list_def; + return emit_structure (va ("_OBJ_PROTOCOLS_%s", name), 's', + proto_list_struct, 0, protocols, sc_static); } void From be4c3a82a2e120859c0eee641c7309bf3b67b977 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 19:25:25 +0900 Subject: [PATCH 0106/3664] Detect redefinitions of structs and unions While the redefinition was being detected, it was misreported as the tag being wrong, and on the wrong line, too. --- tools/qfcc/source/qc-parse.y | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 3e05a55e5..15edcb0ee 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -584,8 +584,13 @@ struct_specifier { symbol_t *sym; sym = find_struct ($1, $2, 0); - if (!sym->table) + if (!sym->table) { symtab_addsymbol (current_symtab, sym); + } else { + error (0, "%s %s redefined", $1 == 's' ? "struct" : "union", + $2->name); + $1 = 0; + } current_symtab = new_symtab (current_symtab, stab_local); } struct_defs '}' @@ -594,10 +599,12 @@ struct_specifier symtab_t *symtab = current_symtab; current_symtab = symtab->parent; - sym = build_struct ($1, $2, symtab, 0); - $$ = make_spec (sym->type, 0, 0, 0); - if (!sym->table) - symtab_addsymbol (current_symtab, sym); + if ($1) { + sym = build_struct ($1, $2, symtab, 0); + $$ = make_spec (sym->type, 0, 0, 0); + if (!sym->table) + symtab_addsymbol (current_symtab, sym); + } } | STRUCT tag { From 5bd3c8c985e03c18acc37c633f209f1fdfc99176 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jun 2019 21:52:17 +0900 Subject: [PATCH 0107/3664] Allow variable declarations in for loops Matches C, C++ and C# --- tools/qfcc/source/qc-parse.y | 55 ++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 15edcb0ee..945e3b5fb 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -180,11 +180,12 @@ int yylex (void); %type methoddef %type opt_initializer var_initializer local_def -%type opt_expr fexpr expr element_list element vector_expr -%type optional_state_expr texpr +%type opt_init opt_expr fexpr expr element_list element +%type optional_state_expr texpr vector_expr %type statement statements compound_statement %type else label break_label continue_label %type unary_expr cast_expr opt_arg_list arg_list +%type init_var_decl_list init_var_decl %type switch_block %type identifier @@ -1053,22 +1054,28 @@ optional_comma | ',' ; -compound_statement - : '{' +push_scope + : /* empty */ { if (!options.traditional) { current_symtab = new_symtab (current_symtab, stab_local); current_symtab->space = current_symtab->parent->space; } } - statements '}' + ; + +pop_scope + : /* empty */ { if (!options.traditional) current_symtab = current_symtab->parent; - $$ = $3; } ; +compound_statement + : '{' push_scope statements '}' pop_scope { $$ = $3; } + ; + statements : /*empty*/ { @@ -1143,13 +1150,13 @@ statement { $$ = build_if_statement ($2, $4, $6, $7, $8); } - | FOR break_label continue_label - '(' opt_expr ';' opt_expr ';' opt_expr ')' statement + | FOR push_scope break_label continue_label + '(' opt_init ';' opt_expr ';' opt_expr ')' statement pop_scope { - $$ = build_for_statement ($5, $7, $9, $11, + $$ = build_for_statement ($6, $8, $10, $12, break_label, continue_label); - break_label = $2; - continue_label = $3; + break_label = $3; + continue_label = $4; } | WHILE break_label continue_label not '(' texpr ')' statement { @@ -1216,6 +1223,32 @@ switch_block } ; +opt_init + : fexpr + | type init_var_decl_list { $$ = $2; } + | /* empty */ + { + $$ = 0; + } + ; + +init_var_decl_list + : init_var_decl + | init_var_decl_list ',' init_var_decl + ; + +init_var_decl + : var_decl opt_initializer + { + specifier_t spec = $0; + $1->type = append_type ($1->type, spec.type); + $1->type = find_type ($1->type); + $1->sy_type = sy_var; + initialize_def ($1, 0, current_symtab->space, spec.storage); + $$ = assign_expr (new_symbol_expr ($1), $2); + } + ; + opt_expr : fexpr | /* empty */ From 625e767684b904b83cba021e318c525847e704b0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 13:00:55 +0900 Subject: [PATCH 0108/3664] Update qf dependency stuff for recent automake Not sure just what version of automake broke things, but I do remember having a bad time getting the dependencies to work in the first place. At least now they should be more reliable (until automake changes things). --- tools/qfcc/test/Makefile.am | 116 ++++++++++++++++++++++-------------- 1 file changed, 72 insertions(+), 44 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 352254f9b..469ba261a 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -31,9 +31,9 @@ fail_bins= test_progs_dat=\ chewed-alias.dat \ chewed-return.dat \ + deadbool.dat \ func-expr.dat \ func-static.dat \ - deadbool.dat \ infloop.dat \ modulo.dat \ paramret.dat \ @@ -47,8 +47,8 @@ test_progs_dat=\ triangle.dat \ vecexpr.dat \ vecinit.dat \ - while.dat \ - voidfor.dat + voidfor.dat \ + while.dat fail_progs_dat= @@ -68,13 +68,16 @@ test_harness_SOURCES= test-bi.c test-harness.c test_harness_LDADD= $(QFCC_TEST_LIBS) test_harness_DEPENDENCIES= $(QFCC_TEST_DEPS) +r_depfiles_remade= + chewed_alias_dat_SOURCES=chewed-alias.r chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo) chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_alias_obj) chewed-alias.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/chewed-alias.Qo +include ./$(DEPDIR)/chewed-alias.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/chewed-alias.Qo chewed_return_dat_SOURCES=chewed-return.r chewed_return_obj=$(chewed_return_dat_SOURCES:.r=.qfo) @@ -82,23 +85,8 @@ chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_return_obj) chewed-return.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ -include ./$(DEPDIR)/chewed-return.Qo - -func_expr_dat_SOURCES=func-expr.r -func_expr_obj=$(func_expr_dat_SOURCES:.r=.qfo) -func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) -func-expr.run: Makefile build-run - $(srcdir)/build-run $@ -include ./$(DEPDIR)/func-expr.Qo - -func_static_dat_SOURCES=func-static.r -func_static_obj=$(func_static_dat_SOURCES:.r=.qfo) -func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) -func-static.run: Makefile build-run - $(srcdir)/build-run $@ -include ./$(DEPDIR)/func-static.Qo +include ./$(DEPDIR)/chewed-return.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/chewed-return.Qo deadbool_dat_SOURCES=deadbool.r deadbool_obj=$(deadbool_dat_SOURCES:.r=.qfo) @@ -106,7 +94,26 @@ deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(deadbool_obj) deadbool.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/deadbool.Qo +include ./$(DEPDIR)/deadbool.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/deadbool.Qo + +func_expr_dat_SOURCES=func-expr.r +func_expr_obj=$(func_expr_dat_SOURCES:.r=.qfo) +func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) +func-expr.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/func-expr.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/func-expr.Qo + +func_static_dat_SOURCES=func-static.r +func_static_obj=$(func_static_dat_SOURCES:.r=.qfo) +func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) +func-static.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/func-static.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/func-static.Qo infloop_dat_SOURCES=infloop.r infloop_obj=$(infloop_dat_SOURCES:.r=.qfo) @@ -114,7 +121,8 @@ infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(infloop_obj) infloop.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/infloop.Qo +include ./$(DEPDIR)/infloop.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/infloop.Qo modulo_dat_SOURCES=modulo.r modulo_obj=$(modulo_dat_SOURCES:.r=.qfo) @@ -122,7 +130,8 @@ modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(modulo_obj) modulo.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ -include ./$(DEPDIR)/modulo.Qo +include ./$(DEPDIR)/modulo.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/modulo.Qo paramret_dat_SOURCES=paramret.r paramret_obj=$(paramret_dat_SOURCES:.r=.qfo) @@ -130,7 +139,8 @@ paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) paramret.run: Makefile build-run TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ -include ./$(DEPDIR)/paramret.Qo +include ./$(DEPDIR)/paramret.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/paramret.Qo quaternion_dat_SOURCES=quaternion.r quaternion_obj=$(quaternion_dat_SOURCES:.r=.qfo) @@ -138,7 +148,8 @@ quaternion.dat$(EXEEXT): $(quaternion_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(quaternion_obj) quaternion.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/quaternion.Qo +include ./$(DEPDIR)/quaternion.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/quaternion.Qo return_ivar_dat_SOURCES=return-ivar.r return_ivar_obj=$(return_ivar_dat_SOURCES:.r=.qfo) @@ -146,7 +157,8 @@ return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(return_ivar_obj) return-ivar.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/return-ivar.Qo +include ./$(DEPDIR)/return-ivar.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/return-ivar.Qo sendv_dat_SOURCES=sendv.r sendv_obj=$(sendv_dat_SOURCES:.r=.qfo) @@ -154,7 +166,8 @@ sendv.dat$(EXEEXT): $(sendv_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(sendv_obj) sendv.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/sendv.Qo +include ./$(DEPDIR)/sendv.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/sendv.Qo state_dat_SOURCES=state.r state_obj=$(state_dat_SOURCES:.r=.qfo) @@ -162,7 +175,8 @@ state.dat$(EXEEXT): $(state_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(state_obj) state.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/state.Qo +include ./$(DEPDIR)/state.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/state.Qo structlive_dat_SOURCES=structlive.r structlive_obj=$(structlive_dat_SOURCES:.r=.qfo) @@ -170,7 +184,8 @@ structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structlive_obj) structlive.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/structlive.Qo +include ./$(DEPDIR)/structlive.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/structlive.Qo structptr_dat_SOURCES=structptr.r structptr_obj=$(structptr_dat_SOURCES:.r=.qfo) @@ -178,7 +193,8 @@ structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structptr_obj) structptr.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/structptr.Qo +include ./$(DEPDIR)/structptr.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/structptr.Qo swap_dat_SOURCES=swap.r swap_obj=$(swap_dat_SOURCES:.r=.qfo) @@ -186,7 +202,8 @@ swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(swap_obj) swap.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/swap.Qo +include ./$(DEPDIR)/swap.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/swap.Qo triangle_dat_SOURCES=triangle.r triangle_obj=$(triangle_dat_SOURCES:.r=.qfo) @@ -194,7 +211,8 @@ triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) triangle.run: Makefile build-run $(srcdir)/build-run $@ 100000 100000 1.00005 50002.4961 -include ./$(DEPDIR)/triangle.Qo +include ./$(DEPDIR)/triangle.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/triangle.Qo vecexpr_dat_SOURCES=vecexpr.r vecexpr_obj=$(vecexpr_dat_SOURCES:.r=.qfo) @@ -202,7 +220,8 @@ vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(vecexpr_obj) vecexpr.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/vecexpr.Qo +include ./$(DEPDIR)/vecexpr.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/vecexpr.Qo vecinit_dat_SOURCES=vecinit.r vecinit_obj=$(vecinit_dat_SOURCES:.r=.qfo) @@ -210,15 +229,8 @@ vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(vecinit_obj) vecinit.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/vecinit.Qo - -while_dat_SOURCES=while.r -while_obj=$(while_dat_SOURCES:.r=.qfo) -while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(while_obj) -while.run: Makefile build-run - $(srcdir)/build-run $@ -include ./$(DEPDIR)/while.Qo +include ./$(DEPDIR)/vecinit.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/vecinit.Qo voidfor_dat_SOURCES=voidfor.r voidfor_obj=$(voidfor_dat_SOURCES:.r=.qfo) @@ -226,8 +238,24 @@ voidfor.dat$(EXEEXT): $(voidfor_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj) voidfor.run: Makefile build-run $(srcdir)/build-run $@ -include ./$(DEPDIR)/voidfor.Qo +include ./$(DEPDIR)/voidfor.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/voidfor.Qo +while_dat_SOURCES=while.r +while_obj=$(while_dat_SOURCES:.r=.qfo) +while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(while_obj) +while.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/while.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/while.Qo + +$(r_depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + + +am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) EXTRA_DIST= test-bi.h build-run test-defspace.h CLEANFILES= *.dat *.sym *.qfo *.run *.frame From d29ea55826cfc748a750e8fbf7002d8299c79ae3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 13:02:36 +0900 Subject: [PATCH 0109/3664] Add a test for for loop declarations I think the compiler segfaulting indicates a test failure. --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/fordecl.r | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tools/qfcc/test/fordecl.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 469ba261a..87742d8e0 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -32,6 +32,7 @@ test_progs_dat=\ chewed-alias.dat \ chewed-return.dat \ deadbool.dat \ + fordecl.dat \ func-expr.dat \ func-static.dat \ infloop.dat \ @@ -97,6 +98,15 @@ deadbool.run: Makefile build-run include ./$(DEPDIR)/deadbool.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/deadbool.Qo +fordecl_dat_SOURCES=fordecl.r +fordecl_obj=$(fordecl_dat_SOURCES:.r=.qfo) +fordecl.dat$(EXEEXT): $(fordecl_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(fordecl_obj) +fordecl.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/fordecl.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/fordecl.Qo + func_expr_dat_SOURCES=func-expr.r func_expr_obj=$(func_expr_dat_SOURCES:.r=.qfo) func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/fordecl.r b/tools/qfcc/test/fordecl.r new file mode 100644 index 000000000..9277dc828 --- /dev/null +++ b/tools/qfcc/test/fordecl.r @@ -0,0 +1,26 @@ +void printf (string fmt, ...) = #0; + +int +test_fordecl () +{ + int fail = 1; + int count = 5; + + for (int i = 3, j = 5; count-- > 0; ) { + i += 2; + j += 3; + } + if (i == 13 && j == 20) { + fail = 0; + } + + return fail; +} + +int +main () +{ + int fail = 0; + fail |= test_fordecl (); + return fail; +} From ec89149b2902e328da28b96beb1e6ad9c5875b10 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 13:54:03 +0900 Subject: [PATCH 0110/3664] Build for loop decl inits correctly The multiple expressions are chained together and evaluate in left to right order. --- tools/qfcc/include/expr.h | 11 +++++++++++ tools/qfcc/source/expr.c | 14 ++++++++++++++ tools/qfcc/source/qc-parse.y | 15 ++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index f1987bb8a..d8831b766 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -314,6 +314,17 @@ expr_t *new_bool_expr (ex_list_t *true_list, ex_list_t *false_list, expr_t *e); */ expr_t *new_block_expr (void); +/** Create a new statement block expression node from an expression list + + The returned block holds the expression list in reverse order. This makes + it easy to build the list in a parser. + + \param expr_list The expression list to convert to an expression block. + Note that the evaluation order will be reversed. + \return The new block expression (::ex_block_t) node. +*/ +expr_t *build_block_expr (expr_t *expr_list); + /** Create a new binary expression node node. If either \a e1 or \a e2 are error expressions, then that expression will diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 104963189..c6bed8e39 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -539,6 +539,20 @@ new_binary_expr (int op, expr_t *e1, expr_t *e2) return e; } +expr_t * +build_block_expr (expr_t *expr_list) +{ + expr_t *b = new_block_expr (); + + while (expr_list) { + expr_t *e = expr_list; + expr_list = e->next; + e->next = 0; + append_expr (b, e); + } + return b; +} + expr_t * new_unary_expr (int op, expr_t *e1) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 945e3b5fb..8e9c38af8 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1153,6 +1153,9 @@ statement | FOR push_scope break_label continue_label '(' opt_init ';' opt_expr ';' opt_expr ')' statement pop_scope { + if ($6) { + $6 = build_block_expr ($6); + } $$ = build_for_statement ($6, $8, $10, $12, break_label, continue_label); break_label = $3; @@ -1234,12 +1237,22 @@ opt_init init_var_decl_list : init_var_decl - | init_var_decl_list ',' init_var_decl + { + printf ("a\n"); + $$ = $1; + } + | init_var_decl_list ',' { $$ = $0; } init_var_decl + { + printf ("b\n"); + $4->next = $1; + $$ = $4; + } ; init_var_decl : var_decl opt_initializer { + printf ("c\n"); specifier_t spec = $0; $1->type = append_type ($1->type, spec.type); $1->type = find_type ($1->type); From 1db600548e7406253e830e1e78e9fa50caf1516c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 13:55:07 +0900 Subject: [PATCH 0111/3664] Fix for decl test scope issue --- tools/qfcc/test/fordecl.r | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/test/fordecl.r b/tools/qfcc/test/fordecl.r index 9277dc828..70d57690a 100644 --- a/tools/qfcc/test/fordecl.r +++ b/tools/qfcc/test/fordecl.r @@ -5,12 +5,15 @@ test_fordecl () { int fail = 1; int count = 5; + int ti = -1, tj = -1; for (int i = 3, j = 5; count-- > 0; ) { i += 2; j += 3; + ti = i; + tj = j; } - if (i == 13 && j == 20) { + if (ti == 13 && tj == 20) { fail = 0; } From 33c2eb430fa098f438463a43a120e2e7bf7ac8f7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 16:19:27 +0900 Subject: [PATCH 0112/3664] Stop bison complaining about %expect And make sure warnings get fixed. --- tools/qfcc/source/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index b0bf53fb7..e63edc20d 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -33,7 +33,7 @@ QFCC_DEPS=@QFCC_DEPS@ QFCC_INCS=@QFCC_INCS@ AM_CPPFLAGS= -I$(top_srcdir)/include $(QFCC_INCS) -YFLAGS = -v -d +YFLAGS = -v -d -Wno-yacc -Werror bin_PROGRAMS= qfcc qfprogs bin_SCRIPTS= qfpreqcc From 689d1ad3ece314f9c07a2ea5a03de3bd106a1244 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 16:45:01 +0900 Subject: [PATCH 0113/3664] Remove some debug prints --- tools/qfcc/source/qc-parse.y | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 8e9c38af8..308512b6b 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1238,12 +1238,10 @@ opt_init init_var_decl_list : init_var_decl { - printf ("a\n"); $$ = $1; } | init_var_decl_list ',' { $$ = $0; } init_var_decl { - printf ("b\n"); $4->next = $1; $$ = $4; } @@ -1252,7 +1250,6 @@ init_var_decl_list init_var_decl : var_decl opt_initializer { - printf ("c\n"); specifier_t spec = $0; $1->type = append_type ($1->type, spec.type); $1->type = find_type ($1->type); From 7fce68649af1e2248f8658221bd2d29573548417 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 16:56:20 +0900 Subject: [PATCH 0114/3664] Implement comma expressions Doesn't quite work (attempt to suppress warning for return a = 3, 5; failed). --- tools/qfcc/source/qc-parse.y | 20 ++++++++++++--- tools/qfcc/test/Makefile.am | 10 ++++++++ tools/qfcc/test/comma-expr.r | 50 ++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 tools/qfcc/test/comma-expr.r diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 308512b6b..c8c269d27 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -180,7 +180,7 @@ int yylex (void); %type methoddef %type opt_initializer var_initializer local_def -%type opt_init opt_expr fexpr expr element_list element +%type opt_init opt_expr cexpr fexpr expr element_list element %type optional_state_expr texpr vector_expr %type statement statements compound_statement %type else label break_label continue_label @@ -1175,7 +1175,7 @@ statement break_label = $2; continue_label = $3; } - | fexpr ';' + | cexpr ';' { $$ = $1; } @@ -1227,7 +1227,7 @@ switch_block ; opt_init - : fexpr + : cexpr | type init_var_decl_list { $$ = $2; } | /* empty */ { @@ -1260,7 +1260,7 @@ init_var_decl ; opt_expr - : fexpr + : cexpr | /* empty */ { $$ = 0; @@ -1346,6 +1346,18 @@ texpr : fexpr { $$ = convert_bool ($1, 1); } ; +cexpr + : arg_list + { + if ($1->next) { + expr_t *res = $1; + $1 = build_block_expr ($1->next); + $1->e.block.result = res; + } + $$ = $1; + } + ; + opt_arg_list : /* emtpy */ { $$ = 0; } | arg_list { $$ = $1; } diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 87742d8e0..c0d7bade0 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -31,6 +31,7 @@ fail_bins= test_progs_dat=\ chewed-alias.dat \ chewed-return.dat \ + comma-expr.dat \ deadbool.dat \ fordecl.dat \ func-expr.dat \ @@ -89,6 +90,15 @@ chewed-return.run: Makefile build-run include ./$(DEPDIR)/chewed-return.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/chewed-return.Qo +comma_expr_dat_SOURCES=comma-expr.r +comma_expr_obj=$(comma_expr_dat_SOURCES:.r=.qfo) +comma-expr.dat$(EXEEXT): $(comma_expr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(comma_expr_obj) +comma-expr.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/comma-expr.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/comma-expr.Qo + deadbool_dat_SOURCES=deadbool.r deadbool_obj=$(deadbool_dat_SOURCES:.r=.qfo) deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/comma-expr.r b/tools/qfcc/test/comma-expr.r new file mode 100644 index 000000000..ea145c0a2 --- /dev/null +++ b/tools/qfcc/test/comma-expr.r @@ -0,0 +1,50 @@ +void printf (string fmt, ...) = #0; + +int a = 0; +int b = 0; + +int +return_comma() +{ + return a = 3, 5; +} + +int +test_for_comma () +{ + int fail = 1; + int count = 5; + int i = -1; + float j = -1; + + for (i = 3, j = 5; count-- > 0; ) { + i += 2; + j += 3; + } + if (i == 13 && j == 20) { + fail = 0; + } + + return fail; +} + +int +test_comma () +{ + int fail = 1; + if (return_comma() == 5) { + if (a == 3) { + fail = 0; + } + } + return fail; +} + +int +main () +{ + int fail = 0; + fail |= test_comma (); + fail |= test_for_comma (); + return fail; +} From f093516962c30923a3e184466d298d8148630623 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 18:07:58 +0900 Subject: [PATCH 0115/3664] Move qfo type encoding structs This makes them available to the gamecode VM, and thus the debugger. --- include/QF/Makefile.am | 3 +- include/QF/pr_type.h | 107 ++++++++++++++++++++++++++++++++++ tools/qfcc/include/obj_type.h | 71 +--------------------- 3 files changed, 110 insertions(+), 71 deletions(-) create mode 100644 include/QF/pr_type.h diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am index ffb0ff56b..8bf956359 100644 --- a/include/QF/Makefile.am +++ b/include/QF/Makefile.am @@ -6,7 +6,8 @@ nobase_pkginclude_HEADERS = \ idparse.h image.h in_event.h info.h input.h iqm.h joystick.h keys.h \ link.h llist.h locs.h mathlib.h mdfour.h mersenne.h model.h modelgen.h \ msg.h object.h pak.h pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h \ - pr_obj.h progs.h qargs.h qdefs.h qendian.h qfplist.h qtypes.h quakefs.h \ + pr_obj.h pr_type.h progs.h qargs.h qdefs.h qendian.h qfplist.h qtypes.h \ + quakefs.h \ quakeio.h render.h riff.h ruamoko.h screen.h script.h segtext.h set.h \ sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h tga.h uint32.h va.h \ ver_check.h vid.h vrect.h view.h wad.h wadfile.h winding.h zone.h \ diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h new file mode 100644 index 000000000..8e3f771df --- /dev/null +++ b/include/QF/pr_type.h @@ -0,0 +1,107 @@ +/* + pr_type.h + + object file type encoding support + + Copyright (C) 2011 Bill Currie + + Author: Bill Currie + Date: 2011/02/18 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __pr_type_h +#define __pr_type_h + +/** \defgroup qfcc_qfo_type Object file type encoding + \ingroup progs + + All \c pointer_t \c type fields are pointers within the type qfo_space. +*/ +//@{ + +#include "QF/pr_comp.h" + +typedef struct qfot_fldptr_s { + pr_int_t type; ///< ev_field or ev_pointer + pointer_t aux_type; ///< referenced type +} qfot_fldptr_t; + +typedef struct qfot_func_s { + pr_int_t type; ///< always ev_func + pointer_t return_type; ///< return type of the function + pr_int_t num_params; ///< ones compliment count of the + ///< parameters. -ve values indicate the + ///< number of real parameters before the + ///< ellipsis + pointer_t param_types[1]; ///< variable length list of parameter + ///< types +} qfot_func_t; + +typedef struct qfot_var_s { + pointer_t type; ///< type of field or self reference for + ///< enum + string_t name; ///< name of field/enumerator + pr_int_t offset; ///< value for enum, 0 for union +} qfot_var_t; + +typedef struct qfot_struct_s { + string_t tag; ///< struct/union/enum tag + pr_int_t num_fields; ///< number of fields/enumerators + qfot_var_t fields[1]; ///< variable length list of + ///< fields/enumerators +} qfot_struct_t; + +typedef struct qfot_array_s { + pointer_t type; ///< element type + pr_int_t base; ///< start index of array + pr_int_t size; ///< number of elements in array +} qfot_array_t; + +/** QFO type encoding. + + \note As this holds a union of all type representations, and those + representations may contain variable arrays, sizeof() will return only + one, rather useless, value. It is also not suitable for direct use in + arrays. +*/ +typedef struct qfot_type_s { + pr_int_t ty; ///< meta type: ty_meta_e + pr_int_t size; ///< total word size of this encoding + string_t encoding; ///< Objective-QC encoding + union { + pr_int_t type; ///< basic type: etype_t + qfot_fldptr_t fldptr; ///< ty_none, ev_pointer/ev_field + qfot_func_t func; ///< ty_none, ev_func + qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum + qfot_array_t array; ///< ty_array + pointer_t class; ///< ty_class + } t; +} qfot_type_t; + +typedef struct qfot_type_encodings_s { + pointer_t types; + pr_int_t size; +} qfot_type_encodings_t; + +//@} + +#endif//__pr_type_h diff --git a/tools/qfcc/include/obj_type.h b/tools/qfcc/include/obj_type.h index 1e559f45e..d9c677641 100644 --- a/tools/qfcc/include/obj_type.h +++ b/tools/qfcc/include/obj_type.h @@ -31,79 +31,10 @@ #ifndef __obj_type_h #define __obj_type_h -/** \defgroup qfcc_qfo_type Object file type encoding - \ingroup qfcc_qfo - - All \c pointer_t \c type fields are pointers within the type qfo_space. -*/ -//@{ - -#include "QF/pr_comp.h" +#include "QF/pr_type.h" #include "type.h" -typedef struct qfot_fldptr_s { - pr_int_t type; ///< ev_field or ev_pointer - pointer_t aux_type; ///< referenced type -} qfot_fldptr_t; - -typedef struct qfot_func_s { - pr_int_t type; ///< always ev_func - pointer_t return_type; ///< return type of the function - pr_int_t num_params; ///< ones compliment count of the - ///< parameters. -ve values indicate the - ///< number of real parameters before the - ///< ellipsis - pointer_t param_types[1]; ///< variable length list of parameter - ///< types -} qfot_func_t; - -typedef struct qfot_var_s { - pointer_t type; ///< type of field or self reference for - ///< enum - string_t name; ///< name of field/enumerator - pr_int_t offset; ///< value for enum, 0 for union -} qfot_var_t; - -typedef struct qfot_struct_s { - string_t tag; ///< struct/union/enum tag - pr_int_t num_fields; ///< number of fields/enumerators - qfot_var_t fields[1]; ///< variable length list of - ///< fields/enumerators -} qfot_struct_t; - -typedef struct qfot_array_s { - pointer_t type; ///< element type - pr_int_t base; ///< start index of array - pr_int_t size; ///< number of elements in array -} qfot_array_t; - -/** QFO type encoding. - - \note As this holds a union of all type representations, and those - representations may contain variable arrays, sizeof() will return only - one, rather useless, value. It is also not suitable for direct use in - arrays. -*/ -typedef struct qfot_type_s { - pr_int_t ty; ///< meta type: ty_meta_e - pr_int_t size; ///< total word size of this encoding - string_t encoding; ///< Objective-QC encoding - union { - pr_int_t type; ///< basic type: etype_t - qfot_fldptr_t fldptr; ///< ty_none, ev_pointer/ev_field - qfot_func_t func; ///< ty_none, ev_func - qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum - qfot_array_t array; ///< ty_array - pointer_t class; ///< ty_class - } t; -} qfot_type_t; - -typedef struct qfot_type_encodings_s { - pointer_t types; - pr_int_t size; -} qfot_type_encodings_t; - struct type_s; struct def_s *qfo_encode_type (struct type_s *type); From 2ee36e8b9927f0a8fd6f37f38101ff1f92c402c0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 18:10:07 +0900 Subject: [PATCH 0116/3664] Rename qfot_type_t.ty to meta When I did up a ruamoko implementation of a type encoding dumper, I named the field meta, which feels much better than ty. --- include/QF/pr_type.h | 2 +- tools/qfcc/source/dump_globals.c | 10 +++++----- tools/qfcc/source/linker.c | 2 +- tools/qfcc/source/obj_file.c | 6 +++--- tools/qfcc/source/obj_type.c | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index 8e3f771df..4cc6cf82e 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -84,7 +84,7 @@ typedef struct qfot_array_s { arrays. */ typedef struct qfot_type_s { - pr_int_t ty; ///< meta type: ty_meta_e + pr_int_t meta; ///< meta type: ty_meta_e pr_int_t size; ///< total word size of this encoding string_t encoding; ///< Objective-QC encoding union { diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 4361b7a57..71b769629 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -445,17 +445,17 @@ dump_qfo_types (qfo_t *qfo, int base_address) qfo->spaces[qfo_type_space].data_size); continue; } - if (type->ty < 0 || type->ty >= NUM_META) - meta = va ("invalid meta: %d", type->ty); + if (type->meta < 0 || type->meta >= NUM_META) + meta = va ("invalid meta: %d", type->meta); else - meta = ty_meta_names[type->ty]; + meta = ty_meta_names[type->meta]; printf ("%-5x %-9s %-20s", type_ptr + base_address, meta, QFO_TYPESTR (qfo, type_ptr)); - if (type->ty < 0 || type->ty >= NUM_META) { + if (type->meta < 0 || type->meta >= NUM_META) { puts (""); break; } - switch ((ty_meta_e) type->ty) { + switch ((ty_meta_e) type->meta) { case ty_none: printf (" %-10s", (type->t.type < 0 || type->t.type >= ev_type_count) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 4d1c86e31..3f07ba7b0 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -414,7 +414,7 @@ process_type_def (defref_t *ref, qfo_mspace_t *space, qfo_def_t *old) // mark the old type encoding as having been transfered, and save the // new address in the encoding's class field so def and function types // can be updated easily. - old_type->ty = -1; + old_type->meta = -1; old_type->t.class = REF (ref)->offset; } } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 428b733dc..10ca126f9 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -646,7 +646,7 @@ get_def_type (qfo_t *qfo, pointer_t type) if (type >= qfo->spaces[qfo_type_space].data_size) return ev_void; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); - switch ((ty_meta_e)type_def->ty) { + switch ((ty_meta_e)type_def->meta) { case ty_none: // field, pointer and function types store their basic type in // the same location. @@ -673,7 +673,7 @@ get_type_size (qfo_t *qfo, pointer_t type) if (type >= qfo->spaces[qfo_type_space].data_size) return 1; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); - switch ((ty_meta_e)type_def->ty) { + switch ((ty_meta_e)type_def->meta) { case ty_none: // field, pointer and function types store their basic type in // the same location. @@ -711,7 +711,7 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) if (func->type >= qfo->spaces[qfo_type_space].data_size) return; type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); - if (type->ty != ty_none && type->t.type != ev_func) + if (type->meta != ty_none && type->t.type != ev_func) return; df->numparms = num_params = type->t.func.num_params; if (num_params < 0) diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 2b77a864f..55da5c137 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -87,7 +87,7 @@ qfo_new_encoding (type_t *type, int size) def->offset = defspace_alloc_loc (pr.type_data, size); enc = D_POINTER (qfot_type_t, def); - enc->ty = type->meta; + enc->meta = type->meta; enc->size = size; ENC_STR (enc->encoding, type->encoding); return def; From f68129dc0f457aac9964f1e30994feac0d773174 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 18:11:56 +0900 Subject: [PATCH 0117/3664] Try to use type encodings for function return type Now return statements in traces make much more sense. --- libs/gamecode/pr_debug.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 9f5cdc818..8973e318c 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -46,6 +46,7 @@ #include "QF/hash.h" #include "QF/mathlib.h" #include "QF/pr_debug.h" +#include "QF/pr_type.h" #include "QF/progs.h" #include "QF/qendian.h" #include "QF/quakefs.h" @@ -514,6 +515,26 @@ get_aux_function (progs_t *pr) return pr->auxfunction_map[func - pr->pr_functions]; } +static etype_t +get_etype (progs_t *pr, int typeptr) +{ + //FIXME cache .type_encodings def + ddef_t *te_def = PR_FindGlobal (pr, ".type_encodings"); + qfot_type_encodings_t *encodings; + qfot_type_t *type; + + if (!te_def) { + // can't decode the type, so make no assumptions about it + return typeptr; + } + encodings = &G_STRUCT (pr, qfot_type_encodings_t, te_def->ofs); + type = &G_STRUCT (pr, qfot_type_t, encodings->types + typeptr); + if (type->meta == 0) { + return type->t.type; + } + return ev_void; +} + ddef_t * PR_Get_Local_Def (progs_t *pr, pr_int_t offs) { @@ -885,7 +906,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) optype = ev_void; aux_func = get_aux_function (pr); if (aux_func) - optype = aux_func->return_type; + optype = get_etype (pr, aux_func->return_type); str = global_string (pr, opval, optype, contents & 1); break; case 'F': From b7b6a89b91754ce28905f4a94cb01fe60f82b30d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 19:20:35 +0900 Subject: [PATCH 0118/3664] Simplify fold_constants While this does break automatic type promotion, it does stop fold_constants recursing through complex expressions: only the top level expression needs to be folded, and then only if both sides are actually constant. --- tools/qfcc/source/constfold.c | 78 +++++++++++------------------------ 1 file changed, 23 insertions(+), 55 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index f44cb2b68..c4816907e 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1456,34 +1456,12 @@ fold_constants (expr_t *e) expr_t *e1, *e2; etype_t t1, t2; - if (e->type == ex_block) { - expr_t *block = new_block_expr (); - expr_t *next; - - block->e.block.result = e->e.block.result; - block->line = e->line; - block->file = e->file; - - for (e = e->e.block.head; e; e = next) { - next = e->next; - e = fold_constants (e); - e->next = 0; - append_expr (block, e); - } - - return block; - } - if (e->type == ex_bool) { - e->e.bool.e = fold_constants (e->e.bool.e); - return e; - } if (e->type == ex_uexpr) { - if (!e->e.expr.e1) + e1 = e->e.expr.e1; + if (!e1 || !is_constant (e1)) { return e; + } op = e->e.expr.op; - e->e.expr.e1 = e1 = fold_constants (e->e.expr.e1); - if (e1->type == ex_error) - return e1; if (op == 'A' || op == 'g' || op == 'r') return e; t1 = extract_type (e1); @@ -1492,35 +1470,25 @@ fold_constants (expr_t *e) internal_error (e, "invalid type: %d", t1); } return do_unary_op[t1] (op, e, e1); + } else if (e->type == ex_expr) { + e1 = e->e.expr.e1; + e2 = e->e.expr.e2; + if (!is_constant (e1) || !is_constant (e2)) { + return e; + } + + op = e->e.expr.op; + if (op == 'i' || op == 'n' || op == 'c' || op == 's') { + return e; + } + + t1 = extract_type (e1); + t2 = extract_type (e2); + + if (t1 >= ev_type_count || t2 >= ev_type_count + || !do_op[t1] || !do_op[t1][t2]) + internal_error (e, "invalid type"); + return do_op[t1][t2] (op, e, e1, e2); } - - if (e->type != ex_expr) - return e; - - op = e->e.expr.op; - - e->e.expr.e1 = e1 = fold_constants (e->e.expr.e1); - if (e1->type == ex_error) - return e1; - t1 = extract_type (e1); - - if (op == 'i' || op == 'n' || op == 'c') - return e; - - e->e.expr.e2 = e2 = fold_constants (e->e.expr.e2); - if (e2->type == ex_error) - return e2; - - if (e2->type == ex_label || e2->type == ex_labelref) - return e; - - t2 = extract_type (e2); - - if (op == 's') - return e; - - if (t1 >= ev_type_count || t2 >= ev_type_count - || !do_op[t1] || !do_op[t1][t2]) - internal_error (e, "invalid type"); - return do_op[t1][t2] (op, e, e1, e2); + return e; } From d9c96862883926e89e6cb11fb61cdab109c8ffcf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 19:23:23 +0900 Subject: [PATCH 0119/3664] Make initialized globals non-constant This is for modern code. Traditional code still treats initialized globals as constant and nosave. This will make a bit of a mess of modern code that expects traditional behavior. --- tools/qfcc/source/def.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 1bc1faf81..6b4b6449f 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -578,8 +578,11 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, type_size (sym->type) * sizeof (pr_type_t)); } } - sym->s.def->initialized = sym->s.def->constant = 1; - sym->s.def->nosave = 1; + sym->s.def->initialized = 1; + if (options.traditional) { + sym->s.def->constant = 1; + sym->s.def->nosave = 1; + } } } sym->s.def->initializer = init; From e849c2d1ceb1bf9fd297ca5fbedf38805f285932 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 19:29:21 +0900 Subject: [PATCH 0120/3664] Mark block expr result as rvalue when used as one At least for return. There may be other cases that need it, but this fixes comma-expr.r (minus int->float promotion issues). --- tools/qfcc/source/expr.c | 3 +++ tools/qfcc/source/qc-parse.y | 2 +- tools/qfcc/source/statements.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c6bed8e39..257d5bd19 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2021,6 +2021,9 @@ return_expr (function_t *f, expr_t *e) if (e->type == ex_vector) { e = assign_expr (new_temp_def_expr (t), e); } + if (e->type == ex_block) { + e->e.block.result->rvalue = 1; + } return new_unary_expr ('r', e); } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index c8c269d27..cb1b28ea3 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1351,7 +1351,7 @@ cexpr { if ($1->next) { expr_t *res = $1; - $1 = build_block_expr ($1->next); + $1 = build_block_expr ($1); $1->e.block.result = res; } $$ = $1; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index f78575fe0..948b5558f 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1273,7 +1273,7 @@ statement_uexpr (sblock_t *sblock, expr_t *e) static sblock_t * statement_nonexec (sblock_t *sblock, expr_t *e) { - if (options.warnings.executable) + if (!e->rvalue && options.warnings.executable) warning (e, "Non-executable statement; executing programmer instead."); return sblock; } From 8cef85e5de451c4e00c298c5e9d64f16fe248288 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 20:12:50 +0900 Subject: [PATCH 0121/3664] Cast scalar types when necessary on assignment This fixes type promotion errors that broke some tests. --- tools/qfcc/source/expr_assign.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 7cf1d8b4d..1662d6b10 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -142,7 +142,15 @@ check_types_compatible (expr_t *dst, expr_t *src) type_t *dst_type = get_type (dst); type_t *src_type = get_type (src); + if (dst_type == src_type) { + return 0; + } + if (type_assignable (dst_type, src_type)) { + if (is_scalar (dst_type) && is_scalar (src_type)) { + // the types are different but cast-compatible + return assign_expr (dst, cast_expr (dst_type, src)); + } return 0; } // traditional qcc is a little sloppy From f49303e774c8b6696048a610210cd0a04bfece99 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 21:21:41 +0900 Subject: [PATCH 0122/3664] Emit code for address expressions It helps if the necessary code is actually emitted in the first place. --- tools/qfcc/source/expr.c | 1 + tools/qfcc/source/statements.c | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 257d5bd19..9bc14fa9d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2238,6 +2238,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) return new_label_ref (&e1->e.label); case ex_temp: e = new_unary_expr ('&', e1); + e->e.expr.type = pointer_type (t); break; default: return error (e1, "invalid type for unary &"); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 948b5558f..79f2ba3d3 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -706,10 +706,12 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) static sblock_t * expr_address (sblock_t *sblock, expr_t *e, operand_t **op) { - if (e->type == ex_uexpr) { - sblock = statement_subexpr (sblock, e->e.expr.e1, op); - (*op)->type = ev_pointer; - } + statement_t *s; + s = new_statement (st_expr, "&", e); + sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); + s->opc = temp_operand (e->e.expr.type); + sblock_add_statement (sblock, s); + *(op) = s->opc; return sblock; } From 6253623e9b5909fe0b2d7bf7691d422b5e38ede4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 21:23:06 +0900 Subject: [PATCH 0123/3664] Remove some weird dereference code It appears to have been an attempt at optimizing dereferences, but it instead just utterly mangled them. --- tools/qfcc/source/statements.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 79f2ba3d3..fb55412e1 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -567,11 +567,6 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) sblock = statement_subexpr (sblock, dst_expr->e.expr.e1, &dst); sblock = statement_subexpr (sblock, dst_expr->e.expr.e2, &ofs); } else { - if (dst_expr->type == ex_uexpr - && dst_expr->e.expr.op == '&') { - opcode = "="; - dst_expr = unary_expr ('.', dst_expr); - } sblock = statement_subexpr (sblock, dst_expr, &dst); ofs = 0; } From e46a44d9c641ed1efa020724259f98ea6fc0b038 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 21:25:03 +0900 Subject: [PATCH 0124/3664] Update TODO --- tools/qfcc/TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/TODO b/tools/qfcc/TODO index ed68de57c..5bce50696 100644 --- a/tools/qfcc/TODO +++ b/tools/qfcc/TODO @@ -12,7 +12,7 @@ M unnamed function parameters for prototypes/typdefs etc. I optimizations (esp CSE) I fix used/uninitialized warnings o id id; -o vec = [x, y, z]; expressions (nice feature in fteqcc) +M vec = [x, y, z]; expressions (nice feature in fteqcc) M finish -Fifstring o isset() intrinsic for more consistent string handling. o arrays in entities From f70801fa52dbf4bb414a70ba35d07bb1356d49b4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 21:44:58 +0900 Subject: [PATCH 0125/3664] Add a test for accessing an array in a struct That's accessed via a pointer. Whee. However, at this stage, the problem is really a promotion issue for short -> integer. --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/structarray.r | 20 ++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tools/qfcc/test/structarray.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index c0d7bade0..0e9e39e81 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -43,6 +43,7 @@ test_progs_dat=\ return-ivar.dat \ sendv.dat \ state.dat \ + structarray.dat \ structlive.dat \ structptr.dat \ swap.dat \ @@ -198,6 +199,15 @@ state.run: Makefile build-run include ./$(DEPDIR)/state.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/state.Qo +structarray_dat_SOURCES=structarray.r +structarray_obj=$(structarray_dat_SOURCES:.r=.qfo) +structarray.dat$(EXEEXT): $(structarray_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(structarray_obj) +structarray.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/structarray.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/structarray.Qo + structlive_dat_SOURCES=structlive.r structlive_obj=$(structlive_dat_SOURCES:.r=.qfo) structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/structarray.r b/tools/qfcc/test/structarray.r new file mode 100644 index 000000000..d6c67171a --- /dev/null +++ b/tools/qfcc/test/structarray.r @@ -0,0 +1,20 @@ +void printf (string fmt, ...) = #0; +void *obj_malloc (int size) = #0; + +typedef struct { + int val; + int cap; + int ofs[]; +} valstruct_t; + +valstruct_t *vs; +int dst; + +int +main () +{ + for (int i = 0; i < 2; i++) { + dst = vs.ofs[i]; + } + return 1; +} From 227ac46ffe972a990e7d78a0fcb7d7c113194c0b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 22:25:55 +0900 Subject: [PATCH 0126/3664] Clean up array expression processing And make sure constants are folded since fold_constants is no longer recursive. --- tools/qfcc/source/expr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 9bc14fa9d..609d602e0 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2106,6 +2106,8 @@ array_expr (expr_t *array, expr_t *index) type_t *array_type = get_type (array); type_t *index_type = get_type (index); expr_t *scale; + expr_t *offset; + expr_t *base; expr_t *e; int ind = 0; @@ -2128,12 +2130,10 @@ array_expr (expr_t *array, expr_t *index) || ind - array_type->t.array.base >= array_type->t.array.size)) return error (index, "array index out of bounds"); scale = new_integer_expr (type_size (array_type->t.array.type)); - index = binary_expr ('*', index, scale); - index = binary_expr ('-', index, - binary_expr ('*', - new_integer_expr (array_type->t.array.base), - scale)); - index = fold_constants (index); + index = fold_constants (binary_expr ('*', index, scale)); + base = new_integer_expr (array_type->t.array.base); + offset = fold_constants (binary_expr ('*', base, scale)); + index = fold_constants (binary_expr ('-', index, offset)); if (is_short_val (index)) ind = expr_short (index); if (is_integer_val (index)) From 439cd15620af1c556aeeec9b722b660ba6e2f90f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 22:26:57 +0900 Subject: [PATCH 0127/3664] Do type promotion for short fold_constants used to do this when it was overly aggressive. Fixes the ICE when accessing an array in a struct via a pointer. --- tools/qfcc/source/expr_binary.c | 88 ++++++++++++++++----------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index b3717c1e8..8b0c5a485 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -269,22 +269,22 @@ static expr_type_t integer_uinteger[] = { }; static expr_type_t integer_short[] = { - {'+', &type_integer}, - {'-', &type_integer}, - {'*', &type_integer}, - {'/', &type_integer}, - {'&', &type_integer}, - {'|', &type_integer}, - {'^', &type_integer}, - {'%', &type_integer}, - {SHL, &type_integer}, - {SHR, &type_integer}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {'+', &type_integer, 0, &type_integer}, + {'-', &type_integer, 0, &type_integer}, + {'*', &type_integer, 0, &type_integer}, + {'/', &type_integer, 0, &type_integer}, + {'&', &type_integer, 0, &type_integer}, + {'|', &type_integer, 0, &type_integer}, + {'^', &type_integer, 0, &type_integer}, + {'%', &type_integer, 0, &type_integer}, + {SHL, &type_integer, 0, &type_integer}, + {SHR, &type_integer, 0, &type_integer}, + {EQ, &type_integer, 0, &type_integer}, + {NE, &type_integer, 0, &type_integer}, + {LE, &type_integer, 0, &type_integer}, + {GE, &type_integer, 0, &type_integer}, + {LT, &type_integer, 0, &type_integer}, + {GT, &type_integer, 0, &type_integer}, {0, 0} }; @@ -340,42 +340,42 @@ static expr_type_t uinteger_uinteger[] = { #define short_quat integer_quat static expr_type_t short_integer[] = { - {'+', &type_integer}, - {'-', &type_integer}, - {'*', &type_integer}, - {'/', &type_integer}, - {'&', &type_integer}, - {'|', &type_integer}, - {'^', &type_integer}, - {'%', &type_integer}, + {'+', &type_integer, &type_integer, 0}, + {'-', &type_integer, &type_integer, 0}, + {'*', &type_integer, &type_integer, 0}, + {'/', &type_integer, &type_integer, 0}, + {'&', &type_integer, &type_integer, 0}, + {'|', &type_integer, &type_integer, 0}, + {'^', &type_integer, &type_integer, 0}, + {'%', &type_integer, &type_integer, 0}, {SHL, &type_short}, {SHR, &type_short}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {EQ, &type_integer, &type_integer, 0}, + {NE, &type_integer, &type_integer, 0}, + {LE, &type_integer, &type_integer, 0}, + {GE, &type_integer, &type_integer, 0}, + {LT, &type_integer, &type_integer, 0}, + {GT, &type_integer, &type_integer, 0}, {0, 0} }; static expr_type_t short_uinteger[] = { - {'+', &type_uinteger}, - {'-', &type_uinteger}, - {'*', &type_uinteger}, - {'/', &type_uinteger}, - {'&', &type_uinteger}, - {'|', &type_uinteger}, - {'^', &type_uinteger}, - {'%', &type_uinteger}, + {'+', &type_uinteger, &type_uinteger, 0}, + {'-', &type_uinteger, &type_uinteger, 0}, + {'*', &type_uinteger, &type_uinteger, 0}, + {'/', &type_uinteger, &type_uinteger, 0}, + {'&', &type_uinteger, &type_uinteger, 0}, + {'|', &type_uinteger, &type_uinteger, 0}, + {'^', &type_uinteger, &type_uinteger, 0}, + {'%', &type_uinteger, &type_uinteger, 0}, {SHL, &type_short}, {SHR, &type_short}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {EQ, &type_integer, &type_uinteger, 0}, + {NE, &type_integer, &type_uinteger, 0}, + {LE, &type_integer, &type_uinteger, 0}, + {GE, &type_integer, &type_uinteger, 0}, + {LT, &type_integer, &type_uinteger, 0}, + {GT, &type_integer, &type_uinteger, 0}, {0, 0} }; From c98d1ff08c8551d861c1434453ce60c211598e94 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 22:29:51 +0900 Subject: [PATCH 0128/3664] Document some problems with nil While he's a pretty cool character in HZD, he seems to have some identity problems when in a compiler. --- ruamoko/cl_menu/plistmenu.r | 2 +- tools/qfcc/source/problem_with_nil.txt | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tools/qfcc/source/problem_with_nil.txt diff --git a/ruamoko/cl_menu/plistmenu.r b/ruamoko/cl_menu/plistmenu.r index 04d4355b7..d5e722377 100644 --- a/ruamoko/cl_menu/plistmenu.r +++ b/ruamoko/cl_menu/plistmenu.r @@ -142,7 +142,7 @@ string_from_plist (PLString *plstring) local @param ret; local string str = [plstring string]; - ret.quaternion_val = nil; //FIXME should be ret = nil; + ret = nil; //FIXME should be ret = nil; if (str_mid (str, 0, 1) == "[") return rect_from_plist (plstring); diff --git a/tools/qfcc/source/problem_with_nil.txt b/tools/qfcc/source/problem_with_nil.txt new file mode 100644 index 000000000..4172aea0e --- /dev/null +++ b/tools/qfcc/source/problem_with_nil.txt @@ -0,0 +1,12 @@ +The problem with nil is more a problem with @param and values. + +@param values used type_nil's low-level type, which is either quaternion +or vector (v6 progs). Thus returning (or passing?) nil through @param +creates a value that has type_param built low-level type quaternion. +Then assigning nil to a quaternion finds the param nil (because the +value and low-level type is checked) which has the wrong type for type +checks. + +one solution is to create an ev_param type (convert to quaternion or +vector for v6 progs) that the VM either ignores or can copy around +ev_param data. From 3196bcc851c327829ded885f3fd2656e3c3b1a59 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 22:34:23 +0900 Subject: [PATCH 0129/3664] Allow fold_constants to handle some math identities Such as x*0 -> 0, x*1 -> x, x+0 ->x, etc. --- tools/qfcc/source/constfold.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index c4816907e..33746c8e9 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1458,7 +1458,7 @@ fold_constants (expr_t *e) if (e->type == ex_uexpr) { e1 = e->e.expr.e1; - if (!e1 || !is_constant (e1)) { + if (!e1) { return e; } op = e->e.expr.op; @@ -1473,7 +1473,7 @@ fold_constants (expr_t *e) } else if (e->type == ex_expr) { e1 = e->e.expr.e1; e2 = e->e.expr.e2; - if (!is_constant (e1) || !is_constant (e2)) { + if (!is_constant (e1) && !is_constant (e2)) { return e; } From 00f12263cafd73c51f7146624c80bca6bb1294de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 22:55:38 +0900 Subject: [PATCH 0130/3664] Fix casting arrays to pointers --- tools/qfcc/source/expr.c | 5 +++-- tools/qfcc/test/structarray.r | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 609d602e0..74a81369f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2537,8 +2537,9 @@ cast_expr (type_t *type, expr_t *e) && !(is_scalar (type) && is_scalar (e_type))) { return cast_error (e, e_type, type); } - if (is_array (e_type)) - return address_expr (e, 0, 0); + if (is_array (e_type)) { + return address_expr (e, 0, type->t.fldptr.type); + } if (is_constant (e) && is_scalar (type) && is_scalar (e_type)) { ex_value_t *val = 0; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) { diff --git a/tools/qfcc/test/structarray.r b/tools/qfcc/test/structarray.r index d6c67171a..7cdb58d99 100644 --- a/tools/qfcc/test/structarray.r +++ b/tools/qfcc/test/structarray.r @@ -7,14 +7,17 @@ typedef struct { int ofs[]; } valstruct_t; +int foo[5] = {1, 2, 3, 4, 5}; valstruct_t *vs; int dst; int main () { + vs = (valstruct_t *)foo; for (int i = 0; i < 2; i++) { dst = vs.ofs[i]; } - return 1; + printf("dst = %d\n", dst); + return dst != 4; } From 28a2b968005a0908e9731a21dc6a29045f8809b0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jun 2019 23:11:38 +0900 Subject: [PATCH 0131/3664] Implement automatic array sizing from initializer --- tools/qfcc/source/def.c | 15 +++++++++++++++ tools/qfcc/test/structarray.r | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 6b4b6449f..4c16060ea 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -483,6 +483,16 @@ init_field_def (def_t *def, expr_t *init, storage_class_t storage) } } +static int +num_elements (expr_t *e) +{ + int count = 0; + for (e = e->e.block.head; e; e = e->next) { + count++; + } + return count; +} + void initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, storage_class_t storage) @@ -520,6 +530,11 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, sym->s.def = 0; } if (!sym->s.def) { + if (is_array (sym->type) && !type_size (sym->type) + && init->type == ex_block && !init->e.block.result) { + sym->type = array_type (sym->type->t.array.type, + num_elements (init)); + } sym->s.def = new_def (sym->name, sym->type, space, storage); reloc_attach_relocs (relocs, &sym->s.def->relocs); } diff --git a/tools/qfcc/test/structarray.r b/tools/qfcc/test/structarray.r index 7cdb58d99..74d64214e 100644 --- a/tools/qfcc/test/structarray.r +++ b/tools/qfcc/test/structarray.r @@ -7,7 +7,7 @@ typedef struct { int ofs[]; } valstruct_t; -int foo[5] = {1, 2, 3, 4, 5}; +int foo[] = {1, 2, 3, 4, 5}; valstruct_t *vs; int dst; @@ -19,5 +19,5 @@ main () dst = vs.ofs[i]; } printf("dst = %d\n", dst); - return dst != 4; + return sizeof(foo) != 5 || dst != 4; } From bf0543f7fbf9c534becc710b3d7ea9fd062da5f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 00:19:48 +0900 Subject: [PATCH 0132/3664] Be paranoid about temp var sizes Prevents array index errors. --- tools/qfcc/source/def.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 4c16060ea..facf82348 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -199,6 +199,9 @@ temp_def (etype_t type, int size) def_t *temp; defspace_t *space = current_func->symtab->space; + if (size < 1 || size > 4) { + internal_error (0, "%d invalid size for temp def", size); + } if ((temp = current_func->temp_defs[size - 1])) { current_func->temp_defs[size - 1] = temp->temp_next; temp->temp_next = 0; From ef4ad52239f9be8ca68987b8a85f698b806444f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 00:36:13 +0900 Subject: [PATCH 0133/3664] Make binary_expr fold constants This is where constant folding should have happened all along. While unary_expr should fold constants too, it seems to already try to do so and it's a bit much of a mess to clean up right now. --- tools/qfcc/source/expr.c | 8 ++++---- tools/qfcc/source/expr_binary.c | 35 ++++++++++++++++++++++++++++----- tools/qfcc/source/qc-parse.y | 33 +++++++++++++------------------ tools/qfcc/source/switch.c | 2 -- 4 files changed, 48 insertions(+), 30 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 74a81369f..e2225d2bc 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1280,7 +1280,7 @@ test_expr (expr_t *e) new = binary_expr (NE, e, new); new->line = e->line; new->file = e->file; - return fold_constants (new); + return new; } void @@ -2130,10 +2130,10 @@ array_expr (expr_t *array, expr_t *index) || ind - array_type->t.array.base >= array_type->t.array.size)) return error (index, "array index out of bounds"); scale = new_integer_expr (type_size (array_type->t.array.type)); - index = fold_constants (binary_expr ('*', index, scale)); + index = binary_expr ('*', index, scale); base = new_integer_expr (array_type->t.array.base); - offset = fold_constants (binary_expr ('*', base, scale)); - index = fold_constants (binary_expr ('-', index, offset)); + offset = binary_expr ('*', base, scale); + index = binary_expr ('-', index, offset); if (is_short_val (index)) ind = expr_short (index); if (is_integer_val (index)) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 8b0c5a485..d53d3677c 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -42,8 +42,11 @@ typedef struct { type_t *type; type_t *a_cast; type_t *b_cast; + expr_t *(*process)(int op, expr_t *e1, expr_t *e2); } expr_type_t; +static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2); + static expr_type_t string_string[] = { {'+', &type_string}, {EQ, &type_integer}, @@ -157,8 +160,8 @@ static expr_type_t pointer_pointer[] = { }; static expr_type_t pointer_integer[] = { - {'+', &type_pointer}, - {'-', &type_pointer}, + {'+', 0, 0, 0, pointer_arithmetic}, + {'-', 0, 0, 0, pointer_arithmetic}, {0, 0} }; #define pointer_uinteger pointer_integer @@ -218,7 +221,7 @@ static expr_type_t integer_vector[] = { }; static expr_type_t integer_pointer[] = { - {'+', &type_pointer}, + {'+', &type_pointer, 0, &type_integer}, {0, 0} }; @@ -579,6 +582,25 @@ static expr_type_t **binary_expr_types[] = { short_x, }; +static expr_t * +pointer_arithmetic (int op, expr_t *e1, expr_t *e2) +{ + expr_t *e; + type_t *ptype = get_type (e1); + + if (!is_pointer (ptype)) { + ptype = get_type (e2); + } + if (!is_pointer (ptype)) { + internal_error (e1, "pointer arithmetic on non-pointers"); + } + + e1 = cast_expr (&type_integer, e1); + e2 = cast_expr (&type_integer, e2); + e = binary_expr (op, e1, e2); + return cast_expr (ptype, e); +} + static expr_t * invalid_binary_expr (int op, expr_t *e1, expr_t *e2) { @@ -780,9 +802,12 @@ binary_expr (int op, expr_t *e1, expr_t *e2) e1 = cast_expr (expr_type->a_cast, e1); if (expr_type->b_cast) e2 = cast_expr (expr_type->b_cast, e2); + if (expr_type->process) { + return fold_constants (expr_type->process (op, e1, e2)); + } if ((e = reimplement_binary_expr (op, e1, e2))) - return e; + return fold_constants (e); e = new_binary_expr (op, e1, e2); e->e.expr.type = expr_type->type; @@ -790,5 +815,5 @@ binary_expr (int op, expr_t *e1, expr_t *e2) if (options.code.progsversion == PROG_ID_VERSION) e->e.expr.type = &type_float; } - return e; + return fold_constants (e); } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index cb1b28ea3..eba38584d 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -180,7 +180,7 @@ int yylex (void); %type methoddef %type opt_initializer var_initializer local_def -%type opt_init opt_expr cexpr fexpr expr element_list element +%type opt_init opt_expr cexpr expr element_list element %type optional_state_expr texpr vector_expr %type statement statements compound_statement %type else label break_label continue_label @@ -577,7 +577,7 @@ enumerator_list enumerator : identifier { add_enum ($0, $1, 0); } - | identifier '=' fexpr { add_enum ($0, $1, $3); } + | identifier '=' expr { add_enum ($0, $1, $3); } ; struct_specifier @@ -846,9 +846,8 @@ abs_decl ; array_decl - : '[' fexpr ']' + : '[' expr ']' { - $2 = fold_constants ($2); if (!is_integer_val ($2) || expr_integer ($2) < 1) { error (0, "invalid array size"); $$ = 0; @@ -971,11 +970,11 @@ overloaded_identifier ; non_code_func - : '=' '#' fexpr + : '=' '#' expr { build_builtin_function ($0, $3, 0); } - | '=' fexpr + | '=' expr { symbol_t *sym = $0; specifier_t spec = $-1; @@ -1023,7 +1022,7 @@ opt_initializer ; var_initializer - : '=' fexpr { $$ = $2; } + : '=' expr { $$ = $2; } | '=' '{' element_list optional_comma '}' { $$ = $3; } ; @@ -1046,7 +1045,7 @@ element_list element : '{' element_list optional_comma '}' { $$ = $2; } - | fexpr { $$ = $1; } + | expr { $$ = $1; } ; optional_comma @@ -1128,7 +1127,7 @@ statement else error (0, "continue outside of loop"); } - | CASE fexpr ':' + | CASE expr ':' { $$ = case_label_expr (switch_block, $2); } @@ -1136,7 +1135,7 @@ statement { $$ = case_label_expr (switch_block, 0); } - | SWITCH break_label '(' fexpr switch_block ')' compound_statement + | SWITCH break_label '(' expr switch_block ')' compound_statement { $$ = switch_expr (switch_block, break_label, $7); switch_block = $5; @@ -1295,7 +1294,7 @@ unary_expr ; vector_expr - : '[' fexpr ',' arg_list ']' + : '[' expr ',' arg_list ']' { expr_t *t = $4; while (t->next) @@ -1338,12 +1337,8 @@ expr | expr '%' expr { $$ = binary_expr ('%', $1, $3); } ; -fexpr - : expr { $$ = fold_constants ($1); } - ; - texpr - : fexpr { $$ = convert_bool ($1, 1); } + : expr { $$ = convert_bool ($1, 1); } ; cexpr @@ -1364,8 +1359,8 @@ opt_arg_list ; arg_list - : fexpr - | arg_list ',' fexpr + : expr + | arg_list ',' expr { $3->next = $1; $$ = $3; @@ -1874,7 +1869,7 @@ obj_messageexpr ; receiver - : fexpr + : expr | CLASS_NAME { $$ = new_symbol_expr ($1); diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 0ff624b95..7e76ef6f4 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -338,8 +338,6 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, int i; expr_t *range = binary_expr ('-', tree->high, tree->low); - range = fold_constants (range); - table_init = new_block_expr (); for (i = 0; i <= high - low; i++) { tree->labels[i]->e.label.used++; From f81484a068eb948c2f6555eb0942045b52165f58 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 07:17:41 +0900 Subject: [PATCH 0134/3664] Test compiling enums It turns out the enumerator type and enum type wind up with different instances of the same type (due to the way type chaining works). This results in infinite recursion in assign_expr and check_types_compatible. --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/enum.r | 12 ++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 tools/qfcc/test/enum.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 0e9e39e81..96351e926 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -33,6 +33,7 @@ test_progs_dat=\ chewed-return.dat \ comma-expr.dat \ deadbool.dat \ + enum.dat \ fordecl.dat \ func-expr.dat \ func-static.dat \ @@ -109,6 +110,15 @@ deadbool.run: Makefile build-run include ./$(DEPDIR)/deadbool.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/deadbool.Qo +enum_dat_SOURCES=enum.r +enum_obj=$(enum_dat_SOURCES:.r=.qfo) +enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(enum_obj) +enum.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/enum.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/enum.Qo + fordecl_dat_SOURCES=fordecl.r fordecl_obj=$(fordecl_dat_SOURCES:.r=.qfo) fordecl.dat$(EXEEXT): $(fordecl_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/enum.r b/tools/qfcc/test/enum.r new file mode 100644 index 000000000..b6ffb09c1 --- /dev/null +++ b/tools/qfcc/test/enum.r @@ -0,0 +1,12 @@ +typedef enum { + NO = 0, + YES +} BOOL; + +int +main() +{ + BOOL b; + b = YES; + return !b; +} From 7dc1a0640a520710a5ecb0c2dc3b63523340423d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 07:44:23 +0900 Subject: [PATCH 0135/3664] Delay creating actual enum symbols In order to keep enumerator type and enum type the same, the values need to have their type set after the enum type is finalized, and then the appropriate symbols created in the parent scope. This fixes the infinite recursion when assigning an enum value to its own type. --- tools/qfcc/source/struct.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index ddf30f8ea..d3f014111 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -159,25 +159,38 @@ start_enum (symbol_t *sym) symbol_t * finish_enum (symbol_t *sym) { - sym->type = find_type (sym->type); + symbol_t *enum_sym; + symbol_t *name; + type_t *enum_type; + symtab_t *enum_tab; + + enum_type = sym->type = find_type (sym->type); + enum_tab = enum_type->t.symtab; + + for (name = enum_tab->symbols; name; name = name->next) { + name->type = sym->type; + + enum_sym = new_symbol_type (name->name, enum_type); + enum_sym->sy_type = sy_const; + enum_sym->s.value = name->s.value; + symtab_addsymbol (enum_tab->parent, enum_sym); + } return sym; } void add_enum (symbol_t *enm, symbol_t *name, expr_t *val) { - symbol_t *sym; type_t *enum_type = enm->type; - symtab_t *enum_tab; + symtab_t *enum_tab = enum_type->t.symtab; int value; - if (name->table == current_symtab) + if (name->table == current_symtab || name->table == enum_tab) error (0, "%s redefined", name->name); if (name->table) name = new_symbol (name->name); name->sy_type = sy_const; name->type = enum_type; - enum_tab = enum_type->t.symtab; value = 0; if (enum_tab->symbols) value = ((symbol_t *)(enum_tab->symtail))->s.value->v.integer_val + 1; @@ -191,10 +204,6 @@ add_enum (symbol_t *enm, symbol_t *name, expr_t *val) } name->s.value = new_integer_val (value); symtab_addsymbol (enum_tab, name); - sym = new_symbol_type (name->name, name->type); - sym->sy_type = sy_const; - sym->s.value = name->s.value; - symtab_addsymbol (enum_tab->parent, sym); } int From 83fb5887273fa9d9900ff966801a66c5ecdf7d53 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 08:44:36 +0900 Subject: [PATCH 0136/3664] Support vector/quaternion division by float Implemented via v*(1/f) or q*(1/f) to give CSE a chance to optimize the division if necessary as otherwise the engine would have to divide every time. --- tools/qfcc/source/expr_binary.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index d53d3677c..2029726af 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -46,6 +46,7 @@ typedef struct { } expr_type_t; static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2); +static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2); static expr_type_t string_string[] = { {'+', &type_string}, @@ -85,7 +86,7 @@ static expr_type_t float_vector[] = { static expr_type_t float_quat[] = { {'*', &type_quaternion}, - {'/', &type_quaternion}, + {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; @@ -113,7 +114,7 @@ static expr_type_t float_integer[] = { static expr_type_t vector_float[] = { {'*', &type_vector}, - {'/', &type_vector}, + {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; @@ -601,6 +602,15 @@ pointer_arithmetic (int op, expr_t *e1, expr_t *e2) return cast_expr (ptype, e); } +static expr_t * +inverse_multiply (int op, expr_t *e1, expr_t *e2) +{ + // There is no vector/float or quaternion/float instruction and adding + // one would mean the engine would have to do 1/f every time + expr_t *one = new_float_expr (1); + return binary_expr ('*', e1, binary_expr ('/', one, e2)); +} + static expr_t * invalid_binary_expr (int op, expr_t *e1, expr_t *e2) { From 49ed4310fdba52fe946a7eac062a8b972d6087c2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 08:46:40 +0900 Subject: [PATCH 0137/3664] Fix assigning int to enum or enum to int Or float, for v6 progs. --- tools/qfcc/source/expr_assign.c | 7 ++++++- tools/qfcc/test/enum.r | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 1662d6b10..b32f6de9e 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -149,7 +149,12 @@ check_types_compatible (expr_t *dst, expr_t *src) if (type_assignable (dst_type, src_type)) { if (is_scalar (dst_type) && is_scalar (src_type)) { // the types are different but cast-compatible - return assign_expr (dst, cast_expr (dst_type, src)); + expr_t *new = cast_expr (dst_type, src); + // the cast was a no-op, so the types are compatible at the + // low level (very true for default type <-> enum) + if (new != src) { + return assign_expr (dst, new); + } } return 0; } diff --git a/tools/qfcc/test/enum.r b/tools/qfcc/test/enum.r index b6ffb09c1..f1565cdf0 100644 --- a/tools/qfcc/test/enum.r +++ b/tools/qfcc/test/enum.r @@ -7,6 +7,7 @@ int main() { BOOL b; + b = 0; b = YES; return !b; } From 08ab42fc153bf28130b085590b44b7c74ee41add Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 15:50:35 +0900 Subject: [PATCH 0138/3664] Handle vector expressions as sub-expressions Now my little game builds again :) --- tools/qfcc/source/expr.c | 1 + tools/qfcc/source/statements.c | 63 +++++++++++++++++++++++++++++++++- tools/qfcc/test/vecexpr.r | 4 +-- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index e2225d2bc..27732dd5f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -210,6 +210,7 @@ convert_vector (expr_t *e) // Either v or s is not constant, so can't convert to a quaternion // constant. // Rebuild the list in case v or s is a new expression + // the list will always be v, s s->next = 0; v->next = s; e->e.vector.list = v; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index fb55412e1..e59092d54 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -984,6 +984,67 @@ expr_temp (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) +{ + expr_t *x, *y, *z, *w; + expr_t *s, *v; + expr_t *ax, *ay, *az, *aw; + expr_t *as, *av; + expr_t *tmp; + type_t *vec_type = get_type(e); + + tmp = new_temp_def_expr(vec_type); + if (vec_type == &type_vector) { + // guaranteed to have three elements + x = e->e.vector.list; + y = x->next; + z = y->next; + ax = new_name_expr ("x"); + ay = new_name_expr ("y"); + az = new_name_expr ("z"); + ax = assign_expr (field_expr (tmp, ax), x); + ay = assign_expr (field_expr (tmp, ay), y); + az = assign_expr (field_expr (tmp, az), z); + sblock = statement_slist (sblock, ax); + sblock = statement_slist (sblock, ay); + sblock = statement_slist (sblock, az); + } else { + // guaranteed to have two or four elements + if (e->e.vector.list->next->next) { + // four vals: x, y, z, w + x = e->e.vector.list; + y = x->next; + z = y->next; + w = z->next; + ax = new_name_expr ("x"); + ay = new_name_expr ("y"); + az = new_name_expr ("z"); + aw = new_name_expr ("w"); + ax = assign_expr (field_expr (tmp, ax), x); + ay = assign_expr (field_expr (tmp, ay), y); + az = assign_expr (field_expr (tmp, az), z); + aw = assign_expr (field_expr (tmp, aw), w); + sblock = statement_slist (sblock, ax); + sblock = statement_slist (sblock, ay); + sblock = statement_slist (sblock, az); + sblock = statement_slist (sblock, aw); + } else { + // v, s + v = e->e.vector.list; + s = v->next; + av = new_name_expr ("v"); + as = new_name_expr ("s"); + av = assign_expr (field_expr (tmp, av), v); + as = assign_expr (field_expr (tmp, as), s); + sblock = statement_slist (sblock, av); + sblock = statement_slist (sblock, as); + } + } + sblock = statement_subexpr (sblock, tmp, op); + return sblock; +} + static sblock_t * expr_value (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1005,7 +1066,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) expr_uexpr, expr_symbol, expr_temp, - 0, // ex_vector + expr_vector_e, // ex_vector 0, // ex_nil expr_value, }; diff --git a/tools/qfcc/test/vecexpr.r b/tools/qfcc/test/vecexpr.r index 59cc66b4a..de6b3af7c 100644 --- a/tools/qfcc/test/vecexpr.r +++ b/tools/qfcc/test/vecexpr.r @@ -13,11 +13,11 @@ t2(float x) vector t3(float x) { - return [x, t2(9).z, x]; + return [x, t2(9).z, x] * 2; } int main () { - return t3(5) == [5, 9, 5] ? 0 : 1; + return t3(5) == [10, 18, 10] ? 0 : 1; } From efdfc7436f2b0e206f764f8ecc04f9470eb8df0f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 18:04:25 +0900 Subject: [PATCH 0139/3664] Move ev_types into types.[ch] No wonder I couldn't find it the other day... --- tools/qfcc/include/expr.h | 1 - tools/qfcc/include/type.h | 2 ++ tools/qfcc/source/expr.c | 16 ---------------- tools/qfcc/source/type.c | 16 ++++++++++++++++ 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index d8831b766..486af55be 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -210,7 +210,6 @@ typedef struct expr_s { } e; } expr_t; -extern struct type_s *ev_types[]; extern const char *expr_names[]; /** Report a type mismatch error. diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index e886ac444..92b495753 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -170,4 +170,6 @@ void chain_initial_types (void); void clear_typedefs (void); +extern type_t *ev_types[]; + #endif//__type_h diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 27732dd5f..aa530c04c 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -67,22 +67,6 @@ static expr_t *exprs_freelist; -type_t *ev_types[ev_type_count] = { - &type_void, - &type_string, - &type_float, - &type_vector, - &type_entity, - &type_field, - &type_function, - &type_pointer, - &type_quaternion, - &type_integer, - &type_uinteger, - &type_short, - &type_invalid, -}; - void convert_name (expr_t *e) { diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index cc95de7ee..d63563524 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -88,6 +88,22 @@ type_t type_type_encodings = { ev_invalid, "@type_encodings", ty_struct }; type_t type_floatfield = { ev_field, ".float", ty_none, {{&type_float}} }; +type_t *ev_types[ev_type_count] = { + &type_void, + &type_string, + &type_float, + &type_vector, + &type_entity, + &type_field, + &type_function, + &type_pointer, + &type_quaternion, + &type_integer, + &type_uinteger, + &type_short, + &type_invalid, +}; + static type_t *types_freelist; etype_t From 913b9f52e0450f17bdc73c813a13e9e9105c66b6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 18:13:28 +0900 Subject: [PATCH 0140/3664] Add an offset alias expression This should make dealing with def elements (vector etc) easier. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/expr.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 486af55be..5109b364e 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -558,6 +558,7 @@ expr_t *new_this_expr (void); expr_t *new_ret_expr (struct type_s *type); expr_t *new_alias_expr (struct type_s *type, expr_t *expr); +expr_t *new_offset_alias_expr (struct type_s *type, expr_t *expr, int offset); /** Create an expression of the correct type that references the specified parameter slot. diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index aa530c04c..3353521b6 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1025,6 +1025,18 @@ new_alias_expr (type_t *type, expr_t *expr) return alias; } +expr_t * +new_offset_alias_expr (type_t *type, expr_t *expr, int offset) +{ + expr_t *alias; + + alias = new_binary_expr ('A', expr, new_integer_expr (offset)); + alias->e.expr.type = type; + alias->file = expr->file; + alias->line = expr->line; + return alias; +} + static expr_t * param_expr (const char *name, type_t *type) { From ee1f5f94781dc11508d61e8b045bd22d6f90a8b6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 23:48:58 +0900 Subject: [PATCH 0141/3664] Add support for binary alias expressions Doesn't quite work yet. --- tools/qfcc/include/statements.h | 1 + tools/qfcc/source/dot_expr.c | 12 +++- tools/qfcc/source/expr_assign.c | 3 + tools/qfcc/source/statements.c | 99 +++++++++++++++++++-------------- 4 files changed, 70 insertions(+), 45 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 356d66b8f..9afe4ef91 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -42,6 +42,7 @@ typedef enum { typedef struct { struct def_s *def; + int offset; struct type_s *type; struct flowvar_s *flowvar; struct daglabel_s *daglabel; diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 175b8c800..2925ffcc7 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -320,8 +320,16 @@ print_subexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"r\"];\n", indent, "", e, e->e.expr.e2); } - dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, - get_op_string (e->e.expr.op), e->line); + if (e->e.expr.op == 'A') { + dstring_t *typestr = dstring_newstr(); + print_type_str (typestr, e->e.expr.type); + dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e, + get_op_string (e->e.expr.op), typestr->str, e->line); + dstring_delete (typestr); + } else { + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + get_op_string (e->e.expr.op), e->line); + } } static void diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index b32f6de9e..1797f7677 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -109,6 +109,9 @@ check_valid_lvalue (expr_t *expr) if (expr->e.expr.op == '.') { return 0; } + if (expr->e.expr.op == 'A') { + return check_valid_lvalue (expr->e.expr.e1); + } break; case ex_uexpr: if (expr->e.expr.op == '.') { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e59092d54..73d5d5cbd 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -804,6 +804,59 @@ expr_block (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) +{ + operand_t *aop = 0; + operand_t *top; + etype_t type; + def_t *def; + int offset = 0; + + if (e->type == ex_expr) { + offset = expr_integer (e->e.expr.e2); + } + type = low_level_type (e->e.expr.type); + sblock = statement_subexpr (sblock, e->e.expr.e1, &aop); + if (aop->type == type) { + if (offset) { + internal_error (e, "offset alias of same type"); + } + *op = aop; + return sblock; + } + if (aop->op_type == op_temp) { + while (aop->o.tempop.alias) { + aop = aop->o.tempop.alias; + if (aop->op_type != op_temp) + internal_error (e, "temp alias of non-temp var"); + } + for (top = aop->o.tempop.alias_ops; top; top = top->next) { + if (top->type == type && top->o.tempop.offset == offset) { + break; + } + } + if (!top) { + top = new_operand (op_temp); + top->type = type; + top->o.tempop.alias = aop; + top->o.tempop.offset = offset; + top->next = aop->o.tempop.alias_ops; + aop->o.tempop.alias_ops = top; + } + *op = top; + } else if (aop->op_type == op_def) { + def = aop->o.def; + while (def->alias) + def = def->alias; + *op = def_operand (alias_def (def, ev_types[type], offset), 0); + } else { + internal_error (e, "invalid alias target: %s: %s", + optype_str (aop->op_type), operand_string (aop)); + } + return sblock; +} + static sblock_t * expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -822,6 +875,9 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) case 'M': sblock = expr_move (sblock, e, op); break; + case 'A': + sblock = expr_alias (sblock, e, op); + break; default: opcode = convert_op (e->e.expr.op); if (!opcode) @@ -838,49 +894,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } -static sblock_t * -expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) -{ - operand_t *aop = 0; - operand_t *top; - etype_t type; - def_t *def; - - type = low_level_type (e->e.expr.type); - sblock = statement_subexpr (sblock, e->e.expr.e1, &aop); - if (aop->type == type) { - *op = aop; - return sblock; - } - if (aop->op_type == op_temp) { - while (aop->o.tempop.alias) { - aop = aop->o.tempop.alias; - if (aop->op_type != op_temp) - internal_error (e, "temp alias of non-temp var"); - } - for (top = aop->o.tempop.alias_ops; top; top = top->next) - if (top->type == type) - break; - if (!top) { - top = new_operand (op_temp); - top->type = type; - top->o.tempop.alias = aop; - top->next = aop->o.tempop.alias_ops; - aop->o.tempop.alias_ops = top; - } - *op = top; - } else if (aop->op_type == op_def) { - def = aop->o.def; - while (def->alias) - def = def->alias; - *op = def_operand (alias_def (def, ev_types[type], 0), 0); - } else { - internal_error (e, "invalid alias target: %s: %s", - optype_str (aop->op_type), operand_string (aop)); - } - return sblock; -} - static sblock_t * expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) { From cc27949a34588ab80b3f2d4730f446dd2ac4e623 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 23:52:39 +0900 Subject: [PATCH 0142/3664] Ensure pointer values always have a type The dags generator was creating a pointer value with no type which caused print_statement to segfault. --- tools/qfcc/source/dags.c | 4 +++- tools/qfcc/source/value.c | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 0f07edbbf..69a5100a8 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -787,6 +787,7 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operand_t *operands[3] = {0, 0, 0}; statement_t *st; operand_t *dst = 0; + type_t *type; operands[0] = make_operand (dag, block, dagnode, 0); operands[1] = make_operand (dag, block, dagnode, 1); @@ -794,7 +795,8 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) var_iter = set_next (var_iter)) { var = dag->labels[var_iter->element]; dst = var->op; - operands[2] = value_operand (new_pointer_val (0, 0, dst->o.def)); + type = dst->o.def->type; + operands[2] = value_operand (new_pointer_val (0, type, dst->o.def)); st = build_statement ("", operands, var->expr); sblock_add_statement (block, st); } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index bdaa9c6f3..29d6eabed 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -189,6 +189,9 @@ ex_value_t * new_pointer_val (int pointer_val, type_t *type, def_t *def) { ex_value_t val; + if (!type) { + internal_error (0, "pointer value with no type"); + } memset (&val, 0, sizeof (val)); set_val_type (&val, pointer_type (type)); val.v.pointer.val = pointer_val; From b18a74428815aae4ae11d86e6021cbc40d0206ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jun 2019 23:55:16 +0900 Subject: [PATCH 0143/3664] Use offset alias expressions They are not quite working yet as the operand generator does not use the offset yet. --- tools/qfcc/source/expr.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 3353521b6..7b5b8edbb 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1195,10 +1195,14 @@ field_expr (expr_t *e1, expr_t *e2) // create a new . expression return field_expr (e1, e2); } else { - e2->type = ex_value; - e2->e.value = new_short_val (field->s.offset); - e = address_expr (e1, e2, field->type); - return unary_expr ('.', e); + if (e1->type == ex_uexpr && e1->e.expr.op == '.') { + e2->type = ex_value; + e2->e.value = new_short_val (field->s.offset); + e = address_expr (e1, e2, field->type); + return unary_expr ('.', e); + } else { + return new_offset_alias_expr (field->type, e1, field->s.offset); + } } } else if (obj_is_class (t1)) { //Class instance variables aren't allowed and thus declaring one From fa69aeef0f5f1a21fd920e47cbd185345d50152d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Jun 2019 00:37:02 +0900 Subject: [PATCH 0144/3664] Improve handling of temp aliases This makes all tests pass when not optimizing. More work needs to be done in dags. --- tools/qfcc/include/flow.h | 1 + tools/qfcc/include/function.h | 1 + tools/qfcc/include/statements.h | 1 + tools/qfcc/source/constfold.c | 2 +- tools/qfcc/source/dags.c | 4 +-- tools/qfcc/source/emit.c | 14 +++++++-- tools/qfcc/source/flow.c | 55 +++++++++++++++++++++++---------- tools/qfcc/source/statements.c | 7 ++++- 8 files changed, 62 insertions(+), 23 deletions(-) diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index c605b1d22..591704a01 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -46,6 +46,7 @@ typedef struct flowvar_s { struct set_s *define; ///< set of statements that define this var struct operand_s *op; ///< an operand using this var int number; ///< number of variable in func's ref list + int flowaddr; ///< psuedo address for local and temp vars } flowvar_t; typedef struct flowloop_s { diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index b4b546fa6..d145fc53e 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -94,6 +94,7 @@ typedef struct function_s { struct set_s *global_vars;///< set indicating which vars are global struct statement_s **statements; int num_statements; + int tmpaddr; ///< tmp var "address" for flow analysis } function_t; extern function_t *current_func; diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 9afe4ef91..eeb3bfdbf 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -49,6 +49,7 @@ typedef struct { struct operand_s *alias; struct operand_s *alias_ops; int users; + int flowaddr; ///< "address" of temp in flow analysis, != 0 } tempop_t; typedef struct operand_s { diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 33746c8e9..817703945 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1478,7 +1478,7 @@ fold_constants (expr_t *e) } op = e->e.expr.op; - if (op == 'i' || op == 'n' || op == 'c' || op == 's') { + if (op == 'A' || op == 'i' || op == 'n' || op == 'c' || op == 's') { return e; } diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 69a5100a8..7596a8646 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -158,8 +158,8 @@ operand_label (dag_t *dag, operand_t *op) return 0; if (op->op_type == op_temp) { - while (op->o.tempop.alias) - op = op->o.tempop.alias; + //while (op->o.tempop.alias) + // op = op->o.tempop.alias; if (op->o.tempop.daglabel) return op->o.tempop.daglabel; label = new_label (dag); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 34a5de3f2..003204dcb 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -91,10 +91,18 @@ get_operand_def (expr_t *expr, operand_t *op) zero_def.type = &type_short; return &zero_def; //FIXME case op_temp: - while (op->o.tempop.alias) - op = op->o.tempop.alias; - if (!op->o.tempop.def) + if (op->o.tempop.def) { + return op->o.tempop.def; + } + if (op->o.tempop.alias) { + def_t *tdef = get_operand_def (expr, op->o.tempop.alias); + int offset = op->o.tempop.offset; + type_t *type = ev_types[op->type]; + op->o.tempop.def = alias_def (tdef, type, offset); + } + if (!op->o.tempop.def) { op->o.tempop.def = temp_def (op->type, op->size); + } return op->o.tempop.def; case op_alias: return get_operand_def (expr, op->o.alias); diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index cd26be5b9..d60a1c5ac 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -204,6 +204,12 @@ flowvar_is_param (flowvar_t *var) return 0; return 1; } + +static int +flowvar_is_local (flowvar_t *var) +{ + return !(flowvar_is_global (var) || flowvar_is_param (var)); +} #if 0 static int flowvar_is_initialized (flowvar_t *var) @@ -263,6 +269,24 @@ count_operand (operand_t *op) return 0; } +static int +get_temp_address (function_t *func, operand_t *op) +{ + operand_t *top = op; + if (op->o.tempop.flowaddr) { + return op->o.tempop.flowaddr; + } + while (top->o.tempop.alias) { + top = top->o.tempop.alias; + } + if (!top->o.tempop.flowaddr) { + top->o.tempop.flowaddr = func->tmpaddr; + func->tmpaddr += top->size; + } + op->o.tempop.flowaddr = top->o.tempop.flowaddr + op->o.tempop.offset; + return op->o.tempop.flowaddr; +} + static void add_operand (function_t *func, operand_t *op) { @@ -280,6 +304,11 @@ add_operand (function_t *func, operand_t *op) var->number = func->num_vars++; var->op = op; func->vars[var->number] = var; + if (op->op_type == op_temp) { + var->flowaddr = get_temp_address (func, op); + } else if (flowvar_is_local (var)) { + var->flowaddr = func->num_statements + def_offset (var->op->o.def); + } } } @@ -348,6 +377,9 @@ flow_build_vars (function_t *func) stuse = set_new (); stdef = set_new (); + // set up pseudo address space for temp vars so accessing tmp vars + // though aliases analyses correctly + func->tmpaddr = func->num_statements + func->symtab->space->size; func->num_vars = 0; // incremented by add_operand // first, add .return and .param_[0-7] as they are always needed for (i = 0; i < num_flow_params; i++) @@ -382,27 +414,18 @@ flow_build_vars (function_t *func) // ([num_statements ... num_statements+localsize]) // with a set element for each def used in the local space // - // temporary vars add their var number to the size of the local space - // before adding the number of statements in the function: - // ([num_statements+localsize ... num_vars]) - // temporary vars are always accessed as a full var, so only one set - // element per temporary var is needed. This can lead to holes in the - // temporary var set element space, but it does keep things simple + // temporary vars are pseudo allocated and their addresses are added as for + // locals + // add_operand takes care of setting flowaddr for both locals and temps for (i = 0; i < func->num_vars; i++) { - int offset, size; int j; var = func->vars[i]; - if (flowvar_is_global (var) || flowvar_is_param (var)) + if (flowvar_is_global (var) || flowvar_is_param (var)) { continue; - if (var->op->op_type == op_temp) { - j = func->symtab->space->size + var->number; - set_add (var->define, func->num_statements + j); - } else { - offset = def_offset (var->op->o.def); - size = def_size (var->op->o.def); - for (j = offset; j < offset + size; j++) - set_add (var->define, func->num_statements + j); + } + for (j = 0; j < var->op->size; j++) { + set_add (var->define, var->flowaddr + j); } } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 73d5d5cbd..e0500aab6 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -126,10 +126,11 @@ operand_string (operand_t *op) return op->o.label->name; case op_temp: if (op->o.tempop.alias) - return va ("", + return va ("", pr_type_name[op->type], op, op->o.tempop.users, op->o.tempop.alias, + op->o.tempop.offset, op->o.tempop.alias->o.tempop.users); return va ("", pr_type_name[op->o.tempop.type->type], op, op->o.tempop.users); @@ -307,6 +308,7 @@ def_operand (def_t *def, type_t *type) type = def->type; op = new_operand (op_def); op->type = low_level_type (type); + op->size = type_size (type); op->o.def = def; return op; } @@ -830,6 +832,8 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) aop = aop->o.tempop.alias; if (aop->op_type != op_temp) internal_error (e, "temp alias of non-temp var"); + if (aop->o.tempop.alias) + bug (e, "aliased temp alias"); } for (top = aop->o.tempop.alias_ops; top; top = top->next) { if (top->type == type && top->o.tempop.offset == offset) { @@ -839,6 +843,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) if (!top) { top = new_operand (op_temp); top->type = type; + top->size = pr_type_size[type]; top->o.tempop.alias = aop; top->o.tempop.offset = offset; top->next = aop->o.tempop.alias_ops; From bc271d8a02b47a5c9a02f58ffdc09303df226d7f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 16:52:49 +0900 Subject: [PATCH 0145/3664] Add tempop_visit_all Works the same as def_visit_all, but for temp operands. --- tools/qfcc/include/statements.h | 3 ++ tools/qfcc/source/statements.c | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index eeb3bfdbf..e0e3dca98 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -117,7 +117,10 @@ const char *optype_str (op_type_e type) __attribute__((const)); operand_t *def_operand (struct def_s *def, struct type_s *type); operand_t *value_operand (struct ex_value_s *value); +int tempop_overlap (tempop_t *t1, tempop_t *t2); operand_t *temp_operand (struct type_s *type); +int tempop_visit_all (tempop_t *tempop, int overlap, + int (*visit) (tempop_t *, void *), void *data); operand_t *alias_operand (etype_t type, operand_t *op); void free_operand (operand_t *op); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e0500aab6..d476aeeaf 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -334,6 +334,55 @@ temp_operand (type_t *type) return op; } +int +tempop_overlap (tempop_t *t1, tempop_t *t2) +{ + int offs1 = t1->offset; + int offs2 = t2->offset; + int size1 = type_size (t1->type); + int size2 = type_size (t2->type); + + if (offs1 <= offs2 && offs1 + size1 >= offs2 + size2) + return 2; // t1 fully overlaps t2 + if (offs1 < offs2 + size2 && offs2 < offs1 + size1) + return 1; // t1 and t2 at least partially overlap + return 0; +} + +int +tempop_visit_all (tempop_t *tempop, int overlap, + int (*visit) (tempop_t *, void *), void *data) +{ + tempop_t *start_tempop = tempop; + operand_t *top; + int ret; + + if ((ret = visit (tempop, data))) + return ret; + if (tempop->alias) { + top = tempop->alias; + if (top->op_type != op_temp) { + internal_error (0, "temp alias of non-temp operand"); + } + tempop = &top->o.tempop; + if ((ret = visit (tempop, data))) + return ret; + } + for (top = tempop->alias_ops; top; top = top->next) { + if (top->op_type != op_temp) { + internal_error (0, "temp alias of non-temp operand"); + } + tempop = &top->o.tempop; + if (tempop == start_tempop) + continue; + if (overlap && tempop_overlap (tempop, start_tempop) < overlap) + continue; + if ((ret = visit (tempop, data))) + return ret; + } + return 0; +} + operand_t * alias_operand (etype_t type, operand_t *op) { From 3c4903245a08e2be69830e753eb09f6cc2b6541c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 16:55:54 +0900 Subject: [PATCH 0146/3664] Fix some curly space --- tools/qfcc/source/dags.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 7596a8646..1af758cbb 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -353,15 +353,17 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) if (child->label->op) { dagnode_t *node = child->label->dagnode; operand_t *op = child->label->op; - if (node != child && node != n) + if (node != child && node != n) { set_add (node->edges, n->number); + } if (op->op_type == op_value && op->o.value->lltype == ev_pointer - && op->o.value->v.pointer.def) + && op->o.value->v.pointer.def) { def_visit_all (op->o.value->v.pointer.def, 1, dagnode_set_edges_visit, n); + } if (op->op_type == op_def - && (op->o.def->alias || op->o.def->alias_defs)) + && (op->o.def->alias || op->o.def->alias_defs)) { def_visit_all (op->o.def, 1, dagnode_set_edges_visit, n); } if (n != child) @@ -449,8 +451,9 @@ dag_kill_aliases (daglabel_t *l) if (op->op_type == op_temp) { } else if (op->op_type == op_def) { - if (op->o.def->alias || op->o.def->alias_defs) + if (op->o.def->alias || op->o.def->alias_defs) { def_visit_all (op->o.def, 1, dag_kill_aliases_visit, l); + } } else { internal_error (0, "rvalue assignment?"); } @@ -494,7 +497,7 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l) // FIXME it would be better to propogate the aliasing if (n->label->op->op_type == op_def && (n->label->op->o.def->alias - || n->label->op->o.def->alias_defs)) + || n->label->op->o.def->alias_defs)) { def_visit_all (n->label->op->o.def, 1, dag_live_aliases, n->label->op->o.def); } From c40f4194e9fcbccaa27357aa0f220845ebe04c54 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 16:56:39 +0900 Subject: [PATCH 0147/3664] Use tempop_visit_all for flow and dags Fixes t3 of vecexpr, but t2 is broken (lost first assignment). --- tools/qfcc/source/dags.c | 86 ++++++++++++++++++++++++++++++++++----- tools/qfcc/source/flow.c | 29 +++++++------ tools/qfcc/test/vecexpr.r | 16 +++++++- 3 files changed, 107 insertions(+), 24 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 1af758cbb..1d773066b 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -311,7 +311,21 @@ dagnode_add_children (dag_t *dag, dagnode_t *n, operand_t *operands[4], } static int -dagnode_set_edges_visit (def_t *def, void *_node) +dagnode_tempop_set_edges_visit (tempop_t *tempop, void *_node) +{ + dagnode_t *node = (dagnode_t *) _node; + daglabel_t *label; + + label = tempop->daglabel; + if (label && label->dagnode) { + set_add (node->edges, label->dagnode->number); + label->live = 1; + } + return 0; +} + +static int +dagnode_def_set_edges_visit (def_t *def, void *_node) { dagnode_t *node = (dagnode_t *) _node; daglabel_t *label; @@ -360,11 +374,17 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) && op->o.value->lltype == ev_pointer && op->o.value->v.pointer.def) { def_visit_all (op->o.value->v.pointer.def, 1, - dagnode_set_edges_visit, n); + dagnode_def_set_edges_visit, n); } if (op->op_type == op_def && (op->o.def->alias || op->o.def->alias_defs)) { - def_visit_all (op->o.def, 1, dagnode_set_edges_visit, n); + def_visit_all (op->o.def, 1, + dagnode_def_set_edges_visit, n); + } + if (op->op_type == op_temp) { + tempop_visit_all (&op->o.tempop, 1, + dagnode_tempop_set_edges_visit, n); + } } if (n != child) set_add (n->edges, child->number); @@ -427,7 +447,25 @@ op_is_identifier (operand_t *op) } static int -dag_kill_aliases_visit (def_t *def, void *_l) +dag_tempop_kill_aliases_visit (tempop_t *tempop, void *_l) +{ + daglabel_t *l = (daglabel_t *) _l; + dagnode_t *node = l->dagnode;; + daglabel_t *label; + + if (tempop == &l->op->o.tempop) + return 0; + label = tempop->daglabel; + if (label && label->dagnode) { + set_add (node->edges, label->dagnode->number); + set_remove (node->edges, node->number); + label->dagnode->killed = 1; + } + return 0; +} + +static int +dag_def_kill_aliases_visit (def_t *def, void *_l) { daglabel_t *l = (daglabel_t *) _l; dagnode_t *node = l->dagnode;; @@ -450,9 +488,10 @@ dag_kill_aliases (daglabel_t *l) operand_t *op = l->op; if (op->op_type == op_temp) { + tempop_visit_all (&op->o.tempop, 1, dag_tempop_kill_aliases_visit, l); } else if (op->op_type == op_def) { if (op->o.def->alias || op->o.def->alias_defs) { - def_visit_all (op->o.def, 1, dag_kill_aliases_visit, l); + def_visit_all (op->o.def, 1, dag_def_kill_aliases_visit, l); } } else { internal_error (0, "rvalue assignment?"); @@ -460,7 +499,16 @@ dag_kill_aliases (daglabel_t *l) } static int -dag_live_aliases (def_t *def, void *_d) +dag_tempop_live_aliases (tempop_t *tempop, void *_t) +{ + + if (tempop != _t && tempop->daglabel) + tempop->daglabel->live = 1; + return 0; +} + +static int +dag_def_live_aliases (def_t *def, void *_d) { if (def != _d && def->daglabel) @@ -493,18 +541,32 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l) set_add (n->identifiers, l->number); dag_kill_aliases (l); if (n->label->op) { - // FIXME temps // FIXME it would be better to propogate the aliasing + if (n->label->op->op_type == op_temp) { + tempop_visit_all (&n->label->op->o.tempop, 1, + dag_tempop_live_aliases, + &n->label->op->o.tempop); + } if (n->label->op->op_type == op_def && (n->label->op->o.def->alias || n->label->op->o.def->alias_defs)) { - def_visit_all (n->label->op->o.def, 1, dag_live_aliases, + def_visit_all (n->label->op->o.def, 1, dag_def_live_aliases, n->label->op->o.def); + } } } static int -dag_alias_live (def_t *def, void *_live_vars) +dag_tempop_alias_live (tempop_t *tempop, void *_live_vars) +{ + set_t *live_vars = (set_t *) _live_vars; + if (!tempop->flowvar) + return 0; + return set_is_member (live_vars, tempop->flowvar->number); +} + +static int +dag_def_alias_live (def_t *def, void *_live_vars) { set_t *live_vars = (set_t *) _live_vars; if (!def->flowvar) @@ -531,7 +593,11 @@ dag_remove_dead_vars (dag_t *dag, set_t *live_vars) if (set_is_member (dag->flownode->global_vars, var->number)) continue; if (l->op->op_type == op_def - && def_visit_all (l->op->o.def, 1, dag_alias_live, live_vars)) + && def_visit_all (l->op->o.def, 1, dag_def_alias_live, live_vars)) + continue; + if (l->op->op_type == op_temp + && tempop_visit_all (&l->op->o.tempop, 1, dag_tempop_alias_live, + live_vars)) continue; if (!set_is_member (live_vars, var->number)) set_remove (l->dagnode->identifiers, l->number); diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index d60a1c5ac..995aa5b7d 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -434,7 +434,18 @@ flow_build_vars (function_t *func) } static int -flow_kill_aliases_visit (def_t *def, void *_kill) +flow_tempop_kill_aliases_visit (tempop_t *tempop, void *_kill) +{ + set_t *kill = (set_t *) _kill; + flowvar_t *var; + var = tempop->flowvar; + if (var) + set_union (kill, var->define); + return 0; +} + +static int +flow_def_kill_aliases_visit (def_t *def, void *_kill) { set_t *kill = (set_t *) _kill; flowvar_t *var; @@ -454,19 +465,11 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) op = var->op; tmp = set_new (); if (op->op_type == op_temp) { - if (op->o.tempop.alias) { - op = op->o.tempop.alias; - var = op->o.tempop.flowvar; - if (var) - set_union (tmp, var->define); - } - for (op = op->o.tempop.alias_ops; op; op = op->next) { - var = op->o.tempop.flowvar; - if (var) - set_union (tmp, var->define); - } + tempop_visit_all (&op->o.tempop, 1, flow_tempop_kill_aliases_visit, + tmp); + set_difference (tmp, uninit); } else if (op->op_type == op_def) { - def_visit_all (op->o.def, 1, flow_kill_aliases_visit, tmp); + def_visit_all (op->o.def, 1, flow_def_kill_aliases_visit, tmp); // don't allow aliases to kill definitions in the entry dummy block set_difference (tmp, uninit); } diff --git a/tools/qfcc/test/vecexpr.r b/tools/qfcc/test/vecexpr.r index de6b3af7c..4007348e1 100644 --- a/tools/qfcc/test/vecexpr.r +++ b/tools/qfcc/test/vecexpr.r @@ -1,3 +1,4 @@ +#include "test-harness.h" vector t1() { @@ -19,5 +20,18 @@ t3(float x) int main () { - return t3(5) == [10, 18, 10] ? 0 : 1; + int ret = 0; + vector v; + + v = t2(5); + if (v != [5, 5, 5]) { + printf("t2(5) = %v\n", v); + ret |= 1; + } + v = t3 (5); + if (v != [10, 18, 10]) { + printf("t3(5) = %v\n", v); + ret |= 1; + } + return ret; } From 82b334e919ddc61047ad2921c5e3f7350c5ce423 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 19:12:18 +0900 Subject: [PATCH 0148/3664] Number dot dumps to help identify order --- tools/qfcc/source/dot.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dot.c b/tools/qfcc/source/dot.c index 54d67c241..5d72b5150 100644 --- a/tools/qfcc/source/dot.c +++ b/tools/qfcc/source/dot.c @@ -40,14 +40,23 @@ #include "options.h" #include "strpool.h" +static function_t *last_func; +static int dot_index; + void dump_dot (const char *stage, void *data, void (*dump_func) (void *data, const char *fname)) { char *fname; - fname = nva ("%s.%s.%s.dot", options.output_file, current_func->name, - stage); + if (last_func != current_func) { + last_func = current_func; + dot_index = 0; + } else { + dot_index++; + } + fname = nva ("%s.%s.%03d.%s.dot", options.output_file, current_func->name, + dot_index, stage); dump_func (data, fname); free (fname); } From 2977c145d0521b9464028c5eabc3f0b9457e52ea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 19:17:01 +0900 Subject: [PATCH 0149/3664] Clean up dag live alias code a little Mainly, this makes it possible to reuse the alias code. --- tools/qfcc/source/dags.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 1d773066b..78fdd7f1d 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -381,7 +381,8 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) def_visit_all (op->o.def, 1, dagnode_def_set_edges_visit, n); } - if (op->op_type == op_temp) { + if (op->op_type == op_temp + && (op->o.tempop.alias || op->o.tempop.alias_ops)) { tempop_visit_all (&op->o.tempop, 1, dagnode_tempop_set_edges_visit, n); } @@ -488,7 +489,10 @@ dag_kill_aliases (daglabel_t *l) operand_t *op = l->op; if (op->op_type == op_temp) { - tempop_visit_all (&op->o.tempop, 1, dag_tempop_kill_aliases_visit, l); + if (op->o.tempop.alias || op->o.tempop.alias_ops) { + tempop_visit_all (&op->o.tempop, 1, + dag_tempop_kill_aliases_visit, l); + } } else if (op->op_type == op_def) { if (op->o.def->alias || op->o.def->alias_defs) { def_visit_all (op->o.def, 1, dag_def_kill_aliases_visit, l); @@ -516,6 +520,21 @@ dag_def_live_aliases (def_t *def, void *_d) return 0; } +static void +dag_live_aliases(operand_t *op) +{ + // FIXME it would be better to propogate the aliasing + if (op->op_type == op_temp + && (op->o.tempop.alias || op->o.tempop.alias_ops)) { + tempop_visit_all (&op->o.tempop, 1, dag_tempop_live_aliases, + &op->o.tempop); + } + if (op->op_type == op_def + && (op->o.def->alias || op->o.def->alias_defs)) { + def_visit_all (op->o.def, 1, dag_def_live_aliases, op->o.def); + } +} + static void dagnode_attach_label (dagnode_t *n, daglabel_t *l) { @@ -541,18 +560,7 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l) set_add (n->identifiers, l->number); dag_kill_aliases (l); if (n->label->op) { - // FIXME it would be better to propogate the aliasing - if (n->label->op->op_type == op_temp) { - tempop_visit_all (&n->label->op->o.tempop, 1, - dag_tempop_live_aliases, - &n->label->op->o.tempop); - } - if (n->label->op->op_type == op_def - && (n->label->op->o.def->alias - || n->label->op->o.def->alias_defs)) { - def_visit_all (n->label->op->o.def, 1, dag_def_live_aliases, - n->label->op->o.def); - } + dag_live_aliases (n->label->op); } } From db4a7a139ef22e350417502575de1a9ebd28e43f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 19:17:45 +0900 Subject: [PATCH 0150/3664] Use the alias code when making vars live Not sure the live forcing flag is needed anymore (need to test). --- tools/qfcc/source/dags.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 78fdd7f1d..1acf9031a 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -535,6 +535,19 @@ dag_live_aliases(operand_t *op) } } +static void +dag_make_var_live (set_t *live_vars, operand_t *op) +{ + flowvar_t *var = 0; + + if (op) { + dag_live_aliases (op); + var = flow_get_var (op); + } + if (var) + set_add (live_vars, var->number); +} + static void dagnode_attach_label (dagnode_t *n, daglabel_t *l) { @@ -650,17 +663,6 @@ dag_sort_nodes (dag_t *dag) dag->num_topo = topo; } -static void -dag_make_var_live (set_t *live_vars, operand_t *op) -{ - flowvar_t *var = 0; - - if (op) - var = flow_get_var (op); - if (var) - set_add (live_vars, var->number); -} - static void dag_kill_nodes (dag_t *dag, dagnode_t *n) { From 6e21c3ae2e0a6fec63e9a1f27f93d1ebe1321e1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 19:19:03 +0900 Subject: [PATCH 0151/3664] Treat func statements similarly to flow statements func statements need their operands marked live like flow statements do because usage is more indirect. --- tools/qfcc/source/dags.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 1acf9031a..ee3ccfb1a 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -724,7 +724,7 @@ dag_create (flownode_t *flownode) int i; dag_make_children (dag, s, operands, children); - if (s->type == st_flow) + if (s->type == st_flow || s->type == st_func) for (i = 0; i < 3; i++) if (children[i]) dag_make_var_live (live_vars, operands[i]); From d6d302741117e16d558e581eaa1871aaea981590 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 19:21:02 +0900 Subject: [PATCH 0152/3664] Mark the correct operand as live This fixes vecexpr (and possibly other cases). --- tools/qfcc/source/dags.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index ee3ccfb1a..3b9300527 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -727,7 +727,7 @@ dag_create (flownode_t *flownode) if (s->type == st_flow || s->type == st_func) for (i = 0; i < 3; i++) if (children[i]) - dag_make_var_live (live_vars, operands[i]); + dag_make_var_live (live_vars, operands[i + 1]); op = opcode_label (dag, s->opcode, s->expr); n = children[0]; if (s->type != st_assign From ec128ffeee43f591471c372b14ae1f00f43a1661 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jun 2019 19:24:19 +0900 Subject: [PATCH 0153/3664] Leave a FIXME for daglabel_t.live --- tools/qfcc/include/dags.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index 7b624ea2e..c083b8502 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -46,7 +46,7 @@ typedef struct daglabel_s { struct daglabel_s *next; struct daglabel_s *daglabel_chain; ///< all labels created for a dag int number; ///< index into array of labels in dag_t - unsigned live:1; ///< accessed via an alias + unsigned live:1; ///< accessed via an alias FIXME redundant? const char *opcode; ///< not if op struct operand_s *op; ///< not if opcode; struct dagnode_s *dagnode; ///< node with which this label is associated From e9c24dbf1cbcca8178fce5bcb1f0e88aefe53186 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jun 2019 22:47:44 +0900 Subject: [PATCH 0154/3664] Test case for accessing nested struct fields Currently fails. --- tools/qfcc/test/Makefile.am | 10 +++++++ tools/qfcc/test/structstruct.r | 53 ++++++++++++++++++++++++++++++++++ tools/qfcc/test/test-harness.h | 1 + 3 files changed, 64 insertions(+) create mode 100644 tools/qfcc/test/structstruct.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 96351e926..680fdbdd7 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -47,6 +47,7 @@ test_progs_dat=\ structarray.dat \ structlive.dat \ structptr.dat \ + structstruct.dat \ swap.dat \ triangle.dat \ vecexpr.dat \ @@ -236,6 +237,15 @@ structptr.run: Makefile build-run include ./$(DEPDIR)/structptr.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/structptr.Qo +structstruct_dat_SOURCES=structstruct.r +structstruct_obj=$(structstruct_dat_SOURCES:.r=.qfo) +structstruct.dat$(EXEEXT): $(structstruct_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(structstruct_obj) +structstruct.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/structstruct.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/structstruct.Qo + swap_dat_SOURCES=swap.r swap_obj=$(swap_dat_SOURCES:.r=.qfo) swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/structstruct.r b/tools/qfcc/test/structstruct.r new file mode 100644 index 000000000..5ae1e06e5 --- /dev/null +++ b/tools/qfcc/test/structstruct.r @@ -0,0 +1,53 @@ +#include "test-harness.h" + +typedef struct Point { + int x; + int y; +} Point; + +typedef struct Size { + int width; + int height; +} Size; + +typedef struct Rect { + Point origin; + Size size; +} Rect; + +Rect rect = {{1, 2}, {3, 4}}; + +int +test_struct_1(Rect rect) +{ + return rect.origin.x; +} + +int +test_struct_2(Rect rect) +{ + return rect.origin.y; +} + +int +test_struct_3(Rect rect) +{ + return rect.size.width; +} + +int +test_struct_4(Rect rect) +{ + return rect.size.height; +} + +int +main() +{ + int ret = 0; + ret |= test_struct_1(rect) != 1; + ret |= test_struct_2(rect) != 2; + ret |= test_struct_3(rect) != 3; + ret |= test_struct_4(rect) != 4; + return ret; +} diff --git a/tools/qfcc/test/test-harness.h b/tools/qfcc/test/test-harness.h index 959910534..f350c7ec7 100644 --- a/tools/qfcc/test/test-harness.h +++ b/tools/qfcc/test/test-harness.h @@ -1,3 +1,4 @@ +void *obj_malloc (int size) = #0; void printf (string fmt, ...) = #0; int errno (void) = #0; string strerror (int err) = #0; From dd52b7fea1a40a0ebc18de3264d7597a81064045 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jun 2019 22:48:42 +0900 Subject: [PATCH 0155/3664] Merge aliased alias expressions This comes up when accessing struct fields nested in another struct. Fixes the nested struct fields test. --- tools/qfcc/source/expr.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 7b5b8edbb..5b2a3b129 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1020,6 +1020,9 @@ new_alias_expr (type_t *type, expr_t *expr) alias->e.expr.type = type; //if (expr->type == ex_uexpr && expr->e.expr.op == 'A') // bug (alias, "aliasing an alias expression"); + if (expr->type == ex_expr && expr->e.expr.op == 'A') { + return new_offset_alias_expr (type, expr, 0); + } alias->file = expr->file; alias->line = expr->line; return alias; @@ -1030,6 +1033,14 @@ new_offset_alias_expr (type_t *type, expr_t *expr, int offset) { expr_t *alias; + if (expr->type == ex_expr && expr->e.expr.op == 'A') { + expr_t *ofs_expr = expr->e.expr.e2; + expr = expr->e.expr.e1; + if (!is_constant (ofs_expr)) { + internal_error (ofs_expr, "non-constant offset for alias expr"); + } + offset += expr_integer (ofs_expr); + } alias = new_binary_expr ('A', expr, new_integer_expr (offset)); alias->e.expr.type = type; alias->file = expr->file; From e0c8285f075e394f5370300451e7767b9d94a761 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jun 2019 22:57:21 +0900 Subject: [PATCH 0156/3664] Extend nested struct test to cover struct copy Fails :P --- tools/qfcc/test/structstruct.r | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/qfcc/test/structstruct.r b/tools/qfcc/test/structstruct.r index 5ae1e06e5..c8ef25fad 100644 --- a/tools/qfcc/test/structstruct.r +++ b/tools/qfcc/test/structstruct.r @@ -16,6 +16,8 @@ typedef struct Rect { } Rect; Rect rect = {{1, 2}, {3, 4}}; +Point origin = {5, 6}; +Size size = {7, 8}; int test_struct_1(Rect rect) @@ -49,5 +51,11 @@ main() ret |= test_struct_2(rect) != 2; ret |= test_struct_3(rect) != 3; ret |= test_struct_4(rect) != 4; + rect.origin = origin; + rect.size = size; + ret |= test_struct_1(rect) != 5; + ret |= test_struct_2(rect) != 6; + ret |= test_struct_3(rect) != 7; + ret |= test_struct_4(rect) != 8; return ret; } From b996fb7aa43a0393558b47a49535436de89a6ed4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jun 2019 23:38:34 +0900 Subject: [PATCH 0157/3664] Make operand->type actual type instead of low-level And clean up the resulting mess. This fixes struct copy, but uncovers another bug :/ --- tools/qfcc/include/dags.h | 4 ++-- tools/qfcc/include/def.h | 7 +++--- tools/qfcc/include/statements.h | 4 ++-- tools/qfcc/source/dags.c | 8 +++---- tools/qfcc/source/def.c | 5 ++-- tools/qfcc/source/emit.c | 14 +++++------ tools/qfcc/source/opcodes.c | 6 ++--- tools/qfcc/source/statements.c | 41 ++++++++++++++++----------------- 8 files changed, 44 insertions(+), 45 deletions(-) diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index c083b8502..c0d07c4b3 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -62,7 +62,7 @@ typedef struct dagnode_s { unsigned killed:1; ///< node is unavailable for cse st_type_t type; ///< type of node (st_none = leaf) daglabel_t *label; ///< ident/const if leaf node, or operator - etype_t tl; + struct type_s *tl; struct operand_s *value; ///< operand holding the value of this node /// \name child nodes /// if \a children[0] is null, the rest must be null as well. Similar for @@ -75,7 +75,7 @@ typedef struct dagnode_s { /// topological sort of the DAG. //@{ struct dagnode_s *children[3]; - etype_t types[3]; ///< desired type of each operand (to alias) + struct type_s *types[3]; ///< desired type of each operand (to alias) struct set_s *edges; ///< includes nodes pointed to by \a children //@} struct set_s *identifiers; ///< set of identifiers attached to this node diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 79502a7d0..68b946fab 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -190,14 +190,13 @@ void free_def (def_t *def); \note ::current_func must be valid. - \param type The low-level type of the temporary variable. - \param size The amount of space to allocate to the temp. + \param type The type of the temporary variable. \return The def for the temparary variable. - \bug \a size is not checked for validity (must be 1-4). + \bug size of type must be 1 to 4. \todo support arbitrary sizes */ -def_t *temp_def (etype_t type, int size); +def_t *temp_def (struct type_s *type); /** Free a tempary def so it may be recycled. diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index e0e3dca98..0d91c874f 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -55,7 +55,7 @@ typedef struct { typedef struct operand_s { struct operand_s *next; op_type_e op_type; - etype_t type; ///< possibly override def's type + struct type_s *type; ///< possibly override def's type int size; ///< for structures union { struct def_s *def; @@ -121,7 +121,7 @@ int tempop_overlap (tempop_t *t1, tempop_t *t2); operand_t *temp_operand (struct type_s *type); int tempop_visit_all (tempop_t *tempop, int overlap, int (*visit) (tempop_t *, void *), void *data); -operand_t *alias_operand (etype_t type, operand_t *op); +operand_t *alias_operand (struct type_s *type, operand_t *op); void free_operand (operand_t *op); sblock_t *new_sblock (void); diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 3b9300527..8de4d0e54 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -818,7 +818,7 @@ dag_calc_node_costs (dagnode_t *dagnode) } #endif static operand_t * -fix_op_type (operand_t *op, etype_t type) +fix_op_type (operand_t *op, type_t *type) { if (op && op->op_type != op_label && op->type != type) op = alias_operand (type, op); @@ -884,7 +884,7 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) static operand_t * generate_assignments (dag_t *dag, sblock_t *block, operand_t *src, - set_iter_t *var_iter, etype_t type) + set_iter_t *var_iter, type_t *type) { statement_t *st; operand_t *dst = 0; @@ -912,7 +912,7 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) statement_t *st; set_iter_t *var_iter; int i; - etype_t type; + type_t *type; switch (dagnode->type) { case st_none: @@ -928,7 +928,7 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[0] = make_operand (dag, block, dagnode, 0); if (dagnode->children[1]) operands[1] = make_operand (dag, block, dagnode, 1); - type = low_level_type (get_type (dagnode->label->expr)); + type = get_type (dagnode->label->expr); if (!(var_iter = set_first (dagnode->identifiers))) { operands[2] = temp_operand (get_type (dagnode->label->expr)); } else { diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index facf82348..5848c20c5 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -194,10 +194,11 @@ alias_def (def_t *def, type_t *type, int offset) } def_t * -temp_def (etype_t type, int size) +temp_def (type_t *type) { def_t *temp; defspace_t *space = current_func->symtab->space; + int size = type_size (type); if (size < 1 || size > 4) { internal_error (0, "%d invalid size for temp def", size); @@ -213,7 +214,7 @@ temp_def (etype_t type, int size) temp->name = save_string (va (".tmp%d", current_func->temp_num++)); } temp->return_addr = __builtin_return_address (0); - temp->type = ev_types[type]; + temp->type = type; temp->file = pr.source_file; temp->line = pr.source_line; set_storage_bits (temp, sc_local); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 003204dcb..253502206 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -61,18 +61,18 @@ static def_t zero_def; static def_t * -get_value_def (ex_value_t *value, etype_t type) +get_value_def (ex_value_t *value, type_t *type) { def_t *def; - if (type == ev_short) { + if (type == &type_short) { def = new_def (0, &type_short, 0, sc_extern); def->offset = value->v.short_val; return def; } def = emit_value (value, 0); - if (type != def->type->type) - return alias_def (def, ev_types[type], 0); + if (type != def->type) + return alias_def (def, type, 0); return def; } @@ -87,7 +87,7 @@ get_operand_def (expr_t *expr, operand_t *op) case op_value: return get_value_def (op->o.value, op->type); case op_label: - op->type = ev_short; + op->type = &type_short; zero_def.type = &type_short; return &zero_def; //FIXME case op_temp: @@ -97,11 +97,11 @@ get_operand_def (expr_t *expr, operand_t *op) if (op->o.tempop.alias) { def_t *tdef = get_operand_def (expr, op->o.tempop.alias); int offset = op->o.tempop.offset; - type_t *type = ev_types[op->type]; + type_t *type = op->type; op->o.tempop.def = alias_def (tdef, type, offset); } if (!op->o.tempop.def) { - op->o.tempop.def = temp_def (op->type, op->size); + op->o.tempop.def = temp_def (op->type); } return op->o.tempop.def; case op_alias: diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 4d8bb4678..bf8b5b189 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -102,9 +102,9 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b, int i; search_op.name = name; - search_op.type_a = op_a ? op_a->type : ev_invalid; - search_op.type_b = op_b ? op_b->type : ev_invalid; - search_op.type_c = op_c ? op_c->type : ev_invalid; + search_op.type_a = op_a ? low_level_type (op_a->type) : ev_invalid; + search_op.type_b = op_b ? low_level_type (op_b->type) : ev_invalid; + search_op.type_c = op_c ? low_level_type (op_c->type) : ev_invalid; op = Hash_FindElement (opcode_type_table, &search_op); if (op) return op; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index d476aeeaf..1be5432d1 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -127,7 +127,7 @@ operand_string (operand_t *op) case op_temp: if (op->o.tempop.alias) return va ("", - pr_type_name[op->type], + pr_type_name[op->type->type], op, op->o.tempop.users, op->o.tempop.alias, op->o.tempop.offset, @@ -139,7 +139,7 @@ operand_string (operand_t *op) const char *alias = operand_string (op->o.alias); char *buf = alloca (strlen (alias) + 1); strcpy (buf, alias); - return va ("alias(%s,%s)", pr_type_name[op->type], buf); + return va ("alias(%s,%s)", pr_type_name[op->type->type], buf); } } return ("??"); @@ -150,11 +150,11 @@ print_operand (operand_t *op) { switch (op->op_type) { case op_def: - printf ("(%s) ", pr_type_name[op->type]); + printf ("(%s) ", pr_type_name[op->type->type]); printf ("%s", op->o.def->name); break; case op_value: - printf ("(%s) ", pr_type_name[op->type]); + printf ("(%s) ", pr_type_name[op->type->type]); switch (op->o.value->lltype) { case ev_string: printf ("\"%s\"", op->o.value->v.string_val); @@ -202,12 +202,12 @@ print_operand (operand_t *op) printf ("block %p", op->o.label->dest); break; case op_temp: - printf ("tmp (%s) %p", pr_type_name[op->type], op); + printf ("tmp (%s) %p", pr_type_name[op->type->type], op); if (op->o.tempop.def) printf (" %s", op->o.tempop.def->name); break; case op_alias: - printf ("alias(%s,", pr_type_name[op->type]); + printf ("alias(%s,", pr_type_name[op->type->type]); print_operand (op->o.alias); printf (")"); } @@ -307,7 +307,7 @@ def_operand (def_t *def, type_t *type) if (!type) type = def->type; op = new_operand (op_def); - op->type = low_level_type (type); + op->type = type; op->size = type_size (type); op->o.def = def; return op; @@ -318,7 +318,7 @@ value_operand (ex_value_t *value) { operand_t *op; op = new_operand (op_value); - op->type = value->lltype; + op->type = value->type; op->o.value = value; return op; } @@ -329,7 +329,7 @@ temp_operand (type_t *type) operand_t *op = new_operand (op_temp); op->o.tempop.type = type; - op->type = low_level_type (type); + op->type = type; op->size = type_size (type); return op; } @@ -384,19 +384,18 @@ tempop_visit_all (tempop_t *tempop, int overlap, } operand_t * -alias_operand (etype_t type, operand_t *op) +alias_operand (type_t *type, operand_t *op) { operand_t *aop; - if (pr_type_size[type] != pr_type_size[op->type]) { + if (type_size (type) != type_size (op->type)) { internal_error (0, "\naliasing operand with type of diffent size" - " (%d, %d)", pr_type_size[type], - pr_type_size[op->type]); + " (%d, %d)", type_size (type), type_size (op->type)); } aop = new_operand (op_alias); aop->o.alias = op; aop->type = type; - aop->size = pr_type_size[type]; + aop->size = type_size (type); return aop; } @@ -860,14 +859,14 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) { operand_t *aop = 0; operand_t *top; - etype_t type; + type_t *type; def_t *def; int offset = 0; if (e->type == ex_expr) { offset = expr_integer (e->e.expr.e2); } - type = low_level_type (e->e.expr.type); + type = e->e.expr.type; sblock = statement_subexpr (sblock, e->e.expr.e1, &aop); if (aop->type == type) { if (offset) { @@ -892,7 +891,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) if (!top) { top = new_operand (op_temp); top->type = type; - top->size = pr_type_size[type]; + top->size = type_size (type); top->o.tempop.alias = aop; top->o.tempop.offset = offset; top->next = aop->o.tempop.alias_ops; @@ -903,7 +902,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) def = aop->o.def; while (def->alias) def = def->alias; - *op = def_operand (alias_def (def, ev_types[type], offset), 0); + *op = def_operand (alias_def (def, type, offset), 0); } else { internal_error (e, "invalid alias target: %s: %s", optype_str (aop->op_type), operand_string (aop)); @@ -1037,7 +1036,7 @@ expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op) *op = def_operand (sym->s.func->def, 0); } else { internal_error (e, "unexpected symbol type: %s for %s", - symtype_str(sym->sy_type), sym->name); + symtype_str (sym->sy_type), sym->name); } return sblock; } @@ -1059,9 +1058,9 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) expr_t *ax, *ay, *az, *aw; expr_t *as, *av; expr_t *tmp; - type_t *vec_type = get_type(e); + type_t *vec_type = get_type (e); - tmp = new_temp_def_expr(vec_type); + tmp = new_temp_def_expr (vec_type); if (vec_type == &type_vector) { // guaranteed to have three elements x = e->e.vector.list; From f7825fe7cf52dc1b9629fc395d7ce1a1d48f7979 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jun 2019 00:03:02 +0900 Subject: [PATCH 0158/3664] Print types properly in pointer value expressions --- tools/qfcc/source/dot_expr.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 2925ffcc7..b98cc7b99 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -428,6 +428,11 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) int indent = level * 2 + 2; type_t *type; const char *label = "?!?"; + static dstring_t *type_str; + + if (!type_str) { + type_str = dstring_newstr (); + } switch (e->e.value->lltype) { case ev_string: @@ -451,14 +456,18 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) break; case ev_pointer: type = e->e.value->v.pointer.type; + dstring_clearstr(type_str); + if (type) { + print_type_str (type_str, type); + } if (e->e.value->v.pointer.def) - label = va ("(%s)[%d]<%s>", - type ? pr_type_name[type->type] : "???", + label = va ("(*%s)[%d]<%s>", + type ? type_str->str : "???", e->e.value->v.pointer.val, e->e.value->v.pointer.def->name); else - label = va ("(%s)[%d]", - type ? pr_type_name[type->type] : "???", + label = va ("(*%s)[%d]", + type ? type_str->str : "???", e->e.value->v.pointer.val); break; case ev_field: From fe73547f43528f93113d3810cb363650ba6aee59 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jun 2019 08:53:05 +0900 Subject: [PATCH 0159/3664] Update alias type sameness check This one seems to be fairly robust. Fixes alias being used to cast pointers (maybe a better way, but this works for now). --- tools/qfcc/include/type.h | 2 ++ tools/qfcc/source/statements.c | 4 ++-- tools/qfcc/source/type.c | 27 +++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 92b495753..14f1038f7 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -159,9 +159,11 @@ int is_vector (const type_t *type) __attribute__((pure)); int is_quaternion (const type_t *type) __attribute__((pure)); int is_math (const type_t *type) __attribute__((pure)); int is_pointer (const type_t *type) __attribute__((pure)); +int is_field (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); int is_func (const type_t *type) __attribute__((pure)); +int type_compatible (const type_t *dst, const type_t *src); int type_assignable (const type_t *dst, const type_t *src); int type_size (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 1be5432d1..a0f9b54bf 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -868,9 +868,9 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) } type = e->e.expr.type; sblock = statement_subexpr (sblock, e->e.expr.e1, &aop); - if (aop->type == type) { + if (type_compatible (aop->type, type)) { if (offset) { - internal_error (e, "offset alias of same type"); + internal_error (e, "offset alias of same size type"); } *op = aop; return sblock; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index d63563524..55879f520 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -734,6 +734,14 @@ is_pointer (const type_t *type) return 0; } +int +is_field (const type_t *type) +{ + if (type->type == ev_field) + return 1; + return 0; +} + int is_array (const type_t *type) { @@ -750,6 +758,25 @@ is_func (const type_t *type) return 0; } +int +type_compatible (const type_t *dst, const type_t *src) +{ + // same type + if (dst == src) { + return 1; + } + if (is_field (dst) && is_field (src)) { + return 1; + } + if (is_func (dst) && is_func (src)) { + return 1; + } + if (is_pointer (dst) && is_pointer (src)) { + return 1; + } + return 0; +} + int type_assignable (const type_t *dst, const type_t *src) { From fc50376297d1b7fce1141dd36248f974270ed20c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jun 2019 08:54:18 +0900 Subject: [PATCH 0160/3664] Fix a minor error check mistake --- tools/qfcc/source/type.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 55879f520..d3f286597 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -109,7 +109,7 @@ static type_t *types_freelist; etype_t low_level_type (type_t *type) { - if (type->type >= ev_type_count) + if (type->type > ev_type_count) internal_error (0, "invalid type"); if (type->type == ev_type_count) internal_error (0, "found 'type count' type"); From 0f1f477e64910a8c8a900fc2d15ae131f84e8e09 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jun 2019 10:38:19 +0900 Subject: [PATCH 0161/3664] Set up temp aliases correctly Fixes vector expressions as sub-expresses. I really don't know why I did the temp alias setup that way. --- tools/qfcc/source/statements.c | 4 +--- tools/qfcc/test/vecexpr.r | 8 ++++++++ tools/qfcc/test/vecinit.r | 17 ++++++++++++++--- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index a0f9b54bf..545d5524b 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -889,9 +889,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) } } if (!top) { - top = new_operand (op_temp); - top->type = type; - top->size = type_size (type); + top = temp_operand (type); top->o.tempop.alias = aop; top->o.tempop.offset = offset; top->next = aop->o.tempop.alias_ops; diff --git a/tools/qfcc/test/vecexpr.r b/tools/qfcc/test/vecexpr.r index 4007348e1..131709bf4 100644 --- a/tools/qfcc/test/vecexpr.r +++ b/tools/qfcc/test/vecexpr.r @@ -21,6 +21,8 @@ int main () { int ret = 0; + float x = 4; + float y = 5; vector v; v = t2(5); @@ -33,5 +35,11 @@ main () printf("t3(5) = %v\n", v); ret |= 1; } + v = [x, y, 0] / 2; + if (v != [2, 2.5, 0]) { + printf("v = %v\n", v); + ret |= 1; + } + return ret; } diff --git a/tools/qfcc/test/vecinit.r b/tools/qfcc/test/vecinit.r index d26a94404..653f9e25d 100644 --- a/tools/qfcc/test/vecinit.r +++ b/tools/qfcc/test/vecinit.r @@ -8,8 +8,8 @@ foo (float x, float y, float z) return v; } -float w; -float h; +float w = 2; +float h = 4; vector bar (void) @@ -22,8 +22,19 @@ bar (void) return pos; } +vector +baz (float w, float h) +{ + vector p = [w, h, 0] / 2; + return p; +} + int main () { - return 0; + int ret = 0; + ret |= foo(1,2,3) != [1, 2, 3]; + ret |= bar() != [2, 4, 0]; + ret |= baz(5, 6) != [2.5, 3, 0]; + return ret; } From b37c331e76f8fbec575f9ae142c8f0ec33faa6c8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jun 2019 10:39:17 +0900 Subject: [PATCH 0162/3664] Catch taking size of null type This should help catch similar errors in the future. --- tools/qfcc/source/type.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index d3f286597..d99a89cc4 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -817,8 +817,6 @@ type_assignable (const type_t *dst, const type_t *src) int type_size (const type_t *type) { - if (!type) - return 0; switch (type->type) { case ev_void: case ev_string: From 83fac13a0cc77f174f98f5a247b34843f7e0882d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jun 2019 11:53:58 +0900 Subject: [PATCH 0163/3664] Fix debug line numbers for vector expressions --- tools/qfcc/source/statements.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 545d5524b..c4c92f254 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1057,6 +1057,11 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) expr_t *as, *av; expr_t *tmp; type_t *vec_type = get_type (e); + int file = pr.source_file; + int line = pr.source_line; + + pr.source_file = e->file; + pr.source_line = e->line; tmp = new_temp_def_expr (vec_type); if (vec_type == &type_vector) { @@ -1105,6 +1110,8 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) sblock = statement_slist (sblock, as); } } + pr.source_file = file; + pr.source_line = line; sblock = statement_subexpr (sblock, tmp, op); return sblock; } From a5ee58cebbe542dec148325734fed6be36305e34 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jun 2019 11:54:45 +0900 Subject: [PATCH 0164/3664] Support 2d vector expressions [x, y] expands to [x, y, 0] (for now, might add a 2d vector type). --- tools/qfcc/source/expr.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 5b2a3b129..4970cc7cd 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -645,9 +645,9 @@ new_vector_list (expr_t *e) type = &type_quaternion; case 3: // quaternion or vector. all expressions must be compatible with - // a float + // a float (ie, a scalar) for (t = e; t; t = t->next) - if (!type_assignable (&type_float, get_type (t))) + if (!is_scalar (get_type (t))) return error (t, "invalid type for vector element"); vec = new_expr (); vec->type = ex_vector; @@ -655,18 +655,28 @@ new_vector_list (expr_t *e) vec->e.vector.list = e; break; case 2: - // quaternion. either float-ish, vector or vector, float-ish - if (type_assignable (&type_float, get_type (e)) - && type_assignable (&type_vector, get_type(e->next))) { - // float-ish, vector + if (is_scalar (get_type (e)) && is_scalar (get_type (e->next))) { + // scalar, scalar + // expand [x, y] to [x, y, 0] + e->next->next = new_float_expr (0); + vec = new_expr (); + vec->type = ex_vector; + vec->e.vector.type = type; + vec->e.vector.list = e; + break; + } + // quaternion. either scalar, vector or vector, scalar + if (is_scalar (get_type (e)) + && is_vector (get_type (e->next))) { + // scalar, vector // swap expressions t = e; e = e->next; e->next = t; t->next = 0; - } else if (type_assignable (&type_vector, get_type (e)) - && type_assignable (&type_float, get_type(e->next))) { - // vector, float-ish + } else if (is_vector (get_type (e)) + && is_scalar (get_type (e->next))) { + // vector, scalar // do nothing } else { return error (t, "invalid types for vector elements"); From 8caf2eb584bd68fd4344c020b6011e28dee47eb1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jun 2019 21:37:48 +0900 Subject: [PATCH 0165/3664] Mark some new functions as pure --- tools/qfcc/include/statements.h | 2 +- tools/qfcc/include/type.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 0d91c874f..14a95ae0a 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -117,7 +117,7 @@ const char *optype_str (op_type_e type) __attribute__((const)); operand_t *def_operand (struct def_s *def, struct type_s *type); operand_t *value_operand (struct ex_value_s *value); -int tempop_overlap (tempop_t *t1, tempop_t *t2); +int tempop_overlap (tempop_t *t1, tempop_t *t2) __attribute__((pure)); operand_t *temp_operand (struct type_s *type); int tempop_visit_all (tempop_t *tempop, int overlap, int (*visit) (tempop_t *, void *), void *data); diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 14f1038f7..d064de8ca 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -163,7 +163,7 @@ int is_field (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); int is_func (const type_t *type) __attribute__((pure)); -int type_compatible (const type_t *dst, const type_t *src); +int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); int type_size (const type_t *type) __attribute__((pure)); From ab71311174f2c4aaa9c02222747f6e7f2afedb1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 6 Jul 2019 14:44:22 +0900 Subject: [PATCH 0166/3664] Correct some comments --- include/QF/set.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/QF/set.h b/include/QF/set.h index 0d50700da..2f4dd76e5 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -251,7 +251,7 @@ set_t *set_empty (set_t *set); */ set_t *set_everything (set_t *set); -/** Test if a set is the set of everything. +/** Test if a set is the empty set. \param set The set to test. \return 1 if \a set is empty (non-inverted). @@ -358,8 +358,8 @@ set_iter_t *set_next_r (set_pool_t *set_pool, set_iter_t *set_iter); /** Return a human-readable string representing the set. - Empty sets will be represented by the string "[empty]". Sets of everything - will be represented by the string "[everything]". Inverted sets will have + Empty sets will be represented by the string "{}". Sets of everything + will be represented by the string "{...}". Inverted sets will have the first implicit member followed by "..." (eg, "256 ..."). \param set The set to be converted to a string. From c727f6a130ba9bbffd69fbe9a7a0f59b5c104f0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 6 Jul 2019 14:45:40 +0900 Subject: [PATCH 0167/3664] Rewrite QuatMultVec to be faster Could be faster still using SSE, but that's another project. --- libs/util/mathlib.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index a1e11f48b..db68455f3 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -258,15 +258,18 @@ QuatMult (const quat_t q1, const quat_t q2, quat_t out) VISIBLE void QuatMultVec (const quat_t q, const vec3_t v, vec3_t out) { - vec_t s; vec3_t tv; + vec_t dqv, dqq; + vec_t s; - s = -DotProduct (q, v); + s = q[3]; CrossProduct (q, v, tv); - VectorMultAdd (tv, q[3], v, tv); - CrossProduct (q, tv, out); - VectorMultSub (out, s, q, out); - VectorMultAdd (out, q[3], tv, out); + dqv = DotProduct (q, v); + dqq = DotProduct (q, q); + VectorScale (tv, s, tv); + VectorMultAdd (tv, dqv, q, tv); + VectorAdd (tv, tv, tv); + VectorMultAdd (tv, s * s - dqq, v, out); } VISIBLE void From c3fa78ef4df9a48d43a031ac04a49f3de0cdac33 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 6 Jul 2019 14:49:28 +0900 Subject: [PATCH 0168/3664] Include test for 2d vector expressions --- tools/qfcc/test/vecexpr.r | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/test/vecexpr.r b/tools/qfcc/test/vecexpr.r index 131709bf4..8667b0c93 100644 --- a/tools/qfcc/test/vecexpr.r +++ b/tools/qfcc/test/vecexpr.r @@ -35,8 +35,8 @@ main () printf("t3(5) = %v\n", v); ret |= 1; } - v = [x, y, 0] / 2; - if (v != [2, 2.5, 0]) { + v = [x, y] / 2; + if (v != [2, 2.5]) { printf("v = %v\n", v); ret |= 1; } From 2bc78e7f0a56e0ac696841be5899f44246b449f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 6 Jul 2019 14:42:53 +0900 Subject: [PATCH 0169/3664] Start work on a Vulkan-based renderer Doesn't do much other than create an instance and enumerate some stuff, but the build system is working. --- config.d/ac_config_files.m4 | 1 + config.d/build_control.m4 | 10 +- config.d/vulkan.m4 | 24 ++ configure.ac | 1 + include/QF/Vulkan/cvars.h | 7 + include/QF/Vulkan/funclist.h | 55 +++ include/QF/Vulkan/funcs.h | 9 + include/QF/Vulkan/init.h | 65 +++ include/QF/Vulkan/qf_draw.h | 37 ++ include/QF/Vulkan/qf_vid.h | 36 ++ libs/video/renderer/Makefile.am | 10 +- libs/video/renderer/vid_render_vulkan.c | 193 +++++++++ libs/video/renderer/vulkan/Makefile.am | 26 ++ libs/video/renderer/vulkan/init.c | 390 ++++++++++++++++++ libs/video/renderer/vulkan/namehack.h | 137 ++++++ libs/video/renderer/vulkan/vulkan_draw.c | 189 +++++++++ libs/video/renderer/vulkan/vulkan_funcs.c | 6 + .../video/renderer/vulkan/vulkan_vid_common.c | 129 ++++++ 18 files changed, 1319 insertions(+), 6 deletions(-) create mode 100644 config.d/vulkan.m4 create mode 100644 include/QF/Vulkan/cvars.h create mode 100644 include/QF/Vulkan/funclist.h create mode 100644 include/QF/Vulkan/funcs.h create mode 100644 include/QF/Vulkan/init.h create mode 100644 include/QF/Vulkan/qf_draw.h create mode 100644 include/QF/Vulkan/qf_vid.h create mode 100644 libs/video/renderer/vid_render_vulkan.c create mode 100644 libs/video/renderer/vulkan/Makefile.am create mode 100644 libs/video/renderer/vulkan/init.c create mode 100644 libs/video/renderer/vulkan/namehack.h create mode 100644 libs/video/renderer/vulkan/vulkan_draw.c create mode 100644 libs/video/renderer/vulkan/vulkan_funcs.c create mode 100644 libs/video/renderer/vulkan/vulkan_vid_common.c diff --git a/config.d/ac_config_files.m4 b/config.d/ac_config_files.m4 index 587a515d9..499c93099 100644 --- a/config.d/ac_config_files.m4 +++ b/config.d/ac_config_files.m4 @@ -32,6 +32,7 @@ libs/video/renderer/glsl/Makefile libs/video/renderer/sw/Makefile libs/video/renderer/sw32/Makefile + libs/video/renderer/vulkan/Makefile libs/video/targets/Makefile hw/Makefile diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index abc60cd75..94a7415af 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -71,7 +71,7 @@ if test "x$HAVE_X" = xyes; then NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA quakeforge-nq-x11.desktop" CL_TARGETS="$CL_TARGETS X11" VID_TARGETS="$VID_TARGETS libQFx11.la" - QF_NEED(vid_render, [sw sw32 gl glsl]) + QF_NEED(vid_render, [sw sw32 gl glsl vulkan]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -95,7 +95,7 @@ if test "x$HAVE_SDL" = xyes; then NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA quakeforge-nq-sdl.desktop" CL_TARGETS="$CL_TARGETS SDL" VID_TARGETS="$VID_TARGETS libQFsdl.la" - QF_NEED(vid_render, [sw sw32 gl glsl]) + QF_NEED(vid_render, [sw sw32 gl glsl vulkan]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -258,7 +258,7 @@ QF_SUBST(progs_gz) QF_PROCESS_NEED_DIRS(top, [libs hw nq qtv qw tools ruamoko]) QF_PROCESS_NEED_LIBS(swrend, [asm]) -QF_PROCESS_NEED_DIRS(vid_render, [gl glsl sw sw32]) +QF_PROCESS_NEED_DIRS(vid_render, [gl glsl sw sw32 vulkan]) QF_PROCESS_NEED_LIBS(models, [gl glsl sw]) QF_PROCESS_NEED_LIBS(alias, [gl glsl sw]) QF_PROCESS_NEED_LIBS(brush, [gl glsl sw]) @@ -308,7 +308,7 @@ if test "x$static_plugins" = xauto; then fi fi if test "x$static_plugins" = xyes; then - QF_PROCESS_NEED_STATIC_PLUGINS(vid_render, [sw sw32 glsl gl]) + QF_PROCESS_NEED_STATIC_PLUGINS(vid_render, [sw sw32 glsl gl vulkan]) QF_PROCESS_NEED_STATIC_PLUGINS(console, [server], [\$(top_builddir)/libs/console], [server]) QF_PROCESS_NEED_STATIC_PLUGINS(console, [client], [\$(top_builddir)/libs/console], [client]) @@ -323,7 +323,7 @@ if test "x$static_plugins" = xyes; then CDTYPE="$CDTYPE (static)" fi else - QF_PROCESS_NEED_PLUGINS(vid_render, [sw sw32 glsl gl]) + QF_PROCESS_NEED_PLUGINS(vid_render, [sw sw32 glsl gl vulkan]) QF_PROCESS_NEED_PLUGINS(console, [server], [server]) QF_PROCESS_NEED_PLUGINS(console, [client], [client]) QF_PROCESS_NEED_PLUGINS(snd_output, [sdl mme sgi sun win dx oss alsa]) diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 new file mode 100644 index 000000000..c82900f58 --- /dev/null +++ b/config.d/vulkan.m4 @@ -0,0 +1,24 @@ +dnl Check for vulkan support +AC_ARG_ENABLE(vulkan, +[ --disable-vulkan do not use Vulkan], + HAVE_VULKAN=$enable_vulkan, HAVE_VULKAN=auto) +if test "x$HAVE_VULKAN" != xno; then + save_CPPFLAGS="$CPPFLAGS" + AS_IF([test x"$VULKAN_SDK" != x], [ + CPPFLAGS="$CPPFLAGS -I$VULKAN_SDK/include" + LDFLAGS="$LDFLAGS -L$VULKAN_SDK/lib" + glslangvalidator="$VULKAN_SDK/bin/glslangValidator" + ], [glslangvalidator="glslangValidator"]) + AC_CHECK_HEADER( + [vulkan/vulkan.h], + dnl Make sure the library "works" + [AC_CHECK_LIB([vulkan], [vkCreateInstance], + [AC_DEFINE([HAVE_VULKAN], [1], [Define if yhou have the Vulkan libs]) + VULKAN_LIBS=-lvulkan], + [AC_MSG_RESULT(no)]) + ], + [AC_MSG_RESULT(no)] + ) + CPPFLAGS="$save_CPPFLAGS" +fi +AC_SUBST(VULKAN_LIBS) diff --git a/configure.ac b/configure.ac index ea203472c..aaf6492ea 100644 --- a/configure.ac +++ b/configure.ac @@ -64,6 +64,7 @@ m4_include(config.d/mgl.m4) m4_include(config.d/fbdev.m4) m4_include(config.d/svga.m4) m4_include(config.d/x11.m4) +m4_include(config.d/vulkan.m4) m4_include(config.d/sdl.m4) m4_include(config.d/curses.m4) diff --git a/include/QF/Vulkan/cvars.h b/include/QF/Vulkan/cvars.h new file mode 100644 index 000000000..9f318b8f0 --- /dev/null +++ b/include/QF/Vulkan/cvars.h @@ -0,0 +1,7 @@ +#ifndef __QF_Vulkan_cvars_h +#define __QF_Vulkan_cvars_h + +extern struct cvar_s *vulkan_library_name; +extern struct cvar_s *vulkan_use_validation; + +#endif//__QF_Vulkan_cvars_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h new file mode 100644 index 000000000..1ab96300c --- /dev/null +++ b/include/QF/Vulkan/funclist.h @@ -0,0 +1,55 @@ +#ifndef EXPORTED_VULKAN_FUNCTION +#define EXPORTED_VULKAN_FUNCTION(function) +#endif + +EXPORTED_VULKAN_FUNCTION (vkGetInstanceProcAddr) + +#undef EXPORTED_VULKAN_FUNCTION + +#ifndef GLOBAL_LEVEL_VULKAN_FUNCTION +#define GLOBAL_LEVEL_VULKAN_FUNCTION(function) +#endif + +GLOBAL_LEVEL_VULKAN_FUNCTION (vkEnumerateInstanceVersion) +GLOBAL_LEVEL_VULKAN_FUNCTION (vkEnumerateInstanceExtensionProperties) +GLOBAL_LEVEL_VULKAN_FUNCTION (vkEnumerateInstanceLayerProperties) +GLOBAL_LEVEL_VULKAN_FUNCTION (vkCreateInstance) + +#undef GLOBAL_LEVEL_VULKAN_FUNCTION + +#ifndef INSTANCE_LEVEL_VULKAN_FUNCTION +#define INSTANCE_LEVEL_VULKAN_FUNCTION(function) +#endif + +INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumeratePhysicalDevices) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateDevice) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetDeviceProcAddr) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceLayerProperties) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceExtensionProperties) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceQueueFamilyProperties) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance) + +#undef INSTANCE_LEVEL_VULKAN_FUNCTION + +#ifndef INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION +#define INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION(function) +#endif + +INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION (vkCreateDebugUtilsMessengerEXT) + +#undef INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION + +#ifndef DEVICE_LEVEL_VULKAN_FUNCTION +#define DEVICE_LEVEL_VULKAN_FUNCTION(function) +#endif + +#undef DEVICE_LEVEL_VULKAN_FUNCTION + +#ifndef DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION +#define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(function) +#endif + +#undef DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION diff --git a/include/QF/Vulkan/funcs.h b/include/QF/Vulkan/funcs.h new file mode 100644 index 000000000..975f5485b --- /dev/null +++ b/include/QF/Vulkan/funcs.h @@ -0,0 +1,9 @@ +#ifndef __QF_Vulkan_funcs_h +#define __QF_Vulkan_funcs_h + +#define EXPORTED_VULKAN_FUNCTION(fname) extern PFN_##fname fname; +#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) extern PFN_##fname fname; + +#include "QF/Vulkan/funclist.h" + +#endif//__QF_Vulkan_funcs_h diff --git a/include/QF/Vulkan/init.h b/include/QF/Vulkan/init.h new file mode 100644 index 000000000..b12dcd42e --- /dev/null +++ b/include/QF/Vulkan/init.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2019 Bill Currie + + Author: Bill Currie + Date: 2019/6/29 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_init_h +#define __QF_Vulkan_init_h + +#include + +#include "QF/qtypes.h" +#include "QF/Vulkan/funcs.h" + +typedef struct { + VkPhysicalDevice device; + VkPhysicalDeviceProperties properties; + uint32_t numLayers; + VkLayerProperties *layers; + uint32_t numExtensions; + VkExtensionProperties *extensions; + VkPhysicalDeviceFeatures features; + VkPhysicalDeviceMemoryProperties memory; + uint32_t numQueueFamilies; + VkQueueFamilyProperties *queueFamilies; +} VulkanPhysDevice_t; + +typedef struct { + VkInstance instance; + VkDebugUtilsMessengerEXT debug_callback; + uint32_t numDevices; + VulkanPhysDevice_t *devices; + + #define INSTANCE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; + #define INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) PFN_##name name; + #include "QF/Vulkan/funclist.h" +} VulkanInstance_t; + +void Vulkan_Init_Cvars (void); +VulkanInstance_t *Vulkan_CreateInstance (const char *appName, + uint32_t appVersion, + const char **layers, + const char **extensions); +void Vulkan_DestroyInstance (VulkanInstance_t *instance); + +#endif // __QF_Vulkan_init_h diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h new file mode 100644 index 000000000..e4716f7ed --- /dev/null +++ b/include/QF/Vulkan/qf_draw.h @@ -0,0 +1,37 @@ +/* + qf_draw.h + + vulkan specific draw function + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __gl_draw_h +#define __gl_draw_h + +void Vulkan_Set2D (void); +void Vulkan_Set2DScaled (void); +void Vulkan_End2D (void); +void Vulkan_DrawReset (void); +void Vulkan_FlushText (void); + +#endif//__gl_draw_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h new file mode 100644 index 000000000..d032a075a --- /dev/null +++ b/include/QF/Vulkan/qf_vid.h @@ -0,0 +1,36 @@ +/* + Vulkan/qf_vid.h + + vulkan vid stuff from the renderer. + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_Vulkan_vid_h +#define __QF_Vulkan_vid_h + +#include "QF/Vulkan/cvars.h" + +void Vulkan_Init_Common (void); +void Vulkan_Shutdown_Common (void); + +#endif // __QF_Vulkan_vid_h diff --git a/libs/video/renderer/Makefile.am b/libs/video/renderer/Makefile.am index 2c234fe33..f7a0fa0cd 100644 --- a/libs/video/renderer/Makefile.am +++ b/libs/video/renderer/Makefile.am @@ -16,7 +16,8 @@ noinst_LTLIBRARIES= libQFrenderer.la @vid_render_static_plugins@ EXTRA_LTLIBRARIES= \ vid_render_sw.la vid_render_sw32.la \ - vid_render_gl.la vid_render_glsl.la + vid_render_gl.la vid_render_glsl.la \ + vid_render_vulkan.la common_sources= \ crosshair.c noisetextures.c r_alias.c r_bsp.c r_cvar.c r_dyn_textures.c \ @@ -63,3 +64,10 @@ vid_render_sw32_la_LDFLAGS= $(plugin_ldflags) vid_render_sw32_la_LIBADD= $(sw32_libs) vid_render_sw32_la_DEPENDENCIES=$(sw32_libs) vid_render_sw32_la_SOURCES= $(common_sources) vid_render_sw32.c + +vulkan_libs= \ + vulkan/libvulkan.la +vid_render_vulkan_la_LDFLAGS= $(plugin_ldflags) +vid_render_vulkan_la_LIBADD= $(vulkan_libs) +vid_render_vulkan_la_DEPENDENCIES=$(vulkan_libs) +vid_render_vulkan_la_SOURCES= $(common_sources) vid_render_vulkan.c diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c new file mode 100644 index 000000000..820d58fa6 --- /dev/null +++ b/libs/video/renderer/vid_render_vulkan.c @@ -0,0 +1,193 @@ +/* + vid_render_vulkan.c + + Vulkan version of the renderer + + Copyright (C) 2019 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define NH_DEFINE +#include "vulkan/namehack.h" + +#include "QF/plugin/general.h" +#include "QF/plugin/vid_render.h" + +#include "QF/Vulkan/qf_vid.h" + +#include "mod_internal.h" +#include "r_internal.h" + +#include "vulkan/namehack.h" + +static vid_model_funcs_t model_funcs = { +/* vulkan_Mod_LoadExternalTextures, + vulkan_Mod_LoadLighting, + vulkan_Mod_SubdivideSurface, + vulkan_Mod_ProcessTexture, + + Mod_LoadIQM, + Mod_LoadAliasModel, + Mod_LoadSpriteModel, + + vulkan_Mod_MakeAliasModelDisplayLists, + vulkan_Mod_LoadSkin, + vulkan_Mod_FinalizeAliasModel, + vulkan_Mod_LoadExternalSkins, + vulkan_Mod_IQMFinish, + 0, + vulkan_Mod_SpriteLoadTexture, + + Skin_SetColormap, + Skin_SetSkin, + vulkan_Skin_SetupSkin, + Skin_SetTranslation, + vulkan_Skin_ProcessTranslation, + vulkan_Skin_InitTranslations,*/ +}; + +vid_render_funcs_t vulkan_vid_render_funcs = { + vulkan_Draw_Init, + vulkan_Draw_Character, + vulkan_Draw_String, + vulkan_Draw_nString, + vulkan_Draw_AltString, + vulkan_Draw_ConsoleBackground, + vulkan_Draw_Crosshair, + vulkan_Draw_CrosshairAt, + vulkan_Draw_TileClear, + vulkan_Draw_Fill, + vulkan_Draw_TextBox, + vulkan_Draw_FadeScreen, + vulkan_Draw_BlendScreen, + vulkan_Draw_CachePic, + vulkan_Draw_UncachePic, + vulkan_Draw_MakePic, + vulkan_Draw_DestroyPic, + vulkan_Draw_PicFromWad, + vulkan_Draw_Pic, + vulkan_Draw_Picf, + vulkan_Draw_SubPic, + +/* vulkan_SCR_UpdateScreen, + SCR_DrawRam, + SCR_DrawTurtle, + SCR_DrawPause, + vulkan_SCR_CaptureBGR, + vulkan_SCR_ScreenShot, + SCR_DrawStringToSnap, + + vulkan_Fog_Update, + vulkan_Fog_ParseWorldspawn, + + vulkan_R_Init, + vulkan_R_ClearState, + vulkan_R_LoadSkys, + vulkan_R_NewMap, + R_AddEfrags, + R_RemoveEfrags, + R_EnqueueEntity, + vulkan_R_LineGraph, + R_AllocDlight, + R_AllocEntity, + vulkan_R_RenderView, + R_DecayLights, + vulkan_R_ViewChanged, + vulkan_R_ClearParticles, + vulkan_R_InitParticles, + vulkan_SCR_ScreenShot_f, + vulkan_r_easter_eggs_f, + vulkan_r_particles_style_f, + 0, + &model_funcs*/ +}; + +static void +set_palette (const byte *palette) +{ + //FIXME really don't want this here: need an application domain + //so Quake can be separated from QuakeForge (ie, Quake itself becomes + //an app using the QuakeForge engine) +} + +static void +vulkan_vid_render_init (void) +{ + vr_data.vid->set_palette = set_palette; + vr_data.vid->init_gl = Vulkan_Init_Common; + vr_data.vid->load_gl (); + vr_funcs = &vulkan_vid_render_funcs; + m_funcs = &model_funcs; +} + +static void +vulkan_vid_render_shutdown (void) +{ + Vulkan_Shutdown_Common (); +} + +static general_funcs_t plugin_info_general_funcs = { + vulkan_vid_render_init, + vulkan_vid_render_shutdown, +}; + +static general_data_t plugin_info_general_data; + +static plugin_funcs_t plugin_info_funcs = { + &plugin_info_general_funcs, + 0, + 0, + 0, + 0, + 0, + &vulkan_vid_render_funcs, +}; + +static plugin_data_t plugin_info_data = { + &plugin_info_general_data, + 0, + 0, + 0, + 0, + 0, + &vid_render_data, +}; + +static plugin_t plugin_info = { + qfp_snd_render, + 0, + QFPLUGIN_VERSION, + "0.1", + "GLSL Renderer", + "Copyright (C) 1996-1997 Id Software, Inc.\n" + "Copyright (C) 1999-2012 contributors of the QuakeForge project\n" + "Please see the file \"AUTHORS\" for a list of contributors", + &plugin_info_funcs, + &plugin_info_data, +}; + +PLUGIN_INFO(vid_render, vulkan) +{ + return &plugin_info; +} diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am new file mode 100644 index 000000000..f3b3d32c5 --- /dev/null +++ b/libs/video/renderer/vulkan/Makefile.am @@ -0,0 +1,26 @@ +AUTOMAKE_OPTIONS= foreign + +AM_CFLAGS= @PREFER_PIC@ +AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES + +vulkan_src = \ + init.c \ + vulkan_draw.c \ + vulkan_funcs.c \ + vulkan_vid_common.c + +noinst_LTLIBRARIES= libvulkan.la +BUILT_SOURCES= $(shader_gen) + +SUFFICES=.frag .vert .fc .vc .slc .glsl +.glsl.slc: + sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ +.frag.fc: + sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ +.vert.vc: + sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ + +libvulkan_la_SOURCES= $(vulkan_src) + +EXTRA_DIST = $(vulkan_src) $(shader_src) namehack.h +CLEANFILES= *.vc *.fc *.slc diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c new file mode 100644 index 000000000..4967c8125 --- /dev/null +++ b/libs/video/renderer/vulkan/init.c @@ -0,0 +1,390 @@ +/* + int.c + + Copyright (C) 2019 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/init.h" + +cvar_t *vulkan_library_name; +cvar_t *vulkan_use_validation; + +static uint32_t numLayers; +static VkLayerProperties *instanceLayerProperties; +static const char **instanceLayerNames; +static uint32_t numExtensions; +static VkExtensionProperties *instanceExtensionProperties; +static const char **instanceExtensionNames; + +static const char *validationLayers[] = { + "VK_LAYER_LUNARG_standard_validation", + 0, +}; + +static const char *debugExtensions[] = { + VK_EXT_DEBUG_UTILS_EXTENSION_NAME, + 0, +}; + +static const char *device_types[] = { + "other", + "integrated gpu", + "discrete gpu", + "virtual gpu", + "cpu", +}; + +static void +get_instance_layers_and_extensions (void) +{ + uint32_t i; + VkLayerProperties *properties; + VkExtensionProperties *extensions; + + vkEnumerateInstanceLayerProperties (&numLayers, 0); + properties = malloc (numLayers * sizeof (VkLayerProperties)); + vkEnumerateInstanceLayerProperties (&numLayers, properties); + instanceLayerNames = (const char **) malloc ((numLayers + 1) + * sizeof (const char **)); + for (i = 0; i < numLayers; i++) { + instanceLayerNames[i] = properties[i].layerName; + } + instanceLayerNames[i] = 0; + + vkEnumerateInstanceExtensionProperties (0, &numExtensions, 0); + extensions = malloc (numExtensions * sizeof (VkLayerProperties)); + vkEnumerateInstanceExtensionProperties (0, &numExtensions, extensions); + instanceExtensionNames = (const char **) malloc ((numExtensions + 1) + * sizeof (const char **)); + for (i = 0; i < numExtensions; i++) { + instanceExtensionNames[i] = extensions[i].extensionName; + } + instanceExtensionNames[i] = 0; + + if (developer->int_val & SYS_VID) { + for (i = 0; i < numLayers; i++) { + Sys_Printf ("%s %x %u %s\n", + properties[i].layerName, + properties[i].specVersion, + properties[i].implementationVersion, + properties[i].description); + } + for (i = 0; i < numExtensions; i++) { + Sys_Printf ("%d %s\n", + extensions[i].specVersion, + extensions[i].extensionName); + } + } + instanceLayerProperties = properties; + instanceExtensionProperties = extensions; +} + +static void +init_physdev (VulkanInstance_t *instance, VkPhysicalDevice dev, VulkanPhysDevice_t *physdev) +{ + physdev->device = dev; + + instance->vkGetPhysicalDeviceProperties (dev, &physdev->properties); + + instance->vkEnumerateDeviceLayerProperties (dev, &physdev->numLayers, 0); + physdev->layers = malloc (physdev->numLayers * sizeof (VkLayerProperties)); + instance->vkEnumerateDeviceLayerProperties (dev, &physdev->numLayers, + physdev->layers); + + instance->vkEnumerateDeviceExtensionProperties (dev, 0, + &physdev->numExtensions, + 0); + physdev->extensions = malloc (physdev->numExtensions + * sizeof (VkExtensionProperties)); + instance->vkEnumerateDeviceExtensionProperties (dev, 0, + &physdev->numExtensions, + physdev->extensions); + + instance->vkGetPhysicalDeviceFeatures (dev, &physdev->features); + + instance->vkGetPhysicalDeviceMemoryProperties (dev, &physdev->memory); + + instance->vkGetPhysicalDeviceQueueFamilyProperties (dev, + &physdev->numQueueFamilies, + 0); + physdev->queueFamilies = malloc (physdev->numQueueFamilies + * sizeof (VkQueueFamilyProperties)); + instance->vkGetPhysicalDeviceQueueFamilyProperties (dev, + &physdev->numQueueFamilies, + physdev->queueFamilies); + + if (developer->int_val & SYS_VID) { + VkPhysicalDeviceProperties *prop = &physdev->properties; + Sys_Printf ("dev: %p\n", dev); + Sys_Printf (" %x %x\n", prop->apiVersion, prop->driverVersion); + Sys_Printf (" %x %x\n", prop->vendorID, prop->deviceID); + Sys_Printf (" %s: %s\n", device_types[prop->deviceType], + prop->deviceName); + for (uint32_t i = 0; i < physdev->numLayers; i++) { + Sys_Printf (" %s %x %u %s\n", + physdev->layers[i].layerName, + physdev->layers[i].specVersion, + physdev->layers[i].implementationVersion, + physdev->layers[i].description); + } + for (uint32_t i = 0; i < physdev->numExtensions; i++) { + Sys_Printf (" %u %s\n", + physdev->extensions[i].specVersion, + physdev->extensions[i].extensionName); + } + Sys_Printf (" memory types:\n"); + for (uint32_t i = 0; i < physdev->memory.memoryTypeCount; i++) { + Sys_Printf (" %x %d\n", + physdev->memory.memoryTypes[i].propertyFlags, + physdev->memory.memoryTypes[i].heapIndex); + } + Sys_Printf (" memory heaps:\n"); + for (uint32_t i = 0; i < physdev->memory.memoryHeapCount; i++) { + Sys_Printf (" %x %ld\n", + physdev->memory.memoryHeaps[i].flags, + physdev->memory.memoryHeaps[i].size); + } + Sys_Printf (" queue families:\n"); + for (uint32_t i = 0; i < physdev->numQueueFamilies; i++) { + VkQueueFamilyProperties *queue = &physdev->queueFamilies[i]; + VkExtent3D gran = queue->minImageTransferGranularity; + Sys_Printf (" %x %3d %3d [%d %d %d]\n", + queue->queueFlags, + queue->queueCount, + queue->timestampValidBits, + gran.width, gran.height, gran.depth); + } + } +} + +static int +count_strings (const char **str) +{ + int count = 0; + + if (str) { + while (*str++) { + count++; + } + } + return count; +} + +static void +merge_strings (const char **out, const char **in1, const char **in2) +{ + if (in1) { + while (*in1) { + *out++ = *in1++; + } + } + if (in2) { + while (*in2) { + *out++ = *in2++; + } + } +} + +static void +prune_strings (const char * const *reference, const char **strings, + uint32_t *count) +{ + for (int i = *count; i-- > 0; ) { + const char *str = strings[i]; + const char * const *ref; + for (ref = reference; *ref; ref++) { + if (!strcmp (*ref, str)) { + break; + } + } + if (!*ref) { + memmove (strings + i, strings + i + 1, + (--(*count) - i) * sizeof (const char **)); + } + } +} + +static int message_severities = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; +static int message_types = + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + +static VKAPI_ATTR VkBool32 VKAPI_CALL +debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* callbackData, + void *data) +{ + fprintf (stderr, "validation layer: %s\n", callbackData->pMessage); + return VK_FALSE; +} + +static void +setup_debug_callback (VulkanInstance_t *instance) +{ + VkDebugUtilsMessengerCreateInfoEXT createInfo = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .messageSeverity = message_severities, + .messageType = message_types, + .pfnUserCallback = debug_callback, + .pUserData = instance, + }; + instance->vkCreateDebugUtilsMessengerEXT(instance->instance, &createInfo, + 0, &instance->debug_callback); +} + +static void +load_instance_funcs (VulkanInstance_t *instance) +{ +#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) \ + instance->name = (PFN_##name) vkGetInstanceProcAddr (instance->instance, \ + #name); \ + if (!instance->name) { \ + Sys_Error ("Couldn't find instance level function %s", #name); \ + } + +#define INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) \ + instance->name = (PFN_##name) vkGetInstanceProcAddr (instance->instance,\ + #name); \ + if (!instance->name) { \ + Sys_Printf ("Couldn't find instance level function %s", #name); \ + } + +#include "QF/Vulkan/funclist.h" +} + +VulkanInstance_t * +Vulkan_CreateInstance (const char *appName, uint32_t appVersion, + const char **layers, const char **extensions) +{ + VkApplicationInfo appInfo = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, 0, + appName, appVersion, + PACKAGE_STRING, 0x000702ff, //FIXME version + VK_API_VERSION_1_0, + }; + VkInstanceCreateInfo createInfo = { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 0, 0, + &appInfo, + 0, 0, + 0, 0, + }; + VkResult res; + VkInstance instance; + uint32_t numDev, i; + VkPhysicalDevice *devices; + VulkanInstance_t *inst; + + if (!instanceLayerProperties) { + get_instance_layers_and_extensions (); + } + + createInfo.enabledLayerCount = count_strings (layers); + createInfo.ppEnabledLayerNames = layers; + createInfo.enabledExtensionCount = count_strings (extensions); + createInfo.ppEnabledExtensionNames = extensions; + if (vulkan_use_validation->int_val) { + createInfo.enabledLayerCount += count_strings (validationLayers); + createInfo.enabledExtensionCount += count_strings (debugExtensions); + } + const char **lay = alloca (createInfo.enabledLayerCount * sizeof (const char *)); + const char **ext = alloca (createInfo.enabledExtensionCount * sizeof (const char *)); + if (vulkan_use_validation->int_val) { + merge_strings (lay, layers, validationLayers); + merge_strings (ext, extensions, debugExtensions); + } else { + merge_strings (lay, layers, 0); + merge_strings (ext, extensions, 0); + } + prune_strings (instanceLayerNames, lay, + &createInfo.enabledLayerCount); + prune_strings (instanceExtensionNames, ext, + &createInfo.enabledExtensionCount); + createInfo.ppEnabledLayerNames = lay; + createInfo.ppEnabledExtensionNames = ext; + + res = vkCreateInstance (&createInfo, 0, &instance); + if (res != VK_SUCCESS) { + Sys_Error ("unable to create vulkan instance\n"); + } + inst = malloc (sizeof(VulkanInstance_t)); + inst->instance = instance; + load_instance_funcs (inst); + + if (vulkan_use_validation->int_val) { + setup_debug_callback (inst); + } + + res = inst->vkEnumeratePhysicalDevices (instance, &numDev, 0); + if (res != VK_SUCCESS) { + Sys_Error ("unable to query vulkan device count: %d\n", res); + } + devices = malloc(numDev * sizeof (VkPhysicalDevice)); + res = inst->vkEnumeratePhysicalDevices (instance, &numDev, devices); + if (res != VK_SUCCESS) { + Sys_Error ("unable to query vulkan device properties: %d\n", res); + } + + inst->numDevices = numDev; + inst->devices = malloc (numDev * sizeof (VulkanPhysDevice_t)); + + for (i = 0; i < numDev; i++) { + init_physdev (inst, devices[i], &inst->devices[i]); + } + + return inst; +} + +void +Vulkan_DestroyInstance (VulkanInstance_t *instance) +{ + for (uint32_t i = 0; i < instance->numDevices; i++) { + free (instance->devices[i].queueFamilies); + free (instance->devices[i].extensions); + free (instance->devices[i].layers); + } + free (instance->devices); + instance->vkDestroyInstance (instance->instance, 0); + free (instance); +} diff --git a/libs/video/renderer/vulkan/namehack.h b/libs/video/renderer/vulkan/namehack.h new file mode 100644 index 000000000..7289995f2 --- /dev/null +++ b/libs/video/renderer/vulkan/namehack.h @@ -0,0 +1,137 @@ +#ifdef NH_DEFINE +#undef NH_DEFINE +#define Draw_Init vulkan_Draw_Init +#define Draw_Character vulkan_Draw_Character +#define Draw_String vulkan_Draw_String +#define Draw_nString vulkan_Draw_nString +#define Draw_AltString vulkan_Draw_AltString +#define Draw_ConsoleBackground vulkan_Draw_ConsoleBackground +#define Draw_Crosshair vulkan_Draw_Crosshair +#define Draw_CrosshairAt vulkan_Draw_CrosshairAt +#define Draw_TileClear vulkan_Draw_TileClear +#define Draw_Fill vulkan_Draw_Fill +#define Draw_TextBox vulkan_Draw_TextBox +#define Draw_FadeScreen vulkan_Draw_FadeScreen +#define Draw_BlendScreen vulkan_Draw_BlendScreen +#define Draw_CachePic vulkan_Draw_CachePic +#define Draw_UncachePic vulkan_Draw_UncachePic +#define Draw_MakePic vulkan_Draw_MakePic +#define Draw_DestroyPic vulkan_Draw_DestroyPic +#define Draw_PicFromWad vulkan_Draw_PicFromWad +#define Draw_Pic vulkan_Draw_Pic +#define Draw_Picf vulkan_Draw_Picf +#define Draw_SubPic vulkan_Draw_SubPic +#define Fog_DisableGFog vulkan_Fog_DisableGFog +#define Fog_EnableGFog vulkan_Fog_EnableGFog +#define Fog_GetColor vulkan_Fog_GetColor +#define Fog_GetDensity vulkan_Fog_GetDensity +#define Fog_Init vulkan_Fog_Init +#define Fog_ParseWorldspawn vulkan_Fog_ParseWorldspawn +#define Fog_SetupFrame vulkan_Fog_SetupFrame +#define Fog_StartAdditive vulkan_Fog_StartAdditive +#define Fog_StopAdditive vulkan_Fog_StopAdditive +#define Fog_Update vulkan_Fog_Update +#define R_AddTexture vulkan_R_AddTexture +#define R_BlendLightmaps vulkan_R_BlendLightmaps +#define R_BuildLightMap vulkan_R_BuildLightMap +#define R_CalcLightmaps vulkan_R_CalcLightmaps +#define R_ClearParticles vulkan_R_ClearParticles +#define R_ClearState vulkan_R_ClearState +#define R_ClearTextures vulkan_R_ClearTextures +#define R_DrawAliasModel vulkan_R_DrawAliasModel +#define R_DrawBrushModel vulkan_R_DrawBrushModel +#define R_DrawParticles vulkan_R_DrawParticles +#define R_DrawSky vulkan_R_DrawSky +#define R_DrawSkyChain vulkan_R_DrawSkyChain +#define R_DrawSprite vulkan_R_DrawSprite +#define R_DrawSpriteModel vulkan_R_DrawSpriteModel +#define R_DrawWaterSurfaces vulkan_R_DrawWaterSurfaces +#define R_DrawWorld vulkan_R_DrawWorld +#define R_InitBubble vulkan_R_InitBubble +#define R_InitGraphTextures vulkan_R_InitGraphTextures +#define R_InitParticles vulkan_R_InitParticles +#define R_InitSky vulkan_R_InitSky +#define R_InitSprites vulkan_R_InitSprites +#define R_InitSurfaceChains vulkan_R_InitSurfaceChains +#define R_LineGraph vulkan_R_LineGraph +#define R_LoadSky_f vulkan_R_LoadSky_f +#define R_LoadSkys vulkan_R_LoadSkys +#define R_NewMap vulkan_R_NewMap +#define R_Particle_New vulkan_R_Particle_New +#define R_Particle_NewRandom vulkan_R_Particle_NewRandom +#define R_Particles_Init_Cvars vulkan_R_Particles_Init_Cvars +#define R_ReadPointFile_f vulkan_R_ReadPointFile_f +#define R_RenderDlights vulkan_R_RenderDlights +#define R_RenderView vulkan_R_RenderView +#define R_RotateForEntity vulkan_R_RotateForEntity +#define R_SetupFrame vulkan_R_SetupFrame +#define R_SpriteBegin vulkan_R_SpriteBegin +#define R_SpriteEnd vulkan_R_SpriteEnd +#define R_TimeRefresh_f vulkan_R_TimeRefresh_f +#define R_ViewChanged vulkan_R_ViewChanged +#define SCR_CaptureBGR vulkan_SCR_CaptureBGR +#define SCR_ScreenShot vulkan_SCR_ScreenShot +#define SCR_ScreenShot_f vulkan_SCR_ScreenShot_f +#define SCR_UpdateScreen vulkan_SCR_UpdateScreen +#define c_alias_polys vulkan_c_alias_polys +#define c_brush_polys vulkan_c_brush_polys +#define r_easter_eggs_f vulkan_r_easter_eggs_f +#define r_particles_style_f vulkan_r_particles_style_f +#define r_world_matrix vulkan_r_world_matrix +#else +#undef Fog_DisableGFog +#undef Fog_EnableGFog +#undef Fog_GetColor +#undef Fog_GetDensity +#undef Fog_Init +#undef Fog_ParseWorldspawn +#undef Fog_SetupFrame +#undef Fog_StartAdditive +#undef Fog_StopAdditive +#undef Fog_Update +#undef R_AddTexture +#undef R_BlendLightmaps +#undef R_BuildLightMap +#undef R_CalcLightmaps +#undef R_ClearParticles +#undef R_ClearState +#undef R_ClearTextures +#undef R_DrawAliasModel +#undef R_DrawBrushModel +#undef R_DrawParticles +#undef R_DrawSky +#undef R_DrawSkyChain +#undef R_DrawSpriteModel +#undef R_DrawWaterSurfaces +#undef R_DrawWorld +#undef R_Init +#undef R_InitBubble +#undef R_InitGraphTextures +#undef R_InitParticles +#undef R_InitSky +#undef R_InitSprites +#undef R_InitSurfaceChains +#undef R_LineGraph +#undef R_LoadSky_f +#undef R_LoadSkys +#undef R_NewMap +#undef R_Particle_New +#undef R_Particle_NewRandom +#undef R_Particles_Init_Cvars +#undef R_ReadPointFile_f +#undef R_RenderDlights +#undef R_RenderView +#undef R_RotateForEntity +#undef R_SetupFrame +#undef R_TimeRefresh_f +#undef R_ViewChanged +#undef SCR_CaptureBGR +#undef SCR_ScreenShot +#undef SCR_ScreenShot_f +#undef SCR_UpdateScreen +#undef c_alias_polys +#undef c_brush_polys +#undef r_easter_eggs_f +#undef r_particles_style_f +#undef r_world_matrix +#endif diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c new file mode 100644 index 000000000..3c8dcc8e4 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -0,0 +1,189 @@ +/* + vulkan_draw.c + + 2D drawing support for Vulkan + + Copyright (C) 2011 Bill Currie + + Author: Bill Currie + Date: 2011/12/23 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define NH_DEFINE +#include "namehack.h" + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/draw.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "QF/Vulkan/qf_draw.h" +#include "QF/Vulkan/qf_vid.h" + +#include "r_internal.h" + +qpic_t * +vulkan_Draw_MakePic (int width, int height, const byte *data) +{ + return 0; +} + +void +vulkan_Draw_DestroyPic (qpic_t *pic) +{ +} + +qpic_t * +vulkan_Draw_PicFromWad (const char *name) +{ + return 0; +} + +qpic_t * +vulkan_Draw_CachePic (const char *path, qboolean alpha) +{ + return 0; +} + +void +vulkan_Draw_UncachePic (const char *path) +{ +} + +void +vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha) +{ +} + +void +vulkan_Draw_Init (void) +{ +} + +void +vulkan_Draw_Character (int x, int y, unsigned int chr) +{ +} + +void +vulkan_Draw_String (int x, int y, const char *str) +{ +} + +void +vulkan_Draw_nString (int x, int y, const char *str, int count) +{ +} + +void +vulkan_Draw_AltString (int x, int y, const char *str) +{ +} + +void +vulkan_Draw_CrosshairAt (int ch, int x, int y) +{ +} + +void +vulkan_Draw_Crosshair (void) +{ +} + +void +vulkan_Draw_Pic (int x, int y, qpic_t *pic) +{ +} + +void +vulkan_Draw_Picf (float x, float y, qpic_t *pic) +{ +} + +void +vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, + int height) +{ +} + +void +vulkan_Draw_ConsoleBackground (int lines, byte alpha) +{ +} + +void +vulkan_Draw_TileClear (int x, int y, int w, int h) +{ +} + +void +vulkan_Draw_Fill (int x, int y, int w, int h, int c) +{ +} + +void +vulkan_Draw_FadeScreen (void) +{ +} + +void +Vulkan_Set2D (void) +{ +} + +void +Vulkan_Set2DScaled (void) +{ +} + +void +Vulkan_End2D (void) +{ +} + +void +Vulkan_DrawReset (void) +{ +} + +void +Vulkan_FlushText (void) +{ +} + +void +vulkan_Draw_BlendScreen (quat_t color) +{ +} diff --git a/libs/video/renderer/vulkan/vulkan_funcs.c b/libs/video/renderer/vulkan/vulkan_funcs.c new file mode 100644 index 000000000..2d8f79c9a --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_funcs.c @@ -0,0 +1,6 @@ +#include + +#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; +#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; + +#include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c new file mode 100644 index 000000000..099135be7 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -0,0 +1,129 @@ +/* + vid_common_vulkan.c + + Common Vulkan video driver functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2019 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/init.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" + +static void *vulkan_library; + +static VulkanInstance_t *vulkan_instance; + +static void +load_vulkan_library (void) +{ + vulkan_library = dlopen (vulkan_library_name->string, RTLD_NOW); + if (!vulkan_library) { + Sys_Error ("Couldn't load vulkan library %s: %s", + vulkan_library_name->name, dlerror ()); + } + + #define EXPORTED_VULKAN_FUNCTION(name) \ + name = (PFN_##name) dlsym (vulkan_library, #name); \ + if (!name) { \ + Sys_Error ("Couldn't find exported vulkan function %s", #name); \ + } + + // Can't use vkGetInstanceProcAddr (0, ...) here because it grabs from + // the whole exe and thus sees the function pointers instead of the actual + // functions. Sure, could rename all the function pointers, but while that + // worked for gl and glsl, it also made it a real pain to work with the + // spec (or man pages, etc). Of course, namespaces would help, too. + #define GLOBAL_LEVEL_VULKAN_FUNCTION(name) \ + name = (PFN_##name) dlsym (vulkan_library, #name); \ + if (!name) { \ + Sys_Error ("Couldn't find global-level function %s", #name); \ + } + + #include "QF/Vulkan/funclist.h" +} + +void +Vulkan_Init_Cvars () +{ + vulkan_library_name = Cvar_Get ("vulkan_library", "libvulkan.so.1", + CVAR_ROM, 0, + "the name of the vulkan shared library"); + vulkan_use_validation = Cvar_Get ("vulkan_use_validation", "1", CVAR_NONE, + 0, + "enable LunarG Standard Validation " + "Layer if available (requires instance " + "restart)."); +} + +const char *extensions[] = { + "foo", + 0, +}; + +void +Vulkan_Init_Common (void) +{ + Vulkan_Init_Cvars (); + + load_vulkan_library (); + + vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, extensions);//FIXME version + Sys_Printf ("Vulkan_Init_Common\n"); + if (developer->int_val & SYS_VID) { + Vulkan_DestroyInstance (vulkan_instance); + Sys_Quit(); + } +} + +void +Vulkan_Shutdown_Common (void) +{ + Vulkan_DestroyInstance (vulkan_instance); +} From ab08e4f20738e7ee9aca220489008c17bb00e662 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 7 Jul 2019 01:28:05 +0900 Subject: [PATCH 0170/3664] Create a logical device with a single queue A single graphics-capable queue should be enough for now. However, I'm not sure I'm happy with a lot of the code: it's a bit difficult to write flexibly configured code for Vulkan (or seems to be at this stage), especially in C. --- include/QF/Vulkan/funclist.h | 6 +- include/QF/Vulkan/init.h | 14 ++- libs/video/renderer/vulkan/init.c | 20 ++++ .../video/renderer/vulkan/vulkan_vid_common.c | 105 +++++++++++++++++- 4 files changed, 138 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 1ab96300c..d0cc47a6f 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -24,13 +24,13 @@ GLOBAL_LEVEL_VULKAN_FUNCTION (vkCreateInstance) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumeratePhysicalDevices) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceQueueFamilyProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateDevice) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetDeviceProcAddr) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceLayerProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceExtensionProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties) -INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceQueueFamilyProperties) -INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance) #undef INSTANCE_LEVEL_VULKAN_FUNCTION @@ -46,6 +46,8 @@ INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION (vkCreateDebugUtilsMessengerEXT) #define DEVICE_LEVEL_VULKAN_FUNCTION(function) #endif +DEVICE_LEVEL_VULKAN_FUNCTION (vkGetDeviceQueue) + #undef DEVICE_LEVEL_VULKAN_FUNCTION #ifndef DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION diff --git a/include/QF/Vulkan/init.h b/include/QF/Vulkan/init.h index b12dcd42e..4a97b82f8 100644 --- a/include/QF/Vulkan/init.h +++ b/include/QF/Vulkan/init.h @@ -31,14 +31,23 @@ #include "QF/qtypes.h" #include "QF/Vulkan/funcs.h" +typedef struct { + VkDevice device; + VkQueue queue; + + #define DEVICE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; + #define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) PFN_##name name; + #include "QF/Vulkan/funclist.h" +} VulkanDevice_t; + typedef struct { VkPhysicalDevice device; + VkPhysicalDeviceFeatures features; VkPhysicalDeviceProperties properties; uint32_t numLayers; VkLayerProperties *layers; uint32_t numExtensions; VkExtensionProperties *extensions; - VkPhysicalDeviceFeatures features; VkPhysicalDeviceMemoryProperties memory; uint32_t numQueueFamilies; VkQueueFamilyProperties *queueFamilies; @@ -61,5 +70,8 @@ VulkanInstance_t *Vulkan_CreateInstance (const char *appName, const char **layers, const char **extensions); void Vulkan_DestroyInstance (VulkanInstance_t *instance); +int Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions, + int numExtensions, + const char * const *requested); #endif // __QF_Vulkan_init_h diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c index 4967c8125..2c4fb7ca1 100644 --- a/libs/video/renderer/vulkan/init.c +++ b/libs/video/renderer/vulkan/init.c @@ -388,3 +388,23 @@ Vulkan_DestroyInstance (VulkanInstance_t *instance) instance->vkDestroyInstance (instance->instance, 0); free (instance); } + +int +Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions, + int numExtensions, + const char * const *requested) +{ + while (*requested) { + int i; + for (i = 0; i < numExtensions; i++) { + if (!strcmp (*requested, extensions[i].extensionName)) { + break; + } + } + if (i < numExtensions) { + // requested extension not found + break; + } + } + return !*requested; +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 099135be7..43921df30 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -59,6 +59,7 @@ static void *vulkan_library; static VulkanInstance_t *vulkan_instance; +static VulkanDevice_t *vulkan_device; static void load_vulkan_library (void) @@ -102,21 +103,117 @@ Vulkan_Init_Cvars () "restart)."); } -const char *extensions[] = { - "foo", +static const char *instance_extensions[] = { 0, }; +static const char *device_extensions[] = { + 0, +}; + +static int +count_bits (uint32_t val) +{ + int bits = 0; + while (val) { + bits += val & 1; + val >>= 1; + } + return bits; +} + +static int +find_queue_family (VulkanPhysDevice_t *dev, uint32_t flags) +{ + int best_diff = 32; + uint32_t family = -1; + + for (uint32_t i = 0; i < dev->numQueueFamilies; i++) { + VkQueueFamilyProperties *queue = &dev->queueFamilies[i]; + + if ((queue->queueFlags & flags) == flags) { + int diff = count_bits (queue->queueFlags & ~flags); + if (diff < best_diff) { + best_diff = diff; + family = i; + } + } + } + return family; +} + +static void +load_device_funcs (VulkanInstance_t *inst, VulkanDevice_t *dev) +{ +#define DEVICE_LEVEL_VULKAN_FUNCTION(name) \ + dev->name = (PFN_##name) inst->vkGetDeviceProcAddr (dev->device, #name); \ + if (!dev->name) { \ + Sys_Error ("Couldn't find device level function %s", #name); \ + } + +#define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) \ + dev->name = (PFN_##name) inst->vkGetDeviceProcAddr (dev->device, #name); \ + if (!dev->name) { \ + Sys_Printf ("Couldn't find device level function %s", #name); \ + } + +#include "QF/Vulkan/funclist.h" +} + +static VulkanDevice_t * +create_suitable_device (VulkanInstance_t *instance) +{ + for (uint32_t i = 0; i < instance->numDevices; i++) { + VulkanPhysDevice_t *phys = &instance->devices[i]; + if (!Vulkan_ExtensionsSupported (phys->extensions, phys->numExtensions, + device_extensions)) { + return 0; + } + int family = find_queue_family (phys, VK_QUEUE_GRAPHICS_BIT); + if (family < 0) { + return 0; + } + float priority = 1; + VkDeviceQueueCreateInfo qCreateInfo = { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, + family, 1, &priority + }; + VkPhysicalDeviceFeatures features; + VkDeviceCreateInfo dCreateInfo = { + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0, + 1, &qCreateInfo, + 0, 0, + 0, device_extensions, + &features + }; + memset (&features, 0, sizeof (features)); + VulkanDevice_t *device = calloc (1, sizeof (VulkanDevice_t)); + if (instance->vkCreateDevice (phys->device, &dCreateInfo, 0, + &device->device) == VK_SUCCESS) { + load_device_funcs (instance, device); + device->vkGetDeviceQueue (device->device, family, + 0, &device->queue); + return device; + } + } + return 0; +} + void Vulkan_Init_Common (void) { + Sys_Printf ("Vulkan_Init_Common\n"); Vulkan_Init_Cvars (); load_vulkan_library (); - vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, extensions);//FIXME version - Sys_Printf ("Vulkan_Init_Common\n"); + vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version + vulkan_device = create_suitable_device (vulkan_instance); + if (!vulkan_device) { + Sys_Error ("no suitable vulkan device found"); + } if (developer->int_val & SYS_VID) { + Sys_Printf ("%p %p\n", vulkan_device->device, vulkan_device->queue); Vulkan_DestroyInstance (vulkan_instance); Sys_Quit(); } From 940ef833ae1541af9623c1c797045787a1b133a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 7 Jul 2019 14:34:02 +0900 Subject: [PATCH 0171/3664] Shutdown Vulkan properly Well, as properly as can be considering how little is started up :P --- include/QF/Vulkan/funclist.h | 1 + libs/video/renderer/vulkan/vulkan_vid_common.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index d0cc47a6f..2b755889e 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -46,6 +46,7 @@ INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION (vkCreateDebugUtilsMessengerEXT) #define DEVICE_LEVEL_VULKAN_FUNCTION(function) #endif +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyDevice) DEVICE_LEVEL_VULKAN_FUNCTION (vkGetDeviceQueue) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 43921df30..ba4a16915 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -214,7 +214,7 @@ Vulkan_Init_Common (void) } if (developer->int_val & SYS_VID) { Sys_Printf ("%p %p\n", vulkan_device->device, vulkan_device->queue); - Vulkan_DestroyInstance (vulkan_instance); + Vulkan_Shutdown_Common (); Sys_Quit(); } } @@ -222,5 +222,13 @@ Vulkan_Init_Common (void) void Vulkan_Shutdown_Common (void) { + if (vulkan_device) { + vulkan_device->vkDestroyDevice (vulkan_device->device, 0); + free (vulkan_device); + vulkan_device = 0; + } Vulkan_DestroyInstance (vulkan_instance); + vulkan_instance = 0; + dlclose (vulkan_library); + vulkan_library = 0; } From 77afc3048637e9cd7b63cfa96169d74195e2ceeb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 7 Jul 2019 14:57:56 +0900 Subject: [PATCH 0172/3664] Fix vid renderer plugin types I guess that plugin type is currently not checked, otherwise I doubt the mistake would have gone unnoticed. --- libs/video/renderer/vid_render_gl.c | 2 +- libs/video/renderer/vid_render_glsl.c | 2 +- libs/video/renderer/vid_render_sw.c | 2 +- libs/video/renderer/vid_render_sw32.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index c79bfaa20..42f5df1dc 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -166,7 +166,7 @@ static plugin_data_t plugin_info_data = { }; static plugin_t plugin_info = { - qfp_snd_render, + qfp_vid_render, 0, QFPLUGIN_VERSION, "0.1", diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index f09820ab3..f162231d1 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -166,7 +166,7 @@ static plugin_data_t plugin_info_data = { }; static plugin_t plugin_info = { - qfp_snd_render, + qfp_vid_render, 0, QFPLUGIN_VERSION, "0.1", diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 7ac10a4d4..7c2485911 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -156,7 +156,7 @@ static plugin_data_t plugin_info_data = { }; static plugin_t plugin_info = { - qfp_snd_render, + qfp_vid_render, 0, QFPLUGIN_VERSION, "0.1", diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 9bc135c78..40034c0dc 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -161,7 +161,7 @@ static plugin_data_t plugin_info_data = { }; static plugin_t plugin_info = { - qfp_snd_render, + qfp_vid_render, 0, QFPLUGIN_VERSION, "0.1", diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 820d58fa6..165d5d832 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -175,7 +175,7 @@ static plugin_data_t plugin_info_data = { }; static plugin_t plugin_info = { - qfp_snd_render, + qfp_vid_render, 0, QFPLUGIN_VERSION, "0.1", From d95e9f9af35010e493e5658bd317c0033a0ba679 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 7 Jul 2019 14:59:20 +0900 Subject: [PATCH 0173/3664] Correct vulkan plugin strings --- libs/video/renderer/vid_render_vulkan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 165d5d832..ec5ee4ea3 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -179,9 +179,9 @@ static plugin_t plugin_info = { 0, QFPLUGIN_VERSION, "0.1", - "GLSL Renderer", + "Vulkan Renderer", "Copyright (C) 1996-1997 Id Software, Inc.\n" - "Copyright (C) 1999-2012 contributors of the QuakeForge project\n" + "Copyright (C) 1999-2019 contributors of the QuakeForge project\n" "Please see the file \"AUTHORS\" for a list of contributors", &plugin_info_funcs, &plugin_info_data, From a755e50c847c00f5018cac27a7f545a7233d2a8d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 7 Jul 2019 15:38:29 +0900 Subject: [PATCH 0174/3664] Clean up vid access a little Things are still a mess, but a proper cleanup will be a lot of work and will, really, involve properly splitting quake-specific code* out from the rest of the renderer. * data loading and format specific stuff --- include/r_screen.h | 2 -- libs/video/renderer/r_screen.c | 3 --- libs/video/renderer/vid_common.c | 2 ++ 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/include/r_screen.h b/include/r_screen.h index 4fb5e91cd..7955fdd3d 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -64,8 +64,6 @@ extern struct qpic_s *scr_turtle; extern int clearconsole; extern int clearnotify; -extern viddef_t vid; // global video state - extern vrect_t *pconupdate; extern vrect_t scr_vrect; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index a6d129674..6eb307229 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -104,8 +104,6 @@ qpic_t *scr_turtle; int clearconsole; -viddef_t vid; // global video state - vrect_t *pconupdate; vrect_t scr_vrect; @@ -365,6 +363,5 @@ SCR_Init (void) scr_ram = vr_funcs->Draw_PicFromWad ("ram"); scr_turtle = vr_funcs->Draw_PicFromWad ("turtle"); - vid = *vr_data.vid; // cache scr_initialized = true; } diff --git a/libs/video/renderer/vid_common.c b/libs/video/renderer/vid_common.c index 5a2cd9d43..74a1140b0 100644 --- a/libs/video/renderer/vid_common.c +++ b/libs/video/renderer/vid_common.c @@ -34,6 +34,8 @@ #include "mod_internal.h" #include "r_internal.h" +viddef_t vid; // global video state + vid_render_data_t vid_render_data = { &vid, &r_refdef, &scr_vrect, 0, 0, 0, From 7137d61c3698a0664c64ed27824b972b8b19b842 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 7 Jul 2019 16:27:55 +0900 Subject: [PATCH 0175/3664] Add some extensions needed for presentation --- libs/video/renderer/vulkan/Makefile.am | 2 +- libs/video/renderer/vulkan/vulkan_vid_common.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index f3b3d32c5..5d2f65d8e 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES +AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES -DVK_USE_PLATFORM_XLIB_KHR vulkan_src = \ init.c \ diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index ba4a16915..42b751de0 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -104,6 +104,8 @@ Vulkan_Init_Cvars () } static const char *instance_extensions[] = { + VK_KHR_SURFACE_EXTENSION_NAME, + VK_KHR_XLIB_SURFACE_EXTENSION_NAME, 0, }; From 613779568291aee01dd3656dfe2bcfb12f64b9fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 7 Jul 2019 16:48:53 +0900 Subject: [PATCH 0176/3664] Use deep binding for the vulkan loader This fixes the problem with using vkGetInstanceProcAddr to find global vulkan functions. --- libs/video/renderer/vulkan/vulkan_vid_common.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 42b751de0..9366799cb 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -64,7 +64,8 @@ static VulkanDevice_t *vulkan_device; static void load_vulkan_library (void) { - vulkan_library = dlopen (vulkan_library_name->string, RTLD_NOW); + vulkan_library = dlopen (vulkan_library_name->string, + RTLD_DEEPBIND | RTLD_NOW); if (!vulkan_library) { Sys_Error ("Couldn't load vulkan library %s: %s", vulkan_library_name->name, dlerror ()); @@ -76,13 +77,8 @@ load_vulkan_library (void) Sys_Error ("Couldn't find exported vulkan function %s", #name); \ } - // Can't use vkGetInstanceProcAddr (0, ...) here because it grabs from - // the whole exe and thus sees the function pointers instead of the actual - // functions. Sure, could rename all the function pointers, but while that - // worked for gl and glsl, it also made it a real pain to work with the - // spec (or man pages, etc). Of course, namespaces would help, too. #define GLOBAL_LEVEL_VULKAN_FUNCTION(name) \ - name = (PFN_##name) dlsym (vulkan_library, #name); \ + name = (PFN_##name) vkGetInstanceProcAddr (0, #name); \ if (!name) { \ Sys_Error ("Couldn't find global-level function %s", #name); \ } From 3e1520c2469bf40b63fc2661db095878d67e6bad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 8 Jul 2019 12:46:22 +0900 Subject: [PATCH 0177/3664] Move vid callback access into vid The plan is to move the callbacks into a "private" struct. --- include/QF/vid.h | 1 + libs/video/targets/vid.c | 7 +++++++ nq/include/client.h | 1 + nq/source/cl_main.c | 8 ++++++++ nq/source/host.c | 5 +---- nq/source/sv_ded.c | 5 +++++ qw/source/cl_main.c | 3 +-- 7 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/QF/vid.h b/include/QF/vid.h index 70298fa8b..057414b2f 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -88,5 +88,6 @@ void VID_Init_Cvars (void); void VID_Init (byte *palette, byte *colormap); void VID_Shutdown (void); void VID_SetCaption (const char *text); +void VID_ClearMemory (void); #endif // __vid_h_ diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 46507e26d..d7aeb3b2d 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -305,3 +305,10 @@ VID_InitBuffers (void) if (viddef.init_caches) viddef.init_caches (viddef.surfcache, cachesize); } + +void +VID_ClearMemory (void) +{ + if (viddef.flush_caches) + viddef.flush_caches (); +} diff --git a/nq/include/client.h b/nq/include/client.h index e6dc80e97..54477f7b4 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -287,6 +287,7 @@ struct cbuf_s; void CL_Init (struct cbuf_s *cbuf); void CL_InitCvars (void); void CL_Shutdown (void); +void CL_ClearMemory (void); void CL_EstablishConnection (const char *host); void CL_Signon1 (void); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 7f6dd9e82..3f8e7bde6 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -130,6 +130,14 @@ CL_Shutdown (void) VID_Shutdown (); } +void +CL_ClearMemory (void) +{ + VID_ClearMemory (); + if (r_data) + r_data->force_fullscreen = 0; +} + void CL_InitCvars (void) { diff --git a/nq/source/host.c b/nq/source/host.c index f6b59cf8b..d15dd0431 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -495,8 +495,7 @@ void Host_ClearMemory (void) { Sys_MaskPrintf (SYS_DEV, "Clearing memory\n"); - if (viddef.flush_caches) - viddef.flush_caches (); + CL_ClearMemory (); Mod_ClearAll (); if (host_hunklevel) Hunk_FreeToLowMark (host_hunklevel); @@ -504,8 +503,6 @@ Host_ClearMemory (void) cls.signon = 0; memset (&sv, 0, sizeof (sv)); memset (&cl, 0, sizeof (cl)); - if (r_data) - r_data->force_fullscreen = 0; } /* diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index c22f9cc3a..44dd57408 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -68,6 +68,11 @@ CL_UpdateScreen (double realtime) { } +void +CL_ClearMemory (void) +{ +} + void CL_Cmd_ForwardToServer (void) { diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 09fb1aec2..c2b3c3a35 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -412,8 +412,7 @@ CL_ClearState (void) CL_Init_Entity (&cl.viewent); Sys_MaskPrintf (SYS_DEV, "Clearing memory\n"); - if (viddef.flush_caches) - viddef.flush_caches (); + VID_ClearMemory (); Mod_ClearAll (); if (host_hunklevel) // FIXME: check this... Hunk_FreeToLowMark (host_hunklevel); From 6ee2df84452ab6a8fc25dfbafb993815a1d9fbf4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 8 Jul 2019 13:40:29 +0900 Subject: [PATCH 0178/3664] Move vid callbacks into vid_internal Currently segfaults because viddef is an alias for *r_data->vid, which has not yet been initialized (chicken and egg). --- include/QF/vid.h | 12 +----------- include/vid_internal.h | 14 ++++++++++++++ libs/video/renderer/gl/gl_rmisc.c | 7 ++++--- libs/video/renderer/gl/gl_screen.c | 5 +++-- libs/video/renderer/gl/qfgl_ext.c | 7 ++++--- libs/video/renderer/glsl/glsl_main.c | 5 +++-- libs/video/renderer/glsl/glsl_screen.c | 3 ++- libs/video/renderer/glsl/qfglsl.c | 5 +++-- libs/video/renderer/r_init.c | 5 +++-- libs/video/renderer/sw/d_init.c | 6 +++--- libs/video/renderer/sw/draw.c | 2 +- libs/video/renderer/sw32/d_init.c | 6 +++--- libs/video/renderer/sw32/draw.c | 2 +- libs/video/renderer/vid_render_gl.c | 7 ++++--- libs/video/renderer/vid_render_glsl.c | 7 ++++--- libs/video/renderer/vid_render_vulkan.c | 7 ++++--- libs/video/targets/vid.c | 23 ++++++++++++----------- libs/video/targets/vid_sdl.c | 14 +++++++++----- libs/video/targets/vid_x11.c | 13 ++++++++----- 19 files changed, 86 insertions(+), 64 deletions(-) diff --git a/include/QF/vid.h b/include/QF/vid.h index 057414b2f..93975ced6 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -61,17 +61,7 @@ typedef struct { int conheight; byte *direct; // direct drawing to framebuffer, if not // NULL - int (*surf_cache_size)(int width, int height); - void (*flush_caches)(void); - void (*init_caches)(void *cache, int size); - void (*do_screen_buffer)(void); - void (*set_palette)(const byte *palette); - - // gl stuff - void (*load_gl)(void); - void (*init_gl)(void); - void *(*get_proc_address)(const char *name, qboolean crit); - void (*end_rendering)(void); + struct vid_internal_s *vid_internal; } viddef_t; #define viddef (*r_data->vid) diff --git a/include/vid_internal.h b/include/vid_internal.h index bf1803270..fc1538202 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -4,6 +4,20 @@ #include "QF/vid.h" #include "QF/plugin/vid_render.h" +typedef struct vid_internal_s { + int (*surf_cache_size) (int width, int height); + void (*flush_caches) (void); + void (*init_caches) (void *cache, int size); + void (*do_screen_buffer) (void); + void (*set_palette) (const byte *palette); + + // gl stuff + void (*load_gl) (void); + void (*init_gl) (void); + void *(*get_proc_address) (const char *name, qboolean crit); + void (*end_rendering) (void); +} vid_internal_t; + extern struct cvar_s *vid_fullscreen; extern struct cvar_s *vid_system_gamma; extern struct cvar_s *vid_gamma; diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index a399c26bd..e054e37bf 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -64,6 +64,7 @@ #include "mod_internal.h" #include "r_internal.h" #include "varrays.h" +#include "vid_internal.h" /* R_Envmap_f @@ -121,7 +122,7 @@ R_Envmap_f (void) gl_envmap = false; qfglDrawBuffer (GL_BACK); qfglReadBuffer (GL_BACK); - vid.end_rendering (); + vid.vid_internal->end_rendering (); } void @@ -249,13 +250,13 @@ gl_R_TimeRefresh_f (void) double start, stop, time; int i; - vid.end_rendering (); + vid.vid_internal->end_rendering (); start = Sys_DoubleTime (); for (i = 0; i < 128; i++) { r_refdef.viewangles[1] = i * (360.0 / 128.0); gl_R_RenderView (); - vid.end_rendering (); + vid.vid_internal->end_rendering (); } stop = Sys_DoubleTime (); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index d463880d8..73674e70c 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -59,6 +59,7 @@ #include "compat.h" #include "r_internal.h" #include "sbar.h" +#include "vid_internal.h" /* SCREEN SHOTS */ @@ -206,7 +207,7 @@ gl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) return; if (begun) - vid.end_rendering (); + vid.vid_internal->end_rendering (); vr_data.realtime = realtime; @@ -263,7 +264,7 @@ gl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) qfglFlush (); if (gl_finish->int_val) { - vid.end_rendering (); + vid.vid_internal->end_rendering (); begun = 0; } } diff --git a/libs/video/renderer/gl/qfgl_ext.c b/libs/video/renderer/gl/qfgl_ext.c index a46472609..41fe1f52b 100644 --- a/libs/video/renderer/gl/qfgl_ext.c +++ b/libs/video/renderer/gl/qfgl_ext.c @@ -61,6 +61,7 @@ #include "QF/GL/funcs.h" #include "r_internal.h" +#include "vid_internal.h" // First we need to get all the function pointers declared. #define QFGL_WANT(ret, name, args) \ @@ -75,9 +76,9 @@ qboolean GLF_FindFunctions (void) { #define QFGL_WANT(ret, name, args) \ - qf##name = vid.get_proc_address (#name, false); + qf##name = vid.vid_internal->get_proc_address (#name, false); #define QFGL_NEED(ret, name, args) \ - qf##name = vid.get_proc_address (#name, true); + qf##name = vid.vid_internal->get_proc_address (#name, true); #include "QF/GL/qf_funcs_list.h" #undef QFGL_NEED #undef QFGL_WANT @@ -135,6 +136,6 @@ void * QFGL_ExtensionAddress (const char *name) { if (name) - return vid.get_proc_address (name, false); + return vid.vid_internal->get_proc_address (name, false); return NULL; } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 9fd3a9c0c..2bc60bdd4 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -58,6 +58,7 @@ #include "mod_internal.h" #include "r_internal.h" +#include "vid_internal.h" mat4_t glsl_projection; mat4_t glsl_view; @@ -304,13 +305,13 @@ glsl_R_TimeRefresh_f (void) double start, stop, time; int i; - vid.end_rendering (); + vid.vid_internal->end_rendering (); start = Sys_DoubleTime (); for (i = 0; i < 128; i++) { r_refdef.viewangles[1] = i * (360.0 / 128.0); glsl_R_RenderView (); - vid.end_rendering (); + vid.vid_internal->end_rendering (); } stop = Sys_DoubleTime (); diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index eab755325..ecdda6ec8 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -60,6 +60,7 @@ #include "QF/GLSL/qf_vid.h" #include "r_internal.h" +#include "vid_internal.h" /* Unknown renamed to GLErr_Unknown to solve conflict with winioctl.h */ static unsigned int GLErr_InvalidEnum; @@ -165,7 +166,7 @@ glsl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, if (begun) { begun = 0; - vid.end_rendering (); + vid.vid_internal->end_rendering (); } vr_data.realtime = realtime; diff --git a/libs/video/renderer/glsl/qfglsl.c b/libs/video/renderer/glsl/qfglsl.c index af3a2f839..b4fd25662 100644 --- a/libs/video/renderer/glsl/qfglsl.c +++ b/libs/video/renderer/glsl/qfglsl.c @@ -60,6 +60,7 @@ #include "QF/GLSL/funcs.h" #include "r_internal.h" +#include "vid_internal.h" // First we need to get all the function pointers declared. #define QFGL_WANT(ret, name, args) \ @@ -74,9 +75,9 @@ qboolean EGLF_FindFunctions (void) { #define QFGL_WANT(ret, name, args) \ - qfe##name = vid.get_proc_address (#name, false); + qfe##name = vid.vid_internal->get_proc_address (#name, false); #define QFGL_NEED(ret, name, args) \ - qfe##name = vid.get_proc_address (#name, true); + qfe##name = vid.vid_internal->get_proc_address (#name, true); #include "QF/GLSL/qf_funcs_list.h" #undef QFGL_NEED #undef QFGL_WANT diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index d4a7e91cd..98acc39ad 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -46,6 +46,7 @@ #include "QF/plugin/general.h" #include "r_internal.h" +#include "vid_internal.h" cvar_t *vidrend_plugin; plugin_t *vidrendmodule = NULL; @@ -76,8 +77,8 @@ R_LoadModule (void (*load_gl)(void), void (*set_palette) (const byte *palette)) r_funcs = vidrendmodule->functions->vid_render; mod_funcs = r_funcs->model_funcs; r_data = vidrendmodule->data->vid_render; - r_data->vid->load_gl = load_gl; - r_data->vid->set_palette = set_palette; + r_data->vid->vid_internal->load_gl = load_gl; + r_data->vid->vid_internal->set_palette = set_palette; vidrendmodule->functions->general->p_Init (); } diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index 67e48e71b..00fb21a89 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -56,9 +56,9 @@ D_Init (void) r_worldpolysbacktofront = false; r_recursiveaffinetriangles = true; - vr_data.vid->surf_cache_size = D_SurfaceCacheForRes; - vr_data.vid->flush_caches = D_FlushCaches; - vr_data.vid->init_caches = D_InitCaches; + vr_data.vid->vid_internal->surf_cache_size = D_SurfaceCacheForRes; + vr_data.vid->vid_internal->flush_caches = D_FlushCaches; + vr_data.vid->vid_internal->init_caches = D_InitCaches; VID_InitBuffers (); } diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index e3728af66..775888a21 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -825,5 +825,5 @@ Draw_BlendScreen (quat_t color) newpal[2] = vid.gammatable[b]; newpal += 3; } - vid.set_palette (pal); + vid.vid_internal->set_palette (pal); } diff --git a/libs/video/renderer/sw32/d_init.c b/libs/video/renderer/sw32/d_init.c index ccb5f7392..e786cf32b 100644 --- a/libs/video/renderer/sw32/d_init.c +++ b/libs/video/renderer/sw32/d_init.c @@ -66,9 +66,9 @@ sw32_D_Init (void) sw32_d_zitable[i] = (65536.0 * 65536.0 / (double) i); } - vr_data.vid->surf_cache_size = sw32_D_SurfaceCacheForRes; - vr_data.vid->flush_caches = sw32_D_FlushCaches; - vr_data.vid->init_caches = sw32_D_InitCaches; + vr_data.vid->vid_internal->surf_cache_size = sw32_D_SurfaceCacheForRes; + vr_data.vid->vid_internal->flush_caches = sw32_D_FlushCaches; + vr_data.vid->vid_internal->init_caches = sw32_D_InitCaches; VID_InitBuffers (); VID_MakeColormaps(); diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c index a420c8ac0..13454c437 100644 --- a/libs/video/renderer/sw32/draw.c +++ b/libs/video/renderer/sw32/draw.c @@ -1299,7 +1299,7 @@ sw32_Draw_BlendScreen (quat_t color) newpal[2] = vid.gammatable[b]; newpal += 3; } - vid.set_palette (pal); + vid.vid_internal->set_palette (pal); } break; case 2: diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 42f5df1dc..91f4178b5 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -38,6 +38,7 @@ #include "mod_internal.h" #include "r_internal.h" +#include "vid_internal.h" #include "gl/namehack.h" @@ -126,9 +127,9 @@ vid_render_funcs_t gl_vid_render_funcs = { static void gl_vid_render_init (void) { - vr_data.vid->set_palette = GL_SetPalette; - vr_data.vid->init_gl = GL_Init_Common; - vr_data.vid->load_gl (); + vr_data.vid->vid_internal->set_palette = GL_SetPalette; + vr_data.vid->vid_internal->init_gl = GL_Init_Common; + vr_data.vid->vid_internal->load_gl (); vr_funcs = &gl_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index f162231d1..d1f380ae5 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -38,6 +38,7 @@ #include "mod_internal.h" #include "r_internal.h" +#include "vid_internal.h" #include "glsl/namehack.h" @@ -126,9 +127,9 @@ vid_render_funcs_t glsl_vid_render_funcs = { static void glsl_vid_render_init (void) { - vr_data.vid->set_palette = GLSL_SetPalette; - vr_data.vid->init_gl = GLSL_Init_Common; - vr_data.vid->load_gl (); + vr_data.vid->vid_internal->set_palette = GLSL_SetPalette; + vr_data.vid->vid_internal->init_gl = GLSL_Init_Common; + vr_data.vid->vid_internal->load_gl (); vr_funcs = &glsl_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index ec5ee4ea3..c71264fcb 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -38,6 +38,7 @@ #include "mod_internal.h" #include "r_internal.h" +#include "vid_internal.h" #include "vulkan/namehack.h" @@ -134,9 +135,9 @@ set_palette (const byte *palette) static void vulkan_vid_render_init (void) { - vr_data.vid->set_palette = set_palette; - vr_data.vid->init_gl = Vulkan_Init_Common; - vr_data.vid->load_gl (); + vr_data.vid->vid_internal->set_palette = set_palette; + vr_data.vid->vid_internal->init_gl = Vulkan_Init_Common; + vr_data.vid->vid_internal->load_gl (); vr_funcs = &vulkan_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index d7aeb3b2d..651101539 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -214,7 +214,7 @@ VID_UpdateGamma (cvar_t *vid_gamma) VID_BuildGammaTable (gamma); for (i = 0; i < 256 * 3; i++) viddef.palette[i] = viddef.gammatable[viddef.basepal[i]]; - viddef.set_palette (viddef.palette); // update with the new palette + viddef.vid_internal->set_palette (viddef.palette); // update with the new palette } } @@ -256,8 +256,9 @@ VID_InitBuffers (void) // Calculate the sizes we want first buffersize = viddef.rowbytes * viddef.height; zbuffersize = viddef.width * viddef.height * sizeof (*viddef.zbuffer); - if (viddef.surf_cache_size) - cachesize = viddef.surf_cache_size (viddef.width, viddef.height); + if (viddef.vid_internal->surf_cache_size) + cachesize = viddef.vid_internal->surf_cache_size (viddef.width, + viddef.height); // Free the old z-buffer if (viddef.zbuffer) { @@ -266,13 +267,13 @@ VID_InitBuffers (void) } // Free the old surface cache if (viddef.surfcache) { - if (viddef.flush_caches) - viddef.flush_caches (); + if (viddef.vid_internal->flush_caches) + viddef.vid_internal->flush_caches (); free (viddef.surfcache); viddef.surfcache = NULL; } - if (viddef.do_screen_buffer) { - viddef.do_screen_buffer (); + if (viddef.vid_internal->do_screen_buffer) { + viddef.vid_internal->do_screen_buffer (); } else { // Free the old screen buffer if (viddef.buffer) { @@ -302,13 +303,13 @@ VID_InitBuffers (void) Sys_Error ("Not enough memory for video mode"); } - if (viddef.init_caches) - viddef.init_caches (viddef.surfcache, cachesize); + if (viddef.vid_internal->init_caches) + viddef.vid_internal->init_caches (viddef.surfcache, cachesize); } void VID_ClearMemory (void) { - if (viddef.flush_caches) - viddef.flush_caches (); + if (viddef.vid_internal->flush_caches) + viddef.vid_internal->flush_caches (); } diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index b32efbee1..e48baea51 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -78,6 +78,8 @@ SDL_Surface *screen = NULL; # endif #endif +static vid_internal_t vid_internal; + static void (*set_vid_mode) (Uint32 flags); static void (GLAPIENTRY *qfglFinish) (void); @@ -157,7 +159,7 @@ sdlgl_set_vid_mode (Uint32 flags) success: viddef.numpages = 2; - viddef.init_gl (); + viddef.vid_internal->init_gl (); } static void @@ -170,8 +172,8 @@ sdlgl_end_rendering (void) static void sdl_load_gl (void) { - viddef.get_proc_address = QFGL_ProcAddress; - viddef.end_rendering = sdlgl_end_rendering; + viddef.vid_internal->get_proc_address = QFGL_ProcAddress; + viddef.vid_internal->end_rendering = sdlgl_end_rendering; set_vid_mode = sdlgl_set_vid_mode; if (SDL_GL_LoadLibrary (gl_driver->string) != 0) @@ -220,7 +222,7 @@ sdl_set_vid_mode (Uint32 flags) // now know everything we need to know about the buffer VGA_width = viddef.width; VGA_height = viddef.height; - viddef.do_screen_buffer = do_screen_buffer; + viddef.vid_internal->do_screen_buffer = do_screen_buffer; VGA_pagebase = viddef.buffer = screen->pixels; VGA_rowbytes = viddef.rowbytes = screen->pitch; viddef.conbuffer = viddef.buffer; @@ -235,6 +237,8 @@ VID_Init (byte *palette, byte *colormap) { Uint32 flags; + viddef.vid_internal = &vid_internal; + set_vid_mode = sdl_set_vid_mode; // Load the SDL library @@ -269,7 +273,7 @@ VID_Init (byte *palette, byte *colormap) VID_SDL_GammaCheck (); VID_InitGamma (palette); - viddef.set_palette (viddef.palette); + viddef.vid_internal->set_palette (viddef.palette); viddef.initialized = true; diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 1050d6adb..905620080 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -79,6 +79,7 @@ #include "dga_check.h" #include "vid_internal.h" +static vid_internal_t vid_internal; int XShmGetEventBase (Display *x); // for broken X11 headers static GC x_gc; @@ -209,7 +210,7 @@ glx_create_context (void) XSync (x_disp, 0); ctx = qfglXCreateContext (x_disp, x_visinfo, NULL, True); qfglXMakeCurrent (x_disp, x_win, ctx); - viddef.init_gl (); + viddef.vid_internal->init_gl (); } static void @@ -227,8 +228,8 @@ glx_load_gl (void) choose_visual = glx_choose_visual; create_context = glx_create_context; - viddef.get_proc_address = QFGL_ProcAddress; - viddef.end_rendering = glx_end_rendering; + viddef.vid_internal->get_proc_address = QFGL_ProcAddress; + viddef.vid_internal->end_rendering = glx_end_rendering; #ifdef RTLD_GLOBAL flags |= RTLD_GLOBAL; @@ -623,7 +624,7 @@ x11_create_context (void) x_shmeventtype = XShmGetEventBase (x_disp) + ShmCompletion; } - viddef.do_screen_buffer = x11_init_buffers; + viddef.vid_internal->do_screen_buffer = x11_init_buffers; VID_InitBuffers (); // XSynchronize (x_disp, False); @@ -666,6 +667,8 @@ VID_SetPalette (const byte *palette) void VID_Init (byte *palette, byte *colormap) { + viddef.vid_internal = &vid_internal; + choose_visual = x11_choose_visual; create_context = x11_create_context; @@ -686,7 +689,7 @@ VID_Init (byte *palette, byte *colormap) create_context (); VID_InitGamma (palette); - viddef.set_palette (viddef.palette); + viddef.vid_internal->set_palette (viddef.palette); Sys_MaskPrintf (SYS_VID, "Video mode %dx%d initialized.\n", viddef.width, viddef.height); From cb10175824d9c829b95b92cef8956c3e7d2a6cd2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 8 Jul 2019 14:02:24 +0900 Subject: [PATCH 0179/3664] Pass vid_internal to R_LoadModule This fixes the segfault and pushes things very much in the desired direction of proper system independence for rendering and presentation separation (though things were headed in the right direction before). --- include/QF/render.h | 4 ++-- libs/video/renderer/r_init.c | 5 ++--- libs/video/targets/vid_sdl.c | 5 +++-- libs/video/targets/vid_x11.c | 5 +++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index cc08c3800..03cebfa1c 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -172,8 +172,8 @@ extern struct texture_s *r_notexture_mip; extern entity_t r_worldentity; void R_Init (void); -void R_LoadModule (void (*load_gl)(void), - void (*set_palette) (const byte *palette)); +struct vid_internal_s; +void R_LoadModule (struct vid_internal_s *vid_internal); struct progs_s; void R_Progs_Init (struct progs_s *pr); diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 98acc39ad..330d0d76d 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -64,7 +64,7 @@ static U void (*const r_progs_init)(struct progs_s *) = R_Progs_Init; #undef U VISIBLE void -R_LoadModule (void (*load_gl)(void), void (*set_palette) (const byte *palette)) +R_LoadModule (vid_internal_t *vid_internal) { PI_RegisterPlugins (vidrend_plugin_list); vidrend_plugin = Cvar_Get ("vid_render", VID_RENDER_DEFAULT, CVAR_ROM, 0, @@ -77,8 +77,7 @@ R_LoadModule (void (*load_gl)(void), void (*set_palette) (const byte *palette)) r_funcs = vidrendmodule->functions->vid_render; mod_funcs = r_funcs->model_funcs; r_data = vidrendmodule->data->vid_render; - r_data->vid->vid_internal->load_gl = load_gl; - r_data->vid->vid_internal->set_palette = set_palette; + r_data->vid->vid_internal = vid_internal; vidrendmodule->functions->general->p_Init (); } diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index e48baea51..514b8020e 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -237,7 +237,8 @@ VID_Init (byte *palette, byte *colormap) { Uint32 flags; - viddef.vid_internal = &vid_internal; + vid_internal.set_palette = VID_SetPalette; + vid_internal.load_gl = sdl_load_gl; set_vid_mode = sdl_set_vid_mode; @@ -245,7 +246,7 @@ VID_Init (byte *palette, byte *colormap) if (SDL_Init (SDL_INIT_VIDEO) < 0) Sys_Error ("VID: Couldn't load SDL: %s", SDL_GetError ()); - R_LoadModule (sdl_load_gl, VID_SetPalette); + R_LoadModule (&vid_internal); viddef.numpages = 1; viddef.colormap8 = colormap; diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 905620080..bc4b4b6dc 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -667,12 +667,13 @@ VID_SetPalette (const byte *palette) void VID_Init (byte *palette, byte *colormap) { - viddef.vid_internal = &vid_internal; + vid_internal.load_gl = glx_load_gl; + vid_internal.set_palette = VID_SetPalette; choose_visual = x11_choose_visual; create_context = x11_create_context; - R_LoadModule (glx_load_gl, VID_SetPalette); + R_LoadModule (&vid_internal); viddef.numpages = 2; viddef.colormap8 = colormap; From 53a62e4d623828d199d12d641daabd3e42fb1341 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 00:44:48 +0900 Subject: [PATCH 0180/3664] Add checks for some dlopen flags Checks aren't used yet, though. --- config.d/library_functions.m4 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/config.d/library_functions.m4 b/config.d/library_functions.m4 index 66ff31edc..ba76c574e 100644 --- a/config.d/library_functions.m4 +++ b/config.d/library_functions.m4 @@ -35,6 +35,25 @@ if test "x$ac_cv_func_dlopen" != "xyes"; then fi AC_SUBST(DL_LIBS) +if test "x$DL_LIBS" != "x"; then +AC_MSG_CHECKING([for RTLD_NOW]) +AC_TRY_COMPILE( + [#include ], + [int foo = RTLD_NOW], + AC_DEFINE(HAVE_RTLD_NOW, 1, [Define if you have RTLD_NOW.]) + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no) +) +AC_MSG_CHECKING([for RTLD_DEEPBIND]) +AC_TRY_COMPILE( + [#include ], + [int foo = RTLD_DEEPBIND], + AC_DEFINE(HAVE_RTLD_DEEPBIND, 1, [Define if you have RTLD_DEEPBIND.]) + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no) +) +fi + dnl Checks for stricmp/strcasecmp #AC_CHECK_FUNC(strcasecmp, # , From 8ee06d75a9547a143c7054c1fb615a38a44c0f9b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 01:00:47 +0900 Subject: [PATCH 0181/3664] Separate render and presentation initialization This paves the way for clean initialization of the Vulkan renderer, and very much cleans up the older renderer initialization code as gl and sw are no longer intertwined. --- config.d/vulkan.m4 | 16 +- configure.ac | 2 +- include/QF/Vulkan/cvars.h | 1 - include/QF/Vulkan/funclist.h | 11 + include/QF/Vulkan/funcs.h | 9 - include/QF/Vulkan/init.h | 1 - include/context_sdl.h | 12 + include/context_x11.h | 9 + include/r_cvar.h | 1 - include/vid_gl.h | 20 + include/vid_internal.h | 13 +- include/vid_sw.h | 18 + include/vid_vulkan.h | 29 + libs/video/renderer/gl/gl_rmisc.c | 8 +- libs/video/renderer/gl/gl_screen.c | 6 +- libs/video/renderer/gl/qfgl_ext.c | 8 +- libs/video/renderer/glsl/glsl_main.c | 6 +- libs/video/renderer/glsl/glsl_screen.c | 4 +- libs/video/renderer/glsl/qfglsl.c | 6 +- libs/video/renderer/sw/screen.c | 3 +- libs/video/renderer/sw/sw_rmisc.c | 3 +- libs/video/renderer/sw32/screen.c | 3 +- libs/video/renderer/sw32/sw32_rmisc.c | 4 +- libs/video/renderer/vid_render_gl.c | 24 +- libs/video/renderer/vid_render_glsl.c | 23 +- libs/video/renderer/vid_render_sw.c | 24 +- libs/video/renderer/vid_render_sw32.c | 22 + libs/video/renderer/vid_render_vulkan.c | 9 +- libs/video/renderer/vulkan/Makefile.am | 3 +- libs/video/renderer/vulkan/init.c | 22 +- libs/video/renderer/vulkan/vulkan_funcs.c | 6 - .../video/renderer/vulkan/vulkan_vid_common.c | 39 +- libs/video/targets/Makefile.am | 14 +- libs/video/targets/context_sdl.c | 9 +- libs/video/targets/vid_sdl.c | 244 +------ libs/video/targets/vid_sdl_gl.c | 178 +++++ libs/video/targets/vid_sdl_sw.c | 183 +++++ libs/video/targets/vid_x11.c | 643 +----------------- libs/video/targets/vid_x11_gl.c | 209 ++++++ libs/video/targets/vid_x11_sw.c | 542 +++++++++++++++ libs/video/targets/vid_x11_vulkan.c | 169 +++++ 41 files changed, 1576 insertions(+), 980 deletions(-) delete mode 100644 include/QF/Vulkan/funcs.h create mode 100644 include/vid_gl.h create mode 100644 include/vid_sw.h create mode 100644 include/vid_vulkan.h delete mode 100644 libs/video/renderer/vulkan/vulkan_funcs.c create mode 100644 libs/video/targets/vid_sdl_gl.c create mode 100644 libs/video/targets/vid_sdl_sw.c create mode 100644 libs/video/targets/vid_x11_gl.c create mode 100644 libs/video/targets/vid_x11_sw.c create mode 100644 libs/video/targets/vid_x11_vulkan.c diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index c82900f58..4c9df43f4 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -9,16 +9,12 @@ if test "x$HAVE_VULKAN" != xno; then LDFLAGS="$LDFLAGS -L$VULKAN_SDK/lib" glslangvalidator="$VULKAN_SDK/bin/glslangValidator" ], [glslangvalidator="glslangValidator"]) - AC_CHECK_HEADER( - [vulkan/vulkan.h], - dnl Make sure the library "works" - [AC_CHECK_LIB([vulkan], [vkCreateInstance], - [AC_DEFINE([HAVE_VULKAN], [1], [Define if yhou have the Vulkan libs]) - VULKAN_LIBS=-lvulkan], - [AC_MSG_RESULT(no)]) - ], - [AC_MSG_RESULT(no)] - ) + AC_CHECK_HEADER([vulkan/vulkan.h], [HAVE_VULKAN=yes], [HAVE_VULKAN=no]) CPPFLAGS="$save_CPPFLAGS" fi +if test "x$HAVE_VULKAN" = xyes; then + AC_DEFINE([HAVE_VULKAN], [1], [Define if yhou have the Vulkan libs]) +fi AC_SUBST(VULKAN_LIBS) + +AM_CONDITIONAL(X11_VULKAN, test "x$HAVE_VULKAN" = "xyes") diff --git a/configure.ac b/configure.ac index aaf6492ea..fe398b273 100644 --- a/configure.ac +++ b/configure.ac @@ -63,8 +63,8 @@ m4_include(config.d/compression.m4) m4_include(config.d/mgl.m4) m4_include(config.d/fbdev.m4) m4_include(config.d/svga.m4) -m4_include(config.d/x11.m4) m4_include(config.d/vulkan.m4) +m4_include(config.d/x11.m4) m4_include(config.d/sdl.m4) m4_include(config.d/curses.m4) diff --git a/include/QF/Vulkan/cvars.h b/include/QF/Vulkan/cvars.h index 9f318b8f0..b6110e353 100644 --- a/include/QF/Vulkan/cvars.h +++ b/include/QF/Vulkan/cvars.h @@ -1,7 +1,6 @@ #ifndef __QF_Vulkan_cvars_h #define __QF_Vulkan_cvars_h -extern struct cvar_s *vulkan_library_name; extern struct cvar_s *vulkan_use_validation; #endif//__QF_Vulkan_cvars_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 2b755889e..79af14277 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -21,6 +21,16 @@ GLOBAL_LEVEL_VULKAN_FUNCTION (vkCreateInstance) #define INSTANCE_LEVEL_VULKAN_FUNCTION(function) #endif +#if defined(VK_USE_PLATFORM_XLIB_KHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceXlibPresentationSupportKHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateXlibSurfaceKHR) +#elif defined(VK_USE_PLATFORM_WIN32_KHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceWin32PresentationSupportKHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateWin32SurfaceKHR) +#elif defined(VK_USE_PLATFORM_XCB_KHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceXcbPresentationSupportKHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateXcbSurfaceKHR) +#else INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumeratePhysicalDevices) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures) @@ -31,6 +41,7 @@ INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceLayerProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceExtensionProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties) +#endif #undef INSTANCE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/funcs.h b/include/QF/Vulkan/funcs.h deleted file mode 100644 index 975f5485b..000000000 --- a/include/QF/Vulkan/funcs.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __QF_Vulkan_funcs_h -#define __QF_Vulkan_funcs_h - -#define EXPORTED_VULKAN_FUNCTION(fname) extern PFN_##fname fname; -#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) extern PFN_##fname fname; - -#include "QF/Vulkan/funclist.h" - -#endif//__QF_Vulkan_funcs_h diff --git a/include/QF/Vulkan/init.h b/include/QF/Vulkan/init.h index 4a97b82f8..85efb44e1 100644 --- a/include/QF/Vulkan/init.h +++ b/include/QF/Vulkan/init.h @@ -29,7 +29,6 @@ #include #include "QF/qtypes.h" -#include "QF/Vulkan/funcs.h" typedef struct { VkDevice device; diff --git a/include/context_sdl.h b/include/context_sdl.h index b097587f1..f6f1dbbe7 100644 --- a/include/context_sdl.h +++ b/include/context_sdl.h @@ -30,7 +30,19 @@ #ifndef __context_sdl_h_ #define __context_sdl_h_ +#include + +extern SDL_Surface *sdl_screen; + void VID_SDL_GammaCheck (void); void SDL_Init_Cvars (void); +struct gl_ctx_s *SDL_GL_Context (void); +void SDL_GL_Init_Cvars (void); + +struct sw_ctx_s *SDL_SW_Context (void); +void SDL_SW_Init_Cvars (void); + +extern uint32_t sdl_flags; + #endif // __context_sdl_h_ diff --git a/include/context_x11.h b/include/context_x11.h index b513e587a..884fafe9e 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -77,4 +77,13 @@ void X11_SaveMouseAcceleration (void); void X11_RemoveMouseAcceleration (void); void X11_RestoreMouseAcceleration (void); +struct gl_ctx_s *X11_GL_Context (void); +void X11_GL_Init_Cvars (void); + +struct sw_ctx_s *X11_SW_Context (void); +void X11_SW_Init_Cvars (void); + +struct vulkan_ctx_s *X11_Vulkan_Context (void); +void X11_Vulkan_Init_Cvars (void); + #endif // __context_x11_h_ diff --git a/include/r_cvar.h b/include/r_cvar.h index 8383f4705..e8a85a679 100644 --- a/include/r_cvar.h +++ b/include/r_cvar.h @@ -16,7 +16,6 @@ extern quat_t crosshair_color; extern struct cvar_s *d_mipcap; extern struct cvar_s *d_mipscale; -extern struct cvar_s *gl_driver; extern struct cvar_s *gl_affinemodels; extern struct cvar_s *gl_anisotropy; extern struct cvar_s *gl_clear; diff --git a/include/vid_gl.h b/include/vid_gl.h new file mode 100644 index 000000000..2561af575 --- /dev/null +++ b/include/vid_gl.h @@ -0,0 +1,20 @@ +#ifndef __vid_gl_h +#define __vid_gl_h + +// GLXContext is a pointer to opaque data +typedef struct __GLXcontextRec *GLXContext; + +typedef struct gl_ctx_s { + GLXContext context; + void (*load_gl) (void); + void (*choose_visual) (struct gl_ctx_s *ctx); + void (*create_context) (struct gl_ctx_s *ctx); + void (*init_gl) (void); + void *(*get_proc_address) (const char *name, qboolean crit); + void (*end_rendering) (void); +} gl_ctx_t; + +extern gl_ctx_t *gl_ctx; +extern gl_ctx_t *glsl_ctx; + +#endif//__vid_gl_h diff --git a/include/vid_internal.h b/include/vid_internal.h index fc1538202..e922508a4 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -11,11 +11,12 @@ typedef struct vid_internal_s { void (*do_screen_buffer) (void); void (*set_palette) (const byte *palette); - // gl stuff - void (*load_gl) (void); - void (*init_gl) (void); - void *(*get_proc_address) (const char *name, qboolean crit); - void (*end_rendering) (void); + void (*choose_visual) (void); + void (*create_context) (void); + + struct gl_ctx_s *(*gl_context) (void); + struct sw_ctx_s *(*sw_context) (void); + struct vulkan_ctx_s *(*vulkan_context) (void); } vid_internal_t; extern struct cvar_s *vid_fullscreen; @@ -30,11 +31,9 @@ void VID_InitGamma (unsigned char *); qboolean VID_SetGamma (double); void VID_UpdateGamma (struct cvar_s *); -void VID_Update (vrect_t *rects); void VID_LockBuffer (void); void VID_UnlockBuffer (void); void VID_InitBuffers (void); void VID_MakeColormaps (void); - #endif//__vid_internal_h diff --git a/include/vid_sw.h b/include/vid_sw.h new file mode 100644 index 000000000..2a5ab20a5 --- /dev/null +++ b/include/vid_sw.h @@ -0,0 +1,18 @@ +#ifndef __vid_sw_h +#define __vid_sw_h + +// GLXContext is a pointer to opaque data +typedef struct __GLXcontextRec *GLXContext; +struct vrect_s; +typedef struct sw_ctx_s { + GLXContext context; + void (*choose_visual) (struct sw_ctx_s *ctx); + void (*create_context) (struct sw_ctx_s *ctx); + void (*set_palette) (const byte *palette); + void (*update) (struct vrect_s *rects); +} sw_ctx_t; + +extern sw_ctx_t *sw_ctx; +extern sw_ctx_t *sw32_ctx; + +#endif//__vid_sw_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h new file mode 100644 index 000000000..627269cdb --- /dev/null +++ b/include/vid_vulkan.h @@ -0,0 +1,29 @@ +#ifndef __vid_vulkan_h +#define __vid_vulkan_h + +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + +typedef struct vulkan_ctx_s { + void (*load_vulkan) (struct vulkan_ctx_s *ctx); + void (*unload_vulkan) (struct vulkan_ctx_s *ctx); + void (*init_vulkan) (void); + + const char * const *required_extensions; + struct vulkan_presentation_s *presentation; + int (*get_presentation_support) (struct vulkan_ctx_s *ctx, + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex); + VkSurfaceKHR (*create_surface) (struct vulkan_ctx_s *ctx); + VkInstance instance; + VkPhysicalDevice physicalDevice; +#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; +#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; +#include "QF/Vulkan/funclist.h" +} vulkan_ctx_t; + +extern vulkan_ctx_t *vulkan_ctx; + +#endif//__vid_vulkan_h diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index e054e37bf..a47e6ba42 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -64,7 +64,7 @@ #include "mod_internal.h" #include "r_internal.h" #include "varrays.h" -#include "vid_internal.h" +#include "vid_gl.h" /* R_Envmap_f @@ -122,7 +122,7 @@ R_Envmap_f (void) gl_envmap = false; qfglDrawBuffer (GL_BACK); qfglReadBuffer (GL_BACK); - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); } void @@ -250,13 +250,13 @@ gl_R_TimeRefresh_f (void) double start, stop, time; int i; - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); start = Sys_DoubleTime (); for (i = 0; i < 128; i++) { r_refdef.viewangles[1] = i * (360.0 / 128.0); gl_R_RenderView (); - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); } stop = Sys_DoubleTime (); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 73674e70c..fbe47106f 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -59,7 +59,7 @@ #include "compat.h" #include "r_internal.h" #include "sbar.h" -#include "vid_internal.h" +#include "vid_gl.h" /* SCREEN SHOTS */ @@ -207,7 +207,7 @@ gl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) return; if (begun) - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); vr_data.realtime = realtime; @@ -264,7 +264,7 @@ gl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) qfglFlush (); if (gl_finish->int_val) { - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); begun = 0; } } diff --git a/libs/video/renderer/gl/qfgl_ext.c b/libs/video/renderer/gl/qfgl_ext.c index 41fe1f52b..f012726de 100644 --- a/libs/video/renderer/gl/qfgl_ext.c +++ b/libs/video/renderer/gl/qfgl_ext.c @@ -61,7 +61,7 @@ #include "QF/GL/funcs.h" #include "r_internal.h" -#include "vid_internal.h" +#include "vid_gl.h" // First we need to get all the function pointers declared. #define QFGL_WANT(ret, name, args) \ @@ -76,9 +76,9 @@ qboolean GLF_FindFunctions (void) { #define QFGL_WANT(ret, name, args) \ - qf##name = vid.vid_internal->get_proc_address (#name, false); + qf##name = gl_ctx->get_proc_address (#name, false); #define QFGL_NEED(ret, name, args) \ - qf##name = vid.vid_internal->get_proc_address (#name, true); + qf##name = gl_ctx->get_proc_address (#name, true); #include "QF/GL/qf_funcs_list.h" #undef QFGL_NEED #undef QFGL_WANT @@ -136,6 +136,6 @@ void * QFGL_ExtensionAddress (const char *name) { if (name) - return vid.vid_internal->get_proc_address (name, false); + return gl_ctx->get_proc_address (name, false); return NULL; } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 2bc60bdd4..32688b2ae 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -58,7 +58,7 @@ #include "mod_internal.h" #include "r_internal.h" -#include "vid_internal.h" +#include "vid_gl.h" mat4_t glsl_projection; mat4_t glsl_view; @@ -305,13 +305,13 @@ glsl_R_TimeRefresh_f (void) double start, stop, time; int i; - vid.vid_internal->end_rendering (); + glsl_ctx->end_rendering (); start = Sys_DoubleTime (); for (i = 0; i < 128; i++) { r_refdef.viewangles[1] = i * (360.0 / 128.0); glsl_R_RenderView (); - vid.vid_internal->end_rendering (); + glsl_ctx->end_rendering (); } stop = Sys_DoubleTime (); diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index ecdda6ec8..89276999d 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -60,7 +60,7 @@ #include "QF/GLSL/qf_vid.h" #include "r_internal.h" -#include "vid_internal.h" +#include "vid_gl.h" /* Unknown renamed to GLErr_Unknown to solve conflict with winioctl.h */ static unsigned int GLErr_InvalidEnum; @@ -166,7 +166,7 @@ glsl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, if (begun) { begun = 0; - vid.vid_internal->end_rendering (); + glsl_ctx->end_rendering (); } vr_data.realtime = realtime; diff --git a/libs/video/renderer/glsl/qfglsl.c b/libs/video/renderer/glsl/qfglsl.c index b4fd25662..0e48e9354 100644 --- a/libs/video/renderer/glsl/qfglsl.c +++ b/libs/video/renderer/glsl/qfglsl.c @@ -60,7 +60,7 @@ #include "QF/GLSL/funcs.h" #include "r_internal.h" -#include "vid_internal.h" +#include "vid_gl.h" // First we need to get all the function pointers declared. #define QFGL_WANT(ret, name, args) \ @@ -75,9 +75,9 @@ qboolean EGLF_FindFunctions (void) { #define QFGL_WANT(ret, name, args) \ - qfe##name = vid.vid_internal->get_proc_address (#name, false); + qfe##name = glsl_ctx->get_proc_address (#name, false); #define QFGL_NEED(ret, name, args) \ - qfe##name = vid.vid_internal->get_proc_address (#name, true); + qfe##name = glsl_ctx->get_proc_address (#name, true); #include "QF/GLSL/qf_funcs_list.h" #undef QFGL_NEED #undef QFGL_WANT diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index d425f6549..5b69e7a0d 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -51,6 +51,7 @@ #include "compat.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" /* SCREEN SHOTS */ @@ -263,5 +264,5 @@ SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) vrect.height = scr_vrect.height; vrect.next = 0; } - VID_Update (&vrect); + sw_ctx->update (&vrect); } diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index f30200ffa..b2272ff14 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -37,6 +37,7 @@ #include "compat.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" static void @@ -74,7 +75,7 @@ R_TimeRefresh_f (void) vr.width = r_refdef.vrect.width; vr.height = r_refdef.vrect.height; vr.next = NULL; - VID_Update (&vr); + sw_ctx->update (&vr); } stop = Sys_DoubleTime (); time = stop - start; diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index bcadb5c9b..e4779d8da 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -54,6 +54,7 @@ #include "compat.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" /* SCREEN SHOTS */ @@ -221,5 +222,5 @@ sw32_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs vrect.height = scr_vrect.height; vrect.next = 0; } - VID_Update (&vrect); + sw32_ctx->update (&vrect); } diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c index cb12395d3..1b329b54f 100644 --- a/libs/video/renderer/sw32/sw32_rmisc.c +++ b/libs/video/renderer/sw32/sw32_rmisc.c @@ -40,7 +40,7 @@ #include "compat.h" #include "r_internal.h" #include "vid_internal.h" - +#include "vid_sw.h" static void R_CheckVariables (void) @@ -77,7 +77,7 @@ sw32_R_TimeRefresh_f (void) vr.width = r_refdef.vrect.width; vr.height = r_refdef.vrect.height; vr.next = NULL; - VID_Update (&vr); + sw32_ctx->update (&vr); } stop = Sys_DoubleTime (); time = stop - start; diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 91f4178b5..9085e751d 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -39,9 +39,12 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_gl.h" #include "gl/namehack.h" +gl_ctx_t *gl_ctx; + static vid_model_funcs_t model_funcs = { gl_Mod_LoadExternalTextures, gl_Mod_LoadLighting, @@ -124,12 +127,29 @@ vid_render_funcs_t gl_vid_render_funcs = { &model_funcs }; +static void +gl_vid_render_choose_visual (void) +{ + gl_ctx->choose_visual (gl_ctx); +} + +static void +gl_vid_render_create_context (void) +{ + gl_ctx->create_context (gl_ctx); +} + static void gl_vid_render_init (void) { + gl_ctx = vr_data.vid->vid_internal->gl_context (); + gl_ctx->init_gl = GL_Init_Common; + gl_ctx->load_gl (); + vr_data.vid->vid_internal->set_palette = GL_SetPalette; - vr_data.vid->vid_internal->init_gl = GL_Init_Common; - vr_data.vid->vid_internal->load_gl (); + vr_data.vid->vid_internal->choose_visual = gl_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = gl_vid_render_create_context; + vr_funcs = &gl_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index d1f380ae5..22de04ea3 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -39,9 +39,12 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_gl.h" #include "glsl/namehack.h" +gl_ctx_t *glsl_ctx; + static vid_model_funcs_t model_funcs = { glsl_Mod_LoadExternalTextures, glsl_Mod_LoadLighting, @@ -124,12 +127,28 @@ vid_render_funcs_t glsl_vid_render_funcs = { &model_funcs }; +static void +glsl_vid_render_choose_visual (void) +{ + glsl_ctx->choose_visual (glsl_ctx); +} + +static void +glsl_vid_render_create_context (void) +{ + glsl_ctx->create_context (glsl_ctx); +} + static void glsl_vid_render_init (void) { + glsl_ctx = vr_data.vid->vid_internal->gl_context (); + glsl_ctx->init_gl = GLSL_Init_Common; + glsl_ctx->load_gl (); + vr_data.vid->vid_internal->set_palette = GLSL_SetPalette; - vr_data.vid->vid_internal->init_gl = GLSL_Init_Common; - vr_data.vid->vid_internal->load_gl (); + vr_data.vid->vid_internal->choose_visual = glsl_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = glsl_vid_render_create_context; vr_funcs = &glsl_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 7c2485911..dcfb4abc7 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -1,5 +1,5 @@ /* - vid_render_gl.c + vid_render_sw.c SW version of the renderer @@ -33,6 +33,10 @@ #include "mod_internal.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" + +sw_ctx_t *sw_ctx; static vid_model_funcs_t model_funcs = { sw_Mod_LoadExternalTextures, @@ -116,9 +120,27 @@ vid_render_funcs_t sw_vid_render_funcs = { &model_funcs }; +static void +sw_vid_render_choose_visual (void) +{ + sw_ctx->choose_visual (sw_ctx); +} + +static void +sw_vid_render_create_context (void) +{ + sw_ctx->create_context (sw_ctx); +} + static void sw_vid_render_init (void) { + sw_ctx = vr_data.vid->vid_internal->sw_context (); + + vr_data.vid->vid_internal->set_palette = sw_ctx->set_palette; + vr_data.vid->vid_internal->choose_visual = sw_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = sw_vid_render_create_context; + vr_funcs = &sw_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 40034c0dc..ed7414a85 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -36,9 +36,13 @@ #include "mod_internal.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" #include "sw32/namehack.h" +sw_ctx_t *sw32_ctx; + static vid_model_funcs_t model_funcs = { sw_Mod_LoadExternalTextures, sw_Mod_LoadLighting, @@ -121,9 +125,27 @@ vid_render_funcs_t sw32_vid_render_funcs = { &model_funcs }; +static void +sw32_vid_render_choose_visual (void) +{ + sw32_ctx->choose_visual (sw32_ctx); +} + +static void +sw32_vid_render_create_context (void) +{ + sw32_ctx->create_context (sw32_ctx); +} + static void sw32_vid_render_init (void) { + sw32_ctx = vr_data.vid->vid_internal->sw_context (); + + vr_data.vid->vid_internal->set_palette = sw32_ctx->set_palette; + vr_data.vid->vid_internal->choose_visual = sw32_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = sw32_vid_render_create_context; + vr_funcs = &sw32_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index c71264fcb..2a94f31cb 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -39,9 +39,12 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_vulkan.h" #include "vulkan/namehack.h" +vulkan_ctx_t *vulkan_ctx; + static vid_model_funcs_t model_funcs = { /* vulkan_Mod_LoadExternalTextures, vulkan_Mod_LoadLighting, @@ -135,9 +138,11 @@ set_palette (const byte *palette) static void vulkan_vid_render_init (void) { + vulkan_ctx = vr_data.vid->vid_internal->vulkan_context (); + vulkan_ctx->init_vulkan = Vulkan_Init_Common; + vulkan_ctx->load_vulkan (vulkan_ctx); + vr_data.vid->vid_internal->set_palette = set_palette; - vr_data.vid->vid_internal->init_gl = Vulkan_Init_Common; - vr_data.vid->vid_internal->load_gl (); vr_funcs = &vulkan_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index 5d2f65d8e..e4102ec9d 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -1,12 +1,11 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES -DVK_USE_PLATFORM_XLIB_KHR +AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES vulkan_src = \ init.c \ vulkan_draw.c \ - vulkan_funcs.c \ vulkan_vid_common.c noinst_LTLIBRARIES= libvulkan.la diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c index 2c4fb7ca1..e3181fc07 100644 --- a/libs/video/renderer/vulkan/init.c +++ b/libs/video/renderer/vulkan/init.c @@ -43,7 +43,8 @@ #include "QF/vid.h" #include "QF/Vulkan/init.h" -cvar_t *vulkan_library_name; +#include "vid_vulkan.h" + cvar_t *vulkan_use_validation; static uint32_t numLayers; @@ -78,9 +79,9 @@ get_instance_layers_and_extensions (void) VkLayerProperties *properties; VkExtensionProperties *extensions; - vkEnumerateInstanceLayerProperties (&numLayers, 0); + vulkan_ctx->vkEnumerateInstanceLayerProperties (&numLayers, 0); properties = malloc (numLayers * sizeof (VkLayerProperties)); - vkEnumerateInstanceLayerProperties (&numLayers, properties); + vulkan_ctx->vkEnumerateInstanceLayerProperties (&numLayers, properties); instanceLayerNames = (const char **) malloc ((numLayers + 1) * sizeof (const char **)); for (i = 0; i < numLayers; i++) { @@ -88,9 +89,10 @@ get_instance_layers_and_extensions (void) } instanceLayerNames[i] = 0; - vkEnumerateInstanceExtensionProperties (0, &numExtensions, 0); + vulkan_ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, 0); extensions = malloc (numExtensions * sizeof (VkLayerProperties)); - vkEnumerateInstanceExtensionProperties (0, &numExtensions, extensions); + vulkan_ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, + extensions); instanceExtensionNames = (const char **) malloc ((numExtensions + 1) * sizeof (const char **)); for (i = 0; i < numExtensions; i++) { @@ -278,15 +280,15 @@ static void load_instance_funcs (VulkanInstance_t *instance) { #define INSTANCE_LEVEL_VULKAN_FUNCTION(name) \ - instance->name = (PFN_##name) vkGetInstanceProcAddr (instance->instance, \ - #name); \ + instance->name = (PFN_##name) \ + vulkan_ctx->vkGetInstanceProcAddr (instance->instance, #name); \ if (!instance->name) { \ Sys_Error ("Couldn't find instance level function %s", #name); \ } #define INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) \ - instance->name = (PFN_##name) vkGetInstanceProcAddr (instance->instance,\ - #name); \ + instance->name = (PFN_##name) \ + vulkan_ctx->vkGetInstanceProcAddr (instance->instance, #name); \ if (!instance->name) { \ Sys_Printf ("Couldn't find instance level function %s", #name); \ } @@ -344,7 +346,7 @@ Vulkan_CreateInstance (const char *appName, uint32_t appVersion, createInfo.ppEnabledLayerNames = lay; createInfo.ppEnabledExtensionNames = ext; - res = vkCreateInstance (&createInfo, 0, &instance); + res = vulkan_ctx->vkCreateInstance (&createInfo, 0, &instance); if (res != VK_SUCCESS) { Sys_Error ("unable to create vulkan instance\n"); } diff --git a/libs/video/renderer/vulkan/vulkan_funcs.c b/libs/video/renderer/vulkan/vulkan_funcs.c deleted file mode 100644 index 2d8f79c9a..000000000 --- a/libs/video/renderer/vulkan/vulkan_funcs.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; -#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; - -#include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 9366799cb..98a4d3dc3 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -39,8 +39,6 @@ # include #endif -#include - #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/input.h" @@ -55,43 +53,14 @@ #include "compat.h" #include "d_iface.h" #include "r_internal.h" - -static void *vulkan_library; +#include "vid_vulkan.h" static VulkanInstance_t *vulkan_instance; static VulkanDevice_t *vulkan_device; -static void -load_vulkan_library (void) -{ - vulkan_library = dlopen (vulkan_library_name->string, - RTLD_DEEPBIND | RTLD_NOW); - if (!vulkan_library) { - Sys_Error ("Couldn't load vulkan library %s: %s", - vulkan_library_name->name, dlerror ()); - } - - #define EXPORTED_VULKAN_FUNCTION(name) \ - name = (PFN_##name) dlsym (vulkan_library, #name); \ - if (!name) { \ - Sys_Error ("Couldn't find exported vulkan function %s", #name); \ - } - - #define GLOBAL_LEVEL_VULKAN_FUNCTION(name) \ - name = (PFN_##name) vkGetInstanceProcAddr (0, #name); \ - if (!name) { \ - Sys_Error ("Couldn't find global-level function %s", #name); \ - } - - #include "QF/Vulkan/funclist.h" -} - void Vulkan_Init_Cvars () { - vulkan_library_name = Cvar_Get ("vulkan_library", "libvulkan.so.1", - CVAR_ROM, 0, - "the name of the vulkan shared library"); vulkan_use_validation = Cvar_Get ("vulkan_use_validation", "1", CVAR_NONE, 0, "enable LunarG Standard Validation " @@ -101,7 +70,6 @@ Vulkan_Init_Cvars () static const char *instance_extensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_XLIB_SURFACE_EXTENSION_NAME, 0, }; @@ -203,8 +171,6 @@ Vulkan_Init_Common (void) Sys_Printf ("Vulkan_Init_Common\n"); Vulkan_Init_Cvars (); - load_vulkan_library (); - vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version vulkan_device = create_suitable_device (vulkan_instance); if (!vulkan_device) { @@ -227,6 +193,5 @@ Vulkan_Shutdown_Common (void) } Vulkan_DestroyInstance (vulkan_instance); vulkan_instance = 0; - dlclose (vulkan_library); - vulkan_library = 0; + vulkan_ctx->unload_vulkan (vulkan_ctx); } diff --git a/libs/video/targets/Makefile.am b/libs/video/targets/Makefile.am index b883b676b..d7241f528 100644 --- a/libs/video/targets/Makefile.am +++ b/libs/video/targets/Makefile.am @@ -27,6 +27,15 @@ joy_src= $(joy_null_src) endif endif +x11_gl_src=vid_x11_gl.c +x11_sw_src=vid_x11_sw.c +x11_vulkan_src=vid_x11_vulkan.c +if X11_VULKAN +x11_src= $(x11_gl_src) $(x11_sw_src) $(x11_vulkan_src) +else +x11_src= $(x11_gl_src) $(x11_sw_src) +endif + js_libs=$(top_builddir)/libs/util/libQFutil.la libQFjs_la_LDFLAGS= $(lib_ldflags) @@ -41,15 +50,16 @@ libvid_common_la_SOURCES= \ libvid_common_la_CFLAGS= @PREFER_NON_PIC@ libvid_common_la_LDFLAGS= @STATIC@ -libvid_x11_la_SOURCES= in_x11.c context_x11.c dga_check.c +libvid_x11_la_SOURCES= in_x11.c context_x11.c dga_check.c $(x11_src) libvid_x11_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) libvid_x11_la_LDFLAGS= @STATIC@ +EXTRA_libvid_x11_la_SOURCES= $(x11_vulkan_src) libvid_svga_la_SOURCES= in_svgalib.c libvid_svga_la_CFLAGS= @PREFER_NON_PIC@ $(SVGA_CFLAGS) libvid_svga_la_LDFLAGS= @STATIC@ -libvid_sdl_la_SOURCES= in_sdl.c context_sdl.c +libvid_sdl_la_SOURCES= in_sdl.c context_sdl.c vid_sdl_gl.c vid_sdl_sw.c libvid_sdl_la_CFLAGS= @PREFER_NON_PIC@ $(SDL_CFLAGS) libvid_sdl_la_LDFLAGS= @STATIC@ diff --git a/libs/video/targets/context_sdl.c b/libs/video/targets/context_sdl.c index 105d7e1f6..7426ea8f8 100644 --- a/libs/video/targets/context_sdl.c +++ b/libs/video/targets/context_sdl.c @@ -23,9 +23,6 @@ cvar_t *vid_bitdepth; -extern SDL_Surface *screen; - - void VID_SDL_GammaCheck (void) { @@ -67,9 +64,9 @@ VID_UpdateFullscreen (cvar_t *vid_fullscreen) { if (!r_data || !viddef.initialized) return; - if ((vid_fullscreen->int_val && !(screen->flags & SDL_FULLSCREEN)) - || (!vid_fullscreen->int_val && screen->flags & SDL_FULLSCREEN)) - if (!SDL_WM_ToggleFullScreen (screen)) + if ((vid_fullscreen->int_val && !(sdl_screen->flags & SDL_FULLSCREEN)) + || (!vid_fullscreen->int_val && sdl_screen->flags & SDL_FULLSCREEN)) + if (!SDL_WM_ToggleFullScreen (sdl_screen)) Sys_Printf ("VID_UpdateFullscreen: error setting fullscreen\n"); IN_UpdateGrab (in_grab); } diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index 514b8020e..9b1938d30 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -58,190 +58,17 @@ HWND mainwindow; #define BASEWIDTH 320 #define BASEHEIGHT 200 -byte *VGA_pagebase; -int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0; - -SDL_Surface *screen = NULL; - -// Define GLAPIENTRY to a useful value -#ifndef GLAPIENTRY -# ifdef _WIN32 -# include -# define GLAPIENTRY WINAPI -# undef LoadImage -# else -# ifdef APIENTRY -# define GLAPIENTRY APIENTRY -# else -# define GLAPIENTRY -# endif -# endif -#endif +SDL_Surface *sdl_screen = NULL; static vid_internal_t vid_internal; -static void (*set_vid_mode) (Uint32 flags); - -static void (GLAPIENTRY *qfglFinish) (void); -static int use_gl_procaddress = 0; -static cvar_t *gl_driver; - -static byte cached_palette[256 * 3]; -static int update_palette; - -static void * -QFGL_ProcAddress (const char *name, qboolean crit) -{ - void *glfunc = NULL; - - Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); - - glfunc = SDL_GL_GetProcAddress (name); - if (glfunc) { - Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); - return glfunc; - } - Sys_MaskPrintf (SYS_VID, "not found\n"); - - if (crit) { - if (strncmp ("fxMesa", name, 6) == 0) { - Sys_Printf ("This target requires a special version of Mesa with " - "support for Glide and SVGAlib.\n"); - Sys_Printf ("If you are in X, try using a GLX or SGL target.\n"); - } - Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", - name); - } - return NULL; -} - -static void -sdlgl_set_vid_mode (Uint32 flags) -{ - int i, j; - - flags |= SDL_OPENGL; - - // Setup GL Attributes - SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); -// SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 0); // Try for 0, 8 -// SDL_GL_SetAttribute (SDL_GL_STEREO, 1); // Someday... - - for (i = 0; i < 5; i++) { - int k; - int color[5] = {32, 24, 16, 15, 0}; - int rgba[5][4] = { - {8, 8, 8, 0}, - {8, 8, 8, 8}, - {5, 6, 5, 0}, - {5, 5, 5, 0}, - {5, 5, 5, 1}, - }; - - SDL_GL_SetAttribute (SDL_GL_RED_SIZE, rgba[i][0]); - SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgba[i][1]); - SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, rgba[i][2]); - SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, rgba[i][3]); - - for (j = 0; j < 5; j++) { - for (k = 32; k >= 16; k -= 8) { - SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, k); - if ((screen = SDL_SetVideoMode (viddef.width, viddef.height, - color[j], flags))) - goto success; - } - } - } - - Sys_Error ("Couldn't set video mode: %s", SDL_GetError ()); - SDL_Quit (); - -success: - viddef.numpages = 2; - - viddef.vid_internal->init_gl (); -} - -static void -sdlgl_end_rendering (void) -{ - qfglFinish (); - SDL_GL_SwapBuffers (); -} - -static void -sdl_load_gl (void) -{ - viddef.vid_internal->get_proc_address = QFGL_ProcAddress; - viddef.vid_internal->end_rendering = sdlgl_end_rendering; - set_vid_mode = sdlgl_set_vid_mode; - - if (SDL_GL_LoadLibrary (gl_driver->string) != 0) - Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); - - use_gl_procaddress = 1; - - qfglFinish = QFGL_ProcAddress ("glFinish", true); -} - -static void -sdl_update_palette (const byte *palette) -{ - SDL_Color colors[256]; - int i; - - for (i = 0; i < 256; ++i) { - colors[i].r = *palette++; - colors[i].g = *palette++; - colors[i].b = *palette++; - } - SDL_SetColors (screen, colors, 0, 256); -} - -static void -VID_SetPalette (const byte *palette) -{ - if (memcmp (cached_palette, palette, sizeof (cached_palette))) { - memcpy (cached_palette, palette, sizeof (cached_palette)); - update_palette = 1; - } -} - -static void -do_screen_buffer (void) -{ -} - -static void -sdl_set_vid_mode (Uint32 flags) -{ - // Initialize display - if (!(screen = SDL_SetVideoMode (viddef.width, viddef.height, 8, flags))) - Sys_Error ("VID: Couldn't set video mode: %s", SDL_GetError ()); - - // now know everything we need to know about the buffer - VGA_width = viddef.width; - VGA_height = viddef.height; - viddef.vid_internal->do_screen_buffer = do_screen_buffer; - VGA_pagebase = viddef.buffer = screen->pixels; - VGA_rowbytes = viddef.rowbytes = screen->pitch; - viddef.conbuffer = viddef.buffer; - viddef.conrowbytes = viddef.rowbytes; - viddef.direct = 0; - - VID_InitBuffers (); // allocate z buffer and surface cache -} +uint32_t sdl_flags; void VID_Init (byte *palette, byte *colormap) { - Uint32 flags; - - vid_internal.set_palette = VID_SetPalette; - vid_internal.load_gl = sdl_load_gl; - - set_vid_mode = sdl_set_vid_mode; - + vid_internal.gl_context = SDL_GL_Context; + vid_internal.sw_context = SDL_SW_Context; // Load the SDL library if (SDL_Init (SDL_INIT_VIDEO) < 0) Sys_Error ("VID: Couldn't load SDL: %s", SDL_GetError ()); @@ -256,9 +83,9 @@ VID_Init (byte *palette, byte *colormap) VID_GetWindowSize (BASEWIDTH, BASEHEIGHT); // Set video width, height and flags - flags = (SDL_SWSURFACE | SDL_HWPALETTE); + sdl_flags = (SDL_SWSURFACE | SDL_HWPALETTE); if (vid_fullscreen->int_val) { - flags |= SDL_FULLSCREEN; + sdl_flags |= SDL_FULLSCREEN; #ifndef _WIN32 // Don't annoy Mesa/3dfx folks // doesn't hurt if not using a gl renderer // FIXME: Maybe this could be put in a different spot, but I don't @@ -270,11 +97,10 @@ VID_Init (byte *palette, byte *colormap) #endif } - set_vid_mode (flags); + vid_internal.create_context (); VID_SDL_GammaCheck (); VID_InitGamma (palette); - viddef.vid_internal->set_palette (viddef.palette); viddef.initialized = true; @@ -296,46 +122,8 @@ void VID_Init_Cvars () { SDL_Init_Cvars (); - gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, - "The OpenGL library to use. (path optional)"); -} - -void -VID_Update (vrect_t *rects) -{ - static SDL_Rect *sdlrects; - static int num_sdlrects; - int i, n; - vrect_t *rect; - - if (update_palette) { - update_palette = 0; - sdl_update_palette (cached_palette); - } - // Two-pass system, since Quake doesn't do it the SDL way... - - // First, count the number of rectangles - n = 0; - for (rect = rects; rect; rect = rect->next) - ++n; - - if (n > num_sdlrects) { - num_sdlrects = n; - sdlrects = realloc (sdlrects, n * sizeof (SDL_Rect)); - if (!sdlrects) - Sys_Error ("Out of memory!"); - } - - // Second, copy them to SDL rectangles and update - i = 0; - for (rect = rects; rect; rect = rect->next) { - sdlrects[i].x = rect->x; - sdlrects[i].y = rect->y; - sdlrects[i].w = rect->width; - sdlrects[i].h = rect->height; - ++i; - } - SDL_UpdateRects (screen, n, sdlrects); + SDL_GL_Init_Cvars (); + SDL_SW_Init_Cvars (); } void @@ -343,14 +131,14 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { Uint8 *offset; - if (!screen) + if (!sdl_screen) return; if (x < 0) - x = screen->w + x - 1; - offset = (Uint8 *) screen->pixels + y * screen->pitch + x; + x = sdl_screen->w + x - 1; + offset = (Uint8 *) sdl_screen->pixels + y * sdl_screen->pitch + x; while (height--) { memcpy (offset, pbitmap, width); - offset += screen->pitch; + offset += sdl_screen->pitch; pbitmap += width; } } @@ -358,11 +146,11 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) void D_EndDirectRect (int x, int y, int width, int height) { - if (!screen) + if (!sdl_screen) return; if (x < 0) - x = screen->w + x - 1; - SDL_UpdateRect (screen, x, y, width, height); + x = sdl_screen->w + x - 1; + SDL_UpdateRect (sdl_screen, x, y, width, height); } void diff --git a/libs/video/targets/vid_sdl_gl.c b/libs/video/targets/vid_sdl_gl.c new file mode 100644 index 000000000..829ca2860 --- /dev/null +++ b/libs/video/targets/vid_sdl_gl.c @@ -0,0 +1,178 @@ +/* + vid_sdl.c + + Video driver for Sam Lantinga's Simple DirectMedia Layer + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include + +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/qendian.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_sdl.h" +#include "d_iface.h" +#include "vid_internal.h" +#include "vid_gl.h" + +// Define GLAPIENTRY to a useful value +#ifndef GLAPIENTRY +# ifdef _WIN32 +# include +# define GLAPIENTRY WINAPI +# undef LoadImage +# else +# ifdef APIENTRY +# define GLAPIENTRY APIENTRY +# else +# define GLAPIENTRY +# endif +# endif +#endif + +static void (GLAPIENTRY *qfglFinish) (void); +static int use_gl_procaddress = 0; +static cvar_t *gl_driver; + +static void * +QFGL_ProcAddress (const char *name, qboolean crit) +{ + void *glfunc = NULL; + + Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); + + glfunc = SDL_GL_GetProcAddress (name); + if (glfunc) { + Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); + return glfunc; + } + Sys_MaskPrintf (SYS_VID, "not found\n"); + + if (crit) { + if (strncmp ("fxMesa", name, 6) == 0) { + Sys_Printf ("This target requires a special version of Mesa with " + "support for Glide and SVGAlib.\n"); + Sys_Printf ("If you are in X, try using a GLX or SGL target.\n"); + } + Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", + name); + } + return NULL; +} + +static void +sdlgl_set_vid_mode (gl_ctx_t *ctx) +{ + int i, j; + + sdl_flags |= SDL_OPENGL; + + // Setup GL Attributes + SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); +// SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 0); // Try for 0, 8 +// SDL_GL_SetAttribute (SDL_GL_STEREO, 1); // Someday... + + for (i = 0; i < 5; i++) { + int k; + int color[5] = {32, 24, 16, 15, 0}; + int rgba[5][4] = { + {8, 8, 8, 0}, + {8, 8, 8, 8}, + {5, 6, 5, 0}, + {5, 5, 5, 0}, + {5, 5, 5, 1}, + }; + + SDL_GL_SetAttribute (SDL_GL_RED_SIZE, rgba[i][0]); + SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgba[i][1]); + SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, rgba[i][2]); + SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, rgba[i][3]); + + for (j = 0; j < 5; j++) { + for (k = 32; k >= 16; k -= 8) { + SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, k); + if ((sdl_screen = SDL_SetVideoMode (viddef.width, viddef.height, + color[j], sdl_flags))) + goto success; + } + } + } + + Sys_Error ("Couldn't set video mode: %s", SDL_GetError ()); + SDL_Quit (); + +success: + viddef.numpages = 2; + + ctx->init_gl (); +} + +static void +sdlgl_end_rendering (void) +{ + qfglFinish (); + SDL_GL_SwapBuffers (); +} + +static void +sdl_load_gl (void) +{ + if (SDL_GL_LoadLibrary (gl_driver->string) != 0) + Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); + + use_gl_procaddress = 1; + + qfglFinish = QFGL_ProcAddress ("glFinish", true); +} + +gl_ctx_t * +SDL_GL_Context (void) +{ + gl_ctx_t *ctx = calloc (1, sizeof (gl_ctx_t)); + ctx->load_gl = sdl_load_gl; + ctx->create_context = sdlgl_set_vid_mode; + ctx->get_proc_address = QFGL_ProcAddress; + ctx->end_rendering = sdlgl_end_rendering; + return ctx; +} + +void +SDL_GL_Init_Cvars () +{ + gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, + "The OpenGL library to use. (path optional)"); +} diff --git a/libs/video/targets/vid_sdl_sw.c b/libs/video/targets/vid_sdl_sw.c new file mode 100644 index 000000000..2d4f806d4 --- /dev/null +++ b/libs/video/targets/vid_sdl_sw.c @@ -0,0 +1,183 @@ +/* + vid_sdl.c + + Video driver for Sam Lantinga's Simple DirectMedia Layer + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include + +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/qendian.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_sdl.h" +#include "d_iface.h" +#include "vid_internal.h" +#include "vid_sw.h" + +#ifdef _WIN32 // FIXME: evil hack to get full DirectSound support with SDL +#include +#include +HWND mainwindow; +#endif + +// The original defaults +#define BASEWIDTH 320 +#define BASEHEIGHT 200 + +byte *VGA_pagebase; +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0; + +// Define GLAPIENTRY to a useful value +#ifndef GLAPIENTRY +# ifdef _WIN32 +# include +# define GLAPIENTRY WINAPI +# undef LoadImage +# else +# ifdef APIENTRY +# define GLAPIENTRY APIENTRY +# else +# define GLAPIENTRY +# endif +# endif +#endif + +static byte cached_palette[256 * 3]; +static int update_palette; + +static void +sdl_update_palette (const byte *palette) +{ + SDL_Color colors[256]; + int i; + + for (i = 0; i < 256; ++i) { + colors[i].r = *palette++; + colors[i].g = *palette++; + colors[i].b = *palette++; + } + SDL_SetColors (sdl_screen, colors, 0, 256); +} + +static void +VID_SetPalette (const byte *palette) +{ + if (memcmp (cached_palette, palette, sizeof (cached_palette))) { + memcpy (cached_palette, palette, sizeof (cached_palette)); + update_palette = 1; + } +} + +static void +do_screen_buffer (void) +{ +} + +static void +sdl_set_vid_mode (sw_ctx_t *ctx) +{ + // Initialize display + if (!(sdl_screen = SDL_SetVideoMode (viddef.width, viddef.height, 8, + sdl_flags))) + Sys_Error ("VID: Couldn't set video mode: %s", SDL_GetError ()); + + // now know everything we need to know about the buffer + VGA_width = viddef.width; + VGA_height = viddef.height; + viddef.vid_internal->do_screen_buffer = do_screen_buffer; + VGA_pagebase = viddef.buffer = sdl_screen->pixels; + VGA_rowbytes = viddef.rowbytes = sdl_screen->pitch; + viddef.conbuffer = viddef.buffer; + viddef.conrowbytes = viddef.rowbytes; + viddef.direct = 0; + + VID_InitBuffers (); // allocate z buffer and surface cache +} + +static void +sdl_sw_update (vrect_t *rects) +{ + static SDL_Rect *sdlrects; + static int num_sdlrects; + int i, n; + vrect_t *rect; + + if (update_palette) { + update_palette = 0; + sdl_update_palette (cached_palette); + } + // Two-pass system, since Quake doesn't do it the SDL way... + + // First, count the number of rectangles + n = 0; + for (rect = rects; rect; rect = rect->next) + ++n; + + if (n > num_sdlrects) { + num_sdlrects = n; + sdlrects = realloc (sdlrects, n * sizeof (SDL_Rect)); + if (!sdlrects) + Sys_Error ("Out of memory!"); + } + + // Second, copy them to SDL rectangles and update + i = 0; + for (rect = rects; rect; rect = rect->next) { + sdlrects[i].x = rect->x; + sdlrects[i].y = rect->y; + sdlrects[i].w = rect->width; + sdlrects[i].h = rect->height; + ++i; + } + SDL_UpdateRects (sdl_screen, n, sdlrects); +} + +sw_ctx_t * +SDL_SW_Context (void) +{ + sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); + ctx->set_palette = VID_SetPalette; + ctx->create_context = sdl_set_vid_mode; + ctx->update = sdl_sw_update; + return ctx; +} + +void +SDL_SW_Init_Cvars () +{ +} diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index bc4b4b6dc..946824547 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -44,21 +44,10 @@ # include #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include -#include #ifdef HAVE_VIDMODE # include @@ -67,7 +56,6 @@ #include "QF/cmd.h" #include "QF/console.h" #include "QF/cvar.h" -#include "QF/qargs.h" #include "QF/qendian.h" #include "QF/screen.h" #include "QF/sys.h" @@ -80,339 +68,9 @@ #include "vid_internal.h" static vid_internal_t vid_internal; -int XShmGetEventBase (Display *x); // for broken X11 headers - -static GC x_gc; - -static qboolean doShm; -static XShmSegmentInfo x_shminfo[2]; - -static int current_framebuffer; -static XImage *x_framebuffer[2] = { 0, 0 }; int VID_options_items = 1; -static byte current_palette[768]; - -typedef unsigned char PIXEL8; -typedef unsigned short PIXEL16; -typedef unsigned int PIXEL24; - -static PIXEL16 st2d_8to16table[256]; -static PIXEL24 st2d_8to24table[256]; -static int shiftmask_fl = 0; -static long r_shift, g_shift, b_shift; -static unsigned long r_mask, g_mask, b_mask; - -#define GLX_RGBA 4 // true if RGBA mode -#define GLX_DOUBLEBUFFER 5 // double buffering supported -#define GLX_RED_SIZE 8 // number of red component bits -#define GLX_GREEN_SIZE 9 // number of green component bits -#define GLX_BLUE_SIZE 10 // number of blue component bits -#define GLX_DEPTH_SIZE 12 // number of depth bits - -// GLXContext is a pointer to opaque data -typedef struct __GLXcontextRec *GLXContext; -typedef XID GLXDrawable; - -// Define GLAPIENTRY to a useful value -#ifndef GLAPIENTRY -# ifdef _WIN32 -# include -# define GLAPIENTRY WINAPI -# undef LoadImage -# else -# ifdef APIENTRY -# define GLAPIENTRY APIENTRY -# else -# define GLAPIENTRY -# endif -# endif -#endif -static GLXContext ctx = NULL; -static void *libgl_handle; -static void (*qfglXSwapBuffers) (Display *dpy, GLXDrawable drawable); -static XVisualInfo* (*qfglXChooseVisual) (Display *dpy, int screen, - int *attribList); -static GLXContext (*qfglXCreateContext) (Display *dpy, XVisualInfo *vis, - GLXContext shareList, Bool direct); -static Bool (*qfglXMakeCurrent) (Display *dpy, GLXDrawable drawable, - GLXContext ctx); -static void (GLAPIENTRY *qfglFinish) (void); -static void *(*glGetProcAddress) (const char *symbol) = NULL; -static int use_gl_procaddress = 0; -static cvar_t *gl_driver; - -static void (*choose_visual) (void); -static void (*create_context) (void); - -static void * -QFGL_GetProcAddress (void *handle, const char *name) -{ - void *glfunc = NULL; - - if (use_gl_procaddress && glGetProcAddress) - glfunc = glGetProcAddress (name); - if (!glfunc) - glfunc = dlsym (handle, name); - return glfunc; -} - -static void * -QFGL_ProcAddress (const char *name, qboolean crit) -{ - void *glfunc = NULL; - - Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); - - glfunc = QFGL_GetProcAddress (libgl_handle, name); - if (glfunc) { - Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); - return glfunc; - } - Sys_MaskPrintf (SYS_VID, "not found\n"); - - if (crit) { - if (strncmp ("fxMesa", name, 6) == 0) { - Sys_Printf ("This target requires a special version of Mesa with " - "support for Glide and SVGAlib.\n"); - Sys_Printf ("If you are in X, try using a GLX or SGL target.\n"); - } - Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", - name); - } - return NULL; -} - -static void -glx_choose_visual (void) -{ - int attrib[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, - GLX_DEPTH_SIZE, 1, - None - }; - - x_visinfo = qfglXChooseVisual (x_disp, x_screen, attrib); - if (!x_visinfo) { - Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth visual"); - } - x_vis = x_visinfo->visual; -} - -static void -glx_create_context (void) -{ - XSync (x_disp, 0); - ctx = qfglXCreateContext (x_disp, x_visinfo, NULL, True); - qfglXMakeCurrent (x_disp, x_win, ctx); - viddef.vid_internal->init_gl (); -} - -static void -glx_end_rendering (void) -{ - qfglFinish (); - qfglXSwapBuffers (x_disp, x_win); -} - -static void -glx_load_gl (void) -{ - int flags = RTLD_NOW; - - choose_visual = glx_choose_visual; - create_context = glx_create_context; - - viddef.vid_internal->get_proc_address = QFGL_ProcAddress; - viddef.vid_internal->end_rendering = glx_end_rendering; - -#ifdef RTLD_GLOBAL - flags |= RTLD_GLOBAL; -#endif - if (!(libgl_handle = dlopen (gl_driver->string, flags))) { - Sys_Error ("Couldn't load OpenGL library %s: %s", gl_driver->string, - dlerror ()); - } - glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddress"); - if (!glGetProcAddress) - glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddressARB"); - - qfglXSwapBuffers = QFGL_ProcAddress ("glXSwapBuffers", true); - qfglXChooseVisual = QFGL_ProcAddress ("glXChooseVisual", true); - qfglXCreateContext = QFGL_ProcAddress ("glXCreateContext", true); - qfglXMakeCurrent = QFGL_ProcAddress ("glXMakeCurrent", true); - - use_gl_procaddress = 1; - - qfglFinish = QFGL_ProcAddress ("glFinish", true); -} - -static void -shiftmask_init (void) -{ - unsigned long long x; - - r_mask = x_vis->red_mask; - g_mask = x_vis->green_mask; - b_mask = x_vis->blue_mask; - - for (r_shift = -8, x = 1; x < r_mask; x <<= 1) - r_shift++; - for (g_shift = -8, x = 1; x < g_mask; x <<= 1) - g_shift++; - for (b_shift = -8, x = 1; x < b_mask; x <<= 1) - b_shift++; - shiftmask_fl = 1; -} - -static PIXEL16 -xlib_rgb16 (int r, int g, int b) -{ - PIXEL16 p = 0; - - if (!shiftmask_fl) - shiftmask_init (); - - if (r_shift > 0) { - p = (r << (r_shift)) & r_mask; - } else { - if (r_shift < 0) { - p = (r >> (-r_shift)) & r_mask; - } else { - p |= (r & r_mask); - } - } - - if (g_shift > 0) { - p |= (g << (g_shift)) & g_mask; - } else { - if (g_shift < 0) { - p |= (g >> (-g_shift)) & g_mask; - } else { - p |= (g & g_mask); - } - } - - if (b_shift > 0) { - p |= (b << (b_shift)) & b_mask; - } else { - if (b_shift < 0) { - p |= (b >> (-b_shift)) & b_mask; - } else { - p |= (b & b_mask); - } - } - - return p; -} - -static PIXEL24 -xlib_rgb24 (int r, int g, int b) -{ - PIXEL24 p = 0; - - if (!shiftmask_fl) - shiftmask_init (); - - if (r_shift > 0) { - p = (r << (r_shift)) & r_mask; - } else { - if (r_shift < 0) { - p = (r >> (-r_shift)) & r_mask; - } else { - p |= (r & r_mask); - } - } - - if (g_shift > 0) { - p |= (g << (g_shift)) & g_mask; - } else { - if (g_shift < 0) { - p |= (g >> (-g_shift)) & g_mask; - } else { - p |= (g & g_mask); - } - } - - if (b_shift > 0) { - p |= (b << (b_shift)) & b_mask; - } else { - if (b_shift < 0) { - p |= (b >> (-b_shift)) & b_mask; - } else { - p |= (b & b_mask); - } - } - - return p; -} - -static void -st2_fixup (XImage *framebuf, int x, int y, int width, int height) -{ - int xi, yi; - unsigned char *src; - PIXEL16 *dest; - - if (x < 0 || y < 0) - return; - - for (yi = y; yi < (y + height); yi++) { - src = &((byte *)viddef.buffer)[yi * viddef.width]; - dest = (PIXEL16 *) &framebuf->data[yi * framebuf->bytes_per_line]; - for (xi = x; xi < x + width; xi++) { - dest[xi] = st2d_8to16table[src[xi]]; - } - } -} - -static void -st3_fixup (XImage * framebuf, int x, int y, int width, int height) -{ - int yi; - unsigned char *src; - PIXEL24 *dest; - register int count, n; - - if (x < 0 || y < 0) - return; - - for (yi = y; yi < (y + height); yi++) { - src = &((byte *)viddef.buffer)[yi * viddef.width + x]; - dest = (PIXEL24 *) &framebuf->data[yi * framebuf->bytes_per_line + x]; - - // Duff's Device - count = width; - n = (count + 7) / 8; - - switch (count % 8) { - case 0: - do { - *dest++ = st2d_8to24table[*src++]; - case 7: - *dest++ = st2d_8to24table[*src++]; - case 6: - *dest++ = st2d_8to24table[*src++]; - case 5: - *dest++ = st2d_8to24table[*src++]; - case 4: - *dest++ = st2d_8to24table[*src++]; - case 3: - *dest++ = st2d_8to24table[*src++]; - case 2: - *dest++ = st2d_8to24table[*src++]; - case 1: - *dest++ = st2d_8to24table[*src++]; - } while (--n > 0); - } - } -} - void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { @@ -425,240 +83,6 @@ D_EndDirectRect (int x, int y, int width, int height) // direct drawing of the "accessing disk" icon isn't supported } -static void -ResetFrameBuffer (void) -{ - int mem, pwidth; - char *buf; - - if (x_framebuffer[0]) { - XDestroyImage (x_framebuffer[0]); - } - - pwidth = x_visinfo->depth / 8; - - if (pwidth == 3) - pwidth = 4; - mem = ((viddef.width * pwidth + 7) & ~7) * viddef.height; - buf = malloc (mem); - SYS_CHECKMEM (buf); - - // allocate new screen buffer - x_framebuffer[0] = XCreateImage (x_disp, x_vis, x_visinfo->depth, - ZPixmap, 0, buf, viddef.width, - viddef.height, 32, 0); - - if (!x_framebuffer[0]) { - Sys_Error ("VID: XCreateImage failed"); - } -} - -static void -ResetSharedFrameBuffers (void) -{ - int size; - int key; - int minsize = getpagesize (); - int frm; - - for (frm = 0; frm < 2; frm++) { - - // free up old frame buffer memory - if (x_framebuffer[frm]) { - XShmDetach (x_disp, &x_shminfo[frm]); - free (x_framebuffer[frm]); - shmdt (x_shminfo[frm].shmaddr); - } - // create the image - x_framebuffer[frm] = XShmCreateImage (x_disp, x_vis, x_visinfo->depth, - ZPixmap, 0, &x_shminfo[frm], - viddef.width, viddef.height); - - // grab shared memory - size = x_framebuffer[frm]->bytes_per_line * x_framebuffer[frm]->height; - - if (size < minsize) - Sys_Error ("VID: Window must use at least %d bytes", minsize); - - key = random (); - x_shminfo[frm].shmid = shmget ((key_t) key, size, IPC_CREAT | 0777); - if (x_shminfo[frm].shmid == -1) - Sys_Error ("VID: Could not get any shared memory (%s)", - strerror (errno)); - - // attach to the shared memory segment - x_shminfo[frm].shmaddr = (void *) shmat (x_shminfo[frm].shmid, 0, 0); - - Sys_MaskPrintf (SYS_VID, "VID: shared memory id=%d, addr=0x%lx\n", - x_shminfo[frm].shmid, (long) x_shminfo[frm].shmaddr); - - x_framebuffer[frm]->data = x_shminfo[frm].shmaddr; - - // get the X server to attach to it - if (!XShmAttach (x_disp, &x_shminfo[frm])) - Sys_Error ("VID: XShmAttach() failed"); - XSync (x_disp, 0); - shmctl (x_shminfo[frm].shmid, IPC_RMID, 0); - - } -} - -static void -x11_init_buffers (void) -{ - if (doShm) - ResetSharedFrameBuffers (); - else - ResetFrameBuffer (); - - current_framebuffer = 0; - - viddef.direct = 0; - viddef.rowbytes = viddef.width; - if (x_visinfo->depth != 8) { - if (viddef.buffer) - free (viddef.buffer); - viddef.buffer = calloc (viddef.width, viddef.height); - if (!viddef.buffer) - Sys_Error ("Not enough memory for video mode"); - } else { - viddef.buffer = x_framebuffer[current_framebuffer]->data; - } - viddef.conbuffer = viddef.buffer; - - viddef.conrowbytes = viddef.rowbytes; -} - -static void -x11_choose_visual (void) -{ - int pnum, i; - XVisualInfo template; - int num_visuals; - int template_mask; - - // specify a visual id - if ((pnum = COM_CheckParm ("-visualid"))) { - if (pnum >= com_argc - 1) - Sys_Error ("VID: -visualid "); - template.visualid = atoi (com_argv[pnum + 1]); - template_mask = VisualIDMask; - } else { // If not specified, use default - // visual - template.visualid = - XVisualIDFromVisual (XDefaultVisual (x_disp, x_screen)); - template_mask = VisualIDMask; - } - - // pick a visual -- warn if more than one was available - x_visinfo = XGetVisualInfo (x_disp, template_mask, &template, - &num_visuals); - - if (x_visinfo->depth == 8 && x_visinfo->class == PseudoColor) - x_cmap = XCreateColormap (x_disp, x_win, x_vis, AllocAll); - x_vis = x_visinfo->visual; - - if (num_visuals > 1) { - Sys_MaskPrintf (SYS_VID, - "Found more than one visual id at depth %d:\n", - template.depth); - for (i = 0; i < num_visuals; i++) - Sys_MaskPrintf (SYS_VID, " -visualid %d\n", - (int) x_visinfo[i].visualid); - } else { - if (num_visuals == 0) { - if (template_mask == VisualIDMask) { - Sys_Error ("VID: Bad visual ID %ld", template.visualid); - } else { - Sys_Error ("VID: No visuals at depth %d", template.depth); - } - } - } - - Sys_MaskPrintf (SYS_VID, "Using visualid %d:\n", - (int) x_visinfo->visualid); - Sys_MaskPrintf (SYS_VID, " class %d\n", x_visinfo->class); - Sys_MaskPrintf (SYS_VID, " screen %d\n", x_visinfo->screen); - Sys_MaskPrintf (SYS_VID, " depth %d\n", x_visinfo->depth); - Sys_MaskPrintf (SYS_VID, " red_mask 0x%x\n", - (int) x_visinfo->red_mask); - Sys_MaskPrintf (SYS_VID, " green_mask 0x%x\n", - (int) x_visinfo->green_mask); - Sys_MaskPrintf (SYS_VID, " blue_mask 0x%x\n", - (int) x_visinfo->blue_mask); - Sys_MaskPrintf (SYS_VID, " colormap_size %d\n", - x_visinfo->colormap_size); - Sys_MaskPrintf (SYS_VID, " bits_per_rgb %d\n", - x_visinfo->bits_per_rgb); -} - -static void -x11_create_context (void) -{ - // create the GC - { - XGCValues xgcvalues; - int valuemask = GCGraphicsExposures; - - xgcvalues.graphics_exposures = False; - x_gc = XCreateGC (x_disp, x_win, valuemask, &xgcvalues); - } - - // even if MITSHM is available, make sure it's a local connection - if (XShmQueryExtension (x_disp)) { - char *displayname; - char *d; - - doShm = true; - - if ((displayname = XDisplayName (NULL))) { - if ((d = strchr (displayname, ':'))) - *d = '\0'; - - if (!(!strcasecmp (displayname, "unix") || !*displayname)) - doShm = false; - } - } - - if (doShm) { - x_shmeventtype = XShmGetEventBase (x_disp) + ShmCompletion; - } - - viddef.vid_internal->do_screen_buffer = x11_init_buffers; - VID_InitBuffers (); - -// XSynchronize (x_disp, False); -// X11_AddEvent (x_shmeventtype, event_shm); -} - -static void -VID_SetPalette (const byte *palette) -{ - int i; - XColor colors[256]; - - for (i = 0; i < 256; i++) { - st2d_8to16table[i] = xlib_rgb16 (palette[i * 3], palette[i * 3 + 1], - palette[i * 3 + 2]); - st2d_8to24table[i] = xlib_rgb24 (palette[i * 3], palette[i * 3 + 1], - palette[i * 3 + 2]); - } - - if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8) { - if (palette != current_palette) { - memcpy (current_palette, palette, 768); - } - for (i = 0; i < 256; i++) { - colors[i].pixel = i; - colors[i].flags = DoRed | DoGreen | DoBlue; - colors[i].red = palette[(i * 3)] << 8; - colors[i].green = palette[(i * 3) + 1] << 8; - colors[i].blue = palette[(i * 3) + 2] << 8; - } - XStoreColors (x_disp, x_cmap, colors, 256); - } -} - /* Set up color translation tables and the window. Takes a 256-color 8-bit palette. Palette data will go away after the call, so copy it if you'll @@ -667,11 +91,11 @@ VID_SetPalette (const byte *palette) void VID_Init (byte *palette, byte *colormap) { - vid_internal.load_gl = glx_load_gl; - vid_internal.set_palette = VID_SetPalette; - - choose_visual = x11_choose_visual; - create_context = x11_create_context; + vid_internal.gl_context = X11_GL_Context; + vid_internal.sw_context = X11_SW_Context; +#ifdef HAVE_VULKAN + vid_internal.vulkan_context = X11_Vulkan_Context; +#endif R_LoadModule (&vid_internal); @@ -683,11 +107,11 @@ VID_Init (byte *palette, byte *colormap) VID_GetWindowSize (320, 200); X11_OpenDisplay (); - choose_visual (); + vid_internal.choose_visual (); X11_SetVidMode (viddef.width, viddef.height); X11_CreateWindow (viddef.width, viddef.height); X11_CreateNullCursor (); // hide mouse pointer - create_context (); + vid_internal.create_context (); VID_InitGamma (palette); viddef.vid_internal->set_palette (viddef.palette); @@ -703,8 +127,10 @@ void VID_Init_Cvars () { X11_Init_Cvars (); - gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, - "The OpenGL library to use. (path optional)"); +#ifdef HAVE_VULKAN + X11_Vulkan_Init_Cvars (); +#endif + X11_GL_Init_Cvars (); } /* @@ -719,17 +145,13 @@ VID_Shutdown (void) X11_CloseDisplay (); } +#if 0 static int config_notify = 0; static int config_notify_width; static int config_notify_height; -/* - VID_Update - - Flush the given rectangles from the view buffer to the screen. -*/ -void -VID_Update (vrect_t *rects) +static void +update () { /* If the window changes dimension, skip this frame. */ if (config_notify) { @@ -744,43 +166,8 @@ VID_Update (vrect_t *rects) Con_CheckResize (); return; } - - while (rects) { - switch (x_visinfo->depth) { - case 16: - st2_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - break; - case 24: - st3_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - break; - } - if (doShm) { - if (!XShmPutImage (x_disp, x_win, x_gc, - x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height, True)) { - Sys_Error ("VID_Update: XShmPutImage failed"); - } - oktodraw = false; - while (!oktodraw) - X11_ProcessEvent (); - rects = rects->next; - - current_framebuffer = !current_framebuffer; - } else { - if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height)) { - Sys_Error ("VID_Update: XPutImage failed"); - } - rects = rects->next; - } - } - XSync (x_disp, False); - r_data->scr_fullupdate = 0; } +#endif void VID_LockBuffer (void) diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c new file mode 100644 index 000000000..28b2f3294 --- /dev/null +++ b/libs/video/targets/vid_x11_gl.c @@ -0,0 +1,209 @@ +/* + vid_x11_gl.c + + GLX X11 video driver + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 contributors of the QuakeForge project + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include + +#include "QF/cvar.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_x11.h" +#include "r_internal.h" +#include "vid_internal.h" +#include "vid_gl.h" + +#define GLX_RGBA 4 // true if RGBA mode +#define GLX_DOUBLEBUFFER 5 // double buffering supported +#define GLX_RED_SIZE 8 // number of red component bits +#define GLX_GREEN_SIZE 9 // number of green component bits +#define GLX_BLUE_SIZE 10 // number of blue component bits +#define GLX_DEPTH_SIZE 12 // number of depth bits + +typedef XID GLXDrawable; + +// Define GLAPIENTRY to a useful value +#ifndef GLAPIENTRY +# ifdef _WIN32 +# include +# define GLAPIENTRY WINAPI +# undef LoadImage +# else +# ifdef APIENTRY +# define GLAPIENTRY APIENTRY +# else +# define GLAPIENTRY +# endif +# endif +#endif +static void *libgl_handle; +static void (*qfglXSwapBuffers) (Display *dpy, GLXDrawable drawable); +static XVisualInfo* (*qfglXChooseVisual) (Display *dpy, int screen, + int *attribList); +static GLXContext (*qfglXCreateContext) (Display *dpy, XVisualInfo *vis, + GLXContext shareList, Bool direct); +static Bool (*qfglXMakeCurrent) (Display *dpy, GLXDrawable drawable, + GLXContext ctx); +static void (GLAPIENTRY *qfglFinish) (void); +static void *(*glGetProcAddress) (const char *symbol) = NULL; +static int use_gl_procaddress = 0; + +static cvar_t *gl_driver; + +static void * +QFGL_GetProcAddress (void *handle, const char *name) +{ + void *glfunc = NULL; + + if (use_gl_procaddress && glGetProcAddress) + glfunc = glGetProcAddress (name); + if (!glfunc) + glfunc = dlsym (handle, name); + return glfunc; +} + +static void * +QFGL_ProcAddress (const char *name, qboolean crit) +{ + void *glfunc = NULL; + + Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); + + glfunc = QFGL_GetProcAddress (libgl_handle, name); + if (glfunc) { + Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); + return glfunc; + } + Sys_MaskPrintf (SYS_VID, "not found\n"); + + if (crit) { + if (strncmp ("fxMesa", name, 6) == 0) { + Sys_Printf ("This target requires a special version of Mesa with " + "support for Glide and SVGAlib.\n"); + Sys_Printf ("If you are in X, try using a GLX or SGL target.\n"); + } + Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", + name); + } + return NULL; +} + +static void +glx_choose_visual (gl_ctx_t *ctx) +{ + int attrib[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None + }; + + x_visinfo = qfglXChooseVisual (x_disp, x_screen, attrib); + if (!x_visinfo) { + Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth visual"); + } + x_vis = x_visinfo->visual; +} + +static void +glx_create_context (gl_ctx_t *ctx) +{ + XSync (x_disp, 0); + ctx->context = qfglXCreateContext (x_disp, x_visinfo, NULL, True); + qfglXMakeCurrent (x_disp, x_win, ctx->context); + ctx->init_gl (); +} + +static void +glx_end_rendering (void) +{ + qfglFinish (); + qfglXSwapBuffers (x_disp, x_win); +} + +static void +glx_load_gl (void) +{ + libgl_handle = dlopen (gl_driver->string, RTLD_NOW); + if (!libgl_handle) { + Sys_Error ("Couldn't load OpenGL library %s: %s", gl_driver->string, + dlerror ()); + } + glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddress"); + if (!glGetProcAddress) + glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddressARB"); + + qfglXSwapBuffers = QFGL_ProcAddress ("glXSwapBuffers", true); + qfglXChooseVisual = QFGL_ProcAddress ("glXChooseVisual", true); + qfglXCreateContext = QFGL_ProcAddress ("glXCreateContext", true); + qfglXMakeCurrent = QFGL_ProcAddress ("glXMakeCurrent", true); + + use_gl_procaddress = 1; + + qfglFinish = QFGL_ProcAddress ("glFinish", true); +} + +gl_ctx_t * +X11_GL_Context (void) +{ + gl_ctx_t *ctx = calloc (1, sizeof (gl_ctx_t)); + ctx->load_gl = glx_load_gl; + ctx->choose_visual = glx_choose_visual; + ctx->create_context = glx_create_context; + ctx->get_proc_address = QFGL_ProcAddress; + ctx->end_rendering = glx_end_rendering; + return ctx; +} + +void +X11_GL_Init_Cvars (void) +{ + gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, + "The OpenGL library to use. (path optional)"); +} diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c new file mode 100644 index 000000000..9c734a635 --- /dev/null +++ b/libs/video/targets/vid_x11_sw.c @@ -0,0 +1,542 @@ +/* + vid_x11_sw.c + + Software X11 video driver (8/32 bit) + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 contributors of the QuakeForge project + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "QF/cvar.h" +#include "QF/qargs.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_x11.h" +#include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" + +int XShmGetEventBase (Display *x); // for broken X11 headers + +static GC x_gc; + +static qboolean doShm; +static XShmSegmentInfo x_shminfo[2]; + +static int current_framebuffer; +static XImage *x_framebuffer[2] = { 0, 0 }; + +typedef unsigned char PIXEL8; +typedef unsigned short PIXEL16; +typedef unsigned int PIXEL24; + +static PIXEL16 st2d_8to16table[256]; +static PIXEL24 st2d_8to24table[256]; + +static byte current_palette[768]; +static int shiftmask_fl = 0; +static long r_shift, g_shift, b_shift; +static unsigned long r_mask, g_mask, b_mask; + +static void +shiftmask_init (void) +{ + unsigned long long x; + + r_mask = x_vis->red_mask; + g_mask = x_vis->green_mask; + b_mask = x_vis->blue_mask; + + for (r_shift = -8, x = 1; x < r_mask; x <<= 1) + r_shift++; + for (g_shift = -8, x = 1; x < g_mask; x <<= 1) + g_shift++; + for (b_shift = -8, x = 1; x < b_mask; x <<= 1) + b_shift++; + shiftmask_fl = 1; +} + +static PIXEL16 +xlib_rgb16 (int r, int g, int b) +{ + PIXEL16 p = 0; + + if (!shiftmask_fl) + shiftmask_init (); + + if (r_shift > 0) { + p = (r << (r_shift)) & r_mask; + } else { + if (r_shift < 0) { + p = (r >> (-r_shift)) & r_mask; + } else { + p |= (r & r_mask); + } + } + + if (g_shift > 0) { + p |= (g << (g_shift)) & g_mask; + } else { + if (g_shift < 0) { + p |= (g >> (-g_shift)) & g_mask; + } else { + p |= (g & g_mask); + } + } + + if (b_shift > 0) { + p |= (b << (b_shift)) & b_mask; + } else { + if (b_shift < 0) { + p |= (b >> (-b_shift)) & b_mask; + } else { + p |= (b & b_mask); + } + } + + return p; +} + +static PIXEL24 +xlib_rgb24 (int r, int g, int b) +{ + PIXEL24 p = 0; + + if (!shiftmask_fl) + shiftmask_init (); + + if (r_shift > 0) { + p = (r << (r_shift)) & r_mask; + } else { + if (r_shift < 0) { + p = (r >> (-r_shift)) & r_mask; + } else { + p |= (r & r_mask); + } + } + + if (g_shift > 0) { + p |= (g << (g_shift)) & g_mask; + } else { + if (g_shift < 0) { + p |= (g >> (-g_shift)) & g_mask; + } else { + p |= (g & g_mask); + } + } + + if (b_shift > 0) { + p |= (b << (b_shift)) & b_mask; + } else { + if (b_shift < 0) { + p |= (b >> (-b_shift)) & b_mask; + } else { + p |= (b & b_mask); + } + } + + return p; +} + +static void +VID_SetPalette (const byte *palette) +{ + int i; + XColor colors[256]; + + for (i = 0; i < 256; i++) { + st2d_8to16table[i] = xlib_rgb16 (palette[i * 3], palette[i * 3 + 1], + palette[i * 3 + 2]); + st2d_8to24table[i] = xlib_rgb24 (palette[i * 3], palette[i * 3 + 1], + palette[i * 3 + 2]); + } + + if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8) { + if (palette != current_palette) { + memcpy (current_palette, palette, 768); + } + for (i = 0; i < 256; i++) { + colors[i].pixel = i; + colors[i].flags = DoRed | DoGreen | DoBlue; + colors[i].red = palette[(i * 3)] << 8; + colors[i].green = palette[(i * 3) + 1] << 8; + colors[i].blue = palette[(i * 3) + 2] << 8; + } + XStoreColors (x_disp, x_cmap, colors, 256); + } +} + +static void +st2_fixup (XImage *framebuf, int x, int y, int width, int height) +{ + int xi, yi; + unsigned char *src; + PIXEL16 *dest; + + if (x < 0 || y < 0) + return; + + for (yi = y; yi < (y + height); yi++) { + src = &((byte *)viddef.buffer)[yi * viddef.width]; + dest = (PIXEL16 *) &framebuf->data[yi * framebuf->bytes_per_line]; + for (xi = x; xi < x + width; xi++) { + dest[xi] = st2d_8to16table[src[xi]]; + } + } +} + +static void +st3_fixup (XImage * framebuf, int x, int y, int width, int height) +{ + int yi; + unsigned char *src; + PIXEL24 *dest; + register int count, n; + + if (x < 0 || y < 0) + return; + + for (yi = y; yi < (y + height); yi++) { + src = &((byte *)viddef.buffer)[yi * viddef.width + x]; + dest = (PIXEL24 *) &framebuf->data[yi * framebuf->bytes_per_line + x]; + + // Duff's Device + count = width; + n = (count + 7) / 8; + + switch (count % 8) { + case 0: + do { + *dest++ = st2d_8to24table[*src++]; + case 7: + *dest++ = st2d_8to24table[*src++]; + case 6: + *dest++ = st2d_8to24table[*src++]; + case 5: + *dest++ = st2d_8to24table[*src++]; + case 4: + *dest++ = st2d_8to24table[*src++]; + case 3: + *dest++ = st2d_8to24table[*src++]; + case 2: + *dest++ = st2d_8to24table[*src++]; + case 1: + *dest++ = st2d_8to24table[*src++]; + } while (--n > 0); + } + } +} + +/* + Flush the given rectangles from the view buffer to the screen. +*/ +static void +x11_sw_update (vrect_t *rects) +{ + while (rects) { + switch (x_visinfo->depth) { + case 16: + st2_fixup (x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + break; + case 24: + st3_fixup (x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + break; + } + if (doShm) { + if (!XShmPutImage (x_disp, x_win, x_gc, + x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height, True)) { + Sys_Error ("VID_Update: XShmPutImage failed"); + } + oktodraw = false; + while (!oktodraw) + X11_ProcessEvent (); + rects = rects->next; + + current_framebuffer = !current_framebuffer; + } else { + if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height)) { + Sys_Error ("VID_Update: XPutImage failed"); + } + rects = rects->next; + } + } + XSync (x_disp, False); + r_data->scr_fullupdate = 0; +} + +static void +x11_choose_visual (sw_ctx_t *ctx) +{ + int pnum, i; + XVisualInfo template; + int num_visuals; + int template_mask; + + // specify a visual id + if ((pnum = COM_CheckParm ("-visualid"))) { + if (pnum >= com_argc - 1) + Sys_Error ("VID: -visualid "); + template.visualid = atoi (com_argv[pnum + 1]); + template_mask = VisualIDMask; + } else { // If not specified, use default + // visual + template.visualid = + XVisualIDFromVisual (XDefaultVisual (x_disp, x_screen)); + template_mask = VisualIDMask; + } + + // pick a visual -- warn if more than one was available + x_visinfo = XGetVisualInfo (x_disp, template_mask, &template, + &num_visuals); + + if (x_visinfo->depth == 8 && x_visinfo->class == PseudoColor) + x_cmap = XCreateColormap (x_disp, x_win, x_vis, AllocAll); + x_vis = x_visinfo->visual; + + if (num_visuals > 1) { + Sys_MaskPrintf (SYS_VID, + "Found more than one visual id at depth %d:\n", + template.depth); + for (i = 0; i < num_visuals; i++) + Sys_MaskPrintf (SYS_VID, " -visualid %d\n", + (int) x_visinfo[i].visualid); + } else { + if (num_visuals == 0) { + if (template_mask == VisualIDMask) { + Sys_Error ("VID: Bad visual ID %ld", template.visualid); + } else { + Sys_Error ("VID: No visuals at depth %d", template.depth); + } + } + } + + Sys_MaskPrintf (SYS_VID, "Using visualid %d:\n", + (int) x_visinfo->visualid); + Sys_MaskPrintf (SYS_VID, " class %d\n", x_visinfo->class); + Sys_MaskPrintf (SYS_VID, " screen %d\n", x_visinfo->screen); + Sys_MaskPrintf (SYS_VID, " depth %d\n", x_visinfo->depth); + Sys_MaskPrintf (SYS_VID, " red_mask 0x%x\n", + (int) x_visinfo->red_mask); + Sys_MaskPrintf (SYS_VID, " green_mask 0x%x\n", + (int) x_visinfo->green_mask); + Sys_MaskPrintf (SYS_VID, " blue_mask 0x%x\n", + (int) x_visinfo->blue_mask); + Sys_MaskPrintf (SYS_VID, " colormap_size %d\n", + x_visinfo->colormap_size); + Sys_MaskPrintf (SYS_VID, " bits_per_rgb %d\n", + x_visinfo->bits_per_rgb); +} + +static void +ResetFrameBuffer (void) +{ + int mem, pwidth; + char *buf; + + if (x_framebuffer[0]) { + XDestroyImage (x_framebuffer[0]); + } + + pwidth = x_visinfo->depth / 8; + + if (pwidth == 3) + pwidth = 4; + mem = ((viddef.width * pwidth + 7) & ~7) * viddef.height; + buf = malloc (mem); + SYS_CHECKMEM (buf); + + // allocate new screen buffer + x_framebuffer[0] = XCreateImage (x_disp, x_vis, x_visinfo->depth, + ZPixmap, 0, buf, viddef.width, + viddef.height, 32, 0); + + if (!x_framebuffer[0]) { + Sys_Error ("VID: XCreateImage failed"); + } +} + +static void +ResetSharedFrameBuffers (void) +{ + int size; + int key; + int minsize = getpagesize (); + int frm; + + for (frm = 0; frm < 2; frm++) { + + // free up old frame buffer memory + if (x_framebuffer[frm]) { + XShmDetach (x_disp, &x_shminfo[frm]); + free (x_framebuffer[frm]); + shmdt (x_shminfo[frm].shmaddr); + } + // create the image + x_framebuffer[frm] = XShmCreateImage (x_disp, x_vis, x_visinfo->depth, + ZPixmap, 0, &x_shminfo[frm], + viddef.width, viddef.height); + + // grab shared memory + size = x_framebuffer[frm]->bytes_per_line * x_framebuffer[frm]->height; + + if (size < minsize) + Sys_Error ("VID: Window must use at least %d bytes", minsize); + + key = random (); + x_shminfo[frm].shmid = shmget ((key_t) key, size, IPC_CREAT | 0777); + if (x_shminfo[frm].shmid == -1) + Sys_Error ("VID: Could not get any shared memory (%s)", + strerror (errno)); + + // attach to the shared memory segment + x_shminfo[frm].shmaddr = (void *) shmat (x_shminfo[frm].shmid, 0, 0); + + Sys_MaskPrintf (SYS_VID, "VID: shared memory id=%d, addr=0x%lx\n", + x_shminfo[frm].shmid, (long) x_shminfo[frm].shmaddr); + + x_framebuffer[frm]->data = x_shminfo[frm].shmaddr; + + // get the X server to attach to it + if (!XShmAttach (x_disp, &x_shminfo[frm])) + Sys_Error ("VID: XShmAttach() failed"); + XSync (x_disp, 0); + shmctl (x_shminfo[frm].shmid, IPC_RMID, 0); + + } +} + +static void +x11_init_buffers (void) +{ + if (doShm) + ResetSharedFrameBuffers (); + else + ResetFrameBuffer (); + + current_framebuffer = 0; + + viddef.direct = 0; + viddef.rowbytes = viddef.width; + if (x_visinfo->depth != 8) { + if (viddef.buffer) + free (viddef.buffer); + viddef.buffer = calloc (viddef.width, viddef.height); + if (!viddef.buffer) + Sys_Error ("Not enough memory for video mode"); + } else { + viddef.buffer = x_framebuffer[current_framebuffer]->data; + } + viddef.conbuffer = viddef.buffer; + + viddef.conrowbytes = viddef.rowbytes; +} + +static void +x11_create_context (sw_ctx_t *ctx) +{ + // create the GC + { + XGCValues xgcvalues; + int valuemask = GCGraphicsExposures; + + xgcvalues.graphics_exposures = False; + x_gc = XCreateGC (x_disp, x_win, valuemask, &xgcvalues); + } + + // even if MITSHM is available, make sure it's a local connection + if (XShmQueryExtension (x_disp)) { + char *displayname; + char *d; + + doShm = true; + + if ((displayname = XDisplayName (NULL))) { + if ((d = strchr (displayname, ':'))) + *d = '\0'; + + if (!(!strcasecmp (displayname, "unix") || !*displayname)) + doShm = false; + } + } + + if (doShm) { + x_shmeventtype = XShmGetEventBase (x_disp) + ShmCompletion; + } + + viddef.vid_internal->do_screen_buffer = x11_init_buffers; + VID_InitBuffers (); + +// XSynchronize (x_disp, False); +// X11_AddEvent (x_shmeventtype, event_shm); +} + +sw_ctx_t * +X11_SW_Context (void) +{ + sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); + ctx->set_palette = VID_SetPalette; + ctx->choose_visual = x11_choose_visual; + ctx->create_context = x11_create_context; + ctx->update = x11_sw_update; + return ctx; +} + +void +X11_SW_Init_Cvars (void) +{ +} diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c new file mode 100644 index 000000000..e472c0c0e --- /dev/null +++ b/libs/video/targets/vid_x11_vulkan.c @@ -0,0 +1,169 @@ +/* + vid_x11_vulkan.c + + Vulkan X11 video driver + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 contributors of the QuakeForge project + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#define VK_NO_PROTOTYPES +#define VK_USE_PLATFORM_XLIB_KHR +#include + +#include "QF/cvar.h" +#include "QF/set.h" +#include "QF/sys.h" + +#include "context_x11.h" +#include "vid_internal.h" +#include "vid_vulkan.h" + +static cvar_t *vulkan_library_name; + +typedef struct vulkan_presentation_s { +#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; +#include "QF/Vulkan/funclist.h" + + Display *display; + Window window; + int num_visuals; + XVisualInfo *visinfo; + set_t *usable_visuals; +} vulkan_presentation_t; + +static const char *required_extensions[] = { + VK_KHR_XLIB_SURFACE_EXTENSION_NAME, + 0 +}; + +static void *vulkan_library; + +static void +load_vulkan_library (vulkan_ctx_t *ctx) +{ + vulkan_library = dlopen (vulkan_library_name->string, + RTLD_DEEPBIND | RTLD_NOW); + if (!vulkan_library) { + Sys_Error ("Couldn't load vulkan library %s: %s", + vulkan_library_name->name, dlerror ()); + } + + #define EXPORTED_VULKAN_FUNCTION(name) \ + ctx->name = (PFN_##name) dlsym (vulkan_library, #name); \ + if (!ctx->name) { \ + Sys_Error ("Couldn't find exported vulkan function %s", #name); \ + } + + #define GLOBAL_LEVEL_VULKAN_FUNCTION(name) \ + ctx->name = (PFN_##name) ctx->vkGetInstanceProcAddr (0, #name); \ + if (!ctx->name) { \ + Sys_Error ("Couldn't find global-level function %s", #name); \ + } + + #include "QF/Vulkan/funclist.h" +} + +static void +unload_vulkan_library (vulkan_ctx_t *ctx) +{ + dlclose (vulkan_library); + vulkan_library = 0; +} + +static int +x11_vulkan_get_presentation_support (vulkan_ctx_t *ctx, + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex) +{ + vulkan_presentation_t *pres = ctx->presentation; + + set_empty (pres->usable_visuals); + for (int i = 0; i < pres->num_visuals; i++) { + VisualID visID = pres->visinfo[i].visualid; + + if (pres->vkGetPhysicalDeviceXlibPresentationSupportKHR ( + physicalDevice, queueFamilyIndex, pres->display, visID)) { + set_add (pres->usable_visuals, i); + } + } + return !set_is_empty (pres->usable_visuals); +} + +static VkSurfaceKHR +x11_vulkan_create_surface (vulkan_ctx_t *ctx) +{ + vulkan_presentation_t *pres = ctx->presentation; + VkSurfaceKHR surface; + VkXlibSurfaceCreateInfoKHR createInfo = { + .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, + .flags = 0, + .dpy = pres->display, + .window = pres->window + }; + + if (pres->vkCreateXlibSurfaceKHR (ctx->instance, &createInfo, 0, &surface) + != VK_SUCCESS) { + return 0; + } + return surface; +} + +vulkan_ctx_t * +X11_Vulkan_Context (void) +{ + vulkan_ctx_t *ctx = calloc (1, sizeof (vulkan_ctx_t)); + ctx->load_vulkan = load_vulkan_library; + ctx->unload_vulkan = unload_vulkan_library; + ctx->get_presentation_support = x11_vulkan_get_presentation_support; + ctx->create_surface = x11_vulkan_create_surface; + ctx->required_extensions = required_extensions; + return ctx; +} + +void +X11_Vulkan_Init_Cvars (void) +{ + vulkan_library_name = Cvar_Get ("vulkan_library", "libvulkan.so.1", + CVAR_ROM, 0, + "the name of the vulkan shared library"); +} From e9f1bc7b30b77d41a733f914ffd507524a056c3a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 01:03:26 +0900 Subject: [PATCH 0182/3664] Make vulkan building actually conditional --- config.d/build_control.m4 | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 94a7415af..a4df4a3a4 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -71,7 +71,11 @@ if test "x$HAVE_X" = xyes; then NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA quakeforge-nq-x11.desktop" CL_TARGETS="$CL_TARGETS X11" VID_TARGETS="$VID_TARGETS libQFx11.la" - QF_NEED(vid_render, [sw sw32 gl glsl vulkan]) + if test "$HAVE_VULKAN" = "yes"; then + QF_NEED(vid_render, [sw sw32 gl glsl vulkan]) + else + QF_NEED(vid_render, [sw sw32 gl glsl]) + fi QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -95,7 +99,11 @@ if test "x$HAVE_SDL" = xyes; then NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA quakeforge-nq-sdl.desktop" CL_TARGETS="$CL_TARGETS SDL" VID_TARGETS="$VID_TARGETS libQFsdl.la" - QF_NEED(vid_render, [sw sw32 gl glsl vulkan]) + if test "$HAVE_VULKAN" = "yes"; then + QF_NEED(vid_render, [sw sw32 gl glsl vulkan]) + else + QF_NEED(vid_render, [sw sw32 gl glsl]) + fi QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) From 707bdfc5f24fed2ac8b72c79b9c84ad835afe605 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 09:06:35 +0900 Subject: [PATCH 0183/3664] Get vulkan back to where it was --- include/vid_vulkan.h | 2 -- libs/video/renderer/vid_render_vulkan.c | 18 +++++++++++++++++- libs/video/renderer/vulkan/vulkan_vid_common.c | 12 +++++++----- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 627269cdb..ae83ae397 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -9,7 +9,6 @@ typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); void (*unload_vulkan) (struct vulkan_ctx_s *ctx); - void (*init_vulkan) (void); const char * const *required_extensions; struct vulkan_presentation_s *presentation; @@ -18,7 +17,6 @@ typedef struct vulkan_ctx_s { uint32_t queueFamilyIndex); VkSurfaceKHR (*create_surface) (struct vulkan_ctx_s *ctx); VkInstance instance; - VkPhysicalDevice physicalDevice; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 2a94f31cb..840505e10 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -135,14 +135,30 @@ set_palette (const byte *palette) //an app using the QuakeForge engine) } +static void +vulkan_vid_render_choose_visual (void) +{ + //vulkan_ctx->coose_visual (vulkan_ctx); +} + +static void +vulkan_vid_render_create_context (void) +{ + vulkan_ctx->create_surface (vulkan_ctx); +} + static void vulkan_vid_render_init (void) { vulkan_ctx = vr_data.vid->vid_internal->vulkan_context (); - vulkan_ctx->init_vulkan = Vulkan_Init_Common; vulkan_ctx->load_vulkan (vulkan_ctx); + Vulkan_Init_Common (); + vr_data.vid->vid_internal->set_palette = set_palette; + vr_data.vid->vid_internal->choose_visual = vulkan_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = vulkan_vid_render_create_context; + vr_funcs = &vulkan_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 98a4d3dc3..cfd2a980f 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -165,6 +165,8 @@ create_suitable_device (VulkanInstance_t *instance) return 0; } +int x = 1; + void Vulkan_Init_Common (void) { @@ -176,11 +178,11 @@ Vulkan_Init_Common (void) if (!vulkan_device) { Sys_Error ("no suitable vulkan device found"); } - if (developer->int_val & SYS_VID) { - Sys_Printf ("%p %p\n", vulkan_device->device, vulkan_device->queue); - Vulkan_Shutdown_Common (); - Sys_Quit(); - } + // only for now... + Sys_Printf ("%p %p\n", vulkan_device->device, vulkan_device->queue); + Vulkan_Shutdown_Common (); + if (x) + Sys_Quit(); } void From b3d982bfc3a053e7058cace4e058050ff916c801 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 11:54:23 +0900 Subject: [PATCH 0184/3664] Remove global vulkan_ctx While I can't say that I'm happy with the details of vulkan_ctx_t, I am pretty sure I don't want to be limited to having only one. --- include/QF/Vulkan/init.h | 6 ++-- include/QF/Vulkan/qf_vid.h | 5 +-- include/vid_vulkan.h | 6 ++-- libs/video/renderer/vid_render_vulkan.c | 6 ++-- libs/video/renderer/vulkan/init.c | 34 ++++++++++--------- .../video/renderer/vulkan/vulkan_vid_common.c | 10 +++--- 6 files changed, 36 insertions(+), 31 deletions(-) diff --git a/include/QF/Vulkan/init.h b/include/QF/Vulkan/init.h index 85efb44e1..c964e6c41 100644 --- a/include/QF/Vulkan/init.h +++ b/include/QF/Vulkan/init.h @@ -52,7 +52,7 @@ typedef struct { VkQueueFamilyProperties *queueFamilies; } VulkanPhysDevice_t; -typedef struct { +typedef struct VulkanInstance_s { VkInstance instance; VkDebugUtilsMessengerEXT debug_callback; uint32_t numDevices; @@ -64,7 +64,9 @@ typedef struct { } VulkanInstance_t; void Vulkan_Init_Cvars (void); -VulkanInstance_t *Vulkan_CreateInstance (const char *appName, +struct vulkan_ctx_s; +VulkanInstance_t *Vulkan_CreateInstance (struct vulkan_ctx_s *ctx, + const char *appName, uint32_t appVersion, const char **layers, const char **extensions); diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index d032a075a..8e1825b48 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -30,7 +30,8 @@ #include "QF/Vulkan/cvars.h" -void Vulkan_Init_Common (void); -void Vulkan_Shutdown_Common (void); +struct vulkan_ctx_s; +void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); +void Vulkan_Shutdown_Common (struct vulkan_ctx_s *ctx); #endif // __QF_Vulkan_vid_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index ae83ae397..eea285ae4 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -10,18 +10,18 @@ typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); void (*unload_vulkan) (struct vulkan_ctx_s *ctx); - const char * const *required_extensions; + const char **required_extensions; struct vulkan_presentation_s *presentation; int (*get_presentation_support) (struct vulkan_ctx_s *ctx, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); VkSurfaceKHR (*create_surface) (struct vulkan_ctx_s *ctx); + + struct VulkanInstance_s *vtx; VkInstance instance; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" } vulkan_ctx_t; -extern vulkan_ctx_t *vulkan_ctx; - #endif//__vid_vulkan_h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 840505e10..60c7c1b5e 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -43,7 +43,7 @@ #include "vulkan/namehack.h" -vulkan_ctx_t *vulkan_ctx; +static vulkan_ctx_t *vulkan_ctx; static vid_model_funcs_t model_funcs = { /* vulkan_Mod_LoadExternalTextures, @@ -153,7 +153,7 @@ vulkan_vid_render_init (void) vulkan_ctx = vr_data.vid->vid_internal->vulkan_context (); vulkan_ctx->load_vulkan (vulkan_ctx); - Vulkan_Init_Common (); + Vulkan_Init_Common (vulkan_ctx); vr_data.vid->vid_internal->set_palette = set_palette; vr_data.vid->vid_internal->choose_visual = vulkan_vid_render_choose_visual; @@ -166,7 +166,7 @@ vulkan_vid_render_init (void) static void vulkan_vid_render_shutdown (void) { - Vulkan_Shutdown_Common (); + Vulkan_Shutdown_Common (vulkan_ctx); } static general_funcs_t plugin_info_general_funcs = { diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c index e3181fc07..af3f21b4b 100644 --- a/libs/video/renderer/vulkan/init.c +++ b/libs/video/renderer/vulkan/init.c @@ -73,15 +73,15 @@ static const char *device_types[] = { }; static void -get_instance_layers_and_extensions (void) +get_instance_layers_and_extensions (vulkan_ctx_t *ctx) { uint32_t i; VkLayerProperties *properties; VkExtensionProperties *extensions; - vulkan_ctx->vkEnumerateInstanceLayerProperties (&numLayers, 0); + ctx->vkEnumerateInstanceLayerProperties (&numLayers, 0); properties = malloc (numLayers * sizeof (VkLayerProperties)); - vulkan_ctx->vkEnumerateInstanceLayerProperties (&numLayers, properties); + ctx->vkEnumerateInstanceLayerProperties (&numLayers, properties); instanceLayerNames = (const char **) malloc ((numLayers + 1) * sizeof (const char **)); for (i = 0; i < numLayers; i++) { @@ -89,9 +89,9 @@ get_instance_layers_and_extensions (void) } instanceLayerNames[i] = 0; - vulkan_ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, 0); + ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, 0); extensions = malloc (numExtensions * sizeof (VkLayerProperties)); - vulkan_ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, + ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, extensions); instanceExtensionNames = (const char **) malloc ((numExtensions + 1) * sizeof (const char **)); @@ -277,19 +277,19 @@ setup_debug_callback (VulkanInstance_t *instance) } static void -load_instance_funcs (VulkanInstance_t *instance) +load_instance_funcs (vulkan_ctx_t *ctx) { + VulkanInstance_t *vtx = ctx->vtx; + VkInstance instance = vtx->instance; #define INSTANCE_LEVEL_VULKAN_FUNCTION(name) \ - instance->name = (PFN_##name) \ - vulkan_ctx->vkGetInstanceProcAddr (instance->instance, #name); \ - if (!instance->name) { \ + vtx->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, #name); \ + if (!vtx->name) { \ Sys_Error ("Couldn't find instance level function %s", #name); \ } #define INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) \ - instance->name = (PFN_##name) \ - vulkan_ctx->vkGetInstanceProcAddr (instance->instance, #name); \ - if (!instance->name) { \ + vtx->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, #name); \ + if (!vtx->name) { \ Sys_Printf ("Couldn't find instance level function %s", #name); \ } @@ -297,7 +297,8 @@ load_instance_funcs (VulkanInstance_t *instance) } VulkanInstance_t * -Vulkan_CreateInstance (const char *appName, uint32_t appVersion, +Vulkan_CreateInstance (vulkan_ctx_t *ctx, + const char *appName, uint32_t appVersion, const char **layers, const char **extensions) { VkApplicationInfo appInfo = { @@ -319,7 +320,7 @@ Vulkan_CreateInstance (const char *appName, uint32_t appVersion, VulkanInstance_t *inst; if (!instanceLayerProperties) { - get_instance_layers_and_extensions (); + get_instance_layers_and_extensions (ctx); } createInfo.enabledLayerCount = count_strings (layers); @@ -346,13 +347,14 @@ Vulkan_CreateInstance (const char *appName, uint32_t appVersion, createInfo.ppEnabledLayerNames = lay; createInfo.ppEnabledExtensionNames = ext; - res = vulkan_ctx->vkCreateInstance (&createInfo, 0, &instance); + res = ctx->vkCreateInstance (&createInfo, 0, &instance); if (res != VK_SUCCESS) { Sys_Error ("unable to create vulkan instance\n"); } inst = malloc (sizeof(VulkanInstance_t)); inst->instance = instance; - load_instance_funcs (inst); + ctx->vtx = inst; + load_instance_funcs (ctx); if (vulkan_use_validation->int_val) { setup_debug_callback (inst); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index cfd2a980f..96094303a 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -168,25 +168,25 @@ create_suitable_device (VulkanInstance_t *instance) int x = 1; void -Vulkan_Init_Common (void) +Vulkan_Init_Common (vulkan_ctx_t *ctx) { Sys_Printf ("Vulkan_Init_Common\n"); Vulkan_Init_Cvars (); - vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version + vulkan_instance = Vulkan_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version vulkan_device = create_suitable_device (vulkan_instance); if (!vulkan_device) { Sys_Error ("no suitable vulkan device found"); } // only for now... Sys_Printf ("%p %p\n", vulkan_device->device, vulkan_device->queue); - Vulkan_Shutdown_Common (); + Vulkan_Shutdown_Common (ctx); if (x) Sys_Quit(); } void -Vulkan_Shutdown_Common (void) +Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { if (vulkan_device) { vulkan_device->vkDestroyDevice (vulkan_device->device, 0); @@ -195,5 +195,5 @@ Vulkan_Shutdown_Common (void) } Vulkan_DestroyInstance (vulkan_instance); vulkan_instance = 0; - vulkan_ctx->unload_vulkan (vulkan_ctx); + ctx->unload_vulkan (ctx); } From 0f511e8342e5ce27a419ef4504defa3db6f3234d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 14:24:55 +0900 Subject: [PATCH 0185/3664] Move the string list funcs to their own file They're not (at this stage, at least) worthy of being promoted out to the utils lib. --- libs/video/renderer/vulkan/Makefile.am | 3 +- libs/video/renderer/vulkan/init.c | 51 +--------------- libs/video/renderer/vulkan/util.c | 83 ++++++++++++++++++++++++++ libs/video/renderer/vulkan/util.h | 9 +++ 4 files changed, 97 insertions(+), 49 deletions(-) create mode 100644 libs/video/renderer/vulkan/util.c create mode 100644 libs/video/renderer/vulkan/util.h diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index e4102ec9d..b134d1f91 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -5,6 +5,7 @@ AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES vulkan_src = \ init.c \ + util.c \ vulkan_draw.c \ vulkan_vid_common.c @@ -21,5 +22,5 @@ SUFFICES=.frag .vert .fc .vc .slc .glsl libvulkan_la_SOURCES= $(vulkan_src) -EXTRA_DIST = $(vulkan_src) $(shader_src) namehack.h +EXTRA_DIST = $(vulkan_src) $(shader_src) namehack.h util.h CLEANFILES= *.vc *.fc *.slc diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c index af3f21b4b..7b553d5f6 100644 --- a/libs/video/renderer/vulkan/init.c +++ b/libs/video/renderer/vulkan/init.c @@ -1,5 +1,5 @@ /* - int.c + init.c Copyright (C) 2019 Bill Currie @@ -45,6 +45,8 @@ #include "vid_vulkan.h" +#include "util.h" + cvar_t *vulkan_use_validation; static uint32_t numLayers; @@ -196,53 +198,6 @@ init_physdev (VulkanInstance_t *instance, VkPhysicalDevice dev, VulkanPhysDevice } } -static int -count_strings (const char **str) -{ - int count = 0; - - if (str) { - while (*str++) { - count++; - } - } - return count; -} - -static void -merge_strings (const char **out, const char **in1, const char **in2) -{ - if (in1) { - while (*in1) { - *out++ = *in1++; - } - } - if (in2) { - while (*in2) { - *out++ = *in2++; - } - } -} - -static void -prune_strings (const char * const *reference, const char **strings, - uint32_t *count) -{ - for (int i = *count; i-- > 0; ) { - const char *str = strings[i]; - const char * const *ref; - for (ref = reference; *ref; ref++) { - if (!strcmp (*ref, str)) { - break; - } - } - if (!*ref) { - memmove (strings + i, strings + i + 1, - (--(*count) - i) * sizeof (const char **)); - } - } -} - static int message_severities = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | diff --git a/libs/video/renderer/vulkan/util.c b/libs/video/renderer/vulkan/util.c new file mode 100644 index 000000000..5603bbd5d --- /dev/null +++ b/libs/video/renderer/vulkan/util.c @@ -0,0 +1,83 @@ +/* + util.c + + Copyright (C) 2019 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "util.h" + +int +count_strings (const char **str) +{ + int count = 0; + + if (str) { + while (*str++) { + count++; + } + } + return count; +} + +void +merge_strings (const char **out, const char **in1, const char **in2) +{ + if (in1) { + while (*in1) { + *out++ = *in1++; + } + } + if (in2) { + while (*in2) { + *out++ = *in2++; + } + } +} + +void +prune_strings (const char * const *reference, const char **strings, + uint32_t *count) +{ + for (int i = *count; i-- > 0; ) { + const char *str = strings[i]; + const char * const *ref; + for (ref = reference; *ref; ref++) { + if (!strcmp (*ref, str)) { + break; + } + } + if (!*ref) { + memmove (strings + i, strings + i + 1, + (--(*count) - i) * sizeof (const char **)); + } + } +} diff --git a/libs/video/renderer/vulkan/util.h b/libs/video/renderer/vulkan/util.h new file mode 100644 index 000000000..8d1a967a3 --- /dev/null +++ b/libs/video/renderer/vulkan/util.h @@ -0,0 +1,9 @@ +#ifndef __util_h +#define __util_h + +#include +int count_strings (const char **str); +void merge_strings (const char **out, const char **in1, const char **in2); +void prune_strings (const char * const *reference, const char **strings, uint32_t *count); + +#endif//__util_h From 68449d0f6f5ccd98aeb6b2d5b5fa159675e0d164 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 16:33:44 +0900 Subject: [PATCH 0186/3664] Create a window and a surface for vulkan Yay, segfaults in R_Init :) --- include/QF/Vulkan/init.h | 8 +- include/QF/Vulkan/qf_vid.h | 1 + include/vid_vulkan.h | 4 + libs/video/renderer/vid_render_vulkan.c | 10 +- libs/video/renderer/vulkan/init.c | 66 +++++++---- libs/video/renderer/vulkan/util.c | 5 +- libs/video/renderer/vulkan/util.h | 8 +- .../video/renderer/vulkan/vulkan_vid_common.c | 107 ++++++++++-------- libs/video/targets/vid_x11_vulkan.c | 48 ++++++++ 9 files changed, 180 insertions(+), 77 deletions(-) diff --git a/include/QF/Vulkan/init.h b/include/QF/Vulkan/init.h index c964e6c41..3afab0179 100644 --- a/include/QF/Vulkan/init.h +++ b/include/QF/Vulkan/init.h @@ -30,9 +30,10 @@ #include "QF/qtypes.h" -typedef struct { +typedef struct VulkanDevice_s { VkDevice device; VkQueue queue; + VkSurfaceKHR surface; #define DEVICE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; #define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) PFN_##name name; @@ -63,6 +64,8 @@ typedef struct VulkanInstance_s { #include "QF/Vulkan/funclist.h" } VulkanInstance_t; +extern const char * const vulkanValidationLayers[]; + void Vulkan_Init_Cvars (void); struct vulkan_ctx_s; VulkanInstance_t *Vulkan_CreateInstance (struct vulkan_ctx_s *ctx, @@ -74,5 +77,8 @@ void Vulkan_DestroyInstance (VulkanInstance_t *instance); int Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions, int numExtensions, const char * const *requested); +int Vulkan_LayersSupported (const VkLayerProperties *extensions, + int numLayers, + const char * const *requested); #endif // __QF_Vulkan_init_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 8e1825b48..877bebaa3 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -31,6 +31,7 @@ #include "QF/Vulkan/cvars.h" struct vulkan_ctx_s; +void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); void Vulkan_Shutdown_Common (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index eea285ae4..387a82078 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -15,10 +15,14 @@ typedef struct vulkan_ctx_s { int (*get_presentation_support) (struct vulkan_ctx_s *ctx, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex); + void (*choose_visual) (struct vulkan_ctx_s *ctx); + void (*create_window) (struct vulkan_ctx_s *ctx); VkSurfaceKHR (*create_surface) (struct vulkan_ctx_s *ctx); struct VulkanInstance_s *vtx; + struct VulkanDevice_s *dev; VkInstance instance; + VkDevice device; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 60c7c1b5e..c09bfe5e4 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -31,10 +31,13 @@ #define NH_DEFINE #include "vulkan/namehack.h" +#include "QF/sys.h" + #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/init.h" #include "mod_internal.h" #include "r_internal.h" @@ -138,13 +141,16 @@ set_palette (const byte *palette) static void vulkan_vid_render_choose_visual (void) { - //vulkan_ctx->coose_visual (vulkan_ctx); + Vulkan_CreateDevice (vulkan_ctx); + vulkan_ctx->choose_visual (vulkan_ctx); + Sys_Printf ("%p %p\n", vulkan_ctx->dev->device, vulkan_ctx->dev->queue); } static void vulkan_vid_render_create_context (void) { - vulkan_ctx->create_surface (vulkan_ctx); + vulkan_ctx->create_window (vulkan_ctx); + vulkan_ctx->dev->surface = vulkan_ctx->create_surface (vulkan_ctx); } static void diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c index 7b553d5f6..eba6fa4be 100644 --- a/libs/video/renderer/vulkan/init.c +++ b/libs/video/renderer/vulkan/init.c @@ -56,17 +56,17 @@ static uint32_t numExtensions; static VkExtensionProperties *instanceExtensionProperties; static const char **instanceExtensionNames; -static const char *validationLayers[] = { +const char * const vulkanValidationLayers[] = { "VK_LAYER_LUNARG_standard_validation", 0, }; -static const char *debugExtensions[] = { +static const char * const debugExtensions[] = { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, 0, }; -static const char *device_types[] = { +static const char * const device_types[] = { "other", "integrated gpu", "discrete gpu", @@ -278,28 +278,30 @@ Vulkan_CreateInstance (vulkan_ctx_t *ctx, get_instance_layers_and_extensions (ctx); } - createInfo.enabledLayerCount = count_strings (layers); - createInfo.ppEnabledLayerNames = layers; - createInfo.enabledExtensionCount = count_strings (extensions); - createInfo.ppEnabledExtensionNames = extensions; + uint32_t nlay = count_strings (layers); + uint32_t next = count_strings (extensions) + + count_strings (ctx->required_extensions); if (vulkan_use_validation->int_val) { - createInfo.enabledLayerCount += count_strings (validationLayers); - createInfo.enabledExtensionCount += count_strings (debugExtensions); + nlay += count_strings (vulkanValidationLayers); + next += count_strings (debugExtensions); } - const char **lay = alloca (createInfo.enabledLayerCount * sizeof (const char *)); - const char **ext = alloca (createInfo.enabledExtensionCount * sizeof (const char *)); + const char **lay = alloca (nlay * sizeof (const char *)); + const char **ext = alloca (next * sizeof (const char *)); + // ensure there are null pointers so merge_strings can act as append + // since it does not add a null + memset (lay, 0, nlay * sizeof (const char *)); + memset (ext, 0, next * sizeof (const char *)); + merge_strings (lay, layers, 0); + merge_strings (ext, extensions, ctx->required_extensions); if (vulkan_use_validation->int_val) { - merge_strings (lay, layers, validationLayers); - merge_strings (ext, extensions, debugExtensions); - } else { - merge_strings (lay, layers, 0); - merge_strings (ext, extensions, 0); + merge_strings (lay, lay, vulkanValidationLayers); + merge_strings (ext, ext, debugExtensions); } - prune_strings (instanceLayerNames, lay, - &createInfo.enabledLayerCount); - prune_strings (instanceExtensionNames, ext, - &createInfo.enabledExtensionCount); + prune_strings (instanceLayerNames, lay, &nlay); + prune_strings (instanceExtensionNames, ext, &next); + createInfo.enabledLayerCount = nlay; createInfo.ppEnabledLayerNames = lay; + createInfo.enabledExtensionCount = next; createInfo.ppEnabledExtensionNames = ext; res = ctx->vkCreateInstance (&createInfo, 0, &instance); @@ -348,6 +350,27 @@ Vulkan_DestroyInstance (VulkanInstance_t *instance) free (instance); } +int +Vulkan_LayersSupported (const VkLayerProperties *layers, + int numLayers, + const char * const *requested) +{ + while (*requested) { + int i; + for (i = 0; i < numLayers; i++) { + if (!strcmp (*requested, layers[i].layerName)) { + break; + } + } + if (i == numLayers) { + // requested layer not found + break; + } + requested++; + } + return !*requested; +} + int Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions, int numExtensions, @@ -360,10 +383,11 @@ Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions, break; } } - if (i < numExtensions) { + if (i == numExtensions) { // requested extension not found break; } + requested++; } return !*requested; } diff --git a/libs/video/renderer/vulkan/util.c b/libs/video/renderer/vulkan/util.c index 5603bbd5d..8fa5c2a72 100644 --- a/libs/video/renderer/vulkan/util.c +++ b/libs/video/renderer/vulkan/util.c @@ -36,7 +36,7 @@ #include "util.h" int -count_strings (const char **str) +count_strings (const char * const *str) { int count = 0; @@ -49,7 +49,8 @@ count_strings (const char **str) } void -merge_strings (const char **out, const char **in1, const char **in2) +merge_strings (const char **out, const char * const *in1, + const char * const *in2) { if (in1) { while (*in1) { diff --git a/libs/video/renderer/vulkan/util.h b/libs/video/renderer/vulkan/util.h index 8d1a967a3..0948a1bbd 100644 --- a/libs/video/renderer/vulkan/util.h +++ b/libs/video/renderer/vulkan/util.h @@ -2,8 +2,10 @@ #define __util_h #include -int count_strings (const char **str); -void merge_strings (const char **out, const char **in1, const char **in2); -void prune_strings (const char * const *reference, const char **strings, uint32_t *count); +int count_strings (const char * const *str); +void merge_strings (const char **out, const char * const *in1, + const char * const *in2); +void prune_strings (const char * const *reference, const char **strings, + uint32_t *count); #endif//__util_h diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 96094303a..c7060ef58 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -55,8 +55,7 @@ #include "r_internal.h" #include "vid_vulkan.h" -static VulkanInstance_t *vulkan_instance; -static VulkanDevice_t *vulkan_device; +#include "util.h" void Vulkan_Init_Cvars () @@ -74,6 +73,7 @@ static const char *instance_extensions[] = { }; static const char *device_extensions[] = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, 0, }; @@ -126,18 +126,61 @@ load_device_funcs (VulkanInstance_t *inst, VulkanDevice_t *dev) #include "QF/Vulkan/funclist.h" } -static VulkanDevice_t * -create_suitable_device (VulkanInstance_t *instance) +void +Vulkan_Init_Common (vulkan_ctx_t *ctx) { - for (uint32_t i = 0; i < instance->numDevices; i++) { - VulkanPhysDevice_t *phys = &instance->devices[i]; + Sys_Printf ("Vulkan_Init_Common\n"); + Vulkan_Init_Cvars (); + + ctx->vtx = Vulkan_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version + ctx->instance = ctx->vtx->instance; +} + +void +Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) +{ + Vulkan_DestroyInstance (ctx->vtx); + ctx->vtx = 0; + ctx->unload_vulkan (ctx); +} + +void +Vulkan_CreateDevice (vulkan_ctx_t *ctx) +{ + VulkanInstance_t *inst = ctx->vtx; + + uint32_t nlay = 1; // ensure alloca doesn't see 0 and terminated + uint32_t next = count_strings (device_extensions) + 1; // ensure terminated + if (vulkan_use_validation->int_val) { + nlay += count_strings (vulkanValidationLayers); + } + const char **lay = alloca (nlay * sizeof (const char *)); + const char **ext = alloca (next * sizeof (const char *)); + // ensure there are null pointers so merge_strings can act as append + // since it does not add a null, but also make sure the counts reflect + // actual numbers + memset (lay, 0, nlay-- * sizeof (const char *)); + memset (ext, 0, next-- * sizeof (const char *)); + merge_strings (ext, device_extensions, 0); + if (vulkan_use_validation->int_val) { + merge_strings (lay, lay, vulkanValidationLayers); + } + + for (uint32_t i = 0; i < inst->numDevices; i++) { + VulkanPhysDevice_t *phys = &inst->devices[i]; + if (!Vulkan_LayersSupported (phys->layers, phys->numLayers, lay)) { + continue; + } if (!Vulkan_ExtensionsSupported (phys->extensions, phys->numExtensions, - device_extensions)) { - return 0; + ext)) { + continue; } int family = find_queue_family (phys, VK_QUEUE_GRAPHICS_BIT); if (family < 0) { - return 0; + continue; + } + if (!ctx->get_presentation_support (ctx, phys->device, family)) { + continue; } float priority = 1; VkDeviceQueueCreateInfo qCreateInfo = { @@ -148,52 +191,20 @@ create_suitable_device (VulkanInstance_t *instance) VkDeviceCreateInfo dCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0, 1, &qCreateInfo, - 0, 0, - 0, device_extensions, + nlay, lay, + next, ext, &features }; memset (&features, 0, sizeof (features)); VulkanDevice_t *device = calloc (1, sizeof (VulkanDevice_t)); - if (instance->vkCreateDevice (phys->device, &dCreateInfo, 0, + if (inst->vkCreateDevice (phys->device, &dCreateInfo, 0, &device->device) == VK_SUCCESS) { - load_device_funcs (instance, device); + load_device_funcs (inst, device); device->vkGetDeviceQueue (device->device, family, 0, &device->queue); - return device; + ctx->dev = device; + ctx->device = device->device; + return; } } - return 0; -} - -int x = 1; - -void -Vulkan_Init_Common (vulkan_ctx_t *ctx) -{ - Sys_Printf ("Vulkan_Init_Common\n"); - Vulkan_Init_Cvars (); - - vulkan_instance = Vulkan_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version - vulkan_device = create_suitable_device (vulkan_instance); - if (!vulkan_device) { - Sys_Error ("no suitable vulkan device found"); - } - // only for now... - Sys_Printf ("%p %p\n", vulkan_device->device, vulkan_device->queue); - Vulkan_Shutdown_Common (ctx); - if (x) - Sys_Quit(); -} - -void -Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) -{ - if (vulkan_device) { - vulkan_device->vkDestroyDevice (vulkan_device->device, 0); - free (vulkan_device); - vulkan_device = 0; - } - Vulkan_DestroyInstance (vulkan_instance); - vulkan_instance = 0; - ctx->unload_vulkan (ctx); } diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index e472c0c0e..b7b88d1b1 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -110,11 +110,38 @@ unload_vulkan_library (vulkan_ctx_t *ctx) vulkan_library = 0; } +static void +x11_vulkan_init_presentation (vulkan_ctx_t *ctx) +{ + ctx->presentation = calloc (1, sizeof (vulkan_presentation_t)); + vulkan_presentation_t *pres = ctx->presentation; + VkInstance instance = ctx->instance; + +#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) \ + pres->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, #name); \ + if (!pres->name) { \ + Sys_Error ("Couldn't find instance-level function %s", #name); \ + } +#include "QF/Vulkan/funclist.h" + + XVisualInfo template; + Visual *defaultVisual = XDefaultVisual (x_disp, x_screen); + template.visualid = XVisualIDFromVisual (defaultVisual); + int template_mask = VisualIDMask; + pres->display = x_disp; + pres->usable_visuals = set_new (); + pres->visinfo = XGetVisualInfo (x_disp, template_mask, &template, + &pres->num_visuals); +} + static int x11_vulkan_get_presentation_support (vulkan_ctx_t *ctx, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) { + if (!ctx->presentation) { + x11_vulkan_init_presentation (ctx); + } vulkan_presentation_t *pres = ctx->presentation; set_empty (pres->usable_visuals); @@ -129,6 +156,25 @@ x11_vulkan_get_presentation_support (vulkan_ctx_t *ctx, return !set_is_empty (pres->usable_visuals); } +static void +x11_vulkan_choose_visual (vulkan_ctx_t *ctx) +{ + vulkan_presentation_t *pres = ctx->presentation; + set_iter_t *first = set_first (pres->usable_visuals); + if (first) { + x_visinfo = pres->visinfo + first->element; + x_vis = x_visinfo->visual; + set_del_iter (first); + } +} + +static void +x11_vulkan_create_window (vulkan_ctx_t *ctx) +{ + vulkan_presentation_t *pres = ctx->presentation; + pres->window = x_win; +} + static VkSurfaceKHR x11_vulkan_create_surface (vulkan_ctx_t *ctx) { @@ -155,6 +201,8 @@ X11_Vulkan_Context (void) ctx->load_vulkan = load_vulkan_library; ctx->unload_vulkan = unload_vulkan_library; ctx->get_presentation_support = x11_vulkan_get_presentation_support; + ctx->choose_visual = x11_vulkan_choose_visual; + ctx->create_window = x11_vulkan_create_window; ctx->create_surface = x11_vulkan_create_surface; ctx->required_extensions = required_extensions; return ctx; From 8a3cd224a36a9bb1c8fba84e5e77113c3d7f3fe3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 20:14:30 +0900 Subject: [PATCH 0187/3664] Add vulkan developer flag --- include/QF/sys.h | 1 + libs/video/renderer/vulkan/init.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index f93432d65..4dd61bacd 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -97,6 +97,7 @@ void Sys_MaskPrintf (int mask, const char *fmt, ...) __attribute__((format(print #define SYS_GLSL (1|2048) #define SYS_SKIN (1|4096) #define SYS_MODEL (1|8192) +#define SYS_VULKAN (1|16384) int Sys_CheckInput (int idle, int net_socket); const char *Sys_ConsoleInput (void); diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c index eba6fa4be..19091bb8a 100644 --- a/libs/video/renderer/vulkan/init.c +++ b/libs/video/renderer/vulkan/init.c @@ -102,7 +102,7 @@ get_instance_layers_and_extensions (vulkan_ctx_t *ctx) } instanceExtensionNames[i] = 0; - if (developer->int_val & SYS_VID) { + if (developer->int_val & SYS_VULKAN) { for (i = 0; i < numLayers; i++) { Sys_Printf ("%s %x %u %s\n", properties[i].layerName, @@ -154,7 +154,7 @@ init_physdev (VulkanInstance_t *instance, VkPhysicalDevice dev, VulkanPhysDevice &physdev->numQueueFamilies, physdev->queueFamilies); - if (developer->int_val & SYS_VID) { + if (developer->int_val & SYS_VULKAN) { VkPhysicalDeviceProperties *prop = &physdev->properties; Sys_Printf ("dev: %p\n", dev); Sys_Printf (" %x %x\n", prop->apiVersion, prop->driverVersion); From 8c238d3def13ef509272f2f9889d57aa00fe4eaa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 20:14:57 +0900 Subject: [PATCH 0188/3664] Parse developer flag names when cvar is set So much easier to remember "vulkan" instead of which power of two it is. --- libs/util/cvar.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 64ef200ab..3b30b00f9 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -37,6 +37,7 @@ # include #endif +#include #include #include @@ -327,6 +328,82 @@ Cvar_WriteVariables (QFile *f) Qprintf (f, "seta %s \"%s\"\n", var->name, var->string); } +// XXX make sure in sync with SYS_* in sys.h +static const char *developer_flags[] = { + "dev", + "warn", + "vid", + "fs_nf", + "fs_f", + "fs", + "net", + "rua_obj", + "rua_msg", + "snd", + "glt", + "glsl", + "skin", + "model", + "vulkan", + 0 +}; + +static int +parse_developer_flag (const char *flag) +{ + const char **devflag; + char *end; + int val; + + val = strtol (flag, &end, 0); + if (!*end) { + return val; + } + for (devflag = developer_flags; *devflag; devflag++) { + if (!strcmp (*devflag, flag)) { + return 1 << (devflag - developer_flags); + } + } + return 0; +} + +static void +developer_f (cvar_t *var) +{ + char *buf = alloca (strlen (var->string) + 1); + const char *s; + char *b; + char c; + int parse = 0; + + for (s = var->string; *s; s++) { + if (isalpha (*s) || *s == '|') { + parse = 1; + break; + } + } + if (!parse) { + return; + } + var->int_val = 0; + for (s = var->string, b = buf; (c = *s++); ) { + if (isspace (c)) { + continue; + } + if (c == '|') { + *b = 0; + var->int_val |= parse_developer_flag (buf); + b = buf; + continue; + } + *b++ = c; + } + if (b != buf) { + *b = 0; + var->int_val |= parse_developer_flag (buf); + } +} + static void set_cvar (const char *cmd, int orflags) { @@ -587,7 +664,7 @@ Cvar_Init_Hash (void) VISIBLE void Cvar_Init (void) { - developer = Cvar_Get ("developer", "0", CVAR_NONE, NULL, + developer = Cvar_Get ("developer", "0", CVAR_NONE, developer_f, "set to enable extra debugging information"); Cmd_AddCommand ("set", Cvar_Set_f, "Set the selected variable, useful on " From 452eb5a83d85db2d0c38215472fde386f8696aff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 20:16:08 +0900 Subject: [PATCH 0189/3664] Preserve parsed cvar values when string is same Fixes parsed developer flags on the command line getting reset. --- libs/util/cvar.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 3b30b00f9..e3e14236f 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -264,19 +264,21 @@ Cvar_Set (cvar_t *var, const char *value) } changed = !strequal (var->string, value); - free ((char*)var->string); // free the old value string + if (changed) { + free ((char*)var->string); // free the old value string - var->string = strdup (value); - var->value = atof (var->string); - var->int_val = atoi (var->string); - VectorZero (var->vec); - vals = sscanf (var->string, "%f %f %f", - &var->vec[0], &var->vec[1], &var->vec[2]); - if (vals == 1) - var->vec[2] = var->vec[1] = var->vec[0]; + var->string = strdup (value); + var->value = atof (var->string); + var->int_val = atoi (var->string); + VectorZero (var->vec); + vals = sscanf (var->string, "%f %f %f", + &var->vec[0], &var->vec[1], &var->vec[2]); + if (vals == 1) + var->vec[2] = var->vec[1] = var->vec[0]; - if (changed && var->callback) - var->callback (var); + if (var->callback) + var->callback (var); + } } VISIBLE void From 3191604641aba1e4775fabc4c4565c81e6719039 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 21:07:59 +0900 Subject: [PATCH 0190/3664] Uncomment already implemented functions --- libs/video/renderer/vid_render_vulkan.c | 62 ++++++++++++------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index c09bfe5e4..693a85d14 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -49,29 +49,29 @@ static vulkan_ctx_t *vulkan_ctx; static vid_model_funcs_t model_funcs = { -/* vulkan_Mod_LoadExternalTextures, - vulkan_Mod_LoadLighting, - vulkan_Mod_SubdivideSurface, - vulkan_Mod_ProcessTexture, + 0,//vulkan_Mod_LoadExternalTextures, + 0,//vulkan_Mod_LoadLighting, + 0,//vulkan_Mod_SubdivideSurface, + 0,//vulkan_Mod_ProcessTexture, Mod_LoadIQM, Mod_LoadAliasModel, Mod_LoadSpriteModel, - vulkan_Mod_MakeAliasModelDisplayLists, - vulkan_Mod_LoadSkin, - vulkan_Mod_FinalizeAliasModel, - vulkan_Mod_LoadExternalSkins, - vulkan_Mod_IQMFinish, + 0,//vulkan_Mod_MakeAliasModelDisplayLists, + 0,//vulkan_Mod_LoadSkin, + 0,//vulkan_Mod_FinalizeAliasModel, + 0,//vulkan_Mod_LoadExternalSkins, + 0,//vulkan_Mod_IQMFinish, 0, - vulkan_Mod_SpriteLoadTexture, + 0,//vulkan_Mod_SpriteLoadTexture, Skin_SetColormap, Skin_SetSkin, - vulkan_Skin_SetupSkin, + 0,//vulkan_Skin_SetupSkin, Skin_SetTranslation, - vulkan_Skin_ProcessTranslation, - vulkan_Skin_InitTranslations,*/ + 0,//vulkan_Skin_ProcessTranslation, + 0,//vulkan_Skin_InitTranslations, }; vid_render_funcs_t vulkan_vid_render_funcs = { @@ -97,37 +97,37 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_Picf, vulkan_Draw_SubPic, -/* vulkan_SCR_UpdateScreen, + 0,//vulkan_SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, SCR_DrawPause, - vulkan_SCR_CaptureBGR, - vulkan_SCR_ScreenShot, + 0,//vulkan_SCR_CaptureBGR, + 0,//vulkan_SCR_ScreenShot, SCR_DrawStringToSnap, - vulkan_Fog_Update, - vulkan_Fog_ParseWorldspawn, + 0,//vulkan_Fog_Update, + 0,//vulkan_Fog_ParseWorldspawn, - vulkan_R_Init, - vulkan_R_ClearState, - vulkan_R_LoadSkys, - vulkan_R_NewMap, + 0,//vulkan_R_Init, + 0,//vulkan_R_ClearState, + 0,//vulkan_R_LoadSkys, + 0,//vulkan_R_NewMap, R_AddEfrags, R_RemoveEfrags, R_EnqueueEntity, - vulkan_R_LineGraph, + 0,//vulkan_R_LineGraph, R_AllocDlight, R_AllocEntity, - vulkan_R_RenderView, + 0,//vulkan_R_RenderView, R_DecayLights, - vulkan_R_ViewChanged, - vulkan_R_ClearParticles, - vulkan_R_InitParticles, - vulkan_SCR_ScreenShot_f, - vulkan_r_easter_eggs_f, - vulkan_r_particles_style_f, + 0,//vulkan_R_ViewChanged, + 0,//vulkan_R_ClearParticles, + 0,//vulkan_R_InitParticles, + 0,//vulkan_SCR_ScreenShot_f, + 0,//vulkan_r_easter_eggs_f, + 0,//vulkan_r_particles_style_f, 0, - &model_funcs*/ + &model_funcs }; static void From 31ead15e9688bde056a91967a200915d10f6f149 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 22:04:48 +0900 Subject: [PATCH 0191/3664] Add comment about developer flags --- include/QF/sys.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/QF/sys.h b/include/QF/sys.h index 4dd61bacd..7c669563e 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -83,6 +83,7 @@ double Sys_DoubleTime (void); void Sys_TimeOfDay(date_t *date); void Sys_MaskPrintf (int mask, const char *fmt, ...) __attribute__((format(printf,2,3))); +// remember to update developer_flags in cvar.c #define SYS_DEV (1|0) #define SYS_WARN (1|2) // bit 0 so developer 1 will pick it up #define SYS_VID (1|4) From ed3c5cb9ec0fc47abd29a597c2d91b73505d7bff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Jul 2019 13:09:16 +0900 Subject: [PATCH 0192/3664] Add a strset "class" It's just a wrapper around hashtab, but it makes checking if a string is in a set easy. Way overkill when only a few extensions are enabled, but more might come later. --- libs/video/renderer/vulkan/util.c | 27 +++++++++++++++++++++++++++ libs/video/renderer/vulkan/util.h | 5 +++++ 2 files changed, 32 insertions(+) diff --git a/libs/video/renderer/vulkan/util.c b/libs/video/renderer/vulkan/util.c index 8fa5c2a72..09e1b146a 100644 --- a/libs/video/renderer/vulkan/util.c +++ b/libs/video/renderer/vulkan/util.c @@ -33,8 +33,35 @@ # include #endif +#include "QF/hash.h" + #include "util.h" +static const char * +strset_get_key (const void *_str, void *unused) +{ + return (const char *)_str; +} + +strset_t * +new_strset (const char * const *strings) +{ + hashtab_t *tab = Hash_NewTable (61, strset_get_key, 0, 0); + for ( ; *strings; strings++) { + Hash_Add (tab, (void *) *strings); + } + return (strset_t *) tab; +} +void del_strset (strset_t *strset) +{ + Hash_DelTable ((hashtab_t *) strset); +} + +int strset_contains (strset_t *strset, const char *str) +{ + return Hash_Find ((hashtab_t *) strset, str) != 0; +} + int count_strings (const char * const *str) { diff --git a/libs/video/renderer/vulkan/util.h b/libs/video/renderer/vulkan/util.h index 0948a1bbd..a15aac4c8 100644 --- a/libs/video/renderer/vulkan/util.h +++ b/libs/video/renderer/vulkan/util.h @@ -8,4 +8,9 @@ void merge_strings (const char **out, const char * const *in1, void prune_strings (const char * const *reference, const char **strings, uint32_t *count); +typedef struct strset_s strset_t; +strset_t *new_strset (const char * const *strings); +void del_strset (strset_t *strset); +int strset_contains (strset_t *strset, const char *str); + #endif//__util_h From 2771e9c5736b5e96e313e40a59c0c93a128c8d2d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Jul 2019 13:16:46 +0900 Subject: [PATCH 0193/3664] Correct extension handling I had missed a critical bit from the cookbook. --- include/QF/Vulkan/funclist.h | 49 ++++++++++++------- include/QF/Vulkan/init.h | 15 +++--- include/vid_vulkan.h | 4 ++ libs/video/renderer/vid_render_vulkan.c | 10 +++- libs/video/renderer/vulkan/init.c | 30 +++++++++--- .../video/renderer/vulkan/vulkan_vid_common.c | 12 +++-- libs/video/targets/vid_x11_vulkan.c | 13 +++-- 7 files changed, 91 insertions(+), 42 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 79af14277..e54ce6f50 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -21,16 +21,6 @@ GLOBAL_LEVEL_VULKAN_FUNCTION (vkCreateInstance) #define INSTANCE_LEVEL_VULKAN_FUNCTION(function) #endif -#if defined(VK_USE_PLATFORM_XLIB_KHR) -INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceXlibPresentationSupportKHR) -INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateXlibSurfaceKHR) -#elif defined(VK_USE_PLATFORM_WIN32_KHR) -INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceWin32PresentationSupportKHR) -INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateWin32SurfaceKHR) -#elif defined(VK_USE_PLATFORM_XCB_KHR) -INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceXcbPresentationSupportKHR) -INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateXcbSurfaceKHR) -#else INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumeratePhysicalDevices) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures) @@ -41,17 +31,40 @@ INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceLayerProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceExtensionProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties) -#endif #undef INSTANCE_LEVEL_VULKAN_FUNCTION -#ifndef INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION -#define INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION(function) +#ifndef INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION +#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(function, extension) #endif -INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION (vkCreateDebugUtilsMessengerEXT) +#if defined(VK_USE_PLATFORM_XLIB_KHR) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceXlibPresentationSupportKHR, + VK_KHR_XLIB_SURFACE_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkCreateXlibSurfaceKHR, + VK_KHR_XLIB_SURFACE_EXTENSION_NAME) +#elif defined(VK_USE_PLATFORM_WIN32_KHR) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceWin32PresentationSupportKHR, + VK_KHR_WIN32_SURFACE_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkCreateWin32SurfaceKHR, + VK_KHR_WIN32_SURFACE_EXTENSION_NAME) +#elif defined(VK_USE_PLATFORM_XCB_KHR) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceXcbPresentationSupportKHR, + VK_KHR_XCB_SURFACE_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkCreateXcbSurfaceKHR, + VK_KHR_XCB_SURFACE_EXTENSION_NAME) +#else +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkCreateDebugUtilsMessengerEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) +#endif -#undef INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION +#undef INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION #ifndef DEVICE_LEVEL_VULKAN_FUNCTION #define DEVICE_LEVEL_VULKAN_FUNCTION(function) @@ -62,8 +75,8 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkGetDeviceQueue) #undef DEVICE_LEVEL_VULKAN_FUNCTION -#ifndef DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION -#define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(function) +#ifndef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION +#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(function, extension) #endif -#undef DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION +#undef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION diff --git a/include/QF/Vulkan/init.h b/include/QF/Vulkan/init.h index 3afab0179..961c72d84 100644 --- a/include/QF/Vulkan/init.h +++ b/include/QF/Vulkan/init.h @@ -35,9 +35,9 @@ typedef struct VulkanDevice_s { VkQueue queue; VkSurfaceKHR surface; - #define DEVICE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; - #define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) PFN_##name name; - #include "QF/Vulkan/funclist.h" +#define DEVICE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; +#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; +#include "QF/Vulkan/funclist.h" } VulkanDevice_t; typedef struct { @@ -55,13 +55,16 @@ typedef struct { typedef struct VulkanInstance_s { VkInstance instance; + struct strset_s *enabled_extensions; + int (*extension_enabled) (struct VulkanInstance_s *inst, + const char *ext); VkDebugUtilsMessengerEXT debug_callback; uint32_t numDevices; VulkanPhysDevice_t *devices; - #define INSTANCE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; - #define INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) PFN_##name name; - #include "QF/Vulkan/funclist.h" +#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; +#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; +#include "QF/Vulkan/funclist.h" } VulkanInstance_t; extern const char * const vulkanValidationLayers[]; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 387a82078..924a3a1d4 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -6,11 +6,14 @@ #endif #include +struct VulkanInstance_s; typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); void (*unload_vulkan) (struct vulkan_ctx_s *ctx); const char **required_extensions; + int (*extension_enabled) (struct VulkanInstance_s *inst, + const char *ext); struct vulkan_presentation_s *presentation; int (*get_presentation_support) (struct vulkan_ctx_s *ctx, VkPhysicalDevice physicalDevice, @@ -22,6 +25,7 @@ typedef struct vulkan_ctx_s { struct VulkanInstance_s *vtx; struct VulkanDevice_s *dev; VkInstance instance; + VkPhysicalDevice physDevice; VkDevice device; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 693a85d14..11fe640f2 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -48,6 +48,13 @@ static vulkan_ctx_t *vulkan_ctx; +static void +vulkan_R_Init (void) +{ + if (vulkan_ctx) + Sys_Quit (); +} + static vid_model_funcs_t model_funcs = { 0,//vulkan_Mod_LoadExternalTextures, 0,//vulkan_Mod_LoadLighting, @@ -108,7 +115,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { 0,//vulkan_Fog_Update, 0,//vulkan_Fog_ParseWorldspawn, - 0,//vulkan_R_Init, + vulkan_R_Init, 0,//vulkan_R_ClearState, 0,//vulkan_R_LoadSkys, 0,//vulkan_R_NewMap, @@ -151,6 +158,7 @@ vulkan_vid_render_create_context (void) { vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->dev->surface = vulkan_ctx->create_surface (vulkan_ctx); + Sys_Printf ("%p\n", vulkan_ctx->dev->surface); } static void diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c index 19091bb8a..529969014 100644 --- a/libs/video/renderer/vulkan/init.c +++ b/libs/video/renderer/vulkan/init.c @@ -198,6 +198,12 @@ init_physdev (VulkanInstance_t *instance, VkPhysicalDevice dev, VulkanPhysDevice } } +static int +instance_extension_enabled (VulkanInstance_t *inst, const char *ext) +{ + return strset_contains (inst->enabled_extensions, ext); +} + static int message_severities = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | @@ -242,10 +248,13 @@ load_instance_funcs (vulkan_ctx_t *ctx) Sys_Error ("Couldn't find instance level function %s", #name); \ } -#define INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) \ - vtx->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, #name); \ - if (!vtx->name) { \ - Sys_Printf ("Couldn't find instance level function %s", #name); \ +#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ + if (vtx->extension_enabled (vtx, ext)) { \ + vtx->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, \ + #name); \ + if (!vtx->name) { \ + Sys_Error ("Couldn't find instance level function %s", #name); \ + } \ } #include "QF/Vulkan/funclist.h" @@ -278,9 +287,9 @@ Vulkan_CreateInstance (vulkan_ctx_t *ctx, get_instance_layers_and_extensions (ctx); } - uint32_t nlay = count_strings (layers); + uint32_t nlay = count_strings (layers) + 1; uint32_t next = count_strings (extensions) - + count_strings (ctx->required_extensions); + + count_strings (ctx->required_extensions) + 1; if (vulkan_use_validation->int_val) { nlay += count_strings (vulkanValidationLayers); next += count_strings (debugExtensions); @@ -289,8 +298,8 @@ Vulkan_CreateInstance (vulkan_ctx_t *ctx, const char **ext = alloca (next * sizeof (const char *)); // ensure there are null pointers so merge_strings can act as append // since it does not add a null - memset (lay, 0, nlay * sizeof (const char *)); - memset (ext, 0, next * sizeof (const char *)); + memset (lay, 0, nlay-- * sizeof (const char *)); + memset (ext, 0, next-- * sizeof (const char *)); merge_strings (lay, layers, 0); merge_strings (ext, extensions, ctx->required_extensions); if (vulkan_use_validation->int_val) { @@ -299,6 +308,8 @@ Vulkan_CreateInstance (vulkan_ctx_t *ctx, } prune_strings (instanceLayerNames, lay, &nlay); prune_strings (instanceExtensionNames, ext, &next); + lay[nlay] = 0; + ext[next] = 0; createInfo.enabledLayerCount = nlay; createInfo.ppEnabledLayerNames = lay; createInfo.enabledExtensionCount = next; @@ -310,6 +321,9 @@ Vulkan_CreateInstance (vulkan_ctx_t *ctx, } inst = malloc (sizeof(VulkanInstance_t)); inst->instance = instance; + inst->enabled_extensions = new_strset (ext); + inst->extension_enabled = instance_extension_enabled; + ctx->extension_enabled = instance_extension_enabled; ctx->vtx = inst; load_instance_funcs (ctx); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index c7060ef58..561eb64f5 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -117,10 +117,13 @@ load_device_funcs (VulkanInstance_t *inst, VulkanDevice_t *dev) Sys_Error ("Couldn't find device level function %s", #name); \ } -#define DEVICE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) \ - dev->name = (PFN_##name) inst->vkGetDeviceProcAddr (dev->device, #name); \ - if (!dev->name) { \ - Sys_Printf ("Couldn't find device level function %s", #name); \ +#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ + if (inst->extension_enabled (vtx, ext)) { \ + dev->name = (PFN_##name) inst->vkGetDeviceProcAddr (dev->device, \ + #name); \ + if (!dev->name) { \ + Sys_Printf ("Couldn't find device level function %s", #name); \ + } \ } #include "QF/Vulkan/funclist.h" @@ -204,6 +207,7 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) 0, &device->queue); ctx->dev = device; ctx->device = device->device; + ctx->physDevice = phys->device; return; } } diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index b7b88d1b1..812e74dad 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -61,7 +61,7 @@ static cvar_t *vulkan_library_name; typedef struct vulkan_presentation_s { -#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; +#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; #include "QF/Vulkan/funclist.h" Display *display; @@ -117,10 +117,13 @@ x11_vulkan_init_presentation (vulkan_ctx_t *ctx) vulkan_presentation_t *pres = ctx->presentation; VkInstance instance = ctx->instance; -#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) \ - pres->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, #name); \ - if (!pres->name) { \ - Sys_Error ("Couldn't find instance-level function %s", #name); \ +#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ + if (ctx->extension_enabled (ctx->vtx, ext)) { \ + pres->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, \ + #name); \ + if (!pres->name) { \ + Sys_Error ("Couldn't find instance-level function %s", #name); \ + } \ } #include "QF/Vulkan/funclist.h" From d5cb4329112dcb766bbd337edd6bac4b1bc63e79 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Jul 2019 22:15:39 +0900 Subject: [PATCH 0194/3664] Add a cvar to block use of x11 vidmode Or really, allow it if the user specifically requests it: the default is blocked. Modern systems (particularly displays) do not really like changing resolution, so doing so by default seems rather wrong. --- libs/video/targets/context_x11.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 41045fcdf..5c23d1875 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -125,6 +125,8 @@ static int accel_threshold; static Atom x_net_state; static Atom x_net_fullscreen; +static cvar_t *x11_vidmode; + static void set_fullscreen (int full) { @@ -387,6 +389,10 @@ X11_SetVidMode (int width, int height) if (vidmode_active) return; + if (!x11_vidmode->int_val) { + return; + } + if (str && (tolower (*str) == 'f')) { Cvar_Set (vid_fullscreen, "1"); } @@ -506,6 +512,9 @@ X11_Init_Cvars (void) "Toggles fullscreen game mode"); vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, "Use system gamma control if available"); + x11_vidmode = Cvar_Get ("x11_vidmode", "0", CVAR_ROM, 0, + "Use x11 vidmode extension to set video mode " + "(not recommended for modern systems)"); } void From 203d981675fe869fc3eb171ce28b6365d189a045 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Jul 2019 22:18:51 +0900 Subject: [PATCH 0195/3664] Wait for the window to be visible before mouse warping This fixes the hang during fullscreen startup on my system (the motion events weren't being generated because there was no window to see the motion). --- libs/video/targets/context_x11.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 5c23d1875..5a6556ce0 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -574,10 +574,11 @@ X11_CreateWindow (int width, int height) X11_WaitForEvent (ConfigureNotify); vid_context_created = true; + XRaiseWindow (x_disp, x_win); + X11_WaitForEvent (VisibilityNotify); if (vid_fullscreen->int_val) { X11_UpdateFullscreen (vid_fullscreen); } - XRaiseWindow (x_disp, x_win); } void From 4eb6cf6f9ebd1633c57edfc2f6f0667fa7a83912 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Jul 2019 22:24:11 +0900 Subject: [PATCH 0196/3664] Make SetMouse timeout after 2 seconds This makes sure that some unchecked event doesn't cause a lockup. However, blocking input is really not the way to go: need to implement a state machine and use non-blocking event reads. --- libs/video/targets/context_x11.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 5a6556ce0..614f83ebd 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -354,7 +354,14 @@ X11_SetMouse (void) XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, 0, 0); XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, viddef.width / 2, viddef.height / 2); - XPeekIfEvent (x_disp, &ev, check_mouse_event, 0); + //FIXME this should be done in a state machine that handles events without + //blocking + double start = Sys_DoubleTime (); + while (!XCheckIfEvent (x_disp, &ev, check_mouse_event, 0)) { + if (Sys_DoubleTime () - start > 2) { + break; + } + } x_mouse_time = ev.xmotion.time; } From a4f963f67b36920db3aaabccf8b966cb45c26e67 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Jul 2019 22:15:39 +0900 Subject: [PATCH 0197/3664] Add a cvar to block use of x11 vidmode Or really, allow it if the user specifically requests it: the default is blocked. Modern systems (particularly displays) do not really like changing resolution, so doing so by default seems rather wrong. --- libs/video/targets/context_x11.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 41045fcdf..5c23d1875 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -125,6 +125,8 @@ static int accel_threshold; static Atom x_net_state; static Atom x_net_fullscreen; +static cvar_t *x11_vidmode; + static void set_fullscreen (int full) { @@ -387,6 +389,10 @@ X11_SetVidMode (int width, int height) if (vidmode_active) return; + if (!x11_vidmode->int_val) { + return; + } + if (str && (tolower (*str) == 'f')) { Cvar_Set (vid_fullscreen, "1"); } @@ -506,6 +512,9 @@ X11_Init_Cvars (void) "Toggles fullscreen game mode"); vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, "Use system gamma control if available"); + x11_vidmode = Cvar_Get ("x11_vidmode", "0", CVAR_ROM, 0, + "Use x11 vidmode extension to set video mode " + "(not recommended for modern systems)"); } void From 980cf58ac5068c9123c77e1c6d335eefe8e39010 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Jul 2019 22:18:51 +0900 Subject: [PATCH 0198/3664] Wait for the window to be visible before mouse warping This fixes the hang during fullscreen startup on my system (the motion events weren't being generated because there was no window to see the motion). --- libs/video/targets/context_x11.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 5c23d1875..5a6556ce0 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -574,10 +574,11 @@ X11_CreateWindow (int width, int height) X11_WaitForEvent (ConfigureNotify); vid_context_created = true; + XRaiseWindow (x_disp, x_win); + X11_WaitForEvent (VisibilityNotify); if (vid_fullscreen->int_val) { X11_UpdateFullscreen (vid_fullscreen); } - XRaiseWindow (x_disp, x_win); } void From 302a462c32e3e7c78b5afc7d9fcef94b8bed20ed Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Jul 2019 22:24:11 +0900 Subject: [PATCH 0199/3664] Make SetMouse timeout after 2 seconds This makes sure that some unchecked event doesn't cause a lockup. However, blocking input is really not the way to go: need to implement a state machine and use non-blocking event reads. --- libs/video/targets/context_x11.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 5a6556ce0..614f83ebd 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -354,7 +354,14 @@ X11_SetMouse (void) XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, 0, 0); XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, viddef.width / 2, viddef.height / 2); - XPeekIfEvent (x_disp, &ev, check_mouse_event, 0); + //FIXME this should be done in a state machine that handles events without + //blocking + double start = Sys_DoubleTime (); + while (!XCheckIfEvent (x_disp, &ev, check_mouse_event, 0)) { + if (Sys_DoubleTime () - start > 2) { + break; + } + } x_mouse_time = ev.xmotion.time; } From c0bc5cfad609891e383f0a5c25f4d6dc4230acf6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Jul 2019 00:58:14 +0900 Subject: [PATCH 0200/3664] Implement swapchain creation --- include/QF/Vulkan/funclist.h | 15 ++ include/QF/Vulkan/init.h | 1 + include/QF/Vulkan/qf_vid.h | 1 + include/vid_vulkan.h | 3 + libs/video/renderer/vid_render_vulkan.c | 7 + .../video/renderer/vulkan/vulkan_vid_common.c | 140 +++++++++++++++++- 6 files changed, 166 insertions(+), 1 deletion(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index e54ce6f50..8418aeb6a 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -62,6 +62,14 @@ INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION #else INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkCreateDebugUtilsMessengerEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceSurfaceSupportKHR, VK_KHR_SURFACE_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceSurfacePresentModesKHR, VK_KHR_SURFACE_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceSurfaceCapabilitiesKHR, VK_KHR_SURFACE_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceSurfaceFormatsKHR, VK_KHR_SURFACE_EXTENSION_NAME) #endif #undef INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION @@ -79,4 +87,11 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkGetDeviceQueue) #define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(function, extension) #endif +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkCreateSwapchainKHR, VK_KHR_SURFACE_EXTENSION_NAME) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkDestroySwapchainKHR, VK_KHR_SURFACE_EXTENSION_NAME) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetSwapchainImagesKHR, VK_KHR_SURFACE_EXTENSION_NAME) + #undef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION diff --git a/include/QF/Vulkan/init.h b/include/QF/Vulkan/init.h index 961c72d84..0988dd25a 100644 --- a/include/QF/Vulkan/init.h +++ b/include/QF/Vulkan/init.h @@ -32,6 +32,7 @@ typedef struct VulkanDevice_s { VkDevice device; + int32_t queueFamily; VkQueue queue; VkSurfaceKHR surface; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 877bebaa3..fe04da536 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -31,6 +31,7 @@ #include "QF/Vulkan/cvars.h" struct vulkan_ctx_s; +void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); void Vulkan_Shutdown_Common (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 924a3a1d4..fabaa088b 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -27,6 +27,9 @@ typedef struct vulkan_ctx_s { VkInstance instance; VkPhysicalDevice physDevice; VkDevice device; + VkSwapchainKHR swapchain; + int32_t numSwapchainImages; + VkImage *swapchainImages; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 11fe640f2..46d475917 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -159,6 +159,13 @@ vulkan_vid_render_create_context (void) vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->dev->surface = vulkan_ctx->create_surface (vulkan_ctx); Sys_Printf ("%p\n", vulkan_ctx->dev->surface); + Vulkan_CreateSwapchain (vulkan_ctx); + Sys_Printf ("%p %d", vulkan_ctx->swapchain, + vulkan_ctx->numSwapchainImages); + for (int32_t i = 0; i < vulkan_ctx->numSwapchainImages; i++) { + Sys_Printf (" %p", vulkan_ctx->swapchainImages[i]); + } + Sys_Printf ("\n"); } static void diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 561eb64f5..22ce1d71e 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -42,6 +42,7 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/input.h" +#include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" #include "QF/sys.h" @@ -57,6 +58,25 @@ #include "util.h" +static cvar_t *vulkan_presentation_mode; + +static void +vulkan_presentation_mode_f (cvar_t *var) +{ + if (!strcmp (var->string, "immediate")) { + var->int_val = VK_PRESENT_MODE_IMMEDIATE_KHR; + } else if (!strcmp (var->string, "fifo")) { + var->int_val = VK_PRESENT_MODE_FIFO_KHR; + } else if (!strcmp (var->string, "relaxed")) { + var->int_val = VK_PRESENT_MODE_FIFO_RELAXED_KHR; + } else if (!strcmp (var->string, "mailbox")) { + var->int_val = VK_PRESENT_MODE_MAILBOX_KHR; + } else { + Sys_Printf ("Invalid presentation mode, using fifo\n"); + var->int_val = VK_PRESENT_MODE_FIFO_KHR; + } +} + void Vulkan_Init_Cvars () { @@ -65,6 +85,11 @@ Vulkan_Init_Cvars () "enable LunarG Standard Validation " "Layer if available (requires instance " "restart)."); + // FIXME implement fallback choices (instead of just fifo) + vulkan_presentation_mode = Cvar_Get ("vulkan_presentation_mode", "mailbox", + CVAR_NONE, vulkan_presentation_mode_f, + "desired presentation mode (may fall " + "back to fifo)."); } static const char *instance_extensions[] = { @@ -118,7 +143,7 @@ load_device_funcs (VulkanInstance_t *inst, VulkanDevice_t *dev) } #define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ - if (inst->extension_enabled (vtx, ext)) { \ + if (inst->extension_enabled (inst, ext)) { \ dev->name = (PFN_##name) inst->vkGetDeviceProcAddr (dev->device, \ #name); \ if (!dev->name) { \ @@ -208,7 +233,120 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) ctx->dev = device; ctx->device = device->device; ctx->physDevice = phys->device; + device->queueFamily = family; return; } } } + +void +Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) +{ + VkBool32 supported; + ctx->vtx->vkGetPhysicalDeviceSurfaceSupportKHR (ctx->physDevice, + ctx->dev->queueFamily, + ctx->dev->surface, + &supported); + if (!supported) { + Sys_Error ("unsupported surface for swapchain"); + } + uint32_t numModes; + VkPresentModeKHR *modes; + VkPresentModeKHR useMode = VK_PRESENT_MODE_FIFO_KHR;; + ctx->vtx->vkGetPhysicalDeviceSurfacePresentModesKHR (ctx->physDevice, + ctx->dev->surface, + &numModes, 0); + modes = alloca (numModes * sizeof (VkPresentModeKHR)); + ctx->vtx->vkGetPhysicalDeviceSurfacePresentModesKHR (ctx->physDevice, + ctx->dev->surface, + &numModes, modes); + for (uint32_t i = 0; i < numModes; i++) { + if ((int) modes[i] == vulkan_presentation_mode->int_val) { + useMode = modes[i]; + } + } + Sys_MaskPrintf (SYS_VULKAN, "presentation mode: %d (%d)\n", useMode, + vulkan_presentation_mode->int_val); + + VkSurfaceCapabilitiesKHR surfCaps; + ctx->vtx->vkGetPhysicalDeviceSurfaceCapabilitiesKHR (ctx->physDevice, + ctx->dev->surface, + &surfCaps); + uint32_t numImages = surfCaps.minImageCount + 1; + if (surfCaps.maxImageCount > 0 && numImages > surfCaps.maxImageCount) { + numImages = surfCaps.maxImageCount; + } + + VkExtent2D imageSize = {viddef.width, viddef.height}; + if (surfCaps.currentExtent.width == ~0u) { + imageSize.width = bound (surfCaps.minImageExtent.width, + imageSize.width, + surfCaps.maxImageExtent.width); + imageSize.height = bound (surfCaps.minImageExtent.height, + imageSize.height, + surfCaps.maxImageExtent.height); + } else { + imageSize = surfCaps.currentExtent; + } + Sys_MaskPrintf (SYS_VULKAN, "%d [%d, %d]\n", numImages, + imageSize.width, imageSize.height); + + VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageUsage &= surfCaps.supportedUsageFlags; + + VkSurfaceTransformFlagBitsKHR surfTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + + uint32_t numFormats; + ctx->vtx->vkGetPhysicalDeviceSurfaceFormatsKHR (ctx->physDevice, + ctx->dev->surface, + &numFormats, 0); + VkSurfaceFormatKHR *formats = alloca (numFormats * sizeof (*formats)); + ctx->vtx->vkGetPhysicalDeviceSurfaceFormatsKHR (ctx->physDevice, + ctx->dev->surface, + &numFormats, formats); + VkSurfaceFormatKHR useFormat = {VK_FORMAT_R8G8B8A8_UNORM, + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}; + if (numFormats > 1) { + uint32_t i; + for (i = 0; i < numFormats; i++) { + if (formats[i].format == useFormat.format + && formats[i].colorSpace == useFormat.colorSpace) { + break; + } + } + if (i == numFormats) { + useFormat = formats[0]; + } + } else if (numFormats == 1 && formats[0].format != VK_FORMAT_UNDEFINED) { + useFormat = formats[0]; + } + + VkSwapchainCreateInfoKHR createInfo = { + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, 0, 0, + ctx->dev->surface, + numImages, + useFormat.format, useFormat.colorSpace, + imageSize, + 1, // array layers + imageUsage, + VK_SHARING_MODE_EXCLUSIVE, + 0, 0, + surfTransform, + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + useMode, + VK_TRUE, + ctx->swapchain + }; + VkSwapchainKHR swapchain; + ctx->dev->vkCreateSwapchainKHR (ctx->device, &createInfo, 0, &swapchain); + if (ctx->swapchain != swapchain) { + ctx->dev->vkDestroySwapchainKHR (ctx->device, ctx->swapchain, 0); + } + ctx->swapchain = swapchain; + + ctx->dev->vkGetSwapchainImagesKHR (ctx->device, swapchain, &numImages, 0); + ctx->swapchainImages = malloc (numImages * sizeof (*ctx->swapchainImages)); + ctx->dev->vkGetSwapchainImagesKHR (ctx->device, swapchain, &numImages, + ctx->swapchainImages); + ctx->numSwapchainImages = numImages; +} From b5828bc2cefb98e59f533a0bcd8b7dec2ebfbbde Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Jul 2019 00:58:37 +0900 Subject: [PATCH 0201/3664] Output validation message severity It's nice knowing if something is an error or otherwise. --- libs/video/renderer/vulkan/init.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c index 529969014..2ba5bfc06 100644 --- a/libs/video/renderer/vulkan/init.c +++ b/libs/video/renderer/vulkan/init.c @@ -219,7 +219,20 @@ debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void *data) { - fprintf (stderr, "validation layer: %s\n", callbackData->pMessage); + const char *msgSev = ""; + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { + msgSev = "verbose: "; + } + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { + msgSev = "info: "; + } + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { + msgSev = "warning: "; + } + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + msgSev = "error: "; + } + fprintf (stderr, "validation layer: %s%s\n", msgSev, callbackData->pMessage); return VK_FALSE; } From 75f19f724373afb7e6fa0bc00fdda6815f3eb127 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Jul 2019 13:15:25 +0900 Subject: [PATCH 0202/3664] Completely rework the vulkan related api Things don't work yet, but this feels much cleaner. --- include/QF/Vulkan/cvars.h | 1 + include/QF/Vulkan/device.h | 26 ++ include/QF/Vulkan/funclist.h | 52 ++- include/QF/Vulkan/init.h | 88 ---- include/QF/Vulkan/instance.h | 55 +++ include/QF/Vulkan/qf_vid.h | 5 + include/QF/Vulkan/swapchain.h | 17 + include/vid_vulkan.h | 15 +- libs/video/renderer/vid_render_vulkan.c | 18 +- libs/video/renderer/vulkan/Makefile.am | 4 +- libs/video/renderer/vulkan/device.c | 211 +++++++++ libs/video/renderer/vulkan/init.c | 420 ------------------ libs/video/renderer/vulkan/instance.c | 266 +++++++++++ libs/video/renderer/vulkan/swapchain.c | 148 ++++++ libs/video/renderer/vulkan/util.c | 32 +- libs/video/renderer/vulkan/util.h | 8 +- .../video/renderer/vulkan/vulkan_vid_common.c | 238 +--------- libs/video/targets/vid_x11_vulkan.c | 17 +- 18 files changed, 817 insertions(+), 804 deletions(-) create mode 100644 include/QF/Vulkan/device.h delete mode 100644 include/QF/Vulkan/init.h create mode 100644 include/QF/Vulkan/instance.h create mode 100644 include/QF/Vulkan/swapchain.h create mode 100644 libs/video/renderer/vulkan/device.c delete mode 100644 libs/video/renderer/vulkan/init.c create mode 100644 libs/video/renderer/vulkan/instance.c create mode 100644 libs/video/renderer/vulkan/swapchain.c diff --git a/include/QF/Vulkan/cvars.h b/include/QF/Vulkan/cvars.h index b6110e353..706bc44de 100644 --- a/include/QF/Vulkan/cvars.h +++ b/include/QF/Vulkan/cvars.h @@ -2,5 +2,6 @@ #define __QF_Vulkan_cvars_h extern struct cvar_s *vulkan_use_validation; +extern struct cvar_s *vulkan_presentation_mode; #endif//__QF_Vulkan_cvars_h diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h new file mode 100644 index 000000000..ae0c26ffc --- /dev/null +++ b/include/QF/Vulkan/device.h @@ -0,0 +1,26 @@ +#ifndef __QF_Vulkan_device_h +#define __QF_Vulkan_device_h + +typedef struct qfv_devfuncs_s { +#define DEVICE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; +#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; +#include "QF/Vulkan/funclist.h" +} qfv_devfuncs_t; + +struct qfv_instance_s; +typedef struct qfv_device_s { + VkDevice dev; + VkPhysicalDevice physDev; + qfv_devfuncs_t *funcs; + int32_t queueFamily; + VkQueue queue; + struct strset_s *enabled_extensions; + int (*extension_enabled) (struct qfv_device_s *inst, + const char *ext); +} qfv_device_t; + +struct vulkan_ctx_s; +qfv_device_t *QFV_CreateDevice(struct vulkan_ctx_s *ctx, + const char **extensions); + +#endif//__QF_Vulkan_swapchain_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 8418aeb6a..719335699 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -38,28 +38,6 @@ INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties) #define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(function, extension) #endif -#if defined(VK_USE_PLATFORM_XLIB_KHR) -INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION - (vkGetPhysicalDeviceXlibPresentationSupportKHR, - VK_KHR_XLIB_SURFACE_EXTENSION_NAME) -INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION - (vkCreateXlibSurfaceKHR, - VK_KHR_XLIB_SURFACE_EXTENSION_NAME) -#elif defined(VK_USE_PLATFORM_WIN32_KHR) -INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION - (vkGetPhysicalDeviceWin32PresentationSupportKHR, - VK_KHR_WIN32_SURFACE_EXTENSION_NAME) -INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION - (vkCreateWin32SurfaceKHR, - VK_KHR_WIN32_SURFACE_EXTENSION_NAME) -#elif defined(VK_USE_PLATFORM_XCB_KHR) -INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION - (vkGetPhysicalDeviceXcbPresentationSupportKHR, - VK_KHR_XCB_SURFACE_EXTENSION_NAME) -INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION - (vkCreateXcbSurfaceKHR, - VK_KHR_XCB_SURFACE_EXTENSION_NAME) -#else INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkCreateDebugUtilsMessengerEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION @@ -70,10 +48,38 @@ INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkGetPhysicalDeviceSurfaceCapabilitiesKHR, VK_KHR_SURFACE_EXTENSION_NAME) INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkGetPhysicalDeviceSurfaceFormatsKHR, VK_KHR_SURFACE_EXTENSION_NAME) -#endif #undef INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION +#ifndef PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION +#define PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION(function, extension) +#endif + +#if defined(VK_USE_PLATFORM_XLIB_KHR) +PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceXlibPresentationSupportKHR, + VK_KHR_XLIB_SURFACE_EXTENSION_NAME) +PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION + (vkCreateXlibSurfaceKHR, + VK_KHR_XLIB_SURFACE_EXTENSION_NAME) +#elif defined(VK_USE_PLATFORM_WIN32_KHR) +PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceWin32PresentationSupportKHR, + VK_KHR_WIN32_SURFACE_EXTENSION_NAME) +PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION + (vkCreateWin32SurfaceKHR, + VK_KHR_WIN32_SURFACE_EXTENSION_NAME) +#elif defined(VK_USE_PLATFORM_XCB_KHR) +PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION + (vkGetPhysicalDeviceXcbPresentationSupportKHR, + VK_KHR_XCB_SURFACE_EXTENSION_NAME) +PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION + (vkCreateXcbSurfaceKHR, + VK_KHR_XCB_SURFACE_EXTENSION_NAME) +#endif + +#undef PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION + #ifndef DEVICE_LEVEL_VULKAN_FUNCTION #define DEVICE_LEVEL_VULKAN_FUNCTION(function) #endif diff --git a/include/QF/Vulkan/init.h b/include/QF/Vulkan/init.h deleted file mode 100644 index 0988dd25a..000000000 --- a/include/QF/Vulkan/init.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - Copyright (C) 2019 Bill Currie - - Author: Bill Currie - Date: 2019/6/29 - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifndef __QF_Vulkan_init_h -#define __QF_Vulkan_init_h - -#include - -#include "QF/qtypes.h" - -typedef struct VulkanDevice_s { - VkDevice device; - int32_t queueFamily; - VkQueue queue; - VkSurfaceKHR surface; - -#define DEVICE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; -#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; -#include "QF/Vulkan/funclist.h" -} VulkanDevice_t; - -typedef struct { - VkPhysicalDevice device; - VkPhysicalDeviceFeatures features; - VkPhysicalDeviceProperties properties; - uint32_t numLayers; - VkLayerProperties *layers; - uint32_t numExtensions; - VkExtensionProperties *extensions; - VkPhysicalDeviceMemoryProperties memory; - uint32_t numQueueFamilies; - VkQueueFamilyProperties *queueFamilies; -} VulkanPhysDevice_t; - -typedef struct VulkanInstance_s { - VkInstance instance; - struct strset_s *enabled_extensions; - int (*extension_enabled) (struct VulkanInstance_s *inst, - const char *ext); - VkDebugUtilsMessengerEXT debug_callback; - uint32_t numDevices; - VulkanPhysDevice_t *devices; - -#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; -#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; -#include "QF/Vulkan/funclist.h" -} VulkanInstance_t; - -extern const char * const vulkanValidationLayers[]; - -void Vulkan_Init_Cvars (void); -struct vulkan_ctx_s; -VulkanInstance_t *Vulkan_CreateInstance (struct vulkan_ctx_s *ctx, - const char *appName, - uint32_t appVersion, - const char **layers, - const char **extensions); -void Vulkan_DestroyInstance (VulkanInstance_t *instance); -int Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions, - int numExtensions, - const char * const *requested); -int Vulkan_LayersSupported (const VkLayerProperties *extensions, - int numLayers, - const char * const *requested); - -#endif // __QF_Vulkan_init_h diff --git a/include/QF/Vulkan/instance.h b/include/QF/Vulkan/instance.h new file mode 100644 index 000000000..1cc05d6cf --- /dev/null +++ b/include/QF/Vulkan/instance.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2019 Bill Currie + + Author: Bill Currie + Date: 2019/6/29 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_instance_h +#define __QF_Vulkan_instance_h + +#include + +#include "QF/qtypes.h" + +typedef struct qfv_instfuncs_s { +#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; +#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; +#include "QF/Vulkan/funclist.h" +} qfv_instfuncs_t; + +typedef struct qfv_instance_s { + VkInstance instance; + qfv_instfuncs_t *funcs; + struct strset_s *enabled_extensions; + int (*extension_enabled) (struct qfv_instance_s *inst, + const char *ext); +} qfv_instance_t; + +struct vulkan_ctx_s; +qfv_instance_t *QFV_CreateInstance (struct vulkan_ctx_s *ctx, + const char *appName, + uint32_t appVersion, + const char **layers, + const char **extensions); +void QFV_DestroyInstance (qfv_instance_t *instance); + +#endif // __QF_Vulkan_instance_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index fe04da536..bfa543c46 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -30,6 +30,11 @@ #include "QF/Vulkan/cvars.h" +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + struct vulkan_ctx_s; void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/swapchain.h b/include/QF/Vulkan/swapchain.h new file mode 100644 index 000000000..71d0b6d75 --- /dev/null +++ b/include/QF/Vulkan/swapchain.h @@ -0,0 +1,17 @@ +#ifndef __QF_Vulkan_swapchain_h +#define __QF_Vulkan_swapchain_h + +typedef struct qfv_swapchain_s { + VkDevice dev; + struct qfv_devfuncs_s *funcs; + VkSurfaceKHR surface; + VkSwapchainKHR swapchain; + int32_t numImages; + VkImage *images; +} qfv_swapchain_t; + +struct vulkan_ctx_s; +qfv_swapchain_t *QFV_CreateSwapchain (struct vulkan_ctx_s *ctx, + VkSwapchainKHR old_swapchain); + +#endif//__QF_Vulkan_swapchain_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index fabaa088b..9cfb3ad8a 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -6,14 +6,11 @@ #endif #include -struct VulkanInstance_s; typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); void (*unload_vulkan) (struct vulkan_ctx_s *ctx); const char **required_extensions; - int (*extension_enabled) (struct VulkanInstance_s *inst, - const char *ext); struct vulkan_presentation_s *presentation; int (*get_presentation_support) (struct vulkan_ctx_s *ctx, VkPhysicalDevice physicalDevice, @@ -22,14 +19,10 @@ typedef struct vulkan_ctx_s { void (*create_window) (struct vulkan_ctx_s *ctx); VkSurfaceKHR (*create_surface) (struct vulkan_ctx_s *ctx); - struct VulkanInstance_s *vtx; - struct VulkanDevice_s *dev; - VkInstance instance; - VkPhysicalDevice physDevice; - VkDevice device; - VkSwapchainKHR swapchain; - int32_t numSwapchainImages; - VkImage *swapchainImages; + struct qfv_instance_s *instance; + struct qfv_device_s *device; + struct qfv_swapchain_s *swapchain; + VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 46d475917..506406394 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -37,7 +37,9 @@ #include "QF/plugin/vid_render.h" #include "QF/Vulkan/qf_vid.h" -#include "QF/Vulkan/init.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/swapchain.h" #include "mod_internal.h" #include "r_internal.h" @@ -150,20 +152,20 @@ vulkan_vid_render_choose_visual (void) { Vulkan_CreateDevice (vulkan_ctx); vulkan_ctx->choose_visual (vulkan_ctx); - Sys_Printf ("%p %p\n", vulkan_ctx->dev->device, vulkan_ctx->dev->queue); + Sys_Printf ("%p %p\n", vulkan_ctx->device->dev, vulkan_ctx->device->queue); } static void vulkan_vid_render_create_context (void) { vulkan_ctx->create_window (vulkan_ctx); - vulkan_ctx->dev->surface = vulkan_ctx->create_surface (vulkan_ctx); - Sys_Printf ("%p\n", vulkan_ctx->dev->surface); + vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); + Sys_Printf ("%p\n", vulkan_ctx->surface); Vulkan_CreateSwapchain (vulkan_ctx); - Sys_Printf ("%p %d", vulkan_ctx->swapchain, - vulkan_ctx->numSwapchainImages); - for (int32_t i = 0; i < vulkan_ctx->numSwapchainImages; i++) { - Sys_Printf (" %p", vulkan_ctx->swapchainImages[i]); + Sys_Printf ("%p %d", vulkan_ctx->swapchain->swapchain, + vulkan_ctx->swapchain->numImages); + for (int32_t i = 0; i < vulkan_ctx->swapchain->numImages; i++) { + Sys_Printf (" %p", vulkan_ctx->swapchain->images[i]); } Sys_Printf ("\n"); } diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index b134d1f91..e59e29551 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -4,7 +4,9 @@ AM_CFLAGS= @PREFER_PIC@ AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES vulkan_src = \ - init.c \ + device.c \ + instance.c \ + swapchain.c \ util.c \ vulkan_draw.c \ vulkan_vid_common.c diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c new file mode 100644 index 000000000..1579c0633 --- /dev/null +++ b/libs/video/renderer/vulkan/device.c @@ -0,0 +1,211 @@ +/* + vid_common_vulkan.c + + Common Vulkan video driver functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2019 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +static int +count_bits (uint32_t val) +{ + int bits = 0; + while (val) { + bits += val & 1; + val >>= 1; + } + return bits; +} + +static int +find_queue_family (qfv_instance_t *instance, VkPhysicalDevice dev, + uint32_t flags) +{ + qfv_instfuncs_t *funcs = instance->funcs; + uint32_t numFamilies; + VkQueueFamilyProperties *queueFamilies; + int best_diff = 32; + uint32_t family = -1; + + funcs->vkGetPhysicalDeviceQueueFamilyProperties (dev, &numFamilies, 0); + queueFamilies = alloca (numFamilies * sizeof (*queueFamilies)); + funcs->vkGetPhysicalDeviceQueueFamilyProperties (dev, &numFamilies, + queueFamilies); + + for (uint32_t i = 0; i < numFamilies; i++) { + VkQueueFamilyProperties *queue = &queueFamilies[i]; + + if ((queue->queueFlags & flags) == flags) { + int diff = count_bits (queue->queueFlags & ~flags); + if (diff < best_diff) { + best_diff = diff; + family = i; + } + } + } + return family; +} + +static void +load_device_funcs (qfv_instance_t *inst, qfv_device_t *dev) +{ + qfv_instfuncs_t *ifunc = inst->funcs; + qfv_devfuncs_t *dfunc = dev->funcs; + VkDevice device = dev->dev; +#define DEVICE_LEVEL_VULKAN_FUNCTION(name) \ + dfunc->name = (PFN_##name) ifunc->vkGetDeviceProcAddr (device, #name); \ + if (!dfunc->name) { \ + Sys_Error ("Couldn't find device level function %s", #name); \ + } + +#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ + if (dev->extension_enabled (dev, ext)) { \ + dfunc->name = (PFN_##name) ifunc->vkGetDeviceProcAddr (device, #name); \ + if (!dfunc->name) { \ + Sys_Printf ("Couldn't find device level function %s", #name); \ + } \ + } + +#include "QF/Vulkan/funclist.h" +} + +static int +device_extension_enabled (qfv_device_t *device, const char *ext) +{ + return strset_contains (device->enabled_extensions, ext); +} + +qfv_device_t * +QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) +{ + uint32_t nlay = 1; // ensure alloca doesn't see 0 and terminated + uint32_t next = count_strings (extensions) + 1; // ensure terminated + //if (vulkan_use_validation->int_val) { + // nlay += count_strings (vulkanValidationLayers); + //} + const char **lay = alloca (nlay * sizeof (const char *)); + const char **ext = alloca (next * sizeof (const char *)); + // ensure there are null pointers so merge_strings can act as append + // since it does not add a null, but also make sure the counts reflect + // actual numbers + memset (lay, 0, nlay-- * sizeof (const char *)); + memset (ext, 0, next-- * sizeof (const char *)); + merge_strings (ext, extensions, 0); + //if (vulkan_use_validation->int_val) { + // merge_strings (lay, lay, vulkanValidationLayers); + //} + + qfv_instance_t *inst = ctx->instance; + VkInstance instance = inst->instance; + qfv_instfuncs_t *ifunc = inst->funcs; + + uint32_t numDevices; + ifunc->vkEnumeratePhysicalDevices (instance, &numDevices, 0); + VkPhysicalDevice *devices = alloca (numDevices * sizeof (*devices)); + ifunc->vkEnumeratePhysicalDevices (instance, &numDevices, devices); + + for (uint32_t i = 0; i < numDevices; i++) { + VkPhysicalDevice physdev = devices[i]; + /* + if (!Vulkan_LayersSupported (phys->layers, phys->numLayers, lay)) { + continue; + } + if (!Vulkan_ExtensionsSupported (phys->extensions, phys->numExtensions, + ext)) { + continue; + } + */ + int family = find_queue_family (inst, physdev, VK_QUEUE_GRAPHICS_BIT); + if (family < 0) { + continue; + } + if (!ctx->get_presentation_support (ctx, physdev, family)) { + continue; + } + float priority = 1; + VkDeviceQueueCreateInfo qCreateInfo = { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, + family, 1, &priority + }; + VkPhysicalDeviceFeatures features; + VkDeviceCreateInfo dCreateInfo = { + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0, + 1, &qCreateInfo, + nlay, lay, + next, ext, + &features + }; + memset (&features, 0, sizeof (features)); + qfv_device_t *device = calloc (1, sizeof (qfv_device_t) + + sizeof (qfv_devfuncs_t)); + device->funcs = (qfv_devfuncs_t *) (device + 1); + if (ifunc->vkCreateDevice (physdev, &dCreateInfo, 0, + &device->dev) == VK_SUCCESS) { + qfv_devfuncs_t *dfunc = device->funcs; + + device->physDev = physdev; + load_device_funcs (inst, device); + device->queueFamily = family; + dfunc->vkGetDeviceQueue (device->dev, family, 0, &device->queue); + device->enabled_extensions = new_strset (ext); + device->extension_enabled = device_extension_enabled; + ctx->device = device; + return device; + } + free (device); + } + return 0; +} diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c deleted file mode 100644 index 2ba5bfc06..000000000 --- a/libs/video/renderer/vulkan/init.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - init.c - - Copyright (C) 2019 Bill Currie - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cvar.h" -#include "QF/dstring.h" -#include "QF/input.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" -#include "QF/Vulkan/init.h" - -#include "vid_vulkan.h" - -#include "util.h" - -cvar_t *vulkan_use_validation; - -static uint32_t numLayers; -static VkLayerProperties *instanceLayerProperties; -static const char **instanceLayerNames; -static uint32_t numExtensions; -static VkExtensionProperties *instanceExtensionProperties; -static const char **instanceExtensionNames; - -const char * const vulkanValidationLayers[] = { - "VK_LAYER_LUNARG_standard_validation", - 0, -}; - -static const char * const debugExtensions[] = { - VK_EXT_DEBUG_UTILS_EXTENSION_NAME, - 0, -}; - -static const char * const device_types[] = { - "other", - "integrated gpu", - "discrete gpu", - "virtual gpu", - "cpu", -}; - -static void -get_instance_layers_and_extensions (vulkan_ctx_t *ctx) -{ - uint32_t i; - VkLayerProperties *properties; - VkExtensionProperties *extensions; - - ctx->vkEnumerateInstanceLayerProperties (&numLayers, 0); - properties = malloc (numLayers * sizeof (VkLayerProperties)); - ctx->vkEnumerateInstanceLayerProperties (&numLayers, properties); - instanceLayerNames = (const char **) malloc ((numLayers + 1) - * sizeof (const char **)); - for (i = 0; i < numLayers; i++) { - instanceLayerNames[i] = properties[i].layerName; - } - instanceLayerNames[i] = 0; - - ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, 0); - extensions = malloc (numExtensions * sizeof (VkLayerProperties)); - ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, - extensions); - instanceExtensionNames = (const char **) malloc ((numExtensions + 1) - * sizeof (const char **)); - for (i = 0; i < numExtensions; i++) { - instanceExtensionNames[i] = extensions[i].extensionName; - } - instanceExtensionNames[i] = 0; - - if (developer->int_val & SYS_VULKAN) { - for (i = 0; i < numLayers; i++) { - Sys_Printf ("%s %x %u %s\n", - properties[i].layerName, - properties[i].specVersion, - properties[i].implementationVersion, - properties[i].description); - } - for (i = 0; i < numExtensions; i++) { - Sys_Printf ("%d %s\n", - extensions[i].specVersion, - extensions[i].extensionName); - } - } - instanceLayerProperties = properties; - instanceExtensionProperties = extensions; -} - -static void -init_physdev (VulkanInstance_t *instance, VkPhysicalDevice dev, VulkanPhysDevice_t *physdev) -{ - physdev->device = dev; - - instance->vkGetPhysicalDeviceProperties (dev, &physdev->properties); - - instance->vkEnumerateDeviceLayerProperties (dev, &physdev->numLayers, 0); - physdev->layers = malloc (physdev->numLayers * sizeof (VkLayerProperties)); - instance->vkEnumerateDeviceLayerProperties (dev, &physdev->numLayers, - physdev->layers); - - instance->vkEnumerateDeviceExtensionProperties (dev, 0, - &physdev->numExtensions, - 0); - physdev->extensions = malloc (physdev->numExtensions - * sizeof (VkExtensionProperties)); - instance->vkEnumerateDeviceExtensionProperties (dev, 0, - &physdev->numExtensions, - physdev->extensions); - - instance->vkGetPhysicalDeviceFeatures (dev, &physdev->features); - - instance->vkGetPhysicalDeviceMemoryProperties (dev, &physdev->memory); - - instance->vkGetPhysicalDeviceQueueFamilyProperties (dev, - &physdev->numQueueFamilies, - 0); - physdev->queueFamilies = malloc (physdev->numQueueFamilies - * sizeof (VkQueueFamilyProperties)); - instance->vkGetPhysicalDeviceQueueFamilyProperties (dev, - &physdev->numQueueFamilies, - physdev->queueFamilies); - - if (developer->int_val & SYS_VULKAN) { - VkPhysicalDeviceProperties *prop = &physdev->properties; - Sys_Printf ("dev: %p\n", dev); - Sys_Printf (" %x %x\n", prop->apiVersion, prop->driverVersion); - Sys_Printf (" %x %x\n", prop->vendorID, prop->deviceID); - Sys_Printf (" %s: %s\n", device_types[prop->deviceType], - prop->deviceName); - for (uint32_t i = 0; i < physdev->numLayers; i++) { - Sys_Printf (" %s %x %u %s\n", - physdev->layers[i].layerName, - physdev->layers[i].specVersion, - physdev->layers[i].implementationVersion, - physdev->layers[i].description); - } - for (uint32_t i = 0; i < physdev->numExtensions; i++) { - Sys_Printf (" %u %s\n", - physdev->extensions[i].specVersion, - physdev->extensions[i].extensionName); - } - Sys_Printf (" memory types:\n"); - for (uint32_t i = 0; i < physdev->memory.memoryTypeCount; i++) { - Sys_Printf (" %x %d\n", - physdev->memory.memoryTypes[i].propertyFlags, - physdev->memory.memoryTypes[i].heapIndex); - } - Sys_Printf (" memory heaps:\n"); - for (uint32_t i = 0; i < physdev->memory.memoryHeapCount; i++) { - Sys_Printf (" %x %ld\n", - physdev->memory.memoryHeaps[i].flags, - physdev->memory.memoryHeaps[i].size); - } - Sys_Printf (" queue families:\n"); - for (uint32_t i = 0; i < physdev->numQueueFamilies; i++) { - VkQueueFamilyProperties *queue = &physdev->queueFamilies[i]; - VkExtent3D gran = queue->minImageTransferGranularity; - Sys_Printf (" %x %3d %3d [%d %d %d]\n", - queue->queueFlags, - queue->queueCount, - queue->timestampValidBits, - gran.width, gran.height, gran.depth); - } - } -} - -static int -instance_extension_enabled (VulkanInstance_t *inst, const char *ext) -{ - return strset_contains (inst->enabled_extensions, ext); -} - -static int message_severities = - VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; -static int message_types = - VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; - -static VKAPI_ATTR VkBool32 VKAPI_CALL -debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageType, - const VkDebugUtilsMessengerCallbackDataEXT* callbackData, - void *data) -{ - const char *msgSev = ""; - if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { - msgSev = "verbose: "; - } - if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { - msgSev = "info: "; - } - if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { - msgSev = "warning: "; - } - if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { - msgSev = "error: "; - } - fprintf (stderr, "validation layer: %s%s\n", msgSev, callbackData->pMessage); - return VK_FALSE; -} - -static void -setup_debug_callback (VulkanInstance_t *instance) -{ - VkDebugUtilsMessengerCreateInfoEXT createInfo = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = message_severities, - .messageType = message_types, - .pfnUserCallback = debug_callback, - .pUserData = instance, - }; - instance->vkCreateDebugUtilsMessengerEXT(instance->instance, &createInfo, - 0, &instance->debug_callback); -} - -static void -load_instance_funcs (vulkan_ctx_t *ctx) -{ - VulkanInstance_t *vtx = ctx->vtx; - VkInstance instance = vtx->instance; -#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) \ - vtx->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, #name); \ - if (!vtx->name) { \ - Sys_Error ("Couldn't find instance level function %s", #name); \ - } - -#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ - if (vtx->extension_enabled (vtx, ext)) { \ - vtx->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, \ - #name); \ - if (!vtx->name) { \ - Sys_Error ("Couldn't find instance level function %s", #name); \ - } \ - } - -#include "QF/Vulkan/funclist.h" -} - -VulkanInstance_t * -Vulkan_CreateInstance (vulkan_ctx_t *ctx, - const char *appName, uint32_t appVersion, - const char **layers, const char **extensions) -{ - VkApplicationInfo appInfo = { - VK_STRUCTURE_TYPE_APPLICATION_INFO, 0, - appName, appVersion, - PACKAGE_STRING, 0x000702ff, //FIXME version - VK_API_VERSION_1_0, - }; - VkInstanceCreateInfo createInfo = { - VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 0, 0, - &appInfo, - 0, 0, - 0, 0, - }; - VkResult res; - VkInstance instance; - uint32_t numDev, i; - VkPhysicalDevice *devices; - VulkanInstance_t *inst; - - if (!instanceLayerProperties) { - get_instance_layers_and_extensions (ctx); - } - - uint32_t nlay = count_strings (layers) + 1; - uint32_t next = count_strings (extensions) - + count_strings (ctx->required_extensions) + 1; - if (vulkan_use_validation->int_val) { - nlay += count_strings (vulkanValidationLayers); - next += count_strings (debugExtensions); - } - const char **lay = alloca (nlay * sizeof (const char *)); - const char **ext = alloca (next * sizeof (const char *)); - // ensure there are null pointers so merge_strings can act as append - // since it does not add a null - memset (lay, 0, nlay-- * sizeof (const char *)); - memset (ext, 0, next-- * sizeof (const char *)); - merge_strings (lay, layers, 0); - merge_strings (ext, extensions, ctx->required_extensions); - if (vulkan_use_validation->int_val) { - merge_strings (lay, lay, vulkanValidationLayers); - merge_strings (ext, ext, debugExtensions); - } - prune_strings (instanceLayerNames, lay, &nlay); - prune_strings (instanceExtensionNames, ext, &next); - lay[nlay] = 0; - ext[next] = 0; - createInfo.enabledLayerCount = nlay; - createInfo.ppEnabledLayerNames = lay; - createInfo.enabledExtensionCount = next; - createInfo.ppEnabledExtensionNames = ext; - - res = ctx->vkCreateInstance (&createInfo, 0, &instance); - if (res != VK_SUCCESS) { - Sys_Error ("unable to create vulkan instance\n"); - } - inst = malloc (sizeof(VulkanInstance_t)); - inst->instance = instance; - inst->enabled_extensions = new_strset (ext); - inst->extension_enabled = instance_extension_enabled; - ctx->extension_enabled = instance_extension_enabled; - ctx->vtx = inst; - load_instance_funcs (ctx); - - if (vulkan_use_validation->int_val) { - setup_debug_callback (inst); - } - - res = inst->vkEnumeratePhysicalDevices (instance, &numDev, 0); - if (res != VK_SUCCESS) { - Sys_Error ("unable to query vulkan device count: %d\n", res); - } - devices = malloc(numDev * sizeof (VkPhysicalDevice)); - res = inst->vkEnumeratePhysicalDevices (instance, &numDev, devices); - if (res != VK_SUCCESS) { - Sys_Error ("unable to query vulkan device properties: %d\n", res); - } - - inst->numDevices = numDev; - inst->devices = malloc (numDev * sizeof (VulkanPhysDevice_t)); - - for (i = 0; i < numDev; i++) { - init_physdev (inst, devices[i], &inst->devices[i]); - } - - return inst; -} - -void -Vulkan_DestroyInstance (VulkanInstance_t *instance) -{ - for (uint32_t i = 0; i < instance->numDevices; i++) { - free (instance->devices[i].queueFamilies); - free (instance->devices[i].extensions); - free (instance->devices[i].layers); - } - free (instance->devices); - instance->vkDestroyInstance (instance->instance, 0); - free (instance); -} - -int -Vulkan_LayersSupported (const VkLayerProperties *layers, - int numLayers, - const char * const *requested) -{ - while (*requested) { - int i; - for (i = 0; i < numLayers; i++) { - if (!strcmp (*requested, layers[i].layerName)) { - break; - } - } - if (i == numLayers) { - // requested layer not found - break; - } - requested++; - } - return !*requested; -} - -int -Vulkan_ExtensionsSupported (const VkExtensionProperties *extensions, - int numExtensions, - const char * const *requested) -{ - while (*requested) { - int i; - for (i = 0; i < numExtensions; i++) { - if (!strcmp (*requested, extensions[i].extensionName)) { - break; - } - } - if (i == numExtensions) { - // requested extension not found - break; - } - requested++; - } - return !*requested; -} diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c new file mode 100644 index 000000000..74b0ea756 --- /dev/null +++ b/libs/video/renderer/vulkan/instance.c @@ -0,0 +1,266 @@ +/* + init.c + + Copyright (C) 2019 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/instance.h" + +#include "vid_vulkan.h" + +#include "util.h" + +cvar_t *vulkan_use_validation; + +static uint32_t numLayers; +static VkLayerProperties *instanceLayerProperties; +static strset_t *instanceLayers; + +static uint32_t numExtensions; +static VkExtensionProperties *instanceExtensionProperties; +static strset_t *instanceExtensions; + +const char * const vulkanValidationLayers[] = { + "VK_LAYER_LUNARG_standard_validation", + 0, +}; + +static const char * const debugExtensions[] = { + VK_EXT_DEBUG_UTILS_EXTENSION_NAME, + 0, +}; + +static void +get_instance_layers_and_extensions (vulkan_ctx_t *ctx) +{ + uint32_t i; + VkLayerProperties *layers; + VkExtensionProperties *extensions; + + ctx->vkEnumerateInstanceLayerProperties (&numLayers, 0); + layers = malloc (numLayers * sizeof (VkLayerProperties)); + ctx->vkEnumerateInstanceLayerProperties (&numLayers, layers); + instanceLayers = new_strset (0); + for (i = 0; i < numLayers; i++) { + strset_add (instanceLayers, layers[i].layerName); + } + + ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, 0); + extensions = malloc (numExtensions * sizeof (VkLayerProperties)); + ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, + extensions); + instanceExtensions = new_strset (0); + for (i = 0; i < numExtensions; i++) { + strset_add (instanceExtensions, extensions[i].extensionName); + } + + if (developer->int_val & SYS_VULKAN) { + for (i = 0; i < numLayers; i++) { + Sys_Printf ("%s %x %u %s\n", + layers[i].layerName, + layers[i].specVersion, + layers[i].implementationVersion, + layers[i].description); + } + for (i = 0; i < numExtensions; i++) { + Sys_Printf ("%d %s\n", + extensions[i].specVersion, + extensions[i].extensionName); + } + } + instanceLayerProperties = layers; + instanceExtensionProperties = extensions; +} + +static int +instance_extension_enabled (qfv_instance_t *inst, const char *ext) +{ + return strset_contains (inst->enabled_extensions, ext); +} + +static int message_severities = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; +static int message_types = + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + +static VKAPI_ATTR VkBool32 VKAPI_CALL +debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* callbackData, + void *data) +{ + const char *msgSev = ""; + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { + msgSev = "verbose: "; + } + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { + msgSev = "info: "; + } + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { + msgSev = "warning: "; + } + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + msgSev = "error: "; + } + fprintf (stderr, "validation layer: %s%s\n", msgSev, callbackData->pMessage); + return VK_FALSE; +} + +static void +setup_debug_callback (qfv_instance_t *instance) +{ + VkDebugUtilsMessengerEXT debug_callback_handle; + VkDebugUtilsMessengerCreateInfoEXT createInfo = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .messageSeverity = message_severities, + .messageType = message_types, + .pfnUserCallback = debug_callback, + .pUserData = instance, + }; + instance->funcs->vkCreateDebugUtilsMessengerEXT(instance->instance, + &createInfo, 0, + &debug_callback_handle); +} + +static void +load_instance_funcs (vulkan_ctx_t *ctx) +{ + qfv_instance_t *instance = ctx->instance; + qfv_instfuncs_t *funcs = instance->funcs; + VkInstance inst = instance->instance; +#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) \ + funcs->name = (PFN_##name) ctx->vkGetInstanceProcAddr (inst, #name); \ + if (!funcs->name) { \ + Sys_Error ("Couldn't find instance level function %s", #name); \ + } + +#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ + if (instance->extension_enabled (instance, ext)) { \ + funcs->name = (PFN_##name) ctx->vkGetInstanceProcAddr (inst, #name); \ + if (!funcs->name) { \ + Sys_Error ("Couldn't find instance level function %s", #name); \ + } \ + } + +#include "QF/Vulkan/funclist.h" +} + +qfv_instance_t * +QFV_CreateInstance (vulkan_ctx_t *ctx, + const char *appName, uint32_t appVersion, + const char **layers, const char **extensions) +{ + VkApplicationInfo appInfo = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, 0, + appName, appVersion, + PACKAGE_STRING, 0x000702ff, //FIXME version + VK_API_VERSION_1_0, + }; + VkInstanceCreateInfo createInfo = { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 0, 0, + &appInfo, + 0, 0, + 0, 0, + }; + VkResult res; + VkInstance instance; + + if (!instanceLayerProperties) { + get_instance_layers_and_extensions (ctx); + } + + uint32_t nlay = count_strings (layers) + 1; + uint32_t next = count_strings (extensions) + + count_strings (ctx->required_extensions) + 1; + if (vulkan_use_validation->int_val) { + nlay += count_strings (vulkanValidationLayers); + next += count_strings (debugExtensions); + } + const char **lay = alloca (nlay * sizeof (const char *)); + const char **ext = alloca (next * sizeof (const char *)); + // ensure there are null pointers so merge_strings can act as append + // since it does not add a null + memset (lay, 0, nlay-- * sizeof (const char *)); + memset (ext, 0, next-- * sizeof (const char *)); + merge_strings (lay, layers, 0); + merge_strings (ext, extensions, ctx->required_extensions); + if (vulkan_use_validation->int_val) { + merge_strings (lay, lay, vulkanValidationLayers); + merge_strings (ext, ext, debugExtensions); + } + prune_strings (instanceLayers, lay, &nlay); + prune_strings (instanceExtensions, ext, &next); + lay[nlay] = 0; + ext[next] = 0; + createInfo.enabledLayerCount = nlay; + createInfo.ppEnabledLayerNames = lay; + createInfo.enabledExtensionCount = next; + createInfo.ppEnabledExtensionNames = ext; + + res = ctx->vkCreateInstance (&createInfo, 0, &instance); + if (res != VK_SUCCESS) { + Sys_Error ("unable to create vulkan instance\n"); + } + qfv_instance_t *inst = malloc (sizeof(qfv_instance_t) + + sizeof (qfv_instfuncs_t)); + inst->instance = instance; + inst->funcs = (qfv_instfuncs_t *)(inst + 1); + inst->enabled_extensions = new_strset (ext); + inst->extension_enabled = instance_extension_enabled; + ctx->instance = inst; + load_instance_funcs (ctx); + + if (vulkan_use_validation->int_val) { + setup_debug_callback (inst); + } + + return inst; +} + +void +QFV_DestroyInstance (qfv_instance_t *instance) +{ + instance->funcs->vkDestroyInstance (instance->instance, 0); + free (instance); +} diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c new file mode 100644 index 000000000..91f8280c9 --- /dev/null +++ b/libs/video/renderer/vulkan/swapchain.c @@ -0,0 +1,148 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/mathlib.h" +#include "QF/sys.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/cvars.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/swapchain.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +qfv_swapchain_t * +QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) +{ + qfv_instfuncs_t *ifuncs = ctx->instance->funcs; + qfv_devfuncs_t *dfuncs = ctx->device->funcs; + + VkBool32 supported; + ifuncs->vkGetPhysicalDeviceSurfaceSupportKHR (ctx->device->physDev, + ctx->device->queueFamily, + ctx->surface, + &supported); + if (!supported) { + Sys_Error ("unsupported surface for swapchain"); + } + + uint32_t numModes; + VkPresentModeKHR *modes; + VkPresentModeKHR useMode = VK_PRESENT_MODE_FIFO_KHR;; + ifuncs->vkGetPhysicalDeviceSurfacePresentModesKHR (ctx->device->physDev, + ctx->surface, + &numModes, 0); + modes = alloca (numModes * sizeof (VkPresentModeKHR)); + ifuncs->vkGetPhysicalDeviceSurfacePresentModesKHR (ctx->device->physDev, + ctx->surface, + &numModes, modes); + for (uint32_t i = 0; i < numModes; i++) { + if ((int) modes[i] == vulkan_presentation_mode->int_val) { + useMode = modes[i]; + } + } + Sys_MaskPrintf (SYS_VULKAN, "presentation mode: %d (%d)\n", useMode, + vulkan_presentation_mode->int_val); + + VkSurfaceCapabilitiesKHR surfCaps; + ifuncs->vkGetPhysicalDeviceSurfaceCapabilitiesKHR (ctx->device->physDev, + ctx->surface, + &surfCaps); + uint32_t numImages = surfCaps.minImageCount + 1; + if (surfCaps.maxImageCount > 0 && numImages > surfCaps.maxImageCount) { + numImages = surfCaps.maxImageCount; + } + + VkExtent2D imageSize = {viddef.width, viddef.height}; + if (surfCaps.currentExtent.width == ~0u) { + imageSize.width = bound (surfCaps.minImageExtent.width, + imageSize.width, + surfCaps.maxImageExtent.width); + imageSize.height = bound (surfCaps.minImageExtent.height, + imageSize.height, + surfCaps.maxImageExtent.height); + } else { + imageSize = surfCaps.currentExtent; + } + Sys_MaskPrintf (SYS_VULKAN, "%d [%d, %d]\n", numImages, + imageSize.width, imageSize.height); + + VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageUsage &= surfCaps.supportedUsageFlags; + + VkSurfaceTransformFlagBitsKHR surfTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + + uint32_t numFormats; + ifuncs->vkGetPhysicalDeviceSurfaceFormatsKHR (ctx->device->physDev, + ctx->surface, + &numFormats, 0); + VkSurfaceFormatKHR *formats = alloca (numFormats * sizeof (*formats)); + ifuncs->vkGetPhysicalDeviceSurfaceFormatsKHR (ctx->device->physDev, + ctx->surface, + &numFormats, formats); + VkSurfaceFormatKHR useFormat = {VK_FORMAT_R8G8B8A8_UNORM, + VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}; + if (numFormats > 1) { + uint32_t i; + for (i = 0; i < numFormats; i++) { + if (formats[i].format == useFormat.format + && formats[i].colorSpace == useFormat.colorSpace) { + break; + } + } + if (i == numFormats) { + useFormat = formats[0]; + } + } else if (numFormats == 1 && formats[0].format != VK_FORMAT_UNDEFINED) { + useFormat = formats[0]; + } + + VkSwapchainCreateInfoKHR createInfo = { + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, 0, 0, + ctx->surface, + numImages, + useFormat.format, useFormat.colorSpace, + imageSize, + 1, // array layers + imageUsage, + VK_SHARING_MODE_EXCLUSIVE, + 0, 0, + surfTransform, + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + useMode, + VK_TRUE, + old_swapchain + }; + + VkDevice device = ctx->device->dev; + VkSwapchainKHR swapchain; + dfuncs->vkCreateSwapchainKHR (device, &createInfo, 0, &swapchain); + + if (old_swapchain != swapchain) { + dfuncs->vkDestroySwapchainKHR (device, old_swapchain, 0); + } + + dfuncs->vkGetSwapchainImagesKHR (device, swapchain, &numImages, 0); + qfv_swapchain_t *sc = malloc (sizeof (qfv_swapchain_t) + + numImages * sizeof (VkImage)); + sc->dev = device; + sc->funcs = ctx->device->funcs; + sc->surface = ctx->surface; + sc->swapchain = swapchain; + sc->numImages = numImages; + sc->images = (VkImage *) (sc + 1); + dfuncs->vkGetSwapchainImagesKHR (device, swapchain, &numImages, + sc->images); + return sc; +} diff --git a/libs/video/renderer/vulkan/util.c b/libs/video/renderer/vulkan/util.c index 09e1b146a..854557e95 100644 --- a/libs/video/renderer/vulkan/util.c +++ b/libs/video/renderer/vulkan/util.c @@ -47,17 +47,27 @@ strset_t * new_strset (const char * const *strings) { hashtab_t *tab = Hash_NewTable (61, strset_get_key, 0, 0); - for ( ; *strings; strings++) { + for ( ; strings && *strings; strings++) { Hash_Add (tab, (void *) *strings); } return (strset_t *) tab; } -void del_strset (strset_t *strset) + +void +del_strset (strset_t *strset) { Hash_DelTable ((hashtab_t *) strset); } -int strset_contains (strset_t *strset, const char *str) +void +strset_add (strset_t *strset, const char *str) +{ + hashtab_t *tab = (hashtab_t *) strset; + Hash_Add (tab, (void *) str); +} + +int +strset_contains (strset_t *strset, const char *str) { return Hash_Find ((hashtab_t *) strset, str) != 0; } @@ -92,18 +102,12 @@ merge_strings (const char **out, const char * const *in1, } void -prune_strings (const char * const *reference, const char **strings, - uint32_t *count) +prune_strings (strset_t *strset, const char **strings, uint32_t *count) { - for (int i = *count; i-- > 0; ) { - const char *str = strings[i]; - const char * const *ref; - for (ref = reference; *ref; ref++) { - if (!strcmp (*ref, str)) { - break; - } - } - if (!*ref) { + hashtab_t *tab = (hashtab_t *) strset; + + for (uint32_t i = *count; i-- > 0; ) { + if (!Hash_Find (tab, strings[i])) { memmove (strings + i, strings + i + 1, (--(*count) - i) * sizeof (const char **)); } diff --git a/libs/video/renderer/vulkan/util.h b/libs/video/renderer/vulkan/util.h index a15aac4c8..ae87b8096 100644 --- a/libs/video/renderer/vulkan/util.h +++ b/libs/video/renderer/vulkan/util.h @@ -2,15 +2,17 @@ #define __util_h #include + +typedef struct strset_s strset_t; + int count_strings (const char * const *str); void merge_strings (const char **out, const char * const *in1, const char * const *in2); -void prune_strings (const char * const *reference, const char **strings, - uint32_t *count); +void prune_strings (strset_t *strset, const char **strings, uint32_t *count); -typedef struct strset_s strset_t; strset_t *new_strset (const char * const *strings); void del_strset (strset_t *strset); +void strset_add (strset_t *strset, const char *str); int strset_contains (strset_t *strset, const char *str); #endif//__util_h diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 22ce1d71e..f7988c26c 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -49,7 +49,8 @@ #include "QF/va.h" #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" -#include "QF/Vulkan/init.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" #include "compat.h" #include "d_iface.h" @@ -58,7 +59,7 @@ #include "util.h" -static cvar_t *vulkan_presentation_mode; +cvar_t *vulkan_presentation_mode; static void vulkan_presentation_mode_f (cvar_t *var) @@ -77,8 +78,8 @@ vulkan_presentation_mode_f (cvar_t *var) } } -void -Vulkan_Init_Cvars () +static void +Vulkan_Init_Cvars (void) { vulkan_use_validation = Cvar_Get ("vulkan_use_validation", "1", CVAR_NONE, 0, @@ -102,251 +103,30 @@ static const char *device_extensions[] = { 0, }; -static int -count_bits (uint32_t val) -{ - int bits = 0; - while (val) { - bits += val & 1; - val >>= 1; - } - return bits; -} - -static int -find_queue_family (VulkanPhysDevice_t *dev, uint32_t flags) -{ - int best_diff = 32; - uint32_t family = -1; - - for (uint32_t i = 0; i < dev->numQueueFamilies; i++) { - VkQueueFamilyProperties *queue = &dev->queueFamilies[i]; - - if ((queue->queueFlags & flags) == flags) { - int diff = count_bits (queue->queueFlags & ~flags); - if (diff < best_diff) { - best_diff = diff; - family = i; - } - } - } - return family; -} - -static void -load_device_funcs (VulkanInstance_t *inst, VulkanDevice_t *dev) -{ -#define DEVICE_LEVEL_VULKAN_FUNCTION(name) \ - dev->name = (PFN_##name) inst->vkGetDeviceProcAddr (dev->device, #name); \ - if (!dev->name) { \ - Sys_Error ("Couldn't find device level function %s", #name); \ - } - -#define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ - if (inst->extension_enabled (inst, ext)) { \ - dev->name = (PFN_##name) inst->vkGetDeviceProcAddr (dev->device, \ - #name); \ - if (!dev->name) { \ - Sys_Printf ("Couldn't find device level function %s", #name); \ - } \ - } - -#include "QF/Vulkan/funclist.h" -} - void Vulkan_Init_Common (vulkan_ctx_t *ctx) { Sys_Printf ("Vulkan_Init_Common\n"); Vulkan_Init_Cvars (); - ctx->vtx = Vulkan_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version - ctx->instance = ctx->vtx->instance; + ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version } void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { - Vulkan_DestroyInstance (ctx->vtx); - ctx->vtx = 0; + QFV_DestroyInstance (ctx->instance); + ctx->instance = 0; ctx->unload_vulkan (ctx); } void Vulkan_CreateDevice (vulkan_ctx_t *ctx) { - VulkanInstance_t *inst = ctx->vtx; - - uint32_t nlay = 1; // ensure alloca doesn't see 0 and terminated - uint32_t next = count_strings (device_extensions) + 1; // ensure terminated - if (vulkan_use_validation->int_val) { - nlay += count_strings (vulkanValidationLayers); - } - const char **lay = alloca (nlay * sizeof (const char *)); - const char **ext = alloca (next * sizeof (const char *)); - // ensure there are null pointers so merge_strings can act as append - // since it does not add a null, but also make sure the counts reflect - // actual numbers - memset (lay, 0, nlay-- * sizeof (const char *)); - memset (ext, 0, next-- * sizeof (const char *)); - merge_strings (ext, device_extensions, 0); - if (vulkan_use_validation->int_val) { - merge_strings (lay, lay, vulkanValidationLayers); - } - - for (uint32_t i = 0; i < inst->numDevices; i++) { - VulkanPhysDevice_t *phys = &inst->devices[i]; - if (!Vulkan_LayersSupported (phys->layers, phys->numLayers, lay)) { - continue; - } - if (!Vulkan_ExtensionsSupported (phys->extensions, phys->numExtensions, - ext)) { - continue; - } - int family = find_queue_family (phys, VK_QUEUE_GRAPHICS_BIT); - if (family < 0) { - continue; - } - if (!ctx->get_presentation_support (ctx, phys->device, family)) { - continue; - } - float priority = 1; - VkDeviceQueueCreateInfo qCreateInfo = { - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, - family, 1, &priority - }; - VkPhysicalDeviceFeatures features; - VkDeviceCreateInfo dCreateInfo = { - VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0, - 1, &qCreateInfo, - nlay, lay, - next, ext, - &features - }; - memset (&features, 0, sizeof (features)); - VulkanDevice_t *device = calloc (1, sizeof (VulkanDevice_t)); - if (inst->vkCreateDevice (phys->device, &dCreateInfo, 0, - &device->device) == VK_SUCCESS) { - load_device_funcs (inst, device); - device->vkGetDeviceQueue (device->device, family, - 0, &device->queue); - ctx->dev = device; - ctx->device = device->device; - ctx->physDevice = phys->device; - device->queueFamily = family; - return; - } - } + ctx->device = QFV_CreateDevice (ctx, device_extensions); } void Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) { - VkBool32 supported; - ctx->vtx->vkGetPhysicalDeviceSurfaceSupportKHR (ctx->physDevice, - ctx->dev->queueFamily, - ctx->dev->surface, - &supported); - if (!supported) { - Sys_Error ("unsupported surface for swapchain"); - } - uint32_t numModes; - VkPresentModeKHR *modes; - VkPresentModeKHR useMode = VK_PRESENT_MODE_FIFO_KHR;; - ctx->vtx->vkGetPhysicalDeviceSurfacePresentModesKHR (ctx->physDevice, - ctx->dev->surface, - &numModes, 0); - modes = alloca (numModes * sizeof (VkPresentModeKHR)); - ctx->vtx->vkGetPhysicalDeviceSurfacePresentModesKHR (ctx->physDevice, - ctx->dev->surface, - &numModes, modes); - for (uint32_t i = 0; i < numModes; i++) { - if ((int) modes[i] == vulkan_presentation_mode->int_val) { - useMode = modes[i]; - } - } - Sys_MaskPrintf (SYS_VULKAN, "presentation mode: %d (%d)\n", useMode, - vulkan_presentation_mode->int_val); - - VkSurfaceCapabilitiesKHR surfCaps; - ctx->vtx->vkGetPhysicalDeviceSurfaceCapabilitiesKHR (ctx->physDevice, - ctx->dev->surface, - &surfCaps); - uint32_t numImages = surfCaps.minImageCount + 1; - if (surfCaps.maxImageCount > 0 && numImages > surfCaps.maxImageCount) { - numImages = surfCaps.maxImageCount; - } - - VkExtent2D imageSize = {viddef.width, viddef.height}; - if (surfCaps.currentExtent.width == ~0u) { - imageSize.width = bound (surfCaps.minImageExtent.width, - imageSize.width, - surfCaps.maxImageExtent.width); - imageSize.height = bound (surfCaps.minImageExtent.height, - imageSize.height, - surfCaps.maxImageExtent.height); - } else { - imageSize = surfCaps.currentExtent; - } - Sys_MaskPrintf (SYS_VULKAN, "%d [%d, %d]\n", numImages, - imageSize.width, imageSize.height); - - VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - imageUsage &= surfCaps.supportedUsageFlags; - - VkSurfaceTransformFlagBitsKHR surfTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - - uint32_t numFormats; - ctx->vtx->vkGetPhysicalDeviceSurfaceFormatsKHR (ctx->physDevice, - ctx->dev->surface, - &numFormats, 0); - VkSurfaceFormatKHR *formats = alloca (numFormats * sizeof (*formats)); - ctx->vtx->vkGetPhysicalDeviceSurfaceFormatsKHR (ctx->physDevice, - ctx->dev->surface, - &numFormats, formats); - VkSurfaceFormatKHR useFormat = {VK_FORMAT_R8G8B8A8_UNORM, - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}; - if (numFormats > 1) { - uint32_t i; - for (i = 0; i < numFormats; i++) { - if (formats[i].format == useFormat.format - && formats[i].colorSpace == useFormat.colorSpace) { - break; - } - } - if (i == numFormats) { - useFormat = formats[0]; - } - } else if (numFormats == 1 && formats[0].format != VK_FORMAT_UNDEFINED) { - useFormat = formats[0]; - } - - VkSwapchainCreateInfoKHR createInfo = { - VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, 0, 0, - ctx->dev->surface, - numImages, - useFormat.format, useFormat.colorSpace, - imageSize, - 1, // array layers - imageUsage, - VK_SHARING_MODE_EXCLUSIVE, - 0, 0, - surfTransform, - VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - useMode, - VK_TRUE, - ctx->swapchain - }; - VkSwapchainKHR swapchain; - ctx->dev->vkCreateSwapchainKHR (ctx->device, &createInfo, 0, &swapchain); - if (ctx->swapchain != swapchain) { - ctx->dev->vkDestroySwapchainKHR (ctx->device, ctx->swapchain, 0); - } - ctx->swapchain = swapchain; - - ctx->dev->vkGetSwapchainImagesKHR (ctx->device, swapchain, &numImages, 0); - ctx->swapchainImages = malloc (numImages * sizeof (*ctx->swapchainImages)); - ctx->dev->vkGetSwapchainImagesKHR (ctx->device, swapchain, &numImages, - ctx->swapchainImages); - ctx->numSwapchainImages = numImages; } diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index 812e74dad..cd228b051 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -54,6 +54,8 @@ #include "QF/set.h" #include "QF/sys.h" +#include "QF/Vulkan/instance.h" + #include "context_x11.h" #include "vid_internal.h" #include "vid_vulkan.h" @@ -61,7 +63,7 @@ static cvar_t *vulkan_library_name; typedef struct vulkan_presentation_s { -#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; +#define PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; #include "QF/Vulkan/funclist.h" Display *display; @@ -115,12 +117,12 @@ x11_vulkan_init_presentation (vulkan_ctx_t *ctx) { ctx->presentation = calloc (1, sizeof (vulkan_presentation_t)); vulkan_presentation_t *pres = ctx->presentation; - VkInstance instance = ctx->instance; + qfv_instance_t *instance = ctx->instance; + VkInstance inst = instance->instance; -#define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ - if (ctx->extension_enabled (ctx->vtx, ext)) { \ - pres->name = (PFN_##name) ctx->vkGetInstanceProcAddr (instance, \ - #name); \ +#define PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ + if (instance->extension_enabled (instance, ext)) { \ + pres->name = (PFN_##name) ctx->vkGetInstanceProcAddr (inst, #name); \ if (!pres->name) { \ Sys_Error ("Couldn't find instance-level function %s", #name); \ } \ @@ -182,6 +184,7 @@ static VkSurfaceKHR x11_vulkan_create_surface (vulkan_ctx_t *ctx) { vulkan_presentation_t *pres = ctx->presentation; + VkInstance inst = ctx->instance->instance; VkSurfaceKHR surface; VkXlibSurfaceCreateInfoKHR createInfo = { .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, @@ -190,7 +193,7 @@ x11_vulkan_create_surface (vulkan_ctx_t *ctx) .window = pres->window }; - if (pres->vkCreateXlibSurfaceKHR (ctx->instance, &createInfo, 0, &surface) + if (pres->vkCreateXlibSurfaceKHR (inst, &createInfo, 0, &surface) != VK_SUCCESS) { return 0; } From 66e7336b624015ae8590eeed16fcbb0da1c36f9b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Jul 2019 13:37:30 +0900 Subject: [PATCH 0203/3664] Initialize device extension checks early They need to be initialized before attempting to load the function pointers. --- libs/video/renderer/vulkan/device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 1579c0633..36b81b025 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -195,13 +195,13 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) if (ifunc->vkCreateDevice (physdev, &dCreateInfo, 0, &device->dev) == VK_SUCCESS) { qfv_devfuncs_t *dfunc = device->funcs; + device->enabled_extensions = new_strset (ext); + device->extension_enabled = device_extension_enabled; device->physDev = physdev; load_device_funcs (inst, device); device->queueFamily = family; dfunc->vkGetDeviceQueue (device->dev, family, 0, &device->queue); - device->enabled_extensions = new_strset (ext); - device->extension_enabled = device_extension_enabled; ctx->device = device; return device; } From b2e12d701bc151e7ec284b340e122e83fd1decd8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Jul 2019 14:09:12 +0900 Subject: [PATCH 0204/3664] Fix up swapchain creation Things are working again. --- include/QF/Vulkan/funclist.h | 6 +++--- libs/video/renderer/vulkan/vulkan_vid_common.c | 11 +++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 719335699..1419aebd4 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -94,10 +94,10 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkGetDeviceQueue) #endif DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION - (vkCreateSwapchainKHR, VK_KHR_SURFACE_EXTENSION_NAME) + (vkCreateSwapchainKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME) DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION - (vkDestroySwapchainKHR, VK_KHR_SURFACE_EXTENSION_NAME) + (vkDestroySwapchainKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME) DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION - (vkGetSwapchainImagesKHR, VK_KHR_SURFACE_EXTENSION_NAME) + (vkGetSwapchainImagesKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME) #undef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index f7988c26c..70890ab7a 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -51,6 +51,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/swapchain.h" #include "compat.h" #include "d_iface.h" @@ -129,4 +130,14 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) void Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) { + VkSwapchainKHR old_swapchain = 0; + if (ctx->swapchain) { + old_swapchain = ctx->swapchain->swapchain; + free (ctx->swapchain); + } + ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain); + if (ctx->swapchain->swapchain == old_swapchain) { + ctx->device->funcs->vkDestroySwapchainKHR (ctx->device->dev, + old_swapchain, 0); + } } From 4e4d1b99b48b06d67b271c92d7095b0c55d3970c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Jul 2019 23:15:26 +0900 Subject: [PATCH 0205/3664] Clean up all the system shutdown calls I added Sys_RegisterShutdown years ago and never really did anything with it: now any system that needs to be shutdown can ensure it gets shutdown on program exit, and in the correct order (ie, reverse to init order). --- hw/source/master.c | 3 -- include/QF/cdaudio.h | 1 - include/QF/console.h | 1 - include/QF/input.h | 2 -- include/QF/sound.h | 4 --- include/QF/vid.h | 1 - include/netchan.h | 4 --- include/netmain.h | 4 --- libs/audio/cd.c | 6 ++-- libs/audio/snd.c | 29 ++++++++-------- libs/audio/targets/snd_alsa.c | 4 +-- libs/audio/targets/snd_disk.c | 4 +-- libs/audio/targets/snd_dx.c | 13 +++---- libs/audio/targets/snd_oss.c | 4 +-- libs/audio/targets/snd_sdl.c | 4 +-- libs/audio/targets/snd_sgi.c | 4 +-- libs/audio/targets/snd_sun.c | 4 +-- libs/audio/targets/snd_win.c | 9 ++--- libs/console/client.c | 4 +-- libs/console/console.c | 20 ++++++----- libs/console/server.c | 4 +-- libs/net/nc/net_udp.c | 23 +++++++------ libs/net/nc/net_udp6.c | 4 +-- libs/net/net_main.c | 56 ++++++++++++++++--------------- libs/video/targets/context_sdl.c | 6 ---- libs/video/targets/in_common.c | 6 ++-- libs/video/targets/vid_3dfxsvga.c | 6 ++-- libs/video/targets/vid_fbdev.c | 6 ++-- libs/video/targets/vid_sdl.c | 8 +++++ libs/video/targets/vid_svgalib.c | 6 ++-- libs/video/targets/vid_wgl.c | 6 ++-- libs/video/targets/vid_x11.c | 21 +++++------- nq/include/client.h | 1 - nq/source/cl_main.c | 8 ++--- nq/source/host.c | 7 ---- nq/source/sv_ded.c | 5 --- qtv/source/qtv.c | 2 -- qw/source/cl_main.c | 5 --- qw/source/sv_main.c | 3 -- tools/qwaq/qwaq-bi.c | 3 -- 40 files changed, 135 insertions(+), 176 deletions(-) diff --git a/hw/source/master.c b/hw/source/master.c index 6e744c4ac..31f457f5a 100644 --- a/hw/source/master.c +++ b/hw/source/master.c @@ -471,11 +471,8 @@ SV_WriteFilterList (void) static void SV_Shutdown (void) { - NET_Shutdown (); - // write filter list SV_WriteFilterList (); - Con_Shutdown (); } static void diff --git a/include/QF/cdaudio.h b/include/QF/cdaudio.h index e7596ad78..12d3aa2a9 100644 --- a/include/QF/cdaudio.h +++ b/include/QF/cdaudio.h @@ -35,7 +35,6 @@ void CDAudio_Play(int track, qboolean looping); void CDAudio_Stop(void); void CDAudio_Pause(void); void CDAudio_Resume(void); -void CDAudio_Shutdown(void); void CDAudio_Update(void); #endif // _CDAUDIO_H diff --git a/include/QF/console.h b/include/QF/console.h index 4f3bcb3c8..b18e66401 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -119,7 +119,6 @@ void Con_BufferAddText (con_buffer_t *buf, const char *text); // init/shutdown functions void Con_Init (const char *plugin_name); -void Con_Shutdown (void); void Con_ExecLine (const char *line); void Con_ProcessInput (void); diff --git a/include/QF/input.h b/include/QF/input.h index 8f0438071..ab808386f 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -44,8 +44,6 @@ struct cvar_s; void IN_Init (struct cbuf_s *cbuf); void IN_Init_Cvars (void); -void IN_Shutdown (void); - void IN_ProcessEvents (void); void IN_UpdateGrab (struct cvar_s *); diff --git a/include/QF/sound.h b/include/QF/sound.h index 874469ea4..3e37a5871 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -81,10 +81,6 @@ void S_Init (int *viewentity, double *host_frametime); */ void S_Init_Cvars (void); -/** Shutdown the sound engine. Allows audio output modules to shutdown - gracefully. -*/ -void S_Shutdown (void); //@} /** \defgroup sound_stuff Unclassified diff --git a/include/QF/vid.h b/include/QF/vid.h index 93975ced6..e1228fcd7 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -76,7 +76,6 @@ void VID_Init_Cvars (void); // the palette data will go away after the call, so it must be copied off if // the video driver will need it again void VID_Init (byte *palette, byte *colormap); -void VID_Shutdown (void); void VID_SetCaption (const char *text); void VID_ClearMemory (void); diff --git a/include/netchan.h b/include/netchan.h index 556732ba2..4aa266fc8 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -90,10 +90,6 @@ extern struct cvar_s *net_packetlog; */ void NET_Init (int port); -/** Shutdown the UDP network interface. -*/ -void NET_Shutdown (void); - /** Read a single packet from the network into net_message. \return True if successfully read, otherwise false. diff --git a/include/netmain.h b/include/netmain.h index a35171415..fdb870628 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -273,10 +273,6 @@ extern int net_activeconnections; */ void NET_Init (void); -/** Shutdown the networking sub-system. -*/ -void NET_Shutdown (void); - /** Check for new connections. \return Pointer to the qsocket for the new connection if there diff --git a/libs/audio/cd.c b/libs/audio/cd.c index bf4245ba6..e025abbe2 100644 --- a/libs/audio/cd.c +++ b/libs/audio/cd.c @@ -69,8 +69,8 @@ CDAudio_Resume (void) cdmodule->functions->cd->pCDAudio_Resume (); } -VISIBLE void -CDAudio_Shutdown (void) +static void +CDAudio_shutdown (void) { if (cdmodule) cdmodule->functions->general->p_Shutdown (); @@ -93,6 +93,8 @@ CD_f (void) VISIBLE int CDAudio_Init (void) { + Sys_RegisterShutdown (CDAudio_shutdown); + PI_RegisterPlugins (cd_plugin_list); cd_plugin = Cvar_Get ("cd_plugin", CD_DEFAULT, CVAR_ROM, NULL, "CD Plugin to use"); diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 6f4ecba05..e76c548e0 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -53,6 +53,19 @@ static plugin_list_t snd_render_list[] = { SND_RENDER_PLUGIN_LIST }; +static void +S_shutdown (void) +{ + if (snd_render_module) { + PI_UnloadPlugin (snd_render_module); + snd_render_module = NULL; + snd_render_funcs = NULL; + } + if (snd_output_module) { + PI_UnloadPlugin (snd_output_module); + snd_output_module = NULL; + } +} VISIBLE void S_Init (int *viewentity, double *host_frametime) @@ -65,6 +78,8 @@ S_Init (int *viewentity, double *host_frametime) return; } + Sys_RegisterShutdown (S_shutdown); + PI_RegisterPlugins (snd_output_list); PI_RegisterPlugins (snd_render_list); snd_output_module = PI_LoadPlugin ("snd_output", snd_output->string); @@ -120,20 +135,6 @@ S_AmbientOn (void) snd_render_funcs->pS_AmbientOn (); } -VISIBLE void -S_Shutdown (void) -{ - if (snd_render_module) { - PI_UnloadPlugin (snd_render_module); - snd_render_module = NULL; - snd_render_funcs = NULL; - } - if (snd_output_module) { - PI_UnloadPlugin (snd_output_module); - snd_output_module = NULL; - } -} - VISIBLE void S_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, float attenuation) { diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 76450bcc9..205153752 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -463,7 +463,7 @@ SNDDMA_GetDMAPos (void) } static void -SNDDMA_Shutdown (void) +SNDDMA_shutdown (void) { if (snd_inited) { qfsnd_pcm_close (pcm); @@ -549,7 +549,7 @@ PLUGIN_INFO(snd_output, alsa) plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; plugin_info_general_funcs.p_Shutdown = NULL; plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_Shutdown; + plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; diff --git a/libs/audio/targets/snd_disk.c b/libs/audio/targets/snd_disk.c index e24bc0e9f..878ca90ca 100644 --- a/libs/audio/targets/snd_disk.c +++ b/libs/audio/targets/snd_disk.c @@ -108,7 +108,7 @@ SNDDMA_GetDMAPos (void) } static void -SNDDMA_Shutdown (void) +SNDDMA_shutdown (void) { if (snd_inited) { Qclose (snd_file); @@ -174,7 +174,7 @@ PLUGIN_INFO(snd_output, disk) plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; plugin_info_general_funcs.p_Shutdown = NULL; plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_Shutdown; + plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; diff --git a/libs/audio/targets/snd_dx.c b/libs/audio/targets/snd_dx.c index 1bae2c3d0..3852a17a5 100644 --- a/libs/audio/targets/snd_dx.c +++ b/libs/audio/targets/snd_dx.c @@ -417,13 +417,8 @@ SNDDMA_Submit (void) DSOUND_LockBuffer (false); } -/* - SNDDMA_Shutdown - - Reset the sound device for exiting -*/ static void -SNDDMA_Shutdown (void) +SNDDMA_shutdown (void) { FreeSound (); } @@ -450,7 +445,7 @@ DSOUND_LockBuffer (qboolean lockit) if (hresult != DSERR_BUFFERLOST) { Sys_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); - SNDDMA_Shutdown (); + SNDDMA_shutdown (); SNDDMA_Init (); return NULL; } @@ -458,7 +453,7 @@ DSOUND_LockBuffer (qboolean lockit) if (++reps > 10000) { Sys_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); - SNDDMA_Shutdown (); + SNDDMA_shutdown (); SNDDMA_Init (); return NULL; } @@ -529,7 +524,7 @@ PLUGIN_INFO(snd_output, dx) plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; plugin_info_general_funcs.p_Shutdown = NULL; plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_Shutdown; + plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; diff --git a/libs/audio/targets/snd_oss.c b/libs/audio/targets/snd_oss.c index 33349dc98..97383ff82 100644 --- a/libs/audio/targets/snd_oss.c +++ b/libs/audio/targets/snd_oss.c @@ -331,7 +331,7 @@ SNDDMA_GetDMAPos (void) } static void -SNDDMA_Shutdown (void) +SNDDMA_shutdown (void) { if (snd_inited) { if (mmaped_io) @@ -413,7 +413,7 @@ PLUGIN_INFO(snd_output, oss) plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; plugin_info_general_funcs.p_Shutdown = NULL; plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_Shutdown; + plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; diff --git a/libs/audio/targets/snd_sdl.c b/libs/audio/targets/snd_sdl.c index 91d5500f5..5e8dfc409 100644 --- a/libs/audio/targets/snd_sdl.c +++ b/libs/audio/targets/snd_sdl.c @@ -206,7 +206,7 @@ SNDDMA_GetDMAPos (void) } static void -SNDDMA_Shutdown (void) +SNDDMA_shutdown (void) { if (snd_inited) { SDL_CloseAudio (); @@ -297,7 +297,7 @@ PLUGIN_INFO(snd_output, sdl) plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; plugin_info_general_funcs.p_Shutdown = NULL; plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_Shutdown; + plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; diff --git a/libs/audio/targets/snd_sgi.c b/libs/audio/targets/snd_sgi.c index 4b431dbaf..27ae12d64 100644 --- a/libs/audio/targets/snd_sgi.c +++ b/libs/audio/targets/snd_sgi.c @@ -269,7 +269,7 @@ SNDDMA_GetDMAPos (void) } static void -SNDDMA_Shutdown (void) +SNDDMA_shutdown (void) { if (snd_inited) { free (write_buffer); @@ -357,7 +357,7 @@ PLUGIN_INFO(snd_output, sgi) plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; plugin_info_general_funcs.p_Shutdown = NULL; plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_Shutdown; + plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; diff --git a/libs/audio/targets/snd_sun.c b/libs/audio/targets/snd_sun.c index 89c649416..702757a34 100644 --- a/libs/audio/targets/snd_sun.c +++ b/libs/audio/targets/snd_sun.c @@ -189,7 +189,7 @@ SNDDMA_GetSamples (void) } #endif static void -SNDDMA_Shutdown (void) +SNDDMA_shutdown (void) { if (snd_inited) { close (audio_fd); @@ -281,7 +281,7 @@ PLUGIN_INFO(snd_output, sun) plugin_info_general_funcs.p_Shutdown = NULL; plugin_info_sound_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_sound_funcs.pS_O_Shutdown = SNDDMA_Shutdown; + plugin_info_sound_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_sound_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; plugin_info_sound_funcs.pS_O_Submit = SNDDMA_Submit; plugin_info_sound_funcs.pS_O_BlockSound = SNDDMA_BlockSound; diff --git a/libs/audio/targets/snd_win.c b/libs/audio/targets/snd_win.c index 91d4ce298..84465516c 100644 --- a/libs/audio/targets/snd_win.c +++ b/libs/audio/targets/snd_win.c @@ -344,13 +344,8 @@ SNDDMA_Submit (void) } } -/* - SNDDMA_Shutdown - - Reset the sound device for exiting -*/ static void -SNDDMA_Shutdown (void) +SNDDMA_shutdown (void) { FreeSound (); } @@ -379,7 +374,7 @@ PLUGIN_INFO(snd_output, win) plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; plugin_info_general_funcs.p_Shutdown = NULL; plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_Shutdown; + plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; diff --git a/libs/console/client.c b/libs/console/client.c index ad31462a0..582113703 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -931,13 +931,13 @@ C_Init (void) } static void -C_Shutdown (void) +C_shutdown (void) { } static general_funcs_t plugin_info_general_funcs = { C_Init, - C_Shutdown, + C_shutdown, }; static console_funcs_t plugin_info_console_funcs = { diff --git a/libs/console/console.c b/libs/console/console.c index fbfdbd608..4801c0fdb 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -84,9 +84,20 @@ Con_Interp_f (cvar_t *var) } } +static void +Con_shutdown (void) +{ + if (con_module) { + con_module->functions->general->p_Shutdown (); + PI_UnloadPlugin (con_module); + } +} + VISIBLE void Con_Init (const char *plugin_name) { + Sys_RegisterShutdown (Con_shutdown); + con_module = PI_LoadPlugin ("console", plugin_name); if (con_module) { con_module->functions->general->p_Init (); @@ -123,15 +134,6 @@ Con_ExecLine (const char *line) Sys_Printf ("%s\n", line); } -VISIBLE void -Con_Shutdown (void) -{ - if (con_module) { - con_module->functions->general->p_Shutdown (); - PI_UnloadPlugin (con_module); - } -} - VISIBLE void Con_Printf (const char *fmt, ...) { diff --git a/libs/console/server.c b/libs/console/server.c index 83cce7f3d..5edd2a669 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -696,7 +696,7 @@ C_Init (void) } static void -C_Shutdown (void) +C_shutdown (void) { if (log_file) { Qclose (log_file); @@ -780,7 +780,7 @@ C_NewMap (void) static general_funcs_t plugin_info_general_funcs = { C_Init, - C_Shutdown, + C_shutdown, }; static general_data_t plugin_info_general_data; diff --git a/libs/net/nc/net_udp.c b/libs/net/nc/net_udp.c index 051785c5e..e349d5cd6 100644 --- a/libs/net/nc/net_udp.c +++ b/libs/net/nc/net_udp.c @@ -403,6 +403,17 @@ NET_GetLocalAddress (void) Sys_Printf ("IP address %s\n", NET_AdrToString (net_local_adr)); } +static void +NET_shutdown (void) +{ +#ifdef _WIN32 + closesocket (net_socket); + WSACleanup (); +#else + close (net_socket); +#endif +} + void NET_Init (int port) { @@ -416,6 +427,7 @@ NET_Init (int port) if (r) Sys_Error ("Winsock initialization failed."); #endif /* _WIN32 */ + Sys_RegisterShutdown (NET_shutdown); net_socket = UDP_OpenSocket (port); @@ -431,14 +443,3 @@ NET_Init (int port) Sys_Printf ("UDP (IPv4) Initialized\n"); } - -void -NET_Shutdown (void) -{ -#ifdef _WIN32 - closesocket (net_socket); - WSACleanup (); -#else - close (net_socket); -#endif -} diff --git a/libs/net/nc/net_udp6.c b/libs/net/nc/net_udp6.c index bad834082..c04092a83 100644 --- a/libs/net/nc/net_udp6.c +++ b/libs/net/nc/net_udp6.c @@ -600,8 +600,8 @@ NET_Init (int port) Sys_Printf ("UDP (IPv6) Initialized\n"); } -void -NET_Shutdown (void) +static void +NET_shutdown (void) { #ifdef _WIN32 closesocket (net_socket); diff --git a/libs/net/net_main.c b/libs/net/net_main.c index 7c235f4a9..051598003 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -718,6 +718,33 @@ NET_SendToAll (sizebuf_t *data, double blocktime) //============================================================================= +static void +NET_shutdown (void) +{ + qsocket_t *sock; + + SetNetTime (); + + for (sock = net_activeSockets; sock; sock = sock->next) + NET_Close (sock); + +// +// shutdown the drivers +// + for (net_driverlevel = 0; net_driverlevel < net_numdrivers; + net_driverlevel++) { + if (net_drivers[net_driverlevel].initialized == true) { + net_drivers[net_driverlevel].Shutdown (); + net_drivers[net_driverlevel].initialized = false; + } + } + + if (vcrFile) { + Sys_Printf ("Closing vcrfile.\n"); + Qclose (vcrFile); + } +} + void NET_Init (void) { @@ -725,6 +752,8 @@ NET_Init (void) int controlSocket; qsocket_t *s; + Sys_RegisterShutdown (NET_shutdown); + if (COM_CheckParm ("-playback")) { net_numdrivers = 1; net_drivers[0].Init = VCR_Init; @@ -790,33 +819,6 @@ NET_Init (void) Sys_MaskPrintf (SYS_NET, "TCP/IP address %s\n", my_tcpip_address); } -void -NET_Shutdown (void) -{ - qsocket_t *sock; - - SetNetTime (); - - for (sock = net_activeSockets; sock; sock = sock->next) - NET_Close (sock); - -// -// shutdown the drivers -// - for (net_driverlevel = 0; net_driverlevel < net_numdrivers; - net_driverlevel++) { - if (net_drivers[net_driverlevel].initialized == true) { - net_drivers[net_driverlevel].Shutdown (); - net_drivers[net_driverlevel].initialized = false; - } - } - - if (vcrFile) { - Sys_Printf ("Closing vcrfile.\n"); - Qclose (vcrFile); - } -} - static PollProcedure *pollProcedureList = NULL; diff --git a/libs/video/targets/context_sdl.c b/libs/video/targets/context_sdl.c index 7426ea8f8..7a764553a 100644 --- a/libs/video/targets/context_sdl.c +++ b/libs/video/targets/context_sdl.c @@ -53,12 +53,6 @@ VID_SetGamma (double gamma) return SDL_SetGamma((float) gamma, (float) gamma, (float) gamma); } -void -VID_Shutdown (void) -{ - SDL_Quit (); -} - static void VID_UpdateFullscreen (cvar_t *vid_fullscreen) { diff --git a/libs/video/targets/in_common.c b/libs/video/targets/in_common.c index d5bdf8bda..4b37f23d1 100644 --- a/libs/video/targets/in_common.c +++ b/libs/video/targets/in_common.c @@ -128,8 +128,8 @@ IN_Move (void) } /* Called at shutdown */ -void -IN_Shutdown (void) +static void +IN_shutdown (void) { JOY_Shutdown (); @@ -142,6 +142,8 @@ IN_Shutdown (void) void IN_Init (cbuf_t *cbuf) { + Sys_RegisterShutdown (IN_shutdown); + IE_Init (); IN_LL_Init (); Key_Init (cbuf); diff --git a/libs/video/targets/vid_3dfxsvga.c b/libs/video/targets/vid_3dfxsvga.c index e7df1f342..68078703f 100644 --- a/libs/video/targets/vid_3dfxsvga.c +++ b/libs/video/targets/vid_3dfxsvga.c @@ -150,8 +150,8 @@ QFGL_LoadLibrary (void) #endif // HAVE_DLOPEN -void -VID_Shutdown (void) +static void +VID_shutdown (void) { if (!fc) return; @@ -271,6 +271,8 @@ VID_Init (byte *palette, byte *colormap) { GLint attribs[32]; + Sys_RegisterShutdown (VID_shutdown); + GLF_Init (); qf_fxMesaCreateContext = QFGL_ProcAddress (libgl_handle, diff --git a/libs/video/targets/vid_fbdev.c b/libs/video/targets/vid_fbdev.c index 5cd81cc47..84e3db80a 100644 --- a/libs/video/targets/vid_fbdev.c +++ b/libs/video/targets/vid_fbdev.c @@ -209,8 +209,8 @@ static unsigned long fb_map_length = 0; static struct fb_var_screeninfo orig_var; -void -VID_Shutdown (void) +static void +VID_shutdown (void) { Sys_MaskPrintf (SYS_VID, "VID_Shutdown\n"); @@ -406,6 +406,8 @@ VID_Init (byte *palette, byte *colormap) if (fbdev_inited) return; + Sys_RegisterShutdown (VID_shutdown); + R_LoadModule (0, VID_SetPalette); if (COM_CheckParm ("-novideo")) { diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index 9b1938d30..80f005328 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -64,9 +64,17 @@ static vid_internal_t vid_internal; uint32_t sdl_flags; +static void +VID_shutdown (void) +{ + SDL_Quit (); +} + void VID_Init (byte *palette, byte *colormap) { + Sys_RegisterShutdown (VID_shutdown); + vid_internal.gl_context = SDL_GL_Context; vid_internal.sw_context = SDL_SW_Context; // Load the SDL library diff --git a/libs/video/targets/vid_svgalib.c b/libs/video/targets/vid_svgalib.c index 8849a4eb5..91e0414b8 100644 --- a/libs/video/targets/vid_svgalib.c +++ b/libs/video/targets/vid_svgalib.c @@ -239,8 +239,8 @@ get_mode (int width, int height, int depth) return i; } -void -VID_Shutdown (void) +static void +VID_shutdown (void) { Sys_MaskPrintf (SYS_VID, "VID_Shutdown\n"); @@ -358,6 +358,8 @@ VID_Init (byte *palette, byte *colormap) if (svgalib_inited) return; + Sys_RegisterShutdown (VID_shutdown); + err = vga_init (); if (err) Sys_Error ("SVGALib failed to allocate a new VC"); diff --git a/libs/video/targets/vid_wgl.c b/libs/video/targets/vid_wgl.c index bec07fe19..a9054510b 100644 --- a/libs/video/targets/vid_wgl.c +++ b/libs/video/targets/vid_wgl.c @@ -372,8 +372,8 @@ GL_EndRendering (void) } } -void -VID_Shutdown (void) +static void +VID_shutdown (void) { HGLRC hRC; HDC hDC; @@ -454,6 +454,8 @@ VID_Init (byte *palette, byte *colormap) DWORD lasterror; WNDCLASS wc; + Sys_RegisterShutdown (VID_shutdown); + vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ROM | CVAR_ARCHIVE, NULL, "Run WGL client at fullscreen"); GLF_Init (); diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 946824547..18f56c305 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -83,6 +83,13 @@ D_EndDirectRect (int x, int y, int width, int height) // direct drawing of the "accessing disk" icon isn't supported } +static void +VID_shutdown (void) +{ + Sys_MaskPrintf (SYS_VID, "VID_shutdown\n"); + X11_CloseDisplay (); +} + /* Set up color translation tables and the window. Takes a 256-color 8-bit palette. Palette data will go away after the call, so copy it if you'll @@ -91,6 +98,8 @@ D_EndDirectRect (int x, int y, int width, int height) void VID_Init (byte *palette, byte *colormap) { + Sys_RegisterShutdown (VID_shutdown); + vid_internal.gl_context = X11_GL_Context; vid_internal.sw_context = X11_SW_Context; #ifdef HAVE_VULKAN @@ -133,18 +142,6 @@ VID_Init_Cvars () X11_GL_Init_Cvars (); } -/* - VID_Shutdown - - Restore video mode -*/ -void -VID_Shutdown (void) -{ - Sys_MaskPrintf (SYS_VID, "VID_Shutdown\n"); - X11_CloseDisplay (); -} - #if 0 static int config_notify = 0; static int config_notify_width; diff --git a/nq/include/client.h b/nq/include/client.h index 54477f7b4..817bebaf6 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -286,7 +286,6 @@ extern void (*write_angles) (sizebuf_t *sb, const vec3_t angles); struct cbuf_s; void CL_Init (struct cbuf_s *cbuf); void CL_InitCvars (void); -void CL_Shutdown (void); void CL_ClearMemory (void); void CL_EstablishConnection (const char *host); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 3f8e7bde6..672269c9f 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -120,14 +120,10 @@ CL_WriteConfiguration (void) } } -void +static void CL_Shutdown (void) { CL_WriteConfiguration (); - CDAudio_Shutdown (); - S_Shutdown (); - IN_Shutdown (); - VID_Shutdown (); } void @@ -537,6 +533,8 @@ CL_Init (cbuf_t *cbuf) { byte *basepal, *colormap; + Sys_RegisterShutdown (CL_Shutdown); + basepal = (byte *) QFS_LoadHunkFile (QFS_FOpenFile ("gfx/palette.lmp")); if (!basepal) Sys_Error ("Couldn't load gfx/palette.lmp"); diff --git a/nq/source/host.c b/nq/source/host.c index d15dd0431..0d85b9a1a 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -968,11 +968,4 @@ Host_Shutdown (void) return; } isdown = true; - - - NET_Shutdown (); - if (cls.state != ca_dedicated) { - CL_Shutdown (); - } - Con_Shutdown (); } diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index 44dd57408..7db231bd2 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -98,11 +98,6 @@ CL_EstablishConnection (const char *host) { } -void -CL_Shutdown () -{ -} - void CL_Init (struct cbuf_s *cbuf) { diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 4980dea9b..2f9f826ad 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -222,8 +222,6 @@ qtv_memory_init (void) static void qtv_shutdown (void) { - NET_Shutdown (); - Con_Shutdown (); Cbuf_Delete (qtv_cbuf); Cbuf_ArgsDelete (qtv_args); } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index c2b3c3a35..3cb0e1432 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1882,10 +1882,5 @@ Host_Shutdown (void) Host_WriteConfiguration (); - CDAudio_Shutdown (); CL_HTTP_Shutdown (); - NET_Shutdown (); - S_Shutdown (); - IN_Shutdown (); - VID_Shutdown (); } diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index c69e23594..a121ba5ce 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -246,9 +246,6 @@ SV_Shutdown (void) } if (sv.recording_demo) SV_Stop (0); - - NET_Shutdown (); - Con_Shutdown (); } /* diff --git a/tools/qwaq/qwaq-bi.c b/tools/qwaq/qwaq-bi.c index 7e21a9259..cad5108f3 100644 --- a/tools/qwaq/qwaq-bi.c +++ b/tools/qwaq/qwaq-bi.c @@ -161,9 +161,6 @@ static builtin_t builtins[] = { static void bi_shutdown (void) { - S_Shutdown (); - IN_Shutdown (); - VID_Shutdown (); } void From 1eafc330527ae738dd2e088ca4837cded151c067 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 Jul 2019 00:36:21 +0900 Subject: [PATCH 0206/3664] Ensure vulkan gets shut down --- include/QF/Vulkan/device.h | 5 +++-- include/QF/Vulkan/funclist.h | 6 ++++++ include/QF/Vulkan/swapchain.h | 1 + libs/video/renderer/r_init.c | 9 +++++++++ libs/video/renderer/vulkan/device.c | 17 ++++++++--------- libs/video/renderer/vulkan/swapchain.c | 8 ++++++++ libs/video/renderer/vulkan/vulkan_vid_common.c | 2 ++ 7 files changed, 37 insertions(+), 11 deletions(-) diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h index ae0c26ffc..8dc4df371 100644 --- a/include/QF/Vulkan/device.h +++ b/include/QF/Vulkan/device.h @@ -20,7 +20,8 @@ typedef struct qfv_device_s { } qfv_device_t; struct vulkan_ctx_s; -qfv_device_t *QFV_CreateDevice(struct vulkan_ctx_s *ctx, - const char **extensions); +qfv_device_t *QFV_CreateDevice (struct vulkan_ctx_s *ctx, + const char **extensions); +void QFV_DestroyDevice (qfv_device_t *device); #endif//__QF_Vulkan_swapchain_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 1419aebd4..43bad39c7 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -48,6 +48,8 @@ INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkGetPhysicalDeviceSurfaceCapabilitiesKHR, VK_KHR_SURFACE_EXTENSION_NAME) INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkGetPhysicalDeviceSurfaceFormatsKHR, VK_KHR_SURFACE_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkDestroySurfaceKHR, VK_KHR_SURFACE_EXTENSION_NAME) #undef INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION @@ -99,5 +101,9 @@ DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkDestroySwapchainKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME) DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkGetSwapchainImagesKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkAcquireNextImageKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkQueuePresentKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME) #undef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION diff --git a/include/QF/Vulkan/swapchain.h b/include/QF/Vulkan/swapchain.h index 71d0b6d75..91d158c89 100644 --- a/include/QF/Vulkan/swapchain.h +++ b/include/QF/Vulkan/swapchain.h @@ -13,5 +13,6 @@ typedef struct qfv_swapchain_s { struct vulkan_ctx_s; qfv_swapchain_t *QFV_CreateSwapchain (struct vulkan_ctx_s *ctx, VkSwapchainKHR old_swapchain); +void QFV_DestroySwapchain (qfv_swapchain_t *swapchain); #endif//__QF_Vulkan_swapchain_h diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 330d0d76d..df2392a6b 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -63,6 +63,14 @@ vid_render_funcs_t *r_funcs; static U void (*const r_progs_init)(struct progs_s *) = R_Progs_Init; #undef U +static void +R_shutdown (void) +{ + if (vidrendmodule->functions->general->p_Shutdown) { + vidrendmodule->functions->general->p_Shutdown (); + } +} + VISIBLE void R_LoadModule (vid_internal_t *vid_internal) { @@ -80,6 +88,7 @@ R_LoadModule (vid_internal_t *vid_internal) r_data->vid->vid_internal = vid_internal; vidrendmodule->functions->general->p_Init (); + Sys_RegisterShutdown (R_shutdown); } VISIBLE void diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 36b81b025..736b5e915 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -133,9 +133,6 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) { uint32_t nlay = 1; // ensure alloca doesn't see 0 and terminated uint32_t next = count_strings (extensions) + 1; // ensure terminated - //if (vulkan_use_validation->int_val) { - // nlay += count_strings (vulkanValidationLayers); - //} const char **lay = alloca (nlay * sizeof (const char *)); const char **ext = alloca (next * sizeof (const char *)); // ensure there are null pointers so merge_strings can act as append @@ -144,9 +141,6 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) memset (lay, 0, nlay-- * sizeof (const char *)); memset (ext, 0, next-- * sizeof (const char *)); merge_strings (ext, extensions, 0); - //if (vulkan_use_validation->int_val) { - // merge_strings (lay, lay, vulkanValidationLayers); - //} qfv_instance_t *inst = ctx->instance; VkInstance instance = inst->instance; @@ -160,9 +154,6 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) for (uint32_t i = 0; i < numDevices; i++) { VkPhysicalDevice physdev = devices[i]; /* - if (!Vulkan_LayersSupported (phys->layers, phys->numLayers, lay)) { - continue; - } if (!Vulkan_ExtensionsSupported (phys->extensions, phys->numExtensions, ext)) { continue; @@ -209,3 +200,11 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) } return 0; } + +void +QFV_DestroyDevice (qfv_device_t *device) +{ + device->funcs->vkDestroyDevice (device->dev, 0); + del_strset (device->enabled_extensions); + free (device); +} diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 91f8280c9..2707676d6 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -146,3 +146,11 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) sc->images); return sc; } + +void +QFV_DestroySwapchain (qfv_swapchain_t *swapchain) +{ + swapchain->funcs->vkDestroySwapchainKHR (swapchain->dev, + swapchain->swapchain, 0); + free (swapchain); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 70890ab7a..ed5369c9c 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -116,6 +116,8 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { + Sys_Printf ("are we here?\n"); + QFV_DestroyDevice (ctx->device); QFV_DestroyInstance (ctx->instance); ctx->instance = 0; ctx->unload_vulkan (ctx); From b4dc746a66886319e1a2a607fd53ee2ba6e12cc8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 Jul 2019 01:11:34 +0900 Subject: [PATCH 0207/3664] Clean up the debug callback --- include/QF/Vulkan/funclist.h | 2 ++ include/QF/Vulkan/instance.h | 1 + libs/video/renderer/vulkan/instance.c | 12 +++++++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 43bad39c7..5fe467937 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -40,6 +40,8 @@ INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties) INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkCreateDebugUtilsMessengerEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkDestroyDebugUtilsMessengerEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkGetPhysicalDeviceSurfaceSupportKHR, VK_KHR_SURFACE_EXTENSION_NAME) INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION diff --git a/include/QF/Vulkan/instance.h b/include/QF/Vulkan/instance.h index 1cc05d6cf..0a677c945 100644 --- a/include/QF/Vulkan/instance.h +++ b/include/QF/Vulkan/instance.h @@ -42,6 +42,7 @@ typedef struct qfv_instance_s { struct strset_s *enabled_extensions; int (*extension_enabled) (struct qfv_instance_s *inst, const char *ext); + VkDebugUtilsMessengerEXT debug_handle; } qfv_instance_t; struct vulkan_ctx_s; diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index 74b0ea756..25ccdb306 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -150,7 +150,7 @@ debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, static void setup_debug_callback (qfv_instance_t *instance) { - VkDebugUtilsMessengerEXT debug_callback_handle; + VkDebugUtilsMessengerEXT debug_handle; VkDebugUtilsMessengerCreateInfoEXT createInfo = { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, .messageSeverity = message_severities, @@ -160,7 +160,8 @@ setup_debug_callback (qfv_instance_t *instance) }; instance->funcs->vkCreateDebugUtilsMessengerEXT(instance->instance, &createInfo, 0, - &debug_callback_handle); + &debug_handle); + instance->debug_handle = debug_handle; } static void @@ -242,7 +243,7 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, if (res != VK_SUCCESS) { Sys_Error ("unable to create vulkan instance\n"); } - qfv_instance_t *inst = malloc (sizeof(qfv_instance_t) + qfv_instance_t *inst = calloc (1, sizeof(qfv_instance_t) + sizeof (qfv_instfuncs_t)); inst->instance = instance; inst->funcs = (qfv_instfuncs_t *)(inst + 1); @@ -261,6 +262,11 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, void QFV_DestroyInstance (qfv_instance_t *instance) { + qfv_instfuncs_t *ifunc = instance->funcs; + if (instance->debug_handle) { + ifunc->vkDestroyDebugUtilsMessengerEXT (instance->instance, + instance->debug_handle, 0); + } instance->funcs->vkDestroyInstance (instance->instance, 0); free (instance); } From dd1c2db2496ad55eb7cbc9fe1251ec4dff8c3e4f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 Jul 2019 01:14:21 +0900 Subject: [PATCH 0208/3664] Clean up the swapchain And be a little safer about it --- libs/video/renderer/vulkan/vulkan_vid_common.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index ed5369c9c..6d8c32505 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -116,9 +116,15 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { - Sys_Printf ("are we here?\n"); - QFV_DestroyDevice (ctx->device); - QFV_DestroyInstance (ctx->instance); + if (ctx->swapchain) { + QFV_DestroySwapchain (ctx->swapchain); + } + if (ctx->device) { + QFV_DestroyDevice (ctx->device); + } + if (ctx->instance) { + QFV_DestroyInstance (ctx->instance); + } ctx->instance = 0; ctx->unload_vulkan (ctx); } From 1f24a1408acdcc48be2010cc38d5e936fb2ee0b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 Jul 2019 01:20:02 +0900 Subject: [PATCH 0209/3664] Destroy the surface --- libs/video/renderer/vulkan/vulkan_vid_common.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 6d8c32505..37fe9c564 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -119,6 +119,8 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } + ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, + ctx->surface, 0); if (ctx->device) { QFV_DestroyDevice (ctx->device); } From e16400205027956978fec72c895264b93251d41d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Jul 2019 08:52:15 +0900 Subject: [PATCH 0210/3664] Make QuatToMat faster and more accurate The better accuracy is for specific cases (90 degree rotations around a main axis: the matrix element for that axis is now 1 instead of 0.99999994). The speedup comes from doing fewer additions (multiply seems to be faster than add for fp, at least in this situation). --- libs/util/mathlib.c | 34 ++++++++++---------- libs/util/test/test-quat.c | 64 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index db68455f3..3e6540636 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -303,7 +303,7 @@ QuatExp (const quat_t a, quat_t b) VISIBLE void QuatToMatrix (const quat_t q, vec_t *m, int homogenous, int vertical) { - vec_t xx, xy, xz, xw, yy, yz, yw, zz, zw, ww; + vec_t xx, xy, xz, xw, yy, yz, yw, zz, zw; vec_t *_m[4] = { m + (homogenous ? 0 : 0), m + (homogenous ? 4 : 3), @@ -311,28 +311,26 @@ QuatToMatrix (const quat_t q, vec_t *m, int homogenous, int vertical) m + (homogenous ? 12 : 9), }; - xx = q[0] * q[0]; - xy = q[0] * q[1]; - xz = q[0] * q[2]; - xw = q[0] * q[3]; + xx = 2 * q[0] * q[0]; + xy = 2 * q[0] * q[1]; + xz = 2 * q[0] * q[2]; + xw = 2 * q[0] * q[3]; - yy = q[1] * q[1]; - yz = q[1] * q[2]; - yw = q[1] * q[3]; + yy = 2 * q[1] * q[1]; + yz = 2 * q[1] * q[2]; + yw = 2 * q[1] * q[3]; - zz = q[2] * q[2]; - zw = q[2] * q[3]; - - ww = q[3] * q[3]; + zz = 2 * q[2] * q[2]; + zw = 2 * q[2] * q[3]; if (vertical) { - VectorSet (ww + xx - yy - zz, 2 * (xy + zw), 2 * (xz - yw), _m[0]); - VectorSet (2 * (xy - zw), ww - xx + yy - zz, 2 * (yz + xw), _m[1]); - VectorSet (2 * (xz + yw), 2 * (yz - xw), ww - xx - yy + zz, _m[2]); + VectorSet (1.0f - yy - zz, xy + zw, xz - yw, _m[0]); + VectorSet (xy - zw, 1.0f - xx - zz, yz + xw, _m[1]); + VectorSet (xz + yw, yz - xw, 1.0f - xx - yy, _m[2]); } else { - VectorSet (ww + xx - yy - zz, 2 * (xy - zw), 2 * (xz + yw), _m[0]); - VectorSet (2 * (xy + zw), ww - xx + yy - zz, 2 * (yz - xw), _m[1]); - VectorSet (2 * (xz - yw), 2 * (yz + xw), ww - xx - yy + zz, _m[2]); + VectorSet (1.0f - yy - zz, xy - zw, xz + yw, _m[0]); + VectorSet (xy + zw, 1.0f - xx - zz, yz - xw, _m[1]); + VectorSet (xz - yw, yz + xw, 1.0f - xx - yy, _m[2]); } if (homogenous) { _m[0][3] = 0; diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index 47539d144..44c8923b3 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -200,6 +200,62 @@ fail: return 0; } +#define s05 0.70710678118654757 + +static struct { + quat_t q; + vec_t expect[9]; +} quat_mat_tests[] = { + {{0, 0, 0, 1}, + {1, 0, 0, + 0, 1, 0, + 0, 0, 1}}, + {{1, 0, 0, 0}, + {1, 0, 0, + 0, -1, 0, + 0, 0, -1}}, + {{0, 1, 0, 0}, + {-1, 0, 0, + 0, 1, 0, + 0, 0, -1}}, + {{0, 0, 1, 0}, + {-1, 0, 0, + 0, -1, 0, + 0, 0, 1}}, + {{0.5, 0.5, 0.5, 0.5}, + {0, 0, 1, + 1, 0, 0, + 0, 1, 0}}, + {{s05, 0.0, 0.0, s05}, + {1, 0, 0, + 0, 5.96046448e-8, -0.99999994, + 0, 0.99999994, 5.96046448e-8}}, +}; +#define num_quat_mat_tests (sizeof (quat_mat_tests) / sizeof (quat_mat_tests[0])) + +static int +test_quat_mat(const quat_t q, const quat_t expect) +{ + int i; + vec_t m[9]; + + QuatToMatrix (q, m, 0, 0); + + for (i = 0; i < 9; i++) + if (m[i] != expect[i]) // exact tests here + goto fail; + return 1; +fail: + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (q)); + printf ("%11.9g %11.9g %11.9g %11.9g %11.9g %11.9g\n", + VectorExpand (m + 0), VectorExpand (expect + 0)); + printf ("%11.9g %11.9g %11.9g %11.9g %11.9g %11.9g\n", + VectorExpand (m + 3), VectorExpand (expect + 3)); + printf ("%11.9g %11.9g %11.9g %11.9g %11.9g %11.9g\n", + VectorExpand (m + 6), VectorExpand (expect + 6)); + return 0; +} + int main (int argc, const char **argv) { @@ -228,5 +284,13 @@ main (int argc, const char **argv) if (!test_rotation3 (test_angles[i])) res = 1; } + + for (i = 0; i < num_quat_mat_tests; i ++) { + vec_t *q = quat_mat_tests[i].q; + vec_t *expect = quat_mat_tests[i].expect; + if (!test_quat_mat (q, expect)) + res = 1; + } + return res; } From ae11a70147c05ba5e15ff29c213d49b362bdc039 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Jul 2019 12:27:57 +0900 Subject: [PATCH 0211/3664] Correct a comment --- include/QF/Vulkan/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h index 8dc4df371..0a90ea539 100644 --- a/include/QF/Vulkan/device.h +++ b/include/QF/Vulkan/device.h @@ -24,4 +24,4 @@ qfv_device_t *QFV_CreateDevice (struct vulkan_ctx_s *ctx, const char **extensions); void QFV_DestroyDevice (qfv_device_t *device); -#endif//__QF_Vulkan_swapchain_h +#endif//__QF_Vulkan_device_h From 411b897f09f8d89c19c361cf86ffef044dce5441 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Jul 2019 12:28:57 +0900 Subject: [PATCH 0212/3664] Implement most of the stuff for command submission --- include/QF/Vulkan/command.h | 79 +++++++ include/QF/Vulkan/funclist.h | 11 + libs/video/renderer/vulkan/Makefile.am | 1 + libs/video/renderer/vulkan/command.c | 316 +++++++++++++++++++++++++ 4 files changed, 407 insertions(+) create mode 100644 include/QF/Vulkan/command.h create mode 100644 libs/video/renderer/vulkan/command.c diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h new file mode 100644 index 000000000..1fe12df6d --- /dev/null +++ b/include/QF/Vulkan/command.h @@ -0,0 +1,79 @@ +#ifndef __QF_Vulkan_command_h +#define __QF_Vulkan_command_h + +typedef struct qfv_cmdpool_s { + VkDevice dev; + struct qfv_devfuncs_s *funcs; + VkCommandPool cmdpool; +} qfv_cmdpool_t; + +typedef struct qfv_cmdbuffer_s { + VkDevice dev; + struct qfv_devfuncs_s *funcs; + VkCommandBuffer buffer; +} qfv_cmdbuffer_t; + +typedef struct qfv_cmdbufferset_s { + VkDevice dev; + struct qfv_devfuncs_s *funcs; + VkCommandBuffer *buffers; + int numBuffers; +} qfv_cmdbufferset_t; + +typedef struct qfv_semaphore_s { + VkDevice dev; + struct qfv_devfuncs_s *funcs; + VkSemaphore semaphore; +} qfv_semaphore_t; + +typedef struct qfv_semaphoreset_s { + VkDevice dev; + struct qfv_devfuncs_s *funcs; + VkSemaphore *semaphores; + VkPipelineStageFlags *stages; + int numSemaphores; +} qfv_semaphoreset_t; + +typedef struct qfv_fence_s { + VkDevice dev; + struct qfv_devfuncs_s *funcs; + VkFence fence; +} qfv_fence_t; + +typedef struct qfv_fenceset_s { + VkDevice dev; + struct qfv_devfuncs_s *funcs; + VkFence *fences; + int numFences; +} qfv_fenceset_t; + +struct qfv_device_s; +qfv_cmdpool_t *QFV_CreateCommandPool (struct qfv_device_s *device, + uint32_t queueFamily, + int transient, int reset); +int QFV_ResetCommandPool (qfv_cmdpool_t *pool, int release); +qfv_cmdbuffer_t *QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, + int secondary, int count); +qfv_cmdbufferset_t *QFV_CreateCommandBufferSet (qfv_cmdbuffer_t **buffers, + int numBuffers); +int QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, + int rpContinue, int simultaneous, + VkCommandBufferInheritanceInfo *inheritanceInfo); +int QFV_EndCommandBuffer (qfv_cmdbuffer_t *buffer); +int QFV_ResetCommandBuffer (qfv_cmdbuffer_t *buffer, int release); + +qfv_semaphore_t *QFV_CreateSemaphore (struct qfv_device_s *device); +qfv_semaphoreset_t *QFV_CreateSemaphoreSet (qfv_semaphore_t **semaphores, + int numSemaphores); + +qfv_fence_t *QFV_CreateFence (struct qfv_device_s *device, int signaled); +qfv_fenceset_t *QFV_CreateFenceSet (qfv_fence_t **fences, int numFences); +int QFV_WaitForFences (qfv_fenceset_t *fences, int all, uint64_t timeout); +int QFV_ResetFences (qfv_fenceset_t *fences); +int QFV_QueueSubmit (struct qfv_device_s *device, + qfv_semaphoreset_t *waitSemaphores, + qfv_cmdbufferset_t *buffers, + qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence); + + +#endif//__QF_Vulkan_command_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 5fe467937..20ccbe275 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -90,6 +90,17 @@ PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyDevice) DEVICE_LEVEL_VULKAN_FUNCTION (vkGetDeviceQueue) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateCommandPool) +DEVICE_LEVEL_VULKAN_FUNCTION (vkResetCommandPool) +DEVICE_LEVEL_VULKAN_FUNCTION (vkAllocateCommandBuffers) +DEVICE_LEVEL_VULKAN_FUNCTION (vkBeginCommandBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkEndCommandBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkResetCommandBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSemaphore) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateFence) +DEVICE_LEVEL_VULKAN_FUNCTION (vkWaitForFences) +DEVICE_LEVEL_VULKAN_FUNCTION (vkResetFences) +DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueSubmit) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index e59e29551..f754853f2 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -4,6 +4,7 @@ AM_CFLAGS= @PREFER_PIC@ AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES vulkan_src = \ + command.c \ device.c \ instance.c \ swapchain.c \ diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c new file mode 100644 index 000000000..13dbde1a6 --- /dev/null +++ b/libs/video/renderer/vulkan/command.c @@ -0,0 +1,316 @@ +/* + vid_common_vulkan.c + + Common Vulkan video driver functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2019 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +qfv_cmdpool_t * +QFV_CreateCommandPool (qfv_device_t *device, uint32_t queueFamily, + int transient, int reset) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + uint32_t flags = 0; + if (transient) { + flags |= VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; + } + if (reset) { + flags |= VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + } + VkCommandPoolCreateInfo createInfo = { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 0, + flags, + queueFamily + }; + qfv_cmdpool_t *cmdpool = malloc (sizeof (*cmdpool)); + dfunc->vkCreateCommandPool (dev, &createInfo, 0, &cmdpool->cmdpool); + cmdpool->dev = dev; + cmdpool->funcs = dfunc; + return cmdpool; +} + +int +QFV_ResetCommandPool (qfv_cmdpool_t *pool, int release) +{ + VkDevice dev = pool->dev; + VkCommandPool cmdpool = pool->cmdpool; + qfv_devfuncs_t *dfunc = pool->funcs; + VkCommandPoolResetFlags release_flag = 0; + + if (release) { + release_flag = VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT; + } + + return dfunc->vkResetCommandPool (dev, cmdpool, release_flag) == VK_SUCCESS; +} + +qfv_cmdbuffer_t * +QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) +{ + VkDevice dev = pool->dev; + qfv_devfuncs_t *dfunc = pool->funcs; + uint32_t level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + if (secondary) { + level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; + } + VkCommandBufferAllocateInfo allocInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 0, + pool->cmdpool, level, count + }; + qfv_cmdbuffer_t *cmdbuffers = malloc (count * sizeof (*cmdbuffers)); + VkCommandBuffer *buffers = alloca (count * sizeof (*buffers)); + dfunc->vkAllocateCommandBuffers (dev, &allocInfo, buffers); + for (int i = 0; i < count; i++) { + cmdbuffers[i].dev = dev; + cmdbuffers[i].funcs = dfunc; + cmdbuffers[i].buffer = buffers[i]; + } + return cmdbuffers; +} + +qfv_cmdbufferset_t * +QFV_CreateCommandBufferSet (qfv_cmdbuffer_t **buffers, int numBuffers) +{ + VkDevice dev = buffers[0]->dev; + qfv_devfuncs_t *dfunc = buffers[0]->funcs; + qfv_cmdbufferset_t *bufferset = malloc (sizeof (*bufferset) + + sizeof (VkCommandBuffer) + * numBuffers); + + bufferset->dev = dev; + bufferset->funcs = dfunc; + bufferset->buffers = (VkCommandBuffer *) (bufferset + 1); + bufferset->numBuffers = numBuffers; + + for (int i = 0; i < numBuffers; i++) { + bufferset->buffers[i] = buffers[i]->buffer; + } + return bufferset; +} + +int +QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, int rpContinue, + int simultaneous, + VkCommandBufferInheritanceInfo *inheritanceInfo) +{ + VkCommandBuffer buff = buffer->buffer; + qfv_devfuncs_t *dfunc = buffer->funcs; + VkCommandBufferUsageFlags usage = 0; + + if (oneTime) { + usage |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + } + if (rpContinue) { + usage |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; + } + if (simultaneous) { + usage |= VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; + } + + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + usage, + 0 + }; + + return dfunc->vkBeginCommandBuffer (buff, &beginInfo) == VK_SUCCESS; +} + +int +QFV_EndCommandBuffer (qfv_cmdbuffer_t *buffer) +{ + VkCommandBuffer buff = buffer->buffer; + qfv_devfuncs_t *dfunc = buffer->funcs; + + return dfunc->vkEndCommandBuffer (buff) == VK_SUCCESS; +} + +int +QFV_ResetCommandBuffer (qfv_cmdbuffer_t *buffer, int release) +{ + VkCommandBuffer buff = buffer->buffer; + qfv_devfuncs_t *dfunc = buffer->funcs; + VkCommandBufferResetFlags release_flag = 0; + + if (release) { + release_flag = VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT; + } + + return dfunc->vkResetCommandBuffer (buff, release_flag) == VK_SUCCESS; +} + +qfv_semaphore_t * +QFV_CreateSemaphore (qfv_device_t *device) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkSemaphoreCreateInfo createInfo = { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, 0, + 0 + }; + + qfv_semaphore_t *semaphore = malloc (sizeof (*semaphore)); + semaphore->dev = dev; + semaphore->funcs = dfunc; + + dfunc->vkCreateSemaphore (dev, &createInfo, 0, &semaphore->semaphore); + return semaphore; +} + +qfv_semaphoreset_t * +QFV_CreateSemaphoreSet (qfv_semaphore_t **semaphores, int numSemaphores) +{ + VkDevice dev = semaphores[0]->dev; + qfv_devfuncs_t *dfunc = semaphores[0]->funcs; + qfv_semaphoreset_t *semaphoreset; + semaphoreset = calloc (1, sizeof (*semaphoreset) + + sizeof (VkSemaphore) * numSemaphores + + sizeof (VkPipelineStageFlags) * numSemaphores); + + semaphoreset->dev = dev; + semaphoreset->funcs = dfunc; + semaphoreset->semaphores = (VkSemaphore *) (semaphoreset + 1); + semaphoreset->stages = (VkPipelineStageFlags *) + &semaphoreset->semaphores[numSemaphores]; + semaphoreset->numSemaphores = numSemaphores; + + for (int i = 0; i < numSemaphores; i++) { + semaphoreset->semaphores[i] = semaphores[i]->semaphore; + } + return semaphoreset; +} + +qfv_fence_t * +QFV_CreateFence (qfv_device_t *device, int signaled) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkFenceCreateInfo createInfo = { + VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 0, + signaled ? VK_FENCE_CREATE_SIGNALED_BIT : 0, + }; + + qfv_fence_t *fence = malloc (sizeof (*fence)); + fence->dev = dev; + fence->funcs = dfunc; + + dfunc->vkCreateFence (dev, &createInfo, 0, &fence->fence); + return fence; +} + +qfv_fenceset_t * +QFV_CreateFenceSet (qfv_fence_t **fences, int numFences) +{ + VkDevice dev = fences[0]->dev; + qfv_devfuncs_t *dfunc = fences[0]->funcs; + qfv_fenceset_t *fenceset = malloc (sizeof (*fenceset) + + sizeof (VkFence) * numFences); + + fenceset->dev = dev; + fenceset->funcs = dfunc; + fenceset->fences = (VkFence *) (fenceset + 1); + fenceset->numFences = numFences; + + for (int i = 0; i < numFences; i++) { + fenceset->fences[i] = fences[i]->fence; + } + return fenceset; +} + +int +QFV_WaitForFences (qfv_fenceset_t *fences, int all, uint64_t timeout) +{ + VkDevice dev = fences->dev; + qfv_devfuncs_t *dfunc = fences->funcs; + + VkResult res = dfunc->vkWaitForFences (dev, fences->numFences, + fences->fences, all, timeout); + return res == VK_SUCCESS; +} + +int +QFV_ResetFences (qfv_fenceset_t *fences) +{ + VkDevice dev = fences->dev; + qfv_devfuncs_t *dfunc = fences->funcs; + + return dfunc->vkResetFences (dev, fences->numFences, + fences->fences) == VK_SUCCESS; +} + +int +QFV_QueueSubmit (qfv_device_t *device, qfv_semaphoreset_t *waitSemaphores, + qfv_cmdbufferset_t *buffers, + qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence) +{ + qfv_devfuncs_t *dfunc = device->funcs; + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + waitSemaphores->numSemaphores, + waitSemaphores->semaphores, waitSemaphores->stages, + buffers->numBuffers, buffers->buffers, + signalSemaphores->numSemaphores, + signalSemaphores->semaphores + }; + //FIXME multi-batch + return dfunc->vkQueueSubmit (device->queue, 1, &submitInfo, + fence->fence) == VK_SUCCESS; +} From a165d67dfa324bad91b94b1ecaeb5c621742edfe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Jul 2019 12:37:47 +0900 Subject: [PATCH 0213/3664] Add a queue type --- include/QF/Vulkan/command.h | 3 ++- include/QF/Vulkan/device.h | 12 ++++++++++-- libs/video/renderer/vulkan/command.c | 6 +++--- libs/video/renderer/vulkan/device.c | 7 +++++-- libs/video/renderer/vulkan/swapchain.c | 3 ++- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 1fe12df6d..3ad1164ff 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -48,6 +48,7 @@ typedef struct qfv_fenceset_s { } qfv_fenceset_t; struct qfv_device_s; +struct qfv_queue_s; qfv_cmdpool_t *QFV_CreateCommandPool (struct qfv_device_s *device, uint32_t queueFamily, int transient, int reset); @@ -70,7 +71,7 @@ qfv_fence_t *QFV_CreateFence (struct qfv_device_s *device, int signaled); qfv_fenceset_t *QFV_CreateFenceSet (qfv_fence_t **fences, int numFences); int QFV_WaitForFences (qfv_fenceset_t *fences, int all, uint64_t timeout); int QFV_ResetFences (qfv_fenceset_t *fences); -int QFV_QueueSubmit (struct qfv_device_s *device, +int QFV_QueueSubmit (struct qfv_queue_s *queue, qfv_semaphoreset_t *waitSemaphores, qfv_cmdbufferset_t *buffers, qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence); diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h index 0a90ea539..959b3d956 100644 --- a/include/QF/Vulkan/device.h +++ b/include/QF/Vulkan/device.h @@ -7,13 +7,21 @@ typedef struct qfv_devfuncs_s { #include "QF/Vulkan/funclist.h" } qfv_devfuncs_t; +struct qfv_device_s; +typedef struct qfv_queue_s { + VkDevice dev; + qfv_devfuncs_t *funcs; + + int32_t queueFamily; + VkQueue queue; +} qfv_queue_t; + struct qfv_instance_s; typedef struct qfv_device_s { VkDevice dev; VkPhysicalDevice physDev; qfv_devfuncs_t *funcs; - int32_t queueFamily; - VkQueue queue; + qfv_queue_t queue; struct strset_s *enabled_extensions; int (*extension_enabled) (struct qfv_device_s *inst, const char *ext); diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 13dbde1a6..fab0a1966 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -297,11 +297,11 @@ QFV_ResetFences (qfv_fenceset_t *fences) } int -QFV_QueueSubmit (qfv_device_t *device, qfv_semaphoreset_t *waitSemaphores, +QFV_QueueSubmit (qfv_queue_t *queue, qfv_semaphoreset_t *waitSemaphores, qfv_cmdbufferset_t *buffers, qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence) { - qfv_devfuncs_t *dfunc = device->funcs; + qfv_devfuncs_t *dfunc = queue->funcs; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, waitSemaphores->numSemaphores, @@ -311,6 +311,6 @@ QFV_QueueSubmit (qfv_device_t *device, qfv_semaphoreset_t *waitSemaphores, signalSemaphores->semaphores }; //FIXME multi-batch - return dfunc->vkQueueSubmit (device->queue, 1, &submitInfo, + return dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, fence->fence) == VK_SUCCESS; } diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 736b5e915..a90b58744 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -191,8 +191,11 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) device->physDev = physdev; load_device_funcs (inst, device); - device->queueFamily = family; - dfunc->vkGetDeviceQueue (device->dev, family, 0, &device->queue); + device->queue.dev = device->dev; + device->queue.funcs = dfunc; + device->queue.queueFamily = family; + dfunc->vkGetDeviceQueue (device->dev, family, 0, + &device->queue.queue); ctx->device = device; return device; } diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 2707676d6..c9487a913 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -27,10 +27,11 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) { qfv_instfuncs_t *ifuncs = ctx->instance->funcs; qfv_devfuncs_t *dfuncs = ctx->device->funcs; + qfv_queue_t *queue = &ctx->device->queue; VkBool32 supported; ifuncs->vkGetPhysicalDeviceSurfaceSupportKHR (ctx->device->physDev, - ctx->device->queueFamily, + queue->queueFamily, ctx->surface, &supported); if (!supported) { From 4957c4f31adc2e50b176ea112b074d348e839f30 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Jul 2019 13:05:32 +0900 Subject: [PATCH 0214/3664] Implement the rest of the command stuff --- include/QF/Vulkan/command.h | 13 +++++- include/QF/Vulkan/device.h | 1 + include/QF/Vulkan/funclist.h | 6 +++ libs/video/renderer/vulkan/command.c | 70 ++++++++++++++++++++++++++++ libs/video/renderer/vulkan/device.c | 7 +++ 5 files changed, 96 insertions(+), 1 deletion(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 3ad1164ff..2af925f29 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -10,6 +10,7 @@ typedef struct qfv_cmdpool_s { typedef struct qfv_cmdbuffer_s { VkDevice dev; struct qfv_devfuncs_s *funcs; + VkCommandPool cmdpool; VkCommandBuffer buffer; } qfv_cmdbuffer_t; @@ -53,10 +54,14 @@ qfv_cmdpool_t *QFV_CreateCommandPool (struct qfv_device_s *device, uint32_t queueFamily, int transient, int reset); int QFV_ResetCommandPool (qfv_cmdpool_t *pool, int release); +void QFV_DestroyCommandPool (qfv_cmdpool_t *pool); qfv_cmdbuffer_t *QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count); qfv_cmdbufferset_t *QFV_CreateCommandBufferSet (qfv_cmdbuffer_t **buffers, int numBuffers); +void QFV_FreeCommandBuffers (qfv_cmdbuffer_t *buffer, int count); +// NOTE: does not destroy buffers +void QFV_DestroyCommandBufferSet (qfv_cmdbufferset_t *buffers); int QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, int rpContinue, int simultaneous, VkCommandBufferInheritanceInfo *inheritanceInfo); @@ -66,15 +71,21 @@ int QFV_ResetCommandBuffer (qfv_cmdbuffer_t *buffer, int release); qfv_semaphore_t *QFV_CreateSemaphore (struct qfv_device_s *device); qfv_semaphoreset_t *QFV_CreateSemaphoreSet (qfv_semaphore_t **semaphores, int numSemaphores); - +void QFV_DestroySemaphore (qfv_semaphore_t *semaphore); +// NOTE: does not destroy semaphores +void QFV_DestroySemaphoreSet (qfv_semaphoreset_t *semaphores); qfv_fence_t *QFV_CreateFence (struct qfv_device_s *device, int signaled); qfv_fenceset_t *QFV_CreateFenceSet (qfv_fence_t **fences, int numFences); +void QFV_DestroyFence (qfv_fence_t *fence); +// NOTE: does not destroy fences +void QFV_DestroyFenceSet (qfv_fenceset_t *fences); int QFV_WaitForFences (qfv_fenceset_t *fences, int all, uint64_t timeout); int QFV_ResetFences (qfv_fenceset_t *fences); int QFV_QueueSubmit (struct qfv_queue_s *queue, qfv_semaphoreset_t *waitSemaphores, qfv_cmdbufferset_t *buffers, qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence); +int QFV_QueueWaitIdle (struct qfv_queue_s *queue); #endif//__QF_Vulkan_command_h diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h index 959b3d956..6f6907148 100644 --- a/include/QF/Vulkan/device.h +++ b/include/QF/Vulkan/device.h @@ -31,5 +31,6 @@ struct vulkan_ctx_s; qfv_device_t *QFV_CreateDevice (struct vulkan_ctx_s *ctx, const char **extensions); void QFV_DestroyDevice (qfv_device_t *device); +int QFV_DeviceWaitIdle (qfv_device_t *device); #endif//__QF_Vulkan_device_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 20ccbe275..5d649d5c2 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -101,6 +101,12 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateFence) DEVICE_LEVEL_VULKAN_FUNCTION (vkWaitForFences) DEVICE_LEVEL_VULKAN_FUNCTION (vkResetFences) DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueSubmit) +DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueWaitIdle) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDeviceWaitIdle) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFence) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySemaphore) +DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeCommandBuffers) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyCommandPool) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index fab0a1966..4031f0be4 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -100,6 +100,16 @@ QFV_ResetCommandPool (qfv_cmdpool_t *pool, int release) return dfunc->vkResetCommandPool (dev, cmdpool, release_flag) == VK_SUCCESS; } +void +QFV_DestroyCommandPool (qfv_cmdpool_t *pool) +{ + VkDevice dev = pool->dev; + qfv_devfuncs_t *dfunc = pool->funcs; + + dfunc->vkDestroyCommandPool (dev, pool->cmdpool, 0); + free (pool); +} + qfv_cmdbuffer_t * QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) { @@ -119,6 +129,7 @@ QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) for (int i = 0; i < count; i++) { cmdbuffers[i].dev = dev; cmdbuffers[i].funcs = dfunc; + cmdbuffers[i].cmdpool = pool->cmdpool; cmdbuffers[i].buffer = buffers[i]; } return cmdbuffers; @@ -144,6 +155,26 @@ QFV_CreateCommandBufferSet (qfv_cmdbuffer_t **buffers, int numBuffers) return bufferset; } +void QFV_FreeCommandBuffers (qfv_cmdbuffer_t *buffer, int count) +{ + VkDevice dev = buffer->dev; + qfv_devfuncs_t *dfunc = buffer->funcs; + VkCommandBuffer *buffers = alloca (sizeof (*buffers) * count); + + for (int i = 0; i < count; i++) { + buffers[i] = buffer[i].buffer; + } + + dfunc->vkFreeCommandBuffers (dev, buffer->cmdpool, count, buffers); + free (buffer); +} + +void +QFV_DestroyCommandBufferSet (qfv_cmdbufferset_t *buffers) +{ + free (buffers); +} + int QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, int rpContinue, int simultaneous, @@ -237,6 +268,22 @@ QFV_CreateSemaphoreSet (qfv_semaphore_t **semaphores, int numSemaphores) return semaphoreset; } +void +QFV_DestroySemaphore (qfv_semaphore_t *semaphore) +{ + VkDevice dev = semaphore->dev; + qfv_devfuncs_t *dfunc = semaphore->funcs; + + dfunc->vkDestroySemaphore (dev, semaphore->semaphore, 0); + free (semaphore); +} + +void +QFV_DestroySemaphoreSet (qfv_semaphoreset_t *semaphores) +{ + free (semaphores); +} + qfv_fence_t * QFV_CreateFence (qfv_device_t *device, int signaled) { @@ -275,6 +322,22 @@ QFV_CreateFenceSet (qfv_fence_t **fences, int numFences) return fenceset; } +void +QFV_DestroyFence (qfv_fence_t *fence) +{ + VkDevice dev = fence->dev; + qfv_devfuncs_t *dfunc = fence->funcs; + + dfunc->vkDestroyFence (dev, fence->fence, 0); + free (fence); +} + +void +QFV_DestroyFenceSet (qfv_fenceset_t *fences) +{ + free (fences); +} + int QFV_WaitForFences (qfv_fenceset_t *fences, int all, uint64_t timeout) { @@ -314,3 +377,10 @@ QFV_QueueSubmit (qfv_queue_t *queue, qfv_semaphoreset_t *waitSemaphores, return dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, fence->fence) == VK_SUCCESS; } + +int +QFV_QueueWaitIdle (qfv_queue_t *queue) +{ + qfv_devfuncs_t *dfunc = queue->funcs; + return dfunc->vkQueueWaitIdle (queue->queue) == VK_SUCCESS; +} diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index a90b58744..85f200956 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -211,3 +211,10 @@ QFV_DestroyDevice (qfv_device_t *device) del_strset (device->enabled_extensions); free (device); } + +int +QFV_DeviceWaitIdle (qfv_device_t *device) +{ + qfv_devfuncs_t *dfunc = device->funcs; + return dfunc->vkDeviceWaitIdle (device->dev) == VK_SUCCESS; +} From 90a707f7f96762f581d59936964f4e0fa627db62 Mon Sep 17 00:00:00 2001 From: khreathor Date: Tue, 20 Nov 2018 18:28:42 +0100 Subject: [PATCH 0215/3664] Export animation range selected with start/end playback range in Timeline Editor --- tools/io_mesh_qfmdl/export_mdl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index 9b98ee20a..e2260e372 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -300,7 +300,7 @@ def export_mdl(operator, context, filepath): make_skin(operator, mdl, mesh) if not mdl.frames: curframe = context.scene.frame_current - for fno in range(1, curframe + 1): + for fno in range(context.scene.frame_start, context.scene.frame_end + 1): context.scene.frame_set(fno) mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg? if mdl.obj.qfmdl.xform: From 8112c4e8b6265ae6c35e247802f80ef76bbeb053 Mon Sep 17 00:00:00 2001 From: khreathor Date: Sat, 24 Nov 2018 02:59:41 +0100 Subject: [PATCH 0216/3664] Moved MDL settings from Object tab to export options/presets --- tools/io_mesh_qfmdl/__init__.py | 33 +++++++++++++++++-- tools/io_mesh_qfmdl/export_mdl.py | 54 ++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/tools/io_mesh_qfmdl/__init__.py b/tools/io_mesh_qfmdl/__init__.py index 03eb35e71..a3abea3cd 100644 --- a/tools/io_mesh_qfmdl/__init__.py +++ b/tools/io_mesh_qfmdl/__init__.py @@ -66,6 +66,7 @@ EFFECTS=( ) class QFMDLSettings(bpy.types.PropertyGroup): + ''' eyeposition = FloatVectorProperty( name="Eye Position", description="View possion relative to object origin") @@ -85,9 +86,7 @@ class QFMDLSettings(bpy.types.PropertyGroup): # type=bpy.types.Object, # name="Script", # description="Script for animating frames and skins") - script = StringProperty( - name="Script", - description="Script for animating frames and skins") + xform = BoolProperty( name="Auto transform", description="Auto-apply location/rotation/scale when exporting", @@ -95,6 +94,10 @@ class QFMDLSettings(bpy.types.PropertyGroup): md16 = BoolProperty( name="16-bit", description="16 bit vertex coordinates: QuakeForge only") + ''' + script = StringProperty( + name="Script", + description="Script for animating frames and skins") class ImportMDL6(bpy.types.Operator, ImportHelper): '''Load a Quake MDL (v6) File''' @@ -114,10 +117,34 @@ class ExportMDL6(bpy.types.Operator, ExportHelper): bl_idname = "export_mesh.quake_mdl_v6" bl_label = "Export MDL" + bl_options = {'PRESET'}; filename_ext = ".mdl" filter_glob = StringProperty(default="*.mdl", options={'HIDDEN'}) + eyeposition = FloatVectorProperty( + name="Eye Position", + description="View possion relative to object origin") + synctype = EnumProperty( + items=SYNCTYPE, + name="Sync Type", + description="Add random time offset for automatic animations") + rotate = BoolProperty( + name="Rotate", + description="Rotate automatically (for pickup items)", + default=False) + effects = EnumProperty( + items=EFFECTS, + name="Effects", + description="Particle trail effects") + xform = BoolProperty( + name="Auto transform", + description="Auto-apply location/rotation/scale when exporting", + default=True) + md16 = BoolProperty( + name="16-bit", + description="16 bit vertex coordinates: QuakeForge only") + @classmethod def poll(cls, context): return (context.active_object != None diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index e2260e372..d6f7371d0 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -27,6 +27,7 @@ from .qfplist import pldata, PListError from .quakepal import palette from .quakenorm import map_normal from .mdl import MDL +from .__init__ import SYNCTYPE, EFFECTS def check_faces(mesh): #Check that all faces are tris because mdl does not support anything else. @@ -185,14 +186,25 @@ def calc_average_area(mdl): totalarea += (c * c) ** 0.5 / 2.0 return totalarea / len(mdl.tris) -def get_properties(operator, mdl, obj): - mdl.eyeposition = tuple(obj.qfmdl.eyeposition) - mdl.synctype = MDL.SYNCTYPE[obj.qfmdl.synctype] - mdl.flags = ((obj.qfmdl.rotate and MDL.EF_ROTATE or 0) - | MDL.EFFECTS[obj.qfmdl.effects]) - if obj.qfmdl.md16: +def get_properties( + operator, + mdl, + eyeposition, + synctype, + rotate, + effects, + xform, + md16): + mdl.eyeposition = eyeposition + mdl.synctype = MDL.SYNCTYPE[synctype] + mdl.flags = ((rotate and MDL.EF_ROTATE or 0) + | MDL.EFFECTS[effects]) + if md16: mdl.ident = "MD16" - script = obj.qfmdl.script + + #tomporarily disabled + #script = obj.qfmdl.script + script = None mdl.script = None if script: try: @@ -276,7 +288,18 @@ def process_frame(mdl, scene, frame, vertmap, ingroup = False, fr.name = name return fr -def export_mdl(operator, context, filepath): +def export_mdl( + operator, + context, + filepath = "", + eyeposition = (0.0, 0.0, 0.0), + synctype = SYNCTYPE[1], + rotate = False, + effects = EFFECTS[1], + xform = True, + md16 = False + ): + obj = context.active_object mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg? #if not check_faces(mesh): @@ -285,8 +308,17 @@ def export_mdl(operator, context, filepath): # return {'CANCELLED'} mdl = MDL(obj.name) mdl.obj = obj - if not get_properties(operator, mdl, obj): - return {'CANCELLED'} + if not get_properties( + operator, + mdl, + eyeposition, + synctype, + rotate, + effects, + xform, + md16): + return {'CANCELLED'} + mdl.tris, mdl.stverts, vertmap = build_tris(mesh) if mdl.script: if 'skins' in mdl.script: @@ -303,7 +335,7 @@ def export_mdl(operator, context, filepath): for fno in range(context.scene.frame_start, context.scene.frame_end + 1): context.scene.frame_set(fno) mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg? - if mdl.obj.qfmdl.xform: + if xform: mesh.transform(mdl.obj.matrix_world) mdl.frames.append(make_frame(mesh, vertmap)) convert_stverts(mdl, mdl.stverts) From ae86790e6ccc1e77d9d9448cb5fbdc966ec49fad Mon Sep 17 00:00:00 2001 From: khreathor Date: Tue, 8 Jan 2019 03:02:11 +0100 Subject: [PATCH 0217/3664] Initial Blender 2.8 changes - it works, now it's time for improvements --- tools/io_mesh_qfmdl/__init__.py | 83 ++++++++++++++++++------------- tools/io_mesh_qfmdl/export_mdl.py | 23 +++++++-- tools/io_mesh_qfmdl/import_mdl.py | 81 +++++++++++++++++++----------- 3 files changed, 119 insertions(+), 68 deletions(-) diff --git a/tools/io_mesh_qfmdl/__init__.py b/tools/io_mesh_qfmdl/__init__.py index a3abea3cd..1f4a682c6 100644 --- a/tools/io_mesh_qfmdl/__init__.py +++ b/tools/io_mesh_qfmdl/__init__.py @@ -24,14 +24,14 @@ bl_info = { "name": "Quake MDL format", "author": "Bill Currie", - "blender": (2, 6, 3), + "blender": (2, 80, 0), "api": 35622, "location": "File > Import-Export", "description": "Import-Export Quake MDL (version 6) files. (.mdl)", - "warning": "not even alpha", + "warning": "still work in progress", "wiki_url": "", "tracker_url": "", -# "support": 'OFFICIAL', +# "support": 'OFFICIAL', "category": "Import-Export"} # To support reload properly, try to access a package var, if it's there, @@ -64,28 +64,35 @@ EFFECTS=( ('EF_TRACER2', "Tracer 2", "Orange split trail + rotate"), ('EF_TRACER3', "Tracer 3", "Purple split trail"), ) +''' + class QFMDLSettings(bpy.types.PropertyGroup): +# eyeposition = FloatVectorProperty( +# name="Eye Position", +# description="View possion relative to object origin") +# synctype = EnumProperty( +# items=SYNCTYPE, +# name="Sync Type", +# description="Add random time offset for automatic animations") +# rotate = BoolProperty( +# name="Rotate", +# description="Rotate automatically (for pickup items)") +# effects = EnumProperty( +# items=EFFECTS, +# name="Effects", +# description="Particle trail effects") +# #doesn't work :( +# #script = PointerProperty( +# # type=bpy.types.Object, +# # name="Script", +# # description="Script for animating frames and skins") -class QFMDLSettings(bpy.types.PropertyGroup): - ''' - eyeposition = FloatVectorProperty( - name="Eye Position", - description="View possion relative to object origin") - synctype = EnumProperty( - items=SYNCTYPE, - name="Sync Type", - description="Add random time offset for automatic animations") - rotate = BoolProperty( - name="Rotate", - description="Rotate automatically (for pickup items)") - effects = EnumProperty( - items=EFFECTS, - name="Effects", - description="Particle trail effects") - #doesn't work :( - #script = PointerProperty( - # type=bpy.types.Object, - # name="Script", - # description="Script for animating frames and skins") +# xform = BoolProperty( +# name="Auto transform", +# description="Auto-apply location/rotation/scale when exporting", +# default=True) +# md16 = BoolProperty( +# name="16-bit", +# description="16 bit vertex coordinates: QuakeForge only") xform = BoolProperty( name="Auto transform", @@ -94,10 +101,10 @@ class QFMDLSettings(bpy.types.PropertyGroup): md16 = BoolProperty( name="16-bit", description="16 bit vertex coordinates: QuakeForge only") - ''' script = StringProperty( name="Script", - description="Script for animating frames and skins") + description="Script for animating frames and skins") +''' class ImportMDL6(bpy.types.Operator, ImportHelper): '''Load a Quake MDL (v6) File''' @@ -155,6 +162,7 @@ class ExportMDL6(bpy.types.Operator, ExportHelper): keywords = self.as_keywords (ignore=("check_existing", "filter_glob")) return export_mdl.export_mdl(self, context, **keywords) +''' class OBJECT_PT_MDLPanel(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' @@ -176,6 +184,7 @@ class OBJECT_PT_MDLPanel(bpy.types.Panel): layout.prop(obj.qfmdl, "script") layout.prop(obj.qfmdl, "xform") layout.prop(obj.qfmdl, "md16") +''' def menu_func_import(self, context): self.layout.operator(ImportMDL6.bl_idname, text="Quake MDL (.mdl)") @@ -184,21 +193,25 @@ def menu_func_import(self, context): def menu_func_export(self, context): self.layout.operator(ExportMDL6.bl_idname, text="Quake MDL (.mdl)") +classes = ( + #OBJECT_PT_MDLPanel, + ImportMDL6, + ExportMDL6 +) def register(): - bpy.utils.register_module(__name__) - - bpy.types.Object.qfmdl = PointerProperty(type=QFMDLSettings) - - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) + for cls in classes: + bpy.utils.register_class(cls) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) + bpy.types.TOPBAR_MT_file_export.append(menu_func_export) def unregister(): - bpy.utils.unregister_module(__name__) + for cls in classes: + bpy.utils.unregister_class(cls) - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) + bpy.types.TOPBAR_MT_file_import.remove(menu_func_import) + bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) if __name__ == "__main__": register() diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index d6f7371d0..0344c4561 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -86,7 +86,7 @@ def null_skin(size): return skin def active_uv(mesh): - for uvt in mesh.uv_textures: + for uvt in mesh.uv_layers: if uvt.active: return uvt return None @@ -95,6 +95,18 @@ def make_skin(operator, mdl, mesh): uvt = active_uv(mesh) mdl.skinwidth, mdl.skinheight = (4, 4) skin = null_skin((mdl.skinwidth, mdl.skinheight)) + + mat = bpy.context.object.data.materials[0] + allNodes = mat.node_tree.nodes + + for node in allNodes: + if node.type == "TEX_IMAGE": + image = node.image + mdl.skinwidth, mdl.skinheight = image.size + skin = convert_image(image) + mdl.skins.append(skin) + + ''' if (uvt and uvt.data and uvt.data[0].image): image = uvt.data[0].image if (uvt.data[0].image.size[0] and uvt.data[0].image.size[1]): @@ -103,7 +115,9 @@ def make_skin(operator, mdl, mesh): else: operator.report({'WARNING'}, "Texture '%s' invalid (missing?)." % image.name) + mdl.skins.append(skin) + ''' def build_tris(mesh): # mdl files have a 1:1 relationship between stverts and 3d verts. @@ -183,7 +197,7 @@ def calc_average_area(mdl): a = Vector(verts[0].r) - Vector(verts[1].r) b = Vector(verts[2].r) - Vector(verts[1].r) c = a.cross(b) - totalarea += (c * c) ** 0.5 / 2.0 + totalarea += (c @ c) ** 0.5 / 2.0 return totalarea / len(mdl.tris) def get_properties( @@ -301,7 +315,8 @@ def export_mdl( ): obj = context.active_object - mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg? + #mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg? + mesh = obj.to_mesh(context.depsgraph, True, calc_undeformed=False) #if not check_faces(mesh): # operator.report({'ERROR'}, # "Mesh has faces with more than 3 vertices.") @@ -334,7 +349,7 @@ def export_mdl( curframe = context.scene.frame_current for fno in range(context.scene.frame_start, context.scene.frame_end + 1): context.scene.frame_set(fno) - mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg? + mesh = obj.to_mesh(context.depsgraph, True, calc_undeformed=False) #wysiwyg? if xform: mesh.transform(mdl.obj.matrix_world) mdl.frames.append(make_frame(mesh, vertmap)) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index feca0fa08..c3e64b3c0 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -39,7 +39,7 @@ def make_verts(mdl, framenum, subframenum=0): ( 0, 0,s.z,o.z), ( 0, 0, 0, 1))) for v in frame.verts: - verts.append(m * Vector(v.r)) + verts.append(m @ Vector(v.r)) return verts def make_faces(mdl): @@ -87,7 +87,7 @@ def load_skins(mdl): p[l + 2] = c[2] / 255.0 p[l + 3] = 1.0 img.pixels[:] = p[:] - img.pack(True) + img.pack(as_png=True) img.use_fake_user = True mdl.images=[] @@ -100,27 +100,47 @@ def load_skins(mdl): def setup_skins(mdl, uvs): load_skins(mdl) - img = mdl.images[0] # use the first skin for now - uvlay = mdl.mesh.uv_textures.new(mdl.name) - uvloop = mdl.mesh.uv_layers[0] - for i, texpoly in enumerate(uvlay.data): +# img = mdl.images[0] # use the first skin for now +# uvlay = mdl.mesh.uv_textures.new(mdl.name) +# uvloop = mdl.mesh.uv_layers[0] +# for i, texpoly in enumerate(uvlay.data): + uvloop = mdl.mesh.uv_layers.new(name = mdl.name) + for i in range(len(mdl.mesh.polygons)): poly = mdl.mesh.polygons[i] mdl_uv = uvs[i] - texpoly.image = img +# texpoly.image = img # TODO: commented out by jazz for j,k in enumerate(poly.loop_indices): uvloop.data[k].uv = mdl_uv[j] + + # Create main material mat = bpy.data.materials.new(mdl.name) + mat.blend_method = 'OPAQUE' mat.diffuse_color = (1,1,1) - mat.use_raytrace = False - tex = bpy.data.textures.new(mdl.name, 'IMAGE') - tex.extension = 'CLIP' - tex.use_preview_alpha = True - tex.image = img - mat.texture_slots.add() - ts = mat.texture_slots[0] - ts.texture = tex - ts.use_map_alpha = True - ts.texture_coords = 'UV' + mat.metallic = 1 + mat.roughness = 1 + mat.specular_intensity = 0 + mat.use_nodes = True + + # TODO: turn transform to True and position it properly in editor + emissionNode = mat.node_tree.nodes.new("ShaderNodeEmission") + shaderOut = mat.node_tree.nodes["Material Output"] + bdsf_node = mat.node_tree.nodes["Principled BSDF"] + mat.node_tree.nodes.remove(bdsf_node) + + #Add skingroup + #bpy.ops.object.material_slot_add() + #bpy.ops.material.new() + + #Add all existing textures to shader node + for i in range(len(mdl.images)): + tex_node = mat.node_tree.nodes.new("ShaderNodeTexImage") + tex_node.image = mdl.images[i] + tex_node.interpolation = "Closest" + if i == 0: + # connect only first texture (we'll need something smarter in the future) + mat.node_tree.links.new(tex_node.outputs[0], emissionNode.inputs[0]) + + mat.node_tree.links.new(emissionNode.outputs[0], shaderOut.inputs[0]) mdl.mesh.materials.append(mat) def make_shape_key(mdl, framenum, subframenum=0): @@ -133,7 +153,7 @@ def make_shape_key(mdl, framenum, subframenum=0): name = frame.name else: frame.name = name - frame.key = mdl.obj.shape_key_add(name) + frame.key = mdl.obj.shape_key_add(name=name) frame.key.value = 0.0 mdl.keys.append(frame.key) s = Vector(mdl.scale) @@ -143,11 +163,11 @@ def make_shape_key(mdl, framenum, subframenum=0): ( 0, 0,s.z,o.z), ( 0, 0, 0, 1))) for i, v in enumerate(frame.verts): - frame.key.data[i].co = m * Vector(v.r) + frame.key.data[i].co = m @ Vector(v.r) def build_shape_keys(mdl): mdl.keys = [] - mdl.obj.shape_key_add("Basis") + mdl.obj.shape_key_add(name="Basis",from_mix=False) mdl.mesh.shape_keys.name = mdl.name mdl.obj.active_shape_key_index = 0 for i, frame in enumerate(mdl.frames): @@ -327,6 +347,7 @@ def parse_flags(flags): else: return 'EF_NONE' +''' def set_properties(mdl): mdl.obj.qfmdl.eyeposition = mdl.eyeposition try: @@ -337,12 +358,13 @@ def set_properties(mdl): mdl.obj.qfmdl.effects = parse_flags(mdl.flags) mdl.obj.qfmdl.script = mdl.text.name #FIXME really want the text object mdl.obj.qfmdl.md16 = (mdl.ident == "MD16") +''' -def import_mdl(operator, context, filepath): - bpy.context.user_preferences.edit.use_global_undo = False +def import_mdl(operator, context, filepath, **opts): + bpy.context.preferences.edit.use_global_undo = False - for obj in bpy.context.scene.objects: - obj.select = False + for obj in bpy.context.scene.collection.objects: + obj.select_set(False) mdl = MDL() if not mdl.read(filepath): @@ -354,18 +376,19 @@ def import_mdl(operator, context, filepath): mdl.mesh = bpy.data.meshes.new(mdl.name) mdl.mesh.from_pydata(verts, [], faces) mdl.obj = bpy.data.objects.new(mdl.name, mdl.mesh) - bpy.context.scene.objects.link(mdl.obj) - bpy.context.scene.objects.active = mdl.obj - mdl.obj.select = True + + bpy.context.scene.collection.objects.link(mdl.obj) + mdl.obj.select_set(True) + bpy.context.view_layer.objects.active = mdl.obj setup_skins(mdl, uvs) if len(mdl.frames) > 1 or mdl.frames[0].type: build_shape_keys(mdl) merge_frames(mdl) build_actions(mdl) write_text(mdl) - set_properties(mdl) + #set_properties(mdl) #TODO: bring it back mdl.mesh.update() - bpy.context.user_preferences.edit.use_global_undo = True + bpy.context.preferences.edit.use_global_undo = True return {'FINISHED'} From 66fe862a8736c171df7562110ab231b7f4c249e4 Mon Sep 17 00:00:00 2001 From: khreathor Date: Tue, 8 Jan 2019 03:55:13 +0100 Subject: [PATCH 0218/3664] Import skingroups as separate materials with skins as textures --- tools/io_mesh_qfmdl/import_mdl.py | 66 +++++++++++++++++++------------ 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index c3e64b3c0..7b67d6d09 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -98,6 +98,16 @@ def load_skins(mdl): else: load_skin(skin, "%s_%d" % (mdl.name, i)) +def setup_main_material(mdl): + mat = bpy.data.materials.new(mdl.name) + mat.blend_method = 'OPAQUE' + mat.diffuse_color = (1, 1, 1) + mat.metallic = 1 + mat.roughness = 1 + mat.specular_intensity = 0 + mat.use_nodes = True + return mat + def setup_skins(mdl, uvs): load_skins(mdl) # img = mdl.images[0] # use the first skin for now @@ -112,36 +122,40 @@ def setup_skins(mdl, uvs): for j,k in enumerate(poly.loop_indices): uvloop.data[k].uv = mdl_uv[j] - # Create main material - mat = bpy.data.materials.new(mdl.name) - mat.blend_method = 'OPAQUE' - mat.diffuse_color = (1,1,1) - mat.metallic = 1 - mat.roughness = 1 - mat.specular_intensity = 0 - mat.use_nodes = True + #Load all skins + for i, skin in enumerate(mdl.skins): + if skin.type: + mat = setup_main_material(mdl) + emissionNode = mat.node_tree.nodes.new("ShaderNodeEmission") + shaderOut = mat.node_tree.nodes["Material Output"] + mat.node_tree.nodes.remove(mat.node_tree.nodes["Principled BSDF"]) - # TODO: turn transform to True and position it properly in editor - emissionNode = mat.node_tree.nodes.new("ShaderNodeEmission") - shaderOut = mat.node_tree.nodes["Material Output"] - bdsf_node = mat.node_tree.nodes["Principled BSDF"] - mat.node_tree.nodes.remove(bdsf_node) + for j, subskin in enumerate(skin.skins): + tex_node = mat.node_tree.nodes.new("ShaderNodeTexImage") + tex_node.image = mdl.images[i + j] + tex_node.interpolation = "Closest" + if j == 0: + # connect only first texture (we'll need something smarter in the future) + mat.node_tree.links.new(tex_node.outputs[0], emissionNode.inputs[0]) - #Add skingroup - #bpy.ops.object.material_slot_add() - #bpy.ops.material.new() + mat.node_tree.links.new(emissionNode.outputs[0], shaderOut.inputs[0]) + mdl.mesh.materials.append(mat) + + else: + mat = setup_main_material(mdl) + + # TODO: turn transform to True and position it properly in editor + emissionNode = mat.node_tree.nodes.new("ShaderNodeEmission") + shaderOut = mat.node_tree.nodes["Material Output"] + mat.node_tree.nodes.remove(mat.node_tree.nodes["Principled BSDF"]) + + tex_node = mat.node_tree.nodes.new("ShaderNodeTexImage") + tex_node.image = mdl.images[i] + tex_node.interpolation = "Closest" - #Add all existing textures to shader node - for i in range(len(mdl.images)): - tex_node = mat.node_tree.nodes.new("ShaderNodeTexImage") - tex_node.image = mdl.images[i] - tex_node.interpolation = "Closest" - if i == 0: - # connect only first texture (we'll need something smarter in the future) mat.node_tree.links.new(tex_node.outputs[0], emissionNode.inputs[0]) - - mat.node_tree.links.new(emissionNode.outputs[0], shaderOut.inputs[0]) - mdl.mesh.materials.append(mat) + mat.node_tree.links.new(emissionNode.outputs[0], shaderOut.inputs[0]) + mdl.mesh.materials.append(mat) def make_shape_key(mdl, framenum, subframenum=0): frame = mdl.frames[framenum] From 17e76149a13329e4d8e0200679006a80f587a1f7 Mon Sep 17 00:00:00 2001 From: khreathor Date: Wed, 9 Jan 2019 02:04:05 +0100 Subject: [PATCH 0219/3664] Adjust playback range on import, to fit mdl's animation length --- tools/io_mesh_qfmdl/export_mdl.py | 1 - tools/io_mesh_qfmdl/import_mdl.py | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index 0344c4561..5e9ea43e0 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -346,7 +346,6 @@ def export_mdl( if not mdl.skins: make_skin(operator, mdl, mesh) if not mdl.frames: - curframe = context.scene.frame_current for fno in range(context.scene.frame_start, context.scene.frame_end + 1): context.scene.frame_set(fno) mesh = obj.to_mesh(context.depsgraph, True, calc_undeformed=False) #wysiwyg? diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index 7b67d6d09..15e1cf063 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -184,13 +184,16 @@ def build_shape_keys(mdl): mdl.obj.shape_key_add(name="Basis",from_mix=False) mdl.mesh.shape_keys.name = mdl.name mdl.obj.active_shape_key_index = 0 + bpy.context.scene.frame_end = 0 for i, frame in enumerate(mdl.frames): frame = mdl.frames[i] if frame.type: for j in range(len(frame.frames)): make_shape_key(mdl, i, j) + bpy.context.scene.frame_end += 1 else: make_shape_key(mdl, i) + bpy.context.scene.frame_end += 1 def set_keys(act, data): for d in data: @@ -395,6 +398,9 @@ def import_mdl(operator, context, filepath, **opts): mdl.obj.select_set(True) bpy.context.view_layer.objects.active = mdl.obj setup_skins(mdl, uvs) + + bpy.context.scene.frame_start = 1 + bpy.context.scene.frame_end = 1 if len(mdl.frames) > 1 or mdl.frames[0].type: build_shape_keys(mdl) merge_frames(mdl) From 4d1f05186b995414169bc8515ca86eef648f9d91 Mon Sep 17 00:00:00 2001 From: khreathor Date: Thu, 10 Jan 2019 04:56:21 +0100 Subject: [PATCH 0220/3664] Skingroups export added --- tools/io_mesh_qfmdl/export_mdl.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index 5e9ea43e0..baf97e72c 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -96,15 +96,30 @@ def make_skin(operator, mdl, mesh): mdl.skinwidth, mdl.skinheight = (4, 4) skin = null_skin((mdl.skinwidth, mdl.skinheight)) - mat = bpy.context.object.data.materials[0] - allNodes = mat.node_tree.nodes + materials = bpy.context.object.data.materials - for node in allNodes: - if node.type == "TEX_IMAGE": - image = node.image - mdl.skinwidth, mdl.skinheight = image.size - skin = convert_image(image) - mdl.skins.append(skin) + for mat in materials: + allNodes = mat.node_tree.nodes + if len(allNodes) > 1: + skingroup = MDL.Skin() + skingroup.type = 1 + skingroup.skins = [] + skingroup.times = [] + for node in allNodes: + if node.type == "TEX_IMAGE": + image = node.image + mdl.skinwidth, mdl.skinheight = image.size + skin = convert_image(image) + skingroup.skins.append(skin) + skingroup.times.append(0.1) # hardcoded at the moment + mdl.skins.append(skingroup) + else: + for node in allNodes: + if node.type == "TEX_IMAGE": + image = node.image + mdl.skinwidth, mdl.skinheight = image.size + skin = convert_image(image) + mdl.skins.append(skin) ''' if (uvt and uvt.data and uvt.data[0].image): From a13c382969691adcd5ec8d15183b9cf5e580f70f Mon Sep 17 00:00:00 2001 From: khreathor Date: Thu, 10 Jan 2019 05:40:56 +0100 Subject: [PATCH 0221/3664] Skingroup images import order fix --- tools/io_mesh_qfmdl/import_mdl.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index 15e1cf063..28ac24762 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -123,6 +123,7 @@ def setup_skins(mdl, uvs): uvloop.data[k].uv = mdl_uv[j] #Load all skins + img_counter = 0 for i, skin in enumerate(mdl.skins): if skin.type: mat = setup_main_material(mdl) @@ -132,7 +133,8 @@ def setup_skins(mdl, uvs): for j, subskin in enumerate(skin.skins): tex_node = mat.node_tree.nodes.new("ShaderNodeTexImage") - tex_node.image = mdl.images[i + j] + tex_node.image = mdl.images[img_counter] + img_counter += 1 tex_node.interpolation = "Closest" if j == 0: # connect only first texture (we'll need something smarter in the future) @@ -150,7 +152,8 @@ def setup_skins(mdl, uvs): mat.node_tree.nodes.remove(mat.node_tree.nodes["Principled BSDF"]) tex_node = mat.node_tree.nodes.new("ShaderNodeTexImage") - tex_node.image = mdl.images[i] + tex_node.image = mdl.images[img_counter] + img_counter += 1 tex_node.interpolation = "Closest" mat.node_tree.links.new(tex_node.outputs[0], emissionNode.inputs[0]) From 4f29f57e77a503fefb8b7d16fb4ba9691f18f9cd Mon Sep 17 00:00:00 2001 From: khreathor Date: Thu, 10 Jan 2019 20:56:40 +0100 Subject: [PATCH 0222/3664] Proper node positioning after import --- tools/io_mesh_qfmdl/import_mdl.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index 28ac24762..272f8de1b 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -131,11 +131,20 @@ def setup_skins(mdl, uvs): shaderOut = mat.node_tree.nodes["Material Output"] mat.node_tree.nodes.remove(mat.node_tree.nodes["Principled BSDF"]) + emissionNode.location = (0, 0) + shaderOut.location = (200, 0) + + yPos = 0 + for j, subskin in enumerate(skin.skins): tex_node = mat.node_tree.nodes.new("ShaderNodeTexImage") tex_node.image = mdl.images[img_counter] img_counter += 1 tex_node.interpolation = "Closest" + + tex_node.location = (-300, yPos) + yPos -= 280 + if j == 0: # connect only first texture (we'll need something smarter in the future) mat.node_tree.links.new(tex_node.outputs[0], emissionNode.inputs[0]) @@ -156,6 +165,10 @@ def setup_skins(mdl, uvs): img_counter += 1 tex_node.interpolation = "Closest" + emissionNode.location = (0, 0) + shaderOut.location = (200, 0) + tex_node.location = (-300, 0) + mat.node_tree.links.new(tex_node.outputs[0], emissionNode.inputs[0]) mat.node_tree.links.new(emissionNode.outputs[0], shaderOut.inputs[0]) mdl.mesh.materials.append(mat) From 94c3c8c2cb2cb71f0a4204aa50e7587310021733 Mon Sep 17 00:00:00 2001 From: khreathor Date: Fri, 11 Jan 2019 01:40:05 +0100 Subject: [PATCH 0223/3664] Skingroup image export order based on texture node position (height) in shader editor. Nodes with higher position are exported first. --- tools/io_mesh_qfmdl/export_mdl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index baf97e72c..25eca68fa 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -105,7 +105,9 @@ def make_skin(operator, mdl, mesh): skingroup.type = 1 skingroup.skins = [] skingroup.times = [] - for node in allNodes: + sortedNodes = list(allNodes) + sortedNodes.sort(key=lambda x: x.location[1], reverse=True) + for node in sortedNodes: if node.type == "TEX_IMAGE": image = node.image mdl.skinwidth, mdl.skinheight = image.size From 31fa7a81efb24c7631c207fb628f0102c054fbf8 Mon Sep 17 00:00:00 2001 From: khreathor Date: Wed, 16 Jan 2019 03:08:48 +0100 Subject: [PATCH 0224/3664] Fix for single skin being marked as skingroup --- tools/io_mesh_qfmdl/export_mdl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index 25eca68fa..9dcdd8577 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -99,7 +99,7 @@ def make_skin(operator, mdl, mesh): materials = bpy.context.object.data.materials for mat in materials: - allNodes = mat.node_tree.nodes + allNodes = list(filter(lambda node: node.type == "TEX_IMAGE", mat.node_tree.nodes)) if len(allNodes) > 1: skingroup = MDL.Skin() skingroup.type = 1 From 3913febacee35c47c21ffc7c7bf2007d5e97dd4a Mon Sep 17 00:00:00 2001 From: khreathor Date: Wed, 16 Jan 2019 05:15:37 +0100 Subject: [PATCH 0225/3664] MDL properties in object panel are back --- tools/io_mesh_qfmdl/__init__.py | 78 +++++++++++++++++-------------- tools/io_mesh_qfmdl/import_mdl.py | 6 +-- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/tools/io_mesh_qfmdl/__init__.py b/tools/io_mesh_qfmdl/__init__.py index 1f4a682c6..6ea6b2ea6 100644 --- a/tools/io_mesh_qfmdl/__init__.py +++ b/tools/io_mesh_qfmdl/__init__.py @@ -64,35 +64,28 @@ EFFECTS=( ('EF_TRACER2', "Tracer 2", "Orange split trail + rotate"), ('EF_TRACER3', "Tracer 3", "Purple split trail"), ) -''' - class QFMDLSettings(bpy.types.PropertyGroup): -# eyeposition = FloatVectorProperty( -# name="Eye Position", -# description="View possion relative to object origin") -# synctype = EnumProperty( -# items=SYNCTYPE, -# name="Sync Type", -# description="Add random time offset for automatic animations") -# rotate = BoolProperty( -# name="Rotate", -# description="Rotate automatically (for pickup items)") -# effects = EnumProperty( -# items=EFFECTS, -# name="Effects", -# description="Particle trail effects") -# #doesn't work :( -# #script = PointerProperty( -# # type=bpy.types.Object, -# # name="Script", -# # description="Script for animating frames and skins") -# xform = BoolProperty( -# name="Auto transform", -# description="Auto-apply location/rotation/scale when exporting", -# default=True) -# md16 = BoolProperty( -# name="16-bit", -# description="16 bit vertex coordinates: QuakeForge only") +class QFMDLSettings(bpy.types.PropertyGroup): + eyeposition = FloatVectorProperty( + name="Eye Position", + description="View possion relative to object origin") + synctype = EnumProperty( + items=SYNCTYPE, + name="Sync Type", + description="Add random time offset for automatic animations") + rotate = BoolProperty( + name="Rotate", + description="Rotate automatically (for pickup items)") + effects = EnumProperty( + items=EFFECTS, + name="Effects", + description="Particle trail effects") + + #doesn't work :( + #script = PointerProperty( + # type=bpy.types.Object, + # name="Script", + # description="Script for animating frames and skins") xform = BoolProperty( name="Auto transform", @@ -101,10 +94,16 @@ EFFECTS=( md16 = BoolProperty( name="16-bit", description="16 bit vertex coordinates: QuakeForge only") - script = StringProperty( - name="Script", - description="Script for animating frames and skins") -''' + xform = BoolProperty( + name="Auto transform", + description="Auto-apply location/rotation/scale when exporting", + default=True) + md16 = BoolProperty( + name="16-bit", + description="16 bit vertex coordinates: QuakeForge only") + #script = StringProperty( + # name="Script", + # description="Script for animating frames and skins") class ImportMDL6(bpy.types.Operator, ImportHelper): '''Load a Quake MDL (v6) File''' @@ -162,18 +161,23 @@ class ExportMDL6(bpy.types.Operator, ExportHelper): keywords = self.as_keywords (ignore=("check_existing", "filter_glob")) return export_mdl.export_mdl(self, context, **keywords) -''' class OBJECT_PT_MDLPanel(bpy.types.Panel): + bl_label = "MDL Properties" bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = 'object' - bl_label = 'QF MDL' + bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): obj = context.active_object return obj and obj.type == 'MESH' + def draw_header(self, context): + layout = self.layout + obj = context.object + layout.prop(obj, "select", text="") + def draw(self, context): layout = self.layout obj = context.active_object @@ -184,7 +188,6 @@ class OBJECT_PT_MDLPanel(bpy.types.Panel): layout.prop(obj.qfmdl, "script") layout.prop(obj.qfmdl, "xform") layout.prop(obj.qfmdl, "md16") -''' def menu_func_import(self, context): self.layout.operator(ImportMDL6.bl_idname, text="Quake MDL (.mdl)") @@ -194,7 +197,8 @@ def menu_func_export(self, context): self.layout.operator(ExportMDL6.bl_idname, text="Quake MDL (.mdl)") classes = ( - #OBJECT_PT_MDLPanel, + QFMDLSettings, + OBJECT_PT_MDLPanel, ImportMDL6, ExportMDL6 ) @@ -203,6 +207,8 @@ def register(): for cls in classes: bpy.utils.register_class(cls) + bpy.types.Object.qfmdl = PointerProperty(type=QFMDLSettings) + bpy.types.TOPBAR_MT_file_import.append(menu_func_import) bpy.types.TOPBAR_MT_file_export.append(menu_func_export) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index 272f8de1b..545d1873d 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -380,7 +380,6 @@ def parse_flags(flags): else: return 'EF_NONE' -''' def set_properties(mdl): mdl.obj.qfmdl.eyeposition = mdl.eyeposition try: @@ -389,9 +388,8 @@ def set_properties(mdl): mdl.obj.qfmdl.synctype = 'ST_SYNC' mdl.obj.qfmdl.rotate = (mdl.flags & MDL.EF_ROTATE) and True or False mdl.obj.qfmdl.effects = parse_flags(mdl.flags) - mdl.obj.qfmdl.script = mdl.text.name #FIXME really want the text object + #mdl.obj.qfmdl.script = mdl.text.name #FIXME really want the text object mdl.obj.qfmdl.md16 = (mdl.ident == "MD16") -''' def import_mdl(operator, context, filepath, **opts): bpy.context.preferences.edit.use_global_undo = False @@ -422,7 +420,7 @@ def import_mdl(operator, context, filepath, **opts): merge_frames(mdl) build_actions(mdl) write_text(mdl) - #set_properties(mdl) #TODO: bring it back + set_properties(mdl) mdl.mesh.update() From ff5f9f18316b22faba91bb2d107fb4aa5200f68c Mon Sep 17 00:00:00 2001 From: khreathor Date: Wed, 16 Jan 2019 21:40:34 +0100 Subject: [PATCH 0226/3664] Add "empty" skin during export for models with no materials or texture nodes --- tools/io_mesh_qfmdl/export_mdl.py | 53 +++++++++++++++++-------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index 9dcdd8577..d68c7a6cd 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -98,30 +98,35 @@ def make_skin(operator, mdl, mesh): materials = bpy.context.object.data.materials - for mat in materials: - allNodes = list(filter(lambda node: node.type == "TEX_IMAGE", mat.node_tree.nodes)) - if len(allNodes) > 1: - skingroup = MDL.Skin() - skingroup.type = 1 - skingroup.skins = [] - skingroup.times = [] - sortedNodes = list(allNodes) - sortedNodes.sort(key=lambda x: x.location[1], reverse=True) - for node in sortedNodes: - if node.type == "TEX_IMAGE": - image = node.image - mdl.skinwidth, mdl.skinheight = image.size - skin = convert_image(image) - skingroup.skins.append(skin) - skingroup.times.append(0.1) # hardcoded at the moment - mdl.skins.append(skingroup) - else: - for node in allNodes: - if node.type == "TEX_IMAGE": - image = node.image - mdl.skinwidth, mdl.skinheight = image.size - skin = convert_image(image) - mdl.skins.append(skin) + if len(materials) > 0: + for mat in materials: + allTextureNodes = list(filter(lambda node: node.type == "TEX_IMAGE", mat.node_tree.nodes)) + if len(allTextureNodes) > 1: #=== skingroup + skingroup = MDL.Skin() + skingroup.type = 1 + skingroup.skins = [] + skingroup.times = [] + sortedNodes = list(allTextureNodes) + sortedNodes.sort(key=lambda x: x.location[1], reverse=True) + for node in sortedNodes: + if node.type == "TEX_IMAGE": + image = node.image + mdl.skinwidth, mdl.skinheight = image.size + skin = convert_image(image) + skingroup.skins.append(skin) + skingroup.times.append(0.1) # hardcoded at the moment + mdl.skins.append(skingroup) + elif len(allTextureNodes) == 1: #=== single skin + for node in allTextureNodes: + if node.type == "TEX_IMAGE": + image = node.image + mdl.skinwidth, mdl.skinheight = image.size + skin = convert_image(image) + mdl.skins.append(skin) + else: + mdl.skins.append(skin) # add empty skin - no texture nodes + else: + mdl.skins.append(skin) # add empty skin - no materials ''' if (uvt and uvt.data and uvt.data[0].image): From 33d114c09e358f7c0bbc304a525ef0e60e408f06 Mon Sep 17 00:00:00 2001 From: khreathor Date: Thu, 17 Jan 2019 22:34:45 +0100 Subject: [PATCH 0227/3664] Set playback/animation range to start from frame 1 --- tools/io_mesh_qfmdl/import_mdl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index 545d1873d..1eb057b68 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -211,6 +211,8 @@ def build_shape_keys(mdl): make_shape_key(mdl, i) bpy.context.scene.frame_end += 1 + bpy.context.scene.frame_start = 1 + def set_keys(act, data): for d in data: key, co = d From 36da80c0d0b7891c9c639772ce9eaeac1d8a7132 Mon Sep 17 00:00:00 2001 From: khreathor Date: Fri, 18 Jan 2019 03:16:16 +0100 Subject: [PATCH 0228/3664] Export proper frame names --- tools/io_mesh_qfmdl/export_mdl.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index d68c7a6cd..f9aa5ac2b 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -189,8 +189,14 @@ def convert_stverts(mdl, stverts): t = ((t % mdl.skinheight) + mdl.skinheight) % mdl.skinheight stverts[i] = MDL.STVert((s, t)) -def make_frame(mesh, vertmap): +def make_frame(mesh, vertmap, idx): frame = MDL.Frame() + frame.name = "frame" + str(idx) + + shape_keys_amount = len(bpy.context.object.data.shape_keys.key_blocks) + if shape_keys_amount > idx: + frame.name = bpy.context.object.data.shape_keys.key_blocks[idx].name + for v in vertmap: mv = mesh.vertices[v] vert = MDL.Vert(tuple(mv.co), map_normal(mv.normal)) @@ -373,7 +379,7 @@ def export_mdl( mesh = obj.to_mesh(context.depsgraph, True, calc_undeformed=False) #wysiwyg? if xform: mesh.transform(mdl.obj.matrix_world) - mdl.frames.append(make_frame(mesh, vertmap)) + mdl.frames.append(make_frame(mesh, vertmap, fno)) convert_stverts(mdl, mdl.stverts) mdl.size = calc_average_area(mdl) scale_verts(mdl) From 11e5f39fdc7732e8f13fd6b861d798959af0bae9 Mon Sep 17 00:00:00 2001 From: khreathor Date: Sat, 19 Jan 2019 05:10:21 +0100 Subject: [PATCH 0229/3664] Fix for the export error when there is no Shape Keys available --- tools/io_mesh_qfmdl/export_mdl.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index f9aa5ac2b..6b7237c4f 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -193,9 +193,10 @@ def make_frame(mesh, vertmap, idx): frame = MDL.Frame() frame.name = "frame" + str(idx) - shape_keys_amount = len(bpy.context.object.data.shape_keys.key_blocks) - if shape_keys_amount > idx: - frame.name = bpy.context.object.data.shape_keys.key_blocks[idx].name + if bpy.context.object.data.shape_keys: + shape_keys_amount = len(bpy.context.object.data.shape_keys.key_blocks) + if shape_keys_amount > idx: + frame.name = bpy.context.object.data.shape_keys.key_blocks[idx].name for v in vertmap: mv = mesh.vertices[v] From 008b5a4d2c3e7113b2ac3ffd307e0e9a80326178 Mon Sep 17 00:00:00 2001 From: khreathor Date: Wed, 29 May 2019 02:08:37 +0200 Subject: [PATCH 0230/3664] Import/Export fixes after some Blender 2.8 API changes --- tools/io_mesh_qfmdl/export_mdl.py | 11 ++++++++--- tools/io_mesh_qfmdl/import_mdl.py | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index 6b7237c4f..8391baeb9 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -344,8 +344,10 @@ def export_mdl( ): obj = context.active_object - #mesh = obj.to_mesh(context.scene, True, 'PREVIEW') #wysiwyg? - mesh = obj.to_mesh(context.depsgraph, True, calc_undeformed=False) + obj.update_from_editmode() + depsgraph = context.evaluated_depsgraph_get() + ob_eval = obj.evaluated_get(depsgraph) + mesh = ob_eval.to_mesh() #if not check_faces(mesh): # operator.report({'ERROR'}, # "Mesh has faces with more than 3 vertices.") @@ -377,7 +379,10 @@ def export_mdl( if not mdl.frames: for fno in range(context.scene.frame_start, context.scene.frame_end + 1): context.scene.frame_set(fno) - mesh = obj.to_mesh(context.depsgraph, True, calc_undeformed=False) #wysiwyg? + obj.update_from_editmode() + depsgraph = context.evaluated_depsgraph_get() + ob_eval = obj.evaluated_get(depsgraph) + mesh = ob_eval.to_mesh() if xform: mesh.transform(mdl.obj.matrix_world) mdl.frames.append(make_frame(mesh, vertmap, fno)) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index 1eb057b68..adfa8f610 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -87,7 +87,7 @@ def load_skins(mdl): p[l + 2] = c[2] / 255.0 p[l + 3] = 1.0 img.pixels[:] = p[:] - img.pack(as_png=True) + img.pack() img.use_fake_user = True mdl.images=[] @@ -101,7 +101,7 @@ def load_skins(mdl): def setup_main_material(mdl): mat = bpy.data.materials.new(mdl.name) mat.blend_method = 'OPAQUE' - mat.diffuse_color = (1, 1, 1) + mat.diffuse_color = (1, 1, 1, 1) mat.metallic = 1 mat.roughness = 1 mat.specular_intensity = 0 From 839d90981d851d984ad2f80f4231ccbfb087985a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Aug 2019 22:32:37 +0900 Subject: [PATCH 0231/3664] Clean up a few last things for blender 2.80 Many many thanks to Aleksander Marhall for the initial work. --- tools/io_mesh_qfmdl/__init__.py | 33 +++++++++++++------------------ tools/io_mesh_qfmdl/export_mdl.py | 8 ++++---- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/tools/io_mesh_qfmdl/__init__.py b/tools/io_mesh_qfmdl/__init__.py index 6ea6b2ea6..fd1520346 100644 --- a/tools/io_mesh_qfmdl/__init__.py +++ b/tools/io_mesh_qfmdl/__init__.py @@ -66,17 +66,17 @@ EFFECTS=( ) class QFMDLSettings(bpy.types.PropertyGroup): - eyeposition = FloatVectorProperty( + eyeposition : FloatVectorProperty( name="Eye Position", description="View possion relative to object origin") - synctype = EnumProperty( + synctype : EnumProperty( items=SYNCTYPE, name="Sync Type", description="Add random time offset for automatic animations") - rotate = BoolProperty( + rotate : BoolProperty( name="Rotate", description="Rotate automatically (for pickup items)") - effects = EnumProperty( + effects : EnumProperty( items=EFFECTS, name="Effects", description="Particle trail effects") @@ -87,11 +87,11 @@ class QFMDLSettings(bpy.types.PropertyGroup): # name="Script", # description="Script for animating frames and skins") - xform = BoolProperty( + xform : BoolProperty( name="Auto transform", description="Auto-apply location/rotation/scale when exporting", default=True) - md16 = BoolProperty( + md16 : BoolProperty( name="16-bit", description="16 bit vertex coordinates: QuakeForge only") xform = BoolProperty( @@ -111,7 +111,7 @@ class ImportMDL6(bpy.types.Operator, ImportHelper): bl_label = "Import MDL" filename_ext = ".mdl" - filter_glob = StringProperty(default="*.mdl", options={'HIDDEN'}) + filter_glob : StringProperty(default="*.mdl", options={'HIDDEN'}) def execute(self, context): from . import import_mdl @@ -126,28 +126,28 @@ class ExportMDL6(bpy.types.Operator, ExportHelper): bl_options = {'PRESET'}; filename_ext = ".mdl" - filter_glob = StringProperty(default="*.mdl", options={'HIDDEN'}) + filter_glob : StringProperty(default="*.mdl", options={'HIDDEN'}) - eyeposition = FloatVectorProperty( + eyeposition : FloatVectorProperty( name="Eye Position", description="View possion relative to object origin") - synctype = EnumProperty( + synctype : EnumProperty( items=SYNCTYPE, name="Sync Type", description="Add random time offset for automatic animations") - rotate = BoolProperty( + rotate : BoolProperty( name="Rotate", description="Rotate automatically (for pickup items)", default=False) - effects = EnumProperty( + effects : EnumProperty( items=EFFECTS, name="Effects", description="Particle trail effects") - xform = BoolProperty( + xform : BoolProperty( name="Auto transform", description="Auto-apply location/rotation/scale when exporting", default=True) - md16 = BoolProperty( + md16 : BoolProperty( name="16-bit", description="16 bit vertex coordinates: QuakeForge only") @@ -173,11 +173,6 @@ class OBJECT_PT_MDLPanel(bpy.types.Panel): obj = context.active_object return obj and obj.type == 'MESH' - def draw_header(self, context): - layout = self.layout - obj = context.object - layout.prop(obj, "select", text="") - def draw(self, context): layout = self.layout obj = context.active_object diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index 8391baeb9..39b7d8295 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -36,17 +36,17 @@ def check_faces(mesh): faces_ok = True save_select = [] for f in mesh.polygons: - save_select.append(f.select) - f.select = False + save_select.append(f.select_get()) + f.select_set('DESELECT') if len(f.vertices) > 3: - f.select = True + f.select_set('SELECT') faces_ok = False if not faces_ok: mesh.update() return False #reset selection to what it was before the check. for f, s in map(lambda x, y: (x, y), mesh.polygons, save_select): - f.select = s + f.select_set('SELECT' if s else 'DESELECT') mesh.update() return True From c14e5623ad2ba0b8b27b179e6f0bcdd8b28105e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Aug 2019 22:34:45 +0900 Subject: [PATCH 0232/3664] Get the mdl frames script property working Maybe late 2.78+, blender added the ability to use any ID type in PointerProperty, which is just what I wanted for the frames script. --- tools/io_mesh_qfmdl/__init__.py | 12 ++++-------- tools/io_mesh_qfmdl/export_mdl.py | 12 ++---------- tools/io_mesh_qfmdl/import_mdl.py | 2 +- 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/tools/io_mesh_qfmdl/__init__.py b/tools/io_mesh_qfmdl/__init__.py index fd1520346..7a1c8afcb 100644 --- a/tools/io_mesh_qfmdl/__init__.py +++ b/tools/io_mesh_qfmdl/__init__.py @@ -81,11 +81,10 @@ class QFMDLSettings(bpy.types.PropertyGroup): name="Effects", description="Particle trail effects") - #doesn't work :( - #script = PointerProperty( - # type=bpy.types.Object, - # name="Script", - # description="Script for animating frames and skins") + script : PointerProperty( + type=bpy.types.Text, + name="Script", + description="Script for animating frames and skins") xform : BoolProperty( name="Auto transform", @@ -101,9 +100,6 @@ class QFMDLSettings(bpy.types.PropertyGroup): md16 = BoolProperty( name="16-bit", description="16 bit vertex coordinates: QuakeForge only") - #script = StringProperty( - # name="Script", - # description="Script for animating frames and skins") class ImportMDL6(bpy.types.Operator, ImportHelper): '''Load a Quake MDL (v6) File''' diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index 39b7d8295..c11529cba 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -245,18 +245,10 @@ def get_properties( if md16: mdl.ident = "MD16" - #tomporarily disabled - #script = obj.qfmdl.script - script = None + script = obj.qfmdl.script mdl.script = None if script: - try: - script = bpy.data.texts[script].as_string() - except KeyError: - operator.report({'ERROR'}, - "Script '%s' not found." % script) - return False - pl = pldata(script) + pl = pldata(script.as_string()) try: mdl.script = pl.parse() except PListError as err: diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index adfa8f610..1f6a1a8c3 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -390,7 +390,7 @@ def set_properties(mdl): mdl.obj.qfmdl.synctype = 'ST_SYNC' mdl.obj.qfmdl.rotate = (mdl.flags & MDL.EF_ROTATE) and True or False mdl.obj.qfmdl.effects = parse_flags(mdl.flags) - #mdl.obj.qfmdl.script = mdl.text.name #FIXME really want the text object + mdl.obj.qfmdl.script = mdl.text mdl.obj.qfmdl.md16 = (mdl.ident == "MD16") def import_mdl(operator, context, filepath, **opts): From 9d09d65d9a90e9e437c2747feaf96b631fce167b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Aug 2019 16:52:43 +0900 Subject: [PATCH 0233/3664] Clean up some export stuff While it's not there yet, the eventual goal is to support multiple models in the one blend file, so per-object settings is a requirement. --- tools/io_mesh_qfmdl/__init__.py | 24 ---------- tools/io_mesh_qfmdl/export_mdl.py | 77 +++++++++++-------------------- tools/io_mesh_qfmdl/import_mdl.py | 4 +- 3 files changed, 30 insertions(+), 75 deletions(-) diff --git a/tools/io_mesh_qfmdl/__init__.py b/tools/io_mesh_qfmdl/__init__.py index 7a1c8afcb..3d9be7b20 100644 --- a/tools/io_mesh_qfmdl/__init__.py +++ b/tools/io_mesh_qfmdl/__init__.py @@ -119,34 +119,10 @@ class ExportMDL6(bpy.types.Operator, ExportHelper): bl_idname = "export_mesh.quake_mdl_v6" bl_label = "Export MDL" - bl_options = {'PRESET'}; filename_ext = ".mdl" filter_glob : StringProperty(default="*.mdl", options={'HIDDEN'}) - eyeposition : FloatVectorProperty( - name="Eye Position", - description="View possion relative to object origin") - synctype : EnumProperty( - items=SYNCTYPE, - name="Sync Type", - description="Add random time offset for automatic animations") - rotate : BoolProperty( - name="Rotate", - description="Rotate automatically (for pickup items)", - default=False) - effects : EnumProperty( - items=EFFECTS, - name="Effects", - description="Particle trail effects") - xform : BoolProperty( - name="Auto transform", - description="Auto-apply location/rotation/scale when exporting", - default=True) - md16 : BoolProperty( - name="16-bit", - description="16 bit vertex coordinates: QuakeForge only") - @classmethod def poll(cls, context): return (context.active_object != None diff --git a/tools/io_mesh_qfmdl/export_mdl.py b/tools/io_mesh_qfmdl/export_mdl.py index c11529cba..e82d08ca6 100644 --- a/tools/io_mesh_qfmdl/export_mdl.py +++ b/tools/io_mesh_qfmdl/export_mdl.py @@ -96,7 +96,7 @@ def make_skin(operator, mdl, mesh): mdl.skinwidth, mdl.skinheight = (4, 4) skin = null_skin((mdl.skinwidth, mdl.skinheight)) - materials = bpy.context.object.data.materials + materials = mesh.materials if len(materials) > 0: for mat in materials: @@ -189,15 +189,8 @@ def convert_stverts(mdl, stverts): t = ((t % mdl.skinheight) + mdl.skinheight) % mdl.skinheight stverts[i] = MDL.STVert((s, t)) -def make_frame(mesh, vertmap, idx): +def make_frame(mesh, vertmap): frame = MDL.Frame() - frame.name = "frame" + str(idx) - - if bpy.context.object.data.shape_keys: - shape_keys_amount = len(bpy.context.object.data.shape_keys.key_blocks) - if shape_keys_amount > idx: - frame.name = bpy.context.object.data.shape_keys.key_blocks[idx].name - for v in vertmap: mv = mesh.vertices[v] vert = MDL.Vert(tuple(mv.co), map_normal(mv.normal)) @@ -229,20 +222,12 @@ def calc_average_area(mdl): totalarea += (c @ c) ** 0.5 / 2.0 return totalarea / len(mdl.tris) -def get_properties( - operator, - mdl, - eyeposition, - synctype, - rotate, - effects, - xform, - md16): - mdl.eyeposition = eyeposition - mdl.synctype = MDL.SYNCTYPE[synctype] - mdl.flags = ((rotate and MDL.EF_ROTATE or 0) - | MDL.EFFECTS[effects]) - if md16: +def get_properties(operator, mdl, obj): + mdl.eyeposition = tuple(obj.qfmdl.eyeposition) + mdl.synctype = MDL.SYNCTYPE[obj.qfmdl.synctype] + mdl.flags = ((obj.qfmdl.rotate and MDL.EF_ROTATE or 0) + | MDL.EFFECTS[obj.qfmdl.effects]) + if obj.qfmdl.md16: mdl.ident = "MD16" script = obj.qfmdl.script @@ -315,26 +300,24 @@ def process_frame(mdl, scene, frame, vertmap, ingroup = False, return fr mdl.frames += fr.frames[:-1] return fr.frames[-1] - scene.frame_set(int(frameno), frameno - int(frameno)) - mesh = mdl.obj.to_mesh(scene, True, 'PREVIEW') #wysiwyg? + scene.frame_set(int(frameno), subframe = frameno - int(frameno)) + depsgraph = bpy.context.evaluated_depsgraph_get() + mesh = mdl.obj.evaluated_get(depsgraph).to_mesh() #wysiwyg? if mdl.obj.qfmdl.xform: mesh.transform(mdl.obj.matrix_world) fr = make_frame(mesh, vertmap) fr.name = name return fr -def export_mdl( - operator, - context, - filepath = "", - eyeposition = (0.0, 0.0, 0.0), - synctype = SYNCTYPE[1], - rotate = False, - effects = EFFECTS[1], - xform = True, - md16 = False - ): +def get_frame_name(mesh, idx): + name = "frame" + str(idx) + if mesh.shape_keys: + shape_keys_amount = len(mesh.shape_keys.key_blocks) + if shape_keys_amount > idx: + name = mesh.shape_keys.key_blocks[idx].name + return name +def export_mdl(operator, context, filepath): obj = context.active_object obj.update_from_editmode() depsgraph = context.evaluated_depsgraph_get() @@ -346,16 +329,8 @@ def export_mdl( # return {'CANCELLED'} mdl = MDL(obj.name) mdl.obj = obj - if not get_properties( - operator, - mdl, - eyeposition, - synctype, - rotate, - effects, - xform, - md16): - return {'CANCELLED'} + if not get_properties(operator, mdl, obj): + return {'CANCELLED'} mdl.tris, mdl.stverts, vertmap = build_tris(mesh) if mdl.script: @@ -369,15 +344,19 @@ def export_mdl( if not mdl.skins: make_skin(operator, mdl, mesh) if not mdl.frames: - for fno in range(context.scene.frame_start, context.scene.frame_end + 1): + scene = context.scene + for fno in range(scene.frame_start, scene.frame_end + 1): context.scene.frame_set(fno) obj.update_from_editmode() depsgraph = context.evaluated_depsgraph_get() ob_eval = obj.evaluated_get(depsgraph) mesh = ob_eval.to_mesh() - if xform: + if obj.qfmdl.xform: mesh.transform(mdl.obj.matrix_world) - mdl.frames.append(make_frame(mesh, vertmap, fno)) + frame = make_frame(mesh, vertmap) + frame.name = get_frame_name(obj.data, fno) + mdl.frames.append(frame) + convert_stverts(mdl, mdl.stverts) mdl.size = calc_average_area(mdl) scale_verts(mdl) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index 1f6a1a8c3..d27ed45a1 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -296,8 +296,8 @@ def write_text(mdl): /* This script represents the animation data within the model file. It is generated automatically on import, and is optional when exporting. If no script is used when exporting, frames will be exported one per - blender frame from frame 1 to the current frame (inclusive), and only - one skin will be exported. + blender frame from the scene start frame to the scene end frame + (inclusive), and one skin per teximage node will be exported. The fundamental format of the script is documented at http://quakeforge.net/doxygen/property-list.html From 8819d26c95870b7d3b4e6d9018d8068a080e8d63 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 16 Oct 2019 20:57:39 +0900 Subject: [PATCH 0234/3664] Fix a compile error not sure how that one got through --- libs/video/renderer/vid_render_vulkan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 506406394..7fce05272 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -152,7 +152,8 @@ vulkan_vid_render_choose_visual (void) { Vulkan_CreateDevice (vulkan_ctx); vulkan_ctx->choose_visual (vulkan_ctx); - Sys_Printf ("%p %p\n", vulkan_ctx->device->dev, vulkan_ctx->device->queue); + Sys_Printf ("vk choose visual %p %p\n", vulkan_ctx->device->dev, + vulkan_ctx->device->queue.queue); } static void @@ -160,7 +161,7 @@ vulkan_vid_render_create_context (void) { vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); - Sys_Printf ("%p\n", vulkan_ctx->surface); + Sys_Printf ("vk create context %p\n", vulkan_ctx->surface); Vulkan_CreateSwapchain (vulkan_ctx); Sys_Printf ("%p %d", vulkan_ctx->swapchain->swapchain, vulkan_ctx->swapchain->numImages); From 494f673def819dca44e9ac9dd10fea31b84d0e7c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Feb 2020 17:38:51 +0900 Subject: [PATCH 0235/3664] Fix a potential buffer overflow Highly unlikely to have that many sub models, but it does keep gcc quiet. --- libs/models/brush/model_brush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 33e67b952..c81fbabe9 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -962,7 +962,7 @@ Mod_LoadBrushModel (model_t *mod, void *buffer) if (i < mod->numsubmodels - 1) { // duplicate the basic information - char name[10]; + char name[12]; snprintf (name, sizeof (name), "*%i", i + 1); loadmodel = Mod_FindName (name); From 6ce87497f384a58cdb3b86587501de58ad07ffaa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Feb 2020 17:38:51 +0900 Subject: [PATCH 0236/3664] Fix a potential buffer overflow Highly unlikely to have that many sub models, but it does keep gcc quiet. --- libs/models/brush/model_brush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 33e67b952..c81fbabe9 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -962,7 +962,7 @@ Mod_LoadBrushModel (model_t *mod, void *buffer) if (i < mod->numsubmodels - 1) { // duplicate the basic information - char name[10]; + char name[12]; snprintf (name, sizeof (name), "*%i", i + 1); loadmodel = Mod_FindName (name); From d3b4e4653e30ffb5d789095e5806cdcb0e7def45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Feb 2020 19:04:28 +0900 Subject: [PATCH 0237/3664] Cache physical devices in the instance --- include/QF/Vulkan/device.h | 2 +- include/QF/Vulkan/instance.h | 7 +++++++ libs/video/renderer/vulkan/device.c | 12 +++--------- libs/video/renderer/vulkan/instance.c | 12 ++++++++++++ libs/video/renderer/vulkan/swapchain.c | 13 +++++++------ 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h index 6f6907148..28a8fe229 100644 --- a/include/QF/Vulkan/device.h +++ b/include/QF/Vulkan/device.h @@ -19,7 +19,7 @@ typedef struct qfv_queue_s { struct qfv_instance_s; typedef struct qfv_device_s { VkDevice dev; - VkPhysicalDevice physDev; + struct qfv_physdev_s *physDev; qfv_devfuncs_t *funcs; qfv_queue_t queue; struct strset_s *enabled_extensions; diff --git a/include/QF/Vulkan/instance.h b/include/QF/Vulkan/instance.h index 0a677c945..6c393d140 100644 --- a/include/QF/Vulkan/instance.h +++ b/include/QF/Vulkan/instance.h @@ -36,6 +36,11 @@ typedef struct qfv_instfuncs_s { #include "QF/Vulkan/funclist.h" } qfv_instfuncs_t; +typedef struct qfv_physdev_s { + VkPhysicalDevice dev; + VkPhysicalDeviceMemoryProperties memory_properties; +} qfv_physdev_t; + typedef struct qfv_instance_s { VkInstance instance; qfv_instfuncs_t *funcs; @@ -43,6 +48,8 @@ typedef struct qfv_instance_s { int (*extension_enabled) (struct qfv_instance_s *inst, const char *ext); VkDebugUtilsMessengerEXT debug_handle; + uint32_t numDevices; + qfv_physdev_t *devices; } qfv_instance_t; struct vulkan_ctx_s; diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 85f200956..1c838fdfa 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -143,16 +143,10 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) merge_strings (ext, extensions, 0); qfv_instance_t *inst = ctx->instance; - VkInstance instance = inst->instance; qfv_instfuncs_t *ifunc = inst->funcs; - uint32_t numDevices; - ifunc->vkEnumeratePhysicalDevices (instance, &numDevices, 0); - VkPhysicalDevice *devices = alloca (numDevices * sizeof (*devices)); - ifunc->vkEnumeratePhysicalDevices (instance, &numDevices, devices); - - for (uint32_t i = 0; i < numDevices; i++) { - VkPhysicalDevice physdev = devices[i]; + for (uint32_t i = 0; i < inst->numDevices; i++) { + VkPhysicalDevice physdev = inst->devices[i].dev; /* if (!Vulkan_ExtensionsSupported (phys->extensions, phys->numExtensions, ext)) { @@ -189,7 +183,7 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) device->enabled_extensions = new_strset (ext); device->extension_enabled = device_extension_enabled; - device->physDev = physdev; + device->physDev = &inst->devices[i]; load_device_funcs (inst, device); device->queue.dev = device->dev; device->queue.funcs = dfunc; diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index 25ccdb306..a744c2608 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -256,6 +256,18 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, setup_debug_callback (inst); } + qfv_instfuncs_t *ifunc = inst->funcs; + ifunc->vkEnumeratePhysicalDevices (instance, &inst->numDevices, 0); + inst->devices = malloc (inst->numDevices * sizeof (*inst->devices)); + VkPhysicalDevice *devices = alloca (inst->numDevices * sizeof (*devices)); + ifunc->vkEnumeratePhysicalDevices (instance, &inst->numDevices, devices); + for (uint32_t i = 0; i < inst->numDevices; i++) { + VkPhysicalDevice physDev = devices[i]; + qfv_physdev_t *dev = &inst->devices[i]; + dev->dev = physDev; + ifunc->vkGetPhysicalDeviceMemoryProperties (physDev, + &dev->memory_properties); + } return inst; } diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index c9487a913..5a7a2ecac 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -28,9 +28,10 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) qfv_instfuncs_t *ifuncs = ctx->instance->funcs; qfv_devfuncs_t *dfuncs = ctx->device->funcs; qfv_queue_t *queue = &ctx->device->queue; + VkPhysicalDevice physDev = ctx->device->physDev->dev; VkBool32 supported; - ifuncs->vkGetPhysicalDeviceSurfaceSupportKHR (ctx->device->physDev, + ifuncs->vkGetPhysicalDeviceSurfaceSupportKHR (physDev, queue->queueFamily, ctx->surface, &supported); @@ -41,11 +42,11 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) uint32_t numModes; VkPresentModeKHR *modes; VkPresentModeKHR useMode = VK_PRESENT_MODE_FIFO_KHR;; - ifuncs->vkGetPhysicalDeviceSurfacePresentModesKHR (ctx->device->physDev, + ifuncs->vkGetPhysicalDeviceSurfacePresentModesKHR (physDev, ctx->surface, &numModes, 0); modes = alloca (numModes * sizeof (VkPresentModeKHR)); - ifuncs->vkGetPhysicalDeviceSurfacePresentModesKHR (ctx->device->physDev, + ifuncs->vkGetPhysicalDeviceSurfacePresentModesKHR (physDev, ctx->surface, &numModes, modes); for (uint32_t i = 0; i < numModes; i++) { @@ -57,7 +58,7 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) vulkan_presentation_mode->int_val); VkSurfaceCapabilitiesKHR surfCaps; - ifuncs->vkGetPhysicalDeviceSurfaceCapabilitiesKHR (ctx->device->physDev, + ifuncs->vkGetPhysicalDeviceSurfaceCapabilitiesKHR (physDev, ctx->surface, &surfCaps); uint32_t numImages = surfCaps.minImageCount + 1; @@ -85,11 +86,11 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) VkSurfaceTransformFlagBitsKHR surfTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; uint32_t numFormats; - ifuncs->vkGetPhysicalDeviceSurfaceFormatsKHR (ctx->device->physDev, + ifuncs->vkGetPhysicalDeviceSurfaceFormatsKHR (physDev, ctx->surface, &numFormats, 0); VkSurfaceFormatKHR *formats = alloca (numFormats * sizeof (*formats)); - ifuncs->vkGetPhysicalDeviceSurfaceFormatsKHR (ctx->device->physDev, + ifuncs->vkGetPhysicalDeviceSurfaceFormatsKHR (physDev, ctx->surface, &numFormats, formats); VkSurfaceFormatKHR useFormat = {VK_FORMAT_R8G8B8A8_UNORM, From 8148f256f5653a3902dc43ec07a1c25a3a76d79e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Feb 2020 11:45:05 +0900 Subject: [PATCH 0238/3664] Rework object device caching It turned out I needed access to the physical device from a buffer object, so rather than storing the vulkan logical device directly in buffer (and other) objects, store the qfv logical device. --- include/QF/Vulkan/command.h | 22 +++---- include/QF/Vulkan/device.h | 4 +- include/QF/Vulkan/swapchain.h | 3 +- libs/video/renderer/vulkan/command.c | 85 +++++++++++++------------- libs/video/renderer/vulkan/device.c | 3 +- libs/video/renderer/vulkan/swapchain.c | 9 +-- 6 files changed, 59 insertions(+), 67 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 2af925f29..94165ce13 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -2,53 +2,45 @@ #define __QF_Vulkan_command_h typedef struct qfv_cmdpool_s { - VkDevice dev; - struct qfv_devfuncs_s *funcs; + struct qfv_device_s *device; VkCommandPool cmdpool; } qfv_cmdpool_t; typedef struct qfv_cmdbuffer_s { - VkDevice dev; - struct qfv_devfuncs_s *funcs; + struct qfv_device_s *device; VkCommandPool cmdpool; VkCommandBuffer buffer; } qfv_cmdbuffer_t; typedef struct qfv_cmdbufferset_s { - VkDevice dev; - struct qfv_devfuncs_s *funcs; + struct qfv_device_s *device; VkCommandBuffer *buffers; int numBuffers; } qfv_cmdbufferset_t; typedef struct qfv_semaphore_s { - VkDevice dev; - struct qfv_devfuncs_s *funcs; + struct qfv_device_s *device; VkSemaphore semaphore; } qfv_semaphore_t; typedef struct qfv_semaphoreset_s { - VkDevice dev; - struct qfv_devfuncs_s *funcs; + struct qfv_device_s *device; VkSemaphore *semaphores; VkPipelineStageFlags *stages; int numSemaphores; } qfv_semaphoreset_t; typedef struct qfv_fence_s { - VkDevice dev; - struct qfv_devfuncs_s *funcs; + struct qfv_device_s *device; VkFence fence; } qfv_fence_t; typedef struct qfv_fenceset_s { - VkDevice dev; - struct qfv_devfuncs_s *funcs; + struct qfv_device_s *device; VkFence *fences; int numFences; } qfv_fenceset_t; -struct qfv_device_s; struct qfv_queue_s; qfv_cmdpool_t *QFV_CreateCommandPool (struct qfv_device_s *device, uint32_t queueFamily, diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h index 28a8fe229..c05b2ba7e 100644 --- a/include/QF/Vulkan/device.h +++ b/include/QF/Vulkan/device.h @@ -7,10 +7,8 @@ typedef struct qfv_devfuncs_s { #include "QF/Vulkan/funclist.h" } qfv_devfuncs_t; -struct qfv_device_s; typedef struct qfv_queue_s { - VkDevice dev; - qfv_devfuncs_t *funcs; + struct qfv_device_s *device; int32_t queueFamily; VkQueue queue; diff --git a/include/QF/Vulkan/swapchain.h b/include/QF/Vulkan/swapchain.h index 91d158c89..cd9323009 100644 --- a/include/QF/Vulkan/swapchain.h +++ b/include/QF/Vulkan/swapchain.h @@ -2,8 +2,7 @@ #define __QF_Vulkan_swapchain_h typedef struct qfv_swapchain_s { - VkDevice dev; - struct qfv_devfuncs_s *funcs; + struct qfv_device_s *device; VkSurfaceKHR surface; VkSwapchainKHR swapchain; int32_t numImages; diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 4031f0be4..d3f3d4082 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -80,17 +80,17 @@ QFV_CreateCommandPool (qfv_device_t *device, uint32_t queueFamily, }; qfv_cmdpool_t *cmdpool = malloc (sizeof (*cmdpool)); dfunc->vkCreateCommandPool (dev, &createInfo, 0, &cmdpool->cmdpool); - cmdpool->dev = dev; - cmdpool->funcs = dfunc; + cmdpool->device = device; return cmdpool; } int QFV_ResetCommandPool (qfv_cmdpool_t *pool, int release) { - VkDevice dev = pool->dev; + qfv_device_t *device = pool->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; VkCommandPool cmdpool = pool->cmdpool; - qfv_devfuncs_t *dfunc = pool->funcs; VkCommandPoolResetFlags release_flag = 0; if (release) { @@ -103,8 +103,9 @@ QFV_ResetCommandPool (qfv_cmdpool_t *pool, int release) void QFV_DestroyCommandPool (qfv_cmdpool_t *pool) { - VkDevice dev = pool->dev; - qfv_devfuncs_t *dfunc = pool->funcs; + qfv_device_t *device = pool->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkDestroyCommandPool (dev, pool->cmdpool, 0); free (pool); @@ -113,8 +114,9 @@ QFV_DestroyCommandPool (qfv_cmdpool_t *pool) qfv_cmdbuffer_t * QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) { - VkDevice dev = pool->dev; - qfv_devfuncs_t *dfunc = pool->funcs; + qfv_device_t *device = pool->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; uint32_t level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; if (secondary) { level = VK_COMMAND_BUFFER_LEVEL_SECONDARY; @@ -127,8 +129,7 @@ QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) VkCommandBuffer *buffers = alloca (count * sizeof (*buffers)); dfunc->vkAllocateCommandBuffers (dev, &allocInfo, buffers); for (int i = 0; i < count; i++) { - cmdbuffers[i].dev = dev; - cmdbuffers[i].funcs = dfunc; + cmdbuffers[i].device = device; cmdbuffers[i].cmdpool = pool->cmdpool; cmdbuffers[i].buffer = buffers[i]; } @@ -138,14 +139,12 @@ QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) qfv_cmdbufferset_t * QFV_CreateCommandBufferSet (qfv_cmdbuffer_t **buffers, int numBuffers) { - VkDevice dev = buffers[0]->dev; - qfv_devfuncs_t *dfunc = buffers[0]->funcs; + qfv_device_t *device = buffers[0]->device; qfv_cmdbufferset_t *bufferset = malloc (sizeof (*bufferset) + sizeof (VkCommandBuffer) * numBuffers); - bufferset->dev = dev; - bufferset->funcs = dfunc; + bufferset->device = device; bufferset->buffers = (VkCommandBuffer *) (bufferset + 1); bufferset->numBuffers = numBuffers; @@ -157,8 +156,9 @@ QFV_CreateCommandBufferSet (qfv_cmdbuffer_t **buffers, int numBuffers) void QFV_FreeCommandBuffers (qfv_cmdbuffer_t *buffer, int count) { - VkDevice dev = buffer->dev; - qfv_devfuncs_t *dfunc = buffer->funcs; + qfv_device_t *device = buffer->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; VkCommandBuffer *buffers = alloca (sizeof (*buffers) * count); for (int i = 0; i < count; i++) { @@ -180,8 +180,9 @@ QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, int rpContinue, int simultaneous, VkCommandBufferInheritanceInfo *inheritanceInfo) { + qfv_device_t *device = buffer->device; + qfv_devfuncs_t *dfunc = device->funcs; VkCommandBuffer buff = buffer->buffer; - qfv_devfuncs_t *dfunc = buffer->funcs; VkCommandBufferUsageFlags usage = 0; if (oneTime) { @@ -206,8 +207,9 @@ QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, int rpContinue, int QFV_EndCommandBuffer (qfv_cmdbuffer_t *buffer) { + qfv_device_t *device = buffer->device; + qfv_devfuncs_t *dfunc = device->funcs; VkCommandBuffer buff = buffer->buffer; - qfv_devfuncs_t *dfunc = buffer->funcs; return dfunc->vkEndCommandBuffer (buff) == VK_SUCCESS; } @@ -215,8 +217,9 @@ QFV_EndCommandBuffer (qfv_cmdbuffer_t *buffer) int QFV_ResetCommandBuffer (qfv_cmdbuffer_t *buffer, int release) { + qfv_device_t *device = buffer->device; + qfv_devfuncs_t *dfunc = device->funcs; VkCommandBuffer buff = buffer->buffer; - qfv_devfuncs_t *dfunc = buffer->funcs; VkCommandBufferResetFlags release_flag = 0; if (release) { @@ -238,8 +241,7 @@ QFV_CreateSemaphore (qfv_device_t *device) }; qfv_semaphore_t *semaphore = malloc (sizeof (*semaphore)); - semaphore->dev = dev; - semaphore->funcs = dfunc; + semaphore->device = device; dfunc->vkCreateSemaphore (dev, &createInfo, 0, &semaphore->semaphore); return semaphore; @@ -248,15 +250,13 @@ QFV_CreateSemaphore (qfv_device_t *device) qfv_semaphoreset_t * QFV_CreateSemaphoreSet (qfv_semaphore_t **semaphores, int numSemaphores) { - VkDevice dev = semaphores[0]->dev; - qfv_devfuncs_t *dfunc = semaphores[0]->funcs; + qfv_device_t *device = semaphores[0]->device; qfv_semaphoreset_t *semaphoreset; semaphoreset = calloc (1, sizeof (*semaphoreset) + sizeof (VkSemaphore) * numSemaphores + sizeof (VkPipelineStageFlags) * numSemaphores); - semaphoreset->dev = dev; - semaphoreset->funcs = dfunc; + semaphoreset->device = device; semaphoreset->semaphores = (VkSemaphore *) (semaphoreset + 1); semaphoreset->stages = (VkPipelineStageFlags *) &semaphoreset->semaphores[numSemaphores]; @@ -271,8 +271,9 @@ QFV_CreateSemaphoreSet (qfv_semaphore_t **semaphores, int numSemaphores) void QFV_DestroySemaphore (qfv_semaphore_t *semaphore) { - VkDevice dev = semaphore->dev; - qfv_devfuncs_t *dfunc = semaphore->funcs; + qfv_device_t *device = semaphore->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkDestroySemaphore (dev, semaphore->semaphore, 0); free (semaphore); @@ -296,8 +297,7 @@ QFV_CreateFence (qfv_device_t *device, int signaled) }; qfv_fence_t *fence = malloc (sizeof (*fence)); - fence->dev = dev; - fence->funcs = dfunc; + fence->device = device; dfunc->vkCreateFence (dev, &createInfo, 0, &fence->fence); return fence; @@ -306,13 +306,11 @@ QFV_CreateFence (qfv_device_t *device, int signaled) qfv_fenceset_t * QFV_CreateFenceSet (qfv_fence_t **fences, int numFences) { - VkDevice dev = fences[0]->dev; - qfv_devfuncs_t *dfunc = fences[0]->funcs; + qfv_device_t *device = fences[0]->device; qfv_fenceset_t *fenceset = malloc (sizeof (*fenceset) + sizeof (VkFence) * numFences); - fenceset->dev = dev; - fenceset->funcs = dfunc; + fenceset->device = device; fenceset->fences = (VkFence *) (fenceset + 1); fenceset->numFences = numFences; @@ -325,8 +323,9 @@ QFV_CreateFenceSet (qfv_fence_t **fences, int numFences) void QFV_DestroyFence (qfv_fence_t *fence) { - VkDevice dev = fence->dev; - qfv_devfuncs_t *dfunc = fence->funcs; + qfv_device_t *device = fence->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkDestroyFence (dev, fence->fence, 0); free (fence); @@ -341,8 +340,9 @@ QFV_DestroyFenceSet (qfv_fenceset_t *fences) int QFV_WaitForFences (qfv_fenceset_t *fences, int all, uint64_t timeout) { - VkDevice dev = fences->dev; - qfv_devfuncs_t *dfunc = fences->funcs; + qfv_device_t *device = fences->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; VkResult res = dfunc->vkWaitForFences (dev, fences->numFences, fences->fences, all, timeout); @@ -352,8 +352,9 @@ QFV_WaitForFences (qfv_fenceset_t *fences, int all, uint64_t timeout) int QFV_ResetFences (qfv_fenceset_t *fences) { - VkDevice dev = fences->dev; - qfv_devfuncs_t *dfunc = fences->funcs; + qfv_device_t *device = fences->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; return dfunc->vkResetFences (dev, fences->numFences, fences->fences) == VK_SUCCESS; @@ -364,7 +365,8 @@ QFV_QueueSubmit (qfv_queue_t *queue, qfv_semaphoreset_t *waitSemaphores, qfv_cmdbufferset_t *buffers, qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence) { - qfv_devfuncs_t *dfunc = queue->funcs; + qfv_device_t *device = queue->device; + qfv_devfuncs_t *dfunc = device->funcs; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, waitSemaphores->numSemaphores, @@ -381,6 +383,7 @@ QFV_QueueSubmit (qfv_queue_t *queue, qfv_semaphoreset_t *waitSemaphores, int QFV_QueueWaitIdle (qfv_queue_t *queue) { - qfv_devfuncs_t *dfunc = queue->funcs; + qfv_device_t *device = queue->device; + qfv_devfuncs_t *dfunc = device->funcs; return dfunc->vkQueueWaitIdle (queue->queue) == VK_SUCCESS; } diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 1c838fdfa..0ed7ec808 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -185,8 +185,7 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) device->physDev = &inst->devices[i]; load_device_funcs (inst, device); - device->queue.dev = device->dev; - device->queue.funcs = dfunc; + device->queue.device = device; device->queue.queueFamily = family; dfunc->vkGetDeviceQueue (device->dev, family, 0, &device->queue.queue); diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 5a7a2ecac..bae8e4ff4 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -138,8 +138,7 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) dfuncs->vkGetSwapchainImagesKHR (device, swapchain, &numImages, 0); qfv_swapchain_t *sc = malloc (sizeof (qfv_swapchain_t) + numImages * sizeof (VkImage)); - sc->dev = device; - sc->funcs = ctx->device->funcs; + sc->device = ctx->device; sc->surface = ctx->surface; sc->swapchain = swapchain; sc->numImages = numImages; @@ -152,7 +151,9 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) void QFV_DestroySwapchain (qfv_swapchain_t *swapchain) { - swapchain->funcs->vkDestroySwapchainKHR (swapchain->dev, - swapchain->swapchain, 0); + qfv_device_t *device = swapchain->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + dfunc->vkDestroySwapchainKHR (dev, swapchain->swapchain, 0); free (swapchain); } From 2f9ad73f789d4f83e459db1cfa2be0c330bc82c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Feb 2020 15:07:35 +0900 Subject: [PATCH 0239/3664] Implement buffer memory up to barriers Still lots to go (views, destruction, transfer...) and I'm uncertain about the location of the pipeline barrier function. --- include/QF/Vulkan/buffer.h | 47 ++++++++ include/QF/Vulkan/command.h | 10 ++ include/QF/Vulkan/funclist.h | 6 + libs/video/renderer/vulkan/Makefile.am | 1 + libs/video/renderer/vulkan/buffer.c | 161 +++++++++++++++++++++++++ libs/video/renderer/vulkan/command.c | 30 +++++ 6 files changed, 255 insertions(+) create mode 100644 include/QF/Vulkan/buffer.h create mode 100644 libs/video/renderer/vulkan/buffer.c diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h new file mode 100644 index 000000000..dfd8c2313 --- /dev/null +++ b/include/QF/Vulkan/buffer.h @@ -0,0 +1,47 @@ +#ifndef __QF_Vulkan_buffer_h +#define __QF_Vulkan_buffer_h + +typedef struct qfv_buffer_s { + struct qfv_device_s *device; + VkBuffer buffer; +} qfv_buffer_t; + +typedef struct qfv_memory_s { + struct qfv_device_s *device; + VkDeviceMemory object; +} qfv_memory_t; + +typedef struct qfv_buffertransition_s { + qfv_buffer_t *buffer; + VkAccessFlags srcAccess; + VkAccessFlags dstAccess; + uint32_t srcQueueFamily; + uint32_t dstQueueFamily; + VkDeviceSize offset; + VkDeviceSize size; +} qfv_buffertransition_t; + +typedef struct qfv_bufferbarrierset_s { + struct qfv_device_s *device; + uint32_t numBarriers; + VkBufferMemoryBarrier *barriers; +} qfv_bufferbarrierset_t; + +struct qfv_device_s; +qfv_buffer_t *QFV_CreateBuffer (struct qfv_device_s *device, + VkDeviceSize size, + VkBufferUsageFlags usage); + +qfv_memory_t *QFV_AllocMemory (qfv_buffer_t *buffer, + VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset); + +int QFV_BindBufferMemory (qfv_buffer_t *buffer, qfv_memory_t *memory, + VkDeviceSize offset); + +qfv_bufferbarrierset_t * +QFV_CreateBufferTransitionSet (qfv_buffertransition_t **transitions, + int numTransitions); + + +#endif//__QF_Vulkan_buffer_h diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 94165ce13..a19ff7bd3 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -79,5 +79,15 @@ int QFV_QueueSubmit (struct qfv_queue_s *queue, qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence); int QFV_QueueWaitIdle (struct qfv_queue_s *queue); +struct qfv_memorybarrierset_s *memBarriers; +struct qfv_bufferbarrierset_s *buffBarriers; +struct qfv_imagebarrierset_s *imgBarriers; +void QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + struct qfv_memorybarrierset_s *memBarriers, + struct qfv_bufferbarrierset_s *buffBarriers, + struct qfv_imagebarrierset_s *imgBarriers); #endif//__QF_Vulkan_command_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 5d649d5c2..5337bd472 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -107,6 +107,12 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFence) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeCommandBuffers) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyCommandPool) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkGetBufferMemoryRequirements) +DEVICE_LEVEL_VULKAN_FUNCTION (vkAllocateMemory) +DEVICE_LEVEL_VULKAN_FUNCTION (vkBindBufferMemory) + +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index f754853f2..cfe2acb0d 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -4,6 +4,7 @@ AM_CFLAGS= @PREFER_PIC@ AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES vulkan_src = \ + buffer.c \ command.c \ device.c \ instance.c \ diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c new file mode 100644 index 000000000..6a69b201d --- /dev/null +++ b/libs/video/renderer/vulkan/buffer.c @@ -0,0 +1,161 @@ +/* + buffer.c + + Vulkan buffer functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +qfv_buffer_t * +QFV_CreateBuffer (qfv_device_t *device, VkDeviceSize size, + VkBufferUsageFlags usage) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + VkBufferCreateInfo createInfo = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 0, + 0, + size, usage, VK_SHARING_MODE_EXCLUSIVE, + 0, 0 + }; + qfv_buffer_t *buffer = malloc (sizeof (*buffer)); + dfunc->vkCreateBuffer (dev, &createInfo, 0, &buffer->buffer); + buffer->device = device; + return buffer; +} + +qfv_memory_t * +QFV_AllocMemory (qfv_buffer_t *buffer, VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset) +{ + qfv_device_t *device = buffer->device; + VkDevice dev = device->dev; + qfv_physdev_t *physdev = device->physDev; + VkPhysicalDeviceMemoryProperties *memprops = &physdev->memory_properties; + qfv_devfuncs_t *dfunc = device->funcs; + + VkMemoryRequirements requirements; + dfunc->vkGetBufferMemoryRequirements (dev, buffer->buffer, &requirements); + + size = max (size, offset + requirements.size); + VkDeviceMemory object = 0; + + for (uint32_t type = 0; type < memprops->memoryTypeCount; type++) { + if ((requirements.memoryTypeBits & (1 << type)) + && ((memprops->memoryTypes[type].propertyFlags & properties) + == properties)) { + VkMemoryAllocateInfo allocate_info = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 0, + size, type + }; + + VkResult res = dfunc->vkAllocateMemory (dev, &allocate_info, + 0, &object); + if (res == VK_SUCCESS) { + break; + } + } + } + + qfv_memory_t *memory = 0; + + if (object) { + memory = malloc (sizeof (*memory)); + memory->device = device; + memory->object = object; + } + return memory; +} + +int +QFV_BindBufferMemory (qfv_buffer_t *buffer, qfv_memory_t *memory, + VkDeviceSize offset) +{ + qfv_device_t *device = buffer->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + VkResult res = dfunc->vkBindBufferMemory (dev, buffer->buffer, + memory->object, offset); + return res == VK_SUCCESS; +} + +qfv_bufferbarrierset_t * +QFV_CreateBufferTransitionSet (qfv_buffertransition_t **transitions, + int numTransitions) +{ + qfv_device_t *device = transitions[0]->buffer->device; + qfv_bufferbarrierset_t *barrierset = malloc (sizeof (*barrierset) + + sizeof (VkBufferMemoryBarrier) * numTransitions); + + barrierset->device = device; + barrierset->numBarriers = numTransitions; + barrierset->barriers = (VkBufferMemoryBarrier *) (barrierset + 1); + + for (int i = 0; i < numTransitions; i++) { + VkBufferMemoryBarrier *barrier = &barrierset->barriers[i]; + barrier->sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrier->pNext = 0; + barrier->srcAccessMask = transitions[i]->srcAccess; + barrier->dstAccessMask = transitions[i]->dstAccess; + barrier->srcQueueFamilyIndex = transitions[i]->srcQueueFamily; + barrier->dstQueueFamilyIndex = transitions[i]->dstQueueFamily; + barrier->buffer = transitions[i]->buffer->buffer; + barrier->offset = transitions[i]->offset; + barrier->size = transitions[i]->size; + } + return barrierset; +} diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index d3f3d4082..f30b1dfeb 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -49,6 +49,7 @@ #include "QF/va.h" #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/buffer.h"//FIXME should QFV_CmdPipelineBarrier be here? #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" @@ -387,3 +388,32 @@ QFV_QueueWaitIdle (qfv_queue_t *queue) qfv_devfuncs_t *dfunc = device->funcs; return dfunc->vkQueueWaitIdle (queue->queue) == VK_SUCCESS; } + +void +QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + struct qfv_memorybarrierset_s *memBarrierSet, + qfv_bufferbarrierset_t *buffBarrierSet, + struct qfv_imagebarrierset_s *imgBarrierSet) +{ + qfv_device_t *device = cmdBuffer->device; + qfv_devfuncs_t *dfunc = device->funcs; + uint32_t numMemBarriers = 0; + VkMemoryBarrier *memBarriers = 0; + uint32_t numBuffBarriers = 0; + VkBufferMemoryBarrier *buffBarriers = 0; + uint32_t numImgBarriers = 0; + VkImageMemoryBarrier *imgBarriers = 0; + + if (buffBarrierSet) { + numBuffBarriers = buffBarrierSet->numBarriers; + buffBarriers = buffBarrierSet->barriers; + } + dfunc->vkCmdPipelineBarrier (cmdBuffer->buffer, + srcStageMask, dstStageMask, dependencyFlags, + numMemBarriers, memBarriers, + numBuffBarriers, buffBarriers, + numImgBarriers, imgBarriers); +} From f4c0d0ebcfea88821884abc9a93bff2d8461169e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Feb 2020 18:17:58 +0900 Subject: [PATCH 0240/3664] Implement buffer view creation And rename memory allocation as it's buffer-specific. --- include/QF/Vulkan/buffer.h | 17 ++++++++++++++--- include/QF/Vulkan/funclist.h | 1 + libs/video/renderer/vulkan/buffer.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h index dfd8c2313..e61e4c744 100644 --- a/include/QF/Vulkan/buffer.h +++ b/include/QF/Vulkan/buffer.h @@ -27,14 +27,23 @@ typedef struct qfv_bufferbarrierset_s { VkBufferMemoryBarrier *barriers; } qfv_bufferbarrierset_t; +typedef struct qfv_bufferview_s { + struct qfv_device_s *device; + VkBufferView view; + qfv_buffer_t *buffer; + VkFormat format; + VkDeviceSize offset; + VkDeviceSize size; +} qfv_bufferview_t; + struct qfv_device_s; qfv_buffer_t *QFV_CreateBuffer (struct qfv_device_s *device, VkDeviceSize size, VkBufferUsageFlags usage); -qfv_memory_t *QFV_AllocMemory (qfv_buffer_t *buffer, - VkMemoryPropertyFlags properties, - VkDeviceSize size, VkDeviceSize offset); +qfv_memory_t *QFV_AllocBufferMemory (qfv_buffer_t *buffer, + VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset); int QFV_BindBufferMemory (qfv_buffer_t *buffer, qfv_memory_t *memory, VkDeviceSize offset); @@ -43,5 +52,7 @@ qfv_bufferbarrierset_t * QFV_CreateBufferTransitionSet (qfv_buffertransition_t **transitions, int numTransitions); +qfv_bufferview_t *QFV_CreateBufferView (qfv_buffer_t *buffer, VkFormat format, + VkDeviceSize offset, VkDeviceSize size); #endif//__QF_Vulkan_buffer_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 5337bd472..597cb1dc7 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -111,6 +111,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkGetBufferMemoryRequirements) DEVICE_LEVEL_VULKAN_FUNCTION (vkAllocateMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkBindBufferMemory) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateBufferView) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index 6a69b201d..3f67c80bb 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -79,8 +79,8 @@ QFV_CreateBuffer (qfv_device_t *device, VkDeviceSize size, } qfv_memory_t * -QFV_AllocMemory (qfv_buffer_t *buffer, VkMemoryPropertyFlags properties, - VkDeviceSize size, VkDeviceSize offset) +QFV_AllocBufferMemory (qfv_buffer_t *buffer, VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset) { qfv_device_t *device = buffer->device; VkDevice dev = device->dev; @@ -159,3 +159,27 @@ QFV_CreateBufferTransitionSet (qfv_buffertransition_t **transitions, } return barrierset; } + +qfv_bufferview_t * +QFV_CreateBufferView (qfv_buffer_t *buffer, VkFormat format, + VkDeviceSize offset, VkDeviceSize size) +{ + qfv_device_t *device = buffer->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkBufferViewCreateInfo createInfo = { + VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, 0, + 0, + buffer->buffer, format, offset, size, + }; + + qfv_bufferview_t *view = malloc (sizeof (*view)); + view->device = device; + view->buffer = buffer; + view->format = format; + view->offset = offset; + view->size = size; + dfunc->vkCreateBufferView (dev, &createInfo, 0, &view->view); + return view; +} From 9fdc15c439bf29c497ba676b35bff4540745fd24 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Feb 2020 18:18:37 +0900 Subject: [PATCH 0241/3664] Implement image stuff up to view creation --- include/QF/Vulkan/funclist.h | 5 + include/QF/Vulkan/image.h | 60 +++++++ libs/video/renderer/vulkan/Makefile.am | 1 + libs/video/renderer/vulkan/command.c | 7 +- libs/video/renderer/vulkan/image.c | 214 +++++++++++++++++++++++++ 5 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 include/QF/Vulkan/image.h create mode 100644 libs/video/renderer/vulkan/image.c diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 597cb1dc7..c5d79af7b 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -113,6 +113,11 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkAllocateMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkBindBufferMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateBufferView) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateImage) +DEVICE_LEVEL_VULKAN_FUNCTION (vkGetImageMemoryRequirements) +DEVICE_LEVEL_VULKAN_FUNCTION (vkBindImageMemory) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateImageView) + DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h new file mode 100644 index 000000000..9c927e6b6 --- /dev/null +++ b/include/QF/Vulkan/image.h @@ -0,0 +1,60 @@ +#ifndef __QF_Vulkan_image_h +#define __QF_Vulkan_image_h + +typedef struct qfv_image_s { + struct qfv_device_s *device; + VkImage image; +} qfv_image_t; + +typedef struct qfv_imagetransition_s { + qfv_image_t *image; + VkAccessFlags srcAccess; + VkAccessFlags dstAccess; + VkImageLayout oldLayout; + VkImageLayout newLayout; + uint32_t srcQueueFamily; + uint32_t dstQueueFamily; + VkImageAspectFlags aspect; +} qfv_imagetransition_t; + +typedef struct qfv_imagebarrierset_s { + struct qfv_device_s *device; + uint32_t numBarriers; + VkImageMemoryBarrier *barriers; +} qfv_imagebarrierset_t; + +typedef struct qfv_imageview_s { + struct qfv_device_s *device; + VkImageView view; + qfv_image_t *image; + VkImageViewType type; + VkFormat format; + VkImageAspectFlags aspect; +} qfv_imageview_t; + +struct qfv_device_s; +qfv_image_t *QFV_CreateImage (struct qfv_device_s *device, int cubemap, + VkImageType type, + VkFormat format, + VkExtent3D size, + uint32_t num_mipmaps, + uint32_t num_layers, + VkSampleCountFlagBits samples, + VkImageUsageFlags usage_scenarios); + +struct qfv_memory_s *QFV_AllocImageMemory (qfv_image_t *image, + VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset); + +int QFV_BindImageMemory (qfv_image_t *image, struct qfv_memory_s *memory, + VkDeviceSize offset); + +qfv_imagebarrierset_t * +QFV_CreateImageTransitionSet (qfv_imagetransition_t **transitions, + int numTransitions); + +qfv_imageview_t *QFV_CreateImageView (qfv_image_t *image, VkImageViewType type, + VkFormat format, + VkImageAspectFlags aspect); + +#endif//__QF_Vulkan_image_h diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index cfe2acb0d..810e86d29 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -7,6 +7,7 @@ vulkan_src = \ buffer.c \ command.c \ device.c \ + image.c \ instance.c \ swapchain.c \ util.c \ diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index f30b1dfeb..ecc6f7975 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -50,6 +50,7 @@ #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/buffer.h"//FIXME should QFV_CmdPipelineBarrier be here? +#include "QF/Vulkan/image.h"//FIXME should QFV_CmdPipelineBarrier be here? #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" @@ -396,7 +397,7 @@ QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, VkDependencyFlags dependencyFlags, struct qfv_memorybarrierset_s *memBarrierSet, qfv_bufferbarrierset_t *buffBarrierSet, - struct qfv_imagebarrierset_s *imgBarrierSet) + qfv_imagebarrierset_t *imgBarrierSet) { qfv_device_t *device = cmdBuffer->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -411,6 +412,10 @@ QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, numBuffBarriers = buffBarrierSet->numBarriers; buffBarriers = buffBarrierSet->barriers; } + if (imgBarrierSet) { + numImgBarriers = imgBarrierSet->numBarriers; + imgBarriers = imgBarrierSet->barriers; + } dfunc->vkCmdPipelineBarrier (cmdBuffer->buffer, srcStageMask, dstStageMask, dependencyFlags, numMemBarriers, memBarriers, diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c new file mode 100644 index 000000000..18057278f --- /dev/null +++ b/libs/video/renderer/vulkan/image.c @@ -0,0 +1,214 @@ +/* + image.c + + Vulkan image functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/buffer.h"//FIXME qfv_memory_t +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +qfv_image_t * +QFV_CreateImage (qfv_device_t *device, int cubemap, + VkImageType type, + VkFormat format, + VkExtent3D size, + uint32_t num_mipmaps, + uint32_t num_layers, + VkSampleCountFlagBits samples, + VkImageUsageFlags usage_scenarios) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + VkImageCreateInfo createInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 0, + cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, + type, format, size, num_mipmaps, + cubemap ? 6 * num_layers : num_layers, + samples, + VK_IMAGE_TILING_OPTIMAL, + usage_scenarios, + VK_SHARING_MODE_EXCLUSIVE, + 0, 0, + VK_IMAGE_LAYOUT_UNDEFINED, + }; + qfv_image_t *image = malloc (sizeof (*image)); + dfunc->vkCreateImage (dev, &createInfo, 0, &image->image); + image->device = device; + return image; +} + +qfv_memory_t * +QFV_AllocImageMemory (qfv_image_t *image, VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset) +{ + qfv_device_t *device = image->device; + VkDevice dev = device->dev; + qfv_physdev_t *physdev = device->physDev; + VkPhysicalDeviceMemoryProperties *memprops = &physdev->memory_properties; + qfv_devfuncs_t *dfunc = device->funcs; + + VkMemoryRequirements requirements; + dfunc->vkGetImageMemoryRequirements (dev, image->image, &requirements); + + size = max (size, offset + requirements.size); + VkDeviceMemory object = 0; + + for (uint32_t type = 0; type < memprops->memoryTypeCount; type++) { + if ((requirements.memoryTypeBits & (1 << type)) + && ((memprops->memoryTypes[type].propertyFlags & properties) + == properties)) { + VkMemoryAllocateInfo allocate_info = { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 0, + size, type + }; + + VkResult res = dfunc->vkAllocateMemory (dev, &allocate_info, + 0, &object); + if (res == VK_SUCCESS) { + break; + } + } + } + + qfv_memory_t *memory = 0; + + if (object) { + memory = malloc (sizeof (*memory)); + memory->device = device; + memory->object = object; + } + return memory; +} + +int +QFV_BindImageMemory (qfv_image_t *image, qfv_memory_t *memory, + VkDeviceSize offset) +{ + qfv_device_t *device = image->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + VkResult res = dfunc->vkBindImageMemory (dev, image->image, + memory->object, offset); + return res == VK_SUCCESS; +} + +qfv_imagebarrierset_t * +QFV_CreateImageTransitionSet (qfv_imagetransition_t **transitions, + int numTransitions) +{ + qfv_device_t *device = transitions[0]->image->device; + qfv_imagebarrierset_t *barrierset = malloc (sizeof (*barrierset) + + sizeof (VkImageMemoryBarrier) * numTransitions); + + barrierset->device = device; + barrierset->numBarriers = numTransitions; + barrierset->barriers = (VkImageMemoryBarrier *) (barrierset + 1); + + for (int i = 0; i < numTransitions; i++) { + VkImageMemoryBarrier *barrier = &barrierset->barriers[i]; + barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier->pNext = 0; + barrier->srcAccessMask = transitions[i]->srcAccess; + barrier->dstAccessMask = transitions[i]->dstAccess; + barrier->oldLayout = transitions[i]->oldLayout; + barrier->newLayout = transitions[i]->newLayout; + barrier->srcQueueFamilyIndex = transitions[i]->srcQueueFamily; + barrier->dstQueueFamilyIndex = transitions[i]->dstQueueFamily; + barrier->image = transitions[i]->image->image; + barrier->subresourceRange.aspectMask = transitions[i]->aspect; + barrier->subresourceRange.baseMipLevel = 0; + barrier->subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier->subresourceRange.baseArrayLayer = 0; + barrier->subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + } + return barrierset; +} + +qfv_imageview_t * +QFV_CreateImageView (qfv_image_t *image, VkImageViewType type, VkFormat format, + VkImageAspectFlags aspect) +{ + qfv_device_t *device = image->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkImageViewCreateInfo createInfo = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0, + 0, + image->image, type, format, + { + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, + }, + { + aspect, + 0, VK_REMAINING_MIP_LEVELS, + 0, VK_REMAINING_ARRAY_LAYERS, + } + }; + + qfv_imageview_t *view = malloc (sizeof (*view)); + view->device = device; + view->image = image; + view->type = type; + view->format = format; + view->aspect = aspect; + dfunc->vkCreateImageView (dev, &createInfo, 0, &view->view); + return view; +} From 43e37aa31e62ace1b3195d8962c3ced465d38cdd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Feb 2020 18:33:29 +0900 Subject: [PATCH 0242/3664] Separate out the generic memory stuff --- include/QF/Vulkan/buffer.h | 9 ++------- include/QF/Vulkan/memory.h | 9 +++++++++ libs/video/renderer/vulkan/buffer.c | 1 + libs/video/renderer/vulkan/image.c | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 include/QF/Vulkan/memory.h diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h index e61e4c744..09ff14c2b 100644 --- a/include/QF/Vulkan/buffer.h +++ b/include/QF/Vulkan/buffer.h @@ -6,11 +6,6 @@ typedef struct qfv_buffer_s { VkBuffer buffer; } qfv_buffer_t; -typedef struct qfv_memory_s { - struct qfv_device_s *device; - VkDeviceMemory object; -} qfv_memory_t; - typedef struct qfv_buffertransition_s { qfv_buffer_t *buffer; VkAccessFlags srcAccess; @@ -41,11 +36,11 @@ qfv_buffer_t *QFV_CreateBuffer (struct qfv_device_s *device, VkDeviceSize size, VkBufferUsageFlags usage); -qfv_memory_t *QFV_AllocBufferMemory (qfv_buffer_t *buffer, +struct qfv_memory_s *QFV_AllocBufferMemory (qfv_buffer_t *buffer, VkMemoryPropertyFlags properties, VkDeviceSize size, VkDeviceSize offset); -int QFV_BindBufferMemory (qfv_buffer_t *buffer, qfv_memory_t *memory, +int QFV_BindBufferMemory (qfv_buffer_t *buffer, struct qfv_memory_s *memory, VkDeviceSize offset); qfv_bufferbarrierset_t * diff --git a/include/QF/Vulkan/memory.h b/include/QF/Vulkan/memory.h new file mode 100644 index 000000000..d50bddd00 --- /dev/null +++ b/include/QF/Vulkan/memory.h @@ -0,0 +1,9 @@ +#ifndef __QF_Vulkan_memory_h +#define __QF_Vulkan_memory_h + +typedef struct qfv_memory_s { + struct qfv_device_s *device; + VkDeviceMemory object; +} qfv_memory_t; + +#endif//__QF_Vulkan_memory_h diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index 3f67c80bb..f2053c5db 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -52,6 +52,7 @@ #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/memory.h" #include "compat.h" #include "d_iface.h" diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 18057278f..4564fd2fe 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -49,10 +49,10 @@ #include "QF/va.h" #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" -#include "QF/Vulkan/buffer.h"//FIXME qfv_memory_t #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/memory.h" #include "compat.h" #include "d_iface.h" From 1baee0cbba5c8fc530d6641dd19a6ce4d3f8766b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Feb 2020 20:42:19 +0900 Subject: [PATCH 0243/3664] Implement mem mapping and buffer/image copying --- include/QF/Vulkan/command.h | 18 +++++ include/QF/Vulkan/funclist.h | 7 ++ include/QF/Vulkan/memory.h | 11 +++ libs/video/renderer/vulkan/Makefile.am | 1 + libs/video/renderer/vulkan/command.c | 40 ++++++++++ libs/video/renderer/vulkan/memory.c | 102 +++++++++++++++++++++++++ 6 files changed, 179 insertions(+) create mode 100644 libs/video/renderer/vulkan/memory.c diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index a19ff7bd3..9326617ca 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -90,4 +90,22 @@ void QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, struct qfv_bufferbarrierset_s *buffBarriers, struct qfv_imagebarrierset_s *imgBarriers); +struct qfv_buffer_s; +struct qfv_image_s; +void QFV_CmdCopyBuffer (qfv_cmdbuffer_t *cmdBuffer, + struct qfv_buffer_s *src, struct qfv_buffer_s *dst, + VkBufferCopy *regions, uint32_t numRegions); +void QFV_CmdCopyBufferToImage (qfv_cmdbuffer_t *cmdBuffer, + struct qfv_buffer_s *src, + struct qfv_image_s *dst, + VkImageLayout layout, + VkBufferImageCopy *regions, + uint32_t numRegions); +void QFV_CmdCopyImageToBuffer (qfv_cmdbuffer_t *cmdBuffer, + struct qfv_image_s *src, + VkImageLayout layout, + struct qfv_buffer_s *dst, + VkBufferImageCopy *regions, + uint32_t numRegions); + #endif//__QF_Vulkan_command_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index c5d79af7b..aded86eb6 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -118,7 +118,14 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkGetImageMemoryRequirements) DEVICE_LEVEL_VULKAN_FUNCTION (vkBindImageMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateImageView) +DEVICE_LEVEL_VULKAN_FUNCTION (vkMapMemory) +DEVICE_LEVEL_VULKAN_FUNCTION (vkUnmapMemory) +DEVICE_LEVEL_VULKAN_FUNCTION (vkFlushMappedMemoryRanges) + DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBufferToImage) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyImageToBuffer) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/memory.h b/include/QF/Vulkan/memory.h index d50bddd00..bae79d9b7 100644 --- a/include/QF/Vulkan/memory.h +++ b/include/QF/Vulkan/memory.h @@ -6,4 +6,15 @@ typedef struct qfv_memory_s { VkDeviceMemory object; } qfv_memory_t; +typedef struct qfv_mappedmemrange_s { + qfv_memory_t *memory; + VkDeviceSize offset; + VkDeviceSize size; +} qfv_mappedmemrange_t; + +void *QFV_MapMemory (qfv_memory_t *memory, + VkDeviceSize offset, VkDeviceSize size); +void QFV_UnmapMemory (qfv_memory_t *memory); +void QFV_FlushMemory (qfv_mappedmemrange_t *ranges, uint32_t numRanges); + #endif//__QF_Vulkan_memory_h diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index 810e86d29..ba9b64948 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -9,6 +9,7 @@ vulkan_src = \ device.c \ image.c \ instance.c \ + memory.c \ swapchain.c \ util.c \ vulkan_draw.c \ diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index ecc6f7975..46c2ed83f 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -422,3 +422,43 @@ QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, numBuffBarriers, buffBarriers, numImgBarriers, imgBarriers); } + +void +QFV_CmdCopyBuffer (qfv_cmdbuffer_t *cmdBuffer, + struct qfv_buffer_s *src, struct qfv_buffer_s *dst, + VkBufferCopy *regions, uint32_t numRegions) +{ + qfv_device_t *device = cmdBuffer->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkCmdCopyBuffer (cmdBuffer->buffer, src->buffer, dst->buffer, + numRegions, regions); +} + +void +QFV_CmdCopyBufferToImage (qfv_cmdbuffer_t *cmdBuffer, + struct qfv_buffer_s *src, + struct qfv_image_s *dst, + VkImageLayout layout, + VkBufferImageCopy *regions, uint32_t numRegions) +{ + qfv_device_t *device = cmdBuffer->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkCmdCopyBufferToImage (cmdBuffer->buffer, src->buffer, dst->image, + layout, numRegions, regions); +} + +void +QFV_CmdCopyImageToBuffer (qfv_cmdbuffer_t *cmdBuffer, + struct qfv_image_s *src, + VkImageLayout layout, + struct qfv_buffer_s *dst, + VkBufferImageCopy *regions, uint32_t numRegions) +{ + qfv_device_t *device = cmdBuffer->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkCmdCopyImageToBuffer (cmdBuffer->buffer, src->image, layout, + dst->buffer, numRegions, regions); +} diff --git a/libs/video/renderer/vulkan/memory.c b/libs/video/renderer/vulkan/memory.c new file mode 100644 index 000000000..4ed912edb --- /dev/null +++ b/libs/video/renderer/vulkan/memory.c @@ -0,0 +1,102 @@ +/* + memory.c + + Vulkan memory functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/memory.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +void * +QFV_MapMemory (qfv_memory_t *memory, VkDeviceSize offset, VkDeviceSize size) +{ + qfv_device_t *device = memory->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + void *map = 0; + + dfunc->vkMapMemory (dev, memory->object, offset, size, 0, &map); + return map; +} + +void +QFV_UnmapMemory (qfv_memory_t *memory) +{ + qfv_device_t *device = memory->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkUnmapMemory (dev, memory->object); +} + +void +QFV_FlushMemory (qfv_mappedmemrange_t *flushRanges, uint32_t numFlushRanges) +{ + qfv_device_t *device = flushRanges[0].memory->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkMappedMemoryRange *ranges = alloca(sizeof (*ranges) * numFlushRanges); + + for (uint32_t i = 0; i < numFlushRanges; i++) { + ranges[i].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + ranges[i].pNext = 0; + ranges[i].memory = flushRanges[i].memory->object; + ranges[i].offset = flushRanges[i].offset; + ranges[i].size = flushRanges[i].size; + } + dfunc->vkFlushMappedMemoryRanges (dev, numFlushRanges, ranges); +} From 29b1d6baf8f94d31f4472798f6699abac5e832d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Feb 2020 09:37:04 +0900 Subject: [PATCH 0244/3664] Finish up memory stuff For now, of course. --- include/QF/Vulkan/buffer.h | 4 ++++ include/QF/Vulkan/funclist.h | 8 +++++++- include/QF/Vulkan/image.h | 4 ++++ include/QF/Vulkan/memory.h | 1 + libs/video/renderer/vulkan/buffer.c | 22 ++++++++++++++++++++++ libs/video/renderer/vulkan/image.c | 22 ++++++++++++++++++++++ libs/video/renderer/vulkan/memory.c | 11 +++++++++++ 7 files changed, 71 insertions(+), 1 deletion(-) diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h index 09ff14c2b..ef11ae8b7 100644 --- a/include/QF/Vulkan/buffer.h +++ b/include/QF/Vulkan/buffer.h @@ -50,4 +50,8 @@ QFV_CreateBufferTransitionSet (qfv_buffertransition_t **transitions, qfv_bufferview_t *QFV_CreateBufferView (qfv_buffer_t *buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize size); +void QFV_DestroyBufferView (qfv_bufferview_t *view); + +void QFV_DestroyBuffer (qfv_buffer_t *buffer); + #endif//__QF_Vulkan_buffer_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index aded86eb6..1f00d0b54 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -107,17 +107,23 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFence) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeCommandBuffers) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyCommandPool) + DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkGetBufferMemoryRequirements) -DEVICE_LEVEL_VULKAN_FUNCTION (vkAllocateMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkBindBufferMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateBufferView) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyBufferView) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkGetImageMemoryRequirements) DEVICE_LEVEL_VULKAN_FUNCTION (vkBindImageMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateImageView) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyImageView) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyImage) +DEVICE_LEVEL_VULKAN_FUNCTION (vkAllocateMemory) +DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkMapMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkUnmapMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkFlushMappedMemoryRanges) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 9c927e6b6..4258fe2e0 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -57,4 +57,8 @@ qfv_imageview_t *QFV_CreateImageView (qfv_image_t *image, VkImageViewType type, VkFormat format, VkImageAspectFlags aspect); +void QFV_DestroyImageView (qfv_imageview_t *view); + +void QFV_DestroyImage (qfv_image_t *image); + #endif//__QF_Vulkan_image_h diff --git a/include/QF/Vulkan/memory.h b/include/QF/Vulkan/memory.h index bae79d9b7..55b87f6c6 100644 --- a/include/QF/Vulkan/memory.h +++ b/include/QF/Vulkan/memory.h @@ -12,6 +12,7 @@ typedef struct qfv_mappedmemrange_s { VkDeviceSize size; } qfv_mappedmemrange_t; +void QFV_FreeMemory (qfv_memory_t *memory); void *QFV_MapMemory (qfv_memory_t *memory, VkDeviceSize offset, VkDeviceSize size); void QFV_UnmapMemory (qfv_memory_t *memory); diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index f2053c5db..e2d598b81 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -184,3 +184,25 @@ QFV_CreateBufferView (qfv_buffer_t *buffer, VkFormat format, dfunc->vkCreateBufferView (dev, &createInfo, 0, &view->view); return view; } + +void +QFV_DestroyBufferView (qfv_bufferview_t *view) +{ + qfv_device_t *device = view->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyBufferView (dev, view->view, 0); + free (view); +} + +void +QFV_DestroyBuffer (qfv_buffer_t *buffer) +{ + qfv_device_t *device = buffer->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyBuffer (dev, buffer->buffer, 0); + free (buffer); +} diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 4564fd2fe..63b836be5 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -212,3 +212,25 @@ QFV_CreateImageView (qfv_image_t *image, VkImageViewType type, VkFormat format, dfunc->vkCreateImageView (dev, &createInfo, 0, &view->view); return view; } + +void +QFV_DestroyImageView (qfv_imageview_t *view) +{ + qfv_device_t *device = view->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyImageView (dev, view->view, 0); + free (view); +} + +void +QFV_DestroyImage (qfv_image_t *image) +{ + qfv_device_t *device = image->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyImage (dev, image->image, 0); + free (image); +} diff --git a/libs/video/renderer/vulkan/memory.c b/libs/video/renderer/vulkan/memory.c index 4ed912edb..c18a8144f 100644 --- a/libs/video/renderer/vulkan/memory.c +++ b/libs/video/renderer/vulkan/memory.c @@ -60,6 +60,17 @@ #include "util.h" +void +QFV_FreeMemory (qfv_memory_t *memory) +{ + qfv_device_t *device = memory->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkFreeMemory (dev, memory->object, 0); + free (memory); +} + void * QFV_MapMemory (qfv_memory_t *memory, VkDeviceSize offset, VkDeviceSize size) { From 3144443a822a52ac465953042c441ae9f592ca72 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Feb 2020 12:19:16 +0900 Subject: [PATCH 0245/3664] Allow vulkan_draw to compile when optimizing Even though it's nowhere near done --- libs/video/renderer/vulkan/vulkan_draw.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 3c8dcc8e4..628306044 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -54,10 +54,22 @@ #include "r_internal.h" +static qpic_t * +pic_data (const char *name, int w, int h, const byte *data) +{ + qpic_t *pic; + + pic = malloc (field_offset (qpic_t, data[w * h])); + pic->width = w; + pic->height = h; + memcpy (pic->data, data, pic->width * pic->height); + return pic; +} + qpic_t * vulkan_Draw_MakePic (int width, int height, const byte *data) { - return 0; + return pic_data (0, width, height, data); } void @@ -68,13 +80,13 @@ vulkan_Draw_DestroyPic (qpic_t *pic) qpic_t * vulkan_Draw_PicFromWad (const char *name) { - return 0; + return pic_data (0, 1, 1, (const byte *)""); } qpic_t * vulkan_Draw_CachePic (const char *path, qboolean alpha) { - return 0; + return pic_data (0, 1, 1, (const byte *)""); } void From fbd79963bbbbf384cca33a61db8c97b088930c7f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Feb 2020 15:20:49 +0900 Subject: [PATCH 0246/3664] Update for doxygen 1.8.16 --- doc/quakeforge.dox.conf.in | 299 +++++++++++++++++++++-------- include/QF/alloc.h | 4 +- include/QF/cbuf.h | 4 +- include/QF/checksum.h | 4 +- include/QF/cmd.h | 4 +- include/QF/crc.h | 4 +- include/QF/cvar.h | 8 +- include/QF/draw.h | 8 +- include/QF/dstring.h | 20 +- include/QF/hash.h | 4 +- include/QF/idparse.h | 4 +- include/QF/info.h | 4 +- include/QF/keys.h | 4 +- include/QF/math/dual.h | 4 +- include/QF/math/half.h | 4 +- include/QF/math/matrix3.h | 4 +- include/QF/math/matrix4.h | 4 +- include/QF/math/quaternion.h | 4 +- include/QF/math/vector.h | 4 +- include/QF/mathlib.h | 4 +- include/QF/mdfour.h | 4 +- include/QF/msg.h | 4 +- include/QF/pak.h | 4 +- include/QF/pakfile.h | 4 +- include/QF/plugin.h | 4 +- include/QF/pr_type.h | 4 +- include/QF/progs.h | 73 +++---- include/QF/qargs.h | 4 +- include/QF/qendian.h | 4 +- include/QF/qfplist.h | 4 +- include/QF/quakefs.h | 4 +- include/QF/quakeio.h | 4 +- include/QF/script.h | 4 +- include/QF/set.h | 4 +- include/QF/sizebuf.h | 4 +- include/QF/sound.h | 12 +- include/QF/sys.h | 4 +- include/QF/va.h | 4 +- include/QF/ver_check.h | 4 +- include/QF/view.h | 4 +- include/QF/wad.h | 4 +- include/QF/wadfile.h | 4 +- include/QF/winding.h | 4 +- include/QF/zone.h | 4 +- include/net_dgrm.h | 4 +- include/net_loop.h | 4 +- include/net_udp.h | 4 +- include/net_vcr.h | 4 +- include/net_wins.h | 4 +- include/netchan.h | 12 +- include/netmain.h | 28 +-- include/snd_internal.h | 28 +-- libs/models/winding.c | 6 - qtv/include/connection.h | 4 +- qtv/include/qtv.h | 4 +- ruamoko/include/gui/Group.h | 4 +- ruamoko/include/gui/InputLine.h | 8 +- ruamoko/include/gui/Pic.h | 4 +- ruamoko/include/gui/Point.h | 4 +- ruamoko/include/gui/Rect.h | 4 +- ruamoko/include/gui/Size.h | 4 +- ruamoko/include/gui/Slider.h | 4 +- ruamoko/include/gui/Text.h | 4 +- ruamoko/include/gui/View.h | 4 +- tools/qfbsp/include/brush.h | 4 +- tools/qfbsp/include/bsp5.h | 4 +- tools/qfbsp/include/csg4.h | 4 +- tools/qfbsp/include/draw.h | 4 +- tools/qfbsp/include/map.h | 4 +- tools/qfbsp/include/merge.h | 4 +- tools/qfbsp/include/options.h | 4 +- tools/qfbsp/include/outside.h | 4 +- tools/qfbsp/include/portals.h | 4 +- tools/qfbsp/include/readbsp.h | 4 +- tools/qfbsp/include/region.h | 4 +- tools/qfbsp/include/solidbsp.h | 4 +- tools/qfbsp/include/surfaces.h | 4 +- tools/qfbsp/include/tjunc.h | 4 +- tools/qfbsp/include/writebsp.h | 4 +- tools/qfcc/include/dags.h | 4 +- tools/qfcc/include/def.h | 8 +- tools/qfcc/include/defspace.h | 4 +- tools/qfcc/include/diagnostic.h | 4 +- tools/qfcc/include/expr.h | 4 +- tools/qfcc/include/flow.h | 4 +- tools/qfcc/include/function.h | 4 +- tools/qfcc/include/obj_file.h | 21 +- tools/qfcc/include/obj_type.h | 2 - tools/qfcc/include/pragma.h | 4 +- tools/qfcc/include/qfcc.h | 4 +- tools/qfcc/include/symtab.h | 4 +- tools/qfcc/include/value.h | 4 +- tools/qflight/include/entities.h | 4 +- tools/qflight/include/light.h | 4 +- tools/qflight/include/noise.h | 4 +- tools/qflight/include/options.h | 4 +- tools/qflight/include/properties.h | 4 +- tools/qflight/include/threads.h | 4 +- 98 files changed, 496 insertions(+), 373 deletions(-) diff --git a/doc/quakeforge.dox.conf.in b/doc/quakeforge.dox.conf.in index 9db22207d..64028f578 100644 --- a/doc/quakeforge.dox.conf.in +++ b/doc/quakeforge.dox.conf.in @@ -1,4 +1,4 @@ -# Doxyfile 1.8.9.1 +# Doxyfile 1.8.16 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -17,11 +17,11 @@ # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 @@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. @@ -179,6 +187,16 @@ SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus @@ -226,7 +244,12 @@ TAB_SIZE = 4 # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) ALIASES = QF=QuakeForge @@ -264,17 +287,26 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # @@ -285,7 +317,7 @@ EXTENSION_MAPPING = no_extension=C # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. +# documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. @@ -293,6 +325,15 @@ EXTENSION_MAPPING = no_extension=C MARKDOWN_SUPPORT = YES +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or @@ -318,7 +359,7 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. @@ -343,6 +384,13 @@ IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = YES + # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent @@ -417,6 +465,12 @@ EXTRACT_ALL = YES EXTRACT_PRIVATE = NO +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. @@ -437,7 +491,7 @@ EXTRACT_STATIC = @STATIC_DOC@ EXTRACT_LOCAL_CLASSES = NO -# This flag is only useful for Objective-C code. When set to YES, local methods, +# This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. @@ -495,7 +549,7 @@ INTERNAL_DOCS = NO # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. +# (including Cygwin) ands Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = NO @@ -682,7 +736,7 @@ LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. @@ -727,11 +781,18 @@ WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = NO +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated @@ -755,7 +816,7 @@ WARN_LOGFILE = # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with -# spaces. +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = @TOPSRC@/include \ @@ -770,7 +831,7 @@ INPUT = @TOPSRC@/include \ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of # possible encodings. # The default value is: UTF-8. @@ -778,12 +839,17 @@ INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank the -# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, -# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, -# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, -# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, -# *.qsf, *.as and *.js. +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.h \ @@ -889,6 +955,10 @@ IMAGE_PATH = @TOPSRC@/doc \ # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. INPUT_FILTER = @@ -898,6 +968,10 @@ INPUT_FILTER = # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. FILTER_PATTERNS = @@ -950,7 +1024,7 @@ INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. +# entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO @@ -982,12 +1056,12 @@ SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version +# (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # @@ -1015,7 +1089,7 @@ VERBATIM_HEADERS = NO # rich C++ code for which doxygen's built-in parser lacks the necessary type # information. # Note: The availability of this option depends on whether or not doxygen was -# compiled with the --with-libclang option. +# generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO @@ -1028,6 +1102,16 @@ CLANG_ASSISTED_PARSING = NO CLANG_OPTIONS = +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1146,7 +1230,7 @@ HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. @@ -1182,6 +1266,17 @@ HTML_COLORSTYLE_GAMMA = 100 HTML_TIMESTAMP = NO +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. @@ -1205,13 +1300,13 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1250,7 +1345,7 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output @@ -1326,7 +1421,7 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1334,7 +1429,7 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1343,7 +1438,7 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1351,7 +1446,7 @@ QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1359,7 +1454,7 @@ QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = @@ -1452,7 +1547,7 @@ EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # @@ -1464,7 +1559,7 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering +# https://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path @@ -1491,8 +1586,8 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest @@ -1553,7 +1648,7 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). +# Xapian (see: https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1566,7 +1661,7 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Xapian (see: https://xapian.org/). See the section "External Indexing and # Searching" for details. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1618,21 +1713,35 @@ LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. # -# Note that when enabling USE_PDFLATEX this option is only used for generating -# bitmaps for formulas in the HTML output, but not in the Makefile that is -# written to the output directory. -# The default file is: latex. +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate # index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). # The default file is: makeindex. # This tag requires that the tag GENERATE_LATEX is set to YES. MAKEINDEX_CMD_NAME = makeindex +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = makeindex + # If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. @@ -1651,9 +1760,12 @@ COMPACT_LATEX = YES PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names -# that should be included in the LaTeX output. To get the times font for -# instance you can specify -# EXTRA_PACKAGES=times +# that should be included in the LaTeX output. The package can be specified just +# by its name or with the correct syntax as to be used with the LaTeX +# \usepackage command. To get the times font for instance you can specify : +# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} +# To use the option intlimits with the amsmath package you can specify: +# EXTRA_PACKAGES=[intlimits]{amsmath} # If left blank no extra packages will be included. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1750,12 +1862,28 @@ LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See -# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. # The default value is: plain. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BIB_STYLE = plain +# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_TIMESTAMP = NO + +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EMOJI_DIRECTORY = + #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- @@ -1795,9 +1923,9 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's config -# file, i.e. a series of assignments. You only have to provide replacements, -# missing definitions are set to their default value. +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the # default style sheet that doxygen normally uses. @@ -1806,8 +1934,8 @@ RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's config file. A template extensions file can be generated -# using doxygen -e rtf extensionFile. +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = @@ -1893,6 +2021,13 @@ XML_OUTPUT = xml XML_PROGRAMLISTING = YES +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- @@ -1925,9 +2060,9 @@ DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sf.net) file that captures the -# structure of the code including all documentation. Note that this feature is -# still experimental and incomplete at the moment. +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO @@ -2101,12 +2236,6 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of 'which perl'). -# The default file (with absolute path) is: /usr/bin/perl. - -PERL_PATH = /usr/bin/perl - #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- @@ -2120,15 +2249,6 @@ PERL_PATH = /usr/bin/perl CLASS_DIAGRAMS = YES -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see: -# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. @@ -2207,7 +2327,7 @@ COLLABORATION_GRAPH = YES # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. -GROUP_GRAPHS = NO +GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES, doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling @@ -2261,7 +2381,8 @@ INCLUDED_BY_GRAPH = YES # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. +# functions only using the \callgraph command. Disabling a call graph can be +# accomplished by means of the command \hidecallgraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2272,7 +2393,8 @@ CALL_GRAPH = NO # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. +# functions only using the \callergraph command. Disabling a caller graph can be +# accomplished by means of the command \hidecallergraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2295,13 +2417,17 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = NO # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. +# generated by dot. For an explanation of the image formats see the section +# output formats in the documentation of the dot tool (Graphviz (see: +# http://www.graphviz.org/)). # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). # Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, # png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, -# gif:cairo:gd, gif:gd, gif:gd:gd and svg. +# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo, +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2352,6 +2478,11 @@ DIAFILE_DIRS = PLANTUML_JAR_PATH = +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + # When using plantuml, the specified paths are searched for files specified by # the !include statement in a plantuml block. diff --git a/include/QF/alloc.h b/include/QF/alloc.h index 59a57bdf1..f67fe7176 100644 --- a/include/QF/alloc.h +++ b/include/QF/alloc.h @@ -37,7 +37,7 @@ /** \defgroup alloc High-tide allocator. \ingroup utils */ -//@{ +///@{ #ifndef DEBUG_QF_MEMORY /** High-tide structure allocator for use in linked lists. @@ -93,6 +93,6 @@ #define FREE(n, p) do { free (p); } while (0) #endif -//@} +///@} #endif//__QF_alloc_h diff --git a/include/QF/cbuf.h b/include/QF/cbuf.h index 9018fa6b6..29a89588e 100644 --- a/include/QF/cbuf.h +++ b/include/QF/cbuf.h @@ -34,7 +34,7 @@ /** \defgroup cbuf Command buffer management. \ingroup utils */ -//@{ +///@{ #include @@ -100,6 +100,6 @@ void Cbuf_Execute (cbuf_t *cbuf); void Cbuf_Execute_Stack (cbuf_t *cbuf); void Cbuf_Execute_Sets (cbuf_t *cbuf); -//@} +///@} #endif//__QF_cbuf_h diff --git a/include/QF/checksum.h b/include/QF/checksum.h index 9a7dfb8e6..ed6f035b1 100644 --- a/include/QF/checksum.h +++ b/include/QF/checksum.h @@ -30,7 +30,7 @@ /** \addtogroup crc */ -//@{ +///@{ #include "QF/qtypes.h" @@ -38,6 +38,6 @@ unsigned int Com_BlockChecksum (const void *buffer, int length); void Com_BlockFullChecksum (const void *buffer, int len, unsigned char *outbuf); byte COM_BlockSequenceCRCByte (const byte *base, int length, int sequence); -//@} +///@} #endif // __checksum_h diff --git a/include/QF/cmd.h b/include/QF/cmd.h index 2ac508b9f..35846a063 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -31,7 +31,7 @@ /** \defgroup cmd Command management. \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" #include "QF/cbuf.h" @@ -81,6 +81,6 @@ struct cbuf_interpreter_s *Cmd_GetProvider(const char *name); extern struct cbuf_args_s *cmd_args; extern struct cvar_s *cmd_warncmd; -//@} +///@} #endif//__QF_cmd_h diff --git a/include/QF/crc.h b/include/QF/crc.h index 2aa16b616..cc635e7b9 100644 --- a/include/QF/crc.h +++ b/include/QF/crc.h @@ -31,7 +31,7 @@ /** \defgroup crc Checksum generation. \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -41,6 +41,6 @@ void CRC_ProcessBlock (const byte *start, unsigned short *crcvalue, int count); unsigned short CRC_Value(unsigned short crcvalue) __attribute__((const)); unsigned short CRC_Block (const byte *start, int count) __attribute__((pure)); -//@} +///@} #endif // __crc_h diff --git a/include/QF/cvar.h b/include/QF/cvar.h index 091a13b61..3d81a3b1c 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -31,7 +31,7 @@ /** \defgroup cvar Configuration variables \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" #include "QF/quakeio.h" @@ -72,7 +72,7 @@ typedef struct cvar_alias_s { code goes "look, the user made fs_basepath already", uses the users value, but sets CVAR_ROM as per the call. */ -//@{ +///@{ #define CVAR_NONE 0 ///< normal cvar #define CVAR_ARCHIVE 1 ///< set to cause it to be saved to ///< config.cfg @@ -85,7 +85,7 @@ typedef struct cvar_alias_s { #define CVAR_LATCH 2048 ///< will change only when C code next does ///< a Cvar_Get(), so it can't be changed ///< (not implemented) -//@} +///@} // Returns the Cvar if found, creates it with value if not. Description and @@ -138,6 +138,6 @@ void Cvar_Init (void); extern cvar_t *cvar_vars; -//@} +///@} #endif // __cvar_h diff --git a/include/QF/draw.h b/include/QF/draw.h index d8067a4c7..529f3e892 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -37,7 +37,7 @@ /** \defgroup video_renderer_draw Generic draw functions \ingroup video_renderer */ -//@{ +///@{ #include "QF/wad.h" @@ -160,12 +160,12 @@ void Draw_FadeScreen (void); /** Shift the screen colors. */ void Draw_BlendScreen (quat_t color); -//@} +///@} /** \defgroup video_renderer_draw_qpic QPic functions \ingroup video_renderer_draw */ -//@{ +///@{ /** Load a qpic from the filesystem. \param path path of the file within the quake filesystem \param alpha transparency level of the pic. @@ -232,6 +232,6 @@ void Draw_Picf (float x, float y, qpic_t *pic); \param height vertical size of the sub-region to be drawn */ void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); -//@} +///@} #endif // _DRAW_H diff --git a/include/QF/dstring.h b/include/QF/dstring.h index 1075bc04b..638d9e340 100644 --- a/include/QF/dstring.h +++ b/include/QF/dstring.h @@ -31,7 +31,7 @@ /** \defgroup dstring Dynamic Strings \ingroup utils */ -//@{ +///@{ #include #include @@ -52,13 +52,13 @@ typedef struct dstring_s { extern dstring_mem_t dstring_default_mem; // General buffer functions -//@{ +///@{ /** Create a new dstring. size and truesize start at 0 and no string buffer is allocated. */ dstring_t *_dstring_new (dstring_mem_t *mem); dstring_t *dstring_new (void); -//@} +///@} /** Delete a dstring. Both the string buffer and dstring object are freed. */ void dstring_delete (dstring_t *dstr); @@ -103,13 +103,13 @@ void dstring_replace (dstring_t *dstr, unsigned int pos, unsigned int rlen, char *dstring_freeze (dstring_t *dstr); // String-specific functions -//@{ +///@{ /** Allocate a new dstring pre-initialized as a null terminated string. size will be 1 and the first byte 0. */ dstring_t *_dstring_newstr (dstring_mem_t *mem); dstring_t *dstring_newstr (void); -//@} +///@} /** Create a new dstring from a string. Similar to strdup(). \param str the string to copy \return inititialized dstring @@ -160,21 +160,21 @@ void dstring_insertsubstr (dstring_t *dstr, unsigned int pos, const char *str, */ void dstring_clearstr (dstring_t *dstr); -//@{ +///@{ /** Formatted printing to dstrings. Existing data is replaced by the formatted string. */ int dvsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); int dsprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); -//@} -//@{ +///@} +///@{ /** Formatted printing to dstrings. Formatted string is appened to the dstring. Embedded nulls in the dstring are ignored. */ int davsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); int dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); -//@} +///@} -//@} +///@} #endif // __dstring_h diff --git a/include/QF/hash.h b/include/QF/hash.h index 1a8a8f912..ae040cfa9 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -34,7 +34,7 @@ /** \defgroup hash Hash tables \ingroup utils */ -//@{ +///@{ typedef struct hashtab_s hashtab_t; @@ -209,6 +209,6 @@ void **Hash_GetList (hashtab_t *tab); */ void Hash_Stats (hashtab_t *tab); -//@} +///@} #endif // __hash_h diff --git a/include/QF/idparse.h b/include/QF/idparse.h index 07b5c322e..e48cf30e6 100644 --- a/include/QF/idparse.h +++ b/include/QF/idparse.h @@ -33,7 +33,7 @@ /** \addtogroup cbuf */ -//@{ +///@{ extern const char *com_token; @@ -44,6 +44,6 @@ void COM_TokenizeString (const char *str, struct cbuf_args_s *args); extern struct cbuf_interpreter_s id_interp; -//@} +///@} #endif//__QF_idparse_h diff --git a/include/QF/info.h b/include/QF/info.h index d57a221f6..4e34f6fa2 100644 --- a/include/QF/info.h +++ b/include/QF/info.h @@ -31,7 +31,7 @@ /** \defgroup info Info Keys \ingroup utils */ -//@{ +///@{ #include // for size_t. sys/types.h SHOULD be used, but can't :(bc) #include @@ -63,6 +63,6 @@ void Info_Destroy (info_t *info); char *Info_MakeString (info_t *info, int (*filter)(const char *)); void Info_AddKeys (info_t *info, info_t *keys); -//@} +///@} #endif // _INFO_H diff --git a/include/QF/keys.h b/include/QF/keys.h index ada46a265..66ef8d99e 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -39,7 +39,7 @@ /** \defgroup input_keybinding Key Binding Sub-system \ingroup input */ -//@{ +///@{ /// these are the key numbers that should be passed to Key_Event typedef enum { @@ -659,6 +659,6 @@ struct progs_s; void Key_Progs_Init (struct progs_s *pr); #endif -//@} +///@} #endif // _KEYS_H diff --git a/include/QF/math/dual.h b/include/QF/math/dual.h index eba9b8bf0..34c58a984 100644 --- a/include/QF/math/dual.h +++ b/include/QF/math/dual.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_dual Dual and dual quaternion functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -189,6 +189,6 @@ } while (0) #define DualQuatExpand(dq) QuatExpand ((dq).q0.q), QuatExpand ((dq).qe.q) -//@} +///@} #endif // __QF_math_dual_h diff --git a/include/QF/math/half.h b/include/QF/math/half.h index 1fe474cd3..bc9133fc6 100644 --- a/include/QF/math/half.h +++ b/include/QF/math/half.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_half Half-float functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -42,6 +42,6 @@ int16_t FloatToHalf (float x) __attribute__((const)); float HalfToFloat (int16_t x) __attribute__((const)); -//@} +///@} #endif // __QF_math_half_h diff --git a/include/QF/math/matrix3.h b/include/QF/math/matrix3.h index ce2474a99..dfe9b530f 100644 --- a/include/QF/math/matrix3.h +++ b/include/QF/math/matrix3.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_matrix3 3x3 matrix functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -118,6 +118,6 @@ void Mat3SymEigen (const mat3_t m, vec3_t e); */ int Mat3Decompose (const mat4_t mat, quat_t rot, vec3_t shear, vec3_t scale); -//@} +///@} #endif // __QF_math_matrix3_h diff --git a/include/QF/math/matrix4.h b/include/QF/math/matrix4.h index 4f0e0dfb5..a55c8ed94 100644 --- a/include/QF/math/matrix4.h +++ b/include/QF/math/matrix4.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_matrix4 4x4 matrix functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -130,6 +130,6 @@ void Mat4as3MultVec (const mat4_t a, const vec3_t b, vec3_t c); int Mat4Decompose (const mat4_t mat, quat_t rot, vec3_t shear, vec3_t scale, vec3_t trans); -//@} +///@} #endif // __QF_math_matrix4_h diff --git a/include/QF/math/quaternion.h b/include/QF/math/quaternion.h index 84d7b64b4..d6e34814a 100644 --- a/include/QF/math/quaternion.h +++ b/include/QF/math/quaternion.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_quaternion Quaternion functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -168,6 +168,6 @@ void QuatInverse (const quat_t in, quat_t out); void QuatExp (const quat_t a, quat_t b); void QuatToMatrix (const quat_t q, vec_t *m, int homogenous, int vertical); -//@} +///@} #endif // __QF_math_quaternion_h diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 73cc1f708..6a8b80809 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -31,7 +31,7 @@ /** \defgroup mathlib_vector Vector functions \ingroup mathlib */ -//@{ +///@{ #include "QF/qtypes.h" @@ -209,6 +209,6 @@ VectorNormalize (vec3_t v) return length; } -//@} +///@} #endif // __QF_math_vector_h diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index c4575705e..5c9b854fe 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -31,7 +31,7 @@ /** \defgroup mathlib Vector and matrix functions \ingroup utils */ -//@{ +///@{ #include #include "QF/qtypes.h" @@ -218,6 +218,6 @@ int CircumSphere (const vec3_t points[], int num_points, sphere_t *sphere); void BarycentricCoords (const vec_t **points, int num_points, const vec3_t p, vec_t *lambda); -//@} +///@} #endif // __mathlib_h diff --git a/include/QF/mdfour.h b/include/QF/mdfour.h index 94fe99da0..19360e838 100644 --- a/include/QF/mdfour.h +++ b/include/QF/mdfour.h @@ -31,7 +31,7 @@ /** \addtogroup crc */ -//@{ +///@{ #include "QF/uint32.h" @@ -47,6 +47,6 @@ void mdfour_update(struct mdfour *md, const unsigned char *in, int n); //old: MD void mdfour_result(struct mdfour *md, unsigned char *out); // old: MD4Final void mdfour(unsigned char *out, const unsigned char *in, int n); -//@} +///@} #endif // __mdfour_h diff --git a/include/QF/msg.h b/include/QF/msg.h index 6e550a191..6a92e2d54 100644 --- a/include/QF/msg.h +++ b/include/QF/msg.h @@ -30,7 +30,7 @@ /** \defgroup msg Message reading and writing \ingroup utils */ -//@{ +///@{ #include "QF/sizebuf.h" @@ -249,6 +249,6 @@ void MSG_ReadAngle16V (qmsg_t *msg, vec3_t angles); */ int MSG_ReadUTF8 (qmsg_t *msg); -//@} +///@} #endif diff --git a/include/QF/pak.h b/include/QF/pak.h index f176e5733..ea86ffd14 100644 --- a/include/QF/pak.h +++ b/include/QF/pak.h @@ -33,7 +33,7 @@ /** \addtogroup pak */ -//@{ +///@{ // little-endian PACK #define IDPAKHEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P') @@ -51,6 +51,6 @@ typedef struct { int dirlen; } dpackheader_t; -//@} +///@} #endif//__qf_pak_h diff --git a/include/QF/pakfile.h b/include/QF/pakfile.h index ecb6738f0..7bb4f3a0e 100644 --- a/include/QF/pakfile.h +++ b/include/QF/pakfile.h @@ -33,7 +33,7 @@ /** \defgroup pak pakfile proccessing \ingroup utils */ -//@{ +///@{ #include "QF/hash.h" #include "QF/pak.h" @@ -64,6 +64,6 @@ int pack_add (pack_t *pack, const char *filename); int pack_extract (pack_t *pack, dpackfile_t *pf); dpackfile_t *pack_find_file (pack_t *pack, const char *filename); -//@} +///@} #endif//__QF_pakfile_h diff --git a/include/QF/plugin.h b/include/QF/plugin.h index 28cb9962f..0a06f73f2 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -31,7 +31,7 @@ /** \defgroup plugin Plugins \ingroup utils */ -//@{ +///@{ #define QFPLUGIN_VERSION "1.0" @@ -111,6 +111,6 @@ void PI_Shutdown (void); // FIXME: we need a generic function to initialize unused fields -//@} +///@} #endif // __QF_plugin_h_ diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index 4cc6cf82e..0c8b37664 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -36,7 +36,7 @@ All \c pointer_t \c type fields are pointers within the type qfo_space. */ -//@{ +///@{ #include "QF/pr_comp.h" @@ -102,6 +102,6 @@ typedef struct qfot_type_encodings_s { pr_int_t size; } qfot_type_encodings_t; -//@} +///@} #endif//__pr_type_h diff --git a/include/QF/progs.h b/include/QF/progs.h index 5b834d1f0..7631f1de1 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -39,18 +39,18 @@ struct QFile_s; /** \ingroup progs */ -//@{ +///@{ typedef struct progs_s progs_t; typedef struct pr_resource_s pr_resource_t; typedef struct edict_s edict_t; -//@} +///@} //============================================================================ /** \defgroup progs_misc Miscelaneous functions \ingroup progs */ -//@{ +///@{ /** Initialize the progs engine. */ @@ -63,12 +63,12 @@ void PR_Init_Cvars (void); void PR_Error (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3), noreturn)); void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3), noreturn)); -//@} +///@} /** \defgroup progs_execution Execution \ingroup progs */ -//@{ +///@{ /** Ensure P_* macros point to the right place for passing parameters to progs functions. @@ -128,12 +128,12 @@ void PR_ExecuteProgram (progs_t *pr, func_t fnum); */ int PR_CallFunction (progs_t *pr, func_t fnum); -//@} +///@} /** \defgroup progs_load Loading \ingroup progs */ -//@{ +///@{ /** Type of functions that are called at progs load. \param pr pointer to ::progs_t VM struct @@ -204,12 +204,12 @@ int PR_Check_Opcodes (progs_t *pr); void PR_BoundsCheckSize (progs_t *pr, pointer_t addr, unsigned size); void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); -//@} +///@} /** \defgroup progs_edict Edict management \ingroup progs */ -//@{ +///@{ struct edict_s { qboolean free; @@ -261,13 +261,13 @@ void ED_EntityParseFunction (progs_t *pr); # define NUM_FOR_EDICT(p,e) ED_NumForEdict (p, e) #endif -//@} +///@} /** \defgroup pr_symbols Symbol Management \ingroup progs Lookup functions for symbol name resolution. */ -//@{ +///@{ ddef_t *PR_FieldAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure)); ddef_t *PR_GlobalAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure)); @@ -282,7 +282,7 @@ int PR_AccessField (progs_t *pr, const char *name, etype_t type, const char *file, int line); void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute__((noreturn)); -//@} +///@} //============================================================================ @@ -296,7 +296,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ Typed global access macros. No checking is done against the QC type, but the appropriate C type will be used. */ -//@{ +///@{ /** \internal \param p pointer to ::progs_t VM struct @@ -479,14 +479,14 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ #define G_STRUCT(p,t,o) (*(t *)G_GPOINTER (p, o)) -//@} +///@} /** \defgroup prda_parameters Parameters \ingroup progs_data_access Typed parameter access macros. No checking is done against the QC type, but the appropriate C type will be used. */ -//@{ +///@{ /** \internal \param p pointer to ::progs_t VM struct @@ -669,7 +669,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ #define P_STRUCT(p,t,n) (*(t *)P_GPOINTER (p, n)) -//@} +///@} /** \defgroup prda_return Return Values \ingroup progs_data_access @@ -680,7 +680,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ ask for an \c int from a function that returned a \c float, you're asking for trouble. */ -//@{ +///@{ /** \internal \param p pointer to ::progs_t VM struct @@ -836,14 +836,14 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ #define RETURN_QUAT(p,q) VectorCopy (q, R_QUAT (p)) -//@} +///@} /** \defgroup prda_entity_fields Entity Fields \ingroup progs_data_access Typed entity field access macros. No checking is done against the QC type, but the appropriate C type will be used. */ -//@{ +///@{ /** \internal \param e pointer to the entity @@ -980,7 +980,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ #define E_DSTRING(p,e,o) (PR_GetMutableString (p, E_STRING (e, o))) -//@} +///@} /** \defgroup pr_builtins VM Builtin functions \ingroup progs @@ -993,7 +993,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ 0x8000000 to 0xffffffff is unavailable due to the builtin number being a negative statement address. */ -//@{ +///@{ #define PR_RANGE_SHIFT 16 #define PR_RANGE_MASK 0xffff0000 @@ -1067,7 +1067,7 @@ builtin_t *PR_FindBuiltinNum (progs_t *pr, pr_int_t num); */ int PR_RelocateBuiltins (progs_t *pr); -//@} +///@} /** \defgroup pr_strings String Management \ingroup progs @@ -1093,7 +1093,7 @@ int PR_RelocateBuiltins (progs_t *pr); They can be created, altered, and destroyed at any time by the main program (or the progs code via an appropriate builtin function). */ -//@{ +///@{ /** Initialize the string tables using the strings supplied by the progs. Called automatically during progs load. @@ -1254,13 +1254,13 @@ void PR_FreeTempStrings (progs_t *pr); void PR_Sprintf (progs_t *pr, struct dstring_s *result, const char *name, const char *format, int count, pr_type_t **args); -//@} +///@} /** \defgroup pr_resources Resource Management \ingroup progs Builtin module private data management. */ -//@{ +///@{ /** Initialize the resource management fields. @@ -1314,7 +1314,7 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \note \p map is the resource map itself, not a pointer to the resource map. */ -//@{ +///@{ /** Type delcaration for the resource map. @@ -1416,29 +1416,30 @@ void *PR_Resources_Find (progs_t *pr, const char *name); return ~(i * 1024 + d); \ } \ return 0 -//@} +///@} -//@} +///@} /** \defgroup pr_zone VM memory management. \ingroup progs Used to allocate and free memory in the VM address space. */ -//@{ +///@{ void PR_Zone_Init (progs_t *pr); void PR_Zone_Free (progs_t *pr, void *ptr); void *PR_Zone_Malloc (progs_t *pr, pr_int_t size); void *PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size); -//@} +///@} /** \defgroup debug VM Debugging \ingroup progs Progs debugging support. */ -//@{ +/// \addtogroup debug +///@{ void PR_Debug_Init (void); void PR_Debug_Init_Cvars (void); @@ -1464,20 +1465,20 @@ extern struct cvar_s *pr_deadbeef_locals; extern struct cvar_s *pr_boundscheck; extern struct cvar_s *pr_faultchecks; -//@} +///@} /** \defgroup pr_cmds Quake and Quakeworld common builtins \ingroup progs \todo This really doesn't belong in progs. */ -//@{ +///@{ char *PF_VarString (progs_t *pr, int first); void PR_Cmds_Init (progs_t *pr); extern const char *pr_gametype; -//@} +///@} //============================================================================ @@ -1682,7 +1683,7 @@ struct progs_s { /** \addtogroup progs_data_access */ -//@{ +///@{ /** Convert a progs offset/pointer to a C pointer. \param pr pointer to ::progs_t VM struct @@ -1706,7 +1707,7 @@ PR_SetPointer (progs_t *pr, void *p) return p ? (pr_type_t *) p - pr->pr_globals : 0; } -//@} +///@} /** \example vm-exec.c */ diff --git a/include/QF/qargs.h b/include/QF/qargs.h index fe4eb98f8..50dfbd35a 100644 --- a/include/QF/qargs.h +++ b/include/QF/qargs.h @@ -32,7 +32,7 @@ /** \addtogroup misc */ -//@{ +///@{ #include "QF/qtypes.h" @@ -50,6 +50,6 @@ void COM_Init_Cvars (void); void COM_InitArgv (int argc, const char **argv); void COM_ParseConfig (void); -//@} +///@} #endif // __qargs_h diff --git a/include/QF/qendian.h b/include/QF/qendian.h index d63ca2d0c..a42bd749f 100644 --- a/include/QF/qendian.h +++ b/include/QF/qendian.h @@ -33,7 +33,7 @@ /** \defgroup qendian Endian handling functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -118,6 +118,6 @@ byte ReadByte (struct QFile_s *file); unsigned short ReadShort (struct QFile_s *file); unsigned int ReadLong (struct QFile_s *file); -//@} +///@} #endif // __qendian_h diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 6c5d61202..e0c2557ca 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -31,7 +31,7 @@ /** \defgroup qfplist Property lists \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -226,6 +226,6 @@ plitem_t *PL_NewString (const char *str); */ void PL_Free (plitem_t *item); -//@} +///@} #endif // __QF_qfplist_h_ diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index 336537495..364718db0 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -33,7 +33,7 @@ /** \defgroup quakefs Quake Filesystem \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" #include "QF/quakeio.h" @@ -418,6 +418,6 @@ void QFS_FilelistFill (filelist_t *list, const char *path, const char *ext, */ void QFS_FilelistFree (filelist_t *list); -//@} +///@} #endif // __quakefs_h diff --git a/include/QF/quakeio.h b/include/QF/quakeio.h index d72d8ec29..08b14af69 100644 --- a/include/QF/quakeio.h +++ b/include/QF/quakeio.h @@ -34,7 +34,7 @@ /** \defgroup quakeio File IO \ingroup utils */ -//@{ +///@{ typedef struct QFile_s QFile; @@ -60,6 +60,6 @@ int Qflush(QFile *file); int Qeof(QFile *file); const char *Qgetline(QFile *file); -//@} +///@} #endif /*__quakeio_h*/ diff --git a/include/QF/script.h b/include/QF/script.h index 2fe21c215..357e5100b 100644 --- a/include/QF/script.h +++ b/include/QF/script.h @@ -25,7 +25,7 @@ Line oriented script parsing. Multiple scripts being parsed at the same time is supported. */ -//@{ +///@{ #include "QF/qtypes.h" @@ -97,6 +97,6 @@ void Script_UngetToken (script_t *script); */ const char *Script_Token (script_t *script) __attribute__((pure)); -//@} +///@} #endif//__QF_script_h diff --git a/include/QF/set.h b/include/QF/set.h index 2f4dd76e5..1261bdb40 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -36,7 +36,7 @@ /** \defgroup set Set handling \ingroup utils */ -//@{ +///@{ //FIXME other archs #ifdef __x86_64__ @@ -370,5 +370,5 @@ set_iter_t *set_next_r (set_pool_t *set_pool, set_iter_t *set_iter); */ const char *set_as_string (const set_t *set); -//@} +///@} #endif//__QF_set_h diff --git a/include/QF/sizebuf.h b/include/QF/sizebuf.h index 8605f803d..7f6fc4ac3 100644 --- a/include/QF/sizebuf.h +++ b/include/QF/sizebuf.h @@ -31,7 +31,7 @@ \ingroup utils Fixed size buffer management */ -//@{ +///@{ #include "QF/qtypes.h" @@ -51,6 +51,6 @@ void *SZ_GetSpace (sizebuf_t *buf, int length); void SZ_Write (sizebuf_t *buf, const void *data, int length); void SZ_Print (sizebuf_t *buf, const char *data); // strcats onto the sizebuf -//@} +///@} #endif // __sizebuf_h diff --git a/include/QF/sound.h b/include/QF/sound.h index 3e37a5871..11f103080 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -37,7 +37,7 @@ /** \ingroup sound */ -//@{ +///@{ typedef struct sfx_s sfx_t; struct sfx_s { @@ -62,14 +62,14 @@ struct sfx_s sfx_t *(*open) (sfx_t *sfx); void (*close) (sfx_t *sfx); }; -//@} +///@} struct model_s; /** \defgroup sound_init Initialization functions \ingroup sound */ -//@{ +///@{ /** Initialize the sound engine. \param viewentity pointer to view entity index @@ -81,12 +81,12 @@ void S_Init (int *viewentity, double *host_frametime); */ void S_Init_Cvars (void); -//@} +///@} /** \defgroup sound_stuff Unclassified \ingroup sound */ -//@{ +///@{ /** Start a sound playing. \param entnum index of entity the sound is associated with. @@ -189,6 +189,6 @@ void S_AmbientOn (void); struct progs_s; void S_Progs_Init (struct progs_s *pr); -//@} +///@} #endif // _SOUND_H diff --git a/include/QF/sys.h b/include/QF/sys.h index 7c669563e..10c1c902e 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -32,7 +32,7 @@ \ingroup utils Non-portable functions */ -//@{ +///@{ #include #include @@ -159,6 +159,6 @@ int Sys_CreatePath (const char *path); */ char *Sys_ExpandSquiggle (const char *path); -//@} +///@} #endif // __sys_h diff --git a/include/QF/va.h b/include/QF/va.h index 6a5e54465..40c794712 100644 --- a/include/QF/va.h +++ b/include/QF/va.h @@ -32,13 +32,13 @@ /** \addtogroup misc Formatted printing. */ -//@{ +///@{ // does a varargs printf into a temp buffer char *va(const char *format, ...) __attribute__((format(printf,1,2))); // does a varargs printf into a malloced buffer char *nva(const char *format, ...) __attribute__((format(printf,1,2))); -//@} +///@} #endif // __va_h diff --git a/include/QF/ver_check.h b/include/QF/ver_check.h index 5d8c1061c..8ac943796 100644 --- a/include/QF/ver_check.h +++ b/include/QF/ver_check.h @@ -34,7 +34,7 @@ /** \defgroup misc Miscellaneous functions \ingroup utils */ -//@{ +///@{ /* ver_compare @@ -45,6 +45,6 @@ */ int ver_compare (const char *, const char *); -//@} +///@} #endif // __ver_check_h_ diff --git a/include/QF/view.h b/include/QF/view.h index ecb2ea920..570935ae8 100644 --- a/include/QF/view.h +++ b/include/QF/view.h @@ -34,7 +34,7 @@ /** \defgroup console_view Console View Objects \ingroup console */ -//@{ +///@{ /** Control the positioning of a view within its parent. The directions are the standard compass rose (north, east, south, west in clockwise order) @@ -215,6 +215,6 @@ void view_resize (view_t *view, int xl, int yl); */ void view_move (view_t *view, int xp, int yp); -//@} +///@} #endif//__qf_view_h diff --git a/include/QF/wad.h b/include/QF/wad.h index 805a69925..82e836dc9 100644 --- a/include/QF/wad.h +++ b/include/QF/wad.h @@ -32,7 +32,7 @@ /** \addtogroup wad Wad Files */ -//@{ +///@{ #include "QF/wadfile.h" @@ -46,6 +46,6 @@ void *W_GetLumpName (const char *name); void SwapPic (qpic_t *pic); -//@} +///@} #endif // _WAD_H diff --git a/include/QF/wadfile.h b/include/QF/wadfile.h index 79e5e2055..9e6c220f6 100644 --- a/include/QF/wadfile.h +++ b/include/QF/wadfile.h @@ -29,7 +29,7 @@ \ingroup utils Wadfile processing */ -//@{ +///@{ #ifndef __QF_wadfile_h #define __QF_wadfile_h @@ -102,6 +102,6 @@ int wad_add_data (wad_t *wad, const char *lumpname, byte type, const void *data, int bytes); lumpinfo_t *wad_find_lump (wad_t *wad, const char *filename); -//@} +///@} #endif//__QF_wadfile_h diff --git a/include/QF/winding.h b/include/QF/winding.h index 5ef3d8094..5815ac793 100644 --- a/include/QF/winding.h +++ b/include/QF/winding.h @@ -26,7 +26,7 @@ /** \defgroup winding Winding Manipulation */ -//@{ +///@{ struct plane_s; @@ -138,6 +138,6 @@ winding_t *ClipWinding (winding_t *in, struct plane_s *split, qboolean keepon); void DivideWinding (winding_t *in, struct plane_s *split, winding_t **front, winding_t **back); -//@} +///@} #endif//__QF_winding_h diff --git a/include/QF/zone.h b/include/QF/zone.h index 379f4557a..1f968737f 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -88,7 +88,7 @@ ----- Bottom of Memory ----- */ -//@{ +///@{ typedef struct memzone_s memzone_t; @@ -140,6 +140,6 @@ void *Cache_Get (cache_user_t *c); void Cache_Release (cache_user_t *c); int Cache_ReadLock (cache_user_t *c) __attribute__((pure)); -//@} +///@} #endif // __zone_h diff --git a/include/net_dgrm.h b/include/net_dgrm.h index 712864dd3..38c2f7e19 100644 --- a/include/net_dgrm.h +++ b/include/net_dgrm.h @@ -29,7 +29,7 @@ /** \defgroup nq-dgrm NetQuake Datagram network driver. \ingroup nq-nd */ -//@{ +///@{ /** Initialize the Datagram net driver. @@ -125,4 +125,4 @@ void Datagram_Close (qsocket_t *sock); */ void Datagram_Shutdown (void); -//@} +///@} diff --git a/include/net_loop.h b/include/net_loop.h index a0f58a34a..9247f949e 100644 --- a/include/net_loop.h +++ b/include/net_loop.h @@ -34,7 +34,7 @@ /** \defgroup nq-loop NetQuake loopback network driver. \ingroup nq-nd */ -//@{ +///@{ int Loop_Init (void); void Loop_Listen (qboolean state); @@ -49,6 +49,6 @@ qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock); void Loop_Close (qsocket_t *sock); void Loop_Shutdown (void); -//@} +///@} #endif//__net_loop_h diff --git a/include/net_udp.h b/include/net_udp.h index 78f26a6ec..bd414513d 100644 --- a/include/net_udp.h +++ b/include/net_udp.h @@ -33,7 +33,7 @@ /** \defgroup nq-udp NetQuake UDP lan driver. \ingroup nq-ld */ -//@{ +///@{ /** Initialize the UDP network interface. @@ -193,6 +193,6 @@ int UDP_GetSocketPort (netadr_t *addr); */ int UDP_SetSocketPort (netadr_t *addr, int port); -//@} +///@} #endif // __net_udp_h diff --git a/include/net_vcr.h b/include/net_vcr.h index f5383b572..9f5446453 100644 --- a/include/net_vcr.h +++ b/include/net_vcr.h @@ -29,7 +29,7 @@ /** \defgroup nq-vcr NetQuake VCR network driver. \ingroup nq-nd */ -//@{ +///@{ #define VCR_OP_CONNECT 1 #define VCR_OP_GETMESSAGE 2 @@ -48,4 +48,4 @@ qboolean VCR_CanSendMessage (qsocket_t *sock); void VCR_Close (qsocket_t *sock); void VCR_Shutdown (void); -//@} +///@} diff --git a/include/net_wins.h b/include/net_wins.h index fe4133f50..c4954f9ac 100644 --- a/include/net_wins.h +++ b/include/net_wins.h @@ -35,7 +35,7 @@ /** \defgroup nq-wins NetQuake Winsock lan driver. \ingroup nq-ld */ -//@{ +///@{ extern int winsock_initialized; extern WSADATA winsockdata; @@ -58,6 +58,6 @@ int WINS_AddrCompare (netadr_t *addr1, netadr_t *addr2); int WINS_GetSocketPort (netadr_t *addr); int WINS_SetSocketPort (netadr_t *addr, int port); -//@} +///@} #endif//__net_wins_h diff --git a/include/netchan.h b/include/netchan.h index 4aa266fc8..cebfe4bd4 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -39,7 +39,7 @@ /** \defgroup qw-net QuakeWorld network support. \ingroup network */ -//{ +///@{ #define MAX_MSGLEN 1450 ///< max length of a reliable message #define MAX_DATAGRAM 1450 ///< max length of unreliable message @@ -75,12 +75,12 @@ void Analyze_Client_Packet (const byte * data, int len, int has_sequence); void Analyze_Server_Packet (const byte * data, int len, int has_sequence); extern struct cvar_s *net_packetlog; -//@} +///@} /** \defgroup qw-udp QuakeWorld udp support. \ingroup qw-net */ -//@{ +///@{ /** Initialize the UDP network interface. @@ -161,7 +161,7 @@ const char *NET_BaseAdrToString (netadr_t a); */ qboolean NET_StringToAdr (const char *s, netadr_t *a); -//@} +///@} /** \defgroup netchan Netchan \ingroup qw-net @@ -216,7 +216,7 @@ qboolean NET_StringToAdr (const char *s, netadr_t *a); the channel matches even if the IP port differs. The IP port should be updated to the new value before sending out any replies. */ -//@{ +///@{ #define OLD_AVG 0.99 // total = oldtotal*OLD_AVG + new*(1-OLD_AVG) #define MAX_LATENT 32 @@ -377,6 +377,6 @@ qboolean Netchan_CanReliable (netchan_t *chan) __attribute__((pure)); */ void Netchan_SendPacket (int length, const void *data, netadr_t to); -//@} +///@} #endif // _NET_H diff --git a/include/netmain.h b/include/netmain.h index fdb870628..351e615ba 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -34,7 +34,7 @@ /** \defgroup nq-net NetQuake network support. \ingroup network */ -//@{ +///@{ typedef struct { @@ -56,7 +56,7 @@ typedef struct /** \name NetHeader flags */ -//@{ +///@{ #define NETFLAG_LENGTH_MASK 0x0000ffff #define NETFLAG_DATA 0x00010000 #define NETFLAG_ACK 0x00020000 @@ -64,7 +64,7 @@ typedef struct #define NETFLAG_EOM 0x00080000 #define NETFLAG_UNRELIABLE 0x00100000 #define NETFLAG_CTL 0x80000000 -//@} +///@} #define NET_PROTOCOL_VERSION 3 @@ -86,7 +86,7 @@ typedef struct a full address and port in a string. It is used for returning the address of a server that is not running locally. */ -//@{ +///@{ /** Connect Request: \arg \b string \c game_name \em "QUAKE" @@ -153,7 +153,7 @@ typedef struct \arg \b string \c value */ #define CCREP_RULE_INFO 0x85 -//@} +///@} typedef struct qsocket_s { struct qsocket_s *next; @@ -205,11 +205,11 @@ typedef struct qsocket_s { /** \name socket management */ -//@{ +///@{ extern qsocket_t *net_activeSockets; extern qsocket_t *net_freeSockets; extern int net_numsockets; -//@} +///@} #define MAX_NET_DRIVERS 8 @@ -220,12 +220,12 @@ extern int net_driverlevel; /** \name message statistics */ -//@{ +///@{ extern int messagesSent; extern int messagesReceived; extern int unreliableMessagesSent; extern int unreliableMessagesReceived; -//@} +///@} /** Create and initialize a new qsocket. @@ -386,12 +386,12 @@ extern struct cvar_s *hostname; extern QFile *vcrFile; -//@} +///@} /** \defgroup nq-ld NetQuake lan drivers. \ingroup nq-net */ -//@{ +///@{ typedef struct { const char *name; @@ -419,12 +419,12 @@ typedef struct { extern int net_numlandrivers; extern net_landriver_t net_landrivers[MAX_NET_DRIVERS]; -//@} +///@} /** \defgroup nq-nd NetQuake network drivers. \ingroup nq-net */ -//@{ +///@{ typedef struct { const char *name; @@ -447,6 +447,6 @@ typedef struct { extern int net_numdrivers; extern net_driver_t net_drivers[MAX_NET_DRIVERS]; -//@} +///@} #endif // __net_h diff --git a/include/snd_internal.h b/include/snd_internal.h index 0b1e87a21..ca4dc76c6 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -35,7 +35,7 @@ /** \defgroup sound_render Sound rendering sub-system. \ingroup sound */ -//@{ +///@{ #include "QF/plugin/general.h" #include "QF/plugin/snd_render.h" @@ -234,12 +234,12 @@ extern snd_render_data_t snd_render_data; #define PAINTBUFFER_SIZE 512 extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; -//@} +///@} /** \defgroup sound_render_sfx Sound sfx \ingroup sound_render_mix */ -//@{ +///@{ /** Cache sound data. Initializes caching fields of sfx. \param sfx \param realname @@ -289,7 +289,7 @@ sfx_t *SND_LoadSound (const char *name); */ void SND_SFX_Init (void); -//@} +///@} /** \defgroup sound_render_mix_channels Sound channels \ingroup sound_render_mix @@ -302,7 +302,7 @@ void SND_SFX_Init (void); - MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels - 1
static sounds */ -//@{ +///@{ #define MAX_CHANNELS 512 //!< number of available mixing channels #define MAX_DYNAMIC_CHANNELS 128 //!< number of dynamic channels #define MAX_STATIC_CHANNELS 256 //!< number of static channels @@ -390,13 +390,13 @@ void SND_StopSound (int entnum, int entchannel); \param s name of sound to play */ void SND_LocalSound (const char *s); -//@} +///@} /** \defgroup sound_render_mix Mixer engine. \ingroup sound_render */ -//@{ +///@{ /** sound clock in samples */ extern unsigned snd_paintedtime; @@ -414,13 +414,13 @@ void SND_InitScaletable (void); \param sc sfxbuffer to set. */ void SND_SetPaint (sfxbuffer_t *sc); -//@} +///@} /** \defgroup sound_render_resample Resampling functions \ingroup sound_render */ -//@{ +///@{ /** Set up the various parameters that depend on the actual sample rate. \param sc buffer to setup \param streamed non-zero if this is for a stream. @@ -448,13 +448,13 @@ void SND_Resample (sfxbuffer_t *sc, float *data, int length); */ void SND_Convert (byte *idata, float *fdata, int frames, int channels, int width); -//@} +///@} /** \defgroup sound_render_load Sound loading functions \ingroup sound_render */ -//@{ +///@{ /** Load the referenced sound. \param sfx sound reference \return 0 if ok, -1 on error @@ -492,12 +492,12 @@ int SND_LoadWav (QFile *file, sfx_t *sfx, char *realname); \return 0 if ok, -1 on error */ int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname); -//@} +///@} /** \defgroup sound_render_cache_stream Cache/Stream Functions. \ingroup sound_render */ -//@{ +///@{ /** Retrieve wavinfo from a cached sound. \param sfx sound reference \return pointer to sound's wavinfo @@ -579,6 +579,6 @@ void SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos); */ sfxbuffer_t *SND_GetCache (long samples, int rate, int channels, sfxblock_t *block, cache_allocator_t allocator); -//@} +///@} #endif//__snd_internal_h diff --git a/libs/models/winding.c b/libs/models/winding.c index d065224f7..62ae9fcb8 100644 --- a/libs/models/winding.c +++ b/libs/models/winding.c @@ -40,10 +40,6 @@ #define BOGUS (18000.0) -/** \addtogroup qfbsp_winding -*/ -//@{ - int c_activewindings, c_peakwindings; winding_t * @@ -326,5 +322,3 @@ FreeWinding (winding_t *w) c_activewindings--; free (w); } - -//@} diff --git a/qtv/include/connection.h b/qtv/include/connection.h index d02e4b971..18bbbc277 100644 --- a/qtv/include/connection.h +++ b/qtv/include/connection.h @@ -36,7 +36,7 @@ /** \defgroup qtv_connection Connection Management \ingroup qtv */ -//@{ +///@{ typedef struct connection_s { netadr_t address; ///< Address of the remote end. @@ -77,6 +77,6 @@ void Connection_Del (connection_t *con); */ connection_t *Connection_Find (netadr_t *address); -//@} +///@} #endif//__connection_h diff --git a/qtv/include/qtv.h b/qtv/include/qtv.h index 57947af16..732febfb3 100644 --- a/qtv/include/qtv.h +++ b/qtv/include/qtv.h @@ -40,7 +40,7 @@ /** \defgroup qtv_general General Functions \ingroup qtv */ -//@{ +///@{ #define PORT_QTV 27501 ///< Default port to listen for connecting clients. @@ -91,6 +91,6 @@ void qtv_end_redirect (void); void qtv_sbar_init (void); -//@} +///@} #endif//__qtv_h diff --git a/ruamoko/include/gui/Group.h b/ruamoko/include/gui/Group.h index b9ea99386..f20cca09c 100644 --- a/ruamoko/include/gui/Group.h +++ b/ruamoko/include/gui/Group.h @@ -4,7 +4,7 @@ #include "View.h" /** \addtogroup gui */ -//@{ +///@{ @class Array; @@ -41,6 +41,6 @@ - (id) addViews: (Array*)viewlist; @end -//@} +///@} #endif//__ruamoko_gui_Group_h diff --git a/ruamoko/include/gui/InputLine.h b/ruamoko/include/gui/InputLine.h index 692562a08..363cc0b8c 100644 --- a/ruamoko/include/gui/InputLine.h +++ b/ruamoko/include/gui/InputLine.h @@ -8,7 +8,7 @@ Interface functions to the engine implementation. */ -//@{ +///@{ /** Opaque handle to an inputline. @@ -118,10 +118,10 @@ typedef void (il_enterfunc)(string, void*); \return The current text of the intputline. */ @extern string InputLine_GetText (inputline_t il); -//@} +///@} /** \addtogroup gui */ -//@{ +///@{ /** Class representation of the low-level inputline objects. */ @@ -252,6 +252,6 @@ typedef void (il_enterfunc)(string, void*); - (string) text; @end -//@} +///@} #endif //__ruamoko_gui_InputLine_h diff --git a/ruamoko/include/gui/Pic.h b/ruamoko/include/gui/Pic.h index f19e8b6e4..9ed9e3380 100644 --- a/ruamoko/include/gui/Pic.h +++ b/ruamoko/include/gui/Pic.h @@ -4,7 +4,7 @@ #include "gui/View.h" /** \addtogroup gui */ -//@{ +///@{ @interface Pic : View { @@ -18,6 +18,6 @@ -(void)draw; @end -//@} +///@} #endif//__ruamoko_gui_Pic_h diff --git a/ruamoko/include/gui/Point.h b/ruamoko/include/gui/Point.h index 4ac36391a..9de4d7f5e 100644 --- a/ruamoko/include/gui/Point.h +++ b/ruamoko/include/gui/Point.h @@ -2,7 +2,7 @@ #define __ruamoko_gui_Point_h /** \addtogroup gui */ -//@{ +///@{ struct Point { int x; @@ -15,6 +15,6 @@ typedef struct Point Point; @extern Point addPoint (Point a, Point b); @extern Point subtractPoint (Point a, Point b); -//@} +///@} #endif //__ruamoko_gui_Point_h diff --git a/ruamoko/include/gui/Rect.h b/ruamoko/include/gui/Rect.h index 145815d66..005ce4a70 100644 --- a/ruamoko/include/gui/Rect.h +++ b/ruamoko/include/gui/Rect.h @@ -5,7 +5,7 @@ #include "gui/Size.h" /** \addtogroup gui */ -//@{ +///@{ struct Rect { Point origin; @@ -30,6 +30,6 @@ typedef struct Rect Rect; - (Rect) offsetBySize: (Size)aSize; #endif -//@} +///@} #endif //__ruamoko_gui_Rect_h diff --git a/ruamoko/include/gui/Size.h b/ruamoko/include/gui/Size.h index 0f6b387a3..dd48c6259 100644 --- a/ruamoko/include/gui/Size.h +++ b/ruamoko/include/gui/Size.h @@ -2,7 +2,7 @@ #define __ruamoko_gui_Size_h /** \addtogroup gui */ -//@{ +///@{ struct Size { int width; @@ -15,6 +15,6 @@ typedef struct Size Size; @extern Size addSize (Size a, Size b); @extern Size subtractSize (Size a, Size b); -//@} +///@} #endif //__ruamoko_gui_Size_h diff --git a/ruamoko/include/gui/Slider.h b/ruamoko/include/gui/Slider.h index 13a68f492..66710d28e 100644 --- a/ruamoko/include/gui/Slider.h +++ b/ruamoko/include/gui/Slider.h @@ -4,7 +4,7 @@ #include "View.h" /** \addtogroup gui */ -//@{ +///@{ @interface Slider: View { @@ -19,6 +19,6 @@ @end -//@} +///@} #endif //__ruamoko_gui_Slider_h diff --git a/ruamoko/include/gui/Text.h b/ruamoko/include/gui/Text.h index d9c6a1311..d5654d555 100644 --- a/ruamoko/include/gui/Text.h +++ b/ruamoko/include/gui/Text.h @@ -4,7 +4,7 @@ #include "View.h" /** \addtogroup gui */ -//@{ +///@{ @interface Text: View { @@ -18,6 +18,6 @@ - (void) draw; @end -//@} +///@} #endif //__ruamoko_gui_Text_h diff --git a/ruamoko/include/gui/View.h b/ruamoko/include/gui/View.h index a84f05e06..c2a99e036 100644 --- a/ruamoko/include/gui/View.h +++ b/ruamoko/include/gui/View.h @@ -8,7 +8,7 @@ */ /** \addtogroup gui */ -//@{ +///@{ /** The View class. */ @@ -34,6 +34,6 @@ - (int) keyEvent:(int)key unicode:(int)unicode down:(int)down; @end -//@} +///@} #endif //__ruamoko_gui_View_h diff --git a/tools/qfbsp/include/brush.h b/tools/qfbsp/include/brush.h index f51beab00..345b14747 100644 --- a/tools/qfbsp/include/brush.h +++ b/tools/qfbsp/include/brush.h @@ -30,7 +30,7 @@ /** \defgroup qfbsp_brush Brush Functions \ingroup qfbsp */ -//@{ +///@{ #define NUM_HULLS 2 // normal and +16 @@ -95,6 +95,6 @@ int NormalizePlane (plane_t *dp); */ int FindPlane (const plane_t *dplane, int *side); -//@} +///@} #endif//qfbsp_brush_h diff --git a/tools/qfbsp/include/bsp5.h b/tools/qfbsp/include/bsp5.h index 4cacb23ae..b949cf77c 100644 --- a/tools/qfbsp/include/bsp5.h +++ b/tools/qfbsp/include/bsp5.h @@ -32,7 +32,7 @@ /** \defgroup qfbsp_general General functions \ingroup qfbsp */ -//@{ +///@{ #define MAX_THREADS 4 @@ -129,6 +129,6 @@ node_t *AllocNode (void); extern bsp_t *bsp; -//@} +///@} #endif//qfbsp_bsp5_h diff --git a/tools/qfbsp/include/csg4.h b/tools/qfbsp/include/csg4.h index dd48047f4..e6ff8b4a3 100644 --- a/tools/qfbsp/include/csg4.h +++ b/tools/qfbsp/include/csg4.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_csg4 CSG Functions \ingroup qfbsp */ -//@{ +///@{ struct plane_s; struct visfacet_s; @@ -84,6 +84,6 @@ struct surface_s *CSGFaces (struct brushset_s *bs); void SplitFace (struct visfacet_s *in, struct plane_s *split, struct visfacet_s **front, struct visfacet_s **back); -//@} +///@} #endif//qfbsp_csg4_h diff --git a/tools/qfbsp/include/draw.h b/tools/qfbsp/include/draw.h index ecaa3fd53..740fa9050 100644 --- a/tools/qfbsp/include/draw.h +++ b/tools/qfbsp/include/draw.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_draw Debug Drawing Functions \ingroup qfbsp */ -//@{ +///@{ struct visfacet_s; struct portal_s; @@ -53,6 +53,6 @@ void DrawBrush (const struct brush_s *b); void DrawWinding (const struct winding_s *w); void DrawTri (const vec3_t p1, const vec3_t p2, const vec3_t p3); -//@} +///@} #endif//qfbsp_draw_h diff --git a/tools/qfbsp/include/map.h b/tools/qfbsp/include/map.h index e531fad8a..25c56d4ef 100644 --- a/tools/qfbsp/include/map.h +++ b/tools/qfbsp/include/map.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_map Map Parser \ingroup qfbsp */ -//@{ +///@{ #define MAX_FACES 256 typedef struct mface_s { @@ -120,6 +120,6 @@ void GetVectorForKey (const entity_t *ent, const char *key, vec3_t vec); */ void WriteEntitiesToString (void); -//@} +///@} #endif//qfbsp_map_h diff --git a/tools/qfbsp/include/merge.h b/tools/qfbsp/include/merge.h index 81e8b2c1c..c65ee15ff 100644 --- a/tools/qfbsp/include/merge.h +++ b/tools/qfbsp/include/merge.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_merge Merge Functions \ingroup qfbsp */ -//@{ +///@{ /** Add a face to the list of faces, doing any possible merging. @@ -63,6 +63,6 @@ void MergePlaneFaces (surface_t *plane); */ void MergeAll (surface_t *surfhead); -//@} +///@} #endif//qfbsp_merge_h diff --git a/tools/qfbsp/include/options.h b/tools/qfbsp/include/options.h index 4b062f27e..47a8e0df7 100644 --- a/tools/qfbsp/include/options.h +++ b/tools/qfbsp/include/options.h @@ -33,7 +33,7 @@ /** \defgroup qfbsp_options Command-line Options Parsing \ingroup qfbsp */ -//@{ +///@{ typedef struct { int verbosity; // 0=silent @@ -65,6 +65,6 @@ extern options_t options; int DecodeArgs (int argc, char **argv); extern const char *this_program; -//@} +///@} #endif//qfbsp_options_h diff --git a/tools/qfbsp/include/outside.h b/tools/qfbsp/include/outside.h index 8ad85fe49..e45e11496 100644 --- a/tools/qfbsp/include/outside.h +++ b/tools/qfbsp/include/outside.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_outside Outside Functions \ingroup qfbsp */ -//@{ +///@{ struct node_s; @@ -41,6 +41,6 @@ struct node_s; */ qboolean FillOutside (struct node_s *node); -//@} +///@} #endif//qfbsp_outside_h diff --git a/tools/qfbsp/include/portals.h b/tools/qfbsp/include/portals.h index 381bbf0f9..6d5da460e 100644 --- a/tools/qfbsp/include/portals.h +++ b/tools/qfbsp/include/portals.h @@ -31,7 +31,7 @@ Decision nodes will not have portals on them, though as part of the portal building process, they will temporarily have portals. */ -//@{ +///@{ struct node_s; @@ -89,6 +89,6 @@ void FreeAllPortals (struct node_s *node); */ void WritePortalfile (struct node_s *headnode); -//@} +///@} #endif//qfbsp_portals_h diff --git a/tools/qfbsp/include/readbsp.h b/tools/qfbsp/include/readbsp.h index 17f1b2890..5887a68ea 100644 --- a/tools/qfbsp/include/readbsp.h +++ b/tools/qfbsp/include/readbsp.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_readbsp BSP Reading Functions \ingroup qfbsp */ -//@{ +///@{ /** Load the bspfile into memory. */ @@ -47,6 +47,6 @@ void extract_entities (void); */ void extract_hull (void); -//@} +///@} #endif//qfbsp_readbsp_h diff --git a/tools/qfbsp/include/region.h b/tools/qfbsp/include/region.h index ce30e71f7..2a17734c5 100644 --- a/tools/qfbsp/include/region.h +++ b/tools/qfbsp/include/region.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_region Region Functions \ingroup qfbsp */ -//@{ +///@{ struct node_s; @@ -35,6 +35,6 @@ struct node_s; */ void GrowNodeRegions (struct node_s *headnode); -//@} +///@} #endif//qfbsp_region_h diff --git a/tools/qfbsp/include/solidbsp.h b/tools/qfbsp/include/solidbsp.h index 18bd306a6..5a3d7fbe4 100644 --- a/tools/qfbsp/include/solidbsp.h +++ b/tools/qfbsp/include/solidbsp.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_solidbsp BSP Creation Functions \ingroup qfbsp */ -//@{ +///@{ struct visfacet_s; struct plane_s; @@ -48,6 +48,6 @@ void CalcSurfaceInfo (struct surface_s *surf); */ struct node_s *SolidBSP (struct surface_s *surfhead, qboolean midsplit); -//@} +///@} #endif//qfbsp_solidbsp_h diff --git a/tools/qfbsp/include/surfaces.h b/tools/qfbsp/include/surfaces.h index ebb8314cc..561d21048 100644 --- a/tools/qfbsp/include/surfaces.h +++ b/tools/qfbsp/include/surfaces.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_surface Surface Functions \ingroup qfbsp */ -//@{ +///@{ struct visfacet_s; struct node_s; @@ -104,6 +104,6 @@ struct surface_s *GatherNodeFaces (struct node_s *headnode); */ void MakeFaceEdges (struct node_s *headnode); -//@} +///@} #endif//surfaces_h diff --git a/tools/qfbsp/include/tjunc.h b/tools/qfbsp/include/tjunc.h index 46fa939fc..3557e4df7 100644 --- a/tools/qfbsp/include/tjunc.h +++ b/tools/qfbsp/include/tjunc.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_tjunc T-Junction Repair \ingroup qfbsp */ -//@{ +///@{ struct node_s; @@ -35,6 +35,6 @@ struct node_s; */ void tjunc (struct node_s *headnode); -//@} +///@} #endif//qfbsp_tjunc_h diff --git a/tools/qfbsp/include/writebsp.h b/tools/qfbsp/include/writebsp.h index 6d2a5cf0f..759220904 100644 --- a/tools/qfbsp/include/writebsp.h +++ b/tools/qfbsp/include/writebsp.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_writebsp BSP Writing Functions \ingroup qfbsp */ -//@{ +///@{ struct node_s; @@ -78,6 +78,6 @@ void BeginBSPFile (void); */ void FinishBSPFile (void); -//@} +///@} #endif//qfbsp_writebsp_h diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index c0d07c4b3..c83c029f6 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -33,7 +33,7 @@ /** \defgroup qfcc_dags DAG building \ingroup qfcc */ -//@{ +///@{ #include "QF/pr_comp.h" @@ -110,6 +110,6 @@ dag_t *dag_create (struct flownode_s *flownode); void dag_remove_dead_nodes (dag_t *dag); void dag_generate (dag_t *dag, sblock_t *block); -//@} +///@} #endif//dags_h diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 68b946fab..df0104178 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -37,7 +37,7 @@ /** \defgroup qfcc_def Def handling \ingroup qfcc */ -//@{ +///@{ struct symbol_s; struct expr_s; @@ -180,7 +180,7 @@ void free_def (def_t *def); Temporary defs are bound to the current function (::current_func must be valid). They are always allocated from the funciont's local defspace. */ -//@{ +///@{ /** Get a temporary def. If the current function has a free temp def of the same size as \a size, @@ -207,7 +207,7 @@ def_t *temp_def (struct type_s *type); \param temp The temp def to be recycled. */ void free_temp_def (def_t *temp); -//@} +///@} /** Initialize a vm def from a qfcc def. @@ -306,6 +306,6 @@ int def_size (def_t *def) __attribute__((pure)); */ int def_visit_all (def_t *def, int overlap, int (*visit) (def_t *, void *), void *data); -//@} +///@} #endif//__def_h diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index 8e7f034d6..bd4b68920 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -37,7 +37,7 @@ /** \defgroup qfcc_defspace Defspace handling \ingroup qfcc */ -//@{ +///@{ typedef enum { ds_backed, ///< data space is globally addressable (near/far/type) and @@ -145,6 +145,6 @@ void defspace_free_loc (defspace_t *space, int ofs, int size); */ int defspace_add_data (defspace_t *space, pr_type_t *data, int size); -//@} +///@} #endif//__defspace_h diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index bd32711f8..3a19c9722 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -36,7 +36,7 @@ /** \defgroup qfcc_diagnostic Diagnostic Messages \ingroup qfcc */ -//@{ +///@{ typedef void (*diagnostic_hook)(const char *message); extern diagnostic_hook bug_hook; @@ -73,6 +73,6 @@ void _bug (struct expr_s *e, const char *file, int line, const char *fmt, ...) __attribute__ ((format (printf, 4, 5))); #define bug(e, fmt...) _bug(e, __FILE__, __LINE__, fmt) -//@} +///@} #endif//__diagnostic_h diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5109b364e..d83610b7f 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -36,7 +36,7 @@ /** \defgroup qfcc_expr Expressions \ingroup qfcc */ -//@{ +///@{ /** Type of the exression node in an expression tree. */ @@ -652,6 +652,6 @@ expr_t *sizeof_expr (expr_t *expr, struct type_s *type); expr_t *fold_constants (expr_t *e); -//@} +///@} #endif//__expr_h diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index 591704a01..b4cc48cf5 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -33,7 +33,7 @@ /** \defgroup qfcc_flow Flow graph analysis \ingroup qfcc */ -//@{ +///@{ struct function_s; struct sblock_s; @@ -120,6 +120,6 @@ void dump_dot_flow_live (void *g, const char *filename); void dump_dot_flow_reaching (void *g, const char *filename); void dump_dot_flow_statements (void *g, const char *filename); -//@} +///@} #endif//flow_h diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index d145fc53e..88ea05dc8 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -34,7 +34,7 @@ /** \defgroup qfcc_function Internal function structures. \ingroup qfcc */ -//@{ +///@{ #include "QF/pr_comp.h" #include "QF/pr_debug.h" @@ -147,6 +147,6 @@ void emit_function (function_t *f, struct expr_s *e); int function_parms (function_t *f, byte *parm_size); void clear_functions (void); -//@} +///@} #endif//__function_h diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 1fe1d3690..0e6096028 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -34,7 +34,7 @@ /** \defgroup qfcc_qfo Object file functions \ingroup qfcc */ -//@{ +///@{ #include "QF/pr_comp.h" #include "QF/pr_debug.h" @@ -106,12 +106,12 @@ typedef struct qfo_def_s { string_t file; ///< source file name pr_uint_t line; ///< source line number } qfo_def_t; -//@} +///@} /** \defgroup qfcc_qfo_QFOD QFOD flags \ingroup qfcc_qfo */ -//@{ +///@{ /** The def has been initialized. @@ -168,11 +168,11 @@ typedef struct qfo_def_s { \hideinitializer */ #define QFOD_PARAM (1u<<8) -//@} +///@} /** \addtogroup qfcc_qfo */ -//@{ +///@{ /** Representation of a function in the object file. */ @@ -286,13 +286,13 @@ enum { qfo_num_spaces }; -//@} +///@} /** \defgroup qfcc_qfo_data_access QFO Data Acess \ingroup qfcc_qfo Macros for accessing data in the QFO address space */ -//@{ +///@{ /** \internal \param q pointer to ::qfo_t struct @@ -361,7 +361,6 @@ enum { \param q pointer to ::qfo_t struct \param s space index - \param s offset into object file string space \return (char *) \hideinitializer @@ -439,11 +438,11 @@ enum { */ #define QFO_STRUCT(q, s, t, o) (*QFO_POINTER (q, s, t, o)) -//@} +///@} /** \addtogroup qfcc_qfo */ -//@{ +///@{ struct pr_info_s; @@ -485,6 +484,6 @@ qfo_t *qfo_new (void); */ void qfo_delete (qfo_t *qfo); -//@} +///@} #endif//__obj_file_h diff --git a/tools/qfcc/include/obj_type.h b/tools/qfcc/include/obj_type.h index d9c677641..13ce701e4 100644 --- a/tools/qfcc/include/obj_type.h +++ b/tools/qfcc/include/obj_type.h @@ -38,6 +38,4 @@ struct type_s; struct def_s *qfo_encode_type (struct type_s *type); -//@} - #endif//__obj_type_h diff --git a/tools/qfcc/include/pragma.h b/tools/qfcc/include/pragma.h index 1f6726f28..5f660ac23 100644 --- a/tools/qfcc/include/pragma.h +++ b/tools/qfcc/include/pragma.h @@ -33,10 +33,10 @@ /** \defgroup qfcc_pragma pragma handling \ingroup qfcc */ -//@{ +///@{ void pragma (const char *id); -//@} +///@} #endif//pragma_h diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 0bec07d37..1a1793b34 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -39,7 +39,7 @@ /** \defgroup qfcc_general General functions \ingroup qfcc */ -//@{ +///@{ typedef struct srcline_s srcline_t; struct srcline_s { @@ -132,6 +132,6 @@ char *fix_backslash (char *path); */ #define RUP(x,a) (((x) + ((a) - 1)) & ~((a) - 1)) -//@} +///@} #endif//__qfcc_h diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index f338077eb..c0c064f3e 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -39,7 +39,7 @@ enum storage_class_e; /** \defgroup qfcc_symtab Symbol Table Management \ingroup qfcc */ -//@{ +///@{ typedef enum vis_e { vis_public, @@ -235,6 +235,6 @@ symtab_t *symtab_flat_copy (symtab_t *symtab, symtab_t *parent); symbol_t *make_symbol (const char *name, struct type_s *type, struct defspace_s *space, enum storage_class_e storage); -//@} +///@} #endif//__symtab_h diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index 11bee26e6..883af01e0 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -34,7 +34,7 @@ /** \defgroup qfcc_value Constant values. \ingroup qfcc_expr */ -//@{ +///@{ struct ex_value_s; struct type_s; @@ -63,6 +63,6 @@ int ReuseString (const char *str); void clear_immediates (void); -//@} +///@} #endif//__value_h diff --git a/tools/qflight/include/entities.h b/tools/qflight/include/entities.h index 82bf378cc..6f3d1dd12 100644 --- a/tools/qflight/include/entities.h +++ b/tools/qflight/include/entities.h @@ -34,7 +34,7 @@ /** \defgroup qflight_entities Light entity data. \ingroup qflight */ -//@{ +///@{ #define DEFAULTLIGHTLEVEL 300 #define DEFAULTFALLOFF 1.0f @@ -106,6 +106,6 @@ void GetVectorForKey (entity_t *ent, const char *key, vec3_t vec); void LoadEntities (void); void WriteEntitiesToString (void); -//@} +///@} #endif// __entities_h diff --git a/tools/qflight/include/light.h b/tools/qflight/include/light.h index e06a9157a..350b7e442 100644 --- a/tools/qflight/include/light.h +++ b/tools/qflight/include/light.h @@ -37,7 +37,7 @@ /** \defgroup qflight_general General functions \ingroup qflight */ -//@{ +///@{ #define ON_EPSILON 0.1 #define MAXLIGHTS 1024 @@ -130,6 +130,6 @@ extern int num_novislights; const char *get_tex_name (int texindex) __attribute__((pure)); -//@} +///@} #endif// __light_h diff --git a/tools/qflight/include/noise.h b/tools/qflight/include/noise.h index 30625ae13..be63d9de1 100644 --- a/tools/qflight/include/noise.h +++ b/tools/qflight/include/noise.h @@ -31,7 +31,7 @@ /** \defgroup qflight_noise Light noise functions. \ingroup qflight */ -//@{ +///@{ float noise3d (vec3_t v, int num) __attribute__((pure)); float noiseXYZ (float x, float y, float z, int num) __attribute__((pure)); @@ -39,4 +39,4 @@ float noise_scaled (vec3_t v, float s, int num) __attribute__((pure)); float noise_perlin (vec3_t v, float p, int num) __attribute__((pure)); void snap_vector (vec3_t v_old, vec3_t v_new, float scale); -//@} +///@} diff --git a/tools/qflight/include/options.h b/tools/qflight/include/options.h index a90592519..32c6d6755 100644 --- a/tools/qflight/include/options.h +++ b/tools/qflight/include/options.h @@ -33,7 +33,7 @@ /** \defgroup qflight_options Light command line options. \ingroup qflight */ -//@{ +///@{ typedef struct { int verbosity; // 0=silent @@ -59,6 +59,6 @@ extern const char *this_program; int DecodeArgs (int argc, char **argv); void usage (int status) __attribute__((noreturn)); -//@} +///@} #endif//__options_h diff --git a/tools/qflight/include/properties.h b/tools/qflight/include/properties.h index a6b724d19..d5e73db7f 100644 --- a/tools/qflight/include/properties.h +++ b/tools/qflight/include/properties.h @@ -33,7 +33,7 @@ /** \defgroup qflight_properties Lighting properties \ingroup qflight */ -//@{ +///@{ struct plitem_s; @@ -199,6 +199,6 @@ void set_properties (entity_t *ent, struct plitem_s *dict); */ void LoadProperties (const char *filename); -//@} +///@} #endif//__properties_h diff --git a/tools/qflight/include/threads.h b/tools/qflight/include/threads.h index 30b9cc59f..0fd5c00af 100644 --- a/tools/qflight/include/threads.h +++ b/tools/qflight/include/threads.h @@ -32,7 +32,7 @@ /** \defgroup qflight_threads Light thread handling. \ingroup qflight */ -//@{ +///@{ #if defined (HAVE_PTHREAD_H) && defined (HAVE_PTHREAD) @@ -66,6 +66,6 @@ typedef void *(threadfunc_t) (void *); void InitThreads (void); void RunThreadsOn (threadfunc_t func); -//@} +///@} #endif// __threads_h From 9248e8cf014f69341fd55a4fea5f8933a24af0ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Feb 2020 15:20:49 +0900 Subject: [PATCH 0247/3664] Update for doxygen 1.8.16 --- doc/quakeforge.dox.conf.in | 299 +++++++++++++++++++++-------- include/QF/alloc.h | 4 +- include/QF/cbuf.h | 4 +- include/QF/checksum.h | 4 +- include/QF/cmd.h | 4 +- include/QF/crc.h | 4 +- include/QF/cvar.h | 8 +- include/QF/draw.h | 8 +- include/QF/dstring.h | 20 +- include/QF/hash.h | 4 +- include/QF/idparse.h | 4 +- include/QF/info.h | 4 +- include/QF/keys.h | 4 +- include/QF/math/dual.h | 4 +- include/QF/math/half.h | 4 +- include/QF/math/matrix3.h | 4 +- include/QF/math/matrix4.h | 4 +- include/QF/math/quaternion.h | 4 +- include/QF/math/vector.h | 4 +- include/QF/mathlib.h | 4 +- include/QF/mdfour.h | 4 +- include/QF/msg.h | 4 +- include/QF/pak.h | 4 +- include/QF/pakfile.h | 4 +- include/QF/plugin.h | 4 +- include/QF/pr_type.h | 4 +- include/QF/progs.h | 73 +++---- include/QF/qargs.h | 4 +- include/QF/qendian.h | 4 +- include/QF/qfplist.h | 4 +- include/QF/quakefs.h | 4 +- include/QF/quakeio.h | 4 +- include/QF/script.h | 4 +- include/QF/set.h | 4 +- include/QF/sizebuf.h | 4 +- include/QF/sound.h | 12 +- include/QF/sys.h | 4 +- include/QF/va.h | 4 +- include/QF/ver_check.h | 4 +- include/QF/view.h | 4 +- include/QF/wad.h | 4 +- include/QF/wadfile.h | 4 +- include/QF/winding.h | 4 +- include/QF/zone.h | 4 +- include/net_dgrm.h | 4 +- include/net_loop.h | 4 +- include/net_udp.h | 4 +- include/net_vcr.h | 4 +- include/net_wins.h | 4 +- include/netchan.h | 12 +- include/netmain.h | 28 +-- include/snd_internal.h | 28 +-- libs/models/winding.c | 6 - qtv/include/connection.h | 4 +- qtv/include/qtv.h | 4 +- ruamoko/include/gui/Group.h | 4 +- ruamoko/include/gui/InputLine.h | 8 +- ruamoko/include/gui/Pic.h | 4 +- ruamoko/include/gui/Point.h | 4 +- ruamoko/include/gui/Rect.h | 4 +- ruamoko/include/gui/Size.h | 4 +- ruamoko/include/gui/Slider.h | 4 +- ruamoko/include/gui/Text.h | 4 +- ruamoko/include/gui/View.h | 4 +- tools/qfbsp/include/brush.h | 4 +- tools/qfbsp/include/bsp5.h | 4 +- tools/qfbsp/include/csg4.h | 4 +- tools/qfbsp/include/draw.h | 4 +- tools/qfbsp/include/map.h | 4 +- tools/qfbsp/include/merge.h | 4 +- tools/qfbsp/include/options.h | 4 +- tools/qfbsp/include/outside.h | 4 +- tools/qfbsp/include/portals.h | 4 +- tools/qfbsp/include/readbsp.h | 4 +- tools/qfbsp/include/region.h | 4 +- tools/qfbsp/include/solidbsp.h | 4 +- tools/qfbsp/include/surfaces.h | 4 +- tools/qfbsp/include/tjunc.h | 4 +- tools/qfbsp/include/writebsp.h | 4 +- tools/qfcc/include/dags.h | 4 +- tools/qfcc/include/def.h | 8 +- tools/qfcc/include/defspace.h | 4 +- tools/qfcc/include/diagnostic.h | 4 +- tools/qfcc/include/expr.h | 4 +- tools/qfcc/include/flow.h | 4 +- tools/qfcc/include/function.h | 4 +- tools/qfcc/include/obj_file.h | 21 +- tools/qfcc/include/obj_type.h | 2 - tools/qfcc/include/pragma.h | 4 +- tools/qfcc/include/qfcc.h | 4 +- tools/qfcc/include/symtab.h | 4 +- tools/qfcc/include/value.h | 4 +- tools/qflight/include/entities.h | 4 +- tools/qflight/include/light.h | 4 +- tools/qflight/include/noise.h | 4 +- tools/qflight/include/options.h | 4 +- tools/qflight/include/properties.h | 4 +- tools/qflight/include/threads.h | 4 +- 98 files changed, 496 insertions(+), 373 deletions(-) diff --git a/doc/quakeforge.dox.conf.in b/doc/quakeforge.dox.conf.in index 9db22207d..64028f578 100644 --- a/doc/quakeforge.dox.conf.in +++ b/doc/quakeforge.dox.conf.in @@ -1,4 +1,4 @@ -# Doxyfile 1.8.9.1 +# Doxyfile 1.8.16 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -17,11 +17,11 @@ # Project related configuration options #--------------------------------------------------------------------------- -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all text -# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv -# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv -# for the list of possible encodings. +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 @@ -93,6 +93,14 @@ ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. @@ -179,6 +187,16 @@ SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus @@ -226,7 +244,12 @@ TAB_SIZE = 4 # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines. +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) ALIASES = QF=QuakeForge @@ -264,17 +287,26 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: -# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: -# Fortran. In the later case the parser tries to guess whether the code is fixed -# or free formatted code, this is the default for Fortran type files), VHDL. For -# instance to make doxygen treat .inc files as Fortran files (default is PHP), -# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # @@ -285,7 +317,7 @@ EXTENSION_MAPPING = no_extension=C # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable -# documentation. See http://daringfireball.net/projects/markdown/ for details. +# documentation. See https://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. @@ -293,6 +325,15 @@ EXTENSION_MAPPING = no_extension=C MARKDOWN_SUPPORT = YES +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or @@ -318,7 +359,7 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. @@ -343,6 +384,13 @@ IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = YES + # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent @@ -417,6 +465,12 @@ EXTRACT_ALL = YES EXTRACT_PRIVATE = NO +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. @@ -437,7 +491,7 @@ EXTRACT_STATIC = @STATIC_DOC@ EXTRACT_LOCAL_CLASSES = NO -# This flag is only useful for Objective-C code. When set to YES, local methods, +# This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. @@ -495,7 +549,7 @@ INTERNAL_DOCS = NO # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. +# (including Cygwin) ands Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = NO @@ -682,7 +736,7 @@ LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool -# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. @@ -727,11 +781,18 @@ WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = NO +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated @@ -755,7 +816,7 @@ WARN_LOGFILE = # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with -# spaces. +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = @TOPSRC@/include \ @@ -770,7 +831,7 @@ INPUT = @TOPSRC@/include \ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv -# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of # possible encodings. # The default value is: UTF-8. @@ -778,12 +839,17 @@ INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank the -# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, -# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, -# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, -# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, -# *.qsf, *.as and *.js. +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.h \ @@ -889,6 +955,10 @@ IMAGE_PATH = @TOPSRC@/doc \ # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. INPUT_FILTER = @@ -898,6 +968,10 @@ INPUT_FILTER = # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. FILTER_PATTERNS = @@ -950,7 +1024,7 @@ INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented -# function all documented functions referencing it will be listed. +# entity all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO @@ -982,12 +1056,12 @@ SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system -# (see http://www.gnu.org/software/global/global.html). You will need version +# (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global -# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # @@ -1015,7 +1089,7 @@ VERBATIM_HEADERS = NO # rich C++ code for which doxygen's built-in parser lacks the necessary type # information. # Note: The availability of this option depends on whether or not doxygen was -# compiled with the --with-libclang option. +# generated with the -Duse_libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO @@ -1028,6 +1102,16 @@ CLANG_ASSISTED_PARSING = NO CLANG_OPTIONS = +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1146,7 +1230,7 @@ HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see -# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. @@ -1182,6 +1266,17 @@ HTML_COLORSTYLE_GAMMA = 100 HTML_TIMESTAMP = NO +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. @@ -1205,13 +1300,13 @@ HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development -# environment (see: http://developer.apple.com/tools/xcode/), introduced with -# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at -# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1250,7 +1345,7 @@ DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output @@ -1326,7 +1421,7 @@ QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace -# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1334,7 +1429,7 @@ QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual -# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1343,7 +1438,7 @@ QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1351,7 +1446,7 @@ QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom -# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1359,7 +1454,7 @@ QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: -# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = @@ -1452,7 +1547,7 @@ EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # @@ -1464,7 +1559,7 @@ FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see -# http://www.mathjax.org) which uses client side Javascript for the rendering +# https://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path @@ -1491,8 +1586,8 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from http://www.mathjax.org before deployment. -# The default value is: http://cdn.mathjax.org/mathjax/latest. +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest @@ -1553,7 +1648,7 @@ SERVER_BASED_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). +# Xapian (see: https://xapian.org/). # # See the section "External Indexing and Searching" for details. # The default value is: NO. @@ -1566,7 +1661,7 @@ EXTERNAL_SEARCH = NO # # Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library -# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Xapian (see: https://xapian.org/). See the section "External Indexing and # Searching" for details. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1618,21 +1713,35 @@ LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. # -# Note that when enabling USE_PDFLATEX this option is only used for generating -# bitmaps for formulas in the HTML output, but not in the Makefile that is -# written to the output directory. -# The default file is: latex. +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate # index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). # The default file is: makeindex. # This tag requires that the tag GENERATE_LATEX is set to YES. MAKEINDEX_CMD_NAME = makeindex +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = makeindex + # If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. @@ -1651,9 +1760,12 @@ COMPACT_LATEX = YES PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names -# that should be included in the LaTeX output. To get the times font for -# instance you can specify -# EXTRA_PACKAGES=times +# that should be included in the LaTeX output. The package can be specified just +# by its name or with the correct syntax as to be used with the LaTeX +# \usepackage command. To get the times font for instance you can specify : +# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} +# To use the option intlimits with the amsmath package you can specify: +# EXTRA_PACKAGES=[intlimits]{amsmath} # If left blank no extra packages will be included. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1750,12 +1862,28 @@ LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See -# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. # The default value is: plain. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BIB_STYLE = plain +# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_TIMESTAMP = NO + +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EMOJI_DIRECTORY = + #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- @@ -1795,9 +1923,9 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's config -# file, i.e. a series of assignments. You only have to provide replacements, -# missing definitions are set to their default value. +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the # default style sheet that doxygen normally uses. @@ -1806,8 +1934,8 @@ RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's config file. A template extensions file can be generated -# using doxygen -e rtf extensionFile. +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = @@ -1893,6 +2021,13 @@ XML_OUTPUT = xml XML_PROGRAMLISTING = YES +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- @@ -1925,9 +2060,9 @@ DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sf.net) file that captures the -# structure of the code including all documentation. Note that this feature is -# still experimental and incomplete at the moment. +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO @@ -2101,12 +2236,6 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of 'which perl'). -# The default file (with absolute path) is: /usr/bin/perl. - -PERL_PATH = /usr/bin/perl - #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- @@ -2120,15 +2249,6 @@ PERL_PATH = /usr/bin/perl CLASS_DIAGRAMS = YES -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see: -# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. @@ -2207,7 +2327,7 @@ COLLABORATION_GRAPH = YES # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. -GROUP_GRAPHS = NO +GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES, doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling @@ -2261,7 +2381,8 @@ INCLUDED_BY_GRAPH = YES # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. +# functions only using the \callgraph command. Disabling a call graph can be +# accomplished by means of the command \hidecallgraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2272,7 +2393,8 @@ CALL_GRAPH = NO # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. +# functions only using the \callergraph command. Disabling a caller graph can be +# accomplished by means of the command \hidecallergraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2295,13 +2417,17 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = NO # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. +# generated by dot. For an explanation of the image formats see the section +# output formats in the documentation of the dot tool (Graphviz (see: +# http://www.graphviz.org/)). # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). # Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, # png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, -# gif:cairo:gd, gif:gd, gif:gd:gd and svg. +# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo, +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2352,6 +2478,11 @@ DIAFILE_DIRS = PLANTUML_JAR_PATH = +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + # When using plantuml, the specified paths are searched for files specified by # the !include statement in a plantuml block. diff --git a/include/QF/alloc.h b/include/QF/alloc.h index 59a57bdf1..f67fe7176 100644 --- a/include/QF/alloc.h +++ b/include/QF/alloc.h @@ -37,7 +37,7 @@ /** \defgroup alloc High-tide allocator. \ingroup utils */ -//@{ +///@{ #ifndef DEBUG_QF_MEMORY /** High-tide structure allocator for use in linked lists. @@ -93,6 +93,6 @@ #define FREE(n, p) do { free (p); } while (0) #endif -//@} +///@} #endif//__QF_alloc_h diff --git a/include/QF/cbuf.h b/include/QF/cbuf.h index 9018fa6b6..29a89588e 100644 --- a/include/QF/cbuf.h +++ b/include/QF/cbuf.h @@ -34,7 +34,7 @@ /** \defgroup cbuf Command buffer management. \ingroup utils */ -//@{ +///@{ #include @@ -100,6 +100,6 @@ void Cbuf_Execute (cbuf_t *cbuf); void Cbuf_Execute_Stack (cbuf_t *cbuf); void Cbuf_Execute_Sets (cbuf_t *cbuf); -//@} +///@} #endif//__QF_cbuf_h diff --git a/include/QF/checksum.h b/include/QF/checksum.h index 9a7dfb8e6..ed6f035b1 100644 --- a/include/QF/checksum.h +++ b/include/QF/checksum.h @@ -30,7 +30,7 @@ /** \addtogroup crc */ -//@{ +///@{ #include "QF/qtypes.h" @@ -38,6 +38,6 @@ unsigned int Com_BlockChecksum (const void *buffer, int length); void Com_BlockFullChecksum (const void *buffer, int len, unsigned char *outbuf); byte COM_BlockSequenceCRCByte (const byte *base, int length, int sequence); -//@} +///@} #endif // __checksum_h diff --git a/include/QF/cmd.h b/include/QF/cmd.h index 2ac508b9f..35846a063 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -31,7 +31,7 @@ /** \defgroup cmd Command management. \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" #include "QF/cbuf.h" @@ -81,6 +81,6 @@ struct cbuf_interpreter_s *Cmd_GetProvider(const char *name); extern struct cbuf_args_s *cmd_args; extern struct cvar_s *cmd_warncmd; -//@} +///@} #endif//__QF_cmd_h diff --git a/include/QF/crc.h b/include/QF/crc.h index 2aa16b616..cc635e7b9 100644 --- a/include/QF/crc.h +++ b/include/QF/crc.h @@ -31,7 +31,7 @@ /** \defgroup crc Checksum generation. \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -41,6 +41,6 @@ void CRC_ProcessBlock (const byte *start, unsigned short *crcvalue, int count); unsigned short CRC_Value(unsigned short crcvalue) __attribute__((const)); unsigned short CRC_Block (const byte *start, int count) __attribute__((pure)); -//@} +///@} #endif // __crc_h diff --git a/include/QF/cvar.h b/include/QF/cvar.h index 091a13b61..3d81a3b1c 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -31,7 +31,7 @@ /** \defgroup cvar Configuration variables \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" #include "QF/quakeio.h" @@ -72,7 +72,7 @@ typedef struct cvar_alias_s { code goes "look, the user made fs_basepath already", uses the users value, but sets CVAR_ROM as per the call. */ -//@{ +///@{ #define CVAR_NONE 0 ///< normal cvar #define CVAR_ARCHIVE 1 ///< set to cause it to be saved to ///< config.cfg @@ -85,7 +85,7 @@ typedef struct cvar_alias_s { #define CVAR_LATCH 2048 ///< will change only when C code next does ///< a Cvar_Get(), so it can't be changed ///< (not implemented) -//@} +///@} // Returns the Cvar if found, creates it with value if not. Description and @@ -138,6 +138,6 @@ void Cvar_Init (void); extern cvar_t *cvar_vars; -//@} +///@} #endif // __cvar_h diff --git a/include/QF/draw.h b/include/QF/draw.h index d8067a4c7..529f3e892 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -37,7 +37,7 @@ /** \defgroup video_renderer_draw Generic draw functions \ingroup video_renderer */ -//@{ +///@{ #include "QF/wad.h" @@ -160,12 +160,12 @@ void Draw_FadeScreen (void); /** Shift the screen colors. */ void Draw_BlendScreen (quat_t color); -//@} +///@} /** \defgroup video_renderer_draw_qpic QPic functions \ingroup video_renderer_draw */ -//@{ +///@{ /** Load a qpic from the filesystem. \param path path of the file within the quake filesystem \param alpha transparency level of the pic. @@ -232,6 +232,6 @@ void Draw_Picf (float x, float y, qpic_t *pic); \param height vertical size of the sub-region to be drawn */ void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); -//@} +///@} #endif // _DRAW_H diff --git a/include/QF/dstring.h b/include/QF/dstring.h index 1075bc04b..638d9e340 100644 --- a/include/QF/dstring.h +++ b/include/QF/dstring.h @@ -31,7 +31,7 @@ /** \defgroup dstring Dynamic Strings \ingroup utils */ -//@{ +///@{ #include #include @@ -52,13 +52,13 @@ typedef struct dstring_s { extern dstring_mem_t dstring_default_mem; // General buffer functions -//@{ +///@{ /** Create a new dstring. size and truesize start at 0 and no string buffer is allocated. */ dstring_t *_dstring_new (dstring_mem_t *mem); dstring_t *dstring_new (void); -//@} +///@} /** Delete a dstring. Both the string buffer and dstring object are freed. */ void dstring_delete (dstring_t *dstr); @@ -103,13 +103,13 @@ void dstring_replace (dstring_t *dstr, unsigned int pos, unsigned int rlen, char *dstring_freeze (dstring_t *dstr); // String-specific functions -//@{ +///@{ /** Allocate a new dstring pre-initialized as a null terminated string. size will be 1 and the first byte 0. */ dstring_t *_dstring_newstr (dstring_mem_t *mem); dstring_t *dstring_newstr (void); -//@} +///@} /** Create a new dstring from a string. Similar to strdup(). \param str the string to copy \return inititialized dstring @@ -160,21 +160,21 @@ void dstring_insertsubstr (dstring_t *dstr, unsigned int pos, const char *str, */ void dstring_clearstr (dstring_t *dstr); -//@{ +///@{ /** Formatted printing to dstrings. Existing data is replaced by the formatted string. */ int dvsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); int dsprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); -//@} -//@{ +///@} +///@{ /** Formatted printing to dstrings. Formatted string is appened to the dstring. Embedded nulls in the dstring are ignored. */ int davsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); int dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); -//@} +///@} -//@} +///@} #endif // __dstring_h diff --git a/include/QF/hash.h b/include/QF/hash.h index 1a8a8f912..ae040cfa9 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -34,7 +34,7 @@ /** \defgroup hash Hash tables \ingroup utils */ -//@{ +///@{ typedef struct hashtab_s hashtab_t; @@ -209,6 +209,6 @@ void **Hash_GetList (hashtab_t *tab); */ void Hash_Stats (hashtab_t *tab); -//@} +///@} #endif // __hash_h diff --git a/include/QF/idparse.h b/include/QF/idparse.h index 07b5c322e..e48cf30e6 100644 --- a/include/QF/idparse.h +++ b/include/QF/idparse.h @@ -33,7 +33,7 @@ /** \addtogroup cbuf */ -//@{ +///@{ extern const char *com_token; @@ -44,6 +44,6 @@ void COM_TokenizeString (const char *str, struct cbuf_args_s *args); extern struct cbuf_interpreter_s id_interp; -//@} +///@} #endif//__QF_idparse_h diff --git a/include/QF/info.h b/include/QF/info.h index d57a221f6..4e34f6fa2 100644 --- a/include/QF/info.h +++ b/include/QF/info.h @@ -31,7 +31,7 @@ /** \defgroup info Info Keys \ingroup utils */ -//@{ +///@{ #include // for size_t. sys/types.h SHOULD be used, but can't :(bc) #include @@ -63,6 +63,6 @@ void Info_Destroy (info_t *info); char *Info_MakeString (info_t *info, int (*filter)(const char *)); void Info_AddKeys (info_t *info, info_t *keys); -//@} +///@} #endif // _INFO_H diff --git a/include/QF/keys.h b/include/QF/keys.h index ada46a265..66ef8d99e 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -39,7 +39,7 @@ /** \defgroup input_keybinding Key Binding Sub-system \ingroup input */ -//@{ +///@{ /// these are the key numbers that should be passed to Key_Event typedef enum { @@ -659,6 +659,6 @@ struct progs_s; void Key_Progs_Init (struct progs_s *pr); #endif -//@} +///@} #endif // _KEYS_H diff --git a/include/QF/math/dual.h b/include/QF/math/dual.h index eba9b8bf0..34c58a984 100644 --- a/include/QF/math/dual.h +++ b/include/QF/math/dual.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_dual Dual and dual quaternion functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -189,6 +189,6 @@ } while (0) #define DualQuatExpand(dq) QuatExpand ((dq).q0.q), QuatExpand ((dq).qe.q) -//@} +///@} #endif // __QF_math_dual_h diff --git a/include/QF/math/half.h b/include/QF/math/half.h index 1fe474cd3..bc9133fc6 100644 --- a/include/QF/math/half.h +++ b/include/QF/math/half.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_half Half-float functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -42,6 +42,6 @@ int16_t FloatToHalf (float x) __attribute__((const)); float HalfToFloat (int16_t x) __attribute__((const)); -//@} +///@} #endif // __QF_math_half_h diff --git a/include/QF/math/matrix3.h b/include/QF/math/matrix3.h index ce2474a99..dfe9b530f 100644 --- a/include/QF/math/matrix3.h +++ b/include/QF/math/matrix3.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_matrix3 3x3 matrix functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -118,6 +118,6 @@ void Mat3SymEigen (const mat3_t m, vec3_t e); */ int Mat3Decompose (const mat4_t mat, quat_t rot, vec3_t shear, vec3_t scale); -//@} +///@} #endif // __QF_math_matrix3_h diff --git a/include/QF/math/matrix4.h b/include/QF/math/matrix4.h index 4f0e0dfb5..a55c8ed94 100644 --- a/include/QF/math/matrix4.h +++ b/include/QF/math/matrix4.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_matrix4 4x4 matrix functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -130,6 +130,6 @@ void Mat4as3MultVec (const mat4_t a, const vec3_t b, vec3_t c); int Mat4Decompose (const mat4_t mat, quat_t rot, vec3_t shear, vec3_t scale, vec3_t trans); -//@} +///@} #endif // __QF_math_matrix4_h diff --git a/include/QF/math/quaternion.h b/include/QF/math/quaternion.h index 84d7b64b4..d6e34814a 100644 --- a/include/QF/math/quaternion.h +++ b/include/QF/math/quaternion.h @@ -34,7 +34,7 @@ /** \defgroup mathlib_quaternion Quaternion functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -168,6 +168,6 @@ void QuatInverse (const quat_t in, quat_t out); void QuatExp (const quat_t a, quat_t b); void QuatToMatrix (const quat_t q, vec_t *m, int homogenous, int vertical); -//@} +///@} #endif // __QF_math_quaternion_h diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 73cc1f708..6a8b80809 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -31,7 +31,7 @@ /** \defgroup mathlib_vector Vector functions \ingroup mathlib */ -//@{ +///@{ #include "QF/qtypes.h" @@ -209,6 +209,6 @@ VectorNormalize (vec3_t v) return length; } -//@} +///@} #endif // __QF_math_vector_h diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index c4575705e..5c9b854fe 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -31,7 +31,7 @@ /** \defgroup mathlib Vector and matrix functions \ingroup utils */ -//@{ +///@{ #include #include "QF/qtypes.h" @@ -218,6 +218,6 @@ int CircumSphere (const vec3_t points[], int num_points, sphere_t *sphere); void BarycentricCoords (const vec_t **points, int num_points, const vec3_t p, vec_t *lambda); -//@} +///@} #endif // __mathlib_h diff --git a/include/QF/mdfour.h b/include/QF/mdfour.h index 94fe99da0..19360e838 100644 --- a/include/QF/mdfour.h +++ b/include/QF/mdfour.h @@ -31,7 +31,7 @@ /** \addtogroup crc */ -//@{ +///@{ #include "QF/uint32.h" @@ -47,6 +47,6 @@ void mdfour_update(struct mdfour *md, const unsigned char *in, int n); //old: MD void mdfour_result(struct mdfour *md, unsigned char *out); // old: MD4Final void mdfour(unsigned char *out, const unsigned char *in, int n); -//@} +///@} #endif // __mdfour_h diff --git a/include/QF/msg.h b/include/QF/msg.h index 6e550a191..6a92e2d54 100644 --- a/include/QF/msg.h +++ b/include/QF/msg.h @@ -30,7 +30,7 @@ /** \defgroup msg Message reading and writing \ingroup utils */ -//@{ +///@{ #include "QF/sizebuf.h" @@ -249,6 +249,6 @@ void MSG_ReadAngle16V (qmsg_t *msg, vec3_t angles); */ int MSG_ReadUTF8 (qmsg_t *msg); -//@} +///@} #endif diff --git a/include/QF/pak.h b/include/QF/pak.h index f176e5733..ea86ffd14 100644 --- a/include/QF/pak.h +++ b/include/QF/pak.h @@ -33,7 +33,7 @@ /** \addtogroup pak */ -//@{ +///@{ // little-endian PACK #define IDPAKHEADER (('K'<<24)+('C'<<16)+('A'<<8)+'P') @@ -51,6 +51,6 @@ typedef struct { int dirlen; } dpackheader_t; -//@} +///@} #endif//__qf_pak_h diff --git a/include/QF/pakfile.h b/include/QF/pakfile.h index ecb6738f0..7bb4f3a0e 100644 --- a/include/QF/pakfile.h +++ b/include/QF/pakfile.h @@ -33,7 +33,7 @@ /** \defgroup pak pakfile proccessing \ingroup utils */ -//@{ +///@{ #include "QF/hash.h" #include "QF/pak.h" @@ -64,6 +64,6 @@ int pack_add (pack_t *pack, const char *filename); int pack_extract (pack_t *pack, dpackfile_t *pf); dpackfile_t *pack_find_file (pack_t *pack, const char *filename); -//@} +///@} #endif//__QF_pakfile_h diff --git a/include/QF/plugin.h b/include/QF/plugin.h index 28cb9962f..0a06f73f2 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -31,7 +31,7 @@ /** \defgroup plugin Plugins \ingroup utils */ -//@{ +///@{ #define QFPLUGIN_VERSION "1.0" @@ -111,6 +111,6 @@ void PI_Shutdown (void); // FIXME: we need a generic function to initialize unused fields -//@} +///@} #endif // __QF_plugin_h_ diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index 4cc6cf82e..0c8b37664 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -36,7 +36,7 @@ All \c pointer_t \c type fields are pointers within the type qfo_space. */ -//@{ +///@{ #include "QF/pr_comp.h" @@ -102,6 +102,6 @@ typedef struct qfot_type_encodings_s { pr_int_t size; } qfot_type_encodings_t; -//@} +///@} #endif//__pr_type_h diff --git a/include/QF/progs.h b/include/QF/progs.h index 5b834d1f0..7631f1de1 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -39,18 +39,18 @@ struct QFile_s; /** \ingroup progs */ -//@{ +///@{ typedef struct progs_s progs_t; typedef struct pr_resource_s pr_resource_t; typedef struct edict_s edict_t; -//@} +///@} //============================================================================ /** \defgroup progs_misc Miscelaneous functions \ingroup progs */ -//@{ +///@{ /** Initialize the progs engine. */ @@ -63,12 +63,12 @@ void PR_Init_Cvars (void); void PR_Error (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3), noreturn)); void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3), noreturn)); -//@} +///@} /** \defgroup progs_execution Execution \ingroup progs */ -//@{ +///@{ /** Ensure P_* macros point to the right place for passing parameters to progs functions. @@ -128,12 +128,12 @@ void PR_ExecuteProgram (progs_t *pr, func_t fnum); */ int PR_CallFunction (progs_t *pr, func_t fnum); -//@} +///@} /** \defgroup progs_load Loading \ingroup progs */ -//@{ +///@{ /** Type of functions that are called at progs load. \param pr pointer to ::progs_t VM struct @@ -204,12 +204,12 @@ int PR_Check_Opcodes (progs_t *pr); void PR_BoundsCheckSize (progs_t *pr, pointer_t addr, unsigned size); void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); -//@} +///@} /** \defgroup progs_edict Edict management \ingroup progs */ -//@{ +///@{ struct edict_s { qboolean free; @@ -261,13 +261,13 @@ void ED_EntityParseFunction (progs_t *pr); # define NUM_FOR_EDICT(p,e) ED_NumForEdict (p, e) #endif -//@} +///@} /** \defgroup pr_symbols Symbol Management \ingroup progs Lookup functions for symbol name resolution. */ -//@{ +///@{ ddef_t *PR_FieldAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure)); ddef_t *PR_GlobalAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure)); @@ -282,7 +282,7 @@ int PR_AccessField (progs_t *pr, const char *name, etype_t type, const char *file, int line); void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute__((noreturn)); -//@} +///@} //============================================================================ @@ -296,7 +296,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ Typed global access macros. No checking is done against the QC type, but the appropriate C type will be used. */ -//@{ +///@{ /** \internal \param p pointer to ::progs_t VM struct @@ -479,14 +479,14 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ #define G_STRUCT(p,t,o) (*(t *)G_GPOINTER (p, o)) -//@} +///@} /** \defgroup prda_parameters Parameters \ingroup progs_data_access Typed parameter access macros. No checking is done against the QC type, but the appropriate C type will be used. */ -//@{ +///@{ /** \internal \param p pointer to ::progs_t VM struct @@ -669,7 +669,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ #define P_STRUCT(p,t,n) (*(t *)P_GPOINTER (p, n)) -//@} +///@} /** \defgroup prda_return Return Values \ingroup progs_data_access @@ -680,7 +680,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ ask for an \c int from a function that returned a \c float, you're asking for trouble. */ -//@{ +///@{ /** \internal \param p pointer to ::progs_t VM struct @@ -836,14 +836,14 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ #define RETURN_QUAT(p,q) VectorCopy (q, R_QUAT (p)) -//@} +///@} /** \defgroup prda_entity_fields Entity Fields \ingroup progs_data_access Typed entity field access macros. No checking is done against the QC type, but the appropriate C type will be used. */ -//@{ +///@{ /** \internal \param e pointer to the entity @@ -980,7 +980,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ #define E_DSTRING(p,e,o) (PR_GetMutableString (p, E_STRING (e, o))) -//@} +///@} /** \defgroup pr_builtins VM Builtin functions \ingroup progs @@ -993,7 +993,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ 0x8000000 to 0xffffffff is unavailable due to the builtin number being a negative statement address. */ -//@{ +///@{ #define PR_RANGE_SHIFT 16 #define PR_RANGE_MASK 0xffff0000 @@ -1067,7 +1067,7 @@ builtin_t *PR_FindBuiltinNum (progs_t *pr, pr_int_t num); */ int PR_RelocateBuiltins (progs_t *pr); -//@} +///@} /** \defgroup pr_strings String Management \ingroup progs @@ -1093,7 +1093,7 @@ int PR_RelocateBuiltins (progs_t *pr); They can be created, altered, and destroyed at any time by the main program (or the progs code via an appropriate builtin function). */ -//@{ +///@{ /** Initialize the string tables using the strings supplied by the progs. Called automatically during progs load. @@ -1254,13 +1254,13 @@ void PR_FreeTempStrings (progs_t *pr); void PR_Sprintf (progs_t *pr, struct dstring_s *result, const char *name, const char *format, int count, pr_type_t **args); -//@} +///@} /** \defgroup pr_resources Resource Management \ingroup progs Builtin module private data management. */ -//@{ +///@{ /** Initialize the resource management fields. @@ -1314,7 +1314,7 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \note \p map is the resource map itself, not a pointer to the resource map. */ -//@{ +///@{ /** Type delcaration for the resource map. @@ -1416,29 +1416,30 @@ void *PR_Resources_Find (progs_t *pr, const char *name); return ~(i * 1024 + d); \ } \ return 0 -//@} +///@} -//@} +///@} /** \defgroup pr_zone VM memory management. \ingroup progs Used to allocate and free memory in the VM address space. */ -//@{ +///@{ void PR_Zone_Init (progs_t *pr); void PR_Zone_Free (progs_t *pr, void *ptr); void *PR_Zone_Malloc (progs_t *pr, pr_int_t size); void *PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size); -//@} +///@} /** \defgroup debug VM Debugging \ingroup progs Progs debugging support. */ -//@{ +/// \addtogroup debug +///@{ void PR_Debug_Init (void); void PR_Debug_Init_Cvars (void); @@ -1464,20 +1465,20 @@ extern struct cvar_s *pr_deadbeef_locals; extern struct cvar_s *pr_boundscheck; extern struct cvar_s *pr_faultchecks; -//@} +///@} /** \defgroup pr_cmds Quake and Quakeworld common builtins \ingroup progs \todo This really doesn't belong in progs. */ -//@{ +///@{ char *PF_VarString (progs_t *pr, int first); void PR_Cmds_Init (progs_t *pr); extern const char *pr_gametype; -//@} +///@} //============================================================================ @@ -1682,7 +1683,7 @@ struct progs_s { /** \addtogroup progs_data_access */ -//@{ +///@{ /** Convert a progs offset/pointer to a C pointer. \param pr pointer to ::progs_t VM struct @@ -1706,7 +1707,7 @@ PR_SetPointer (progs_t *pr, void *p) return p ? (pr_type_t *) p - pr->pr_globals : 0; } -//@} +///@} /** \example vm-exec.c */ diff --git a/include/QF/qargs.h b/include/QF/qargs.h index fe4eb98f8..50dfbd35a 100644 --- a/include/QF/qargs.h +++ b/include/QF/qargs.h @@ -32,7 +32,7 @@ /** \addtogroup misc */ -//@{ +///@{ #include "QF/qtypes.h" @@ -50,6 +50,6 @@ void COM_Init_Cvars (void); void COM_InitArgv (int argc, const char **argv); void COM_ParseConfig (void); -//@} +///@} #endif // __qargs_h diff --git a/include/QF/qendian.h b/include/QF/qendian.h index d63ca2d0c..a42bd749f 100644 --- a/include/QF/qendian.h +++ b/include/QF/qendian.h @@ -33,7 +33,7 @@ /** \defgroup qendian Endian handling functions \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -118,6 +118,6 @@ byte ReadByte (struct QFile_s *file); unsigned short ReadShort (struct QFile_s *file); unsigned int ReadLong (struct QFile_s *file); -//@} +///@} #endif // __qendian_h diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 6c5d61202..e0c2557ca 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -31,7 +31,7 @@ /** \defgroup qfplist Property lists \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" @@ -226,6 +226,6 @@ plitem_t *PL_NewString (const char *str); */ void PL_Free (plitem_t *item); -//@} +///@} #endif // __QF_qfplist_h_ diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index 336537495..364718db0 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -33,7 +33,7 @@ /** \defgroup quakefs Quake Filesystem \ingroup utils */ -//@{ +///@{ #include "QF/qtypes.h" #include "QF/quakeio.h" @@ -418,6 +418,6 @@ void QFS_FilelistFill (filelist_t *list, const char *path, const char *ext, */ void QFS_FilelistFree (filelist_t *list); -//@} +///@} #endif // __quakefs_h diff --git a/include/QF/quakeio.h b/include/QF/quakeio.h index d72d8ec29..08b14af69 100644 --- a/include/QF/quakeio.h +++ b/include/QF/quakeio.h @@ -34,7 +34,7 @@ /** \defgroup quakeio File IO \ingroup utils */ -//@{ +///@{ typedef struct QFile_s QFile; @@ -60,6 +60,6 @@ int Qflush(QFile *file); int Qeof(QFile *file); const char *Qgetline(QFile *file); -//@} +///@} #endif /*__quakeio_h*/ diff --git a/include/QF/script.h b/include/QF/script.h index 2fe21c215..357e5100b 100644 --- a/include/QF/script.h +++ b/include/QF/script.h @@ -25,7 +25,7 @@ Line oriented script parsing. Multiple scripts being parsed at the same time is supported. */ -//@{ +///@{ #include "QF/qtypes.h" @@ -97,6 +97,6 @@ void Script_UngetToken (script_t *script); */ const char *Script_Token (script_t *script) __attribute__((pure)); -//@} +///@} #endif//__QF_script_h diff --git a/include/QF/set.h b/include/QF/set.h index 2f4dd76e5..1261bdb40 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -36,7 +36,7 @@ /** \defgroup set Set handling \ingroup utils */ -//@{ +///@{ //FIXME other archs #ifdef __x86_64__ @@ -370,5 +370,5 @@ set_iter_t *set_next_r (set_pool_t *set_pool, set_iter_t *set_iter); */ const char *set_as_string (const set_t *set); -//@} +///@} #endif//__QF_set_h diff --git a/include/QF/sizebuf.h b/include/QF/sizebuf.h index 8605f803d..7f6fc4ac3 100644 --- a/include/QF/sizebuf.h +++ b/include/QF/sizebuf.h @@ -31,7 +31,7 @@ \ingroup utils Fixed size buffer management */ -//@{ +///@{ #include "QF/qtypes.h" @@ -51,6 +51,6 @@ void *SZ_GetSpace (sizebuf_t *buf, int length); void SZ_Write (sizebuf_t *buf, const void *data, int length); void SZ_Print (sizebuf_t *buf, const char *data); // strcats onto the sizebuf -//@} +///@} #endif // __sizebuf_h diff --git a/include/QF/sound.h b/include/QF/sound.h index 874469ea4..3382d4b91 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -37,7 +37,7 @@ /** \ingroup sound */ -//@{ +///@{ typedef struct sfx_s sfx_t; struct sfx_s { @@ -62,14 +62,14 @@ struct sfx_s sfx_t *(*open) (sfx_t *sfx); void (*close) (sfx_t *sfx); }; -//@} +///@} struct model_s; /** \defgroup sound_init Initialization functions \ingroup sound */ -//@{ +///@{ /** Initialize the sound engine. \param viewentity pointer to view entity index @@ -85,12 +85,12 @@ void S_Init_Cvars (void); gracefully. */ void S_Shutdown (void); -//@} +///@} /** \defgroup sound_stuff Unclassified \ingroup sound */ -//@{ +///@{ /** Start a sound playing. \param entnum index of entity the sound is associated with. @@ -193,6 +193,6 @@ void S_AmbientOn (void); struct progs_s; void S_Progs_Init (struct progs_s *pr); -//@} +///@} #endif // _SOUND_H diff --git a/include/QF/sys.h b/include/QF/sys.h index f93432d65..85785ed6e 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -32,7 +32,7 @@ \ingroup utils Non-portable functions */ -//@{ +///@{ #include #include @@ -157,6 +157,6 @@ int Sys_CreatePath (const char *path); */ char *Sys_ExpandSquiggle (const char *path); -//@} +///@} #endif // __sys_h diff --git a/include/QF/va.h b/include/QF/va.h index 6a5e54465..40c794712 100644 --- a/include/QF/va.h +++ b/include/QF/va.h @@ -32,13 +32,13 @@ /** \addtogroup misc Formatted printing. */ -//@{ +///@{ // does a varargs printf into a temp buffer char *va(const char *format, ...) __attribute__((format(printf,1,2))); // does a varargs printf into a malloced buffer char *nva(const char *format, ...) __attribute__((format(printf,1,2))); -//@} +///@} #endif // __va_h diff --git a/include/QF/ver_check.h b/include/QF/ver_check.h index 5d8c1061c..8ac943796 100644 --- a/include/QF/ver_check.h +++ b/include/QF/ver_check.h @@ -34,7 +34,7 @@ /** \defgroup misc Miscellaneous functions \ingroup utils */ -//@{ +///@{ /* ver_compare @@ -45,6 +45,6 @@ */ int ver_compare (const char *, const char *); -//@} +///@} #endif // __ver_check_h_ diff --git a/include/QF/view.h b/include/QF/view.h index ecb2ea920..570935ae8 100644 --- a/include/QF/view.h +++ b/include/QF/view.h @@ -34,7 +34,7 @@ /** \defgroup console_view Console View Objects \ingroup console */ -//@{ +///@{ /** Control the positioning of a view within its parent. The directions are the standard compass rose (north, east, south, west in clockwise order) @@ -215,6 +215,6 @@ void view_resize (view_t *view, int xl, int yl); */ void view_move (view_t *view, int xp, int yp); -//@} +///@} #endif//__qf_view_h diff --git a/include/QF/wad.h b/include/QF/wad.h index 805a69925..82e836dc9 100644 --- a/include/QF/wad.h +++ b/include/QF/wad.h @@ -32,7 +32,7 @@ /** \addtogroup wad Wad Files */ -//@{ +///@{ #include "QF/wadfile.h" @@ -46,6 +46,6 @@ void *W_GetLumpName (const char *name); void SwapPic (qpic_t *pic); -//@} +///@} #endif // _WAD_H diff --git a/include/QF/wadfile.h b/include/QF/wadfile.h index 79e5e2055..9e6c220f6 100644 --- a/include/QF/wadfile.h +++ b/include/QF/wadfile.h @@ -29,7 +29,7 @@ \ingroup utils Wadfile processing */ -//@{ +///@{ #ifndef __QF_wadfile_h #define __QF_wadfile_h @@ -102,6 +102,6 @@ int wad_add_data (wad_t *wad, const char *lumpname, byte type, const void *data, int bytes); lumpinfo_t *wad_find_lump (wad_t *wad, const char *filename); -//@} +///@} #endif//__QF_wadfile_h diff --git a/include/QF/winding.h b/include/QF/winding.h index 5ef3d8094..5815ac793 100644 --- a/include/QF/winding.h +++ b/include/QF/winding.h @@ -26,7 +26,7 @@ /** \defgroup winding Winding Manipulation */ -//@{ +///@{ struct plane_s; @@ -138,6 +138,6 @@ winding_t *ClipWinding (winding_t *in, struct plane_s *split, qboolean keepon); void DivideWinding (winding_t *in, struct plane_s *split, winding_t **front, winding_t **back); -//@} +///@} #endif//__QF_winding_h diff --git a/include/QF/zone.h b/include/QF/zone.h index 379f4557a..1f968737f 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -88,7 +88,7 @@ ----- Bottom of Memory ----- */ -//@{ +///@{ typedef struct memzone_s memzone_t; @@ -140,6 +140,6 @@ void *Cache_Get (cache_user_t *c); void Cache_Release (cache_user_t *c); int Cache_ReadLock (cache_user_t *c) __attribute__((pure)); -//@} +///@} #endif // __zone_h diff --git a/include/net_dgrm.h b/include/net_dgrm.h index 712864dd3..38c2f7e19 100644 --- a/include/net_dgrm.h +++ b/include/net_dgrm.h @@ -29,7 +29,7 @@ /** \defgroup nq-dgrm NetQuake Datagram network driver. \ingroup nq-nd */ -//@{ +///@{ /** Initialize the Datagram net driver. @@ -125,4 +125,4 @@ void Datagram_Close (qsocket_t *sock); */ void Datagram_Shutdown (void); -//@} +///@} diff --git a/include/net_loop.h b/include/net_loop.h index a0f58a34a..9247f949e 100644 --- a/include/net_loop.h +++ b/include/net_loop.h @@ -34,7 +34,7 @@ /** \defgroup nq-loop NetQuake loopback network driver. \ingroup nq-nd */ -//@{ +///@{ int Loop_Init (void); void Loop_Listen (qboolean state); @@ -49,6 +49,6 @@ qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock); void Loop_Close (qsocket_t *sock); void Loop_Shutdown (void); -//@} +///@} #endif//__net_loop_h diff --git a/include/net_udp.h b/include/net_udp.h index 78f26a6ec..bd414513d 100644 --- a/include/net_udp.h +++ b/include/net_udp.h @@ -33,7 +33,7 @@ /** \defgroup nq-udp NetQuake UDP lan driver. \ingroup nq-ld */ -//@{ +///@{ /** Initialize the UDP network interface. @@ -193,6 +193,6 @@ int UDP_GetSocketPort (netadr_t *addr); */ int UDP_SetSocketPort (netadr_t *addr, int port); -//@} +///@} #endif // __net_udp_h diff --git a/include/net_vcr.h b/include/net_vcr.h index f5383b572..9f5446453 100644 --- a/include/net_vcr.h +++ b/include/net_vcr.h @@ -29,7 +29,7 @@ /** \defgroup nq-vcr NetQuake VCR network driver. \ingroup nq-nd */ -//@{ +///@{ #define VCR_OP_CONNECT 1 #define VCR_OP_GETMESSAGE 2 @@ -48,4 +48,4 @@ qboolean VCR_CanSendMessage (qsocket_t *sock); void VCR_Close (qsocket_t *sock); void VCR_Shutdown (void); -//@} +///@} diff --git a/include/net_wins.h b/include/net_wins.h index fe4133f50..c4954f9ac 100644 --- a/include/net_wins.h +++ b/include/net_wins.h @@ -35,7 +35,7 @@ /** \defgroup nq-wins NetQuake Winsock lan driver. \ingroup nq-ld */ -//@{ +///@{ extern int winsock_initialized; extern WSADATA winsockdata; @@ -58,6 +58,6 @@ int WINS_AddrCompare (netadr_t *addr1, netadr_t *addr2); int WINS_GetSocketPort (netadr_t *addr); int WINS_SetSocketPort (netadr_t *addr, int port); -//@} +///@} #endif//__net_wins_h diff --git a/include/netchan.h b/include/netchan.h index 556732ba2..d811ba913 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -39,7 +39,7 @@ /** \defgroup qw-net QuakeWorld network support. \ingroup network */ -//{ +///@{ #define MAX_MSGLEN 1450 ///< max length of a reliable message #define MAX_DATAGRAM 1450 ///< max length of unreliable message @@ -75,12 +75,12 @@ void Analyze_Client_Packet (const byte * data, int len, int has_sequence); void Analyze_Server_Packet (const byte * data, int len, int has_sequence); extern struct cvar_s *net_packetlog; -//@} +///@} /** \defgroup qw-udp QuakeWorld udp support. \ingroup qw-net */ -//@{ +///@{ /** Initialize the UDP network interface. @@ -165,7 +165,7 @@ const char *NET_BaseAdrToString (netadr_t a); */ qboolean NET_StringToAdr (const char *s, netadr_t *a); -//@} +///@} /** \defgroup netchan Netchan \ingroup qw-net @@ -220,7 +220,7 @@ qboolean NET_StringToAdr (const char *s, netadr_t *a); the channel matches even if the IP port differs. The IP port should be updated to the new value before sending out any replies. */ -//@{ +///@{ #define OLD_AVG 0.99 // total = oldtotal*OLD_AVG + new*(1-OLD_AVG) #define MAX_LATENT 32 @@ -381,6 +381,6 @@ qboolean Netchan_CanReliable (netchan_t *chan) __attribute__((pure)); */ void Netchan_SendPacket (int length, const void *data, netadr_t to); -//@} +///@} #endif // _NET_H diff --git a/include/netmain.h b/include/netmain.h index a35171415..8cae78d60 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -34,7 +34,7 @@ /** \defgroup nq-net NetQuake network support. \ingroup network */ -//@{ +///@{ typedef struct { @@ -56,7 +56,7 @@ typedef struct /** \name NetHeader flags */ -//@{ +///@{ #define NETFLAG_LENGTH_MASK 0x0000ffff #define NETFLAG_DATA 0x00010000 #define NETFLAG_ACK 0x00020000 @@ -64,7 +64,7 @@ typedef struct #define NETFLAG_EOM 0x00080000 #define NETFLAG_UNRELIABLE 0x00100000 #define NETFLAG_CTL 0x80000000 -//@} +///@} #define NET_PROTOCOL_VERSION 3 @@ -86,7 +86,7 @@ typedef struct a full address and port in a string. It is used for returning the address of a server that is not running locally. */ -//@{ +///@{ /** Connect Request: \arg \b string \c game_name \em "QUAKE" @@ -153,7 +153,7 @@ typedef struct \arg \b string \c value */ #define CCREP_RULE_INFO 0x85 -//@} +///@} typedef struct qsocket_s { struct qsocket_s *next; @@ -205,11 +205,11 @@ typedef struct qsocket_s { /** \name socket management */ -//@{ +///@{ extern qsocket_t *net_activeSockets; extern qsocket_t *net_freeSockets; extern int net_numsockets; -//@} +///@} #define MAX_NET_DRIVERS 8 @@ -220,12 +220,12 @@ extern int net_driverlevel; /** \name message statistics */ -//@{ +///@{ extern int messagesSent; extern int messagesReceived; extern int unreliableMessagesSent; extern int unreliableMessagesReceived; -//@} +///@} /** Create and initialize a new qsocket. @@ -390,12 +390,12 @@ extern struct cvar_s *hostname; extern QFile *vcrFile; -//@} +///@} /** \defgroup nq-ld NetQuake lan drivers. \ingroup nq-net */ -//@{ +///@{ typedef struct { const char *name; @@ -423,12 +423,12 @@ typedef struct { extern int net_numlandrivers; extern net_landriver_t net_landrivers[MAX_NET_DRIVERS]; -//@} +///@} /** \defgroup nq-nd NetQuake network drivers. \ingroup nq-net */ -//@{ +///@{ typedef struct { const char *name; @@ -451,6 +451,6 @@ typedef struct { extern int net_numdrivers; extern net_driver_t net_drivers[MAX_NET_DRIVERS]; -//@} +///@} #endif // __net_h diff --git a/include/snd_internal.h b/include/snd_internal.h index 0b1e87a21..ca4dc76c6 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -35,7 +35,7 @@ /** \defgroup sound_render Sound rendering sub-system. \ingroup sound */ -//@{ +///@{ #include "QF/plugin/general.h" #include "QF/plugin/snd_render.h" @@ -234,12 +234,12 @@ extern snd_render_data_t snd_render_data; #define PAINTBUFFER_SIZE 512 extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; -//@} +///@} /** \defgroup sound_render_sfx Sound sfx \ingroup sound_render_mix */ -//@{ +///@{ /** Cache sound data. Initializes caching fields of sfx. \param sfx \param realname @@ -289,7 +289,7 @@ sfx_t *SND_LoadSound (const char *name); */ void SND_SFX_Init (void); -//@} +///@} /** \defgroup sound_render_mix_channels Sound channels \ingroup sound_render_mix @@ -302,7 +302,7 @@ void SND_SFX_Init (void); - MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels - 1
static sounds */ -//@{ +///@{ #define MAX_CHANNELS 512 //!< number of available mixing channels #define MAX_DYNAMIC_CHANNELS 128 //!< number of dynamic channels #define MAX_STATIC_CHANNELS 256 //!< number of static channels @@ -390,13 +390,13 @@ void SND_StopSound (int entnum, int entchannel); \param s name of sound to play */ void SND_LocalSound (const char *s); -//@} +///@} /** \defgroup sound_render_mix Mixer engine. \ingroup sound_render */ -//@{ +///@{ /** sound clock in samples */ extern unsigned snd_paintedtime; @@ -414,13 +414,13 @@ void SND_InitScaletable (void); \param sc sfxbuffer to set. */ void SND_SetPaint (sfxbuffer_t *sc); -//@} +///@} /** \defgroup sound_render_resample Resampling functions \ingroup sound_render */ -//@{ +///@{ /** Set up the various parameters that depend on the actual sample rate. \param sc buffer to setup \param streamed non-zero if this is for a stream. @@ -448,13 +448,13 @@ void SND_Resample (sfxbuffer_t *sc, float *data, int length); */ void SND_Convert (byte *idata, float *fdata, int frames, int channels, int width); -//@} +///@} /** \defgroup sound_render_load Sound loading functions \ingroup sound_render */ -//@{ +///@{ /** Load the referenced sound. \param sfx sound reference \return 0 if ok, -1 on error @@ -492,12 +492,12 @@ int SND_LoadWav (QFile *file, sfx_t *sfx, char *realname); \return 0 if ok, -1 on error */ int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname); -//@} +///@} /** \defgroup sound_render_cache_stream Cache/Stream Functions. \ingroup sound_render */ -//@{ +///@{ /** Retrieve wavinfo from a cached sound. \param sfx sound reference \return pointer to sound's wavinfo @@ -579,6 +579,6 @@ void SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos); */ sfxbuffer_t *SND_GetCache (long samples, int rate, int channels, sfxblock_t *block, cache_allocator_t allocator); -//@} +///@} #endif//__snd_internal_h diff --git a/libs/models/winding.c b/libs/models/winding.c index d065224f7..62ae9fcb8 100644 --- a/libs/models/winding.c +++ b/libs/models/winding.c @@ -40,10 +40,6 @@ #define BOGUS (18000.0) -/** \addtogroup qfbsp_winding -*/ -//@{ - int c_activewindings, c_peakwindings; winding_t * @@ -326,5 +322,3 @@ FreeWinding (winding_t *w) c_activewindings--; free (w); } - -//@} diff --git a/qtv/include/connection.h b/qtv/include/connection.h index d02e4b971..18bbbc277 100644 --- a/qtv/include/connection.h +++ b/qtv/include/connection.h @@ -36,7 +36,7 @@ /** \defgroup qtv_connection Connection Management \ingroup qtv */ -//@{ +///@{ typedef struct connection_s { netadr_t address; ///< Address of the remote end. @@ -77,6 +77,6 @@ void Connection_Del (connection_t *con); */ connection_t *Connection_Find (netadr_t *address); -//@} +///@} #endif//__connection_h diff --git a/qtv/include/qtv.h b/qtv/include/qtv.h index 57947af16..732febfb3 100644 --- a/qtv/include/qtv.h +++ b/qtv/include/qtv.h @@ -40,7 +40,7 @@ /** \defgroup qtv_general General Functions \ingroup qtv */ -//@{ +///@{ #define PORT_QTV 27501 ///< Default port to listen for connecting clients. @@ -91,6 +91,6 @@ void qtv_end_redirect (void); void qtv_sbar_init (void); -//@} +///@} #endif//__qtv_h diff --git a/ruamoko/include/gui/Group.h b/ruamoko/include/gui/Group.h index b9ea99386..f20cca09c 100644 --- a/ruamoko/include/gui/Group.h +++ b/ruamoko/include/gui/Group.h @@ -4,7 +4,7 @@ #include "View.h" /** \addtogroup gui */ -//@{ +///@{ @class Array; @@ -41,6 +41,6 @@ - (id) addViews: (Array*)viewlist; @end -//@} +///@} #endif//__ruamoko_gui_Group_h diff --git a/ruamoko/include/gui/InputLine.h b/ruamoko/include/gui/InputLine.h index 692562a08..363cc0b8c 100644 --- a/ruamoko/include/gui/InputLine.h +++ b/ruamoko/include/gui/InputLine.h @@ -8,7 +8,7 @@ Interface functions to the engine implementation. */ -//@{ +///@{ /** Opaque handle to an inputline. @@ -118,10 +118,10 @@ typedef void (il_enterfunc)(string, void*); \return The current text of the intputline. */ @extern string InputLine_GetText (inputline_t il); -//@} +///@} /** \addtogroup gui */ -//@{ +///@{ /** Class representation of the low-level inputline objects. */ @@ -252,6 +252,6 @@ typedef void (il_enterfunc)(string, void*); - (string) text; @end -//@} +///@} #endif //__ruamoko_gui_InputLine_h diff --git a/ruamoko/include/gui/Pic.h b/ruamoko/include/gui/Pic.h index f19e8b6e4..9ed9e3380 100644 --- a/ruamoko/include/gui/Pic.h +++ b/ruamoko/include/gui/Pic.h @@ -4,7 +4,7 @@ #include "gui/View.h" /** \addtogroup gui */ -//@{ +///@{ @interface Pic : View { @@ -18,6 +18,6 @@ -(void)draw; @end -//@} +///@} #endif//__ruamoko_gui_Pic_h diff --git a/ruamoko/include/gui/Point.h b/ruamoko/include/gui/Point.h index 4ac36391a..9de4d7f5e 100644 --- a/ruamoko/include/gui/Point.h +++ b/ruamoko/include/gui/Point.h @@ -2,7 +2,7 @@ #define __ruamoko_gui_Point_h /** \addtogroup gui */ -//@{ +///@{ struct Point { int x; @@ -15,6 +15,6 @@ typedef struct Point Point; @extern Point addPoint (Point a, Point b); @extern Point subtractPoint (Point a, Point b); -//@} +///@} #endif //__ruamoko_gui_Point_h diff --git a/ruamoko/include/gui/Rect.h b/ruamoko/include/gui/Rect.h index 145815d66..005ce4a70 100644 --- a/ruamoko/include/gui/Rect.h +++ b/ruamoko/include/gui/Rect.h @@ -5,7 +5,7 @@ #include "gui/Size.h" /** \addtogroup gui */ -//@{ +///@{ struct Rect { Point origin; @@ -30,6 +30,6 @@ typedef struct Rect Rect; - (Rect) offsetBySize: (Size)aSize; #endif -//@} +///@} #endif //__ruamoko_gui_Rect_h diff --git a/ruamoko/include/gui/Size.h b/ruamoko/include/gui/Size.h index 0f6b387a3..dd48c6259 100644 --- a/ruamoko/include/gui/Size.h +++ b/ruamoko/include/gui/Size.h @@ -2,7 +2,7 @@ #define __ruamoko_gui_Size_h /** \addtogroup gui */ -//@{ +///@{ struct Size { int width; @@ -15,6 +15,6 @@ typedef struct Size Size; @extern Size addSize (Size a, Size b); @extern Size subtractSize (Size a, Size b); -//@} +///@} #endif //__ruamoko_gui_Size_h diff --git a/ruamoko/include/gui/Slider.h b/ruamoko/include/gui/Slider.h index 13a68f492..66710d28e 100644 --- a/ruamoko/include/gui/Slider.h +++ b/ruamoko/include/gui/Slider.h @@ -4,7 +4,7 @@ #include "View.h" /** \addtogroup gui */ -//@{ +///@{ @interface Slider: View { @@ -19,6 +19,6 @@ @end -//@} +///@} #endif //__ruamoko_gui_Slider_h diff --git a/ruamoko/include/gui/Text.h b/ruamoko/include/gui/Text.h index d9c6a1311..d5654d555 100644 --- a/ruamoko/include/gui/Text.h +++ b/ruamoko/include/gui/Text.h @@ -4,7 +4,7 @@ #include "View.h" /** \addtogroup gui */ -//@{ +///@{ @interface Text: View { @@ -18,6 +18,6 @@ - (void) draw; @end -//@} +///@} #endif //__ruamoko_gui_Text_h diff --git a/ruamoko/include/gui/View.h b/ruamoko/include/gui/View.h index a84f05e06..c2a99e036 100644 --- a/ruamoko/include/gui/View.h +++ b/ruamoko/include/gui/View.h @@ -8,7 +8,7 @@ */ /** \addtogroup gui */ -//@{ +///@{ /** The View class. */ @@ -34,6 +34,6 @@ - (int) keyEvent:(int)key unicode:(int)unicode down:(int)down; @end -//@} +///@} #endif //__ruamoko_gui_View_h diff --git a/tools/qfbsp/include/brush.h b/tools/qfbsp/include/brush.h index f51beab00..345b14747 100644 --- a/tools/qfbsp/include/brush.h +++ b/tools/qfbsp/include/brush.h @@ -30,7 +30,7 @@ /** \defgroup qfbsp_brush Brush Functions \ingroup qfbsp */ -//@{ +///@{ #define NUM_HULLS 2 // normal and +16 @@ -95,6 +95,6 @@ int NormalizePlane (plane_t *dp); */ int FindPlane (const plane_t *dplane, int *side); -//@} +///@} #endif//qfbsp_brush_h diff --git a/tools/qfbsp/include/bsp5.h b/tools/qfbsp/include/bsp5.h index 4cacb23ae..b949cf77c 100644 --- a/tools/qfbsp/include/bsp5.h +++ b/tools/qfbsp/include/bsp5.h @@ -32,7 +32,7 @@ /** \defgroup qfbsp_general General functions \ingroup qfbsp */ -//@{ +///@{ #define MAX_THREADS 4 @@ -129,6 +129,6 @@ node_t *AllocNode (void); extern bsp_t *bsp; -//@} +///@} #endif//qfbsp_bsp5_h diff --git a/tools/qfbsp/include/csg4.h b/tools/qfbsp/include/csg4.h index dd48047f4..e6ff8b4a3 100644 --- a/tools/qfbsp/include/csg4.h +++ b/tools/qfbsp/include/csg4.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_csg4 CSG Functions \ingroup qfbsp */ -//@{ +///@{ struct plane_s; struct visfacet_s; @@ -84,6 +84,6 @@ struct surface_s *CSGFaces (struct brushset_s *bs); void SplitFace (struct visfacet_s *in, struct plane_s *split, struct visfacet_s **front, struct visfacet_s **back); -//@} +///@} #endif//qfbsp_csg4_h diff --git a/tools/qfbsp/include/draw.h b/tools/qfbsp/include/draw.h index ecaa3fd53..740fa9050 100644 --- a/tools/qfbsp/include/draw.h +++ b/tools/qfbsp/include/draw.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_draw Debug Drawing Functions \ingroup qfbsp */ -//@{ +///@{ struct visfacet_s; struct portal_s; @@ -53,6 +53,6 @@ void DrawBrush (const struct brush_s *b); void DrawWinding (const struct winding_s *w); void DrawTri (const vec3_t p1, const vec3_t p2, const vec3_t p3); -//@} +///@} #endif//qfbsp_draw_h diff --git a/tools/qfbsp/include/map.h b/tools/qfbsp/include/map.h index e531fad8a..25c56d4ef 100644 --- a/tools/qfbsp/include/map.h +++ b/tools/qfbsp/include/map.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_map Map Parser \ingroup qfbsp */ -//@{ +///@{ #define MAX_FACES 256 typedef struct mface_s { @@ -120,6 +120,6 @@ void GetVectorForKey (const entity_t *ent, const char *key, vec3_t vec); */ void WriteEntitiesToString (void); -//@} +///@} #endif//qfbsp_map_h diff --git a/tools/qfbsp/include/merge.h b/tools/qfbsp/include/merge.h index 81e8b2c1c..c65ee15ff 100644 --- a/tools/qfbsp/include/merge.h +++ b/tools/qfbsp/include/merge.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_merge Merge Functions \ingroup qfbsp */ -//@{ +///@{ /** Add a face to the list of faces, doing any possible merging. @@ -63,6 +63,6 @@ void MergePlaneFaces (surface_t *plane); */ void MergeAll (surface_t *surfhead); -//@} +///@} #endif//qfbsp_merge_h diff --git a/tools/qfbsp/include/options.h b/tools/qfbsp/include/options.h index 4b062f27e..47a8e0df7 100644 --- a/tools/qfbsp/include/options.h +++ b/tools/qfbsp/include/options.h @@ -33,7 +33,7 @@ /** \defgroup qfbsp_options Command-line Options Parsing \ingroup qfbsp */ -//@{ +///@{ typedef struct { int verbosity; // 0=silent @@ -65,6 +65,6 @@ extern options_t options; int DecodeArgs (int argc, char **argv); extern const char *this_program; -//@} +///@} #endif//qfbsp_options_h diff --git a/tools/qfbsp/include/outside.h b/tools/qfbsp/include/outside.h index 8ad85fe49..e45e11496 100644 --- a/tools/qfbsp/include/outside.h +++ b/tools/qfbsp/include/outside.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_outside Outside Functions \ingroup qfbsp */ -//@{ +///@{ struct node_s; @@ -41,6 +41,6 @@ struct node_s; */ qboolean FillOutside (struct node_s *node); -//@} +///@} #endif//qfbsp_outside_h diff --git a/tools/qfbsp/include/portals.h b/tools/qfbsp/include/portals.h index 381bbf0f9..6d5da460e 100644 --- a/tools/qfbsp/include/portals.h +++ b/tools/qfbsp/include/portals.h @@ -31,7 +31,7 @@ Decision nodes will not have portals on them, though as part of the portal building process, they will temporarily have portals. */ -//@{ +///@{ struct node_s; @@ -89,6 +89,6 @@ void FreeAllPortals (struct node_s *node); */ void WritePortalfile (struct node_s *headnode); -//@} +///@} #endif//qfbsp_portals_h diff --git a/tools/qfbsp/include/readbsp.h b/tools/qfbsp/include/readbsp.h index 17f1b2890..5887a68ea 100644 --- a/tools/qfbsp/include/readbsp.h +++ b/tools/qfbsp/include/readbsp.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_readbsp BSP Reading Functions \ingroup qfbsp */ -//@{ +///@{ /** Load the bspfile into memory. */ @@ -47,6 +47,6 @@ void extract_entities (void); */ void extract_hull (void); -//@} +///@} #endif//qfbsp_readbsp_h diff --git a/tools/qfbsp/include/region.h b/tools/qfbsp/include/region.h index ce30e71f7..2a17734c5 100644 --- a/tools/qfbsp/include/region.h +++ b/tools/qfbsp/include/region.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_region Region Functions \ingroup qfbsp */ -//@{ +///@{ struct node_s; @@ -35,6 +35,6 @@ struct node_s; */ void GrowNodeRegions (struct node_s *headnode); -//@} +///@} #endif//qfbsp_region_h diff --git a/tools/qfbsp/include/solidbsp.h b/tools/qfbsp/include/solidbsp.h index 18bd306a6..5a3d7fbe4 100644 --- a/tools/qfbsp/include/solidbsp.h +++ b/tools/qfbsp/include/solidbsp.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_solidbsp BSP Creation Functions \ingroup qfbsp */ -//@{ +///@{ struct visfacet_s; struct plane_s; @@ -48,6 +48,6 @@ void CalcSurfaceInfo (struct surface_s *surf); */ struct node_s *SolidBSP (struct surface_s *surfhead, qboolean midsplit); -//@} +///@} #endif//qfbsp_solidbsp_h diff --git a/tools/qfbsp/include/surfaces.h b/tools/qfbsp/include/surfaces.h index ebb8314cc..561d21048 100644 --- a/tools/qfbsp/include/surfaces.h +++ b/tools/qfbsp/include/surfaces.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_surface Surface Functions \ingroup qfbsp */ -//@{ +///@{ struct visfacet_s; struct node_s; @@ -104,6 +104,6 @@ struct surface_s *GatherNodeFaces (struct node_s *headnode); */ void MakeFaceEdges (struct node_s *headnode); -//@} +///@} #endif//surfaces_h diff --git a/tools/qfbsp/include/tjunc.h b/tools/qfbsp/include/tjunc.h index 46fa939fc..3557e4df7 100644 --- a/tools/qfbsp/include/tjunc.h +++ b/tools/qfbsp/include/tjunc.h @@ -25,7 +25,7 @@ /** \defgroup qfbsp_tjunc T-Junction Repair \ingroup qfbsp */ -//@{ +///@{ struct node_s; @@ -35,6 +35,6 @@ struct node_s; */ void tjunc (struct node_s *headnode); -//@} +///@} #endif//qfbsp_tjunc_h diff --git a/tools/qfbsp/include/writebsp.h b/tools/qfbsp/include/writebsp.h index 6d2a5cf0f..759220904 100644 --- a/tools/qfbsp/include/writebsp.h +++ b/tools/qfbsp/include/writebsp.h @@ -27,7 +27,7 @@ /** \defgroup qfbsp_writebsp BSP Writing Functions \ingroup qfbsp */ -//@{ +///@{ struct node_s; @@ -78,6 +78,6 @@ void BeginBSPFile (void); */ void FinishBSPFile (void); -//@} +///@} #endif//qfbsp_writebsp_h diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index c0d07c4b3..c83c029f6 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -33,7 +33,7 @@ /** \defgroup qfcc_dags DAG building \ingroup qfcc */ -//@{ +///@{ #include "QF/pr_comp.h" @@ -110,6 +110,6 @@ dag_t *dag_create (struct flownode_s *flownode); void dag_remove_dead_nodes (dag_t *dag); void dag_generate (dag_t *dag, sblock_t *block); -//@} +///@} #endif//dags_h diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 68b946fab..df0104178 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -37,7 +37,7 @@ /** \defgroup qfcc_def Def handling \ingroup qfcc */ -//@{ +///@{ struct symbol_s; struct expr_s; @@ -180,7 +180,7 @@ void free_def (def_t *def); Temporary defs are bound to the current function (::current_func must be valid). They are always allocated from the funciont's local defspace. */ -//@{ +///@{ /** Get a temporary def. If the current function has a free temp def of the same size as \a size, @@ -207,7 +207,7 @@ def_t *temp_def (struct type_s *type); \param temp The temp def to be recycled. */ void free_temp_def (def_t *temp); -//@} +///@} /** Initialize a vm def from a qfcc def. @@ -306,6 +306,6 @@ int def_size (def_t *def) __attribute__((pure)); */ int def_visit_all (def_t *def, int overlap, int (*visit) (def_t *, void *), void *data); -//@} +///@} #endif//__def_h diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index 8e7f034d6..bd4b68920 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -37,7 +37,7 @@ /** \defgroup qfcc_defspace Defspace handling \ingroup qfcc */ -//@{ +///@{ typedef enum { ds_backed, ///< data space is globally addressable (near/far/type) and @@ -145,6 +145,6 @@ void defspace_free_loc (defspace_t *space, int ofs, int size); */ int defspace_add_data (defspace_t *space, pr_type_t *data, int size); -//@} +///@} #endif//__defspace_h diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index bd32711f8..3a19c9722 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -36,7 +36,7 @@ /** \defgroup qfcc_diagnostic Diagnostic Messages \ingroup qfcc */ -//@{ +///@{ typedef void (*diagnostic_hook)(const char *message); extern diagnostic_hook bug_hook; @@ -73,6 +73,6 @@ void _bug (struct expr_s *e, const char *file, int line, const char *fmt, ...) __attribute__ ((format (printf, 4, 5))); #define bug(e, fmt...) _bug(e, __FILE__, __LINE__, fmt) -//@} +///@} #endif//__diagnostic_h diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5109b364e..d83610b7f 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -36,7 +36,7 @@ /** \defgroup qfcc_expr Expressions \ingroup qfcc */ -//@{ +///@{ /** Type of the exression node in an expression tree. */ @@ -652,6 +652,6 @@ expr_t *sizeof_expr (expr_t *expr, struct type_s *type); expr_t *fold_constants (expr_t *e); -//@} +///@} #endif//__expr_h diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index 591704a01..b4cc48cf5 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -33,7 +33,7 @@ /** \defgroup qfcc_flow Flow graph analysis \ingroup qfcc */ -//@{ +///@{ struct function_s; struct sblock_s; @@ -120,6 +120,6 @@ void dump_dot_flow_live (void *g, const char *filename); void dump_dot_flow_reaching (void *g, const char *filename); void dump_dot_flow_statements (void *g, const char *filename); -//@} +///@} #endif//flow_h diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index d145fc53e..88ea05dc8 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -34,7 +34,7 @@ /** \defgroup qfcc_function Internal function structures. \ingroup qfcc */ -//@{ +///@{ #include "QF/pr_comp.h" #include "QF/pr_debug.h" @@ -147,6 +147,6 @@ void emit_function (function_t *f, struct expr_s *e); int function_parms (function_t *f, byte *parm_size); void clear_functions (void); -//@} +///@} #endif//__function_h diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 1fe1d3690..0e6096028 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -34,7 +34,7 @@ /** \defgroup qfcc_qfo Object file functions \ingroup qfcc */ -//@{ +///@{ #include "QF/pr_comp.h" #include "QF/pr_debug.h" @@ -106,12 +106,12 @@ typedef struct qfo_def_s { string_t file; ///< source file name pr_uint_t line; ///< source line number } qfo_def_t; -//@} +///@} /** \defgroup qfcc_qfo_QFOD QFOD flags \ingroup qfcc_qfo */ -//@{ +///@{ /** The def has been initialized. @@ -168,11 +168,11 @@ typedef struct qfo_def_s { \hideinitializer */ #define QFOD_PARAM (1u<<8) -//@} +///@} /** \addtogroup qfcc_qfo */ -//@{ +///@{ /** Representation of a function in the object file. */ @@ -286,13 +286,13 @@ enum { qfo_num_spaces }; -//@} +///@} /** \defgroup qfcc_qfo_data_access QFO Data Acess \ingroup qfcc_qfo Macros for accessing data in the QFO address space */ -//@{ +///@{ /** \internal \param q pointer to ::qfo_t struct @@ -361,7 +361,6 @@ enum { \param q pointer to ::qfo_t struct \param s space index - \param s offset into object file string space \return (char *) \hideinitializer @@ -439,11 +438,11 @@ enum { */ #define QFO_STRUCT(q, s, t, o) (*QFO_POINTER (q, s, t, o)) -//@} +///@} /** \addtogroup qfcc_qfo */ -//@{ +///@{ struct pr_info_s; @@ -485,6 +484,6 @@ qfo_t *qfo_new (void); */ void qfo_delete (qfo_t *qfo); -//@} +///@} #endif//__obj_file_h diff --git a/tools/qfcc/include/obj_type.h b/tools/qfcc/include/obj_type.h index d9c677641..13ce701e4 100644 --- a/tools/qfcc/include/obj_type.h +++ b/tools/qfcc/include/obj_type.h @@ -38,6 +38,4 @@ struct type_s; struct def_s *qfo_encode_type (struct type_s *type); -//@} - #endif//__obj_type_h diff --git a/tools/qfcc/include/pragma.h b/tools/qfcc/include/pragma.h index 1f6726f28..5f660ac23 100644 --- a/tools/qfcc/include/pragma.h +++ b/tools/qfcc/include/pragma.h @@ -33,10 +33,10 @@ /** \defgroup qfcc_pragma pragma handling \ingroup qfcc */ -//@{ +///@{ void pragma (const char *id); -//@} +///@} #endif//pragma_h diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 0bec07d37..1a1793b34 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -39,7 +39,7 @@ /** \defgroup qfcc_general General functions \ingroup qfcc */ -//@{ +///@{ typedef struct srcline_s srcline_t; struct srcline_s { @@ -132,6 +132,6 @@ char *fix_backslash (char *path); */ #define RUP(x,a) (((x) + ((a) - 1)) & ~((a) - 1)) -//@} +///@} #endif//__qfcc_h diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index f338077eb..c0c064f3e 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -39,7 +39,7 @@ enum storage_class_e; /** \defgroup qfcc_symtab Symbol Table Management \ingroup qfcc */ -//@{ +///@{ typedef enum vis_e { vis_public, @@ -235,6 +235,6 @@ symtab_t *symtab_flat_copy (symtab_t *symtab, symtab_t *parent); symbol_t *make_symbol (const char *name, struct type_s *type, struct defspace_s *space, enum storage_class_e storage); -//@} +///@} #endif//__symtab_h diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index 11bee26e6..883af01e0 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -34,7 +34,7 @@ /** \defgroup qfcc_value Constant values. \ingroup qfcc_expr */ -//@{ +///@{ struct ex_value_s; struct type_s; @@ -63,6 +63,6 @@ int ReuseString (const char *str); void clear_immediates (void); -//@} +///@} #endif//__value_h diff --git a/tools/qflight/include/entities.h b/tools/qflight/include/entities.h index 82bf378cc..6f3d1dd12 100644 --- a/tools/qflight/include/entities.h +++ b/tools/qflight/include/entities.h @@ -34,7 +34,7 @@ /** \defgroup qflight_entities Light entity data. \ingroup qflight */ -//@{ +///@{ #define DEFAULTLIGHTLEVEL 300 #define DEFAULTFALLOFF 1.0f @@ -106,6 +106,6 @@ void GetVectorForKey (entity_t *ent, const char *key, vec3_t vec); void LoadEntities (void); void WriteEntitiesToString (void); -//@} +///@} #endif// __entities_h diff --git a/tools/qflight/include/light.h b/tools/qflight/include/light.h index e06a9157a..350b7e442 100644 --- a/tools/qflight/include/light.h +++ b/tools/qflight/include/light.h @@ -37,7 +37,7 @@ /** \defgroup qflight_general General functions \ingroup qflight */ -//@{ +///@{ #define ON_EPSILON 0.1 #define MAXLIGHTS 1024 @@ -130,6 +130,6 @@ extern int num_novislights; const char *get_tex_name (int texindex) __attribute__((pure)); -//@} +///@} #endif// __light_h diff --git a/tools/qflight/include/noise.h b/tools/qflight/include/noise.h index 30625ae13..be63d9de1 100644 --- a/tools/qflight/include/noise.h +++ b/tools/qflight/include/noise.h @@ -31,7 +31,7 @@ /** \defgroup qflight_noise Light noise functions. \ingroup qflight */ -//@{ +///@{ float noise3d (vec3_t v, int num) __attribute__((pure)); float noiseXYZ (float x, float y, float z, int num) __attribute__((pure)); @@ -39,4 +39,4 @@ float noise_scaled (vec3_t v, float s, int num) __attribute__((pure)); float noise_perlin (vec3_t v, float p, int num) __attribute__((pure)); void snap_vector (vec3_t v_old, vec3_t v_new, float scale); -//@} +///@} diff --git a/tools/qflight/include/options.h b/tools/qflight/include/options.h index a90592519..32c6d6755 100644 --- a/tools/qflight/include/options.h +++ b/tools/qflight/include/options.h @@ -33,7 +33,7 @@ /** \defgroup qflight_options Light command line options. \ingroup qflight */ -//@{ +///@{ typedef struct { int verbosity; // 0=silent @@ -59,6 +59,6 @@ extern const char *this_program; int DecodeArgs (int argc, char **argv); void usage (int status) __attribute__((noreturn)); -//@} +///@} #endif//__options_h diff --git a/tools/qflight/include/properties.h b/tools/qflight/include/properties.h index a6b724d19..d5e73db7f 100644 --- a/tools/qflight/include/properties.h +++ b/tools/qflight/include/properties.h @@ -33,7 +33,7 @@ /** \defgroup qflight_properties Lighting properties \ingroup qflight */ -//@{ +///@{ struct plitem_s; @@ -199,6 +199,6 @@ void set_properties (entity_t *ent, struct plitem_s *dict); */ void LoadProperties (const char *filename); -//@} +///@} #endif//__properties_h diff --git a/tools/qflight/include/threads.h b/tools/qflight/include/threads.h index 30b9cc59f..0fd5c00af 100644 --- a/tools/qflight/include/threads.h +++ b/tools/qflight/include/threads.h @@ -32,7 +32,7 @@ /** \defgroup qflight_threads Light thread handling. \ingroup qflight */ -//@{ +///@{ #if defined (HAVE_PTHREAD_H) && defined (HAVE_PTHREAD) @@ -66,6 +66,6 @@ typedef void *(threadfunc_t) (void *); void InitThreads (void); void RunThreadsOn (threadfunc_t func); -//@} +///@} #endif// __threads_h From bdf2443d010f2e9fe32413bde1281a8881736091 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Feb 2020 15:27:32 +0900 Subject: [PATCH 0248/3664] Fix ambiguous image file name warnings Most of the warnings are due to a bug in doxygen (fixed in 1.8.17, but...), however some were legit due to overzealous image search paths wildly including the doxygen output tree. --- doc/quakeforge.dox.conf.in | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/quakeforge.dox.conf.in b/doc/quakeforge.dox.conf.in index 64028f578..3781f222a 100644 --- a/doc/quakeforge.dox.conf.in +++ b/doc/quakeforge.dox.conf.in @@ -937,7 +937,6 @@ EXAMPLE_RECURSIVE = NO # \image command). IMAGE_PATH = @TOPSRC@/doc \ - @builddir@ \ @builddir@/progs \ @builddir@/qtv From 729ac22267c36fa0b55a52ef0c9a795506d39346 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Feb 2020 15:54:45 +0900 Subject: [PATCH 0249/3664] Make qw connection sequence visible Black lines with transparent background on a black backdrop... --- doc/connect.dox | 67 +++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/doc/connect.dox b/doc/connect.dox index 44d83586a..14295294e 100644 --- a/doc/connect.dox +++ b/doc/connect.dox @@ -3,38 +3,39 @@ /** \page connection_sequence QW Connection Sequence \msc -Client,Server; -Client=>Server [label = "getchallenge\n"]; -Server=>Client [label = "c[challenge][ext]"]; -Client=>Server [label = "connect [protover] [qport] [challenge] [userinfo]"]; -Server=>Client [label = "j"]; -Client->Server [label = "[clc_stringcmd]new"]; -Server->Client [label = "[svc_serverdata][data]"]; -|||; -Client->Server [label = "[clc_stringcmd]soundlist [svcount] 0"]; ---- [label = "soundlist loop start"]; -Server->Client [label = "[svc_soundlist][data][next]"]; -Client->Server [label = "[clc_stringcmd]soundlist [svcount] [next]"]; ---- [label = "soundlist loop end"]; -Server->Client [label = "[svc_soundlist][data]0"]; -|||; -Client->Server [label = "[clc_stringcmd]modellist [svcount] 0"]; ---- [label = "modellist list loop start"]; -Server->Client [label = "[svc_modellist][data][next]"]; -Client->Server [label = "[clc_stringcmd]modellist [svcount] [next]"]; ---- [label = "modellist list loop end"]; -Server->Client [label = "[svc_modellist][data]0"]; -|||; -Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n=0] [wcsum]"]; ---- [label = "prespawn loop start"]; -Server->Client [label = "[signon buffer n][stuffcmd]prespawn..."]; -Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n]"]; ---- [label = "prespawn loop end"]; -Server->Client [label = "[signon buffer n][stuffcmd]spawn..."]; -|||; -Client->Server [label = "[clc_stringcmd]spawn [svcount] 0"]; -Server->Client [label = "[spawn info][stuffcmd]skins"]; -Client->Server [label = "[clc_stringcmd]begin [svcount]"]; -#... [label = "in game message sequence"]; +Client [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black], +Server [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client=>Server [label = "getchallenge\n", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server=>Client [label = "c[challenge][ext]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client=>Server [label = "connect [protover] [qport] [challenge] [userinfo]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server=>Client [label = "j", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client->Server [label = "[clc_stringcmd]new", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server->Client [label = "[svc_serverdata][data]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +||| [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client->Server [label = "[clc_stringcmd]soundlist [svcount] 0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +--- [label = "soundlist loop start", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server->Client [label = "[svc_soundlist][data][next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client->Server [label = "[clc_stringcmd]soundlist [svcount] [next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +--- [label = "soundlist loop end", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server->Client [label = "[svc_soundlist][data]0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +||| [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client->Server [label = "[clc_stringcmd]modellist [svcount] 0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +--- [label = "modellist list loop start", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server->Client [label = "[svc_modellist][data][next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client->Server [label = "[clc_stringcmd]modellist [svcount] [next]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +--- [label = "modellist list loop end", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server->Client [label = "[svc_modellist][data]0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +||| [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n=0] [wcsum]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +--- [label = "prespawn loop start", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server->Client [label = "[signon buffer n][stuffcmd]prespawn...", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client->Server [label = "[clc_stringcmd]prespawn [svcount] [n]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +--- [label = "prespawn loop end", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server->Client [label = "[signon buffer n][stuffcmd]spawn...", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +||| [linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client->Server [label = "[clc_stringcmd]spawn [svcount] 0", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Server->Client [label = "[spawn info][stuffcmd]skins", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +Client->Server [label = "[clc_stringcmd]begin [svcount]", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; +... [label = "in game message sequence", linecolor=white, textcolor=white, arclinecolor=white, arctextcolor=white, textbgcolor=black, arctextbgcolor=black]; \endmsc */ From 3208fce42e7b497a8cf129bc223fdc7007482814 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Feb 2020 15:27:32 +0900 Subject: [PATCH 0250/3664] Fix ambiguous image file name warnings Most of the warnings are due to a bug in doxygen (fixed in 1.8.17, but...), however some were legit due to overzealous image search paths wildly including the doxygen output tree. --- doc/quakeforge.dox.conf.in | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/quakeforge.dox.conf.in b/doc/quakeforge.dox.conf.in index 64028f578..3781f222a 100644 --- a/doc/quakeforge.dox.conf.in +++ b/doc/quakeforge.dox.conf.in @@ -937,7 +937,6 @@ EXAMPLE_RECURSIVE = NO # \image command). IMAGE_PATH = @TOPSRC@/doc \ - @builddir@ \ @builddir@/progs \ @builddir@/qtv From 6e96b91aa1b34815027f3a8a21f7443603de1ea2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Feb 2020 15:59:12 +0900 Subject: [PATCH 0251/3664] Fix a couple more optimization warnings --- libs/video/renderer/vulkan/device.c | 2 +- libs/video/renderer/vulkan/util.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 0ed7ec808..750534f53 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -59,7 +59,7 @@ #include "util.h" -static int +static int __attribute__((const)) count_bits (uint32_t val) { int bits = 0; diff --git a/libs/video/renderer/vulkan/util.h b/libs/video/renderer/vulkan/util.h index ae87b8096..41181ff9e 100644 --- a/libs/video/renderer/vulkan/util.h +++ b/libs/video/renderer/vulkan/util.h @@ -5,7 +5,7 @@ typedef struct strset_s strset_t; -int count_strings (const char * const *str); +int count_strings (const char * const *str) __attribute__((const)); void merge_strings (const char **out, const char * const *in1, const char * const *in2); void prune_strings (strset_t *strset, const char **strings, uint32_t *count); From 31501ad641a9682ea083e4e726beecf9b641fc6f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Feb 2020 10:52:47 +0900 Subject: [PATCH 0252/3664] Add some docs for linked lists Found in an old stash --- include/QF/llist.h | 62 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/include/QF/llist.h b/include/QF/llist.h index a7488b312..b9a3a0140 100644 --- a/include/QF/llist.h +++ b/include/QF/llist.h @@ -30,16 +30,28 @@ #include "QF/qtypes.h" +/** \defgroup llist Linked lists + \ingroup utils +*/ +//@{ + typedef struct llist_node_s { - struct llist_s *parent; - struct llist_node_s *prev, *next; - void *data; + struct llist_s *parent; ///< The list owning this node. + struct llist_node_s *prev; ///< The previous node in the list, or null. + struct llist_node_s *next; ///< The flowing node in the list, or null. + void *data; ///< The actual list item. } llist_node_t; typedef struct llist_s { - struct llist_node_s *start, *end, *iter; + struct llist_node_s *start; ///< The first node in the list, or null. + struct llist_node_s *end; ///< The last node in the list, or null. + struct llist_node_s *iter; + /// Function called when deleting a list item. + /// \param element The item being deleted. + /// \param userdata Pointer to user data supplied to llist_new(). void (*freedata)(void *element, void *userdata); - qboolean (*cmpdata)(const void *element, const void *comparison, void *userdata); + qboolean (*cmpdata)(const void *element, const void *comparison, + void *userdata); void *userdata; } llist_t; @@ -48,8 +60,43 @@ typedef qboolean (*llist_iterator_t)(void *element, llist_node_t *node); #define LLIST_ICAST(x) (llist_iterator_t)(x) #define LLIST_DATA(node, type) ((type *)((node)->data)) -llist_t *llist_new (void (*freedata)(void *element, void *userdata), qboolean (*cmpdata)(const void *element, const void *comparison, void *userdata), void *userdata); +/** Create a new, empty, linked list. + + \param freedata Function to call when deleting a list item. + \param cmpdata Function to call to compare two list items. It must + return true when the items are the same and false when + they differ. + \param userdata User data pointer. Set to whatever you want, it will be + passed to the \a freedata and \a cmpdata functions as + their final parameter. + \return Pointer to the list's control structure, which is to be + passed to the other functions accessing the list. +*/ +llist_t *llist_new (void (*freedata)(void *element, void *userdata), + qboolean (*cmpdata)(const void *element, + const void *comparison, + void *userdata), + void *userdata); + +/** Empty a linked list. + All of the items in the list will be deleted via the list's \a freedata + function and the list will become empty. + + \param list Pointer to the list's control structure created by + llist_new(). May be null, in which case no operation is + performed. +*/ void llist_flush (llist_t *list); + +/** Delete a linked list. + All of the items in the list will be deleted via the list's \a freedata + function and the list will be destroyed. Do not attempt to use the list + pointer after destroying the list. + + \param list Pointer to the list's control structure created by + llist_new(). May be null, in which case no operation is + performed. +*/ void llist_delete (llist_t *list); llist_node_t *llist_append (llist_t *list, void *element); llist_node_t *llist_prefix (llist_t *list, void *element); @@ -62,4 +109,7 @@ void llist_iterate (llist_t *list, llist_iterator_t iterate); void *llist_find (llist_t *list, void *comparison); llist_node_t *llist_findnode (llist_t *list, void *comparison); void *llist_createarray (llist_t *list, size_t esize); + +//@} + #endif From de64be1d67d4619af573c09ad4cfba20dd33fddf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Feb 2020 11:04:28 +0900 Subject: [PATCH 0253/3664] Show more info when dumping x11 video modes Found in an old stash. Probably the start of xrandr support. --- libs/video/targets/context_x11.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 614f83ebd..7f952aa99 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -439,19 +439,23 @@ X11_SetVidMode (int width, int height) &vidmodes); XF86VidModeGetModeLine (x_disp, x_screen, &dotclock, &orig_data); - if (developer->int_val & SYS_VID) { - Sys_Printf ("VID: %d modes\n", nummodes); - for (i = 0; i < nummodes; i++) { - Sys_Printf ("VID: %xx%d\n", vidmodes[i]->hdisplay, - vidmodes[i]->vdisplay); - } - } - + Sys_MaskPrintf (SYS_VID, "VID: %d modes\n", nummodes); + original_mode = -1; for (i = 0; i < nummodes; i++) { - if ((vidmodes[i]->hdisplay == orig_data.hdisplay) && - (vidmodes[i]->vdisplay == orig_data.vdisplay)) { + if (original_mode == -1 + && (vidmodes[i]->hdisplay == orig_data.hdisplay) && + (vidmodes[i]->vdisplay == orig_data.vdisplay)) { original_mode = i; - break; + } + if (developer->int_val & SYS_VID) { + Sys_Printf ("VID:%c%dx%d\n", + original_mode == i ? '*' : ' ', + vidmodes[i]->hdisplay, vidmodes[i]->vdisplay); + Sys_Printf ("\t%d %d %d %d:%d %d %d:%d\n", + vidmodes[i]->hsyncstart, vidmodes[i]->hsyncend, + vidmodes[i]->htotal, vidmodes[i]->hskew, + vidmodes[i]->vsyncstart, vidmodes[i]->vsyncend, + vidmodes[i]->vtotal, vidmodes[i]->flags); } } @@ -468,8 +472,10 @@ X11_SetVidMode (int width, int height) Sys_MaskPrintf (SYS_VID, "VID: Chose video mode: %dx%d\n", viddef.width, viddef.height); + if (0) { XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[best_mode]); + } vidmode_active = true; X11_SetScreenSaver (); } else { @@ -594,7 +600,7 @@ X11_RestoreVidMode (void) #ifdef HAVE_VIDMODE if (vidmode_active) { X11_RestoreScreenSaver (); - XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[original_mode]); + //XF86VidModeSwitchToMode (x_disp, x_screen, vidmodes[original_mode]); XFree (vidmodes); vidmode_active = false; } From 85a2f9f621e67b6db5691c5da01573e6671475b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Feb 2020 16:36:01 +0900 Subject: [PATCH 0254/3664] Implement descriptor stuff --- include/QF/Vulkan/descriptor.h | 123 +++++++++ include/QF/Vulkan/funclist.h | 11 + libs/video/renderer/vulkan/Makefile.am | 1 + libs/video/renderer/vulkan/descriptor.c | 342 ++++++++++++++++++++++++ 4 files changed, 477 insertions(+) create mode 100644 include/QF/Vulkan/descriptor.h create mode 100644 libs/video/renderer/vulkan/descriptor.c diff --git a/include/QF/Vulkan/descriptor.h b/include/QF/Vulkan/descriptor.h new file mode 100644 index 000000000..ced2805a1 --- /dev/null +++ b/include/QF/Vulkan/descriptor.h @@ -0,0 +1,123 @@ +#ifndef __QF_Vulkan_descriptor_h +#define __QF_Vulkan_descriptor_h + +typedef struct qfv_sampler_s { + struct qfv_device_s *device; + VkSampler sampler; +} qfv_sampler_t; + +typedef struct qfv_bindingset_s { + int numBindings; + VkDescriptorSetLayoutBinding bindings[]; +} qfv_bindingset_t; + +typedef struct qfv_descriptorsetlayout_s { + struct qfv_device_s *device; + VkDescriptorSetLayout layout; +} qfv_descriptorsetlayout_t; + +typedef struct qfv_descriptorpool_s { + struct qfv_device_s *device; + VkDescriptorPool pool; +} qfv_descriptorpool_t; + +typedef struct qfv_descriptorset_s { + struct qfv_device_s *device; + qfv_descriptorpool_t *pool; + VkDescriptorSet set; +} qfv_descriptorset_t; + +typedef struct qfv_imagedescriptorinfo_s { + qfv_descriptorset_t *descriptorset; + uint32_t binding; + uint32_t arrayElement; + VkDescriptorType type; + uint32_t numInfo; + VkDescriptorImageInfo infos[]; +} qfv_imagedescriptorinfo_t; + +typedef struct qfv_bufferdescriptorinfo_s { + qfv_descriptorset_t *descriptorset; + uint32_t binding; + uint32_t arrayElement; + VkDescriptorType type; + uint32_t numInfo; + VkDescriptorBufferInfo infos[]; +} qfv_bufferdescriptorinfo_t; + +typedef struct qfv_texelbufferdescriptorinfo_s { + qfv_descriptorset_t *descriptorset; + uint32_t binding; + uint32_t arrayElement; + VkDescriptorType type; + uint32_t numInfo; + VkBufferView infos[]; +} qfv_texelbufferdescriptorinfo_t; + +typedef struct qfv_copydescriptorinfo_s { + qfv_descriptorset_t *dstSet; + uint32_t dstBinding; + uint32_t dstArrayElement; + qfv_descriptorset_t *srcSet; + uint32_t srcBinding; + uint32_t srcArrayElement; + uint32_t descriptorCount; +} qfv_copydescriptorinfo_t; + +qfv_sampler_t *QFV_CreateSampler (struct qfv_device_s *device, + VkFilter magFilter, VkFilter minFilter, + VkSamplerMipmapMode mipmapMode, + VkSamplerAddressMode addressModeU, + VkSamplerAddressMode addressModeV, + VkSamplerAddressMode addressModeW, + float mipLodBias, + VkBool32 anisotryEnable, float maxAnisotropy, + VkBool32 compareEnable, VkCompareOp compareOp, + float minLod, float maxLod, + VkBorderColor borderColor, + VkBool32 unnormalizedCoordinates); + +qfv_bindingset_t *QFV_CreateBindingSet (int numBindings); +void QFV_DestroyBindingSet (qfv_bindingset_t *bindingset); + +qfv_descriptorsetlayout_t * +QFV_CreateDescriptorSetLayout (struct qfv_device_s *device, + qfv_bindingset_t *bindings); + +qfv_descriptorpool_t * +QFV_CreateDescriptorPool (struct qfv_device_s *device, + VkDescriptorPoolCreateFlags flags, uint32_t maxSets, + qfv_bindingset_t *bindings); + +qfv_descriptorset_t * +QFV_AllocateDescriptorSet (qfv_descriptorpool_t *pool, + qfv_descriptorsetlayout_t *layout); + +#define QFV_allocateinfo(type, num, allocator) \ + allocator (field_offset (type, infos[num])) +#define QFV_ImageDescriptorInfo(num, allocator) \ + QFV_allocateinfo(qfv_imagedescriptorinfo_t, num, allocator) +#define QFV_BufferDescriptorInfo(num, allocator) \ + QFV_allocateinfo(qfv_bufferdescriptorinfo_t, num, allocator) +#define QFV_TexelBufferDescriptorInfo(num, allocator) \ + QFV_allocateinfo(qfv_texelbufferdescriptorinfo_t, num, allocator) + +void +QFV_UpdateDescriptorSets (struct qfv_device_s *device, + uint32_t numImageInfos, + qfv_imagedescriptorinfo_t *imageInfos, + uint32_t numBufferInfos, + qfv_bufferdescriptorinfo_t *bufferInfos, + uint32_t numTexelBufferInfos, + qfv_texelbufferdescriptorinfo_t *texelbufferInfos, + uint32_t numCopyInfos, + qfv_copydescriptorinfo_t *copyInfos); + +void QFV_FreeDescriptorSet (qfv_descriptorset_t *set); +void QFV_ResetDescriptorPool (qfv_descriptorpool_t *pool); +void QFV_DestroyDescriptorPool (qfv_descriptorpool_t *pool); +void QFV_DestroyDescriptorSetLayout (qfv_descriptorsetlayout_t *layout); +void QFV_DestroySampler (qfv_sampler_t *sampler); + + +#endif//__QF_Vulkan_descriptor_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 1f00d0b54..e25188999 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -128,6 +128,17 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkMapMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkUnmapMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkFlushMappedMemoryRanges) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSampler) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateDescriptorSetLayout) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateDescriptorPool) +DEVICE_LEVEL_VULKAN_FUNCTION (vkAllocateDescriptorSets) +DEVICE_LEVEL_VULKAN_FUNCTION (vkUpdateDescriptorSets) +DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeDescriptorSets) +DEVICE_LEVEL_VULKAN_FUNCTION (vkResetDescriptorPool) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyDescriptorPool) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyDescriptorSetLayout) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySampler) + DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBufferToImage) diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index ba9b64948..ec888d6cd 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -6,6 +6,7 @@ AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES vulkan_src = \ buffer.c \ command.c \ + descriptor.c \ device.c \ image.c \ instance.c \ diff --git a/libs/video/renderer/vulkan/descriptor.c b/libs/video/renderer/vulkan/descriptor.c new file mode 100644 index 000000000..4662cb9b4 --- /dev/null +++ b/libs/video/renderer/vulkan/descriptor.c @@ -0,0 +1,342 @@ +/* + descriptor.c + + Vulkan descriptor functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +qfv_sampler_t * +QFV_CreateSampler (qfv_device_t *device, + VkFilter magFilter, VkFilter minFilter, + VkSamplerMipmapMode mipmapMode, + VkSamplerAddressMode addressModeU, + VkSamplerAddressMode addressModeV, + VkSamplerAddressMode addressModeW, + float mipLodBias, + VkBool32 anisotryEnable, float maxAnisotropy, + VkBool32 compareEnable, VkCompareOp compareOp, + float minLod, float maxLod, + VkBorderColor borderColor, + VkBool32 unnormalizedCoordinates) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkSamplerCreateInfo createInfo = { + VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, 0, + 0, + magFilter, minFilter, mipmapMode, + addressModeU, addressModeV, addressModeW, + mipLodBias, + anisotryEnable, maxAnisotropy, + compareEnable, compareOp, + minLod, maxLod, + borderColor, unnormalizedCoordinates, + }; + + qfv_sampler_t *sampler = malloc (sizeof (*sampler)); + sampler->device = device; + dfunc->vkCreateSampler (dev, &createInfo, 0, &sampler->sampler); + return sampler; +} + +qfv_bindingset_t * +QFV_CreateBindingSet (int numBindings) +{ + qfv_bindingset_t *bindingset; + bindingset = malloc (field_offset (qfv_bindingset_t, + bindings[numBindings])); + bindingset->numBindings = numBindings; + return bindingset; +} + +void +QFV_DestroyBindingSet (qfv_bindingset_t *bindingset) +{ + free (bindingset); +} + +qfv_descriptorsetlayout_t * +QFV_CreateDescriptorSetLayout (qfv_device_t *device, + qfv_bindingset_t *bindingset) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkDescriptorSetLayoutCreateInfo createInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 0, + 0, + bindingset->numBindings, bindingset->bindings, + }; + + qfv_descriptorsetlayout_t *layout = malloc (sizeof (layout)); + layout->device = device; + dfunc->vkCreateDescriptorSetLayout (dev, &createInfo, 0, &layout->layout); + return layout; +} + +// There are currently only 13 descriptor types, so 16 should be plenty +static VkDescriptorPoolSize poolsize_pool[16]; +static VkDescriptorPoolSize *poolsize_next; + +static uintptr_t +poolsize_gethash (const void *ele, void *unused) +{ + const VkDescriptorPoolSize *poolsize = ele; + return poolsize->type; +} + +static int +poolsize_compmare (const void *ele1, const void *ele2, void *unused) +{ + const VkDescriptorPoolSize *poolsize1 = ele1; + const VkDescriptorPoolSize *poolsize2 = ele2; + return poolsize1->type == poolsize2->type; +} + +//FIXME not thread-safe +qfv_descriptorpool_t * +QFV_CreateDescriptorPool (qfv_device_t *device, + VkDescriptorPoolCreateFlags flags, uint32_t maxSets, + qfv_bindingset_t *bindings) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + static hashtab_t *poolsizes; + + if (!poolsizes) { + poolsizes = Hash_NewTable (16, 0, 0, 0); + Hash_SetHashCompare (poolsizes, poolsize_gethash, poolsize_compmare); + } else { + Hash_FlushTable (poolsizes); + } + poolsize_next = poolsize_pool; + + VkDescriptorPoolSize *ps; + for (int i = 0; i < bindings->numBindings; i++) { + VkDescriptorPoolSize test = { bindings->bindings[i].descriptorType, 0 }; + ps = Hash_FindElement (poolsizes, &test); + if (!ps) { + ps = poolsize_next++; + if ((size_t) (poolsize_next - poolsize_pool) + > sizeof (poolsize_pool) / sizeof (poolsize_pool[0])) { + Sys_Error ("Too many descriptor types"); + } + Hash_AddElement (poolsizes, ps); + } + //XXX is descriptorCount correct? + //FIXME assumes only one layout is used with this pool + ps->descriptorCount += bindings->bindings[i].descriptorCount * maxSets; + } + + VkDescriptorPoolCreateInfo createInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 0, + flags, maxSets, ps - poolsize_pool, poolsize_pool, + }; + + qfv_descriptorpool_t *descriptorpool = malloc (sizeof (descriptorpool)); + descriptorpool->device = device; + dfunc->vkCreateDescriptorPool (dev, &createInfo, 0, &descriptorpool->pool); + return descriptorpool; +} + +qfv_descriptorset_t * +QFV_AllocateDescriptorSet (qfv_descriptorpool_t *pool, + qfv_descriptorsetlayout_t *layout) +{ + qfv_device_t *device = pool->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkDescriptorSetAllocateInfo allocateInfo = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 0, + pool->pool, 1, &layout->layout, + }; + + qfv_descriptorset_t *descriptorset = malloc (sizeof (*descriptorset)); + descriptorset->device = device; + descriptorset->pool = pool; + dfunc->vkAllocateDescriptorSets (dev, &allocateInfo, &descriptorset->set); + return descriptorset; +} + +void +QFV_UpdateDescriptorSets (qfv_device_t *device, + uint32_t numImageInfos, + qfv_imagedescriptorinfo_t *imageInfos, + uint32_t numBufferInfos, + qfv_bufferdescriptorinfo_t *bufferInfos, + uint32_t numTexelBufferInfos, + qfv_texelbufferdescriptorinfo_t *texelbufferInfos, + uint32_t numCopyInfos, + qfv_copydescriptorinfo_t *copyInfos) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + uint32_t numWrite = 0; + numWrite += numImageInfos; + numWrite += numBufferInfos; + numWrite += numTexelBufferInfos; + VkWriteDescriptorSet *writeSets = alloca (numWrite * sizeof (*writeSets)); + VkWriteDescriptorSet *writeSet = writeSets; + for (uint32_t i = 0; i < numImageInfos; i++, writeSet++) { + writeSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeSet->pNext = 0; + writeSet->dstSet = imageInfos[i].descriptorset->set; + writeSet->dstBinding = imageInfos[i].binding; + writeSet->dstArrayElement = imageInfos[i].arrayElement; + writeSet->descriptorCount = imageInfos[i].numInfo; + writeSet->descriptorType = imageInfos[i].type; + writeSet->pImageInfo = imageInfos[i].infos; + writeSet->pBufferInfo = 0; + writeSet->pTexelBufferView = 0; + } + for (uint32_t i = 0; i < numBufferInfos; i++, writeSet++) { + writeSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeSet->pNext = 0; + writeSet->dstSet = bufferInfos[i].descriptorset->set; + writeSet->dstBinding = bufferInfos[i].binding; + writeSet->dstArrayElement = bufferInfos[i].arrayElement; + writeSet->descriptorCount = bufferInfos[i].numInfo; + writeSet->descriptorType = bufferInfos[i].type; + writeSet->pImageInfo = 0; + writeSet->pBufferInfo = bufferInfos[i].infos; + writeSet->pTexelBufferView = 0; + } + for (uint32_t i = 0; i < numTexelBufferInfos; i++, writeSet++) { + writeSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writeSet->pNext = 0; + writeSet->dstSet = bufferInfos[i].descriptorset->set; + writeSet->dstBinding = texelbufferInfos[i].binding; + writeSet->dstArrayElement = texelbufferInfos[i].arrayElement; + writeSet->descriptorCount = texelbufferInfos[i].numInfo; + writeSet->descriptorType = texelbufferInfos[i].type; + writeSet->pImageInfo = 0; + writeSet->pBufferInfo = 0; + writeSet->pTexelBufferView = texelbufferInfos[i].infos; + } + VkCopyDescriptorSet *copySets = alloca (numWrite * sizeof (*copySets)); + VkCopyDescriptorSet *copySet = copySets; + for (uint32_t i = 0; i < numCopyInfos; i++, copySet++) { + copySet->sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; + copySet->pNext = 0; + copySet->srcSet = copyInfos[i].srcSet->set; + copySet->srcBinding = copyInfos[i].srcBinding; + copySet->srcArrayElement = copyInfos[i].srcArrayElement; + copySet->dstSet = copyInfos[i].dstSet->set; + copySet->dstBinding = copyInfos[i].dstBinding; + copySet->dstArrayElement = copyInfos[i].dstArrayElement; + copySet->descriptorCount = copyInfos[i].descriptorCount; + } + dfunc->vkUpdateDescriptorSets (dev, numWrite, writeSets, + numCopyInfos, copySets); +} + +void +QFV_FreeDescriptorSet (qfv_descriptorset_t *set) +{ + qfv_device_t *device = set->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + VkDescriptorPool pool = set->pool->pool; + + dfunc->vkFreeDescriptorSets (dev, pool, 1, &set->set); +} + +void +QFV_ResetDescriptorPool (qfv_descriptorpool_t *pool) +{ + qfv_device_t *device = pool->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkResetDescriptorPool (dev, pool->pool, 0); +} + +void +QFV_DestroyDescriptorPool (qfv_descriptorpool_t *pool) +{ + qfv_device_t *device = pool->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyDescriptorPool (dev, pool->pool, 0); +} + +void +QFV_DestroyDescriptorSetLayout (qfv_descriptorsetlayout_t *layout) +{ + qfv_device_t *device = layout->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyDescriptorSetLayout (dev, layout->layout, 0); +} + +void +QFV_DestroySampler (qfv_sampler_t *sampler) +{ + qfv_device_t *device = sampler->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroySampler (dev, sampler->sampler, 0); +} From 44f5b134e6d2589071842a4fab5f7930a59c721d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Feb 2020 18:55:22 +0900 Subject: [PATCH 0255/3664] Free custom descriptor structs Forgot this earlier --- libs/video/renderer/vulkan/descriptor.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/video/renderer/vulkan/descriptor.c b/libs/video/renderer/vulkan/descriptor.c index 4662cb9b4..d0b2031c1 100644 --- a/libs/video/renderer/vulkan/descriptor.c +++ b/libs/video/renderer/vulkan/descriptor.c @@ -319,6 +319,7 @@ QFV_DestroyDescriptorPool (qfv_descriptorpool_t *pool) qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkDestroyDescriptorPool (dev, pool->pool, 0); + free (pool); } void @@ -329,6 +330,7 @@ QFV_DestroyDescriptorSetLayout (qfv_descriptorsetlayout_t *layout) qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkDestroyDescriptorSetLayout (dev, layout->layout, 0); + free (layout); } void @@ -339,4 +341,5 @@ QFV_DestroySampler (qfv_sampler_t *sampler) qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkDestroySampler (dev, sampler->sampler, 0); + free (sampler); } From 61036378e2d7670f2de5564ee94c23bd71c2ef02 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Feb 2020 18:55:51 +0900 Subject: [PATCH 0256/3664] Implement render pass stuff --- include/QF/Vulkan/command.h | 12 ++ include/QF/Vulkan/funclist.h | 8 ++ include/QF/Vulkan/renderpass.h | 72 +++++++++++ libs/video/renderer/vulkan/Makefile.am | 1 + libs/video/renderer/vulkan/command.c | 42 +++++++ libs/video/renderer/vulkan/renderpass.c | 151 ++++++++++++++++++++++++ 6 files changed, 286 insertions(+) create mode 100644 include/QF/Vulkan/renderpass.h create mode 100644 libs/video/renderer/vulkan/renderpass.c diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 9326617ca..ffb462b98 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -92,6 +92,8 @@ void QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, struct qfv_buffer_s; struct qfv_image_s; +struct qfv_renderpass_s; +struct qfv_framebuffer_s; void QFV_CmdCopyBuffer (qfv_cmdbuffer_t *cmdBuffer, struct qfv_buffer_s *src, struct qfv_buffer_s *dst, VkBufferCopy *regions, uint32_t numRegions); @@ -107,5 +109,15 @@ void QFV_CmdCopyImageToBuffer (qfv_cmdbuffer_t *cmdBuffer, struct qfv_buffer_s *dst, VkBufferImageCopy *regions, uint32_t numRegions); +void QFV_CmdBeginRenderPass (qfv_cmdbuffer_t *cmdBuffer, + struct qfv_renderpass_s *renderPass, + struct qfv_framebuffer_s *framebuffer, + VkRect2D renderArea, + uint32_t numClearValues, + VkClearValue *clearValues, + VkSubpassContents subpassContents); +void QFV_CmdNextSubpass (qfv_cmdbuffer_t *cmdBuffer, + VkSubpassContents subpassContents); +void QFV_CmdEndRenderPass (qfv_cmdbuffer_t *cmdBuffer); #endif//__QF_Vulkan_command_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index e25188999..f51e53478 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -139,10 +139,18 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyDescriptorPool) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyDescriptorSetLayout) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySampler) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateRenderPass) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateFramebuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyRenderPass) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFramebuffer) + DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBufferToImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyImageToBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBeginRenderPass) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h new file mode 100644 index 000000000..c8fdc2965 --- /dev/null +++ b/include/QF/Vulkan/renderpass.h @@ -0,0 +1,72 @@ +#ifndef __QF_Vulkan_renderpass_h +#define __QF_Vulkan_renderpass_h + +typedef struct qfv_attachmentdescription_s { + uint32_t numAttachments; + VkAttachmentDescription attachments[]; +} qfv_attachmentdescription_t; + +#define QFV_AllocAttachmentDescription(num, allocator) \ + allocator (field_offset (qfv_attachmentdescription_t, attachments[num])) + +typedef struct qfv_attachmentreference_s { + uint32_t numReferences; + VkAttachmentReference references[]; +} qfv_attachmentreference_t; + +#define QFV_AllocAttachmentReference(num, allocator) \ + allocator (field_offset (qfv_attachmentreference_t, references[num])) + +typedef struct qfv_subpassparameters_s { + VkPipelineBindPoint pipelineBindPoint; + qfv_attachmentreference_t *inputAttachments; + qfv_attachmentreference_t *colorAttachments; + qfv_attachmentreference_t *resolveAttachments; + VkAttachmentReference *depthStencilAttachment; + uint32_t numPreserve; + uint32_t *preserveAttachments; +} qfv_subpassparameters_t; + +typedef struct qfv_subpassparametersset_s { + uint32_t numSubpasses; + qfv_subpassparameters_t subpasses[]; +} qfv_subpassparametersset_t; + +#define QFV_AllocSubpassParametersSet(num, allocator) \ + allocator (field_offset (qfv_subpassparametersset_t, subpasses[num])) + +typedef struct qfv_subpassdependency_s { + uint32_t numDependencies; + VkSubpassDependency dependencies[]; +} qfv_subpassdependency_t; + +#define QFV_AllocSubpassDependencies(num, allocator) \ + allocator (field_offset (qfv_subpassdependency_t, dependencies[num])) + +typedef struct qfv_renderpass_s { + struct qfv_device_s *device; + VkRenderPass renderPass; +} qfv_renderpass_t; + +typedef struct qfv_framebuffer_s { + struct qfv_device_s *device; + VkFramebuffer framebuffer; +} qfv_framebuffer_t; + +qfv_renderpass_t * +QFV_CreateRenderPass (struct qfv_device_s *device, + qfv_attachmentdescription_t *attachments, + qfv_subpassparametersset_t *subpasses, + qfv_subpassdependency_t *dependencies); + +struct qfv_imageview_s; +qfv_framebuffer_t * +QFV_CreateFramebuffer (qfv_renderpass_t *renderPass, + uint32_t numAttachments, + struct qfv_imageview_s **attachments, + uint32_t width, uint32_t height, uint32_t layers); + +void QFV_DestroyFramebuffer (qfv_framebuffer_t *framebuffer); +void QFV_DestroyRenderPass (qfv_renderpass_t *renderPass); + +#endif//__QF_Vulkan_renderpass_h diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index ec888d6cd..936dd504d 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -11,6 +11,7 @@ vulkan_src = \ image.c \ instance.c \ memory.c \ + renderpass.c \ swapchain.c \ util.c \ vulkan_draw.c \ diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 46c2ed83f..15e884b64 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -51,6 +51,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/buffer.h"//FIXME should QFV_CmdPipelineBarrier be here? #include "QF/Vulkan/image.h"//FIXME should QFV_CmdPipelineBarrier be here? +#include "QF/Vulkan/renderpass.h"//FIXME should QFV_CmdPipelineBarrier be here? #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" @@ -462,3 +463,44 @@ QFV_CmdCopyImageToBuffer (qfv_cmdbuffer_t *cmdBuffer, dfunc->vkCmdCopyImageToBuffer (cmdBuffer->buffer, src->image, layout, dst->buffer, numRegions, regions); } + +void +QFV_CmdBeginRenderPass (qfv_cmdbuffer_t *cmdBuffer, + qfv_renderpass_t *renderPass, + qfv_framebuffer_t *framebuffer, + VkRect2D renderArea, + uint32_t numClearValues, + VkClearValue *clearValues, + VkSubpassContents subpassContents) +{ + qfv_device_t *device = cmdBuffer->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkRenderPassBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, + renderPass->renderPass, framebuffer->framebuffer, renderArea, + numClearValues, clearValues, + }; + + dfunc->vkCmdBeginRenderPass (cmdBuffer->buffer, &beginInfo, + subpassContents); +} + +void +QFV_CmdNextSubpass (qfv_cmdbuffer_t *cmdBuffer, + VkSubpassContents subpassContents) +{ + qfv_device_t *device = cmdBuffer->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkCmdNextSubpass (cmdBuffer->buffer, subpassContents); +} + +void +QFV_CmdEndRenderPass (qfv_cmdbuffer_t *cmdBuffer) +{ + qfv_device_t *device = cmdBuffer->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkCmdEndRenderPass (cmdBuffer->buffer); +} diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c new file mode 100644 index 000000000..9c1064192 --- /dev/null +++ b/libs/video/renderer/vulkan/renderpass.c @@ -0,0 +1,151 @@ +/* + descriptor.c + + Vulkan descriptor functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/renderpass.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +qfv_renderpass_t * +QFV_CreateRenderPass (qfv_device_t *device, + qfv_attachmentdescription_t *attachments, + qfv_subpassparametersset_t *subpassparams, + qfv_subpassdependency_t *dependencies) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkSubpassDescription *subpasses = alloca (subpassparams->numSubpasses + * sizeof (*subpasses)); + + for (uint32_t i = 0; i < subpassparams->numSubpasses; i++) { + qfv_subpassparameters_t *params = &subpassparams->subpasses[i]; + subpasses[i].flags = 0; + subpasses[i].pipelineBindPoint = params->pipelineBindPoint; + subpasses[i].inputAttachmentCount = params->inputAttachments->numReferences; + subpasses[i].pInputAttachments = params->inputAttachments->references; + subpasses[i].colorAttachmentCount = params->colorAttachments->numReferences; + subpasses[i].pColorAttachments = params->colorAttachments->references; + if (params->resolveAttachments) { + subpasses[i].pResolveAttachments = params->resolveAttachments->references; + } + subpasses[i].pDepthStencilAttachment = params->depthStencilAttachment; + subpasses[i].preserveAttachmentCount = params->numPreserve; + subpasses[i].pPreserveAttachments = params->preserveAttachments; + } + + VkRenderPassCreateInfo createInfo = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 0, 0, + attachments->numAttachments, attachments->attachments, + subpassparams->numSubpasses, subpasses, + dependencies->numDependencies, dependencies->dependencies, + }; + + qfv_renderpass_t *renderpass = malloc (sizeof (*renderpass)); + renderpass->device = device; + dfunc->vkCreateRenderPass (dev, &createInfo, 0, &renderpass->renderPass); + return renderpass; +} + +qfv_framebuffer_t * +QFV_CreateFramebuffer (qfv_renderpass_t *renderPass, + uint32_t numAttachments, qfv_imageview_t **attachments, + uint32_t width, uint32_t height, uint32_t layers) +{ + qfv_device_t *device = renderPass->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkImageView *views = alloca (numAttachments * sizeof (*views)); + for (uint32_t i = 0; i < numAttachments; i++) { + views[i] = attachments[i]->view; + } + + VkFramebufferCreateInfo createInfo = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 0, 0, + renderPass->renderPass, numAttachments, views, width, height, layers, + }; + + qfv_framebuffer_t *framebuffer = malloc (sizeof (*framebuffer)); + framebuffer->device = device; + dfunc->vkCreateFramebuffer (dev, &createInfo, 0, &framebuffer->framebuffer); + return framebuffer; +} + +void +QFV_DestroyFramebuffer (qfv_framebuffer_t *framebuffer) +{ + qfv_device_t *device = framebuffer->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyFramebuffer (dev, framebuffer->framebuffer, 0); + free (framebuffer); +} + +void +QFV_DestroyRenderPass (qfv_renderpass_t *renderPass) +{ + qfv_device_t *device = renderPass->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyRenderPass (dev, renderPass->renderPass, 0); + free (renderPass); +} From 69c110193aefc07a8c1fdd9792071542c1d79050 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 13 Feb 2020 04:20:54 +0900 Subject: [PATCH 0257/3664] Fix a thinko Wrong var for computing number of slots used. --- libs/video/renderer/vulkan/descriptor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/descriptor.c b/libs/video/renderer/vulkan/descriptor.c index d0b2031c1..cc9cce6d4 100644 --- a/libs/video/renderer/vulkan/descriptor.c +++ b/libs/video/renderer/vulkan/descriptor.c @@ -188,7 +188,7 @@ QFV_CreateDescriptorPool (qfv_device_t *device, VkDescriptorPoolCreateInfo createInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 0, - flags, maxSets, ps - poolsize_pool, poolsize_pool, + flags, maxSets, poolsize_next - poolsize_pool, poolsize_pool, }; qfv_descriptorpool_t *descriptorpool = malloc (sizeof (descriptorpool)); From 53b46f05416ca3eaa8ad00180d3d0b074a60152d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 13 Feb 2020 04:21:35 +0900 Subject: [PATCH 0258/3664] Implement pipeline stuff --- include/QF/Vulkan/command.h | 4 + include/QF/Vulkan/descriptor.h | 9 + include/QF/Vulkan/funclist.h | 13 + include/QF/Vulkan/pipeline.h | 244 ++++++++++++ libs/video/renderer/vulkan/Makefile.am | 1 + libs/video/renderer/vulkan/command.c | 12 + libs/video/renderer/vulkan/pipeline.c | 525 +++++++++++++++++++++++++ 7 files changed, 808 insertions(+) create mode 100644 include/QF/Vulkan/pipeline.h create mode 100644 libs/video/renderer/vulkan/pipeline.c diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index ffb462b98..c1d54d43d 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -119,5 +119,9 @@ void QFV_CmdBeginRenderPass (qfv_cmdbuffer_t *cmdBuffer, void QFV_CmdNextSubpass (qfv_cmdbuffer_t *cmdBuffer, VkSubpassContents subpassContents); void QFV_CmdEndRenderPass (qfv_cmdbuffer_t *cmdBuffer); +struct qfv_pipeline_s; +void QFV_CmdBindPipeline (qfv_cmdbuffer_t *cmdBuffer, + VkPipelineBindPoint bindPoint, + struct qfv_pipeline_s *pipeline); #endif//__QF_Vulkan_command_h diff --git a/include/QF/Vulkan/descriptor.h b/include/QF/Vulkan/descriptor.h index ced2805a1..48a1cd92d 100644 --- a/include/QF/Vulkan/descriptor.h +++ b/include/QF/Vulkan/descriptor.h @@ -16,6 +16,15 @@ typedef struct qfv_descriptorsetlayout_s { VkDescriptorSetLayout layout; } qfv_descriptorsetlayout_t; +typedef struct qfv_descriptorsetlayoutset_s { + uint32_t numLayouts; + qfv_descriptorsetlayout_t *layouts[]; +} qfv_descriptorsetlayoutset_t; + +#define QFV_AllocDescriptorSetLayoutSet(num, allocator) \ + allocator (field_offset (qfv_descriptorsetlayoutset_t, layouts[num])) + + typedef struct qfv_descriptorpool_s { struct qfv_device_s *device; VkDescriptorPool pool; diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index f51e53478..5bacf29eb 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -144,6 +144,18 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateFramebuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFramebuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateShaderModule) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyShaderModule) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreatePipelineCache) +DEVICE_LEVEL_VULKAN_FUNCTION (vkGetPipelineCacheData) +DEVICE_LEVEL_VULKAN_FUNCTION (vkMergePipelineCaches) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyPipelineCache) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreatePipelineLayout) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyPipelineLayout) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateGraphicsPipelines) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateComputePipelines) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyPipeline) + DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBufferToImage) @@ -151,6 +163,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyImageToBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBeginRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/pipeline.h b/include/QF/Vulkan/pipeline.h new file mode 100644 index 000000000..6a532102b --- /dev/null +++ b/include/QF/Vulkan/pipeline.h @@ -0,0 +1,244 @@ +#ifndef __QF_Vulkan_pipeline_h +#define __QF_Vulkan_pipeline_h + +typedef struct qfv_shadermodule_s { + struct qfv_device_s *device; + VkShaderModule module; +} qfv_shadermodule_t; + +typedef struct qfv_shaderstageparams_s { + VkShaderStageFlagBits stageFlags; + qfv_shadermodule_t *module; + const char *entryPointName; + const VkSpecializationInfo *specializationInfo; +} qfv_shaderstageparams_t; + +typedef struct qfv_shaderstageparamsset_s { + uint32_t numParams; + qfv_shaderstageparams_t params[]; +} qfv_shaderstageparamsset_t; + +#define QFV_AllocShaderParamsSet(num, allocator) \ + allocator (field_offset (qfv_shaderstageparamsset_t, params[num])) + +typedef struct qfv_vertexinputbindingset_s { + uint32_t numBindings; + VkVertexInputBindingDescription bindings[]; +} qfv_vertexinputbindingset_t; + +#define QFV_AllocVertexInputBindingSet(num, allocator) \ + allocator (field_offset (qfv_vertexinputbindingset_t, bindings[num])) + +typedef struct qfv_vertexinputattributeset_s { + uint32_t numAttributes; + VkVertexInputAttributeDescription attributes[]; +} qfv_vertexinputattributeset_t; + +#define QFV_AllocVertexInputAttributeSet(num, allocator) \ + allocator (field_offset (qfv_vertexinputattributeset_t, bindings[num])) + +typedef struct qfv_vertexinputstate_s { + qfv_vertexinputbindingset_t *bindings; + qfv_vertexinputattributeset_t *attributes; +} qfv_vertexinputstate_t; + +typedef struct qfv_pipelineinputassembly_s { + VkPrimitiveTopology topology; + VkBool32 primativeRestartEnable; +} qfv_pipelineinputassembly_t; + +typedef struct qfv_pipelinetessellation_s { + uint32_t patchControlPoints; +} qfv_pipelinetessellation_t; + +typedef struct qfv_viewportset_s { + uint32_t numViewports; + VkViewport viewports[]; +} qfv_viewportset_t; + +#define QFV_AllocViewportSet(num, allocator) \ + allocator (field_offset (qfv_viewportset_t, viewports[num])) + +typedef struct qfv_scissorsset_s { + uint32_t numScissors; + VkRect2D scissors[]; +} qfv_scissorsset_t; + +#define QFV_AllocScissorsSet(num, allocator) \ + allocator (field_offset (qfv_scissorsset_t, scissors[num])) + +typedef struct qfv_viewportinfo_s { + qfv_viewportset_t *viewportset; + qfv_scissorsset_t *scissorsset; +} qfv_viewportinfo_t; + +typedef struct qfv_pipelinerasterization_s { + VkBool32 depthClampEnable; + VkBool32 rasterizerDiscardEnable; + VkPolygonMode polygonMode; + VkCullModeFlags cullMode; + VkFrontFace frontFace; + VkBool32 depthBiasEnable; + float depthBiasConstantFactor; + float depthBiasClamp; + float depthBiasSlopeFactor; + float lineWidth; +} qfv_pipelinerasterization_t; + +typedef struct qfv_pipelinemultisample_s { + VkSampleCountFlagBits rasterizationSamples; + VkBool32 sampleShadingEnable; + float minSampleShading; + const VkSampleMask *sampleMask; + VkBool32 alphaToCoverageEnable; + VkBool32 alphaToOneEnable; +} qfv_pipelinemultisample_t; + +typedef struct qfv_pipelinedepthandstencil_s { + VkBool32 depthTestEnable; + VkBool32 depthWriteEnable; + VkCompareOp depthCompareOp; + VkBool32 depthBoundsTestEnable; + VkBool32 stencilTestEnable; + VkStencilOpState front; + VkStencilOpState back; + float minDepthBounds; + float maxDepthBounds; +} qfv_pipelinedepthandstencil_t; + +typedef struct qfv_blendattachmentset_s { + uint32_t numAttachments; + VkPipelineColorBlendAttachmentState attachments[]; +} qfv_blendattachmentset_t; + +#define QFV_AllocBlendAttachmentSet(num, allocator) \ + allocator (field_offset (qfv_blendattachmentset_t, attachments[num])) + +typedef struct qfv_pipelineblend_s { + VkBool32 logicOpEnable; + VkLogicOp logicOp; + qfv_blendattachmentset_t *blendAttachments; + float blendConstants[4]; +} qfv_pipelineblend_t; + +typedef struct qfv_dynamicstateset_s { + uint32_t numStates; + VkDynamicState states[]; +} qfv_dynamicstateset_t; + +#define QFV_AllocDynamicStateSet(num, allocator) \ + allocator (field_offset (qfv_dynamicstateset_t, states[num])) + +typedef struct qfv_pushconstantrangeset_s { + uint32_t numRanges; + VkPushConstantRange ranges[]; +} qfv_pushconstantrangeset_t; + +#define QFV_AllocPushConstantRangeSet(num, allocator) \ + allocator (field_offset (qfv_pushconstantrangeset_t, ranges[num])) + +typedef struct qfv_pipelinelayout_s { + struct qfv_device_s *device; + VkPipelineLayout layout; +} qfv_pipelinelayout_t; + +typedef struct qfv_pipeline_s { + struct qfv_device_s *device; + VkPipeline pipeline; +} qfv_pipeline_t; + +typedef struct qfv_pipelineset_s { + uint32_t numPipelines; + qfv_pipeline_t *pipelines[]; +} qfv_pipelineset_t; + +#define QFV_AllocPipelineSet(num, allocator) \ + allocator (field_offset (qfv_pipelineset_t, pipelines[num])) + +typedef struct qfv_graphicspipelinecreateinfo_s { + VkPipelineCreateFlags flags; + qfv_shaderstageparamsset_t *stages; + qfv_vertexinputstate_t *vertexState; + qfv_pipelineinputassembly_t *inputAssemblyState; + qfv_pipelinetessellation_t *tessellationState; + qfv_viewportinfo_t *viewportState; + qfv_pipelinerasterization_t *rasterizationState; + qfv_pipelinemultisample_t *multisampleState; + qfv_pipelinedepthandstencil_t *depthStencilState; + qfv_pipelineblend_t *colorBlendState; + qfv_dynamicstateset_t *dynamicState; + qfv_pipelinelayout_t *layout; + struct qfv_renderpass_s *renderPass; + uint32_t subpass; + qfv_pipeline_t *basePipeline; + int32_t basePipelineIndex; +} qfv_graphicspipelinecreateinfo_t; + +typedef struct qfv_graphicspipelinecreateinfoset_s { + uint32_t numPipelines; + qfv_graphicspipelinecreateinfo_t *pipelines[]; +} qfv_graphicspipelinecreateinfoset_t; + +#define QFV_AllocGraphicsPipelineCreateInfoSet(num, allocator) \ + allocator (field_offset (qfv_graphicspipelinecreateinfoset_t, \ + pipelines[num])) + +typedef struct qfv_computepipelinecreateinfo_s { + VkPipelineCreateFlags flags; + qfv_shaderstageparams_t *stage; + qfv_pipelinelayout_t *layout; + qfv_pipeline_t *basePipeline; + int32_t basePipelineIndex; +} qfv_computepipelinecreateinfo_t; + +typedef struct qfv_computepipelinecreateinfoset_s { + uint32_t numPipelines; + qfv_computepipelinecreateinfo_t *pipelines[]; +} qfv_computepipelinecreateinfoset_t; + +#define QFV_AllocComputePipelineCreateInfoSet(num, allocator) \ + allocator (field_offset (qfv_computepipelinecreateinfoset_t, \ + pipelines[num])) + +typedef struct qfv_pipelinecache_s { + struct qfv_device_s *device; + VkPipelineCache cache; +} qfv_pipelinecache_t; + +typedef struct qfv_pipelinecacheset_s { + uint32_t numCaches; + qfv_pipelinecache_t *caches[]; +} qfv_pipelinecacheset_t; + +#define QFV_AllocPipelineCacheSet(num, allocator) \ + allocator (field_offset (qfv_pipelinecacheset_t, caches[num])) + +qfv_shadermodule_t *QFV_CreateShaderModule (struct qfv_device_s *device, + size_t size, const uint32_t *code); +void QFV_DestroyShaderModule (qfv_shadermodule_t *module); + +struct dstring_s; +qfv_pipelinecache_t *QFV_CreatePipelineCache (struct qfv_device_s *device, + struct dstring_s *cacheData); +struct dstring_s *QFV_GetPipelineCacheData (qfv_pipelinecache_t *cache); +void QFV_MergePipelineCaches (qfv_pipelinecache_t *targetCache, + qfv_pipelinecacheset_t *sourceCaches); +void QFV_DestroyPipelineCache (qfv_pipelinecache_t *cache); + +struct qfv_descriptorsetlayoutset_s; +qfv_pipelinelayout_t * +QFV_CreatePipelineLayout (struct qfv_device_s *device, + struct qfv_descriptorsetlayoutset_s *layouts, + qfv_pushconstantrangeset_t *pushConstants); +void QFV_DestroyPipelineLayout (qfv_pipelinelayout_t *layout); +qfv_pipelineset_t * +QFV_CreateGraphicsPipelines (struct qfv_device_s *device, + qfv_pipelinecache_t *cache, + qfv_graphicspipelinecreateinfoset_t *gpciSet); +qfv_pipelineset_t * +QFV_CreateComputePipelines (struct qfv_device_s *device, + qfv_pipelinecache_t *cache, + qfv_computepipelinecreateinfoset_t *cpciSet); +void QFV_DestroyPipeline (qfv_pipeline_t *pipeline); + +#endif//__QF_Vulkan_pipeline_h diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index 936dd504d..707b6b064 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -11,6 +11,7 @@ vulkan_src = \ image.c \ instance.c \ memory.c \ + pipeline.c \ renderpass.c \ swapchain.c \ util.c \ diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 15e884b64..09621ede5 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -52,6 +52,7 @@ #include "QF/Vulkan/buffer.h"//FIXME should QFV_CmdPipelineBarrier be here? #include "QF/Vulkan/image.h"//FIXME should QFV_CmdPipelineBarrier be here? #include "QF/Vulkan/renderpass.h"//FIXME should QFV_CmdPipelineBarrier be here? +#include "QF/Vulkan/pipeline.h"//FIXME should QFV_CmdPipelineBarrier be here? #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" @@ -504,3 +505,14 @@ QFV_CmdEndRenderPass (qfv_cmdbuffer_t *cmdBuffer) dfunc->vkCmdEndRenderPass (cmdBuffer->buffer); } + +void +QFV_CmdBindPipeline (qfv_cmdbuffer_t *cmdBuffer, + VkPipelineBindPoint bindPoint, + qfv_pipeline_t *pipeline) +{ + qfv_device_t *device = cmdBuffer->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkCmdBindPipeline (cmdBuffer->buffer, bindPoint, pipeline->pipeline); +} diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c new file mode 100644 index 000000000..168ec100d --- /dev/null +++ b/libs/video/renderer/vulkan/pipeline.c @@ -0,0 +1,525 @@ +/* + pipeline.c + + Vulkan pipeline functions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/pipeline.h" +#include "QF/Vulkan/renderpass.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +qfv_shadermodule_t * +QFV_CreateShaderModule (qfv_device_t *device, + size_t size, const uint32_t *code) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkShaderModuleCreateInfo createInfo = { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 0, 0, + size, code, + }; + + qfv_shadermodule_t *module = malloc (sizeof (*module)); + module->device = device; + dfunc->vkCreateShaderModule (dev, &createInfo, 0, &module->module); + return module; +} + +void +QFV_DestroyShaderModule (qfv_shadermodule_t *module) +{ + qfv_device_t *device = module->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyShaderModule (dev, module->module, 0); + free (module); +} + +qfv_pipelinecache_t * +QFV_CreatePipelineCache (qfv_device_t *device, dstring_t *cacheData) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkPipelineCacheCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, 0, 0, + cacheData->size, cacheData->str, + }; + + qfv_pipelinecache_t *cache = malloc (sizeof (*cache)); + cache->device = device; + dfunc->vkCreatePipelineCache (dev, &createInfo, 0, &cache->cache); + return cache; +} + +dstring_t * +QFV_GetPipelineCacheData (qfv_pipelinecache_t *cache) +{ + qfv_device_t *device = cache->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + dstring_t *cacheData = dstring_new (); + + dfunc->vkGetPipelineCacheData (dev, cache->cache, &cacheData->size, 0); + dstring_adjust (cacheData); + dfunc->vkGetPipelineCacheData (dev, cache->cache, &cacheData->size, + cacheData->str); + return cacheData; +} + +void +QFV_MergePipelineCaches (qfv_pipelinecache_t *targetCache, + qfv_pipelinecacheset_t *sourceCaches) +{ + qfv_device_t *device = targetCache->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + VkPipelineCache *srcCaches = alloca (sourceCaches->numCaches + * sizeof (*srcCaches)); + for (uint32_t i = 0; i < sourceCaches->numCaches; i++) { + srcCaches[i] = sourceCaches->caches[i]->cache; + } + dfunc->vkMergePipelineCaches (dev, targetCache->cache, + sourceCaches->numCaches, srcCaches); +} + +void +QFV_DestroyPipelineCache (qfv_pipelinecache_t *cache) +{ + qfv_device_t *device = cache->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyPipelineCache (dev, cache->cache, 0); +} + +qfv_pipelinelayout_t * +QFV_CreatePipelineLayout (qfv_device_t *device, + qfv_descriptorsetlayoutset_t *layoutset, + qfv_pushconstantrangeset_t *pushConstants) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + uint32_t numLayouts = layoutset->numLayouts; + VkDescriptorSetLayout *layouts = alloca (numLayouts * sizeof (*layouts)); + + for (uint32_t i = 0; i < numLayouts; i++) { + layouts[i] = layoutset->layouts[i]->layout; + } + + VkPipelineLayoutCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 0, 0, + numLayouts, layouts, pushConstants->numRanges, pushConstants->ranges, + }; + + qfv_pipelinelayout_t *layout = malloc (sizeof (layout)); + layout->device = device; + dfunc->vkCreatePipelineLayout (dev, &createInfo, 0, &layout->layout); + return layout; +} + +void +QFV_DestroyPipelineLayout (qfv_pipelinelayout_t *layout) +{ + qfv_device_t *device = layout->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyPipelineLayout (dev, layout->layout, 0); + free (layout); +} + +static VkPipelineShaderStageCreateInfo +shaderStageCI (qfv_shaderstageparams_t params) +{ + VkPipelineShaderStageCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 0, 0, + params.stageFlags, params.module->module, + params.entryPointName, params.specializationInfo, + }; + return createInfo; +} + +static VkPipelineVertexInputStateCreateInfo +vertexInputSCI (qfv_vertexinputstate_t vertexState) +{ + VkPipelineVertexInputStateCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 0, 0, + vertexState.bindings->numBindings, + vertexState.bindings->bindings, + vertexState.attributes->numAttributes, + vertexState.attributes->attributes, + }; + return createInfo; +} + +static VkPipelineInputAssemblyStateCreateInfo +inputAssemblySCI (qfv_pipelineinputassembly_t inputAssemblyState) +{ + VkPipelineInputAssemblyStateCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 0, 0, + inputAssemblyState.topology, + inputAssemblyState.primativeRestartEnable, + }; + return createInfo; +} + +static VkPipelineTessellationStateCreateInfo +tessellationSCI (qfv_pipelinetessellation_t tessellationState) +{ + VkPipelineTessellationStateCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, 0, 0, + tessellationState.patchControlPoints + }; + return createInfo; +} + +static VkPipelineViewportStateCreateInfo +viewportSCI (qfv_viewportinfo_t viewportState) +{ + VkPipelineViewportStateCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 0, 0, + viewportState.viewportset->numViewports, + viewportState.viewportset->viewports, + viewportState.scissorsset->numScissors, + viewportState.scissorsset->scissors, + }; + return createInfo; +} + +static VkPipelineRasterizationStateCreateInfo +rasterizationSCI (qfv_pipelinerasterization_t rasterizationState) +{ + VkPipelineRasterizationStateCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 0, 0, + rasterizationState.depthClampEnable, + rasterizationState.rasterizerDiscardEnable, + rasterizationState.polygonMode, + rasterizationState.cullMode, + rasterizationState.frontFace, + rasterizationState.depthBiasEnable, + rasterizationState.depthBiasConstantFactor, + rasterizationState.depthBiasClamp, + rasterizationState.depthBiasSlopeFactor, + rasterizationState.lineWidth, + }; + return createInfo; +} + +static VkPipelineMultisampleStateCreateInfo +multisampleSCI (qfv_pipelinemultisample_t multisampleState) +{ + VkPipelineMultisampleStateCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 0, 0, + multisampleState.rasterizationSamples, + multisampleState.sampleShadingEnable, + multisampleState.minSampleShading, + multisampleState.sampleMask, + multisampleState.alphaToCoverageEnable, + multisampleState.alphaToOneEnable, + }; + return createInfo; +} + +static VkPipelineDepthStencilStateCreateInfo +depthStencilSCI (qfv_pipelinedepthandstencil_t depthStencilState) +{ + VkPipelineDepthStencilStateCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 0, 0, + depthStencilState.depthTestEnable, + depthStencilState.depthWriteEnable, + depthStencilState.depthCompareOp, + depthStencilState.depthBoundsTestEnable, + depthStencilState.stencilTestEnable, + depthStencilState.front, + depthStencilState.back, + depthStencilState.minDepthBounds, + depthStencilState.maxDepthBounds, + }; + return createInfo; +} + +static VkPipelineColorBlendStateCreateInfo +colorBlendSCI (qfv_pipelineblend_t colorBlendState) +{ + VkPipelineColorBlendStateCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 0, 0, + colorBlendState.logicOpEnable, + colorBlendState.logicOp, + colorBlendState.blendAttachments->numAttachments, + colorBlendState.blendAttachments->attachments, + { + colorBlendState.blendConstants[0], + colorBlendState.blendConstants[1], + colorBlendState.blendConstants[2], + colorBlendState.blendConstants[3], + }, + }; + return createInfo; +} + +static VkPipelineDynamicStateCreateInfo +dynamicSCI (qfv_dynamicstateset_t *dynamicState) +{ + VkPipelineDynamicStateCreateInfo createInfo = { + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 0, 0, + dynamicState->numStates, dynamicState->states, + }; + return createInfo; +} + +qfv_pipelineset_t * +QFV_CreateGraphicsPipelines (qfv_device_t *device, + qfv_pipelinecache_t *cache, + qfv_graphicspipelinecreateinfoset_t *gpciSet) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + uint32_t numPipelines = gpciSet->numPipelines; + uint32_t stageCount = 0; + for (uint32_t i = 0; i < numPipelines; i++) { + stageCount += gpciSet->pipelines[i]->stages->numParams; + } + + size_t blockSize = numPipelines + * (sizeof (VkGraphicsPipelineCreateInfo) + + sizeof (VkPipelineVertexInputStateCreateInfo) + + sizeof (VkPipelineInputAssemblyStateCreateInfo) + + sizeof (VkPipelineTessellationStateCreateInfo) + + sizeof (VkPipelineViewportStateCreateInfo) + + sizeof (VkPipelineRasterizationStateCreateInfo) + + sizeof (VkPipelineMultisampleStateCreateInfo) + + sizeof (VkPipelineDepthStencilStateCreateInfo) + + sizeof (VkPipelineColorBlendStateCreateInfo) + + sizeof (VkPipelineDynamicStateCreateInfo)) + + stageCount * sizeof (VkPipelineShaderStageCreateInfo); + VkGraphicsPipelineCreateInfo *pipelineInfos = malloc (blockSize); + + pipelineInfos->pStages = (void *)(pipelineInfos + numPipelines); + pipelineInfos->pVertexInputState + = (void *)(pipelineInfos->pStages + stageCount); + pipelineInfos->pInputAssemblyState + = (void *)(pipelineInfos->pVertexInputState + numPipelines); + pipelineInfos->pTessellationState + = (void *)(pipelineInfos->pInputAssemblyState + numPipelines); + pipelineInfos->pViewportState + = (void *)(pipelineInfos->pTessellationState + numPipelines); + pipelineInfos->pRasterizationState + = (void *)(pipelineInfos->pViewportState + numPipelines); + pipelineInfos->pMultisampleState + = (void *)(pipelineInfos->pRasterizationState + numPipelines); + pipelineInfos->pDepthStencilState + = (void *)(pipelineInfos->pMultisampleState + numPipelines); + pipelineInfos->pColorBlendState + = (void *)(pipelineInfos->pDepthStencilState + numPipelines); + pipelineInfos->pDynamicState + = (void *)(pipelineInfos->pColorBlendState + numPipelines); + for (uint32_t i = 1; i < gpciSet->numPipelines; i++) { + pipelineInfos[i].pStages = pipelineInfos[i - 1].pStages + + gpciSet->pipelines[i - 1]->stages->numParams; + pipelineInfos[i].pVertexInputState + = pipelineInfos[i - 1].pVertexInputState + 1; + pipelineInfos[i].pInputAssemblyState + = pipelineInfos[i - 1].pInputAssemblyState + 1; + pipelineInfos[i].pTessellationState + = pipelineInfos[i - 1].pTessellationState + 1; + pipelineInfos[i].pViewportState + = pipelineInfos[i - 1].pViewportState + 1; + pipelineInfos[i].pRasterizationState + = pipelineInfos[i - 1].pRasterizationState + 1; + pipelineInfos[i].pMultisampleState + = pipelineInfos[i - 1].pMultisampleState + 1; + pipelineInfos[i].pDepthStencilState + = pipelineInfos[i - 1].pDepthStencilState + 1; + pipelineInfos[i].pColorBlendState + = pipelineInfos[i - 1].pColorBlendState + 1; + pipelineInfos[i].pDynamicState + = pipelineInfos[i - 1].pDynamicState + 1; + } + for (uint32_t i = 0; i < gpciSet->numPipelines; i++) { + VkGraphicsPipelineCreateInfo *gci = pipelineInfos + i; + qfv_graphicspipelinecreateinfo_t *ci = gpciSet->pipelines[i]; + gci->sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + gci->pNext = 0; + gci->flags = ci->flags; + gci->stageCount = ci->stages->numParams; + for (uint32_t j = 0; j < gci->stageCount; j++) { + ((VkPipelineShaderStageCreateInfo *)gci->pStages)[i] = shaderStageCI (ci->stages->params[j]); + } + if (ci->vertexState) { + *(VkPipelineVertexInputStateCreateInfo *)gci->pVertexInputState = vertexInputSCI (*ci->vertexState); + } else { + gci->pVertexInputState = 0; + } + if (ci->inputAssemblyState) { + *(VkPipelineInputAssemblyStateCreateInfo *)gci->pInputAssemblyState = inputAssemblySCI (*ci->inputAssemblyState); + } else { + gci->pInputAssemblyState = 0; + } + if (ci->tessellationState) { + *(VkPipelineTessellationStateCreateInfo *)gci->pTessellationState = tessellationSCI (*ci->tessellationState); + } else { + gci->pTessellationState = 0; + } + if (ci->viewportState) { + *(VkPipelineViewportStateCreateInfo *)gci->pViewportState = viewportSCI (*ci->viewportState); + } else { + gci->pViewportState = 0; + } + if (ci->rasterizationState) { + *(VkPipelineRasterizationStateCreateInfo *)gci->pRasterizationState = rasterizationSCI (*ci->rasterizationState); + } else { + gci->pRasterizationState = 0; + } + if (ci->multisampleState) { + *(VkPipelineMultisampleStateCreateInfo *)gci->pMultisampleState = multisampleSCI (*ci->multisampleState); + } else { + gci->pMultisampleState = 0; + } + if (ci->depthStencilState) { + *(VkPipelineDepthStencilStateCreateInfo *)gci->pDepthStencilState = depthStencilSCI (*ci->depthStencilState); + } else { + gci->pDepthStencilState = 0; + } + if (ci->colorBlendState) { + *(VkPipelineColorBlendStateCreateInfo *)gci->pColorBlendState = colorBlendSCI (*ci->colorBlendState); + } else { + gci->pColorBlendState = 0; + } + if (ci->dynamicState) { + *(VkPipelineDynamicStateCreateInfo *)gci->pDynamicState = dynamicSCI (ci->dynamicState); + } else { + gci->pDynamicState = 0; + } + gci->layout = ci->layout->layout; + gci->renderPass = ci->renderPass->renderPass; + gci->subpass = ci->subpass; + gci->basePipelineHandle = ci->basePipeline->pipeline; + gci->basePipelineIndex = ci->basePipelineIndex; + } + + VkPipeline *pipelines = alloca (numPipelines * sizeof (pipelines)); + dfunc->vkCreateGraphicsPipelines (dev, cache->cache, + numPipelines, pipelineInfos, 0, + pipelines); + + qfv_pipelineset_t *pipelineset = QFV_AllocPipelineSet (numPipelines, malloc); + pipelineset->numPipelines = numPipelines; + for (uint32_t i = 0; i < numPipelines; i++) { + pipelineset->pipelines[i] = malloc (sizeof (qfv_pipeline_t)); + pipelineset->pipelines[i]->device = device; + pipelineset->pipelines[i]->pipeline = pipelines[i]; + } + return pipelineset; +} + +qfv_pipelineset_t * +QFV_CreateComputePipelines (qfv_device_t *device, + qfv_pipelinecache_t *cache, + qfv_computepipelinecreateinfoset_t *cpciSet) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + uint32_t numPipelines = cpciSet->numPipelines; + + size_t blockSize = numPipelines * (sizeof (VkComputePipelineCreateInfo)); + VkComputePipelineCreateInfo *pipelineInfos = malloc (blockSize); + + for (uint32_t i = 0; i < cpciSet->numPipelines; i++) { + VkComputePipelineCreateInfo *cci = pipelineInfos + i; + qfv_computepipelinecreateinfo_t *ci = cpciSet->pipelines[i]; + cci->sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + cci->pNext = 0; + cci->flags = ci->flags; + cci->stage = shaderStageCI (*ci->stage); + cci->layout = ci->layout->layout; + cci->basePipelineHandle = ci->basePipeline->pipeline; + cci->basePipelineIndex = ci->basePipelineIndex; + } + + VkPipeline *pipelines = alloca (numPipelines * sizeof (pipelines)); + dfunc->vkCreateComputePipelines (dev, cache->cache, + numPipelines, pipelineInfos, 0, + pipelines); + + qfv_pipelineset_t *pipelineset = QFV_AllocPipelineSet (numPipelines, malloc); + pipelineset->numPipelines = numPipelines; + for (uint32_t i = 0; i < numPipelines; i++) { + pipelineset->pipelines[i] = malloc (sizeof (qfv_pipeline_t)); + pipelineset->pipelines[i]->device = device; + pipelineset->pipelines[i]->pipeline = pipelines[i]; + } + return pipelineset; +} + +void +QFV_DestroyPipeline (qfv_pipeline_t *pipeline) +{ + qfv_device_t *device = pipeline->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyPipeline (dev, pipeline->pipeline, 0); +} From d56f88f779e9abbf52173a5fc4af48de057eb00c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 11:11:27 +0900 Subject: [PATCH 0259/3664] Implement swapchain image acquisition --- include/QF/Vulkan/swapchain.h | 5 +++++ libs/video/renderer/vulkan/swapchain.c | 28 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/QF/Vulkan/swapchain.h b/include/QF/Vulkan/swapchain.h index cd9323009..1a9abb896 100644 --- a/include/QF/Vulkan/swapchain.h +++ b/include/QF/Vulkan/swapchain.h @@ -13,5 +13,10 @@ struct vulkan_ctx_s; qfv_swapchain_t *QFV_CreateSwapchain (struct vulkan_ctx_s *ctx, VkSwapchainKHR old_swapchain); void QFV_DestroySwapchain (qfv_swapchain_t *swapchain); +struct qfv_semaphore_s; +struct qfv_fence_s; +int QFV_AcquireNextImage (qfv_swapchain_t *swapchain, + struct qfv_semaphore_s *semaphore, + struct qfv_fence_s *fence, uint32_t *imageIndex); #endif//__QF_Vulkan_swapchain_h diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index bae8e4ff4..b32e3b3ed 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -11,6 +11,7 @@ #include "QF/sys.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/cvars.h" +#include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/swapchain.h" @@ -157,3 +158,30 @@ QFV_DestroySwapchain (qfv_swapchain_t *swapchain) dfunc->vkDestroySwapchainKHR (dev, swapchain->swapchain, 0); free (swapchain); } + +int +QFV_AcquireNextImage (qfv_swapchain_t *swapchain, qfv_semaphore_t *semaphore, + qfv_fence_t *fence, uint32_t *imageIndex) +{ + qfv_device_t *device = swapchain->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + uint64_t timeout = 2000000000; + VkSemaphore sem = semaphore ? semaphore->semaphore : VK_NULL_HANDLE; + VkFence fnc = fence ? fence->fence : VK_NULL_HANDLE; + *imageIndex = ~0u; + VkResult res = dfunc->vkAcquireNextImageKHR (dev, swapchain->swapchain, + timeout, sem, fnc, + imageIndex); + switch (res) { + case VK_SUCCESS: + case VK_TIMEOUT: + case VK_NOT_READY: + return 1; + case VK_SUBOPTIMAL_KHR: + case VK_ERROR_OUT_OF_DATE_KHR: + return 0; + default: + Sys_Error ("vkAcquireNextImageKHR failed: %d", res); + } +} From 8654ac44bb5736272f8f5e4c85de36d6b61779d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 16:34:14 +0900 Subject: [PATCH 0260/3664] Fix incorrect struct forward declaraction --- include/QF/Vulkan/command.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index c1d54d43d..7f28e7c88 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -79,9 +79,9 @@ int QFV_QueueSubmit (struct qfv_queue_s *queue, qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence); int QFV_QueueWaitIdle (struct qfv_queue_s *queue); -struct qfv_memorybarrierset_s *memBarriers; -struct qfv_bufferbarrierset_s *buffBarriers; -struct qfv_imagebarrierset_s *imgBarriers; +struct qfv_memorybarrierset_s; +struct qfv_bufferbarrierset_s; +struct qfv_imagebarrierset_s; void QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, From c50dda1d08b2a32c9dc2c1ab489c2a02848a7ffe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Feb 2020 10:40:38 +0900 Subject: [PATCH 0261/3664] Document segmented text --- include/QF/segtext.h | 92 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 5 deletions(-) diff --git a/include/QF/segtext.h b/include/QF/segtext.h index 1c781fcb9..79020356c 100644 --- a/include/QF/segtext.h +++ b/include/QF/segtext.h @@ -31,28 +31,110 @@ #ifndef __QF_segtext_h #define __QF_segtext_h -/** \defgroup segtext Segmented text files. +/** \defgroup segtext Segmented text files \ingroup utils - Based on The OpenGL Shader Wrangler: http://prideout.net/blog/?p=11 + Based on The OpenGL Shader Wrangler: + https://prideout.net/blog/old/blog/index.html@p=11.html + However, nothing is assumed about any of the segments: they are all nothing + more than chunks of mostly random (lines cannot start with --) text with + identifying tags. Also, the identifying tag represents only the shader_key + of OpenGL Shader Wrangler's Effect.shader_key identifier. */ +///@{ +/** Represent a single text segment + + Segments are separated by lines beginning with "--" (without the quotes). + + The first word ([A-Za-z0-9_.]+) following the double-hyphen is used as an + identifying tag for the segment. Whitespace and any additional characters + are ignored. + + The segment itself starts on the following line. +*/ typedef struct segchunk_s { struct segchunk_s *next; - const char *tag; - const char *text; - int start_line; + const char *tag; ///< identifying tag or null if no tag + const char *text; ///< nul-terminated string holding the segment + int start_line; ///< line number for first line of the segment } segchunk_t; +/** Container for all the segments extracted from the provided text + + The first segment has no tag and may or may not be empty. + Segments are stored sequentially in \a chunk_list are indexed by + identifying tag (if present) in \a tab. + Segments that have no identifying tag are not in \a tab, but can + be accessed by walking \a chunk_list its \a next field. +*/ typedef struct segtext_s { struct segtext_s *next; segchunk_t *chunk_list; struct hashtab_s *tab; } segtext_t; +/** Parse a nul-terminated string into (optionally) tagged segments + + The segments are separated by lines beginning with a double-hyphen ("--"), + with an optional tag following the double-hyphen on the same line. Valid + tag characters are ASCII alpha-numerics, "." and "_". Whitespace is ignored + and invalid characters are treated as whitespace. Only the first tag on the + line is significant. + + \param src nul-terminated string to be parsed into segments + \return Pointer to container of parsed segments. Can be freed using + Segtext_delete(). +*/ segtext_t *Segtext_new (const char *src); +/** Free a segmented text container created by Segtext_new() + + \param st Pointer to segmented text container to be freed. Must have been + created by Segtext_new(). +*/ void Segtext_delete (segtext_t *st); +/** Find a text segment via its identifying tag + + Like OpenGL Shader Wrangler, the segment tag does not have to be a perfect + match with the specified tag: the segment with the longest string of + sub-tags matching the leading subtags of the specified tag is selected. + Tags are logically broken into sub-tag by the "." character. Thus in a + collection of segments with tags "foo" and "foo.b", "foo.bar" will find the + segment tagged "foo". However, if a segment tagged "foo.bar" is present, it + will be returned. A segment tagged "foo.bar.baz" will not. + + \param st Pointer to segmented text container + \param tag String specifying the tag identifying the segment to be + returned. Valid tag characters are alphanumerics, "_" and "." + (ie, [A-Za-z0-9._]). "." is used as a sub-tag separator for + partial matches. + \return Pointer to segment data block with the best matching tag, + providing access to the segment's tag and starting line number, + as well as the segment contents. Null if no matching tag was + found. +*/ const segchunk_t *Segtext_FindChunk (const segtext_t *st, const char *tag); + +/** Find a text segment via its identifying tag + + Like OpenGL Shader Wrangler, the segment tag does not have to be a perfect + match with the specified tag: the segment with the longest string of + sub-tags matching the leading subtags of the specified tag is selected. + Tags are logically broken into sub-tag by the "." character. Thus in a + collection of segments with tags "foo" and "foo.b", "foo.bar" will find the + segment tagged "foo". However, if a segment tagged "foo.bar" is present, it + will be returned. A segment tagged "foo.bar.baz" will not. + + \param st Pointer to segmented text container + \param tag String specifying the tag identifying the segment to be + returned. Valid tag characters are alphanumerics, "_" and "." + (ie, [A-Za-z0-9._]). "." is used as a sub-tag separator for + partial matches. + \return Contents of the segment with the best matching tag, or null if + no matching tag was found. +*/ const char *Segtext_Find (const segtext_t *st, const char *tag); +///@} + #endif//__QF_segtext_h From 197f856a3012186706a071a09a5cf45e2c26db06 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 10:27:38 +0900 Subject: [PATCH 0262/3664] Fix incorrect scalar/quaternion division It's just not possible. --- tools/qfcc/source/expr_binary.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 2029726af..103cd1e7d 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -86,7 +86,6 @@ static expr_type_t float_vector[] = { static expr_type_t float_quat[] = { {'*', &type_quaternion}, - {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; @@ -170,7 +169,7 @@ static expr_type_t pointer_integer[] = { static expr_type_t quat_float[] = { {'*', &type_quaternion}, - {'/', &type_quaternion}, + {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; @@ -190,7 +189,7 @@ static expr_type_t quat_quat[] = { static expr_type_t quat_integer[] = { {'*', &type_quaternion, 0, &type_float}, - {'/', &type_quaternion, 0, &type_float}, + {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; #define quat_uinteger quat_integer @@ -228,7 +227,6 @@ static expr_type_t integer_pointer[] = { static expr_type_t integer_quat[] = { {'*', &type_quaternion, &type_float, 0}, - {'/', &type_quaternion, &type_float, 0}, {0, 0} }; @@ -478,7 +476,7 @@ static expr_type_t *field_x[] = { 0, // ev_short }; -static expr_type_t *funcx[] = { +static expr_type_t *func_x[] = { 0, // ev_void 0, // ev_string 0, // ev_float @@ -575,7 +573,7 @@ static expr_type_t **binary_expr_types[] = { vector_x, entity_x, field_x, - funcx, + func_x, pointer_x, quat_x, integer_x, From 16f8dca72e8772ca50c968599bfa18ce34966e56 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 10:56:25 +0900 Subject: [PATCH 0263/3664] Align local and far data spaces I plan on adding doubles, and so it's necessary to ensure that attempts to align doubles in local or far data spaces remain aligned after final linking. --- tools/qfcc/source/obj_file.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 10ca126f9..e0b6c668f 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -795,6 +795,14 @@ qfo_relocate_refs (qfo_t *qfo) } } +static unsigned +align_globals_size (unsigned size) +{ + if (options.code.progsversion == PROG_ID_VERSION) + return size; + return RUP (size, 16 / sizeof (pr_type_t)); +} + dprograms_t * qfo_to_progs (qfo_t *qfo, int *size) { @@ -811,6 +819,7 @@ qfo_to_progs (qfo_t *qfo, int *size) dprograms_t *progs; qfo_def_t *types_def = 0; unsigned i, j; + unsigned near_data_size = 0; unsigned locals_size = 0; int locals_start; unsigned big_locals = 0; @@ -827,9 +836,8 @@ qfo_to_progs (qfo_t *qfo, int *size) progs->numfunctions = qfo->num_funcs + 1; progs->numstrings = qfo->spaces[qfo_strings_space].data_size; progs->numglobals = qfo->spaces[qfo_near_data_space].data_size; - progs->numglobals += qfo->spaces[qfo_far_data_space].data_size; - progs->numglobals += qfo->spaces[qfo_type_space].data_size; - locals_start = qfo->spaces[qfo_near_data_space].data_size; + progs->numglobals = align_globals_size (progs->numglobals); + locals_start = progs->numglobals; for (i = qfo_num_spaces; i < qfo->num_spaces; i++) { if (options.code.local_merging) { if (locals_size < qfo->spaces[i].data_size) { @@ -837,11 +845,14 @@ qfo_to_progs (qfo_t *qfo, int *size) big_locals = i; } } else { - locals_size += qfo->spaces[i].data_size; + locals_size += align_globals_size (qfo->spaces[i].data_size); } } progs->numglobals += locals_size; + near_data_size = progs->numglobals; progs->numglobals = RUP (progs->numglobals, 16 / sizeof (pr_type_t)); + progs->numglobals += qfo->spaces[qfo_far_data_space].data_size; + progs->numglobals += qfo->spaces[qfo_type_space].data_size; progs->entityfields = qfo->spaces[qfo_entity_space].data_size; *size += progs->numstatements * sizeof (dstatement_t); *size += progs->numglobaldefs * sizeof (ddef_t); @@ -902,7 +913,7 @@ qfo_to_progs (qfo_t *qfo, int *size) for (j = 0; j < space->num_defs; j++) space->defs[j].offset += locals_start; if (!options.code.local_merging) - locals_start += df->locals; + locals_start += align_globals_size (df->locals); df->profile = 0; df->s_name = qf->name; df->s_file = qf->file; @@ -978,8 +989,7 @@ qfo_to_progs (qfo_t *qfo, int *size) printf ("%6i global defs\n", progs->numglobaldefs); printf ("%6i fielddefs\n", progs->numfielddefs); printf ("%6i globals\n", progs->numglobals); - printf (" %6i near globals\n", - qfo->spaces[qfo_near_data_space].data_size + locals_size); + printf (" %6i near globals\n", near_data_size); printf (" %6i locals size%s\n", locals_size, big_function); printf (" %6i far globals\n", qfo->spaces[qfo_far_data_space].data_size); From 13b608f40c890578a5805b5f1127306eb1d590b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 13:54:26 +0900 Subject: [PATCH 0264/3664] Don't truncat float % float This allows full usage, eg, x % pi, but otherwise maintains compatibility with integer % --- libs/gamecode/pr_exec.c | 6 +++++- tools/qfcc/source/expr_binary.c | 26 ++++---------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 56d5b0401..27c3f9c50 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1337,7 +1337,11 @@ op_call: OPC.integer_var = OPA.integer_var % OPB.integer_var; break; case OP_MOD_F: - OPC.float_var = (int) OPA.float_var % (int) OPB.float_var; + { + float a = OPA.float_var; + float b = OPB.float_var; + OPC.float_var = a - b * truncf (a / b); + } break; case OP_CONV_IF: OPC.float_var = OPA.integer_var; diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 103cd1e7d..6dd7c1177 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -628,32 +628,14 @@ reimplement_binary_expr (int op, expr_t *e1, expr_t *e2) switch (op) { case '%': { - expr_t *tmp1, *tmp2, *tmp3, *tmp4, *t1, *t2; + expr_t *tmp1, *tmp2; e = new_block_expr (); - t1 = new_temp_def_expr (&type_float); - t2 = new_temp_def_expr (&type_float); tmp1 = new_temp_def_expr (&type_float); tmp2 = new_temp_def_expr (&type_float); - tmp3 = new_temp_def_expr (&type_float); - tmp4 = new_temp_def_expr (&type_float); - append_expr (e, assign_expr (t1, e1)); - e1 = binary_expr ('&', t1, t1); - append_expr (e, assign_expr (tmp1, e1)); - - append_expr (e, assign_expr (t2, e2)); - e2 = binary_expr ('&', t2, t2); - append_expr (e, assign_expr (tmp2, e2)); - - e1 = binary_expr ('/', tmp1, tmp2); - append_expr (e, assign_expr (tmp3, e1)); - - e2 = binary_expr ('&', tmp3, tmp3); - append_expr (e, assign_expr (tmp4, e2)); - - e1 = binary_expr ('*', tmp2, tmp4); - e2 = binary_expr ('-', tmp1, e1); - e->e.block.result = e2; + append_expr (e, assign_expr (tmp1, binary_expr ('/', e1, e2))); + append_expr (e, assign_expr (tmp2, binary_expr ('&', tmp1, tmp1))); + e->e.block.result = binary_expr ('-', e1, binary_expr ('*', e2, tmp2)); return e; } break; From df7c08a01033f49c5d0bfb2e1d05a1854f4552e9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 16:38:37 +0900 Subject: [PATCH 0265/3664] Add support for doubles to Ruamoko Only as scalars, I still need to think about what to do for vectors and quaternions due to param size issues. Also, doubles are not yet guaranteed to be correctly aligned. --- include/QF/pr_comp.h | 38 +++++- include/QF/progs.h | 48 +++++++ libs/gamecode/pr_exec.c | 158 +++++++++++++++++++++-- libs/gamecode/pr_opcode.c | 126 +++++++++++++++++++ libs/gamecode/pr_strings.c | 31 +++-- libs/ruamoko/rua_math.c | 223 +++++++++++++++++++++++++++------ nq/include/sv_progs.h | 5 + nq/source/sv_progs.c | 3 + qw/include/sv_progs.h | 5 + qw/source/sv_progs.c | 3 + ruamoko/include/math.h | 73 +++++++---- ruamoko/lib/math.r | 24 ++++ tools/qfcc/include/expr.h | 10 ++ tools/qfcc/include/type.h | 2 + tools/qfcc/include/value.h | 1 + tools/qfcc/source/constfold.c | 222 +++++++++++++++++++++++++++++++- tools/qfcc/source/dot_expr.c | 3 + tools/qfcc/source/expr.c | 34 +++++ tools/qfcc/source/qc-lex.l | 1 + tools/qfcc/source/statements.c | 5 + tools/qfcc/source/type.c | 19 ++- tools/qfcc/source/value.c | 10 ++ 22 files changed, 958 insertions(+), 86 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index c657a7ca1..122de60b9 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -44,6 +44,7 @@ typedef enum { ev_integer, ev_uinteger, ev_short, // value is embedded in the opcode + ev_double, ev_invalid, // invalid type. used for instruction checking ev_type_count // not a type, gives number of types @@ -305,6 +306,7 @@ typedef enum { OP_PUSH_P, OP_PUSH_Q, OP_PUSH_I, + OP_PUSH_D, OP_PUSHB_S, OP_PUSHB_F, @@ -315,6 +317,7 @@ typedef enum { OP_PUSHB_P, OP_PUSHB_Q, OP_PUSHB_I, + OP_PUSHB_D, OP_PUSHBI_S, OP_PUSHBI_F, @@ -325,6 +328,7 @@ typedef enum { OP_PUSHBI_P, OP_PUSHBI_Q, OP_PUSHBI_I, + OP_PUSHBI_D, OP_POP_S, OP_POP_F, @@ -335,6 +339,7 @@ typedef enum { OP_POP_P, OP_POP_Q, OP_POP_I, + OP_POP_D, OP_POPB_S, OP_POPB_F, @@ -345,6 +350,7 @@ typedef enum { OP_POPB_P, OP_POPB_Q, OP_POPB_I, + OP_POPB_D, OP_POPBI_S, OP_POPBI_F, @@ -355,6 +361,36 @@ typedef enum { OP_POPBI_P, OP_POPBI_Q, OP_POPBI_I, + OP_POPBI_D, + + OP_ADD_D, + OP_SUB_D, + OP_MUL_D, + OP_MUL_QD, + OP_MUL_DQ, + OP_MUL_VD, + OP_MUL_DV, + OP_DIV_D, + OP_MOD_D, + OP_GE_D, + OP_LE_D, + OP_GT_D, + OP_LT_D, + OP_NOT_D, + OP_EQ_D, + OP_NE_D, + OP_CONV_FD, + OP_CONV_DF, + OP_CONV_ID, + OP_CONV_DI, + OP_STORE_D, + OP_STOREB_D, + OP_STOREBI_D, + OP_STOREP_D, + OP_LOAD_D, + OP_LOADB_D, + OP_LOADBI_D, + OP_ADDRESS_D, } pr_opcode_e; typedef struct opcode_s { @@ -423,7 +459,7 @@ typedef struct pr_va_list_s { |(((0x##b) & 0xfff) << 12) \ |(((0x##c) & 0xfff) << 0) ) #define PROG_ID_VERSION 6 -#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,009) +#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,00a) typedef struct dprograms_s { pr_uint_t version; diff --git a/include/QF/progs.h b/include/QF/progs.h index 7631f1de1..f3358c708 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -320,6 +320,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define G_FLOAT(p,o) G_var (p, o, float) +/** Access a double global. Can be assigned to. + + \par QC type: + \c double + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \return double lvalue + + \hideinitializer +*/ +#define G_DOUBLE(p,o) (*(double *) ((p)->pr_globals + o)) + /** Access an integer global. Can be assigned to. \par QC type: @@ -510,6 +522,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define P_FLOAT(p,n) P_var (p, n, float) +/** Access a double parameter. Can be assigned to. + + \par QC type: + \c double + \param p pointer to ::progs_t VM struct + \param n parameter number (0-7) + \return double lvalue + + \hideinitializer +*/ +#define P_DOUBLE(p,n) (*(double *) ((p)->pr_params[n])) + /** Access an integer parameter. Can be assigned to. \par QC type: @@ -702,6 +726,17 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_FLOAT(p) R_var (p, float) +/** Access the VM function return value as a \c double + + \par QC type: + \c double + \param p pointer to ::progs_t VM struct + \return double lvalue + + \hideinitializer +*/ +#define R_DOUBLE(p) (*(double *) ((p)->pr_return)) + /** Access the VM function return value as a \c ::pr_int_t (AKA int32_t) \par QC type: @@ -868,6 +903,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define E_FLOAT(e,o) E_var (e, o, float) +/** Access a double entity field. Can be assigned to. + + \par QC type: + \c double + \param e pointer to the entity + \param o field offset into entity data space + \return double lvalue + + \hideinitializer +*/ +#define E_DOUBLE(e,o) (*(double *) ((e)->v + o)) + /** Access an integer entity field. Can be assigned to. \par QC type: @@ -1560,6 +1607,7 @@ struct progs_s { struct hashtab_s *strref_hash; int num_strings; strref_t *pr_xtstr; + int float_promoted; ///< for PR_Sprintf //@} /// \name memory map diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 27c3f9c50..3ea2c3bd5 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -280,12 +280,15 @@ PR_BoundsCheck (progs_t *pr, int addr, etype_t type) #define OPB (*op_b) #define OPC (*op_c) +#define OPA_double_var (*((double *) (op_a))) +#define OPB_double_var (*((double *) (op_b))) +#define OPC_double_var (*((double *) (op_c))) + /* This gets around the problem of needing to test for -0.0 but denormals causing exceptions (or wrong results for what we need) on the alpha. */ -#define FNZ(x) ((x).uinteger_var && (x).uinteger_var != 0x80000000u) - +#define FNZ(x) ((x).uinteger_var & ~0x80000000u) static int signal_hook (int sig, void *data) @@ -421,6 +424,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_PrintStatement (pr, st, 1); switch (st->op) { + case OP_ADD_D: + OPC_double_var = OPA_double_var + OPB_double_var; + break; case OP_ADD_F: OPC.float_var = OPA.float_var + OPB.float_var; break; @@ -437,6 +443,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_GetString (pr, OPB.string_var)); break; + case OP_SUB_D: + OPC_double_var = OPA_double_var - OPB_double_var; + break; case OP_SUB_F: OPC.float_var = OPA.float_var - OPB.float_var; break; @@ -446,12 +455,31 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) case OP_SUB_Q: QuatSubtract (OPA.quat_var, OPB.quat_var, OPC.quat_var); break; + case OP_MUL_D: + OPC_double_var = OPA_double_var * OPB_double_var; + break; case OP_MUL_F: OPC.float_var = OPA.float_var * OPB.float_var; break; case OP_MUL_V: OPC.float_var = DotProduct (OPA.vector_var, OPB.vector_var); break; + case OP_MUL_DV: + { + // avoid issues with the likes of x = x.x * x; + // makes for faster code, too + double scale = OPA_double_var; + VectorScale (OPB.vector_var, scale, OPC.vector_var); + } + break; + case OP_MUL_VD: + { + // avoid issues with the likes of x = x * x.x; + // makes for faster code, too + double scale = OPB_double_var; + VectorScale (OPA.vector_var, scale, OPC.vector_var); + } + break; case OP_MUL_FV: { // avoid issues with the likes of x = x.x * x; @@ -474,6 +502,22 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) case OP_MUL_QV: QuatMultVec (OPA.quat_var, OPB.vector_var, OPC.vector_var); break; + case OP_MUL_DQ: + { + // avoid issues with the likes of x = x.s * x; + // makes for faster code, too + double scale = OPA_double_var; + QuatScale (OPB.quat_var, scale, OPC.quat_var); + } + break; + case OP_MUL_QD: + { + // avoid issues with the likes of x = x * x.s; + // makes for faster code, too + double scale = OPB_double_var; + QuatScale (OPA.quat_var, scale, OPC.quat_var); + } + break; case OP_MUL_FQ: { // avoid issues with the likes of x = x.s * x; @@ -493,6 +537,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) case OP_CONJ_Q: QuatConj (OPA.quat_var, OPC.quat_var); break; + case OP_DIV_D: + OPC_double_var = OPA_double_var / OPB_double_var; + break; case OP_DIV_F: OPC.float_var = OPA.float_var / OPB.float_var; break; @@ -630,6 +677,9 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) case OP_STORE_Q: QuatCopy (OPA.quat_var, OPB.quat_var); break; + case OP_STORE_D: + OPB_double_var = OPA_double_var; + break; case OP_STOREP_F: case OP_STOREP_ENT: @@ -661,6 +711,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) ptr = pr->pr_globals + pointer; QuatCopy (OPA.quat_var, ptr->quat_var); break; + case OP_STOREP_D: + pointer = OPB.integer_var; + if (pr_boundscheck->int_val) { + PR_BoundsCheck (pr, pointer, ev_double); + } + ptr = pr->pr_globals + pointer; + *(double *) ptr = OPA_double_var; + break; case OP_ADDRESS: if (pr_boundscheck->int_val) { @@ -687,6 +745,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) case OP_ADDRESS_FN: case OP_ADDRESS_I: case OP_ADDRESS_P: + case OP_ADDRESS_D: OPC.integer_var = st->a; break; @@ -735,6 +794,19 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) ed = PROG_TO_EDICT (pr, OPA.entity_var); memcpy (&OPC, &ed->v[OPB.integer_var], 4 * sizeof (OPC)); break; + case OP_LOAD_D: + if (pr_boundscheck->int_val) { + if (OPA.entity_var < 0 + || OPA.entity_var >= pr->pr_edictareasize) + PR_RunError (pr, "Progs attempted to read an out of " + "bounds edict number"); + if (OPB.uinteger_var + 1 >= pr->progs->entityfields) + PR_RunError (pr, "Progs attempted to read an invalid " + "field in an edict"); + } + ed = PROG_TO_EDICT (pr, OPA.entity_var); + OPC_double_var = *(double *) (ed->v + OPB.integer_var); + break; case OP_LOADB_F: case OP_LOADB_S: @@ -766,6 +838,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) ptr = pr->pr_globals + pointer; QuatCopy (ptr->quat_var, OPC.quat_var); break; + case OP_LOADB_D: + pointer = OPA.integer_var + OPB.integer_var; + if (pr_boundscheck->int_val) { + PR_BoundsCheck (pr, pointer, ev_double); + } + ptr = pr->pr_globals + pointer; + OPC_double_var = *(double *) ptr; + break; case OP_LOADBI_F: case OP_LOADBI_S: @@ -797,6 +877,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) ptr = pr->pr_globals + pointer; QuatCopy (ptr->quat_var, OPC.quat_var); break; + case OP_LOADBI_D: + pointer = OPA.integer_var + (short) st->b; + if (pr_boundscheck->int_val) { + PR_BoundsCheck (pr, pointer, ev_quat); + } + ptr = pr->pr_globals + pointer; + OPC_double_var = *(double *) ptr; + break; case OP_LEA: pointer = OPA.integer_var + OPB.integer_var; @@ -838,6 +926,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) ptr = pr->pr_globals + pointer; QuatCopy (OPA.quat_var, ptr->quat_var); break; + case OP_STOREB_D: + pointer = OPB.integer_var + OPC.integer_var; + if (pr_boundscheck->int_val) { + PR_BoundsCheck (pr, pointer, ev_quat); + } + ptr = pr->pr_globals + pointer; + *(double *) ptr = OPA_double_var; + break; case OP_STOREBI_F: case OP_STOREBI_S: @@ -869,6 +965,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) ptr = pr->pr_globals + pointer; QuatCopy (OPA.quat_var, ptr->quat_var); break; + case OP_STOREBI_D: + pointer = OPB.integer_var + (short) st->c; + if (pr_boundscheck->int_val) { + PR_BoundsCheck (pr, pointer, ev_quat); + } + ptr = pr->pr_globals + pointer; + *(double *) ptr = OPA_double_var; + break; case OP_PUSH_F: case OP_PUSH_FLD: @@ -1322,20 +1426,19 @@ op_call: case OP_MUL_I: OPC.integer_var = OPA.integer_var * OPB.integer_var; break; -/* - case OP_DIV_VF: - { - float temp = 1.0f / OPB.float_var; - VectorScale (OPA.vector_var, temp, OPC.vector_var); - } - break; -*/ case OP_DIV_I: OPC.integer_var = OPA.integer_var / OPB.integer_var; break; case OP_MOD_I: OPC.integer_var = OPA.integer_var % OPB.integer_var; break; + case OP_MOD_D: + { + double a = OPA_double_var; + double b = OPB_double_var; + OPC_double_var = a - b * trunc (a / b); + } + break; case OP_MOD_F: { float a = OPA.float_var; @@ -1432,6 +1535,41 @@ op_call: st->b * 4); break; + case OP_GE_D: + OPC.float_var = OPA_double_var >= OPB_double_var; + break; + case OP_LE_D: + OPC.float_var = OPA_double_var <= OPB_double_var; + break; + case OP_GT_D: + OPC.float_var = OPA_double_var > OPB_double_var; + break; + case OP_LT_D: + OPC.float_var = OPA_double_var < OPB_double_var; + break; + case OP_NOT_D: + OPC.integer_var = (op_a[0].integer_var + || (op_a[1].integer_var & ~0x80000000u)); + break; + case OP_EQ_D: + OPC.integer_var = OPA_double_var == OPB_double_var; + break; + case OP_NE_D: + OPC.integer_var = OPA_double_var != OPB_double_var; + break; + case OP_CONV_ID: + OPC_double_var = OPA.integer_var; + break; + case OP_CONV_DI: + OPC.integer_var = OPA_double_var; + break; + case OP_CONV_FD: + OPC_double_var = OPA.float_var; + break; + case OP_CONV_DF: + OPC.float_var = OPA_double_var; + break; + // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized /* case OP_BOUNDCHECK: diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 9e970c781..a2a344a1e 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -61,6 +61,7 @@ VISIBLE int pr_type_size[ev_type_count] = { 1, // ev_integer 1, // ev_uinteger 0, // ev_short value in opcode + 2, // ev_double }; VISIBLE const char *pr_type_name[ev_type_count] = { @@ -102,6 +103,10 @@ VISIBLE opcode_t pr_opcodes[] = { "%Va", }, + {"*", "mul.d", OP_MUL_D, false, + ev_double, ev_double, ev_double, + PROG_VERSION, + }, {"*", "mul.f", OP_MUL_F, false, ev_float, ev_float, ev_float, PROG_ID_VERSION, @@ -118,6 +123,14 @@ VISIBLE opcode_t pr_opcodes[] = { ev_vector, ev_float, ev_vector, PROG_ID_VERSION, }, + {"*", "mul.dv", OP_MUL_DV, false, + ev_double, ev_vector, ev_vector, + PROG_ID_VERSION, + }, + {"*", "mul.vd", OP_MUL_VD, false, + ev_vector, ev_double, ev_vector, + PROG_ID_VERSION, + }, {"*", "mul.q", OP_MUL_Q, false, ev_quat, ev_quat, ev_quat, PROG_VERSION, @@ -130,6 +143,14 @@ VISIBLE opcode_t pr_opcodes[] = { ev_quat, ev_float, ev_quat, PROG_VERSION, }, + {"*", "mul.dq", OP_MUL_DQ, false, + ev_double, ev_quat, ev_quat, + PROG_VERSION, + }, + {"*", "mul.qd", OP_MUL_QD, false, + ev_quat, ev_double, ev_quat, + PROG_VERSION, + }, {"*", "mul.qv", OP_MUL_QV, false, ev_quat, ev_vector, ev_vector, PROG_VERSION, @@ -145,7 +166,19 @@ VISIBLE opcode_t pr_opcodes[] = { ev_float, ev_float, ev_float, PROG_ID_VERSION, }, + {"/", "div.d", OP_DIV_D, false, + ev_double, ev_double, ev_double, + PROG_VERSION, + }, + {"%", "mod.d", OP_MOD_D, false, + ev_double, ev_double, ev_double, + PROG_VERSION, + }, + {"+", "add.d", OP_ADD_D, false, + ev_double, ev_double, ev_double, + PROG_VERSION, + }, {"+", "add.f", OP_ADD_F, false, ev_float, ev_float, ev_float, PROG_ID_VERSION, @@ -163,6 +196,10 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_VERSION, }, + {"-", "sub.d", OP_SUB_D, false, + ev_double, ev_double, ev_double, + PROG_VERSION, + }, {"-", "sub.f", OP_SUB_F, false, ev_float, ev_float, ev_float, PROG_ID_VERSION, @@ -176,6 +213,10 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_VERSION, }, + {"==", "eq.d", OP_EQ_D, false, + ev_double, ev_double, ev_integer, + PROG_VERSION, + }, {"==", "eq.f", OP_EQ_F, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, @@ -201,6 +242,10 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_ID_VERSION, }, + {"!=", "ne.d", OP_NE_D, false, + ev_double, ev_double, ev_integer, + PROG_VERSION, + }, {"!=", "ne.f", OP_NE_F, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, @@ -226,10 +271,18 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_ID_VERSION, }, + {"<=", "le.d", OP_LE_D, false, + ev_double, ev_double, ev_integer, + PROG_VERSION, + }, {"<=", "le.f", OP_LE_F, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, + {">=", "ge.d", OP_GE_D, false, + ev_double, ev_double, ev_integer, + PROG_VERSION, + }, {">=", "ge.f", OP_GE_F, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, @@ -242,10 +295,18 @@ VISIBLE opcode_t pr_opcodes[] = { ev_string, ev_string, ev_integer, PROG_VERSION, }, + {"<", "lt.d", OP_LT_D, false, + ev_double, ev_double, ev_integer, + PROG_VERSION, + }, {"<", "lt.f", OP_LT_F, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, + {">", "gt.d", OP_GT_D, false, + ev_double, ev_double, ev_integer, + PROG_VERSION, + }, {">", "gt.f", OP_GT_F, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, @@ -264,6 +325,11 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible? }, + {".", "load.d", OP_LOAD_D, false, + ev_entity, ev_field, ev_double, + PROG_VERSION, + "%Ga.%Gb(%Ec), %gc", + }, {".", "load.v", OP_LOAD_V, false, ev_entity, ev_field, ev_vector, PROG_ID_VERSION, @@ -305,6 +371,11 @@ VISIBLE opcode_t pr_opcodes[] = { "%Ga.%Gb(%Ec), %gc", }, + {".", "loadb.d", OP_LOADB_D, false, + ev_pointer, ev_integer, ev_double, + PROG_VERSION, + "*(%Ga + %Gb), %gc", + }, {".", "loadb.f", OP_LOADB_F, false, ev_pointer, ev_integer, ev_float, PROG_VERSION, @@ -351,6 +422,11 @@ VISIBLE opcode_t pr_opcodes[] = { "*(%Ga + %Gb), %gc", }, + {".", "loadbi.d", OP_LOADBI_D, false, + ev_pointer, ev_short, ev_double, + PROG_VERSION, + "*(%Ga + %sb), %gc", + }, {".", "loadbi.f", OP_LOADBI_F, false, ev_pointer, ev_short, ev_float, PROG_VERSION, @@ -408,6 +484,11 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_VERSION, "%Ga, %gc", }, + {"&", "address.d", OP_ADDRESS_D, false, + ev_double, ev_invalid, ev_pointer, + PROG_VERSION, + "%Ga, %gc", + }, {"&", "address.f", OP_ADDRESS_F, false, ev_float, ev_invalid, ev_pointer, PROG_VERSION, @@ -475,7 +556,32 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_VERSION, "%Ga, %gc", }, + {"", "conv.id", OP_CONV_ID, false, + ev_integer, ev_invalid, ev_double, + PROG_VERSION, + "%Ga, %gc", + }, + {"", "conv.di", OP_CONV_DI, false, + ev_double, ev_invalid, ev_integer, + PROG_VERSION, + "%Ga, %gc", + }, + {"", "conv.fd", OP_CONV_FD, false, + ev_float, ev_invalid, ev_double, + PROG_VERSION, + "%Ga, %gc", + }, + {"", "conv.df", OP_CONV_DF, false, + ev_double, ev_invalid, ev_float, + PROG_VERSION, + "%Ga, %gc", + }, + {"=", "store.d", OP_STORE_D, true, + ev_double, ev_double, ev_invalid, + PROG_VERSION, + "%Ga, %gb", + }, {"=", "store.f", OP_STORE_F, true, ev_float, ev_float, ev_invalid, PROG_ID_VERSION, @@ -522,6 +628,11 @@ VISIBLE opcode_t pr_opcodes[] = { "%Ga, %gb", }, + {".=", "storep.d", OP_STOREP_D, true, + ev_double, ev_pointer, ev_invalid, + PROG_ID_VERSION, + "%Ga, *%Gb", + }, {".=", "storep.f", OP_STOREP_F, true, ev_float, ev_pointer, ev_invalid, PROG_ID_VERSION, @@ -568,6 +679,11 @@ VISIBLE opcode_t pr_opcodes[] = { "%Ga, *%Gb", }, + {".=", "storeb.d", OP_STOREB_D, true, + ev_double, ev_pointer, ev_integer, + PROG_VERSION, + "%Ga, *(%Gb + %Gc)", + }, {".=", "storeb.f", OP_STOREB_F, true, ev_float, ev_pointer, ev_integer, PROG_VERSION, @@ -614,6 +730,11 @@ VISIBLE opcode_t pr_opcodes[] = { "%Ga, *(%Gb + %Gc)", }, + {".=", "storebi.d", OP_STOREBI_D, true, + ev_double, ev_pointer, ev_short, + PROG_VERSION, + "%Ga, *(%Gb + %sc)", + }, {".=", "storebi.f", OP_STOREBI_F, true, ev_float, ev_pointer, ev_short, PROG_VERSION, @@ -672,6 +793,11 @@ VISIBLE opcode_t pr_opcodes[] = { "", }, + {"!", "not.d", OP_NOT_D, false, + ev_double, ev_invalid, ev_integer, + PROG_VERSION, + "%Ga, %gc", + }, {"!", "not.f", OP_NOT_F, false, ev_float, ev_invalid, ev_integer, PROG_ID_VERSION, diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index b0edefa63..684551fda 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -70,6 +70,7 @@ struct strref_s { #define FMT_ADDSIGN (1<<3) #define FMT_ADDBLANK (1<<4) #define FMT_HEX (1<<5) +#define FMT_LONG (1<<6) typedef struct fmt_item_s { byte type; @@ -81,6 +82,7 @@ typedef struct fmt_item_s { int integer_var; unsigned uinteger_var; float float_var; + double double_var; } data; struct fmt_item_s *next; } fmt_item_t; @@ -596,11 +598,19 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting) break; case 'f': dstring_appendstr (tmp, "f"); - PRINT (float); + if (current->flags & FMT_LONG) { + PRINT (double); + } else { + PRINT (float); + } break; case 'g': dstring_appendstr (tmp, "g"); - PRINT (float); + if (current->flags & FMT_LONG) { + PRINT (double); + } else { + PRINT (float); + } break; default: break; @@ -650,7 +660,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, int fmt_count = 0; if (!name) - name = "PF_InternalSprintf"; + name = "PR_Sprintf"; *fi = new_fmt_item (); c = l = format; @@ -742,12 +752,19 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, fi = &(*fi)->next; break; case 'f': - // float + // float or double case 'g': - // float, no trailing zeroes, trim "." if nothing - // after + // float or double, no trailing zeroes, trim "." + // if nothing after (*fi)->type = *c; - (*fi)->data.float_var = P_FLOAT (pr, fmt_count); + if (pr->float_promoted) { + (*fi)->flags |= FMT_LONG; + (*fi)->data.double_var + = P_DOUBLE (pr, fmt_count); + } else { + (*fi)->data.float_var + = P_FLOAT (pr, fmt_count); + } fmt_count++; (*fi)->next = new_fmt_item (); diff --git a/libs/ruamoko/rua_math.c b/libs/ruamoko/rua_math.c index 0cc5e5636..167db865f 100644 --- a/libs/ruamoko/rua_math.c +++ b/libs/ruamoko/rua_math.c @@ -42,55 +42,55 @@ #include "rua_internal.h" static void -bi_sin (progs_t *pr) +bi_sinf (progs_t *pr) { R_FLOAT (pr) = sinf (P_FLOAT (pr, 0)); } static void -bi_cos (progs_t *pr) +bi_cosf (progs_t *pr) { R_FLOAT (pr) = cosf (P_FLOAT (pr, 0)); } static void -bi_tan (progs_t *pr) +bi_tanf (progs_t *pr) { R_FLOAT (pr) = tanf (P_FLOAT (pr, 0)); } static void -bi_asin (progs_t *pr) +bi_asinf (progs_t *pr) { R_FLOAT (pr) = asinf (P_FLOAT (pr, 0)); } static void -bi_acos (progs_t *pr) +bi_acosf (progs_t *pr) { R_FLOAT (pr) = acosf (P_FLOAT (pr, 0)); } static void -bi_atan (progs_t *pr) +bi_atanf (progs_t *pr) { R_FLOAT (pr) = atanf (P_FLOAT (pr, 0)); } static void -bi_atan2 (progs_t *pr) +bi_atan2f (progs_t *pr) { R_FLOAT (pr) = atan2f (P_FLOAT (pr, 0), P_FLOAT (pr, 1)); } static void -bi_log (progs_t *pr) +bi_logf (progs_t *pr) { R_FLOAT (pr) = logf (P_FLOAT (pr, 0)); } static void -bi_log2 (progs_t *pr) +bi_log2f (progs_t *pr) { #ifdef HAVE_LOG2F R_FLOAT (pr) = log2f (P_FLOAT (pr, 0)); @@ -100,95 +100,238 @@ bi_log2 (progs_t *pr) } static void -bi_log10 (progs_t *pr) +bi_log10f (progs_t *pr) { R_FLOAT (pr) = log10f (P_FLOAT (pr, 0)); } static void -bi_pow (progs_t *pr) +bi_powf (progs_t *pr) { R_FLOAT (pr) = powf (P_FLOAT (pr, 0), P_FLOAT (pr, 1)); } static void -bi_sqrt (progs_t *pr) +bi_sqrtf (progs_t *pr) { R_FLOAT (pr) = sqrtf (P_FLOAT (pr, 0)); } static void -bi_cbrt (progs_t *pr) +bi_cbrtf (progs_t *pr) { R_FLOAT (pr) = cbrtf (P_FLOAT (pr, 0)); } static void -bi_hypot (progs_t *pr) +bi_hypotf (progs_t *pr) { R_FLOAT (pr) = hypotf (P_FLOAT (pr, 0), P_FLOAT (pr, 1)); } static void -bi_sinh (progs_t *pr) +bi_sinhf (progs_t *pr) { R_FLOAT (pr) = sinhf (P_FLOAT (pr, 0)); } static void -bi_cosh (progs_t *pr) +bi_coshf (progs_t *pr) { R_FLOAT (pr) = coshf (P_FLOAT (pr, 0)); } static void -bi_tanh (progs_t *pr) +bi_tanhf (progs_t *pr) { R_FLOAT (pr) = tanhf (P_FLOAT (pr, 0)); } static void -bi_asinh (progs_t *pr) +bi_asinhf (progs_t *pr) { double y = P_FLOAT (pr, 0); R_FLOAT (pr) = logf (y + sqrtf (y * y + 1)); } static void -bi_acosh (progs_t *pr) +bi_acoshf (progs_t *pr) { double y = P_FLOAT (pr, 0); R_FLOAT (pr) = logf (y + sqrtf (y * y - 1)); } static void -bi_atanh (progs_t *pr) +bi_atanhf (progs_t *pr) { double y = P_FLOAT (pr, 0); R_FLOAT (pr) = logf ((1 + y) / (1 - y)) / 2; } +static void +bi_sin (progs_t *pr) +{ + R_DOUBLE (pr) = sin (P_DOUBLE (pr, 0)); +} + +static void +bi_cos (progs_t *pr) +{ + R_DOUBLE (pr) = cos (P_DOUBLE (pr, 0)); +} + +static void +bi_tan (progs_t *pr) +{ + R_DOUBLE (pr) = tan (P_DOUBLE (pr, 0)); +} + +static void +bi_asin (progs_t *pr) +{ + R_DOUBLE (pr) = asin (P_DOUBLE (pr, 0)); +} + +static void +bi_acos (progs_t *pr) +{ + R_DOUBLE (pr) = acos (P_DOUBLE (pr, 0)); +} + +static void +bi_atan (progs_t *pr) +{ + R_DOUBLE (pr) = atan (P_DOUBLE (pr, 0)); +} + +static void +bi_atan2 (progs_t *pr) +{ + R_DOUBLE (pr) = atan2 (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1)); +} + +static void +bi_log (progs_t *pr) +{ + R_DOUBLE (pr) = log (P_DOUBLE (pr, 0)); +} + +static void +bi_log2 (progs_t *pr) +{ + R_DOUBLE (pr) = log (P_DOUBLE (pr, 0)) / M_LOG2E; +} + +static void +bi_log10 (progs_t *pr) +{ + R_DOUBLE (pr) = log10 (P_DOUBLE (pr, 0)); +} + +static void +bi_pow (progs_t *pr) +{ + R_DOUBLE (pr) = pow (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1)); +} + +static void +bi_sqrt (progs_t *pr) +{ + R_DOUBLE (pr) = sqrt (P_DOUBLE (pr, 0)); +} + +static void +bi_cbrt (progs_t *pr) +{ + R_DOUBLE (pr) = cbrt (P_DOUBLE (pr, 0)); +} + +static void +bi_hypot (progs_t *pr) +{ + R_DOUBLE (pr) = hypot (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1)); +} + +static void +bi_sinh (progs_t *pr) +{ + R_DOUBLE (pr) = sinh (P_DOUBLE (pr, 0)); +} + +static void +bi_cosh (progs_t *pr) +{ + R_DOUBLE (pr) = cosh (P_DOUBLE (pr, 0)); +} + +static void +bi_tanh (progs_t *pr) +{ + R_DOUBLE (pr) = tanh (P_DOUBLE (pr, 0)); +} + +static void +bi_asinh (progs_t *pr) +{ + double y = P_DOUBLE (pr, 0); + R_DOUBLE (pr) = log (y + sqrt (y * y + 1)); +} + +static void +bi_acosh (progs_t *pr) +{ + double y = P_DOUBLE (pr, 0); + R_DOUBLE (pr) = log (y + sqrt (y * y - 1)); +} + +static void +bi_atanh (progs_t *pr) +{ + double y = P_DOUBLE (pr, 0); + R_DOUBLE (pr) = log ((1 + y) / (1 - y)) / 2; +} + static builtin_t builtins[] = { - {"sin", bi_sin, -1}, - {"cos", bi_cos, -1}, - {"tan", bi_tan, -1}, - {"asin", bi_asin, -1}, - {"acos", bi_acos, -1}, - {"atan", bi_atan, -1}, - {"atan2", bi_atan2, -1}, - {"log", bi_log, -1}, - {"log2", bi_log2, -1}, - {"log10", bi_log10, -1}, - {"pow", bi_pow, -1}, - {"sqrt", bi_sqrt, -1}, - {"cbrt", bi_cbrt, -1}, - {"hypot", bi_hypot, -1}, - {"sinh", bi_sinh, -1}, - {"cosh", bi_cosh, -1}, - {"tanh", bi_tanh, -1}, - {"asinh", bi_asinh, -1}, - {"acosh", bi_acosh, -1}, - {"atanh", bi_atanh, -1}, + {"sin|f", bi_sinf, -1}, + {"cos|f", bi_cosf, -1}, + {"tan|f", bi_tanf, -1}, + {"asin|f", bi_asinf, -1}, + {"acos|f", bi_acosf, -1}, + {"atan|f", bi_atanf, -1}, + {"atan2|f", bi_atan2f, -1}, + {"log|f", bi_logf, -1}, + {"log2|f", bi_log2f, -1}, + {"log10|f", bi_log10f, -1}, + {"pow|f", bi_powf, -1}, + {"sqrt|f", bi_sqrtf, -1}, + {"cbrt|f", bi_cbrtf, -1}, + {"hypot|f", bi_hypotf, -1}, + {"sinh|f", bi_sinhf, -1}, + {"cosh|f", bi_coshf, -1}, + {"tanh|f", bi_tanhf, -1}, + {"asinh|f", bi_asinhf, -1}, + {"acosh|f", bi_acoshf, -1}, + {"atanh|f", bi_atanhf, -1}, + {"sin|d", bi_sin, -1}, + {"cos|d", bi_cos, -1}, + {"tan|d", bi_tan, -1}, + {"asin|d", bi_asin, -1}, + {"acos|d", bi_acos, -1}, + {"atan|d", bi_atan, -1}, + {"atan2|d", bi_atan2, -1}, + {"log|d", bi_log, -1}, + {"log2|d", bi_log2, -1}, + {"log10|d", bi_log10, -1}, + {"pow|d", bi_pow, -1}, + {"sqrt|d", bi_sqrt, -1}, + {"cbrt|d", bi_cbrt, -1}, + {"hypot|d", bi_hypot, -1}, + {"sinh|d", bi_sinh, -1}, + {"cosh|d", bi_cosh, -1}, + {"tanh|d", bi_tanh, -1}, + {"asinh|d", bi_asinh, -1}, + {"acosh|d", bi_acosh, -1}, + {"atanh|d", bi_atanh, -1}, {0} }; diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index e1b8d4e4a..07a8c8f7c 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -210,6 +210,11 @@ extern progs_t sv_pr_state; #define SVentity(e,f) SVFIELD (e, f, entity) #define SVvector(e,f) SVFIELD (e, f, vector) #define SVinteger(e,f) SVFIELD (e, f, integer) +#if TYPECHECK_PROGS +#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) +#else +#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f) +#endif typedef struct edict_leaf_s { struct edict_leaf_s *next; diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index c289b6e44..7e98550d4 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -361,6 +361,9 @@ set_address (sv_def_t *def, void *address) case ev_quat: *(float **)def->field = (float *) address; break; + case ev_double: + *(double **)def->field = (double *) address; + break; case ev_string: case ev_entity: case ev_field: diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index ca96f7de5..18bdde503 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -195,6 +195,11 @@ extern progs_t sv_pr_state; #define SVentity(e,f) SVFIELD (e, f, entity) #define SVvector(e,f) SVFIELD (e, f, vector) #define SVinteger(e,f) SVFIELD (e, f, integer) +#if TYPECHECK_PROGS +#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) +#else +#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f) +#endif typedef struct edict_leaf_s { struct edict_leaf_s *next; diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index cad265b11..e4856f69b 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -371,6 +371,9 @@ set_address (sv_def_t *def, void *address) case ev_quat: *(float **)def->field = (float *) address; break; + case ev_double: + *(double **)def->field = (double *) address; + break; case ev_string: case ev_entity: case ev_field: diff --git a/ruamoko/include/math.h b/ruamoko/include/math.h index fad67a9de..d6ad33342 100644 --- a/ruamoko/include/math.h +++ b/ruamoko/include/math.h @@ -60,17 +60,20 @@ /** Returns \a f, rounded down to the next lower integer */ -@extern float floor (float f); +@extern @overload float floor (float f); +@extern @overload double floor (double f); /** Returns \a f, rounded up to the next highest integer */ -@extern float ceil (float f); +@extern @overload float ceil (float f); +@extern @overload double ceil (double f); /** Returns the absolute value of \a f */ -@extern float fabs (float f); +@extern @overload float fabs (float f); +@extern @overload double fabs (double f); //\} ///\name Exponentials and Logarithms @@ -78,32 +81,38 @@ /** Returns the natural log of \a x. */ -@extern float log (float x); +@extern @overload float log (float x); +@extern @overload double log (double x); /** Returns the base-2 log of \a x. */ -@extern float log2 (float x); +@extern @overload float log2 (float x); +@extern @overload double log2 (double x); /** Returns the base-10 log of \a x. */ -@extern float log10 (float x); +@extern @overload float log10 (float x); +@extern @overload double log10 (double x); /** Returns \a x to the \a y power */ -@extern float pow (float x, float y); +@extern @overload float pow (float x, float y); +@extern @overload double pow (double x, double y); /** Returns the square root of \a x */ -@extern float sqrt (float x); +@extern @overload float sqrt (float x); +@extern @overload double sqrt (double x); /** Returns the cube root of \a x */ -@extern float cbrt (float x); +@extern @overload float cbrt (float x); +@extern @overload double cbrt (double x); //\} ///\name Trigonometric functions @@ -112,40 +121,52 @@ /** Returns the sine of \a x. */ -@extern float sin (float x); +@extern @overload float sin (float x); +@extern @overload double sin (double x); /** Returns the cosine of \a x. */ -@extern float cos (float x); +@extern @overload float cos (float x); +@extern @overload double cos (double x); /** Returns the tangent of \a x. */ -@extern float tan (float x); +@extern @overload float tan (float x); +@extern @overload double tan (double x); /** Returns the arcsine of \a x. */ -@extern float asin (float x); +@extern @overload float asin (float x); +@extern @overload double asin (double x); /** Returns the arccosine of \a x. */ -@extern float acos (float x); +@extern @overload float acos (float x); +@extern @overload double acos (double x); /** Returns the arctangent of \a x. */ -@extern float atan (float x); -@extern float atan2 (float y, float x); +@extern @overload float atan (float x); +@extern @overload double atan (double x); + +/** + Returns the arctangent of \a y / \a x preserving the quadrant. +*/ +@extern @overload float atan2 (float y, float x); +@extern @overload double atan2 (double y, double x); /** Returns the length of the hypotenuse of a right triangle with sides \a x and \a y. That is, this function returns sqrt (\a x*\a x + \a y*\a y). */ -@extern float hypot (float x, float y); +@extern @overload float hypot (float x, float y); +@extern @overload double hypot (double x, double y); //\} ///\name Hyperbolic functions @@ -153,32 +174,38 @@ /** Returns the hyperbolic sine of \a x */ -@extern float sinh (float x); +@extern @overload float sinh (float x); +@extern @overload double sinh (double x); /** Returns the hyperbolic cosine of \a x */ -@extern float cosh (float x); +@extern @overload float cosh (float x); +@extern @overload double cosh (double x); /** Returns the hyperbolic tangent of \a x */ -@extern float tanh (float x); +@extern @overload float tanh (float x); +@extern @overload double tanh (double x); /** Returns the area hyperbolic sine of \a x */ -@extern float asinh (float x); +@extern @overload float asinh (float x); +@extern @overload double asinh (double x); /** Returns the area hyperbolic cosine of \a x */ -@extern float acosh (float x); +@extern @overload float acosh (float x); +@extern @overload double acosh (double x); /** Returns the area hyperbolic tangent of \a x */ -@extern float atanh (float x); +@extern @overload float atanh (float x); +@extern @overload double atanh (double x); //\} ///\name Vector Functions diff --git a/ruamoko/lib/math.r b/ruamoko/lib/math.r index 8d0c51342..80db2b710 100644 --- a/ruamoko/lib/math.r +++ b/ruamoko/lib/math.r @@ -34,3 +34,27 @@ float (float x) atanh = #0; float (float x) sqrt = #0; float (float x) cbrt = #0; float (float x, float y) hypot = #0; + +double (double v) floor = #0; +double (double v) ceil = #0; +double (double f) fabs = #0; +double (double x) sin = #0; +double (double x) cos = #0; +double (double x) tan = #0; +double (double x) asin = #0; +double (double x) acos = #0; +double (double x) atan = #0; +double (double y, double x) atan2 = #0; +double (double x) log = #0; +double (double x) log2 = #0; +double (double x) log10 = #0; +double (double x, double y) pow = #0; +double (double x) sinh = #0; +double (double x) cosh = #0; +double (double x) tanh = #0; +double (double x) asinh = #0; +double (double x) acosh = #0; +double (double x) atanh = #0; +double (double x) sqrt = #0; +double (double x) cbrt = #0; +double (double x, double y) hypot = #0; diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index d83610b7f..b11e93c2c 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -174,6 +174,7 @@ typedef struct ex_value_s { etype_t lltype; union { const char *string_val; ///< string constant + float double_val; ///< double constant float float_val; ///< float constant float vector_val[3]; ///< vector constant int entity_val; ///< entity constant @@ -397,6 +398,15 @@ expr_t *new_name_expr (const char *name); expr_t *new_string_expr (const char *string_val); const char *expr_string (expr_t *e) __attribute__((pure)); +/** Create a new double constant expression node. + + \param double_val The double constant being represented. + \return The new double constant expression node + (expr_t::e::double_val). +*/ +expr_t *new_double_expr (double double_val); +double expr_double (expr_t *e) __attribute__((pure)); + /** Create a new float constant expression node. \param float_val The float constant being represented. diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index d064de8ca..d6a43816e 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -98,6 +98,7 @@ typedef struct { extern type_t type_invalid; extern type_t type_void; extern type_t type_string; +extern type_t type_double; extern type_t type_float; extern type_t type_vector; extern type_t type_entity; @@ -153,6 +154,7 @@ const char *type_get_encoding (const type_t *type); int is_void (const type_t *type) __attribute__((pure)); int is_enum (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); +int is_double (const type_t *type) __attribute__((pure)); int is_float (const type_t *type) __attribute__((pure)); int is_scalar (const type_t *type) __attribute__((pure)); int is_vector (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index 883af01e0..aaac286b7 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -40,6 +40,7 @@ struct ex_value_s; struct type_s; struct ex_value_s *new_string_val (const char *string_val); +struct ex_value_s *new_double_val (double double_val); struct ex_value_s *new_float_val (float float_val); struct ex_value_s *new_vector_val (const float *vector_val); struct ex_value_s *new_entity_val (int entity_val); diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 817703945..3cba7f467 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -48,6 +48,7 @@ #include "qfcc.h" #include "strpool.h" #include "type.h" +#include "value.h" #include "qc-parse.h" typedef expr_t *(*operation_t) (int op, expr_t *e, expr_t *e1, expr_t *e2); @@ -163,6 +164,40 @@ convert_to_float (expr_t *e) } } +static expr_t * +convert_to_double (expr_t *e) +{ + if (get_type (e) == &type_double) + return e; + + switch (e->type) { + case ex_value: + switch (e->e.value->lltype) { + case ev_integer: + e->e.value = new_double_val (expr_integer (e)); + return e; + case ev_short: + e->e.value = new_double_val (expr_short (e)); + return e; + case ev_float: + e->e.value = new_double_val (expr_float (e)); + return e; + default: + internal_error (e, 0); + } + break; + case ex_symbol: + case ex_expr: + case ex_uexpr: + case ex_temp: + case ex_block: + e = cf_cast_expr (&type_float, e); + return e; + default: + internal_error (e, 0); + } +} + static expr_t * do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) { @@ -292,6 +327,111 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) return e; } +static expr_t * +do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2) +{ + double d1, d2; + expr_t *conv; + type_t *type = &type_double; + static int valid[] = { + '=', '+', '-', '*', '/', '%', + LT, GT, LE, GE, EQ, NE, 0 + }; + + if (!valid_op (op, valid)) + return error (e1, "invalid operator for double"); + + if (op == '=' || op == PAS) { + if ((type = get_type (e1)) != &type_double) { + //FIXME optimize casting a constant + e->e.expr.e2 = e2 = cf_cast_expr (type, e2); + } else if ((conv = convert_to_double (e2)) != e2) { + e->e.expr.e2 = e2 = conv; + } + } else { + if ((conv = convert_to_double (e1)) != e1) { + e->e.expr.e1 = e1 = conv; + } + if ((conv = convert_to_double (e2)) != e2) { + e->e.expr.e2 = e2 = conv; + } + } + if (is_compare (op) || is_logic (op)) { + type = &type_integer; + } + e->e.expr.type = type; + + if (op == '*' && is_constant (e1) && expr_double (e1) == 1) + return e2; + if (op == '*' && is_constant (e2) && expr_double (e2) == 1) + return e1; + if (op == '*' && is_constant (e1) && expr_double (e1) == 0) + return e1; + if (op == '*' && is_constant (e2) && expr_double (e2) == 0) + return e2; + if (op == '/' && is_constant (e2) && expr_double (e2) == 1) + return e1; + if (op == '/' && is_constant (e2) && expr_double (e2) == 0) + return error (e, "division by zero"); + if (op == '/' && is_constant (e1) && expr_double (e1) == 0) + return e1; + if (op == '+' && is_constant (e1) && expr_double (e1) == 0) + return e2; + if (op == '+' && is_constant (e2) && expr_double (e2) == 0) + return e1; + if (op == '-' && is_constant (e2) && expr_double (e2) == 0) + return e1; + + if (op == '=' || !is_constant (e1) || !is_constant (e2)) + return e; + + d1 = expr_double (e1); + d2 = expr_double (e2); + + switch (op) { + case '+': + e = new_double_expr (d1 + d2); + break; + case '-': + e = new_double_expr (d1 - d2); + break; + case '*': + e = new_double_expr (d1 * d2); + break; + case '/': + if (!d2) + return error (e1, "divide by zero"); + e = new_double_expr (d1 / d2); + break; + case '%': + e = new_double_expr ((int)d1 % (int)d2); + break; + case LT: + e = new_integer_expr (d1 < d2); + break; + case GT: + e = new_integer_expr (d1 > d2); + break; + case LE: + e = new_integer_expr (d1 <= d2); + break; + case GE: + e = new_integer_expr (d1 >= d2); + break; + case EQ: + e = new_integer_expr (d1 == d2); + break; + case NE: + e = new_integer_expr (d1 != d2); + break; + default: + internal_error (e1, 0); + } + e->file = e1->file; + e->line = e1->line; + return e; +} + static expr_t * do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) { @@ -884,11 +1024,15 @@ do_op_compound (int op, expr_t *e, expr_t *e1, expr_t *e2) return do_op_struct (op, e, e1, e2); if (is_scalar (t1) && is_scalar (t2)) { if (is_enum (t1)) { - if (t2->type == ev_float) + if (t2->type == ev_double) + return do_op_float (op, e, e1, e2); + if (t2->type == ev_double) return do_op_float (op, e, e1, e2); return do_op_integer (op, e, e1, e2); } if (is_enum (t2)) { + if (t1->type == ev_double) + return do_op_double (op, e, e1, e2); if (t1->type == ev_float) return do_op_float (op, e, e1, e2); return do_op_integer (op, e, e1, e2); @@ -947,6 +1091,7 @@ static operation_t op_void[ev_type_count] = { do_op_invalid, // ev_integer do_op_invalid, // ev_uinteger do_op_invalid, // ev_short + do_op_invalid, // ev_double do_op_invalid, // ev_invalid }; @@ -963,6 +1108,7 @@ static operation_t op_string[ev_type_count] = { do_op_invalid, // ev_integer do_op_invalid, // ev_uinteger do_op_invalid, // ev_short + do_op_invalid, // ev_double do_op_invalid, // ev_invalid }; @@ -979,6 +1125,7 @@ static operation_t op_float[ev_type_count] = { do_op_float, // ev_integer do_op_float, // ev_uinteger do_op_float, // ev_short + do_op_double, // ev_double do_op_invalid, // ev_invalid }; @@ -995,6 +1142,7 @@ static operation_t op_vector[ev_type_count] = { do_op_vector, // ev_integer do_op_vector, // ev_uinteger do_op_vector, // ev_short + do_op_vector, // ev_double do_op_invalid, // ev_invalid }; @@ -1011,6 +1159,7 @@ static operation_t op_entity[ev_type_count] = { do_op_invalid, // ev_integer do_op_invalid, // ev_uinteger do_op_invalid, // ev_short + do_op_invalid, // ev_double do_op_invalid, // ev_invalid }; @@ -1027,6 +1176,7 @@ static operation_t op_field[ev_type_count] = { do_op_invalid, // ev_integer do_op_invalid, // ev_uinteger do_op_invalid, // ev_short + do_op_invalid, // ev_double do_op_invalid, // ev_invalid }; @@ -1043,6 +1193,7 @@ static operation_t op_func[ev_type_count] = { do_op_func, // ev_integer do_op_func, // ev_uinteger do_op_func, // ev_short + do_op_func, // ev_double do_op_func, // ev_invalid }; @@ -1059,6 +1210,7 @@ static operation_t op_pointer[ev_type_count] = { do_op_pointer, // ev_integer do_op_pointer, // ev_uinteger do_op_pointer, // ev_short + do_op_pointer, // ev_double do_op_pointer, // ev_invalid }; @@ -1075,6 +1227,7 @@ static operation_t op_quaternion[ev_type_count] = { do_op_quaternion, // ev_integer do_op_quaternion, // ev_uinteger do_op_quaternion, // ev_short + do_op_quaternion, // ev_double do_op_invalid, // ev_invalid }; @@ -1091,6 +1244,7 @@ static operation_t op_integer[ev_type_count] = { do_op_integer, // ev_integer do_op_uinteger, // ev_uinteger do_op_integer, // ev_short + do_op_double, // ev_double do_op_invalid, // ev_invalid }; @@ -1107,6 +1261,7 @@ static operation_t op_uinteger[ev_type_count] = { do_op_uinteger, // ev_integer do_op_uinteger, // ev_uinteger do_op_uinteger, // ev_short + do_op_double, // ev_double do_op_invalid, // ev_invalid }; @@ -1123,6 +1278,24 @@ static operation_t op_short[ev_type_count] = { do_op_integer, // ev_integer do_op_uinteger, // ev_uinteger do_op_short, // ev_short + do_op_double, // ev_double + do_op_invalid, // ev_invalid +}; + +static operation_t op_double[ev_type_count] = { + do_op_invalid, // ev_void + do_op_invalid, // ev_string + do_op_float, // ev_float + do_op_vector, // ev_vector + do_op_invalid, // ev_entity + do_op_invalid, // ev_field + do_op_invalid, // ev_func + do_op_invalid, // ev_pointer + do_op_quaternion, // ev_quaternion + do_op_integer, // ev_integer + do_op_uinteger, // ev_uinteger + do_op_short, // ev_short + do_op_double, // ev_double do_op_invalid, // ev_invalid }; @@ -1139,6 +1312,7 @@ static operation_t op_compound[ev_type_count] = { do_op_compound, // ev_integer do_op_compound, // ev_uinteger do_op_compound, // ev_short + do_op_compound, // ev_double do_op_compound, // ev_invalid }; @@ -1155,6 +1329,7 @@ static operation_t *do_op[ev_type_count] = { op_integer, // ev_integer op_uinteger, // ev_uinteger op_short, // ev_short + op_double, // ev_double op_compound, // ev_invalid }; @@ -1203,13 +1378,15 @@ static expr_t * uop_float (int op, expr_t *e, expr_t *e1) { static int valid[] = { '+', '-', '!', '~', 'C', 0 }; + type_t *type; if (!valid_op (op, valid)) return error (e1, "invalid unary operator for float: %s", get_op_string (op)); if (op == '+') return e1; - if (op == 'C' && get_type (e) != &type_integer) + type = get_type (e); + if (op == 'C' && type != &type_integer && type != &type_double) return error (e1, "invalid cast of float"); if (!is_constant (e1)) return e; @@ -1222,7 +1399,11 @@ uop_float (int op, expr_t *e, expr_t *e1) case '~': return new_float_expr (~(int) expr_float (e1)); case 'C': - return new_integer_expr (expr_float (e1)); + if (type == &type_integer) { + return new_integer_expr (expr_float (e1)); + } else { + return new_double_expr (expr_float (e1)); + } } internal_error (e, "float unary op blew up"); } @@ -1420,6 +1601,38 @@ uop_short (int op, expr_t *e, expr_t *e1) internal_error (e, "short unary op blew up"); } +static expr_t * +uop_double (int op, expr_t *e, expr_t *e1) +{ + static int valid[] = { '+', '-', '!', 'C', 0 }; + type_t *type; + + if (!valid_op (op, valid)) + return error (e1, "invalid unary operator for double: %s", + get_op_string (op)); + if (op == '+') + return e1; + type = get_type (e); + if (op == 'C' && type != &type_integer && type != &type_float) + return error (e1, "invalid cast of double"); + if (!is_constant (e1)) + return e; + switch (op) { + case '-': + return new_double_expr (-expr_double (e1)); + case '!': + print_type (get_type (e)); + return new_integer_expr (!expr_double (e1)); + case 'C': + if (type == &type_integer) { + return new_integer_expr (expr_double (e1)); + } else { + return new_float_expr (expr_double (e1)); + } + } + internal_error (e, "float unary op blew up"); +} + static expr_t * uop_compound (int op, expr_t *e, expr_t *e1) { @@ -1446,6 +1659,7 @@ static unaryop_t do_unary_op[ev_type_count] = { uop_integer, // ev_integer uop_uinteger, // ev_uinteger uop_short, // ev_short + uop_double, // ev_double uop_compound, // ev_invalid }; @@ -1487,7 +1701,7 @@ fold_constants (expr_t *e) if (t1 >= ev_type_count || t2 >= ev_type_count || !do_op[t1] || !do_op[t1][t2]) - internal_error (e, "invalid type"); + internal_error (e, "invalid type %d %d", t1, t2); return do_op[t1][t2] (op, e, e1, e2); } return e; diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index b98cc7b99..675488e93 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -438,6 +438,9 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) case ev_string: label = va ("\\\"%s\\\"", quote_string (e->e.value->v.string_val)); break; + case ev_double: + label = va ("f %g", e->e.value->v.double_val); + break; case ev_float: label = va ("f %g", e->e.value->v.float_val); break; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 4970cc7cd..0773e0a8f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -611,6 +611,15 @@ new_string_expr (const char *string_val) return e; } +expr_t * +new_double_expr (double double_val) +{ + expr_t *e = new_expr (); + e->type = ex_value; + e->e.value = new_double_val (double_val); + return e; +} + expr_t * new_float_expr (float float_val) { @@ -845,6 +854,23 @@ is_float_val (expr_t *e) return 0; } +double +expr_double (expr_t *e) +{ + if (e->type == ex_nil) + return 0; + if (e->type == ex_value && e->e.value->lltype == ev_double) + return e->e.value->v.double_val; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_double) + return e->e.symbol->s.value->v.double_val; + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var + && e->e.symbol->s.def->constant + && is_double (e->e.symbol->s.def->type)) + return D_FLOAT (e->e.symbol->s.def); + internal_error (e, "not a double constant"); +} + float expr_float (expr_t *e) { @@ -1276,6 +1302,9 @@ test_expr (expr_t *e) } new = new_float_expr (0); break; + case ev_double: + new = new_double_expr (0); + break; case ev_vector: new = new_vector_expr (zero); break; @@ -1610,6 +1639,8 @@ unary_expr (int op, expr_t *e) case ev_func: case ev_pointer: internal_error (e, "type check failed!"); + case ev_double: + return new_double_expr (-expr_double (e)); case ev_float: return new_float_expr (-expr_float (e)); case ev_vector: @@ -1676,6 +1707,8 @@ unary_expr (int op, expr_t *e) case ev_string: s = expr_string (e); return new_integer_expr (!s || !s[0]); + case ev_double: + return new_integer_expr (!expr_double (e)); case ev_float: return new_integer_expr (!expr_float (e)); case ev_vector: @@ -1735,6 +1768,7 @@ unary_expr (int op, expr_t *e) case ev_func: case ev_pointer: case ev_vector: + case ev_double: return error (e, "invalid type for unary ~"); case ev_float: return new_float_expr (~(int) expr_float (e)); diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 1b234e9e4..0c9fea604 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -333,6 +333,7 @@ static keyword_t at_keywords[] = { // be supported (sanely) by v6 progs. static keyword_t qf_keywords[] = { {"quaternion", TYPE, &type_quaternion}, + {"double", TYPE, &type_double}, {"int", TYPE, &type_integer }, {"unsigned", TYPE, &type_integer },//FIXME {"function", TYPE, &type_function }, diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index c4c92f254..cd49b3970 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -87,6 +87,8 @@ operand_string (operand_t *op) case ev_string: return va ("\"%s\"", quote_string (op->o.value->v.string_val)); + case ev_double: + return va ("%g", op->o.value->v.double_val); case ev_float: return va ("%g", op->o.value->v.float_val); case ev_vector: @@ -159,6 +161,9 @@ print_operand (operand_t *op) case ev_string: printf ("\"%s\"", op->o.value->v.string_val); break; + case ev_double: + printf ("%g", op->o.value->v.double_val); + break; case ev_float: printf ("%g", op->o.value->v.float_val); break; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index d99a89cc4..81bd21ef9 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -76,6 +76,7 @@ type_t type_quaternion = { ev_quat, "quaternion" }; type_t type_integer = { ev_integer, "int" }; type_t type_uinteger = { ev_uinteger, "uint" }; type_t type_short = { ev_short, "short" }; +type_t type_double = { ev_double, "double" }; type_t *type_nil; type_t *type_default; @@ -101,6 +102,7 @@ type_t *ev_types[ev_type_count] = { &type_integer, &type_uinteger, &type_short, + &type_double, &type_invalid, }; @@ -180,6 +182,7 @@ free_type (type_t *type) case ev_integer: case ev_uinteger: case ev_short: + case ev_double: break; case ev_field: case ev_pointer: @@ -214,6 +217,7 @@ append_type (type_t *type, type_t *new) case ev_integer: case ev_uinteger: case ev_short: + case ev_double: internal_error (0, "append to basic type"); case ev_field: case ev_pointer: @@ -582,6 +586,9 @@ encode_type (dstring_t *encoding, const type_t *type) case ev_string: dasprintf (encoding, "*"); break; + case ev_double: + dasprintf (encoding, "d"); + break; case ev_float: dasprintf (encoding, "f"); break; @@ -685,6 +692,12 @@ is_integral (const type_t *type) return is_enum (type); } +int +is_double (const type_t *type) +{ + return type->type == ev_double; +} + int is_float (const type_t *type) { @@ -694,7 +707,7 @@ is_float (const type_t *type) int is_scalar (const type_t *type) { - return is_float (type) || is_integral (type); + return is_float (type) || is_integral (type) || is_double (type); } int @@ -830,6 +843,7 @@ type_size (const type_t *type) case ev_integer: case ev_uinteger: case ev_short: + case ev_double: case ev_type_count: return pr_type_size[type->type]; case ev_invalid: @@ -869,6 +883,7 @@ init_types (void) { static struct_def_t zero_struct[] = { {"string_val", &type_string}, + {"double_val", &type_double}, {"float_val", &type_float}, {"entity_val", &type_entity}, {"field_val", &type_field}, @@ -884,6 +899,7 @@ init_types (void) }; static struct_def_t param_struct[] = { {"string_val", &type_string}, + {"double_val", &type_double}, {"float_val", &type_float}, {"vector_val", &type_vector}, {"entity_val", &type_entity}, @@ -982,6 +998,7 @@ chain_initial_types (void) chain_type (&type_integer); chain_type (&type_uinteger); chain_type (&type_short); + chain_type (&type_double); } chain_type (&type_param); diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 29d6eabed..4f1ae9f82 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -132,6 +132,16 @@ new_string_val (const char *string_val) return find_value (&val); } +ex_value_t * +new_double_val (double double_val) +{ + ex_value_t val; + memset (&val, 0, sizeof (val)); + set_val_type (&val, &type_double); + val.v.double_val = double_val; + return find_value (&val); +} + ex_value_t * new_float_val (float float_val) { From 98216c6eb06fe5956e63230de31cc3bdaaf2f313 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 16:40:38 +0900 Subject: [PATCH 0266/3664] Fixed some missed doxygen updates --- include/QF/progs.h | 56 +++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index f3358c708..945145bd3 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1567,36 +1567,36 @@ struct progs_s { int zone_size; ///< set by user /// \name builtin functions - //@{ + ///@{ struct hashtab_s *builtin_hash; struct hashtab_s *builtin_num_hash; unsigned bi_next; unsigned (*bi_map) (progs_t *pr, unsigned binum); - //@} + ///@} /// \name symbol management - //@{ + ///@{ struct hashtab_s *function_hash; struct hashtab_s *global_hash; struct hashtab_s *field_hash; - //@} + ///@} /// \name load hooks - //@{ + ///@{ int num_load_funcs; int max_load_funcs; pr_load_func_t **load_funcs; /// cleared each load - //@{ + ///@{ int num_load_finish_funcs; int max_load_finish_funcs; pr_load_func_t **load_finish_funcs; - //@} - //@} + ///@} + ///@} /// \name string management - //@{ + ///@{ struct dstring_mem_s *ds_mem; strref_t *free_string_refs; strref_t *static_strings; @@ -1608,10 +1608,10 @@ struct progs_s { int num_strings; strref_t *pr_xtstr; int float_promoted; ///< for PR_Sprintf - //@} + ///@} /// \name memory map - //@{ + ///@{ dfunction_t *pr_functions; bfunction_t *function_table; char *pr_strings; @@ -1621,10 +1621,10 @@ struct progs_s { dstatement_t *pr_statements; pr_type_t *pr_globals; unsigned globals_size; - //@} + ///@} /// \name parameter block - //@{ + ///@{ pr_type_t *pr_return; pr_type_t *pr_params[MAX_PARMS]; pr_type_t *pr_real_params[MAX_PARMS]; @@ -1632,10 +1632,10 @@ struct progs_s { pr_type_t *pr_saved_params; int pr_saved_argc; int pr_param_size; ///< covers both params and return - //@} + ///@} /// \name edicts - //@{ + ///@{ edict_t **edicts; int max_edicts; ///< set by user int *num_edicts; @@ -1647,10 +1647,10 @@ struct progs_s { int pr_edict_size; ///< in bytes int pr_edictareasize; ///< for bounds checking, starts at 0 func_t edict_parse; - //@} + ///@} /// \name execution state - //@{ + ///@{ int pr_argc; qboolean pr_trace; @@ -1668,24 +1668,24 @@ struct progs_s { /// be considered valid if there is no .stack global. /// \note The return address and saved locals will not ever be on this /// stack. - //@{ + ///@{ pr_type_t *stack; pointer_t stack_bottom; int stack_size; ///< set by user - //@} + ///@} int localstack[LOCALSTACK_SIZE]; int localstack_used; - //@} + ///@} /// \name resources - //@{ + ///@{ pr_resource_t *resources; struct hashtab_s *resource_hash; - //@} + ///@} /// \name obj info - //@{ + ///@{ unsigned selector_index; unsigned selector_index_max; struct obj_list_s **selector_sels; @@ -1698,10 +1698,10 @@ struct progs_s { struct obj_list_s *unclaimed_proto_list; struct obj_list_s *module_list; struct obj_list_s *class_tree_list; - //@} + ///@} /// \name debug info - //@{ + ///@{ const char *debugfile; struct pr_debug_header_s *debug; struct pr_auxfunction_s *auxfunctions; @@ -1711,10 +1711,10 @@ struct progs_s { pr_type_t *watch; int wp_conditional; pr_type_t wp_val; - //@} + ///@} /// \name globals and fields needed by the VM - //@{ + ///@{ struct { float *time; ///< required for OP_STATE pr_int_t *self; ///< required for OP_STATE @@ -1726,7 +1726,7 @@ struct progs_s { pr_int_t think; ///< required for OP_STATE pr_int_t this; ///< optional for entity<->object linking } fields; - //@} + ///@} }; /** \addtogroup progs_data_access From 8920c59515eed6db31e6a47e5c54e3489bca8285 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 18:13:55 +0900 Subject: [PATCH 0267/3664] Find @override functions even when there's only one --- tools/qfcc/source/function.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 7f28a77b9..9120386b5 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -338,7 +338,7 @@ find_function (expr_t *fexpr, expr_t *params) return fexpr; for (func_count = 0; funcs[func_count]; func_count++) ; - if (func_count < 2) { + if (func_count < 1) { free (funcs); return fexpr; } From eb7f8251580cd8515bc87fb7e96f1b8f7a0aa3ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 18:14:22 +0900 Subject: [PATCH 0268/3664] Test for full-float % --- tools/qfcc/test/modulo.r | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/test/modulo.r b/tools/qfcc/test/modulo.r index 4d59fdf87..1e02fcaa0 100644 --- a/tools/qfcc/test/modulo.r +++ b/tools/qfcc/test/modulo.r @@ -57,5 +57,8 @@ float main (void) res |= test ("foo", foo, -5, -3, -2); res |= test ("bar", bar, -5, -3, -2); res |= test ("baz", baz, -5, -3, 0); + + res |= test ("foo", foo, 5, 3.5, 1.5); + res |= test ("foo", foo, -5, 3.5, -1.5); return res; } From 2cd62fe01b5ada4cd333359889e678fe21874cc9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 18:15:34 +0900 Subject: [PATCH 0269/3664] Fix several double-related bug float is promoted to double through ... for non-v6 code. PR_Sprintf has custom param access via P_*, messed up doubles. --- libs/gamecode/pr_load.c | 2 ++ libs/gamecode/pr_opcode.c | 1 + libs/gamecode/pr_strings.c | 2 ++ tools/qfcc/include/obj_file.h | 13 +++++++++++++ tools/qfcc/include/qfcc.h | 1 + tools/qfcc/source/expr.c | 9 ++++++--- tools/qfcc/source/statements.c | 3 +-- tools/qfcc/test/triangle.r | 2 +- 8 files changed, 27 insertions(+), 6 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 9fee72574..8bc554296 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -202,6 +202,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) base -= sizeof (progs); // offsets are from file start heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize); + pr->float_promoted = progs.version == PROG_VERSION; + if (pr->edicts) { *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); } diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index a2a344a1e..f18fd2b42 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -77,6 +77,7 @@ VISIBLE const char *pr_type_name[ev_type_count] = { "integer", "uinteger", "short", + "double", "invalid", }; diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 684551fda..85602e3d2 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -649,6 +649,8 @@ free_fmt_item (fmt_item_t *fi) #undef P_var #define P_var(p,n,t) (args[n]->t##_var) +#undef P_DOUBLE +#define P_DOUBLE(p,n) (*(double *) (args[n])) VISIBLE void PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, const char *format, int count, pr_type_t **args) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 0e6096028..c32c67eb2 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -305,6 +305,19 @@ enum { */ #define QFO_var(q, s, t, o) ((q)->spaces[s].d.data[o].t##_var) +/** Access a double variable in the object file. Can be assigned to. + + \par QC type: + \c double + \param q pointer to ::qfo_t struct + \param s space index + \param o offset into object file data space + \return double lvalue + + \hideinitializer +*/ +#define QFO_DOUBLE(q, s, o) (*(double *) ((q)->spaces[s].d.data + o)) + /** Access a float variable in the object file. Can be assigned to. \par QC type: diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 1a1793b34..e428831cb 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -92,6 +92,7 @@ extern pr_info_t pr; #define GETSTR(s) (pr.strings->strings + (s)) #define D_var(t, d) ((d)->space->data[(d)->offset].t##_var) +#define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset)) #define D_FLOAT(d) D_var (float, d) #define D_INT(d) D_var (integer, d) #define D_VECTOR(d) D_var (vector, d) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 0773e0a8f..d40214d77 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -867,7 +867,7 @@ expr_double (expr_t *e) if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var && e->e.symbol->s.def->constant && is_double (e->e.symbol->s.def->type)) - return D_FLOAT (e->e.symbol->s.def); + return D_DOUBLE (e->e.symbol->s.def); internal_error (e, "not a double constant"); } @@ -1915,6 +1915,10 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params) if (is_integer_val (e) && options.code.progsversion == PROG_ID_VERSION) convert_int (e); + if (is_float (get_type (e)) + && options.code.progsversion != PROG_ID_VERSION) { + t = &type_double; + } if (is_integer_val (e) && options.warnings.vararg_integer) warning (e, "passing integer constant into ... function"); } @@ -2611,8 +2615,7 @@ cast_expr (type_t *type, expr_t *e) e->e.value = convert_value (val, type); e->type = ex_value; c = e; - } else if ((is_float (type) && is_integral (e_type)) - || (is_integral (type) && is_float (e_type))) { + } else if (is_scalar (type) && is_scalar (e_type)) { c = new_unary_expr ('C', e); c->e.expr.type = type; } else if (e->type == ex_uexpr && e->e.expr.op == '.') { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index cd49b3970..072d175cf 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -958,8 +958,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) statement_t *s; src_type = get_type (e->e.expr.e1); - if ((src_type->type == ev_integer && type->type == ev_float) - || (src_type->type == ev_float && type->type == ev_integer)) { + if (is_scalar (src_type) && is_scalar (type)) { operand_t *src = 0; sblock = statement_subexpr (sblock, e->e.expr.e1, &src); *op = temp_operand (e->e.expr.type); diff --git a/tools/qfcc/test/triangle.r b/tools/qfcc/test/triangle.r index 6ef592ace..cec1f6884 100644 --- a/tools/qfcc/test/triangle.r +++ b/tools/qfcc/test/triangle.r @@ -1,6 +1,6 @@ void printf (string fmt, ...) = #0; float (string s) stof = #0; -float (float x) sqrt = #0; +@overload float (float x) sqrt = #0; float heron (float a, float b, float c) From 533fb8acc9383d3ea2d0198263adf138f9202b03 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 20:08:59 +0900 Subject: [PATCH 0270/3664] Implement double constants --- libs/gamecode/pr_debug.c | 7 +++++- tools/qfcc/include/expr.h | 2 +- tools/qfcc/source/dump_globals.c | 3 +++ tools/qfcc/source/expr.c | 8 +++++++ tools/qfcc/source/qc-lex.l | 27 +++++++++++++++++++++ tools/qfcc/source/value.c | 40 ++++++++++++++++++++++++++++++++ tools/qfcc/test/Makefile.am | 10 ++++++++ tools/qfcc/test/deadbool.r | 2 +- tools/qfcc/test/double.r | 25 ++++++++++++++++++++ tools/qfcc/test/state.r | 10 ++++---- tools/qfcc/test/test-harness.c | 8 +++++-- 11 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 tools/qfcc/test/double.r diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 8973e318c..174987135 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -692,7 +692,12 @@ value_string (progs_t *pr, etype_t type, pr_type_t *val) case ev_uinteger: dsprintf (line, "$%08x", val->uinteger_var); break; - default: + case ev_double: + dsprintf (line, "%g", *(double *)val); + break; + case ev_short: + case ev_invalid: + case ev_type_count: //dsprintf (line, "bad type %i", type); dsprintf (line, "<%x %x %x %x>", val[0].integer_var, val[1].integer_var, diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index b11e93c2c..90e4f6313 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -174,7 +174,7 @@ typedef struct ex_value_s { etype_t lltype; union { const char *string_val; ///< string constant - float double_val; ///< double constant + double double_val; ///< double constant float float_val; ///< float constant float vector_val[3]; ///< vector constant int entity_val; ///< entity constant diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 71b769629..6bebf5bb5 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -97,6 +97,9 @@ dump_def (progs_t *pr, ddef_t *def, int indent) case ev_float: comment = va (" %g", G_FLOAT (pr, offset)); break; + case ev_double: + comment = va (" %.17g", G_DOUBLE (pr, offset)); + break; case ev_vector: comment = va (" '%g %g %g'", G_VECTOR (pr, offset)[0], diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index d40214d77..46ed0aeaa 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2273,6 +2273,14 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) e = e1->e.expr.e2; break; } + if (e1->e.expr.op == 'A') { + if (!t) + t = e1->e.expr.type; + if (e2) { + e2 = binary_expr ('+', e1->e.expr.e2, e2); + } + return address_expr (e1->e.expr.e1, e2, t); + } return error (e1, "invalid type for unary &"); case ex_uexpr: if (e1->e.expr.op == '.') { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 0c9fea604..d17cad55e 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -93,6 +93,8 @@ B [01] X [0-9a-fA-F] ID [a-zA-Z_][a-zA-Z_0-9]* FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)? +FLOATf {FLOAT}[fF] +FLOATd {FLOAT}[dD] INT ({D}+|0[xX]{X}+|0[bB]{B}) RANGE \.\. ELLIPSIS \.\.\. @@ -136,10 +138,35 @@ STRING \"(\\.|[^"\\])*\" } {FLOAT} { + // advanced code defaults to double, but traditional + // and extended code defaults to float + if (options.traditional < 1) { + double d = strtod (yytext, 0); + qc_yylval.expr = new_double_expr (d); + } else { + float f = strtof (yytext, 0); + qc_yylval.expr = new_float_expr (f); + } + return VALUE; + } +{FLOATf} { float f = strtof (yytext, 0); qc_yylval.expr = new_float_expr (f); return VALUE; } +{FLOATd} { + // advanced code defaults to double, but traditional + // and extended code defaults to float + if (options.traditional < 1) { + double d = strtod (yytext, 0); + qc_yylval.expr = new_double_expr (d); + } else { + float f = strtof (yytext, 0); + qc_yylval.expr = new_float_expr (f); + warning (0, "truncating double constant to float"); + } + return VALUE; + } {ID} { int tok = keyword_or_id(yytext); diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 4f1ae9f82..fc2024a57 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -69,6 +69,7 @@ typedef struct { ex_pointer_t pointer; float quaternion_val[4]; int integer_val; + double double_val; } i; } immediate_t; @@ -275,6 +276,7 @@ static hashtab_t *func_imm_defs; static hashtab_t *pointer_imm_defs; static hashtab_t *quaternion_imm_defs; static hashtab_t *integer_imm_defs; +static hashtab_t *double_imm_defs; static void imm_free (void *_imm, void *unused) @@ -306,6 +308,8 @@ imm_get_hash (const void *_imm, void *_tab) } else if (tab == &quaternion_imm_defs) { return Hash_Buffer (&imm->i.quaternion_val, sizeof (&imm->i.quaternion_val)); + } else if (tab == &double_imm_defs) { + return Hash_Buffer (&imm->i.double_val, sizeof (&imm->i.double_val)); } else if (tab == &integer_imm_defs) { return imm->i.integer_val; } else { @@ -340,6 +344,8 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab) sizeof (imm1->i.pointer)); } else if (tab == &quaternion_imm_defs) { return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val); + } else if (tab == &double_imm_defs) { + return imm1->i.double_val == imm2->i.double_val; } else if (tab == &integer_imm_defs) { return imm1->i.integer_val == imm2->i.integer_val; } else { @@ -362,6 +368,24 @@ value_as_float (ex_value_t *value) return value->v.integer_val; if (value->lltype == ev_short) return value->v.short_val; + if (value->lltype == ev_double) + return value->v.double_val; + if (value->lltype == ev_float) + return value->v.float_val; + return 0; +} + +static double +value_as_double (ex_value_t *value) +{ + if (value->lltype == ev_uinteger) + return value->v.uinteger_val; + if (value->lltype == ev_integer) + return value->v.integer_val; + if (value->lltype == ev_short) + return value->v.short_val; + if (value->lltype == ev_double) + return value->v.double_val; if (value->lltype == ev_float) return value->v.float_val; return 0; @@ -376,6 +400,8 @@ value_as_int (ex_value_t *value) return value->v.integer_val; if (value->lltype == ev_short) return value->v.short_val; + if (value->lltype == ev_double) + return value->v.double_val; if (value->lltype == ev_float) return value->v.float_val; return 0; @@ -390,6 +416,8 @@ value_as_uint (ex_value_t *value) return value->v.integer_val; if (value->lltype == ev_short) return value->v.short_val; + if (value->lltype == ev_double) + return value->v.double_val; if (value->lltype == ev_float) return value->v.float_val; return 0; @@ -405,6 +433,9 @@ convert_value (ex_value_t *value, type_t *type) if (is_float (type)) { float val = value_as_float (value); return new_float_val (val); + } else if (is_double (type)) { + double val = value_as_double (value); + return new_double_val (val); } else if (type->type == ev_short) { int val = value_as_int (value); return new_short_val (val); @@ -504,6 +535,10 @@ emit_value (ex_value_t *value, def_t *def) tab = quaternion_imm_defs; type = &type_quaternion; break; + case ev_double: + tab = double_imm_defs; + type = &type_double; + break; default: internal_error (0, 0); } @@ -601,6 +636,7 @@ clear_immediates (void) Hash_FlushTable (pointer_imm_defs); Hash_FlushTable (quaternion_imm_defs); Hash_FlushTable (integer_imm_defs); + Hash_FlushTable (double_imm_defs); } else { value_table = Hash_NewTable (16381, 0, 0, 0); Hash_SetHashCompare (value_table, value_get_hash, value_compare); @@ -634,6 +670,10 @@ clear_immediates (void) integer_imm_defs = Hash_NewTable (16381, 0, imm_free, &integer_imm_defs); Hash_SetHashCompare (integer_imm_defs, imm_get_hash, imm_compare); + + double_imm_defs = + Hash_NewTable (16381, 0, imm_free, &double_imm_defs); + Hash_SetHashCompare (double_imm_defs, imm_get_hash, imm_compare); } def = make_symbol (".zero", &type_zero, 0, sc_extern)->s.def; diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 680fdbdd7..d3510f5d9 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -33,6 +33,7 @@ test_progs_dat=\ chewed-return.dat \ comma-expr.dat \ deadbool.dat \ + double.dat \ enum.dat \ fordecl.dat \ func-expr.dat \ @@ -111,6 +112,15 @@ deadbool.run: Makefile build-run include ./$(DEPDIR)/deadbool.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/deadbool.Qo +double_dat_SOURCES=double.r +double_obj=$(double_dat_SOURCES:.r=.qfo) +double.dat$(EXEEXT): $(double_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(double_obj) +double.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/double.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/double.Qo + enum_dat_SOURCES=enum.r enum_obj=$(enum_dat_SOURCES:.r=.qfo) enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/deadbool.r b/tools/qfcc/test/deadbool.r index c4869b293..c56aa0f10 100644 --- a/tools/qfcc/test/deadbool.r +++ b/tools/qfcc/test/deadbool.r @@ -9,7 +9,7 @@ void foo (void) return; if (!time) { ent = spawn (); - ent.f = time + 0.1; + ent.f = time + 0.1f; } } diff --git a/tools/qfcc/test/double.r b/tools/qfcc/test/double.r new file mode 100644 index 000000000..db02adbac --- /dev/null +++ b/tools/qfcc/test/double.r @@ -0,0 +1,25 @@ +void printf (string fmt, ...) = #0; +# define M_PI 3.14159265358979323846 + +union { + double d; + int i[2]; +} type_pun; + +int +test_format () +{ + int fail = 0; + type_pun.d = M_PI; + printf ("%g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]); + //printf ("%08x%08x\n", type_pun.i[1], type_pun.i[0]); + return fail; +} + +int +main () +{ + int fail = 0; + fail |= test_format (); + return fail; +} diff --git a/tools/qfcc/test/state.r b/tools/qfcc/test/state.r index 7fec3c2d0..a7be65754 100644 --- a/tools/qfcc/test/state.r +++ b/tools/qfcc/test/state.r @@ -13,7 +13,7 @@ state0 (void) [$frame1, state1] { if (self.frame != $frame1 || self.think != state1 - || self.nextthink != 0.1) { + || self.nextthink != 0.1f) { printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink); exit (1); } @@ -21,10 +21,10 @@ state0 (void) void state1 (void) -[$frame2, state2, 0.2] +[$frame2, state2, 0.2f] { if (self.frame != $frame2 || self.think != state2 - || self.nextthink != 0.2) { + || self.nextthink != 0.2f) { printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink); exit (1); } @@ -32,10 +32,10 @@ state1 (void) void state2 (void) -[$frame0, state0, 0.5] +[$frame0, state0, 0.5f] { if (self.frame != $frame0 || self.think != state0 - || self.nextthink != 0.5) { + || self.nextthink != 0.5f) { printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink); exit (1); } diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index dcb251037..a8f829cd9 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -135,9 +135,13 @@ init_qf (void) Memory_Init (malloc (1024 * 1024), 1024 * 1024); - Cvar_Get ("pr_debug", "2", 0, 0, 0); + cvar_t *debug = Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "2", 0, 0, 0); + if (options.trace > 1) { + Cvar_SetValue (debug, 4); + } + pr.edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; @@ -207,7 +211,7 @@ parse_options (int argc, char **argv) options.flote = 1; break; case 't': - options.trace = 1; + options.trace++; break; case 'h': usage (0); From 5d8d805b60e98f80bbdf9e8db5067301ab4be064 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 20:39:12 +0900 Subject: [PATCH 0271/3664] Fix test for single overload functions All functions are stored in the overload functions table, even those that are never explicitly overloaded, but only explicitly overloaded functions (those with @overload) use the type-qualified naming. --- tools/qfcc/source/function.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 9120386b5..bd37d6d05 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -338,9 +338,12 @@ find_function (expr_t *fexpr, expr_t *params) return fexpr; for (func_count = 0; funcs[func_count]; func_count++) ; - if (func_count < 1) { - free (funcs); - return fexpr; + if (func_count < 2) { + f = (overloaded_function_t *) funcs[0]; + if (func_count && !f->overloaded) { + free (funcs); + return fexpr; + } } type.t.func.type = ((overloaded_function_t *) funcs[0])->type->t.func.type; dummy.type = find_type (&type); From 7e09a944691971fdebb7cd08db896d11866e2cac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 20:42:12 +0900 Subject: [PATCH 0272/3664] Fix "casts" between signed and unsigned int --- tools/qfcc/source/expr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 46ed0aeaa..013d55d81 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2623,6 +2623,8 @@ cast_expr (type_t *type, expr_t *e) e->e.value = convert_value (val, type); e->type = ex_value; c = e; + } else if (is_integral (type) && is_integral (e_type)) { + c = new_alias_expr (type, e); } else if (is_scalar (type) && is_scalar (e_type)) { c = new_unary_expr ('C', e); c->e.expr.type = type; From 7e7e0526dd3c63ee23ed89fd2f055799169e76d6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 20:42:36 +0900 Subject: [PATCH 0273/3664] Fix a double constant issue There will be more of these :/ --- ruamoko/game/Axe.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/game/Axe.r b/ruamoko/game/Axe.r index 06c4ca083..2ea71f0ef 100644 --- a/ruamoko/game/Axe.r +++ b/ruamoko/game/Axe.r @@ -32,7 +32,7 @@ source = s.origin + '0 0 16'; traceline (source, source + v_forward * 64, NO, s); - if (trace_fraction == 1.0) + if (trace_fraction == 1.0f) return; org = trace_endpos - v_forward * 4; From 0542daacdf1a315ffa40f2931cb4561aecbfca43 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Feb 2020 23:36:36 +0900 Subject: [PATCH 0274/3664] Create more double related tests Including catching warnings :) (yay -Werror) --- tools/qfcc/source/expr_binary.c | 188 +++++++++++++++++++++++-- tools/qfcc/test/Makefile.am | 22 ++- tools/qfcc/test/build-compile-fail-run | 15 ++ tools/qfcc/test/double-float-compare.r | 7 + tools/qfcc/test/double-int-compare.r | 7 + tools/qfcc/test/double.r | 43 +++++- 6 files changed, 265 insertions(+), 17 deletions(-) create mode 100755 tools/qfcc/test/build-compile-fail-run create mode 100644 tools/qfcc/test/double-float-compare.r create mode 100644 tools/qfcc/test/double-int-compare.r diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 6dd7c1177..0f2a1e256 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -47,6 +47,7 @@ typedef struct { static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2); static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2); +static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); static expr_type_t string_string[] = { {'+', &type_string}, @@ -111,6 +112,21 @@ static expr_type_t float_integer[] = { #define float_uinteger float_integer #define float_short float_integer +static expr_type_t float_double[] = { + {'+', &type_double, &type_double, 0}, + {'-', &type_double, &type_double, 0}, + {'*', &type_double, &type_double, 0}, + {'/', &type_double, &type_double, 0}, + {'%', &type_double, &type_double, 0}, + {EQ, 0, 0, 0, double_compare}, + {NE, 0, 0, 0, double_compare}, + {LE, 0, 0, 0, double_compare}, + {GE, 0, 0, 0, double_compare}, + {LT, 0, 0, 0, double_compare}, + {GT, 0, 0, 0, double_compare}, + {0, 0} +}; + static expr_type_t vector_float[] = { {'*', &type_vector}, {'/', 0, 0, 0, inverse_multiply}, @@ -130,6 +146,12 @@ static expr_type_t vector_vector[] = { #define vector_uinteger vector_float #define vector_short vector_float +static expr_type_t vector_double[] = { + {'*', &type_vector}, + {'/', 0, 0, 0, inverse_multiply}, + {0, 0} +}; + static expr_type_t entity_entity[] = { {EQ, &type_integer}, {NE, &type_integer}, @@ -195,6 +217,12 @@ static expr_type_t quat_integer[] = { #define quat_uinteger quat_integer #define quat_short quat_integer +static expr_type_t quat_double[] = { + {'*', &type_quaternion}, + {'/', 0, 0, 0, inverse_multiply}, + {0, 0} +}; + static expr_type_t integer_float[] = { {'+', &type_float, &type_float, 0}, {'-', &type_float, &type_float, 0}, @@ -290,6 +318,21 @@ static expr_type_t integer_short[] = { {0, 0} }; +static expr_type_t integer_double[] = { + {'+', &type_double, &type_double, 0}, + {'-', &type_double, &type_double, 0}, + {'*', &type_double, &type_double, 0}, + {'/', &type_double, &type_double, 0}, + {'%', &type_double, &type_double, 0}, + {EQ, &type_integer, &type_double, 0}, + {NE, &type_integer, &type_double, 0}, + {LE, &type_integer, &type_double, 0}, + {GE, &type_integer, &type_double, 0}, + {LT, &type_integer, &type_double, 0}, + {GT, &type_integer, &type_double, 0}, + {0, 0} +}; + #define uinteger_float integer_float #define uinteger_vector integer_vector #define uinteger_pointer integer_pointer @@ -335,6 +378,7 @@ static expr_type_t uinteger_uinteger[] = { {0, 0} }; #define uinteger_short uinteger_integer +#define uinteger_double integer_double #define short_float integer_float #define short_vector integer_vector @@ -400,8 +444,66 @@ static expr_type_t short_short[] = { {GT, &type_integer}, {0, 0} }; +#define short_double integer_double -static expr_type_t *string_x[] = { +static expr_type_t double_float[] = { + {'+', &type_double, 0, &type_double}, + {'-', &type_double, 0, &type_double}, + {'*', &type_double, 0, &type_double}, + {'/', &type_double, 0, &type_double}, + {'%', &type_double, 0, &type_double}, + {EQ, 0, 0, 0, double_compare}, + {NE, 0, 0, 0, double_compare}, + {LE, 0, 0, 0, double_compare}, + {GE, 0, 0, 0, double_compare}, + {LT, 0, 0, 0, double_compare}, + {GT, 0, 0, 0, double_compare}, + {0, 0} +}; + +static expr_type_t double_vector[] = { + {'*', &type_vector}, + {0, 0} +}; + +static expr_type_t double_quat[] = { + {'*', &type_quaternion}, + {0, 0} +}; + +static expr_type_t double_integer[] = { + {'+', &type_double, 0, &type_double}, + {'-', &type_double, 0, &type_double}, + {'*', &type_double, 0, &type_double}, + {'/', &type_double, 0, &type_double}, + {'%', &type_double, 0, &type_double}, + {EQ, 0, 0, 0, double_compare}, + {NE, 0, 0, 0, double_compare}, + {LE, 0, 0, 0, double_compare}, + {GE, 0, 0, 0, double_compare}, + {LT, 0, 0, 0, double_compare}, + {GT, 0, 0, 0, double_compare}, + {0, 0} +}; +#define double_uinteger double_integer +#define double_short double_integer + +static expr_type_t double_double[] = { + {'+', &type_double}, + {'-', &type_double}, + {'*', &type_double}, + {'/', &type_double}, + {'%', &type_double}, + {EQ, &type_integer}, + {NE, &type_integer}, + {LE, &type_integer}, + {GE, &type_integer}, + {LT, &type_integer}, + {GT, &type_integer}, + {0, 0} +}; + +static expr_type_t *string_x[ev_type_count] = { 0, // ev_void string_string, 0, // ev_float @@ -414,9 +516,10 @@ static expr_type_t *string_x[] = { 0, // ev_integer 0, // ev_uinteger 0, // ev_short + 0, // ev_double }; -static expr_type_t *float_x[] = { +static expr_type_t *float_x[ev_type_count] = { 0, // ev_void 0, // ev_string float_float, @@ -429,9 +532,10 @@ static expr_type_t *float_x[] = { float_integer, float_uinteger, float_short, + float_double, }; -static expr_type_t *vector_x[] = { +static expr_type_t *vector_x[ev_type_count] = { 0, // ev_void 0, // ev_string vector_float, @@ -444,9 +548,10 @@ static expr_type_t *vector_x[] = { vector_integer, vector_uinteger, vector_short, + vector_double, }; -static expr_type_t *entity_x[] = { +static expr_type_t *entity_x[ev_type_count] = { 0, // ev_void 0, // ev_string 0, // ev_float @@ -459,9 +564,10 @@ static expr_type_t *entity_x[] = { 0, // ev_integer 0, // ev_uinteger 0, // ev_short + 0, // ev_double }; -static expr_type_t *field_x[] = { +static expr_type_t *field_x[ev_type_count] = { 0, // ev_void 0, // ev_string 0, // ev_float @@ -474,9 +580,10 @@ static expr_type_t *field_x[] = { 0, // ev_integer 0, // ev_uinteger 0, // ev_short + 0, // ev_double }; -static expr_type_t *func_x[] = { +static expr_type_t *func_x[ev_type_count] = { 0, // ev_void 0, // ev_string 0, // ev_float @@ -489,9 +596,10 @@ static expr_type_t *func_x[] = { 0, // ev_integer 0, // ev_uinteger 0, // ev_short + 0, // ev_double }; -static expr_type_t *pointer_x[] = { +static expr_type_t *pointer_x[ev_type_count] = { 0, // ev_void 0, // ev_string 0, // ev_float @@ -504,9 +612,10 @@ static expr_type_t *pointer_x[] = { pointer_integer, pointer_uinteger, pointer_short, + 0, // ev_double }; -static expr_type_t *quat_x[] = { +static expr_type_t *quat_x[ev_type_count] = { 0, // ev_void 0, // ev_string quat_float, @@ -519,9 +628,10 @@ static expr_type_t *quat_x[] = { quat_integer, quat_uinteger, quat_short, + quat_double, }; -static expr_type_t *integer_x[] = { +static expr_type_t *integer_x[ev_type_count] = { 0, // ev_void 0, // ev_string integer_float, @@ -534,9 +644,10 @@ static expr_type_t *integer_x[] = { integer_integer, integer_uinteger, integer_short, + integer_double, }; -static expr_type_t *uinteger_x[] = { +static expr_type_t *uinteger_x[ev_type_count] = { 0, // ev_void 0, // ev_string uinteger_float, @@ -549,9 +660,10 @@ static expr_type_t *uinteger_x[] = { uinteger_integer, uinteger_uinteger, uinteger_short, + uinteger_double, }; -static expr_type_t *short_x[] = { +static expr_type_t *short_x[ev_type_count] = { 0, // ev_void 0, // ev_string short_float, @@ -564,9 +676,26 @@ static expr_type_t *short_x[] = { short_integer, short_uinteger, short_short, + short_double, }; -static expr_type_t **binary_expr_types[] = { +static expr_type_t *double_x[ev_type_count] = { + 0, // ev_void + 0, // ev_string + double_float, + double_vector, + 0, // ev_entity + 0, // ev_field + 0, // ev_func + 0, // ev_pointer + double_quat, + double_integer, + double_uinteger, + double_short, + double_double, +}; + +static expr_type_t **binary_expr_types[ev_type_count] = { 0, // ev_void string_x, float_x, @@ -579,6 +708,7 @@ static expr_type_t **binary_expr_types[] = { integer_x, uinteger_x, short_x, + double_x }; static expr_t * @@ -609,6 +739,36 @@ inverse_multiply (int op, expr_t *e1, expr_t *e2) return binary_expr ('*', e1, binary_expr ('/', one, e2)); } +static expr_t * +double_compare (int op, expr_t *e1, expr_t *e2) +{ + type_t *t1 = get_type (e1); + type_t *t2 = get_type (e2); + expr_t *e; + + if ((is_double (t1) && is_float (t2)) + || (is_float (t1) && is_double (t2))) { + } + if (is_double (t1)) { + if (is_float (t2)) { + warning (e2, "comparison between double and float"); + } else if (!is_constant (e2)) { + warning (e2, "comparison between double and integer"); + } + e2 = cast_expr (&type_double, e2); + } else { + if (is_float (t1)) { + warning (e1, "comparison between float and double"); + } else if (!is_constant (e1)) { + warning (e1, "comparison between integer and double"); + } + e1 = cast_expr (&type_double, e1); + } + e = new_binary_expr (op, e1, e2); + e->e.expr.type = &type_double; + return e; +} + static expr_t * invalid_binary_expr (int op, expr_t *e1, expr_t *e2) { @@ -778,9 +938,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2) et1 = low_level_type (t1); et2 = low_level_type (t2); - if (et1 > ev_short || !binary_expr_types[et1]) + if (et1 >= ev_type_count || !binary_expr_types[et1]) return invalid_binary_expr(op, e1, e2); - if (et2 > ev_short || !binary_expr_types[et1][et2]) + if (et2 >= ev_type_count || !binary_expr_types[et1][et2]) return invalid_binary_expr(op, e1, e2); expr_type = binary_expr_types[et1][et2]; while (expr_type->op && expr_type->op != op) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index d3510f5d9..531c621a1 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -58,11 +58,23 @@ test_progs_dat=\ fail_progs_dat= +test_build_errors=\ + double-int-compare.r \ + double-float-compare.r + +fail_build_errors= + test_defspace_src=\ tw-defspace.c tw-diagnostic.c tw-strpool.c -TESTS=$(test_bins) $(test_progs_dat:.dat=.run) -XFAIL_TESTS=$(fail_bins) $(fail_progs_dat:.dat=.run) +TESTS=\ + $(test_bins) \ + $(test_progs_dat:.dat=.run) \ + $(test_build_errors:.r=.run) +XFAIL_TESTS=\ + $(fail_bins) \ + $(fail_progs_dat:.dat=.run) \ + $(fail_build_errors:.r=.run) check_PROGRAMS=test-harness $(test_progs_dat) $(test_bins) @@ -121,6 +133,12 @@ double.run: Makefile build-run include ./$(DEPDIR)/double.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/double.Qo +double-int-compare.run$(EXEEXT): double-int-compare.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +double-float-compare.run$(EXEEXT): double-float-compare.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + enum_dat_SOURCES=enum.r enum_obj=$(enum_dat_SOURCES:.r=.qfo) enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/build-compile-fail-run b/tools/qfcc/test/build-compile-fail-run new file mode 100755 index 000000000..294727d96 --- /dev/null +++ b/tools/qfcc/test/build-compile-fail-run @@ -0,0 +1,15 @@ +#! /bin/sh + +script=$1 +shift + +cat > $script < Date: Sat, 15 Feb 2020 02:19:55 +0900 Subject: [PATCH 0275/3664] Start on alignment test Currently fails (deliberately, WIP) --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/alignment.r | 9 +++++++++ 2 files changed, 19 insertions(+) create mode 100644 tools/qfcc/test/alignment.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 531c621a1..cdc9d8c01 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -29,6 +29,7 @@ test_bins=\ fail_bins= test_progs_dat=\ + alignment.dat \ chewed-alias.dat \ chewed-return.dat \ comma-expr.dat \ @@ -88,6 +89,15 @@ test_harness_DEPENDENCIES= $(QFCC_TEST_DEPS) r_depfiles_remade= +alignment_dat_SOURCES=alignment.r +alignment_obj=$(alignment_dat_SOURCES:.r=.qfo) +alignment.dat$(EXEEXT): $(alignment_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(alignment_obj) +alignment.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/alignment.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/alignment.Qo + chewed_alias_dat_SOURCES=chewed-alias.r chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo) chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/alignment.r b/tools/qfcc/test/alignment.r new file mode 100644 index 000000000..819f45d30 --- /dev/null +++ b/tools/qfcc/test/alignment.r @@ -0,0 +1,9 @@ +int a; +double b; +int c; +double d; + +int main() +{ + return 1; +} From a4a57b6ffda8bae97c49677b1a1a8511bb185d1f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 02:21:21 +0900 Subject: [PATCH 0276/3664] Implement aligned allocations --- tools/qfcc/include/defspace.h | 21 ++++++++ tools/qfcc/include/type.h | 1 + tools/qfcc/source/class.c | 37 +++++++------- tools/qfcc/source/def.c | 14 +++++- tools/qfcc/source/defspace.c | 94 ++++++++++++++++++++++++++--------- tools/qfcc/source/function.c | 1 + tools/qfcc/source/struct.c | 6 +++ tools/qfcc/source/type.c | 46 +++++++++++------ 8 files changed, 161 insertions(+), 59 deletions(-) diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index bd4b68920..ef6036286 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -109,6 +109,27 @@ defspace_t *defspace_new (ds_type_t type); */ int defspace_alloc_loc (defspace_t *space, int size); +/** Allocate space from the defspace's backing memory. + + If the memory is fragmented, then the first available location at least + as large as \a size plus padding for alignment is returned. This means + that freeing a location then allocating the same amount of space may + return a different location. + + If memory cannot be allocated (there is no free space in the currently + available memory and defspace_t::grow is null), then an internal error + will be generated. + + \param space The space from which to allocate data. + \param size The amount of pr_type_t words to allocated. int and float + need 1 word, vector 3 words, and quaternion 4. + \param alignment The alignment of the allocated space. + \return The offset of the first word of the freshly allocated + space. May be 0 if the allocated space is at the beginning + of the defspace. +*/ +int defspace_alloc_aligned_loc (defspace_t *space, int size, int alignment); + /** Free a block of contiguous words, returning them to the defspace. The block to be freed is specified by \a ofs indicating the offset of the diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index d6a43816e..6944db353 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -63,6 +63,7 @@ typedef enum { typedef struct type_s { etype_t type; ///< ev_invalid means structure/array etc const char *name; + int alignment; ///< required alignment for instances /// function/pointer/array/struct types are more complex ty_meta_e meta; union { diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index adeb4d4bf..e0d601aa9 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -68,28 +68,29 @@ static hashtab_t *category_hash; static hashtab_t *protocol_hash; // these will be built up further -type_t type_obj_selector = { ev_invalid, 0, ty_struct}; -type_t type_SEL = { ev_pointer, "SEL", ty_none, {{&type_obj_selector}}}; -type_t type_IMP = { ev_func, "IMP", ty_none, +type_t type_obj_selector = { ev_invalid, 0, 0, ty_struct}; +type_t type_SEL = { ev_pointer, "SEL", 1, ty_none, {{&type_obj_selector}}}; +type_t type_IMP = { ev_func, "IMP", 1, ty_none, {{&type_id, -3, {&type_id, &type_SEL}}}}; -type_t type_obj_super = { ev_invalid, 0 }; -type_t type_SuperPtr = { ev_pointer, 0, ty_none, {{&type_obj_super}}}; -type_t type_supermsg = { ev_func, ".supermsg", ty_none, +type_t type_obj_super = { ev_invalid, 0, 0 }; +type_t type_SuperPtr = { ev_pointer, 0, 1, ty_none, {{&type_obj_super}}}; +type_t type_supermsg = { ev_func, ".supermsg", 1, ty_none, {{&type_id, -3, {&type_SuperPtr, &type_SEL}}}}; -type_t type_obj_method = { ev_invalid, 0, ty_struct }; -type_t type_obj_method_description = { ev_invalid, 0, ty_struct }; -type_t type_obj_category = { ev_invalid, 0, ty_struct}; -type_t type_obj_ivar = { ev_invalid, 0, ty_struct}; -type_t type_obj_module = { ev_invalid, 0, ty_struct}; -type_t type_moduleptr = { ev_pointer, 0, ty_none, {{&type_obj_module}}}; -type_t type_obj_exec_class = { ev_func, 0, ty_none, +type_t type_obj_method = { ev_invalid, 0, 0, ty_struct }; +type_t type_obj_method_description = { ev_invalid, 0, 0, ty_struct }; +type_t type_obj_category = { ev_invalid, 0, 0, ty_struct}; +type_t type_obj_ivar = { ev_invalid, 0, 0, ty_struct}; +type_t type_obj_module = { ev_invalid, 0, 0, ty_struct}; +type_t type_moduleptr = { ev_pointer, 0, 1, ty_none, + {{&type_obj_module}}}; +type_t type_obj_exec_class = { ev_func, 0, 1, ty_none, {{&type_void, 1, { &type_moduleptr }}}}; -type_t type_obj_object = {ev_invalid, 0, ty_struct}; -type_t type_id = { ev_pointer, "id", ty_none, {{&type_obj_object}}}; -type_t type_obj_class = { ev_invalid, 0, ty_struct}; -type_t type_Class = { ev_pointer, 0, ty_none, {{&type_obj_class}}}; -type_t type_obj_protocol = { ev_invalid, 0, ty_struct}; +type_t type_obj_object = {ev_invalid, 0, 0, ty_struct}; +type_t type_id = { ev_pointer, "id", 1, ty_none, {{&type_obj_object}}}; +type_t type_obj_class = { ev_invalid, 0, 0, ty_struct}; +type_t type_Class = { ev_pointer, 0, 1, ty_none, {{&type_obj_class}}}; +type_t type_obj_protocol = { ev_invalid, 0, 0, ty_struct}; int obj_initialized = 0; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 5848c20c5..2b946a72c 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -148,11 +148,17 @@ new_def (const char *name, type_t *type, defspace_t *space, if (storage != sc_extern) { int size = type_size (type); + int alignment = type->alignment; + if (!size) { error (0, "%s has incomplete type", name); size = 1; } - def->offset = defspace_alloc_loc (space, size); + if (alignment < 1) { + print_type (type); + internal_error (0, "temp type has no alignment"); + } + def->offset = defspace_alloc_aligned_loc (space, size, alignment); } return def; @@ -199,16 +205,20 @@ temp_def (type_t *type) def_t *temp; defspace_t *space = current_func->symtab->space; int size = type_size (type); + int alignment = type->alignment; if (size < 1 || size > 4) { internal_error (0, "%d invalid size for temp def", size); } + if (alignment < 1) { + internal_error (0, "temp type has no alignment"); + } if ((temp = current_func->temp_defs[size - 1])) { current_func->temp_defs[size - 1] = temp->temp_next; temp->temp_next = 0; } else { ALLOC (16384, def_t, defs, temp); - temp->offset = defspace_alloc_loc (space, size); + temp->offset = defspace_alloc_aligned_loc (space, size, alignment); *space->def_tail = temp; space->def_tail = &temp->next; temp->name = save_string (va (".tmp%d", current_func->temp_num++)); diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index f227209d3..f2c9f7011 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -63,6 +63,33 @@ typedef struct locref_s { static defspace_t *spaces_freelist; static locref_t *locrefs_freelist; +static locref_t * +new_locref (int ofs, int size, locref_t *next) +{ + locref_t *loc; + + ALLOC (1024, locref_t, locrefs, loc); + loc->ofs = ofs; + loc->size = size; + loc->next = next; + return loc; +} + +static void +del_locref (locref_t *loc) +{ + FREE (locrefs, loc); +} + +static defspace_t * +new_defspace (void) +{ + defspace_t *space; + + ALLOC (1024, defspace_t, spaces, space); + return space; +} + #define GROW 1024 static int @@ -98,9 +125,8 @@ grow_space_virtual (defspace_t *space) defspace_t * defspace_new (ds_type_t type) { - defspace_t *space; + defspace_t *space = new_defspace (); - ALLOC (1024, defspace_t, spaces, space); space->def_tail = &space->defs; space->type = type; if (type == ds_backed) { @@ -116,33 +142,59 @@ defspace_new (ds_type_t type) int defspace_alloc_loc (defspace_t *space, int size) { - int ofs; + return defspace_alloc_aligned_loc (space, size, 1); +} + +int +defspace_alloc_aligned_loc (defspace_t *space, int size, int alignment) +{ + int ofs, pad; locref_t *loc; locref_t **l = &space->free_locs; if (size <= 0) internal_error (0, "invalid number of words requested: %d", size); - while (*l && (*l)->size < size) - l = &(*l)->next; - if ((loc = *l)) { - ofs = (*l)->ofs; - if ((*l)->size == size) { - loc = *l; - *l = (*l)->next; - FREE (locrefs, loc); - } else { - (*l)->ofs += size; - (*l)->size -= size; + if (alignment <= 0) + internal_error (0, "invalid alignment requested: %d", alignment); + while ((loc = *l)) { + ofs = loc->ofs; + pad = alignment * ((ofs + alignment - 1) / alignment) - ofs; + // exact fit, so just shrink the block or remove it if there is no + // padding (any padding remains free) + if (size + pad == loc->size) { + if (!pad) { + *l = loc->next; + del_locref (loc); + } + return ofs + pad; } - return ofs; + // there's excess space in the block. If there's no padding, then + // just shrink it, otherwise split it into two, one on either side + // of the allocated block, such that the padding remains free + if (size + pad < loc->size) { + if (!pad) { + loc->ofs += size; + loc->size -= size; + } else { + loc->next = new_locref (ofs + pad + size, + loc->size - ofs - pad, loc->next); + loc->size = pad; + } + return ofs + pad; + } + l = &(*l)->next; } ofs = space->size; - space->size += size; + pad = alignment * ((ofs + alignment - 1) / alignment) - ofs; + space->size += size + pad; if (space->size > space->max_size) { if (!space->grow || !space->grow (space)) internal_error (0, "unable to allocate %d words", size); } - return ofs; + if (pad) { + *l = new_locref (ofs, pad, 0); + } + return ofs + pad; } void @@ -184,17 +236,13 @@ defspace_free_loc (defspace_t *space, int ofs, int size) loc->size += loc->next->size; loc = loc->next; *l = loc->next; - FREE (locrefs, loc); + del_locref (loc); } return; } } // insert a new free block for the location to be freed - ALLOC (1024, locref_t, locrefs, loc); - loc->ofs = ofs; - loc->size = size; - loc->next = *l; - *l = loc; + *l = new_locref (ofs, size, *l); } int diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index bd37d6d05..b150e4baf 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -158,6 +158,7 @@ parse_params (type_t *type, param_t *parms) new = new_type (); new->type = ev_func; + new->alignment = 1; new->t.func.type = type; new->t.func.num_params = 0; diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index d3f014111..358b337f0 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -112,6 +112,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) { symbol_t *sym = find_struct (su, tag, type); symbol_t *s; + int alignment = 1; symtab->parent = 0; // disconnect struct's symtab from parent scope @@ -130,10 +131,14 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) if (size > symtab->size) symtab->size = size; } + if (s->type->alignment > alignment) { + alignment = s->type->alignment; + } } if (!type) sym->type = find_type (sym->type); // checks the tag, not the symtab sym->type->t.symtab = symtab; + sym->type->alignment = alignment; if (!type && sym->type->type_def->external) //FIXME should not be necessary sym->type->type_def = qfo_encode_type (sym->type); return sym; @@ -166,6 +171,7 @@ finish_enum (symbol_t *sym) enum_type = sym->type = find_type (sym->type); enum_tab = enum_type->t.symtab; + enum_type->alignment = 1; for (name = enum_tab->symbols; name; name = name->next) { name->type = sym->type; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 81bd21ef9..d326a5f33 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -63,20 +63,20 @@ // simple types. function types are dynamically allocated type_t type_invalid = { ev_invalid, "invalid" }; type_t type_void = { ev_void, "void" }; -type_t type_string = { ev_string, "string" }; -type_t type_float = { ev_float, "float" }; -type_t type_vector = { ev_vector, "vector" }; -type_t type_entity = { ev_entity, "entity" }; -type_t type_field = {ev_field, "field", ty_none, {{&type_void}} }; +type_t type_string = { ev_string, "string", 1 }; +type_t type_float = { ev_float, "float", 1 }; +type_t type_vector = { ev_vector, "vector", 1 }; +type_t type_entity = { ev_entity, "entity", 1 }; +type_t type_field = {ev_field, "field", 1, ty_none, {{&type_void}} }; // type_function is a void() function used for state defs -type_t type_function = { ev_func, "function", ty_none, {{&type_void}} }; -type_t type_pointer = { ev_pointer, "pointer", ty_none, {{&type_void}} }; -type_t type_quaternion = { ev_quat, "quaternion" }; -type_t type_integer = { ev_integer, "int" }; -type_t type_uinteger = { ev_uinteger, "uint" }; -type_t type_short = { ev_short, "short" }; -type_t type_double = { ev_double, "double" }; +type_t type_function = { ev_func, "function", 1, ty_none, {{&type_void}} }; +type_t type_pointer = { ev_pointer, "pointer", 1, ty_none, {{&type_void}} }; +type_t type_quaternion = { ev_quat, "quaternion", 1 }; +type_t type_integer = { ev_integer, "int", 1 }; +type_t type_uinteger = { ev_uinteger, "uint", 1 }; +type_t type_short = { ev_short, "short", 1 }; +type_t type_double = { ev_double, "double", 2 }; type_t *type_nil; type_t *type_default; @@ -85,9 +85,11 @@ type_t *type_default; type_t type_va_list = { ev_invalid, 0, ty_struct }; type_t type_param = { ev_invalid, 0, ty_struct }; type_t type_zero = { ev_invalid, 0, ty_struct }; -type_t type_type_encodings = { ev_invalid, "@type_encodings", ty_struct }; +type_t type_type_encodings = { ev_invalid, "@type_encodings", 0, + ty_struct }; -type_t type_floatfield = { ev_field, ".float", ty_none, {{&type_float}} }; +type_t type_floatfield = { ev_field, ".float", 1, ty_none, + {{&type_float}} }; type_t *ev_types[ev_type_count] = { &type_void, @@ -222,15 +224,19 @@ append_type (type_t *type, type_t *new) case ev_field: case ev_pointer: t = &(*t)->t.fldptr.type; + type->alignment = 1; break; case ev_func: t = &(*t)->t.func.type; + type->alignment = 1; break; case ev_invalid: - if ((*t)->meta == ty_array) + if ((*t)->meta == ty_array) { t = &(*t)->t.array.type; - else + type->alignment = new->alignment; + } else { internal_error (0, "append to object type"); + } break; } } @@ -364,6 +370,7 @@ field_type (type_t *aux) else new = new_type (); new->type = ev_field; + new->alignment = 1; new->t.fldptr.type = aux; if (aux) new = find_type (new); @@ -381,6 +388,7 @@ pointer_type (type_t *aux) else new = new_type (); new->type = ev_pointer; + new->alignment = 1; new->t.fldptr.type = aux; if (aux) new = find_type (new); @@ -398,6 +406,9 @@ array_type (type_t *aux, int size) else new = new_type (); new->type = ev_invalid; + if (aux) { + new->alignment = aux->alignment; + } new->meta = ty_array; new->t.array.type = aux; new->t.array.size = size; @@ -417,6 +428,9 @@ based_array_type (type_t *aux, int base, int top) else new = new_type (); new->type = ev_invalid; + if (aux) { + new->alignment = aux->alignment; + } new->meta = ty_array; new->t.array.type = aux; new->t.array.base = base; From 4caa875442b929f78dfee1d8e02d09ab5b289f64 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 10:10:01 +0900 Subject: [PATCH 0277/3664] Finish up alignment tests and add address cast It turns out that initializing a local int with a pointer cast doesn't work. --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/address-cast.r | 17 +++++++++++++++++ tools/qfcc/test/alignment.r | 29 ++++++++++++++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tools/qfcc/test/address-cast.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index cdc9d8c01..c13bfd9d0 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -29,6 +29,7 @@ test_bins=\ fail_bins= test_progs_dat=\ + address-cast.dat \ alignment.dat \ chewed-alias.dat \ chewed-return.dat \ @@ -89,6 +90,15 @@ test_harness_DEPENDENCIES= $(QFCC_TEST_DEPS) r_depfiles_remade= +address_cast_dat_SOURCES=address-cast.r +address_cast_obj=$(address_cast_dat_SOURCES:.r=.qfo) +address-cast.dat$(EXEEXT): $(address_cast_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(address_cast_obj) +address-cast.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/address-cast.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/address-cast.Qo + alignment_dat_SOURCES=alignment.r alignment_obj=$(alignment_dat_SOURCES:.r=.qfo) alignment.dat$(EXEEXT): $(alignment_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/address-cast.r b/tools/qfcc/test/address-cast.r new file mode 100644 index 000000000..b9f11640d --- /dev/null +++ b/tools/qfcc/test/address-cast.r @@ -0,0 +1,17 @@ +int a; +double b; +int c; +double d; +void printf (string fmt, ...) = #0; + +int main() +{ + int di = (int) &d; + int fail = 0; + + if (!di) { + printf ("address cast fail: %d\n", di); + fail |= 1; + } + return fail; +} diff --git a/tools/qfcc/test/alignment.r b/tools/qfcc/test/alignment.r index 819f45d30..9b867b2d6 100644 --- a/tools/qfcc/test/alignment.r +++ b/tools/qfcc/test/alignment.r @@ -2,8 +2,35 @@ int a; double b; int c; double d; +void printf (string fmt, ...) = #0; int main() { - return 1; + int fail = 0; + void *ap = &a; + void *bp = &b; + void *cp = &c; + void *dp = &d; + int aa = (int) ap; + int ba = (int) bp; + int ca = (int) cp; + int da = (int) dp; + + if (ba & 1) { + printf ("double b is not aligned: %d\n", ba); + fail |= 1; + } + if (da & 1) { + printf ("double d is not aligned: %d\n", da); + fail |= 1; + } + if (ca - aa != 1) { + printf ("int c (%d) is not adjacant to int a (%d)\n", ca, aa); + fail |= 1; + } + if (ba <= ca) { + printf ("double b does not come after int c: %d %d\n", ba, ca); + fail |= 1; + } + return fail; } From 3257e7145b26287f1e19b41ec370984f8aa3ebc7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 10:12:33 +0900 Subject: [PATCH 0278/3664] Add failing global init test too --- tools/qfcc/test/address-cast.r | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/test/address-cast.r b/tools/qfcc/test/address-cast.r index b9f11640d..ed853f9e5 100644 --- a/tools/qfcc/test/address-cast.r +++ b/tools/qfcc/test/address-cast.r @@ -1,6 +1,6 @@ int a; double b; -int c; +int c = (int) &b; double d; void printf (string fmt, ...) = #0; @@ -9,8 +9,12 @@ int main() int di = (int) &d; int fail = 0; + if (!c) { + printf ("global init address cast fail: %d\n", c); + fail |= 1; + } if (!di) { - printf ("address cast fail: %d\n", di); + printf ("local init address cast fail: %d\n", di); fail |= 1; } return fail; From ce9902baed172b69b3cdcb4dd83afeba9c8240c5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 15:32:01 +0900 Subject: [PATCH 0279/3664] Don't short-circuit aliased values Not sure why I thought it was a good idea as it turns out this is why cast pointer initializers were being lost. --- tools/qfcc/source/expr.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 013d55d81..842da5ad8 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1050,8 +1050,6 @@ new_alias_expr (type_t *type, expr_t *expr) { expr_t *alias; - if (expr->type == ex_value) - return new_value_expr (alias_value (expr->e.value, type)); alias = new_unary_expr ('A', expr); alias->e.expr.type = type; //if (expr->type == ex_uexpr && expr->e.expr.op == 'A') From e4eb793fb31dbb19b13db1849b1d95f143d4c044 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 15:37:16 +0900 Subject: [PATCH 0280/3664] Treat aliased values as constant One step closer to cast address initializers working. --- tools/qfcc/source/def.c | 14 +++++++++++++- tools/qfcc/source/expr.c | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 2b946a72c..f7735d8c3 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -585,8 +585,20 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, // fold_constants takes care of int/float conversions append_expr (local_expr, fold_constants (init)); } else { + int offset = 0; + if (!is_constant (init)) { + error (init, "non-constant initializier"); + return; + } + while ((init->type == ex_uexpr || init->type == ex_expr) + && init->e.expr.op == 'A') { + if (init->type == ex_expr) { + offset += expr_integer (init->e.expr.e2); + } + init = init->e.expr.e1; + } if (init->type != ex_value) { //FIXME enum etc - error (0, "non-constant initializier"); + internal_error (0, "initializier not a value"); return; } if (init->e.value->lltype == ev_pointer diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 842da5ad8..7d7e55a21 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -777,6 +777,10 @@ new_short_expr (short short_val) int is_constant (expr_t *e) { + while ((e->type == ex_uexpr || e->type == ex_expr) + && e->e.expr.op == 'A') { + e = e->e.expr.e1; + } if (e->type == ex_nil || e->type == ex_value || e->type == ex_labelref || (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) || (e->type == ex_symbol && e->e.symbol->sy_type == sy_var From 3e651b43f8411c40967f7e5be8f5581a81a490b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 15:38:15 +0900 Subject: [PATCH 0281/3664] Handle aliased values when emitting statements With this, cast address initializers work. I have to wonder if the alias value short-circuit was legacy from long before the rewrite, as it was quite trivial to handle in the back-end. --- tools/qfcc/source/statements.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 072d175cf..6ec05d593 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -906,6 +906,8 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) while (def->alias) def = def->alias; *op = def_operand (alias_def (def, type, offset), 0); + } else if (aop->op_type == op_value) { + *op = value_operand (aop->o.value); } else { internal_error (e, "invalid alias target: %s: %s", optype_str (aop->op_type), operand_string (aop)); From be30a0eb19a526f07ebab48856289d5bc0952c74 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 16:08:21 +0900 Subject: [PATCH 0282/3664] Fix missing alignment init on zero and param types --- tools/qfcc/source/type.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index d326a5f33..981d2fbed 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -82,9 +82,9 @@ type_t *type_nil; type_t *type_default; // these will be built up further -type_t type_va_list = { ev_invalid, 0, ty_struct }; -type_t type_param = { ev_invalid, 0, ty_struct }; -type_t type_zero = { ev_invalid, 0, ty_struct }; +type_t type_va_list = { ev_invalid, 0, 0, ty_struct }; +type_t type_param = { ev_invalid, 0, 0, ty_struct }; +type_t type_zero = { ev_invalid, 0, 0, ty_struct }; type_t type_type_encodings = { ev_invalid, "@type_encodings", 0, ty_struct }; From 4bf37b274bb3c04c6bb3cba85066a408bcdd2685 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 16:08:55 +0900 Subject: [PATCH 0283/3664] Ensure double is not in zero or param structs for v6 --- tools/qfcc/source/type.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 981d2fbed..289b76563 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -913,7 +913,6 @@ init_types (void) }; static struct_def_t param_struct[] = { {"string_val", &type_string}, - {"double_val", &type_double}, {"float_val", &type_float}, {"vector_val", &type_vector}, {"entity_val", &type_entity}, @@ -925,6 +924,7 @@ init_types (void) {"integer_val", &type_integer}, {"uinteger_val", &type_uinteger}, {"quaternion_val", &type_quaternion}, + {"double_val", &type_double}, {0, 0} }; static struct_def_t vector_struct[] = { From 08ca59d0df5f206665660bd7b159bb4ee7fd5507 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 17:00:14 +0900 Subject: [PATCH 0284/3664] Add tests for double demotion --- tools/qfcc/test/Makefile.am | 8 ++++++++ tools/qfcc/test/double-demote-float.r | 7 +++++++ tools/qfcc/test/double-demote-int.r | 7 +++++++ 3 files changed, 22 insertions(+) create mode 100644 tools/qfcc/test/double-demote-float.r create mode 100644 tools/qfcc/test/double-demote-int.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index c13bfd9d0..32e5cd5ec 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -61,6 +61,8 @@ test_progs_dat=\ fail_progs_dat= test_build_errors=\ + double-demote-int.r \ + double-demote-float.r \ double-int-compare.r \ double-float-compare.r @@ -153,6 +155,12 @@ double.run: Makefile build-run include ./$(DEPDIR)/double.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/double.Qo +double-demote-int.run$(EXEEXT): double-demote-int.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +double-demote-float.run$(EXEEXT): double-demote-float.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + double-int-compare.run$(EXEEXT): double-int-compare.r Makefile build-compile-fail-run $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/double-demote-float.r b/tools/qfcc/test/double-demote-float.r new file mode 100644 index 000000000..330a0bdef --- /dev/null +++ b/tools/qfcc/test/double-demote-float.r @@ -0,0 +1,7 @@ +double a; +float b; +int main () +{ + b = a; + return 1; // test fails if compile succeeds +} diff --git a/tools/qfcc/test/double-demote-int.r b/tools/qfcc/test/double-demote-int.r new file mode 100644 index 000000000..bebef5436 --- /dev/null +++ b/tools/qfcc/test/double-demote-int.r @@ -0,0 +1,7 @@ +double a; +int b; +int main () +{ + b = a; + return 1; // test fails if compile succeeds +} From c5ce18591f9cf3fd9b6658a8844fa1039f425e2f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 17:24:53 +0900 Subject: [PATCH 0285/3664] Catch and warn demotion of double in assignments --- tools/qfcc/source/expr_assign.c | 4 ++++ tools/qfcc/test/Makefile.am | 10 +++++++++- tools/qfcc/test/double-demote-float-linit.r | 6 ++++++ tools/qfcc/test/double-demote-int-linit.r | 6 ++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tools/qfcc/test/double-demote-float-linit.r create mode 100644 tools/qfcc/test/double-demote-int-linit.r diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 1797f7677..600c6140a 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -151,6 +151,10 @@ check_types_compatible (expr_t *dst, expr_t *src) if (type_assignable (dst_type, src_type)) { if (is_scalar (dst_type) && is_scalar (src_type)) { + if (is_double (src_type)) { + warning (dst, "assignment of double to %s (use a cast)\n", + dst_type->name); + } // the types are different but cast-compatible expr_t *new = cast_expr (dst_type, src); // the cast was a no-op, so the types are compatible at the diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 32e5cd5ec..1d3d9de9c 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -61,8 +61,10 @@ test_progs_dat=\ fail_progs_dat= test_build_errors=\ - double-demote-int.r \ double-demote-float.r \ + double-demote-float-linit.r \ + double-demote-int.r \ + double-demote-int-linit.r \ double-int-compare.r \ double-float-compare.r @@ -161,6 +163,12 @@ double-demote-int.run$(EXEEXT): double-demote-int.r Makefile build-compile-fail- double-demote-float.run$(EXEEXT): double-demote-float.r Makefile build-compile-fail-run $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< +double-demote-int-linit.run$(EXEEXT): double-demote-int-linit.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +double-demote-float-linit.run$(EXEEXT): double-demote-float-linit.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + double-int-compare.run$(EXEEXT): double-int-compare.r Makefile build-compile-fail-run $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/double-demote-float-linit.r b/tools/qfcc/test/double-demote-float-linit.r new file mode 100644 index 000000000..796b2040f --- /dev/null +++ b/tools/qfcc/test/double-demote-float-linit.r @@ -0,0 +1,6 @@ +double a; +int main () +{ + float b = a; + return 1; // test fails if compile succeeds +} diff --git a/tools/qfcc/test/double-demote-int-linit.r b/tools/qfcc/test/double-demote-int-linit.r new file mode 100644 index 000000000..3a206f4b5 --- /dev/null +++ b/tools/qfcc/test/double-demote-int-linit.r @@ -0,0 +1,6 @@ +double a; +int main () +{ + int b = a; + return 1; // test fails if compile succeeds +} From 6ce99afa5bd7260937a0b74d3cb07fcdc87a8488 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 17:42:46 +0900 Subject: [PATCH 0286/3664] Catch double demotion in global initializers Local initializers are handled by regular assignments --- tools/qfcc/source/def.c | 8 +++++++- tools/qfcc/test/Makefile.am | 8 ++++++++ tools/qfcc/test/double-demote-float-ginit.r | 6 ++++++ tools/qfcc/test/double-demote-int-ginit.r | 6 ++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tools/qfcc/test/double-demote-float-ginit.r create mode 100644 tools/qfcc/test/double-demote-int-ginit.r diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index f7735d8c3..6e545ba40 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -575,7 +575,8 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, init_elements (sym->s.def, init); sym->s.def->initialized = 1; } else { - if (!type_assignable (sym->type, get_type (init))) { + type_t *init_type = get_type (init); + if (!type_assignable (sym->type, init_type)) { error (init, "type mismatch in initializer"); return; } @@ -609,6 +610,11 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, reloc_def_field (init->e.value->v.pointer.def, sym->s.def); } else { ex_value_t *v = init->e.value; + if (is_double (init_type) + && (is_integral (sym->type) || is_float (sym->type))) { + warning (init, "assigning double to %s in initializer " + "(use a cast)", sym->type->name); + } if (is_scalar (sym->type)) v = convert_value (v, sym->type); if (v->lltype == ev_string) { diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 1d3d9de9c..748f779c1 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -62,8 +62,10 @@ fail_progs_dat= test_build_errors=\ double-demote-float.r \ + double-demote-float-ginit.r \ double-demote-float-linit.r \ double-demote-int.r \ + double-demote-int-ginit.r \ double-demote-int-linit.r \ double-int-compare.r \ double-float-compare.r @@ -163,6 +165,12 @@ double-demote-int.run$(EXEEXT): double-demote-int.r Makefile build-compile-fail- double-demote-float.run$(EXEEXT): double-demote-float.r Makefile build-compile-fail-run $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< +double-demote-int-ginit.run$(EXEEXT): double-demote-int-ginit.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +double-demote-float-ginit.run$(EXEEXT): double-demote-float-ginit.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + double-demote-int-linit.run$(EXEEXT): double-demote-int-linit.r Makefile build-compile-fail-run $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/double-demote-float-ginit.r b/tools/qfcc/test/double-demote-float-ginit.r new file mode 100644 index 000000000..c88b5e987 --- /dev/null +++ b/tools/qfcc/test/double-demote-float-ginit.r @@ -0,0 +1,6 @@ +double a; +float b = 1.0d; +int main () +{ + return 1; // test fails if compile succeeds +} diff --git a/tools/qfcc/test/double-demote-int-ginit.r b/tools/qfcc/test/double-demote-int-ginit.r new file mode 100644 index 000000000..767328715 --- /dev/null +++ b/tools/qfcc/test/double-demote-int-ginit.r @@ -0,0 +1,6 @@ +double a; +int b = 1.0d; +int main () +{ + return 1; // test fails if compile succeeds +} From 344d42913430dc8d45bf4732bfc645ff80fa4281 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 17:49:26 +0900 Subject: [PATCH 0287/3664] Test array initializer double demotions Turns out array inits are very strict about types (bug?). --- tools/qfcc/test/Makefile.am | 8 ++++++++ tools/qfcc/test/double-demote-float-ainit.r | 6 ++++++ tools/qfcc/test/double-demote-int-ainit.r | 6 ++++++ 3 files changed, 20 insertions(+) create mode 100644 tools/qfcc/test/double-demote-float-ainit.r create mode 100644 tools/qfcc/test/double-demote-int-ainit.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 748f779c1..7c51613e8 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -62,9 +62,11 @@ fail_progs_dat= test_build_errors=\ double-demote-float.r \ + double-demote-float-ainit.r \ double-demote-float-ginit.r \ double-demote-float-linit.r \ double-demote-int.r \ + double-demote-int-ainit.r \ double-demote-int-ginit.r \ double-demote-int-linit.r \ double-int-compare.r \ @@ -165,6 +167,12 @@ double-demote-int.run$(EXEEXT): double-demote-int.r Makefile build-compile-fail- double-demote-float.run$(EXEEXT): double-demote-float.r Makefile build-compile-fail-run $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< +double-demote-int-ainit.run$(EXEEXT): double-demote-int-ainit.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +double-demote-float-ainit.run$(EXEEXT): double-demote-float-ainit.r Makefile build-compile-fail-run + $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + double-demote-int-ginit.run$(EXEEXT): double-demote-int-ginit.r Makefile build-compile-fail-run $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/double-demote-float-ainit.r b/tools/qfcc/test/double-demote-float-ainit.r new file mode 100644 index 000000000..6d380447d --- /dev/null +++ b/tools/qfcc/test/double-demote-float-ainit.r @@ -0,0 +1,6 @@ +double a; +int b[] = {1.0d}; +int main () +{ + return 1; // test fails if compile succeeds +} diff --git a/tools/qfcc/test/double-demote-int-ainit.r b/tools/qfcc/test/double-demote-int-ainit.r new file mode 100644 index 000000000..6d380447d --- /dev/null +++ b/tools/qfcc/test/double-demote-int-ainit.r @@ -0,0 +1,6 @@ +double a; +int b[] = {1.0d}; +int main () +{ + return 1; // test fails if compile succeeds +} From 39df9c0c87785d3fbc5589bd7bf403b7d012464c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 18:17:18 +0900 Subject: [PATCH 0288/3664] Fix some more double related warnings Fewer than I expected --- ruamoko/cl_menu/HUD.r | 4 ++-- ruamoko/game/Axe.r | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ruamoko/cl_menu/HUD.r b/ruamoko/cl_menu/HUD.r index 48bfc916f..b0ff525b2 100644 --- a/ruamoko/cl_menu/HUD.r +++ b/ruamoko/cl_menu/HUD.r @@ -166,7 +166,7 @@ int HUDHandleClass; if (looping) currentFrame = 0; else { - nextFrameTime = 0.0; + nextFrameTime = 0.0f; currentFrame = 0; return; } @@ -201,7 +201,7 @@ int HUDHandleClass; - (void) stop { - nextFrameTime = 0.0; + nextFrameTime = 0.0f; currentFrame = 0; } diff --git a/ruamoko/game/Axe.r b/ruamoko/game/Axe.r index 2ea71f0ef..7e3c49745 100644 --- a/ruamoko/game/Axe.r +++ b/ruamoko/game/Axe.r @@ -14,7 +14,7 @@ - (id) init { [super init]; - damage = (deathmatch > 3) ? 75.0 : 20.0; + damage = (deathmatch > 3) ? 75.0f : 20.0f; return self; } From 91f5023681c8e7baddffffea796483f12ea01492 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 18:44:53 +0900 Subject: [PATCH 0289/3664] Promote bugs to internal errors Mostly so I can catch them in test cases --- tools/qfcc/include/options.h | 6 ++++++ tools/qfcc/source/diagnostic.c | 36 ++++++++++++++++++++++------------ tools/qfcc/source/options.c | 35 +++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index b66d9b19a..cfcd350de 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -70,6 +70,11 @@ typedef struct { qboolean silent; // don't even bother (overrides promote) } notice_options_t; +typedef struct { + qboolean promote; // Promote bugs to internal errors + qboolean silent; // don't even bother (overrides promote) +} bug_options_t; + typedef struct { qboolean initial; qboolean thread; @@ -88,6 +93,7 @@ typedef struct { code_options_t code; // Code generation options warn_options_t warnings; // Warning options notice_options_t notices; // Notice options + bug_options_t bug; // Bug options blockdot_options_t block_dot; // Statement block flow diagrams int verbosity; // 0=silent, goes up to 2 currently diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 85e2b6d27..d38c1eecb 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -141,17 +141,39 @@ _debug (expr_t *e, const char *file, int line, const char *fmt, ...) va_end (args); } +static __attribute__((noreturn, format(printf, 4, 0))) void +__internal_error (expr_t *e, const char *file, int line, + const char *fmt, va_list args) +{ + dstring_t *message = dstring_new (); + + report_function (e); + + format_message (message, "internal error", e, fmt, args); + dasprintf (message, " (%s:%d)", file, line); + fprintf (stderr, "%s\n", message->str); + dstring_delete (message); + abort (); +} + void _bug (expr_t *e, const char *file, int line, const char *fmt, ...) { va_list args; - report_function (e); + if (options.bug.silent) + return; va_start (args, fmt); + if (options.bug.promote) { + __internal_error (e, file, line, fmt, args); + } + { dstring_t *message = dstring_new (); + report_function (e); + format_message (message, "BUG", e, fmt, args); dasprintf (message, " (%s:%d)", file, line); if (bug_hook) { @@ -211,19 +233,9 @@ _internal_error (expr_t *e, const char *file, int line, const char *fmt, ...) { va_list args; - report_function (e); - va_start (args, fmt); - { - dstring_t *message = dstring_new (); - - format_message (message, "internal error", e, fmt, args); - dasprintf (message, " (%s:%d)", file, line); - fprintf (stderr, "%s\n", message->str); - dstring_delete (message); - } + __internal_error (e, file, line, fmt, args); va_end (args); - abort (); } expr_t * diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index a0e7f83a9..cfd1e27bf 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -69,11 +69,13 @@ enum { OPT_PROGDEFS, OPT_QCCX_ESCAPES, OPT_TRADITIONAL, + OPT_BUG, }; static struct option const long_options[] = { {"advanced", no_argument, 0, OPT_ADVANCED}, {"block-dot", optional_argument, 0, OPT_BLOCK_DOT}, + {"bug", required_argument, 0, OPT_BUG}, {"code", required_argument, 0, 'C'}, {"cpp", required_argument, 0, OPT_CPP}, {"define", required_argument, 0, 'D'}, @@ -139,6 +141,7 @@ usage (int status) "Options:\n" " --advanced Advanced Ruamoko mode\n" " default for separate compilation mode\n" +" --bug OPTION,... Set bug options\n" " -C, --code OPTION,... Set code generation options\n" " -c Only compile, don't link\n" " --cpp CPPSPEC cpp execution command line\n" @@ -264,6 +267,21 @@ notice_usage (void) exit (0); } +static void +bug_usage (void) +{ + printf ("%s - QuakeForge Code Compiler\n", this_program); + printf ("Bug options\n"); + printf ( +" help Display his text.\n" +" none Turn off all bugs (don't we wish: messages).\n" +" die Change bugs to internal errors.\n" +"\n" +"This is a developer feature and thus not in the manual page\n" + ); + exit (0); +} + static void add_file (const char *file) { @@ -590,6 +608,23 @@ DecodeArgs (int argc, char **argv) free (opts); } break; + case OPT_BUG:{ + char *opts = strdup (optarg); + char *temp = strtok (opts, ","); + + while (temp) { + if (!strcasecmp (temp, "help")) { + bug_usage (); + } else if (!(strcasecmp (temp, "none"))) { + options.bug.silent = true; + } else if (!(strcasecmp (temp, "die"))) { + options.bug.promote = true; + } + temp = strtok (NULL, ","); + } + free (opts); + } + break; case OPT_CPP: // --cpp= cpp_name = save_string (optarg); break; From 7bfa0f7a9250c3e68aa1abfb374f8faf8fd10157 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 19:41:20 +0900 Subject: [PATCH 0290/3664] Allow pragmas to have arguments It does mean only one pragma per line, but that's not such a big deal. --- tools/qfcc/include/pragma.h | 3 +- tools/qfcc/source/pragma.c | 69 +++++++++++++++++++++++++++++++------ tools/qfcc/source/qc-lex.l | 5 ++- 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/include/pragma.h b/tools/qfcc/include/pragma.h index 5f660ac23..2fad5a357 100644 --- a/tools/qfcc/include/pragma.h +++ b/tools/qfcc/include/pragma.h @@ -35,7 +35,8 @@ */ ///@{ -void pragma (const char *id); +void pragma_process (void); +void pragma_add_arg (const char *id); ///@} diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index c5e8e816d..e1a465b53 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -39,14 +39,25 @@ #endif #include +#include "QF/alloc.h" #include "QF/pr_comp.h" #include "diagnostic.h" #include "opcodes.h" #include "options.h" #include "pragma.h" +#include "strpool.h" #include "type.h" +typedef struct pragma_arg_s { + struct pragma_arg_s *next; + const char *arg; +} pragma_arg_t; + +static pragma_arg_t *pragma_args_freelist; +static pragma_arg_t *pragma_args; +static pragma_arg_t **pragma_args_tail = &pragma_args; + static void set_traditional (int traditional) { @@ -73,20 +84,58 @@ set_traditional (int traditional) opcode_init (); // reset the opcode table } -void -pragma (const char *id) +static void +set_bug (pragma_arg_t *args) { + if (!args) { + warning (0, "missing bug flag"); + return; + } + const char *flag = args->arg; + if (!strcmp (flag, "none")) { + options.bug.silent = true; + } else if (!strcmp (flag, "!none")) { + options.bug.silent = false; + } else if (!strcmp (flag, "die")) { + options.bug.promote = true; + } else if (!strcmp (flag, "!die")) { + options.bug.promote = false; + } + if (args->next) { + warning (0, "pragma bug: ignoring extra arguments"); + } +} + +void +pragma_process () +{ + if (!pragma_args) { + warning (0, "empty pragma"); + return; + } + const char *id = pragma_args->arg; if (!strcmp (id, "traditional")) { set_traditional (2); - return; - } - if (!strcmp (id, "extended")) { + } else if (!strcmp (id, "extended")) { set_traditional (1); - return; - } - if (!strcmp (id, "advanced")) { + } else if (!strcmp (id, "advanced")) { set_traditional (0); - return; + } else if (!strcmp (id, "bug")) { + set_bug (pragma_args->next); + } else { + warning (0, "unknown pragma: '%s'", id); } - warning (0, "unknown pragma: %s", id); + *pragma_args_tail = pragma_args_freelist; + pragma_args_tail = &pragma_args; + pragma_args = 0; +} + +void +pragma_add_arg (const char *id) +{ + pragma_arg_t *arg; + ALLOC (16, pragma_arg_t, pragma_args, arg); + arg->arg = save_string (id); + *pragma_args_tail = arg; + pragma_args_tail = &arg->next; } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index d17cad55e..5b97a0938 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -272,9 +272,12 @@ STRING \"(\\.|[^"\\])*\" write_frame_macros (s); BEGIN (GRAB_OTHER); // ignore rest of line } -{ID} { pragma (yytext); } +{ID} { pragma_add_arg (yytext); } <*>\r*\n { + if (YY_START == PRAGMA) { + pragma_process (); + } pr.source_line++; BEGIN (INITIAL); } From 9c996df7b4689228b6177521dcea4180deb2b925 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 19:42:32 +0900 Subject: [PATCH 0291/3664] Add a test case for the uninit temp in HUD.r --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/ivar-struct-return.r | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tools/qfcc/test/ivar-struct-return.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 7c51613e8..d9d66090a 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -41,6 +41,7 @@ test_progs_dat=\ func-expr.dat \ func-static.dat \ infloop.dat \ + ivar-struct-return.dat \ modulo.dat \ paramret.dat \ quaternion.dat \ @@ -236,6 +237,15 @@ infloop.run: Makefile build-run include ./$(DEPDIR)/infloop.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/infloop.Qo +ivar_struct_return_dat_SOURCES=ivar-struct-return.r +ivar_struct_return_obj=$(ivar_struct_return_dat_SOURCES:.r=.qfo) +ivar-struct-return.dat$(EXEEXT): $(ivar_struct_return_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(ivar_struct_return_obj) +ivar-struct-return.run: Makefile build-run + $(srcdir)/build-run $@ +include ./$(DEPDIR)/ivar-struct-return.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/ivar-struct-return.Qo + modulo_dat_SOURCES=modulo.r modulo_obj=$(modulo_dat_SOURCES:.r=.qfo) modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/ivar-struct-return.r b/tools/qfcc/test/ivar-struct-return.r new file mode 100644 index 000000000..a96cafac7 --- /dev/null +++ b/tools/qfcc/test/ivar-struct-return.r @@ -0,0 +1,26 @@ +#pragma bug die + +struct Point { + int x; + int y; +}; +typedef struct Point Point; + +@interface Object +{ + Point origin; +} +-(Point) origin; +@end + +@implementation Object +-(Point) origin +{ + return origin; +} +@end +void __obj_exec_class (struct obj_module *msg) = #0; +int main() +{ + return 0; // to survive and prevail +} From 1985b6d4fd2a39c8717ceedaf1d6fe46ac7ebcde Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 22:10:46 +0900 Subject: [PATCH 0292/3664] Avoid creating a struct temp for ivar struct return This fixed the uninitialized temp warning in HUD.r. The problem was caused by the flow analyzer not being able to detect that the struct temp was being initialized by the move statement due to the address of the temp being in a pointer temp. While it would be good to use a constant pointer for the address of the struct temp or improving the flow analyzer to track actual data, avoiding the temp in the first place results in nicer code as it removes a move statement. --- tools/qfcc/include/statements.h | 1 + tools/qfcc/source/statements.c | 30 +++++++++++++++------------- tools/qfcc/test/ivar-struct-return.r | 1 + 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 14a95ae0a..ce230d9ec 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -116,6 +116,7 @@ struct dstring_s; const char *optype_str (op_type_e type) __attribute__((const)); operand_t *def_operand (struct def_s *def, struct type_s *type); +operand_t *return_operand (struct type_s *type); operand_t *value_operand (struct ex_value_s *value); int tempop_overlap (tempop_t *t1, tempop_t *t2) __attribute__((pure)); operand_t *temp_operand (struct type_s *type); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 6ec05d593..5dc5d878c 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -318,6 +318,15 @@ def_operand (def_t *def, type_t *type) return op; } +operand_t * +return_operand (type_t *type) +{ + symbol_t *return_symbol; + return_symbol = make_symbol (".return", &type_param, pr.symtab->space, + sc_extern); + return def_operand (return_symbol->s.def, type); +} + operand_t * value_operand (ex_value_t *value) { @@ -394,7 +403,7 @@ alias_operand (type_t *type, operand_t *op) operand_t *aop; if (type_size (type) != type_size (op->type)) { - internal_error (0, "\naliasing operand with type of diffent size" + internal_error (0, "\naliasing operand with type of different size" " (%d, %d)", type_size (type), type_size (op->type)); } aop = new_operand (op_alias); @@ -1387,8 +1396,10 @@ statement_uexpr (sblock_t *sblock, expr_t *e) } } s = new_statement (st_func, opcode, e); - if (e->e.expr.e1) + if (e->e.expr.e1) { + s->opa = return_operand (get_type (e->e.expr.e1)); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); + } sblock_add_statement (sblock, s); sblock->next = new_sblock (); sblock = sblock->next; @@ -1667,10 +1678,6 @@ static void check_final_block (sblock_t *sblock) { statement_t *s = 0; - symbol_t *return_symbol = 0; - def_t *return_def = 0; - operand_t *return_operand = 0; - const char *return_opcode = ""; if (!sblock) return; @@ -1691,16 +1698,11 @@ check_final_block (sblock_t *sblock) sblock->next = new_sblock (); sblock = sblock->next; } + s = new_statement (st_func, "", 0); if (options.traditional || options.code.progsversion == PROG_ID_VERSION) { - return_symbol = make_symbol (".return", &type_param, pr.symtab->space, - sc_extern); - return_def = return_symbol->s.def; - return_opcode = ""; + s->opcode = save_string (""); + s->opa = return_operand (&type_void); } - if (return_symbol) - return_operand = def_operand (return_def, &type_void); - s = new_statement (st_func, return_opcode, 0); - s->opa = return_operand; sblock_add_statement (sblock, s); } diff --git a/tools/qfcc/test/ivar-struct-return.r b/tools/qfcc/test/ivar-struct-return.r index a96cafac7..5e212a5ba 100644 --- a/tools/qfcc/test/ivar-struct-return.r +++ b/tools/qfcc/test/ivar-struct-return.r @@ -8,6 +8,7 @@ typedef struct Point Point; @interface Object { + int foo; Point origin; } -(Point) origin; From 14acfad7c4c73f8931fea35fe19e4170c1b9d00e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 22:53:21 +0900 Subject: [PATCH 0293/3664] Fix incorrect placement of far data All the care in aligning things was undone by not updating the calculations of the pointers. --- tools/qfcc/source/obj_file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index e0b6c668f..c809a4a8b 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -889,8 +889,8 @@ qfo_to_progs (qfo_t *qfo, int *size) progs->ofs_globals = data - (byte *) progs; globals = (pr_type_t*) data; - locals = globals + qfo->spaces[qfo_near_data_space].data_size; - far_data = locals + locals_size; + locals = globals + locals_start; + far_data = globals + near_data_size; type_data = far_data + qfo->spaces[qfo_far_data_space].data_size; memcpy (strings, qfo->spaces[qfo_strings_space].d.strings, @@ -947,7 +947,7 @@ qfo_to_progs (qfo_t *qfo, int *size) memcpy (globals, qfo->spaces[qfo_near_data_space].d.data, qfo->spaces[qfo_near_data_space].data_size * sizeof (pr_type_t)); qfo->spaces[qfo_near_data_space].d.data = globals; - // lcear locals data + // clear locals data memset (locals, 0, locals_size * sizeof (pr_type_t)); // copy far data memcpy (far_data, qfo->spaces[qfo_far_data_space].d.data, From bab3752e989c9e92f06affeebbcbaecac133c5d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 23:22:56 +0900 Subject: [PATCH 0294/3664] Add missed overridden math functions And fix misspelled ones too. --- libs/ruamoko/rua_math.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/libs/ruamoko/rua_math.c b/libs/ruamoko/rua_math.c index 167db865f..a81d33356 100644 --- a/libs/ruamoko/rua_math.c +++ b/libs/ruamoko/rua_math.c @@ -168,6 +168,24 @@ bi_atanhf (progs_t *pr) R_FLOAT (pr) = logf ((1 + y) / (1 - y)) / 2; } +static void +bi_floor (progs_t *pr) +{ + R_DOUBLE (pr) = floor (P_DOUBLE (pr, 0)); +} + +static void +bi_ceil (progs_t *pr) +{ + R_DOUBLE (pr) = ceil (P_DOUBLE (pr, 0)); +} + +static void +bi_fabs (progs_t *pr) +{ + R_DOUBLE (pr) = fabs (P_DOUBLE (pr, 0)); +} + static void bi_sin (progs_t *pr) { @@ -298,34 +316,37 @@ static builtin_t builtins[] = { {"asin|f", bi_asinf, -1}, {"acos|f", bi_acosf, -1}, {"atan|f", bi_atanf, -1}, - {"atan2|f", bi_atan2f, -1}, + {"atan2|ff",bi_atan2f, -1}, {"log|f", bi_logf, -1}, {"log2|f", bi_log2f, -1}, {"log10|f", bi_log10f, -1}, - {"pow|f", bi_powf, -1}, + {"pow|ff", bi_powf, -1}, {"sqrt|f", bi_sqrtf, -1}, {"cbrt|f", bi_cbrtf, -1}, - {"hypot|f", bi_hypotf, -1}, + {"hypot|ff",bi_hypotf, -1}, {"sinh|f", bi_sinhf, -1}, {"cosh|f", bi_coshf, -1}, {"tanh|f", bi_tanhf, -1}, {"asinh|f", bi_asinhf, -1}, {"acosh|f", bi_acoshf, -1}, {"atanh|f", bi_atanhf, -1}, + {"floor|d", bi_floor, -1}, // float version in pr_cmds + {"ceil|d", bi_ceil, -1}, // float version in pr_cmds + {"fabs|d", bi_fabs, -1}, // float version in pr_cmds {"sin|d", bi_sin, -1}, {"cos|d", bi_cos, -1}, {"tan|d", bi_tan, -1}, {"asin|d", bi_asin, -1}, {"acos|d", bi_acos, -1}, {"atan|d", bi_atan, -1}, - {"atan2|d", bi_atan2, -1}, + {"atan2|dd",bi_atan2, -1}, {"log|d", bi_log, -1}, {"log2|d", bi_log2, -1}, {"log10|d", bi_log10, -1}, - {"pow|d", bi_pow, -1}, + {"pow|dd", bi_pow, -1}, {"sqrt|d", bi_sqrt, -1}, {"cbrt|d", bi_cbrt, -1}, - {"hypot|d", bi_hypot, -1}, + {"hypot|dd",bi_hypot, -1}, {"sinh|d", bi_sinh, -1}, {"cosh|d", bi_cosh, -1}, {"tanh|d", bi_tanh, -1}, From db9996023fcdcc4d057e3c068434c92e62b3450b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Feb 2020 23:43:33 +0900 Subject: [PATCH 0295/3664] Add some tests for double comparison More testing the engine than the compiler, but hey :) --- tools/qfcc/test/double.r | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tools/qfcc/test/double.r b/tools/qfcc/test/double.r index 623d9f0ae..326ccf906 100644 --- a/tools/qfcc/test/double.r +++ b/tools/qfcc/test/double.r @@ -35,6 +35,46 @@ test_constant () return fail; } +double less = 3; +double greater_equal = 3; +double less_equal = 5; +double greater = 5; + +int +test_copare () +{ + int fail = 0; + + fail |= !(less < greater); + fail |= (less > greater); + fail |= !(less != greater); + fail |= (less == greater); + fail |= !(less <= greater); + fail |= (less >= greater); + + fail |= (less_equal < greater); + fail |= (less_equal > greater); + fail |= !(less_equal == greater); + fail |= (less_equal != greater); + fail |= !(less_equal <= greater); + fail |= !(less_equal >= greater); + + fail |= (greater < less); + fail |= !(greater > less); + fail |= !(greater != less); + fail |= (greater == less); + fail |= (greater <= less); + fail |= !(greater >= less); + + fail |= (greater_equal < less); + fail |= (greater_equal > less); + fail |= !(greater_equal == less); + fail |= (greater_equal != less); + fail |= !(greater_equal <= less); + fail |= !(greater_equal >= less); + return fail; +} + int test_ops () { From 4269c8cb07db4748b444e0f191901bef49cf33ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 11:04:30 +0900 Subject: [PATCH 0296/3664] Rename the mod instruction to rem Because % really implements remainder rather than true modulo, and I plan on adding %% to implement true modulo. --- include/QF/pr_comp.h | 6 +++--- libs/gamecode/pr_exec.c | 10 +++++----- libs/gamecode/pr_opcode.c | 6 +++--- tools/qfcc/test/modulo.r | 20 ++++++++++++++++++-- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 122de60b9..0fb09da41 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -181,8 +181,8 @@ typedef enum { OP_SHL_I, OP_SHR_I, - OP_MOD_F, - OP_MOD_I, + OP_REM_F, + OP_REM_I, OP_LOADB_F, OP_LOADB_V, @@ -371,7 +371,7 @@ typedef enum { OP_MUL_VD, OP_MUL_DV, OP_DIV_D, - OP_MOD_D, + OP_REM_D, OP_GE_D, OP_LE_D, OP_GT_D, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 3ea2c3bd5..8cb6ecbb8 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -318,8 +318,8 @@ signal_hook (int sig, void *data) else OPC.integer_var = 0x7fffffff; return 1; - case OP_MOD_I: - case OP_MOD_F: + case OP_REM_I: + case OP_REM_F: OPC.integer_var = 0x00000000; return 1; default: @@ -1429,17 +1429,17 @@ op_call: case OP_DIV_I: OPC.integer_var = OPA.integer_var / OPB.integer_var; break; - case OP_MOD_I: + case OP_REM_I: OPC.integer_var = OPA.integer_var % OPB.integer_var; break; - case OP_MOD_D: + case OP_REM_D: { double a = OPA_double_var; double b = OPB_double_var; OPC_double_var = a - b * trunc (a / b); } break; - case OP_MOD_F: + case OP_REM_F: { float a = OPA.float_var; float b = OPB.float_var; diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index f18fd2b42..01dd172ae 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -171,7 +171,7 @@ VISIBLE opcode_t pr_opcodes[] = { ev_double, ev_double, ev_double, PROG_VERSION, }, - {"%", "mod.d", OP_MOD_D, false, + {"%", "rem.d", OP_REM_D, false, ev_double, ev_double, ev_double, PROG_VERSION, }, @@ -1036,7 +1036,7 @@ VISIBLE opcode_t pr_opcodes[] = { ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"%", "mod.i", OP_MOD_I, false, + {"%", "rem.i", OP_REM_I, false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, @@ -1049,7 +1049,7 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_VERSION, }, - {"%", "mod.f", OP_MOD_F, false, + {"%", "rem.f", OP_REM_F, false, ev_float, ev_float, ev_float, PROG_VERSION, }, diff --git a/tools/qfcc/test/modulo.r b/tools/qfcc/test/modulo.r index 1e02fcaa0..81366c134 100644 --- a/tools/qfcc/test/modulo.r +++ b/tools/qfcc/test/modulo.r @@ -1,11 +1,19 @@ -#pragma traditional +void printf (string ftm, ...) = #0; -void (...) printf = #0; +float snafu (float a, float b) +{ + float c = a % b; + return c; +} + +#pragma traditional float foo (float a, float b) { float c = a % b; return c; } +#pragma advanced + float bar (float a, float b) { float c; @@ -15,11 +23,13 @@ float bar (float a, float b) return c; } +#pragma traditional float baz (float a, float b) { float c = (a + b) % (a - b); return c; } +#pragma advanced float test (string name, float (func)(float a, float b), float a, float b, float c) @@ -45,20 +55,26 @@ float main (void) res |= test ("foo", foo, 5, 3, 2); res |= test ("bar", bar, 5, 3, 2); res |= test ("baz", baz, 5, 3, 0); + res |= test ("snafu", snafu, 5, 3, 2); res |= test ("foo", foo, -5, 3, -2); res |= test ("bar", bar, -5, 3, -2); res |= test ("baz", baz, -5, 3, -2); + res |= test ("snafu", snafu, -5, 3, -2); res |= test ("foo", foo, 5, -3, 2); res |= test ("bar", bar, 5, -3, 2); res |= test ("baz", baz, 5, -3, 2); + res |= test ("snafu", snafu, 5, -3, 2); res |= test ("foo", foo, -5, -3, -2); res |= test ("bar", bar, -5, -3, -2); res |= test ("baz", baz, -5, -3, 0); + res |= test ("snafu", snafu, -5, -3, -2); res |= test ("foo", foo, 5, 3.5, 1.5); res |= test ("foo", foo, -5, 3.5, -1.5); + res |= test ("snafu", snafu, 5, 3.5, 1.5); + res |= test ("snafu", snafu, -5, 3.5, -1.5); return res; } From b4fd804e4e9cfa9bfc484704f80a87c0146eb0d7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 11:53:56 +0900 Subject: [PATCH 0297/3664] Implement true modulo in the engine --- include/QF/pr_comp.h | 4 ++++ libs/gamecode/pr_exec.c | 35 +++++++++++++++++++++++++++++++++++ libs/gamecode/pr_opcode.c | 13 +++++++++++++ 3 files changed, 52 insertions(+) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 0fb09da41..7d7589c4d 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -391,6 +391,10 @@ typedef enum { OP_LOADB_D, OP_LOADBI_D, OP_ADDRESS_D, + + OP_MOD_I, + OP_MOD_F, + OP_MOD_D, } pr_opcode_e; typedef struct opcode_s { diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 8cb6ecbb8..c6f376c62 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -318,6 +318,8 @@ signal_hook (int sig, void *data) else OPC.integer_var = 0x7fffffff; return 1; + case OP_MOD_I: + case OP_MOD_F: case OP_REM_I: case OP_REM_F: OPC.integer_var = 0x00000000; @@ -1429,9 +1431,35 @@ op_call: case OP_DIV_I: OPC.integer_var = OPA.integer_var / OPB.integer_var; break; + case OP_MOD_I: + { + // implement true modulo for integers: + // 5 mod 3 = 2 + // -5 mod 3 = 1 + // 5 mod -3 = -1 + // -5 mod -3 = -2 + int a = OPA.integer_var; + int b = OPB.integer_var; + int c = a % b; + // % is really remainder and so has the same sign rules + // as division: -5 % 3 = -2, so need to add b (3 here) + // if c's sign is incorrect, but only if c is non-zero + int mask = (a ^ b) >> 31; + mask &= ~!!c + 1; + OPC.integer_var = c + (mask & b); + } + break; case OP_REM_I: OPC.integer_var = OPA.integer_var % OPB.integer_var; break; + case OP_MOD_D: + { + double a = OPA_double_var; + double b = OPB_double_var; + // floating point modulo is so much easier :P + OPC_double_var = a - b * floor (a / b); + } + break; case OP_REM_D: { double a = OPA_double_var; @@ -1439,6 +1467,13 @@ op_call: OPC_double_var = a - b * trunc (a / b); } break; + case OP_MOD_F: + { + float a = OPA.float_var; + float b = OPB.float_var; + OPC.float_var = a - b * floorf (a / b); + } + break; case OP_REM_F: { float a = OPA.float_var; diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 01dd172ae..15185b37d 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -175,6 +175,10 @@ VISIBLE opcode_t pr_opcodes[] = { ev_double, ev_double, ev_double, PROG_VERSION, }, + {"%%", "mod.d", OP_MOD_D, false, + ev_double, ev_double, ev_double, + PROG_VERSION, + }, {"+", "add.d", OP_ADD_D, false, ev_double, ev_double, ev_double, @@ -1040,6 +1044,10 @@ VISIBLE opcode_t pr_opcodes[] = { ev_integer, ev_integer, ev_integer, PROG_VERSION, }, + {"%%", "mod.i", OP_MOD_I, false, + ev_integer, ev_integer, ev_integer, + PROG_VERSION, + }, {"&", "bitand.i", OP_BITAND_I, false, ev_integer, ev_integer, ev_integer, PROG_VERSION, @@ -1054,6 +1062,11 @@ VISIBLE opcode_t pr_opcodes[] = { PROG_VERSION, }, + {"%%", "mod.f", OP_MOD_F, false, + ev_float, ev_float, ev_float, + PROG_VERSION, + }, + {">=", "ge.i", OP_GE_I, false, ev_integer, ev_integer, ev_integer, PROG_VERSION, From 9d2d33fa50acd65a5ec59edc2a1e740b7f33bad3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 11:57:58 +0900 Subject: [PATCH 0298/3664] Implement %% (true modulo) support in qfcc However, it's not quite working yet --- tools/qfcc/source/dot_expr.c | 1 + tools/qfcc/source/expr_binary.c | 16 ++++++++++++++++ tools/qfcc/source/qc-lex.l | 10 ++++++++++ tools/qfcc/source/qc-parse.y | 3 ++- tools/qfcc/test/modulo.r | 15 +++++++++++++++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 675488e93..081dbecec 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -88,6 +88,7 @@ get_op_string (int op) case '*': return "*"; case '/': return "/"; case '%': return "%"; + case MOD: return "%%"; case '&': return "&"; case '|': return "|"; case '^': return "^"; diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 0f2a1e256..2e31116f3 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -69,6 +69,7 @@ static expr_type_t float_float[] = { {'|', &type_float}, {'^', &type_float}, {'%', &type_float}, + {MOD, &type_float}, {SHL, &type_float}, {SHR, &type_float}, {EQ, &type_integer}, @@ -99,6 +100,7 @@ static expr_type_t float_integer[] = { {'|', &type_float, 0, &type_float}, {'^', &type_float, 0, &type_float}, {'%', &type_float, 0, &type_float}, + {MOD, &type_float, 0, &type_float}, {SHL, &type_float, 0, &type_float}, {SHR, &type_float, 0, &type_float}, {EQ, &type_integer, 0, &type_float}, @@ -118,6 +120,7 @@ static expr_type_t float_double[] = { {'*', &type_double, &type_double, 0}, {'/', &type_double, &type_double, 0}, {'%', &type_double, &type_double, 0}, + {MOD, &type_double, &type_double, 0}, {EQ, 0, 0, 0, double_compare}, {NE, 0, 0, 0, double_compare}, {LE, 0, 0, 0, double_compare}, @@ -232,6 +235,7 @@ static expr_type_t integer_float[] = { {'|', &type_float, &type_float, 0}, {'^', &type_float, &type_float, 0}, {'%', &type_float, &type_float, 0}, + {MOD, &type_float, &type_float, 0}, {SHL, &type_integer, 0, &type_integer}, //FIXME? {SHR, &type_integer, 0, &type_integer}, //FIXME? {EQ, &type_integer, &type_float, 0}, @@ -267,6 +271,7 @@ static expr_type_t integer_integer[] = { {'|', &type_integer}, {'^', &type_integer}, {'%', &type_integer}, + {MOD, &type_integer}, {SHL, &type_integer}, {SHR, &type_integer}, {EQ, &type_integer}, @@ -287,6 +292,7 @@ static expr_type_t integer_uinteger[] = { {'|', &type_integer}, {'^', &type_integer}, {'%', &type_integer}, + {MOD, &type_integer}, {SHL, &type_integer}, {SHR, &type_integer}, {EQ, &type_integer}, @@ -307,6 +313,7 @@ static expr_type_t integer_short[] = { {'|', &type_integer, 0, &type_integer}, {'^', &type_integer, 0, &type_integer}, {'%', &type_integer, 0, &type_integer}, + {MOD, &type_integer, 0, &type_integer}, {SHL, &type_integer, 0, &type_integer}, {SHR, &type_integer, 0, &type_integer}, {EQ, &type_integer, 0, &type_integer}, @@ -324,6 +331,7 @@ static expr_type_t integer_double[] = { {'*', &type_double, &type_double, 0}, {'/', &type_double, &type_double, 0}, {'%', &type_double, &type_double, 0}, + {MOD, &type_double, &type_double, 0}, {EQ, &type_integer, &type_double, 0}, {NE, &type_integer, &type_double, 0}, {LE, &type_integer, &type_double, 0}, @@ -347,6 +355,7 @@ static expr_type_t uinteger_integer[] = { {'|', &type_integer}, {'^', &type_integer}, {'%', &type_integer}, + {MOD, &type_integer}, {SHL, &type_uinteger}, {SHR, &type_uinteger}, {EQ, &type_integer}, @@ -367,6 +376,7 @@ static expr_type_t uinteger_uinteger[] = { {'|', &type_uinteger}, {'^', &type_uinteger}, {'%', &type_uinteger}, + {MOD, &type_uinteger}, {SHL, &type_uinteger}, {SHR, &type_uinteger}, {EQ, &type_integer}, @@ -394,6 +404,7 @@ static expr_type_t short_integer[] = { {'|', &type_integer, &type_integer, 0}, {'^', &type_integer, &type_integer, 0}, {'%', &type_integer, &type_integer, 0}, + {MOD, &type_integer, &type_integer, 0}, {SHL, &type_short}, {SHR, &type_short}, {EQ, &type_integer, &type_integer, 0}, @@ -414,6 +425,7 @@ static expr_type_t short_uinteger[] = { {'|', &type_uinteger, &type_uinteger, 0}, {'^', &type_uinteger, &type_uinteger, 0}, {'%', &type_uinteger, &type_uinteger, 0}, + {MOD, &type_uinteger, &type_uinteger, 0}, {SHL, &type_short}, {SHR, &type_short}, {EQ, &type_integer, &type_uinteger, 0}, @@ -434,6 +446,7 @@ static expr_type_t short_short[] = { {'|', &type_short}, {'^', &type_short}, {'%', &type_short}, + {MOD, &type_short}, {SHL, &type_short}, {SHR, &type_short}, {EQ, &type_integer}, @@ -452,6 +465,7 @@ static expr_type_t double_float[] = { {'*', &type_double, 0, &type_double}, {'/', &type_double, 0, &type_double}, {'%', &type_double, 0, &type_double}, + {MOD, &type_double, 0, &type_double}, {EQ, 0, 0, 0, double_compare}, {NE, 0, 0, 0, double_compare}, {LE, 0, 0, 0, double_compare}, @@ -477,6 +491,7 @@ static expr_type_t double_integer[] = { {'*', &type_double, 0, &type_double}, {'/', &type_double, 0, &type_double}, {'%', &type_double, 0, &type_double}, + {MOD, &type_double, 0, &type_double}, {EQ, 0, 0, 0, double_compare}, {NE, 0, 0, 0, double_compare}, {LE, 0, 0, 0, double_compare}, @@ -494,6 +509,7 @@ static expr_type_t double_double[] = { {'*', &type_double}, {'/', &type_double}, {'%', &type_double}, + {MOD, &type_double}, {EQ, &type_integer}, {NE, &type_integer}, {LE, &type_integer}, diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 5b97a0938..58b661220 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -216,6 +216,11 @@ STRING \"(\\.|[^"\\])*\" return ASX; } +"%%=" { + qc_yylval.op = MOD; + return ASX; + } + "<<=" { qc_yylval.op = SHL; return ASX; @@ -231,6 +236,11 @@ STRING \"(\\.|[^"\\])*\" return yytext[0]; } +"%%" { + qc_yylval.pointer = 0; // ensure pointer vals are null + return MOD; + } + {ELLIPSIS} return ELLIPSIS; "<<" return SHL; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index eba38584d..c34efd0a0 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -135,7 +135,7 @@ int yylex (void); %left SHL SHR %left '+' '-' -%left '*' '/' '%' +%left '*' '/' '%' MOD %right SIZEOF UNARY INCOP %left HYPERUNARY %left '.' '(' '[' @@ -1335,6 +1335,7 @@ expr | expr '|' expr { $$ = binary_expr ('|', $1, $3); } | expr '^' expr { $$ = binary_expr ('^', $1, $3); } | expr '%' expr { $$ = binary_expr ('%', $1, $3); } + | expr MOD expr { $$ = binary_expr (MOD, $1, $3); } ; texpr diff --git a/tools/qfcc/test/modulo.r b/tools/qfcc/test/modulo.r index 81366c134..9d529a0b8 100644 --- a/tools/qfcc/test/modulo.r +++ b/tools/qfcc/test/modulo.r @@ -6,6 +6,21 @@ float snafu (float a, float b) return c; } +@overload int modulo (int a, int b) +{ + return a %% b; +} + +@overload float modulo (float a, float b) +{ + return a %% b; +} + +@overload double modulo (double a, double b) +{ + return a %% b; +} + #pragma traditional float foo (float a, float b) { From 32c21ec559f6d335ca5da2b9bf4013d42bd2e96c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 12:08:08 +0900 Subject: [PATCH 0299/3664] Make gcc accept the bitwise-boolean magic Forgot to compile check... --- libs/gamecode/pr_exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index c6f376c62..3d5e938ec 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1445,7 +1445,7 @@ op_call: // as division: -5 % 3 = -2, so need to add b (3 here) // if c's sign is incorrect, but only if c is non-zero int mask = (a ^ b) >> 31; - mask &= ~!!c + 1; + mask &= ~(!!c + 0) + 1; // +0 to convert bool to int (gcc) OPC.integer_var = c + (mask & b); } break; From 1a9510834a33ff6baf422dfd8b9505420bc693e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 12:10:09 +0900 Subject: [PATCH 0300/3664] Add a missed opcode conversion for %% --- tools/qfcc/source/statements.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 5dc5d878c..239c11f49 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -439,6 +439,7 @@ convert_op (int op) case '*': return "*"; case '/': return "/"; case '%': return "%"; + case MOD: return "%%"; case '&': return "&"; case '|': return "|"; case '^': return "^"; From 1bc08c59f679e1e6abed4a6043358663075d5b44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 17:02:38 +0900 Subject: [PATCH 0301/3664] Add tests for %% double fails due to qfcc aligning double param locals, but the engine not doing so. --- tools/qfcc/test/modulo.r | 119 ++++++++++++++++++++++++++++++--------- 1 file changed, 92 insertions(+), 27 deletions(-) diff --git a/tools/qfcc/test/modulo.r b/tools/qfcc/test/modulo.r index 9d529a0b8..2d31a69a2 100644 --- a/tools/qfcc/test/modulo.r +++ b/tools/qfcc/test/modulo.r @@ -6,17 +6,17 @@ float snafu (float a, float b) return c; } -@overload int modulo (int a, int b) +int imodulo (int a, int b) { return a %% b; } -@overload float modulo (float a, float b) +float fmodulo (float a, float b) { return a %% b; } -@overload double modulo (double a, double b) +double dmodulo (double a, double b) { return a %% b; } @@ -46,8 +46,27 @@ float baz (float a, float b) } #pragma advanced -float test (string name, float (func)(float a, float b), - float a, float b, float c) +@overload int +test (string name, string op, int (func)(int a, int b), int a, int b, int c) +{ + int ret; + + ret = func (a, b); + if (ret != c) { + if (func == baz) + printf ("%s: (%d + %d) %% (%d - %d): %d != %d\n", + name, a, b, a, b, ret, c); + else + printf ("%s: %d %s %d: %d != %d\n", + name, a, op, b, ret, c); + return 1; + } + return 0; +} + +@overload int +test (string name, string op, float (func)(float a, float b), + float a, float b, float c) { float ret; @@ -57,8 +76,27 @@ float test (string name, float (func)(float a, float b), printf ("%s: (%g + %g) %% (%g - %g): %g != %g\n", name, a, b, a, b, ret, c); else - printf ("%s: %g %% %g: %g != %g\n", - name, a, b, ret, c); + printf ("%s: %g %s %g: %g != %g\n", + name, a, op, b, ret, c); + return 1; + } + return 0; +} + +@overload int +test (string name, string op, double (func)(double a, double b), + double a, double b, double c) +{ + double ret; + + ret = func (a, b); + if (ret != c) { + if (func == baz) + printf ("%s: (%g + %g) %% (%g - %g): %g != %g\n", + name, a, b, a, b, ret, c); + else + printf ("%s: %g %s %g: %g != %g\n", + name, a, op, b, ret, c); return 1; } return 0; @@ -67,29 +105,56 @@ float test (string name, float (func)(float a, float b), float main (void) { float res = 0; - res |= test ("foo", foo, 5, 3, 2); - res |= test ("bar", bar, 5, 3, 2); - res |= test ("baz", baz, 5, 3, 0); - res |= test ("snafu", snafu, 5, 3, 2); + res |= test ("foo", "%", foo, 5, 3, 2); + res |= test ("bar", "%", bar, 5, 3, 2); + res |= test ("baz", "%", baz, 5, 3, 0); + res |= test ("snafu", "%", snafu, 5, 3, 2); - res |= test ("foo", foo, -5, 3, -2); - res |= test ("bar", bar, -5, 3, -2); - res |= test ("baz", baz, -5, 3, -2); - res |= test ("snafu", snafu, -5, 3, -2); + res |= test ("foo", "%", foo, -5, 3, -2); + res |= test ("bar", "%", bar, -5, 3, -2); + res |= test ("baz", "%", baz, -5, 3, -2); + res |= test ("snafu", "%", snafu, -5, 3, -2); - res |= test ("foo", foo, 5, -3, 2); - res |= test ("bar", bar, 5, -3, 2); - res |= test ("baz", baz, 5, -3, 2); - res |= test ("snafu", snafu, 5, -3, 2); + res |= test ("foo", "%", foo, 5, -3, 2); + res |= test ("bar", "%", bar, 5, -3, 2); + res |= test ("baz", "%", baz, 5, -3, 2); + res |= test ("snafu", "%", snafu, 5, -3, 2); - res |= test ("foo", foo, -5, -3, -2); - res |= test ("bar", bar, -5, -3, -2); - res |= test ("baz", baz, -5, -3, 0); - res |= test ("snafu", snafu, -5, -3, -2); + res |= test ("foo", "%", foo, -5, -3, -2); + res |= test ("bar", "%", bar, -5, -3, -2); + res |= test ("baz", "%", baz, -5, -3, 0); + res |= test ("snafu", "%", snafu, -5, -3, -2); - res |= test ("foo", foo, 5, 3.5, 1.5); - res |= test ("foo", foo, -5, 3.5, -1.5); - res |= test ("snafu", snafu, 5, 3.5, 1.5); - res |= test ("snafu", snafu, -5, 3.5, -1.5); + res |= test ("foo", "%", foo, 5, 3.5, 1.5); + res |= test ("foo", "%", foo, -5, 3.5, -1.5); + res |= test ("snafu", "%", snafu, 5, 3.5, 1.5); + res |= test ("snafu", "%", snafu, -5, 3.5, -1.5); + + res |= test ("int modulo", "%%", imodulo, 5, 3, 2); + res |= test ("int modulo", "%%", imodulo, -5, 3, 1); + res |= test ("int modulo", "%%", imodulo, 5, -3, -1); + res |= test ("int modulo", "%%", imodulo, -5, -3, -2); + res |= test ("int modulo", "%%", imodulo, 6, 3, 0); + res |= test ("int modulo", "%%", imodulo, -6, 3, 0); + res |= test ("int modulo", "%%", imodulo, 6, -3, 0); + res |= test ("int modulo", "%%", imodulo, -6, -3, 0); + + res |= test ("float modulo", "%%", fmodulo, 5, 3, 2); + res |= test ("float modulo", "%%", fmodulo, -5, 3, 1); + res |= test ("float modulo", "%%", fmodulo, 5, -3, -1); + res |= test ("float modulo", "%%", fmodulo, -5, -3, -2); + res |= test ("float modulo", "%%", fmodulo, 6, 3, 0); + res |= test ("float modulo", "%%", fmodulo, -6, 3, 0); + res |= test ("float modulo", "%%", fmodulo, 6, -3, 0); + res |= test ("float modulo", "%%", fmodulo, -6, -3, 0); + + res |= test ("double modulo", "%%", dmodulo, 5, 3, 2); + res |= test ("double modulo", "%%", dmodulo, -5, 3, 1); + res |= test ("double modulo", "%%", dmodulo, 5, -3, -1); + res |= test ("double modulo", "%%", dmodulo, -5, -3, -2); + res |= test ("double modulo", "%%", dmodulo, 6, 3, 0); + res |= test ("double modulo", "%%", dmodulo, -6, 3, 0); + res |= test ("double modulo", "%%", dmodulo, 6, -3, 0); + res |= test ("double modulo", "%%", dmodulo, -6, -3, 0); return res; } From 7a399c956be525b386c232047a38dea441b6a688 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 17:10:43 +0900 Subject: [PATCH 0302/3664] Encode function parameter alignment The encoding is 3:5 giving 3 bits for alignment (log2) and 5 bits for size, with alignment in the 3 most significant bits. This keeps the format backwards compatible as until doubles were added, all types were aligned to 1 word which gets encoded as 0, and the size is unaffected. --- include/QF/pr_comp.h | 7 +++- tools/qfcc/include/obj_file.h | 2 + tools/qfcc/source/Makefile.am | 2 +- tools/qfcc/source/dump_globals.c | 3 +- tools/qfcc/source/obj_file.c | 63 ++++++++++++++++++++++++++++++-- tools/qfcc/source/qfcc.c | 3 ++ tools/qfcc/source/stub.c | 18 ++++++++- 7 files changed, 91 insertions(+), 7 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 7d7589c4d..185a802ad 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -423,6 +423,11 @@ typedef struct ddef_s { pr_int_t s_name; } ddef_t; +typedef struct dparmsize_s { + uint8_t size:5; + uint8_t alignment:3; +} dparmsize_t; + #define DEF_SAVEGLOBAL (1<<15) #define MAX_PARMS 8 @@ -438,7 +443,7 @@ typedef struct dfunction_s { pr_int_t s_file; // source file defined in pr_int_t numparms; - uint8_t parm_size[MAX_PARMS]; + dparmsize_t parm_size[MAX_PARMS]; } dfunction_t; typedef union pr_type_u { diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index c32c67eb2..ae1986245 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -497,6 +497,8 @@ qfo_t *qfo_new (void); */ void qfo_delete (qfo_t *qfo); +__attribute__((const)) int qfo_log2 (unsigned x); + ///@} #endif//__obj_file_h diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index e63edc20d..7feed1dca 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -53,7 +53,7 @@ qfcc_DEPENDENCIES= $(QFCC_DEPS) qfprogs_SOURCES= \ disassemble.c dump_globals.c dump_lines.c dump_modules.c dump_strings.c \ - obj_file.c qfprogs.c strpool.c stub.c + obj_file.c qfprogs.c strpool.c stub.c type.c qfprogs_LDADD= $(QFCC_LIBS) qfprogs_DEPENDENCIES= $(QFCC_DEPS) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 6bebf5bb5..9e0b5bd5f 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -217,7 +217,8 @@ dump_functions (progs_t *pr) else count = func->numparms; for (j = 0; j < count; j++) - printf (" %d", func->parm_size[j]); + printf (" %d:%d", func->parm_size[j].alignment, + func->parm_size[j].size); printf (") %d @ %x", func->locals, func->parm_start); puts (""); if (pr->debug) { diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index c809a4a8b..44148eec8 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -665,7 +665,7 @@ get_def_type (qfo_t *qfo, pointer_t type) return ev_invalid; } -static __attribute__((pure)) etype_t +static __attribute__((pure)) int get_type_size (qfo_t *qfo, pointer_t type) { qfot_type_t *type_def; @@ -701,6 +701,62 @@ get_type_size (qfo_t *qfo, pointer_t type) return 0; } +int +qfo_log2 (unsigned x) +{ + int log2 = 0; + + while (x > 1) { + x >>= 1; + log2++; + } + return log2; +} + +static __attribute__((pure)) int +get_type_alignment_log (qfo_t *qfo, pointer_t type) +{ + qfot_type_t *type_def; + int i, alignment; + if (type >= qfo->spaces[qfo_type_space].data_size) + return 0; + type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); + switch ((ty_meta_e)type_def->meta) { + case ty_none: + // field, pointer and function types store their basic type in + // the same location. + return qfo_log2 (ev_types[type_def->t.type]->alignment); + case ty_struct: + case ty_union: + for (i = alignment = 0; i < type_def->t.strct.num_fields; i++) { + qfot_var_t *field = type_def->t.strct.fields + i; + int a; + a = get_type_alignment_log (qfo, field->type); + if (a > alignment) { + alignment = a; + } + } + return alignment; + case ty_enum: + return qfo_log2 (ev_types[ev_integer]->alignment); + case ty_array: + return get_type_alignment_log (qfo, type_def->t.array.type); + case ty_class: + return 0; // FIXME + } + return 0; +} + +static __attribute__((pure)) dparmsize_t +get_parmsize (qfo_t *qfo, pointer_t type) +{ + dparmsize_t parmsize = { + get_type_size (qfo, type), + get_type_alignment_log (qfo, type), + }; + return parmsize; +} + static void function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) { @@ -716,8 +772,9 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) df->numparms = num_params = type->t.func.num_params; if (num_params < 0) num_params = ~num_params; - for (i = 0; i < num_params; i++) - df->parm_size[i] = get_type_size (qfo, type->t.func.param_types[i]); + for (i = 0; i < num_params; i++) { + df->parm_size[i] = get_parmsize (qfo, type->t.func.param_types[i]); + } } static void diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 0da2caf88..780db073a 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -418,8 +418,11 @@ finish_link (void) flags = (QFOD_GLOBAL | QFOD_CONSTANT | QFOD_INITIALIZED | QFOD_NOSAVE); if (options.code.progsversion != PROG_ID_VERSION) { pr_int_t param_size = type_size (&type_param); + pr_int_t param_alignment = qfo_log2 (type_param.alignment); linker_add_def (".param_size", &type_integer, flags, ¶m_size); + linker_add_def (".param_alignment", &type_integer, flags, + ¶m_alignment); } if (options.code.debug) { diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index c10aff34a..4ff08975c 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -2,6 +2,8 @@ # include "config.h" #endif +#include + #include "class.h" #include "codespace.h" #include "diagnostic.h" @@ -12,9 +14,12 @@ #include "expr.h" #include "function.h" #include "obj_file.h" +#include "obj_type.h" #include "options.h" #include "qfcc.h" #include "strpool.h" +#include "struct.h" +#include "symtab.h" #include "type.h" #include "value.h" @@ -23,11 +28,22 @@ options_t options; int num_linenos; pr_lineno_t *linenos; pr_info_t pr; +type_t type_Class; +type_t type_SEL; +type_t type_id; __attribute__((const)) string_t ReuseString (const char *str) {return 0;} -void encode_type (struct dstring_s *str, const type_t *type) {} __attribute__((const)) codespace_t *codespace_new (void) {return 0;} void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {} __attribute__((const)) int function_parms (function_t *f, byte *parm_size) {return 0;} void def_to_ddef (def_t *def, ddef_t *ddef, int aux) {} +__attribute__((noreturn)) void _internal_error (expr_t *e, const char *file, int line, const char *fmt, ...) {abort();} __attribute__((const)) expr_t *_warning (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;} __attribute__((const)) expr_t *_error (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;} +__attribute__((const)) symbol_t *make_structure (const char *name, int su, struct_def_t *defs, type_t *type) {return 0;} +__attribute__((const)) symbol_t *symtab_addsymbol (symtab_t *symtab, symbol_t *symbol) {return 0;} +__attribute__((const)) symbol_t *new_symbol_type (const char *name, type_t *type) {return 0;} +__attribute__((const)) def_t *qfo_encode_type (type_t *type) {return 0;} +__attribute__((const)) int obj_types_assignable (const type_t *dst, const type_t *src) {return 0;} +void print_protocollist (struct dstring_s *dstr, protocollist_t *protocollist) {} +int obj_is_id (const type_t *type){return type->type;} +int compare_protocols (protocollist_t *protos1, protocollist_t *protos2){return protos1->count - protos2->count;} From f5741a979e5d5db7dcef2816262519fc65eeb576 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 17:13:45 +0900 Subject: [PATCH 0303/3664] Implement parameter alignment in the engine The engine now requires non-v6 progs to store the log2 alignment for the param struct in .param_alignment. PR_EnterFunction is clearer and possibly more efficient. --- include/QF/progs.h | 3 +- libs/gamecode/pr_exec.c | 107 ++++++++++++++++++++----------------- libs/gamecode/pr_resolve.c | 4 ++ 3 files changed, 64 insertions(+), 50 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 945145bd3..e7953883e 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1079,7 +1079,7 @@ typedef struct { pr_int_t locals; pr_int_t profile; pr_int_t numparms; - uint8_t parm_size[MAX_PARMS]; + dparmsize_t parm_size[MAX_PARMS]; dfunction_t *descriptor; builtin_proc func; } bfunction_t; @@ -1632,6 +1632,7 @@ struct progs_s { pr_type_t *pr_saved_params; int pr_saved_argc; int pr_param_size; ///< covers both params and return + int pr_param_alignment; ///< covers both params and return ///@} /// \name edicts diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 3d5e938ec..500d5e922 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -142,6 +142,21 @@ PR_PopFrame (progs_t *pr) pr->pr_xtstr = frame->tstr; } +static __attribute__((pure)) long +align_offset (long offset, dparmsize_t parmsize) +{ + int mask = (1 << parmsize.alignment) - 1; + return (offset + mask) & ~mask; +} + +static void +copy_param (pr_type_t *dst, pr_type_t *src, size_t size) +{ + while (size--) { + memcpy (dst++, src++, sizeof (pr_type_t)); + } +} + /** Setup the stackframe prior to calling a progs function. Saves all local data the called function will trample on and copies the parameters used by the function into the function's local data space. @@ -153,39 +168,44 @@ PR_PopFrame (progs_t *pr) static void PR_EnterFunction (progs_t *pr, bfunction_t *f) { - pr_int_t i, j, c, o; - pr_int_t k; - pr_int_t count = 0; - int size[2] = {0, 0}; + pr_int_t i; + pr_type_t *dstParams[MAX_PARMS]; long paramofs = 0; - long offs; PR_PushFrame (pr); if (f->numparms > 0) { - for (i = 0; i < 2 && i < f->numparms; i++) { - paramofs += f->parm_size[i]; - size[i] = f->parm_size[i]; + paramofs = f->parm_start; + for (i = 0; i < f->numparms; i++) { + paramofs = align_offset (paramofs, f->parm_size[i]); + dstParams[i] = pr->pr_globals + paramofs; + paramofs += f->parm_size[i].size; + if (pr->pr_params[i] != pr->pr_real_params[i]) { + copy_param (pr->pr_real_params[i], pr->pr_params[i], + f->parm_size[i].size); + } } - count = i; } else if (f->numparms < 0) { - for (i = 0; i < 2 && i < -f->numparms - 1; i++) { - paramofs += f->parm_size[i]; - size[i] = f->parm_size[i]; + paramofs = f->parm_start + 2; // argc and argv + for (i = 0; i < -f->numparms - 1; i++) { + paramofs = align_offset (paramofs, f->parm_size[i]); + dstParams[i] = pr->pr_globals + paramofs; + paramofs += f->parm_size[i].size; + if (pr->pr_params[i] != pr->pr_real_params[i]) { + copy_param (pr->pr_real_params[i], pr->pr_params[i], + f->parm_size[i].size); + } } - for (; i < 2; i++) { - paramofs += pr->pr_param_size; - size[i] = pr->pr_param_size; + dparmsize_t parmsize = { pr->pr_param_size, pr->pr_param_alignment }; + paramofs = align_offset (paramofs, parmsize ); + if (i < MAX_PARMS) { + dstParams[i] = pr->pr_globals + paramofs; } - count = i; - } - - for (i = 0; i < count && i < pr->pr_argc; i++) { - offs = (pr->pr_params[i] - pr->pr_globals) - f->parm_start; - if (offs >= 0 && offs < paramofs) { - memcpy (pr->pr_real_params[i], pr->pr_params[i], - size[i] * sizeof (pr_type_t)); - pr->pr_params[i] = pr->pr_real_params[i]; + for (; i < MAX_PARMS; i++) { + if (pr->pr_params[i] != pr->pr_real_params[i]) { + copy_param (pr->pr_real_params[i], pr->pr_params[i], + f->parm_size[i].size); + } } } @@ -194,43 +214,33 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) pr->pr_xstatement = f->first_statement - 1; // offset the st++ // save off any locals that the new function steps on - c = f->locals; - if (pr->localstack_used + c > LOCALSTACK_SIZE) + if (pr->localstack_used + f->locals > LOCALSTACK_SIZE) PR_RunError (pr, "PR_EnterFunction: locals stack overflow"); memcpy (&pr->localstack[pr->localstack_used], &pr->pr_globals[f->parm_start], - sizeof (pr_type_t) * c); - pr->localstack_used += c; + sizeof (pr_type_t) * f->locals); + pr->localstack_used += f->locals; if (pr_deadbeef_locals->int_val) - for (k = f->parm_start; k < f->parm_start + c; k++) - pr->pr_globals[k].integer_var = 0xdeadbeef; + for (i = f->parm_start; i < f->parm_start + f->locals; i++) + pr->pr_globals[i].integer_var = 0xdeadbeef; // copy parameters - o = f->parm_start; if (f->numparms >= 0) { for (i = 0; i < f->numparms; i++) { - for (j = 0; j < f->parm_size[i]; j++) { - memcpy (&pr->pr_globals[o], &P_INT (pr, i) + j, - sizeof (pr_type_t)); - o++; - } + copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size); } } else { - pr_type_t *argc = &pr->pr_globals[o++]; - pr_type_t *argv = &pr->pr_globals[o++]; + pr_type_t *argc = &pr->pr_globals[f->parm_start + 0]; + pr_type_t *argv = &pr->pr_globals[f->parm_start + 1]; for (i = 0; i < -f->numparms - 1; i++) { - for (j = 0; j < f->parm_size[i]; j++) { - memcpy (&pr->pr_globals[o], &P_INT (pr, i) + j, - sizeof (pr_type_t)); - o++; - } + copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size); } argc->integer_var = pr->pr_argc - i; - argv->integer_var = o; + argv->integer_var = dstParams[i] - pr->pr_globals; if (i < MAX_PARMS) { - memcpy (&pr->pr_globals[o], &P_INT (pr, i), + memcpy (dstParams[i], &P_INT (pr, i), (MAX_PARMS - i) * pr->pr_param_size * sizeof (pr_type_t)); } } @@ -239,19 +249,18 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) static void PR_LeaveFunction (progs_t *pr) { - int c; bfunction_t *f = pr->pr_xfunction; PR_PopFrame (pr); // restore locals from the stack - c = f->locals; - pr->localstack_used -= c; + pr->localstack_used -= f->locals; if (pr->localstack_used < 0) PR_RunError (pr, "PR_LeaveFunction: locals stack underflow"); memcpy (&pr->pr_globals[f->parm_start], - &pr->localstack[pr->localstack_used], sizeof (pr_type_t) * c); + &pr->localstack[pr->localstack_used], + sizeof (pr_type_t) * f->locals); } VISIBLE void diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index ba82b48e8..3238e774e 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -122,6 +122,7 @@ PR_ResolveGlobals (progs_t *pr) pr->pr_params[6] = &pr->pr_globals[OFS_PARM6]; pr->pr_params[7] = &pr->pr_globals[OFS_PARM7]; pr->pr_param_size = OFS_PARM1 - OFS_PARM0; + pr->pr_param_alignment = 0; // log2 } else { if (!(def = PR_FindGlobal (pr, sym = ".return"))) goto error; @@ -134,6 +135,9 @@ PR_ResolveGlobals (progs_t *pr) if (!(def = PR_FindGlobal (pr, sym = ".param_size"))) goto error; pr->pr_param_size = G_INT (pr, def->ofs); + if (!(def = PR_FindGlobal (pr, sym = ".param_alignment"))) + goto error; + pr->pr_param_alignment = G_INT (pr, def->ofs); } if (pr->pr_saved_params) free (pr->pr_saved_params); From 12d2a0ff75b4d63aca183324579f301d9a059302 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 17:58:36 +0900 Subject: [PATCH 0304/3664] Copy the correct number of words for rcall --- libs/gamecode/pr_exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 500d5e922..5f9e09790 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -204,7 +204,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) for (; i < MAX_PARMS; i++) { if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], - f->parm_size[i].size); + parmsize.size); } } } From ed283a9e7f8f086f9731c31f81d7c5ec2105bc45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 18:00:29 +0900 Subject: [PATCH 0305/3664] Copy only the necessary number of vararg parameters --- libs/gamecode/pr_exec.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 5f9e09790..f7becdfa5 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -170,7 +170,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) { pr_int_t i; pr_type_t *dstParams[MAX_PARMS]; - long paramofs = 0; + pointer_t paramofs = 0; PR_PushFrame (pr); @@ -201,7 +201,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) if (i < MAX_PARMS) { dstParams[i] = pr->pr_globals + paramofs; } - for (; i < MAX_PARMS; i++) { + for (; i < pr->pr_argc; i++) { if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], parmsize.size); @@ -232,16 +232,18 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size); } } else { + int copy_args; pr_type_t *argc = &pr->pr_globals[f->parm_start + 0]; pr_type_t *argv = &pr->pr_globals[f->parm_start + 1]; for (i = 0; i < -f->numparms - 1; i++) { copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size); } - argc->integer_var = pr->pr_argc - i; + copy_args = pr->pr_argc - i; + argc->integer_var = copy_args; argv->integer_var = dstParams[i] - pr->pr_globals; if (i < MAX_PARMS) { - memcpy (dstParams[i], &P_INT (pr, i), - (MAX_PARMS - i) * pr->pr_param_size * sizeof (pr_type_t)); + memcpy (dstParams[i], pr->pr_params[i], + (copy_args * pr->pr_param_size) * sizeof (pr_type_t)); } } } From b947cc1791a37e8f483d43d07950cd7c212ce5fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 22:43:57 +0900 Subject: [PATCH 0306/3664] Rework command buffer and fence-set management I found command buffer handling to be totally redundant and fence-set management to be a bit awkward. --- include/QF/Vulkan/command.h | 28 ++--- libs/video/renderer/vulkan/command.c | 150 ++++++++++++++------------- 2 files changed, 92 insertions(+), 86 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 7f28e7c88..14eb625ac 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -8,13 +8,14 @@ typedef struct qfv_cmdpool_s { typedef struct qfv_cmdbuffer_s { struct qfv_device_s *device; - VkCommandPool cmdpool; - VkCommandBuffer buffer; + VkCommandBuffer *buffer; } qfv_cmdbuffer_t; typedef struct qfv_cmdbufferset_s { struct qfv_device_s *device; - VkCommandBuffer *buffers; + qfv_cmdbuffer_t **buffers; + VkCommandBuffer *vkBuffers; + VkCommandPool cmdpool; int numBuffers; } qfv_cmdbufferset_t; @@ -37,7 +38,8 @@ typedef struct qfv_fence_s { typedef struct qfv_fenceset_s { struct qfv_device_s *device; - VkFence *fences; + qfv_fence_t **fences; + VkFence *vkFences; int numFences; } qfv_fenceset_t; @@ -47,13 +49,9 @@ qfv_cmdpool_t *QFV_CreateCommandPool (struct qfv_device_s *device, int transient, int reset); int QFV_ResetCommandPool (qfv_cmdpool_t *pool, int release); void QFV_DestroyCommandPool (qfv_cmdpool_t *pool); -qfv_cmdbuffer_t *QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, - int secondary, int count); -qfv_cmdbufferset_t *QFV_CreateCommandBufferSet (qfv_cmdbuffer_t **buffers, - int numBuffers); -void QFV_FreeCommandBuffers (qfv_cmdbuffer_t *buffer, int count); -// NOTE: does not destroy buffers -void QFV_DestroyCommandBufferSet (qfv_cmdbufferset_t *buffers); +qfv_cmdbufferset_t *QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, + int secondary, int count); +void QFV_FreeCommandBuffers (qfv_cmdbufferset_t *buffer); int QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, int rpContinue, int simultaneous, VkCommandBufferInheritanceInfo *inheritanceInfo); @@ -70,9 +68,11 @@ qfv_fence_t *QFV_CreateFence (struct qfv_device_s *device, int signaled); qfv_fenceset_t *QFV_CreateFenceSet (qfv_fence_t **fences, int numFences); void QFV_DestroyFence (qfv_fence_t *fence); // NOTE: does not destroy fences -void QFV_DestroyFenceSet (qfv_fenceset_t *fences); -int QFV_WaitForFences (qfv_fenceset_t *fences, int all, uint64_t timeout); -int QFV_ResetFences (qfv_fenceset_t *fences); +void QFV_DestroyFenceSet (qfv_fenceset_t *fenceset); +int QFV_WaitForFences (qfv_fenceset_t *fenceset, int all, uint64_t timeout); +int QFV_WaitForFence (qfv_fence_t *fence, uint64_t timeout); +int QFV_ResetFences (qfv_fenceset_t *fenceset); +int QFV_ResetFence (qfv_fence_t *fence); int QFV_QueueSubmit (struct qfv_queue_s *queue, qfv_semaphoreset_t *waitSemaphores, qfv_cmdbufferset_t *buffers, diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 09621ede5..9f581ded6 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -115,7 +115,7 @@ QFV_DestroyCommandPool (qfv_cmdpool_t *pool) free (pool); } -qfv_cmdbuffer_t * +qfv_cmdbufferset_t * QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) { qfv_device_t *device = pool->device; @@ -129,54 +129,34 @@ QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 0, pool->cmdpool, level, count }; - qfv_cmdbuffer_t *cmdbuffers = malloc (count * sizeof (*cmdbuffers)); - VkCommandBuffer *buffers = alloca (count * sizeof (*buffers)); - dfunc->vkAllocateCommandBuffers (dev, &allocInfo, buffers); + qfv_cmdbufferset_t *cmdbufferset; + cmdbufferset = malloc (sizeof (qfv_cmdbufferset_t) + + count * sizeof (qfv_buffer_t *) + + count * sizeof (qfv_buffer_t) + + count * sizeof (VkCommandBuffer)); + cmdbufferset->buffers = (qfv_cmdbuffer_t **) (cmdbufferset + 1); + cmdbufferset->vkBuffers = (VkCommandBuffer *) (cmdbufferset->buffers + + count); + cmdbufferset->cmdpool = pool->cmdpool; + cmdbufferset->numBuffers = count; + dfunc->vkAllocateCommandBuffers (dev, &allocInfo, cmdbufferset->vkBuffers); for (int i = 0; i < count; i++) { - cmdbuffers[i].device = device; - cmdbuffers[i].cmdpool = pool->cmdpool; - cmdbuffers[i].buffer = buffers[i]; + cmdbufferset->buffers[i]->device = device; + cmdbufferset->buffers[i]->buffer = &cmdbufferset->vkBuffers[i]; } - return cmdbuffers; + return cmdbufferset; } -qfv_cmdbufferset_t * -QFV_CreateCommandBufferSet (qfv_cmdbuffer_t **buffers, int numBuffers) +void QFV_FreeCommandBuffers (qfv_cmdbufferset_t *bufferset) { - qfv_device_t *device = buffers[0]->device; - qfv_cmdbufferset_t *bufferset = malloc (sizeof (*bufferset) - + sizeof (VkCommandBuffer) - * numBuffers); - - bufferset->device = device; - bufferset->buffers = (VkCommandBuffer *) (bufferset + 1); - bufferset->numBuffers = numBuffers; - - for (int i = 0; i < numBuffers; i++) { - bufferset->buffers[i] = buffers[i]->buffer; - } - return bufferset; -} - -void QFV_FreeCommandBuffers (qfv_cmdbuffer_t *buffer, int count) -{ - qfv_device_t *device = buffer->device; + qfv_device_t *device = bufferset->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - VkCommandBuffer *buffers = alloca (sizeof (*buffers) * count); - for (int i = 0; i < count; i++) { - buffers[i] = buffer[i].buffer; - } - - dfunc->vkFreeCommandBuffers (dev, buffer->cmdpool, count, buffers); - free (buffer); -} - -void -QFV_DestroyCommandBufferSet (qfv_cmdbufferset_t *buffers) -{ - free (buffers); + dfunc->vkFreeCommandBuffers (dev, bufferset->cmdpool, + bufferset->numBuffers, + bufferset->vkBuffers); + free (bufferset); } int @@ -186,7 +166,7 @@ QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, int rpContinue, { qfv_device_t *device = buffer->device; qfv_devfuncs_t *dfunc = device->funcs; - VkCommandBuffer buff = buffer->buffer; + VkCommandBuffer buff = *buffer->buffer; VkCommandBufferUsageFlags usage = 0; if (oneTime) { @@ -213,7 +193,7 @@ QFV_EndCommandBuffer (qfv_cmdbuffer_t *buffer) { qfv_device_t *device = buffer->device; qfv_devfuncs_t *dfunc = device->funcs; - VkCommandBuffer buff = buffer->buffer; + VkCommandBuffer buff = *buffer->buffer; return dfunc->vkEndCommandBuffer (buff) == VK_SUCCESS; } @@ -223,7 +203,7 @@ QFV_ResetCommandBuffer (qfv_cmdbuffer_t *buffer, int release) { qfv_device_t *device = buffer->device; qfv_devfuncs_t *dfunc = device->funcs; - VkCommandBuffer buff = buffer->buffer; + VkCommandBuffer buff = *buffer->buffer; VkCommandBufferResetFlags release_flag = 0; if (release) { @@ -310,16 +290,20 @@ QFV_CreateFence (qfv_device_t *device, int signaled) qfv_fenceset_t * QFV_CreateFenceSet (qfv_fence_t **fences, int numFences) { - qfv_device_t *device = fences[0]->device; qfv_fenceset_t *fenceset = malloc (sizeof (*fenceset) + + sizeof (qfv_fence_t) * numFences + sizeof (VkFence) * numFences); - fenceset->device = device; - fenceset->fences = (VkFence *) (fenceset + 1); + fenceset->fences = (qfv_fence_t **) (fenceset + 1); + fenceset->vkFences = (VkFence *) (fenceset->fences + numFences); fenceset->numFences = numFences; - for (int i = 0; i < numFences; i++) { - fenceset->fences[i] = fences[i]->fence; + if (fences) { + fenceset->device = fences[0]->device; + for (int i = 0; i < numFences; i++) { + fenceset->fences[i] = fences[i]; + fenceset->vkFences[i] = fences[i]->fence; + } } return fenceset; } @@ -336,32 +320,53 @@ QFV_DestroyFence (qfv_fence_t *fence) } void -QFV_DestroyFenceSet (qfv_fenceset_t *fences) +QFV_DestroyFenceSet (qfv_fenceset_t *fenceset) { - free (fences); + free (fenceset); } int -QFV_WaitForFences (qfv_fenceset_t *fences, int all, uint64_t timeout) +QFV_WaitForFences (qfv_fenceset_t *fenceset, int all, uint64_t timeout) { - qfv_device_t *device = fences->device; + qfv_device_t *device = fenceset->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - VkResult res = dfunc->vkWaitForFences (dev, fences->numFences, - fences->fences, all, timeout); + VkResult res = dfunc->vkWaitForFences (dev, fenceset->numFences, + fenceset->vkFences, all, timeout); return res == VK_SUCCESS; } int -QFV_ResetFences (qfv_fenceset_t *fences) +QFV_WaitForFence (qfv_fence_t *fence, uint64_t timeout) { - qfv_device_t *device = fences->device; + qfv_device_t *device = fence->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - return dfunc->vkResetFences (dev, fences->numFences, - fences->fences) == VK_SUCCESS; + VkResult res = dfunc->vkWaitForFences (dev, 1, &fence->fence, 1, timeout); + return res == VK_SUCCESS; +} + +int +QFV_ResetFences (qfv_fenceset_t *fenceset) +{ + qfv_device_t *device = fenceset->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + return dfunc->vkResetFences (dev, fenceset->numFences, + fenceset->vkFences) == VK_SUCCESS; +} + +int +QFV_ResetFence (qfv_fence_t *fence) +{ + qfv_device_t *device = fence->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + return dfunc->vkResetFences (dev, 1, &fence->fence) == VK_SUCCESS; } int @@ -375,7 +380,7 @@ QFV_QueueSubmit (qfv_queue_t *queue, qfv_semaphoreset_t *waitSemaphores, VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, waitSemaphores->numSemaphores, waitSemaphores->semaphores, waitSemaphores->stages, - buffers->numBuffers, buffers->buffers, + buffers->numBuffers, buffers->vkBuffers, signalSemaphores->numSemaphores, signalSemaphores->semaphores }; @@ -418,11 +423,11 @@ QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, numImgBarriers = imgBarrierSet->numBarriers; imgBarriers = imgBarrierSet->barriers; } - dfunc->vkCmdPipelineBarrier (cmdBuffer->buffer, - srcStageMask, dstStageMask, dependencyFlags, - numMemBarriers, memBarriers, - numBuffBarriers, buffBarriers, - numImgBarriers, imgBarriers); + dfunc->vkCmdPipelineBarrier (*cmdBuffer->buffer, + srcStageMask, dstStageMask, dependencyFlags, + numMemBarriers, memBarriers, + numBuffBarriers, buffBarriers, + numImgBarriers, imgBarriers); } void @@ -433,7 +438,7 @@ QFV_CmdCopyBuffer (qfv_cmdbuffer_t *cmdBuffer, qfv_device_t *device = cmdBuffer->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCmdCopyBuffer (cmdBuffer->buffer, src->buffer, dst->buffer, + dfunc->vkCmdCopyBuffer (*cmdBuffer->buffer, src->buffer, dst->buffer, numRegions, regions); } @@ -447,7 +452,7 @@ QFV_CmdCopyBufferToImage (qfv_cmdbuffer_t *cmdBuffer, qfv_device_t *device = cmdBuffer->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCmdCopyBufferToImage (cmdBuffer->buffer, src->buffer, dst->image, + dfunc->vkCmdCopyBufferToImage (*cmdBuffer->buffer, src->buffer, dst->image, layout, numRegions, regions); } @@ -461,7 +466,7 @@ QFV_CmdCopyImageToBuffer (qfv_cmdbuffer_t *cmdBuffer, qfv_device_t *device = cmdBuffer->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCmdCopyImageToBuffer (cmdBuffer->buffer, src->image, layout, + dfunc->vkCmdCopyImageToBuffer (*cmdBuffer->buffer, src->image, layout, dst->buffer, numRegions, regions); } @@ -483,7 +488,7 @@ QFV_CmdBeginRenderPass (qfv_cmdbuffer_t *cmdBuffer, numClearValues, clearValues, }; - dfunc->vkCmdBeginRenderPass (cmdBuffer->buffer, &beginInfo, + dfunc->vkCmdBeginRenderPass (*cmdBuffer->buffer, &beginInfo, subpassContents); } @@ -494,7 +499,7 @@ QFV_CmdNextSubpass (qfv_cmdbuffer_t *cmdBuffer, qfv_device_t *device = cmdBuffer->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCmdNextSubpass (cmdBuffer->buffer, subpassContents); + dfunc->vkCmdNextSubpass (*cmdBuffer->buffer, subpassContents); } void @@ -503,7 +508,7 @@ QFV_CmdEndRenderPass (qfv_cmdbuffer_t *cmdBuffer) qfv_device_t *device = cmdBuffer->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCmdEndRenderPass (cmdBuffer->buffer); + dfunc->vkCmdEndRenderPass (*cmdBuffer->buffer); } void @@ -514,5 +519,6 @@ QFV_CmdBindPipeline (qfv_cmdbuffer_t *cmdBuffer, qfv_device_t *device = cmdBuffer->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCmdBindPipeline (cmdBuffer->buffer, bindPoint, pipeline->pipeline); + dfunc->vkCmdBindPipeline (*cmdBuffer->buffer, bindPoint, + pipeline->pipeline); } From 559bd2e636778e0721212a730285972bb0a70e42 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Feb 2020 22:45:27 +0900 Subject: [PATCH 0307/3664] Create command pool and frame timing fences Nothing is actually done yet, so the reported fps is around 172k (yes, k), but startup and shutdown seems to be clean (yay validation layers). --- include/vid_vulkan.h | 11 +++ libs/video/renderer/vid_render_vulkan.c | 114 +++++++++++++++++------- 2 files changed, 92 insertions(+), 33 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 9cfb3ad8a..cd1964ff7 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -6,6 +6,13 @@ #endif #include +typedef struct vulkan_frameset_s { + int curFrame; // index into fences + int curImage; // index into cmdBuffers and swapchain images + struct qfv_fenceset_s *fences; + struct qfv_cmdbufferset_s *cmdBuffers; +} vulkan_frameset_t; + typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); void (*unload_vulkan) (struct vulkan_ctx_s *ctx); @@ -23,6 +30,10 @@ typedef struct vulkan_ctx_s { struct qfv_device_s *device; struct qfv_swapchain_s *swapchain; VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain + + struct qfv_cmdpool_s *cmdpool; + vulkan_frameset_t frameset; + #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 7fce05272..0699ced5c 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -28,8 +28,10 @@ # include "config.h" #endif -#define NH_DEFINE -#include "vulkan/namehack.h" +#include + +//#define NH_DEFINE +//#include "vulkan/namehack.h" #include "QF/sys.h" @@ -37,6 +39,7 @@ #include "QF/plugin/vid_render.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/swapchain.h" @@ -53,8 +56,43 @@ static vulkan_ctx_t *vulkan_ctx; static void vulkan_R_Init (void) { - if (vulkan_ctx) - Sys_Quit (); + Vulkan_CreateSwapchain (vulkan_ctx); + Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, + vulkan_ctx->swapchain->numImages); + for (int32_t i = 0; i < vulkan_ctx->swapchain->numImages; i++) { + Sys_Printf (" %p", vulkan_ctx->swapchain->images[i]); + } + Sys_Printf ("\n"); +} + +static void +vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) +{ + static int count = 0; + static double startTime; + + if (++count >= 100) { + double currenTime = Sys_DoubleTime (); + double time = currenTime - startTime; + startTime = currenTime; + printf ("%d frames in %g s: %g fps \r", count, time, count / time); + fflush (stdout); + count = 0; + } +} + +static qpic_t * +vulkan_Draw_CachePic (const char *path, qboolean alpha) +{ + return 0; +} + +static qpic_t qpic = { 1, 1, {0} }; + +static qpic_t * +vulkan_Draw_MakePic (int width, int height, const byte *data) +{ + return &qpic; } static vid_model_funcs_t model_funcs = { @@ -84,29 +122,29 @@ static vid_model_funcs_t model_funcs = { }; vid_render_funcs_t vulkan_vid_render_funcs = { - vulkan_Draw_Init, - vulkan_Draw_Character, - vulkan_Draw_String, - vulkan_Draw_nString, - vulkan_Draw_AltString, - vulkan_Draw_ConsoleBackground, - vulkan_Draw_Crosshair, - vulkan_Draw_CrosshairAt, - vulkan_Draw_TileClear, - vulkan_Draw_Fill, - vulkan_Draw_TextBox, - vulkan_Draw_FadeScreen, - vulkan_Draw_BlendScreen, + 0,//vulkan_Draw_Init, + 0,//vulkan_Draw_Character, + 0,//vulkan_Draw_String, + 0,//vulkan_Draw_nString, + 0,//vulkan_Draw_AltString, + 0,//vulkan_Draw_ConsoleBackground, + 0,//vulkan_Draw_Crosshair, + 0,//vulkan_Draw_CrosshairAt, + 0,//vulkan_Draw_TileClear, + 0,//vulkan_Draw_Fill, + 0,//vulkan_Draw_TextBox, + 0,//vulkan_Draw_FadeScreen, + 0,//vulkan_Draw_BlendScreen, vulkan_Draw_CachePic, - vulkan_Draw_UncachePic, + 0,//vulkan_Draw_UncachePic, vulkan_Draw_MakePic, - vulkan_Draw_DestroyPic, - vulkan_Draw_PicFromWad, - vulkan_Draw_Pic, - vulkan_Draw_Picf, - vulkan_Draw_SubPic, + 0,//vulkan_Draw_DestroyPic, + 0,//vulkan_Draw_PicFromWad, + 0,//vulkan_Draw_Pic, + 0,//vulkan_Draw_Picf, + 0,//vulkan_Draw_SubPic, - 0,//vulkan_SCR_UpdateScreen, + vulkan_SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, SCR_DrawPause, @@ -152,8 +190,13 @@ vulkan_vid_render_choose_visual (void) { Vulkan_CreateDevice (vulkan_ctx); vulkan_ctx->choose_visual (vulkan_ctx); - Sys_Printf ("vk choose visual %p %p\n", vulkan_ctx->device->dev, - vulkan_ctx->device->queue.queue); + vulkan_ctx->cmdpool = QFV_CreateCommandPool (vulkan_ctx->device, + vulkan_ctx->device->queue.queueFamily, + 0, 0); + Sys_Printf ("vk choose visual %p %p %d %p\n", vulkan_ctx->device->dev, + vulkan_ctx->device->queue.queue, + vulkan_ctx->device->queue.queueFamily, + vulkan_ctx->cmdpool->cmdpool); } static void @@ -161,14 +204,14 @@ vulkan_vid_render_create_context (void) { vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); - Sys_Printf ("vk create context %p\n", vulkan_ctx->surface); - Vulkan_CreateSwapchain (vulkan_ctx); - Sys_Printf ("%p %d", vulkan_ctx->swapchain->swapchain, - vulkan_ctx->swapchain->numImages); - for (int32_t i = 0; i < vulkan_ctx->swapchain->numImages; i++) { - Sys_Printf (" %p", vulkan_ctx->swapchain->images[i]); + vulkan_ctx->frameset.curFrame = 0; + vulkan_ctx->frameset.curImage = -1; // not acquired yet + qfv_fence_t **fences = alloca (2 * sizeof (*fences)); + for (int i = 0; i < 2; i++) { + fences[i]= QFV_CreateFence (vulkan_ctx->device, 1); } - Sys_Printf ("\n"); + vulkan_ctx->frameset.fences = QFV_CreateFenceSet (fences, 2); + Sys_Printf ("vk create context %p\n", vulkan_ctx->surface); } static void @@ -190,6 +233,11 @@ vulkan_vid_render_init (void) static void vulkan_vid_render_shutdown (void) { + for (int i = 0; i < vulkan_ctx->frameset.fences->numFences; i++) { + QFV_DestroyFence (vulkan_ctx->frameset.fences->fences[i]); + } + QFV_DestroyFenceSet (vulkan_ctx->frameset.fences); + QFV_DestroyCommandPool (vulkan_ctx->cmdpool); Vulkan_Shutdown_Common (vulkan_ctx); } From 4b152a4492b500dc06a7c85c48b3cf4d1f61c464 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 00:10:32 +0900 Subject: [PATCH 0308/3664] Rework semaphore sets --- include/QF/Vulkan/command.h | 3 ++- libs/video/renderer/vulkan/command.c | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 14eb625ac..7ef36a7f4 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -26,7 +26,8 @@ typedef struct qfv_semaphore_s { typedef struct qfv_semaphoreset_s { struct qfv_device_s *device; - VkSemaphore *semaphores; + qfv_semaphore_t **semaphores; + VkSemaphore *vkSemaphores; VkPipelineStageFlags *stages; int numSemaphores; } qfv_semaphoreset_t; diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 9f581ded6..f4cf4bc14 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -237,17 +237,23 @@ QFV_CreateSemaphoreSet (qfv_semaphore_t **semaphores, int numSemaphores) qfv_device_t *device = semaphores[0]->device; qfv_semaphoreset_t *semaphoreset; semaphoreset = calloc (1, sizeof (*semaphoreset) + + sizeof (qfv_semaphore_t *) * numSemaphores + sizeof (VkSemaphore) * numSemaphores + sizeof (VkPipelineStageFlags) * numSemaphores); semaphoreset->device = device; - semaphoreset->semaphores = (VkSemaphore *) (semaphoreset + 1); + semaphoreset->vkSemaphores = (VkSemaphore *) (semaphoreset + 1); semaphoreset->stages = (VkPipelineStageFlags *) - &semaphoreset->semaphores[numSemaphores]; + &semaphoreset->vkSemaphores[numSemaphores]; + semaphoreset->semaphores = (qfv_semaphore_t **) (semaphoreset->stages + + numSemaphores); semaphoreset->numSemaphores = numSemaphores; - for (int i = 0; i < numSemaphores; i++) { - semaphoreset->semaphores[i] = semaphores[i]->semaphore; + if (semaphores) { + for (int i = 0; i < numSemaphores; i++) { + semaphoreset->semaphores[i] = semaphores[i]; + semaphoreset->vkSemaphores[i] = semaphores[i]->semaphore; + } } return semaphoreset; } @@ -379,10 +385,10 @@ QFV_QueueSubmit (qfv_queue_t *queue, qfv_semaphoreset_t *waitSemaphores, VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, waitSemaphores->numSemaphores, - waitSemaphores->semaphores, waitSemaphores->stages, + waitSemaphores->vkSemaphores, waitSemaphores->stages, buffers->numBuffers, buffers->vkBuffers, signalSemaphores->numSemaphores, - signalSemaphores->semaphores + signalSemaphores->vkSemaphores }; //FIXME multi-batch return dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, From ce72135e70776d9efe82838f87b5de97049991af Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 00:10:59 +0900 Subject: [PATCH 0309/3664] Fix incorrect init of command buffer set --- libs/video/renderer/vulkan/command.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index f4cf4bc14..fa671fa5d 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -137,12 +137,15 @@ QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) cmdbufferset->buffers = (qfv_cmdbuffer_t **) (cmdbufferset + 1); cmdbufferset->vkBuffers = (VkCommandBuffer *) (cmdbufferset->buffers + count); + qfv_cmdbuffer_t *buffer = (qfv_cmdbuffer_t *) (cmdbufferset->vkBuffers + + count); cmdbufferset->cmdpool = pool->cmdpool; cmdbufferset->numBuffers = count; dfunc->vkAllocateCommandBuffers (dev, &allocInfo, cmdbufferset->vkBuffers); for (int i = 0; i < count; i++) { - cmdbufferset->buffers[i]->device = device; - cmdbufferset->buffers[i]->buffer = &cmdbufferset->vkBuffers[i]; + buffer->device = device; + buffer->buffer = &cmdbufferset->vkBuffers[i]; + cmdbufferset->buffers[i] = buffer++; } return cmdbufferset; } From 916e57de3741a7baf9706e74e608c968dbee1491 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 00:50:39 +0900 Subject: [PATCH 0310/3664] Get the swapchain image switching sort of working The render pass isn't set up yet, so the validation layer is having a fit, but cycling through the swapchain images does seem to be working. --- include/vid_vulkan.h | 3 +- libs/video/renderer/vid_render_vulkan.c | 59 +++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index cd1964ff7..5b9a31daf 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -8,9 +8,10 @@ typedef struct vulkan_frameset_s { int curFrame; // index into fences - int curImage; // index into cmdBuffers and swapchain images struct qfv_fenceset_s *fences; struct qfv_cmdbufferset_s *cmdBuffers; + struct qfv_semaphoreset_s *imageSemaphores; + struct qfv_semaphoreset_s *renderDoneSemaphores; } vulkan_frameset_t; typedef struct vulkan_ctx_s { diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 0699ced5c..de0917310 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -56,7 +56,15 @@ static vulkan_ctx_t *vulkan_ctx; static void vulkan_R_Init (void) { + qfv_cmdbufferset_t *cmdBuffers; Vulkan_CreateSwapchain (vulkan_ctx); + cmdBuffers = QFV_AllocateCommandBuffers (vulkan_ctx->cmdpool, 0, + vulkan_ctx->swapchain->numImages); + vulkan_ctx->frameset.cmdBuffers = cmdBuffers; + for (int i = 0; i < cmdBuffers->numBuffers; i++) { + QFV_BeginCommandBuffer (cmdBuffers->buffers[i], 0, 0, 0, 0); + QFV_EndCommandBuffer (cmdBuffers->buffers[i]); + } Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, vulkan_ctx->swapchain->numImages); for (int32_t i = 0; i < vulkan_ctx->swapchain->numImages; i++) { @@ -70,6 +78,40 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) { static int count = 0; static double startTime; + uint32_t imageIndex = 0; + qfv_devfuncs_t *dfunc = vulkan_ctx->device->funcs; + qfv_queue_t *queue = &vulkan_ctx->device->queue; + vulkan_frameset_t *frameset = &vulkan_ctx->frameset; + + QFV_WaitForFence (frameset->fences->fences[frameset->curFrame], + 2000000000); + QFV_AcquireNextImage (vulkan_ctx->swapchain, + frameset->imageSemaphores->semaphores[frameset->curFrame], + 0, &imageIndex); + + VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + 1, + &frameset->imageSemaphores->vkSemaphores[frameset->curFrame], + &waitStage, + 1, &frameset->cmdBuffers->vkBuffers[imageIndex], + 1, &frameset->renderDoneSemaphores->vkSemaphores[frameset->curFrame], + }; + QFV_ResetFence (frameset->fences->fences[frameset->curFrame]); + dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, + frameset->fences->vkFences[frameset->curFrame]); + + VkPresentInfoKHR presentInfo = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, + 1, &frameset->renderDoneSemaphores->vkSemaphores[frameset->curFrame], + 1, &vulkan_ctx->swapchain->swapchain, &imageIndex, + 0 + }; + dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); + + frameset->curFrame++; + frameset->curFrame %= frameset->fences->numFences; if (++count >= 100) { double currenTime = Sys_DoubleTime (); @@ -205,12 +247,19 @@ vulkan_vid_render_create_context (void) vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); vulkan_ctx->frameset.curFrame = 0; - vulkan_ctx->frameset.curImage = -1; // not acquired yet qfv_fence_t **fences = alloca (2 * sizeof (*fences)); + qfv_semaphore_t **imageSems = alloca (2 * sizeof (*imageSems)); + qfv_semaphore_t **renderDoneSems = alloca (2 * sizeof (*renderDoneSems)); for (int i = 0; i < 2; i++) { fences[i]= QFV_CreateFence (vulkan_ctx->device, 1); + imageSems[i] = QFV_CreateSemaphore (vulkan_ctx->device); + renderDoneSems[i] = QFV_CreateSemaphore (vulkan_ctx->device); } vulkan_ctx->frameset.fences = QFV_CreateFenceSet (fences, 2); + vulkan_ctx->frameset.imageSemaphores + = QFV_CreateSemaphoreSet (imageSems, 2); + vulkan_ctx->frameset.renderDoneSemaphores + = QFV_CreateSemaphoreSet (renderDoneSems, 2); Sys_Printf ("vk create context %p\n", vulkan_ctx->surface); } @@ -233,8 +282,12 @@ vulkan_vid_render_init (void) static void vulkan_vid_render_shutdown (void) { - for (int i = 0; i < vulkan_ctx->frameset.fences->numFences; i++) { - QFV_DestroyFence (vulkan_ctx->frameset.fences->fences[i]); + QFV_DeviceWaitIdle (vulkan_ctx->device); + vulkan_frameset_t *frameset = &vulkan_ctx->frameset; + for (int i = 0; i < frameset->fences->numFences; i++) { + QFV_DestroyFence (frameset->fences->fences[i]); + QFV_DestroySemaphore (frameset->imageSemaphores->semaphores[i]); + QFV_DestroySemaphore (frameset->renderDoneSemaphores->semaphores[i]); } QFV_DestroyFenceSet (vulkan_ctx->frameset.fences); QFV_DestroyCommandPool (vulkan_ctx->cmdpool); From e37aba364a6bd71b5252480f6f7663c5457daea5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 12:58:23 +0900 Subject: [PATCH 0311/3664] Correct an apparent typo Black makes much more sense than Slack, especially if the text is from a quake mod (no idea where, though). --- libs/util/test/test-plist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/test/test-plist.c b/libs/util/test/test-plist.c index 20ab1e94e..0335493f2 100644 --- a/libs/util/test/test-plist.c +++ b/libs/util/test/test-plist.c @@ -11,7 +11,7 @@ static const char *test_strings[] = { "of the Shadow cult.\n\n" "For years the Shadow Gate existed in\n" "obscurity but after the cult discovered\n" - "the \3023\354\341\343\353\240\307\341\364\345 in the caves below\n" + "the \302\354\341\343\353\240\307\341\364\345 in the caves below\n" "the empire took notice.\n" "A batallion of Imperial Knights were\n" "sent to the gate to destroy the cult\n" From 0cb04dc49028990091a083332a016394caa556b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 16:17:21 +0900 Subject: [PATCH 0312/3664] Add a set of macros for dynamic arrays Includes docs and test cases. --- include/QF/darray.h | 301 +++++++++++++++++++++++++++++++++++ libs/util/test/Makefile.am | 8 +- libs/util/test/test-darray.c | 213 +++++++++++++++++++++++++ 3 files changed, 520 insertions(+), 2 deletions(-) create mode 100644 include/QF/darray.h create mode 100644 libs/util/test/test-darray.c diff --git a/include/QF/darray.h b/include/QF/darray.h new file mode 100644 index 000000000..88792715f --- /dev/null +++ b/include/QF/darray.h @@ -0,0 +1,301 @@ +/* + darray.h + + Dynamic arrays + + Copyright (C) 2020 Bill Currie + + Author: Bill Currie + Date: 2020/02/17 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __pr_type_h +#define __pr_type_h + +/** \defgroup darray Dynamic Arrays + \ingroup utils + + Dynamic array container object +*/ +///@{ + +/** The structure defs for a dynamic array with elements of the given type. + + This is just the defs of a struct delcaration: it is useless on its own. + The intended usage is something like: + + typedef struct dynamic_array_s DARRAY_TYPE(int) dynamic_array_t; + + This allows full flexibility in just how the actual type is used. + + The \a size field is the number of elements currently in the array, and + the \a maxSize field is the number of elements the array can hold without + being resized. + + The \a grow field specifies the number of elements by which \a maxSize is + to grow when the array needs to be resized. Setting this to 0 prevents + resizing and any attempt to do so is a fatal error. + + \param ele_type The type to use for the element array, which is accessed + by the \a a field. + \hideinitializer +*/ +#define DARRAY_TYPE(ele_type) \ + { \ + size_t size; \ + size_t maxSize; \ + size_t grow; \ + ele_type *a; \ + } + +/** Clear the array. + + If the array can grow, its backing will be freed and maxSize and a reset, + otherwise maxSize and a are left untouched. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \hideinitializer +*/ +#define DARRAY_CLEAR(array) \ + do { \ + __auto_type ar = (array); \ + free (ar->a); \ + ar->size = 0; \ + if (ar->grow) { \ + ar->maxSize = 0; \ + ar->a = 0; \ + } \ + } while (0) + +/** Set the size of the array. + + If the new size is greater than maxSize, and the array can grow (grow is + non-zero), then maxSize will be increased to the smallest multiple of grow + greater than or equal to size (ie, maxSize >= size, maxSize % grow == 0). + + Attempting to increase maxSize on an array that cannot grow is an error: + it is assumed that the array struct does not own the backing memory. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param newSize The new size of the array: newly opened slots are + uninitialized, but old slots retain their values. + \hideinitializer +*/ +#define DARRAY_RESIZE(array, newSize) \ + do { \ + __auto_type ar = (array); \ + size_t ns = (newSize); \ + if (__builtin_expect (ns > ar->maxSize, 0)) { \ + if (__builtin_expect (!ar->grow, 0)) { \ + Sys_Error ("Attempt to grow fixed-size darray: %s:%d", \ + __FILE__, __LINE__); \ + } \ + ar->maxSize = ar->grow * ((ns + ar->grow - 1) / ar->grow); \ + ar->a = realloc (ar->a, ar->maxSize * sizeof (*ar->a)); \ + if (__builtin_expect (!ar->a, 0)) { \ + Sys_Error ("failed to realloc darray: %s:%d", \ + __FILE__, __LINE__); \ + } \ + } \ + ar->size = ns; \ + } while (0) + +/** Append a value to the end of the array. + + The array is grown by one and the value written to the newly opened slot. + + If the new array size is greater than maxSize and the array can be grown, + the array backing will be resized to the next multiple of grow. + + Attempting to grow an array that cannot grow is an error: it is assumed + that the array struct does not own the backing memory. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param value The value to be appended to the array. Must be of a type + compatible with that used for creating the array struct. + \return The appended value: can be assigned to another compatible + value. + \hideinitializer +*/ +#define DARRAY_APPEND(array, value) \ + ({ \ + __auto_type ar = (array); \ + __auto_type ob = (value); \ + size_t sz = ar->size; \ + DARRAY_RESIZE (ar, ar->size + 1); \ + ar->a[sz] = ob; \ + }) + +/** Open a hole in the array for bulk copying of data. + + The array is grown by the requested size, opening a hole at the specified + index. Values beyond the index are copied to just after the newly opened + hole. + + If the new array size is greater than maxSize and the array can be grown, + the array backing will be resized to the next multiple of grow. + + Attempting to grow an array that cannot grow is an error: it is assumed + that the array struct does not own the backing memory. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param index The index at which the hole will begin. + \param space The sized of the hole to be opened, in array elements. + \return The *address* of the newly opened hole: can be passed to + memcpy and friends. + + memcpy (DARRAY_OPEN_AT(array, index, size), data, + size * sizeof (*data)); + \hideinitializer +*/ +#define DARRAY_OPEN_AT(array, index, space) \ + ({ \ + __auto_type ar = (array); \ + size_t po = (index); \ + size_t sp = (space); \ + if (__builtin_expect (po > ar->size, 0)) { \ + Sys_Error ("Attempt to insert elements outside darray: " \ + "%s:%d", __FILE__, __LINE__); \ + } \ + DARRAY_RESIZE (ar, ar->size + sp); \ + memmove (&ar->a[po + sp], &ar->a[po], \ + (ar->size - po) * sizeof (*ar->a)); \ + &ar->a[po]; \ + }) + +/** Insert a value into the array at the specified index. + + The array is grown by one at the specified index and the value written + to the newly opened slot. Values beyond the index are copied to just + after the newly opened slot. + + If the new array size is greater than maxSize and the array can be grown, + the array backing will be resized to the next multiple of grow. + + Attempting to grow an array that cannot grow is an error: it is assumed + that the array struct does not own the backing memory. + + Attempting to insert a value beyond one past the end of the array is an + error (inserting at index = size is valid). + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param value The value to be inserted into the array. Must be of a type + compatible with that used for creating the array struct. + \param index The index at which the value will be inserted + \return The inserted value: can be assigned to another compatible + value. + \hideinitializer +*/ +#define DARRAY_INSERT_AT(array, value, index) \ + ({ \ + __auto_type ar = (array); \ + __auto_type ob = (value); \ + *DARRAY_OPEN_AT (ar, index, 1) = ob; \ + }) + +/** Close a segment of an array. + + The values beyond the segment are copied to the beginning of the segment + and the array size reduced by the size of the segment. All but the first + one of the values previously in the segment are lost and gone forever. + + Attempting to close a segment that extends outside the array is an error. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param index The index of the beginning of the segment. + \param count The number of values in the segment. + \return The single value at the beginning of the segment: can be + assigned to another compatible value. + \hideinitializer +*/ +#define DARRAY_CLOSE_AT(array, index, count) \ + ({ \ + __auto_type ar = (array); \ + size_t po = (index); \ + size_t co = (count); \ + if (__builtin_expect (po + co > ar->size \ + || po >= ar->size, 0)) { \ + Sys_Error ("Attempt to remove elements outside darray: " \ + "%s:%d", __FILE__, __LINE__); \ + } \ + __auto_type ob = ar->a[po]; \ + memmove (&ar->a[po], &ar->a[po + co], \ + (ar->size - po - co) * sizeof (ob)); \ + ar->size -= co; \ + ob; \ + }) + +/** Remove a value from an array at the specified index. + + The values beyond the index are moved down to fill the hole left by the + single value and the array size reduced by one. + + Attempting to remove a value from beyond the array is an error. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param index The index of the value to be removed. + \return The removed value: can be assigned to another compatible + value. + \hideinitializer +*/ +#define DARRAY_REMOVE_AT(array, index) \ + ({ \ + __auto_type ar = (array); \ + DARRAY_CLOSE_AT (ar, index, 1); \ + }) + +/** Remove (pop) a value from the end of an array. + + The size of the array size reduced by one. + + Attempting to remove a value from an empty array is an error. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \return The removed value: can be assigned to another compatible + value. + \hideinitializer +*/ +#define DARRAY_REMOVE(array) \ + ({ \ + __auto_type ar = (array); \ + DARRAY_CLOSE_AT (ar, ar->size - 1, 1); \ + }) + +///@} + +#endif//__pr_type_h diff --git a/libs/util/test/Makefile.am b/libs/util/test/Makefile.am index a7bdb5d4e..f6dd4115a 100644 --- a/libs/util/test/Makefile.am +++ b/libs/util/test/Makefile.am @@ -3,8 +3,8 @@ AUTOMAKE_OPTIONS= foreign AM_CPPFLAGS= -I$(top_srcdir)/include check_PROGRAMS= \ - test-bary test-cs test-dq test-half test-mat3 test-mat4 test-plist \ - test-qfs test-quat test-seb test-seg test-set test-vrect + test-bary test-cs test-darray test-dq test-half test-mat3 test-mat4 \ + test-plist test-qfs test-quat test-seb test-seg test-set test-vrect test_bary_SOURCES=test-bary.c test_bary_LDADD=$(top_builddir)/libs/util/libQFutil.la @@ -14,6 +14,10 @@ test_cs_SOURCES=test-cs.c test_cs_LDADD=$(top_builddir)/libs/util/libQFutil.la test_cs_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la +test_darray_SOURCES=test-darray.c +test_darray_LDADD=$(top_builddir)/libs/util/libQFutil.la +test_darray_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la + test_dq_SOURCES=test-dq.c test_dq_LDADD=$(top_builddir)/libs/util/libQFutil.la test_dq_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la diff --git a/libs/util/test/test-darray.c b/libs/util/test/test-darray.c new file mode 100644 index 000000000..59dbad0ab --- /dev/null +++ b/libs/util/test/test-darray.c @@ -0,0 +1,213 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#define remove remove_renamed +#include +#include +#include + +#include "QF/darray.h" +#include "QF/sys.h" +#undef remove + +typedef int (*test_func) (int a, int b); +typedef struct intarray_s DARRAY_TYPE(int) intarray_t; + +intarray_t intarray = {0, 0, 16, 0}; + +static int +append (int val, int b) +{ + return DARRAY_APPEND (&intarray, val); +} + +static int +check_size (int a, int b) +{ + return intarray.size; +} + +static int +check_maxSize (int a, int b) +{ + return intarray.maxSize; +} + +static int +check_grow (int a, int b) +{ + return intarray.grow; +} + +static int +check_maxSizeGrowth (int a, int b) +{ + return intarray.maxSize % intarray.grow; +} + +static int +check_array (int a, int b) +{ + return !!intarray.a; +} + +static int +check_value (int index, int b) +{ + if ((size_t) index >= intarray.size) { + Sys_Error ("indexing beyond array"); + } + return intarray.a[index]; +} + +static int +insert_at (int val, int pos) +{ + return DARRAY_INSERT_AT (&intarray, val, pos); +} + +static int +open_at (int pos, int size) +{ + return DARRAY_OPEN_AT (&intarray, pos, size) - intarray.a; +} + +static const char text[] = "Aloy is an awesome huntress."; +static int +open_at2 (int pos, int size) +{ + memcpy(DARRAY_OPEN_AT (&intarray, pos, size), text, size * sizeof (int)); + return strcmp((char*) (intarray.a + pos), text); +} + +static int +remove_at (int pos, int b) +{ + return DARRAY_REMOVE_AT (&intarray, pos); +} + +static int +remove (int pos, int b) +{ + return DARRAY_REMOVE (&intarray); +} + +static int +close_at (int pos, int size) +{ + return DARRAY_CLOSE_AT (&intarray, pos, size); +} + +static int +clear (int a, int b) +{ + DARRAY_CLEAR (&intarray); + return 0; +} + +static int +resize (int size, int b) +{ + DARRAY_RESIZE (&intarray, size); + return 0; +} + +struct { + test_func test; + int param1, param2; + int test_expect; +} tests[] = { + {check_size, 0, 0, 0}, // confirm array empty but can grow + {check_maxSize, 0, 0, 0}, + {check_grow, 0, 0, 16}, + {check_array, 0, 0, 0}, + {append, 5, 0, 5}, // test first append to emtpty array + {check_size, 0, 0, 1}, + {check_maxSizeGrowth, 0, 0, 0}, + {check_maxSize, 0, 0, 16}, + {check_array, 0, 0, 1}, + {check_value, 0, 0, 5}, + {append, 42, 0, 42}, // test a second append + {check_size, 0, 0, 2}, + {check_maxSize, 0, 0, 16}, + {check_value, 0, 0, 5}, + {check_value, 1, 0, 42}, + {insert_at, 69, 1, 69}, // test insertions + {insert_at, 96, 0, 96}, + {check_size, 0, 0, 4}, + {check_maxSize, 0, 0, 16}, + {check_value, 0, 0, 96}, + {check_value, 1, 0, 5}, + {check_value, 2, 0, 69}, + {check_value, 3, 0, 42}, + {open_at, 2, 14, 2}, // test opening a large hole + {check_maxSizeGrowth, 0, 0, 0}, + {check_maxSize, 0, 0, 32}, + {check_size, 0, 0, 18}, + {check_value, 0, 0, 96}, + {check_value, 1, 0, 5}, + {check_value, 16, 0, 69}, + {check_value, 17, 0, 42}, + {close_at, 1, 15, 5}, // test block removal + {check_maxSize, 0, 0, 32}, + {check_size, 0, 0, 3}, + {check_value, 0, 0, 96}, + {check_value, 1, 0, 69}, + {check_value, 2, 0, 42}, + {remove, 0, 0, 42}, // test "pop" + {check_maxSize, 0, 0, 32}, + {check_size, 0, 0, 2}, + {check_value, 0, 0, 96}, + {check_value, 1, 0, 69}, + {remove_at, 0, 0, 96}, // test remove at + {check_maxSize, 0, 0, 32}, + {check_size, 0, 0, 1}, + {check_value, 0, 0, 69}, + {insert_at, 71, 1, 71}, // test insertion at end + {resize, 48, 0, 0}, // test resize bigger + {check_maxSizeGrowth, 0, 0, 0}, + {check_maxSize, 0, 0, 48}, + {check_size, 0, 0, 48}, + {check_value, 0, 0, 69}, + {check_value, 1, 0, 71}, + {resize, 24, 0, 0}, // test resize smaller + {check_maxSizeGrowth, 0, 0, 0}, + {check_maxSize, 0, 0, 48}, + {check_size, 0, 0, 24}, + {check_value, 0, 0, 69}, + {check_value, 1, 0, 71}, + {open_at2, 1, (sizeof (text) + sizeof (int) - 1) / sizeof (int), 0}, + {check_value, 0, 0, 69}, + {check_value, 1, 0, 0x796f6c41}, + {check_value, 9, 0, 71}, + {clear, 0, 0, 0}, // test clearing + {check_size, 0, 0, 0}, + {check_maxSize, 0, 0, 0}, + {check_array, 0, 0, 0}, +}; +#define num_tests (sizeof (tests) / sizeof (tests[0])) +int test_start_line = __LINE__ - num_tests - 2; + +int +main (int argc, const char **argv) +{ + int res = 0; + + size_t i; + + for (i = 0; i < num_tests; i++) { + if (tests[i].test) { + int test_res; + test_res = tests[i].test (tests[i].param1, tests[i].param2); + if (test_res != tests[i].test_expect) { + res |= 1; + printf ("test %d (line %d) failed\n", (int) i, + (int) i + test_start_line); + printf ("expect: %d\n", tests[i].test_expect); + printf ("got : %d\n", test_res); + continue; + } + } + } + return res; +} From cb70dc7212e176929d43efab5b37e791aaa15ef0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 16:40:12 +0900 Subject: [PATCH 0313/3664] Fix incorrect include protection --- include/QF/Makefile.am | 2 +- include/QF/darray.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am index 8bf956359..aa9eaf1f8 100644 --- a/include/QF/Makefile.am +++ b/include/QF/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = foreign pkgincludedir = $(includedir)/QF nobase_pkginclude_HEADERS = \ alloc.h bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \ - console.h crc.h csqc.h cvar.h dstring.h draw.h gib.h hash.h hl.h \ + console.h crc.h csqc.h cvar.h darray.h dstring.h draw.h gib.h hash.h hl.h \ idparse.h image.h in_event.h info.h input.h iqm.h joystick.h keys.h \ link.h llist.h locs.h mathlib.h mdfour.h mersenne.h model.h modelgen.h \ msg.h object.h pak.h pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h \ diff --git a/include/QF/darray.h b/include/QF/darray.h index 88792715f..0287f958f 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -28,8 +28,8 @@ */ -#ifndef __pr_type_h -#define __pr_type_h +#ifndef __darray_h +#define __darray_h /** \defgroup darray Dynamic Arrays \ingroup utils @@ -298,4 +298,4 @@ ///@} -#endif//__pr_type_h +#endif//__darray_h From 65890dd2fb12e6751bb747221364ed9234f6b543 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 20:27:43 +0900 Subject: [PATCH 0314/3664] Add a fixed-array allocator Turned out to be very convenient. --- include/QF/darray.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/QF/darray.h b/include/QF/darray.h index 0287f958f..7a4484575 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -67,6 +67,27 @@ ele_type *a; \ } +/** Allocate a fixed-size array using the given allocator + + The allocated array is initilized to be ungrowable, and with both size + and maxSize set to the given size. + + \param array_type Expression acceptable by typeof for determining the + type of the array. + \param array_size The size of the array. + \param alloc Allocator compatible with malloc (eg, alloca). +*/ +#define DARRAY_ALLOCFIXED(array_type, array_size, alloc) \ + ({ \ + __auto_type s = (array_size); \ + typeof (array_type) *ar = alloc (sizeof(*ar) \ + + s * sizeof (*ar->a)); \ + ar->size = ar->maxSize = s; \ + ar->grow = 0; \ + ar->a = (typeof (ar->a)) (ar + 1); \ + ar; \ + }) + /** Clear the array. If the array can grow, its backing will be freed and maxSize and a reset, From 94565c23820960d106c33bff4d25161596ac9470 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 20:29:35 +0900 Subject: [PATCH 0315/3664] Rework much of the Vulkan array handling So much for all those little wrappers hiding the device. Some survived, but mostly just the bigger things like device, swapchain, etc. --- include/QF/Vulkan/buffer.h | 62 ++-- include/QF/Vulkan/command.h | 125 +------- include/QF/Vulkan/device.h | 5 + include/QF/Vulkan/funclist.h | 1 + include/QF/Vulkan/image.h | 62 ++-- include/QF/Vulkan/instance.h | 2 + include/QF/Vulkan/memory.h | 19 +- include/QF/Vulkan/renderpass.h | 2 +- include/QF/Vulkan/swapchain.h | 10 +- include/vid_vulkan.h | 2 +- libs/video/renderer/vid_render_vulkan.c | 83 ++--- libs/video/renderer/vulkan/buffer.c | 101 ++---- libs/video/renderer/vulkan/command.c | 410 ++---------------------- libs/video/renderer/vulkan/device.c | 21 ++ libs/video/renderer/vulkan/image.c | 118 ++----- libs/video/renderer/vulkan/instance.c | 2 + libs/video/renderer/vulkan/memory.c | 42 +-- libs/video/renderer/vulkan/renderpass.c | 10 +- libs/video/renderer/vulkan/swapchain.c | 42 ++- 19 files changed, 282 insertions(+), 837 deletions(-) diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h index ef11ae8b7..9346d0466 100644 --- a/include/QF/Vulkan/buffer.h +++ b/include/QF/Vulkan/buffer.h @@ -1,57 +1,43 @@ #ifndef __QF_Vulkan_buffer_h #define __QF_Vulkan_buffer_h -typedef struct qfv_buffer_s { - struct qfv_device_s *device; - VkBuffer buffer; -} qfv_buffer_t; +#include "QF/darray.h" typedef struct qfv_buffertransition_s { - qfv_buffer_t *buffer; + VkBuffer buffer; VkAccessFlags srcAccess; VkAccessFlags dstAccess; - uint32_t srcQueueFamily; - uint32_t dstQueueFamily; - VkDeviceSize offset; - VkDeviceSize size; -} qfv_buffertransition_t; - -typedef struct qfv_bufferbarrierset_s { - struct qfv_device_s *device; - uint32_t numBarriers; - VkBufferMemoryBarrier *barriers; -} qfv_bufferbarrierset_t; - -typedef struct qfv_bufferview_s { - struct qfv_device_s *device; - VkBufferView view; - qfv_buffer_t *buffer; - VkFormat format; + uint32_t srcQueueFamily; + uint32_t dstQueueFamily; VkDeviceSize offset; VkDeviceSize size; -} qfv_bufferview_t; +} qfv_buffertransition_t; + +typedef struct qfv_buffertransitionset_s + DARRAY_TYPE (qfv_buffertransition_t) qfv_buffertransitionset_t; +typedef struct qfv_bufferbarrierset_s + DARRAY_TYPE (VkBufferMemoryBarrier) qfv_bufferbarrierset_t; struct qfv_device_s; -qfv_buffer_t *QFV_CreateBuffer (struct qfv_device_s *device, - VkDeviceSize size, - VkBufferUsageFlags usage); +VkBuffer QFV_CreateBuffer (struct qfv_device_s *device, + VkDeviceSize size, + VkBufferUsageFlags usage); -struct qfv_memory_s *QFV_AllocBufferMemory (qfv_buffer_t *buffer, - VkMemoryPropertyFlags properties, - VkDeviceSize size, VkDeviceSize offset); +VkDeviceMemory QFV_AllocBufferMemory (struct qfv_device_s *device, + VkBuffer buffer, + VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset); -int QFV_BindBufferMemory (qfv_buffer_t *buffer, struct qfv_memory_s *memory, +int QFV_BindBufferMemory (struct qfv_device_s *device, + VkBuffer buffer, VkDeviceMemory object, VkDeviceSize offset); qfv_bufferbarrierset_t * -QFV_CreateBufferTransitionSet (qfv_buffertransition_t **transitions, - int numTransitions); +QFV_CreateBufferTransitions (qfv_buffertransition_t *transitions, + int numTransitions); -qfv_bufferview_t *QFV_CreateBufferView (qfv_buffer_t *buffer, VkFormat format, - VkDeviceSize offset, VkDeviceSize size); - -void QFV_DestroyBufferView (qfv_bufferview_t *view); - -void QFV_DestroyBuffer (qfv_buffer_t *buffer); +VkBufferView QFV_CreateBufferView (struct qfv_device_s *device, + VkBuffer buffer, VkFormat format, + VkDeviceSize offset, VkDeviceSize size); #endif//__QF_Vulkan_buffer_h diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 7ef36a7f4..046c8b2b3 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -1,128 +1,33 @@ #ifndef __QF_Vulkan_command_h #define __QF_Vulkan_command_h -typedef struct qfv_cmdpool_s { - struct qfv_device_s *device; - VkCommandPool cmdpool; -} qfv_cmdpool_t; +#include "QF/darray.h" -typedef struct qfv_cmdbuffer_s { - struct qfv_device_s *device; - VkCommandBuffer *buffer; -} qfv_cmdbuffer_t; +typedef struct qfv_cmdbufferset_s + DARRAY_TYPE (VkCommandBuffer) qfv_cmdbufferset_t; -typedef struct qfv_cmdbufferset_s { - struct qfv_device_s *device; - qfv_cmdbuffer_t **buffers; - VkCommandBuffer *vkBuffers; - VkCommandPool cmdpool; - int numBuffers; -} qfv_cmdbufferset_t; +typedef struct qfv_semaphoreset_s + DARRAY_TYPE (VkSemaphore) qfv_semaphoreset_t; -typedef struct qfv_semaphore_s { - struct qfv_device_s *device; - VkSemaphore semaphore; -} qfv_semaphore_t; - -typedef struct qfv_semaphoreset_s { - struct qfv_device_s *device; - qfv_semaphore_t **semaphores; - VkSemaphore *vkSemaphores; - VkPipelineStageFlags *stages; - int numSemaphores; -} qfv_semaphoreset_t; - -typedef struct qfv_fence_s { - struct qfv_device_s *device; - VkFence fence; -} qfv_fence_t; - -typedef struct qfv_fenceset_s { - struct qfv_device_s *device; - qfv_fence_t **fences; - VkFence *vkFences; - int numFences; -} qfv_fenceset_t; +typedef struct qfv_fenceset_s + DARRAY_TYPE (VkFence) qfv_fenceset_t; struct qfv_queue_s; -qfv_cmdpool_t *QFV_CreateCommandPool (struct qfv_device_s *device, +struct qfv_device_s; +VkCommandPool QFV_CreateCommandPool (struct qfv_device_s *device, uint32_t queueFamily, int transient, int reset); -int QFV_ResetCommandPool (qfv_cmdpool_t *pool, int release); -void QFV_DestroyCommandPool (qfv_cmdpool_t *pool); -qfv_cmdbufferset_t *QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, +qfv_cmdbufferset_t *QFV_AllocateCommandBuffers (struct qfv_device_s *device, + VkCommandPool pool, int secondary, int count); -void QFV_FreeCommandBuffers (qfv_cmdbufferset_t *buffer); -int QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, - int rpContinue, int simultaneous, - VkCommandBufferInheritanceInfo *inheritanceInfo); -int QFV_EndCommandBuffer (qfv_cmdbuffer_t *buffer); -int QFV_ResetCommandBuffer (qfv_cmdbuffer_t *buffer, int release); -qfv_semaphore_t *QFV_CreateSemaphore (struct qfv_device_s *device); -qfv_semaphoreset_t *QFV_CreateSemaphoreSet (qfv_semaphore_t **semaphores, - int numSemaphores); -void QFV_DestroySemaphore (qfv_semaphore_t *semaphore); -// NOTE: does not destroy semaphores -void QFV_DestroySemaphoreSet (qfv_semaphoreset_t *semaphores); -qfv_fence_t *QFV_CreateFence (struct qfv_device_s *device, int signaled); -qfv_fenceset_t *QFV_CreateFenceSet (qfv_fence_t **fences, int numFences); -void QFV_DestroyFence (qfv_fence_t *fence); -// NOTE: does not destroy fences -void QFV_DestroyFenceSet (qfv_fenceset_t *fenceset); -int QFV_WaitForFences (qfv_fenceset_t *fenceset, int all, uint64_t timeout); -int QFV_WaitForFence (qfv_fence_t *fence, uint64_t timeout); -int QFV_ResetFences (qfv_fenceset_t *fenceset); -int QFV_ResetFence (qfv_fence_t *fence); +VkSemaphore QFV_CreateSemaphore (struct qfv_device_s *device); +VkFence QFV_CreateFence (struct qfv_device_s *device, int signaled); int QFV_QueueSubmit (struct qfv_queue_s *queue, qfv_semaphoreset_t *waitSemaphores, + VkPipelineStageFlags *stages, qfv_cmdbufferset_t *buffers, - qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence); + qfv_semaphoreset_t *signalSemaphores, VkFence fence); int QFV_QueueWaitIdle (struct qfv_queue_s *queue); -struct qfv_memorybarrierset_s; -struct qfv_bufferbarrierset_s; -struct qfv_imagebarrierset_s; -void QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, - VkPipelineStageFlags srcStageMask, - VkPipelineStageFlags dstStageMask, - VkDependencyFlags dependencyFlags, - struct qfv_memorybarrierset_s *memBarriers, - struct qfv_bufferbarrierset_s *buffBarriers, - struct qfv_imagebarrierset_s *imgBarriers); - -struct qfv_buffer_s; -struct qfv_image_s; -struct qfv_renderpass_s; -struct qfv_framebuffer_s; -void QFV_CmdCopyBuffer (qfv_cmdbuffer_t *cmdBuffer, - struct qfv_buffer_s *src, struct qfv_buffer_s *dst, - VkBufferCopy *regions, uint32_t numRegions); -void QFV_CmdCopyBufferToImage (qfv_cmdbuffer_t *cmdBuffer, - struct qfv_buffer_s *src, - struct qfv_image_s *dst, - VkImageLayout layout, - VkBufferImageCopy *regions, - uint32_t numRegions); -void QFV_CmdCopyImageToBuffer (qfv_cmdbuffer_t *cmdBuffer, - struct qfv_image_s *src, - VkImageLayout layout, - struct qfv_buffer_s *dst, - VkBufferImageCopy *regions, - uint32_t numRegions); -void QFV_CmdBeginRenderPass (qfv_cmdbuffer_t *cmdBuffer, - struct qfv_renderpass_s *renderPass, - struct qfv_framebuffer_s *framebuffer, - VkRect2D renderArea, - uint32_t numClearValues, - VkClearValue *clearValues, - VkSubpassContents subpassContents); -void QFV_CmdNextSubpass (qfv_cmdbuffer_t *cmdBuffer, - VkSubpassContents subpassContents); -void QFV_CmdEndRenderPass (qfv_cmdbuffer_t *cmdBuffer); -struct qfv_pipeline_s; -void QFV_CmdBindPipeline (qfv_cmdbuffer_t *cmdBuffer, - VkPipelineBindPoint bindPoint, - struct qfv_pipeline_s *pipeline); - #endif//__QF_Vulkan_command_h diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h index c05b2ba7e..2ebc7b1d9 100644 --- a/include/QF/Vulkan/device.h +++ b/include/QF/Vulkan/device.h @@ -31,4 +31,9 @@ qfv_device_t *QFV_CreateDevice (struct vulkan_ctx_s *ctx, void QFV_DestroyDevice (qfv_device_t *device); int QFV_DeviceWaitIdle (qfv_device_t *device); +VkFormat QFV_FindSupportedFormat (qfv_device_t *device, VkImageTiling tiling, + VkFormatFeatureFlags features, + int numCandidates, + const VkFormat *candidates); + #endif//__QF_Vulkan_device_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 5bacf29eb..426b0fa62 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -31,6 +31,7 @@ INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceLayerProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceExtensionProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFormatProperties) #undef INSTANCE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 4258fe2e0..8db6ee632 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -1,13 +1,13 @@ #ifndef __QF_Vulkan_image_h #define __QF_Vulkan_image_h -typedef struct qfv_image_s { - struct qfv_device_s *device; - VkImage image; -} qfv_image_t; +#include "QF/darray.h" + +typedef struct qfv_imageset_s DARRAY_TYPE (VkImage) qfv_imageset_t; +typedef struct qfv_imageviewset_s DARRAY_TYPE (VkImageView) qfv_imageviewset_t; typedef struct qfv_imagetransition_s { - qfv_image_t *image; + VkImage image; VkAccessFlags srcAccess; VkAccessFlags dstAccess; VkImageLayout oldLayout; @@ -17,48 +17,32 @@ typedef struct qfv_imagetransition_s { VkImageAspectFlags aspect; } qfv_imagetransition_t; -typedef struct qfv_imagebarrierset_s { - struct qfv_device_s *device; - uint32_t numBarriers; - VkImageMemoryBarrier *barriers; -} qfv_imagebarrierset_t; - -typedef struct qfv_imageview_s { - struct qfv_device_s *device; - VkImageView view; - qfv_image_t *image; - VkImageViewType type; - VkFormat format; - VkImageAspectFlags aspect; -} qfv_imageview_t; +typedef struct qfv_imagetransitionset_s + DARRAY_TYPE (qfv_imagetransition_t) qfv_imagetransitionset_t; +typedef struct qfv_imagebarrierset_s + DARRAY_TYPE (VkImageMemoryBarrier) qfv_imagebarrierset_t; struct qfv_device_s; -qfv_image_t *QFV_CreateImage (struct qfv_device_s *device, int cubemap, - VkImageType type, - VkFormat format, - VkExtent3D size, - uint32_t num_mipmaps, - uint32_t num_layers, - VkSampleCountFlagBits samples, - VkImageUsageFlags usage_scenarios); +VkImage QFV_CreateImage (struct qfv_device_s *device, int cubemap, + VkImageType type, + VkFormat format, + VkExtent3D size, + uint32_t num_mipmaps, + uint32_t num_layers, + VkSampleCountFlagBits samples, + VkImageUsageFlags usage_scenarios); -struct qfv_memory_s *QFV_AllocImageMemory (qfv_image_t *image, +VkDeviceMemory QFV_AllocImageMemory (struct qfv_device_s *device, + VkImage image, VkMemoryPropertyFlags properties, VkDeviceSize size, VkDeviceSize offset); -int QFV_BindImageMemory (qfv_image_t *image, struct qfv_memory_s *memory, - VkDeviceSize offset); - qfv_imagebarrierset_t * -QFV_CreateImageTransitionSet (qfv_imagetransition_t **transitions, +QFV_CreateImageTransitionSet (qfv_imagetransition_t *transitions, int numTransitions); -qfv_imageview_t *QFV_CreateImageView (qfv_image_t *image, VkImageViewType type, - VkFormat format, - VkImageAspectFlags aspect); - -void QFV_DestroyImageView (qfv_imageview_t *view); - -void QFV_DestroyImage (qfv_image_t *image); +VkImageView QFV_CreateImageView (struct qfv_device_s *device, + VkImage image, VkImageViewType type, + VkFormat format, VkImageAspectFlags aspect); #endif//__QF_Vulkan_image_h diff --git a/include/QF/Vulkan/instance.h b/include/QF/Vulkan/instance.h index 6c393d140..0cf5b2226 100644 --- a/include/QF/Vulkan/instance.h +++ b/include/QF/Vulkan/instance.h @@ -37,7 +37,9 @@ typedef struct qfv_instfuncs_s { } qfv_instfuncs_t; typedef struct qfv_physdev_s { + struct qfv_instance_s *instance; VkPhysicalDevice dev; + VkPhysicalDeviceProperties properties; VkPhysicalDeviceMemoryProperties memory_properties; } qfv_physdev_t; diff --git a/include/QF/Vulkan/memory.h b/include/QF/Vulkan/memory.h index 55b87f6c6..91885d31b 100644 --- a/include/QF/Vulkan/memory.h +++ b/include/QF/Vulkan/memory.h @@ -1,21 +1,22 @@ #ifndef __QF_Vulkan_memory_h #define __QF_Vulkan_memory_h -typedef struct qfv_memory_s { - struct qfv_device_s *device; - VkDeviceMemory object; -} qfv_memory_t; +#include "QF/darray.h" typedef struct qfv_mappedmemrange_s { - qfv_memory_t *memory; + VkDeviceMemory object; VkDeviceSize offset; VkDeviceSize size; } qfv_mappedmemrange_t; -void QFV_FreeMemory (qfv_memory_t *memory); -void *QFV_MapMemory (qfv_memory_t *memory, +typedef struct qfv_mappedmemrangeset_s + DARRAY_TYPE (qfv_mappedmemrange_t) qfv_mappedmemrangeset_t; + +struct qfv_device_s; + +void *QFV_MapMemory (struct qfv_device_s *device, VkDeviceMemory object, VkDeviceSize offset, VkDeviceSize size); -void QFV_UnmapMemory (qfv_memory_t *memory); -void QFV_FlushMemory (qfv_mappedmemrange_t *ranges, uint32_t numRanges); +void QFV_FlushMemory (struct qfv_device_s *device, + qfv_mappedmemrangeset_t *ranges); #endif//__QF_Vulkan_memory_h diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index c8fdc2965..3dd4acc63 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -63,7 +63,7 @@ struct qfv_imageview_s; qfv_framebuffer_t * QFV_CreateFramebuffer (qfv_renderpass_t *renderPass, uint32_t numAttachments, - struct qfv_imageview_s **attachments, + VkImageView *attachments, uint32_t width, uint32_t height, uint32_t layers); void QFV_DestroyFramebuffer (qfv_framebuffer_t *framebuffer); diff --git a/include/QF/Vulkan/swapchain.h b/include/QF/Vulkan/swapchain.h index 1a9abb896..9d04b35e4 100644 --- a/include/QF/Vulkan/swapchain.h +++ b/include/QF/Vulkan/swapchain.h @@ -5,8 +5,11 @@ typedef struct qfv_swapchain_s { struct qfv_device_s *device; VkSurfaceKHR surface; VkSwapchainKHR swapchain; + VkFormat format; + VkExtent2D extent; int32_t numImages; - VkImage *images; + struct qfv_imageset_s *images; + struct qfv_imageviewset_s *imageViews; } qfv_swapchain_t; struct vulkan_ctx_s; @@ -15,8 +18,7 @@ qfv_swapchain_t *QFV_CreateSwapchain (struct vulkan_ctx_s *ctx, void QFV_DestroySwapchain (qfv_swapchain_t *swapchain); struct qfv_semaphore_s; struct qfv_fence_s; -int QFV_AcquireNextImage (qfv_swapchain_t *swapchain, - struct qfv_semaphore_s *semaphore, - struct qfv_fence_s *fence, uint32_t *imageIndex); +int QFV_AcquireNextImage (qfv_swapchain_t *swapchain, VkSemaphore semaphore, + VkFence fence, uint32_t *imageIndex); #endif//__QF_Vulkan_swapchain_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 5b9a31daf..77718ab9c 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -32,7 +32,7 @@ typedef struct vulkan_ctx_s { struct qfv_swapchain_s *swapchain; VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain - struct qfv_cmdpool_s *cmdpool; + VkCommandPool cmdpool; vulkan_frameset_t frameset; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index de0917310..0373867de 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -33,6 +33,7 @@ //#define NH_DEFINE //#include "vulkan/namehack.h" +#include "QF/darray.h" #include "QF/sys.h" #include "QF/plugin/general.h" @@ -41,6 +42,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/swapchain.h" @@ -56,19 +58,24 @@ static vulkan_ctx_t *vulkan_ctx; static void vulkan_R_Init (void) { + qfv_device_t *device = vulkan_ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; qfv_cmdbufferset_t *cmdBuffers; + Vulkan_CreateSwapchain (vulkan_ctx); - cmdBuffers = QFV_AllocateCommandBuffers (vulkan_ctx->cmdpool, 0, + cmdBuffers = QFV_AllocateCommandBuffers (device, vulkan_ctx->cmdpool, 0, vulkan_ctx->swapchain->numImages); vulkan_ctx->frameset.cmdBuffers = cmdBuffers; - for (int i = 0; i < cmdBuffers->numBuffers; i++) { - QFV_BeginCommandBuffer (cmdBuffers->buffers[i], 0, 0, 0, 0); - QFV_EndCommandBuffer (cmdBuffers->buffers[i]); + VkCommandBufferBeginInfo beginInfo + = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + for (size_t i = 0; i < cmdBuffers->size; i++) { + dfunc->vkBeginCommandBuffer (cmdBuffers->a[i], &beginInfo); + dfunc->vkEndCommandBuffer (cmdBuffers->a[i]); } Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, vulkan_ctx->swapchain->numImages); for (int32_t i = 0; i < vulkan_ctx->swapchain->numImages; i++) { - Sys_Printf (" %p", vulkan_ctx->swapchain->images[i]); + Sys_Printf (" %p", vulkan_ctx->swapchain->images->a[i]); } Sys_Printf ("\n"); } @@ -79,39 +86,42 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) static int count = 0; static double startTime; uint32_t imageIndex = 0; - qfv_devfuncs_t *dfunc = vulkan_ctx->device->funcs; + qfv_device_t *device = vulkan_ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkDevice dev = device->dev; qfv_queue_t *queue = &vulkan_ctx->device->queue; vulkan_frameset_t *frameset = &vulkan_ctx->frameset; - QFV_WaitForFence (frameset->fences->fences[frameset->curFrame], - 2000000000); + dfunc->vkWaitForFences (dev, 1, & frameset->fences->a[frameset->curFrame], + VK_TRUE, 2000000000); QFV_AcquireNextImage (vulkan_ctx->swapchain, - frameset->imageSemaphores->semaphores[frameset->curFrame], + frameset->imageSemaphores->a[frameset->curFrame], 0, &imageIndex); - VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkPipelineStageFlags waitStage + = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, 1, - &frameset->imageSemaphores->vkSemaphores[frameset->curFrame], + &frameset->imageSemaphores->a[frameset->curFrame], &waitStage, - 1, &frameset->cmdBuffers->vkBuffers[imageIndex], - 1, &frameset->renderDoneSemaphores->vkSemaphores[frameset->curFrame], + 1, &frameset->cmdBuffers->a[imageIndex], + 1, &frameset->renderDoneSemaphores->a[frameset->curFrame], }; - QFV_ResetFence (frameset->fences->fences[frameset->curFrame]); + dfunc->vkResetFences (dev, 1, &frameset->fences->a[frameset->curFrame]); dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, - frameset->fences->vkFences[frameset->curFrame]); + frameset->fences->a[frameset->curFrame]); VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, - 1, &frameset->renderDoneSemaphores->vkSemaphores[frameset->curFrame], + 1, &frameset->renderDoneSemaphores->a[frameset->curFrame], 1, &vulkan_ctx->swapchain->swapchain, &imageIndex, 0 }; dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); frameset->curFrame++; - frameset->curFrame %= frameset->fences->numFences; + frameset->curFrame %= frameset->fences->size; if (++count >= 100) { double currenTime = Sys_DoubleTime (); @@ -238,7 +248,7 @@ vulkan_vid_render_choose_visual (void) Sys_Printf ("vk choose visual %p %p %d %p\n", vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue, vulkan_ctx->device->queue.queueFamily, - vulkan_ctx->cmdpool->cmdpool); + vulkan_ctx->cmdpool); } static void @@ -247,19 +257,18 @@ vulkan_vid_render_create_context (void) vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); vulkan_ctx->frameset.curFrame = 0; - qfv_fence_t **fences = alloca (2 * sizeof (*fences)); - qfv_semaphore_t **imageSems = alloca (2 * sizeof (*imageSems)); - qfv_semaphore_t **renderDoneSems = alloca (2 * sizeof (*renderDoneSems)); + qfv_fenceset_t *fences = DARRAY_ALLOCFIXED (*fences, 2, malloc); + qfv_semaphoreset_t *imageSems = DARRAY_ALLOCFIXED (*imageSems, 2, malloc); + qfv_semaphoreset_t *renderDoneSems = DARRAY_ALLOCFIXED (*renderDoneSems, 2, + malloc); for (int i = 0; i < 2; i++) { - fences[i]= QFV_CreateFence (vulkan_ctx->device, 1); - imageSems[i] = QFV_CreateSemaphore (vulkan_ctx->device); - renderDoneSems[i] = QFV_CreateSemaphore (vulkan_ctx->device); + fences->a[i]= QFV_CreateFence (vulkan_ctx->device, 1); + imageSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device); + renderDoneSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device); } - vulkan_ctx->frameset.fences = QFV_CreateFenceSet (fences, 2); - vulkan_ctx->frameset.imageSemaphores - = QFV_CreateSemaphoreSet (imageSems, 2); - vulkan_ctx->frameset.renderDoneSemaphores - = QFV_CreateSemaphoreSet (renderDoneSems, 2); + vulkan_ctx->frameset.fences = fences; + vulkan_ctx->frameset.imageSemaphores = imageSems; + vulkan_ctx->frameset.renderDoneSemaphores = renderDoneSems; Sys_Printf ("vk create context %p\n", vulkan_ctx->surface); } @@ -282,15 +291,17 @@ vulkan_vid_render_init (void) static void vulkan_vid_render_shutdown (void) { - QFV_DeviceWaitIdle (vulkan_ctx->device); + qfv_device_t *device = vulkan_ctx->device; + qfv_devfuncs_t *df = device->funcs; + VkDevice dev = device->dev; + QFV_DeviceWaitIdle (device); vulkan_frameset_t *frameset = &vulkan_ctx->frameset; - for (int i = 0; i < frameset->fences->numFences; i++) { - QFV_DestroyFence (frameset->fences->fences[i]); - QFV_DestroySemaphore (frameset->imageSemaphores->semaphores[i]); - QFV_DestroySemaphore (frameset->renderDoneSemaphores->semaphores[i]); + for (size_t i = 0; i < frameset->fences->size; i++) { + df->vkDestroyFence (dev, frameset->fences->a[i], 0); + df->vkDestroySemaphore (dev, frameset->imageSemaphores->a[i], 0); + df->vkDestroySemaphore (dev, frameset->renderDoneSemaphores->a[i], 0); } - QFV_DestroyFenceSet (vulkan_ctx->frameset.fences); - QFV_DestroyCommandPool (vulkan_ctx->cmdpool); + df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); Vulkan_Shutdown_Common (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index e2d598b81..71b094e68 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -61,7 +61,7 @@ #include "util.h" -qfv_buffer_t * +VkBuffer QFV_CreateBuffer (qfv_device_t *device, VkDeviceSize size, VkBufferUsageFlags usage) { @@ -73,24 +73,23 @@ QFV_CreateBuffer (qfv_device_t *device, VkDeviceSize size, size, usage, VK_SHARING_MODE_EXCLUSIVE, 0, 0 }; - qfv_buffer_t *buffer = malloc (sizeof (*buffer)); - dfunc->vkCreateBuffer (dev, &createInfo, 0, &buffer->buffer); - buffer->device = device; + VkBuffer buffer; + dfunc->vkCreateBuffer (dev, &createInfo, 0, &buffer); return buffer; } -qfv_memory_t * -QFV_AllocBufferMemory (qfv_buffer_t *buffer, VkMemoryPropertyFlags properties, +VkDeviceMemory +QFV_AllocBufferMemory (qfv_device_t *device, + VkBuffer buffer, VkMemoryPropertyFlags properties, VkDeviceSize size, VkDeviceSize offset) { - qfv_device_t *device = buffer->device; VkDevice dev = device->dev; qfv_physdev_t *physdev = device->physDev; VkPhysicalDeviceMemoryProperties *memprops = &physdev->memory_properties; qfv_devfuncs_t *dfunc = device->funcs; VkMemoryRequirements requirements; - dfunc->vkGetBufferMemoryRequirements (dev, buffer->buffer, &requirements); + dfunc->vkGetBufferMemoryRequirements (dev, buffer, &requirements); size = max (size, offset + requirements.size); VkDeviceMemory object = 0; @@ -112,97 +111,55 @@ QFV_AllocBufferMemory (qfv_buffer_t *buffer, VkMemoryPropertyFlags properties, } } - qfv_memory_t *memory = 0; - - if (object) { - memory = malloc (sizeof (*memory)); - memory->device = device; - memory->object = object; - } - return memory; + return object; } int -QFV_BindBufferMemory (qfv_buffer_t *buffer, qfv_memory_t *memory, +QFV_BindBufferMemory (qfv_device_t *device, + VkBuffer buffer, VkDeviceMemory object, VkDeviceSize offset) { - qfv_device_t *device = buffer->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - VkResult res = dfunc->vkBindBufferMemory (dev, buffer->buffer, - memory->object, offset); + VkResult res = dfunc->vkBindBufferMemory (dev, buffer, object, offset); return res == VK_SUCCESS; } qfv_bufferbarrierset_t * -QFV_CreateBufferTransitionSet (qfv_buffertransition_t **transitions, - int numTransitions) +QFV_CreateBufferTransitions (qfv_buffertransition_t *transitions, + int numTransitions) { - qfv_device_t *device = transitions[0]->buffer->device; - qfv_bufferbarrierset_t *barrierset = malloc (sizeof (*barrierset) - + sizeof (VkBufferMemoryBarrier) * numTransitions); - - barrierset->device = device; - barrierset->numBarriers = numTransitions; - barrierset->barriers = (VkBufferMemoryBarrier *) (barrierset + 1); + qfv_bufferbarrierset_t *barrierset; + barrierset = DARRAY_ALLOCFIXED (*barrierset, numTransitions, malloc); for (int i = 0; i < numTransitions; i++) { - VkBufferMemoryBarrier *barrier = &barrierset->barriers[i]; - barrier->sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier->pNext = 0; - barrier->srcAccessMask = transitions[i]->srcAccess; - barrier->dstAccessMask = transitions[i]->dstAccess; - barrier->srcQueueFamilyIndex = transitions[i]->srcQueueFamily; - barrier->dstQueueFamilyIndex = transitions[i]->dstQueueFamily; - barrier->buffer = transitions[i]->buffer->buffer; - barrier->offset = transitions[i]->offset; - barrier->size = transitions[i]->size; + barrierset->a[i].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + barrierset->a[i].pNext = 0; + barrierset->a[i].srcAccessMask = transitions[i].srcAccess; + barrierset->a[i].dstAccessMask = transitions[i].dstAccess; + barrierset->a[i].srcQueueFamilyIndex = transitions[i].srcQueueFamily; + barrierset->a[i].dstQueueFamilyIndex = transitions[i].dstQueueFamily; + barrierset->a[i].buffer = transitions[i].buffer; + barrierset->a[i].offset = transitions[i].offset; + barrierset->a[i].size = transitions[i].size; } return barrierset; } -qfv_bufferview_t * -QFV_CreateBufferView (qfv_buffer_t *buffer, VkFormat format, +VkBufferView +QFV_CreateBufferView (qfv_device_t *device, VkBuffer buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize size) { - qfv_device_t *device = buffer->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; VkBufferViewCreateInfo createInfo = { VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, 0, 0, - buffer->buffer, format, offset, size, + buffer, format, offset, size, }; - qfv_bufferview_t *view = malloc (sizeof (*view)); - view->device = device; - view->buffer = buffer; - view->format = format; - view->offset = offset; - view->size = size; - dfunc->vkCreateBufferView (dev, &createInfo, 0, &view->view); + VkBufferView view; + dfunc->vkCreateBufferView (dev, &createInfo, 0, &view); return view; } - -void -QFV_DestroyBufferView (qfv_bufferview_t *view) -{ - qfv_device_t *device = view->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyBufferView (dev, view->view, 0); - free (view); -} - -void -QFV_DestroyBuffer (qfv_buffer_t *buffer) -{ - qfv_device_t *device = buffer->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyBuffer (dev, buffer->buffer, 0); - free (buffer); -} diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index fa671fa5d..8ba60ab32 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -64,7 +64,7 @@ #include "util.h" -qfv_cmdpool_t * +VkCommandPool QFV_CreateCommandPool (qfv_device_t *device, uint32_t queueFamily, int transient, int reset) { @@ -82,43 +82,15 @@ QFV_CreateCommandPool (qfv_device_t *device, uint32_t queueFamily, flags, queueFamily }; - qfv_cmdpool_t *cmdpool = malloc (sizeof (*cmdpool)); - dfunc->vkCreateCommandPool (dev, &createInfo, 0, &cmdpool->cmdpool); - cmdpool->device = device; - return cmdpool; -} - -int -QFV_ResetCommandPool (qfv_cmdpool_t *pool, int release) -{ - qfv_device_t *device = pool->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - VkCommandPool cmdpool = pool->cmdpool; - VkCommandPoolResetFlags release_flag = 0; - - if (release) { - release_flag = VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT; - } - - return dfunc->vkResetCommandPool (dev, cmdpool, release_flag) == VK_SUCCESS; -} - -void -QFV_DestroyCommandPool (qfv_cmdpool_t *pool) -{ - qfv_device_t *device = pool->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyCommandPool (dev, pool->cmdpool, 0); - free (pool); + VkCommandPool pool; + dfunc->vkCreateCommandPool (dev, &createInfo, 0, &pool); + return pool; } qfv_cmdbufferset_t * -QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) +QFV_AllocateCommandBuffers (qfv_device_t *device, VkCommandPool pool, + int secondary, int count) { - qfv_device_t *device = pool->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; uint32_t level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; @@ -127,96 +99,15 @@ QFV_AllocateCommandBuffers (qfv_cmdpool_t *pool, int secondary, int count) } VkCommandBufferAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 0, - pool->cmdpool, level, count + pool, level, count }; qfv_cmdbufferset_t *cmdbufferset; - cmdbufferset = malloc (sizeof (qfv_cmdbufferset_t) - + count * sizeof (qfv_buffer_t *) - + count * sizeof (qfv_buffer_t) - + count * sizeof (VkCommandBuffer)); - cmdbufferset->buffers = (qfv_cmdbuffer_t **) (cmdbufferset + 1); - cmdbufferset->vkBuffers = (VkCommandBuffer *) (cmdbufferset->buffers - + count); - qfv_cmdbuffer_t *buffer = (qfv_cmdbuffer_t *) (cmdbufferset->vkBuffers - + count); - cmdbufferset->cmdpool = pool->cmdpool; - cmdbufferset->numBuffers = count; - dfunc->vkAllocateCommandBuffers (dev, &allocInfo, cmdbufferset->vkBuffers); - for (int i = 0; i < count; i++) { - buffer->device = device; - buffer->buffer = &cmdbufferset->vkBuffers[i]; - cmdbufferset->buffers[i] = buffer++; - } + cmdbufferset = DARRAY_ALLOCFIXED (*cmdbufferset, count, malloc); + dfunc->vkAllocateCommandBuffers (dev, &allocInfo, cmdbufferset->a); return cmdbufferset; } -void QFV_FreeCommandBuffers (qfv_cmdbufferset_t *bufferset) -{ - qfv_device_t *device = bufferset->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkFreeCommandBuffers (dev, bufferset->cmdpool, - bufferset->numBuffers, - bufferset->vkBuffers); - free (bufferset); -} - -int -QFV_BeginCommandBuffer (qfv_cmdbuffer_t *buffer, int oneTime, int rpContinue, - int simultaneous, - VkCommandBufferInheritanceInfo *inheritanceInfo) -{ - qfv_device_t *device = buffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkCommandBuffer buff = *buffer->buffer; - VkCommandBufferUsageFlags usage = 0; - - if (oneTime) { - usage |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - } - if (rpContinue) { - usage |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; - } - if (simultaneous) { - usage |= VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; - } - - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - usage, - 0 - }; - - return dfunc->vkBeginCommandBuffer (buff, &beginInfo) == VK_SUCCESS; -} - -int -QFV_EndCommandBuffer (qfv_cmdbuffer_t *buffer) -{ - qfv_device_t *device = buffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkCommandBuffer buff = *buffer->buffer; - - return dfunc->vkEndCommandBuffer (buff) == VK_SUCCESS; -} - -int -QFV_ResetCommandBuffer (qfv_cmdbuffer_t *buffer, int release) -{ - qfv_device_t *device = buffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkCommandBuffer buff = *buffer->buffer; - VkCommandBufferResetFlags release_flag = 0; - - if (release) { - release_flag = VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT; - } - - return dfunc->vkResetCommandBuffer (buff, release_flag) == VK_SUCCESS; -} - -qfv_semaphore_t * +VkSemaphore QFV_CreateSemaphore (qfv_device_t *device) { VkDevice dev = device->dev; @@ -227,58 +118,12 @@ QFV_CreateSemaphore (qfv_device_t *device) 0 }; - qfv_semaphore_t *semaphore = malloc (sizeof (*semaphore)); - semaphore->device = device; - - dfunc->vkCreateSemaphore (dev, &createInfo, 0, &semaphore->semaphore); + VkSemaphore semaphore; + dfunc->vkCreateSemaphore (dev, &createInfo, 0, &semaphore); return semaphore; } -qfv_semaphoreset_t * -QFV_CreateSemaphoreSet (qfv_semaphore_t **semaphores, int numSemaphores) -{ - qfv_device_t *device = semaphores[0]->device; - qfv_semaphoreset_t *semaphoreset; - semaphoreset = calloc (1, sizeof (*semaphoreset) - + sizeof (qfv_semaphore_t *) * numSemaphores - + sizeof (VkSemaphore) * numSemaphores - + sizeof (VkPipelineStageFlags) * numSemaphores); - - semaphoreset->device = device; - semaphoreset->vkSemaphores = (VkSemaphore *) (semaphoreset + 1); - semaphoreset->stages = (VkPipelineStageFlags *) - &semaphoreset->vkSemaphores[numSemaphores]; - semaphoreset->semaphores = (qfv_semaphore_t **) (semaphoreset->stages - + numSemaphores); - semaphoreset->numSemaphores = numSemaphores; - - if (semaphores) { - for (int i = 0; i < numSemaphores; i++) { - semaphoreset->semaphores[i] = semaphores[i]; - semaphoreset->vkSemaphores[i] = semaphores[i]->semaphore; - } - } - return semaphoreset; -} - -void -QFV_DestroySemaphore (qfv_semaphore_t *semaphore) -{ - qfv_device_t *device = semaphore->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroySemaphore (dev, semaphore->semaphore, 0); - free (semaphore); -} - -void -QFV_DestroySemaphoreSet (qfv_semaphoreset_t *semaphores) -{ - free (semaphores); -} - -qfv_fence_t * +VkFence QFV_CreateFence (qfv_device_t *device, int signaled) { VkDevice dev = device->dev; @@ -289,113 +134,28 @@ QFV_CreateFence (qfv_device_t *device, int signaled) signaled ? VK_FENCE_CREATE_SIGNALED_BIT : 0, }; - qfv_fence_t *fence = malloc (sizeof (*fence)); - fence->device = device; - - dfunc->vkCreateFence (dev, &createInfo, 0, &fence->fence); + VkFence fence; + dfunc->vkCreateFence (dev, &createInfo, 0, &fence); return fence; } -qfv_fenceset_t * -QFV_CreateFenceSet (qfv_fence_t **fences, int numFences) -{ - qfv_fenceset_t *fenceset = malloc (sizeof (*fenceset) - + sizeof (qfv_fence_t) * numFences - + sizeof (VkFence) * numFences); - - fenceset->fences = (qfv_fence_t **) (fenceset + 1); - fenceset->vkFences = (VkFence *) (fenceset->fences + numFences); - fenceset->numFences = numFences; - - if (fences) { - fenceset->device = fences[0]->device; - for (int i = 0; i < numFences; i++) { - fenceset->fences[i] = fences[i]; - fenceset->vkFences[i] = fences[i]->fence; - } - } - return fenceset; -} - -void -QFV_DestroyFence (qfv_fence_t *fence) -{ - qfv_device_t *device = fence->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyFence (dev, fence->fence, 0); - free (fence); -} - -void -QFV_DestroyFenceSet (qfv_fenceset_t *fenceset) -{ - free (fenceset); -} - -int -QFV_WaitForFences (qfv_fenceset_t *fenceset, int all, uint64_t timeout) -{ - qfv_device_t *device = fenceset->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - VkResult res = dfunc->vkWaitForFences (dev, fenceset->numFences, - fenceset->vkFences, all, timeout); - return res == VK_SUCCESS; -} - -int -QFV_WaitForFence (qfv_fence_t *fence, uint64_t timeout) -{ - qfv_device_t *device = fence->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - VkResult res = dfunc->vkWaitForFences (dev, 1, &fence->fence, 1, timeout); - return res == VK_SUCCESS; -} - -int -QFV_ResetFences (qfv_fenceset_t *fenceset) -{ - qfv_device_t *device = fenceset->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - return dfunc->vkResetFences (dev, fenceset->numFences, - fenceset->vkFences) == VK_SUCCESS; -} - -int -QFV_ResetFence (qfv_fence_t *fence) -{ - qfv_device_t *device = fence->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - return dfunc->vkResetFences (dev, 1, &fence->fence) == VK_SUCCESS; -} - int QFV_QueueSubmit (qfv_queue_t *queue, qfv_semaphoreset_t *waitSemaphores, + VkPipelineStageFlags *stages, qfv_cmdbufferset_t *buffers, - qfv_semaphoreset_t *signalSemaphores, qfv_fence_t *fence) + qfv_semaphoreset_t *signalSemaphores, VkFence fence) { qfv_device_t *device = queue->device; qfv_devfuncs_t *dfunc = device->funcs; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - waitSemaphores->numSemaphores, - waitSemaphores->vkSemaphores, waitSemaphores->stages, - buffers->numBuffers, buffers->vkBuffers, - signalSemaphores->numSemaphores, - signalSemaphores->vkSemaphores + waitSemaphores->size, waitSemaphores->a, stages, + buffers->size, buffers->a, + signalSemaphores->size, signalSemaphores->a }; //FIXME multi-batch - return dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, - fence->fence) == VK_SUCCESS; + return dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, fence) + == VK_SUCCESS; } int @@ -405,129 +165,3 @@ QFV_QueueWaitIdle (qfv_queue_t *queue) qfv_devfuncs_t *dfunc = device->funcs; return dfunc->vkQueueWaitIdle (queue->queue) == VK_SUCCESS; } - -void -QFV_CmdPipelineBarrier (qfv_cmdbuffer_t *cmdBuffer, - VkPipelineStageFlags srcStageMask, - VkPipelineStageFlags dstStageMask, - VkDependencyFlags dependencyFlags, - struct qfv_memorybarrierset_s *memBarrierSet, - qfv_bufferbarrierset_t *buffBarrierSet, - qfv_imagebarrierset_t *imgBarrierSet) -{ - qfv_device_t *device = cmdBuffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - uint32_t numMemBarriers = 0; - VkMemoryBarrier *memBarriers = 0; - uint32_t numBuffBarriers = 0; - VkBufferMemoryBarrier *buffBarriers = 0; - uint32_t numImgBarriers = 0; - VkImageMemoryBarrier *imgBarriers = 0; - - if (buffBarrierSet) { - numBuffBarriers = buffBarrierSet->numBarriers; - buffBarriers = buffBarrierSet->barriers; - } - if (imgBarrierSet) { - numImgBarriers = imgBarrierSet->numBarriers; - imgBarriers = imgBarrierSet->barriers; - } - dfunc->vkCmdPipelineBarrier (*cmdBuffer->buffer, - srcStageMask, dstStageMask, dependencyFlags, - numMemBarriers, memBarriers, - numBuffBarriers, buffBarriers, - numImgBarriers, imgBarriers); -} - -void -QFV_CmdCopyBuffer (qfv_cmdbuffer_t *cmdBuffer, - struct qfv_buffer_s *src, struct qfv_buffer_s *dst, - VkBufferCopy *regions, uint32_t numRegions) -{ - qfv_device_t *device = cmdBuffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkCmdCopyBuffer (*cmdBuffer->buffer, src->buffer, dst->buffer, - numRegions, regions); -} - -void -QFV_CmdCopyBufferToImage (qfv_cmdbuffer_t *cmdBuffer, - struct qfv_buffer_s *src, - struct qfv_image_s *dst, - VkImageLayout layout, - VkBufferImageCopy *regions, uint32_t numRegions) -{ - qfv_device_t *device = cmdBuffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkCmdCopyBufferToImage (*cmdBuffer->buffer, src->buffer, dst->image, - layout, numRegions, regions); -} - -void -QFV_CmdCopyImageToBuffer (qfv_cmdbuffer_t *cmdBuffer, - struct qfv_image_s *src, - VkImageLayout layout, - struct qfv_buffer_s *dst, - VkBufferImageCopy *regions, uint32_t numRegions) -{ - qfv_device_t *device = cmdBuffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkCmdCopyImageToBuffer (*cmdBuffer->buffer, src->image, layout, - dst->buffer, numRegions, regions); -} - -void -QFV_CmdBeginRenderPass (qfv_cmdbuffer_t *cmdBuffer, - qfv_renderpass_t *renderPass, - qfv_framebuffer_t *framebuffer, - VkRect2D renderArea, - uint32_t numClearValues, - VkClearValue *clearValues, - VkSubpassContents subpassContents) -{ - qfv_device_t *device = cmdBuffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - - VkRenderPassBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, - renderPass->renderPass, framebuffer->framebuffer, renderArea, - numClearValues, clearValues, - }; - - dfunc->vkCmdBeginRenderPass (*cmdBuffer->buffer, &beginInfo, - subpassContents); -} - -void -QFV_CmdNextSubpass (qfv_cmdbuffer_t *cmdBuffer, - VkSubpassContents subpassContents) -{ - qfv_device_t *device = cmdBuffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkCmdNextSubpass (*cmdBuffer->buffer, subpassContents); -} - -void -QFV_CmdEndRenderPass (qfv_cmdbuffer_t *cmdBuffer) -{ - qfv_device_t *device = cmdBuffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkCmdEndRenderPass (*cmdBuffer->buffer); -} - -void -QFV_CmdBindPipeline (qfv_cmdbuffer_t *cmdBuffer, - VkPipelineBindPoint bindPoint, - qfv_pipeline_t *pipeline) -{ - qfv_device_t *device = cmdBuffer->device; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkCmdBindPipeline (*cmdBuffer->buffer, bindPoint, - pipeline->pipeline); -} diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 750534f53..0457d0570 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -211,3 +211,24 @@ QFV_DeviceWaitIdle (qfv_device_t *device) qfv_devfuncs_t *dfunc = device->funcs; return dfunc->vkDeviceWaitIdle (device->dev) == VK_SUCCESS; } + +VkFormat +QFV_FindSupportedFormat (qfv_device_t *device, + VkImageTiling tiling, VkFormatFeatureFlags features, + int numCandidates, const VkFormat *candidates) +{ + VkPhysicalDevice pdev = device->physDev->dev; + qfv_instfuncs_t *ifuncs = device->physDev->instance->funcs; + for (int i = 0; i < numCandidates; i++) { + VkFormat format = candidates[i]; + VkFormatProperties props; + ifuncs->vkGetPhysicalDeviceFormatProperties (pdev, format, &props); + if ((tiling == VK_IMAGE_TILING_LINEAR + && (props.linearTilingFeatures & features) == features) + || (tiling == VK_IMAGE_TILING_OPTIMAL + && (props.optimalTilingFeatures & features) == features)) { + return format; + } + } + Sys_Error ("no supported format"); +} diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 63b836be5..65f0dcdd3 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -61,7 +61,7 @@ #include "util.h" -qfv_image_t * +VkImage QFV_CreateImage (qfv_device_t *device, int cubemap, VkImageType type, VkFormat format, @@ -85,24 +85,23 @@ QFV_CreateImage (qfv_device_t *device, int cubemap, 0, 0, VK_IMAGE_LAYOUT_UNDEFINED, }; - qfv_image_t *image = malloc (sizeof (*image)); - dfunc->vkCreateImage (dev, &createInfo, 0, &image->image); - image->device = device; + VkImage image; + dfunc->vkCreateImage (dev, &createInfo, 0, &image); return image; } -qfv_memory_t * -QFV_AllocImageMemory (qfv_image_t *image, VkMemoryPropertyFlags properties, - VkDeviceSize size, VkDeviceSize offset) +VkDeviceMemory +QFV_AllocImageMemory (qfv_device_t *device, + VkImage image, VkMemoryPropertyFlags properties, + VkDeviceSize size, VkDeviceSize offset) { - qfv_device_t *device = image->device; VkDevice dev = device->dev; qfv_physdev_t *physdev = device->physDev; VkPhysicalDeviceMemoryProperties *memprops = &physdev->memory_properties; qfv_devfuncs_t *dfunc = device->funcs; VkMemoryRequirements requirements; - dfunc->vkGetImageMemoryRequirements (dev, image->image, &requirements); + dfunc->vkGetImageMemoryRequirements (dev, image, &requirements); size = max (size, offset + requirements.size); VkDeviceMemory object = 0; @@ -124,72 +123,48 @@ QFV_AllocImageMemory (qfv_image_t *image, VkMemoryPropertyFlags properties, } } - qfv_memory_t *memory = 0; - - if (object) { - memory = malloc (sizeof (*memory)); - memory->device = device; - memory->object = object; - } - return memory; -} - -int -QFV_BindImageMemory (qfv_image_t *image, qfv_memory_t *memory, - VkDeviceSize offset) -{ - qfv_device_t *device = image->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - VkResult res = dfunc->vkBindImageMemory (dev, image->image, - memory->object, offset); - return res == VK_SUCCESS; + return object; } qfv_imagebarrierset_t * -QFV_CreateImageTransitionSet (qfv_imagetransition_t **transitions, +QFV_CreateImageTransitionSet (qfv_imagetransition_t *transitions, int numTransitions) { - qfv_device_t *device = transitions[0]->image->device; - qfv_imagebarrierset_t *barrierset = malloc (sizeof (*barrierset) - + sizeof (VkImageMemoryBarrier) * numTransitions); - - barrierset->device = device; - barrierset->numBarriers = numTransitions; - barrierset->barriers = (VkImageMemoryBarrier *) (barrierset + 1); + qfv_imagebarrierset_t *barrierset; + barrierset = DARRAY_ALLOCFIXED (*barrierset, numTransitions, malloc); for (int i = 0; i < numTransitions; i++) { - VkImageMemoryBarrier *barrier = &barrierset->barriers[i]; - barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier->pNext = 0; - barrier->srcAccessMask = transitions[i]->srcAccess; - barrier->dstAccessMask = transitions[i]->dstAccess; - barrier->oldLayout = transitions[i]->oldLayout; - barrier->newLayout = transitions[i]->newLayout; - barrier->srcQueueFamilyIndex = transitions[i]->srcQueueFamily; - barrier->dstQueueFamilyIndex = transitions[i]->dstQueueFamily; - barrier->image = transitions[i]->image->image; - barrier->subresourceRange.aspectMask = transitions[i]->aspect; - barrier->subresourceRange.baseMipLevel = 0; - barrier->subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier->subresourceRange.baseArrayLayer = 0; - barrier->subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + barrierset->a[i].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrierset->a[i].pNext = 0; + barrierset->a[i].srcAccessMask = transitions[i].srcAccess; + barrierset->a[i].dstAccessMask = transitions[i].dstAccess; + barrierset->a[i].oldLayout = transitions[i].oldLayout; + barrierset->a[i].newLayout = transitions[i].newLayout; + barrierset->a[i].srcQueueFamilyIndex = transitions[i].srcQueueFamily; + barrierset->a[i].dstQueueFamilyIndex = transitions[i].dstQueueFamily; + barrierset->a[i].image = transitions[i].image; + barrierset->a[i].subresourceRange.aspectMask = transitions[i].aspect; + barrierset->a[i].subresourceRange.baseMipLevel = 0; + barrierset->a[i].subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrierset->a[i].subresourceRange.baseArrayLayer = 0; + barrierset->a[i].subresourceRange.layerCount + = VK_REMAINING_ARRAY_LAYERS; } return barrierset; } -qfv_imageview_t * -QFV_CreateImageView (qfv_image_t *image, VkImageViewType type, VkFormat format, +VkImageView +QFV_CreateImageView (qfv_device_t *device, VkImage image, + VkImageViewType type, VkFormat format, VkImageAspectFlags aspect) { - qfv_device_t *device = image->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; VkImageViewCreateInfo createInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0, 0, - image->image, type, format, + image, type, format, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, @@ -203,34 +178,7 @@ QFV_CreateImageView (qfv_image_t *image, VkImageViewType type, VkFormat format, } }; - qfv_imageview_t *view = malloc (sizeof (*view)); - view->device = device; - view->image = image; - view->type = type; - view->format = format; - view->aspect = aspect; - dfunc->vkCreateImageView (dev, &createInfo, 0, &view->view); + VkImageView view; + dfunc->vkCreateImageView (dev, &createInfo, 0, &view); return view; } - -void -QFV_DestroyImageView (qfv_imageview_t *view) -{ - qfv_device_t *device = view->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyImageView (dev, view->view, 0); - free (view); -} - -void -QFV_DestroyImage (qfv_image_t *image) -{ - qfv_device_t *device = image->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyImage (dev, image->image, 0); - free (image); -} diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index a744c2608..234236014 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -264,7 +264,9 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, for (uint32_t i = 0; i < inst->numDevices; i++) { VkPhysicalDevice physDev = devices[i]; qfv_physdev_t *dev = &inst->devices[i]; + dev->instance = inst; dev->dev = physDev; + ifunc->vkGetPhysicalDeviceProperties (physDev, &dev->properties); ifunc->vkGetPhysicalDeviceMemoryProperties (physDev, &dev->memory_properties); } diff --git a/libs/video/renderer/vulkan/memory.c b/libs/video/renderer/vulkan/memory.c index c18a8144f..9397f4366 100644 --- a/libs/video/renderer/vulkan/memory.c +++ b/libs/video/renderer/vulkan/memory.c @@ -60,54 +60,32 @@ #include "util.h" -void -QFV_FreeMemory (qfv_memory_t *memory) -{ - qfv_device_t *device = memory->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkFreeMemory (dev, memory->object, 0); - free (memory); -} - void * -QFV_MapMemory (qfv_memory_t *memory, VkDeviceSize offset, VkDeviceSize size) +QFV_MapMemory (qfv_device_t *device, VkDeviceMemory object, + VkDeviceSize offset, VkDeviceSize size) { - qfv_device_t *device = memory->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; void *map = 0; - dfunc->vkMapMemory (dev, memory->object, offset, size, 0, &map); + dfunc->vkMapMemory (dev, object, offset, size, 0, &map); return map; } void -QFV_UnmapMemory (qfv_memory_t *memory) +QFV_FlushMemory (qfv_device_t *device, qfv_mappedmemrangeset_t *flushRanges) { - qfv_device_t *device = memory->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkUnmapMemory (dev, memory->object); -} + VkMappedMemoryRange *ranges = alloca(sizeof (*ranges) * flushRanges->size); -void -QFV_FlushMemory (qfv_mappedmemrange_t *flushRanges, uint32_t numFlushRanges) -{ - qfv_device_t *device = flushRanges[0].memory->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - VkMappedMemoryRange *ranges = alloca(sizeof (*ranges) * numFlushRanges); - - for (uint32_t i = 0; i < numFlushRanges; i++) { + for (uint32_t i = 0; i < flushRanges->size; i++) { ranges[i].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; ranges[i].pNext = 0; - ranges[i].memory = flushRanges[i].memory->object; - ranges[i].offset = flushRanges[i].offset; - ranges[i].size = flushRanges[i].size; + ranges[i].memory = flushRanges->a[i].object; + ranges[i].offset = flushRanges->a[i].offset; + ranges[i].size = flushRanges->a[i].size; } - dfunc->vkFlushMappedMemoryRanges (dev, numFlushRanges, ranges); + dfunc->vkFlushMappedMemoryRanges (dev, flushRanges->size, ranges); } diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 9c1064192..7a64d10a3 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -105,21 +105,17 @@ QFV_CreateRenderPass (qfv_device_t *device, qfv_framebuffer_t * QFV_CreateFramebuffer (qfv_renderpass_t *renderPass, - uint32_t numAttachments, qfv_imageview_t **attachments, + uint32_t numAttachments, VkImageView *attachments, uint32_t width, uint32_t height, uint32_t layers) { qfv_device_t *device = renderPass->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - VkImageView *views = alloca (numAttachments * sizeof (*views)); - for (uint32_t i = 0; i < numAttachments; i++) { - views[i] = attachments[i]->view; - } - VkFramebufferCreateInfo createInfo = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 0, 0, - renderPass->renderPass, numAttachments, views, width, height, layers, + renderPass->renderPass, numAttachments, attachments, + width, height, layers, }; qfv_framebuffer_t *framebuffer = malloc (sizeof (*framebuffer)); diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index b32e3b3ed..4ea0a36dc 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -13,6 +13,7 @@ #include "QF/Vulkan/cvars.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/swapchain.h" @@ -84,7 +85,8 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; imageUsage &= surfCaps.supportedUsageFlags; - VkSurfaceTransformFlagBitsKHR surfTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + VkSurfaceTransformFlagBitsKHR surfTransform + = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; uint32_t numFormats; ifuncs->vkGetPhysicalDeviceSurfaceFormatsKHR (physDev, @@ -128,24 +130,31 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) old_swapchain }; - VkDevice device = ctx->device->dev; + VkDevice dev = ctx->device->dev; VkSwapchainKHR swapchain; - dfuncs->vkCreateSwapchainKHR (device, &createInfo, 0, &swapchain); + dfuncs->vkCreateSwapchainKHR (dev, &createInfo, 0, &swapchain); if (old_swapchain != swapchain) { - dfuncs->vkDestroySwapchainKHR (device, old_swapchain, 0); + dfuncs->vkDestroySwapchainKHR (dev, old_swapchain, 0); } - dfuncs->vkGetSwapchainImagesKHR (device, swapchain, &numImages, 0); - qfv_swapchain_t *sc = malloc (sizeof (qfv_swapchain_t) - + numImages * sizeof (VkImage)); + dfuncs->vkGetSwapchainImagesKHR (dev, swapchain, &numImages, 0); + qfv_swapchain_t *sc = malloc (sizeof (qfv_swapchain_t)); sc->device = ctx->device; sc->surface = ctx->surface; sc->swapchain = swapchain; + sc->format = useFormat.format; + sc->extent = imageSize; sc->numImages = numImages; - sc->images = (VkImage *) (sc + 1); - dfuncs->vkGetSwapchainImagesKHR (device, swapchain, &numImages, - sc->images); + sc->images = DARRAY_ALLOCFIXED (qfv_imageset_t, numImages, malloc); + sc->imageViews = DARRAY_ALLOCFIXED (qfv_imageviewset_t, numImages, malloc); + dfuncs->vkGetSwapchainImagesKHR (dev, swapchain, &numImages, sc->images->a); + for (uint32_t i = 0; i < numImages; i++) { + sc->imageViews->a[i] + = QFV_CreateImageView (ctx->device, sc->images->a[i], + VK_IMAGE_VIEW_TYPE_2D, sc->format, + VK_IMAGE_ASPECT_COLOR_BIT); + } return sc; } @@ -155,23 +164,26 @@ QFV_DestroySwapchain (qfv_swapchain_t *swapchain) qfv_device_t *device = swapchain->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; + for (size_t i = 0; i < swapchain->imageViews->size; i++) { + dfunc->vkDestroyImageView (dev, swapchain->imageViews->a[i], 0); + } + free (swapchain->images); + free (swapchain->imageViews); dfunc->vkDestroySwapchainKHR (dev, swapchain->swapchain, 0); free (swapchain); } int -QFV_AcquireNextImage (qfv_swapchain_t *swapchain, qfv_semaphore_t *semaphore, - qfv_fence_t *fence, uint32_t *imageIndex) +QFV_AcquireNextImage (qfv_swapchain_t *swapchain, VkSemaphore semaphore, + VkFence fence, uint32_t *imageIndex) { qfv_device_t *device = swapchain->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; uint64_t timeout = 2000000000; - VkSemaphore sem = semaphore ? semaphore->semaphore : VK_NULL_HANDLE; - VkFence fnc = fence ? fence->fence : VK_NULL_HANDLE; *imageIndex = ~0u; VkResult res = dfunc->vkAcquireNextImageKHR (dev, swapchain->swapchain, - timeout, sem, fnc, + timeout, semaphore, fence, imageIndex); switch (res) { case VK_SUCCESS: From 73fde40cad512c8b6842791ea4aa0a3c017fadd6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 23:30:25 +0900 Subject: [PATCH 0316/3664] Sanitize some more structs --- include/QF/Vulkan/pipeline.h | 29 +++++------ include/QF/Vulkan/renderpass.h | 56 +++++++-------------- libs/video/renderer/vulkan/pipeline.c | 18 +++---- libs/video/renderer/vulkan/renderpass.c | 67 ++++++++----------------- 4 files changed, 62 insertions(+), 108 deletions(-) diff --git a/include/QF/Vulkan/pipeline.h b/include/QF/Vulkan/pipeline.h index 6a532102b..2120e2317 100644 --- a/include/QF/Vulkan/pipeline.h +++ b/include/QF/Vulkan/pipeline.h @@ -1,6 +1,8 @@ #ifndef __QF_Vulkan_pipeline_h #define __QF_Vulkan_pipeline_h +#include "QF/darray.h" + typedef struct qfv_shadermodule_s { struct qfv_device_s *device; VkShaderModule module; @@ -13,29 +15,24 @@ typedef struct qfv_shaderstageparams_s { const VkSpecializationInfo *specializationInfo; } qfv_shaderstageparams_t; -typedef struct qfv_shaderstageparamsset_s { - uint32_t numParams; - qfv_shaderstageparams_t params[]; -} qfv_shaderstageparamsset_t; +typedef struct qfv_shaderstageparamsset_s + DARRAY_TYPE (qfv_shaderstageparams_t) qfv_shaderstageparamsset_t; #define QFV_AllocShaderParamsSet(num, allocator) \ - allocator (field_offset (qfv_shaderstageparamsset_t, params[num])) + DARRAY_ALLOCFIXED (qfv_shaderstageparamsset_t, num, allocator) -typedef struct qfv_vertexinputbindingset_s { - uint32_t numBindings; - VkVertexInputBindingDescription bindings[]; -} qfv_vertexinputbindingset_t; +typedef struct qfv_vertexinputbindingset_s + DARRAY_TYPE (VkVertexInputBindingDescription) qfv_vertexinputbindingset_t; #define QFV_AllocVertexInputBindingSet(num, allocator) \ - allocator (field_offset (qfv_vertexinputbindingset_t, bindings[num])) + DARRAY_ALLOCFIXED (qfv_vertexinputbindingset_t, num, allocator) -typedef struct qfv_vertexinputattributeset_s { - uint32_t numAttributes; - VkVertexInputAttributeDescription attributes[]; -} qfv_vertexinputattributeset_t; +typedef struct qfv_vertexinputattributeset_s + DARRAY_TYPE (VkVertexInputAttributeDescription) + qfv_vertexinputattributeset_t; #define QFV_AllocVertexInputAttributeSet(num, allocator) \ - allocator (field_offset (qfv_vertexinputattributeset_t, bindings[num])) + DARRAY_ALLOCFIXED (qfv_vertexinputattributeset_t, num, allocator) typedef struct qfv_vertexinputstate_s { qfv_vertexinputbindingset_t *bindings; @@ -168,7 +165,7 @@ typedef struct qfv_graphicspipelinecreateinfo_s { qfv_pipelineblend_t *colorBlendState; qfv_dynamicstateset_t *dynamicState; qfv_pipelinelayout_t *layout; - struct qfv_renderpass_s *renderPass; + VkRenderPass renderPass; uint32_t subpass; qfv_pipeline_t *basePipeline; int32_t basePipelineIndex; diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index 3dd4acc63..257441ca1 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -1,21 +1,19 @@ #ifndef __QF_Vulkan_renderpass_h #define __QF_Vulkan_renderpass_h -typedef struct qfv_attachmentdescription_s { - uint32_t numAttachments; - VkAttachmentDescription attachments[]; -} qfv_attachmentdescription_t; +#include "QF/darray.h" + +typedef struct qfv_attachmentdescription_s + DARRAY_TYPE (VkAttachmentDescription) qfv_attachmentdescription_t; #define QFV_AllocAttachmentDescription(num, allocator) \ - allocator (field_offset (qfv_attachmentdescription_t, attachments[num])) + DARRAY_ALLOCFIXED (qfv_attachmentdescription_t, num, allocator) -typedef struct qfv_attachmentreference_s { - uint32_t numReferences; - VkAttachmentReference references[]; -} qfv_attachmentreference_t; +typedef struct qfv_attachmentreference_s + DARRAY_TYPE (VkAttachmentReference) qfv_attachmentreference_t; #define QFV_AllocAttachmentReference(num, allocator) \ - allocator (field_offset (qfv_attachmentreference_t, references[num])) + DARRAY_ALLOCFIXED (qfv_attachmentreference_t, num, allocator) typedef struct qfv_subpassparameters_s { VkPipelineBindPoint pipelineBindPoint; @@ -27,46 +25,30 @@ typedef struct qfv_subpassparameters_s { uint32_t *preserveAttachments; } qfv_subpassparameters_t; -typedef struct qfv_subpassparametersset_s { - uint32_t numSubpasses; - qfv_subpassparameters_t subpasses[]; -} qfv_subpassparametersset_t; +typedef struct qfv_subpassparametersset_s + DARRAY_TYPE (qfv_subpassparameters_t) qfv_subpassparametersset_t; #define QFV_AllocSubpassParametersSet(num, allocator) \ - allocator (field_offset (qfv_subpassparametersset_t, subpasses[num])) + DARRAY_ALLOCFIXED (qfv_subpassparametersset_t, num, allocator) -typedef struct qfv_subpassdependency_s { - uint32_t numDependencies; - VkSubpassDependency dependencies[]; -} qfv_subpassdependency_t; +typedef struct qfv_subpassdependency_s + DARRAY_TYPE (VkSubpassDependency) qfv_subpassdependency_t; #define QFV_AllocSubpassDependencies(num, allocator) \ - allocator (field_offset (qfv_subpassdependency_t, dependencies[num])) + DARRAY_ALLOCFIXED (qfv_subpassdependency_t, num, allocator) -typedef struct qfv_renderpass_s { - struct qfv_device_s *device; - VkRenderPass renderPass; -} qfv_renderpass_t; - -typedef struct qfv_framebuffer_s { - struct qfv_device_s *device; - VkFramebuffer framebuffer; -} qfv_framebuffer_t; - -qfv_renderpass_t * +struct qfv_device_s; +VkRenderPass QFV_CreateRenderPass (struct qfv_device_s *device, qfv_attachmentdescription_t *attachments, qfv_subpassparametersset_t *subpasses, qfv_subpassdependency_t *dependencies); -struct qfv_imageview_s; -qfv_framebuffer_t * -QFV_CreateFramebuffer (qfv_renderpass_t *renderPass, +VkFramebuffer +QFV_CreateFramebuffer (struct qfv_device_s *device, + VkRenderPass renderPass, uint32_t numAttachments, VkImageView *attachments, uint32_t width, uint32_t height, uint32_t layers); -void QFV_DestroyFramebuffer (qfv_framebuffer_t *framebuffer); -void QFV_DestroyRenderPass (qfv_renderpass_t *renderPass); - #endif//__QF_Vulkan_renderpass_h diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c index 168ec100d..0dd5f260e 100644 --- a/libs/video/renderer/vulkan/pipeline.c +++ b/libs/video/renderer/vulkan/pipeline.c @@ -205,10 +205,10 @@ vertexInputSCI (qfv_vertexinputstate_t vertexState) { VkPipelineVertexInputStateCreateInfo createInfo = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 0, 0, - vertexState.bindings->numBindings, - vertexState.bindings->bindings, - vertexState.attributes->numAttributes, - vertexState.attributes->attributes, + vertexState.bindings->size, + vertexState.bindings->a, + vertexState.attributes->size, + vertexState.attributes->a, }; return createInfo; } @@ -339,7 +339,7 @@ QFV_CreateGraphicsPipelines (qfv_device_t *device, uint32_t numPipelines = gpciSet->numPipelines; uint32_t stageCount = 0; for (uint32_t i = 0; i < numPipelines; i++) { - stageCount += gpciSet->pipelines[i]->stages->numParams; + stageCount += gpciSet->pipelines[i]->stages->size; } size_t blockSize = numPipelines @@ -377,7 +377,7 @@ QFV_CreateGraphicsPipelines (qfv_device_t *device, = (void *)(pipelineInfos->pColorBlendState + numPipelines); for (uint32_t i = 1; i < gpciSet->numPipelines; i++) { pipelineInfos[i].pStages = pipelineInfos[i - 1].pStages - + gpciSet->pipelines[i - 1]->stages->numParams; + + gpciSet->pipelines[i - 1]->stages->size; pipelineInfos[i].pVertexInputState = pipelineInfos[i - 1].pVertexInputState + 1; pipelineInfos[i].pInputAssemblyState @@ -403,9 +403,9 @@ QFV_CreateGraphicsPipelines (qfv_device_t *device, gci->sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; gci->pNext = 0; gci->flags = ci->flags; - gci->stageCount = ci->stages->numParams; + gci->stageCount = ci->stages->size; for (uint32_t j = 0; j < gci->stageCount; j++) { - ((VkPipelineShaderStageCreateInfo *)gci->pStages)[i] = shaderStageCI (ci->stages->params[j]); + ((VkPipelineShaderStageCreateInfo *)gci->pStages)[i] = shaderStageCI (ci->stages->a[j]); } if (ci->vertexState) { *(VkPipelineVertexInputStateCreateInfo *)gci->pVertexInputState = vertexInputSCI (*ci->vertexState); @@ -453,7 +453,7 @@ QFV_CreateGraphicsPipelines (qfv_device_t *device, gci->pDynamicState = 0; } gci->layout = ci->layout->layout; - gci->renderPass = ci->renderPass->renderPass; + gci->renderPass = ci->renderPass; gci->subpass = ci->subpass; gci->basePipelineHandle = ci->basePipeline->pipeline; gci->basePipelineIndex = ci->basePipelineIndex; diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 7a64d10a3..60e279e18 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -1,7 +1,7 @@ /* - descriptor.c + renderpass.c - Vulkan descriptor functions + Vulkan render pass and frame buffer functions Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2020 Bill Currie @@ -62,7 +62,7 @@ #include "util.h" -qfv_renderpass_t * +VkRenderPass QFV_CreateRenderPass (qfv_device_t *device, qfv_attachmentdescription_t *attachments, qfv_subpassparametersset_t *subpassparams, @@ -71,19 +71,19 @@ QFV_CreateRenderPass (qfv_device_t *device, VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - VkSubpassDescription *subpasses = alloca (subpassparams->numSubpasses + VkSubpassDescription *subpasses = alloca (subpassparams->size * sizeof (*subpasses)); - for (uint32_t i = 0; i < subpassparams->numSubpasses; i++) { - qfv_subpassparameters_t *params = &subpassparams->subpasses[i]; + for (uint32_t i = 0; i < subpassparams->size; i++) { + qfv_subpassparameters_t *params = &subpassparams->a[i]; subpasses[i].flags = 0; subpasses[i].pipelineBindPoint = params->pipelineBindPoint; - subpasses[i].inputAttachmentCount = params->inputAttachments->numReferences; - subpasses[i].pInputAttachments = params->inputAttachments->references; - subpasses[i].colorAttachmentCount = params->colorAttachments->numReferences; - subpasses[i].pColorAttachments = params->colorAttachments->references; + subpasses[i].inputAttachmentCount = params->inputAttachments->size; + subpasses[i].pInputAttachments = params->inputAttachments->a; + subpasses[i].colorAttachmentCount = params->colorAttachments->size; + subpasses[i].pColorAttachments = params->colorAttachments->a; if (params->resolveAttachments) { - subpasses[i].pResolveAttachments = params->resolveAttachments->references; + subpasses[i].pResolveAttachments = params->resolveAttachments->a; } subpasses[i].pDepthStencilAttachment = params->depthStencilAttachment; subpasses[i].preserveAttachmentCount = params->numPreserve; @@ -92,56 +92,31 @@ QFV_CreateRenderPass (qfv_device_t *device, VkRenderPassCreateInfo createInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 0, 0, - attachments->numAttachments, attachments->attachments, - subpassparams->numSubpasses, subpasses, - dependencies->numDependencies, dependencies->dependencies, + attachments->size, attachments->a, + subpassparams->size, subpasses, + dependencies->size, dependencies->a, }; - qfv_renderpass_t *renderpass = malloc (sizeof (*renderpass)); - renderpass->device = device; - dfunc->vkCreateRenderPass (dev, &createInfo, 0, &renderpass->renderPass); + VkRenderPass renderpass; + dfunc->vkCreateRenderPass (dev, &createInfo, 0, &renderpass); return renderpass; } -qfv_framebuffer_t * -QFV_CreateFramebuffer (qfv_renderpass_t *renderPass, +VkFramebuffer +QFV_CreateFramebuffer (qfv_device_t *device, VkRenderPass renderPass, uint32_t numAttachments, VkImageView *attachments, uint32_t width, uint32_t height, uint32_t layers) { - qfv_device_t *device = renderPass->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; VkFramebufferCreateInfo createInfo = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 0, 0, - renderPass->renderPass, numAttachments, attachments, + renderPass, numAttachments, attachments, width, height, layers, }; - qfv_framebuffer_t *framebuffer = malloc (sizeof (*framebuffer)); - framebuffer->device = device; - dfunc->vkCreateFramebuffer (dev, &createInfo, 0, &framebuffer->framebuffer); + VkFramebuffer framebuffer; + dfunc->vkCreateFramebuffer (dev, &createInfo, 0, &framebuffer); return framebuffer; } - -void -QFV_DestroyFramebuffer (qfv_framebuffer_t *framebuffer) -{ - qfv_device_t *device = framebuffer->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyFramebuffer (dev, framebuffer->framebuffer, 0); - free (framebuffer); -} - -void -QFV_DestroyRenderPass (qfv_renderpass_t *renderPass) -{ - qfv_device_t *device = renderPass->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyRenderPass (dev, renderPass->renderPass, 0); - free (renderPass); -} From 89d48b56507fa3546b06a131e0daaf2266c6f4b4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Feb 2020 01:03:36 +0900 Subject: [PATCH 0317/3664] Output first pixels Just clearing the screen to 0xbada55, but the validation layer is quiet. --- include/QF/Vulkan/funclist.h | 1 + libs/video/renderer/vid_render_vulkan.c | 47 +++++++++++++++++++++++++ libs/video/renderer/vulkan/swapchain.c | 1 + 3 files changed, 49 insertions(+) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 426b0fa62..8ab62852a 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -165,6 +165,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBeginRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdClearColorImage) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 0373867de..fec8afa24 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -68,8 +68,55 @@ vulkan_R_Init (void) vulkan_ctx->frameset.cmdBuffers = cmdBuffers; VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + VkClearColorValue clearColor = { {0.7294, 0.8549, 0.3333, 1.0} }; + VkImageSubresourceRange image_subresource_range = { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, 1, 0, 1, + }; + VkImageMemoryBarrier pc_barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_MEMORY_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + device->queue.queueFamily, + device->queue.queueFamily, + 0, // filled in later + image_subresource_range + }; + VkImageMemoryBarrier cp_barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_MEMORY_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + device->queue.queueFamily, + device->queue.queueFamily, + 0, // filled in later + image_subresource_range + }; for (size_t i = 0; i < cmdBuffers->size; i++) { + pc_barrier.image = vulkan_ctx->swapchain->images->a[i]; + cp_barrier.image = vulkan_ctx->swapchain->images->a[i]; dfunc->vkBeginCommandBuffer (cmdBuffers->a[i], &beginInfo); + dfunc->vkCmdPipelineBarrier (cmdBuffers->a[i], + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, + 0, 0, // memory barriers + 0, 0, // buffer barriers + 1, &pc_barrier); + dfunc->vkCmdClearColorImage (cmdBuffers->a[i], pc_barrier.image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &clearColor, 1, + &image_subresource_range); + dfunc->vkCmdPipelineBarrier (cmdBuffers->a[i], + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + 0, + 0, 0, + 0, 0, + 1, &cp_barrier); dfunc->vkEndCommandBuffer (cmdBuffers->a[i]); } Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 4ea0a36dc..b2007953a 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -83,6 +83,7 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) imageSize.width, imageSize.height); VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; imageUsage &= surfCaps.supportedUsageFlags; VkSurfaceTransformFlagBitsKHR surfTransform From 1f4c019abc0381d2120f5d4cf7be214899e90dd7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Feb 2020 14:28:28 +0900 Subject: [PATCH 0318/3664] Create and destroy color/depth resources --- include/QF/Vulkan/image.h | 10 + include/QF/Vulkan/qf_vid.h | 2 + include/vid_vulkan.h | 8 + libs/video/renderer/vid_render_vulkan.c | 17 +- libs/video/renderer/vulkan/image.c | 10 + .../video/renderer/vulkan/vulkan_vid_common.c | 192 ++++++++++++++++++ 6 files changed, 235 insertions(+), 4 deletions(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 8db6ee632..edb5e025e 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -6,6 +6,13 @@ typedef struct qfv_imageset_s DARRAY_TYPE (VkImage) qfv_imageset_t; typedef struct qfv_imageviewset_s DARRAY_TYPE (VkImageView) qfv_imageviewset_t; +typedef struct qfv_imageresource_s { + struct qfv_device_s *device; + VkImage image; + VkDeviceMemory object; + VkImageView view; +} qfv_imageresource_t; + typedef struct qfv_imagetransition_s { VkImage image; VkAccessFlags srcAccess; @@ -37,6 +44,9 @@ VkDeviceMemory QFV_AllocImageMemory (struct qfv_device_s *device, VkMemoryPropertyFlags properties, VkDeviceSize size, VkDeviceSize offset); +int QFV_BindImageMemory (struct qfv_device_s *device, VkImage image, + VkDeviceMemory object, VkDeviceSize offset); + qfv_imagebarrierset_t * QFV_CreateImageTransitionSet (qfv_imagetransition_t *transitions, int numTransitions); diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index bfa543c46..26d9d288c 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -36,6 +36,8 @@ #include struct vulkan_ctx_s; +void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); +void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 77718ab9c..a158f0a77 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -14,6 +14,11 @@ typedef struct vulkan_frameset_s { struct qfv_semaphoreset_s *renderDoneSemaphores; } vulkan_frameset_t; +typedef struct vulkan_renderpass_s { + struct qfv_imageresource_s *colorImage; + struct qfv_imageresource_s *depthImage; +} vulkan_renderpass_t; + typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); void (*unload_vulkan) (struct vulkan_ctx_s *ctx); @@ -33,7 +38,10 @@ typedef struct vulkan_ctx_s { VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain VkCommandPool cmdpool; + VkCommandBuffer cmdbuffer; + VkFence fence; // for ctx->cmdbuffer only vulkan_frameset_t frameset; + vulkan_renderpass_t renderpass; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index fec8afa24..5c0b602d0 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -63,6 +63,7 @@ vulkan_R_Init (void) qfv_cmdbufferset_t *cmdBuffers; Vulkan_CreateSwapchain (vulkan_ctx); + Vulkan_CreateRenderPass (vulkan_ctx); cmdBuffers = QFV_AllocateCommandBuffers (device, vulkan_ctx->cmdpool, 0, vulkan_ctx->swapchain->numImages); vulkan_ctx->frameset.cmdBuffers = cmdBuffers; @@ -139,7 +140,7 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) qfv_queue_t *queue = &vulkan_ctx->device->queue; vulkan_frameset_t *frameset = &vulkan_ctx->frameset; - dfunc->vkWaitForFences (dev, 1, & frameset->fences->a[frameset->curFrame], + dfunc->vkWaitForFences (dev, 1, &frameset->fences->a[frameset->curFrame], VK_TRUE, 2000000000); QFV_AcquireNextImage (vulkan_ctx->swapchain, frameset->imageSemaphores->a[frameset->curFrame], @@ -174,7 +175,8 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) double currenTime = Sys_DoubleTime (); double time = currenTime - startTime; startTime = currenTime; - printf ("%d frames in %g s: %g fps \r", count, time, count / time); + printf ("%d frames in %g s: %g fps \r", + count, time, count / time); fflush (stdout); count = 0; } @@ -291,7 +293,13 @@ vulkan_vid_render_choose_visual (void) vulkan_ctx->choose_visual (vulkan_ctx); vulkan_ctx->cmdpool = QFV_CreateCommandPool (vulkan_ctx->device, vulkan_ctx->device->queue.queueFamily, - 0, 0); + 0, 1); + __auto_type cmdset = QFV_AllocateCommandBuffers (vulkan_ctx->device, + vulkan_ctx->cmdpool, + 0, 1); + vulkan_ctx->cmdbuffer = cmdset->a[0]; + free (cmdset); + vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1); Sys_Printf ("vk choose visual %p %p %d %p\n", vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue, vulkan_ctx->device->queue.queueFamily, @@ -309,7 +317,7 @@ vulkan_vid_render_create_context (void) qfv_semaphoreset_t *renderDoneSems = DARRAY_ALLOCFIXED (*renderDoneSems, 2, malloc); for (int i = 0; i < 2; i++) { - fences->a[i]= QFV_CreateFence (vulkan_ctx->device, 1); + fences->a[i] = QFV_CreateFence (vulkan_ctx->device, 1); imageSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device); renderDoneSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device); } @@ -348,6 +356,7 @@ vulkan_vid_render_shutdown (void) df->vkDestroySemaphore (dev, frameset->imageSemaphores->a[i], 0); df->vkDestroySemaphore (dev, frameset->renderDoneSemaphores->a[i], 0); } + df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); Vulkan_Shutdown_Common (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 65f0dcdd3..68decb94a 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -126,6 +126,16 @@ QFV_AllocImageMemory (qfv_device_t *device, return object; } +int +QFV_BindImageMemory (qfv_device_t *device, + VkImage image, VkDeviceMemory object, VkDeviceSize offset) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + VkResult res = dfunc->vkBindImageMemory (dev, image, object, offset); + return res == VK_SUCCESS; +} + qfv_imagebarrierset_t * QFV_CreateImageTransitionSet (qfv_imagetransition_t *transitions, int numTransitions) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 37fe9c564..4d4160caf 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -51,6 +51,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/image.h" #include "QF/Vulkan/swapchain.h" #include "compat.h" @@ -116,6 +117,9 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { + if (ctx->renderpass.colorImage) { + Vulkan_DestroyRenderPass (ctx); + } if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } @@ -151,3 +155,191 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) old_swapchain, 0); } } + +typedef struct { + VkPipelineStageFlags src; + VkPipelineStageFlags dst; +} qfv_pipelinestagepair_t; + +//XXX Note: imageLayoutTransitionBarriers, imageLayoutTransitionStages and +// the enum be kept in sync +enum { + qfv_LT_Undefined_to_TransferDst, + qfv_LT_TransferDst_to_ShaderReadOnly, + qfv_LT_Undefined_to_DepthStencil, + qfv_LT_Undefined_to_Color, +}; + +static VkImageMemoryBarrier imageLayoutTransitionBarriers[] = { + // undefined -> transfer dst optimal + { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + // transfer dst optimal -> shader read only optimal + { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + // undefined -> depth stencil attachment optimal + { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 } + }, + // undefined -> color attachment optimal + { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + { /* end of transition barriers */ } +}; + +static qfv_pipelinestagepair_t imageLayoutTransitionStages[] = { + // undefined -> transfer dst optimal + { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT }, + // transfer dst optimal -> shader read only optimal + { VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, + // undefined -> depth stencil attachment optimal + { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT }, + // undefined -> color attachment optimal + { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }, +}; + +void +Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *df = device->funcs; + VkCommandBuffer cmd = ctx->cmdbuffer; + qfv_swapchain_t *sc = ctx->swapchain; + + qfv_imageresource_t *colorImage = malloc (sizeof (*colorImage)); + qfv_imageresource_t *depthImage = malloc (sizeof (*depthImage)); + + VkExtent3D extent = {sc->extent.width, sc->extent.height, 1}; + + Sys_MaskPrintf (SYS_VULKAN, "color resource\n"); + colorImage->image + = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, + sc->format, extent, 1, 1, + VK_SAMPLE_COUNT_1_BIT, // FIXME + VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT + | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + colorImage->object + = QFV_AllocImageMemory (device, colorImage->image, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); + QFV_BindImageMemory (device, colorImage->image, colorImage->object, 0); + colorImage->view + = QFV_CreateImageView (device, colorImage->image, + VK_IMAGE_VIEW_TYPE_2D, + sc->format, VK_IMAGE_ASPECT_COLOR_BIT); + Sys_MaskPrintf (SYS_VULKAN, " image: %p object: %p view:%p\n", + colorImage->image, colorImage->object, colorImage->view); + + Sys_MaskPrintf (SYS_VULKAN, "depth resource\n"); + VkFormat depthFormat = VK_FORMAT_D32_SFLOAT; + depthImage->image + = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, + depthFormat, extent, 1, 1, + VK_SAMPLE_COUNT_1_BIT, // FIXME (for depth?!?) + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + depthImage->object + = QFV_AllocImageMemory (device, depthImage->image, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); + QFV_BindImageMemory (device, depthImage->image, depthImage->object, 0); + depthImage->view + = QFV_CreateImageView (device, depthImage->image, + VK_IMAGE_VIEW_TYPE_2D, + depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); + Sys_MaskPrintf (SYS_VULKAN, " image: %p object: %p view:%p\n", + depthImage->image, depthImage->object, depthImage->view); + + VkImageMemoryBarrier barrier; + qfv_pipelinestagepair_t stages; + + df->vkWaitForFences (dev, 1, &ctx->fence, VK_TRUE, ~0ul); + df->vkResetCommandBuffer (cmd, 0); + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0, + }; + df->vkBeginCommandBuffer (cmd, &beginInfo); + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_Color]; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_Color]; + barrier.image = colorImage->image; + + df->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, + 0, 0, + 0, 0, + 1, &barrier); + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_DepthStencil]; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_DepthStencil]; + barrier.image = depthImage->image; + if (depthFormat == VK_FORMAT_D32_SFLOAT_S8_UINT + || depthFormat == VK_FORMAT_D24_UNORM_S8_UINT) { + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + + df->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, + 0, 0, + 0, 0, + 1, &barrier); + df->vkEndCommandBuffer (cmd); + + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + 0, 0, 0, + 1, &cmd, + 0, 0 + }; + df->vkResetFences (dev, 1, &ctx->fence); + df->vkQueueSubmit (device->queue.queue, 1, &submitInfo, ctx->fence); + + ctx->renderpass.colorImage = colorImage; + ctx->renderpass.depthImage = depthImage; +} + +void +Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *df = device->funcs; + + df->vkDestroyImageView (dev, ctx->renderpass.colorImage->view, 0); + df->vkDestroyImage (dev, ctx->renderpass.colorImage->image, 0); + df->vkFreeMemory (dev, ctx->renderpass.colorImage->object, 0); + free (ctx->renderpass.colorImage); + ctx->renderpass.colorImage = 0; + + df->vkDestroyImageView (dev, ctx->renderpass.depthImage->view, 0); + df->vkDestroyImage (dev, ctx->renderpass.depthImage->image, 0); + df->vkFreeMemory (dev, ctx->renderpass.depthImage->object, 0); + free (ctx->renderpass.depthImage); + ctx->renderpass.depthImage = 0; +} From ba654b09f7dbe9dbe8b9d1d9311785df9fcbd5f1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Feb 2020 17:18:37 +0900 Subject: [PATCH 0319/3664] Create and destroy render pass and frame buffers --- include/QF/Vulkan/instance.h | 2 + include/QF/Vulkan/qf_vid.h | 2 + include/QF/Vulkan/renderpass.h | 14 +- include/QF/darray.h | 19 +++ include/vid_vulkan.h | 23 +-- libs/video/renderer/vid_render_vulkan.c | 66 +++------ libs/video/renderer/vulkan/instance.c | 15 ++ libs/video/renderer/vulkan/renderpass.c | 25 +--- .../video/renderer/vulkan/vulkan_vid_common.c | 135 +++++++++++++++++- 9 files changed, 212 insertions(+), 89 deletions(-) diff --git a/include/QF/Vulkan/instance.h b/include/QF/Vulkan/instance.h index 0cf5b2226..4df1827c5 100644 --- a/include/QF/Vulkan/instance.h +++ b/include/QF/Vulkan/instance.h @@ -62,4 +62,6 @@ qfv_instance_t *QFV_CreateInstance (struct vulkan_ctx_s *ctx, const char **extensions); void QFV_DestroyInstance (qfv_instance_t *instance); +VkSampleCountFlagBits QFV_GetMaxSampleCount (qfv_physdev_t *physdev); + #endif // __QF_Vulkan_instance_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 26d9d288c..d7ef64a97 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -36,6 +36,8 @@ #include struct vulkan_ctx_s; +void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); +void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index 257441ca1..9a197ac70 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -15,18 +15,8 @@ typedef struct qfv_attachmentreference_s #define QFV_AllocAttachmentReference(num, allocator) \ DARRAY_ALLOCFIXED (qfv_attachmentreference_t, num, allocator) -typedef struct qfv_subpassparameters_s { - VkPipelineBindPoint pipelineBindPoint; - qfv_attachmentreference_t *inputAttachments; - qfv_attachmentreference_t *colorAttachments; - qfv_attachmentreference_t *resolveAttachments; - VkAttachmentReference *depthStencilAttachment; - uint32_t numPreserve; - uint32_t *preserveAttachments; -} qfv_subpassparameters_t; - typedef struct qfv_subpassparametersset_s - DARRAY_TYPE (qfv_subpassparameters_t) qfv_subpassparametersset_t; + DARRAY_TYPE (VkSubpassDescription) qfv_subpassparametersset_t; #define QFV_AllocSubpassParametersSet(num, allocator) \ DARRAY_ALLOCFIXED (qfv_subpassparametersset_t, num, allocator) @@ -49,6 +39,6 @@ QFV_CreateFramebuffer (struct qfv_device_s *device, VkRenderPass renderPass, uint32_t numAttachments, VkImageView *attachments, - uint32_t width, uint32_t height, uint32_t layers); + VkExtent2D, uint32_t layers); #endif//__QF_Vulkan_renderpass_h diff --git a/include/QF/darray.h b/include/QF/darray.h index 7a4484575..9f8c9630b 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -88,6 +88,25 @@ ar; \ }) +/** Initialized the array. + + The array will be initialized to be empty but with grow set to the + specifed value. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param growSize Number of elements by which the array is to grow when + required. + \hideinitializer +*/ +#define DARRAY_INIT(array, growSize) \ + do { \ + __auto_type ar = (array); \ + ar->size = ar->maxSize = 0; \ + ar->grow = (growSize); \ + } while (0) + /** Clear the array. If the array can grow, its backing will be freed and maxSize and a reset, diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index a158f0a77..2675d3036 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -6,19 +6,25 @@ #endif #include -typedef struct vulkan_frameset_s { - int curFrame; // index into fences - struct qfv_fenceset_s *fences; - struct qfv_cmdbufferset_s *cmdBuffers; - struct qfv_semaphoreset_s *imageSemaphores; - struct qfv_semaphoreset_s *renderDoneSemaphores; -} vulkan_frameset_t; +#include "QF/darray.h" typedef struct vulkan_renderpass_s { + VkRenderPass renderpass; struct qfv_imageresource_s *colorImage; struct qfv_imageresource_s *depthImage; } vulkan_renderpass_t; +typedef struct vulkan_framebuffer_s { + VkFramebuffer framebuffer; + VkFence fence; + VkSemaphore imageAvailableSemaphore; + VkSemaphore renderDoneSemaphore; + VkCommandBuffer cmdBuffer; +} vulkan_framebuffer_t; + +typedef struct vulkan_framebufferset_s + DARRAY_TYPE (vulkan_framebuffer_t) vulkan_framebufferset_t; + typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); void (*unload_vulkan) (struct vulkan_ctx_s *ctx); @@ -40,8 +46,9 @@ typedef struct vulkan_ctx_s { VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; VkFence fence; // for ctx->cmdbuffer only - vulkan_frameset_t frameset; vulkan_renderpass_t renderpass; + size_t curFrame; + vulkan_framebufferset_t framebuffers; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 5c0b602d0..ce6863753 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -60,13 +60,11 @@ vulkan_R_Init (void) { qfv_device_t *device = vulkan_ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - qfv_cmdbufferset_t *cmdBuffers; Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); - cmdBuffers = QFV_AllocateCommandBuffers (device, vulkan_ctx->cmdpool, 0, - vulkan_ctx->swapchain->numImages); - vulkan_ctx->frameset.cmdBuffers = cmdBuffers; + Vulkan_CreateFramebuffers (vulkan_ctx); + VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; VkClearColorValue clearColor = { {0.7294, 0.8549, 0.3333, 1.0} }; @@ -96,29 +94,30 @@ vulkan_R_Init (void) 0, // filled in later image_subresource_range }; - for (size_t i = 0; i < cmdBuffers->size; i++) { + for (size_t i = 0; i < vulkan_ctx->framebuffers.size; i++) { + __auto_type framebuffer = &vulkan_ctx->framebuffers.a[i]; pc_barrier.image = vulkan_ctx->swapchain->images->a[i]; cp_barrier.image = vulkan_ctx->swapchain->images->a[i]; - dfunc->vkBeginCommandBuffer (cmdBuffers->a[i], &beginInfo); - dfunc->vkCmdPipelineBarrier (cmdBuffers->a[i], + dfunc->vkBeginCommandBuffer (framebuffer->cmdBuffer, &beginInfo); + dfunc->vkCmdPipelineBarrier (framebuffer->cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, 0, // memory barriers 0, 0, // buffer barriers 1, &pc_barrier); - dfunc->vkCmdClearColorImage (cmdBuffers->a[i], pc_barrier.image, + dfunc->vkCmdClearColorImage (framebuffer->cmdBuffer, pc_barrier.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &image_subresource_range); - dfunc->vkCmdPipelineBarrier (cmdBuffers->a[i], + dfunc->vkCmdPipelineBarrier (framebuffer->cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &cp_barrier); - dfunc->vkEndCommandBuffer (cmdBuffers->a[i]); + dfunc->vkEndCommandBuffer (framebuffer->cmdBuffer); } Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, vulkan_ctx->swapchain->numImages); @@ -138,38 +137,38 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) qfv_devfuncs_t *dfunc = device->funcs; VkDevice dev = device->dev; qfv_queue_t *queue = &vulkan_ctx->device->queue; - vulkan_frameset_t *frameset = &vulkan_ctx->frameset; - dfunc->vkWaitForFences (dev, 1, &frameset->fences->a[frameset->curFrame], - VK_TRUE, 2000000000); + __auto_type framebuffer + = &vulkan_ctx->framebuffers.a[vulkan_ctx->curFrame]; + + dfunc->vkWaitForFences (dev, 1, &framebuffer->fence, VK_TRUE, 2000000000); QFV_AcquireNextImage (vulkan_ctx->swapchain, - frameset->imageSemaphores->a[frameset->curFrame], - 0, &imageIndex); + framebuffer->imageAvailableSemaphore, + 0, &imageIndex); VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, 1, - &frameset->imageSemaphores->a[frameset->curFrame], + &framebuffer->imageAvailableSemaphore, &waitStage, - 1, &frameset->cmdBuffers->a[imageIndex], - 1, &frameset->renderDoneSemaphores->a[frameset->curFrame], + 1, &framebuffer->cmdBuffer, + 1, &framebuffer->renderDoneSemaphore, }; - dfunc->vkResetFences (dev, 1, &frameset->fences->a[frameset->curFrame]); - dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, - frameset->fences->a[frameset->curFrame]); + dfunc->vkResetFences (dev, 1, &framebuffer->fence); + dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, framebuffer->fence); VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, - 1, &frameset->renderDoneSemaphores->a[frameset->curFrame], + 1, &framebuffer->renderDoneSemaphore, 1, &vulkan_ctx->swapchain->swapchain, &imageIndex, 0 }; dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); - frameset->curFrame++; - frameset->curFrame %= frameset->fences->size; + vulkan_ctx->curFrame++; + vulkan_ctx->curFrame %= vulkan_ctx->framebuffers.size; if (++count >= 100) { double currenTime = Sys_DoubleTime (); @@ -311,19 +310,6 @@ vulkan_vid_render_create_context (void) { vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); - vulkan_ctx->frameset.curFrame = 0; - qfv_fenceset_t *fences = DARRAY_ALLOCFIXED (*fences, 2, malloc); - qfv_semaphoreset_t *imageSems = DARRAY_ALLOCFIXED (*imageSems, 2, malloc); - qfv_semaphoreset_t *renderDoneSems = DARRAY_ALLOCFIXED (*renderDoneSems, 2, - malloc); - for (int i = 0; i < 2; i++) { - fences->a[i] = QFV_CreateFence (vulkan_ctx->device, 1); - imageSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device); - renderDoneSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device); - } - vulkan_ctx->frameset.fences = fences; - vulkan_ctx->frameset.imageSemaphores = imageSems; - vulkan_ctx->frameset.renderDoneSemaphores = renderDoneSems; Sys_Printf ("vk create context %p\n", vulkan_ctx->surface); } @@ -350,12 +336,6 @@ vulkan_vid_render_shutdown (void) qfv_devfuncs_t *df = device->funcs; VkDevice dev = device->dev; QFV_DeviceWaitIdle (device); - vulkan_frameset_t *frameset = &vulkan_ctx->frameset; - for (size_t i = 0; i < frameset->fences->size; i++) { - df->vkDestroyFence (dev, frameset->fences->a[i], 0); - df->vkDestroySemaphore (dev, frameset->imageSemaphores->a[i], 0); - df->vkDestroySemaphore (dev, frameset->renderDoneSemaphores->a[i], 0); - } df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); Vulkan_Shutdown_Common (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index 234236014..4d23b5a75 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -36,6 +36,7 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/input.h" +#include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" #include "QF/sys.h" @@ -284,3 +285,17 @@ QFV_DestroyInstance (qfv_instance_t *instance) instance->funcs->vkDestroyInstance (instance->instance, 0); free (instance); } + +VkSampleCountFlagBits +QFV_GetMaxSampleCount (qfv_physdev_t *physdev) +{ + VkSampleCountFlagBits maxSamples = VK_SAMPLE_COUNT_64_BIT; + VkSampleCountFlagBits counts; + counts = min (physdev->properties.limits.framebufferColorSampleCounts, + physdev->properties.limits.framebufferDepthSampleCounts); + while (maxSamples && maxSamples > counts) { + maxSamples >>= 1; + } + Sys_MaskPrintf (SYS_VULKAN, "Max samples: %x\n", maxSamples); + return maxSamples; +} diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 60e279e18..e61005278 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -71,29 +71,10 @@ QFV_CreateRenderPass (qfv_device_t *device, VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - VkSubpassDescription *subpasses = alloca (subpassparams->size - * sizeof (*subpasses)); - - for (uint32_t i = 0; i < subpassparams->size; i++) { - qfv_subpassparameters_t *params = &subpassparams->a[i]; - subpasses[i].flags = 0; - subpasses[i].pipelineBindPoint = params->pipelineBindPoint; - subpasses[i].inputAttachmentCount = params->inputAttachments->size; - subpasses[i].pInputAttachments = params->inputAttachments->a; - subpasses[i].colorAttachmentCount = params->colorAttachments->size; - subpasses[i].pColorAttachments = params->colorAttachments->a; - if (params->resolveAttachments) { - subpasses[i].pResolveAttachments = params->resolveAttachments->a; - } - subpasses[i].pDepthStencilAttachment = params->depthStencilAttachment; - subpasses[i].preserveAttachmentCount = params->numPreserve; - subpasses[i].pPreserveAttachments = params->preserveAttachments; - } - VkRenderPassCreateInfo createInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 0, 0, attachments->size, attachments->a, - subpassparams->size, subpasses, + subpassparams->size, subpassparams->a, dependencies->size, dependencies->a, }; @@ -105,7 +86,7 @@ QFV_CreateRenderPass (qfv_device_t *device, VkFramebuffer QFV_CreateFramebuffer (qfv_device_t *device, VkRenderPass renderPass, uint32_t numAttachments, VkImageView *attachments, - uint32_t width, uint32_t height, uint32_t layers) + VkExtent2D extent, uint32_t layers) { VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; @@ -113,7 +94,7 @@ QFV_CreateFramebuffer (qfv_device_t *device, VkRenderPass renderPass, VkFramebufferCreateInfo createInfo = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 0, 0, renderPass, numAttachments, attachments, - width, height, layers, + extent.width, extent.height, layers, }; VkFramebuffer framebuffer; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 4d4160caf..151f6ea55 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -50,8 +50,10 @@ #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/command.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/swapchain.h" #include "compat.h" @@ -117,6 +119,9 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { + if (ctx->framebuffers.size) { + Vulkan_DestroyFramebuffers (ctx); + } if (ctx->renderpass.colorImage) { Vulkan_DestroyRenderPass (ctx); } @@ -241,11 +246,13 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) VkExtent3D extent = {sc->extent.width, sc->extent.height, 1}; + VkSampleCountFlagBits msaaSamples + = QFV_GetMaxSampleCount (device->physDev); + Sys_MaskPrintf (SYS_VULKAN, "color resource\n"); colorImage->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - sc->format, extent, 1, 1, - VK_SAMPLE_COUNT_1_BIT, // FIXME + sc->format, extent, 1, 1, msaaSamples, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); colorImage->object @@ -263,8 +270,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) VkFormat depthFormat = VK_FORMAT_D32_SFLOAT; depthImage->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - depthFormat, extent, 1, 1, - VK_SAMPLE_COUNT_1_BIT, // FIXME (for depth?!?) + depthFormat, extent, 1, 1, msaaSamples, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); depthImage->object = QFV_AllocImageMemory (device, depthImage->image, @@ -322,6 +328,72 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) ctx->renderpass.colorImage = colorImage; ctx->renderpass.depthImage = depthImage; + + __auto_type attachments = QFV_AllocAttachmentDescription (3, alloca); + __auto_type attachmentRefs = QFV_AllocAttachmentReference (3, alloca); + + // color attachment + attachments->a[0].flags = 0; + attachments->a[0].format = sc->format; + attachments->a[0].samples = msaaSamples; + attachments->a[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments->a[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments->a[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments->a[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments->a[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachments->a[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachmentRefs->a[0].attachment = 0; + attachmentRefs->a[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + // depth attachment + attachments->a[1].flags = 0; + attachments->a[1].format = depthFormat; + attachments->a[1].samples = msaaSamples; + attachments->a[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments->a[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments->a[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments->a[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments->a[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachments->a[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachmentRefs->a[1].attachment = 1; + attachmentRefs->a[1].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + // resolve attachment + attachments->a[2].flags = 0; + attachments->a[2].format = sc->format; + attachments->a[2].samples = VK_SAMPLE_COUNT_1_BIT; + attachments->a[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments->a[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments->a[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments->a[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments->a[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + attachments->a[2].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + attachmentRefs->a[2].attachment = 2; + attachmentRefs->a[2].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + __auto_type subpasses = QFV_AllocSubpassParametersSet (1, alloca); + subpasses->a[0].flags = 0; + subpasses->a[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpasses->a[0].inputAttachmentCount = 0; + subpasses->a[0].pInputAttachments = 0; + subpasses->a[0].colorAttachmentCount = 1; + subpasses->a[0].pColorAttachments = &attachmentRefs->a[0]; + subpasses->a[0].pResolveAttachments = &attachmentRefs->a[2]; + subpasses->a[0].pDepthStencilAttachment = &attachmentRefs->a[1]; + subpasses->a[0].preserveAttachmentCount = 0; + subpasses->a[0].pPreserveAttachments = 0; + + __auto_type depenencies = QFV_AllocSubpassDependencies (1, alloca); + depenencies->a[0].srcSubpass = VK_SUBPASS_EXTERNAL; + depenencies->a[0].dstSubpass = 0; + depenencies->a[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + depenencies->a[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + depenencies->a[0].srcAccessMask = 0; + depenencies->a[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + depenencies->a[0].dependencyFlags = 0; + + ctx->renderpass.renderpass = QFV_CreateRenderPass (device, attachments, + subpasses, depenencies); } void @@ -331,6 +403,8 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) VkDevice dev = device->dev; qfv_devfuncs_t *df = device->funcs; + df->vkDestroyRenderPass (dev, ctx->renderpass.renderpass, 0); + df->vkDestroyImageView (dev, ctx->renderpass.colorImage->view, 0); df->vkDestroyImage (dev, ctx->renderpass.colorImage->image, 0); df->vkFreeMemory (dev, ctx->renderpass.colorImage->object, 0); @@ -343,3 +417,56 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) free (ctx->renderpass.depthImage); ctx->renderpass.depthImage = 0; } + +void +Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + VkCommandPool cmdpool = ctx->cmdpool; + qfv_swapchain_t *sc = ctx->swapchain; + VkRenderPass renderpass = ctx->renderpass.renderpass; + + if (!ctx->framebuffers.grow) { + DARRAY_INIT (&ctx->framebuffers, 4); + } + + DARRAY_RESIZE (&ctx->framebuffers, sc->numImages); + + __auto_type attachments = DARRAY_ALLOCFIXED (qfv_imageviewset_t, 3, + alloca); + attachments->a[0] = ctx->renderpass.colorImage->view; + attachments->a[1] = ctx->renderpass.depthImage->view; + + __auto_type cmdBuffers + = QFV_AllocateCommandBuffers (device, cmdpool, 0, + ctx->framebuffers.size); + + for (size_t i = 0; i < ctx->framebuffers.size; i++) { + attachments->a[2] = sc->imageViews->a[i]; + __auto_type frame = &ctx->framebuffers.a[i]; + frame->framebuffer = QFV_CreateFramebuffer (device, renderpass, + attachments->size, + attachments->a, + sc->extent, 1); + frame->fence = QFV_CreateFence (device, 1); + frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); + frame->renderDoneSemaphore = QFV_CreateSemaphore (device); + frame->cmdBuffer = cmdBuffers->a[i]; + } +} + +void +Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *df = device->funcs; + VkDevice dev = device->dev; + + for (size_t i = 0; i < ctx->framebuffers.size; i++) { + __auto_type frame = &ctx->framebuffers.a[i]; + df->vkDestroyFence (dev, frame->fence, 0); + df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0); + df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); + df->vkDestroyFramebuffer (dev, frame->framebuffer, 0); + } +} From 0a0035e5e5e7771e28563684dbea1d34f2043e55 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Feb 2020 17:48:22 +0900 Subject: [PATCH 0320/3664] Use the render pass to clear the window Very satisfying to get to this point. --- libs/video/renderer/vid_render_vulkan.c | 63 +++++-------------- .../video/renderer/vulkan/vulkan_vid_common.c | 4 +- 2 files changed, 20 insertions(+), 47 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index ce6863753..85181547c 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -65,58 +65,29 @@ vulkan_R_Init (void) Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_CreateFramebuffers (vulkan_ctx); + qfv_swapchain_t *sc = vulkan_ctx->swapchain; + VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - VkClearColorValue clearColor = { {0.7294, 0.8549, 0.3333, 1.0} }; - VkImageSubresourceRange image_subresource_range = { - VK_IMAGE_ASPECT_COLOR_BIT, - 0, 1, 0, 1, + VkClearValue clearValues[3] = { + { { {0.7294, 0.8549, 0.3333, 1.0} } }, + { { {1.0, 0.0} } }, + { { {0, 0, 0, 0} } }, + }; + VkRenderPassBeginInfo renderPassInfo = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, + vulkan_ctx->renderpass.renderpass, 0, + { {0, 0}, sc->extent }, + 2, clearValues }; - VkImageMemoryBarrier pc_barrier = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_MEMORY_READ_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - device->queue.queueFamily, - device->queue.queueFamily, - 0, // filled in later - image_subresource_range - }; - VkImageMemoryBarrier cp_barrier = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_MEMORY_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - device->queue.queueFamily, - device->queue.queueFamily, - 0, // filled in later - image_subresource_range - }; for (size_t i = 0; i < vulkan_ctx->framebuffers.size; i++) { __auto_type framebuffer = &vulkan_ctx->framebuffers.a[i]; - pc_barrier.image = vulkan_ctx->swapchain->images->a[i]; - cp_barrier.image = vulkan_ctx->swapchain->images->a[i]; dfunc->vkBeginCommandBuffer (framebuffer->cmdBuffer, &beginInfo); - dfunc->vkCmdPipelineBarrier (framebuffer->cmdBuffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, - 0, 0, // memory barriers - 0, 0, // buffer barriers - 1, &pc_barrier); - dfunc->vkCmdClearColorImage (framebuffer->cmdBuffer, pc_barrier.image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - &clearColor, 1, - &image_subresource_range); - dfunc->vkCmdPipelineBarrier (framebuffer->cmdBuffer, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, 0, - 0, 0, - 1, &cp_barrier); + renderPassInfo.framebuffer = framebuffer->framebuffer; + dfunc->vkCmdBeginRenderPass (framebuffer->cmdBuffer, &renderPassInfo, + VK_SUBPASS_CONTENTS_INLINE); + + dfunc->vkCmdEndRenderPass (framebuffer->cmdBuffer); dfunc->vkEndCommandBuffer (framebuffer->cmdBuffer); } Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 151f6ea55..882aede78 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -362,7 +362,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) attachments->a[2].flags = 0; attachments->a[2].format = sc->format; attachments->a[2].samples = VK_SAMPLE_COUNT_1_BIT; - attachments->a[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachments->a[2].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments->a[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attachments->a[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attachments->a[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; @@ -469,4 +469,6 @@ Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); df->vkDestroyFramebuffer (dev, frame->framebuffer, 0); } + + DARRAY_CLEAR (&ctx->framebuffers); } From c740dea2120d24723c97efc84f80e5fd43a40427 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Feb 2020 19:44:40 +0900 Subject: [PATCH 0321/3664] Use the correct constant for "infinity" --- libs/video/renderer/vulkan/vulkan_vid_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 882aede78..452a74eb8 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -286,7 +286,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) VkImageMemoryBarrier barrier; qfv_pipelinestagepair_t stages; - df->vkWaitForFences (dev, 1, &ctx->fence, VK_TRUE, ~0ul); + df->vkWaitForFences (dev, 1, &ctx->fence, VK_TRUE, ~0ull); df->vkResetCommandBuffer (cmd, 0); VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, From 264c4ccdacff051bffca85f1a97e5ca0907b048c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Feb 2020 21:18:03 +0900 Subject: [PATCH 0322/3664] Sanitize descriptors I'm sure it will end soon, I think pipelines is the end of it. --- include/QF/Vulkan/descriptor.h | 144 +++++------------- libs/video/renderer/vulkan/descriptor.c | 193 +++--------------------- libs/video/renderer/vulkan/pipeline.c | 12 +- 3 files changed, 63 insertions(+), 286 deletions(-) diff --git a/include/QF/Vulkan/descriptor.h b/include/QF/Vulkan/descriptor.h index 48a1cd92d..6dd09bff4 100644 --- a/include/QF/Vulkan/descriptor.h +++ b/include/QF/Vulkan/descriptor.h @@ -1,132 +1,62 @@ #ifndef __QF_Vulkan_descriptor_h #define __QF_Vulkan_descriptor_h -typedef struct qfv_sampler_s { - struct qfv_device_s *device; - VkSampler sampler; -} qfv_sampler_t; +#include "QF/darray.h" -typedef struct qfv_bindingset_s { - int numBindings; - VkDescriptorSetLayoutBinding bindings[]; -} qfv_bindingset_t; +typedef struct qfv_bindingset_s + DARRAY_TYPE (VkDescriptorSetLayoutBinding) qfv_bindingset_t; -typedef struct qfv_descriptorsetlayout_s { - struct qfv_device_s *device; - VkDescriptorSetLayout layout; -} qfv_descriptorsetlayout_t; - -typedef struct qfv_descriptorsetlayoutset_s { - uint32_t numLayouts; - qfv_descriptorsetlayout_t *layouts[]; -} qfv_descriptorsetlayoutset_t; +typedef struct qfv_descriptorsetlayoutset_s + DARRAY_TYPE (VkDescriptorSetLayout) qfv_descriptorsetlayoutset_t; #define QFV_AllocDescriptorSetLayoutSet(num, allocator) \ - allocator (field_offset (qfv_descriptorsetlayoutset_t, layouts[num])) + DARRAY_ALLOCFIXED (qfv_descriptorsetlayoutset_t, num, allocator) +typedef struct qfv_descriptorsets_s + DARRAY_TYPE (VkDescriptorSet) qfv_descriptorsets_t; -typedef struct qfv_descriptorpool_s { - struct qfv_device_s *device; - VkDescriptorPool pool; -} qfv_descriptorpool_t; +#define QFV_AllocDescriptorSets(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_descriptorsets_t, num, allocator) -typedef struct qfv_descriptorset_s { - struct qfv_device_s *device; - qfv_descriptorpool_t *pool; - VkDescriptorSet set; -} qfv_descriptorset_t; +typedef struct qfv_writedescriptorsets_s + DARRAY_TYPE (VkWriteDescriptorSet) qfv_writedescriptorsets_t; -typedef struct qfv_imagedescriptorinfo_s { - qfv_descriptorset_t *descriptorset; - uint32_t binding; - uint32_t arrayElement; - VkDescriptorType type; - uint32_t numInfo; - VkDescriptorImageInfo infos[]; -} qfv_imagedescriptorinfo_t; +#define QFV_AllocWriteDescriptorSets(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_writedescriptorsets_t, num, allocator) -typedef struct qfv_bufferdescriptorinfo_s { - qfv_descriptorset_t *descriptorset; - uint32_t binding; - uint32_t arrayElement; - VkDescriptorType type; - uint32_t numInfo; - VkDescriptorBufferInfo infos[]; -} qfv_bufferdescriptorinfo_t; +typedef struct qfv_copydescriptorsets_s + DARRAY_TYPE (VkCopyDescriptorSet) qfv_copydescriptorsets_t; -typedef struct qfv_texelbufferdescriptorinfo_s { - qfv_descriptorset_t *descriptorset; - uint32_t binding; - uint32_t arrayElement; - VkDescriptorType type; - uint32_t numInfo; - VkBufferView infos[]; -} qfv_texelbufferdescriptorinfo_t; +#define QFV_AllocCopyDescriptorSets(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_descriptorsetlayoutset_t, num, allocator) -typedef struct qfv_copydescriptorinfo_s { - qfv_descriptorset_t *dstSet; - uint32_t dstBinding; - uint32_t dstArrayElement; - qfv_descriptorset_t *srcSet; - uint32_t srcBinding; - uint32_t srcArrayElement; - uint32_t descriptorCount; -} qfv_copydescriptorinfo_t; +struct qfv_device_s; -qfv_sampler_t *QFV_CreateSampler (struct qfv_device_s *device, - VkFilter magFilter, VkFilter minFilter, - VkSamplerMipmapMode mipmapMode, - VkSamplerAddressMode addressModeU, - VkSamplerAddressMode addressModeV, - VkSamplerAddressMode addressModeW, - float mipLodBias, - VkBool32 anisotryEnable, float maxAnisotropy, - VkBool32 compareEnable, VkCompareOp compareOp, - float minLod, float maxLod, - VkBorderColor borderColor, - VkBool32 unnormalizedCoordinates); +VkSampler QFV_CreateSampler (struct qfv_device_s *device, + VkFilter magFilter, VkFilter minFilter, + VkSamplerMipmapMode mipmapMode, + VkSamplerAddressMode addressModeU, + VkSamplerAddressMode addressModeV, + VkSamplerAddressMode addressModeW, + float mipLodBias, + VkBool32 anisotryEnable, float maxAnisotropy, + VkBool32 compareEnable, VkCompareOp compareOp, + float minLod, float maxLod, + VkBorderColor borderColor, + VkBool32 unnormalizedCoordinates); -qfv_bindingset_t *QFV_CreateBindingSet (int numBindings); -void QFV_DestroyBindingSet (qfv_bindingset_t *bindingset); - -qfv_descriptorsetlayout_t * +VkDescriptorSetLayout QFV_CreateDescriptorSetLayout (struct qfv_device_s *device, qfv_bindingset_t *bindings); -qfv_descriptorpool_t * +VkDescriptorPool QFV_CreateDescriptorPool (struct qfv_device_s *device, VkDescriptorPoolCreateFlags flags, uint32_t maxSets, qfv_bindingset_t *bindings); -qfv_descriptorset_t * -QFV_AllocateDescriptorSet (qfv_descriptorpool_t *pool, - qfv_descriptorsetlayout_t *layout); - -#define QFV_allocateinfo(type, num, allocator) \ - allocator (field_offset (type, infos[num])) -#define QFV_ImageDescriptorInfo(num, allocator) \ - QFV_allocateinfo(qfv_imagedescriptorinfo_t, num, allocator) -#define QFV_BufferDescriptorInfo(num, allocator) \ - QFV_allocateinfo(qfv_bufferdescriptorinfo_t, num, allocator) -#define QFV_TexelBufferDescriptorInfo(num, allocator) \ - QFV_allocateinfo(qfv_texelbufferdescriptorinfo_t, num, allocator) - -void -QFV_UpdateDescriptorSets (struct qfv_device_s *device, - uint32_t numImageInfos, - qfv_imagedescriptorinfo_t *imageInfos, - uint32_t numBufferInfos, - qfv_bufferdescriptorinfo_t *bufferInfos, - uint32_t numTexelBufferInfos, - qfv_texelbufferdescriptorinfo_t *texelbufferInfos, - uint32_t numCopyInfos, - qfv_copydescriptorinfo_t *copyInfos); - -void QFV_FreeDescriptorSet (qfv_descriptorset_t *set); -void QFV_ResetDescriptorPool (qfv_descriptorpool_t *pool); -void QFV_DestroyDescriptorPool (qfv_descriptorpool_t *pool); -void QFV_DestroyDescriptorSetLayout (qfv_descriptorsetlayout_t *layout); -void QFV_DestroySampler (qfv_sampler_t *sampler); - +qfv_descriptorsets_t * +QFV_AllocateDescriptorSet (struct qfv_device_s *device, + VkDescriptorPool pool, + qfv_descriptorsetlayoutset_t *layouts); #endif//__QF_Vulkan_descriptor_h diff --git a/libs/video/renderer/vulkan/descriptor.c b/libs/video/renderer/vulkan/descriptor.c index cc9cce6d4..7610a8fd9 100644 --- a/libs/video/renderer/vulkan/descriptor.c +++ b/libs/video/renderer/vulkan/descriptor.c @@ -61,7 +61,7 @@ #include "util.h" -qfv_sampler_t * +VkSampler QFV_CreateSampler (qfv_device_t *device, VkFilter magFilter, VkFilter minFilter, VkSamplerMipmapMode mipmapMode, @@ -90,29 +90,12 @@ QFV_CreateSampler (qfv_device_t *device, borderColor, unnormalizedCoordinates, }; - qfv_sampler_t *sampler = malloc (sizeof (*sampler)); - sampler->device = device; - dfunc->vkCreateSampler (dev, &createInfo, 0, &sampler->sampler); + VkSampler sampler; + dfunc->vkCreateSampler (dev, &createInfo, 0, &sampler); return sampler; } -qfv_bindingset_t * -QFV_CreateBindingSet (int numBindings) -{ - qfv_bindingset_t *bindingset; - bindingset = malloc (field_offset (qfv_bindingset_t, - bindings[numBindings])); - bindingset->numBindings = numBindings; - return bindingset; -} - -void -QFV_DestroyBindingSet (qfv_bindingset_t *bindingset) -{ - free (bindingset); -} - -qfv_descriptorsetlayout_t * +VkDescriptorSetLayout QFV_CreateDescriptorSetLayout (qfv_device_t *device, qfv_bindingset_t *bindingset) { @@ -122,12 +105,11 @@ QFV_CreateDescriptorSetLayout (qfv_device_t *device, VkDescriptorSetLayoutCreateInfo createInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 0, 0, - bindingset->numBindings, bindingset->bindings, + bindingset->size, bindingset->a, }; - qfv_descriptorsetlayout_t *layout = malloc (sizeof (layout)); - layout->device = device; - dfunc->vkCreateDescriptorSetLayout (dev, &createInfo, 0, &layout->layout); + VkDescriptorSetLayout layout; + dfunc->vkCreateDescriptorSetLayout (dev, &createInfo, 0, &layout); return layout; } @@ -151,7 +133,7 @@ poolsize_compmare (const void *ele1, const void *ele2, void *unused) } //FIXME not thread-safe -qfv_descriptorpool_t * +VkDescriptorPool QFV_CreateDescriptorPool (qfv_device_t *device, VkDescriptorPoolCreateFlags flags, uint32_t maxSets, qfv_bindingset_t *bindings) @@ -170,8 +152,8 @@ QFV_CreateDescriptorPool (qfv_device_t *device, poolsize_next = poolsize_pool; VkDescriptorPoolSize *ps; - for (int i = 0; i < bindings->numBindings; i++) { - VkDescriptorPoolSize test = { bindings->bindings[i].descriptorType, 0 }; + for (size_t i = 0; i < bindings->size; i++) { + VkDescriptorPoolSize test = { bindings->a[i].descriptorType, 0 }; ps = Hash_FindElement (poolsizes, &test); if (!ps) { ps = poolsize_next++; @@ -183,7 +165,7 @@ QFV_CreateDescriptorPool (qfv_device_t *device, } //XXX is descriptorCount correct? //FIXME assumes only one layout is used with this pool - ps->descriptorCount += bindings->bindings[i].descriptorCount * maxSets; + ps->descriptorCount += bindings->a[i].descriptorCount * maxSets; } VkDescriptorPoolCreateInfo createInfo = { @@ -191,155 +173,26 @@ QFV_CreateDescriptorPool (qfv_device_t *device, flags, maxSets, poolsize_next - poolsize_pool, poolsize_pool, }; - qfv_descriptorpool_t *descriptorpool = malloc (sizeof (descriptorpool)); - descriptorpool->device = device; - dfunc->vkCreateDescriptorPool (dev, &createInfo, 0, &descriptorpool->pool); - return descriptorpool; + VkDescriptorPool pool; + dfunc->vkCreateDescriptorPool (dev, &createInfo, 0, &pool); + return pool; } -qfv_descriptorset_t * -QFV_AllocateDescriptorSet (qfv_descriptorpool_t *pool, - qfv_descriptorsetlayout_t *layout) +qfv_descriptorsets_t * +QFV_AllocateDescriptorSet (qfv_device_t *device, + VkDescriptorPool pool, + qfv_descriptorsetlayoutset_t *layouts) { - qfv_device_t *device = pool->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; VkDescriptorSetAllocateInfo allocateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 0, - pool->pool, 1, &layout->layout, + pool, layouts->size, layouts->a, }; - qfv_descriptorset_t *descriptorset = malloc (sizeof (*descriptorset)); - descriptorset->device = device; - descriptorset->pool = pool; - dfunc->vkAllocateDescriptorSets (dev, &allocateInfo, &descriptorset->set); - return descriptorset; -} - -void -QFV_UpdateDescriptorSets (qfv_device_t *device, - uint32_t numImageInfos, - qfv_imagedescriptorinfo_t *imageInfos, - uint32_t numBufferInfos, - qfv_bufferdescriptorinfo_t *bufferInfos, - uint32_t numTexelBufferInfos, - qfv_texelbufferdescriptorinfo_t *texelbufferInfos, - uint32_t numCopyInfos, - qfv_copydescriptorinfo_t *copyInfos) -{ - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - uint32_t numWrite = 0; - numWrite += numImageInfos; - numWrite += numBufferInfos; - numWrite += numTexelBufferInfos; - VkWriteDescriptorSet *writeSets = alloca (numWrite * sizeof (*writeSets)); - VkWriteDescriptorSet *writeSet = writeSets; - for (uint32_t i = 0; i < numImageInfos; i++, writeSet++) { - writeSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeSet->pNext = 0; - writeSet->dstSet = imageInfos[i].descriptorset->set; - writeSet->dstBinding = imageInfos[i].binding; - writeSet->dstArrayElement = imageInfos[i].arrayElement; - writeSet->descriptorCount = imageInfos[i].numInfo; - writeSet->descriptorType = imageInfos[i].type; - writeSet->pImageInfo = imageInfos[i].infos; - writeSet->pBufferInfo = 0; - writeSet->pTexelBufferView = 0; - } - for (uint32_t i = 0; i < numBufferInfos; i++, writeSet++) { - writeSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeSet->pNext = 0; - writeSet->dstSet = bufferInfos[i].descriptorset->set; - writeSet->dstBinding = bufferInfos[i].binding; - writeSet->dstArrayElement = bufferInfos[i].arrayElement; - writeSet->descriptorCount = bufferInfos[i].numInfo; - writeSet->descriptorType = bufferInfos[i].type; - writeSet->pImageInfo = 0; - writeSet->pBufferInfo = bufferInfos[i].infos; - writeSet->pTexelBufferView = 0; - } - for (uint32_t i = 0; i < numTexelBufferInfos; i++, writeSet++) { - writeSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writeSet->pNext = 0; - writeSet->dstSet = bufferInfos[i].descriptorset->set; - writeSet->dstBinding = texelbufferInfos[i].binding; - writeSet->dstArrayElement = texelbufferInfos[i].arrayElement; - writeSet->descriptorCount = texelbufferInfos[i].numInfo; - writeSet->descriptorType = texelbufferInfos[i].type; - writeSet->pImageInfo = 0; - writeSet->pBufferInfo = 0; - writeSet->pTexelBufferView = texelbufferInfos[i].infos; - } - VkCopyDescriptorSet *copySets = alloca (numWrite * sizeof (*copySets)); - VkCopyDescriptorSet *copySet = copySets; - for (uint32_t i = 0; i < numCopyInfos; i++, copySet++) { - copySet->sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET; - copySet->pNext = 0; - copySet->srcSet = copyInfos[i].srcSet->set; - copySet->srcBinding = copyInfos[i].srcBinding; - copySet->srcArrayElement = copyInfos[i].srcArrayElement; - copySet->dstSet = copyInfos[i].dstSet->set; - copySet->dstBinding = copyInfos[i].dstBinding; - copySet->dstArrayElement = copyInfos[i].dstArrayElement; - copySet->descriptorCount = copyInfos[i].descriptorCount; - } - dfunc->vkUpdateDescriptorSets (dev, numWrite, writeSets, - numCopyInfos, copySets); -} - -void -QFV_FreeDescriptorSet (qfv_descriptorset_t *set) -{ - qfv_device_t *device = set->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - VkDescriptorPool pool = set->pool->pool; - - dfunc->vkFreeDescriptorSets (dev, pool, 1, &set->set); -} - -void -QFV_ResetDescriptorPool (qfv_descriptorpool_t *pool) -{ - qfv_device_t *device = pool->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkResetDescriptorPool (dev, pool->pool, 0); -} - -void -QFV_DestroyDescriptorPool (qfv_descriptorpool_t *pool) -{ - qfv_device_t *device = pool->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyDescriptorPool (dev, pool->pool, 0); - free (pool); -} - -void -QFV_DestroyDescriptorSetLayout (qfv_descriptorsetlayout_t *layout) -{ - qfv_device_t *device = layout->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyDescriptorSetLayout (dev, layout->layout, 0); - free (layout); -} - -void -QFV_DestroySampler (qfv_sampler_t *sampler) -{ - qfv_device_t *device = sampler->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroySampler (dev, sampler->sampler, 0); - free (sampler); + __auto_type descriptorsets + = QFV_AllocDescriptorSets (layouts->size, malloc); + dfunc->vkAllocateDescriptorSets (dev, &allocateInfo, descriptorsets->a); + return descriptorsets; } diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c index 0dd5f260e..18babb115 100644 --- a/libs/video/renderer/vulkan/pipeline.c +++ b/libs/video/renderer/vulkan/pipeline.c @@ -154,22 +154,16 @@ QFV_DestroyPipelineCache (qfv_pipelinecache_t *cache) qfv_pipelinelayout_t * QFV_CreatePipelineLayout (qfv_device_t *device, - qfv_descriptorsetlayoutset_t *layoutset, + qfv_descriptorsetlayoutset_t *layouts, qfv_pushconstantrangeset_t *pushConstants) { VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - uint32_t numLayouts = layoutset->numLayouts; - VkDescriptorSetLayout *layouts = alloca (numLayouts * sizeof (*layouts)); - - for (uint32_t i = 0; i < numLayouts; i++) { - layouts[i] = layoutset->layouts[i]->layout; - } - VkPipelineLayoutCreateInfo createInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 0, 0, - numLayouts, layouts, pushConstants->numRanges, pushConstants->ranges, + layouts->size, layouts->a, + pushConstants->numRanges, pushConstants->ranges, }; qfv_pipelinelayout_t *layout = malloc (sizeof (layout)); From ad175d054bfb2fb3cd11b3018deb2d5a8ceb5803 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Feb 2020 22:38:01 +0900 Subject: [PATCH 0323/3664] Sanitize pipelines wow, talk about doing things the wrong way. I guess that's the problem with following a book targeted for C++: you get all that safety-goat nonsense. --- include/QF/Vulkan/pipeline.h | 164 +++-------- libs/video/renderer/vulkan/pipeline.c | 403 ++------------------------ 2 files changed, 68 insertions(+), 499 deletions(-) diff --git a/include/QF/Vulkan/pipeline.h b/include/QF/Vulkan/pipeline.h index 2120e2317..f77585217 100644 --- a/include/QF/Vulkan/pipeline.h +++ b/include/QF/Vulkan/pipeline.h @@ -3,23 +3,11 @@ #include "QF/darray.h" -typedef struct qfv_shadermodule_s { - struct qfv_device_s *device; - VkShaderModule module; -} qfv_shadermodule_t; +typedef struct qfv_pipelineshaderstateset_s + DARRAY_TYPE (VkPipelineShaderStageCreateInfo) qfv_pipelineshaderstateset_s; -typedef struct qfv_shaderstageparams_s { - VkShaderStageFlagBits stageFlags; - qfv_shadermodule_t *module; - const char *entryPointName; - const VkSpecializationInfo *specializationInfo; -} qfv_shaderstageparams_t; - -typedef struct qfv_shaderstageparamsset_s - DARRAY_TYPE (qfv_shaderstageparams_t) qfv_shaderstageparamsset_t; - -#define QFV_AllocShaderParamsSet(num, allocator) \ - DARRAY_ALLOCFIXED (qfv_shaderstageparamsset_t, num, allocator) +#define QFV_AllocPipelineShaderStageSet(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_pipelineshaderstateset_s, num, allocator) typedef struct qfv_vertexinputbindingset_s DARRAY_TYPE (VkVertexInputBindingDescription) qfv_vertexinputbindingset_t; @@ -48,21 +36,15 @@ typedef struct qfv_pipelinetessellation_s { uint32_t patchControlPoints; } qfv_pipelinetessellation_t; -typedef struct qfv_viewportset_s { - uint32_t numViewports; - VkViewport viewports[]; -} qfv_viewportset_t; +typedef struct qfv_viewportset_s DARRAY_TYPE (VkViewport) qfv_viewportset_t; #define QFV_AllocViewportSet(num, allocator) \ - allocator (field_offset (qfv_viewportset_t, viewports[num])) + DARRAY_ALLOCFIXED (qfv_viewportset_t, num, allocator) -typedef struct qfv_scissorsset_s { - uint32_t numScissors; - VkRect2D scissors[]; -} qfv_scissorsset_t; +typedef struct qfv_scissorsset_s DARRAY_TYPE (VkRect2D) qfv_scissorsset_t; #define QFV_AllocScissorsSet(num, allocator) \ - allocator (field_offset (qfv_scissorsset_t, scissors[num])) + DARRAY_ALLOCFIXED (qfv_scissorsset_t, num, allocator) typedef struct qfv_viewportinfo_s { qfv_viewportset_t *viewportset; @@ -103,139 +85,73 @@ typedef struct qfv_pipelinedepthandstencil_s { float maxDepthBounds; } qfv_pipelinedepthandstencil_t; -typedef struct qfv_blendattachmentset_s { - uint32_t numAttachments; - VkPipelineColorBlendAttachmentState attachments[]; -} qfv_blendattachmentset_t; +typedef struct qfv_blendattachmentset_s + DARRAY_TYPE (VkPipelineColorBlendAttachmentState) qfv_blendattachmentset_t; #define QFV_AllocBlendAttachmentSet(num, allocator) \ - allocator (field_offset (qfv_blendattachmentset_t, attachments[num])) + DARRAY_ALLOCFIXED (qfv_blendattachmentset_t, num, allocator) -typedef struct qfv_pipelineblend_s { - VkBool32 logicOpEnable; - VkLogicOp logicOp; - qfv_blendattachmentset_t *blendAttachments; - float blendConstants[4]; -} qfv_pipelineblend_t; - -typedef struct qfv_dynamicstateset_s { - uint32_t numStates; - VkDynamicState states[]; -} qfv_dynamicstateset_t; +typedef struct qfv_dynamicstateset_s + DARRAY_TYPE (VkDynamicState) qfv_dynamicstateset_t; #define QFV_AllocDynamicStateSet(num, allocator) \ - allocator (field_offset (qfv_dynamicstateset_t, states[num])) + DARRAY_ALLOCFIXED (qfv_dynamicstateset_t, num, allocator) -typedef struct qfv_pushconstantrangeset_s { - uint32_t numRanges; - VkPushConstantRange ranges[]; -} qfv_pushconstantrangeset_t; +typedef struct qfv_pushconstantrangeset_s + DARRAY_TYPE (VkPushConstantRange) qfv_pushconstantrangeset_t; #define QFV_AllocPushConstantRangeSet(num, allocator) \ - allocator (field_offset (qfv_pushconstantrangeset_t, ranges[num])) + DARRAY_ALLOCFIXED (qfv_pushconstantrangeset_t, num, allocator) -typedef struct qfv_pipelinelayout_s { - struct qfv_device_s *device; - VkPipelineLayout layout; -} qfv_pipelinelayout_t; - -typedef struct qfv_pipeline_s { - struct qfv_device_s *device; - VkPipeline pipeline; -} qfv_pipeline_t; - -typedef struct qfv_pipelineset_s { - uint32_t numPipelines; - qfv_pipeline_t *pipelines[]; -} qfv_pipelineset_t; +typedef struct qfv_pipelineset_s DARRAY_TYPE (VkPipeline) qfv_pipelineset_t; #define QFV_AllocPipelineSet(num, allocator) \ - allocator (field_offset (qfv_pipelineset_t, pipelines[num])) + DARRAY_ALLOCFIXED (qfv_pipelineset_t, num, allocator) -typedef struct qfv_graphicspipelinecreateinfo_s { - VkPipelineCreateFlags flags; - qfv_shaderstageparamsset_t *stages; - qfv_vertexinputstate_t *vertexState; - qfv_pipelineinputassembly_t *inputAssemblyState; - qfv_pipelinetessellation_t *tessellationState; - qfv_viewportinfo_t *viewportState; - qfv_pipelinerasterization_t *rasterizationState; - qfv_pipelinemultisample_t *multisampleState; - qfv_pipelinedepthandstencil_t *depthStencilState; - qfv_pipelineblend_t *colorBlendState; - qfv_dynamicstateset_t *dynamicState; - qfv_pipelinelayout_t *layout; - VkRenderPass renderPass; - uint32_t subpass; - qfv_pipeline_t *basePipeline; - int32_t basePipelineIndex; -} qfv_graphicspipelinecreateinfo_t; - -typedef struct qfv_graphicspipelinecreateinfoset_s { - uint32_t numPipelines; - qfv_graphicspipelinecreateinfo_t *pipelines[]; -} qfv_graphicspipelinecreateinfoset_t; +typedef struct qfv_graphicspipelinecreateinfoset_s + DARRAY_TYPE (VkGraphicsPipelineCreateInfo) + qfv_graphicspipelinecreateinfoset_t; #define QFV_AllocGraphicsPipelineCreateInfoSet(num, allocator) \ - allocator (field_offset (qfv_graphicspipelinecreateinfoset_t, \ - pipelines[num])) + DARRAY_ALLOCFIXED (qfv_graphicspipelinecreateinfoset_t, num, allocator) -typedef struct qfv_computepipelinecreateinfo_s { - VkPipelineCreateFlags flags; - qfv_shaderstageparams_t *stage; - qfv_pipelinelayout_t *layout; - qfv_pipeline_t *basePipeline; - int32_t basePipelineIndex; -} qfv_computepipelinecreateinfo_t; - -typedef struct qfv_computepipelinecreateinfoset_s { - uint32_t numPipelines; - qfv_computepipelinecreateinfo_t *pipelines[]; -} qfv_computepipelinecreateinfoset_t; +typedef struct qfv_computepipelinecreateinfoset_s + DARRAY_TYPE (VkComputePipelineCreateInfo) + qfv_computepipelinecreateinfoset_t; #define QFV_AllocComputePipelineCreateInfoSet(num, allocator) \ - allocator (field_offset (qfv_computepipelinecreateinfoset_t, \ - pipelines[num])) + DARRAY_ALLOCFIXED (qfv_computepipelinecreateinfoset_t, num, allocator) -typedef struct qfv_pipelinecache_s { - struct qfv_device_s *device; - VkPipelineCache cache; -} qfv_pipelinecache_t; - -typedef struct qfv_pipelinecacheset_s { - uint32_t numCaches; - qfv_pipelinecache_t *caches[]; -} qfv_pipelinecacheset_t; +typedef struct qfv_pipelinecacheset_s + DARRAY_TYPE (VkPipelineCache) qfv_pipelinecacheset_t; #define QFV_AllocPipelineCacheSet(num, allocator) \ - allocator (field_offset (qfv_pipelinecacheset_t, caches[num])) + DARRAY_ALLOCFIXED (qfv_pipelinecacheset_t, num, allocator) -qfv_shadermodule_t *QFV_CreateShaderModule (struct qfv_device_s *device, +VkShaderModule QFV_CreateShaderModule (struct qfv_device_s *device, size_t size, const uint32_t *code); -void QFV_DestroyShaderModule (qfv_shadermodule_t *module); struct dstring_s; -qfv_pipelinecache_t *QFV_CreatePipelineCache (struct qfv_device_s *device, - struct dstring_s *cacheData); -struct dstring_s *QFV_GetPipelineCacheData (qfv_pipelinecache_t *cache); -void QFV_MergePipelineCaches (qfv_pipelinecache_t *targetCache, +VkPipelineCache QFV_CreatePipelineCache (struct qfv_device_s *device, + struct dstring_s *cacheData); +struct dstring_s *QFV_GetPipelineCacheData (struct qfv_device_s *device, + VkPipelineCache cache); +void QFV_MergePipelineCaches (struct qfv_device_s *device, + VkPipelineCache targetCache, qfv_pipelinecacheset_t *sourceCaches); -void QFV_DestroyPipelineCache (qfv_pipelinecache_t *cache); struct qfv_descriptorsetlayoutset_s; -qfv_pipelinelayout_t * +VkPipelineLayout QFV_CreatePipelineLayout (struct qfv_device_s *device, struct qfv_descriptorsetlayoutset_s *layouts, qfv_pushconstantrangeset_t *pushConstants); -void QFV_DestroyPipelineLayout (qfv_pipelinelayout_t *layout); qfv_pipelineset_t * QFV_CreateGraphicsPipelines (struct qfv_device_s *device, - qfv_pipelinecache_t *cache, + VkPipelineCache cache, qfv_graphicspipelinecreateinfoset_t *gpciSet); qfv_pipelineset_t * QFV_CreateComputePipelines (struct qfv_device_s *device, - qfv_pipelinecache_t *cache, + VkPipelineCache cache, qfv_computepipelinecreateinfoset_t *cpciSet); -void QFV_DestroyPipeline (qfv_pipeline_t *pipeline); #endif//__QF_Vulkan_pipeline_h diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c index 18babb115..119fbf303 100644 --- a/libs/video/renderer/vulkan/pipeline.c +++ b/libs/video/renderer/vulkan/pipeline.c @@ -64,7 +64,7 @@ #include "util.h" -qfv_shadermodule_t * +VkShaderModule QFV_CreateShaderModule (qfv_device_t *device, size_t size, const uint32_t *code) { @@ -76,24 +76,12 @@ QFV_CreateShaderModule (qfv_device_t *device, size, code, }; - qfv_shadermodule_t *module = malloc (sizeof (*module)); - module->device = device; - dfunc->vkCreateShaderModule (dev, &createInfo, 0, &module->module); + VkShaderModule module; + dfunc->vkCreateShaderModule (dev, &createInfo, 0, &module); return module; } -void -QFV_DestroyShaderModule (qfv_shadermodule_t *module) -{ - qfv_device_t *device = module->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyShaderModule (dev, module->module, 0); - free (module); -} - -qfv_pipelinecache_t * +VkPipelineCache QFV_CreatePipelineCache (qfv_device_t *device, dstring_t *cacheData) { VkDevice dev = device->dev; @@ -104,55 +92,38 @@ QFV_CreatePipelineCache (qfv_device_t *device, dstring_t *cacheData) cacheData->size, cacheData->str, }; - qfv_pipelinecache_t *cache = malloc (sizeof (*cache)); - cache->device = device; - dfunc->vkCreatePipelineCache (dev, &createInfo, 0, &cache->cache); + VkPipelineCache cache; + dfunc->vkCreatePipelineCache (dev, &createInfo, 0, &cache); return cache; } dstring_t * -QFV_GetPipelineCacheData (qfv_pipelinecache_t *cache) +QFV_GetPipelineCacheData (qfv_device_t *device, VkPipelineCache cache) { - qfv_device_t *device = cache->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; dstring_t *cacheData = dstring_new (); - dfunc->vkGetPipelineCacheData (dev, cache->cache, &cacheData->size, 0); + dfunc->vkGetPipelineCacheData (dev, cache, &cacheData->size, 0); dstring_adjust (cacheData); - dfunc->vkGetPipelineCacheData (dev, cache->cache, &cacheData->size, - cacheData->str); + dfunc->vkGetPipelineCacheData (dev, cache, + &cacheData->size, cacheData->str); return cacheData; } void -QFV_MergePipelineCaches (qfv_pipelinecache_t *targetCache, +QFV_MergePipelineCaches (qfv_device_t *device, + VkPipelineCache targetCache, qfv_pipelinecacheset_t *sourceCaches) { - qfv_device_t *device = targetCache->device; VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - VkPipelineCache *srcCaches = alloca (sourceCaches->numCaches - * sizeof (*srcCaches)); - for (uint32_t i = 0; i < sourceCaches->numCaches; i++) { - srcCaches[i] = sourceCaches->caches[i]->cache; - } - dfunc->vkMergePipelineCaches (dev, targetCache->cache, - sourceCaches->numCaches, srcCaches); + dfunc->vkMergePipelineCaches (dev, targetCache, + sourceCaches->size, sourceCaches->a); } -void -QFV_DestroyPipelineCache (qfv_pipelinecache_t *cache) -{ - qfv_device_t *device = cache->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyPipelineCache (dev, cache->cache, 0); -} - -qfv_pipelinelayout_t * +VkPipelineLayout QFV_CreatePipelineLayout (qfv_device_t *device, qfv_descriptorsetlayoutset_t *layouts, qfv_pushconstantrangeset_t *pushConstants) @@ -163,357 +134,39 @@ QFV_CreatePipelineLayout (qfv_device_t *device, VkPipelineLayoutCreateInfo createInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 0, 0, layouts->size, layouts->a, - pushConstants->numRanges, pushConstants->ranges, + pushConstants->size, pushConstants->a, }; - qfv_pipelinelayout_t *layout = malloc (sizeof (layout)); - layout->device = device; - dfunc->vkCreatePipelineLayout (dev, &createInfo, 0, &layout->layout); + VkPipelineLayout layout; + dfunc->vkCreatePipelineLayout (dev, &createInfo, 0, &layout); return layout; } -void -QFV_DestroyPipelineLayout (qfv_pipelinelayout_t *layout) -{ - qfv_device_t *device = layout->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyPipelineLayout (dev, layout->layout, 0); - free (layout); -} - -static VkPipelineShaderStageCreateInfo -shaderStageCI (qfv_shaderstageparams_t params) -{ - VkPipelineShaderStageCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 0, 0, - params.stageFlags, params.module->module, - params.entryPointName, params.specializationInfo, - }; - return createInfo; -} - -static VkPipelineVertexInputStateCreateInfo -vertexInputSCI (qfv_vertexinputstate_t vertexState) -{ - VkPipelineVertexInputStateCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 0, 0, - vertexState.bindings->size, - vertexState.bindings->a, - vertexState.attributes->size, - vertexState.attributes->a, - }; - return createInfo; -} - -static VkPipelineInputAssemblyStateCreateInfo -inputAssemblySCI (qfv_pipelineinputassembly_t inputAssemblyState) -{ - VkPipelineInputAssemblyStateCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 0, 0, - inputAssemblyState.topology, - inputAssemblyState.primativeRestartEnable, - }; - return createInfo; -} - -static VkPipelineTessellationStateCreateInfo -tessellationSCI (qfv_pipelinetessellation_t tessellationState) -{ - VkPipelineTessellationStateCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, 0, 0, - tessellationState.patchControlPoints - }; - return createInfo; -} - -static VkPipelineViewportStateCreateInfo -viewportSCI (qfv_viewportinfo_t viewportState) -{ - VkPipelineViewportStateCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 0, 0, - viewportState.viewportset->numViewports, - viewportState.viewportset->viewports, - viewportState.scissorsset->numScissors, - viewportState.scissorsset->scissors, - }; - return createInfo; -} - -static VkPipelineRasterizationStateCreateInfo -rasterizationSCI (qfv_pipelinerasterization_t rasterizationState) -{ - VkPipelineRasterizationStateCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 0, 0, - rasterizationState.depthClampEnable, - rasterizationState.rasterizerDiscardEnable, - rasterizationState.polygonMode, - rasterizationState.cullMode, - rasterizationState.frontFace, - rasterizationState.depthBiasEnable, - rasterizationState.depthBiasConstantFactor, - rasterizationState.depthBiasClamp, - rasterizationState.depthBiasSlopeFactor, - rasterizationState.lineWidth, - }; - return createInfo; -} - -static VkPipelineMultisampleStateCreateInfo -multisampleSCI (qfv_pipelinemultisample_t multisampleState) -{ - VkPipelineMultisampleStateCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 0, 0, - multisampleState.rasterizationSamples, - multisampleState.sampleShadingEnable, - multisampleState.minSampleShading, - multisampleState.sampleMask, - multisampleState.alphaToCoverageEnable, - multisampleState.alphaToOneEnable, - }; - return createInfo; -} - -static VkPipelineDepthStencilStateCreateInfo -depthStencilSCI (qfv_pipelinedepthandstencil_t depthStencilState) -{ - VkPipelineDepthStencilStateCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 0, 0, - depthStencilState.depthTestEnable, - depthStencilState.depthWriteEnable, - depthStencilState.depthCompareOp, - depthStencilState.depthBoundsTestEnable, - depthStencilState.stencilTestEnable, - depthStencilState.front, - depthStencilState.back, - depthStencilState.minDepthBounds, - depthStencilState.maxDepthBounds, - }; - return createInfo; -} - -static VkPipelineColorBlendStateCreateInfo -colorBlendSCI (qfv_pipelineblend_t colorBlendState) -{ - VkPipelineColorBlendStateCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 0, 0, - colorBlendState.logicOpEnable, - colorBlendState.logicOp, - colorBlendState.blendAttachments->numAttachments, - colorBlendState.blendAttachments->attachments, - { - colorBlendState.blendConstants[0], - colorBlendState.blendConstants[1], - colorBlendState.blendConstants[2], - colorBlendState.blendConstants[3], - }, - }; - return createInfo; -} - -static VkPipelineDynamicStateCreateInfo -dynamicSCI (qfv_dynamicstateset_t *dynamicState) -{ - VkPipelineDynamicStateCreateInfo createInfo = { - VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 0, 0, - dynamicState->numStates, dynamicState->states, - }; - return createInfo; -} - qfv_pipelineset_t * QFV_CreateGraphicsPipelines (qfv_device_t *device, - qfv_pipelinecache_t *cache, + VkPipelineCache cache, qfv_graphicspipelinecreateinfoset_t *gpciSet) { VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - uint32_t numPipelines = gpciSet->numPipelines; - uint32_t stageCount = 0; - for (uint32_t i = 0; i < numPipelines; i++) { - stageCount += gpciSet->pipelines[i]->stages->size; - } + __auto_type pipelines = QFV_AllocPipelineSet (gpciSet->size, malloc); + dfunc->vkCreateGraphicsPipelines (dev, cache, gpciSet->size, gpciSet->a, 0, + pipelines->a); - size_t blockSize = numPipelines - * (sizeof (VkGraphicsPipelineCreateInfo) - + sizeof (VkPipelineVertexInputStateCreateInfo) - + sizeof (VkPipelineInputAssemblyStateCreateInfo) - + sizeof (VkPipelineTessellationStateCreateInfo) - + sizeof (VkPipelineViewportStateCreateInfo) - + sizeof (VkPipelineRasterizationStateCreateInfo) - + sizeof (VkPipelineMultisampleStateCreateInfo) - + sizeof (VkPipelineDepthStencilStateCreateInfo) - + sizeof (VkPipelineColorBlendStateCreateInfo) - + sizeof (VkPipelineDynamicStateCreateInfo)) - + stageCount * sizeof (VkPipelineShaderStageCreateInfo); - VkGraphicsPipelineCreateInfo *pipelineInfos = malloc (blockSize); - - pipelineInfos->pStages = (void *)(pipelineInfos + numPipelines); - pipelineInfos->pVertexInputState - = (void *)(pipelineInfos->pStages + stageCount); - pipelineInfos->pInputAssemblyState - = (void *)(pipelineInfos->pVertexInputState + numPipelines); - pipelineInfos->pTessellationState - = (void *)(pipelineInfos->pInputAssemblyState + numPipelines); - pipelineInfos->pViewportState - = (void *)(pipelineInfos->pTessellationState + numPipelines); - pipelineInfos->pRasterizationState - = (void *)(pipelineInfos->pViewportState + numPipelines); - pipelineInfos->pMultisampleState - = (void *)(pipelineInfos->pRasterizationState + numPipelines); - pipelineInfos->pDepthStencilState - = (void *)(pipelineInfos->pMultisampleState + numPipelines); - pipelineInfos->pColorBlendState - = (void *)(pipelineInfos->pDepthStencilState + numPipelines); - pipelineInfos->pDynamicState - = (void *)(pipelineInfos->pColorBlendState + numPipelines); - for (uint32_t i = 1; i < gpciSet->numPipelines; i++) { - pipelineInfos[i].pStages = pipelineInfos[i - 1].pStages - + gpciSet->pipelines[i - 1]->stages->size; - pipelineInfos[i].pVertexInputState - = pipelineInfos[i - 1].pVertexInputState + 1; - pipelineInfos[i].pInputAssemblyState - = pipelineInfos[i - 1].pInputAssemblyState + 1; - pipelineInfos[i].pTessellationState - = pipelineInfos[i - 1].pTessellationState + 1; - pipelineInfos[i].pViewportState - = pipelineInfos[i - 1].pViewportState + 1; - pipelineInfos[i].pRasterizationState - = pipelineInfos[i - 1].pRasterizationState + 1; - pipelineInfos[i].pMultisampleState - = pipelineInfos[i - 1].pMultisampleState + 1; - pipelineInfos[i].pDepthStencilState - = pipelineInfos[i - 1].pDepthStencilState + 1; - pipelineInfos[i].pColorBlendState - = pipelineInfos[i - 1].pColorBlendState + 1; - pipelineInfos[i].pDynamicState - = pipelineInfos[i - 1].pDynamicState + 1; - } - for (uint32_t i = 0; i < gpciSet->numPipelines; i++) { - VkGraphicsPipelineCreateInfo *gci = pipelineInfos + i; - qfv_graphicspipelinecreateinfo_t *ci = gpciSet->pipelines[i]; - gci->sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - gci->pNext = 0; - gci->flags = ci->flags; - gci->stageCount = ci->stages->size; - for (uint32_t j = 0; j < gci->stageCount; j++) { - ((VkPipelineShaderStageCreateInfo *)gci->pStages)[i] = shaderStageCI (ci->stages->a[j]); - } - if (ci->vertexState) { - *(VkPipelineVertexInputStateCreateInfo *)gci->pVertexInputState = vertexInputSCI (*ci->vertexState); - } else { - gci->pVertexInputState = 0; - } - if (ci->inputAssemblyState) { - *(VkPipelineInputAssemblyStateCreateInfo *)gci->pInputAssemblyState = inputAssemblySCI (*ci->inputAssemblyState); - } else { - gci->pInputAssemblyState = 0; - } - if (ci->tessellationState) { - *(VkPipelineTessellationStateCreateInfo *)gci->pTessellationState = tessellationSCI (*ci->tessellationState); - } else { - gci->pTessellationState = 0; - } - if (ci->viewportState) { - *(VkPipelineViewportStateCreateInfo *)gci->pViewportState = viewportSCI (*ci->viewportState); - } else { - gci->pViewportState = 0; - } - if (ci->rasterizationState) { - *(VkPipelineRasterizationStateCreateInfo *)gci->pRasterizationState = rasterizationSCI (*ci->rasterizationState); - } else { - gci->pRasterizationState = 0; - } - if (ci->multisampleState) { - *(VkPipelineMultisampleStateCreateInfo *)gci->pMultisampleState = multisampleSCI (*ci->multisampleState); - } else { - gci->pMultisampleState = 0; - } - if (ci->depthStencilState) { - *(VkPipelineDepthStencilStateCreateInfo *)gci->pDepthStencilState = depthStencilSCI (*ci->depthStencilState); - } else { - gci->pDepthStencilState = 0; - } - if (ci->colorBlendState) { - *(VkPipelineColorBlendStateCreateInfo *)gci->pColorBlendState = colorBlendSCI (*ci->colorBlendState); - } else { - gci->pColorBlendState = 0; - } - if (ci->dynamicState) { - *(VkPipelineDynamicStateCreateInfo *)gci->pDynamicState = dynamicSCI (ci->dynamicState); - } else { - gci->pDynamicState = 0; - } - gci->layout = ci->layout->layout; - gci->renderPass = ci->renderPass; - gci->subpass = ci->subpass; - gci->basePipelineHandle = ci->basePipeline->pipeline; - gci->basePipelineIndex = ci->basePipelineIndex; - } - - VkPipeline *pipelines = alloca (numPipelines * sizeof (pipelines)); - dfunc->vkCreateGraphicsPipelines (dev, cache->cache, - numPipelines, pipelineInfos, 0, - pipelines); - - qfv_pipelineset_t *pipelineset = QFV_AllocPipelineSet (numPipelines, malloc); - pipelineset->numPipelines = numPipelines; - for (uint32_t i = 0; i < numPipelines; i++) { - pipelineset->pipelines[i] = malloc (sizeof (qfv_pipeline_t)); - pipelineset->pipelines[i]->device = device; - pipelineset->pipelines[i]->pipeline = pipelines[i]; - } - return pipelineset; + return pipelines; } qfv_pipelineset_t * QFV_CreateComputePipelines (qfv_device_t *device, - qfv_pipelinecache_t *cache, + VkPipelineCache cache, qfv_computepipelinecreateinfoset_t *cpciSet) { VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - uint32_t numPipelines = cpciSet->numPipelines; - - size_t blockSize = numPipelines * (sizeof (VkComputePipelineCreateInfo)); - VkComputePipelineCreateInfo *pipelineInfos = malloc (blockSize); - - for (uint32_t i = 0; i < cpciSet->numPipelines; i++) { - VkComputePipelineCreateInfo *cci = pipelineInfos + i; - qfv_computepipelinecreateinfo_t *ci = cpciSet->pipelines[i]; - cci->sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - cci->pNext = 0; - cci->flags = ci->flags; - cci->stage = shaderStageCI (*ci->stage); - cci->layout = ci->layout->layout; - cci->basePipelineHandle = ci->basePipeline->pipeline; - cci->basePipelineIndex = ci->basePipelineIndex; - } - - VkPipeline *pipelines = alloca (numPipelines * sizeof (pipelines)); - dfunc->vkCreateComputePipelines (dev, cache->cache, - numPipelines, pipelineInfos, 0, - pipelines); - - qfv_pipelineset_t *pipelineset = QFV_AllocPipelineSet (numPipelines, malloc); - pipelineset->numPipelines = numPipelines; - for (uint32_t i = 0; i < numPipelines; i++) { - pipelineset->pipelines[i] = malloc (sizeof (qfv_pipeline_t)); - pipelineset->pipelines[i]->device = device; - pipelineset->pipelines[i]->pipeline = pipelines[i]; - } - return pipelineset; -} - -void -QFV_DestroyPipeline (qfv_pipeline_t *pipeline) -{ - qfv_device_t *device = pipeline->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyPipeline (dev, pipeline->pipeline, 0); + __auto_type pipelines = QFV_AllocPipelineSet (cpciSet->size, malloc); + dfunc->vkCreateComputePipelines (dev, cache, cpciSet->size, cpciSet->a, 0, + pipelines->a); + return pipelines; } From e658c0d5cde846cffa90d4675c37af62592908ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 01:28:09 +0900 Subject: [PATCH 0324/3664] Fix self-referenced enum declarations eg: typedef enum foo { bar = 1, baz = bar, } foo; --- tools/qfcc/source/qc-parse.y | 2 ++ tools/qfcc/source/struct.c | 1 + 2 files changed, 3 insertions(+) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index c34efd0a0..a2bbf1c03 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -553,6 +553,7 @@ optional_enum_list enum_list : '{' enum_init enumerator_list optional_comma '}' { + current_symtab = current_symtab->parent; $$ = finish_enum ($3); } ; @@ -562,6 +563,7 @@ enum_init { $$ = find_enum ($-1); start_enum ($$); + current_symtab = $$->type->t.symtab; } ; diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 358b337f0..800a1aa66 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -201,6 +201,7 @@ add_enum (symbol_t *enm, symbol_t *name, expr_t *val) if (enum_tab->symbols) value = ((symbol_t *)(enum_tab->symtail))->s.value->v.integer_val + 1; if (val) { + convert_name (val); if (!is_constant (val)) error (val, "non-constant initializer"); else if (!is_integer_val (val)) From 501174e14f4dc0a8e2709af0a0fd41ef18bf541a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 01:51:24 +0900 Subject: [PATCH 0325/3664] Allow unlimited parameters in function declarations However, definitions are still limited to 8 parameters. This allows processing of C headers for type information. --- tools/qfcc/include/function.h | 1 - tools/qfcc/include/type.h | 2 +- tools/qfcc/source/class.c | 9 ++++++--- tools/qfcc/source/cpp.c | 3 --- tools/qfcc/source/function.c | 36 ++++++++++++++++++++--------------- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 88ea05dc8..209f40026 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -141,7 +141,6 @@ function_t *build_code_function (struct symbol_s *fsym, struct expr_s *statements); function_t *build_builtin_function (struct symbol_s *sym, struct expr_s *bi_val, int far); -void build_function (function_t *f); void finish_function (function_t *f); void emit_function (function_t *f, struct expr_s *e); int function_parms (function_t *f, byte *parm_size); diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 6944db353..fcb4a808a 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -38,7 +38,7 @@ typedef struct ty_func_s { struct type_s *type; int num_params; - struct type_s *param_types[MAX_PARMS]; + struct type_s **param_types; } ty_func_t; typedef struct ty_fldptr_s { diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index e0d601aa9..b249069c2 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -70,12 +70,14 @@ static hashtab_t *protocol_hash; // these will be built up further type_t type_obj_selector = { ev_invalid, 0, 0, ty_struct}; type_t type_SEL = { ev_pointer, "SEL", 1, ty_none, {{&type_obj_selector}}}; +type_t *IMP_params[] = {&type_id, &type_SEL}; type_t type_IMP = { ev_func, "IMP", 1, ty_none, - {{&type_id, -3, {&type_id, &type_SEL}}}}; + {{&type_id, -3, IMP_params}}}; type_t type_obj_super = { ev_invalid, 0, 0 }; type_t type_SuperPtr = { ev_pointer, 0, 1, ty_none, {{&type_obj_super}}}; +type_t *supermsg_params[] = {&type_SuperPtr, &type_SEL}; type_t type_supermsg = { ev_func, ".supermsg", 1, ty_none, - {{&type_id, -3, {&type_SuperPtr, &type_SEL}}}}; + {{&type_id, -3, supermsg_params}}}; type_t type_obj_method = { ev_invalid, 0, 0, ty_struct }; type_t type_obj_method_description = { ev_invalid, 0, 0, ty_struct }; type_t type_obj_category = { ev_invalid, 0, 0, ty_struct}; @@ -83,8 +85,9 @@ type_t type_obj_ivar = { ev_invalid, 0, 0, ty_struct}; type_t type_obj_module = { ev_invalid, 0, 0, ty_struct}; type_t type_moduleptr = { ev_pointer, 0, 1, ty_none, {{&type_obj_module}}}; +type_t *obj_exec_class_params[] = { &type_moduleptr }; type_t type_obj_exec_class = { ev_func, 0, 1, ty_none, - {{&type_void, 1, { &type_moduleptr }}}}; + {{&type_void, 1, obj_exec_class_params}}}; type_t type_obj_object = {ev_invalid, 0, 0, ty_struct}; type_t type_id = { ev_pointer, "id", 1, ty_none, {{&type_obj_object}}}; diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index 9bea8741d..7e8affb49 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -141,9 +141,6 @@ build_cpp_args (const char *in_name, const char *out_name) } } *arg = 0; - //for (arg = cpp_argv; *arg; arg++) - // printf ("%s ", *arg); - //puts (""); } //============================================================================ diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index b150e4baf..884dce1da 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -155,6 +155,7 @@ parse_params (type_t *type, param_t *parms) { param_t *p; type_t *new; + int count; new = new_type (); new->type = ev_func; @@ -163,10 +164,12 @@ parse_params (type_t *type, param_t *parms) new->t.func.num_params = 0; for (p = parms; p; p = p->next) { - if (new->t.func.num_params > MAX_PARMS) { - error (0, "too many params"); - return type; + if (p->type) { + count++; } + } + new->t.func.param_types = malloc (count * sizeof (type_t)); + for (p = parms; p; p = p->next) { if (!p->selector && !p->type && !p->name) { if (p->next) internal_error (0, 0); @@ -581,12 +584,25 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, return sym->s.func; } +static void +build_function (symbol_t *fsym) +{ + if (fsym->type->t.func.num_params > MAX_PARMS) { + error (0, "too many params"); + } + // FIXME +// f->def->constant = 1; +// f->def->nosave = 1; +// f->def->initialized = 1; +// G_FUNCTION (f->def->ofs) = f->function_num; +} + function_t * build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) { if (fsym->sy_type != sy_func) // probably in error recovery return 0; - build_function (fsym->s.func); + build_function (fsym); if (state_expr) { state_expr->next = statements; statements = state_expr; @@ -629,7 +645,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far) bi = expr_float (bi_val); sym->s.func->builtin = bi; reloc_def_func (sym->s.func, sym->s.func->def); - build_function (sym->s.func); + build_function (sym); finish_function (sym->s.func); // for debug info @@ -638,16 +654,6 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far) return sym->s.func; } -void -build_function (function_t *f) -{ - // FIXME -// f->def->constant = 1; -// f->def->nosave = 1; -// f->def->initialized = 1; -// G_FUNCTION (f->def->ofs) = f->function_num; -} - void finish_function (function_t *f) { From 2f726a497b6e853f7e2c4e0b5c83cb63932841bc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 02:30:50 +0900 Subject: [PATCH 0326/3664] Fix segfault in unlimited params --- tools/qfcc/source/function.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 884dce1da..4d3a617e9 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -330,8 +330,9 @@ find_function (expr_t *fexpr, expr_t *params) return e; type.t.func.num_params++; } - if (type.t.func.num_params > MAX_PARMS) - return fexpr; + i = type.t.func.num_params * sizeof (type_t); + type.t.func.param_types = alloca(i); + memset (type.t.func.param_types, 0, i); for (i = 0, e = params; e; i++, e = e->next) { type.t.func.param_types[type.t.func.num_params - 1 - i] = get_type (e); if (e->type == ex_error) From d4574111b528155e0e8e14018f36a2992b6598a0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 02:31:16 +0900 Subject: [PATCH 0327/3664] Replace system defines/includes with qfcc's Right now, it probably works only with modern gcc. --- config.d/qfcc.m4 | 2 +- tools/qfcc/configure.in | 2 +- tools/qfcc/include/cpp.h | 2 ++ tools/qfcc/source/cpp.c | 46 +++++++++++++++++++++++++++++++++---- tools/qfcc/source/options.c | 5 +++- 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/config.d/qfcc.m4 b/config.d/qfcc.m4 index 3e1d87ae7..380e6a31c 100644 --- a/config.d/qfcc.m4 +++ b/config.d/qfcc.m4 @@ -9,7 +9,7 @@ AC_ARG_WITH(cpp, if test "x$cpp_name" != xauto; then CPP_NAME="$cpp_name" else - CPP_NAME="cpp %d -o %o %i" + CPP_NAME="cpp %u %d %s -o %o %i" case "$host_os" in *freebsd*) CPP_NAME="cpp %d %i %o" diff --git a/tools/qfcc/configure.in b/tools/qfcc/configure.in index 21934d623..3c6383d5a 100644 --- a/tools/qfcc/configure.in +++ b/tools/qfcc/configure.in @@ -30,7 +30,7 @@ AC_ARG_WITH(cpp, if test "x$cpp_name" != xauto; then CPP_NAME="$cpp_name" else - CPP_NAME="cpp %d -o %o %i" + CPP_NAME="cpp %u %d %s -o %o %i" case "$target_os" in *bsd*) touch conftest.c diff --git a/tools/qfcc/include/cpp.h b/tools/qfcc/include/cpp.h index 6b599b439..81274c353 100644 --- a/tools/qfcc/include/cpp.h +++ b/tools/qfcc/include/cpp.h @@ -34,6 +34,8 @@ struct dstring_s; void parse_cpp_name (void); +void add_cpp_sysinc (const char *arg); +void add_cpp_undef (const char *arg); void add_cpp_def (const char *arg); void intermediate_file (struct dstring_s *ifile, const char *filename, const char *ext, int local); diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index 7e8affb49..71b42c6d1 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -67,11 +67,25 @@ cpp_arg_t *cpp_arg_list; cpp_arg_t **cpp_arg_tail = &cpp_arg_list; cpp_arg_t *cpp_def_list; cpp_arg_t **cpp_def_tail = &cpp_def_list; +cpp_arg_t *cpp_undef_list; +cpp_arg_t **cpp_undef_tail = &cpp_undef_list; +cpp_arg_t *cpp_sysinc_list; +cpp_arg_t **cpp_sysinc_tail = &cpp_sysinc_list; const char **cpp_argv; const char *cpp_name = CPP_NAME; static int cpp_argc = 0; dstring_t *tempname; +static const char ** +append_cpp_args (const char **arg, cpp_arg_t *arg_list) +{ + cpp_arg_t *cpp_arg; + + for (cpp_arg = arg_list; cpp_arg; cpp_arg = cpp_arg->next) + *arg++ = cpp_arg->arg; + return arg; +} + static void add_cpp_arg (const char *arg) { @@ -83,6 +97,28 @@ add_cpp_arg (const char *arg) cpp_argc++; } +void +add_cpp_sysinc (const char *arg) +{ + cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); + cpp_arg->next = 0; + cpp_arg->arg = arg; + *cpp_sysinc_tail = cpp_arg; + cpp_sysinc_tail = &(*cpp_sysinc_tail)->next; + cpp_argc++; +} + +void +add_cpp_undef (const char *arg) +{ + cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); + cpp_arg->next = 0; + cpp_arg->arg = arg; + *cpp_undef_tail = cpp_arg; + cpp_undef_tail = &(*cpp_undef_tail)->next; + cpp_argc++; +} + void add_cpp_def (const char *arg) { @@ -117,7 +153,6 @@ static void build_cpp_args (const char *in_name, const char *out_name) { cpp_arg_t *cpp_arg; - cpp_arg_t *cpp_def; const char **arg; if (cpp_argv) @@ -126,9 +161,12 @@ build_cpp_args (const char *in_name, const char *out_name) for (arg = cpp_argv, cpp_arg = cpp_arg_list; cpp_arg; cpp_arg = cpp_arg->next) { - if (!strcmp (cpp_arg->arg, "%d")) { - for (cpp_def = cpp_def_list; cpp_def; cpp_def = cpp_def->next) - *arg++ = cpp_def->arg; + if (!strcmp (cpp_arg->arg, "%u")) { + arg = append_cpp_args (arg, cpp_undef_list); + } else if (!strcmp (cpp_arg->arg, "%s")) { + arg = append_cpp_args (arg, cpp_sysinc_list); + } else if (!strcmp (cpp_arg->arg, "%d")) { + arg = append_cpp_args (arg, cpp_def_list); } else if (!strcmp (cpp_arg->arg, "%i")) { *arg++ = in_name; } else if (!strcmp (cpp_arg->arg, "%o")) { diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index cfd1e27bf..c3f283e89 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -299,6 +299,8 @@ DecodeArgs (int argc, char **argv) int c; int saw_E = 0, saw_MD = 0; + add_cpp_undef ("-undef"); + add_cpp_undef ("-nostdinc"); add_cpp_def ("-D__QFCC__=1"); add_cpp_def ("-D__QUAKEC__=1"); @@ -720,7 +722,8 @@ DecodeArgs (int argc, char **argv) // add the default paths if (!options.no_default_paths) { - add_cpp_def (nva ("-I%s", QFCC_INCLUDE_PATH)); + add_cpp_sysinc ("-isystem"); + add_cpp_sysinc (QFCC_INCLUDE_PATH); linker_add_path (QFCC_LIB_PATH); } From ee228504aa96c18a1f677607ace95afbec427ca4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 01:28:09 +0900 Subject: [PATCH 0328/3664] Fix self-referenced enum declarations eg: typedef enum foo { bar = 1, baz = bar, } foo; --- tools/qfcc/source/qc-parse.y | 2 ++ tools/qfcc/source/struct.c | 1 + 2 files changed, 3 insertions(+) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index c34efd0a0..a2bbf1c03 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -553,6 +553,7 @@ optional_enum_list enum_list : '{' enum_init enumerator_list optional_comma '}' { + current_symtab = current_symtab->parent; $$ = finish_enum ($3); } ; @@ -562,6 +563,7 @@ enum_init { $$ = find_enum ($-1); start_enum ($$); + current_symtab = $$->type->t.symtab; } ; diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 358b337f0..800a1aa66 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -201,6 +201,7 @@ add_enum (symbol_t *enm, symbol_t *name, expr_t *val) if (enum_tab->symbols) value = ((symbol_t *)(enum_tab->symtail))->s.value->v.integer_val + 1; if (val) { + convert_name (val); if (!is_constant (val)) error (val, "non-constant initializer"); else if (!is_integer_val (val)) From c61d0b6ff00800d6e8a9beaf924730cef885a081 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 01:51:24 +0900 Subject: [PATCH 0329/3664] Allow unlimited parameters in function declarations However, definitions are still limited to 8 parameters. This allows processing of C headers for type information. --- tools/qfcc/include/function.h | 1 - tools/qfcc/include/type.h | 2 +- tools/qfcc/source/class.c | 9 ++++++--- tools/qfcc/source/cpp.c | 3 --- tools/qfcc/source/function.c | 36 ++++++++++++++++++++--------------- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 88ea05dc8..209f40026 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -141,7 +141,6 @@ function_t *build_code_function (struct symbol_s *fsym, struct expr_s *statements); function_t *build_builtin_function (struct symbol_s *sym, struct expr_s *bi_val, int far); -void build_function (function_t *f); void finish_function (function_t *f); void emit_function (function_t *f, struct expr_s *e); int function_parms (function_t *f, byte *parm_size); diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 6944db353..fcb4a808a 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -38,7 +38,7 @@ typedef struct ty_func_s { struct type_s *type; int num_params; - struct type_s *param_types[MAX_PARMS]; + struct type_s **param_types; } ty_func_t; typedef struct ty_fldptr_s { diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index e0d601aa9..b249069c2 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -70,12 +70,14 @@ static hashtab_t *protocol_hash; // these will be built up further type_t type_obj_selector = { ev_invalid, 0, 0, ty_struct}; type_t type_SEL = { ev_pointer, "SEL", 1, ty_none, {{&type_obj_selector}}}; +type_t *IMP_params[] = {&type_id, &type_SEL}; type_t type_IMP = { ev_func, "IMP", 1, ty_none, - {{&type_id, -3, {&type_id, &type_SEL}}}}; + {{&type_id, -3, IMP_params}}}; type_t type_obj_super = { ev_invalid, 0, 0 }; type_t type_SuperPtr = { ev_pointer, 0, 1, ty_none, {{&type_obj_super}}}; +type_t *supermsg_params[] = {&type_SuperPtr, &type_SEL}; type_t type_supermsg = { ev_func, ".supermsg", 1, ty_none, - {{&type_id, -3, {&type_SuperPtr, &type_SEL}}}}; + {{&type_id, -3, supermsg_params}}}; type_t type_obj_method = { ev_invalid, 0, 0, ty_struct }; type_t type_obj_method_description = { ev_invalid, 0, 0, ty_struct }; type_t type_obj_category = { ev_invalid, 0, 0, ty_struct}; @@ -83,8 +85,9 @@ type_t type_obj_ivar = { ev_invalid, 0, 0, ty_struct}; type_t type_obj_module = { ev_invalid, 0, 0, ty_struct}; type_t type_moduleptr = { ev_pointer, 0, 1, ty_none, {{&type_obj_module}}}; +type_t *obj_exec_class_params[] = { &type_moduleptr }; type_t type_obj_exec_class = { ev_func, 0, 1, ty_none, - {{&type_void, 1, { &type_moduleptr }}}}; + {{&type_void, 1, obj_exec_class_params}}}; type_t type_obj_object = {ev_invalid, 0, 0, ty_struct}; type_t type_id = { ev_pointer, "id", 1, ty_none, {{&type_obj_object}}}; diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index 9bea8741d..7e8affb49 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -141,9 +141,6 @@ build_cpp_args (const char *in_name, const char *out_name) } } *arg = 0; - //for (arg = cpp_argv; *arg; arg++) - // printf ("%s ", *arg); - //puts (""); } //============================================================================ diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index b150e4baf..884dce1da 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -155,6 +155,7 @@ parse_params (type_t *type, param_t *parms) { param_t *p; type_t *new; + int count; new = new_type (); new->type = ev_func; @@ -163,10 +164,12 @@ parse_params (type_t *type, param_t *parms) new->t.func.num_params = 0; for (p = parms; p; p = p->next) { - if (new->t.func.num_params > MAX_PARMS) { - error (0, "too many params"); - return type; + if (p->type) { + count++; } + } + new->t.func.param_types = malloc (count * sizeof (type_t)); + for (p = parms; p; p = p->next) { if (!p->selector && !p->type && !p->name) { if (p->next) internal_error (0, 0); @@ -581,12 +584,25 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, return sym->s.func; } +static void +build_function (symbol_t *fsym) +{ + if (fsym->type->t.func.num_params > MAX_PARMS) { + error (0, "too many params"); + } + // FIXME +// f->def->constant = 1; +// f->def->nosave = 1; +// f->def->initialized = 1; +// G_FUNCTION (f->def->ofs) = f->function_num; +} + function_t * build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) { if (fsym->sy_type != sy_func) // probably in error recovery return 0; - build_function (fsym->s.func); + build_function (fsym); if (state_expr) { state_expr->next = statements; statements = state_expr; @@ -629,7 +645,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far) bi = expr_float (bi_val); sym->s.func->builtin = bi; reloc_def_func (sym->s.func, sym->s.func->def); - build_function (sym->s.func); + build_function (sym); finish_function (sym->s.func); // for debug info @@ -638,16 +654,6 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far) return sym->s.func; } -void -build_function (function_t *f) -{ - // FIXME -// f->def->constant = 1; -// f->def->nosave = 1; -// f->def->initialized = 1; -// G_FUNCTION (f->def->ofs) = f->function_num; -} - void finish_function (function_t *f) { From 2d52da9c0d9ec87c5fa3931b65445596478febe7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 02:30:50 +0900 Subject: [PATCH 0330/3664] Fix segfault in unlimited params --- tools/qfcc/source/function.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 884dce1da..4d3a617e9 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -330,8 +330,9 @@ find_function (expr_t *fexpr, expr_t *params) return e; type.t.func.num_params++; } - if (type.t.func.num_params > MAX_PARMS) - return fexpr; + i = type.t.func.num_params * sizeof (type_t); + type.t.func.param_types = alloca(i); + memset (type.t.func.param_types, 0, i); for (i = 0, e = params; e; i++, e = e->next) { type.t.func.param_types[type.t.func.num_params - 1 - i] = get_type (e); if (e->type == ex_error) From bd6dcafdc89c1a3c1ab7a41931838b784d17f913 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 02:31:16 +0900 Subject: [PATCH 0331/3664] Replace system defines/includes with qfcc's Right now, it probably works only with modern gcc. --- config.d/qfcc.m4 | 2 +- tools/qfcc/configure.in | 2 +- tools/qfcc/include/cpp.h | 2 ++ tools/qfcc/source/cpp.c | 46 +++++++++++++++++++++++++++++++++---- tools/qfcc/source/options.c | 5 +++- 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/config.d/qfcc.m4 b/config.d/qfcc.m4 index 3e1d87ae7..380e6a31c 100644 --- a/config.d/qfcc.m4 +++ b/config.d/qfcc.m4 @@ -9,7 +9,7 @@ AC_ARG_WITH(cpp, if test "x$cpp_name" != xauto; then CPP_NAME="$cpp_name" else - CPP_NAME="cpp %d -o %o %i" + CPP_NAME="cpp %u %d %s -o %o %i" case "$host_os" in *freebsd*) CPP_NAME="cpp %d %i %o" diff --git a/tools/qfcc/configure.in b/tools/qfcc/configure.in index 21934d623..3c6383d5a 100644 --- a/tools/qfcc/configure.in +++ b/tools/qfcc/configure.in @@ -30,7 +30,7 @@ AC_ARG_WITH(cpp, if test "x$cpp_name" != xauto; then CPP_NAME="$cpp_name" else - CPP_NAME="cpp %d -o %o %i" + CPP_NAME="cpp %u %d %s -o %o %i" case "$target_os" in *bsd*) touch conftest.c diff --git a/tools/qfcc/include/cpp.h b/tools/qfcc/include/cpp.h index 6b599b439..81274c353 100644 --- a/tools/qfcc/include/cpp.h +++ b/tools/qfcc/include/cpp.h @@ -34,6 +34,8 @@ struct dstring_s; void parse_cpp_name (void); +void add_cpp_sysinc (const char *arg); +void add_cpp_undef (const char *arg); void add_cpp_def (const char *arg); void intermediate_file (struct dstring_s *ifile, const char *filename, const char *ext, int local); diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index 7e8affb49..71b42c6d1 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -67,11 +67,25 @@ cpp_arg_t *cpp_arg_list; cpp_arg_t **cpp_arg_tail = &cpp_arg_list; cpp_arg_t *cpp_def_list; cpp_arg_t **cpp_def_tail = &cpp_def_list; +cpp_arg_t *cpp_undef_list; +cpp_arg_t **cpp_undef_tail = &cpp_undef_list; +cpp_arg_t *cpp_sysinc_list; +cpp_arg_t **cpp_sysinc_tail = &cpp_sysinc_list; const char **cpp_argv; const char *cpp_name = CPP_NAME; static int cpp_argc = 0; dstring_t *tempname; +static const char ** +append_cpp_args (const char **arg, cpp_arg_t *arg_list) +{ + cpp_arg_t *cpp_arg; + + for (cpp_arg = arg_list; cpp_arg; cpp_arg = cpp_arg->next) + *arg++ = cpp_arg->arg; + return arg; +} + static void add_cpp_arg (const char *arg) { @@ -83,6 +97,28 @@ add_cpp_arg (const char *arg) cpp_argc++; } +void +add_cpp_sysinc (const char *arg) +{ + cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); + cpp_arg->next = 0; + cpp_arg->arg = arg; + *cpp_sysinc_tail = cpp_arg; + cpp_sysinc_tail = &(*cpp_sysinc_tail)->next; + cpp_argc++; +} + +void +add_cpp_undef (const char *arg) +{ + cpp_arg_t *cpp_arg = malloc (sizeof (cpp_arg_t)); + cpp_arg->next = 0; + cpp_arg->arg = arg; + *cpp_undef_tail = cpp_arg; + cpp_undef_tail = &(*cpp_undef_tail)->next; + cpp_argc++; +} + void add_cpp_def (const char *arg) { @@ -117,7 +153,6 @@ static void build_cpp_args (const char *in_name, const char *out_name) { cpp_arg_t *cpp_arg; - cpp_arg_t *cpp_def; const char **arg; if (cpp_argv) @@ -126,9 +161,12 @@ build_cpp_args (const char *in_name, const char *out_name) for (arg = cpp_argv, cpp_arg = cpp_arg_list; cpp_arg; cpp_arg = cpp_arg->next) { - if (!strcmp (cpp_arg->arg, "%d")) { - for (cpp_def = cpp_def_list; cpp_def; cpp_def = cpp_def->next) - *arg++ = cpp_def->arg; + if (!strcmp (cpp_arg->arg, "%u")) { + arg = append_cpp_args (arg, cpp_undef_list); + } else if (!strcmp (cpp_arg->arg, "%s")) { + arg = append_cpp_args (arg, cpp_sysinc_list); + } else if (!strcmp (cpp_arg->arg, "%d")) { + arg = append_cpp_args (arg, cpp_def_list); } else if (!strcmp (cpp_arg->arg, "%i")) { *arg++ = in_name; } else if (!strcmp (cpp_arg->arg, "%o")) { diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index cfd1e27bf..c3f283e89 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -299,6 +299,8 @@ DecodeArgs (int argc, char **argv) int c; int saw_E = 0, saw_MD = 0; + add_cpp_undef ("-undef"); + add_cpp_undef ("-nostdinc"); add_cpp_def ("-D__QFCC__=1"); add_cpp_def ("-D__QUAKEC__=1"); @@ -720,7 +722,8 @@ DecodeArgs (int argc, char **argv) // add the default paths if (!options.no_default_paths) { - add_cpp_def (nva ("-I%s", QFCC_INCLUDE_PATH)); + add_cpp_sysinc ("-isystem"); + add_cpp_sysinc (QFCC_INCLUDE_PATH); linker_add_path (QFCC_LIB_PATH); } From a65d6bce09d08fdc1d33f56eb21033dc321684d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 02:43:27 +0900 Subject: [PATCH 0332/3664] Fix a warning that got through I forgot to compile test in optimized... --- tools/qfcc/source/function.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 4d3a617e9..538bb8f65 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -155,7 +155,7 @@ parse_params (type_t *type, param_t *parms) { param_t *p; type_t *new; - int count; + int count = 0; new = new_type (); new->type = ev_func; @@ -168,7 +168,9 @@ parse_params (type_t *type, param_t *parms) count++; } } - new->t.func.param_types = malloc (count * sizeof (type_t)); + if (count) { + new->t.func.param_types = malloc (count * sizeof (type_t)); + } for (p = parms; p; p = p->next) { if (!p->selector && !p->type && !p->name) { if (p->next) From 4c40928112099d7c736a6b5819d0dc84411fde11 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 02:53:38 +0900 Subject: [PATCH 0333/3664] Remove what appears to be a redundant check It was long wrong anyway as it checked past the end of the function's parameters, which caused a segfault when calling varargs functions with no formal parameters. --- tools/qfcc/source/expr.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 7d7e55a21..03e3ddc6a 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1892,11 +1892,6 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params) if (type_size (t) > type_size (&type_param)) err = error (e, "formal parameter %d is too large to be passed by" " value", i + 1); - if (ftype->t.func.param_types[i] == &type_float - && is_integer_val (e)) { - convert_int (e); - t = &type_float; - } if (i < parm_count) { if (e->type == ex_nil) convert_nil (e, t = ftype->t.func.param_types[i]); @@ -1934,7 +1929,8 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params) for (e = params, i = 0; e; e = e->next, i++) { if (has_function_call (e)) { *a = new_temp_def_expr (arg_types[i]); - arg_exprs[arg_expr_count][0] = cast_expr (arg_types[i], convert_vector (e)); + arg_exprs[arg_expr_count][0] = cast_expr (arg_types[i], + convert_vector (e)); arg_exprs[arg_expr_count][1] = *a; arg_expr_count++; } else { From 67e183c8b65cad0745c063f5e830a9a45552ea1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 10:46:16 +0900 Subject: [PATCH 0334/3664] Put the guts of qwaq's reflection code into ruamoko --- ruamoko/include/Makefile.am | 2 +- ruamoko/include/types.h | 84 +++++++++++++++++++++++++++++++++++++ ruamoko/lib/Makefile.am | 2 +- ruamoko/lib/types.r | 28 +++++++++++++ tools/qwaq/types.r | 2 + 5 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 ruamoko/include/types.h create mode 100644 ruamoko/lib/types.r diff --git a/ruamoko/include/Makefile.am b/ruamoko/include/Makefile.am index d978b3a70..b11080d13 100644 --- a/ruamoko/include/Makefile.am +++ b/ruamoko/include/Makefile.am @@ -3,7 +3,7 @@ pkgincludedir= $(datarootdir)/qfcc/include nobase_pkginclude_HEADERS= \ crudefile.h debug.h entities.h infokey.h math.h message.h nq_message.h \ physics.h msgbuf.h qfile.h qfs.h qw_message.h qw_physics.h qw_sys.h \ - server.h sound.h script.h string.h sv_sound.h system.h \ + server.h sound.h script.h string.h sv_sound.h system.h types.h \ \ draw.h key.h \ \ diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h new file mode 100644 index 000000000..8ff66e10c --- /dev/null +++ b/ruamoko/include/types.h @@ -0,0 +1,84 @@ +#ifndef __types_h +#define __types_h + +typedef enum { + ev_void, + ev_string, + ev_float, + ev_vector, + ev_entity, + ev_field, + ev_func, + ev_pointer, // end of v6 types + ev_quat, + ev_integer, + ev_uinteger, + ev_short, // value is embedded in the opcode + ev_double, + + ev_invalid, // invalid type. used for instruction checking + ev_type_count // not a type, gives number of types +} etype_t; + +typedef enum { + ty_none, ///< func/field/pointer or not used + ty_struct, + ty_union, + ty_enum, + ty_array, + ty_class, +} ty_meta_e; + +typedef struct qfot_fldptr_s { + etype_t type; + struct qfot_type_s *aux_type; +} qfot_fldptr_t; + +typedef struct qfot_func_s { + etype_t type; + struct qfot_type_s *return_type; + int num_params; + struct qfot_type_s *param_types[1]; +} qfot_func_t; + +typedef struct qfot_var_s { + struct qfot_type_s *type; + string name; + int offset; // value for enum, 0 for union +} qfot_var_t; + +typedef struct qfot_struct_s { + string tag; + int num_fields; + qfot_var_t fields[1]; +} qfot_struct_t; + +typedef struct qfot_array_s { + struct qfot_type_s *type; + int base; + int size; +} qfot_array_t; + +typedef struct qfot_type_s { + ty_meta_e meta; + int size; + string encoding; + union { + etype_t type; + qfot_fldptr_t fldptr; + qfot_func_t func; + qfot_struct_t strct; + qfot_array_t array; + string class; + } t; +} qfot_type_t; + +typedef struct qfot_type_encodings_s { + qfot_type_t *types; + int size; +} qfot_type_encodings_t; + +@extern string ty_meta_name[6]; +@extern string pr_type_name[ev_type_count]; + +#endif diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index 53a20875b..e4b475d64 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -27,7 +27,7 @@ SUFFIXES= .o .r .qc libr_a_SOURCES=\ cbuf.r cmd.r cvar.r file.r hash.r msgbuf.r plist.r qfile.r qfs.r script.r \ - sound.r string.r math.r \ + sound.r string.r math.r types.r \ Object.r Protocol.r \ AutoreleasePool.r Array.r Array+Private.r Entity.r PropertyList.r Set.r libr_a_AR=$(PAK) -cf diff --git a/ruamoko/lib/types.r b/ruamoko/lib/types.r new file mode 100644 index 000000000..66140b83f --- /dev/null +++ b/ruamoko/lib/types.r @@ -0,0 +1,28 @@ +#include +#include + +string ty_meta_name[6] = { + "basic", + "struct", + "union", + "enum", + "array", + "class", +}; + +string pr_type_name[ev_type_count] = { + "void", + "string", + "float", + "vector", + "entity", + "field", + "function", + "pointer", + "quaternion", + "integer", + "uinteger", + "short", + "double" + "invalid", +}; diff --git a/tools/qwaq/types.r b/tools/qwaq/types.r index 82665e20a..324185b93 100644 --- a/tools/qwaq/types.r +++ b/tools/qwaq/types.r @@ -12,6 +12,7 @@ typedef enum { ev_integer, ev_uinteger, ev_short, // value is embedded in the opcode + ev_double, ev_invalid, // invalid type. used for instruction checking ev_type_count // not a type, gives number of types @@ -107,6 +108,7 @@ string pr_type_name[ev_type_count] = { "integer", "uinteger", "short", + "double" "invalid", }; From 7a315b4a893393709e0cba381f889ccafaaee798 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 10:50:15 +0900 Subject: [PATCH 0335/3664] Fix storage class for for-loop declarations Getting "i redeclared" when i was declared in a for loop in two different functions was a tad unexpected. --- tools/qfcc/source/qc-parse.y | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a2bbf1c03..a71563abb 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -153,7 +153,7 @@ int yylex (void); %token PROTECTED PROTOCOL PUBLIC SELECTOR REFERENCE SELF THIS %type optional_specifiers specifiers local_specifiers -%type storage_class save_storage +%type storage_class save_storage set_spec_storage %type type_specifier type_specifier_or_storage_class %type type @@ -349,6 +349,14 @@ save_storage } ; +set_spec_storage + : /* emtpy */ + { + $$ = $0; + $$.storage = current_storage; + } + ; + function_body : optional_state_expr { @@ -1229,7 +1237,7 @@ switch_block opt_init : cexpr - | type init_var_decl_list { $$ = $2; } + | type set_spec_storage init_var_decl_list { $$ = $3; } | /* empty */ { $$ = 0; From a6f3e1753a1376a4ffead4b943d39fe6a8b229e0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 12:58:55 +0900 Subject: [PATCH 0336/3664] Fix ruamoko's hashtab_t typedef Being typedefed directly to a pointer is a holdover from when pointer declarations were really awkward. --- ruamoko/include/hash.h | 32 ++++++++++++++++---------------- ruamoko/lib/hash.r | 30 +++++++++++++++--------------- ruamoko/scheme/Machine.h | 2 +- ruamoko/scheme/Symbol.r | 2 +- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ruamoko/include/hash.h b/ruamoko/include/hash.h index 8c07169aa..2d0aa80fc 100644 --- a/ruamoko/include/hash.h +++ b/ruamoko/include/hash.h @@ -1,24 +1,24 @@ #ifndef __ruamoko_hash_h #define __ruamoko_hash_h -typedef struct _hashtab_t *hashtab_t; +typedef struct _hashtab_t hashtab_t; -@extern hashtab_t Hash_NewTable (int size, string gk (void *ele, void *data), void f (void *ele, void *data), void *ud); -@extern void Hash_SetHashCompare (hashtab_t tab, unsigned gh (void *ele, void *data), int cmp (void *ele1, void *ele2, void *data)); -@extern void Hash_DelTable (hashtab_t tab); -@extern void Hash_FlushTable (hashtab_t tab); -@extern int Hash_Add (hashtab_t tab, void *ele); -@extern int Hash_AddElement (hashtab_t tab, void *ele); -@extern void *Hash_Find (hashtab_t tab, string key); -@extern void *Hash_FindElement (hashtab_t tab, void *ele); -@extern void **Hash_FindList (hashtab_t tab, string key); -@extern void **Hash_FindElementList (hashtab_t tab, void *ele); -@extern void *Hash_Del (hashtab_t tab, string key); -@extern void *Hash_DelElement (hashtab_t tab, void *ele); -@extern void Hash_Free (hashtab_t tab, void *ele); +@extern hashtab_t *Hash_NewTable (int size, string gk (void *ele, void *data), void f (void *ele, void *data), void *ud); +@extern void Hash_SetHashCompare (hashtab_t *tab, unsigned gh (void *ele, void *data), int cmp (void *ele1, void *ele2, void *data)); +@extern void Hash_DelTable (hashtab_t *tab); +@extern void Hash_FlushTable (hashtab_t *tab); +@extern int Hash_Add (hashtab_t *tab, void *ele); +@extern int Hash_AddElement (hashtab_t *tab, void *ele); +@extern void *Hash_Find (hashtab_t *tab, string key); +@extern void *Hash_FindElement (hashtab_t *tab, void *ele); +@extern void **Hash_FindList (hashtab_t *tab, string key); +@extern void **Hash_FindElementList (hashtab_t *tab, void *ele); +@extern void *Hash_Del (hashtab_t *tab, string key); +@extern void *Hash_DelElement (hashtab_t *tab, void *ele); +@extern void Hash_Free (hashtab_t *tab, void *ele); @extern int Hash_String (string str); @extern int Hash_Buffer (void *buf, int len); -@extern void **Hash_GetList (hashtab_t tab); -@extern void Hash_Stats (hashtab_t tab); +@extern void **Hash_GetList (hashtab_t *tab); +@extern void Hash_Stats (hashtab_t *tab); #endif // __ruamoko_hash_h diff --git a/ruamoko/lib/hash.r b/ruamoko/lib/hash.r index 24844bfc2..a70d59b10 100644 --- a/ruamoko/lib/hash.r +++ b/ruamoko/lib/hash.r @@ -1,19 +1,19 @@ #include "hash.h" -hashtab_t Hash_NewTable (int size, string gk (void *ele, void *data), void f (void *ele, void *data), void *ud) = #0; -void Hash_SetHashCompare (hashtab_t tab, unsigned gh (void *ele, void *data), int cmp (void *ele1, void *ele2, void *data)) = #0; -void Hash_DelTable (hashtab_t tab) = #0; -void Hash_FlushTable (hashtab_t tab) = #0; -int Hash_Add (hashtab_t tab, void *ele) = #0; -int Hash_AddElement (hashtab_t tab, void *ele) = #0; -void *Hash_Find (hashtab_t tab, string key) = #0; -void *Hash_FindElement (hashtab_t tab, void *ele) = #0; -void **Hash_FindList (hashtab_t tab, string key) = #0; -void **Hash_FindElementList (hashtab_t tab, void *ele) = #0; -void *Hash_Del (hashtab_t tab, string key) = #0; -void *Hash_DelElement (hashtab_t tab, void *ele) = #0; -void Hash_Free (hashtab_t tab, void *ele) = #0; +hashtab_t *Hash_NewTable (int size, string gk (void *ele, void *data), void f (void *ele, void *data), void *ud) = #0; +void Hash_SetHashCompare (hashtab_t *tab, unsigned gh (void *ele, void *data), int cmp (void *ele1, void *ele2, void *data)) = #0; +void Hash_DelTable (hashtab_t *tab) = #0; +void Hash_FlushTable (hashtab_t *tab) = #0; +int Hash_Add (hashtab_t *tab, void *ele) = #0; +int Hash_AddElement (hashtab_t *tab, void *ele) = #0; +void *Hash_Find (hashtab_t *tab, string key) = #0; +void *Hash_FindElement (hashtab_t *tab, void *ele) = #0; +void **Hash_FindList (hashtab_t *tab, string key) = #0; +void **Hash_FindElementList (hashtab_t *tab, void *ele) = #0; +void *Hash_Del (hashtab_t *tab, string key) = #0; +void *Hash_DelElement (hashtab_t *tab, void *ele) = #0; +void Hash_Free (hashtab_t *tab, void *ele) = #0; int Hash_String (string str) = #0; int Hash_Buffer (void *buf, int len) = #0; -void **Hash_GetList (hashtab_t tab) = #0; -void Hash_Stats (hashtab_t tab) = #0; +void **Hash_GetList (hashtab_t *tab) = #0; +void Hash_Stats (hashtab_t *tab) = #0; diff --git a/ruamoko/scheme/Machine.h b/ruamoko/scheme/Machine.h index 7c99a2433..a7da59f61 100644 --- a/ruamoko/scheme/Machine.h +++ b/ruamoko/scheme/Machine.h @@ -11,7 +11,7 @@ { state_t state; SchemeObject *value; - hashtab_t globals; + hashtab_t *globals; SchemeObject *all_globals; } - (void) loadCode: (CompiledCode *) code; diff --git a/ruamoko/scheme/Symbol.r b/ruamoko/scheme/Symbol.r index 0704b3a50..b83f3dbd6 100644 --- a/ruamoko/scheme/Symbol.r +++ b/ruamoko/scheme/Symbol.r @@ -16,7 +16,7 @@ void SymbolFree (void *ele, void *data) [s release]; } -hashtab_t symbols; +hashtab_t *symbols; Symbol *lparen; Symbol *rparen; Symbol *quote; From b00c866c4e32d109de7c2dc683eff4f3c4e0378f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 13:00:36 +0900 Subject: [PATCH 0337/3664] Allow casting between string and pointer types --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/expr.c | 5 +++++ tools/qfcc/source/type.c | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index fcb4a808a..33d283462 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -166,6 +166,7 @@ int is_field (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); int is_func (const type_t *type) __attribute__((pure)); +int is_string (const type_t *type) __attribute__((pure)); int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); int type_size (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 03e3ddc6a..691a03162 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2595,6 +2595,11 @@ cast_expr (type_t *type, expr_t *e) if ((type == type_default && is_enum (e_type)) || (is_enum (type) && e_type == type_default)) return e; + if ((is_pointer (type) && is_string (e_type)) + || (is_string (type) && is_pointer (e_type))) { + c = new_alias_expr (type, e); + return c; + } if (!(type->type == ev_pointer && (e_type->type == ev_pointer || is_integral (e_type) || is_array (e_type))) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 289b76563..c0d5b58e3 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -785,6 +785,14 @@ is_func (const type_t *type) return 0; } +int +is_string (const type_t *type) +{ + if (type->type == ev_string) + return 1; + return 0; +} + int type_compatible (const type_t *dst, const type_t *src) { From 2db5d04e3f5cfdd76e2cf3ab0214f3cae7e52caf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 14:40:01 +0900 Subject: [PATCH 0338/3664] Reduce the ephemeral nature of str_mid When the substring is the tail of the supplied string, return a "pointer" to within the supplied string rather than a new "return" string. This means that tail-end substrings of string constants are themselves constants. --- libs/ruamoko/rua_string.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 7f233e362..fcd78c1cc 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -112,6 +112,10 @@ bi_str_mid (progs_t *pr) end = size; if (pos < 0 || pos >= size || end <= pos) return; + if (end == size) { + R_STRING (pr) = str + pos - pr->pr_strings; + return; + } temp = alloca (end - pos + 1); strncpy (temp, str + pos, end - pos); temp[end - pos] = 0; From adb7f5d601b793a077b033cef3d4b4340f6d06de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 16:21:55 +0900 Subject: [PATCH 0339/3664] Quieten the test script build rules --- tools/qfcc/test/Makefile.am | 78 ++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index d9d66090a..fd2603f61 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -104,7 +104,7 @@ address_cast_obj=$(address_cast_dat_SOURCES:.r=.qfo) address-cast.dat$(EXEEXT): $(address_cast_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(address_cast_obj) address-cast.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/address-cast.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/address-cast.Qo @@ -113,7 +113,7 @@ alignment_obj=$(alignment_dat_SOURCES:.r=.qfo) alignment.dat$(EXEEXT): $(alignment_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(alignment_obj) alignment.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/alignment.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/alignment.Qo @@ -122,7 +122,7 @@ chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo) chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_alias_obj) chewed-alias.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/chewed-alias.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/chewed-alias.Qo @@ -131,7 +131,7 @@ chewed_return_obj=$(chewed_return_dat_SOURCES:.r=.qfo) chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_return_obj) chewed-return.run: Makefile build-run - TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ + @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ include ./$(DEPDIR)/chewed-return.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/chewed-return.Qo @@ -140,7 +140,7 @@ comma_expr_obj=$(comma_expr_dat_SOURCES:.r=.qfo) comma-expr.dat$(EXEEXT): $(comma_expr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(comma_expr_obj) comma-expr.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/comma-expr.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/comma-expr.Qo @@ -149,7 +149,7 @@ deadbool_obj=$(deadbool_dat_SOURCES:.r=.qfo) deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(deadbool_obj) deadbool.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/deadbool.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/deadbool.Qo @@ -158,46 +158,46 @@ double_obj=$(double_dat_SOURCES:.r=.qfo) double.dat$(EXEEXT): $(double_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(double_obj) double.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/double.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/double.Qo double-demote-int.run$(EXEEXT): double-demote-int.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< double-demote-float.run$(EXEEXT): double-demote-float.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< double-demote-int-ainit.run$(EXEEXT): double-demote-int-ainit.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< double-demote-float-ainit.run$(EXEEXT): double-demote-float-ainit.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< double-demote-int-ginit.run$(EXEEXT): double-demote-int-ginit.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< double-demote-float-ginit.run$(EXEEXT): double-demote-float-ginit.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< double-demote-int-linit.run$(EXEEXT): double-demote-int-linit.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< double-demote-float-linit.run$(EXEEXT): double-demote-float-linit.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< double-int-compare.run$(EXEEXT): double-int-compare.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< double-float-compare.run$(EXEEXT): double-float-compare.r Makefile build-compile-fail-run - $(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< enum_dat_SOURCES=enum.r enum_obj=$(enum_dat_SOURCES:.r=.qfo) enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(enum_obj) enum.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/enum.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/enum.Qo @@ -206,7 +206,7 @@ fordecl_obj=$(fordecl_dat_SOURCES:.r=.qfo) fordecl.dat$(EXEEXT): $(fordecl_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(fordecl_obj) fordecl.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/fordecl.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/fordecl.Qo @@ -215,7 +215,7 @@ func_expr_obj=$(func_expr_dat_SOURCES:.r=.qfo) func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) func-expr.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/func-expr.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/func-expr.Qo @@ -224,7 +224,7 @@ func_static_obj=$(func_static_dat_SOURCES:.r=.qfo) func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) func-static.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/func-static.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/func-static.Qo @@ -233,7 +233,7 @@ infloop_obj=$(infloop_dat_SOURCES:.r=.qfo) infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(infloop_obj) infloop.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/infloop.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/infloop.Qo @@ -242,7 +242,7 @@ ivar_struct_return_obj=$(ivar_struct_return_dat_SOURCES:.r=.qfo) ivar-struct-return.dat$(EXEEXT): $(ivar_struct_return_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(ivar_struct_return_obj) ivar-struct-return.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/ivar-struct-return.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/ivar-struct-return.Qo @@ -251,7 +251,7 @@ modulo_obj=$(modulo_dat_SOURCES:.r=.qfo) modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(modulo_obj) modulo.run: Makefile build-run - TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ + @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ include ./$(DEPDIR)/modulo.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/modulo.Qo @@ -260,7 +260,7 @@ paramret_obj=$(paramret_dat_SOURCES:.r=.qfo) paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) paramret.run: Makefile build-run - TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ + @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ include ./$(DEPDIR)/paramret.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/paramret.Qo @@ -269,7 +269,7 @@ quaternion_obj=$(quaternion_dat_SOURCES:.r=.qfo) quaternion.dat$(EXEEXT): $(quaternion_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(quaternion_obj) quaternion.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/quaternion.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/quaternion.Qo @@ -278,7 +278,7 @@ return_ivar_obj=$(return_ivar_dat_SOURCES:.r=.qfo) return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(return_ivar_obj) return-ivar.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/return-ivar.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/return-ivar.Qo @@ -287,7 +287,7 @@ sendv_obj=$(sendv_dat_SOURCES:.r=.qfo) sendv.dat$(EXEEXT): $(sendv_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(sendv_obj) sendv.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/sendv.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/sendv.Qo @@ -296,7 +296,7 @@ state_obj=$(state_dat_SOURCES:.r=.qfo) state.dat$(EXEEXT): $(state_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(state_obj) state.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/state.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/state.Qo @@ -305,7 +305,7 @@ structarray_obj=$(structarray_dat_SOURCES:.r=.qfo) structarray.dat$(EXEEXT): $(structarray_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structarray_obj) structarray.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/structarray.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/structarray.Qo @@ -314,7 +314,7 @@ structlive_obj=$(structlive_dat_SOURCES:.r=.qfo) structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structlive_obj) structlive.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/structlive.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/structlive.Qo @@ -323,7 +323,7 @@ structptr_obj=$(structptr_dat_SOURCES:.r=.qfo) structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structptr_obj) structptr.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/structptr.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/structptr.Qo @@ -332,7 +332,7 @@ structstruct_obj=$(structstruct_dat_SOURCES:.r=.qfo) structstruct.dat$(EXEEXT): $(structstruct_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structstruct_obj) structstruct.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/structstruct.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/structstruct.Qo @@ -341,7 +341,7 @@ swap_obj=$(swap_dat_SOURCES:.r=.qfo) swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(swap_obj) swap.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/swap.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/swap.Qo @@ -350,7 +350,7 @@ triangle_obj=$(triangle_dat_SOURCES:.r=.qfo) triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) triangle.run: Makefile build-run - $(srcdir)/build-run $@ 100000 100000 1.00005 50002.4961 + @$(srcdir)/build-run $@ 100000 100000 1.00005 50002.4961 include ./$(DEPDIR)/triangle.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/triangle.Qo @@ -359,7 +359,7 @@ vecexpr_obj=$(vecexpr_dat_SOURCES:.r=.qfo) vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(vecexpr_obj) vecexpr.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/vecexpr.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/vecexpr.Qo @@ -368,7 +368,7 @@ vecinit_obj=$(vecinit_dat_SOURCES:.r=.qfo) vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(vecinit_obj) vecinit.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/vecinit.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/vecinit.Qo @@ -377,7 +377,7 @@ voidfor_obj=$(voidfor_dat_SOURCES:.r=.qfo) voidfor.dat$(EXEEXT): $(voidfor_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj) voidfor.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/voidfor.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/voidfor.Qo @@ -386,7 +386,7 @@ while_obj=$(while_dat_SOURCES:.r=.qfo) while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(while_obj) while.run: Makefile build-run - $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/while.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/while.Qo From 2f18364364ee1340b8108ddee315c288ccde2978 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 17:05:25 +0900 Subject: [PATCH 0340/3664] Start work on encoding typedef chains --- include/QF/pr_type.h | 7 ++++ ruamoko/include/types.h | 8 +++++ tools/qfcc/include/type.h | 6 ++++ tools/qfcc/source/dump_globals.c | 4 +++ tools/qfcc/source/obj_file.c | 6 ++++ tools/qfcc/source/type.c | 15 ++++++++ tools/qfcc/test/Makefile.am | 14 ++++++-- tools/qfcc/test/typedef.r | 62 ++++++++++++++++++++++++++++++++ 8 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 tools/qfcc/test/typedef.r diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index 0c8b37664..0e33b0fd6 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -40,6 +40,12 @@ #include "QF/pr_comp.h" +typedef struct qfot_alias_s { + pr_int_t type; ///< type at end of alias chain + pointer_t aux_type; ///< referenced type + string_t name; ///< alias name +} qfot_alias_t; + typedef struct qfot_fldptr_s { pr_int_t type; ///< ev_field or ev_pointer pointer_t aux_type; ///< referenced type @@ -94,6 +100,7 @@ typedef struct qfot_type_s { qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum qfot_array_t array; ///< ty_array pointer_t class; ///< ty_class + qfot_alias_t alias; ///< ty_alias } t; } qfot_type_t; diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index 8ff66e10c..deb480ebf 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -27,8 +27,15 @@ typedef enum { ty_enum, ty_array, ty_class, + ty_alias, } ty_meta_e; +typedef struct qfot_alias_s { + etype_t type; + struct qfot_type_s *aux_type; + string name; +} qfot_alias_t; + typedef struct qfot_fldptr_s { etype_t type; struct qfot_type_s *aux_type; @@ -70,6 +77,7 @@ typedef struct qfot_type_s { qfot_struct_t strct; qfot_array_t array; string class; + qfot_alias_t alias; } t; } qfot_type_t; diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 33d283462..45aecd293 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -51,6 +51,10 @@ typedef struct ty_array_s { int size; } ty_array_t; +typedef struct ty_alias_s { + struct type_s *type; +} ty_alias_t; + typedef enum { ty_none, ///< func/field/pointer or not used ty_struct, @@ -58,6 +62,7 @@ typedef enum { ty_enum, ty_array, ty_class, + ty_alias, } ty_meta_e; typedef struct type_s { @@ -72,6 +77,7 @@ typedef struct type_s { ty_array_t array; struct symtab_s *symtab; struct class_s *class; + ty_alias_t alias; } t; struct type_s *next; int freeable; diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 9e0b5bd5f..d77f5af32 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -493,6 +493,10 @@ dump_qfo_types (qfo_t *qfo, int base_address) printf (" %-5x %d %d\n", type->t.array.type, type->t.array.base, type->t.array.size); break; + case ty_alias: + printf (" %s %-5x\n", QFO_GETSTR (qfo, type->t.alias.name), + type->t.alias.type); + break; case ty_class: printf (" %-5x\n", type->t.class); break; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 44148eec8..e49d64c46 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -648,8 +648,10 @@ get_def_type (qfo_t *qfo, pointer_t type) type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { case ty_none: + case ty_alias: // field, pointer and function types store their basic type in // the same location. + // alias types store the basic type at the end of the alias chain return type_def->t.type; case ty_struct: case ty_union: @@ -674,9 +676,11 @@ get_type_size (qfo_t *qfo, pointer_t type) return 1; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { + case ty_alias: case ty_none: // field, pointer and function types store their basic type in // the same location. + // alias types store the basic type at the end of the alias chain return pr_type_size[type_def->t.type]; case ty_struct: for (i = size = 0; i < type_def->t.strct.num_fields; i++) @@ -723,8 +727,10 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { case ty_none: + case ty_alias: // field, pointer and function types store their basic type in // the same location. + // alias types store the basic type at the end of the alias chain return qfo_log2 (ev_types[type_def->t.type]->alignment); case ty_struct: case ty_union: diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index c0d5b58e3..5ffd2b7be 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -292,6 +292,8 @@ types_same (type_t *a, type_t *b) if (a->t.class != b->t.class) return 0; return compare_protocols (a->protos, b->protos); + case ty_alias: + return !strcmp (a->name, b->name); } internal_error (0, "we be broke"); } @@ -341,6 +343,9 @@ find_type (type_t *type) break; case ty_class: break; + case ty_alias: + type->t.alias.type = find_type (type->t.alias.type); + break; } } @@ -512,6 +517,11 @@ print_type_str (dstring_t *str, const type_t *type) dasprintf (str, "[%d]", type->t.array.size); } break; + case ty_alias: + dasprintf (str, "({%s=", type->name); + print_type_str (str, type->t.alias.type); + dstring_appendstr (str, "})"); + break; case ty_none: break; } @@ -671,6 +681,9 @@ encode_type (dstring_t *encoding, const type_t *type) encode_type (encoding, type->t.array.type); dasprintf (encoding, "]"); break; + case ty_alias: + encode_type (encoding, type->t.alias.type); + break; case ty_none: dasprintf (encoding, "?"); break; @@ -892,6 +905,8 @@ type_size (const type_t *type) } case ty_array: return type->t.array.size * type_size (type->t.array.type); + case ty_alias: + return type_size (type->t.alias.type); case ty_none: return 0; } diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index fd2603f61..e715b38ed 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -9,8 +9,8 @@ AM_CPPFLAGS= -I$(top_srcdir)/include $(QFCC_INCS) QFCC_DEP=$(builddir)/../source/qfcc$(EXEEXT) QFCC=$(QFCC_DEP) -QCFLAGS=-qq -O -g --no-default-paths -Werror -QCPPFLAGS= +QCFLAGS=-qq -O -g -Werror +QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) SUFFIXES=.qfo .r @@ -54,6 +54,7 @@ test_progs_dat=\ structstruct.dat \ swap.dat \ triangle.dat \ + typedef.dat \ vecexpr.dat \ vecinit.dat \ voidfor.dat \ @@ -354,6 +355,15 @@ triangle.run: Makefile build-run include ./$(DEPDIR)/triangle.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/triangle.Qo +typedef_dat_SOURCES=typedef.r +typedef_obj=$(typedef_dat_SOURCES:.r=.qfo) +typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) +typedef.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/typedef.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/typedef.Qo + vecexpr_dat_SOURCES=vecexpr.r vecexpr_obj=$(vecexpr_dat_SOURCES:.r=.qfo) vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/typedef.r b/tools/qfcc/test/typedef.r new file mode 100644 index 000000000..48ea84478 --- /dev/null +++ b/tools/qfcc/test/typedef.r @@ -0,0 +1,62 @@ +#include + +// can't link against libr.a (may not be built) +void *PR_FindGlobal (string name) = #0; +void printf (string fmt, ...) = #0; + +qfot_type_encodings_t *encodings; + +typedef int *foo; +typedef int *bar; + +foo baz; +bar snafu; + +qfot_type_t * +next_type (qfot_type_t *type) +{ + int size = type.size; + if (!size) + size = 4; + return (qfot_type_t *) ((int *) type + size); +} + +int +main (void) +{ + int found_foo = 0; + int found_bar = 0; + qfot_type_t *type; + qfot_type_t *alias; + + baz = snafu; // must be able to assign without warnings (won't compile) + + encodings = PR_FindGlobal (".type_encodings"); + + for (type = encodings.types; + ((int *)type - (int *) encodings.types) < encodings.size; + type = next_type (type)) { + if (type.meta == ty_alias && type.t.alias.type == ev_integer) { + alias = type.t.alias.aux_type; + if (type.t.alias.name == "foo") { + if (alias.meta == ty_none && alias.t.type == ev_integer) { + found_foo = 1; + } else { + printf ("foo type not aliased to int\n"); + } + } + if (type.t.alias.name == "bar") { + if (alias.meta == ty_none && alias.t.type == ev_integer) { + found_bar = 1; + } else { + printf ("bar type not aliased to int\n"); + } + } + } + } + if (!(found_bar && found_foo)) { + printf ("missing typedef: foo: %d bar:%d\n", found_foo, found_bar); + return 1; + } + return 0; +} From a5aba6c8ac80dc680ba9f0e324cee01d397b0fc9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 18:11:43 +0900 Subject: [PATCH 0341/3664] Implement type aliasing The separate types are in the file, but there are multiple issues --- tools/qfcc/include/type.h | 6 ++++-- tools/qfcc/source/dump_globals.c | 1 + tools/qfcc/source/obj_type.c | 19 ++++++++++++++++++- tools/qfcc/source/qc-parse.y | 1 + tools/qfcc/source/type.c | 19 +++++++++++++++++++ 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 45aecd293..1efbfc21a 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -138,8 +138,9 @@ void chain_type (type_t *type); /** Append a type to the end of a type chain. - The type chain must be made up of only field, pointer, function and array - types, as other types do not have auxiliary type fields. + The type chain must be made up of only field, pointer, function, array + and alias (typedef) types, as other types do not have auxiliary type + fields. \param type The type chain to which the type will be appended. \param new The type to be appended. May be any type. @@ -153,6 +154,7 @@ type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); type_t *array_type (type_t *aux, int size); type_t *based_array_type (type_t *aux, int base, int top); +type_t *alias_type (type_t *aux, const char *name); void print_type_str (struct dstring_s *str, const type_t *type); void print_type (const type_t *type); const char *encode_params (const type_t *type); diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index d77f5af32..7f4adbbc9 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -423,6 +423,7 @@ static const char *ty_meta_names[] = { "ty_enum", "ty_array", "ty_class", + "ty_alias", }; #define NUM_META ((int)(sizeof (ty_meta_names) / sizeof (ty_meta_names[0]))) diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 55da5c137..e67f7a0b5 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -253,6 +253,22 @@ qfo_encode_class (type_t *type) return def; } +static def_t * +qfo_encode_alias (type_t *type) +{ + qfot_type_t *enc; + def_t *def; + def_t *alias_type_def; + + alias_type_def = qfo_encode_type (type->t.alias.type); + + def = qfo_new_encoding (type, sizeof (enc->t.alias)); + enc = D_POINTER (qfot_type_t, def); + ENC_DEF (enc->t.alias.type, alias_type_def); + ENC_STR (enc->t.alias.name, type->name); + return def; +} + def_t * qfo_encode_type (type_t *type) { @@ -265,6 +281,7 @@ qfo_encode_type (type_t *type) qfo_encode_struct, // ty_enum qfo_encode_array, // ty_array qfo_encode_class, // ty_class + qfo_encode_alias, // ty_alias }; if (type->type_def && type->type_def->external) { @@ -274,7 +291,7 @@ qfo_encode_type (type_t *type) } if (type->type_def) return type->type_def; - if (type->meta > ty_class) + if (type->meta > sizeof (funcs) / (sizeof (funcs[0]))) internal_error (0, "bad type meta type"); if (!type->encoding) type->encoding = type_get_encoding (type); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a71563abb..4773eb303 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -406,6 +406,7 @@ external_decl $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; + $1->type = alias_type ($1->type, $1->name); symtab_addsymbol (current_symtab, $1); } else { initialize_def ($1, 0, current_symtab->space, spec.storage); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 5ffd2b7be..964d2d367 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -445,6 +445,25 @@ based_array_type (type_t *aux, int base, int top) return new; } +type_t * +alias_type (type_t *aux, const char *name) +{ + type_t _new; + type_t *new = &_new; + + if (!aux || !name) { + internal_error (0, "alias to null type or with no name"); + } + memset (&_new, 0, sizeof (_new)); + new->name = save_string (name); + new->meta = ty_alias; + new->type = aux->type; + new->alignment = aux->alignment; + new->t.alias.type = aux; + new = find_type (new); + return new; +} + void print_type_str (dstring_t *str, const type_t *type) { From d50a27a045a9fb7cbe6a15cd3557b88e5d75a4ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 18:28:11 +0900 Subject: [PATCH 0342/3664] Race down the alias chain before checking types This takes care of some of the type aliasing issues. --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/type.c | 337 ++++++++++++++++++++------------------ 2 files changed, 182 insertions(+), 156 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 1efbfc21a..098df5e00 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -160,6 +160,7 @@ void print_type (const type_t *type); const char *encode_params (const type_t *type); void encode_type (struct dstring_s *encoding, const type_t *type); const char *type_get_encoding (const type_t *type); +const type_t *unalias_type (const type_t *type) __attribute__((pure)); int is_void (const type_t *type) __attribute__((pure)); int is_enum (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 964d2d367..2aff5c5d1 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -471,84 +471,95 @@ print_type_str (dstring_t *str, const type_t *type) dasprintf (str, " (null)"); return; } - switch (type->type) { - case ev_field: - dasprintf (str, ".("); - print_type_str (str, type->t.fldptr.type); - dasprintf (str, ")"); - break; - case ev_func: - print_type_str (str, type->t.func.type); - if (type->t.func.num_params == -1) { - dasprintf (str, "(...)"); + switch (type->meta) { + case ty_class: + dasprintf (str, " %s", type->t.class->name); + if (type->protos) + print_protocollist (str, type->protos); + return; + case ty_enum: + dasprintf (str, " enum %s", type->name); + return; + case ty_struct: + dasprintf (str, " struct %s", type->name); + return; + case ty_union: + dasprintf (str, " union %s", type->name); + return; + case ty_array: + print_type_str (str, type->t.array.type); + if (type->t.array.base) { + dasprintf (str, "[%d..%d]", type->t.array.base, + type->t.array.base + type->t.array.size - 1); } else { - int c, i; - dasprintf (str, "("); - if ((c = type->t.func.num_params) < 0) - c = ~c; // num_params is one's compliment - for (i = 0; i < c; i++) { - if (i) - dasprintf (str, ", "); - print_type_str (str, type->t.func.param_types[i]); - } - if (type->t.func.num_params < 0) - dasprintf (str, ", ..."); - dasprintf (str, ")"); + dasprintf (str, "[%d]", type->t.array.size); } - break; - case ev_pointer: - if (obj_is_id (type)) { - dasprintf (str, "id"); - if (type->t.fldptr.type->protos) - print_protocollist (str, type->t.fldptr.type->protos); - break; - } - if (type == &type_SEL) { - dasprintf (str, "SEL"); - break; - } - dasprintf (str, "(*"); - print_type_str (str, type->t.fldptr.type); - dasprintf (str, ")"); - break; - case ev_invalid: - switch (type->meta) { - case ty_class: - dasprintf (str, " %s", type->t.class->name); - if (type->protos) - print_protocollist (str, type->protos); - break; - case ty_enum: - dasprintf (str, " enum %s", type->name); - break; - case ty_struct: - dasprintf (str, " struct %s", type->name); - break; - case ty_union: - dasprintf (str, " union %s", type->name); - break; - case ty_array: - print_type_str (str, type->t.array.type); - if (type->t.array.base) { - dasprintf (str, "[%d..%d]", type->t.array.base, - type->t.array.base + type->t.array.size - 1); + return; + case ty_alias: + dasprintf (str, "({%s=", type->name); + print_type_str (str, type->t.alias.type); + dstring_appendstr (str, "})"); + return; + case ty_none: + switch (type->type) { + case ev_field: + dasprintf (str, ".("); + print_type_str (str, type->t.fldptr.type); + dasprintf (str, ")"); + return; + case ev_func: + print_type_str (str, type->t.func.type); + if (type->t.func.num_params == -1) { + dasprintf (str, "(...)"); } else { - dasprintf (str, "[%d]", type->t.array.size); + int c, i; + dasprintf (str, "("); + if ((c = type->t.func.num_params) < 0) + c = ~c; // num_params is one's compliment + for (i = 0; i < c; i++) { + if (i) + dasprintf (str, ", "); + print_type_str (str, type->t.func.param_types[i]); + } + if (type->t.func.num_params < 0) + dasprintf (str, ", ..."); + dasprintf (str, ")"); } - break; - case ty_alias: - dasprintf (str, "({%s=", type->name); - print_type_str (str, type->t.alias.type); - dstring_appendstr (str, "})"); - break; - case ty_none: + return; + case ev_pointer: + if (obj_is_id (type)) { + dasprintf (str, "id"); + if (type->t.fldptr.type->protos) + print_protocollist (str, type->t.fldptr.type->protos); + return; + } + if (type == &type_SEL) { + dasprintf (str, "SEL"); + return; + } + dasprintf (str, "(*"); + print_type_str (str, type->t.fldptr.type); + dasprintf (str, ")"); + return; + case ev_void: + case ev_string: + case ev_float: + case ev_vector: + case ev_entity: + case ev_quat: + case ev_integer: + case ev_uinteger: + case ev_short: + case ev_double: + dasprintf (str, " %s", pr_type_name[type->type]); + return; + case ev_invalid: + case ev_type_count: break; } break; - default: - dasprintf (str, " %s", pr_type_name[type->type]); - break; } + internal_error (0, "bad type meta:type %d:%d", type->meta, type->type); } void @@ -622,96 +633,103 @@ encode_type (dstring_t *encoding, const type_t *type) { if (!type) return; - switch (type->type) { - case ev_void: - dasprintf (encoding, "v"); - break; - case ev_string: - dasprintf (encoding, "*"); - break; - case ev_double: - dasprintf (encoding, "d"); - break; - case ev_float: - dasprintf (encoding, "f"); - break; - case ev_vector: - dasprintf (encoding, "V"); - break; - case ev_entity: - dasprintf (encoding, "E"); - break; - case ev_field: - dasprintf (encoding, "F"); - encode_type (encoding, type->t.fldptr.type); - break; - case ev_func: - dasprintf (encoding, "("); - encode_type (encoding, type->t.func.type); - dasprintf (encoding, "%s)", encode_params (type)); - break; - case ev_pointer: - if (type == &type_id) { - dasprintf (encoding, "@"); + switch (type->meta) { + case ty_class: + encode_class (encoding, type); + return; + case ty_enum: + encode_enum (encoding, type); + return; + case ty_struct: + case ty_union: + encode_struct (encoding, type); + return; + case ty_array: + dasprintf (encoding, "["); + dasprintf (encoding, "%d", type->t.array.size); + if (type->t.array.base) + dasprintf (encoding, ":%d", type->t.array.base); + dasprintf (encoding, "="); + encode_type (encoding, type->t.array.type); + dasprintf (encoding, "]"); + return; + case ty_alias: + encode_type (encoding, type->t.alias.type); + return; + case ty_none: + switch (type->type) { + case ev_void: + dasprintf (encoding, "v"); + return; + case ev_string: + dasprintf (encoding, "*"); + return; + case ev_double: + dasprintf (encoding, "d"); + return; + case ev_float: + dasprintf (encoding, "f"); + return; + case ev_vector: + dasprintf (encoding, "V"); + return; + case ev_entity: + dasprintf (encoding, "E"); + return; + case ev_field: + dasprintf (encoding, "F"); + encode_type (encoding, type->t.fldptr.type); + return; + case ev_func: + dasprintf (encoding, "("); + encode_type (encoding, type->t.func.type); + dasprintf (encoding, "%s)", encode_params (type)); + return; + case ev_pointer: + if (type == &type_id) { + dasprintf (encoding, "@"); + return; + } + if (type == &type_SEL) { + dasprintf (encoding, ":"); + return; + } + if (type == &type_Class) { + dasprintf (encoding, "#"); + return; + } + type = type->t.fldptr.type; + dasprintf (encoding, "^"); + encode_type (encoding, type); + return; + case ev_quat: + dasprintf (encoding, "Q"); + return; + case ev_integer: + dasprintf (encoding, "i"); + return; + case ev_uinteger: + dasprintf (encoding, "I"); + return; + case ev_short: + dasprintf (encoding, "s"); + return; + case ev_invalid: + case ev_type_count: break; } - if (type == &type_SEL) { - dasprintf (encoding, ":"); - break; - } - if (type == &type_Class) { - dasprintf (encoding, "#"); - break; - } - type = type->t.fldptr.type; - dasprintf (encoding, "^"); - encode_type (encoding, type); - break; - case ev_quat: - dasprintf (encoding, "Q"); - break; - case ev_integer: - dasprintf (encoding, "i"); - break; - case ev_uinteger: - dasprintf (encoding, "I"); - break; - case ev_short: - dasprintf (encoding, "s"); - break; - case ev_invalid: - switch (type->meta) { - case ty_class: - encode_class (encoding, type); - break; - case ty_enum: - encode_enum (encoding, type); - break; - case ty_struct: - case ty_union: - encode_struct (encoding, type); - break; - case ty_array: - dasprintf (encoding, "["); - dasprintf (encoding, "%d", type->t.array.size); - if (type->t.array.base) - dasprintf (encoding, ":%d", type->t.array.base); - dasprintf (encoding, "="); - encode_type (encoding, type->t.array.type); - dasprintf (encoding, "]"); - break; - case ty_alias: - encode_type (encoding, type->t.alias.type); - break; - case ty_none: - dasprintf (encoding, "?"); - break; - } - break; - case ev_type_count: - dasprintf (encoding, "?"); break; } + internal_error (0, "bad type meta:type %d:%d", type->meta, type->type); +} + +const type_t * +unalias_type (const type_t *type) +{ + while (type->meta == ty_alias) { + type = type->t.alias.type; + } + return type; } int @@ -723,6 +741,7 @@ is_void (const type_t *type) int is_enum (const type_t *type) { + type = unalias_type (type); if (type->type == ev_invalid && type->meta == ty_enum) return 1; return 0; @@ -779,6 +798,7 @@ is_math (const type_t *type) int is_struct (const type_t *type) { + type = unalias_type (type); if (type->type == ev_invalid && (type->meta == ty_struct || type->meta == ty_union)) return 1; @@ -804,6 +824,7 @@ is_field (const type_t *type) int is_array (const type_t *type) { + type = unalias_type (type); if (type->type == ev_invalid && type->meta == ty_array) return 1; return 0; @@ -828,6 +849,8 @@ is_string (const type_t *type) int type_compatible (const type_t *dst, const type_t *src) { + dst = unalias_type (dst); + src = unalias_type (src); // same type if (dst == src) { return 1; @@ -847,6 +870,8 @@ type_compatible (const type_t *dst, const type_t *src) int type_assignable (const type_t *dst, const type_t *src) { + dst = unalias_type (dst); + src = unalias_type (src); int ret; // same type From 9610788deac044bae7d8dd68762ae390a368c7e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 19:16:07 +0900 Subject: [PATCH 0343/3664] Fix some more type aliasing issues Getting there... (I knew this would be a big job) --- tools/qfcc/source/expr.c | 8 ++++---- tools/qfcc/source/qc-parse.y | 2 ++ tools/qfcc/source/type.c | 7 +++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 691a03162..da96bd5fc 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1138,9 +1138,9 @@ append_expr (expr_t *block, expr_t *e) } static symbol_t * -get_struct_field (type_t *t1, expr_t *e1, expr_t *e2) +get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2) { - symtab_t *strct = t1->t.symtab; + symtab_t *strct = unalias_type (t1)->t.symtab; symbol_t *sym = e2->e.symbol;//FIXME need to check symbol_t *field; @@ -1159,12 +1159,12 @@ get_struct_field (type_t *t1, expr_t *e1, expr_t *e2) expr_t * field_expr (expr_t *e1, expr_t *e2) { - type_t *t1, *t2; + const type_t *t1, *t2; expr_t *e; if (e1->type == ex_error) return e1; - t1 = get_type (e1); + t1 = unalias_type (get_type (e1)); if (t1->type == ev_entity) { symbol_t *field = 0; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 4773eb303..e64bb748e 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -422,6 +422,7 @@ external_decl if (spec.is_typedef) { error (0, "typedef %s is initialized", $1->name); $1->sy_type = sy_type; + $1->type = alias_type ($1->type, $1->name); symtab_addsymbol (current_symtab, $1); } else { initialize_def ($1, $2, current_symtab->space, spec.storage); @@ -435,6 +436,7 @@ external_decl $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; + $1->type = alias_type ($1->type, $1->name); symtab_addsymbol (current_symtab, $1); } else { $1 = function_symbol ($1, spec.is_overload, 1); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 2aff5c5d1..2c3064405 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -897,8 +897,11 @@ type_assignable (const type_t *dst, const type_t *src) if (ret >= 0) return ret; - dst = dst->t.fldptr.type; - src = src->t.fldptr.type; + dst = unalias_type (dst->t.fldptr.type); + src = unalias_type (src->t.fldptr.type); + if (dst == src) { + return 1; + } if (is_void (dst)) return 1; if (is_void (src)) From 6bcc2c49ab829fc370c7f783e79cedd72fdb7a20 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 20:52:27 +0900 Subject: [PATCH 0344/3664] Use helper functions for type checks They hide the evil details of aliased types. More to come :/ --- tools/qfcc/source/def.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 6e545ba40..7bef8790b 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -307,10 +307,9 @@ init_elements (struct def_s *def, expr_t *eles) elements[i].offset = base_offset + i * type_size (array_type); } num_elements = i; - } else if (is_struct (def->type) - || def->type == &type_vector - || def->type == &type_quaternion) { - symtab_t *symtab = def->type->t.symtab; + } else if (is_struct (def->type) || is_vector (def->type) + || is_quaternion (def->type)) { + symtab_t *symtab = unalias_type (def->type)->t.symtab; symbol_t *field; for (i = 0, field = symtab->symbols; field; field = field->next) { From 6bc803c72d31d37319c9be3adaae7ec4f8f7e662 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 20:53:50 +0900 Subject: [PATCH 0345/3664] Use correct encoding for alias types I got confused which field was which. --- tools/qfcc/source/dump_globals.c | 4 ++-- tools/qfcc/source/obj_type.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 7f4adbbc9..7d7d29f9e 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -495,8 +495,8 @@ dump_qfo_types (qfo_t *qfo, int base_address) type->t.array.base, type->t.array.size); break; case ty_alias: - printf (" %s %-5x\n", QFO_GETSTR (qfo, type->t.alias.name), - type->t.alias.type); + printf (" %s %d %-5x\n", QFO_GETSTR (qfo, type->t.alias.name), + type->t.alias.type, type->t.alias.aux_type); break; case ty_class: printf (" %-5x\n", type->t.class); diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index e67f7a0b5..ff2409986 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -264,7 +264,8 @@ qfo_encode_alias (type_t *type) def = qfo_new_encoding (type, sizeof (enc->t.alias)); enc = D_POINTER (qfot_type_t, def); - ENC_DEF (enc->t.alias.type, alias_type_def); + enc->t.alias.type = type->type; + ENC_DEF (enc->t.alias.aux_type, alias_type_def); ENC_STR (enc->t.alias.name, type->name); return def; } From 6a70d2e362077a73ec6fad1ac250c39a8ce60c41 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 20:56:01 +0900 Subject: [PATCH 0346/3664] Give alias types a unique encoding The encoding is used as the def name and it needs to be different than the alias target or the linker throws it away as an external def. --- tools/qfcc/source/type.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 2c3064405..4453e6284 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -654,7 +654,9 @@ encode_type (dstring_t *encoding, const type_t *type) dasprintf (encoding, "]"); return; case ty_alias: + dasprintf (encoding, "{%s>", type->name); encode_type (encoding, type->t.alias.type); + dasprintf (encoding, "}"); return; case ty_none: switch (type->type) { From a0914e1ec86612c8d0d493c406c3349342ef75a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 20:58:02 +0900 Subject: [PATCH 0347/3664] Fix the typedef test case to actually work --- tools/qfcc/test/typedef.r | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/qfcc/test/typedef.r b/tools/qfcc/test/typedef.r index 48ea84478..ff5015c9e 100644 --- a/tools/qfcc/test/typedef.r +++ b/tools/qfcc/test/typedef.r @@ -21,36 +21,36 @@ next_type (qfot_type_t *type) return (qfot_type_t *) ((int *) type + size); } +int +check_alias (qfot_type_t *alias) +{ + if (alias.meta != ty_none && alias.t.type != ev_pointer) { + printf ("%s is not a *int alias\n", alias.t.alias.name); + return 0; + } + return 1; +} + int main (void) { + baz = snafu; + int found_foo = 0; int found_bar = 0; qfot_type_t *type; - qfot_type_t *alias; - - baz = snafu; // must be able to assign without warnings (won't compile) encodings = PR_FindGlobal (".type_encodings"); for (type = encodings.types; ((int *)type - (int *) encodings.types) < encodings.size; type = next_type (type)) { - if (type.meta == ty_alias && type.t.alias.type == ev_integer) { - alias = type.t.alias.aux_type; + if (type.meta == ty_alias) { if (type.t.alias.name == "foo") { - if (alias.meta == ty_none && alias.t.type == ev_integer) { - found_foo = 1; - } else { - printf ("foo type not aliased to int\n"); - } + found_foo = check_alias (type.t.alias.aux_type); } if (type.t.alias.name == "bar") { - if (alias.meta == ty_none && alias.t.type == ev_integer) { - found_bar = 1; - } else { - printf ("bar type not aliased to int\n"); - } + found_bar = check_alias (type.t.alias.aux_type); } } } From a6003ed08a8e82a5c4d4766c668f0132d099a4b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 21:04:45 +0900 Subject: [PATCH 0348/3664] Walk qfo alias chain for type size and alignment While the basic type is stored in the alias type record, it's no good for size or alignment as it will give incorrect results for complex types. --- tools/qfcc/source/obj_file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index e49d64c46..803f9995c 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -677,10 +677,10 @@ get_type_size (qfo_t *qfo, pointer_t type) type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { case ty_alias: + return get_type_size (qfo, type_def->t.alias.aux_type); case ty_none: // field, pointer and function types store their basic type in // the same location. - // alias types store the basic type at the end of the alias chain return pr_type_size[type_def->t.type]; case ty_struct: for (i = size = 0; i < type_def->t.strct.num_fields; i++) @@ -726,11 +726,11 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) return 0; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { - case ty_none: case ty_alias: + return get_type_alignment_log (qfo, type_def->t.alias.aux_type); + case ty_none: // field, pointer and function types store their basic type in // the same location. - // alias types store the basic type at the end of the alias chain return qfo_log2 (ev_types[type_def->t.type]->alignment); case ty_struct: case ty_union: From fd2b7ee6f9caedc870ef0ea2a1d2d18540a317d6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 21:13:36 +0900 Subject: [PATCH 0349/3664] Use more type checking helper functions --- tools/qfcc/include/type.h | 3 +++ tools/qfcc/source/expr.c | 6 +++--- tools/qfcc/source/type.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 098df5e00..17f21665d 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -163,6 +163,9 @@ const char *type_get_encoding (const type_t *type); const type_t *unalias_type (const type_t *type) __attribute__((pure)); int is_void (const type_t *type) __attribute__((pure)); int is_enum (const type_t *type) __attribute__((pure)); +int is_integer (const type_t *type) __attribute__((pure)); +int is_uinteger (const type_t *type) __attribute__((pure)); +int is_short (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); int is_double (const type_t *type) __attribute__((pure)); int is_float (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index da96bd5fc..44032eb5d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1459,15 +1459,15 @@ convert_from_bool (expr_t *e, type_t *type) expr_t *one; expr_t *cond; - if (type == &type_float) { + if (is_float (type)) { one = new_float_expr (1); zero = new_float_expr (0); - } else if (type == &type_integer) { + } else if (is_integer (type)) { one = new_integer_expr (1); zero = new_integer_expr (0); } else if (is_enum (type) && enum_as_bool (type, &zero, &one)) { // don't need to do anything - } else if (type == &type_uinteger) { + } else if (is_uinteger (type)) { one = new_uinteger_expr (1); zero = new_uinteger_expr (0); } else { diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 4453e6284..0622d392e 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -750,11 +750,39 @@ is_enum (const type_t *type) } int -is_integral (const type_t *type) +is_integer (const type_t *type) { etype_t t = type->type; - if (t == ev_integer || t == ev_uinteger || t == ev_short) + if (t == ev_integer) + return 1; + return is_enum (type); +} + +int +is_uinteger (const type_t *type) +{ + etype_t t = type->type; + + if (t == ev_uinteger) + return 1; + return is_enum (type); +} + +int +is_short (const type_t *type) +{ + etype_t t = type->type; + + if (t == ev_short) + return 1; + return is_enum (type); +} + +int +is_integral (const type_t *type) +{ + if (is_integer (type) || is_uinteger (type) || is_short (type)) return 1; return is_enum (type); } From 1b43046c8a1e06d96ff78641b12ed386450070dd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Feb 2020 21:28:32 +0900 Subject: [PATCH 0350/3664] Handle aliased types when building function calls --- tools/qfcc/include/expr.h | 2 +- tools/qfcc/source/expr.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 90e4f6313..36d785be0 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -623,7 +623,7 @@ expr_t *binary_expr (int op, expr_t *e1, expr_t *e2); expr_t *field_expr (expr_t *e1, expr_t *e2); expr_t *asx_expr (int op, expr_t *e1, expr_t *e2); expr_t *unary_expr (int op, expr_t *e); -expr_t *build_function_call (expr_t *fexpr, struct type_s *ftype, +expr_t *build_function_call (expr_t *fexpr, const struct type_s *ftype, expr_t *params); expr_t *function_expr (expr_t *e1, expr_t *e2); struct function_s; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 44032eb5d..efddb5427 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1843,7 +1843,7 @@ bitnot_expr: } expr_t * -build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params) +build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) { expr_t *e; int arg_count = 0, parm_count = 0; @@ -1855,6 +1855,8 @@ build_function_call (expr_t *fexpr, type_t *ftype, expr_t *params) expr_t *call; expr_t *err = 0; + ftype = unalias_type (ftype); + for (e = params; e; e = e->next) { if (e->type == ex_error) return e; From caf78b5422ac3883a13dd80b6997aed9ee2a2a6e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Feb 2020 17:47:16 +0900 Subject: [PATCH 0351/3664] Rename ty_none to ty_basic This far better reflects the actual meaning. It is very likely that ty_none is a holdover from long before there was full type encoding and it meant that the union in qfcc's type_t had no data. This is still true for basic types, but only if not a function, field or pointer type. If the type was function, field or pointer, it was not true, so it was misnamed pretty much from the start. --- include/QF/pr_type.h | 6 +++--- ruamoko/include/types.h | 2 +- tools/qfcc/include/type.h | 3 ++- tools/qfcc/source/class.c | 17 +++++++++-------- tools/qfcc/source/dump_globals.c | 4 ++-- tools/qfcc/source/linker.c | 2 +- tools/qfcc/source/obj_file.c | 8 ++++---- tools/qfcc/source/type.c | 24 +++++++++++++----------- 8 files changed, 35 insertions(+), 31 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index 0e33b0fd6..80f90b309 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -94,9 +94,9 @@ typedef struct qfot_type_s { pr_int_t size; ///< total word size of this encoding string_t encoding; ///< Objective-QC encoding union { - pr_int_t type; ///< basic type: etype_t - qfot_fldptr_t fldptr; ///< ty_none, ev_pointer/ev_field - qfot_func_t func; ///< ty_none, ev_func + pr_int_t type; ///< ty_basic: etype_t + qfot_fldptr_t fldptr; ///< ty_basic, ev_pointer/ev_field + qfot_func_t func; ///< ty_basic, ev_func qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum qfot_array_t array; ///< ty_array pointer_t class; ///< ty_class diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index deb480ebf..b435a6bab 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -21,7 +21,7 @@ typedef enum { } etype_t; typedef enum { - ty_none, ///< func/field/pointer or not used + ty_basic, ///< VM type (float, int, pointer, field, etc) ty_struct, ty_union, ty_enum, diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 17f21665d..34afd4449 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -56,7 +56,7 @@ typedef struct ty_alias_s { } ty_alias_t; typedef enum { - ty_none, ///< func/field/pointer or not used + ty_basic, ///< VM type (float, int, pointer, field, etc) ty_struct, ty_union, ty_enum, @@ -72,6 +72,7 @@ typedef struct type_s { /// function/pointer/array/struct types are more complex ty_meta_e meta; union { + // no data for ty_basic when not a func, field or pointer ty_func_t func; ty_fldptr_t fldptr; ty_array_t array; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index b249069c2..caa1967cd 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -69,30 +69,31 @@ static hashtab_t *protocol_hash; // these will be built up further type_t type_obj_selector = { ev_invalid, 0, 0, ty_struct}; -type_t type_SEL = { ev_pointer, "SEL", 1, ty_none, {{&type_obj_selector}}}; +type_t type_SEL = { ev_pointer, "SEL", 1, ty_basic, + {{&type_obj_selector}}}; type_t *IMP_params[] = {&type_id, &type_SEL}; -type_t type_IMP = { ev_func, "IMP", 1, ty_none, +type_t type_IMP = { ev_func, "IMP", 1, ty_basic, {{&type_id, -3, IMP_params}}}; type_t type_obj_super = { ev_invalid, 0, 0 }; -type_t type_SuperPtr = { ev_pointer, 0, 1, ty_none, {{&type_obj_super}}}; +type_t type_SuperPtr = { ev_pointer, 0, 1, ty_basic, {{&type_obj_super}}}; type_t *supermsg_params[] = {&type_SuperPtr, &type_SEL}; -type_t type_supermsg = { ev_func, ".supermsg", 1, ty_none, +type_t type_supermsg = { ev_func, ".supermsg", 1, ty_basic, {{&type_id, -3, supermsg_params}}}; type_t type_obj_method = { ev_invalid, 0, 0, ty_struct }; type_t type_obj_method_description = { ev_invalid, 0, 0, ty_struct }; type_t type_obj_category = { ev_invalid, 0, 0, ty_struct}; type_t type_obj_ivar = { ev_invalid, 0, 0, ty_struct}; type_t type_obj_module = { ev_invalid, 0, 0, ty_struct}; -type_t type_moduleptr = { ev_pointer, 0, 1, ty_none, +type_t type_moduleptr = { ev_pointer, 0, 1, ty_basic, {{&type_obj_module}}}; type_t *obj_exec_class_params[] = { &type_moduleptr }; -type_t type_obj_exec_class = { ev_func, 0, 1, ty_none, +type_t type_obj_exec_class = { ev_func, 0, 1, ty_basic, {{&type_void, 1, obj_exec_class_params}}}; type_t type_obj_object = {ev_invalid, 0, 0, ty_struct}; -type_t type_id = { ev_pointer, "id", 1, ty_none, {{&type_obj_object}}}; +type_t type_id = { ev_pointer, "id", 1, ty_basic, {{&type_obj_object}}}; type_t type_obj_class = { ev_invalid, 0, 0, ty_struct}; -type_t type_Class = { ev_pointer, 0, 1, ty_none, {{&type_obj_class}}}; +type_t type_Class = { ev_pointer, 0, 1, ty_basic, {{&type_obj_class}}}; type_t type_obj_protocol = { ev_invalid, 0, 0, ty_struct}; int obj_initialized = 0; diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 7d7d29f9e..89dbb50fa 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -417,7 +417,7 @@ qfo_functions (qfo_t *qfo) } static const char *ty_meta_names[] = { - "ty_none", + "ty_basic", "ty_struct", "ty_union", "ty_enum", @@ -461,7 +461,7 @@ dump_qfo_types (qfo_t *qfo, int base_address) break; } switch ((ty_meta_e) type->meta) { - case ty_none: + case ty_basic: printf (" %-10s", (type->t.type < 0 || type->t.type >= ev_type_count) ? "invalid type" diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 3f07ba7b0..3ce5ca3fd 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -1164,7 +1164,7 @@ check_defs (void) defref_t *_d = Hash_Find (defined_data_defs, "self"); if (_d) { qfo_def_t *d = REF (_d); - if (QFO_TYPEMETA (work, d->type) == ty_none + if (QFO_TYPEMETA (work, d->type) == ty_basic && QFO_TYPETYPE (work, d->type) == ev_entity) def_warning (d, "@self and self used together"); } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 803f9995c..d4db18377 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -647,7 +647,7 @@ get_def_type (qfo_t *qfo, pointer_t type) return ev_void; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { - case ty_none: + case ty_basic: case ty_alias: // field, pointer and function types store their basic type in // the same location. @@ -678,7 +678,7 @@ get_type_size (qfo_t *qfo, pointer_t type) switch ((ty_meta_e)type_def->meta) { case ty_alias: return get_type_size (qfo, type_def->t.alias.aux_type); - case ty_none: + case ty_basic: // field, pointer and function types store their basic type in // the same location. return pr_type_size[type_def->t.type]; @@ -728,7 +728,7 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) switch ((ty_meta_e)type_def->meta) { case ty_alias: return get_type_alignment_log (qfo, type_def->t.alias.aux_type); - case ty_none: + case ty_basic: // field, pointer and function types store their basic type in // the same location. return qfo_log2 (ev_types[type_def->t.type]->alignment); @@ -773,7 +773,7 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) if (func->type >= qfo->spaces[qfo_type_space].data_size) return; type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); - if (type->meta != ty_none && type->t.type != ev_func) + if (type->meta != ty_basic && type->t.type != ev_func) return; df->numparms = num_params = type->t.func.num_params; if (num_params < 0) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 0622d392e..e33f0ec34 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -67,11 +67,13 @@ type_t type_string = { ev_string, "string", 1 }; type_t type_float = { ev_float, "float", 1 }; type_t type_vector = { ev_vector, "vector", 1 }; type_t type_entity = { ev_entity, "entity", 1 }; -type_t type_field = {ev_field, "field", 1, ty_none, {{&type_void}} }; +type_t type_field = {ev_field, "field", 1, ty_basic, {{&type_void}} }; // type_function is a void() function used for state defs -type_t type_function = { ev_func, "function", 1, ty_none, {{&type_void}} }; -type_t type_pointer = { ev_pointer, "pointer", 1, ty_none, {{&type_void}} }; +type_t type_function = { ev_func, "function", 1, ty_basic, + {{&type_void}} }; +type_t type_pointer = { ev_pointer, "pointer", 1, ty_basic, + {{&type_void}} }; type_t type_quaternion = { ev_quat, "quaternion", 1 }; type_t type_integer = { ev_integer, "int", 1 }; type_t type_uinteger = { ev_uinteger, "uint", 1 }; @@ -88,7 +90,7 @@ type_t type_zero = { ev_invalid, 0, 0, ty_struct }; type_t type_type_encodings = { ev_invalid, "@type_encodings", 0, ty_struct }; -type_t type_floatfield = { ev_field, ".float", 1, ty_none, +type_t type_floatfield = { ev_field, ".float", 1, ty_basic, {{&type_float}} }; type_t *ev_types[ev_type_count] = { @@ -252,7 +254,7 @@ types_same (type_t *a, type_t *b) if (a->type != b->type || a->meta != b->meta) return 0; switch (a->meta) { - case ty_none: + case ty_basic: switch (a->type) { case ev_field: case ev_pointer: @@ -315,7 +317,7 @@ find_type (type_t *type) if (type->freeable) { switch (type->meta) { - case ty_none: + case ty_basic: switch (type->type) { case ev_field: case ev_pointer: @@ -500,7 +502,7 @@ print_type_str (dstring_t *str, const type_t *type) print_type_str (str, type->t.alias.type); dstring_appendstr (str, "})"); return; - case ty_none: + case ty_basic: switch (type->type) { case ev_field: dasprintf (str, ".("); @@ -658,7 +660,7 @@ encode_type (dstring_t *encoding, const type_t *type) encode_type (encoding, type->t.alias.type); dasprintf (encoding, "}"); return; - case ty_none: + case ty_basic: switch (type->type) { case ev_void: dasprintf (encoding, "v"); @@ -984,7 +986,7 @@ type_size (const type_t *type) return type->t.array.size * type_size (type->t.array.type); case ty_alias: return type_size (type->t.alias.type); - case ty_none: + case ty_basic: return 0; } break; @@ -1060,7 +1062,7 @@ init_types (void) make_structure ("@param", 'u', param_struct, &type_param); make_structure ("@vector", 's', vector_struct, &type_vector); type_vector.type = ev_vector; - type_vector.meta = ty_none; + type_vector.meta = ty_basic; make_structure ("@type_encodings", 's', type_encoding_struct, &type_type_encodings); @@ -1070,7 +1072,7 @@ init_types (void) make_structure ("@quaternion", 's', quaternion_struct, &type_quaternion); type_quaternion.type = ev_quat; - type_quaternion.meta = ty_none; + type_quaternion.meta = ty_basic; { symbol_t *sym; sym = new_symbol_type ("x", &type_float); From 8b225dbfc10962c113e2cb32cc1594c3e7bcd301 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Feb 2020 17:53:27 +0900 Subject: [PATCH 0352/3664] Ensure .ctor functions do not reset tracing --- tools/qfcc/test/test-harness.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index a8f829cd9..ed8a5c929 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -149,6 +149,7 @@ init_qf (void) pr.allocate_progs_mem = allocate_progs_mem; pr.free_progs_mem = free_progs_mem; pr.no_exec_limit = 0; // absolutely want a limit! + pr.pr_trace_depth = -1; pr.pr_trace = options.trace; PR_Init_Cvars (); From 3c9e2a6451f331be6c9fc3f01f846475e1c7a8fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Feb 2020 17:54:42 +0900 Subject: [PATCH 0353/3664] Rename the sys documentation group --- include/QF/sys.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 85785ed6e..10ef6999f 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -28,7 +28,7 @@ #ifndef __sys_h #define __sys_h -/** \defgroup sys Portability +/** \defgroup sys System Portability \ingroup utils Non-portable functions */ From fe796eee68906a8f31f0f743708af226a486e84f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Feb 2020 17:58:19 +0900 Subject: [PATCH 0354/3664] Move the meta type enum ino pr_type.h --- include/QF/pr_type.h | 10 ++++++++++ tools/qfcc/include/type.h | 12 +----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index 80f90b309..b2ea05060 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -40,6 +40,16 @@ #include "QF/pr_comp.h" +typedef enum { + ty_basic, ///< VM type (float, int, pointer, field, etc) + ty_struct, + ty_union, + ty_enum, + ty_array, + ty_class, + ty_alias, +} ty_meta_e; + typedef struct qfot_alias_s { pr_int_t type; ///< type at end of alias chain pointer_t aux_type; ///< referenced type diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 34afd4449..784ed6f9a 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -31,7 +31,7 @@ #ifndef __type_h #define __type_h -#include "QF/pr_comp.h" +#include "QF/pr_type.h" #include "def.h" @@ -55,16 +55,6 @@ typedef struct ty_alias_s { struct type_s *type; } ty_alias_t; -typedef enum { - ty_basic, ///< VM type (float, int, pointer, field, etc) - ty_struct, - ty_union, - ty_enum, - ty_array, - ty_class, - ty_alias, -} ty_meta_e; - typedef struct type_s { etype_t type; ///< ev_invalid means structure/array etc const char *name; From 7e76a96f7d0c963ca98899e6196c98b87f8d6a71 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Feb 2020 21:13:18 +0900 Subject: [PATCH 0355/3664] Fix a missed ty_none --- tools/qfcc/test/typedef.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/test/typedef.r b/tools/qfcc/test/typedef.r index ff5015c9e..bb5d52e4a 100644 --- a/tools/qfcc/test/typedef.r +++ b/tools/qfcc/test/typedef.r @@ -24,7 +24,7 @@ next_type (qfot_type_t *type) int check_alias (qfot_type_t *alias) { - if (alias.meta != ty_none && alias.t.type != ev_pointer) { + if (alias.meta != ty_basic && alias.t.type != ev_pointer) { printf ("%s is not a *int alias\n", alias.t.alias.name); return 0; } From c296514b950ad2956e2da00d85dadf27406ee40a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Feb 2020 21:17:28 +0900 Subject: [PATCH 0356/3664] Make pr.load_file 'return' the file size --- include/QF/progs.h | 2 +- libs/console/menu.c | 6 ++++-- libs/gamecode/pr_debug.c | 7 +++++-- libs/gamecode/pr_load.c | 6 ++++-- tools/qfcc/source/qfprogs.c | 3 ++- tools/qfcc/test/test-harness.c | 3 ++- tools/qwaq/main.c | 3 ++- tools/qwaq/qwaq.c | 3 ++- 8 files changed, 22 insertions(+), 11 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index e7953883e..87fd87c89 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1550,7 +1550,7 @@ struct progs_s { int no_exec_limit; void (*file_error) (progs_t *pr, const char *path); - void *(*load_file) (progs_t *pr, const char *path); + void *(*load_file) (progs_t *pr, const char *path, off_t *size); void *(*allocate_progs_mem) (progs_t *pr, int size); void (*free_progs_mem) (progs_t *pr, void *mem); diff --git a/libs/console/menu.c b/libs/console/menu.c index e65fff1cb..043532023 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -510,9 +510,11 @@ menu_free_progs_mem (progs_t *pr, void *mem) } static void * -menu_load_file (progs_t *pr, const char *path) +menu_load_file (progs_t *pr, const char *path, off_t *size) { - return QFS_LoadFile (QFS_FOpenFile (path), 0); + void *data = QFS_LoadFile (QFS_FOpenFile (path), 0); + *size = qfs_filesize; + return data; } static builtin_t builtins[] = { diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 174987135..7f86c2c8f 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -65,6 +65,7 @@ typedef struct { typedef struct { char *name; char *text; + off_t size; line_t *lines; pr_uint_t num_lines; progs_t *pr; @@ -227,7 +228,8 @@ PR_Load_Source_File (progs_t *pr, const char *fname) return 0; for (dir = source_paths; *dir && !f->text; dir++) { f->text = pr->load_file (pr, va ("%s%s%s", *dir, **dir ? "/" : "", - fname)); + fname), + &f->size); } if (!f->text) { pr->file_error (pr, fname); @@ -273,6 +275,7 @@ PR_LoadDebug (progs_t *pr) { char *sym_path; const char *path_end, *sym_file; + off_t debug_size; pr_uint_t i; ddef_t *def; pr_type_t *str = 0; @@ -303,7 +306,7 @@ PR_LoadDebug (progs_t *pr) sym_path = malloc (strlen (sym_file) + (path_end - pr->progs_name) + 1); strncpy (sym_path, pr->progs_name, path_end - pr->progs_name); strcpy (sym_path + (path_end - pr->progs_name), sym_file); - pr->debug = pr->load_file (pr, sym_path); + pr->debug = pr->load_file (pr, sym_path, &debug_size); if (!pr->debug) { Sys_Printf ("can't load %s for debug info\n", sym_path); free (sym_path); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 8bc554296..cadfebca3 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -81,9 +81,11 @@ file_error (progs_t *pr, const char *path) } static void * -load_file (progs_t *pr, const char *path) +load_file (progs_t *pr, const char *path, off_t *size) { - return QFS_LoadHunkFile (QFS_FOpenFile (path)); + void *data = QFS_LoadHunkFile (QFS_FOpenFile (path)); + *size = qfs_filesize; + return data; } static void * diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 10ddf8abd..be14d144f 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -176,7 +176,7 @@ file_error (progs_t *pr, const char *name) } static void * -load_file (progs_t *pr, const char *name) +load_file (progs_t *pr, const char *name, off_t *_size) { QFile *file; int size; @@ -191,6 +191,7 @@ load_file (progs_t *pr, const char *name) sym = malloc (size + 1); sym[size] = 0; Qread (file, sym, size); + *_size = size; return sym; } diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index ed8a5c929..78c657d05 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -96,7 +96,7 @@ open_file (const char *path, int *len) } static void * -load_file (progs_t *pr, const char *name) +load_file (progs_t *pr, const char *name, off_t *_size) { QFile *file; int size; @@ -112,6 +112,7 @@ load_file (progs_t *pr, const char *name) sym = malloc (size + 1); sym[size] = 0; Qread (file, sym, size); + *_size = size; return sym; } diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index 15270d5e4..035e4f73b 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -65,7 +65,7 @@ open_file (const char *path, int *len) } static void * -load_file (progs_t *pr, const char *name) +load_file (progs_t *pr, const char *name, off_t *_size) { QFile *file; int size; @@ -81,6 +81,7 @@ load_file (progs_t *pr, const char *name) sym = malloc (size + 1); sym[size] = 0; Qread (file, sym, size); + *_size = size; return sym; } diff --git a/tools/qwaq/qwaq.c b/tools/qwaq/qwaq.c index 40576e868..24a14d217 100644 --- a/tools/qwaq/qwaq.c +++ b/tools/qwaq/qwaq.c @@ -71,7 +71,7 @@ open_file (const char *path, int *len) } static void * -load_file (progs_t *pr, const char *name) +load_file (progs_t *pr, const char *name, off_t *_size) { QFile *file; int size; @@ -87,6 +87,7 @@ load_file (progs_t *pr, const char *name) sym = malloc (size + 1); sym[size] = 0; Qread (file, sym, size); + *_size = size; return sym; } From e7b4eedc07526d925f3538e00ed905dbddd2fb54 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Feb 2020 14:04:10 +0900 Subject: [PATCH 0357/3664] Fix segfault in dereferencing undefined field containers --- tools/qfcc/source/expr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index efddb5427..ab9672813 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1162,9 +1162,10 @@ field_expr (expr_t *e1, expr_t *e2) const type_t *t1, *t2; expr_t *e; + t1 = get_type (e1); if (e1->type == ex_error) return e1; - t1 = unalias_type (get_type (e1)); + t1 = unalias_type (t1); if (t1->type == ev_entity) { symbol_t *field = 0; From 4df926e531fe203e293e9e7c3d0ec326bc05fe61 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Feb 2020 14:11:15 +0900 Subject: [PATCH 0358/3664] Write extended ddef information to progs far data I was originally going to put it in the debug syms file, but I realized that the data persistence code would need access to both def type and certainly correct def offsets for defs in far data. --- include/QF/pr_comp.h | 10 +++++++++ tools/qfcc/include/type.h | 3 +++ tools/qfcc/source/obj_file.c | 43 +++++++++++++++++++++++++++++++----- tools/qfcc/source/qfcc.c | 1 + tools/qfcc/source/type.c | 18 +++++++++++++++ tools/qwaq/main.qc | 1 + tools/qwaq/types.r | 27 ++++++++++++++++++++++ 7 files changed, 98 insertions(+), 5 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 185a802ad..6b39ff1bc 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -423,6 +423,16 @@ typedef struct ddef_s { pr_int_t s_name; } ddef_t; +typedef struct xdef_s { + pointer_t type; ///< pointer to type definition + pointer_t ofs; ///< 32-bit version of ddef_t.ofs +} xdef_t; + +typedef struct pr_xdefs_s { + pointer_t xdefs; + pr_int_t num_xdefs; +} pr_xdefs_t; + typedef struct dparmsize_s { uint8_t size:5; uint8_t alignment:3; diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 784ed6f9a..c8913933e 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -116,6 +116,9 @@ extern type_t type_va_list; extern type_t type_param; extern type_t type_zero; extern type_t type_type_encodings; +extern type_t type_xdef; +extern type_t type_xdef_pointer; +extern type_t type_xdefs; extern struct symtab_s *vector_struct; extern struct symtab_s *quaternion_struct; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index d4db18377..79c4effeb 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -879,12 +879,16 @@ qfo_to_progs (qfo_t *qfo, int *size) pr_type_t *locals; pr_type_t *far_data; pr_type_t *type_data; + pr_type_t *xdef_data; dprograms_t *progs; qfo_def_t *types_def = 0; + qfo_def_t *xdefs_def = 0; unsigned i, j; unsigned near_data_size = 0; unsigned locals_size = 0; int locals_start; + int type_encodings_start; + int xdefs_start; unsigned big_locals = 0; int big_func = 0; @@ -893,7 +897,9 @@ qfo_to_progs (qfo_t *qfo, int *size) progs->version = options.code.progsversion; progs->numstatements = qfo->spaces[qfo_code_space].data_size; progs->numglobaldefs = qfo->spaces[qfo_near_data_space].num_defs; - //FIXME ddef offsets are 16 bits + //ddef offsets are 16 bits so the ddef ofs will likely be invalid + //thus it will be forced invalid and the true offset written to the + //symbols file if it is created (fa progs->numglobaldefs += qfo->spaces[qfo_far_data_space].num_defs; progs->numfielddefs = qfo->spaces[qfo_entity_space].num_defs; progs->numfunctions = qfo->num_funcs + 1; @@ -915,7 +921,11 @@ qfo_to_progs (qfo_t *qfo, int *size) near_data_size = progs->numglobals; progs->numglobals = RUP (progs->numglobals, 16 / sizeof (pr_type_t)); progs->numglobals += qfo->spaces[qfo_far_data_space].data_size; + type_encodings_start = progs->numglobals; progs->numglobals += qfo->spaces[qfo_type_space].data_size; + progs->numglobals = RUP (progs->numglobals, type_xdef.alignment); + xdefs_start = progs->numglobals; + progs->numglobals += progs->numglobaldefs * type_size (&type_xdef); progs->entityfields = qfo->spaces[qfo_entity_space].data_size; *size += progs->numstatements * sizeof (dstatement_t); *size += progs->numglobaldefs * sizeof (ddef_t); @@ -954,7 +964,8 @@ qfo_to_progs (qfo_t *qfo, int *size) globals = (pr_type_t*) data; locals = globals + locals_start; far_data = globals + near_data_size; - type_data = far_data + qfo->spaces[qfo_far_data_space].data_size; + type_data = globals + type_encodings_start; + xdef_data = globals + xdefs_start; memcpy (strings, qfo->spaces[qfo_strings_space].d.strings, qfo->spaces[qfo_strings_space].data_size * sizeof (char)); @@ -987,14 +998,18 @@ qfo_to_progs (qfo_t *qfo, int *size) qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; if (!strcmp (QFO_GETSTR (qfo, def->name), ".type_encodings")) types_def = def; + if (!strcmp (QFO_GETSTR (qfo, def->name), ".xdefs")) + xdefs_def = def; convert_def (qfo, def, globaldefs++); } - //FIXME ddef offsets are 16 bits for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + i; def->offset += far_data - globals; - convert_def (qfo, def, globaldefs++); + convert_def (qfo, def, globaldefs); + // the correct offset will be written to the far data space + globaldefs->ofs = -1; + globaldefs++; } for (i = 0; i < qfo->spaces[qfo_type_space].num_defs; i++) { @@ -1025,9 +1040,27 @@ qfo_to_progs (qfo_t *qfo, int *size) if (types_def) { qfot_type_encodings_t *encodings; encodings = (qfot_type_encodings_t *) &globals[types_def->offset]; - encodings->types = type_data - globals; + encodings->types = type_encodings_start; encodings->size = qfo->spaces[qfo_type_space].data_size; } + if (xdefs_def) { + int xdef_data_size = type_size (&type_xdef); + pr_xdefs_t *xdefs = (pr_xdefs_t *) &globals[xdefs_def->offset]; + xdefs->xdefs = xdefs_start; + xdefs->num_xdefs = progs->numglobaldefs; + for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { + qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; + xdef_data[0].pointer_var = def->type + type_encodings_start; + xdef_data[1].pointer_var = def->offset; + xdef_data += xdef_data_size; + } + for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { + qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + i; + xdef_data[0].pointer_var = def->type + type_encodings_start; + xdef_data[1].pointer_var = def->offset; + xdef_data += xdef_data_size; + } + } // undo the relocation of the offsets of local defs so the local defs have // the correct offset in the debug info diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 780db073a..9e292d136 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -423,6 +423,7 @@ finish_link (void) ¶m_size); linker_add_def (".param_alignment", &type_integer, flags, ¶m_alignment); + linker_add_def (".xdefs", &type_xdefs, flags, 0); } if (options.code.debug) { diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index e33f0ec34..04c8d7442 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -89,6 +89,9 @@ type_t type_param = { ev_invalid, 0, 0, ty_struct }; type_t type_zero = { ev_invalid, 0, 0, ty_struct }; type_t type_type_encodings = { ev_invalid, "@type_encodings", 0, ty_struct }; +type_t type_xdef = { ev_invalid, "@xdef", 0, ty_struct }; +type_t type_xdef_pointer = { ev_pointer, 0, 1, ty_basic, {{&type_xdef}} }; +type_t type_xdefs = { ev_invalid, "@xdefs", 0, ty_struct }; type_t type_floatfield = { ev_field, ".float", 1, ty_basic, {{&type_float}} }; @@ -1045,6 +1048,16 @@ init_types (void) {"size", &type_integer}, {0, 0} }; + static struct_def_t xdef_struct[] = { + {"types", &type_pointer}, + {"offset", &type_pointer}, + {0, 0} + }; + static struct_def_t xdefs_struct[] = { + {"xdefs", &type_xdef_pointer}, + {"num_xdefs", &type_pointer}, + {0, 0} + }; type_nil = &type_quaternion; type_default = &type_integer; @@ -1066,6 +1079,8 @@ init_types (void) make_structure ("@type_encodings", 's', type_encoding_struct, &type_type_encodings); + make_structure ("@xdef", 's', xdef_struct, &type_xdef); + make_structure ("@xdefs", 's', xdefs_struct, &type_xdefs); if (options.traditional) return; @@ -1120,6 +1135,9 @@ chain_initial_types (void) chain_type (&type_param); chain_type (&type_zero); chain_type (&type_type_encodings); + chain_type (&type_xdef); + chain_type (&type_xdef_pointer); + chain_type (&type_xdefs); va_list_struct[1].type = pointer_type (&type_param); make_structure ("@va_list", 's', va_list_struct, &type_va_list); diff --git a/tools/qwaq/main.qc b/tools/qwaq/main.qc index 1014c1f4d..25cfaabdb 100644 --- a/tools/qwaq/main.qc +++ b/tools/qwaq/main.qc @@ -109,5 +109,6 @@ int main (int argc, string *argv) test_script (); test_plist (); test_types (); + test_xdefs (); return 0; }; diff --git a/tools/qwaq/types.r b/tools/qwaq/types.r index 324185b93..5cf874c61 100644 --- a/tools/qwaq/types.r +++ b/tools/qwaq/types.r @@ -77,6 +77,16 @@ typedef struct qfot_type_encodings_s { int size; } qfot_type_encodings_t; +typedef struct xdef_s { + qfot_type_t *type; + void *offset; +} xdef_t; + +typedef struct pr_xdefs_s { + xdef_t *xdefs; + int num_xdefs; +} pr_xdefs_t; + qfot_type_t * next_type (qfot_type_t *type) { @@ -174,3 +184,20 @@ test_types (void) } } } + +void +test_xdefs (void) +{ + pr_xdefs_t *xdefs; + int i; + + xdefs = PR_FindGlobal (".xdefs"); + if (!xdefs) { + printf ("Can't find xdefs\n"); + return; + } + printf ("%p %i\n", xdefs.xdefs, xdefs.num_xdefs); + for (i = 0; i < xdefs.num_xdefs; i++) { + printf ("%p %p\n", xdefs.xdefs[i].type, xdefs.xdefs[i].offset); + } +} From 81083698a8958137ba91d28fdaf21416eb4a93a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Feb 2020 22:33:44 +0900 Subject: [PATCH 0359/3664] Move to using an in-memory form of ddef_t This allows the VM to work with extended ddefs transparently. It seems to have uncovered a typedef alias relocation bug, though. --- include/QF/pr_comp.h | 13 ++++++-- include/QF/pr_debug.h | 2 +- include/QF/progs.h | 22 +++++++------ libs/console/menu.c | 2 +- libs/gamecode/pr_debug.c | 56 ++++++++++++++++---------------- libs/gamecode/pr_edict.c | 6 ++-- libs/gamecode/pr_load.c | 56 ++++++++++++++++++++++++++------ libs/gamecode/pr_opcode.c | 2 +- libs/gamecode/pr_parse.c | 22 ++++++------- libs/gamecode/pr_resolve.c | 20 ++++++------ libs/ruamoko/pr_cmds.c | 4 +-- libs/ruamoko/rua_obj.c | 4 +-- nq/source/sv_progs.c | 4 +-- qw/source/sv_pr_qwe.c | 2 +- qw/source/sv_progs.c | 4 +-- tools/qfcc/source/dump_globals.c | 24 +++++++------- tools/qfcc/source/dump_modules.c | 6 ++-- tools/qfcc/source/obj_file.c | 48 +++++++++++++++------------ tools/qfcc/source/qfprogs.c | 41 +++++++++++++++++++++-- 19 files changed, 213 insertions(+), 125 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 6b39ff1bc..d1865d1cc 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -420,7 +420,7 @@ typedef struct ddef_s { pr_ushort_t type; // if DEF_SAVEGLOBGAL bit is set // the variable needs to be saved in savegames pr_ushort_t ofs; - pr_int_t s_name; + string_t s_name; } ddef_t; typedef struct xdef_s { @@ -433,6 +433,13 @@ typedef struct pr_xdefs_s { pr_int_t num_xdefs; } pr_xdefs_t; +typedef struct pr_def_s { + pr_uint_t type; + pointer_t ofs; + string_t name; + pointer_t type_encoding; +} pr_def_t; + typedef struct dparmsize_s { uint8_t size:5; uint8_t alignment:3; @@ -445,11 +452,11 @@ typedef struct dparmsize_s { typedef struct dfunction_s { pr_int_t first_statement; // negative numbers are builtins pr_int_t parm_start; - pr_int_t locals; // total ints of parms + locals + pr_uint_t locals; // total ints of parms + locals pr_int_t profile; // runtime - pr_int_t s_name; + string_t s_name; pr_int_t s_file; // source file defined in pr_int_t numparms; diff --git a/include/QF/pr_debug.h b/include/QF/pr_debug.h index 65b953381..d80b9f417 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/pr_debug.h @@ -51,7 +51,7 @@ typedef struct pr_lineno_s { pr_uint_t line; } pr_lineno_t; -#define PROG_DEBUG_VERSION 0x00001002 // MMmmmRRR 0.001.002 (hex) +#define PROG_DEBUG_VERSION 0x00001003 // MMmmmRRR 0.001.002 (hex) typedef struct pr_debug_header_s { pr_int_t version; diff --git a/include/QF/progs.h b/include/QF/progs.h index 87fd87c89..e93bea597 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -236,7 +236,7 @@ void ED_PrintNum (progs_t *pr, pr_int_t ent); // pr_parse.c struct script_s; struct plitem_s; -qboolean ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key, +qboolean ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s); struct plitem_s *ED_EntityDict (progs_t *pr, edict_t *ed); struct plitem_s *ED_GlobalsDict (progs_t *pr); @@ -269,11 +269,11 @@ void ED_EntityParseFunction (progs_t *pr); */ ///@{ -ddef_t *PR_FieldAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure)); -ddef_t *PR_GlobalAtOfs (progs_t *pr, pr_int_t ofs) __attribute__((pure)); +pr_def_t *PR_FieldAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure)); +pr_def_t *PR_GlobalAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure)); -ddef_t *PR_FindField (progs_t *pr, const char *name); -ddef_t *PR_FindGlobal (progs_t *pr, const char *name); +pr_def_t *PR_FindField (progs_t *pr, const char *name); +pr_def_t *PR_FindGlobal (progs_t *pr, const char *name); dfunction_t *PR_FindFunction (progs_t *pr, const char *name); int PR_ResolveGlobals (progs_t *pr); @@ -1499,8 +1499,8 @@ pr_uint_t PR_Get_Lineno_Line (progs_t *pr, pr_lineno_t *lineno) __attribute__((p pr_lineno_t *PR_Find_Lineno (progs_t *pr, pr_uint_t addr) __attribute__((pure)); const char *PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); const char *PR_Get_Source_Line (progs_t *pr, pr_uint_t addr); -ddef_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) __attribute__((pure)); -ddef_t *PR_Get_Local_Def (progs_t *pr, pr_int_t offs) __attribute__((pure)); +pr_def_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) __attribute__((pure)); +pr_def_t *PR_Get_Local_Def (progs_t *pr, pointer_t offs) __attribute__((pure)); void PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents); void PR_DumpState (progs_t *pr); void PR_StackTrace (progs_t *pr); @@ -1616,8 +1616,10 @@ struct progs_s { bfunction_t *function_table; char *pr_strings; int pr_stringsize; - ddef_t *pr_globaldefs; - ddef_t *pr_fielddefs; + ddef_t *pr_globalddefs; + ddef_t *pr_fieldddefs; + pr_def_t *pr_globaldefs; + pr_def_t *pr_fielddefs; dstatement_t *pr_statements; pr_type_t *pr_globals; unsigned globals_size; @@ -1708,7 +1710,7 @@ struct progs_s { struct pr_auxfunction_s *auxfunctions; struct pr_auxfunction_s **auxfunction_map; struct pr_lineno_s *linenos; - ddef_t *local_defs; + pr_def_t *local_defs; pr_type_t *watch; int wp_conditional; pr_type_t wp_val; diff --git a/libs/console/menu.c b/libs/console/menu.c index 043532023..8320bc405 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -117,7 +117,7 @@ static int menu_resolve_globals (progs_t *pr) { const char *sym; - ddef_t *def; + pr_def_t *def; dfunction_t *f; size_t i; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 7f86c2c8f..0c388eaff 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -126,17 +126,17 @@ pr_debug_expression_error (script_t *script, const char *msg) Sys_Printf ("%s\n", msg); } -static ddef_t +static pr_def_t parse_expression (progs_t *pr, const char *expr, int conditional) { script_t *es; char *e; pr_type_t *expr_ptr; - ddef_t d; + pr_def_t d; d.ofs = 0; d.type = ev_invalid; - d.s_name = 0; + d.name = 0; es = Script_New (); es->error = pr_debug_expression_error; Script_Start (es, "", expr); @@ -145,7 +145,7 @@ parse_expression (progs_t *pr, const char *expr, int conditional) if (Script_GetToken (es, 1)) { if (strequal (es->token->str, "[")) { edict_t *ent; - ddef_t *field; + pr_def_t *field; if (!Script_GetToken (es, 1)) goto error; @@ -169,7 +169,7 @@ parse_expression (progs_t *pr, const char *expr, int conditional) d.type = ev_void; d.ofs = PR_SetPointer (pr, expr_ptr); } else { - ddef_t *global = PR_FindGlobal (pr, es->token->str); + pr_def_t *global = PR_FindGlobal (pr, es->token->str); if (!global) goto error; d = *global; @@ -277,7 +277,7 @@ PR_LoadDebug (progs_t *pr) const char *path_end, *sym_file; off_t debug_size; pr_uint_t i; - ddef_t *def; + pr_def_t *def; pr_type_t *str = 0; if (pr->debug) @@ -348,7 +348,7 @@ PR_LoadDebug (progs_t *pr) pr->auxfunctions = (pr_auxfunction_t*)((char*)pr->debug + pr->debug->auxfunctions); pr->linenos = (pr_lineno_t*)((char*)pr->debug + pr->debug->linenos); - pr->local_defs = (ddef_t*)((char*)pr->debug + pr->debug->locals); + pr->local_defs = (pr_def_t*)((char*)pr->debug + pr->debug->locals); i = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); pr->auxfunction_map = pr->allocate_progs_mem (pr, i); @@ -377,7 +377,7 @@ PR_LoadDebug (progs_t *pr) for (i = 0; i < pr->debug->num_locals; i++) { pr->local_defs[i].type = LittleShort (pr->local_defs[i].type); pr->local_defs[i].ofs = LittleShort (pr->local_defs[i].ofs); - pr->local_defs[i].s_name = LittleLong (pr->local_defs[i].s_name); + pr->local_defs[i].name = LittleLong (pr->local_defs[i].name); } return 1; } @@ -474,12 +474,12 @@ PR_Get_Source_Line (progs_t *pr, pr_uint_t addr) file->lines[line - 1].text); } -ddef_t * +pr_def_t * PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) { pr_uint_t i; pr_auxfunction_t *aux_func; - ddef_t *ddef = 0; + pr_def_t *ddef = 0; int num_params; int param_offs = 0; @@ -522,7 +522,7 @@ static etype_t get_etype (progs_t *pr, int typeptr) { //FIXME cache .type_encodings def - ddef_t *te_def = PR_FindGlobal (pr, ".type_encodings"); + pr_def_t *te_def = PR_FindGlobal (pr, ".type_encodings"); qfot_type_encodings_t *encodings; qfot_type_t *type; @@ -538,8 +538,8 @@ get_etype (progs_t *pr, int typeptr) return ev_void; } -ddef_t * -PR_Get_Local_Def (progs_t *pr, pr_int_t offs) +pr_def_t * +PR_Get_Local_Def (progs_t *pr, pointer_t offs) { pr_uint_t i; dfunction_t *func; @@ -554,7 +554,7 @@ PR_Get_Local_Def (progs_t *pr, pr_int_t offs) if (!aux_func) return 0; offs -= func->parm_start; - if (offs < 0 || offs >= func->locals) + if (offs >= func->locals) return 0; for (i = 0; i < aux_func->num_locals; i++) if (pr->local_defs[aux_func->local_defs + i].ofs == offs) @@ -594,7 +594,7 @@ static const char * value_string (progs_t *pr, etype_t type, pr_type_t *val) { static dstring_t *line; - ddef_t *def; + pr_def_t *def; pr_int_t ofs; edict_t *edict; dfunction_t *f; @@ -655,7 +655,7 @@ value_string (progs_t *pr, etype_t type, pr_type_t *val) case ev_field: def = PR_FieldAtOfs (pr, val->integer_var); if (def) - dsprintf (line, ".%s", PR_GetString (pr, def->s_name)); + dsprintf (line, ".%s", PR_GetString (pr, def->name)); else dsprintf (line, ".<$%04x>", val->integer_var); break; @@ -679,8 +679,8 @@ value_string (progs_t *pr, etype_t type, pr_type_t *val) def = PR_Get_Local_Def (pr, ofs); if (!def) def = PR_GlobalAtOfs (pr, ofs); - if (def && def->s_name) - dsprintf (line, "&%s", PR_GetString (pr, def->s_name)); + if (def && def->name) + dsprintf (line, "&%s", PR_GetString (pr, def->name)); else dsprintf (line, "[$%x]", ofs); break; @@ -711,17 +711,17 @@ value_string (progs_t *pr, etype_t type, pr_type_t *val) return line->str; } -static ddef_t * +static pr_def_t * def_string (progs_t *pr, pr_int_t ofs, dstring_t *dstr) { - ddef_t *def = 0; + pr_def_t *def = 0; const char *name; if (pr_debug->int_val && pr->debug) def = PR_Get_Local_Def (pr, ofs); if (!def) def = PR_GlobalAtOfs (pr, ofs); - if (!def || !*(name = PR_GetString (pr, def->s_name))) + if (!def || !*(name = PR_GetString (pr, def->name))) dsprintf (dstr, "[$%x]", ofs); else dsprintf (dstr, "%s", name); @@ -732,7 +732,7 @@ static const char * global_string (progs_t *pr, pointer_t ofs, etype_t type, int contents) { static dstring_t *line = NULL; - ddef_t *def = NULL; + pr_def_t *def = NULL; const char *s; if (!line) @@ -771,7 +771,7 @@ global_string (progs_t *pr, pointer_t ofs, etype_t type, int contents) VISIBLE void PR_Debug_Watch (progs_t *pr, const char *expr) { - ddef_t watch; + pr_def_t watch; if (!expr) { Sys_Printf ("watch \n"); if (pr->watch) { @@ -802,7 +802,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) VISIBLE void PR_Debug_Print (progs_t *pr, const char *expr) { - ddef_t print; + pr_def_t print; if (!expr) { Sys_Printf ("print \n"); @@ -825,7 +825,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) opcode_t *op; static dstring_t *line; dfunction_t *call_func = 0; - ddef_t *parm_def = 0; + pr_def_t *parm_def = 0; pr_auxfunction_t *aux_func = 0; if (!line) @@ -1075,7 +1075,7 @@ ED_Print (progs_t *pr, edict_t *ed) int type, l; pr_uint_t i; const char *name; - ddef_t *d; + pr_def_t *d; pr_type_t *v; if (ed->free) { @@ -1086,9 +1086,9 @@ ED_Print (progs_t *pr, edict_t *ed) Sys_Printf ("\nEDICT %d:\n", NUM_FOR_BAD_EDICT (pr, ed)); for (i = 0; i < pr->progs->numfielddefs; i++) { d = &pr->pr_fielddefs[i]; - if (!d->s_name) // null field def (probably 1st) + if (!d->name) // null field def (probably 1st) continue; - name = PR_GetString (pr, d->s_name); + name = PR_GetString (pr, d->name); if (name[strlen (name) - 2] == '_' && strchr ("xyz", name[strlen (name) -1])) continue; // skip _x, _y, _z vars diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 2241e3e9f..76eb07e9b 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -158,7 +158,7 @@ ED_PrintEdicts (progs_t *pr, const char *fieldval) { pr_int_t i; int count; - ddef_t *def; + pr_def_t *def; def = PR_FindField(pr, "classname"); @@ -188,8 +188,8 @@ ED_Count (progs_t *pr) { pr_int_t i; int active, models, solid, step, zombie; - ddef_t *solid_def; - ddef_t *model_def; + pr_def_t *solid_def; + pr_def_t *model_def; edict_t *ent; solid_def = PR_FindField (pr, "solid"); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index cadfebca3..eec948d45 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -70,8 +70,8 @@ static const char * var_get_key (const void *d, void *_pr) { progs_t *pr = (progs_t*)_pr; - ddef_t *def = (ddef_t*)d; - return PR_GetString (pr, def->s_name); + pr_def_t *def = (pr_def_t*)d; + return PR_GetString (pr, def->name); } static void @@ -119,6 +119,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) dprograms_t progs; byte *base; byte *heap; + pr_def_t *xdefs_def = 0; + if (!pr->file_error) pr->file_error = file_error; @@ -220,8 +222,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) (dfunction_t *) (base + pr->progs->ofs_functions); pr->pr_strings = (char *) base + pr->progs->ofs_strings; pr->pr_stringsize = (char *) heap + pr->zone_size - (char *) base; - pr->pr_globaldefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); - pr->pr_fielddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs); + pr->pr_globalddefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); + pr->pr_fieldddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs); pr->pr_statements = (dstatement_t *) (base + pr->progs->ofs_statements); pr->pr_globals = (pr_type_t *) (base + pr->progs->ofs_globals); @@ -272,24 +274,58 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) Hash_Add (pr->function_hash, &pr->pr_functions[i]); } + if (pr->pr_globaldefs) { + free (pr->pr_globaldefs); + } + pr->pr_globaldefs = calloc (pr->progs->numglobaldefs, sizeof (pr_def_t)); + for (i = 0; i < pr->progs->numglobaldefs; i++) { - pr->pr_globaldefs[i].type = LittleShort (pr->pr_globaldefs[i].type); - pr->pr_globaldefs[i].ofs = LittleShort (pr->pr_globaldefs[i].ofs); - pr->pr_globaldefs[i].s_name = LittleLong (pr->pr_globaldefs[i].s_name); + pr->pr_globalddefs[i].type = LittleShort (pr->pr_globalddefs[i].type); + pr->pr_globalddefs[i].ofs = LittleShort (pr->pr_globalddefs[i].ofs); + pr->pr_globalddefs[i].s_name = LittleLong (pr->pr_globalddefs[i].s_name); + + pr->pr_globaldefs[i].type = pr->pr_globalddefs[i].type; + pr->pr_globaldefs[i].ofs = pr->pr_globalddefs[i].ofs; + pr->pr_globaldefs[i].name = pr->pr_globalddefs[i].s_name; Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]); } + if (pr->pr_fielddefs) { + free (pr->pr_fielddefs); + } + pr->pr_fielddefs = calloc (pr->progs->numfielddefs, sizeof (pr_def_t)); for (i = 0; i < pr->progs->numfielddefs; i++) { - pr->pr_fielddefs[i].type = LittleShort (pr->pr_fielddefs[i].type); + pr->pr_fieldddefs[i].type = LittleShort (pr->pr_fieldddefs[i].type); if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL) PR_Error (pr, "PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); - pr->pr_fielddefs[i].ofs = LittleShort (pr->pr_fielddefs[i].ofs); - pr->pr_fielddefs[i].s_name = LittleLong (pr->pr_fielddefs[i].s_name); + pr->pr_fieldddefs[i].ofs = LittleShort (pr->pr_fieldddefs[i].ofs); + pr->pr_fieldddefs[i].s_name = LittleLong (pr->pr_fieldddefs[i].s_name); + + pr->pr_fielddefs[i].type = pr->pr_fieldddefs[i].type; + pr->pr_fielddefs[i].ofs = pr->pr_fieldddefs[i].ofs; + pr->pr_fielddefs[i].name = pr->pr_fieldddefs[i].s_name; Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]); } for (i = 0; i < pr->progs->numglobals; i++) ((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]); + + xdefs_def = PR_FindGlobal (pr, ".xdefs"); + if (xdefs_def) { + pr_xdefs_t *xdefs = &G_STRUCT (pr, pr_xdefs_t, xdefs_def->ofs); + xdef_t *xdef = &G_STRUCT (pr, xdef_t, xdefs->xdefs); + pr_def_t *def; + for (def = pr->pr_globaldefs, i = 0; i < pr->progs->numglobaldefs; + i++, xdef++, def++) { + def->ofs = xdef->ofs; + def->type_encoding = xdef->type; + } + for (def = pr->pr_fielddefs, i = 0; i < pr->progs->numfielddefs; + i++, xdef++, def++) { + def->ofs = xdef->ofs; + def->type_encoding = xdef->type; + } + } } VISIBLE void diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 15185b37d..0ad3fab4b 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -1535,7 +1535,7 @@ check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type, unsigned short operand, int check_denorm) { const char *msg; - ddef_t *def; + pr_def_t *def; switch (type) { case ev_short: diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index a8259ee78..69219651f 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -71,7 +71,7 @@ static const char * PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val) { static dstring_t *line = 0; - ddef_t *def; + pr_def_t *def; dfunction_t *f; if (!line) @@ -93,7 +93,7 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val) break; case ev_field: def = PR_FieldAtOfs (pr, val->integer_var); - dsprintf (line, "%s", PR_GetString (pr, def->s_name)); + dsprintf (line, "%s", PR_GetString (pr, def->name)); break; case ev_void: dstring_copystr (line, "void"); @@ -131,9 +131,9 @@ ED_EntityDict (progs_t *pr, edict_t *ed) if (!ed->free) { for (i = 0; i < pr->progs->numfielddefs; i++) { - ddef_t *d = &pr->pr_fielddefs[i]; + pr_def_t *d = &pr->pr_fielddefs[i]; - name = PR_GetString (pr, d->s_name); + name = PR_GetString (pr, d->name); if (!name[0]) continue; // skip unnamed fields if (name[strlen (name) - 2] == '_') @@ -169,7 +169,7 @@ ED_GlobalsDict (progs_t *pr) pr_uint_t i; const char *name; const char *value; - ddef_t *def; + pr_def_t *def; int type; for (i = 0; i < pr->progs->numglobaldefs; i++) { @@ -182,7 +182,7 @@ ED_GlobalsDict (progs_t *pr) if (type != ev_string && type != ev_float && type != ev_entity) continue; - name = PR_GetString (pr, def->s_name); + name = PR_GetString (pr, def->name); value = PR_UglyValueString (pr, type, &pr->pr_globals[def->ofs]); PL_D_AddObject (globals, name, PL_NewString (value)); } @@ -222,11 +222,11 @@ ED_NewString (progs_t *pr, const char *string) returns false if error */ VISIBLE qboolean -ED_ParseEpair (progs_t *pr, pr_type_t *base, ddef_t *key, const char *s) +ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) { int i; char *string; - ddef_t *def; + pr_def_t *def; char *v, *w; pr_type_t *d; dfunction_t *func; @@ -357,8 +357,8 @@ ED_ConvertToPlist (script_t *script, int nohack) VISIBLE void ED_InitGlobals (progs_t *pr, plitem_t *globals) { - ddef_t vector_def; - ddef_t *global; + pr_def_t vector_def; + pr_def_t *global; plitem_t *keys; int count; const char *global_name; @@ -405,7 +405,7 @@ ED_InitGlobals (progs_t *pr, plitem_t *globals) VISIBLE void ED_InitEntity (progs_t *pr, plitem_t *entity, edict_t *ent) { - ddef_t *field; + pr_def_t *field; plitem_t *keys; const char *field_name; const char *value; diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 3238e774e..07ef44d60 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -52,10 +52,10 @@ #include "compat.h" -ddef_t * -PR_GlobalAtOfs (progs_t * pr, pr_int_t ofs) +pr_def_t * +PR_GlobalAtOfs (progs_t * pr, pointer_t ofs) { - ddef_t *def; + pr_def_t *def; pr_uint_t i; for (i = 0; i < pr->progs->numglobaldefs; i++) { @@ -66,10 +66,10 @@ PR_GlobalAtOfs (progs_t * pr, pr_int_t ofs) return NULL; } -VISIBLE ddef_t * -PR_FieldAtOfs (progs_t * pr, pr_int_t ofs) +VISIBLE pr_def_t * +PR_FieldAtOfs (progs_t * pr, pointer_t ofs) { - ddef_t *def; + pr_def_t *def; pr_uint_t i; for (i = 0; i < pr->progs->numfielddefs; i++) { @@ -80,13 +80,13 @@ PR_FieldAtOfs (progs_t * pr, pr_int_t ofs) return NULL; } -VISIBLE ddef_t * +VISIBLE pr_def_t * PR_FindField (progs_t * pr, const char *name) { return Hash_Find (pr->field_hash, name); } -VISIBLE ddef_t * +VISIBLE pr_def_t * PR_FindGlobal (progs_t * pr, const char *name) { return Hash_Find (pr->global_hash, name); @@ -108,7 +108,7 @@ VISIBLE int PR_ResolveGlobals (progs_t *pr) { const char *sym; - ddef_t *def; + pr_def_t *def; int i; if (pr->progs->version == PROG_ID_VERSION) { @@ -180,7 +180,7 @@ int PR_AccessField (progs_t *pr, const char *name, etype_t type, const char *file, int line) { - ddef_t *def = PR_FindField (pr, name); + pr_def_t *def = PR_FindField (pr, name); if (!def) PR_Error (pr, "undefined field %s accessed at %s:%d", name, file, line); diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 8352228d4..8c6aa3d58 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -255,7 +255,7 @@ PF_Find (progs_t *pr) int i; // ev_vector int e, f; etype_t type; - ddef_t *field_def; + pr_def_t *field_def; edict_t *ed; e = P_EDICTNUM (pr, 0); @@ -596,7 +596,7 @@ static void PF_PR_SetField (progs_t *pr) { edict_t *ent = P_EDICT (pr, 0); - ddef_t *field = PR_FindField (pr, P_GSTRING (pr, 1)); + pr_def_t *field = PR_FindField (pr, P_GSTRING (pr, 1)); const char *value = P_GSTRING (pr, 2); R_INT (pr) = 0; diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index ed3a1d78b..efb193bc8 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1550,7 +1550,7 @@ static void rua_PR_FindGlobal (progs_t *pr) { const char *name = P_GSTRING (pr, 0); - ddef_t *def; + pr_def_t *def; R_POINTER (pr) = 0; def = PR_FindGlobal (pr, name); @@ -1654,7 +1654,7 @@ rua_init_finish (progs_t *pr) static int rua_init_runtime (progs_t *pr) { - ddef_t *def; + pr_def_t *def; unsigned i; if (!pr->selector_hash) diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 7e98550d4..60ee75368 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -379,7 +379,7 @@ set_address (sv_def_t *def, void *address) static int resolve_globals (progs_t *pr, sv_def_t *def, int mode) { - ddef_t *ddef; + pr_def_t *ddef; int ret = 1; if (mode == 2) { @@ -425,7 +425,7 @@ resolve_functions (progs_t *pr, sv_def_t *def, int mode) static int resolve_fields (progs_t *pr, sv_def_t *def, int mode) { - ddef_t *ddef; + pr_def_t *ddef; int ret = 1; if (mode == 2) { diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index 0c844abd8..7c8a46d84 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -551,7 +551,7 @@ static int qwe_load_finish (progs_t *pr) { edict_t *ent; - ddef_t *targetname; + pr_def_t *targetname; targetname = PR_FindField (pr, "targetname"); ent = EDICT_NUM (pr, 0); diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index e4856f69b..f5abeed3f 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -389,7 +389,7 @@ set_address (sv_def_t *def, void *address) static int resolve_globals (progs_t *pr, sv_def_t *def, int mode) { - ddef_t *ddef; + pr_def_t *ddef; int ret = 1; if (mode == 2) { @@ -435,7 +435,7 @@ resolve_functions (progs_t *pr, sv_def_t *def, int mode) static int resolve_fields (progs_t *pr, sv_def_t *def, int mode) { - ddef_t *ddef; + pr_def_t *ddef; int ret = 1; if (mode == 2) { diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 89dbb50fa..79024313b 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -52,14 +52,14 @@ static int cmp (const void *_a, const void *_b) { - const ddef_t *a = (const ddef_t *)_a; - const ddef_t *b = (const ddef_t *)_b; + const pr_def_t *a = (const pr_def_t *)_a; + const pr_def_t *b = (const pr_def_t *)_b; return a->ofs - b->ofs; } static void -dump_def (progs_t *pr, ddef_t *def, int indent) +dump_def (progs_t *pr, pr_def_t *def, int indent) { const char *name; const char *type; @@ -69,10 +69,10 @@ dump_def (progs_t *pr, ddef_t *def, int indent) const char *str; int saveglobal; - if (!def->type && !def->ofs && !def->s_name) + if (!def->type && !def->ofs && !def->name) return; - name = PR_GetString (pr, def->s_name); + name = PR_GetString (pr, def->name); type = pr_type_name[def->type & ~DEF_SAVEGLOBAL]; saveglobal = (def->type & DEF_SAVEGLOBAL) != 0; offset = def->ofs; @@ -148,15 +148,15 @@ dump_def (progs_t *pr, ddef_t *def, int indent) break; } } - printf ("%*s %x %d %s %s%s\n", indent * 12, "", - offset, saveglobal, name, type, comment); + printf ("%*s %x %d %s %s:%x %s\n", indent * 12, "", + offset, saveglobal, name, type, def->type_encoding, comment); } void dump_globals (progs_t *pr) { unsigned int i; - ddef_t *global_defs = pr->pr_globaldefs; + pr_def_t *global_defs = pr->pr_globaldefs; if (sorted) { global_defs = malloc (pr->progs->numglobaldefs * sizeof (ddef_t)); @@ -165,7 +165,7 @@ dump_globals (progs_t *pr) qsort (global_defs, pr->progs->numglobaldefs, sizeof (ddef_t), cmp); } for (i = 0; i < pr->progs->numglobaldefs; i++) { - ddef_t *def = &global_defs[i]; + pr_def_t *def = &global_defs[i]; dump_def (pr, def, 0); } } @@ -180,9 +180,9 @@ dump_fields (progs_t *pr) const char *comment; for (i = 0; i < pr->progs->numfielddefs; i++) { - ddef_t *def = &pr->pr_fielddefs[i]; + pr_def_t *def = &pr->pr_fielddefs[i]; - name = PR_GetString (pr, def->s_name); + name = PR_GetString (pr, def->name); type = pr_type_name[def->type & ~DEF_SAVEGLOBAL]; offset = def->ofs; @@ -516,7 +516,7 @@ dump_types (progs_t *pr) { qfo_mspace_t spaces[qfo_num_spaces]; qfo_t qfo; - ddef_t *encodings_def; + pr_def_t *encodings_def; qfot_type_encodings_t *encodings; encodings_def = PR_FindGlobal (pr, ".type_encodings"); diff --git a/tools/qfcc/source/dump_modules.c b/tools/qfcc/source/dump_modules.c index d55195aaa..6bb559003 100644 --- a/tools/qfcc/source/dump_modules.c +++ b/tools/qfcc/source/dump_modules.c @@ -205,11 +205,11 @@ dump_modules (progs_t *pr) unsigned int i; for (i = 0; i < pr->progs->numglobaldefs; i++) { - ddef_t *def = &pr->pr_globaldefs[i]; + pr_def_t *def = &pr->pr_globaldefs[i]; const char *name = ""; - if (PR_StringValid (pr, def->s_name)) - name = PR_GetString (pr, def->s_name); + if (PR_StringValid (pr, def->name)) + name = PR_GetString (pr, def->name); if (strcmp (name, "_OBJ_MODULE") == 0) { printf ("module @ %x\n", def->ofs); dump_module (pr, &G_STRUCT (pr, pr_module_t, def->ofs)); diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 79c4effeb..f79bed688 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -926,6 +926,7 @@ qfo_to_progs (qfo_t *qfo, int *size) progs->numglobals = RUP (progs->numglobals, type_xdef.alignment); xdefs_start = progs->numglobals; progs->numglobals += progs->numglobaldefs * type_size (&type_xdef); + progs->numglobals += progs->numfielddefs * type_size (&type_xdef); progs->entityfields = qfo->spaces[qfo_entity_space].data_size; *size += progs->numstatements * sizeof (dstatement_t); *size += progs->numglobaldefs * sizeof (ddef_t); @@ -1012,10 +1013,6 @@ qfo_to_progs (qfo_t *qfo, int *size) globaldefs++; } - for (i = 0; i < qfo->spaces[qfo_type_space].num_defs; i++) { - qfo->spaces[qfo_type_space].defs[i].offset += type_data - globals; - } - for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { convert_def (qfo, qfo->spaces[qfo_entity_space].defs + i, fielddefs + i); @@ -1044,21 +1041,27 @@ qfo_to_progs (qfo_t *qfo, int *size) encodings->size = qfo->spaces[qfo_type_space].data_size; } if (xdefs_def) { - int xdef_data_size = type_size (&type_xdef); - pr_xdefs_t *xdefs = (pr_xdefs_t *) &globals[xdefs_def->offset]; + pr_xdefs_t *xdefs = (pr_xdefs_t *) &globals[xdefs_def->offset]; + xdef_t *xdef = (xdef_t *) xdef_data; xdefs->xdefs = xdefs_start; - xdefs->num_xdefs = progs->numglobaldefs; - for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { + xdefs->num_xdefs = progs->numglobaldefs + progs->numfielddefs; + for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; + i++, xdef++) { qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; - xdef_data[0].pointer_var = def->type + type_encodings_start; - xdef_data[1].pointer_var = def->offset; - xdef_data += xdef_data_size; + xdef->type = def->type + type_encodings_start; + xdef->ofs = def->offset; } - for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { + for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; + i++, xdef++) { qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + i; - xdef_data[0].pointer_var = def->type + type_encodings_start; - xdef_data[1].pointer_var = def->offset; - xdef_data += xdef_data_size; + xdef->type = def->type + type_encodings_start; + xdef->ofs = def->offset; + } + for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; + i++, xdef++) { + qfo_def_t *def = qfo->spaces[qfo_entity_space].defs + i; + xdef->type = def->type + type_encodings_start; + xdef->ofs = def->offset; } } @@ -1108,7 +1111,7 @@ qfo_to_sym (qfo_t *qfo, int *size) pr_auxfunction_t *auxfuncs; pr_auxfunction_t *aux; pr_lineno_t *linenos; - ddef_t *locals, *ld; + pr_def_t *locals, *ld; *size = sizeof (pr_debug_header_t); sym = calloc (1, *size); @@ -1129,12 +1132,12 @@ qfo_to_sym (qfo_t *qfo, int *size) *size += sym->num_auxfunctions * sizeof (pr_auxfunction_t); *size += sym->num_linenos * sizeof (pr_lineno_t); - *size += sym->num_locals * sizeof (ddef_t); + *size += sym->num_locals * sizeof (pr_def_t); sym = realloc (sym, *size); auxfuncs = (pr_auxfunction_t *)(sym + 1); linenos = (pr_lineno_t *)(auxfuncs + sym->num_auxfunctions); - locals = (ddef_t *)(linenos + sym->num_linenos); + locals = (pr_def_t *)(linenos + sym->num_linenos); sym->auxfunctions = (char *) auxfuncs - (char *) sym; sym->linenos = (char *) linenos - (char *) sym; @@ -1162,8 +1165,13 @@ qfo_to_sym (qfo_t *qfo, int *size) qfo->lines[func->line_info].fa.func = aux - auxfuncs; if (num_locals) { aux->local_defs = ld - locals; - for (j = 0; j < num_locals; j++) - convert_def (qfo, def++, ld++); + for (j = 0; j < num_locals; j++, def++, ld++) { + ld->type = get_def_type (qfo, def->type); + ld->type = def->type; + ld->ofs = def->offset; + ld->name = def->name; + ld->type_encoding = def->type; + } } aux->num_locals = num_locals; //FIXME check type diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index be14d144f..e113912fb 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -256,6 +256,9 @@ convert_qfo (void) { int size; int i; + xdef_t *xdef = 0; + pr_xdefs_t *xdefs = 0; + ddef_t *xdefs_def = 0; pr.progs = qfo_to_progs (qfo, &size); @@ -264,20 +267,52 @@ convert_qfo (void) pr.pr_strings = P (char, ofs_strings); pr.pr_stringsize = pr.progs->numstrings; pr.pr_functions = P (dfunction_t, ofs_functions); - pr.pr_globaldefs = P (ddef_t, ofs_globaldefs); - pr.pr_fielddefs = P (ddef_t, ofs_fielddefs); + pr.pr_globalddefs = P (ddef_t, ofs_globaldefs); + pr.pr_fieldddefs = P (ddef_t, ofs_fielddefs); pr.pr_globals = P (pr_type_t, ofs_globals); pr.globals_size = pr.progs->numglobals; pr.pr_edict_size = max (1, pr.progs->entityfields) * 4; pr.pr_edictareasize = 1 * pr.pr_edict_size; #undef P + pr.pr_globaldefs = malloc ((pr.progs->numglobaldefs + + pr.progs->numfielddefs) + * sizeof (pr_def_t)); + // can't use PR_FindGlobal yet as pr_globaldefs is still uninitialized + for (i = 0; i < (int) pr.progs->numglobaldefs; i++) { + ddef_t *ddef = pr.pr_globalddefs + i; + if (!strcmp (PR_GetString (&pr, ddef->s_name), ".xdefs")) { + xdefs_def = ddef; + break; + } + } + if (xdefs_def) { + xdefs = &G_STRUCT (&pr, pr_xdefs_t, xdefs_def->ofs); + xdef = &G_STRUCT (&pr, xdef_t, xdefs->xdefs); + } + for (i = 0; i < (int) pr.progs->numglobaldefs; i++, xdef++) { + ddef_t *ddef = pr.pr_globalddefs + i; + pr_def_t *def = pr.pr_globaldefs + i; + def->type = ddef->type; + def->ofs = xdefs ? xdef->ofs : ddef->ofs; + def->name = ddef->s_name; + def->type_encoding = xdefs ? xdef->type : 0; + } + for (i = 0; i < (int) pr.progs->numfielddefs; i++, xdef++) { + ddef_t *ddef = pr.pr_fieldddefs + i; + pr_def_t *def = pr.pr_fielddefs + i; + def->type = ddef->type; + def->ofs = xdefs ? xdef->ofs : ddef->ofs; + def->name = ddef->s_name; + def->type_encoding = xdefs ? xdef->type : 0; + } + if (verbosity) { pr.debug = qfo_to_sym (qfo, &size); #define P(t,o) ((t *)((char *)pr.debug + pr.debug->o)) pr.auxfunctions = P (pr_auxfunction_t, auxfunctions); pr.linenos = P (pr_lineno_t, linenos); - pr.local_defs = P (ddef_t, locals); + pr.local_defs = P (pr_def_t, locals); #undef P pr.local_defs = calloc (qfo->num_defs, sizeof (ddef_t)); From 806af854475f491c6facb6afb68b15e2ea9672e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Feb 2020 22:44:08 +0900 Subject: [PATCH 0360/3664] Remove reference to ddef_t from progs.h This cleans up some horrible names and redundant fields that were a result of the transition to pr_def_t --- include/QF/progs.h | 2 -- libs/gamecode/pr_load.c | 35 ++++++++++++++++++----------------- tools/qfcc/source/qfprogs.c | 13 ++++++++----- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index e93bea597..a413b2f25 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1616,8 +1616,6 @@ struct progs_s { bfunction_t *function_table; char *pr_strings; int pr_stringsize; - ddef_t *pr_globalddefs; - ddef_t *pr_fieldddefs; pr_def_t *pr_globaldefs; pr_def_t *pr_fielddefs; dstatement_t *pr_statements; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index eec948d45..99136ed4f 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -120,7 +120,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) byte *base; byte *heap; pr_def_t *xdefs_def = 0; - + ddef_t *global_ddefs; + ddef_t *field_ddefs; if (!pr->file_error) pr->file_error = file_error; @@ -222,8 +223,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) (dfunction_t *) (base + pr->progs->ofs_functions); pr->pr_strings = (char *) base + pr->progs->ofs_strings; pr->pr_stringsize = (char *) heap + pr->zone_size - (char *) base; - pr->pr_globalddefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); - pr->pr_fieldddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs); + global_ddefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); + field_ddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs); pr->pr_statements = (dstatement_t *) (base + pr->progs->ofs_statements); pr->pr_globals = (pr_type_t *) (base + pr->progs->ofs_globals); @@ -280,13 +281,13 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->pr_globaldefs = calloc (pr->progs->numglobaldefs, sizeof (pr_def_t)); for (i = 0; i < pr->progs->numglobaldefs; i++) { - pr->pr_globalddefs[i].type = LittleShort (pr->pr_globalddefs[i].type); - pr->pr_globalddefs[i].ofs = LittleShort (pr->pr_globalddefs[i].ofs); - pr->pr_globalddefs[i].s_name = LittleLong (pr->pr_globalddefs[i].s_name); + global_ddefs[i].type = LittleShort (global_ddefs[i].type); + global_ddefs[i].ofs = LittleShort (global_ddefs[i].ofs); + global_ddefs[i].s_name = LittleLong (global_ddefs[i].s_name); - pr->pr_globaldefs[i].type = pr->pr_globalddefs[i].type; - pr->pr_globaldefs[i].ofs = pr->pr_globalddefs[i].ofs; - pr->pr_globaldefs[i].name = pr->pr_globalddefs[i].s_name; + pr->pr_globaldefs[i].type = global_ddefs[i].type; + pr->pr_globaldefs[i].ofs = global_ddefs[i].ofs; + pr->pr_globaldefs[i].name = global_ddefs[i].s_name; Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]); } @@ -295,15 +296,15 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) } pr->pr_fielddefs = calloc (pr->progs->numfielddefs, sizeof (pr_def_t)); for (i = 0; i < pr->progs->numfielddefs; i++) { - pr->pr_fieldddefs[i].type = LittleShort (pr->pr_fieldddefs[i].type); - if (pr->pr_fielddefs[i].type & DEF_SAVEGLOBAL) - PR_Error (pr, "PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); - pr->pr_fieldddefs[i].ofs = LittleShort (pr->pr_fieldddefs[i].ofs); - pr->pr_fieldddefs[i].s_name = LittleLong (pr->pr_fieldddefs[i].s_name); + field_ddefs[i].type = LittleShort (field_ddefs[i].type); + if (field_ddefs[i].type & DEF_SAVEGLOBAL) + PR_Error (pr, "PR_LoadProgs: DEF_SAVEGLOBAL on field def %zd", i); + field_ddefs[i].ofs = LittleShort (field_ddefs[i].ofs); + field_ddefs[i].s_name = LittleLong (field_ddefs[i].s_name); - pr->pr_fielddefs[i].type = pr->pr_fieldddefs[i].type; - pr->pr_fielddefs[i].ofs = pr->pr_fieldddefs[i].ofs; - pr->pr_fielddefs[i].name = pr->pr_fieldddefs[i].s_name; + pr->pr_fielddefs[i].type = field_ddefs[i].type; + pr->pr_fielddefs[i].ofs = field_ddefs[i].ofs; + pr->pr_fielddefs[i].name = field_ddefs[i].s_name; Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]); } diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index e113912fb..28d9141c5 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -259,6 +259,8 @@ convert_qfo (void) xdef_t *xdef = 0; pr_xdefs_t *xdefs = 0; ddef_t *xdefs_def = 0; + ddef_t *global_ddefs; + ddef_t *field_ddefs; pr.progs = qfo_to_progs (qfo, &size); @@ -267,8 +269,8 @@ convert_qfo (void) pr.pr_strings = P (char, ofs_strings); pr.pr_stringsize = pr.progs->numstrings; pr.pr_functions = P (dfunction_t, ofs_functions); - pr.pr_globalddefs = P (ddef_t, ofs_globaldefs); - pr.pr_fieldddefs = P (ddef_t, ofs_fielddefs); + global_ddefs = P (ddef_t, ofs_globaldefs); + field_ddefs = P (ddef_t, ofs_fielddefs); pr.pr_globals = P (pr_type_t, ofs_globals); pr.globals_size = pr.progs->numglobals; pr.pr_edict_size = max (1, pr.progs->entityfields) * 4; @@ -278,9 +280,10 @@ convert_qfo (void) pr.pr_globaldefs = malloc ((pr.progs->numglobaldefs + pr.progs->numfielddefs) * sizeof (pr_def_t)); + pr.pr_fielddefs = pr.pr_globaldefs + pr.progs->numglobaldefs; // can't use PR_FindGlobal yet as pr_globaldefs is still uninitialized for (i = 0; i < (int) pr.progs->numglobaldefs; i++) { - ddef_t *ddef = pr.pr_globalddefs + i; + ddef_t *ddef = global_ddefs + i; if (!strcmp (PR_GetString (&pr, ddef->s_name), ".xdefs")) { xdefs_def = ddef; break; @@ -291,7 +294,7 @@ convert_qfo (void) xdef = &G_STRUCT (&pr, xdef_t, xdefs->xdefs); } for (i = 0; i < (int) pr.progs->numglobaldefs; i++, xdef++) { - ddef_t *ddef = pr.pr_globalddefs + i; + ddef_t *ddef = global_ddefs + i; pr_def_t *def = pr.pr_globaldefs + i; def->type = ddef->type; def->ofs = xdefs ? xdef->ofs : ddef->ofs; @@ -299,7 +302,7 @@ convert_qfo (void) def->type_encoding = xdefs ? xdef->type : 0; } for (i = 0; i < (int) pr.progs->numfielddefs; i++, xdef++) { - ddef_t *ddef = pr.pr_fieldddefs + i; + ddef_t *ddef = field_ddefs + i; pr_def_t *def = pr.pr_fielddefs + i; def->type = ddef->type; def->ofs = xdefs ? xdef->ofs : ddef->ofs; From 3aabfa71d986e75d7489dd58f3cefa3ce5a8b608 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Feb 2020 23:33:56 +0900 Subject: [PATCH 0361/3664] Find lost type encoding relocations I have no idea why I thought it was a good idea to delete those lines. Yay for regression tests, though. --- tools/qfcc/source/obj_file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index f79bed688..8d7250abc 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -1013,6 +1013,10 @@ qfo_to_progs (qfo_t *qfo, int *size) globaldefs++; } + for (i = 0; i < qfo->spaces[qfo_type_space].num_defs; i++) { + qfo->spaces[qfo_type_space].defs[i].offset += type_encodings_start; + } + for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { convert_def (qfo, qfo->spaces[qfo_entity_space].defs + i, fielddefs + i); From 52d54f98bfecd16674ec71bae798ad36bc3150db Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Feb 2020 23:41:09 +0900 Subject: [PATCH 0362/3664] Fix some issues in the typedef test It wasn't being strict enough in the test (but was good enough to catch the relocation error, at least) and was printing the alias name incorrectly. --- tools/qfcc/test/typedef.r | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/test/typedef.r b/tools/qfcc/test/typedef.r index bb5d52e4a..e6e80a92b 100644 --- a/tools/qfcc/test/typedef.r +++ b/tools/qfcc/test/typedef.r @@ -22,10 +22,12 @@ next_type (qfot_type_t *type) } int -check_alias (qfot_type_t *alias) +check_alias (string name, qfot_type_t *alias) { - if (alias.meta != ty_basic && alias.t.type != ev_pointer) { - printf ("%s is not a *int alias\n", alias.t.alias.name); + if (alias.meta != ty_basic || alias.t.type != ev_pointer + || alias.t.fldptr.aux_type.meta != ty_basic + || alias.t.fldptr.aux_type.t.type != ev_integer) { + printf ("%s is not a *int alias\n", name); return 0; } return 1; @@ -47,10 +49,12 @@ main (void) type = next_type (type)) { if (type.meta == ty_alias) { if (type.t.alias.name == "foo") { - found_foo = check_alias (type.t.alias.aux_type); + found_foo = check_alias (type.t.alias.name, + type.t.alias.aux_type); } if (type.t.alias.name == "bar") { - found_bar = check_alias (type.t.alias.aux_type); + found_bar = check_alias (type.t.alias.name, + type.t.alias.aux_type); } } } From f8b1a3a89fdb40cdf4463c467388dd2ddd365071 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 11:41:19 +0900 Subject: [PATCH 0363/3664] Return the previous sys print callbacks This allows for temporary overrides. --- include/QF/sys.h | 4 ++-- libs/util/sys.c | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 10ef6999f..76b6ad844 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -65,8 +65,8 @@ int Sys_mkdir (const char *path); typedef void (*sys_printf_t) (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); typedef void (*sys_error_t) (void *data); -void Sys_SetStdPrintf (sys_printf_t func); -void Sys_SetErrPrintf (sys_printf_t func); +sys_printf_t Sys_SetStdPrintf (sys_printf_t func); +sys_printf_t Sys_SetErrPrintf (sys_printf_t func); void Sys_PushErrorHandler (sys_error_t func, void *data); void Sys_PopErrorHandler (void); diff --git a/libs/util/sys.c b/libs/util/sys.c index b2e28f71d..62ddfa35b 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -240,16 +240,20 @@ Sys_FileExists (const char *path) for want of a better name, but it sets the function pointer for the actual implementation of Sys_Printf. */ -VISIBLE void +VISIBLE sys_printf_t Sys_SetStdPrintf (sys_printf_t func) { + sys_printf_t prev = sys_std_printf_function; sys_std_printf_function = func; + return prev; } -VISIBLE void +VISIBLE sys_printf_t Sys_SetErrPrintf (sys_printf_t func) { + sys_printf_t prev = sys_err_printf_function; sys_err_printf_function = func; + return prev; } void From 6c6433dea5bb6643747960f77d430afaf6c11ff9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 11:52:35 +0900 Subject: [PATCH 0364/3664] Fetch the def name only once when scanning Not that speed is critical at this point, but it feels better. --- tools/qfcc/source/obj_file.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 8d7250abc..15fc0fdf0 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -997,9 +997,10 @@ qfo_to_progs (qfo_t *qfo, int *size) for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; - if (!strcmp (QFO_GETSTR (qfo, def->name), ".type_encodings")) + const char *defname = QFO_GETSTR (qfo, def->name); + if (!strcmp (defname, ".type_encodings")) types_def = def; - if (!strcmp (QFO_GETSTR (qfo, def->name), ".xdefs")) + if (!strcmp (defname, ".xdefs")) xdefs_def = def; convert_def (qfo, def, globaldefs++); } From 155a633ebe0455b334e8d5605055fe4a5653e638 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 11:53:57 +0900 Subject: [PATCH 0365/3664] Include extended defs data in the size report --- tools/qfcc/source/obj_file.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 15fc0fdf0..735a68ab0 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -891,6 +891,8 @@ qfo_to_progs (qfo_t *qfo, int *size) int xdefs_start; unsigned big_locals = 0; int big_func = 0; + pr_xdefs_t *xdefs; + xdef_t *xdef; *size = RUP (sizeof (dprograms_t), 16); progs = calloc (1, *size); @@ -1046,8 +1048,8 @@ qfo_to_progs (qfo_t *qfo, int *size) encodings->size = qfo->spaces[qfo_type_space].data_size; } if (xdefs_def) { - pr_xdefs_t *xdefs = (pr_xdefs_t *) &globals[xdefs_def->offset]; - xdef_t *xdef = (xdef_t *) xdef_data; + xdefs = (pr_xdefs_t *) &globals[xdefs_def->offset]; + xdef = (xdef_t *) xdef_data; xdefs->xdefs = xdefs_start; xdefs->num_xdefs = progs->numglobaldefs + progs->numfielddefs; for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; @@ -1091,7 +1093,7 @@ qfo_to_progs (qfo_t *qfo, int *size) printf ("%6i statements\n", progs->numstatements); printf ("%6i functions\n", progs->numfunctions); printf ("%6i global defs\n", progs->numglobaldefs); - printf ("%6i fielddefs\n", progs->numfielddefs); + printf ("%6i field defs\n", progs->numfielddefs); printf ("%6i globals\n", progs->numglobals); printf (" %6i near globals\n", near_data_size); printf (" %6i locals size%s\n", locals_size, big_function); @@ -1099,6 +1101,10 @@ qfo_to_progs (qfo_t *qfo, int *size) qfo->spaces[qfo_far_data_space].data_size); printf (" %6i type globals\n", qfo->spaces[qfo_type_space].data_size); + if (xdefs) { + printf (" %6i extended defs\n", + xdefs->num_xdefs * type_size (&type_xdef)); + } printf ("%6i entity fields\n", progs->entityfields); } From 81293d98dd2d236d647c1b6e2e72a33ba63b2bc7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 14:39:02 +0900 Subject: [PATCH 0366/3664] Fix qfo line info dumping The addition of xdef data has made qfo_to_progs unusable in qfprogs, resulting in various invalid memory accesses. It always was an ugly hack anyway, so this is the first step to proper qfo support in qfprogs. --- tools/qfcc/include/qfprogs.h | 1 + tools/qfcc/source/dump_lines.c | 164 ++++++++++++++++++++++++++------- tools/qfcc/source/qfprogs.c | 94 +------------------ 3 files changed, 139 insertions(+), 120 deletions(-) diff --git a/tools/qfcc/include/qfprogs.h b/tools/qfcc/include/qfprogs.h index 09fade09d..bb64b3fb6 100644 --- a/tools/qfcc/include/qfprogs.h +++ b/tools/qfcc/include/qfprogs.h @@ -56,6 +56,7 @@ void dump_strings (struct progs_s *pr); void qfo_globals (struct qfo_s *qfo); void qfo_functions (struct qfo_s *qfo); +void qfo_lines (struct qfo_s *qfo); void qfo_relocs (struct qfo_s *qfo); void qfo_types (struct qfo_s *qfo); diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index 847bdb5c2..ae504c03d 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -41,49 +41,151 @@ #include #include "QF/progs.h" +#include "QF/pr_type.h" +#include "obj_file.h" #include "qfprogs.h" -void -dump_lines (progs_t *pr) +typedef struct { + const char *source_name; + const char *source_file; + pr_uint_t source_line; + pr_int_t first_statement; + pointer_t return_type; + pr_uint_t local_defs; + pr_uint_t num_locals; + pr_uint_t line_info; + pr_uint_t function; +} func_data_t; + +typedef func_data_t *(*get_func_data_t)(unsigned func, void *data); + +static func_data_t * +progs_get_func_data (unsigned func_index, void *data) { - unsigned int i, line, addr; - pr_lineno_t *lineno; - pr_auxfunction_t *aux_func = 0; - dfunction_t *func = 0; + static func_data_t func_data; + progs_t *pr = (progs_t *) data; + pr_auxfunction_t *aux_func; + dfunction_t *func; - if (!pr->debug) - return; - for (i = 0; i < pr->debug->num_linenos; i++) { - lineno = &pr->linenos[i]; + memset (&func_data, 0, sizeof (func_data)); + if (func_index < pr->debug->num_auxfunctions) { + aux_func = pr->auxfunctions + func_index; + func_data.source_line = aux_func->source_line; + func_data.return_type = aux_func->return_type; + func_data.num_locals = aux_func->num_locals; + func_data.local_defs = aux_func->local_defs; + func_data.line_info = aux_func->line_info; + func_data.function = aux_func->function; + if (aux_func->function < (unsigned int) pr->progs->numfunctions) { + func = pr->pr_functions + aux_func->function; + func_data.source_file = pr->pr_strings + func->s_file; + func_data.source_name = pr->pr_strings + func->s_name; + func_data.first_statement = func->first_statement; + } + return &func_data; + } + return 0; +} +static void +dump_line_set (pr_lineno_t *lineno, unsigned count, + get_func_data_t get_func_data, void *data) +{ + unsigned int line, addr; + func_data_t *func_data = 0; + + for (; count-- > 0; lineno++) { if (!lineno->line) { - aux_func = 0; - func = 0; - if (lineno->fa.func < pr->debug->num_auxfunctions) - aux_func = pr->auxfunctions + lineno->fa.func; - if (aux_func - && aux_func->function < (unsigned int) pr->progs->numfunctions) - func = pr->pr_functions + aux_func->function; + func_data = get_func_data(lineno->fa.func, data); } printf ("%5u %5u", lineno->fa.addr, lineno->line); line = addr = -1; - if (aux_func) - line = aux_func->source_line + lineno->line; - if (func) - addr = lineno->line ? lineno->fa.addr - : (unsigned int) func->first_statement; - if (aux_func && func) - printf (" %05x %s:%u %s+%u %d", addr, pr->pr_strings + func->s_file, - line, pr->pr_strings + func->s_name, - addr - func->first_statement, aux_func->return_type); - else if (aux_func) - printf ("%u %u %u %u %u %d", aux_func->function, line, - aux_func->line_info, aux_func->local_defs, - aux_func->num_locals, aux_func->return_type); - else if (lineno->line) + if (func_data) { + line = func_data->source_line + lineno->line; + if (func_data->source_name) { + addr = lineno->line ? (pr_int_t) lineno->fa.addr + : func_data->first_statement; + printf (" %05x %s:%u %s+%u %d", addr, func_data->source_file, + line, func_data->source_name, + addr - func_data->first_statement, + func_data->return_type); + } else { + printf ("%u %u %u %u %u %d", func_data->function, line, + func_data->line_info, func_data->local_defs, + func_data->num_locals, func_data->return_type); + } + } else if (lineno->line) { printf ("%5x", lineno->fa.addr); + } printf ("\n"); } } + +void +dump_lines (progs_t *pr) +{ + if (!pr->debug) + return; + dump_line_set (pr->linenos, pr->debug->num_linenos, + progs_get_func_data, pr); +} + +static func_data_t * +qfo_get_func_data (unsigned func_index, void *data) +{ + return (func_data_t *) data; +} + +static void +qfo_set_func_data (qfo_t *qfo, qfo_func_t *func, func_data_t *func_data) +{ + qfot_type_t *type; + + func_data->source_line = func->line; + //FIXME check type + type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); + func_data->return_type = type->t.func.return_type; + func_data->num_locals = -1; + if (func->locals_space < qfo->num_spaces) { + func_data->num_locals = qfo->spaces[func->locals_space].num_defs; + } + func_data->local_defs = func->locals_space; + func_data->line_info = func->line_info; + func_data->function = func - qfo->funcs; + func_data->source_file = QFO_GETSTR (qfo, func->file); + func_data->source_name = QFO_GETSTR (qfo, func->name); + func_data->first_statement = func->code; +} + +void +qfo_lines (qfo_t *qfo) +{ + static func_data_t func_data; + pr_lineno_t *start_lineno = 0; + pr_lineno_t *lineno; + qfo_func_t *func = 0; + + for (func = qfo->funcs; func - qfo->funcs < qfo->num_funcs; func++) { + if (!func->line_info) { + // builtin + continue; + } + if (func->line_info >= qfo->num_lines) { + printf ("%s: bad line info: %u >= %u\n", + QFO_GETSTR (qfo, func->name), + func->line_info, qfo->num_lines); + continue; + } + qfo_set_func_data(qfo, func, &func_data); + start_lineno = qfo->lines + func->line_info; + for (lineno = start_lineno + 1; + lineno - qfo->lines < qfo->num_lines && lineno->line; + lineno++) + { + } + dump_line_set (start_lineno, lineno-start_lineno, + qfo_get_func_data, &func_data); + } +} diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 28d9141c5..692a4f5ed 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -128,7 +128,6 @@ static edict_t *edicts; static int num_edicts; static int reserved_edicts = 1; static progs_t pr; -static int need_progs; static qfo_t *qfo; static const char *source_path = ""; @@ -234,7 +233,7 @@ init_qf (void) { Sys_Init (); - Cvar_Get ("pr_debug", va ("%d", verbosity), 0, 0, ""); + Cvar_Get ("pr_debug", va ("%d", 1+verbosity), 0, 0, ""); Cvar_Get ("pr_source_path", source_path, 0, 0, ""); PR_Init_Cvars (); PR_Init (); @@ -251,87 +250,6 @@ init_qf (void) Hash_SetHashCompare (func_tab, func_hash, func_compare); } -static void -convert_qfo (void) -{ - int size; - int i; - xdef_t *xdef = 0; - pr_xdefs_t *xdefs = 0; - ddef_t *xdefs_def = 0; - ddef_t *global_ddefs; - ddef_t *field_ddefs; - - pr.progs = qfo_to_progs (qfo, &size); - -#define P(t,o) ((t *)((char *)pr.progs + pr.progs->o)) - pr.pr_statements = P (dstatement_t, ofs_statements); - pr.pr_strings = P (char, ofs_strings); - pr.pr_stringsize = pr.progs->numstrings; - pr.pr_functions = P (dfunction_t, ofs_functions); - global_ddefs = P (ddef_t, ofs_globaldefs); - field_ddefs = P (ddef_t, ofs_fielddefs); - pr.pr_globals = P (pr_type_t, ofs_globals); - pr.globals_size = pr.progs->numglobals; - pr.pr_edict_size = max (1, pr.progs->entityfields) * 4; - pr.pr_edictareasize = 1 * pr.pr_edict_size; -#undef P - - pr.pr_globaldefs = malloc ((pr.progs->numglobaldefs - + pr.progs->numfielddefs) - * sizeof (pr_def_t)); - pr.pr_fielddefs = pr.pr_globaldefs + pr.progs->numglobaldefs; - // can't use PR_FindGlobal yet as pr_globaldefs is still uninitialized - for (i = 0; i < (int) pr.progs->numglobaldefs; i++) { - ddef_t *ddef = global_ddefs + i; - if (!strcmp (PR_GetString (&pr, ddef->s_name), ".xdefs")) { - xdefs_def = ddef; - break; - } - } - if (xdefs_def) { - xdefs = &G_STRUCT (&pr, pr_xdefs_t, xdefs_def->ofs); - xdef = &G_STRUCT (&pr, xdef_t, xdefs->xdefs); - } - for (i = 0; i < (int) pr.progs->numglobaldefs; i++, xdef++) { - ddef_t *ddef = global_ddefs + i; - pr_def_t *def = pr.pr_globaldefs + i; - def->type = ddef->type; - def->ofs = xdefs ? xdef->ofs : ddef->ofs; - def->name = ddef->s_name; - def->type_encoding = xdefs ? xdef->type : 0; - } - for (i = 0; i < (int) pr.progs->numfielddefs; i++, xdef++) { - ddef_t *ddef = field_ddefs + i; - pr_def_t *def = pr.pr_fielddefs + i; - def->type = ddef->type; - def->ofs = xdefs ? xdef->ofs : ddef->ofs; - def->name = ddef->s_name; - def->type_encoding = xdefs ? xdef->type : 0; - } - - if (verbosity) { - pr.debug = qfo_to_sym (qfo, &size); -#define P(t,o) ((t *)((char *)pr.debug + pr.debug->o)) - pr.auxfunctions = P (pr_auxfunction_t, auxfunctions); - pr.linenos = P (pr_lineno_t, linenos); - pr.local_defs = P (pr_def_t, locals); -#undef P - - pr.local_defs = calloc (qfo->num_defs, sizeof (ddef_t)); - - pr.auxfunction_map = calloc (pr.progs->numfunctions, - sizeof (pr_auxfunction_t *)); - for (i = 0; (int) i < pr.progs->numfunctions; i++) //FIXME (cast) - pr.auxfunction_map[i] = 0; - - for (i = 0; i < (int) pr.debug->num_auxfunctions; i++) { - pr_auxfunction_t *aux = pr.auxfunctions + i; - pr.auxfunction_map[aux->function] = aux; - } - } -} - static int load_progs (const char *name) { @@ -349,6 +267,7 @@ load_progs (const char *name) Qread (file, buff, 4); buff[4] = 0; Qseek (file, 0, SEEK_SET); + qfo = 0; if (!strcmp (buff, QFO)) { qfo = qfo_read (file); Qclose (file); @@ -356,9 +275,7 @@ load_progs (const char *name) if (!qfo) return 0; - if (!need_progs) - return 1; - convert_qfo (); + return 1; } else { pr.progs_name = name; pr.max_edicts = 1; @@ -392,7 +309,7 @@ operation_t operations[] = { {dump_strings, 0}, // strings {dump_fields, 0}, // fields {dump_functions, qfo_functions}, // functions - {dump_lines, 0}, // lines + {dump_lines, qfo_lines}, // lines {dump_modules, 0}, // modules {0, qfo_relocs}, // relocs {dump_types, qfo_types}, // types @@ -451,12 +368,11 @@ main (int argc, char **argv) } init_qf (); while (optind < argc) { - need_progs = !func->qfo; if (!load_progs (argv[optind++])) return 1; if (qfo && func->qfo) func->qfo (qfo); - else if (func->progs) + else if (!qfo && func->progs) func->progs (&pr); else fprintf (stderr, "can't process %s\n", argv[optind - 1]); From b0157e509559a8a403dcd882f0d27fd43bc94baa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 14:56:50 +0900 Subject: [PATCH 0367/3664] Fix qfo field dumping --- tools/qfcc/include/qfprogs.h | 1 + tools/qfcc/source/dump_globals.c | 35 ++++++++++++++++++++++++++++++++ tools/qfcc/source/qfprogs.c | 2 +- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/qfprogs.h b/tools/qfcc/include/qfprogs.h index bb64b3fb6..22a4574c4 100644 --- a/tools/qfcc/include/qfprogs.h +++ b/tools/qfcc/include/qfprogs.h @@ -55,6 +55,7 @@ struct dfunction_s *func_find (int st_num); void dump_strings (struct progs_s *pr); void qfo_globals (struct qfo_s *qfo); +void qfo_fields (struct qfo_s *qfo); void qfo_functions (struct qfo_s *qfo); void qfo_lines (struct qfo_s *qfo); void qfo_relocs (struct qfo_s *qfo); diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 79024313b..ea94f5d9d 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -192,6 +192,41 @@ dump_fields (progs_t *pr) } } +void +qfo_fields (qfo_t *qfo) +{ + unsigned int i; + const char *name; + const char *typestr; + qfot_type_t *type; + int offset; + const char *comment; + qfo_mspace_t *space = &qfo->spaces[qfo_entity_space]; + + if (qfo_entity_space >= qfo->num_spaces) { + printf ("no entity space\n"); + return; + } + if (!space->num_defs) { + printf ("no fields\n"); + return; + } + + for (i = 0; i < space->num_defs; i++) { + qfo_def_t *def = space->defs + i; + + name = QFO_GETSTR (qfo, def->name); + //FIXME check type + type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, def->type); + typestr = QFO_GETSTR (qfo, type->encoding); + offset = def->offset; + + comment = ""; + + printf ("%d %s %s%s\n", offset, name, typestr, comment); + } +} + void dump_functions (progs_t *pr) { diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 692a4f5ed..1ff2e6a85 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -307,7 +307,7 @@ operation_t operations[] = { {disassemble_progs, 0}, // disassemble {dump_globals, qfo_globals}, // globals {dump_strings, 0}, // strings - {dump_fields, 0}, // fields + {dump_fields, qfo_fields}, // fields {dump_functions, qfo_functions}, // functions {dump_lines, qfo_lines}, // lines {dump_modules, 0}, // modules From 6009d1d02384fede00a5c53b1b4e18cf1461a9a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 15:08:31 +0900 Subject: [PATCH 0368/3664] Fix qfo strings dumping --- tools/qfcc/include/qfprogs.h | 1 + tools/qfcc/source/dump_strings.c | 42 ++++++++++++++++++++++++-------- tools/qfcc/source/qfprogs.c | 2 +- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/include/qfprogs.h b/tools/qfcc/include/qfprogs.h index 22a4574c4..731a61194 100644 --- a/tools/qfcc/include/qfprogs.h +++ b/tools/qfcc/include/qfprogs.h @@ -59,6 +59,7 @@ void qfo_fields (struct qfo_s *qfo); void qfo_functions (struct qfo_s *qfo); void qfo_lines (struct qfo_s *qfo); void qfo_relocs (struct qfo_s *qfo); +void qfo_strings (struct qfo_s *qfo); void qfo_types (struct qfo_s *qfo); #endif//__qfprogs_h diff --git a/tools/qfcc/source/dump_strings.c b/tools/qfcc/source/dump_strings.c index 91d6ca2ba..fc0c0cb7d 100644 --- a/tools/qfcc/source/dump_strings.c +++ b/tools/qfcc/source/dump_strings.c @@ -36,21 +36,22 @@ #include "QF/progs.h" #include "QF/sys.h" +#include "obj_file.h" #include "qfprogs.h" -void -dump_strings (progs_t *pr) +static void +dump_string_block (const char *strblock, unsigned size) { - int i = 0; - char *s = pr->pr_strings; + const char *s = strblock; printf ("%d ", 0); - while (i++ < pr->progs->numstrings) { - switch (*s) { + while (s - strblock < size) { + char c = *s++; + switch (c) { case 0: fputs ("\n", stdout); - if (i < pr->progs->numstrings) - printf ("%d ", i); + if (s - strblock < size) + printf ("%ld ", s - strblock); break; case 9: fputs ("\\t", stdout); @@ -62,9 +63,30 @@ dump_strings (progs_t *pr) fputs ("\\r", stdout); break; default: - fputc (sys_char_map[(unsigned char)*s], stdout); + fputc (sys_char_map[(unsigned char)c], stdout); break; } - s++; } } + +void +dump_strings (progs_t *pr) +{ + dump_string_block (pr->pr_strings, pr->progs->numstrings); +} + +void +qfo_strings (qfo_t *qfo) +{ + qfo_mspace_t *space = &qfo->spaces[qfo_strings_space]; + + if (qfo_strings_space >= qfo->num_spaces) { + printf ("no strings space\n"); + return; + } + if (!space->data_size) { + printf ("no strings\n"); + return; + } + dump_string_block (space->d.strings, space->data_size); +} diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 1ff2e6a85..42c91b9ed 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -306,7 +306,7 @@ typedef struct { operation_t operations[] = { {disassemble_progs, 0}, // disassemble {dump_globals, qfo_globals}, // globals - {dump_strings, 0}, // strings + {dump_strings, qfo_strings}, // strings {dump_fields, qfo_fields}, // fields {dump_functions, qfo_functions}, // functions {dump_lines, qfo_lines}, // lines From 4b7ecdf74a2ce15316879bcdb0c4d0e646d61100 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 15:56:36 +0900 Subject: [PATCH 0369/3664] Make PR_Init take an instance to initialize This allows internal sub-systems to do per-instance initializations without other engine systems having to know about them. --- include/QF/pr_comp.h | 2 +- include/QF/progs.h | 8 ++++++-- libs/console/menu.c | 2 ++ libs/gamecode/pr_debug.c | 2 +- libs/gamecode/pr_load.c | 7 ++++--- libs/gamecode/pr_opcode.c | 4 ++++ libs/ruamoko/rua_init.c | 1 - nq/source/host.c | 5 ----- nq/source/sv_progs.c | 5 +++++ qw/source/cl_main.c | 4 +--- qw/source/sv_main.c | 3 --- qw/source/sv_progs.c | 6 ++++++ tools/qfcc/source/qfprogs.c | 3 ++- tools/qfcc/test/test-harness.c | 2 +- tools/qwaq/main.c | 2 +- tools/qwaq/qwaq.c | 2 +- 16 files changed, 35 insertions(+), 23 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index d1865d1cc..9df0416d3 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -409,7 +409,7 @@ typedef struct opcode_s { extern opcode_t pr_opcodes[]; opcode_t *PR_Opcode (pr_short_t opcode); -void PR_Opcode_Init (void); +void PR_Opcode_Init (void); // idempotent typedef struct dstatement_s { pr_opcode_e op:16; diff --git a/include/QF/progs.h b/include/QF/progs.h index a413b2f25..a07f70534 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -53,8 +53,12 @@ typedef struct edict_s edict_t; ///@{ /** Initialize the progs engine. + + The first call will initialize subsystems common to all progs instances. + + \param pr The progs engine instance to initialize. */ -void PR_Init (void); +void PR_Init (progs_t *pr); /** Initialize the Cvars for the progs engine. Call before calling PR_Init(). */ @@ -1488,7 +1492,7 @@ void *PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size); /// \addtogroup debug ///@{ -void PR_Debug_Init (void); +void PR_Debug_Init (progs_t *pr); void PR_Debug_Init_Cvars (void); int PR_LoadDebug (progs_t *pr); void PR_Debug_Watch (progs_t *pr, const char *expr); diff --git a/libs/console/menu.c b/libs/console/menu.c index 8320bc405..3ebf1d60a 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -583,6 +583,8 @@ Menu_Init (void) menu_pr_state.max_edicts = 0; menu_pr_state.zone_size = 1024 * 1024; + PR_Init (&menu_pr_state); + menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0); PR_RegisterBuiltins (&menu_pr_state, builtins); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 0c388eaff..8f05793b9 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -200,7 +200,7 @@ error: } void -PR_Debug_Init (void) +PR_Debug_Init (progs_t *pr) { file_hash = Hash_NewTable (1024, file_get_key, file_free, 0); } diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 99136ed4f..a7dced537 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -466,10 +466,11 @@ PR_Init_Cvars (void) } VISIBLE void -PR_Init (void) +PR_Init (progs_t *pr) { - PR_Opcode_Init (); - PR_Debug_Init (); + PR_Opcode_Init (); // idempotent + PR_Resources_Init (pr); + PR_Debug_Init (pr); } VISIBLE void diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 0ad3fab4b..26ce130cb 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -1493,6 +1493,10 @@ PR_Opcode_Init (void) { opcode_t *op; + if (opcode_table) { + // already initialized + return; + } opcode_table = Hash_NewTable (1021, 0, 0, 0); Hash_SetHashCompare (opcode_table, opcode_get_hash, opcode_compare); diff --git a/libs/ruamoko/rua_init.c b/libs/ruamoko/rua_init.c index ab973b569..bbfc67525 100644 --- a/libs/ruamoko/rua_init.c +++ b/libs/ruamoko/rua_init.c @@ -56,7 +56,6 @@ RUA_Init (progs_t *pr, int secure) { size_t i; - PR_Resources_Init (pr); for (i = 0; i < sizeof (init_funcs) / sizeof (init_funcs[0]); i++) init_funcs[i] (pr, secure); } diff --git a/nq/source/host.c b/nq/source/host.c index f6b59cf8b..67b55507b 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -896,14 +896,9 @@ Host_Init (void) Game_Init (); - PR_Init_Cvars (); - SV_Progs_Init_Cvars (); - if (!isDedicated) CL_InitCvars (); - PR_Init (); - if (isDedicated) { PI_RegisterPlugins (server_plugin_list); Con_Init ("server"); diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 60ee75368..8626ade59 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -521,6 +521,8 @@ SV_LoadProgs (void) void SV_Progs_Init (void) { + SV_Progs_Init_Cvars (); + pr_gametype = "netquake"; sv_pr_state.edicts = &sv.edicts; sv_pr_state.num_edicts = &sv.num_edicts; @@ -531,6 +533,8 @@ SV_Progs_Init (void) sv_pr_state.bi_map = bi_map; sv_pr_state.resolve = resolve; + PR_Init (&sv_pr_state); + SV_PR_Cmds_Init (); Cmd_AddCommand ("edict", ED_PrintEdict_f, "Report information on a given " @@ -548,6 +552,7 @@ SV_Progs_Init (void) void SV_Progs_Init_Cvars (void) { + PR_Init_Cvars (); sv_progs = Cvar_Get ("sv_progs", "", CVAR_NONE, NULL, "Override the default game progs."); sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL, diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 09fb1aec2..aa223736f 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1804,12 +1804,10 @@ Host_Init (void) Netchan_Init_Cvars (); - PR_Init_Cvars (); + PR_Init_Cvars (); // FIXME location CL_Init_Cvars (); - PR_Init (); - CL_Chat_Init (); CL_Cmd_Init (); diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index c69e23594..d764c012f 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2523,8 +2523,6 @@ SV_Init (void) Mod_Init_Cvars (); Netchan_Init_Cvars (); Pmove_Init_Cvars (); - SV_Progs_Init_Cvars (); - PR_Init_Cvars (); // and now reprocess the cmdline's sets for overrides Cmd_StuffCmds (sv_cbuf); @@ -2534,7 +2532,6 @@ SV_Init (void) Game_Init (); - PR_Init (); SV_Progs_Init (); Mod_Init (); diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index f5abeed3f..2c4ff5c3f 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -544,6 +544,8 @@ SV_LoadProgs (void) void SV_Progs_Init (void) { + SV_Progs_Init_Cvars (); + pr_gametype = "quakeworld"; sv_pr_state.edicts = &sv.edicts; sv_pr_state.num_edicts = &sv.num_edicts; @@ -556,6 +558,8 @@ SV_Progs_Init (void) sv_pr_state.bi_map = bi_map; sv_pr_state.resolve = resolve; + PR_Init (&sv_pr_state); + SV_PR_Cmds_Init (); SV_PR_QWE_Init (&sv_pr_state); SV_PR_CPQW_Init (&sv_pr_state); @@ -575,6 +579,8 @@ SV_Progs_Init (void) void SV_Progs_Init_Cvars (void) { + PR_Init_Cvars (); + r_skyname = Cvar_Get ("r_skyname", "", CVAR_NONE, NULL, "Default name of skybox if none given by map"); sv_progs = Cvar_Get ("sv_progs", "", CVAR_NONE, NULL, diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 42c91b9ed..64dab879a 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -236,7 +236,6 @@ init_qf (void) Cvar_Get ("pr_debug", va ("%d", 1+verbosity), 0, 0, ""); Cvar_Get ("pr_source_path", source_path, 0, 0, ""); PR_Init_Cvars (); - PR_Init (); pr.edicts = &edicts; pr.num_edicts = &num_edicts; @@ -246,6 +245,8 @@ init_qf (void) pr.allocate_progs_mem = allocate_progs_mem; pr.free_progs_mem = free_progs_mem; + PR_Init (&pr); + func_tab = Hash_NewTable (1021, 0, 0, 0); Hash_SetHashCompare (func_tab, func_hash, func_compare); } diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 78c657d05..cabef6ab7 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -154,7 +154,7 @@ init_qf (void) pr.pr_trace = options.trace; PR_Init_Cvars (); - PR_Init (); + PR_Init (&pr); RUA_Init (&pr, 0); PR_Cmds_Init(&pr); BI_Init (&pr); diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index 035e4f73b..1ab7c027e 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -117,7 +117,7 @@ init_qf (void) pr.no_exec_limit = 1; PR_Init_Cvars (); - PR_Init (); + PR_Init (&pr); RUA_Init (&pr, 0); PR_Cmds_Init(&pr); BI_Init (&pr); diff --git a/tools/qwaq/qwaq.c b/tools/qwaq/qwaq.c index 24a14d217..b446a02dd 100644 --- a/tools/qwaq/qwaq.c +++ b/tools/qwaq/qwaq.c @@ -128,7 +128,7 @@ init_qf (void) pr.no_exec_limit = 1; PR_Init_Cvars (); - PR_Init (); + PR_Init (&pr); RUA_Init (&pr, 0); PR_Cmds_Init (&pr); BI_Init (&pr); From b173c35eb455676a59826b700511c90352479e2e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 18:56:30 +0900 Subject: [PATCH 0370/3664] Rework progs debug to use the type encodings It's only a start: the output is, if anything, slightly worse than before, but it does have the basics going. --- include/QF/progs.h | 43 +++ libs/gamecode/pr_debug.c | 664 ++++++++++++++++++++++++++++----------- 2 files changed, 519 insertions(+), 188 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index a07f70534..78b3036c7 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1492,6 +1492,49 @@ void *PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size); /// \addtogroup debug ///@{ +struct qfot_type_s; + +/** Callback for viewing progs data + + \param type C pointer to the type definition by which to view the + data. + \param value C pointer to the data to be viewed. + \param data User data. +*/ +typedef void (*type_view_func) (struct qfot_type_s *type, pr_type_t *value, + void *data); + +/** Set of callbacks for viewing progs data + + Each possible type has its own callback. Basic types (those for which the + VM has specific instructions) all have separate callbacks, one for each + type, but the callbacks for compound types are expected to some + interpretation on their own, such as displaying a simple identifier or + the entire contents of the data. +*/ +typedef struct type_view_s { + type_view_func void_view; + type_view_func string_view; + type_view_func float_view; + type_view_func vector_view; + type_view_func entity_view; + type_view_func field_view; + type_view_func func_view; + type_view_func pointer_view; + type_view_func quat_view; + type_view_func integer_view; + type_view_func uinteger_view; + type_view_func short_view; + type_view_func double_view; + + type_view_func struct_view; + type_view_func union_view; + type_view_func enum_view; + type_view_func array_view; + type_view_func class_view; + type_view_func alias_view; +} type_view_t; + void PR_Debug_Init (progs_t *pr); void PR_Debug_Init_Cvars (void); int PR_LoadDebug (progs_t *pr); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 8f05793b9..2a41ec61c 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -71,12 +71,81 @@ typedef struct { progs_t *pr; } file_t; +typedef struct { + dstring_t *string; +} pr_debug_resources_t; + +typedef struct { + progs_t *pr; + dstring_t *dstr; +} pr_debug_data_t; + cvar_t *pr_debug; cvar_t *pr_source_path; static hashtab_t *file_hash; static char *source_path_string; static char **source_paths; +static void pr_debug_void_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_string_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_float_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_field_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_func_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_integer_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_uinteger_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_short_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_double_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_struct_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_union_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_enum_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_array_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_class_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_alias_view (qfot_type_t *type, pr_type_t *value, + void *_data); + +static type_view_t raw_type_view = { + pr_debug_void_view, + pr_debug_string_view, + pr_debug_float_view, + pr_debug_vector_view, + pr_debug_entity_view, + pr_debug_field_view, + pr_debug_func_view, + pr_debug_pointer_view, + pr_debug_quat_view, + pr_debug_integer_view, + pr_debug_uinteger_view, + pr_debug_short_view, + pr_debug_double_view, + pr_debug_struct_view, + pr_debug_union_view, + pr_debug_enum_view, + pr_debug_array_view, + pr_debug_class_view, + pr_debug_alias_view, +}; static const char * file_get_key (const void *_f, void *unused) @@ -199,10 +268,28 @@ error: return d; } +static void +pr_debug_clear (progs_t *pr, void *data) +{ + __auto_type res = (pr_debug_resources_t *) data; + + if (res->string) { + dstring_clearstr (res->string); + } else { + res->string = dstring_newstr (); + } +} + void PR_Debug_Init (progs_t *pr) { - file_hash = Hash_NewTable (1024, file_get_key, file_free, 0); + pr_debug_resources_t *res = calloc (1, sizeof (*res)); + res->string = 0; + + PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); + if (!file_hash) { + file_hash = Hash_NewTable (1024, file_get_key, file_free, 0); + } } void @@ -591,181 +678,386 @@ PR_DumpState (progs_t *pr) #define ISDENORM(x) ((x) && !((x) & 0x7f800000)) static const char * -value_string (progs_t *pr, etype_t type, pr_type_t *val) +value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) { - static dstring_t *line; - pr_def_t *def; - pr_int_t ofs; - edict_t *edict; - dfunction_t *f; - const char *str; - - if (!line) - line = dstring_new (); - - type &= ~DEF_SAVEGLOBAL; - - switch (type) { - case ev_string: - if (!PR_StringValid (pr, val->string_var)) - return "*** invalid ***"; - str = PR_GetString (pr, val->string_var); - dstring_copystr (line, "\""); - while (*str) { - const char *s; - - for (s = str; *s && !strchr ("\"\n\t", *s); s++) - ; - if (s != str) - dstring_appendsubstr (line, str, s - str); - if (*s) { - switch (*s) { - case '\"': - dstring_appendstr (line, "\\\""); - break; - case '\n': - dstring_appendstr (line, "\\n"); - break; - case '\t': - dstring_appendstr (line, "\\t"); - break; - default: - dasprintf (line, "\\x%02x", *s & 0xff); - } - s++; - } - str = s; - } - dstring_appendstr (line, "\""); - break; - case ev_entity: - edict = PROG_TO_EDICT (pr, val->entity_var); - dsprintf (line, "entity %d", NUM_FOR_BAD_EDICT (pr, edict)); - break; - case ev_func: - if (val->func_var < 0 || val->func_var >= pr->progs->numfunctions) - dsprintf (line, "INVALID:%d", val->func_var); - else if (!val->func_var) - return "NULL"; - else { - f = pr->pr_functions + val->func_var; - dsprintf (line, "%s()", PR_GetString (pr, f->s_name)); + switch (type->meta) { + case ty_basic: + switch (type->t.type) { + case ev_void: + raw_type_view.void_view (type, value, data); + break; + case ev_string: + raw_type_view.string_view (type, value, data); + break; + case ev_float: + raw_type_view.float_view (type, value, data); + break; + case ev_vector: + raw_type_view.vector_view (type, value, data); + break; + case ev_entity: + raw_type_view.entity_view (type, value, data); + break; + case ev_field: + raw_type_view.field_view (type, value, data); + break; + case ev_func: + raw_type_view.func_view (type, value, data); + break; + case ev_pointer: + raw_type_view.pointer_view (type, value, data); + break; + case ev_quat: + raw_type_view.quat_view (type, value, data); + break; + case ev_integer: + raw_type_view.integer_view (type, value, data); + break; + case ev_uinteger: + raw_type_view.uinteger_view (type, value, data); + break; + case ev_short: + raw_type_view.short_view (type, value, data); + break; + case ev_double: + raw_type_view.double_view (type, value, data); + break; + case ev_invalid: + case ev_type_count: + dstring_appendstr (data->dstr, ""); } break; - case ev_field: - def = PR_FieldAtOfs (pr, val->integer_var); - if (def) - dsprintf (line, ".%s", PR_GetString (pr, def->name)); - else - dsprintf (line, ".<$%04x>", val->integer_var); + case ty_struct: + raw_type_view.struct_view (type, value, data); break; - case ev_void: - return "void"; - case ev_float: - if (ISDENORM (val->integer_var) && val->uinteger_var != 0x80000000) - dsprintf (line, "<%08x>", val->integer_var); - else - dsprintf (line, "%g", val->float_var); + case ty_union: + raw_type_view.union_view (type, value, data); break; - case ev_vector: - dsprintf (line, "'%g %g %g'", - val->vector_var[0], val->vector_var[1], - val->vector_var[2]); + case ty_enum: + raw_type_view.enum_view (type, value, data); break; - case ev_pointer: - def = 0; - ofs = val->integer_var; - if (pr_debug->int_val && pr->debug) - def = PR_Get_Local_Def (pr, ofs); - if (!def) - def = PR_GlobalAtOfs (pr, ofs); - if (def && def->name) - dsprintf (line, "&%s", PR_GetString (pr, def->name)); - else - dsprintf (line, "[$%x]", ofs); + case ty_array: + raw_type_view.array_view (type, value, data); break; - case ev_quat: - dsprintf (line, "'%g %g %g %g'", - val->vector_var[0], val->vector_var[1], - val->vector_var[2], val->vector_var[3]); + case ty_class: + raw_type_view.class_view (type, value, data); break; - case ev_integer: - dsprintf (line, "%d", val->integer_var); - break; - case ev_uinteger: - dsprintf (line, "$%08x", val->uinteger_var); - break; - case ev_double: - dsprintf (line, "%g", *(double *)val); - break; - case ev_short: - case ev_invalid: - case ev_type_count: - //dsprintf (line, "bad type %i", type); - dsprintf (line, "<%x %x %x %x>", - val[0].integer_var, val[1].integer_var, - val[2].integer_var, val[3].integer_var); + case ty_alias: + raw_type_view.alias_view (type, value, data); break; } - - return line->str; + return data->dstr->str; } static pr_def_t * -def_string (progs_t *pr, pr_int_t ofs, dstring_t *dstr) +pr_debug_find_def (progs_t *pr, pr_int_t ofs) { pr_def_t *def = 0; - const char *name; if (pr_debug->int_val && pr->debug) def = PR_Get_Local_Def (pr, ofs); if (!def) def = PR_GlobalAtOfs (pr, ofs); - if (!def || !*(name = PR_GetString (pr, def->name))) - dsprintf (dstr, "[$%x]", ofs); - else - dsprintf (dstr, "%s", name); return def; } static const char * -global_string (progs_t *pr, pointer_t ofs, etype_t type, int contents) +global_string (pr_debug_data_t *data, pointer_t ofs, etype_t etype, + int contents) { - static dstring_t *line = NULL; + progs_t *pr = data->pr; + dstring_t *dstr = data->dstr; pr_def_t *def = NULL; - const char *s; + qfot_type_t dummy_type = { }; + qfot_type_t *type; + const char *name = 0; - if (!line) - line = dstring_newstr(); + dstring_clearstr (dstr); - if (type == ev_short) { - dsprintf (line, "%04x", (short) ofs); - return line->str; + if (etype == ev_short) { + dsprintf (dstr, "%04x", (short) ofs); + return dstr->str; } - def = def_string (pr, ofs, line); + if (ofs > pr->globals_size) { + dsprintf (dstr, "%08x out of bounds", ofs); + return dstr->str; + } - if (contents && (def || type != ev_void)) { - const char *oi = ""; - if (def) { - if (type == ev_void) - type = def->type; - if (type != (etype_t) (def->type & ~DEF_SAVEGLOBAL)) - oi = "?"; - } - - if (ofs > pr->globals_size) - s = "Out of bounds"; - else - s = value_string (pr, type, &pr->pr_globals[ofs]); - - if (strequal(line->str, "IMMEDIATE") || strequal(line->str, ".imm")) { - dsprintf (line, "%s", s); + def = pr_debug_find_def (pr, ofs); + if (!def || !PR_StringValid (pr, def->name) + || !*(name = PR_GetString (pr, def->name))) { + dsprintf (dstr, "[$%x]", ofs); + } + if (name) { + if (strequal (name, "IMMEDIATE") || strequal (name, ".imm")) { + contents = 1; } else { - dasprintf (line, "%s(%s)", oi, s); + dsprintf (dstr, "%s", name); } } - return line->str; + if (contents) { + if (name) { + dstring_appendstr (dstr, "("); + } + if (def) { + if (!def->type_encoding) { + dummy_type.t.type = def->type; + type = &dummy_type; + } else { + type = &G_STRUCT (pr, qfot_type_t, def->type_encoding); + } + } else { + dummy_type.t.type = etype; + type = &dummy_type; + } + value_string (data, type, pr->pr_globals + ofs); + if (name) { + dstring_appendstr (dstr, ")"); + } + } + return dstr->str; +} + +static void +pr_debug_void_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dasprintf (data->dstr, ""); +} + +static void +pr_debug_string_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + string_t string = value->string_var; + if (PR_StringValid (data->pr, string)) { + const char *str = PR_GetString (data->pr, string); + + dstring_appendstr (dstr, "\""); + while (*str) { + const char *s; + + for (s = str; *s && !strchr ("\"\n\t", *s); s++) { + } + if (s != str) { + dstring_appendsubstr (dstr, str, s - str); + } + if (*s) { + switch (*s) { + case '\"': + dstring_appendstr (dstr, "\\\""); + break; + case '\n': + dstring_appendstr (dstr, "\\n"); + break; + case '\t': + dstring_appendstr (dstr, "\\t"); + break; + default: + dasprintf (dstr, "\\x%02x", *s & 0xff); + } + s++; + } + str = s; + } + dstring_appendstr (dstr, "\""); + } else { + dstring_appendstr (dstr, "*** invalid string offset ***"); + } +} + +static void +pr_debug_float_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + if (data->pr->progs->version == PROG_ID_VERSION + && ISDENORM (value->integer_var) + && value->uinteger_var != 0x80000000) { + dasprintf (dstr, "<%08x>", value->integer_var); + } else { + dasprintf (dstr, "%g", value->float_var); + } +} + +static void +pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "'%g %g %g'", + value->vector_var[0], value->vector_var[1], + value->vector_var[2]); +} + +static void +pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + progs_t *pr = data->pr; + dstring_t *dstr = data->dstr; + edict_t *edict = PROG_TO_EDICT (pr, value->entity_var); + + dasprintf (dstr, "entity %d", NUM_FOR_BAD_EDICT (pr, edict)); +} + +static void +pr_debug_field_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + progs_t *pr = data->pr; + dstring_t *dstr = data->dstr; + pr_def_t *def = PR_FieldAtOfs (pr, value->integer_var); + + if (def) { + dasprintf (dstr, ".%s", PR_GetString (pr, def->name)); + } else { + dasprintf (dstr, ".<$%04x>", value->integer_var); + } +} + +static void +pr_debug_func_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + progs_t *pr = data->pr; + dstring_t *dstr = data->dstr; + + if (value->func_var < 0 || value->func_var >= pr->progs->numfunctions) { + dasprintf (dstr, "INVALID:%d", value->func_var); + } else if (!value->func_var) { + dstring_appendstr (dstr, "NULL"); + } else { + dfunction_t *f = pr->pr_functions + value->func_var; + dasprintf (dstr, "%s()", PR_GetString (pr, f->s_name)); + } +} + +static void +pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + progs_t *pr = data->pr; + dstring_t *dstr = data->dstr; + pointer_t ofs = value->integer_var; + pr_def_t *def; + + if (pr_debug->int_val && pr->debug) { + def = PR_Get_Local_Def (pr, ofs); + } + if (!def) { + def = PR_GlobalAtOfs (pr, ofs); + } + if (def && def->name) { + dasprintf (dstr, "&%s", PR_GetString (pr, def->name)); + } else { + dasprintf (dstr, "[$%x]", ofs); + } +} + +static void +pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "'%g %g %g %g'", + value->vector_var[0], value->vector_var[1], + value->vector_var[2], value->vector_var[3]); +} + +static void +pr_debug_integer_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "%d", value->integer_var); +} + +static void +pr_debug_uinteger_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "$%08x", value->uinteger_var); +} + +static void +pr_debug_short_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "%d", (short)value->integer_var); +} + +static void +pr_debug_double_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "%g", *(double *)value); +} + +static void +pr_debug_struct_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dstring_appendstr (dstr, ""); +} + +static void +pr_debug_union_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dstring_appendstr (dstr, ""); +} + +static void +pr_debug_enum_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dstring_appendstr (dstr, ""); +} + +static void +pr_debug_array_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dstring_appendstr (dstr, ""); +} + +static void +pr_debug_class_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dstring_appendstr (dstr, ""); +} + +static void +pr_debug_alias_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dstring_appendstr (dstr, ""); } VISIBLE void @@ -780,8 +1072,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) if (pr->wp_conditional) Sys_Printf (" if new val == %d\n", pr->wp_val.integer_var); - } else { - Sys_Printf (" none active\n"); + } else { Sys_Printf (" none active\n"); } return; } @@ -803,6 +1094,8 @@ VISIBLE void PR_Debug_Print (progs_t *pr, const char *expr) { pr_def_t print; + dstring_t *dstr = dstring_newstr(); + pr_debug_data_t data = {pr, dstr}; if (!expr) { Sys_Printf ("print \n"); @@ -811,9 +1104,10 @@ PR_Debug_Print (progs_t *pr, const char *expr) print = parse_expression (pr, expr, 0); if (print.type != ev_invalid) { - const char *s = global_string (pr, print.ofs, print.type, 1); + const char *s = global_string (&data, print.ofs, print.type, 1); Sys_Printf ("[%d] = %s\n", print.ofs, s); } + dstring_delete (dstr); } VISIBLE void @@ -824,15 +1118,21 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) const char *fmt; opcode_t *op; static dstring_t *line; + static dstring_t *dstr; dfunction_t *call_func = 0; pr_def_t *parm_def = 0; pr_auxfunction_t *aux_func = 0; + pr_debug_data_t data; - if (!line) + if (!line) { line = dstring_new (); - + dstr = dstring_new (); + } dstring_clearstr (line); + data.pr = pr; + data.dstr = dstr; + if (pr_debug->int_val > 1) dump_code = 1; @@ -915,10 +1215,12 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) aux_func = get_aux_function (pr); if (aux_func) optype = get_etype (pr, aux_func->return_type); - str = global_string (pr, opval, optype, contents & 1); + str = global_string (&data, opval, optype, + contents & 1); break; case 'F': - str = global_string (pr, opval, optype, contents & 1); + str = global_string (&data, opval, optype, + contents & 1); if (G_FUNCTION (pr, opval) >= 0 && G_FUNCTION (pr, opval) < pr->progs->numfunctions) @@ -929,16 +1231,19 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) optype = ev_void; if (parm_def) optype = parm_def->type; - str = global_string (pr, opval, optype, contents & 1); + str = global_string (&data, opval, optype, + contents & 1); break; case 'V': - str = global_string (pr, opval, ev_void, contents & 1); + str = global_string (&data, opval, ev_void, + contents & 1); break; case 'G': - str = global_string (pr, opval, optype, contents & 1); + str = global_string (&data, opval, optype, + contents & 1); break; case 'g': - str = global_string (pr, opval, optype, 0); + str = global_string (&data, opval, optype, 0); break; case 's': str = va ("%d", (short) opval); @@ -961,7 +1266,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) str = "bad entity.field"; break; } - str = global_string (pr, opval, optype, + str = global_string (&data, opval, optype, contents & 1); str = va ("$%x $%x %s", s->a, s->b, str); } @@ -1072,11 +1377,15 @@ PR_Profile (progs_t * pr) VISIBLE void ED_Print (progs_t *pr, edict_t *ed) { - int type, l; + int l; pr_uint_t i; const char *name; pr_def_t *d; pr_type_t *v; + qfot_type_t dummy_type = { }; + qfot_type_t *type; + dstring_t *dstr = dstring_newstr(); + pr_debug_data_t data = {pr, dstr}; if (ed->free) { Sys_Printf ("FREE\n"); @@ -1088,6 +1397,12 @@ ED_Print (progs_t *pr, edict_t *ed) d = &pr->pr_fielddefs[i]; if (!d->name) // null field def (probably 1st) continue; + if (!d->type_encoding) { + dummy_type.t.type = d->type; + type = &dummy_type; + } else { + type = &G_STRUCT (pr, qfot_type_t, d->type_encoding); + } name = PR_GetString (pr, d->name); if (name[strlen (name) - 2] == '_' && strchr ("xyz", name[strlen (name) -1])) @@ -1095,41 +1410,14 @@ ED_Print (progs_t *pr, edict_t *ed) v = ed->v + d->ofs; - // if the value is still all 0, skip the field - type = d->type & ~DEF_SAVEGLOBAL; - - switch (type) { - case ev_entity: - case ev_integer: - case ev_uinteger: - case ev_pointer: - case ev_func: - case ev_field: - if (!v->integer_var) - continue; - break; - case ev_string: - if (PR_StringValid (pr, v->string_var)) - if (!PR_GetString (pr, v->string_var)[0]) - continue; - break; - case ev_float: - if (!v->float_var) - continue; - break; - case ev_vector: - if (!v[0].float_var && !v[1].float_var && !v[2].float_var) - continue; - break; - case ev_void: - break; - default: - PR_Error (pr, "ED_Print: Unhandled type %d", type); - } - l = 15 - strlen (name); if (l < 1) l = 1; - Sys_Printf ("%s%*s%s\n", name, l, "", value_string (pr, d->type, v)); + + dstring_clearstr (dstr); + value_string (&data, type, v); + Sys_Printf ("%s%*s%s\n", name, l, "", dstr->str); } + + dstring_delete (dstr); } From d0dc0e15fbb19b90e7bdfe4b873d589e2b1476bc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 19:02:16 +0900 Subject: [PATCH 0371/3664] Handle alias types in debug prints --- libs/gamecode/pr_debug.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 2a41ec61c..06ed76a5b 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1055,9 +1055,10 @@ static void pr_debug_alias_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; - dstring_t *dstr = data->dstr; + progs_t *pr = data->pr; - dstring_appendstr (dstr, ""); + type = &G_STRUCT (pr, qfot_type_t, type->t.alias.aux_type); + value_string (data, type, value); } VISIBLE void From c3c55f0bccc0dff92fc1815598ae0a92c1d7a9da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 19:05:43 +0900 Subject: [PATCH 0372/3664] Fix some source formatting --- libs/util/sys.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/util/sys.c b/libs/util/sys.c index 62ddfa35b..811cac886 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -126,18 +126,18 @@ qboolean stdin_ready; /* The translation table between the graphical font and plain ASCII --KB */ VISIBLE const char sys_char_map[256] = { - '\0', '#', '#', '#', '#', '.', '#', '#', - '#', 9, 10, '#', ' ', 13, '.', '.', + 0, '#', '#', '#', '#', '.', '#', '#', + '#', 9, 10, '#', ' ', 13, '.', '.', '[', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '<', '=', '>', - ' ', '!', '"', '#', '$', '%', '&', '\'', + ' ', '!', '"', '#', '$', '%', '&','\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + 'X', 'Y', 'Z', '[','\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', @@ -147,14 +147,14 @@ VISIBLE const char sys_char_map[256] = { '#', '#', ' ', '#', ' ', '>', '.', '.', '[', ']', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '<', '=', '>', - ' ', '!', '"', '#', '$', '%', '&', '\'', + ' ', '!', '"', '#', '$', '%', '&','\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + 'X', 'Y', 'Z', '[','\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', From c9fca9c98a00e9002f9a9308f2a299e645a19e44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 20:48:12 +0900 Subject: [PATCH 0373/3664] Fix another inside-out type utility function --- tools/qfcc/source/type.c | 67 ++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 43 deletions(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 04c8d7442..a22ca4f0a 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -947,52 +947,33 @@ type_assignable (const type_t *dst, const type_t *src) int type_size (const type_t *type) { - switch (type->type) { - case ev_void: - case ev_string: - case ev_float: - case ev_vector: - case ev_entity: - case ev_field: - case ev_func: - case ev_pointer: - case ev_quat: - case ev_integer: - case ev_uinteger: - case ev_short: - case ev_double: - case ev_type_count: + switch (type->meta) { + case ty_basic: return pr_type_size[type->type]; - case ev_invalid: - switch (type->meta) { - case ty_enum: - if (!type->t.symtab) - return 0; - return type_size (&type_integer); - case ty_struct: - case ty_union: - if (!type->t.symtab) - return 0; - return type->t.symtab->size; - case ty_class: - { - class_t *class = type->t.class; - int size; - if (!class->ivars) - return 0; - size = class->ivars->size; - if (class->super_class) - size += type_size (class->super_class->type); - return size; - } - case ty_array: - return type->t.array.size * type_size (type->t.array.type); - case ty_alias: - return type_size (type->t.alias.type); - case ty_basic: + case ty_struct: + case ty_union: + if (!type->t.symtab) + return 0; + return type->t.symtab->size; + case ty_enum: + if (!type->t.symtab) + return 0; + return type_size (&type_integer); + case ty_array: + return type->t.array.size * type_size (type->t.array.type); + case ty_class: + { + class_t *class = type->t.class; + int size; + if (!class->ivars) return 0; + size = class->ivars->size; + if (class->super_class) + size += type_size (class->super_class->type); + return size; } - break; + case ty_alias: + return type_size (type->t.alias.type); } return 0; } From 2a392080693e8bfca2fac8a5feb60eba637deb67 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 20:48:43 +0900 Subject: [PATCH 0374/3664] Set void alignment to 1 qcc allowed void variables. --- tools/qfcc/source/type.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index a22ca4f0a..a583a943c 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -62,7 +62,7 @@ // simple types. function types are dynamically allocated type_t type_invalid = { ev_invalid, "invalid" }; -type_t type_void = { ev_void, "void" }; +type_t type_void = { ev_void, "void", 1 }; type_t type_string = { ev_string, "string", 1 }; type_t type_float = { ev_float, "float", 1 }; type_t type_vector = { ev_vector, "vector", 1 }; From ea3af84baaab88050f740796445daa4d5bab3f79 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 20:49:56 +0900 Subject: [PATCH 0375/3664] Fix ICE when const-folding doubles I really need to rework that system. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/constfold.c | 6 +++++- tools/qfcc/source/expr.c | 8 ++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 36d785be0..bfeb1b83f 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -612,6 +612,7 @@ void dump_dot_expr (void *e, const char *filename); void convert_int (expr_t *e); void convert_short (expr_t *e); void convert_short_int (expr_t *e); +void convert_double (expr_t *e); void convert_nil (expr_t *e, struct type_s *t); expr_t *test_expr (expr_t *e); diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 3cba7f467..df8ea6ae0 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -148,8 +148,12 @@ convert_to_float (expr_t *e) case ev_short: convert_short (e); return e; + case ev_double: + convert_double (e); + return e; default: - internal_error (e, 0); + internal_error (e, "bad conversion to float: %d", + e->e.value->lltype); } break; case ex_symbol: diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index ab9672813..e8505fac2 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1546,6 +1546,14 @@ convert_short_int (expr_t *e) e->e.value = new_integer_val (integer_val); } +void +convert_double (expr_t *e) +{ + float float_val = expr_double (e); + e->type = ex_value; + e->e.value = new_float_val (float_val); +} + void convert_nil (expr_t *e, type_t *t) { From 7efefceee2956cf2c725c2136d7b53f25f342ffd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 22:21:25 +0900 Subject: [PATCH 0376/3664] Fix a comment --- include/QF/pr_comp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 9df0416d3..40ac1aa00 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -417,7 +417,7 @@ typedef struct dstatement_s { } GCC_STRUCT dstatement_t; typedef struct ddef_s { - pr_ushort_t type; // if DEF_SAVEGLOBGAL bit is set + pr_ushort_t type; // if DEF_SAVEGLOBAL bit is set // the variable needs to be saved in savegames pr_ushort_t ofs; string_t s_name; From 23573953a76626af7e6dba4e2a1b936b8bcbc4c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 22:25:08 +0900 Subject: [PATCH 0377/3664] Change pr_type_size to pr_ushort_t --- include/QF/pr_comp.h | 2 +- libs/gamecode/pr_opcode.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 40ac1aa00..0430d35fe 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -50,7 +50,7 @@ typedef enum { ev_type_count // not a type, gives number of types } etype_t; -extern int pr_type_size[ev_type_count]; +extern pr_ushort_t pr_type_size[ev_type_count]; extern const char *pr_type_name[ev_type_count]; #define OFS_NULL 0 diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 26ce130cb..3d2bc0c4d 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -48,7 +48,7 @@ hashtab_t *opcode_table; -VISIBLE int pr_type_size[ev_type_count] = { +VISIBLE pr_ushort_t pr_type_size[ev_type_count] = { 1, // ev_void 1, // ev_string 1, // ev_float From e6f243323e9fbbe8442d6dfd47b2d935fb380875 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 22:26:09 +0900 Subject: [PATCH 0378/3664] Fix type of class in qfo type encodings --- include/QF/pr_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index b2ea05060..39215840f 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -109,7 +109,7 @@ typedef struct qfot_type_s { qfot_func_t func; ///< ty_basic, ev_func qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum qfot_array_t array; ///< ty_array - pointer_t class; ///< ty_class + string_t class; ///< ty_class qfot_alias_t alias; ///< ty_alias } t; } qfot_type_t; From 14cde99d6ebe83912191827556b0c228c1826542 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 22:27:07 +0900 Subject: [PATCH 0379/3664] White space of the worst sort. --- tools/qfcc/include/expr.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index bfeb1b83f..e8fdccb0c 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -191,12 +191,12 @@ typedef struct ex_value_s { typedef struct expr_s { struct expr_s *next; ///< the next expression in a block expression - expr_type type; ///< the type of the result of this expression - int line; ///< source line that generated this expression - string_t file; ///< source file that generated this expression + expr_type type; ///< the type of the result of this expression + int line; ///< source line that generated this expression + string_t file; ///< source file that generated this expression int printid; ///< avoid duplicate output when printing - unsigned paren:1; ///< the expression is enclosed in () - unsigned rvalue:1; ///< the expression is on the right side of = + unsigned paren:1; ///< the expression is enclosed in () + unsigned rvalue:1; ///< the expression is on the right side of = union { ex_label_t label; ///< label expression ex_labelref_t labelref; ///< label reference expression (&) From e23aa40994aff978d0f78e96e7e919ab40748365 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 22:28:54 +0900 Subject: [PATCH 0380/3664] Implicitly cast unadorned floating point constants Floating point constants without f or d adornments will automatically cast, without warnings, to the type appropriate to the rest of the expression. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/def.c | 3 ++- tools/qfcc/source/expr_assign.c | 8 +++++--- tools/qfcc/source/expr_binary.c | 9 +++++++++ tools/qfcc/source/qc-lex.l | 1 + 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index e8fdccb0c..0a030e75a 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -197,6 +197,7 @@ typedef struct expr_s { int printid; ///< avoid duplicate output when printing unsigned paren:1; ///< the expression is enclosed in () unsigned rvalue:1; ///< the expression is on the right side of = + unsigned implicit:1; ///< don't warn for implicit casts union { ex_label_t label; ///< label expression ex_labelref_t labelref; ///< label reference expression (&) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 7bef8790b..ce59166a5 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -609,7 +609,8 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, reloc_def_field (init->e.value->v.pointer.def, sym->s.def); } else { ex_value_t *v = init->e.value; - if (is_double (init_type) + if (!init->implicit + && is_double (init_type) && (is_integral (sym->type) || is_float (sym->type))) { warning (init, "assigning double to %s in initializer " "(use a cast)", sym->type->name); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 600c6140a..046f1c07b 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -151,9 +151,11 @@ check_types_compatible (expr_t *dst, expr_t *src) if (type_assignable (dst_type, src_type)) { if (is_scalar (dst_type) && is_scalar (src_type)) { - if (is_double (src_type)) { - warning (dst, "assignment of double to %s (use a cast)\n", - dst_type->name); + if (!src->implicit) { + if (is_double (src_type)) { + warning (dst, "assignment of double to %s (use a cast)\n", + dst_type->name); + } } // the types are different but cast-compatible expr_t *new = cast_expr (dst_type, src); diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 2e31116f3..ed8dcc85d 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -954,6 +954,15 @@ binary_expr (int op, expr_t *e1, expr_t *e2) et1 = low_level_type (t1); et2 = low_level_type (t2); + if (is_constant (e1) && is_double (t1) && e1->implicit && is_float (t2)) { + t1 = &type_float; + convert_double (e1); + } + if (is_constant (e2) && is_double (t2) && e2->implicit && is_float (t1)) { + t2 = &type_float; + convert_double (e2); + } + if (et1 >= ev_type_count || !binary_expr_types[et1]) return invalid_binary_expr(op, e1, e2); if (et2 >= ev_type_count || !binary_expr_types[et1][et2]) diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 58b661220..353191593 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -143,6 +143,7 @@ STRING \"(\\.|[^"\\])*\" if (options.traditional < 1) { double d = strtod (yytext, 0); qc_yylval.expr = new_double_expr (d); + qc_yylval.expr->implicit = 1; } else { float f = strtof (yytext, 0); qc_yylval.expr = new_float_expr (f); From 607fd2e30ef6e2281c83ec638934c9a56de923af Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 22:51:00 +0900 Subject: [PATCH 0381/3664] Allow constant initialized globals in advanced code Use -C const-initializers to enable (or no-const-initializers to disable in traditional/extended code). --- tools/qfcc/doc/man/qfcc.1 | 23 ++++++++++++++++------- tools/qfcc/include/options.h | 1 + tools/qfcc/source/def.c | 2 +- tools/qfcc/source/expr.c | 13 +++++++++++++ tools/qfcc/source/options.c | 8 +++++++- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index a5e2794e0..b4fbd2685 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -85,7 +85,8 @@ No compilation or linking is done. .TP .B \-\-extended -Allow extended keywords in traditional mode. +Allow extended keywords in traditional mode. Otherwise, it has \fIall\fP +the implications of \fB\-\-traditional\fP. .TP .B \-F, \-\-files @@ -198,9 +199,9 @@ Look for \*[progs.src] in \fBDIR\fP instead of the current directory. .TP .B \-\-traditional Use traditional QuakeC syntax, semantics and \*(lqbugs\*(rq. -Also implies the \fBv6only\fP, \fBno-short-circuit\fP and -\fBno-local-merging\fP code generation options (see -\fBCODE GENERATION OPTIONS\fP). +Also implies the \fBv6only\fP, \fBno-short-circuit\fP, +\fBconst-initializers\fP and \fBno-local-merging\fP code generation options +(see \fBCODE GENERATION OPTIONS\fP). This is the default when using \fBprogs.src\fP mode. .TP @@ -236,15 +237,23 @@ command line. Unsupported options are ignored. The following options are supported by \*[qfcc]'s \fB\-\-code\fP argument: +.TP +.B const-initializers +Treat initialized globals as constants. +This option is implied by \fB\-\-traditional\fP and \fB\-\-extended\fP, and is +turned off by \fB\-\-advanced\fP. + .TP .B cow Allow assignment to initialized globals. -In Quake-C and Ruamoko, a global that has been initialized to a value is not -a variable, but a named constant. +When initialized globals are treated as constants (traditional Quake-C, or +when const-initializers is activated), a global that has been initialized to a +value is not a variable, but a named constant. However, \fBqcc\fP never really enforced this. The \fBcow\fP option allows \*[qfcc] to gracefully cope with QuakeC source that assigns values to initialized globals in this manner. -(also known as \*(lqcopy on write\*(rq\(emnever mind the bovine connotations) +(also known as \*(lqcopy on write\*(rq\(emlo and behold the bovine +connotations) .TP .B cpp diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index cfcd350de..01345cff4 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -45,6 +45,7 @@ typedef struct { unsigned progsversion; // Progs version to generate code for qboolean vector_components; // add *_[xyz] symbols for vectors qboolean ifstring; // expand if (str) to if (str != "") + qboolean const_initializers; // initialied globals are constant } code_options_t; typedef struct { diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index ce59166a5..38d95ca23 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -626,7 +626,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, } } sym->s.def->initialized = 1; - if (options.traditional) { + if (options.code.const_initializers) { sym->s.def->constant = 1; sym->s.def->nosave = 1; } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index e8505fac2..5e370c4b0 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2626,6 +2626,19 @@ cast_expr (type_t *type, expr_t *e) ex_value_t *val = 0; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) { val = e->e.symbol->s.value; + } else if (e->type == ex_symbol + && e->e.symbol->sy_type == sy_var) { + // initialized global def treated as a constant + // from the tests above, the def is known to be constant + // and of one of the three storable scalar types + def_t *def = e->e.symbol->s.def; + if (is_float (def->type)) { + val = new_float_val (D_FLOAT (def)); + } else if (is_double (def->type)) { + val = new_double_val (D_DOUBLE (def)); + } else if (is_integral (def->type)) { + val = new_integer_val (D_INT (def)); + } } else if (e->type == ex_value) { val = e->e.value; } else if (e->type == ex_nil) { diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index c3f283e89..f9807de7b 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -194,12 +194,13 @@ code_usage (void) printf ("%s - QuakeForge Code Compiler\n", this_program); printf ("Code generation options\n"); printf ( +" [no-]const-initializers Treat initialized globals as constants.\n" " [no-]cow Allow assignment to initialized globals.\n" " [no-]cpp Preprocess all input files with cpp.\n" " [no-]crc Write progdefs.h crc to progs.dat.\n" " [no-]debug Generate debug information.\n" " [no-]fast-float Use float values directly in \"if\" statements.\n" -" help Display his text.\n" +" help Display this text.\n" " [no-]local-merging Merge the local variable blocks into one.\n" " [no-]optimize Perform various optimizations on the code.\n" " [no-]short-circuit Generate short circuit code for logical\n" @@ -392,16 +393,19 @@ DecodeArgs (int argc, char **argv) options.traditional = 1; options.advanced = false; options.code.progsversion = PROG_ID_VERSION; + options.code.const_initializers = true; break; case OPT_TRADITIONAL: options.traditional = 2; options.advanced = false; options.code.progsversion = PROG_ID_VERSION; + options.code.const_initializers = true; break; case OPT_ADVANCED: options.traditional = 0; options.advanced = true; options.code.progsversion = PROG_VERSION; + options.code.const_initializers = false; break; case OPT_BLOCK_DOT: if (optarg) { @@ -506,6 +510,8 @@ DecodeArgs (int argc, char **argv) options.code.progsversion = PROG_ID_VERSION; else options.code.progsversion = PROG_VERSION; + } else if (!(strcasecmp (temp, "const-initializers"))) { + options.code.const_initializers = flag; } temp = strtok (NULL, ","); } From 526c27cf03973ef60a3e5af706334b33ddd6be07 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 23:10:10 +0900 Subject: [PATCH 0382/3664] Handle implicit casts for double/float comparisons --- tools/qfcc/source/expr_binary.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index ed8dcc85d..aad78dea5 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -762,8 +762,13 @@ double_compare (int op, expr_t *e1, expr_t *e2) type_t *t2 = get_type (e2); expr_t *e; - if ((is_double (t1) && is_float (t2)) - || (is_float (t1) && is_double (t2))) { + if (is_constant (e1) && e1->implicit && is_double (t1) && is_float (t2)) { + t1 = &type_float; + convert_double (e1); + } + if (is_float (t1) && is_constant (e2) && e2->implicit && is_double (t2)) { + t2 = &type_float; + convert_double (e2); } if (is_double (t1)) { if (is_float (t2)) { @@ -772,7 +777,7 @@ double_compare (int op, expr_t *e1, expr_t *e2) warning (e2, "comparison between double and integer"); } e2 = cast_expr (&type_double, e2); - } else { + } else if (is_double (t2)) { if (is_float (t1)) { warning (e1, "comparison between float and double"); } else if (!is_constant (e1)) { From 05f6ddbb13f424fd8e54e6d835d3c7736945d859 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 23:10:56 +0900 Subject: [PATCH 0383/3664] Print promoted warnings as errors This makes it much easier to see why a compilation failed when only warnings are visible. --- tools/qfcc/source/diagnostic.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index d38c1eecb..5ba576212 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -99,16 +99,21 @@ static __attribute__((format(printf, 4, 0))) void __warning (expr_t *e, const char *file, int line, const char *fmt, va_list args) { + static int promoted = 0; dstring_t *message = dstring_new (); report_function (e); if (options.warnings.promote) { - options.warnings.promote = 0; // want to do this only once - fprintf (stderr, "%s: warnings treated as errors\n", "qfcc"); + if (!promoted) { + promoted = 1; // want to do this only once + fprintf (stderr, "%s: warnings treated as errors\n", "qfcc"); + } pr.error_count++; + format_message (message, "error", e, fmt, args); + } else { + format_message (message, "warning", e, fmt, args); } - format_message (message, "warning", e, fmt, args); if (options.verbosity > 1) { dasprintf (message, " (%s:%d)", file, line); } From 5374798ef90147afa4abc12e43dcc1bf8d826664 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 23:18:31 +0900 Subject: [PATCH 0384/3664] Fix order of operations for implicit casts --- tools/qfcc/source/expr_binary.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index aad78dea5..a251860bf 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -956,9 +956,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) } } - et1 = low_level_type (t1); - et2 = low_level_type (t2); - if (is_constant (e1) && is_double (t1) && e1->implicit && is_float (t2)) { t1 = &type_float; convert_double (e1); @@ -968,6 +965,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2) convert_double (e2); } + et1 = low_level_type (t1); + et2 = low_level_type (t2); + if (et1 >= ev_type_count || !binary_expr_types[et1]) return invalid_binary_expr(op, e1, e2); if (et2 >= ev_type_count || !binary_expr_types[et1][et2]) From dda045bf96fc82596a2942227bbb98b7eb77a805 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 23:29:58 +0900 Subject: [PATCH 0385/3664] Do lazy computation of def sizes from type encodings The size is calculated when needed and cached. --- include/QF/pr_comp.h | 3 +- libs/gamecode/pr_debug.c | 69 +++++++++++++++++++++++++++++++++++---- libs/gamecode/pr_load.c | 2 ++ libs/gamecode/pr_opcode.c | 1 + 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 0430d35fe..451d3a9ab 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -434,7 +434,8 @@ typedef struct pr_xdefs_s { } pr_xdefs_t; typedef struct pr_def_s { - pr_uint_t type; + pr_ushort_t type; + pr_ushort_t size; ///< may not be correct pointer_t ofs; string_t name; pointer_t type_encoding; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 06ed76a5b..9b0deece5 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -195,6 +195,57 @@ pr_debug_expression_error (script_t *script, const char *msg) Sys_Printf ("%s\n", msg); } +#define RUP(x,a) (((x) + ((a) - 1)) & ~((a) - 1)) +static pr_short_t +pr_debug_type_size (progs_t *pr, qfot_type_t *type) +{ + pr_short_t size; + qfot_type_t *aux_type; + switch (type->meta) { + case ty_basic: + return pr_type_size[type->t.type]; + case ty_struct: + case ty_union: + size = 0; + for (pr_int_t i = 0; i < type->t.strct.num_fields; i++) { + qfot_var_t *field = &type->t.strct.fields[i]; + aux_type = &G_STRUCT (pr, qfot_type_t, field->type); + size = max (size, + field->offset + pr_debug_type_size (pr, aux_type)); + } + return size; + case ty_enum: + return pr_type_size[ev_integer]; + case ty_array: + aux_type = &G_STRUCT (pr, qfot_type_t, type->t.array.type); + size = pr_debug_type_size (pr, aux_type); + return type->t.array.size * size; + case ty_class: + return 1; //FIXME or should it return sizeof class struct? + case ty_alias: + aux_type = &G_STRUCT (pr, qfot_type_t, type->t.alias.aux_type); + return pr_debug_type_size (pr, aux_type); + } + return 0; +} + +static qfot_type_t * +get_def_type (progs_t *pr, pr_def_t *def, qfot_type_t *type) +{ + if (!def->type_encoding) { + // no type encoding, so use basic type data to fill in and return + // the dummy encoding + memset (type, 0, sizeof (*type)); + type->t.type = def->type; + } else { + type = &G_STRUCT (pr, qfot_type_t, def->type_encoding); + if (!def->size) { + def->size = pr_debug_type_size (pr, type); + } + } + return type; +} + static pr_def_t parse_expression (progs_t *pr, const char *expr, int conditional) { @@ -1379,7 +1430,7 @@ VISIBLE void ED_Print (progs_t *pr, edict_t *ed) { int l; - pr_uint_t i; + pr_uint_t i, j; const char *name; pr_def_t *d; pr_type_t *v; @@ -1398,17 +1449,21 @@ ED_Print (progs_t *pr, edict_t *ed) d = &pr->pr_fielddefs[i]; if (!d->name) // null field def (probably 1st) continue; - if (!d->type_encoding) { - dummy_type.t.type = d->type; - type = &dummy_type; - } else { - type = &G_STRUCT (pr, qfot_type_t, d->type_encoding); - } + type = get_def_type (pr, d, &dummy_type); name = PR_GetString (pr, d->name); if (name[strlen (name) - 2] == '_' && strchr ("xyz", name[strlen (name) -1])) continue; // skip _x, _y, _z vars + for (j = 0; j < d->size; j++) { + if (E_INT (ed, d->ofs + j)) { + break; + } + } + if (j == d->size) { + continue; + } + v = ed->v + d->ofs; l = 15 - strlen (name); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index a7dced537..994e9b581 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -281,11 +281,13 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->pr_globaldefs = calloc (pr->progs->numglobaldefs, sizeof (pr_def_t)); for (i = 0; i < pr->progs->numglobaldefs; i++) { + pr_ushort_t safe_type = global_ddefs[i].type & ~DEF_SAVEGLOBAL; global_ddefs[i].type = LittleShort (global_ddefs[i].type); global_ddefs[i].ofs = LittleShort (global_ddefs[i].ofs); global_ddefs[i].s_name = LittleLong (global_ddefs[i].s_name); pr->pr_globaldefs[i].type = global_ddefs[i].type; + pr->pr_globaldefs[i].size = pr_type_size[safe_type]; pr->pr_globaldefs[i].ofs = global_ddefs[i].ofs; pr->pr_globaldefs[i].name = global_ddefs[i].s_name; Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]); diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 3d2bc0c4d..ab266c84c 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -62,6 +62,7 @@ VISIBLE pr_ushort_t pr_type_size[ev_type_count] = { 1, // ev_uinteger 0, // ev_short value in opcode 2, // ev_double + 0, // ev_invalid not a valid/simple type }; VISIBLE const char *pr_type_name[ev_type_count] = { From f387b9aa47dc411be0238f6aec95d6bb0ad64a4a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 23:41:12 +0900 Subject: [PATCH 0386/3664] Propagate implicit for negating double constants --- tools/qfcc/source/expr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 5e370c4b0..16db0b57d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1634,6 +1634,7 @@ unary_expr (int op, expr_t *e) vec3_t v; quat_t q; const char *s; + expr_t *new; convert_name (e); if (e->type == ex_error) @@ -1651,7 +1652,9 @@ unary_expr (int op, expr_t *e) case ev_pointer: internal_error (e, "type check failed!"); case ev_double: - return new_double_expr (-expr_double (e)); + new = new_double_expr (-expr_double (e)); + new->implicit = e->implicit; + return new; case ev_float: return new_float_expr (-expr_float (e)); case ev_vector: From 27ae5ccfcecaff4d4ead562248bfe28b0c05ac4c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Feb 2020 23:46:47 +0900 Subject: [PATCH 0387/3664] Fix ICE after incomplete type error Attempting to define a variable with an incomplete type is an error, and results in a default size 1 of allocated, but I forgot to set default alignment when implementing alignment. --- tools/qfcc/source/def.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 38d95ca23..ed5e69964 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -153,6 +153,7 @@ new_def (const char *name, type_t *type, defspace_t *space, if (!size) { error (0, "%s has incomplete type", name); size = 1; + alignment = 1; } if (alignment < 1) { print_type (type); From 11365024d2648972dd1b76252f6b1fd6e23c2752 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 00:07:48 +0900 Subject: [PATCH 0388/3664] Fix writing of frames files when not requested I forgot to check for the option for separate compilation. --- tools/qfcc/source/qfcc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 9e292d136..8a363a9cd 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -391,7 +391,9 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) exit (1); } } - write_frame_macros (va ("%s.frame", file_basename (file))); + if (options.frames_files) { + write_frame_macros (va ("%s.frame", file_basename (file))); + } if (!err) { qfo_t *qfo; @@ -750,8 +752,10 @@ progs_src_compile (void) } else { if (compile_file (qc_filename->str)) return 1; - write_frame_macros (va ("%s.frame", - file_basename (qc_filename->str))); + if (options.frames_files) { + write_frame_macros (va ("%s.frame", + file_basename (qc_filename->str))); + } } if (!Script_TokenAvailable (script, 0)) break; From 0bf7ec07b719bcbfb0402a292202ead3d677501b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 00:22:13 +0900 Subject: [PATCH 0389/3664] Make debug output verbosity 2 and internal diagnostic sources level 1. --- tools/qfcc/source/diagnostic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 5ba576212..84892687f 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -114,7 +114,7 @@ __warning (expr_t *e, const char *file, int line, format_message (message, "warning", e, fmt, args); } - if (options.verbosity > 1) { + if (options.verbosity) { dasprintf (message, " (%s:%d)", file, line); } if (warning_hook) { @@ -130,7 +130,7 @@ _debug (expr_t *e, const char *file, int line, const char *fmt, ...) { va_list args; - if (options.verbosity < 1) + if (options.verbosity < 2) return; report_function (e); @@ -208,7 +208,7 @@ _notice (expr_t *e, const char *file, int line, const char *fmt, ...) report_function (e); format_message (message, "notice", e, fmt, args); - if (options.verbosity > 1) { + if (options.verbosity) { dasprintf (message, " (%s:%d)", file, line); } if (notice_hook) { @@ -257,7 +257,7 @@ _error (expr_t *e, const char *file, int line, const char *fmt, ...) dstring_t *message = dstring_new (); format_message (message, "error", e, fmt, args); - if (options.verbosity > 1) { + if (options.verbosity) { dasprintf (message, " (%s:%d)", file, line); } if (error_hook) { From d6752c254c649cb30157c810ae2f553f7b04816a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 01:20:24 +0900 Subject: [PATCH 0390/3664] Move short-circuit boolean code to its own file --- tools/qfcc/source/Makefile.am | 3 +- tools/qfcc/source/expr.c | 229 ------------------------- tools/qfcc/source/expr_binary.c | 3 +- tools/qfcc/source/expr_bool.c | 295 ++++++++++++++++++++++++++++++++ 4 files changed, 299 insertions(+), 231 deletions(-) create mode 100644 tools/qfcc/source/expr_bool.c diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index 7feed1dca..d9ceb5ba2 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -41,7 +41,8 @@ bin_SCRIPTS= qfpreqcc common_src=\ class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \ diagnostic.c dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c emit.c \ - expr.c expr_assign.c expr_binary.c flow.c function.c grab.c idstuff.c \ + expr.c expr_assign.c expr_binary.c expr_bool.c flow.c function.c grab.c \ + idstuff.c \ linker.c method.c \ obj_file.c \ obj_type.c opcodes.c options.c pragma.c qfcc.c reloc.c shared.c \ diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 16db0b57d..41c3ca7a2 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1262,197 +1262,6 @@ field_expr (expr_t *e1, expr_t *e2) return type_mismatch (e1, e2, '.'); } -expr_t * -test_expr (expr_t *e) -{ - static float zero[4] = {0, 0, 0, 0}; - expr_t *new = 0; - type_t *type; - - if (e->type == ex_error) - return e; - - type = get_type (e); - if (e->type == ex_error) - return e; - switch (type->type) { - case ev_type_count: - internal_error (e, 0); - case ev_void: - if (options.traditional) { - if (options.warnings.traditional) - warning (e, "void has no value"); - return e; - } - return error (e, "void has no value"); - case ev_string: - if (!options.code.ifstring) - return new_alias_expr (type_default, e); - new = new_string_expr (0); - break; - case ev_uinteger: - case ev_integer: - case ev_short: - if (type_default != &type_integer) - return new_alias_expr (type_default, e); - return e; - case ev_float: - if (options.code.fast_float - || options.code.progsversion == PROG_ID_VERSION) { - if (type_default != &type_float) - return new_alias_expr (type_default, e); - return e; - } - new = new_float_expr (0); - break; - case ev_double: - new = new_double_expr (0); - break; - case ev_vector: - new = new_vector_expr (zero); - break; - case ev_entity: - return new_alias_expr (type_default, e); - case ev_field: - return new_alias_expr (type_default, e); - case ev_func: - return new_alias_expr (type_default, e); - case ev_pointer: - return new_alias_expr (type_default, e); - case ev_quat: - new = new_quaternion_expr (zero); - break; - case ev_invalid: - if (is_enum (type)) { - new = new_nil_expr (); - break; - } - return test_error (e, get_type (e)); - } - new->line = e->line; - new->file = e->file; - new = binary_expr (NE, e, new); - new->line = e->line; - new->file = e->file; - return new; -} - -void -backpatch (ex_list_t *list, expr_t *label) -{ - int i; - expr_t *e; - - if (!list) - return; - if (!label || label->type != ex_label) - internal_error (label, "not a label"); - - for (i = 0; i < list->size; i++) { - e = list->e[i]; - if (e->type == ex_uexpr && e->e.expr.op == 'g') - e->e.expr.e1 = label; - else if (e->type == ex_expr && (e->e.expr.op == 'i' - || e->e.expr.op == 'n')) - e->e.expr.e2 = label; - else { - internal_error (e, 0); - } - label->e.label.used++; - } -} - -static ex_list_t * -merge (ex_list_t *l1, ex_list_t *l2) -{ - ex_list_t *m; - - if (!l1 && !l2) - internal_error (0, 0); - if (!l2) - return l1; - if (!l1) - return l2; - m = malloc ((size_t)&((ex_list_t *)0)->e[l1->size + l2->size]); - m->size = l1->size + l2->size; - memcpy (m->e, l1->e, l1->size * sizeof (expr_t *)); - memcpy (m->e + l1->size, l2->e, l2->size * sizeof (expr_t *)); - return m; -} - -static ex_list_t * -make_list (expr_t *e) -{ - ex_list_t *m; - - m = malloc ((size_t)&((ex_list_t *) 0)->e[1]); - m->size = 1; - m->e[0] = e; - return m; -} - -expr_t * -convert_bool (expr_t *e, int block) -{ - expr_t *b; - - if (e->type == ex_expr && (e->e.expr.op == '=' || e->e.expr.op == PAS)) { - expr_t *src; - if (!e->paren && options.warnings.precedence) - warning (e, "suggest parentheses around assignment " - "used as truth value"); - src = e->e.expr.e2; - if (src->type == ex_block) { - src = new_temp_def_expr (get_type (src)); - e = new_binary_expr (e->e.expr.op, e->e.expr.e1, - assign_expr (src, e->e.expr.e2)); - } - b = convert_bool (src, 1); - if (b->type == ex_error) - return b; - // insert the assignment into the bool's block - e->next = b->e.bool.e->e.block.head; - b->e.bool.e->e.block.head = e; - if (b->e.bool.e->e.block.tail == &b->e.bool.e->e.block.head) { - // shouldn't happen, but just in case - b->e.bool.e->e.block.tail = &e->next; - } - return b; - } - - if (e->type == ex_uexpr && e->e.expr.op == '!' - && get_type (e->e.expr.e1) != &type_string) { - e = convert_bool (e->e.expr.e1, 0); - if (e->type == ex_error) - return e; - e = unary_expr ('!', e); - } - if (e->type != ex_bool) { - e = test_expr (e); - if (e->type == ex_error) - return e; - if (is_integer_val (e)) { - b = goto_expr (0); - if (expr_integer (e)) - e = new_bool_expr (make_list (b), 0, b); - else - e = new_bool_expr (0, make_list (b), b); - } else { - b = new_block_expr (); - append_expr (b, branch_expr ('i', e, 0)); - append_expr (b, goto_expr (0)); - e = new_bool_expr (make_list (b->e.block.head), - make_list (b->e.block.head->next), b); - } - } - if (block && e->e.bool.e->type != ex_block) { - expr_t *block = new_block_expr (); - append_expr (block, e->e.bool.e); - e->e.bool.e = block; - } - return e; -} - expr_t * convert_from_bool (expr_t *e, type_t *type) { @@ -1484,44 +1293,6 @@ convert_from_bool (expr_t *e, type_t *type) return e; } -expr_t * -bool_expr (int op, expr_t *label, expr_t *e1, expr_t *e2) -{ - expr_t *block; - - if (!options.code.short_circuit) - return binary_expr (op, e1, e2); - - e1 = convert_bool (e1, 0); - if (e1->type == ex_error) - return e1; - - e2 = convert_bool (e2, 0); - if (e2->type == ex_error) - return e2; - - block = new_block_expr (); - append_expr (block, e1); - append_expr (block, label); - append_expr (block, e2); - - switch (op) { - case OR: - backpatch (e1->e.bool.false_list, label); - return new_bool_expr (merge (e1->e.bool.true_list, - e2->e.bool.true_list), - e2->e.bool.false_list, block); - break; - case AND: - backpatch (e1->e.bool.true_list, label); - return new_bool_expr (e2->e.bool.true_list, - merge (e1->e.bool.false_list, - e2->e.bool.false_list), block); - break; - } - internal_error (e1, 0); -} - void convert_int (expr_t *e) { diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index a251860bf..ee1fb162c 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -992,8 +992,9 @@ binary_expr (int op, expr_t *e1, expr_t *e2) e = new_binary_expr (op, e1, e2); e->e.expr.type = expr_type->type; if (is_compare (op) || is_logic (op)) { - if (options.code.progsversion == PROG_ID_VERSION) + if (options.code.progsversion == PROG_ID_VERSION) { e->e.expr.type = &type_float; + } } return fold_constants (e); } diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c new file mode 100644 index 000000000..6eda9aa8d --- /dev/null +++ b/tools/qfcc/source/expr_bool.c @@ -0,0 +1,295 @@ +/* + expr_bool.c + + short-circuit boolean expressions + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2001/06/15 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/alloc.h" +#include "QF/dstring.h" +#include "QF/mathlib.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "qfcc.h" +#include "class.h" +#include "def.h" +#include "defspace.h" +#include "diagnostic.h" +#include "emit.h" +#include "expr.h" +#include "function.h" +#include "idstuff.h" +#include "method.h" +#include "options.h" +#include "reloc.h" +#include "shared.h" +#include "strpool.h" +#include "struct.h" +#include "symtab.h" +#include "type.h" +#include "value.h" +#include "qc-parse.h" + +expr_t * +test_expr (expr_t *e) +{ + static float zero[4] = {0, 0, 0, 0}; + expr_t *new = 0; + type_t *type; + + if (e->type == ex_error) + return e; + + type = get_type (e); + if (e->type == ex_error) + return e; + switch (type->type) { + case ev_type_count: + internal_error (e, 0); + case ev_void: + if (options.traditional) { + if (options.warnings.traditional) + warning (e, "void has no value"); + return e; + } + return error (e, "void has no value"); + case ev_string: + if (!options.code.ifstring) + return new_alias_expr (type_default, e); + new = new_string_expr (0); + break; + case ev_uinteger: + case ev_integer: + case ev_short: + if (type_default != &type_integer) + return new_alias_expr (type_default, e); + return e; + case ev_float: + if (options.code.fast_float + || options.code.progsversion == PROG_ID_VERSION) { + if (type_default != &type_float) + return new_alias_expr (type_default, e); + return e; + } + new = new_float_expr (0); + break; + case ev_double: + new = new_double_expr (0); + break; + case ev_vector: + new = new_vector_expr (zero); + break; + case ev_entity: + return new_alias_expr (type_default, e); + case ev_field: + return new_alias_expr (type_default, e); + case ev_func: + return new_alias_expr (type_default, e); + case ev_pointer: + return new_alias_expr (type_default, e); + case ev_quat: + new = new_quaternion_expr (zero); + break; + case ev_invalid: + if (is_enum (type)) { + new = new_nil_expr (); + break; + } + return test_error (e, get_type (e)); + } + new->line = e->line; + new->file = e->file; + new = binary_expr (NE, e, new); + new->line = e->line; + new->file = e->file; + return new; +} + +void +backpatch (ex_list_t *list, expr_t *label) +{ + int i; + expr_t *e; + + if (!list) + return; + if (!label || label->type != ex_label) + internal_error (label, "not a label"); + + for (i = 0; i < list->size; i++) { + e = list->e[i]; + if (e->type == ex_uexpr && e->e.expr.op == 'g') + e->e.expr.e1 = label; + else if (e->type == ex_expr && (e->e.expr.op == 'i' + || e->e.expr.op == 'n')) + e->e.expr.e2 = label; + else { + internal_error (e, 0); + } + label->e.label.used++; + } +} + +static ex_list_t * +merge (ex_list_t *l1, ex_list_t *l2) +{ + ex_list_t *m; + + if (!l1 && !l2) + internal_error (0, 0); + if (!l2) + return l1; + if (!l1) + return l2; + m = malloc ((size_t)&((ex_list_t *)0)->e[l1->size + l2->size]); + m->size = l1->size + l2->size; + memcpy (m->e, l1->e, l1->size * sizeof (expr_t *)); + memcpy (m->e + l1->size, l2->e, l2->size * sizeof (expr_t *)); + return m; +} + +static ex_list_t * +make_list (expr_t *e) +{ + ex_list_t *m; + + m = malloc ((size_t)&((ex_list_t *) 0)->e[1]); + m->size = 1; + m->e[0] = e; + return m; +} + +expr_t * +bool_expr (int op, expr_t *label, expr_t *e1, expr_t *e2) +{ + expr_t *block; + + if (!options.code.short_circuit) + return binary_expr (op, e1, e2); + + e1 = convert_bool (e1, 0); + if (e1->type == ex_error) + return e1; + + e2 = convert_bool (e2, 0); + if (e2->type == ex_error) + return e2; + + block = new_block_expr (); + append_expr (block, e1); + append_expr (block, label); + append_expr (block, e2); + + switch (op) { + case OR: + backpatch (e1->e.bool.false_list, label); + return new_bool_expr (merge (e1->e.bool.true_list, + e2->e.bool.true_list), + e2->e.bool.false_list, block); + break; + case AND: + backpatch (e1->e.bool.true_list, label); + return new_bool_expr (e2->e.bool.true_list, + merge (e1->e.bool.false_list, + e2->e.bool.false_list), block); + break; + } + internal_error (e1, 0); +} + +expr_t * +convert_bool (expr_t *e, int block) +{ + expr_t *b; + + if (e->type == ex_expr && (e->e.expr.op == '=' || e->e.expr.op == PAS)) { + expr_t *src; + if (!e->paren && options.warnings.precedence) + warning (e, "suggest parentheses around assignment " + "used as truth value"); + src = e->e.expr.e2; + if (src->type == ex_block) { + src = new_temp_def_expr (get_type (src)); + e = new_binary_expr (e->e.expr.op, e->e.expr.e1, + assign_expr (src, e->e.expr.e2)); + } + b = convert_bool (src, 1); + if (b->type == ex_error) + return b; + // insert the assignment into the bool's block + e->next = b->e.bool.e->e.block.head; + b->e.bool.e->e.block.head = e; + if (b->e.bool.e->e.block.tail == &b->e.bool.e->e.block.head) { + // shouldn't happen, but just in case + b->e.bool.e->e.block.tail = &e->next; + } + return b; + } + + if (e->type == ex_uexpr && e->e.expr.op == '!' + && get_type (e->e.expr.e1) != &type_string) { + e = convert_bool (e->e.expr.e1, 0); + if (e->type == ex_error) + return e; + e = unary_expr ('!', e); + } + if (e->type != ex_bool) { + e = test_expr (e); + if (e->type == ex_error) + return e; + if (is_integer_val (e)) { + b = goto_expr (0); + if (expr_integer (e)) + e = new_bool_expr (make_list (b), 0, b); + else + e = new_bool_expr (0, make_list (b), b); + } else { + b = new_block_expr (); + append_expr (b, branch_expr ('i', e, 0)); + append_expr (b, goto_expr (0)); + e = new_bool_expr (make_list (b->e.block.head), + make_list (b->e.block.head->next), b); + } + } + if (block && e->e.bool.e->type != ex_block) { + expr_t *block = new_block_expr (); + append_expr (block, e->e.bool.e); + e->e.bool.e = block; + } + return e; +} From 55e53211e2711e155b1ace1a6d19e363d2a6647c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 02:11:31 +0900 Subject: [PATCH 0391/3664] Generate default type expressions for folded booleans --- tools/qfcc/source/constfold.c | 102 +++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index df8ea6ae0..e7c037deb 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -69,6 +69,16 @@ valid_op (int op, int *valid_ops) return *valid_ops == op; } +static expr_t * +cmp_result_expr (int result) +{ + if (is_float (type_default)) { + return new_float_expr (result); + } else { + return new_integer_expr(result); + } +} + static expr_t * do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) { @@ -108,22 +118,22 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) e = new_string_expr (save_string (temp_str->str)); break; case LT: - e = new_integer_expr (strcmp (s1, s2) < 0); + e = cmp_result_expr (strcmp (s1, s2) < 0); break; case GT: - e = new_integer_expr (strcmp (s1, s2) > 0); + e = cmp_result_expr (strcmp (s1, s2) > 0); break; case LE: - e = new_integer_expr (strcmp (s1, s2) <= 0); + e = cmp_result_expr (strcmp (s1, s2) <= 0); break; case GE: - e = new_integer_expr (strcmp (s1, s2) >= 0); + e = cmp_result_expr (strcmp (s1, s2) >= 0); break; case EQ: - e = new_integer_expr (strcmp (s1, s2) == 0); + e = cmp_result_expr (strcmp (s1, s2) == 0); break; case NE: - e = new_integer_expr (strcmp (s1, s2)); + e = cmp_result_expr (strcmp (s1, s2)); break; default: internal_error (e1, 0); @@ -300,28 +310,28 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) e = new_float_expr ((int)f1 >> (int)f2); break; case AND: - e = new_integer_expr (f1 && f2); + e = cmp_result_expr (f1 && f2); break; case OR: - e = new_integer_expr (f1 || f2); + e = cmp_result_expr (f1 || f2); break; case LT: - e = new_integer_expr (f1 < f2); + e = cmp_result_expr (f1 < f2); break; case GT: - e = new_integer_expr (f1 > f2); + e = cmp_result_expr (f1 > f2); break; case LE: - e = new_integer_expr (f1 <= f2); + e = cmp_result_expr (f1 <= f2); break; case GE: - e = new_integer_expr (f1 >= f2); + e = cmp_result_expr (f1 >= f2); break; case EQ: - e = new_integer_expr (f1 == f2); + e = cmp_result_expr (f1 == f2); break; case NE: - e = new_integer_expr (f1 != f2); + e = cmp_result_expr (f1 != f2); break; default: internal_error (e1, 0); @@ -411,22 +421,22 @@ do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2) e = new_double_expr ((int)d1 % (int)d2); break; case LT: - e = new_integer_expr (d1 < d2); + e = cmp_result_expr (d1 < d2); break; case GT: - e = new_integer_expr (d1 > d2); + e = cmp_result_expr (d1 > d2); break; case LE: - e = new_integer_expr (d1 <= d2); + e = cmp_result_expr (d1 <= d2); break; case GE: - e = new_integer_expr (d1 >= d2); + e = cmp_result_expr (d1 >= d2); break; case EQ: - e = new_integer_expr (d1 == d2); + e = cmp_result_expr (d1 == d2); break; case NE: - e = new_integer_expr (d1 != d2); + e = cmp_result_expr (d1 != d2); break; default: internal_error (e1, 0); @@ -539,10 +549,10 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) } break; case EQ: - e = new_integer_expr (VectorCompare (v1, v2)); + e = cmp_result_expr (VectorCompare (v1, v2)); break; case NE: - e = new_integer_expr (!VectorCompare (v1, v2)); + e = cmp_result_expr (!VectorCompare (v1, v2)); break; default: internal_error (e1, 0); @@ -776,10 +786,10 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) e = new_quaternion_expr (q); break; case EQ: - e = new_integer_expr (QuatCompare (q1, q2)); + e = cmp_result_expr (QuatCompare (q1, q2)); break; case NE: - e = new_integer_expr (!QuatCompare (q1, q2)); + e = cmp_result_expr (!QuatCompare (q1, q2)); break; default: internal_error (e1, 0); @@ -877,28 +887,28 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) e = new_integer_expr (i1 >> i2); break; case AND: - e = new_integer_expr (i1 && i2); + e = cmp_result_expr (i1 && i2); break; case OR: - e = new_integer_expr (i1 || i2); + e = cmp_result_expr (i1 || i2); break; case LT: - e = new_integer_expr (i1 < i2); + e = cmp_result_expr (i1 < i2); break; case GT: - e = new_integer_expr (i1 > i2); + e = cmp_result_expr (i1 > i2); break; case LE: - e = new_integer_expr (i1 <= i2); + e = cmp_result_expr (i1 <= i2); break; case GE: - e = new_integer_expr (i1 >= i2); + e = cmp_result_expr (i1 >= i2); break; case EQ: - e = new_integer_expr (i1 == i2); + e = cmp_result_expr (i1 == i2); break; case NE: - e = new_integer_expr (i1 != i2); + e = cmp_result_expr (i1 != i2); break; default: internal_error (e1, 0); @@ -981,22 +991,22 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) e = new_short_expr (i1 || i2); break; case LT: - e = new_integer_expr (i1 < i2); + e = cmp_result_expr (i1 < i2); break; case GT: - e = new_integer_expr (i1 > i2); + e = cmp_result_expr (i1 > i2); break; case LE: - e = new_integer_expr (i1 <= i2); + e = cmp_result_expr (i1 <= i2); break; case GE: - e = new_integer_expr (i1 >= i2); + e = cmp_result_expr (i1 >= i2); break; case EQ: - e = new_integer_expr (i1 == i2); + e = cmp_result_expr (i1 == i2); break; case NE: - e = new_integer_expr (i1 != i2); + e = cmp_result_expr (i1 != i2); break; default: internal_error (e1, 0); @@ -1375,7 +1385,7 @@ uop_string (int op, expr_t *e, expr_t *e1) return e; s = expr_string (e1); - return new_integer_expr (!s || !s[0]); + return cmp_result_expr (!s || !s[0]); } static expr_t * @@ -1399,7 +1409,7 @@ uop_float (int op, expr_t *e, expr_t *e1) return new_float_expr (-expr_float (e1)); case '!': print_type (get_type (e)); - return new_integer_expr (!expr_float (e1)); + return cmp_result_expr (!expr_float (e1)); case '~': return new_float_expr (~(int) expr_float (e1)); case 'C': @@ -1430,7 +1440,7 @@ uop_vector (int op, expr_t *e, expr_t *e1) VectorNegate (expr_vector (e), v); return new_vector_expr (v); case '!': - return new_integer_expr (!VectorIsZero (expr_vector (e1))); + return cmp_result_expr (!VectorIsZero (expr_vector (e1))); } internal_error (e, "vector unary op blew up"); } @@ -1524,7 +1534,7 @@ uop_quaternion (int op, expr_t *e, expr_t *e1) QuatNegate (expr_vector (e), q); return new_quaternion_expr (q); case '!': - return new_integer_expr (!QuatIsZero (expr_quaternion (e1))); + return cmp_result_expr (!QuatIsZero (expr_quaternion (e1))); case '~': QuatConj (expr_vector (e), q); return new_quaternion_expr (q); @@ -1550,7 +1560,7 @@ uop_integer (int op, expr_t *e, expr_t *e1) case '-': return new_integer_expr (-expr_integer (e1)); case '!': - return new_integer_expr (!expr_integer (e1)); + return cmp_result_expr (!expr_integer (e1)); case '~': return new_integer_expr (~expr_integer (e1)); case 'C': @@ -1575,7 +1585,7 @@ uop_uinteger (int op, expr_t *e, expr_t *e1) case '-': return new_uinteger_expr (-expr_uinteger (e1)); case '!': - return new_integer_expr (!expr_uinteger (e1)); + return cmp_result_expr (!expr_uinteger (e1)); case '~': return new_uinteger_expr (~expr_uinteger (e1)); } @@ -1598,7 +1608,7 @@ uop_short (int op, expr_t *e, expr_t *e1) case '-': return new_short_expr (-expr_short (e1)); case '!': - return new_integer_expr (!expr_short (e1)); + return cmp_result_expr (!expr_short (e1)); case '~': return new_short_expr (~expr_short (e1)); } @@ -1626,7 +1636,7 @@ uop_double (int op, expr_t *e, expr_t *e1) return new_double_expr (-expr_double (e1)); case '!': print_type (get_type (e)); - return new_integer_expr (!expr_double (e1)); + return cmp_result_expr (!expr_double (e1)); case 'C': if (type == &type_integer) { return new_integer_expr (expr_double (e1)); From 9c26d12f95bae7c4223dc601ed49f577ec267ae4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 02:13:23 +0900 Subject: [PATCH 0392/3664] Cast rather than alias for testing constants Fixes ICE in do { ... } while (1); --- tools/qfcc/source/expr_bool.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 6eda9aa8d..c460144b5 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -96,14 +96,22 @@ test_expr (expr_t *e) case ev_uinteger: case ev_integer: case ev_short: - if (type_default != &type_integer) + if (type_default != &type_integer) { + if (is_constant (e)) { + return cast_expr (type_default, e); + } return new_alias_expr (type_default, e); + } return e; case ev_float: if (options.code.fast_float || options.code.progsversion == PROG_ID_VERSION) { - if (type_default != &type_float) + if (type_default != &type_float) { + if (is_constant (e)) { + return cast_expr (type_default, e); + } return new_alias_expr (type_default, e); + } return e; } new = new_float_expr (0); From ac32bbca40d0dbb1f79d78e202f5a496c0005005 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 02:14:44 +0900 Subject: [PATCH 0393/3664] Improve code for short-circuited float logic --- tools/qfcc/source/expr_bool.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index c460144b5..7f7fdbfee 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -280,9 +280,16 @@ convert_bool (expr_t *e, int block) e = test_expr (e); if (e->type == ex_error) return e; - if (is_integer_val (e)) { + if (is_constant (e)) { + int val; + b = goto_expr (0); - if (expr_integer (e)) + if (is_integer_val (e)) { + val = expr_integer (e); + } else { + val = expr_float (e) != 0; + } + if (val) e = new_bool_expr (make_list (b), 0, b); else e = new_bool_expr (0, make_list (b), b); From 2adcad7c84e23522a94cf6f683b294b4cb5ab80a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 02:25:28 +0900 Subject: [PATCH 0394/3664] Allow non-short-circuited logic to work --- tools/qfcc/source/expr_binary.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index ee1fb162c..228112311 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -72,6 +72,8 @@ static expr_type_t float_float[] = { {MOD, &type_float}, {SHL, &type_float}, {SHR, &type_float}, + {AND, &type_integer}, + {OR, &type_integer}, {EQ, &type_integer}, {NE, &type_integer}, {LE, &type_integer}, @@ -274,6 +276,8 @@ static expr_type_t integer_integer[] = { {MOD, &type_integer}, {SHL, &type_integer}, {SHR, &type_integer}, + {AND, &type_integer}, + {OR, &type_integer}, {EQ, &type_integer}, {NE, &type_integer}, {LE, &type_integer}, From c43b9681ebc62155b316f56e1d300ccec44a05e9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 08:43:32 +0900 Subject: [PATCH 0395/3664] Keep structure members aligned --- tools/qfcc/source/struct.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 800a1aa66..5fe569d31 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -124,6 +124,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) if (s->sy_type != sy_var) continue; if (su == 's') { + symtab->size = RUP (symtab->size, s->type->alignment); s->s.offset = symtab->size; symtab->size += type_size (s->type); } else { From 7406e0308e85179f0104a785ea233abc989b8314 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 11:28:43 +0900 Subject: [PATCH 0396/3664] Fix some warnings picked up in an optimized build --- include/QF/progs.h | 6 +++--- libs/console/buffer.c | 2 +- libs/gamecode/pr_debug.c | 8 ++++---- tools/qfcc/source/obj_file.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 78b3036c7..d007ac81f 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1787,7 +1787,7 @@ struct progs_s { \return C pointer represented by the parameter. 0 offset -> NULL */ static inline pr_type_t * -PR_GetPointer (progs_t *pr, pointer_t o) +PR_GetPointer (const progs_t *pr, pointer_t o) { return o ? pr->pr_globals + o : 0; } @@ -1798,9 +1798,9 @@ PR_GetPointer (progs_t *pr, pointer_t o) \return Progs offset/pointer represented by \c p. NULL -> 0 offset */ static inline pointer_t -PR_SetPointer (progs_t *pr, void *p) +PR_SetPointer (const progs_t *pr, const void *p) { - return p ? (pr_type_t *) p - pr->pr_globals : 0; + return p ? (const pr_type_t *) p - pr->pr_globals : 0; } ///@} diff --git a/libs/console/buffer.c b/libs/console/buffer.c index d494c0655..2aa477abc 100644 --- a/libs/console/buffer.c +++ b/libs/console/buffer.c @@ -92,7 +92,7 @@ Con_BufferAddText (con_buffer_t *buf, const char *text) } while (len--) { byte c = *pos++ = *text++; - if ((size_t) (pos - buf->buffer) >= buf->buffer_size) + if (pos >= buf->buffer + buf->buffer_size) pos = buf->buffer; cur_line->len++; if (pos == tail_line->text) { diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 9b0deece5..d895f631a 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -196,8 +196,8 @@ pr_debug_expression_error (script_t *script, const char *msg) } #define RUP(x,a) (((x) + ((a) - 1)) & ~((a) - 1)) -static pr_short_t -pr_debug_type_size (progs_t *pr, qfot_type_t *type) +static pr_short_t __attribute__((pure)) +pr_debug_type_size (const progs_t *pr, const qfot_type_t *type) { pr_short_t size; qfot_type_t *aux_type; @@ -208,7 +208,7 @@ pr_debug_type_size (progs_t *pr, qfot_type_t *type) case ty_union: size = 0; for (pr_int_t i = 0; i < type->t.strct.num_fields; i++) { - qfot_var_t *field = &type->t.strct.fields[i]; + const qfot_var_t *field = &type->t.strct.fields[i]; aux_type = &G_STRUCT (pr, qfot_type_t, field->type); size = max (size, field->offset + pr_debug_type_size (pr, aux_type)); @@ -995,7 +995,7 @@ pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) progs_t *pr = data->pr; dstring_t *dstr = data->dstr; pointer_t ofs = value->integer_var; - pr_def_t *def; + pr_def_t *def = 0; if (pr_debug->int_val && pr->debug) { def = PR_Get_Local_Def (pr, ofs); diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 735a68ab0..855e48b61 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -891,7 +891,7 @@ qfo_to_progs (qfo_t *qfo, int *size) int xdefs_start; unsigned big_locals = 0; int big_func = 0; - pr_xdefs_t *xdefs; + pr_xdefs_t *xdefs = 0; xdef_t *xdef; *size = RUP (sizeof (dprograms_t), 16); From a30433fa9ebfa47ced0ac883e33f8d0c333c3272 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 12:21:20 +0900 Subject: [PATCH 0397/3664] Make header protection consistent And delete a couple of useless files. --- include/QF/Makefile.am | 4 ++-- include/QF/bspfile.h | 6 ++--- include/QF/cdaudio.h | 6 ++--- include/QF/checksum.h | 6 ++--- include/QF/console.h | 6 ++--- include/QF/crc.h | 6 ++--- include/QF/cvar.h | 6 ++--- include/QF/draw.h | 6 ++--- include/QF/dstring.h | 6 ++--- include/QF/gib.h | 6 ++--- include/QF/hash.h | 6 ++--- include/QF/hl.h | 40 -------------------------------- include/QF/image.h | 2 +- include/QF/info.h | 6 ++--- include/QF/input.h | 6 ++--- include/QF/iqm.h | 6 ++--- include/QF/joystick.h | 6 ++--- include/QF/keys.h | 6 ++--- include/QF/link.h | 6 ++--- include/QF/llist.h | 6 ++--- include/QF/locs.h | 6 ++--- include/QF/mathlib.h | 6 ++--- include/QF/mdfour.h | 6 ++--- include/QF/model.h | 6 ++--- include/QF/modelgen.h | 6 ++--- include/QF/msg.h | 6 ++--- include/QF/object.h | 6 ++--- include/QF/pak.h | 6 ++--- include/QF/pcx.h | 6 ++--- include/QF/plugin.h | 6 ++--- include/QF/pr_comp.h | 6 ++--- include/QF/pr_debug.h | 6 ++--- include/QF/pr_obj.h | 6 ++--- include/QF/pr_type.h | 6 ++--- include/QF/qargs.h | 6 ++--- include/QF/qdefs.h | 6 ++--- include/QF/qendian.h | 6 ++--- include/QF/qfplist.h | 6 ++--- include/QF/qtypes.h | 6 ++--- include/QF/quakefs.h | 6 ++--- include/QF/quakeio.h | 6 ++--- include/QF/render.h | 6 ++--- include/QF/screen.h | 6 ++--- include/QF/sizebuf.h | 6 ++--- include/QF/skin.h | 6 ++--- include/QF/sound.h | 6 ++--- include/QF/spritegn.h | 6 ++--- include/QF/sys.h | 6 ++--- include/QF/teamplay.h | 6 ++--- include/QF/tga.h | 6 ++--- include/QF/uint32.h | 52 ------------------------------------------ include/QF/va.h | 6 ++--- include/QF/ver_check.h | 6 ++--- include/QF/vid.h | 6 ++--- include/QF/view.h | 6 ++--- include/QF/wad.h | 6 ++--- include/QF/zone.h | 6 ++--- 57 files changed, 162 insertions(+), 254 deletions(-) delete mode 100644 include/QF/hl.h delete mode 100644 include/QF/uint32.h diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am index 8bf956359..3041d64d6 100644 --- a/include/QF/Makefile.am +++ b/include/QF/Makefile.am @@ -2,14 +2,14 @@ AUTOMAKE_OPTIONS = foreign pkgincludedir = $(includedir)/QF nobase_pkginclude_HEADERS = \ alloc.h bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \ - console.h crc.h csqc.h cvar.h dstring.h draw.h gib.h hash.h hl.h \ + console.h crc.h csqc.h cvar.h dstring.h draw.h gib.h hash.h \ idparse.h image.h in_event.h info.h input.h iqm.h joystick.h keys.h \ link.h llist.h locs.h mathlib.h mdfour.h mersenne.h model.h modelgen.h \ msg.h object.h pak.h pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h \ pr_obj.h pr_type.h progs.h qargs.h qdefs.h qendian.h qfplist.h qtypes.h \ quakefs.h \ quakeio.h render.h riff.h ruamoko.h screen.h script.h segtext.h set.h \ - sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h tga.h uint32.h va.h \ + sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h tga.h va.h \ ver_check.h vid.h vrect.h view.h wad.h wadfile.h winding.h zone.h \ \ GL/ati.h GL/defines.h GL/extensions.h GL/funcs.h GL/qf_draw.h \ diff --git a/include/QF/bspfile.h b/include/QF/bspfile.h index b7683849f..0d32c09e8 100644 --- a/include/QF/bspfile.h +++ b/include/QF/bspfile.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __bspfile_h_ -#define __bspfile_h_ +#ifndef __QF_bspfile_h +#define __QF_bspfile_h #include "QF/qtypes.h" #include "QF/quakeio.h" @@ -310,4 +310,4 @@ void BSP_AddVisibility (bsp_t *bsp, const byte *visdata, size_t visdatasize); void BSP_AddEntities (bsp_t *bsp, const char *entdata, size_t entdatasize); void BSP_AddTextures (bsp_t *bsp, const byte *texdata, size_t texdatasize); -#endif//__bspfile_h_ +#endif//__QF_bspfile_h diff --git a/include/QF/cdaudio.h b/include/QF/cdaudio.h index e7596ad78..abc07b2e7 100644 --- a/include/QF/cdaudio.h +++ b/include/QF/cdaudio.h @@ -25,8 +25,8 @@ */ -#ifndef _CDAUDIO_H -#define _CDAUDIO_H +#ifndef __QF_cdaudio_h +#define __QF_cdaudio_h #include "QF/qtypes.h" @@ -38,4 +38,4 @@ void CDAudio_Resume(void); void CDAudio_Shutdown(void); void CDAudio_Update(void); -#endif // _CDAUDIO_H +#endif//__QF_cdaudio_h diff --git a/include/QF/checksum.h b/include/QF/checksum.h index ed6f035b1..12fcaf477 100644 --- a/include/QF/checksum.h +++ b/include/QF/checksum.h @@ -25,8 +25,8 @@ */ -#ifndef __checksum_h -#define __checksum_h +#ifndef __QF_checksum_h +#define __QF_checksum_h /** \addtogroup crc */ @@ -40,4 +40,4 @@ byte COM_BlockSequenceCRCByte (const byte *base, int length, int sequence); ///@} -#endif // __checksum_h +#endif//__QF_checksum_h diff --git a/include/QF/console.h b/include/QF/console.h index 4f3bcb3c8..da88f8744 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -25,8 +25,8 @@ */ -#ifndef __console_h -#define __console_h +#ifndef __QF_console_h +#define __QF_console_h #include @@ -151,4 +151,4 @@ void Menu_Leave_f (void); void Menu_Prev_f (void); void Menu_Next_f (void); -#endif // __console_h +#endif//__QF_console_h diff --git a/include/QF/crc.h b/include/QF/crc.h index cc635e7b9..ad26bacb8 100644 --- a/include/QF/crc.h +++ b/include/QF/crc.h @@ -25,8 +25,8 @@ */ -#ifndef __crc_h -#define __crc_h +#ifndef __QF_crc_h +#define __QF_crc_h /** \defgroup crc Checksum generation. \ingroup utils @@ -43,4 +43,4 @@ unsigned short CRC_Block (const byte *start, int count) __attribute__((pure)); ///@} -#endif // __crc_h +#endif//__QF_crc_h diff --git a/include/QF/cvar.h b/include/QF/cvar.h index 3d81a3b1c..946a20f13 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -25,8 +25,8 @@ */ -#ifndef __cvar_h -#define __cvar_h +#ifndef __QF_cvar_h +#define __QF_cvar_h /** \defgroup cvar Configuration variables \ingroup utils @@ -140,4 +140,4 @@ extern cvar_t *cvar_vars; ///@} -#endif // __cvar_h +#endif//__QF_cvar_h diff --git a/include/QF/draw.h b/include/QF/draw.h index 529f3e892..8f6b78889 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -25,8 +25,8 @@ */ -#ifndef _DRAW_H -#define _DRAW_H +#ifndef __QF_draw_h +#define __QF_draw_h /** \defgroup video Video Sub-sytem */ @@ -234,4 +234,4 @@ void Draw_Picf (float x, float y, qpic_t *pic); void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); ///@} -#endif // _DRAW_H +#endif//__QF_draw_h diff --git a/include/QF/dstring.h b/include/QF/dstring.h index 638d9e340..bb5ea9117 100644 --- a/include/QF/dstring.h +++ b/include/QF/dstring.h @@ -25,8 +25,8 @@ */ -#ifndef __dstring_h -#define __dstring_h +#ifndef __QF_dstring_h +#define __QF_dstring_h /** \defgroup dstring Dynamic Strings \ingroup utils @@ -177,4 +177,4 @@ int dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(prin ///@} -#endif // __dstring_h +#endif//__QF_dstring_h diff --git a/include/QF/gib.h b/include/QF/gib.h index 34c187ac7..09bcf01ad 100644 --- a/include/QF/gib.h +++ b/include/QF/gib.h @@ -28,8 +28,8 @@ */ -#ifndef __gib_h -#define __gib_h +#ifndef __QF_gib_h +#define __QF_gib_h // Dependencies @@ -216,4 +216,4 @@ unsigned long int GIB_Handle_New (gib_object_t *data); void GIB_Handle_Free (unsigned long int num); gib_object_t *GIB_Handle_Get (unsigned long int num) __attribute__((pure)); -#endif +#endif//__QF_gib_h diff --git a/include/QF/hash.h b/include/QF/hash.h index ae040cfa9..7a31a06db 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -25,8 +25,8 @@ */ -#ifndef __hash_h -#define __hash_h +#ifndef __QF_hash_h +#define __QF_hash_h #include #include @@ -211,4 +211,4 @@ void Hash_Stats (hashtab_t *tab); ///@} -#endif // __hash_h +#endif//__QF_hash_h diff --git a/include/QF/hl.h b/include/QF/hl.h deleted file mode 100644 index 286768cc0..000000000 --- a/include/QF/hl.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - hl_bsp.h - - Half Life file definitions - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ - - -#ifndef _HL_BSP_H -#define _HL_BSP_H - -#include "QF/qtypes.h" - -extern void CL_ParseEntityLump(const char *entdata); -extern void HL_Mod_LoadLighting (lump_t *l); -extern void HL_Mod_LoadTextures (lump_t *l); -extern byte *W_GetTexture(const char *name, int matchwidth, int matchheight); -extern void W_LoadTextureWadFile (const char *filename, int complain); - -#endif // _HL_BSP_H diff --git a/include/QF/image.h b/include/QF/image.h index 33c69c120..106379bb7 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -49,4 +49,4 @@ typedef struct tex_s { tex_t *LoadImage (const char *imageFile); -#endif //__QF_image_h +#endif//__QF_image_h diff --git a/include/QF/info.h b/include/QF/info.h index 4e34f6fa2..7bf16b0ab 100644 --- a/include/QF/info.h +++ b/include/QF/info.h @@ -25,8 +25,8 @@ */ -#ifndef _INFO_H -#define _INFO_H +#ifndef __QF_info_h +#define __QF_info_h /** \defgroup info Info Keys \ingroup utils @@ -65,4 +65,4 @@ void Info_AddKeys (info_t *info, info_t *keys); ///@} -#endif // _INFO_H +#endif//__QF_info_h diff --git a/include/QF/input.h b/include/QF/input.h index 8f0438071..5835ee17b 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -25,8 +25,8 @@ */ -#ifndef __QF_input_h_ -#define __QF_input_h_ +#ifndef __QF_input_h +#define __QF_input_h #include "QF/keys.h" @@ -75,4 +75,4 @@ void IN_LL_Grab_Input (int grab); extern kbutton_t in_strafe, in_klook, in_speed, in_mlook; -#endif // __QF_input_h_ +#endif//__QF_input_h diff --git a/include/QF/iqm.h b/include/QF/iqm.h index fb6517c76..adc5a3313 100644 --- a/include/QF/iqm.h +++ b/include/QF/iqm.h @@ -1,5 +1,5 @@ -#ifndef __QF_iqm_h__ -#define __QF_iqm_h__ +#ifndef __QF_iqm_h +#define __QF_iqm_h #include "QF/qtypes.h" @@ -149,4 +149,4 @@ typedef struct { void *extra_data; } iqm_t; -#endif//__QF_iqm_h__ +#endif//__QF_iqm_h diff --git a/include/QF/joystick.h b/include/QF/joystick.h index 1eeba5d49..4b8163f7e 100644 --- a/include/QF/joystick.h +++ b/include/QF/joystick.h @@ -25,8 +25,8 @@ */ -#ifndef __QF_joystick_h_ -#define __QF_joystick_h_ +#ifndef __QF_joystick_h +#define __QF_joystick_h #include #include "QF/quakeio.h" @@ -154,4 +154,4 @@ int JOY_GetAxis_i (int dest, const char *c); void Joy_WriteBindings (QFile *f); -#endif // __QF_joystick_h_ +#endif//__QF_joystick_h diff --git a/include/QF/keys.h b/include/QF/keys.h index 66ef8d99e..7c9c959fd 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -26,8 +26,8 @@ */ -#ifndef _KEYS_H -#define _KEYS_H +#ifndef __QF_keys_h +#define __QF_keys_h #ifndef __QFCC__ # include "QF/qtypes.h" @@ -661,4 +661,4 @@ void Key_Progs_Init (struct progs_s *pr); ///@} -#endif // _KEYS_H +#endif//__QF_keys_h diff --git a/include/QF/link.h b/include/QF/link.h index de29bb454..5b6fdcf8c 100644 --- a/include/QF/link.h +++ b/include/QF/link.h @@ -25,8 +25,8 @@ */ -#ifndef _LINK_H -#define _LINK_H +#ifndef __QF_link_h +#define __QF_link_h // (type *)STRUCT_FROM_LINK(link_t *link, type, member) // ent = STRUCT_FROM_LINK(link,entity_t,order) @@ -43,4 +43,4 @@ void RemoveLink (link_t *l); void InsertLinkBefore (link_t *l, link_t *before); void InsertLinkAfter (link_t *l, link_t *after); -#endif // _LINK_H +#endif//__QF_link_h diff --git a/include/QF/llist.h b/include/QF/llist.h index b9a3a0140..e555c6bd6 100644 --- a/include/QF/llist.h +++ b/include/QF/llist.h @@ -25,8 +25,8 @@ */ -#ifndef _LLIST_H -#define _LLIST_H +#ifndef __QF_llist_h +#define __QF_llist_h #include "QF/qtypes.h" @@ -112,4 +112,4 @@ void *llist_createarray (llist_t *list, size_t esize); //@} -#endif +#endif//__QF_llist_h diff --git a/include/QF/locs.h b/include/QF/locs.h index 425e8980d..4f7dc9b5c 100644 --- a/include/QF/locs.h +++ b/include/QF/locs.h @@ -25,8 +25,8 @@ */ -#ifndef __locs_h -#define __locs_h +#ifndef __QF_locs_h +#define __QF_locs_h #include "QF/qtypes.h" @@ -47,4 +47,4 @@ void locs_reset (void); void locs_save (const char *filename, qboolean gz); void map_to_loc (const char *mapname, char *filename); -#endif // __locs_h +#endif//__QF_locs_h diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index 5c9b854fe..851b841eb 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -25,8 +25,8 @@ */ -#ifndef __mathlib_h -#define __mathlib_h +#ifndef __QF_mathlib_h +#define __QF_mathlib_h /** \defgroup mathlib Vector and matrix functions \ingroup utils @@ -220,4 +220,4 @@ void BarycentricCoords (const vec_t **points, int num_points, const vec3_t p, ///@} -#endif // __mathlib_h +#endif//__QF_mathlib_h diff --git a/include/QF/mdfour.h b/include/QF/mdfour.h index 19360e838..bff20aefb 100644 --- a/include/QF/mdfour.h +++ b/include/QF/mdfour.h @@ -26,8 +26,8 @@ */ -#ifndef __mdfour_h -#define __mdfour_h +#ifndef __QF_mdfour_h +#define __QF_mdfour_h /** \addtogroup crc */ @@ -49,4 +49,4 @@ void mdfour(unsigned char *out, const unsigned char *in, int n); ///@} -#endif // __mdfour_h +#endif//__QF_mdfour_h diff --git a/include/QF/model.h b/include/QF/model.h index 6b3fbc3b5..d4b243241 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -25,8 +25,8 @@ */ -#ifndef _MODEL_H -#define _MODEL_H +#ifndef __QF_model_h +#define __QF_model_h #include "QF/qtypes.h" #include "QF/bspfile.h" @@ -468,4 +468,4 @@ extern byte *mod_base; extern byte mod_novis[MAX_MAP_LEAFS / 8]; extern int mod_lightmap_bytes; -#endif // _MODEL_H +#endif//__QF_model_h diff --git a/include/QF/modelgen.h b/include/QF/modelgen.h index 447a8c864..66cdd1308 100644 --- a/include/QF/modelgen.h +++ b/include/QF/modelgen.h @@ -31,8 +31,8 @@ // * pass data from one to the other via model files. * // ********************************************************* -#ifndef _MODELGEN_H -#define _MODELGEN_H +#ifndef __QF_modelgen_h +#define __QF_modelgen_h #include "QF/mathlib.h" @@ -142,4 +142,4 @@ typedef struct { // little-endian "IDP2" #define IDHEADER_MD2 (('2'<<24)+('P'<<16)+('D'<<8)+'I') -#endif // _MODELGEN_H +#endif//__QF_modelgen_h diff --git a/include/QF/msg.h b/include/QF/msg.h index 6a92e2d54..4f696f896 100644 --- a/include/QF/msg.h +++ b/include/QF/msg.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef _MSG_H -#define _MSG_H +#ifndef __QF_msg_h +#define __QF_msg_h /** \defgroup msg Message reading and writing \ingroup utils @@ -251,4 +251,4 @@ int MSG_ReadUTF8 (qmsg_t *msg); ///@} -#endif +#endif//__QF_msg_h diff --git a/include/QF/object.h b/include/QF/object.h index 39f06210b..f5c4f97f8 100644 --- a/include/QF/object.h +++ b/include/QF/object.h @@ -32,8 +32,8 @@ */ -#ifndef __object_h -#define __object_h +#ifndef __QF_object_h +#define __QF_object_h #include "QF/qtypes.h" @@ -115,4 +115,4 @@ void Object_Garbage_Collect (void); #include "QF/classes/String.h" -#endif +#endif//__QF_object_h diff --git a/include/QF/pak.h b/include/QF/pak.h index ea86ffd14..e331fca6e 100644 --- a/include/QF/pak.h +++ b/include/QF/pak.h @@ -28,8 +28,8 @@ */ -#ifndef __qf_pak_h -#define __qf_pak_h +#ifndef __QF_pak_h +#define __QF_pak_h /** \addtogroup pak */ @@ -53,4 +53,4 @@ typedef struct { ///@} -#endif//__qf_pak_h +#endif//__QF_pak_h diff --git a/include/QF/pcx.h b/include/QF/pcx.h index 6bfeb03e5..8536b9f69 100644 --- a/include/QF/pcx.h +++ b/include/QF/pcx.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __pcx_h -#define __pcx_h +#ifndef __QF_pcx_h +#define __QF_pcx_h #include "QF/qtypes.h" #include "QF/quakeio.h" @@ -77,4 +77,4 @@ pcx_t *EncodePCX (byte *data, int width, int height, int rowbytes, */ struct tex_s *LoadPCX (QFile *f, qboolean convert, byte *pal); -#endif // __pcx_h +#endif//__QF_pcx_h diff --git a/include/QF/plugin.h b/include/QF/plugin.h index 0a06f73f2..f1ff974a3 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -25,8 +25,8 @@ */ -#ifndef __QF_plugin_h_ -#define __QF_plugin_h_ +#ifndef __QF_plugin_h +#define __QF_plugin_h /** \defgroup plugin Plugins \ingroup utils @@ -113,4 +113,4 @@ void PI_Shutdown (void); ///@} -#endif // __QF_plugin_h_ +#endif//__QF_plugin_h diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 451d3a9ab..8c03a7981 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -18,8 +18,8 @@ */ // this file is shared by QuakeForge and qfcc -#ifndef __pr_comp_h -#define __pr_comp_h +#ifndef __QF_pr_comp_h +#define __QF_pr_comp_h #include "QF/qtypes.h" @@ -513,4 +513,4 @@ typedef struct dprograms_s { pr_uint_t entityfields; } dprograms_t; -#endif // __pr_comp_h +#endif//__QF_pr_comp_h diff --git a/include/QF/pr_debug.h b/include/QF/pr_debug.h index d80b9f417..be5e1471d 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/pr_debug.h @@ -28,8 +28,8 @@ */ -#ifndef __pr_debug_h -#define __pr_debug_h +#ifndef __QF_pr_debug_h +#define __QF_pr_debug_h #include "QF/pr_comp.h" @@ -65,4 +65,4 @@ typedef struct pr_debug_header_s { pr_uint_t num_locals; } pr_debug_header_t; -#endif//__pr_debug_h +#endif//__QF_pr_debug_h diff --git a/include/QF/pr_obj.h b/include/QF/pr_obj.h index 5e4f8463c..fa3bbca84 100644 --- a/include/QF/pr_obj.h +++ b/include/QF/pr_obj.h @@ -28,8 +28,8 @@ */ -#ifndef __pr_obj_h -#define __pr_obj_h +#ifndef __QF_pr_obj_h +#define __QF_pr_obj_h #include "QF/pr_comp.h" @@ -185,4 +185,4 @@ typedef struct pr_super_s { pointer_t class; } pr_super_t; -#endif//__pr_obj_h +#endif//__QF_pr_obj_h diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index 39215840f..179a4e407 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -28,8 +28,8 @@ */ -#ifndef __pr_type_h -#define __pr_type_h +#ifndef __QF_pr_type_h +#define __QF_pr_type_h /** \defgroup qfcc_qfo_type Object file type encoding \ingroup progs @@ -121,4 +121,4 @@ typedef struct qfot_type_encodings_s { ///@} -#endif//__pr_type_h +#endif//__QF_pr_type_h diff --git a/include/QF/qargs.h b/include/QF/qargs.h index 50dfbd35a..bf49495a4 100644 --- a/include/QF/qargs.h +++ b/include/QF/qargs.h @@ -27,8 +27,8 @@ */ -#ifndef __qargs_h -#define __qargs_h +#ifndef __QF_qargs_h +#define __QF_qargs_h /** \addtogroup misc */ @@ -52,4 +52,4 @@ void COM_ParseConfig (void); ///@} -#endif // __qargs_h +#endif//__QF_qargs_h diff --git a/include/QF/qdefs.h b/include/QF/qdefs.h index 1d00abee0..a0dbbfe5c 100644 --- a/include/QF/qdefs.h +++ b/include/QF/qdefs.h @@ -27,8 +27,8 @@ */ -#ifndef __qdefs_h -#define __qdefs_h +#ifndef __QF_qdefs_h +#define __QF_qdefs_h #define MAX_QPATH 64 #define MAX_CL_STATS 32 @@ -40,4 +40,4 @@ #define clc_stringcmd 4 -#endif // __qdefs_h +#endif//__QF_qdefs_h diff --git a/include/QF/qendian.h b/include/QF/qendian.h index a42bd749f..7c418be53 100644 --- a/include/QF/qendian.h +++ b/include/QF/qendian.h @@ -27,8 +27,8 @@ */ -#ifndef __qendian_h -#define __qendian_h +#ifndef __QF_qendian_h +#define __QF_qendian_h /** \defgroup qendian Endian handling functions \ingroup utils @@ -120,4 +120,4 @@ unsigned int ReadLong (struct QFile_s *file); ///@} -#endif // __qendian_h +#endif//__QF_qendian_h diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index e0c2557ca..7a12b7c4c 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -25,8 +25,8 @@ */ -#ifndef __QF_qfplist_h_ -#define __QF_qfplist_h_ +#ifndef __QF_qfplist_h +#define __QF_qfplist_h /** \defgroup qfplist Property lists \ingroup utils @@ -228,4 +228,4 @@ void PL_Free (plitem_t *item); ///@} -#endif // __QF_qfplist_h_ +#endif//__QF_qfplist_h diff --git a/include/QF/qtypes.h b/include/QF/qtypes.h index e328ff2fc..ea3a4df6c 100644 --- a/include/QF/qtypes.h +++ b/include/QF/qtypes.h @@ -27,8 +27,8 @@ */ -#ifndef __qtypes_h -#define __qtypes_h +#ifndef __QF_qtypes_h +#define __QF_qtypes_h #include #include @@ -115,4 +115,4 @@ typedef struct sphere_s { vec_t radius; } sphere_t; -#endif // __qtypes_h +#endif//__QF_qtypes_h diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index 364718db0..761997eea 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -27,8 +27,8 @@ */ -#ifndef __quakefs_h -#define __quakefs_h +#ifndef __QF_quakefs_h +#define __QF_quakefs_h /** \defgroup quakefs Quake Filesystem \ingroup utils @@ -420,4 +420,4 @@ void QFS_FilelistFree (filelist_t *list); ///@} -#endif // __quakefs_h +#endif//__QF_quakefs_h diff --git a/include/QF/quakeio.h b/include/QF/quakeio.h index 08b14af69..1fd7205a0 100644 --- a/include/QF/quakeio.h +++ b/include/QF/quakeio.h @@ -26,8 +26,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __quakeio_h -#define __quakeio_h +#ifndef __QF_quakeio_h +#define __QF_quakeio_h #include @@ -62,4 +62,4 @@ const char *Qgetline(QFile *file); ///@} -#endif /*__quakeio_h*/ +#endif//__QF_quakeio_h diff --git a/include/QF/render.h b/include/QF/render.h index cc08c3800..86892e4ec 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -25,8 +25,8 @@ */ -#ifndef __render_h -#define __render_h +#ifndef __QF_render_h +#define __QF_render_h #include "QF/mathlib.h" #include "QF/model.h" @@ -177,4 +177,4 @@ void R_LoadModule (void (*load_gl)(void), struct progs_s; void R_Progs_Init (struct progs_s *pr); -#endif // __render_h +#endif//__QF_render_h diff --git a/include/QF/screen.h b/include/QF/screen.h index 9586e20a1..8dda2deb4 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -26,8 +26,8 @@ */ // screen.h -#ifndef __screen_h -#define __screen_h +#ifndef __QF_screen_h +#define __QF_screen_h #include "QF/qtypes.h" @@ -67,4 +67,4 @@ extern struct qpic_s *scr_turtle; extern struct cvar_s *hud_fps, *hud_time; -#endif // __screen_h +#endif//__QF_screen_h diff --git a/include/QF/sizebuf.h b/include/QF/sizebuf.h index 7f6fc4ac3..08436b1b8 100644 --- a/include/QF/sizebuf.h +++ b/include/QF/sizebuf.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __sizebuf_h -#define __sizebuf_h +#ifndef __QF_sizebuf_h +#define __QF_sizebuf_h /** \defgroup sizebuf Fixed Size Buffers \ingroup utils @@ -53,4 +53,4 @@ void SZ_Print (sizebuf_t *buf, const char *data); // strcats onto the sizebuf ///@} -#endif // __sizebuf_h +#endif//__QF_sizebuf_h diff --git a/include/QF/skin.h b/include/QF/skin.h index b9c8a3dcb..7f520e1d6 100644 --- a/include/QF/skin.h +++ b/include/QF/skin.h @@ -25,8 +25,8 @@ */ -#ifndef _SKIN_H -#define _SKIN_H +#ifndef __QF_skin_h +#define __QF_skin_h #include "QF/qtypes.h" #include "QF/vid.h" @@ -57,4 +57,4 @@ typedef struct skin_s { int auxtex; } skin_t; -#endif +#endif//__QF_skin_h diff --git a/include/QF/sound.h b/include/QF/sound.h index 3382d4b91..9fba9b158 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -26,8 +26,8 @@ */ // sound.h -- client sound i/o functions -#ifndef _SOUND_H -#define _SOUND_H +#ifndef __QF_sound_h +#define __QF_sound_h /** \defgroup sound QuakeForge sound engine */ @@ -195,4 +195,4 @@ void S_Progs_Init (struct progs_s *pr); ///@} -#endif // _SOUND_H +#endif//__QF_sound_h diff --git a/include/QF/spritegn.h b/include/QF/spritegn.h index 4505ad59f..de490f28d 100644 --- a/include/QF/spritegn.h +++ b/include/QF/spritegn.h @@ -45,8 +45,8 @@ // //------------------------------------------------------- -#ifndef _SPRITEGN_H -#define _SPRITEGN_H +#ifndef __QF_sprintgn_h +#define __QF_sprintgn_h #define SPR_VERSION 1 #define SP2_VERSION 2 @@ -102,4 +102,4 @@ typedef struct { // little-endian "IDS2" #define IDHEADER_SP2 (('2'<<24)+('S'<<16)+('D'<<8)+'I') -#endif // _SPRITEGN_H +#endif//__QF_sprintgn_h diff --git a/include/QF/sys.h b/include/QF/sys.h index 76b6ad844..06e2590fa 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -25,8 +25,8 @@ */ -#ifndef __sys_h -#define __sys_h +#ifndef __QF_sys_h +#define __QF_sys_h /** \defgroup sys System Portability \ingroup utils @@ -159,4 +159,4 @@ char *Sys_ExpandSquiggle (const char *path); ///@} -#endif // __sys_h +#endif//__QF_sys_h diff --git a/include/QF/teamplay.h b/include/QF/teamplay.h index bf4ae9445..91b2a6f65 100644 --- a/include/QF/teamplay.h +++ b/include/QF/teamplay.h @@ -25,8 +25,8 @@ */ -#ifndef __teamplay_h -#define __teamplay_h +#ifndef __QF_teamplay_h +#define __QF_teamplay_h extern struct cvar_s *cl_parsesay; extern struct cvar_s *cl_nofake; @@ -47,4 +47,4 @@ const char *Team_ParseSay (struct dstring_s *buf, const char *); void Locs_Init (void); void Team_ParseChat (const char *string); void Team_ResetTimers (void); -#endif // __teamplay_h +#endif//__QF_teamplay_h diff --git a/include/QF/tga.h b/include/QF/tga.h index 1d0bc8c25..365f5d366 100644 --- a/include/QF/tga.h +++ b/include/QF/tga.h @@ -25,8 +25,8 @@ */ -#ifndef __tga_h -#define __tga_h +#ifndef __QF_tga_h +#define __QF_tga_h #include "QF/qtypes.h" #include "QF/quakeio.h" @@ -70,4 +70,4 @@ typedef struct _TargaHeader { struct tex_s *LoadTGA (QFile *fin); void WriteTGAfile (const char *tganame, byte *data, int width, int height); -#endif // __tga_h +#endif//__QF_tga_h diff --git a/include/QF/uint32.h b/include/QF/uint32.h deleted file mode 100644 index 513117d01..000000000 --- a/include/QF/uint32.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - uint32.h - - Definitions for portable (?) unsigned int - - Copyright (C) 2000 Jeff Teunissen - - Author: Jeff Teunissen - Date: 01 Jan 2000 - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ - -#ifndef __uint32_h -#define __uint32_h - -#ifndef int32 -# if (SIZEOF_INT == 4) -# define int32 int -# elif (SIZEOF_LONG == 4) -# define int32 long -# elif (SIZEOF_SHORT == 4) -# define int32 short -# else -/* I hope this works */ -# define int32 int -# define LARGE_INT32 -# endif -#endif - -#ifndef uint32 -# define uint32 unsigned int32 -#endif - -#endif // __uint32_h diff --git a/include/QF/va.h b/include/QF/va.h index 40c794712..1bf0eadaf 100644 --- a/include/QF/va.h +++ b/include/QF/va.h @@ -26,8 +26,8 @@ */ -#ifndef __va_h -#define __va_h +#ifndef __QF_va_h +#define __QF_va_h /** \addtogroup misc Formatted printing. @@ -41,4 +41,4 @@ char *nva(const char *format, ...) __attribute__((format(printf,1,2))); ///@} -#endif // __va_h +#endif//__QF_va_h diff --git a/include/QF/ver_check.h b/include/QF/ver_check.h index 8ac943796..eaa4d9391 100644 --- a/include/QF/ver_check.h +++ b/include/QF/ver_check.h @@ -25,8 +25,8 @@ */ -#ifndef __ver_check_h_ -#define __ver_check_h_ +#ifndef __QF_ver_check_h +#define __QF_ver_check_h /** \defgroup utils Utils */ @@ -47,4 +47,4 @@ int ver_compare (const char *, const char *); ///@} -#endif // __ver_check_h_ +#endif//__QF_ver_check_h diff --git a/include/QF/vid.h b/include/QF/vid.h index 70298fa8b..312da65dd 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -25,8 +25,8 @@ */ -#ifndef __vid_h_ -#define __vid_h_ +#ifndef __QF_vid_h +#define __QF_vid_h #include "QF/qtypes.h" #include "QF/vrect.h" @@ -89,4 +89,4 @@ void VID_Init (byte *palette, byte *colormap); void VID_Shutdown (void); void VID_SetCaption (const char *text); -#endif // __vid_h_ +#endif//__QF_vid_h diff --git a/include/QF/view.h b/include/QF/view.h index 570935ae8..5a6ae339f 100644 --- a/include/QF/view.h +++ b/include/QF/view.h @@ -28,8 +28,8 @@ */ -#ifndef __qf_view_h -#define __qf_view_h +#ifndef __QF_view_h +#define __QF_view_h /** \defgroup console_view Console View Objects \ingroup console @@ -217,4 +217,4 @@ void view_move (view_t *view, int xp, int yp); ///@} -#endif//__qf_view_h +#endif//__QF_view_h diff --git a/include/QF/wad.h b/include/QF/wad.h index 82e836dc9..2e6bb9c67 100644 --- a/include/QF/wad.h +++ b/include/QF/wad.h @@ -26,8 +26,8 @@ */ // wad.h -#ifndef _WAD_H -#define _WAD_H +#ifndef __QF_wad_h +#define __QF_wad_h /** \addtogroup wad Wad Files @@ -48,4 +48,4 @@ void SwapPic (qpic_t *pic); ///@} -#endif // _WAD_H +#endif//__QF_wad_h diff --git a/include/QF/zone.h b/include/QF/zone.h index 1f968737f..10063b2cc 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __zone_h -#define __zone_h +#ifndef __QF_zone_h +#define __QF_zone_h /** \defgroup zone Memory Management \ingroup utils @@ -142,4 +142,4 @@ int Cache_ReadLock (cache_user_t *c) __attribute__((pure)); ///@} -#endif // __zone_h +#endif//__QF_zone_h From f7493fe8fb65a8a356c157185c647f131cf48730 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 17:30:33 +0900 Subject: [PATCH 0398/3664] Add a buffer-gap text buffer This should be good for text editing and working with text files in general. --- include/QF/txtbuffer.h | 98 +++++++++++++ libs/util/Makefile.am | 3 +- libs/util/test/Makefile.am | 6 +- libs/util/test/test-txtbuffer.c | 240 ++++++++++++++++++++++++++++++++ libs/util/txtbuffer.c | 172 +++++++++++++++++++++++ 5 files changed, 517 insertions(+), 2 deletions(-) create mode 100644 include/QF/txtbuffer.h create mode 100644 libs/util/test/test-txtbuffer.c create mode 100644 libs/util/txtbuffer.c diff --git a/include/QF/txtbuffer.h b/include/QF/txtbuffer.h new file mode 100644 index 000000000..e73c7257a --- /dev/null +++ b/include/QF/txtbuffer.h @@ -0,0 +1,98 @@ +/* + txtbuffer.h + + Text buffer for edit or scrollback + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_txtbuffer_h +#define __QF_txtbuffer_h + +#include +#include + +/** \defgroup txtbuffer Text buffers + \ingroup utils +*/ +///@{ + +/// must be a power of 2 +#define TXTBUFFER_GROW 0x4000 + +/** Text buffer implementing efficient editing. +*/ +typedef struct txtbuffer_s { + struct txtbuffer_s *next; + char *text; + size_t textSize; ///< amount of text in the buffer + size_t bufferSize; ///< current capacity of the buffer + size_t gapOffset; ///< beginning of the gap + size_t gapSize; ///< size of gap. gapSize + textSize == bufferSize +} txtbuffer_t; + +/** Create a new, empty buffer. +*/ +txtbuffer_t *TextBuffer_Create (void); + +/** Destroy a buffer, freeing all resources connected to it. + \param buffer The buffer to destroy. +*/ +void TextBuffer_Destroy (txtbuffer_t *buffer); + +/** Insert a block of text at the specified offset. + + Text after the offset is moved to be after the inserted block of text. + The buffer is resized as necessary. + nul characters are not significant in that they do not mark the end of + the text to be inserted. + + \param buffer The buffer to be updated + \param offset The offset in the buffer at which to insert the text block + \param text The text block to be inserted. May contain nul ('\0') + characters. + \param text_len The number of characters to insert. + \return 1 for success, 0 for failure (offset not valid or out + of memory) +*/ +int TextBuffer_InsertAt (txtbuffer_t *buffer, size_t offset, + const char *text, size_t text_len); + +/** Delete a block of text from the buffer. + + The buffer is not resized. Rather, its capacity before resizing is require + is increased. + + \param buffer The buffer to be updated + \param offset The offset of the beginning of the text block to be deleted + \param len The amount of characters to be deleted. Values larger than + the amount of text in the buffer beyond the beginning of + block are truncated to the amount of remaining text. Thus + using excessivly large values sets the offset to be the + end of the buffer. + \return 1 for success, 0 for failure (offset not valid) +*/ +int TextBuffer_DeleteAt (txtbuffer_t *buffer, size_t offset, size_t len); + +///@} + +#endif//__QF_txtbuffer_h diff --git a/libs/util/Makefile.am b/libs/util/Makefile.am index 0c6421450..c35e4e305 100644 --- a/libs/util/Makefile.am +++ b/libs/util/Makefile.am @@ -53,7 +53,8 @@ libQFutil_la_SOURCES= \ fendian.c hash.c idparse.c info.c link.c llist.c \ mathlib.c mdfour.c mersenne.c msg.c pakfile.c plugin.c qargs.c qendian.c \ qfplist.c quakefs.c quakeio.c riff.c script.c segtext.c set.c sizebuf.c \ - string.c sys.c va.c ver_check.c vrect.c wad.c wadfile.c zone.c \ + string.c sys.c txtbuffer.c va.c ver_check.c vrect.c wad.c wadfile.c \ + zone.c \ $(dirent) $(fnmatch) $(getopt) EXTRA_DIST= $(fnmatch_src) $(getopt_src) diff --git a/libs/util/test/Makefile.am b/libs/util/test/Makefile.am index a7bdb5d4e..283ac561e 100644 --- a/libs/util/test/Makefile.am +++ b/libs/util/test/Makefile.am @@ -4,7 +4,7 @@ AM_CPPFLAGS= -I$(top_srcdir)/include check_PROGRAMS= \ test-bary test-cs test-dq test-half test-mat3 test-mat4 test-plist \ - test-qfs test-quat test-seb test-seg test-set test-vrect + test-qfs test-quat test-seb test-seg test-set test-txtbuffer test-vrect test_bary_SOURCES=test-bary.c test_bary_LDADD=$(top_builddir)/libs/util/libQFutil.la @@ -54,6 +54,10 @@ test_set_SOURCES=test-set.c test_set_LDADD=$(top_builddir)/libs/util/libQFutil.la test_set_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la +test_txtbuffer_SOURCES=test-txtbuffer.c +test_txtbuffer_LDADD=$(top_builddir)/libs/util/libQFutil.la +test_txtbuffer_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la + test_vrect_SOURCES=test-vrect.c test_vrect_LDADD=$(top_builddir)/libs/util/libQFutil.la test_vrect_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la diff --git a/libs/util/test/test-txtbuffer.c b/libs/util/test/test-txtbuffer.c new file mode 100644 index 000000000..44ccebdc9 --- /dev/null +++ b/libs/util/test/test-txtbuffer.c @@ -0,0 +1,240 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include + +#include "QF/txtbuffer.h" + +static size_t +check_text_ptr (txtbuffer_t *buffer, size_t offset, const char *txt, + size_t length) +{ + return buffer->text != 0; +} + +static size_t +get_textSize (txtbuffer_t *buffer, size_t offset, const char *txt, + size_t length) +{ + return buffer->textSize; +} + +static size_t +get_bufferSize (txtbuffer_t *buffer, size_t offset, const char *txt, + size_t length) +{ + return buffer->bufferSize; +} + +static size_t +get_gapOffset (txtbuffer_t *buffer, size_t offset, const char *txt, + size_t length) +{ + return buffer->gapOffset; +} + +static size_t +get_gapSize (txtbuffer_t *buffer, size_t offset, const char *txt, + size_t length) +{ + return buffer->gapSize; +} + +static size_t +insert_text (txtbuffer_t *buffer, size_t offset, const char *txt, + size_t length) +{ + if (TextBuffer_InsertAt (buffer, offset, txt, length)) { + memset (buffer->text + buffer->gapOffset, 0xff, buffer->gapSize); + return 1; + } + return 0; +} + +static size_t +delete_text (txtbuffer_t *buffer, size_t offset, const char *txt, + size_t length) +{ + if (TextBuffer_DeleteAt (buffer, offset, length)) { + memset (buffer->text + buffer->gapOffset, 0xff, buffer->gapSize); + return 1; + } + return 0; +} + +static size_t +destroy_buffer (txtbuffer_t *buffer, size_t offset, const char *txt, + size_t length) +{ + TextBuffer_Destroy (buffer); + return 0; +} + +typedef size_t (*test_func) (txtbuffer_t *buffer, size_t offset, + const char *text, size_t length); + +static const char test_text[] = { + "Guarding the entrance to the Grendal\n" + "Gorge is the Shadow Gate, a small keep\n" + "and monastary which was once the home\n" + "of the Shadow cult.\n\n" + "For years the Shadow Gate existed in\n" + "obscurity but after the cult discovered\n" + "the \3023\354\341\343\353\240\307\341\364\345 in the caves below\n" + "the empire took notice.\n" + "A batallion of Imperial Knights were\n" + "sent to the gate to destroy the cult\n" + "and claim the artifact for the King.", +}; +static const char empty[TXTBUFFER_GROW] = { }; + +static size_t +compare_text (txtbuffer_t *buffer, size_t offset, const char *txt, + size_t length) +{ + //printf("%zd %ld %zd\n", offset, txt - test_text, length); + size_t res = memcmp (buffer->text + offset, txt, length) == 0; + if (!res) { + for (size_t i = 0; i < length; i++) { + //printf ("%02x %02x\n", txt[i] & 0xff, buffer->text[offset + i] & 0xff); + } + } + return res; +} + +#define txtsize (sizeof (test_text) - 1) +#define txtsize0 txtsize +#define bufsize0 (TXTBUFFER_GROW) +#define gapoffs0 txtsize0 +#define gapsize0 (bufsize0 - txtsize0) +#define subtxtlen 200 +#define suboffs 200 +#define txtsize1 (txtsize0 + subtxtlen) +#define bufsize1 (TXTBUFFER_GROW) +#define gapoffs1 (suboffs + subtxtlen) +#define gapsize1 (bufsize1 - txtsize1) +#define deltxtlen 350 +#define deloffs 150 +#define txtsize2 (txtsize + subtxtlen - deltxtlen) +#define bufsize2 (TXTBUFFER_GROW) +#define gapoffs2 (deloffs) +#define gapsize2 (bufsize2 - txtsize2) +#define deltxtrem (txtsize2 - gapoffs2) +#define emptyoffs 370 +#define txtsize3 (txtsize + sizeof (empty)) +#define bufsize3 (2 * TXTBUFFER_GROW) +#define gapoffs3 (emptyoffs + sizeof (empty)) +#define gapsize3 (bufsize3 - txtsize3) +#define txtsize4 (txtsize + 2 * sizeof (empty)) +#define bufsize4 (3 * TXTBUFFER_GROW) +#define gapoffs4 (emptyoffs + sizeof (empty)) +#define gapsize4 (bufsize4 - txtsize4) + +struct { + test_func test; + size_t offset_param; + const char *text_param; + size_t length_param; + int test_expect; +} tests[] = { + { check_text_ptr, 0, 0, 0, 0 }, + { get_textSize, 0, 0, 0, 0 }, + { get_bufferSize, 0, 0, 0, 0 }, + { get_gapOffset, 0, 0, 0, 0 }, + { get_gapSize, 0, 0, 0, 0 }, + { insert_text, 0, test_text, txtsize, 1 }, + { get_textSize, 0, 0, 0, txtsize0 }, + { get_bufferSize, 0, 0, 0, bufsize0 }, + { get_gapOffset, 0, 0, 0, gapoffs0 }, + { get_gapSize, 0, 0, 0, gapsize0 }, + { compare_text, 0, test_text, txtsize, 1 }, + { insert_text, suboffs, test_text, subtxtlen, 1 }, + { get_textSize, 0, 0, 0, txtsize1 }, + { get_bufferSize, 0, 0, 0, bufsize1 }, + { get_gapOffset, 0, 0, 0, gapoffs1 }, + { get_gapSize, 0, 0, 0, gapsize1 }, + { compare_text, 0, test_text, txtsize, 0 }, + { compare_text, 0, test_text, suboffs, 1 }, + { compare_text, suboffs, test_text, subtxtlen, 1 }, + { compare_text, gapoffs1 + gapsize1, test_text + subtxtlen, txtsize - subtxtlen, 1 }, + { delete_text, deloffs, 0, deltxtlen, 1 }, + { get_textSize, 0, 0, 0, txtsize2 }, + { get_bufferSize, 0, 0, 0, bufsize2 }, + { get_gapOffset, 0, 0, 0, gapoffs2 }, + { get_gapSize, 0, 0, 0, gapsize2 }, + { compare_text, 0, test_text, suboffs, 0 }, + { compare_text, suboffs, test_text, subtxtlen, 0 }, + { compare_text, gapoffs1 + gapsize1, test_text + subtxtlen, txtsize - subtxtlen, 0 }, + { compare_text, 0, test_text, deloffs, 1 }, + { compare_text, gapoffs2 + gapsize2, test_text + txtsize - deltxtrem, deltxtrem, 1 }, + { compare_text, gapoffs2 + gapsize2 - 1, test_text + txtsize - deltxtrem - 1, 1, 0 }, + { delete_text, 0, 0, -1, 1 }, + { check_text_ptr, 0, 0, 0, 1 }, + { get_textSize, 0, 0, 0, 0 }, + { get_bufferSize, 0, 0, 0, bufsize2 }, + { get_gapOffset, 0, 0, 0, 0 }, + { get_gapSize, 0, 0, 0, bufsize2 }, + { insert_text, 1, test_text, txtsize, 0 }, + { get_textSize, 0, 0, 0, 0 }, + { get_bufferSize, 0, 0, 0, bufsize2 }, + { get_gapOffset, 0, 0, 0, 0 }, + { get_gapSize, 0, 0, 0, bufsize2 }, + { insert_text, 0, test_text, txtsize, 1 }, + { insert_text, 300, 0, 0, 1 }, + { get_textSize, 0, 0, 0, txtsize0 }, + { get_bufferSize, 0, 0, 0, bufsize2 }, + { get_gapOffset, 0, 0, 0, 300 }, + { get_gapSize, 0, 0, 0, gapsize0 }, + { compare_text, 0, test_text, 300, 1 }, + { compare_text, 300, test_text + 300, 1, 0 }, + { compare_text, 300 + gapsize0, test_text + 300, txtsize - 300, 1 }, + { compare_text, 300 + gapsize0 - 1, test_text + 300 - 1, 1, 0 }, + { insert_text, 350, 0, 0, 1 }, + { compare_text, (emptyoffs - 20) + gapsize0, test_text + (emptyoffs - 20), txtsize - (emptyoffs - 20), 1 }, + { get_textSize, 0, 0, 0, txtsize0 }, + { get_bufferSize, 0, 0, 0, bufsize2 }, + { get_gapOffset, 0, 0, 0, (emptyoffs - 20) }, + { get_gapSize, 0, 0, 0, gapsize0 }, + { insert_text, emptyoffs, empty, sizeof (empty), 1 }, + { get_textSize, 0, 0, 0, txtsize3 }, + { get_bufferSize, 0, 0, 0, bufsize3 }, + { get_gapOffset, 0, 0, 0, gapoffs3 }, + { get_gapSize, 0, 0, 0, gapsize3 }, + { insert_text, emptyoffs, empty, sizeof (empty), 1 }, + { get_textSize, 0, 0, 0, txtsize4 }, + { get_bufferSize, 0, 0, 0, bufsize4 }, + { get_gapOffset, 0, 0, 0, gapoffs4 }, + { get_gapSize, 0, 0, 0, gapsize4 }, + { destroy_buffer, 0, 0, 0, 0 }, +}; +#define num_tests (sizeof (tests) / sizeof (tests[0])) +int test_start_line = __LINE__ - num_tests - 2; + +int +main (int argc, const char **argv) +{ + size_t i; + int res = 0; + + txtbuffer_t *buffer = TextBuffer_Create (); + + for (i = 0; i < num_tests; i++) { + if (tests[i].test) { + int test_res; + test_res = tests[i].test (buffer, + tests[i].offset_param, + tests[i].text_param, + tests[i].length_param); + if (test_res != tests[i].test_expect) { + res |= 1; + printf ("test %d (line %d) failed\n", (int) i, + (int) i + test_start_line); + printf ("expect: %d\n", tests[i].test_expect); + printf ("got : %d\n", test_res); + continue; + } + } + } + return res; +} diff --git a/libs/util/txtbuffer.c b/libs/util/txtbuffer.c new file mode 100644 index 000000000..03ad06500 --- /dev/null +++ b/libs/util/txtbuffer.c @@ -0,0 +1,172 @@ +/* + txtbuffer.c + + Text buffer + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/alloc.h" +#include "QF/qtypes.h" +#include "QF/sys.h" +#include "QF/txtbuffer.h" + +#include "compat.h" + +static txtbuffer_t *txtbuffers_freelist; + +static char * +txtbuffer_open_gap (txtbuffer_t *buffer, size_t offset, size_t length) +{ + size_t len; + char *dst; + char *src; + + if (offset == buffer->gapOffset && length <= buffer->gapSize) { + return buffer->text + buffer->gapOffset; + } + if (length <= buffer->gapSize) { + // no resize needed + if (offset < buffer->gapOffset) { + len = buffer->gapOffset - offset; + dst = buffer->text + buffer->gapOffset + buffer->gapSize - len; + src = buffer->text + offset; + } else { + len = offset - buffer->gapOffset; + dst = buffer->text + buffer->gapOffset; + src = buffer->text + buffer->gapOffset + buffer->gapSize; + } + memmove (dst, src, len); + } else { + // need to resize the buffer + // grow the buffer by the difference in lengths rounded up to the + // next multiple of TXTBUFFER_GROW + size_t new_size = buffer->bufferSize + length - buffer->gapSize; + new_size = (new_size + TXTBUFFER_GROW - 1) & ~(TXTBUFFER_GROW - 1); + char *new_text = realloc (buffer->text, new_size); + + if (!new_text) { + return 0; + } + buffer->text = new_text; + + if (offset < buffer->gapOffset) { + // move the old post-gap to the end of the new buffer + len = buffer->bufferSize - (buffer->gapOffset + buffer->gapSize); + dst = buffer->text + new_size - len; + src = buffer->text + buffer->gapOffset + buffer->gapSize; + memmove (dst, src, len); + // move the remaining chunk to after the end of the new gap or + // just before the location of the previous move + len = buffer->gapOffset - offset; + dst -= len; + src = buffer->text + offset; + memmove (dst, src, len); + } else if (offset > buffer->gapOffset) { + // move the old post-offset to the end of the new buffer + len = buffer->bufferSize - (offset + buffer->gapSize); + dst = buffer->text + new_size - len; + src = buffer->text + offset + buffer->gapSize; + memmove (dst, src, len); + // move the old post-gap to offset block to before the new gap + len = offset - buffer->gapOffset; + dst = buffer->text + buffer->gapOffset; + src = buffer->text + buffer->gapOffset + buffer->gapSize; + memmove (dst, src, len); + } else { + // the gap only grew, did not move + len = buffer->bufferSize - (offset + buffer->gapSize); + dst = buffer->text + new_size - len; + src = buffer->text + buffer->gapOffset + buffer->gapSize; + memmove (dst, src, len); + } + buffer->gapSize += new_size - buffer->bufferSize; + buffer->bufferSize = new_size; + } + buffer->gapOffset = offset; + return buffer->text + buffer->gapOffset; +} + +VISIBLE txtbuffer_t * +TextBuffer_Create (void) +{ + txtbuffer_t *buffer; + ALLOC (16, txtbuffer_t, txtbuffers, buffer); + return buffer; +} + +VISIBLE void +TextBuffer_Destroy (txtbuffer_t *buffer) +{ + if (buffer->text) { + free (buffer->text); + } + FREE (txtbuffers, buffer); +} + +VISIBLE int +TextBuffer_InsertAt (txtbuffer_t *buffer, size_t offset, + const char *text, size_t text_len) +{ + char *dst; + + if (offset > buffer->textSize) { + return 0; + } + dst = txtbuffer_open_gap (buffer, offset, text_len); + if (!dst) { + return 0; + } + memcpy (dst, text, text_len); + buffer->textSize += text_len; + buffer->gapOffset += text_len; + buffer->gapSize -= text_len; + return 1; +} + +VISIBLE int +TextBuffer_DeleteAt (txtbuffer_t *buffer, size_t offset, size_t len) +{ + if (offset > buffer->textSize) { + return 0; + } + // only moves, does not resize, the gap if necessary + txtbuffer_open_gap (buffer, offset, buffer->gapSize); + // clamp len to the amount of text beyond offset + if (len > buffer->textSize - offset) { + len = buffer->textSize - offset; + } + // delete the text + buffer->gapSize += len; + buffer->textSize -= len; + return 1; +} From 3720956d8884d0aee329f79ab66237fcbed4192e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Feb 2020 18:52:46 +0900 Subject: [PATCH 0399/3664] Speed up two of the three deletion cases The initial code was pretty much a port of the code in the editor I wrote 25 years ago. Either I didn't think of the optimization back then, or I tried to implement it, failed, and figured it wasn't worth it (despite using it on a 386dx33). However, I noticed it now and it was easy enough to get working, and it's always good to not do something that's not needed. --- libs/util/txtbuffer.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/libs/util/txtbuffer.c b/libs/util/txtbuffer.c index 03ad06500..59ee0da16 100644 --- a/libs/util/txtbuffer.c +++ b/libs/util/txtbuffer.c @@ -116,6 +116,32 @@ txtbuffer_open_gap (txtbuffer_t *buffer, size_t offset, size_t length) return buffer->text + buffer->gapOffset; } +static char * +txtbuffer_delete_text (txtbuffer_t *buffer, size_t offset, size_t length) +{ + size_t len; + char *dst; + char *src; + + if (offset > buffer->gapOffset) { + len = offset - buffer->gapOffset; + dst = buffer->text + buffer->gapOffset; + src = buffer->text + buffer->gapOffset + buffer->gapSize; + memmove (dst, src, len); + } else if (offset + length < buffer->gapOffset) { + len = buffer->gapOffset - (offset + length); + dst = buffer->text + buffer->gapSize + (offset + length); + src = buffer->text + (offset + length); + memmove (dst, src, len); + } + // don't need to do any copying when offset <= gapOffset && + // offset + length >= offset + buffer->gapOffset = offset; + buffer->gapSize += length; + buffer->textSize -= length; + return buffer->text + buffer->gapOffset; +} + VISIBLE txtbuffer_t * TextBuffer_Create (void) { @@ -159,14 +185,10 @@ TextBuffer_DeleteAt (txtbuffer_t *buffer, size_t offset, size_t len) if (offset > buffer->textSize) { return 0; } - // only moves, does not resize, the gap if necessary - txtbuffer_open_gap (buffer, offset, buffer->gapSize); // clamp len to the amount of text beyond offset if (len > buffer->textSize - offset) { len = buffer->textSize - offset; } - // delete the text - buffer->gapSize += len; - buffer->textSize -= len; + txtbuffer_delete_text (buffer, offset, len); return 1; } From c51c9edd9d1cdf2b374727be0d0b3a06926c50d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 00:11:01 +0900 Subject: [PATCH 0400/3664] Fix incorrect encoding of local defs --- tools/qfcc/source/obj_file.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 855e48b61..d1c5296c4 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -1178,7 +1178,6 @@ qfo_to_sym (qfo_t *qfo, int *size) aux->local_defs = ld - locals; for (j = 0; j < num_locals; j++, def++, ld++) { ld->type = get_def_type (qfo, def->type); - ld->type = def->type; ld->ofs = def->offset; ld->name = def->name; ld->type_encoding = def->type; From 1cfac0f11a785ff1d1556b2110845f161301a042 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 00:12:02 +0900 Subject: [PATCH 0401/3664] Resolve local def type encodings They need to be resolved at load-time. --- tools/qfcc/source/dump_globals.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index ea94f5d9d..ea52bd8f6 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -234,6 +234,13 @@ dump_functions (progs_t *pr) const char *name; int start, count; const char *comment; + pr_def_t *encodings_def; + pointer_t type_encodings = 0; + + encodings_def = PR_FindGlobal (pr, ".type_encodings"); + if (encodings_def) { + type_encodings = encodings_def->ofs; + } for (i = 0; i < pr->progs->numfunctions; i++) { dfunction_t *func = &pr->pr_functions[i]; @@ -256,7 +263,7 @@ dump_functions (progs_t *pr) func->parm_size[j].size); printf (") %d @ %x", func->locals, func->parm_start); puts (""); - if (pr->debug) { + if (pr->debug && type_encodings) { pr_auxfunction_t *aux = pr->auxfunction_map[i]; if (!aux) continue; @@ -265,8 +272,11 @@ dump_functions (progs_t *pr) aux->line_info, aux->local_defs, aux->num_locals, aux->return_type); - for (j = 0; j < (int)aux->num_locals; j++) + for (j = 0; j < (int)aux->num_locals; j++) { + pr->local_defs[+ aux->local_defs + j].type_encoding + += type_encodings; dump_def (pr, pr->local_defs + aux->local_defs + j, 1); + } } } } From 256dee98a17d9264dceec38c730d41ad53474c64 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 00:21:56 +0900 Subject: [PATCH 0402/3664] Make progs string resources management private Strangely enough, using the progs resources system. This is a step towards having progs that can be reset properly, or even dynamically created VMs. --- include/QF/progs.h | 25 +--- libs/gamecode/pr_load.c | 3 +- libs/gamecode/pr_strings.c | 231 +++++++++++++++++++++--------------- tools/qfcc/source/qfprogs.c | 1 - 4 files changed, 141 insertions(+), 119 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index d007ac81f..25f81f2b5 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1146,12 +1146,12 @@ int PR_RelocateBuiltins (progs_t *pr); */ ///@{ -/** Initialize the string tables using the strings supplied by the progs. - Called automatically during progs load. - \param pr pointer to ::progs_t VM struct - \return true for success, false for failure +/** Initialize the string management subsystem. + + \param pr The VM of which the string management subsystem will be + initialized; */ -int PR_LoadStrings (progs_t *pr); +void PR_Strings_Init (progs_t *pr); /** Check the validity of a string index. \param pr pointer to ::progs_t VM struct @@ -1230,11 +1230,6 @@ string_t PR_NewMutableString (progs_t *pr); */ string_t PR_SetDynamicString (progs_t *pr, const char *s); -/** Clear all of the return string slots. Called at progs load. - \param pr pointer to ::progs_t VM struct -*/ -void PR_ClearReturnStrings (progs_t *pr); - /** Destroy a mutable, dynamic or temporary string. \param pr pointer to ::progs_t VM struct \param str string index of the string to be destroyed @@ -1644,15 +1639,7 @@ struct progs_s { /// \name string management ///@{ - struct dstring_mem_s *ds_mem; - strref_t *free_string_refs; - strref_t *static_strings; - strref_t **string_map; - strref_t *return_strings[PR_RS_SLOTS]; - int rs_slot; - unsigned dyn_str_size; - struct hashtab_s *strref_hash; - int num_strings; + struct prstr_resources_s *pr_string_resources; strref_t *pr_xtstr; int float_promoted; ///< for PR_Sprintf ///@} diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 994e9b581..a156e99c8 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -133,7 +133,6 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->free_progs_mem = free_progs_mem; PR_Resources_Clear (pr); - PR_ClearReturnStrings (pr); if (pr->progs) pr->free_progs_mem (pr, pr->progs); pr->progs = 0; @@ -374,7 +373,6 @@ pr_run_ctors (progs_t *pr) } static int (*load_funcs_1[])(progs_t *) = { - PR_LoadStrings, PR_RelocateBuiltins, PR_LoadDebug, 0, @@ -472,6 +470,7 @@ PR_Init (progs_t *pr) { PR_Opcode_Init (); // idempotent PR_Resources_Init (pr); + PR_Strings_Init (pr); PR_Debug_Init (pr); } diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 85602e3d2..a8c8c4fee 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -44,6 +44,19 @@ #include "QF/progs.h" #include "QF/va.h" +typedef struct prstr_resources_s { + progs_t *pr; + dstring_mem_t ds_mem; + strref_t *free_string_refs; + strref_t *static_strings; + strref_t **string_map; + strref_t *return_strings[PR_RS_SLOTS]; + int rs_slot; + unsigned dyn_str_size; + struct hashtab_s *strref_hash; + int num_strings; +} prstr_resources_t; + typedef enum { str_free, str_static, @@ -111,51 +124,51 @@ pr_strings_realloc (void *_pr, void *ptr, size_t size) } static strref_t * -new_string_ref (progs_t *pr) +new_string_ref (prstr_resources_t *res) { strref_t *sr; - if (!pr->free_string_refs) { + if (!res->free_string_refs) { int i; size_t size; - pr->dyn_str_size++; - size = pr->dyn_str_size * sizeof (strref_t *); - pr->string_map = realloc (pr->string_map, size); - if (!pr->string_map) - PR_Error (pr, "out of memory"); - if (!(pr->free_string_refs = calloc (1024, sizeof (strref_t)))) - PR_Error (pr, "out of memory"); - pr->string_map[pr->dyn_str_size - 1] = pr->free_string_refs; - for (i = 0, sr = pr->free_string_refs; i < 1023; i++, sr++) + res->dyn_str_size++; + size = res->dyn_str_size * sizeof (strref_t *); + res->string_map = realloc (res->string_map, size); + if (!res->string_map) + PR_Error (res->pr, "out of memory"); + if (!(res->free_string_refs = calloc (1024, sizeof (strref_t)))) + PR_Error (res->pr, "out of memory"); + res->string_map[res->dyn_str_size - 1] = res->free_string_refs; + for (i = 0, sr = res->free_string_refs; i < 1023; i++, sr++) sr->next = sr + 1; sr->next = 0; } - sr = pr->free_string_refs; - pr->free_string_refs = sr->next; + sr = res->free_string_refs; + res->free_string_refs = sr->next; sr->next = 0; return sr; } static void -free_string_ref (progs_t *pr, strref_t *sr) +free_string_ref (prstr_resources_t *res, strref_t *sr) { sr->type = str_free; if (sr->prev) *sr->prev = sr->next; - sr->next = pr->free_string_refs; - pr->free_string_refs = sr; + sr->next = res->free_string_refs; + res->free_string_refs = sr; } static __attribute__((pure)) string_t -string_index (progs_t *pr, strref_t *sr) +string_index (prstr_resources_t *res, strref_t *sr) { - long o = (long) (sr - pr->static_strings); + long o = (long) (sr - res->static_strings); unsigned i; - if (o >= 0 && o < pr->num_strings) - return sr->s.string - pr->pr_strings; - for (i = 0; i < pr->dyn_str_size; i++) { - int d = sr - pr->string_map[i]; + if (o >= 0 && o < res->num_strings) + return sr->s.string - res->pr->pr_strings; + for (i = 0; i < res->dyn_str_size; i++) { + int d = sr - res->string_map[i]; if (d >= 0 && d < 1024) return ~(i * 1024 + d); } @@ -172,24 +185,44 @@ strref_get_key (const void *_sr, void *notused) } static void -strref_free (void *_sr, void *_pr) +strref_free (void *_sr, void *_res) { - progs_t *pr = (progs_t*)_pr; - strref_t *sr = (strref_t*)_sr; + __auto_type res = (prstr_resources_t *) _res; + __auto_type sr = (strref_t *) _sr; // Since this is called only by Hash_FlushTable, the memory pointed // to by sr->string or sr->dstring has already been lost in the progs // load/reload and thus there's no need to free it. // free the string and ref only if it's not a static string - if (sr < pr->static_strings || sr >= pr->static_strings + pr->num_strings) { - free_string_ref (pr, sr); + if (sr < res->static_strings + || sr >= res->static_strings + res->num_strings) { + free_string_ref (res, sr); } } -VISIBLE int +static void +pr_strings_clear (progs_t *pr, void *data) +{ + __auto_type res = (prstr_resources_t *) data; + int i; + + for (i = 0; i < PR_RS_SLOTS; i++) { + if (res->return_strings[i]) + free_string_ref (res, res->return_strings[i]); + res->return_strings[i] = 0; + } + res->rs_slot = 0; + + pr->pr_string_resources = res; + pr->pr_xtstr = 0; +} + +static int PR_LoadStrings (progs_t *pr) { + prstr_resources_t *res = PR_Resources_Find (pr, "Strings"); + char *end = pr->pr_strings + pr->progs->numstrings; char *str = pr->pr_strings; int count = 0; @@ -199,43 +232,41 @@ PR_LoadStrings (progs_t *pr) str += strlen (str) + 1; } - if (!pr->ds_mem) { - pr->ds_mem = malloc (sizeof (dstring_mem_t)); - pr->ds_mem->alloc = pr_strings_alloc; - pr->ds_mem->free = pr_strings_free; - pr->ds_mem->realloc = pr_strings_realloc; - pr->ds_mem->data = pr; - } - if (pr->strref_hash) { - Hash_FlushTable (pr->strref_hash); + res->ds_mem.alloc = pr_strings_alloc; + res->ds_mem.free = pr_strings_free; + res->ds_mem.realloc = pr_strings_realloc; + res->ds_mem.data = pr; + + if (res->strref_hash) { + Hash_FlushTable (res->strref_hash); } else { - pr->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free, - pr); - pr->string_map = 0; - pr->free_string_refs = 0; - pr->dyn_str_size = 0; + res->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free, + res); + res->string_map = 0; + res->free_string_refs = 0; + res->dyn_str_size = 0; } - if (pr->static_strings) - free (pr->static_strings); - pr->static_strings = malloc (count * sizeof (strref_t)); + if (res->static_strings) + free (res->static_strings); + res->static_strings = malloc (count * sizeof (strref_t)); count = 0; str = pr->pr_strings; while (str < end) { - if (!Hash_Find (pr->strref_hash, str)) { - pr->static_strings[count].type = str_static; - pr->static_strings[count].s.string = str; - Hash_Add (pr->strref_hash, &pr->static_strings[count]); + if (!Hash_Find (res->strref_hash, str)) { + res->static_strings[count].type = str_static; + res->static_strings[count].s.string = str; + Hash_Add (res->strref_hash, &res->static_strings[count]); count++; } str += strlen (str) + 1; } - pr->num_strings = count; + res->num_strings = count; return 1; } static inline strref_t * -get_strref (progs_t *pr, string_t num) +get_strref (prstr_resources_t *res, string_t num) { if (num < 0) { strref_t *ref; @@ -243,9 +274,9 @@ get_strref (progs_t *pr, string_t num) num = ~num % 1024; - if (row >= pr->dyn_str_size) + if (row >= res->dyn_str_size) return 0; - ref = &pr->string_map[row][num]; + ref = &res->string_map[row][num]; if (ref->type == str_free) return 0; return ref; @@ -257,7 +288,7 @@ static inline __attribute__((pure)) const char * get_string (progs_t *pr, string_t num) { if (num < 0) { - strref_t *ref = get_strref (pr, num); + strref_t *ref = get_strref (pr->pr_string_resources, num); if (!ref) return 0; switch (ref->type) { @@ -299,7 +330,7 @@ PR_GetString (progs_t *pr, string_t num) VISIBLE dstring_t * PR_GetMutableString (progs_t *pr, string_t num) { - strref_t *ref = get_strref (pr, num); + strref_t *ref = get_strref (pr->pr_string_resources, num); if (ref) { if (ref->type == str_mutable) return ref->s.dstring; @@ -331,70 +362,60 @@ pr_strdup (progs_t *pr, const char *s) VISIBLE string_t PR_SetString (progs_t *pr, const char *s) { + prstr_resources_t *res = pr->pr_string_resources; strref_t *sr; if (!s) s = ""; - sr = Hash_Find (pr->strref_hash, s); + sr = Hash_Find (res->strref_hash, s); if (__builtin_expect (!sr, 1)) { - sr = new_string_ref (pr); + sr = new_string_ref (res); sr->type = str_static; sr->s.string = pr_strdup(pr, s); - Hash_Add (pr->strref_hash, sr); - } - return string_index (pr, sr); -} - -void -PR_ClearReturnStrings (progs_t *pr) -{ - int i; - - for (i = 0; i < PR_RS_SLOTS; i++) { - if (pr->return_strings[i]) - free_string_ref (pr, pr->return_strings[i]); - pr->return_strings[i] = 0; + Hash_Add (res->strref_hash, sr); } + return string_index (res, sr); } VISIBLE string_t PR_SetReturnString (progs_t *pr, const char *s) { + prstr_resources_t *res = pr->pr_string_resources; strref_t *sr; if (!s) s = ""; - if ((sr = Hash_Find (pr->strref_hash, s))) { - return string_index (pr, sr); + if ((sr = Hash_Find (res->strref_hash, s))) { + return string_index (res, sr); } - if ((sr = pr->return_strings[pr->rs_slot])) { + if ((sr = res->return_strings[res->rs_slot])) { if (sr->type != str_return) PR_Error (pr, "internal string error"); pr_strfree (pr, sr->s.string); } else { - sr = new_string_ref (pr); + sr = new_string_ref (res); } sr->type = str_return; sr->s.string = pr_strdup(pr, s); - pr->return_strings[pr->rs_slot++] = sr; - pr->rs_slot %= PR_RS_SLOTS; - return string_index (pr, sr); + res->return_strings[res->rs_slot++] = sr; + res->rs_slot %= PR_RS_SLOTS; + return string_index (res, sr); } static inline string_t -pr_settempstring (progs_t *pr, char *s) +pr_settempstring (progs_t *pr, prstr_resources_t *res, char *s) { strref_t *sr; - sr = new_string_ref (pr); + sr = new_string_ref (res); sr->type = str_temp; sr->s.string = s; sr->next = pr->pr_xtstr; pr->pr_xtstr = sr; - return string_index (pr, sr); + return string_index (res, sr); } VISIBLE string_t @@ -410,46 +431,49 @@ PR_CatStrings (progs_t *pr, const char *a, const char *b) strcpy (c, a); strcpy (c + lena, b); - return pr_settempstring (pr, c); + return pr_settempstring (pr, pr->pr_string_resources, c); } VISIBLE string_t PR_SetTempString (progs_t *pr, const char *s) { + prstr_resources_t *res = pr->pr_string_resources; strref_t *sr; if (!s) return PR_SetString (pr, ""); - if ((sr = Hash_Find (pr->strref_hash, s))) { - return string_index (pr, sr); + if ((sr = Hash_Find (res->strref_hash, s))) { + return string_index (res, sr); } - return pr_settempstring (pr, pr_strdup (pr, s)); + return pr_settempstring (pr, res, pr_strdup (pr, s)); } VISIBLE string_t PR_SetDynamicString (progs_t *pr, const char *s) { + prstr_resources_t *res = pr->pr_string_resources; strref_t *sr; if (!s) return PR_SetString (pr, ""); - if ((sr = Hash_Find (pr->strref_hash, s))) { - return string_index (pr, sr); + if ((sr = Hash_Find (res->strref_hash, s))) { + return string_index (res, sr); } - sr = new_string_ref (pr); + sr = new_string_ref (res); sr->type = str_dynamic; sr->s.string = pr_strdup (pr, s); - return string_index (pr, sr); + return string_index (res, sr); } void PR_MakeTempString (progs_t *pr, string_t str) { - strref_t *sr = get_strref (pr, str); + prstr_resources_t *res = pr->pr_string_resources; + strref_t *sr = get_strref (res, str); if (!sr) PR_RunError (pr, "invalid string %d", str); @@ -470,16 +494,18 @@ PR_MakeTempString (progs_t *pr, string_t str) VISIBLE string_t PR_NewMutableString (progs_t *pr) { - strref_t *sr = new_string_ref (pr); + prstr_resources_t *res = pr->pr_string_resources; + strref_t *sr = new_string_ref (res); sr->type = str_mutable; - sr->s.dstring = _dstring_newstr (pr->ds_mem); - return string_index (pr, sr); + sr->s.dstring = _dstring_newstr (&res->ds_mem); + return string_index (res, sr); } VISIBLE void PR_FreeString (progs_t *pr, string_t str) { - strref_t *sr = get_strref (pr, str); + prstr_resources_t *res = pr->pr_string_resources; + strref_t *sr = get_strref (res, str); if (sr) { switch (sr->type) { @@ -496,7 +522,7 @@ PR_FreeString (progs_t *pr, string_t str) default: PR_Error (pr, "internal string error"); } - free_string_ref (pr, sr); + free_string_ref (res, sr); return; } if (!get_string (pr, str)) @@ -506,20 +532,21 @@ PR_FreeString (progs_t *pr, string_t str) void PR_FreeTempStrings (progs_t *pr) { + prstr_resources_t *res = pr->pr_string_resources; strref_t *sr, *t; for (sr = pr->pr_xtstr; sr; sr = t) { t = sr->next; if (sr->type != str_temp) PR_Error (pr, "internal string error"); - if (R_STRING (pr) < 0 && string_index (pr, sr) == R_STRING (pr) + if (R_STRING (pr) < 0 && string_index (res, sr) == R_STRING (pr) && pr->pr_depth) { prstack_t *frame = pr->pr_stack + pr->pr_depth - 1; sr->next = frame->tstr; frame->tstr = sr; } else { pr_strfree (pr, sr->s.string); - free_string_ref (pr, sr); + free_string_ref (res, sr); } } pr->pr_xtstr = 0; @@ -881,3 +908,13 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, error: PR_RunError (pr, "%s: %s", name, msg); } + +void +PR_Strings_Init (progs_t *pr) +{ + prstr_resources_t *res = calloc (1, sizeof (*res)); + res->pr = pr; + + PR_Resources_Register (pr, "Strings", res, pr_strings_clear); + PR_AddLoadFunc (pr, PR_LoadStrings); +} diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 64dab879a..37acd11fc 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -287,7 +287,6 @@ load_progs (const char *name) if (!pr.progs) return 0; - PR_LoadStrings (&pr); PR_ResolveGlobals (&pr); PR_LoadDebug (&pr); } From 99c818adccd15a5e823c41ac38427196ff60c71d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 00:25:24 +0900 Subject: [PATCH 0403/3664] Ensure progs zone is always set on load --- libs/gamecode/pr_load.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index a156e99c8..1178fe039 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -212,6 +212,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); } + pr->zone = 0; if (pr->zone_size) { //FIXME zone_size needs to be at least as big as memzone_t, but //memzone_t is opaque so its size is unknown From 9bb68f2d8c047a410651d97cf814bb0c9952a82c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 14:30:26 +0900 Subject: [PATCH 0404/3664] Allow nested use of PR_SaveParams() PR_SaveParams() is required for implementing the +initialize diversion used by Objective-QuakeC because builtins do not have local def spaces (of course, a normal stack calling convention would help). However, it is entirely possible for a call to +initialize to trigger another call to +initialize, thus the need for stacking parameter stashes. As a bonus, this implementation cleans up some fields in progs_t. --- include/QF/progs.h | 59 +++++++++++++++++++++++++++++++++----- libs/gamecode/pr_exec.c | 31 +++++++++++--------- libs/gamecode/pr_resolve.c | 4 --- libs/ruamoko/rua_obj.c | 4 +-- 4 files changed, 71 insertions(+), 27 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 25f81f2b5..1162625ac 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -91,15 +91,63 @@ void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(pri (pr)->pr_params[1] = (pr)->pr_real_params[1]; \ } while (0) -/** Save the current parameters. - \param pr pointer to ::progs_t VM struct +/** \name Detouring Function Calls + + These functions allow a builtin function that uses PR_CallFunction() to + safely insert a call to another VM function. The +initialize diversion + required by Objective-QuakeC uses this. + + PR_PushFrame (pr); + __auto_type params = PR_SaveParams (pr); + ... set up parameters to detour_function + PR_ExecuteProgram (pr, detour_function) + PR_RestoreParams (pr, params); + PR_PopFrame (pr); + */ -void PR_SaveParams (progs_t *pr); +///@{ +typedef struct pr_stashed_params_s { + pr_type_t *param_ptrs[2]; + int argc; + pr_type_t params[1]; +} pr_stashed_params_t; + +/** Save the current parameters to the provided stash. + + \warning The memory for the parameter stash is allocated using + alloca(). + + \param pr pointer to ::progs_t VM struct + \return Pointer to a newly allocated and initialized parameter + stash that has the current parameters saved to it. + \hideinitializer +*/ +#define PR_SaveParams(pr) \ + _PR_SaveParams((pr), \ + alloca (field_offset (pr_stashed_params_t, \ + params[(pr)->pr_argc \ + * (pr)->pr_param_size]))) + +/** [INTERNAL] Save the current parameters to the provided stash. + + \warning Requires \a params to be correctly allocated. Use + PR_SaveParams instead as it will create a suitable stash for + saving the parameters. + + \param pr pointer to ::progs_t VM struct + \param params location to save the parameters, must be of adequade size + to hold \a pr_argc * \a pr_param_size words in \a params + \return \a params Allows the likes of: + __auto_type params = PR_SaveParams (pr); +*/ +pr_stashed_params_t *_PR_SaveParams (progs_t *pr, pr_stashed_params_t *params); /** Restore the parameters saved by PR_SaveParams(). \param pr pointer to ::progs_t VM struct + \param params pointer to stash created by PR_SaveParams() */ -void PR_RestoreParams (progs_t *pr); +void PR_RestoreParams (progs_t *pr, pr_stashed_params_t *params); +///@} /** Push an execution frame onto the VM stack. Saves current execution state. \param pr pointer to ::progs_t VM struct @@ -1662,9 +1710,6 @@ struct progs_s { pr_type_t *pr_return; pr_type_t *pr_params[MAX_PARMS]; pr_type_t *pr_real_params[MAX_PARMS]; - pr_type_t *pr_param_ptrs[2]; - pr_type_t *pr_saved_params; - int pr_saved_argc; int pr_param_size; ///< covers both params and return int pr_param_alignment; ///< covers both params and return ///@} diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index f7becdfa5..e7e9d28eb 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -72,37 +72,40 @@ PR_RunError (progs_t * pr, const char *error, ...) PR_Error (pr, "Program error: %s", string->str); } -VISIBLE void -PR_SaveParams (progs_t *pr) +VISIBLE pr_stashed_params_t * +_PR_SaveParams (progs_t *pr, pr_stashed_params_t *params) { int i; int size = pr->pr_param_size * sizeof (pr_type_t); - pr->pr_param_ptrs[0] = pr->pr_params[0]; - pr->pr_param_ptrs[1] = pr->pr_params[1]; + params->param_ptrs[0] = pr->pr_params[0]; + params->param_ptrs[1] = pr->pr_params[1]; pr->pr_params[0] = pr->pr_real_params[0]; pr->pr_params[1] = pr->pr_real_params[1]; for (i = 0; i < pr->pr_argc; i++) { - memcpy (pr->pr_saved_params + i * pr->pr_param_size, + memcpy (params->params + i * pr->pr_param_size, pr->pr_real_params[i], size); - if (i < 2) - memcpy (pr->pr_real_params[i], pr->pr_param_ptrs[0], size); + if (i < 2) { //XXX FIXME what the what?!? + memcpy (pr->pr_real_params[i], params->param_ptrs[0], size); + } } - pr->pr_saved_argc = pr->pr_argc; + params->argc = pr->pr_argc; + return params; } VISIBLE void -PR_RestoreParams (progs_t *pr) +PR_RestoreParams (progs_t *pr, pr_stashed_params_t *params) { int i; int size = pr->pr_param_size * sizeof (pr_type_t); - pr->pr_params[0] = pr->pr_param_ptrs[0]; - pr->pr_params[1] = pr->pr_param_ptrs[1]; - pr->pr_argc = pr->pr_saved_argc; - for (i = 0; i < pr->pr_argc; i++) + pr->pr_params[0] = params->param_ptrs[0]; + pr->pr_params[1] = params->param_ptrs[1]; + pr->pr_argc = params->argc; + for (i = 0; i < pr->pr_argc; i++) { memcpy (pr->pr_real_params[i], - pr->pr_saved_params + i * pr->pr_param_size, size); + params->params + i * pr->pr_param_size, size); + } } VISIBLE inline void diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 07ef44d60..0f7acaa8f 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -139,10 +139,6 @@ PR_ResolveGlobals (progs_t *pr) goto error; pr->pr_param_alignment = G_INT (pr, def->ofs); } - if (pr->pr_saved_params) - free (pr->pr_saved_params); - pr->pr_saved_params = calloc (pr->pr_param_size * MAX_PARMS, - sizeof (pr_type_t)); memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params)); if (!pr->globals.time) { if ((def = PR_FindGlobal (pr, "time"))) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index efb193bc8..f44da87a9 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -728,12 +728,12 @@ obj_send_initialize (progs_t *pr, pr_class_t *class) sel = &G_STRUCT (pr, pr_sel_t, method->method_name); if (sel->sel_id == selector->sel_id) { PR_PushFrame (pr); - PR_SaveParams (pr); + __auto_type params = PR_SaveParams (pr); // param 0 is known to be the class pointer P_POINTER (pr, 1) = method->method_name; // pr->pr_argc is known to be 2 PR_ExecuteProgram (pr, method->method_imp); - PR_RestoreParams (pr); + PR_RestoreParams (pr, params); PR_PopFrame (pr); return; } From 6e56c9a4aa0eac6194be3c327a96c48e999072f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 14:40:03 +0900 Subject: [PATCH 0405/3664] Ensure edict_parse is reset on progs load A server switching from a game that sets edict_parse to one that does not could go badly when it comes time to loading a level. --- libs/gamecode/pr_load.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 1178fe039..2b6e9d9ff 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -188,6 +188,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->pr_edict_size = align_size (pr->pr_edict_size); pr->pr_edictareasize = pr->max_edicts * pr->pr_edict_size; + pr->edict_parse = 0; mem_size = pr->progs_size + pr->zone_size + pr->pr_edictareasize + pr->stack_size; From 6a4ef598ab3212975099d27ba38416f0714d2e28 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 14:57:36 +0900 Subject: [PATCH 0406/3664] Allow progs num_edicts and reserved_edicts to be null Really, while there are edict related instructions, edict support should probably not be in the VM itself. --- include/QF/progs.h | 1 + libs/gamecode/pr_edict.c | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 1162625ac..f5767f47c 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1715,6 +1715,7 @@ struct progs_s { ///@} /// \name edicts + /// \todo FIXME should this be outside the VM? ///@{ edict_t **edicts; int max_edicts; ///< set by user diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 76eb07e9b..29559f8f1 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -63,7 +63,7 @@ ED_ClearEdict (progs_t *pr, edict_t *e, int val) { pr_uint_t i; - if (NUM_FOR_EDICT (pr, e) < *pr->reserved_edicts) + if (pr->reserved_edicts && NUM_FOR_EDICT (pr, e) < *pr->reserved_edicts) Sys_Printf ("clearing reserved edict %d\n", NUM_FOR_EDICT (pr, e)); for (i=0; i < pr->progs->entityfields; i++) e->v[i].integer_var = val; @@ -86,6 +86,9 @@ ED_Alloc (progs_t *pr) edict_t *e; int start = pr->reserved_edicts ? *pr->reserved_edicts : 0; + if (!pr->num_edicts) { + PR_RunError (pr, "Edicts not supported in this VM\n"); + } for (i = start + 1; i < *pr->num_edicts; i++) { e = EDICT_NUM (pr, i); // the first couple seconds of server time can involve a lot of @@ -145,6 +148,10 @@ ED_Free (progs_t *pr, edict_t *ed) VISIBLE void ED_PrintNum (progs_t *pr, pr_int_t ent) { + if (!pr->num_edicts) { + Sys_Printf ("Edicts not supported in this VM\n"); + return; + } ED_Print (pr, EDICT_NUM (pr, ent)); } @@ -162,9 +169,13 @@ ED_PrintEdicts (progs_t *pr, const char *fieldval) def = PR_FindField(pr, "classname"); + if (!pr->num_edicts) { + Sys_Printf ("Edicts not supported in this VM\n"); + return; + } if (fieldval && fieldval[0] && def) { count = 0; - for (i = 0; i < *(pr)->num_edicts; i++) + for (i = 0; i < *pr->num_edicts; i++) if (strequal(fieldval, E_GSTRING (pr, EDICT_NUM(pr, i), def->ofs))) { ED_PrintNum (pr, i); @@ -172,9 +183,9 @@ ED_PrintEdicts (progs_t *pr, const char *fieldval) } Sys_Printf ("%i entities\n", count); } else { - for (i = 0; i < *(pr)->num_edicts; i++) + for (i = 0; i < *pr->num_edicts; i++) ED_PrintNum (pr, i); - Sys_Printf ("%i entities\n", *(pr)->num_edicts); + Sys_Printf ("%i entities\n", *pr->num_edicts); } } @@ -192,10 +203,14 @@ ED_Count (progs_t *pr) pr_def_t *model_def; edict_t *ent; + if (!pr->num_edicts) { + Sys_Printf ("Edicts not supported in this VM\n"); + return; + } solid_def = PR_FindField (pr, "solid"); model_def = PR_FindField (pr, "model"); active = models = solid = step = zombie = 0; - for (i = 0; i < *(pr)->num_edicts; i++) { + for (i = 0; i < *pr->num_edicts; i++) { ent = EDICT_NUM (pr, i); if (ent->free) { if (pr->globals.time && *pr->globals.time - ent->freetime <= 0.5) @@ -209,7 +224,7 @@ ED_Count (progs_t *pr) models++; } - Sys_Printf ("num_edicts:%3i\n", *(pr)->num_edicts); + Sys_Printf ("num_edicts:%3i\n", *pr->num_edicts); Sys_Printf ("active :%3i\n", active); Sys_Printf ("view :%3i\n", models); Sys_Printf ("touch :%3i\n", solid); @@ -234,7 +249,7 @@ ED_NumForEdict (progs_t *pr, edict_t *e) b = NUM_FOR_BAD_EDICT (pr, e); - if (b && (b < 0 || b >= *(pr)->num_edicts)) + if (b && (b < 0 || b >= *pr->num_edicts)) PR_RunError (pr, "NUM_FOR_EDICT: bad pointer %d %p %p", b, e, *(pr)->edicts); @@ -244,6 +259,9 @@ ED_NumForEdict (progs_t *pr, edict_t *e) qboolean PR_EdictValid (progs_t *pr, pr_int_t e) { + if (!pr->num_edicts) { + return false; + } if (e < 0 || e >= pr->pr_edictareasize) return false; if (e % pr->pr_edict_size) From 61d7f4f9c4145168871ad64f30e879a0860979cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 15:18:15 +0900 Subject: [PATCH 0407/3664] Dump locals stack when dumping main stack Any shutdown functions in progs will need locals too. --- libs/gamecode/pr_exec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index e7e9d28eb..345792f4d 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -68,6 +68,7 @@ PR_RunError (progs_t * pr, const char *error, ...) // dump the stack so PR_Error can shutdown functions pr->pr_depth = 0; + pr->localstack_used = 0; PR_Error (pr, "Program error: %s", string->str); } From e3953be8f8d7911052ecc08d6f2baa2d00a4e9e9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 15:19:21 +0900 Subject: [PATCH 0408/3664] Ensure execution state is initialized on progs load --- libs/gamecode/pr_load.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 2b6e9d9ff..efa347f4b 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -330,6 +330,12 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) def->type_encoding = xdef->type; } } + pr->pr_trace = 0; + pr->pr_trace_depth = 0; + pr->pr_xfunction = 0; + pr->pr_xstatement = 0; + pr->pr_depth = 0; + pr->localstack_used = 0; } VISIBLE void From a55b9544ac6c876683de267d17ed7af8e9357453 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 17:28:32 +0900 Subject: [PATCH 0409/3664] Improve handling of pr_argc It is now set to 0 when progs are loaded and every time PR_ExecuteProgram() returns. This takes care of the default case, but when setting parameters, pr_argc needs to be set correctly in case a vararg function is called. --- doc/progs/vm-exec.c | 1 + include/QF/progs.h | 2 +- libs/console/bi_inputline.c | 2 ++ libs/console/menu.c | 5 +++++ libs/gamecode/pr_exec.c | 1 + libs/gamecode/pr_load.c | 1 + libs/gamecode/pr_parse.c | 1 + libs/gib/bi_gib.c | 1 + libs/ruamoko/rua_hash.c | 4 ++++ qw/source/sv_ccmds.c | 1 + qw/source/sv_pr_cpqw.c | 1 + qw/source/sv_pr_qwe.c | 1 + qw/source/sv_user.c | 2 ++ tools/qfcc/test/test-harness.c | 1 + tools/qwaq/main.c | 1 + tools/qwaq/qwaq.c | 1 + 16 files changed, 25 insertions(+), 1 deletion(-) diff --git a/doc/progs/vm-exec.c b/doc/progs/vm-exec.c index 0234c2158..1f9ae4b8e 100644 --- a/doc/progs/vm-exec.c +++ b/doc/progs/vm-exec.c @@ -23,6 +23,7 @@ call_progs_main (progs_t *pr, int argc, const char **argv) PR_RESET_PARAMS (pr); P_INT (pr, 0) = argc; P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv); + pr->pr_argc = 2; PR_ExecuteProgram (pr, progs_main); PR_PopFrame (pr); PR_Zone_Free (pr, pr_argv); diff --git a/include/QF/progs.h b/include/QF/progs.h index f5767f47c..00f948d52 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1732,7 +1732,7 @@ struct progs_s { /// \name execution state ///@{ - int pr_argc; + int pr_argc; //FIXME need a good way to ensure it is correct qboolean pr_trace; int pr_trace_depth; diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index e4a936d6f..f48a4551e 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -130,9 +130,11 @@ bi_inputline_enter (inputline_t *il) P_POINTER (pr, 0) = data->data[0]; P_POINTER (pr, 1) = data->data[1]; P_STRING (pr, 2) = PR_SetTempString (pr, line); + pr->pr_argc = 3; } else { P_STRING (pr, 0) = PR_SetTempString (pr, line); P_POINTER (pr, 1) = data->data[0]; + pr->pr_argc = 2; } PR_ExecuteProgram (pr, data->enter); PR_PopFrame (pr); diff --git a/libs/console/menu.c b/libs/console/menu.c index 3ebf1d60a..ec9fc3355 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -439,6 +439,7 @@ bi_Menu_Enter (progs_t *pr) P_STRING (&menu_pr_state, 0) = PR_SetTempString (&menu_pr_state, item->text); P_INT (&menu_pr_state, 1) = 0; + pr->pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, item->func); PR_PopFrame (&menu_pr_state); run_menu_post (); @@ -672,6 +673,7 @@ Menu_Draw (view_t *view) PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = x; P_INT (&menu_pr_state, 1) = y; + menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, menu->draw); ret = R_INT (&menu_pr_state); run_menu_post (); @@ -706,6 +708,7 @@ Menu_Draw (view_t *view) PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = x + item->x; P_INT (&menu_pr_state, 1) = y + item->y; + menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, menu->cursor); run_menu_post (); } else { @@ -738,6 +741,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) P_INT (&menu_pr_state, 0) = key; P_INT (&menu_pr_state, 1) = unicode; P_INT (&menu_pr_state, 2) = down; + menu_pr_state.pr_argc = 3; PR_ExecuteProgram (&menu_pr_state, menu->keyevent); ret = R_INT (&menu_pr_state); run_menu_post (); @@ -752,6 +756,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) P_STRING (&menu_pr_state, 0) = PR_SetTempString (&menu_pr_state, item->text); P_INT (&menu_pr_state, 1) = key; + menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, item->func); PR_PopFrame (&menu_pr_state); ret = R_INT (&menu_pr_state); diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 345792f4d..024594d81 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1640,6 +1640,7 @@ op_call: watch->integer_var); } exit_program: + pr->pr_argc = 0; Sys_PopErrorHandler (); Sys_PopSignalHook (); } diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index efa347f4b..b7790711f 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -336,6 +336,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->pr_xstatement = 0; pr->pr_depth = 0; pr->localstack_used = 0; + pr->pr_argc = 0; } VISIBLE void diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 69219651f..f17b69bf1 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -524,6 +524,7 @@ ED_LoadFromFile (progs_t *pr, const char *data) PR_PushFrame (pr); PR_RESET_PARAMS (pr); P_INT (pr, 0) = PR_SetTempString (pr, data); + pr->pr_argc = 1; PR_ExecuteProgram (pr, pr->edict_parse); PR_PopFrame (pr); return; diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index b1482c030..3c462712c 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -91,6 +91,7 @@ bi_gib_builtin_f (void) PR_RESET_PARAMS (builtin->pr); P_INT (builtin->pr, 0) = GIB_Argc(); P_INT (builtin->pr, 1) = PR_SetPointer (builtin->pr, pr_list); + builtin->pr->pr_argc = 2; PR_ExecuteProgram (builtin->pr, builtin->func); PR_PopFrame (builtin->pr); PR_Zone_Free (builtin->pr, pr_list); diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index cc6d2b8c6..fedb8c288 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -98,6 +98,7 @@ bi_get_key (const void *key, void *_ht) PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key); P_INT (ht->pr, 1) = ht->ud; + ht->pr->pr_argc = 2; PR_ExecuteProgram (ht->pr, ht->gk); return PR_GetString (ht->pr, R_STRING (ht->pr)); } @@ -109,6 +110,7 @@ bi_get_hash (const void *key, void *_ht) PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key); P_INT (ht->pr, 1) = ht->ud; + ht->pr->pr_argc = 2; PR_ExecuteProgram (ht->pr, ht->gh); return R_INT (ht->pr); } @@ -121,6 +123,7 @@ bi_compare (const void *key1, const void *key2, void *_ht) P_INT (ht->pr, 0) = (intptr_t) (key1); P_INT (ht->pr, 1) = (intptr_t) (key2); P_INT (ht->pr, 2) = ht->ud; + ht->pr->pr_argc = 3; PR_ExecuteProgram (ht->pr, ht->cmp); return R_INT (ht->pr); } @@ -132,6 +135,7 @@ bi_free (void *key, void *_ht) PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key); P_INT (ht->pr, 1) = ht->ud; + ht->pr->pr_argc = 2; PR_ExecuteProgram (ht->pr, ht->f); } diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index aa359c576..318a2edaf 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -950,6 +950,7 @@ SV_SetLocalinfo (const char *key, const char *value) P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, key); P_STRING (&sv_pr_state, 1) = PR_SetTempString (&sv_pr_state, oldvalue); P_STRING (&sv_pr_state, 2) = PR_SetTempString (&sv_pr_state, value); + sv_pr_state.pr_argc = 3; PR_ExecuteProgram (&sv_pr_state, sv_funcs.LocalinfoChanged); PR_PopFrame (&sv_pr_state); } diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index 594f66219..e67b951b6 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -822,6 +822,7 @@ cpqw_user_cmd (void) P_STRING (pr, i) = PR_SetTempString (pr, Cmd_Argv (i - 1)); for (; i < 7; i++) P_STRING (pr, i) = 0; + pr->pr_argc = 7; PR_ExecuteProgram (pr, cpqw_funcs.ClientCommand); PR_PopFrame (pr); return (int) R_FLOAT (pr); diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index 7c8a46d84..9a84892cf 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -353,6 +353,7 @@ PF_calltimeofday (progs_t *pr) P_FLOAT (pr, 5) = (float) date.year; P_STRING (pr, 6) = PR_SetReturnString (pr, date.str); + pr->pr_argc = 7; PR_ExecuteProgram (pr, (func_t) (f - sv_pr_state.pr_functions)); PR_PopFrame (&sv_pr_state); } diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 5398eff6c..a6b56c219 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -1211,6 +1211,7 @@ SV_SetUserinfo (client_t *client, const char *key, const char *value) P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, key); P_STRING (&sv_pr_state, 1) = PR_SetTempString (&sv_pr_state, oldvalue); P_STRING (&sv_pr_state, 2) = PR_SetTempString (&sv_pr_state, value); + sv_pr_state.pr_argc = 3; PR_ExecuteProgram (&sv_pr_state, sv_funcs.UserInfoChanged); PR_PopFrame (&sv_pr_state); send_changes = !R_FLOAT (&sv_pr_state); @@ -1261,6 +1262,7 @@ SV_SetInfo_f (void *unused) PR_RESET_PARAMS (&sv_pr_state); P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, key); P_STRING (&sv_pr_state, 1) = PR_SetTempString (&sv_pr_state, value); + sv_pr_state.pr_argc = 2; PR_ExecuteProgram (&sv_pr_state, sv_funcs.UserInfoCallback); PR_PopFrame (&sv_pr_state); if (R_FLOAT (&sv_pr_state)) diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index cabef6ab7..1c6610723 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -266,6 +266,7 @@ main (int argc, char **argv) PR_RESET_PARAMS (&pr); P_INT (&pr, 0) = pr_argc; P_POINTER (&pr, 1) = PR_SetPointer (&pr, pr_argv); + pr.pr_argc = 2; PR_ExecuteProgram (&pr, main_func); PR_PopFrame (&pr); if (options.flote) diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index 1ab7c027e..7f51ea6df 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -177,6 +177,7 @@ main (int argc, char **argv) PR_RESET_PARAMS (&pr); P_INT (&pr, 0) = pr_argc; P_POINTER (&pr, 1) = PR_SetPointer (&pr, pr_argv); + pr.pr_argc = 2; PR_ExecuteProgram (&pr, main_func); PR_PopFrame (&pr); return R_INT (&pr); diff --git a/tools/qwaq/qwaq.c b/tools/qwaq/qwaq.c index b446a02dd..05d515f4e 100644 --- a/tools/qwaq/qwaq.c +++ b/tools/qwaq/qwaq.c @@ -189,6 +189,7 @@ main (int argc, const char **argv) PR_RESET_PARAMS (&pr); P_INT (&pr, 0) = pr_argc; P_POINTER (&pr, 1) = PR_SetPointer (&pr, pr_argv); + pr.pr_argc = 2; PR_ExecuteProgram (&pr, main_func); PR_PopFrame (&pr); return R_INT (&pr); From 6739f5df4dbd3ebf72b0718a74b1cb43f1e968fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 17:39:34 +0900 Subject: [PATCH 0410/3664] Fix an out-by-one error Noticed while sorting out pr_argc --- qw/source/sv_pr_cpqw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index e67b951b6..4263cc097 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -818,11 +818,11 @@ cpqw_user_cmd (void) PR_PushFrame (pr); P_FLOAT (pr, 0) = argc; - for (i = 1; i < argc; i++) + for (i = 1; i < argc + 1; i++) P_STRING (pr, i) = PR_SetTempString (pr, Cmd_Argv (i - 1)); - for (; i < 7; i++) + for (; i < 8; i++) P_STRING (pr, i) = 0; - pr->pr_argc = 7; + pr->pr_argc = 8; PR_ExecuteProgram (pr, cpqw_funcs.ClientCommand); PR_PopFrame (pr); return (int) R_FLOAT (pr); From ca6fe0730bc151653043669f86f0f3f5b9c53dd9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 19:02:24 +0900 Subject: [PATCH 0411/3664] Fix qfcc test harness tracing Just a consequence of progs execution state being initialized properly. --- tools/qfcc/test/test-harness.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 1c6610723..69e660941 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -150,8 +150,6 @@ init_qf (void) pr.allocate_progs_mem = allocate_progs_mem; pr.free_progs_mem = free_progs_mem; pr.no_exec_limit = 0; // absolutely want a limit! - pr.pr_trace_depth = -1; - pr.pr_trace = options.trace; PR_Init_Cvars (); PR_Init (&pr); @@ -178,6 +176,8 @@ load_progs (const char *name) Qclose (file); if (!PR_RunLoadFuncs (&pr)) PR_Error (&pr, "unable to load %s", pr.progs_name); + pr.pr_trace_depth = -1; + pr.pr_trace = options.trace; return 1; } From 89e83d7d73548375af6a9750152c93bf3726e979 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 20:07:29 +0900 Subject: [PATCH 0412/3664] Move the debug info out of progs_t The debug subsystem now uses the resources system to ensure it cleans up, and its data is now semi-private. Unfortunately, PR_LoadDebug had to remain public for qfprogs because using PR_RunLoadFuncs would cause builtin resolution to complain. --- include/QF/progs.h | 14 +- libs/gamecode/pr_debug.c | 291 ++++++++++++++++++++----------- libs/gamecode/pr_load.c | 1 - tools/qfcc/source/dump_globals.c | 16 +- tools/qfcc/source/dump_lines.c | 11 +- 5 files changed, 211 insertions(+), 122 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 00f948d52..ebfa0a3fd 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1583,6 +1583,11 @@ void PR_Debug_Init_Cvars (void); int PR_LoadDebug (progs_t *pr); void PR_Debug_Watch (progs_t *pr, const char *expr); void PR_Debug_Print (progs_t *pr, const char *expr); +pr_auxfunction_t *PR_Debug_AuxFunction (progs_t *pr, pr_uint_t func) __attribute__((pure)); +pr_auxfunction_t *PR_Debug_MappedAuxFunction (progs_t *pr, pr_uint_t func) __attribute__((pure)); +pr_def_t *PR_Debug_LocalDefs (progs_t *pr, pr_auxfunction_t *aux_function) __attribute__((pure)); +pr_lineno_t *PR_Debug_Linenos (progs_t *pr, pr_auxfunction_t *aux_function, + pr_uint_t *num_linenos); pr_auxfunction_t *PR_Get_Lineno_Func (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); pr_uint_t PR_Get_Lineno_Addr (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); pr_uint_t PR_Get_Lineno_Line (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); @@ -1781,14 +1786,9 @@ struct progs_s { struct obj_list_s *class_tree_list; ///@} - /// \name debug info + /// \name debugging ///@{ - const char *debugfile; - struct pr_debug_header_s *debug; - struct pr_auxfunction_s *auxfunctions; - struct pr_auxfunction_s **auxfunction_map; - struct pr_lineno_s *linenos; - pr_def_t *local_defs; + struct prdeb_resources_s *pr_debug_resources; pr_type_t *watch; int wp_conditional; pr_type_t wp_val; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index d895f631a..898e7255a 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -71,9 +71,16 @@ typedef struct { progs_t *pr; } file_t; -typedef struct { +typedef struct prdeb_resources_s { + progs_t *pr; dstring_t *string; -} pr_debug_resources_t; + const char *debugfile; + struct pr_debug_header_s *debug; + struct pr_auxfunction_s *auxfunctions; + struct pr_auxfunction_s **auxfunction_map; + struct pr_lineno_s *linenos; + pr_def_t *local_defs; +} prdeb_resources_t; typedef struct { progs_t *pr; @@ -322,35 +329,28 @@ error: static void pr_debug_clear (progs_t *pr, void *data) { - __auto_type res = (pr_debug_resources_t *) data; + __auto_type res = (prdeb_resources_t *) data; if (res->string) { dstring_clearstr (res->string); } else { res->string = dstring_newstr (); } -} -void -PR_Debug_Init (progs_t *pr) -{ - pr_debug_resources_t *res = calloc (1, sizeof (*res)); - res->string = 0; + if (res->debug) + pr->free_progs_mem (pr, res->debug); + res->debug = 0; + res->auxfunctions = 0; + if (res->auxfunction_map) + pr->free_progs_mem (pr, res->auxfunction_map); + res->auxfunction_map = 0; + res->linenos = 0; + res->local_defs = 0; - PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); - if (!file_hash) { - file_hash = Hash_NewTable (1024, file_get_key, file_free, 0); - } -} - -void -PR_Debug_Init_Cvars (void) -{ - pr_debug = Cvar_Get ("pr_debug", "0", CVAR_NONE, NULL, - "enable progs debugging"); - pr_source_path = Cvar_Get ("pr_source_path", ".", CVAR_NONE, source_path_f, - "where to look (within gamedir) for source " - "files"); + pr->pr_debug_resources = res; + pr->watch = 0; + pr->wp_conditional = 0; + pr->wp_val.integer_var = 0; } static file_t * @@ -411,6 +411,7 @@ PR_Load_Source_File (progs_t *pr, const char *fname) VISIBLE int PR_LoadDebug (progs_t *pr) { + prdeb_resources_t *res = PR_Resources_Find (pr, "PR_Debug"); char *sym_path; const char *path_end, *sym_file; off_t debug_size; @@ -418,16 +419,6 @@ PR_LoadDebug (progs_t *pr) pr_def_t *def; pr_type_t *str = 0; - if (pr->debug) - pr->free_progs_mem (pr, pr->debug); - pr->debug = 0; - pr->auxfunctions = 0; - if (pr->auxfunction_map) - pr->free_progs_mem (pr, pr->auxfunction_map); - pr->auxfunction_map = 0; - pr->linenos = 0; - pr->local_defs = 0; - if (!pr_debug->int_val) return 1; @@ -438,107 +429,169 @@ PR_LoadDebug (progs_t *pr) Hash_FlushTable (file_hash); if (!str) return 1; - pr->debugfile = PR_GetString (pr, str->string_var); - sym_file = QFS_SkipPath (pr->debugfile); + res->debugfile = PR_GetString (pr, str->string_var); + sym_file = QFS_SkipPath (res->debugfile); path_end = QFS_SkipPath (pr->progs_name); sym_path = malloc (strlen (sym_file) + (path_end - pr->progs_name) + 1); strncpy (sym_path, pr->progs_name, path_end - pr->progs_name); strcpy (sym_path + (path_end - pr->progs_name), sym_file); - pr->debug = pr->load_file (pr, sym_path, &debug_size); - if (!pr->debug) { + res->debug = pr->load_file (pr, sym_path, &debug_size); + if (!res->debug) { Sys_Printf ("can't load %s for debug info\n", sym_path); free (sym_path); return 1; } - pr->debug->version = LittleLong (pr->debug->version); - if (pr->debug->version != PROG_DEBUG_VERSION) { + res->debug->version = LittleLong (res->debug->version); + if (res->debug->version != PROG_DEBUG_VERSION) { Sys_Printf ("ignoring %s with unsupported version %x.%03x.%03x\n", sym_path, - (pr->debug->version >> 24) & 0xff, - (pr->debug->version >> 12) & 0xfff, - pr->debug->version & 0xfff); - pr->debug = 0; + (res->debug->version >> 24) & 0xff, + (res->debug->version >> 12) & 0xfff, + res->debug->version & 0xfff); + res->debug = 0; free (sym_path); return 1; } - pr->debug->crc = LittleShort (pr->debug->crc); - if (pr->debug->crc != pr->crc) { + res->debug->crc = LittleShort (res->debug->crc); + if (res->debug->crc != pr->crc) { Sys_Printf ("ignoring %s that doesn't match %s. (CRCs: " "sym:%d dat:%d)\n", sym_path, pr->progs_name, - pr->debug->crc, + res->debug->crc, pr->crc); - pr->debug = 0; + res->debug = 0; free (sym_path); return 1; } free (sym_path); - pr->debug->you_tell_me_and_we_will_both_know = LittleShort - (pr->debug->you_tell_me_and_we_will_both_know); - pr->debug->auxfunctions = LittleLong (pr->debug->auxfunctions); - pr->debug->num_auxfunctions = LittleLong (pr->debug->num_auxfunctions); - pr->debug->linenos = LittleLong (pr->debug->linenos); - pr->debug->num_linenos = LittleLong (pr->debug->num_linenos); - pr->debug->locals = LittleLong (pr->debug->locals); - pr->debug->num_locals = LittleLong (pr->debug->num_locals); + res->debug->you_tell_me_and_we_will_both_know = LittleShort + (res->debug->you_tell_me_and_we_will_both_know); + res->debug->auxfunctions = LittleLong (res->debug->auxfunctions); + res->debug->num_auxfunctions = LittleLong (res->debug->num_auxfunctions); + res->debug->linenos = LittleLong (res->debug->linenos); + res->debug->num_linenos = LittleLong (res->debug->num_linenos); + res->debug->locals = LittleLong (res->debug->locals); + res->debug->num_locals = LittleLong (res->debug->num_locals); - pr->auxfunctions = (pr_auxfunction_t*)((char*)pr->debug + - pr->debug->auxfunctions); - pr->linenos = (pr_lineno_t*)((char*)pr->debug + pr->debug->linenos); - pr->local_defs = (pr_def_t*)((char*)pr->debug + pr->debug->locals); + res->auxfunctions = (pr_auxfunction_t*)((char*)res->debug + + res->debug->auxfunctions); + res->linenos = (pr_lineno_t*)((char*)res->debug + res->debug->linenos); + res->local_defs = (pr_def_t*)((char*)res->debug + res->debug->locals); i = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); - pr->auxfunction_map = pr->allocate_progs_mem (pr, i); + res->auxfunction_map = pr->allocate_progs_mem (pr, i); for (i = 0; (int) i < pr->progs->numfunctions; i++) //FIXME (cast) - pr->auxfunction_map[i] = 0; + res->auxfunction_map[i] = 0; - for (i = 0; i < pr->debug->num_auxfunctions; i++) { - pr->auxfunctions[i].function = LittleLong - (pr->auxfunctions[i].function); - pr->auxfunctions[i].source_line = LittleLong - (pr->auxfunctions[i].source_line); - pr->auxfunctions[i].line_info = LittleLong - (pr->auxfunctions[i].line_info); - pr->auxfunctions[i].local_defs = LittleLong - (pr->auxfunctions[i].local_defs); - pr->auxfunctions[i].num_locals = LittleLong - (pr->auxfunctions[i].num_locals); + for (i = 0; i < res->debug->num_auxfunctions; i++) { + res->auxfunctions[i].function = LittleLong + (res->auxfunctions[i].function); + res->auxfunctions[i].source_line = LittleLong + (res->auxfunctions[i].source_line); + res->auxfunctions[i].line_info = LittleLong + (res->auxfunctions[i].line_info); + res->auxfunctions[i].local_defs = LittleLong + (res->auxfunctions[i].local_defs); + res->auxfunctions[i].num_locals = LittleLong + (res->auxfunctions[i].num_locals); - pr->auxfunction_map[pr->auxfunctions[i].function] = - &pr->auxfunctions[i]; + res->auxfunction_map[res->auxfunctions[i].function] = + &res->auxfunctions[i]; } - for (i = 0; i < pr->debug->num_linenos; i++) { - pr->linenos[i].fa.func = LittleLong (pr->linenos[i].fa.func); - pr->linenos[i].line = LittleLong (pr->linenos[i].line); + for (i = 0; i < res->debug->num_linenos; i++) { + res->linenos[i].fa.func = LittleLong (res->linenos[i].fa.func); + res->linenos[i].line = LittleLong (res->linenos[i].line); } - for (i = 0; i < pr->debug->num_locals; i++) { - pr->local_defs[i].type = LittleShort (pr->local_defs[i].type); - pr->local_defs[i].ofs = LittleShort (pr->local_defs[i].ofs); - pr->local_defs[i].name = LittleLong (pr->local_defs[i].name); + for (i = 0; i < res->debug->num_locals; i++) { + res->local_defs[i].type = LittleShort (res->local_defs[i].type); + res->local_defs[i].ofs = LittleShort (res->local_defs[i].ofs); + res->local_defs[i].name = LittleLong (res->local_defs[i].name); } return 1; } +VISIBLE pr_auxfunction_t * +PR_Debug_AuxFunction (progs_t *pr, pr_uint_t func) +{ + prdeb_resources_t *res = pr->pr_debug_resources; + if (!res->debug || func >= res->debug->num_auxfunctions) { + return 0; + } + return &res->auxfunctions[func]; +} + +VISIBLE pr_auxfunction_t * +PR_Debug_MappedAuxFunction (progs_t *pr, pr_uint_t func) +{ + prdeb_resources_t *res = pr->pr_debug_resources; + if (!res->debug || (int)func >= pr->progs->numfunctions) {//FIXME (cast) + return 0; + } + return res->auxfunction_map[func]; +} + +VISIBLE pr_def_t * +PR_Debug_LocalDefs (progs_t *pr, pr_auxfunction_t *aux_function) +{ + prdeb_resources_t *res = pr->pr_debug_resources; + if (!res->debug || !aux_function) { + return 0; + } + if (aux_function->local_defs > res->debug->num_locals) { + return 0; + } + return res->local_defs + aux_function->local_defs; +} + +VISIBLE pr_lineno_t * +PR_Debug_Linenos (progs_t *pr, pr_auxfunction_t *aux_function, + pr_uint_t *num_linenos) +{ + pr_uint_t i, count; + prdeb_resources_t *res = pr->pr_debug_resources; + if (!res->debug) { + return 0; + } + if (!aux_function) { + *num_linenos = res->debug->num_linenos; + return res->linenos; + } + if (aux_function->line_info > res->debug->num_linenos) { + return 0; + } + //FIXME put lineno count in sym file + for (count = 1, i = aux_function->line_info + 1; + i < res->debug->num_linenos; i++, count++) { + if (!res->linenos[i].line) { + break; + } + } + *num_linenos = count; + return res->linenos + aux_function->line_info; +} + pr_auxfunction_t * PR_Get_Lineno_Func (progs_t *pr, pr_lineno_t *lineno) { - while (lineno > pr->linenos && lineno->line) + prdeb_resources_t *res = pr->pr_debug_resources; + while (lineno > res->linenos && lineno->line) lineno--; if (lineno->line) return 0; - return &pr->auxfunctions[lineno->fa.func]; + return &res->auxfunctions[lineno->fa.func]; } pr_uint_t PR_Get_Lineno_Addr (progs_t *pr, pr_lineno_t *lineno) { + prdeb_resources_t *res = pr->pr_debug_resources; pr_auxfunction_t *f; if (lineno->line) return lineno->fa.addr; - if (lineno->fa.func < pr->debug->num_auxfunctions) { - f = &pr->auxfunctions[lineno->fa.func]; + if (lineno->fa.func < res->debug->num_auxfunctions) { + f = &res->auxfunctions[lineno->fa.func]; return pr->pr_functions[f->function].first_statement; } // take a wild guess that only the line number is bogus and return @@ -557,16 +610,17 @@ PR_Get_Lineno_Line (progs_t *pr, pr_lineno_t *lineno) pr_lineno_t * PR_Find_Lineno (progs_t *pr, pr_uint_t addr) { + prdeb_resources_t *res = pr->pr_debug_resources; pr_uint_t i; pr_lineno_t *lineno = 0; - if (!pr->debug) + if (!res->debug) return 0; - if (!pr->debug->num_linenos) + if (!res->debug->num_linenos) return 0; - for (i = pr->debug->num_linenos; i > 0; i--) { - if (PR_Get_Lineno_Addr (pr, &pr->linenos[i - 1]) <= addr) { - lineno = &pr->linenos[i - 1]; + for (i = res->debug->num_linenos; i > 0; i--) { + if (PR_Get_Lineno_Addr (pr, &res->linenos[i - 1]) <= addr) { + lineno = &res->linenos[i - 1]; break; } } @@ -615,13 +669,14 @@ PR_Get_Source_Line (progs_t *pr, pr_uint_t addr) pr_def_t * PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) { + prdeb_resources_t *res = pr->pr_debug_resources; pr_uint_t i; pr_auxfunction_t *aux_func; pr_def_t *ddef = 0; int num_params; int param_offs = 0; - if (!pr->debug) + if (!res->debug) return 0; if (!func) return 0; @@ -634,12 +689,12 @@ PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) if (parm >= (unsigned) num_params) return 0; - aux_func = pr->auxfunction_map[func - pr->pr_functions]; + aux_func = res->auxfunction_map[func - pr->pr_functions]; if (!aux_func) return 0; for (i = 0; i < aux_func->num_locals; i++) { - ddef = &pr->local_defs[aux_func->local_defs + param_offs + i]; + ddef = &res->local_defs[aux_func->local_defs + param_offs + i]; if (!parm--) break; } @@ -649,11 +704,12 @@ PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) static pr_auxfunction_t * get_aux_function (progs_t *pr) { + prdeb_resources_t *res = pr->pr_debug_resources; dfunction_t *func; - if (!pr->pr_xfunction || !pr->auxfunction_map) + if (!pr->pr_xfunction || !res->auxfunction_map) return 0; func = pr->pr_xfunction->descriptor; - return pr->auxfunction_map[func - pr->pr_functions]; + return res->auxfunction_map[func - pr->pr_functions]; } static etype_t @@ -679,6 +735,7 @@ get_etype (progs_t *pr, int typeptr) pr_def_t * PR_Get_Local_Def (progs_t *pr, pointer_t offs) { + prdeb_resources_t *res = pr->pr_debug_resources; pr_uint_t i; dfunction_t *func; pr_auxfunction_t *aux_func; @@ -688,23 +745,24 @@ PR_Get_Local_Def (progs_t *pr, pointer_t offs) func = pr->pr_xfunction->descriptor; if (!func) return 0; - aux_func = pr->auxfunction_map[func - pr->pr_functions]; + aux_func = res->auxfunction_map[func - pr->pr_functions]; if (!aux_func) return 0; offs -= func->parm_start; if (offs >= func->locals) return 0; for (i = 0; i < aux_func->num_locals; i++) - if (pr->local_defs[aux_func->local_defs + i].ofs == offs) - return &pr->local_defs[aux_func->local_defs + i]; + if (res->local_defs[aux_func->local_defs + i].ofs == offs) + return &res->local_defs[aux_func->local_defs + i]; return 0; } VISIBLE void PR_DumpState (progs_t *pr) { + prdeb_resources_t *res = pr->pr_debug_resources; if (pr->pr_xfunction) { - if (pr_debug->int_val && pr->debug) { + if (pr_debug->int_val && res->debug) { pr_lineno_t *lineno; pr_auxfunction_t *func = 0; dfunction_t *descriptor = pr->pr_xfunction->descriptor; @@ -803,9 +861,10 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) static pr_def_t * pr_debug_find_def (progs_t *pr, pr_int_t ofs) { + prdeb_resources_t *res = pr->pr_debug_resources; pr_def_t *def = 0; - if (pr_debug->int_val && pr->debug) + if (pr_debug->int_val && res->debug) def = PR_Get_Local_Def (pr, ofs); if (!def) def = PR_GlobalAtOfs (pr, ofs); @@ -993,11 +1052,12 @@ pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; + prdeb_resources_t *res = pr->pr_debug_resources; //FIXME dstring_t *dstr = data->dstr; pointer_t ofs = value->integer_var; pr_def_t *def = 0; - if (pr_debug->int_val && pr->debug) { + if (pr_debug->int_val && res->debug) { def = PR_Get_Local_Def (pr, ofs); } if (!def) { @@ -1165,6 +1225,7 @@ PR_Debug_Print (progs_t *pr, const char *expr) VISIBLE void PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) { + prdeb_resources_t *res = pr->pr_debug_resources; int addr = s - pr->pr_statements; int dump_code = contents & 2; const char *fmt; @@ -1188,7 +1249,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) if (pr_debug->int_val > 1) dump_code = 1; - if (pr_debug->int_val && pr->debug) { + if (pr_debug->int_val && res->debug) { const char *source_line = PR_Get_Source_Line (pr, addr); if (source_line) { @@ -1344,13 +1405,14 @@ do_print: static void dump_frame (progs_t *pr, prstack_t *frame) { + prdeb_resources_t *res = pr->pr_debug_resources; dfunction_t *f = frame->f ? frame->f->descriptor : 0; if (!f) { Sys_Printf ("\n"); return; } - if (pr_debug->int_val && pr->debug) { + if (pr_debug->int_val && res->debug) { pr_lineno_t *lineno = PR_Find_Lineno (pr, frame->s); pr_auxfunction_t *func = PR_Get_Lineno_Func (pr, lineno); pr_uint_t line = PR_Get_Lineno_Line (pr, lineno); @@ -1477,3 +1539,26 @@ ED_Print (progs_t *pr, edict_t *ed) dstring_delete (dstr); } + +void +PR_Debug_Init (progs_t *pr) +{ + prdeb_resources_t *res = calloc (1, sizeof (*res)); + res->pr = pr; + + PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); + if (!file_hash) { + file_hash = Hash_NewTable (1024, file_get_key, file_free, 0); + } + PR_AddLoadFunc (pr, PR_LoadDebug); +} + +void +PR_Debug_Init_Cvars (void) +{ + pr_debug = Cvar_Get ("pr_debug", "0", CVAR_NONE, NULL, + "enable progs debugging"); + pr_source_path = Cvar_Get ("pr_source_path", ".", CVAR_NONE, source_path_f, + "where to look (within gamedir) for source " + "files"); +} diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index b7790711f..51723cd64 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -383,7 +383,6 @@ pr_run_ctors (progs_t *pr) static int (*load_funcs_1[])(progs_t *) = { PR_RelocateBuiltins, - PR_LoadDebug, 0, }; diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index ea52bd8f6..0dba5c6dc 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -263,19 +263,23 @@ dump_functions (progs_t *pr) func->parm_size[j].size); printf (") %d @ %x", func->locals, func->parm_start); puts (""); - if (pr->debug && type_encodings) { - pr_auxfunction_t *aux = pr->auxfunction_map[i]; - if (!aux) + if (type_encodings) { + pr_auxfunction_t *aux = PR_Debug_MappedAuxFunction (pr, i); + if (!aux) { continue; + } printf (" %d %s:%d %d %d %d %x\n", aux->function, PR_GetString (pr, func->s_file), aux->source_line, aux->line_info, aux->local_defs, aux->num_locals, aux->return_type); + pr_def_t *local_defs = PR_Debug_LocalDefs (pr, aux); + if (!local_defs) { + continue; + } for (j = 0; j < (int)aux->num_locals; j++) { - pr->local_defs[+ aux->local_defs + j].type_encoding - += type_encodings; - dump_def (pr, pr->local_defs + aux->local_defs + j, 1); + local_defs[j].type_encoding += type_encodings;//FIXME do in debug + dump_def (pr, local_defs + j, 1); } } } diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index ae504c03d..966203a72 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -69,8 +69,8 @@ progs_get_func_data (unsigned func_index, void *data) dfunction_t *func; memset (&func_data, 0, sizeof (func_data)); - if (func_index < pr->debug->num_auxfunctions) { - aux_func = pr->auxfunctions + func_index; + aux_func = PR_Debug_AuxFunction (pr, func_index); + if (aux_func) { func_data.source_line = aux_func->source_line; func_data.return_type = aux_func->return_type; func_data.num_locals = aux_func->num_locals; @@ -126,10 +126,11 @@ dump_line_set (pr_lineno_t *lineno, unsigned count, void dump_lines (progs_t *pr) { - if (!pr->debug) + pr_lineno_t *linenos; + pr_uint_t num_linenos; + if (!(linenos = PR_Debug_Linenos (pr, 0, &num_linenos))) return; - dump_line_set (pr->linenos, pr->debug->num_linenos, - progs_get_func_data, pr); + dump_line_set (linenos, num_linenos, progs_get_func_data, pr); } static func_data_t * From 4bc36836a10e699cb2fbfd7a34e99e7189b8653e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 20:16:37 +0900 Subject: [PATCH 0413/3664] Correct the type of an aux function's return type It was made to be the address of the type encoding long ago. --- include/QF/pr_debug.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/QF/pr_debug.h b/include/QF/pr_debug.h index be5e1471d..be398f056 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/pr_debug.h @@ -39,8 +39,7 @@ typedef struct pr_auxfunction_s { pr_uint_t line_info; // index to first lineno entry pr_uint_t local_defs; // index to the first local def pr_uint_t num_locals; // number of local defs - pr_short_t return_type; // return type of this function - pr_short_t reserved; + pr_uint_t return_type; // return type of this function } pr_auxfunction_t; typedef struct pr_lineno_s { From 282132958f2dbea62e651a643aff3a82fb3f8084 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 20:45:36 +0900 Subject: [PATCH 0414/3664] Relocate local def type encodings in debug load For technical reasons (programmer laziness), qfcc does not fix up local def type encodings when writing the debug symbols file (type encoding location not readily accessible). --- libs/gamecode/pr_debug.c | 29 +++++++++++++++++++---------- tools/qfcc/source/dump_globals.c | 1 - 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 898e7255a..e9bc860a9 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -80,6 +80,7 @@ typedef struct prdeb_resources_s { struct pr_auxfunction_s **auxfunction_map; struct pr_lineno_s *linenos; pr_def_t *local_defs; + pr_def_t *type_encodings_def; } prdeb_resources_t; typedef struct { @@ -418,6 +419,7 @@ PR_LoadDebug (progs_t *pr) pr_uint_t i; pr_def_t *def; pr_type_t *str = 0; + pointer_t type_encodings = 0; if (!pr_debug->int_val) return 1; @@ -503,10 +505,22 @@ PR_LoadDebug (progs_t *pr) res->linenos[i].fa.func = LittleLong (res->linenos[i].fa.func); res->linenos[i].line = LittleLong (res->linenos[i].line); } + res->type_encodings_def = PR_FindGlobal (pr, ".type_encodings"); + if (res->type_encodings_def) { + __auto_type encodings = &G_STRUCT (pr, qfot_type_encodings_t, + res->type_encodings_def->ofs); + type_encodings = encodings->types; + } for (i = 0; i < res->debug->num_locals; i++) { res->local_defs[i].type = LittleShort (res->local_defs[i].type); - res->local_defs[i].ofs = LittleShort (res->local_defs[i].ofs); + res->local_defs[i].size = LittleShort (res->local_defs[i].size); + res->local_defs[i].ofs = LittleLong (res->local_defs[i].ofs); res->local_defs[i].name = LittleLong (res->local_defs[i].name); + res->local_defs[i].type_encoding + = LittleLong (res->local_defs[i].type_encoding); + if (type_encodings) { + res->local_defs[i].type_encoding += type_encodings; + } } return 1; } @@ -715,18 +729,13 @@ get_aux_function (progs_t *pr) static etype_t get_etype (progs_t *pr, int typeptr) { - //FIXME cache .type_encodings def - pr_def_t *te_def = PR_FindGlobal (pr, ".type_encodings"); - qfot_type_encodings_t *encodings; qfot_type_t *type; - if (!te_def) { - // can't decode the type, so make no assumptions about it - return typeptr; + if (!typeptr) { + return ev_void; } - encodings = &G_STRUCT (pr, qfot_type_encodings_t, te_def->ofs); - type = &G_STRUCT (pr, qfot_type_t, encodings->types + typeptr); - if (type->meta == 0) { + type = &G_STRUCT (pr, qfot_type_t, typeptr); + if (type->meta == ty_basic) { return type->t.type; } return ev_void; diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 0dba5c6dc..65271b289 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -278,7 +278,6 @@ dump_functions (progs_t *pr) continue; } for (j = 0; j < (int)aux->num_locals; j++) { - local_defs[j].type_encoding += type_encodings;//FIXME do in debug dump_def (pr, local_defs + j, 1); } } From 66dd3ef0704bf15f8465277cd560c5db961608ef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 21:23:13 +0900 Subject: [PATCH 0415/3664] Make a bunch of count things positive-only This fixes a pile of FIXMEs, because some things should never be negative. --- include/QF/pr_comp.h | 8 ++++---- libs/gamecode/pr_builtins.c | 3 ++- libs/gamecode/pr_debug.c | 17 +++++++++-------- libs/gamecode/pr_load.c | 2 +- tools/qfcc/source/dump_globals.c | 15 ++++++++++----- tools/qfcc/source/qfprogs.c | 3 ++- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 8c03a7981..60022098f 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -27,7 +27,7 @@ typedef int16_t pr_short_t; typedef uint16_t pr_ushort_t; typedef int32_t pr_int_t; typedef uint32_t pr_uint_t; -typedef pr_int_t func_t; +typedef pr_uint_t func_t; typedef pr_int_t string_t; typedef pr_uint_t pointer_t; @@ -455,7 +455,7 @@ typedef struct dfunction_s { pr_int_t parm_start; pr_uint_t locals; // total ints of parms + locals - pr_int_t profile; // runtime + pr_uint_t profile; // runtime string_t s_name; pr_int_t s_file; // source file defined in @@ -502,10 +502,10 @@ typedef struct dprograms_s { pr_uint_t numfielddefs; pr_uint_t ofs_functions; - pr_int_t numfunctions; // function 0 is an empty + pr_uint_t numfunctions; // function 0 is an empty pr_uint_t ofs_strings; - pr_int_t numstrings; // first string is a null string + pr_uint_t numstrings; // first string is a null string pr_uint_t ofs_globals; pr_uint_t numglobals; diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index a3ab8c9d9..12c2e6050 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -158,7 +158,8 @@ bi_no_function (progs_t *pr) VISIBLE int PR_RelocateBuiltins (progs_t *pr) { - pr_int_t i, ind; + pr_uint_t i; + pr_int_t ind; int bad = 0; dfunction_t *desc; bfunction_t *func; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index e9bc860a9..9fd61b020 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -483,7 +483,7 @@ PR_LoadDebug (progs_t *pr) i = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); res->auxfunction_map = pr->allocate_progs_mem (pr, i); - for (i = 0; (int) i < pr->progs->numfunctions; i++) //FIXME (cast) + for (i = 0; i < pr->progs->numfunctions; i++) res->auxfunction_map[i] = 0; for (i = 0; i < res->debug->num_auxfunctions; i++) { @@ -539,7 +539,7 @@ VISIBLE pr_auxfunction_t * PR_Debug_MappedAuxFunction (progs_t *pr, pr_uint_t func) { prdeb_resources_t *res = pr->pr_debug_resources; - if (!res->debug || (int)func >= pr->progs->numfunctions) {//FIXME (cast) + if (!res->debug || func >= pr->progs->numfunctions) { return 0; } return res->auxfunction_map[func]; @@ -1046,7 +1046,7 @@ pr_debug_func_view (qfot_type_t *type, pr_type_t *value, void *_data) progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - if (value->func_var < 0 || value->func_var >= pr->progs->numfunctions) { + if (value->func_var >= pr->progs->numfunctions) { dasprintf (dstr, "INVALID:%d", value->func_var); } else if (!value->func_var) { dstring_appendstr (dstr, "NULL"); @@ -1300,6 +1300,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) unsigned parm_ind = 0; pr_int_t opval; etype_t optype = ev_void; + func_t func; if (mode == 'P') { opchar = fmt[3]; @@ -1343,10 +1344,10 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) case 'F': str = global_string (&data, opval, optype, contents & 1); - if (G_FUNCTION (pr, opval) >= 0 - && G_FUNCTION (pr, opval) - < pr->progs->numfunctions) - call_func = pr->pr_functions + G_FUNCTION (pr, opval); + func = G_FUNCTION (pr, opval); + if (func < pr->progs->numfunctions) { + call_func = pr->pr_functions + func; + } break; case 'P': parm_def = PR_Get_Param_Def (pr, call_func, parm_ind); @@ -1468,7 +1469,7 @@ PR_StackTrace (progs_t *pr) VISIBLE void PR_Profile (progs_t * pr) { - pr_int_t max, num, i; + pr_uint_t max, num, i; dfunction_t *best, *f; num = 0; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 51723cd64..c8157efa8 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -370,7 +370,7 @@ PR_AddLoadFinishFunc (progs_t *pr, int (*func)(progs_t *)) static int pr_run_ctors (progs_t *pr) { - pr_int_t fnum; + pr_uint_t fnum; dfunction_t *func; for (fnum = 0; fnum < pr->progs->numfunctions; fnum++) { diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 65271b289..9343a0ac7 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -86,7 +86,12 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) break; case ev_string: string = G_INT (pr, offset); - if (string < 0 || string >= pr->progs->numstrings) { + // at runtime, strings can be negative (thus string_t is + // signed), but negative strings means they have been + // dynamically allocated, thus a negative string index should + // never appear in compiled code + if (string < 0 + || (pr_uint_t) string >= pr->progs->numstrings) { str = "invalid string offset"; comment = va (" %d %s", string, str); } else { @@ -115,7 +120,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) { func_t func = G_FUNCTION (pr, offset); int start; - if (func >= 0 && func < pr->progs->numfunctions) { + if (func < pr->progs->numfunctions) { start = pr->pr_functions[func].first_statement; if (start > 0) comment = va (" %d @ %x", func, start); @@ -230,9 +235,9 @@ qfo_fields (qfo_t *qfo) void dump_functions (progs_t *pr) { - int i, j; + pr_uint_t i, j, count; const char *name; - int start, count; + int start; const char *comment; pr_def_t *encodings_def; pointer_t type_encodings = 0; @@ -277,7 +282,7 @@ dump_functions (progs_t *pr) if (!local_defs) { continue; } - for (j = 0; j < (int)aux->num_locals; j++) { + for (j = 0; j < aux->num_locals; j++) { dump_def (pr, local_defs + j, 1); } } diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 37acd11fc..02f05bce9 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -255,7 +255,8 @@ static int load_progs (const char *name) { QFile *file; - int i, size; + int size; + pr_uint_t i; char buff[5]; Hash_FlushTable (func_tab); From 3577d27a45815a53c9f5b0dc0b5db2bdcb45efd1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Feb 2020 23:14:18 +0900 Subject: [PATCH 0416/3664] Move the ObjQC data into a resource block This makes it nice and private (though with the cached pointer, ObjQC is still a first-class component). --- include/QF/progs.h | 15 +- libs/ruamoko/rua_obj.c | 488 ++++++++++++++++++++++++----------------- 2 files changed, 288 insertions(+), 215 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index ebfa0a3fd..369360449 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1636,8 +1636,6 @@ typedef struct { strref_t *tstr; ///< Linked list of temporary strings. } prstack_t; -struct obj_list_s; - struct progs_s { int (*parse_field) (progs_t *pr, const char *key, const char *value); @@ -1772,18 +1770,7 @@ struct progs_s { /// \name obj info ///@{ - unsigned selector_index; - unsigned selector_index_max; - struct obj_list_s **selector_sels; - string_t *selector_names; - struct hashtab_s *selector_hash; - struct hashtab_s *classes; - struct hashtab_s *load_methods; - struct obj_list_s *unresolved_classes; - struct obj_list_s *unclaimed_categories; - struct obj_list_s *unclaimed_proto_list; - struct obj_list_s *module_list; - struct obj_list_s *class_tree_list; + struct probj_resources_s *pr_objective_resources; ///@} /// \name debugging diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index f44da87a9..93fe8a68b 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -61,6 +61,22 @@ typedef struct obj_list_s { void *data; } obj_list; +typedef struct probj_resources_s { + progs_t *pr; + unsigned selector_index; + unsigned selector_index_max; + obj_list **selector_sels; + string_t *selector_names; + hashtab_t *selector_hash; + hashtab_t *classes; + hashtab_t *load_methods; + obj_list *unresolved_classes; + obj_list *unclaimed_categories; + obj_list *unclaimed_proto_list; + obj_list *module_list; + obj_list *class_tree_list; +} probj_t; + static obj_list *obj_list_free_list; static obj_list * @@ -144,7 +160,7 @@ class_tree_new (void) } static int -class_is_subclass_of_class (progs_t *pr, pr_class_t *class, +class_is_subclass_of_class (probj_t *probj, pr_class_t *class, pr_class_t *superclass) { while (class) { @@ -152,20 +168,22 @@ class_is_subclass_of_class (progs_t *pr, pr_class_t *class, return 1; if (!class->super_class) break; - class = Hash_Find (pr->classes, PR_GetString (pr, class->super_class)); + class = Hash_Find (probj->classes, + PR_GetString (probj->pr, class->super_class)); } return 0; } static class_tree * -create_tree_of_subclasses_inherited_from (progs_t *pr, pr_class_t *bottom, +create_tree_of_subclasses_inherited_from (probj_t *probj, pr_class_t *bottom, pr_class_t *upper) { + progs_t *pr = probj->pr; const char *super_class = PR_GetString (pr, bottom->super_class); pr_class_t *superclass; class_tree *tree, *prev; - superclass = bottom->super_class ? Hash_Find (pr->classes, super_class) + superclass = bottom->super_class ? Hash_Find (probj->classes, super_class) : 0; tree = prev = class_tree_new (); prev->class = bottom; @@ -174,7 +192,7 @@ create_tree_of_subclasses_inherited_from (progs_t *pr, pr_class_t *bottom, tree->class = superclass; tree->subclasses = list_cons (prev, tree->subclasses); super_class = PR_GetString (pr, superclass->super_class); - superclass = (superclass->super_class ? Hash_Find (pr->classes, + superclass = (superclass->super_class ? Hash_Find (probj->classes, super_class) : 0); prev = tree; @@ -183,16 +201,17 @@ create_tree_of_subclasses_inherited_from (progs_t *pr, pr_class_t *bottom, } static class_tree * -_obj_tree_insert_class (progs_t *pr, class_tree *tree, pr_class_t *class) +_obj_tree_insert_class (probj_t *probj, class_tree *tree, pr_class_t *class) { + progs_t *pr = probj->pr; obj_list *subclasses; class_tree *new_tree; if (!tree) - return create_tree_of_subclasses_inherited_from (pr, class, 0); + return create_tree_of_subclasses_inherited_from (probj, class, 0); if (class == tree->class) return tree; - if ((class->super_class ? Hash_Find (pr->classes, + if ((class->super_class ? Hash_Find (probj->classes, PR_GetString (pr, class->super_class)) : 0) == tree->class) { @@ -209,32 +228,32 @@ _obj_tree_insert_class (progs_t *pr, class_tree *tree, pr_class_t *class) tree->subclasses = list_cons (node, tree->subclasses); return tree; } - if (!class_is_subclass_of_class (pr, class, tree->class)) + if (!class_is_subclass_of_class (probj, class, tree->class)) return 0; for (subclasses = tree->subclasses; subclasses; subclasses = subclasses->next) { pr_class_t *aclass = ((class_tree *)subclasses->data)->class; - if (class_is_subclass_of_class (pr, class, aclass)) { - subclasses->data = _obj_tree_insert_class (pr, subclasses->data, + if (class_is_subclass_of_class (probj, class, aclass)) { + subclasses->data = _obj_tree_insert_class (probj, subclasses->data, class); return tree; } } - new_tree = create_tree_of_subclasses_inherited_from (pr, class, + new_tree = create_tree_of_subclasses_inherited_from (probj, class, tree->class); tree->subclasses = list_cons (new_tree, tree->subclasses); return tree; } static void -obj_tree_insert_class (progs_t *pr, pr_class_t *class) +obj_tree_insert_class (probj_t *probj, pr_class_t *class) { obj_list *list_node; class_tree *tree; - list_node = pr->class_tree_list; + list_node = probj->class_tree_list; while (list_node) { - tree = _obj_tree_insert_class (pr, list_node->data, class); + tree = _obj_tree_insert_class (probj, list_node->data, class); if (tree) { list_node->data = tree; break; @@ -243,73 +262,75 @@ obj_tree_insert_class (progs_t *pr, pr_class_t *class) } } if (!list_node) { - tree = _obj_tree_insert_class (pr, 0, class); - pr->class_tree_list = list_cons (tree, pr->class_tree_list); + tree = _obj_tree_insert_class (probj, 0, class); + probj->class_tree_list = list_cons (tree, probj->class_tree_list); } } static void -obj_create_classes_tree (progs_t *pr, pr_module_t *module) +obj_create_classes_tree (probj_t *probj, pr_module_t *module) { + progs_t *pr = probj->pr; pr_symtab_t *symtab = &G_STRUCT (pr, pr_symtab_t, module->symtab); int i; for (i = 0; i < symtab->cls_def_cnt; i++) { pr_class_t *class = &G_STRUCT (pr, pr_class_t, symtab->defs[i]); - obj_tree_insert_class (pr, class); + obj_tree_insert_class (probj, class); } } static void -obj_destroy_class_tree_node (progs_t *pr, class_tree *tree, int level) +obj_destroy_class_tree_node (probj_t *probj, class_tree *tree, int level) { tree->subclasses = (obj_list *) class_tree_free_list; class_tree_free_list = tree; } static void -obj_preorder_traverse (progs_t *pr, class_tree *tree, int level, - void (*func) (progs_t *, class_tree *, int)) +obj_preorder_traverse (probj_t *probj, class_tree *tree, int level, + void (*func) (probj_t *, class_tree *, int)) { obj_list *node; - func (pr, tree, level); + func (probj, tree, level); for (node = tree->subclasses; node; node = node->next) - obj_preorder_traverse (pr, node->data, level + 1, func); + obj_preorder_traverse (probj, node->data, level + 1, func); } static void -obj_postorder_traverse (progs_t *pr, class_tree *tree, int level, - void (*func) (progs_t *, class_tree *, int)) +obj_postorder_traverse (probj_t *probj, class_tree *tree, int level, + void (*func) (probj_t *, class_tree *, int)) { obj_list *node; for (node = tree->subclasses; node; node = node->next) - obj_postorder_traverse (pr, node->data, level + 1, func); - func (pr, tree, level); + obj_postorder_traverse (probj, node->data, level + 1, func); + func (probj, tree, level); } static const char * -selector_get_key (const void *s, void *_pr) +selector_get_key (const void *s, void *_probj) { - progs_t *pr = (progs_t *) _pr; - return PR_GetString (pr, pr->selector_names[(intptr_t) s]); + __auto_type probj = (probj_t *) _probj; + return PR_GetString (probj->pr, probj->selector_names[(intptr_t) s]); } static const char * -class_get_key (const void *c, void *pr) +class_get_key (const void *c, void *_probj) { - return PR_GetString ((progs_t *)pr, ((pr_class_t *)c)->name); + __auto_type probj = (probj_t *) _probj; + return PR_GetString (probj->pr, ((pr_class_t *)c)->name); } static uintptr_t -load_methods_get_hash (const void *m, void *pr) +load_methods_get_hash (const void *m, void *_probj) { return (uintptr_t) m; } static int -load_methods_compare (const void *m1, const void *m2, void *pr) +load_methods_compare (const void *m1, const void *m2, void *_probj) { return m1 == m2; } @@ -323,8 +344,9 @@ sel_eq (pr_sel_t *s1, pr_sel_t *s2) } static int -object_is_instance (progs_t *pr, pr_id_t *object) +object_is_instance (probj_t *probj, pr_id_t *object) { + progs_t *pr = probj->pr; pr_class_t *class; if (object) { @@ -335,8 +357,9 @@ object_is_instance (progs_t *pr, pr_id_t *object) } static string_t -object_get_class_name (progs_t *pr, pr_id_t *object) +object_get_class_name (probj_t *probj, pr_id_t *object) { + progs_t *pr = probj->pr; pr_class_t *class; if (object) { @@ -356,8 +379,9 @@ object_get_class_name (progs_t *pr, pr_id_t *object) //==================================================================== static void -finish_class (progs_t *pr, pr_class_t *class, pointer_t object_ptr) +finish_class (probj_t *probj, pr_class_t *class, pointer_t object_ptr) { + progs_t *pr = probj->pr; pr_class_t *meta = &G_STRUCT (pr, pr_class_t, class->class_pointer); pr_class_t *val; @@ -365,7 +389,7 @@ finish_class (progs_t *pr, pr_class_t *class, pointer_t object_ptr) if (class->super_class) { const char *super_class = PR_GetString (pr, class->super_class); const char *class_name = PR_GetString (pr, class->name); - val = Hash_Find (pr->classes, super_class); + val = Hash_Find (probj->classes, super_class); if (!val) PR_Error (pr, "broken class %s: super class %s not found", class_name, super_class); @@ -384,39 +408,40 @@ finish_class (progs_t *pr, pr_class_t *class, pointer_t object_ptr) //==================================================================== static int -add_sel_name (progs_t *pr, const char *name) +add_sel_name (probj_t *probj, const char *name) { - int ind = ++pr->selector_index; + int ind = ++probj->selector_index; int size, i; - if (pr->selector_index >= pr->selector_index_max) { - size = pr->selector_index_max + 128; - pr->selector_sels = realloc (pr->selector_sels, - size * sizeof (obj_list *)); - pr->selector_names = realloc (pr->selector_names, - size * sizeof (string_t)); - for (i = pr->selector_index_max; i < size; i++) { - pr->selector_sels[i] = 0; - pr->selector_names[i] = 0; + if (probj->selector_index >= probj->selector_index_max) { + size = probj->selector_index_max + 128; + probj->selector_sels = realloc (probj->selector_sels, + size * sizeof (obj_list *)); + probj->selector_names = realloc (probj->selector_names, + size * sizeof (string_t)); + for (i = probj->selector_index_max; i < size; i++) { + probj->selector_sels[i] = 0; + probj->selector_names[i] = 0; } - pr->selector_index_max = size; + probj->selector_index_max = size; } - pr->selector_names[ind] = PR_SetString (pr, name); + probj->selector_names[ind] = PR_SetString (probj->pr, name); return ind; } static pr_sel_t * -sel_register_typed_name (progs_t *pr, const char *name, const char *types, +sel_register_typed_name (probj_t *probj, const char *name, const char *types, pr_sel_t *sel) { + progs_t *pr = probj->pr; intptr_t index; int is_new = 0; obj_list *l; Sys_MaskPrintf (SYS_RUA_OBJ, " Registering SEL %s %s\n", name, types); - index = (intptr_t) Hash_Find (pr->selector_hash, name); + index = (intptr_t) Hash_Find (probj->selector_hash, name); if (index) { - for (l = pr->selector_sels[index]; l; l = l->next) { + for (l = probj->selector_sels[index]; l; l = l->next) { pr_sel_t *s = l->data; if (!types || !s->sel_types) { if (!s->sel_types && !types) { @@ -435,7 +460,7 @@ sel_register_typed_name (progs_t *pr, const char *name, const char *types, } } } else { - index = add_sel_name (pr, name); + index = add_sel_name (probj, name); is_new = 1; } if (!sel) @@ -446,11 +471,11 @@ sel_register_typed_name (progs_t *pr, const char *name, const char *types, l = obj_list_new (); l->data = sel; - l->next = pr->selector_sels[index]; - pr->selector_sels[index] = l; + l->next = probj->selector_sels[index]; + probj->selector_sels[index] = l; if (is_new) - Hash_Add (pr->selector_hash, (void *) index); + Hash_Add (probj->selector_hash, (void *) index); done: Sys_MaskPrintf (SYS_RUA_OBJ, " %d @ %x\n", sel->sel_id, PR_SetPointer (pr, sel)); @@ -458,40 +483,43 @@ done: } static pr_sel_t * -sel_register_name (progs_t *pr, const char *name) +sel_register_name (probj_t *probj, const char *name) { - return sel_register_typed_name (pr, name, "", 0); + return sel_register_typed_name (probj, name, "", 0); } static void -register_selectors_from_list (progs_t *pr, pr_method_list_t *method_list) +register_selectors_from_list (probj_t *probj, pr_method_list_t *method_list) { + progs_t *pr = probj->pr; int i; for (i = 0; i < method_list->method_count; i++) { pr_method_t *method = &method_list->method_list[i]; const char *name = PR_GetString (pr, method->method_name); const char *types = PR_GetString (pr, method->method_types); - pr_sel_t *sel = sel_register_typed_name (pr, name, types, 0); + pr_sel_t *sel = sel_register_typed_name (probj, name, types, 0); method->method_name = PR_SetPointer (pr, sel); } } static void -obj_register_selectors_from_class (progs_t *pr, pr_class_t *class) +obj_register_selectors_from_class (probj_t *probj, pr_class_t *class) { + progs_t *pr = probj->pr; pr_method_list_t *method_list = &G_STRUCT (pr, pr_method_list_t, class->methods); while (method_list) { - register_selectors_from_list (pr, method_list); + register_selectors_from_list (probj, method_list); method_list = &G_STRUCT (pr, pr_method_list_t, method_list->method_next); } } static void -obj_init_protocols (progs_t *pr, pr_protocol_list_t *protos) +obj_init_protocols (probj_t *probj, pr_protocol_list_t *protos) { + progs_t *pr = probj->pr; pr_class_t *proto_class; pr_protocol_t *proto; int i; @@ -499,9 +527,9 @@ obj_init_protocols (progs_t *pr, pr_protocol_list_t *protos) if (!protos) return; - if (!(proto_class = Hash_Find (pr->classes, "Protocol"))) { - pr->unclaimed_proto_list = list_cons (protos, - pr->unclaimed_proto_list); + if (!(proto_class = Hash_Find (probj->classes, "Protocol"))) { + probj->unclaimed_proto_list = list_cons (protos, + probj->unclaimed_proto_list); return; } @@ -509,8 +537,8 @@ obj_init_protocols (progs_t *pr, pr_protocol_list_t *protos) proto = &G_STRUCT (pr, pr_protocol_t, protos->list[i]); if (!proto->class_pointer) { proto->class_pointer = PR_SetPointer (pr, proto_class); - obj_init_protocols (pr, &G_STRUCT (pr, pr_protocol_list_t, - proto->protocol_list)); + obj_init_protocols (probj, &G_STRUCT (pr, pr_protocol_list_t, + proto->protocol_list)); } else { if (proto->class_pointer != PR_SetPointer (pr, proto_class)) PR_RunError (pr, "protocol broken"); @@ -519,8 +547,10 @@ obj_init_protocols (progs_t *pr, pr_protocol_list_t *protos) } static void -class_add_method_list (progs_t *pr, pr_class_t *class, pr_method_list_t *list) +class_add_method_list (probj_t *probj, pr_class_t *class, + pr_method_list_t *list) { + progs_t *pr = probj->pr; int i; for (i = 0; i < list->method_count; i++) { @@ -528,7 +558,7 @@ class_add_method_list (progs_t *pr, pr_class_t *class, pr_method_list_t *list) if (method->method_name) { const char *name = PR_GetString (pr, method->method_name); const char *types = PR_GetString (pr, method->method_types); - pr_sel_t *sel = sel_register_typed_name (pr, name, types, 0); + pr_sel_t *sel = sel_register_typed_name (probj, name, types, 0); method->method_name = PR_SetPointer (pr, sel); } } @@ -538,7 +568,7 @@ class_add_method_list (progs_t *pr, pr_class_t *class, pr_method_list_t *list) } static void -obj_class_add_protocols (progs_t *pr, pr_class_t *class, +obj_class_add_protocols (probj_t *probj, pr_class_t *class, pr_protocol_list_t *protos) { if (!protos) @@ -549,50 +579,54 @@ obj_class_add_protocols (progs_t *pr, pr_class_t *class, } static void -finish_category (progs_t *pr, pr_category_t *category, pr_class_t *class) +finish_category (probj_t *probj, pr_category_t *category, pr_class_t *class) { + progs_t *pr = probj->pr; pr_method_list_t *method_list; pr_protocol_list_t *protocol_list; if (category->instance_methods) { method_list = &G_STRUCT (pr, pr_method_list_t, category->instance_methods); - class_add_method_list (pr, class, method_list); + class_add_method_list (probj, class, method_list); } if (category->class_methods) { pr_class_t *meta = &G_STRUCT (pr, pr_class_t, class->class_pointer); method_list = &G_STRUCT (pr, pr_method_list_t, category->class_methods); - class_add_method_list (pr, meta, method_list); + class_add_method_list (probj, meta, method_list); } if (category->protocols) { protocol_list = &G_STRUCT (pr, pr_protocol_list_t, category->protocols); - obj_init_protocols (pr, protocol_list); - obj_class_add_protocols (pr, class, protocol_list); + obj_init_protocols (probj, protocol_list); + obj_class_add_protocols (probj, class, protocol_list); } } static void -obj_send_message_in_list (progs_t *pr, pr_method_list_t *method_list, +obj_send_message_in_list (probj_t *probj, pr_method_list_t *method_list, pr_class_t *class, pr_sel_t *op) { + progs_t *pr = probj->pr; int i; if (!method_list) return; - obj_send_message_in_list (pr, &G_STRUCT (pr, pr_method_list_t, - method_list->method_next), + obj_send_message_in_list (probj, &G_STRUCT (pr, pr_method_list_t, + method_list->method_next), class, op); for (i = 0; i < method_list->method_count; i++) { pr_method_t *mth = &method_list->method_list[i]; if (mth->method_name && sel_eq (&G_STRUCT (pr, pr_sel_t, mth->method_name), op) - && !Hash_FindElement (pr->load_methods, (void *) (intptr_t) mth->method_imp)) { - Hash_AddElement (pr->load_methods, (void *) (intptr_t) mth->method_imp); - + && !Hash_FindElement (probj->load_methods, + (void *) (intptr_t) mth->method_imp)) { + Hash_AddElement (probj->load_methods, + (void *) (intptr_t) mth->method_imp); + //FIXME need to wrap in save/restore params? PR_ExecuteProgram (pr, mth->method_imp); break; } @@ -600,58 +634,62 @@ obj_send_message_in_list (progs_t *pr, pr_method_list_t *method_list, } static void -send_load (progs_t *pr, class_tree *tree, int level) +send_load (probj_t *probj, class_tree *tree, int level) { - pr_sel_t *load_sel = sel_register_name (pr, "load"); + progs_t *pr = probj->pr; + pr_sel_t *load_sel = sel_register_name (probj, "load"); pr_class_t *class = tree->class; pr_class_t *meta = &G_STRUCT (pr, pr_class_t, class->class_pointer); pr_method_list_t *method_list = &G_STRUCT (pr, pr_method_list_t, meta->methods); - obj_send_message_in_list (pr, method_list, class, load_sel); + obj_send_message_in_list (probj, method_list, class, load_sel); } static void -obj_send_load (progs_t *pr) +obj_send_load (probj_t *probj) { + progs_t *pr = probj->pr; obj_list *m; - if (pr->unresolved_classes) { - pr_class_t *class = pr->unresolved_classes->data; + if (probj->unresolved_classes) { + pr_class_t *class = probj->unresolved_classes->data; const char *super_class = PR_GetString (pr, class->super_class); - while (Hash_Find (pr->classes, super_class)) { - list_remove (&pr->unresolved_classes); - if (pr->unresolved_classes) { - class = pr->unresolved_classes->data; + while (Hash_Find (probj->classes, super_class)) { + list_remove (&probj->unresolved_classes); + if (probj->unresolved_classes) { + class = probj->unresolved_classes->data; super_class = PR_GetString (pr, class->super_class); } else { break; } } - if (pr->unresolved_classes) + if (probj->unresolved_classes) return; } //XXX constant string stuff here (see init.c in libobjc source) - for (m = pr->module_list; m; m = m->next) - obj_create_classes_tree (pr, m->data); - while (pr->class_tree_list) { - obj_preorder_traverse (pr, pr->class_tree_list->data, 0, send_load); - obj_postorder_traverse (pr, pr->class_tree_list->data, 0, + for (m = probj->module_list; m; m = m->next) + obj_create_classes_tree (probj, m->data); + while (probj->class_tree_list) { + obj_preorder_traverse (probj, probj->class_tree_list->data, 0, + send_load); + obj_postorder_traverse (probj, probj->class_tree_list->data, 0, obj_destroy_class_tree_node); - list_remove (&pr->class_tree_list); + list_remove (&probj->class_tree_list); } //XXX callback - //for (m = pr->module_list; m; m = m->next) - // obj_create_classes_tree (pr, m->data); - obj_list_free (pr->module_list); - pr->module_list = 0; + //for (m = probj->module_list; m; m = m->next) + // obj_create_classes_tree (probj, m->data); + obj_list_free (probj->module_list); + probj->module_list = 0; } static pr_method_t * -obj_find_message (progs_t *pr, pr_class_t *class, pr_sel_t *selector) +obj_find_message (probj_t *probj, pr_class_t *class, pr_sel_t *selector) { + progs_t *pr = probj->pr; pr_class_t *c = class; pr_method_list_t *method_list; pr_method_t *method; @@ -661,7 +699,7 @@ obj_find_message (progs_t *pr, pr_class_t *class, pr_sel_t *selector) string_t *names; if (dev & SYS_RUA_MSG) { - names = pr->selector_names; + names = probj->selector_names; Sys_Printf ("Searching for %s\n", PR_GetString (pr, names[selector->sel_id])); } @@ -680,13 +718,13 @@ obj_find_message (progs_t *pr, pr_class_t *class, pr_sel_t *selector) i < method_list->method_count; i++, method++) { sel = &G_STRUCT (pr, pr_sel_t, method->method_name); if (developer->int_val & SYS_RUA_MSG) { - names = pr->selector_names; + names = probj->selector_names; Sys_Printf (" %s\n", PR_GetString (pr, names[sel->sel_id])); } if (sel->sel_id == selector->sel_id) { if (dev & SYS_RUA_MSG) { - names = pr->selector_names; + names = probj->selector_names; Sys_Printf ("found %s: %x\n", PR_GetString (pr, names[selector->sel_id]), method->method_imp); @@ -703,13 +741,14 @@ obj_find_message (progs_t *pr, pr_class_t *class, pr_sel_t *selector) } static void -obj_send_initialize (progs_t *pr, pr_class_t *class) +obj_send_initialize (probj_t *probj, pr_class_t *class) { + progs_t *pr = probj->pr; pr_method_list_t *method_list; pr_method_t *method; pr_sel_t *sel; pr_class_t *class_pointer; - pr_sel_t *selector = sel_register_name (pr, "initialize"); + pr_sel_t *selector = sel_register_name (probj, "initialize"); int i; if (PR_CLS_ISINITIALIZED (class)) @@ -718,8 +757,8 @@ obj_send_initialize (progs_t *pr, pr_class_t *class) PR_CLS_SETINITIALIZED (class); PR_CLS_SETINITIALIZED (class_pointer); if (class->super_class) - obj_send_initialize (pr, &G_STRUCT (pr, pr_class_t, - class->super_class)); + obj_send_initialize (probj, &G_STRUCT (pr, pr_class_t, + class->super_class)); method_list = &G_STRUCT (pr, pr_method_list_t, class_pointer->methods); while (method_list) { @@ -744,47 +783,50 @@ obj_send_initialize (progs_t *pr, pr_class_t *class) } static func_t -get_imp (progs_t *pr, pr_class_t *class, pr_sel_t *sel) +get_imp (probj_t *probj, pr_class_t *class, pr_sel_t *sel) { - pr_method_t *method = obj_find_message (pr, class, sel); + pr_method_t *method = obj_find_message (probj, class, sel); return method ? method->method_imp : 0; } static func_t -obj_msg_lookup (progs_t *pr, pr_id_t *receiver, pr_sel_t *op) +obj_msg_lookup (probj_t *probj, pr_id_t *receiver, pr_sel_t *op) { + progs_t *pr = probj->pr; pr_class_t *class; if (!receiver) return 0; class = &G_STRUCT (pr, pr_class_t, receiver->class_pointer); if (PR_CLS_ISCLASS (class)) { if (!PR_CLS_ISINITIALIZED (class)) - obj_send_initialize (pr, class); + obj_send_initialize (probj, class); } else if (PR_CLS_ISMETA (class) && PR_CLS_ISCLASS ((pr_class_t *) receiver)) { if (!PR_CLS_ISINITIALIZED ((pr_class_t *) receiver)) - obj_send_initialize (pr, (pr_class_t *) receiver); + obj_send_initialize (probj, (pr_class_t *) receiver); } - return get_imp (pr, class, op); + return get_imp (probj, class, op); } static func_t -obj_msg_lookup_super (progs_t *pr, pr_super_t *super, pr_sel_t *op) +obj_msg_lookup_super (probj_t *probj, pr_super_t *super, pr_sel_t *op) { + progs_t *pr = probj->pr; pr_class_t *class; if (!super->self) return 0; class = &G_STRUCT (pr, pr_class_t, super->class); - return get_imp (pr, class, op); + return get_imp (probj, class, op); } static void -obj_verror (progs_t *pr, pr_id_t *object, int code, const char *fmt, int count, +obj_verror (probj_t *probj, pr_id_t *object, int code, const char *fmt, int count, pr_type_t **args) { + progs_t *pr = probj->pr; dstring_t *dstr = dstring_newstr (); PR_Sprintf (pr, dstr, "obj_verror", fmt, count, args); @@ -792,8 +834,9 @@ obj_verror (progs_t *pr, pr_id_t *object, int code, const char *fmt, int count, } static void -dump_ivars (progs_t *pr, pointer_t _ivars) +dump_ivars (probj_t *probj, pointer_t _ivars) { + progs_t *pr = probj->pr; pr_ivar_list_t *ivars; int i; @@ -811,6 +854,7 @@ dump_ivars (progs_t *pr, pointer_t _ivars) static void rua___obj_exec_class (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_module_t *module = &P_STRUCT (pr, pr_module_t, 0); pr_symtab_t *symtab; pr_sel_t *sel; @@ -833,14 +877,14 @@ rua___obj_exec_class (progs_t *pr) symtab->cat_def_cnt, symtab->cat_def_cnt == 1 ? "y" : "ies"); - pr->module_list = list_cons (module, pr->module_list); + probj->module_list = list_cons (module, probj->module_list); sel = &G_STRUCT (pr, pr_sel_t, symtab->refs); for (i = 0; i < symtab->sel_ref_cnt; i++) { const char *name, *types; name = PR_GetString (pr, sel->sel_id); types = PR_GetString (pr, sel->sel_types); - sel_register_typed_name (pr, name, types, sel); + sel_register_typed_name (probj, name, types, sel); sel++; } @@ -860,7 +904,7 @@ rua___obj_exec_class (progs_t *pr) class->instance_size, class->ivars); if (developer->int_val & SYS_RUA_OBJ) - dump_ivars (pr, class->ivars); + dump_ivars (probj, class->ivars); Sys_MaskPrintf (SYS_RUA_OBJ, " instance methods: %x\n", class->methods); Sys_MaskPrintf (SYS_RUA_OBJ, " protocols: %x\n", class->protocols); @@ -870,30 +914,31 @@ rua___obj_exec_class (progs_t *pr) meta->instance_size, meta->ivars); if (developer->int_val & SYS_RUA_OBJ) - dump_ivars (pr, meta->ivars); + dump_ivars (probj, meta->ivars); class->subclass_list = 0; - Hash_Add (pr->classes, class); + Hash_Add (probj->classes, class); - obj_register_selectors_from_class (pr, class); - obj_register_selectors_from_class (pr, meta); + obj_register_selectors_from_class (probj, class); + obj_register_selectors_from_class (probj, meta); if (class->protocols) { pr_protocol_list_t *protocol_list; protocol_list = &G_STRUCT (pr, pr_protocol_list_t, class->protocols); - obj_init_protocols (pr, protocol_list); + obj_init_protocols (probj, protocol_list); } - if (class->super_class && !Hash_Find (pr->classes, super_class)) - pr->unresolved_classes = list_cons (class, pr->unresolved_classes); + if (class->super_class && !Hash_Find (probj->classes, super_class)) + probj->unresolved_classes = list_cons (class, + probj->unresolved_classes); } for (i = 0; i < symtab->cat_def_cnt; i++, ptr++) { pr_category_t *category = &G_STRUCT (pr, pr_category_t, *ptr); const char *class_name = PR_GetString (pr, category->class_name); - pr_class_t *class = Hash_Find (pr->classes, class_name); + pr_class_t *class = Hash_Find (probj->classes, class_name); Sys_MaskPrintf (SYS_RUA_OBJ, "Category %s (%s) @ %x\n", PR_GetString (pr, category->class_name), @@ -906,36 +951,37 @@ rua___obj_exec_class (progs_t *pr) category->protocols); if (class) { - finish_category (pr, category, class); + finish_category (probj, category, class); } else { - pr->unclaimed_categories = list_cons (category, - pr->unclaimed_categories); + probj->unclaimed_categories + = list_cons (category, probj->unclaimed_categories); } } - for (cell = &pr->unclaimed_categories; *cell; ) { + for (cell = &probj->unclaimed_categories; *cell; ) { pr_category_t *category = (*cell)->data; const char *class_name = PR_GetString (pr, category->class_name); - pr_class_t *class = Hash_Find (pr->classes, class_name); + pr_class_t *class = Hash_Find (probj->classes, class_name); if (class) { list_remove (cell); - finish_category (pr, category, class); + finish_category (probj, category, class); } else { cell = &(*cell)->next; } } - if (pr->unclaimed_proto_list && Hash_Find (pr->classes, "Protocol")) { - for (cell = &pr->unclaimed_proto_list; *cell; ) { - obj_init_protocols (pr, (*cell)->data); + if (probj->unclaimed_proto_list + && Hash_Find (probj->classes, "Protocol")) { + for (cell = &probj->unclaimed_proto_list; *cell; ) { + obj_init_protocols (probj, (*cell)->data); list_remove (cell); } } Sys_MaskPrintf (SYS_RUA_OBJ, "Finished initializing %s module\n", PR_GetString (pr, module->name)); - obj_send_load (pr); + obj_send_load (probj); Sys_MaskPrintf (SYS_RUA_OBJ, "Leaving %s module init\n", PR_GetString (pr, module->name)); } @@ -943,18 +989,20 @@ rua___obj_exec_class (progs_t *pr) static void rua_obj_error (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); int code = P_INT (pr, 1); const char *fmt = P_GSTRING (pr, 2); int count = pr->pr_argc - 3; pr_type_t **args = &pr->pr_params[3]; - obj_verror (pr, object, code, fmt, count, args); + obj_verror (probj, object, code, fmt, count, args); } static void rua_obj_verror (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); int code = P_INT (pr, 1); const char *fmt = P_GSTRING (pr, 2); @@ -965,12 +1013,13 @@ rua_obj_verror (progs_t *pr) for (i = 0; i < val->count; i++) args[i] = params + i * pr->pr_param_size; - obj_verror (pr, object, code, fmt, val->count, args); + obj_verror (probj, object, code, fmt, val->count, args); } static void rua_obj_set_error_handler (progs_t *pr) { + //probj_t *probj = pr->pr_objective_resources; //func_t func = P_INT (pr, 0); //arglist //XXX @@ -980,38 +1029,41 @@ rua_obj_set_error_handler (progs_t *pr) static void rua_obj_msg_lookup (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0); pr_sel_t *op = &P_STRUCT (pr, pr_sel_t, 1); - R_INT (pr) = obj_msg_lookup (pr, receiver, op); + R_INT (pr) = obj_msg_lookup (probj, receiver, op); } static void rua_obj_msg_lookup_super (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_super_t *super = &P_STRUCT (pr, pr_super_t, 0); pr_sel_t *_cmd = &P_STRUCT (pr, pr_sel_t, 1); - R_INT (pr) = obj_msg_lookup_super (pr, super, _cmd); + R_INT (pr) = obj_msg_lookup_super (probj, super, _cmd); } static void rua_obj_msg_sendv (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0); pr_sel_t *op = &P_STRUCT (pr, pr_sel_t, 1); pr_va_list_t *args = (pr_va_list_t *) &P_POINTER (pr, 2); pr_type_t *params = G_GPOINTER (pr, args->list); int count = args->count; - func_t imp = obj_msg_lookup (pr, receiver, op); + func_t imp = obj_msg_lookup (probj, receiver, op); count = bound (0, count, 6); if (count && pr_boundscheck->int_val) PR_BoundsCheckSize (pr, args->list, count * pr->pr_param_size); if (!imp) PR_RunError (pr, "%s does not respond to %s", - PR_GetString (pr, object_get_class_name (pr, receiver)), - PR_GetString (pr, pr->selector_names[op->sel_id])); + PR_GetString (pr, object_get_class_name (probj, receiver)), + PR_GetString (pr, probj->selector_names[op->sel_id])); if (count) memcpy (pr->pr_params[2], params, count * 4 * pr->pr_param_size); PR_CallFunction (pr, imp); @@ -1096,6 +1148,7 @@ rua_obj_free (progs_t *pr) static void rua_obj_get_uninstalled_dtable (progs_t *pr) { + //probj_t *probj = pr->pr_objective_resources; //XXX PR_RunError (pr, "%s, not implemented", __FUNCTION__); } @@ -1103,6 +1156,7 @@ rua_obj_get_uninstalled_dtable (progs_t *pr) static void rua_obj_msgSend (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &P_STRUCT (pr, pr_id_t, 0); pr_sel_t *_cmd = &P_STRUCT (pr, pr_sel_t, 1); func_t imp; @@ -1113,11 +1167,11 @@ rua_obj_msgSend (progs_t *pr) } if (!_cmd) PR_RunError (pr, "null selector"); - imp = obj_msg_lookup (pr, self, _cmd); + imp = obj_msg_lookup (probj, self, _cmd); if (!imp) PR_RunError (pr, "%s does not respond to %s", - PR_GetString (pr, object_get_class_name (pr, self)), - PR_GetString (pr, pr->selector_names[_cmd->sel_id])); + PR_GetString (pr, object_get_class_name (probj, self)), + PR_GetString (pr, probj->selector_names[_cmd->sel_id])); PR_CallFunction (pr, imp); } @@ -1125,16 +1179,17 @@ rua_obj_msgSend (progs_t *pr) static void rua_obj_msgSend_super (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_super_t *super = &P_STRUCT (pr, pr_super_t, 0); pr_sel_t *_cmd = &P_STRUCT (pr, pr_sel_t, 1); func_t imp; - imp = obj_msg_lookup_super (pr, super, _cmd); + imp = obj_msg_lookup_super (probj, super, _cmd); if (!imp) { pr_id_t *self = &G_STRUCT (pr, pr_id_t, super->self); PR_RunError (pr, "%s does not respond to %s", - PR_GetString (pr, object_get_class_name (pr, self)), - PR_GetString (pr, pr->selector_names[_cmd->sel_id])); + PR_GetString (pr, object_get_class_name (probj, self)), + PR_GetString (pr, probj->selector_names[_cmd->sel_id])); } pr->pr_params[0] = pr->pr_real_params[0]; P_POINTER (pr, 0) = super->self; @@ -1144,10 +1199,11 @@ rua_obj_msgSend_super (progs_t *pr) static void rua_obj_get_class (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; const char *name = P_GSTRING (pr, 0); pr_class_t *class; - class = Hash_Find (pr->classes, name); + class = Hash_Find (probj->classes, name); if (!class) PR_RunError (pr, "could not find class %s", name); RETURN_POINTER (pr, class); @@ -1156,16 +1212,18 @@ rua_obj_get_class (progs_t *pr) static void rua_obj_lookup_class (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; const char *name = P_GSTRING (pr, 0); pr_class_t *class; - class = Hash_Find (pr->classes, name); + class = Hash_Find (probj->classes, name); RETURN_POINTER (pr, class); } static void rua_obj_next_class (progs_t *pr) { + //probj_t *probj = pr->pr_objective_resources; //XXX PR_RunError (pr, "%s, not implemented", __FUNCTION__); } @@ -1175,10 +1233,11 @@ rua_obj_next_class (progs_t *pr) static void rua_sel_get_name (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 0); - if (sel->sel_id > 0 && sel->sel_id <= pr->selector_index) - R_STRING (pr) = pr->selector_names[sel->sel_id]; + if (sel->sel_id > 0 && sel->sel_id <= probj->selector_index) + R_STRING (pr) = probj->selector_names[sel->sel_id]; else R_STRING (pr) = 0; } @@ -1194,25 +1253,28 @@ rua_sel_get_type (progs_t *pr) static void rua_sel_get_uid (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; const char *name = P_GSTRING (pr, 0); - RETURN_POINTER (pr, sel_register_typed_name (pr, name, "", 0)); + RETURN_POINTER (pr, sel_register_typed_name (probj, name, "", 0)); } static void rua_sel_register_name (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; const char *name = P_GSTRING (pr, 0); - RETURN_POINTER (pr, sel_register_typed_name (pr, name, "", 0)); + RETURN_POINTER (pr, sel_register_typed_name (probj, name, "", 0)); } static void rua_sel_is_mapped (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; // FIXME might correspond to a string pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 0); - R_INT (pr) = sel->sel_id > 0 && sel->sel_id <= pr->selector_index; + R_INT (pr) = sel->sel_id > 0 && sel->sel_id <= probj->selector_index; } //==================================================================== @@ -1220,20 +1282,22 @@ rua_sel_is_mapped (progs_t *pr) static void rua_class_get_class_method (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); pr_sel_t *aSel = &P_STRUCT (pr, pr_sel_t, 1); pr_method_t *method; class = &G_STRUCT (pr, pr_class_t, class->class_pointer); - method = obj_find_message (pr, class, aSel); + method = obj_find_message (probj, class, aSel); RETURN_POINTER (pr, method); } static void rua_class_get_instance_method (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); pr_sel_t *aSel = &P_STRUCT (pr, pr_sel_t, 1); - pr_method_t *method = obj_find_message (pr, class, aSel); + pr_method_t *method = obj_find_message (probj, class, aSel); RETURN_POINTER (pr, method); } @@ -1363,6 +1427,7 @@ rua_class_get_gc_object_type (progs_t *pr) static void rua_class_ivar_set_gcinvisible (progs_t *pr) { + //probj_t *probj = pr->pr_objective_resources; //pr_class_t *impostor = &P_STRUCT (pr, pr_class_t, 0); //const char *ivarname = P_GSTRING (pr, 1); //int gcInvisible = P_INT (pr, 2); @@ -1383,10 +1448,11 @@ rua_method_get_imp (progs_t *pr) static void rua_get_imp (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 1); - R_INT (pr) = get_imp (pr, class, sel); + R_INT (pr) = get_imp (probj, class, sel); } //==================================================================== @@ -1476,9 +1542,10 @@ rua_object_get_meta_class (progs_t *pr) static void rua_object_get_class_name (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); - R_STRING (pr) = object_get_class_name (pr, object); + R_STRING (pr) = object_get_class_name (probj, object); } static void @@ -1496,9 +1563,10 @@ rua_object_is_class (progs_t *pr) static void rua_object_is_instance (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); - R_INT (pr) = object_is_instance (pr, object); + R_INT (pr) = object_is_instance (probj, object); } static void @@ -1524,6 +1592,7 @@ rua__i_Object__hash (progs_t *pr) static void rua__i_Object_error_error_ (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &P_STRUCT (pr, pr_id_t, 0); const char *fmt = P_GSTRING (pr, 2); dstring_t *dstr = dstring_new (); @@ -1531,14 +1600,15 @@ rua__i_Object_error_error_ (progs_t *pr) pr_type_t **args = &pr->pr_params[3]; dsprintf (dstr, "error: %s (%s)\n%s", - PR_GetString (pr, object_get_class_name (pr, self)), - object_is_instance (pr, self) ? "instance" : "class", fmt); - obj_verror (pr, self, 0, dstr->str, count, args); + PR_GetString (pr, object_get_class_name (probj, self)), + object_is_instance (probj, self) ? "instance" : "class", fmt); + obj_verror (probj, self, 0, dstr->str, count, args); } static void rua__c_Object__conformsToProtocol_ (progs_t *pr) { + //probj_t *probj = pr->pr_objective_resources; //pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); //pr_protocol_t *proto = &P_STRUCT (pr, pr_protocol_t, 2); //... @@ -1631,20 +1701,21 @@ static builtin_t obj_methods [] = { static int rua_init_finish (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_class_t **class_list, **class; - class_list = (pr_class_t **) Hash_GetList (pr->classes); + class_list = (pr_class_t **) Hash_GetList (probj->classes); if (*class_list) { pr_class_t *object_class; pointer_t object_ptr; - object_class = Hash_Find (pr->classes, "Object"); + object_class = Hash_Find (probj->classes, "Object"); if (object_class && !object_class->super_class) object_ptr = (pr_type_t *)object_class - pr->pr_globals; else PR_Error (pr, "root class Object not found"); for (class = class_list; *class; class++) - finish_class (pr, *class, object_ptr); + finish_class (probj, *class, object_ptr); } free (class_list); @@ -1652,40 +1723,42 @@ rua_init_finish (progs_t *pr) } static int -rua_init_runtime (progs_t *pr) +rua_obj_init_runtime (progs_t *pr) { + probj_t *probj = pr->pr_objective_resources; pr_def_t *def; unsigned i; - if (!pr->selector_hash) - pr->selector_hash = Hash_NewTable (1021, selector_get_key, 0, pr); + if (!probj->selector_hash) + probj->selector_hash = Hash_NewTable (1021, selector_get_key, 0, + probj); else - Hash_FlushTable (pr->selector_hash); - pr->selector_index = 0; - for (i = 0; i < pr->selector_index_max; i++) { - obj_list_free (pr->selector_sels[i]); - pr->selector_sels[i] = 0; - pr->selector_names[i] = 0; + Hash_FlushTable (probj->selector_hash); + probj->selector_index = 0; + for (i = 0; i < probj->selector_index_max; i++) { + obj_list_free (probj->selector_sels[i]); + probj->selector_sels[i] = 0; + probj->selector_names[i] = 0; } - if (!pr->classes) - pr->classes = Hash_NewTable (1021, class_get_key, 0, pr); + if (!probj->classes) + probj->classes = Hash_NewTable (1021, class_get_key, 0, probj); else - Hash_FlushTable (pr->classes); + Hash_FlushTable (probj->classes); - if (!pr->load_methods) { - pr->load_methods = Hash_NewTable (1021, 0, 0, pr); - Hash_SetHashCompare (pr->load_methods, load_methods_get_hash, + if (!probj->load_methods) { + probj->load_methods = Hash_NewTable (1021, 0, 0, probj); + Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, load_methods_compare); } else { - Hash_FlushTable (pr->load_methods); + Hash_FlushTable (probj->load_methods); } - pr->unresolved_classes = 0; - pr->unclaimed_categories = 0; - pr->unclaimed_proto_list = 0; - pr->module_list = 0; - pr->class_tree_list = 0; + probj->unresolved_classes = 0; + probj->unclaimed_categories = 0; + probj->unclaimed_proto_list = 0; + probj->module_list = 0; + probj->class_tree_list = 0; if ((def = PR_FindField (pr, ".this"))) pr->fields.this = def->ofs; @@ -1694,17 +1767,30 @@ rua_init_runtime (progs_t *pr) return 1; } +static void +rua_obj_cleanup (progs_t *pr, void *data) +{ + __auto_type probj = (probj_t *) data; + pr->pr_objective_resources = probj; +} + void RUA_Obj_Init (progs_t *pr, int secure) { + probj_t *probj = calloc (1, sizeof (*probj)); + probj->pr = pr; + + PR_Resources_Register (pr, "RUA_ObjectiveQuakeC", probj, rua_obj_cleanup); + PR_RegisterBuiltins (pr, obj_methods); - PR_AddLoadFunc (pr, rua_init_runtime); + PR_AddLoadFunc (pr, rua_obj_init_runtime); } func_t RUA_Obj_msg_lookup (progs_t *pr, pointer_t _self, pointer_t __cmd) { + probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &G_STRUCT (pr, pr_id_t, _self); pr_sel_t *_cmd = &G_STRUCT (pr, pr_sel_t, __cmd); func_t imp; @@ -1713,11 +1799,11 @@ RUA_Obj_msg_lookup (progs_t *pr, pointer_t _self, pointer_t __cmd) return 0; if (!_cmd) PR_RunError (pr, "null selector"); - imp = obj_msg_lookup (pr, self, _cmd); + imp = obj_msg_lookup (probj, self, _cmd); if (!imp) PR_RunError (pr, "%s does not respond to %s", - PR_GetString (pr, object_get_class_name (pr, self)), - PR_GetString (pr, pr->selector_names[_cmd->sel_id])); + PR_GetString (pr, object_get_class_name (probj, self)), + PR_GetString (pr, probj->selector_names[_cmd->sel_id])); return imp; } From f185e07ad2ed23e64ae80655e3044c9536670d2a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 01:01:47 +0900 Subject: [PATCH 0417/3664] Fix some missing dependencies Generally not a problem with libtool and its automatic dependencies, but best to be explicit. --- config.d/build_control.m4 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index abc60cd75..13004a6c8 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -372,6 +372,7 @@ QF_DEPS(QFCC, QF_DEPS(QFCC_TEST, [], [$(top_builddir)/libs/ruamoko/libQFruamoko.la + $(top_builddir)/libs/gamecode/libQFgamecode.la $(top_builddir)/libs/util/libQFutil.la], [$(WIN32_LIBS)], ) @@ -406,6 +407,7 @@ QF_DEPS(QFVIS, QF_DEPS(QWAQ, [], [$(top_builddir)/libs/ruamoko/libQFruamoko.la + $(top_builddir)/libs/gamecode/libQFgamecode.la $(top_builddir)/libs/util/libQFutil.la], [$(WIN32_LIBS)], ) @@ -413,6 +415,7 @@ QF_DEPS(CARNE, [], [$(top_builddir)/libs/gib/libQFgib.la $(top_builddir)/libs/ruamoko/libQFruamoko.la + $(top_builddir)/libs/gamecode/libQFgamecode.la $(top_builddir)/libs/util/libQFutil.la], [$(WIN32_LIBS)], ) From 35c9d6ee38ae3aa00097627c5ef86be520935962 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 01:20:28 +0900 Subject: [PATCH 0418/3664] Make pr_obcode.c mostly thread safe Its public data is all read-only, and once set up, its private data is too (just don't call init in multiple threads). --- include/QF/pr_comp.h | 6 +++--- libs/gamecode/pr_opcode.c | 12 ++++++------ tools/qfcc/source/opcodes.c | 3 ++- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 60022098f..03f5b3a46 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -50,8 +50,8 @@ typedef enum { ev_type_count // not a type, gives number of types } etype_t; -extern pr_ushort_t pr_type_size[ev_type_count]; -extern const char *pr_type_name[ev_type_count]; +extern const pr_ushort_t pr_type_size[ev_type_count]; +extern const char * const pr_type_name[ev_type_count]; #define OFS_NULL 0 #define OFS_RETURN 1 @@ -407,7 +407,7 @@ typedef struct opcode_s { const char *fmt; } opcode_t; -extern opcode_t pr_opcodes[]; +extern const opcode_t pr_opcodes[]; opcode_t *PR_Opcode (pr_short_t opcode); void PR_Opcode_Init (void); // idempotent diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index ab266c84c..853176925 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -46,9 +46,9 @@ #include "compat.h" -hashtab_t *opcode_table; +static hashtab_t *opcode_table; -VISIBLE pr_ushort_t pr_type_size[ev_type_count] = { +VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { 1, // ev_void 1, // ev_string 1, // ev_float @@ -65,7 +65,7 @@ VISIBLE pr_ushort_t pr_type_size[ev_type_count] = { 0, // ev_invalid not a valid/simple type }; -VISIBLE const char *pr_type_name[ev_type_count] = { +VISIBLE const char * const pr_type_name[ev_type_count] = { "void", "string", "float", @@ -98,7 +98,7 @@ VISIBLE const char *pr_type_name[ev_type_count] = { // c operand c // x place holder for P (padding) // 0-7 parameter index (for P) -VISIBLE opcode_t pr_opcodes[] = { +VISIBLE const opcode_t pr_opcodes[] = { {"", "done", OP_DONE, false, // OP_DONE is actually the same as ev_entity, ev_field, ev_void, // OP_RETURN, the types are bogus PROG_ID_VERSION, @@ -1492,7 +1492,7 @@ PR_Opcode (pr_short_t opcode) VISIBLE void PR_Opcode_Init (void) { - opcode_t *op; + const opcode_t *op; if (opcode_table) { // already initialized @@ -1502,7 +1502,7 @@ PR_Opcode_Init (void) Hash_SetHashCompare (opcode_table, opcode_get_hash, opcode_compare); for (op = pr_opcodes; op->name; op++) { - Hash_AddElement (opcode_table, op); + Hash_AddElement (opcode_table, (void *) op); } } diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index bf8b5b189..bbf10250a 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -131,7 +131,8 @@ opcode_free (void *_op, void *unused) void opcode_init (void) { - opcode_t *op, *mop; + const opcode_t *op; + opcode_t *mop; if (opcode_type_table) { Hash_FlushTable (opcode_void_table); From 4c1b6ce76ce62c287f3dde86b721c8e23ad2f587 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 01:55:56 +0900 Subject: [PATCH 0419/3664] Make pr_parse thread safe Or at least, conversion to property list is thread safe. --- libs/gamecode/pr_parse.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index f17b69bf1..c63bb71b5 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -68,15 +68,11 @@ Easier to parse than PR_ValueString */ static const char * -PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val) +PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) { - static dstring_t *line = 0; pr_def_t *def; dfunction_t *f; - if (!line) - line = dstring_new (); - type &= ~DEF_SAVEGLOBAL; switch (type) { @@ -121,6 +117,7 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val) VISIBLE plitem_t * ED_EntityDict (progs_t *pr, edict_t *ed) { + dstring_t *dstr = dstring_newstr (); plitem_t *entity = PL_NewDictionary (); pr_uint_t i; int j; @@ -149,10 +146,11 @@ ED_EntityDict (progs_t *pr, edict_t *ed) if (j == pr_type_size[type]) continue; - value = PR_UglyValueString (pr, type, v); + value = PR_UglyValueString (pr, type, v, dstr); PL_D_AddObject (entity, name, PL_NewString (value)); } } + dstring_delete (dstr); return entity; } @@ -165,6 +163,7 @@ ED_EntityDict (progs_t *pr, edict_t *ed) VISIBLE plitem_t * ED_GlobalsDict (progs_t *pr) { + dstring_t *dstr = dstring_newstr (); plitem_t *globals = PL_NewDictionary (); pr_uint_t i; const char *name; @@ -183,9 +182,10 @@ ED_GlobalsDict (progs_t *pr) continue; name = PR_GetString (pr, def->name); - value = PR_UglyValueString (pr, type, &pr->pr_globals[def->ofs]); + value = PR_UglyValueString (pr, type, &pr->pr_globals[def->ofs], dstr); PL_D_AddObject (globals, name, PL_NewString (value)); } + dstring_delete (dstr); return globals; } From 42713cad8b13b589c4b218b3d0ccbd06ae139777 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 09:39:03 +0900 Subject: [PATCH 0420/3664] Make script much friendlier to use It now simply sets an error message pointer and returns false if there's an error. --- include/QF/script.h | 6 ++++-- libs/gamecode/pr_debug.c | 10 +++------ libs/ruamoko/rua_script.c | 13 ++--------- libs/util/script.c | 45 +++++++++++++++++---------------------- 4 files changed, 28 insertions(+), 46 deletions(-) diff --git a/include/QF/script.h b/include/QF/script.h index 357e5100b..34e6f269a 100644 --- a/include/QF/script.h +++ b/include/QF/script.h @@ -41,8 +41,9 @@ typedef struct script_s { /// line number of the file being processed. used only for error reporting /// but updated internally. int line; - /// if set, will be called instead of the internal error handler - void (*error)(struct script_s *script, const char *msg); + /// contains last error message or null if no error + /// if set, no tokens will be parsed. + const char *error; /// if set, multi line quoted tokens will be treated as errors int no_quote_lines; /// if set, characters in this string will always be lexed as single @@ -65,6 +66,7 @@ void Script_Delete (script_t *script); /** Prepare a script_t object for parsing. The caller is responsible for freeing the memory associated with file and data when parsing is complete. + Resets \a script->error \param script The script_t object being parsed \param file Name of the file being parsed. used only for error reporting \param data The script to be parsed diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 9fd61b020..f7f3f3b7c 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -197,12 +197,6 @@ source_path_f (cvar_t *var) source_paths[i] = 0; } -static void -pr_debug_expression_error (script_t *script, const char *msg) -{ - Sys_Printf ("%s\n", msg); -} - #define RUP(x,a) (((x) + ((a) - 1)) & ~((a) - 1)) static pr_short_t __attribute__((pure)) pr_debug_type_size (const progs_t *pr, const qfot_type_t *type) @@ -266,7 +260,6 @@ parse_expression (progs_t *pr, const char *expr, int conditional) d.type = ev_invalid; d.name = 0; es = Script_New (); - es->error = pr_debug_expression_error; Script_Start (es, "", expr); expr_ptr = 0; es->single = "{}()':[]."; @@ -323,6 +316,9 @@ parse_expression (progs_t *pr, const char *expr, int conditional) Sys_Printf ("ignoring tail\n"); } error: + if (es->error) { + Sys_Printf (es->error); + } Script_Delete (es); return d; } diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index c6fae5750..ff5b2ab0a 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -48,7 +48,6 @@ typedef struct { script_t script; string_t dstr; progs_t *pr; - string_t err_msg; } rua_script_t; typedef struct { @@ -92,13 +91,6 @@ bi_script_clear (progs_t *pr, void *data) script_reset (res); } -static void -bi_script_error (script_t *_script, const char *msg) -{ - rua_script_t *script = (rua_script_t *)_script; - script->err_msg = PR_SetString (script->pr, msg); -} - static void bi_Script_New (progs_t *pr) { @@ -110,7 +102,6 @@ bi_Script_New (progs_t *pr) script->dstr = PR_NewMutableString (pr); script->script.token = PR_GetMutableString (pr, script->dstr); - script->script.error = bi_script_error; script->pr = pr; R_INT (pr) = script_index (res, script); } @@ -180,8 +171,8 @@ bi_Script_Error (progs_t *pr) if (!script) PR_RunError (pr, "invalid script handle"); - R_STRING (pr) = script->err_msg; - script->err_msg = 0; + R_STRING (pr) = PR_SetString (pr, script->script.error); + script->script.error = 0; } static void diff --git a/libs/util/script.c b/libs/util/script.c index eeb1df977..fa8b51ae0 100644 --- a/libs/util/script.c +++ b/libs/util/script.c @@ -34,19 +34,6 @@ #include "QF/dstring.h" #include "QF/script.h" -static void __attribute__ ((format (printf, 2, 3), noreturn)) -script_error (script_t *script, const char *fmt, ...) -{ - va_list args; - - va_start (args, fmt); - fprintf (stderr, "%s:%d: ", script->file, script->line); - vfprintf (stderr, fmt, args); - fprintf (stderr, "\n"); - va_end (args); - exit (1); -} - VISIBLE script_t * Script_New (void) { @@ -69,11 +56,16 @@ Script_Start (script_t *script, const char *file, const char *data) script->file = file; script->p = data; script->unget = false; + script->error = 0; } VISIBLE qboolean Script_TokenAvailable (script_t *script, qboolean crossline) { + if (script->error) { + return false; + } + if (script->unget) return true; skipspace: @@ -111,6 +103,10 @@ Script_GetToken (script_t *script, qboolean crossline) { const char *token_p; + if (script->error) { + return false; + } + if (script->unget) { // is a token allready waiting? script->unget = false; return true; @@ -118,10 +114,7 @@ Script_GetToken (script_t *script, qboolean crossline) if (!Script_TokenAvailable (script, crossline)) { if (!crossline) { - if (script->error) - script->error (script, "line is incomplete"); - else - script_error (script, "line is incomplete"); + script->error = "line is incomplete"; } return false; } @@ -134,18 +127,13 @@ Script_GetToken (script_t *script, qboolean crossline) while (*script->p != '"') { if (!*script->p) { script->line = start_line; - if (script->error) - script->error (script, "EOF inside quoted token"); - else - script_error (script, "EOF inside quoted token"); + script->error = "EOF inside quoted token"; return false; } if (*script->p == '\n') { if (script->no_quote_lines) { - if (script->error) - script->error (script, "EOL inside quoted token"); - else - script_error (script, "EOL inside quoted token"); + script->error = "EOL inside quoted token"; + return false; } script->line++; } @@ -175,11 +163,16 @@ Script_GetToken (script_t *script, qboolean crossline) VISIBLE void Script_UngetToken (script_t *script) { - script->unget = true; + if (!script->error) { + script->unget = true; + } } VISIBLE const char * Script_Token (script_t *script) { + if (script->error) { + return 0; + } return script->token->str; } From d60291a73e16308125df3ede2dc3428283bd7cca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 09:46:59 +0900 Subject: [PATCH 0421/3664] Clean up a lot of va usage va is not thread-safe (it's not save even without threads), and I want to be able to run progs in threads. --- libs/gamecode/pr_edict.c | 12 ------------ libs/gamecode/pr_load.c | 5 ----- libs/gamecode/pr_parse.c | 19 +++++++------------ libs/gamecode/pr_resolve.c | 16 +++++----------- libs/ruamoko/rua_qfile.c | 4 +--- 5 files changed, 13 insertions(+), 43 deletions(-) diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 29559f8f1..e3bfc778b 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -34,22 +34,10 @@ #ifdef HAVE_STRINGS_H # include #endif -#include -#include -#include "QF/cbuf.h" -#include "QF/crc.h" #include "QF/cvar.h" -#include "QF/dstring.h" -#include "QF/hash.h" -#include "QF/idparse.h" #include "QF/progs.h" -#include "QF/qdefs.h" -#include "QF/qendian.h" -#include "QF/quakefs.h" #include "QF/sys.h" -#include "QF/zone.h" -#include "QF/va.h" #include "compat.h" diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index c8157efa8..df72cbbc9 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -34,22 +34,17 @@ #ifdef HAVE_STRINGS_H # include #endif -#include -#include -#include "QF/cmd.h" #include "QF/crc.h" #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" #include "QF/progs.h" -#include "QF/qdefs.h" #include "QF/qendian.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/zone.h" -#include "QF/va.h" #include "compat.h" diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index c63bb71b5..2652694e8 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -43,21 +43,12 @@ #include #endif -#include "QF/cbuf.h" -#include "QF/crc.h" -#include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/hash.h" #include "QF/mathlib.h" #include "QF/progs.h" -#include "QF/qdefs.h" #include "QF/qfplist.h" -#include "QF/qendian.h" -#include "QF/quakefs.h" #include "QF/script.h" #include "QF/sys.h" -#include "QF/zone.h" -#include "QF/va.h" #include "compat.h" @@ -301,6 +292,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) VISIBLE plitem_t * ED_ConvertToPlist (script_t *script, int nohack) { + dstring_t *dstr = dstring_newstr (); plitem_t *plist = PL_NewArray (); plitem_t *ent; plitem_t *key; @@ -341,15 +333,18 @@ ED_ConvertToPlist (script_t *script, int nohack) token = script->token->str; if (strequal (token, "}")) Sys_Error ("ED_ConvertToPlist: closing brace without data"); - if (anglehack) - value = PL_NewString (va ("0 %s 0", token)); - else + if (anglehack) { + dsprintf (dstr, "0 %s 0", token); + value = PL_NewString (dstr->str); + } else { value = PL_NewString (token); + } PL_D_AddObject (ent, PL_String (key), value); PL_Free (key); } PL_A_AddObject (plist, ent); } + dstring_delete (dstr); return plist; } diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 0f7acaa8f..5297f101a 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -34,23 +34,14 @@ #ifdef HAVE_STRINGS_H # include #endif -#include -#include -#include "QF/cmd.h" -#include "QF/crc.h" -#include "QF/cvar.h" #include "QF/hash.h" #include "QF/progs.h" -#include "QF/qdefs.h" -#include "QF/qendian.h" -#include "QF/quakefs.h" #include "QF/sys.h" -#include "QF/zone.h" -#include "QF/va.h" #include "compat.h" +static const char param_str[] = ".param_0"; pr_def_t * PR_GlobalAtOfs (progs_t * pr, pointer_t ofs) @@ -124,11 +115,14 @@ PR_ResolveGlobals (progs_t *pr) pr->pr_param_size = OFS_PARM1 - OFS_PARM0; pr->pr_param_alignment = 0; // log2 } else { + char *param_n = alloca (sizeof (param_str)); + strcpy (param_n, param_str); if (!(def = PR_FindGlobal (pr, sym = ".return"))) goto error; pr->pr_return = &pr->pr_globals[def->ofs]; for (i = 0; i < MAX_PARMS; i++) { - if (!(def = PR_FindGlobal (pr, sym = va(".param_%d", i)))) + param_n[sizeof (param_str) - 2] = i + '0'; + if (!(def = PR_FindGlobal (pr, sym = param_n))) goto error; pr->pr_params[i] = &pr->pr_globals[def->ofs]; } diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index 057ff0ef6..d96c433a2 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -38,9 +38,7 @@ #include "QF/dstring.h" #include "QF/progs.h" -#include "QF/quakefs.h" -#include "QF/va.h" -#include "QF/zone.h" +#include "QF/quakeio.h" #include "rua_internal.h" From aa02069dd1c2fd2d4b85e3ee06738cefcc4999e1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 13:40:26 +0900 Subject: [PATCH 0422/3664] Add a breakpoint flag to opcodes The progs execution code will call a breakpoint handler just before executing an instruction with the flag set. This means there's no need for the breakpoint handler to mess with execution state or even the instruction in order to continue past the breakpoint. The flag being set in a progs file is invalid. --- include/QF/pr_comp.h | 1 + include/QF/progs.h | 1 + libs/gamecode/pr_exec.c | 11 ++++++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 03f5b3a46..6458d3913 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -396,6 +396,7 @@ typedef enum { OP_MOD_F, OP_MOD_D, } pr_opcode_e; +#define OP_BREAK 0x8000 typedef struct opcode_s { const char *name; diff --git a/include/QF/progs.h b/include/QF/progs.h index 369360449..5abd0d1c6 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1776,6 +1776,7 @@ struct progs_s { /// \name debugging ///@{ struct prdeb_resources_s *pr_debug_resources; + void (*breakpoint_handler) (progs_t *pr); pr_type_t *watch; int wp_conditional; pr_type_t wp_val; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 024594d81..b933572e4 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -440,7 +440,16 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) if (pr->pr_trace) PR_PrintStatement (pr, st, 1); - switch (st->op) { + if (st->op & OP_BREAK) { + if (pr->breakpoint_handler) { + pr->breakpoint_handler (pr); + } else { + PR_RunError (pr, "breakpoint hit"); + } + } + + pr_opcode_e op = st->op & ~OP_BREAK; + switch (op) { case OP_ADD_D: OPC_double_var = OPA_double_var + OPB_double_var; break; From 225a375ab96225a4ebc2bf855132241028f616f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 13:43:03 +0900 Subject: [PATCH 0423/3664] Extend the lifetime of return-strings This is done by putting the most recently used return-string at the end of the queue for recycling. --- libs/gamecode/pr_strings.c | 82 +++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 18 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index a8c8c4fee..cb74797a5 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -44,14 +44,20 @@ #include "QF/progs.h" #include "QF/va.h" +typedef struct strref_slot_s { + struct strref_slot_s *next; + struct strref_slot_s **prev; + strref_t *strref; +} strref_slot_t; + typedef struct prstr_resources_s { progs_t *pr; dstring_mem_t ds_mem; strref_t *free_string_refs; strref_t *static_strings; strref_t **string_map; - strref_t *return_strings[PR_RS_SLOTS]; - int rs_slot; + strref_slot_t return_strings[PR_RS_SLOTS]; + strref_slot_t *rs_slot; unsigned dyn_str_size; struct hashtab_s *strref_hash; int num_strings; @@ -68,7 +74,7 @@ typedef enum { struct strref_s { strref_t *next; - strref_t **prev; + strref_slot_t *rs_slot; str_e type; union { char *string; @@ -146,6 +152,7 @@ new_string_ref (prstr_resources_t *res) sr = res->free_string_refs; res->free_string_refs = sr->next; sr->next = 0; + sr->rs_slot = 0; return sr; } @@ -153,8 +160,6 @@ static void free_string_ref (prstr_resources_t *res, strref_t *sr) { sr->type = str_free; - if (sr->prev) - *sr->prev = sr->next; sr->next = res->free_string_refs; res->free_string_refs = sr; } @@ -208,11 +213,18 @@ pr_strings_clear (progs_t *pr, void *data) int i; for (i = 0; i < PR_RS_SLOTS; i++) { - if (res->return_strings[i]) - free_string_ref (res, res->return_strings[i]); - res->return_strings[i] = 0; + if (res->return_strings[i].strref) + free_string_ref (res, res->return_strings[i].strref); + res->return_strings[i].strref = 0; + } + if (!res->rs_slot) { + strref_slot_t * const rs = res->return_strings; + for (i = 0; i < PR_RS_SLOTS; i++) { + rs[i].next = &rs[(i + 1) % PR_RS_SLOTS]; + rs[i].prev = &rs[(i - 1 + PR_RS_SLOTS) % PR_RS_SLOTS].next; + } + res->rs_slot = rs; } - res->rs_slot = 0; pr->pr_string_resources = res; pr->pr_xtstr = 0; @@ -265,6 +277,28 @@ PR_LoadStrings (progs_t *pr) return 1; } +static void +requeue_strref (prstr_resources_t *res, strref_t *sr) +{ + strref_slot_t *rs_slot = sr->rs_slot; + if (rs_slot->next != res->rs_slot) { + // this is the oldest slot, so advance res->rs_slot to the + // next oldest slot so this slot does not get reused just yet + if (res->rs_slot == rs_slot) { + res->rs_slot = rs_slot->next; + } + // unlink this slot from the chain + rs_slot->next->prev = rs_slot->prev; + *rs_slot->prev = rs_slot->next; + // link this slot just before the oldest slot: all the slots + // form a doubly linked circular list + rs_slot->prev = res->rs_slot->prev; + rs_slot->next = res->rs_slot; + *res->rs_slot->prev = rs_slot; + res->rs_slot->prev = &rs_slot->next; + } +} + static inline strref_t * get_strref (prstr_resources_t *res, string_t num) { @@ -287,15 +321,17 @@ get_strref (prstr_resources_t *res, string_t num) static inline __attribute__((pure)) const char * get_string (progs_t *pr, string_t num) { + __auto_type res = pr->pr_string_resources; if (num < 0) { - strref_t *ref = get_strref (pr->pr_string_resources, num); + strref_t *ref = get_strref (res, num); if (!ref) return 0; switch (ref->type) { + case str_return: + requeue_strref (res, ref); case str_static: case str_temp: case str_dynamic: - case str_return: return ref->s.string; case str_mutable: return ref->s.dstring->str; @@ -313,7 +349,7 @@ get_string (progs_t *pr, string_t num) VISIBLE qboolean PR_StringValid (progs_t *pr, string_t num) { - return get_string (pr, num) != 0; + return get_strref (pr->pr_string_resources, num) != 0; } VISIBLE const char * @@ -387,21 +423,32 @@ PR_SetReturnString (progs_t *pr, const char *s) if (!s) s = ""; if ((sr = Hash_Find (res->strref_hash, s))) { + if (sr->type == str_return && sr->rs_slot) { + requeue_strref (res, sr); + } else if ((sr->type == str_return && !sr->rs_slot) + || (sr->type != str_return && sr->rs_slot)) { + PR_Error (pr, "internal string error"); + } return string_index (res, sr); } - if ((sr = res->return_strings[res->rs_slot])) { - if (sr->type != str_return) + // grab the string ref from the oldest slot, or make a new one if the + // slot is empty + if ((sr = res->rs_slot->strref)) { + if (sr->type != str_return || sr->rs_slot != res->rs_slot) { PR_Error (pr, "internal string error"); + } pr_strfree (pr, sr->s.string); } else { sr = new_string_ref (res); } sr->type = str_return; + sr->rs_slot = res->rs_slot; sr->s.string = pr_strdup(pr, s); - res->return_strings[res->rs_slot++] = sr; - res->rs_slot %= PR_RS_SLOTS; + // the oldest slot just became the newest, so advance to the next oldest + res->rs_slot = res->rs_slot->next; + return string_index (res, sr); } @@ -525,8 +572,7 @@ PR_FreeString (progs_t *pr, string_t str) free_string_ref (res, sr); return; } - if (!get_string (pr, str)) - PR_RunError (pr, "attempt to free invalid string %d", str); + PR_RunError (pr, "attempt to free invalid string %d", str); } void From 383a7fe5e1ab15edf388657f618e4dee4cb14c06 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 13:45:14 +0900 Subject: [PATCH 0424/3664] Remove File_Open Other than its blocking of access to certain files, it really wasn't that useful compared to the functions in qfs, and pointless with access to qfs anyway. --- include/rua_internal.h | 2 - libs/ruamoko/Makefile.am | 2 +- libs/ruamoko/rua_file.c | 184 ---------------------------------- libs/ruamoko/rua_init.c | 1 - libs/ruamoko/rua_qfs.c | 7 ++ ruamoko/cl_menu/client_menu.r | 14 +-- ruamoko/include/Makefile.am | 2 +- ruamoko/include/file.h | 8 -- ruamoko/include/qfs.h | 1 + ruamoko/lib/Makefile.am | 2 +- ruamoko/lib/file.r | 3 - ruamoko/lib/qfs.r | 1 + 12 files changed, 19 insertions(+), 208 deletions(-) delete mode 100644 libs/ruamoko/rua_file.c delete mode 100644 ruamoko/include/file.h delete mode 100644 ruamoko/lib/file.r diff --git a/include/rua_internal.h b/include/rua_internal.h index 0b6b34801..158d6e477 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -39,8 +39,6 @@ void RUA_Cmd_Init (struct progs_s *pr, int secure); void RUA_Cvar_Init (struct progs_s *pr, int secure); -void RUA_File_Init (struct progs_s *pr, int secure); - void RUA_Hash_Init (struct progs_s *pr, int secure); void RUA_Math_Init (struct progs_s *pr, int secure); diff --git a/libs/ruamoko/Makefile.am b/libs/ruamoko/Makefile.am index 64c65e972..15d4c4360 100644 --- a/libs/ruamoko/Makefile.am +++ b/libs/ruamoko/Makefile.am @@ -16,6 +16,6 @@ libQFruamoko_la_LIBADD= $(rua_libs) libQFruamoko_la_DEPENDENCIES= $(rua_libs) libQFruamoko_la_SOURCES= \ pr_cmds.c \ - rua_cbuf.c rua_cmd.c rua_cvar.c rua_file.c rua_hash.c rua_init.c \ + rua_cbuf.c rua_cmd.c rua_cvar.c rua_hash.c rua_init.c \ rua_math.c rua_msgbuf.c rua_obj.c rua_plist.c rua_qfile.c rua_qfs.c \ rua_script.c rua_set.c rua_string.c diff --git a/libs/ruamoko/rua_file.c b/libs/ruamoko/rua_file.c deleted file mode 100644 index 61def0a3f..000000000 --- a/libs/ruamoko/rua_file.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - bi_file.c - - CSQC file builtins - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#ifdef HAVE_FNMATCH_H -# define model_t sunmodel_t -# include -# undef model_t -#else -# ifdef _WIN32 -# include "fnmatch.h" -# endif -#endif - -#ifndef HAVE_FNMATCH_PROTO -int fnmatch (const char *__pattern, const char *__string, int __flags); -#endif - -#include "QF/cvar.h" -#include "QF/progs.h" -#include "QF/quakefs.h" -#include "QF/va.h" -#include "QF/zone.h" - -#include "rua_internal.h" - -static const char *file_ban_list[] = { - "default.cfg{,.gz}", - "demo1.dem{,.gz}", - "demo2.dem{,.gz}", - "demo3.dem{,.gz}", - "end1.bin{,.gz}", - "end2.bin{,.gz}", - "gfx.wad{,.gz}", - "progs.dat{,.gz}", - "quake.rc{,.gz}", - 0, -}; - -static const char *dir_ban_list[] = { - "gfx", - "maps", - "progs", - "skins", - "sound", - 0, -}; - -static int -file_readable (char *path) -{ - char t; - char *p = strchr (path, '/'); - const char **match; - - if (p) { - t = *p; - *p = 0; - for (match = dir_ban_list; *match; match++) { - if (fnmatch (*match, path, FNM_PATHNAME) == 0) { - *p = t; - return 0; - } - } - } else { - for (match = file_ban_list; *match; match++) { - if (fnmatch (*match, path, FNM_PATHNAME) == 0) { - return 0; - } - } - } - return 1; -} - -static int -file_writeable (char *path) -{ - return file_readable (path); -} - -static void -bi_File_Open (progs_t *pr) -{ - QFile *file; - const char *pth = P_GSTRING (pr, 0); - const char *mode = P_GSTRING (pr, 1); - char *path; - char *p; - int do_write = 0; - int do_read = 0; - - p = strchr (mode, 'r'); - if (p) { - do_read |= 1; - if (p[1] == '+') - do_write |= 1; - } - - p = strchr (mode, 'w'); - if (p) { - do_write |= 1; - if (p[1] == '+') - do_read |= 1; - } - - p = strchr (mode, 'a'); - if (p) { - do_write |= 1; - if (p[1] == '+') - do_read |= 1; - } - - path = QFS_CompressPath (pth); - //printf ("'%s' '%s'\n", P_GSTRING (pr, 0), path); - if (!path[0]) - goto error; - if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || path [2] == 0)) - goto error; - if (path[strlen (path) - 1] =='/') - goto error; - if (!do_read && !do_write) - goto error; - if (do_read && !file_readable (path)) - goto error; - if (do_write && !file_writeable (path)) - goto error; - - file = QFS_Open (va ("%s/%s", qfs_gamedir->dir.def, path), mode); - if (!file) - goto error; - free (path); - if ((R_INT (pr) = QFile_AllocHandle (pr, file))) - return; - Qclose (file); - return; -error: - free (path); - R_INT (pr) = 0; -} - -static builtin_t builtins[] = { - {"File_Open", bi_File_Open, -1}, - {0} -}; - -void -RUA_File_Init (progs_t *pr, int secure) -{ - PR_RegisterBuiltins (pr, builtins); -} diff --git a/libs/ruamoko/rua_init.c b/libs/ruamoko/rua_init.c index bbfc67525..7741405a5 100644 --- a/libs/ruamoko/rua_init.c +++ b/libs/ruamoko/rua_init.c @@ -39,7 +39,6 @@ static void (*init_funcs[])(progs_t *, int) = { RUA_Cbuf_Init, RUA_Cmd_Init, RUA_Cvar_Init, - RUA_File_Init, RUA_Hash_Init, RUA_Math_Init, RUA_MsgBuf_Init, diff --git a/libs/ruamoko/rua_qfs.c b/libs/ruamoko/rua_qfs.c index 35d69d0c8..87b2c5add 100644 --- a/libs/ruamoko/rua_qfs.c +++ b/libs/ruamoko/rua_qfs.c @@ -181,6 +181,12 @@ bi_QFS_FilelistFree (progs_t *pr) PR_Zone_Free (pr, list); } +static void +bi_QFS_GetDirectory (progs_t *pr) +{ + RETURN_STRING (pr, qfs_gamedir->dir.def); +} + static builtin_t builtins[] = { {"QFS_Open", bi_QFS_Open, -1}, {"QFS_WOpen", bi_QFS_WOpen, -1}, @@ -190,6 +196,7 @@ static builtin_t builtins[] = { {"QFS_WriteFile", bi_QFS_WriteFile, -1}, {"QFS_Filelist", bi_QFS_Filelist, -1}, {"QFS_FilelistFree", bi_QFS_FilelistFree, -1}, + {"QFS_GetDirectory", bi_QFS_GetDirectory, -1}, {0} }; diff --git a/ruamoko/cl_menu/client_menu.r b/ruamoko/cl_menu/client_menu.r index 769ad9cae..840eac1c8 100644 --- a/ruamoko/cl_menu/client_menu.r +++ b/ruamoko/cl_menu/client_menu.r @@ -1,6 +1,5 @@ #include "AutoreleasePool.h" #include "menu.h" -#include "file.h" #include "cmd.h" #include "gib.h" #include "draw.h" @@ -10,6 +9,7 @@ #include "options.h" #include "servlist.h" #include "system.h" +#include "qfs.h" #include "debug.h" #include "HUD.h" #include "client_menu.h" @@ -137,17 +137,17 @@ void (int quick) scan_saves = local QFile f; local string line; local int max = MAX_SAVEGAMES; - if (quick) + string basename = "s"; + if (quick) { max = MAX_QUICK; + basename = "quick"; + } + string gamedir = QFS_GetDirectory(); for (i = 0; i < max; i++) { if (!filenames[i]) filenames[i] = str_new (); loadable[i] = 0; - if (quick) { - f = File_Open (sprintf ("quick%i.sav", i + 1), "rz"); - } else { - f = File_Open (sprintf ("s%i.sav", i), "rz"); - } + f = QFS_OpenFile (sprintf ("%s/%s%i.sav", gamedir, basename, i)); if (!f) { str_copy (filenames[i], "--- UNUSED SLOT ---"); continue; diff --git a/ruamoko/include/Makefile.am b/ruamoko/include/Makefile.am index b11080d13..17167cbec 100644 --- a/ruamoko/include/Makefile.am +++ b/ruamoko/include/Makefile.am @@ -7,7 +7,7 @@ nobase_pkginclude_HEADERS= \ \ draw.h key.h \ \ - cbuf.h cmd.h cvar.h file.h gib.h hash.h plist.h runtime.h \ + cbuf.h cmd.h cvar.h gib.h hash.h plist.h runtime.h \ Object.h Protocol.h \ AutoreleasePool.h Array.h Entity.h PropertyList.h Set.h \ \ diff --git a/ruamoko/include/file.h b/ruamoko/include/file.h deleted file mode 100644 index f1c3a580b..000000000 --- a/ruamoko/include/file.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ruamoko_file_h -#define __ruamoko_file_h - -#include "qfile.h" - -@extern QFile File_Open (string path, string mode); - -#endif//__ruamoko_file_h diff --git a/ruamoko/include/qfs.h b/ruamoko/include/qfs.h index 484a020c0..4a31154f9 100644 --- a/ruamoko/include/qfs.h +++ b/ruamoko/include/qfs.h @@ -17,5 +17,6 @@ typedef struct _qfslist_t *QFSlist; @extern int QFS_WriteFile (string filename, void *buf, int count); @extern QFSlist QFS_Filelist (string path, string ext, int strip); @extern void QFS_FilelistFree (QFSlist list); +@extern string QFS_GetDirectory (void); #endif//__ruamoko_qfs_h diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index e4b475d64..ee2c80ff7 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -26,7 +26,7 @@ SUFFIXES= .o .r .qc $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -c -o $@ $< libr_a_SOURCES=\ - cbuf.r cmd.r cvar.r file.r hash.r msgbuf.r plist.r qfile.r qfs.r script.r \ + cbuf.r cmd.r cvar.r hash.r msgbuf.r plist.r qfile.r qfs.r script.r \ sound.r string.r math.r types.r \ Object.r Protocol.r \ AutoreleasePool.r Array.r Array+Private.r Entity.r PropertyList.r Set.r diff --git a/ruamoko/lib/file.r b/ruamoko/lib/file.r deleted file mode 100644 index 02494d317..000000000 --- a/ruamoko/lib/file.r +++ /dev/null @@ -1,3 +0,0 @@ -#include "file.h" - -QFile (string path, string mode) File_Open = #0; diff --git a/ruamoko/lib/qfs.r b/ruamoko/lib/qfs.r index e1d374fc4..b0632d030 100644 --- a/ruamoko/lib/qfs.r +++ b/ruamoko/lib/qfs.r @@ -8,3 +8,4 @@ QFile QFS_OpenFile (string filename) = #0; int QFS_WriteFile (string filename, void *buf, int count) = #0; QFSlist QFS_Filelist (string path, string ext, int strip) = #0; void QFS_FilelistFree (QFSlist list) = #0; +string QFS_GetDirectory (void) = #0; From 5d302ff6f419041fd7feb2eb7eff2f8f2d86d518 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 17:13:13 +0900 Subject: [PATCH 0425/3664] Fix incorrect usage of signed verbosity --- tools/qfcc/source/diagnostic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 84892687f..ab830280a 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -114,7 +114,7 @@ __warning (expr_t *e, const char *file, int line, format_message (message, "warning", e, fmt, args); } - if (options.verbosity) { + if (options.verbosity > 0) { dasprintf (message, " (%s:%d)", file, line); } if (warning_hook) { @@ -208,7 +208,7 @@ _notice (expr_t *e, const char *file, int line, const char *fmt, ...) report_function (e); format_message (message, "notice", e, fmt, args); - if (options.verbosity) { + if (options.verbosity > 0) { dasprintf (message, " (%s:%d)", file, line); } if (notice_hook) { @@ -257,7 +257,7 @@ _error (expr_t *e, const char *file, int line, const char *fmt, ...) dstring_t *message = dstring_new (); format_message (message, "error", e, fmt, args); - if (options.verbosity) { + if (options.verbosity > 0) { dasprintf (message, " (%s:%d)", file, line); } if (error_hook) { From 5c36c60005e55f64af1e26e8590ae863d7dbb40a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 17:41:45 +0900 Subject: [PATCH 0426/3664] Use type check helpers some more --- tools/qfcc/source/expr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 41c3ca7a2..666a3f3fd 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -291,7 +291,7 @@ cast_error (expr_t *e, type_t *t1, type_t *t2) print_type_str (s1, t1); print_type_str (s2, t2); - e = error (e, "can not cast from %s to %s", s1->str, s2->str); + e = error (e, "cannot cast from %s to %s", s1->str, s2->str); dstring_delete (s1); dstring_delete (s2); return e; @@ -2385,11 +2385,11 @@ cast_expr (type_t *type, expr_t *e) c = new_alias_expr (type, e); return c; } - if (!(type->type == ev_pointer - && (e_type->type == ev_pointer || is_integral (e_type) + if (!(is_pointer (type) + && (is_pointer (e_type) || is_integral (e_type) || is_array (e_type))) - && !(is_integral (type) && e_type->type == ev_pointer) - && !(type->type == ev_func && e_type->type == ev_func) + && !(is_integral (type) && is_pointer (e_type)) + && !(is_func (type) && is_func (e_type)) && !(is_scalar (type) && is_scalar (e_type))) { return cast_error (e, e_type, type); } From 9528c1176e28791d9fac24f725dae069c1387f86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 17:45:08 +0900 Subject: [PATCH 0427/3664] Rename cast_expr's type vars for better clarity --- tools/qfcc/source/expr.c | 54 ++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 666a3f3fd..9ad394a07 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2362,41 +2362,41 @@ think_expr (symbol_t *think_sym) } expr_t * -cast_expr (type_t *type, expr_t *e) +cast_expr (type_t *dstType, expr_t *e) { expr_t *c; - type_t *e_type; + type_t *srcType; convert_name (e); if (e->type == ex_error) return e; - e_type = get_type (e); + srcType = get_type (e); - if (type == e_type) + if (dstType == srcType) return e; - if ((type == type_default && is_enum (e_type)) - || (is_enum (type) && e_type == type_default)) + if ((dstType == type_default && is_enum (srcType)) + || (is_enum (dstType) && srcType == type_default)) return e; - if ((is_pointer (type) && is_string (e_type)) - || (is_string (type) && is_pointer (e_type))) { - c = new_alias_expr (type, e); + if ((is_pointer (dstType) && is_string (srcType)) + || (is_string (dstType) && is_pointer (srcType))) { + c = new_alias_expr (dstType, e); return c; } - if (!(is_pointer (type) - && (is_pointer (e_type) || is_integral (e_type) - || is_array (e_type))) - && !(is_integral (type) && is_pointer (e_type)) - && !(is_func (type) && is_func (e_type)) - && !(is_scalar (type) && is_scalar (e_type))) { - return cast_error (e, e_type, type); + if (!(is_pointer (dstType) + && (is_pointer (srcType) || is_integral (srcType) + || is_array (srcType))) + && !(is_integral (dstType) && is_pointer (srcType)) + && !(is_func (dstType) && is_func (srcType)) + && !(is_scalar (dstType) && is_scalar (srcType))) { + return cast_error (e, srcType, dstType); } - if (is_array (e_type)) { - return address_expr (e, 0, type->t.fldptr.type); + if (is_array (srcType)) { + return address_expr (e, 0, dstType->t.fldptr.type); } - if (is_constant (e) && is_scalar (type) && is_scalar (e_type)) { + if (is_constant (e) && is_scalar (dstType) && is_scalar (srcType)) { ex_value_t *val = 0; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) { val = e->e.symbol->s.value; @@ -2416,24 +2416,24 @@ cast_expr (type_t *type, expr_t *e) } else if (e->type == ex_value) { val = e->e.value; } else if (e->type == ex_nil) { - convert_nil (e, type); + convert_nil (e, dstType); return e; } if (!val) internal_error (e, "unexpected constant expression type"); - e->e.value = convert_value (val, type); + e->e.value = convert_value (val, dstType); e->type = ex_value; c = e; - } else if (is_integral (type) && is_integral (e_type)) { - c = new_alias_expr (type, e); - } else if (is_scalar (type) && is_scalar (e_type)) { + } else if (is_integral (dstType) && is_integral (srcType)) { + c = new_alias_expr (dstType, e); + } else if (is_scalar (dstType) && is_scalar (srcType)) { c = new_unary_expr ('C', e); - c->e.expr.type = type; + c->e.expr.type = dstType; } else if (e->type == ex_uexpr && e->e.expr.op == '.') { - e->e.expr.type = type; + e->e.expr.type = dstType; c = e; } else { - c = new_alias_expr (type, e); + c = new_alias_expr (dstType, e); } return c; } From 69b5029de5a4f28b88b84d0b8dc07549c7eb3ceb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 17:46:53 +0900 Subject: [PATCH 0428/3664] Throw away function parameter type alias info typedef is meant to create a simple renaming of a potentially complex type, not create a new type. Keeping the parameter type alias info makes the types effectively different when it comes to overloaded function resolution, which is quite contrary to the goal. Does expose some breakage elsewhere, though. --- tools/qfcc/TODO | 1 + tools/qfcc/source/function.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/TODO b/tools/qfcc/TODO index 5bce50696..8180ed95d 100644 --- a/tools/qfcc/TODO +++ b/tools/qfcc/TODO @@ -18,5 +18,6 @@ o isset() intrinsic for more consistent string handling. o arrays in entities o optional arguments for functions (alternative to overloading) vector(vector fwd, optional vector up) vectoangles = #51; +o rewrite type system to be const-correct (hard!) ? try to reduce memory consumption ?? embedded nul characters in strings (why?) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 538bb8f65..eb376e0ea 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -177,7 +177,10 @@ parse_params (type_t *type, param_t *parms) internal_error (0, 0); new->t.func.num_params = -(new->t.func.num_params + 1); } else if (p->type) { - new->t.func.param_types[new->t.func.num_params] = p->type; + // FIXME this cast should not be necessary, but making the + // type system const-correct would probably take a rewrite + type_t *t = (type_t *) unalias_type (p->type); + new->t.func.param_types[new->t.func.num_params] = t; new->t.func.num_params++; } } From 4cec3bbff6aa749490ae8a947b6f65c288d9278d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 17:49:09 +0900 Subject: [PATCH 0429/3664] Unalias types when checking cast-compatibility This fixes the problem with passing typedefs to function parameters. --- tools/qfcc/source/expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 9ad394a07..c23460b06 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2374,7 +2374,7 @@ cast_expr (type_t *dstType, expr_t *e) srcType = get_type (e); - if (dstType == srcType) + if (unalias_type (dstType) == unalias_type (srcType)) return e; if ((dstType == type_default && is_enum (srcType)) From 6fccfdf1b9888fbb76075fdb06e50e2da6ff08b1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 18:03:00 +0900 Subject: [PATCH 0430/3664] Fix a thinko in the save game menu I thought I had to prepend the gamedir when using QFS_FOpenFile (or QFS_OpenFile in rua). Nope, it's gamedir based --- ruamoko/cl_menu/client_menu.r | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ruamoko/cl_menu/client_menu.r b/ruamoko/cl_menu/client_menu.r index 840eac1c8..67f9e80f1 100644 --- a/ruamoko/cl_menu/client_menu.r +++ b/ruamoko/cl_menu/client_menu.r @@ -142,12 +142,13 @@ void (int quick) scan_saves = max = MAX_QUICK; basename = "quick"; } - string gamedir = QFS_GetDirectory(); for (i = 0; i < max; i++) { if (!filenames[i]) filenames[i] = str_new (); loadable[i] = 0; - f = QFS_OpenFile (sprintf ("%s/%s%i.sav", gamedir, basename, i)); + string path = sprintf ("%s%i.sav", basename, i); + dprint(path + "\n"); + f = QFS_OpenFile (path); if (!f) { str_copy (filenames[i], "--- UNUSED SLOT ---"); continue; From 0f4d89a832ce285352ac9478ef0e6021a0de4a67 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 18:19:21 +0900 Subject: [PATCH 0431/3664] Move free_fmt_items into strings resources This will make it per-thread. --- libs/gamecode/pr_strings.c | 128 ++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index cb74797a5..6d39b8481 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -44,44 +44,6 @@ #include "QF/progs.h" #include "QF/va.h" -typedef struct strref_slot_s { - struct strref_slot_s *next; - struct strref_slot_s **prev; - strref_t *strref; -} strref_slot_t; - -typedef struct prstr_resources_s { - progs_t *pr; - dstring_mem_t ds_mem; - strref_t *free_string_refs; - strref_t *static_strings; - strref_t **string_map; - strref_slot_t return_strings[PR_RS_SLOTS]; - strref_slot_t *rs_slot; - unsigned dyn_str_size; - struct hashtab_s *strref_hash; - int num_strings; -} prstr_resources_t; - -typedef enum { - str_free, - str_static, - str_dynamic, - str_mutable, - str_temp, - str_return, -} str_e; - -struct strref_s { - strref_t *next; - strref_slot_t *rs_slot; - str_e type; - union { - char *string; - dstring_t *dstring; - } s; -}; - // format adjustments #define FMT_ALTFORM (1<<0) #define FMT_LJUSTIFY (1<<1) @@ -106,7 +68,44 @@ typedef struct fmt_item_s { struct fmt_item_s *next; } fmt_item_t; -static fmt_item_t *free_fmt_items; +typedef struct strref_slot_s { + struct strref_slot_s *next; + struct strref_slot_s **prev; + strref_t *strref; +} strref_slot_t; + +typedef struct prstr_resources_s { + progs_t *pr; + dstring_mem_t ds_mem; + strref_t *free_string_refs; + strref_t *static_strings; + strref_t **string_map; + strref_slot_t return_strings[PR_RS_SLOTS]; + strref_slot_t *rs_slot; + unsigned dyn_str_size; + struct hashtab_s *strref_hash; + int num_strings; + fmt_item_t *free_fmt_items; +} prstr_resources_t; + +typedef enum { + str_free, + str_static, + str_dynamic, + str_mutable, + str_temp, + str_return, +} str_e; + +struct strref_s { + strref_t *next; + strref_slot_t *rs_slot; + str_e type; + union { + char *string; + dstring_t *dstring; + } s; +}; static void * pr_strings_alloc (void *_pr, size_t size) @@ -694,30 +693,30 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting) } static fmt_item_t * -new_fmt_item (void) +new_fmt_item (prstr_resources_t *res) { int i; fmt_item_t *fi; - if (!free_fmt_items) { - free_fmt_items = malloc (16 * sizeof (fmt_item_t)); + if (!res->free_fmt_items) { + res->free_fmt_items = malloc (16 * sizeof (fmt_item_t)); for (i = 0; i < 15; i++) - free_fmt_items[i].next = free_fmt_items + i + 1; - free_fmt_items[i].next = 0; + res->free_fmt_items[i].next = res->free_fmt_items + i + 1; + res->free_fmt_items[i].next = 0; } - fi = free_fmt_items; - free_fmt_items = fi->next; + fi = res->free_fmt_items; + res->free_fmt_items = fi->next; memset (fi, 0, sizeof (*fi)); fi->precision = -1; return fi; } static void -free_fmt_item (fmt_item_t *fi) +free_fmt_item (prstr_resources_t *res, fmt_item_t *fi) { - fi->next = free_fmt_items; - free_fmt_items = fi; + fi->next = res->free_fmt_items; + res->free_fmt_items = fi; } #undef P_var @@ -728,6 +727,7 @@ VISIBLE void PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, const char *format, int count, pr_type_t **args) { + prstr_resources_t *res = pr->pr_string_resources; const char *c, *l; const char *msg = ""; fmt_item_t *fmt_items = 0; @@ -737,7 +737,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, if (!name) name = "PR_Sprintf"; - *fi = new_fmt_item (); + *fi = new_fmt_item (res); c = l = format; while (*c) { if (*c++ == '%') { @@ -747,14 +747,14 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->type = 's'; (*fi)->data.string_var = l; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; } if (*c == '%') { (*fi)->type = 's'; (*fi)->data.string_var = "%"; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; } else { do { @@ -802,7 +802,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, case '@': // object fmt_count++; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; break; case 'e': @@ -812,7 +812,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, P_EDICTNUM (pr, fmt_count); fmt_count++; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; break; case 'i': @@ -823,7 +823,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->data.integer_var = P_INT (pr, fmt_count); fmt_count++; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; break; case 'f': @@ -842,7 +842,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, } fmt_count++; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; break; case 'p': @@ -852,7 +852,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->data.uinteger_var = P_UINT (pr, fmt_count); fmt_count++; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; break; case 's': @@ -861,7 +861,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->data.string_var = P_GSTRING (pr, fmt_count); fmt_count++; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; break; case 'v': @@ -888,7 +888,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->type = 's'; (*fi)->data.string_var = " "; } - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; (*fi)->flags = flags; @@ -898,7 +898,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->data.float_var = P_VECTOR (pr, fmt_count)[i]; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; } } @@ -907,7 +907,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->data.string_var = "'"; fmt_count++; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; break; case 'x': @@ -916,7 +916,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->data.uinteger_var = P_UINT (pr, fmt_count); fmt_count++; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); fi = &(*fi)->next; break; } @@ -932,7 +932,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, (*fi)->type = 's'; (*fi)->data.string_var = l; - (*fi)->next = new_fmt_item (); + (*fi)->next = new_fmt_item (res); } if (fmt_count != count) { @@ -947,7 +947,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, I_DoPrint (result, fmt_items); while (fmt_items) { fmt_item_t *t = fmt_items->next; - free_fmt_item (fmt_items); + free_fmt_item (res, fmt_items); fmt_items = t; } return; From 36bc139b274bf2279463404249fdc5159d8f45b6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 18:35:19 +0900 Subject: [PATCH 0432/3664] Avoid use of va in PR_Sprintf With this, progs strings are thread safe so long as only one thread tries to use the VM. --- libs/gamecode/pr_strings.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 6d39b8481..4e2acca11 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -86,6 +86,7 @@ typedef struct prstr_resources_s { struct hashtab_s *strref_hash; int num_strings; fmt_item_t *free_fmt_items; + dstring_t *print_str; } prstr_resources_t; typedef enum { @@ -623,10 +624,9 @@ PR_FreeTempStrings (progs_t *pr) list item. */ static void -I_DoPrint (dstring_t *result, fmt_item_t *formatting) +I_DoPrint (dstring_t *tmp, dstring_t *result, fmt_item_t *formatting) { fmt_item_t *current = formatting; - dstring_t *tmp = dstring_new (); while (current) { qboolean doPrecision, doWidth; @@ -689,7 +689,6 @@ I_DoPrint (dstring_t *result, fmt_item_t *formatting) } current = current->next; } - dstring_delete (tmp); } static fmt_item_t * @@ -940,11 +939,13 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, msg = "Not enough arguments for format string."; else msg = "Too many arguments for format string."; - msg = va ("%s: %d %d", msg, fmt_count, count); + dsprintf (res->print_str, "%s: %d %d", msg, fmt_count, count); + msg = res->print_str->str; goto error; } - I_DoPrint (result, fmt_items); + dstring_clear (res->print_str); + I_DoPrint (res->print_str, result, fmt_items); while (fmt_items) { fmt_item_t *t = fmt_items->next; free_fmt_item (res, fmt_items); @@ -960,6 +961,7 @@ PR_Strings_Init (progs_t *pr) { prstr_resources_t *res = calloc (1, sizeof (*res)); res->pr = pr; + res->print_str = dstring_new (); PR_Resources_Register (pr, "Strings", res, pr_strings_clear); PR_AddLoadFunc (pr, PR_LoadStrings); From ddd007e2d56bcff50f6aafe16a5186b389bd70c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 19:00:19 +0900 Subject: [PATCH 0433/3664] [dstring] Return the string instead of printed size Other than consistency with printf(), I'm not sure why we went with the printed size as the return value; returning the resultant strings makes much more sense as dsprintf() (etc) can then be used as a safe va() --- include/QF/dstring.h | 8 ++++---- libs/util/dstring.c | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/QF/dstring.h b/include/QF/dstring.h index bb5ea9117..937e9be54 100644 --- a/include/QF/dstring.h +++ b/include/QF/dstring.h @@ -164,15 +164,15 @@ void dstring_clearstr (dstring_t *dstr); /** Formatted printing to dstrings. Existing data is replaced by the formatted string. */ -int dvsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); -int dsprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); +char *dvsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); +char *dsprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); ///@} ///@{ /** Formatted printing to dstrings. Formatted string is appened to the dstring. Embedded nulls in the dstring are ignored. */ -int davsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); -int dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); +char *davsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); +char *dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); ///@} ///@} diff --git a/libs/util/dstring.c b/libs/util/dstring.c index 18d83f44a..fb495403c 100644 --- a/libs/util/dstring.c +++ b/libs/util/dstring.c @@ -299,7 +299,7 @@ dstring_clearstr (dstring_t *dstr) dstr->str[0] = 0; } -static __attribute__((format(printf, 3, 0))) int +static __attribute__((format(printf, 3, 0))) char * _dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args) { int size; @@ -325,20 +325,20 @@ _dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args) } dstr->size = size + offs + 1; dstr->str[dstr->size - 1] = 0; - return size; + return dstr->str; } -VISIBLE int +VISIBLE char * dvsprintf (dstring_t *dstr, const char *fmt, va_list args) { return _dvsprintf (dstr, 0, fmt, args); } -VISIBLE int +VISIBLE char * dsprintf (dstring_t *dstr, const char *fmt, ...) { va_list args; - int ret; + char *ret; va_start (args, fmt); ret = _dvsprintf (dstr, 0, fmt, args); @@ -347,7 +347,7 @@ dsprintf (dstring_t *dstr, const char *fmt, ...) return ret; } -VISIBLE int +VISIBLE char * davsprintf (dstring_t *dstr, const char *fmt, va_list args) { int offs = 0; @@ -357,11 +357,11 @@ davsprintf (dstring_t *dstr, const char *fmt, va_list args) return _dvsprintf (dstr, offs, fmt, args); } -VISIBLE int +VISIBLE char * dasprintf (dstring_t *dstr, const char *fmt, ...) { va_list args; - int ret; + char *ret; int offs = 0; if (dstr->size) From 62b541793dddb7a4564d1c2eab1dadaf8c4ee19a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 19:30:10 +0900 Subject: [PATCH 0434/3664] [gamecode] Remove all use of va With this, the VA is very close to being safe to use in a threaded environment (so long as each VM is used by only one thread). Just the debug file hash and source paths to sort out. --- libs/gamecode/pr_builtins.c | 1 - libs/gamecode/pr_debug.c | 83 ++++++++++++++++++------------------- libs/gamecode/pr_strings.c | 1 - 3 files changed, 41 insertions(+), 44 deletions(-) diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index 12c2e6050..7e4bb4431 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -47,7 +47,6 @@ #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/zone.h" -#include "QF/va.h" #include "compat.h" diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index f7f3f3b7c..3ae9a972e 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -52,7 +52,6 @@ #include "QF/quakefs.h" #include "QF/script.h" #include "QF/sys.h" -#include "QF/va.h" #include "QF/zone.h" #include "compat.h" @@ -74,6 +73,9 @@ typedef struct { typedef struct prdeb_resources_s { progs_t *pr; dstring_t *string; + dstring_t *dva; + dstring_t *line; + dstring_t *dstr; const char *debugfile; struct pr_debug_header_s *debug; struct pr_auxfunction_s *auxfunctions; @@ -328,11 +330,10 @@ pr_debug_clear (progs_t *pr, void *data) { __auto_type res = (prdeb_resources_t *) data; - if (res->string) { - dstring_clearstr (res->string); - } else { - res->string = dstring_newstr (); - } + dstring_clearstr (res->string); + dstring_clearstr (res->dva); + dstring_clearstr (res->line); + dstring_clearstr (res->dstr); if (res->debug) pr->free_progs_mem (pr, res->debug); @@ -353,6 +354,7 @@ pr_debug_clear (progs_t *pr, void *data) static file_t * PR_Load_Source_File (progs_t *pr, const char *fname) { + prdeb_resources_t *res = pr->pr_debug_resources; char *l, *p, **dir; file_t *f = Hash_Find (file_hash, fname); @@ -362,8 +364,8 @@ PR_Load_Source_File (progs_t *pr, const char *fname) if (!f) return 0; for (dir = source_paths; *dir && !f->text; dir++) { - f->text = pr->load_file (pr, va ("%s%s%s", *dir, **dir ? "/" : "", - fname), + f->text = pr->load_file (pr, dsprintf (res->dva, "%s%s%s", *dir, + **dir ? "/" : "", fname), &f->size); } if (!f->text) { @@ -651,6 +653,7 @@ PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) const char * PR_Get_Source_Line (progs_t *pr, pr_uint_t addr) { + prdeb_resources_t *res = pr->pr_debug_resources; const char *fname; pr_uint_t line; file_t *file; @@ -670,10 +673,11 @@ PR_Get_Source_Line (progs_t *pr, pr_uint_t addr) file = PR_Load_Source_File (pr, fname); if (!file || !file->lines || !line || line > file->num_lines) - return va ("%s:%u", fname, line); + return dsprintf (res->dva, "%s:%u", fname, line); - return va ("%s:%u:%.*s", fname, line, (int)file->lines[line - 1].len, - file->lines[line - 1].text); + return dsprintf (res->dva, "%s:%u:%.*s", fname, line, + (int)file->lines[line - 1].len, + file->lines[line - 1].text); } pr_def_t * @@ -1210,9 +1214,9 @@ PR_Debug_Watch (progs_t *pr, const char *expr) VISIBLE void PR_Debug_Print (progs_t *pr, const char *expr) { + prdeb_resources_t *res = pr->pr_debug_resources; pr_def_t print; - dstring_t *dstr = dstring_newstr(); - pr_debug_data_t data = {pr, dstr}; + pr_debug_data_t data = {pr, res->dstr}; if (!expr) { Sys_Printf ("print \n"); @@ -1224,7 +1228,6 @@ PR_Debug_Print (progs_t *pr, const char *expr) const char *s = global_string (&data, print.ofs, print.type, 1); Sys_Printf ("[%d] = %s\n", print.ofs, s); } - dstring_delete (dstr); } VISIBLE void @@ -1235,21 +1238,13 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) int dump_code = contents & 2; const char *fmt; opcode_t *op; - static dstring_t *line; - static dstring_t *dstr; dfunction_t *call_func = 0; pr_def_t *parm_def = 0; pr_auxfunction_t *aux_func = 0; pr_debug_data_t data; - if (!line) { - line = dstring_new (); - dstr = dstring_new (); - } - dstring_clearstr (line); - data.pr = pr; - data.dstr = dstr; + data.dstr = res->dstr; if (pr_debug->int_val > 1) dump_code = 1; @@ -1258,7 +1253,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) const char *source_line = PR_Get_Source_Line (pr, addr); if (source_line) { - dasprintf (line, "%s%s", source_line, dump_code ? "\n" : ""); + dasprintf (res->line, "%s%s", source_line, dump_code ? "\n" : ""); if (!dump_code) goto do_print; } @@ -1268,27 +1263,27 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) op = PR_Opcode (s->op); if (!op) { - Sys_Printf ("%sUnknown instruction %d\n", line->str, s->op); + Sys_Printf ("%sUnknown instruction %d\n", res->line->str, s->op); return; } if (!(fmt = op->fmt)) fmt = "%Ga, %Gb, %gc"; - dasprintf (line, "%04x ", addr); + dasprintf (res->line, "%04x ", addr); if (pr_debug->int_val > 2) - dasprintf (line, "%02x %04x(%8s) %04x(%8s) %04x(%8s)\t", + dasprintf (res->line, "%02x %04x(%8s) %04x(%8s) %04x(%8s)\t", s->op, s->a, pr_type_name[op->type_a], s->b, pr_type_name[op->type_b], s->c, pr_type_name[op->type_c]); - dasprintf (line, "%s ", op->opname); + dasprintf (res->line, "%s ", op->opname); while (*fmt) { if (*fmt == '%') { if (fmt[1] == '%') { - dstring_appendsubstr (line, fmt + 1, 1); + dstring_appendsubstr (res->line, fmt + 1, 1); fmt += 2; } else { const char *str; @@ -1365,10 +1360,11 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) str = global_string (&data, opval, optype, 0); break; case 's': - str = va ("%d", (short) opval); + str = dsprintf (res->dva, "%d", (short) opval); break; case 'O': - str = va ("%04x", addr + (short) opval); + str = dsprintf (res->dva, "%04x", + addr + (short) opval); break; case 'E': { @@ -1387,25 +1383,26 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) } str = global_string (&data, opval, optype, contents & 1); - str = va ("$%x $%x %s", s->a, s->b, str); + str = dsprintf (res->dva, "$%x $%x %s", + s->a, s->b, str); } break; default: goto err; } - dstring_appendstr (line, str); + dstring_appendstr (res->line, str); fmt += 3; continue; err: - dstring_appendstr (line, fmt); + dstring_appendstr (res->line, fmt); break; } } else { - dstring_appendsubstr (line, fmt++, 1); + dstring_appendsubstr (res->line, fmt++, 1); } } do_print: - Sys_Printf ("%s\n", line->str); + Sys_Printf ("%s\n", res->line->str); } static void @@ -1497,6 +1494,7 @@ PR_Profile (progs_t * pr) VISIBLE void ED_Print (progs_t *pr, edict_t *ed) { + prdeb_resources_t *res = pr->pr_debug_resources; int l; pr_uint_t i, j; const char *name; @@ -1504,8 +1502,7 @@ ED_Print (progs_t *pr, edict_t *ed) pr_type_t *v; qfot_type_t dummy_type = { }; qfot_type_t *type; - dstring_t *dstr = dstring_newstr(); - pr_debug_data_t data = {pr, dstr}; + pr_debug_data_t data = {pr, res->dstr}; if (ed->free) { Sys_Printf ("FREE\n"); @@ -1538,12 +1535,10 @@ ED_Print (progs_t *pr, edict_t *ed) if (l < 1) l = 1; - dstring_clearstr (dstr); + dstring_clearstr (res->dstr); value_string (&data, type, v); - Sys_Printf ("%s%*s%s\n", name, l, "", dstr->str); + Sys_Printf ("%s%*s%s\n", name, l, "", res->dstr->str); } - - dstring_delete (dstr); } void @@ -1551,6 +1546,10 @@ PR_Debug_Init (progs_t *pr) { prdeb_resources_t *res = calloc (1, sizeof (*res)); res->pr = pr; + res->string = dstring_newstr (); + res->dva = dstring_newstr (); + res->line = dstring_newstr (); + res->dstr = dstring_newstr (); PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); if (!file_hash) { diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 4e2acca11..ff5e1ffab 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -42,7 +42,6 @@ #include "QF/dstring.h" #include "QF/hash.h" #include "QF/progs.h" -#include "QF/va.h" // format adjustments #define FMT_ALTFORM (1<<0) From 126f8502bd1f1af53455ed7ed73d2e127c3a35b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Feb 2020 22:10:59 +0900 Subject: [PATCH 0435/3664] Start working on a qwaq console tool The intention is it will hopefully become a debugger. It will certainly help with development of the progs engine. --- config.d/build_control.m4 | 5 +- config.d/curses.m4 | 27 ++++- tools/qwaq/Makefile.am | 23 +++-- tools/qwaq/defs.qc | 22 ----- tools/qwaq/main.c | 39 ++++---- tools/qwaq/main.qc | 114 --------------------- tools/qwaq/qwaq-curses.c | 54 ++++++++++ tools/qwaq/test.r | 42 -------- tools/qwaq/types.r | 203 -------------------------------------- 9 files changed, 119 insertions(+), 410 deletions(-) delete mode 100644 tools/qwaq/defs.qc delete mode 100644 tools/qwaq/main.qc create mode 100644 tools/qwaq/qwaq-curses.c delete mode 100644 tools/qwaq/test.r delete mode 100644 tools/qwaq/types.r diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 13004a6c8..a53bf74a4 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -227,7 +227,10 @@ if test "x$ENABLE_tools_qfvis" = xyes; then QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qwaq" = xyes; then - QF_NEED(tools,[qwaq]) + if test "x$HAVE_PANEL" = xyes -a "x$HAVE_PTHREAD" = xyes; then + QWAQ_TARGETS="$QWAQ_TARGETS qwaq-curses\$(EXEEXT)" + fi + QF_NEED(tools,[qfcc qwaq]) QF_NEED(libs,[ruamoko gamecode util]) fi if test "x$ENABLE_tools_wad" = xyes; then diff --git a/config.d/curses.m4 b/config.d/curses.m4 index 80a2b0415..073e98217 100644 --- a/config.d/curses.m4 +++ b/config.d/curses.m4 @@ -2,7 +2,7 @@ AC_ARG_ENABLE(curses, [ --disable-curses disable curses support] ) if test "x$enable_curses" != "xno"; then - AC_CHECK_HEADERS(curses.h) + AC_CHECK_HEADER(curses.h) AC_CHECK_LIB(ncurses, initscr, CURSES_LIBS=-lncurses, AC_CHECK_LIB(pdcurses, initscr, @@ -13,7 +13,32 @@ if test "x$enable_curses" != "xno"; then ) ) ) + if test "x$CURSES_LIBS" != "x"; then + AC_DEFINE(HAVE_CURSES, 1, [Define if you have the ncurses library]) + HAVE_CURSES=yes + else + HAVE_CURSES=no + fi else + HAVE_CURSES=no CURSES_LIBS= fi AC_SUBST(CURSES_LIBS) + +if test "x$HAVE_CURSES" == "xyes"; then + AC_CHECK_HEADER(panel.h, + [AC_CHECK_LIB(panel, new_panel, + [AC_DEFINE(HAVE_PANEL, 1, + [Define if you have the ncurses panel library]) + PANEL_LIBS=-lpanel + HAVE_PANEL=yes], + [HAVE_PANEL=no], + $CURSES_LIBS + )], + HAVE_PANEL=no, + [] + ) +else + PANEL_LIBS= +fi +AC_SUBST(PANEL_LIBS) diff --git a/tools/qwaq/Makefile.am b/tools/qwaq/Makefile.am index dd34fd9c5..104a7743d 100644 --- a/tools/qwaq/Makefile.am +++ b/tools/qwaq/Makefile.am @@ -2,21 +2,24 @@ QWAQ_LIBS=@QWAQ_LIBS@ QWAQ_DEPS=@QWAQ_DEPS@ QWAQ_INCS=@QWAQ_INCS@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(QWAQ_INCS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(QWAQ_INCS) $(PTHREAD_CFLAGS) QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(top_builddir)/tools/qfcc/source/qfcc QCFLAGS=-qq -O -g -Werror --advanced --no-default-paths -noinst_PROGRAMS=qwaq @QWAQ_TARGETS@ -noinst_DATA=qwaq.dat +noinst_PROGRAMS=@QWAQ_TARGETS@ +noinst_DATA= #qwaq.dat qwaq_dat_src= \ - defs.qc main.qc test.r types.r + $e -qwaq_SOURCES= main.c builtins.c -qwaq_LDADD= $(QWAQ_LIBS) -qwaq_DEPENDENCIES= $(QWAQ_DEPS) +qwaq_curses_libs= +qwaq_curses_SOURCES=main.c qwaq-curses.c +qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ + $(PANEL_LIBS) $(CURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) +qwaq_curses_LDFLAGS= +qwaq_curses_DEPENDENCIES= $(qwaq_curses_libs) $(QWAQ_DEPS) cl_plugin_libs= \ @client_static_plugin_libs@ @@ -42,9 +45,9 @@ qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \ qwaq_x11_LDFLAGS= qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) -qwaq.dat: progs.src $(qwaq_dat_src) $(QFCC_DEP) $(top_srcdir)/ruamoko/lib/Object.r - $(QFCC) $(QCFLAGS) -I$(top_srcdir)/ruamoko/include +#qwaq.dat: $(qwaq_dat_src) $(QFCC_DEP) $(top_srcdir)/ruamoko/lib/Object.r +# $(QFCC) $(QCFLAGS) -I$(top_srcdir)/ruamoko/include -EXTRA_PROGRAMS=qwaq-x11 +EXTRA_PROGRAMS=qwaq-curses qwaq-x11 EXTRA_DIST=$(qwaq_dat_src) qwaq.h CLEANFILES= *.dat *.sym diff --git a/tools/qwaq/defs.qc b/tools/qwaq/defs.qc deleted file mode 100644 index e872fb799..000000000 --- a/tools/qwaq/defs.qc +++ /dev/null @@ -1,22 +0,0 @@ -void (string str) print = #0; -int () errno = #0; -string (int err) strerror = #0; -int (...) open = #0; // string path, float flags[, float mode] -int (int handle) close = #0; -string read (int handle, int count, int *result) = #0; -int (int handle, string buffer, int count) write = #0; -int (int handle, int pos, int whence) seek = #0; - -//void() traceon = #0; // turns statment trace on -//void() traceoff = #0; - -void (...) printf = #0; - - -float time; -entity self; - -.float nextthink; -.void() think; -.float frame; -.vector origin; diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index 7f51ea6df..357579290 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -33,24 +33,27 @@ #include -#include -#include -#include -#include +#include "QF/cbuf.h" +#include "QF/cmd.h" +#include "QF/cvar.h" +#include "QF/gib.h" +#include "QF/idparse.h" +#include "QF/progs.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" #include "QF/ruamoko.h" -#include +#include "QF/sys.h" #include "QF/va.h" -#include +#include "QF/zone.h" #include "qwaq.h" #define MAX_EDICTS 1024 -static edict_t *edicts; -static int num_edicts; -static int reserved_edicts; static progs_t pr; +cbuf_t *qwaq_cbuf; + static QFile * open_file (const char *path, int *len) { @@ -100,17 +103,18 @@ free_progs_mem (progs_t *pr, void *mem) static void init_qf (void) { - Sys_Init (); - //Cvar_Get ("developer", "128", 0, 0, 0); + qwaq_cbuf = Cbuf_New (&id_interp); - Memory_Init (malloc (1024 * 1024), 1024 * 1024); + Sys_Init (); + COM_ParseConfig (); + + //Cvar_Set (developer, "1"); + + Memory_Init (malloc (8 * 1024 * 1024), 8 * 1024 * 1024); Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); - pr.edicts = &edicts; - pr.num_edicts = &num_edicts; - pr.reserved_edicts = &reserved_edicts; pr.load_file = load_file; pr.allocate_progs_mem = allocate_progs_mem; pr.free_progs_mem = free_progs_mem; @@ -119,7 +123,7 @@ init_qf (void) PR_Init_Cvars (); PR_Init (&pr); RUA_Init (&pr, 0); - PR_Cmds_Init(&pr); + PR_Cmds_Init (&pr); BI_Init (&pr); } @@ -144,7 +148,7 @@ load_progs (const char *name) } int -main (int argc, char **argv) +main (int argc, const char **argv) { dfunction_t *dfunc; func_t main_func = 0; @@ -152,6 +156,7 @@ main (int argc, char **argv) string_t *pr_argv; int pr_argc = 1, i; + COM_InitArgv (argc, argv); init_qf (); if (argc > 1) diff --git a/tools/qwaq/main.qc b/tools/qwaq/main.qc deleted file mode 100644 index 25cfaabdb..000000000 --- a/tools/qwaq/main.qc +++ /dev/null @@ -1,114 +0,0 @@ -string read_file (string filename) -{ - local QFile file; - local string data = nil, d; - file = Qopen (filename, "rtz"); - if (!file) { - printf ("Can't open %s for reading." - " Probably a bad hardcoded filename:)\n", filename); - return nil; - } - while ((d = Qgetline (file))) - data = data + d; - //FIXME can't read to a string, can't convert a pointer to a string ... - //Qread (file, data, 1023); - Qclose (file); - d = str_new (); - str_copy (d, data); - return d; -} - -void test_plist (void) -{ - local string data, l; - local plitem_t pl, item, i; - - data = read_file ("/home/bill/.quakeforge/gamedir.conf"); - pl = PL_GetPropertyList ("{" + data + "}"); - l = PL_WritePropertyList (pl); - printf ("%s", data); - printf ("%s", l); - i = PL_ObjectForKey (pl, "QF"); - item = PL_RemoveObjectForKey (pl, "QF"); - l = PL_WritePropertyList (item); - printf ("%s", l); - PL_Free (item); - //Because i and item both point to the same plitem, and item has been, - //freed, freeing i will generate an error - //l = PL_WritePropertyList (i); - PL_Free (pl); - str_free (data); -} - -void test_script (void) -{ - local script_t script; - local string token; - local string data; - - data = read_file ("progs.src"); - script = Script_New (); - token = Script_Start (script, "progs.src", data); - while (Script_GetToken (script, 1)) { - printf ("%s\n", token); - } - Script_Delete (script); - str_free (data); -} - -void () test_str = -{ - local string a,b,c,d; - a = "testing "; - b = "temp "; - c = "strings "; - d = "\n"; - print (a + b + c + d); - printf ("%i \"%.5s\" %3.4f %v\n", 14, "hi there", 3.1415926, '4 1 3'); -}; -void (...) dprint = #0; -int main (int argc, string *argv) -{ - local int i; - local SEL sel; - dprint ("foo", "bar\n"); - for (i = 0; i < argc; i++) { - print (argv[i]); - print ("\n"); - } - local id foo = [[Foo alloc] init]; - [foo run]; - sel = sel_get_uid ("run"); - if (sel) { - print ("found selector for `run'\n"); - if ([foo respondsToSelector:sel]) - print ("foo responds to `run'\n"); - else - print ("foo does not repond to `run'\n"); - } else - print ("did not find selector for `run'\n"); - sel = sel_get_uid ("alloc"); - if (sel) { - print ("found selector for `alloc'\n"); - if ([Object instancesRespondToSelector:sel]) - print ("Object instances respond to `alloc'\n"); - else - print ("Object instances do not repond to `alloc'\n"); - } else - print ("did not find selector for `alloc'\n"); - sel = sel_get_uid ("run:with:me:"); - if (sel) { - print ("found selector for `run:with:me:'\n"); - if ([Object instancesRespondToSelector:sel]) - print ("Object instances respond to `run:with:me:'\n"); - else - print ("Object instances do not repond to `run:with:me:'\n"); - } else - print ("did not find selector for `run:with:me:'\n"); - test_str (); - test_script (); - test_plist (); - test_types (); - test_xdefs (); - return 0; -}; diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c new file mode 100644 index 000000000..71439d0a9 --- /dev/null +++ b/tools/qwaq/qwaq-curses.c @@ -0,0 +1,54 @@ +/* + #FILENAME# + + #DESCRIPTION# + + Copyright (C) 2001 #AUTHOR# + + Author: #AUTHOR# + Date: #DATE# + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/progs.h" +#include "QF/sys.h" + +#include "qwaq.h" + +static builtin_t builtins[] = { + {0} +}; + +static void +bi_shutdown (void) +{ +} + +void +BI_Init (progs_t *pr) +{ + PR_RegisterBuiltins (pr, builtins); + + Sys_RegisterShutdown (bi_shutdown); +} diff --git a/tools/qwaq/test.r b/tools/qwaq/test.r deleted file mode 100644 index 6e0afd6f2..000000000 --- a/tools/qwaq/test.r +++ /dev/null @@ -1,42 +0,0 @@ -@interface Foo : Object -{ - int x; -} --run; -@end - - -@implementation Foo - -+load -{ - print ("+load\n"); - return self; -} - -+alloc -{ - print ("+alloc\n"); - return class_create_instance (self); -} - --init -{ - print ("-init\n"); - return [super init]; -} - -+ (void) initialize -{ - print ("+initialize\n"); -} - --run -{ - print ("Hello world\n"); - printf ("%i %p [%s %s]\n", self, &self.x, [self description], - __PRETTY_FUNCTION__); - return self; -} - -@end diff --git a/tools/qwaq/types.r b/tools/qwaq/types.r deleted file mode 100644 index 5cf874c61..000000000 --- a/tools/qwaq/types.r +++ /dev/null @@ -1,203 +0,0 @@ -#include "runtime.h" //FIXME for PR_FindGlobal -typedef enum { - ev_void, - ev_string, - ev_float, - ev_vector, - ev_entity, - ev_field, - ev_func, - ev_pointer, // end of v6 types - ev_quat, - ev_integer, - ev_uinteger, - ev_short, // value is embedded in the opcode - ev_double, - - ev_invalid, // invalid type. used for instruction checking - ev_type_count // not a type, gives number of types -} etype_t; - -typedef enum { - ty_none, ///< func/field/pointer or not used - ty_struct, - ty_union, - ty_enum, - ty_array, - ty_class, -} ty_meta_e; - - -typedef struct qfot_fldptr_s { - etype_t type; - struct qfot_type_s *aux_type; -} qfot_fldptr_t; - -typedef struct qfot_func_s { - etype_t type; - struct qfot_type_s *return_type; - int num_params; - struct qfot_type_s *param_types[1]; -} qfot_func_t; - -typedef struct qfot_var_s { - struct qfot_type_s *type; - string name; - int offset; // value for enum, 0 for union -} qfot_var_t; - -typedef struct qfot_struct_s { - string tag; - int num_fields; - qfot_var_t fields[1]; -} qfot_struct_t; - -typedef struct qfot_array_s { - struct qfot_type_s *type; - int base; - int size; -} qfot_array_t; - -typedef struct qfot_type_s { - ty_meta_e meta; - int size; - string encoding; - union { - etype_t type; - qfot_fldptr_t fldptr; - qfot_func_t func; - qfot_struct_t strct; - qfot_array_t array; - string class; - } t; -} qfot_type_t; - -typedef struct qfot_type_encodings_s { - qfot_type_t *types; - int size; -} qfot_type_encodings_t; - -typedef struct xdef_s { - qfot_type_t *type; - void *offset; -} xdef_t; - -typedef struct pr_xdefs_s { - xdef_t *xdefs; - int num_xdefs; -} pr_xdefs_t; - -qfot_type_t * -next_type (qfot_type_t *type) -{ - int size = type.size; - if (!size) - size = 4; - return (qfot_type_t *) ((int *) type + size); -} - -string ty_meta_name[6] = { - "basic", - "struct", - "union", - "enum", - "array", - "class", -}; - -string pr_type_name[ev_type_count] = { - "void", - "string", - "float", - "vector", - "entity", - "field", - "function", - "pointer", - "quaternion", - "integer", - "uinteger", - "short", - "double" - "invalid", -}; - -void -test_types (void) -{ - qfot_type_encodings_t *encodings; - qfot_type_t *type; - int i; - - encodings = PR_FindGlobal (".type_encodings"); - if (!encodings) { - printf ("Can't find encodings\n"); - return; - } - for (type = encodings.types; - ((int *)type - (int *) encodings.types) < encodings.size; - type = next_type (type)) { - printf ("%p %-6s %-20s", type, ty_meta_name[type.meta], - type.encoding); - if (!type.size) { - printf ("\n"); - continue; - } - switch (type.meta) { - case ty_none: - printf (" %-10s", pr_type_name[type.t.type]); - if (type.t.type == ev_func) { - int count = type.t.func.num_params; - printf ("%p %d", type.t.func.return_type, count); - if (count < 0) - count = ~count; - for (i = 0; i < count; i++) - printf (" %p", type.t.func.param_types[i]); - } else if (type.t.type == ev_pointer) { - printf (" *%p", type.t.fldptr.aux_type); - } else if (type.t.type == ev_field) { - printf (" .%p", type.t.fldptr.aux_type); - } else { - printf (" %p", type.t.fldptr.aux_type); - } - printf ("\n"); - break; - case ty_struct: - case ty_union: - case ty_enum: - printf (" %s\n", type.t.strct.tag); - for (i = 0; i < type.t.strct.num_fields; i++) { - printf (" %p %4x %s\n", - type.t.strct.fields[i].type, - type.t.strct.fields[i].offset, - type.t.strct.fields[i].name); - } - break; - case ty_array: - printf (" %p %d %d\n", type.t.array.type, - type.t.array.base, type.t.array.size); - break; - case ty_class: - printf (" %s %p\n", type.t.class, - obj_lookup_class (type.t.class)); - break; - } - } -} - -void -test_xdefs (void) -{ - pr_xdefs_t *xdefs; - int i; - - xdefs = PR_FindGlobal (".xdefs"); - if (!xdefs) { - printf ("Can't find xdefs\n"); - return; - } - printf ("%p %i\n", xdefs.xdefs, xdefs.num_xdefs); - for (i = 0; i < xdefs.num_xdefs; i++) { - printf ("%p %p\n", xdefs.xdefs[i].type, xdefs.xdefs[i].offset); - } -} From edde4bad15c9f4910d4e2a333fed0a6d23b9a30b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 01:18:38 +0900 Subject: [PATCH 0436/3664] Create a basic hello world And it has begun. It has some problems, but worse, it seems I broke qfprogs and maybe pr_debug.c. --- tools/qwaq/Makefile.am | 33 +++++++-- tools/qwaq/main.c | 6 +- tools/qwaq/qwaq-app.r | 23 ++++++ tools/qwaq/qwaq-curses.c | 153 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 204 insertions(+), 11 deletions(-) create mode 100644 tools/qwaq/qwaq-app.r diff --git a/tools/qwaq/Makefile.am b/tools/qwaq/Makefile.am index 104a7743d..b6e9b8345 100644 --- a/tools/qwaq/Makefile.am +++ b/tools/qwaq/Makefile.am @@ -1,15 +1,25 @@ +AUTOMAKE_OPTIONS= foreign + QWAQ_LIBS=@QWAQ_LIBS@ QWAQ_DEPS=@QWAQ_DEPS@ QWAQ_INCS=@QWAQ_INCS@ AM_CPPFLAGS= -I$(top_srcdir)/include $(QWAQ_INCS) $(PTHREAD_CFLAGS) +noinst_PROGRAMS=@QWAQ_TARGETS@ qwaq-app.dat$(EXEEXT) + QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(top_builddir)/tools/qfcc/source/qfcc -QCFLAGS=-qq -O -g -Werror --advanced --no-default-paths -noinst_PROGRAMS=@QWAQ_TARGETS@ -noinst_DATA= #qwaq.dat +QCFLAGS=-qq -O -g -Werror +QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include +QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) + +SUFFIXES=.o .r +.r.o: + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< + sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo qwaq_dat_src= \ $e @@ -45,8 +55,21 @@ qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \ qwaq_x11_LDFLAGS= qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) -#qwaq.dat: $(qwaq_dat_src) $(QFCC_DEP) $(top_srcdir)/ruamoko/lib/Object.r -# $(QFCC) $(QCFLAGS) -I$(top_srcdir)/ruamoko/include +r_depfiles_remade= + +qwaq_app_dat_SOURCES=qwaq-app.r +qwaq_app_obj=$(qwaq_app_dat_SOURCES:.r=.o) +qwaq_app_dep=$(addprefix ./$(DEPDIR)/,$(qwaq_app_obj:.o=.Qo)) +qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(qwaq_app_obj) +include $(qwaq_app_dep) # am--include-marker +r_depfiles_remade += $(qwaq_app_dep) + +$(r_depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) EXTRA_PROGRAMS=qwaq-curses qwaq-x11 EXTRA_DIST=$(qwaq_dat_src) qwaq.h diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index 357579290..3f88a428a 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -152,7 +152,7 @@ main (int argc, const char **argv) { dfunction_t *dfunc; func_t main_func = 0; - const char *name = "qwaq.dat"; + const char *name = "qwaq-app.dat"; string_t *pr_argv; int pr_argc = 1, i; @@ -162,8 +162,9 @@ main (int argc, const char **argv) if (argc > 1) name = argv[1]; - if (!load_progs (name)) + if (!load_progs (name)) { Sys_Error ("couldn't load %s", name); + } PR_PushFrame (&pr); if (argc > 2) @@ -185,5 +186,6 @@ main (int argc, const char **argv) pr.pr_argc = 2; PR_ExecuteProgram (&pr, main_func); PR_PopFrame (&pr); + Sys_Shutdown (); return R_INT (&pr); } diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r new file mode 100644 index 000000000..6473ef6a8 --- /dev/null +++ b/tools/qwaq/qwaq-app.r @@ -0,0 +1,23 @@ +typedef struct window_s *window_t; + +void initialize (void) = #0; +window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; +void destroy_window (window_t win) = #0; +void wprintf (window_t win, string fmt, ...) = #0; +int wgetch (window_t win) = #0; + +int main (int argc, string *argv) +{ + int ch; + + initialize (); + window_t win = create_window (20, 5, 50, 10); + wprintf (win, "Hi there!\n"); + do { + ch = wgetch (win); + if (ch) { + wprintf (win, "%d\n", ch); + } + } while (ch != 27); + return 0; +} diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index 71439d0a9..a3f055ae8 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -31,24 +31,169 @@ # include "config.h" #endif +#include +#include +#include + +#include "QF/dstring.h" #include "QF/progs.h" #include "QF/sys.h" #include "qwaq.h" -static builtin_t builtins[] = { - {0} -}; +#define always_inline inline __attribute__((__always_inline__)) +typedef struct window_s { + WINDOW *win; +} window_t; + +typedef struct qwaq_resources_s { + progs_t *pr; + int initialized; + dstring_t *print_buffer; + PR_RESMAP (window_t) window_map; +} qwaq_resources_t; + +static window_t * +window_new (qwaq_resources_t *res) +{ + PR_RESNEW (window_t, res->window_map); +} + +static void +window_free (qwaq_resources_t *res, window_t *win) +{ + PR_RESFREE (window_t, res->window_map, win); +} + +static void +window_reset (qwaq_resources_t *res) +{ + PR_RESRESET (window_t, res->window_map); +} + +static inline window_t * +window_get (qwaq_resources_t *res, unsigned index) +{ + PR_RESGET(res->window_map, index); +} + +static inline int +window_index (qwaq_resources_t *res, window_t *win) +{ + PR_RESINDEX (res->window_map, win); +} + +static always_inline window_t * +get_window (qwaq_resources_t *res, const char *name, int handle) +{ + window_t *window = window_get (res, handle); + + if (!window || !window->win) { + PR_RunError (res->pr, "invalid window passed to %s", name + 3); + } + return window; +} + +static int need_endwin; static void bi_shutdown (void) { + if (need_endwin) { + endwin (); + } } +static void +bi_initialize (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + initscr (); + need_endwin = 1; + res->initialized = 1; + raw (); + keypad (stdscr, TRUE); + noecho (); + nonl (); +} + +static void +bi_create_window (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int xpos = P_INT (pr, 0); + int ypos = P_INT (pr, 1); + int xlen = P_INT (pr, 2); + int ylen = P_INT (pr, 3); + window_t *window = window_new (res); + window->win = newwin (ylen, xlen, ypos, xpos); + keypad (window->win, TRUE); + R_INT (pr) = window_index (res, window); +} + +static void +bi_destroy_window (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); + delwin (window->win); + window->win = 0; + window_free (res, window); +} + +static void +bi_wprintf (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); + const char *fmt = P_GSTRING (pr, 1); + int count = pr->pr_argc - 2; + pr_type_t **args = pr->pr_params + 2; + + PR_Sprintf (pr, res->print_buffer, "bi_wprintf", fmt, count, args); + waddstr (window->win, res->print_buffer->str); + wrefresh (window->win); +} + +static void +bi_wgetch (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); + + R_INT (pr) = wgetch (window->win); +} + +static void +bi_qwaq_clear (progs_t *pr, void *data) +{ + __auto_type res = (qwaq_resources_t *) data; + + if (res->initialized) { + endwin (); + } + need_endwin = 0; + window_reset (res); +} + +static builtin_t builtins[] = { + {"initialize", bi_initialize, -1}, + {"create_window", bi_create_window, -1}, + {"destroy_window", bi_destroy_window, -1}, + {"wprintf", bi_wprintf, -1}, + {"wgetch", bi_wgetch, -1}, + {0} +}; + void BI_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + qwaq_resources_t *res = calloc (sizeof (*res), 1); + res->pr = pr; + res->print_buffer = dstring_newstr (); + PR_Resources_Register (pr, "qwaq", res, bi_qwaq_clear); + PR_RegisterBuiltins (pr, builtins); Sys_RegisterShutdown (bi_shutdown); } From c9186c82961af767afc83a90d6e223c5cba2951c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 01:25:41 +0900 Subject: [PATCH 0437/3664] Clear the statement line buffer The problem with moving to a cached buffer is it needs to be cleared. Fixes the weird output of qfprogs and tracing (not missing local defs, though). --- libs/gamecode/pr_debug.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 3ae9a972e..e7bf90a92 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1243,6 +1243,8 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) pr_auxfunction_t *aux_func = 0; pr_debug_data_t data; + dstring_clearstr (res->line); + data.pr = pr; data.dstr = res->dstr; From 789f263855b5b94d27295b7552fcbaf580b6a99d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 02:07:53 +0900 Subject: [PATCH 0438/3664] Use get_strref() correctly I had forgotten that it works only for dynamic strings. --- libs/gamecode/pr_strings.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index ff5e1ffab..4d393776e 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -348,6 +348,9 @@ get_string (progs_t *pr, string_t num) VISIBLE qboolean PR_StringValid (progs_t *pr, string_t num) { + if (num >= 0) { + return num < pr->pr_stringsize; + } return get_strref (pr->pr_string_resources, num) != 0; } From e8c357393f369c853e7fac3932fd825254b57c5d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 02:11:54 +0900 Subject: [PATCH 0439/3664] [qwaq] Clear qwaq's print buffer Didn't realized PR_Sprintf appended. Or, more likely, I had forgotten because I imagine Deek and I discussed it at the time. --- tools/qwaq/qwaq-curses.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index a3f055ae8..3932298d8 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -151,6 +151,7 @@ bi_wprintf (progs_t *pr) int count = pr->pr_argc - 2; pr_type_t **args = pr->pr_params + 2; + dstring_clearstr (res->print_buffer); PR_Sprintf (pr, res->print_buffer, "bi_wprintf", fmt, count, args); waddstr (window->win, res->print_buffer->str); wrefresh (window->win); From dbbb8a1396de8e948ee30bb2d54fadd1890381b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 17:43:39 +0900 Subject: [PATCH 0440/3664] [qfcc] Fix syntax error for id as a field name event.e.mouse.id produced a syntax error, which is contrary to Objective-C. --- tools/qfcc/source/qc-parse.y | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index e64bb748e..8c417a8f5 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -184,7 +184,7 @@ int yylex (void); %type optional_state_expr texpr vector_expr %type statement statements compound_statement %type else label break_label continue_label -%type unary_expr cast_expr opt_arg_list arg_list +%type unary_expr ident_expr cast_expr opt_arg_list arg_list %type init_var_decl_list init_var_decl %type switch_block %type identifier @@ -1288,6 +1288,7 @@ unary_expr | '(' expr ')' { $$ = $2; $$->paren = 1; } | unary_expr '(' opt_arg_list ')' { $$ = function_expr ($1, $3); } | unary_expr '[' expr ']' { $$ = array_expr ($1, $3); } + | unary_expr '.' ident_expr { $$ = field_expr ($1, $3); } | unary_expr '.' unary_expr { $$ = field_expr ($1, $3); } | INCOP unary_expr { $$ = incop_expr ($1, $2, 0); } | unary_expr INCOP { $$ = incop_expr ($2, $1, 1); } @@ -1306,6 +1307,12 @@ unary_expr | obj_expr { $$ = $1; } ; +ident_expr + : OBJECT { $$ = new_symbol_expr ($1); } + | CLASS_NAME { $$ = new_symbol_expr ($1); } + | TYPE_NAME { $$ = new_symbol_expr ($1); } + ; + vector_expr : '[' expr ',' arg_list ']' { From 7c9072aebf84e6eaea4c78978ee6f1210340b004 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 17:50:11 +0900 Subject: [PATCH 0441/3664] [qfcc] Create struct fields for "type typename" Such declarations were being lost, thus in the following, the id field never got added: typedef struct qwaq_mevent_s { int id; int x, y, z; int buttons; } qwaq_mevent_t; --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/qc-parse.y | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index c8913933e..46d524574 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -81,6 +81,7 @@ typedef struct type_s { typedef struct { type_t *type; struct param_s *params; + struct symbol_s *sym; ///< for dealing with "int id" etc storage_class_t storage; unsigned multi_type:1; unsigned multi_store:1; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 8c417a8f5..dd33aa07c 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -484,6 +484,15 @@ specifiers type : type_specifier | type type_specifier + { + // deal with eg "int id" + $1.sym = $2.sym; + + if (!$1.sym) { + error (0, "two or more data types in declaration specifiers"); + } + $$ = $1; + } ; type_specifier_or_storage_class @@ -501,6 +510,7 @@ type_specifier | TYPE_NAME { $$ = make_spec ($1->type, 0, 0, 0); + $$.sym = $1; } | OBJECT protocolrefs { @@ -512,6 +522,7 @@ type_specifier } else { $$ = make_spec (&type_id, 0, 0, 0); } + $$.sym = $1; } | CLASS_NAME protocolrefs { @@ -523,6 +534,7 @@ type_specifier } else { $$ = make_spec ($1->type, 0, 0, 0); } + $$.sym = $1; } // NOTE: fields don't parse the way they should. This is not a problem // for basic types, but functions need special treatment @@ -656,6 +668,22 @@ struct_def_list struct_def : type struct_decl_list | type + { + if ($1.sym) { + // a type name (id, typedef, etc) was used as a field name. + // this is allowed in C + print_type ($1.type); + printf ("%s\n", $1.sym->name); + $1.sym = new_symbol ($1.sym->name); + $1.sym->type = $1.type; + $1.sym->sy_type = sy_var; + symtab_addsymbol (current_symtab, $1.sym); + } else { + // bare type + warning (0, "declaration does not declare anything"); + } + $$ = $1; + } ; struct_decl_list From b4aebc120ee5f1355de9545b155fc43fedbea426 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 20:30:07 +0900 Subject: [PATCH 0442/3664] [qfcc] Treat { } as nil for initializing compound types --- tools/qfcc/include/expr.h | 2 +- tools/qfcc/source/def.c | 67 ++++++++++++++++++++++++++++--- tools/qfcc/source/expr.c | 3 +- tools/qfcc/source/qc-parse.y | 7 ++++ tools/qfcc/test/Makefile.am | 10 +++++ tools/qfcc/test/struct-nil-init.r | 12 ++++++ 6 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 tools/qfcc/test/struct-nil-init.r diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 0a030e75a..ac2646dfe 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -614,7 +614,7 @@ void convert_int (expr_t *e); void convert_short (expr_t *e); void convert_short_int (expr_t *e); void convert_double (expr_t *e); -void convert_nil (expr_t *e, struct type_s *t); +expr_t *convert_nil (expr_t *e, struct type_s *t); expr_t *test_expr (expr_t *e); void backpatch (ex_list_t *list, expr_t *label); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index ed5e69964..049740563 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -287,6 +287,21 @@ def_to_ddef (def_t *def, ddef_t *ddef, int aux) ddef->s_name = ReuseString (def->name); } +static int +zero_memory (expr_t *local_expr, def_t *def, type_t *zero_type, + int init_size, int init_offset) +{ + int zero_size = type_size (zero_type); + expr_t *zero = convert_nil (new_nil_expr (), zero_type); + expr_t *dst; + + for (; init_offset < init_size + 1 - zero_size; init_offset += zero_size) { + dst = new_pointer_expr (init_offset, zero_type, def); + append_expr (local_expr, assign_expr (unary_expr ('.', dst), zero)); + } + return init_offset; +} + static void init_elements (struct def_s *def, expr_t *eles) { @@ -298,6 +313,39 @@ init_elements (struct def_s *def, expr_t *eles) base_offset = def->offset; if (def->local && local_expr) base_offset = 0; + if (eles->type == ex_nil) { + if (def->local && local_expr) { + // memset to 0 + int init_size = type_size (def->type); + int init_offset = 0; + + if (options.code.progsversion != PROG_ID_VERSION) { + init_offset = zero_memory (local_expr, def, &type_zero, + init_size, init_offset); + } + // probably won't happen any time soon, but who knows... + if (options.code.progsversion != PROG_ID_VERSION + && init_size - init_offset >= type_size (&type_quaternion)) { + init_offset = zero_memory (local_expr, def, &type_quaternion, + init_size, init_offset); + } + if (init_size - init_offset >= type_size (&type_vector)) { + init_offset = zero_memory (local_expr, def, &type_vector, + init_size, init_offset); + } + if (options.code.progsversion != PROG_ID_VERSION + && init_size - init_offset >= type_size (&type_double)) { + init_offset = zero_memory (local_expr, def, &type_double, + init_size, init_offset); + } + if (init_size - init_offset >= type_size (type_default)) { + zero_memory (local_expr, def, type_default, + init_size, init_offset); + } + } + // it's a global, so already initialized to 0 + return; + } if (is_array (def->type)) { type_t *array_type = def->type->t.array.type; int array_size = def->type->t.array.size; @@ -334,8 +382,11 @@ init_elements (struct def_s *def, expr_t *eles) } for (count = 0, e = eles->e.block.head; e; count++, e = e->next) { convert_name (e); - if (e->type == ex_nil && count < num_elements) + if (e->type == ex_nil && count < num_elements + && !(is_array (elements[count].type) + || is_struct (elements[count].type))) { convert_nil (e, elements[count].type); + } if (e->type == ex_error) { free (elements); return; @@ -349,7 +400,8 @@ init_elements (struct def_s *def, expr_t *eles) for (i = 0, e = eles->e.block.head; i < count; i++, e = e->next) { g = D_POINTER (pr_type_t, &elements[i]); c = constant_expr (e); - if (c->type == ex_block) { + // nil will not survive as nil to this point if array or struct + if (c->type == ex_block || c->type == ex_nil) { if (!is_array (elements[i].type) && !is_struct (elements[i].type)) { error (e, "type mismatch in initializer"); @@ -567,15 +619,18 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, convert_name (init); if (init->type == ex_error) return; - if (init->type == ex_nil) - convert_nil (init, sym->type); if ((is_array (sym->type) || is_struct (sym->type) || sym->type == &type_vector || sym->type == &type_quaternion) - && init->type == ex_block && !init->e.block.result) { + && ((init->type == ex_block && !init->e.block.result) + || init->type == ex_nil)) { init_elements (sym->s.def, init); sym->s.def->initialized = 1; } else { - type_t *init_type = get_type (init); + type_t *init_type; + if (init->type == ex_nil) { + convert_nil (init, sym->type); + } + init_type = get_type (init); if (!type_assignable (sym->type, init_type)) { error (init, "type mismatch in initializer"); return; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c23460b06..7d5baddb9 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1325,11 +1325,12 @@ convert_double (expr_t *e) e->e.value = new_float_val (float_val); } -void +expr_t * convert_nil (expr_t *e, type_t *t) { e->type = ex_value; e->e.value = new_nil_val (t); + return e; } int diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index dd33aa07c..07c12692e 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1065,6 +1065,13 @@ opt_initializer var_initializer : '=' expr { $$ = $2; } | '=' '{' element_list optional_comma '}' { $$ = $3; } + | '=' '{' '}' + { + if (is_scalar ($-1.type)) { + error (0, "empty scalar initializer"); + } + $$ = new_nil_expr (); + } ; optional_state_expr diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index e715b38ed..c53dd7cbf 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -48,6 +48,7 @@ test_progs_dat=\ return-ivar.dat \ sendv.dat \ state.dat \ + struct-nil-init.dat \ structarray.dat \ structlive.dat \ structptr.dat \ @@ -301,6 +302,15 @@ state.run: Makefile build-run include ./$(DEPDIR)/state.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/state.Qo +struct_nil_init_dat_SOURCES=struct-nil-init.r +struct_nil_init_obj=$(struct_nil_init_dat_SOURCES:.r=.qfo) +struct-nil-init.dat$(EXEEXT): $(struct_nil_init_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(struct_nil_init_obj) +struct-nil-init.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/struct-nil-init.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/struct-nil-init.Qo + structarray_dat_SOURCES=structarray.r structarray_obj=$(structarray_dat_SOURCES:.r=.qfo) structarray.dat$(EXEEXT): $(structarray_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/struct-nil-init.r b/tools/qfcc/test/struct-nil-init.r new file mode 100644 index 000000000..065a43b34 --- /dev/null +++ b/tools/qfcc/test/struct-nil-init.r @@ -0,0 +1,12 @@ +#pragma bug die + +struct foo { + quaternion x; + double y; +}; + +int main() +{ + struct foo bar = { }; + return bar.y; // to survive and prevail +} From 08bf8a04e4f53750b8dfb221c8c578b8ae98611a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 21:01:09 +0900 Subject: [PATCH 0443/3664] [qwaq] Implement an event queue It seems to have an issue with a bogus clearing of the screen, but the basics seem to be working. --- tools/qwaq/event.h | 25 ++++++++++++ tools/qwaq/qwaq-app.r | 25 ++++++++++-- tools/qwaq/qwaq-curses.c | 82 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 tools/qwaq/event.h diff --git a/tools/qwaq/event.h b/tools/qwaq/event.h new file mode 100644 index 000000000..a3591fdca --- /dev/null +++ b/tools/qwaq/event.h @@ -0,0 +1,25 @@ +#ifndef __qwaq_event_h +#define __qwaq_event_h + +typedef enum { + qe_idle, + qe_key, + qe_mouse, +} qwaq_etype; + +// right now, this is just a copy of ncurses MEVENT, but all int +typedef struct qwaq_mevent_s { + int id; // XXX does it matter? + int x, y, z; // z? what? + int buttons; +} qwaq_mevent_t; + +typedef struct qwaq_event_s { + qwaq_etype event_type; + union { + int key; + qwaq_mevent_t mouse; + } e; +} qwaq_event_t; + +#endif//__qwaq_event_h diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index 6473ef6a8..05f07bd68 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -1,3 +1,5 @@ +#include "event.h" + typedef struct window_s *window_t; void initialize (void) = #0; @@ -6,17 +8,32 @@ void destroy_window (window_t win) = #0; void wprintf (window_t win, string fmt, ...) = #0; int wgetch (window_t win) = #0; +void process_input (void) = #0; +int get_event (qwaq_event_t *event) = #0; + int main (int argc, string *argv) { - int ch; + int ch = 0; + qwaq_event_t event = { }; initialize (); window_t win = create_window (20, 5, 50, 10); wprintf (win, "Hi there!\n"); do { - ch = wgetch (win); - if (ch) { - wprintf (win, "%d\n", ch); + process_input (); + + if (get_event (&event)) { + if (event.event_type == qe_key) { + ch = event.e.key; + wprintf (win, "key: %d\n", ch); + } else if (event.event_type == qe_mouse) { + wprintf (win, "mouse: %d %d %d %d %d\n", + event.e.mouse.id, + event.e.mouse.x, + event.e.mouse.y, + event.e.mouse.z, + event.e.mouse.buttons); + } } } while (ch != 27); return 0; diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index 3932298d8..a281c3327 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -40,8 +40,11 @@ #include "QF/sys.h" #include "qwaq.h" +#include "event.h" #define always_inline inline __attribute__((__always_inline__)) +#define QUEUE_SIZE 16 // must be power of 2 greater than 1 +#define QUEUE_MASK (QUEUE_SIZE - 1) typedef struct window_s { WINDOW *win; @@ -52,6 +55,9 @@ typedef struct qwaq_resources_s { int initialized; dstring_t *print_buffer; PR_RESMAP (window_t) window_map; + qwaq_event_t event_queue[QUEUE_SIZE]; + unsigned queue_head; + unsigned queue_tail; } qwaq_resources_t; static window_t * @@ -116,6 +122,8 @@ bi_initialize (progs_t *pr) keypad (stdscr, TRUE); noecho (); nonl (); + nodelay (stdscr, TRUE); + mousemask(ALL_MOUSE_EVENTS, NULL); } static void @@ -166,6 +174,78 @@ bi_wgetch (progs_t *pr) R_INT (pr) = wgetch (window->win); } +static void +add_event (qwaq_resources_t *res, qwaq_event_t *event) +{ + if (((res->queue_head - res->queue_tail) & QUEUE_MASK) != QUEUE_MASK) { + res->event_queue[res->queue_head] = *event; + res->queue_head = (res->queue_head + 1) & QUEUE_MASK; + } +} + +static int +get_event (qwaq_resources_t *res, qwaq_event_t *event) +{ + if (res->queue_head != res->queue_tail) { + if (event) { + *event = res->event_queue[res->queue_tail]; + res->queue_tail = (res->queue_tail + 1) & QUEUE_MASK; + } + return 1; + } + return 0; +} + +static void +mouse_event (qwaq_resources_t *res, MEVENT *mevent) +{ + qwaq_event_t event = {}; + event.event_type = qe_mouse; + event.e.mouse.id = mevent->id; + event.e.mouse.x = mevent->x; + event.e.mouse.y = mevent->y; + event.e.mouse.z = mevent->z; + event.e.mouse.buttons = mevent->bstate; + add_event (res, &event); +} + +static void +key_event (qwaq_resources_t *res, int key) +{ + qwaq_event_t event = {}; + event.event_type = qe_key; + event.e.key = key; + add_event (res, &event); +} + +static void +bi_process_input (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + if (Sys_CheckInput (1, -1)) { + int ch; + while ((ch = getch ()) != ERR && ch) { + fflush (stderr); + if (ch == KEY_MOUSE) { + MEVENT mevent; + getmouse (&mevent); + mouse_event (res, &mevent); + } else { + key_event (res, ch); + } + } + } +} + +static void +bi_get_event (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_event_t *event = &G_STRUCT (pr, qwaq_event_t, P_INT (pr, 0)); + + R_INT (pr) = get_event (res, event); +} + static void bi_qwaq_clear (progs_t *pr, void *data) { @@ -184,6 +264,8 @@ static builtin_t builtins[] = { {"destroy_window", bi_destroy_window, -1}, {"wprintf", bi_wprintf, -1}, {"wgetch", bi_wgetch, -1}, + {"process_input", bi_process_input, -1}, + {"get_event", bi_get_event, -1}, {0} }; From a3ed5926b955fa016180c039241c230a62f303b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 21:08:12 +0900 Subject: [PATCH 0444/3664] [qwaq] Remove unnecessary fields from mouse events id and z seem to always be 0. Ironically, it turns out that the work needed for "int id" and "large" struct nil init wasn't strictly necessary to get to this point, but without having done that work, I wouldn't know :) --- tools/qwaq/event.h | 3 +-- tools/qwaq/qwaq-app.r | 4 +--- tools/qwaq/qwaq-curses.c | 2 -- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/tools/qwaq/event.h b/tools/qwaq/event.h index a3591fdca..933c61569 100644 --- a/tools/qwaq/event.h +++ b/tools/qwaq/event.h @@ -9,8 +9,7 @@ typedef enum { // right now, this is just a copy of ncurses MEVENT, but all int typedef struct qwaq_mevent_s { - int id; // XXX does it matter? - int x, y, z; // z? what? + int x, y; int buttons; } qwaq_mevent_t; diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index 05f07bd68..1bc2dcbe9 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -27,11 +27,9 @@ int main (int argc, string *argv) ch = event.e.key; wprintf (win, "key: %d\n", ch); } else if (event.event_type == qe_mouse) { - wprintf (win, "mouse: %d %d %d %d %d\n", - event.e.mouse.id, + wprintf (win, "mouse: %d %d %d\n", event.e.mouse.x, event.e.mouse.y, - event.e.mouse.z, event.e.mouse.buttons); } } diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index a281c3327..ccc4b73b1 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -201,10 +201,8 @@ mouse_event (qwaq_resources_t *res, MEVENT *mevent) { qwaq_event_t event = {}; event.event_type = qe_mouse; - event.e.mouse.id = mevent->id; event.e.mouse.x = mevent->x; event.e.mouse.y = mevent->y; - event.e.mouse.z = mevent->z; event.e.mouse.buttons = mevent->bstate; add_event (res, &event); } From dd25bf5dfec0949c34f9e4eabf6275ec963dbebd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 21:22:10 +0900 Subject: [PATCH 0445/3664] [qwaq] Read mouse movements Many thanks to https://gist.github.com/sylt/93d3f7b77e7f3a881603 for the necessary escape sequence to get xterm reporting mouse movement events. --- tools/qwaq/qwaq-app.r | 13 +++++++------ tools/qwaq/qwaq-curses.c | 23 ++++++++++++++++++++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index 1bc2dcbe9..3cb5f85a4 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -6,6 +6,7 @@ void initialize (void) = #0; window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; void destroy_window (window_t win) = #0; void wprintf (window_t win, string fmt, ...) = #0; +void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; int wgetch (window_t win) = #0; void process_input (void) = #0; @@ -25,14 +26,14 @@ int main (int argc, string *argv) if (get_event (&event)) { if (event.event_type == qe_key) { ch = event.e.key; - wprintf (win, "key: %d\n", ch); + mvwprintf (win, 1, 1, "key: %d\n", ch); } else if (event.event_type == qe_mouse) { - wprintf (win, "mouse: %d %d %d\n", - event.e.mouse.x, - event.e.mouse.y, - event.e.mouse.buttons); + mvwprintf (win, 1, 2, "mouse: %d %d %d\n", + event.e.mouse.x, + event.e.mouse.y, + event.e.mouse.buttons); } } - } while (ch != 27); + } while (ch != 'q' && ch != 'Q'); return 0; } diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index ccc4b73b1..eb3724020 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "QF/dstring.h" #include "QF/progs.h" @@ -45,6 +46,7 @@ #define always_inline inline __attribute__((__always_inline__)) #define QUEUE_SIZE 16 // must be power of 2 greater than 1 #define QUEUE_MASK (QUEUE_SIZE - 1) +#define MOUSE_MOVES "\033[?1003h" // Make the terminal report mouse movements typedef struct window_s { WINDOW *win; @@ -123,7 +125,8 @@ bi_initialize (progs_t *pr) noecho (); nonl (); nodelay (stdscr, TRUE); - mousemask(ALL_MOUSE_EVENTS, NULL); + mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); + write(1, MOUSE_MOVES, sizeof (MOUSE_MOVES) - 1); } static void @@ -165,6 +168,23 @@ bi_wprintf (progs_t *pr) wrefresh (window->win); } +static void +bi_mvwprintf (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + const char *fmt = P_GSTRING (pr, 3); + int count = pr->pr_argc - 4; + pr_type_t **args = pr->pr_params + 4; + + dstring_clearstr (res->print_buffer); + PR_Sprintf (pr, res->print_buffer, "bi_wprintf", fmt, count, args); + mvwaddstr (window->win, y, x, res->print_buffer->str); + wrefresh (window->win); +} + static void bi_wgetch (progs_t *pr) { @@ -261,6 +281,7 @@ static builtin_t builtins[] = { {"create_window", bi_create_window, -1}, {"destroy_window", bi_destroy_window, -1}, {"wprintf", bi_wprintf, -1}, + {"mvwprintf", bi_mvwprintf, -1}, {"wgetch", bi_wgetch, -1}, {"process_input", bi_process_input, -1}, {"get_event", bi_get_event, -1}, From 6a58dcdddd1a8efbfab49b15864585d0f2f20e19 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Feb 2020 21:38:55 +0900 Subject: [PATCH 0446/3664] [qwaq] Fix lost output Turns out all I needed was a refresh() after initialization. --- tools/qwaq/qwaq-curses.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index eb3724020..210124e35 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -127,6 +127,7 @@ bi_initialize (progs_t *pr) nodelay (stdscr, TRUE); mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); write(1, MOUSE_MOVES, sizeof (MOUSE_MOVES) - 1); + refresh(); } static void From 644ef93dde821e9fe16b07be1a982b0b2850a21c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Feb 2020 22:27:29 +0900 Subject: [PATCH 0447/3664] [qwaq] Create some ring-buffer macros I expect I will need several messaging buffers, and ring buffers tend to be quite robust. Replacing the event buffer code with the macros made testing easy. --- tools/qwaq/qwaq-app.r | 2 +- tools/qwaq/qwaq-curses.c | 71 ++++++++++++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index 3cb5f85a4..9aa3301f2 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -28,7 +28,7 @@ int main (int argc, string *argv) ch = event.e.key; mvwprintf (win, 1, 1, "key: %d\n", ch); } else if (event.event_type == qe_mouse) { - mvwprintf (win, 1, 2, "mouse: %d %d %d\n", + mvwprintf (win, 1, 2, "mouse: %2d %2d %08x\n", event.e.mouse.x, event.e.mouse.y, event.e.mouse.buttons); diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index 210124e35..1a5d08840 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -48,6 +48,61 @@ #define QUEUE_MASK (QUEUE_SIZE - 1) #define MOUSE_MOVES "\033[?1003h" // Make the terminal report mouse movements +#define RING_BUFFER(type, size) \ + struct { \ + type buffer[size]; \ + unsigned head; \ + unsigned tail; \ + } + +#define RB_buffer_size(ring_buffer) \ + ({ __auto_type rb = (ring_buffer); \ + sizeof (rb->buffer) / sizeof (rb->buffer[0]); \ + }) + +#define RB_SPACE_AVAILABLE(ring_buffer) \ + ({ __auto_type rb = &(ring_buffer); \ + (rb->tail + RB_buffer_size(rb) - rb->head - 1) % RB_buffer_size(rb);\ + }) + +#define RB_DATA_AVAILABLE(ring_buffer) \ + ({ __auto_type rb = &(ring_buffer); \ + (rb->head + RB_buffer_size (rb) - rb->tail) % RB_buffer_size (rb); \ + }) + +#define RB_WRITE_DATA(ring_buffer, data, count) \ + ({ __auto_type rb = &(ring_buffer); \ + typeof (&rb->buffer[0]) d = (data); \ + unsigned c = (count); \ + unsigned h = rb->head; \ + rb->head = (h + c) % RB_buffer_size (rb); \ + if (c > RB_buffer_size (rb) - h) { \ + memcpy (rb->buffer + h, d, \ + (RB_buffer_size (rb) - h) * sizeof (rb->buffer[0])); \ + c -= RB_buffer_size (rb) - h; \ + d += RB_buffer_size (rb) - h; \ + h = 0; \ + } \ + memcpy (rb->buffer + h, d, c * sizeof (rb->buffer[0])); \ + }) + +#define RB_READ_DATA(ring_buffer, data, count) \ + ({ __auto_type rb = &(ring_buffer); \ + typeof (&rb->buffer[0]) d = (data); \ + unsigned c = (count); \ + unsigned oc = c; \ + unsigned t = rb->tail; \ + if (c > RB_buffer_size (rb) - t) { \ + memcpy (d, rb->buffer + t, \ + (RB_buffer_size (rb) - t) * sizeof (rb->buffer[0])); \ + c -= RB_buffer_size (rb) - t; \ + d += RB_buffer_size (rb) - t; \ + t = 0; \ + } \ + memcpy (d, rb->buffer + t, c * sizeof (rb->buffer[0])); \ + rb->tail = (t + oc) % RB_buffer_size (rb); \ + }) + typedef struct window_s { WINDOW *win; } window_t; @@ -57,9 +112,7 @@ typedef struct qwaq_resources_s { int initialized; dstring_t *print_buffer; PR_RESMAP (window_t) window_map; - qwaq_event_t event_queue[QUEUE_SIZE]; - unsigned queue_head; - unsigned queue_tail; + RING_BUFFER (qwaq_event_t, QUEUE_SIZE) event_queue; } qwaq_resources_t; static window_t * @@ -92,7 +145,7 @@ window_index (qwaq_resources_t *res, window_t *win) PR_RESINDEX (res->window_map, win); } -static always_inline window_t * +static always_inline window_t * __attribute__((pure)) get_window (qwaq_resources_t *res, const char *name, int handle) { window_t *window = window_get (res, handle); @@ -198,19 +251,17 @@ bi_wgetch (progs_t *pr) static void add_event (qwaq_resources_t *res, qwaq_event_t *event) { - if (((res->queue_head - res->queue_tail) & QUEUE_MASK) != QUEUE_MASK) { - res->event_queue[res->queue_head] = *event; - res->queue_head = (res->queue_head + 1) & QUEUE_MASK; + if (RB_SPACE_AVAILABLE (res->event_queue) >= 1) { + RB_WRITE_DATA (res->event_queue, event, 1); } } static int get_event (qwaq_resources_t *res, qwaq_event_t *event) { - if (res->queue_head != res->queue_tail) { + if (RB_DATA_AVAILABLE (res->event_queue) >= 1) { if (event) { - *event = res->event_queue[res->queue_tail]; - res->queue_tail = (res->queue_tail + 1) & QUEUE_MASK; + RB_READ_DATA (res->event_queue, event, 1); } return 1; } From bd98d1d9fb45208bec172390b9428f8b83fe1ec3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 01:45:33 +0900 Subject: [PATCH 0448/3664] [qwaq] Prepare for threading So far, no threading has been set up, and only window creation and printing have been updated, but the basics of the design seem to be sound. The builtin functions now no longer call ncurses directly: the build commands and write them to a command buffer. Commands that have return values (eg, window creation) write their results to a results buffer that the originating builtin function reads. Builtin functions that expect a result "poll" the results buffer for the correct result (marked by the same command). In a single UI-thread environment, the results should always be in the same order as the commands, and in a multi-UI-thread environment, things should (fingers crossed) sort themselves out as ONE of the threads will be the originator of the next available result. Strings in commands (eg, for printing) are handled by acquiring a string id (index into an array of dstring_t) and including the string id in the written command. The string id is released upon completion of the command. Builtin functions write commands, acquire string ids, and read results. The command processor reads commands, releases string ids, and writes results. Since commands, string ids, and results are all in ring buffers, and assuming there is only one thread running the builtin functions and only one thread processing commands (there can be only one because ncurses is not thread-safe), then there should never be any contention on the buffers. Of course, if there are multiple threads running the builtin functions, then locking will be required on the builtin function side. --- tools/qwaq/qwaq-app.r | 7 +- tools/qwaq/qwaq-curses.c | 357 ++++++++++++++++++++++++++++++--------- 2 files changed, 280 insertions(+), 84 deletions(-) diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index 9aa3301f2..a0b2a2c63 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -5,11 +5,8 @@ typedef struct window_s *window_t; void initialize (void) = #0; window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; void destroy_window (window_t win) = #0; -void wprintf (window_t win, string fmt, ...) = #0; void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; -int wgetch (window_t win) = #0; -void process_input (void) = #0; int get_event (qwaq_event_t *event) = #0; int main (int argc, string *argv) @@ -19,10 +16,8 @@ int main (int argc, string *argv) initialize (); window_t win = create_window (20, 5, 50, 10); - wprintf (win, "Hi there!\n"); + mvwprintf (win, 0, 0, "Hi there!\n"); do { - process_input (); - if (get_event (&event)) { if (event.event_type == qe_key) { ch = event.e.key; diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index 1a5d08840..bb5c3a958 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -32,6 +32,7 @@ #endif #include +#include #include #include #include @@ -44,9 +45,19 @@ #include "event.h" #define always_inline inline __attribute__((__always_inline__)) -#define QUEUE_SIZE 16 // must be power of 2 greater than 1 -#define QUEUE_MASK (QUEUE_SIZE - 1) +#define QUEUE_SIZE 16 #define MOUSE_MOVES "\033[?1003h" // Make the terminal report mouse movements +#define STRING_ID_QUEUE_SIZE 8 // must be > 1 +#define COMMAND_QUEUE_SIZE 128 +#define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) + +typedef enum qwaq_commands_e { + qwaq_cmd_create_window, + qwaq_cmd_destroy_window, + qwaq_cmd_create_panel, + qwaq_cmd_destroy_panel, + qwaq_cmd_mvwprint, +} qwaq_commands; #define RING_BUFFER(type, size) \ struct { \ @@ -103,16 +114,36 @@ rb->tail = (t + oc) % RB_buffer_size (rb); \ }) +#define RB_DROP_DATA(ring_buffer, count) \ + ({ __auto_type rb = &(ring_buffer); \ + unsigned c = (count); \ + unsigned t = rb->tail; \ + rb->tail = (t + c) % RB_buffer_size (rb); \ + }) + +#define RB_PEEK_DATA(ring_buffer, ahead) \ + ({ __auto_type rb = &(ring_buffer); \ + rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)]; \ + }) + typedef struct window_s { WINDOW *win; } window_t; +typedef struct panel_s { + PANEL *panel; +} panel_t; + typedef struct qwaq_resources_s { progs_t *pr; int initialized; - dstring_t *print_buffer; PR_RESMAP (window_t) window_map; + PR_RESMAP (panel_t) panel_map; RING_BUFFER (qwaq_event_t, QUEUE_SIZE) event_queue; + RING_BUFFER (int, COMMAND_QUEUE_SIZE) command_queue; + RING_BUFFER (int, COMMAND_QUEUE_SIZE) results; + RING_BUFFER (int, STRING_ID_QUEUE_SIZE) string_ids; + dstring_t strings[STRING_ID_QUEUE_SIZE - 1]; } qwaq_resources_t; static window_t * @@ -156,96 +187,127 @@ get_window (qwaq_resources_t *res, const char *name, int handle) return window; } -static int need_endwin; -static void -bi_shutdown (void) +static panel_t * +panel_new (qwaq_resources_t *res) { - if (need_endwin) { - endwin (); + PR_RESNEW (panel_t, res->panel_map); +} + +static void +panel_free (qwaq_resources_t *res, panel_t *win) +{ + PR_RESFREE (panel_t, res->panel_map, win); +} + +static void +panel_reset (qwaq_resources_t *res) +{ + PR_RESRESET (panel_t, res->panel_map); +} + +static inline panel_t * +panel_get (qwaq_resources_t *res, unsigned index) +{ + PR_RESGET(res->panel_map, index); +} + +static inline int +panel_index (qwaq_resources_t *res, panel_t *win) +{ + PR_RESINDEX (res->panel_map, win); +} + +static always_inline panel_t * __attribute__((pure)) +get_panel (qwaq_resources_t *res, const char *name, int handle) +{ + panel_t *panel = panel_get (res, handle); + + if (!panel || !panel->panel) { + PR_RunError (res->pr, "invalid panel passed to %s", name + 3); + } + return panel; +} + +static int +acquire_string (qwaq_resources_t *res) +{ + int string_id = -1; + + // XXX add locking and loop for available + if (RB_DATA_AVAILABLE (res->string_ids)) { + RB_READ_DATA (res->string_ids, &string_id, 1); + } + // XXX unlock and end of loop + return string_id; +} + +static void +release_string (qwaq_resources_t *res, int string_id) +{ + // locking shouldn't be necessary as there should be only one writer + // but if it becomes such that there is more than one writer, locks as per + // acquire + if (RB_SPACE_AVAILABLE (res->string_ids)) { + RB_WRITE_DATA (res->string_ids, &string_id, 1); } } static void -bi_initialize (progs_t *pr) +create_window (qwaq_resources_t *res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int xpos = RB_PEEK_DATA (res->command_queue, 2); + int ypos = RB_PEEK_DATA (res->command_queue, 3); + int xlen = RB_PEEK_DATA (res->command_queue, 4); + int ylen = RB_PEEK_DATA (res->command_queue, 5); - initscr (); - need_endwin = 1; - res->initialized = 1; - raw (); - keypad (stdscr, TRUE); - noecho (); - nonl (); - nodelay (stdscr, TRUE); - mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); - write(1, MOUSE_MOVES, sizeof (MOUSE_MOVES) - 1); - refresh(); -} - -static void -bi_create_window (progs_t *pr) -{ - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int xpos = P_INT (pr, 0); - int ypos = P_INT (pr, 1); - int xlen = P_INT (pr, 2); - int ylen = P_INT (pr, 3); window_t *window = window_new (res); window->win = newwin (ylen, xlen, ypos, xpos); keypad (window->win, TRUE); - R_INT (pr) = window_index (res, window); + + int window_id = window_index (res, window); + + int cmd_result[] = { qwaq_cmd_create_window, window_id }; + + // loop + if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { + RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); + } } static void -bi_destroy_window (progs_t *pr) +move_print (qwaq_resources_t *res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); - delwin (window->win); - window->win = 0; - window_free (res, window); -} + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int x = RB_PEEK_DATA (res->command_queue, 3); + int y = RB_PEEK_DATA (res->command_queue, 4); + int string_id = RB_PEEK_DATA (res->command_queue, 5); -static void -bi_wprintf (progs_t *pr) -{ - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); - const char *fmt = P_GSTRING (pr, 1); - int count = pr->pr_argc - 2; - pr_type_t **args = pr->pr_params + 2; - - dstring_clearstr (res->print_buffer); - PR_Sprintf (pr, res->print_buffer, "bi_wprintf", fmt, count, args); - waddstr (window->win, res->print_buffer->str); + window_t *window = get_window (res, __FUNCTION__, window_id); + mvwaddstr (window->win, y, x, res->strings[string_id].str); + release_string (res, string_id); wrefresh (window->win); } static void -bi_mvwprintf (progs_t *pr) +process_commands (qwaq_resources_t *res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); - int x = P_INT (pr, 1); - int y = P_INT (pr, 2); - const char *fmt = P_GSTRING (pr, 3); - int count = pr->pr_argc - 4; - pr_type_t **args = pr->pr_params + 4; - - dstring_clearstr (res->print_buffer); - PR_Sprintf (pr, res->print_buffer, "bi_wprintf", fmt, count, args); - mvwaddstr (window->win, y, x, res->print_buffer->str); - wrefresh (window->win); -} - -static void -bi_wgetch (progs_t *pr) -{ - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); - - R_INT (pr) = wgetch (window->win); + while (RB_DATA_AVAILABLE (res->command_queue) > 2) { + switch ((qwaq_commands) RB_PEEK_DATA (res->command_queue, 0)) { + case qwaq_cmd_create_window: + create_window (res); + break; + case qwaq_cmd_destroy_window: + break; + case qwaq_cmd_create_panel: + break; + case qwaq_cmd_destroy_panel: + break; + case qwaq_cmd_mvwprint: + move_print (res); + break; + } + RB_DROP_DATA (res->command_queue, RB_PEEK_DATA (res->command_queue, 1)); + } } static void @@ -289,9 +351,8 @@ key_event (qwaq_resources_t *res, int key) } static void -bi_process_input (progs_t *pr) +process_input (qwaq_resources_t *res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); if (Sys_CheckInput (1, -1)) { int ch; while ((ch = getch ()) != ERR && ch) { @@ -307,15 +368,143 @@ bi_process_input (progs_t *pr) } } +static int need_endwin; +static void +bi_shutdown (void) +{ + if (need_endwin) { + endwin (); + } +} + +static void +bi_create_window (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int xpos = P_INT (pr, 0); + int ypos = P_INT (pr, 1); + int xlen = P_INT (pr, 2); + int ylen = P_INT (pr, 3); + int command[] = { + qwaq_cmd_create_window, 0, + xpos, ypos, xlen, ylen, + }; + + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + // XXX should just wait on the mutex + process_commands (res); + process_input (res); + // locking and loop until id is correct + if (RB_DATA_AVAILABLE (res->results) + && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_create_window) { + int cmd_result[2]; // should results have a size? + RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); + R_INT (pr) = cmd_result[1]; + } +} + +static void +bi_destroy_window (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); + delwin (window->win); + window->win = 0; + window_free (res, window); +} + +static void +bi_create_panel (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); + + panel_t *panel = panel_new (res); + panel->panel = new_panel (window->win); + R_INT (pr) = panel_index (res, panel); +} + +static void +bi_destroy_panel (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + panel_t *panel = get_panel (res, __FUNCTION__, P_INT (pr, 0)); + del_panel (panel->panel); + panel->panel = 0; + panel_free (res, panel); +} + +static void +bi_mvwprintf (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int window_id = P_INT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + const char *fmt = P_GSTRING (pr, 3); + int count = pr->pr_argc - 4; + pr_type_t **args = pr->pr_params + 4; + + int string_id = acquire_string (res); + dstring_t *print_buffer = res->strings + string_id; + int command[] = { + qwaq_cmd_mvwprint, 0, + window_id, x, y, string_id + }; + + if (get_window (res, __FUNCTION__, window_id)) { + command[1] = CMD_SIZE(command); + + dstring_clearstr (print_buffer); + PR_Sprintf (pr, print_buffer, "mvwprintf", fmt, count, args); + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + } +} + +static void +bi_wgetch (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); + + R_INT (pr) = wgetch (window->win); +} + static void bi_get_event (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); qwaq_event_t *event = &G_STRUCT (pr, qwaq_event_t, P_INT (pr, 0)); + process_commands (res); + process_input (res); R_INT (pr) = get_event (res, event); } +static void +bi_initialize (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + initscr (); + need_endwin = 1; + res->initialized = 1; + raw (); + keypad (stdscr, TRUE); + noecho (); + nonl (); + nodelay (stdscr, TRUE); + mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); + write(1, MOUSE_MOVES, sizeof (MOUSE_MOVES) - 1); + refresh(); +} + static void bi_qwaq_clear (progs_t *pr, void *data) { @@ -326,28 +515,40 @@ bi_qwaq_clear (progs_t *pr, void *data) } need_endwin = 0; window_reset (res); + panel_reset (res); } static builtin_t builtins[] = { {"initialize", bi_initialize, -1}, {"create_window", bi_create_window, -1}, {"destroy_window", bi_destroy_window, -1}, - {"wprintf", bi_wprintf, -1}, + {"create_panel", bi_create_panel, -1}, + {"destroy_panel", bi_destroy_panel, -1}, {"mvwprintf", bi_mvwprintf, -1}, {"wgetch", bi_wgetch, -1}, - {"process_input", bi_process_input, -1}, {"get_event", bi_get_event, -1}, {0} }; +static __attribute__((format(printf, 1, 0))) void +qwaq_print (const char *fmt, va_list args) +{ + vfprintf (stderr, fmt, args); + fflush (stderr); +} + void BI_Init (progs_t *pr) { qwaq_resources_t *res = calloc (sizeof (*res), 1); res->pr = pr; - res->print_buffer = dstring_newstr (); + for (int i = 0; i < STRING_ID_QUEUE_SIZE - 1; i++) { + RB_WRITE_DATA (res->string_ids, &i, 1); + res->strings[i].mem = &dstring_default_mem; + } PR_Resources_Register (pr, "qwaq", res, bi_qwaq_clear); PR_RegisterBuiltins (pr, builtins); Sys_RegisterShutdown (bi_shutdown); + Sys_SetStdPrintf (qwaq_print); } From 513c808875ccaae0e9cbede9f8ba8d1b0ac97413 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 02:07:47 +0900 Subject: [PATCH 0449/3664] [qwaq] Make some bad ascii art --- tools/qwaq/qwaq-app.r | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index a0b2a2c63..bf3bfb85e 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -16,7 +16,9 @@ int main (int argc, string *argv) initialize (); window_t win = create_window (20, 5, 50, 10); - mvwprintf (win, 0, 0, "Hi there!\n"); + mvwprintf (win, 0, 0, "Hi there! (q to quit)\n"); + mvwprintf (win, 1, 1, "(?)Oo.\n"); + mvwprintf (win, 1, 2, " \\_O>\n"); do { if (get_event (&event)) { if (event.event_type == qe_key) { From 0119660b01c5a8bba42915c9239bebef5df93fd4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 11:44:43 +0900 Subject: [PATCH 0450/3664] [qwaq] Convert remaining functions to command queue Now that the initial prototype seems to be working well, it's time to implement more commands. I might have to do some wrappers for actual command writing (and result reading) as it looks like there will be a lot of nearly identical code. --- tools/qwaq/qwaq-app.r | 2 + tools/qwaq/qwaq-curses.c | 101 ++++++++++++++++++++++++++++++--------- 2 files changed, 80 insertions(+), 23 deletions(-) diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index bf3bfb85e..3e51b7e98 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -32,5 +32,7 @@ int main (int argc, string *argv) } } } while (ch != 'q' && ch != 'Q'); + destroy_window (win); + get_event (&event); return 0; } diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index bb5c3a958..e218e969a 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -265,7 +265,6 @@ create_window (qwaq_resources_t *res) keypad (window->win, TRUE); int window_id = window_index (res, window); - int cmd_result[] = { qwaq_cmd_create_window, window_id }; // loop @@ -274,6 +273,44 @@ create_window (qwaq_resources_t *res) } } +static void +destroy_window (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + + window_t *window = get_window (res, __FUNCTION__, window_id); + delwin (window->win); + window_free (res, window); +} + +static void +create_panel (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + + window_t *window = get_window (res, __FUNCTION__, window_id); + panel_t *panel = panel_new (res); + panel->panel = new_panel (window->win); + + int panel_id = panel_index (res, panel); + int cmd_result[] = { qwaq_cmd_create_panel, panel_id }; + + // loop + if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { + RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); + } +} + +static void +destroy_panel (qwaq_resources_t *res) +{ + int panel_id = RB_PEEK_DATA (res->command_queue, 2); + + panel_t *panel = get_panel (res, __FUNCTION__, panel_id); + del_panel (panel->panel); + panel_free (res, panel); +} + static void move_print (qwaq_resources_t *res) { @@ -297,10 +334,13 @@ process_commands (qwaq_resources_t *res) create_window (res); break; case qwaq_cmd_destroy_window: + destroy_window (res); break; case qwaq_cmd_create_panel: + create_panel (res); break; case qwaq_cmd_destroy_panel: + destroy_panel (res); break; case qwaq_cmd_mvwprint: move_print (res); @@ -411,31 +451,56 @@ static void bi_destroy_window (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); - delwin (window->win); - window->win = 0; - window_free (res, window); + int window_id = P_INT (pr, 0); + int command[] = { qwaq_cmd_destroy_window, 0, window_id, }; + + if (get_window (res, __FUNCTION__, window_id)) { + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + } } static void bi_create_panel (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); + int window_id = P_INT (pr, 0); + int command[] = { qwaq_cmd_create_panel, 0, window_id, }; - panel_t *panel = panel_new (res); - panel->panel = new_panel (window->win); - R_INT (pr) = panel_index (res, panel); + if (get_window (res, __FUNCTION__, window_id)) { + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + + // locking and loop until id is correct + if (RB_DATA_AVAILABLE (res->results) + && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_create_panel) { + int cmd_result[2]; // should results have a size? + RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); + R_INT (pr) = cmd_result[1]; + } + } } static void bi_destroy_panel (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - panel_t *panel = get_panel (res, __FUNCTION__, P_INT (pr, 0)); - del_panel (panel->panel); - panel->panel = 0; - panel_free (res, panel); + int panel_id = P_INT (pr, 0); + int command[] = { qwaq_cmd_destroy_panel, 0, panel_id, }; + + if (get_panel (res, __FUNCTION__, panel_id)) { + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + } } static void @@ -467,15 +532,6 @@ bi_mvwprintf (progs_t *pr) } } -static void -bi_wgetch (progs_t *pr) -{ - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - window_t *window = get_window (res, __FUNCTION__, P_INT (pr, 0)); - - R_INT (pr) = wgetch (window->win); -} - static void bi_get_event (progs_t *pr) { @@ -525,7 +581,6 @@ static builtin_t builtins[] = { {"create_panel", bi_create_panel, -1}, {"destroy_panel", bi_destroy_panel, -1}, {"mvwprintf", bi_mvwprintf, -1}, - {"wgetch", bi_wgetch, -1}, {"get_event", bi_get_event, -1}, {0} }; From ea69921e6a268a35b37e7f094a2bd0416ca1cc97 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 12:33:45 +0900 Subject: [PATCH 0451/3664] [qwaq] Validate window before acquiring string If the window is invalid and recovery is done, string ids will leak if acquired before validation. Afterwards, make the rest of the builtin wrappers consistent: extract parameters, validate, [acquire resources], generate command. --- tools/qwaq/qwaq-curses.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index e218e969a..8460a36b4 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -452,9 +452,10 @@ bi_destroy_window (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); int window_id = P_INT (pr, 0); - int command[] = { qwaq_cmd_destroy_window, 0, window_id, }; if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_destroy_window, 0, window_id, }; + command[1] = CMD_SIZE(command); if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { @@ -468,9 +469,10 @@ bi_create_panel (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); int window_id = P_INT (pr, 0); - int command[] = { qwaq_cmd_create_panel, 0, window_id, }; if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_create_panel, 0, window_id, }; + command[1] = CMD_SIZE(command); if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { @@ -514,14 +516,14 @@ bi_mvwprintf (progs_t *pr) int count = pr->pr_argc - 4; pr_type_t **args = pr->pr_params + 4; - int string_id = acquire_string (res); - dstring_t *print_buffer = res->strings + string_id; - int command[] = { - qwaq_cmd_mvwprint, 0, - window_id, x, y, string_id - }; - if (get_window (res, __FUNCTION__, window_id)) { + int string_id = acquire_string (res); + dstring_t *print_buffer = res->strings + string_id; + int command[] = { + qwaq_cmd_mvwprint, 0, + window_id, x, y, string_id + }; + command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); From 17005637cadbd74d6d3d08720c9daeb3b23adfe6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 12:46:25 +0900 Subject: [PATCH 0452/3664] [qwaq] Rename the internal function names Now they reflect the curses functions they wrap. The externally visible builtin names are not changed because the parameters are in x, y order rather than curses' y, x order. --- tools/qwaq/qwaq-curses.c | 76 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index 8460a36b4..fafbe8c80 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -52,11 +52,11 @@ #define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) typedef enum qwaq_commands_e { - qwaq_cmd_create_window, - qwaq_cmd_destroy_window, - qwaq_cmd_create_panel, - qwaq_cmd_destroy_panel, - qwaq_cmd_mvwprint, + qwaq_cmd_newwin, + qwaq_cmd_delwin, + qwaq_cmd_new_panel, + qwaq_cmd_del_panel, + qwaq_cmd_mvwaddstr, } qwaq_commands; #define RING_BUFFER(type, size) \ @@ -253,7 +253,7 @@ release_string (qwaq_resources_t *res, int string_id) } static void -create_window (qwaq_resources_t *res) +cmd_newwin (qwaq_resources_t *res) { int xpos = RB_PEEK_DATA (res->command_queue, 2); int ypos = RB_PEEK_DATA (res->command_queue, 3); @@ -265,7 +265,7 @@ create_window (qwaq_resources_t *res) keypad (window->win, TRUE); int window_id = window_index (res, window); - int cmd_result[] = { qwaq_cmd_create_window, window_id }; + int cmd_result[] = { qwaq_cmd_newwin, window_id }; // loop if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { @@ -274,7 +274,7 @@ create_window (qwaq_resources_t *res) } static void -destroy_window (qwaq_resources_t *res) +cmd_delwin (qwaq_resources_t *res) { int window_id = RB_PEEK_DATA (res->command_queue, 2); @@ -284,7 +284,7 @@ destroy_window (qwaq_resources_t *res) } static void -create_panel (qwaq_resources_t *res) +cmd_new_panel (qwaq_resources_t *res) { int window_id = RB_PEEK_DATA (res->command_queue, 2); @@ -293,7 +293,7 @@ create_panel (qwaq_resources_t *res) panel->panel = new_panel (window->win); int panel_id = panel_index (res, panel); - int cmd_result[] = { qwaq_cmd_create_panel, panel_id }; + int cmd_result[] = { qwaq_cmd_new_panel, panel_id }; // loop if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { @@ -302,7 +302,7 @@ create_panel (qwaq_resources_t *res) } static void -destroy_panel (qwaq_resources_t *res) +cmd_del_panel (qwaq_resources_t *res) { int panel_id = RB_PEEK_DATA (res->command_queue, 2); @@ -312,7 +312,7 @@ destroy_panel (qwaq_resources_t *res) } static void -move_print (qwaq_resources_t *res) +cmd_mvwaddstr (qwaq_resources_t *res) { int window_id = RB_PEEK_DATA (res->command_queue, 2); int x = RB_PEEK_DATA (res->command_queue, 3); @@ -330,20 +330,20 @@ process_commands (qwaq_resources_t *res) { while (RB_DATA_AVAILABLE (res->command_queue) > 2) { switch ((qwaq_commands) RB_PEEK_DATA (res->command_queue, 0)) { - case qwaq_cmd_create_window: - create_window (res); + case qwaq_cmd_newwin: + cmd_newwin (res); break; - case qwaq_cmd_destroy_window: - destroy_window (res); + case qwaq_cmd_delwin: + cmd_delwin (res); break; - case qwaq_cmd_create_panel: - create_panel (res); + case qwaq_cmd_new_panel: + cmd_new_panel (res); break; - case qwaq_cmd_destroy_panel: - destroy_panel (res); + case qwaq_cmd_del_panel: + cmd_del_panel (res); break; - case qwaq_cmd_mvwprint: - move_print (res); + case qwaq_cmd_mvwaddstr: + cmd_mvwaddstr (res); break; } RB_DROP_DATA (res->command_queue, RB_PEEK_DATA (res->command_queue, 1)); @@ -418,7 +418,7 @@ bi_shutdown (void) } static void -bi_create_window (progs_t *pr) +bi_newwin (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); int xpos = P_INT (pr, 0); @@ -426,7 +426,7 @@ bi_create_window (progs_t *pr) int xlen = P_INT (pr, 2); int ylen = P_INT (pr, 3); int command[] = { - qwaq_cmd_create_window, 0, + qwaq_cmd_newwin, 0, xpos, ypos, xlen, ylen, }; @@ -440,7 +440,7 @@ bi_create_window (progs_t *pr) process_input (res); // locking and loop until id is correct if (RB_DATA_AVAILABLE (res->results) - && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_create_window) { + && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_newwin) { int cmd_result[2]; // should results have a size? RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); R_INT (pr) = cmd_result[1]; @@ -448,13 +448,13 @@ bi_create_window (progs_t *pr) } static void -bi_destroy_window (progs_t *pr) +bi_delwin (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); int window_id = P_INT (pr, 0); if (get_window (res, __FUNCTION__, window_id)) { - int command[] = { qwaq_cmd_destroy_window, 0, window_id, }; + int command[] = { qwaq_cmd_delwin, 0, window_id, }; command[1] = CMD_SIZE(command); @@ -465,13 +465,13 @@ bi_destroy_window (progs_t *pr) } static void -bi_create_panel (progs_t *pr) +bi_new_panel (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); int window_id = P_INT (pr, 0); if (get_window (res, __FUNCTION__, window_id)) { - int command[] = { qwaq_cmd_create_panel, 0, window_id, }; + int command[] = { qwaq_cmd_new_panel, 0, window_id, }; command[1] = CMD_SIZE(command); @@ -481,7 +481,7 @@ bi_create_panel (progs_t *pr) // locking and loop until id is correct if (RB_DATA_AVAILABLE (res->results) - && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_create_panel) { + && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_new_panel) { int cmd_result[2]; // should results have a size? RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); R_INT (pr) = cmd_result[1]; @@ -490,11 +490,11 @@ bi_create_panel (progs_t *pr) } static void -bi_destroy_panel (progs_t *pr) +bi_del_panel (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); int panel_id = P_INT (pr, 0); - int command[] = { qwaq_cmd_destroy_panel, 0, panel_id, }; + int command[] = { qwaq_cmd_del_panel, 0, panel_id, }; if (get_panel (res, __FUNCTION__, panel_id)) { command[1] = CMD_SIZE(command); @@ -520,14 +520,14 @@ bi_mvwprintf (progs_t *pr) int string_id = acquire_string (res); dstring_t *print_buffer = res->strings + string_id; int command[] = { - qwaq_cmd_mvwprint, 0, + qwaq_cmd_mvwaddstr, 0, window_id, x, y, string_id }; command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "mvwprintf", fmt, count, args); + PR_Sprintf (pr, print_buffer, "mvwaddstr", fmt, count, args); if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); } @@ -578,10 +578,10 @@ bi_qwaq_clear (progs_t *pr, void *data) static builtin_t builtins[] = { {"initialize", bi_initialize, -1}, - {"create_window", bi_create_window, -1}, - {"destroy_window", bi_destroy_window, -1}, - {"create_panel", bi_create_panel, -1}, - {"destroy_panel", bi_destroy_panel, -1}, + {"create_window", bi_newwin, -1}, + {"destroy_window", bi_delwin, -1}, + {"create_panel", bi_new_panel, -1}, + {"destroy_panel", bi_del_panel, -1}, {"mvwprintf", bi_mvwprintf, -1}, {"get_event", bi_get_event, -1}, {0} From 5e4677f8d54471d2949e84d089aafcb8275dff5b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 13:06:58 +0900 Subject: [PATCH 0453/3664] [qwaq] Implement the immediately useful panel functions --- tools/qwaq/qwaq-curses.c | 129 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 2 deletions(-) diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index fafbe8c80..eaab87c82 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -56,6 +56,11 @@ typedef enum qwaq_commands_e { qwaq_cmd_delwin, qwaq_cmd_new_panel, qwaq_cmd_del_panel, + qwaq_cmd_hide_panel, + qwaq_cmd_show_panel, + qwaq_cmd_top_panel, + qwaq_cmd_bottom_panel, + qwaq_cmd_move_panel, qwaq_cmd_mvwaddstr, } qwaq_commands; @@ -311,6 +316,58 @@ cmd_del_panel (qwaq_resources_t *res) panel_free (res, panel); } +static void +cmd_hide_panel (qwaq_resources_t *res) +{ + int panel_id = RB_PEEK_DATA (res->command_queue, 2); + + panel_t *panel = get_panel (res, __FUNCTION__, panel_id); + hide_panel (panel->panel); + panel_free (res, panel); +} + +static void +cmd_show_panel (qwaq_resources_t *res) +{ + int panel_id = RB_PEEK_DATA (res->command_queue, 2); + + panel_t *panel = get_panel (res, __FUNCTION__, panel_id); + show_panel (panel->panel); + panel_free (res, panel); +} + +static void +cmd_top_panel (qwaq_resources_t *res) +{ + int panel_id = RB_PEEK_DATA (res->command_queue, 2); + + panel_t *panel = get_panel (res, __FUNCTION__, panel_id); + top_panel (panel->panel); + panel_free (res, panel); +} + +static void +cmd_bottom_panel (qwaq_resources_t *res) +{ + int panel_id = RB_PEEK_DATA (res->command_queue, 2); + + panel_t *panel = get_panel (res, __FUNCTION__, panel_id); + bottom_panel (panel->panel); + panel_free (res, panel); +} + +static void +cmd_move_panel (qwaq_resources_t *res) +{ + int panel_id = RB_PEEK_DATA (res->command_queue, 2); + int x = RB_PEEK_DATA (res->command_queue, 3); + int y = RB_PEEK_DATA (res->command_queue, 4); + + panel_t *panel = get_panel (res, __FUNCTION__, panel_id); + move_panel (panel->panel, y, x); + panel_free (res, panel); +} + static void cmd_mvwaddstr (qwaq_resources_t *res) { @@ -342,6 +399,21 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_del_panel: cmd_del_panel (res); break; + case qwaq_cmd_hide_panel: + cmd_hide_panel (res); + break; + case qwaq_cmd_show_panel: + cmd_show_panel (res); + break; + case qwaq_cmd_top_panel: + cmd_top_panel (res); + break; + case qwaq_cmd_bottom_panel: + cmd_bottom_panel (res); + break; + case qwaq_cmd_move_panel: + cmd_move_panel (res); + break; case qwaq_cmd_mvwaddstr: cmd_mvwaddstr (res); break; @@ -490,13 +562,61 @@ bi_new_panel (progs_t *pr) } static void -bi_del_panel (progs_t *pr) +panel_command (progs_t *pr, qwaq_commands cmd) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); int panel_id = P_INT (pr, 0); - int command[] = { qwaq_cmd_del_panel, 0, panel_id, }; if (get_panel (res, __FUNCTION__, panel_id)) { + int command[] = { cmd, 0, panel_id, }; + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + } +} + +static void +bi_del_panel (progs_t *pr) +{ + panel_command (pr, qwaq_cmd_del_panel); +} + +static void +bi_hide_panel (progs_t *pr) +{ + panel_command (pr, qwaq_cmd_hide_panel); +} + +static void +bi_show_panel (progs_t *pr) +{ + panel_command (pr, qwaq_cmd_show_panel); +} + +static void +bi_top_panel (progs_t *pr) +{ + panel_command (pr, qwaq_cmd_top_panel); +} + +static void +bi_bottom_panel (progs_t *pr) +{ + panel_command (pr, qwaq_cmd_bottom_panel); +} + +static void +bi_move_panel (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int panel_id = P_INT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + + if (get_panel (res, __FUNCTION__, panel_id)) { + int command[] = { qwaq_cmd_move_panel, 0, panel_id, x, y, }; command[1] = CMD_SIZE(command); if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { @@ -582,6 +702,11 @@ static builtin_t builtins[] = { {"destroy_window", bi_delwin, -1}, {"create_panel", bi_new_panel, -1}, {"destroy_panel", bi_del_panel, -1}, + {"hide_panel", bi_hide_panel, -1}, + {"show_panel", bi_show_panel, -1}, + {"top_panel", bi_top_panel, -1}, + {"bottom_panel", bi_bottom_panel, -1}, + {"move_panel", bi_move_panel, -1}, {"mvwprintf", bi_mvwprintf, -1}, {"get_event", bi_get_event, -1}, {0} From f5f50ae23133f2924113be937d28ea56f6293b1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 14:38:54 +0900 Subject: [PATCH 0454/3664] [qwaq] Make stdscr available to progs --- tools/qwaq/qwaq-app.r | 2 ++ tools/qwaq/qwaq-curses.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index 3e51b7e98..9e8706b89 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -2,6 +2,8 @@ typedef struct window_s *window_t; +window_t stdscr = (window_t) 1; + void initialize (void) = #0; window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; void destroy_window (window_t win) = #0; diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index eaab87c82..00caef9f5 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -142,6 +142,7 @@ typedef struct panel_s { typedef struct qwaq_resources_s { progs_t *pr; int initialized; + window_t stdscr; PR_RESMAP (window_t) window_map; PR_RESMAP (panel_t) panel_map; RING_BUFFER (qwaq_event_t, QUEUE_SIZE) event_queue; @@ -184,6 +185,10 @@ window_index (qwaq_resources_t *res, window_t *win) static always_inline window_t * __attribute__((pure)) get_window (qwaq_resources_t *res, const char *name, int handle) { + if (handle == 1) { + return &res->stdscr; + } + window_t *window = window_get (res, handle); if (!window || !window->win) { @@ -681,6 +686,8 @@ bi_initialize (progs_t *pr) mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); write(1, MOUSE_MOVES, sizeof (MOUSE_MOVES) - 1); refresh(); + + res->stdscr.win = stdscr; } static void From ec4e9b326d1d1cc988fca1ca786073b6b04bbfbf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 14:43:08 +0900 Subject: [PATCH 0455/3664] [qwaq] Don't call wrefresh in cmd_mvwaddstr There is now an implementation for wrefresh. --- tools/qwaq/qwaq-app.r | 13 ++++++++----- tools/qwaq/qwaq-curses.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index 9e8706b89..ccf7485bb 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -8,6 +8,7 @@ void initialize (void) = #0; window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; void destroy_window (window_t win) = #0; void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; +void wrefresh (window_t win) = #0; int get_event (qwaq_event_t *event) = #0; @@ -18,20 +19,22 @@ int main (int argc, string *argv) initialize (); window_t win = create_window (20, 5, 50, 10); - mvwprintf (win, 0, 0, "Hi there! (q to quit)\n"); - mvwprintf (win, 1, 1, "(?)Oo.\n"); - mvwprintf (win, 1, 2, " \\_O>\n"); + mvwprintf (win, 0, 0, "Hi there! (q to quit)"); + mvwprintf (win, 1, 1, "(?)Oo."); + mvwprintf (win, 1, 2, " \\_O>"); + wrefresh (win); do { if (get_event (&event)) { if (event.event_type == qe_key) { ch = event.e.key; - mvwprintf (win, 1, 1, "key: %d\n", ch); + mvwprintf (win, 1, 1, "key: %d", ch); } else if (event.event_type == qe_mouse) { - mvwprintf (win, 1, 2, "mouse: %2d %2d %08x\n", + mvwprintf (win, 1, 2, "mouse: %2d %2d %08x", event.e.mouse.x, event.e.mouse.y, event.e.mouse.buttons); } + wrefresh (win); } } while (ch != 'q' && ch != 'Q'); destroy_window (win); diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index 00caef9f5..0f80dfc62 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -62,6 +62,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_bottom_panel, qwaq_cmd_move_panel, qwaq_cmd_mvwaddstr, + qwaq_cmd_wrefresh, } qwaq_commands; #define RING_BUFFER(type, size) \ @@ -384,6 +385,14 @@ cmd_mvwaddstr (qwaq_resources_t *res) window_t *window = get_window (res, __FUNCTION__, window_id); mvwaddstr (window->win, y, x, res->strings[string_id].str); release_string (res, string_id); +} + +static void +cmd_wrefresh (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + + window_t *window = get_window (res, __FUNCTION__, window_id); wrefresh (window->win); } @@ -422,6 +431,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_mvwaddstr: cmd_mvwaddstr (res); break; + case qwaq_cmd_wrefresh: + cmd_wrefresh (res); + break; } RB_DROP_DATA (res->command_queue, RB_PEEK_DATA (res->command_queue, 1)); } @@ -659,6 +671,22 @@ bi_mvwprintf (progs_t *pr) } } +static void +bi_wrefresh (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int window_id = P_INT (pr, 0); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_wrefresh, 0, window_id, }; + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + } +} + static void bi_get_event (progs_t *pr) { @@ -715,6 +743,7 @@ static builtin_t builtins[] = { {"bottom_panel", bi_bottom_panel, -1}, {"move_panel", bi_move_panel, -1}, {"mvwprintf", bi_mvwprintf, -1}, + {"wrefresh", bi_wrefresh, -1}, {"get_event", bi_get_event, -1}, {0} }; From ae532870c42d057bd431db8580440badfe5a3fa3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 14:48:18 +0900 Subject: [PATCH 0456/3664] [qwaq] Implement basic color support --- tools/qwaq/color.h | 21 +++++++++++ tools/qwaq/qwaq-app.r | 10 +++++ tools/qwaq/qwaq-curses.c | 79 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 tools/qwaq/color.h diff --git a/tools/qwaq/color.h b/tools/qwaq/color.h new file mode 100644 index 000000000..95067b5de --- /dev/null +++ b/tools/qwaq/color.h @@ -0,0 +1,21 @@ +#ifndef __qwaq_color_h +#define __qwaq_color_h + +#ifndef COLOR_PAIR +// double protection in case this header is included in a C file + +#define COLOR_PAIR(cp) ((cp) << 8) + +// taken from ncurses.h +#define COLOR_BLACK 0 +#define COLOR_RED 1 +#define COLOR_GREEN 2 +#define COLOR_YELLOW 3 +#define COLOR_BLUE 4 +#define COLOR_MAGENTA 5 +#define COLOR_CYAN 6 +#define COLOR_WHITE 7 + +#endif + +#endif//__qwaq_color_h diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index ccf7485bb..3e39f14a0 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -1,3 +1,4 @@ +#include "color.h" #include "event.h" typedef struct window_s *window_t; @@ -11,6 +12,10 @@ void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; void wrefresh (window_t win) = #0; int get_event (qwaq_event_t *event) = #0; +int max_colors (void) = #0; +int max_color_pairs (void) = #0; +int init_pair (int pair, int f, int b) = #0; +void wbkgd (window_t win, int ch) = #0; int main (int argc, string *argv) { @@ -18,10 +23,15 @@ int main (int argc, string *argv) qwaq_event_t event = { }; initialize (); + init_pair (1, COLOR_WHITE, COLOR_BLUE); + wbkgd (stdscr, COLOR_PAIR(1)); + wrefresh (stdscr); window_t win = create_window (20, 5, 50, 10); + wbkgd (win, COLOR_PAIR(0)); mvwprintf (win, 0, 0, "Hi there! (q to quit)"); mvwprintf (win, 1, 1, "(?)Oo."); mvwprintf (win, 1, 2, " \\_O>"); + mvwprintf (win, 1, 3, " %d %d", max_colors (), max_color_pairs ()); wrefresh (win); do { if (get_event (&event)) { diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index 0f80dfc62..a5db37e02 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -63,6 +63,8 @@ typedef enum qwaq_commands_e { qwaq_cmd_move_panel, qwaq_cmd_mvwaddstr, qwaq_cmd_wrefresh, + qwaq_cmd_init_pair, + qwaq_cmd_wbkgd, } qwaq_commands; #define RING_BUFFER(type, size) \ @@ -396,6 +398,26 @@ cmd_wrefresh (qwaq_resources_t *res) wrefresh (window->win); } +static void +cmd_init_pair (qwaq_resources_t *res) +{ + int pair = RB_PEEK_DATA (res->command_queue, 2); + int f = RB_PEEK_DATA (res->command_queue, 3); + int b = RB_PEEK_DATA (res->command_queue, 4); + + init_pair (pair, f, b); +} + +static void +cmd_wbkgd (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int ch = RB_PEEK_DATA (res->command_queue, 3); + + window_t *window = get_window (res, __FUNCTION__, window_id); + wbkgd (window->win, ch); +} + static void process_commands (qwaq_resources_t *res) { @@ -434,6 +456,12 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_wrefresh: cmd_wrefresh (res); break; + case qwaq_cmd_init_pair: + cmd_init_pair (res); + break; + case qwaq_cmd_wbkgd: + cmd_wbkgd (res); + break; } RB_DROP_DATA (res->command_queue, RB_PEEK_DATA (res->command_queue, 1)); } @@ -698,6 +726,52 @@ bi_get_event (progs_t *pr) R_INT (pr) = get_event (res, event); } +static void +bi_max_colors (progs_t *pr) +{ + R_INT (pr) = COLORS; +} + +static void +bi_max_color_pairs (progs_t *pr) +{ + R_INT (pr) = COLOR_PAIRS; +} + +static void +bi_init_pair (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int pair = P_INT (pr, 0); + int f = P_INT (pr, 1); + int b = P_INT (pr, 2); + + int command[] = { qwaq_cmd_init_pair, 0, pair, f, b, }; + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } +} + +static void +bi_wbkgd (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int window_id = P_INT (pr, 0); + int ch = P_INT (pr, 1); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_wbkgd, 0, window_id, ch, }; + + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + } +} + static void bi_initialize (progs_t *pr) { @@ -706,6 +780,7 @@ bi_initialize (progs_t *pr) initscr (); need_endwin = 1; res->initialized = 1; + start_color (); raw (); keypad (stdscr, TRUE); noecho (); @@ -745,6 +820,10 @@ static builtin_t builtins[] = { {"mvwprintf", bi_mvwprintf, -1}, {"wrefresh", bi_wrefresh, -1}, {"get_event", bi_get_event, -1}, + {"max_colors", bi_max_colors, -1}, + {"max_color_pairs", bi_max_color_pairs, -1}, + {"init_pair", bi_init_pair, -1}, + {"wbkgd", bi_wbkgd, -1}, {0} }; From 75f4cebf0eda783cb9bb54a4770a3369b3a7fa93 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 16:11:07 +0900 Subject: [PATCH 0457/3664] Clean up after removal of uint32.h I guess I forgot to check for its usage in header files, and the fact that it didn't get cleaned out from being installed hid the error. --- include/QF/mdfour.h | 8 ++++---- libs/util/mdfour.c | 19 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/QF/mdfour.h b/include/QF/mdfour.h index bff20aefb..ec8648cd2 100644 --- a/include/QF/mdfour.h +++ b/include/QF/mdfour.h @@ -29,17 +29,17 @@ #ifndef __QF_mdfour_h #define __QF_mdfour_h +#include "QF/qtypes.h" + /** \addtogroup crc */ ///@{ -#include "QF/uint32.h" - #define MDFOUR_DIGEST_BYTES 16 struct mdfour { - uint32 A, B, C, D; - uint32 totalN; + uint32_t A, B, C, D; + uint32_t totalN; }; void mdfour_begin(struct mdfour *md); // old: MD4Init diff --git a/libs/util/mdfour.c b/libs/util/mdfour.c index 99f57bef2..61bc46e9a 100644 --- a/libs/util/mdfour.c +++ b/libs/util/mdfour.c @@ -37,7 +37,6 @@ #endif #include "QF/mdfour.h" -#include "QF/uint32.h" /* NOTE: This code makes no attempt to be fast! It assumes that a int is at least 32 bits long @@ -62,12 +61,12 @@ static struct mdfour *m; /* this applies md4 to 64 byte chunks */ static void -mdfour64 (uint32 * M) +mdfour64 (uint32_t * M) { int j; - uint32 AA, BB, CC, DD; - uint32 X[16]; - uint32 A, B, C, D; + uint32_t AA, BB, CC, DD; + uint32_t X[16]; + uint32_t A, B, C, D; for (j = 0; j < 16; j++) X[j] = M[j]; @@ -154,7 +153,7 @@ mdfour64 (uint32 * M) } static void -copy64 (uint32 * M, const unsigned char *in) +copy64 (uint32_t * M, const unsigned char *in) { int i; @@ -164,7 +163,7 @@ copy64 (uint32 * M, const unsigned char *in) } static void -copy4 (unsigned char *out, uint32 x) +copy4 (unsigned char *out, uint32_t x) { out[0] = x & 0xFF; out[1] = (x >> 8) & 0xFF; @@ -186,8 +185,8 @@ static void mdfour_tail (const unsigned char *in, int n) { unsigned char buf[128]; - uint32 M[16]; - uint32 b; + uint32_t M[16]; + uint32_t b; m->totalN += n; @@ -214,7 +213,7 @@ mdfour_tail (const unsigned char *in, int n) VISIBLE void mdfour_update (struct mdfour *md, const unsigned char *in, int n) { - uint32 M[16]; + uint32_t M[16]; if (n == 0) mdfour_tail (in, n); From 8b6d05a4dd2cbc95508b2fc604a353c9fd8b774c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 16:36:23 +0900 Subject: [PATCH 0458/3664] [qwaq] Ensure mouse motion reporting gets turned off It seems that xterm automatically disables it when ncurses shuts down and mate-terminal does not, or maybe a different version of something. Still, good to clean up properly. --- tools/qwaq/qwaq-curses.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index a5db37e02..73fe6b39b 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -46,7 +46,8 @@ #define always_inline inline __attribute__((__always_inline__)) #define QUEUE_SIZE 16 -#define MOUSE_MOVES "\033[?1003h" // Make the terminal report mouse movements +#define MOUSE_MOVES_ON "\033[?1003h"// Make the terminal report mouse movements +#define MOUSE_MOVES_OFF "\033[?1003l"// Make the terminal report mouse movements #define STRING_ID_QUEUE_SIZE 8 // must be > 1 #define COMMAND_QUEUE_SIZE 128 #define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) @@ -530,6 +531,7 @@ static void bi_shutdown (void) { if (need_endwin) { + write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); endwin (); } } @@ -787,7 +789,7 @@ bi_initialize (progs_t *pr) nonl (); nodelay (stdscr, TRUE); mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); - write(1, MOUSE_MOVES, sizeof (MOUSE_MOVES) - 1); + write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); refresh(); res->stdscr.win = stdscr; @@ -799,6 +801,7 @@ bi_qwaq_clear (progs_t *pr, void *data) __auto_type res = (qwaq_resources_t *) data; if (res->initialized) { + write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); endwin (); } need_endwin = 0; From e93ca9d828c55846f42c0bea00d227d8a9983233 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 20:13:25 +0900 Subject: [PATCH 0459/3664] [qfcc] Fix infinite loop in linker --- tools/qfcc/source/linker.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 3ce5ca3fd..5a9d367ce 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -1122,12 +1122,11 @@ undefined_def (qfo_def_t *def) if (func->code < 0) { continue; } - if ((pr_uint_t) func->code > reloc->offset) { - continue; - } - if (!best || reloc->offset - func->code < best_dist) { - best = func; - best_dist = reloc->offset - func->code; + if ((pr_uint_t) func->code <= reloc->offset) { + if (!best || reloc->offset - func->code < best_dist) { + best = func; + best_dist = reloc->offset - func->code; + } } func++; } From 271d836cd2ba2157b6ab51be740fef1fd7b60d62 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Feb 2020 21:09:24 +0900 Subject: [PATCH 0460/3664] [qfcc] Catch static class instances in structs --- tools/qfcc/source/struct.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 5fe569d31..989b298ef 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -47,6 +47,7 @@ #include #include +#include "class.h" #include "def.h" #include "defspace.h" #include "diagnostic.h" @@ -123,6 +124,10 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) for (s = symtab->symbols; s; s = s->next) { if (s->sy_type != sy_var) continue; + if (obj_is_class (s->type)) { + error (0, "statically allocated instance of class %s", + s->type->t.class->name); + } if (su == 's') { symtab->size = RUP (symtab->size, s->type->alignment); s->s.offset = symtab->size; From c079eb851b4165c80aad33f88475f2f8465ec8f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 00:40:55 +0900 Subject: [PATCH 0461/3664] [qwaq] Start work on the actual app It doesn't look good, but it does have panel based windows working, and using objects. Won't build reliably right now due to qwaq being in tools and thus building before ruamoko, but I'll fix that next. --- tools/qwaq/Makefile.am | 4 +- tools/qwaq/event.h | 15 ++- tools/qwaq/qwaq-app.h | 18 ++++ tools/qwaq/qwaq-app.r | 142 ++++++++++++++++++++-------- tools/qwaq/qwaq-curses.c | 198 +++++++++++++++++++++++++++++++++++++++ tools/qwaq/qwaq-curses.h | 37 ++++++++ tools/qwaq/qwaq-view.h | 44 +++++++++ tools/qwaq/qwaq-view.r | 105 +++++++++++++++++++++ tools/qwaq/qwaq-window.h | 11 +++ tools/qwaq/qwaq-window.r | 8 ++ 10 files changed, 540 insertions(+), 42 deletions(-) create mode 100644 tools/qwaq/qwaq-app.h create mode 100644 tools/qwaq/qwaq-curses.h create mode 100644 tools/qwaq/qwaq-view.h create mode 100644 tools/qwaq/qwaq-view.r create mode 100644 tools/qwaq/qwaq-window.h create mode 100644 tools/qwaq/qwaq-window.r diff --git a/tools/qwaq/Makefile.am b/tools/qwaq/Makefile.am index b6e9b8345..f38fc77e5 100644 --- a/tools/qwaq/Makefile.am +++ b/tools/qwaq/Makefile.am @@ -57,11 +57,11 @@ qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) r_depfiles_remade= -qwaq_app_dat_SOURCES=qwaq-app.r +qwaq_app_dat_SOURCES=qwaq-app.r qwaq-view.r qwaq-window.r qwaq_app_obj=$(qwaq_app_dat_SOURCES:.r=.o) qwaq_app_dep=$(addprefix ./$(DEPDIR)/,$(qwaq_app_obj:.o=.Qo)) qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(qwaq_app_obj) + $(QFCC) $(QCFLAGS) -o $@ $(qwaq_app_obj) -lr include $(qwaq_app_dep) # am--include-marker r_depfiles_remade += $(qwaq_app_dep) diff --git a/tools/qwaq/event.h b/tools/qwaq/event.h index 933c61569..006d37c42 100644 --- a/tools/qwaq/event.h +++ b/tools/qwaq/event.h @@ -2,22 +2,33 @@ #define __qwaq_event_h typedef enum { - qe_idle, + qe_none, qe_key, qe_mouse, + qe_command, // application level command } qwaq_etype; -// right now, this is just a copy of ncurses MEVENT, but all int +typedef enum { + qc_valid, + qc_exit, + qc_error, +} qwaq_command; + typedef struct qwaq_mevent_s { int x, y; int buttons; } qwaq_mevent_t; +typedef struct qwaq_message_s { + qwaq_command command; +} qwaq_message_t; + typedef struct qwaq_event_s { qwaq_etype event_type; union { int key; qwaq_mevent_t mouse; + qwaq_message_t message; } e; } qwaq_event_t; diff --git a/tools/qwaq/qwaq-app.h b/tools/qwaq/qwaq-app.h new file mode 100644 index 000000000..c02beac67 --- /dev/null +++ b/tools/qwaq/qwaq-app.h @@ -0,0 +1,18 @@ +#ifndef __qwaq_app_h +#define __qwaq_app_h + +#include "qwaq-view.h" + +#include "event.h" + +@interface QwaqApplication: Object +{ + qwaq_event_t event; + qwaq_command endState; + View *view; +} +-run; +-handleEvent: (qwaq_event_t *) event; +@end + +#endif//__qwaq_app_h diff --git a/tools/qwaq/qwaq-app.r b/tools/qwaq/qwaq-app.r index 3e39f14a0..80ed06c41 100644 --- a/tools/qwaq/qwaq-app.r +++ b/tools/qwaq/qwaq-app.r @@ -1,7 +1,97 @@ -#include "color.h" -#include "event.h" +#include -typedef struct window_s *window_t; +#include "color.h" +#include "qwaq-app.h" +#include "qwaq-curses.h" +#include "qwaq-window.h" + +static AutoreleasePool *autorelease_pool; +static void +arp_start (void) +{ + autorelease_pool = [[AutoreleasePool alloc] init]; +} + +static void +arp_end (void) +{ + [autorelease_pool release]; + autorelease_pool = nil; +} + +@implementation QwaqApplication ++app +{ + return [[[self alloc] init] autorelease]; +} + +-init +{ + if (!(self = [super init])) { + return nil; + } + initialize (); + init_pair (1, COLOR_WHITE, COLOR_BLUE); + init_pair (2, COLOR_WHITE, COLOR_BLACK); + view = [[View viewFromWindow:stdscr] retain]; + [view setBackground: COLOR_PAIR (1)]; + Rect r = view.rect; + wprintf (view.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + r.xpos = r.xlen / 4; + r.ypos = r.ylen / 4; + r.xlen /= 2; + r.ylen /= 2; + wprintf (view.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + wrefresh(view.window); + Window *w; + [view addView: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; + wprintf (w.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + return self; +} + +-run +{ + do { + arp_start (); + + update_panels (); + doupdate (); + get_event (&event); + if (event.event_type != qe_none) { + [self handleEvent: &event]; + } + + arp_end (); + } while (!endState); + return self; +} + +-handleEvent: (qwaq_event_t *) event +{ + [view handleEvent: event]; + if (event.event_type == qe_key && event.e.key == '\x18') { + event.event_type = qe_command; + event.e.message.command = qc_exit; + } + if (event.event_type == qe_command + && (event.e.message.command == qc_exit + || event.e.message.command == qc_error)) { + endState = event.e.message.command; + } + return self; +} +@end + +int main (int argc, string *argv) +{ + id app = [[QwaqApplication app] retain]; + + [app run]; + [app release]; + qwaq_event_t event; + get_event (&event); // XXX need a "wait for queue idle" + return 0; +} window_t stdscr = (window_t) 1; @@ -9,45 +99,21 @@ void initialize (void) = #0; window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; void destroy_window (window_t win) = #0; void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; +void wprintf (window_t win, string fmt, ...) = #0; void wrefresh (window_t win) = #0; - int get_event (qwaq_event_t *event) = #0; int max_colors (void) = #0; int max_color_pairs (void) = #0; int init_pair (int pair, int f, int b) = #0; void wbkgd (window_t win, int ch) = #0; -int main (int argc, string *argv) -{ - int ch = 0; - qwaq_event_t event = { }; - - initialize (); - init_pair (1, COLOR_WHITE, COLOR_BLUE); - wbkgd (stdscr, COLOR_PAIR(1)); - wrefresh (stdscr); - window_t win = create_window (20, 5, 50, 10); - wbkgd (win, COLOR_PAIR(0)); - mvwprintf (win, 0, 0, "Hi there! (q to quit)"); - mvwprintf (win, 1, 1, "(?)Oo."); - mvwprintf (win, 1, 2, " \\_O>"); - mvwprintf (win, 1, 3, " %d %d", max_colors (), max_color_pairs ()); - wrefresh (win); - do { - if (get_event (&event)) { - if (event.event_type == qe_key) { - ch = event.e.key; - mvwprintf (win, 1, 1, "key: %d", ch); - } else if (event.event_type == qe_mouse) { - mvwprintf (win, 1, 2, "mouse: %2d %2d %08x", - event.e.mouse.x, - event.e.mouse.y, - event.e.mouse.buttons); - } - wrefresh (win); - } - } while (ch != 'q' && ch != 'Q'); - destroy_window (win); - get_event (&event); - return 0; -} +panel_t create_panel (window_t window) = #0; +void destroy_panel (panel_t panel) = #0; +void hide_panel (panel_t panel) = #0; +void show_panel (panel_t panel) = #0; +void top_panel (panel_t panel) = #0; +void bottom_panel (panel_t panel) = #0; +void move_panel (panel_t panel, int x, int y) = #0; +window_t panel_window (panel_t panel) = #0; +void update_panels (void) = #0; +void doupdate (void) = #0; diff --git a/tools/qwaq/qwaq-curses.c b/tools/qwaq/qwaq-curses.c index 73fe6b39b..1c081e1eb 100644 --- a/tools/qwaq/qwaq-curses.c +++ b/tools/qwaq/qwaq-curses.c @@ -55,6 +55,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_newwin, qwaq_cmd_delwin, + qwaq_cmd_getwrect, qwaq_cmd_new_panel, qwaq_cmd_del_panel, qwaq_cmd_hide_panel, @@ -62,7 +63,11 @@ typedef enum qwaq_commands_e { qwaq_cmd_top_panel, qwaq_cmd_bottom_panel, qwaq_cmd_move_panel, + qwaq_cmd_panel_window, + qwaq_cmd_update_panels, + qwaq_cmd_doupdate, qwaq_cmd_mvwaddstr, + qwaq_cmd_waddstr, qwaq_cmd_wrefresh, qwaq_cmd_init_pair, qwaq_cmd_wbkgd, @@ -141,6 +146,7 @@ typedef struct window_s { typedef struct panel_s { PANEL *panel; + int window_id; } panel_t; typedef struct qwaq_resources_s { @@ -297,6 +303,28 @@ cmd_delwin (qwaq_resources_t *res) window_free (res, window); } +static void +cmd_getwrect (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int xpos, ypos; + int xlen, ylen; + + window_t *window = get_window (res, __FUNCTION__, window_id); + getparyx (window->win, ypos, xpos); + if (xpos == -1 && ypos ==-1) { + getbegyx (window->win, ypos, xpos); + } + getmaxyx (window->win, ylen, xlen); + + int cmd_result[] = { qwaq_cmd_getwrect, xpos, ypos, xlen, ylen }; + + // loop + if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { + RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); + } +} + static void cmd_new_panel (qwaq_resources_t *res) { @@ -305,6 +333,7 @@ cmd_new_panel (qwaq_resources_t *res) window_t *window = get_window (res, __FUNCTION__, window_id); panel_t *panel = panel_new (res); panel->panel = new_panel (window->win); + panel->window_id = window_id; int panel_id = panel_index (res, panel); int cmd_result[] = { qwaq_cmd_new_panel, panel_id }; @@ -377,6 +406,34 @@ cmd_move_panel (qwaq_resources_t *res) panel_free (res, panel); } +static void +cmd_panel_window (qwaq_resources_t *res) +{ + int panel_id = RB_PEEK_DATA (res->command_queue, 2); + + panel_t *panel = get_panel (res, __FUNCTION__, panel_id); + + int window_id = panel->window_id; + int cmd_result[] = { qwaq_cmd_panel_window, window_id, }; + + // loop + if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { + RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); + } +} + +static void +cmd_update_panels (qwaq_resources_t *res) +{ + update_panels (); +} + +static void +cmd_doupdate (qwaq_resources_t *res) +{ + doupdate (); +} + static void cmd_mvwaddstr (qwaq_resources_t *res) { @@ -390,6 +447,17 @@ cmd_mvwaddstr (qwaq_resources_t *res) release_string (res, string_id); } +static void +cmd_waddstr (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int string_id = RB_PEEK_DATA (res->command_queue, 3); + + window_t *window = get_window (res, __FUNCTION__, window_id); + waddstr (window->win, res->strings[string_id].str); + release_string (res, string_id); +} + static void cmd_wrefresh (qwaq_resources_t *res) { @@ -430,6 +498,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_delwin: cmd_delwin (res); break; + case qwaq_cmd_getwrect: + cmd_getwrect (res); + break; case qwaq_cmd_new_panel: cmd_new_panel (res); break; @@ -451,9 +522,21 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_move_panel: cmd_move_panel (res); break; + case qwaq_cmd_panel_window: + cmd_panel_window (res); + break; + case qwaq_cmd_update_panels: + cmd_update_panels (res); + break; + case qwaq_cmd_doupdate: + cmd_doupdate (res); + break; case qwaq_cmd_mvwaddstr: cmd_mvwaddstr (res); break; + case qwaq_cmd_waddstr: + cmd_waddstr (res); + break; case qwaq_cmd_wrefresh: cmd_wrefresh (res); break; @@ -583,6 +666,37 @@ bi_delwin (progs_t *pr) } } +static void +bi_getwrect (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int window_id = P_INT (pr, 0); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_getwrect, 0, window_id, }; + + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + // XXX should just wait on the mutex + process_commands (res); + process_input (res); + // locking and loop until id is correct + if (RB_DATA_AVAILABLE (res->results) + && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_getwrect) { + int cmd_result[5]; + RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); + // return xpos, ypos, xlen, ylen + (&R_INT (pr))[0] = cmd_result[1]; + (&R_INT (pr))[1] = cmd_result[2]; + (&R_INT (pr))[2] = cmd_result[3]; + (&R_INT (pr))[3] = cmd_result[4]; + } + } +} + static void bi_new_panel (progs_t *pr) { @@ -672,6 +786,58 @@ bi_move_panel (progs_t *pr) } } +static void +bi_panel_window (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int panel_id = P_INT (pr, 0); + + if (get_panel (res, __FUNCTION__, panel_id)) { + int command[] = { qwaq_cmd_panel_window, 0, panel_id, }; + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + // XXX should just wait on the mutex + process_commands (res); + process_input (res); + // locking and loop until id is correct + if (RB_DATA_AVAILABLE (res->results) + && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_panel_window) { + int cmd_result[2]; + RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); + (&R_INT (pr))[0] = cmd_result[0]; + } + } +} + +static void +bi_update_panels (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + int command[] = { qwaq_cmd_update_panels, 0, }; + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } +} + +static void +bi_doupdate (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + int command[] = { qwaq_cmd_doupdate, 0, }; + command[1] = CMD_SIZE(command); + + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } +} + static void bi_mvwprintf (progs_t *pr) { @@ -701,6 +867,33 @@ bi_mvwprintf (progs_t *pr) } } +static void +bi_wprintf (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int window_id = P_INT (pr, 0); + const char *fmt = P_GSTRING (pr, 1); + int count = pr->pr_argc - 2; + pr_type_t **args = pr->pr_params + 2; + + if (get_window (res, __FUNCTION__, window_id)) { + int string_id = acquire_string (res); + dstring_t *print_buffer = res->strings + string_id; + int command[] = { + qwaq_cmd_waddstr, 0, + window_id, string_id + }; + + command[1] = CMD_SIZE(command); + + dstring_clearstr (print_buffer); + PR_Sprintf (pr, print_buffer, "waddstr", fmt, count, args); + if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { + RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); + } + } +} + static void bi_wrefresh (progs_t *pr) { @@ -813,6 +1006,7 @@ static builtin_t builtins[] = { {"initialize", bi_initialize, -1}, {"create_window", bi_newwin, -1}, {"destroy_window", bi_delwin, -1}, + {"getwrect", bi_getwrect, -1}, {"create_panel", bi_new_panel, -1}, {"destroy_panel", bi_del_panel, -1}, {"hide_panel", bi_hide_panel, -1}, @@ -820,7 +1014,11 @@ static builtin_t builtins[] = { {"top_panel", bi_top_panel, -1}, {"bottom_panel", bi_bottom_panel, -1}, {"move_panel", bi_move_panel, -1}, + {"panel_window", bi_panel_window, -1}, + {"update_panels", bi_update_panels, -1}, + {"doupdate", bi_doupdate, -1}, {"mvwprintf", bi_mvwprintf, -1}, + {"wprintf", bi_wprintf, -1}, {"wrefresh", bi_wrefresh, -1}, {"get_event", bi_get_event, -1}, {"max_colors", bi_max_colors, -1}, diff --git a/tools/qwaq/qwaq-curses.h b/tools/qwaq/qwaq-curses.h new file mode 100644 index 000000000..751c521a7 --- /dev/null +++ b/tools/qwaq/qwaq-curses.h @@ -0,0 +1,37 @@ +#ifndef __qwaq_curses_h +#define __qwaq_curses_h + +#include "event.h" + +#ifdef __QFCC__ +typedef struct window_s *window_t; +typedef struct panel_s *panel_t; + +@extern window_t stdscr; + +@extern void initialize (void); +@extern window_t create_window (int xpos, int ypos, int xlen, int ylen); +@extern void destroy_window (window_t win); +@extern void mvwprintf (window_t win, int x, int y, string fmt, ...); +@extern void wprintf (window_t win, string fmt, ...); +@extern void wrefresh (window_t win); + +@extern panel_t create_panel (window_t window); +@extern void destroy_panel (panel_t panel); +@extern void hide_panel (panel_t panel); +@extern void show_panel (panel_t panel); +@extern void top_panel (panel_t panel); +@extern void bottom_panel (panel_t panel); +@extern void move_panel (panel_t panel, int x, int y); +@extern window_t panel_window (panel_t panel); +@extern void update_panels (void); +@extern void doupdate (void); + +@extern int get_event (qwaq_event_t *event); +@extern int max_colors (void); +@extern int max_color_pairs (void); +@extern int init_pair (int pair, int f, int b); +@extern void wbkgd (window_t win, int ch); +#endif + +#endif//__qwaq_curses_h diff --git a/tools/qwaq/qwaq-view.h b/tools/qwaq/qwaq-view.h new file mode 100644 index 000000000..63a9b4db5 --- /dev/null +++ b/tools/qwaq/qwaq-view.h @@ -0,0 +1,44 @@ +#ifndef __qwaq_view_h +#define __qwaq_view_h + +#include +#include + +#include "event.h" +#include "qwaq-curses.h" + +typedef struct { + int xpos; + int ypos; + int xlen; + int ylen; +} Rect; + +typedef struct { + int x; + int y; +} Point; + +@extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); +//XXX will not work if point or rect point to a local variabl +@extern int rectContainsPoint (Rect *rect, Point *point); +@extern Rect getwrect (window_t window); + +@interface View: Object +{ + Rect rect; + Rect absRect; + Array *views; + Point point; // can't be local :( + View *focusedView; + window_t window; + panel_t panel; +} ++viewFromWindow: (window_t) window; +-initWithRect: (Rect) rect; +-handleEvent: (qwaq_event_t *) event; +-addView: (View *) view; +-setBackground: (int) ch; +@end + +#endif//__qwaq_view_h diff --git a/tools/qwaq/qwaq-view.r b/tools/qwaq/qwaq-view.r new file mode 100644 index 000000000..3673b8fee --- /dev/null +++ b/tools/qwaq/qwaq-view.r @@ -0,0 +1,105 @@ +#include "qwaq-curses.h" +#include "qwaq-view.h" + +Rect +makeRect (int xpos, int ypos, int xlen, int ylen) +{ + Rect rect = {xpos, ypos, xlen, ylen}; + return rect; +} + +int +rectContainsPoint (Rect *rect, Point *point) +{ + return ((point.x >= rect.xpos && point.x < rect.xpos + rect.xlen) + && (point.y >= rect.ypos && point.y < rect.ypos + rect.ylen)); +} + +@implementation View + ++viewFromWindow: (window_t) window +{ + return [[[self alloc] initFromWindow: window] autorelease]; +} + +-initWithRect: (Rect) rect +{ + if (!(self = [super init])) { + return nil; + } + self.rect = rect; + self.absRect = rect; + self.window = create_window (rect.xpos, rect.ypos, rect.xlen, rect.ylen); + self.panel = create_panel (self.window); + return self; +} + +-initFromWindow: (window_t) window +{ + if (!(self = [super init])) { + return nil; + } + rect = getwrect (window); + self.window = window; + self.panel = nil; + return self; +} + +-initWithPanel: (panel_t) panel +{ + if (!(self = [super init])) { + return nil; + } + self.panel = panel; + self.window = panel_window (panel); + rect = getwrect (window); + return self; +} + +-addView: (View *) view +{ + [views addObject: view]; + return self; +} + +-setBackground: (int) ch +{ + wbkgd (window, ch); + if (!panel) { + wrefresh (window); + } + return self; +} + +-handleEvent: (qwaq_event_t *) event +{ + switch (event.event_type) { + case qe_mouse: + point.x = event.e.mouse.x; + point.y = event.e.mouse.y; + for (int i = [views count]; i--> 0; ) { + View *v = [views objectAtIndex: i]; + if (rectContainsPoint (&v.absRect, &point)) { + [v handleEvent: event]; + break; + } + } + break; + case qe_key: + case qe_command: + if (focusedView) { + [focusedView handleEvent: event]; + for (int i = [views count]; + event.event_type != qe_none && i--> 0; ) { + View *v = [views objectAtIndex: i]; + [v handleEvent: event]; + } + } + break; + } + return self; +} + +@end + +Rect getwrect (window_t window) = #0; diff --git a/tools/qwaq/qwaq-window.h b/tools/qwaq/qwaq-window.h new file mode 100644 index 000000000..13730ccca --- /dev/null +++ b/tools/qwaq/qwaq-window.h @@ -0,0 +1,11 @@ +#ifndef __qwaq_window_h +#define __qwaq_window_h + +#include "qwaq-view.h" + +@interface Window: View +{ +} +@end + +#endif//__qwaq_window_h diff --git a/tools/qwaq/qwaq-window.r b/tools/qwaq/qwaq-window.r new file mode 100644 index 000000000..48722cdc2 --- /dev/null +++ b/tools/qwaq/qwaq-window.r @@ -0,0 +1,8 @@ +#include "qwaq-window.h" + +@implementation Window ++windowWithRect: (Rect) rect +{ + return [[[self alloc] initWithRect: rect] autorelease]; +} +@end From df2ed4b0863725c48d4c2c07532b0cfa943f7a42 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 00:55:15 +0900 Subject: [PATCH 0462/3664] [qwaq] Move from tools to ruamoko This fixes the dependency issues between qwaq and ruamoko. qwaq is actually older than ruamoko. That little language feature test has come a long way. However, I'm considering moving to non-recursive make, but... --- config.d/ac_config_files.m4 | 3 +-- config.d/build_control.m4 | 9 ++++++--- ruamoko/Makefile.am | 3 ++- {tools => ruamoko}/qwaq/.gdbinit | 0 {tools => ruamoko}/qwaq/Makefile.am | 0 {tools => ruamoko}/qwaq/builtins.c | 0 {tools => ruamoko}/qwaq/color.h | 0 {tools => ruamoko}/qwaq/event.h | 0 {tools => ruamoko}/qwaq/main.c | 0 {tools => ruamoko}/qwaq/progs.src.in | 0 {tools => ruamoko}/qwaq/qwaq-app.h | 0 {tools => ruamoko}/qwaq/qwaq-app.r | 0 {tools => ruamoko}/qwaq/qwaq-bi.c | 0 {tools => ruamoko}/qwaq/qwaq-curses.c | 0 {tools => ruamoko}/qwaq/qwaq-curses.h | 0 {tools => ruamoko}/qwaq/qwaq-view.h | 0 {tools => ruamoko}/qwaq/qwaq-view.r | 0 {tools => ruamoko}/qwaq/qwaq-window.h | 0 {tools => ruamoko}/qwaq/qwaq-window.r | 0 {tools => ruamoko}/qwaq/qwaq.c | 0 {tools => ruamoko}/qwaq/qwaq.h | 0 tools/Makefile.am | 2 +- 22 files changed, 10 insertions(+), 7 deletions(-) rename {tools => ruamoko}/qwaq/.gdbinit (100%) rename {tools => ruamoko}/qwaq/Makefile.am (100%) rename {tools => ruamoko}/qwaq/builtins.c (100%) rename {tools => ruamoko}/qwaq/color.h (100%) rename {tools => ruamoko}/qwaq/event.h (100%) rename {tools => ruamoko}/qwaq/main.c (100%) rename {tools => ruamoko}/qwaq/progs.src.in (100%) rename {tools => ruamoko}/qwaq/qwaq-app.h (100%) rename {tools => ruamoko}/qwaq/qwaq-app.r (100%) rename {tools => ruamoko}/qwaq/qwaq-bi.c (100%) rename {tools => ruamoko}/qwaq/qwaq-curses.c (100%) rename {tools => ruamoko}/qwaq/qwaq-curses.h (100%) rename {tools => ruamoko}/qwaq/qwaq-view.h (100%) rename {tools => ruamoko}/qwaq/qwaq-view.r (100%) rename {tools => ruamoko}/qwaq/qwaq-window.h (100%) rename {tools => ruamoko}/qwaq/qwaq-window.r (100%) rename {tools => ruamoko}/qwaq/qwaq.c (100%) rename {tools => ruamoko}/qwaq/qwaq.h (100%) diff --git a/config.d/ac_config_files.m4 b/config.d/ac_config_files.m4 index 587a515d9..6f49d4bb5 100644 --- a/config.d/ac_config_files.m4 +++ b/config.d/ac_config_files.m4 @@ -74,8 +74,6 @@ tools/qfvis/Makefile tools/qfvis/include/Makefile tools/qfvis/source/Makefile - tools/qwaq/Makefile - tools/qwaq/progs.src tools/wad/Makefile tools/wav/Makefile @@ -87,6 +85,7 @@ ruamoko/gui/Makefile ruamoko/cl_menu/Makefile ruamoko/scheme/Makefile + ruamoko/qwaq/Makefile pkg-config/Makefile pkg-config/qfcc.pc diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index a53bf74a4..98517088e 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -230,7 +230,8 @@ if test "x$ENABLE_tools_qwaq" = xyes; then if test "x$HAVE_PANEL" = xyes -a "x$HAVE_PTHREAD" = xyes; then QWAQ_TARGETS="$QWAQ_TARGETS qwaq-curses\$(EXEEXT)" fi - QF_NEED(tools,[qfcc qwaq]) + QF_NEED(tools,[qfcc]) + QF_NEED(ruamoko,[qwaq]) QF_NEED(libs,[ruamoko gamecode util]) fi if test "x$ENABLE_tools_wad" = xyes; then @@ -244,11 +245,13 @@ fi QF_NEED(top, [libs hw nq qtv qw]) -QF_PROCESS_NEED_DIRS(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis qwaq wad wav]) -QF_PROCESS_NEED_FUNC(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis qwaq wad wav], QF_NEED(top,tools)) +QF_PROCESS_NEED_DIRS(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav]) +QF_PROCESS_NEED_FUNC(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav], QF_NEED(top,tools)) QF_PROCESS_NEED_DIRS(libs,[util gamecode ruamoko gib audio image models video console net qw client]) +QF_PROCESS_NEED_DIRS(ruamoko,[qwaq]) + if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) fi diff --git a/ruamoko/Makefile.am b/ruamoko/Makefile.am index 779fc1439..b899690f8 100644 --- a/ruamoko/Makefile.am +++ b/ruamoko/Makefile.am @@ -1,4 +1,5 @@ -SUBDIRS= include lib game gui cl_menu scheme +SUBDIRS= include lib game gui cl_menu scheme @ruamoko_dirs@ +DIST_SUBDIRS=qwaq doc: Doxyfile doxygen diff --git a/tools/qwaq/.gdbinit b/ruamoko/qwaq/.gdbinit similarity index 100% rename from tools/qwaq/.gdbinit rename to ruamoko/qwaq/.gdbinit diff --git a/tools/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am similarity index 100% rename from tools/qwaq/Makefile.am rename to ruamoko/qwaq/Makefile.am diff --git a/tools/qwaq/builtins.c b/ruamoko/qwaq/builtins.c similarity index 100% rename from tools/qwaq/builtins.c rename to ruamoko/qwaq/builtins.c diff --git a/tools/qwaq/color.h b/ruamoko/qwaq/color.h similarity index 100% rename from tools/qwaq/color.h rename to ruamoko/qwaq/color.h diff --git a/tools/qwaq/event.h b/ruamoko/qwaq/event.h similarity index 100% rename from tools/qwaq/event.h rename to ruamoko/qwaq/event.h diff --git a/tools/qwaq/main.c b/ruamoko/qwaq/main.c similarity index 100% rename from tools/qwaq/main.c rename to ruamoko/qwaq/main.c diff --git a/tools/qwaq/progs.src.in b/ruamoko/qwaq/progs.src.in similarity index 100% rename from tools/qwaq/progs.src.in rename to ruamoko/qwaq/progs.src.in diff --git a/tools/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h similarity index 100% rename from tools/qwaq/qwaq-app.h rename to ruamoko/qwaq/qwaq-app.h diff --git a/tools/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r similarity index 100% rename from tools/qwaq/qwaq-app.r rename to ruamoko/qwaq/qwaq-app.r diff --git a/tools/qwaq/qwaq-bi.c b/ruamoko/qwaq/qwaq-bi.c similarity index 100% rename from tools/qwaq/qwaq-bi.c rename to ruamoko/qwaq/qwaq-bi.c diff --git a/tools/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c similarity index 100% rename from tools/qwaq/qwaq-curses.c rename to ruamoko/qwaq/qwaq-curses.c diff --git a/tools/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h similarity index 100% rename from tools/qwaq/qwaq-curses.h rename to ruamoko/qwaq/qwaq-curses.h diff --git a/tools/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h similarity index 100% rename from tools/qwaq/qwaq-view.h rename to ruamoko/qwaq/qwaq-view.h diff --git a/tools/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r similarity index 100% rename from tools/qwaq/qwaq-view.r rename to ruamoko/qwaq/qwaq-view.r diff --git a/tools/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h similarity index 100% rename from tools/qwaq/qwaq-window.h rename to ruamoko/qwaq/qwaq-window.h diff --git a/tools/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r similarity index 100% rename from tools/qwaq/qwaq-window.r rename to ruamoko/qwaq/qwaq-window.r diff --git a/tools/qwaq/qwaq.c b/ruamoko/qwaq/qwaq.c similarity index 100% rename from tools/qwaq/qwaq.c rename to ruamoko/qwaq/qwaq.c diff --git a/tools/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h similarity index 100% rename from tools/qwaq/qwaq.h rename to ruamoko/qwaq/qwaq.h diff --git a/tools/Makefile.am b/tools/Makefile.am index 008638b4a..768efdccb 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,5 +1,5 @@ SUBDIRS=@tools_dirs@ -DIST_SUBDIRS=bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis qwaq wad wav +DIST_SUBDIRS=bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav EXTRA_DIST= \ io_mesh_qfmdl/export_mdl.py io_mesh_qfmdl/import_mdl.py \ io_mesh_qfmdl/__init__.py io_mesh_qfmdl/mdl.py io_mesh_qfmdl/qfplist.py \ From 1033716b2b7c893a2d0098c299c313d80bdd89c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 13:53:18 +0900 Subject: [PATCH 0463/3664] [qfcc] Fix some curly space --- tools/qfcc/source/class.c | 3 ++- tools/qfcc/source/method.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index caa1967cd..841fa53a0 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -925,7 +925,7 @@ class_find_method (class_type_t *class_type, method_t *method) start_methods = methods; start_class = class; while (class) { - for (m = methods->head; m; m = m->next) + for (m = methods->head; m; m = m->next) { if (method_compare (method, m)) { if (m->type != method->type) error (0, "method type mismatch"); @@ -937,6 +937,7 @@ class_find_method (class_type_t *class_type, method_t *method) method_set_param_names (m, method); return m; } + } if (class->methods == methods) class = class->super_class; else diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 883133b64..726acfd76 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -474,7 +474,7 @@ emit_methods (methodlist_t *methods, const char *name, int instance) if (!methods) return 0; - for (count = 0, m = methods->head; m; m = m->next) + for (count = 0, m = methods->head; m; m = m->next) { if (!m->instance == !instance) { if (!m->def && options.warnings.unimplemented) { warning (0, "Method `%c%s' not implemented", @@ -483,6 +483,7 @@ emit_methods (methodlist_t *methods, const char *name, int instance) if (m->def) count++; } + } if (!count) return 0; methods->count = count; From caa297b756d5ced81908d66b7b23eb600e61c6c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 16:13:18 +0900 Subject: [PATCH 0464/3664] [qfcc] Remove type alias encoding It proved to be too fragile in its current implementation. It broke pointers to incomplete structs and switch enum checking, and getting it to work for other things was overly invasive. I still want the encoding, but need to come up with something more robust.a --- include/QF/pr_type.h | 7 ---- tools/qfcc/include/type.h | 12 ++----- tools/qfcc/source/def.c | 2 +- tools/qfcc/source/dump_globals.c | 4 --- tools/qfcc/source/expr.c | 6 ++-- tools/qfcc/source/function.c | 5 +-- tools/qfcc/source/obj_file.c | 6 ---- tools/qfcc/source/obj_type.c | 18 ---------- tools/qfcc/source/qc-parse.y | 3 -- tools/qfcc/source/type.c | 56 ++------------------------------ tools/qfcc/test/Makefile.am | 1 - 11 files changed, 8 insertions(+), 112 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index 179a4e407..c7fbc4b9c 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -47,14 +47,8 @@ typedef enum { ty_enum, ty_array, ty_class, - ty_alias, } ty_meta_e; -typedef struct qfot_alias_s { - pr_int_t type; ///< type at end of alias chain - pointer_t aux_type; ///< referenced type - string_t name; ///< alias name -} qfot_alias_t; typedef struct qfot_fldptr_s { pr_int_t type; ///< ev_field or ev_pointer @@ -110,7 +104,6 @@ typedef struct qfot_type_s { qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum qfot_array_t array; ///< ty_array string_t class; ///< ty_class - qfot_alias_t alias; ///< ty_alias } t; } qfot_type_t; diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 46d524574..21f4feb2c 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -51,10 +51,6 @@ typedef struct ty_array_s { int size; } ty_array_t; -typedef struct ty_alias_s { - struct type_s *type; -} ty_alias_t; - typedef struct type_s { etype_t type; ///< ev_invalid means structure/array etc const char *name; @@ -68,7 +64,6 @@ typedef struct type_s { ty_array_t array; struct symtab_s *symtab; struct class_s *class; - ty_alias_t alias; } t; struct type_s *next; int freeable; @@ -133,9 +128,8 @@ void chain_type (type_t *type); /** Append a type to the end of a type chain. - The type chain must be made up of only field, pointer, function, array - and alias (typedef) types, as other types do not have auxiliary type - fields. + The type chain must be made up of only field, pointer, function, and + array types, as other types do not have auxiliary type fields. \param type The type chain to which the type will be appended. \param new The type to be appended. May be any type. @@ -149,13 +143,11 @@ type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); type_t *array_type (type_t *aux, int size); type_t *based_array_type (type_t *aux, int base, int top); -type_t *alias_type (type_t *aux, const char *name); void print_type_str (struct dstring_s *str, const type_t *type); void print_type (const type_t *type); const char *encode_params (const type_t *type); void encode_type (struct dstring_s *encoding, const type_t *type); const char *type_get_encoding (const type_t *type); -const type_t *unalias_type (const type_t *type) __attribute__((pure)); int is_void (const type_t *type) __attribute__((pure)); int is_enum (const type_t *type) __attribute__((pure)); int is_integer (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 049740563..82e88c5ae 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -358,7 +358,7 @@ init_elements (struct def_s *def, expr_t *eles) num_elements = i; } else if (is_struct (def->type) || is_vector (def->type) || is_quaternion (def->type)) { - symtab_t *symtab = unalias_type (def->type)->t.symtab; + symtab_t *symtab = def->type->t.symtab; symbol_t *field; for (i = 0, field = symtab->symbols; field; field = field->next) { diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 9343a0ac7..657f016e8 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -547,10 +547,6 @@ dump_qfo_types (qfo_t *qfo, int base_address) printf (" %-5x %d %d\n", type->t.array.type, type->t.array.base, type->t.array.size); break; - case ty_alias: - printf (" %s %d %-5x\n", QFO_GETSTR (qfo, type->t.alias.name), - type->t.alias.type, type->t.alias.aux_type); - break; case ty_class: printf (" %-5x\n", type->t.class); break; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 7d5baddb9..ad91a8d81 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1140,7 +1140,7 @@ append_expr (expr_t *block, expr_t *e) static symbol_t * get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2) { - symtab_t *strct = unalias_type (t1)->t.symtab; + symtab_t *strct = t1->t.symtab; symbol_t *sym = e2->e.symbol;//FIXME need to check symbol_t *field; @@ -1165,7 +1165,6 @@ field_expr (expr_t *e1, expr_t *e2) t1 = get_type (e1); if (e1->type == ex_error) return e1; - t1 = unalias_type (t1); if (t1->type == ev_entity) { symbol_t *field = 0; @@ -1639,7 +1638,6 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) expr_t *call; expr_t *err = 0; - ftype = unalias_type (ftype); for (e = params; e; e = e->next) { if (e->type == ex_error) @@ -2375,7 +2373,7 @@ cast_expr (type_t *dstType, expr_t *e) srcType = get_type (e); - if (unalias_type (dstType) == unalias_type (srcType)) + if (dstType == srcType) return e; if ((dstType == type_default && is_enum (srcType)) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index eb376e0ea..538bb8f65 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -177,10 +177,7 @@ parse_params (type_t *type, param_t *parms) internal_error (0, 0); new->t.func.num_params = -(new->t.func.num_params + 1); } else if (p->type) { - // FIXME this cast should not be necessary, but making the - // type system const-correct would probably take a rewrite - type_t *t = (type_t *) unalias_type (p->type); - new->t.func.param_types[new->t.func.num_params] = t; + new->t.func.param_types[new->t.func.num_params] = p->type; new->t.func.num_params++; } } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index d1c5296c4..6ceb1a74e 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -648,10 +648,8 @@ get_def_type (qfo_t *qfo, pointer_t type) type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { case ty_basic: - case ty_alias: // field, pointer and function types store their basic type in // the same location. - // alias types store the basic type at the end of the alias chain return type_def->t.type; case ty_struct: case ty_union: @@ -676,8 +674,6 @@ get_type_size (qfo_t *qfo, pointer_t type) return 1; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { - case ty_alias: - return get_type_size (qfo, type_def->t.alias.aux_type); case ty_basic: // field, pointer and function types store their basic type in // the same location. @@ -726,8 +722,6 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) return 0; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { - case ty_alias: - return get_type_alignment_log (qfo, type_def->t.alias.aux_type); case ty_basic: // field, pointer and function types store their basic type in // the same location. diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index ff2409986..c21e7e576 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -253,23 +253,6 @@ qfo_encode_class (type_t *type) return def; } -static def_t * -qfo_encode_alias (type_t *type) -{ - qfot_type_t *enc; - def_t *def; - def_t *alias_type_def; - - alias_type_def = qfo_encode_type (type->t.alias.type); - - def = qfo_new_encoding (type, sizeof (enc->t.alias)); - enc = D_POINTER (qfot_type_t, def); - enc->t.alias.type = type->type; - ENC_DEF (enc->t.alias.aux_type, alias_type_def); - ENC_STR (enc->t.alias.name, type->name); - return def; -} - def_t * qfo_encode_type (type_t *type) { @@ -282,7 +265,6 @@ qfo_encode_type (type_t *type) qfo_encode_struct, // ty_enum qfo_encode_array, // ty_array qfo_encode_class, // ty_class - qfo_encode_alias, // ty_alias }; if (type->type_def && type->type_def->external) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 07c12692e..1bcd240c1 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -406,7 +406,6 @@ external_decl $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; - $1->type = alias_type ($1->type, $1->name); symtab_addsymbol (current_symtab, $1); } else { initialize_def ($1, 0, current_symtab->space, spec.storage); @@ -422,7 +421,6 @@ external_decl if (spec.is_typedef) { error (0, "typedef %s is initialized", $1->name); $1->sy_type = sy_type; - $1->type = alias_type ($1->type, $1->name); symtab_addsymbol (current_symtab, $1); } else { initialize_def ($1, $2, current_symtab->space, spec.storage); @@ -436,7 +434,6 @@ external_decl $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; - $1->type = alias_type ($1->type, $1->name); symtab_addsymbol (current_symtab, $1); } else { $1 = function_symbol ($1, spec.is_overload, 1); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index a583a943c..4fd77a9fd 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -297,8 +297,6 @@ types_same (type_t *a, type_t *b) if (a->t.class != b->t.class) return 0; return compare_protocols (a->protos, b->protos); - case ty_alias: - return !strcmp (a->name, b->name); } internal_error (0, "we be broke"); } @@ -348,9 +346,6 @@ find_type (type_t *type) break; case ty_class: break; - case ty_alias: - type->t.alias.type = find_type (type->t.alias.type); - break; } } @@ -450,25 +445,6 @@ based_array_type (type_t *aux, int base, int top) return new; } -type_t * -alias_type (type_t *aux, const char *name) -{ - type_t _new; - type_t *new = &_new; - - if (!aux || !name) { - internal_error (0, "alias to null type or with no name"); - } - memset (&_new, 0, sizeof (_new)); - new->name = save_string (name); - new->meta = ty_alias; - new->type = aux->type; - new->alignment = aux->alignment; - new->t.alias.type = aux; - new = find_type (new); - return new; -} - void print_type_str (dstring_t *str, const type_t *type) { @@ -500,11 +476,6 @@ print_type_str (dstring_t *str, const type_t *type) dasprintf (str, "[%d]", type->t.array.size); } return; - case ty_alias: - dasprintf (str, "({%s=", type->name); - print_type_str (str, type->t.alias.type); - dstring_appendstr (str, "})"); - return; case ty_basic: switch (type->type) { case ev_field: @@ -658,11 +629,6 @@ encode_type (dstring_t *encoding, const type_t *type) encode_type (encoding, type->t.array.type); dasprintf (encoding, "]"); return; - case ty_alias: - dasprintf (encoding, "{%s>", type->name); - encode_type (encoding, type->t.alias.type); - dasprintf (encoding, "}"); - return; case ty_basic: switch (type->type) { case ev_void: @@ -730,15 +696,6 @@ encode_type (dstring_t *encoding, const type_t *type) internal_error (0, "bad type meta:type %d:%d", type->meta, type->type); } -const type_t * -unalias_type (const type_t *type) -{ - while (type->meta == ty_alias) { - type = type->t.alias.type; - } - return type; -} - int is_void (const type_t *type) { @@ -748,7 +705,6 @@ is_void (const type_t *type) int is_enum (const type_t *type) { - type = unalias_type (type); if (type->type == ev_invalid && type->meta == ty_enum) return 1; return 0; @@ -833,7 +789,6 @@ is_math (const type_t *type) int is_struct (const type_t *type) { - type = unalias_type (type); if (type->type == ev_invalid && (type->meta == ty_struct || type->meta == ty_union)) return 1; @@ -859,7 +814,6 @@ is_field (const type_t *type) int is_array (const type_t *type) { - type = unalias_type (type); if (type->type == ev_invalid && type->meta == ty_array) return 1; return 0; @@ -884,8 +838,6 @@ is_string (const type_t *type) int type_compatible (const type_t *dst, const type_t *src) { - dst = unalias_type (dst); - src = unalias_type (src); // same type if (dst == src) { return 1; @@ -905,8 +857,6 @@ type_compatible (const type_t *dst, const type_t *src) int type_assignable (const type_t *dst, const type_t *src) { - dst = unalias_type (dst); - src = unalias_type (src); int ret; // same type @@ -932,8 +882,8 @@ type_assignable (const type_t *dst, const type_t *src) if (ret >= 0) return ret; - dst = unalias_type (dst->t.fldptr.type); - src = unalias_type (src->t.fldptr.type); + dst = dst->t.fldptr.type; + src = src->t.fldptr.type; if (dst == src) { return 1; } @@ -972,8 +922,6 @@ type_size (const type_t *type) size += type_size (class->super_class->type); return size; } - case ty_alias: - return type_size (type->t.alias.type); } return 0; } diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index c53dd7cbf..937686a6e 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -55,7 +55,6 @@ test_progs_dat=\ structstruct.dat \ swap.dat \ triangle.dat \ - typedef.dat \ vecexpr.dat \ vecinit.dat \ voidfor.dat \ From 4d076da4b6b2b78f7f1b0315331eae0f3a2f7cc8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 16:15:33 +0900 Subject: [PATCH 0465/3664] [qwaq] Fix warning hidden by type alias bug --- ruamoko/qwaq/qwaq-view.r | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 3673b8fee..e71006846 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -96,6 +96,8 @@ rectContainsPoint (Rect *rect, Point *point) } } break; + case qe_none: + break; } return self; } From 4e4b553cc3c2fbc958007758f0c585052e445029 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 16:20:23 +0900 Subject: [PATCH 0466/3664] [gamecode] Take care of missed type alias stuff --- include/QF/progs.h | 1 - libs/gamecode/pr_debug.c | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 5abd0d1c6..18ea33b04 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1575,7 +1575,6 @@ typedef struct type_view_s { type_view_func enum_view; type_view_func array_view; type_view_func class_view; - type_view_func alias_view; } type_view_t; void PR_Debug_Init (progs_t *pr); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index e7bf90a92..28bb97e54 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -132,8 +132,6 @@ static void pr_debug_array_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_class_view (qfot_type_t *type, pr_type_t *value, void *_data); -static void pr_debug_alias_view (qfot_type_t *type, pr_type_t *value, - void *_data); static type_view_t raw_type_view = { pr_debug_void_view, @@ -154,7 +152,6 @@ static type_view_t raw_type_view = { pr_debug_enum_view, pr_debug_array_view, pr_debug_class_view, - pr_debug_alias_view, }; static const char * @@ -226,9 +223,6 @@ pr_debug_type_size (const progs_t *pr, const qfot_type_t *type) return type->t.array.size * size; case ty_class: return 1; //FIXME or should it return sizeof class struct? - case ty_alias: - aux_type = &G_STRUCT (pr, qfot_type_t, type->t.alias.aux_type); - return pr_debug_type_size (pr, aux_type); } return 0; } @@ -860,9 +854,6 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) case ty_class: raw_type_view.class_view (type, value, data); break; - case ty_alias: - raw_type_view.alias_view (type, value, data); - break; } return data->dstr->str; } @@ -1171,16 +1162,6 @@ pr_debug_class_view (qfot_type_t *type, pr_type_t *value, void *_data) dstring_appendstr (dstr, ""); } -static void -pr_debug_alias_view (qfot_type_t *type, pr_type_t *value, void *_data) -{ - __auto_type data = (pr_debug_data_t *) _data; - progs_t *pr = data->pr; - - type = &G_STRUCT (pr, qfot_type_t, type->t.alias.aux_type); - value_string (data, type, value); -} - VISIBLE void PR_Debug_Watch (progs_t *pr, const char *expr) { From 277c64a4607b2f5b32b01497f4b2b19a9754e231 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 17:28:33 +0900 Subject: [PATCH 0467/3664] [qfcc] Correct a typo --- tools/qfcc/source/idstuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/idstuff.c b/tools/qfcc/source/idstuff.c index 629862003..2f195b7e2 100644 --- a/tools/qfcc/source/idstuff.c +++ b/tools/qfcc/source/idstuff.c @@ -295,7 +295,7 @@ WriteProgdefs (dprograms_t *progs, const char *filename) crc = CRC_Block ((byte *) dstr->str, dstr->size - 1); dasprintf (dstr, "#define PROGHEADER_CRC %u\n", crc); - dstring_insertstr (dstr, 0, "/* Actually, generated by qfcc, be one must " + dstring_insertstr (dstr, 0, "/* Actually, generated by qfcc, but one must " "maintain formalities */"); if (filename) { From b5443216097966c06e39fb5319a4ac5bc6cc7415 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 17:43:28 +0900 Subject: [PATCH 0468/3664] [qfcc] Catch deferences to incomplete types Reporting an error is so much more helpful than segmentation fault. --- tools/qfcc/source/class.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 841fa53a0..682bf59f5 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -889,6 +889,10 @@ class_find_ivar (class_t *class, int vis, const char *name) { symbol_t *ivar; + if (!class->ivars) { + error (0, "accessing incomplete type %s", class->name); + return 0; + } ivar = symtab_lookup (class->ivars, name); if (ivar) { if (ivar->visibility > (vis_t) vis) From 80d9401eeeb58a620b4ce8344ab2ad24b9803cdb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 17:44:13 +0900 Subject: [PATCH 0469/3664] [qfcc] Report errors for objects in function decls The number of time's I've forgotten the * in a declaration in objective code (probably thanks to C#'s lack of them). --- tools/qfcc/source/function.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 538bb8f65..3b844b5a3 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -46,6 +46,7 @@ #include "qfcc.h" +#include "class.h" #include "codespace.h" #include "debug.h" #include "def.h" @@ -157,6 +158,11 @@ parse_params (type_t *type, param_t *parms) type_t *new; int count = 0; + if (type && obj_is_class (type)) { + error (0, "cannot return an object (forgot *?)"); + type = &type_id; + } + new = new_type (); new->type = ev_func; new->alignment = 1; @@ -177,6 +183,10 @@ parse_params (type_t *type, param_t *parms) internal_error (0, 0); new->t.func.num_params = -(new->t.func.num_params + 1); } else if (p->type) { + if (obj_is_class (p->type)) { + error (0, "cannot use an object as a parameter (forgot *?)"); + p->type = &type_id; + } new->t.func.param_types[new->t.func.num_params] = p->type; new->t.func.num_params++; } From 92cb3a5285fb75538255c18e2e2dc692e4ecf74b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 18:25:02 +0900 Subject: [PATCH 0470/3664] [qwaq] Flatten the hierarchy and do some cleanup --- ruamoko/qwaq/Makefile.am | 2 +- ruamoko/qwaq/qwaq-app.h | 6 ++-- ruamoko/qwaq/qwaq-app.r | 18 +++++----- ruamoko/qwaq/qwaq-rect.h | 21 +++++++++++ ruamoko/qwaq/qwaq-screen.h | 22 ++++++++++++ ruamoko/qwaq/qwaq-screen.r | 32 +++++++++++++++++ ruamoko/qwaq/qwaq-view.h | 30 ++-------------- ruamoko/qwaq/qwaq-view.r | 71 +------------------------------------- ruamoko/qwaq/qwaq-window.h | 18 ++++++++-- ruamoko/qwaq/qwaq-window.r | 63 +++++++++++++++++++++++++++++++++ 10 files changed, 172 insertions(+), 111 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-rect.h create mode 100644 ruamoko/qwaq/qwaq-screen.h create mode 100644 ruamoko/qwaq/qwaq-screen.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index f38fc77e5..38584d949 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -57,7 +57,7 @@ qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) r_depfiles_remade= -qwaq_app_dat_SOURCES=qwaq-app.r qwaq-view.r qwaq-window.r +qwaq_app_dat_SOURCES=qwaq-app.r qwaq-screen.r qwaq-window.r qwaq-view.r qwaq_app_obj=$(qwaq_app_dat_SOURCES:.r=.o) qwaq_app_dep=$(addprefix ./$(DEPDIR)/,$(qwaq_app_obj:.o=.Qo)) qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index c02beac67..b603fb4b1 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -1,15 +1,15 @@ #ifndef __qwaq_app_h #define __qwaq_app_h -#include "qwaq-view.h" - #include "event.h" +@class Screen; + @interface QwaqApplication: Object { qwaq_event_t event; qwaq_command endState; - View *view; + Screen *screen; } -run; -handleEvent: (qwaq_event_t *) event; diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 80ed06c41..d9051f4d9 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -4,6 +4,8 @@ #include "qwaq-app.h" #include "qwaq-curses.h" #include "qwaq-window.h" +#include "qwaq-screen.h" +#include "qwaq-view.h" static AutoreleasePool *autorelease_pool; static void @@ -33,18 +35,18 @@ arp_end (void) initialize (); init_pair (1, COLOR_WHITE, COLOR_BLUE); init_pair (2, COLOR_WHITE, COLOR_BLACK); - view = [[View viewFromWindow:stdscr] retain]; - [view setBackground: COLOR_PAIR (1)]; - Rect r = view.rect; - wprintf (view.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + screen = [[Screen screen] retain]; + [screen setBackground: COLOR_PAIR (1)]; + Rect r = screen.rect; + wprintf (screen.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); r.xpos = r.xlen / 4; r.ypos = r.ylen / 4; r.xlen /= 2; r.ylen /= 2; - wprintf (view.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); - wrefresh(view.window); + wprintf (screen.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + wrefresh(screen.window); Window *w; - [view addView: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; + [screen add: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; wprintf (w.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); return self; } @@ -68,7 +70,7 @@ arp_end (void) -handleEvent: (qwaq_event_t *) event { - [view handleEvent: event]; + [screen handleEvent: event]; if (event.event_type == qe_key && event.e.key == '\x18') { event.event_type = qe_command; event.e.message.command = qc_exit; diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h new file mode 100644 index 000000000..0c26b5817 --- /dev/null +++ b/ruamoko/qwaq/qwaq-rect.h @@ -0,0 +1,21 @@ +#ifndef __qwaq_rect_h +#define __qwaq_rect_h + +typedef struct { + int xpos; + int ypos; + int xlen; + int ylen; +} Rect; + +typedef struct { + int x; + int y; +} Point; + +@extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); +//XXX will not work if point or rect point to a local variabl +@extern int rectContainsPoint (Rect *rect, Point *point); +@extern Rect getwrect (struct window_s *window); + +#endif//__qwaq_rect_h diff --git a/ruamoko/qwaq/qwaq-screen.h b/ruamoko/qwaq/qwaq-screen.h new file mode 100644 index 000000000..365c54506 --- /dev/null +++ b/ruamoko/qwaq/qwaq-screen.h @@ -0,0 +1,22 @@ +#ifndef __qwaq_screen_h +#define __qwaq_screen_h + +#include + +#include "qwaq-rect.h" +@class View; +@class Array; + +@interface Screen: Object +{ + Rect rect; + Array *views; + View *focusedView; + struct window_s *window; +} ++(Screen *) screen; +-add: obj; +-setBackground: (int) ch; +@end + +#endif//__qwaq_screen_h diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r new file mode 100644 index 000000000..cd4e25365 --- /dev/null +++ b/ruamoko/qwaq/qwaq-screen.r @@ -0,0 +1,32 @@ +#include "qwaq-curses.h" +#include "qwaq-screen.h" + +@implementation Screen ++(Screen *) screen +{ + return [[[self alloc] init] autorelease]; +} + +-init +{ + if (!(self = [super init])) { + return nil; + } + window = stdscr; + rect = getwrect (window); + return self; +} + +-add: obj +{ + return self; +} + +-setBackground: (int) ch +{ + wbkgd (window, ch); + wrefresh (window); + return self; +} + +@end diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 63a9b4db5..811998ed0 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -4,41 +4,17 @@ #include #include -#include "event.h" -#include "qwaq-curses.h" - -typedef struct { - int xpos; - int ypos; - int xlen; - int ylen; -} Rect; - -typedef struct { - int x; - int y; -} Point; - -@extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); -//XXX will not work if point or rect point to a local variabl -@extern int rectContainsPoint (Rect *rect, Point *point); -@extern Rect getwrect (window_t window); +#include "qwaq-rect.h" @interface View: Object { Rect rect; Rect absRect; - Array *views; Point point; // can't be local :( - View *focusedView; - window_t window; - panel_t panel; + struct window_s *window; } -+viewFromWindow: (window_t) window; -initWithRect: (Rect) rect; --handleEvent: (qwaq_event_t *) event; --addView: (View *) view; --setBackground: (int) ch; +-handleEvent: (struct qwaq_event_s *) event; @end #endif//__qwaq_view_h diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index e71006846..c03d880f4 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -17,11 +17,6 @@ rectContainsPoint (Rect *rect, Point *point) @implementation View -+viewFromWindow: (window_t) window -{ - return [[[self alloc] initFromWindow: window] autorelease]; -} - -initWithRect: (Rect) rect { if (!(self = [super init])) { @@ -29,76 +24,12 @@ rectContainsPoint (Rect *rect, Point *point) } self.rect = rect; self.absRect = rect; - self.window = create_window (rect.xpos, rect.ypos, rect.xlen, rect.ylen); - self.panel = create_panel (self.window); - return self; -} - --initFromWindow: (window_t) window -{ - if (!(self = [super init])) { - return nil; - } - rect = getwrect (window); - self.window = window; - self.panel = nil; - return self; -} - --initWithPanel: (panel_t) panel -{ - if (!(self = [super init])) { - return nil; - } - self.panel = panel; - self.window = panel_window (panel); - rect = getwrect (window); - return self; -} - --addView: (View *) view -{ - [views addObject: view]; - return self; -} - --setBackground: (int) ch -{ - wbkgd (window, ch); - if (!panel) { - wrefresh (window); - } + self.window = nil; return self; } -handleEvent: (qwaq_event_t *) event { - switch (event.event_type) { - case qe_mouse: - point.x = event.e.mouse.x; - point.y = event.e.mouse.y; - for (int i = [views count]; i--> 0; ) { - View *v = [views objectAtIndex: i]; - if (rectContainsPoint (&v.absRect, &point)) { - [v handleEvent: event]; - break; - } - } - break; - case qe_key: - case qe_command: - if (focusedView) { - [focusedView handleEvent: event]; - for (int i = [views count]; - event.event_type != qe_none && i--> 0; ) { - View *v = [views objectAtIndex: i]; - [v handleEvent: event]; - } - } - break; - case qe_none: - break; - } return self; } diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 13730ccca..5d777c828 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -1,11 +1,25 @@ #ifndef __qwaq_window_h #define __qwaq_window_h -#include "qwaq-view.h" +#include "Object.h" -@interface Window: View +@class View; +@class Array; + +#include "qwaq-rect.h" + +@interface Window: Object { + Rect rect; + Point point; // FIXME can't be local :( + Array *views; + View *focusedView; + struct window_s *window; + struct panel_s *panel; } ++windowWithRect: (Rect) rect; +-addView: (View *) view; +-setBackground: (int) ch; @end #endif//__qwaq_window_h diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 48722cdc2..70fe2c476 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -1,8 +1,71 @@ +#include + +#include "event.h" +#include "qwaq-curses.h" #include "qwaq-window.h" +#include "qwaq-view.h" @implementation Window + +windowWithRect: (Rect) rect { return [[[self alloc] initWithRect: rect] autorelease]; } + +-initWithRect: (Rect) rect +{ + if (!(self = [super init])) { + return nil; + } + self.rect = rect; + window = create_window (rect.xpos, rect.ypos, rect.xlen, rect.ylen); + panel = create_panel (window); + return self; +} + +-handleEvent: (qwaq_event_t *) event +{ + switch (event.event_type) { + case qe_mouse: + point.x = event.e.mouse.x; + point.y = event.e.mouse.y; + for (int i = [views count]; i--> 0; ) { + View *v = [views objectAtIndex: i]; + if (rectContainsPoint (&v.absRect, &point)) { + [v handleEvent: event]; + break; + } + } + break; + case qe_key: + case qe_command: + if (focusedView) { + [focusedView handleEvent: event]; + for (int i = [views count]; + event.event_type != qe_none && i--> 0; ) { + View *v = [views objectAtIndex: i]; + [v handleEvent: event]; + } + } + break; + case qe_none: + break; + } + return self; +} + +-addView: (View *) view +{ + [views addObject: view]; + view.absRect.xpos = view.rect.xpos + rect.xpos; + view.absRect.ypos = view.rect.ypos + rect.ypos; + view.window = window; + return self; +} + +-setBackground: (int) ch +{ + wbkgd (window, ch); + return self; +} @end From 254bf29bd4f299d6afe5138e803de768b2a47413 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Mar 2020 19:37:40 +0900 Subject: [PATCH 0471/3664] [qfcc] Handle protocol forward declarations --- tools/qfcc/source/class.c | 8 +++++-- tools/qfcc/source/qc-parse.y | 41 +++++++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 682bf59f5..07068ecb9 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -515,7 +515,11 @@ class_add_protocols (class_t *class, protocollist_t *protocols) for (i = 0; i < protocols->count; i++) { p = protocols->list[i]; - copy_methods (methods, p->methods); + if (p->methods) { + copy_methods (methods, p->methods); + } else { + warning (0, "definition of protocol `%s' not found", p->name); + } if (p->protocols) class_add_protocols (class, p->protocols); } @@ -1356,7 +1360,7 @@ get_protocol (const char *name, int create) p = calloc (sizeof (protocol_t), 1); p->name = name; - p->methods = new_methodlist (); + p->methods = 0; p->class_type.type = ct_protocol; p->class_type.c.protocol = p; if (name) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 1bcd240c1..a7b353082 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -192,7 +192,7 @@ int yylex (void); %type overloaded_identifier %type identifier_list -%type selector reserved_word +%type protocol_name_list selector reserved_word %type optional_param_list unaryselector keyworddecl %type keywordselector %type methodproto methoddecl @@ -1443,6 +1443,7 @@ identifier obj_def : classdef { } | classdecl + | protocoldecl | protocoldef | { if (!current_class) PARSE_ERROR; } methoddef | END @@ -1570,17 +1571,18 @@ category_reference } ; - protocol_name : identifier { $$ = get_protocol ($1->name, 0); - if ($$) { - error (0, "redefinition of %s", $1->name); + if ($$ && $$->methods) { + error (0, "redefinition of protocol %s", $1->name); $$ = get_protocol (0, 1); - } else { + } + if (!$$) { $$ = get_protocol ($1->name, 1); } + $$->methods = new_methodlist (); current_class = &$$->class_type; } ; @@ -1673,18 +1675,33 @@ classdef | REFERENCE category_reference ';' { } ; +protocoldecl + : protocol + protocol_name_list ';' + { + while ($2) { + get_protocol ($2->name, 1); + $2 = $2->next; + } + } + ; + protocoldef - : PROTOCOL { $$ = current_class; } + : protocol protocol_name - protocolrefs { protocol_add_protocols ($3, $4); $$ = 0; } - methodprotolist { protocol_add_methods ($3, $6); } + protocolrefs { protocol_add_protocols ($2, $3); $$ = 0; } + methodprotolist { protocol_add_methods ($2, $5); } END { - current_class = $2; - (void) ($5); + current_class = $1; + (void) ($4); } ; +protocol + : PROTOCOL { $$ = current_class; } + ; + protocolrefs : /* emtpy */ { $$ = 0; } | LT { $$ = new_protocol_list (); } @@ -1870,6 +1887,10 @@ keywordselector | keywordselector keyworddecl { $2->next = $1; $$ = $2; } ; +protocol_name_list + : identifier + | protocol_name_list ',' identifier { $3->next = $1; $$ = $3; } + selector : NAME { $$ = $1; } | CLASS_NAME { $$ = $1; } From 544d7de1ec5e2b1c2b229a43a0feff34dd9d198a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 10:42:26 +0900 Subject: [PATCH 0472/3664] [qfcc] Implement @protocol(foo) Unlike gcc, qfcc requires foo to be defined, not just declared (I suspect this is a bug in gcc, or even the ObjC spec), because allowing forward declarations causes an empty (no methods) protocol to be emitted, and then when the protocol is actually defined, one with methods, resulting in two different versions of the same protocol, which comments in the gnu objc runtime specifically state is a problem but is not checked because it "never happens in practice" (found while investigating gcc's behavior with @protocol and just what some of the comments about static instance lists meant). --- tools/qfcc/include/class.h | 1 + tools/qfcc/source/class.c | 6 ++++-- tools/qfcc/source/expr.c | 11 +++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index 323912591..a4f65538b 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -74,6 +74,7 @@ typedef struct protocol_s { const char *name; struct methodlist_s *methods; struct protocollist_s *protocols; + struct def_s *def; class_type_t class_type; } protocol_t; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 07068ecb9..64ebf692f 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1387,8 +1387,10 @@ protocol_add_protocols (protocol_t *protocol, protocollist_t *protocols) def_t * protocol_def (protocol_t *protocol) { - return make_symbol (protocol->name, &type_obj_protocol, - pr.far_data, sc_static)->s.def; + if (!protocol->def) { + protocol->def = emit_protocol (protocol); + } + return protocol->def; } protocollist_t * diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index ad91a8d81..967484f95 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2470,9 +2470,16 @@ selector_expr (keywordarg_t *selector) } expr_t * -protocol_expr (const char *protocol) +protocol_expr (const char *protocol_name) { - return error (0, "not implemented"); + protocol_t *protocol = get_protocol (protocol_name, 0); + + if (!protocol) { + return error (0, "cannot find protocol declaration for `%s'", + protocol_name); + } + class_t *proto_class = get_class (new_symbol ("Protocol"), 1); + return new_pointer_expr (0, proto_class->type, protocol_def (protocol)); } expr_t * From b6b7f9675f77fcab401be1f32d2fc1c35109f26d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 10:48:51 +0900 Subject: [PATCH 0473/3664] [qfcc] Emit static instance lists For now, only protocols are in the list (gcc adds only static string objects and qfcc doesn't do those yet, so not so far behind). qfprogs dumps them. --- tools/qfcc/include/class.h | 5 + tools/qfcc/source/class.c | 164 +++++++++++++++++++++++++++++-- tools/qfcc/source/dump_modules.c | 54 +++++++++- tools/qfcc/source/dump_strings.c | 4 +- 4 files changed, 216 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index a4f65538b..726a272be 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -83,6 +83,11 @@ typedef struct protocollist_s { protocol_t **list; } protocollist_t; +typedef struct static_instance_s { + const char *class; + struct def_s *instance; +} static_instance_t; + extern struct type_s type_id; extern struct type_s type_obj_object; extern struct type_s type_obj_class; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 64ebf692f..0b981d065 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -66,6 +66,8 @@ static hashtab_t *class_hash; static hashtab_t *category_hash; static hashtab_t *protocol_hash; +static hashtab_t *static_instances; +static hashtab_t *static_instance_classes; // these will be built up further type_t type_obj_selector = { ev_invalid, 0, 0, ty_struct}; @@ -178,6 +180,141 @@ static struct_def_t object_struct[] = { {0, 0} }; +static const char * +static_instance_get_key (const void *instance, void *unused) +{ + return ((static_instance_t *) instance)->class; +} + +static void +add_static_instance (const char *class, def_t *instance_def) +{ + static_instance_t *instance = malloc (sizeof (*instance)); + + if (!static_instances) { + static_instances = Hash_NewTable (1021, static_instance_get_key, 0, 0); + static_instance_classes = Hash_NewTable (1021, static_instance_get_key, + 0, 0); + } + + instance->class = save_string (class); + instance->instance = instance_def; + Hash_Add (static_instances, instance); + + // uniqued set of class names for all static instances + if (!Hash_Find (static_instance_classes, class)) { + Hash_Add (static_instance_classes, instance); + } +} +typedef struct { + const char *class_name; + int num_instances; + static_instance_t **instances; +} obj_static_instances_data_t; + +static void +emit_instance_classname (def_t *def, void *data, int index) +{ + obj_static_instances_data_t *da = (obj_static_instances_data_t *)data; + + if (def->type != &type_string) + internal_error (0, "%s: expected string def", __FUNCTION__); + EMIT_STRING (def->space, D_STRING (def), da->class_name); +} + +static void +emit_instance_defs (def_t *def, void *data, int index) +{ + obj_static_instances_data_t *da = (obj_static_instances_data_t *)data; + + if (!is_array (def->type) || def->type->t.array.type->type != ev_pointer) + internal_error (0, "%s: expected array of pointers def", __FUNCTION__); + if (index < 0 || index >= da->num_instances + 1) + internal_error (0, "%s: out of bounds index: %d %d", + __FUNCTION__, index, da->num_instances + 1); + D_INT (def) = 0; + if (index < da->num_instances) { + EMIT_DEF (def->space, D_INT (def), da->instances[index]->instance); + } +} + +static def_t * +emit_static_instances (const char *classname) +{ + static struct_def_t instances_struct[] = { + {"class_name", &type_string, emit_instance_classname}, + {"instances", 0, emit_instance_defs}, + {0, 0} + }; + obj_static_instances_data_t data = {}; + def_t *instances_def; + + data.class_name = classname; + data.instances = (static_instance_t **) Hash_FindList (static_instances, + classname); + for (static_instance_t **inst = data.instances; *inst; inst++) { + data.num_instances++; + } + instances_struct[1].type = array_type (&type_pointer, + data.num_instances + 1); + instances_def = emit_structure (va ("_OBJ_STATIC_INSTANCES_%s", classname), + 's', instances_struct, 0, &data, + sc_static); + free (data.instances); + return instances_def; +} + +static def_t * +emit_static_instances_list (void) +{ + static_instance_t **classes; + int num_classes = 0; + def_t **instance_lists; + type_t *instance_lists_type; + symbol_t *instance_lists_sym; + def_t *instance_lists_def; + pointer_t *list; + defspace_t *space; + + if (!static_instance_classes || !static_instances) { + return 0; + } + + classes = (static_instance_t **) Hash_GetList (static_instance_classes); + for (static_instance_t **c = classes; *c; c++) { + num_classes++; + } + if (!num_classes) { + free (classes); + return 0; + } + instance_lists = alloca (num_classes * sizeof (*instance_lists)); + for (int i = 0; i < num_classes; i++) { + instance_lists[i] = emit_static_instances (classes[i]->class); + } + free (classes); + + // +1 for terminating null + instance_lists_type = array_type (&type_pointer, num_classes + 1); + instance_lists_sym = make_symbol ("_OBJ_STATIC_INSTANCES", + instance_lists_type, + pr.far_data, sc_static); + if (!instance_lists_sym->table) { + symtab_addsymbol (pr.symtab, instance_lists_sym); + } + instance_lists_def = instance_lists_sym->s.def; + instance_lists_def->initialized = instance_lists_def->constant = 1; + instance_lists_def->nosave = 1; + + list = D_POINTER (pointer_t, instance_lists_def); + space = instance_lists_def->space; + for (int i = 0; i < num_classes; i++, list++) { + EMIT_DEF (space, *list, instance_lists[i]); + } + *list = 0; + return instance_lists_def; +} + int obj_is_id (const type_t *type) { @@ -1185,6 +1322,7 @@ typedef struct { int cls_def_cnt; category_t **categories; int cat_def_cnt; + def_t *instances_list; } obj_symtab_data_t; static void @@ -1238,10 +1376,10 @@ emit_symtab_defs (def_t *def, void *data, int index) if (!is_array (def->type) || def->type->t.array.type->type != ev_pointer) internal_error (0, "%s: expected array of pointers def", __FUNCTION__); - if (index < 0 || index >= da->cls_def_cnt + da->cat_def_cnt) + if (index < 0 || index >= da->cls_def_cnt + da->cat_def_cnt + 1) internal_error (0, "%s: out of bounds index: %d %d", __FUNCTION__, index, - da->cls_def_cnt + da->cat_def_cnt); + da->cls_def_cnt + da->cat_def_cnt + 1); if (index < da->cls_def_cnt) { class_t **cl; @@ -1250,7 +1388,7 @@ emit_symtab_defs (def_t *def, void *data, int index) if (!index--) break; EMIT_DEF (def->space, D_INT (def), (*cl)->def); - } else { + } else if (index < da->cls_def_cnt + da->cat_def_cnt) { category_t **ca; index -= da->cls_def_cnt; for (ca = da->categories; *ca; ca++) @@ -1258,6 +1396,11 @@ emit_symtab_defs (def_t *def, void *data, int index) if (!index--) break; EMIT_DEF (def->space, D_INT (def), (*ca)->def); + } else { + D_INT (def) = 0; + if (da->instances_list) { + EMIT_DEF (def->space, D_INT (def), da->instances_list); + } } } @@ -1273,7 +1416,7 @@ class_finish_module (void) {0, 0} }; - obj_symtab_data_t data = {0, 0, 0, 0, 0}; + obj_symtab_data_t data = {}; class_t **cl; category_t **ca; @@ -1299,10 +1442,14 @@ class_finish_module (void) if ((*ca)->def && !(*ca)->def->external) data.cat_def_cnt++; } - if (!data.refs && !data.cls_def_cnt && !data.cat_def_cnt) + data.instances_list = emit_static_instances_list (); + if (!data.refs && !data.cls_def_cnt && !data.cat_def_cnt + && !data.instances_list) return; symtab_struct[4].type = array_type (&type_pointer, - data.cls_def_cnt + data.cat_def_cnt); + data.cls_def_cnt + + data.cat_def_cnt + + 1); symtab_def = emit_structure ("_OBJ_SYMTAB", 's', symtab_struct, 0, &data, sc_static); free (data.classes); @@ -1389,6 +1536,7 @@ protocol_def (protocol_t *protocol) { if (!protocol->def) { protocol->def = emit_protocol (protocol); + add_static_instance ("Protocol", protocol->def); } return protocol->def; } @@ -1548,6 +1696,10 @@ clear_classes (void) Hash_FlushTable (protocol_hash); if (category_hash) Hash_FlushTable (category_hash); + if (static_instances) + Hash_FlushTable (static_instances); + if (static_instance_classes) + Hash_FlushTable (static_instance_classes); obj_initialized = 0; } diff --git a/tools/qfcc/source/dump_modules.c b/tools/qfcc/source/dump_modules.c index 6bb559003..68cee44eb 100644 --- a/tools/qfcc/source/dump_modules.c +++ b/tools/qfcc/source/dump_modules.c @@ -89,22 +89,41 @@ dump_selector (progs_t *pr, pr_sel_t *sel) printf (" %s\n", sel_types); } +static void +dump_method_description_list (progs_t *pr, char c, + pr_method_description_list_t *list) +{ + if (list) { + for (int i = 0; i < list->count; i++) { + printf ("%*s%s\n", 20, "", PR_GetString (pr, list->list[i].name)); + printf ("%*s%s\n", 20, "", PR_GetString (pr, list->list[i].types)); + } + } +} + static void dump_protocol (progs_t *pr, pr_protocol_t *proto) { const char *protocol_name = ""; - printf (" %d ", proto->class_pointer); + printf (" %x %x ", + (pointer_t) ((pr_int_t *) proto - (pr_int_t *) pr->pr_globals), + proto->class_pointer); if (PR_StringValid (pr, proto->protocol_name)) protocol_name = PR_GetString (pr, proto->protocol_name); printf ("<%s>\n", protocol_name); + dump_method_description_list (pr, '-', + &G_STRUCT (pr, pr_method_description_list_t, + proto->instance_methods)); + dump_method_description_list (pr, '-', + &G_STRUCT (pr, pr_method_description_list_t, + proto->class_methods)); } static void dump_protocol_list (progs_t *pr, pr_protocol_list_t *list) { int i; - printf (" %d\n", list->next); - printf (" %d\n", list->count); + printf (" %x %d\n", list->next, list->count); for (i = 0; i < list->count; i++) { if (list->list[i] <= 0 || list->list[i] >= pr->globals_size) { printf ("invalid pointer\n"); @@ -171,6 +190,32 @@ dump_category (progs_t *pr, pr_category_t *category) category->protocols)); } +static void +dump_static_instance_lists (progs_t *pr, pointer_t instance_lists) +{ + pointer_t *ptr = &G_STRUCT (pr, pointer_t, instance_lists); + + printf (" static instance lists @ %x\n", instance_lists); + while (*ptr) { + __auto_type list = &G_STRUCT (pr, pr_static_instances_t, *ptr); + const char *class_name = "*** INVALID ***"; + + if (PR_StringValid (pr, list->class_name)) { + class_name = PR_GetString (pr, list->class_name); + } + printf (" %x %s\n", *ptr, class_name); + for (int i = 0; list->instances[i]; i++) { + if (!strcmp (class_name, "Protocol")) { + dump_protocol (pr, &G_STRUCT (pr, pr_protocol_t, + list->instances[i])); + } else { + printf (" %x\n", list->instances[i]); + } + } + ptr++; + } +} + static void dump_module (progs_t *pr, pr_module_t *module) { @@ -197,6 +242,9 @@ dump_module (progs_t *pr, pr_module_t *module) dump_class (pr, &G_STRUCT (pr, pr_class_t, *ptr++)); for (i = 0; i < symtab->cat_def_cnt; i++) dump_category (pr, &G_STRUCT (pr, pr_category_t, *ptr++)); + if (*ptr) { + dump_static_instance_lists (pr, *ptr); + } } void diff --git a/tools/qfcc/source/dump_strings.c b/tools/qfcc/source/dump_strings.c index fc0c0cb7d..77f3c0ae4 100644 --- a/tools/qfcc/source/dump_strings.c +++ b/tools/qfcc/source/dump_strings.c @@ -44,14 +44,14 @@ dump_string_block (const char *strblock, unsigned size) { const char *s = strblock; - printf ("%d ", 0); + printf ("%x ", 0); while (s - strblock < size) { char c = *s++; switch (c) { case 0: fputs ("\n", stdout); if (s - strblock < size) - printf ("%ld ", s - strblock); + printf ("%lx ", s - strblock); break; case 9: fputs ("\\t", stdout); From 8021613b79daa56e908c34ff3d44da2e55f390c5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 10:52:09 +0900 Subject: [PATCH 0474/3664] [qfcc] Fix missing protocol method lists The problem was an erroneous assumption that the methods had to be defined. Any class implementing a protocol must implement (and thus define) the methods, but a protocol declaration cannot: it merely declares the methods, and it's entirely possible for a module to see only the protocol definition and not any classes implementing the protocol. --- tools/qfcc/source/method.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 726acfd76..2ae50f39d 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -511,9 +511,11 @@ emit_method_list_item (def_t *def, void *data, int index) method_t *m; pr_method_description_t *desc; - if (def->type != &type_obj_method_description) - internal_error (0, "%s: expected method_description def", + if (!is_array (def->type) + || def->type->t.array.type != &type_obj_method_description) { + internal_error (0, "%s: expected array of method_description def", __FUNCTION__); + } if (index < 0 || index >= methods->count) internal_error (0, "%s: out of bounds index: %d %d", __FUNCTION__, index, methods->count); @@ -521,7 +523,7 @@ emit_method_list_item (def_t *def, void *data, int index) desc = D_POINTER (pr_method_description_t, def); for (m = methods->head; m; m = m->next) { - if (!m->instance != !methods->instance || !m->def) + if (!m->instance != !methods->instance) continue; if (!index--) break; @@ -547,7 +549,7 @@ emit_method_descriptions (methodlist_t *methods, const char *name, return 0; for (count = 0, m = methods->head; m; m = m->next) - if (!m->instance == !instance && m->def) + if (!m->instance == !instance) count++; if (!count) return 0; From 9ccff74fcf5dac1abdcffa6c8b9bfbc7cd7094df Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 10:55:46 +0900 Subject: [PATCH 0475/3664] [qfcc] Emit only one instance per protocol per module This is actually a double issue: when a class implementing a protocol used the protocol in @protocol(), not only would the protocol get emitted as part of the class data specifying that the class conforms to the protocol, a second instance would be emitted again when @protocol() was used. On top of that, only the instance referenced by @protocol() would be initialized. Now, both class emission and @protocol() get their protocol def from the same place and thus only one, properly initialized, protocol instance is emitted. --- tools/qfcc/source/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 0b981d065..381b37e1e 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1667,7 +1667,7 @@ emit_protocol_list_item (def_t *def, void *data, int index) internal_error (0, "%s: out of bounds index: %d %d", __FUNCTION__, index, protocols->count); } - EMIT_DEF (def->space, D_INT(def), emit_protocol (protocol)); + EMIT_DEF (def->space, D_INT(def), protocol_def (protocol)); } def_t * From bc4bea79cb9af733a908915a77c428095099ed3a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 13:00:33 +0900 Subject: [PATCH 0476/3664] [ruamoko] Remove a stale FIXME This was fixed when pr_def_t was introduced. I missed the comment at the time. --- libs/ruamoko/rua_obj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 93fe8a68b..2d30874dd 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1625,7 +1625,7 @@ rua_PR_FindGlobal (progs_t *pr) R_POINTER (pr) = 0; def = PR_FindGlobal (pr, name); if (def) - R_POINTER (pr) = def->ofs; //FIXME def's can't access > 32k + R_POINTER (pr) = def->ofs; } //==================================================================== From 78f552aa87570ba7e9d8742198d2efc71bb50fe6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 13:02:29 +0900 Subject: [PATCH 0477/3664] [ruamoko] Initialize static instances This is one step closer to implementing conformsToProtocol. However, protocols are not yet initialized correctly: they are not registered, nor are their selectors. While the static initializer list pointer was not written previously, the module struct always came immediately after the symbols struct, and the module version has so far always been 0. Thus, the list pointer is correctly 0 for older progs and there's no need for a version bump. --- libs/ruamoko/rua_obj.c | 90 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 2d30874dd..3aa345bfa 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -72,6 +72,7 @@ typedef struct probj_resources_s { hashtab_t *load_methods; obj_list *unresolved_classes; obj_list *unclaimed_categories; + obj_list *uninitialized_statics; obj_list *unclaimed_proto_list; obj_list *module_list; obj_list *class_tree_list; @@ -516,6 +517,24 @@ obj_register_selectors_from_class (probj_t *probj, pr_class_t *class) } } +static void obj_init_protocols (probj_t *probj, pr_protocol_list_t *protos); + +static void +obj_init_protocol (probj_t *probj, pr_class_t *proto_class, + pr_protocol_t *proto) +{ + progs_t *pr = probj->pr; + + if (!proto->class_pointer) { + proto->class_pointer = PR_SetPointer (pr, proto_class); + obj_init_protocols (probj, &G_STRUCT (pr, pr_protocol_list_t, + proto->protocol_list)); + } else { + if (proto->class_pointer != PR_SetPointer (pr, proto_class)) + PR_RunError (pr, "protocol broken"); + } +} + static void obj_init_protocols (probj_t *probj, pr_protocol_list_t *protos) { @@ -535,14 +554,7 @@ obj_init_protocols (probj_t *probj, pr_protocol_list_t *protos) for (i = 0; i < protos->count; i++) { proto = &G_STRUCT (pr, pr_protocol_t, protos->list[i]); - if (!proto->class_pointer) { - proto->class_pointer = PR_SetPointer (pr, proto_class); - obj_init_protocols (probj, &G_STRUCT (pr, pr_protocol_list_t, - proto->protocol_list)); - } else { - if (proto->class_pointer != PR_SetPointer (pr, proto_class)) - PR_RunError (pr, "protocol broken"); - } + obj_init_protocol (probj, proto_class, proto); } } @@ -851,6 +863,51 @@ dump_ivars (probj_t *probj, pointer_t _ivars) } } +static void +obj_init_statics (probj_t *probj) +{ + progs_t *pr = probj->pr; + obj_list **cell = &probj->uninitialized_statics; + pointer_t *ptr; + pointer_t *inst; + + Sys_MaskPrintf (SYS_RUA_OBJ, "Initializing statics\n"); + while (*cell) { + int initialized = 1; + + for (ptr = (*cell)->data; *ptr; ptr++) { + __auto_type statics = &G_STRUCT (pr, pr_static_instances_t, *ptr); + const char *class_name = PR_GetString (pr, statics->class_name); + pr_class_t *class = Hash_Find (probj->classes, class_name); + + Sys_MaskPrintf (SYS_RUA_OBJ, " %s %p\n", class_name, class); + if (!class) { + initialized = 0; + continue; + } + + if (strcmp (class_name, "Protocol") == 0) { + // protocols are special + for (inst = statics->instances; *inst; inst++) { + obj_init_protocol (probj, class, + &G_STRUCT (pr, pr_protocol_t, *inst)); + } + } else { + for (inst = statics->instances; *inst; inst++) { + pr_id_t *id = &G_STRUCT (pr, pr_id_t, *inst); + id->class_pointer = PR_SetPointer (pr, class); + } + } + } + + if (initialized) { + list_remove (cell); + } else { + cell = &(*cell)->next; + } + } +} + static void rua___obj_exec_class (progs_t *pr) { @@ -869,13 +926,16 @@ rua___obj_exec_class (progs_t *pr) return; Sys_MaskPrintf (SYS_RUA_OBJ, "Initializing %s module\n" "symtab @ %x : %d selector%s @ %x, " - "%d class%s and %d categor%s\n", + "%d class%s and %d categor%s\n" + "static instance lists: %s\n", PR_GetString (pr, module->name), module->symtab, symtab->sel_ref_cnt, symtab->sel_ref_cnt == 1 ? "" : "s", symtab->refs, symtab->cls_def_cnt, symtab->cls_def_cnt == 1 ? "" : "es", symtab->cat_def_cnt, - symtab->cat_def_cnt == 1 ? "y" : "ies"); + symtab->cat_def_cnt == 1 ? "y" : "ies", + symtab->defs[symtab->cls_def_cnt + + symtab->cat_def_cnt] ? "yes" : "no"); probj->module_list = list_cons (module, probj->module_list); @@ -958,6 +1018,16 @@ rua___obj_exec_class (progs_t *pr) } } + if (*ptr) { + Sys_MaskPrintf (SYS_RUA_OBJ, "Static instances lists: %x\n", *ptr); + probj->uninitialized_statics + = list_cons (&G_STRUCT (pr, pointer_t, *ptr), + probj->uninitialized_statics); + } + if (probj->uninitialized_statics) { + obj_init_statics (probj); + } + for (cell = &probj->unclaimed_categories; *cell; ) { pr_category_t *category = (*cell)->data; const char *class_name = PR_GetString (pr, category->class_name); From 0db617719e39faa16381d2c5cfa95d3d6850375c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 13:31:26 +0900 Subject: [PATCH 0478/3664] [qfcc] Improve error messages for bad qc builtins While global quakec functions could not be initialized to another function, the error messages were rather obscure. --- tools/qfcc/source/qc-parse.y | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a7b353082..8d939185b 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1014,11 +1014,20 @@ non_code_func } | '=' expr { - symbol_t *sym = $0; - specifier_t spec = $-1; - initialize_def (sym, $2, current_symtab->space, spec.storage); - if (sym->s.def) - sym->s.def->nosave |= spec.nosave; + if (local_expr) { + symbol_t *sym = $0; + specifier_t spec = $-1; + initialize_def (sym, $2, current_symtab->space, spec.storage); + if (sym->s.def) + sym->s.def->nosave |= spec.nosave; + } else { + if (is_integer_val ($2) || is_float_val ($2)) { + error (0, "invalid function initializer." + " did you forget #?"); + } else { + error (0, "cannot create global function variables"); + } + } } | /* emtpy */ { From 5893bd750135a95222ae34f004da7c9bc27af31b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 13:32:58 +0900 Subject: [PATCH 0479/3664] [qfcc] Catch erroneous negative builtin numbers Setting a builtin number negative makes it a non-builtin function, but possibly in the middle of another function. Not good. --- tools/qfcc/source/function.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 3b844b5a3..e2b87d04a 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -656,6 +656,10 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far) bi = expr_integer (bi_val); else bi = expr_float (bi_val); + if (bi < 0) { + error (bi_val, "builtin functions must be positive or 0"); + return 0; + } sym->s.func->builtin = bi; reloc_def_func (sym->s.func, sym->s.func->def); build_function (sym); From a906efac47d804798870a1d1eb839c7db6433483 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 15:20:34 +0900 Subject: [PATCH 0480/3664] [ruamoko] Register protocols and their selectors --- libs/ruamoko/rua_obj.c | 47 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 3aa345bfa..028850561 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -69,6 +69,7 @@ typedef struct probj_resources_s { string_t *selector_names; hashtab_t *selector_hash; hashtab_t *classes; + hashtab_t *protocols; hashtab_t *load_methods; obj_list *unresolved_classes; obj_list *unclaimed_categories; @@ -324,6 +325,13 @@ class_get_key (const void *c, void *_probj) return PR_GetString (probj->pr, ((pr_class_t *)c)->name); } +static const char * +protocol_get_key (const void *p, void *_probj) +{ + __auto_type probj = (probj_t *) _probj; + return PR_GetString (probj->pr, ((pr_protocol_t *)p)->protocol_name); +} + static uintptr_t load_methods_get_hash (const void *m, void *_probj) { @@ -490,7 +498,27 @@ sel_register_name (probj_t *probj, const char *name) } static void -register_selectors_from_list (probj_t *probj, pr_method_list_t *method_list) +obj_register_selectors_from_description_list (probj_t *probj, + pr_method_description_list_t *method_list) +{ + progs_t *pr = probj->pr; + int i; + + if (!method_list) { + return; + } + for (i = 0; i < method_list->count; i++) { + pr_method_description_t *method = &method_list->list[i]; + const char *name = PR_GetString (pr, method->name); + const char *types = PR_GetString (pr, method->types); + pr_sel_t *sel = sel_register_typed_name (probj, name, types, 0); + method->name = PR_SetPointer (pr, sel); + } +} + +static void +obj_register_selectors_from_list (probj_t *probj, + pr_method_list_t *method_list) { progs_t *pr = probj->pr; int i; @@ -511,7 +539,7 @@ obj_register_selectors_from_class (probj_t *probj, pr_class_t *class) pr_method_list_t *method_list = &G_STRUCT (pr, pr_method_list_t, class->methods); while (method_list) { - register_selectors_from_list (probj, method_list); + obj_register_selectors_from_list (probj, method_list); method_list = &G_STRUCT (pr, pr_method_list_t, method_list->method_next); } @@ -526,7 +554,17 @@ obj_init_protocol (probj_t *probj, pr_class_t *proto_class, progs_t *pr = probj->pr; if (!proto->class_pointer) { + const char *protocol_name = PR_GetString (pr, proto->protocol_name); proto->class_pointer = PR_SetPointer (pr, proto_class); + obj_register_selectors_from_description_list (probj, + &G_STRUCT (pr, pr_method_description_list_t, + proto->instance_methods)); + obj_register_selectors_from_description_list (probj, + &G_STRUCT (pr, pr_method_description_list_t, + proto->class_methods)); + if (!Hash_Find (probj->protocols, protocol_name)) { + Hash_Add (probj->protocols, proto); + } obj_init_protocols (probj, &G_STRUCT (pr, pr_protocol_list_t, proto->protocol_list)); } else { @@ -1816,6 +1854,11 @@ rua_obj_init_runtime (progs_t *pr) else Hash_FlushTable (probj->classes); + if (!probj->protocols) + probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj); + else + Hash_FlushTable (probj->protocols); + if (!probj->load_methods) { probj->load_methods = Hash_NewTable (1021, 0, 0, probj); Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, From 0e40366c7fe3a34f8f20ce52c051254721c8cc6b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 15:21:10 +0900 Subject: [PATCH 0481/3664] [ruamoko] Implement class conformsToProtocol Seems to work nicely, too :) --- libs/ruamoko/rua_obj.c | 85 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 6 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 028850561..e088ff140 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1713,15 +1713,88 @@ rua__i_Object_error_error_ (progs_t *pr) obj_verror (probj, self, 0, dstr->str, count, args); } +static int +obj_protocol_conformsToProtocol (probj_t *probj, pr_protocol_t *proto, + pr_protocol_t *protocol) +{ + progs_t *pr = probj->pr; + + pr_protocol_list_t *proto_list; + + if (!proto || !protocol) { + return 0; + } + if (proto == protocol) { + return 1; + } + if (proto->protocol_name == protocol->protocol_name + || strcmp (PR_GetString (pr, proto->protocol_name), + PR_GetString (pr, protocol->protocol_name)) == 0) { + return 1; + } + proto_list = &G_STRUCT (pr, pr_protocol_list_t, proto->protocol_list); + while (proto_list) { + Sys_MaskPrintf (SYS_RUA_OBJ, "%x %x %d\n", + PR_SetPointer (pr, proto_list), proto_list->next, + proto_list->count); + for (int i = 0; i < proto_list->count; i++) { + proto = &G_STRUCT (pr, pr_protocol_t, proto_list->list[i]); + if (proto == protocol + || obj_protocol_conformsToProtocol (probj, proto, protocol)) { + return 1; + } + } + + proto_list = &G_STRUCT (pr, pr_protocol_list_t, proto_list->next); + } + return 0; +} + static void rua__c_Object__conformsToProtocol_ (progs_t *pr) { - //probj_t *probj = pr->pr_objective_resources; - //pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); - //pr_protocol_t *proto = &P_STRUCT (pr, pr_protocol_t, 2); - //... - //XXX - PR_RunError (pr, "%s, not implemented", __FUNCTION__); + probj_t *probj = pr->pr_objective_resources; + // class points to _OBJ_CLASS_foo, and class->class_pointer points to + // _OBJ_METACLASS_foo + pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); + // protocol->class_pointer must point to _OBJ_CLASS_Protocol (ie, if + // protocol is not actually a protocol, then the class cannot conform + // to it) + pr_protocol_t *protocol = &P_STRUCT (pr, pr_protocol_t, 2); + pr_protocol_list_t *proto_list; + + if (!class || !protocol) { + goto not_conforms; + } + if (protocol->class_pointer != PR_SetPointer (pr, + Hash_Find (probj->classes, + "Protocol"))) { + goto not_conforms; + } + proto_list = &G_STRUCT (pr, pr_protocol_list_t, class->protocols); + while (proto_list) { + Sys_MaskPrintf (SYS_RUA_OBJ, "%x %x %d\n", + PR_SetPointer (pr, proto_list), proto_list->next, + proto_list->count); + for (int i = 0; i < proto_list->count; i++) { + __auto_type proto = &G_STRUCT (pr, pr_protocol_t, + proto_list->list[i]); + if (proto == protocol + || obj_protocol_conformsToProtocol (probj, proto, protocol)) { + goto conforms; + } + } + + proto_list = &G_STRUCT (pr, pr_protocol_list_t, proto_list->next); + } +not_conforms: + Sys_MaskPrintf (SYS_RUA_OBJ, "does not conform\n"); + R_INT (pr) = 0; + return; +conforms: + Sys_MaskPrintf (SYS_RUA_OBJ, "conforms\n"); + R_INT (pr) = 1; + return; } static void From d88a091fc658500d16fd88219e2102067ac376f1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 15:22:54 +0900 Subject: [PATCH 0482/3664] [qwaq] Use protocols to distinguish object abilities Well, that took a fair bit more than it should have to get working: had to implement the protocol support in qfcc and engine-side ruamoko. --- ruamoko/qwaq/event.h | 12 ++++++++++++ ruamoko/qwaq/main.c | 3 +++ ruamoko/qwaq/qwaq-draw.h | 8 ++++++++ ruamoko/qwaq/qwaq-screen.h | 4 +++- ruamoko/qwaq/qwaq-screen.r | 16 ++++++++++++++++ ruamoko/qwaq/qwaq-view.h | 4 ++-- ruamoko/qwaq/qwaq-view.r | 2 +- ruamoko/qwaq/qwaq-window.h | 3 ++- ruamoko/qwaq/qwaq-window.r | 15 +++++++++++++++ 9 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-draw.h diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index 006d37c42..f494234a9 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -32,4 +32,16 @@ typedef struct qwaq_event_s { } e; } qwaq_event_t; +#ifdef __QFCC__ // don't want C gcc to see this :) +@protocol HandleEvent +-handleEvent: (struct qwaq_event_s *) event; +@end + +@protocol TakeFocus +-takeFocus; +-loseFocus; +@end + +#endif + #endif//__qwaq_event_h diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 3f88a428a..191714c74 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -166,6 +166,9 @@ main (int argc, const char **argv) Sys_Error ("couldn't load %s", name); } + //pr.pr_trace = 1; + //pr.pr_trace_depth = -1; + PR_PushFrame (&pr); if (argc > 2) pr_argc = argc - 1; diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h new file mode 100644 index 000000000..4abac3e55 --- /dev/null +++ b/ruamoko/qwaq/qwaq-draw.h @@ -0,0 +1,8 @@ +#ifndef __qwaq_draw_h +#define __qwaq_draw_h + +@protocol Draw +-draw; +@end + +#endif diff --git a/ruamoko/qwaq/qwaq-screen.h b/ruamoko/qwaq/qwaq-screen.h index 365c54506..cbd0a6721 100644 --- a/ruamoko/qwaq/qwaq-screen.h +++ b/ruamoko/qwaq/qwaq-screen.h @@ -3,14 +3,16 @@ #include +#include "qwaq-draw.h" #include "qwaq-rect.h" @class View; @class Array; -@interface Screen: Object +@interface Screen: Object { Rect rect; Array *views; + Array *event_handlers; View *focusedView; struct window_s *window; } diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index cd4e25365..e44c25481 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -19,6 +19,12 @@ -add: obj { + if ([obj conformsToProtocol: @protocol (Draw)]) { + [views addObject: obj]; + } + if ([obj conformsToProtocol: @protocol (HandleEvent)]) { + [event_handlers addObject: obj]; + } return self; } @@ -29,4 +35,14 @@ return self; } +-handleEvent: (qwaq_event_t *) event +{ + return self; +} + +-draw +{ + return self; +} + @end diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 811998ed0..e532f9f0b 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -4,9 +4,10 @@ #include #include +#include "qwaq-draw.h" #include "qwaq-rect.h" -@interface View: Object +@interface View: Object { Rect rect; Rect absRect; @@ -14,7 +15,6 @@ struct window_s *window; } -initWithRect: (Rect) rect; --handleEvent: (struct qwaq_event_s *) event; @end #endif//__qwaq_view_h diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index c03d880f4..8cf37c53d 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -28,7 +28,7 @@ rectContainsPoint (Rect *rect, Point *point) return self; } --handleEvent: (qwaq_event_t *) event +-draw { return self; } diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 5d777c828..66c6d440e 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -6,9 +6,10 @@ @class View; @class Array; +#include "qwaq-draw.h" #include "qwaq-rect.h" -@interface Window: Object +@interface Window: Object { Rect rect; Point point; // FIXME can't be local :( diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 70fe2c476..307f09dce 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -68,4 +68,19 @@ wbkgd (window, ch); return self; } + +-takeFocus +{ + return self; +} + +-loseFocus +{ + return self; +} + +-draw +{ + return self; +} @end From fa66e9fc2f61c9b43670a822c2f051aee1f0fb7f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 18:15:31 +0900 Subject: [PATCH 0483/3664] [qwaq] Move queue handling into separate functions This makes it so I need to edit only one place when I get threads working. Also, it fixes some bugs (eg, panel creation wasn't implemented correctly). --- ruamoko/qwaq/qwaq-curses.c | 196 +++++++++++++++---------------------- 1 file changed, 79 insertions(+), 117 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 1c081e1eb..474203e47 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -97,7 +97,7 @@ typedef enum qwaq_commands_e { #define RB_WRITE_DATA(ring_buffer, data, count) \ ({ __auto_type rb = &(ring_buffer); \ - typeof (&rb->buffer[0]) d = (data); \ + const typeof (rb->buffer[0]) *d = (data); \ unsigned c = (count); \ unsigned h = rb->head; \ rb->head = (h + c) % RB_buffer_size (rb); \ @@ -272,6 +272,45 @@ release_string (qwaq_resources_t *res, int string_id) } } +static void +qwaq_submit_command (qwaq_resources_t *res, const int *cmd) +{ + unsigned len = cmd[1]; + + if (RB_SPACE_AVAILABLE (res->command_queue) >= len) { + RB_WRITE_DATA (res->command_queue, cmd, len); + } else { + PR_RunError (res->pr, "command buffer full"); + } +} + +static void +qwaq_submit_result (qwaq_resources_t *res, const int *result, unsigned len) +{ + // loop + if (RB_SPACE_AVAILABLE (res->results) >= len) { + RB_WRITE_DATA (res->results, result, len); + } else { + PR_RunError (res->pr, "result buffer full"); + } +} + +//XXX goes away with threads +static void process_commands (qwaq_resources_t *); +static void process_input (qwaq_resources_t *); +static void +qwaq_wait_result (qwaq_resources_t *res, int *result, int cmd, unsigned len) +{ + // XXX should just wait on the mutex + process_commands (res); + process_input (res); + // locking and loop until id is correct + if (RB_DATA_AVAILABLE (res->results) >= len + && RB_PEEK_DATA (res->results, 0) == cmd) { + RB_READ_DATA (res->results, result, len); + } +} + static void cmd_newwin (qwaq_resources_t *res) { @@ -286,11 +325,7 @@ cmd_newwin (qwaq_resources_t *res) int window_id = window_index (res, window); int cmd_result[] = { qwaq_cmd_newwin, window_id }; - - // loop - if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { - RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); - } + qwaq_submit_result (res, cmd_result, CMD_SIZE (cmd_result)); } static void @@ -318,11 +353,7 @@ cmd_getwrect (qwaq_resources_t *res) getmaxyx (window->win, ylen, xlen); int cmd_result[] = { qwaq_cmd_getwrect, xpos, ypos, xlen, ylen }; - - // loop - if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { - RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); - } + qwaq_submit_result (res, cmd_result, CMD_SIZE (cmd_result)); } static void @@ -337,11 +368,7 @@ cmd_new_panel (qwaq_resources_t *res) int panel_id = panel_index (res, panel); int cmd_result[] = { qwaq_cmd_new_panel, panel_id }; - - // loop - if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { - RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); - } + qwaq_submit_result (res, cmd_result, CMD_SIZE (cmd_result)); } static void @@ -415,11 +442,7 @@ cmd_panel_window (qwaq_resources_t *res) int window_id = panel->window_id; int cmd_result[] = { qwaq_cmd_panel_window, window_id, }; - - // loop - if (RB_SPACE_AVAILABLE (res->results) >= CMD_SIZE (cmd_result)) { - RB_WRITE_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); - } + qwaq_submit_result (res, cmd_result, CMD_SIZE (cmd_result)); } static void @@ -631,22 +654,12 @@ bi_newwin (progs_t *pr) qwaq_cmd_newwin, 0, xpos, ypos, xlen, ylen, }; - command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } - // XXX should just wait on the mutex - process_commands (res); - process_input (res); - // locking and loop until id is correct - if (RB_DATA_AVAILABLE (res->results) - && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_newwin) { - int cmd_result[2]; // should results have a size? - RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); - R_INT (pr) = cmd_result[1]; - } + int cmd_result[2]; + qwaq_wait_result (res, cmd_result, qwaq_cmd_newwin, CMD_SIZE (cmd_result)); + R_INT (pr) = cmd_result[1]; } static void @@ -657,12 +670,8 @@ bi_delwin (progs_t *pr) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_delwin, 0, window_id, }; - command[1] = CMD_SIZE(command); - - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } + qwaq_submit_command (res, command); } } @@ -674,26 +683,17 @@ bi_getwrect (progs_t *pr) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_getwrect, 0, window_id, }; - command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } - // XXX should just wait on the mutex - process_commands (res); - process_input (res); - // locking and loop until id is correct - if (RB_DATA_AVAILABLE (res->results) - && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_getwrect) { - int cmd_result[5]; - RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); - // return xpos, ypos, xlen, ylen - (&R_INT (pr))[0] = cmd_result[1]; - (&R_INT (pr))[1] = cmd_result[2]; - (&R_INT (pr))[2] = cmd_result[3]; - (&R_INT (pr))[3] = cmd_result[4]; - } + int cmd_result[5]; + qwaq_wait_result (res, cmd_result, qwaq_cmd_getwrect, + CMD_SIZE (cmd_result)); + // return xpos, ypos, xlen, ylen + (&R_INT (pr))[0] = cmd_result[1]; + (&R_INT (pr))[1] = cmd_result[2]; + (&R_INT (pr))[2] = cmd_result[3]; + (&R_INT (pr))[3] = cmd_result[4]; } } @@ -705,20 +705,13 @@ bi_new_panel (progs_t *pr) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_new_panel, 0, window_id, }; - command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } - - // locking and loop until id is correct - if (RB_DATA_AVAILABLE (res->results) - && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_new_panel) { - int cmd_result[2]; // should results have a size? - RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); - R_INT (pr) = cmd_result[1]; - } + int cmd_result[2]; + qwaq_wait_result (res, cmd_result, qwaq_cmd_new_panel, + CMD_SIZE (cmd_result)); + R_INT (pr) = cmd_result[1]; } } @@ -731,10 +724,7 @@ panel_command (progs_t *pr, qwaq_commands cmd) if (get_panel (res, __FUNCTION__, panel_id)) { int command[] = { cmd, 0, panel_id, }; command[1] = CMD_SIZE(command); - - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } + qwaq_submit_command (res, command); } } @@ -779,10 +769,7 @@ bi_move_panel (progs_t *pr) if (get_panel (res, __FUNCTION__, panel_id)) { int command[] = { qwaq_cmd_move_panel, 0, panel_id, x, y, }; command[1] = CMD_SIZE(command); - - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } + qwaq_submit_command (res, command); } } @@ -795,20 +782,12 @@ bi_panel_window (progs_t *pr) if (get_panel (res, __FUNCTION__, panel_id)) { int command[] = { qwaq_cmd_panel_window, 0, panel_id, }; command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } - // XXX should just wait on the mutex - process_commands (res); - process_input (res); - // locking and loop until id is correct - if (RB_DATA_AVAILABLE (res->results) - && RB_PEEK_DATA (res->results, 0) == qwaq_cmd_panel_window) { - int cmd_result[2]; - RB_READ_DATA (res->results, cmd_result, CMD_SIZE (cmd_result)); - (&R_INT (pr))[0] = cmd_result[0]; - } + int cmd_result[2]; + qwaq_wait_result (res, cmd_result, qwaq_cmd_panel_window, + CMD_SIZE (cmd_result)); + (&R_INT (pr))[0] = cmd_result[1]; } } @@ -819,10 +798,7 @@ bi_update_panels (progs_t *pr) int command[] = { qwaq_cmd_update_panels, 0, }; command[1] = CMD_SIZE(command); - - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } + qwaq_submit_command (res, command); } static void @@ -832,10 +808,7 @@ bi_doupdate (progs_t *pr) int command[] = { qwaq_cmd_doupdate, 0, }; command[1] = CMD_SIZE(command); - - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } + qwaq_submit_command (res, command); } static void @@ -861,9 +834,8 @@ bi_mvwprintf (progs_t *pr) dstring_clearstr (print_buffer); PR_Sprintf (pr, print_buffer, "mvwaddstr", fmt, count, args); - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } + + qwaq_submit_command (res, command); } } @@ -888,9 +860,8 @@ bi_wprintf (progs_t *pr) dstring_clearstr (print_buffer); PR_Sprintf (pr, print_buffer, "waddstr", fmt, count, args); - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } + + qwaq_submit_command (res, command); } } @@ -903,10 +874,7 @@ bi_wrefresh (progs_t *pr) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wrefresh, 0, window_id, }; command[1] = CMD_SIZE(command); - - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } + qwaq_submit_command (res, command); } } @@ -943,10 +911,7 @@ bi_init_pair (progs_t *pr) int command[] = { qwaq_cmd_init_pair, 0, pair, f, b, }; command[1] = CMD_SIZE(command); - - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } + qwaq_submit_command (res, command); } static void @@ -958,12 +923,9 @@ bi_wbkgd (progs_t *pr) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wbkgd, 0, window_id, ch, }; - command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); - if (RB_SPACE_AVAILABLE (res->command_queue) >= CMD_SIZE(command)) { - RB_WRITE_DATA (res->command_queue, command, CMD_SIZE(command)); - } } } From a0c4d566683c3e9663d94519fac00dfe52af99d6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 18:19:41 +0900 Subject: [PATCH 0484/3664] [qwaq] Continue processing on void commands If the last command in the buffer had no parameters, its length would be only 2 and thus processing would stop before reading the command from the buffer. --- ruamoko/qwaq/qwaq-curses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 474203e47..2b53efb06 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -513,7 +513,7 @@ cmd_wbkgd (qwaq_resources_t *res) static void process_commands (qwaq_resources_t *res) { - while (RB_DATA_AVAILABLE (res->command_queue) > 2) { + while (RB_DATA_AVAILABLE (res->command_queue) >= 2) { switch ((qwaq_commands) RB_PEEK_DATA (res->command_queue, 0)) { case qwaq_cmd_newwin: cmd_newwin (res); From b9ab30ff59d49cf5044332b7c1a53017471b6bac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 18:24:45 +0900 Subject: [PATCH 0485/3664] [qwaq] Add mvwaddch and ACS support --- ruamoko/qwaq/qwaq-app.r | 2 ++ ruamoko/qwaq/qwaq-curses.c | 50 +++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-curses.h | 64 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index d9051f4d9..28bf31126 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -103,11 +103,13 @@ void destroy_window (window_t win) = #0; void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; void wprintf (window_t win, string fmt, ...) = #0; void wrefresh (window_t win) = #0; +void mvwaddch (window_t win, int x, int y, int ch) = #0; int get_event (qwaq_event_t *event) = #0; int max_colors (void) = #0; int max_color_pairs (void) = #0; int init_pair (int pair, int f, int b) = #0; void wbkgd (window_t win, int ch) = #0; +int acs_char (int acs) = #0; panel_t create_panel (window_t window) = #0; void destroy_panel (panel_t panel) = #0; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 2b53efb06..e8c6548eb 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -68,6 +68,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_doupdate, qwaq_cmd_mvwaddstr, qwaq_cmd_waddstr, + qwaq_cmd_mvwaddch, qwaq_cmd_wrefresh, qwaq_cmd_init_pair, qwaq_cmd_wbkgd, @@ -481,6 +482,18 @@ cmd_waddstr (qwaq_resources_t *res) release_string (res, string_id); } +static void +cmd_mvwaddch (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int x = RB_PEEK_DATA (res->command_queue, 3); + int y = RB_PEEK_DATA (res->command_queue, 4); + int ch = RB_PEEK_DATA (res->command_queue, 5); + + window_t *window = get_window (res, __FUNCTION__, window_id); + mvwaddch (window->win, y, x, ch); +} + static void cmd_wrefresh (qwaq_resources_t *res) { @@ -560,6 +573,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_waddstr: cmd_waddstr (res); break; + case qwaq_cmd_mvwaddch: + cmd_mvwaddch (res); + break; case qwaq_cmd_wrefresh: cmd_wrefresh (res); break; @@ -865,6 +881,25 @@ bi_wprintf (progs_t *pr) } } +static void +bi_mvwaddch (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int window_id = P_INT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + int ch = P_INT (pr, 3); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { + qwaq_cmd_mvwaddch, 0, + window_id, x, y, ch + }; + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} + static void bi_wrefresh (progs_t *pr) { @@ -925,7 +960,20 @@ bi_wbkgd (progs_t *pr) int command[] = { qwaq_cmd_wbkgd, 0, window_id, ch, }; command[1] = CMD_SIZE(command); qwaq_submit_command (res, command); + } +} +static const char qwaq_acs_char_map[] = "lmkjtuvwqxnos`afg~,+.-hi0pryz{|}"; +static void +bi_acs_char (progs_t *pr) +{ + unsigned acs = P_INT (pr, 0); + if (acs < 256) { + R_INT (pr) = NCURSES_ACS(acs); + } else if (acs - 256 < sizeof (qwaq_acs_char_map)) { + R_INT (pr) = NCURSES_ACS(qwaq_acs_char_map[acs - 256]); + } else { + R_INT (pr) = 0; } } @@ -981,12 +1029,14 @@ static builtin_t builtins[] = { {"doupdate", bi_doupdate, -1}, {"mvwprintf", bi_mvwprintf, -1}, {"wprintf", bi_wprintf, -1}, + {"mvwaddch", bi_mvwaddch, -1}, {"wrefresh", bi_wrefresh, -1}, {"get_event", bi_get_event, -1}, {"max_colors", bi_max_colors, -1}, {"max_color_pairs", bi_max_color_pairs, -1}, {"init_pair", bi_init_pair, -1}, {"wbkgd", bi_wbkgd, -1}, + {"acs_char", bi_acs_char, -1}, {0} }; diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 751c521a7..bf5d24191 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -4,6 +4,67 @@ #include "event.h" #ifdef __QFCC__ +// names, order and comments lifted from ncurses.h +typedef enum { +/* VT100 symbols begin here */ + ACS_ULCORNER = 256, /* upper left corner */ + ACS_LLCORNER, /* lower left corner */ + ACS_URCORNER, /* upper right corner */ + ACS_LRCORNER, /* lower right corner */ + ACS_LTEE, /* tee pointing right */ + ACS_RTEE, /* tee pointing left */ + ACS_BTEE, /* tee pointing up */ + ACS_TTEE, /* tee pointing down */ + ACS_HLINE, /* horizontal line */ + ACS_VLINE, /* vertical line */ + ACS_PLUS, /* large plus or crossover */ + ACS_S1, /* scan line 1 */ + ACS_S9, /* scan line 9 */ + ACS_DIAMOND, /* diamond */ + ACS_CKBOARD, /* checker board (stipple) */ + ACS_DEGREE, /* degree symbol */ + ACS_PLMINUS, /* plus/minus */ + ACS_BULLET, /* bullet */ +/* Teletype 5410v1 symbols begin here */ + ACS_LARROW, /* arrow pointing left */ + ACS_RARROW, /* arrow pointing right */ + ACS_DARROW, /* arrow pointing down */ + ACS_UARROW, /* arrow pointing up */ + ACS_BOARD, /* board of squares */ + ACS_LANTERN, /* lantern symbol */ + ACS_BLOCK, /* solid square block */ +/* + * These aren't documented, but a lot of System Vs have them anyway + * (you can spot pprryyzz{{||}} in a lot of AT&T terminfo strings). + * The ACS_names may not match AT&T's, our source didn't know them. + */ + ACS_S3, /* scan line 3 */ + ACS_S7, /* scan line 7 */ + ACS_LEQUAL, /* less/equal */ + ACS_GEQUAL, /* greater/equal */ + ACS_PI, /* Pi */ + ACS_NEQUAL, /* not equal */ + ACS_STERLING, /* UK pound sign */ + +/* + * Line drawing ACS names are of the form ACS_trbl, where t is the top, r + * is the right, b is the bottom, and l is the left. t, r, b, and l might + * be B (blank), S (single), D (double), or T (thick). The subset defined + * here only uses B and S. + */ + ACS_BSSB = ACS_ULCORNER, + ACS_SSBB = ACS_LLCORNER, + ACS_BBSS = ACS_URCORNER, + ACS_SBBS = ACS_LRCORNER, + ACS_SBSS = ACS_RTEE, + ACS_SSSB = ACS_LTEE, + ACS_SSBS = ACS_BTEE, + ACS_BSSS = ACS_TTEE, + ACS_BSBS = ACS_HLINE, + ACS_SBSB = ACS_VLINE, + ACS_SSSS = ACS_PLUS, +} qwaq_acs_chars; + typedef struct window_s *window_t; typedef struct panel_s *panel_t; @@ -15,6 +76,7 @@ typedef struct panel_s *panel_t; @extern void mvwprintf (window_t win, int x, int y, string fmt, ...); @extern void wprintf (window_t win, string fmt, ...); @extern void wrefresh (window_t win); +@extern void mvwaddch (window_t win, int x, int y, int ch); @extern panel_t create_panel (window_t window); @extern void destroy_panel (panel_t panel); @@ -32,6 +94,8 @@ typedef struct panel_s *panel_t; @extern int max_color_pairs (void); @extern int init_pair (int pair, int f, int b); @extern void wbkgd (window_t win, int ch); + +@extern int acs_char (int acs); #endif #endif//__qwaq_curses_h From 6f1386fa0dbd77f7030ff21a31e01a06b80fea60 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 18:29:31 +0900 Subject: [PATCH 0486/3664] [qwaq] Test out acs chars and the classes Crashes due to flooding the command buffer, but otherwise works (with larger buffer). --- ruamoko/qwaq/qwaq-app.r | 7 ++++--- ruamoko/qwaq/qwaq-screen.r | 5 +++++ ruamoko/qwaq/qwaq-window.r | 16 ++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 28bf31126..619001b79 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -44,20 +44,21 @@ arp_end (void) r.xlen /= 2; r.ylen /= 2; wprintf (screen.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + wprintf (screen.window, "%d\n", acs_char(ACS_HLINE)); + mvwaddch(screen.window, 4, 4, acs_char(ACS_HLINE)); wrefresh(screen.window); Window *w; [screen add: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; - wprintf (w.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + //wprintf (w.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); return self; } -run { + [screen draw]; do { arp_start (); - update_panels (); - doupdate (); get_event (&event); if (event.event_type != qe_none) { [self handleEvent: &event]; diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index e44c25481..be7400468 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -12,6 +12,8 @@ if (!(self = [super init])) { return nil; } + views = [[Array array] retain]; + event_handlers = [[Array array] retain]; window = stdscr; rect = getwrect (window); return self; @@ -42,6 +44,9 @@ -draw { + [views makeObjectsPerformSelector: @selector (draw)]; + update_panels (); + doupdate (); return self; } diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 307f09dce..bf94b177d 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -81,6 +81,22 @@ -draw { + int x = 0, y = 0; + for (int i = ACS_ULCORNER; i <= ACS_STERLING; i++) { + int ch = acs_char (i); + if (ch) { + mvwaddch (window, x, y, ch); + } else { + mvwaddch (window, x, y, '.'); + } + if (++x >= rect.xlen) { + x = 0; + if (++y >= rect.ylen) { + break; + } + } + } + wrefresh(window); return self; } @end From 33a07c0f6b3cecae9eb4b72bbb5387ec916ec8ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 18:30:58 +0900 Subject: [PATCH 0487/3664] [qwaq] Make command buffer larger for now A small one should be fine once threading is working. --- ruamoko/qwaq/qwaq-curses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index e8c6548eb..f33e01a5a 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -49,7 +49,7 @@ #define MOUSE_MOVES_ON "\033[?1003h"// Make the terminal report mouse movements #define MOUSE_MOVES_OFF "\033[?1003l"// Make the terminal report mouse movements #define STRING_ID_QUEUE_SIZE 8 // must be > 1 -#define COMMAND_QUEUE_SIZE 128 +#define COMMAND_QUEUE_SIZE 1280 #define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) typedef enum qwaq_commands_e { From d91289ea1b37856c8d7b60d3114581f44ca06713 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 18:43:27 +0900 Subject: [PATCH 0488/3664] [qwaq] Remove unnecessary wrefresh calls --- ruamoko/qwaq/qwaq-app.r | 1 - ruamoko/qwaq/qwaq-screen.r | 1 - ruamoko/qwaq/qwaq-window.r | 1 - 3 files changed, 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 619001b79..e100ae69e 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -46,7 +46,6 @@ arp_end (void) wprintf (screen.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); wprintf (screen.window, "%d\n", acs_char(ACS_HLINE)); mvwaddch(screen.window, 4, 4, acs_char(ACS_HLINE)); - wrefresh(screen.window); Window *w; [screen add: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; //wprintf (w.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index be7400468..770104c64 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -33,7 +33,6 @@ -setBackground: (int) ch { wbkgd (window, ch); - wrefresh (window); return self; } diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index bf94b177d..493a6ccff 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -96,7 +96,6 @@ } } } - wrefresh(window); return self; } @end From e33d83fc9eeeb97707b5eb9fe908afbea69f32fc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 20:16:29 +0900 Subject: [PATCH 0489/3664] [qfcc] Accept "struct foo; struct foo { ... };" That is, do not treat structure definition after declaration to be a redefinition. --- tools/qfcc/source/qc-parse.y | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 8d939185b..5658382c5 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -610,9 +610,18 @@ struct_specifier if (!sym->table) { symtab_addsymbol (current_symtab, sym); } else { - error (0, "%s %s redefined", $1 == 's' ? "struct" : "union", - $2->name); - $1 = 0; + if (!sym->type) { + internal_error (0, "broken structure symbol?"); + } + if (sym->type->meta == ty_enum + || (sym->type->meta == ty_struct && sym->type->t.symtab)) { + error (0, "%s %s redefined", + $1 == 's' ? "struct" : "union", $2->name); + $1 = 0; + } else if (sym->type->meta != ty_struct) { + internal_error (0, "%s is not a struct or union", + $2->name); + } } current_symtab = new_symtab (current_symtab, stab_local); } From f6d650d47351ba71d4df9049436c9e8a506578b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 21:15:21 +0900 Subject: [PATCH 0490/3664] [qfcc] Merge duplicate methods in interfaces Duplicate methods in an interface (especially across protocols and between protocols and the interface) are both harmless and even to be expected. They certainly should not cause the compiler to demand duplicate method implementations :) --- tools/qfcc/source/class.c | 9 +++------ tools/qfcc/source/method.c | 6 ++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 381b37e1e..e4861b8d2 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -631,8 +631,7 @@ class_add_methods (class_t *class, methodlist_t *methods) if (!methods) return; - *class->methods->tail = methods->head; - class->methods->tail = methods->tail; + copy_methods (class->methods, methods); free (methods); methods_set_self_type (class, class->methods); @@ -1260,8 +1259,7 @@ category_add_methods (category_t *category, methodlist_t *methods) { if (!methods) return; - *category->methods->tail = methods->head; - category->methods->tail = methods->tail; + copy_methods (category->methods, methods); free (methods); methods_set_self_type (category->class, category->methods); @@ -1520,8 +1518,7 @@ protocol_add_methods (protocol_t *protocol, methodlist_t *methods) { if (!methods) return; - *protocol->methods->tail = methods->head; - protocol->methods->tail = methods->tail; + copy_methods (protocol->methods, methods); free (methods); } diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 2ae50f39d..4bc819621 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -147,6 +147,12 @@ add_method (methodlist_t *methodlist, method_t *method) if (method->next) internal_error (0, "add_method: method loop detected"); + for (method_t *m = methodlist->head; m; m = m->next) { + if (method_compare (m, method)) { + debug (0, "dropping duplicate method: %s", method->name); + return; + } + } *methodlist->tail = method; methodlist->tail = &method->next; } From 8a4de6fea6159779cce78b51cb18b6d7e31accb4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 22:38:12 +0900 Subject: [PATCH 0491/3664] [qfcc] Fix segmentation fault for parameter errors --- tools/qfcc/source/expr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 967484f95..ea9d64881 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1670,6 +1670,10 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) for (i = arg_count - 1, e = params; i >= 0; i--, e = e->next) { type_t *t = get_type (e); + if (!t) { + return e; + } + if (!type_size (t)) err = error (e, "type of formal parameter %d is incomplete", i + 1); From f025bd96d46ba4416bb9df669473106c39888004 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Mar 2020 23:38:04 +0900 Subject: [PATCH 0492/3664] [qfcc] Copy self param when copying methods Copying methods is done when adding protocols to classes (the current use for adding regular methods is an incorrect solution to a different problem). However, when a method is added to a class, the type of its self parameter is set to be a pointer to the class. Thus, not only does the method need to be copied, the self parameter does too, otherwise the self parameter of methods added via protocols will have their type set to be a pointer to the last class seen adding the protocol. That is, if, while compiling the implementation for class A, but the interface for class B is comes after the interface for class A, and both A and B add protocol P, then all methods in protocol P will have self pointing to B rather than A. @protocol P -method; @end @interface A

@end @interface B

@end @implementation A -method {} // self is B, not A! @end --- tools/qfcc/source/method.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 4bc819621..e296adf3b 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -208,11 +208,21 @@ new_methodlist (void) void copy_methods (methodlist_t *dst, methodlist_t *src) { - method_t *s, *d; + method_t *s, *d; + param_t *self; for (s = src->head; s; s = s->next) { d = malloc (sizeof (method_t)); *d = *s; + // The above is only a shallow copy and thus even though the methods + // are not shared between the source and destination lists, the + // parameters are. Thus, duplicate the self (first) parameter so + // changing its type to match the class into which it is inserted does + // not affect the source list. The rest of the parameters do not need + // to be copied as they will not be altered. + self = malloc (sizeof (param_t)); + *self = *d->params; + d->params = self; d->next = 0; add_method (dst, d); } From 679744fc7d671ad1ec90d08e090229bb5145d298 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 00:11:07 +0900 Subject: [PATCH 0493/3664] [libr] Fix incorrect bounds check on array insert --- ruamoko/lib/Array.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/lib/Array.r b/ruamoko/lib/Array.r index 4673c31d8..bbf5ce883 100644 --- a/ruamoko/lib/Array.r +++ b/ruamoko/lib/Array.r @@ -261,7 +261,7 @@ { local unsigned i; - if (index >= count) // FIXME: need exceptions + if (index > count) // FIXME: need exceptions [self error: "-insertObject:atIndex: index out of range"]; if (count == capacity) { // at capacity, expand From ed04e6fc23b20fdd7e4dc85c7020f82533e3610d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 00:11:54 +0900 Subject: [PATCH 0494/3664] [qfcc] Merge method lists instead of copying This is for adding methods to classes and protocols via their interface, not for adding methods by adding protocols (they still get copied). Slightly more memory efficient. --- tools/qfcc/include/method.h | 2 ++ tools/qfcc/source/class.c | 9 +++------ tools/qfcc/source/method.c | 40 ++++++++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/include/method.h b/tools/qfcc/include/method.h index ef51e1579..6b02bbe00 100644 --- a/tools/qfcc/include/method.h +++ b/tools/qfcc/include/method.h @@ -80,6 +80,8 @@ struct symbol_s *method_symbol (struct class_type_s *class_type, void method_set_param_names (method_t *dst, method_t *src); methodlist_t *new_methodlist (void); +//NOTE frees the source list and any methods not copied +void merge_method_lists (methodlist_t *dst, methodlist_t *src); void copy_methods (methodlist_t *dst, methodlist_t *src); int method_compare (method_t *m1, method_t *m2); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index e4861b8d2..4b331d237 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -631,8 +631,7 @@ class_add_methods (class_t *class, methodlist_t *methods) if (!methods) return; - copy_methods (class->methods, methods); - free (methods); + merge_method_lists (class->methods, methods); methods_set_self_type (class, class->methods); } @@ -1259,8 +1258,7 @@ category_add_methods (category_t *category, methodlist_t *methods) { if (!methods) return; - copy_methods (category->methods, methods); - free (methods); + merge_method_lists (category->methods, methods); methods_set_self_type (category->class, category->methods); } @@ -1518,8 +1516,7 @@ protocol_add_methods (protocol_t *protocol, methodlist_t *methods) { if (!methods) return; - copy_methods (protocol->methods, methods); - free (methods); + merge_method_lists (protocol->methods, methods); } void diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index e296adf3b..d1f8dd5cd 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -205,6 +205,38 @@ new_methodlist (void) return l; } +static int +method_in_list (methodlist_t *method_list, method_t *method) +{ + method_t *m; + + for (m = method_list->head; m; m = m->next) { + if (method_compare (m, method)) { + return 1; + } + } + return 0; +} + +void +merge_method_lists (methodlist_t *dst, methodlist_t *src) +{ + while (src->head) { + method_t *s = src->head; + src->head = s->next; + s->next = 0; + if (method_in_list (dst, s)) { + debug (0, "dropping duplicate method: %s", s->name); + free (s); + } else { + // add_method does the duplicate check + *dst->tail = s; + dst->tail = &s->next; + } + } + free (src); +} + void copy_methods (methodlist_t *dst, methodlist_t *src) { @@ -212,6 +244,10 @@ copy_methods (methodlist_t *dst, methodlist_t *src) param_t *self; for (s = src->head; s; s = s->next) { + if (method_in_list (dst, s)) { + debug (0, "skipping duplicate method: %s", s->name); + continue; + } d = malloc (sizeof (method_t)); *d = *s; // The above is only a shallow copy and thus even though the methods @@ -224,7 +260,9 @@ copy_methods (methodlist_t *dst, methodlist_t *src) *self = *d->params; d->params = self; d->next = 0; - add_method (dst, d); + // add_method does the duplicate check + *dst->tail = d; + dst->tail = &d->next; } } From 50d39d64cbd77071d34a4fd2db33b1f1909ce8be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 09:30:20 +0900 Subject: [PATCH 0495/3664] [qwaq] Link against build ruamoko libs, not installed --- ruamoko/qwaq/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 38584d949..f32d9d536 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -13,7 +13,9 @@ QFCC=$(top_builddir)/tools/qfcc/source/qfcc QCFLAGS=-qq -O -g -Werror QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include +QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) +QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) SUFFIXES=.o .r .r.o: @@ -61,7 +63,7 @@ qwaq_app_dat_SOURCES=qwaq-app.r qwaq-screen.r qwaq-window.r qwaq-view.r qwaq_app_obj=$(qwaq_app_dat_SOURCES:.r=.o) qwaq_app_dep=$(addprefix ./$(DEPDIR)/,$(qwaq_app_obj:.o=.Qo)) qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(qwaq_app_obj) -lr + $(QLINK) -o $@ $(qwaq_app_obj) -lr include $(qwaq_app_dep) # am--include-marker r_depfiles_remade += $(qwaq_app_dep) From 16223098e52a7e981277581bd0df43202f9cb643 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 10:42:05 +0900 Subject: [PATCH 0496/3664] [qfcc] Fix ivar visibility It was broken by the big rewrite and I forgot to fix it. --- tools/qfcc/source/expr.c | 3 ++- tools/qfcc/source/qc-parse.y | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index ea9d64881..dafb49c96 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1202,8 +1202,9 @@ field_expr (expr_t *e1, expr_t *e2) class_t *class = t1->t.fldptr.type->t.class; symbol_t *sym = e2->e.symbol;//FIXME need to check symbol_t *ivar; + int protected = class_access (current_class, class); - ivar = class_find_ivar (class, vis_protected, sym->name); + ivar = class_find_ivar (class, protected, sym->name); if (!ivar) return new_error_expr (); e2->type = ex_value; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 5658382c5..7ae13bd6e 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -706,6 +706,7 @@ struct_decl $1->type = append_type ($1->type, $0.type); $1->type = find_type ($1->type); $1->sy_type = sy_var; + $1->visibility = current_visibility; symtab_addsymbol (current_symtab, $1); } | var_decl @@ -715,6 +716,7 @@ struct_decl $1->type = append_type ($1->type, $0.type); $1->type = find_type ($1->type); $1->sy_type = sy_var; + $1->visibility = current_visibility; symtab_addsymbol (current_symtab, $1); } | var_decl ':' expr %prec COMMA {} @@ -1762,6 +1764,7 @@ ivar_decl_list tab = $$->parent; // preserve the ivars inheritance chain build_struct ('s', 0, $$, 0); $$->parent = tab; + current_visibility = vis_public; } ; From c2138183dd159a2d2ee13288b5f319b7ee582ebf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 10:43:29 +0900 Subject: [PATCH 0497/3664] [libr] Initialize SetIterator the right way I'd written Set.[rh] after the big rewrite so never noticed the access error. --- ruamoko/lib/Set.r | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ruamoko/lib/Set.r b/ruamoko/lib/Set.r index 10cf6397d..06ef95193 100644 --- a/ruamoko/lib/Set.r +++ b/ruamoko/lib/Set.r @@ -27,6 +27,15 @@ string set_as_string (set_t *set) = #0; @implementation SetIterator: Object +- initWithIterator: (set_iter_t *) iter +{ + if (!(self = [super init])) { + return nil; + } + self.iter = iter; + return self; +} + - (SetIterator *) next { if ((iter = set_next (iter))) @@ -84,8 +93,7 @@ string set_as_string (set_t *set) = #0; if (!iter) return nil; - iterator = [[SetIterator alloc] init]; - iterator.iter = iter; + iterator = [[SetIterator alloc] initWithIterator: iter]; return iterator; } From bb25057feb7a51a3420da14e14ca09da0825fc47 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 10:46:28 +0900 Subject: [PATCH 0498/3664] [qwaq] Quickly Workaround Access Qualifications :) --- ruamoko/qwaq/qwaq-screen.h | 1 + ruamoko/qwaq/qwaq-view.h | 1 + ruamoko/qwaq/qwaq-window.h | 1 + 3 files changed, 3 insertions(+) diff --git a/ruamoko/qwaq/qwaq-screen.h b/ruamoko/qwaq/qwaq-screen.h index cbd0a6721..5ded2ecaf 100644 --- a/ruamoko/qwaq/qwaq-screen.h +++ b/ruamoko/qwaq/qwaq-screen.h @@ -10,6 +10,7 @@ @interface Screen: Object { + @public Rect rect; Array *views; Array *event_handlers; diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index e532f9f0b..817ec0ab7 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -9,6 +9,7 @@ @interface View: Object { + @public Rect rect; Rect absRect; Point point; // can't be local :( diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 66c6d440e..ae45d7e72 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -11,6 +11,7 @@ @interface Window: Object { + @public Rect rect; Point point; // FIXME can't be local :( Array *views; From c7cde5f409626609665cbb847df3e0c18c896412 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 10:59:01 +0900 Subject: [PATCH 0499/3664] [qfcc] Pass gcc's purity test *sigh* --- tools/qfcc/source/method.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index d1f8dd5cd..c5bd8b334 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -205,7 +205,7 @@ new_methodlist (void) return l; } -static int +static int __attribute__((pure)) method_in_list (methodlist_t *method_list, method_t *method) { method_t *m; From b8984e5f660b426a5c3a994c1eb565926e801e65 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 13:39:24 +0900 Subject: [PATCH 0500/3664] [qfcc] Fix another infinite loop in the linker I think this should be it for infinite loops caused by undefined symbols. I don't know why I didn't remove this continue when I removed the other. --- tools/qfcc/source/linker.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 5a9d367ce..de107d1b4 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -1119,10 +1119,8 @@ undefined_def (qfo_def_t *def) pr_lineno_t *line; while (func - work->funcs < work->num_funcs) { - if (func->code < 0) { - continue; - } - if ((pr_uint_t) func->code <= reloc->offset) { + if (func->code >= 0 + && (pr_uint_t) func->code <= reloc->offset) { if (!best || reloc->offset - func->code < best_dist) { best = func; best_dist = reloc->offset - func->code; From cdc1f0c5e7429845243311fd563de7eb961cd773 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 15:24:41 +0900 Subject: [PATCH 0501/3664] [libr] Treat ruamoko headers as system headers Now that qfcc actually supports them properly. --- ruamoko/gui/Group.r | 6 +++--- ruamoko/gui/InputLine.r | 6 +++--- ruamoko/gui/Makefile.am | 5 ++++- ruamoko/gui/Pic.r | 6 +++--- ruamoko/gui/Point.r | 2 +- ruamoko/gui/Rect.r | 8 ++++---- ruamoko/gui/Size.r | 2 +- ruamoko/gui/Slider.r | 6 +++--- ruamoko/gui/Text.r | 6 +++--- ruamoko/gui/View.r | 8 ++++---- ruamoko/include/Array.h | 4 ++-- ruamoko/include/AutoreleasePool.h | 2 +- ruamoko/include/Entity.h | 2 +- ruamoko/include/Object.h | 2 +- ruamoko/include/PropertyList.h | 4 ++-- ruamoko/include/Protocol.h | 2 +- ruamoko/include/draw.h | 2 +- ruamoko/include/gui/Group.h | 2 +- ruamoko/include/gui/InputLine.h | 2 +- ruamoko/include/gui/Pic.h | 2 +- ruamoko/include/gui/Rect.h | 4 ++-- ruamoko/include/gui/Slider.h | 2 +- ruamoko/include/gui/Text.h | 2 +- ruamoko/include/gui/View.h | 4 ++-- ruamoko/include/key.h | 2 +- ruamoko/include/msgbuf.h | 2 +- ruamoko/include/plist.h | 2 +- ruamoko/include/qfs.h | 2 +- ruamoko/include/qw_message.h | 2 +- ruamoko/lib/Array.r | 6 +++--- ruamoko/lib/AutoreleasePool.r | 5 ++--- ruamoko/lib/Entity.r | 12 ++++++------ ruamoko/lib/Makefile.am | 5 ++++- ruamoko/lib/Object.r | 4 ++-- ruamoko/lib/PropertyList.r | 2 +- ruamoko/lib/Protocol.r | 2 +- ruamoko/lib/Set.r | 2 +- ruamoko/lib/cbuf.r | 2 +- ruamoko/lib/cmd.r | 2 +- ruamoko/lib/crudefile.r | 2 +- ruamoko/lib/cvar.r | 2 +- ruamoko/lib/debug.r | 2 +- ruamoko/lib/draw.r | 2 +- ruamoko/lib/entities.r | 2 +- ruamoko/lib/gib.r | 2 +- ruamoko/lib/hash.r | 2 +- ruamoko/lib/infokey.r | 2 +- ruamoko/lib/key.r | 2 +- ruamoko/lib/math.r | 2 +- ruamoko/lib/message.r | 2 +- ruamoko/lib/msgbuf.r | 2 +- ruamoko/lib/nq_message.r | 2 +- ruamoko/lib/physics.r | 2 +- ruamoko/lib/plist.r | 2 +- ruamoko/lib/qfile.r | 2 +- ruamoko/lib/qfs.r | 2 +- ruamoko/lib/qw_message.r | 2 +- ruamoko/lib/qw_physics.r | 2 +- ruamoko/lib/qw_sys.r | 2 +- ruamoko/lib/script.r | 2 +- ruamoko/lib/server.r | 2 +- ruamoko/lib/sound.r | 2 +- ruamoko/lib/string.r | 2 +- ruamoko/lib/sv_sound.r | 2 +- ruamoko/lib/system.r | 2 +- 65 files changed, 100 insertions(+), 95 deletions(-) diff --git a/ruamoko/gui/Group.r b/ruamoko/gui/Group.r index 4bcccadf1..56b7303c7 100644 --- a/ruamoko/gui/Group.r +++ b/ruamoko/gui/Group.r @@ -1,6 +1,6 @@ -#include "gui/Group.h" -#include "gui/Point.h" -#include "Array.h" +#include +#include +#include @implementation Group diff --git a/ruamoko/gui/InputLine.r b/ruamoko/gui/InputLine.r index 781e56b78..e4fb8df8a 100644 --- a/ruamoko/gui/InputLine.r +++ b/ruamoko/gui/InputLine.r @@ -1,6 +1,6 @@ -#include "draw.h" -#include "gui/InputLine.h" -#include "gui/Rect.h" +#include +#include +#include inputline_t InputLine_Create (int lines, int size, int prompt) = #0; void InputLine_SetPos (inputline_t il, int x, int y) = #0; diff --git a/ruamoko/gui/Makefile.am b/ruamoko/gui/Makefile.am index e4866e856..91ac97245 100644 --- a/ruamoko/gui/Makefile.am +++ b/ruamoko/gui/Makefile.am @@ -4,7 +4,10 @@ pkglibdir=$(datarootdir)/qfcc/lib QFCC=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide --no-default-paths -QCPPFLAGS=$(AM_CPPFLAGS) +QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include +QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib +QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) +QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) RANLIB=touch diff --git a/ruamoko/gui/Pic.r b/ruamoko/gui/Pic.r index 89cf93950..748393cc5 100644 --- a/ruamoko/gui/Pic.r +++ b/ruamoko/gui/Pic.r @@ -1,6 +1,6 @@ -#include "draw.h" -#include "string.h" -#include "gui/Pic.h" +#include +#include +#include @implementation Pic -(id)init diff --git a/ruamoko/gui/Point.r b/ruamoko/gui/Point.r index c25c72000..91163087b 100644 --- a/ruamoko/gui/Point.r +++ b/ruamoko/gui/Point.r @@ -1,4 +1,4 @@ -#include "gui/Point.h" +#include Point makePoint (int x, int y) { diff --git a/ruamoko/gui/Rect.r b/ruamoko/gui/Rect.r index be1c69384..a7280cea3 100644 --- a/ruamoko/gui/Rect.r +++ b/ruamoko/gui/Rect.r @@ -1,7 +1,7 @@ -#include "Object.h" -#include "gui/Point.h" -#include "gui/Size.h" -#include "gui/Rect.h" +#include +#include +#include +#include Rect makeRect (int x, int y, int w, int h) { diff --git a/ruamoko/gui/Size.r b/ruamoko/gui/Size.r index d4565a33f..da1bf04a9 100644 --- a/ruamoko/gui/Size.r +++ b/ruamoko/gui/Size.r @@ -1,4 +1,4 @@ -#include "gui/Size.h" +#include Size makeSize (int width, int height) { diff --git a/ruamoko/gui/Slider.r b/ruamoko/gui/Slider.r index d43cdcf21..275a64de4 100644 --- a/ruamoko/gui/Slider.r +++ b/ruamoko/gui/Slider.r @@ -1,7 +1,7 @@ -#include "draw.h" +#include -#include "gui/Slider.h" -#include "gui/Rect.h" +#include +#include @implementation Slider diff --git a/ruamoko/gui/Text.r b/ruamoko/gui/Text.r index 731f661ce..6011273d8 100644 --- a/ruamoko/gui/Text.r +++ b/ruamoko/gui/Text.r @@ -1,6 +1,6 @@ -#include "gui/Text.h" -#include "string.h" -#include "draw.h" +#include +#include +#include @implementation Text - (id) init diff --git a/ruamoko/gui/View.r b/ruamoko/gui/View.r index 2accc4fe7..a83ebeb33 100644 --- a/ruamoko/gui/View.r +++ b/ruamoko/gui/View.r @@ -1,7 +1,7 @@ -#include "gui/Size.h" -#include "gui/Point.h" -#include "gui/Rect.h" -#include "gui/View.h" +#include +#include +#include +#include @implementation View diff --git a/ruamoko/include/Array.h b/ruamoko/include/Array.h index 8a9f91f36..113e466a9 100644 --- a/ruamoko/include/Array.h +++ b/ruamoko/include/Array.h @@ -1,8 +1,8 @@ #ifndef __ruamoko_Array_h #define __ruamoko_Array_h -#include "Object.h" -#include "runtime.h" +#include +#include /** The Array class is a general ordered collection class. diff --git a/ruamoko/include/AutoreleasePool.h b/ruamoko/include/AutoreleasePool.h index a02600c9e..c8202e0f0 100644 --- a/ruamoko/include/AutoreleasePool.h +++ b/ruamoko/include/AutoreleasePool.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_AutoreleasePool_h #define __ruamoko_AutoreleasePool_h -#include "Object.h" +#include @class Array; diff --git a/ruamoko/include/Entity.h b/ruamoko/include/Entity.h index 85f304efb..8ff0f568c 100644 --- a/ruamoko/include/Entity.h +++ b/ruamoko/include/Entity.h @@ -30,7 +30,7 @@ #ifndef __ruamoko_Entity_h #define __ruamoko_Entity_h -#include "Object.h" +#include @interface Entity: Object { diff --git a/ruamoko/include/Object.h b/ruamoko/include/Object.h index 23623ef06..475e0bec9 100644 --- a/ruamoko/include/Object.h +++ b/ruamoko/include/Object.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_Object_h #define __ruamoko_Object_h -#include "runtime.h" +#include @class Protocol; diff --git a/ruamoko/include/PropertyList.h b/ruamoko/include/PropertyList.h index 0f255cdfe..3deb99a2b 100644 --- a/ruamoko/include/PropertyList.h +++ b/ruamoko/include/PropertyList.h @@ -1,8 +1,8 @@ #ifndef __ruamoko_PropertyList_h #define __ruamoko_PropertyList_h -#include "plist.h" -#include "Object.h" +#include +#include @interface PLItem: Object { diff --git a/ruamoko/include/Protocol.h b/ruamoko/include/Protocol.h index 2894ee4fa..3d377ab75 100644 --- a/ruamoko/include/Protocol.h +++ b/ruamoko/include/Protocol.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_Protocol_h #define __ruamoko_Protocol_h -#include "Object.h" +#include struct obj_method_description { string name; diff --git a/ruamoko/include/draw.h b/ruamoko/include/draw.h index df4a1470f..ae868ff36 100644 --- a/ruamoko/include/draw.h +++ b/ruamoko/include/draw.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_draw_h #define __ruamoko_draw_h -#include "Object.h" +#include struct _qpic_t { int width; diff --git a/ruamoko/include/gui/Group.h b/ruamoko/include/gui/Group.h index f20cca09c..ccd4baa65 100644 --- a/ruamoko/include/gui/Group.h +++ b/ruamoko/include/gui/Group.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_gui_Group_h #define __ruamoko_gui_Group_h -#include "View.h" +#include /** \addtogroup gui */ ///@{ diff --git a/ruamoko/include/gui/InputLine.h b/ruamoko/include/gui/InputLine.h index 363cc0b8c..c0b14cfb4 100644 --- a/ruamoko/include/gui/InputLine.h +++ b/ruamoko/include/gui/InputLine.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_gui_InputLine_h #define __ruamoko_gui_InputLine_h -#include "View.h" +#include /** \defgroup inputline Low level intputline interface. \ingroup gui diff --git a/ruamoko/include/gui/Pic.h b/ruamoko/include/gui/Pic.h index 9ed9e3380..9bfe29fbc 100644 --- a/ruamoko/include/gui/Pic.h +++ b/ruamoko/include/gui/Pic.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_gui_Pic_h #define __ruamoko_gui_Pic_h -#include "gui/View.h" +#include /** \addtogroup gui */ ///@{ diff --git a/ruamoko/include/gui/Rect.h b/ruamoko/include/gui/Rect.h index 005ce4a70..d1432f460 100644 --- a/ruamoko/include/gui/Rect.h +++ b/ruamoko/include/gui/Rect.h @@ -1,8 +1,8 @@ #ifndef __ruamoko_gui_Rect_h #define __ruamoko_gui_Rect_h -#include "gui/Point.h" -#include "gui/Size.h" +#include +#include /** \addtogroup gui */ ///@{ diff --git a/ruamoko/include/gui/Slider.h b/ruamoko/include/gui/Slider.h index 66710d28e..99840af7e 100644 --- a/ruamoko/include/gui/Slider.h +++ b/ruamoko/include/gui/Slider.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_gui_Slider_h #define __ruamoko_gui_Slider_h -#include "View.h" +#include /** \addtogroup gui */ ///@{ diff --git a/ruamoko/include/gui/Text.h b/ruamoko/include/gui/Text.h index d5654d555..ef389bf9c 100644 --- a/ruamoko/include/gui/Text.h +++ b/ruamoko/include/gui/Text.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_gui_Text_h #define __ruamoko_gui_Text_h -#include "View.h" +#include /** \addtogroup gui */ ///@{ diff --git a/ruamoko/include/gui/View.h b/ruamoko/include/gui/View.h index c2a99e036..3cb51ee67 100644 --- a/ruamoko/include/gui/View.h +++ b/ruamoko/include/gui/View.h @@ -1,8 +1,8 @@ #ifndef __ruamoko_gui_View_h #define __ruamoko_gui_View_h -#include "Object.h" -#include "gui/Rect.h" +#include +#include /** \defgroup gui GUI goo for gooey chewing */ diff --git a/ruamoko/include/key.h b/ruamoko/include/key.h index bc7d04801..f3355b3d2 100644 --- a/ruamoko/include/key.h +++ b/ruamoko/include/key.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_key_h #define __ruamoko_key_h -#include "QF/keys.h" +#include @extern int Key_keydown (int keynum); @extern string Key_SetBinding (string imt, int keynum, string binding); diff --git a/ruamoko/include/msgbuf.h b/ruamoko/include/msgbuf.h index d26ba4de9..172d7338a 100644 --- a/ruamoko/include/msgbuf.h +++ b/ruamoko/include/msgbuf.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_msgbuf_h #define __ruamoko_msgbuf_h -#include "qfile.h" +#include struct msgbuf_s; typedef struct msgbuf_s msgbuf_t; diff --git a/ruamoko/include/plist.h b/ruamoko/include/plist.h index 949419ea9..4544e00ff 100644 --- a/ruamoko/include/plist.h +++ b/ruamoko/include/plist.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_plist_h #define __ruamoko_plist_h -#include "qfile.h" +#include typedef struct plitem_s *plitem_t; typedef enum {QFDictionary, QFArray, QFBinary, QFString} pltype_t; // possible types diff --git a/ruamoko/include/qfs.h b/ruamoko/include/qfs.h index 4a31154f9..379e29ad2 100644 --- a/ruamoko/include/qfs.h +++ b/ruamoko/include/qfs.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_qfs_h #define __ruamoko_qfs_h -#include "qfile.h" +#include struct _qfslist_t { int count; diff --git a/ruamoko/include/qw_message.h b/ruamoko/include/qw_message.h index 5bd7efb0d..60c8587d1 100644 --- a/ruamoko/include/qw_message.h +++ b/ruamoko/include/qw_message.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_qw_message_h #define __ruamoko_qw_message_h -#include "message.h" +#include @extern void multicast (vector where, float set); diff --git a/ruamoko/lib/Array.r b/ruamoko/lib/Array.r index bbf5ce883..842076f72 100644 --- a/ruamoko/lib/Array.r +++ b/ruamoko/lib/Array.r @@ -1,7 +1,7 @@ -#include "math.h" +#include -#include "Array.h" -#include "runtime.h" +#include +#include #define STANDARD_CAPACITY 16 #define ARRAY_MAX_GRANULARITY 100 diff --git a/ruamoko/lib/AutoreleasePool.r b/ruamoko/lib/AutoreleasePool.r index 6d8077cfc..b4aadd36f 100644 --- a/ruamoko/lib/AutoreleasePool.r +++ b/ruamoko/lib/AutoreleasePool.r @@ -1,7 +1,6 @@ -#include "AutoreleasePool.h" -#include "Array+Private.h" +#include -#include "Array.h" +#include #include "Array+Private.h" @static Array *poolStack; diff --git a/ruamoko/lib/Entity.r b/ruamoko/lib/Entity.r index 5cc1f4f11..474bc3db1 100644 --- a/ruamoko/lib/Entity.r +++ b/ruamoko/lib/Entity.r @@ -1,10 +1,10 @@ -#include "Entity.h" +#include -#include "debug.h" -#include "entities.h" -#include "plist.h" -#include "script.h" -#include "string.h" +#include +#include +#include +#include +#include typedef void () void_function; diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index ee2c80ff7..525c20d6c 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -4,7 +4,10 @@ pkglibdir=$(datarootdir)/qfcc/lib QFCC=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QCFLAGS=-qq -O -g -Wall -Wno-integer-divide -Werror --no-default-paths -QCPPFLAGS=$(AM_CPPFLAGS) +QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib +QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) +QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) RANLIB=touch diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index a6b0e9d85..dba6b5071 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -1,5 +1,5 @@ -#include "Object.h" -#include "AutoreleasePool.h" +#include +#include void *PR_FindGlobal (string name) = #0; //FIXME where? diff --git a/ruamoko/lib/PropertyList.r b/ruamoko/lib/PropertyList.r index 0bcfa9850..b65edc85d 100644 --- a/ruamoko/lib/PropertyList.r +++ b/ruamoko/lib/PropertyList.r @@ -1,4 +1,4 @@ -#include "PropertyList.h" +#include @implementation PLItem diff --git a/ruamoko/lib/Protocol.r b/ruamoko/lib/Protocol.r index 715ca30a7..8893d13bb 100644 --- a/ruamoko/lib/Protocol.r +++ b/ruamoko/lib/Protocol.r @@ -1,4 +1,4 @@ -#include "Protocol.h" +#include struct obj_protocol_list { struct obj_protocol_list *next; diff --git a/ruamoko/lib/Set.r b/ruamoko/lib/Set.r index 06ef95193..9e215ec51 100644 --- a/ruamoko/lib/Set.r +++ b/ruamoko/lib/Set.r @@ -1,4 +1,4 @@ -#include "Set.h" +#include void set_del_iter (set_iter_t *set_iter) = #0; set_t *set_new (void) = #0; diff --git a/ruamoko/lib/cbuf.r b/ruamoko/lib/cbuf.r index 496585fd5..f22498f3c 100644 --- a/ruamoko/lib/cbuf.r +++ b/ruamoko/lib/cbuf.r @@ -1,4 +1,4 @@ -#include "cbuf.h" +#include void (string text) Cbuf_AddText = #0; void (string text) Cbuf_InsertText = #0; diff --git a/ruamoko/lib/cmd.r b/ruamoko/lib/cmd.r index 2ecb6d100..ba86632f8 100644 --- a/ruamoko/lib/cmd.r +++ b/ruamoko/lib/cmd.r @@ -1,4 +1,4 @@ -#include "cmd.h" +#include void (string name, void () func) Cmd_AddCommand = #0; int () Cmd_Argc = #0; diff --git a/ruamoko/lib/crudefile.r b/ruamoko/lib/crudefile.r index c8d4b9e27..2987af452 100644 --- a/ruamoko/lib/crudefile.r +++ b/ruamoko/lib/crudefile.r @@ -1,4 +1,4 @@ -#include "crudefile.h" +#include float (string path, string mode) cfopen = #0x000f0000 + 103; void (float desc) cfclose = #0x000f0000 + 104; diff --git a/ruamoko/lib/cvar.r b/ruamoko/lib/cvar.r index 168c38e18..be12b212e 100644 --- a/ruamoko/lib/cvar.r +++ b/ruamoko/lib/cvar.r @@ -1,4 +1,4 @@ -#include "cvar.h" +#include float (string s) cvar = #45; void (string var, string val) cvar_set = #72; diff --git a/ruamoko/lib/debug.r b/ruamoko/lib/debug.r index 844c88eff..7cf9c8895 100644 --- a/ruamoko/lib/debug.r +++ b/ruamoko/lib/debug.r @@ -1,4 +1,4 @@ -#include "debug.h" +#include void abort (void) = #6; void coredump (void) = #28; diff --git a/ruamoko/lib/draw.r b/ruamoko/lib/draw.r index 741857bf5..5aef3ab75 100644 --- a/ruamoko/lib/draw.r +++ b/ruamoko/lib/draw.r @@ -1,4 +1,4 @@ -#include "draw.h" +#include void Draw_FreePic (qpic_t pic) = #0; qpic_t Draw_MakePic (int width, int heiight, string data) = #0; diff --git a/ruamoko/lib/entities.r b/ruamoko/lib/entities.r index f55bd91a7..f49cc9a53 100644 --- a/ruamoko/lib/entities.r +++ b/ruamoko/lib/entities.r @@ -1,4 +1,4 @@ -#include "entities.h" +#include void setmodel (entity e, string m) = #3; void setorigin (entity e, vector o) = #2; diff --git a/ruamoko/lib/gib.r b/ruamoko/lib/gib.r index c3fead7b1..26baacd2f 100644 --- a/ruamoko/lib/gib.r +++ b/ruamoko/lib/gib.r @@ -1,4 +1,4 @@ -#include "gib.h" +#include void GIB_Builtin_Add (string name, void func (int argc, string *argv)) = #0; int (string value) GIB_Return = #0; diff --git a/ruamoko/lib/hash.r b/ruamoko/lib/hash.r index a70d59b10..120d140f9 100644 --- a/ruamoko/lib/hash.r +++ b/ruamoko/lib/hash.r @@ -1,4 +1,4 @@ -#include "hash.h" +#include hashtab_t *Hash_NewTable (int size, string gk (void *ele, void *data), void f (void *ele, void *data), void *ud) = #0; void Hash_SetHashCompare (hashtab_t *tab, unsigned gh (void *ele, void *data), int cmp (void *ele1, void *ele2, void *data)) = #0; diff --git a/ruamoko/lib/infokey.r b/ruamoko/lib/infokey.r index d0049a4fd..a2913df18 100644 --- a/ruamoko/lib/infokey.r +++ b/ruamoko/lib/infokey.r @@ -1,4 +1,4 @@ -#include "infokey.h" +#include string (entity e, string key) infokey = #80; void (entity ent, string key, string value) setinfokey = #0x000f0000 + 102; diff --git a/ruamoko/lib/key.r b/ruamoko/lib/key.r index 19662f138..4b8c1a09a 100644 --- a/ruamoko/lib/key.r +++ b/ruamoko/lib/key.r @@ -1,4 +1,4 @@ -#include "key.h" +#include int Key_keydown (int keynum) = #0; string (string imt, int keynum, string binding) Key_SetBinding = #0; diff --git a/ruamoko/lib/math.r b/ruamoko/lib/math.r index 80db2b710..47624527a 100644 --- a/ruamoko/lib/math.r +++ b/ruamoko/lib/math.r @@ -1,4 +1,4 @@ -#include "math.h" +#include vector v_forward, v_up, v_right; diff --git a/ruamoko/lib/message.r b/ruamoko/lib/message.r index 3136cd678..4ddb31571 100644 --- a/ruamoko/lib/message.r +++ b/ruamoko/lib/message.r @@ -1,4 +1,4 @@ -#include "message.h" +#include void (...) bprint = #23; void (entity client, string s) sprint = #24; diff --git a/ruamoko/lib/msgbuf.r b/ruamoko/lib/msgbuf.r index c1352a43e..1bd4e09b1 100644 --- a/ruamoko/lib/msgbuf.r +++ b/ruamoko/lib/msgbuf.r @@ -1,4 +1,4 @@ -#include "msgbuf.h" +#include msgbuf_t *MsgBuf_New (int size) = #0; void MsgBuf_Delete (msgbuf_t *msgbuf) = #0; diff --git a/ruamoko/lib/nq_message.r b/ruamoko/lib/nq_message.r index 14c06827a..223d1c604 100644 --- a/ruamoko/lib/nq_message.r +++ b/ruamoko/lib/nq_message.r @@ -1,3 +1,3 @@ -#include "nq_message.h" +#include void (vector o, vector d, float color, float count) particle = #48; diff --git a/ruamoko/lib/physics.r b/ruamoko/lib/physics.r index ca19e052f..b42585d00 100644 --- a/ruamoko/lib/physics.r +++ b/ruamoko/lib/physics.r @@ -1,4 +1,4 @@ -#include "physics.h" +#include float trace_allsolid; float trace_startsolid; diff --git a/ruamoko/lib/plist.r b/ruamoko/lib/plist.r index 4b01c653b..40ab2e1fc 100644 --- a/ruamoko/lib/plist.r +++ b/ruamoko/lib/plist.r @@ -1,4 +1,4 @@ -#include "plist.h" +#include plitem_t PL_GetFromFile (QFile file) = #0; plitem_t PL_GetPropertyList (string str) = #0; diff --git a/ruamoko/lib/qfile.r b/ruamoko/lib/qfile.r index 072d72a1c..487beb5c5 100644 --- a/ruamoko/lib/qfile.r +++ b/ruamoko/lib/qfile.r @@ -1,4 +1,4 @@ -#include "qfile.h" +#include int Qrename (string old, string new) = #0; int Qremove (string path) = #0; diff --git a/ruamoko/lib/qfs.r b/ruamoko/lib/qfs.r index b0632d030..d467b09ce 100644 --- a/ruamoko/lib/qfs.r +++ b/ruamoko/lib/qfs.r @@ -1,4 +1,4 @@ -#include "qfs.h" +#include QFile QFS_Open (string path, string mode) = #0; QFile QFS_WOpen (string path, int zip) = #0; diff --git a/ruamoko/lib/qw_message.r b/ruamoko/lib/qw_message.r index fcc714c37..218db52cd 100644 --- a/ruamoko/lib/qw_message.r +++ b/ruamoko/lib/qw_message.r @@ -1,3 +1,3 @@ -#include "qw_message.h" +#include void (vector where, float set) multicast = #82; diff --git a/ruamoko/lib/qw_physics.r b/ruamoko/lib/qw_physics.r index 431e97e63..0ff633569 100644 --- a/ruamoko/lib/qw_physics.r +++ b/ruamoko/lib/qw_physics.r @@ -1,4 +1,4 @@ -#include "qw_physics.h" +#include entity (entity ent) testentitypos = #0x000f0000 + 92; void (vector start, vector mins, vector maxs, vector end, float type, entity passent) checkmove = #0x000f0000 + 98; diff --git a/ruamoko/lib/qw_sys.r b/ruamoko/lib/qw_sys.r index 8d8643576..529f42947 100644 --- a/ruamoko/lib/qw_sys.r +++ b/ruamoko/lib/qw_sys.r @@ -1,3 +1,3 @@ -#include "qw_sys.h" +#include void (entity killer, entity killee) logfrag = #79; diff --git a/ruamoko/lib/script.r b/ruamoko/lib/script.r index 74c120075..e72c4b72a 100644 --- a/ruamoko/lib/script.r +++ b/ruamoko/lib/script.r @@ -1,4 +1,4 @@ -#include "script.h" +#include script_t Script_New (void) = #0; void Script_Delete (script_t script) = #0; diff --git a/ruamoko/lib/server.r b/ruamoko/lib/server.r index 42bd99eb5..b65c3ac7d 100644 --- a/ruamoko/lib/server.r +++ b/ruamoko/lib/server.r @@ -1,4 +1,4 @@ -#include "server.h" +#include void (string s) precache_sound = #19; void (string s) precache_model = #20; diff --git a/ruamoko/lib/sound.r b/ruamoko/lib/sound.r index 863800c81..000ef7047 100644 --- a/ruamoko/lib/sound.r +++ b/ruamoko/lib/sound.r @@ -1,3 +1,3 @@ -#include "sound.h" +#include void (string sound) S_LocalSound = #0; diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index f7eda6b48..36247bf91 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -1,4 +1,4 @@ -#include "string.h" +#include string (float f) ftos = #26; string (vector v) vtos = #27; diff --git a/ruamoko/lib/sv_sound.r b/ruamoko/lib/sv_sound.r index 7880c6b1b..cd4b4f43e 100644 --- a/ruamoko/lib/sv_sound.r +++ b/ruamoko/lib/sv_sound.r @@ -1,4 +1,4 @@ -#include "sound.h" +#include void (entity e, float chan, string samp, float vol, float atten) sound = #8; void (vector pos, string samp, float vol, float atten) ambientsound = #74; diff --git a/ruamoko/lib/system.r b/ruamoko/lib/system.r index 1a387f890..753a41d99 100644 --- a/ruamoko/lib/system.r +++ b/ruamoko/lib/system.r @@ -1,4 +1,4 @@ -#include "system.h" +#include float time; From 6def1fc01c8ac8adafc01c049062a3179b13b698 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 15:26:33 +0900 Subject: [PATCH 0502/3664] [qfcc] Fix a bootstrap warning --- tools/qfcc/test/Makefile.am | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 937686a6e..129240670 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -364,14 +364,14 @@ triangle.run: Makefile build-run include ./$(DEPDIR)/triangle.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/triangle.Qo -typedef_dat_SOURCES=typedef.r -typedef_obj=$(typedef_dat_SOURCES:.r=.qfo) -typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) -typedef.run: Makefile build-run - @$(srcdir)/build-run $@ -include ./$(DEPDIR)/typedef.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/typedef.Qo +#typedef_dat_SOURCES=typedef.r +#typedef_obj=$(typedef_dat_SOURCES:.r=.qfo) +#typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) +# $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) +#typedef.run: Makefile build-run +# @$(srcdir)/build-run $@ +#include ./$(DEPDIR)/typedef.Qo # am--include-marker +#r_depfiles_remade += ./$(DEPDIR)/typedef.Qo vecexpr_dat_SOURCES=vecexpr.r vecexpr_obj=$(vecexpr_dat_SOURCES:.r=.qfo) From 051a572bcc28ef59e847960638c55613e48c6529 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 17:24:53 +0900 Subject: [PATCH 0503/3664] [build] Dependency checking for all ruamoko code Including dependency on qfcc itself. Getting automake to chooch the way I want it to chooch can be a pain in the... see AvE --- ruamoko/cl_menu/Makefile.am | 67 ++++++++++++++++-------- ruamoko/game/Makefile.am | 62 +++++++++++++++------- ruamoko/gui/Makefile.am | 36 +++++++++---- ruamoko/lib/Makefile.am | 98 ++++++++++++++++++++++++---------- ruamoko/scheme/Makefile.am | 101 +++++++++++++++++++++--------------- 5 files changed, 244 insertions(+), 120 deletions(-) diff --git a/ruamoko/cl_menu/Makefile.am b/ruamoko/cl_menu/Makefile.am index 55c21a857..ceaef7fe5 100644 --- a/ruamoko/cl_menu/Makefile.am +++ b/ruamoko/cl_menu/Makefile.am @@ -1,43 +1,66 @@ ## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -pkgdatadir=@sharepath@/QF +AUTOMAKE_OPTIONS= foreign no-exeext QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(QFCC_DEP) -QCFLAGS=-qq -O -g -Wall -Werror -Wno-integer-divide --no-default-paths -QCPPFLAGS=-I. -I$(srcdir) -I$(top_builddir)/ruamoko/include -I$(top_srcdir)/ruamoko/include -I$(top_builddir)/include -I$(top_srcdir)/include -GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi + GZ=@progs_gz@ +menu_libexec=menu.dat +menu_data=menu.plist menu.sym + +pkglibexecdir=@sharepath@/QF +pkgdatadir=@sharepath@/QF + +pkgdata_DATA= $(menu_data) +pkglibexec_PROGRAMS= $(menu_libexec) +EXTRA_PROGRAMS= $(menu_libexec) + +QCFLAGS=-qq -O -g -Wall -Werror -Wno-integer-divide +QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib +QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) +QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) + +MKDIR_P = @MKDIR_P@ +am__mv = mv -f + +GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi # BSD make can't handle $(shell foo) directives, and GNU make can't handle |= # so we have to bite the bullet and pass this to the shell every time. STRIP=`echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c` -menu_data=menu.dat$(GZ) menu.sym$(GZ) menu.plist - -data=$(menu_data) - -pkgdata_DATA= $(data) -EXTRA_DATA= $(menu_data) +SUFFIXES=.o .r +.r.o: + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo menu_src= \ client_menu.r controls_o.r options.r options_util.r servlist.r \ - Frame.r menu.r HUD.r plistmenu.r ../lib/debug.r \ + Frame.r HUD.r menu.r plistmenu.r \ \ CrosshairCvar.r CrosshairView.r CvarColor.r CvarColorView.r \ CvarObject.r CvarRange.r CvarRangeView.r CvarString.r CvarStringView.r \ CvarToggle.r CvarToggleView.r \ MenuGroup.r MouseToggle.r ProxyView.r RunToggle.r SubMenu.r -SUFFIXES=.qfo .r -.r.qfo: - $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -p $(STRIP) -c -o $@ $< -menu_obj=$(menu_src:.r=.qfo) +r_depfiles_remade= -menu.dat$(GZ): $(menu_obj) $(QFCC_DEP) ../lib/libcsqc.a ../lib/libr.a ../gui/libgui.a - $(QFCC) $(QCFLAGS) -p $(STRIP) -o menu.dat $(menu_obj) ../gui/libgui.a ../lib/libcsqc.a ../lib/libr.a - $(GZIP) -menu.sym$(GZ): menu.dat$(GZ) +menu_dat_SOURCES=$(menu_src) +menu_obj=$(menu_src:.r=.o) +menu_dep=$(addprefix ./$(DEPDIR)/,$(menu_obj:.o=.Qo)) +menu.dat: $(menu_obj) $(QFCC_DEP) ../lib/libcsqc.a ../lib/libr.a ../gui/libgui.a + $(QLINK) -p $(STRIP) -o menu.dat $(menu_obj) ../gui/libgui.a ../lib/libcsqc.a ../lib/libr.a +include $(menu_dep) # am--include-marker +r_depfiles_remade += $(menu_dep) + +menu.sym: menu.dat + +$(r_depfiles_remade): + $(MKDIR_P) $(@D) + echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) EXTRA_DIST= $(menu_src) \ CrosshairCvar.h CrosshairView.h CvarColor.h CvarColorView.h CvarObject.h \ @@ -46,4 +69,4 @@ EXTRA_DIST= $(menu_src) \ MenuGroup.h MouseToggle.h ProxyView.h RunToggle.h SubMenu.h client_menu.h \ controls_o.h menu.h options.h options_util.h plistmenu.h servlist.h \ menu.plist -CLEANFILES= *.dat *.sym *.gz *.qfo +CLEANFILES= *.dat *.sym *.gz *.qfo *.o diff --git a/ruamoko/game/Makefile.am b/ruamoko/game/Makefile.am index e1ff2fbf2..95093647f 100644 --- a/ruamoko/game/Makefile.am +++ b/ruamoko/game/Makefile.am @@ -1,35 +1,57 @@ ## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -#FIXME should qf data be installed somewhere other than id1 that gets -#searched after everything else? -pkgdatadir=@sharepath@/id1 +AUTOMAKE_OPTIONS= foreign no-exeext QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(QFCC_DEP) -QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide --no-default-paths -QCPPFLAGS=-I. -I$(srcdir) -I$(top_builddir)/ruamoko/include -I$(top_srcdir)/ruamoko/include -GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi + GZ=@progs_gz@ +game_libexec=game.dat + +pkglibexecdir=@sharepath@/QF + +# this will eventually go into pkglibexecdir, but for now... +noinst_PROGRAMS= $(game_libexec) +EXTRA_PROGRAMS= $(game_libexec) + +QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide +QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include +QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib +QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) +QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) + +MKDIR_P = @MKDIR_P@ +am__mv = mv -f + +GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi # BSD make can't handle $(shell foo) directives, and GNU make can't handle |= # so we have to bite the bullet and pass this to the shell every time. STRIP=`echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c` -data=game.dat$(GZ) - -noinst_DATA= $(data) -EXTRA_DATA= game.dat +SUFFIXES=.o .r +.r.o: + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo game_src= Axe.r GameEntity.r World.r tempent.r -SUFFIXES=.qfo .r -.r.qfo: - $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -p $(STRIP) -c -o $@ $< +r_depfiles_remade= -game_obj=$(game_src:.r=.qfo) -game.dat$(GZ): $(game_obj) ../lib/libr.a ../lib/libqw.a - $(QFCC) $(QCFLAGS) -p $(STRIP) -o game.dat $(game_obj) ../lib/libr.a ../lib/libqw.a ../lib/libr.a - $(GZIP) +game_dat_SOURCES=$(game_src) +game_obj=$(game_src:.r=.o) +game_dep=$(addprefix ./$(DEPDIR)/,$(game_obj:.o=.Qo)) +game.dat: $(game_obj) $(QFCC_DEP) ../lib/libr.a ../lib/libqw.a + $(QLINK) -p $(STRIP) -o game.dat $(game_obj) ../lib/libr.a ../lib/libqw.a ../lib/libr.a +include $(game_dep) # am--include-marker +r_depfiles_remade += $(game_dep) + +game.sym: game.dat + +$(r_depfiles_remade): + $(MKDIR_P) $(@D) + echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) EXTRA_DIST= $(game_src) Axe.h GameEntity.h tempent.h Weapon.h World.h -CLEANFILES= *.dat *.sym *.gz *.qfo +CLEANFILES= *.dat *.sym *.gz *.o *.qfo diff --git a/ruamoko/gui/Makefile.am b/ruamoko/gui/Makefile.am index 91ac97245..35d2624df 100644 --- a/ruamoko/gui/Makefile.am +++ b/ruamoko/gui/Makefile.am @@ -1,30 +1,48 @@ AUTOMAKE_OPTIONS= foreign +QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) +QFCC=$(QFCC_DEP) + +gui_libs=libgui.a +libs=$(gui_libs) + pkglibdir=$(datarootdir)/qfcc/lib +pkglib_LIBRARIES= $(libs) +EXTRA_LIBRARIES= $(gui_libs) + QFCC=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide --no-default-paths QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) + +MKDIR_P = @MKDIR_P@ +am__mv = mv -f + PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) RANLIB=touch -AM_CPPFLAGS= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include - -gui_libs=libgui.a -libs=$(gui_libs) - -pkglib_LIBRARIES= $(libs) -EXTRA_LIBRARIES= $(gui_libs) - -SUFFIXES= .qfo .r .qc +SUFFIXES= .o .r .r.o: $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -c -o $@ $< +r_depfiles_remade= + libgui_a_SOURCES= \ Group.r InputLine.r Pic.r Point.r Rect.r Size.r Slider.r Text.r View.r +libgui_a_obj=$(libgui_a_SOURCES:.r=.o) +libgui_a_dep=$(addprefix ./$(DEPDIR)/,$(libgui_a_obj:.o=.Qo)) libgui_a_AR= $(PAK) -cf +include $(libgui_a_dep) # am--include-marker +r_depfiles_remade += $(libgui_a_dep) + +$(r_depfiles_remade): + $(MKDIR_P) $(@D) + echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) + CLEANFILES= *.qfo *.o diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index 525c20d6c..8a66a3839 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -1,53 +1,95 @@ AUTOMAKE_OPTIONS= foreign -pkglibdir=$(datarootdir)/qfcc/lib - -QFCC=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) -QCFLAGS=-qq -O -g -Wall -Wno-integer-divide -Werror --no-default-paths -QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include -QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib -QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) -QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) -PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) -RANLIB=touch - -AM_CPPFLAGS= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include - -noinst_HEADERS= \ - Array+Private.h +QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) +QFCC=$(QFCC_DEP) ruamoko_libs=libr.a libqw.a libnq.a libcsqc.a libs=$(ruamoko_libs) +pkglibdir=$(datarootdir)/qfcc/lib + pkglib_LIBRARIES= $(libs) EXTRA_LIBRARIES= $(ruamoko_libs) -SUFFIXES= .o .r .qc +noinst_HEADERS= \ + Array+Private.h + +QCFLAGS=-qq -O -g -Wall -Wno-integer-divide -Werror +QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib +QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) +QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) + +MKDIR_P = @MKDIR_P@ +am__mv = mv -f + +PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) +RANLIB=touch + +SUFFIXES= .o .r .r.o: - $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -c -o $@ $< -.qc.o: - $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -c -o $@ $< + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo + +r_depfiles_remade= libr_a_SOURCES=\ cbuf.r cmd.r cvar.r hash.r msgbuf.r plist.r qfile.r qfs.r script.r \ sound.r string.r math.r types.r \ Object.r Protocol.r \ AutoreleasePool.r Array.r Array+Private.r Entity.r PropertyList.r Set.r +libr_a_obj=$(libr_a_SOURCES:.r=.o) +libr_a_dep=$(addprefix ./$(DEPDIR)/,$(libr_a_obj:.o=.Qo)) libr_a_AR=$(PAK) -cf +include $(libr_a_dep) # am--include-marker +r_depfiles_remade += $(libr_a_dep) -libqw_a_SOURCES=\ - crudefile.r debug.r entities.r infokey.r math.r message.r \ - physics.r qw_message.r qw_physics.r qw_sys.r \ - server.r sv_sound.r system.r +common_src=debug.r system.r +server_src= \ + crudefile.r entities.r infokey.r message.r \ + physics.r server.r sv_sound.r +libqw_a_src= \ + qw_message.r qw_physics.r qw_sys.r +libnq_a_src= \ + nq_message.r +libcsqc_a_src= draw.r gib.r key.r + +common_obj=$(common_src:.r=.o) +common_dep=$(addprefix ./$(DEPDIR)/,$(common_obj:.o=.Qo)) +include $(common_dep) # am--include-marker +r_depfiles_remade += $(common_dep) + +server_obj=$(server_src:.r=.o) +server_dep=$(addprefix ./$(DEPDIR)/,$(server_obj:.o=.Qo)) +include $(server_dep) # am--include-marker +r_depfiles_remade += $(server_dep) + +libqw_a_SOURCES=$(libqw_a_src) $(common_src) $(server_src) math.r +libqw_a_obj=$(libqw_a_src:.r=.o) +libqw_a_dep=$(addprefix ./$(DEPDIR)/,$(libqw_a_obj:.o=.Qo)) libqw_a_AR=$(PAK) -cf +include $(libqw_a_dep) # am--include-marker +r_depfiles_remade += $(libqw_a_dep) -libnq_a_SOURCES=\ - crudefile.r debug.r entities.r infokey.r math.r message.r \ - nq_message.r physics.r server.r sv_sound.r system.r +libnq_a_SOURCES=$(libnq_a_src) $(common_src) $(server_src) math.r +libnq_a_obj=$(libnq_a_src:.r=.o) +libnq_a_dep=$(addprefix ./$(DEPDIR)/,$(libnq_a_obj:.o=.Qo)) libnq_a_AR=$(PAK) -cf +include $(libnq_a_dep) # am--include-marker +r_depfiles_remade += $(libnq_a_dep) -libcsqc_a_SOURCES= \ - debug.r draw.r gib.r key.r system.r +libcsqc_a_SOURCES=$(libcsqc_a_src) $(common_src) +libcsqc_a_obj=$(libcsqc_a_src:.r=.o) +libcsqc_a_dep=$(addprefix ./$(DEPDIR)/,$(libcsqc_a_obj:.o=.Qo)) libcsqc_a_AR= $(PAK) -cf +include $(libcsqc_a_dep) # am--include-marker +r_depfiles_remade += $(libcsqc_a_dep) + +$(r_depfiles_remade): + $(MKDIR_P) $(@D) + echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) CLEANFILES= *.qfo *.o diff --git a/ruamoko/scheme/Makefile.am b/ruamoko/scheme/Makefile.am index 75f784ef5..f62c36191 100644 --- a/ruamoko/scheme/Makefile.am +++ b/ruamoko/scheme/Makefile.am @@ -1,30 +1,75 @@ -AUTOMAKE_OPTIONS= foreign - -pkglibdir=$(datarootdir)/qfcc/lib +AUTOMAKE_OPTIONS= foreign no-exeext QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(QFCC_DEP) -QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide --no-default-paths -QCPPFLAGS=$(AM_CPPFLAGS) + +GZ=@progs_gz@ +scheme_libs=libscheme.a +scheme_libexec=main.dat + +pkglibdir=$(datarootdir)/qfcc/lib +#FIXME where to put pkglibexec? +#pkglibexecdir=$(datarootdir)/qfcc/bin + +pkglib_LIBRARIES= $(scheme_libs) +EXTRA_LIBRARIES= $(scheme_libs) + +noinst_PROGRAMS= $(scheme_libexec) +EXTRA_PROGRAMS = $(scheme_libexec) + +QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide +QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include +QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib +QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) +QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) + +MKDIR_P = @MKDIR_P@ +am__mv = mv -f + PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi -GZ=@progs_gz@ # BSD make can't handle $(shell foo) directives, and GNU make can't handle |= # so we have to bite the bullet and pass this to the shell every time. STRIP=`echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c` - RANLIB=touch -AM_CPPFLAGS= -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +SUFFIXES=.o .r +.r.o: + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo -scheme_libs=libscheme.a -libs=$(scheme_libs) -data=$(scheme_data) +r_depfiles_remade= -pkglib_LIBRARIES= $(libs) -EXTRA_LIBRARIES= $(scheme_libs) -#pkgdata_DATA= $(data) -EXTRA_DATA = $(scheme_data) +libscheme_a_SOURCES=\ + SchemeObject.r Cons.r Number.r SchemeString.r Symbol.r Lexer.r Parser.r \ + Nil.r Procedure.r Primitive.r Lambda.r Scope.r Instruction.r builtins.r \ + Frame.r CompiledCode.r Compiler.r Continuation.r Machine.r Void.r \ + Error.r Boolean.r BaseContinuation.r +libscheme_a_obj=$(libscheme_a_SOURCES:.r=.o) +libscheme_a_dep=$(addprefix ./$(DEPDIR)/,$(libscheme_a_obj:.o=.Qo)) +libscheme_a_AR=$(PAK) -cf +include $(libscheme_a_dep) # am--include-marker +r_depfiles_remade += $(libscheme_a_dep) + +scheme_src=\ + main.r defs.r + +main_dat_SOURCES=$(scheme_src) +main_obj=$(scheme_src:.r=.o) +main_dep=$(addprefix ./$(DEPDIR)/,$(main_obj:.o=.Qo)) +main.dat: $(main_obj) $(QFCC_DEP) libscheme.a ../lib/libcsqc.a ../lib/libr.a + $(QLINK) -p $(STRIP) -o main.dat $(main_obj) libscheme.a ../lib/libcsqc.a ../lib/libr.a +include $(main_dep) # am--include-marker +r_depfiles_remade += $(main_dep) + +main.sym: main.dat + +$(r_depfiles_remade): + $(MKDIR_P) $(@D) + echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) EXTRA_DIST = \ BaseContinuation.h Boolean.h CompiledCode.h Compiler.h Cons.h \ @@ -34,30 +79,4 @@ EXTRA_DIST = \ debug.h defs.h state.h \ \ main.r defs.r - -SUFFIXES=.qc .qfo .r -.r.qfo: - $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -p $(STRIP) -c -o $@ $< -.r.o: - $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -p $(STRIP) -c -o $@ $< - -libscheme_a_SOURCES=\ - SchemeObject.r Cons.r Number.r SchemeString.r Symbol.r Lexer.r Parser.r \ - Nil.r Procedure.r Primitive.r Lambda.r Scope.r Instruction.r builtins.r \ - Frame.r CompiledCode.r Compiler.r Continuation.r Machine.r Void.r \ - Error.r Boolean.r BaseContinuation.r -libscheme_a_AR=$(PAK) -cf - -scheme_data=\ - main.dat$(GZ) - -scheme_src=\ - main.r defs.r - -scheme_obj=$(scheme_src:.qc=.o) - -main.dat$(GZ): $(scheme_obj) $(QFCC_DEP) ../lib/libcsqc.a ../lib/libr.a libscheme.a - $(QFCC) $(QCFLAGS) -p $(STRIP) -o main.dat $(scheme_obj) libscheme.a ../lib/libcsqc.a ../lib/libr.a - $(GZIP) - CLEANFILES= *.dat *.sym *.gz *.qfo *.o From b186332da0ca011a1e7c296cb5482890b122cfd9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 17:32:48 +0900 Subject: [PATCH 0504/3664] [qfcc] Make initialization of external vars an error --- tools/qfcc/source/def.c | 4 ++-- tools/qfcc/source/qc-parse.y | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 82e88c5ae..c0332be60 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -575,7 +575,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, internal_error (0, "half defined var"); if (storage == sc_extern) { if (init) - warning (0, "initializing external variable"); + error (0, "initializing external variable"); return; } if (init && check->s.def->initialized) { @@ -611,7 +611,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, init_field_def (sym->s.def, init, storage); if (storage == sc_extern) { if (init) - warning (0, "initializing external variable"); + error (0, "initializing external variable"); return; } if (!init) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 7ae13bd6e..3fac0f926 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1021,6 +1021,9 @@ overloaded_identifier non_code_func : '=' '#' expr { + if ($-1.storage == sc_extern) { + error (0, "initializing external variable"); + } build_builtin_function ($0, $3, 0); } | '=' expr From 7976eec2ce6b2e099ad7e020459298c566ba5170 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 17:35:14 +0900 Subject: [PATCH 0505/3664] [scheme] Clean up a pile of rotten bits --- ruamoko/scheme/SchemeObject.h | 1 + ruamoko/scheme/defs.h | 22 +++++++++++----------- ruamoko/scheme/defs.r | 2 +- ruamoko/scheme/main.r | 35 +++++++++++++++++++---------------- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/ruamoko/scheme/SchemeObject.h b/ruamoko/scheme/SchemeObject.h index 262c700f4..e831b50bd 100644 --- a/ruamoko/scheme/SchemeObject.h +++ b/ruamoko/scheme/SchemeObject.h @@ -14,6 +14,7 @@ int line; string source; } ++ (void) finishCollecting; + (void) collectCheckPoint; - (void) mark; - (void) markReachable; diff --git a/ruamoko/scheme/defs.h b/ruamoko/scheme/defs.h index a1d691684..7f1e4289c 100644 --- a/ruamoko/scheme/defs.h +++ b/ruamoko/scheme/defs.h @@ -1,13 +1,13 @@ -@extern void (string str) print = #0; -@extern int () errno = #0; -@extern string (int err) strerror = #0; -@extern int (...) open = #0; // string path, float flags[, float mode] -@extern int (int handle) close = #0; -@extern string read (int handle, int count, int *result) = #0; -@extern int (int handle, string buffer, int count) write = #0; -@extern int (int handle, int pos, int whence) seek = #0; +@extern void (string str) print; +@extern int () errno; +@extern string (int err) strerror; +@extern int (...) open; // string path, float flags[, float mode] +@extern int (int handle) close; +@extern string read (int handle, int count, int *result); +@extern int (int handle, string buffer, int count) write; +@extern int (int handle, int pos, int whence) seek; -@extern void() traceon = #0; // turns statment trace on -@extern void() traceoff = #0; +@extern void() traceon; // turns statment trace on +@extern void() traceoff; -@extern void (...) printf = #0; +@extern void (...) printf; diff --git a/ruamoko/scheme/defs.r b/ruamoko/scheme/defs.r index 943ef9173..1c638232d 100644 --- a/ruamoko/scheme/defs.r +++ b/ruamoko/scheme/defs.r @@ -3,7 +3,7 @@ int () errno = #0; string (int err) strerror = #0; int (...) open = #0; // string path, float flags[, float mode] int (int handle) close = #0; -string (int handle, int count, int []result) read = #0; +string read (int handle, int count, int *result) = #0; int (int handle, string buffer, int count) write = #0; int (int handle, int pos, int whence) seek = #0; diff --git a/ruamoko/scheme/main.r b/ruamoko/scheme/main.r index fb1fa3e33..be7d8bca6 100644 --- a/ruamoko/scheme/main.r +++ b/ruamoko/scheme/main.r @@ -22,23 +22,23 @@ string readfile (string filename) str_copy(res, acc); return res; } - -int main (int argc, string []argv) +int main (int argc, string *argv) { - local Parser parser; - local CompiledCode code; - local Compiler comp; - local Machine vm; - local Lambda lm; - local SchemeObject stuff, res; + local Parser *parser; + local CompiledCode *code; + local Compiler *comp; + local Machine *vm; + local Lambda *lm; + local SchemeObject *stuff, *res; + local Error *err; if (argc < 1) { return -1; } //traceon(); - + parser = [Parser newFromSource: readfile(argv[1]) file: argv[1]]; vm = [Machine new]; [vm makeRootCell]; @@ -46,26 +46,29 @@ int main (int argc, string []argv) builtin_addtomachine (vm); while ((stuff = [parser read])) { if ([stuff isError]) { - printf(">> %s: %i\n", [stuff source], [stuff line]); - printf(">> Error (%s): %s\n", [stuff type], [stuff message]); + err = (Error *) stuff; + printf(">> %s: %i\n", [err source], [err line]); + printf(">> Error (%s): %s\n", [err type], [err message]); return -1; } comp = [Compiler newWithLambda: cons ([Symbol forString: "lambda"], cons ([Nil nil], cons(stuff, [Nil nil]))) scope: nil]; - code = (CompiledCode) [comp compile]; + code = (CompiledCode *) [comp compile]; if ([code isError]) { - printf(">> %s: %i\n", [code source], [code line]); - printf(">> Error (%s): %s\n", [code type], [code message]); + err = (Error *) code; + printf(">> %s: %i\n", [err source], [err line]); + printf(">> Error (%s): %s\n", [err type], [err message]); return -1; } lm = [Lambda newWithCode: code environment: nil]; [lm invokeOnMachine: vm]; res = [vm run]; if ([res isError]) { - printf(">> %s: %i\n", [res source], [res line]); - printf(">> Error (%s): %s\n", [res type], [res message]); + err = (Error *) res; + printf(">> %s: %i\n", [err source], [err line]); + printf(">> Error (%s): %s\n", [err type], [err message]); return -1; } [vm reset]; From c58cf2c2d059a585c5e941418d2ea66b6f404986 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 21:30:47 +0900 Subject: [PATCH 0506/3664] [qwaq] Fail at object oriented design 101 This is horrible, doesn't work, isn't really the direction I want to go (that became apparent while implementing Screen's handleEvent) and crashes anyway (Array and not-id...) *sigh* Still, this does have some good stuff in it, and it pushed qfcc along some more. --- ruamoko/qwaq/event.h | 6 +++- ruamoko/qwaq/qwaq-app.r | 12 +++++--- ruamoko/qwaq/qwaq-curses.c | 61 ++++++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-curses.h | 2 ++ ruamoko/qwaq/qwaq-draw.h | 2 ++ ruamoko/qwaq/qwaq-rect.h | 2 +- ruamoko/qwaq/qwaq-screen.h | 5 ++- ruamoko/qwaq/qwaq-screen.r | 63 +++++++++++++++++++++++++++++++++++++- ruamoko/qwaq/qwaq-view.h | 1 + ruamoko/qwaq/qwaq-view.r | 11 +++++++ ruamoko/qwaq/qwaq-window.h | 4 +-- ruamoko/qwaq/qwaq-window.r | 22 +++++++++++++ 12 files changed, 180 insertions(+), 11 deletions(-) diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index f494234a9..9eca5158e 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -37,11 +37,15 @@ typedef struct qwaq_event_s { -handleEvent: (struct qwaq_event_s *) event; @end -@protocol TakeFocus +@protocol HandleFocusedEvent -takeFocus; -loseFocus; @end +@protocol HandleMouseEvent +-(struct Rect_s *)getRect; +@end + #endif #endif//__qwaq_event_h diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index e100ae69e..ed6339faf 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -37,15 +37,15 @@ arp_end (void) init_pair (2, COLOR_WHITE, COLOR_BLACK); screen = [[Screen screen] retain]; [screen setBackground: COLOR_PAIR (1)]; - Rect r = screen.rect; - wprintf (screen.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + Rect r = *[screen getRect]; + [screen printf:"%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen]; r.xpos = r.xlen / 4; r.ypos = r.ylen / 4; r.xlen /= 2; r.ylen /= 2; - wprintf (screen.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); - wprintf (screen.window, "%d\n", acs_char(ACS_HLINE)); - mvwaddch(screen.window, 4, 4, acs_char(ACS_HLINE)); + [screen printf:"%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen]; + [screen printf:"%d\n", acs_char(ACS_HLINE)]; + [screen addch: acs_char(ACS_HLINE) atX:4 Y:4]; Window *w; [screen add: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; //wprintf (w.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); @@ -102,6 +102,7 @@ window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; void destroy_window (window_t win) = #0; void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; void wprintf (window_t win, string fmt, ...) = #0; +void wvprintf (window_t win, string fmt, @va_list args) = #0; void wrefresh (window_t win) = #0; void mvwaddch (window_t win, int x, int y, int ch) = #0; int get_event (qwaq_event_t *event) = #0; @@ -109,6 +110,7 @@ int max_colors (void) = #0; int max_color_pairs (void) = #0; int init_pair (int pair, int f, int b) = #0; void wbkgd (window_t win, int ch) = #0; +void scrollok (window_t win, int flag) = #0; int acs_char (int acs) = #0; panel_t create_panel (window_t window) = #0; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index f33e01a5a..c03a38542 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -72,6 +72,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_wrefresh, qwaq_cmd_init_pair, qwaq_cmd_wbkgd, + qwaq_cmd_scrollok, } qwaq_commands; #define RING_BUFFER(type, size) \ @@ -523,6 +524,16 @@ cmd_wbkgd (qwaq_resources_t *res) wbkgd (window->win, ch); } +static void +cmd_scrollok (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int flag = RB_PEEK_DATA (res->command_queue, 3); + + window_t *window = get_window (res, __FUNCTION__, window_id); + scrollok (window->win, flag); +} + static void process_commands (qwaq_resources_t *res) { @@ -585,6 +596,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_wbkgd: cmd_wbkgd (res); break; + case qwaq_cmd_scrollok: + cmd_scrollok (res); + break; } RB_DROP_DATA (res->command_queue, RB_PEEK_DATA (res->command_queue, 1)); } @@ -881,6 +895,37 @@ bi_wprintf (progs_t *pr) } } +static void +bi_wvprintf (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int window_id = P_INT (pr, 0); + const char *fmt = P_GSTRING (pr, 1); + __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 2); + pr_type_t *list_start = PR_GetPointer (pr, args->list); + pr_type_t **list = alloca (args->count); + + for (int i = 0; i < args->count; i++) { + list[i] = list_start + i * pr->pr_param_size; + } + + if (get_window (res, __FUNCTION__, window_id)) { + int string_id = acquire_string (res); + dstring_t *print_buffer = res->strings + string_id; + int command[] = { + qwaq_cmd_waddstr, 0, + window_id, string_id + }; + + command[1] = CMD_SIZE(command); + + dstring_clearstr (print_buffer); + PR_Sprintf (pr, print_buffer, "waddstr", fmt, args->count, list); + + qwaq_submit_command (res, command); + } +} + static void bi_mvwaddch (progs_t *pr) { @@ -963,6 +1008,20 @@ bi_wbkgd (progs_t *pr) } } +static void +bi_scrollok (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int window_id = P_INT (pr, 0); + int flag = P_INT (pr, 1); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_scrollok, 0, window_id, flag, }; + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} + static const char qwaq_acs_char_map[] = "lmkjtuvwqxnos`afg~,+.-hi0pryz{|}"; static void bi_acs_char (progs_t *pr) @@ -1029,6 +1088,7 @@ static builtin_t builtins[] = { {"doupdate", bi_doupdate, -1}, {"mvwprintf", bi_mvwprintf, -1}, {"wprintf", bi_wprintf, -1}, + {"wvprintf", bi_wvprintf, -1}, {"mvwaddch", bi_mvwaddch, -1}, {"wrefresh", bi_wrefresh, -1}, {"get_event", bi_get_event, -1}, @@ -1036,6 +1096,7 @@ static builtin_t builtins[] = { {"max_color_pairs", bi_max_color_pairs, -1}, {"init_pair", bi_init_pair, -1}, {"wbkgd", bi_wbkgd, -1}, + {"scrollok", bi_scrollok, -1}, {"acs_char", bi_acs_char, -1}, {0} }; diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index bf5d24191..e9574e764 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -75,6 +75,7 @@ typedef struct panel_s *panel_t; @extern void destroy_window (window_t win); @extern void mvwprintf (window_t win, int x, int y, string fmt, ...); @extern void wprintf (window_t win, string fmt, ...); +@extern void wvprintf (window_t win, string fmt, @va_list args); @extern void wrefresh (window_t win); @extern void mvwaddch (window_t win, int x, int y, int ch); @@ -94,6 +95,7 @@ typedef struct panel_s *panel_t; @extern int max_color_pairs (void); @extern int init_pair (int pair, int f, int b); @extern void wbkgd (window_t win, int ch); +@extern void scrollok (window_t win, int flag); @extern int acs_char (int acs); #endif diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index 4abac3e55..7b614a29e 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -3,6 +3,8 @@ @protocol Draw -draw; +-redraw; +-setParent: parent; @end #endif diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index 0c26b5817..c679352fc 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -1,7 +1,7 @@ #ifndef __qwaq_rect_h #define __qwaq_rect_h -typedef struct { +typedef struct Rect_s { int xpos; int ypos; int xlen; diff --git a/ruamoko/qwaq/qwaq-screen.h b/ruamoko/qwaq/qwaq-screen.h index 5ded2ecaf..8c83abb6e 100644 --- a/ruamoko/qwaq/qwaq-screen.h +++ b/ruamoko/qwaq/qwaq-screen.h @@ -10,16 +10,19 @@ @interface Screen: Object { - @public Rect rect; Array *views; Array *event_handlers; + Array *focused_handlers; + Array *mouse_handlers; + Array *mouse_handler_rects; View *focusedView; struct window_s *window; } +(Screen *) screen; -add: obj; -setBackground: (int) ch; +-printf: (string) fmt, ...; @end #endif//__qwaq_screen_h diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index 770104c64..0c8573a83 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -1,3 +1,4 @@ +#include #include "qwaq-curses.h" #include "qwaq-screen.h" @@ -14,7 +15,11 @@ } views = [[Array array] retain]; event_handlers = [[Array array] retain]; + focused_handlers = [[Array array] retain]; + mouse_handlers = [[Array array] retain]; + mouse_handler_rects = [[Array array] retain]; window = stdscr; + scrollok (window, 1); rect = getwrect (window); return self; } @@ -22,10 +27,22 @@ -add: obj { if ([obj conformsToProtocol: @protocol (Draw)]) { + // "top" objects are drawn last [views addObject: obj]; + [obj setParent: self]; + } + if ([obj conformsToProtocol: @protocol (HandleFocusedEvent)]) { + // want "top" objects to respond first + [focused_handlers insertObject: obj atIndex: 0]; + } + if ([obj conformsToProtocol: @protocol (HandleMouseEvent)]) { + // "top" objects respond first, but the array is searched in reverse + [mouse_handlers addObject: obj]; + [mouse_handler_rects addObject: (id) [obj getRect]]; } if ([obj conformsToProtocol: @protocol (HandleEvent)]) { - [event_handlers addObject: obj]; + // want "top" objects to respond first + [event_handlers insertObject: obj atIndex: 0]; } return self; } @@ -38,6 +55,25 @@ -handleEvent: (qwaq_event_t *) event { + switch (event.event_type) { + case qe_none: + break; + case qe_key: + case qe_command: + [focused_handlers + makeObjectsPerformSelector: @selector(handleEvent:) + withObject: (id) event]; + break; + case qe_mouse: + Point p = { event.e.mouse.x, event.e.mouse.y }; + for (int i = [mouse_handler_rects count]; i-->0; ) { + //if (rectContainsPoint((Rect*)mouse_handler_rects._objs[i], &p)) { + // [mouse_handlers._objs[i] handleEvent: event]; + // break; + //} + } + break; + } return self; } @@ -49,4 +85,29 @@ return self; } +-redraw +{ + [self error:"hmm"]; + update_panels (); + doupdate (); + return self; +} + +-printf: (string) fmt, ... +{ + wvprintf (window, fmt, @args); + return self; +} + +-addch: (int) ch atX: (int) x Y: (int) y +{ + mvwaddch(window, x, y, ch); + return self; +} + +-setParent: parent +{ + return self; +} + @end diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 817ec0ab7..e7c0db85e 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -13,6 +13,7 @@ Rect rect; Rect absRect; Point point; // can't be local :( + id parent; struct window_s *window; } -initWithRect: (Rect) rect; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 8cf37c53d..bc218630f 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -33,6 +33,17 @@ rectContainsPoint (Rect *rect, Point *point) return self; } +-setParent: parent +{ + self.parent = parent; + return self; +} + +-redraw +{ + return [parent redraw]; +} + @end Rect getwrect (window_t window) = #0; diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index ae45d7e72..19921301a 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -9,10 +9,10 @@ #include "qwaq-draw.h" #include "qwaq-rect.h" -@interface Window: Object +@interface Window: Object { - @public Rect rect; + id parent; Point point; // FIXME can't be local :( Array *views; View *focusedView; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 493a6ccff..7e201aa9a 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -17,6 +17,7 @@ if (!(self = [super init])) { return nil; } + views = [[Array array] retain]; self.rect = rect; window = create_window (rect.xpos, rect.ypos, rect.xlen, rect.ylen); panel = create_panel (window); @@ -27,6 +28,9 @@ { switch (event.event_type) { case qe_mouse: + mvwprintf(window, 0, 3, "%2d %2d %08x", + event.e.mouse.x, event.e.mouse.y, event.e.mouse.buttons); + [self redraw]; point.x = event.e.mouse.x; point.y = event.e.mouse.y; for (int i = [views count]; i--> 0; ) { @@ -60,6 +64,7 @@ view.absRect.xpos = view.rect.xpos + rect.xpos; view.absRect.ypos = view.rect.ypos + rect.ypos; view.window = window; + [view setParent: self]; return self; } @@ -96,6 +101,23 @@ } } } + [views makeObjectsPerformSelector: @selector (draw)]; return self; } + +-(Rect *) getRect +{ + return ▭ +} + +-setParent: parent +{ + self.parent = parent; + return self; +} + +-redraw +{ + return [parent redraw]; +} @end From de01cff70ed2e1b1490b5c79cab11f064b0e9810 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Mar 2020 22:22:53 +0900 Subject: [PATCH 0507/3664] [build] Install QF/keys.h into qfcc's include directory As well as $prefix/include, of course. This fixes the problem with external ruamoko builds failing due to keys.h and qfcc's "lockdown" on system headers. --- config.d/build_control.m4 | 8 ++++++++ include/QF/Makefile.am | 11 ++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 98517088e..88b58e610 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -254,7 +254,15 @@ QF_PROCESS_NEED_DIRS(ruamoko,[qwaq]) if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) + qfcc_include_qf="\$(qfcc_include_qf)" fi +QF_SUBST(qfcc_include_qf) + +if test x"${top_need_libs}" = xyes; then + include_qf="\$(include_qf)" +fi +QF_SUBST(include_qf) + progs_gz= if test "$HAVE_ZLIB" = "yes"; then progs_gz=".gz" diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am index 3041d64d6..724d192df 100644 --- a/include/QF/Makefile.am +++ b/include/QF/Makefile.am @@ -1,6 +1,9 @@ AUTOMAKE_OPTIONS = foreign pkgincludedir = $(includedir)/QF -nobase_pkginclude_HEADERS = \ +#for header files that qfcc (ruamoko) will use +pkgdatadir = $(datarootdir)/qfcc/include/QF + +include_qf= \ alloc.h bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \ console.h crc.h csqc.h cvar.h dstring.h draw.h gib.h hash.h \ idparse.h image.h in_event.h info.h input.h iqm.h joystick.h keys.h \ @@ -26,3 +29,9 @@ nobase_pkginclude_HEADERS = \ \ plugin/cd.h plugin/console.h plugin/general.h plugin/input.h \ plugin/snd_output.h plugin/snd_render.h plugin/vid_render.h + +qfcc_include_qf=keys.h +nobase_pkginclude_HEADERS = @include_qf@ +pkgdata_DATA=@qfcc_include_qf@ + +EXTRA_HEADERS = $(include_qf) $(qfcc_include_qf) From 57b2751732a06cf4bcc0a7ae855b17a5de9b0f46 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 00:37:10 +0900 Subject: [PATCH 0508/3664] [qfcc] Add failing vector element address test It's an evil thing to do, but it should at least work. --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/vecaddr.r | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tools/qfcc/test/vecaddr.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 129240670..fc6f7692b 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -55,6 +55,7 @@ test_progs_dat=\ structstruct.dat \ swap.dat \ triangle.dat \ + vecaddr.dat \ vecexpr.dat \ vecinit.dat \ voidfor.dat \ @@ -373,6 +374,15 @@ r_depfiles_remade += ./$(DEPDIR)/triangle.Qo #include ./$(DEPDIR)/typedef.Qo # am--include-marker #r_depfiles_remade += ./$(DEPDIR)/typedef.Qo +vecaddr_dat_SOURCES=vecaddr.r +vecaddr_obj=$(vecaddr_dat_SOURCES:.r=.qfo) +vecaddr.dat$(EXEEXT): $(vecaddr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(vecaddr_obj) +vecaddr.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/vecaddr.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/vecaddr.Qo + vecexpr_dat_SOURCES=vecexpr.r vecexpr_obj=$(vecexpr_dat_SOURCES:.r=.qfo) vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/vecaddr.r b/tools/qfcc/test/vecaddr.r new file mode 100644 index 000000000..323d9205c --- /dev/null +++ b/tools/qfcc/test/vecaddr.r @@ -0,0 +1,16 @@ +void printf (string fmt, ...) = #0; + +float foo (vector v, float z) +{ + return v * *(vector*)(&v.y); +} + +int +main (int argc, string *argv) +{ + vector v = [1, 2, 3]; + vector w = [2, 3, 4]; + float f; + printf ("%v %g %g %g\n", v, v*v, v*w, f=foo (v, 4)); + return f != v*w; +} From 4fa203852acfd9aea655c798500b1a4ba70cba37 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 00:55:31 +0900 Subject: [PATCH 0509/3664] [qfcc] Use offset alias offset when creating alias of offset alias Yes, that's correct. It happens when casting the address of a structure field (for the test case this fixes, vector field). --- tools/qfcc/source/expr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index dafb49c96..00d2b60ee 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2065,6 +2065,8 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) t = e1->e.expr.type; if (e2) { e2 = binary_expr ('+', e1->e.expr.e2, e2); + } else { + e2 = e1->e.expr.e2; } return address_expr (e1->e.expr.e1, e2, t); } From e298904dc03920d0e6754cf7dc8ab496caa6673d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 16:31:28 +0900 Subject: [PATCH 0510/3664] [qfcc] Implement anonymous structs and unions For struct/union scope --- tools/qfcc/include/symtab.h | 1 + tools/qfcc/source/qc-parse.y | 39 ++++++++++++++++++++++-- tools/qfcc/source/struct.c | 23 +++++++++++++++ tools/qfcc/source/symtab.c | 2 +- tools/qfcc/test/Makefile.am | 10 +++++++ tools/qfcc/test/anonstruct.r | 57 ++++++++++++++++++++++++++++++++++++ 6 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 tools/qfcc/test/anonstruct.r diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index c0c064f3e..53b42f150 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -45,6 +45,7 @@ typedef enum vis_e { vis_public, vis_protected, vis_private, + vis_anonymous, } vis_t; typedef enum { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 3fac0f926..17316e79f 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -42,6 +42,7 @@ #include #include +#include #include "class.h" #include "debug.h" @@ -264,6 +265,26 @@ default_type (specifier_t spec, symbol_t *sym) return spec; } +static int +is_anonymous_struct (specifier_t spec) +{ + if (spec.sym) { + return 0; + } + if (!is_struct (spec.type)) { + return 0; + } + if (spec.type->t.symtab->parent) { + return 0; + } + // struct and union type names always begin with "tag ". Untagged s/u + // are "tag ..". + if (spec.type->name[4] != '.') { + return 0; + } + return 1; +} + %} %expect 0 @@ -675,15 +696,27 @@ struct_def : type struct_decl_list | type { - if ($1.sym) { + if ($1.sym && $1.sym->type != $1.type) { // a type name (id, typedef, etc) was used as a field name. // this is allowed in C - print_type ($1.type); - printf ("%s\n", $1.sym->name); $1.sym = new_symbol ($1.sym->name); $1.sym->type = $1.type; $1.sym->sy_type = sy_var; symtab_addsymbol (current_symtab, $1.sym); + if (!$1.sym->table) { + error (0, "duplicate field `%s'", $1.sym->name); + } + } else if (is_anonymous_struct ($1)) { + // anonymous struct/union + // type->name always begins with "tag " + $1.sym = new_symbol (va (".anonymous.%s", $1.type->name + 4)); + $1.sym->type = $1.type; + $1.sym->sy_type = sy_var; + $1.sym->visibility = vis_anonymous; + symtab_addsymbol (current_symtab, $1.sym); + if (!$1.sym->table) { + error (0, "duplicate field `%s'", $1.sym->name); + } } else { // bare type warning (0, "declaration does not declare anything"); diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 989b298ef..7af7f26b2 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -114,6 +114,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) symbol_t *sym = find_struct (su, tag, type); symbol_t *s; int alignment = 1; + symbol_t *as; symtab->parent = 0; // disconnect struct's symtab from parent scope @@ -140,6 +141,28 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) if (s->type->alignment > alignment) { alignment = s->type->alignment; } + if (s->visibility == vis_anonymous) { + symtab_t *anonymous; + symbol_t *t = s->next; + int offset = s->s.offset; + + if (!is_struct (s->type)) { + internal_error (0, "non-struct/union anonymous field"); + } + anonymous = s->type->t.symtab; + for (as = anonymous->symbols; as; as = as->next) { + if (Hash_Find (symtab->tab, as->name)) { + error (0, "ambiguous field `%s' in anonymous %s", + as->name, su == 's' ? "struct" : "union"); + } else { + s->next = copy_symbol (as); + s = s->next; + s->s.offset += offset; + Hash_Add (symtab->tab, s); + } + } + s->next = t; + } } if (!type) sym->type = find_type (sym->type); // checks the tag, not the symtab diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index f26a690e7..377671e8a 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -152,7 +152,7 @@ symtab_removesymbol (symtab_t *symtab, symbol_t *symbol) for (s = &symtab->symbols; *s && *s != symbol; s = & (*s)->next) ; if (!*s) - internal_error (0, "symtab_removesymbol"); + internal_error (0, "attempt to remove symbol not in symtab"); *s = (*s)->next; if (symtab->symtail == &symbol->next) symtab->symtail = s; diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index fc6f7692b..2e1001c11 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -31,6 +31,7 @@ fail_bins= test_progs_dat=\ address-cast.dat \ alignment.dat \ + anonstruct.dat \ chewed-alias.dat \ chewed-return.dat \ comma-expr.dat \ @@ -119,6 +120,15 @@ alignment.run: Makefile build-run include ./$(DEPDIR)/alignment.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/alignment.Qo +anonstruct_dat_SOURCES=anonstruct.r +anonstruct_obj=$(anonstruct_dat_SOURCES:.r=.qfo) +anonstruct.dat$(EXEEXT): $(anonstruct_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(anonstruct_obj) +anonstruct.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/anonstruct.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/anonstruct.Qo + chewed_alias_dat_SOURCES=chewed-alias.r chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo) chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/anonstruct.r b/tools/qfcc/test/anonstruct.r new file mode 100644 index 000000000..a426d8f61 --- /dev/null +++ b/tools/qfcc/test/anonstruct.r @@ -0,0 +1,57 @@ +void printf (string fmt, ...) = #0; + +typedef struct xyzzy_s { + int magic; +} xyzzy_t; + +typedef struct anon_s { + int foo; + int id; + struct { + int bar; + int baz; + }; + union { + int snafu; + float fizzle; + }; +} anon_t; + +union { + int xsnafu; + float xfizzle; +}; + +int foo (float f) +{ + anon_t anon; + anon.fizzle = f; + return anon.snafu; +} + +int main() +{ + anon_t anon; + int ret = 0; + if (&anon.snafu != &anon.fizzle) { + printf ("anon union broken: %p %p\n", + &anon.snafu, &anon.fizzle); + ret |= 1; + } + if (&anon.snafu - &anon.baz != 1) { + printf ("snafu and baz not adjacant: snafu:%p baz:%p\n", + &anon.snafu, &anon.baz); + ret |= 1; + } + if (&anon.baz - &anon.bar != 1) { + printf ("baz and bar not adjacant: baz:%p bar:%p\n", + &anon.baz, &anon.bar); + ret |= 1; + } + if (&anon.bar - &anon.id != 1) { + printf ("bar not after id: bar:%p id:%p\n", + &anon.bar, &anon.id); + ret |= 1; + } + return ret; +} From 597890dda154e8817bffa96bde0104dcbe7a6130 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 16:32:04 +0900 Subject: [PATCH 0511/3664] [qfcc] Catch duplicate field definitions --- tools/qfcc/source/qc-parse.y | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 17316e79f..f0a2f5055 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -741,6 +741,9 @@ struct_decl $1->sy_type = sy_var; $1->visibility = current_visibility; symtab_addsymbol (current_symtab, $1); + if (!$1->table) { + error (0, "duplicate field `%s'", $1->name); + } } | var_decl { @@ -751,6 +754,9 @@ struct_decl $1->sy_type = sy_var; $1->visibility = current_visibility; symtab_addsymbol (current_symtab, $1); + if (!$1->table) { + error (0, "duplicate field `%s'", $1->name); + } } | var_decl ':' expr %prec COMMA {} | ':' expr %prec COMMA {} From 4c82114547a0f39f20da22f5cade1299855bc758 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 17:40:49 +0900 Subject: [PATCH 0512/3664] [qfcc] Catch several useless specifier expressions --- tools/qfcc/source/qc-parse.y | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index f0a2f5055..cf9c2fb9f 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -285,6 +285,13 @@ is_anonymous_struct (specifier_t spec) return 1; } +static int +is_null_spec (specifier_t spec) +{ + static specifier_t null_spec; + return memcmp (&spec, &null_spec, sizeof (spec)) == 0; +} + %} %expect 0 @@ -333,7 +340,25 @@ external_def_list external_def : optional_specifiers external_decl_list ';' { } - | optional_specifiers ';' { } + | optional_specifiers ';' + { + if (!is_null_spec ($1)) { + if (!$1.type && !$1.sym) { + warning (0, "useless specifiers"); + } else if ($1.type && !$1.sym) { + if (is_anonymous_struct ($1)){ + warning (0, "unnamed struct/union that defines " + "no instances"); + } else { + warning (0, "useless type name in empty declaration"); + } + } else if (!$1.type && $1.sym) { + bug (0, "wha? %p %p", $1.type, $1.sym); + } else { + bug (0, "wha? %p %p", $1.type, $1.sym); + } + } + } | optional_specifiers qc_func_params { type_t **type; From 7a2335e9f43e739baf801c5d7aca753d35b67e15 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 18:07:10 +0900 Subject: [PATCH 0513/3664] [qfcc] Catch useless specifiers in function scope --- tools/qfcc/source/qc-parse.y | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index cf9c2fb9f..25581f8ec 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1232,6 +1232,26 @@ local_def local_expr = 0; (void) ($2); } + | specifiers ';' + { + if (!is_null_spec ($1)) { + if (!$1.type && !$1.sym) { + warning (0, "useless specifiers"); + } else if ($1.type && !$1.sym) { + if (is_anonymous_struct ($1)){ + warning (0, "unnamed struct/union that defines " + "no instances"); + } else { + warning (0, "useless type name in empty declaration"); + } + } else if (!$1.type && $1.sym) { + bug (0, "wha? %p %p", $1.type, $1.sym); + } else { + bug (0, "wha? %p %p", $1.type, $1.sym); + } + } + $$ = 0; + } ; statement From f532780dbee88efe42331ed21575089cdc1f1650 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 18:38:04 +0900 Subject: [PATCH 0514/3664] [qfcc] Treat opaque structs as not anonymous I don't know why the segfault happened where it did, but forward-declared structs certainly can't be used as anonymous structs. --- tools/qfcc/source/qc-parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 25581f8ec..24138407d 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -274,7 +274,7 @@ is_anonymous_struct (specifier_t spec) if (!is_struct (spec.type)) { return 0; } - if (spec.type->t.symtab->parent) { + if (!spec.type->t.symtab || spec.type->t.symtab->parent) { return 0; } // struct and union type names always begin with "tag ". Untagged s/u From 269a8a558ad51da626a9169e11d20721f6d73783 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 18:39:41 +0900 Subject: [PATCH 0515/3664] [qfcc] Allow bare enum and named struct declarations Got a little overzealous there --- tools/qfcc/source/qc-parse.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 24138407d..46cf09e7e 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -349,7 +349,7 @@ external_def if (is_anonymous_struct ($1)){ warning (0, "unnamed struct/union that defines " "no instances"); - } else { + } else if (!is_enum ($1.type) && !is_struct ($1.type)) { warning (0, "useless type name in empty declaration"); } } else if (!$1.type && $1.sym) { @@ -1241,7 +1241,7 @@ local_def if (is_anonymous_struct ($1)){ warning (0, "unnamed struct/union that defines " "no instances"); - } else { + } else if (!is_enum ($1.type) && !is_struct ($1.type)) { warning (0, "useless type name in empty declaration"); } } else if (!$1.type && $1.sym) { From d57e05258c6ae3cb80e2c41a0ba000b5f35df06c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 19:10:09 +0900 Subject: [PATCH 0516/3664] [qwaq] Remove now unnecessary union field name \o/ --- ruamoko/qwaq/event.h | 2 +- ruamoko/qwaq/qwaq-app.r | 10 +++++----- ruamoko/qwaq/qwaq-curses.c | 8 ++++---- ruamoko/qwaq/qwaq-screen.r | 2 +- ruamoko/qwaq/qwaq-window.r | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index 9eca5158e..28ddccf59 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -29,7 +29,7 @@ typedef struct qwaq_event_s { int key; qwaq_mevent_t mouse; qwaq_message_t message; - } e; + }; } qwaq_event_t; #ifdef __QFCC__ // don't want C gcc to see this :) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index ed6339faf..12280d2b3 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -71,14 +71,14 @@ arp_end (void) -handleEvent: (qwaq_event_t *) event { [screen handleEvent: event]; - if (event.event_type == qe_key && event.e.key == '\x18') { + if (event.event_type == qe_key && event.key == '\x18') { event.event_type = qe_command; - event.e.message.command = qc_exit; + event.message.command = qc_exit; } if (event.event_type == qe_command - && (event.e.message.command == qc_exit - || event.e.message.command == qc_error)) { - endState = event.e.message.command; + && (event.message.command == qc_exit + || event.message.command == qc_error)) { + endState = event.message.command; } return self; } diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index c03a38542..3d8098ea7 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -629,9 +629,9 @@ mouse_event (qwaq_resources_t *res, MEVENT *mevent) { qwaq_event_t event = {}; event.event_type = qe_mouse; - event.e.mouse.x = mevent->x; - event.e.mouse.y = mevent->y; - event.e.mouse.buttons = mevent->bstate; + event.mouse.x = mevent->x; + event.mouse.y = mevent->y; + event.mouse.buttons = mevent->bstate; add_event (res, &event); } @@ -640,7 +640,7 @@ key_event (qwaq_resources_t *res, int key) { qwaq_event_t event = {}; event.event_type = qe_key; - event.e.key = key; + event.key = key; add_event (res, &event); } diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index 0c8573a83..4e68cae30 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -65,7 +65,7 @@ withObject: (id) event]; break; case qe_mouse: - Point p = { event.e.mouse.x, event.e.mouse.y }; + Point p = { event.mouse.x, event.mouse.y }; for (int i = [mouse_handler_rects count]; i-->0; ) { //if (rectContainsPoint((Rect*)mouse_handler_rects._objs[i], &p)) { // [mouse_handlers._objs[i] handleEvent: event]; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 7e201aa9a..af53a6546 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -29,10 +29,10 @@ switch (event.event_type) { case qe_mouse: mvwprintf(window, 0, 3, "%2d %2d %08x", - event.e.mouse.x, event.e.mouse.y, event.e.mouse.buttons); + event.mouse.x, event.mouse.y, event.mouse.buttons); [self redraw]; - point.x = event.e.mouse.x; - point.y = event.e.mouse.y; + point.x = event.mouse.x; + point.y = event.mouse.y; for (int i = [views count]; i--> 0; ) { View *v = [views objectAtIndex: i]; if (rectContainsPoint (&v.absRect, &point)) { From c214797e973ae8124af900f8b9f8f0cd9ece9912 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 21:09:36 +0900 Subject: [PATCH 0517/3664] [gamecode] Fix some curly space and add some comments. took a bit to figure out what i was doing --- libs/gamecode/pr_debug.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 28bb97e54..6a4703724 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -178,21 +178,30 @@ source_path_f (cvar_t *var) int i; char *s; - if (source_path_string) + if (source_path_string) { free (source_path_string); + } source_path_string = strdup (var->string); - if (source_paths) + if (source_paths) { free (source_paths); - for (i = 2, s = source_path_string; *s; s++) - if (*s == ';') + } + // i starts at 2 because an empty path is equivalent to "." and the + // list is null terminated + for (i = 2, s = source_path_string; *s; s++) { + if (*s == ';') { i++; + } + } source_paths = malloc (i * sizeof (char *)); source_paths[0] = source_path_string; - for (i = 1, s = source_path_string; *s; s++) + // i starts at one because the first path is in 0 and any additional + // paths come after, then the null terminator + for (i = 1, s = source_path_string; *s; s++) { if (*s == ';') { *s++ = 0; source_paths[i++] = s; } + } source_paths[i] = 0; } From 68fc11857ad8ef4c58f5169b209ff6872b0e625c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 21:10:23 +0900 Subject: [PATCH 0518/3664] [gamecode] Fix a string splitting error --- libs/gamecode/pr_debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 6a4703724..c102b46f8 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -198,8 +198,8 @@ source_path_f (cvar_t *var) // paths come after, then the null terminator for (i = 1, s = source_path_string; *s; s++) { if (*s == ';') { - *s++ = 0; - source_paths[i++] = s; + *s = 0; + source_paths[i++] = s + 1; } } source_paths[i] = 0; From 815ae02121e71ad77f51949394fd177b0d2b62d4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 21:17:17 +0900 Subject: [PATCH 0519/3664] [qwaq] Allocate enough bytes for the args list d'oh --- ruamoko/qwaq/qwaq-curses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 3d8098ea7..1a75fa4dc 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -903,7 +903,7 @@ bi_wvprintf (progs_t *pr) const char *fmt = P_GSTRING (pr, 1); __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 2); pr_type_t *list_start = PR_GetPointer (pr, args->list); - pr_type_t **list = alloca (args->count); + pr_type_t **list = alloca (args->count * sizeof (*list)); for (int i = 0; i < args->count; i++) { list[i] = list_start + i * pr->pr_param_size; From f3236410d0460f28df9ed8fcda369e6bfe52b997 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Mar 2020 22:09:40 +0900 Subject: [PATCH 0520/3664] [qwaq] Make the event system more informative Doesn't have timestamps at this stage, but otherwise it reflects the event system I had in my old text UI which was heavily based on TurboVision. TV is pretty good (after looking at things a bit closer I found it wasn't as deep as I thought), and better yet, Borland released it to the public domain 23 years ago! (wish I'd known that). Anyway, this commit gets something happening on the screen, even though the current hierarchy is still a mess. --- ruamoko/qwaq/event.h | 33 ++++++++++++++--- ruamoko/qwaq/qwaq-app.r | 15 +++++--- ruamoko/qwaq/qwaq-curses.c | 76 ++++++++++++++++++++++++++++++++++++-- ruamoko/qwaq/qwaq-screen.h | 2 +- ruamoko/qwaq/qwaq-screen.r | 34 +++++++++++------ ruamoko/qwaq/qwaq-window.r | 4 +- 6 files changed, 135 insertions(+), 29 deletions(-) diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index 28ddccf59..445240e54 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -2,11 +2,31 @@ #define __qwaq_event_h typedef enum { - qe_none, - qe_key, - qe_mouse, - qe_command, // application level command -} qwaq_etype; + qe_mousedown = 0x0001, + qe_mouseup = 0x0002, + qe_mouseclick= 0x0004, + qe_mousemove = 0x0008, + qe_mouseauto = 0x0010, +} qwaq_mouse_event; + +typedef enum { + qe_keydown = 0x0020, +} qwaq_key_event; + +typedef enum { + qe_command = 0x0200, // application level command + qe_broadcast = 0x0400, +} qwaq_message_event; + +typedef enum { + qe_none = 0x0000, + qe_mouse = 0x001f, + qe_key = 0x0020, + qe_system = 0x01c0, + qe_message = 0xfe00, + + qe_focused = qe_key | qe_command, +} qwaq_event_mask; typedef enum { qc_valid, @@ -17,6 +37,7 @@ typedef enum { typedef struct qwaq_mevent_s { int x, y; int buttons; + int click; } qwaq_mevent_t; typedef struct qwaq_message_s { @@ -24,7 +45,7 @@ typedef struct qwaq_message_s { } qwaq_message_t; typedef struct qwaq_event_s { - qwaq_etype event_type; + int what; union { int key; qwaq_mevent_t mouse; diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 12280d2b3..3bf67706a 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -1,3 +1,4 @@ +int fence; #include #include "color.h" @@ -47,8 +48,9 @@ arp_end (void) [screen printf:"%d\n", acs_char(ACS_HLINE)]; [screen addch: acs_char(ACS_HLINE) atX:4 Y:4]; Window *w; - [screen add: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; + //[screen add: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; //wprintf (w.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + [screen redraw]; return self; } @@ -59,7 +61,7 @@ arp_end (void) arp_start (); get_event (&event); - if (event.event_type != qe_none) { + if (event.what != qe_none) { [self handleEvent: &event]; } @@ -71,11 +73,11 @@ arp_end (void) -handleEvent: (qwaq_event_t *) event { [screen handleEvent: event]; - if (event.event_type == qe_key && event.key == '\x18') { - event.event_type = qe_command; + if (event.what == qe_key && event.key == '\x18') { + event.what = qe_command; event.message.command = qc_exit; } - if (event.event_type == qe_command + if (event.what == qe_command && (event.message.command == qc_exit || event.message.command == qc_error)) { endState = event.message.command; @@ -86,6 +88,9 @@ arp_end (void) int main (int argc, string *argv) { + fence = 0; + //while (!fence) {} + id app = [[QwaqApplication app] retain]; [app run]; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 1a75fa4dc..e51c47259 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -142,6 +142,11 @@ typedef enum qwaq_commands_e { rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)]; \ }) +#define RB_POKE_DATA(ring_buffer, ahead, data) \ + ({ __auto_type rb = &(ring_buffer); \ + rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)] = (data); \ + }) + typedef struct window_s { WINDOW *win; } window_t; @@ -607,6 +612,16 @@ process_commands (qwaq_resources_t *res) static void add_event (qwaq_resources_t *res, qwaq_event_t *event) { + // lock + // { + // merge motion events + unsigned last = RB_DATA_AVAILABLE (res->event_queue); + if (event->what == qe_mousemove && last > 1 + && RB_PEEK_DATA(res->event_queue, last - 1).what == qe_mousemove) { + RB_POKE_DATA(res->event_queue, last - 1, *event); + return; // unlock + } + // } if (RB_SPACE_AVAILABLE (res->event_queue) >= 1) { RB_WRITE_DATA (res->event_queue, event, 1); } @@ -624,14 +639,69 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) return 0; } +#define M_MOVE REPORT_MOUSE_POSITION +#define M_PRESS ( BUTTON1_PRESSED \ + | BUTTON2_PRESSED \ + | BUTTON3_PRESSED \ + | BUTTON4_PRESSED \ + | BUTTON5_PRESSED) +#define M_RELEASE ( BUTTON1_RELEASED \ + | BUTTON2_RELEASED \ + | BUTTON3_RELEASED \ + | BUTTON4_RELEASED \ + | BUTTON5_RELEASED) +#define M_CLICK ( BUTTON1_CLICKED \ + | BUTTON2_CLICKED \ + | BUTTON3_CLICKED \ + | BUTTON4_CLICKED \ + | BUTTON5_CLICKED) +#define M_DCLICK ( BUTTON1_DOUBLE_CLICKED \ + | BUTTON2_DOUBLE_CLICKED \ + | BUTTON3_DOUBLE_CLICKED \ + | BUTTON4_DOUBLE_CLICKED \ + | BUTTON5_DOUBLE_CLICKED) +#define M_TCLICK ( BUTTON1_TRIPLE_CLICKED \ + | BUTTON2_TRIPLE_CLICKED \ + | BUTTON3_TRIPLE_CLICKED \ + | BUTTON4_TRIPLE_CLICKED \ + | BUTTON5_TRIPLE_CLICKED) + static void -mouse_event (qwaq_resources_t *res, MEVENT *mevent) +mouse_event (qwaq_resources_t *res, const MEVENT *mevent) { + int mask = mevent->bstate; qwaq_event_t event = {}; - event.event_type = qe_mouse; + event.mouse.x = mevent->x; event.mouse.y = mevent->y; event.mouse.buttons = mevent->bstate; + if (mask & M_MOVE) { + event.what = qe_mousemove; + mask &= ~M_MOVE; + } + if (mask & M_PRESS) { + event.what = qe_mousedown; + mask &= ~M_PRESS; + } + if (mask & M_RELEASE) { + event.what = qe_mouseup; + mask &= ~M_RELEASE; + } + if (mask & M_CLICK) { + event.what = qe_mouseclick; + mask &= ~M_CLICK; + event.mouse.click = 1; + } + if (mask & M_DCLICK) { + event.what = qe_mouseclick; + mask &= ~M_DCLICK; + event.mouse.click = 2; + } + if (mask & M_TCLICK) { + event.what = qe_mouseclick; + mask &= ~M_TCLICK; + event.mouse.click = 3; + } add_event (res, &event); } @@ -639,7 +709,7 @@ static void key_event (qwaq_resources_t *res, int key) { qwaq_event_t event = {}; - event.event_type = qe_key; + event.what = qe_keydown; event.key = key; add_event (res, &event); } diff --git a/ruamoko/qwaq/qwaq-screen.h b/ruamoko/qwaq/qwaq-screen.h index 8c83abb6e..1294b2e28 100644 --- a/ruamoko/qwaq/qwaq-screen.h +++ b/ruamoko/qwaq/qwaq-screen.h @@ -8,7 +8,7 @@ @class View; @class Array; -@interface Screen: Object +@interface Screen: Object { Rect rect; Array *views; diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index 4e68cae30..401e0e41e 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -55,23 +55,28 @@ -handleEvent: (qwaq_event_t *) event { - switch (event.event_type) { + if (event.what & qe_mouse) { + [self printf:"%04x %2d %2d %d %08x\r", event.what, event.mouse.x, event.mouse.y, event.mouse.click, event.mouse.buttons]; + [self redraw]; + Point p = { event.mouse.x, event.mouse.y }; + for (int i = [mouse_handler_rects count]; i-->0; ) { + //if (rectContainsPoint((Rect*)mouse_handler_rects._objs[i], &p)) { + // [mouse_handlers._objs[i] handleEvent: event]; + // break; + //} + } + } else if (event.what & qe_focused) { + [focused_handlers + makeObjectsPerformSelector: @selector(handleEvent:) + withObject: (id) event]; + } + switch (event.what) { case qe_none: break; case qe_key: case qe_command: - [focused_handlers - makeObjectsPerformSelector: @selector(handleEvent:) - withObject: (id) event]; break; case qe_mouse: - Point p = { event.mouse.x, event.mouse.y }; - for (int i = [mouse_handler_rects count]; i-->0; ) { - //if (rectContainsPoint((Rect*)mouse_handler_rects._objs[i], &p)) { - // [mouse_handlers._objs[i] handleEvent: event]; - // break; - //} - } break; } return self; @@ -87,8 +92,8 @@ -redraw { - [self error:"hmm"]; update_panels (); + wrefresh(window); doupdate (); return self; } @@ -105,6 +110,11 @@ return self; } +- (Rect *) getRect +{ + return ▭ +} + -setParent: parent { return self; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index af53a6546..d99b21b3c 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -26,7 +26,7 @@ -handleEvent: (qwaq_event_t *) event { - switch (event.event_type) { + switch (event.what) { case qe_mouse: mvwprintf(window, 0, 3, "%2d %2d %08x", event.mouse.x, event.mouse.y, event.mouse.buttons); @@ -46,7 +46,7 @@ if (focusedView) { [focusedView handleEvent: event]; for (int i = [views count]; - event.event_type != qe_none && i--> 0; ) { + event.what != qe_none && i--> 0; ) { View *v = [views objectAtIndex: i]; [v handleEvent: event]; } From 0bb4279a9f14aef844d810aa8c9e6351da1823b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 01:45:38 +0900 Subject: [PATCH 0521/3664] [qfcc] Handle bitwise not of enums It looks like I need to handle other unary expressions too, but another time. --- tools/qfcc/source/expr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 00d2b60ee..ecdc3606c 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1407,6 +1407,7 @@ unary_expr (int op, expr_t *e) quat_t q; const char *s; expr_t *new; + type_t *t; convert_name (e); if (e->type == ex_error) @@ -1568,6 +1569,11 @@ unary_expr (int op, expr_t *e) case ev_short: return new_short_expr (~expr_short (e)); case ev_invalid: + t = get_type (e); + if (t->meta == ty_enum) { + return new_integer_expr (~expr_integer (e)); + } + break; case ev_type_count: case ev_void: break; From 896c14f33a1afe2297ab056546e5679bd8d6020a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 01:46:56 +0900 Subject: [PATCH 0522/3664] [qfcc] Support anonymous structs in ivars Missed this earlier. --- tools/qfcc/source/qc-parse.y | 18 ++++++++++++++++++ tools/qfcc/source/symtab.c | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 46cf09e7e..a6c5d99e4 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1873,6 +1873,24 @@ ivar_decls ivar_decl : type ivars + | type + { + if (is_anonymous_struct ($1)) { + // anonymous struct/union + // type->name always begins with "tag " + $1.sym = new_symbol (va (".anonymous.%s", $1.type->name + 4)); + $1.sym->type = $1.type; + $1.sym->sy_type = sy_var; + $1.sym->visibility = vis_anonymous; + symtab_addsymbol (current_symtab, $1.sym); + if (!$1.sym->table) { + error (0, "duplicate field `%s'", $1.sym->name); + } + } else { + // bare type + warning (0, "declaration does not declare anything"); + } + } ; ivars diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 377671e8a..f94e8d71a 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -182,7 +182,8 @@ symtab_flat_copy (symtab_t *symtab, symtab_t *parent) newtab = new_symtab (parent, stab_local); do { for (symbol = symtab->symbols; symbol; symbol = symbol->next) { - if (Hash_Find (newtab->tab, symbol->name)) + if (symbol->visibility == vis_anonymous + || Hash_Find (newtab->tab, symbol->name)) continue; newsym = copy_symbol (symbol); symtab_addsymbol (newtab, newsym); From efcbbbb6417a8e9f45d032f3c961098e751be325 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 08:50:29 +0900 Subject: [PATCH 0523/3664] [qfcc] Catch use of missing superclass interfaces --- tools/qfcc/source/qc-parse.y | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a6c5d99e4..3966b9cf9 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1630,6 +1630,10 @@ class_with_super new_class_with_super : new_class_name ':' class_name { + if (!$3->ivars) { + error (0, "cannot find interface declaration for `%s', " + "superclass of `%s'", $3->name, $1->name); + } $1->super_class = $3; $$ = $1; } From 78b71c28fe738028d4a130e5b403de078559e5ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 11:03:23 +0900 Subject: [PATCH 0524/3664] [qfcc] Make reloc functions const-correct --- tools/qfcc/include/reloc.h | 19 ++++++++++--------- tools/qfcc/source/reloc.c | 14 +++++++------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/tools/qfcc/include/reloc.h b/tools/qfcc/include/reloc.h index 2272dab5d..dc6e802c8 100644 --- a/tools/qfcc/include/reloc.h +++ b/tools/qfcc/include/reloc.h @@ -68,7 +68,7 @@ typedef enum { */ typedef struct reloc_s { struct reloc_s *next; ///< next reloc in reloc chain - struct ex_label_s *label; ///< instruction label for *_op relocs + const struct ex_label_s *label; ///< instruction label for *_op relocs struct defspace_s *space; ///< the space containing the location in ///< need of adjustment for def_* relocations ///< (op_* relocations always use the code @@ -78,7 +78,7 @@ typedef struct reloc_s { reloc_type type; ///< type type of relocation to perform int line; ///< current source line when creating reloc string_t file; ///< current source file when creating reloc - void *return_address; ///< for debugging + const void *return_address; ///< for debugging } reloc_t; struct statement_s; @@ -147,7 +147,7 @@ void reloc_op_def_ofs (struct def_s *def, int offset, int field); adjusted. As the def's space and offset will be copied into the relocation record, a dummy def may be used. */ -void reloc_def_def (struct def_s *def, struct def_s *location); +void reloc_def_def (struct def_s *def, const struct def_s *location); /** Create a relocation record for a data location referencing a def. @@ -162,7 +162,7 @@ void reloc_def_def (struct def_s *def, struct def_s *location); adjusted. As the def's space and offset will be copied into the relocation record, a dummy def may be used. */ -void reloc_def_def_ofs (struct def_s *def, struct def_s *location); +void reloc_def_def_ofs (struct def_s *def, const struct def_s *location); /** Create a relocation record for a data location referencing a function. @@ -177,7 +177,7 @@ void reloc_def_def_ofs (struct def_s *def, struct def_s *location); adjusted. As the def's space and offset will be copied into the relocation record, a dummy def may be used. */ -void reloc_def_func (struct function_s *func, struct def_s *location); +void reloc_def_func (struct function_s *func, const struct def_s *location); /** Create a relocation record for a data location referencing a string. @@ -191,7 +191,7 @@ void reloc_def_func (struct function_s *func, struct def_s *location); adjusted. As the def's space and offset will be copied into the relocation record, a dummy def may be used. */ -void reloc_def_string (struct def_s *location); +void reloc_def_string (const struct def_s *location); /** Create a relocation record for a data location referencing a field. @@ -206,7 +206,7 @@ void reloc_def_string (struct def_s *location); adjusted. As the def's space and offset will be copied into the relocation record, a dummy def may be used. */ -void reloc_def_field (struct def_s *def, struct def_s *location); +void reloc_def_field (struct def_s *def, const struct def_s *location); /** Create a relocation record for a data location referencing a field. @@ -221,7 +221,7 @@ void reloc_def_field (struct def_s *def, struct def_s *location); adjusted. As the def's space and offset will be copied into the relocation record, a dummy def may be used. */ -void reloc_def_field_ofs (struct def_s *def, struct def_s *location); +void reloc_def_field_ofs (struct def_s *def, const struct def_s *location); /** Create a relocation record for a data location referencing an instruction. @@ -237,7 +237,8 @@ void reloc_def_field_ofs (struct def_s *def, struct def_s *location); adjusted. As the def's space and offset will be copied into the relocation record, a dummy def may be used. */ -void reloc_def_op (struct ex_label_s *label, struct def_s *location); +void reloc_def_op (const struct ex_label_s *label, + const struct def_s *location); void reloc_attach_relocs (reloc_t *relocs, reloc_t **location); diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 29f1663d8..7c4ed3ce3 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -210,7 +210,7 @@ reloc_op_def_ofs (def_t *def, int offset, int field) } void -reloc_def_def (def_t *def, def_t *location) +reloc_def_def (def_t *def, const def_t *location) { reloc_t *ref; @@ -221,7 +221,7 @@ reloc_def_def (def_t *def, def_t *location) } void -reloc_def_def_ofs (def_t *def, def_t *location) +reloc_def_def_ofs (def_t *def, const def_t *location) { reloc_t *ref; @@ -232,7 +232,7 @@ reloc_def_def_ofs (def_t *def, def_t *location) } void -reloc_def_func (function_t *func, def_t *location) +reloc_def_func (function_t *func, const def_t *location) { reloc_t *ref; @@ -243,7 +243,7 @@ reloc_def_func (function_t *func, def_t *location) } void -reloc_def_string (def_t *location) +reloc_def_string (const def_t *location) { reloc_t *ref; @@ -254,7 +254,7 @@ reloc_def_string (def_t *location) } void -reloc_def_field (def_t *def, def_t *location) +reloc_def_field (def_t *def, const def_t *location) { reloc_t *ref; @@ -265,7 +265,7 @@ reloc_def_field (def_t *def, def_t *location) } void -reloc_def_field_ofs (def_t *def, def_t *location) +reloc_def_field_ofs (def_t *def, const def_t *location) { reloc_t *ref; @@ -276,7 +276,7 @@ reloc_def_field_ofs (def_t *def, def_t *location) } void -reloc_def_op (ex_label_t *label, def_t *location) +reloc_def_op (const ex_label_t *label, const def_t *location) { reloc_t *ref; From 1b2a806f2829b1b756d577e4c8e6981c7daa04f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 11:04:22 +0900 Subject: [PATCH 0525/3664] [qfcc] Fix test that failed due to improved warnings --- tools/qfcc/test/anonstruct.r | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/qfcc/test/anonstruct.r b/tools/qfcc/test/anonstruct.r index a426d8f61..684ae8c2b 100644 --- a/tools/qfcc/test/anonstruct.r +++ b/tools/qfcc/test/anonstruct.r @@ -17,11 +17,6 @@ typedef struct anon_s { }; } anon_t; -union { - int xsnafu; - float xfizzle; -}; - int foo (float f) { anon_t anon; From 9ccfe8aefc2de99f2411ae080656887e113ffda7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 11:05:13 +0900 Subject: [PATCH 0526/3664] [qfcc] Rewrite init_elements The end goal was to fix erroneous non-constant initializer errors for the following (ie, nested initializer blocks): typedef struct { int x; int y; } Point; typedef struct { int width; int height; } Extent; typedef struct Rect_s { Point offset; Extent extent; } Rect; Rect makeRect (int xpos, int ypos, int xlen, int ylen) { Rect rect = {{xpos, ypos}, {xlen, ylen}}; return rect; } However, it turned out that nested initializer blocks for local variables did not work at all in that the relocations were lost because fake defs were being created for the generated instructions. Thus, instead of creating fake defs, simply record the offset relative to the base def, the type, and the basic type initializer expression, then generate instructions that all refer to the correct def but with a relative offset. Other than using the new element system, static initializers are largely unaffected. --- tools/qfcc/source/def.c | 285 +++++++++++++++++++++++----------------- 1 file changed, 167 insertions(+), 118 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index c0332be60..93152b6db 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -62,7 +62,37 @@ #include "type.h" #include "value.h" +typedef struct element_s { + struct element_s *next; + int offset; + type_t *type; + expr_t *expr; +} element_t; + +typedef struct element_chain_s { + element_t *head; + element_t **tail; +} element_chain_t; + static def_t *defs_freelist; +static element_t *elements_freelist; + +static element_t * +new_element (void) +{ + element_t *element; + ALLOC (256, element_t, elements, element); + return element; +} + +static element_t * +append_element (element_chain_t *element_chain, element_t *element) +{ + element->next = 0; + *element_chain->tail = element; + element_chain->tail = &element->next; + return element; +} static void set_storage_bits (def_t *def, storage_class_t storage) @@ -303,141 +333,158 @@ zero_memory (expr_t *local_expr, def_t *def, type_t *zero_type, } static void -init_elements (struct def_s *def, expr_t *eles) +init_elements_nil (def_t *def) { - expr_t *e, *c; - int count, i, num_elements, base_offset; - pr_type_t *g; - def_t *elements; + if (def->local && local_expr) { + // memset to 0 + int init_size = type_size (def->type); + int init_offset = 0; - base_offset = def->offset; - if (def->local && local_expr) - base_offset = 0; - if (eles->type == ex_nil) { - if (def->local && local_expr) { - // memset to 0 - int init_size = type_size (def->type); - int init_offset = 0; - - if (options.code.progsversion != PROG_ID_VERSION) { - init_offset = zero_memory (local_expr, def, &type_zero, - init_size, init_offset); - } - // probably won't happen any time soon, but who knows... - if (options.code.progsversion != PROG_ID_VERSION - && init_size - init_offset >= type_size (&type_quaternion)) { - init_offset = zero_memory (local_expr, def, &type_quaternion, - init_size, init_offset); - } - if (init_size - init_offset >= type_size (&type_vector)) { - init_offset = zero_memory (local_expr, def, &type_vector, - init_size, init_offset); - } - if (options.code.progsversion != PROG_ID_VERSION - && init_size - init_offset >= type_size (&type_double)) { - init_offset = zero_memory (local_expr, def, &type_double, - init_size, init_offset); - } - if (init_size - init_offset >= type_size (type_default)) { - zero_memory (local_expr, def, type_default, - init_size, init_offset); - } + if (options.code.progsversion != PROG_ID_VERSION) { + init_offset = zero_memory (local_expr, def, &type_zero, + init_size, init_offset); + } + // probably won't happen any time soon, but who knows... + if (options.code.progsversion != PROG_ID_VERSION + && init_size - init_offset >= type_size (&type_quaternion)) { + init_offset = zero_memory (local_expr, def, &type_quaternion, + init_size, init_offset); + } + if (init_size - init_offset >= type_size (&type_vector)) { + init_offset = zero_memory (local_expr, def, &type_vector, + init_size, init_offset); + } + if (options.code.progsversion != PROG_ID_VERSION + && init_size - init_offset >= type_size (&type_double)) { + init_offset = zero_memory (local_expr, def, &type_double, + init_size, init_offset); + } + if (init_size - init_offset >= type_size (type_default)) { + zero_memory (local_expr, def, type_default, + init_size, init_offset); } - // it's a global, so already initialized to 0 - return; } - if (is_array (def->type)) { - type_t *array_type = def->type->t.array.type; - int array_size = def->type->t.array.size; - elements = calloc (array_size, sizeof (def_t)); + // it's a global, so already initialized to 0 +} + +static void +build_element_chain (element_chain_t *element_chain, type_t *type, + expr_t *eles, int base_offset) +{ + expr_t *e = eles->e.block.head; + + if (is_array (type)) { + type_t *array_type = type->t.array.type; + int array_size = type->t.array.size; + int i; + for (i = 0; i < array_size; i++) { - elements[i].type = array_type; - elements[i].space = def->space; - elements[i].offset = base_offset + i * type_size (array_type); + int offset = base_offset + i * type_size (array_type); + if (e && e->type == ex_block) { + build_element_chain (element_chain, array_type, e, offset); + } else { + element_t *element = new_element (); + element->type = array_type; + element->offset = offset; + element->expr = e; // null will be treated as nil + append_element (element_chain, element); + } + if (e) { + e = e->next; + } } - num_elements = i; - } else if (is_struct (def->type) || is_vector (def->type) - || is_quaternion (def->type)) { - symtab_t *symtab = def->type->t.symtab; + } else if (is_struct (type) || is_vector (type) || is_quaternion (type)) { + symtab_t *symtab = type->t.symtab; symbol_t *field; - for (i = 0, field = symtab->symbols; field; field = field->next) { - if (field->sy_type != sy_var) + for (field = symtab->symbols; field; field = field->next) { + int offset = base_offset + field->s.offset; + if (field->sy_type != sy_var + || field->visibility == vis_anonymous) { continue; - i++; + } + if (e && e->type == ex_block) { + build_element_chain (element_chain, field->type, e, offset); + } else { + element_t *element = new_element (); + element->type = field->type; + element->offset = offset; + element->expr = e; // null will be treated as nil + append_element (element_chain, element); + } + if (e) { + e = e->next; + } } - elements = calloc (i, sizeof (def_t)); - for (i = 0, field = symtab->symbols; field; field = field->next) { - if (field->sy_type != sy_var) - continue; - elements[i].type = field->type; - elements[i].space = def->space; - elements[i].offset = base_offset + field->s.offset; - i++; - } - num_elements = i; } else { error (eles, "invalid initializer"); + } + if (e && e->next && options.warnings.initializer) { + warning (eles, "excessive elements in initializer"); + } +} + +static void +init_elements (struct def_s *def, expr_t *eles) +{ + expr_t *c; + pr_type_t *g; + element_chain_t element_chain; + element_t *element; + + if (eles->type == ex_nil) { + init_elements_nil (def); return; } - for (count = 0, e = eles->e.block.head; e; count++, e = e->next) { - convert_name (e); - if (e->type == ex_nil && count < num_elements - && !(is_array (elements[count].type) - || is_struct (elements[count].type))) { - convert_nil (e, elements[count].type); - } - if (e->type == ex_error) { - free (elements); - return; - } - } - if (count > num_elements) { - if (options.warnings.initializer) - warning (eles, "excessive elements in initializer"); - count = num_elements; - } - for (i = 0, e = eles->e.block.head; i < count; i++, e = e->next) { - g = D_POINTER (pr_type_t, &elements[i]); - c = constant_expr (e); - // nil will not survive as nil to this point if array or struct - if (c->type == ex_block || c->type == ex_nil) { - if (!is_array (elements[i].type) - && !is_struct (elements[i].type)) { - error (e, "type mismatch in initializer"); - continue; - } - init_elements (&elements[i], c); - continue; - } else if (c->type == ex_labelref) { - def_t loc; - loc.space = elements[i].space; - loc.offset = elements[i].offset; - reloc_def_op (c->e.labelref.label, &loc); - continue; - } else if (c->type == ex_value) { - if (c->e.value->lltype == ev_integer - && elements[i].type->type == ev_float) - convert_int (c); - if (get_type (c) != elements[i].type) { - error (e, "type mismatch in initializer"); - continue; - } - } else { - if (!def->local || !local_expr) { - error (e, "non-constant initializer"); - continue; - } - } - if (def->local && local_expr) { - int offset = elements[i].offset; - type_t *type = elements[i].type; + + element_chain.head = 0; + element_chain.tail = &element_chain.head; + build_element_chain (&element_chain, def->type, eles, 0); + + if (def->local && local_expr) { + for (element = element_chain.head; element; element = element->next) { + int offset = element->offset; + type_t *type = element->type; expr_t *ptr = new_pointer_expr (offset, type, def); + if (element->expr) { + c = constant_expr (element->expr); + } else { + c = convert_nil (new_nil_expr (), type); + } append_expr (local_expr, assign_expr (unary_expr ('.', ptr), c)); - } else { - if (c->type != ex_value) + } + } else { + def_t dummy = *def; + for (element = element_chain.head; element; element = element->next) { + if (element->expr) { + c = constant_expr (element->expr); + } else { + c = convert_nil (new_nil_expr (), element->type); + } + dummy.offset = def->offset + element->offset; + g = D_POINTER (pr_type_t, &dummy); + if (c->type == ex_labelref) { + reloc_def_op (c->e.labelref.label, &dummy); + continue; + } else if (c->type == ex_value) { + if (c->e.value->lltype == ev_integer + && is_float (element->type)) { + convert_int (c); + } + if (get_type (c) != element->type) { + error (c, "type mismatch in initializer"); + continue; + } + } else { + if (!def->local || !local_expr) { + error (c, "non-constant initializer"); + continue; + } + } + if (c->type != ex_value) { internal_error (c, "bogus expression type in init_elements()"); + } if (c->e.value->lltype == ev_string) { EMIT_STRING (def->space, g->string_var, c->e.value->v.string_val); @@ -446,7 +493,9 @@ init_elements (struct def_s *def, expr_t *eles) } } } - free (elements); + + *element_chain.tail = elements_freelist; + elements_freelist = element_chain.head; } static void From 1459361cbdd1ca55729a0d156f10911c365172d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 11:48:15 +0900 Subject: [PATCH 0527/3664] [qfcc] Set builtin function def flags This fixes the missing redefinition error when a builtin is defined twice (and thus corrupting the function chain). --- tools/qfcc/source/function.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index e2b87d04a..ff54b2ce5 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -650,6 +650,9 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far) if (sym->s.func->def->external) return 0; + sym->s.func->def->initialized = 1; + sym->s.func->def->constant = 1; + sym->s.func->def->nosave = 1; add_function (sym->s.func); if (is_integer_val (bi_val)) From 65a5e4f2a49428629e86135f95b6bd1de15c275d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 12:52:37 +0900 Subject: [PATCH 0528/3664] [qfcc] Allow inherited methods to satisfy protocols I suspect that the current state of things will produce problems later on, but this works for now. --- tools/qfcc/include/method.h | 9 ++++++- tools/qfcc/source/class.c | 18 +++++++++++-- tools/qfcc/source/method.c | 50 +++++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/include/method.h b/tools/qfcc/include/method.h index 6b02bbe00..c64f04ade 100644 --- a/tools/qfcc/include/method.h +++ b/tools/qfcc/include/method.h @@ -58,6 +58,10 @@ typedef struct methodlist_s { int instance; ///< used only for emitting } methodlist_t; +typedef struct methodset_s { + struct hashtab_s *tab; +} methodset_t; + typedef struct keywordarg_s { // the first two fields match the first two fields of param_t in // functionl.h @@ -80,9 +84,12 @@ struct symbol_s *method_symbol (struct class_type_s *class_type, void method_set_param_names (method_t *dst, method_t *src); methodlist_t *new_methodlist (void); +methodset_t *new_methodset (void); +void methodset_add_methods (methodset_t *methodset, methodlist_t *methods); +int methodset_contains_method (methodset_t *methodset, method_t *method); //NOTE frees the source list and any methods not copied void merge_method_lists (methodlist_t *dst, methodlist_t *src); -void copy_methods (methodlist_t *dst, methodlist_t *src); +void copy_methods (methodlist_t *dst, methodlist_t *src, methodset_t *except); int method_compare (method_t *m1, method_t *m2); keywordarg_t *new_keywordarg (const char *selector, struct expr_s *expr); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 4b331d237..5a9c5c6e0 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -642,16 +642,23 @@ class_add_protocols (class_t *class, protocollist_t *protocols) int i; protocol_t *p; methodlist_t *methods; + methodset_t *except; + class_t *super; if (!protocols) return; methods = class->methods; + except = new_methodset (); + for (super = class->super_class; super; super = super->super_class) { + methodset_add_methods (except, super->methods); + } + for (i = 0; i < protocols->count; i++) { p = protocols->list[i]; if (p->methods) { - copy_methods (methods, p->methods); + copy_methods (methods, p->methods, except); } else { warning (0, "definition of protocol `%s' not found", p->name); } @@ -1269,15 +1276,22 @@ category_add_protocols (category_t *category, protocollist_t *protocols) int i; protocol_t *p; methodlist_t *methods; + methodset_t *except; + class_t *class; if (!protocols) return; methods = category->methods; + except = new_methodset (); + for (class = category->class; class; class = class->super_class) { + methodset_add_methods (except, class->methods); + } + for (i = 0; i < protocols->count; i++) { p = protocols->list[i]; - copy_methods (methods, p->methods); + copy_methods (methods, p->methods, except); if (p->protocols) category_add_protocols (category, p->protocols); } diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index c5bd8b334..e68ad857f 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -205,6 +205,52 @@ new_methodlist (void) return l; } +static uintptr_t +methodset_get_hash (const void *_method, void *unused) +{ + method_t *method = (method_t *) _method; + uintptr_t hash; + + hash = Hash_String (method->name); + return hash ^ (method->instance << 3); +} + +static int +methodset_compare (const void *_m1, const void *_m2, void *unused) +{ + method_t *m1 = (method_t *) _m1; + method_t *m2 = (method_t *) _m2; + int cmp; + + cmp = strcmp (m1->name, m2->name) == 0; + return cmp && m1->instance == m2->instance; +} + +methodset_t * +new_methodset (void) +{ + methodset_t *s = malloc (sizeof (*s)); + s->tab = Hash_NewTable (31, 0, 0, 0); + Hash_SetHashCompare (s->tab, methodset_get_hash, methodset_compare); + return s; +} + +void +methodset_add_methods (methodset_t *methodset, methodlist_t *methods) +{ + method_t *m; + + for (m = methods->head; m; m = m->next) { + Hash_AddElement (methodset->tab, m); + } +} + +int +methodset_contains_method (methodset_t *methodset, method_t *method) +{ + return Hash_FindElement (methodset->tab, method) != 0; +} + static int __attribute__((pure)) method_in_list (methodlist_t *method_list, method_t *method) { @@ -238,13 +284,13 @@ merge_method_lists (methodlist_t *dst, methodlist_t *src) } void -copy_methods (methodlist_t *dst, methodlist_t *src) +copy_methods (methodlist_t *dst, methodlist_t *src, methodset_t *except) { method_t *s, *d; param_t *self; for (s = src->head; s; s = s->next) { - if (method_in_list (dst, s)) { + if (methodset_contains_method (except, s) || method_in_list (dst, s)) { debug (0, "skipping duplicate method: %s", s->name); continue; } From ccaa4ad3d21334d3c59047055f31c53e8d876b49 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 14:14:20 +0900 Subject: [PATCH 0529/3664] [qfcc] Catch assignment of void* to class pointers id and other class pointers imply that the object can receive messages, but void * has no such implication, so treat it as a mismatch. --- tools/qfcc/source/class.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 5a9c5c6e0..60cfe27ca 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -445,8 +445,14 @@ obj_types_assignable (const type_t *dst, const type_t *src) int i; //puts ("%$$\"$#%"); - if (!obj_is_classptr (dst) || !obj_is_classptr (src)) + if (!obj_is_classptr (src)) { + // if dst is a class pointer, then the types are not compatible, + // otherwise unknown + return obj_is_classptr (dst) - 1; + } + if (!obj_is_classptr (dst)) { return -1; + } dst_is_proto = obj_is_id (dst) && (dst_protos = obj_get_protos (dst)); src_is_proto = obj_is_id (src) && (src_protos = obj_get_protos (src)); From 669c8f43d8817605acd25e14a1219121d2b9586a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 14:48:49 +0900 Subject: [PATCH 0530/3664] whitespace --- tools/qfcc/source/expr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index ecdc3606c..c384bcfe5 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1645,7 +1645,6 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) expr_t *call; expr_t *err = 0; - for (e = params; e; e = e->next) { if (e->type == ex_error) return e; From 59db90d17760536976443e8170d46e290b8dcafd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 14:48:53 +0900 Subject: [PATCH 0531/3664] [qfcc] Fix method not found warnings It turns out they should not be optional, but do need to be smarter about when and which. So another two FIXMEs gone :) --- tools/qfcc/source/class.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 60cfe27ca..574a484b9 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1136,19 +1136,15 @@ class_message_response (class_t *class, int class_msg, expr_t *sel) } c = c->super_class; } - //FIXME right option? - if (options.warnings.interface_check) - warning (sel, "%s may not respond to %c%s", class->name, - class_msg ? '+' : '-', selector->name); + warning (sel, "%s may not respond to %c%s", class->name, + class_msg ? '+' : '-', selector->name); } m = find_method (selector->name); - if (m) - return m; - //FIXME right option? - if (options.warnings.interface_check) + if (!m && (!class || class->type == &type_obj_object)) { warning (sel, "could not find method for %c%s", class_msg ? '+' : '-', selector->name); - return 0; + } + return m; } static uintptr_t From 2ddfe2ef0721f17b31cc7c9560ea002db2646e67 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 15:00:42 +0900 Subject: [PATCH 0532/3664] [libr] Accept void * for performSelector:withObject: It's up to the receiver what the object should be. --- ruamoko/include/Array.h | 2 +- ruamoko/include/Object.h | 6 +++--- ruamoko/lib/Array.r | 4 ++-- ruamoko/lib/Object.r | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ruamoko/include/Array.h b/ruamoko/include/Array.h index 113e466a9..060f50956 100644 --- a/ruamoko/include/Array.h +++ b/ruamoko/include/Array.h @@ -271,7 +271,7 @@ Iteratively sends #performSelector:withObject: to each contained object. */ - (void) makeObjectsPerformSelector: (SEL)selector - withObject: (id)arg; + withObject: (void *)arg; //\} @end diff --git a/ruamoko/include/Object.h b/ruamoko/include/Object.h index 475e0bec9..eb10e55ef 100644 --- a/ruamoko/include/Object.h +++ b/ruamoko/include/Object.h @@ -20,10 +20,10 @@ - (id) performSelector: (SEL)aSelector; - (id) performSelector: (SEL)aSelector - withObject: (id)anObject; + withObject: (void *)anObject; - (id) performSelector: (SEL)aSelector - withObject: (id)anObject - withObject: (id)anotherObject; + withObject: (void *)anObject + withObject: (void *)anotherObject; - (BOOL) respondsToSelector: (SEL)aSelector; - (BOOL) conformsToProtocol: (Protocol *)aProtocol; diff --git a/ruamoko/lib/Array.r b/ruamoko/lib/Array.r index 842076f72..2946141cc 100644 --- a/ruamoko/lib/Array.r +++ b/ruamoko/lib/Array.r @@ -162,7 +162,7 @@ - (id) objectAtIndex: (unsigned)index { if (index >= count) // FIXME: need exceptions - [self error: "-replaceObjectAtIndex:withObject: index out of range"]; + [self error: "-objectAtIndex:withObject: index out of range"]; return _objs[index]; } @@ -401,7 +401,7 @@ } - (void) makeObjectsPerformSelector: (SEL)selector - withObject: (id)anObject + withObject: (void *)anObject { local int i; diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index dba6b5071..d85a78064 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -247,7 +247,7 @@ BOOL (id object) object_is_meta_class = #0; return msg (self, aSelector); } -- (id) performSelector: (SEL)aSelector withObject: (id)anObject +- (id) performSelector: (SEL)aSelector withObject: (void *)anObject { local IMP msg = nil; // FIXME teach qfcc about noreturn @@ -260,8 +260,8 @@ BOOL (id object) object_is_meta_class = #0; } - (id) performSelector: (SEL)aSelector - withObject: (id)anObject - withObject: (id)anotherObject + withObject: (void *)anObject + withObject: (void *)anotherObject { local IMP msg; From a4582e526d6e7cb2cf414240d24e6891d32f59ca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 15:02:40 +0900 Subject: [PATCH 0533/3664] [cl_menu,scheme] Clean up after tightened pointer checks --- ruamoko/cl_menu/options.r | 12 ++++++------ ruamoko/cl_menu/plistmenu.r | 2 +- ruamoko/scheme/Symbol.r | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ruamoko/cl_menu/options.r b/ruamoko/cl_menu/options.r index e0529c23e..a228b1062 100644 --- a/ruamoko/cl_menu/options.r +++ b/ruamoko/cl_menu/options.r @@ -130,7 +130,7 @@ MENU_video_options (PLItem *plist) if (plist) { ret = object_from_plist ([(PLDictionary*) plist getObjectForKey:"video_options"]); - video_options = ret.pointer_val; + video_options = (Group *) ret.pointer_val; } Menu_End (); @@ -177,7 +177,7 @@ MENU_audio_options (PLItem *plist) if (plist) { ret = object_from_plist ([(PLDictionary*) plist getObjectForKey:"audio_options"]); - audio_options = ret.pointer_val; + audio_options = (Group *) ret.pointer_val; } Menu_End (); @@ -224,7 +224,7 @@ MENU_control_options (PLItem *plist) if (plist) { ret = object_from_plist ([(PLDictionary*) plist getObjectForKey:"control_options"]); - control_options = ret.pointer_val; + control_options = (Group *) ret.pointer_val; } MENU_control_binding (); //FIXME how to hook in the bindings menu? @@ -275,7 +275,7 @@ MENU_feature_options (PLItem *plist) if (plist) { ret = object_from_plist ([(PLDictionary*) plist getObjectForKey:"feature_options"]); - feature_options = ret.pointer_val; + feature_options = (Group *) ret.pointer_val; } Menu_End (); @@ -361,7 +361,7 @@ MENU_player_options (PLItem *plist) if (plist) { ret = object_from_plist ([(PLDictionary*) plist getObjectForKey:"player_options"]); - player_options = ret.pointer_val; + player_options = (Group *) ret.pointer_val; } Menu_End (); @@ -426,7 +426,7 @@ MENU_network_options (PLItem *plist) if (plist) { ret = object_from_plist ([(PLDictionary*) plist getObjectForKey:"network_options"]); - network_options = ret.pointer_val; + network_options = (Group *) ret.pointer_val; } Menu_End (); diff --git a/ruamoko/cl_menu/plistmenu.r b/ruamoko/cl_menu/plistmenu.r index d5e722377..bdece6082 100644 --- a/ruamoko/cl_menu/plistmenu.r +++ b/ruamoko/cl_menu/plistmenu.r @@ -103,7 +103,7 @@ array_from_plist (PLArray *plarray) count = [plarray count]; for (i = 0; i < count; i++) { ret = object_from_plist ([plarray getObjectAtIndex:i]); - [array addObject: ret.pointer_val]; + [array addObject: (id) ret.pointer_val]; } ret.pointer_val = array; return ret; diff --git a/ruamoko/scheme/Symbol.r b/ruamoko/scheme/Symbol.r index b83f3dbd6..2adfc6a25 100644 --- a/ruamoko/scheme/Symbol.r +++ b/ruamoko/scheme/Symbol.r @@ -45,7 +45,7 @@ Symbol *symbol (string str) { local Symbol *res; - if ((res = Hash_Find (symbols, s))) { + if ((res = (Symbol *) Hash_Find (symbols, s))) { return res; } else { res = (Symbol*) [self newFromString: s]; From 1bf56b28ac8dd2e885c86085eb8fe5a9da0e5640 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 15:39:34 +0900 Subject: [PATCH 0534/3664] [qfcc] Warn when messaging a forward-declared class But only once. --- tools/qfcc/include/class.h | 1 + tools/qfcc/source/class.c | 10 +++++++++- tools/qfcc/source/qc-parse.y | 5 ++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index 726a272be..7f7f0920d 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -48,6 +48,7 @@ typedef struct class_type_s { typedef struct class_s { int defined; + int interface_declared; const char *name; struct class_s *super_class; struct category_s *categories; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 574a484b9..8e2d458e1 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1042,7 +1042,10 @@ class_find_ivar (class_t *class, int vis, const char *name) symbol_t *ivar; if (!class->ivars) { - error (0, "accessing incomplete type %s", class->name); + if (!class->interface_declared) { + class->interface_declared = 1; + error (0, "accessing incomplete type %s", class->name); + } return 0; } ivar = symtab_lookup (class->ivars, name); @@ -1119,6 +1122,11 @@ class_message_response (class_t *class, int class_msg, expr_t *sel) if (!selector) return 0; if (class && class->type != &type_obj_object) { + if (!class->interface_declared) { + class->interface_declared = 1; + warning (0, "cannot find interface declaration for `%s'", + class->name); + } while (c) { for (cat = c->categories; cat; cat = cat->next) { for (m = cat->methods->head; m; m = m->next) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 3966b9cf9..a99f8c6b5 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1612,6 +1612,7 @@ new_class_name $1 = check_redefined ($1); $$ = get_class ($1, 1); } + $$->interface_declared = 1; current_class = &$$->class_type; if (!$1->table) symtab_addsymbol (current_symtab, $1); @@ -1630,10 +1631,12 @@ class_with_super new_class_with_super : new_class_name ':' class_name { - if (!$3->ivars) { + if (!$3->interface_declared) { + $3->interface_declared = 1; error (0, "cannot find interface declaration for `%s', " "superclass of `%s'", $3->name, $1->name); } + $1->interface_declared = 1; $1->super_class = $3; $$ = $1; } From c377b324a10a5bbbbfa4ed469ea0b518e43cf0ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 15:44:53 +0900 Subject: [PATCH 0535/3664] [qwaq] Add Group and clean up lots of mess Things are finally doing something again, and getting closer to having a moveable window. --- ruamoko/qwaq/Makefile.am | 6 +-- ruamoko/qwaq/event.h | 1 + ruamoko/qwaq/qwaq-app.r | 18 +++++---- ruamoko/qwaq/qwaq-curses.c | 50 +++++++++++++++++++++++++ ruamoko/qwaq/qwaq-curses.h | 2 + ruamoko/qwaq/qwaq-draw.h | 3 +- ruamoko/qwaq/qwaq-group.h | 17 +++++++++ ruamoko/qwaq/qwaq-group.r | 60 ++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-rect.h | 17 +++++---- ruamoko/qwaq/qwaq-screen.h | 18 ++------- ruamoko/qwaq/qwaq-screen.r | 51 +------------------------ ruamoko/qwaq/qwaq-view.h | 48 ++++++++++++++++++++++-- ruamoko/qwaq/qwaq-view.r | 76 ++++++++++++++++++++++++++++++++++---- ruamoko/qwaq/qwaq-window.h | 7 ++-- ruamoko/qwaq/qwaq-window.r | 30 +++++---------- 15 files changed, 287 insertions(+), 117 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-group.h create mode 100644 ruamoko/qwaq/qwaq-group.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index f32d9d536..ab08a5579 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -23,8 +23,8 @@ SUFFIXES=.o .r sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo -qwaq_dat_src= \ - $e +qwaq_app_dat_src= \ + qwaq-app.r qwaq-group.r qwaq-screen.r qwaq-window.r qwaq-view.r qwaq_curses_libs= qwaq_curses_SOURCES=main.c qwaq-curses.c @@ -59,7 +59,7 @@ qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) r_depfiles_remade= -qwaq_app_dat_SOURCES=qwaq-app.r qwaq-screen.r qwaq-window.r qwaq-view.r +qwaq_app_dat_SOURCES=$(qwaq_app_dat_src) qwaq_app_obj=$(qwaq_app_dat_SOURCES:.r=.o) qwaq_app_dep=$(addprefix ./$(DEPDIR)/,$(qwaq_app_obj:.o=.Qo)) qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index 445240e54..03f479fdc 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -26,6 +26,7 @@ typedef enum { qe_message = 0xfe00, qe_focused = qe_key | qe_command, + qe_positional = qe_mouse, } qwaq_event_mask; typedef enum { diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 3bf67706a..aba39ac96 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -39,17 +39,19 @@ arp_end (void) screen = [[Screen screen] retain]; [screen setBackground: COLOR_PAIR (1)]; Rect r = *[screen getRect]; - [screen printf:"%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen]; - r.xpos = r.xlen / 4; - r.ypos = r.ylen / 4; - r.xlen /= 2; - r.ylen /= 2; - [screen printf:"%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen]; + [screen printf:"%d %d %d %d\n", + r.offset.x, r.offset.y, r.extent.width, r.extent.height]; + r.offset.x = r.extent.width / 4; + r.offset.y = r.extent.height / 4; + r.extent.width /= 2; + r.extent.height /= 2; + [screen printf:"%d %d %d %d\n", + r.offset.x, r.offset.y, r.extent.width, r.extent.height]; [screen printf:"%d\n", acs_char(ACS_HLINE)]; [screen addch: acs_char(ACS_HLINE) atX:4 Y:4]; Window *w; //[screen add: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; - //wprintf (w.window, "%d %d %d %d\n", r.xpos, r.ypos, r.xlen, r.ylen); + //wprintf (w.window, "%d %d %d %d\n", r.offset.x, r.offset.y, r.extent.width, r.ylen); [screen redraw]; return self; } @@ -128,3 +130,5 @@ void move_panel (panel_t panel, int x, int y) = #0; window_t panel_window (panel_t panel) = #0; void update_panels (void) = #0; void doupdate (void) = #0; +int curs_set (int visibility) = #0; +int move (int x, int y) = #0; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index e51c47259..9213e4bdd 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -73,6 +73,8 @@ typedef enum qwaq_commands_e { qwaq_cmd_init_pair, qwaq_cmd_wbkgd, qwaq_cmd_scrollok, + qwaq_cmd_move, + qwaq_cmd_curs_set, } qwaq_commands; #define RING_BUFFER(type, size) \ @@ -539,6 +541,23 @@ cmd_scrollok (qwaq_resources_t *res) scrollok (window->win, flag); } +static void +cmd_move (qwaq_resources_t *res) +{ + int x = RB_PEEK_DATA (res->command_queue, 2); + int y = RB_PEEK_DATA (res->command_queue, 3); + + move (y, x); +} + +static void +cmd_curs_set (qwaq_resources_t *res) +{ + int visibility = RB_PEEK_DATA (res->command_queue, 2); + + curs_set (visibility); +} + static void process_commands (qwaq_resources_t *res) { @@ -604,6 +623,12 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_scrollok: cmd_scrollok (res); break; + case qwaq_cmd_move: + cmd_move (res); + break; + case qwaq_cmd_curs_set: + cmd_curs_set (res); + break; } RB_DROP_DATA (res->command_queue, RB_PEEK_DATA (res->command_queue, 1)); } @@ -1106,6 +1131,29 @@ bi_acs_char (progs_t *pr) } } +static void +bi_move (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int x = P_INT (pr, 0); + int y = P_INT (pr, 1); + + int command[] = { qwaq_cmd_move, 0, x, y, }; + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); +} + +static void +bi_curs_set (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int visibility = P_INT (pr, 0); + + int command[] = { qwaq_cmd_curs_set, 0, visibility, }; + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); +} + static void bi_initialize (progs_t *pr) { @@ -1168,6 +1216,8 @@ static builtin_t builtins[] = { {"wbkgd", bi_wbkgd, -1}, {"scrollok", bi_scrollok, -1}, {"acs_char", bi_acs_char, -1}, + {"move", bi_move, -1}, + {"curs_set", bi_curs_set, -1}, {0} }; diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index e9574e764..a17640bd5 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -98,6 +98,8 @@ typedef struct panel_s *panel_t; @extern void scrollok (window_t win, int flag); @extern int acs_char (int acs); +@extern int curs_set (int visibility); +@extern int move (int x, int y); #endif #endif//__qwaq_curses_h diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index 7b614a29e..983dd8074 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -4,7 +4,8 @@ @protocol Draw -draw; -redraw; --setParent: parent; +-setOwner: owner; +-(struct window_s*) getWindow; @end #endif diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h new file mode 100644 index 000000000..a018102d6 --- /dev/null +++ b/ruamoko/qwaq/qwaq-group.h @@ -0,0 +1,17 @@ +#ifndef __qwaq_group_h +#define __qwaq_group_h + +#include "qwaq-view.h" + +@class Array; + +@interface Group : View +{ + Array *views; + int focused; +} +-insert: (View *) view; +-remove: (View *) view; +@end + +#endif//__qwaq_group_h diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r new file mode 100644 index 000000000..a4fc171d0 --- /dev/null +++ b/ruamoko/qwaq/qwaq-group.r @@ -0,0 +1,60 @@ +#include +#include "event.h" +#include "qwaq-group.h" + +@implementation Group +-init +{ + if (!(self = [super init])) { + return nil; + } + views = [[Array array] retain]; + return self; +} + +-(void)dealloc +{ + [views release]; +} + +-insert: (View *) view +{ + [views insertObject: view atIndex: 0]; + return self; +} + +-remove: (View *) view +{ + int index = [views indexOfObject: view]; + if (index != NotFound) { + if (focused == index) { + focused = -1; + } else if (focused > index) { + focused--; + } + [views removeObjectAtIndex: index]; + } + return self; +} + +-draw +{ + [views makeObjectsPerformSelector: @selector(draw)]; + return self; +} + +-handleEvent: (qwaq_event_t *) event +{ + [super handleEvent: event]; + if (event.what & qe_focused) { + if (focused >= 0) { + [[views objectAtIndex:focused] handleEvent: event]; + } + } else if (event.what & qe_positional) { + } else { + // broadcast + [views makeObjectsPerformSelector: @selector(draw) withObject: event]; + } + return self; +} +@end diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index c679352fc..8976d25db 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -1,18 +1,21 @@ #ifndef __qwaq_rect_h #define __qwaq_rect_h -typedef struct Rect_s { - int xpos; - int ypos; - int xlen; - int ylen; -} Rect; - typedef struct { int x; int y; } Point; +typedef struct { + int width; + int height; +} Extent; + +typedef struct Rect_s { + Point offset; + Extent extent; +} Rect; + @extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); //XXX will not work if point or rect point to a local variabl @extern int rectContainsPoint (Rect *rect, Point *point); diff --git a/ruamoko/qwaq/qwaq-screen.h b/ruamoko/qwaq/qwaq-screen.h index 1294b2e28..e92daa2a4 100644 --- a/ruamoko/qwaq/qwaq-screen.h +++ b/ruamoko/qwaq/qwaq-screen.h @@ -1,28 +1,18 @@ #ifndef __qwaq_screen_h #define __qwaq_screen_h -#include - #include "qwaq-draw.h" #include "qwaq-rect.h" -@class View; -@class Array; +#include "qwaq-view.h" -@interface Screen: Object +@interface Screen: View { - Rect rect; - Array *views; - Array *event_handlers; - Array *focused_handlers; - Array *mouse_handlers; - Array *mouse_handler_rects; - View *focusedView; - struct window_s *window; } +(Screen *) screen; --add: obj; +-handleEvent: (qwaq_event_t *) event; -setBackground: (int) ch; -printf: (string) fmt, ...; +-addch: (int) ch atX: (int) x Y: (int) y; @end #endif//__qwaq_screen_h diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index 401e0e41e..45ae3228b 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -13,40 +13,12 @@ if (!(self = [super init])) { return nil; } - views = [[Array array] retain]; - event_handlers = [[Array array] retain]; - focused_handlers = [[Array array] retain]; - mouse_handlers = [[Array array] retain]; - mouse_handler_rects = [[Array array] retain]; window = stdscr; scrollok (window, 1); rect = getwrect (window); return self; } --add: obj -{ - if ([obj conformsToProtocol: @protocol (Draw)]) { - // "top" objects are drawn last - [views addObject: obj]; - [obj setParent: self]; - } - if ([obj conformsToProtocol: @protocol (HandleFocusedEvent)]) { - // want "top" objects to respond first - [focused_handlers insertObject: obj atIndex: 0]; - } - if ([obj conformsToProtocol: @protocol (HandleMouseEvent)]) { - // "top" objects respond first, but the array is searched in reverse - [mouse_handlers addObject: obj]; - [mouse_handler_rects addObject: (id) [obj getRect]]; - } - if ([obj conformsToProtocol: @protocol (HandleEvent)]) { - // want "top" objects to respond first - [event_handlers insertObject: obj atIndex: 0]; - } - return self; -} - -setBackground: (int) ch { wbkgd (window, ch); @@ -58,33 +30,12 @@ if (event.what & qe_mouse) { [self printf:"%04x %2d %2d %d %08x\r", event.what, event.mouse.x, event.mouse.y, event.mouse.click, event.mouse.buttons]; [self redraw]; - Point p = { event.mouse.x, event.mouse.y }; - for (int i = [mouse_handler_rects count]; i-->0; ) { - //if (rectContainsPoint((Rect*)mouse_handler_rects._objs[i], &p)) { - // [mouse_handlers._objs[i] handleEvent: event]; - // break; - //} - } - } else if (event.what & qe_focused) { - [focused_handlers - makeObjectsPerformSelector: @selector(handleEvent:) - withObject: (id) event]; - } - switch (event.what) { - case qe_none: - break; - case qe_key: - case qe_command: - break; - case qe_mouse: - break; } return self; } -draw { - [views makeObjectsPerformSelector: @selector (draw)]; update_panels (); doupdate (); return self; @@ -115,7 +66,7 @@ return ▭ } --setParent: parent +-setOwner: owner { return self; } diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index e7c0db85e..bd38962e6 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -7,16 +7,56 @@ #include "qwaq-draw.h" #include "qwaq-rect.h" -@interface View: Object +@class Group; + +enum { + ofCanFocus =0x0001, + ofFirstClick =0x0002, + ofDontDraw =0x0004, + ofPreProcess =0x0008, + ofPostProcess =0x0010, + ofMakeFirst =0x0020, + ofTileable =0x0040, + ofCentered =0x0080, + + ofCallHasObject =0x8000, +}; + +enum { + sfDrawn =0x0001, + sfDisabled =0x0002, + sfInFocus =0x0004, + sfModal =0x0008, + sfLocked =0x0010, +}; + +@interface View: Object { - @public - Rect rect; + union { + Rect rect; + struct { + int xpos; + int ypos; + int xlen; + int ylen; + }; + }; Rect absRect; Point point; // can't be local :( - id parent; + Group *owner; struct window_s *window; + int state; + int options; + int cursorState; + Point cursor; } -initWithRect: (Rect) rect; +- (void) dealloc; +-(struct window_s *) getWindow; +-setOwner: (Group *) owner; +-(struct Rect_s *)getRect; +-draw; +-redraw; @end #endif//__qwaq_view_h diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index bc218630f..969f1dfe2 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -1,18 +1,21 @@ #include "qwaq-curses.h" #include "qwaq-view.h" +#include "qwaq-group.h" Rect makeRect (int xpos, int ypos, int xlen, int ylen) { - Rect rect = {xpos, ypos, xlen, ylen}; + Rect rect = {{xpos, ypos}, {xlen, ylen}}; return rect; } int rectContainsPoint (Rect *rect, Point *point) { - return ((point.x >= rect.xpos && point.x < rect.xpos + rect.xlen) - && (point.y >= rect.ypos && point.y < rect.ypos + rect.ylen)); + return ((point.x >= rect.offset.x + && point.x < rect.offset.x + rect.extent.width) + && (point.y >= rect.offset.y + && point.y < rect.offset.y + rect.extent.height)); } @implementation View @@ -24,24 +27,83 @@ rectContainsPoint (Rect *rect, Point *point) } self.rect = rect; self.absRect = rect; - self.window = nil; return self; } +- (void) dealloc +{ + if (owner) { + [owner remove:self]; + } + [super dealloc]; +} + +static void +updateScreenCursor (View *view) +{ + while ((view.state & sfInFocus) && view.owner) { + View *owner = (View *) view.owner; + if (view.cursor.x >= 0 && view.cursor.x < view.xlen + && view.cursor.y >= 0 && view.cursor.y < view.ylen) { + owner.cursor.x = view.cursor.x + view.xpos; + owner.cursor.y = view.cursor.y + view.ypos; + owner.cursorState = view.cursorState; + } else { + owner.cursorState = 0; + } + view = owner; + } + if (view.state & sfInFocus) { + if (view.cursor.x >= 0 && view.cursor.x < view.xlen + && view.cursor.y >= 0 && view.cursor.y < view.ylen) { + curs_set (view.cursorState); + move(view.cursor.x, view.cursor.y); + } else { + curs_set (0); + } + } +} + -draw { + state |= sfDrawn; + updateScreenCursor (self); return self; } --setParent: parent +-hide { - self.parent = parent; + if (state & sfDrawn) { + state &= ~sfDrawn; + updateScreenCursor (self); + } return self; } -redraw { - return [parent redraw]; + if ((state & sfDrawn) && !(options & ofDontDraw)) { + [self draw]; + [owner redraw]; + } + return self; +} + +-setOwner: (Group *) owner +{ + self.owner = owner; + window = [owner getWindow]; + return self; +} + +-(window_t) getWindow +{ + return window; +} + +- (Rect *) getRect +{ + return ▭ } @end diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 19921301a..8073c3312 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -3,16 +3,15 @@ #include "Object.h" -@class View; @class Array; #include "qwaq-draw.h" #include "qwaq-rect.h" +#include "qwaq-view.h" +#include "qwaq-group.h" -@interface Window: Object +@interface Window: Group { - Rect rect; - id parent; Point point; // FIXME can't be local :( Array *views; View *focusedView; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index d99b21b3c..237c9dcb9 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -19,14 +19,14 @@ } views = [[Array array] retain]; self.rect = rect; - window = create_window (rect.xpos, rect.ypos, rect.xlen, rect.ylen); + window = create_window (xpos, ypos, xlen, ylen); panel = create_panel (window); return self; } -handleEvent: (qwaq_event_t *) event { - switch (event.what) { +/* switch (event.what) { case qe_mouse: mvwprintf(window, 0, 3, "%2d %2d %08x", event.mouse.x, event.mouse.y, event.mouse.buttons); @@ -54,17 +54,17 @@ break; case qe_none: break; - } + }*/ return self; } -addView: (View *) view { - [views addObject: view]; +/* [views addObject: view]; view.absRect.xpos = view.rect.xpos + rect.xpos; view.absRect.ypos = view.rect.ypos + rect.ypos; view.window = window; - [view setParent: self]; + [view setOwner: self];*/ return self; } @@ -74,16 +74,6 @@ return self; } --takeFocus -{ - return self; -} - --loseFocus -{ - return self; -} - -draw { int x = 0, y = 0; @@ -94,9 +84,9 @@ } else { mvwaddch (window, x, y, '.'); } - if (++x >= rect.xlen) { + if (++x >= xlen) { x = 0; - if (++y >= rect.ylen) { + if (++y >= ylen) { break; } } @@ -110,14 +100,14 @@ return ▭ } --setParent: parent +-setOwner: owner { - self.parent = parent; + self.owner = owner; return self; } -redraw { - return [parent redraw]; + return [owner redraw]; } @end From 5200c3f51860906aa1866e3b895a9a9c85f3d517 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 18:26:11 +0900 Subject: [PATCH 0536/3664] [qfcc] Update chewed-alias test for new warnings --- tools/qfcc/test/chewed-alias.r | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/test/chewed-alias.r b/tools/qfcc/test/chewed-alias.r index 7f151bce5..08c060534 100644 --- a/tools/qfcc/test/chewed-alias.r +++ b/tools/qfcc/test/chewed-alias.r @@ -1,4 +1,9 @@ -@class Array,Object; +@interface Array +-count; +-lastObject; +@end +@interface Object +@end @static entity waypoint_thinker; @static Array *waypoint_queue; void foo (void) @@ -18,4 +23,6 @@ void __obj_exec_class (struct obj_module *msg) = #0; @implementation Object @end @implementation Array +-count { return self; } +-lastObject { return nil; } @end From 66b8ab689014435db7951c2944eb28b0b4f088ac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 18:45:47 +0900 Subject: [PATCH 0537/3664] [qfcc] Rework method ivar access While expression symbols worked for what they are, they weren't so good for ivar access because every ivar of a class (and its super classes) would be accessed at method scope creation, generating spurious access errors if any were private. That is, when the access checks worked at all. --- tools/qfcc/include/symtab.h | 8 ++++++++ tools/qfcc/source/class.c | 24 +++++++++++++++++++----- tools/qfcc/source/expr.c | 4 ++++ tools/qfcc/source/expr_assign.c | 2 ++ tools/qfcc/source/struct.c | 4 ++++ tools/qfcc/source/symtab.c | 2 ++ 6 files changed, 39 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index 53b42f150..7a6904f1a 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -56,8 +56,14 @@ typedef enum { sy_expr, ///< symbol refers to an expression sy_func, ///< symbol refers to a function sy_class, ///< symbol refers to a class + sy_convert, ///< symbol refers to a conversion function } sy_type_e; +typedef struct symconv_s { + struct expr_s *(*conv) (struct symbol_s *symbol, void *data); + void *data; +} symconv_t; + typedef struct symbol_s { struct symbol_s *next; ///< chain of symbols in symbol table struct symtab_s *table; ///< symbol table that owns this symbol @@ -72,6 +78,7 @@ typedef struct symbol_s { struct ex_value_s *value; ///< sy_const struct expr_s *expr; ///< sy_expr struct function_s *func; ///< sy_func + symconv_t convert; ///< sy_convert } s; } symbol_t; @@ -92,6 +99,7 @@ typedef struct symtab_s { symbol_t *symbols; ///< chain of symbols in this table symbol_t **symtail; ///< keep chain in declaration order struct defspace_s *space; ///< storage for vars in scope symtabs + struct class_s *class; ///< owning class if ivar scope } symtab_t; const char *symtype_str (sy_type_e type) __attribute__((const)); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 8e2d458e1..50ab5dcd7 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1050,8 +1050,11 @@ class_find_ivar (class_t *class, int vis, const char *name) } ivar = symtab_lookup (class->ivars, name); if (ivar) { - if (ivar->visibility > (vis_t) vis) + if (ivar->visibility > (vis_t) vis + || (ivar->table->class != class + && ivar->visibility > vis_protected)) { goto access_error; + } return ivar; } error (0, "%s.%s does not exist", class->name, name); @@ -1180,6 +1183,7 @@ class_new_ivars (class_t *class) if (class->super_class) super_ivars = class->super_class->ivars; ivars = new_symtab (super_ivars, stab_local); + ivars->class = class; return ivars; } @@ -1756,6 +1760,15 @@ class_ivar_scope (class_type_t *class_type, symtab_t *parent) return symtab_flat_copy (class->ivars, parent); } +static expr_t * +class_dereference_ivar (symbol_t *sym, void *_self) +{ + expr_t *self = (expr_t *) _self; + + return field_expr (copy_expr (self), + new_symbol_expr (new_symbol (sym->name))); +} + void class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope, symtab_t *param_scope) @@ -1769,8 +1782,9 @@ class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope, if (!ivar_scope) return; self = symtab_lookup (param_scope, "self"); - if (!self) + if (!self) { internal_error (0, "I've lost my self!"); + } self_expr = new_symbol_expr (self); if (self->type != class_ptr) { debug (0, "class method scope"); @@ -1780,9 +1794,9 @@ class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope, for (sym = ivar_scope->symbols; sym; sym = sym->next) { if (sym->sy_type != sy_var) continue; - sym->sy_type = sy_expr; - sym->s.expr = field_expr (copy_expr (self_expr), - new_symbol_expr (new_symbol (sym->name))); + sym->sy_type = sy_convert; + sym->s.convert.conv = class_dereference_ivar; + sym->s.convert.data = self_expr; } } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c384bcfe5..c82585674 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -109,6 +109,10 @@ convert_name (expr_t *e) //FIXME need a def return; } + if (sym->sy_type == sy_convert) { + new = sym->s.convert.conv (sym, sym->s.convert.data); + goto convert; + } if (sym->sy_type == sy_expr) { new = copy_expr (sym->s.expr); goto convert; diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 046f1c07b..f0d7daf4b 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -101,6 +101,8 @@ check_valid_lvalue (expr_t *expr) break; case sy_class: break; + case sy_convert: + break; } break; case ex_temp: diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 7af7f26b2..85c8a85ba 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -151,6 +151,9 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) } anonymous = s->type->t.symtab; for (as = anonymous->symbols; as; as = as->next) { + if (as->visibility == vis_anonymous || as->sy_type!= sy_var) { + continue; + } if (Hash_Find (symtab->tab, as->name)) { error (0, "ambiguous field `%s' in anonymous %s", as->name, su == 's' ? "struct" : "union"); @@ -158,6 +161,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) s->next = copy_symbol (as); s = s->next; s->s.offset += offset; + s->table = symtab; Hash_Add (symtab->tab, s); } } diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index f94e8d71a..353e29142 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -59,6 +59,7 @@ static const char *sy_type_names[] = { "sy_expr", "sy_func", "sy_class", + "sy_convert", }; const char * @@ -165,6 +166,7 @@ symbol_t * copy_symbol (symbol_t *symbol) { symbol_t *sym = new_symbol (symbol->name); + sym->visibility = symbol->visibility; sym->type = symbol->type; sym->params = copy_params (symbol->params); sym->sy_type = symbol->sy_type; From 94e35b5f576267d21dcad1bcb36bcc71bd0bca99 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Mar 2020 21:10:15 +0900 Subject: [PATCH 0538/3664] [qfcc] Clean up error messages around superclass --- tools/qfcc/source/qc-parse.y | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a99f8c6b5..3732e47b7 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1589,9 +1589,13 @@ classdecl class_name : identifier %prec CLASS_NOT_CATEGORY { - $1 = check_undefined ($1); - if (!$1->type || !obj_is_class ($1->type)) { - error (0, "`%s' is not a class %p", $1->name, $1->type); + if (!$1->type) { + $$ = get_class ($1, 1); + if (!$1->table) { + symtab_addsymbol (current_symtab, $1); + } + } else if (!obj_is_class ($1->type)) { + error (0, "`%s' is not a class", $1->name); $$ = get_class (0, 1); } else { $$ = $1->type->t.class; From 3b959c3ed0d8dc29b49bbd67da53ad5ac3b22399 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 00:23:44 +0900 Subject: [PATCH 0539/3664] [gamecode] Add a macros for arbitrary param/return types Of course, the type has to be small enough to fit or bad things may happen, but it beats having to type the crazy casting every time. --- include/QF/progs.h | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 18ea33b04..ea17f533e 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -562,6 +562,20 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define P_var(p,n,t) ((p)->pr_params[n]->t##_var) +/** Access a parameter as an arbitray type. + + \par QC type: + \c struct etc small enough to fit in a single parameter + \param p pointer to ::progs_t VM struct + \param t C type of the structure + \param n parameter number (0-7) + \return structure lvalue. use & to make a pointer of the + appropriate type. + + \hideinitializer +*/ +#define P_PACKED(p,t,n) (*(t *) (p)->pr_params[n]) + /** Access a float parameter. Can be assigned to. \par QC type: @@ -584,7 +598,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_DOUBLE(p,n) (*(double *) ((p)->pr_params[n])) +#define P_DOUBLE(p,n) P_PACKED(p, double, n) /** Access an integer parameter. Can be assigned to. @@ -670,7 +684,6 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define P_POINTER(p,n) P_var (p, n, pointer) - /** Access an entity parameter. \par QC type: @@ -767,6 +780,19 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_var(p,t) ((p)->pr_return->t##_var) +/** Access the VM function return value parameter as an arbitray type. + + \par QC type: + \c struct etc small enough to fit in the return slot + \param p pointer to ::progs_t VM struct + \param t C type of the structure + \return structure lvalue. use & to make a pointer of the + appropriate type. + + \hideinitializer +*/ +#define R_PACKED(p,t) (*(t *) (p)->pr_return) + /** Access the VM function return value as a \c float \par QC type: @@ -787,7 +813,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_DOUBLE(p) (*(double *) ((p)->pr_return)) +#define R_DOUBLE(p) R_PACKED (p, double) /** Access the VM function return value as a \c ::pr_int_t (AKA int32_t) From 971caf553dcd5c5aed2258ef8da6aa5ea1ec7efe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 00:30:11 +0900 Subject: [PATCH 0540/3664] [qwaq] Add debug output to the command queue Be sure to redirect stderr or the screen will get messed up --- ruamoko/qwaq/qwaq-curses.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 9213e4bdd..bab6a9283 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -77,6 +77,29 @@ typedef enum qwaq_commands_e { qwaq_cmd_curs_set, } qwaq_commands; +const char *qwaq_command_names[]= { + "newwin", + "delwin", + "getwrect", + "new_panel", + "del_panel", + "hide_panel", + "show_panel", + "top_panel", + "bottom_panel", + "move_panel", + "panel_window", + "update_panels", + "doupdate", + "mvwaddstr", + "waddstr", + "mvwaddch", + "wrefresh", + "init_pair", + "wbkgd", + "scrollok", + "move", + "curs_set", #define RING_BUFFER(type, size) \ struct { \ type buffer[size]; \ @@ -562,7 +585,14 @@ static void process_commands (qwaq_resources_t *res) { while (RB_DATA_AVAILABLE (res->command_queue) >= 2) { - switch ((qwaq_commands) RB_PEEK_DATA (res->command_queue, 0)) { + qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); + int len = RB_PEEK_DATA (res->command_queue, 1); + Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); + for (int i = 2; i < len; i++) { + Sys_Printf (" %d", RB_PEEK_DATA (res->command_queue, i)); + } + Sys_Printf ("\n"); + switch (cmd) { case qwaq_cmd_newwin: cmd_newwin (res); break; From f18e3c3ad72679893fa2586d75637385edd69a67 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 00:31:29 +0900 Subject: [PATCH 0541/3664] [qwaq] Add wborder command --- ruamoko/qwaq/qwaq-app.r | 1 + ruamoko/qwaq/qwaq-curses.c | 43 ++++++++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-curses.h | 17 +++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index aba39ac96..054b4e3c8 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -132,3 +132,4 @@ void update_panels (void) = #0; void doupdate (void) = #0; int curs_set (int visibility) = #0; int move (int x, int y) = #0; +void wborder (window_t window, box_sides_t sides, box_corners_t corners) = #0; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index bab6a9283..73c500368 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -43,6 +43,7 @@ #include "qwaq.h" #include "event.h" +#include "qwaq-curses.h" #define always_inline inline __attribute__((__always_inline__)) #define QUEUE_SIZE 16 @@ -75,6 +76,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_scrollok, qwaq_cmd_move, qwaq_cmd_curs_set, + qwaq_cmd_wborder, } qwaq_commands; const char *qwaq_command_names[]= { @@ -100,6 +102,9 @@ const char *qwaq_command_names[]= { "scrollok", "move", "curs_set", + "wborder", +}; + #define RING_BUFFER(type, size) \ struct { \ type buffer[size]; \ @@ -581,6 +586,23 @@ cmd_curs_set (qwaq_resources_t *res) curs_set (visibility); } +static void +cmd_wborder (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int ls = RB_PEEK_DATA (res->command_queue, 3); + int rs = RB_PEEK_DATA (res->command_queue, 4); + int ts = RB_PEEK_DATA (res->command_queue, 5); + int bs = RB_PEEK_DATA (res->command_queue, 6); + int tl = RB_PEEK_DATA (res->command_queue, 7); + int tr = RB_PEEK_DATA (res->command_queue, 8); + int bl = RB_PEEK_DATA (res->command_queue, 9); + int br = RB_PEEK_DATA (res->command_queue, 10); + + window_t *window = get_window (res, __FUNCTION__, window_id); + wborder (window->win, ls, rs, ts, bs, tl, tr, bl, br); +} + static void process_commands (qwaq_resources_t *res) { @@ -659,6 +681,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_curs_set: cmd_curs_set (res); break; + case qwaq_cmd_wborder: + cmd_wborder (res); + break; } RB_DROP_DATA (res->command_queue, RB_PEEK_DATA (res->command_queue, 1)); } @@ -1184,6 +1209,23 @@ bi_curs_set (progs_t *pr) qwaq_submit_command (res, command); } +static void +bi_wborder (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int window_id = P_INT (pr, 0); + __auto_type sides = P_PACKED (pr, box_sides_t, 1); + __auto_type corns = P_PACKED (pr, box_corners_t, 2); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_wborder, 0, window_id, + sides.ls, sides.rs, sides.ts, sides.bs, + corns.tl, corns.tr, corns.bl, corns.br, }; + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} + static void bi_initialize (progs_t *pr) { @@ -1248,6 +1290,7 @@ static builtin_t builtins[] = { {"acs_char", bi_acs_char, -1}, {"move", bi_move, -1}, {"curs_set", bi_curs_set, -1}, + {"wborder", bi_wborder, -1}, {0} }; diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index a17640bd5..62bdef880 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -3,6 +3,20 @@ #include "event.h" +typedef struct box_sides_s { + int ls; + int rs; + int ts; + int bs; +} box_sides_t; + +typedef struct box_corners_s { + int tl; + int tr; + int bl; + int br; +} box_corners_t; + #ifdef __QFCC__ // names, order and comments lifted from ncurses.h typedef enum { @@ -100,6 +114,9 @@ typedef struct panel_s *panel_t; @extern int acs_char (int acs); @extern int curs_set (int visibility); @extern int move (int x, int y); + +@extern void wborder (window_t window, + box_sides_t sides, box_corners_t corners); #endif #endif//__qwaq_curses_h From ad4cde15b53e9e3e4e9ca380f200c76b9da41b24 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 00:32:09 +0900 Subject: [PATCH 0542/3664] [qwaq] Get Window working It even draws a border around itself. --- ruamoko/qwaq/qwaq-app.h | 3 ++- ruamoko/qwaq/qwaq-app.r | 14 +++++--------- ruamoko/qwaq/qwaq-group.r | 9 +++++++++ ruamoko/qwaq/qwaq-screen.r | 11 +++-------- ruamoko/qwaq/qwaq-view.r | 5 +++++ ruamoko/qwaq/qwaq-window.h | 4 ---- ruamoko/qwaq/qwaq-window.r | 28 ++++++++++++++++++++++------ 7 files changed, 46 insertions(+), 28 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index b603fb4b1..d8b899624 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -2,10 +2,11 @@ #define __qwaq_app_h #include "event.h" +#include "qwaq-group.h" @class Screen; -@interface QwaqApplication: Object +@interface QwaqApplication: Group { qwaq_event_t event; qwaq_command endState; diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 054b4e3c8..dfd82e096 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -33,32 +33,28 @@ arp_end (void) if (!(self = [super init])) { return nil; } + initialize (); init_pair (1, COLOR_WHITE, COLOR_BLUE); init_pair (2, COLOR_WHITE, COLOR_BLACK); + screen = [[Screen screen] retain]; + [self insert:screen]; [screen setBackground: COLOR_PAIR (1)]; Rect r = *[screen getRect]; - [screen printf:"%d %d %d %d\n", - r.offset.x, r.offset.y, r.extent.width, r.extent.height]; r.offset.x = r.extent.width / 4; r.offset.y = r.extent.height / 4; r.extent.width /= 2; r.extent.height /= 2; - [screen printf:"%d %d %d %d\n", - r.offset.x, r.offset.y, r.extent.width, r.extent.height]; - [screen printf:"%d\n", acs_char(ACS_HLINE)]; - [screen addch: acs_char(ACS_HLINE) atX:4 Y:4]; Window *w; - //[screen add: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; + [self insert: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; //wprintf (w.window, "%d %d %d %d\n", r.offset.x, r.offset.y, r.extent.width, r.ylen); - [screen redraw]; return self; } -run { - [screen draw]; + [self draw]; do { arp_start (); diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index a4fc171d0..1b1bd5c61 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -12,6 +12,15 @@ return self; } +-initWithRect: (Rect) rect +{ + if (!(self = [super initWithRect: rect])) { + return nil; + } + views = [[Array array] retain]; + return self; +} + -(void)dealloc { [views release]; diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index 45ae3228b..e39406448 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -10,12 +10,11 @@ -init { - if (!(self = [super init])) { + if (!(self = [super initWithRect:getwrect (stdscr)])) { return nil; } window = stdscr; scrollok (window, 1); - rect = getwrect (window); return self; } @@ -28,7 +27,7 @@ -handleEvent: (qwaq_event_t *) event { if (event.what & qe_mouse) { - [self printf:"%04x %2d %2d %d %08x\r", event.what, event.mouse.x, event.mouse.y, event.mouse.click, event.mouse.buttons]; + [self printf:"%04x %2d %2d %d %08x \r", event.what, event.mouse.x, event.mouse.y, event.mouse.click, event.mouse.buttons]; [self redraw]; } return self; @@ -61,13 +60,9 @@ return self; } -- (Rect *) getRect -{ - return ▭ -} - -setOwner: owner { + self.owner = owner; return self; } diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 969f1dfe2..3fb5b4e77 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -20,6 +20,11 @@ rectContainsPoint (Rect *rect, Point *point) @implementation View +-init +{ + return [super init]; +} + -initWithRect: (Rect) rect { if (!(self = [super init])) { diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 8073c3312..c59a72f28 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -13,13 +13,9 @@ @interface Window: Group { Point point; // FIXME can't be local :( - Array *views; - View *focusedView; - struct window_s *window; struct panel_s *panel; } +windowWithRect: (Rect) rect; --addView: (View *) view; -setBackground: (int) ch; @end diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 237c9dcb9..45e8c4a77 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -17,7 +17,6 @@ if (!(self = [super init])) { return nil; } - views = [[Array array] retain]; self.rect = rect; window = create_window (xpos, ypos, xlen, ylen); panel = create_panel (window); @@ -76,22 +75,39 @@ -draw { - int x = 0, y = 0; - for (int i = ACS_ULCORNER; i <= ACS_STERLING; i++) { + static box_sides_t box_sides = { + ACS_VLINE, ACS_VLINE, + ACS_HLINE, ACS_HLINE, + }; + static box_corners_t box_corners = { + ACS_ULCORNER, ACS_URCORNER, + ACS_LLCORNER, ACS_LRCORNER, + }; + if (box_sides.ls == ACS_VLINE) { + int *foo = &box_sides.ls; + for (int i = 0; i < 8; i++) { + foo[i] = acs_char (foo[i]); + } + } + [super draw]; + int x = 1, y = 1; + wborder (window, box_sides, box_corners); + //for (int i = ACS_ULCORNER; i <= ACS_STERLING; i++) { + for (int i = 32; i <= 127; i++) { int ch = acs_char (i); if (ch) { mvwaddch (window, x, y, ch); } else { mvwaddch (window, x, y, '.'); } - if (++x >= xlen) { - x = 0; + if (++x > 32) { + x = 1; if (++y >= ylen) { break; } } } - [views makeObjectsPerformSelector: @selector (draw)]; + wrefresh (window); return self; } From 6bf2fd546d945e5171d92d1176286915e77ccebe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 11:27:31 +0900 Subject: [PATCH 0543/3664] [qwaq] Extend Array makeObjectsPerform methods Added conditional message sending and reversed traversal of the array. --- ruamoko/qwaq/qwaq-group.h | 24 ++++++++++++++- ruamoko/qwaq/qwaq-group.r | 63 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index a018102d6..a1b58fbae 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -1,9 +1,31 @@ #ifndef __qwaq_group_h #define __qwaq_group_h +#include #include "qwaq-view.h" -@class Array; +typedef BOOL condition_func (id object, void *data); +typedef BOOL condition_func2 (id object, void *anObject, void *data); + +@interface Array (Group) +- (void) makeObjectsPerformSelector: (SEL)selector + if: (condition_func)condition + with: (void *)data; +- (void) makeObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject + if: (condition_func2)condition + with: (void *)data; +- (void) makeReversedObjectsPerformSelector: (SEL)selector; +- (void) makeReversedObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject; +- (void) makeReversedObjectsPerformSelector: (SEL)selector + if: (condition_func)condition + with: (void *)data; +- (void) makeReversedObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject + if: (condition_func2)condition + with: (void *)data; +@end @interface Group : View { diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 1b1bd5c61..3d03c3402 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -2,6 +2,69 @@ #include "event.h" #include "qwaq-group.h" +@implementation Array (Group) +- (void) makeObjectsPerformSelector: (SEL)selector + if: (condition_func)condition + with: (void *)data +{ + for (int i = 0; i < [self count]; i++) { + if (condition (_objs[i], data)) { + [_objs[i] performSelector: selector]; + } + } +} + +- (void) makeObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject + if: (condition_func2)condition + with: (void *)data +{ + for (int i = 0; i < [self count]; i++) { + if (condition (_objs[i], anObject, data)) { + [_objs[i] performSelector: selector withObject: anObject]; + } + } +} + +- (void) makeReversedObjectsPerformSelector: (SEL)selector +{ + for (int i = [self count]; i-->0; ) { + [_objs[i] performSelector: selector]; + } +} + +- (void) makeReversedObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject +{ + for (int i = [self count]; i-->0; ) { + [_objs[i] performSelector: selector withObject: anObject]; + } +} + +- (void) makeReversedObjectsPerformSelector: (SEL)selector + if: (condition_func)condition + with: (void *)data +{ + for (int i = [self count]; i-->0; ) { + if (condition (_objs[i], data)) { + [_objs[i] performSelector: selector]; + } + } +} + +- (void) makeReversedObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject + if: (condition_func2)condition + with: (void *)data +{ + for (int i = [self count]; i-->0; ) { + if (condition (_objs[i], anObject, data)) { + [_objs[i] performSelector: selector withObject: anObject]; + } + } +} +@end + @implementation Group -init { From 40ae7a7f1902dceb4aae554ec852571fc2393cd4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 11:53:40 +0900 Subject: [PATCH 0544/3664] [qwaq] Implement ofDontDraw The conditional selector performance seems to work nicely, but I've found a mistake with View.window (partly, realizing why my old lib (and probably TV in the first place) had separate textContext and buffers between views and groups). --- ruamoko/qwaq/qwaq-group.h | 1 + ruamoko/qwaq/qwaq-group.r | 20 ++++++++++++++++++-- ruamoko/qwaq/qwaq-screen.r | 18 ++++++------------ ruamoko/qwaq/qwaq-view.h | 3 +-- ruamoko/qwaq/qwaq-view.r | 6 ------ 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index a1b58fbae..a5cf5635e 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -31,6 +31,7 @@ typedef BOOL condition_func2 (id object, void *anObject, void *data); { Array *views; int focused; + struct window_s *window; } -insert: (View *) view; -remove: (View *) view; diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 3d03c3402..c25c6b9ee 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -91,7 +91,7 @@ -insert: (View *) view { - [views insertObject: view atIndex: 0]; + [views addObject: view]; return self; } @@ -109,9 +109,25 @@ return self; } +static BOOL +not_dont_draw (id aView, void *aGroup) +{ + View *view = aView; + Group *group = (Group *) aGroup; + if (!(view.options & ofDontDraw)) { + if (!view.textContext) { + view.textContext = group.window; + } + return YES; + } + return NO; +} + -draw { - [views makeObjectsPerformSelector: @selector(draw)]; + [views makeObjectsPerformSelector: @selector(draw) + if: not_dont_draw + with: self]; return self; } diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index e39406448..7b7a9c9cd 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -13,14 +13,14 @@ if (!(self = [super initWithRect:getwrect (stdscr)])) { return nil; } - window = stdscr; - scrollok (window, 1); + textContext = stdscr; + scrollok (textContext, 1); return self; } -setBackground: (int) ch { - wbkgd (window, ch); + wbkgd (textContext, ch); return self; } @@ -43,26 +43,20 @@ -redraw { update_panels (); - wrefresh(window); + wrefresh(textContext); doupdate (); return self; } -printf: (string) fmt, ... { - wvprintf (window, fmt, @args); + wvprintf (textContext, fmt, @args); return self; } -addch: (int) ch atX: (int) x Y: (int) y { - mvwaddch(window, x, y, ch); - return self; -} - --setOwner: owner -{ - self.owner = owner; + mvwaddch(textContext, x, y, ch); return self; } diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index bd38962e6..a168268af 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -44,7 +44,7 @@ enum { Rect absRect; Point point; // can't be local :( Group *owner; - struct window_s *window; + struct window_s *textContext; //FIXME separate class int state; int options; int cursorState; @@ -52,7 +52,6 @@ enum { } -initWithRect: (Rect) rect; - (void) dealloc; --(struct window_s *) getWindow; -setOwner: (Group *) owner; -(struct Rect_s *)getRect; -draw; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 3fb5b4e77..6b6f3e80d 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -97,15 +97,9 @@ updateScreenCursor (View *view) -setOwner: (Group *) owner { self.owner = owner; - window = [owner getWindow]; return self; } --(window_t) getWindow -{ - return window; -} - - (Rect *) getRect { return ▭ From ba9c43d2d3b323204415cc85234a390d2a6d1852 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 13:54:46 +0900 Subject: [PATCH 0545/3664] [qwaq] Create a TextContext class It is essentially just a wrapper around the window versions of ncurses functions. --- ruamoko/qwaq/Makefile.am | 7 +- ruamoko/qwaq/qwaq-app.r | 32 --- ruamoko/qwaq/qwaq-curses.c | 376 ++++++++++++++++++++++++++++---- ruamoko/qwaq/qwaq-curses.h | 2 + ruamoko/qwaq/qwaq-rect.h | 2 + ruamoko/qwaq/qwaq-textcontext.h | 46 ++++ ruamoko/qwaq/qwaq-textcontext.r | 92 ++++++++ 7 files changed, 481 insertions(+), 76 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-textcontext.h create mode 100644 ruamoko/qwaq/qwaq-textcontext.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index ab08a5579..cf71f7590 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -24,7 +24,12 @@ SUFFIXES=.o .r $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo qwaq_app_dat_src= \ - qwaq-app.r qwaq-group.r qwaq-screen.r qwaq-window.r qwaq-view.r + qwaq-app.r \ + qwaq-group.r \ + qwaq-screen.r \ + qwaq-textcontext.r \ + qwaq-view.r \ + qwaq-window.r qwaq_curses_libs= qwaq_curses_SOURCES=main.c qwaq-curses.c diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index dfd82e096..9d046a89f 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -97,35 +97,3 @@ int main (int argc, string *argv) get_event (&event); // XXX need a "wait for queue idle" return 0; } - -window_t stdscr = (window_t) 1; - -void initialize (void) = #0; -window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; -void destroy_window (window_t win) = #0; -void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; -void wprintf (window_t win, string fmt, ...) = #0; -void wvprintf (window_t win, string fmt, @va_list args) = #0; -void wrefresh (window_t win) = #0; -void mvwaddch (window_t win, int x, int y, int ch) = #0; -int get_event (qwaq_event_t *event) = #0; -int max_colors (void) = #0; -int max_color_pairs (void) = #0; -int init_pair (int pair, int f, int b) = #0; -void wbkgd (window_t win, int ch) = #0; -void scrollok (window_t win, int flag) = #0; -int acs_char (int acs) = #0; - -panel_t create_panel (window_t window) = #0; -void destroy_panel (panel_t panel) = #0; -void hide_panel (panel_t panel) = #0; -void show_panel (panel_t panel) = #0; -void top_panel (panel_t panel) = #0; -void bottom_panel (panel_t panel) = #0; -void move_panel (panel_t panel, int x, int y) = #0; -window_t panel_window (panel_t panel) = #0; -void update_panels (void) = #0; -void doupdate (void) = #0; -int curs_set (int visibility) = #0; -int move (int x, int y) = #0; -void wborder (window_t window, box_sides_t sides, box_corners_t corners) = #0; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 73c500368..f625f80ec 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -44,6 +44,8 @@ #include "qwaq.h" #include "event.h" #include "qwaq-curses.h" +#include "qwaq-rect.h" +#include "qwaq-textcontext.h" #define always_inline inline __attribute__((__always_inline__)) #define QUEUE_SIZE 16 @@ -856,10 +858,9 @@ bi_delwin (progs_t *pr) } static void -bi_getwrect (progs_t *pr) +qwaq_getwrect (progs_t *pr, int window_id) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int window_id = P_INT (pr, 0); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_getwrect, 0, window_id, }; @@ -876,6 +877,11 @@ bi_getwrect (progs_t *pr) (&R_INT (pr))[3] = cmd_result[4]; } } +static void +bi_getwrect (progs_t *pr) +{ + qwaq_getwrect (pr, P_INT (pr, 0)); +} static void bi_new_panel (progs_t *pr) @@ -992,15 +998,10 @@ bi_doupdate (progs_t *pr) } static void -bi_mvwprintf (progs_t *pr) +qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, + int count, pr_type_t **args) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int window_id = P_INT (pr, 0); - int x = P_INT (pr, 1); - int y = P_INT (pr, 2); - const char *fmt = P_GSTRING (pr, 3); - int count = pr->pr_argc - 4; - pr_type_t **args = pr->pr_params + 4; if (get_window (res, __FUNCTION__, window_id)) { int string_id = acquire_string (res); @@ -1018,15 +1019,24 @@ bi_mvwprintf (progs_t *pr) qwaq_submit_command (res, command); } } +static void +bi_mvwprintf (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + const char *fmt = P_GSTRING (pr, 3); + int count = pr->pr_argc - 4; + pr_type_t **args = pr->pr_params + 4; + + qwaq_mvwprintf (pr, window_id, x, y, fmt, count, args); +} static void -bi_wprintf (progs_t *pr) +qwaq_wprintf (progs_t *pr, int window_id, const char *fmt, + int count, pr_type_t **args) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int window_id = P_INT (pr, 0); - const char *fmt = P_GSTRING (pr, 1); - int count = pr->pr_argc - 2; - pr_type_t **args = pr->pr_params + 2; if (get_window (res, __FUNCTION__, window_id)) { int string_id = acquire_string (res); @@ -1044,14 +1054,21 @@ bi_wprintf (progs_t *pr) qwaq_submit_command (res, command); } } - static void -bi_wvprintf (progs_t *pr) +bi_wprintf (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); int window_id = P_INT (pr, 0); const char *fmt = P_GSTRING (pr, 1); - __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 2); + int count = pr->pr_argc - 2; + pr_type_t **args = pr->pr_params + 2; + + qwaq_wprintf (pr, window_id, fmt, count, args); +} + +static void +qwaq_wvprintf (progs_t *pr, int window_id, const char *fmt, pr_va_list_t *args) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); pr_type_t *list_start = PR_GetPointer (pr, args->list); pr_type_t **list = alloca (args->count * sizeof (*list)); @@ -1075,15 +1092,60 @@ bi_wvprintf (progs_t *pr) qwaq_submit_command (res, command); } } +static void +bi_wvprintf (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + const char *fmt = P_GSTRING (pr, 1); + __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 2); + + qwaq_wvprintf (pr, window_id, fmt, args); +} static void -bi_mvwaddch (progs_t *pr) +qwaq_mvwvprintf (progs_t *pr, int window_id, int x, int y, + const char *fmt, pr_va_list_t *args) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + pr_type_t *list_start = PR_GetPointer (pr, args->list); + pr_type_t **list = alloca (args->count * sizeof (*list)); + + for (int i = 0; i < args->count; i++) { + list[i] = list_start + i * pr->pr_param_size; + } + + if (get_window (res, __FUNCTION__, window_id)) { + int string_id = acquire_string (res); + dstring_t *print_buffer = res->strings + string_id; + int command[] = { + qwaq_cmd_mvwaddstr, 0, + window_id, x, y, string_id + }; + + command[1] = CMD_SIZE(command); + + dstring_clearstr (print_buffer); + PR_Sprintf (pr, print_buffer, "waddstr", fmt, args->count, list); + + qwaq_submit_command (res, command); + } +} +static void +bi_mvwvprintf (progs_t *pr) +{ int window_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); - int ch = P_INT (pr, 3); + const char *fmt = P_GSTRING (pr, 2); + __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 3); + + qwaq_mvwvprintf (pr, x, y, window_id, fmt, args); +} + +static void +qwaq_mvwaddch (progs_t *pr, int window_id, int x, int y, int ch) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { @@ -1094,12 +1156,21 @@ bi_mvwaddch (progs_t *pr) qwaq_submit_command (res, command); } } +static void +bi_mvwaddch (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + int ch = P_INT (pr, 3); + + qwaq_mvwaddch (pr, window_id, x, y, ch); +} static void -bi_wrefresh (progs_t *pr) +qwaq_wrefresh (progs_t *pr, int window_id) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int window_id = P_INT (pr, 0); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wrefresh, 0, window_id, }; @@ -1107,6 +1178,13 @@ bi_wrefresh (progs_t *pr) qwaq_submit_command (res, command); } } +static void +bi_wrefresh (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + + qwaq_wrefresh (pr, window_id); +} static void bi_get_event (progs_t *pr) @@ -1132,24 +1210,28 @@ bi_max_color_pairs (progs_t *pr) } static void -bi_init_pair (progs_t *pr) +qwaq_init_pair (progs_t *pr, int pair, int f, int b) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int pair = P_INT (pr, 0); - int f = P_INT (pr, 1); - int b = P_INT (pr, 2); int command[] = { qwaq_cmd_init_pair, 0, pair, f, b, }; command[1] = CMD_SIZE(command); qwaq_submit_command (res, command); } +static void +bi_init_pair (progs_t *pr) +{ + int pair = P_INT (pr, 0); + int f = P_INT (pr, 1); + int b = P_INT (pr, 2); + + qwaq_init_pair (pr, pair, f, b); +} static void -bi_wbkgd (progs_t *pr) +qwaq_wbkgd (progs_t *pr, int window_id, int ch) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int window_id = P_INT (pr, 0); - int ch = P_INT (pr, 1); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wbkgd, 0, window_id, ch, }; @@ -1157,13 +1239,19 @@ bi_wbkgd (progs_t *pr) qwaq_submit_command (res, command); } } +static void +bi_wbkgd (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + int ch = P_INT (pr, 1); + + qwaq_wbkgd (pr, window_id, ch); +} static void -bi_scrollok (progs_t *pr) +qwaq_scrollok (progs_t *pr, int window_id, int flag) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int window_id = P_INT (pr, 0); - int flag = P_INT (pr, 1); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_scrollok, 0, window_id, flag, }; @@ -1171,12 +1259,19 @@ bi_scrollok (progs_t *pr) qwaq_submit_command (res, command); } } +static void +bi_scrollok (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + int flag = P_INT (pr, 1); + + qwaq_scrollok (pr, window_id, flag); +} static const char qwaq_acs_char_map[] = "lmkjtuvwqxnos`afg~,+.-hi0pryz{|}"; static void -bi_acs_char (progs_t *pr) +qwaq_acs_char (progs_t *pr, unsigned acs) { - unsigned acs = P_INT (pr, 0); if (acs < 256) { R_INT (pr) = NCURSES_ACS(acs); } else if (acs - 256 < sizeof (qwaq_acs_char_map)) { @@ -1185,37 +1280,54 @@ bi_acs_char (progs_t *pr) R_INT (pr) = 0; } } +static void +bi_acs_char (progs_t *pr) +{ + int acs = P_INT (pr, 0); + + qwaq_acs_char (pr, acs); +} static void -bi_move (progs_t *pr) +qwaq_move (progs_t *pr, int x, int y) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int x = P_INT (pr, 0); - int y = P_INT (pr, 1); int command[] = { qwaq_cmd_move, 0, x, y, }; command[1] = CMD_SIZE(command); qwaq_submit_command (res, command); } +static void +bi_move (progs_t *pr) +{ + int x = P_INT (pr, 0); + int y = P_INT (pr, 1); + + qwaq_move (pr, x, y); +} static void -bi_curs_set (progs_t *pr) +qwaq_curs_set (progs_t *pr, int visibility) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int visibility = P_INT (pr, 0); int command[] = { qwaq_cmd_curs_set, 0, visibility, }; command[1] = CMD_SIZE(command); qwaq_submit_command (res, command); } +static void +bi_curs_set (progs_t *pr) +{ + int visibility = P_INT (pr, 0); + + qwaq_curs_set (pr, visibility); +} static void -bi_wborder (progs_t *pr) +qwaq_wborder (progs_t *pr, int window_id, + box_sides_t sides, box_corners_t corns) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - int window_id = P_INT (pr, 0); - __auto_type sides = P_PACKED (pr, box_sides_t, 1); - __auto_type corns = P_PACKED (pr, box_corners_t, 2); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wborder, 0, window_id, @@ -1225,6 +1337,15 @@ bi_wborder (progs_t *pr) qwaq_submit_command (res, command); } } +static void +bi_wborder (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + __auto_type sides = P_PACKED (pr, box_sides_t, 1); + __auto_type corns = P_PACKED (pr, box_corners_t, 2); + + qwaq_wborder (pr, window_id, sides, corns); +} static void bi_initialize (progs_t *pr) @@ -1247,6 +1368,155 @@ bi_initialize (progs_t *pr) res->stdscr.win = stdscr; } +static void +bi_c_TextContext__is_initialized (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + R_INT (pr) = res->initialized; +} + +static void +bi_c_TextContext__max_colors (progs_t *pr) +{ + bi_max_colors (pr); +} + +static void +bi_c_TextContext__max_color_pairs (progs_t *pr) +{ + bi_max_color_pairs (pr); +} + +static void +bi_c_TextContext__init_pair_ (progs_t *pr) +{ + int pair = P_INT (pr, 2); + int f = P_INT (pr, 3); + int b = P_INT (pr, 4); + + qwaq_init_pair (pr, pair, f, b); +} + +static void +bi_c_TextContext__acs_char_ (progs_t *pr) +{ + int acs = P_INT (pr, 2); + + qwaq_acs_char (pr, acs); +} + +static void +bi_c_TextContext__move_ (progs_t *pr) +{ + Point *pos = &P_PACKED (pr, Point, 2); + + qwaq_move (pr, pos->x, pos->y); +} + +static void +bi_c_TextContext__curs_set_ (progs_t *pr) +{ + int visibility = P_INT (pr, 2); + + qwaq_curs_set (pr, visibility); +} + +static void +bi_c_TextContext__doupdate (progs_t *pr) +{ + bi_doupdate (pr); +} + +static void +bi_i_TextContext__mvprintf_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + Point *pos = &P_PACKED (pr, Point, 2); + const char *fmt = P_GSTRING (pr, 3); + int count = pr->pr_argc - 4; + pr_type_t **args = pr->pr_params + 4; + + qwaq_mvwprintf (pr, window_id, pos->x, pos->y, fmt, count, args); +} + +static void +bi_i_TextContext__printf_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + const char *fmt = P_GSTRING (pr, 2); + int count = pr->pr_argc - 3; + pr_type_t **args = pr->pr_params + 3; + + qwaq_wprintf (pr, window_id, fmt, count, args); +} + +static void +bi_i_TextContext__vprintf_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + const char *fmt = P_GSTRING (pr, 2); + __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 3); + + qwaq_wvprintf (pr, window_id, fmt, args); +} + +static void +bi_i_TextContext__mvvprintf_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + Point *pos = &P_PACKED (pr, Point, 2); + const char *fmt = P_GSTRING (pr, 3); + __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 4); + + qwaq_mvwvprintf (pr, pos->x, pos->y, window_id, fmt, args); +} + +static void +bi_i_TextContext__refresh (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + + qwaq_wrefresh (pr, window_id); +} + +static void +bi_i_TextContext__mvaddch_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + Point *pos = &P_PACKED (pr, Point, 2); + int ch = P_INT (pr, 3); + + qwaq_mvwaddch (pr, window_id, pos->x, pos->y, ch); +} + +static void +bi_i_TextContext__bkgd_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + int ch = P_INT (pr, 2); + + qwaq_wbkgd (pr, window_id, ch); +} + +static void +bi_i_TextContext__scrollok_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + int flag = P_INT (pr, 2); + + qwaq_scrollok (pr, window_id, flag); +} + +static void +bi_i_TextContext__border_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + __auto_type sides = P_PACKED (pr, box_sides_t, 2); + __auto_type corns = P_PACKED (pr, box_corners_t, 3); + + qwaq_wborder (pr, window_id, sides, corns); +} + static void bi_qwaq_clear (progs_t *pr, void *data) { @@ -1279,6 +1549,7 @@ static builtin_t builtins[] = { {"mvwprintf", bi_mvwprintf, -1}, {"wprintf", bi_wprintf, -1}, {"wvprintf", bi_wvprintf, -1}, + {"mvwvprintf", bi_mvwvprintf, -1}, {"mvwaddch", bi_mvwaddch, -1}, {"wrefresh", bi_wrefresh, -1}, {"get_event", bi_get_event, -1}, @@ -1291,6 +1562,25 @@ static builtin_t builtins[] = { {"move", bi_move, -1}, {"curs_set", bi_curs_set, -1}, {"wborder", bi_wborder, -1}, + + {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, + {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, + {"_c_TextContext__max_color_pairs", bi_c_TextContext__max_color_pairs, -1}, + {"_c_TextContext__init_pair_", bi_c_TextContext__init_pair_, -1}, + {"_c_TextContext__acs_char_", bi_c_TextContext__acs_char_, -1}, + {"_c_TextContext__move_", bi_c_TextContext__move_, -1}, + {"_c_TextContext__curs_set_", bi_c_TextContext__curs_set_, -1}, + {"_c_TextContext__doupdate", bi_c_TextContext__doupdate, -1}, + {"_i_TextContext__mvprintf_", bi_i_TextContext__mvprintf_, -1}, + {"_i_TextContext__printf_", bi_i_TextContext__printf_, -1}, + {"_i_TextContext__vprintf_", bi_i_TextContext__vprintf_, -1}, + {"_i_TextContext__mvvprintf_", bi_i_TextContext__mvvprintf_, -1}, + {"_i_TextContext__refresh", bi_i_TextContext__refresh, -1}, + {"_i_TextContext__mvaddch_", bi_i_TextContext__mvaddch_, -1}, + {"_i_TextContext__bkgd_", bi_i_TextContext__bkgd_, -1}, + {"_i_TextContext__scrollok_", bi_i_TextContext__scrollok_, -1}, + {"_i_TextContext__border_", bi_i_TextContext__border_, -1}, + {0} }; diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 62bdef880..aa9d2456d 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -90,6 +90,8 @@ typedef struct panel_s *panel_t; @extern void mvwprintf (window_t win, int x, int y, string fmt, ...); @extern void wprintf (window_t win, string fmt, ...); @extern void wvprintf (window_t win, string fmt, @va_list args); +@extern void mvwvprintf (window_t win, int x, int y, + string fmt, @va_list args); @extern void wrefresh (window_t win); @extern void mvwaddch (window_t win, int x, int y, int ch); diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index 8976d25db..92c241f40 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -16,9 +16,11 @@ typedef struct Rect_s { Extent extent; } Rect; +#ifdef __QFCC__ @extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); //XXX will not work if point or rect point to a local variabl @extern int rectContainsPoint (Rect *rect, Point *point); @extern Rect getwrect (struct window_s *window); +#endif #endif//__qwaq_rect_h diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/qwaq-textcontext.h new file mode 100644 index 000000000..8cd20d74f --- /dev/null +++ b/ruamoko/qwaq/qwaq-textcontext.h @@ -0,0 +1,46 @@ +#ifndef __qwaq_textcontect_h +#define __qwaq_textcontect_h + +#ifdef __QFCC__ +#include +#include "qwaq-curses.h" +#include "qwaq-rect.h" + +@interface TextContext : Object +{ + window_t window; +} ++ (int) max_colors; ++ (int) max_color_pairs; ++ (void) init_pair: (int) pair, int fg, int bg; ++ (int) acs_char: (int) acs; ++ (void) move: (Point) pos; ++ (void) curs_set: (int) visibility; ++ (void) doupdate; + +-init; +-initWithRect: (Rect) rect; +-initWithWindow: (window_t) window; +- (void) mvprintf: (Point) pos, string fmt, ...; +- (void) printf: (string) fmt, ...; +- (void) vprintf: (string) mft, @va_list args; +- (void) mvvprintf: (Point) pos, string mft, @va_list args; +- (void) refresh; +- (void) mvaddch: (Point) pos, int ch; +- (void) bkgd: (int) ch; +- (void) scrollok: (int) flag; +- (void) border: (box_sides_t) sides, box_corners_t corners; +@end + +#else + +#include "QF/pr_obj.h" + +typedef struct qwaq_textcontext_s { + pr_id_t isa; + pointer_t window; +} qwaq_textcontext_t; + +#endif + +#endif//__qwaq_textcontect_h diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r new file mode 100644 index 000000000..43c8f9320 --- /dev/null +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -0,0 +1,92 @@ +#include "qwaq-textcontext.h" + +@implementation TextContext ++ (int) is_initialized = #0; ++ (void) initialize +{ + if (![self is_initialized]) { + initialize (); + } +} + ++ (int) max_colors = #0; ++ (int) max_color_pairs = #0; ++ (void) init_pair: (int) pair, int fg, int bg = #0; ++ (int) acs_char: (int) acs = #0; ++ (void) move: (Point) pos = #0; ++ (void) curs_set: (int) visibility = #0; ++ (void) doupdate = #0; + +- init +{ + if (!(self = [super init])) { + return nil; + } + window = stdscr; + return self; +} + +- initWithRect: (Rect) rect +{ + if (!(self = [super init])) { + return nil; + } + window = create_window (rect.offset.x, rect.offset.y, + rect.extent.width, rect.extent.height); + return self; +} + +- initWithWindow: (window_t) window +{ + if (!(self = [super init])) { + return nil; + } + self.window = window; + return self; +} + +- (void) mvprintf: (Point) pos, string fmt, ... = #0; +- (void) printf: (string) fmt, ... = #0; +- (void) vprintf: (string) mft, @va_list args = #0; +- (void) mvvprintf: (Point) pos, string mft, @va_list args = #0; +- (void) refresh = #0; +- (void) mvaddch: (Point) pos, int ch = #0; +- (void) bkgd: (int) ch = #0; +- (void) scrollok: (int) flag = #0; +- (void) border: (box_sides_t) sides, box_corners_t corners = #0; + +@end + +window_t stdscr = (window_t) 1; + +void initialize (void) = #0; +window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; +void destroy_window (window_t win) = #0; +void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; +void wprintf (window_t win, string fmt, ...) = #0; +void wvprintf (window_t win, string fmt, @va_list args) = #0; +void mvwvprintf (window_t win, int x, int y, string fmt, @va_list args) = #0; +void wrefresh (window_t win) = #0; +void mvwaddch (window_t win, int x, int y, int ch) = #0; +int get_event (qwaq_event_t *event) = #0; +int max_colors (void) = #0; +int max_color_pairs (void) = #0; +int init_pair (int pair, int f, int b) = #0; +void wbkgd (window_t win, int ch) = #0; +void scrollok (window_t win, int flag) = #0; +int acs_char (int acs) = #0; + +panel_t create_panel (window_t window) = #0; +void destroy_panel (panel_t panel) = #0; +void hide_panel (panel_t panel) = #0; +void show_panel (panel_t panel) = #0; +void top_panel (panel_t panel) = #0; +void bottom_panel (panel_t panel) = #0; +void move_panel (panel_t panel, int x, int y) = #0; +window_t panel_window (panel_t panel) = #0; +void update_panels (void) = #0; + +void doupdate (void) = #0; +int curs_set (int visibility) = #0; +int move (int x, int y) = #0; +void wborder (window_t window, box_sides_t sides, box_corners_t corners) = #0; From a2cebe3cac830343202cb6246f0fd80788a05929 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 17:36:23 +0900 Subject: [PATCH 0546/3664] [qfcc] Add failing test for method parameters --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/methodparams.r | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 tools/qfcc/test/methodparams.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 2e1001c11..7ea8e5c21 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -43,6 +43,7 @@ test_progs_dat=\ func-static.dat \ infloop.dat \ ivar-struct-return.dat \ + methodparams.dat \ modulo.dat \ paramret.dat \ quaternion.dat \ @@ -258,6 +259,15 @@ ivar-struct-return.run: Makefile build-run include ./$(DEPDIR)/ivar-struct-return.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/ivar-struct-return.Qo +methodparams_dat_SOURCES=methodparams.r +methodparams_obj=$(methodparams_dat_SOURCES:.r=.qfo) +methodparams.dat$(EXEEXT): $(methodparams_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(methodparams_obj) +methodparams.run: Makefile build-run + @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ +include ./$(DEPDIR)/methodparams.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/methodparams.Qo + modulo_dat_SOURCES=modulo.r modulo_obj=$(modulo_dat_SOURCES:.r=.qfo) modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/methodparams.r b/tools/qfcc/test/methodparams.r new file mode 100644 index 000000000..b91322358 --- /dev/null +++ b/tools/qfcc/test/methodparams.r @@ -0,0 +1,17 @@ +typedef struct { int x, y; } Point; +@interface TextContext +- (void) mvvprintf: (Point) pos, string mft, @va_list args; +@end +@interface View +{ + TextContext *textContext; +} +- (void) mvprintf: (Point) pos, string mft, ...; +@end + +@implementation View +- (void) mvprintf: (Point) pos, string fmt, ... +{ + [textContext mvvprintf: pos, fmt, @args]; +} +@end From 9b269c2f8ecda23231d33be6bbda7abe3a71d758 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 17:14:14 +0900 Subject: [PATCH 0547/3664] [qfcc] Fix mangled method parameters Method parameters (ie, extra parameters without selector names) were getting reversed during function type construction. --- tools/qfcc/include/function.h | 2 +- tools/qfcc/source/function.c | 16 +++++++++++++++- tools/qfcc/source/method.c | 6 +++--- tools/qfcc/source/qc-parse.y | 3 +-- tools/qfcc/test/methodparams.r | 12 ++++++++++++ 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 209f40026..39cde918c 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -119,8 +119,8 @@ param_t *new_param (const char *selector, struct type_s *type, const char *name); param_t *param_append_identifiers (param_t *params, struct symbol_s *idents, struct type_s *type); -param_t *_reverse_params (param_t *params, param_t *next); param_t *reverse_params (param_t *params); +param_t *append_params (param_t *params, param_t *more_params); param_t *copy_params (param_t *params); struct type_s *parse_params (struct type_s *type, param_t *params); param_t *check_params (param_t *params); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index ff54b2ce5..7f53cd11d 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -120,7 +120,7 @@ param_append_identifiers (param_t *params, symbol_t *idents, type_t *type) return params; } -param_t * +static param_t * _reverse_params (param_t *params, param_t *next) { param_t *p = params; @@ -138,6 +138,20 @@ reverse_params (param_t *params) return _reverse_params (params, 0); } +param_t * +append_params (param_t *params, param_t *more_params) +{ + if (params) { + param_t *p; + for (p = params; p->next; ) { + p = p->next; + } + p->next = more_params; + return params; + } + return more_params; +} + param_t * copy_params (param_t *params) { diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index e68ad857f..676726a5c 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -89,8 +89,8 @@ new_method (type_t *ret_type, param_t *selector, param_t *opt_params) dstring_t *name = dstring_newstr (); dstring_t *types = dstring_newstr (); - opt_params = reverse_params (opt_params); - selector = _reverse_params (selector, opt_params); + selector = reverse_params (selector); + selector = append_params (selector, opt_params); cmd->next = selector; self->next = cmd; @@ -109,7 +109,7 @@ new_method (type_t *ret_type, param_t *selector, param_t *opt_params) free (name); free (types); - //print_type (meth->type); puts (""); + //print_type (meth->type); meth->def = 0; if (!known_methods) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 3732e47b7..93f4aeea9 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -2010,8 +2010,7 @@ optional_param_list | ',' param_list { $$ = $2; } | ',' param_list ',' ELLIPSIS { - $$ = new_param (0, 0, 0); - $$->next = $2; + $$ = param_append_identifiers ($2, 0, 0); } ; diff --git a/tools/qfcc/test/methodparams.r b/tools/qfcc/test/methodparams.r index b91322358..b29e6954b 100644 --- a/tools/qfcc/test/methodparams.r +++ b/tools/qfcc/test/methodparams.r @@ -15,3 +15,15 @@ typedef struct { int x, y; } Point; [textContext mvvprintf: pos, fmt, @args]; } @end +id obj_msgSend (id receiver, SEL op, ...) = #0; +void __obj_exec_class (struct obj_module *msg) = #0; +@interface Object +@end +@implementation Object +@end + +int +main (void) +{ + return 0; // to survive and prevail :) +} From bea64838cc3aac2519ce91ba8e317e57a6bfbd05 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 17:25:19 +0900 Subject: [PATCH 0548/3664] [qwaq] Use new TextContext Not quite right yet, but it worked first try (once I got another compiler bug sorted). --- ruamoko/qwaq/qwaq-group.h | 2 +- ruamoko/qwaq/qwaq-group.r | 2 +- ruamoko/qwaq/qwaq-screen.h | 2 -- ruamoko/qwaq/qwaq-screen.r | 26 ++++++--------------- ruamoko/qwaq/qwaq-textcontext.h | 8 +++++-- ruamoko/qwaq/qwaq-textcontext.r | 14 +++++++++++ ruamoko/qwaq/qwaq-view.h | 11 ++++++++- ruamoko/qwaq/qwaq-view.r | 41 +++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-window.r | 22 +++++++++--------- 9 files changed, 91 insertions(+), 37 deletions(-) diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index a5cf5635e..b599a0c36 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -31,7 +31,7 @@ typedef BOOL condition_func2 (id object, void *anObject, void *data); { Array *views; int focused; - struct window_s *window; + TextContext *buffer; } -insert: (View *) view; -remove: (View *) view; diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index c25c6b9ee..6b8296182 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -116,7 +116,7 @@ not_dont_draw (id aView, void *aGroup) Group *group = (Group *) aGroup; if (!(view.options & ofDontDraw)) { if (!view.textContext) { - view.textContext = group.window; + view.textContext = group.buffer; } return YES; } diff --git a/ruamoko/qwaq/qwaq-screen.h b/ruamoko/qwaq/qwaq-screen.h index e92daa2a4..c51910d0e 100644 --- a/ruamoko/qwaq/qwaq-screen.h +++ b/ruamoko/qwaq/qwaq-screen.h @@ -11,8 +11,6 @@ +(Screen *) screen; -handleEvent: (qwaq_event_t *) event; -setBackground: (int) ch; --printf: (string) fmt, ...; --addch: (int) ch atX: (int) x Y: (int) y; @end #endif//__qwaq_screen_h diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index 7b7a9c9cd..e34ddb7c9 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -13,14 +13,8 @@ if (!(self = [super initWithRect:getwrect (stdscr)])) { return nil; } - textContext = stdscr; - scrollok (textContext, 1); - return self; -} - --setBackground: (int) ch -{ - wbkgd (textContext, ch); + textContext = [TextContext screen]; + [textContext scrollok: 1]; return self; } @@ -36,27 +30,21 @@ -draw { update_panels (); - doupdate (); + [TextContext doupdate]; return self; } -redraw { update_panels (); - wrefresh(textContext); - doupdate (); + [textContext refresh]; + [TextContext doupdate]; return self; } --printf: (string) fmt, ... +-setBackground: (int) ch { - wvprintf (textContext, fmt, @args); - return self; -} - --addch: (int) ch atX: (int) x Y: (int) y -{ - mvwaddch(textContext, x, y, ch); + [textContext bkgd:ch]; return self; } diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/qwaq-textcontext.h index 8cd20d74f..952814f08 100644 --- a/ruamoko/qwaq/qwaq-textcontext.h +++ b/ruamoko/qwaq/qwaq-textcontext.h @@ -17,16 +17,20 @@ + (void) move: (Point) pos; + (void) curs_set: (int) visibility; + (void) doupdate; ++ (TextContext *) screen; -init; -initWithRect: (Rect) rect; -initWithWindow: (window_t) window; -- (void) mvprintf: (Point) pos, string fmt, ...; + +-(window_t) window; + - (void) printf: (string) fmt, ...; - (void) vprintf: (string) mft, @va_list args; +- (void) mvprintf: (Point) pos, string fmt, ...; - (void) mvvprintf: (Point) pos, string mft, @va_list args; -- (void) refresh; - (void) mvaddch: (Point) pos, int ch; +- (void) refresh; - (void) bkgd: (int) ch; - (void) scrollok: (int) flag; - (void) border: (box_sides_t) sides, box_corners_t corners; diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 43c8f9320..f38947773 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -17,6 +17,15 @@ + (void) curs_set: (int) visibility = #0; + (void) doupdate = #0; +static TextContext *screen; ++ (TextContext *) screen +{ + if (!screen) { + screen = [[TextContext alloc] init]; + } + return screen; +} + - init { if (!(self = [super init])) { @@ -45,6 +54,11 @@ return self; } +-(window_t) window +{ + return window; +} + - (void) mvprintf: (Point) pos, string fmt, ... = #0; - (void) printf: (string) fmt, ... = #0; - (void) vprintf: (string) mft, @va_list args = #0; diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index a168268af..0f8727128 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -6,6 +6,7 @@ #include "qwaq-draw.h" #include "qwaq-rect.h" +#include "qwaq-textcontext.h" @class Group; @@ -44,7 +45,7 @@ enum { Rect absRect; Point point; // can't be local :( Group *owner; - struct window_s *textContext; //FIXME separate class + TextContext *textContext; int state; int options; int cursorState; @@ -56,6 +57,14 @@ enum { -(struct Rect_s *)getRect; -draw; -redraw; + +- (void) refresh; +- (void) printf: (string) fmt, ...; +- (void) vprintf: (string) fmt, @va_list args; +//- (void) addch: (int) ch; +- (void) mvprintf: (Point) pos, string fmt, ...; +- (void) mvvprintf: (Point) pos, string fmt, @va_list args; +- (void) mvaddch: (Point) pos, int ch; @end #endif//__qwaq_view_h diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 6b6f3e80d..f5297c1e7 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -105,6 +105,47 @@ updateScreenCursor (View *view) return ▭ } +- (void) printf: (string) fmt, ... +{ + [textContext vprintf: fmt, @args]; +} + +- (void) vprintf: (string) fmt, @va_list args +{ + [textContext vprintf: fmt, args]; +} + +- (void) refresh +{ + [textContext refresh]; +} +/* +- (void) addch: (int) ch +{ + [textContext addch:ch]; +}*/ + +- (void) mvprintf: (Point) pos, string fmt, ... +{ + pos.x += xpos; + pos.y += ypos; + [textContext mvvprintf: pos, fmt, @args]; +} + +- (void) mvvprintf: (Point) pos, string fmt, @va_list args +{ + pos.x += xpos; + pos.y += ypos; + [textContext mvvprintf: pos, fmt, args]; +} + +- (void) mvaddch: (Point) pos, int ch +{ + pos.x += xpos; + pos.y += ypos; + [textContext mvaddch: pos, ch]; +} + @end Rect getwrect (window_t window) = #0; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 45e8c4a77..3cee19d48 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -18,8 +18,8 @@ return nil; } self.rect = rect; - window = create_window (xpos, ypos, xlen, ylen); - panel = create_panel (window); + buffer = [[TextContext alloc] initWithRect: rect]; + panel = create_panel ([buffer window]); return self; } @@ -69,7 +69,7 @@ -setBackground: (int) ch { - wbkgd (window, ch); + [buffer bkgd: ch]; return self; } @@ -90,24 +90,24 @@ } } [super draw]; - int x = 1, y = 1; - wborder (window, box_sides, box_corners); + [buffer border: box_sides, box_corners]; + Point pos = { 1, 1 }; //for (int i = ACS_ULCORNER; i <= ACS_STERLING; i++) { for (int i = 32; i <= 127; i++) { int ch = acs_char (i); if (ch) { - mvwaddch (window, x, y, ch); + [buffer mvaddch: pos, ch]; } else { - mvwaddch (window, x, y, '.'); + [buffer mvaddch: pos, '.']; } - if (++x > 32) { - x = 1; - if (++y >= ylen) { + if (++pos.x > 32) { + pos.x = 1; + if (++pos.y >= ylen) { break; } } } - wrefresh (window); + [buffer refresh]; return self; } From d0a249590cfc29c07fc28918e753f2135de54616 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 17:45:58 +0900 Subject: [PATCH 0549/3664] [qwaq] Use self where possible for drawing in Window --- ruamoko/qwaq/qwaq-window.r | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 3cee19d48..53bf92d66 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -19,6 +19,7 @@ } self.rect = rect; buffer = [[TextContext alloc] initWithRect: rect]; + textContext = buffer; panel = create_panel ([buffer window]); return self; } @@ -96,9 +97,9 @@ for (int i = 32; i <= 127; i++) { int ch = acs_char (i); if (ch) { - [buffer mvaddch: pos, ch]; + [self mvaddch: pos, ch]; } else { - [buffer mvaddch: pos, '.']; + [self mvaddch: pos, '.']; } if (++pos.x > 32) { pos.x = 1; @@ -107,7 +108,7 @@ } } } - [buffer refresh]; + [self refresh]; return self; } From 9a96a9b2c990bd8b88dec2bd411473b69cb8df54 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 17:46:36 +0900 Subject: [PATCH 0550/3664] [qwaq] Use own version of positional drawing in Window Double offsetting the prints doesn't quite look right ;) --- ruamoko/qwaq/qwaq-window.r | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 53bf92d66..23d919648 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -127,4 +127,19 @@ { return [owner redraw]; } + +- (void) mvprintf: (Point) pos, string fmt, ... +{ + [textContext mvvprintf: pos, fmt, @args]; +} + +- (void) mvvprintf: (Point) pos, string fmt, @va_list args +{ + [textContext mvvprintf: pos, fmt, args]; +} + +- (void) mvaddch: (Point) pos, int ch +{ + [textContext mvaddch: pos, ch]; +} @end From b8b74fc07467d6c1f5a60e0fc73695dd15c3d52c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 17:57:33 +0900 Subject: [PATCH 0551/3664] [qwaq] Implement missing addch I either forgot about it, or just didn't need it at the time, but I'm sure it will be useful later when more stuff is implemented. --- ruamoko/qwaq/qwaq-curses.c | 48 ++++++++++++++++++++++++++++++++- ruamoko/qwaq/qwaq-curses.h | 1 + ruamoko/qwaq/qwaq-textcontext.h | 1 + ruamoko/qwaq/qwaq-textcontext.r | 2 ++ ruamoko/qwaq/qwaq-view.h | 2 +- ruamoko/qwaq/qwaq-view.r | 4 +-- 6 files changed, 54 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index f625f80ec..8b218dfad 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -72,6 +72,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_mvwaddstr, qwaq_cmd_waddstr, qwaq_cmd_mvwaddch, + qwaq_cmd_waddch, qwaq_cmd_wrefresh, qwaq_cmd_init_pair, qwaq_cmd_wbkgd, @@ -532,6 +533,16 @@ cmd_mvwaddch (qwaq_resources_t *res) mvwaddch (window->win, y, x, ch); } +static void +cmd_waddch (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int ch = RB_PEEK_DATA (res->command_queue, 3); + + window_t *window = get_window (res, __FUNCTION__, window_id); + waddch (window->win, ch); +} + static void cmd_wrefresh (qwaq_resources_t *res) { @@ -665,6 +676,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_mvwaddch: cmd_mvwaddch (res); break; + case qwaq_cmd_waddch: + cmd_waddch (res); + break; case qwaq_cmd_wrefresh: cmd_wrefresh (res); break; @@ -1102,6 +1116,27 @@ bi_wvprintf (progs_t *pr) qwaq_wvprintf (pr, window_id, fmt, args); } +static void +qwaq_waddch (progs_t *pr, int window_id, int ch) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_waddch, 0, window_id, ch }; + + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} +static void +bi_waddch (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + int ch = P_INT (pr, 0); + + qwaq_waddch (pr, window_id, ch); +} + static void qwaq_mvwvprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, pr_va_list_t *args) @@ -1451,7 +1486,7 @@ bi_i_TextContext__printf_ (progs_t *pr) } static void -bi_i_TextContext__vprintf_ (progs_t *pr) +bi_i_TextContext__addch_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; const char *fmt = P_GSTRING (pr, 2); @@ -1460,6 +1495,15 @@ bi_i_TextContext__vprintf_ (progs_t *pr) qwaq_wvprintf (pr, window_id, fmt, args); } +static void +bi_i_TextContext__vprintf_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + int ch = P_INT (pr, 1); + + qwaq_waddch (pr, window_id, ch); +} + static void bi_i_TextContext__mvvprintf_ (progs_t *pr) { @@ -1551,6 +1595,7 @@ static builtin_t builtins[] = { {"wvprintf", bi_wvprintf, -1}, {"mvwvprintf", bi_mvwvprintf, -1}, {"mvwaddch", bi_mvwaddch, -1}, + {"waddch", bi_waddch, -1}, {"wrefresh", bi_wrefresh, -1}, {"get_event", bi_get_event, -1}, {"max_colors", bi_max_colors, -1}, @@ -1574,6 +1619,7 @@ static builtin_t builtins[] = { {"_i_TextContext__mvprintf_", bi_i_TextContext__mvprintf_, -1}, {"_i_TextContext__printf_", bi_i_TextContext__printf_, -1}, {"_i_TextContext__vprintf_", bi_i_TextContext__vprintf_, -1}, + {"_i_TextContext__addch_", bi_i_TextContext__addch_, -1}, {"_i_TextContext__mvvprintf_", bi_i_TextContext__mvvprintf_, -1}, {"_i_TextContext__refresh", bi_i_TextContext__refresh, -1}, {"_i_TextContext__mvaddch_", bi_i_TextContext__mvaddch_, -1}, diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index aa9d2456d..16cd4fe4e 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -94,6 +94,7 @@ typedef struct panel_s *panel_t; string fmt, @va_list args); @extern void wrefresh (window_t win); @extern void mvwaddch (window_t win, int x, int y, int ch); +@extern void waddch (window_t win, int ch); @extern panel_t create_panel (window_t window); @extern void destroy_panel (panel_t panel); diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/qwaq-textcontext.h index 952814f08..4a47b16ca 100644 --- a/ruamoko/qwaq/qwaq-textcontext.h +++ b/ruamoko/qwaq/qwaq-textcontext.h @@ -27,6 +27,7 @@ - (void) printf: (string) fmt, ...; - (void) vprintf: (string) mft, @va_list args; +- (void) addch: (int) ch; - (void) mvprintf: (Point) pos, string fmt, ...; - (void) mvvprintf: (Point) pos, string mft, @va_list args; - (void) mvaddch: (Point) pos, int ch; diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index f38947773..59b54fb6a 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -62,6 +62,7 @@ static TextContext *screen; - (void) mvprintf: (Point) pos, string fmt, ... = #0; - (void) printf: (string) fmt, ... = #0; - (void) vprintf: (string) mft, @va_list args = #0; +- (void) addch: (int) ch = #0; - (void) mvvprintf: (Point) pos, string mft, @va_list args = #0; - (void) refresh = #0; - (void) mvaddch: (Point) pos, int ch = #0; @@ -82,6 +83,7 @@ void wvprintf (window_t win, string fmt, @va_list args) = #0; void mvwvprintf (window_t win, int x, int y, string fmt, @va_list args) = #0; void wrefresh (window_t win) = #0; void mvwaddch (window_t win, int x, int y, int ch) = #0; +void waddch (window_t win, int ch) = #0; int get_event (qwaq_event_t *event) = #0; int max_colors (void) = #0; int max_color_pairs (void) = #0; diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 0f8727128..10e0c93ae 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -61,7 +61,7 @@ enum { - (void) refresh; - (void) printf: (string) fmt, ...; - (void) vprintf: (string) fmt, @va_list args; -//- (void) addch: (int) ch; +- (void) addch: (int) ch; - (void) mvprintf: (Point) pos, string fmt, ...; - (void) mvvprintf: (Point) pos, string fmt, @va_list args; - (void) mvaddch: (Point) pos, int ch; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index f5297c1e7..541012a47 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -119,11 +119,11 @@ updateScreenCursor (View *view) { [textContext refresh]; } -/* + - (void) addch: (int) ch { [textContext addch:ch]; -}*/ +} - (void) mvprintf: (Point) pos, string fmt, ... { From 1250fe7446c5f2a676285ccf18f9b53844143083 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 18:29:16 +0900 Subject: [PATCH 0552/3664] [qwaq] Use a log file instead of stderr Now I don't have to worry about remembering to redirect the output, but debugging is still easy. --- ruamoko/qwaq/qwaq-curses.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 8b218dfad..15746b5e6 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1630,11 +1630,13 @@ static builtin_t builtins[] = { {0} }; +static FILE *logfile; + static __attribute__((format(printf, 1, 0))) void qwaq_print (const char *fmt, va_list args) { - vfprintf (stderr, fmt, args); - fflush (stderr); + vfprintf (logfile, fmt, args); + fflush (logfile); } void @@ -1650,5 +1652,6 @@ BI_Init (progs_t *pr) PR_Resources_Register (pr, "qwaq", res, bi_qwaq_clear); PR_RegisterBuiltins (pr, builtins); Sys_RegisterShutdown (bi_shutdown); + logfile = fopen ("qwaq-curses.log", "wt"); Sys_SetStdPrintf (qwaq_print); } From 07e6baf32f66fa372a90b88321f1b6386c1d38c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 20:32:37 +0900 Subject: [PATCH 0553/3664] [qfcc] Support { } as nil in nested initializers Did top-level earlier, but forgot to add support for deeper nestings. --- tools/qfcc/source/def.c | 5 ++++- tools/qfcc/source/qc-parse.y | 21 +++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 93152b6db..cf36912bf 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -450,7 +450,10 @@ init_elements (struct def_s *def, expr_t *eles) if (element->expr) { c = constant_expr (element->expr); } else { - c = convert_nil (new_nil_expr (), type); + c = new_nil_expr (); + } + if (c->type == ex_nil) { + c = convert_nil (c, type); } append_expr (local_expr, assign_expr (unary_expr ('.', ptr), c)); } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 93f4aeea9..ba266c512 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1148,7 +1148,8 @@ opt_initializer var_initializer : '=' expr { $$ = $2; } - | '=' '{' element_list optional_comma '}' { $$ = $3; } + | '=' '{' { $$ = $-1; } + element_list optional_comma '}' { $$ = $4; } | '=' '{' '}' { if (is_scalar ($-1.type)) { @@ -1169,14 +1170,26 @@ element_list $$ = new_block_expr (); append_expr ($$, $1); } - | element_list ',' element + | element_list ',' {$$ = $0; } element { - append_expr ($$, $3); + append_expr ($$, $4); } ; element - : '{' element_list optional_comma '}' { $$ = $2; } + : '{' { $$ = $0; } + element_list optional_comma '}' { $$ = $3; } + | '{' '}' + { + // FIXME doesn't check the right type (does prove the inherited + // attributes have been passed down correctly though). The problem + // is that the type of the sub elements needs to be extracted if + // possible + if (is_scalar ($0.type)) { + error (0, "empty scalar initializer"); + } + $$ = new_nil_expr (); + } | expr { $$ = $1; } ; From 9dbc81432a8212ca19b5106bd23c6657e7743e77 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 20:33:47 +0900 Subject: [PATCH 0554/3664] [qfcc] Use full type for differentiating values This fixes the problem of using nil for two different compound types within the one expression. The problem is all compound types have the same low-level type (ev_invalid) and this caused the two different nils to have the same type when taken back up to expression level. --- tools/qfcc/source/value.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index fc2024a57..97198268c 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -80,7 +80,7 @@ static uintptr_t value_get_hash (const void *_val, void *unused) { const ex_value_t *val = (const ex_value_t *) _val; - return Hash_Buffer (&val->v, sizeof (val->v)) + val->lltype; + return Hash_Buffer (&val->v, sizeof (val->v)) ^ (uintptr_t) val->type; } static int @@ -88,7 +88,7 @@ value_compare (const void *_val1, const void *_val2, void *unused) { const ex_value_t *val1 = (const ex_value_t *) _val1; const ex_value_t *val2 = (const ex_value_t *) _val2; - if (val1->lltype != val2->lltype) + if (val1->type != val2->type) return 0; return memcmp (&val1->v, &val2->v, sizeof (val1->v)) == 0; } From de06efa6047a682e10ee9c45ef868b7b3f1e7715 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 20:38:40 +0900 Subject: [PATCH 0555/3664] [qfcc] Fix handling of nil for static initializers nil is most definitely constant. --- tools/qfcc/source/def.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index cf36912bf..3f2f1c838 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -463,7 +463,10 @@ init_elements (struct def_s *def, expr_t *eles) if (element->expr) { c = constant_expr (element->expr); } else { - c = convert_nil (new_nil_expr (), element->type); + c = new_nil_expr (); + } + if (c->type == ex_nil) { + c = convert_nil (c, element->type); } dummy.offset = def->offset + element->offset; g = D_POINTER (pr_type_t, &dummy); From f0ecf7b30a776d6ec6f50c3e168a304d776d4ace Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 20:43:38 +0900 Subject: [PATCH 0556/3664] [qwaq] Clean out log file with make clean --- ruamoko/qwaq/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index cf71f7590..bf8c2c9b8 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -80,4 +80,4 @@ am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) EXTRA_PROGRAMS=qwaq-curses qwaq-x11 EXTRA_DIST=$(qwaq_dat_src) qwaq.h -CLEANFILES= *.dat *.sym +CLEANFILES= *.dat *.sym qwaq-curses.log From f7757cf894a357681d008c5ee6af650f6df99356 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 21:05:53 +0900 Subject: [PATCH 0557/3664] [qfcc] Add filename to dot output It makes things so much easier when viewing the graphs --- tools/qfcc/source/dot_dag.c | 1 + tools/qfcc/source/dot_expr.c | 1 + tools/qfcc/source/dot_flow.c | 1 + tools/qfcc/source/dot_sblock.c | 1 + 4 files changed, 4 insertions(+) diff --git a/tools/qfcc/source/dot_dag.c b/tools/qfcc/source/dot_dag.c index bf0e26c63..e954f75d3 100644 --- a/tools/qfcc/source/dot_dag.c +++ b/tools/qfcc/source/dot_dag.c @@ -176,6 +176,7 @@ dot_dump_dag (void *_dag, const char *filename) dstring_t *dstr = dstring_newstr(); dasprintf (dstr, "digraph dag_%p {\n", dag); + dasprintf (dstr, " graph [label=\"%s\"];\n", quote_string (filename)); dasprintf (dstr, " layout=dot;\n"); dasprintf (dstr, " clusterrank=local;\n"); dasprintf (dstr, " rankdir=TB;\n"); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 081dbecec..f8601c6ff 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -551,6 +551,7 @@ dump_dot_expr (void *_e, const char *filename) expr_t *e = (expr_t *) _e; dasprintf (dstr, "digraph expr_%p {\n", e); + dasprintf (dstr, " graph [label=\"%s\"];\n", quote_string (filename)); dasprintf (dstr, " layout=dot; rankdir=TB; compound=true;\n"); _print_expr (dstr, e, 0, ++id, 0); dasprintf (dstr, "}\n"); diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index d702f7b9e..68f043d98 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -332,6 +332,7 @@ print_flowgraph (flow_dot_t *method, flowgraph_t *graph, const char *filename) dstring_t *dstr = dstring_newstr(); dasprintf (dstr, "digraph flowgraph_%s_%p {\n", method->type, graph); + dasprintf (dstr, " graph [label=\"%s\"];\n", quote_string (filename)); dasprintf (dstr, " layout=dot;\n"); dasprintf (dstr, " clusterrank=local;\n"); dasprintf (dstr, " rankdir=TB;\n"); diff --git a/tools/qfcc/source/dot_sblock.c b/tools/qfcc/source/dot_sblock.c index 72b245efe..26e32681e 100644 --- a/tools/qfcc/source/dot_sblock.c +++ b/tools/qfcc/source/dot_sblock.c @@ -128,6 +128,7 @@ print_sblock (sblock_t *sblock, const char *filename) dstring_t *dstr = dstring_newstr(); dasprintf (dstr, "digraph sblock_%p {\n", sblock); + dasprintf (dstr, " graph [label=\"%s\"];\n", quote_string (filename)); dasprintf (dstr, " layout=dot; rankdir=TB;\n"); for (i = 0; sblock; sblock = sblock->next, i++) flow_sblock (dstr, sblock, i); From faa6eabfbe0fdf51fd983740f77e65aaae2702b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Mar 2020 22:28:04 +0900 Subject: [PATCH 0558/3664] [qfcc] Add a failing test for struct init to param This actually took a bit to reproduce. --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/struct-init-param.r | 30 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tools/qfcc/test/struct-init-param.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 7ea8e5c21..99c24142c 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -50,6 +50,7 @@ test_progs_dat=\ return-ivar.dat \ sendv.dat \ state.dat \ + struct-init-param.dat \ struct-nil-init.dat \ structarray.dat \ structlive.dat \ @@ -322,6 +323,15 @@ state.run: Makefile build-run include ./$(DEPDIR)/state.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/state.Qo +struct_init_param_dat_SOURCES=struct-init-param.r +struct_init_param_obj=$(struct_init_param_dat_SOURCES:.r=.qfo) +struct-init-param.dat$(EXEEXT): $(struct_init_param_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(struct_init_param_obj) +struct-init-param.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/struct-init-param.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/struct-init-param.Qo + struct_nil_init_dat_SOURCES=struct-nil-init.r struct_nil_init_obj=$(struct_nil_init_dat_SOURCES:.r=.qfo) struct-nil-init.dat$(EXEEXT): $(struct_nil_init_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/struct-init-param.r b/tools/qfcc/test/struct-init-param.r new file mode 100644 index 000000000..8b166099e --- /dev/null +++ b/tools/qfcc/test/struct-init-param.r @@ -0,0 +1,30 @@ +typedef struct { + int x; + int y; +} Point; + +typedef struct { + int width; + int height; +} Extent; + +typedef struct Rect_s { + Point offset; + Extent extent; +} Rect; + +void *foo (void *obj, void *cmd, void *o, Point pos, Rect r) +{ + return obj; +} + +void *bar (Rect *obj, void *cmd, void *o, Point pos) +{ + Rect rect = { {}, obj.extent }; + return foo (obj, cmd, o, pos, rect); +} + +int main (void) +{ + return 1;// don't want this to pass until I've checked the generated code +} From 48514ba2f3dd432371ed3325a46108ecd4f9bb19 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 Mar 2020 01:30:36 +0900 Subject: [PATCH 0559/3664] [qfcc] Create alias def for defs accessed via pointer This the fixes the incorrect flow analysis caused by the def being seen to have the wrong size (structure field of structure def seen through a constant pointer). Fixes the ICE, but the pointer constant is broken somewhere in dags, presumably. --- tools/qfcc/source/flow.c | 4 +++- tools/qfcc/source/statements.c | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 995aa5b7d..aa05733e8 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -859,8 +859,10 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, && s->opc->o.value->lltype == ev_pointer && s->opc->o.value->v.pointer.def) { operand_t *op; + def_t *alias; ex_pointer_t *ptr = &s->opc->o.value->v.pointer; - op = def_operand (ptr->def, ptr->type); + alias = alias_def (ptr->def, ptr->type, ptr->val); + op = def_operand (alias, ptr->type); flow_add_op_var (def, op); if (operands) operands[0] = op; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 239c11f49..e29cedaa4 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -103,7 +103,13 @@ operand_string (operand_t *op) op->o.value->v.quaternion_val[2], op->o.value->v.quaternion_val[3]); case ev_pointer: - return va ("ptr %d", op->o.value->v.pointer.val); + if (op->o.value->v.pointer.def) { + return va ("ptr %s+%d", + op->o.value->v.pointer.def->name, + op->o.value->v.pointer.val); + } else { + return va ("ptr %d", op->o.value->v.pointer.val); + } case ev_field: return va ("field %d", op->o.value->v.pointer.val); case ev_entity: From 6ada20f685fcf4d46dfd2e376d5dd91aa7ead93e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 Mar 2020 02:06:33 +0900 Subject: [PATCH 0560/3664] [qfcc] Show offset for op_x_def_ofs relocs --- tools/qfcc/source/dump_globals.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 657f016e8..157635f63 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -337,6 +337,8 @@ qfo_relocs (qfo_t *qfo) qfo_reloc_t *reloc; qfo_def_t *def; qfo_func_t *func; + int opind; + dstatement_t *statement; unsigned i; for (i = 0; i < qfo->num_relocs; i++) { @@ -399,10 +401,13 @@ qfo_relocs (qfo_t *qfo) case rel_op_b_def_ofs: case rel_op_c_def_ofs: def = qfo->defs + reloc->target; - printf (" op.%c@%x def#%d %s", - reloc->type - rel_op_a_def_ofs + 'a', + opind = reloc->type - rel_op_a_def_ofs; + statement = QFO_STATEMENT (qfo, reloc->offset); + printf (" op.%c@%x def#%d %s+%d", + opind + 'a', reloc->offset, reloc->target, - QFO_GETSTR (qfo, def->name)); + QFO_GETSTR (qfo, def->name), + ((pr_ushort_t *)statement)[opind + 1]); break; case rel_def_def_ofs: def = qfo->defs + reloc->target; From 777ce56cf3090f7b32edec1dbdcbe3e47e8cf4ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 Mar 2020 17:48:19 +0900 Subject: [PATCH 0561/3664] [doc] Enable MathJax Nice. Very nice. --- doc/quakeforge.dox.conf.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/quakeforge.dox.conf.in b/doc/quakeforge.dox.conf.in index 3781f222a..a235a895d 100644 --- a/doc/quakeforge.dox.conf.in +++ b/doc/quakeforge.dox.conf.in @@ -1566,7 +1566,7 @@ FORMULA_TRANSPARENT = YES # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -USE_MATHJAX = NO +USE_MATHJAX = YES # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: From e524db1fc116778859c4bb8cfa00e9b03956d523 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 03:11:46 +0900 Subject: [PATCH 0562/3664] [qfcc] Set op type when aliasing a value This fixes the ICE when attempting to compile address-cast without optimization (just realized why, too: the assignment was optimized out of existence). --- tools/qfcc/source/statements.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e29cedaa4..2f2d0a07d 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -890,6 +890,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) type = e->e.expr.type; sblock = statement_subexpr (sblock, e->e.expr.e1, &aop); if (type_compatible (aop->type, type)) { + //FIXME type_compatible??? shouldn't that be type_size ==? if (offset) { internal_error (e, "offset alias of same size type"); } @@ -924,6 +925,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) *op = def_operand (alias_def (def, type, offset), 0); } else if (aop->op_type == op_value) { *op = value_operand (aop->o.value); + (*op)->type = type; } else { internal_error (e, "invalid alias target: %s: %s", optype_str (aop->op_type), operand_string (aop)); From 2b15e61b28f5c56429115e570788e8b7b8c3ef9f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 03:33:01 +0900 Subject: [PATCH 0563/3664] [qfcc] Remove obsolete structure fields init_vars hasn't been used for a long time. --- tools/qfcc/include/flow.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index b4cc48cf5..515c207d1 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -84,12 +84,6 @@ typedef struct flownode_s { struct set_s *in; struct set_s *out; } live_vars; - struct { - struct set_s *use; - struct set_s *def; - struct set_s *in; - struct set_s *out; - } init_vars; struct sblock_s *sblock; ///< original statement block struct dag_s *dag; ///< dag for this node } flownode_t; From f56de00c2103692fbdcb480415eec4b02181b934 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 03:38:45 +0900 Subject: [PATCH 0564/3664] [qfcc] Rename a field depth_first is much clearer than dfo. I had to check what dfo meant too many times in one night. --- tools/qfcc/include/flow.h | 2 +- tools/qfcc/source/flow.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index 515c207d1..f57fd3c37 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -96,7 +96,7 @@ typedef struct flowgraph_s { flowedge_t *edges; ///< array of all edges in the graph int num_edges; struct set_s *dfst; ///< edges in the depth-first search tree - int *dfo; ///< depth-first order of nodes + int *depth_first; ///< depth-first order of nodes flowloop_t *loops; ///< linked list of natural loops } flowgraph_t; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index aa05733e8..3f1f37151 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -148,8 +148,8 @@ delete_graph (flowgraph_t *graph) free (graph->edges); if (graph->dfst) set_delete (graph->dfst); - if (graph->dfo) - free (graph->dfo); + if (graph->depth_first) + free (graph->depth_first); FREE (graphs, graph); } @@ -541,7 +541,7 @@ flow_reaching_defs (flowgraph_t *graph) changed = 0; // flow down the graph for (i = 0; i < graph->num_nodes; i++) { - node = graph->nodes[graph->dfo[i]]; + node = graph->nodes[graph->depth_first[i]]; in = node->reaching_defs.in; out = node->reaching_defs.out; gen = node->reaching_defs.gen; @@ -626,7 +626,7 @@ flow_live_vars (flowgraph_t *graph) // flow UP the graph because live variable analysis uses information // from a node's successors rather than its predecessors. for (j = graph->num_nodes - 1; j >= 0; j--) { - node = graph->nodes[graph->dfo[j]]; + node = graph->nodes[graph->depth_first[j]]; set_empty (tmp); for (succ = set_first (node->successors); succ; succ = set_next (succ)) @@ -718,7 +718,7 @@ flow_uninitialized (flowgraph_t *graph) defs = set_new (); for (i = 0; i < graph->num_nodes; i++) { - node = graph->nodes[graph->dfo[i]]; + node = graph->nodes[graph->depth_first[i]]; set_empty (defs); // collect definitions of all variables "used" in this node. use from // the live vars analysis is perfect for the job @@ -1177,7 +1177,7 @@ df_search (flowgraph_t *graph, set_t *visited, int *i, int n) } } node->dfn = --*i; - graph->dfo[node->dfn] = n; + graph->depth_first[node->dfn] = n; } static void @@ -1190,11 +1190,11 @@ flow_build_dfst (flowgraph_t *graph) set_add (visited, graph->num_nodes); set_add (visited, graph->num_nodes + 1); - if (graph->dfo) - free (graph->dfo); + if (graph->depth_first) + free (graph->depth_first); if (graph->dfst) set_delete (graph->dfst); - graph->dfo = calloc (graph->num_nodes, sizeof (int)); + graph->depth_first = calloc (graph->num_nodes, sizeof (int)); graph->dfst = set_new (); i = graph->num_nodes; df_search (graph, visited, &i, 0); From d44d956038698da9e02562e1452a430052199b00 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 03:39:24 +0900 Subject: [PATCH 0565/3664] [qfcc] Remove a long dead function --- tools/qfcc/source/flow.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 3f1f37151..f7e144663 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -210,18 +210,6 @@ flowvar_is_local (flowvar_t *var) { return !(flowvar_is_global (var) || flowvar_is_param (var)); } -#if 0 -static int -flowvar_is_initialized (flowvar_t *var) -{ - def_t *def; - - if (var->op->op_type != op_def) - return 0; - def = var->op->o.def; - return def->initialized; -} -#endif flowvar_t * flow_get_var (operand_t *op) { From 7338689146f5e588460fa90196b0520b9d91699f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 03:42:18 +0900 Subject: [PATCH 0566/3664] [qfcc] Treat offset real tempops as an error tempops always have an offset field, but only those that are aliases should ever have a non-zero offset. --- tools/qfcc/source/flow.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index f7e144663..526aadbcd 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -271,6 +271,9 @@ get_temp_address (function_t *func, operand_t *op) top->o.tempop.flowaddr = func->tmpaddr; func->tmpaddr += top->size; } + if (top->o.tempop.offset) { + internal_error (0, "real tempop with a non-zero offset"); + } op->o.tempop.flowaddr = top->o.tempop.flowaddr + op->o.tempop.offset; return op->o.tempop.flowaddr; } From 809c103fd1f6b856b8a788adacdddbbedf10c677 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 03:46:52 +0900 Subject: [PATCH 0567/3664] [qfcc] Shuffle some code around to be clearer Doing the same thing at the end of two branches of an if/else seems off. And doing an associative(?) set operation every time through a loop is wasteful. --- tools/qfcc/source/flow.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 526aadbcd..d5288616a 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -458,12 +458,11 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) if (op->op_type == op_temp) { tempop_visit_all (&op->o.tempop, 1, flow_tempop_kill_aliases_visit, tmp); - set_difference (tmp, uninit); } else if (op->op_type == op_def) { def_visit_all (op->o.def, 1, flow_def_kill_aliases_visit, tmp); - // don't allow aliases to kill definitions in the entry dummy block - set_difference (tmp, uninit); } + // don't allow aliases to kill definitions in the entry dummy block + set_difference (tmp, uninit); // merge the alias kills with the current def's kills set_union (kill, tmp); } @@ -492,8 +491,8 @@ flow_reaching_defs (flowgraph_t *graph) for (i = 0; i < graph->func->num_vars; i++) { var = graph->func->vars[i]; set_union (uninit, var->define);// do not want alias handling here - set_difference (uninit, kill); // remove any gens from the function } + set_difference (uninit, kill); // remove any gens from the function graph->nodes[graph->num_nodes]->reaching_defs.out = uninit; graph->nodes[graph->num_nodes]->reaching_defs.in = set_new (); graph->nodes[graph->num_nodes]->reaching_defs.gen = set_new (); From e4c87091a36c7a891f861fb4a5e4bb10c86fc798 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 03:53:53 +0900 Subject: [PATCH 0568/3664] [qfcc] Lots of flow analysis docs And some function shuffling for grouping. I'm not satisfied with the docs, but they're a lot more helpful than they were. --- tools/qfcc/source/flow.c | 343 ++++++++++++++++++++++++++++++++------- 1 file changed, 283 insertions(+), 60 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index d5288616a..0a29ff16d 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -57,11 +57,11 @@ #include "symtab.h" #include "type.h" -static flowvar_t *vars_freelist; -static flowloop_t *loops_freelist; -static flownode_t *nodes_freelist; -static flowgraph_t *graphs_freelist; +/// \addtogroup qfcc_flow +///@{ +/** Static operand definitions for the ever present return and parameter slots. + */ static struct { const char *name; operand_t op; @@ -78,6 +78,17 @@ static struct { }; static const int num_flow_params = sizeof(flow_params)/sizeof(flow_params[0]); +/** \name Flow analysis memory management */ +///@{ +static flowvar_t *vars_freelist; ///< flowvar pool +static flowloop_t *loops_freelist; ///< flow loop pool +static flownode_t *nodes_freelist; ///< flow node pool +static flowgraph_t *graphs_freelist; ///< flow graph pool + +/** Allocate a new flow var. + * + * The var's use and define sets are initialized to empty. + */ static flowvar_t * new_flowvar (void) { @@ -88,6 +99,10 @@ new_flowvar (void) return var; } +/** Allocate a new flow loop. + * + * The loop's nodes set is initialized to the empty set. + */ static flowloop_t * new_loop (void) { @@ -97,6 +112,8 @@ new_loop (void) return loop; } +/** Free a flow loop and its nodes set. + */ static void delete_loop (flowloop_t *loop) { @@ -104,6 +121,10 @@ delete_loop (flowloop_t *loop) FREE (loops, loop); } +/** Allocate a new flow node. + * + * The node is completely empty. + */ static flownode_t * new_node (void) { @@ -112,6 +133,10 @@ new_node (void) return node; } +/** Free a flow node and its resources. + * + * \bug not global_vars or the vars and defs sets? + */ static void delete_node (flownode_t *node) { @@ -126,6 +151,10 @@ delete_node (flownode_t *node) FREE (nodes, node); } +/** Allocate a new flow graph. + * + * The graph is completely empty. + */ static flowgraph_t * new_graph (void) { @@ -134,6 +163,10 @@ new_graph (void) return graph; } +/** Return a flow graph and its resources to the pools. + * + * \bug except loops? + */ static void __attribute__((unused)) delete_graph (flowgraph_t *graph) { @@ -152,7 +185,77 @@ delete_graph (flowgraph_t *graph) free (graph->depth_first); FREE (graphs, graph); } +///@} +/** \name Flowvar classification */ +///@{ +/** Check if the flowvar refers to a global variable. + * + * For the flowvar to refer to a global variable, the flowvar's operand + * must be a def operand (but the def itself may be an alias of the real def) + * and the rel def must not have its def_t::local flag set. This means that + * function-scope static variables are not considered local (ie, only + * non-static function-scope variables and function parameters are considered + * local (temp vars are local too, but are not represented by \a op_def)). + */ +static int +flowvar_is_global (flowvar_t *var) +{ + def_t *def; + + if (var->op->op_type != op_def) + return 0; + def = var->op->o.def; + if (def->alias) + def = def->alias; + if (def->local) + return 0; + return 1; +} + +/** Check if the flowvar refers to a function parameter. + * + * For the flowvar to refer to a function parameter, the flowvar's operand + * must be a def operand (but the def itself may be an alias of the real def) + * and the rel def must have both its def_t::local and def_t::param flags set. + * + * Temp vars are are not represented by op_def, so no mistake can be made. + */ +static int +flowvar_is_param (flowvar_t *var) +{ + def_t *def; + + if (var->op->op_type != op_def) + return 0; + def = var->op->o.def; + if (def->alias) + def = def->alias; + if (!def->local) + return 0; + if (!def->param) + return 0; + return 1; +} + +/** Check if the flowvar refers to a function parameter. + * + * As this is simply "neither global nor pamam", all other flowvars are + * considered local, in particular actual non-staic function scope variables + * and temp vars. + */ +static int +flowvar_is_local (flowvar_t *var) +{ + return !(flowvar_is_global (var) || flowvar_is_param (var)); +} +///@} + +/** Extract the def from a def or temp flowvar. + * + * It is an error for the operand referenced by the flowvar to be anything + * other than a real def or temp. + */ static __attribute__((pure)) def_t * flowvar_get_def (flowvar_t *var) { @@ -173,43 +276,13 @@ flowvar_get_def (flowvar_t *var) return 0; } -static int -flowvar_is_global (flowvar_t *var) -{ - def_t *def; - - if (var->op->op_type != op_def) - return 0; - def = var->op->o.def; - if (def->alias) - def = def->alias; - if (def->local) - return 0; - return 1; -} - -static int -flowvar_is_param (flowvar_t *var) -{ - def_t *def; - - if (var->op->op_type != op_def) - return 0; - def = var->op->o.def; - if (def->alias) - def = def->alias; - if (!def->local) - return 0; - if (!def->param) - return 0; - return 1; -} - -static int -flowvar_is_local (flowvar_t *var) -{ - return !(flowvar_is_global (var) || flowvar_is_param (var)); -} +/** Get a def or temp var operand's flowvar. + * + * Other operand types never have a flowvar. + * + * If the operand does not yet have a flowvar, one is created and assigned + * to the operand. + */ flowvar_t * flow_get_var (operand_t *op) { @@ -229,6 +302,12 @@ flow_get_var (operand_t *op) return 0; } +/** Indicate whether the operand should be counted. + * + * If the operand is a def or temp var operand, and it has not already been + * counted, then it is counted, otherwise it is not. + * \return 1 if the operand should be counted, 0 if not + */ static int count_operand (operand_t *op) { @@ -240,14 +319,15 @@ count_operand (operand_t *op) return 0; var = flow_get_var (op); - // flowvars are initialized with number == 0, and any global flowvar - // used by a function will always have a number >= 0 after flow analysis, - // and local flowvars will always be 0 before flow analysis, so use -1 - // to indicate the variable has been counted. - // - // Also, since this is the beginning of flow analysis for this function, - // ensure the define/use sets for global vars are empty. However, as - // checking if a var is global is too much trouble, just clear them all. + /** Flowvars are initialized with number == 0, and any global flowvar + * used by a function will always have a number >= 0 after flow analysis, + * and local flowvars will always be 0 before flow analysis, so use -1 + * to indicate the variable has been counted. + * + * Also, since this is the beginning of flow analysis for this function, + * ensure the define/use sets for global vars are empty. However, since + * checking if a var is global is too much trouble, just clear them all. + */ if (var && var->number != -1) { set_empty (var->use); set_empty (var->define); @@ -257,6 +337,22 @@ count_operand (operand_t *op) return 0; } +/** Allocate flow analysis pseudo address space to a temporary variable. + * + * If the operand already has an address allocated (flowvar_t::flowaddr is + * not 0), then the already allocated address is returned. + * + * If the operand refers to an alias, the alias chain is followed to the + * actual temp var operand and the real temp var is allocated space if it + * has not allready been alloced. + * + * The operand is given the address of the real temp var operand plus whatever + * offset the operand has. + * + * Real temp var operands must have a zero offset. + * + * The operand address is set in \a op and returned. + */ static int get_temp_address (function_t *func, operand_t *op) { @@ -278,6 +374,8 @@ get_temp_address (function_t *func, operand_t *op) return op->o.tempop.flowaddr; } +/** Add an operand's flowvar to the function's list of variables. + */ static void add_operand (function_t *func, operand_t *op) { @@ -289,8 +387,15 @@ add_operand (function_t *func, operand_t *op) return; var = flow_get_var (op); - // If the flowvar number is still -1, then the flowvar has not yet been - // added to the list of variables referenced by the function. + /** If the flowvar number is still -1, then the flowvar has not yet been + * added to the list of variables referenced by the function. + * + * The flowvar's flowvar_t::number is set to its index in the function's + * list of flowvars. + * + * Also, temp and local flowvars are assigned addresses from the flow + * analysys pseudo address space so partial accesses can be analyzed. + */ if (var && var->number == -1) { var->number = func->num_vars++; var->op = op; @@ -303,6 +408,8 @@ add_operand (function_t *func, operand_t *op) } } +/** Create symbols and defs for params/return if not already available. + */ static symbol_t * param_symbol (const char *name) { @@ -313,6 +420,15 @@ param_symbol (const char *name) return sym; } +/** Build an array of all the statements in a function. + + The array exists so statements can be referenced by number and thus used + in sets. + + The statement references in the array (function_t::statements) are in the + same order as they are within the statement blocks (function_t::sblock) + and with the blocks in the same order as the linked list of blocks. +*/ static void flow_build_statements (function_t *func) { @@ -335,6 +451,48 @@ flow_build_statements (function_t *func) } } +/** Build an array of all the variables used by a function + * + * The array exists so variables can be referenced by number and thus used + * in sets. However, because larger variables may be aliased by smaller types, + * their representation is more complicated. + * + * # Local variable representation + * Defined local vars add their address in local space to the number of + * statements in the function. Thus their flow analysis address in in the + * range: + * + * ([num_statements ... num_statements+localsize]) + * + * with a set element in flowvar_t::define for each word used by the var. + * That is, single word types (int, float, pointer, etc) have one element, + * doubles have two adjacant elements, and vectors and quaternions have + * three and four elements respectively (also adjacant). Structural types + * (struct, union, array) have as many adjacant elements as their size + * dictates. + * + * Temporary vars are pseudo allocated and their addresses are added as + * for normal local vars. + * + * Note, however, that flowvar_t::define also includes real function + * statements that assign to the variable. + * + * # Pseudo Address Space + * Temporary variables are _effectively_ local variables and thus will + * be treated as such by the analizer in that their addresses and sizes + * will be used to determine which and how many set elements to use. + * + * However, at this stage, temporary variables do not have any address + * space assigned to them because their lifetimes are generally limited + * to a few statements and the memory used for the temp vars may be + * recycled. Thus, give temp vars a pseudo address space just past the + * address space used for source-defined local variables. As each temp + * var is added to the analyzer, get_temp_address() assigns the temp var + * an address using function_t::tmpaddr as a starting point. + * + * add_operand() takes care of setting flowvar_t::flowaddr for both locals + * and temps. + */ static void flow_build_vars (function_t *func) { @@ -371,6 +529,7 @@ flow_build_vars (function_t *func) // set up pseudo address space for temp vars so accessing tmp vars // though aliases analyses correctly func->tmpaddr = func->num_statements + func->symtab->space->size; + func->num_vars = 0; // incremented by add_operand // first, add .return and .param_[0-7] as they are always needed for (i = 0; i < num_flow_params; i++) @@ -399,15 +558,8 @@ flow_build_vars (function_t *func) if (flowvar_is_global (func->vars[i])) set_add (func->global_vars, i); } - // create dummy defs for local vars - // defined local vars add their address in local space to the number of - // statements in the function: - // ([num_statements ... num_statements+localsize]) - // with a set element for each def used in the local space - // - // temporary vars are pseudo allocated and their addresses are added as for - // locals - // add_operand takes care of setting flowaddr for both locals and temps + // Put the local varibals in their place (set var->defined to the addresses + // spanned by the var) for (i = 0; i < func->num_vars; i++) { int j; @@ -424,6 +576,8 @@ flow_build_vars (function_t *func) set_delete (stdef); } +/** Add the tempop's spanned addresses to the kill set + */ static int flow_tempop_kill_aliases_visit (tempop_t *tempop, void *_kill) { @@ -435,6 +589,8 @@ flow_tempop_kill_aliases_visit (tempop_t *tempop, void *_kill) return 0; } +/** Add the def's spanned addresses to the kill set + */ static int flow_def_kill_aliases_visit (def_t *def, void *_kill) { @@ -446,6 +602,13 @@ flow_def_kill_aliases_visit (def_t *def, void *_kill) return 0; } +/** Add the flowvar's spanned addresses to the kill set + * + * If the flowvar refers to an alias, then the real def/tempop and any + * overlapping aliases are aslo killed. + * + * However, other aliases cannot kill anything in the uninitialized set. + */ static void flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) { @@ -455,6 +618,7 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) set_union (kill, var->define); op = var->op; tmp = set_new (); + // collect the kill sets from any aliases if (op->op_type == op_temp) { tempop_visit_all (&op->o.tempop, 1, flow_tempop_kill_aliases_visit, tmp); @@ -467,6 +631,8 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) set_union (kill, tmp); } +/** Compute reaching defs + */ static void flow_reaching_defs (flowgraph_t *graph) { @@ -484,15 +650,37 @@ flow_reaching_defs (flowgraph_t *graph) flowvar_t *var; // First, create out for the entry dummy node using fake statement numbers. + //\f[ \bigcup\limits_{i=1}^{\infty} F_{i} \f] + //\f[ \bigcap\limits_{i=1}^{\infty} F_{i} \f] + + /** The dummy entry node reaching defs \a out set is initialized to: + * \f[ out_{reaching}=[\bigcup\limits_{v \in \{locals\}} define_{v}] + * \setminus \{statements\} \f] + * where {\a locals} is the set of local def and tempop flowvars (does + * not include parameters), \a define is the set of addresses spanned + * by the flowvar (see flow_build_vars()) (XXX along with statement + * gens), and {\a statements} is the set of all statements in the + * function (ensures the \a out set does not include any initializers in + * the code nodes). + * + * All other entry node sets are initialized to empty. + */ + // kill represents the set of all statements in the function kill = set_new (); for (i = 0; i < graph->func->num_statements; i++) set_add (kill, i); + // uninit uninit = set_new (); for (i = 0; i < graph->func->num_vars; i++) { var = graph->func->vars[i]; set_union (uninit, var->define);// do not want alias handling here } + /** Any possible gens from the function code are removed from the + * \a uninit set (which becomes the \a out set of the entry node's + * reaching defs) in order to prevent them leaking into the real nodes. + */ set_difference (uninit, kill); // remove any gens from the function + // initialize the reaching defs sets in the entry node graph->nodes[graph->num_nodes]->reaching_defs.out = uninit; graph->nodes[graph->num_nodes]->reaching_defs.in = set_new (); graph->nodes[graph->num_nodes]->reaching_defs.gen = set_new (); @@ -555,6 +743,8 @@ flow_reaching_defs (flowgraph_t *graph) set_delete (stkill); } +/** Update the node's \a use set from the statement's \a use set + */ static void live_set_use (set_t *stuse, set_t *use, set_t *def) { @@ -563,6 +753,8 @@ live_set_use (set_t *stuse, set_t *use, set_t *def) set_union (use, stuse); } +/** Update the node's \a def set from the statement's \a def set + */ static void live_set_def (set_t *stdef, set_t *use, set_t *def) { @@ -1240,6 +1432,35 @@ flow_make_node (sblock_t *sblock, int id, function_t *func) return node; } +/** Build the flow graph for the function. + * + * In addition to the nodes create by the statement blocks, there are two + * dummy blocks: + * + * \dot + * digraph flow_build_graph { + * layout = dot; rankdir = TB; compound =true; nodesp = 1.0; + * dummy_entry [shape=box,label="entry"]; + * sblock0 [label="code"]; sblock1 [label="code"]; + * sblock2 [label="code"]; sblock3 [label="code"]; + * dummy_exit [shape=box,label="exit"]; + * dummy_entry -> sblock0; sblock0 -> sblock1; + * sblock1 -> sblock2; sblock2 -> sblock1; + * sblock2 -> dummy_exit; sblock1 -> sblock3; + * sblock3 -> dummy_exit; + * } + * \enddot + * + * The entry block is used for detecting use of uninitialized local variables + * and the exit block is used for ensuring global variables are treated as + * live at function exit. + * + * The exit block, which also is empty of statements, has its live vars + * \a use set initilized to the set of global defs, which are simply numbered + * by their index in the functions list of flowvars. All other exit node sets + * are initialized to empty. + * \f[ use_{live}=globals \f] + */ static flowgraph_t * flow_build_graph (function_t *func) { @@ -1303,3 +1524,5 @@ flow_data_flow (function_t *func) flow_cleanup_dags (graph); func->sblock = flow_generate (graph); } + +///@} From c2ed6d41bd368f0ef6ee3a4d6a42c401a61200a0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 03:55:08 +0900 Subject: [PATCH 0569/3664] [qfcc] Finish struct-init-param test When the bug is fixed, it will pass now (does without optimization). --- tools/qfcc/test/struct-init-param.r | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/test/struct-init-param.r b/tools/qfcc/test/struct-init-param.r index 8b166099e..1b3bc9e7a 100644 --- a/tools/qfcc/test/struct-init-param.r +++ b/tools/qfcc/test/struct-init-param.r @@ -1,3 +1,4 @@ +void printf (string fmt, ...) = #0; typedef struct { int x; int y; @@ -13,18 +14,31 @@ typedef struct Rect_s { Extent extent; } Rect; -void *foo (void *obj, void *cmd, void *o, Point pos, Rect r) -{ - return obj; -} +void *foo (Rect *obj, void *cmd, Rect *o, Point pos, Rect r); -void *bar (Rect *obj, void *cmd, void *o, Point pos) +void *bar (Rect *obj, void *cmd, Rect *o, Point pos) { Rect rect = { {}, obj.extent }; return foo (obj, cmd, o, pos, rect); } +void *foo (Rect *obj, void *cmd, Rect *o, Point pos, Rect r) +{ + *o = r; + return obj; +} + +Rect obj = { { 1, 2}, { 3, 4} }; +Rect o = { { 5, 6}, {7, 8} }; + int main (void) { - return 1;// don't want this to pass until I've checked the generated code + int ret = 1; + bar(&obj, nil, &o, obj.offset); + printf ("%d %d %d %d\n", o.offset.x, o.offset.y, + o.extent.width, o.extent.height); + if (o.offset.x == 0 && o.offset.y == 0 + && o.extent.width == 3 && o.extent.height == 4) + ret = 0; + return ret; } From b2faca16a7393d728ee0d2543ce84a249b381c2d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 12:08:56 +0900 Subject: [PATCH 0570/3664] [qfcc] Rename the kill alias functions Having "visit" in the name felt redundant in the end. --- tools/qfcc/source/flow.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 0a29ff16d..897e853e4 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -579,7 +579,7 @@ flow_build_vars (function_t *func) /** Add the tempop's spanned addresses to the kill set */ static int -flow_tempop_kill_aliases_visit (tempop_t *tempop, void *_kill) +flow_tempop_kill_aliases (tempop_t *tempop, void *_kill) { set_t *kill = (set_t *) _kill; flowvar_t *var; @@ -592,7 +592,7 @@ flow_tempop_kill_aliases_visit (tempop_t *tempop, void *_kill) /** Add the def's spanned addresses to the kill set */ static int -flow_def_kill_aliases_visit (def_t *def, void *_kill) +flow_def_kill_aliases (def_t *def, void *_kill) { set_t *kill = (set_t *) _kill; flowvar_t *var; @@ -620,10 +620,9 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) tmp = set_new (); // collect the kill sets from any aliases if (op->op_type == op_temp) { - tempop_visit_all (&op->o.tempop, 1, flow_tempop_kill_aliases_visit, - tmp); + tempop_visit_all (&op->o.tempop, 1, flow_tempop_kill_aliases, tmp); } else if (op->op_type == op_def) { - def_visit_all (op->o.def, 1, flow_def_kill_aliases_visit, tmp); + def_visit_all (op->o.def, 1, flow_def_kill_aliases, tmp); } // don't allow aliases to kill definitions in the entry dummy block set_difference (tmp, uninit); From a2f203c840ea551ca3ed3c41d217a96df7278990 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 12:10:12 +0900 Subject: [PATCH 0571/3664] [qfcc] Correct a comment There's a world of difference between "any" and "only". --- tools/qfcc/include/def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index df0104178..d06b5961a 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -293,7 +293,7 @@ int def_size (def_t *def) __attribute__((pure)); function will return. \param def The def representing the alias cluster to visit. - \param overlap If non-zero, then only defs that overlap \a def will + \param overlap If non-zero, then any defs that overlap \a def will be visited. If 2, then the given def must fully overlap the visited def. \param visit The function to call when visiting a def. The first From 8696e76a25c6bcfbff1f5e263d6d847e98a3382a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 12:11:53 +0900 Subject: [PATCH 0572/3664] [qfcc] Handle aliases when setting use and def As expected, this does not fix the mangled pointer problem in struct-init-param.r, but it does improve the ud-chains. There's still a problem with .return, but it's handling in flow_analyze_statement is a bit "special" :P. --- tools/qfcc/source/flow.c | 80 ++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 23 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 897e853e4..5ff1c9662 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -541,7 +541,12 @@ flow_build_vars (function_t *func) flow_analyze_statement (s, 0, 0, 0, operands); for (j = 0; j < 4; j++) add_operand (func, operands[j]); - + } + // and set the use/def sets for the vars (has to be a separate pass + // because the allias handling reqruires the flow address to be valid + // (ie, not -1) + for (i = 0; i < func->num_statements; i++) { + s = func->statements[i]; flow_analyze_statement (s, stuse, stdef, 0, 0); for (var_i = set_first (stdef); var_i; var_i = set_next (var_i)) { var = func->vars[var_i->element]; @@ -977,16 +982,45 @@ flow_generate (flowgraph_t *graph) return code; } +static int +flow_tempop_add_aliases (tempop_t *tempop, void *_set) +{ + set_t *set = (set_t *) _set; + flowvar_t *var; + var = tempop->flowvar; + if (var) + set_add (set, var->number); + return 0; +} + +static int +flow_def_add_aliases (def_t *def, void *_set) +{ + set_t *set = (set_t *) _set; + flowvar_t *var; + var = def->flowvar; + if (var) + set_add (set, var->number); + return 0; +} + static void -flow_add_op_var (set_t *set, operand_t *op) +flow_add_op_var (set_t *set, operand_t *op, int is_use) { flowvar_t *var; + int ol = is_use ? 2 : 1; if (!set) return; if (!(var = flow_get_var (op))) return; set_add (set, var->number); + + if (op->op_type == op_temp) { + tempop_visit_all (&op->o.tempop, ol, flow_tempop_add_aliases, set); + } else { + def_visit_all (op->o.def, ol, flow_def_add_aliases, set); + } } void @@ -1010,10 +1044,10 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, case st_none: internal_error (s->expr, "not a statement"); case st_expr: - flow_add_op_var (def, s->opc); - flow_add_op_var (use, s->opa); + flow_add_op_var (def, s->opc, 0); + flow_add_op_var (use, s->opa, 1); if (s->opb) - flow_add_op_var (use, s->opb); + flow_add_op_var (use, s->opb, 1); if (operands) { operands[0] = s->opc; operands[1] = s->opa; @@ -1021,8 +1055,8 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_assign: - flow_add_op_var (def, s->opb); - flow_add_op_var (use, s->opa); + flow_add_op_var (def, s->opb, 0); + flow_add_op_var (use, s->opa, 1); if (operands) { operands[0] = s->opb; operands[1] = s->opa; @@ -1030,12 +1064,12 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, break; case st_ptrassign: case st_move: - flow_add_op_var (use, s->opa); - flow_add_op_var (use, s->opb); + flow_add_op_var (use, s->opa, 1); + flow_add_op_var (use, s->opb, 1); if (!strcmp (s->opcode, "")) { - flow_add_op_var (def, s->opc); + flow_add_op_var (def, s->opc, 0); } else if (!strcmp (s->opcode, "")) { - flow_add_op_var (use, s->opc); + flow_add_op_var (use, s->opc, 0); if (s->opc->op_type == op_value && s->opc->o.value->lltype == ev_pointer && s->opc->o.value->v.pointer.def) { @@ -1044,7 +1078,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, ex_pointer_t *ptr = &s->opc->o.value->v.pointer; alias = alias_def (ptr->def, ptr->type, ptr->val); op = def_operand (alias, ptr->type); - flow_add_op_var (def, op); + flow_add_op_var (def, op, 0); if (operands) operands[0] = op; else @@ -1055,7 +1089,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } } else { if (s->opc) - flow_add_op_var (use, s->opc); + flow_add_op_var (use, s->opc, 1); } if (kill) { set_everything (kill); @@ -1070,10 +1104,10 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_state: - flow_add_op_var (use, s->opa); - flow_add_op_var (use, s->opb); + flow_add_op_var (use, s->opa, 1); + flow_add_op_var (use, s->opb, 1); if (s->opc) - flow_add_op_var (use, s->opc); + flow_add_op_var (use, s->opc, 1); //FIXME entity members if (operands) { operands[1] = s->opa; @@ -1084,7 +1118,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, case st_func: if (strcmp (s->opcode, "") == 0 || strcmp (s->opcode, "") == 0) { - flow_add_op_var (use, s->opa); + flow_add_op_var (use, s->opa, 1); } else if (strcmp (s->opcode, "") == 0) { if (use) set_add (use, 0); //FIXME assumes .return location @@ -1092,14 +1126,14 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, if (strncmp (s->opcode, "opcode[5] - '0'; - flow_add_op_var (use, s->opa); + flow_add_op_var (use, s->opa, 1); } else if (strncmp (s->opcode, "opcode[6] - '0'; - flow_add_op_var (use, s->opa); - flow_add_op_var (use, s->opb); + flow_add_op_var (use, s->opa, 1); + flow_add_op_var (use, s->opb, 1); if (s->opc) - flow_add_op_var (use, s->opc); + flow_add_op_var (use, s->opc, 1); } if (calln >= 0) { if (use) { @@ -1117,9 +1151,9 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, break; case st_flow: if (strcmp (s->opcode, "") != 0) { - flow_add_op_var (use, s->opa); + flow_add_op_var (use, s->opa, 1); if (strcmp (s->opcode, "") == 0) - flow_add_op_var (use, s->opb); + flow_add_op_var (use, s->opb, 1); } if (operands) { operands[1] = s->opa; From b81d58c795fcc95176b9a9f65a00fdf8ed0e7ee8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 14:58:57 +0900 Subject: [PATCH 0573/3664] Revert "[qfcc] Correct a comment" This reverts commit a2f203c840ea551ca3ed3c41d217a96df7278990. There is indeed a world of difference between "any" and "only", and it helps if I read the rest of the docs AND the code :P. --- tools/qfcc/include/def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index d06b5961a..df0104178 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -293,7 +293,7 @@ int def_size (def_t *def) __attribute__((pure)); function will return. \param def The def representing the alias cluster to visit. - \param overlap If non-zero, then any defs that overlap \a def will + \param overlap If non-zero, then only defs that overlap \a def will be visited. If 2, then the given def must fully overlap the visited def. \param visit The function to call when visiting a def. The first From d9d321f65b1281e302afab531d15e9c68cf4304a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 15:40:07 +0900 Subject: [PATCH 0574/3664] [qfcc] Check for previous errors in vector exprs Fixes a segfault when one of the expressions used to construct the vector was the result of an error. --- tools/qfcc/source/expr.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c82585674..7b9721be4 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -659,15 +659,23 @@ new_vector_list (expr_t *e) case 3: // quaternion or vector. all expressions must be compatible with // a float (ie, a scalar) - for (t = e; t; t = t->next) - if (!is_scalar (get_type (t))) + for (t = e; t; t = t->next) { + if (t->type == ex_error) { + return t; + } + if (!is_scalar (get_type (t))) { return error (t, "invalid type for vector element"); + } + } vec = new_expr (); vec->type = ex_vector; vec->e.vector.type = type; vec->e.vector.list = e; break; case 2: + if (e->type == ex_error || e->next->type == ex_error) { + return e; + } if (is_scalar (get_type (e)) && is_scalar (get_type (e->next))) { // scalar, scalar // expand [x, y] to [x, y, 0] From 695b3ba0d043633db22410dddeaf3a2bcc9d50c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 16:50:39 +0900 Subject: [PATCH 0575/3664] [qfcc] Rearrange vecexpr.r for easier debugging Putting the most likely function to have problems at the top reduces break-point shenanigans. --- tools/qfcc/test/vecexpr.r | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/test/vecexpr.r b/tools/qfcc/test/vecexpr.r index 8667b0c93..0365ed589 100644 --- a/tools/qfcc/test/vecexpr.r +++ b/tools/qfcc/test/vecexpr.r @@ -1,4 +1,14 @@ #include "test-harness.h" + +vector t1(); +vector t2(float x); + +vector +t3(float x) +{ + return [x, t2(9).z, x] * 2; +} + vector t1() { @@ -11,12 +21,6 @@ t2(float x) return [x, x, x]; } -vector -t3(float x) -{ - return [x, t2(9).z, x] * 2; -} - int main () { From 035da472ecd39b19e1745e068ddab8bfef2abc08 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 16:51:01 +0900 Subject: [PATCH 0576/3664] [qfcc] Offset alias tempop offsets Alias tempop offsets are relative to the real tempop. This fixes alias tempops never overlapping the real tempop. --- tools/qfcc/source/statements.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 2f2d0a07d..61ab35c5e 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -362,6 +362,12 @@ tempop_overlap (tempop_t *t1, tempop_t *t2) int size1 = type_size (t1->type); int size2 = type_size (t2->type); + if (t1->alias) { + offs1 += t1->alias->o.tempop.offset; + } + if (t2->alias) { + offs2 += t2->alias->o.tempop.offset; + } if (offs1 <= offs2 && offs1 + size1 >= offs2 + size2) return 2; // t1 fully overlaps t2 if (offs1 < offs2 + size2 && offs2 < offs1 + size1) From 3d9410c66dcca13a23b6cc5500aa2690a8090ce4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 16:53:28 +0900 Subject: [PATCH 0577/3664] [qfcc] Force overlap to 0 for non-alias def/temops Make the code behave as intended: visiting all aliases when starting with the real def/tempop regardless of the overlap setting. --- tools/qfcc/source/def.c | 2 ++ tools/qfcc/source/statements.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 3f2f1c838..865ef4066 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -807,6 +807,8 @@ def_visit_all (def_t *def, int overlap, def = def->alias; if ((ret = visit (def, data))) return ret; + } else { + overlap = 0; } for (def = def->alias_defs; def; def = def->next) { if (def == start_def) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 61ab35c5e..0ba4d1e21 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -393,6 +393,8 @@ tempop_visit_all (tempop_t *tempop, int overlap, tempop = &top->o.tempop; if ((ret = visit (tempop, data))) return ret; + } else { + overlap = 0; } for (top = tempop->alias_ops; top; top = top->next) { if (top->op_type != op_temp) { From 5020966be32693032ab7a864bc2f020b306975e4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 16:57:12 +0900 Subject: [PATCH 0578/3664] [qfcc] Fix ud-chain alias handling That was a fair bit trickier than I thought, but now .return and .paramN are handled correctly, too, especially taking call instructions into account (they can "kill" all 9 defs). --- tools/qfcc/source/flow.c | 55 +++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 5ff1c9662..4ee42e214 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -99,6 +99,16 @@ new_flowvar (void) return var; } +/** Delete a flow var + */ +static void +delete_flowvar (flowvar_t *var) +{ + set_delete (var->use); + set_delete (var->define); + FREE (vars, var); +} + /** Allocate a new flow loop. * * The loop's nodes set is initialized to the empty set. @@ -507,7 +517,16 @@ flow_build_vars (function_t *func) // first, count .return and .param_[0-7] as they are always needed for (i = 0; i < num_flow_params; i++) { - flow_params[i].op.o.def = param_symbol (flow_params[i].name)->s.def; + def_t *def = param_symbol (flow_params[i].name)->s.def; + def_t *a; + for (a = def->alias_defs; a; a = a->next) { + if (a->flowvar) { + delete_flowvar (a->flowvar); + a->flowvar = 0; + } + //free_def (def->alias_defs); + } + flow_params[i].op.o.def = def; num_vars += count_operand (&flow_params[i].op); } // then run through the statements in the function looking for accessed @@ -630,7 +649,9 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) def_visit_all (op->o.def, 1, flow_def_kill_aliases, tmp); } // don't allow aliases to kill definitions in the entry dummy block - set_difference (tmp, uninit); + if (uninit) { + set_difference (tmp, uninit); + } // merge the alias kills with the current def's kills set_union (kill, tmp); } @@ -1008,7 +1029,7 @@ static void flow_add_op_var (set_t *set, operand_t *op, int is_use) { flowvar_t *var; - int ol = is_use ? 2 : 1; + int ol = is_use ? 1 : 2; if (!set) return; @@ -1016,6 +1037,10 @@ flow_add_op_var (set_t *set, operand_t *op, int is_use) return; set_add (set, var->number); + // FIXME XXX I think the curent implementation will have problems + // for the def set when assinging to an alias as right now the real + // var is being treated as assigned as well. Want to handle partial + // defs properly, but I am as yet uncertain of how. if (op->op_type == op_temp) { tempop_visit_all (&op->o.tempop, ol, flow_tempop_add_aliases, set); } else { @@ -1120,8 +1145,9 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, || strcmp (s->opcode, "") == 0) { flow_add_op_var (use, s->opa, 1); } else if (strcmp (s->opcode, "") == 0) { - if (use) - set_add (use, 0); //FIXME assumes .return location + if (use) { + flow_add_op_var (use, &flow_params[0].op, 1); + } } if (strncmp (s->opcode, "= 0) { if (use) { - for (i = start; i < calln; i++) - set_add (use, i + 1);//FIXME assumes .param_N locations + for (i = start; i < calln; i++) { + flow_add_op_var (use, &flow_params[i + 1].op, 1); + } + } + if (def) { + for (i = 0; i < num_flow_params; i++) { + flow_add_op_var (def, &flow_params[i].op, 0); + } + } + if (kill) { + for (i = 0; i < num_flow_params; i++) { + flow_kill_aliases (kill, + flow_get_var (&flow_params[i].op), + 0); + } } - if (kill) - set_add (kill, 0); //FIXME assumes .return location } if (operands) { operands[1] = s->opa; From bcf75b541a68f2546707cf22e9d2c6f926801f26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 17:40:38 +0900 Subject: [PATCH 0579/3664] [qfcc] Build movep dest pointer correctly This fixes the mangled pointer in struct-init-param.r. --- tools/qfcc/source/dags.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 8de4d0e54..86acc210a 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -867,6 +867,8 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) statement_t *st; operand_t *dst = 0; type_t *type; + int offset = 0; + def_t *dstDef; operands[0] = make_operand (dag, block, dagnode, 0); operands[1] = make_operand (dag, block, dagnode, 1); @@ -875,7 +877,12 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) var = dag->labels[var_iter->element]; dst = var->op; type = dst->o.def->type; - operands[2] = value_operand (new_pointer_val (0, type, dst->o.def)); + dstDef = dst->o.def; + if (dstDef->alias) { + offset = dstDef->offset; + dstDef = dstDef->alias; + } + operands[2] = value_operand (new_pointer_val (offset, type, dstDef)); st = build_statement ("", operands, var->expr); sblock_add_statement (block, st); } From 89ec86f77fc4e7d0fd34862915550a48ed527f58 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 19:13:57 +0900 Subject: [PATCH 0580/3664] [qfcc] Add option to promote of float through ... The server code is not yet ready for doubles, especially in its varargs builtins: they expect only floats. When float promotion is enabled (default for advanced code, disabled for traditional or v6only), "@float_promoted@" is written to the prog's strings. --- tools/qfcc/doc/man/qfcc.1 | 6 ++++++ tools/qfcc/source/expr.c | 17 ++++++++++++++--- tools/qfcc/source/options.c | 7 +++++++ tools/qfcc/source/qfcc.c | 3 +++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index b4fbd2685..3162f813d 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -295,6 +295,12 @@ This can be a problem because instructions can access addresses up to 32767 in older servers or 65535 in most modern servers. Defaults to off for traditional mode, and on for advanced mode. +.TP +.B promote\-float +Promote float when passed to a function that takes a variable number of +arguements. Defaults to enabled for advanced code, is forced off for +traditional or v6only code (mostly because such code does not have doubles). + .TP .B short\-circuit Generate short circuit code for logical operators (\fB&&\fP and \fB||\fP). diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 7b9721be4..c1c78ff86 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1718,9 +1718,20 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (is_integer_val (e) && options.code.progsversion == PROG_ID_VERSION) convert_int (e); - if (is_float (get_type (e)) - && options.code.progsversion != PROG_ID_VERSION) { - t = &type_double; + if (options.code.promote_float) { + if (is_float (get_type (e))) { + t = &type_double; + } + } else { + if (is_double (get_type (e))) { + if (!e->implicit) { + warning (e, "passing double into ... function"); + } + if (is_constant (e)) { + // don't auto-demote non-constant doubles + t = &type_float; + } + } } if (is_integer_val (e) && options.warnings.vararg_integer) warning (e, "passing integer constant into ... function"); diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index f9807de7b..6f972fd82 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -203,6 +203,7 @@ code_usage (void) " help Display this text.\n" " [no-]local-merging Merge the local variable blocks into one.\n" " [no-]optimize Perform various optimizations on the code.\n" +" [no-]promote-float Promote float when passed through ...\n" " [no-]short-circuit Generate short circuit code for logical\n" " operators.\n" " [no-]single-cpp Convert progs.src to cpp input file.\n" @@ -310,6 +311,7 @@ DecodeArgs (int argc, char **argv) options.code.vector_components = -1; options.code.crc = -1; options.code.fast_float = true; + options.code.promote_float = true; options.warnings.uninited_variable = true; options.warnings.unused = true; options.warnings.executable = true; @@ -489,6 +491,8 @@ DecodeArgs (int argc, char **argv) options.code.debug = flag; } else if (!(strcasecmp (temp, "fast-float"))) { options.code.fast_float = flag; + } else if (!(strcasecmp (temp, "promote-float"))) { + options.code.promote_float = flag; } else if (!strcasecmp (temp, "help")) { code_usage (); } else if (!(strcasecmp (temp, "local-merging"))) { @@ -716,8 +720,11 @@ DecodeArgs (int argc, char **argv) options.code.local_merging = true; if (options.code.vector_components == (qboolean) -1) options.code.vector_components = false; + } else { + options.code.promote_float = 0; } if (options.code.progsversion == PROG_ID_VERSION) { + options.code.promote_float = 0; add_cpp_def ("-D__VERSION6__=1"); if (options.code.crc == (qboolean) -1) options.code.crc = true; diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 8a363a9cd..6a7e1a039 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -148,6 +148,9 @@ InitData (void) pr.code = codespace_new (); memset (codespace_newstatement (pr.code), 0, sizeof (dstatement_t)); pr.strings = strpool_new (); + if (options.code.promote_float) { + ReuseString ("@float_promoted@"); + } pr.num_functions = 1; pr.num_linenos = 0; From c726d77e7dfe116cb07ed17c01ae06d2310faf50 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 19:17:24 +0900 Subject: [PATCH 0581/3664] [gamecode] Respect the @float_promoted@ magic string Rather than relying on progs code version, use the string to determine whether PR_Sprintf should behave as if floats have been promoted through ... I imagine I'll get to the rest of the server code at some stage. With these two changes, nq-x11 works again (teleporters were the symptom). --- libs/gamecode/pr_load.c | 2 -- libs/gamecode/pr_strings.c | 7 +++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index df72cbbc9..d385dff12 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -202,8 +202,6 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) base -= sizeof (progs); // offsets are from file start heap = ((byte *) pr->progs + pr->progs_size + pr->pr_edictareasize); - pr->float_promoted = progs.version == PROG_VERSION; - if (pr->edicts) { *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); } diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 4d393776e..e280b4743 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -238,8 +238,15 @@ PR_LoadStrings (progs_t *pr) char *str = pr->pr_strings; int count = 0; + pr->float_promoted = 0; + while (str < end) { count++; + if (*str == '@' && pr->progs->version == PROG_VERSION) { + if (!strcmp (str, "@float_promoted@")) { + pr->float_promoted = 1; + } + } str += strlen (str) + 1; } From a013714bd01f0cb20c9a646947f9392940a7e385 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 20:11:21 +0900 Subject: [PATCH 0582/3664] [qfcc] Add missing header file changes Oops --- tools/qfcc/include/options.h | 1 + tools/qfcc/include/value.h | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index 01345cff4..a43c908b6 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -46,6 +46,7 @@ typedef struct { qboolean vector_components; // add *_[xyz] symbols for vectors qboolean ifstring; // expand if (str) to if (str != "") qboolean const_initializers; // initialied globals are constant + qboolean promote_float; // promote float through ... } code_options_t; typedef struct { diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index aaac286b7..b4f22ee60 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -36,6 +36,7 @@ */ ///@{ +struct def_s; struct ex_value_s; struct type_s; From 5f299cbac79bf567a6bec3d30ab85dbb575ab462 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 21:29:31 +0900 Subject: [PATCH 0583/3664] [gamecode] Ensure static string refs are initialized That was a fun one to track down :P --- libs/gamecode/pr_strings.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index e280b4743..6270a8d12 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -267,7 +267,7 @@ PR_LoadStrings (progs_t *pr) if (res->static_strings) free (res->static_strings); - res->static_strings = malloc (count * sizeof (strref_t)); + res->static_strings = calloc (count, sizeof (strref_t)); count = 0; str = pr->pr_strings; while (str < end) { @@ -344,7 +344,7 @@ get_string (progs_t *pr, string_t num) case str_free: break; } - PR_Error (pr, "internal string error"); + PR_Error (pr, "internal string error: %d", __LINE__); } else { if (num >= pr->pr_stringsize) return 0; @@ -436,7 +436,8 @@ PR_SetReturnString (progs_t *pr, const char *s) requeue_strref (res, sr); } else if ((sr->type == str_return && !sr->rs_slot) || (sr->type != str_return && sr->rs_slot)) { - PR_Error (pr, "internal string error"); + PR_Error (pr, "internal string error: %d %d %p", __LINE__, + sr->type, sr->rs_slot); } return string_index (res, sr); } @@ -445,7 +446,7 @@ PR_SetReturnString (progs_t *pr, const char *s) // slot is empty if ((sr = res->rs_slot->strref)) { if (sr->type != str_return || sr->rs_slot != res->rs_slot) { - PR_Error (pr, "internal string error"); + PR_Error (pr, "internal string error: %d", __LINE__); } pr_strfree (pr, sr->s.string); } else { @@ -576,7 +577,7 @@ PR_FreeString (progs_t *pr, string_t str) break; case str_return: default: - PR_Error (pr, "internal string error"); + PR_Error (pr, "internal string error: %d", __LINE__); } free_string_ref (res, sr); return; @@ -593,7 +594,7 @@ PR_FreeTempStrings (progs_t *pr) for (sr = pr->pr_xtstr; sr; sr = t) { t = sr->next; if (sr->type != str_temp) - PR_Error (pr, "internal string error"); + PR_Error (pr, "internal string error: %d", __LINE__); if (R_STRING (pr) < 0 && string_index (res, sr) == R_STRING (pr) && pr->pr_depth) { prstack_t *frame = pr->pr_stack + pr->pr_depth - 1; From 67ec9bfb4796062800e863580295a16974553db5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 21:30:08 +0900 Subject: [PATCH 0584/3664] [vid] Initialize x event before sending Quietens valgrind nicely (though it gave a weird source of the memory). --- libs/video/targets/in_x11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index dc689a7d5..8ef111ec2 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -672,7 +672,7 @@ event_focusin (XEvent *event) static void center_pointer (void) { - XEvent event; + XEvent event = {}; event.type = MotionNotify; event.xmotion.display = x_disp; From bb0e65e9d4c2fd469bdeebfe1f2ccb4f3c728461 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 21:45:51 +0900 Subject: [PATCH 0585/3664] [cl_menu] Silence some debug output --- ruamoko/cl_menu/client_menu.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/cl_menu/client_menu.r b/ruamoko/cl_menu/client_menu.r index 67f9e80f1..dc4cd487e 100644 --- a/ruamoko/cl_menu/client_menu.r +++ b/ruamoko/cl_menu/client_menu.r @@ -147,7 +147,7 @@ void (int quick) scan_saves = filenames[i] = str_new (); loadable[i] = 0; string path = sprintf ("%s%i.sav", basename, i); - dprint(path + "\n"); + //dprint(path + "\n"); f = QFS_OpenFile (path); if (!f) { str_copy (filenames[i], "--- UNUSED SLOT ---"); From 89cf9f95232ccaa87c7977665daf970c443f1c45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 22:19:37 +0900 Subject: [PATCH 0586/3664] [qwaq] Use Sys_Printf for load error messages It gets them into the log file. --- ruamoko/qwaq/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 191714c74..ae82758ad 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -32,6 +32,8 @@ #endif #include +#include +#include #include "QF/cbuf.h" #include "QF/cmd.h" @@ -60,7 +62,7 @@ open_file (const char *path, int *len) QFile *file = Qopen (path, "rbz"); if (!file) { - perror (path); + Sys_Printf ("%s\n", sys_errlist[errno]); return 0; } *len = Qfilesize (file); From 8fc007648c1afd7a42c79fb4b13ff94d03b06b6f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 22:20:46 +0900 Subject: [PATCH 0587/3664] [qwaq] Add missed command enum string --- ruamoko/qwaq/qwaq-curses.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 15746b5e6..8d252a0b2 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -99,6 +99,7 @@ const char *qwaq_command_names[]= { "mvwaddstr", "waddstr", "mvwaddch", + "waddch", "wrefresh", "init_pair", "wbkgd", From 0780cca4963b2114a8c0666f255f6284df1aee5b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Mar 2020 22:21:15 +0900 Subject: [PATCH 0588/3664] [qwaq] Fixed swapped method implementations That was fun --- ruamoko/qwaq/qwaq-curses.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 8d252a0b2..1981a434c 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1487,7 +1487,7 @@ bi_i_TextContext__printf_ (progs_t *pr) } static void -bi_i_TextContext__addch_ (progs_t *pr) +bi_i_TextContext__vprintf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; const char *fmt = P_GSTRING (pr, 2); @@ -1497,7 +1497,7 @@ bi_i_TextContext__addch_ (progs_t *pr) } static void -bi_i_TextContext__vprintf_ (progs_t *pr) +bi_i_TextContext__addch_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int ch = P_INT (pr, 1); From 98756df9f75ffaf11a7dc3bffc108cb85289b3bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 18:03:25 +0900 Subject: [PATCH 0589/3664] [gamecode] Set final resource map free list pointer The sub-tables were being properly linked together, but the very final table was not properly terminated. --- include/QF/progs.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index ea17f533e..1ef71aeb2 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1491,6 +1491,8 @@ void *PR_Resources_Find (progs_t *pr, const char *name); Any memory allocated to the resource must be freed before freeing the resource. + A reset resource map is guaranteed to allocate elements sequentially. + \param type The type of the resource. Must match the \c type parameter used for PR_RESMAP. \param map The resource map. @@ -1505,6 +1507,8 @@ void *PR_Resources_Find (progs_t *pr, const char *name); *(type **) &map._free[j] = &map._free[j + 1]; \ if (i < map._size - 1) \ *(type **) &map._free[j] = &map._map[i + 1][0]; \ + else \ + *(type **) &map._free[j] = 0; \ } \ map._free = map._map[0]; From 1ccdd7678055d0dee27819c95de08e58f4d2836c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 18:09:03 +0900 Subject: [PATCH 0590/3664] [ruamoko] Clean up runtime init and cleanup Move the semi-permanent resource initialisation into the module init and the cleanup of those resources into cleanup. Makes actual runtime init much easier to read. --- libs/ruamoko/rua_obj.c | 72 ++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index e088ff140..a8c2f9e7b 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1908,43 +1908,6 @@ rua_obj_init_runtime (progs_t *pr) { probj_t *probj = pr->pr_objective_resources; pr_def_t *def; - unsigned i; - - if (!probj->selector_hash) - probj->selector_hash = Hash_NewTable (1021, selector_get_key, 0, - probj); - else - Hash_FlushTable (probj->selector_hash); - probj->selector_index = 0; - for (i = 0; i < probj->selector_index_max; i++) { - obj_list_free (probj->selector_sels[i]); - probj->selector_sels[i] = 0; - probj->selector_names[i] = 0; - } - - if (!probj->classes) - probj->classes = Hash_NewTable (1021, class_get_key, 0, probj); - else - Hash_FlushTable (probj->classes); - - if (!probj->protocols) - probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj); - else - Hash_FlushTable (probj->protocols); - - if (!probj->load_methods) { - probj->load_methods = Hash_NewTable (1021, 0, 0, probj); - Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, - load_methods_compare); - } else { - Hash_FlushTable (probj->load_methods); - } - - probj->unresolved_classes = 0; - probj->unclaimed_categories = 0; - probj->unclaimed_proto_list = 0; - probj->module_list = 0; - probj->class_tree_list = 0; if ((def = PR_FindField (pr, ".this"))) pr->fields.this = def->ofs; @@ -1956,15 +1919,50 @@ rua_obj_init_runtime (progs_t *pr) static void rua_obj_cleanup (progs_t *pr, void *data) { + unsigned i; + __auto_type probj = (probj_t *) data; pr->pr_objective_resources = probj; + + Hash_FlushTable (probj->selector_hash); + probj->selector_index = 0; + for (i = 0; i < probj->selector_index_max; i++) { + obj_list_free (probj->selector_sels[i]); + probj->selector_sels[i] = 0; + probj->selector_names[i] = 0; + } + + for (i = 0; i < probj->dtables._size; i++) { + dtable_t *dtable = dtable_get (probj, i); + if (!dtable->imp) { + break; + } + free (dtable->imp); + } + dtable_reset (probj); + + Hash_FlushTable (probj->classes); + Hash_FlushTable (probj->protocols); + Hash_FlushTable (probj->load_methods); + probj->unresolved_classes = 0; + probj->unclaimed_categories = 0; + probj->unclaimed_proto_list = 0; + probj->module_list = 0; + probj->class_tree_list = 0; } void RUA_Obj_Init (progs_t *pr, int secure) { probj_t *probj = calloc (1, sizeof (*probj)); + probj->pr = pr; + probj->selector_hash = Hash_NewTable (1021, selector_get_key, 0, probj); + probj->classes = Hash_NewTable (1021, class_get_key, 0, probj); + probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj); + probj->load_methods = Hash_NewTable (1021, 0, 0, probj); + Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, + load_methods_compare); PR_Resources_Register (pr, "RUA_ObjectiveQuakeC", probj, rua_obj_cleanup); From e2f4c189f998621c396eb2e9d5cd56f43d05c9ae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 18:11:36 +0900 Subject: [PATCH 0591/3664] [ruamoko] Install and use dispatch tables This should speed up ruamoko code somewhat as hash table lookups have been replaced with direct array indexing. As a bonus, support for message forwarding has been added (though not tested). --- include/QF/pr_obj.h | 2 +- libs/ruamoko/rua_obj.c | 125 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/include/QF/pr_obj.h b/include/QF/pr_obj.h index fa3bbca84..52f05aa16 100644 --- a/include/QF/pr_obj.h +++ b/include/QF/pr_obj.h @@ -94,7 +94,7 @@ typedef struct pr_class_s { pr_int_t instance_size; pointer_t ivars; // pr_ivar_list_t pointer_t methods; // pr_method_list_t - pointer_t dtable; + pointer_t dtable; // resource index pointer_t subclass_list; // pr_class_t pointer_t sibling_class; // pr_class_t pointer_t protocols; // pr_protocol_list_t diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index a8c2f9e7b..50ba97de1 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -56,17 +56,26 @@ #include "compat.h" #include "rua_internal.h" +#define always_inline inline __attribute__((__always_inline__)) + typedef struct obj_list_s { struct obj_list_s *next; void *data; } obj_list; +typedef struct dtable_s { + size_t size; + func_t *imp; +} dtable_t; + typedef struct probj_resources_s { progs_t *pr; unsigned selector_index; unsigned selector_index_max; obj_list **selector_sels; string_t *selector_names; + PR_RESMAP (dtable_t) dtables; + func_t obj_forward; hashtab_t *selector_hash; hashtab_t *classes; hashtab_t *protocols; @@ -79,6 +88,41 @@ typedef struct probj_resources_s { obj_list *class_tree_list; } probj_t; +static dtable_t * +dtable_new (probj_t *probj) +{ + PR_RESNEW (dtable_t, probj->dtables); +} + +static void +dtable_reset (probj_t *probj) +{ + PR_RESRESET (dtable_t, probj->dtables); +} + +static inline dtable_t * +dtable_get (probj_t *probj, int index) +{ + PR_RESGET (probj->dtables, index); +} + +static inline int +dtable_index (probj_t *probj, dtable_t *dtable) +{ + PR_RESINDEX (probj->dtables, dtable); +} + +static always_inline dtable_t * __attribute__((pure)) +get_dtable (probj_t *probj, const char *name, int index) +{ + dtable_t *dtable = dtable_get (probj, index); + + if (!dtable) { + PR_RunError (probj->pr, "invalid dtable index in %s", name); + } + return dtable; +} + static obj_list *obj_list_free_list; static obj_list * @@ -832,12 +876,83 @@ obj_send_initialize (probj_t *probj, pr_class_t *class) } } +static void +obj_install_methods_in_dtable (probj_t *probj, pr_class_t *class, + pr_method_list_t *method_list) +{ + progs_t *pr = probj->pr; + dtable_t *dtable; + + if (!method_list) { + return; + } + if (method_list->method_next) { + obj_install_methods_in_dtable (probj, class, + &G_STRUCT (pr, pr_method_list_t, + method_list->method_next)); + } + + dtable = get_dtable (probj, __FUNCTION__, class->dtable); + for (int i = 0; i < method_list->method_count; i++) { + pr_method_t *method = &method_list->method_list[i]; + pr_sel_t *sel = &G_STRUCT (pr, pr_sel_t, method->method_name); + if (sel->sel_id < dtable->size) { + dtable->imp[sel->sel_id] = method->method_imp; + } + } +} + +static void +obj_install_dispatch_table_for_class (probj_t *probj, pr_class_t *class) +{ + progs_t *pr = probj->pr; + pr_class_t *super = &G_STRUCT (pr, pr_class_t, class->super_class); + dtable_t *dtable; + + Sys_MaskPrintf (SYS_RUA_OBJ, " install dispatch for class %s %x %d\n", + PR_GetString (pr, class->name), + class->methods, + PR_CLS_ISMETA(class)); + + if (super && !super->dtable) { + obj_install_dispatch_table_for_class (probj, super); + } + + dtable = dtable_new (probj); + class->dtable = dtable_index (probj, dtable); + dtable->size = probj->selector_index + 1; + dtable->imp = calloc (dtable->size, sizeof (func_t)); + if (super) { + dtable_t *super_dtable = get_dtable (probj, __FUNCTION__, + super->dtable); + memcpy (dtable->imp, super_dtable->imp, + super_dtable->size * sizeof (*dtable->imp)); + } + obj_install_methods_in_dtable (probj, class, + &G_STRUCT (pr, pr_method_list_t, + class->methods)); +} + static func_t get_imp (probj_t *probj, pr_class_t *class, pr_sel_t *sel) { - pr_method_t *method = obj_find_message (probj, class, sel); + func_t imp = 0; - return method ? method->method_imp : 0; + if (class->dtable) { + dtable_t *dtable = get_dtable (probj, __FUNCTION__, class->dtable); + if (sel->sel_id < dtable->size) { + imp = dtable->imp[sel->sel_id]; + } + } + if (!imp) { + if (!class->dtable) { + obj_install_dispatch_table_for_class (probj, class); + imp = get_imp (probj, class, sel); + } else { + imp = probj->obj_forward; + } + } + return imp; } static func_t @@ -1908,10 +2023,16 @@ rua_obj_init_runtime (progs_t *pr) { probj_t *probj = pr->pr_objective_resources; pr_def_t *def; + dfunction_t *obj_forward; if ((def = PR_FindField (pr, ".this"))) pr->fields.this = def->ofs; + probj->obj_forward = 0; + if ((obj_forward = PR_FindFunction (pr, "__obj_forward"))) { + probj->obj_forward = (intptr_t) (obj_forward - pr->pr_functions); + } + PR_AddLoadFinishFunc (pr, rua_init_finish); return 1; } From a4875951498b4c1be74363299290b9f591948087 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 19:09:08 +0900 Subject: [PATCH 0592/3664] [ruamoko,libr] Begin implementation of __obj_forward libr supplies an __obj_forward definition that links to a builtin, but as it is the only def in its object file, it is readily replaceable by an alternative Ruamoko implementation. The builtin version currently simply errors out (rather facetiously), but only as a stub to allow progs to load. --- libs/ruamoko/rua_obj.c | 12 ++++++++++++ ruamoko/include/runtime.h | 1 + ruamoko/lib/Makefile.am | 1 + ruamoko/lib/Object.r | 5 +++++ ruamoko/lib/obj_forward.r | 3 +++ 5 files changed, 22 insertions(+) create mode 100644 ruamoko/lib/obj_forward.r diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 50ba97de1..f5e48ef39 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1209,6 +1209,17 @@ rua___obj_exec_class (progs_t *pr) PR_GetString (pr, module->name)); } +static void +rua___obj_forward (progs_t *pr) +{ + probj_t *probj = pr->pr_objective_resources; + pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0); + pr_sel_t *op = &P_STRUCT (pr, pr_sel_t, 1); + PR_RunError (pr, "seriously, dude, %s does not respond to %s", + PR_GetString (pr, object_get_class_name (probj, receiver)), + PR_GetString (pr, probj->selector_names[op->sel_id])); +} + static void rua_obj_error (progs_t *pr) { @@ -1928,6 +1939,7 @@ rua_PR_FindGlobal (progs_t *pr) static builtin_t obj_methods [] = { {"__obj_exec_class", rua___obj_exec_class, -1}, + {"__obj_forward", rua___obj_forward, -1}, {"obj_error", rua_obj_error, -1}, {"obj_verror", rua_obj_verror, -1}, diff --git a/ruamoko/include/runtime.h b/ruamoko/include/runtime.h index bbcd793ed..357416e26 100644 --- a/ruamoko/include/runtime.h +++ b/ruamoko/include/runtime.h @@ -38,6 +38,7 @@ typedef enum { YES ///< a true value } BOOL; +@extern void __obj_forward(id, SEL, ...); @extern void obj_error (id object, int code, string fmt, ...); @extern void obj_verror (id object, int code, string fmt, @va_list args); //obj_error_handler obj_set_error_handler (objc_error_handler func); diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index 8a66a3839..da1157a82 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -37,6 +37,7 @@ r_depfiles_remade= libr_a_SOURCES=\ cbuf.r cmd.r cvar.r hash.r msgbuf.r plist.r qfile.r qfs.r script.r \ sound.r string.r math.r types.r \ + obj_forward.r \ Object.r Protocol.r \ AutoreleasePool.r Array.r Array+Private.r Entity.r PropertyList.r Set.r libr_a_obj=$(libr_a_SOURCES:.r=.o) diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index d85a78064..07de4b7eb 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -1,6 +1,11 @@ #include #include +static void link__obj_forward (void) +{ + __obj_forward (nil, nil); +} + void *PR_FindGlobal (string name) = #0; //FIXME where? void __obj_exec_class (struct obj_module *msg) = #0; diff --git a/ruamoko/lib/obj_forward.r b/ruamoko/lib/obj_forward.r new file mode 100644 index 000000000..60ad819b5 --- /dev/null +++ b/ruamoko/lib/obj_forward.r @@ -0,0 +1,3 @@ +// __obj_foward is the only thing in this file so it can be readily replaced +// at link time +void __obj_forward(id object, SEL sel, ...) = #0; From e3fe93c586bbad8908ce79cfde915f78ae6b2807 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 20:41:17 +0900 Subject: [PATCH 0593/3664] [gamecode] Implement most of message forwarding All that's left is the parameter setup of forward::. --- libs/ruamoko/rua_obj.c | 85 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 6 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index f5e48ef39..4dca5d218 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -76,6 +76,8 @@ typedef struct probj_resources_s { string_t *selector_names; PR_RESMAP (dtable_t) dtables; func_t obj_forward; + pr_sel_t *forward_selector; + dstring_t *msg; hashtab_t *selector_hash; hashtab_t *classes; hashtab_t *protocols; @@ -491,7 +493,6 @@ sel_register_typed_name (probj_t *probj, const char *name, const char *types, int is_new = 0; obj_list *l; - Sys_MaskPrintf (SYS_RUA_OBJ, " Registering SEL %s %s\n", name, types); index = (intptr_t) Hash_Find (probj->selector_hash, name); if (index) { for (l = probj->selector_sels[index]; l; l = l->next) { @@ -513,6 +514,8 @@ sel_register_typed_name (probj_t *probj, const char *name, const char *types, } } } else { + Sys_MaskPrintf (SYS_RUA_OBJ, " Registering SEL %s %s\n", + name, types); index = add_sel_name (probj, name); is_new = 1; } @@ -933,6 +936,15 @@ obj_install_dispatch_table_for_class (probj_t *probj, pr_class_t *class) class->methods)); } +static inline dtable_t * +obj_check_dtable_installed (probj_t *probj, pr_class_t *class) +{ + if (!class->dtable) { + obj_install_dispatch_table_for_class (probj, class); + } + return get_dtable (probj, __FUNCTION__, class->dtable); +} + static func_t get_imp (probj_t *probj, pr_class_t *class, pr_sel_t *sel) { @@ -955,6 +967,23 @@ get_imp (probj_t *probj, pr_class_t *class, pr_sel_t *sel) return imp; } +static int +obj_reponds_to (probj_t *probj, pr_id_t *obj, pr_sel_t *sel) +{ + progs_t *pr = probj->pr; + pr_class_t *class; + dtable_t *dtable; + func_t imp = 0; + + class = &G_STRUCT (pr, pr_class_t, obj->class_pointer); + dtable = obj_check_dtable_installed (probj, class); + + if (sel->sel_id < dtable->size) { + imp = dtable->imp[sel->sel_id]; + } + return imp != 0; +} + static func_t obj_msg_lookup (probj_t *probj, pr_id_t *receiver, pr_sel_t *op) { @@ -1213,11 +1242,54 @@ static void rua___obj_forward (progs_t *pr) { probj_t *probj = pr->pr_objective_resources; - pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0); - pr_sel_t *op = &P_STRUCT (pr, pr_sel_t, 1); - PR_RunError (pr, "seriously, dude, %s does not respond to %s", - PR_GetString (pr, object_get_class_name (probj, receiver)), - PR_GetString (pr, probj->selector_names[op->sel_id])); + pr_id_t *obj = &P_STRUCT (pr, pr_id_t, 0); + pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 1); + pr_sel_t *fwd_sel = probj->forward_selector; + pr_sel_t *err_sel; + pr_class_t *class =&G_STRUCT (pr, pr_class_t, obj->class_pointer); + func_t imp; + + if (!fwd_sel) { + //FIXME sel_register_typed_name is really not the way to go about + //looking for a selector by name + fwd_sel = sel_register_typed_name (probj, "forward::", "", 0); + probj->forward_selector = fwd_sel; + } + if (obj_reponds_to (probj, obj, fwd_sel)) { + imp = get_imp (probj, class, fwd_sel); + PR_CallFunction (pr, imp); + return; + } + //FIXME ditto + err_sel = sel_register_typed_name (probj, "doesNotRecognize:", "", 0); + if (obj_reponds_to (probj, obj, err_sel)) { + imp = get_imp (probj, class, err_sel); + PR_RESET_PARAMS (pr); + P_POINTER (pr, 0) = PR_SetPointer (pr, obj); + P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); + P_POINTER (pr, 2) = PR_SetPointer (pr, sel); + PR_CallFunction (pr, imp); + return; + } + + dsprintf (probj->msg, "(%s) %s does not recognize %s", + PR_CLS_ISMETA (class) ? "class" : "instance", + PR_GetString (pr, class->name), + PR_GetString (pr, probj->selector_names[sel->sel_id])); + + //FIXME ditto + err_sel = sel_register_typed_name (probj, "error:", "", 0); + if (obj_reponds_to (probj, obj, err_sel)) { + imp = get_imp (probj, class, err_sel); + PR_RESET_PARAMS (pr); + P_POINTER (pr, 0) = PR_SetPointer (pr, obj); + P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); + P_POINTER (pr, 2) = PR_SetTempString (pr, probj->msg->str); + PR_CallFunction (pr, imp); + return; + } + + PR_RunError (pr, "%s", probj->msg->str); } static void @@ -2094,6 +2166,7 @@ RUA_Obj_Init (progs_t *pr, int secure) probj->classes = Hash_NewTable (1021, class_get_key, 0, probj); probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj); probj->load_methods = Hash_NewTable (1021, 0, 0, probj); + probj->msg = dstring_newstr(); Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, load_methods_compare); From 7d43bd5c663e80234a04d5d0da94c10c89d1506d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 22:16:19 +0900 Subject: [PATCH 0594/3664] [gamecode] Add function PR_AllocTempBlock() PR_AllocTempBlock() works the same way as PR_SetTempString(), except that it takes a size parameter and always allocates (never tries to merge). This is, in a way, abusing the string system, but I needed a way to allocate a block of progs memory that would be automatically freed when the current frame ended. The biggest abuse is the need to cast away the const of PR_GetString()'s return value. --- include/QF/progs.h | 12 ++++++++++++ libs/gamecode/pr_strings.c | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 1ef71aeb2..28a2890d2 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1274,6 +1274,18 @@ string_t PR_SetReturnString(progs_t *pr, const char *s); */ string_t PR_SetTempString(progs_t *pr, const char *s); +/** Make a temporary memory block that will be freed when the current progs + stack frame is exited. The contents may be anything and a new block is + returned every time, and the block is in VM addressible space. To access + the contents of the block (for reading, writing, etc), use PR_GetString() + and cast the pointer as necessary. + + \param pr pointer to ::progs_t VM struct + \param size size of block in bytes + \return string index of the block +*/ +string_t PR_AllocTempBlock (progs_t *pr, size_t size); + /** Make a temporary progs string that is the concatenation of two C strings. \param pr pointer to ::progs_t VM struct \param a C string diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 6270a8d12..d9eee8fa2 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -384,10 +384,16 @@ PR_GetMutableString (progs_t *pr, string_t num) PR_RunError (pr, "Invalid string offset: %d", num); } +static inline void * +pr_strmalloc (progs_t *pr, size_t size) +{ + return PR_Zone_Malloc (pr, size); +} + static inline char * pr_stralloc (progs_t *pr, size_t len) { - return PR_Zone_Malloc (pr, len + 1); + return pr_strmalloc (pr, len + 1); } static inline void @@ -507,6 +513,13 @@ PR_SetTempString (progs_t *pr, const char *s) return pr_settempstring (pr, res, pr_strdup (pr, s)); } +VISIBLE string_t +PR_AllocTempBlock (progs_t *pr, size_t size) +{ + prstr_resources_t *res = pr->pr_string_resources; + return pr_settempstring (pr, res, pr_strmalloc (pr, size)); +} + VISIBLE string_t PR_SetDynamicString (progs_t *pr, const char *s) { From fa0a74efdfc8d2cf6ee222ed91e6dd6cf8637402 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 22:20:11 +0900 Subject: [PATCH 0595/3664] [ruamoko] Finish implementation of __obj_forward With this, object's implementing forward:: seem to accept the message well, including receiving all the original args (not quite sure how to deal with them in ruamoko code just yet, though). --- libs/ruamoko/rua_obj.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 4dca5d218..fb54585c1 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1257,6 +1257,25 @@ rua___obj_forward (progs_t *pr) } if (obj_reponds_to (probj, obj, fwd_sel)) { imp = get_imp (probj, class, fwd_sel); + // forward:(SEL) sel :(@va_list) args + // args is full param list + //FIXME oh for a stack + size_t size = pr->pr_argc * sizeof (pr_type_t); + string_t args_block = PR_AllocTempBlock (pr, size); + + int argc = pr->pr_argc; + __auto_type argv = (pr_type_t *) PR_GetString (pr, args_block); + // can't memcpy all params because 0 and 1 could be anywhere + memcpy (argv + 0, &P_INT (pr, 0), 4 * sizeof (pr_type_t)); + memcpy (argv + 4, &P_INT (pr, 1), 4 * sizeof (pr_type_t)); + memcpy (argv + 8, &P_INT (pr, 2), (argc - 2) * sizeof (pr_type_t)); + + PR_RESET_PARAMS (pr); + P_POINTER (pr, 0) = PR_SetPointer (pr, obj); + P_POINTER (pr, 1) = PR_SetPointer (pr, fwd_sel); + P_POINTER (pr, 2) = PR_SetPointer (pr, sel); + P_PACKED (pr, pr_va_list_t, 3).count = argc; + P_PACKED (pr, pr_va_list_t, 3).list = PR_SetPointer (pr, argv); PR_CallFunction (pr, imp); return; } From 9b0368039eef0cccebd8c8c302af2cd3c15d64fb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 22:54:22 +0900 Subject: [PATCH 0596/3664] [ruamoko] Include param size in size of args block I forget it every time. It really doesn't help that params are 4 words and words are 4 bytes, so seeing a size of 12 for 3 parameters *looks* right. --- libs/ruamoko/rua_obj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index fb54585c1..a88edacc0 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1260,7 +1260,7 @@ rua___obj_forward (progs_t *pr) // forward:(SEL) sel :(@va_list) args // args is full param list //FIXME oh for a stack - size_t size = pr->pr_argc * sizeof (pr_type_t); + size_t size = pr->pr_argc * pr->pr_param_size * sizeof(pr_type_t); string_t args_block = PR_AllocTempBlock (pr, size); int argc = pr->pr_argc; From f290b115a5724535e8d2de303cde55662a14e553 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 23:36:09 +0900 Subject: [PATCH 0597/3664] [gamecode] Add function PR_PushTempString This "pushes" a temp string onto the callee's stack frame after removing it from the caller's stack frame. This is so builtins can pass auto-freed memory to called progs code. No checking is done, but mayhem is likely to ensue if a string is pushed that was allocated in an earlier frame. --- include/QF/progs.h | 12 ++++++++++++ libs/gamecode/pr_exec.c | 12 +++++++++++- libs/gamecode/pr_strings.c | 21 +++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 28a2890d2..2659ce303 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1286,6 +1286,17 @@ string_t PR_SetTempString(progs_t *pr, const char *s); */ string_t PR_AllocTempBlock (progs_t *pr, size_t size); +/** Push a temporary string to the callee stack frame + + This is for when the temp string needs to be freed when the called function + returns rather than the calling function. It is an error to push a non-temp + string. + + \param pr pointer to ::progs_t VM struct + \param num string index of the temp string +*/ +void PR_PushTempString (progs_t *pr, string_t num); + /** Make a temporary progs string that is the concatenation of two C strings. \param pr pointer to ::progs_t VM struct \param a C string @@ -1733,6 +1744,7 @@ struct progs_s { ///@{ struct prstr_resources_s *pr_string_resources; strref_t *pr_xtstr; + strref_t *pr_pushtstr; int float_promoted; ///< for PR_Sprintf ///@} diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index b933572e4..7f097dcf7 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -123,7 +123,8 @@ PR_PushFrame (progs_t *pr) frame->f = pr->pr_xfunction; frame->tstr = pr->pr_xtstr; - pr->pr_xtstr = 0; + pr->pr_xtstr = pr->pr_pushtstr; + pr->pr_pushtstr = 0; pr->pr_xfunction = 0; } @@ -137,6 +138,15 @@ PR_PopFrame (progs_t *pr) if (pr->pr_xtstr) PR_FreeTempStrings (pr); + // normally, this won't happen, but if a builtin pushed a temp string + // when calling a function and the callee was another builtin that + // did not call a progs function, then the push strings will still be + // valid because PR_EnterFunction was never called + if (pr->pr_pushtstr) { + pr->pr_xtstr = pr->pr_pushtstr; + pr->pr_pushtstr = 0; + PR_FreeTempStrings (pr); + } // up stack frame = pr->pr_stack + --pr->pr_depth; diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index d9eee8fa2..00bb16e4f 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -520,6 +520,27 @@ PR_AllocTempBlock (progs_t *pr, size_t size) return pr_settempstring (pr, res, pr_strmalloc (pr, size)); } +VISIBLE void +PR_PushTempString (progs_t *pr, string_t num) +{ + prstr_resources_t *res = pr->pr_string_resources; + strref_t *ref = get_strref (res, num); + strref_t **temp_ref; + + if (!ref || ref->type != str_temp) { + PR_Error (pr, "attempt to push a non-temp string"); + } + for (temp_ref = &pr->pr_xtstr; *temp_ref; temp_ref = &(*temp_ref)->next) { + if (*temp_ref == ref) { + *temp_ref = ref->next; + ref->next = pr->pr_pushtstr; + pr->pr_pushtstr = ref; + return; + } + } + PR_Error (pr, "attempt to push stale temp string"); +} + VISIBLE string_t PR_SetDynamicString (progs_t *pr, const char *s) { From af37b660e8c3be492984ee213423f449eb5798c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Mar 2020 23:38:27 +0900 Subject: [PATCH 0598/3664] [ruamoko] Push the forwarded args block This causes the block to be freed when the forward: handler returns (assuming it's not yet another builtin). This is necessary so calling a lot of forwarded messages in a loop doesn't leak memory (though it will get freed eventually). --- libs/ruamoko/rua_obj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index a88edacc0..35557b5ff 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1276,6 +1276,7 @@ rua___obj_forward (progs_t *pr) P_POINTER (pr, 2) = PR_SetPointer (pr, sel); P_PACKED (pr, pr_va_list_t, 3).count = argc; P_PACKED (pr, pr_va_list_t, 3).list = PR_SetPointer (pr, argv); + PR_PushTempString (pr, args_block); PR_CallFunction (pr, imp); return; } From 2a152e63563aaf1f016466c967819f13bc4d0ac0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 00:07:01 +0900 Subject: [PATCH 0599/3664] [ruamoko] Add builtin __obj_responds_to Fast dtable-based messages response test. However, it does not handle forwarding. --- libs/ruamoko/rua_obj.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 35557b5ff..c249e2b6a 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1312,6 +1312,16 @@ rua___obj_forward (progs_t *pr) PR_RunError (pr, "%s", probj->msg->str); } +static void +rua___obj_responds_to (progs_t *pr) +{ + probj_t *probj = pr->pr_objective_resources; + pr_id_t *obj = &P_STRUCT (pr, pr_id_t, 0); + pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 1); + + R_INT (pr) = obj_reponds_to (probj, obj, sel); +} + static void rua_obj_error (progs_t *pr) { @@ -2032,6 +2042,7 @@ rua_PR_FindGlobal (progs_t *pr) static builtin_t obj_methods [] = { {"__obj_exec_class", rua___obj_exec_class, -1}, {"__obj_forward", rua___obj_forward, -1}, + {"__obj_responds_to", rua___obj_responds_to, -1}, {"obj_error", rua_obj_error, -1}, {"obj_verror", rua_obj_verror, -1}, From 4978713dee093902bdf5753daa3f2ca06cb13602 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 00:09:46 +0900 Subject: [PATCH 0600/3664] [libr] Add __obj_responds_to proto and definition --- ruamoko/include/runtime.h | 3 ++- ruamoko/lib/Object.r | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ruamoko/include/runtime.h b/ruamoko/include/runtime.h index 357416e26..80e0aff7e 100644 --- a/ruamoko/include/runtime.h +++ b/ruamoko/include/runtime.h @@ -38,7 +38,8 @@ typedef enum { YES ///< a true value } BOOL; -@extern void __obj_forward(id, SEL, ...); +@extern void __obj_forward(id obj, SEL sel, ...); +@extern BOOL __obj_responds_to(id obj, SEL sel); @extern void obj_error (id object, int code, string fmt, ...); @extern void obj_verror (id object, int code, string fmt, @va_list args); //obj_error_handler obj_set_error_handler (objc_error_handler func); diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index 07de4b7eb..21e53326f 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -9,6 +9,7 @@ static void link__obj_forward (void) void *PR_FindGlobal (string name) = #0; //FIXME where? void __obj_exec_class (struct obj_module *msg) = #0; +BOOL __obj_responds_to(id obj, SEL sel) = #0; void (id object, int code, string fmt, ...) obj_error = #0; void (id object, int code, string fmt, @va_list args) obj_verror = #0; //obj_error_handler (objc_error_handler func) obj_set_error_handler = #0; From e9eab683666b9829e9f6dd8c3bb7d1d7efab6589 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 02:39:18 +0900 Subject: [PATCH 0601/3664] [qwaq] Begin work on local drawing buffers --- ruamoko/qwaq/Makefile.am | 2 + ruamoko/qwaq/qwaq-draw.h | 25 +++++++++--- ruamoko/qwaq/qwaq-draw.r | 86 ++++++++++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-rect.h | 1 + ruamoko/qwaq/qwaq-rect.r | 39 ++++++++++++++++++ ruamoko/qwaq/qwaq-view.r | 16 -------- 6 files changed, 148 insertions(+), 21 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-draw.r create mode 100644 ruamoko/qwaq/qwaq-rect.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index bf8c2c9b8..dc5fa56b9 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -25,7 +25,9 @@ SUFFIXES=.o .r qwaq_app_dat_src= \ qwaq-app.r \ + qwaq-draw.r \ qwaq-group.r \ + qwaq-rect.r \ qwaq-screen.r \ qwaq-textcontext.r \ qwaq-view.r \ diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index 983dd8074..50475fa3d 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -1,11 +1,26 @@ #ifndef __qwaq_draw_h #define __qwaq_draw_h -@protocol Draw --draw; --redraw; --setOwner: owner; --(struct window_s*) getWindow; +#include + +#include "qwaq-rect.h" + +@interface DrawBuffer : Object +{ + int *buffer; + Extent size; + Point cursor; +} ++ (DrawBuffer *) buffer: (Extent) size; +- initWithSize: (Extent) size; +- blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; + +- (void) printf: (string) fmt, ...; +- (void) vprintf: (string) fmt, @va_list args; +- (void) addch: (int) ch; +- (void) mvprintf: (Point) pos, string fmt, ...; +- (void) mvvprintf: (Point) pos, string fmt, @va_list args; +- (void) mvaddch: (Point) pos, int ch; @end #endif diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r new file mode 100644 index 000000000..8ee7ad029 --- /dev/null +++ b/ruamoko/qwaq/qwaq-draw.r @@ -0,0 +1,86 @@ +#include "qwaq-curses.h" +#include "qwaq-draw.h" + +@implementation DrawBuffer + ++ (DrawBuffer *) buffer: (Extent) size +{ + return [[self alloc] initWithSize: size]; +} + +- initWithSize: (Extent) size +{ + if (!(self = [super init])) { + return nil; + } + buffer = obj_malloc (size.width * size.height); + self.size = size; + return self; +} + +- blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect +{ + Extent srcSize = srcBuffer.size; + Rect r = { {}, srcBuffer.size }; + Rect t = { pos, rect.extent }; + + t = clipRect (r, t); + if (t.extent.width < 0 || t.extent.height < 0) { + return self; + } + + rect.offset.x += t.offset.x - pos.x; + rect.offset.y += t.offset.y - pos.y; + rect.extent = t.extent; + pos = t.offset; + + r.offset = nil; + r.extent = size; + + rect = clipRect (r, rect); + if (rect.extent.width < 0 || rect.extent.height < 0) { + return self; + } + + int *dst = buffer + pos.y * size.width + pos.x; + int *src = srcBuffer.buffer + + rect.offset.y * srcSize.width + rect.offset.x; + for (int y = 0; y < rect.extent.height; y++) { + int *d = dst; + int *s = src; + dst += size.width; + src += srcSize.width; + for (int x = 0; x < rect.extent.width; x++) { + // FIXME 1) need memcpy/memmove + // 2) the generated code could be better + *d++ = *s++; + } + } + return self; +} + +- (void) printf: (string) fmt, ... +{ +} + +- (void) vprintf: (string) fmt, @va_list args +{ +} + +- (void) addch: (int) ch +{ +} + +- (void) mvprintf: (Point) pos, string fmt, ... +{ +} + +- (void) mvvprintf: (Point) pos, string fmt, @va_list args +{ +} + +- (void) mvaddch: (Point) pos, int ch +{ +} + +@end diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index 92c241f40..9d4fc51e4 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -21,6 +21,7 @@ typedef struct Rect_s { //XXX will not work if point or rect point to a local variabl @extern int rectContainsPoint (Rect *rect, Point *point); @extern Rect getwrect (struct window_s *window); +@extern Rect clipRect (Rect clipRect, Rect rect); #endif #endif//__qwaq_rect_h diff --git a/ruamoko/qwaq/qwaq-rect.r b/ruamoko/qwaq/qwaq-rect.r new file mode 100644 index 000000000..6ee5c7df5 --- /dev/null +++ b/ruamoko/qwaq/qwaq-rect.r @@ -0,0 +1,39 @@ +#include "qwaq-rect.h" + +Rect +clipRect (Rect clipRect, Rect rect) +{ + if (rect.offset.x < clipRect.offset.x) { + int dist = clipRect.offset.x - rect.offset.x; + rect.offset.x += dist; + rect.extent.width -= dist; + } + if (rect.offset.y < clipRect.offset.y) { + int dist = clipRect.offset.y - rect.offset.y; + rect.offset.y += dist; + rect.extent.height -= dist; + } + if (rect.offset.x + rect.extent.width > clipRect.extent.width) { + rect.extent.width = clipRect.extent.width - rect.offset.x; + } + if (rect.offset.y + rect.extent.height > clipRect.extent.height) { + rect.extent.height = clipRect.extent.height - rect.offset.y; + } + return rect; +} + +Rect +makeRect (int xpos, int ypos, int xlen, int ylen) +{ + Rect rect = {{xpos, ypos}, {xlen, ylen}}; + return rect; +} + +int +rectContainsPoint (Rect *rect, Point *point) +{ + return ((point.x >= rect.offset.x + && point.x < rect.offset.x + rect.extent.width) + && (point.y >= rect.offset.y + && point.y < rect.offset.y + rect.extent.height)); +} diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 541012a47..fc0ccf90f 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -2,22 +2,6 @@ #include "qwaq-view.h" #include "qwaq-group.h" -Rect -makeRect (int xpos, int ypos, int xlen, int ylen) -{ - Rect rect = {{xpos, ypos}, {xlen, ylen}}; - return rect; -} - -int -rectContainsPoint (Rect *rect, Point *point) -{ - return ((point.x >= rect.offset.x - && point.x < rect.offset.x + rect.extent.width) - && (point.y >= rect.offset.y - && point.y < rect.offset.y + rect.extent.height)); -} - @implementation View -init From 4b7d5447bbe5f8b6b0c760660fcd2ae183544c40 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 02:56:37 +0900 Subject: [PATCH 0602/3664] [ruamoko] Correct obj_msg_sendv for __obj_forward Until I implemented forwarding, I didn't know how obj_msg_sendv was meant to be used, so no surprise I got the implementation wrong. --- libs/ruamoko/rua_obj.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index c249e2b6a..f02bedcc3 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1386,22 +1386,41 @@ static void rua_obj_msg_sendv (progs_t *pr) { probj_t *probj = pr->pr_objective_resources; + pointer_t obj = P_POINTER (pr, 0); pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0); + pointer_t sel = P_POINTER (pr, 1); pr_sel_t *op = &P_STRUCT (pr, pr_sel_t, 1); - pr_va_list_t *args = (pr_va_list_t *) &P_POINTER (pr, 2); - pr_type_t *params = G_GPOINTER (pr, args->list); - int count = args->count; func_t imp = obj_msg_lookup (probj, receiver, op); - count = bound (0, count, 6); - if (count && pr_boundscheck->int_val) + __auto_type args = &P_PACKED (pr, pr_va_list_t, 2); + int count = args->count; + pr_type_t *params = G_GPOINTER (pr, args->list); + + if (count < 2 || count > MAX_PARMS) { + PR_RunError (pr, "bad args count in obj_msg_sendv: %d", count); + } + if (pr_boundscheck->int_val) { PR_BoundsCheckSize (pr, args->list, count * pr->pr_param_size); - if (!imp) + } + + if (!imp) { PR_RunError (pr, "%s does not respond to %s", PR_GetString (pr, object_get_class_name (probj, receiver)), PR_GetString (pr, probj->selector_names[op->sel_id])); - if (count) - memcpy (pr->pr_params[2], params, count * 4 * pr->pr_param_size); + } + + pr->pr_argc = count; + // skip over the first two parameters because receiver and op will + // replace them + count -= 2; + params += 2 * pr->pr_param_size; + PR_RESET_PARAMS (pr); + P_POINTER (pr, 0) = obj; + P_POINTER (pr, 1) = sel; + if (count) { + memcpy (&P_INT (pr, 2), params, + count * sizeof (pr_type_t) * pr->pr_param_size); + } PR_CallFunction (pr, imp); } From f9d798c31439a6528df041944dd1a2496fccb676 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 02:58:30 +0900 Subject: [PATCH 0603/3664] [qwaq] Use forwarding for some text methods refresh won't be in the drawing buffer protocol, and the move commands need to be offset by the view's position in its window, but it works as intended. --- ruamoko/qwaq/qwaq-view.h | 10 +++++++--- ruamoko/qwaq/qwaq-view.r | 20 ++++++++------------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 10e0c93ae..086b9d12d 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -59,12 +59,16 @@ enum { -redraw; - (void) refresh; -- (void) printf: (string) fmt, ...; -- (void) vprintf: (string) fmt, @va_list args; -- (void) addch: (int) ch; - (void) mvprintf: (Point) pos, string fmt, ...; - (void) mvvprintf: (Point) pos, string fmt, @va_list args; - (void) mvaddch: (Point) pos, int ch; @end +//These are forwarded (FIXME make a protocol) +@interface View (TextContext) +- (void) printf: (string) fmt, ...; +- (void) vprintf: (string) fmt, @va_list args; +- (void) addch: (int) ch; +@end + #endif//__qwaq_view_h diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index fc0ccf90f..98cdf4429 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -89,14 +89,15 @@ updateScreenCursor (View *view) return ▭ } -- (void) printf: (string) fmt, ... +- (void) forward: (SEL) sel : (@va_list) args { - [textContext vprintf: fmt, @args]; -} - -- (void) vprintf: (string) fmt, @va_list args -{ - [textContext vprintf: fmt, args]; + if (!textContext) { + return; + } + if (!__obj_responds_to (textContext, sel)) { + [self error: "no implementation for %s", sel_get_name (sel)]; + } + obj_msg_sendv (textContext, sel, args); } - (void) refresh @@ -104,11 +105,6 @@ updateScreenCursor (View *view) [textContext refresh]; } -- (void) addch: (int) ch -{ - [textContext addch:ch]; -} - - (void) mvprintf: (Point) pos, string fmt, ... { pos.x += xpos; From 21b64421c3aaf2339c000b5e5fc805181f554fd1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 03:09:21 +0900 Subject: [PATCH 0604/3664] [ruamoko] Copy ALL the params to the args block *sigh* --- libs/ruamoko/rua_obj.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index f02bedcc3..c30683d0e 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1260,7 +1260,8 @@ rua___obj_forward (progs_t *pr) // forward:(SEL) sel :(@va_list) args // args is full param list //FIXME oh for a stack - size_t size = pr->pr_argc * pr->pr_param_size * sizeof(pr_type_t); + size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); + size_t size = pr->pr_argc * parm_size; string_t args_block = PR_AllocTempBlock (pr, size); int argc = pr->pr_argc; @@ -1268,7 +1269,7 @@ rua___obj_forward (progs_t *pr) // can't memcpy all params because 0 and 1 could be anywhere memcpy (argv + 0, &P_INT (pr, 0), 4 * sizeof (pr_type_t)); memcpy (argv + 4, &P_INT (pr, 1), 4 * sizeof (pr_type_t)); - memcpy (argv + 8, &P_INT (pr, 2), (argc - 2) * sizeof (pr_type_t)); + memcpy (argv + 8, &P_INT (pr, 2), (argc - 2) * parm_size); PR_RESET_PARAMS (pr); P_POINTER (pr, 0) = PR_SetPointer (pr, obj); From fb92ee12d67b8a82f69515b1da23d0156216e211 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 03:10:55 +0900 Subject: [PATCH 0605/3664] [qwaq] Set event type to none when no events Fixes the endless looping on the last event. --- ruamoko/qwaq/qwaq-curses.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 1981a434c..de5ed8ef0 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -733,6 +733,7 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) } return 1; } + event->what = qe_none; return 0; } From 6c56e93fc8f2edfc4796ee8f35aa3cca368b6f64 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 03:24:31 +0900 Subject: [PATCH 0606/3664] [gamecode] Be more careful with temp strings If a temp string is found in the return slot, PR_FreeTempStrings won't delete the string. However, PR_PopFrame was blindly stomping on the possibly surviving temp string with the push strings, which would cause a leak. --- libs/gamecode/pr_exec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 7f097dcf7..47b39bc58 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -142,7 +142,9 @@ PR_PopFrame (progs_t *pr) // when calling a function and the callee was another builtin that // did not call a progs function, then the push strings will still be // valid because PR_EnterFunction was never called - if (pr->pr_pushtstr) { + // however, not if a temp string survived: better to hold on to the push + // strings a little longer than lose one erroneously + if (!pr->pr_xtstr && pr->pr_pushtstr) { pr->pr_xtstr = pr->pr_pushtstr; pr->pr_pushtstr = 0; PR_FreeTempStrings (pr); From b517b95e45201b9bdec5428b1a636ff9e1123a77 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 14:29:43 +0900 Subject: [PATCH 0607/3664] [libr] Add -performv:: --- ruamoko/include/Object.h | 4 ++++ ruamoko/lib/Object.r | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/ruamoko/include/Object.h b/ruamoko/include/Object.h index eb10e55ef..981977651 100644 --- a/ruamoko/include/Object.h +++ b/ruamoko/include/Object.h @@ -24,6 +24,10 @@ - (id) performSelector: (SEL)aSelector withObject: (void *)anObject withObject: (void *)anotherObject; +// void return does not touch the actual return value (effectively retval) +// so if the target returns a value, and the forwarding method simply returns +// (and is void), the vallue will get out to the caller +- (void) performv: (SEL) sel : (@va_list) args; - (BOOL) respondsToSelector: (SEL)aSelector; - (BOOL) conformsToProtocol: (Protocol *)aProtocol; diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index 21e53326f..6c7e0e6f4 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -280,6 +280,11 @@ BOOL (id object) object_is_meta_class = #0; return msg (self, aSelector, anObject, anotherObject); } +- (void) performv: (SEL) sel : (@va_list) args +{ + obj_msg_sendv (self, sel, args); +} + - (void) doesNotRecognizeSelector: (SEL)aSelector { [self error: "%s does not recognize %s", From 1b1249bdb0887c44a46b189153816eeed49806a4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 18:16:07 +0900 Subject: [PATCH 0608/3664] [ruamoko] Add vsprintf builtin --- libs/ruamoko/pr_cmds.c | 20 ++++++++++++++++++++ ruamoko/include/string.h | 1 + ruamoko/lib/string.r | 1 + 3 files changed, 22 insertions(+) diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 8c6aa3d58..9a531fb14 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -583,6 +583,25 @@ PF_sprintf (progs_t *pr) dstring_delete (dstr); } +static void +PF_vsprintf (progs_t *pr) +{ + const char *fmt = P_GSTRING (pr, 0); + __auto_type args = &P_PACKED (pr, pr_va_list_t, 1); + pr_type_t *list_start = PR_GetPointer (pr, args->list); + pr_type_t **list = alloca (args->count * sizeof (*list)); + dstring_t *dstr; + + for (int i = 0; i < args->count; i++) { + list[i] = list_start + i * pr->pr_param_size; + } + + dstr = dstring_newstr (); + PR_Sprintf (pr, dstr, "PF_vsprintf", fmt, args->count, list); + RETURN_STRING (pr, dstr->str); + dstring_delete (dstr); +} + /* string () gametype */ @@ -643,6 +662,7 @@ static builtin_t builtins[] = { {"strlen", PF_strlen, QF 100}, {"charcount", PF_charcount, QF 101}, {"sprintf", PF_sprintf, QF 109}, + {"vsprintf", PF_vsprintf, -1}, {"ftoi", PF_ftoi, QF 110}, {"itof", PF_itof, QF 111}, {"itos", PF_itos, QF 112}, diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index c4136e2fc..d41e94ef8 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -7,6 +7,7 @@ @extern float strlen (string s); @extern float charcount (string goal, string s); @extern string sprintf (string fmt, ...); +@extern string vsprintf (string fmt, @va_list args); @extern string itos (int i); @extern int stoi (string s); @extern vector stov (string s); diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index 36247bf91..c6c239fa6 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -6,6 +6,7 @@ float (string s) stof = #81; float (string s) strlen = #0x000f0000 + 100; float (string goal, string s) charcount = #0x000f0000 + 101; string (string fmt, ...) sprintf = #0x000f0000 + 109; +string vsprintf (string fmt, @va_list args) = #0; string (int i) itos = #0x000f0000 + 112; int (string s) stoi = #0x000f0000 + 113; vector (string s) stov = #0x000f0000 + 114; From 694ad2e840c07c01ca7806adeaa4b39bc88ed4be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 18:16:55 +0900 Subject: [PATCH 0609/3664] [ruamoko] Add str_char builtin This returns the character (as an int) at the index. Equivalent to string[index], but qc code doesn't have char-level access and not having it means that strings can internally change to wchar without too much fuss (maybe). --- libs/ruamoko/rua_string.c | 13 +++++++++++++ ruamoko/include/string.h | 1 + ruamoko/lib/string.r | 1 + 3 files changed, 15 insertions(+) diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index fcd78c1cc..c96f44e57 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -134,6 +134,18 @@ bi_str_str (progs_t *pr) R_STRING (pr) = res - pr->pr_strings; } +static void +bi_str_char (progs_t *pr) +{ + const char *str = P_GSTRING (pr, 0); + int ind = P_INT (pr, 1); + + if (ind < 0) { + PR_RunError (pr, "negative index to str_char"); + } + R_INT (pr) = str[ind]; +} + static builtin_t builtins[] = { {"str_new", bi_str_new, -1}, {"str_free", bi_str_free, -1}, @@ -143,6 +155,7 @@ static builtin_t builtins[] = { {"str_mid|*i", bi_str_mid, -1}, {"str_mid|*ii", bi_str_mid, -1}, {"str_str", bi_str_str, -1}, + {"str_char", bi_str_char, -1}, {0} }; diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index d41e94ef8..3951c94c5 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -20,5 +20,6 @@ @extern @overload string str_mid (string str, int start); @extern @overload string str_mid (string str, int start, int len); @extern string str_str (string haystack, string needle); +@extern int str_char (string str, int ind); #endif//__ruamoko_string_h diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index c6c239fa6..58f64911a 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -19,3 +19,4 @@ string (string str) str_clear = #0; string (string str, int start) str_mid = #0; string (string str, int start, int len) str_mid = #0; string (string haystack, string needle) str_str = #0; +int str_char (string str, int ind) = #0; From f91fb4f840d352b46f7cae83a4ce4126391bb65c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 18:21:06 +0900 Subject: [PATCH 0610/3664] [qwaq] Add an mvwblit_line builtin I had to do my own thing with curses as the function I had planned to use turned out to be quite different from what I wanted (misread the man page). --- ruamoko/qwaq/qwaq-curses.c | 54 +++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-curses.h | 1 + ruamoko/qwaq/qwaq-textcontext.r | 1 + 3 files changed, 56 insertions(+) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index de5ed8ef0..8ba194619 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -80,6 +80,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_move, qwaq_cmd_curs_set, qwaq_cmd_wborder, + qwaq_cmd_mvwblit_line, } qwaq_commands; const char *qwaq_command_names[]= { @@ -107,6 +108,7 @@ const char *qwaq_command_names[]= { "move", "curs_set", "wborder", + "mvwblit_line", }; #define RING_BUFFER(type, size) \ @@ -617,6 +619,22 @@ cmd_wborder (qwaq_resources_t *res) wborder (window->win, ls, rs, ts, bs, tl, tr, bl, br); } +static void +cmd_mvwblit_line (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int x = RB_PEEK_DATA (res->command_queue, 3); + int y = RB_PEEK_DATA (res->command_queue, 4); + int chs_id = RB_PEEK_DATA (res->command_queue, 5); + int len = RB_PEEK_DATA (res->command_queue, 6); + int *chs = (int *) res->strings[chs_id].str; + + window_t *window = get_window (res, __FUNCTION__, window_id); + for (int i = 0; i < len; i++) { + mvwaddch (window->win, y, x, chs[i]); + } +} + static void process_commands (qwaq_resources_t *res) { @@ -701,6 +719,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_wborder: cmd_wborder (res); break; + case qwaq_cmd_mvwblit_line: + cmd_mvwblit_line (res); + break; } RB_DROP_DATA (res->command_queue, RB_PEEK_DATA (res->command_queue, 1)); } @@ -1384,6 +1405,38 @@ bi_wborder (progs_t *pr) qwaq_wborder (pr, window_id, sides, corns); } +static void +qwaq__mvwblit_line (progs_t *pr, int window_id, int x, int y, + int *chs, int len) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + if (get_window (res, __FUNCTION__, window_id)) { + int chs_id = acquire_string (res); + dstring_t *chs_buf = res->strings + chs_id; + int command[] = { qwaq_cmd_mvwblit_line, 0, window_id, + x, y, chs_id, len,}; + + command[1] = CMD_SIZE(command); + + chs_buf->size = len * sizeof (int); + dstring_adjust (chs_buf); + memcpy (chs_buf->str, chs, len * sizeof (int)); + + qwaq_submit_command (res, command); + } +} +static void +bi_mvwblit_line (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + int *chs = (int *) P_GPOINTER (pr, 3); + int len = P_INT (pr, 4); + qwaq__mvwblit_line (pr, window_id, x, y, chs, len); +} + static void bi_initialize (progs_t *pr) { @@ -1609,6 +1662,7 @@ static builtin_t builtins[] = { {"move", bi_move, -1}, {"curs_set", bi_curs_set, -1}, {"wborder", bi_wborder, -1}, + {"mvwblit_line", bi_mvwblit_line, -1}, {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 16cd4fe4e..b592ac84b 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -120,6 +120,7 @@ typedef struct panel_s *panel_t; @extern void wborder (window_t window, box_sides_t sides, box_corners_t corners); +@extern void mvwblit_line (window_t window, int x, int y, int *wch, int len); #endif #endif//__qwaq_curses_h diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 59b54fb6a..1797bde48 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -106,3 +106,4 @@ void doupdate (void) = #0; int curs_set (int visibility) = #0; int move (int x, int y) = #0; void wborder (window_t window, box_sides_t sides, box_corners_t corners) = #0; +void mvwblit_line (window_t window, int x, int y, int *wch, int len) = #0; From b3850bbc6986729d12bec63a54b9933979719937 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 19:23:51 +0900 Subject: [PATCH 0611/3664] [qwaq] Implement blitting from draw buffer to text Sending the data out to curses. --- ruamoko/qwaq/qwaq-draw.h | 4 ++++ ruamoko/qwaq/qwaq-draw.r | 10 ++++++++++ ruamoko/qwaq/qwaq-textcontext.h | 17 +++++++++++++++++ ruamoko/qwaq/qwaq-textcontext.r | 34 +++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+) diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index 50475fa3d..931ea6d12 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -13,6 +13,10 @@ } + (DrawBuffer *) buffer: (Extent) size; - initWithSize: (Extent) size; + +- (Extent) size; +- (int *) buffer; + - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; - (void) printf: (string) fmt, ...; diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index 8ee7ad029..333d737e4 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -18,6 +18,16 @@ return self; } +- (Extent) size +{ + return size; +} + +- (int *) buffer +{ + return buffer; +} + - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect { Extent srcSize = srcBuffer.size; diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/qwaq-textcontext.h index 4a47b16ca..765f90572 100644 --- a/ruamoko/qwaq/qwaq-textcontext.h +++ b/ruamoko/qwaq/qwaq-textcontext.h @@ -6,9 +6,24 @@ #include "qwaq-curses.h" #include "qwaq-rect.h" +@class DrawBuffer; + @interface TextContext : Object { window_t window; + union { + Rect rect; + struct { + Point offset; + Extent size; + }; + struct { + int xpos; + int ypos; + int xlen; + int ylen; + }; + }; } + (int) max_colors; + (int) max_color_pairs; @@ -25,6 +40,8 @@ -(window_t) window; +- blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; + - (void) printf: (string) fmt, ...; - (void) vprintf: (string) mft, @va_list args; - (void) addch: (int) ch; diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 1797bde48..726872ccf 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -1,3 +1,4 @@ +#include "qwaq-draw.h" #include "qwaq-textcontext.h" @implementation TextContext @@ -59,6 +60,39 @@ static TextContext *screen; return window; } +- blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect +{ + Extent srcSize = [srcBuffer size]; + Rect r = { {}, srcSize }; + Rect t = { pos, rect.extent }; + + t = clipRect (r, t); + if (t.extent.width < 0 || t.extent.height < 0) { + return self; + } + + rect.offset.x += t.offset.x - pos.x; + rect.offset.y += t.offset.y - pos.y; + rect.extent = t.extent; + pos = t.offset; + + r.offset = nil; + r.extent = size; + + rect = clipRect (r, rect); + if (rect.extent.width < 0 || rect.extent.height < 0) { + return self; + } + + int *src = [srcBuffer buffer] + + rect.offset.y * srcSize.width + rect.offset.x; + for (int y = 0; y < rect.extent.height; y++) { + mvwblit_line (window, pos.x, y + pos.y, src, rect.extent.width); + src += srcSize.width; + } + return self; +} + - (void) mvprintf: (Point) pos, string fmt, ... = #0; - (void) printf: (string) fmt, ... = #0; - (void) vprintf: (string) mft, @va_list args = #0; From ce67d9b202d878001ba614a3f5849fa844c110fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Mar 2020 19:27:26 +0900 Subject: [PATCH 0612/3664] [qwaq] Flesh out DrawBuffer's methods --- ruamoko/qwaq/qwaq-draw.h | 2 ++ ruamoko/qwaq/qwaq-draw.r | 70 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index 931ea6d12..a0ef18dc1 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -22,9 +22,11 @@ - (void) printf: (string) fmt, ...; - (void) vprintf: (string) fmt, @va_list args; - (void) addch: (int) ch; +- (void) addstr: (string) str; - (void) mvprintf: (Point) pos, string fmt, ...; - (void) mvvprintf: (Point) pos, string fmt, @va_list args; - (void) mvaddch: (Point) pos, int ch; +- (void) mvaddstr: (Point) pos, string str; @end #endif diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index 333d737e4..66e266a50 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -1,3 +1,5 @@ +#include + #include "qwaq-curses.h" #include "qwaq-draw.h" @@ -71,26 +73,94 @@ - (void) printf: (string) fmt, ... { + string str = vsprintf (fmt, @args); + [self addstr: str]; } - (void) vprintf: (string) fmt, @va_list args { + string str = vsprintf (fmt, args); + [self addstr: str]; } - (void) addch: (int) ch { + if (cursor.x < 0) { + cursor.x = 0; + } + if (cursor.y < 0) { + cursor.y = 0; + } + if (cursor.x >= size.width && cursor.y < size.height) { + cursor.x = 0; + cursor.y++; + } + if (cursor.y >= size.height) { + return; + } + if (ch == '\n') { + cursor.x = 0; + cursor.y++; + } else if (ch == '\r') { + cursor.x = 0; + } else { + buffer[cursor.y * size.width + cursor.x++] = ch; + } +} + +- (void) addstr: (string) str +{ + int ind = 0; + int ch; + + if (cursor.y >= size.height) { + return; + } + while (cursor.x < size.width && (ch = str_char (str, ind++))) { + [self addch: ch]; + } } - (void) mvprintf: (Point) pos, string fmt, ... { + if (pos.x < 0 || pos.x >= size.width + || pos.y < 0 || pos.y >= size.height) { + return; + } + cursor = pos; + string str = vsprintf (fmt, @args); + [self addstr: str]; } - (void) mvvprintf: (Point) pos, string fmt, @va_list args { + if (pos.x < 0 || pos.x >= size.width + || pos.y < 0 || pos.y >= size.height) { + return; + } + cursor = pos; + string str = vsprintf (fmt, args); + [self addstr: str]; } - (void) mvaddch: (Point) pos, int ch { + if (pos.x < 0 || pos.x >= size.width + || pos.y < 0 || pos.y >= size.height) { + return; + } + cursor = pos; + [self addch: ch]; +} + +- (void) mvaddstr: (Point) pos, string str +{ + if (pos.x < 0 || pos.x >= size.width + || pos.y < 0 || pos.y >= size.height) { + return; + } + cursor = pos; + [self addstr: str]; } @end From 9acfdea8b50f3e7cf1e4732177e76b93411fc1a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 01:52:45 +0900 Subject: [PATCH 0613/3664] [qfcc] Improve line number binding for function calls Multi-line calls (especially messages) got rather confusing to read as the lines jumped back and forth. Now the binding is better but the dags code is reordering the parameters sometimes. --- tools/qfcc/include/expr.h | 8 ++++++++ tools/qfcc/source/expr.c | 33 ++++++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index ac2646dfe..f0f118e8d 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -264,6 +264,14 @@ expr_t *new_expr (void); */ expr_t *copy_expr (expr_t *e); +/** Copy source expression's file and line to the destination expression + + \param dst The expression to receive the file and line + \param src The expression from which the file and line will be taken + \return \a dst +*/ +expr_t *expr_file_line (expr_t *dst, const expr_t *src); + /** Create a new label name. The label name is guaranteed to to the compilation. It is made up of the diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c1c78ff86..67206c663 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -432,6 +432,14 @@ copy_expr (expr_t *e) internal_error (e, "invalid expression"); } +expr_t * +expr_file_line (expr_t *dst, const expr_t *src) +{ + dst->file = src->file; + dst->line = src->line; + return dst; +} + const char * new_label_name (void) { @@ -1654,6 +1662,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) type_t *arg_types[MAX_PARMS]; expr_t *arg_exprs[MAX_PARMS][2]; int arg_expr_count = 0; + expr_t *assign; expr_t *call; expr_t *err = 0; @@ -1741,29 +1750,33 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (err) return err; - call = new_block_expr (); + call = expr_file_line (new_block_expr (), fexpr); call->e.block.is_call = 1; for (e = params, i = 0; e; e = e->next, i++) { if (has_function_call (e)) { - *a = new_temp_def_expr (arg_types[i]); - arg_exprs[arg_expr_count][0] = cast_expr (arg_types[i], - convert_vector (e)); + expr_t *cast = cast_expr (arg_types[i], convert_vector (e)); + expr_t *tmp = new_temp_def_expr (arg_types[i]); + *a = expr_file_line (tmp, e); + arg_exprs[arg_expr_count][0] = expr_file_line (cast, e); arg_exprs[arg_expr_count][1] = *a; arg_expr_count++; } else { - *a = cast_expr (arg_types[i], convert_vector (e)); + *a = expr_file_line (cast_expr (arg_types[i], convert_vector (e)), + e); } a = &(*a)->next; } for (i = 0; i < arg_expr_count - 1; i++) { - append_expr (call, assign_expr (arg_exprs[i][1], arg_exprs[i][0])); + assign = assign_expr (arg_exprs[i][1], arg_exprs[i][0]); + append_expr (call, expr_file_line (assign, arg_exprs[i][0])); } if (arg_expr_count) { e = assign_expr (arg_exprs[arg_expr_count - 1][1], arg_exprs[arg_expr_count - 1][0]); + e = expr_file_line (e, arg_exprs[arg_expr_count - 1][0]); append_expr (call, e); } - e = new_binary_expr ('c', fexpr, args); + e = expr_file_line (new_binary_expr ('c', fexpr, args), fexpr); e->e.expr.type = ftype->t.func.type; append_expr (call, e); if (ftype->t.func.type != &type_void) { @@ -2637,14 +2650,16 @@ message_expr (expr_t *receiver, keywordarg_t *message) for (m = message; m; m = m->next) { *a = m->expr; - while ((*a)) + while ((*a)) { + expr_file_line (selector, *a); a = &(*a)->next; + } } *a = selector; a = &(*a)->next; *a = receiver; - send_msg = send_message (super); + send_msg = expr_file_line (send_message (super), receiver); if (method) { expr_t *err; if ((err = method_check_params (method, args))) From 5535a6a5093fdb6fd1b4f944e7946552fb8f5fc2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 10:49:49 +0900 Subject: [PATCH 0614/3664] [qfcc] Fix missing words in a comment --- tools/qfcc/include/expr.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index f0f118e8d..99fa466b9 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -274,9 +274,9 @@ expr_t *expr_file_line (expr_t *dst, const expr_t *src); /** Create a new label name. - The label name is guaranteed to to the compilation. It is made up of the - name of the current function plus an incrementing number. The number is - not reset between functions. + The label name is guaranteed to be unique to the compilation. It is made + up of the name of the current function plus an incrementing number. The + number is not reset between functions. \return The string representing the label name. */ From 826f066e009fbc52763d336807e92f05c7e9303e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 10:50:15 +0900 Subject: [PATCH 0615/3664] [qfcc] Be more consistent with string saving Not that it really makes any difference for labels since they're guaranteed unique, but it does remove the question of "why nva instead of save_string?". Looking at history, save_string came after I changed it from strdup (va()) to nva(), and then either didn't think to look for nva or thought it wasn't worth changing. --- tools/qfcc/source/expr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 67206c663..416442419 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -446,10 +446,9 @@ new_label_name (void) static int label = 0; int lnum = ++label; const char *fname = current_func->sym->name; - char *lname; + const char *lname; - lname = nva ("$%s_%d", fname, lnum); - SYS_CHECKMEM (lname); + lname = save_string (va ("$%s_%d", fname, lnum)); return lname; } From 3061f7e30ec02b17f503f4969d78827171b11631 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 11:04:49 +0900 Subject: [PATCH 0616/3664] [qfcc] Update sendv test for corrected implementation --- tools/qfcc/test/sendv.r | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/test/sendv.r b/tools/qfcc/test/sendv.r index 979a72c43..aa2cb6665 100644 --- a/tools/qfcc/test/sendv.r +++ b/tools/qfcc/test/sendv.r @@ -8,12 +8,13 @@ int obj_increment_retaincount (id object) = #0; void send (id obj, string cmd, string str) { - @static @param params[1]; - @va_list va_list = {1, params}; - SEL sel; + @static @param params[3]; + @va_list va_list = {3, params}; + SEL sel = sel_get_uid (cmd); - params[0].string_val = str; - sel = sel_get_uid (cmd); + params[0].pointer_val = obj; + params[1].pointer_val = sel; + params[2].string_val = str; obj_msg_sendv (obj, sel, va_list); } From d5560434c022a8aa064c4bbeec6f49e3248bc378 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 11:06:09 +0900 Subject: [PATCH 0617/3664] [qfcc] Rename label to bool_label for clarity And also so I can use `label' for source labels. --- tools/qfcc/source/qc-parse.y | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index ba266c512..9752a4c48 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -184,7 +184,7 @@ int yylex (void); %type opt_init opt_expr cexpr expr element_list element %type optional_state_expr texpr vector_expr %type statement statements compound_statement -%type else label break_label continue_label +%type else bool_label break_label continue_label %type unary_expr ident_expr cast_expr opt_arg_list arg_list %type init_var_decl_list init_var_decl %type switch_block @@ -1358,7 +1358,7 @@ else } ; -label +bool_label : /* empty */ { $$ = new_label_expr (); @@ -1489,8 +1489,8 @@ expr | expr '=' expr { $$ = assign_expr ($1, $3); } | expr ASX expr { $$ = asx_expr ($2, $1, $3); } | expr '?' expr ':' expr { $$ = conditional_expr ($1, $3, $5); } - | expr AND label expr { $$ = bool_expr (AND, $3, $1, $4); } - | expr OR label expr { $$ = bool_expr (OR, $3, $1, $4); } + | expr AND bool_label expr { $$ = bool_expr (AND, $3, $1, $4); } + | expr OR bool_label expr { $$ = bool_expr (OR, $3, $1, $4); } | expr EQ expr { $$ = binary_expr (EQ, $1, $3); } | expr NE expr { $$ = binary_expr (NE, $1, $3); } | expr LE expr { $$ = binary_expr (LE, $1, $3); } From 1cd5ea57324e7f4e2640070393a86c2b7c22f275 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 11:31:54 +0900 Subject: [PATCH 0618/3664] [qfcc] Add support for named labels in statements Yeah, I've finally decided to implement goto. Limited to function scope of course. --- tools/qfcc/include/expr.h | 13 +++++++++++++ tools/qfcc/include/function.h | 1 + tools/qfcc/source/expr.c | 21 +++++++++++++++++++++ tools/qfcc/source/function.c | 1 + tools/qfcc/source/qc-parse.y | 10 +++++++++- 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 99fa466b9..6556a8d06 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -290,6 +290,19 @@ const char *new_label_name (void); */ expr_t *new_label_expr (void); +/** Create a named label expression node. + + The label name is set using new_label_name(), but the symbol is used to add + the label to the function's label scope symbol table. If the label already + exists in the function's label scope, then the existing label is returned, + allowing for forward label declarations. + + \param label The name symbol to use for adding the label to the function + label scope. + \return The new label expression (::ex_label_t) node. +*/ +expr_t *named_label_expr (struct symbol_s *label); + /** Create a new label reference expression node. Used for taking the address of a label (eg. jump tables). diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 39cde918c..951b40597 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -79,6 +79,7 @@ typedef struct function_s { scope symbol table's defspace. */ struct symtab_s *symtab; + struct symtab_s *label_scope; struct reloc_s *refs; ///< relocation targets for this function struct expr_s *var_init; const char *name; ///< nice name for __PRETTY_FUNCTION__ diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 416442419..d080d2332 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -495,6 +495,27 @@ new_label_expr (void) return l; } +expr_t * +named_label_expr (symbol_t *label) +{ + symbol_t *sym; + + if (!current_func) { + // XXX this might be only an error + internal_error (0, "label defined outside of function scope"); + } + + sym = symtab_lookup (current_func->label_scope, label->name); + + if (sym) { + return sym->s.expr; + } + label->sy_type = sy_expr; + label->s.expr = new_label_expr (); + symtab_addsymbol (current_func->label_scope, label); + return label->s.expr; +} + expr_t * new_label_ref (ex_label_t *label) { diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 7f53cd11d..c9e5474a5 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -493,6 +493,7 @@ build_scope (symbol_t *fsym, symtab_t *parent) symtab = new_symtab (parent, stab_local); fsym->s.func->symtab = symtab; + fsym->s.func->label_scope = new_symtab (0, stab_local); symtab->space = defspace_new (ds_virtual); current_symtab = symtab; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 9752a4c48..3e5079313 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -188,7 +188,7 @@ int yylex (void); %type unary_expr ident_expr cast_expr opt_arg_list arg_list %type init_var_decl_list init_var_decl %type switch_block -%type identifier +%type identifier label %type overloaded_identifier @@ -1292,6 +1292,10 @@ statement else error (0, "continue outside of loop"); } + | label + { + $$ = named_label_expr ($1); + } | CASE expr ':' { $$ = case_label_expr (switch_block, $2); @@ -1358,6 +1362,10 @@ else } ; +label + : NAME ':' + ; + bool_label : /* empty */ { From 4a8854d9ed63006155076646397222ebec99daa0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 12:51:34 +0900 Subject: [PATCH 0619/3664] [qfcc] Add expression tracking to operands Not much uses it yet, but it will make for better diagnostics. --- tools/qfcc/include/statements.h | 13 +++--- tools/qfcc/source/dags.c | 8 ++-- tools/qfcc/source/flow.c | 2 +- tools/qfcc/source/statements.c | 75 +++++++++++++++++---------------- 4 files changed, 52 insertions(+), 46 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index ce230d9ec..d1ccff441 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -57,6 +57,7 @@ typedef struct operand_s { op_type_e op_type; struct type_s *type; ///< possibly override def's type int size; ///< for structures + struct expr_s *expr; ///< expression generating this operand union { struct def_s *def; struct ex_value_s *value; @@ -115,14 +116,16 @@ struct dstring_s; const char *optype_str (op_type_e type) __attribute__((const)); -operand_t *def_operand (struct def_s *def, struct type_s *type); -operand_t *return_operand (struct type_s *type); -operand_t *value_operand (struct ex_value_s *value); +operand_t *def_operand (struct def_s *def, struct type_s *type, + struct expr_s *expr); +operand_t *return_operand (struct type_s *type, struct expr_s *expr); +operand_t *value_operand (struct ex_value_s *value, struct expr_s *expr); int tempop_overlap (tempop_t *t1, tempop_t *t2) __attribute__((pure)); -operand_t *temp_operand (struct type_s *type); +operand_t *temp_operand (struct type_s *type, struct expr_s *expr); int tempop_visit_all (tempop_t *tempop, int overlap, int (*visit) (tempop_t *, void *), void *data); -operand_t *alias_operand (struct type_s *type, operand_t *op); +operand_t *alias_operand (struct type_s *type, operand_t *op, + struct expr_s *expr); void free_operand (operand_t *op); sblock_t *new_sblock (void); diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 86acc210a..a97b3e68c 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -821,7 +821,7 @@ static operand_t * fix_op_type (operand_t *op, type_t *type) { if (op && op->op_type != op_label && op->type != type) - op = alias_operand (type, op); + op = alias_operand (type, op, op->expr); return op; } @@ -882,7 +882,8 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) offset = dstDef->offset; dstDef = dstDef->alias; } - operands[2] = value_operand (new_pointer_val (offset, type, dstDef)); + operands[2] = value_operand (new_pointer_val (offset, type, dstDef), + operands[1]->expr); st = build_statement ("", operands, var->expr); sblock_add_statement (block, st); } @@ -937,7 +938,8 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[1] = make_operand (dag, block, dagnode, 1); type = get_type (dagnode->label->expr); if (!(var_iter = set_first (dagnode->identifiers))) { - operands[2] = temp_operand (get_type (dagnode->label->expr)); + operands[2] = temp_operand (get_type (dagnode->label->expr), + dagnode->label->expr); } else { daglabel_t *var = dag->labels[var_iter->element]; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 4ee42e214..ff0d1de96 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1102,7 +1102,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, def_t *alias; ex_pointer_t *ptr = &s->opc->o.value->v.pointer; alias = alias_def (ptr->def, ptr->type, ptr->val); - op = def_operand (alias, ptr->type); + op = def_operand (alias, ptr->type, s->opc->expr); flow_add_op_var (def, op, 0); if (operands) operands[0] = op; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 0ba4d1e21..e156efd1a 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -273,11 +273,12 @@ new_statement (st_type_t type, const char *opcode, expr_t *expr) } static operand_t * -new_operand (op_type_e op) +new_operand (op_type_e op, expr_t *expr) { operand_t *operand; ALLOC (256, operand_t, operands, operand); operand->op_type = op; + operand->expr = expr; return operand; } @@ -311,13 +312,13 @@ free_sblock (sblock_t *sblock) } operand_t * -def_operand (def_t *def, type_t *type) +def_operand (def_t *def, type_t *type, expr_t *expr) { operand_t *op; if (!type) type = def->type; - op = new_operand (op_def); + op = new_operand (op_def, expr); op->type = type; op->size = type_size (type); op->o.def = def; @@ -325,28 +326,28 @@ def_operand (def_t *def, type_t *type) } operand_t * -return_operand (type_t *type) +return_operand (type_t *type, expr_t *expr) { symbol_t *return_symbol; return_symbol = make_symbol (".return", &type_param, pr.symtab->space, sc_extern); - return def_operand (return_symbol->s.def, type); + return def_operand (return_symbol->s.def, type, expr); } operand_t * -value_operand (ex_value_t *value) +value_operand (ex_value_t *value, expr_t *expr) { operand_t *op; - op = new_operand (op_value); + op = new_operand (op_value, expr); op->type = value->type; op->o.value = value; return op; } operand_t * -temp_operand (type_t *type) +temp_operand (type_t *type, expr_t *expr) { - operand_t *op = new_operand (op_temp); + operand_t *op = new_operand (op_temp, expr); op->o.tempop.type = type; op->type = type; @@ -412,7 +413,7 @@ tempop_visit_all (tempop_t *tempop, int overlap, } operand_t * -alias_operand (type_t *type, operand_t *op) +alias_operand (type_t *type, operand_t *op, expr_t *expr) { operand_t *aop; @@ -420,7 +421,7 @@ alias_operand (type_t *type, operand_t *op) internal_error (0, "\naliasing operand with type of different size" " (%d, %d)", type_size (type), type_size (op->type)); } - aop = new_operand (op_alias); + aop = new_operand (op_alias, expr); aop->o.alias = op; aop->type = type; aop->size = type_size (type); @@ -428,10 +429,10 @@ alias_operand (type_t *type, operand_t *op) } static operand_t * -short_operand (short short_val) +short_operand (short short_val, expr_t *expr) { ex_value_t *val = new_short_val (short_val); - return value_operand (val); + return value_operand (val, expr); } static const char * @@ -593,7 +594,7 @@ statement_branch (sblock_t *sblock, expr_t *e) if (e->type == ex_uexpr && e->e.expr.op == 'g') { s = new_statement (st_flow, "", e); - s->opa = new_operand (op_label); + s->opa = new_operand (op_label, e); s->opa->o.label = &e->e.expr.e1->e.label; } else { if (e->e.expr.op == 'g') { @@ -604,7 +605,7 @@ statement_branch (sblock_t *sblock, expr_t *e) opcode = convert_op (e->e.expr.op); s = new_statement (st_flow, opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - s->opb = new_operand (op_label); + s->opb = new_operand (op_label, e); s->opb->o.label = &e->e.expr.e2->e.label; } } @@ -783,7 +784,7 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op) statement_t *s; s = new_statement (st_expr, "&", e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - s->opc = temp_operand (e->e.expr.type); + s->opc = temp_operand (e->e.expr.type, e); sblock_add_statement (sblock, s); *(op) = s->opc; return sblock; @@ -795,7 +796,7 @@ lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) statement_t *s = new_statement (st_expr, "&", e); s->opa = pointer; s->opb = offset; - s->opc = temp_operand (&type_pointer); + s->opc = temp_operand (&type_pointer, e); return s; } @@ -804,7 +805,7 @@ address_statement (operand_t *value, expr_t *e) { statement_t *s = new_statement (st_expr, "&", e); s->opa = value; - s->opc = temp_operand (&type_pointer); + s->opc = temp_operand (&type_pointer, e); return s; } @@ -819,7 +820,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) && e->e.expr.e1->type == ex_symbol) { if (e->e.expr.e1->e.symbol->sy_type != sy_var) internal_error (e, "address of non-var"); - *op = def_operand (e->e.expr.e1->e.symbol->s.def, type); + *op = def_operand (e->e.expr.e1->e.symbol->s.def, type, e); } else if (e->type == ex_expr && e->e.expr.op == '&') { statement_t *s; operand_t *ptr = 0; @@ -827,7 +828,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) sblock = statement_subexpr (sblock, e->e.expr.e1, &ptr); sblock = statement_subexpr (sblock, e->e.expr.e2, &offs); if (!*op) - *op = temp_operand (type); + *op = temp_operand (type, e); if (low_level_type (type) == ev_void) { operand_t *src_addr; operand_t *dst_addr; @@ -843,7 +844,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) s = new_statement (st_move, "", deref); s->opa = src_addr; - s->opb = short_operand (type_size (type)); + s->opb = short_operand (type_size (type), e); s->opc = dst_addr; sblock_add_statement (sblock, s); } else { @@ -856,17 +857,17 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) } else if (e->type == ex_value && e->e.value->lltype == ev_pointer) { ex_pointer_t *ptr = &e->e.value->v.pointer; *op = def_operand (alias_def (ptr->def, ptr->type, ptr->val), - ptr->type); + ptr->type, e); } else { statement_t *s; operand_t *ptr = 0; sblock = statement_subexpr (sblock, e, &ptr); if (!*op) - *op = temp_operand (type); + *op = temp_operand (type, e); s = new_statement (st_expr, ".", deref); s->opa = ptr; - s->opb = short_operand (0); + s->opb = short_operand (0, e); s->opc = *op; sblock_add_statement (sblock, s); } @@ -919,7 +920,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) } } if (!top) { - top = temp_operand (type); + top = temp_operand (type, e); top->o.tempop.alias = aop; top->o.tempop.offset = offset; top->next = aop->o.tempop.alias_ops; @@ -930,9 +931,9 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) def = aop->o.def; while (def->alias) def = def->alias; - *op = def_operand (alias_def (def, type, offset), 0); + *op = def_operand (alias_def (def, type, offset), 0, e); } else if (aop->op_type == op_value) { - *op = value_operand (aop->o.value); + *op = value_operand (aop->o.value, e); (*op)->type = type; } else { internal_error (e, "invalid alias target: %s: %s", @@ -970,7 +971,7 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); if (!*op) - *op = temp_operand (e->e.expr.type); + *op = temp_operand (e->e.expr.type, e); s->opc = *op; sblock_add_statement (sblock, s); break; @@ -989,7 +990,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) if (is_scalar (src_type) && is_scalar (type)) { operand_t *src = 0; sblock = statement_subexpr (sblock, e->e.expr.e1, &src); - *op = temp_operand (e->e.expr.type); + *op = temp_operand (e->e.expr.type, e); s = new_statement (st_expr, "", e); s->opa = src; s->opc = *op; @@ -1046,7 +1047,7 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) s = new_statement (st_expr, opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); if (!*op) - *op = temp_operand (e->e.expr.type); + *op = temp_operand (e->e.expr.type, e); s->opc = *op; sblock_add_statement (sblock, s); } @@ -1059,11 +1060,11 @@ expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op) symbol_t *sym = e->e.symbol; if (sym->sy_type == sy_var) { - *op = def_operand (sym->s.def, sym->type); + *op = def_operand (sym->s.def, sym->type, e); } else if (sym->sy_type == sy_const) { - *op = value_operand (sym->s.value); + *op = value_operand (sym->s.value, e); } else if (sym->sy_type == sy_func) { - *op = def_operand (sym->s.func->def, 0); + *op = def_operand (sym->s.func->def, 0, e); } else { internal_error (e, "unexpected symbol type: %s for %s", symtype_str (sym->sy_type), sym->name); @@ -1075,7 +1076,7 @@ static sblock_t * expr_temp (sblock_t *sblock, expr_t *e, operand_t **op) { if (!e->e.temp.op) - e->e.temp.op = temp_operand (e->e.temp.type); + e->e.temp.op = temp_operand (e->e.temp.type, e); *op = e->e.temp.op; return sblock; } @@ -1151,7 +1152,7 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) static sblock_t * expr_value (sblock_t *sblock, expr_t *e, operand_t **op) { - *op = value_operand (e->e.value); + *op = value_operand (e->e.value, e); return sblock; } @@ -1414,7 +1415,7 @@ statement_uexpr (sblock_t *sblock, expr_t *e) } s = new_statement (st_func, opcode, e); if (e->e.expr.e1) { - s->opa = return_operand (get_type (e->e.expr.e1)); + s->opa = return_operand (get_type (e->e.expr.e1), e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); } sblock_add_statement (sblock, s); @@ -1718,7 +1719,7 @@ check_final_block (sblock_t *sblock) s = new_statement (st_func, "", 0); if (options.traditional || options.code.progsversion == PROG_ID_VERSION) { s->opcode = save_string (""); - s->opa = return_operand (&type_void); + s->opa = return_operand (&type_void, 0); } sblock_add_statement (sblock, s); } From 813319efc241d94154df1032067c90828fa27f73 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 12:53:40 +0900 Subject: [PATCH 0620/3664] [qfcc] Implement goto It's just too useful when used correctly. --- tools/qfcc/source/qc-lex.l | 1 + tools/qfcc/source/qc-parse.y | 9 +++++++-- tools/qfcc/source/statements.c | 16 +++++++++++----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 353191593..9d5c5a1b9 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -353,6 +353,7 @@ static keyword_t obj_keywords[] = { // make the language features available to traditional code. static keyword_t at_keywords[] = { {"for", FOR }, + {"goto", GOTO }, {"break", BREAK }, {"continue", CONTINUE}, {"switch", SWITCH }, diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 3e5079313..27423d4ef 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -145,8 +145,8 @@ int yylex (void); %token VALUE STRING %token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS -%token NIL IFBE IFB IFAE IFA SWITCH CASE DEFAULT ENUM TYPEDEF -%token ARGS EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT +%token NIL IFBE IFB IFAE IFA GOTO SWITCH CASE DEFAULT ENUM +%token ARGS TYPEDEF EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT %token STRUCT %token TYPE %token OBJECT TYPE_NAME @@ -1310,6 +1310,11 @@ statement switch_block = $5; break_label = $2; } + | GOTO NAME + { + expr_t *label = named_label_expr ($2); + $$ = goto_expr (label); + } | IF not '(' texpr ')' statement %prec IFX { $$ = build_if_statement ($2, $4, $6, 0, 0); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e156efd1a..42a5494e8 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1551,7 +1551,7 @@ remove_label_from_dest (ex_label_t *label) sblock_t *sblock; ex_label_t **l; - if (!label) + if (!label || !label->dest) return; debug (0, "dropping deceased label %s", label->name); @@ -1588,14 +1588,20 @@ thread_jumps (sblock_t *blocks) if (!sblock->statements) continue; s = (statement_t *) sblock->tail; - if (statement_is_goto (s)) + if (statement_is_goto (s)) { label = &s->opa->o.label; - else if (statement_is_cond (s)) + if (!(*label)->dest && s->opa->expr) { + error (s->opa->expr, "undefined label `%s'", (*label)->name); + s->opa->expr = 0; + } + } else if (statement_is_cond (s)) { label = &s->opb->o.label; - else + } else { continue; + } for (l = *label; - l->dest->statements && statement_is_goto (l->dest->statements); + l->dest && l->dest->statements + && statement_is_goto (l->dest->statements); l = l->dest->statements->opa->o.label) { } if (l != *label) { From 393e540ffa3af2613668b0de13af2375ae5fcc1e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 13:31:12 +0900 Subject: [PATCH 0621/3664] [qfcc] Print the source name of an undefined label Undefined labels generated by the compiler indicate severe trouble. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/expr.c | 6 +++++- tools/qfcc/source/statements.c | 7 ++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 6556a8d06..fa88dc80d 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -75,6 +75,7 @@ typedef struct ex_label_s { struct reloc_s *refs; ///< relocations associated with this label struct sblock_s *dest; ///< the location of this label if known const char *name; ///< the name of this label + struct symbol_s *symbol; ///< symbol used to define this label (maybe 0) int used; ///< label is used as a target struct daglabel_s *daglabel; } ex_label_t; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index d080d2332..e9967dbc7 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -499,6 +499,7 @@ expr_t * named_label_expr (symbol_t *label) { symbol_t *sym; + expr_t *l; if (!current_func) { // XXX this might be only an error @@ -510,8 +511,11 @@ named_label_expr (symbol_t *label) if (sym) { return sym->s.expr; } + l = new_label_expr (); + l->e.label.name = save_string (va ("%s_%s", l->e.label.name, label->name)); + l->e.label.symbol = label; label->sy_type = sy_expr; - label->s.expr = new_label_expr (); + label->s.expr = l; symtab_addsymbol (current_func->label_scope, label); return label->s.expr; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 42a5494e8..f82fa552e 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1590,9 +1590,10 @@ thread_jumps (sblock_t *blocks) s = (statement_t *) sblock->tail; if (statement_is_goto (s)) { label = &s->opa->o.label; - if (!(*label)->dest && s->opa->expr) { - error (s->opa->expr, "undefined label `%s'", (*label)->name); - s->opa->expr = 0; + if (!(*label)->dest && (*label)->symbol) { + error (s->opa->expr, "undefined label `%s'", + (*label)->symbol->name); + (*label)->symbol = 0; } } else if (statement_is_cond (s)) { label = &s->opb->o.label; From f10f9e157df69587deabcf0e09f550bdd76c31a7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 13:33:06 +0900 Subject: [PATCH 0622/3664] [qfcc] Warn about unused labels --- tools/qfcc/source/statements.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index f82fa552e..517fcc7b3 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1344,7 +1344,11 @@ statement_label (sblock_t *sblock, expr_t *e) e->e.label.next = sblock->labels; sblock->labels = &e->e.label; } else { - debug (e, "dropping unused label %s", e->e.label.name); + if (e->e.label.symbol) { + warning (e, "unused label %s", e->e.label.symbol->name); + } else { + debug (e, "dropping unused label %s", e->e.label.name); + } } return sblock; } From d1e83b9d4887eba79236b5531dc8e0a42063d702 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 15:46:57 +0900 Subject: [PATCH 0623/3664] [qfcc] Create a compound initializer expression type This fixes the problem of using the return value of a function as an element in a compound initializer. The cause of the problem is that compound initializers were represented by block expressions, but function calls are contained within block expressions, so def initialization saw the block expression and thought it was a nested compound initializer. Technically, it was a bug in the nested element parsing code in that it wasn't checking the result value of the block expression, but using a whole new expression type makes things much cleaner and the work done paves the way for labeled initializers and compound assignments. --- tools/qfcc/include/expr.h | 17 ++++++++++ tools/qfcc/source/def.c | 36 +++++++++++---------- tools/qfcc/source/expr.c | 57 +++++++++++++++++++++++++++++++-- tools/qfcc/source/expr_assign.c | 1 + tools/qfcc/source/qc-parse.y | 42 +++++++++++------------- 5 files changed, 109 insertions(+), 44 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index fa88dc80d..230ecd241 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -55,6 +55,7 @@ typedef enum { ex_nil, ///< umm, nil, null. nuff said (0 of any type) ex_value, ///< constant value (::ex_value_t) + ex_compound, ///< compound initializer } expr_type; /** Binary and unary expressions. @@ -84,6 +85,17 @@ typedef struct { ex_label_t *label; } ex_labelref_t; +typedef struct ex_initele_s { + struct ex_initele_s *next; ///< next in chain + struct symbol_s *symbol; ///< for labeled initializers + struct expr_s *expr; ///< initializer expression +} ex_initele_t; + +typedef struct ex_cmpinit_s { + ex_initele_t *head; + ex_initele_t **tail; +} ex_cmpinit_t; + typedef struct { struct expr_s *head; ///< the first expression in the block struct expr_s **tail; ///< last expression in the block, for appending @@ -210,6 +222,7 @@ typedef struct expr_s { ex_temp_t temp; ///< temporary variable expression ex_vector_t vector; ///< vector expression list ex_value_t *value; ///< constant value + ex_cmpinit_t compound; ///< compound initializer } e; } expr_t; @@ -348,6 +361,10 @@ expr_t *new_block_expr (void); */ expr_t *build_block_expr (expr_t *expr_list); +ex_initele_t *new_initele (expr_t *expr, struct symbol_s *symbol); +expr_t *new_compound_init (void); +expr_t *append_element (expr_t *compound, ex_initele_t *element); + /** Create a new binary expression node node. If either \a e1 or \a e2 are error expressions, then that expression will diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 865ef4066..d600fb0ae 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -86,7 +86,7 @@ new_element (void) } static element_t * -append_element (element_chain_t *element_chain, element_t *element) +append_init_element (element_chain_t *element_chain, element_t *element) { element->next = 0; *element_chain->tail = element; @@ -371,7 +371,7 @@ static void build_element_chain (element_chain_t *element_chain, type_t *type, expr_t *eles, int base_offset) { - expr_t *e = eles->e.block.head; + ex_initele_t *ele = eles->e.compound.head; if (is_array (type)) { type_t *array_type = type->t.array.type; @@ -380,17 +380,18 @@ build_element_chain (element_chain_t *element_chain, type_t *type, for (i = 0; i < array_size; i++) { int offset = base_offset + i * type_size (array_type); - if (e && e->type == ex_block) { - build_element_chain (element_chain, array_type, e, offset); + if (ele->expr && ele->expr->type == ex_compound) { + build_element_chain (element_chain, array_type, + ele->expr, offset); } else { element_t *element = new_element (); element->type = array_type; element->offset = offset; - element->expr = e; // null will be treated as nil - append_element (element_chain, element); + element->expr = ele->expr; // null will be treated as nil + append_init_element (element_chain, element); } - if (e) { - e = e->next; + if (ele) { + ele = ele->next; } } } else if (is_struct (type) || is_vector (type) || is_quaternion (type)) { @@ -403,23 +404,24 @@ build_element_chain (element_chain_t *element_chain, type_t *type, || field->visibility == vis_anonymous) { continue; } - if (e && e->type == ex_block) { - build_element_chain (element_chain, field->type, e, offset); + if (ele->expr && ele->expr->type == ex_compound) { + build_element_chain (element_chain, field->type, + ele->expr, offset); } else { element_t *element = new_element (); element->type = field->type; element->offset = offset; - element->expr = e; // null will be treated as nil - append_element (element_chain, element); + element->expr = ele->expr; // null will be treated as nil + append_init_element (element_chain, element); } - if (e) { - e = e->next; + if (ele) { + ele = ele->next; } } } else { error (eles, "invalid initializer"); } - if (e && e->next && options.warnings.initializer) { + if (ele && ele->next && options.warnings.initializer) { warning (eles, "excessive elements in initializer"); } } @@ -652,7 +654,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, } if (!sym->s.def) { if (is_array (sym->type) && !type_size (sym->type) - && init->type == ex_block && !init->e.block.result) { + && init->type == ex_compound) { sym->type = array_type (sym->type->t.array.type, num_elements (init)); } @@ -676,7 +678,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, return; if ((is_array (sym->type) || is_struct (sym->type) || sym->type == &type_vector || sym->type == &type_quaternion) - && ((init->type == ex_block && !init->e.block.result) + && ((init->type == ex_compound) || init->type == ex_nil)) { init_elements (sym->s.def, init); sym->s.def->initialized = 1; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index e9967dbc7..b4173f45d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -217,6 +217,7 @@ get_type (expr_t *e) return &type_void; case ex_label: case ex_error: + case ex_compound: return 0; // something went very wrong case ex_bool: if (options.code.progsversion == PROG_ID_VERSION) @@ -420,14 +421,21 @@ copy_expr (expr_t *e) n = new_expr (); n->e.vector.type = e->e.vector.type; n->e.vector.list = copy_expr (e->e.vector.list); - n = n->e.vector.list; t = e->e.vector.list; + e = n->e.vector.list; while (t->next) { - n->next = copy_expr (t->next); - n = n->next; + e->next = copy_expr (t->next); + e = e->next; t = t->next; } return n; + case ex_compound: + n = new_expr (); + *n = *e; + for (ex_initele_t *i = e->e.compound.head; i; i = i->next) { + append_element (n, new_initele (i->expr, i->symbol)); + } + return n; } internal_error (e, "invalid expression"); } @@ -543,6 +551,46 @@ new_block_expr (void) return b; } +ex_initele_t * +new_initele (expr_t *expr, symbol_t *symbol) +{ + ex_initele_t *i = calloc (1, sizeof (*i)); + i->expr = expr; + i->symbol = symbol; + return i; +} + +expr_t * +new_compound_init (void) +{ + expr_t *c = new_expr (); + c->type = ex_compound; + c->e.compound.head = 0; + c->e.compound.tail = &c->e.compound.head; + return c; +} + +expr_t * +append_element (expr_t *compound, ex_initele_t *element) +{ + if (compound->type != ex_compound) { + internal_error (compound, "not a compound expression"); + } + + if (!element || (element->expr && element->expr->type == ex_error)) { + return compound; + } + + if (element->next) { + internal_error (compound, "append_element: element loop detected"); + } + + *compound->e.compound.tail = element; + compound->e.compound.tail = &element->next; + + return compound; +} + expr_t * new_binary_expr (int op, expr_t *e1, expr_t *e2) { @@ -1499,6 +1547,7 @@ unary_expr (int op, expr_t *e) case ex_label: case ex_labelref: case ex_state: + case ex_compound: internal_error (e, 0); case ex_uexpr: if (e->e.expr.op == '-') @@ -1565,6 +1614,7 @@ unary_expr (int op, expr_t *e) case ex_label: case ex_labelref: case ex_state: + case ex_compound: internal_error (e, 0); case ex_bool: return new_bool_expr (e->e.bool.false_list, @@ -1630,6 +1680,7 @@ unary_expr (int op, expr_t *e) case ex_label: case ex_labelref: case ex_state: + case ex_compound: internal_error (e, 0); case ex_uexpr: if (e->e.expr.op == '~') diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index f0d7daf4b..466ffcf95 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -123,6 +123,7 @@ check_valid_lvalue (expr_t *expr) return check_valid_lvalue (expr->e.expr.e1); } break; + case ex_compound: case ex_state: case ex_bool: case ex_label: diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 27423d4ef..83ac9ca8a 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -98,6 +98,7 @@ int yylex (void); void *pointer; // for ensuring pointer values are null struct type_s *type; struct expr_s *expr; + struct ex_initele_s *element; struct function_s *function; struct switch_block_s *switch_block; struct param_s *param; @@ -181,7 +182,9 @@ int yylex (void); %type methoddef %type opt_initializer var_initializer local_def -%type opt_init opt_expr cexpr expr element_list element +%type opt_init opt_expr cexpr expr +%type compound_init element_list +%type element %type optional_state_expr texpr vector_expr %type statement statements compound_statement %type else bool_label break_label continue_label @@ -1148,17 +1151,20 @@ opt_initializer var_initializer : '=' expr { $$ = $2; } - | '=' '{' { $$ = $-1; } - element_list optional_comma '}' { $$ = $4; } - | '=' '{' '}' + | '=' compound_init { - if (is_scalar ($-1.type)) { + if (!$2 && is_scalar ($-1.type)) { error (0, "empty scalar initializer"); } - $$ = new_nil_expr (); + $$ = $2 ? $2 : new_nil_expr (); } ; +compound_init + : '{' element_list optional_comma '}' { $$ = $2; } + | '{' '}' { $$ = 0; } + ; + optional_state_expr : /* emtpy */ { $$ = 0; } | vector_expr { $$ = build_state_expr ($1); } @@ -1167,30 +1173,18 @@ optional_state_expr element_list : element { - $$ = new_block_expr (); - append_expr ($$, $1); + $$ = new_compound_init (); + append_element ($$, $1); } - | element_list ',' {$$ = $0; } element + | element_list ',' element { - append_expr ($$, $4); + append_element ($$, $3); } ; element - : '{' { $$ = $0; } - element_list optional_comma '}' { $$ = $3; } - | '{' '}' - { - // FIXME doesn't check the right type (does prove the inherited - // attributes have been passed down correctly though). The problem - // is that the type of the sub elements needs to be extracted if - // possible - if (is_scalar ($0.type)) { - error (0, "empty scalar initializer"); - } - $$ = new_nil_expr (); - } - | expr { $$ = $1; } + : compound_init { $$ = new_initele ($1, 0); } + | expr { $$ = new_initele ($1, 0); } ; optional_comma From afd31ed29243e5840f5889c6c746e1cf37a1b153 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 16:07:58 +0900 Subject: [PATCH 0624/3664] [qfcc] Rename cexpr to comma_expr It took me too long to figure out what cexpr was for. --- tools/qfcc/source/qc-parse.y | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 83ac9ca8a..5b3216d10 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -182,7 +182,7 @@ int yylex (void); %type methoddef %type opt_initializer var_initializer local_def -%type opt_init opt_expr cexpr expr +%type opt_init opt_expr comma_expr expr %type compound_init element_list %type element %type optional_state_expr texpr vector_expr @@ -1342,7 +1342,7 @@ statement break_label = $2; continue_label = $3; } - | cexpr ';' + | comma_expr ';' { $$ = $1; } @@ -1398,7 +1398,7 @@ switch_block ; opt_init - : cexpr + : comma_expr | type set_spec_storage init_var_decl_list { $$ = $3; } | /* empty */ { @@ -1431,7 +1431,7 @@ init_var_decl ; opt_expr - : cexpr + : comma_expr | /* empty */ { $$ = 0; @@ -1521,7 +1521,7 @@ texpr : expr { $$ = convert_bool ($1, 1); } ; -cexpr +comma_expr : arg_list { if ($1->next) { From 023a920a511cb3e488608773d36b1a18b9172893 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 19:38:50 +0900 Subject: [PATCH 0625/3664] [gamecode] Replace lost parameter auto-reset rcallN messes with the progs parameter pointers and not resetting them can cause incorrect data to be copied into the called function. --- libs/gamecode/pr_exec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 47b39bc58..d673b7d1c 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -199,6 +199,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], f->parm_size[i].size); + pr->pr_params[i] = pr->pr_real_params[i]; } } } else if (f->numparms < 0) { @@ -210,6 +211,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], f->parm_size[i].size); + pr->pr_params[i] = pr->pr_real_params[i]; } } dparmsize_t parmsize = { pr->pr_param_size, pr->pr_param_alignment }; @@ -221,6 +223,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], parmsize.size); + pr->pr_params[i] = pr->pr_real_params[i]; } } } From b6439e8dc1f2db26078a9b38c4760ac427ef5f44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 19:42:38 +0900 Subject: [PATCH 0626/3664] [qfcc] Support compound init in assignment and params foo({...}) and bar = {...} --- tools/qfcc/include/expr.h | 30 ++-- tools/qfcc/source/Makefile.am | 3 +- tools/qfcc/source/def.c | 109 +-------------- tools/qfcc/source/expr.c | 63 +++------ tools/qfcc/source/expr_assign.c | 8 +- tools/qfcc/source/expr_compound.c | 209 ++++++++++++++++++++++++++++ tools/qfcc/source/qc-parse.y | 32 +++-- tools/qfcc/test/Makefile.am | 10 ++ tools/qfcc/test/compound.r | 72 ++++++++++ tools/qfcc/test/struct-init-param.r | 19 ++- 10 files changed, 381 insertions(+), 174 deletions(-) create mode 100644 tools/qfcc/source/expr_compound.c create mode 100644 tools/qfcc/test/compound.r diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 230ecd241..008313a5a 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -85,16 +85,18 @@ typedef struct { ex_label_t *label; } ex_labelref_t; -typedef struct ex_initele_s { - struct ex_initele_s *next; ///< next in chain - struct symbol_s *symbol; ///< for labeled initializers +typedef struct element_s { + struct element_s *next; ///< next in chain + int offset; + struct type_s *type; struct expr_s *expr; ///< initializer expression -} ex_initele_t; + struct symbol_s *symbol; ///< for labeled initializers +} element_t; -typedef struct ex_cmpinit_s { - ex_initele_t *head; - ex_initele_t **tail; -} ex_cmpinit_t; +typedef struct element_chain_s { + element_t *head; + element_t **tail; +} element_chain_t; typedef struct { struct expr_s *head; ///< the first expression in the block @@ -222,7 +224,7 @@ typedef struct expr_s { ex_temp_t temp; ///< temporary variable expression ex_vector_t vector; ///< vector expression list ex_value_t *value; ///< constant value - ex_cmpinit_t compound; ///< compound initializer + element_chain_t compound; ///< compound initializer } e; } expr_t; @@ -361,9 +363,15 @@ expr_t *new_block_expr (void); */ expr_t *build_block_expr (expr_t *expr_list); -ex_initele_t *new_initele (expr_t *expr, struct symbol_s *symbol); +element_t *new_element (expr_t *expr, struct symbol_s *symbol); expr_t *new_compound_init (void); -expr_t *append_element (expr_t *compound, ex_initele_t *element); +expr_t *append_element (expr_t *compound, element_t *element); +expr_t *initialized_temp_expr (struct type_s *type, expr_t *compound); +void assign_elements (expr_t *local_expr, expr_t *ptr, + element_chain_t *element_chain); +void build_element_chain (element_chain_t *element_chain, struct type_s *type, + expr_t *eles, int base_offset); +void free_element_chain (element_chain_t *element_chain); /** Create a new binary expression node node. diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index d9ceb5ba2..cfd31afbc 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -41,7 +41,8 @@ bin_SCRIPTS= qfpreqcc common_src=\ class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \ diagnostic.c dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c emit.c \ - expr.c expr_assign.c expr_binary.c expr_bool.c flow.c function.c grab.c \ + expr.c expr_assign.c expr_binary.c expr_bool.c expr_compound.c \ + flow.c function.c grab.c \ idstuff.c \ linker.c method.c \ obj_file.c \ diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index d600fb0ae..f690f2c3b 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -62,37 +62,7 @@ #include "type.h" #include "value.h" -typedef struct element_s { - struct element_s *next; - int offset; - type_t *type; - expr_t *expr; -} element_t; - -typedef struct element_chain_s { - element_t *head; - element_t **tail; -} element_chain_t; - static def_t *defs_freelist; -static element_t *elements_freelist; - -static element_t * -new_element (void) -{ - element_t *element; - ALLOC (256, element_t, elements, element); - return element; -} - -static element_t * -append_init_element (element_chain_t *element_chain, element_t *element) -{ - element->next = 0; - *element_chain->tail = element; - element_chain->tail = &element->next; - return element; -} static void set_storage_bits (def_t *def, storage_class_t storage) @@ -367,65 +337,6 @@ init_elements_nil (def_t *def) // it's a global, so already initialized to 0 } -static void -build_element_chain (element_chain_t *element_chain, type_t *type, - expr_t *eles, int base_offset) -{ - ex_initele_t *ele = eles->e.compound.head; - - if (is_array (type)) { - type_t *array_type = type->t.array.type; - int array_size = type->t.array.size; - int i; - - for (i = 0; i < array_size; i++) { - int offset = base_offset + i * type_size (array_type); - if (ele->expr && ele->expr->type == ex_compound) { - build_element_chain (element_chain, array_type, - ele->expr, offset); - } else { - element_t *element = new_element (); - element->type = array_type; - element->offset = offset; - element->expr = ele->expr; // null will be treated as nil - append_init_element (element_chain, element); - } - if (ele) { - ele = ele->next; - } - } - } else if (is_struct (type) || is_vector (type) || is_quaternion (type)) { - symtab_t *symtab = type->t.symtab; - symbol_t *field; - - for (field = symtab->symbols; field; field = field->next) { - int offset = base_offset + field->s.offset; - if (field->sy_type != sy_var - || field->visibility == vis_anonymous) { - continue; - } - if (ele->expr && ele->expr->type == ex_compound) { - build_element_chain (element_chain, field->type, - ele->expr, offset); - } else { - element_t *element = new_element (); - element->type = field->type; - element->offset = offset; - element->expr = ele->expr; // null will be treated as nil - append_init_element (element_chain, element); - } - if (ele) { - ele = ele->next; - } - } - } else { - error (eles, "invalid initializer"); - } - if (ele && ele->next && options.warnings.initializer) { - warning (eles, "excessive elements in initializer"); - } -} - static void init_elements (struct def_s *def, expr_t *eles) { @@ -444,21 +355,8 @@ init_elements (struct def_s *def, expr_t *eles) build_element_chain (&element_chain, def->type, eles, 0); if (def->local && local_expr) { - for (element = element_chain.head; element; element = element->next) { - int offset = element->offset; - type_t *type = element->type; - expr_t *ptr = new_pointer_expr (offset, type, def); - - if (element->expr) { - c = constant_expr (element->expr); - } else { - c = new_nil_expr (); - } - if (c->type == ex_nil) { - c = convert_nil (c, type); - } - append_expr (local_expr, assign_expr (unary_expr ('.', ptr), c)); - } + expr_t *ptr = new_pointer_expr (0, def->type, def); + assign_elements (local_expr, pointer_expr (ptr), &element_chain); } else { def_t dummy = *def; for (element = element_chain.head; element; element = element->next) { @@ -502,8 +400,7 @@ init_elements (struct def_s *def, expr_t *eles) } } - *element_chain.tail = elements_freelist; - elements_freelist = element_chain.head; + free_element_chain (&element_chain); } static void diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index b4173f45d..4b0317d53 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -432,8 +432,8 @@ copy_expr (expr_t *e) case ex_compound: n = new_expr (); *n = *e; - for (ex_initele_t *i = e->e.compound.head; i; i = i->next) { - append_element (n, new_initele (i->expr, i->symbol)); + for (element_t *i = e->e.compound.head; i; i = i->next) { + append_element (n, new_element (i->expr, i->symbol)); } return n; } @@ -551,46 +551,6 @@ new_block_expr (void) return b; } -ex_initele_t * -new_initele (expr_t *expr, symbol_t *symbol) -{ - ex_initele_t *i = calloc (1, sizeof (*i)); - i->expr = expr; - i->symbol = symbol; - return i; -} - -expr_t * -new_compound_init (void) -{ - expr_t *c = new_expr (); - c->type = ex_compound; - c->e.compound.head = 0; - c->e.compound.tail = &c->e.compound.head; - return c; -} - -expr_t * -append_element (expr_t *compound, ex_initele_t *element) -{ - if (compound->type != ex_compound) { - internal_error (compound, "not a compound expression"); - } - - if (!element || (element->expr && element->expr->type == ex_error)) { - return compound; - } - - if (element->next) { - internal_error (compound, "append_element: element loop detected"); - } - - *compound->e.compound.tail = element; - compound->e.compound.tail = &element->next; - - return compound; -} - expr_t * new_binary_expr (int op, expr_t *e1, expr_t *e2) { @@ -1731,6 +1691,7 @@ expr_t * build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) { expr_t *e; + expr_t *p; int arg_count = 0, parm_count = 0; int i; expr_t *args = 0, **a = &args; @@ -1770,8 +1731,18 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) parm_count = ftype->t.func.num_params; } for (i = arg_count - 1, e = params; i >= 0; i--, e = e->next) { - type_t *t = get_type (e); + type_t *t; + if (e->type == ex_compound) { + if (i < parm_count) { + t = ftype->t.func.param_types[i]; + } else { + return error (e, "cannot pass compound initializer " + "through ..."); + } + } else { + t = get_type (e); + } if (!t) { return e; } @@ -1827,7 +1798,11 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) call = expr_file_line (new_block_expr (), fexpr); call->e.block.is_call = 1; - for (e = params, i = 0; e; e = e->next, i++) { + for (p = params, i = 0; p; p = p->next, i++) { + expr_t *e = p; + if (e->type == ex_compound) { + e = expr_file_line (initialized_temp_expr (arg_types[i], e), e); + } if (has_function_call (e)) { expr_t *cast = cast_expr (arg_types[i], convert_vector (e)); expr_t *tmp = new_temp_def_expr (arg_types[i]); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 466ffcf95..edad8eff7 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -313,10 +313,16 @@ assign_expr (expr_t *dst, expr_t *src) } dst_type = get_type (dst); - src_type = get_type (src); if (!dst_type) { internal_error (dst, "dst_type broke in assign_expr"); } + if (src->type == ex_compound) { + src = initialized_temp_expr (dst_type, src); + if (src->type == ex_error) { + return src; + } + } + src_type = get_type (src); if (!src_type) { internal_error (src, "src_type broke in assign_expr"); } diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c new file mode 100644 index 000000000..5ead7de7a --- /dev/null +++ b/tools/qfcc/source/expr_compound.c @@ -0,0 +1,209 @@ +/* + expr_compound.c + + compound intializer expression construction and manipulations + + Copyright (C) 2020 Bill Currie + + Author: Bill Currie + Date: 2020/03/11 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/alloc.h" +#include "QF/dstring.h" +#include "QF/mathlib.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "diagnostic.h" +#include "expr.h" +#include "options.h" +#include "symtab.h" +#include "type.h" + +static element_t *elements_freelist; + +element_t * +new_element (expr_t *expr, symbol_t *symbol) +{ + element_t *element; + ALLOC (256, element_t, elements, element); + element->expr = expr; + element->symbol = symbol; + return element; +} + +static element_t * +append_init_element (element_chain_t *element_chain, element_t *element) +{ + element->next = 0; + *element_chain->tail = element; + element_chain->tail = &element->next; + return element; +} + +expr_t * +new_compound_init (void) +{ + expr_t *c = new_expr (); + c->type = ex_compound; + c->e.compound.head = 0; + c->e.compound.tail = &c->e.compound.head; + return c; +} + +void +build_element_chain (element_chain_t *element_chain, type_t *type, + expr_t *eles, int base_offset) +{ + element_t *ele = eles->e.compound.head; + + if (is_array (type)) { + type_t *array_type = type->t.array.type; + int array_size = type->t.array.size; + int i; + + for (i = 0; i < array_size; i++) { + int offset = base_offset + i * type_size (array_type); + if (ele && ele->expr && ele->expr->type == ex_compound) { + build_element_chain (element_chain, array_type, + ele->expr, offset); + } else { + element_t *element = new_element (0, 0); + element->type = array_type; + element->offset = offset; + element->expr = ele ? ele->expr : 0; // null -> nil + append_init_element (element_chain, element); + } + if (ele) { + ele = ele->next; + } + } + } else if (is_struct (type) || is_vector (type) || is_quaternion (type)) { + symtab_t *symtab = type->t.symtab; + symbol_t *field; + + for (field = symtab->symbols; field; field = field->next) { + int offset = base_offset + field->s.offset; + if (field->sy_type != sy_var + || field->visibility == vis_anonymous) { + continue; + } + if (ele && ele->expr && ele->expr->type == ex_compound) { + build_element_chain (element_chain, field->type, + ele->expr, offset); + } else { + element_t *element = new_element (0, 0); + element->type = field->type; + element->offset = offset; + element->expr = ele ? ele->expr : 0; // null -> nil + append_init_element (element_chain, element); + } + if (ele) { + ele = ele->next; + } + } + } else { + error (eles, "invalid initializer"); + } + if (ele && ele->next && options.warnings.initializer) { + warning (eles, "excessive elements in initializer"); + } +} + +void free_element_chain (element_chain_t *element_chain) +{ + *element_chain->tail = elements_freelist; + elements_freelist = element_chain->head; + element_chain->head = 0; + element_chain->tail = &element_chain->head; +} + +expr_t * +append_element (expr_t *compound, element_t *element) +{ + if (compound->type != ex_compound) { + internal_error (compound, "not a compound expression"); + } + + if (!element || (element->expr && element->expr->type == ex_error)) { + return compound; + } + + if (element->next) { + internal_error (compound, "append_element: element loop detected"); + } + append_init_element (&compound->e.compound, element); + return compound; +} + +void +assign_elements (expr_t *local_expr, expr_t *init, + element_chain_t *element_chain) +{ + element_t *element; + + for (element = element_chain->head; element; element = element->next) { + int offset = element->offset; + type_t *type = element->type; + expr_t *alias = new_offset_alias_expr (type, init, offset); + + expr_t *c; + + if (element->expr) { + c = constant_expr (element->expr); + } else { + c = new_nil_expr (); + } + if (c->type == ex_nil) { + c = convert_nil (c, type); + } + append_expr (local_expr, assign_expr (alias, c)); + } +} + +expr_t * +initialized_temp_expr (type_t *type, expr_t *compound) +{ + element_chain_t element_chain; + expr_t *temp = new_temp_def_expr (type); + expr_t *block = new_block_expr (); + + element_chain.head = 0; + element_chain.tail = &element_chain.head; + build_element_chain (&element_chain, type, compound, 0); + assign_elements (block, temp, &element_chain); + block->e.block.result = temp; + free_element_chain (&element_chain); + return block; +} diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 5b3216d10..a4ce4c433 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -98,7 +98,7 @@ int yylex (void); void *pointer; // for ensuring pointer values are null struct type_s *type; struct expr_s *expr; - struct ex_initele_s *element; + struct element_s *element; struct function_s *function; struct switch_block_s *switch_block; struct param_s *param; @@ -188,7 +188,8 @@ int yylex (void); %type optional_state_expr texpr vector_expr %type statement statements compound_statement %type else bool_label break_label continue_label -%type unary_expr ident_expr cast_expr opt_arg_list arg_list +%type unary_expr ident_expr cast_expr expr_list +%type opt_arg_list arg_list arg_expr %type init_var_decl_list init_var_decl %type switch_block %type identifier label @@ -1183,8 +1184,8 @@ element_list ; element - : compound_init { $$ = new_initele ($1, 0); } - | expr { $$ = new_initele ($1, 0); } + : compound_init { $$ = new_element ($1, 0); } + | expr { $$ = new_element ($1, 0); } ; optional_comma @@ -1473,7 +1474,7 @@ ident_expr ; vector_expr - : '[' expr ',' arg_list ']' + : '[' expr ',' expr_list ']' { expr_t *t = $4; while (t->next) @@ -1494,6 +1495,7 @@ cast_expr expr : cast_expr | expr '=' expr { $$ = assign_expr ($1, $3); } + | expr '=' compound_init { $$ = assign_expr ($1, $3); } | expr ASX expr { $$ = asx_expr ($2, $1, $3); } | expr '?' expr ':' expr { $$ = conditional_expr ($1, $3, $5); } | expr AND bool_label expr { $$ = bool_expr (AND, $3, $1, $4); } @@ -1522,7 +1524,7 @@ texpr ; comma_expr - : arg_list + : expr_list { if ($1->next) { expr_t *res = $1; @@ -1533,20 +1535,34 @@ comma_expr } ; +expr_list + : expr + | expr_list ',' expr + { + $3->next = $1; + $$ = $3; + } + ; + opt_arg_list : /* emtpy */ { $$ = 0; } | arg_list { $$ = $1; } ; arg_list - : expr - | arg_list ',' expr + : arg_expr + | arg_list ',' arg_expr { $3->next = $1; $$ = $3; } ; +arg_expr + : expr + | compound_init + ; + const : VALUE | NIL { $$ = new_nil_expr (); } diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 99c24142c..f4d31a2c9 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -35,6 +35,7 @@ test_progs_dat=\ chewed-alias.dat \ chewed-return.dat \ comma-expr.dat \ + compound.dat \ deadbool.dat \ double.dat \ enum.dat \ @@ -158,6 +159,15 @@ comma-expr.run: Makefile build-run include ./$(DEPDIR)/comma-expr.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/comma-expr.Qo +compound_dat_SOURCES=compound.r +compound_obj=$(compound_dat_SOURCES:.r=.qfo) +compound.dat$(EXEEXT): $(compound_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(compound_obj) +compound.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/compound.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/compound.Qo + deadbool_dat_SOURCES=deadbool.r deadbool_obj=$(deadbool_dat_SOURCES:.r=.qfo) deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/compound.r b/tools/qfcc/test/compound.r new file mode 100644 index 000000000..19a72d3fe --- /dev/null +++ b/tools/qfcc/test/compound.r @@ -0,0 +1,72 @@ +#include "test-harness.h" + +typedef struct Point { + int x; + int y; +} Point; + +typedef struct Size { + int width; + int height; +} Size; + +typedef struct Rect { + Point origin; + Size size; +} Rect; + +int test_simple_param (Point p, int x, int y) +{ + int ret = !(p.x == x && p.y == y); + if (ret) { + printf ("simple param: {%d, %d} != {%d, %d}\n", p.x, p.y, x, y); + } + return ret; +} + +int test_nested_param (Rect r, int x, int y, int w, int h) +{ + int ret = !(r.origin.x == x && r.origin.y == y + && r.size.width == w && r.size.height == h); + if (ret) { + printf ("nested param: {{%d, %d}, {%d, %d}} != ", + r.origin.x, r.origin.y, r.size.width, r.size.height); + printf ("{{%d, %d}, {%d, %d}}\n", x, y, w, h); + } + return ret; +} + +int test_simple_assign (int x, int y) +{ + Point p; + p = { x, y }; + int ret = !(p.x == x && p.y == y); + if (ret) { + printf ("simple assign: {%d, %d} != {%d, %d}\n", p.x, p.y, x, y); + } + return ret; +} + +int test_nested_assign (int x, int y, int w, int h) +{ + Rect r; + r = {{x, y}, {w, h}}; + int ret = !(r.origin.x == x && r.origin.y == y + && r.size.width == w && r.size.height == h); + if (ret) { + printf ("nested assign: {{%d, %d}, {%d, %d}} != ", + r.origin.x, r.origin.y, r.size.width, r.size.height); + printf ("{{%d, %d}, {%d, %d}}\n", x, y, w, h); + } + return ret; +} + +int main (void) +{ + int ret = 0; + ret |= test_simple_param ({1, 2}, 1, 2); + ret |= test_nested_param ({{1, 2}, {3, 4}}, 1, 2, 3, 4); + ret |= test_simple_assign (1, 2); + ret |= test_nested_assign (1, 2, 3, 4); + return ret; +} diff --git a/tools/qfcc/test/struct-init-param.r b/tools/qfcc/test/struct-init-param.r index 1b3bc9e7a..f043cfde3 100644 --- a/tools/qfcc/test/struct-init-param.r +++ b/tools/qfcc/test/struct-init-param.r @@ -16,6 +16,12 @@ typedef struct Rect_s { void *foo (Rect *obj, void *cmd, Rect *o, Point pos, Rect r); +void *baz (Rect *obj, void *cmd, Rect *o, Point pos) +{ + Rect rect = { {1, 2}, {3, 4} }; + return foo (obj, cmd, o, pos, rect); +} + void *bar (Rect *obj, void *cmd, Rect *o, Point pos) { Rect rect = { {}, obj.extent }; @@ -33,12 +39,19 @@ Rect o = { { 5, 6}, {7, 8} }; int main (void) { - int ret = 1; + int ret = 0; bar(&obj, nil, &o, obj.offset); printf ("%d %d %d %d\n", o.offset.x, o.offset.y, o.extent.width, o.extent.height); - if (o.offset.x == 0 && o.offset.y == 0 + if not (o.offset.x == 0 && o.offset.y == 0 && o.extent.width == 3 && o.extent.height == 4) - ret = 0; + ret |= 1; + + baz(&obj, nil, &o, obj.offset); + printf ("%d %d %d %d\n", o.offset.x, o.offset.y, + o.extent.width, o.extent.height); + if not (o.offset.x == 1 && o.offset.y == 2 + && o.extent.width == 3 && o.extent.height == 4) + ret |= 1; return ret; } From 48a256efaa62034196258c7254a8ffd115e97f15 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 20:45:25 +0900 Subject: [PATCH 0627/3664] [qfcc] Fix segfault when assigning {} I had intended to check, but forgot. --- tools/qfcc/source/expr_assign.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index edad8eff7..a6b3f81f0 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -293,29 +293,33 @@ assign_expr (expr_t *dst, expr_t *src) type_t *dst_type, *src_type; convert_name (dst); - convert_name (src); - if (dst->type == ex_error) { return dst; } - if (src->type == ex_error) { - return src; - } - - if (options.traditional - && (expr = check_assign_logic_precedence (dst, src))) { - return expr; - } - - if ((expr = check_valid_lvalue (dst))) { return expr; } - dst_type = get_type (dst); if (!dst_type) { internal_error (dst, "dst_type broke in assign_expr"); } + + if (src) { + convert_name (src); + if (src->type == ex_error) { + return src; + } + + if (options.traditional + && (expr = check_assign_logic_precedence (dst, src))) { + return expr; + } + } else { + if (is_scalar (dst_type)) { + return error (dst, "empty scalar initializer"); + } + src = new_nil_expr (); + } if (src->type == ex_compound) { src = initialized_temp_expr (dst_type, src); if (src->type == ex_error) { From d418be31e6d1362cdbaa4b980207817172f0fcf2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 20:55:21 +0900 Subject: [PATCH 0628/3664] [qfcc] Tweak ivar test to check old bug It turns out that assigning nil to an ivar struct does not work (should, of course). --- tools/qfcc/test/ivar-struct-return.r | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/test/ivar-struct-return.r b/tools/qfcc/test/ivar-struct-return.r index 5e212a5ba..a3883b81c 100644 --- a/tools/qfcc/test/ivar-struct-return.r +++ b/tools/qfcc/test/ivar-struct-return.r @@ -17,6 +17,7 @@ typedef struct Point Point; @implementation Object -(Point) origin { + origin = nil; return origin; } @end From 6ca85d770d471a9212cff42b8981d3222328c052 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 22:48:55 +0900 Subject: [PATCH 0629/3664] [gamecode] Add memset instructions --- include/QF/pr_comp.h | 3 +++ libs/gamecode/pr_exec.c | 23 ++++++++++++++++++++++- libs/gamecode/pr_opcode.c | 10 ++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 6458d3913..80b9e963d 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -395,6 +395,9 @@ typedef enum { OP_MOD_I, OP_MOD_F, OP_MOD_D, + + OP_MEMSET, + OP_MEMSETI, } pr_opcode_e; #define OP_BREAK 0x8000 diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index d673b7d1c..718e2b09a 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -404,6 +404,14 @@ check_stack_pointer (progs_t *pr, pointer_t stack, int size) } } +static inline void +pr_memset (pr_type_t *dst, int val, int count) +{ + while (count-- > 0) { + (*dst++).integer_var = val; + } +} + /* PR_ExecuteProgram @@ -1608,7 +1616,20 @@ op_call: pr->pr_globals + OPA.integer_var, st->b * 4); break; - + case OP_MEMSET: + if (pr_boundscheck->int_val) { + PR_BoundsCheckSize (pr, OPC.pointer_var, OPB.uinteger_var); + } + pr_memset (pr->pr_globals + OPC.pointer_var, OPA.integer_var, + OPB.integer_var); + break; + case OP_MEMSETI: + if (pr_boundscheck->int_val) { + PR_BoundsCheckSize (pr, OPC.pointer_var, st->b); + } + pr_memset (pr->pr_globals + OPC.pointer_var, OPA.integer_var, + st->b); + break; case OP_GE_D: OPC.float_var = OPA_double_var >= OPB_double_var; break; diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 853176925..dc3a59fb9 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -1183,6 +1183,16 @@ VISIBLE const opcode_t pr_opcodes[] = { PROG_VERSION, "%Ga, %Gb, %Gc", }, + {"", "memset", OP_MEMSET, true, + ev_integer, ev_integer, ev_pointer, + PROG_VERSION, + "%Ga, %Gb, %Gc", + }, + {"", "memseti", OP_MEMSETI, true, + ev_integer, ev_short, ev_pointer, + PROG_VERSION, + "%Ga, %Gb, %Gc", + }, {"", "push.s", OP_PUSH_S, false, ev_string, ev_invalid, ev_invalid, From be5f11f33a34d9db9663d35da65c31a7badb00de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 22:57:20 +0900 Subject: [PATCH 0630/3664] [qfcc] Support the new memset instructions --- tools/qfcc/include/expr.h | 11 +++++++++++ tools/qfcc/source/expr.c | 32 ++++++++++++++++++++++++++++++++ tools/qfcc/source/expr_assign.c | 1 + tools/qfcc/source/statements.c | 30 +++++++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 008313a5a..322298da4 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -56,6 +56,7 @@ typedef enum { ex_nil, ///< umm, nil, null. nuff said (0 of any type) ex_value, ///< constant value (::ex_value_t) ex_compound, ///< compound initializer + ex_memset, ///< memset needs three params... } expr_type; /** Binary and unary expressions. @@ -142,6 +143,12 @@ typedef struct { struct expr_s *e; } ex_bool_t; +typedef struct ex_memset_s { + struct expr_s *dst; + struct expr_s *val; + struct expr_s *count; +} ex_memset_t; + /** State expression used for think function state-machines. State expressions are of the form [framenum, nextthink] @@ -225,6 +232,7 @@ typedef struct expr_s { ex_vector_t vector; ///< vector expression list ex_value_t *value; ///< constant value element_chain_t compound; ///< compound initializer + ex_memset_t memset; ///< memset expr params } e; } expr_t; @@ -640,6 +648,9 @@ expr_t *new_param_expr (struct type_s *type, int num); expr_t *new_move_expr (expr_t *e1, expr_t *e2, struct type_s *type, int indirect); +expr_t *new_memset_expr (expr_t *dst, expr_t *val, expr_t *count); + + /** Convert a name to an expression of the appropriate type. Converts the expression in-place. If the exprssion is not a name diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 4b0317d53..47f398f46 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -214,6 +214,7 @@ get_type (expr_t *e) convert_name (e); switch (e->type) { case ex_labelref: + case ex_memset: return &type_void; case ex_label: case ex_error: @@ -436,6 +437,13 @@ copy_expr (expr_t *e) append_element (n, new_element (i->expr, i->symbol)); } return n; + case ex_memset: + n = new_expr (); + *n = *e; + n->e.memset.dst = copy_expr (e->e.memset.dst); + n->e.memset.val = copy_expr (e->e.memset.val); + n->e.memset.count = copy_expr (e->e.memset.count); + return n; } internal_error (e, "invalid expression"); } @@ -1171,6 +1179,27 @@ new_move_expr (expr_t *e1, expr_t *e2, type_t *type, int indirect) return e; } +expr_t * +new_memset_expr (expr_t *dst, expr_t *val, expr_t *count) +{ + expr_t *e; + if (!is_pointer (get_type (dst))) { + return error (dst, "incorrect destination type for memset"); + } + if (!is_scalar (get_type (val))) { + return error (val, "memset value must be a scalar"); + } + if (!is_integral (get_type (count))) { + return error (val, "memset count must be integral"); + } + e = new_expr (); + e->type = ex_memset; + e->e.memset.dst = dst; + e->e.memset.val = val; + e->e.memset.count = count; + return e; +} + expr_t * append_expr (expr_t *block, expr_t *e) { @@ -1508,6 +1537,7 @@ unary_expr (int op, expr_t *e) case ex_labelref: case ex_state: case ex_compound: + case ex_memset: internal_error (e, 0); case ex_uexpr: if (e->e.expr.op == '-') @@ -1575,6 +1605,7 @@ unary_expr (int op, expr_t *e) case ex_labelref: case ex_state: case ex_compound: + case ex_memset: internal_error (e, 0); case ex_bool: return new_bool_expr (e->e.bool.false_list, @@ -1641,6 +1672,7 @@ unary_expr (int op, expr_t *e) case ex_labelref: case ex_state: case ex_compound: + case ex_memset: internal_error (e, 0); case ex_uexpr: if (e->e.expr.op == '~') diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index a6b3f81f0..0ada7160b 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -123,6 +123,7 @@ check_valid_lvalue (expr_t *expr) return check_valid_lvalue (expr->e.expr.e1); } break; + case ex_memset: case ex_compound: case ex_state: case ex_bool: diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 517fcc7b3..1bb2bc2ba 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1438,6 +1438,32 @@ statement_uexpr (sblock_t *sblock, expr_t *e) return sblock; } +static sblock_t * +statement_memset (sblock_t *sblock, expr_t *e) +{ + expr_t *dst = e->e.memset.dst; + expr_t *val = e->e.memset.val; + expr_t *count = e->e.memset.count; + const char *opcode = ""; + statement_t *s; + + if (is_constant (count)) { + if (is_integer (get_type (count)) + && (unsigned) expr_integer (count) < 0x10000) { + count = new_short_expr (expr_integer (count)); + } + if (is_uinteger (get_type (count)) && expr_integer (count) < 0x10000) { + count = new_short_expr (expr_uinteger (count)); + } + } + s = new_statement (st_move, opcode, e); + sblock = statement_subexpr (sblock, dst, &s->opc); + sblock = statement_subexpr (sblock, count, &s->opb); + sblock = statement_subexpr (sblock, val, &s->opa); + sblock_add_statement (sblock, s); + return sblock; +} + static sblock_t * statement_nonexec (sblock_t *sblock, expr_t *e) { @@ -1463,10 +1489,12 @@ statement_slist (sblock_t *sblock, expr_t *e) statement_nonexec, // ex_vector statement_nonexec, // ex_nil statement_nonexec, // ex_value + 0, // ex_compound + statement_memset, }; for (/**/; e; e = e->next) { - if (e->type > ex_value) + if (e->type > ex_memset) internal_error (e, "bad expression type"); sblock = sfuncs[e->type] (sblock, e); } From 5d349efe782f777181818e81de8f65f413f8c356 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 22:57:48 +0900 Subject: [PATCH 0631/3664] [qfcc] Delay conversion of nil in assignments It's not possible to take the address of constants (at this stage) and trying to use a move instruction with .zero as source would result in the VM complaining about null pointer access when bounds checking is on. Thus, don't convert a nil source expression until it is known to be safe, and use memset when it is not. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/expr.c | 6 ++++++ tools/qfcc/source/expr_assign.c | 37 +++++++++++++++++++++++---------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 322298da4..9879ee810 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -595,6 +595,7 @@ int is_logic (int op) __attribute__((const)); int has_function_call (expr_t *e) __attribute__((pure)); +int is_nil (expr_t *e) __attribute__((pure)); int is_string_val (expr_t *e) __attribute__((pure)); int is_float_val (expr_t *e) __attribute__((pure)); int is_vector_val (expr_t *e) __attribute__((pure)); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 47f398f46..2d419c20f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -882,6 +882,12 @@ constant_expr (expr_t *e) return new; } +int +is_nil (expr_t *e) +{ + return e->type == ex_nil; +} + int is_string_val (expr_t *e) { diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 0ada7160b..07a838b13 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -345,21 +345,22 @@ assign_expr (expr_t *dst, expr_t *src) } src_type = get_type (src); } - if (!is_void (dst_type) && src->type == ex_nil) { + if (!is_struct (dst_type) && is_nil (src)) { // nil is a type-agnostic 0 // FIXME: assignment to compound types? error or memset? src_type = dst_type; convert_nil (src, src_type); } - if ((expr = check_types_compatible (dst, src))) { - // expr might be a valid expression, but if so, check_types_compatible - // will take care of everything - return expr; - } - - if ((expr = assign_vector_expr (dst, src))) { - return expr; + if (!is_nil (src)) { + if ((expr = check_types_compatible (dst, src))) { + // expr might be a valid expression, but if so, + // check_types_compatible will take care of everything + return expr; + } + if ((expr = assign_vector_expr (dst, src))) { + return expr; + } } if (is_indirect (dst) && is_indirect (src)) { @@ -381,8 +382,18 @@ assign_expr (expr_t *dst, expr_t *src) debug (dst, "here"); if (is_struct (dst_type)) { dst = address_expr (dst, 0, 0); - src = address_expr (src, 0, 0); - return new_move_expr (dst, src, dst_type, 1); + if (is_nil (src)) { + int size = type_size (dst_type); + return new_memset_expr (dst, new_integer_expr (0), + new_integer_expr (size)); + } else { + src = address_expr (src, 0, 0); + return new_move_expr (dst, src, dst_type, 1); + } + } + if (is_nil (src)) { + src_type = dst_type; + convert_nil (src, src_type); } if (dst->type == ex_expr) { if (get_type (dst->e.expr.e1) == &type_entity) { @@ -420,6 +431,10 @@ assign_expr (expr_t *dst, expr_t *src) } } + if (is_nil (src)) { + src_type = dst_type; + convert_nil (src, src_type); + } if (is_struct (dst_type)) { return new_move_expr (dst, src, dst_type, 0); } From e4caf50ee1aeb2a54fdaacf57cbdf6dc5e1db889 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Mar 2020 23:52:12 +0900 Subject: [PATCH 0632/3664] [qfcc] Update switch tables for compound initializers Forgot to do a full test build (Machine.r found it) --- tools/qfcc/source/def.c | 2 ++ tools/qfcc/source/statements.c | 6 +++--- tools/qfcc/source/switch.c | 6 ++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index f690f2c3b..d642261ef 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -371,6 +371,8 @@ init_elements (struct def_s *def, expr_t *eles) dummy.offset = def->offset + element->offset; g = D_POINTER (pr_type_t, &dummy); if (c->type == ex_labelref) { + // reloc_def_* use only the def's offset and space, so dummy + // is ok reloc_def_op (c->e.labelref.label, &dummy); continue; } else if (c->type == ex_value) { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 1bb2bc2ba..0b27803a1 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -536,7 +536,7 @@ statement_get_targetlist (statement_t *s) sblock_t **target_list; int count = 0, i; def_t *table = 0; - expr_t *e; + element_t *e; if (statement_is_cond (s)) { count = 1; @@ -555,9 +555,9 @@ statement_get_targetlist (statement_t *s) } else if (statement_is_jumpb (s)) { if (table->alias) internal_error (0, "aliased jump table"); - e = table->initializer->e.block.head; //FIXME check!!! + e = table->initializer->e.compound.head; //FIXME check!!! for (i = 0; i < count; e = e->next, i++) - target_list[i] = e->e.labelref.label->dest; + target_list[i] = e->expr->e.labelref.label->dest; } return target_list; } diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 7e76ef6f4..967a7b73f 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -337,11 +337,13 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, const char *table_name = new_label_name (); int i; expr_t *range = binary_expr ('-', tree->high, tree->low); + expr_t *label; - table_init = new_block_expr (); + table_init = new_compound_init (); for (i = 0; i <= high - low; i++) { tree->labels[i]->e.label.used++; - append_expr (table_init, address_expr (tree->labels[i], 0, 0)); + label = address_expr (tree->labels[i], 0, 0); + append_element (table_init, new_element (label, 0)); } table_sym = new_symbol_type (table_name, array_type (&type_integer, From 0d4c7ba10fa8d7df5349e881128bfb78d47835d4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Mar 2020 00:52:42 +0900 Subject: [PATCH 0633/3664] [cl_menu] Update plist usage of obj_msg_sendv Wonder if there's anywhere else... --- ruamoko/cl_menu/plistmenu.r | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ruamoko/cl_menu/plistmenu.r b/ruamoko/cl_menu/plistmenu.r index bdece6082..00d2a61e0 100644 --- a/ruamoko/cl_menu/plistmenu.r +++ b/ruamoko/cl_menu/plistmenu.r @@ -58,6 +58,7 @@ class_from_plist (PLDictionary *pldict) return ret; } obj = [class alloc]; + params[0].pointer_val = obj; messages = (PLArray*) [pldict getObjectForKey:"Messages"]; message_count = [messages count]; @@ -65,9 +66,10 @@ class_from_plist (PLDictionary *pldict) msg = (PLArray*) [messages getObjectAtIndex:i]; selname = [(PLString*) [msg getObjectAtIndex:0] string]; sel = sel_get_uid (selname); - va_list.count = [msg count] - 1; - for (j = 0; j < va_list.count; j++) { - paramstr = [(PLString*) [msg getObjectAtIndex:j + 1] string]; + params[1].pointer_val = sel; + va_list.count = [msg count] + 1; + for (j = 2; j < va_list.count; j++) { + paramstr = [(PLString*) [msg getObjectAtIndex:j - 1] string]; switch (str_mid (paramstr, 0, 1)) { case "\"": va_list.list[j].string_val = str_mid (paramstr, 1, -1); From 21a8559674ac3cb72b9a8a0c13dd3cadb254701e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Mar 2020 19:30:54 +0900 Subject: [PATCH 0634/3664] [qfcc] Improve handling of nil assignments Especially when they result in using memset. --- tools/qfcc/include/expr.h | 3 ++- tools/qfcc/source/expr.c | 11 +++++------ tools/qfcc/source/expr_assign.c | 15 +++++++++------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 9879ee810..a8a1a98f2 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -147,6 +147,7 @@ typedef struct ex_memset_s { struct expr_s *dst; struct expr_s *val; struct expr_s *count; + struct type_s *type; } ex_memset_t; /** State expression used for think function state-machines. @@ -649,7 +650,7 @@ expr_t *new_param_expr (struct type_s *type, int num); expr_t *new_move_expr (expr_t *e1, expr_t *e2, struct type_s *type, int indirect); -expr_t *new_memset_expr (expr_t *dst, expr_t *val, expr_t *count); +expr_t *new_memset_expr (expr_t *dst, expr_t *val, struct type_s *type); /** Convert a name to an expression of the appropriate type. diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 2d419c20f..922d47921 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -214,8 +214,9 @@ get_type (expr_t *e) convert_name (e); switch (e->type) { case ex_labelref: - case ex_memset: return &type_void; + case ex_memset: + return e->e.memset.type; case ex_label: case ex_error: case ex_compound: @@ -1186,7 +1187,7 @@ new_move_expr (expr_t *e1, expr_t *e2, type_t *type, int indirect) } expr_t * -new_memset_expr (expr_t *dst, expr_t *val, expr_t *count) +new_memset_expr (expr_t *dst, expr_t *val, type_t *type) { expr_t *e; if (!is_pointer (get_type (dst))) { @@ -1195,14 +1196,12 @@ new_memset_expr (expr_t *dst, expr_t *val, expr_t *count) if (!is_scalar (get_type (val))) { return error (val, "memset value must be a scalar"); } - if (!is_integral (get_type (count))) { - return error (val, "memset count must be integral"); - } e = new_expr (); e->type = ex_memset; e->e.memset.dst = dst; e->e.memset.val = val; - e->e.memset.count = count; + e->e.memset.count = new_integer_expr (type_size (type)); + e->e.memset.type = type; return e; } diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 07a838b13..f0dca6474 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -286,6 +286,12 @@ is_indirect (expr_t *e) return is_const_ptr (e->e.expr.e1); } +static __attribute__((pure)) int +is_memset (expr_t *e) +{ + return e->type == ex_memset; +} + expr_t * assign_expr (expr_t *dst, expr_t *src) { @@ -305,7 +311,7 @@ assign_expr (expr_t *dst, expr_t *src) internal_error (dst, "dst_type broke in assign_expr"); } - if (src) { + if (src && !is_memset (src)) { convert_name (src); if (src->type == ex_error) { return src; @@ -316,7 +322,7 @@ assign_expr (expr_t *dst, expr_t *src) return expr; } } else { - if (is_scalar (dst_type)) { + if (!is_memset (src) && is_scalar (dst_type)) { return error (dst, "empty scalar initializer"); } src = new_nil_expr (); @@ -347,7 +353,6 @@ assign_expr (expr_t *dst, expr_t *src) } if (!is_struct (dst_type) && is_nil (src)) { // nil is a type-agnostic 0 - // FIXME: assignment to compound types? error or memset? src_type = dst_type; convert_nil (src, src_type); } @@ -383,9 +388,7 @@ assign_expr (expr_t *dst, expr_t *src) if (is_struct (dst_type)) { dst = address_expr (dst, 0, 0); if (is_nil (src)) { - int size = type_size (dst_type); - return new_memset_expr (dst, new_integer_expr (0), - new_integer_expr (size)); + return new_memset_expr (dst, new_integer_expr (0), dst_type); } else { src = address_expr (src, 0, 0); return new_move_expr (dst, src, dst_type, 1); From 08b7064a3f647aa98d8a6bdd351b1be8be790327 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Mar 2020 19:32:09 +0900 Subject: [PATCH 0635/3664] [ruamoko] Set pr_argc before calling error methods Builtins calling ruamoko code need to be careful of the arg count in case the ruamoko function uses varargs. --- libs/ruamoko/rua_obj.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index c30683d0e..854341b56 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1289,6 +1289,7 @@ rua___obj_forward (progs_t *pr) P_POINTER (pr, 0) = PR_SetPointer (pr, obj); P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); P_POINTER (pr, 2) = PR_SetPointer (pr, sel); + pr->pr_argc = 3; PR_CallFunction (pr, imp); return; } @@ -1306,6 +1307,7 @@ rua___obj_forward (progs_t *pr) P_POINTER (pr, 0) = PR_SetPointer (pr, obj); P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); P_POINTER (pr, 2) = PR_SetTempString (pr, probj->msg->str); + pr->pr_argc = 3; PR_CallFunction (pr, imp); return; } From bbfd498b74f1325530caa9228ca3f357884e18ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Mar 2020 19:34:18 +0900 Subject: [PATCH 0636/3664] [qfcc] Handle compound and memset dot nodes compound is currently not very informative, but it's better than "bad expression type" --- tools/qfcc/source/dot_expr.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index f8601c6ff..6b1cb2428 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -506,6 +506,29 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->line); } +static void +print_compound (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + dasprintf (dstr, "%*se_%p [label=\"compound init\"];\n", indent, "", e); +} + +static void +print_memset (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + expr_t *dst = e->e.memset.dst; + expr_t *val = e->e.memset.val; + expr_t *count = e->e.memset.count; + _print_expr (dstr, dst, level, id, next); + _print_expr (dstr, val, level, id, next); + _print_expr (dstr, count, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, dst); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, val); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, count); + dasprintf (dstr, "%*se_%p [label=\"memset\"];\n", indent, "", e); +} + static void _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -523,6 +546,8 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) print_vector, print_nil, print_value, + print_compound, + print_memset, }; int indent = level * 2 + 2; @@ -534,7 +559,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) return; e->printid = id; - if ((int) e->type < 0 || e->type > ex_value) { + if ((int) e->type < 0 || e->type > ex_memset) { dasprintf (dstr, "%*se_%p [label=\"(bad expr type)\\n%d\"];\n", indent, "", e, e->line); return; From c7435830031df704cf3a9ca91e15b654e6727e9d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Mar 2020 19:35:32 +0900 Subject: [PATCH 0637/3664] [qfcc] Fix a comment --- tools/qfcc/source/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 50ab5dcd7..647a64716 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -722,7 +722,7 @@ emit_ivar_list_item (def_t *def, void *data, int index) defspace_t *space; #if 0 - //FIXME the type is dynamic, so need a way to pass it before it cn be + //FIXME the type is dynamic, so need a way to pass it before it can be //checked if (def->type != &XXX) internal_error (0, "%s: expected XXX def", From 65b48c734c2efc1194e2cdec4469fd7d35043cf8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Mar 2020 19:36:15 +0900 Subject: [PATCH 0638/3664] [qfcc} Mark some more functions as pure I guess gcc doesn't consider recursive functions as pure, but marking get_type as pure had a slight ripple effect. --- tools/qfcc/include/expr.h | 4 ++-- tools/qfcc/source/switch.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index a8a1a98f2..d6b71d2b1 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -263,7 +263,7 @@ extern expr_t *local_expr; \return Pointer to the type description, or null if the expression type (expr_t::type) is inappropriate. */ -struct type_s *get_type (expr_t *e); +struct type_s *get_type (expr_t *e) __attribute__((pure)); /** Get the basic type code of the expression result. @@ -271,7 +271,7 @@ struct type_s *get_type (expr_t *e); \return Pointer to the type description, or ev_type_count if get_type() returns null. */ -etype_t extract_type (expr_t *e); +etype_t extract_type (expr_t *e) __attribute__((pure)); /** Create a new expression node. diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 967a7b73f..6c00279a0 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -85,7 +85,7 @@ get_hash (const void *_cl, void *unused) return Hash_Buffer (&val->v, sizeof (val->v)) + val->lltype; } -static int +static int __attribute__((pure)) compare (const void *_cla, const void *_clb, void *unused) { case_label_t *cla = (case_label_t *) _cla; From 4c2a6c9eb218ee219531d776e4da0e8f3807340f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Mar 2020 19:37:55 +0900 Subject: [PATCH 0639/3664] [qfcc] Allow implicit demotion in initializer elements Notably, implicit double constants (no adorning d) being used to initialize float struct members. --- tools/qfcc/source/def.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index d642261ef..751bac7f5 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -380,6 +380,10 @@ init_elements (struct def_s *def, expr_t *eles) && is_float (element->type)) { convert_int (c); } + if (is_double (get_type (c)) && is_float (element->type) + && c->implicit) { + convert_double (c); + } if (get_type (c) != element->type) { error (c, "type mismatch in initializer"); continue; From f45484236181ad4c6a2a46f017852793c6c2d2c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Mar 2020 19:47:09 +0900 Subject: [PATCH 0640/3664] [qfcc] Add breaking assignment chain test This bug drove me nuts for several hours until I figured out what was going on. The assignment sub-tree is being generated, then lost. It works for simple assignments because a = b = c -> (= a (= b c)), but for complex assignments (those that require move or memset), a = b = c -> (b = c) (a = c) but nothing points to (b = c). The cause is using binary expressions to store assignments. --- tools/qfcc/test/Makefile.am | 10 ++++ tools/qfcc/test/assignchain.r | 89 +++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 tools/qfcc/test/assignchain.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index f4d31a2c9..ceb32813f 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -31,6 +31,7 @@ fail_bins= test_progs_dat=\ address-cast.dat \ alignment.dat \ + assignchain.dat \ anonstruct.dat \ chewed-alias.dat \ chewed-return.dat \ @@ -132,6 +133,15 @@ anonstruct.run: Makefile build-run include ./$(DEPDIR)/anonstruct.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/anonstruct.Qo +assignchain_dat_SOURCES=assignchain.r +assignchain_obj=$(assignchain_dat_SOURCES:.r=.qfo) +assignchain.dat$(EXEEXT): $(assignchain_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(assignchain_obj) +assignchain.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/assignchain.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/assignchain.Qo + chewed_alias_dat_SOURCES=chewed-alias.r chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo) chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/assignchain.r b/tools/qfcc/test/assignchain.r new file mode 100644 index 000000000..1e9b8eb8d --- /dev/null +++ b/tools/qfcc/test/assignchain.r @@ -0,0 +1,89 @@ +#include "test-harness.h" + +typedef struct foo { + int x; + float y; +} foo; + +int x, y; +int z = 42; +foo bar, baz; +foo foo_init = { 5, 6.25 }; + +int test_simple_global (void) +{ + int ret = 0; + x = y = z; + if (x != z || y != z) { + printf ("test_simple_global: x=%d y=%d z=%d\n", x, y, z); + ret |= 1; + } + return ret; +} + +int test_struct_global (void) +{ + int ret = 0; + bar = baz = foo_init; + if (bar.x != foo_init.x || bar.y != foo_init.y) { + printf ("test_struct: bar={%d %g} foo_init={%d %g}\n", + bar.x, bar.y, foo_init.x, foo_init.y); + ret |= 1; + } + if (baz.x != foo_init.x || baz.y != foo_init.y) { + printf ("test_struct: baz={%d %g} foo_init={%d %g}\n", + baz.x, baz.y, foo_init.x, foo_init.y); + ret |= 1; + } + bar = baz = nil; + if (bar.x || baz.x || bar.y || baz.y) { + printf ("test_struct: bar={%d %g} baz={%d %g}\n", + bar.x, bar.y, baz.x, baz.y); + ret |= 1; + } + return ret; +} + +int test_simple_pointer (int *x, int *y) +{ + int ret = 0; + *x = *y = z; + if (*x != z || *y != z) { + printf ("test_simple_global: *x=%d *y=%d z=%d\n", *x, *y, z); + ret |= 1; + } + return ret; +} + +int test_struct_pointer (foo *bar, foo *baz) +{ + int ret = 0; + *bar = *baz = foo_init; + if (bar.x != foo_init.x || bar.y != foo_init.y) { + printf ("test_struct: bar={%d %g} foo_init={%d %g}\n", + bar.x, bar.y, foo_init.x, foo_init.y); + ret |= 1; + } + if (baz.x != foo_init.x || baz.y != foo_init.y) { + printf ("test_struct: baz={%d %g} foo_init={%d %g}\n", + baz.x, baz.y, foo_init.x, foo_init.y); + ret |= 1; + } + *bar = *baz = nil; + if (bar.x || baz.x || bar.y || baz.y) { + printf ("test_struct: bar={%d %g} baz={%d %g}\n", + bar.x, bar.y, baz.x, baz.y); + ret |= 1; + } + return ret; +} + +int main () +{ + int ret = 0; + ret |= test_simple_global (); + ret |= test_struct_global (); + ret |= test_simple_pointer (&x, &y); + ret |= test_struct_pointer (&bar, &baz); + return ret; +} From 9c5fac2226e1ec22da8a7665451c5ce15e5c75d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Mar 2020 19:53:15 +0900 Subject: [PATCH 0641/3664] [qfcc] Catch another assignment chain failure --- tools/qfcc/test/assignchain.r | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/test/assignchain.r b/tools/qfcc/test/assignchain.r index 1e9b8eb8d..454279f45 100644 --- a/tools/qfcc/test/assignchain.r +++ b/tools/qfcc/test/assignchain.r @@ -69,6 +69,8 @@ int test_struct_pointer (foo *bar, foo *baz) baz.x, baz.y, foo_init.x, foo_init.y); ret |= 1; } + *bar = foo_init; + *baz = foo_init; *bar = *baz = nil; if (bar.x || baz.x || bar.y || baz.y) { printf ("test_struct: bar={%d %g} baz={%d %g}\n", From 9c06b227199db67c73e7f08573fc3f56878d8bdd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 01:59:35 +0900 Subject: [PATCH 0642/3664] [qfcc] Fix segfault when assigning {} --- tools/qfcc/source/expr_assign.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index f0dca6474..aa759b88d 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -322,7 +322,7 @@ assign_expr (expr_t *dst, expr_t *src) return expr; } } else { - if (!is_memset (src) && is_scalar (dst_type)) { + if (!src && is_scalar (dst_type)) { return error (dst, "empty scalar initializer"); } src = new_nil_expr (); From 7f9a415cbcb84d56bb2950f4f21aec0692a2e22f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 02:09:55 +0900 Subject: [PATCH 0643/3664] [qwaq] Get DrawBuffer and TextContext working Especially blitting whole regions. Partial regions not tested yet. --- ruamoko/qwaq/qwaq-curses.c | 18 ++++++++++++++---- ruamoko/qwaq/qwaq-draw.r | 2 +- ruamoko/qwaq/qwaq-rect.h | 2 ++ ruamoko/qwaq/qwaq-rect.r | 12 ++++++++++++ ruamoko/qwaq/qwaq-textcontext.r | 27 ++++++++++++++++++++++++++- ruamoko/qwaq/qwaq-window.h | 1 + ruamoko/qwaq/qwaq-window.r | 5 +++++ 7 files changed, 61 insertions(+), 6 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 8ba194619..3c1714e35 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -291,12 +291,18 @@ get_panel (qwaq_resources_t *res, const char *name, int handle) return panel; } +//XXX goes away with threads +static void process_commands (qwaq_resources_t *); +static void process_input (qwaq_resources_t *); static int acquire_string (qwaq_resources_t *res) { int string_id = -1; // XXX add locking and loop for available + if (!RB_DATA_AVAILABLE (res->string_ids)) { + process_commands(res); + } if (RB_DATA_AVAILABLE (res->string_ids)) { RB_READ_DATA (res->string_ids, &string_id, 1); } @@ -338,9 +344,6 @@ qwaq_submit_result (qwaq_resources_t *res, const int *result, unsigned len) } } -//XXX goes away with threads -static void process_commands (qwaq_resources_t *); -static void process_input (qwaq_resources_t *); static void qwaq_wait_result (qwaq_resources_t *res, int *result, int cmd, unsigned len) { @@ -628,11 +631,18 @@ cmd_mvwblit_line (qwaq_resources_t *res) int chs_id = RB_PEEK_DATA (res->command_queue, 5); int len = RB_PEEK_DATA (res->command_queue, 6); int *chs = (int *) res->strings[chs_id].str; + int save_x; + int save_y; window_t *window = get_window (res, __FUNCTION__, window_id); + getyx (window->win, save_y, save_x); for (int i = 0; i < len; i++) { - mvwaddch (window->win, y, x, chs[i]); + Sys_Printf(" %d", chs[i]); + mvwaddch (window->win, y, x + i, chs[i]); } + Sys_Printf("\n"); + wmove (window->win, save_y, save_x); + release_string (res, chs_id); } static void diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index 66e266a50..d1cdc950d 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -33,7 +33,7 @@ - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect { Extent srcSize = srcBuffer.size; - Rect r = { {}, srcBuffer.size }; + Rect r = { {}, size }; Rect t = { pos, rect.extent }; t = clipRect (r, t); diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index 9d4fc51e4..d1ba8719b 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -18,6 +18,8 @@ typedef struct Rect_s { #ifdef __QFCC__ @extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); +@extern Point makePoint (int x, int y); +@extern Extent makeExtent (int width, int height); //XXX will not work if point or rect point to a local variabl @extern int rectContainsPoint (Rect *rect, Point *point); @extern Rect getwrect (struct window_s *window); diff --git a/ruamoko/qwaq/qwaq-rect.r b/ruamoko/qwaq/qwaq-rect.r index 6ee5c7df5..8813c84ee 100644 --- a/ruamoko/qwaq/qwaq-rect.r +++ b/ruamoko/qwaq/qwaq-rect.r @@ -29,6 +29,18 @@ makeRect (int xpos, int ypos, int xlen, int ylen) return rect; } +Point makePoint (int x, int y) +{ + Point p = {x, y}; + return p; +} + +Extent makeExtent (int width, int height) +{ + Extent e = {width, height}; + return e; +} + int rectContainsPoint (Rect *rect, Point *point) { diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 726872ccf..9a63e0681 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -43,6 +43,8 @@ static TextContext *screen; } window = create_window (rect.offset.x, rect.offset.y, rect.extent.width, rect.extent.height); + offset = {}; + size = rect.extent; return self; } @@ -60,13 +62,30 @@ static TextContext *screen; return window; } +-(Extent) size +{ + return size; +} + - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect { Extent srcSize = [srcBuffer size]; - Rect r = { {}, srcSize }; + Rect r = { {}, size }; Rect t = { pos, rect.extent }; + wprintf (stdscr, "src: %p\n", srcBuffer); + wprintf (stdscr, "srcSize: %d %d\n", srcSize.width, srcSize.height); + wprintf (stdscr, "pos: %d %d\n", pos.x, pos.x); + wprintf (stdscr, "rect: %d %d %d %d\n", + rect.offset.x, rect.offset.y, + rect.extent.width, rect.extent.height); + wprintf (stdscr, "r: %d %d %d %d\n", + r.offset.x, r.offset.y, r.extent.width, r.extent.height); + wprintf (stdscr, "t: %d %d %d %d\n", + t.offset.x, t.offset.y, t.extent.width, t.extent.height); t = clipRect (r, t); + wprintf (stdscr, "t: %d %d %d %d\n", + t.offset.x, t.offset.y, t.extent.width, t.extent.height); if (t.extent.width < 0 || t.extent.height < 0) { return self; } @@ -80,6 +99,12 @@ static TextContext *screen; r.extent = size; rect = clipRect (r, rect); + wprintf (stdscr, "pos: %d %d\n", pos.x, pos.x); + wprintf (stdscr, "rect: %d %d %d %d\n", + rect.offset.x, rect.offset.y, + rect.extent.width, rect.extent.height); + wprintf (stdscr, "r: %d %d %d %d\n", + r.offset.x, r.offset.y, r.extent.width, r.extent.height); if (rect.extent.width < 0 || rect.extent.height < 0) { return self; } diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index c59a72f28..2e925c035 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -14,6 +14,7 @@ { Point point; // FIXME can't be local :( struct panel_s *panel; + DrawBuffer *buf; } +windowWithRect: (Rect) rect; -setBackground: (int) ch; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 23d919648..5a0f328ff 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -21,6 +21,10 @@ buffer = [[TextContext alloc] initWithRect: rect]; textContext = buffer; panel = create_panel ([buffer window]); + buf = [DrawBuffer buffer: makeExtent (3, 3)]; + [buf mvaddstr: makePoint (0, 0), "XOX"]; + [buf mvaddstr: makePoint (0, 1), "OXO"]; + [buf mvaddstr: makePoint (0, 2), "XOX"]; return self; } @@ -108,6 +112,7 @@ } } } + [textContext blitFromBuffer: buf to: makePoint (6, 3) from: [buf rect]]; [self refresh]; return self; } From 3defe50be627b95a2c2740e65a4fe863c81c9307 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 02:37:25 +0900 Subject: [PATCH 0644/3664] [qwaq] Add printf builtin to ease debugging --- ruamoko/qwaq/qwaq-curses.c | 16 ++++++++++++++++ ruamoko/qwaq/qwaq-curses.h | 2 ++ ruamoko/qwaq/qwaq-textcontext.r | 2 ++ 3 files changed, 20 insertions(+) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 3c1714e35..f7ef86f54 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1468,6 +1468,20 @@ bi_initialize (progs_t *pr) res->stdscr.win = stdscr; } +static void +bi_printf (progs_t *pr) +{ + const char *fmt = P_GSTRING (pr, 0); + int count = pr->pr_argc - 1; + pr_type_t **args = pr->pr_params + 1; + dstring_t *dstr = dstring_new (); + + PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); + if (dstr->str) + Sys_Printf (dstr->str, stdout); + dstring_delete (dstr); +} + static void bi_c_TextContext__is_initialized (progs_t *pr) { @@ -1674,6 +1688,8 @@ static builtin_t builtins[] = { {"wborder", bi_wborder, -1}, {"mvwblit_line", bi_mvwblit_line, -1}, + {"printf", bi_printf, -1}, + {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, {"_c_TextContext__max_color_pairs", bi_c_TextContext__max_color_pairs, -1}, diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index b592ac84b..5e59c9f08 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -121,6 +121,8 @@ typedef struct panel_s *panel_t; @extern void wborder (window_t window, box_sides_t sides, box_corners_t corners); @extern void mvwblit_line (window_t window, int x, int y, int *wch, int len); + +@extern void printf(string fmt, ...); #endif #endif//__qwaq_curses_h diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 9a63e0681..934fd597a 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -166,3 +166,5 @@ int curs_set (int visibility) = #0; int move (int x, int y) = #0; void wborder (window_t window, box_sides_t sides, box_corners_t corners) = #0; void mvwblit_line (window_t window, int x, int y, int *wch, int len) = #0; + +void printf(string fmt, ...) = #0; From d0f21ec2b40ce1cbfc8c4267fcd177323ac820ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 02:43:01 +0900 Subject: [PATCH 0645/3664] [qwaq] Add -refresh to TextContext This does the right thing in the presence of panels and dealing with stdscr. --- ruamoko/qwaq/qwaq-app.r | 7 +++++++ ruamoko/qwaq/qwaq-curses.c | 28 +++++++++++++++++++++++++--- ruamoko/qwaq/qwaq-screen.r | 2 -- ruamoko/qwaq/qwaq-textcontext.h | 1 + ruamoko/qwaq/qwaq-textcontext.r | 1 + 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 9d046a89f..fffe51c7b 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -68,6 +68,13 @@ arp_end (void) return self; } +-draw +{ + [super draw]; + [TextContext refresh]; + return self; +} + -handleEvent: (qwaq_event_t *) event { [screen handleEvent: event]; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index f7ef86f54..eb9ee8024 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1025,7 +1025,7 @@ bi_panel_window (progs_t *pr) } static void -bi_update_panels (progs_t *pr) +qwaq_update_panels (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); @@ -1033,9 +1033,14 @@ bi_update_panels (progs_t *pr) command[1] = CMD_SIZE(command); qwaq_submit_command (res, command); } +static void +bi_update_panels (progs_t *pr) +{ + qwaq_update_panels (pr); +} static void -bi_doupdate (progs_t *pr) +qwaq_doupdate (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); @@ -1043,6 +1048,11 @@ bi_doupdate (progs_t *pr) command[1] = CMD_SIZE(command); qwaq_submit_command (res, command); } +static void +bi_doupdate (progs_t *pr) +{ + qwaq_doupdate (pr); +} static void qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, @@ -1594,12 +1604,23 @@ bi_i_TextContext__mvvprintf_ (progs_t *pr) qwaq_mvwvprintf (pr, pos->x, pos->y, window_id, fmt, args); } +static void +bi_c_TextContext__refresh (progs_t *pr) +{ + qwaq_update_panels (pr); + qwaq_doupdate (pr); +} + static void bi_i_TextContext__refresh (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; - qwaq_wrefresh (pr, window_id); + //qwaq_wrefresh (pr, window_id); + qwaq_update_panels (pr); + if (window_id == 1) { + qwaq_doupdate (pr); + } } static void @@ -1703,6 +1724,7 @@ static builtin_t builtins[] = { {"_i_TextContext__vprintf_", bi_i_TextContext__vprintf_, -1}, {"_i_TextContext__addch_", bi_i_TextContext__addch_, -1}, {"_i_TextContext__mvvprintf_", bi_i_TextContext__mvvprintf_, -1}, + {"_c_TextContext__refresh", bi_c_TextContext__refresh, -1}, {"_i_TextContext__refresh", bi_i_TextContext__refresh, -1}, {"_i_TextContext__mvaddch_", bi_i_TextContext__mvaddch_, -1}, {"_i_TextContext__bkgd_", bi_i_TextContext__bkgd_, -1}, diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index e34ddb7c9..5b2db43ce 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -36,9 +36,7 @@ -redraw { - update_panels (); [textContext refresh]; - [TextContext doupdate]; return self; } diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/qwaq-textcontext.h index 765f90572..c260b6f44 100644 --- a/ruamoko/qwaq/qwaq-textcontext.h +++ b/ruamoko/qwaq/qwaq-textcontext.h @@ -49,6 +49,7 @@ - (void) mvvprintf: (Point) pos, string mft, @va_list args; - (void) mvaddch: (Point) pos, int ch; - (void) refresh; ++ (void) refresh; - (void) bkgd: (int) ch; - (void) scrollok: (int) flag; - (void) border: (box_sides_t) sides, box_corners_t corners; diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 934fd597a..8a4660dfa 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -124,6 +124,7 @@ static TextContext *screen; - (void) addch: (int) ch = #0; - (void) mvvprintf: (Point) pos, string mft, @va_list args = #0; - (void) refresh = #0; ++ (void) refresh = #0; - (void) mvaddch: (Point) pos, int ch = #0; - (void) bkgd: (int) ch = #0; - (void) scrollok: (int) flag = #0; From 1d3c8d8a6c906f86341b704c13a12cb33f4613e2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 02:46:25 +0900 Subject: [PATCH 0646/3664] [qwaq] Sort out mess around placement of getwrect --- ruamoko/qwaq/qwaq-curses.h | 4 ++++ ruamoko/qwaq/qwaq-rect.h | 1 - ruamoko/qwaq/qwaq-textcontext.r | 1 + ruamoko/qwaq/qwaq-view.r | 3 +-- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 5e59c9f08..70af63f7c 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -18,6 +18,8 @@ typedef struct box_corners_s { } box_corners_t; #ifdef __QFCC__ +#include "qwaq-rect.h" + // names, order and comments lifted from ncurses.h typedef enum { /* VT100 symbols begin here */ @@ -122,6 +124,8 @@ typedef struct panel_s *panel_t; box_sides_t sides, box_corners_t corners); @extern void mvwblit_line (window_t window, int x, int y, int *wch, int len); +@extern Rect getwrect (struct window_s *window); + @extern void printf(string fmt, ...); #endif diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index d1ba8719b..7cd72e886 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -22,7 +22,6 @@ typedef struct Rect_s { @extern Extent makeExtent (int width, int height); //XXX will not work if point or rect point to a local variabl @extern int rectContainsPoint (Rect *rect, Point *point); -@extern Rect getwrect (struct window_s *window); @extern Rect clipRect (Rect clipRect, Rect rect); #endif diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 8a4660dfa..848f3dfd5 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -167,5 +167,6 @@ int curs_set (int visibility) = #0; int move (int x, int y) = #0; void wborder (window_t window, box_sides_t sides, box_corners_t corners) = #0; void mvwblit_line (window_t window, int x, int y, int *wch, int len) = #0; +Rect getwrect (window_t window) = #0; void printf(string fmt, ...) = #0; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 98cdf4429..19df51b9c 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -126,6 +126,5 @@ updateScreenCursor (View *view) [textContext mvaddch: pos, ch]; } -@end -Rect getwrect (window_t window) = #0; +@end From 45acbddb792490d25281f2504b955e4ef56a8d1e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 02:52:23 +0900 Subject: [PATCH 0647/3664] [qwaq] Make DrawBuffer and TextContext sizes available --- ruamoko/qwaq/qwaq-draw.h | 1 + ruamoko/qwaq/qwaq-draw.r | 5 +++++ ruamoko/qwaq/qwaq-textcontext.h | 3 ++- ruamoko/qwaq/qwaq-textcontext.r | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index a0ef18dc1..5f7c7bc18 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -16,6 +16,7 @@ - (Extent) size; - (int *) buffer; +- (Rect) rect; - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index d1cdc950d..1311deb3c 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -29,6 +29,11 @@ { return buffer; } +- (Rect) rect +{ + Rect rect = { nil, size }; + return rect; +} - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect { diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/qwaq-textcontext.h index c260b6f44..1fbcb4fbd 100644 --- a/ruamoko/qwaq/qwaq-textcontext.h +++ b/ruamoko/qwaq/qwaq-textcontext.h @@ -38,7 +38,8 @@ -initWithRect: (Rect) rect; -initWithWindow: (window_t) window; --(window_t) window; +- (window_t) window; +- (Extent) size; - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 848f3dfd5..dd94e34c1 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -33,6 +33,7 @@ static TextContext *screen; return nil; } window = stdscr; + rect = getwrect (window); return self; } From 047131a737992936c8f92e577b5c827ba4c7ee68 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 09:46:36 +0900 Subject: [PATCH 0648/3664] [qfcc] Check for compound init in message args I had forgotten message sending did its own type checking and thus needed to be updated for compound initializers in message parameters. --- tools/qfcc/source/method.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 676726a5c..5b818afad 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -706,20 +706,27 @@ method_check_params (method_t *method, expr_t *args) arg_list[i--] = a; for (i = 2; i < count; i++) { expr_t *e = arg_list[i]; - type_t *t = get_type (e); + type_t *arg_type = mtype->t.func.param_types[i]; + type_t *t; - if (!t) + if (e->type == ex_compound) { + e = expr_file_line (initialized_temp_expr (arg_type, e), e); + } + t = get_type (e); + if (!t) { return e; + } if (i < param_count) { - if (e->type != ex_nil) - if (!type_assignable (mtype->t.func.param_types[i], t)) { - err = param_mismatch (e, i - 1, method->name, - mtype->t.func.param_types[i], t); + if (e->type != ex_nil) { + if (!type_assignable (arg_type, t)) { + err = param_mismatch (e, i - 1, method->name, arg_type, t); } + } } else { - if (is_integer_val (e) && options.warnings.vararg_integer) + if (is_integer_val (e) && options.warnings.vararg_integer) { warning (e, "passing integer consant into ... function"); + } } } free (arg_list); From 8d10b0f4aab448cba66ef135218bdb9d46d3f721 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 09:58:52 +0900 Subject: [PATCH 0649/3664] [qfcc] Support compound initializers for return --- tools/qfcc/source/expr.c | 27 +++++++++++++++++---------- tools/qfcc/source/qc-parse.y | 6 ++---- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 922d47921..44d62a803 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1930,9 +1930,10 @@ expr_t * return_expr (function_t *f, expr_t *e) { type_t *t; + type_t *ret_type = f->sym->type->t.func.type; if (!e) { - if (f->sym->type->t.func.type != &type_void) { + if (ret_type != &type_void) { if (options.traditional) { if (options.warnings.traditional) warning (e, @@ -1950,25 +1951,31 @@ return_expr (function_t *f, expr_t *e) } } + if (e->type == ex_compound) { + e = expr_file_line (initialized_temp_expr (ret_type, e), e); + } + t = get_type (e); - if (e->type == ex_error) + if (e->type == ex_error) { return e; - if (f->sym->type->t.func.type == &type_void) { + } + if (ret_type == &type_void) { if (!options.traditional) return error (e, "returning a value for a void function"); if (options.warnings.traditional) warning (e, "returning a value for a void function"); } - if (e->type == ex_bool) - e = convert_from_bool (e, f->sym->type->t.func.type); - if (f->sym->type->t.func.type == &type_float && is_integer_val (e)) { + if (e->type == ex_bool) { + e = convert_from_bool (e, ret_type); + } + if (ret_type == &type_float && is_integer_val (e)) { convert_int (e); t = &type_float; } if (t == &type_void) { if (e->type == ex_nil) { - t = f->sym->type->t.func.type; + t = ret_type; convert_nil (e, t); if (e->type == ex_nil) return error (e, "invalid return type for NIL"); @@ -1980,7 +1987,7 @@ return_expr (function_t *f, expr_t *e) //FIXME does anything need to be done here? } } - if (!type_assignable (f->sym->type->t.func.type, t)) { + if (!type_assignable (ret_type, t)) { if (!options.traditional) return error (e, "type mismatch for return value of %s", f->sym->name); @@ -1988,8 +1995,8 @@ return_expr (function_t *f, expr_t *e) warning (e, "type mismatch for return value of %s", f->sym->name); } else { - if (f->sym->type->t.func.type != t) { - e = cast_expr (f->sym->type->t.func.type, e); + if (ret_type != t) { + e = cast_expr (ret_type, e); t = f->sym->type->t.func.type; } } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a4ce4c433..9fe7fbbd2 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1267,10 +1267,8 @@ statement | error ';' { $$ = 0; yyerrok; } | compound_statement { $$ = $1; } | local_def { $$ = $1; } - | RETURN opt_expr ';' - { - $$ = return_expr (current_func, $2); - } + | RETURN opt_expr ';' { $$ = return_expr (current_func, $2); } + | RETURN compound_init ';' { $$ = return_expr (current_func, $2); } | BREAK ';' { $$ = 0; From 6001abbfdb03ce166b414e4b790844bbf5124bea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 10:00:05 +0900 Subject: [PATCH 0650/3664] [qwaq] Use the now working compound init more --- ruamoko/qwaq/qwaq-rect.r | 6 ++---- ruamoko/qwaq/qwaq-window.r | 8 ++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/ruamoko/qwaq/qwaq-rect.r b/ruamoko/qwaq/qwaq-rect.r index 8813c84ee..e0e3e5ee6 100644 --- a/ruamoko/qwaq/qwaq-rect.r +++ b/ruamoko/qwaq/qwaq-rect.r @@ -31,14 +31,12 @@ makeRect (int xpos, int ypos, int xlen, int ylen) Point makePoint (int x, int y) { - Point p = {x, y}; - return p; + return {x, y}; } Extent makeExtent (int width, int height) { - Extent e = {width, height}; - return e; + return {width, height}; } int diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 5a0f328ff..a4a69ee83 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -21,10 +21,10 @@ buffer = [[TextContext alloc] initWithRect: rect]; textContext = buffer; panel = create_panel ([buffer window]); - buf = [DrawBuffer buffer: makeExtent (3, 3)]; - [buf mvaddstr: makePoint (0, 0), "XOX"]; - [buf mvaddstr: makePoint (0, 1), "OXO"]; - [buf mvaddstr: makePoint (0, 2), "XOX"]; + buf = [DrawBuffer buffer: {3, 3}]; + [buf mvaddstr: {0, 0}, "XOX"]; + [buf mvaddstr: {0, 1}, "OXO"]; + [buf mvaddstr: {0, 2}, "XOX"]; return self; } From 6dfe37635d9a48ded032fb2a8692a975b30c999b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 14:56:56 +0900 Subject: [PATCH 0651/3664] [gamecode] Dump union contents The output is messy, but better than --- libs/gamecode/pr_debug.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index c102b46f8..89e5f6ba9 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1139,8 +1139,22 @@ static void pr_debug_union_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; + progs_t *pr = data->pr; dstring_t *dstr = data->dstr; + qfot_struct_t *strct = &type->t.strct; + dstring_appendstr (dstr, "{"); + for (int i = 0; i < strct->num_fields; i++) { + qfot_var_t *field = strct->fields + i; + qfot_type_t *val_type = &G_STRUCT (pr, qfot_type_t, field->type); + pr_type_t *val = value + field->offset; + dasprintf (dstr, "%s=", PR_GetString (pr, field->name)); + value_string (data, val_type, val); + if (i < strct->num_fields) { + dstring_appendstr (dstr, ", "); + } + } + dstring_appendstr (dstr, "}"); dstring_appendstr (dstr, ""); } From 087cee06be61498eee7b6b5aae4fa40005eae239 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 14:57:33 +0900 Subject: [PATCH 0652/3664] [gamecode] Use full precision for floating point values --- libs/gamecode/pr_debug.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 89e5f6ba9..0b76cb997 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -998,7 +998,7 @@ pr_debug_float_view (qfot_type_t *type, pr_type_t *value, void *_data) && value->uinteger_var != 0x80000000) { dasprintf (dstr, "<%08x>", value->integer_var); } else { - dasprintf (dstr, "%g", value->float_var); + dasprintf (dstr, "%.9g", value->float_var); } } @@ -1008,7 +1008,7 @@ pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%g %g %g'", + dasprintf (dstr, "'%.9g %.9g %.9g'", value->vector_var[0], value->vector_var[1], value->vector_var[2]); } @@ -1085,7 +1085,7 @@ pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%g %g %g %g'", + dasprintf (dstr, "'%.9g %.9g %.9g %.9g'", value->vector_var[0], value->vector_var[1], value->vector_var[2], value->vector_var[3]); } @@ -1123,7 +1123,7 @@ pr_debug_double_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%g", *(double *)value); + dasprintf (dstr, "%.17g", *(double *)value); } static void From a0d85e33c21e2578f9e484eba969fa9419b81925 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 17:50:57 +0900 Subject: [PATCH 0653/3664] [gamecode] Rework implementation of memset* The memset instructions now match the move* instructions other than the first operand (always int). Probably breaks much, but fixed in next few commits. --- include/QF/pr_comp.h | 3 ++- libs/gamecode/pr_exec.c | 9 ++++++--- libs/gamecode/pr_opcode.c | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 80b9e963d..3c6ccc8fe 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -396,8 +396,9 @@ typedef enum { OP_MOD_F, OP_MOD_D, - OP_MEMSET, OP_MEMSETI, + OP_MEMSETP, + OP_MEMSETPI, } pr_opcode_e; #define OP_BREAK 0x8000 diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 718e2b09a..a73e5a474 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1616,14 +1616,17 @@ op_call: pr->pr_globals + OPA.integer_var, st->b * 4); break; - case OP_MEMSET: + case OP_MEMSETI: + pr_memset (&OPC, OPA.integer_var, st->b); + break; + case OP_MEMSETP: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC.pointer_var, OPB.uinteger_var); + PR_BoundsCheckSize (pr, OPC.pointer_var, OPB.integer_var); } pr_memset (pr->pr_globals + OPC.pointer_var, OPA.integer_var, OPB.integer_var); break; - case OP_MEMSETI: + case OP_MEMSETPI: if (pr_boundscheck->int_val) { PR_BoundsCheckSize (pr, OPC.pointer_var, st->b); } diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index dc3a59fb9..3d3e8fe17 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -1181,17 +1181,22 @@ VISIBLE const opcode_t pr_opcodes[] = { {"", "movepi", OP_MOVEPI, true, ev_pointer, ev_short, ev_pointer, PROG_VERSION, - "%Ga, %Gb, %Gc", + "%Ga, %sb, %Gc", }, - {"", "memset", OP_MEMSET, true, + {"", "memseti", OP_MEMSETI, true, + ev_integer, ev_short, ev_void, + PROG_VERSION, + "%Ga, %sb, %gc", + }, + {"", "memsetp", OP_MEMSETP, true, ev_integer, ev_integer, ev_pointer, PROG_VERSION, "%Ga, %Gb, %Gc", }, - {"", "memseti", OP_MEMSETI, true, + {"", "memsetpi", OP_MEMSETPI, true, ev_integer, ev_short, ev_pointer, PROG_VERSION, - "%Ga, %Gb, %Gc", + "%Ga, %sb, %Gc", }, {"", "push.s", OP_PUSH_S, false, @@ -1710,6 +1715,9 @@ PR_Check_Opcodes (progs_t *pr) check_global_size (pr, st, op, st->b, st->a); check_global_size (pr, st, op, st->b, st->c); break; + case OP_MEMSETI: + check_global_size (pr, st, op, st->b, st->c); + break; case OP_PUSHB_F: case OP_PUSHB_S: case OP_PUSHB_ENT: From 2c9c15f4c85470ee37e1b684125325946b1c9844 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 17:54:05 +0900 Subject: [PATCH 0654/3664] [qfcc] Add a type check helper for structural types ie, struct/union/array. I finally though up a decent name (didn't want to use record as that's a pascal type). --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/type.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 21f4feb2c..791ea0fc9 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -164,6 +164,7 @@ int is_pointer (const type_t *type) __attribute__((pure)); int is_field (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); +int is_structural (const type_t *type) __attribute__((pure)); int is_func (const type_t *type) __attribute__((pure)); int is_string (const type_t *type) __attribute__((pure)); int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 4fd77a9fd..1c21e1d62 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -827,6 +827,12 @@ is_func (const type_t *type) return 0; } +int +is_structural (const type_t *type) +{ + return is_struct (type) || is_array (type); +} + int is_string (const type_t *type) { From 19002116c2fc566d11ef1c7a689f6ceb4ad467cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 17:56:07 +0900 Subject: [PATCH 0655/3664] [qfcc] Fix missing expression types from dot_expr --- tools/qfcc/source/dot_expr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 6b1cb2428..c81d982cc 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -67,6 +67,8 @@ const char *expr_names[] = "vector", "nil", "value", + "compound", + "memset", }; const char * From c04f1c01560dcb0922b69449a7806edd926aa040 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 17:57:58 +0900 Subject: [PATCH 0656/3664] [qfcc] Really delay the conversion of nil Now convert_nil only assigns the nil expression a type, and nil makes its way down to the statement emission code (where it belongs, really). Breaks even more things :) --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/def.c | 9 +++++---- tools/qfcc/source/expr.c | 9 +++++---- tools/qfcc/source/statements.c | 27 +++++++++++++++++++++++---- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index d6b71d2b1..65c8ad290 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -234,6 +234,7 @@ typedef struct expr_s { ex_value_t *value; ///< constant value element_chain_t compound; ///< compound initializer ex_memset_t memset; ///< memset expr params + struct type_s *nil; ///< type for nil if known } e; } expr_t; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 751bac7f5..689b21dac 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -360,10 +360,11 @@ init_elements (struct def_s *def, expr_t *eles) } else { def_t dummy = *def; for (element = element_chain.head; element; element = element->next) { - if (element->expr) { - c = constant_expr (element->expr); - } else { - c = new_nil_expr (); + if (!element->expr + || ((c = constant_expr (element->expr))->type == ex_nil)) { + // nil is type agnostic 0 and defspaces are initialized to + // 0 on creation + continue; } if (c->type == ex_nil) { c = convert_nil (c, element->type); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 44d62a803..c4408f6e2 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -226,6 +226,10 @@ get_type (expr_t *e) return &type_float; return &type_integer; case ex_nil: + if (e->e.nil) { + return e->e.nil; + } + // fall through case ex_state: return &type_void; case ex_block: @@ -1414,8 +1418,7 @@ convert_double (expr_t *e) expr_t * convert_nil (expr_t *e, type_t *t) { - e->type = ex_value; - e->e.value = new_nil_val (t); + e->e.nil = t; return e; } @@ -1977,8 +1980,6 @@ return_expr (function_t *f, expr_t *e) if (e->type == ex_nil) { t = ret_type; convert_nil (e, t); - if (e->type == ex_nil) - return error (e, "invalid return type for NIL"); } else { if (!options.traditional) return error (e, "void value not ignored as it ought to be"); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 0b27803a1..e38248bed 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1149,6 +1149,23 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_nil (sblock_t *sblock, expr_t *e, operand_t **op) +{ + type_t *nil = e->e.nil; + expr_t *ptr; + if (!is_struct (nil) && !is_array (nil)) { + *op = value_operand (new_nil_val (nil), e); + return sblock; + } + ptr = address_expr (new_temp_def_expr (nil), 0, 0); + expr_file_line (ptr, e); + sblock = statement_subexpr (sblock, ptr, op); + e = expr_file_line (new_memset_expr (ptr, new_integer_expr (0), nil), e); + sblock = statement_slist (sblock, e); + return sblock; +} + static sblock_t * expr_value (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1171,18 +1188,20 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) expr_symbol, expr_temp, expr_vector_e, // ex_vector - 0, // ex_nil + expr_nil, expr_value, + 0, // ex_compound + 0, // ex_memset }; if (!e) { *op = 0; return sblock; } - if (e->type > ex_value) - internal_error (e, "bad expression type"); + if (e->type > ex_memset) + internal_error (e, "bad sub-expression type"); if (!sfuncs[e->type]) - internal_error (e, "unexpected expression type: %s", + internal_error (e, "unexpected sub-expression type: %s", expr_names[e->type]); sblock = sfuncs[e->type] (sblock, e, op); From 3d88c3845fe0baede222e5aa2a8a336b30232f24 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 18:20:38 +0900 Subject: [PATCH 0657/3664] [qfcc] Move struct copy/set into statement emission Doing it in the expression trees was a big mistake for a several reasons. For one, expression trees are meant to be target-agnostic, so they're the wrong place for selecting instruction types. Also, the move and memset expressions broke "a = b = c;" type expression chains. This fixes most things (including the assignchain test) with -Werror turned off (some issues in flow analysis uncovered by the nil migration: memset target not extracted). --- tools/qfcc/source/expr_assign.c | 106 ++------------------------------ tools/qfcc/source/statements.c | 106 ++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 102 deletions(-) diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index aa759b88d..465746983 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -263,29 +263,6 @@ assign_vector_expr (expr_t *dst, expr_t *src) return 0; } -static __attribute__((pure)) int -is_const_ptr (expr_t *e) -{ - if ((e->type != ex_value || e->e.value->lltype != ev_pointer) - || !(POINTER_VAL (e->e.value->v.pointer) >= 0 - && POINTER_VAL (e->e.value->v.pointer) < 65536)) { - return 1; - } - return 0; -} - -static __attribute__((pure)) int -is_indirect (expr_t *e) -{ - if (e->type == ex_block && e->e.block.result) - return is_indirect (e->e.block.result); - if (e->type == ex_expr && e->e.expr.op == '.') - return 1; - if (!(e->type == ex_uexpr && e->e.expr.op == '.')) - return 0; - return is_const_ptr (e->e.expr.e1); -} - static __attribute__((pure)) int is_memset (expr_t *e) { @@ -345,17 +322,14 @@ assign_expr (expr_t *dst, expr_t *src) src_type = get_type (src); } if (src->type == ex_bool) { + // boolean expressions are chains of tests, so extract the result + // of the tests src = convert_from_bool (src, dst_type); if (src->type == ex_error) { return src; } src_type = get_type (src); } - if (!is_struct (dst_type) && is_nil (src)) { - // nil is a type-agnostic 0 - src_type = dst_type; - convert_nil (src, src_type); - } if (!is_nil (src)) { if ((expr = check_types_compatible (dst, src))) { @@ -366,80 +340,8 @@ assign_expr (expr_t *dst, expr_t *src) if ((expr = assign_vector_expr (dst, src))) { return expr; } - } - - if (is_indirect (dst) && is_indirect (src)) { - debug (dst, "here"); - if (is_struct (src_type)) { - dst = address_expr (dst, 0, 0); - src = address_expr (src, 0, 0); - expr = new_move_expr (dst, src, src_type, 1); - } else { - expr_t *temp = new_temp_def_expr (dst_type); - - expr = new_block_expr (); - append_expr (expr, assign_expr (temp, src)); - append_expr (expr, assign_expr (dst, temp)); - expr->e.block.result = temp; - } - return expr; - } else if (is_indirect (dst)) { - debug (dst, "here"); - if (is_struct (dst_type)) { - dst = address_expr (dst, 0, 0); - if (is_nil (src)) { - return new_memset_expr (dst, new_integer_expr (0), dst_type); - } else { - src = address_expr (src, 0, 0); - return new_move_expr (dst, src, dst_type, 1); - } - } - if (is_nil (src)) { - src_type = dst_type; - convert_nil (src, src_type); - } - if (dst->type == ex_expr) { - if (get_type (dst->e.expr.e1) == &type_entity) { - dst_type = dst->e.expr.type; - dst->e.expr.type = pointer_type (dst_type); - dst->e.expr.op = '&'; - } - op = PAS; - } else { - if (is_const_ptr (dst->e.expr.e1)) { - dst = dst->e.expr.e1; - op = PAS; - } - } - } else if (is_indirect (src)) { - debug (dst, "here"); - if (is_struct (dst_type)) { - dst = address_expr (dst, 0, 0); - src = address_expr (src, 0, 0); - src->rvalue = 1; - return new_move_expr (dst, src, src_type, 1); - } - if (src->type == ex_uexpr) { - expr = src->e.expr.e1; - if (is_const_ptr (expr)) { - if (expr->type == ex_expr && expr->e.expr.op == '&' - && expr->e.expr.type->type == ev_pointer - && !is_constant (expr)) { - src = expr; - src->e.expr.op = '.'; - src->e.expr.type = src_type; - src->rvalue = 1; - } - } - } - } - - if (is_nil (src)) { - src_type = dst_type; - convert_nil (src, src_type); - } - if (is_struct (dst_type)) { - return new_move_expr (dst, src, dst_type, 0); + } else { + convert_nil (src, dst_type); } expr = new_binary_expr (op, dst, src); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e38248bed..4a3aff674 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -42,6 +42,7 @@ #include "qfalloca.h" #include "QF/alloc.h" +#include "QF/mathlib.h" #include "QF/va.h" #include "dags.h" @@ -615,18 +616,123 @@ statement_branch (sblock_t *sblock, expr_t *e) return sblock->next; } +static __attribute__((pure)) int +is_const_ptr (expr_t *e) +{ + if ((e->type != ex_value || e->e.value->lltype != ev_pointer) + || !(POINTER_VAL (e->e.value->v.pointer) >= 0 + && POINTER_VAL (e->e.value->v.pointer) < 65536)) { + return 1; + } + return 0; +} + +static __attribute__((pure)) int +is_indirect (expr_t *e) +{ + if (e->type == ex_block && e->e.block.result) + return is_indirect (e->e.block.result); + if (e->type == ex_expr && e->e.expr.op == '.') + return 1; + if (!(e->type == ex_uexpr && e->e.expr.op == '.')) + return 0; + return is_const_ptr (e->e.expr.e1); +} + +static sblock_t * +expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op) +{ + statement_t *s; + expr_t *dst_expr = e->e.expr.e1; + expr_t *src_expr = e->e.expr.e2; + type_t *dst_type = get_type (dst_expr); + type_t *src_type = get_type (src_expr); + unsigned count; + expr_t *count_expr; + operand_t *dst = 0; + operand_t *src = 0; + operand_t *size = 0; + static const char *opcode_sets[][2] = { + {"", ""}, + {"", ""}, + }; + const unsigned max_count = 1 << 16; + const char **opcode_set = opcode_sets[0]; + const char *opcode; + int need_ptr = 0; + operand_t *dummy; + + if (src_expr->type == ex_expr + && (src_expr->e.expr.op == '=' || src_expr->e.expr.op == PAS)) { + sblock = statement_subexpr (sblock, src_expr, &dummy); + } + // follow the assignment chain to find the actual source expression + // (can't take the address of an assignment) + while (src_expr->type == ex_expr + && (src_expr->e.expr.op == '=' || src_expr->e.expr.op == PAS)) { + src_expr = src_expr->e.expr.e2; + } + if (src_expr->type == ex_nil) { + // switch to memset because nil is type agnostic 0 + src_expr = new_integer_expr (0); + opcode_set = opcode_sets[1]; + if (is_indirect (dst_expr)) { + need_ptr = 1; + dst_expr = address_expr (dst_expr, 0, 0); + } + } else { + if (is_indirect (dst_expr) || is_indirect (src_expr)) { + need_ptr = 1; + dst_expr = address_expr (dst_expr, 0, 0); + src_expr = address_expr (src_expr, 0, 0); + } + } + + if (type_size (dst_type) != type_size (src_type)) { + bug (e, "dst and src sizes differ in expr_assign_copy: %d %d", + type_size (dst_type), type_size (src_type)); + } + count = min (type_size (dst_type), type_size (src_type)); + if (count < (1 << 16)) { + count_expr = expr_file_line (new_short_expr (count), e); + } else { + count_expr = expr_file_line (new_integer_expr (count), e); + } + + if (count < max_count && !need_ptr) { + opcode = opcode_set[0]; + } else { + opcode = opcode_set[1]; + } + + s = new_statement (st_move, opcode, e); + sblock = statement_subexpr (sblock, dst_expr, &dst); + sblock = statement_subexpr (sblock, src_expr, &src); + sblock = statement_subexpr (sblock, count_expr, &size); + s->opa = src; + s->opb = size; + s->opc = dst; + sblock_add_statement (sblock, s); + return sblock; +} + static sblock_t * expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) { statement_t *s; expr_t *src_expr = e->e.expr.e2; expr_t *dst_expr = e->e.expr.e1; + type_t *dst_type = get_type (dst_expr); operand_t *src = 0; operand_t *dst = 0; operand_t *ofs = 0; const char *opcode = convert_op (e->e.expr.op); st_type_t type; + if (is_structural (dst_type)) { + return expr_assign_copy (sblock, e, op); + } + if (e->e.expr.op == '=') { sblock = statement_subexpr (sblock, dst_expr, &dst); src = dst; From e22579d70e134aa04038cdedd8fe24176cc063a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 18:28:54 +0900 Subject: [PATCH 0658/3664] [qfcc] Analyze memset target pointer This fixes the false uninitialized warnings cause by nil migration. --- tools/qfcc/source/flow.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index ff0d1de96..a1043df52 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1091,9 +1091,11 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, case st_move: flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opb, 1); - if (!strcmp (s->opcode, "")) { + if (!strcmp (s->opcode, "") + || !strcmp (s->opcode, "")) { flow_add_op_var (def, s->opc, 0); - } else if (!strcmp (s->opcode, "")) { + } else if (!strcmp (s->opcode, "") + || !strcmp (s->opcode, "")) { flow_add_op_var (use, s->opc, 0); if (s->opc->op_type == op_value && s->opc->o.value->lltype == ev_pointer From f738639d68883698a23ae72770478d990e8489e9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 19:58:07 +0900 Subject: [PATCH 0659/3664] Revert "[qfcc} Mark some more functions as pure" This reverts commit 65b48c734c2efc1194e2cdec4469fd7d35043cf8. I forgot that get_type calls convert_name, which most definitely is not pure. Fixes the segfault in scheme. --- tools/qfcc/include/expr.h | 4 ++-- tools/qfcc/source/switch.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 65c8ad290..b25481a8f 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -264,7 +264,7 @@ extern expr_t *local_expr; \return Pointer to the type description, or null if the expression type (expr_t::type) is inappropriate. */ -struct type_s *get_type (expr_t *e) __attribute__((pure)); +struct type_s *get_type (expr_t *e); /** Get the basic type code of the expression result. @@ -272,7 +272,7 @@ struct type_s *get_type (expr_t *e) __attribute__((pure)); \return Pointer to the type description, or ev_type_count if get_type() returns null. */ -etype_t extract_type (expr_t *e) __attribute__((pure)); +etype_t extract_type (expr_t *e); /** Create a new expression node. diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 6c00279a0..967a7b73f 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -85,7 +85,7 @@ get_hash (const void *_cl, void *unused) return Hash_Buffer (&val->v, sizeof (val->v)) + val->lltype; } -static int __attribute__((pure)) +static int compare (const void *_cla, const void *_clb, void *unused) { case_label_t *cla = (case_label_t *) _cla; From a069fad41ea87366243f19c45cf3f7b761b3dfa2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 20:16:06 +0900 Subject: [PATCH 0660/3664] [gamecode] Print only entity address when no edicts If the edicts pointer is null, it's not possible to convert the entity address to an index. --- libs/gamecode/pr_debug.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 0b76cb997..9464c326c 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1019,9 +1019,13 @@ pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - edict_t *edict = PROG_TO_EDICT (pr, value->entity_var); - dasprintf (dstr, "entity %d", NUM_FOR_BAD_EDICT (pr, edict)); + if (pr->edicts) { + edict_t *edict = PROG_TO_EDICT (pr, value->entity_var); + dasprintf (dstr, "entity %d", NUM_FOR_BAD_EDICT (pr, edict)); + } else { + dasprintf (dstr, "entity [%x]",value->entity_var); + } } static void From de89f2f31fde7ee2066fcd46632057534b4088e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 20:47:57 +0900 Subject: [PATCH 0661/3664] [qfcc] Fix a test that wasn't failing when it should --- tools/qfcc/test/assignchain.r | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/test/assignchain.r b/tools/qfcc/test/assignchain.r index 454279f45..4d6fd2e4b 100644 --- a/tools/qfcc/test/assignchain.r +++ b/tools/qfcc/test/assignchain.r @@ -85,6 +85,7 @@ int main () int ret = 0; ret |= test_simple_global (); ret |= test_struct_global (); + x = 0; y = 0; ret |= test_simple_pointer (&x, &y); ret |= test_struct_pointer (&bar, &baz); return ret; From d150210888f90c0a0ae290181b3d2a2b406c1c4c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 20:56:10 +0900 Subject: [PATCH 0662/3664] [qfcc] Nuke PAS from orbit And there was much rejoicing. I hated having to create that opcode. --- tools/qfcc/source/constfold.c | 21 ++++----------------- tools/qfcc/source/dot_expr.c | 1 - tools/qfcc/source/expr_bool.c | 2 +- tools/qfcc/source/qc-parse.y | 2 +- tools/qfcc/source/statements.c | 25 ++----------------------- 5 files changed, 8 insertions(+), 43 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index e7c037deb..f46d1a452 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -226,7 +226,7 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) if (!valid_op (op, valid)) return error (e1, "invalid operator for float"); - if (op == '=' || op == PAS) { + if (op == '=') { if ((type = get_type (e1)) != &type_float) { //FIXME optimize casting a constant e->e.expr.e2 = e2 = cf_cast_expr (type, e2); @@ -355,7 +355,7 @@ do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2) if (!valid_op (op, valid)) return error (e1, "invalid operator for double"); - if (op == '=' || op == PAS) { + if (op == '=') { if ((type = get_type (e1)) != &type_double) { //FIXME optimize casting a constant e->e.expr.e2 = e2 = cf_cast_expr (type, e2); @@ -616,7 +616,7 @@ static expr_t * do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) { type_t *type; - static int valid[] = {'=', PAS, '-', '&', 'M', '.', EQ, NE, 0}; + static int valid[] = {'=', '-', '&', 'M', '.', EQ, NE, 0}; if (is_integral (type = get_type (e2)) && (op == '-' || op == '+')) { // pointer arithmetic @@ -640,26 +640,13 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) e = binary_expr ('/', e, new_integer_expr (type_size (type))); return e; } - if (op == PAS && (type = get_type (e1)->t.fldptr.type) != get_type (e2)) { - // make sure auto-convertions happen - expr_t *tmp = new_temp_def_expr (type); - expr_t *ass = new_binary_expr ('=', tmp, e2); - - tmp->file = e1->file; - ass->line = e2->line; - ass->file = e2->file; - ass = fold_constants (ass); - if (e->e.expr.e2 == tmp) - internal_error (e2, 0); - e->e.expr.e2 = ass->e.expr.e2; - } if (op == EQ || op == NE) { if (options.code.progsversion > PROG_ID_VERSION) e->e.expr.type = &type_integer; else e->e.expr.type = &type_float; } - if (op != PAS && op != '.' && op != '&' && op != 'M' + if (op != '.' && op != '&' && op != 'M' && extract_type (e1) != extract_type (e2)) return type_mismatch (e1, e2, op); if ((op == '.' || op == '&') && get_type (e2) == &type_uinteger) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index c81d982cc..76bd21089 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -75,7 +75,6 @@ const char * get_op_string (int op) { switch (op) { - case PAS: return ".="; case OR: return "||"; case AND: return "&&"; case EQ: return "=="; diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 7f7fdbfee..74f8d24de 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -245,7 +245,7 @@ convert_bool (expr_t *e, int block) { expr_t *b; - if (e->type == ex_expr && (e->e.expr.op == '=' || e->e.expr.op == PAS)) { + if (e->type == ex_expr && e->e.expr.op == '=') { expr_t *src; if (!e->paren && options.warnings.precedence) warning (e, "suggest parentheses around assignment " diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 9fe7fbbd2..6ca42392c 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -124,7 +124,7 @@ int yylex (void); %nonassoc STORAGEX %left COMMA -%right '=' ASX PAS /* pointer assign */ +%right '=' ASX %right '?' ':' %left OR %left AND diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 4a3aff674..1ac0311a5 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -440,7 +440,6 @@ static const char * convert_op (int op) { switch (op) { - case PAS: return ".="; case OR: return "||"; case AND: return "&&"; case EQ: return "=="; @@ -662,14 +661,12 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op) int need_ptr = 0; operand_t *dummy; - if (src_expr->type == ex_expr - && (src_expr->e.expr.op == '=' || src_expr->e.expr.op == PAS)) { + if (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { sblock = statement_subexpr (sblock, src_expr, &dummy); } // follow the assignment chain to find the actual source expression // (can't take the address of an assignment) - while (src_expr->type == ex_expr - && (src_expr->e.expr.op == '=' || src_expr->e.expr.op == PAS)) { + while (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { src_expr = src_expr->e.expr.e2; } if (src_expr->type == ex_nil) { @@ -743,22 +740,6 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) if (src == dst) return sblock; type = st_assign; - } else { - //FIXME this sucks. find a better way to handle both pointer - //dereferences and pointer assignements - sblock = statement_subexpr (sblock, src_expr, &src); - if (dst_expr->type == ex_expr - && extract_type (dst_expr->e.expr.e1) == ev_pointer - && !is_constant (dst_expr->e.expr.e1)) { - sblock = statement_subexpr (sblock, dst_expr->e.expr.e1, &dst); - sblock = statement_subexpr (sblock, dst_expr->e.expr.e2, &ofs); - } else { - sblock = statement_subexpr (sblock, dst_expr, &dst); - ofs = 0; - } - if (op) - *op = src; - type = st_ptrassign; } s = new_statement (type, opcode, e); s->opa = src; @@ -1059,7 +1040,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) sblock = expr_call (sblock, e, op); break; case '=': - case PAS: sblock = expr_assign (sblock, e, op); break; case 'm': @@ -1506,7 +1486,6 @@ statement_expr (sblock_t *sblock, expr_t *e) sblock = statement_branch (sblock, e); break; case '=': - case PAS: sblock = expr_assign (sblock, e, 0); break; case 'm': From 57134e01cdad37fc4ea34765a1092e41f60cc9ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Mar 2020 22:14:30 +0900 Subject: [PATCH 0663/3664] [qfcc] Handle l-value pointer dereferences again While I still hate ".=", at least it's more hidden, and the new implementation is a fair bit cleaner (hah, goto a label in an if (0) {} block). Most importantly, the expression tree code knows nothing about it. Now just to figure out what broke func-epxr. A bit of whack-a-mole, but yay for automated tests. --- tools/qfcc/source/statements.c | 75 ++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 1ac0311a5..37a94b81c 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -659,11 +659,11 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op) const char **opcode_set = opcode_sets[0]; const char *opcode; int need_ptr = 0; - operand_t *dummy; + //operand_t *dummy; - if (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { - sblock = statement_subexpr (sblock, src_expr, &dummy); - } + //if (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { + // sblock = statement_subexpr (sblock, src_expr, &dummy); + //} // follow the assignment chain to find the actual source expression // (can't take the address of an assignment) while (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { @@ -726,21 +726,62 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) const char *opcode = convert_op (e->e.expr.op); st_type_t type; - if (is_structural (dst_type)) { - return expr_assign_copy (sblock, e, op); - } - - if (e->e.expr.op == '=') { - sblock = statement_subexpr (sblock, dst_expr, &dst); - src = dst; + if (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { sblock = statement_subexpr (sblock, src_expr, &src); - ofs = 0; - if (op) - *op = dst; - if (src == dst) - return sblock; - type = st_assign; + if (is_structural (dst_type)) { + return expr_assign_copy (sblock, e, op); + } + if (is_indirect (dst_expr)) { + goto dereference_dst; + } else { + sblock = statement_subexpr (sblock, dst_expr, &dst); + } + } else { + if (is_structural (dst_type)) { + return expr_assign_copy (sblock, e, op); + } + + if (is_indirect (dst_expr)) { + // If both dst_expr and src_expr are indirect, then a staging temp + // is needed, but emitting src_expr first generates that temp + // because src is null. If src_expr is not indirect and is a simple + // variable reference, then just the ref will be generated and thus + // will be assigned to the dereferenced destination. If src_expr + // is not simple, then a temp will be generated, so all good. + sblock = statement_subexpr (sblock, src_expr, &src); + goto dereference_dst; + } else { + // dst_expr is direct and known to be an l-value, so emitting + // its expression will simply generate a reference to that l-value + // which will be used as the default location to store src_expr's + // result + sblock = statement_subexpr (sblock, dst_expr, &dst); + src = dst; + sblock = statement_subexpr (sblock, src_expr, &src); + } } + if (0) { +dereference_dst: + // dst_expr is a dereferenced pointer, so need to un-dereference it + // to get the pointer and switch to storep instructions. + dst_expr = address_expr (dst_expr, 0, 0); + opcode = ".="; // FIXME find a nicer representation (lose strings?) + if (dst_expr->type == ex_expr && !is_const_ptr (dst_expr->e.expr.e1)) { + sblock = statement_subexpr (sblock, dst_expr->e.expr.e1, &dst); + sblock = statement_subexpr (sblock, dst_expr->e.expr.e2, &ofs); + } else { + sblock = statement_subexpr (sblock, dst_expr, &dst); + ofs = 0; + } + } + if (op) { + *op = src; + } + if (src == dst) { + return sblock; + } + type = st_assign; + s = new_statement (type, opcode, e); s->opa = src; s->opb = dst; From b1459ac816cbbd99ecee1ee7a85290cd080b9202 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 01:24:13 +0900 Subject: [PATCH 0664/3664] [qfcc] Move return save temp into call block This fixes func-expr after the assignment rewrite. Now all tests pass when not optimizing (something not quite right in assignchain when optimizing). --- tools/qfcc/source/expr.c | 3 +++ tools/qfcc/source/expr_binary.c | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c4408f6e2..85c07511b 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1843,6 +1843,9 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (e->type == ex_compound) { e = expr_file_line (initialized_temp_expr (arg_types[i], e), e); } + // FIXME this is target-specific info and should not be in the + // expression tree + // That, or always use a temp, since it should get optimized out if (has_function_call (e)) { expr_t *cast = cast_expr (arg_types[i], convert_vector (e)); expr_t *tmp = new_temp_def_expr (arg_types[i]); diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 228112311..c2d446334 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -924,10 +924,14 @@ binary_expr (int op, expr_t *e1, expr_t *e2) convert_name (e1); e1 = convert_vector (e1); + // FIXME this is target-specific info and should not be in the + // expression tree if (e1->type == ex_block && e1->e.block.is_call && has_function_call (e2) && e1->e.block.result) { - e = new_temp_def_expr (get_type (e1->e.block.result)); - e1 = assign_expr (e, e1); + expr_t *tmp = new_temp_def_expr (get_type (e1->e.block.result)); + e = assign_expr (tmp, e1->e.block.result); + append_expr (e1, e); + e1->e.block.result = tmp; } if (e1->type == ex_error) return e1; From a98f0e04eba6541b20f4f10383fdf2cf20e71a5c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 01:28:00 +0900 Subject: [PATCH 0665/3664] [qfcc] Correct some misinformative prints --- tools/qfcc/test/assignchain.r | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/test/assignchain.r b/tools/qfcc/test/assignchain.r index 4d6fd2e4b..7f08c0494 100644 --- a/tools/qfcc/test/assignchain.r +++ b/tools/qfcc/test/assignchain.r @@ -26,18 +26,18 @@ int test_struct_global (void) int ret = 0; bar = baz = foo_init; if (bar.x != foo_init.x || bar.y != foo_init.y) { - printf ("test_struct: bar={%d %g} foo_init={%d %g}\n", + printf ("test_struct_global: bar={%d %g} foo_init={%d %g}\n", bar.x, bar.y, foo_init.x, foo_init.y); ret |= 1; } if (baz.x != foo_init.x || baz.y != foo_init.y) { - printf ("test_struct: baz={%d %g} foo_init={%d %g}\n", + printf ("test_struct_global: baz={%d %g} foo_init={%d %g}\n", baz.x, baz.y, foo_init.x, foo_init.y); ret |= 1; } bar = baz = nil; if (bar.x || baz.x || bar.y || baz.y) { - printf ("test_struct: bar={%d %g} baz={%d %g}\n", + printf ("test_struct_global: bar={%d %g} baz={%d %g}\n", bar.x, bar.y, baz.x, baz.y); ret |= 1; } @@ -49,7 +49,7 @@ int test_simple_pointer (int *x, int *y) int ret = 0; *x = *y = z; if (*x != z || *y != z) { - printf ("test_simple_global: *x=%d *y=%d z=%d\n", *x, *y, z); + printf ("test_simple_pointer: *x=%d *y=%d z=%d\n", *x, *y, z); ret |= 1; } return ret; @@ -60,12 +60,12 @@ int test_struct_pointer (foo *bar, foo *baz) int ret = 0; *bar = *baz = foo_init; if (bar.x != foo_init.x || bar.y != foo_init.y) { - printf ("test_struct: bar={%d %g} foo_init={%d %g}\n", + printf ("test_struct_pointer: bar={%d %g} foo_init={%d %g}\n", bar.x, bar.y, foo_init.x, foo_init.y); ret |= 1; } if (baz.x != foo_init.x || baz.y != foo_init.y) { - printf ("test_struct: baz={%d %g} foo_init={%d %g}\n", + printf ("test_struct_pointer: baz={%d %g} foo_init={%d %g}\n", baz.x, baz.y, foo_init.x, foo_init.y); ret |= 1; } From d30c895c134024562b9ff615b44e9ec4e09ed32a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 11:36:42 +0900 Subject: [PATCH 0666/3664] [qfcc] Use correct assignment statement type Just another minor detail lost in the assignment rewrite. With this, all tests pass when optimizing. --- tools/qfcc/source/statements.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 37a94b81c..e58294b00 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -760,6 +760,8 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) sblock = statement_subexpr (sblock, src_expr, &src); } } + type = st_assign; + if (0) { dereference_dst: // dst_expr is a dereferenced pointer, so need to un-dereference it @@ -773,6 +775,7 @@ dereference_dst: sblock = statement_subexpr (sblock, dst_expr, &dst); ofs = 0; } + type = st_ptrassign; } if (op) { *op = src; @@ -780,7 +783,6 @@ dereference_dst: if (src == dst) { return sblock; } - type = st_assign; s = new_statement (type, opcode, e); s->opa = src; From 7cc51c9ca35f08b311d71c9dae1a7b3f28ebe71e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 12:27:23 +0900 Subject: [PATCH 0667/3664] [qfcc] Save block expression creator's address I've already found the bug that necessitated it (and the creator was innocent), but it will help later. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/expr.c | 1 + 2 files changed, 2 insertions(+) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index b25481a8f..0efc998ba 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -104,6 +104,7 @@ typedef struct { struct expr_s **tail; ///< last expression in the block, for appending struct expr_s *result; ///< the result of this block if non-void int is_call; ///< this block exprssion forms a function call + void *return_addr;///< who allocated this } ex_block_t; typedef struct { diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 85c07511b..734886f9a 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -561,6 +561,7 @@ new_block_expr (void) b->type = ex_block; b->e.block.head = 0; b->e.block.tail = &b->e.block.head; + b->e.block.return_addr = __builtin_return_address (0); return b; } From 277ff719f5929e2494360376fa5656ffe054bb95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 12:30:18 +0900 Subject: [PATCH 0668/3664] Revert "Do not lose the block expression when taking its address." This reverts commit b49d90e769e6f936795379ed643aa91f55561610. I suspect this was a workaround for the mess in assignment chains. However, it caused compile errors with the new implementation, and is just bogus anyway. --- tools/qfcc/source/expr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 734886f9a..70e4b2076 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2229,8 +2229,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) case ex_block: if (!e1->e.block.result) return error (e1, "invalid type for unary &"); - e1->e.block.result = address_expr (e1->e.block.result, e2, t); - return e1; + return address_expr (e1->e.block.result, e2, t); case ex_label: return new_label_ref (&e1->e.label); case ex_temp: From 6608c8a1f66c4f007bfd48e14b8c058252665177 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 13:14:25 +0900 Subject: [PATCH 0669/3664] Revert "Support taking the address of block expressions that have a result." This reverts commit c78d15b331f830118a27726b522765d985f94624. While a block expression's result may be an l-value, block expressions are not (and their results may not be), thus taking the address of one is not really correct. It seems the only place that tries to do so is the assignment code when dealing with structures. --- tools/qfcc/source/expr.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 70e4b2076..72624364c 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2226,10 +2226,6 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) return address_expr (e1->e.expr.e1, e2, t); } return error (e1, "invalid type for unary &"); - case ex_block: - if (!e1->e.block.result) - return error (e1, "invalid type for unary &"); - return address_expr (e1->e.block.result, e2, t); case ex_label: return new_label_ref (&e1->e.label); case ex_temp: From 51a30de9c560caf89403af1514cc2dcdecd1fe89 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 16:51:54 +0900 Subject: [PATCH 0670/3664] [qfcc] Print accurate linenos for more ICEs --- tools/qfcc/source/dags.c | 9 +++++---- tools/qfcc/source/flow.c | 6 +++--- tools/qfcc/source/statements.c | 13 +++++++------ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index a97b3e68c..ce4bd98cf 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -80,7 +80,7 @@ flush_daglabels (void) else if (op->op_type == op_label) op->o.label->daglabel = 0; else - internal_error (0, "unexpected operand type"); + internal_error (op->expr, "unexpected operand type"); } daglabel_chain = daglabel_chain->daglabel_chain; } @@ -186,7 +186,7 @@ operand_label (dag_t *dag, operand_t *op) label->op = op; op->o.label->daglabel = label; } else { - internal_error (0, "unexpected operand type: %d", op->op_type); + internal_error (op->expr, "unexpected operand type: %d", op->op_type); } return label; } @@ -498,7 +498,7 @@ dag_kill_aliases (daglabel_t *l) def_visit_all (op->o.def, 1, dag_def_kill_aliases_visit, l); } } else { - internal_error (0, "rvalue assignment?"); + internal_error (op->expr, "rvalue assignment?"); } } @@ -555,7 +555,8 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l) internal_error (0, "attempt to attach operator label to dagnode " "identifiers"); if (!op_is_identifier (l->op)) - internal_error (0, "attempt to attach non-identifer label to dagnode " + internal_error (l->op->expr, + "attempt to attach non-identifer label to dagnode " "identifiers"); if (l->dagnode) { // if the node is a leaf, then kill its value so no attempt is made diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index a1043df52..d3fa1d38f 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -280,9 +280,9 @@ flowvar_get_def (flowvar_t *var) case op_temp: return op->o.tempop.def; case op_alias: - internal_error (0, "unexpected alias operand"); + internal_error (op->expr, "unexpected alias operand"); } - internal_error (0, "oops, blue pill"); + internal_error (op->expr, "oops, blue pill"); return 0; } @@ -378,7 +378,7 @@ get_temp_address (function_t *func, operand_t *op) func->tmpaddr += top->size; } if (top->o.tempop.offset) { - internal_error (0, "real tempop with a non-zero offset"); + internal_error (top->expr, "real tempop with a non-zero offset"); } op->o.tempop.flowaddr = top->o.tempop.flowaddr + op->o.tempop.offset; return op->o.tempop.flowaddr; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e58294b00..d633d6434 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -207,7 +207,7 @@ print_operand (operand_t *op) case ev_void: case ev_invalid: case ev_type_count: - internal_error (0, "weird value type"); + internal_error (op->expr, "weird value type"); } break; case op_label: @@ -390,7 +390,7 @@ tempop_visit_all (tempop_t *tempop, int overlap, if (tempop->alias) { top = tempop->alias; if (top->op_type != op_temp) { - internal_error (0, "temp alias of non-temp operand"); + internal_error (top->expr, "temp alias of non-temp operand"); } tempop = &top->o.tempop; if ((ret = visit (tempop, data))) @@ -400,7 +400,7 @@ tempop_visit_all (tempop_t *tempop, int overlap, } for (top = tempop->alias_ops; top; top = top->next) { if (top->op_type != op_temp) { - internal_error (0, "temp alias of non-temp operand"); + internal_error (top->expr, "temp alias of non-temp operand"); } tempop = &top->o.tempop; if (tempop == start_tempop) @@ -419,8 +419,9 @@ alias_operand (type_t *type, operand_t *op, expr_t *expr) operand_t *aop; if (type_size (type) != type_size (op->type)) { - internal_error (0, "\naliasing operand with type of different size" - " (%d, %d)", type_size (type), type_size (op->type)); + internal_error (op->expr, + "aliasing operand with type of different size: %d, %d", + type_size (type), type_size (op->type)); } aop = new_operand (op_alias, expr); aop->o.alias = op; @@ -554,7 +555,7 @@ statement_get_targetlist (statement_t *s) target_list[0] = statement_get_target (s); } else if (statement_is_jumpb (s)) { if (table->alias) - internal_error (0, "aliased jump table"); + internal_error (s->opa->expr, "aliased jump table"); e = table->initializer->e.compound.head; //FIXME check!!! for (i = 0; i < count; e = e->next, i++) target_list[i] = e->expr->e.labelref.label->dest; From 7d5644e0553df6e453a28a1462cdcc10337dc711 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 17:44:08 +0900 Subject: [PATCH 0671/3664] [qfcc] Save operand creator return address --- tools/qfcc/include/statements.h | 2 ++ tools/qfcc/source/statements.c | 30 +++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index d1ccff441..dcb882d2b 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -58,6 +58,7 @@ typedef struct operand_s { struct type_s *type; ///< possibly override def's type int size; ///< for structures struct expr_s *expr; ///< expression generating this operand + void *return_addr; ///< who created this operand union { struct def_s *def; struct ex_value_s *value; @@ -126,6 +127,7 @@ int tempop_visit_all (tempop_t *tempop, int overlap, int (*visit) (tempop_t *, void *), void *data); operand_t *alias_operand (struct type_s *type, operand_t *op, struct expr_s *expr); +operand_t *label_operand (struct expr_s *label); void free_operand (operand_t *op); sblock_t *new_sblock (void); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index d633d6434..3b8c5b013 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -274,12 +274,13 @@ new_statement (st_type_t type, const char *opcode, expr_t *expr) } static operand_t * -new_operand (op_type_e op, expr_t *expr) +new_operand (op_type_e op, expr_t *expr, void *return_addr) { operand_t *operand; ALLOC (256, operand_t, operands, operand); operand->op_type = op; operand->expr = expr; + operand->return_addr = return_addr; return operand; } @@ -319,7 +320,7 @@ def_operand (def_t *def, type_t *type, expr_t *expr) if (!type) type = def->type; - op = new_operand (op_def, expr); + op = new_operand (op_def, expr, __builtin_return_address (0)); op->type = type; op->size = type_size (type); op->o.def = def; @@ -339,7 +340,7 @@ operand_t * value_operand (ex_value_t *value, expr_t *expr) { operand_t *op; - op = new_operand (op_value, expr); + op = new_operand (op_value, expr, __builtin_return_address (0)); op->type = value->type; op->o.value = value; return op; @@ -348,7 +349,7 @@ value_operand (ex_value_t *value, expr_t *expr) operand_t * temp_operand (type_t *type, expr_t *expr) { - operand_t *op = new_operand (op_temp, expr); + operand_t *op = new_operand (op_temp, expr, __builtin_return_address (0)); op->o.tempop.type = type; op->type = type; @@ -423,13 +424,26 @@ alias_operand (type_t *type, operand_t *op, expr_t *expr) "aliasing operand with type of different size: %d, %d", type_size (type), type_size (op->type)); } - aop = new_operand (op_alias, expr); + aop = new_operand (op_alias, expr, __builtin_return_address (0)); aop->o.alias = op; aop->type = type; aop->size = type_size (type); return aop; } +operand_t * +label_operand (expr_t *label) +{ + operand_t *lop; + + if (label->type != ex_label) { + internal_error (label, "not a label expression"); + } + lop = new_operand (op_label, label, __builtin_return_address (0)); + lop->o.label = &label->e.label; + return lop; +} + static operand_t * short_operand (short short_val, expr_t *expr) { @@ -595,8 +609,7 @@ statement_branch (sblock_t *sblock, expr_t *e) if (e->type == ex_uexpr && e->e.expr.op == 'g') { s = new_statement (st_flow, "", e); - s->opa = new_operand (op_label, e); - s->opa->o.label = &e->e.expr.e1->e.label; + s->opa = label_operand (e->e.expr.e1); } else { if (e->e.expr.op == 'g') { s = new_statement (st_flow, "", e); @@ -606,8 +619,7 @@ statement_branch (sblock_t *sblock, expr_t *e) opcode = convert_op (e->e.expr.op); s = new_statement (st_flow, opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - s->opb = new_operand (op_label, e); - s->opb->o.label = &e->e.expr.e2->e.label; + s->opb = label_operand (e->e.expr.e2); } } From eca976e5ae79cdb1928f9f9cba64e0464abd4f36 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 17:45:54 +0900 Subject: [PATCH 0672/3664] [qfcc] Expose l-value checking Needed for assignment chains. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/expr_assign.c | 33 +++++++++++++++++++++------------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 0efc998ba..39e405622 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -710,6 +710,7 @@ expr_t *build_for_statement (expr_t *init, expr_t *test, expr_t *next, expr_t *break_label, expr_t *continue_label); expr_t *build_state_expr (expr_t *e); expr_t *think_expr (struct symbol_s *think_sym); +int is_lvalue (const expr_t *expr) __attribute__((pure)); expr_t *assign_expr (expr_t *dst, expr_t *src); expr_t *cast_expr (struct type_s *t, expr_t *e); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 465746983..88d45ad7b 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -81,8 +81,8 @@ check_assign_logic_precedence (expr_t *dst, expr_t *src) return 0; } -static expr_t * -check_valid_lvalue (expr_t *expr) +int +is_lvalue (const expr_t *expr) { switch (expr->type) { case ex_symbol: @@ -90,7 +90,7 @@ check_valid_lvalue (expr_t *expr) case sy_name: break; case sy_var: - return 0; + return 1; case sy_const: break; case sy_type: @@ -106,21 +106,21 @@ check_valid_lvalue (expr_t *expr) } break; case ex_temp: - return 0; + return 1; case ex_expr: if (expr->e.expr.op == '.') { - return 0; + return 1; } if (expr->e.expr.op == 'A') { - return check_valid_lvalue (expr->e.expr.e1); + return is_lvalue (expr->e.expr.e1); } break; case ex_uexpr: if (expr->e.expr.op == '.') { - return 0; + return 1; } if (expr->e.expr.op == 'A') { - return check_valid_lvalue (expr->e.expr.e1); + return is_lvalue (expr->e.expr.e1); } break; case ex_memset: @@ -136,11 +136,20 @@ check_valid_lvalue (expr_t *expr) case ex_error: break; } - if (options.traditional) { - warning (expr, "invalid lvalue in assignment"); - return 0; + return 0; +} + +static expr_t * +check_valid_lvalue (expr_t *expr) +{ + if (!is_lvalue (expr)) { + if (options.traditional) { + warning (expr, "invalid lvalue in assignment"); + return 0; + } + return error (expr, "invalid lvalue in assignment"); } - return error (expr, "invalid lvalue in assignment"); + return 0; } static expr_t * From 97e0c235295dc6f932edc170a7d0ae6c7cc1b44a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 17:47:23 +0900 Subject: [PATCH 0673/3664] [qfcc] Create a nil operand This is for struct assignments so they can pass the source operand back up the assignment chain. --- tools/qfcc/include/statements.h | 4 +++- tools/qfcc/source/emit.c | 2 ++ tools/qfcc/source/flow.c | 2 ++ tools/qfcc/source/statements.c | 18 ++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index dcb882d2b..7a0b241ed 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -38,6 +38,7 @@ typedef enum { op_label, op_temp, op_alias, + op_nil, } op_type_e; typedef struct { @@ -55,7 +56,7 @@ typedef struct { typedef struct operand_s { struct operand_s *next; op_type_e op_type; - struct type_s *type; ///< possibly override def's type + struct type_s *type; ///< possibly override def's/nil's type int size; ///< for structures struct expr_s *expr; ///< expression generating this operand void *return_addr; ///< who created this operand @@ -117,6 +118,7 @@ struct dstring_s; const char *optype_str (op_type_e type) __attribute__((const)); +operand_t *nil_operand (struct type_s *type, struct expr_s *expr); operand_t *def_operand (struct def_s *def, struct type_s *type, struct expr_s *expr); operand_t *return_operand (struct type_s *type, struct expr_s *expr); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 253502206..0073f3967 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -106,6 +106,8 @@ get_operand_def (expr_t *expr, operand_t *op) return op->o.tempop.def; case op_alias: return get_operand_def (expr, op->o.alias); + case op_nil: + internal_error (expr, "unexpected nil operand"); } return 0; } diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index d3fa1d38f..d3e82b7ce 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -281,6 +281,8 @@ flowvar_get_def (flowvar_t *var) return op->o.tempop.def; case op_alias: internal_error (op->expr, "unexpected alias operand"); + case op_nil: + internal_error (op->expr, "unexpected nil operand"); } internal_error (op->expr, "oops, blue pill"); return 0; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 3b8c5b013..c64640c2f 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -65,6 +65,8 @@ static const char *op_type_names[] = { "op_value", "op_label", "op_temp", + "op_alias", + "op_nil", }; const char * @@ -150,6 +152,8 @@ operand_string (operand_t *op) strcpy (buf, alias); return va ("alias(%s,%s)", pr_type_name[op->type->type], buf); } + case op_nil: + return va ("nil"); } return ("??"); } @@ -222,6 +226,10 @@ print_operand (operand_t *op) printf ("alias(%s,", pr_type_name[op->type->type]); print_operand (op->o.alias); printf (")"); + break; + case op_nil: + printf ("nil"); + break; } } @@ -313,6 +321,16 @@ free_sblock (sblock_t *sblock) FREE (sblocks, sblock); } +operand_t * +nil_operand (type_t *type, expr_t *expr) +{ + operand_t *op; + op = new_operand (op_nil, expr, __builtin_return_address (0)); + op->type = type; + op->size = type_size (type); + return op; +} + operand_t * def_operand (def_t *def, type_t *type, expr_t *expr) { From 025dd634936853a3d6fd673f85a53ea36a52bf70 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 17:48:53 +0900 Subject: [PATCH 0674/3664] [qfcc] Bubble right-hand assignee back up chain This fixes assignchain when not optimizing. There are problems in dags, though, with address expressions. --- tools/qfcc/source/statements.c | 114 ++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 38 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index c64640c2f..63ec29f15 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -646,6 +646,46 @@ statement_branch (sblock_t *sblock, expr_t *e) return sblock->next; } +static sblock_t * +expr_address (sblock_t *sblock, expr_t *e, operand_t **op) +{ + statement_t *s; + s = new_statement (st_expr, "&", e); + sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); + s->opc = temp_operand (e->e.expr.type, e); + sblock_add_statement (sblock, s); + *(op) = s->opc; + return sblock; +} + +static sblock_t * +operand_address (sblock_t *sblock, operand_t *reference, operand_t **op, + expr_t *e) +{ + statement_t *s; + + switch (reference->op_type) { + case op_def: + case op_temp: + case op_alias: + s = new_statement (st_expr, "&", e); + s->opa = reference; + s->opc = temp_operand (pointer_type (reference->type), e); + sblock_add_statement (sblock, s); + if (op) { + *(op) = s->opc; + } + return sblock; + case op_value: + case op_label: + case op_nil: + break; + } + internal_error ((*op)->expr, + "invalid operand type for operand address: %s", + op_type_names[reference->op_type]); +} + static __attribute__((pure)) int is_const_ptr (expr_t *e) { @@ -660,8 +700,6 @@ is_const_ptr (expr_t *e) static __attribute__((pure)) int is_indirect (expr_t *e) { - if (e->type == ex_block && e->e.block.result) - return is_indirect (e->e.block.result); if (e->type == ex_expr && e->e.expr.op == '.') return 1; if (!(e->type == ex_uexpr && e->e.expr.op == '.')) @@ -670,7 +708,7 @@ is_indirect (expr_t *e) } static sblock_t * -expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op) +expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) { statement_t *s; expr_t *dst_expr = e->e.expr.e1; @@ -680,7 +718,6 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op) unsigned count; expr_t *count_expr; operand_t *dst = 0; - operand_t *src = 0; operand_t *size = 0; static const char *opcode_sets[][2] = { {"", ""}, @@ -692,29 +729,44 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op) int need_ptr = 0; //operand_t *dummy; - //if (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { - // sblock = statement_subexpr (sblock, src_expr, &dummy); - //} - // follow the assignment chain to find the actual source expression - // (can't take the address of an assignment) - while (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { - src_expr = src_expr->e.expr.e2; - } - if (src_expr->type == ex_nil) { - // switch to memset because nil is type agnostic 0 + if ((src && src->op_type == op_nil) || src_expr->type == ex_nil) { + // switch to memset because nil is type agnostic 0 and structures + // can be any size src_expr = new_integer_expr (0); + sblock = statement_subexpr (sblock, src_expr, &src); opcode_set = opcode_sets[1]; + if (op) { + *op = nil_operand (dst_type, src_expr); + } if (is_indirect (dst_expr)) { - need_ptr = 1; - dst_expr = address_expr (dst_expr, 0, 0); + goto dereference_dst; } } else { + if (!src) { + // This is the very right-hand node of a non-nil assignment chain + // (there may be more chains somwhere within src_expr, but they + // are not part of this chain as they are separated by another + // expression). + sblock = statement_subexpr (sblock, src_expr, &src); + } + // send the source operand back up through the assignment chain + // before modifying src if its address is needed + if (op) { + *op = src; + } if (is_indirect (dst_expr) || is_indirect (src_expr)) { - need_ptr = 1; - dst_expr = address_expr (dst_expr, 0, 0); - src_expr = address_expr (src_expr, 0, 0); + sblock = operand_address (sblock, src, &src, src_expr); + goto dereference_dst; } } + if (0) { +dereference_dst: + // dst_expr is a dereferenced pointer, so need to un-dereference it + // to get the pointer and switch to storep instructions. + dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); + need_ptr = 1; + } + sblock = statement_subexpr (sblock, dst_expr, &dst); if (type_size (dst_type) != type_size (src_type)) { bug (e, "dst and src sizes differ in expr_assign_copy: %d %d", @@ -726,6 +778,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op) } else { count_expr = expr_file_line (new_integer_expr (count), e); } + sblock = statement_subexpr (sblock, count_expr, &size); if (count < max_count && !need_ptr) { opcode = opcode_set[0]; @@ -734,9 +787,6 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op) } s = new_statement (st_move, opcode, e); - sblock = statement_subexpr (sblock, dst_expr, &dst); - sblock = statement_subexpr (sblock, src_expr, &src); - sblock = statement_subexpr (sblock, count_expr, &size); s->opa = src; s->opb = size; s->opc = dst; @@ -760,7 +810,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) if (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { sblock = statement_subexpr (sblock, src_expr, &src); if (is_structural (dst_type)) { - return expr_assign_copy (sblock, e, op); + return expr_assign_copy (sblock, e, op, src); } if (is_indirect (dst_expr)) { goto dereference_dst; @@ -769,7 +819,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) } } else { if (is_structural (dst_type)) { - return expr_assign_copy (sblock, e, op); + return expr_assign_copy (sblock, e, op, src); } if (is_indirect (dst_expr)) { @@ -797,7 +847,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) dereference_dst: // dst_expr is a dereferenced pointer, so need to un-dereference it // to get the pointer and switch to storep instructions. - dst_expr = address_expr (dst_expr, 0, 0); + dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); opcode = ".="; // FIXME find a nicer representation (lose strings?) if (dst_expr->type == ex_expr && !is_const_ptr (dst_expr->e.expr.e1)) { sblock = statement_subexpr (sblock, dst_expr->e.expr.e1, &dst); @@ -939,18 +989,6 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) return sblock->next; } -static sblock_t * -expr_address (sblock_t *sblock, expr_t *e, operand_t **op) -{ - statement_t *s; - s = new_statement (st_expr, "&", e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - s->opc = temp_operand (e->e.expr.type, e); - sblock_add_statement (sblock, s); - *(op) = s->opc; - return sblock; -} - static statement_t * lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) { @@ -1318,7 +1356,7 @@ expr_nil (sblock_t *sblock, expr_t *e, operand_t **op) *op = value_operand (new_nil_val (nil), e); return sblock; } - ptr = address_expr (new_temp_def_expr (nil), 0, 0); + ptr = expr_file_line (address_expr (new_temp_def_expr (nil), 0, 0), e); expr_file_line (ptr, e); sblock = statement_subexpr (sblock, ptr, op); e = expr_file_line (new_memset_expr (ptr, new_integer_expr (0), nil), e); From 72f4b8ccb5402de8e3d5d821882b0be2aa6c55e1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 19:26:47 +0900 Subject: [PATCH 0675/3664] [qfcc] Give address operands a good expression That is, those created by operand_address. The dag code needs the expression that is attached to the statement to have the correct expression type in order to do the right thing with the operands and aliasing, especially when generating temps. This fixes assignchain when optimizing (all tests pass again). --- tools/qfcc/include/expr.h | 2 +- tools/qfcc/source/statements.c | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 39e405622..170fc7a50 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -401,7 +401,7 @@ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2); /** Create a new unary expression node node. If \a e1 is an error expression, then it will be returned instead of a - new binary expression. + new unary expression. \param op The op-code of the unary expression. \param e1 The "right" side of the expression. diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 63ec29f15..0b2337b0b 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -663,14 +663,22 @@ operand_address (sblock_t *sblock, operand_t *reference, operand_t **op, expr_t *e) { statement_t *s; + type_t *type; switch (reference->op_type) { case op_def: case op_temp: case op_alias: + // build an address expression so dags can extract the correct + // type. address_expr cannot be used because reference might not + // be something it likes + e = expr_file_line (new_unary_expr ('&', e), e); + type = pointer_type (reference->type); + e->e.expr.type = type; + s = new_statement (st_expr, "&", e); s->opa = reference; - s->opc = temp_operand (pointer_type (reference->type), e); + s->opc = temp_operand (type, e); sblock_add_statement (sblock, s); if (op) { *(op) = s->opc; From 877ad35a82f0eaf50988527eac7c351d140234b9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 19:45:07 +0900 Subject: [PATCH 0676/3664] [qwaq] Rework the hierarchy again It doesn't work right now because View unconditionally sends refresh to its textContext, but textContext can be a draw buffer which does not respond to refresh. Still, these changes (notably the assignment chain in qwaq-group.r really pushed qfcc). --- ruamoko/qwaq/qwaq-app.h | 11 +++++++---- ruamoko/qwaq/qwaq-app.r | 15 ++++++++------- ruamoko/qwaq/qwaq-group.h | 3 ++- ruamoko/qwaq/qwaq-group.r | 17 +++++++++-------- ruamoko/qwaq/qwaq-screen.h | 1 - ruamoko/qwaq/qwaq-screen.r | 12 +++--------- ruamoko/qwaq/qwaq-view.h | 1 + ruamoko/qwaq/qwaq-view.r | 4 ++++ 8 files changed, 34 insertions(+), 30 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index d8b899624..7062ad096 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -1,18 +1,21 @@ #ifndef __qwaq_app_h #define __qwaq_app_h +#include + #include "event.h" -#include "qwaq-group.h" -@class Screen; +@class Group; -@interface QwaqApplication: Group +@interface QwaqApplication: Object { qwaq_event_t event; qwaq_command endState; - Screen *screen; + + Group *objects; } -run; +-draw; -handleEvent: (qwaq_event_t *) event; @end diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index fffe51c7b..5b5889768 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -38,16 +38,17 @@ arp_end (void) init_pair (1, COLOR_WHITE, COLOR_BLUE); init_pair (2, COLOR_WHITE, COLOR_BLACK); - screen = [[Screen screen] retain]; - [self insert:screen]; - [screen setBackground: COLOR_PAIR (1)]; - Rect r = *[screen getRect]; + TextContext *screen = [TextContext screen]; + objects = [[Group alloc] initWithContext: screen]; + + [screen bkgd: COLOR_PAIR (1)]; + Rect r = { nil, [screen size] }; r.offset.x = r.extent.width / 4; r.offset.y = r.extent.height / 4; r.extent.width /= 2; r.extent.height /= 2; Window *w; - [self insert: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; + [objects insert: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; //wprintf (w.window, "%d %d %d %d\n", r.offset.x, r.offset.y, r.extent.width, r.ylen); return self; } @@ -70,14 +71,14 @@ arp_end (void) -draw { - [super draw]; + [objects draw]; [TextContext refresh]; return self; } -handleEvent: (qwaq_event_t *) event { - [screen handleEvent: event]; + [objects handleEvent: event]; if (event.what == qe_key && event.key == '\x18') { event.what = qe_command; event.message.command = qc_exit; diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index b599a0c36..be251b243 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -31,8 +31,9 @@ typedef BOOL condition_func2 (id object, void *anObject, void *data); { Array *views; int focused; - TextContext *buffer; + id buffer; //FIXME id or sim } +-initWithContext: (id) context; //FIXME id or sim -insert: (View *) view; -remove: (View *) view; @end diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 6b8296182..57a5eb8a6 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -66,11 +66,16 @@ @end @implementation Group --init + +-initWithContext: (id) context { if (!(self = [super init])) { return nil; } + textContext = context; + absRect = rect = { nil, [textContext size] }; + printf ("\n\nsize:%d %d\n\n", rect.extent.width, rect.extent.height); + buffer = [DrawBuffer buffer: rect.extent]; views = [[Array array] retain]; return self; } @@ -92,6 +97,7 @@ -insert: (View *) view { [views addObject: view]; + view.textContext = buffer; return self; } @@ -114,13 +120,8 @@ not_dont_draw (id aView, void *aGroup) { View *view = aView; Group *group = (Group *) aGroup; - if (!(view.options & ofDontDraw)) { - if (!view.textContext) { - view.textContext = group.buffer; - } - return YES; - } - return NO; + + return !(view.options & ofDontDraw); } -draw diff --git a/ruamoko/qwaq/qwaq-screen.h b/ruamoko/qwaq/qwaq-screen.h index c51910d0e..9ec2ba8f3 100644 --- a/ruamoko/qwaq/qwaq-screen.h +++ b/ruamoko/qwaq/qwaq-screen.h @@ -10,7 +10,6 @@ } +(Screen *) screen; -handleEvent: (qwaq_event_t *) event; --setBackground: (int) ch; @end #endif//__qwaq_screen_h diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index 5b2db43ce..16d3f1be6 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -29,20 +29,14 @@ -draw { - update_panels (); - [TextContext doupdate]; return self; } -redraw { - [textContext refresh]; - return self; -} - --setBackground: (int) ch -{ - [textContext bkgd:ch]; + //update_panels (); + [TextContext refresh]; + //[TextContext doupdate]; return self; } diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 086b9d12d..e6b5bd47e 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -57,6 +57,7 @@ enum { -(struct Rect_s *)getRect; -draw; -redraw; +-handleEvent: (qwaq_event_t *) event; - (void) refresh; - (void) mvprintf: (Point) pos, string fmt, ...; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 19df51b9c..b005dd4de 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -126,5 +126,9 @@ updateScreenCursor (View *view) [textContext mvaddch: pos, ch]; } +-handleEvent: (qwaq_event_t *) event +{ + return self; +} @end From fea6381574f888cd625823a523c14070fe99bd49 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 20:44:43 +0900 Subject: [PATCH 0677/3664] [gamecode] Rework debug type handling a little Type encodings are used whenever they are available. For now, if they are not, then everything is treated as void (which prints , not very useful). Most return statements and references to .return are now very readable (excluding structs), and only params going through "..." are a messy union. --- include/QF/pr_type.h | 2 +- libs/gamecode/pr_debug.c | 93 ++++++++++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index c7fbc4b9c..c9e45185c 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -109,7 +109,7 @@ typedef struct qfot_type_s { typedef struct qfot_type_encodings_s { pointer_t types; - pr_int_t size; + pr_uint_t size; } qfot_type_encodings_t; ///@} diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 9464c326c..979400244 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -83,6 +83,8 @@ typedef struct prdeb_resources_s { struct pr_lineno_s *linenos; pr_def_t *local_defs; pr_def_t *type_encodings_def; + qfot_type_t void_type; + qfot_type_t *type_encodings[ev_type_count]; } prdeb_resources_t; typedef struct { @@ -352,6 +354,10 @@ pr_debug_clear (progs_t *pr, void *data) pr->watch = 0; pr->wp_conditional = 0; pr->wp_val.integer_var = 0; + + for (int i = 0; i < ev_type_count; i++ ) { + res->type_encodings[i] = &res->void_type; + } } static file_t * @@ -420,7 +426,10 @@ PR_LoadDebug (progs_t *pr) pr_uint_t i; pr_def_t *def; pr_type_t *str = 0; + qfot_type_encodings_t *encodings = 0; pointer_t type_encodings = 0; + pointer_t type_ptr; + qfot_type_t *type; if (!pr_debug->int_val) return 1; @@ -508,8 +517,8 @@ PR_LoadDebug (progs_t *pr) } res->type_encodings_def = PR_FindGlobal (pr, ".type_encodings"); if (res->type_encodings_def) { - __auto_type encodings = &G_STRUCT (pr, qfot_type_encodings_t, - res->type_encodings_def->ofs); + encodings = &G_STRUCT (pr, qfot_type_encodings_t, + res->type_encodings_def->ofs); type_encodings = encodings->types; } for (i = 0; i < res->debug->num_locals; i++) { @@ -523,6 +532,16 @@ PR_LoadDebug (progs_t *pr) res->local_defs[i].type_encoding += type_encodings; } } + if (encodings) { + for (type_ptr = 4; type_ptr < encodings->size; + type_ptr += type->size) { + type = &G_STRUCT (pr, qfot_type_t, type_encodings + type_ptr); + if (type->meta == ty_basic + && type->t.type >= 0 && type->t.type < ev_type_count) { + res->type_encodings[type->t.type] = type; + } + } + } return 1; } @@ -729,19 +748,15 @@ get_aux_function (progs_t *pr) return res->auxfunction_map[func - pr->pr_functions]; } -static etype_t -get_etype (progs_t *pr, int typeptr) +static qfot_type_t * +get_type (prdeb_resources_t *res, int typeptr) { - qfot_type_t *type; + progs_t *pr = res->pr; if (!typeptr) { - return ev_void; + return &res->void_type; } - type = &G_STRUCT (pr, qfot_type_t, typeptr); - if (type->meta == ty_basic) { - return type->t.type; - } - return ev_void; + return &G_STRUCT (pr, qfot_type_t, typeptr); } pr_def_t * @@ -881,19 +896,19 @@ pr_debug_find_def (progs_t *pr, pr_int_t ofs) } static const char * -global_string (pr_debug_data_t *data, pointer_t ofs, etype_t etype, +global_string (pr_debug_data_t *data, pointer_t ofs, qfot_type_t *type, int contents) { progs_t *pr = data->pr; + prdeb_resources_t *res = pr->pr_debug_resources; dstring_t *dstr = data->dstr; pr_def_t *def = NULL; qfot_type_t dummy_type = { }; - qfot_type_t *type; const char *name = 0; dstring_clearstr (dstr); - if (etype == ev_short) { + if (type && type->meta == ty_basic && type->t.type == ev_short) { dsprintf (dstr, "%04x", (short) ofs); return dstr->str; } @@ -919,16 +934,17 @@ global_string (pr_debug_data_t *data, pointer_t ofs, etype_t etype, if (name) { dstring_appendstr (dstr, "("); } - if (def) { - if (!def->type_encoding) { - dummy_type.t.type = def->type; - type = &dummy_type; + if (!type) { + if (def) { + if (!def->type_encoding) { + dummy_type.t.type = def->type; + type = &dummy_type; + } else { + type = &G_STRUCT (pr, qfot_type_t, def->type_encoding); + } } else { - type = &G_STRUCT (pr, qfot_type_t, def->type_encoding); + type = &res->void_type; } - } else { - dummy_type.t.type = etype; - type = &dummy_type; } value_string (data, type, pr->pr_globals + ofs); if (name) { @@ -1118,7 +1134,7 @@ pr_debug_short_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%d", (short)value->integer_var); + dasprintf (dstr, "%04x", (short)value->integer_var); } static void @@ -1232,8 +1248,9 @@ PR_Debug_Print (progs_t *pr, const char *expr) } print = parse_expression (pr, expr, 0); - if (print.type != ev_invalid) { - const char *s = global_string (&data, print.ofs, print.type, 1); + if (print.type_encoding) { + qfot_type_t *type = get_type (res, print.type_encoding); + const char *s = global_string (&data, print.ofs, type, 1); Sys_Printf ("[%d] = %s\n", print.ofs, s); } } @@ -1300,7 +1317,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) char mode = fmt[1], opchar = fmt[2]; unsigned parm_ind = 0; pr_int_t opval; - etype_t optype = ev_void; + qfot_type_t *optype = ev_void; func_t func; if (mode == 'P') { @@ -1314,15 +1331,15 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) switch (opchar) { case 'a': opval = s->a; - optype = op->type_a; + optype = res->type_encodings[op->type_a]; break; case 'b': opval = s->b; - optype = op->type_b; + optype = res->type_encodings[op->type_b]; break; case 'c': opval = s->c; - optype = op->type_c; + optype = res->type_encodings[op->type_c]; break; case 'x': if (mode == 'P') { @@ -1337,8 +1354,9 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) case 'R': optype = ev_void; aux_func = get_aux_function (pr); - if (aux_func) - optype = get_etype (pr, aux_func->return_type); + if (aux_func) { + optype = get_type (res, aux_func->return_type); + } str = global_string (&data, opval, optype, contents & 1); break; @@ -1353,8 +1371,9 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) case 'P': parm_def = PR_Get_Param_Def (pr, call_func, parm_ind); optype = ev_void; - if (parm_def) - optype = parm_def->type; + if (parm_def) { + optype = get_type (res, parm_def->type_encoding); + } str = global_string (&data, opval, optype, contents & 1); break; @@ -1561,6 +1580,14 @@ PR_Debug_Init (progs_t *pr) res->line = dstring_newstr (); res->dstr = dstring_newstr (); + res->void_type.meta = ty_basic; + res->void_type.size = 4; + res->void_type.encoding = 0; + res->void_type.t.type = ev_void; + for (int i = 0; i < ev_type_count; i++ ) { + res->type_encodings[i] = &res->void_type; + } + PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); if (!file_hash) { file_hash = Hash_NewTable (1024, file_get_key, file_free, 0); From 9492f08536908e3ed01486d2dafe8e3312da9ddc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 21:03:01 +0900 Subject: [PATCH 0678/3664] [gamecode] Print structs as well as unions Much better :) --- libs/gamecode/pr_debug.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 979400244..c59a3968a 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1147,16 +1147,8 @@ pr_debug_double_view (qfot_type_t *type, pr_type_t *value, void *_data) } static void -pr_debug_struct_view (qfot_type_t *type, pr_type_t *value, void *_data) -{ - __auto_type data = (pr_debug_data_t *) _data; - dstring_t *dstr = data->dstr; - - dstring_appendstr (dstr, ""); -} - -static void -pr_debug_union_view (qfot_type_t *type, pr_type_t *value, void *_data) +pr_dump_struct (qfot_type_t *type, pr_type_t *value, void *_data, + const char *struct_type) { __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; @@ -1170,12 +1162,23 @@ pr_debug_union_view (qfot_type_t *type, pr_type_t *value, void *_data) pr_type_t *val = value + field->offset; dasprintf (dstr, "%s=", PR_GetString (pr, field->name)); value_string (data, val_type, val); - if (i < strct->num_fields) { + if (i < strct->num_fields - 1) { dstring_appendstr (dstr, ", "); } } dstring_appendstr (dstr, "}"); - dstring_appendstr (dstr, ""); + //dasprintf (dstr, "<%s>", struct_type); +} +static void +pr_debug_struct_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + pr_dump_struct (type, value, _data, "struct"); +} + +static void +pr_debug_union_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + pr_dump_struct (type, value, _data, "union"); } static void From 327d6929928741711673ecda854232825e24cbe7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 22:04:33 +0900 Subject: [PATCH 0679/3664] [qfcc] Correct order of @zero fields This is part of what messed up float_val in the encoding for @params. The other part is something in the linker type encoding merge code: it may be too aggressive. It's also what messed up the size of @params. --- tools/qfcc/source/type.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 1c21e1d62..cdf7ca6df 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -937,7 +937,6 @@ init_types (void) { static struct_def_t zero_struct[] = { {"string_val", &type_string}, - {"double_val", &type_double}, {"float_val", &type_float}, {"entity_val", &type_entity}, {"field_val", &type_field}, @@ -949,6 +948,7 @@ init_types (void) {"integer_val", &type_integer}, {"uinteger_val", &type_uinteger}, {"quaternion_val", &type_quaternion}, + {"double_val", &type_double}, {0, 0} }; static struct_def_t param_struct[] = { From 20fd5eb80c6d580e2533f1ca9e95e18ab676dd0a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 22:07:36 +0900 Subject: [PATCH 0680/3664] [qfcc] Show def size when dumping defs --- tools/qfcc/source/dump_globals.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 157635f63..9b5900454 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -153,8 +153,9 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) break; } } - printf ("%*s %x %d %s %s:%x %s\n", indent * 12, "", - offset, saveglobal, name, type, def->type_encoding, comment); + printf ("%*s %x:%d %d %s %s:%x %s\n", indent * 12, "", + offset, def->size, saveglobal, name, type, def->type_encoding, + comment); } void From 067bc264fafc175c314fb53d5d3d81cfa661a394 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 22:08:27 +0900 Subject: [PATCH 0681/3664] [qfcc] Set local def size in debug sym file It was getting random garbage. Not good for debuggers. --- tools/qfcc/source/obj_file.c | 1 + tools/qfcc/source/qfcc.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 6ceb1a74e..1a63eeea8 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -1172,6 +1172,7 @@ qfo_to_sym (qfo_t *qfo, int *size) aux->local_defs = ld - locals; for (j = 0; j < num_locals; j++, def++, ld++) { ld->type = get_def_type (qfo, def->type); + ld->size = get_type_size (qfo, def->type); ld->ofs = def->offset; ld->name = def->name; ld->type_encoding = def->type; diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 6a7e1a039..7d0f8c800 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -448,7 +448,12 @@ finish_link (void) } else { int size; dprograms_t *progs; + pr_debug_header_t *sym = 0; + int sym_size = 0; + if (options.code.debug) { + sym = qfo_to_sym (qfo, &sym_size); + } progs = qfo_to_progs (qfo, &size); //finish_compilation (); @@ -462,9 +467,6 @@ finish_link (void) WriteProgs (progs, size); if (options.code.debug) { - pr_debug_header_t *sym; - int sym_size = 0; - sym = qfo_to_sym (qfo, &sym_size); sym->crc = CRC_Block ((byte *) progs, size); WriteSym (sym, sym_size); } From 2f9f6d3aa9a8f2c671559fb5f9d108b348aafc54 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 Mar 2020 23:38:22 +0900 Subject: [PATCH 0682/3664] [gamecode] Relocate aux function return types They are written with offsets relative to the type encodings base. --- libs/gamecode/pr_debug.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index c59a3968a..31589e1e1 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -496,6 +496,12 @@ PR_LoadDebug (progs_t *pr) for (i = 0; i < pr->progs->numfunctions; i++) res->auxfunction_map[i] = 0; + res->type_encodings_def = PR_FindGlobal (pr, ".type_encodings"); + if (res->type_encodings_def) { + encodings = &G_STRUCT (pr, qfot_type_encodings_t, + res->type_encodings_def->ofs); + type_encodings = encodings->types; + } for (i = 0; i < res->debug->num_auxfunctions; i++) { res->auxfunctions[i].function = LittleLong (res->auxfunctions[i].function); @@ -508,6 +514,9 @@ PR_LoadDebug (progs_t *pr) res->auxfunctions[i].num_locals = LittleLong (res->auxfunctions[i].num_locals); + if (type_encodings) { + res->auxfunctions[i].return_type += type_encodings; + } res->auxfunction_map[res->auxfunctions[i].function] = &res->auxfunctions[i]; } @@ -515,12 +524,6 @@ PR_LoadDebug (progs_t *pr) res->linenos[i].fa.func = LittleLong (res->linenos[i].fa.func); res->linenos[i].line = LittleLong (res->linenos[i].line); } - res->type_encodings_def = PR_FindGlobal (pr, ".type_encodings"); - if (res->type_encodings_def) { - encodings = &G_STRUCT (pr, qfot_type_encodings_t, - res->type_encodings_def->ofs); - type_encodings = encodings->types; - } for (i = 0; i < res->debug->num_locals; i++) { res->local_defs[i].type = LittleShort (res->local_defs[i].type); res->local_defs[i].size = LittleShort (res->local_defs[i].size); @@ -1320,7 +1323,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) char mode = fmt[1], opchar = fmt[2]; unsigned parm_ind = 0; pr_int_t opval; - qfot_type_t *optype = ev_void; + qfot_type_t *optype = &res->void_type; func_t func; if (mode == 'P') { @@ -1355,7 +1358,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) } switch (mode) { case 'R': - optype = ev_void; + optype = &res->void_type; aux_func = get_aux_function (pr); if (aux_func) { optype = get_type (res, aux_func->return_type); @@ -1373,7 +1376,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) break; case 'P': parm_def = PR_Get_Param_Def (pr, call_func, parm_ind); - optype = ev_void; + optype = &res->void_type; if (parm_def) { optype = get_type (res, parm_def->type_encoding); } From 9a08a51ebdcc61e12377b40593364f653606920b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 Mar 2020 01:32:38 +0900 Subject: [PATCH 0683/3664] [qfcc] Ensure progs defs are sorted by address --- tools/qfcc/source/obj_file.c | 50 +++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 1a63eeea8..45d01be47 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -31,6 +31,8 @@ # include "config.h" #endif +#define _GNU_SOURCE // for qsort_r + #ifdef HAVE_STRING_H # include #endif @@ -860,6 +862,17 @@ align_globals_size (unsigned size) return RUP (size, 16 / sizeof (pr_type_t)); } +static int +qfo_def_compare (const void *i1, const void *i2, void *d) +{ + __auto_type defs = (const qfo_def_t *) d; + unsigned ind1 = *(unsigned *) i1; + unsigned ind2 = *(unsigned *) i2; + const qfo_def_t *def1 = defs + ind1; + const qfo_def_t *def2 = defs + ind2; + return def1->offset - def2->offset; +} + dprograms_t * qfo_to_progs (qfo_t *qfo, int *size) { @@ -887,6 +900,9 @@ qfo_to_progs (qfo_t *qfo, int *size) int big_func = 0; pr_xdefs_t *xdefs = 0; xdef_t *xdef; + unsigned *def_indices; + unsigned *far_def_indices; + unsigned *field_def_indices; *size = RUP (sizeof (dprograms_t), 16); progs = calloc (1, *size); @@ -895,7 +911,7 @@ qfo_to_progs (qfo_t *qfo, int *size) progs->numglobaldefs = qfo->spaces[qfo_near_data_space].num_defs; //ddef offsets are 16 bits so the ddef ofs will likely be invalid //thus it will be forced invalid and the true offset written to the - //symbols file if it is created (fa + //.xdefs array in the progs file progs->numglobaldefs += qfo->spaces[qfo_far_data_space].num_defs; progs->numfielddefs = qfo->spaces[qfo_entity_space].num_defs; progs->numfunctions = qfo->num_funcs + 1; @@ -936,6 +952,29 @@ qfo_to_progs (qfo_t *qfo, int *size) memset (progs + 1, 0, *size - sizeof (dprograms_t)); data += RUP (sizeof (dprograms_t), 16); + def_indices = alloca ((progs->numglobaldefs + progs->numfielddefs) + * sizeof (*def_indices)); + far_def_indices = def_indices + qfo->spaces[qfo_near_data_space].num_defs; + field_def_indices = def_indices + progs->numglobaldefs; + for (unsigned i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { + def_indices[i] = i; + } + for (unsigned i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { + far_def_indices[i] = i; + } + for (unsigned i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { + field_def_indices[i] = i; + } + qsort_r (def_indices, qfo->spaces[qfo_near_data_space].num_defs, + sizeof (unsigned), qfo_def_compare, + qfo->spaces[qfo_near_data_space].defs); + qsort_r (far_def_indices, qfo->spaces[qfo_far_data_space].num_defs, + sizeof (unsigned), qfo_def_compare, + qfo->spaces[qfo_far_data_space].defs); + qsort_r (field_def_indices, qfo->spaces[qfo_entity_space].num_defs, + sizeof (unsigned), qfo_def_compare, + qfo->spaces[qfo_entity_space].defs); + progs->ofs_strings = data - (byte *) progs; strings = (char *) data; data += RUP (progs->numstrings * sizeof (char), 16); @@ -992,7 +1031,8 @@ qfo_to_progs (qfo_t *qfo, int *size) } for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { - qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; + unsigned ind = def_indices[i]; + qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + ind; const char *defname = QFO_GETSTR (qfo, def->name); if (!strcmp (defname, ".type_encodings")) types_def = def; @@ -1002,7 +1042,8 @@ qfo_to_progs (qfo_t *qfo, int *size) } for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { - qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + i; + unsigned ind = far_def_indices[i]; + qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + ind; def->offset += far_data - globals; convert_def (qfo, def, globaldefs); // the correct offset will be written to the far data space @@ -1015,7 +1056,8 @@ qfo_to_progs (qfo_t *qfo, int *size) } for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { - convert_def (qfo, qfo->spaces[qfo_entity_space].defs + i, + unsigned ind = field_def_indices[i]; + convert_def (qfo, qfo->spaces[qfo_entity_space].defs + ind, fielddefs + i); } From 968de155a1c08fc2dd4e3f3e6836c42e26e33c20 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 Mar 2020 01:33:25 +0900 Subject: [PATCH 0684/3664] [qfcc] Make some counts unsigned How do you have -1 def? --- tools/qfcc/include/obj_file.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index ae1986245..62d7b80f0 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -60,13 +60,13 @@ */ typedef struct qfo_header_s { int8_t qfo[4]; ///< identifier string (includes nul) (#QFO) - pr_int_t version; ///< QFO format version (#QFO_VERSION) - pr_int_t num_spaces; - pr_int_t num_relocs; ///< number of relocation records - pr_int_t num_defs; ///< number of def records - pr_int_t num_funcs; ///< number of function records - pr_int_t num_lines; ///< number of line records - pr_int_t num_loose_relocs; ///< number of loose relocation records + pr_uint_t version; ///< QFO format version (#QFO_VERSION) + pr_uint_t num_spaces; + pr_uint_t num_relocs; ///< number of relocation records + pr_uint_t num_defs; ///< number of def records + pr_uint_t num_funcs; ///< number of function records + pr_uint_t num_lines; ///< number of line records + pr_uint_t num_loose_relocs; ///< number of loose relocation records ///< (included in num_relocs) } qfo_header_t; From 3d62a7f25377c3b31efedc3a3211146d1d156a5e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 Mar 2020 02:48:13 +0900 Subject: [PATCH 0685/3664] [gamecode] Use fuzzy bsearch to find defs by address The idea is to find th def that contains the address. Had to write my own bsearch (well... lifted from wikipedia) because libc's is exact. The defs are assumed to be sorted (which qfcc now ensures when it writes progs and sym files). --- include/QF/progs.h | 2 ++ libs/gamecode/pr_resolve.c | 42 ++++++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 2659ce303..7dc7e4af2 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -321,6 +321,8 @@ void ED_EntityParseFunction (progs_t *pr); */ ///@{ +pr_def_t *PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset) + __attribute__((pure)); pr_def_t *PR_FieldAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure)); pr_def_t *PR_GlobalAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure)); diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 5297f101a..03e6949a2 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -43,32 +43,38 @@ static const char param_str[] = ".param_0"; +pr_def_t * +PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset) +{ + // fuzzy bsearh + unsigned left = 0; + unsigned right = num_defs - 1; + unsigned mid; + + while (left != right) { + mid = (left + right + 1) / 2; + if (defs[mid].ofs > offset) { + right = mid - 1; + } else { + left = mid; + } + } + if (defs[left].ofs <= offset) { + return defs + left; + } + return 0; +} + pr_def_t * PR_GlobalAtOfs (progs_t * pr, pointer_t ofs) { - pr_def_t *def; - pr_uint_t i; - - for (i = 0; i < pr->progs->numglobaldefs; i++) { - def = &pr->pr_globaldefs[i]; - if (def->ofs == ofs) - return def; - } - return NULL; + return PR_SearchDefs (pr->pr_globaldefs, pr->progs->numglobaldefs, ofs); } VISIBLE pr_def_t * PR_FieldAtOfs (progs_t * pr, pointer_t ofs) { - pr_def_t *def; - pr_uint_t i; - - for (i = 0; i < pr->progs->numfielddefs; i++) { - def = &pr->pr_fielddefs[i]; - if (def->ofs == ofs) - return def; - } - return NULL; + return PR_SearchDefs (pr->pr_fielddefs, pr->progs->numfielddefs, ofs); } VISIBLE pr_def_t * From 99f89840f9290aeb465a4b2985ced2ce9f15add0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 Mar 2020 02:51:29 +0900 Subject: [PATCH 0686/3664] [gamecode] Show containing def and relative offset No more guessing when accessing structure field members. Next is ivars, I guess. --- include/QF/progs.h | 2 +- libs/gamecode/pr_debug.c | 70 ++++++++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 7dc7e4af2..c615e6d14 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1649,7 +1649,7 @@ pr_lineno_t *PR_Find_Lineno (progs_t *pr, pr_uint_t addr) __attribute__((pure)); const char *PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); const char *PR_Get_Source_Line (progs_t *pr, pr_uint_t addr); pr_def_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) __attribute__((pure)); -pr_def_t *PR_Get_Local_Def (progs_t *pr, pointer_t offs) __attribute__((pure)); +pr_def_t *PR_Get_Local_Def (progs_t *pr, pointer_t *offs) __attribute__((pure)); void PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents); void PR_DumpState (progs_t *pr); void PR_StackTrace (progs_t *pr); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 31589e1e1..d2ed5e7f1 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -763,12 +763,13 @@ get_type (prdeb_resources_t *res, int typeptr) } pr_def_t * -PR_Get_Local_Def (progs_t *pr, pointer_t offs) +PR_Get_Local_Def (progs_t *pr, pointer_t *offset) { prdeb_resources_t *res = pr->pr_debug_resources; - pr_uint_t i; dfunction_t *func; pr_auxfunction_t *aux_func; + pointer_t offs = *offset; + pr_def_t *def; if (!pr->pr_xfunction) return 0; @@ -781,10 +782,11 @@ PR_Get_Local_Def (progs_t *pr, pointer_t offs) offs -= func->parm_start; if (offs >= func->locals) return 0; - for (i = 0; i < aux_func->num_locals; i++) - if (res->local_defs[aux_func->local_defs + i].ofs == offs) - return &res->local_defs[aux_func->local_defs + i]; - return 0; + if ((def = PR_SearchDefs (res->local_defs + aux_func->local_defs, + aux_func->num_locals, offs))) { + *offset = offs - def->ofs; + } + return def; } VISIBLE void @@ -886,20 +888,28 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) } static pr_def_t * -pr_debug_find_def (progs_t *pr, pr_int_t ofs) +pr_debug_find_def (progs_t *pr, pointer_t *ofs) { prdeb_resources_t *res = pr->pr_debug_resources; pr_def_t *def = 0; - if (pr_debug->int_val && res->debug) + if (*ofs >= pr->progs->numglobals) { + return 0; + } + if (pr_debug->int_val && res->debug) { def = PR_Get_Local_Def (pr, ofs); - if (!def) - def = PR_GlobalAtOfs (pr, ofs); + } + if (!def) { + def = PR_GlobalAtOfs (pr, *ofs); + if (def) { + *ofs -= def->ofs; + } + } return def; } static const char * -global_string (pr_debug_data_t *data, pointer_t ofs, qfot_type_t *type, +global_string (pr_debug_data_t *data, pointer_t offset, qfot_type_t *type, int contents) { progs_t *pr = data->pr; @@ -908,29 +918,34 @@ global_string (pr_debug_data_t *data, pointer_t ofs, qfot_type_t *type, pr_def_t *def = NULL; qfot_type_t dummy_type = { }; const char *name = 0; + pointer_t offs = offset; dstring_clearstr (dstr); if (type && type->meta == ty_basic && type->t.type == ev_short) { - dsprintf (dstr, "%04x", (short) ofs); + dsprintf (dstr, "%04x", (short) offset); return dstr->str; } - if (ofs > pr->globals_size) { - dsprintf (dstr, "%08x out of bounds", ofs); + if (offset > pr->globals_size) { + dsprintf (dstr, "%08x out of bounds", offset); return dstr->str; } - def = pr_debug_find_def (pr, ofs); + def = pr_debug_find_def (pr, &offs); if (!def || !PR_StringValid (pr, def->name) || !*(name = PR_GetString (pr, def->name))) { - dsprintf (dstr, "[$%x]", ofs); + dsprintf (dstr, "[$%x]", offset); } if (name) { if (strequal (name, "IMMEDIATE") || strequal (name, ".imm")) { contents = 1; } else { - dsprintf (dstr, "%s", name); + if (offs) { + dsprintf (dstr, "{%s + %u}", name, offs); + } else { + dsprintf (dstr, "%s", name); + } } } if (contents) { @@ -949,7 +964,7 @@ global_string (pr_debug_data_t *data, pointer_t ofs, qfot_type_t *type, type = &res->void_type; } } - value_string (data, type, pr->pr_globals + ofs); + value_string (data, type, pr->pr_globals + offset); if (name) { dstring_appendstr (dstr, ")"); } @@ -1084,21 +1099,20 @@ pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; - prdeb_resources_t *res = pr->pr_debug_resources; //FIXME dstring_t *dstr = data->dstr; - pointer_t ofs = value->integer_var; + pointer_t offset = value->integer_var; + pointer_t offs = offset; pr_def_t *def = 0; - if (pr_debug->int_val && res->debug) { - def = PR_Get_Local_Def (pr, ofs); - } - if (!def) { - def = PR_GlobalAtOfs (pr, ofs); - } + def = pr_debug_find_def (pr, &offs); if (def && def->name) { - dasprintf (dstr, "&%s", PR_GetString (pr, def->name)); + if (offs) { + dasprintf (dstr, "&%s + %u", PR_GetString (pr, def->name), offs); + } else { + dasprintf (dstr, "&%s", PR_GetString (pr, def->name)); + } } else { - dasprintf (dstr, "[$%x]", ofs); + dasprintf (dstr, "[$%x]", offset); } } From e3a1413ad3b1a30eb4ee9d8be23044548fd31116 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 Mar 2020 10:06:37 +0900 Subject: [PATCH 0687/3664] [gamecode] Tweak output for lea --- libs/gamecode/pr_opcode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 3d3e8fe17..30ad8b06e 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -544,12 +544,12 @@ VISIBLE const opcode_t pr_opcodes[] = { {"&", "lea", OP_LEA, false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, - "%Ga, %Gb, %gc", + "(%Ga + %Gb), %gc", }, {"&", "leai", OP_LEAI, false, ev_pointer, ev_short, ev_pointer, PROG_VERSION, - "%Ga, %sb, %gc", + "(%Ga + %sb), %gc", }, {"", "conv.if", OP_CONV_IF, false, From e1140d476aa3f9c14cfa13ee1cc8e918fdc3fd24 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 Mar 2020 16:19:45 +0900 Subject: [PATCH 0688/3664] [qfcc] Handle syntax errors in method protos --- tools/qfcc/source/qc-parse.y | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 6ca42392c..7f257505b 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -2020,6 +2020,10 @@ methodproto $2->instance = 0; $$ = $2; } + | '-' error ';' + { $$ = new_method (&type_id, new_param ("", 0, 0), 0); } + | '+' error ';' + { $$ = new_method (&type_id, new_param ("", 0, 0), 0); } | '-' methoddecl ';' { $2->instance = 1; From fb33a7f2a7df64dec778ba55eaedb987f894712b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 Mar 2020 20:27:43 +0900 Subject: [PATCH 0689/3664] [qfcc] Remove "impossible" code It is not possible to adorn Class with protocols, so no need to check for them when checking if a type is a class. --- tools/qfcc/include/class.h | 2 +- tools/qfcc/source/class.c | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index 7f7f0920d..a468e19b5 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -116,7 +116,7 @@ struct symbol_s; int obj_is_id (const struct type_s *type) __attribute__((pure)); int obj_is_class (const struct type_s *type) __attribute__((pure)); -int obj_is_Class (const struct type_s *type) __attribute__((pure)); +int obj_is_Class (const struct type_s *type) __attribute__((const)); int obj_is_classptr (const struct type_s *type) __attribute__((pure)); int obj_types_assignable (const struct type_s *dst, const struct type_s *src); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 647a64716..d1322c174 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -345,15 +345,6 @@ obj_is_Class (const type_t *type) { if (type == &type_Class) return 1; - // type may be a qualified Class, in which case it will be a pointer to - // a qualified obj_class struct - if (type->type != ev_pointer) - return 0; - if (!is_struct (type->t.fldptr.type)) - return 0; - // if the the symtabs match, then type is Class in disguise - if (type->t.fldptr.type->t.symtab == type_obj_class.t.symtab) - return 1; return 0; } From ea042cf87aba79500da216a23df2f33fb146b035 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 Mar 2020 20:50:04 +0900 Subject: [PATCH 0690/3664] [qfcc] Split out the obj-qc specific expr code --- tools/qfcc/source/Makefile.am | 2 +- tools/qfcc/source/expr.c | 200 ------------------------- tools/qfcc/source/expr_obj.c | 266 ++++++++++++++++++++++++++++++++++ 3 files changed, 267 insertions(+), 201 deletions(-) create mode 100644 tools/qfcc/source/expr_obj.c diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index cfd31afbc..bbaf06ee6 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -41,7 +41,7 @@ bin_SCRIPTS= qfpreqcc common_src=\ class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \ diagnostic.c dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c emit.c \ - expr.c expr_assign.c expr_binary.c expr_bool.c expr_compound.c \ + expr.c expr_assign.c expr_binary.c expr_bool.c expr_compound.c expr_obj.c \ flow.c function.c grab.c \ idstuff.c \ linker.c method.c \ diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 72624364c..8a702714d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1099,28 +1099,6 @@ expr_short (expr_t *e) internal_error (e, "not a short constant"); } -expr_t * -new_self_expr (void) -{ - symbol_t *sym; - - sym = make_symbol (".self", &type_entity, pr.near_data, sc_extern); - if (!sym->table) - symtab_addsymbol (pr.symtab, sym); - return new_symbol_expr (sym); -} - -expr_t * -new_this_expr (void) -{ - symbol_t *sym; - - sym = make_symbol (".this", field_type (&type_id), pr.near_data, sc_extern); - if (!sym->table) - symtab_addsymbol (pr.symtab, sym); - return new_symbol_expr (sym); -} - expr_t * new_alias_expr (type_t *type, expr_t *expr) { @@ -2579,51 +2557,6 @@ cast_expr (type_t *dstType, expr_t *e) return c; } -expr_t * -selector_expr (keywordarg_t *selector) -{ - dstring_t *sel_id = dstring_newstr (); - expr_t *sel; - symbol_t *sel_sym; - symbol_t *sel_table; - int index; - - selector = copy_keywordargs (selector); - selector = (keywordarg_t *) reverse_params ((param_t *) selector); - selector_name (sel_id, selector); - index = selector_index (sel_id->str); - index *= type_size (type_SEL.t.fldptr.type); - sel_sym = make_symbol ("_OBJ_SELECTOR_TABLE_PTR", &type_SEL, - pr.near_data, sc_static); - if (!sel_sym->table) { - symtab_addsymbol (pr.symtab, sel_sym); - sel_table = make_symbol ("_OBJ_SELECTOR_TABLE", - array_type (type_SEL.t.fldptr.type, 0), - pr.far_data, sc_extern); - if (!sel_table->table) - symtab_addsymbol (pr.symtab, sel_table); - reloc_def_def (sel_table->s.def, sel_sym->s.def); - } - sel = new_symbol_expr (sel_sym); - dstring_delete (sel_id); - sel = new_binary_expr ('&', sel, new_short_expr (index)); - sel->e.expr.type = &type_SEL; - return sel; -} - -expr_t * -protocol_expr (const char *protocol_name) -{ - protocol_t *protocol = get_protocol (protocol_name, 0); - - if (!protocol) { - return error (0, "cannot find protocol declaration for `%s'", - protocol_name); - } - class_t *proto_class = get_class (new_symbol ("Protocol"), 1); - return new_pointer_expr (0, proto_class->type, protocol_def (protocol)); -} - expr_t * encode_expr (type_t *type) { @@ -2636,139 +2569,6 @@ encode_expr (type_t *type) return e; } -expr_t * -super_expr (class_type_t *class_type) -{ - symbol_t *sym; - expr_t *super; - expr_t *e; - expr_t *super_block; - class_t *class; - - if (!class_type) - return error (0, "`super' used outside of class implementation"); - - class = extract_class (class_type); - - if (!class->super_class) - return error (0, "%s has no super class", class->name); - - sym = symtab_lookup (current_symtab, ".super"); - if (!sym || sym->table != current_symtab) { - sym = new_symbol_type (".super", &type_obj_super); - initialize_def (sym, 0, current_symtab->space, sc_local); - } - super = new_symbol_expr (sym); - - super_block = new_block_expr (); - - e = assign_expr (field_expr (super, new_name_expr ("self")), - new_name_expr ("self")); - append_expr (super_block, e); - - e = new_symbol_expr (class_pointer_symbol (class)); - e = assign_expr (field_expr (super, new_name_expr ("class")), - field_expr (e, new_name_expr ("super_class"))); - append_expr (super_block, e); - - e = address_expr (super, 0, 0); - super_block->e.block.result = e; - return super_block; -} - -expr_t * -message_expr (expr_t *receiver, keywordarg_t *message) -{ - expr_t *args = 0, **a = &args; - expr_t *selector = selector_expr (message); - expr_t *call; - keywordarg_t *m; - int self = 0, super = 0, class_msg = 0; - type_t *rec_type; - type_t *return_type; - type_t *method_type = &type_IMP; - class_t *class = 0; - method_t *method; - expr_t *send_msg; - - if (receiver->type == ex_symbol - && strcmp (receiver->e.symbol->name, "super") == 0) { - super = 1; - - receiver = super_expr (current_class); - - if (receiver->type == ex_error) - return receiver; - receiver = cast_expr (&type_id, receiver); //FIXME better way? - class = extract_class (current_class); - } else { - if (receiver->type == ex_symbol) { - if (strcmp (receiver->e.symbol->name, "self") == 0) - self = 1; - if (receiver->e.symbol->sy_type == sy_class) { - class = receiver->e.symbol->type->t.class; - class_msg = 1; - receiver = new_symbol_expr (class_pointer_symbol (class)); - } - } else if (receiver->type == ex_nil) { - convert_nil (receiver, &type_id); - } - rec_type = get_type (receiver); - - if (receiver->type == ex_error) - return receiver; - - if (rec_type == &type_id || rec_type == &type_Class) { - } else { - if (rec_type->type == ev_pointer) - rec_type = rec_type->t.fldptr.type; - if (!obj_is_class (rec_type)) - return error (receiver, "not a class/object"); - - if (self) { - if (!class) - class = extract_class (current_class); - if (rec_type == &type_obj_class) - class_msg = 1; - } else { - if (!class) - class = rec_type->t.class; - } - } - } - - return_type = &type_id; - method = class_message_response (class, class_msg, selector); - if (method) - return_type = method->type->t.func.type; - - for (m = message; m; m = m->next) { - *a = m->expr; - while ((*a)) { - expr_file_line (selector, *a); - a = &(*a)->next; - } - } - *a = selector; - a = &(*a)->next; - *a = receiver; - - send_msg = expr_file_line (send_message (super), receiver); - if (method) { - expr_t *err; - if ((err = method_check_params (method, args))) - return err; - method_type = method->type; - } - call = build_function_call (send_msg, method_type, args); - - if (call->type == ex_error) - return receiver; - - call->e.block.result = new_ret_expr (return_type); - return call; -} - expr_t * sizeof_expr (expr_t *expr, struct type_s *type) { diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c new file mode 100644 index 000000000..fe04e2c98 --- /dev/null +++ b/tools/qfcc/source/expr_obj.c @@ -0,0 +1,266 @@ +/* + expr_obj.c + + Objective-QuakeC expression construction and manipulations + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2001/06/15 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/alloc.h" +#include "QF/dstring.h" +#include "QF/mathlib.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "qfcc.h" +#include "class.h" +#include "def.h" +#include "defspace.h" +#include "diagnostic.h" +#include "emit.h" +#include "expr.h" +#include "function.h" +#include "idstuff.h" +#include "method.h" +#include "options.h" +#include "reloc.h" +#include "shared.h" +#include "strpool.h" +#include "struct.h" +#include "symtab.h" +#include "type.h" +#include "value.h" +#include "qc-parse.h" + +expr_t * +new_self_expr (void) +{ + symbol_t *sym; + + sym = make_symbol (".self", &type_entity, pr.near_data, sc_extern); + if (!sym->table) + symtab_addsymbol (pr.symtab, sym); + return new_symbol_expr (sym); +} + +expr_t * +new_this_expr (void) +{ + symbol_t *sym; + + sym = make_symbol (".this", field_type (&type_id), pr.near_data, sc_extern); + if (!sym->table) + symtab_addsymbol (pr.symtab, sym); + return new_symbol_expr (sym); +} + +expr_t * +selector_expr (keywordarg_t *selector) +{ + dstring_t *sel_id = dstring_newstr (); + expr_t *sel; + symbol_t *sel_sym; + symbol_t *sel_table; + int index; + + selector = copy_keywordargs (selector); + selector = (keywordarg_t *) reverse_params ((param_t *) selector); + selector_name (sel_id, selector); + index = selector_index (sel_id->str); + index *= type_size (type_SEL.t.fldptr.type); + sel_sym = make_symbol ("_OBJ_SELECTOR_TABLE_PTR", &type_SEL, + pr.near_data, sc_static); + if (!sel_sym->table) { + symtab_addsymbol (pr.symtab, sel_sym); + sel_table = make_symbol ("_OBJ_SELECTOR_TABLE", + array_type (type_SEL.t.fldptr.type, 0), + pr.far_data, sc_extern); + if (!sel_table->table) + symtab_addsymbol (pr.symtab, sel_table); + reloc_def_def (sel_table->s.def, sel_sym->s.def); + } + sel = new_symbol_expr (sel_sym); + dstring_delete (sel_id); + sel = new_binary_expr ('&', sel, new_short_expr (index)); + sel->e.expr.type = &type_SEL; + return sel; +} + +expr_t * +protocol_expr (const char *protocol_name) +{ + protocol_t *protocol = get_protocol (protocol_name, 0); + + if (!protocol) { + return error (0, "cannot find protocol declaration for `%s'", + protocol_name); + } + class_t *proto_class = get_class (new_symbol ("Protocol"), 1); + return new_pointer_expr (0, proto_class->type, protocol_def (protocol)); +} + +expr_t * +super_expr (class_type_t *class_type) +{ + symbol_t *sym; + expr_t *super; + expr_t *e; + expr_t *super_block; + class_t *class; + + if (!class_type) + return error (0, "`super' used outside of class implementation"); + + class = extract_class (class_type); + + if (!class->super_class) + return error (0, "%s has no super class", class->name); + + sym = symtab_lookup (current_symtab, ".super"); + if (!sym || sym->table != current_symtab) { + sym = new_symbol_type (".super", &type_obj_super); + initialize_def (sym, 0, current_symtab->space, sc_local); + } + super = new_symbol_expr (sym); + + super_block = new_block_expr (); + + e = assign_expr (field_expr (super, new_name_expr ("self")), + new_name_expr ("self")); + append_expr (super_block, e); + + e = new_symbol_expr (class_pointer_symbol (class)); + e = assign_expr (field_expr (super, new_name_expr ("class")), + field_expr (e, new_name_expr ("super_class"))); + append_expr (super_block, e); + + e = address_expr (super, 0, 0); + super_block->e.block.result = e; + return super_block; +} + +expr_t * +message_expr (expr_t *receiver, keywordarg_t *message) +{ + expr_t *args = 0, **a = &args; + expr_t *selector = selector_expr (message); + expr_t *call; + keywordarg_t *m; + int self = 0, super = 0, class_msg = 0; + type_t *rec_type; + type_t *return_type; + type_t *method_type = &type_IMP; + class_t *class = 0; + method_t *method; + expr_t *send_msg; + + if (receiver->type == ex_symbol + && strcmp (receiver->e.symbol->name, "super") == 0) { + super = 1; + + receiver = super_expr (current_class); + + if (receiver->type == ex_error) + return receiver; + receiver = cast_expr (&type_id, receiver); //FIXME better way? + class = extract_class (current_class); + } else { + if (receiver->type == ex_symbol) { + if (strcmp (receiver->e.symbol->name, "self") == 0) + self = 1; + if (receiver->e.symbol->sy_type == sy_class) { + class = receiver->e.symbol->type->t.class; + class_msg = 1; + receiver = new_symbol_expr (class_pointer_symbol (class)); + } + } else if (receiver->type == ex_nil) { + convert_nil (receiver, &type_id); + } + rec_type = get_type (receiver); + + if (receiver->type == ex_error) + return receiver; + + if (rec_type == &type_id || rec_type == &type_Class) { + } else { + if (rec_type->type == ev_pointer) + rec_type = rec_type->t.fldptr.type; + if (!obj_is_class (rec_type)) + return error (receiver, "not a class/object"); + + if (self) { + if (!class) + class = extract_class (current_class); + if (rec_type == &type_obj_class) + class_msg = 1; + } else { + if (!class) + class = rec_type->t.class; + } + } + } + + return_type = &type_id; + method = class_message_response (class, class_msg, selector); + if (method) + return_type = method->type->t.func.type; + + for (m = message; m; m = m->next) { + *a = m->expr; + while ((*a)) { + expr_file_line (selector, *a); + a = &(*a)->next; + } + } + *a = selector; + a = &(*a)->next; + *a = receiver; + + send_msg = expr_file_line (send_message (super), receiver); + if (method) { + expr_t *err; + if ((err = method_check_params (method, args))) + return err; + method_type = method->type; + } + call = build_function_call (send_msg, method_type, args); + + if (call->type == ex_error) + return receiver; + + call->e.block.result = new_ret_expr (return_type); + return call; +} From 0fe3fda44dd76e9648a3b1ec11b51296d38fc916 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 Mar 2020 23:30:57 +0900 Subject: [PATCH 0691/3664] [qfcc] Fix protocol adorned id as message receiver This took a bit as type_id has no class data, only protocols attached to the type_obj_object instance, and then protocol lists can get deep. --- tools/qfcc/include/class.h | 8 ++- tools/qfcc/include/method.h | 3 + tools/qfcc/source/class.c | 107 ++++++++++++++++++++++++++++------- tools/qfcc/source/expr_obj.c | 73 +++++++++--------------- tools/qfcc/source/method.c | 14 +++++ 5 files changed, 138 insertions(+), 67 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index a468e19b5..68cefcd12 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -113,6 +113,7 @@ struct dstring_s; struct expr_s; struct method_s; struct symbol_s; +struct selector_s; int obj_is_id (const struct type_s *type) __attribute__((pure)); int obj_is_class (const struct type_s *type) __attribute__((pure)); @@ -141,7 +142,7 @@ void class_finish_ivar_scope (class_type_t *class_type, struct symtab_s *param_scope); struct method_s *class_find_method (class_type_t *class_type, struct method_s *method); -struct method_s *class_message_response (class_t *class, int class_msg, +struct method_s *class_message_response (struct type_s *clstype, int class_msg, struct expr_s *sel); struct symbol_s *class_pointer_symbol (class_t *class_type); category_t *get_category (struct symbol_s *class_name, @@ -161,6 +162,11 @@ struct def_s *protocol_def (protocol_t *protocol); protocollist_t *new_protocol_list (void); protocollist_t *add_protocol (protocollist_t *protocollist, const char *name); int procollist_find_protocol (protocollist_t *protocollist, protocol_t *proto) __attribute__((pure)); +struct method_s *protocollist_find_method (protocollist_t *protocollist, + struct selector_s *selector, + int nstance) + __attribute__((pure)); + int compare_protocols (protocollist_t *protos1, protocollist_t *protos2) __attribute__((pure)); void print_protocollist (struct dstring_s *dstr, protocollist_t *protocollist); struct def_s *emit_protocol (protocol_t *protocol); diff --git a/tools/qfcc/include/method.h b/tools/qfcc/include/method.h index c64f04ade..598e151ee 100644 --- a/tools/qfcc/include/method.h +++ b/tools/qfcc/include/method.h @@ -98,6 +98,9 @@ keywordarg_t *copy_keywordargs (const keywordarg_t *kwargs); struct expr_s *send_message (int super); method_t *find_method (const char *sel_name); +method_t *methodlist_find_method (methodlist_t *methodlist, + selector_t *selector, int instance) + __attribute__((pure)); void selector_name (struct dstring_s *sel_id, keywordarg_t *selector); void method_types (struct dstring_s *sel_types, method_t *method); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index d1322c174..6f4473e1d 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1104,42 +1104,79 @@ class_find_method (class_type_t *class_type, method_t *method) return method; } +static method_t * +cls_find_method (methodlist_t *methodlist, selector_t *selector, + int class_msg, int is_root) +{ + method_t *m = 0; + m = methodlist_find_method (methodlist, selector, !class_msg); + if (!m && is_root && class_msg + && (m = methodlist_find_method (methodlist, selector, 1))) { + return m; + } + return m; +} + method_t * -class_message_response (class_t *class, int class_msg, expr_t *sel) +class_message_response (type_t *clstype, int class_msg, expr_t *sel) { selector_t *selector; method_t *m; - class_t *c = class; + class_t *c; + class_t *class = 0; category_t *cat; + dstring_t *dstr; selector = get_selector (sel); if (!selector) return 0; - if (class && class->type != &type_obj_object) { - if (!class->interface_declared) { - class->interface_declared = 1; - warning (0, "cannot find interface declaration for `%s'", - class->name); + + if (!obj_is_classptr (clstype) && !obj_is_class (clstype)) { + error (0, "neither class nor object"); + return 0; + } + if (obj_is_id (clstype)) { + protocollist_t *protos = clstype->t.fldptr.type->protos; + if (protos) { + if ((m = protocollist_find_method (protos, selector, !class_msg))) { + return m; + } + dstr = dstring_new (); + print_protocollist (dstr, protos); + warning (sel, "id%s may not respond to %c%s", dstr->str, + class_msg ? '+' : '-', selector->name); + dstring_delete (dstr); } - while (c) { - for (cat = c->categories; cat; cat = cat->next) { - for (m = cat->methods->head; m; m = m->next) { - if (((!c->super_class && class_msg) - || class_msg != m->instance) - && strcmp (selector->name, m->name) == 0) + } else { + if (obj_is_class (clstype)) { + class = clstype->t.class; + } else if (obj_is_class (clstype->t.fldptr.type)) { + class = clstype->t.fldptr.type->t.class; + } + if (class && class->type != &type_obj_object) { + if (!class->interface_declared) { + class->interface_declared = 1; + warning (0, "cannot find interface declaration for `%s'", + class->name); + } + c = class; + while (c) { + for (cat = c->categories; cat; cat = cat->next) { + if ((m = cls_find_method (cat->methods, selector, + class_msg, + !c->super_class))) { return m; + } } - } - for (m = c->methods->head; m; m = m->next) { - if (((!c->super_class && class_msg) - || class_msg != m->instance) - && strcmp (selector->name, m->name) == 0) + if ((m = cls_find_method (c->methods, selector, class_msg, + !c->super_class))) { return m; + } + c = c->super_class; } - c = c->super_class; + warning (sel, "%s may not respond to %c%s", class->name, + class_msg ? '+' : '-', selector->name); } - warning (sel, "%s may not respond to %c%s", class->name, - class_msg ? '+' : '-', selector->name); } m = find_method (selector->name); if (!m && (!class || class->type == &type_obj_object)) { @@ -1592,6 +1629,34 @@ procollist_find_protocol (protocollist_t *protocollist, protocol_t *proto) return 0; } +static method_t * +protocol_find_method (protocol_t *protocol, selector_t *selector, int instance) +{ + method_t *m = 0; + if (protocol->methods) { + m = methodlist_find_method (protocol->methods, selector, instance); + } + if (!m && protocol->protocols) { + return protocollist_find_method (protocol->protocols, selector, + instance); + } + return m; +} + +method_t * +protocollist_find_method (protocollist_t *protocollist, selector_t *selector, + int instance) +{ + method_t *m; + for (int i = 0; i < protocollist->count; i++) { + if ((m = protocol_find_method (protocollist->list[i], selector, + instance))) { + return m; + } + } + return 0; +} + int compare_protocols (protocollist_t *protos1, protocollist_t *protos2) { diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index fe04e2c98..6858adb54 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -179,62 +179,45 @@ message_expr (expr_t *receiver, keywordarg_t *message) expr_t *selector = selector_expr (message); expr_t *call; keywordarg_t *m; - int self = 0, super = 0, class_msg = 0; - type_t *rec_type; + int super = 0, class_msg = 0; + type_t *rec_type = 0; type_t *return_type; type_t *method_type = &type_IMP; - class_t *class = 0; method_t *method; expr_t *send_msg; - if (receiver->type == ex_symbol - && strcmp (receiver->e.symbol->name, "super") == 0) { - super = 1; + if (receiver->type == ex_nil) { + rec_type = &type_id; + convert_nil (receiver, rec_type); + } else if (receiver->type == ex_symbol) { + if (strcmp (receiver->e.symbol->name, "self") == 0) { + rec_type = get_type (receiver); + } else if (strcmp (receiver->e.symbol->name, "super") == 0) { + super = 1; - receiver = super_expr (current_class); + receiver = super_expr (current_class); - if (receiver->type == ex_error) - return receiver; - receiver = cast_expr (&type_id, receiver); //FIXME better way? - class = extract_class (current_class); - } else { - if (receiver->type == ex_symbol) { - if (strcmp (receiver->e.symbol->name, "self") == 0) - self = 1; - if (receiver->e.symbol->sy_type == sy_class) { - class = receiver->e.symbol->type->t.class; - class_msg = 1; - receiver = new_symbol_expr (class_pointer_symbol (class)); - } - } else if (receiver->type == ex_nil) { - convert_nil (receiver, &type_id); - } - rec_type = get_type (receiver); - - if (receiver->type == ex_error) - return receiver; - - if (rec_type == &type_id || rec_type == &type_Class) { - } else { - if (rec_type->type == ev_pointer) - rec_type = rec_type->t.fldptr.type; - if (!obj_is_class (rec_type)) - return error (receiver, "not a class/object"); - - if (self) { - if (!class) - class = extract_class (current_class); - if (rec_type == &type_obj_class) - class_msg = 1; - } else { - if (!class) - class = rec_type->t.class; - } + if (receiver->type == ex_error) + return receiver; + receiver = cast_expr (&type_id, receiver); //FIXME better way? + rec_type = extract_class (current_class)->type; + } else if (receiver->e.symbol->sy_type == sy_class) { + class_t *class; + rec_type = receiver->e.symbol->type; + class = rec_type->t.class; + class_msg = 1; + receiver = new_symbol_expr (class_pointer_symbol (class)); } } + if (!rec_type) { + rec_type = get_type (receiver); + } + + if (receiver->type == ex_error) + return receiver; return_type = &type_id; - method = class_message_response (class, class_msg, selector); + method = class_message_response (rec_type, class_msg, selector); if (method) return_type = method->type->t.func.type; diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 5b818afad..e8e342c7a 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -375,6 +375,20 @@ find_method (const char *sel_name) return Hash_Find (known_methods, sel_name); } +method_t * +methodlist_find_method (methodlist_t *methodlist, selector_t *selector, + int instance) +{ + method_t *m; + + for (m = methodlist->head; m; m = m->next) { + if (m->instance == instance && strcmp (selector->name, m->name) == 0) { + return m; + } + } + return 0; +} + void selector_name (dstring_t *sel_id, keywordarg_t *selector) { From 2f07d9a310f5f51bdceaa6e1ad725423e035fe6e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 09:24:34 +0900 Subject: [PATCH 0692/3664] [qfcc] Improve accuracy of some more diagnostics --- tools/qfcc/source/dags.c | 3 ++- tools/qfcc/source/flow.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index ce4bd98cf..ffaee9be9 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -423,7 +423,8 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) param_node = def_visit_all (param_def, 0, dag_find_node, &daglabel); if (!param_node) { - bug (0, ".param_%d not set for %s", i, n->label->opcode); + bug (n->label->expr, ".param_%d not set for %s", i, + n->label->opcode); continue; } daglabel->live = 1; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index d3e82b7ce..d0b59ef12 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1255,7 +1255,7 @@ flow_find_successors (flowgraph_t *graph) if (sb->next) { set_add (node->successors, sb->next->flownode->id); } else { - bug (0, "code drops off the end of the function"); + bug (st->expr, "code drops off the end of the function"); // this shouldn't happen // however, make the exit dummy block the node's successor set_add (node->successors, graph->num_nodes + 1); From a0c28a5ac580909f90a9cecea4fd5c85dc0a6c73 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 12:15:55 +0900 Subject: [PATCH 0693/3664] [qfcc] Support pointers to temp operands This is necessary for correctly taking the address of operands. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/include/statements.h | 2 +- tools/qfcc/include/value.h | 4 ++- tools/qfcc/source/dags.c | 2 +- tools/qfcc/source/emit.c | 44 ++++++++++++++++++----------- tools/qfcc/source/expr.c | 6 ++-- tools/qfcc/source/value.c | 4 ++- tools/qfcc/test/struct-init-param.r | 22 ++++++++------- tools/qfcc/test/test-harness.c | 1 + 9 files changed, 53 insertions(+), 33 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 170fc7a50..836ec864d 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -126,6 +126,7 @@ typedef struct ex_pointer_s { int val; struct type_s *type; struct def_s *def; + struct tempop_s *tempop; } ex_pointer_t; typedef struct ex_func_s { diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 7a0b241ed..26904db3d 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -41,7 +41,7 @@ typedef enum { op_nil, } op_type_e; -typedef struct { +typedef struct tempop_s { struct def_s *def; int offset; struct type_s *type; diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index b4f22ee60..f2dc7195f 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -38,6 +38,7 @@ struct def_s; struct ex_value_s; +struct tempop_s; struct type_s; struct ex_value_s *new_string_val (const char *string_val); @@ -49,7 +50,8 @@ struct ex_value_s *new_field_val (int field_val, struct type_s *type, struct def_s *def); struct ex_value_s *new_func_val (int func_val, struct type_s *type); struct ex_value_s *new_pointer_val (int val, struct type_s *type, - struct def_s *def); + struct def_s *def, + struct tempop_s *tempop); struct ex_value_s *new_quaternion_val (const float *quaternion_val); struct ex_value_s *new_integer_val (int integer_val); struct ex_value_s *new_uinteger_val (int uinteger_val); diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index ffaee9be9..6745a7a94 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -884,7 +884,7 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) offset = dstDef->offset; dstDef = dstDef->alias; } - operands[2] = value_operand (new_pointer_val (offset, type, dstDef), + operands[2] = value_operand (new_pointer_val (offset, type, dstDef, 0), operands[1]->expr); st = build_statement ("", operands, var->expr); sblock_add_statement (block, st); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 0073f3967..f859e4b9f 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -60,16 +60,40 @@ static def_t zero_def; +static def_t *get_operand_def (expr_t *expr, operand_t *op); + static def_t * -get_value_def (ex_value_t *value, type_t *type) +get_tempop_def (expr_t *expr, tempop_t *tempop, type_t *type) +{ + if (tempop->def) { + return tempop->def; + } + if (tempop->alias) { + def_t *tdef = get_operand_def (expr, tempop->alias); + int offset = tempop->offset; + tempop->def = alias_def (tdef, type, offset); + } + if (!tempop->def) { + tempop->def = temp_def (type); + } + return tempop->def; +} + +static def_t * +get_value_def (expr_t *expr, ex_value_t *value, type_t *type) { def_t *def; - if (type == &type_short) { + if (is_short (type)) { def = new_def (0, &type_short, 0, sc_extern); def->offset = value->v.short_val; return def; } + if (is_pointer (type) && value->v.pointer.tempop + && !value->v.pointer.def) { + value->v.pointer.def = get_tempop_def (expr, value->v.pointer.tempop, + type->t.fldptr.type); + } def = emit_value (value, 0); if (type != def->type) return alias_def (def, type, 0); @@ -85,25 +109,13 @@ get_operand_def (expr_t *expr, operand_t *op) case op_def: return op->o.def; case op_value: - return get_value_def (op->o.value, op->type); + return get_value_def (expr, op->o.value, op->type); case op_label: op->type = &type_short; zero_def.type = &type_short; return &zero_def; //FIXME case op_temp: - if (op->o.tempop.def) { - return op->o.tempop.def; - } - if (op->o.tempop.alias) { - def_t *tdef = get_operand_def (expr, op->o.tempop.alias); - int offset = op->o.tempop.offset; - type_t *type = op->type; - op->o.tempop.def = alias_def (tdef, type, offset); - } - if (!op->o.tempop.def) { - op->o.tempop.def = temp_def (op->type); - } - return op->o.tempop.def; + return get_tempop_def (expr, &op->o.tempop, op->type); case op_alias: return get_operand_def (expr, op->o.alias); case op_nil: diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 8a702714d..2cd64dc13 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -800,7 +800,7 @@ new_pointer_expr (int val, type_t *type, def_t *def) { expr_t *e = new_expr (); e->type = ex_value; - e->e.value = new_pointer_val (val, type, def); + e->e.value = new_pointer_val (val, type, def, 0); return e; } @@ -2152,7 +2152,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) if (is_array (type)) { e = e1; e->type = ex_value; - e->e.value = new_pointer_val (0, t, def); + e->e.value = new_pointer_val (0, t, def, 0); } else { e = new_pointer_expr (0, t, def); e->line = e1->line; @@ -2218,7 +2218,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) return e2; if (e->type == ex_value && e->e.value->lltype == ev_pointer && is_short_val (e2)) { - e->e.value = new_pointer_val (e->e.value->v.pointer.val + expr_short (e2), t, e->e.value->v.pointer.def); + e->e.value = new_pointer_val (e->e.value->v.pointer.val + expr_short (e2), t, e->e.value->v.pointer.def, 0); } else { if (!is_short_val (e2) || expr_short (e2)) { if (e->type == ex_expr && e->e.expr.op == '&') { diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 97198268c..424dadce5 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -197,7 +197,8 @@ new_func_val (int func_val, type_t *type) } ex_value_t * -new_pointer_val (int pointer_val, type_t *type, def_t *def) +new_pointer_val (int pointer_val, type_t *type, def_t *def, + struct tempop_s *tempop) { ex_value_t val; if (!type) { @@ -208,6 +209,7 @@ new_pointer_val (int pointer_val, type_t *type, def_t *def) val.v.pointer.val = pointer_val; val.v.pointer.type = type; val.v.pointer.def = def; + val.v.pointer.tempop = tempop; return find_value (&val); } diff --git a/tools/qfcc/test/struct-init-param.r b/tools/qfcc/test/struct-init-param.r index f043cfde3..c3dd5927b 100644 --- a/tools/qfcc/test/struct-init-param.r +++ b/tools/qfcc/test/struct-init-param.r @@ -40,18 +40,20 @@ Rect o = { { 5, 6}, {7, 8} }; int main (void) { int ret = 0; + int ok; + bar(&obj, nil, &o, obj.offset); - printf ("%d %d %d %d\n", o.offset.x, o.offset.y, - o.extent.width, o.extent.height); - if not (o.offset.x == 0 && o.offset.y == 0 - && o.extent.width == 3 && o.extent.height == 4) - ret |= 1; + ok = (o.offset.x == 0 && o.offset.y == 0 + && o.extent.width == 3 && o.extent.height == 4); + ret |= !ok; + printf ("%d %d %d %d %d\n", o.offset.x, o.offset.y, + o.extent.width, o.extent.height, ok); baz(&obj, nil, &o, obj.offset); - printf ("%d %d %d %d\n", o.offset.x, o.offset.y, - o.extent.width, o.extent.height); - if not (o.offset.x == 1 && o.offset.y == 2 - && o.extent.width == 3 && o.extent.height == 4) - ret |= 1; + ok = (o.offset.x == 1 && o.offset.y == 2 + && o.extent.width == 3 && o.extent.height == 4); + ret |= !ok; + printf ("%d %d %d %d %d\n", o.offset.x, o.offset.y, + o.extent.width, o.extent.height, ok); return ret; } diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 69e660941..934c02cb0 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -138,6 +138,7 @@ init_qf (void) cvar_t *debug = Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "2", 0, 0, 0); + Cvar_Get ("pr_deadbeef_locals", "1", 0, 0, 0); if (options.trace > 1) { Cvar_SetValue (debug, 4); From b58deb56804f9091f07ec0c2b939169772ec40ca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 12:21:38 +0900 Subject: [PATCH 0694/3664] [qfcc] Rewrite operand_address to be much simpler It now creates a pointer value and returns that rather than generating an address statement. --- tools/qfcc/source/statements.c | 49 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 0b2337b0b..a68304838 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -658,39 +658,42 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } -static sblock_t * -operand_address (sblock_t *sblock, operand_t *reference, operand_t **op, - expr_t *e) +static operand_t * +operand_address (operand_t *reference, expr_t *e) { - statement_t *s; + def_t *def; type_t *type; + int offset = 0; + type = reference->type; switch (reference->op_type) { case op_def: - case op_temp: - case op_alias: - // build an address expression so dags can extract the correct - // type. address_expr cannot be used because reference might not - // be something it likes - e = expr_file_line (new_unary_expr ('&', e), e); - type = pointer_type (reference->type); - e->e.expr.type = type; - - s = new_statement (st_expr, "&", e); - s->opa = reference; - s->opc = temp_operand (type, e); - sblock_add_statement (sblock, s); - if (op) { - *(op) = s->opc; + // assumes aliasing is only one level deep which should be the + // case + def = reference->o.def; + if (def->alias) { + offset = def->offset; + def = def->alias; } - return sblock; + return value_operand (new_pointer_val (offset, type, def, 0), e); + case op_temp: + // assumes aliasing is only one level deep which should be the + // case + if (reference->o.tempop.alias) { + offset = reference->o.tempop.offset; + reference = reference->o.tempop.alias; + } + return value_operand (new_pointer_val (offset, type, 0, + &reference->o.tempop), e); + case op_alias: + //op_alias comes only from alias_operand and that is called + // by dags, so not expected case op_value: case op_label: case op_nil: break; } - internal_error ((*op)->expr, - "invalid operand type for operand address: %s", + internal_error (e, "invalid operand type for operand address: %s", op_type_names[reference->op_type]); } @@ -763,7 +766,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) *op = src; } if (is_indirect (dst_expr) || is_indirect (src_expr)) { - sblock = operand_address (sblock, src, &src, src_expr); + src = operand_address (src, src_expr); goto dereference_dst; } } From c8e45c6cfce6ad6c2b8f9f19aef677cca45913c2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 12:25:28 +0900 Subject: [PATCH 0695/3664] [qfcc] Use operand_address in expr_deref This fixes the technically correct but horrible mess of temps and addressing when dealing with ivars, and the resulting uninitialized temps due to the non-constant pointers (do need statement level constant folding, though). --- tools/qfcc/source/statements.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index a68304838..9c926978d 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -966,7 +966,6 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) continue; } if (is_struct (get_type (param))) { - //FIXME this should be done in the expression tree expr_t *mov = assign_expr (param, a); mov->line = a->line; mov->file = a->file; @@ -1010,15 +1009,6 @@ lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) return s; } -static statement_t * -address_statement (operand_t *value, expr_t *e) -{ - statement_t *s = new_statement (st_expr, "&", e); - s->opa = value; - s->opc = temp_operand (&type_pointer, e); - return s; -} - static sblock_t * expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) { @@ -1047,13 +1037,11 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) src_addr = s->opc; sblock_add_statement (sblock, s); - //FIXME an address immediate would be nice. - s = address_statement (*op, e); - dst_addr = s->opc; - sblock_add_statement (sblock, s); + dst_addr = operand_address (*op, e); s = new_statement (st_move, "", deref); s->opa = src_addr; + //FIXME large types s->opb = short_operand (type_size (type), e); s->opc = dst_addr; sblock_add_statement (sblock, s); From b544a052bf25d891c28521c0a3d3fa0cec3f130a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 13:46:46 +0900 Subject: [PATCH 0696/3664] [gamecode] Bail if PR_SearchDefs is given 0 defs Fixes the hang when searching for a field in progs that don't have any. --- libs/gamecode/pr_resolve.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 03e6949a2..6270653d2 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -51,6 +51,9 @@ PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset) unsigned right = num_defs - 1; unsigned mid; + if (!num_defs) { + return 0; + } while (left != right) { mid = (left + right + 1) / 2; if (defs[mid].ofs > offset) { From db06300dddaf4fc50be73312cc5d6fe0613f95e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 20:20:07 +0900 Subject: [PATCH 0697/3664] [qfcc] Make print_operand usable from gdb It not emitting a \n made life difficult, especially whenever gdb decided to make access to printf or puts awkward. --- tools/qfcc/source/statements.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 9c926978d..54f183096 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -158,8 +158,8 @@ operand_string (operand_t *op) return ("??"); } -void -print_operand (operand_t *op) +static void +_print_operand (operand_t *op) { switch (op->op_type) { case op_def: @@ -224,7 +224,7 @@ print_operand (operand_t *op) break; case op_alias: printf ("alias(%s,", pr_type_name[op->type->type]); - print_operand (op->o.alias); + _print_operand (op->o.alias); printf (")"); break; case op_nil: @@ -233,18 +233,25 @@ print_operand (operand_t *op) } } +void +print_operand (operand_t *op) +{ + _print_operand (op); + puts (""); +} + void print_statement (statement_t *s) { printf ("(%s, ", s->opcode); if (s->opa) - print_operand (s->opa); + _print_operand (s->opa); printf (", "); if (s->opb) - print_operand (s->opb); + _print_operand (s->opb); printf (", "); if (s->opc) - print_operand (s->opc); + _print_operand (s->opc); printf (")\n"); } From 69924fe717c9ffc0ce06a54a4521f4a76f009f96 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 20:21:07 +0900 Subject: [PATCH 0698/3664] [qfcc] Return correct value for is_const_ptr It really helps if the logic is not inverted. --- tools/qfcc/source/statements.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 54f183096..f1a4b42e0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -710,9 +710,9 @@ is_const_ptr (expr_t *e) if ((e->type != ex_value || e->e.value->lltype != ev_pointer) || !(POINTER_VAL (e->e.value->v.pointer) >= 0 && POINTER_VAL (e->e.value->v.pointer) < 65536)) { - return 1; + return 0; } - return 0; + return 1; } static __attribute__((pure)) int From 1d10136f2e09d4209fa62348b1556051b0a57bb4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 20:24:22 +0900 Subject: [PATCH 0699/3664] [qfcc] Treat all dereferences and indirect Why I had a const pointer test on there is beyond me. --- tools/qfcc/source/statements.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index f1a4b42e0..013fbd42b 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -722,7 +722,7 @@ is_indirect (expr_t *e) return 1; if (!(e->type == ex_uexpr && e->e.expr.op == '.')) return 0; - return is_const_ptr (e->e.expr.e1); + return 1; } static sblock_t * From ede7dd6d7e3b9dec51fe8755ad65dad069d6dc45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 20:31:21 +0900 Subject: [PATCH 0700/3664] [qfcc] Catch attempts to emit a bad operand type --- tools/qfcc/source/emit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index f859e4b9f..d9b4167f6 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -121,6 +121,7 @@ get_operand_def (expr_t *expr, operand_t *op) case op_nil: internal_error (expr, "unexpected nil operand"); } + internal_error (expr, "unexpected operand"); return 0; } From 5c0c056e2caaf34d9fe57b1f181549bc3ed89e21 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 21:07:31 +0900 Subject: [PATCH 0701/3664] [qfcc] Add is_entity type test helper --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/type.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 791ea0fc9..ba3b82f1e 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -162,6 +162,7 @@ int is_quaternion (const type_t *type) __attribute__((pure)); int is_math (const type_t *type) __attribute__((pure)); int is_pointer (const type_t *type) __attribute__((pure)); int is_field (const type_t *type) __attribute__((pure)); +int is_entity (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); int is_structural (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index cdf7ca6df..4404f2ed0 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -811,6 +811,14 @@ is_field (const type_t *type) return 0; } +int +is_entity (const type_t *type) +{ + if (type->type == ev_entity) + return 1; + return 0; +} + int is_array (const type_t *type) { From f9face0cefc0c1cb9613e1de7ef0f4d7c5465c3d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Mar 2020 23:26:39 +0900 Subject: [PATCH 0702/3664] [qfcc] Make is_indirect easier to read --- tools/qfcc/source/statements.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 013fbd42b..20e145b0c 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -718,11 +718,11 @@ is_const_ptr (expr_t *e) static __attribute__((pure)) int is_indirect (expr_t *e) { - if (e->type == ex_expr && e->e.expr.op == '.') + if ((e->type == ex_expr || e->type == ex_uexpr) + && e->e.expr.op == '.') { return 1; - if (!(e->type == ex_uexpr && e->e.expr.op == '.')) - return 0; - return 1; + } + return 0; } static sblock_t * From 8e6baf1bde4aa76919b8dffac0d9d49498bbf989 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 01:39:35 +0900 Subject: [PATCH 0703/3664] [qfcc] Fix assigning to entity fields At least for basic types. Compound types need testing. --- tools/qfcc/source/statements.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 20e145b0c..1733700fd 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -883,6 +883,15 @@ dereference_dst: return sblock; } + if (is_entity (dst->type) && ofs && is_field (ofs->type)) { + s = new_statement (st_expr, "&", dst_expr); + s->opa = dst; + s->opb = ofs; + s->opc = temp_operand (&type_pointer, dst_expr); + sblock_add_statement (sblock, s); + dst = s->opc; + ofs = 0; + } s = new_statement (type, opcode, e); s->opa = src; s->opb = dst; From fd06cd2b006ad6445ce6f320d4e0034a87f96897 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 01:40:35 +0900 Subject: [PATCH 0704/3664] [qfcc] Analyze assignment through const pointers This fixes a false-positive uninitialized warning. --- tools/qfcc/source/flow.c | 56 ++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index d0b59ef12..ba8868f43 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1040,7 +1040,7 @@ flow_add_op_var (set_t *set, operand_t *op, int is_use) set_add (set, var->number); // FIXME XXX I think the curent implementation will have problems - // for the def set when assinging to an alias as right now the real + // for the def set when assigning to an alias as right now the real // var is being treated as assigned as well. Want to handle partial // defs properly, but I am as yet uncertain of how. if (op->op_type == op_temp) { @@ -1050,6 +1050,28 @@ flow_add_op_var (set_t *set, operand_t *op, int is_use) } } +static int +flow_analyize_pointer_operand (operand_t *ptrop, set_t *def, + operand_t *operands[4]) +{ + if (ptrop->op_type == op_value + && ptrop->o.value->lltype == ev_pointer + && ptrop->o.value->v.pointer.def) { + operand_t *op; + def_t *alias; + ex_pointer_t *ptr = &ptrop->o.value->v.pointer; + alias = alias_def (ptr->def, ptr->type, ptr->val); + op = def_operand (alias, ptr->type, ptrop->expr); + flow_add_op_var (def, op, 0); + if (operands) + operands[0] = op; + else + free_operand (op); + return 1; + } + return 0; +} + void flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, operand_t *operands[4]) @@ -1099,37 +1121,31 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } else if (!strcmp (s->opcode, "") || !strcmp (s->opcode, "")) { flow_add_op_var (use, s->opc, 0); - if (s->opc->op_type == op_value - && s->opc->o.value->lltype == ev_pointer - && s->opc->o.value->v.pointer.def) { - operand_t *op; - def_t *alias; - ex_pointer_t *ptr = &s->opc->o.value->v.pointer; - alias = alias_def (ptr->def, ptr->type, ptr->val); - op = def_operand (alias, ptr->type, s->opc->expr); - flow_add_op_var (def, op, 0); - if (operands) - operands[0] = op; - else - free_operand (op); - } else { - if (operands) + if (!flow_analyize_pointer_operand (s->opc, def, operands)) { + if (operands) { operands[3] = s->opc; + } } + } else if (!strcmp (s->opcode, ".=")) { + flow_add_op_var (use, s->opc, 1); + flow_analyize_pointer_operand (s->opb, def, operands); } else { - if (s->opc) - flow_add_op_var (use, s->opc, 1); + internal_error (s->expr, "unexpected opcode '%s' for %d", + s->opcode, s->type); } if (kill) { set_everything (kill); } if (operands) { - if (!strcmp (s->opcode, "")) + if (!strcmp (s->opcode, "") + || !strcmp (s->opcode, "")) { operands[0] = s->opc; + } operands[1] = s->opa; operands[2] = s->opb; - if (strncmp (s->opcode, "opcode, "opc; + } } break; case st_state: From 888192a9eaf8772841c3ffc2bef2e40336b49445 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 01:42:46 +0900 Subject: [PATCH 0705/3664] [qfcc] Resurrect ex_def expression type It turns out to be useful still as using symbol expressions isn't always appropriate and the workarounds were getting nasty. --- tools/qfcc/include/expr.h | 8 ++++++++ tools/qfcc/source/dot_expr.c | 11 +++++++++++ tools/qfcc/source/expr.c | 21 +++++++++++++++++++++ tools/qfcc/source/expr_assign.c | 2 ++ tools/qfcc/source/statements.c | 9 +++++++++ 5 files changed, 51 insertions(+) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 836ec864d..dc3a84f63 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -49,6 +49,7 @@ typedef enum { ex_block, ///< statement block expression (::ex_block_t) ex_expr, ///< binary expression (::ex_expr_t) ex_uexpr, ///< unary expression (::ex_expr_t) + ex_def, ///< non-temporary variable (::def_t) ex_symbol, ///< non-temporary variable (::symbol_t) ex_temp, ///< temporary variable (::ex_temp_t) ex_vector, ///< "vector" expression (::ex_vector_t) @@ -230,6 +231,7 @@ typedef struct expr_s { ex_bool_t bool; ///< boolean logic expression ex_block_t block; ///< statement block expression ex_expr_t expr; ///< binary or unary expression + struct def_s *def; ///< def reference expression struct symbol_s *symbol; ///< symbol reference expression ex_temp_t temp; ///< temporary variable expression ex_vector_t vector; ///< vector expression list @@ -411,6 +413,12 @@ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2); */ expr_t *new_unary_expr (int op, expr_t *e1); +/** Create a new def reference (non-temporary variable) expression node. + + \return The new def reference expression node (::def_t). +*/ +expr_t *new_def_expr (struct def_s *def); + /** Create a new symbol reference (non-temporary variable) expression node. \return The new symbol reference expression node (::symbol_t). diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 76bd21089..27d535845 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -62,6 +62,7 @@ const char *expr_names[] = "block", "expr", "uexpr", + "def", "symbol", "temp", "vector", @@ -354,6 +355,15 @@ print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) dstring_delete (typestr); } +static void +print_def (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + dasprintf (dstr, "%*se_%p [label=\"d %s\\n%d\"];\n", indent, "", e, + e->e.def->name, e->line); +} + static void print_symbol (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -542,6 +552,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) print_block, print_subexpr, print_uexpr, + print_def, print_symbol, print_temp, print_vector, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 2cd64dc13..8eeea76c1 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -239,6 +239,8 @@ get_type (expr_t *e) case ex_expr: case ex_uexpr: return e->e.expr.type; + case ex_def: + return e->e.def->type; case ex_symbol: return e->e.symbol->type; case ex_temp: @@ -342,6 +344,7 @@ copy_expr (expr_t *e) return 0; switch (e->type) { case ex_error: + case ex_def: case ex_symbol: case ex_nil: case ex_value: @@ -610,6 +613,15 @@ new_unary_expr (int op, expr_t *e1) return e; } +expr_t * +new_def_expr (def_t *def) +{ + expr_t *e = new_expr (); + e->type = ex_def; + e->e.def = def; + return e; +} + expr_t * new_symbol_expr (symbol_t *symbol) { @@ -1542,6 +1554,13 @@ unary_expr (int op, expr_t *e) n->e.expr.type = e->e.expr.type; return n; } + case ex_def: + { + expr_t *n = new_unary_expr (op, e); + + n->e.expr.type = e->e.def->type; + return n; + } case ex_symbol: { expr_t *n = new_unary_expr (op, e); @@ -1602,6 +1621,7 @@ unary_expr (int op, expr_t *e) return error (e, "invalid type for unary !"); case ex_uexpr: case ex_expr: + case ex_def: case ex_symbol: case ex_temp: case ex_vector: @@ -1671,6 +1691,7 @@ unary_expr (int op, expr_t *e) goto bitnot_expr; case ex_expr: case ex_bool: + case ex_def: case ex_symbol: case ex_temp: case ex_vector: diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 88d45ad7b..7d1f1aab9 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -85,6 +85,8 @@ int is_lvalue (const expr_t *expr) { switch (expr->type) { + case ex_def: + return !expr->e.def->constant; case ex_symbol: switch (expr->e.symbol->sy_type) { case sy_name: diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 1733700fd..a950842e5 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1267,6 +1267,13 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_def (sblock_t *sblock, expr_t *e, operand_t **op) +{ + *op = def_operand (e->e.def, e->e.def->type, e); + return sblock; +} + static sblock_t * expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1398,6 +1405,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) expr_block, // ex_block expr_expr, expr_uexpr, + expr_def, expr_symbol, expr_temp, expr_vector_e, // ex_vector @@ -1715,6 +1723,7 @@ statement_slist (sblock_t *sblock, expr_t *e) statement_block, statement_expr, statement_uexpr, + statement_nonexec, // ex_def statement_nonexec, // ex_symbol statement_nonexec, // ex_temp statement_nonexec, // ex_vector From e4a403bbb38154b6fa1a28f8e17354fe7587a233 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 10:55:27 +0900 Subject: [PATCH 0706/3664] [qfcc] Improve integral value extraction readability --- tools/qfcc/source/expr.c | 53 ++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 8eeea76c1..509f5fcfb 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1039,13 +1039,16 @@ expr_quaternion (expr_t *e) int is_integer_val (expr_t *e) { - if (e->type == ex_nil) + if (e->type == ex_nil) { return 1; - if (e->type == ex_value && e->e.value->lltype == ev_integer) + } + if (e->type == ex_value && e->e.value->lltype == ev_integer) { return 1; + } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && (e->e.symbol->type->type == ev_integer - || is_enum (e->e.symbol->type))) + && is_integral (e->e.symbol->type)) { + return 1; + } return 1; return 0; } @@ -1053,61 +1056,75 @@ is_integer_val (expr_t *e) int expr_integer (expr_t *e) { - if (e->type == ex_nil) + if (e->type == ex_nil) { return 0; - if (e->type == ex_value && e->e.value->lltype == ev_integer) + } + if (e->type == ex_value && e->e.value->lltype == ev_integer) { return e->e.value->v.integer_val; + } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && (e->e.symbol->type->type == ev_integer - || is_enum (e->e.symbol->type))) + || is_enum (e->e.symbol->type))) { return e->e.symbol->s.value->v.integer_val; + } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var && e->e.symbol->s.def->constant - && is_integral (e->e.symbol->s.def->type)) + && is_integral (e->e.symbol->s.def->type)) { return D_INT (e->e.symbol->s.def); + } internal_error (e, "not an integer constant"); } unsigned expr_uinteger (expr_t *e) { - if (e->type == ex_nil) + if (e->type == ex_nil) { return 0; - if (e->type == ex_value && e->e.value->lltype == ev_uinteger) + } + if (e->type == ex_value && e->e.value->lltype == ev_uinteger) { return e->e.value->v.uinteger_val; + } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && e->e.symbol->type->type == ev_uinteger) + && e->e.symbol->type->type == ev_uinteger) { return e->e.symbol->s.value->v.uinteger_val; + } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var && e->e.symbol->s.def->constant - && is_integral (e->e.symbol->s.def->type)) + && is_integral (e->e.symbol->s.def->type)) { return D_INT (e->e.symbol->s.def); + } internal_error (e, "not an unsigned constant"); } int is_short_val (expr_t *e) { - if (e->type == ex_nil) + if (e->type == ex_nil) { return 1; - if (e->type == ex_value && e->e.value->lltype == ev_short) + } + if (e->type == ex_value && e->e.value->lltype == ev_short) { return 1; + } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && e->e.symbol->type->type == ev_short) + && e->e.symbol->type->type == ev_short) { return 1; + } return 0; } short expr_short (expr_t *e) { - if (e->type == ex_nil) + if (e->type == ex_nil) { return 0; - if (e->type == ex_value && e->e.value->lltype == ev_short) + } + if (e->type == ex_value && e->e.value->lltype == ev_short) { return e->e.value->v.short_val; + } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && e->e.symbol->type->type == ev_short) + && e->e.symbol->type->type == ev_short) { return e->e.symbol->s.value->v.short_val; + } internal_error (e, "not a short constant"); } From 80967e1471cd5448ea0aa296c5e0e433332f45a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 10:56:45 +0900 Subject: [PATCH 0707/3664] [qfcc] Support def exprs in integral value extractors --- tools/qfcc/source/expr.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 509f5fcfb..638af8e12 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1049,7 +1049,10 @@ is_integer_val (expr_t *e) && is_integral (e->e.symbol->type)) { return 1; } + if (e->type == ex_def && e->e.def->constant + && is_integral (e->e.def->type)) { return 1; + } return 0; } @@ -1072,6 +1075,10 @@ expr_integer (expr_t *e) && is_integral (e->e.symbol->s.def->type)) { return D_INT (e->e.symbol->s.def); } + if (e->type == ex_def && e->e.def->constant + && is_integral (e->e.def->type)) { + return D_INT (e->e.def); + } internal_error (e, "not an integer constant"); } @@ -1093,6 +1100,10 @@ expr_uinteger (expr_t *e) && is_integral (e->e.symbol->s.def->type)) { return D_INT (e->e.symbol->s.def); } + if (e->type == ex_def && e->e.def->constant + && is_integral (e->e.def->type)) { + return D_INT (e->e.def); + } internal_error (e, "not an unsigned constant"); } From c3f04384d565653f05f65fe6fd72815a71df7a7e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 11:07:50 +0900 Subject: [PATCH 0708/3664] [qfcc] Make a general integral value extractor All too often I just want the value. --- tools/qfcc/include/expr.h | 4 +++ tools/qfcc/source/expr.c | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index dc3a84f63..a181f7205 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -567,6 +567,8 @@ unsigned expr_uinteger (expr_t *e) __attribute__((pure)); expr_t *new_short_expr (short short_val); short expr_short (expr_t *e) __attribute__((pure)); +int expr_integral (expr_t *e) __attribute__((pure)); + /** Check of the expression refers to a constant value. \param e The expression to check. @@ -613,7 +615,9 @@ int is_float_val (expr_t *e) __attribute__((pure)); int is_vector_val (expr_t *e) __attribute__((pure)); int is_quaternion_val (expr_t *e) __attribute__((pure)); int is_integer_val (expr_t *e) __attribute__((pure)); +int is_uinteger_val (expr_t *e) __attribute__((pure)); int is_short_val (expr_t *e) __attribute__((pure)); +int is_integral_val (expr_t *e) __attribute__((pure)); /** Create a reference to the global .self entity variable. diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 638af8e12..c8c9207fc 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1082,6 +1082,26 @@ expr_integer (expr_t *e) internal_error (e, "not an integer constant"); } +int +is_uinteger_val (expr_t *e) +{ + if (e->type == ex_nil) { + return 1; + } + if (e->type == ex_value && e->e.value->lltype == ev_uinteger) { + return 1; + } + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && is_integral (e->e.symbol->type)) { + return 1; + } + if (e->type == ex_def && e->e.def->constant + && is_integral (e->e.def->type)) { + return 1; + } + return 0; +} + unsigned expr_uinteger (expr_t *e) { @@ -1139,6 +1159,40 @@ expr_short (expr_t *e) internal_error (e, "not a short constant"); } +int +is_integral_val (expr_t *e) +{ + if (is_constant (e)) { + if (is_integer_val (e)) { + return 1; + } + if (is_uinteger_val (e)) { + return 1; + } + if (is_short_val (e)) { + return 1; + } + } + return 0; +} + +int +expr_integral (expr_t *e) +{ + if (is_constant (e)) { + if (is_integer_val (e)) { + return expr_integer (e); + } + if (is_uinteger_val (e)) { + return expr_uinteger (e); + } + if (is_short_val (e)) { + return expr_short (e); + } + } + internal_error (e, "not an integral constant"); +} + expr_t * new_alias_expr (type_t *type, expr_t *expr) { From 9cb3ee01d601b92a1813e6e93ed7aaf4952088a6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 11:19:12 +0900 Subject: [PATCH 0709/3664] [qfcc] Add pointer value check Extraction is a little more complicated, though, so undecided on that. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/expr.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index a181f7205..b2e01a491 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -618,6 +618,7 @@ int is_integer_val (expr_t *e) __attribute__((pure)); int is_uinteger_val (expr_t *e) __attribute__((pure)); int is_short_val (expr_t *e) __attribute__((pure)); int is_integral_val (expr_t *e) __attribute__((pure)); +int is_pointer_val (expr_t *e) __attribute__((pure)); /** Create a reference to the global .self entity variable. diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c8c9207fc..29e249d70 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1193,6 +1193,15 @@ expr_integral (expr_t *e) internal_error (e, "not an integral constant"); } +int +is_pointer_val (expr_t *e) +{ + if (e->type == ex_value && e->e.value->lltype == ev_pointer) { + return 1; + } + return 0; +} + expr_t * new_alias_expr (type_t *type, expr_t *expr) { From 0d751dcdc5e78ec95229d0638e859f301d11b781 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 12:12:06 +0900 Subject: [PATCH 0710/3664] [qfcc] Improve robustness of do_op_integer --- tools/qfcc/source/constfold.c | 86 +++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index f46d1a452..e1b380a5d 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -789,7 +789,8 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) static expr_t * do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) { - int i1, i2; + int isval1 = 0, isval2 = 0; + int val1, val2; static int valid[] = { '=', '+', '-', '*', '/', '&', '|', '^', '%', SHL, SHR, AND, OR, LT, GT, LE, GE, EQ, NE, 0 @@ -798,11 +799,23 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) if (!valid_op (op, valid)) return error (e1, "invalid operator for integer"); - if (is_short_val (e1)) - convert_short_int (e1); + if (is_short_val (e1)) { + isval1 = 1; + val1 = expr_short (e1); + } + if (is_integer_val (e1)) { + isval1 = 1; + val1 = expr_integer (e1); + } - if (is_short_val (e2)) - convert_short_int (e2); + if (is_short_val (e2)) { + isval2 = 1; + val2 = expr_short (e2); + } + if (is_integer_val (e2)) { + isval2 = 1; + val2 = expr_integer (e2); + } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) @@ -813,89 +826,86 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_integer; } - if (op == '*' && is_constant (e1) && expr_integer (e1) == 1) + if (op == '*' && isval1 && val1 == 1) return e2; - if (op == '*' && is_constant (e2) && expr_integer (e2) == 1) + if (op == '*' && isval2 && val2 == 1) return e1; - if (op == '*' && is_constant (e1) && expr_integer (e1) == 0) + if (op == '*' && isval1 && val1 == 0) return e1; - if (op == '*' && is_constant (e2) && expr_integer (e2) == 0) + if (op == '*' && isval2 && val2 == 0) return e2; - if (op == '/' && is_constant (e2) && expr_integer (e2) == 1) + if (op == '/' && isval2 && val2 == 1) return e1; - if (op == '/' && is_constant (e2) && expr_integer (e2) == 0) + if (op == '/' && isval2 && val2 == 0) return error (e, "division by zero"); - if (op == '/' && is_constant (e1) && expr_integer (e1) == 0) + if (op == '/' && isval1 && val1 == 0) return e1; - if (op == '+' && is_constant (e1) && expr_integer (e1) == 0) + if (op == '+' && isval1 && val1 == 0) return e2; - if (op == '+' && is_constant (e2) && expr_integer (e2) == 0) + if (op == '+' && isval2 && val2 == 0) return e1; - if (op == '-' && is_constant (e2) && expr_integer (e2) == 0) + if (op == '-' && isval2 && val2 == 0) return e1; - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (op == '=' || !isval1 || !isval2) return e; - i1 = expr_integer (e1); - i2 = expr_integer (e2); - switch (op) { case '+': - e = new_integer_expr (i1 + i2); + e = new_integer_expr (val1 + val2); break; case '-': - e = new_integer_expr (i1 - i2); + e = new_integer_expr (val1 - val2); break; case '*': - e = new_integer_expr (i1 * i2); + e = new_integer_expr (val1 * val2); break; case '/': if (options.warnings.integer_divide) - warning (e2, "%d / %d == %d", i1, i2, i1 / i2); - e = new_integer_expr (i1 / i2); + warning (e2, "%d / %d == %d", val1, val2, val1 / val2); + e = new_integer_expr (val1 / val2); break; case '&': - e = new_integer_expr (i1 & i2); + e = new_integer_expr (val1 & val2); break; case '|': - e = new_integer_expr (i1 | i2); + e = new_integer_expr (val1 | val2); break; case '^': - e = new_integer_expr (i1 ^ i2); + e = new_integer_expr (val1 ^ val2); break; case '%': - e = new_integer_expr (i1 % i2); + e = new_integer_expr (val1 % val2); break; case SHL: - e = new_integer_expr (i1 << i2); + e = new_integer_expr (val1 << val2); break; case SHR: - e = new_integer_expr (i1 >> i2); + e = new_integer_expr (val1 >> val2); break; case AND: - e = cmp_result_expr (i1 && i2); + e = cmp_result_expr (val1 && val2); break; case OR: - e = cmp_result_expr (i1 || i2); + e = cmp_result_expr (val1 || val2); break; case LT: - e = cmp_result_expr (i1 < i2); + e = cmp_result_expr (val1 < val2); break; case GT: - e = cmp_result_expr (i1 > i2); + e = cmp_result_expr (val1 > val2); break; case LE: - e = cmp_result_expr (i1 <= i2); + e = cmp_result_expr (val1 <= val2); break; case GE: - e = cmp_result_expr (i1 >= i2); + e = cmp_result_expr (val1 >= val2); break; case EQ: - e = cmp_result_expr (i1 == i2); + e = cmp_result_expr (val1 == val2); break; case NE: - e = cmp_result_expr (i1 != i2); + e = cmp_result_expr (val1 != val2); break; default: internal_error (e1, 0); From 0d784d9ef4157c2b383246feae25efdc597b3f1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 12:13:09 +0900 Subject: [PATCH 0711/3664] [qfcc] Rework address expr calculation This removes a bogus lea from the instruction stream (and there can be many such). --- tools/qfcc/source/def.c | 9 +++++---- tools/qfcc/source/expr.c | 24 +++++++++++++++++++++--- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 689b21dac..2fbf0bf08 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -296,8 +296,9 @@ zero_memory (expr_t *local_expr, def_t *def, type_t *zero_type, expr_t *dst; for (; init_offset < init_size + 1 - zero_size; init_offset += zero_size) { - dst = new_pointer_expr (init_offset, zero_type, def); - append_expr (local_expr, assign_expr (unary_expr ('.', dst), zero)); + dst = new_def_expr (def); + dst = new_offset_alias_expr (zero_type, dst, init_offset); + append_expr (local_expr, assign_expr (dst, zero)); } return init_offset; } @@ -355,8 +356,8 @@ init_elements (struct def_s *def, expr_t *eles) build_element_chain (&element_chain, def->type, eles, 0); if (def->local && local_expr) { - expr_t *ptr = new_pointer_expr (0, def->type, def); - assign_elements (local_expr, pointer_expr (ptr), &element_chain); + expr_t *dst = new_def_expr (def); + assign_elements (local_expr, dst, &element_chain); } else { def_t dummy = *def; for (element = element_chain.head; element; element = element->next) { diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 29e249d70..ac128e378 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2256,6 +2256,22 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) t = get_type (e1); switch (e1->type) { + case ex_def: + { + def_t *def = e1->e.def; + type_t *type = def->type; + + if (is_array (type)) { + e = e1; + e->type = ex_value; + e->e.value = new_pointer_val (0, t, def, 0); + } else { + e = new_pointer_expr (0, t, def); + e->line = e1->line; + e->file = e1->file; + } + } + break; case ex_symbol: if (e1->e.symbol->sy_type == sy_var) { def_t *def = e1->e.symbol->s.def; @@ -2328,9 +2344,11 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) if (e2) { if (e2->type == ex_error) return e2; - if (e->type == ex_value && e->e.value->lltype == ev_pointer - && is_short_val (e2)) { - e->e.value = new_pointer_val (e->e.value->v.pointer.val + expr_short (e2), t, e->e.value->v.pointer.def, 0); + if (is_pointer_val (e) && is_integral_val (e2)) { + int base = e->e.value->v.pointer.val; + int offset = expr_integral (e2); + def_t *def = e->e.value->v.pointer.def; + e->e.value = new_pointer_val (base + offset, t, def, 0); } else { if (!is_short_val (e2) || expr_short (e2)) { if (e->type == ex_expr && e->e.expr.op == '&') { From c5400c458175eec7c0f253a3defed1d66fecbcf3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 12:16:24 +0900 Subject: [PATCH 0712/3664] [qfcc] Make anonstruct test robust against pointer math I noticed that pointer math is currently incorrect in qfcc, but it would be nice for fixing it to not break anonstruct since it is testing something else. --- tools/qfcc/test/anonstruct.r | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/test/anonstruct.r b/tools/qfcc/test/anonstruct.r index 684ae8c2b..3c025bb38 100644 --- a/tools/qfcc/test/anonstruct.r +++ b/tools/qfcc/test/anonstruct.r @@ -28,22 +28,22 @@ int main() { anon_t anon; int ret = 0; - if (&anon.snafu != &anon.fizzle) { + if ((int)&anon.snafu != (int)&anon.fizzle) { printf ("anon union broken: %p %p\n", &anon.snafu, &anon.fizzle); ret |= 1; } - if (&anon.snafu - &anon.baz != 1) { + if ((int)&anon.snafu - (int)&anon.baz != 1) { printf ("snafu and baz not adjacant: snafu:%p baz:%p\n", &anon.snafu, &anon.baz); ret |= 1; } - if (&anon.baz - &anon.bar != 1) { + if ((int)&anon.baz - (int)&anon.bar != 1) { printf ("baz and bar not adjacant: baz:%p bar:%p\n", &anon.baz, &anon.bar); ret |= 1; } - if (&anon.bar - &anon.id != 1) { + if ((int)&anon.bar - (int)&anon.id != 1) { printf ("bar not after id: bar:%p id:%p\n", &anon.bar, &anon.id); ret |= 1; From 441e7b99bcb8cd42b8cc2c73ec1bab457bdf1c84 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 12:45:55 +0900 Subject: [PATCH 0713/3664] [qfcc] Correctly implement pointer arithmetic --- tools/qfcc/source/expr_binary.c | 74 +++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index c2d446334..b7b526853 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -46,6 +46,7 @@ typedef struct { } expr_type_t; static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2); +static expr_t *pointer_compare (int op, expr_t *e1, expr_t *e2); static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2); static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); @@ -176,13 +177,13 @@ static expr_type_t func_func[] = { }; static expr_type_t pointer_pointer[] = { - {'-', &type_integer, &type_integer, &type_integer}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {'-', 0, 0, 0, pointer_arithmetic}, + {EQ, 0, 0, 0, pointer_compare}, + {NE, 0, 0, 0, pointer_compare}, + {LE, 0, 0, 0, pointer_compare}, + {GE, 0, 0, 0, pointer_compare}, + {LT, 0, 0, 0, pointer_compare}, + {GT, 0, 0, 0, pointer_compare}, {0, 0} }; @@ -255,7 +256,7 @@ static expr_type_t integer_vector[] = { }; static expr_type_t integer_pointer[] = { - {'+', &type_pointer, 0, &type_integer}, + {'+', 0, 0, 0, pointer_arithmetic}, {0, 0} }; @@ -735,21 +736,58 @@ static expr_t * pointer_arithmetic (int op, expr_t *e1, expr_t *e2) { expr_t *e; - type_t *ptype = get_type (e1); + type_t *t1 = get_type (e1); + type_t *t2 = get_type (e2); + expr_t *ptr; + expr_t *offset; + expr_t *psize; + type_t *ptype; - if (!is_pointer (ptype)) { - ptype = get_type (e2); - } - if (!is_pointer (ptype)) { + if (!is_pointer (t1) && !is_pointer (t2)) { internal_error (e1, "pointer arithmetic on non-pointers"); } - - e1 = cast_expr (&type_integer, e1); - e2 = cast_expr (&type_integer, e2); - e = binary_expr (op, e1, e2); + if (is_pointer (t1) && is_pointer (t2)) { + if (op != '-') { + return error (e2, "invalid pointer operation"); + } + if (t1 != t2) { + return error (e2, "cannot use %c on pointers of different types", + op); + } + e1 = cast_expr (&type_integer, e1); + e2 = cast_expr (&type_integer, e2); + psize = new_integer_expr (type_size (t1->t.fldptr.type)); + return binary_expr ('/', binary_expr ('-', e1, e2), psize); + } else if (is_pointer (t1)) { + offset = cast_expr (&type_integer, e2); + ptr = cast_expr (&type_integer, e1); + ptype = t1; + } else if (is_pointer (t2)) { + offset = cast_expr (&type_integer, e1); + ptr = cast_expr (&type_integer, e2); + ptype = t2; + } + psize = new_integer_expr (type_size (ptype->t.fldptr.type)); + e = binary_expr (op, ptr, binary_expr ('*', offset, psize)); return cast_expr (ptype, e); } +static expr_t * +pointer_compare (int op, expr_t *e1, expr_t *e2) +{ + type_t *t1 = get_type (e1); + type_t *t2 = get_type (e2); + expr_t *e; + + if (!type_assignable (t1, t2)) { + return error (e2, "cannot use %s on pointers of different types", + get_op_string (op)); + } + e = new_binary_expr (op, e1, e2); + e->e.expr.type = &type_integer; + return e; +} + static expr_t * inverse_multiply (int op, expr_t *e1, expr_t *e2) { @@ -790,7 +828,7 @@ double_compare (int op, expr_t *e1, expr_t *e2) e1 = cast_expr (&type_double, e1); } e = new_binary_expr (op, e1, e2); - e->e.expr.type = &type_double; + e->e.expr.type = &type_integer; return e; } From 28a8c1fda7523d2f5ac947127e8532844afb9558 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 14:05:31 +0900 Subject: [PATCH 0714/3664] [qwaq] Implement more curses wrappers --- ruamoko/qwaq/qwaq-curses.c | 83 ++++++++++++++++++++++++++++++++- ruamoko/qwaq/qwaq-curses.h | 2 + ruamoko/qwaq/qwaq-textcontext.r | 11 ++++- 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index eb9ee8024..3da81cfe3 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1054,6 +1054,64 @@ bi_doupdate (progs_t *pr) qwaq_doupdate (pr); } +static void +qwaq_waddstr (progs_t *pr, int window_id, const char *str) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + if (get_window (res, __FUNCTION__, window_id)) { + int string_id = acquire_string (res); + dstring_t *print_buffer = res->strings + string_id; + int command[] = { + qwaq_cmd_waddstr, 0, + window_id, string_id + }; + + command[1] = CMD_SIZE(command); + + dstring_copystr (print_buffer, str); + qwaq_submit_command (res, command); + } +} +static void +bi_waddstr (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + const char *str = P_GSTRING (pr, 1); + + qwaq_waddstr (pr, window_id, str); +} + +static void +qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + if (get_window (res, __FUNCTION__, window_id)) { + int string_id = acquire_string (res); + dstring_t *print_buffer = res->strings + string_id; + int command[] = { + qwaq_cmd_mvwaddstr, 0, + window_id, x, y, string_id + }; + + command[1] = CMD_SIZE(command); + + dstring_copystr (print_buffer, str); + qwaq_submit_command (res, command); + } +} +static void +bi_mvwaddstr (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + const char *str = P_GSTRING (pr, 3); + + qwaq_mvwaddstr (pr, window_id, x, y, str); +} + static void qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, int count, pr_type_t **args) @@ -1588,11 +1646,20 @@ static void bi_i_TextContext__addch_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; - int ch = P_INT (pr, 1); + int ch = P_INT (pr, 2); qwaq_waddch (pr, window_id, ch); } +static void +bi_i_TextContext__addstr_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + const char *str = P_GSTRING (pr, 2); + + qwaq_waddstr (pr, window_id, str); +} + static void bi_i_TextContext__mvvprintf_ (progs_t *pr) { @@ -1633,6 +1700,16 @@ bi_i_TextContext__mvaddch_ (progs_t *pr) qwaq_mvwaddch (pr, window_id, pos->x, pos->y, ch); } +static void +bi_i_TextContext__mvaddstr_ (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + Point *pos = &P_PACKED (pr, Point, 2); + const char *str = P_GSTRING (pr, 3); + + qwaq_mvwaddstr (pr, window_id, pos->x, pos->y, str); +} + static void bi_i_TextContext__bkgd_ (progs_t *pr) { @@ -1696,6 +1773,8 @@ static builtin_t builtins[] = { {"mvwvprintf", bi_mvwvprintf, -1}, {"mvwaddch", bi_mvwaddch, -1}, {"waddch", bi_waddch, -1}, + {"mvwaddstr", bi_mvwaddstr, -1}, + {"waddstr", bi_waddstr, -1}, {"wrefresh", bi_wrefresh, -1}, {"get_event", bi_get_event, -1}, {"max_colors", bi_max_colors, -1}, @@ -1723,10 +1802,12 @@ static builtin_t builtins[] = { {"_i_TextContext__printf_", bi_i_TextContext__printf_, -1}, {"_i_TextContext__vprintf_", bi_i_TextContext__vprintf_, -1}, {"_i_TextContext__addch_", bi_i_TextContext__addch_, -1}, + {"_i_TextContext__addstr_", bi_i_TextContext__addstr_, -1}, {"_i_TextContext__mvvprintf_", bi_i_TextContext__mvvprintf_, -1}, {"_c_TextContext__refresh", bi_c_TextContext__refresh, -1}, {"_i_TextContext__refresh", bi_i_TextContext__refresh, -1}, {"_i_TextContext__mvaddch_", bi_i_TextContext__mvaddch_, -1}, + {"_i_TextContext__mvaddstr_", bi_i_TextContext__mvaddstr_, -1}, {"_i_TextContext__bkgd_", bi_i_TextContext__bkgd_, -1}, {"_i_TextContext__scrollok_", bi_i_TextContext__scrollok_, -1}, {"_i_TextContext__border_", bi_i_TextContext__border_, -1}, diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 70af63f7c..fc5c5c4cc 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -97,6 +97,8 @@ typedef struct panel_s *panel_t; @extern void wrefresh (window_t win); @extern void mvwaddch (window_t win, int x, int y, int ch); @extern void waddch (window_t win, int ch); +@extern void mvwaddstr (window_t win, int x, int y, string str); +@extern void waddstr (window_t win, string str); @extern panel_t create_panel (window_t window); @extern void destroy_panel (panel_t panel); diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index dd94e34c1..d7ec2a4c4 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -119,14 +119,19 @@ static TextContext *screen; return self; } -- (void) mvprintf: (Point) pos, string fmt, ... = #0; - (void) printf: (string) fmt, ... = #0; - (void) vprintf: (string) mft, @va_list args = #0; - (void) addch: (int) ch = #0; +- (void) addstr: (string) str = #0; + +- (void) mvprintf: (Point) pos, string fmt, ... = #0; - (void) mvvprintf: (Point) pos, string mft, @va_list args = #0; +- (void) mvaddch: (Point) pos, int ch = #0; +- (void) mvaddstr: (Point) pos, string str = #0; + - (void) refresh = #0; + (void) refresh = #0; -- (void) mvaddch: (Point) pos, int ch = #0; + - (void) bkgd: (int) ch = #0; - (void) scrollok: (int) flag = #0; - (void) border: (box_sides_t) sides, box_corners_t corners = #0; @@ -145,6 +150,8 @@ void mvwvprintf (window_t win, int x, int y, string fmt, @va_list args) = #0; void wrefresh (window_t win) = #0; void mvwaddch (window_t win, int x, int y, int ch) = #0; void waddch (window_t win, int ch) = #0; +void mvwaddstr (window_t win, int x, int y, string str) = #0; +void waddstr (window_t win, string str) = #0; int get_event (qwaq_event_t *event) = #0; int max_colors (void) = #0; int max_color_pairs (void) = #0; From d02a01c28207b5a8c45bcd83c3c5d7e5e6360733 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 14:46:20 +0900 Subject: [PATCH 0715/3664] [qfcc] Make tempop pointer strings more informative Now that the address of a tempop can be taken, their op strings need to be visible. --- tools/qfcc/source/statements.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index a950842e5..554473ea8 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -77,6 +77,21 @@ optype_str (op_type_e type) return op_type_names[type]; } +static const char * +tempop_string (tempop_t *tempop) +{ + if (tempop->alias) { + return va ("", + pr_type_name[tempop->type->type], + tempop, tempop->users, + &tempop->alias->o.tempop, + tempop->offset, + tempop->alias->o.tempop.users); + } + return va ("", pr_type_name[tempop->type->type], + &tempop, tempop->users); +} + const char * operand_string (operand_t *op) { @@ -110,6 +125,10 @@ operand_string (operand_t *op) return va ("ptr %s+%d", op->o.value->v.pointer.def->name, op->o.value->v.pointer.val); + } else if(op->o.value->v.pointer.tempop) { + tempop_t *tempop = op->o.value->v.pointer.tempop; + return va ("ptr %s+%d", tempop_string (tempop), + op->o.value->v.pointer.val); } else { return va ("ptr %d", op->o.value->v.pointer.val); } @@ -136,15 +155,7 @@ operand_string (operand_t *op) case op_label: return op->o.label->name; case op_temp: - if (op->o.tempop.alias) - return va ("", - pr_type_name[op->type->type], - op, op->o.tempop.users, - op->o.tempop.alias, - op->o.tempop.offset, - op->o.tempop.alias->o.tempop.users); - return va ("", pr_type_name[op->o.tempop.type->type], - op, op->o.tempop.users); + return tempop_string (&op->o.tempop); case op_alias: { const char *alias = operand_string (op->o.alias); From c5cbe83f71a8f3cc149a2f4318caa6dceb3c2aa6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 14:47:34 +0900 Subject: [PATCH 0716/3664] [qfcc] Initialize statement numbers to -1 This is to indicate the statement has not yet been flow analyzed. --- tools/qfcc/source/statements.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 554473ea8..6058c62a8 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -296,6 +296,7 @@ new_statement (st_type_t type, const char *opcode, expr_t *expr) statement->type = type; statement->opcode = save_string (opcode); statement->expr = expr; + statement->number = -1; // indicates flow analysis not done yet return statement; } From 0cbe438ac199abae3a890c72fa25c4e24fbbfd66 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 15:04:07 +0900 Subject: [PATCH 0717/3664] [util] Make va slight robust against chained use va now cycles through a set of four dstrings rather than using just the one. This allows for some simple chaining of va usage. --- libs/util/va.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/libs/util/va.c b/libs/util/va.c index aa99f7955..dd24c05d1 100644 --- a/libs/util/va.c +++ b/libs/util/va.c @@ -51,16 +51,23 @@ VISIBLE char * va (const char *fmt, ...) { va_list args; - static dstring_t *string; + static dstring_t *string[4]; +#define NUM_STRINGS (sizeof (string) / sizeof (string[0])) + static int str_index; + dstring_t *dstr; - if (!string) - string = dstring_new (); + if (!string[0]) { + for (size_t i = 0; i < NUM_STRINGS; i++) { + string[i] = dstring_new (); + } + } + dstr = string[str_index++ % NUM_STRINGS]; va_start (args, fmt); - dvsprintf (string, fmt, args); + dvsprintf (dstr, fmt, args); va_end (args); - return string->str; + return dstr->str; } VISIBLE char * From 0de011d0bf9055d3c2333fbca81ce2f10d53b3c3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 15:23:24 +0900 Subject: [PATCH 0718/3664] [qfcc] Add some disabled additional statement info It's a bit cluttered for normal debugging, but I haven't decided how to make it optional just yet. --- tools/qfcc/source/dot_sblock.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tools/qfcc/source/dot_sblock.c b/tools/qfcc/source/dot_sblock.c index 26e32681e..fc892a1c7 100644 --- a/tools/qfcc/source/dot_sblock.c +++ b/tools/qfcc/source/dot_sblock.c @@ -41,6 +41,7 @@ #include #include +#include #include #include "dags.h" @@ -62,6 +63,30 @@ flow_statement (dstring_t *dstr, statement_t *s) dasprintf (dstr, "%s", html_string(operand_string (s->opa))); dasprintf (dstr, "%s", html_string(operand_string (s->opb))); dasprintf (dstr, "%s", html_string(operand_string (s->opc))); +#if 0 + if (s->number >= 0) { + set_t *use = set_new (); + set_t *def = set_new (); + set_t *kill = set_new (); + set_t *ops = set_new (); + operand_t *operands[4]; + + flow_analyze_statement (s, use, def, kill, operands); + for (int i = 0; i < 4; i++) { + if (operands[i]) { + set_add (ops, i); + } + } + dasprintf (dstr, "%s", html_string(set_as_string (use))); + dasprintf (dstr, "%s", html_string(set_as_string (def))); + dasprintf (dstr, "%s", html_string(set_as_string (kill))); + dasprintf (dstr, "%s", html_string(set_as_string (ops))); + + set_delete (use); + set_delete (def); + set_delete (kill); + } +#endif dasprintf (dstr, "\n"); } From 6ec92fb83bf55f2a46ed07d04e239ffe5794efff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 15:28:15 +0900 Subject: [PATCH 0719/3664] [qfcc] Point pointer tempop to the operand It turns out I need the operand itself, not just the tempop. --- tools/qfcc/include/expr.h | 2 +- tools/qfcc/include/value.h | 2 +- tools/qfcc/source/emit.c | 5 +++-- tools/qfcc/source/statements.c | 15 ++++++++------- tools/qfcc/source/value.c | 2 +- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index b2e01a491..be1640ffc 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -127,7 +127,7 @@ typedef struct ex_pointer_s { int val; struct type_s *type; struct def_s *def; - struct tempop_s *tempop; + struct operand_s *tempop; } ex_pointer_t; typedef struct ex_func_s { diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index f2dc7195f..a2f13dd67 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -51,7 +51,7 @@ struct ex_value_s *new_field_val (int field_val, struct type_s *type, struct ex_value_s *new_func_val (int func_val, struct type_s *type); struct ex_value_s *new_pointer_val (int val, struct type_s *type, struct def_s *def, - struct tempop_s *tempop); + struct operand_s *tempop); struct ex_value_s *new_quaternion_val (const float *quaternion_val); struct ex_value_s *new_integer_val (int integer_val); struct ex_value_s *new_uinteger_val (int uinteger_val); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index d9b4167f6..e7a4b2465 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -63,8 +63,9 @@ static def_t zero_def; static def_t *get_operand_def (expr_t *expr, operand_t *op); static def_t * -get_tempop_def (expr_t *expr, tempop_t *tempop, type_t *type) +get_tempop_def (expr_t *expr, operand_t *tmpop, type_t *type) { + tempop_t *tempop = &tmpop->o.tempop; if (tempop->def) { return tempop->def; } @@ -115,7 +116,7 @@ get_operand_def (expr_t *expr, operand_t *op) zero_def.type = &type_short; return &zero_def; //FIXME case op_temp: - return get_tempop_def (expr, &op->o.tempop, op->type); + return get_tempop_def (expr, op, op->type); case op_alias: return get_operand_def (expr, op->o.alias); case op_nil: diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 6058c62a8..ac5d6d6f0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -78,18 +78,19 @@ optype_str (op_type_e type) } static const char * -tempop_string (tempop_t *tempop) +tempop_string (operand_t *tmpop) { + tempop_t *tempop = &tmpop->o.tempop; if (tempop->alias) { return va ("", pr_type_name[tempop->type->type], - tempop, tempop->users, - &tempop->alias->o.tempop, + tmpop, tempop->users, + tempop->alias, tempop->offset, tempop->alias->o.tempop.users); } return va ("", pr_type_name[tempop->type->type], - &tempop, tempop->users); + tmpop, tempop->users); } const char * @@ -126,7 +127,7 @@ operand_string (operand_t *op) op->o.value->v.pointer.def->name, op->o.value->v.pointer.val); } else if(op->o.value->v.pointer.tempop) { - tempop_t *tempop = op->o.value->v.pointer.tempop; + operand_t *tempop = op->o.value->v.pointer.tempop; return va ("ptr %s+%d", tempop_string (tempop), op->o.value->v.pointer.val); } else { @@ -155,7 +156,7 @@ operand_string (operand_t *op) case op_label: return op->o.label->name; case op_temp: - return tempop_string (&op->o.tempop); + return tempop_string (op); case op_alias: { const char *alias = operand_string (op->o.alias); @@ -703,7 +704,7 @@ operand_address (operand_t *reference, expr_t *e) reference = reference->o.tempop.alias; } return value_operand (new_pointer_val (offset, type, 0, - &reference->o.tempop), e); + reference), e); case op_alias: //op_alias comes only from alias_operand and that is called // by dags, so not expected diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 424dadce5..2ee44db06 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -198,7 +198,7 @@ new_func_val (int func_val, type_t *type) ex_value_t * new_pointer_val (int pointer_val, type_t *type, def_t *def, - struct tempop_s *tempop) + struct operand_s *tempop) { ex_value_t val; if (!type) { From fa2cbc72d84be5b63812c1a2d8a066466381c471 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 15:48:06 +0900 Subject: [PATCH 0720/3664] [qfcc] Analyze tempop pointers in move/memset statements --- tools/qfcc/source/flow.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index ba8868f43..febd101b6 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1054,20 +1054,28 @@ static int flow_analyize_pointer_operand (operand_t *ptrop, set_t *def, operand_t *operands[4]) { - if (ptrop->op_type == op_value - && ptrop->o.value->lltype == ev_pointer - && ptrop->o.value->v.pointer.def) { - operand_t *op; - def_t *alias; + if (ptrop->op_type == op_value && ptrop->o.value->lltype == ev_pointer) { ex_pointer_t *ptr = &ptrop->o.value->v.pointer; - alias = alias_def (ptr->def, ptr->type, ptr->val); - op = def_operand (alias, ptr->type, ptrop->expr); - flow_add_op_var (def, op, 0); - if (operands) - operands[0] = op; - else - free_operand (op); - return 1; + operand_t *op = 0; + if (ptrop->o.value->v.pointer.def) { + def_t *alias; + alias = alias_def (ptr->def, ptr->type, ptr->val); + op = def_operand (alias, ptr->type, ptrop->expr); + } + if (ptrop->o.value->v.pointer.tempop) { + op = ptrop->o.value->v.pointer.tempop; + } + if (op) { + flow_add_op_var (def, op, 0); + if (operands) { + operands[0] = op; + } else { + if (op->op_type != op_temp) { + free_operand (op); + } + } + return 1; + } } return 0; } From dec2e6249ef147a802987d622dfe80c614eeb44d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 16:32:26 +0900 Subject: [PATCH 0721/3664] [qfcc] Increase flow operand count to 5 MOVEP instructions have up to 5 operands: 2 pointers, the count, and 0-2 referenced variables (when known). --- tools/qfcc/include/flow.h | 3 ++- tools/qfcc/source/dags.c | 14 +++++++++----- tools/qfcc/source/dot_sblock.c | 4 ++-- tools/qfcc/source/flow.c | 8 ++++---- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index f57fd3c37..f68c5d5cf 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -102,9 +102,10 @@ typedef struct flowgraph_s { flowvar_t *flow_get_var (struct operand_s *op); +#define FLOW_OPERANDS 5 void flow_analyze_statement (struct statement_s *s, struct set_s *use, struct set_s *def, struct set_s *kill, - struct operand_s *operands[4]); + struct operand_s *operands[FLOW_OPERANDS]); void flow_data_flow (struct function_s *func); diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 6745a7a94..f1e1edde7 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -700,6 +700,8 @@ dag_create (flownode_t *flownode) dagnode_t **nodes; daglabel_t **labels; int num_statements = 0; + int num_nodes; + int num_lables; set_t *live_vars = set_new (); flush_daglabels (); @@ -713,14 +715,16 @@ dag_create (flownode_t *flownode) dag = new_dag (); dag->flownode = flownode; - // at most 4 per statement - dag->nodes = alloca (num_statements * 4 * sizeof (dagnode_t)); - // at most 4 per statement, + return + params - dag->labels = alloca (num_statements * (4 + 1 + 8) * sizeof (daglabel_t)); + // at most FLOW_OPERANDS per statement + num_nodes = num_statements * FLOW_OPERANDS; + dag->nodes = alloca (num_nodes * sizeof (dagnode_t)); + // at most FLOW_OPERANDS per statement, + return + params + num_lables = num_statements * (FLOW_OPERANDS + 1 + 8); + dag->labels = alloca (num_lables * sizeof (daglabel_t)); dag->roots = set_new (); for (s = block->statements; s; s = s->next) { - operand_t *operands[4]; + operand_t *operands[FLOW_OPERANDS]; dagnode_t *n = 0, *children[3] = {0, 0, 0}; daglabel_t *op, *lx; int i; diff --git a/tools/qfcc/source/dot_sblock.c b/tools/qfcc/source/dot_sblock.c index fc892a1c7..b0e975ef7 100644 --- a/tools/qfcc/source/dot_sblock.c +++ b/tools/qfcc/source/dot_sblock.c @@ -69,10 +69,10 @@ flow_statement (dstring_t *dstr, statement_t *s) set_t *def = set_new (); set_t *kill = set_new (); set_t *ops = set_new (); - operand_t *operands[4]; + operand_t *operands[FLOW_OPERANDS]; flow_analyze_statement (s, use, def, kill, operands); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < FLOW_OPERANDS; i++) { if (operands[i]) { set_add (ops, i); } diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index febd101b6..0ccf0d32a 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -509,7 +509,7 @@ static void flow_build_vars (function_t *func) { statement_t *s; - operand_t *operands[4]; + operand_t *operands[FLOW_OPERANDS]; int num_vars = 0; int i, j; set_t *stuse; @@ -1052,7 +1052,7 @@ flow_add_op_var (set_t *set, operand_t *op, int is_use) static int flow_analyize_pointer_operand (operand_t *ptrop, set_t *def, - operand_t *operands[4]) + operand_t *operands[FLOW_OPERANDS]) { if (ptrop->op_type == op_value && ptrop->o.value->lltype == ev_pointer) { ex_pointer_t *ptr = &ptrop->o.value->v.pointer; @@ -1082,7 +1082,7 @@ flow_analyize_pointer_operand (operand_t *ptrop, set_t *def, void flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, - operand_t *operands[4]) + operand_t *operands[FLOW_OPERANDS]) { int i, start, calln = -1; @@ -1093,7 +1093,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, if (kill) set_empty (kill); if (operands) { - for (i = 0; i < 4; i++) + for (i = 0; i < FLOW_OPERANDS; i++) operands[i] = 0; } From 3c2f6c8447325ae64fbbc74f93d470296b0ff6b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 21:28:10 +0900 Subject: [PATCH 0722/3664] [qfcc] Simplify flow_analyize_pointer_operand and its usage. The parts of flow_analyze_statement that use it know where the returned operand needs to go. Unfortunately, this breaks dags pretty hard, but that's because dags needs to learn about the fancy assignment-type statements. --- tools/qfcc/source/flow.c | 49 +++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 0ccf0d32a..adf417989 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1050,13 +1050,13 @@ flow_add_op_var (set_t *set, operand_t *op, int is_use) } } -static int -flow_analyize_pointer_operand (operand_t *ptrop, set_t *def, - operand_t *operands[FLOW_OPERANDS]) +static operand_t * +flow_analyze_pointer_operand (operand_t *ptrop, set_t *def) { + operand_t *op = 0; + if (ptrop->op_type == op_value && ptrop->o.value->lltype == ev_pointer) { ex_pointer_t *ptr = &ptrop->o.value->v.pointer; - operand_t *op = 0; if (ptrop->o.value->v.pointer.def) { def_t *alias; alias = alias_def (ptr->def, ptr->type, ptr->val); @@ -1067,17 +1067,9 @@ flow_analyize_pointer_operand (operand_t *ptrop, set_t *def, } if (op) { flow_add_op_var (def, op, 0); - if (operands) { - operands[0] = op; - } else { - if (op->op_type != op_temp) { - free_operand (op); - } - } - return 1; } } - return 0; + return op; } void @@ -1085,6 +1077,9 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, operand_t *operands[FLOW_OPERANDS]) { int i, start, calln = -1; + operand_t *res_op = 0; + operand_t *aux_op1 = 0; + operand_t *aux_op2 = 0; if (use) set_empty (use); @@ -1126,17 +1121,19 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, if (!strcmp (s->opcode, "") || !strcmp (s->opcode, "")) { flow_add_op_var (def, s->opc, 0); - } else if (!strcmp (s->opcode, "") - || !strcmp (s->opcode, "")) { + res_op = s->opc; + } else if (!strcmp (s->opcode, "")) { flow_add_op_var (use, s->opc, 0); - if (!flow_analyize_pointer_operand (s->opc, def, operands)) { - if (operands) { - operands[3] = s->opc; - } - } + aux_op2 = flow_analyze_pointer_operand (s->opa, use); + res_op = flow_analyze_pointer_operand (s->opc, def); + aux_op1 = s->opc; + } else if (!strcmp (s->opcode, "")) { + flow_add_op_var (use, s->opc, 0); + res_op = flow_analyze_pointer_operand (s->opc, def); + aux_op1 = s->opc; } else if (!strcmp (s->opcode, ".=")) { flow_add_op_var (use, s->opc, 1); - flow_analyize_pointer_operand (s->opb, def, operands); + res_op = flow_analyze_pointer_operand (s->opb, def); } else { internal_error (s->expr, "unexpected opcode '%s' for %d", s->opcode, s->type); @@ -1145,15 +1142,11 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, set_everything (kill); } if (operands) { - if (!strcmp (s->opcode, "") - || !strcmp (s->opcode, "")) { - operands[0] = s->opc; - } + operands[0] = res_op; operands[1] = s->opa; operands[2] = s->opb; - if (strncmp (s->opcode, "opc; - } + operands[3] = aux_op1; + operands[4] = aux_op2; } break; case st_state: From 16bda667857203a43d26d14d7dfd19eb4ede964f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 21:39:49 +0900 Subject: [PATCH 0723/3664] [qfcc] Add more statement types for move/memset They ease the statement checks between assign/move/memset and the pointer versions (don't need all those strcmps) --- tools/qfcc/include/statements.h | 13 ++++++++----- tools/qfcc/source/dags.c | 26 ++++++++++++++++++++++---- tools/qfcc/source/flow.c | 3 +++ tools/qfcc/source/statements.c | 11 +++++++---- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 26904db3d..8ee8a16f4 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -73,17 +73,20 @@ typedef struct operand_s { Statement types are broken down into expressions (binary and unary, includes address and pointer dereferencing (read)), assignment, pointer - assignment (write to dereference pointer), move (special case of pointer - assignment), state, function related (call, rcall, return and done), and - flow control (conditional branches, goto, jump (single pointer and jump - table)). + assignment (write to dereference pointer), move (special case of + assignment), pointer move (special case of pointer assignment), state, + function related (call, rcall, return and done), and flow control + (conditional branches, goto, jump (single pointer and jump table)). */ typedef enum { st_none, ///< not a (valid) statement. Used in dags. st_expr, ///< c = a op b; or c = op a; st_assign, ///< b = a st_ptrassign, ///< *b = a; or *(b + c) = a; - st_move, ///< memcpy (c, a, b); + st_move, ///< memcpy (c, a, b); c and a are direct def references + st_ptrmove, ///< memcpy (c, a, b); c and a are pointers + st_memset, ///< memset (c, a, b); c is direct def reference + st_ptrmemset, ///< memset (c, a, b); c is pointer st_state, ///< state (a, b); or state (a, b, c) st_func, ///< call, rcall or return/done st_flow, ///< if/ifa/ifae/ifb/ifbe/ifnot or goto or jump/jumpb diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index f1e1edde7..e594ca2ae 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -49,8 +49,10 @@ #include "dags.h" #include "diagnostic.h" +#include "dot.h" #include "flow.h" #include "function.h" +#include "options.h" #include "qfcc.h" #include "statements.h" #include "strpool.h" @@ -133,6 +135,11 @@ daglabel_string (daglabel_t *label) // operand_string might use quote_string, which returns a pointer to // a static variable. dstring_copystr (str, operand_string (label->op)); +#if 0 + if (label->op->type) { + dstring_appendstr (str, label->op->type->encoding); + } +#endif return quote_string (str->str); } @@ -730,10 +737,13 @@ dag_create (flownode_t *flownode) int i; dag_make_children (dag, s, operands, children); - if (s->type == st_flow || s->type == st_func) - for (i = 0; i < 3; i++) - if (children[i]) + if (s->type == st_flow || s->type == st_func) { + for (i = 0; i < 3; i++) { + if (children[i]) { dag_make_var_live (live_vars, operands[i + 1]); + } + } + } op = opcode_label (dag, s->opcode, s->expr); n = children[0]; if (s->type != st_assign @@ -759,7 +769,12 @@ dag_create (flownode_t *flownode) labels = malloc (dag->num_labels * sizeof (daglabel_t *)); memcpy (labels, dag->labels, dag->num_labels * sizeof (daglabel_t *)); dag->labels = labels; - +#if 0 + if (options.block_dot.dags) { + flownode->dag = dag; + dump_dot ("raw-dags", flownode->graph, dump_dot_flow_dags); + } +#endif dag_remove_dead_vars (dag, live_vars); dag_sort_nodes (dag); set_delete (live_vars); @@ -972,6 +987,9 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) dst = operands[0]; break; case st_move: + case st_ptrmove: + case st_memset: + case st_ptrmemset: if (!strcmp (dagnode->label->opcode, "")) { dst = generate_moves (dag, block, dagnode); break; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index adf417989..ac554d0a2 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1116,6 +1116,9 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, break; case st_ptrassign: case st_move: + case st_ptrmove: + case st_memset: + case st_ptrmemset: flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opb, 1); if (!strcmp (s->opcode, "") diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ac5d6d6f0..78173ac0b 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -758,7 +758,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) const char **opcode_set = opcode_sets[0]; const char *opcode; int need_ptr = 0; - //operand_t *dummy; + st_type_t type = st_move; if ((src && src->op_type == op_nil) || src_expr->type == ex_nil) { // switch to memset because nil is type agnostic 0 and structures @@ -769,6 +769,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) if (op) { *op = nil_operand (dst_type, src_expr); } + type = st_memset; if (is_indirect (dst_expr)) { goto dereference_dst; } @@ -815,9 +816,10 @@ dereference_dst: opcode = opcode_set[0]; } else { opcode = opcode_set[1]; + type++; // from st_move/st_memset to st_ptrmove/st_ptrmemset } - s = new_statement (st_move, opcode, e); + s = new_statement (type, opcode, e); s->opa = src; s->opb = size; s->opc = dst; @@ -932,7 +934,8 @@ expr_move (sblock_t *sblock, expr_t *e, operand_t **op) dst = *op; sblock = statement_subexpr (sblock, src_expr, &src); sblock = statement_subexpr (sblock, size_expr, &size); - s = new_statement (st_move, convert_op (e->e.expr.op), e); + s = new_statement (e->e.expr.op == 'm' ? st_move : st_ptrmove, + convert_op (e->e.expr.op), e); s->opa = src; s->opb = size; s->opc = dst; @@ -1068,7 +1071,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) dst_addr = operand_address (*op, e); - s = new_statement (st_move, "", deref); + s = new_statement (st_ptrmove, "", deref); s->opa = src_addr; //FIXME large types s->opb = short_operand (type_size (type), e); From 77806f4b1b5929be4aceeb1d138c3a15b6940685 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 22:35:36 +0900 Subject: [PATCH 0724/3664] [qfcc] Get dag code generation mostly working There's an ICE in return-ivar, but assignchain passes let alone builds. --- tools/qfcc/source/dags.c | 120 ++++++++++++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 27 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index e594ca2ae..718a6319b 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -746,13 +746,14 @@ dag_create (flownode_t *flownode) } op = opcode_label (dag, s->opcode, s->expr); n = children[0]; - if (s->type != st_assign - && !(n = dagnode_search (dag, op, children))) { - n = new_node (dag); - n->type = s->type; - n->label = op; - dagnode_add_children (dag, n, operands, children); - dagnode_set_edges (dag, n); + if (s->type != st_assign) { + if (!(n = dagnode_search (dag, op, children))) { + n = new_node (dag); + n->type = s->type; + n->label = op; + dagnode_add_children (dag, n, operands, children); + dagnode_set_edges (dag, n); + } } lx = operand_label (dag, operands[0]); if (lx && lx->dagnode != n) { @@ -893,24 +894,91 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[0] = make_operand (dag, block, dagnode, 0); operands[1] = make_operand (dag, block, dagnode, 1); + if (dagnode->children[2]) { + operands[2] = make_operand (dag, block, dagnode, 2); + st = build_statement ("", operands, dagnode->label->expr); + sblock_add_statement (block, st); + } else { + for (var_iter = set_first (dagnode->identifiers); var_iter; + var_iter = set_next (var_iter)) { + var = dag->labels[var_iter->element]; + dst = var->op; + type = dst->o.def->type; + dstDef = dst->o.def; + if (dstDef->alias) { + offset = dstDef->offset; + dstDef = dstDef->alias; + } + operands[2] = value_operand (new_pointer_val (offset, type, dstDef, 0), + operands[1]->expr); + st = build_statement ("", operands, var->expr); + sblock_add_statement (block, st); + } + } + return dst; +} + +static operand_t * +generate_memsets (dag_t *dag, sblock_t *block, dagnode_t *dagnode) +{ + set_iter_t *var_iter; + daglabel_t *var; + operand_t *operands[3] = {0, 0, 0}; + statement_t *st; + operand_t *dst; + + operands[0] = make_operand (dag, block, dagnode, 0); + operands[1] = make_operand (dag, block, dagnode, 1); + dst = operands[0]; for (var_iter = set_first (dagnode->identifiers); var_iter; var_iter = set_next (var_iter)) { var = dag->labels[var_iter->element]; - dst = var->op; - type = dst->o.def->type; - dstDef = dst->o.def; - if (dstDef->alias) { - offset = dstDef->offset; - dstDef = dstDef->alias; - } - operands[2] = value_operand (new_pointer_val (offset, type, dstDef, 0), - operands[1]->expr); - st = build_statement ("", operands, var->expr); + operands[2] = var->op; + dst = operands[2]; + st = build_statement ("", operands, var->expr); sblock_add_statement (block, st); } return dst; } +static operand_t * +generate_memsetps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) +{ + set_iter_t *var_iter; + daglabel_t *var; + operand_t *operands[3] = {0, 0, 0}; + statement_t *st; + operand_t *dst = 0; + type_t *type; + int offset = 0; + def_t *dstDef; + + operands[0] = make_operand (dag, block, dagnode, 0); + operands[1] = make_operand (dag, block, dagnode, 1); + if (dagnode->children[2]) { + operands[2] = make_operand (dag, block, dagnode, 2); + st = build_statement ("", operands, dagnode->label->expr); + sblock_add_statement (block, st); + } else { + for (var_iter = set_first (dagnode->identifiers); var_iter; + var_iter = set_next (var_iter)) { + var = dag->labels[var_iter->element]; + dst = var->op; + type = dst->o.def->type; + dstDef = dst->o.def; + if (dstDef->alias) { + offset = dstDef->offset; + dstDef = dstDef->alias; + } + operands[2] = value_operand (new_pointer_val (offset, type, dstDef, 0), + operands[1]->expr); + st = build_statement ("", operands, var->expr); + sblock_add_statement (block, st); + } + } + return dst; +} + static operand_t * generate_assignments (dag_t *dag, sblock_t *block, operand_t *src, set_iter_t *var_iter, type_t *type) @@ -987,19 +1055,17 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) dst = operands[0]; break; case st_move: + dst = generate_moves (dag, block, dagnode); + break; case st_ptrmove: + dst = generate_moveps (dag, block, dagnode); + break; case st_memset: + dst = generate_memsets (dag, block, dagnode); + break; case st_ptrmemset: - if (!strcmp (dagnode->label->opcode, "")) { - dst = generate_moves (dag, block, dagnode); - break; - } - if (!strcmp (dagnode->label->opcode, "") - && !dagnode->children[2]) { - dst = generate_moveps (dag, block, dagnode); - break; - } - //fall through + dst = generate_memsetps (dag, block, dagnode); + break; case st_state: case st_func: for (i = 0; i < 3; i++) From 34c9ec51bb2cd67866882d0208dc166a59ce1d1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 22:46:23 +0900 Subject: [PATCH 0725/3664] [qfcc] Make opcode and statement type names available --- tools/qfcc/include/statements.h | 3 +++ tools/qfcc/source/statements.c | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 8ee8a16f4..829723729 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -119,6 +119,9 @@ struct expr_s; struct type_s; struct dstring_s; +extern const char *op_type_names[]; +extern const char *st_type_names[]; + const char *optype_str (op_type_e type) __attribute__((const)); operand_t *nil_operand (struct type_s *type, struct expr_s *expr); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 78173ac0b..ba7af0765 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -60,7 +60,7 @@ #include "value.h" #include "qc-parse.h" -static const char *op_type_names[] = { +const char *op_type_names[] = { "op_def", "op_value", "op_label", @@ -69,6 +69,20 @@ static const char *op_type_names[] = { "op_nil", }; +const char *st_type_names[] = { + "st_none", + "st_expr", + "st_assign", + "st_ptrassign", + "st_move", + "st_ptrmove", + "st_memset", + "st_ptrmemset", + "st_state", + "st_func", + "st_flow", +}; + const char * optype_str (op_type_e type) { From 578bf9a16f893619b78acc98d888eb07b4aaf11f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 22:54:27 +0900 Subject: [PATCH 0726/3664] [qfcc] Set dag node value for movep This fixes compilation of all tests. However, structptr still fails. --- tools/qfcc/source/dags.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 718a6319b..6b3e3ff44 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -898,6 +898,11 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[2] = make_operand (dag, block, dagnode, 2); st = build_statement ("", operands, dagnode->label->expr); sblock_add_statement (block, st); + if ((var_iter = set_first (dagnode->identifiers))) { + var = dag->labels[var_iter->element]; + dst = var->op; + set_del_iter (var_iter); + } } else { for (var_iter = set_first (dagnode->identifiers); var_iter; var_iter = set_next (var_iter)) { From 22cd39c853d9c85dae8f976dba82868480758679 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 23:05:57 +0900 Subject: [PATCH 0727/3664] [qfcc] Mark ptr assignment offset as an operand This fixes structptr. All current tests pass. --- tools/qfcc/source/flow.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index ac554d0a2..438ece827 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1137,6 +1137,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } else if (!strcmp (s->opcode, ".=")) { flow_add_op_var (use, s->opc, 1); res_op = flow_analyze_pointer_operand (s->opb, def); + aux_op1 = s->opc; } else { internal_error (s->expr, "unexpected opcode '%s' for %d", s->opcode, s->type); From 43ea34535e9959e997d6efaaddc790b13f2d5dce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Mar 2020 23:34:37 +0900 Subject: [PATCH 0728/3664] [qfcc] Make ivar-struct-return fail It turns out that assignments to struct fields are not counted as live when the whole struct is later used via a pointer move. --- tools/qfcc/test/ivar-struct-return.r | 11 ++++++----- tools/qfcc/test/test-harness.h | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/test/ivar-struct-return.r b/tools/qfcc/test/ivar-struct-return.r index a3883b81c..8351293c8 100644 --- a/tools/qfcc/test/ivar-struct-return.r +++ b/tools/qfcc/test/ivar-struct-return.r @@ -1,4 +1,5 @@ #pragma bug die +#include "test-harness.h" struct Point { int x; @@ -11,18 +12,18 @@ typedef struct Point Point; int foo; Point origin; } --(Point) origin; ++(Point) origin; @end @implementation Object --(Point) origin ++(Point) origin { - origin = nil; + origin = {1, 2}; return origin; } @end -void __obj_exec_class (struct obj_module *msg) = #0; int main() { - return 0; // to survive and prevail + Point p = [Object origin]; + return !(p.x == 1 && p.y == 2); } diff --git a/tools/qfcc/test/test-harness.h b/tools/qfcc/test/test-harness.h index f350c7ec7..63f368416 100644 --- a/tools/qfcc/test/test-harness.h +++ b/tools/qfcc/test/test-harness.h @@ -5,3 +5,5 @@ string strerror (int err) = #0; void exit (int code) = #0; entity spawn (void) = #0; void remove (entity e) = #0; +id obj_msgSend (id receiver, SEL op, ...) = #0; +void __obj_exec_class (struct obj_module *msg) = #0; From 0293d335d01b5367c80ac87435137a28287208dc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 18 Mar 2020 00:02:36 +0900 Subject: [PATCH 0729/3664] [qfcc] Mark known source def live for movep This fixes ivar-struct-return (and qwaq). --- tools/qfcc/source/dags.c | 5 +++++ tools/qfcc/source/dot_sblock.c | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 6b3e3ff44..8b352e1c1 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -744,6 +744,11 @@ dag_create (flownode_t *flownode) } } } + if (operands[4]) { + // a movep instruction knew what it was reading, so mark that + // as live + dag_make_var_live (live_vars, operands[4]); + } op = opcode_label (dag, s->opcode, s->expr); n = children[0]; if (s->type != st_assign) { diff --git a/tools/qfcc/source/dot_sblock.c b/tools/qfcc/source/dot_sblock.c index b0e975ef7..8e003aa6b 100644 --- a/tools/qfcc/source/dot_sblock.c +++ b/tools/qfcc/source/dot_sblock.c @@ -102,11 +102,10 @@ dot_sblock (dstring_t *dstr, sblock_t *sblock, int blockno) dasprintf (dstr, " \n"); dasprintf (dstr, " %p(%d)\n", sblock, blockno); - dasprintf (dstr, " \n"); + dasprintf (dstr, " \n"); for (l = sblock->labels; l; l = l->next) dasprintf (dstr, " %s(%d)\n", l->name, l->used); dasprintf (dstr, " \n"); - dasprintf (dstr, " \n"); dasprintf (dstr, " \n"); for (s = sblock->statements; s; s = s->next) flow_statement (dstr, s); From e5bc6dd8b688eeecc9748b0370697db76eb194d2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 18 Mar 2020 01:12:23 +0900 Subject: [PATCH 0730/3664] [qwaq] Split Array(Group) into its own file --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/qwaq-garray.r | 66 ++++++++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-group.r | 63 ------------------------------------ 3 files changed, 67 insertions(+), 63 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-garray.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index dc5fa56b9..76b4af136 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -26,6 +26,7 @@ SUFFIXES=.o .r qwaq_app_dat_src= \ qwaq-app.r \ qwaq-draw.r \ + qwaq-garray.r \ qwaq-group.r \ qwaq-rect.r \ qwaq-screen.r \ diff --git a/ruamoko/qwaq/qwaq-garray.r b/ruamoko/qwaq/qwaq-garray.r new file mode 100644 index 000000000..1b7fc46d3 --- /dev/null +++ b/ruamoko/qwaq/qwaq-garray.r @@ -0,0 +1,66 @@ +#include +#include "event.h" +#include "qwaq-group.h" + +@implementation Array (Group) +- (void) makeObjectsPerformSelector: (SEL)selector + if: (condition_func)condition + with: (void *)data +{ + for (int i = 0; i < [self count]; i++) { + if (condition (_objs[i], data)) { + [_objs[i] performSelector: selector]; + } + } +} + +- (void) makeObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject + if: (condition_func2)condition + with: (void *)data +{ + for (int i = 0; i < [self count]; i++) { + if (condition (_objs[i], anObject, data)) { + [_objs[i] performSelector: selector withObject: anObject]; + } + } +} + +- (void) makeReversedObjectsPerformSelector: (SEL)selector +{ + for (int i = [self count]; i-->0; ) { + [_objs[i] performSelector: selector]; + } +} + +- (void) makeReversedObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject +{ + for (int i = [self count]; i-->0; ) { + [_objs[i] performSelector: selector withObject: anObject]; + } +} + +- (void) makeReversedObjectsPerformSelector: (SEL)selector + if: (condition_func)condition + with: (void *)data +{ + for (int i = [self count]; i-->0; ) { + if (condition (_objs[i], data)) { + [_objs[i] performSelector: selector]; + } + } +} + +- (void) makeReversedObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject + if: (condition_func2)condition + with: (void *)data +{ + for (int i = [self count]; i-->0; ) { + if (condition (_objs[i], anObject, data)) { + [_objs[i] performSelector: selector withObject: anObject]; + } + } +} +@end diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 57a5eb8a6..205f07dda 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -2,69 +2,6 @@ #include "event.h" #include "qwaq-group.h" -@implementation Array (Group) -- (void) makeObjectsPerformSelector: (SEL)selector - if: (condition_func)condition - with: (void *)data -{ - for (int i = 0; i < [self count]; i++) { - if (condition (_objs[i], data)) { - [_objs[i] performSelector: selector]; - } - } -} - -- (void) makeObjectsPerformSelector: (SEL)selector - withObject: (void *)anObject - if: (condition_func2)condition - with: (void *)data -{ - for (int i = 0; i < [self count]; i++) { - if (condition (_objs[i], anObject, data)) { - [_objs[i] performSelector: selector withObject: anObject]; - } - } -} - -- (void) makeReversedObjectsPerformSelector: (SEL)selector -{ - for (int i = [self count]; i-->0; ) { - [_objs[i] performSelector: selector]; - } -} - -- (void) makeReversedObjectsPerformSelector: (SEL)selector - withObject: (void *)anObject -{ - for (int i = [self count]; i-->0; ) { - [_objs[i] performSelector: selector withObject: anObject]; - } -} - -- (void) makeReversedObjectsPerformSelector: (SEL)selector - if: (condition_func)condition - with: (void *)data -{ - for (int i = [self count]; i-->0; ) { - if (condition (_objs[i], data)) { - [_objs[i] performSelector: selector]; - } - } -} - -- (void) makeReversedObjectsPerformSelector: (SEL)selector - withObject: (void *)anObject - if: (condition_func2)condition - with: (void *)data -{ - for (int i = [self count]; i-->0; ) { - if (condition (_objs[i], anObject, data)) { - [_objs[i] performSelector: selector withObject: anObject]; - } - } -} -@end - @implementation Group -initWithContext: (id) context From affadc3d252c8a74eefad6892527405b082ccbe6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 18 Mar 2020 01:39:12 +0900 Subject: [PATCH 0731/3664] [qwaq] Create protocols for DrawBuffer and TextContext Plenty of flaws at the moment (casts to id :/), but the basic idea seems to be ok. --- ruamoko/qwaq/qwaq-app.r | 4 +--- ruamoko/qwaq/qwaq-draw.h | 27 +++++++++++++++++---------- ruamoko/qwaq/qwaq-draw.r | 3 +++ ruamoko/qwaq/qwaq-group.h | 4 ++-- ruamoko/qwaq/qwaq-group.r | 3 +-- ruamoko/qwaq/qwaq-screen.r | 2 +- ruamoko/qwaq/qwaq-textcontext.h | 9 ++------- ruamoko/qwaq/qwaq-view.h | 8 ++------ ruamoko/qwaq/qwaq-view.r | 4 +++- ruamoko/qwaq/qwaq-window.r | 8 ++++---- 10 files changed, 36 insertions(+), 36 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 5b5889768..d8809f307 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -47,9 +47,7 @@ arp_end (void) r.offset.y = r.extent.height / 4; r.extent.width /= 2; r.extent.height /= 2; - Window *w; - [objects insert: w=[[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; - //wprintf (w.window, "%d %d %d %d\n", r.offset.x, r.offset.y, r.extent.width, r.ylen); + [objects insert: [[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; return self; } diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index 5f7c7bc18..1592559d0 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -5,20 +5,17 @@ #include "qwaq-rect.h" -@interface DrawBuffer : Object -{ - int *buffer; - Extent size; - Point cursor; -} -+ (DrawBuffer *) buffer: (Extent) size; -- initWithSize: (Extent) size; +@class DrawBuffer; +@protocol DrawBuffer +- blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; +- (Rect) rect; - (Extent) size; - (int *) buffer; -- (Rect) rect; +@end -- blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; +@protocol TextContext +- (Extent) size; - (void) printf: (string) fmt, ...; - (void) vprintf: (string) fmt, @va_list args; @@ -30,4 +27,14 @@ - (void) mvaddstr: (Point) pos, string str; @end +@interface DrawBuffer : Object +{ + int *buffer; + Extent size; + Point cursor; +} ++ (DrawBuffer *) buffer: (Extent) size; +- initWithSize: (Extent) size; +@end + #endif diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index 1311deb3c..600537215 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -41,6 +41,9 @@ Rect r = { {}, size }; Rect t = { pos, rect.extent }; + wprintf (stdscr, "src: %p\n", srcBuffer); + wprintf (stdscr, "srcSize: %d %d\n", srcSize.width, srcSize.height); + t = clipRect (r, t); if (t.extent.width < 0 || t.extent.height < 0) { return self; diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index be251b243..c534979ab 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -31,9 +31,9 @@ typedef BOOL condition_func2 (id object, void *anObject, void *data); { Array *views; int focused; - id buffer; //FIXME id or sim + id buffer; } --initWithContext: (id) context; //FIXME id or sim +-initWithContext: (id) context; -insert: (View *) view; -remove: (View *) view; @end diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 205f07dda..770834c71 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -4,14 +4,13 @@ @implementation Group --initWithContext: (id) context +-initWithContext: (id) context { if (!(self = [super init])) { return nil; } textContext = context; absRect = rect = { nil, [textContext size] }; - printf ("\n\nsize:%d %d\n\n", rect.extent.width, rect.extent.height); buffer = [DrawBuffer buffer: rect.extent]; views = [[Array array] retain]; return self; diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r index 16d3f1be6..b6149db25 100644 --- a/ruamoko/qwaq/qwaq-screen.r +++ b/ruamoko/qwaq/qwaq-screen.r @@ -14,7 +14,7 @@ return nil; } textContext = [TextContext screen]; - [textContext scrollok: 1]; + [(id)textContext scrollok: 1]; return self; } diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/qwaq-textcontext.h index 1fbcb4fbd..ce0f5ef2c 100644 --- a/ruamoko/qwaq/qwaq-textcontext.h +++ b/ruamoko/qwaq/qwaq-textcontext.h @@ -4,11 +4,12 @@ #ifdef __QFCC__ #include #include "qwaq-curses.h" +#include "qwaq-draw.h" #include "qwaq-rect.h" @class DrawBuffer; -@interface TextContext : Object +@interface TextContext : Object { window_t window; union { @@ -43,12 +44,6 @@ - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; -- (void) printf: (string) fmt, ...; -- (void) vprintf: (string) mft, @va_list args; -- (void) addch: (int) ch; -- (void) mvprintf: (Point) pos, string fmt, ...; -- (void) mvvprintf: (Point) pos, string mft, @va_list args; -- (void) mvaddch: (Point) pos, int ch; - (void) refresh; + (void) refresh; - (void) bkgd: (int) ch; diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index e6b5bd47e..54e52f03a 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -45,7 +45,7 @@ enum { Rect absRect; Point point; // can't be local :( Group *owner; - TextContext *textContext; + id textContext; int state; int options; int cursorState; @@ -65,11 +65,7 @@ enum { - (void) mvaddch: (Point) pos, int ch; @end -//These are forwarded (FIXME make a protocol) -@interface View (TextContext) -- (void) printf: (string) fmt, ...; -- (void) vprintf: (string) fmt, @va_list args; -- (void) addch: (int) ch; +@interface View (TextContext) @end #endif//__qwaq_view_h diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index b005dd4de..659e9ffbe 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -102,7 +102,9 @@ updateScreenCursor (View *view) - (void) refresh { - [textContext refresh]; + if (__obj_responds_to (textContext, @selector(refresh))) { + [(id)textContext refresh]; + } } - (void) mvprintf: (Point) pos, string fmt, ... diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index a4a69ee83..af0f576cb 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -20,7 +20,7 @@ self.rect = rect; buffer = [[TextContext alloc] initWithRect: rect]; textContext = buffer; - panel = create_panel ([buffer window]); + panel = create_panel ([(id)buffer window]); buf = [DrawBuffer buffer: {3, 3}]; [buf mvaddstr: {0, 0}, "XOX"]; [buf mvaddstr: {0, 1}, "OXO"]; @@ -74,7 +74,7 @@ -setBackground: (int) ch { - [buffer bkgd: ch]; + [(id)buffer bkgd: ch]; return self; } @@ -95,7 +95,7 @@ } } [super draw]; - [buffer border: box_sides, box_corners]; + [(id)buffer border: box_sides, box_corners]; Point pos = { 1, 1 }; //for (int i = ACS_ULCORNER; i <= ACS_STERLING; i++) { for (int i = 32; i <= 127; i++) { @@ -112,7 +112,7 @@ } } } - [textContext blitFromBuffer: buf to: makePoint (6, 3) from: [buf rect]]; + [(id)textContext blitFromBuffer: buf to: makePoint (6, 3) from: [buf rect]]; [self refresh]; return self; } From f6f6b2cba38147ca4b5dc4ef1023473148b234bd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 18 Mar 2020 01:40:58 +0900 Subject: [PATCH 0732/3664] [qwaq] Doc the issue number for blit slug --- ruamoko/qwaq/qwaq-draw.r | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index 600537215..fd0d368aa 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -73,6 +73,7 @@ for (int x = 0; x < rect.extent.width; x++) { // FIXME 1) need memcpy/memmove // 2) the generated code could be better + // github issue #3 *d++ = *s++; } } From 4c6e1b7fc4a9f15d1c180e31d4884e1b54491d2e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 18 Mar 2020 01:51:52 +0900 Subject: [PATCH 0733/3664] [qfcc] Fix some uninitialized variable warnings I really wish gcc would catch more issues when not optimizing. --- tools/qfcc/source/constfold.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index e1b380a5d..f367987a3 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -790,7 +790,7 @@ static expr_t * do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) { int isval1 = 0, isval2 = 0; - int val1, val2; + int val1 = 0, val2 = 0; static int valid[] = { '=', '+', '-', '*', '/', '&', '|', '^', '%', SHL, SHR, AND, OR, LT, GT, LE, GE, EQ, NE, 0 From 7447854d7c70aa01c72779ac0831d52d0cbf36c5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 11:01:26 +0900 Subject: [PATCH 0734/3664] [qfcc] Recover from syntax errors in abstract_decl --- tools/qfcc/source/qc-parse.y | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 7f257505b..4e49397bc 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -914,6 +914,7 @@ abstract_decl $1.type = type_default; $$->type = find_type (append_type ($$->type, $1.type)); } + | error { $$ = new_symbol (""); } ; qc_param_decl From b16093a5336ba79dd93efdae1a458525e73662d4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 11:04:02 +0900 Subject: [PATCH 0735/3664] [qwaq] Split out Array(Group) interface --- ruamoko/qwaq/qwaq-garray.h | 29 +++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-garray.r | 2 +- ruamoko/qwaq/qwaq-group.h | 24 ------------------------ ruamoko/qwaq/qwaq-group.r | 1 + 4 files changed, 31 insertions(+), 25 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-garray.h diff --git a/ruamoko/qwaq/qwaq-garray.h b/ruamoko/qwaq/qwaq-garray.h new file mode 100644 index 000000000..1a2e53576 --- /dev/null +++ b/ruamoko/qwaq/qwaq-garray.h @@ -0,0 +1,29 @@ +#ifndef __qwaq_garray_h +#define __qwaq_garray_h + +#include + +typedef BOOL condition_func (id object, void *data); +typedef BOOL condition_func2 (id object, void *anObject, void *data); + +@interface Array (Group) +- (void) makeObjectsPerformSelector: (SEL)selector + if: (condition_func)condition + with: (void *)data; +- (void) makeObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject + if: (condition_func2)condition + with: (void *)data; +- (void) makeReversedObjectsPerformSelector: (SEL)selector; +- (void) makeReversedObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject; +- (void) makeReversedObjectsPerformSelector: (SEL)selector + if: (condition_func)condition + with: (void *)data; +- (void) makeReversedObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject + if: (condition_func2)condition + with: (void *)data; +@end + +#endif//__qwaq_garray_h diff --git a/ruamoko/qwaq/qwaq-garray.r b/ruamoko/qwaq/qwaq-garray.r index 1b7fc46d3..b3298ffa4 100644 --- a/ruamoko/qwaq/qwaq-garray.r +++ b/ruamoko/qwaq/qwaq-garray.r @@ -1,6 +1,6 @@ #include #include "event.h" -#include "qwaq-group.h" +#include "qwaq-garray.h" @implementation Array (Group) - (void) makeObjectsPerformSelector: (SEL)selector diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index c534979ab..483a07c05 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -1,32 +1,8 @@ #ifndef __qwaq_group_h #define __qwaq_group_h -#include #include "qwaq-view.h" -typedef BOOL condition_func (id object, void *data); -typedef BOOL condition_func2 (id object, void *anObject, void *data); - -@interface Array (Group) -- (void) makeObjectsPerformSelector: (SEL)selector - if: (condition_func)condition - with: (void *)data; -- (void) makeObjectsPerformSelector: (SEL)selector - withObject: (void *)anObject - if: (condition_func2)condition - with: (void *)data; -- (void) makeReversedObjectsPerformSelector: (SEL)selector; -- (void) makeReversedObjectsPerformSelector: (SEL)selector - withObject: (void *)anObject; -- (void) makeReversedObjectsPerformSelector: (SEL)selector - if: (condition_func)condition - with: (void *)data; -- (void) makeReversedObjectsPerformSelector: (SEL)selector - withObject: (void *)anObject - if: (condition_func2)condition - with: (void *)data; -@end - @interface Group : View { Array *views; diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 770834c71..e9982fd1c 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -1,5 +1,6 @@ #include #include "event.h" +#include "qwaq-garray.h" #include "qwaq-group.h" @implementation Group From 2f3ca9d9e477ed96103a36cbb0d8edf6416dc90c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 11:32:44 +0900 Subject: [PATCH 0736/3664] [qwaq] Clean up the hierarchy I think I've finally figured out what I want the core hierarchy to be. Right now, it's just the two classes: View and Window (derived from View). Window has a Group, and Group is just a collection of Views that it manages. QwaqApplication is just an object but like a Window, it has a Group of views. View Window has a Group Group contains Views QwaqApplication has a group More work needs to be done on drawing and event handling, but things are working again. --- ruamoko/qwaq/qwaq-app.r | 1 + ruamoko/qwaq/qwaq-group.h | 14 +++++++++++--- ruamoko/qwaq/qwaq-group.r | 25 ++++++++++--------------- ruamoko/qwaq/qwaq-view.h | 9 ++++++++- ruamoko/qwaq/qwaq-view.r | 13 ++++++++++++- ruamoko/qwaq/qwaq-window.h | 8 ++++---- ruamoko/qwaq/qwaq-window.r | 16 +++++++++++----- 7 files changed, 57 insertions(+), 29 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index d8809f307..798c83308 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -4,6 +4,7 @@ int fence; #include "color.h" #include "qwaq-app.h" #include "qwaq-curses.h" +#include "qwaq-group.h" #include "qwaq-window.h" #include "qwaq-screen.h" #include "qwaq-view.h" diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index 483a07c05..956e43d1a 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -1,17 +1,25 @@ #ifndef __qwaq_group_h #define __qwaq_group_h -#include "qwaq-view.h" +#include -@interface Group : View +#include "event.h" +#include "qwaq-draw.h" + +@class View; + +@interface Group : Object { Array *views; int focused; - id buffer; + id context; } -initWithContext: (id) context; -insert: (View *) view; -remove: (View *) view; +-draw; +-redraw; +-handleEvent: (qwaq_event_t *) event; @end #endif//__qwaq_group_h diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index e9982fd1c..0480fbf05 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -1,7 +1,9 @@ #include #include "event.h" +#include "qwaq-draw.h" #include "qwaq-garray.h" #include "qwaq-group.h" +#include "qwaq-view.h" @implementation Group @@ -10,18 +12,7 @@ if (!(self = [super init])) { return nil; } - textContext = context; - absRect = rect = { nil, [textContext size] }; - buffer = [DrawBuffer buffer: rect.extent]; - views = [[Array array] retain]; - return self; -} - --initWithRect: (Rect) rect -{ - if (!(self = [super initWithRect: rect])) { - return nil; - } + self.context = context; views = [[Array array] retain]; return self; } @@ -34,7 +25,7 @@ -insert: (View *) view { [views addObject: view]; - view.textContext = buffer; + [view setContext: context]; return self; } @@ -58,7 +49,7 @@ not_dont_draw (id aView, void *aGroup) View *view = aView; Group *group = (Group *) aGroup; - return !(view.options & ofDontDraw); + return !([view options] & ofDontDraw); } -draw @@ -69,9 +60,13 @@ not_dont_draw (id aView, void *aGroup) return self; } +-redraw +{ + return self; +} + -handleEvent: (qwaq_event_t *) event { - [super handleEvent: event]; if (event.what & qe_focused) { if (focused >= 0) { [[views objectAtIndex:focused] handleEvent: event]; diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 54e52f03a..ef6d79568 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -53,12 +53,19 @@ enum { } -initWithRect: (Rect) rect; - (void) dealloc; + -setOwner: (Group *) owner; --(struct Rect_s *)getRect; + +-(struct Rect_s *)rect; + +-(int) options; + +-setContext: (id) context; -draw; -redraw; -handleEvent: (qwaq_event_t *) event; + - (void) refresh; - (void) mvprintf: (Point) pos, string fmt, ...; - (void) mvvprintf: (Point) pos, string fmt, @va_list args; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 659e9ffbe..5217504fd 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -27,6 +27,17 @@ [super dealloc]; } +- setContext: (id) context +{ + textContext = context; + return self; +} + +- (int) options +{ + return options; +} + static void updateScreenCursor (View *view) { @@ -84,7 +95,7 @@ updateScreenCursor (View *view) return self; } -- (Rect *) getRect +- (Rect *) rect { return ▭ } diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 2e925c035..18c4f9fc6 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -3,17 +3,17 @@ #include "Object.h" -@class Array; +@class Group; #include "qwaq-draw.h" #include "qwaq-rect.h" #include "qwaq-view.h" -#include "qwaq-group.h" -@interface Window: Group +@interface Window: View { - Point point; // FIXME can't be local :( struct panel_s *panel; + Group *objects; + Point point; // FIXME can't be local :( DrawBuffer *buf; } +windowWithRect: (Rect) rect; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index af0f576cb..0f3c81037 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -2,6 +2,7 @@ #include "event.h" #include "qwaq-curses.h" +#include "qwaq-group.h" #include "qwaq-window.h" #include "qwaq-view.h" @@ -18,9 +19,9 @@ return nil; } self.rect = rect; - buffer = [[TextContext alloc] initWithRect: rect]; - textContext = buffer; - panel = create_panel ([(id)buffer window]); + textContext = [[TextContext alloc] initWithRect: rect]; + panel = create_panel ([(id)textContext window]); + buf = [DrawBuffer buffer: {3, 3}]; [buf mvaddstr: {0, 0}, "XOX"]; [buf mvaddstr: {0, 1}, "OXO"]; @@ -28,6 +29,11 @@ return self; } +-setContext: (id) context +{ + return self; +} + -handleEvent: (qwaq_event_t *) event { /* switch (event.what) { @@ -74,7 +80,7 @@ -setBackground: (int) ch { - [(id)buffer bkgd: ch]; + [(id)textContext bkgd: ch]; return self; } @@ -95,7 +101,7 @@ } } [super draw]; - [(id)buffer border: box_sides, box_corners]; + [(id)textContext border: box_sides, box_corners]; Point pos = { 1, 1 }; //for (int i = ACS_ULCORNER; i <= ACS_STERLING; i++) { for (int i = 32; i <= 127; i++) { From 01835cbd94349f6b729e11929fc380d1b1a9ed89 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 13:48:48 +0900 Subject: [PATCH 0737/3664] [qwaq] Add blitFromBuffer to TextContext protocol --- ruamoko/qwaq/qwaq-draw.h | 1 + ruamoko/qwaq/qwaq-window.r | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index 1592559d0..efda03b41 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -15,6 +15,7 @@ @end @protocol TextContext +- blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; - (Extent) size; - (void) printf: (string) fmt, ...; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 0f3c81037..d2b52e985 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -118,7 +118,7 @@ } } } - [(id)textContext blitFromBuffer: buf to: makePoint (6, 3) from: [buf rect]]; + [textContext blitFromBuffer: buf to: makePoint (6, 3) from: [buf rect]]; [self refresh]; return self; } From 8c3cf83f02b57c09040b4600b58822648c102405 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 13:49:27 +0900 Subject: [PATCH 0738/3664] [qwaq] Add Listener and ListenerGroup delegates Simple single parameter (caller) direct messages. --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/qwaq-listener.h | 29 ++++++++++++++++ ruamoko/qwaq/qwaq-listener.r | 66 ++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 ruamoko/qwaq/qwaq-listener.h create mode 100644 ruamoko/qwaq/qwaq-listener.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 76b4af136..f0dbe4167 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -28,6 +28,7 @@ qwaq_app_dat_src= \ qwaq-draw.r \ qwaq-garray.r \ qwaq-group.r \ + qwaq-listener.r \ qwaq-rect.r \ qwaq-screen.r \ qwaq-textcontext.r \ diff --git a/ruamoko/qwaq/qwaq-listener.h b/ruamoko/qwaq/qwaq-listener.h new file mode 100644 index 000000000..bb02d71f1 --- /dev/null +++ b/ruamoko/qwaq/qwaq-listener.h @@ -0,0 +1,29 @@ +#ifndef __qwaq_listener_h +#define __qwaq_listener_h + +#include + +@class Array; + +@interface Listener : Object +{ + id responder; + SEL message; + IMP imp; +} +-initWithResponder: (id) responder message: (SEL) message; +-(void) respond: (id) caller; +-(BOOL) matchResponder: (id) responder message: (SEL) message; +@end + +@interface ListenerGroup : Object +{ + Array *listeners; +} +-init; +-addListener: (id) responder message: (SEL) message; +-removeListener: (id) responder message: (SEL) message; +-(void) respond: (id) caller; +@end + +#endif//__qwaq_listener_h diff --git a/ruamoko/qwaq/qwaq-listener.r b/ruamoko/qwaq/qwaq-listener.r new file mode 100644 index 000000000..5184668fd --- /dev/null +++ b/ruamoko/qwaq/qwaq-listener.r @@ -0,0 +1,66 @@ +#include + +#include "qwaq-listener.h" + +@class Array; + +@implementation Listener +-initWithResponder: (id) responder message: (SEL) message +{ + if (!(self = [super init])) { + return nil; + } + self.responder = responder; + self.message = message; + imp = [responder instanceMethodForSelector: message]; + return self; +} + +-(void)respond: (id) caller +{ + imp (responder, message, caller); +} + +-(BOOL) matchResponder: (id) responder message: (SEL) message +{ + return self.responder == responder && self.message == message; +} +@end + +@implementation ListenerGroup : Object +-init +{ + if (!(self = [super init])) { + return nil; + } + listeners = [[Array alloc] retain]; + return self; +} + +-addListener: (id) responder message: (SEL) message +{ + Listener *listener = [[Listener alloc] initWithResponder: responder + message: message]; + if (listener) { + [listeners addObject: listener]; + } + return self; +} + +-removeListener: (id) responder message: (SEL) message +{ + for (int i = [listeners count]; i-- > 0; ) { + Listener *l = [listeners objectAtIndex: i]; + if ([l matchResponder: responder message: message]) { + [listeners removeObjectAtIndex: i]; + } + } + return self; +} + +-(void)respond: (id) caller +{ + [listeners makeObjectsPerformSelector: @selector (respond:) + withObject: caller]; +} +@end From 03f87d6f27cc4eed12c380b5397f3ec270ba2f20 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 13:50:35 +0900 Subject: [PATCH 0739/3664] [qwaq] Add pos Point alias --- ruamoko/qwaq/qwaq-view.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index ef6d79568..920fa793e 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -36,10 +36,14 @@ enum { union { Rect rect; struct { - int xpos; - int ypos; - int xlen; - int ylen; + int xpos; + int ypos; + int xlen; + int ylen; + }; + struct { + Point pos; + Extent size; }; }; Rect absRect; From 6a18b1dd559c4324b16bae6815cf9cd9aa05506b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 13:51:14 +0900 Subject: [PATCH 0740/3664] [qwaq] Add function to merge extents It's pretty much the union of two rectangles with the same origin. --- ruamoko/qwaq/qwaq-rect.h | 1 + ruamoko/qwaq/qwaq-rect.r | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index 7cd72e886..3278afd14 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -20,6 +20,7 @@ typedef struct Rect_s { @extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); @extern Point makePoint (int x, int y); @extern Extent makeExtent (int width, int height); +@extern Extent mergeExtents (Extent a, Extent b); //XXX will not work if point or rect point to a local variabl @extern int rectContainsPoint (Rect *rect, Point *point); @extern Rect clipRect (Rect clipRect, Rect rect); diff --git a/ruamoko/qwaq/qwaq-rect.r b/ruamoko/qwaq/qwaq-rect.r index e0e3e5ee6..64048ca0b 100644 --- a/ruamoko/qwaq/qwaq-rect.r +++ b/ruamoko/qwaq/qwaq-rect.r @@ -39,6 +39,12 @@ Extent makeExtent (int width, int height) return {width, height}; } +Extent mergeExtents (Extent a, Extent b) +{ + return { a.width < b.width ? b.width : a.width, + a.height < b.height ? b.height : a.height }; +} + int rectContainsPoint (Rect *rect, Point *point) { From bd3884f6fabf940affef7c289d251ff36c35b128 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 13:52:14 +0900 Subject: [PATCH 0741/3664] [qwaq] Add a button class It may or may not work just yet, but I think it's the right direction. --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/qwaq-button.h | 28 ++++++++++++ ruamoko/qwaq/qwaq-button.r | 91 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 ruamoko/qwaq/qwaq-button.h create mode 100644 ruamoko/qwaq/qwaq-button.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index f0dbe4167..683a0923c 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -25,6 +25,7 @@ SUFFIXES=.o .r qwaq_app_dat_src= \ qwaq-app.r \ + qwaq-button.r \ qwaq-draw.r \ qwaq-garray.r \ qwaq-group.r \ diff --git a/ruamoko/qwaq/qwaq-button.h b/ruamoko/qwaq/qwaq-button.h new file mode 100644 index 000000000..2c19236d3 --- /dev/null +++ b/ruamoko/qwaq/qwaq-button.h @@ -0,0 +1,28 @@ +#ifndef __qwaq_button_h +#define __qwaq_button_h + +#include "qwaq-draw.h" +#include "qwaq-view.h" + +@class ListenerGroup; + +@interface Button : View +{ + DrawBuffer *icon[2]; + int pressed; + ListenerGroup *onPress; + ListenerGroup *onRelease; + ListenerGroup *onClick; + ListenerGroup *onDrag; + ListenerGroup *onAuto; +} +-initWithPos: (Point) pos releasedIcon: (DrawBuffer *) released + pressedIcon: (DrawBuffer *) pressed; +-(ListenerGroup *) onPress; +-(ListenerGroup *) onRelease; +-(ListenerGroup *) onClick; +-(ListenerGroup *) onDrag; +-(ListenerGroup *) onAuto; +@end + +#endif//__qwaq_button_h diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/qwaq-button.r new file mode 100644 index 000000000..d79092b0c --- /dev/null +++ b/ruamoko/qwaq/qwaq-button.r @@ -0,0 +1,91 @@ +#include "qwaq-button.h" +#include "qwaq-listener.h" + +@implementation Button +-initWithPos: (Point) pos releasedIcon: (DrawBuffer *) released + pressedIcon: (DrawBuffer *) pressed +{ + Extent size = mergeExtents ([released size], [pressed size]); + + if (!(self = [super initWithRect: {pos, size}])) { + return nil; + } + icon[0] = released; + icon[1] = pressed; + onPress = [[ListenerGroup alloc] init]; + onRelease = [[ListenerGroup alloc] init]; + onClick = [[ListenerGroup alloc] init]; + onDrag = [[ListenerGroup alloc] init]; + onAuto = [[ListenerGroup alloc] init]; + return self; +} + +-draw +{ + [textContext blitFromBuffer: icon[pressed] + to: pos + from: [icon[pressed] rect]]; + return self; +} + +-handleEvent: (qwaq_event_t *) event +{ + ListenerGroup *action = nil; + + if (event.what & qe_mouse) { + switch ((qwaq_mouse_event) (event.what & qe_mouse)) { + case qe_mousedown: + pressed = 1; + [self redraw]; + action = onPress; + break; + case qe_mouseup: + pressed = 0; + [self redraw]; + action = onRelease; + break; + case qe_mouseclick: + action = onClick; + break; + case qe_mousemove: + if (pressed) { + action = onDrag; + } + break; + case qe_mouseauto: + action = onAuto; + break; + } + if (action) { + [action respond: self]; + } + } + return self; +} + +-(ListenerGroup *) onPress +{ + return onPress; +} + +-(ListenerGroup *) onRelease +{ + return onRelease; +} + +-(ListenerGroup *) onClick +{ + return onClick; +} + +-(ListenerGroup *) onDrag +{ + return onDrag; +} + +-(ListenerGroup *) onAuto +{ + return onAuto; +} + +@end From db39f7ed3e87851b6e7fec7a5f7042a894122056 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 13:57:10 +0900 Subject: [PATCH 0742/3664] [qwaq] Add hover listener to button Forgot about this (very useful for tooltips etc). --- ruamoko/qwaq/qwaq-button.h | 2 ++ ruamoko/qwaq/qwaq-button.r | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/ruamoko/qwaq/qwaq-button.h b/ruamoko/qwaq/qwaq-button.h index 2c19236d3..470a2ae08 100644 --- a/ruamoko/qwaq/qwaq-button.h +++ b/ruamoko/qwaq/qwaq-button.h @@ -15,6 +15,7 @@ ListenerGroup *onClick; ListenerGroup *onDrag; ListenerGroup *onAuto; + ListenerGroup *onHover; } -initWithPos: (Point) pos releasedIcon: (DrawBuffer *) released pressedIcon: (DrawBuffer *) pressed; @@ -23,6 +24,7 @@ -(ListenerGroup *) onClick; -(ListenerGroup *) onDrag; -(ListenerGroup *) onAuto; +-(ListenerGroup *) onHover; @end #endif//__qwaq_button_h diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/qwaq-button.r index d79092b0c..093865576 100644 --- a/ruamoko/qwaq/qwaq-button.r +++ b/ruamoko/qwaq/qwaq-button.r @@ -17,6 +17,7 @@ onClick = [[ListenerGroup alloc] init]; onDrag = [[ListenerGroup alloc] init]; onAuto = [[ListenerGroup alloc] init]; + onHover = [[ListenerGroup alloc] init]; return self; } @@ -88,4 +89,8 @@ return onAuto; } +-(ListenerGroup *) onHover +{ + return onHover; +} @end From 3e9977c272debe36c27eeb9c8785a9123e9745fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 15:53:20 +0900 Subject: [PATCH 0743/3664] [qwaq] Give up on pass-by-reference for now It's too much hassle to ensure the passed variable isn't a local. It's just not worth the grief right now. --- ruamoko/qwaq/qwaq-rect.h | 3 +-- ruamoko/qwaq/qwaq-rect.r | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index 3278afd14..2ab79788e 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -21,8 +21,7 @@ typedef struct Rect_s { @extern Point makePoint (int x, int y); @extern Extent makeExtent (int width, int height); @extern Extent mergeExtents (Extent a, Extent b); -//XXX will not work if point or rect point to a local variabl -@extern int rectContainsPoint (Rect *rect, Point *point); +@extern int rectContainsPoint (Rect rect, Point point); @extern Rect clipRect (Rect clipRect, Rect rect); #endif diff --git a/ruamoko/qwaq/qwaq-rect.r b/ruamoko/qwaq/qwaq-rect.r index 64048ca0b..c2677decc 100644 --- a/ruamoko/qwaq/qwaq-rect.r +++ b/ruamoko/qwaq/qwaq-rect.r @@ -46,7 +46,7 @@ Extent mergeExtents (Extent a, Extent b) } int -rectContainsPoint (Rect *rect, Point *point) +rectContainsPoint (Rect rect, Point point) { return ((point.x >= rect.offset.x && point.x < rect.offset.x + rect.extent.width) From 23e6b498454d27f53b2dc173e58a890e2f1294a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 15:55:57 +0900 Subject: [PATCH 0744/3664] [qwaq] Implement mouse enter/leave events --- ruamoko/qwaq/qwaq-group.h | 2 ++ ruamoko/qwaq/qwaq-group.r | 30 ++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-view.h | 7 ++++++- ruamoko/qwaq/qwaq-view.r | 18 ++++++++++++++++-- 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index 956e43d1a..c1edd01b3 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -11,6 +11,8 @@ @interface Group : Object { Array *views; + View *mouse_grabbed; + View *mouse_within; int focused; id context; } diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 0480fbf05..75c5c2a90 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -65,6 +65,18 @@ not_dont_draw (id aView, void *aGroup) return self; } +static View * +find_mouse_view(Group *group, Point pos) +{ + for (int i = [group.views count]; i--; ) { + View *v = [group.views objectAtIndex: i]; + if ([v containsPoint: pos]) { + return v; + } + } + return nil; +} + -handleEvent: (qwaq_event_t *) event { if (event.what & qe_focused) { @@ -72,6 +84,24 @@ not_dont_draw (id aView, void *aGroup) [[views objectAtIndex:focused] handleEvent: event]; } } else if (event.what & qe_positional) { + Point pos = {event.mouse.x, event.mouse.y}; + if (mouse_grabbed) { + [mouse_grabbed handleEvent: event]; + } else { + if (mouse_within && ![mouse_within containsPoint: pos]) { + [mouse_within onMouseLeave: pos]; + mouse_within = nil; + } + if (!mouse_within) { + mouse_within = find_mouse_view (self, pos); + if (mouse_within) { + [mouse_within onMouseEnter: pos]; + } + } + if (mouse_within) { + [mouse_within handleEvent: event]; + } + } } else { // broadcast [views makeObjectsPerformSelector: @selector(draw) withObject: event]; diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 920fa793e..a7314f7e0 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -60,7 +60,9 @@ enum { -setOwner: (Group *) owner; --(struct Rect_s *)rect; +-(Rect)rect; + +-(int) containsPoint: (Point) point; -(int) options; @@ -69,6 +71,9 @@ enum { -redraw; -handleEvent: (qwaq_event_t *) event; +- (void) onMouseEnter: (Point) pos; +- (void) onMouseLeave: (Point) pos; + - (void) refresh; - (void) mvprintf: (Point) pos, string fmt, ...; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 5217504fd..b46004755 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -95,9 +95,14 @@ updateScreenCursor (View *view) return self; } -- (Rect *) rect +- (Rect) rect { - return ▭ + return rect; +} + +-(int) containsPoint: (Point) point +{ + return rectContainsPoint (rect, point); } - (void) forward: (SEL) sel : (@va_list) args @@ -144,4 +149,13 @@ updateScreenCursor (View *view) return self; } +- (void) onMouseEnter: (Point) pos +{ +} + +- (void) onMouseLeave: (Point) pos +{ +} + + @end From 19161ea80a60c4b568c738f228b14180a747adb2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 16:27:30 +0900 Subject: [PATCH 0745/3664] [qwaq] Clean things up in prep for button testing --- ruamoko/qwaq/qwaq-app.r | 2 +- ruamoko/qwaq/qwaq-group.h | 5 ++- ruamoko/qwaq/qwaq-group.r | 17 +++++++++- ruamoko/qwaq/qwaq-view.h | 2 ++ ruamoko/qwaq/qwaq-view.r | 10 ++++++ ruamoko/qwaq/qwaq-window.r | 68 +++----------------------------------- 6 files changed, 38 insertions(+), 66 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 798c83308..e040fe84c 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -40,7 +40,7 @@ arp_end (void) init_pair (2, COLOR_WHITE, COLOR_BLACK); TextContext *screen = [TextContext screen]; - objects = [[Group alloc] initWithContext: screen]; + objects = [[Group alloc] initWithContext: screen owner: nil]; [screen bkgd: COLOR_PAIR (1)]; Rect r = { nil, [screen size] }; diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index c1edd01b3..f9e4bc858 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -10,18 +10,21 @@ @interface Group : Object { + View *owner; Array *views; View *mouse_grabbed; View *mouse_within; int focused; id context; } --initWithContext: (id) context; +-initWithContext: (id) context owner: (View *) owner; -insert: (View *) view; -remove: (View *) view; -draw; -redraw; -handleEvent: (qwaq_event_t *) event; +-(void) grabMouse; +-(void) releaseMouse; @end #endif//__qwaq_group_h diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 75c5c2a90..284a8a6a3 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -7,12 +7,14 @@ @implementation Group --initWithContext: (id) context +-initWithContext: (id) context owner: (View *) owner { if (!(self = [super init])) { return nil; } + self.owner = owner; self.context = context; + focused = -1; views = [[Array array] retain]; return self; } @@ -108,4 +110,17 @@ find_mouse_view(Group *group, Point pos) } return self; } + +-(void) grabMouse +{ + mouse_grabbed = mouse_within; + [owner grabMouse]; +} + +-(void) releaseMouse +{ + mouse_grabbed = mouse_within; + [owner grabMouse]; +} + @end diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index a7314f7e0..e56a38ffa 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -63,6 +63,8 @@ enum { -(Rect)rect; -(int) containsPoint: (Point) point; +-(void) grabMouse; +-(void) releaseMouse; -(int) options; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index b46004755..6302e7db1 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -105,6 +105,16 @@ updateScreenCursor (View *view) return rectContainsPoint (rect, point); } +-(void) grabMouse +{ + [owner grabMouse]; +} + +-(void) releaseMouse +{ + [owner releaseMouse]; +} + - (void) forward: (SEL) sel : (@va_list) args { if (!textContext) { diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index d2b52e985..d0ee95fa2 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -22,6 +22,8 @@ textContext = [[TextContext alloc] initWithRect: rect]; panel = create_panel ([(id)textContext window]); + objects = [[Group alloc] initWithContext: textContext owner: self]; + buf = [DrawBuffer buffer: {3, 3}]; [buf mvaddstr: {0, 0}, "XOX"]; [buf mvaddstr: {0, 1}, "OXO"]; @@ -36,45 +38,13 @@ -handleEvent: (qwaq_event_t *) event { -/* switch (event.what) { - case qe_mouse: - mvwprintf(window, 0, 3, "%2d %2d %08x", - event.mouse.x, event.mouse.y, event.mouse.buttons); - [self redraw]; - point.x = event.mouse.x; - point.y = event.mouse.y; - for (int i = [views count]; i--> 0; ) { - View *v = [views objectAtIndex: i]; - if (rectContainsPoint (&v.absRect, &point)) { - [v handleEvent: event]; - break; - } - } - break; - case qe_key: - case qe_command: - if (focusedView) { - [focusedView handleEvent: event]; - for (int i = [views count]; - event.what != qe_none && i--> 0; ) { - View *v = [views objectAtIndex: i]; - [v handleEvent: event]; - } - } - break; - case qe_none: - break; - }*/ + [objects handleEvent: event]; return self; } -addView: (View *) view { -/* [views addObject: view]; - view.absRect.xpos = view.rect.xpos + rect.xpos; - view.absRect.ypos = view.rect.ypos + rect.ypos; - view.window = window; - [view setOwner: self];*/ + [objects insert: view]; return self; } @@ -102,35 +72,7 @@ } [super draw]; [(id)textContext border: box_sides, box_corners]; - Point pos = { 1, 1 }; - //for (int i = ACS_ULCORNER; i <= ACS_STERLING; i++) { - for (int i = 32; i <= 127; i++) { - int ch = acs_char (i); - if (ch) { - [self mvaddch: pos, ch]; - } else { - [self mvaddch: pos, '.']; - } - if (++pos.x > 32) { - pos.x = 1; - if (++pos.y >= ylen) { - break; - } - } - } - [textContext blitFromBuffer: buf to: makePoint (6, 3) from: [buf rect]]; - [self refresh]; - return self; -} - --(Rect *) getRect -{ - return ▭ -} - --setOwner: owner -{ - self.owner = owner; + [objects draw]; return self; } From 1306d9fcdd1a0094feb48e2a5205ef36c799971d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 17:33:47 +0900 Subject: [PATCH 0746/3664] [qwaq] Fix some issues in Listener* --- ruamoko/qwaq/qwaq-listener.r | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-listener.r b/ruamoko/qwaq/qwaq-listener.r index 5184668fd..14a0816aa 100644 --- a/ruamoko/qwaq/qwaq-listener.r +++ b/ruamoko/qwaq/qwaq-listener.r @@ -12,7 +12,7 @@ } self.responder = responder; self.message = message; - imp = [responder instanceMethodForSelector: message]; + imp = [responder methodForSelector: message]; return self; } @@ -33,7 +33,7 @@ if (!(self = [super init])) { return nil; } - listeners = [[Array alloc] retain]; + listeners = [[Array array] retain]; return self; } From ec2409cebad037f02b28a02430d4db7d7b5c61d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 17:34:29 +0900 Subject: [PATCH 0747/3664] [qwaq] Mention that Window knows addView --- ruamoko/qwaq/qwaq-window.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 18c4f9fc6..215fcc2db 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -18,6 +18,7 @@ } +windowWithRect: (Rect) rect; -setBackground: (int) ch; +-addView: (View *) view; @end #endif//__qwaq_window_h From 490f1ad4b8e69230d74a26edf06b067f1e549938 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 18:36:15 +0900 Subject: [PATCH 0748/3664] [qwaq] Add wrappers for werase --- ruamoko/qwaq/qwaq-curses.c | 45 +++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-curses.h | 1 + ruamoko/qwaq/qwaq-textcontext.r | 2 ++ 3 files changed, 48 insertions(+) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 3da81cfe3..cfad0c6ff 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -76,6 +76,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_wrefresh, qwaq_cmd_init_pair, qwaq_cmd_wbkgd, + qwaq_cmd_werase, qwaq_cmd_scrollok, qwaq_cmd_move, qwaq_cmd_curs_set, @@ -104,6 +105,7 @@ const char *qwaq_command_names[]= { "wrefresh", "init_pair", "wbkgd", + "werase", "scrollok", "move", "curs_set", @@ -578,6 +580,15 @@ cmd_wbkgd (qwaq_resources_t *res) wbkgd (window->win, ch); } +static void +cmd_werase (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + + window_t *window = get_window (res, __FUNCTION__, window_id); + werase (window->win); +} + static void cmd_scrollok (qwaq_resources_t *res) { @@ -717,6 +728,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_wbkgd: cmd_wbkgd (res); break; + case qwaq_cmd_werase: + cmd_werase (res); + break; case qwaq_cmd_scrollok: cmd_scrollok (res); break; @@ -1384,6 +1398,26 @@ bi_wbkgd (progs_t *pr) qwaq_wbkgd (pr, window_id, ch); } +static void +qwaq_werase (progs_t *pr, int window_id, int ch) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_werase, 0, window_id, }; + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} +static void +bi_werase (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + int ch = P_INT (pr, 1); + + qwaq_werase (pr, window_id, ch); +} + static void qwaq_scrollok (progs_t *pr, int window_id, int flag) { @@ -1719,6 +1753,15 @@ bi_i_TextContext__bkgd_ (progs_t *pr) qwaq_wbkgd (pr, window_id, ch); } +static void +bi_i_TextContext__clear (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + int ch = P_INT (pr, 2); + + qwaq_werase (pr, window_id, ch); +} + static void bi_i_TextContext__scrollok_ (progs_t *pr) { @@ -1781,6 +1824,7 @@ static builtin_t builtins[] = { {"max_color_pairs", bi_max_color_pairs, -1}, {"init_pair", bi_init_pair, -1}, {"wbkgd", bi_wbkgd, -1}, + {"werase", bi_werase, -1}, {"scrollok", bi_scrollok, -1}, {"acs_char", bi_acs_char, -1}, {"move", bi_move, -1}, @@ -1809,6 +1853,7 @@ static builtin_t builtins[] = { {"_i_TextContext__mvaddch_", bi_i_TextContext__mvaddch_, -1}, {"_i_TextContext__mvaddstr_", bi_i_TextContext__mvaddstr_, -1}, {"_i_TextContext__bkgd_", bi_i_TextContext__bkgd_, -1}, + {"_i_TextContext__clear", bi_i_TextContext__clear, -1}, {"_i_TextContext__scrollok_", bi_i_TextContext__scrollok_, -1}, {"_i_TextContext__border_", bi_i_TextContext__border_, -1}, diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index fc5c5c4cc..6d0c43df2 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -116,6 +116,7 @@ typedef struct panel_s *panel_t; @extern int max_color_pairs (void); @extern int init_pair (int pair, int f, int b); @extern void wbkgd (window_t win, int ch); +@extern void werase (window_t win); @extern void scrollok (window_t win, int flag); @extern int acs_char (int acs); diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index d7ec2a4c4..85507dfce 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -133,6 +133,7 @@ static TextContext *screen; + (void) refresh = #0; - (void) bkgd: (int) ch = #0; +- (void) clear = #0; - (void) scrollok: (int) flag = #0; - (void) border: (box_sides_t) sides, box_corners_t corners = #0; @@ -157,6 +158,7 @@ int max_colors (void) = #0; int max_color_pairs (void) = #0; int init_pair (int pair, int f, int b) = #0; void wbkgd (window_t win, int ch) = #0; +void werase (window_t win) = #0; void scrollok (window_t win, int flag) = #0; int acs_char (int acs) = #0; From e49ba896aad3e117263d900ffaa1a4982a56034b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 18:37:25 +0900 Subject: [PATCH 0749/3664] [qwaq] Support background and clearing in DrawBuffer --- ruamoko/qwaq/qwaq-draw.h | 3 +++ ruamoko/qwaq/qwaq-draw.r | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index efda03b41..65599347f 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -18,6 +18,8 @@ - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; - (Extent) size; +- (void) bkgd: (int) ch; +- (void) clear; - (void) printf: (string) fmt, ...; - (void) vprintf: (string) fmt, @va_list args; - (void) addch: (int) ch; @@ -33,6 +35,7 @@ int *buffer; Extent size; Point cursor; + int background; } + (DrawBuffer *) buffer: (Extent) size; - initWithSize: (Extent) size; diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index fd0d368aa..947d349f7 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -80,6 +80,26 @@ return self; } +- (void) bkgd: (int) ch +{ + if ((ch & 0xff) < 32) { + ch = (ch & ~0xff) | 32; + } + background = ch; +} + +- (void) clear +{ + int ch = background; + int *dst = buffer; + int *end = buffer + size.width * size.height; + + while (dst < end) { + *dst++ = ch; + } + cursor = {0, 0}; +} + - (void) printf: (string) fmt, ... { string str = vsprintf (fmt, @args); @@ -113,6 +133,12 @@ } else if (ch == '\r') { cursor.x = 0; } else { + if ((ch & 0xff) < 32) { + ch = (ch & ~0xff) | 32; + } + if (!(ch & ~0xff)) { + ch |= background & ~0xff; + } buffer[cursor.y * size.width + cursor.x++] = ch; } } From 8bd702ab1a5dc0097b43dc12fbf3faadcfb1e82a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 18:38:24 +0900 Subject: [PATCH 0750/3664] [qwaq] Fetch View origin and size separately --- ruamoko/qwaq/qwaq-view.h | 2 ++ ruamoko/qwaq/qwaq-view.r | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index e56a38ffa..2bb646653 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -61,6 +61,8 @@ enum { -setOwner: (Group *) owner; -(Rect)rect; +-(Point)origin; +-(Extent)size; -(int) containsPoint: (Point) point; -(void) grabMouse; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 6302e7db1..936a83352 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -100,6 +100,17 @@ updateScreenCursor (View *view) return rect; } +-(Point)origin +{ + return pos; +} + +-(Extent)size +{ + return size; +} + + -(int) containsPoint: (Point) point { return rectContainsPoint (rect, point); From 28a9e041e64678777c2c6a0ab4bf3fbd3cf5bb34 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 18:39:11 +0900 Subject: [PATCH 0751/3664] [qwaq] Implement Group redraw --- ruamoko/qwaq/qwaq-group.r | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 284a8a6a3..a358a4f59 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -64,6 +64,14 @@ not_dont_draw (id aView, void *aGroup) -redraw { + if (owner) { + [owner redraw]; + } else { + [self draw]; + if (__obj_responds_to (context, @selector(refresh))) { + [(id)context refresh]; + } + } return self; } From cce6837fe8119a0832c1721e0357d63c23143e66 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 18:40:21 +0900 Subject: [PATCH 0752/3664] [qwaq] Offset event mouse coordinates Each level of the object hierarchy has its own offset relative to the level above, but mouse coordinates are absolute. --- ruamoko/qwaq/qwaq-button.r | 1 + ruamoko/qwaq/qwaq-group.r | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/qwaq-button.r index 093865576..cece78609 100644 --- a/ruamoko/qwaq/qwaq-button.r +++ b/ruamoko/qwaq/qwaq-button.r @@ -23,6 +23,7 @@ -draw { + [super draw]; [textContext blitFromBuffer: icon[pressed] to: pos from: [icon[pressed] rect]]; diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index a358a4f59..48eca7bd6 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -94,6 +94,12 @@ find_mouse_view(Group *group, Point pos) [[views objectAtIndex:focused] handleEvent: event]; } } else if (event.what & qe_positional) { + Point origin = {}; + if (owner) { + origin = [owner origin]; + } + event.mouse.x -= origin.x; + event.mouse.y -= origin.y; Point pos = {event.mouse.x, event.mouse.y}; if (mouse_grabbed) { [mouse_grabbed handleEvent: event]; @@ -112,6 +118,8 @@ find_mouse_view(Group *group, Point pos) [mouse_within handleEvent: event]; } } + event.mouse.x += origin.x; + event.mouse.y += origin.y; } else { // broadcast [views makeObjectsPerformSelector: @selector(draw) withObject: event]; From 2c20a031e41592bd2d6833eb46c9a2d900e6d729 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 18:41:53 +0900 Subject: [PATCH 0753/3664] [qwaq] Do up a little button test "scene" Hmm... "scene"... too much Unity? --- ruamoko/qwaq/qwaq-app.h | 4 +++ ruamoko/qwaq/qwaq-app.r | 57 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index 7062ad096..db341c7a3 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -6,6 +6,7 @@ #include "event.h" @class Group; +@class TextContext; @interface QwaqApplication: Object { @@ -13,6 +14,9 @@ qwaq_command endState; Group *objects; + + TextContext *screen; + int autocount; } -run; -draw; diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index e040fe84c..9df5bf3e1 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -3,8 +3,10 @@ int fence; #include "color.h" #include "qwaq-app.h" +#include "qwaq-button.h" #include "qwaq-curses.h" #include "qwaq-group.h" +#include "qwaq-listener.h" #include "qwaq-window.h" #include "qwaq-screen.h" #include "qwaq-view.h" @@ -38,8 +40,10 @@ arp_end (void) initialize (); init_pair (1, COLOR_WHITE, COLOR_BLUE); init_pair (2, COLOR_WHITE, COLOR_BLACK); + init_pair (3, COLOR_WHITE, COLOR_GREEN); + init_pair (4, COLOR_YELLOW, COLOR_RED); - TextContext *screen = [TextContext screen]; + screen = [TextContext screen]; objects = [[Group alloc] initWithContext: screen owner: nil]; [screen bkgd: COLOR_PAIR (1)]; @@ -48,10 +52,59 @@ arp_end (void) r.offset.y = r.extent.height / 4; r.extent.width /= 2; r.extent.height /= 2; - [objects insert: [[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; + Window *w; + [objects insert: w = [[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; + DrawBuffer *released = [DrawBuffer buffer: {12, 1}]; + DrawBuffer *pressed = [DrawBuffer buffer: {12, 1}]; + Button *b = [[Button alloc] initWithPos: {3, 4} releasedIcon: released + pressedIcon: pressed]; + [w addView: b]; + [released bkgd: COLOR_PAIR(3)]; + [released clear]; + [released mvaddstr: {2, 0}, "press me"]; + [pressed bkgd: COLOR_PAIR(4)]; + [pressed clear]; + [pressed mvaddstr: {1, 0}, "release me"]; + [[b onPress] addListener: self message: @selector (buttonPressed:)]; + [[b onRelease] addListener: self message: @selector (buttonReleased:)]; + [[b onClick] addListener: self message: @selector (buttonClick:)]; + [[b onDrag] addListener: self message: @selector (buttonDrag:)]; + [[b onAuto] addListener: self message: @selector (buttonAuto:)]; return self; } +-(void) buttonPressed: (id) sender +{ + [screen mvaddstr: {2, 0}, " pressed"]; + [screen refresh]; +} + +-(void) buttonReleased: (id) sender +{ + [screen mvaddstr: {2, 0}, "released"]; + [screen refresh]; +} + +-(void) buttonClick: (id) sender +{ + [screen mvaddstr: {2, 0}, "clicked "]; + [screen refresh]; +} + +-(void) buttonDrag: (id) sender +{ + [screen mvaddstr: {2, 0}, "dragged "]; + Rect rect = [sender rect]; + [screen mvprintf: {15, 0}, "%d %d", rect.offset.x, rect.offset.y]; + [screen refresh]; +} + +-(void) buttonAuto: (id) sender +{ + [screen mvprintf: {2, 1}, "%d", autocount++]; + [screen refresh]; +} + -run { [self draw]; From 95d20d67c77897d30cb79d9791c1f6f9fec986ea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 19:00:03 +0900 Subject: [PATCH 0754/3664] [qwaq] Implement mouse grabbing Button will need it for dragging. --- ruamoko/qwaq/qwaq-app.r | 2 +- ruamoko/qwaq/qwaq-button.r | 6 ++++-- ruamoko/qwaq/qwaq-group.r | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 9df5bf3e1..7d5ed4ba2 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -40,7 +40,7 @@ arp_end (void) initialize (); init_pair (1, COLOR_WHITE, COLOR_BLUE); init_pair (2, COLOR_WHITE, COLOR_BLACK); - init_pair (3, COLOR_WHITE, COLOR_GREEN); + init_pair (3, COLOR_BLACK, COLOR_GREEN); init_pair (4, COLOR_YELLOW, COLOR_RED); screen = [TextContext screen]; diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/qwaq-button.r index cece78609..6287de9ce 100644 --- a/ruamoko/qwaq/qwaq-button.r +++ b/ruamoko/qwaq/qwaq-button.r @@ -38,13 +38,15 @@ switch ((qwaq_mouse_event) (event.what & qe_mouse)) { case qe_mousedown: pressed = 1; - [self redraw]; action = onPress; + [self grabMouse]; + [self redraw]; break; case qe_mouseup: pressed = 0; - [self redraw]; action = onRelease; + [self releaseMouse]; + [self redraw]; break; case qe_mouseclick: action = onClick; diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 48eca7bd6..c8af9bf8a 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -27,6 +27,7 @@ -insert: (View *) view { [views addObject: view]; + [view setOwner: self]; [view setContext: context]; return self; } @@ -135,8 +136,8 @@ find_mouse_view(Group *group, Point pos) -(void) releaseMouse { - mouse_grabbed = mouse_within; - [owner grabMouse]; + mouse_grabbed = nil; + [owner releaseMouse]; } @end From e8d947ed8a7314e58d48d8f5a0fb118b73b6c008 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 19:25:57 +0900 Subject: [PATCH 0755/3664] [qwaq] Get click and drag reporting working --- ruamoko/qwaq/qwaq-app.r | 12 ++++++------ ruamoko/qwaq/qwaq-button.h | 6 ++++++ ruamoko/qwaq/qwaq-button.r | 21 +++++++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 7d5ed4ba2..2aaf62880 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -75,33 +75,33 @@ arp_end (void) -(void) buttonPressed: (id) sender { - [screen mvaddstr: {2, 0}, " pressed"]; + [screen mvaddstr: {2, 0}, " pressed "]; [screen refresh]; } -(void) buttonReleased: (id) sender { - [screen mvaddstr: {2, 0}, "released"]; + [screen mvaddstr: {2, 0}, "released "]; [screen refresh]; } -(void) buttonClick: (id) sender { - [screen mvaddstr: {2, 0}, "clicked "]; + [screen mvprintf: {2, 1}, "clicked %d", [sender click]]; [screen refresh]; } -(void) buttonDrag: (id) sender { [screen mvaddstr: {2, 0}, "dragged "]; - Rect rect = [sender rect]; - [screen mvprintf: {15, 0}, "%d %d", rect.offset.x, rect.offset.y]; + Point delta = [sender delta]; + [screen mvprintf: {15, 0}, "%3d %3d", delta.x, delta.y]; [screen refresh]; } -(void) buttonAuto: (id) sender { - [screen mvprintf: {2, 1}, "%d", autocount++]; + [screen mvprintf: {2, 2}, "%d", autocount++]; [screen refresh]; } diff --git a/ruamoko/qwaq/qwaq-button.h b/ruamoko/qwaq/qwaq-button.h index 470a2ae08..bab624e35 100644 --- a/ruamoko/qwaq/qwaq-button.h +++ b/ruamoko/qwaq/qwaq-button.h @@ -10,6 +10,9 @@ { DrawBuffer *icon[2]; int pressed; + int click; + Point dragBase; + Point dragPos; ListenerGroup *onPress; ListenerGroup *onRelease; ListenerGroup *onClick; @@ -25,6 +28,9 @@ -(ListenerGroup *) onDrag; -(ListenerGroup *) onAuto; -(ListenerGroup *) onHover; + +- (int) click; +- (Point) delta; @end #endif//__qwaq_button_h diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/qwaq-button.r index 6287de9ce..fe7aa5f2f 100644 --- a/ruamoko/qwaq/qwaq-button.r +++ b/ruamoko/qwaq/qwaq-button.r @@ -38,25 +38,35 @@ switch ((qwaq_mouse_event) (event.what & qe_mouse)) { case qe_mousedown: pressed = 1; + click = 0; + dragBase = {event.mouse.x, event.mouse.y}; action = onPress; [self grabMouse]; [self redraw]; break; case qe_mouseup: pressed = 0; + click = 0; action = onRelease; [self releaseMouse]; + if ([self containsPoint: {event.mouse.x, event.mouse.y}]) { + [onClick respond: self]; + } [self redraw]; break; case qe_mouseclick: action = onClick; + click = event.mouse.click; break; case qe_mousemove: + click = 0; if (pressed) { + dragPos = {event.mouse.x, event.mouse.y}; action = onDrag; } break; case qe_mouseauto: + click = 0; action = onAuto; break; } @@ -96,4 +106,15 @@ { return onHover; } + +- (int) click +{ + return click; +} + +- (Point) delta +{ + return {dragPos.x - dragBase.x, dragPos.y - dragBase.y}; +} + @end From 14fbdc7df91c090fa87b78cc30319effb90fb21a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 19:35:19 +0900 Subject: [PATCH 0756/3664] [qwaq] Clean up debug in TextContext --- ruamoko/qwaq/qwaq-textcontext.r | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 85507dfce..d2fd9144b 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -74,19 +74,7 @@ static TextContext *screen; Rect r = { {}, size }; Rect t = { pos, rect.extent }; - wprintf (stdscr, "src: %p\n", srcBuffer); - wprintf (stdscr, "srcSize: %d %d\n", srcSize.width, srcSize.height); - wprintf (stdscr, "pos: %d %d\n", pos.x, pos.x); - wprintf (stdscr, "rect: %d %d %d %d\n", - rect.offset.x, rect.offset.y, - rect.extent.width, rect.extent.height); - wprintf (stdscr, "r: %d %d %d %d\n", - r.offset.x, r.offset.y, r.extent.width, r.extent.height); - wprintf (stdscr, "t: %d %d %d %d\n", - t.offset.x, t.offset.y, t.extent.width, t.extent.height); t = clipRect (r, t); - wprintf (stdscr, "t: %d %d %d %d\n", - t.offset.x, t.offset.y, t.extent.width, t.extent.height); if (t.extent.width < 0 || t.extent.height < 0) { return self; } @@ -100,12 +88,6 @@ static TextContext *screen; r.extent = size; rect = clipRect (r, rect); - wprintf (stdscr, "pos: %d %d\n", pos.x, pos.x); - wprintf (stdscr, "rect: %d %d %d %d\n", - rect.offset.x, rect.offset.y, - rect.extent.width, rect.extent.height); - wprintf (stdscr, "r: %d %d %d %d\n", - r.offset.x, r.offset.y, r.extent.width, r.extent.height); if (rect.extent.width < 0 || rect.extent.height < 0) { return self; } From f027a42e72679d561a237cac5cd4ed8120186981 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 19:53:32 +0900 Subject: [PATCH 0757/3664] [qwaq] Treat 0 as transparent character --- ruamoko/qwaq/qwaq-curses.c | 4 +++- ruamoko/qwaq/qwaq-draw.r | 5 +---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index cfad0c6ff..c3dcf1b4c 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -649,7 +649,9 @@ cmd_mvwblit_line (qwaq_resources_t *res) getyx (window->win, save_y, save_x); for (int i = 0; i < len; i++) { Sys_Printf(" %d", chs[i]); - mvwaddch (window->win, y, x + i, chs[i]); + if (chs[i] & 0xff) { + mvwaddch (window->win, y, x + i, chs[i]); + } } Sys_Printf("\n"); wmove (window->win, save_y, save_x); diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index 947d349f7..31975ef19 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -82,9 +82,6 @@ - (void) bkgd: (int) ch { - if ((ch & 0xff) < 32) { - ch = (ch & ~0xff) | 32; - } background = ch; } @@ -132,7 +129,7 @@ cursor.y++; } else if (ch == '\r') { cursor.x = 0; - } else { + } else if (ch & 0xff) { if ((ch & 0xff) < 32) { ch = (ch & ~0xff) | 32; } From fe4f8315120db57323b53c5642a8335785778554 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 20:31:01 +0900 Subject: [PATCH 0758/3664] [qwaq] Remove a pile of stray panel_free calls C&P programming FTW :P --- ruamoko/qwaq/qwaq-curses.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index c3dcf1b4c..afb2ca246 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -436,7 +436,6 @@ cmd_hide_panel (qwaq_resources_t *res) panel_t *panel = get_panel (res, __FUNCTION__, panel_id); hide_panel (panel->panel); - panel_free (res, panel); } static void @@ -446,7 +445,6 @@ cmd_show_panel (qwaq_resources_t *res) panel_t *panel = get_panel (res, __FUNCTION__, panel_id); show_panel (panel->panel); - panel_free (res, panel); } static void @@ -456,7 +454,6 @@ cmd_top_panel (qwaq_resources_t *res) panel_t *panel = get_panel (res, __FUNCTION__, panel_id); top_panel (panel->panel); - panel_free (res, panel); } static void @@ -466,7 +463,6 @@ cmd_bottom_panel (qwaq_resources_t *res) panel_t *panel = get_panel (res, __FUNCTION__, panel_id); bottom_panel (panel->panel); - panel_free (res, panel); } static void @@ -478,7 +474,6 @@ cmd_move_panel (qwaq_resources_t *res) panel_t *panel = get_panel (res, __FUNCTION__, panel_id); move_panel (panel->panel, y, x); - panel_free (res, panel); } static void @@ -648,12 +643,10 @@ cmd_mvwblit_line (qwaq_resources_t *res) window_t *window = get_window (res, __FUNCTION__, window_id); getyx (window->win, save_y, save_x); for (int i = 0; i < len; i++) { - Sys_Printf(" %d", chs[i]); if (chs[i] & 0xff) { mvwaddch (window->win, y, x + i, chs[i]); } } - Sys_Printf("\n"); wmove (window->win, save_y, save_x); release_string (res, chs_id); } @@ -663,12 +656,12 @@ process_commands (qwaq_resources_t *res) { while (RB_DATA_AVAILABLE (res->command_queue) >= 2) { qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); - int len = RB_PEEK_DATA (res->command_queue, 1); - Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); - for (int i = 2; i < len; i++) { - Sys_Printf (" %d", RB_PEEK_DATA (res->command_queue, i)); - } - Sys_Printf ("\n"); + //int len = RB_PEEK_DATA (res->command_queue, 1); + //Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); + //for (int i = 2; i < len; i++) { + // Sys_Printf (" %d", RB_PEEK_DATA (res->command_queue, i)); + //} + //Sys_Printf ("\n"); switch (cmd) { case qwaq_cmd_newwin: cmd_newwin (res); From 3a28d84c3fc992647d5478c6ebc1bcedf9eca845 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 20:31:59 +0900 Subject: [PATCH 0759/3664] [qwaq] Implement window dragging Other than the stray panel_free, that was surprisingly easy. However, do need to check that the window can be moved otherwise window pos and panel pos will get out of sync. --- ruamoko/qwaq/qwaq-window.r | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index d0ee95fa2..35a0af8b4 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -1,8 +1,11 @@ #include +#include #include "event.h" +#include "qwaq-button.h" #include "qwaq-curses.h" #include "qwaq-group.h" +#include "qwaq-listener.h" #include "qwaq-window.h" #include "qwaq-view.h" @@ -24,6 +27,15 @@ objects = [[Group alloc] initWithContext: textContext owner: self]; + string titlestr = "drag me"; + DrawBuffer *title = [DrawBuffer buffer: {xlen, 1}]; + [title mvaddstr: {(xlen - strlen(titlestr)) / 2, 0}, titlestr]; + + Button *b = [[Button alloc] initWithPos: {0, 0} releasedIcon: title + pressedIcon: title]; + [[b onDrag] addListener: self message: @selector(dragWindow:)]; + [self addView: b]; + buf = [DrawBuffer buffer: {3, 3}]; [buf mvaddstr: {0, 0}, "XOX"]; [buf mvaddstr: {0, 1}, "OXO"]; @@ -31,6 +43,15 @@ return self; } +- (void) dragWindow: (Button *) sender +{ + Point delta = [sender delta]; + xpos += delta.x; + ypos += delta.y; + move_panel (panel, xpos, ypos); + [owner redraw]; +} + -setContext: (id) context { return self; From f329ca83b67ec73ad54dc0c8e02d642eb24d1d35 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 20:39:23 +0900 Subject: [PATCH 0760/3664] [qwaq] Ensure background color clearing works Even with 0 for the character, colors should get into the buffer. --- ruamoko/qwaq/qwaq-draw.r | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index 31975ef19..757f00e90 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -91,6 +91,9 @@ int *dst = buffer; int *end = buffer + size.width * size.height; + if (ch && !(ch & 0xff)) { + ch |= ' '; + } while (dst < end) { *dst++ = ch; } @@ -129,10 +132,7 @@ cursor.y++; } else if (ch == '\r') { cursor.x = 0; - } else if (ch & 0xff) { - if ((ch & 0xff) < 32) { - ch = (ch & ~0xff) | 32; - } + } else { if (!(ch & ~0xff)) { ch |= background & ~0xff; } From ac23156ecd9cf1d6d3309752033240b1be0278e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 21:28:55 +0900 Subject: [PATCH 0761/3664] [qwaq] Clamp window motion to owner's bounds --- ruamoko/qwaq/qwaq-group.h | 3 +++ ruamoko/qwaq/qwaq-group.r | 24 ++++++++++++++++++++++++ ruamoko/qwaq/qwaq-window.r | 20 +++++++++++++++++--- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index f9e4bc858..eaa7606eb 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -20,6 +20,9 @@ -initWithContext: (id) context owner: (View *) owner; -insert: (View *) view; -remove: (View *) view; +-(Rect) rect; +-(Point) origin; +-(Extent) size; -draw; -redraw; -handleEvent: (qwaq_event_t *) event; diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index c8af9bf8a..2df05bcba 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -46,6 +46,30 @@ return self; } +-(Rect) rect +{ + if (owner) { + return [owner rect]; + } + return {[self origin], [self size]}; +} + +-(Point) origin +{ + if (owner) { + return [owner origin]; + } + return {0, 0}; +} + +-(Extent) size +{ + if (owner) { + return [owner size]; + } + return [context size]; +} + static BOOL not_dont_draw (id aView, void *aGroup) { diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 35a0af8b4..2235a82c9 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -46,9 +46,23 @@ - (void) dragWindow: (Button *) sender { Point delta = [sender delta]; - xpos += delta.x; - ypos += delta.y; - move_panel (panel, xpos, ypos); + Point p = {xpos + delta.x, ypos + delta.y}; + Extent bounds = [owner size]; + if (p.x < 0) { + p.x = 0; + } + if (p.x + xlen > bounds.width) { + p.x = bounds.width - xlen; + } + if (p.y < 0) { + p.y = 0; + } + if (p.y + ylen > bounds.height) { + p.y = bounds.height - ylen; + } + xpos = p.x; + ypos = p.y; + move_panel (panel, p.x, p.y); [owner redraw]; } From 65538104bf1f5eec12279ba8026cd9dea805ac91 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 23:18:01 +0900 Subject: [PATCH 0762/3664] [qwaq] Tweak listener message names I didn't like the message:message bit --- ruamoko/qwaq/qwaq-app.r | 10 +++++----- ruamoko/qwaq/qwaq-listener.h | 8 ++++---- ruamoko/qwaq/qwaq-listener.r | 12 ++++++------ ruamoko/qwaq/qwaq-window.r | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 2aaf62880..beeb02788 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -65,11 +65,11 @@ arp_end (void) [pressed bkgd: COLOR_PAIR(4)]; [pressed clear]; [pressed mvaddstr: {1, 0}, "release me"]; - [[b onPress] addListener: self message: @selector (buttonPressed:)]; - [[b onRelease] addListener: self message: @selector (buttonReleased:)]; - [[b onClick] addListener: self message: @selector (buttonClick:)]; - [[b onDrag] addListener: self message: @selector (buttonDrag:)]; - [[b onAuto] addListener: self message: @selector (buttonAuto:)]; + [[b onPress] addListener: self : @selector (buttonPressed:)]; + [[b onRelease] addListener: self : @selector (buttonReleased:)]; + [[b onClick] addListener: self : @selector (buttonClick:)]; + [[b onDrag] addListener: self : @selector (buttonDrag:)]; + [[b onAuto] addListener: self : @selector (buttonAuto:)]; return self; } diff --git a/ruamoko/qwaq/qwaq-listener.h b/ruamoko/qwaq/qwaq-listener.h index bb02d71f1..2f7ec02b3 100644 --- a/ruamoko/qwaq/qwaq-listener.h +++ b/ruamoko/qwaq/qwaq-listener.h @@ -11,9 +11,9 @@ SEL message; IMP imp; } --initWithResponder: (id) responder message: (SEL) message; +-initWithResponder: (id) responder :(SEL)message; -(void) respond: (id) caller; --(BOOL) matchResponder: (id) responder message: (SEL) message; +-(BOOL) matchResponder: (id) responder :(SEL)message; @end @interface ListenerGroup : Object @@ -21,8 +21,8 @@ Array *listeners; } -init; --addListener: (id) responder message: (SEL) message; --removeListener: (id) responder message: (SEL) message; +-addListener: (id) responder :(SEL)message; +-removeListener: (id) responder :(SEL)message; -(void) respond: (id) caller; @end diff --git a/ruamoko/qwaq/qwaq-listener.r b/ruamoko/qwaq/qwaq-listener.r index 14a0816aa..26e6f28c5 100644 --- a/ruamoko/qwaq/qwaq-listener.r +++ b/ruamoko/qwaq/qwaq-listener.r @@ -5,7 +5,7 @@ @class Array; @implementation Listener --initWithResponder: (id) responder message: (SEL) message +-initWithResponder: (id) responder :(SEL)message { if (!(self = [super init])) { return nil; @@ -21,7 +21,7 @@ imp (responder, message, caller); } --(BOOL) matchResponder: (id) responder message: (SEL) message +-(BOOL) matchResponder: (id) responder :(SEL)message { return self.responder == responder && self.message == message; } @@ -37,21 +37,21 @@ return self; } --addListener: (id) responder message: (SEL) message +-addListener: (id) responder :(SEL)message { Listener *listener = [[Listener alloc] initWithResponder: responder - message: message]; + : message]; if (listener) { [listeners addObject: listener]; } return self; } --removeListener: (id) responder message: (SEL) message +-removeListener: (id) responder :(SEL)message { for (int i = [listeners count]; i-- > 0; ) { Listener *l = [listeners objectAtIndex: i]; - if ([l matchResponder: responder message: message]) { + if ([l matchResponder: responder : message]) { [listeners removeObjectAtIndex: i]; } } diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 2235a82c9..1c772867f 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -33,7 +33,7 @@ Button *b = [[Button alloc] initWithPos: {0, 0} releasedIcon: title pressedIcon: title]; - [[b onDrag] addListener: self message: @selector(dragWindow:)]; + [[b onDrag] addListener: self : @selector(dragWindow:)]; [self addView: b]; buf = [DrawBuffer buffer: {3, 3}]; From ec12941fcbbf72fe12c2990d4ebb40f7a77d50d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Mar 2020 23:53:54 +0900 Subject: [PATCH 0763/3664] Move the ring buffer macros to their own header They seem to have proven themselves to be robust. --- include/QF/Makefile.am | 3 +- include/QF/ringbuffer.h | 103 +++++++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-curses.c | 73 +------------------------- 3 files changed, 106 insertions(+), 73 deletions(-) create mode 100644 include/QF/ringbuffer.h diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am index 724d192df..c0fda5cd1 100644 --- a/include/QF/Makefile.am +++ b/include/QF/Makefile.am @@ -11,7 +11,8 @@ include_qf= \ msg.h object.h pak.h pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h \ pr_obj.h pr_type.h progs.h qargs.h qdefs.h qendian.h qfplist.h qtypes.h \ quakefs.h \ - quakeio.h render.h riff.h ruamoko.h screen.h script.h segtext.h set.h \ + quakeio.h render.h riff.h ringbuffer.h ruamoko.h \ + screen.h script.h segtext.h set.h \ sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h tga.h va.h \ ver_check.h vid.h vrect.h view.h wad.h wadfile.h winding.h zone.h \ \ diff --git a/include/QF/ringbuffer.h b/include/QF/ringbuffer.h new file mode 100644 index 000000000..cc289640e --- /dev/null +++ b/include/QF/ringbuffer.h @@ -0,0 +1,103 @@ +/* + ringbuffer.h + + ring buffer + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_ringbuffer_h +#define __QF_ringbuffer_h + +#define RING_BUFFER(type, size) \ + struct { \ + type buffer[size]; \ + unsigned head; \ + unsigned tail; \ + } + +#define RB_buffer_size(ring_buffer) \ + ({ __auto_type rb = (ring_buffer); \ + sizeof (rb->buffer) / sizeof (rb->buffer[0]); \ + }) + +#define RB_SPACE_AVAILABLE(ring_buffer) \ + ({ __auto_type rb = &(ring_buffer); \ + (rb->tail + RB_buffer_size(rb) - rb->head - 1) % RB_buffer_size(rb);\ + }) + +#define RB_DATA_AVAILABLE(ring_buffer) \ + ({ __auto_type rb = &(ring_buffer); \ + (rb->head + RB_buffer_size (rb) - rb->tail) % RB_buffer_size (rb); \ + }) + +#define RB_WRITE_DATA(ring_buffer, data, count) \ + ({ __auto_type rb = &(ring_buffer); \ + const typeof (rb->buffer[0]) *d = (data); \ + unsigned c = (count); \ + unsigned h = rb->head; \ + rb->head = (h + c) % RB_buffer_size (rb); \ + if (c > RB_buffer_size (rb) - h) { \ + memcpy (rb->buffer + h, d, \ + (RB_buffer_size (rb) - h) * sizeof (rb->buffer[0])); \ + c -= RB_buffer_size (rb) - h; \ + d += RB_buffer_size (rb) - h; \ + h = 0; \ + } \ + memcpy (rb->buffer + h, d, c * sizeof (rb->buffer[0])); \ + }) + +#define RB_READ_DATA(ring_buffer, data, count) \ + ({ __auto_type rb = &(ring_buffer); \ + typeof (&rb->buffer[0]) d = (data); \ + unsigned c = (count); \ + unsigned oc = c; \ + unsigned t = rb->tail; \ + if (c > RB_buffer_size (rb) - t) { \ + memcpy (d, rb->buffer + t, \ + (RB_buffer_size (rb) - t) * sizeof (rb->buffer[0])); \ + c -= RB_buffer_size (rb) - t; \ + d += RB_buffer_size (rb) - t; \ + t = 0; \ + } \ + memcpy (d, rb->buffer + t, c * sizeof (rb->buffer[0])); \ + rb->tail = (t + oc) % RB_buffer_size (rb); \ + }) + +#define RB_DROP_DATA(ring_buffer, count) \ + ({ __auto_type rb = &(ring_buffer); \ + unsigned c = (count); \ + unsigned t = rb->tail; \ + rb->tail = (t + c) % RB_buffer_size (rb); \ + }) + +#define RB_PEEK_DATA(ring_buffer, ahead) \ + ({ __auto_type rb = &(ring_buffer); \ + rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)]; \ + }) + +#define RB_POKE_DATA(ring_buffer, ahead, data) \ + ({ __auto_type rb = &(ring_buffer); \ + rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)] = (data); \ + }) + +#endif//__QF_ringbuffer_h diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index afb2ca246..3837d2f8c 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -39,6 +39,7 @@ #include "QF/dstring.h" #include "QF/progs.h" +#include "QF/ringbuffer.h" #include "QF/sys.h" #include "qwaq.h" @@ -113,78 +114,6 @@ const char *qwaq_command_names[]= { "mvwblit_line", }; -#define RING_BUFFER(type, size) \ - struct { \ - type buffer[size]; \ - unsigned head; \ - unsigned tail; \ - } - -#define RB_buffer_size(ring_buffer) \ - ({ __auto_type rb = (ring_buffer); \ - sizeof (rb->buffer) / sizeof (rb->buffer[0]); \ - }) - -#define RB_SPACE_AVAILABLE(ring_buffer) \ - ({ __auto_type rb = &(ring_buffer); \ - (rb->tail + RB_buffer_size(rb) - rb->head - 1) % RB_buffer_size(rb);\ - }) - -#define RB_DATA_AVAILABLE(ring_buffer) \ - ({ __auto_type rb = &(ring_buffer); \ - (rb->head + RB_buffer_size (rb) - rb->tail) % RB_buffer_size (rb); \ - }) - -#define RB_WRITE_DATA(ring_buffer, data, count) \ - ({ __auto_type rb = &(ring_buffer); \ - const typeof (rb->buffer[0]) *d = (data); \ - unsigned c = (count); \ - unsigned h = rb->head; \ - rb->head = (h + c) % RB_buffer_size (rb); \ - if (c > RB_buffer_size (rb) - h) { \ - memcpy (rb->buffer + h, d, \ - (RB_buffer_size (rb) - h) * sizeof (rb->buffer[0])); \ - c -= RB_buffer_size (rb) - h; \ - d += RB_buffer_size (rb) - h; \ - h = 0; \ - } \ - memcpy (rb->buffer + h, d, c * sizeof (rb->buffer[0])); \ - }) - -#define RB_READ_DATA(ring_buffer, data, count) \ - ({ __auto_type rb = &(ring_buffer); \ - typeof (&rb->buffer[0]) d = (data); \ - unsigned c = (count); \ - unsigned oc = c; \ - unsigned t = rb->tail; \ - if (c > RB_buffer_size (rb) - t) { \ - memcpy (d, rb->buffer + t, \ - (RB_buffer_size (rb) - t) * sizeof (rb->buffer[0])); \ - c -= RB_buffer_size (rb) - t; \ - d += RB_buffer_size (rb) - t; \ - t = 0; \ - } \ - memcpy (d, rb->buffer + t, c * sizeof (rb->buffer[0])); \ - rb->tail = (t + oc) % RB_buffer_size (rb); \ - }) - -#define RB_DROP_DATA(ring_buffer, count) \ - ({ __auto_type rb = &(ring_buffer); \ - unsigned c = (count); \ - unsigned t = rb->tail; \ - rb->tail = (t + c) % RB_buffer_size (rb); \ - }) - -#define RB_PEEK_DATA(ring_buffer, ahead) \ - ({ __auto_type rb = &(ring_buffer); \ - rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)]; \ - }) - -#define RB_POKE_DATA(ring_buffer, ahead, data) \ - ({ __auto_type rb = &(ring_buffer); \ - rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)] = (data); \ - }) - typedef struct window_s { WINDOW *win; } window_t; From 79719babda27b73daf2ff437d0933fab60711e38 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 12:55:23 +0900 Subject: [PATCH 0764/3664] [util] Fix darray test for gcc purity --- libs/util/test/test-darray.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/test/test-darray.c b/libs/util/test/test-darray.c index 59dbad0ab..59d3a2ddc 100644 --- a/libs/util/test/test-darray.c +++ b/libs/util/test/test-darray.c @@ -51,7 +51,7 @@ check_array (int a, int b) return !!intarray.a; } -static int +static int __attribute__((pure)) check_value (int index, int b) { if ((size_t) index >= intarray.size) { From f64038b8725b3838faf5701ddfa926ab3d8abc11 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 11:46:16 +0900 Subject: [PATCH 0765/3664] [qfcc] Add gcd.pas to the tests --- tools/qfcc/test/Makefile.am | 16 +++++++++++++++- tools/qfcc/test/{old => }/gcd.pas | 0 2 files changed, 15 insertions(+), 1 deletion(-) rename tools/qfcc/test/{old => }/gcd.pas (100%) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index ceb32813f..f6f0c6043 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -13,11 +13,15 @@ QCFLAGS=-qq -O -g -Werror QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) -SUFFIXES=.qfo .r +SUFFIXES=.qfo .r .pas .r.qfo: $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo +.pas.qfo: + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< + sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo QFCC_TEST_LIBS=@QFCC_TEST_LIBS@ QFCC_TEST_DEPS=@QFCC_TEST_DEPS@ @@ -43,6 +47,7 @@ test_progs_dat=\ fordecl.dat \ func-expr.dat \ func-static.dat \ + gcd.dat \ infloop.dat \ ivar-struct-return.dat \ methodparams.dat \ @@ -262,6 +267,15 @@ func-static.run: Makefile build-run include ./$(DEPDIR)/func-static.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/func-static.Qo +gcd_dat_SOURCES=gcd.pas +gcd_obj=$(gcd_dat_SOURCES:.pas=.qfo) +gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(gcd_obj) +gcd.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/gcd.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/gcd.Qo + infloop_dat_SOURCES=infloop.r infloop_obj=$(infloop_dat_SOURCES:.r=.qfo) infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/old/gcd.pas b/tools/qfcc/test/gcd.pas similarity index 100% rename from tools/qfcc/test/old/gcd.pas rename to tools/qfcc/test/gcd.pas From ed03eeb8d2fed9a08cfee67807de71510f7ef6b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 11:47:01 +0900 Subject: [PATCH 0766/3664] [qfcc] Resync qc and qp common symbols Forgot I needed to remove PAS from pascal as well. --- tools/qfcc/source/qp-parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 922068b02..08759a544 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -105,7 +105,7 @@ int yylex (void); %nonassoc STORAGEX %left COMMA -%right '=' ASX PAS /* pointer assign */ +%right '=' ASX %right '?' ':' %left OR %left AND From 298fcbbf708883c2fdff49fb33b059b61436dc6c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 11:48:01 +0900 Subject: [PATCH 0767/3664] [qfcc] Add ExitCode support to quake-pascal gcd now passes :) --- tools/qfcc/source/qp-parse.y | 43 ++++++++++++++++++++++++++++-------- tools/qfcc/test/gcd.pas | 6 +++-- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 08759a544..730eab57a 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -139,6 +139,29 @@ int yylex (void); %type sign %{ + +static void +build_dotmain (symbol_t *program) +{ + symbol_t *dotmain = new_symbol (".main"); + expr_t *code; + expr_t *exitcode; + + dotmain->params = 0; + dotmain->type = parse_params (&type_integer, 0); + dotmain->type = find_type (dotmain->type); + dotmain = function_symbol (dotmain, 0, 1); + + exitcode = new_symbol_expr (symtab_lookup (current_symtab, "ExitCode")); + + current_func = begin_function (dotmain, 0, current_symtab, 0); + current_symtab = current_func->symtab; + code = new_block_expr (); + append_expr (code, function_expr (new_symbol_expr (program), 0)); + append_expr (code, return_expr (current_func, exitcode)); + build_code_function (dotmain, 0, code); +} + %} %% @@ -159,15 +182,7 @@ program build_code_function ($1, 0, $4); current_symtab = st; - $4 = function_expr (new_symbol_expr ($1), 0); - $1 = new_symbol (".main"); - $1->params = 0; - $1->type = parse_params (&type_void, 0); - $1->type = find_type ($1->type); - $1 = function_symbol ($1, 0, 1); - current_func = begin_function ($1, 0, current_symtab, 0); - current_symtab = current_func->symtab; - build_code_function ($1, 0, $4); + build_dotmain ($1); current_symtab = st; } ; @@ -178,6 +193,15 @@ program_head { $$ = $3; + // FIXME need units and standard units + { + symbol_t *sym = new_symbol ("ExitCode"); + sym->type = &type_integer; + initialize_def (sym, 0, current_symtab->space, sc_global); + if (sym->s.def) { + sym->s.def->nosave = 1; + } + } $$->type = parse_params (&type_void, 0); $$->type = find_type ($$->type); $$ = function_symbol ($$, 0, 1); @@ -375,6 +399,7 @@ statement else : ELSE { + // this is only to get the the file and line number info $$ = new_nil_expr (); } ; diff --git a/tools/qfcc/test/gcd.pas b/tools/qfcc/test/gcd.pas index 04e193b26..3879a3d3d 100644 --- a/tools/qfcc/test/gcd.pas +++ b/tools/qfcc/test/gcd.pas @@ -1,5 +1,5 @@ program example (input, output); -var x, y: integer; +var x, y, g: integer; procedure printf (format:string; ...) := #0; function gcd (a, b: integer): integer; var c: quaternion; @@ -11,5 +11,7 @@ end; begin x := 130; y := 120; - printf ("%d\n", gcd (x, y)) + g := gcd (x, y); + printf ("%d\n", g); + ExitCode := g <> 10; end. From 966bd267c58839839394613cecc0a5b0a1208862 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 16:17:21 +0900 Subject: [PATCH 0768/3664] Add a set of macros for dynamic arrays Includes docs and test cases. --- include/QF/darray.h | 301 +++++++++++++++++++++++++++++++++++ libs/util/test/Makefile.am | 9 +- libs/util/test/test-darray.c | 213 +++++++++++++++++++++++++ 3 files changed, 521 insertions(+), 2 deletions(-) create mode 100644 include/QF/darray.h create mode 100644 libs/util/test/test-darray.c diff --git a/include/QF/darray.h b/include/QF/darray.h new file mode 100644 index 000000000..88792715f --- /dev/null +++ b/include/QF/darray.h @@ -0,0 +1,301 @@ +/* + darray.h + + Dynamic arrays + + Copyright (C) 2020 Bill Currie + + Author: Bill Currie + Date: 2020/02/17 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __pr_type_h +#define __pr_type_h + +/** \defgroup darray Dynamic Arrays + \ingroup utils + + Dynamic array container object +*/ +///@{ + +/** The structure defs for a dynamic array with elements of the given type. + + This is just the defs of a struct delcaration: it is useless on its own. + The intended usage is something like: + + typedef struct dynamic_array_s DARRAY_TYPE(int) dynamic_array_t; + + This allows full flexibility in just how the actual type is used. + + The \a size field is the number of elements currently in the array, and + the \a maxSize field is the number of elements the array can hold without + being resized. + + The \a grow field specifies the number of elements by which \a maxSize is + to grow when the array needs to be resized. Setting this to 0 prevents + resizing and any attempt to do so is a fatal error. + + \param ele_type The type to use for the element array, which is accessed + by the \a a field. + \hideinitializer +*/ +#define DARRAY_TYPE(ele_type) \ + { \ + size_t size; \ + size_t maxSize; \ + size_t grow; \ + ele_type *a; \ + } + +/** Clear the array. + + If the array can grow, its backing will be freed and maxSize and a reset, + otherwise maxSize and a are left untouched. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \hideinitializer +*/ +#define DARRAY_CLEAR(array) \ + do { \ + __auto_type ar = (array); \ + free (ar->a); \ + ar->size = 0; \ + if (ar->grow) { \ + ar->maxSize = 0; \ + ar->a = 0; \ + } \ + } while (0) + +/** Set the size of the array. + + If the new size is greater than maxSize, and the array can grow (grow is + non-zero), then maxSize will be increased to the smallest multiple of grow + greater than or equal to size (ie, maxSize >= size, maxSize % grow == 0). + + Attempting to increase maxSize on an array that cannot grow is an error: + it is assumed that the array struct does not own the backing memory. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param newSize The new size of the array: newly opened slots are + uninitialized, but old slots retain their values. + \hideinitializer +*/ +#define DARRAY_RESIZE(array, newSize) \ + do { \ + __auto_type ar = (array); \ + size_t ns = (newSize); \ + if (__builtin_expect (ns > ar->maxSize, 0)) { \ + if (__builtin_expect (!ar->grow, 0)) { \ + Sys_Error ("Attempt to grow fixed-size darray: %s:%d", \ + __FILE__, __LINE__); \ + } \ + ar->maxSize = ar->grow * ((ns + ar->grow - 1) / ar->grow); \ + ar->a = realloc (ar->a, ar->maxSize * sizeof (*ar->a)); \ + if (__builtin_expect (!ar->a, 0)) { \ + Sys_Error ("failed to realloc darray: %s:%d", \ + __FILE__, __LINE__); \ + } \ + } \ + ar->size = ns; \ + } while (0) + +/** Append a value to the end of the array. + + The array is grown by one and the value written to the newly opened slot. + + If the new array size is greater than maxSize and the array can be grown, + the array backing will be resized to the next multiple of grow. + + Attempting to grow an array that cannot grow is an error: it is assumed + that the array struct does not own the backing memory. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param value The value to be appended to the array. Must be of a type + compatible with that used for creating the array struct. + \return The appended value: can be assigned to another compatible + value. + \hideinitializer +*/ +#define DARRAY_APPEND(array, value) \ + ({ \ + __auto_type ar = (array); \ + __auto_type ob = (value); \ + size_t sz = ar->size; \ + DARRAY_RESIZE (ar, ar->size + 1); \ + ar->a[sz] = ob; \ + }) + +/** Open a hole in the array for bulk copying of data. + + The array is grown by the requested size, opening a hole at the specified + index. Values beyond the index are copied to just after the newly opened + hole. + + If the new array size is greater than maxSize and the array can be grown, + the array backing will be resized to the next multiple of grow. + + Attempting to grow an array that cannot grow is an error: it is assumed + that the array struct does not own the backing memory. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param index The index at which the hole will begin. + \param space The sized of the hole to be opened, in array elements. + \return The *address* of the newly opened hole: can be passed to + memcpy and friends. + + memcpy (DARRAY_OPEN_AT(array, index, size), data, + size * sizeof (*data)); + \hideinitializer +*/ +#define DARRAY_OPEN_AT(array, index, space) \ + ({ \ + __auto_type ar = (array); \ + size_t po = (index); \ + size_t sp = (space); \ + if (__builtin_expect (po > ar->size, 0)) { \ + Sys_Error ("Attempt to insert elements outside darray: " \ + "%s:%d", __FILE__, __LINE__); \ + } \ + DARRAY_RESIZE (ar, ar->size + sp); \ + memmove (&ar->a[po + sp], &ar->a[po], \ + (ar->size - po) * sizeof (*ar->a)); \ + &ar->a[po]; \ + }) + +/** Insert a value into the array at the specified index. + + The array is grown by one at the specified index and the value written + to the newly opened slot. Values beyond the index are copied to just + after the newly opened slot. + + If the new array size is greater than maxSize and the array can be grown, + the array backing will be resized to the next multiple of grow. + + Attempting to grow an array that cannot grow is an error: it is assumed + that the array struct does not own the backing memory. + + Attempting to insert a value beyond one past the end of the array is an + error (inserting at index = size is valid). + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param value The value to be inserted into the array. Must be of a type + compatible with that used for creating the array struct. + \param index The index at which the value will be inserted + \return The inserted value: can be assigned to another compatible + value. + \hideinitializer +*/ +#define DARRAY_INSERT_AT(array, value, index) \ + ({ \ + __auto_type ar = (array); \ + __auto_type ob = (value); \ + *DARRAY_OPEN_AT (ar, index, 1) = ob; \ + }) + +/** Close a segment of an array. + + The values beyond the segment are copied to the beginning of the segment + and the array size reduced by the size of the segment. All but the first + one of the values previously in the segment are lost and gone forever. + + Attempting to close a segment that extends outside the array is an error. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param index The index of the beginning of the segment. + \param count The number of values in the segment. + \return The single value at the beginning of the segment: can be + assigned to another compatible value. + \hideinitializer +*/ +#define DARRAY_CLOSE_AT(array, index, count) \ + ({ \ + __auto_type ar = (array); \ + size_t po = (index); \ + size_t co = (count); \ + if (__builtin_expect (po + co > ar->size \ + || po >= ar->size, 0)) { \ + Sys_Error ("Attempt to remove elements outside darray: " \ + "%s:%d", __FILE__, __LINE__); \ + } \ + __auto_type ob = ar->a[po]; \ + memmove (&ar->a[po], &ar->a[po + co], \ + (ar->size - po - co) * sizeof (ob)); \ + ar->size -= co; \ + ob; \ + }) + +/** Remove a value from an array at the specified index. + + The values beyond the index are moved down to fill the hole left by the + single value and the array size reduced by one. + + Attempting to remove a value from beyond the array is an error. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param index The index of the value to be removed. + \return The removed value: can be assigned to another compatible + value. + \hideinitializer +*/ +#define DARRAY_REMOVE_AT(array, index) \ + ({ \ + __auto_type ar = (array); \ + DARRAY_CLOSE_AT (ar, index, 1); \ + }) + +/** Remove (pop) a value from the end of an array. + + The size of the array size reduced by one. + + Attempting to remove a value from an empty array is an error. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \return The removed value: can be assigned to another compatible + value. + \hideinitializer +*/ +#define DARRAY_REMOVE(array) \ + ({ \ + __auto_type ar = (array); \ + DARRAY_CLOSE_AT (ar, ar->size - 1, 1); \ + }) + +///@} + +#endif//__pr_type_h diff --git a/libs/util/test/Makefile.am b/libs/util/test/Makefile.am index 283ac561e..74d9a2f4e 100644 --- a/libs/util/test/Makefile.am +++ b/libs/util/test/Makefile.am @@ -3,8 +3,9 @@ AUTOMAKE_OPTIONS= foreign AM_CPPFLAGS= -I$(top_srcdir)/include check_PROGRAMS= \ - test-bary test-cs test-dq test-half test-mat3 test-mat4 test-plist \ - test-qfs test-quat test-seb test-seg test-set test-txtbuffer test-vrect + test-bary test-cs test-darray test-dq test-half test-mat3 test-mat4 \ + test-plist test-qfs test-quat test-seb test-seg test-set test-txtbuffer \ + test-vrect test_bary_SOURCES=test-bary.c test_bary_LDADD=$(top_builddir)/libs/util/libQFutil.la @@ -14,6 +15,10 @@ test_cs_SOURCES=test-cs.c test_cs_LDADD=$(top_builddir)/libs/util/libQFutil.la test_cs_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la +test_darray_SOURCES=test-darray.c +test_darray_LDADD=$(top_builddir)/libs/util/libQFutil.la +test_darray_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la + test_dq_SOURCES=test-dq.c test_dq_LDADD=$(top_builddir)/libs/util/libQFutil.la test_dq_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la diff --git a/libs/util/test/test-darray.c b/libs/util/test/test-darray.c new file mode 100644 index 000000000..59dbad0ab --- /dev/null +++ b/libs/util/test/test-darray.c @@ -0,0 +1,213 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#define remove remove_renamed +#include +#include +#include + +#include "QF/darray.h" +#include "QF/sys.h" +#undef remove + +typedef int (*test_func) (int a, int b); +typedef struct intarray_s DARRAY_TYPE(int) intarray_t; + +intarray_t intarray = {0, 0, 16, 0}; + +static int +append (int val, int b) +{ + return DARRAY_APPEND (&intarray, val); +} + +static int +check_size (int a, int b) +{ + return intarray.size; +} + +static int +check_maxSize (int a, int b) +{ + return intarray.maxSize; +} + +static int +check_grow (int a, int b) +{ + return intarray.grow; +} + +static int +check_maxSizeGrowth (int a, int b) +{ + return intarray.maxSize % intarray.grow; +} + +static int +check_array (int a, int b) +{ + return !!intarray.a; +} + +static int +check_value (int index, int b) +{ + if ((size_t) index >= intarray.size) { + Sys_Error ("indexing beyond array"); + } + return intarray.a[index]; +} + +static int +insert_at (int val, int pos) +{ + return DARRAY_INSERT_AT (&intarray, val, pos); +} + +static int +open_at (int pos, int size) +{ + return DARRAY_OPEN_AT (&intarray, pos, size) - intarray.a; +} + +static const char text[] = "Aloy is an awesome huntress."; +static int +open_at2 (int pos, int size) +{ + memcpy(DARRAY_OPEN_AT (&intarray, pos, size), text, size * sizeof (int)); + return strcmp((char*) (intarray.a + pos), text); +} + +static int +remove_at (int pos, int b) +{ + return DARRAY_REMOVE_AT (&intarray, pos); +} + +static int +remove (int pos, int b) +{ + return DARRAY_REMOVE (&intarray); +} + +static int +close_at (int pos, int size) +{ + return DARRAY_CLOSE_AT (&intarray, pos, size); +} + +static int +clear (int a, int b) +{ + DARRAY_CLEAR (&intarray); + return 0; +} + +static int +resize (int size, int b) +{ + DARRAY_RESIZE (&intarray, size); + return 0; +} + +struct { + test_func test; + int param1, param2; + int test_expect; +} tests[] = { + {check_size, 0, 0, 0}, // confirm array empty but can grow + {check_maxSize, 0, 0, 0}, + {check_grow, 0, 0, 16}, + {check_array, 0, 0, 0}, + {append, 5, 0, 5}, // test first append to emtpty array + {check_size, 0, 0, 1}, + {check_maxSizeGrowth, 0, 0, 0}, + {check_maxSize, 0, 0, 16}, + {check_array, 0, 0, 1}, + {check_value, 0, 0, 5}, + {append, 42, 0, 42}, // test a second append + {check_size, 0, 0, 2}, + {check_maxSize, 0, 0, 16}, + {check_value, 0, 0, 5}, + {check_value, 1, 0, 42}, + {insert_at, 69, 1, 69}, // test insertions + {insert_at, 96, 0, 96}, + {check_size, 0, 0, 4}, + {check_maxSize, 0, 0, 16}, + {check_value, 0, 0, 96}, + {check_value, 1, 0, 5}, + {check_value, 2, 0, 69}, + {check_value, 3, 0, 42}, + {open_at, 2, 14, 2}, // test opening a large hole + {check_maxSizeGrowth, 0, 0, 0}, + {check_maxSize, 0, 0, 32}, + {check_size, 0, 0, 18}, + {check_value, 0, 0, 96}, + {check_value, 1, 0, 5}, + {check_value, 16, 0, 69}, + {check_value, 17, 0, 42}, + {close_at, 1, 15, 5}, // test block removal + {check_maxSize, 0, 0, 32}, + {check_size, 0, 0, 3}, + {check_value, 0, 0, 96}, + {check_value, 1, 0, 69}, + {check_value, 2, 0, 42}, + {remove, 0, 0, 42}, // test "pop" + {check_maxSize, 0, 0, 32}, + {check_size, 0, 0, 2}, + {check_value, 0, 0, 96}, + {check_value, 1, 0, 69}, + {remove_at, 0, 0, 96}, // test remove at + {check_maxSize, 0, 0, 32}, + {check_size, 0, 0, 1}, + {check_value, 0, 0, 69}, + {insert_at, 71, 1, 71}, // test insertion at end + {resize, 48, 0, 0}, // test resize bigger + {check_maxSizeGrowth, 0, 0, 0}, + {check_maxSize, 0, 0, 48}, + {check_size, 0, 0, 48}, + {check_value, 0, 0, 69}, + {check_value, 1, 0, 71}, + {resize, 24, 0, 0}, // test resize smaller + {check_maxSizeGrowth, 0, 0, 0}, + {check_maxSize, 0, 0, 48}, + {check_size, 0, 0, 24}, + {check_value, 0, 0, 69}, + {check_value, 1, 0, 71}, + {open_at2, 1, (sizeof (text) + sizeof (int) - 1) / sizeof (int), 0}, + {check_value, 0, 0, 69}, + {check_value, 1, 0, 0x796f6c41}, + {check_value, 9, 0, 71}, + {clear, 0, 0, 0}, // test clearing + {check_size, 0, 0, 0}, + {check_maxSize, 0, 0, 0}, + {check_array, 0, 0, 0}, +}; +#define num_tests (sizeof (tests) / sizeof (tests[0])) +int test_start_line = __LINE__ - num_tests - 2; + +int +main (int argc, const char **argv) +{ + int res = 0; + + size_t i; + + for (i = 0; i < num_tests; i++) { + if (tests[i].test) { + int test_res; + test_res = tests[i].test (tests[i].param1, tests[i].param2); + if (test_res != tests[i].test_expect) { + res |= 1; + printf ("test %d (line %d) failed\n", (int) i, + (int) i + test_start_line); + printf ("expect: %d\n", tests[i].test_expect); + printf ("got : %d\n", test_res); + continue; + } + } + } + return res; +} From 0764df127643b32d97a6d73f63039a40bb40ba10 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 16:40:12 +0900 Subject: [PATCH 0769/3664] Fix incorrect include protection --- include/QF/Makefile.am | 2 +- include/QF/darray.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am index c0fda5cd1..bb6b0d2da 100644 --- a/include/QF/Makefile.am +++ b/include/QF/Makefile.am @@ -5,7 +5,7 @@ pkgdatadir = $(datarootdir)/qfcc/include/QF include_qf= \ alloc.h bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \ - console.h crc.h csqc.h cvar.h dstring.h draw.h gib.h hash.h \ + console.h crc.h csqc.h cvar.h darray.h dstring.h draw.h gib.h hash.h \ idparse.h image.h in_event.h info.h input.h iqm.h joystick.h keys.h \ link.h llist.h locs.h mathlib.h mdfour.h mersenne.h model.h modelgen.h \ msg.h object.h pak.h pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h \ diff --git a/include/QF/darray.h b/include/QF/darray.h index 88792715f..0287f958f 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -28,8 +28,8 @@ */ -#ifndef __pr_type_h -#define __pr_type_h +#ifndef __darray_h +#define __darray_h /** \defgroup darray Dynamic Arrays \ingroup utils @@ -298,4 +298,4 @@ ///@} -#endif//__pr_type_h +#endif//__darray_h From 2966b035bf0cf78544b8a7c2e73e42b3d7c76af6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Feb 2020 20:27:43 +0900 Subject: [PATCH 0770/3664] Add a fixed-array allocator Turned out to be very convenient. --- include/QF/darray.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/QF/darray.h b/include/QF/darray.h index 0287f958f..7a4484575 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -67,6 +67,27 @@ ele_type *a; \ } +/** Allocate a fixed-size array using the given allocator + + The allocated array is initilized to be ungrowable, and with both size + and maxSize set to the given size. + + \param array_type Expression acceptable by typeof for determining the + type of the array. + \param array_size The size of the array. + \param alloc Allocator compatible with malloc (eg, alloca). +*/ +#define DARRAY_ALLOCFIXED(array_type, array_size, alloc) \ + ({ \ + __auto_type s = (array_size); \ + typeof (array_type) *ar = alloc (sizeof(*ar) \ + + s * sizeof (*ar->a)); \ + ar->size = ar->maxSize = s; \ + ar->grow = 0; \ + ar->a = (typeof (ar->a)) (ar + 1); \ + ar; \ + }) + /** Clear the array. If the array can grow, its backing will be freed and maxSize and a reset, From 38fc7459e40b865b34350f7225aa45ee49618730 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 12:52:56 +0900 Subject: [PATCH 0771/3664] Add DARRAY_INIT from the vulkan branch Couldn't cherry-pick this one as it was a bigger commit. --- include/QF/darray.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/QF/darray.h b/include/QF/darray.h index 7a4484575..9f8c9630b 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -88,6 +88,25 @@ ar; \ }) +/** Initialized the array. + + The array will be initialized to be empty but with grow set to the + specifed value. + + \param array *Address* of the array to be modified (ie, pointer to the + array struct instance, not the instance itself: use & for + static instances of the array struct). + \param growSize Number of elements by which the array is to grow when + required. + \hideinitializer +*/ +#define DARRAY_INIT(array, growSize) \ + do { \ + __auto_type ar = (array); \ + ar->size = ar->maxSize = 0; \ + ar->grow = (growSize); \ + } while (0) + /** Clear the array. If the array can grow, its backing will be freed and maxSize and a reset, From d2f03e8a640d96f3e8dc6de1b0173b969ae887b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 12:55:23 +0900 Subject: [PATCH 0772/3664] [util] Fix darray test for gcc purity --- libs/util/test/test-darray.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/test/test-darray.c b/libs/util/test/test-darray.c index 59dbad0ab..59d3a2ddc 100644 --- a/libs/util/test/test-darray.c +++ b/libs/util/test/test-darray.c @@ -51,7 +51,7 @@ check_array (int a, int b) return !!intarray.a; } -static int +static int __attribute__((pure)) check_value (int index, int b) { if ((size_t) index >= intarray.size) { From 74ed057a5fd8266d1d838f1327d0574ce613ebcd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 08:48:40 +0900 Subject: [PATCH 0773/3664] [qwaq] Begin move over to threading Of course, it currently locks up, but there aren't any other threads as of yet so the queues starve. --- ruamoko/qwaq/qwaq-curses.c | 198 +++++++++++++++++++++++++++---------- 1 file changed, 145 insertions(+), 53 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 3837d2f8c..8f793bdac 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -31,8 +31,12 @@ # include "config.h" #endif +#include + #include +#include #include +#include #include #include #include @@ -85,7 +89,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_mvwblit_line, } qwaq_commands; -const char *qwaq_command_names[]= { +static const char *qwaq_command_names[]= { "newwin", "delwin", "getwrect", @@ -123,15 +127,24 @@ typedef struct panel_s { int window_id; } panel_t; +typedef struct cond_s { + pthread_cond_t cond; + pthread_mutex_t mut; +} cond_t; + typedef struct qwaq_resources_s { progs_t *pr; int initialized; window_t stdscr; PR_RESMAP (window_t) window_map; PR_RESMAP (panel_t) panel_map; + cond_t event_cond; RING_BUFFER (qwaq_event_t, QUEUE_SIZE) event_queue; + cond_t command_cond; RING_BUFFER (int, COMMAND_QUEUE_SIZE) command_queue; + cond_t results_cond; RING_BUFFER (int, COMMAND_QUEUE_SIZE) results; + cond_t string_id_cond; RING_BUFFER (int, STRING_ID_QUEUE_SIZE) string_ids; dstring_t strings[STRING_ID_QUEUE_SIZE - 1]; } qwaq_resources_t; @@ -222,34 +235,33 @@ get_panel (qwaq_resources_t *res, const char *name, int handle) return panel; } -//XXX goes away with threads -static void process_commands (qwaq_resources_t *); -static void process_input (qwaq_resources_t *); static int acquire_string (qwaq_resources_t *res) { int string_id = -1; - // XXX add locking and loop for available - if (!RB_DATA_AVAILABLE (res->string_ids)) { - process_commands(res); + pthread_mutex_lock (&res->string_id_cond.mut); + while (!RB_DATA_AVAILABLE (res->string_ids)) { + pthread_cond_wait (&res->string_id_cond.cond, + &res->string_id_cond.mut); } - if (RB_DATA_AVAILABLE (res->string_ids)) { - RB_READ_DATA (res->string_ids, &string_id, 1); - } - // XXX unlock and end of loop + RB_READ_DATA (res->string_ids, &string_id, 1); + pthread_cond_broadcast (&res->string_id_cond.cond); + pthread_mutex_unlock (&res->string_id_cond.mut); return string_id; } static void release_string (qwaq_resources_t *res, int string_id) { - // locking shouldn't be necessary as there should be only one writer - // but if it becomes such that there is more than one writer, locks as per - // acquire - if (RB_SPACE_AVAILABLE (res->string_ids)) { - RB_WRITE_DATA (res->string_ids, &string_id, 1); + pthread_mutex_lock (&res->string_id_cond.mut); + while (RB_SPACE_AVAILABLE (res->string_ids)) { + pthread_cond_wait (&res->string_id_cond.cond, + &res->string_id_cond.mut); } + RB_WRITE_DATA (res->string_ids, &string_id, 1); + pthread_cond_broadcast (&res->string_id_cond.cond); + pthread_mutex_unlock (&res->string_id_cond.mut); } static void @@ -257,35 +269,41 @@ qwaq_submit_command (qwaq_resources_t *res, const int *cmd) { unsigned len = cmd[1]; - if (RB_SPACE_AVAILABLE (res->command_queue) >= len) { - RB_WRITE_DATA (res->command_queue, cmd, len); - } else { - PR_RunError (res->pr, "command buffer full"); + pthread_mutex_lock (&res->command_cond.mut); + while (RB_SPACE_AVAILABLE (res->command_queue) < len) { + pthread_cond_wait (&res->command_cond.cond, + &res->command_cond.mut); } + RB_WRITE_DATA (res->command_queue, cmd, len); + pthread_cond_broadcast (&res->command_cond.cond); + pthread_mutex_unlock (&res->command_cond.mut); } static void qwaq_submit_result (qwaq_resources_t *res, const int *result, unsigned len) { - // loop - if (RB_SPACE_AVAILABLE (res->results) >= len) { - RB_WRITE_DATA (res->results, result, len); - } else { - PR_RunError (res->pr, "result buffer full"); + pthread_mutex_lock (&res->results_cond.mut); + while (RB_SPACE_AVAILABLE (res->results) < len) { + pthread_cond_wait (&res->results_cond.cond, + &res->results_cond.mut); } + RB_WRITE_DATA (res->results, result, len); + pthread_cond_broadcast (&res->results_cond.cond); + pthread_mutex_unlock (&res->results_cond.mut); } static void qwaq_wait_result (qwaq_resources_t *res, int *result, int cmd, unsigned len) { - // XXX should just wait on the mutex - process_commands (res); - process_input (res); - // locking and loop until id is correct - if (RB_DATA_AVAILABLE (res->results) >= len - && RB_PEEK_DATA (res->results, 0) == cmd) { - RB_READ_DATA (res->results, result, len); + pthread_mutex_lock (&res->results_cond.mut); + while (RB_DATA_AVAILABLE (res->results) < len + && RB_PEEK_DATA (res->results, 0) != cmd) { + pthread_cond_wait (&res->results_cond.cond, + &res->results_cond.mut); } + RB_READ_DATA (res->results, result, len); + pthread_cond_broadcast (&res->results_cond.cond); + pthread_mutex_unlock (&res->results_cond.mut); } static void @@ -580,17 +598,53 @@ cmd_mvwblit_line (qwaq_resources_t *res) release_string (res, chs_id); } +static void +dump_command (qwaq_resources_t *res, int len) +{ + if (0) { + qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); + Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); + for (int i = 2; i < len; i++) { + Sys_Printf (" %d", RB_PEEK_DATA (res->command_queue, i)); + } + Sys_Printf ("\n"); + } +} + +static void +init_timeout (struct timespec *timeout, long time) +{ + #define SEC 1000000000 + struct timeval now; + gettimeofday(&now, 0); + timeout->tv_sec = now.tv_sec; + timeout->tv_nsec = now.tv_usec * 1000 + time; + if (timeout->tv_nsec > SEC) { + timeout->tv_sec += timeout->tv_nsec / SEC; + timeout->tv_nsec %= SEC; + } +} + static void process_commands (qwaq_resources_t *res) { - while (RB_DATA_AVAILABLE (res->command_queue) >= 2) { + struct timespec timeout; + int avail; + int len; + int ret = 0; + + pthread_mutex_lock (&res->command_cond.mut); + init_timeout (&timeout, 20 * 1000000); + while (RB_DATA_AVAILABLE (res->command_queue) < 2 && ret != ETIMEDOUT) { + ret = pthread_cond_timedwait (&res->command_cond.cond, + &res->command_cond.mut, &timeout); + } + pthread_mutex_unlock (&res->command_cond.mut); + + while ((avail = RB_DATA_AVAILABLE (res->command_queue)) >= 2 + && avail >= (len = RB_PEEK_DATA (res->command_queue, 1))) { + dump_command (res, len); qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); - //int len = RB_PEEK_DATA (res->command_queue, 1); - //Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); - //for (int i = 2; i < len; i++) { - // Sys_Printf (" %d", RB_PEEK_DATA (res->command_queue, i)); - //} - //Sys_Printf ("\n"); switch (cmd) { case qwaq_cmd_newwin: cmd_newwin (res); @@ -671,39 +725,66 @@ process_commands (qwaq_resources_t *res) cmd_mvwblit_line (res); break; } - RB_DROP_DATA (res->command_queue, RB_PEEK_DATA (res->command_queue, 1)); + pthread_mutex_lock (&res->command_cond.mut); + RB_DROP_DATA (res->command_queue, len); + pthread_cond_broadcast (&res->command_cond.cond); + pthread_mutex_unlock (&res->command_cond.mut); } } static void add_event (qwaq_resources_t *res, qwaq_event_t *event) { - // lock - // { + struct timespec timeout; + int merged = 0; + int ret = 0; + // merge motion events + pthread_mutex_lock (&res->event_cond.mut); unsigned last = RB_DATA_AVAILABLE (res->event_queue); if (event->what == qe_mousemove && last > 1 && RB_PEEK_DATA(res->event_queue, last - 1).what == qe_mousemove) { RB_POKE_DATA(res->event_queue, last - 1, *event); - return; // unlock + merged = 1; + pthread_cond_broadcast (&res->event_cond.cond); } - // } - if (RB_SPACE_AVAILABLE (res->event_queue) >= 1) { - RB_WRITE_DATA (res->event_queue, event, 1); + pthread_mutex_unlock (&res->event_cond.mut); + if (merged) { + return; } + + pthread_mutex_lock (&res->event_cond.mut); + init_timeout (&timeout, 5000 * 1000000L); + while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { + ret = pthread_cond_timedwait (&res->event_cond.cond, + &res->event_cond.mut, &timeout); + } + RB_WRITE_DATA (res->event_queue, event, 1); + pthread_cond_broadcast (&res->event_cond.cond); } static int get_event (qwaq_resources_t *res, qwaq_event_t *event) { - if (RB_DATA_AVAILABLE (res->event_queue) >= 1) { - if (event) { - RB_READ_DATA (res->event_queue, event, 1); - } - return 1; + struct timespec timeout; + int ret = 0; + + pthread_mutex_lock (&res->event_cond.mut); + init_timeout (&timeout, 20 * 1000000); + while (RB_DATA_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { + ret = pthread_cond_timedwait (&res->event_cond.cond, + &res->event_cond.mut, &timeout); } - event->what = qe_none; - return 0; + if (event) { + if (ret != ETIMEDOUT) { + RB_READ_DATA (res->event_queue, event, 1); + } else { + event->what = qe_none; + } + } + pthread_cond_broadcast (&res->event_cond.cond); + pthread_mutex_lock (&res->event_cond.mut); + return ret != ETIMEDOUT; } #define M_MOVE REPORT_MOUSE_POSITION @@ -1793,6 +1874,13 @@ qwaq_print (const char *fmt, va_list args) fflush (logfile); } +static void +qwaq_init_cond (cond_t *cond) +{ + pthread_cond_init (&cond->cond, 0); + pthread_mutex_init (&cond->mut, 0); +} + void BI_Init (progs_t *pr) { @@ -1802,6 +1890,10 @@ BI_Init (progs_t *pr) RB_WRITE_DATA (res->string_ids, &i, 1); res->strings[i].mem = &dstring_default_mem; } + qwaq_init_cond (&res->event_cond); + qwaq_init_cond (&res->command_cond); + qwaq_init_cond (&res->results_cond); + qwaq_init_cond (&res->string_id_cond); PR_Resources_Register (pr, "qwaq", res, bi_qwaq_clear); PR_RegisterBuiltins (pr, builtins); From 52a46f5d5c5bcc5d6787d83f5905f3fcb5bc1097 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 10:13:37 +0900 Subject: [PATCH 0774/3664] [qwaq] Use allocate progs instead of static --- ruamoko/qwaq/main.c | 80 +++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index ae82758ad..bfd0f6550 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -52,8 +52,6 @@ #define MAX_EDICTS 1024 -static progs_t pr; - cbuf_t *qwaq_cbuf; static QFile * @@ -117,20 +115,29 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); - pr.load_file = load_file; - pr.allocate_progs_mem = allocate_progs_mem; - pr.free_progs_mem = free_progs_mem; - pr.no_exec_limit = 1; +} + +static progs_t * +create_progs (void) +{ + progs_t *pr = calloc (1, sizeof (*pr)); + + pr->load_file = load_file; + pr->allocate_progs_mem = allocate_progs_mem; + pr->free_progs_mem = free_progs_mem; + pr->no_exec_limit = 1; PR_Init_Cvars (); - PR_Init (&pr); - RUA_Init (&pr, 0); - PR_Cmds_Init (&pr); - BI_Init (&pr); + PR_Init (pr); + RUA_Init (pr, 0); + PR_Cmds_Init (pr); + BI_Init (pr); + + return pr; } static int -load_progs (const char *name) +load_progs (progs_t *pr, const char *name) { QFile *file; int size; @@ -139,13 +146,13 @@ load_progs (const char *name) if (!file) { return 0; } - pr.progs_name = name; - pr.max_edicts = 1; - pr.zone_size = 1024*1024; - PR_LoadProgsFile (&pr, file, size); + pr->progs_name = name; + pr->max_edicts = 1; + pr->zone_size = 1024*1024; + PR_LoadProgsFile (pr, file, size); Qclose (file); - if (!PR_RunLoadFuncs (&pr)) - PR_Error (&pr, "unable to load %s", pr.progs_name); + if (!PR_RunLoadFuncs (pr)) + PR_Error (pr, "unable to load %s", pr->progs_name); return 1; } @@ -157,40 +164,43 @@ main (int argc, const char **argv) const char *name = "qwaq-app.dat"; string_t *pr_argv; int pr_argc = 1, i; + progs_t *pr; COM_InitArgv (argc, argv); init_qf (); + pr = create_progs (); + if (argc > 1) name = argv[1]; - if (!load_progs (name)) { + if (!load_progs (pr, name)) { Sys_Error ("couldn't load %s", name); } - //pr.pr_trace = 1; - //pr.pr_trace_depth = -1; + pr->pr_trace = 1; + pr->pr_trace_depth = -1; - PR_PushFrame (&pr); + PR_PushFrame (pr); if (argc > 2) pr_argc = argc - 1; - pr_argv = PR_Zone_Malloc (&pr, (pr_argc + 1) * 4); - pr_argv[0] = PR_SetTempString (&pr, name); + pr_argv = PR_Zone_Malloc (pr, (pr_argc + 1) * 4); + pr_argv[0] = PR_SetTempString (pr, name); for (i = 1; i < pr_argc; i++) - pr_argv[i] = PR_SetTempString (&pr, argv[1 + i]); + pr_argv[i] = PR_SetTempString (pr, argv[1 + i]); pr_argv[i] = 0; - if ((dfunc = PR_FindFunction (&pr, ".main")) - || (dfunc = PR_FindFunction (&pr, "main"))) - main_func = dfunc - pr.pr_functions; + if ((dfunc = PR_FindFunction (pr, ".main")) + || (dfunc = PR_FindFunction (pr, "main"))) + main_func = dfunc - pr->pr_functions; else - PR_Undefined (&pr, "function", "main"); - PR_RESET_PARAMS (&pr); - P_INT (&pr, 0) = pr_argc; - P_POINTER (&pr, 1) = PR_SetPointer (&pr, pr_argv); - pr.pr_argc = 2; - PR_ExecuteProgram (&pr, main_func); - PR_PopFrame (&pr); + PR_Undefined (pr, "function", "main"); + PR_RESET_PARAMS (pr); + P_INT (pr, 0) = pr_argc; + P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv); + pr->pr_argc = 2; + PR_ExecuteProgram (pr, main_func); + PR_PopFrame (pr); Sys_Shutdown (); - return R_INT (&pr); + return R_INT (pr); } From 9678eba59b06e8b422733b5034bb57e5f5f475a2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 14:43:52 +0900 Subject: [PATCH 0775/3664] Initialize array pointer in dynamic array Oops. I guess I was using calloc in the vulkan branch. --- include/QF/darray.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/QF/darray.h b/include/QF/darray.h index 9f8c9630b..05387b2fe 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -105,6 +105,7 @@ __auto_type ar = (array); \ ar->size = ar->maxSize = 0; \ ar->grow = (growSize); \ + ar->a = 0; \ } while (0) /** Clear the array. From a5f57a8a4c4b1ae69cf9e120cc5b72f49600a921 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 15:47:30 +0900 Subject: [PATCH 0776/3664] [qwaq] Parse arguments into sets The sets are separated by --, and the first set is passed to getopt_long which currently recognizes only --qargs and non-options. The --qargs options parses out a set (to -- or end of args) that is passed to the qargs sub-system for standard qf command line parsing. Set 0 is for the main qwaq application. Any additional sets (excluding --qargs) will be used to spawn additional threads when that's working. --- ruamoko/qwaq/main.c | 129 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index bfd0f6550..4c4e3165c 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -33,11 +33,14 @@ #include #include +#include #include +#include #include "QF/cbuf.h" #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/darray.h" #include "QF/gib.h" #include "QF/idparse.h" #include "QF/progs.h" @@ -54,6 +57,28 @@ cbuf_t *qwaq_cbuf; +const char *this_program; + +enum { + start_opts = 255, + OPT_QARGS, +}; + +static struct option const long_options[] = { + {"qargs", no_argument, 0, OPT_QARGS}, + {NULL, 0, NULL, 0}, +}; + +static const char *short_options = + "-" // magic option parsing mode doohicky (must come first) + ; + +typedef struct qwaq_thread_s { + struct DARRAY_TYPE (const char *) args; +} qwaq_thread_t; + +struct DARRAY_TYPE(qwaq_thread_t) thread_args; + static QFile * open_file (const char *path, int *len) { @@ -156,23 +181,119 @@ load_progs (progs_t *pr, const char *name) return 1; } +static void +usage (int status) +{ + printf ("%s - QuakeForge runtime\n", this_program); + printf ("sorry, no help yet\n"); + exit (status); +} + +static int +parse_argset (int argc, char **argv) +{ + qwaq_thread_t thread; + DARRAY_INIT (&thread.args, 8); + + DARRAY_APPEND (&thread.args, NULL); + while (optind < argc && strcmp (argv[optind], "--")) { + DARRAY_APPEND (&thread.args, argv[optind++]); + } + if (optind < argc) { + optind++; + } + DARRAY_APPEND (&thread_args, thread); + return thread_args.size - 1; +} + +static int +parse_args (int argc, char **argv) +{ + int c; + qwaq_thread_t main_thread; + int qargs_ind = -1; + + DARRAY_INIT (&main_thread.args, 8); + + while ((c = getopt_long (argc, argv, + short_options, long_options, 0)) != -1) { + switch (c) { + case 1: + DARRAY_APPEND (&main_thread.args, argv[optind - 1]); + break; + case OPT_QARGS: + if (qargs_ind < 0) { + qargs_ind = parse_argset (argc, argv); + thread_args.a[qargs_ind].args.a[0] = "--qargs"; + goto done; + } else { + printf ("more than one set of qargs given"); + exit (1); + } + break; + default: + usage (1); + } + } +done: + + free (thread_args.a[0].args.a); + thread_args.a[0] = main_thread; + + while (optind < argc) { + parse_argset (argc, argv); + } + return qargs_ind; +} + int -main (int argc, const char **argv) +main (int argc, char **argv) { dfunction_t *dfunc; func_t main_func = 0; const char *name = "qwaq-app.dat"; string_t *pr_argv; int pr_argc = 1, i; + int qargs_ind; progs_t *pr; - COM_InitArgv (argc, argv); + this_program = argv[0]; + + DARRAY_INIT (&thread_args, 4); + for (optind = 1; optind < argc; ) { + parse_argset (argc, argv); + } + if (thread_args.size) { + qwaq_thread_t *thread = &thread_args.a[0]; + // the first arg is initialized to null, but this is for getopt, so + // set to main program name + thread->args.a[0] = this_program; + optind = 0; + qargs_ind = parse_args (thread->args.size, (char **) thread->args.a); + } else { + // create a blank main thread set + qwaq_thread_t thread = {}; + DARRAY_APPEND (&thread_args, thread); + } + + if (qargs_ind >= 0) { + qwaq_thread_t *args = &thread_args.a[qargs_ind]; + // the first arg is initialized to --qargs, so + // set to main program name for now + args->args.a[0] = this_program; + COM_InitArgv (args->args.size, args->args.a); + } + init_qf (); pr = create_progs (); - if (argc > 1) - name = argv[1]; + { + qwaq_thread_t *thread = &thread_args.a[0]; + if (thread->args.size) { + name = thread->args.a[0]; + } + } if (!load_progs (pr, name)) { Sys_Error ("couldn't load %s", name); From 4e739f6b368acec0aa3b3a168666c914a8e388b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 16:51:12 +0900 Subject: [PATCH 0777/3664] Use dynamic array element type instead of __auto_type This allows using 0 for pointer arrays. --- include/QF/darray.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/QF/darray.h b/include/QF/darray.h index 05387b2fe..2b8689726 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -186,10 +186,10 @@ #define DARRAY_APPEND(array, value) \ ({ \ __auto_type ar = (array); \ - __auto_type ob = (value); \ + typeof(ar->a[0]) ob = (value); \ size_t sz = ar->size; \ DARRAY_RESIZE (ar, ar->size + 1); \ - ar->a[sz] = ob; \ + ar->a[sz] = ob; \ }) /** Open a hole in the array for bulk copying of data. @@ -259,7 +259,7 @@ #define DARRAY_INSERT_AT(array, value, index) \ ({ \ __auto_type ar = (array); \ - __auto_type ob = (value); \ + typeof(ar->a[0]) ob = (value); \ *DARRAY_OPEN_AT (ar, index, 1) = ob; \ }) From 0cc28c864140caad15d157c0ba1c3ff703fd3ca2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 16:59:59 +0900 Subject: [PATCH 0778/3664] [qwaq] Run main thread And only thread, still, so things lock up still, but they're coming together. --- ruamoko/qwaq/main.c | 125 +++++++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 48 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 4c4e3165c..282b9f5bf 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -75,6 +75,9 @@ static const char *short_options = typedef struct qwaq_thread_s { struct DARRAY_TYPE (const char *) args; + sys_printf_t sys_printf; + progs_t *pr; + func_t main_func; } qwaq_thread_t; struct DARRAY_TYPE(qwaq_thread_t) thread_args; @@ -181,6 +184,58 @@ load_progs (progs_t *pr, const char *name) return 1; } +static void +spawn_progs (qwaq_thread_t *thread) +{ + dfunction_t *dfunc; + const char *name = "qwaq-app.dat"; + string_t *pr_argv; + int pr_argc = 1, i; + progs_t *pr; + + thread->main_func = 0; + pr = thread->pr = create_progs (); + if (thread->args.size) { + name = thread->args.a[0]; + } + + if (!load_progs (pr, name)) { + Sys_Error ("couldn't load %s", name); + } + + //pr->pr_trace = 1; + //pr->pr_trace_depth = -1; + + PR_PushFrame (pr); + if (thread->args.size > 2) { + pr_argc = thread->args.size - 1; + } + pr_argv = PR_Zone_Malloc (pr, (pr_argc + 1) * 4); + pr_argv[0] = PR_SetTempString (pr, name); + for (i = 1; i < pr_argc; i++) + pr_argv[i] = PR_SetTempString (pr, thread->args.a[1 + i]); + pr_argv[i] = 0; + + if ((dfunc = PR_FindFunction (pr, ".main")) + || (dfunc = PR_FindFunction (pr, "main"))) { + thread->main_func = dfunc - pr->pr_functions; + } else { + PR_Undefined (pr, "function", "main"); + } + PR_RESET_PARAMS (pr); + P_INT (pr, 0) = pr_argc; + P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv); + pr->pr_argc = 2; +} + +static int +run_progs (qwaq_thread_t *thread) +{ + PR_ExecuteProgram (thread->pr, thread->main_func); + PR_PopFrame (thread->pr); + return R_INT (thread->pr); +} + static void usage (int status) { @@ -192,10 +247,10 @@ usage (int status) static int parse_argset (int argc, char **argv) { - qwaq_thread_t thread; + qwaq_thread_t thread = {}; DARRAY_INIT (&thread.args, 8); - DARRAY_APPEND (&thread.args, NULL); + DARRAY_APPEND (&thread.args, 0); while (optind < argc && strcmp (argv[optind], "--")) { DARRAY_APPEND (&thread.args, argv[optind++]); } @@ -210,7 +265,7 @@ static int parse_args (int argc, char **argv) { int c; - qwaq_thread_t main_thread; + qwaq_thread_t main_thread = {}; int qargs_ind = -1; DARRAY_INIT (&main_thread.args, 8); @@ -249,13 +304,8 @@ done: int main (int argc, char **argv) { - dfunction_t *dfunc; - func_t main_func = 0; - const char *name = "qwaq-app.dat"; - string_t *pr_argv; - int pr_argc = 1, i; - int qargs_ind; - progs_t *pr; + int qargs_ind = -1; + int ret; this_program = argv[0]; @@ -277,51 +327,30 @@ main (int argc, char **argv) } if (qargs_ind >= 0) { - qwaq_thread_t *args = &thread_args.a[qargs_ind]; + qwaq_thread_t *qargs = &thread_args.a[qargs_ind]; // the first arg is initialized to --qargs, so // set to main program name for now - args->args.a[0] = this_program; - COM_InitArgv (args->args.size, args->args.a); + qargs->args.a[0] = this_program; + COM_InitArgv (qargs->args.size, qargs->args.a); + } else { + qwaq_thread_t qargs = {}; + DARRAY_INIT (&qargs.args, 2); + DARRAY_APPEND (&qargs.args, this_program); + COM_InitArgv (qargs.args.size, qargs.args.a); } init_qf (); - pr = create_progs (); - - { - qwaq_thread_t *thread = &thread_args.a[0]; - if (thread->args.size) { - name = thread->args.a[0]; + for (size_t i = 0; i < thread_args.size; i++) { + qwaq_thread_t *thread = &thread_args.a[i]; + if (thread->args.size && thread->args.a[0] + && strcmp (thread->args.a[0], "--qargs")) { + // skip the args set that's passed to qargs + continue; } + spawn_progs (thread); } - - if (!load_progs (pr, name)) { - Sys_Error ("couldn't load %s", name); - } - - pr->pr_trace = 1; - pr->pr_trace_depth = -1; - - PR_PushFrame (pr); - if (argc > 2) - pr_argc = argc - 1; - pr_argv = PR_Zone_Malloc (pr, (pr_argc + 1) * 4); - pr_argv[0] = PR_SetTempString (pr, name); - for (i = 1; i < pr_argc; i++) - pr_argv[i] = PR_SetTempString (pr, argv[1 + i]); - pr_argv[i] = 0; - - if ((dfunc = PR_FindFunction (pr, ".main")) - || (dfunc = PR_FindFunction (pr, "main"))) - main_func = dfunc - pr->pr_functions; - else - PR_Undefined (pr, "function", "main"); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = pr_argc; - P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv); - pr->pr_argc = 2; - PR_ExecuteProgram (pr, main_func); - PR_PopFrame (pr); + ret = run_progs (&thread_args.a[0]); Sys_Shutdown (); - return R_INT (pr); + return ret; } From 93886d6cd798466d659aff557b5da2548b6f3ddf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 17:30:26 +0900 Subject: [PATCH 0779/3664] [qwaq] Use main args non-options as progs files If none are specified, default to qwaq-app.dat (for now, anyway). For each progs file, an optional args set can be specified in the same order (separated by --). Missing sets default to empty, excess sets are ignored. --- ruamoko/qwaq/main.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 282b9f5bf..ed8fbf203 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -188,7 +188,7 @@ static void spawn_progs (qwaq_thread_t *thread) { dfunction_t *dfunc; - const char *name = "qwaq-app.dat"; + const char *name = 0; string_t *pr_argv; int pr_argc = 1, i; progs_t *pr; @@ -305,7 +305,9 @@ int main (int argc, char **argv) { int qargs_ind = -1; - int ret; + int main_ind = -1; + int ret = 0; + size_t num_sys = 1; this_program = argv[0]; @@ -323,6 +325,7 @@ main (int argc, char **argv) } else { // create a blank main thread set qwaq_thread_t thread = {}; + DARRAY_INIT (&thread.args, 4); DARRAY_APPEND (&thread_args, thread); } @@ -332,6 +335,7 @@ main (int argc, char **argv) // set to main program name for now qargs->args.a[0] = this_program; COM_InitArgv (qargs->args.size, qargs->args.a); + num_sys++; } else { qwaq_thread_t qargs = {}; DARRAY_INIT (&qargs.args, 2); @@ -341,16 +345,38 @@ main (int argc, char **argv) init_qf (); - for (size_t i = 0; i < thread_args.size; i++) { + if (thread_args.a[0].args.size < 1) { + DARRAY_APPEND (&thread_args.a[0].args, "qwaq-app.dat"); + } + + while (thread_args.size < thread_args.a[0].args.size + num_sys) { + qwaq_thread_t thread = {}; + DARRAY_INIT (&thread.args, 4); + DARRAY_APPEND (&thread.args, 0); + DARRAY_APPEND (&thread_args, thread); + } + + for (size_t i = 1, thread_ind = 0; i < thread_args.size; i++) { qwaq_thread_t *thread = &thread_args.a[i]; if (thread->args.size && thread->args.a[0] && strcmp (thread->args.a[0], "--qargs")) { // skip the args set that's passed to qargs continue; } + if (thread_ind < thread_args.a[0].args.size) { + thread->args.a[0] = thread_args.a[0].args.a[thread_ind++]; + } else { + printf ("ignoring extra arg sets\n"); + break; + } + if (main_ind < 0) { + main_ind = i; + } spawn_progs (thread); } - ret = run_progs (&thread_args.a[0]); + if (main_ind >= 0) { + ret = run_progs (&thread_args.a[main_ind]); + } Sys_Shutdown (); return ret; } From f14f2f518a5c442c47357d47902dfd198dfa1d8e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 21:16:56 +0900 Subject: [PATCH 0780/3664] [qwaq] Rename thread_args to thread_data --- ruamoko/qwaq/main.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index ed8fbf203..22dcf25ed 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -80,7 +80,7 @@ typedef struct qwaq_thread_s { func_t main_func; } qwaq_thread_t; -struct DARRAY_TYPE(qwaq_thread_t) thread_args; +struct DARRAY_TYPE(qwaq_thread_t) thread_data; static QFile * open_file (const char *path, int *len) @@ -257,8 +257,8 @@ parse_argset (int argc, char **argv) if (optind < argc) { optind++; } - DARRAY_APPEND (&thread_args, thread); - return thread_args.size - 1; + DARRAY_APPEND (&thread_data, thread); + return thread_data.size - 1; } static int @@ -279,7 +279,7 @@ parse_args (int argc, char **argv) case OPT_QARGS: if (qargs_ind < 0) { qargs_ind = parse_argset (argc, argv); - thread_args.a[qargs_ind].args.a[0] = "--qargs"; + thread_data.a[qargs_ind].args.a[0] = "--qargs"; goto done; } else { printf ("more than one set of qargs given"); @@ -292,8 +292,8 @@ parse_args (int argc, char **argv) } done: - free (thread_args.a[0].args.a); - thread_args.a[0] = main_thread; + free (thread_data.a[0].args.a); + thread_data.a[0] = main_thread; while (optind < argc) { parse_argset (argc, argv); @@ -311,12 +311,12 @@ main (int argc, char **argv) this_program = argv[0]; - DARRAY_INIT (&thread_args, 4); + DARRAY_INIT (&thread_data, 4); for (optind = 1; optind < argc; ) { parse_argset (argc, argv); } - if (thread_args.size) { - qwaq_thread_t *thread = &thread_args.a[0]; + if (thread_data.size) { + qwaq_thread_t *thread = &thread_data.a[0]; // the first arg is initialized to null, but this is for getopt, so // set to main program name thread->args.a[0] = this_program; @@ -326,11 +326,11 @@ main (int argc, char **argv) // create a blank main thread set qwaq_thread_t thread = {}; DARRAY_INIT (&thread.args, 4); - DARRAY_APPEND (&thread_args, thread); + DARRAY_APPEND (&thread_data, thread); } if (qargs_ind >= 0) { - qwaq_thread_t *qargs = &thread_args.a[qargs_ind]; + qwaq_thread_t *qargs = &thread_data.a[qargs_ind]; // the first arg is initialized to --qargs, so // set to main program name for now qargs->args.a[0] = this_program; @@ -345,26 +345,26 @@ main (int argc, char **argv) init_qf (); - if (thread_args.a[0].args.size < 1) { - DARRAY_APPEND (&thread_args.a[0].args, "qwaq-app.dat"); + if (thread_data.a[0].args.size < 1) { + DARRAY_APPEND (&thread_data.a[0].args, "qwaq-app.dat"); } - while (thread_args.size < thread_args.a[0].args.size + num_sys) { + while (thread_data.size < thread_data.a[0].args.size + num_sys) { qwaq_thread_t thread = {}; DARRAY_INIT (&thread.args, 4); DARRAY_APPEND (&thread.args, 0); - DARRAY_APPEND (&thread_args, thread); + DARRAY_APPEND (&thread_data, thread); } - for (size_t i = 1, thread_ind = 0; i < thread_args.size; i++) { - qwaq_thread_t *thread = &thread_args.a[i]; + for (size_t i = 1, thread_ind = 0; i < thread_data.size; i++) { + qwaq_thread_t *thread = &thread_data.a[i]; if (thread->args.size && thread->args.a[0] && strcmp (thread->args.a[0], "--qargs")) { // skip the args set that's passed to qargs continue; } - if (thread_ind < thread_args.a[0].args.size) { - thread->args.a[0] = thread_args.a[0].args.a[thread_ind++]; + if (thread_ind < thread_data.a[0].args.size) { + thread->args.a[0] = thread_data.a[0].args.a[thread_ind++]; } else { printf ("ignoring extra arg sets\n"); break; @@ -375,7 +375,7 @@ main (int argc, char **argv) spawn_progs (thread); } if (main_ind >= 0) { - ret = run_progs (&thread_args.a[main_ind]); + ret = run_progs (&thread_data.a[main_ind]); } Sys_Shutdown (); return ret; From 6c1a026bf15f3602781b4a06c513bb7c547e2605 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Mar 2020 23:17:06 +0900 Subject: [PATCH 0781/3664] [qwaq] Change thread data array to pointers I realized that with dynamic thread creation the arrays resizing could cause them to move around in memory which would be bad for anything holding a pointer to the data, and even using indices wouldn't help that much as the array would need to be mutex protected. --- ruamoko/qwaq/main.c | 49 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 22dcf25ed..8c20c3558 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -80,7 +80,7 @@ typedef struct qwaq_thread_s { func_t main_func; } qwaq_thread_t; -struct DARRAY_TYPE(qwaq_thread_t) thread_data; +struct DARRAY_TYPE(qwaq_thread_t *) thread_data; static QFile * open_file (const char *path, int *len) @@ -247,12 +247,12 @@ usage (int status) static int parse_argset (int argc, char **argv) { - qwaq_thread_t thread = {}; - DARRAY_INIT (&thread.args, 8); + qwaq_thread_t *thread = calloc (1, sizeof (*thread)); + DARRAY_INIT (&thread->args, 8); - DARRAY_APPEND (&thread.args, 0); + DARRAY_APPEND (&thread->args, 0); while (optind < argc && strcmp (argv[optind], "--")) { - DARRAY_APPEND (&thread.args, argv[optind++]); + DARRAY_APPEND (&thread->args, argv[optind++]); } if (optind < argc) { optind++; @@ -265,21 +265,21 @@ static int parse_args (int argc, char **argv) { int c; - qwaq_thread_t main_thread = {}; + qwaq_thread_t *main_thread = calloc (1, sizeof (*main_thread)); int qargs_ind = -1; - DARRAY_INIT (&main_thread.args, 8); + DARRAY_INIT (&main_thread->args, 8); while ((c = getopt_long (argc, argv, short_options, long_options, 0)) != -1) { switch (c) { case 1: - DARRAY_APPEND (&main_thread.args, argv[optind - 1]); + DARRAY_APPEND (&main_thread->args, argv[optind - 1]); break; case OPT_QARGS: if (qargs_ind < 0) { qargs_ind = parse_argset (argc, argv); - thread_data.a[qargs_ind].args.a[0] = "--qargs"; + thread_data.a[qargs_ind]->args.a[0] = "--qargs"; goto done; } else { printf ("more than one set of qargs given"); @@ -292,7 +292,8 @@ parse_args (int argc, char **argv) } done: - free (thread_data.a[0].args.a); + free (thread_data.a[0]->args.a); + free (thread_data.a[0]); thread_data.a[0] = main_thread; while (optind < argc) { @@ -316,7 +317,7 @@ main (int argc, char **argv) parse_argset (argc, argv); } if (thread_data.size) { - qwaq_thread_t *thread = &thread_data.a[0]; + qwaq_thread_t *thread = thread_data.a[0]; // the first arg is initialized to null, but this is for getopt, so // set to main program name thread->args.a[0] = this_program; @@ -324,13 +325,13 @@ main (int argc, char **argv) qargs_ind = parse_args (thread->args.size, (char **) thread->args.a); } else { // create a blank main thread set - qwaq_thread_t thread = {}; - DARRAY_INIT (&thread.args, 4); + qwaq_thread_t *thread = calloc (1, sizeof (*thread)); + DARRAY_INIT (&thread->args, 4); DARRAY_APPEND (&thread_data, thread); } if (qargs_ind >= 0) { - qwaq_thread_t *qargs = &thread_data.a[qargs_ind]; + qwaq_thread_t *qargs = thread_data.a[qargs_ind]; // the first arg is initialized to --qargs, so // set to main program name for now qargs->args.a[0] = this_program; @@ -345,26 +346,26 @@ main (int argc, char **argv) init_qf (); - if (thread_data.a[0].args.size < 1) { - DARRAY_APPEND (&thread_data.a[0].args, "qwaq-app.dat"); + if (thread_data.a[0]->args.size < 1) { + DARRAY_APPEND (&thread_data.a[0]->args, "qwaq-app.dat"); } - while (thread_data.size < thread_data.a[0].args.size + num_sys) { - qwaq_thread_t thread = {}; - DARRAY_INIT (&thread.args, 4); - DARRAY_APPEND (&thread.args, 0); + while (thread_data.size < thread_data.a[0]->args.size + num_sys) { + qwaq_thread_t *thread = calloc (1, sizeof (*thread)); + DARRAY_INIT (&thread->args, 4); + DARRAY_APPEND (&thread->args, 0); DARRAY_APPEND (&thread_data, thread); } for (size_t i = 1, thread_ind = 0; i < thread_data.size; i++) { - qwaq_thread_t *thread = &thread_data.a[i]; + qwaq_thread_t *thread = thread_data.a[i]; if (thread->args.size && thread->args.a[0] && strcmp (thread->args.a[0], "--qargs")) { // skip the args set that's passed to qargs continue; } - if (thread_ind < thread_data.a[0].args.size) { - thread->args.a[0] = thread_data.a[0].args.a[thread_ind++]; + if (thread_ind < thread_data.a[0]->args.size) { + thread->args.a[0] = thread_data.a[0]->args.a[thread_ind++]; } else { printf ("ignoring extra arg sets\n"); break; @@ -375,7 +376,7 @@ main (int argc, char **argv) spawn_progs (thread); } if (main_ind >= 0) { - ret = run_progs (&thread_data.a[main_ind]); + ret = run_progs (thread_data.a[main_ind]); } Sys_Shutdown (); return ret; From cf9455293b4c4d9b49057699251c14ea35b5e61f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 00:01:36 +0900 Subject: [PATCH 0782/3664] [qwaq] Start threads for progs and curses No idea if anything works, probably come crashing down in a flaming pile of debris. --- ruamoko/qwaq/main.c | 52 ++++++++++++++++++++++++++------------ ruamoko/qwaq/qwaq-curses.c | 19 ++++++++++++-- ruamoko/qwaq/qwaq.h | 17 +++++++++++++ 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 8c20c3558..2368c2fc9 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -1,12 +1,12 @@ /* #FILENAME# - #DESCRIPTION# + Qwaq - Copyright (C) 2001 #AUTHOR# + Copyright (C) 2001 Bill Currie - Author: #AUTHOR# - Date: #DATE# + Author: Bill Currie + Date: 2001/06/01 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -34,13 +34,13 @@ #include #include #include +#include #include #include #include "QF/cbuf.h" #include "QF/cmd.h" #include "QF/cvar.h" -#include "QF/darray.h" #include "QF/gib.h" #include "QF/idparse.h" #include "QF/progs.h" @@ -73,13 +73,6 @@ static const char *short_options = "-" // magic option parsing mode doohicky (must come first) ; -typedef struct qwaq_thread_s { - struct DARRAY_TYPE (const char *) args; - sys_printf_t sys_printf; - progs_t *pr; - func_t main_func; -} qwaq_thread_t; - struct DARRAY_TYPE(qwaq_thread_t *) thread_data; static QFile * @@ -228,12 +221,31 @@ spawn_progs (qwaq_thread_t *thread) pr->pr_argc = 2; } -static int -run_progs (qwaq_thread_t *thread) +static void * +run_progs (void *data) { + __auto_type thread = (qwaq_thread_t *) data; + PR_ExecuteProgram (thread->pr, thread->main_func); PR_PopFrame (thread->pr); - return R_INT (thread->pr); + thread->return_code = R_INT (thread->pr); + return thread; +} + +static void +start_progs_thread (qwaq_thread_t *thread) +{ + pthread_create (&thread->thread_id, 0, run_progs, thread); +} + +qwaq_thread_t * +create_thread (void *(*thread_func) (void *)) +{ + qwaq_thread_t *thread = calloc (1, sizeof (*thread)); + + DARRAY_APPEND (&thread_data, thread); + pthread_create (&thread->thread_id, 0, thread_func, thread); + return thread; } static void @@ -376,8 +388,16 @@ main (int argc, char **argv) spawn_progs (thread); } if (main_ind >= 0) { - ret = run_progs (thread_data.a[main_ind]); + // threads might start new threads before the end is reached + size_t count = thread_data.size; + for (size_t i = 0; i < count; i++) { + if (thread_data.a[i]->pr && thread_data.a[i]->main_func) { + start_progs_thread (thread_data.a[main_ind]); + } + } + pthread_join (thread_data.a[main_ind]->thread_id, 0); } + Sys_Shutdown (); return ret; } diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 8f793bdac..65a08d53f 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1347,8 +1347,6 @@ bi_get_event (progs_t *pr) qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); qwaq_event_t *event = &G_STRUCT (pr, qwaq_event_t, P_INT (pr, 0)); - process_commands (res); - process_input (res); R_INT (pr) = get_event (res, event); } @@ -1554,6 +1552,21 @@ bi_mvwblit_line (progs_t *pr) qwaq__mvwblit_line (pr, window_id, x, y, chs, len); } +static void * +qwaq_curse_thread (void *data) +{ + __auto_type thread = (qwaq_thread_t *) data; + progs_t *pr = thread->pr; + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + while (1) { + process_commands (res); + process_input (res); + } + thread->return_code = 0; + return thread; +} + static void bi_initialize (progs_t *pr) { @@ -1573,6 +1586,8 @@ bi_initialize (progs_t *pr) refresh(); res->stdscr.win = stdscr; + + create_thread (qwaq_curse_thread); } static void diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 9dbb2c23a..f89f529e8 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -1,2 +1,19 @@ +#ifndef __qwaq_h +#define __qwaq_h + +#include "QF/darray.h" + +typedef struct qwaq_thread_s { + pthread_t thread_id; + int return_code; + struct DARRAY_TYPE (const char *) args; + sys_printf_t sys_printf; + progs_t *pr; + func_t main_func; +} qwaq_thread_t; + void BI_Init (progs_t *pr); extern struct cbuf_s *qwaq_cbuf; +qwaq_thread_t *create_thread (void *(*thread_func) (void *)); + +#endif//__qwaq_h From ac3fef6dd8d4e01dbd91e5217d622cdb7a97390c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 00:05:56 +0900 Subject: [PATCH 0783/3664] [qwaq] Fix a harmless typo Amusing, though... it was cursed (segaulted). --- ruamoko/qwaq/qwaq-curses.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 65a08d53f..1318445b3 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1553,7 +1553,7 @@ bi_mvwblit_line (progs_t *pr) } static void * -qwaq_curse_thread (void *data) +qwaq_curses_thread (void *data) { __auto_type thread = (qwaq_thread_t *) data; progs_t *pr = thread->pr; @@ -1587,7 +1587,7 @@ bi_initialize (progs_t *pr) res->stdscr.win = stdscr; - create_thread (qwaq_curse_thread); + create_thread (qwaq_curses_thread); } static void From 7beaa567e6235b34bbb7a60e9f2ffe66aee04317 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 00:14:33 +0900 Subject: [PATCH 0784/3664] [qwaq] Pass resource data into the thread Things have come crashing down, but no fire (ie, no deadlocks so far). --- ruamoko/qwaq/main.c | 6 ++++-- ruamoko/qwaq/qwaq-curses.c | 8 +++----- ruamoko/qwaq/qwaq.h | 3 ++- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 2368c2fc9..45da8847e 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -239,12 +239,14 @@ start_progs_thread (qwaq_thread_t *thread) } qwaq_thread_t * -create_thread (void *(*thread_func) (void *)) +create_thread (void *(*thread_func) (qwaq_thread_t *), void *data) { qwaq_thread_t *thread = calloc (1, sizeof (*thread)); + thread->data = data; DARRAY_APPEND (&thread_data, thread); - pthread_create (&thread->thread_id, 0, thread_func, thread); + pthread_create (&thread->thread_id, 0, + (void*(*)(void*))thread_func, thread); return thread; } diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 1318445b3..4503645d2 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1553,11 +1553,9 @@ bi_mvwblit_line (progs_t *pr) } static void * -qwaq_curses_thread (void *data) +qwaq_curses_thread (qwaq_thread_t *thread) { - __auto_type thread = (qwaq_thread_t *) data; - progs_t *pr = thread->pr; - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = thread->data; while (1) { process_commands (res); @@ -1587,7 +1585,7 @@ bi_initialize (progs_t *pr) res->stdscr.win = stdscr; - create_thread (qwaq_curses_thread); + create_thread (qwaq_curses_thread, res); } static void diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index f89f529e8..f0974e61c 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -10,10 +10,11 @@ typedef struct qwaq_thread_s { sys_printf_t sys_printf; progs_t *pr; func_t main_func; + void *data; } qwaq_thread_t; void BI_Init (progs_t *pr); extern struct cbuf_s *qwaq_cbuf; -qwaq_thread_t *create_thread (void *(*thread_func) (void *)); +qwaq_thread_t *create_thread (void *(*thread_func) (qwaq_thread_t *), void *); #endif//__qwaq_h From 5f887c47739da2a6c1314fa31ed3d33c1757eea2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 11:36:24 +0900 Subject: [PATCH 0785/3664] [qwaq] Fix missed logic conversion --- ruamoko/qwaq/qwaq-curses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 4503645d2..a1c9f78cb 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -297,7 +297,7 @@ qwaq_wait_result (qwaq_resources_t *res, int *result, int cmd, unsigned len) { pthread_mutex_lock (&res->results_cond.mut); while (RB_DATA_AVAILABLE (res->results) < len - && RB_PEEK_DATA (res->results, 0) != cmd) { + || RB_PEEK_DATA (res->results, 0) != cmd) { pthread_cond_wait (&res->results_cond.cond, &res->results_cond.mut); } From af137937bd411e23a7208be2cf5723453bddd87c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 11:37:08 +0900 Subject: [PATCH 0786/3664] [qwaq] Add missing mutex unlock --- ruamoko/qwaq/qwaq-curses.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index a1c9f78cb..c97418ea3 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -761,6 +761,7 @@ add_event (qwaq_resources_t *res, qwaq_event_t *event) } RB_WRITE_DATA (res->event_queue, event, 1); pthread_cond_broadcast (&res->event_cond.cond); + pthread_mutex_unlock (&res->event_cond.mut); } static int From abedb465af462ba3c52fafac7a009f1ea53f62e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 11:39:55 +0900 Subject: [PATCH 0787/3664] [qwaq] Use separate conditions for queue read/write While writing the code I suspected this would be necessary, but it's nice to know. Now the window seems to be correctly fetched, but get_event locks up. --- ruamoko/qwaq/qwaq-curses.c | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index c97418ea3..4fdc9e018 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -128,7 +128,8 @@ typedef struct panel_s { } panel_t; typedef struct cond_s { - pthread_cond_t cond; + pthread_cond_t rcond; + pthread_cond_t wcond; pthread_mutex_t mut; } cond_t; @@ -242,11 +243,11 @@ acquire_string (qwaq_resources_t *res) pthread_mutex_lock (&res->string_id_cond.mut); while (!RB_DATA_AVAILABLE (res->string_ids)) { - pthread_cond_wait (&res->string_id_cond.cond, + pthread_cond_wait (&res->string_id_cond.rcond, &res->string_id_cond.mut); } RB_READ_DATA (res->string_ids, &string_id, 1); - pthread_cond_broadcast (&res->string_id_cond.cond); + pthread_cond_broadcast (&res->string_id_cond.wcond); pthread_mutex_unlock (&res->string_id_cond.mut); return string_id; } @@ -256,11 +257,11 @@ release_string (qwaq_resources_t *res, int string_id) { pthread_mutex_lock (&res->string_id_cond.mut); while (RB_SPACE_AVAILABLE (res->string_ids)) { - pthread_cond_wait (&res->string_id_cond.cond, + pthread_cond_wait (&res->string_id_cond.wcond, &res->string_id_cond.mut); } RB_WRITE_DATA (res->string_ids, &string_id, 1); - pthread_cond_broadcast (&res->string_id_cond.cond); + pthread_cond_broadcast (&res->string_id_cond.rcond); pthread_mutex_unlock (&res->string_id_cond.mut); } @@ -271,11 +272,11 @@ qwaq_submit_command (qwaq_resources_t *res, const int *cmd) pthread_mutex_lock (&res->command_cond.mut); while (RB_SPACE_AVAILABLE (res->command_queue) < len) { - pthread_cond_wait (&res->command_cond.cond, + pthread_cond_wait (&res->command_cond.wcond, &res->command_cond.mut); } RB_WRITE_DATA (res->command_queue, cmd, len); - pthread_cond_broadcast (&res->command_cond.cond); + pthread_cond_broadcast (&res->command_cond.rcond); pthread_mutex_unlock (&res->command_cond.mut); } @@ -284,11 +285,11 @@ qwaq_submit_result (qwaq_resources_t *res, const int *result, unsigned len) { pthread_mutex_lock (&res->results_cond.mut); while (RB_SPACE_AVAILABLE (res->results) < len) { - pthread_cond_wait (&res->results_cond.cond, + pthread_cond_wait (&res->results_cond.wcond, &res->results_cond.mut); } RB_WRITE_DATA (res->results, result, len); - pthread_cond_broadcast (&res->results_cond.cond); + pthread_cond_broadcast (&res->results_cond.rcond); pthread_mutex_unlock (&res->results_cond.mut); } @@ -298,11 +299,11 @@ qwaq_wait_result (qwaq_resources_t *res, int *result, int cmd, unsigned len) pthread_mutex_lock (&res->results_cond.mut); while (RB_DATA_AVAILABLE (res->results) < len || RB_PEEK_DATA (res->results, 0) != cmd) { - pthread_cond_wait (&res->results_cond.cond, + pthread_cond_wait (&res->results_cond.rcond, &res->results_cond.mut); } RB_READ_DATA (res->results, result, len); - pthread_cond_broadcast (&res->results_cond.cond); + pthread_cond_broadcast (&res->results_cond.wcond); pthread_mutex_unlock (&res->results_cond.mut); } @@ -636,7 +637,7 @@ process_commands (qwaq_resources_t *res) pthread_mutex_lock (&res->command_cond.mut); init_timeout (&timeout, 20 * 1000000); while (RB_DATA_AVAILABLE (res->command_queue) < 2 && ret != ETIMEDOUT) { - ret = pthread_cond_timedwait (&res->command_cond.cond, + ret = pthread_cond_timedwait (&res->command_cond.rcond, &res->command_cond.mut, &timeout); } pthread_mutex_unlock (&res->command_cond.mut); @@ -727,7 +728,7 @@ process_commands (qwaq_resources_t *res) } pthread_mutex_lock (&res->command_cond.mut); RB_DROP_DATA (res->command_queue, len); - pthread_cond_broadcast (&res->command_cond.cond); + pthread_cond_broadcast (&res->command_cond.wcond); pthread_mutex_unlock (&res->command_cond.mut); } } @@ -746,7 +747,7 @@ add_event (qwaq_resources_t *res, qwaq_event_t *event) && RB_PEEK_DATA(res->event_queue, last - 1).what == qe_mousemove) { RB_POKE_DATA(res->event_queue, last - 1, *event); merged = 1; - pthread_cond_broadcast (&res->event_cond.cond); + pthread_cond_broadcast (&res->event_cond.rcond); } pthread_mutex_unlock (&res->event_cond.mut); if (merged) { @@ -756,11 +757,11 @@ add_event (qwaq_resources_t *res, qwaq_event_t *event) pthread_mutex_lock (&res->event_cond.mut); init_timeout (&timeout, 5000 * 1000000L); while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { - ret = pthread_cond_timedwait (&res->event_cond.cond, + ret = pthread_cond_timedwait (&res->event_cond.wcond, &res->event_cond.mut, &timeout); } RB_WRITE_DATA (res->event_queue, event, 1); - pthread_cond_broadcast (&res->event_cond.cond); + pthread_cond_broadcast (&res->event_cond.rcond); pthread_mutex_unlock (&res->event_cond.mut); } @@ -773,7 +774,7 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) pthread_mutex_lock (&res->event_cond.mut); init_timeout (&timeout, 20 * 1000000); while (RB_DATA_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { - ret = pthread_cond_timedwait (&res->event_cond.cond, + ret = pthread_cond_timedwait (&res->event_cond.rcond, &res->event_cond.mut, &timeout); } if (event) { @@ -783,7 +784,7 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) event->what = qe_none; } } - pthread_cond_broadcast (&res->event_cond.cond); + pthread_cond_broadcast (&res->event_cond.wcond); pthread_mutex_lock (&res->event_cond.mut); return ret != ETIMEDOUT; } @@ -1891,7 +1892,8 @@ qwaq_print (const char *fmt, va_list args) static void qwaq_init_cond (cond_t *cond) { - pthread_cond_init (&cond->cond, 0); + pthread_cond_init (&cond->rcond, 0); + pthread_cond_init (&cond->wcond, 0); pthread_mutex_init (&cond->mut, 0); } From fb17f8093d82f30ada6b8f3db1c9456baa0c95c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 12:02:35 +0900 Subject: [PATCH 0788/3664] [qwaq] Correct some queue test logic This fixes the wedge during initial setup and drawing, but the program deadlocks when processing input and there's an event. --- ruamoko/qwaq/qwaq-curses.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 4fdc9e018..49d6c24e6 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -242,7 +242,7 @@ acquire_string (qwaq_resources_t *res) int string_id = -1; pthread_mutex_lock (&res->string_id_cond.mut); - while (!RB_DATA_AVAILABLE (res->string_ids)) { + while (RB_DATA_AVAILABLE (res->string_ids) < 1) { pthread_cond_wait (&res->string_id_cond.rcond, &res->string_id_cond.mut); } @@ -256,7 +256,7 @@ static void release_string (qwaq_resources_t *res, int string_id) { pthread_mutex_lock (&res->string_id_cond.mut); - while (RB_SPACE_AVAILABLE (res->string_ids)) { + while (RB_SPACE_AVAILABLE (res->string_ids) < 1) { pthread_cond_wait (&res->string_id_cond.wcond, &res->string_id_cond.mut); } From fb6883851d38d23d859e87d9f0a69f6671ccbf44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 12:46:22 +0900 Subject: [PATCH 0789/3664] [qwaq] Actually unlock the event queue mutex And now everything works as well threaded as it did unthreaded. --- ruamoko/qwaq/qwaq-curses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 49d6c24e6..9cc17ab6c 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -785,7 +785,7 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) } } pthread_cond_broadcast (&res->event_cond.wcond); - pthread_mutex_lock (&res->event_cond.mut); + pthread_mutex_unlock (&res->event_cond.mut); return ret != ETIMEDOUT; } From ae70efcaf51c835e32e79e37f5ab0206b1ab2dba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 16:27:53 +0900 Subject: [PATCH 0790/3664] [qw] Clean up a comment --- qw/source/sv_sys_unix.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qw/source/sv_sys_unix.c b/qw/source/sv_sys_unix.c index 315fb02ff..b3781bf5b 100644 --- a/qw/source/sv_sys_unix.c +++ b/qw/source/sv_sys_unix.c @@ -138,8 +138,7 @@ main (int argc, const char **argv) SV_Frame (time); - // extrasleep is just a way to generate a fucked up connection on - // purpose + // extrasleep is just a way to generate a bad connection on purpose if (sys_extrasleep->int_val) usleep (sys_extrasleep->int_val); } From 176cc7b9c1d07e3a3cb6c755cb8d213a5fa45009 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 21:05:34 +0900 Subject: [PATCH 0791/3664] [qwaq] Make some improvements to mouse handling This doesn't fix the problem of lost events: that seems to be inside ncurses. I've done some investigations, and it seems xterm sends separate events for motion and pre/release (which have current coords), in both 1003 and 1006 modes. No idea what ncurses is doing (does it even handle 1003 properly?), and it requires the use of xterm-1006 for it to use 1006 mode (which is nice in that it disambiguates button releases and allows for huge terminals (not that I would use such normally)). Guess I've got some side-work cut out for me :P --- ruamoko/qwaq/event.h | 10 +++++- ruamoko/qwaq/qwaq-curses.c | 65 ++++++++++++++++++++++++++++++-------- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index 03f479fdc..56327c42d 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -9,6 +9,14 @@ typedef enum { qe_mouseauto = 0x0010, } qwaq_mouse_event; +typedef enum { + qe_mouse1 = 0x0001, + qe_mouse2 = 0x0002, + qe_mouse3 = 0x0004, + qe_mouse4 = 0x0008, + qe_mouse5 = 0x0010, +} qwaq_button; + typedef enum { qe_keydown = 0x0020, } qwaq_key_event; @@ -37,7 +45,7 @@ typedef enum { typedef struct qwaq_mevent_s { int x, y; - int buttons; + qwaq_button buttons; // current button state int click; } qwaq_mevent_t; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 9cc17ab6c..6ab3f6154 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1,12 +1,12 @@ /* - #FILENAME# + qwaq-curses.c - #DESCRIPTION# + Ruamoko ncurses wrapper using threading - Copyright (C) 2001 #AUTHOR# + Copyright (C) 2020 Bill Currie - Author: #AUTHOR# - Date: #DATE# + Author: Bill Currie + Date: 2020/03/01 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -54,8 +54,10 @@ #define always_inline inline __attribute__((__always_inline__)) #define QUEUE_SIZE 16 -#define MOUSE_MOVES_ON "\033[?1003h"// Make the terminal report mouse movements -#define MOUSE_MOVES_OFF "\033[?1003l"// Make the terminal report mouse movements +#define MOUSE_MOVES_ON "\033[?1003h" +#define MOUSE_MOVES_OFF "\033[?1003l" +#define SGR_ON "\033[?1006h" +#define SGR_OFF "\033[?1006l" #define STRING_ID_QUEUE_SIZE 8 // must be > 1 #define COMMAND_QUEUE_SIZE 1280 #define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) @@ -141,6 +143,7 @@ typedef struct qwaq_resources_s { PR_RESMAP (panel_t) panel_map; cond_t event_cond; RING_BUFFER (qwaq_event_t, QUEUE_SIZE) event_queue; + qwaq_button button_state; cond_t command_cond; RING_BUFFER (int, COMMAND_QUEUE_SIZE) command_queue; cond_t results_cond; @@ -820,36 +823,70 @@ static void mouse_event (qwaq_resources_t *res, const MEVENT *mevent) { int mask = mevent->bstate; + qwaq_button buttons = res->button_state; qwaq_event_t event = {}; + if (mevent->bstate & ~M_MOVE) { + mvprintw (1, 0, "%08x", mevent->bstate); + doupdate(); + } event.mouse.x = mevent->x; event.mouse.y = mevent->y; - event.mouse.buttons = mevent->bstate; if (mask & M_MOVE) { event.what = qe_mousemove; - mask &= ~M_MOVE; } if (mask & M_PRESS) { event.what = qe_mousedown; - mask &= ~M_PRESS; + if (mask & BUTTON1_PRESSED) { + buttons |= qe_mouse1; + } + if (mask & BUTTON2_PRESSED) { + buttons |= qe_mouse2; + } + if (mask & BUTTON3_PRESSED) { + buttons |= qe_mouse3; + } +#if 0 // wheel events don't report release + if (mask & BUTTON4_PRESSED) { + buttons |= qe_mouse4; + } + if (mask & BUTTON5_PRESSED) { + buttons |= qe_mouse5; + } +#endif } if (mask & M_RELEASE) { event.what = qe_mouseup; - mask &= ~M_RELEASE; + if (mask & BUTTON1_RELEASED) { + buttons &= ~qe_mouse1; + } + if (mask & BUTTON2_RELEASED) { + buttons &= ~qe_mouse2; + } + if (mask & BUTTON3_RELEASED) { + buttons &= ~qe_mouse3; + } +#if 0 // wheel events don't report release + if (mask & BUTTON4_RELEASED) { + buttons &= ~qe_mouse4; + } + if (mask & BUTTON5_RELEASED) { + buttons &= ~qe_mouse5; + } +#endif } + event.mouse.buttons = buttons; + res->button_state = buttons; if (mask & M_CLICK) { event.what = qe_mouseclick; - mask &= ~M_CLICK; event.mouse.click = 1; } if (mask & M_DCLICK) { event.what = qe_mouseclick; - mask &= ~M_DCLICK; event.mouse.click = 2; } if (mask & M_TCLICK) { event.what = qe_mouseclick; - mask &= ~M_TCLICK; event.mouse.click = 3; } add_event (res, &event); From 88b4046632feb42708c38d8b0c67c041d31e84e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Mar 2020 22:24:11 +0900 Subject: [PATCH 0792/3664] [util] Pass a data pointer to shutdown functions And clean up the mess. --- hw/source/master.c | 4 ++-- include/QF/sys.h | 2 +- include/netchan.h | 2 +- libs/util/sys.c | 8 +++++--- nq/include/host.h | 2 +- nq/source/host.c | 2 +- nq/source/sys_sdl.c | 6 +++--- nq/source/sys_unix.c | 6 +++--- nq/source/sys_unixd.c | 6 +++--- nq/source/sys_win.c | 6 +++--- nq/source/sys_wind.c | 6 +++--- qtv/source/qtv.c | 4 ++-- qtv/source/server.c | 4 ++-- qw/include/host.h | 2 +- qw/include/server.h | 2 +- qw/source/cl_main.c | 2 +- qw/source/cl_sys_sdl.c | 8 ++++---- qw/source/cl_sys_unix.c | 8 ++++---- qw/source/cl_sys_win.c | 8 ++++---- qw/source/net_packetlog.c | 4 ++-- qw/source/sv_ccmds.c | 2 +- qw/source/sv_main.c | 4 ++-- qw/source/sv_sys_unix.c | 2 +- qw/source/sv_sys_win.c | 2 +- ruamoko/qwaq/qwaq-bi.c | 4 ++-- ruamoko/qwaq/qwaq-curses.c | 4 ++-- 26 files changed, 56 insertions(+), 54 deletions(-) diff --git a/hw/source/master.c b/hw/source/master.c index 6e744c4ac..afa01cc2b 100644 --- a/hw/source/master.c +++ b/hw/source/master.c @@ -469,7 +469,7 @@ SV_WriteFilterList (void) } static void -SV_Shutdown (void) +SV_Shutdown (void *data) { NET_Shutdown (); @@ -525,7 +525,7 @@ main (int argc, const char **argv) mst_cbuf = Cbuf_New (&id_interp); - Sys_RegisterShutdown (SV_Shutdown); + Sys_RegisterShutdown (SV_Shutdown, 0); Sys_Init (); diff --git a/include/QF/sys.h b/include/QF/sys.h index 06e2590fa..a1a5402c7 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -77,7 +77,7 @@ void Sys_Error (const char *error, ...) __attribute__((format(printf,1,2), noret void Sys_FatalError (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); void Sys_Quit (void) __attribute__((noreturn)); void Sys_Shutdown (void); -void Sys_RegisterShutdown (void (*func) (void)); +void Sys_RegisterShutdown (void (*func) (void *), void *data); int64_t Sys_LongTime (void); double Sys_DoubleTime (void); void Sys_TimeOfDay(date_t *date); diff --git a/include/netchan.h b/include/netchan.h index d811ba913..cfdcf1066 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -70,7 +70,7 @@ void Log_Incoming_Packet (const byte *p, int len, int has_sequence, int is_server); void Log_Outgoing_Packet (const byte *p, int len, int has_sequence, int is_server); -void Net_LogStop (void); +void Net_LogStop (void *data); void Analyze_Client_Packet (const byte * data, int len, int has_sequence); void Analyze_Server_Packet (const byte * data, int len, int has_sequence); diff --git a/libs/util/sys.c b/libs/util/sys.c index 811cac886..de1cb35d8 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -105,7 +105,8 @@ static sys_printf_t sys_err_printf_function = Sys_ErrPrintf; typedef struct shutdown_list_s { struct shutdown_list_s *next; - void (*func)(void); + void (*func) (void *); + void *data; } shutdown_list_t; typedef struct error_handler_s { @@ -492,7 +493,7 @@ Sys_Shutdown (void) shutdown_list_t *t; while (shutdown_list) { - shutdown_list->func (); + shutdown_list->func (shutdown_list->data); t = shutdown_list; shutdown_list = shutdown_list->next; free (t); @@ -571,7 +572,7 @@ Sys_Error (const char *error, ...) } VISIBLE void -Sys_RegisterShutdown (void (*func) (void)) +Sys_RegisterShutdown (void (*func) (void *), void *data) { shutdown_list_t *p; if (!func) @@ -580,6 +581,7 @@ Sys_RegisterShutdown (void (*func) (void)) if (!p) Sys_Error ("Sys_RegisterShutdown: insufficient memory"); p->func = func; + p->data = data; p->next = shutdown_list; shutdown_list = p; } diff --git a/nq/include/host.h b/nq/include/host.h index 8601ea4c2..9300abbfe 100644 --- a/nq/include/host.h +++ b/nq/include/host.h @@ -61,7 +61,7 @@ void Host_ClearMemory (void); void Host_ServerFrame (void); void Host_InitCommands (void); void Host_Init (void); -void Host_Shutdown(void); +void Host_Shutdown(void *data); void Host_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2), noreturn)); void Host_Frame (float time); diff --git a/nq/source/host.c b/nq/source/host.c index 67b55507b..c08a4c093 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -957,7 +957,7 @@ Host_Init (void) better to run quit through here before final handoff to the sys code. */ void -Host_Shutdown (void) +Host_Shutdown (void *data) { static qboolean isdown = false; diff --git a/nq/source/sys_sdl.c b/nq/source/sys_sdl.c index 3f4fa726e..37ff959aa 100644 --- a/nq/source/sys_sdl.c +++ b/nq/source/sys_sdl.c @@ -85,7 +85,7 @@ startup (void) } static void -shutdown_f (void) +shutdown_f (void *data) { #ifndef _WIN32 // change stdin to blocking @@ -113,8 +113,8 @@ SDL_main (int argc, char *argv[]) isDedicated = (COM_CheckParm ("-dedicated") != 0); - Sys_RegisterShutdown (Host_Shutdown); - Sys_RegisterShutdown (shutdown_f); + Sys_RegisterShutdown (Host_Shutdown, 0); + Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/nq/source/sys_unix.c b/nq/source/sys_unix.c index ec21a1d7b..2803d31f6 100644 --- a/nq/source/sys_unix.c +++ b/nq/source/sys_unix.c @@ -55,7 +55,7 @@ qboolean isDedicated = false; static void -shutdown_f (void) +shutdown_f (void *data) { // change stdin to blocking fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK); @@ -75,8 +75,8 @@ main (int argc, const char **argv) isDedicated = (COM_CheckParm ("-dedicated") != 0); - Sys_RegisterShutdown (Host_Shutdown); - Sys_RegisterShutdown (shutdown_f); + Sys_RegisterShutdown (Host_Shutdown, 0); + Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/nq/source/sys_unixd.c b/nq/source/sys_unixd.c index 55d956268..f9ff4ca74 100644 --- a/nq/source/sys_unixd.c +++ b/nq/source/sys_unixd.c @@ -53,7 +53,7 @@ qboolean isDedicated = true; static void -shutdown_f (void) +shutdown_f (void *data) { // change stdin to blocking fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK); @@ -86,8 +86,8 @@ main (int argc, const char **argv) host_parms.argc = com_argc; host_parms.argv = com_argv; - Sys_RegisterShutdown (Host_Shutdown); - Sys_RegisterShutdown (shutdown_f); + Sys_RegisterShutdown (Host_Shutdown, 0); + Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/nq/source/sys_win.c b/nq/source/sys_win.c index 421690748..e4593ffd0 100644 --- a/nq/source/sys_win.c +++ b/nq/source/sys_win.c @@ -104,7 +104,7 @@ startup (void) } static void -shutdown_f (void) +shutdown_f (void *data) { if (tevent) CloseHandle (tevent); @@ -207,8 +207,8 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, if (!isDedicated) init_handles (hInstance); - Sys_RegisterShutdown (Host_Shutdown); - Sys_RegisterShutdown (shutdown_f); + Sys_RegisterShutdown (Host_Shutdown, 0); + Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/nq/source/sys_wind.c b/nq/source/sys_wind.c index b38461448..b0555ec43 100644 --- a/nq/source/sys_wind.c +++ b/nq/source/sys_wind.c @@ -39,7 +39,7 @@ qboolean isDedicated = true; static void -shutdown_f (void) +shutdown_f (void *data) { } @@ -69,8 +69,8 @@ main (int argc, const char **argv) host_parms.argc = com_argc; host_parms.argv = com_argv; - Sys_RegisterShutdown (Host_Shutdown); - Sys_RegisterShutdown (shutdown_f); + Sys_RegisterShutdown (Host_Shutdown, 0); + Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 4980dea9b..1274254d5 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -220,7 +220,7 @@ qtv_memory_init (void) } static void -qtv_shutdown (void) +qtv_shutdown (void *data) { NET_Shutdown (); Con_Shutdown (); @@ -253,7 +253,7 @@ qtv_init (void) qtv_cbuf = Cbuf_New (&id_interp); qtv_args = Cbuf_ArgsNew (); - Sys_RegisterShutdown (qtv_shutdown); + Sys_RegisterShutdown (qtv_shutdown, 0); Sys_Init (); COM_ParseConfig (); diff --git a/qtv/source/server.c b/qtv/source/server.c index c664f36e4..c36465d31 100644 --- a/qtv/source/server.c +++ b/qtv/source/server.c @@ -508,7 +508,7 @@ sv_list_f (void) } static void -server_shutdown (void) +server_shutdown (void *data) { Hash_FlushTable (server_hash); Hash_DelTable (server_hash); @@ -540,7 +540,7 @@ server_run (server_t *sv) void Server_Init (void) { - Sys_RegisterShutdown (server_shutdown); + Sys_RegisterShutdown (server_shutdown, 0); server_hash = Hash_NewTable (61, server_get_key, server_free, 0); Cmd_AddCommand ("sv_new", sv_new_f, "Add a new server"); Cmd_AddCommand ("sv_del", sv_del_f, "Remove an existing server"); diff --git a/qw/include/host.h b/qw/include/host.h index 0c1492f47..27ad77325 100644 --- a/qw/include/host.h +++ b/qw/include/host.h @@ -50,7 +50,7 @@ extern int host_framecount; // incremented every frame, never reset void Host_ServerFrame (void); void Host_InitCommands (void); void Host_Init (void); -void Host_Shutdown(void); +void Host_Shutdown(void *data); void Host_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2), noreturn)); void Host_Frame (float time); diff --git a/qw/include/server.h b/qw/include/server.h index abc5fdd9d..b32a46c63 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -488,7 +488,7 @@ client_t *SV_AllocClient (int spectator, int server); void SV_SavePenaltyFilter (client_t *cl, filtertype_t type, double pentime); double SV_RestorePenaltyFilter (client_t *cl, filtertype_t type); -void SV_Shutdown (void); +void SV_Shutdown (void *data); void SV_Frame (float time); void SV_FinalMessage (const char *message); void SV_DropClient (client_t *drop); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index aa223736f..b78038ca9 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1867,7 +1867,7 @@ Host_Init (void) } void -Host_Shutdown (void) +Host_Shutdown (void *data) { static qboolean isdown = false; diff --git a/qw/source/cl_sys_sdl.c b/qw/source/cl_sys_sdl.c index 75f7c0024..79357134a 100644 --- a/qw/source/cl_sys_sdl.c +++ b/qw/source/cl_sys_sdl.c @@ -93,7 +93,7 @@ startup (void) } static void -shutdown_f (void) +shutdown_f (void *data) { #ifndef _WIN32 // change stdin to blocking @@ -122,9 +122,9 @@ SDL_main (int argc, char *argv[]) if (!COM_CheckParm ("-noconinput")) fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | O_NONBLOCK); #endif - Sys_RegisterShutdown (Host_Shutdown); - Sys_RegisterShutdown (Net_LogStop); - Sys_RegisterShutdown (shutdown_f); + Sys_RegisterShutdown (Host_Shutdown, 0); + Sys_RegisterShutdown (Net_LogStop, 0); + Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/qw/source/cl_sys_unix.c b/qw/source/cl_sys_unix.c index 05aedf9ff..4c7071ba2 100644 --- a/qw/source/cl_sys_unix.c +++ b/qw/source/cl_sys_unix.c @@ -52,7 +52,7 @@ #include "netchan.h" static void -shutdown_f (void) +shutdown_f (void *data) { // change stdin to blocking fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK); @@ -73,9 +73,9 @@ main (int argc, const char **argv) if (!COM_CheckParm ("-noconinput")) fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | O_NONBLOCK); - Sys_RegisterShutdown (Host_Shutdown); - Sys_RegisterShutdown (Net_LogStop); - Sys_RegisterShutdown (shutdown_f); + Sys_RegisterShutdown (Host_Shutdown, 0); + Sys_RegisterShutdown (Net_LogStop, 0); + Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/qw/source/cl_sys_win.c b/qw/source/cl_sys_win.c index 44d7c8afb..388166e7a 100644 --- a/qw/source/cl_sys_win.c +++ b/qw/source/cl_sys_win.c @@ -93,7 +93,7 @@ startup (void) } static void -shutdown_f (void) +shutdown_f (void *data) { if (tevent) CloseHandle (tevent); @@ -181,9 +181,9 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, if (!tevent) Sys_Error ("Couldn't create event"); - Sys_RegisterShutdown (Host_Shutdown); - Sys_RegisterShutdown (Net_LogStop); - Sys_RegisterShutdown (shutdown_f); + Sys_RegisterShutdown (Host_Shutdown, 0); + Sys_RegisterShutdown (Net_LogStop, 0); + Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index 3ec8078e5..189c6fefe 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -177,7 +177,7 @@ Net_LogStart (const char *fname) } void -Net_LogStop (void) +Net_LogStop (void *data) { if (Net_PacketLog) Qclose (Net_PacketLog); @@ -954,7 +954,7 @@ Net_PacketLog_f (cvar_t *var) if (var->int_val) { Net_LogStart ("qfpacket.log"); } else { - Net_LogStop (); + Net_LogStop (0); } } diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index 318a2edaf..93c5247f6 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -223,7 +223,7 @@ SV_Restart_f (void) net_message->message->data); } Sys_Printf ("Shutting down: server restart, shell must relaunch server\n"); - SV_Shutdown (); + SV_Shutdown (0); // Error code 2 on exit, indication shell must restart the server exit (2); } diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index d764c012f..56d135e16 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -237,7 +237,7 @@ Master_Shutdown (void) Quake calls this before calling Sys_Quit or Sys_Error */ void -SV_Shutdown (void) +SV_Shutdown (void *data) { Master_Shutdown (); if (sv_fraglogfile) { @@ -2486,7 +2486,7 @@ SV_Init (void) sv_cbuf = Cbuf_New (&id_interp); sv_args = Cbuf_ArgsNew (); - Sys_RegisterShutdown (SV_Shutdown); + Sys_RegisterShutdown (SV_Shutdown, 0); Sys_Init (); GIB_Init (true); diff --git a/qw/source/sv_sys_unix.c b/qw/source/sv_sys_unix.c index b3781bf5b..24b3adb4b 100644 --- a/qw/source/sv_sys_unix.c +++ b/qw/source/sv_sys_unix.c @@ -122,7 +122,7 @@ main (int argc, const char **argv) SV_Init (); - Sys_RegisterShutdown (Net_LogStop); + Sys_RegisterShutdown (Net_LogStop, 0); // run one frame immediately for first heartbeat SV_Frame (0.1); diff --git a/qw/source/sv_sys_win.c b/qw/source/sv_sys_win.c index 4397f5d92..52f3b230a 100644 --- a/qw/source/sv_sys_win.c +++ b/qw/source/sv_sys_win.c @@ -93,7 +93,7 @@ main (int argc, const char **argv) if (WinNT) Cvar_Set (sys_sleep, "0"); - Sys_RegisterShutdown (Net_LogStop); + Sys_RegisterShutdown (Net_LogStop, 0); // run one frame immediately for first heartbeat SV_Frame (0.1); diff --git a/ruamoko/qwaq/qwaq-bi.c b/ruamoko/qwaq/qwaq-bi.c index 7e21a9259..82bce4996 100644 --- a/ruamoko/qwaq/qwaq-bi.c +++ b/ruamoko/qwaq/qwaq-bi.c @@ -159,7 +159,7 @@ static builtin_t builtins[] = { }; static void -bi_shutdown (void) +bi_shutdown (void *data) { S_Shutdown (); IN_Shutdown (); @@ -177,7 +177,7 @@ BI_Init (progs_t *pr) PI_Init (); PI_RegisterPlugins (client_plugin_list); - Sys_RegisterShutdown (bi_shutdown); + Sys_RegisterShutdown (bi_shutdown, 0); VID_Init_Cvars (); IN_Init_Cvars (); diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 6ab3f6154..27306fc28 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -921,7 +921,7 @@ process_input (qwaq_resources_t *res) static int need_endwin; static void -bi_shutdown (void) +bi_shutdown (void *_pr) { if (need_endwin) { write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); @@ -1950,7 +1950,7 @@ BI_Init (progs_t *pr) PR_Resources_Register (pr, "qwaq", res, bi_qwaq_clear); PR_RegisterBuiltins (pr, builtins); - Sys_RegisterShutdown (bi_shutdown); + Sys_RegisterShutdown (bi_shutdown, pr); logfile = fopen ("qwaq-curses.log", "wt"); Sys_SetStdPrintf (qwaq_print); } From d3527496668029ad7f194d0ce25ee16ef4f0d8f7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 01:00:05 +0900 Subject: [PATCH 0793/3664] [qwaq] Bypass ncurses for input handling For now, only 1003 mouse mode is supported, and function keys are not yet supported, but the mouse is much more reliable: no lost events. --- ruamoko/qwaq/Makefile.am | 2 +- ruamoko/qwaq/event.h | 11 +- ruamoko/qwaq/qwaq-curses.c | 228 +++---------------------------------- ruamoko/qwaq/qwaq-curses.h | 65 +++++++++++ ruamoko/qwaq/qwaq-input.c | 226 ++++++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq.h | 1 + 6 files changed, 313 insertions(+), 220 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-input.c diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 683a0923c..df02f64ab 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -37,7 +37,7 @@ qwaq_app_dat_src= \ qwaq-window.r qwaq_curses_libs= -qwaq_curses_SOURCES=main.c qwaq-curses.c +qwaq_curses_SOURCES=main.c qwaq-curses.c qwaq-input.c qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ $(PANEL_LIBS) $(CURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) qwaq_curses_LDFLAGS= diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index 56327c42d..f1d9e6fbb 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -9,14 +9,6 @@ typedef enum { qe_mouseauto = 0x0010, } qwaq_mouse_event; -typedef enum { - qe_mouse1 = 0x0001, - qe_mouse2 = 0x0002, - qe_mouse3 = 0x0004, - qe_mouse4 = 0x0008, - qe_mouse5 = 0x0010, -} qwaq_button; - typedef enum { qe_keydown = 0x0020, } qwaq_key_event; @@ -45,7 +37,7 @@ typedef enum { typedef struct qwaq_mevent_s { int x, y; - qwaq_button buttons; // current button state + int buttons; // current button state int click; } qwaq_mevent_t; @@ -55,6 +47,7 @@ typedef struct qwaq_message_s { typedef struct qwaq_event_s { int what; + double when; // NOTE: 1<<32 based union { int key; qwaq_mevent_t mouse; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 27306fc28..23f216353 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -47,19 +47,11 @@ #include "QF/sys.h" #include "qwaq.h" -#include "event.h" #include "qwaq-curses.h" #include "qwaq-rect.h" #include "qwaq-textcontext.h" #define always_inline inline __attribute__((__always_inline__)) -#define QUEUE_SIZE 16 -#define MOUSE_MOVES_ON "\033[?1003h" -#define MOUSE_MOVES_OFF "\033[?1003l" -#define SGR_ON "\033[?1006h" -#define SGR_OFF "\033[?1006l" -#define STRING_ID_QUEUE_SIZE 8 // must be > 1 -#define COMMAND_QUEUE_SIZE 1280 #define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) typedef enum qwaq_commands_e { @@ -120,39 +112,6 @@ static const char *qwaq_command_names[]= { "mvwblit_line", }; -typedef struct window_s { - WINDOW *win; -} window_t; - -typedef struct panel_s { - PANEL *panel; - int window_id; -} panel_t; - -typedef struct cond_s { - pthread_cond_t rcond; - pthread_cond_t wcond; - pthread_mutex_t mut; -} cond_t; - -typedef struct qwaq_resources_s { - progs_t *pr; - int initialized; - window_t stdscr; - PR_RESMAP (window_t) window_map; - PR_RESMAP (panel_t) panel_map; - cond_t event_cond; - RING_BUFFER (qwaq_event_t, QUEUE_SIZE) event_queue; - qwaq_button button_state; - cond_t command_cond; - RING_BUFFER (int, COMMAND_QUEUE_SIZE) command_queue; - cond_t results_cond; - RING_BUFFER (int, COMMAND_QUEUE_SIZE) results; - cond_t string_id_cond; - RING_BUFFER (int, STRING_ID_QUEUE_SIZE) string_ids; - dstring_t strings[STRING_ID_QUEUE_SIZE - 1]; -} qwaq_resources_t; - static window_t * window_new (qwaq_resources_t *res) { @@ -320,7 +279,7 @@ cmd_newwin (qwaq_resources_t *res) window_t *window = window_new (res); window->win = newwin (ylen, xlen, ypos, xpos); - keypad (window->win, TRUE); + keypad (window->win, FALSE); // do it ourselves int window_id = window_index (res, window); int cmd_result[] = { qwaq_cmd_newwin, window_id }; @@ -615,8 +574,8 @@ dump_command (qwaq_resources_t *res, int len) } } -static void -init_timeout (struct timespec *timeout, long time) +void +qwaq_init_timeout (struct timespec *timeout, long time) { #define SEC 1000000000 struct timeval now; @@ -638,7 +597,7 @@ process_commands (qwaq_resources_t *res) int ret = 0; pthread_mutex_lock (&res->command_cond.mut); - init_timeout (&timeout, 20 * 1000000); + qwaq_init_timeout (&timeout, 20 * 1000000); while (RB_DATA_AVAILABLE (res->command_queue) < 2 && ret != ETIMEDOUT) { ret = pthread_cond_timedwait (&res->command_cond.rcond, &res->command_cond.mut, &timeout); @@ -736,38 +695,6 @@ process_commands (qwaq_resources_t *res) } } -static void -add_event (qwaq_resources_t *res, qwaq_event_t *event) -{ - struct timespec timeout; - int merged = 0; - int ret = 0; - - // merge motion events - pthread_mutex_lock (&res->event_cond.mut); - unsigned last = RB_DATA_AVAILABLE (res->event_queue); - if (event->what == qe_mousemove && last > 1 - && RB_PEEK_DATA(res->event_queue, last - 1).what == qe_mousemove) { - RB_POKE_DATA(res->event_queue, last - 1, *event); - merged = 1; - pthread_cond_broadcast (&res->event_cond.rcond); - } - pthread_mutex_unlock (&res->event_cond.mut); - if (merged) { - return; - } - - pthread_mutex_lock (&res->event_cond.mut); - init_timeout (&timeout, 5000 * 1000000L); - while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { - ret = pthread_cond_timedwait (&res->event_cond.wcond, - &res->event_cond.mut, &timeout); - } - RB_WRITE_DATA (res->event_queue, event, 1); - pthread_cond_broadcast (&res->event_cond.rcond); - pthread_mutex_unlock (&res->event_cond.mut); -} - static int get_event (qwaq_resources_t *res, qwaq_event_t *event) { @@ -775,7 +702,7 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) int ret = 0; pthread_mutex_lock (&res->event_cond.mut); - init_timeout (&timeout, 20 * 1000000); + qwaq_init_timeout (&timeout, 20 * 1000000); while (RB_DATA_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { ret = pthread_cond_timedwait (&res->event_cond.rcond, &res->event_cond.mut, &timeout); @@ -792,139 +719,15 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) return ret != ETIMEDOUT; } -#define M_MOVE REPORT_MOUSE_POSITION -#define M_PRESS ( BUTTON1_PRESSED \ - | BUTTON2_PRESSED \ - | BUTTON3_PRESSED \ - | BUTTON4_PRESSED \ - | BUTTON5_PRESSED) -#define M_RELEASE ( BUTTON1_RELEASED \ - | BUTTON2_RELEASED \ - | BUTTON3_RELEASED \ - | BUTTON4_RELEASED \ - | BUTTON5_RELEASED) -#define M_CLICK ( BUTTON1_CLICKED \ - | BUTTON2_CLICKED \ - | BUTTON3_CLICKED \ - | BUTTON4_CLICKED \ - | BUTTON5_CLICKED) -#define M_DCLICK ( BUTTON1_DOUBLE_CLICKED \ - | BUTTON2_DOUBLE_CLICKED \ - | BUTTON3_DOUBLE_CLICKED \ - | BUTTON4_DOUBLE_CLICKED \ - | BUTTON5_DOUBLE_CLICKED) -#define M_TCLICK ( BUTTON1_TRIPLE_CLICKED \ - | BUTTON2_TRIPLE_CLICKED \ - | BUTTON3_TRIPLE_CLICKED \ - | BUTTON4_TRIPLE_CLICKED \ - | BUTTON5_TRIPLE_CLICKED) - -static void -mouse_event (qwaq_resources_t *res, const MEVENT *mevent) -{ - int mask = mevent->bstate; - qwaq_button buttons = res->button_state; - qwaq_event_t event = {}; - - if (mevent->bstate & ~M_MOVE) { - mvprintw (1, 0, "%08x", mevent->bstate); - doupdate(); - } - event.mouse.x = mevent->x; - event.mouse.y = mevent->y; - if (mask & M_MOVE) { - event.what = qe_mousemove; - } - if (mask & M_PRESS) { - event.what = qe_mousedown; - if (mask & BUTTON1_PRESSED) { - buttons |= qe_mouse1; - } - if (mask & BUTTON2_PRESSED) { - buttons |= qe_mouse2; - } - if (mask & BUTTON3_PRESSED) { - buttons |= qe_mouse3; - } -#if 0 // wheel events don't report release - if (mask & BUTTON4_PRESSED) { - buttons |= qe_mouse4; - } - if (mask & BUTTON5_PRESSED) { - buttons |= qe_mouse5; - } -#endif - } - if (mask & M_RELEASE) { - event.what = qe_mouseup; - if (mask & BUTTON1_RELEASED) { - buttons &= ~qe_mouse1; - } - if (mask & BUTTON2_RELEASED) { - buttons &= ~qe_mouse2; - } - if (mask & BUTTON3_RELEASED) { - buttons &= ~qe_mouse3; - } -#if 0 // wheel events don't report release - if (mask & BUTTON4_RELEASED) { - buttons &= ~qe_mouse4; - } - if (mask & BUTTON5_RELEASED) { - buttons &= ~qe_mouse5; - } -#endif - } - event.mouse.buttons = buttons; - res->button_state = buttons; - if (mask & M_CLICK) { - event.what = qe_mouseclick; - event.mouse.click = 1; - } - if (mask & M_DCLICK) { - event.what = qe_mouseclick; - event.mouse.click = 2; - } - if (mask & M_TCLICK) { - event.what = qe_mouseclick; - event.mouse.click = 3; - } - add_event (res, &event); -} - -static void -key_event (qwaq_resources_t *res, int key) -{ - qwaq_event_t event = {}; - event.what = qe_keydown; - event.key = key; - add_event (res, &event); -} - -static void -process_input (qwaq_resources_t *res) -{ - if (Sys_CheckInput (1, -1)) { - int ch; - while ((ch = getch ()) != ERR && ch) { - fflush (stderr); - if (ch == KEY_MOUSE) { - MEVENT mevent; - getmouse (&mevent); - mouse_event (res, &mevent); - } else { - key_event (res, ch); - } - } - } -} - static int need_endwin; static void bi_shutdown (void *_pr) { + __auto_type pr = (progs_t *) _pr; + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + if (need_endwin) { - write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); + qwaq_input_shutdown (res); endwin (); } } @@ -1598,7 +1401,7 @@ qwaq_curses_thread (qwaq_thread_t *thread) while (1) { process_commands (res); - process_input (res); + qwaq_process_input (res); } thread->return_code = 0; return thread; @@ -1614,12 +1417,12 @@ bi_initialize (progs_t *pr) res->initialized = 1; start_color (); raw (); - keypad (stdscr, TRUE); + keypad (stdscr, FALSE); // do it ourselves noecho (); nonl (); nodelay (stdscr, TRUE); mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); - write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); + qwaq_input_init (res); refresh(); res->stdscr.win = stdscr; @@ -1844,7 +1647,7 @@ bi_qwaq_clear (progs_t *pr, void *data) __auto_type res = (qwaq_resources_t *) data; if (res->initialized) { - write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); + qwaq_input_shutdown (res); endwin (); } need_endwin = 0; @@ -1939,10 +1742,15 @@ BI_Init (progs_t *pr) { qwaq_resources_t *res = calloc (sizeof (*res), 1); res->pr = pr; + for (int i = 0; i < STRING_ID_QUEUE_SIZE - 1; i++) { RB_WRITE_DATA (res->string_ids, &i, 1); res->strings[i].mem = &dstring_default_mem; } + res->escbuff.mem = &dstring_default_mem; + // ensure the backing buffer exists + dstring_clearstr (&res->escbuff); + qwaq_init_cond (&res->event_cond); qwaq_init_cond (&res->command_cond); qwaq_init_cond (&res->results_cond); diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 6d0c43df2..9bc5c1d2d 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -130,6 +130,71 @@ typedef struct panel_s *panel_t; @extern Rect getwrect (struct window_s *window); @extern void printf(string fmt, ...); +// qfcc stuff +#else +// gcc stuff + +#include +#include + +#include "QF/dstring.h" +#include "QF/progs.h" +#include "QF/ringbuffer.h" + +#define QUEUE_SIZE 16 +#define STRING_ID_QUEUE_SIZE 8 // must be > 1 +#define COMMAND_QUEUE_SIZE 1280 + +typedef struct window_s { + WINDOW *win; +} window_t; + +typedef struct panel_s { + PANEL *panel; + int window_id; +} panel_t; + +typedef struct cond_s { + pthread_cond_t rcond; + pthread_cond_t wcond; + pthread_mutex_t mut; +} cond_t; + +typedef enum { + esc_ground, + esc_escape, + esc_csi, + esc_mouse, + esc_sgr, +} esc_state_t; + +typedef struct qwaq_resources_s { + progs_t *pr; + int initialized; + window_t stdscr; + PR_RESMAP (window_t) window_map; + PR_RESMAP (panel_t) panel_map; + cond_t event_cond; + RING_BUFFER (qwaq_event_t, QUEUE_SIZE) event_queue; + cond_t command_cond; + RING_BUFFER (int, COMMAND_QUEUE_SIZE) command_queue; + cond_t results_cond; + RING_BUFFER (int, COMMAND_QUEUE_SIZE) results; + cond_t string_id_cond; + RING_BUFFER (int, STRING_ID_QUEUE_SIZE) string_ids; + dstring_t strings[STRING_ID_QUEUE_SIZE - 1]; + + dstring_t escbuff; + esc_state_t escstate; + unsigned button_state; + qwaq_event_t lastClick; +} qwaq_resources_t; +// gcc stuff + +void qwaq_input_init (qwaq_resources_t *res); +void qwaq_input_shutdown (qwaq_resources_t *res); +void qwaq_process_input (qwaq_resources_t *res); +void qwaq_init_timeout (struct timespec *timeout, long time); #endif #endif//__qwaq_curses_h diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c new file mode 100644 index 000000000..2875e44f6 --- /dev/null +++ b/ruamoko/qwaq/qwaq-input.c @@ -0,0 +1,226 @@ +/* + qwaq-input.c + + Input handling + + Copyright (C) 2020 Bill Currie + + Author: Bill Currie + Date: 2020/03/21 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "QF/dstring.h" +#include "QF/sys.h" + +#include "qwaq.h" +#include "event.h" +#include "qwaq-curses.h" + +#define always_inline inline __attribute__((__always_inline__)) + +#define MOUSE_MOVES_ON "\033[?1003h" +#define MOUSE_MOVES_OFF "\033[?1003l" +#define SGR_ON "\033[?1006h" +#define SGR_OFF "\033[?1006l" +#define WHEEL_BUTTONS 0x7c // scroll up/down/left/right - always click + +static void +add_event (qwaq_resources_t *res, qwaq_event_t *event) +{ + struct timespec timeout; + int merged = 0; + int ret = 0; + + // merge motion events + pthread_mutex_lock (&res->event_cond.mut); + unsigned last = RB_DATA_AVAILABLE (res->event_queue); + if (event->what == qe_mousemove && last > 1 + && RB_PEEK_DATA(res->event_queue, last - 1).what == qe_mousemove) { + RB_POKE_DATA(res->event_queue, last - 1, *event); + merged = 1; + pthread_cond_broadcast (&res->event_cond.rcond); + } + pthread_mutex_unlock (&res->event_cond.mut); + if (merged) { + return; + } + + pthread_mutex_lock (&res->event_cond.mut); + qwaq_init_timeout (&timeout, 5000 * 1000000L); + while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { + ret = pthread_cond_timedwait (&res->event_cond.wcond, + &res->event_cond.mut, &timeout); + } + RB_WRITE_DATA (res->event_queue, event, 1); + pthread_cond_broadcast (&res->event_cond.rcond); + pthread_mutex_unlock (&res->event_cond.mut); +} + +static void +key_event (qwaq_resources_t *res, int key) +{ + qwaq_event_t event = {}; + event.what = qe_keydown; + event.when = Sys_DoubleTime (); + event.key = key; + add_event (res, &event); +} + +static void +mouse_event (qwaq_resources_t *res, int what, int x, int y) +{ + qwaq_event_t event = {}; + + event.what = what; + event.when = Sys_DoubleTime (); + event.mouse.x = x; + event.mouse.y = y; + event.mouse.buttons = res->button_state; + + if (event.what == qe_mousedown) { + if (event.when - res->lastClick.when <= 0.4 + && res->lastClick.mouse.buttons == event.mouse.buttons + && res->lastClick.mouse.click < 3) { + event.mouse.click = res->lastClick.mouse.click + 1; + event.what = qe_mouseclick; + } + res->lastClick = event; + } else if (event.what == qe_mouseclick) { + // scroll button event, so always single click + event.mouse.click = 1; + } + add_event (res, &event); +} + +static void +parse_mouse (qwaq_resources_t *res) +{ + int x = (byte) res->escbuff.str[1] - '!'; // want 0-based + int y = (byte) res->escbuff.str[2] - '!'; // want 0-based + unsigned ctrl = (byte) res->escbuff.str[0] - ' '; + int button = ctrl & 3; + int ext = (ctrl >> 6); + int what = qe_none; + + if (ctrl & 0x20) { + // motion-only event + button = -1; + what = qe_mousemove; + } else { + // xterm doesn't send release events for buttons 4-7 + res->button_state &= ~(0x7c); + if (!ext && button == 3) { + res->button_state = 0; // unknown which button was released + button = -1; + what = qe_mouseup; + } else { + if (ext) { + button += 4 * ext - 1; + } + res->button_state |= 1 << button; + if (res->button_state & WHEEL_BUTTONS) { + what = qe_mouseclick; + } else { + what = qe_mousedown; + } + } + } + Sys_Printf ("%3d %3d %02x %03x %02x %2d\n", x, y, ctrl, res->button_state, + ext, button + 1); + + mouse_event (res, what, x, y); +} + +static void process_char (qwaq_resources_t *res, char ch) +{ + if (ch == 0x1b) { + // always reset if escape is seen, may be a desync + res->escstate = esc_escape; + } else { + switch (res->escstate) { + case esc_ground: + key_event (res, (byte) ch); + break; + case esc_escape: + if (ch == '[') { + res->escstate = esc_csi; + } + break; + case esc_csi: + if (ch == 'M') { + res->escstate = esc_mouse; + dstring_clear (&res->escbuff); + } + break; + case esc_mouse: + dstring_append (&res->escbuff, &ch, 1); + if (res->escbuff.size == 3) { + parse_mouse (res); + res->escstate = esc_ground; + } + break; + case esc_sgr: + break; + } + //printf("res->escstate %d\n", res->escstate); + } +} + +void qwaq_input_init (qwaq_resources_t *res) +{ + // ncurses takes care of input mode for us, so need only tell xterm + // what we need + write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); +// write(1, SGR_ON, sizeof (SGR_ON) - 1); +} + +void qwaq_input_shutdown (qwaq_resources_t *res) +{ + // ncurses takes care of input mode for us, so need only tell xterm + // what we need +// write(1, SGR_OFF, sizeof (SGR_OFF) - 1); + write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); +} + +void qwaq_process_input (qwaq_resources_t *res) +{ + char buf[256]; + int len; + + while (Sys_CheckInput (1, -1)) { + len = read(0, buf, sizeof (buf)); + //Sys_Printf ("%.*s\n", len-1, buf+1); + for (int i = 0; i < len; i++) { + process_char (res, buf[i]); + } + } +} diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index f0974e61c..3172cd7f7 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -2,6 +2,7 @@ #define __qwaq_h #include "QF/darray.h" +#include "QF/progs.h" typedef struct qwaq_thread_s { pthread_t thread_id; From 9ce64a5cfb20cf69824cf59e1429989bd2c5706f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 01:14:57 +0900 Subject: [PATCH 0794/3664] [build] Fix curses.h header check --- config.d/curses.m4 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config.d/curses.m4 b/config.d/curses.m4 index 073e98217..02d9ce7f4 100644 --- a/config.d/curses.m4 +++ b/config.d/curses.m4 @@ -2,7 +2,9 @@ AC_ARG_ENABLE(curses, [ --disable-curses disable curses support] ) if test "x$enable_curses" != "xno"; then - AC_CHECK_HEADER(curses.h) + AC_CHECK_HEADER([curses.h], + [AC_DEFINE([HAVE_CURSES_H], [1], + [Define to 1 if you have .])]) AC_CHECK_LIB(ncurses, initscr, CURSES_LIBS=-lncurses, AC_CHECK_LIB(pdcurses, initscr, From 243840daa7d8f1ed0da9edb0ea6afa6bd17780a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 02:44:33 +0900 Subject: [PATCH 0795/3664] [qwaq] Support sgr mouse reports Now buttons 12+ work (in theory, I have only 12 so can't test higher), and button release is no longer ambiguous. --- ruamoko/qwaq/qwaq-input.c | 67 +++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c index 2875e44f6..f101036f5 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/qwaq-input.c @@ -31,6 +31,7 @@ # include "config.h" #endif +#include #include #include #include @@ -122,11 +123,8 @@ mouse_event (qwaq_resources_t *res, int what, int x, int y) } static void -parse_mouse (qwaq_resources_t *res) +parse_mouse (qwaq_resources_t *res, unsigned ctrl, int x, int y, int cmd) { - int x = (byte) res->escbuff.str[1] - '!'; // want 0-based - int y = (byte) res->escbuff.str[2] - '!'; // want 0-based - unsigned ctrl = (byte) res->escbuff.str[0] - ' '; int button = ctrl & 3; int ext = (ctrl >> 6); int what = qe_none; @@ -137,8 +135,8 @@ parse_mouse (qwaq_resources_t *res) what = qe_mousemove; } else { // xterm doesn't send release events for buttons 4-7 - res->button_state &= ~(0x7c); - if (!ext && button == 3) { + res->button_state &= ~(0x78); + if (!ext && button == 3 && !cmd) { res->button_state = 0; // unknown which button was released button = -1; what = qe_mouseup; @@ -146,20 +144,42 @@ parse_mouse (qwaq_resources_t *res) if (ext) { button += 4 * ext - 1; } - res->button_state |= 1 << button; - if (res->button_state & WHEEL_BUTTONS) { - what = qe_mouseclick; + if (cmd == 'm') { + res->button_state &= ~(1 << button); + what = qe_mouseup; } else { - what = qe_mousedown; + res->button_state |= 1 << button; + if (res->button_state & WHEEL_BUTTONS) { + what = qe_mouseclick; + } else { + what = qe_mousedown; + } } } } - Sys_Printf ("%3d %3d %02x %03x %02x %2d\n", x, y, ctrl, res->button_state, - ext, button + 1); - mouse_event (res, what, x, y); } +static void +parse_x10 (qwaq_resources_t *res) +{ + int x = (byte) res->escbuff.str[1] - '!'; // want 0-based + int y = (byte) res->escbuff.str[2] - '!'; // want 0-based + unsigned ctrl = (byte) res->escbuff.str[0] - ' '; + + parse_mouse (res, ctrl, x, y, 0); +} + +static void +parse_sgr (qwaq_resources_t *res, char cmd) +{ + unsigned ctrl, x, y; + + sscanf (res->escbuff.str, "%u;%u;%u", &ctrl, &x, &y); + // mouse coords are 1-based, but want 0-based + parse_mouse (res, ctrl, x - 1, y - 1, cmd); +} + static void process_char (qwaq_resources_t *res, char ch) { if (ch == 0x1b) { @@ -179,16 +199,30 @@ static void process_char (qwaq_resources_t *res, char ch) if (ch == 'M') { res->escstate = esc_mouse; dstring_clear (&res->escbuff); + } else if (ch == '<') { + res->escstate = esc_sgr; + dstring_clear (&res->escbuff); + } else { + res->escstate = esc_ground; } break; case esc_mouse: dstring_append (&res->escbuff, &ch, 1); if (res->escbuff.size == 3) { - parse_mouse (res); + parse_x10 (res); res->escstate = esc_ground; } break; case esc_sgr: + if (isdigit (ch) || ch ==';') { + dstring_append (&res->escbuff, &ch, 1); + } else { + if (ch == 'm' || ch == 'M') { + dstring_append (&res->escbuff, "", 1); + parse_sgr (res, ch); + } + res->escstate = esc_ground; + } break; } //printf("res->escstate %d\n", res->escstate); @@ -200,14 +234,14 @@ void qwaq_input_init (qwaq_resources_t *res) // ncurses takes care of input mode for us, so need only tell xterm // what we need write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); -// write(1, SGR_ON, sizeof (SGR_ON) - 1); + write(1, SGR_ON, sizeof (SGR_ON) - 1); } void qwaq_input_shutdown (qwaq_resources_t *res) { // ncurses takes care of input mode for us, so need only tell xterm // what we need -// write(1, SGR_OFF, sizeof (SGR_OFF) - 1); + write(1, SGR_OFF, sizeof (SGR_OFF) - 1); write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); } @@ -218,7 +252,6 @@ void qwaq_process_input (qwaq_resources_t *res) while (Sys_CheckInput (1, -1)) { len = read(0, buf, sizeof (buf)); - //Sys_Printf ("%.*s\n", len-1, buf+1); for (int i = 0; i < len; i++) { process_char (res, buf[i]); } From 486728a4bd0114c5f8bcb073b7f70e7ce01a3a07 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 08:35:37 +0900 Subject: [PATCH 0796/3664] [qwaq] Be a little paranoid about cond wait timeouts I'd left qwaq-curses running overnight and found it locked up: both threads were looping because pthread_cond_timedwait was returning EINVAL. Thus bail if anything other than 0 is returned, and try to ensure tv_nsec is in the range 0..999999999 --- ruamoko/qwaq/qwaq-curses.c | 14 ++++++++------ ruamoko/qwaq/qwaq-input.c | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 23f216353..a59e19ced 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -577,11 +577,11 @@ dump_command (qwaq_resources_t *res, int len) void qwaq_init_timeout (struct timespec *timeout, long time) { - #define SEC 1000000000 + #define SEC 1000000000L struct timeval now; gettimeofday(&now, 0); timeout->tv_sec = now.tv_sec; - timeout->tv_nsec = now.tv_usec * 1000 + time; + timeout->tv_nsec = now.tv_usec * 1000L + time; if (timeout->tv_nsec > SEC) { timeout->tv_sec += timeout->tv_nsec / SEC; timeout->tv_nsec %= SEC; @@ -598,7 +598,7 @@ process_commands (qwaq_resources_t *res) pthread_mutex_lock (&res->command_cond.mut); qwaq_init_timeout (&timeout, 20 * 1000000); - while (RB_DATA_AVAILABLE (res->command_queue) < 2 && ret != ETIMEDOUT) { + while (RB_DATA_AVAILABLE (res->command_queue) < 2 && ret == 0) { ret = pthread_cond_timedwait (&res->command_cond.rcond, &res->command_cond.mut, &timeout); } @@ -700,23 +700,25 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) { struct timespec timeout; int ret = 0; + int was_event = 0; pthread_mutex_lock (&res->event_cond.mut); qwaq_init_timeout (&timeout, 20 * 1000000); - while (RB_DATA_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { + while (RB_DATA_AVAILABLE (res->event_queue) < 1 && ret == 0) { ret = pthread_cond_timedwait (&res->event_cond.rcond, &res->event_cond.mut, &timeout); } if (event) { - if (ret != ETIMEDOUT) { + if (ret == 0) { RB_READ_DATA (res->event_queue, event, 1); + was_event = 1; } else { event->what = qe_none; } } pthread_cond_broadcast (&res->event_cond.wcond); pthread_mutex_unlock (&res->event_cond.mut); - return ret != ETIMEDOUT; + return was_event; } static int need_endwin; diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c index f101036f5..016f57aa0 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/qwaq-input.c @@ -77,7 +77,7 @@ add_event (qwaq_resources_t *res, qwaq_event_t *event) pthread_mutex_lock (&res->event_cond.mut); qwaq_init_timeout (&timeout, 5000 * 1000000L); - while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret != ETIMEDOUT) { + while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret == 0) { ret = pthread_cond_timedwait (&res->event_cond.wcond, &res->event_cond.mut, &timeout); } From 275ed22362e946ef08306e3c9240e1262f7f851b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 08:40:51 +0900 Subject: [PATCH 0797/3664] [qwaq] Actually ensure tv_nsec is valid While typing the previous message I thought to check my "carry" logic. Sure enough, it was wrong... out by 1. I guess I won the threading lottery :P --- ruamoko/qwaq/qwaq-curses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index a59e19ced..eb4be924b 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -582,7 +582,7 @@ qwaq_init_timeout (struct timespec *timeout, long time) gettimeofday(&now, 0); timeout->tv_sec = now.tv_sec; timeout->tv_nsec = now.tv_usec * 1000L + time; - if (timeout->tv_nsec > SEC) { + if (timeout->tv_nsec >= SEC) { timeout->tv_sec += timeout->tv_nsec / SEC; timeout->tv_nsec %= SEC; } From 84cff64f992d5099a0c40fe5ad948f77fd772cf2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 11:18:44 +0900 Subject: [PATCH 0798/3664] Remove many key number hard-codings I left the ones below 256 alone (some were necessary anyway), but above 256 they were almost entirely sequential, which rather defeats the purpose of using an enum, especially since it makes it difficult to expand sections. --- include/QF/keys.h | 126 +++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/include/QF/keys.h b/include/QF/keys.h index 7c9c959fd..bdf32f6f0 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -227,77 +227,77 @@ typedef enum { /* Numeric keypad */ QFK_KP0 = 256, - QFK_KP1 = 257, - QFK_KP2 = 258, - QFK_KP3 = 259, - QFK_KP4 = 260, - QFK_KP5 = 261, - QFK_KP6 = 262, - QFK_KP7 = 263, - QFK_KP8 = 264, - QFK_KP9 = 265, - QFK_KP_PERIOD = 266, - QFK_KP_DIVIDE = 267, - QFK_KP_MULTIPLY = 268, - QFK_KP_MINUS = 269, - QFK_KP_PLUS = 270, - QFK_KP_ENTER = 271, - QFK_KP_EQUALS = 272, + QFK_KP1, + QFK_KP2, + QFK_KP3, + QFK_KP4, + QFK_KP5, + QFK_KP6, + QFK_KP7, + QFK_KP8, + QFK_KP9, + QFK_KP_PERIOD, + QFK_KP_DIVIDE, + QFK_KP_MULTIPLY, + QFK_KP_MINUS, + QFK_KP_PLUS, + QFK_KP_ENTER, + QFK_KP_EQUALS, /* Arrows + Home/End pad */ - QFK_UP = 273, - QFK_DOWN = 274, - QFK_RIGHT = 275, - QFK_LEFT = 276, - QFK_INSERT = 277, - QFK_HOME = 278, - QFK_END = 279, - QFK_PAGEUP = 280, - QFK_PAGEDOWN = 281, + QFK_UP, + QFK_DOWN, + QFK_RIGHT, + QFK_LEFT, + QFK_INSERT, + QFK_HOME, + QFK_END, + QFK_PAGEUP, + QFK_PAGEDOWN, /* Function keys */ - QFK_F1 = 282, - QFK_F2 = 283, - QFK_F3 = 284, - QFK_F4 = 285, - QFK_F5 = 286, - QFK_F6 = 287, - QFK_F7 = 288, - QFK_F8 = 289, - QFK_F9 = 290, - QFK_F10 = 291, - QFK_F11 = 292, - QFK_F12 = 293, - QFK_F13 = 294, - QFK_F14 = 295, - QFK_F15 = 296, + QFK_F1, + QFK_F2, + QFK_F3, + QFK_F4, + QFK_F5, + QFK_F6, + QFK_F7, + QFK_F8, + QFK_F9, + QFK_F10, + QFK_F11, + QFK_F12, + QFK_F13, + QFK_F14, + QFK_F15, /* Key state modifier keys */ - QFK_NUMLOCK = 300, - QFK_CAPSLOCK = 301, - QFK_SCROLLOCK = 302, - QFK_RSHIFT = 303, - QFK_LSHIFT = 304, - QFK_RCTRL = 305, - QFK_LCTRL = 306, - QFK_RALT = 307, - QFK_LALT = 308, - QFK_RMETA = 309, - QFK_LMETA = 310, - QFK_LSUPER = 311, /* Left "Windows" key */ - QFK_RSUPER = 312, /* Right "Windows" key */ - QFK_MODE = 313, /* "Alt Gr" key */ - QFK_COMPOSE = 314, /* Multi-key compose key */ + QFK_NUMLOCK, + QFK_CAPSLOCK, + QFK_SCROLLOCK, + QFK_RSHIFT, + QFK_LSHIFT, + QFK_RCTRL, + QFK_LCTRL, + QFK_RALT, + QFK_LALT, + QFK_RMETA, + QFK_LMETA, + QFK_LSUPER, /* Left "Windows" key */ + QFK_RSUPER, /* Right "Windows" key */ + QFK_MODE, /* "Alt Gr" key */ + QFK_COMPOSE, /* Multi-key compose key */ /* Miscellaneous function keys */ - QFK_HELP = 315, - QFK_PRINT = 316, - QFK_SYSREQ = 317, - QFK_BREAK = 318, - QFK_MENU = 319, - QFK_POWER = 320, /* Power Macintosh power key */ - QFK_EURO = 321, /* Some european keyboards */ - QFK_UNDO = 322, + QFK_HELP, + QFK_PRINT, + QFK_SYSREQ, + QFK_BREAK, + QFK_MENU, + QFK_POWER, /* Power Macintosh power key */ + QFK_EURO, /* Some european keyboards */ + QFK_UNDO, /* Japanese keys */ QFK_KANJI, /* Kanji, Kanji convert */ From 28f50d27191cd245715a19dde3067acc835077c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 11:24:40 +0900 Subject: [PATCH 0799/3664] Add function key defs up to F48 This allows for the four combinations of shift and control. Not bothering with alt because alt-f4 closes my xterm (bbkeys from the looks of it: it grabs a bunch of Mod1-* keys). --- include/QF/keys.h | 33 +++++++++++++++++++++++++++++++++ libs/video/targets/keys.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/include/QF/keys.h b/include/QF/keys.h index bdf32f6f0..c8fe1cbe2 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -271,6 +271,39 @@ typedef enum { QFK_F13, QFK_F14, QFK_F15, + QFK_F16, + QFK_F17, + QFK_F18, + QFK_F19, + QFK_F20, + QFK_F21, + QFK_F22, + QFK_F23, + QFK_F24, + QFK_F25, + QFK_F26, + QFK_F27, + QFK_F28, + QFK_F29, + QFK_F30, + QFK_F31, + QFK_F32, + QFK_F33, + QFK_F34, + QFK_F35, + QFK_F36, + QFK_F37, + QFK_F38, + QFK_F39, + QFK_F40, + QFK_F41, + QFK_F42, + QFK_F43, + QFK_F44, + QFK_F45, + QFK_F46, + QFK_F47, + QFK_F48, /* Key state modifier keys */ QFK_NUMLOCK, diff --git a/libs/video/targets/keys.c b/libs/video/targets/keys.c index daa9eeda8..5d42aadd0 100644 --- a/libs/video/targets/keys.c +++ b/libs/video/targets/keys.c @@ -312,6 +312,39 @@ keyname_t keynames[] = { { "K_F13", QFK_F13 }, { "K_F14", QFK_F14 }, { "K_F15", QFK_F15 }, + { "K_F16", QFK_F16 }, + { "K_F17", QFK_F17 }, + { "K_F18", QFK_F18 }, + { "K_F19", QFK_F19 }, + { "K_F20", QFK_F20 }, + { "K_F21", QFK_F21 }, + { "K_F22", QFK_F22 }, + { "K_F23", QFK_F23 }, + { "K_F24", QFK_F24 }, + { "K_F25", QFK_F25 }, + { "K_F26", QFK_F26 }, + { "K_F27", QFK_F27 }, + { "K_F28", QFK_F28 }, + { "K_F29", QFK_F29 }, + { "K_F30", QFK_F30 }, + { "K_F31", QFK_F31 }, + { "K_F32", QFK_F32 }, + { "K_F33", QFK_F33 }, + { "K_F34", QFK_F34 }, + { "K_F35", QFK_F35 }, + { "K_F36", QFK_F36 }, + { "K_F37", QFK_F37 }, + { "K_F38", QFK_F38 }, + { "K_F39", QFK_F39 }, + { "K_F40", QFK_F40 }, + { "K_F41", QFK_F41 }, + { "K_F42", QFK_F42 }, + { "K_F43", QFK_F43 }, + { "K_F44", QFK_F44 }, + { "K_F45", QFK_F45 }, + { "K_F46", QFK_F46 }, + { "K_F47", QFK_F47 }, + { "K_F48", QFK_F48 }, { "K_NUMLOCK", QFK_NUMLOCK }, { "K_CAPSLOCK", QFK_CAPSLOCK }, { "K_SCROLLOCK", QFK_SCROLLOCK }, From fc445827266fce1078e1ea074a9f90a61ac39f88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 13:47:44 +0900 Subject: [PATCH 0800/3664] [qwaq] Parse function keys While the key escape sequences are xterm-specific, they are only the default and preliminary provision has been made for overriding them. However, no override mechanism has been implemented beyond using dynamic table lookup. --- ruamoko/qwaq/Makefile.am | 10 ++- ruamoko/qwaq/event.h | 7 +- ruamoko/qwaq/main.c | 2 + ruamoko/qwaq/qwaq-curses.h | 2 + ruamoko/qwaq/qwaq-input.c | 174 ++++++++++++++++++++++++++++++++++++- 5 files changed, 187 insertions(+), 8 deletions(-) diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index df02f64ab..f8e402e10 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -12,7 +12,7 @@ QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(top_builddir)/tools/qfcc/source/qfcc QCFLAGS=-qq -O -g -Werror -QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include +QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) @@ -36,7 +36,11 @@ qwaq_app_dat_src= \ qwaq-view.r \ qwaq-window.r -qwaq_curses_libs= +#FIXME this coupling is horrible +qwaq_curses_libs= \ + $(top_builddir)/libs/video/targets/libvid_common.la \ + $(top_builddir)/libs/console/libQFconsole.la \ + $(top_builddir)/libs/gib/libQFgib.la qwaq_curses_SOURCES=main.c qwaq-curses.c qwaq-input.c qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ $(PANEL_LIBS) $(CURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) @@ -73,7 +77,7 @@ qwaq_app_dat_SOURCES=$(qwaq_app_dat_src) qwaq_app_obj=$(qwaq_app_dat_SOURCES:.r=.o) qwaq_app_dep=$(addprefix ./$(DEPDIR)/,$(qwaq_app_obj:.o=.Qo)) qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) - $(QLINK) -o $@ $(qwaq_app_obj) -lr + $(QLINK) -o $@ $(qwaq_app_obj) -lcsqc -lr include $(qwaq_app_dep) # am--include-marker r_depfiles_remade += $(qwaq_app_dep) diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index f1d9e6fbb..89534f32a 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -41,6 +41,11 @@ typedef struct qwaq_mevent_s { int click; } qwaq_mevent_t; +typedef struct qwaq_kevent_s { + int code; + int shift; +} qwaq_kevent_t; + typedef struct qwaq_message_s { qwaq_command command; } qwaq_message_t; @@ -49,7 +54,7 @@ typedef struct qwaq_event_s { int what; double when; // NOTE: 1<<32 based union { - int key; + qwaq_kevent_t key; qwaq_mevent_t mouse; qwaq_message_t message; }; diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 45da8847e..b9f0dd0e4 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -43,6 +43,7 @@ #include "QF/cvar.h" #include "QF/gib.h" #include "QF/idparse.h" +#include "QF/keys.h" #include "QF/progs.h" #include "QF/qargs.h" #include "QF/quakefs.h" @@ -151,6 +152,7 @@ create_progs (void) PR_Init_Cvars (); PR_Init (pr); RUA_Init (pr, 0); + Key_Progs_Init (pr); PR_Cmds_Init (pr); BI_Init (pr); diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 9bc5c1d2d..55f121990 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -166,6 +166,7 @@ typedef enum { esc_csi, esc_mouse, esc_sgr, + esc_key, } esc_state_t; typedef struct qwaq_resources_s { @@ -188,6 +189,7 @@ typedef struct qwaq_resources_s { esc_state_t escstate; unsigned button_state; qwaq_event_t lastClick; + struct hashtab_s *key_sequences; } qwaq_resources_t; // gcc stuff diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c index 016f57aa0..505ea4f8f 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/qwaq-input.c @@ -40,6 +40,8 @@ #include #include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/keys.h" #include "QF/sys.h" #include "qwaq.h" @@ -54,6 +56,112 @@ #define SGR_OFF "\033[?1006l" #define WHEEL_BUTTONS 0x7c // scroll up/down/left/right - always click +typedef struct qwaq_key_s { + const char *sequence; + knum_t key; + unsigned shift; +} qwaq_key_t; + +static qwaq_key_t default_keys[] = { + { "\033OP", QFK_F1 }, + { "\033OQ", QFK_F2 }, + { "\033OR", QFK_F3 }, + { "\033OS", QFK_F4 }, + { "\033[15~", QFK_F5 }, + { "\033[17~", QFK_F6 }, + { "\033[18~", QFK_F7 }, + { "\033[19~", QFK_F8 }, + { "\033[20~", QFK_F9 }, + { "\033[21~", QFK_F10 }, + { "\033[23~", QFK_F11 }, + { "\033[24~", QFK_F12 }, + // shift F1-F12 + { "\033[1;2P", QFK_F13 }, + { "\033[1;2Q", QFK_F14 }, + { "\033[1;2R", QFK_F15 }, + { "\033[1;2S", QFK_F16 }, + { "\033[15;2~", QFK_F17 }, + { "\033[17;2~", QFK_F18 }, + { "\033[18;2~", QFK_F19 }, + { "\033[19;2~", QFK_F20 }, + { "\033[20;2~", QFK_F21 }, + { "\033[21;2~", QFK_F22 }, + { "\033[23;2~", QFK_F23 }, + { "\033[24;2~", QFK_F24 }, + // control F1-F12 + { "\033[1;5P", QFK_F25 }, + { "\033[1;5Q", QFK_F26 }, + { "\033[1;5R", QFK_F27 }, + { "\033[1;5S", QFK_F28 }, + { "\033[15;5~", QFK_F29 }, + { "\033[17;5~", QFK_F30 }, + { "\033[18;5~", QFK_F31 }, + { "\033[19;5~", QFK_F32 }, + { "\033[20;5~", QFK_F33 }, + { "\033[21;5~", QFK_F34 }, + { "\033[23;5~", QFK_F35 }, + { "\033[24;5~", QFK_F36 }, + // shift control F1-F12 + { "\033[1;6P", QFK_F37 }, + { "\033[1;6Q", QFK_F38 }, + { "\033[1;6R", QFK_F39 }, + { "\033[1;6S", QFK_F40 }, + { "\033[15;6~", QFK_F41 }, + { "\033[17;6~", QFK_F42 }, + { "\033[18;6~", QFK_F43 }, + { "\033[19;6~", QFK_F44 }, + { "\033[20;6~", QFK_F45 }, + { "\033[21;6~", QFK_F46 }, + { "\033[23;6~", QFK_F47 }, + { "\033[24;6~", QFK_F48 }, + + { "\033[2~", QFK_INSERT, 0 }, + { "\033[3~", QFK_DELETE, 0 }, + { "\033[H", QFK_HOME, 0 }, + { "\033[F", QFK_END, 0 }, + { "\033[5~", QFK_PAGEUP, 0 }, + { "\033[6~", QFK_PAGEDOWN, 0 }, + { "\033[A", QFK_UP, 0 }, + { "\033[B", QFK_DOWN, 0 }, + { "\033[C", QFK_RIGHT, 0 }, + { "\033[D", QFK_LEFT, 0 }, + // shift + // there may be a setting to tell xterm to NOT act on shift ins/pgup/pgdn + { "\033[2;2~", QFK_INSERT, 1 }, // xterm gobbles (and pastes) + { "\033[3;2~", QFK_DELETE, 1 }, + { "\033[1;2H", QFK_HOME, 1 }, + { "\033[1;2F", QFK_END, 1 }, + { "\033[5;2~", QFK_PAGEUP, 1 }, // xterm gobbles (scrolls term) + { "\033[6;2~", QFK_PAGEDOWN, 1 }, // xterm gobbles (scrolls term) + { "\033[1;2A", QFK_UP, 1 }, + { "\033[1;2B", QFK_DOWN, 1 }, + { "\033[1;2C", QFK_RIGHT, 1 }, + { "\033[1;2D", QFK_LEFT, 1 }, + { "\033[Z", QFK_TAB, 1 }, + // control + { "\033[2;5~", QFK_INSERT, 4 }, + { "\033[3;5~", QFK_DELETE, 4 }, + { "\033[1;5H", QFK_HOME, 4 }, + { "\033[1;5F", QFK_END, 4 }, + { "\033[5;5~", QFK_PAGEUP, 4 }, + { "\033[6;5~", QFK_PAGEDOWN, 4 }, + { "\033[1;5A", QFK_UP, 4 }, + { "\033[1;5B", QFK_DOWN, 4 }, + { "\033[1;5C", QFK_RIGHT, 4 }, + { "\033[1;5D", QFK_LEFT, 4 }, + // shift control + { "\033[2;6~", QFK_INSERT, 5 }, + { "\033[3;6~", QFK_DELETE, 5 }, + { "\033[1;6H", QFK_HOME, 5 }, + { "\033[1;6F", QFK_END, 5 }, + { "\033[5;6~", QFK_PAGEUP, 5 }, + { "\033[6;6~", QFK_PAGEDOWN, 5 }, + { "\033[1;6A", QFK_UP, 5 }, + { "\033[1;6B", QFK_DOWN, 5 }, + { "\033[1;6C", QFK_RIGHT, 5 }, + { "\033[1;6D", QFK_LEFT, 5 }, +}; + static void add_event (qwaq_resources_t *res, qwaq_event_t *event) { @@ -87,12 +195,13 @@ add_event (qwaq_resources_t *res, qwaq_event_t *event) } static void -key_event (qwaq_resources_t *res, int key) +key_event (qwaq_resources_t *res, int key, unsigned shift) { qwaq_event_t event = {}; event.what = qe_keydown; event.when = Sys_DoubleTime (); - event.key = key; + event.key.code = key; + event.key.shift = shift; add_event (res, &event); } @@ -180,6 +289,19 @@ parse_sgr (qwaq_resources_t *res, char cmd) parse_mouse (res, ctrl, x - 1, y - 1, cmd); } +static void +parse_key (qwaq_resources_t *res) +{ + qwaq_key_t *key = Hash_Find (res->key_sequences, res->escbuff.str); + + Sys_Printf ("parse_key %s %p\n", res->escbuff.str + 1, key); + if (key) { + Sys_Printf (" %d %03x %s\n", key->key, key->shift, + Key_KeynumToString (key->key)); + key_event (res, key->key, key->shift); + } +} + static void process_char (qwaq_resources_t *res, char ch) { if (ch == 0x1b) { @@ -188,11 +310,19 @@ static void process_char (qwaq_resources_t *res, char ch) } else { switch (res->escstate) { case esc_ground: - key_event (res, (byte) ch); + key_event (res, (byte) ch, 0); // shift state unknown break; case esc_escape: if (ch == '[') { res->escstate = esc_csi; + } else if (ch == 'O') { + // will wind up accepting P;P... but meh + res->escstate = esc_key; + dstring_clear (&res->escbuff); + // start the buffer with what got us hear: eases key lookup + dstring_append (&res->escbuff, "\033O", 2); + } else { + res->escstate = esc_ground; } break; case esc_csi: @@ -202,6 +332,14 @@ static void process_char (qwaq_resources_t *res, char ch) } else if (ch == '<') { res->escstate = esc_sgr; dstring_clear (&res->escbuff); + } else if (ch >= '0' && ch < 127) { + res->escstate = esc_key; + dstring_clear (&res->escbuff); + // start the buffer with what got us hear: eases key lookup + dstring_append (&res->escbuff, "\033[", 2); + // the csi code might be short (eg, \e[H for home) so + // need to check for end of string right away + goto esc_key_jump; } else { res->escstate = esc_ground; } @@ -214,23 +352,51 @@ static void process_char (qwaq_resources_t *res, char ch) } break; case esc_sgr: - if (isdigit (ch) || ch ==';') { + if (isdigit (ch) || ch == ';') { dstring_append (&res->escbuff, &ch, 1); } else { if (ch == 'm' || ch == 'M') { + // terminate the string dstring_append (&res->escbuff, "", 1); parse_sgr (res, ch); } res->escstate = esc_ground; } break; + case esc_key: +esc_key_jump: + dstring_append (&res->escbuff, &ch, 1); + if (!isdigit (ch) && ch != ';') { + // terminate the string + dstring_append (&res->escbuff, "", 1); + // parse_key will sort out whether it was a valid sequence + parse_key (res); + res->escstate = esc_ground; + } + break; } //printf("res->escstate %d\n", res->escstate); } } +static const char * +key_sequence_getkey (const void *_seq, void *unused) +{ + __auto_type seq = (const qwaq_key_t *) _seq; + return seq->sequence; +} + void qwaq_input_init (qwaq_resources_t *res) { + if (res->key_sequences) { + Hash_FlushTable (res->key_sequences); + } else { + res->key_sequences = Hash_NewTable (127, key_sequence_getkey, 0, 0); + } + for (size_t i = 0; i < sizeof (default_keys) / sizeof (default_keys[0]); + i++) { + Hash_Add (res->key_sequences, &default_keys[i]); + } // ncurses takes care of input mode for us, so need only tell xterm // what we need write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); From 75f38f456bbdacf01d5b77b75108c78c25a53b52 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 13:49:42 +0900 Subject: [PATCH 0801/3664] [qwaq] Fix a linker warning that had been hiding --- ruamoko/qwaq/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index b9f0dd0e4..484618571 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -80,9 +80,11 @@ static QFile * open_file (const char *path, int *len) { QFile *file = Qopen (path, "rbz"); + char errbuff[1024]; if (!file) { - Sys_Printf ("%s\n", sys_errlist[errno]); + strerror_r(errno, errbuff, sizeof (errbuff)); + Sys_Printf ("%s\n", errbuff); return 0; } *len = Qfilesize (file); From 50290baf048dd8bf2d6a274de4f94fa611188073 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 13:54:54 +0900 Subject: [PATCH 0802/3664] [qwaq] Add missing part of commit --- ruamoko/qwaq/qwaq-app.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index beeb02788..f2834b77e 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -131,7 +131,7 @@ arp_end (void) -handleEvent: (qwaq_event_t *) event { [objects handleEvent: event]; - if (event.what == qe_key && event.key == '\x18') { + if (event.what == qe_key && event.key.code == '\x18') { event.what = qe_command; event.message.command = qc_exit; } From 5cdd1931b7d9b5c3e2c63c73bd51f1ad2a2472a2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 13:56:31 +0900 Subject: [PATCH 0803/3664] [qwaq] Remove some debug --- ruamoko/qwaq/qwaq-input.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c index 505ea4f8f..558744d81 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/qwaq-input.c @@ -294,10 +294,7 @@ parse_key (qwaq_resources_t *res) { qwaq_key_t *key = Hash_Find (res->key_sequences, res->escbuff.str); - Sys_Printf ("parse_key %s %p\n", res->escbuff.str + 1, key); if (key) { - Sys_Printf (" %d %03x %s\n", key->key, key->shift, - Key_KeynumToString (key->key)); key_event (res, key->key, key->shift); } } From f3c68eaadacc13c7447f41d85369276af26e81d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 14:06:27 +0900 Subject: [PATCH 0804/3664] Implement mouse auto events These are for when a button is held down: good for scroll bar arrows etc. --- ruamoko/qwaq/qwaq-button.r | 7 +++++-- ruamoko/qwaq/qwaq-curses.c | 5 +++++ ruamoko/qwaq/qwaq-curses.h | 2 ++ ruamoko/qwaq/qwaq-input.c | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/qwaq-button.r index fe7aa5f2f..ab8477a8a 100644 --- a/ruamoko/qwaq/qwaq-button.r +++ b/ruamoko/qwaq/qwaq-button.r @@ -66,8 +66,11 @@ } break; case qe_mouseauto: - click = 0; - action = onAuto; + if (pressed + && [self containsPoint: {event.mouse.x, event.mouse.y}]) { + click = 0; + action = onAuto; + } break; } if (action) { diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index eb4be924b..3306af584 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -712,6 +712,11 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) if (ret == 0) { RB_READ_DATA (res->event_queue, event, 1); was_event = 1; + } else if (res->button_state) { + event->what = qe_mouseauto; + event->mouse.buttons = res->button_state; + event->mouse.x = res->mouse_x; + event->mouse.y = res->mouse_y; } else { event->what = qe_none; } diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 55f121990..be87e6423 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -188,6 +188,8 @@ typedef struct qwaq_resources_s { dstring_t escbuff; esc_state_t escstate; unsigned button_state; + int mouse_x; + int mouse_y; qwaq_event_t lastClick; struct hashtab_s *key_sequences; } qwaq_resources_t; diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c index 558744d81..cab020328 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/qwaq-input.c @@ -266,6 +266,8 @@ parse_mouse (qwaq_resources_t *res, unsigned ctrl, int x, int y, int cmd) } } } + res->mouse_x = x; + res->mouse_y = y; mouse_event (res, what, x, y); } From 63a2204fa594b09863fe8bab3dd440feb0d34552 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 14:24:12 +0900 Subject: [PATCH 0805/3664] [qwaq] Fix incorrect mouse wheel bits I thought I fixed that already (mistreating mouse 3 as part of the wheel group). --- ruamoko/qwaq/qwaq-input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c index cab020328..61d3b1208 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/qwaq-input.c @@ -54,7 +54,7 @@ #define MOUSE_MOVES_OFF "\033[?1003l" #define SGR_ON "\033[?1006h" #define SGR_OFF "\033[?1006l" -#define WHEEL_BUTTONS 0x7c // scroll up/down/left/right - always click +#define WHEEL_BUTTONS 0x78 // scroll up/down/left/right - always click typedef struct qwaq_key_s { const char *sequence; From 4dbf280012521e6bf6bc7d546cb35ce797ef1de1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 20:19:25 +0900 Subject: [PATCH 0806/3664] [util] Add a means to open a gap in a text buffer for loading files into the buffer. --- include/QF/txtbuffer.h | 14 ++++++++++++++ libs/util/txtbuffer.c | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/QF/txtbuffer.h b/include/QF/txtbuffer.h index e73c7257a..8e4723fb9 100644 --- a/include/QF/txtbuffer.h +++ b/include/QF/txtbuffer.h @@ -59,6 +59,20 @@ txtbuffer_t *TextBuffer_Create (void); */ void TextBuffer_Destroy (txtbuffer_t *buffer); +/** Open a gap for writing at the specified offset. + + Text after the offset is moved to be after the opened gap. + The buffer is resized as necessary. + + \param buffer The buffer to be updated + \param offset The offset in the buffer at which to insert the text block + \param text_len The size of the gap to be opened + \return Pointr to beginning of gap if successful, 0 if failure + (offset not valid or out of memory) +*/ +char *TextBuffer_OpenGap (txtbuffer_t *buffer, size_t offset, + size_t text_len); + /** Insert a block of text at the specified offset. Text after the offset is moved to be after the inserted block of text. diff --git a/libs/util/txtbuffer.c b/libs/util/txtbuffer.c index 59ee0da16..0edc785b5 100644 --- a/libs/util/txtbuffer.c +++ b/libs/util/txtbuffer.c @@ -159,6 +159,21 @@ TextBuffer_Destroy (txtbuffer_t *buffer) FREE (txtbuffers, buffer); } +VISIBLE char * +TextBuffer_OpenGap (txtbuffer_t *buffer, size_t offset, size_t text_len) +{ + char *dst; + + if (offset > buffer->textSize) { + return 0; + } + dst = txtbuffer_open_gap (buffer, offset, text_len); + if (!dst) { + return 0; + } + return dst; +} + VISIBLE int TextBuffer_InsertAt (txtbuffer_t *buffer, size_t offset, const char *text, size_t text_len) From ee9d3a36ab942217d31c4f1db45fd75c3482a48f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 20:51:55 +0900 Subject: [PATCH 0807/3664] [qwaq] Add an editor buffer It's a fairly high-level wrapper for TextBuffer in that it implements file ops (load/save), searching, navigation, and formatting (simple line-oriented with tab stops (currently at 4 spaces)). --- ruamoko/qwaq/Makefile.am | 7 +- ruamoko/qwaq/main.c | 7 +- ruamoko/qwaq/qwaq-editbuffer-bi.c | 908 ++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-editbuffer.h | 79 +++ ruamoko/qwaq/qwaq-editbuffer.r | 47 ++ ruamoko/qwaq/qwaq.h | 2 + 6 files changed, 1046 insertions(+), 4 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-editbuffer-bi.c create mode 100644 ruamoko/qwaq/qwaq-editbuffer.h create mode 100644 ruamoko/qwaq/qwaq-editbuffer.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index f8e402e10..4f8b552e2 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -27,6 +27,7 @@ qwaq_app_dat_src= \ qwaq-app.r \ qwaq-button.r \ qwaq-draw.r \ + qwaq-editbuffer.r \ qwaq-garray.r \ qwaq-group.r \ qwaq-listener.r \ @@ -41,7 +42,11 @@ qwaq_curses_libs= \ $(top_builddir)/libs/video/targets/libvid_common.la \ $(top_builddir)/libs/console/libQFconsole.la \ $(top_builddir)/libs/gib/libQFgib.la -qwaq_curses_SOURCES=main.c qwaq-curses.c qwaq-input.c +qwaq_curses_SOURCES= \ + main.c \ + qwaq-curses.c \ + qwaq-editbuffer-bi.c \ + qwaq-input.c qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ $(PANEL_LIBS) $(CURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) qwaq_curses_LDFLAGS= diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 484618571..1e7bfa28f 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -154,9 +154,10 @@ create_progs (void) PR_Init_Cvars (); PR_Init (pr); RUA_Init (pr, 0); - Key_Progs_Init (pr); - PR_Cmds_Init (pr); - BI_Init (pr); + Key_Progs_Init (pr); // FIXME not all threads + PR_Cmds_Init (pr); // FIXME not all threads + BI_Init (pr); // FIXME not all threads + QWAQ_EditBuffer_Init (pr); // FIXME not all threads return pr; } diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/qwaq-editbuffer-bi.c new file mode 100644 index 000000000..d8ec63969 --- /dev/null +++ b/ruamoko/qwaq/qwaq-editbuffer-bi.c @@ -0,0 +1,908 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "QF/progs.h" +#include "QF/quakeio.h" +#include "QF/txtbuffer.h" + +#include "qwaq.h" +#include "qwaq-editbuffer.h" + +#define always_inline inline __attribute__((__always_inline__)) + +typedef struct editbuffer_s { + void *freenext; // for PR_RESMAP + txtbuffer_t *txtbuffer; + int modified; + int tabSize; +} editbuffer_t; + +typedef struct qwaq_ebresources_s { + progs_t *pr; + PR_RESMAP (editbuffer_t) buffers; +} qwaq_ebresources_t; + +static editbuffer_t * +editbuffer_new (qwaq_ebresources_t *res) +{ + PR_RESNEW (editbuffer_t, res->buffers); +} + +static void +editbuffer_free (qwaq_ebresources_t *res, editbuffer_t *buffer) +{ + PR_RESFREE (editbuffer_t, res->buffers, buffer); +} + +static void +editbuffer_reset (qwaq_ebresources_t *res) +{ + PR_RESRESET (editbuffer_t, res->buffers); +} + +static inline editbuffer_t * +editbuffer_get (qwaq_ebresources_t *res, unsigned index) +{ + PR_RESGET (res->buffers, index); +} + +static inline int +editbuffer_index (qwaq_ebresources_t *res, editbuffer_t *buffer) +{ + PR_RESINDEX (res->buffers, buffer); +} + +static always_inline editbuffer_t * __attribute__((pure)) +get_editbuffer (qwaq_ebresources_t *res, const char *name, int handle) +{ + editbuffer_t *buffer = editbuffer_get (res, handle); + + if (!buffer || !buffer->txtbuffer) { + PR_RunError (res->pr, "invalid edit buffer passed to %s", name + 3); + } + return buffer; +} + +static always_inline int +isword (unsigned char c) +{ + return c >= 128 || c == '_' || isalnum(c); +} + +static always_inline unsigned +spanGap (txtbuffer_t *buffer, unsigned ptr) +{ + return ptr < buffer->gapOffset ? ptr : ptr + buffer->gapSize; +} + +static always_inline char +getChar (txtbuffer_t *buffer, unsigned ptr) +{ + return buffer->text[spanGap (buffer, ptr)]; +} + +static always_inline unsigned +nextChar (txtbuffer_t *buffer, unsigned ptr) +{ + if (ptr < buffer->textSize && getChar (buffer, ptr) != '\n') { + return ptr + 1; + } + return ptr; +} + +static always_inline unsigned +prevChar (txtbuffer_t *buffer, unsigned ptr) +{ + if (ptr > 0 && getChar (buffer, ptr - 1) != '\n') { + return ptr - 1; + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +nextNonSpace (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (!isspace (c) || c == '\n') { + break; + } + ptr++; + } + return ptr; +} + +static always_inline unsigned +prevNonSpace (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (!isspace (c) || c == '\n') { + break; + } + ptr--; + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +nextWord (txtbuffer_t *buffer, unsigned ptr) +{ + if (buffer->textSize && ptr < buffer->textSize - 1) { + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (!isword (c)) { + break; + } + ptr++; + } + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (c == '\n') { + return ptr; + } + if (isword (c)) { + break; + } + ptr++; + } + } + return ptr; +} + +static always_inline unsigned +prevWord (txtbuffer_t *buffer, unsigned ptr) +{ + if (ptr > 0) { + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (!isword (c)) { + break; + } + ptr--; + } + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (c == '\n') { + return ptr; + } + if (isword (c)) { + break; + } + ptr--; + } + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +nextLine (txtbuffer_t *buffer, unsigned ptr) +{ + unsigned oldptr = ptr; + while (ptr < buffer->textSize && getChar (buffer, ptr++) != '\n') { + } + if (ptr == buffer->textSize && ptr > 0 + && getChar (buffer, ptr - 1) != '\n') { + return oldptr; + } + return ptr; +} + +static always_inline unsigned +prevLine (txtbuffer_t *buffer, unsigned ptr) +{ + if (ptr) { + ptr--; + while (ptr > 0 && getChar (buffer, ptr - 1) != '\n') { + ptr--; + } + } + return ptr; +} + +static always_inline unsigned +charPos (txtbuffer_t *buffer, unsigned ptr, unsigned target, int tabSize) +{ + unsigned pos = 0; + + while (ptr < target) { + if (getChar (buffer, ptr) == '\t') { + pos += tabSize - (pos % tabSize) - 1; // -1 for ++ + } + pos++; + ptr++; + } + return pos; +} + +static always_inline unsigned __attribute__((pure)) +charPtr (txtbuffer_t *buffer, unsigned ptr, unsigned target, int tabSize) +{ + unsigned pos = 0; + while (pos < target && ptr < buffer->textSize + && getChar (buffer, ptr) != '\n') { + if (getChar (buffer, ptr) == '\t') { + pos += tabSize - (pos % tabSize) - 1; // -1 for ++ + } + pos++; + ptr++; + } + if (pos > target) { + ptr--; + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +getEOW (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (!isword (c)) { + break; + } + ptr++; + } + return ptr; +} + +static always_inline unsigned +getBOW (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (!isword (c)) { + break; + } + ptr--; + } + return ptr; +} + +static always_inline unsigned __attribute__((pure)) +getEOL (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr < buffer->textSize) { + char c = getChar (buffer, ptr); + if (c == '\n') { + break; + } + ptr++; + } + return ptr; +} + +static always_inline unsigned +getBOL (txtbuffer_t *buffer, unsigned ptr) +{ + while (ptr > 0) { + char c = getChar (buffer, ptr - 1); + if (c == '\n') { + break; + } + ptr--; + } + return ptr; +} + +static always_inline unsigned +_countLines (txtbuffer_t *buffer, unsigned start, unsigned len) +{ + unsigned count = 0; + char *ptr = buffer->text + start; + + while (len-- > 0) { + count += *ptr++ == '\n'; + } + return count; +} + +static always_inline unsigned +countLines (txtbuffer_t *buffer, unsigned start, unsigned len) +{ + if (start < buffer->gapOffset) { + if (start + len <= buffer->gapOffset) { + return _countLines (buffer, start, len); + } else { + return _countLines (buffer, start, buffer->gapOffset - start) + + _countLines (buffer, buffer->gapOffset + buffer->gapSize, + len - (buffer->gapOffset - start)); + } + } else { + return _countLines (buffer, start + buffer->gapOffset, len); + } +} + +static const char * +_search (txtbuffer_t *buffer, const char *ptr, unsigned len, + const char *str, unsigned slen, int dir, + int (*cmp)(const char *, const char *, size_t)) +{ + while (len-- > 0) { + if (*ptr == *str) { + unsigned offset = ptr - buffer->text; + if (offset > buffer->gapOffset + || offset + slen < buffer->gapOffset) { + // search does not span gap + if (cmp (ptr, str, slen) == 0) { + return ptr; + } + } else { + // search spans gap + unsigned l = buffer->gapOffset - offset; + if (cmp (ptr, str, l) == 0 + && cmp (ptr + l + buffer->gapSize, + str + l, slen - l) == 0) { + return ptr; + } + } + } else { + ptr += dir; + } + } + return 0; +} + +static int +search (txtbuffer_t *buffer, const eb_sel_t *sel, const char *str, int dir, + eb_sel_t *find, int (*cmp)(const char *, const char *, size_t)) +{ + unsigned start = sel->start; + unsigned slen = strlen (str); + unsigned end = start + sel->length - slen; + const char *found = 0; + + find->start = 0; + find->length = 0; + + if (sel->length >= slen) { + if (dir < 0) { + const char *s = buffer->text + spanGap (buffer, end); + if ((start < buffer->gapOffset && end <= buffer->gapOffset) + || start > buffer->gapOffset) { + found = _search (buffer, s, end - start, str, slen, -1, cmp); + } else { + unsigned l = end - (buffer->gapOffset + buffer->gapSize); + found = _search (buffer, s, l, str, slen, 1, cmp); + if (!found) { + s -= l + buffer->gapSize; + l = buffer->gapOffset - start; + found = _search (buffer, s, l, str, slen, 1, cmp); + } + } + } else { + const char *s = buffer->text + spanGap (buffer, start); + if ((start < buffer->gapOffset && end <= buffer->gapOffset) + || start > buffer->gapOffset) { + found = _search (buffer, s, end - start, str, slen, 1, cmp); + } else { + unsigned l = buffer->gapOffset - start; + found = _search (buffer, s, l, str, slen, 1, cmp); + if (!found) { + s += l + buffer->gapSize; + l = end - start - l; + found = _search (buffer, s, l, str, slen, 1, cmp); + } + } + } + } + if (found) { + unsigned offset = found - buffer->text; + if (offset > buffer->gapOffset) { + offset -= buffer->gapSize; + } + find->start = offset; + find->length = slen; + return 1; + } + return 0; +} + +static int +saveFile (txtbuffer_t *buffer, const char *filename) +{ + QFile *file = Qopen (filename, "wt"); + + if (file) { + unsigned offset = buffer->gapOffset + buffer->gapSize; + Qwrite (file, buffer->text, buffer->gapOffset); + Qwrite (file, buffer->text + offset, buffer->textSize - offset); + Qclose (file); + return 1; + } + return 0; +} + +static int +loadFile (txtbuffer_t *buffer, const char *filename) +{ + QFile *file = Qopen (filename, "rtz"); + char *dst; + unsigned len; + + if (file) { + len = Qfilesize (file); + // ensure buffer is empty + TextBuffer_DeleteAt (buffer, 0, buffer->textSize); + dst = TextBuffer_OpenGap (buffer, 0, len); + Qread (file, dst, len); + + buffer->textSize += len; + buffer->gapOffset += len; + buffer->gapSize -= len; + + Qclose (file); + return 1; + } + return 0; +} + +static unsigned +formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, + int *dst, unsigned length, eb_sel_t *selection, eb_color_t *colors, + int tabSize) +{ + unsigned pos = 0; + unsigned ptr = linePtr; + unsigned sels = selection->start; + unsigned sele = selection->start + selection->length; + int coln = (colors->normal & ~0xff); + int cols = (colors->selected & ~0xff); + int col; + byte c; + int count; + + while (pos < xpos && ptr < buffer->textSize) { + c = getChar (buffer, ptr); + if (c == '\n') { + break; + } + if (c == '\t') { + pos += tabSize - (pos % tabSize) - 1; // -1 for ++ + } + pos++; + ptr++; + } + col = ptr >= sels && ptr < sele ? cols : coln; + while (xpos < pos && length-- > 0) { + *dst++ = col | ' '; + } + while (length > 0) { + col = ptr >= sels && ptr < sele ? cols : coln; + c = getChar (buffer, ptr++); + if (c == '\n') { + break; + } + count = 1; + if (c == '\t') { + c = ' '; + count = tabSize - (pos % tabSize); + } + while (length-- > 0 && count-- > 0) { + *dst++ = col | c; + pos++; + } + } + col = ptr >= sels && ptr < sele ? cols : coln; + while (length-- > 0) { + *dst++ = col | ' '; + } + return ptr; +} + +//=== + +static void +bi_i_EditBuffer__init (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + txtbuffer_t *txtbuffer = TextBuffer_Create (); + editbuffer_t *buffer = editbuffer_new (res); + + buffer->txtbuffer = txtbuffer; + buffer->tabSize = 4; // FIXME + + R_INT (pr) = editbuffer_index (res, buffer); +} + +static void +bi_i_EditBuffer__initWithFile_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + const char *filename = P_GSTRING (pr, 0); + txtbuffer_t *txtbuffer = TextBuffer_Create (); + editbuffer_t *buffer = editbuffer_new (res); + + buffer->txtbuffer = txtbuffer; + buffer->tabSize = 4; // FIXME + + loadFile (buffer->txtbuffer, filename); + R_INT (pr) = editbuffer_index (res, buffer); +} + +static void +bi_i_EditBuffer__dealloc (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + + TextBuffer_Destroy (buffer->txtbuffer); + editbuffer_free (res, buffer); +} + +static void +bi_i_EditBuffer__nextChar_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = nextChar (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__prevChar_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = prevChar (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__nextNonSpace_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = nextNonSpace (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__prevNonSpace_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = prevNonSpace (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__nextWord_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = nextWord (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__prevWord_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = prevWord (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__nextLine_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = nextLine (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__prevLine_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = prevLine (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__nextLine__ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned count = P_UINT (pr, 3); + + while (count-- > 0) { + unsigned oldptr = ptr; + ptr = nextLine (buffer->txtbuffer, ptr); + if (ptr == buffer->txtbuffer->textSize && ptr > 0 + && getChar (buffer->txtbuffer, ptr - 1) != '\n') { + ptr = oldptr; + break; + } + } + R_INT (pr) = ptr; +} + +static void +bi_i_EditBuffer__prevLine__ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned count = P_UINT (pr, 3); + + while (ptr && count-- > 0) { + ptr = prevLine (buffer->txtbuffer, ptr); + } + R_INT (pr) = ptr; +} + +static void +bi_i_EditBuffer__charPos_at_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned target = P_UINT (pr, 3); + int tabSize = buffer->tabSize; + + R_INT (pr) = charPos (buffer->txtbuffer, ptr, target, tabSize); +} + +static void +bi_i_EditBuffer__charPtr_at_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned target = P_UINT (pr, 3); + int tabSize = buffer->tabSize; + + R_INT (pr) = charPtr (buffer->txtbuffer, ptr, target, tabSize); +} + +static void +bi_i_EditBuffer__getWord_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned s = getBOW (buffer->txtbuffer, ptr); + unsigned e = getEOW (buffer->txtbuffer, ptr); + + R_PACKED (pr, eb_sel_t).start = s; + R_PACKED (pr, eb_sel_t).length = e - s; +} + +static void +bi_i_EditBuffer__getLine_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + unsigned s = getBOL (buffer->txtbuffer, ptr); + unsigned e = getEOL (buffer->txtbuffer, ptr); + + R_PACKED (pr, eb_sel_t).start = s; + R_PACKED (pr, eb_sel_t).length = e - s; +} + +static void +bi_i_EditBuffer__getBOL_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = getBOL (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__getEOL_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = getEOL (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__getBOT (progs_t *pr) +{ + //qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + //int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + //editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + + R_INT (pr) = 0; +} + +static void +bi_i_EditBuffer__getEOT (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + + R_INT (pr) = buffer->txtbuffer->textSize; +} + +static void +bi_i_EditBuffer__countLines_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); + + R_INT (pr) = countLines (buffer->txtbuffer, + selection->start, selection->length); +} + +static void +bi_i_EditBuffer__search_for_direction_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); + const char *str = P_GSTRING (pr, 3); + int dir = P_INT (pr, 4); + + search (buffer->txtbuffer, selection, str, dir, &R_PACKED (pr, eb_sel_t), + strncmp); +} + +static void +bi_i_EditBuffer__isearch_for_direction_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); + const char *str = P_GSTRING (pr, 3); + int dir = P_INT (pr, 4); + + search (buffer->txtbuffer, selection, str, dir, &R_PACKED (pr, eb_sel_t), + strncasecmp); +} + +static void +bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned linePtr = P_UINT (pr, 2); + unsigned xpos = P_UINT (pr, 3); + int *dst = (int *) P_GPOINTER (pr, 4); + unsigned length = P_UINT (pr, 5); + __auto_type selection = &P_PACKED (pr, eb_sel_t, 6); + __auto_type colors = &P_PACKED (pr, eb_color_t, 7); + int tabSize = buffer->tabSize; + unsigned ptr; + + ptr = formatLine (buffer->txtbuffer, linePtr, xpos, dst, length, selection, + colors, tabSize); + R_INT (pr) = ptr; +} + +static void +bi_i_EditBuffer__modified (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + R_INT (pr) = buffer->modified; +} + +static void +bi_i_EditBuffer__textSize (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + R_INT (pr) = buffer->txtbuffer->textSize; +} + +static void +bi_i_EditBuffer__saveFile_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + const char *filename = P_GSTRING (pr, 2); + + if (saveFile (buffer->txtbuffer, filename)) { + buffer->modified = 0; + } +} + +static void +qwaq_ebresources_clear (progs_t *pr, void *data) +{ + __auto_type res = (qwaq_ebresources_t *) data; + + for (size_t i = 0; i < res->buffers._size; i++) { + editbuffer_t *buffer = editbuffer_get (res, ~i); + if (buffer->txtbuffer) { + TextBuffer_Destroy (buffer->txtbuffer); + buffer->txtbuffer = 0; + } + } + editbuffer_reset (res); +} + +static builtin_t builtins[] = { + {"_i_EditBuffer__init", bi_i_EditBuffer__init, -1}, + {"_i_EditBuffer__initWithFile_", bi_i_EditBuffer__initWithFile_, -1}, + {"_i_EditBuffer__dealloc", bi_i_EditBuffer__dealloc, -1}, + {"_i_EditBuffer__nextChar_", bi_i_EditBuffer__nextChar_, -1}, + {"_i_EditBuffer__prevChar_", bi_i_EditBuffer__prevChar_, -1}, + {"_i_EditBuffer__nextNonSpace_", bi_i_EditBuffer__nextNonSpace_, -1}, + {"_i_EditBuffer__prevNonSpace_", bi_i_EditBuffer__prevNonSpace_, -1}, + {"_i_EditBuffer__nextWord_", bi_i_EditBuffer__nextWord_, -1}, + {"_i_EditBuffer__prevWord_", bi_i_EditBuffer__prevWord_, -1}, + {"_i_EditBuffer__nextLine_", bi_i_EditBuffer__nextLine_, -1}, + {"_i_EditBuffer__prevLine_", bi_i_EditBuffer__prevLine_, -1}, + {"_i_EditBuffer__nextLine__", bi_i_EditBuffer__nextLine__, -1}, + {"_i_EditBuffer__prevLine__", bi_i_EditBuffer__prevLine__, -1}, + {"_i_EditBuffer__charPos_at_", bi_i_EditBuffer__charPos_at_, -1}, + {"_i_EditBuffer__charPtr_at_", bi_i_EditBuffer__charPtr_at_, -1}, + {"_i_EditBuffer__getWord_", bi_i_EditBuffer__getWord_, -1}, + {"_i_EditBuffer__getLine_", bi_i_EditBuffer__getLine_, -1}, + {"_i_EditBuffer__getBOL_", bi_i_EditBuffer__getBOL_, -1}, + {"_i_EditBuffer__getEOL_", bi_i_EditBuffer__getEOL_, -1}, + {"_i_EditBuffer__getBOT", bi_i_EditBuffer__getBOT, -1}, + {"_i_EditBuffer__getEOT", bi_i_EditBuffer__getEOT, -1}, + {"_i_EditBuffer__countLines_", bi_i_EditBuffer__countLines_, -1}, + {"_i_EditBuffer__search_for_direction_", + bi_i_EditBuffer__search_for_direction_, -1}, + {"_i_EditBuffer__isearch_for_direction_", + bi_i_EditBuffer__isearch_for_direction_,-1}, + {"_i_EditBuffer__formatLine_from_into_width_highlight_colors_", + bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_, -1}, + {"_i_EditBuffer__modified", bi_i_EditBuffer__modified, -1}, + {"_i_EditBuffer__textSize", bi_i_EditBuffer__textSize, -1}, + {"_i_EditBuffer__saveFile_", bi_i_EditBuffer__saveFile_, -1}, + {} +}; + +void +QWAQ_EditBuffer_Init (progs_t *pr) +{ + qwaq_ebresources_t *res = calloc (sizeof (*res), 1); + res->pr = pr; + + PR_Resources_Register (pr, "qwaq-editbuffer", res, qwaq_ebresources_clear); + PR_RegisterBuiltins (pr, builtins); +} diff --git a/ruamoko/qwaq/qwaq-editbuffer.h b/ruamoko/qwaq/qwaq-editbuffer.h new file mode 100644 index 000000000..215937a55 --- /dev/null +++ b/ruamoko/qwaq/qwaq-editbuffer.h @@ -0,0 +1,79 @@ +#ifndef __qwaq_editbuffer_h +#define __qwaq_editbuffer_h + +#ifdef __QFCC__ +#include + +//FIXME add unsigned to qfcc +#define unsigned int +#define umax 0x7fffffff +#endif//__QFCC__ + +typedef struct eb_sel_s { + unsigned start; + unsigned length; +} eb_sel_t; + +typedef struct eb_color_s { + int normal; + int selected; +} eb_color_t; + +#ifdef __QFCC__ +@interface EditBuffer : Object +{ + struct edit_buffer_s *buffer; +} +-init; +-initWithFile: (string) filename; +- (unsigned) nextChar: (unsigned) charPtr; +- (unsigned) prevChar: (unsigned) charPtr; +- (unsigned) nextNonSpace: (unsigned) charPtr; +- (unsigned) prevNonSpace: (unsigned) charPtr; +- (unsigned) nextWord: (unsigned) wordPtr; +- (unsigned) prevWord: (unsigned) wordPtr; +- (unsigned) nextLine: (unsigned) linePtr; +- (unsigned) prevLine: (unsigned) linePtr; +- (unsigned) nextLine: (unsigned) linePtr : (unsigned) count; +- (unsigned) prevLine: (unsigned) linePtr : (unsigned) count; + +- (unsigned) charPos: (unsigned) linePtr at: (unsigned) target; +- (unsigned) charPtr: (unsigned) linePtr at: (unsigned) target; + +- (eb_sel_t) getWord: (unsigned) wordPtr; +- (eb_sel_t) getLine: (unsigned) linePtr; +- (unsigned) getBOL: (unsigned) linePtr; +- (unsigned) getEOL: (unsigned) linePtr; +- (unsigned) getBOT; +- (unsigned) getEOT; + +- (unsigned) countLines: (eb_sel_t) selection; +- (eb_sel_t) search: (eb_sel_t) selection + for: (string) str + direction: (int) dir; +- (eb_sel_t) isearch: (eb_sel_t) selection + for: (string) str + direction: (int) dir; +- (unsigned) formatLine: (unsigned) linePtr + from: (unsigned) xpos + into: (int *) buf + width: (unsigned) length + highlight: (eb_sel_t) selection + colors: (eb_color_t) colors; + +- (BOOL) modified; +- (unsigned) textSize; +- (int) saveFile: (string) fileName; +@end +#else//__QFCC__ + +#include "QF/pr_obj.h" + +typedef struct qwaq_editbuffer_s { + pr_id_t isa; + pointer_t buffer; +} qwaq_editbuffer_t; + +#endif//!__QFCC__ + +#endif//__qwaq_editbuffer_h diff --git a/ruamoko/qwaq/qwaq-editbuffer.r b/ruamoko/qwaq/qwaq-editbuffer.r new file mode 100644 index 000000000..ce12a6edf --- /dev/null +++ b/ruamoko/qwaq/qwaq-editbuffer.r @@ -0,0 +1,47 @@ +#include "qwaq-editbuffer.h" + +@implementation EditBuffer +- init = #0; +- initWithFile: (string) filename = #0; +- (void) dealloc = #0; +- (unsigned) nextChar: (unsigned) charPtr = #0; +- (unsigned) prevChar: (unsigned) charPtr = #0; +- (unsigned) nextNonSpace: (unsigned) charPtr = #0; +- (unsigned) prevNonSpace: (unsigned) charPtr = #0; +- (unsigned) nextWord: (unsigned) wordPtr = #0; +- (unsigned) prevWord: (unsigned) wordPtr = #0; +- (unsigned) nextLine: (unsigned) linePtr = #0; +- (unsigned) prevLine: (unsigned) linePtr = #0; +- (unsigned) nextLine: (unsigned) linePtr : (unsigned) count = #0; +- (unsigned) prevLine: (unsigned) linePtr : (unsigned) count = #0; + +- (unsigned) charPos: (unsigned) linePtr + at: (unsigned) target = #0; +- (unsigned) charPtr: (unsigned) linePtr + at: (unsigned) target = #0; + +- (eb_sel_t) getWord: (unsigned) wordPtr = #0; +- (eb_sel_t) getLine: (unsigned) linePtr = #0; +- (unsigned) getBOL: (unsigned) linePtr = #0; +- (unsigned) getEOL: (unsigned) linePtr = #0; +- (unsigned) getBOT = #0; +- (unsigned) getEOT = #0; + +- (unsigned) countLines: (eb_sel_t) selection = #0; +- (eb_sel_t) search: (eb_sel_t) selection + for: (string) str + direction: (int) dir = #0; +- (eb_sel_t) isearch: (eb_sel_t) selection + for: (string) str + direction: (int) dir = #0; +- (unsigned) formatLine: (unsigned) linePtr + from: (unsigned) xpos + into: (int *) buf + width: (unsigned) length + highlight: (eb_sel_t) selection + colors: (eb_color_t) colors = #0; + +- (BOOL) modified = #0; +- (unsigned) textSize = #0; +- (int) saveFile: (string) fileName = #0; +@end diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 3172cd7f7..da9ec6e98 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -3,6 +3,7 @@ #include "QF/darray.h" #include "QF/progs.h" +#include "QF/sys.h" typedef struct qwaq_thread_s { pthread_t thread_id; @@ -15,6 +16,7 @@ typedef struct qwaq_thread_s { } qwaq_thread_t; void BI_Init (progs_t *pr); +void QWAQ_EditBuffer_Init (progs_t *pr); extern struct cbuf_s *qwaq_cbuf; qwaq_thread_t *create_thread (void *(*thread_func) (qwaq_thread_t *), void *); From 10adb116efd70df7d6d557daa97005c3587eb2dd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 22:03:34 +0900 Subject: [PATCH 0808/3664] [qwaq] Start working on the source view/editor Line formatting is a bit messed up, but other than non-virtual text being double-counted, things seem to be ok (view only). --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/qwaq-app.r | 54 ++++--------------------------- ruamoko/qwaq/qwaq-editbuffer-bi.c | 14 +++++--- ruamoko/qwaq/qwaq-editor.h | 24 ++++++++++++++ ruamoko/qwaq/qwaq-editor.r | 30 +++++++++++++++++ 5 files changed, 71 insertions(+), 52 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-editor.h create mode 100644 ruamoko/qwaq/qwaq-editor.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 4f8b552e2..3e803509b 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -28,6 +28,7 @@ qwaq_app_dat_src= \ qwaq-button.r \ qwaq-draw.r \ qwaq-editbuffer.r \ + qwaq-editor.r \ qwaq-garray.r \ qwaq-group.r \ qwaq-listener.r \ diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index f2834b77e..4ea23f2ae 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -1,10 +1,13 @@ int fence; + #include +#include #include "color.h" #include "qwaq-app.h" #include "qwaq-button.h" #include "qwaq-curses.h" +#include "qwaq-editor.h" #include "qwaq-group.h" #include "qwaq-listener.h" #include "qwaq-window.h" @@ -47,6 +50,7 @@ arp_end (void) objects = [[Group alloc] initWithContext: screen owner: nil]; [screen bkgd: COLOR_PAIR (1)]; + [screen scrollok: 1]; Rect r = { nil, [screen size] }; r.offset.x = r.extent.width / 4; r.offset.y = r.extent.height / 4; @@ -54,57 +58,11 @@ arp_end (void) r.extent.height /= 2; Window *w; [objects insert: w = [[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; - DrawBuffer *released = [DrawBuffer buffer: {12, 1}]; - DrawBuffer *pressed = [DrawBuffer buffer: {12, 1}]; - Button *b = [[Button alloc] initWithPos: {3, 4} releasedIcon: released - pressedIcon: pressed]; - [w addView: b]; - [released bkgd: COLOR_PAIR(3)]; - [released clear]; - [released mvaddstr: {2, 0}, "press me"]; - [pressed bkgd: COLOR_PAIR(4)]; - [pressed clear]; - [pressed mvaddstr: {1, 0}, "release me"]; - [[b onPress] addListener: self : @selector (buttonPressed:)]; - [[b onRelease] addListener: self : @selector (buttonReleased:)]; - [[b onClick] addListener: self : @selector (buttonClick:)]; - [[b onDrag] addListener: self : @selector (buttonDrag:)]; - [[b onAuto] addListener: self : @selector (buttonAuto:)]; + r = {{1, 1}, {r.extent.width - 2, r.extent.height - 2}}; + [w addView: [[Editor alloc] initWithRect: r file: "Makefile"]]; return self; } --(void) buttonPressed: (id) sender -{ - [screen mvaddstr: {2, 0}, " pressed "]; - [screen refresh]; -} - --(void) buttonReleased: (id) sender -{ - [screen mvaddstr: {2, 0}, "released "]; - [screen refresh]; -} - --(void) buttonClick: (id) sender -{ - [screen mvprintf: {2, 1}, "clicked %d", [sender click]]; - [screen refresh]; -} - --(void) buttonDrag: (id) sender -{ - [screen mvaddstr: {2, 0}, "dragged "]; - Point delta = [sender delta]; - [screen mvprintf: {15, 0}, "%3d %3d", delta.x, delta.y]; - [screen refresh]; -} - --(void) buttonAuto: (id) sender -{ - [screen mvprintf: {2, 2}, "%d", autocount++]; - [screen refresh]; -} - -run { [self draw]; diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/qwaq-editbuffer-bi.c index d8ec63969..a7cf25cc5 100644 --- a/ruamoko/qwaq/qwaq-editbuffer-bi.c +++ b/ruamoko/qwaq/qwaq-editbuffer-bi.c @@ -501,20 +501,23 @@ static void bi_i_EditBuffer__init (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); txtbuffer_t *txtbuffer = TextBuffer_Create (); editbuffer_t *buffer = editbuffer_new (res); buffer->txtbuffer = txtbuffer; buffer->tabSize = 4; // FIXME - R_INT (pr) = editbuffer_index (res, buffer); + self->buffer = editbuffer_index (res, buffer); + R_INT (pr) = PR_SetPointer (pr, self); } static void bi_i_EditBuffer__initWithFile_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); - const char *filename = P_GSTRING (pr, 0); + __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); + const char *filename = P_GSTRING (pr, 2); txtbuffer_t *txtbuffer = TextBuffer_Create (); editbuffer_t *buffer = editbuffer_new (res); @@ -522,14 +525,17 @@ bi_i_EditBuffer__initWithFile_ (progs_t *pr) buffer->tabSize = 4; // FIXME loadFile (buffer->txtbuffer, filename); - R_INT (pr) = editbuffer_index (res, buffer); + + self->buffer = editbuffer_index (res, buffer); + R_INT (pr) = PR_SetPointer (pr, self); } static void bi_i_EditBuffer__dealloc (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); - int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); + int buffer_id = self->buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); TextBuffer_Destroy (buffer->txtbuffer); diff --git a/ruamoko/qwaq/qwaq-editor.h b/ruamoko/qwaq/qwaq-editor.h new file mode 100644 index 000000000..8a9fd6e06 --- /dev/null +++ b/ruamoko/qwaq/qwaq-editor.h @@ -0,0 +1,24 @@ +#ifndef __qwaq_editor_h +#define __qwaq_editor_h + +#include "qwaq-editbuffer.h" +#include "qwaq-view.h" + +@class EditBuffer; + +@interface Editor : View +{ + EditBuffer *buffer; + DrawBuffer *linebuffer; + eb_sel_t selection; + unsigned base_index; // top left corner + unsigned line_index; // current line + unsigned char_index; // current character + unsigned old_cind; // previous character + Point cursor; + unsigned line_count; +} +-initWithRect:(Rect) rect file:(string) filename; +@end + +#endif//__qwaq_editor_h diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r new file mode 100644 index 000000000..2192ec320 --- /dev/null +++ b/ruamoko/qwaq/qwaq-editor.r @@ -0,0 +1,30 @@ +#include "color.h" +#include "qwaq-editor.h" + +@implementation Editor + +-initWithRect:(Rect) rect file:(string) filename +{ + if (!(self = [super initWithRect: rect])) { + return nil; + } + buffer = [[EditBuffer alloc] initWithFile: filename]; + line_count = [buffer countLines: {0, [buffer textSize]}]; + linebuffer = [DrawBuffer buffer: { xlen, 1 }]; + return self; +} + +-draw +{ + unsigned lind = base_index; + int *lbuf = [linebuffer buffer]; + for (int y = 0; y < ylen; y++) { + lind = [buffer formatLine:lind from:0 into:lbuf width:xlen + highlight:selection colors: {COLOR_PAIR (1), COLOR_PAIR(2)}]; + [textContext blitFromBuffer: linebuffer to: {xpos, ypos + y} + from: [linebuffer rect]]; + } + return self; +} + +@end From 869479894300512b32d33f0149b30e5116a2152d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 22:13:35 +0900 Subject: [PATCH 0809/3664] [qwaq] Fix line formatting for the simple case That is, known to be working for the simple case (no tabs, no horizontal scroll). --- ruamoko/qwaq/qwaq-editbuffer-bi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/qwaq-editbuffer-bi.c index a7cf25cc5..70bb64fa5 100644 --- a/ruamoko/qwaq/qwaq-editbuffer-bi.c +++ b/ruamoko/qwaq/qwaq-editbuffer-bi.c @@ -483,11 +483,15 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, c = ' '; count = tabSize - (pos % tabSize); } - while (length-- > 0 && count-- > 0) { + while (length > 0 && count-- > 0) { *dst++ = col | c; pos++; + length--; } } + while (c != '\n') { + c = getChar (buffer, ptr++); + } col = ptr >= sels && ptr < sele ? cols : coln; while (length-- > 0) { *dst++ = col | ' '; From 16c60655e7bafa97869660ee97d724bc86a9e5a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 22:42:56 +0900 Subject: [PATCH 0810/3664] [qwaq] Implement scrolling via mouse wheel Line formatting segs when scrolling horizontally through a tab, but... things ware working nicely. --- ruamoko/qwaq/qwaq-editor.h | 5 +++ ruamoko/qwaq/qwaq-editor.r | 68 +++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-editor.h b/ruamoko/qwaq/qwaq-editor.h index 8a9fd6e06..2a480103e 100644 --- a/ruamoko/qwaq/qwaq-editor.h +++ b/ruamoko/qwaq/qwaq-editor.h @@ -13,12 +13,17 @@ eb_sel_t selection; unsigned base_index; // top left corner unsigned line_index; // current line + unsigned x_index; // horizontal scrolling unsigned char_index; // current character unsigned old_cind; // previous character Point cursor; unsigned line_count; } -initWithRect:(Rect) rect file:(string) filename; +-scrollUp:(unsigned) count; +-scrollDown:(unsigned) count; +-scrollLeft:(unsigned) count; +-scrollRight:(unsigned) count; @end #endif//__qwaq_editor_h diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 2192ec320..629090727 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -16,10 +16,11 @@ -draw { + [super draw]; unsigned lind = base_index; int *lbuf = [linebuffer buffer]; for (int y = 0; y < ylen; y++) { - lind = [buffer formatLine:lind from:0 into:lbuf width:xlen + lind = [buffer formatLine:lind from:x_index into:lbuf width:xlen highlight:selection colors: {COLOR_PAIR (1), COLOR_PAIR(2)}]; [textContext blitFromBuffer: linebuffer to: {xpos, ypos + y} from: [linebuffer rect]]; @@ -27,4 +28,69 @@ return self; } +-handleEvent:(qwaq_event_t *) event +{ + if (event.what & qe_mouse) { + if (event.what == qe_mouseclick) { + if (event.mouse.buttons & (1 << 3)) { + [self scrollUp: 1]; + } + if (event.mouse.buttons & (1 << 4)) { + [self scrollDown: 1]; + } + if (event.mouse.buttons & (1 << 5)) { + [self scrollLeft: 1]; + } + if (event.mouse.buttons & (1 << 6)) { + [self scrollRight: 1]; + } + } + } + return self; +} + +-scrollUp:(unsigned) count +{ + if (count == 1) { + base_index = [buffer prevLine: base_index]; + } else { + base_index = [buffer prevLine: base_index :count]; + } + [self redraw]; + return self; +} + +-scrollDown:(unsigned) count +{ + if (count == 1) { + base_index = [buffer nextLine: base_index]; + } else { + base_index = [buffer nextLine: base_index :count]; + } + [self redraw]; + return self; +} + +-scrollLeft:(unsigned) count +{ + if (x_index > count) { + x_index -= count; + } else { + x_index = 0; + } + [self redraw]; + return self; +} + +-scrollRight:(unsigned) count +{ + if (1024 - x_index > count) { + x_index += count; + } else { + x_index = 1024; + } + [self redraw]; + return self; +} + @end From bde31245331faa732bfedd7a1ae77764ea27ecd5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 23:50:27 +0900 Subject: [PATCH 0811/3664] [qwaq] Fix some more formatLine cases I think this is all of them. Scrolling around in a file, including having the end of file visible in the window, seems to work well. --- ruamoko/qwaq/qwaq-curses.c | 2 +- ruamoko/qwaq/qwaq-editbuffer-bi.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 3306af584..02368edc8 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -152,7 +152,7 @@ get_window (qwaq_resources_t *res, const char *name, int handle) window_t *window = window_get (res, handle); if (!window || !window->win) { - PR_RunError (res->pr, "invalid window passed to %s", name + 3); + PR_RunError (res->pr, "invalid window passed to %s", name + 5); } return window; } diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/qwaq-editbuffer-bi.c index 70bb64fa5..2f3f560e9 100644 --- a/ruamoko/qwaq/qwaq-editbuffer-bi.c +++ b/ruamoko/qwaq/qwaq-editbuffer-bi.c @@ -469,10 +469,12 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, ptr++; } col = ptr >= sels && ptr < sele ? cols : coln; - while (xpos < pos && length-- > 0) { + while (xpos < pos && length > 0) { *dst++ = col | ' '; + length--; + xpos++; } - while (length > 0) { + while (length > 0 && ptr < buffer->textSize) { col = ptr >= sels && ptr < sele ? cols : coln; c = getChar (buffer, ptr++); if (c == '\n') { @@ -489,7 +491,7 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, length--; } } - while (c != '\n') { + while (c != '\n' && ptr < buffer->textSize) { c = getChar (buffer, ptr++); } col = ptr >= sels && ptr < sele ? cols : coln; From 1dd05a8ac966ab4318edf2101de8d7bcb2e534e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Mar 2020 23:58:58 +0900 Subject: [PATCH 0812/3664] [qwaq] Fix an uninitialized var warning --- ruamoko/qwaq/qwaq-editbuffer-bi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/qwaq-editbuffer-bi.c index 2f3f560e9..ef870e4a0 100644 --- a/ruamoko/qwaq/qwaq-editbuffer-bi.c +++ b/ruamoko/qwaq/qwaq-editbuffer-bi.c @@ -454,7 +454,7 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, int coln = (colors->normal & ~0xff); int cols = (colors->selected & ~0xff); int col; - byte c; + byte c = 0; int count; while (pos < xpos && ptr < buffer->textSize) { From 4a61ff0d35e0a51b3ec267619421374b28e83e8e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 15:15:39 +0900 Subject: [PATCH 0813/3664] [util] Switch to using sigaction for signal handling This allows for much more consistent semantics when dealing with signals. --- libs/util/sys.c | 67 ++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/libs/util/sys.c b/libs/util/sys.c index de1cb35d8..4f7076d92 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -103,6 +103,19 @@ int sys_checksum; static sys_printf_t sys_std_printf_function = Sys_StdPrintf; static sys_printf_t sys_err_printf_function = Sys_ErrPrintf; +#ifndef _WIN32 +static struct sigaction save_hup; +static struct sigaction save_quit; +static struct sigaction save_trap; +static struct sigaction save_iot; +static struct sigaction save_bus; +#endif +static struct sigaction save_int; +static struct sigaction save_ill; +static struct sigaction save_segv; +static struct sigaction save_term; +static struct sigaction save_fpe; + typedef struct shutdown_list_s { struct shutdown_list_s *next; void (*func) (void *); @@ -812,7 +825,7 @@ aiee (int sig) } static void -signal_handler (int sig) +signal_handler (int sig, siginfo_t *info, void *ucontext) { int volatile recover = 0; // volatile for longjump @@ -845,26 +858,19 @@ signal_handler (int sig) Sys_Shutdown (); } - if (recover) { + if (!recover) { #ifndef _WIN32 - signal (SIGQUIT, signal_handler); - signal (SIGTRAP, signal_handler); - signal (SIGIOT, signal_handler); - signal (SIGBUS, signal_handler); + sigaction (SIGHUP, &save_hup, 0); + sigaction (SIGQUIT, &save_quit, 0); + sigaction (SIGTRAP, &save_trap, 0); + sigaction (SIGIOT, &save_iot, 0); + sigaction (SIGBUS, &save_bus, 0); #endif - signal (SIGILL, signal_handler); - signal (SIGSEGV, signal_handler); - signal (SIGFPE, signal_handler); - } else { -#ifndef _WIN32 - signal (SIGQUIT, SIG_DFL); - signal (SIGTRAP, SIG_DFL); - signal (SIGIOT, SIG_DFL); - signal (SIGBUS, SIG_DFL); -#endif - signal (SIGILL, SIG_DFL); - signal (SIGSEGV, SIG_DFL); - signal (SIGFPE, SIG_DFL); + sigaction (SIGINT, &save_int, 0); + sigaction (SIGILL, &save_ill, 0); + sigaction (SIGSEGV, &save_segv, 0); + sigaction (SIGTERM, &save_term, 0); + sigaction (SIGFPE, &save_fpe, 0); } } } @@ -873,18 +879,21 @@ VISIBLE void Sys_Init (void) { // catch signals + struct sigaction action = {}; + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = signal_handler; #ifndef _WIN32 - signal (SIGHUP, signal_handler); - signal (SIGQUIT, signal_handler); - signal (SIGTRAP, signal_handler); - signal (SIGIOT, signal_handler); - signal (SIGBUS, signal_handler); + sigaction (SIGHUP, &action, &save_hup); + sigaction (SIGQUIT, &action, &save_quit); + sigaction (SIGTRAP, &action, &save_trap); + sigaction (SIGIOT, &action, &save_iot); + sigaction (SIGBUS, &action, &save_bus); #endif - signal (SIGINT, signal_handler); - signal (SIGILL, signal_handler); - signal (SIGSEGV, signal_handler); - signal (SIGTERM, signal_handler); - signal (SIGFPE, signal_handler); + sigaction (SIGINT, &action, &save_int); + sigaction (SIGILL, &action, &save_ill); + sigaction (SIGSEGV, &action, &save_segv); + sigaction (SIGTERM, &action, &save_term); + sigaction (SIGFPE, &action, &save_fpe); Cvar_Init_Hash (); Cmd_Init_Hash (); From a9c6974fc73f135c3061e0ada7aadc9ba9f92cb4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 15:19:05 +0900 Subject: [PATCH 0814/3664] [audio] Quieten jack about xruns They messages are annoying at the moment, but I will want them when I get around to chasing down the root cause, so hidden behind a developer mask. --- libs/audio/renderer/snd_jack.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/audio/renderer/snd_jack.c b/libs/audio/renderer/snd_jack.c index 36c5d0e6a..f37ef3dc8 100644 --- a/libs/audio/renderer/snd_jack.c +++ b/libs/audio/renderer/snd_jack.c @@ -306,7 +306,9 @@ snd_jack_error (const char *desc) static int snd_jack_xrun (void *arg) { - fprintf (stderr, "snd_jack: xrun\n"); + if (developer->int_val & SYS_SND) { + fprintf (stderr, "snd_jack: xrun\n"); + } return 0; } From eb386826d3e27cf2d537c01acf9d626133d77bfd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 15:27:42 +0900 Subject: [PATCH 0815/3664] [util] Fix some missed signal calls *sigh* --- libs/util/sys.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/libs/util/sys.c b/libs/util/sys.c index 4f7076d92..7e09b4f91 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -817,18 +817,22 @@ Sys_PopSignalHook (void) } } -static void +static void __attribute__((noreturn)) aiee (int sig) { printf ("AIEE, signal %d in shutdown code, giving up\n", sig); - longjmp (aiee_abort, 1); + siglongjmp (aiee_abort, 1); } static void signal_handler (int sig, siginfo_t *info, void *ucontext) { int volatile recover = 0; // volatile for longjump + static volatile int in_signal_handler = 0; + if (in_signal_handler) { + aiee (sig); + } printf ("Received signal %d, exiting...\n", sig); switch (sig) { @@ -836,23 +840,13 @@ signal_handler (int sig, siginfo_t *info, void *ucontext) case SIGTERM: #ifndef _WIN32 case SIGHUP: - signal (SIGHUP, SIG_DFL); + sigaction (SIGHUP, &save_hup, 0); #endif - signal (SIGINT, SIG_DFL); - signal (SIGTERM, SIG_DFL); + sigaction (SIGINT, &save_int, 0); + sigaction (SIGTERM, &save_term, 0); Sys_Quit (); default: -#ifndef _WIN32 - signal (SIGQUIT, aiee); - signal (SIGTRAP, aiee); - signal (SIGIOT, aiee); - signal (SIGBUS, aiee); -#endif - signal (SIGILL, aiee); - signal (SIGSEGV, aiee); - signal (SIGFPE, aiee); - - if (!setjmp (aiee_abort)) { + if (!sigsetjmp (aiee_abort, 1)) { if (signal_hook) recover = signal_hook (sig, signal_hook_data); Sys_Shutdown (); @@ -860,16 +854,13 @@ signal_handler (int sig, siginfo_t *info, void *ucontext) if (!recover) { #ifndef _WIN32 - sigaction (SIGHUP, &save_hup, 0); sigaction (SIGQUIT, &save_quit, 0); sigaction (SIGTRAP, &save_trap, 0); sigaction (SIGIOT, &save_iot, 0); sigaction (SIGBUS, &save_bus, 0); #endif - sigaction (SIGINT, &save_int, 0); sigaction (SIGILL, &save_ill, 0); sigaction (SIGSEGV, &save_segv, 0); - sigaction (SIGTERM, &save_term, 0); sigaction (SIGFPE, &save_fpe, 0); } } From 178c8dec85414ee2744273e9b73ca96b29d2574f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 16:01:07 +0900 Subject: [PATCH 0816/3664] [console] Fix server console resize I goofed when doing the win32 fixes --- libs/console/server.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libs/console/server.c b/libs/console/server.c index 83cce7f3d..82be1cf1c 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -342,13 +342,12 @@ static void sigwinch (int sig) { interrupted = 1; - signal (SIGWINCH, sigwinch); } #endif static void get_size (int *xlen, int *ylen) { -#if 0 +#ifdef SIGWINCH struct winsize size; *xlen = *ylen = 0; @@ -356,8 +355,9 @@ get_size (int *xlen, int *ylen) return; *xlen = size.ws_col; *ylen = size.ws_row; -#endif +#else getmaxyx (stdscr, *ylen, *xlen); +#endif } static void @@ -366,10 +366,11 @@ process_input (void) int ch; int escape = 0; - if (interrupted) { -#ifdef SIGWINCH + if (__builtin_expect (interrupted, 0)) { interrupted = 0; +#ifdef SIGWINCH get_size (&screen_x, &screen_y); + Sys_MaskPrintf (SYS_DEV, "resizing to %d x %d\n", screen_x, screen_y); resizeterm (screen_y, screen_x); con_linewidth = screen_x; view_resize (sv_con_data.view, screen_x, screen_y); @@ -570,7 +571,9 @@ static void init (void) { #ifdef SIGWINCH - signal (SIGWINCH, sigwinch); + struct sigaction action = {}; + action.sa_handler = sigwinch; + sigaction (SIGWINCH, &action, 0); #endif initscr (); From 9986b57a777c83ab017a3f88141d5e6d7279628a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 16:16:50 +0900 Subject: [PATCH 0817/3664] [console] Use sig_atomic_t for SIGWINCH If it's not defined on other platforms, something can be done in config.h --- libs/console/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/console/server.c b/libs/console/server.c index 82be1cf1c..3b8cd2dd6 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -99,7 +99,7 @@ static view_t *output; static view_t *status; static view_t *input; static int screen_x, screen_y; -static int interrupted; +static volatile sig_atomic_t interrupted; static int batch_print; #define MAXCMDLINE 256 From d0c8d75e9261ef68210320c0819994610c9d31f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 16:18:08 +0900 Subject: [PATCH 0818/3664] Clean up unnecessary includes of signal.h --- libs/audio/cd_xmms.c | 3 --- qw/source/cl_sys_sdl.c | 4 ---- 2 files changed, 7 deletions(-) diff --git a/libs/audio/cd_xmms.c b/libs/audio/cd_xmms.c index 6ed35d2cf..47c8a187f 100644 --- a/libs/audio/cd_xmms.c +++ b/libs/audio/cd_xmms.c @@ -43,9 +43,6 @@ #ifdef HAVE_SYS_IOCTL_H # include #endif -#ifdef HAVE_SIGNAL_H -# include -#endif #include #include diff --git a/qw/source/cl_sys_sdl.c b/qw/source/cl_sys_sdl.c index 79357134a..3a5f1385b 100644 --- a/qw/source/cl_sys_sdl.c +++ b/qw/source/cl_sys_sdl.c @@ -50,10 +50,6 @@ # include #endif -#ifndef _WIN32 -# include -#endif - #include #include From 9bc91cd7d1ea1797aebfeb5f77dbf0fa50f36d52 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 20:14:32 +0900 Subject: [PATCH 0819/3664] [qwaq] Implement resizing Terminal resize is detected and the views adjust appropriately (well, those for which I've set grow flags: the window title bar doesn't adjust yet). --- ruamoko/qwaq/event.h | 7 ++ ruamoko/qwaq/qwaq-app.h | 2 + ruamoko/qwaq/qwaq-app.r | 21 +++++- ruamoko/qwaq/qwaq-curses.c | 130 +++++++++++++++++++++++++++++++- ruamoko/qwaq/qwaq-curses.h | 3 + ruamoko/qwaq/qwaq-draw.h | 1 + ruamoko/qwaq/qwaq-draw.r | 6 ++ ruamoko/qwaq/qwaq-editor.r | 8 ++ ruamoko/qwaq/qwaq-group.h | 1 + ruamoko/qwaq/qwaq-group.r | 8 ++ ruamoko/qwaq/qwaq-input.c | 44 +++++++++++ ruamoko/qwaq/qwaq-rect.h | 4 +- ruamoko/qwaq/qwaq-textcontext.h | 14 ++++ ruamoko/qwaq/qwaq-textcontext.r | 4 + ruamoko/qwaq/qwaq-view.h | 16 ++++ ruamoko/qwaq/qwaq-view.r | 63 ++++++++++++++++ ruamoko/qwaq/qwaq-window.r | 13 ++++ 17 files changed, 339 insertions(+), 6 deletions(-) diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index 89534f32a..0679d42dd 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -16,6 +16,7 @@ typedef enum { typedef enum { qe_command = 0x0200, // application level command qe_broadcast = 0x0400, + qe_resize = 0x0800, // screen resized } qwaq_message_event; typedef enum { @@ -46,6 +47,11 @@ typedef struct qwaq_kevent_s { int shift; } qwaq_kevent_t; +typedef struct qwaq_resize_s { + int width; + int height; +} qwaq_resize_t; + typedef struct qwaq_message_s { qwaq_command command; } qwaq_message_t; @@ -57,6 +63,7 @@ typedef struct qwaq_event_s { qwaq_kevent_t key; qwaq_mevent_t mouse; qwaq_message_t message; + qwaq_resize_t resize; }; } qwaq_event_t; diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index db341c7a3..acf63f679 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -4,6 +4,7 @@ #include #include "event.h" +#include "qwaq-rect.h" @class Group; @class TextContext; @@ -16,6 +17,7 @@ Group *objects; TextContext *screen; + Extent screenSize; int autocount; } -run; diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 4ea23f2ae..6d92e9729 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -47,11 +47,13 @@ arp_end (void) init_pair (4, COLOR_YELLOW, COLOR_RED); screen = [TextContext screen]; + screenSize = [screen size]; + printf ("screenSize = %d x %d", screenSize.width, screenSize.height); objects = [[Group alloc] initWithContext: screen owner: nil]; [screen bkgd: COLOR_PAIR (1)]; [screen scrollok: 1]; - Rect r = { nil, [screen size] }; + Rect r = {nil, screenSize}; r.offset.x = r.extent.width / 4; r.offset.y = r.extent.height / 4; r.extent.width /= 2; @@ -88,8 +90,23 @@ arp_end (void) -handleEvent: (qwaq_event_t *) event { + if (event.what == qe_resize) { + Extent delta; + delta.width = event.resize.width - screenSize.width; + delta.height = event.resize.height - screenSize.height; + + resizeterm (event.resize.width, event.resize.height); + [screen resizeTo: {event.resize.width, event.resize.height}]; + screenSize = [screen size]; + [screen printf:"resized to %d x %d, delta: %d x %d\n", event.resize.width, event.resize.height, delta.width, delta.height]; + [objects resize: delta]; + [screen refresh]; + event.what = qe_none; + return self; + } [objects handleEvent: event]; - if (event.what == qe_key && event.key.code == '\x18') { + if (event.what == qe_key + && (event.key.code == '\x18' || event.key.code == '\x11')) { event.what = qe_command; event.message.command = qc_exit; } diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 02368edc8..847c3be52 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -66,6 +66,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_bottom_panel, qwaq_cmd_move_panel, qwaq_cmd_panel_window, + qwaq_cmd_replace_panel, qwaq_cmd_update_panels, qwaq_cmd_doupdate, qwaq_cmd_mvwaddstr, @@ -81,6 +82,8 @@ typedef enum qwaq_commands_e { qwaq_cmd_curs_set, qwaq_cmd_wborder, qwaq_cmd_mvwblit_line, + qwaq_cmd_wresize, + qwaq_cmd_resizeterm, } qwaq_commands; static const char *qwaq_command_names[]= { @@ -95,6 +98,7 @@ static const char *qwaq_command_names[]= { "bottom_panel", "move_panel", "panel_window", + "replace_panel", "update_panels", "doupdate", "mvwaddstr", @@ -110,6 +114,8 @@ static const char *qwaq_command_names[]= { "curs_set", "wborder", "mvwblit_line", + "wresize", + "resizeterm", }; static window_t * @@ -398,6 +404,18 @@ cmd_panel_window (qwaq_resources_t *res) qwaq_submit_result (res, cmd_result, CMD_SIZE (cmd_result)); } +static void +cmd_replace_panel (qwaq_resources_t *res) +{ + int panel_id = RB_PEEK_DATA (res->command_queue, 2); + int window_id = RB_PEEK_DATA (res->command_queue, 3); + + panel_t *panel = get_panel (res, __FUNCTION__, panel_id); + window_t *window = get_window (res, __FUNCTION__, window_id); + + replace_panel (panel->panel, window->win); +} + static void cmd_update_panels (qwaq_resources_t *res) { @@ -561,10 +579,30 @@ cmd_mvwblit_line (qwaq_resources_t *res) release_string (res, chs_id); } +static void +cmd_wresize (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int width = RB_PEEK_DATA (res->command_queue, 3); + int height = RB_PEEK_DATA (res->command_queue, 4); + + window_t *window = get_window (res, __FUNCTION__, window_id); + wresize (window->win, height, width); +} + +static void +cmd_resizeterm (qwaq_resources_t *res) +{ + int width = RB_PEEK_DATA (res->command_queue, 2); + int height = RB_PEEK_DATA (res->command_queue, 3); + + resizeterm (height, width); +} + static void dump_command (qwaq_resources_t *res, int len) { - if (0) { + if (1) { qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); for (int i = 2; i < len; i++) { @@ -642,6 +680,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_panel_window: cmd_panel_window (res); break; + case qwaq_cmd_replace_panel: + cmd_replace_panel (res); + break; case qwaq_cmd_update_panels: cmd_update_panels (res); break; @@ -687,6 +728,12 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_mvwblit_line: cmd_mvwblit_line (res); break; + case qwaq_cmd_wresize: + cmd_wresize (res); + break; + case qwaq_cmd_resizeterm: + cmd_resizeterm (res); + break; } pthread_mutex_lock (&res->command_cond.mut); RB_DROP_DATA (res->command_queue, len); @@ -892,6 +939,22 @@ bi_panel_window (progs_t *pr) } } +static void +bi_replace_panel (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + int panel_id = P_INT (pr, 0); + int window_id = P_INT (pr, 1); + + if (get_panel (res, __FUNCTION__, panel_id) + && get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_replace_panel, 0, + panel_id, window_id}; + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} + static void qwaq_update_panels (progs_t *pr) { @@ -950,6 +1013,50 @@ bi_waddstr (progs_t *pr) qwaq_waddstr (pr, window_id, str); } +static void +qwaq_wresize (progs_t *pr, int window_id, int width, int height) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { + qwaq_cmd_wresize, 0, + window_id, width, height + }; + + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} +static void +bi_wresize (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + int width = P_INT (pr, 1); + int height = P_INT (pr, 2); + + qwaq_wresize (pr, window_id, width, height); +} + +static void +qwaq_resizeterm (progs_t *pr, int width, int height) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + int command[] = { qwaq_cmd_resizeterm, 0, width, height }; + + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); +} +static void +bi_resizeterm (progs_t *pr) +{ + int width = P_INT (pr, 0); + int height = P_INT (pr, 1); + + qwaq_resizeterm (pr, width, height); +} + static void qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str) { @@ -1572,6 +1679,19 @@ bi_i_TextContext__mvvprintf_ (progs_t *pr) qwaq_mvwvprintf (pr, pos->x, pos->y, window_id, fmt, args); } +static void +bi_i_TextContext__resizeTo_ (progs_t *pr) +{ + __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); + int window_id = self->window; + + self->size = P_PACKED (pr, Extent, 2); + qwaq_wresize (pr, window_id, self->size.width, self->size.height); + if (window_id == 1) { + qwaq_wbkgd (pr, window_id, self->background); + } +} + static void bi_c_TextContext__refresh (progs_t *pr) { @@ -1614,9 +1734,11 @@ bi_i_TextContext__mvaddstr_ (progs_t *pr) static void bi_i_TextContext__bkgd_ (progs_t *pr) { - int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); + int window_id = self->window; int ch = P_INT (pr, 2); + self->background = ch; qwaq_wbkgd (pr, window_id, ch); } @@ -1675,6 +1797,7 @@ static builtin_t builtins[] = { {"bottom_panel", bi_bottom_panel, -1}, {"move_panel", bi_move_panel, -1}, {"panel_window", bi_panel_window, -1}, + {"replace_panel", bi_replace_panel, -1}, {"update_panels", bi_update_panels, -1}, {"doupdate", bi_doupdate, -1}, {"mvwprintf", bi_mvwprintf, -1}, @@ -1698,6 +1821,8 @@ static builtin_t builtins[] = { {"curs_set", bi_curs_set, -1}, {"wborder", bi_wborder, -1}, {"mvwblit_line", bi_mvwblit_line, -1}, + {"wresize", bi_wresize, -1}, + {"resizeterm", bi_resizeterm, -1}, {"printf", bi_printf, -1}, @@ -1715,6 +1840,7 @@ static builtin_t builtins[] = { {"_i_TextContext__addch_", bi_i_TextContext__addch_, -1}, {"_i_TextContext__addstr_", bi_i_TextContext__addstr_, -1}, {"_i_TextContext__mvvprintf_", bi_i_TextContext__mvvprintf_, -1}, + {"_i_TextContext__resizeTo_", bi_i_TextContext__resizeTo_, -1}, {"_c_TextContext__refresh", bi_c_TextContext__refresh, -1}, {"_i_TextContext__refresh", bi_i_TextContext__refresh, -1}, {"_i_TextContext__mvaddch_", bi_i_TextContext__mvaddch_, -1}, diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index be87e6423..f04c0dd1a 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -109,6 +109,7 @@ typedef struct panel_s *panel_t; @extern void move_panel (panel_t panel, int x, int y); @extern window_t panel_window (panel_t panel); @extern void update_panels (void); +@extern void replace_panel (panel_t panel, window_t window); @extern void doupdate (void); @extern int get_event (qwaq_event_t *event); @@ -126,6 +127,8 @@ typedef struct panel_s *panel_t; @extern void wborder (window_t window, box_sides_t sides, box_corners_t corners); @extern void mvwblit_line (window_t window, int x, int y, int *wch, int len); +@extern void wresize (window_t window, int width, int height); +@extern void resizeterm (int width, int height); @extern Rect getwrect (struct window_s *window); diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index 65599347f..3092cc77f 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -17,6 +17,7 @@ @protocol TextContext - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; - (Extent) size; +- (void) resizeTo: (Extent) newSize; // absolute size - (void) bkgd: (int) ch; - (void) clear; diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index 757f00e90..ed1f8837a 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -25,6 +25,12 @@ return size; } +- (void) resizeTo: (Extent) newSize +{ + size = newSize; + buffer = obj_realloc (buffer, size.width * size.height); +} + - (int *) buffer { return buffer; diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 629090727..72db77115 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -11,6 +11,7 @@ buffer = [[EditBuffer alloc] initWithFile: filename]; line_count = [buffer countLines: {0, [buffer textSize]}]; linebuffer = [DrawBuffer buffer: { xlen, 1 }]; + growMode = gfGrowHi; return self; } @@ -28,6 +29,13 @@ return self; } +-resize: (Extent) delta +{ + [super resize: delta]; + [linebuffer resizeTo: {xlen, 1}]; + return self; +} + -handleEvent:(qwaq_event_t *) event { if (event.what & qe_mouse) { diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index eaa7606eb..776aa1b16 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -25,6 +25,7 @@ -(Extent) size; -draw; -redraw; +-resize: (Extent) delta; -handleEvent: (qwaq_event_t *) event; -(void) grabMouse; -(void) releaseMouse; diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 2df05bcba..bcfa7e375 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -100,6 +100,14 @@ not_dont_draw (id aView, void *aGroup) return self; } +-resize: (Extent) delta +{ + for (int i = [views count]; i-- > 0; ) { + [[views objectAtIndex: i] grow: delta]; + } + return self; +} + static View * find_mouse_view(Group *group, Point pos) { diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c index 61d3b1208..b0d0da742 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/qwaq-input.c @@ -31,9 +31,11 @@ # include "config.h" #endif +#include #include #include #include +#include #include #include #include @@ -162,6 +164,16 @@ static qwaq_key_t default_keys[] = { { "\033[1;6D", QFK_LEFT, 5 }, }; +static struct sigaction save_winch; +static sigset_t winch_mask; +static volatile sig_atomic_t winch_arrived; + +static void +handle_winch (int sig) +{ + winch_arrived = 1; +} + static void add_event (qwaq_resources_t *res, qwaq_event_t *event) { @@ -194,6 +206,20 @@ add_event (qwaq_resources_t *res, qwaq_event_t *event) pthread_mutex_unlock (&res->event_cond.mut); } +static void +resize_event (qwaq_resources_t *res) +{ + qwaq_event_t event = {}; + struct winsize size; + if (ioctl (fileno (stdout), TIOCGWINSZ, &size) != 0) { + return; + } + event.what = qe_resize; + event.resize.width = size.ws_col; + event.resize.height = size.ws_row; + add_event (res, &event); +} + static void key_event (qwaq_resources_t *res, int key, unsigned shift) { @@ -396,6 +422,13 @@ void qwaq_input_init (qwaq_resources_t *res) i++) { Hash_Add (res->key_sequences, &default_keys[i]); } + + sigemptyset (&winch_mask); + sigaddset (&winch_mask, SIGWINCH); + struct sigaction action = {}; + action.sa_handler = handle_winch; + sigaction (SIGWINCH, &action, &save_winch); + // ncurses takes care of input mode for us, so need only tell xterm // what we need write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); @@ -408,13 +441,24 @@ void qwaq_input_shutdown (qwaq_resources_t *res) // what we need write(1, SGR_OFF, sizeof (SGR_OFF) - 1); write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); + + sigaction (SIGWINCH, &save_winch, 0); } void qwaq_process_input (qwaq_resources_t *res) { char buf[256]; int len; + sigset_t save_set; + int saw_winch; + pthread_sigmask (SIG_BLOCK, &winch_mask, &save_set); + saw_winch = winch_arrived; + winch_arrived = 0; + pthread_sigmask (SIG_SETMASK, &save_set, 0); + if (saw_winch) { + resize_event (res); + } while (Sys_CheckInput (1, -1)) { len = read(0, buf, sizeof (buf)); for (int i = 0; i < len; i++) { diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index 2ab79788e..ba1e47c10 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -1,12 +1,12 @@ #ifndef __qwaq_rect_h #define __qwaq_rect_h -typedef struct { +typedef struct Point_s { int x; int y; } Point; -typedef struct { +typedef struct Extent_s { int width; int height; } Extent; diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/qwaq-textcontext.h index ce0f5ef2c..e2db46da4 100644 --- a/ruamoko/qwaq/qwaq-textcontext.h +++ b/ruamoko/qwaq/qwaq-textcontext.h @@ -58,6 +58,20 @@ typedef struct qwaq_textcontext_s { pr_id_t isa; pointer_t window; + union { + Rect rect; + struct { + Point offset; + Extent size; + }; + struct { + int xpos; + int ypos; + int xlen; + int ylen; + }; + }; + int background; } qwaq_textcontext_t; #endif diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index d2fd9144b..972bd8a99 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -111,6 +111,7 @@ static TextContext *screen; - (void) mvaddch: (Point) pos, int ch = #0; - (void) mvaddstr: (Point) pos, string str = #0; +- (void) resizeTo: (Extent) newSize = #0; // absolute size - (void) refresh = #0; + (void) refresh = #0; @@ -152,6 +153,7 @@ void top_panel (panel_t panel) = #0; void bottom_panel (panel_t panel) = #0; void move_panel (panel_t panel, int x, int y) = #0; window_t panel_window (panel_t panel) = #0; +void replace_panel (panel_t panel, window_t window) = #0; void update_panels (void) = #0; void doupdate (void) = #0; @@ -159,6 +161,8 @@ int curs_set (int visibility) = #0; int move (int x, int y) = #0; void wborder (window_t window, box_sides_t sides, box_corners_t corners) = #0; void mvwblit_line (window_t window, int x, int y, int *wch, int len) = #0; +void wresize (window_t window, int width, int height) = #0; +void resizeterm (int width, int height) = #0; Rect getwrect (window_t window) = #0; void printf(string fmt, ...) = #0; diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 2bb646653..d0b484eec 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -31,6 +31,18 @@ enum { sfLocked =0x0010, }; +enum { + gfGrowLoX = 0x0001, + gfGrowLoY = 0x0002, + gfGrowHiX = 0x0004, + gfGrowHiY = 0x0008, + gfGrowRel = 0x0010, + gfGrowLo = gfGrowLoX | gfGrowLoY, + gfGrowHi = gfGrowHiX | gfGrowHiY, + gfGrowX = gfGrowLoX | gfGrowHiX, + gfGrowY = gfGrowLoY | gfGrowHiY, + gfGrowAll = gfGrowX | gfGrowY, +}; @interface View: Object { union { @@ -52,6 +64,7 @@ enum { id textContext; int state; int options; + int growMode; int cursorState; Point cursor; } @@ -73,6 +86,9 @@ enum { -setContext: (id) context; -draw; -redraw; +-move: (Point) delta; +-resize: (Extent) delta; +-grow: (Extent) delta; -handleEvent: (qwaq_event_t *) event; - (void) onMouseEnter: (Point) pos; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 936a83352..c9177b221 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -165,6 +165,69 @@ updateScreenCursor (View *view) [textContext mvaddch: pos, ch]; } +-move: (Point) delta +{ + xpos += delta.x; + ypos += delta.y; + if (xpos + xlen < 1) { + xpos = 1 - xlen; + } + if (ypos < 0) { + ypos = 0; + } + if (owner) { + Extent s = [owner size]; + if (xpos > s.width - 1) { + xpos = s.width - 1; + } + if (ypos > s.height - 1) { + ypos = s.height - 1; + } + } + return self; +} + +-resize: (Extent) delta +{ + xlen += delta.width; + ylen += delta.height; + if (xlen < 1) { + xlen = 1; + } + if (ylen < 1) { + ylen = 1; + } + return self; +} + +-grow: (Extent) delta +{ + Point dpos = {}; + Extent dsize = {}; + + if (growMode & gfGrowLoX) { + dpos.x += delta.width; + dsize.width -= delta.width; + } + if (growMode & gfGrowHiX) { + dsize.width += delta.width; + } + if (growMode & gfGrowLoY) { + dpos.y += delta.height; + dsize.height -= delta.height; + } + if (growMode & gfGrowHiY) { + dsize.height += delta.height; + } + int save_state = state; + state &= ~sfDrawn; + [self move: dpos]; + [self resize: dsize]; + state = save_state; + [self redraw]; + return self; +} + -handleEvent: (qwaq_event_t *) event { return self; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 1c772867f..d3dfd3947 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -40,6 +40,8 @@ [buf mvaddstr: {0, 0}, "XOX"]; [buf mvaddstr: {0, 1}, "OXO"]; [buf mvaddstr: {0, 2}, "XOX"]; + + growMode = gfGrowHi; return self; } @@ -71,6 +73,17 @@ return self; } +-resize: (Extent) delta +{ + Extent size = self.size; + [super resize:delta]; + delta = {self.size.width - size.width, self.size.height - size.height}; + [(id)textContext resizeTo: self.size]; + replace_panel (panel, [(id)textContext window]); + [objects resize:delta]; + return self; +} + -handleEvent: (qwaq_event_t *) event { [objects handleEvent: event]; From afda21448740963eebcbdb6ca9ce6935c3c1ec91 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 20:18:12 +0900 Subject: [PATCH 0820/3664] Adjust some whitespace --- ruamoko/qwaq/qwaq-view.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index d0b484eec..87952f039 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -11,24 +11,24 @@ @class Group; enum { - ofCanFocus =0x0001, - ofFirstClick =0x0002, - ofDontDraw =0x0004, - ofPreProcess =0x0008, - ofPostProcess =0x0010, - ofMakeFirst =0x0020, - ofTileable =0x0040, - ofCentered =0x0080, + ofCanFocus = 0x0001, + ofFirstClick = 0x0002, + ofDontDraw = 0x0004, + ofPreProcess = 0x0008, + ofPostProcess = 0x0010, + ofMakeFirst = 0x0020, + ofTileable = 0x0040, + ofCentered = 0x0080, - ofCallHasObject =0x8000, + ofCallHasObject = 0x8000, }; enum { - sfDrawn =0x0001, - sfDisabled =0x0002, - sfInFocus =0x0004, - sfModal =0x0008, - sfLocked =0x0010, + sfDrawn = 0x0001, + sfDisabled = 0x0002, + sfInFocus = 0x0004, + sfModal = 0x0008, + sfLocked = 0x0010, }; enum { From 19a4efed167d96f1c68a17279d1c7867fd0058c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 22:00:05 +0900 Subject: [PATCH 0821/3664] [qwaq] Add support for invisible buttons Useful for window controls. --- ruamoko/qwaq/qwaq-button.h | 1 + ruamoko/qwaq/qwaq-button.r | 24 +++++++++++++++++++++--- ruamoko/qwaq/qwaq-curses.c | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/qwaq-button.h b/ruamoko/qwaq/qwaq-button.h index bab624e35..c855505a9 100644 --- a/ruamoko/qwaq/qwaq-button.h +++ b/ruamoko/qwaq/qwaq-button.h @@ -22,6 +22,7 @@ } -initWithPos: (Point) pos releasedIcon: (DrawBuffer *) released pressedIcon: (DrawBuffer *) pressed; +-initWithRect: (Rect) rect; // invisible button -(ListenerGroup *) onPress; -(ListenerGroup *) onRelease; -(ListenerGroup *) onClick; diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/qwaq-button.r index ab8477a8a..1c89d2ec4 100644 --- a/ruamoko/qwaq/qwaq-button.r +++ b/ruamoko/qwaq/qwaq-button.r @@ -21,12 +21,30 @@ return self; } +-initWithRect: (Rect) rect +{ + if (!(self = [super initWithRect: rect])) { + return nil; + } + icon[0] = nil; + icon[1] = nil; + onPress = [[ListenerGroup alloc] init]; + onRelease = [[ListenerGroup alloc] init]; + onClick = [[ListenerGroup alloc] init]; + onDrag = [[ListenerGroup alloc] init]; + onAuto = [[ListenerGroup alloc] init]; + onHover = [[ListenerGroup alloc] init]; + return self; +} + -draw { [super draw]; - [textContext blitFromBuffer: icon[pressed] - to: pos - from: [icon[pressed] rect]]; + if (icon[pressed]) { + [textContext blitFromBuffer: icon[pressed] + to: pos + from: [icon[pressed] rect]]; + } return self; } diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 847c3be52..453ff72bf 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -602,7 +602,7 @@ cmd_resizeterm (qwaq_resources_t *res) static void dump_command (qwaq_resources_t *res, int len) { - if (1) { + if (0) { qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); for (int i = 2; i < len; i++) { From 731a123b79b513877a94a6700cf068767ed319b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 22:01:13 +0900 Subject: [PATCH 0822/3664] [qwaq] Add a title bar The title bar is special in that it is always centered at the top of its owner, thus it takes no rect. --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/qwaq-titlebar.h | 16 ++++++++++++++ ruamoko/qwaq/qwaq-titlebar.r | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 ruamoko/qwaq/qwaq-titlebar.h create mode 100644 ruamoko/qwaq/qwaq-titlebar.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 3e803509b..194c31933 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -35,6 +35,7 @@ qwaq_app_dat_src= \ qwaq-rect.r \ qwaq-screen.r \ qwaq-textcontext.r \ + qwaq-titlebar.r \ qwaq-view.r \ qwaq-window.r diff --git a/ruamoko/qwaq/qwaq-titlebar.h b/ruamoko/qwaq/qwaq-titlebar.h new file mode 100644 index 000000000..addfdde4e --- /dev/null +++ b/ruamoko/qwaq/qwaq-titlebar.h @@ -0,0 +1,16 @@ +#ifndef __qwaq_titlebar_h +#define __qwaq_titlebar_h + +#include "qwaq-view.h" + +@interface TitleBar : View +{ + string title; + int length; +} +// title always centered at top of owner +-initWithTitle:(string) title; +-setTitle:(string) newTitle; +@end + +#endif//__qwaq_titlebar_h diff --git a/ruamoko/qwaq/qwaq-titlebar.r b/ruamoko/qwaq/qwaq-titlebar.r new file mode 100644 index 000000000..3a5bcfcda --- /dev/null +++ b/ruamoko/qwaq/qwaq-titlebar.r @@ -0,0 +1,41 @@ +#include + +#include "qwaq-group.h" +#include "qwaq-titlebar.h" + +@implementation TitleBar + +-initWithTitle:(string) title +{ + if (!(self = [super init])) { + return nil; + } + self.title = title; + length = strlen (title); + growMode = gfGrowHiX; + return self; +} + +-setTitle:(string) newTitle +{ + title = newTitle; + length = strlen (title); + [self redraw]; + return self; +} + +-setOwner: (Group *) owner +{ + [super setOwner: owner]; + size = [owner size]; + return self; +} + +-draw +{ + [super draw]; + [self mvaddstr: { (xlen - length) / 2, 0}, title]; + return self; +} + +@end From 467115429e7a7dd68264a1833b2d59b12baece40 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 22:08:30 +0900 Subject: [PATCH 0823/3664] [qwaq] Add gfGrowNone and a grow mode setter gfGrowNone is just to allow not growing with the owner to be explicitly stated. --- ruamoko/qwaq/qwaq-view.h | 2 ++ ruamoko/qwaq/qwaq-view.r | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 87952f039..7c3bf9f80 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -32,6 +32,7 @@ enum { }; enum { + gfGrowNone = 0x0000, gfGrowLoX = 0x0001, gfGrowLoY = 0x0002, gfGrowHiX = 0x0004, @@ -72,6 +73,7 @@ enum { - (void) dealloc; -setOwner: (Group *) owner; +-setGrowMode: (int) mode; -(Rect)rect; -(Point)origin; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index c9177b221..6413cbd13 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -95,6 +95,12 @@ updateScreenCursor (View *view) return self; } +-setGrowMode: (int) mode +{ + growMode = mode; + return self; +} + - (Rect) rect { return rect; From 147988095497ff3725ff68d783ce15a17039c98c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 22:10:03 +0900 Subject: [PATCH 0824/3664] [qwaq] Add window control buttons With this, windows can be resized using any of the corners or the three sides other than top (top side is move-only, otherwise moving a window without resizing would be impossible). --- ruamoko/qwaq/qwaq-button.r | 9 +++ ruamoko/qwaq/qwaq-window.h | 10 ++++ ruamoko/qwaq/qwaq-window.r | 119 +++++++++++++++++++++++++++++-------- 3 files changed, 114 insertions(+), 24 deletions(-) diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/qwaq-button.r index 1c89d2ec4..3f72d2ca8 100644 --- a/ruamoko/qwaq/qwaq-button.r +++ b/ruamoko/qwaq/qwaq-button.r @@ -138,4 +138,13 @@ return {dragPos.x - dragBase.x, dragPos.y - dragBase.y}; } +-move:(Point) delta +{ + Point pos = self.pos; + [super move:delta]; + dragBase.x += self.pos.x - pos.x; + dragBase.y += self.pos.y - pos.y; + return self; +} + @end diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 215fcc2db..716c0ccfd 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -4,6 +4,7 @@ #include "Object.h" @class Group; +@class Button; #include "qwaq-draw.h" #include "qwaq-rect.h" @@ -15,6 +16,15 @@ Group *objects; Point point; // FIXME can't be local :( DrawBuffer *buf; + + Button *topDrag; // move-only + Button *topLeftDrag; + Button *topRightDrag; + Button *leftDrag; + Button *rightDrag; + Button *bottomLeftDrag; + Button *bottomRightDrag; + Button *bottomDrag; } +windowWithRect: (Rect) rect; -setBackground: (int) ch; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index d3dfd3947..41d353ba3 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -6,6 +6,7 @@ #include "qwaq-curses.h" #include "qwaq-group.h" #include "qwaq-listener.h" +#include "qwaq-titlebar.h" #include "qwaq-window.h" #include "qwaq-view.h" @@ -27,14 +28,41 @@ objects = [[Group alloc] initWithContext: textContext owner: self]; - string titlestr = "drag me"; - DrawBuffer *title = [DrawBuffer buffer: {xlen, 1}]; - [title mvaddstr: {(xlen - strlen(titlestr)) / 2, 0}, titlestr]; + [self addView: [[TitleBar alloc] initWithTitle:"drag me"]]; - Button *b = [[Button alloc] initWithPos: {0, 0} releasedIcon: title - pressedIcon: title]; - [[b onDrag] addListener: self : @selector(dragWindow:)]; - [self addView: b]; + topDrag = [[Button alloc] initWithRect: {{1, 0}, + {xlen - 2, 1}}]; + topLeftDrag = [[Button alloc] initWithRect: {{0, 0}, + {1, 1}}]; + topRightDrag = [[Button alloc] initWithRect: {{xlen - 1, 0}, + {1, 1}}]; + leftDrag = [[Button alloc] initWithRect: {{0, 1}, + {1, ylen - 2}}]; + rightDrag = [[Button alloc] initWithRect: {{xlen - 1, 1}, + {1, ylen - 2}}]; + bottomLeftDrag = [[Button alloc] initWithRect: {{0, ylen - 1}, + {1, 1}}]; + bottomRightDrag = [[Button alloc] initWithRect: {{xlen - 1, ylen - 1}, + {1, 1}}]; + bottomDrag = [[Button alloc] initWithRect: {{1, ylen - 1}, + {xlen - 2, 1}}]; + [self addView: [topDrag setGrowMode: gfGrowHiX]]; + [self addView: [topLeftDrag setGrowMode: gfGrowNone]]; + [self addView: [topRightDrag setGrowMode: gfGrowX]]; + [self addView: [leftDrag setGrowMode: gfGrowHiY]]; + [self addView: [rightDrag setGrowMode: gfGrowX | gfGrowHiY]]; + [self addView: [bottomLeftDrag setGrowMode: gfGrowY]]; + [self addView: [bottomRightDrag setGrowMode: gfGrowAll]]; + [self addView: [bottomDrag setGrowMode: gfGrowHiX | gfGrowY]]; + + [[topDrag onDrag] addListener: self : @selector(dragWindow:)]; + [[topLeftDrag onDrag] addListener: self : @selector(dragWindow:)]; + [[topRightDrag onDrag] addListener: self : @selector(dragWindow:)]; + [[leftDrag onDrag] addListener: self : @selector(dragWindow:)]; + [[rightDrag onDrag] addListener: self : @selector(dragWindow:)]; + [[bottomLeftDrag onDrag] addListener: self : @selector(dragWindow:)]; + [[bottomRightDrag onDrag] addListener: self : @selector(dragWindow:)]; + [[bottomDrag onDrag] addListener: self : @selector(dragWindow:)]; buf = [DrawBuffer buffer: {3, 3}]; [buf mvaddstr: {0, 0}, "XOX"]; @@ -45,27 +73,56 @@ return self; } +#ifndef max +# define max(a,b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef min +# define min(a,b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef bound +# define bound(a,b,c) (max(a, min(b, c))) +#endif + - (void) dragWindow: (Button *) sender { Point delta = [sender delta]; - Point p = {xpos + delta.x, ypos + delta.y}; + Point dp = nil; + Point ds = nil; Extent bounds = [owner size]; - if (p.x < 0) { - p.x = 0; + + if (sender == topDrag) { + dp.x = bound (0, xpos + delta.x, bounds.width - xlen) - xpos; + dp.y = bound (0, ypos + delta.y, bounds.height - ylen) - ypos; + } else if (sender == topLeftDrag) { + dp.x = bound (0, xpos + delta.x, xpos + xlen - 1) - xpos; + dp.y = bound (0, ypos + delta.y, ypos + ylen - 1) - ypos; + ds.x = bound (1, xlen - delta.x, bounds.width - xpos) - xlen; + ds.y = bound (1, ylen - delta.y, bounds.width - ypos) - ylen; + } else if (sender == topRightDrag) { + dp.y = bound (0, ypos + delta.y, ypos + ylen - 1) - ypos; + ds.x = bound (1, xlen + delta.x, bounds.width - xpos) - xlen; + ds.y = bound (1, ylen - delta.y, bounds.width - ypos) - ylen; + } else if (sender == leftDrag) { + dp.x = bound (0, xpos + delta.x, xpos + xlen - 1) - xpos; + ds.x = bound (1, xlen - delta.x, bounds.width - xpos) - xlen; + } else if (sender == rightDrag) { + ds.x = bound (1, xlen + delta.x, bounds.width - xpos) - xlen; + } else if (sender == bottomLeftDrag) { + dp.x = bound (0, xpos + delta.x, xpos + xlen - 1) - xpos; + ds.x = bound (1, xlen - delta.x, bounds.width - xpos) - xlen; + ds.y = bound (1, ylen + delta.y, bounds.width - ypos) - ylen; + } else if (sender == bottomRightDrag) { + ds.x = bound (1, xlen + delta.x, bounds.width - xpos) - xlen; + ds.y = bound (1, ylen + delta.y, bounds.width - ypos) - ylen; + } else if (sender == bottomDrag) { + ds.y = bound (1, ylen + delta.y, bounds.width - ypos) - ylen; } - if (p.x + xlen > bounds.width) { - p.x = bounds.width - xlen; - } - if (p.y < 0) { - p.y = 0; - } - if (p.y + ylen > bounds.height) { - p.y = bounds.height - ylen; - } - xpos = p.x; - ypos = p.y; - move_panel (panel, p.x, p.y); - [owner redraw]; + int save_state = state; + state &= ~sfDrawn; + [self move: dp]; + [self resize: {ds.x, ds.y}]; + state = save_state; + [self redraw]; } -setContext: (id) context @@ -73,6 +130,17 @@ return self; } +-move: (Point) delta +{ + int save_state = state; + state &= ~sfDrawn; + [super move: delta]; + move_panel (panel, xpos, ypos); + state = save_state; + [self redraw]; + return self; +} + -resize: (Extent) delta { Extent size = self.size; @@ -126,7 +194,10 @@ -redraw { - return [owner redraw]; + if (state & sfDrawn) { + [owner redraw]; + } + return self; } - (void) mvprintf: (Point) pos, string fmt, ... From ba3efca8e565026b8324e1378db2e77eb64c676c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 22:27:08 +0900 Subject: [PATCH 0825/3664] [qwaq] Make the corner window controls 2x2 This makes them a little easier to grab but exposes a bug in Group handleEvent when views partially overlap. --- ruamoko/qwaq/qwaq-window.r | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 41d353ba3..b81ddcd0b 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -33,17 +33,17 @@ topDrag = [[Button alloc] initWithRect: {{1, 0}, {xlen - 2, 1}}]; topLeftDrag = [[Button alloc] initWithRect: {{0, 0}, - {1, 1}}]; - topRightDrag = [[Button alloc] initWithRect: {{xlen - 1, 0}, - {1, 1}}]; + {2, 2}}]; + topRightDrag = [[Button alloc] initWithRect: {{xlen - 2, 0}, + {2, 2}}]; leftDrag = [[Button alloc] initWithRect: {{0, 1}, {1, ylen - 2}}]; rightDrag = [[Button alloc] initWithRect: {{xlen - 1, 1}, {1, ylen - 2}}]; - bottomLeftDrag = [[Button alloc] initWithRect: {{0, ylen - 1}, - {1, 1}}]; - bottomRightDrag = [[Button alloc] initWithRect: {{xlen - 1, ylen - 1}, - {1, 1}}]; + bottomLeftDrag = [[Button alloc] initWithRect: {{0, ylen - 2}, + {2, 2}}]; + bottomRightDrag = [[Button alloc] initWithRect: {{xlen - 2, ylen - 2}, + {2, 2}}]; bottomDrag = [[Button alloc] initWithRect: {{1, ylen - 1}, {xlen - 2, 1}}]; [self addView: [topDrag setGrowMode: gfGrowHiX]]; From 8b193c6b6c5083edf4e96b195edcb127dfa74215 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 22:28:18 +0900 Subject: [PATCH 0826/3664] [qwaq] Remove some debug prints --- ruamoko/qwaq/qwaq-app.r | 2 -- 1 file changed, 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 6d92e9729..d6ad038a9 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -48,7 +48,6 @@ arp_end (void) screen = [TextContext screen]; screenSize = [screen size]; - printf ("screenSize = %d x %d", screenSize.width, screenSize.height); objects = [[Group alloc] initWithContext: screen owner: nil]; [screen bkgd: COLOR_PAIR (1)]; @@ -98,7 +97,6 @@ arp_end (void) resizeterm (event.resize.width, event.resize.height); [screen resizeTo: {event.resize.width, event.resize.height}]; screenSize = [screen size]; - [screen printf:"resized to %d x %d, delta: %d x %d\n", event.resize.width, event.resize.height, delta.width, delta.height]; [objects resize: delta]; [screen refresh]; event.what = qe_none; From 622b5f4c451845fb092a2126deed2dd990b27af4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 22:35:30 +0900 Subject: [PATCH 0827/3664] [qwaq] Fix the handling of overlapping views This even simplifies the logic for mouse enter/leave handling, a nice bonus. --- ruamoko/qwaq/qwaq-group.r | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index bcfa7e375..34d7a34a7 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -137,15 +137,11 @@ find_mouse_view(Group *group, Point pos) if (mouse_grabbed) { [mouse_grabbed handleEvent: event]; } else { - if (mouse_within && ![mouse_within containsPoint: pos]) { + View *mouse_view = find_mouse_view (self, pos); + if (mouse_within != mouse_view) { [mouse_within onMouseLeave: pos]; - mouse_within = nil; - } - if (!mouse_within) { - mouse_within = find_mouse_view (self, pos); - if (mouse_within) { - [mouse_within onMouseEnter: pos]; - } + [mouse_view onMouseEnter: pos]; + mouse_within = mouse_view; } if (mouse_within) { [mouse_within handleEvent: event]; From 52722b73c1e7abfe171db06dbadddf188e55810c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 23:03:35 +0900 Subject: [PATCH 0828/3664] [qwaq] Adjust edge window control lengths I'd forgotten them when adjusting the corner control sizes --- ruamoko/qwaq/qwaq-window.r | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index b81ddcd0b..e0f4e01a5 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -30,22 +30,22 @@ [self addView: [[TitleBar alloc] initWithTitle:"drag me"]]; - topDrag = [[Button alloc] initWithRect: {{1, 0}, - {xlen - 2, 1}}]; + topDrag = [[Button alloc] initWithRect: {{2, 0}, + {xlen - 4, 1}}]; topLeftDrag = [[Button alloc] initWithRect: {{0, 0}, {2, 2}}]; topRightDrag = [[Button alloc] initWithRect: {{xlen - 2, 0}, {2, 2}}]; - leftDrag = [[Button alloc] initWithRect: {{0, 1}, - {1, ylen - 2}}]; - rightDrag = [[Button alloc] initWithRect: {{xlen - 1, 1}, - {1, ylen - 2}}]; + leftDrag = [[Button alloc] initWithRect: {{0, 2}, + {1, ylen - 4}}]; + rightDrag = [[Button alloc] initWithRect: {{xlen - 1, 2}, + {1, ylen - 4}}]; bottomLeftDrag = [[Button alloc] initWithRect: {{0, ylen - 2}, {2, 2}}]; bottomRightDrag = [[Button alloc] initWithRect: {{xlen - 2, ylen - 2}, {2, 2}}]; - bottomDrag = [[Button alloc] initWithRect: {{1, ylen - 1}, - {xlen - 2, 1}}]; + bottomDrag = [[Button alloc] initWithRect: {{2, ylen - 1}, + {xlen - 4, 1}}]; [self addView: [topDrag setGrowMode: gfGrowHiX]]; [self addView: [topLeftDrag setGrowMode: gfGrowNone]]; [self addView: [topRightDrag setGrowMode: gfGrowX]]; From 8707ac0d5771cd6a84e0cee54dd00373ab4b00da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 23:18:02 +0900 Subject: [PATCH 0829/3664] [qwaq] Add a guard to formatLine I got really weird error (invalid panel passed to top_panel) when there was no such call, so I guess there was some memory corruption. formatLine is the only suspect, but when I put in the guard, the error wasn't reproduced (just scrolling through qwaq's makefile in a big window). --- ruamoko/qwaq/qwaq-editbuffer-bi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/qwaq-editbuffer-bi.c index ef870e4a0..1beb6eabd 100644 --- a/ruamoko/qwaq/qwaq-editbuffer-bi.c +++ b/ruamoko/qwaq/qwaq-editbuffer-bi.c @@ -456,6 +456,8 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, int col; byte c = 0; int count; + int *startdst = dst; + int startlen = length; while (pos < xpos && ptr < buffer->textSize) { c = getChar (buffer, ptr); @@ -498,6 +500,10 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, while (length-- > 0) { *dst++ = col | ' '; } + if (dst - startdst > startlen) { + Sys_Error ("formatLine wrote too much: %zd %u %d", + dst - startdst, startlen, length); + } return ptr; } From 30519e93fb50fb19ba9ba3d01ebfda1264444b97 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Mar 2020 23:59:54 +0900 Subject: [PATCH 0830/3664] [qwaq] Move mouse event offsetting to Window This way, Group doesn't need to query its owner's position. --- ruamoko/qwaq/qwaq-group.r | 12 ++---------- ruamoko/qwaq/qwaq-window.r | 4 ++++ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 34d7a34a7..fa298120e 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -127,17 +127,11 @@ find_mouse_view(Group *group, Point pos) [[views objectAtIndex:focused] handleEvent: event]; } } else if (event.what & qe_positional) { - Point origin = {}; - if (owner) { - origin = [owner origin]; - } - event.mouse.x -= origin.x; - event.mouse.y -= origin.y; - Point pos = {event.mouse.x, event.mouse.y}; if (mouse_grabbed) { [mouse_grabbed handleEvent: event]; } else { - View *mouse_view = find_mouse_view (self, pos); + Point pos = {event.mouse.x, event.mouse.y}; + View *mouse_view = find_mouse_view (self, pos); if (mouse_within != mouse_view) { [mouse_within onMouseLeave: pos]; [mouse_view onMouseEnter: pos]; @@ -147,8 +141,6 @@ find_mouse_view(Group *group, Point pos) [mouse_within handleEvent: event]; } } - event.mouse.x += origin.x; - event.mouse.y += origin.y; } else { // broadcast [views makeObjectsPerformSelector: @selector(draw) withObject: event]; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index e0f4e01a5..4af56498a 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -154,7 +154,11 @@ -handleEvent: (qwaq_event_t *) event { + event.mouse.x -= xpos; + event.mouse.y -= ypos; [objects handleEvent: event]; + event.mouse.x += xpos; + event.mouse.y += ypos; return self; } From 753d183d822c651ab8c9bae5e98abef60712530b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 13:24:55 +0900 Subject: [PATCH 0831/3664] [gamecode] Be more informative with function calls PR_EnterFunction and PR_LeaveFunction now print the entered/left/returned function when tracing. Makes debugging obj code much easier. --- libs/gamecode/pr_exec.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index a73e5a474..d69d4e8a0 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -188,6 +188,11 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) pr_type_t *dstParams[MAX_PARMS]; pointer_t paramofs = 0; + if (pr->pr_trace) { + Sys_Printf ("Entering function %s\n", + PR_GetString (pr, f->descriptor->s_name)); + } + PR_PushFrame (pr); if (f->numparms > 0) { @@ -268,12 +273,24 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) } static void -PR_LeaveFunction (progs_t *pr) +PR_LeaveFunction (progs_t *pr, int to_engine) { bfunction_t *f = pr->pr_xfunction; PR_PopFrame (pr); + if (pr->pr_trace) { + Sys_Printf ("Leaving function %s\n", + PR_GetString (pr, f->descriptor->s_name)); + if (to_engine) { + Sys_Printf ("Returning to engine\n"); + } else { + bfunction_t *rf = pr->pr_xfunction; + Sys_Printf ("Returning to function %s\n", + PR_GetString (pr, rf->descriptor->s_name)); + } + } + // restore locals from the stack pr->localstack_used -= f->locals; if (pr->localstack_used < 0) @@ -1443,7 +1460,7 @@ op_call: case OP_RETURN_V: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; - PR_LeaveFunction (pr); + PR_LeaveFunction (pr, pr->pr_depth == exitdepth); st = pr->pr_statements + pr->pr_xstatement; if (pr->pr_depth == exitdepth) { if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth) From 1d6843d7f05e503579800d575963a4f6752ff679 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 13:26:35 +0900 Subject: [PATCH 0832/3664] [gamecode] Improve watchpoint handling a little Mostly just update the old value if the condition didn't trigger. --- libs/gamecode/pr_exec.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index d69d4e8a0..397eb7bde 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1698,11 +1698,14 @@ op_call: default: PR_RunError (pr, "Bad opcode %i", st->op); } - if (watch && watch->integer_var != old_val.integer_var - && (!pr->wp_conditional - || watch->integer_var == pr->wp_val.integer_var)) - PR_RunError (pr, "watchpoint hit: %d -> %d", old_val.integer_var, - watch->integer_var); + if (watch && watch->integer_var != old_val.integer_var) { + if (!pr->wp_conditional + || watch->integer_var == pr->wp_val.integer_var) { + PR_RunError (pr, "watchpoint hit: %d -> %d", + old_val.integer_var, watch->integer_var); + } + old_val.integer_var = watch->integer_var; + } } exit_program: pr->pr_argc = 0; From 47b8f8dd6a94445a35232a37897ae4c5e2646a64 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 13:27:35 +0900 Subject: [PATCH 0833/3664] [qwaq] Remove useless protocols The HandleEvent protocols wound up being unnecessary. --- ruamoko/qwaq/event.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index 0679d42dd..1f122fc44 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -67,20 +67,4 @@ typedef struct qwaq_event_s { }; } qwaq_event_t; -#ifdef __QFCC__ // don't want C gcc to see this :) -@protocol HandleEvent --handleEvent: (struct qwaq_event_s *) event; -@end - -@protocol HandleFocusedEvent --takeFocus; --loseFocus; -@end - -@protocol HandleMouseEvent --(struct Rect_s *)getRect; -@end - -#endif - #endif//__qwaq_event_h From 77651dbcbad853a7fc4e4f57c3d64d48dc2f2a7b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 13:33:28 +0900 Subject: [PATCH 0834/3664] [qwaq] Implement focus handling Sort of works (when not segfaulting due to problem fixed in next commit). --- ruamoko/qwaq/qwaq-app.r | 5 +- ruamoko/qwaq/qwaq-editor.r | 1 + ruamoko/qwaq/qwaq-group.h | 7 +++ ruamoko/qwaq/qwaq-group.r | 115 ++++++++++++++++++++++++++++++++++++- ruamoko/qwaq/qwaq-view.h | 9 ++- ruamoko/qwaq/qwaq-view.r | 44 +++++++++++++- ruamoko/qwaq/qwaq-window.h | 4 +- ruamoko/qwaq/qwaq-window.r | 47 +++++++++++---- 8 files changed, 216 insertions(+), 16 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index d6ad038a9..5ea0db4c5 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -58,14 +58,15 @@ arp_end (void) r.extent.width /= 2; r.extent.height /= 2; Window *w; - [objects insert: w = [[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; + [objects insertSelected: w = [[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; r = {{1, 1}, {r.extent.width - 2, r.extent.height - 2}}; - [w addView: [[Editor alloc] initWithRect: r file: "Makefile"]]; + [w insertSelected: [[Editor alloc] initWithRect: r file: "Makefile"]]; return self; } -run { + [objects takeFocus]; [self draw]; do { arp_start (); diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 72db77115..32e468021 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -12,6 +12,7 @@ line_count = [buffer countLines: {0, [buffer textSize]}]; linebuffer = [DrawBuffer buffer: { xlen, 1 }]; growMode = gfGrowHi; + options = ofCanFocus; return self; } diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index 776aa1b16..3d9c53e65 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -19,6 +19,8 @@ } -initWithContext: (id) context owner: (View *) owner; -insert: (View *) view; +-insertDrawn: (View *) view; +-insertSelected: (View *) view; -remove: (View *) view; -(Rect) rect; -(Point) origin; @@ -27,6 +29,11 @@ -redraw; -resize: (Extent) delta; -handleEvent: (qwaq_event_t *) event; +-takeFocus; +-loseFocus; +-selectNext; +-selectPrev; +-selectView: (View *) view; -(void) grabMouse; -(void) releaseMouse; @end diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index fa298120e..8743e995d 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -32,16 +32,129 @@ return self; } +-insertDrawn: (View *) view +{ + [self insert: view]; + [view draw]; + return self; +} + +-insertSelected: (View *) view +{ + [self insertDrawn: view]; + [self selectView: view]; + return self; +} + -remove: (View *) view { int index = [views indexOfObject: view]; if (index != NotFound) { if (focused == index) { - focused = -1; + [self selectPrev]; + if (focused == index) { + focused = -1; + } } else if (focused > index) { focused--; } [views removeObjectAtIndex: index]; + if (mouse_within == view) { + mouse_within = nil; + } + if (mouse_grabbed == view) { + [self releaseMouse]; + } + } + return self; +} + +static int +makeFirst (Group *self, int viewIndex) +{ + View *view = [self.views objectAtIndex: viewIndex]; + + [self.views addObject: view]; + [self.views removeObjectAtIndex: viewIndex]; + return [self.views count] - 1; +} + +static int +trySetFocus (Group *self, int viewIndex) +{ + View *view = [self.views objectAtIndex:viewIndex]; + if (([view state] & (sfDrawn | sfDisabled)) == sfDrawn + && [view options] & ofCanFocus) { + if (!self.owner || [self.owner state] & sfInFocus) { + if (self.focused >= 0) { + [[self.views objectAtIndex: self.focused] loseFocus]; + } + self.focused = viewIndex; + if ([view options] & ofMakeFirst) { + self.focused = makeFirst (self, viewIndex); + } + [view takeFocus]; + } + return 1; + } + return 0; +} + +-takeFocus +{ + if (focused >= 0) { + [[views objectAtIndex:focused] takeFocus]; + } + return self; +} + +-loseFocus +{ + if (focused >= 0) { + [[views objectAtIndex:focused] loseFocus]; + } + return self; +} + +-selectNext +{ + for (int i = focused + 1; i < [views count]; i++) { + if (trySetFocus (self, i)) { + return self; + } + } + // hit end, start again at the beginning + for (int i = 0; i < focused; i++) { + if (trySetFocus (self, i)) { + return self; + } + } + // did not find another view that can be focused + return self; +} + +-selectPrev +{ + for (int i = focused - 1; i >= 0; i--) { + if (trySetFocus (self, i)) { + return self; + } + } + // hit end, start again at the beginning + for (int i = [views count] - 1; i > focused; i++) { + if (trySetFocus (self, i)) { + return self; + } + } + // did not find another view that can be focused + return self; +} + +-selectView:(View *)view +{ + int index = [views indexOfObject: view]; + if (index != NotFound) { + trySetFocus (self, index); } return self; } diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 7c3bf9f80..4dae4e20f 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -9,6 +9,7 @@ #include "qwaq-textcontext.h" @class Group; +@class ListenerGroup; enum { ofCanFocus = 0x0001, @@ -68,6 +69,8 @@ enum { int growMode; int cursorState; Point cursor; + ListenerGroup *onReceiveFocus; + ListenerGroup *onReleaseFocus; } -initWithRect: (Rect) rect; - (void) dealloc; @@ -84,6 +87,7 @@ enum { -(void) releaseMouse; -(int) options; +-(int) state; -setContext: (id) context; -draw; @@ -92,11 +96,14 @@ enum { -resize: (Extent) delta; -grow: (Extent) delta; -handleEvent: (qwaq_event_t *) event; +-takeFocus; +-loseFocus; +-(ListenerGroup *) onReceiveFocus; +-(ListenerGroup *) onReleaseFocus; - (void) onMouseEnter: (Point) pos; - (void) onMouseLeave: (Point) pos; - - (void) refresh; - (void) mvprintf: (Point) pos, string fmt, ...; - (void) mvvprintf: (Point) pos, string fmt, @va_list args; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 6413cbd13..574678284 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -1,4 +1,5 @@ #include "qwaq-curses.h" +#include "qwaq-listener.h" #include "qwaq-view.h" #include "qwaq-group.h" @@ -6,7 +7,12 @@ -init { - return [super init]; + if (!(self = [super init])) { + return nil; + } + onReceiveFocus = [[ListenerGroup alloc] init]; + onReleaseFocus = [[ListenerGroup alloc] init]; + return self; } -initWithRect: (Rect) rect @@ -16,6 +22,8 @@ } self.rect = rect; self.absRect = rect; + onReceiveFocus = [[ListenerGroup alloc] init]; + onReleaseFocus = [[ListenerGroup alloc] init]; return self; } @@ -38,6 +46,11 @@ return options; } +- (int) state +{ + return state; +} + static void updateScreenCursor (View *view) { @@ -236,9 +249,38 @@ updateScreenCursor (View *view) -handleEvent: (qwaq_event_t *) event { + if (event.what & (qe_mousedown | qe_mouseclick) + && options & ofCanFocus && !(state & (sfDisabled | sfInFocus))) { + [owner selectView: self]; + if (!(options & ofFirstClick)) { + event.what = qe_none; + } + } return self; } +-takeFocus +{ + state |= sfInFocus; + return self; +} + +-loseFocus +{ + state &= ~sfInFocus; + return self; +} + +-(ListenerGroup *) onReceiveFocus +{ + return onReceiveFocus; +} + +-(ListenerGroup *) onReleaseFocus +{ + return onReleaseFocus; +} + - (void) onMouseEnter: (Point) pos { } diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 716c0ccfd..1e5598856 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -28,7 +28,9 @@ } +windowWithRect: (Rect) rect; -setBackground: (int) ch; --addView: (View *) view; +-insert: (View *) view; +-insertDrawn: (View *) view; +-insertSelected: (View *) view; @end #endif//__qwaq_window_h diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 4af56498a..f69729ac7 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -28,7 +28,7 @@ objects = [[Group alloc] initWithContext: textContext owner: self]; - [self addView: [[TitleBar alloc] initWithTitle:"drag me"]]; + [self insert: [[TitleBar alloc] initWithTitle:"drag me"]]; topDrag = [[Button alloc] initWithRect: {{2, 0}, {xlen - 4, 1}}]; @@ -46,14 +46,14 @@ {2, 2}}]; bottomDrag = [[Button alloc] initWithRect: {{2, ylen - 1}, {xlen - 4, 1}}]; - [self addView: [topDrag setGrowMode: gfGrowHiX]]; - [self addView: [topLeftDrag setGrowMode: gfGrowNone]]; - [self addView: [topRightDrag setGrowMode: gfGrowX]]; - [self addView: [leftDrag setGrowMode: gfGrowHiY]]; - [self addView: [rightDrag setGrowMode: gfGrowX | gfGrowHiY]]; - [self addView: [bottomLeftDrag setGrowMode: gfGrowY]]; - [self addView: [bottomRightDrag setGrowMode: gfGrowAll]]; - [self addView: [bottomDrag setGrowMode: gfGrowHiX | gfGrowY]]; + [self insert: [topDrag setGrowMode: gfGrowHiX]]; + [self insert: [topLeftDrag setGrowMode: gfGrowNone]]; + [self insert: [topRightDrag setGrowMode: gfGrowX]]; + [self insert: [leftDrag setGrowMode: gfGrowHiY]]; + [self insert: [rightDrag setGrowMode: gfGrowX | gfGrowHiY]]; + [self insert: [bottomLeftDrag setGrowMode: gfGrowY]]; + [self insert: [bottomRightDrag setGrowMode: gfGrowAll]]; + [self insert: [bottomDrag setGrowMode: gfGrowHiX | gfGrowY]]; [[topDrag onDrag] addListener: self : @selector(dragWindow:)]; [[topLeftDrag onDrag] addListener: self : @selector(dragWindow:)]; @@ -70,6 +70,7 @@ [buf mvaddstr: {0, 2}, "XOX"]; growMode = gfGrowHi; + options = ofCanFocus | ofMakeFirst; return self; } @@ -162,12 +163,38 @@ return self; } --addView: (View *) view +-takeFocus +{ + [super takeFocus]; + [objects takeFocus]; + return self; +} + +-loseFocus +{ + [super loseFocus]; + [objects loseFocus]; + return self; +} + +-insert: (View *) view { [objects insert: view]; return self; } +-insertDrawn: (View *) view +{ + [objects insertDrawn: view]; + return self; +} + +-insertSelected: (View *) view +{ + [objects insertSelected: view]; + return self; +} + -setBackground: (int) ch { [(id)textContext bkgd: ch]; From d022c6c4bd611528371209c610331ba6dc98151f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 13:34:45 +0900 Subject: [PATCH 0835/3664] [qwaq] Disable updateScreenCursor It's wrong for the current hierarchy and corrupts the view's owning group. Thought is needed for how to proceed with cursor handling. --- ruamoko/qwaq/qwaq-view.r | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 574678284..76a6fd532 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -54,7 +54,8 @@ static void updateScreenCursor (View *view) { - while ((view.state & sfInFocus) && view.owner) { + // XXX this does not work +/* while ((view.state & sfInFocus) && view.owner) { View *owner = (View *) view.owner; if (view.cursor.x >= 0 && view.cursor.x < view.xlen && view.cursor.y >= 0 && view.cursor.y < view.ylen) { @@ -74,7 +75,7 @@ updateScreenCursor (View *view) } else { curs_set (0); } - } + }*/ } -draw From a75eeb6955acf16eb7a48471c26bc370f0144c02 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 13:36:54 +0900 Subject: [PATCH 0836/3664] [qwaq] Remove unnecessary options flag I don't think it will be necessary. --- ruamoko/qwaq/qwaq-view.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 4dae4e20f..4d4456451 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -20,8 +20,6 @@ enum { ofMakeFirst = 0x0020, ofTileable = 0x0040, ofCentered = 0x0080, - - ofCallHasObject = 0x8000, }; enum { From 995074269baa4bd2e996780a49d3634f85232028 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 13:38:20 +0900 Subject: [PATCH 0837/3664] [qwaq] Handle some keys in the editor Doesn't work yet, though. --- ruamoko/qwaq/qwaq-app.r | 2 +- ruamoko/qwaq/qwaq-editor.r | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 5ea0db4c5..04c9a95ed 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -103,7 +103,6 @@ arp_end (void) event.what = qe_none; return self; } - [objects handleEvent: event]; if (event.what == qe_key && (event.key.code == '\x18' || event.key.code == '\x11')) { event.what = qe_command; @@ -114,6 +113,7 @@ arp_end (void) || event.message.command == qc_error)) { endState = event.message.command; } + [objects handleEvent: event]; return self; } @end diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 32e468021..9d36e27ac 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -1,3 +1,4 @@ +#include #include "color.h" #include "qwaq-editor.h" @@ -54,7 +55,17 @@ [self scrollRight: 1]; } } + } else if (event.what == qe_keydown) { + switch (event.key.code) { + case QFK_PAGEUP: + [self scrollUp: ylen]; + break; + case QFK_PAGEDOWN: + [self scrollDown: ylen]; + break; + } } + event.what = qe_none; return self; } From 148a351e9483fe4df131b48cc266343917e9cb48 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 13:46:26 +0900 Subject: [PATCH 0838/3664] [qwaq] Offset event coords only when positional This fixes pgup/pgdn not working in the editor. --- ruamoko/qwaq/qwaq-window.r | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index f69729ac7..6071130eb 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -155,11 +155,17 @@ -handleEvent: (qwaq_event_t *) event { - event.mouse.x -= xpos; - event.mouse.y -= ypos; + int offset = event.what & qe_positional; + + if (offset) { + event.mouse.x -= xpos; + event.mouse.y -= ypos; + } [objects handleEvent: event]; - event.mouse.x += xpos; - event.mouse.y += ypos; + if (offset) { + event.mouse.x += xpos; + event.mouse.y += ypos; + } return self; } From 713150b41a02f7d5aa859d32be48866b78f31202 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 15:35:42 +0900 Subject: [PATCH 0839/3664] [gamecode] Add debug hooks to the VM engine While there was a breakpoint hook, it was for only breakpoints and more was needed. Now there's a generic hook that is called for tracing, breakpoints, watch points, runtime errors and VM errors, with the "event" type passed as the first parameter and a data pointer in the second. --- include/QF/progs.h | 13 ++++++++++++- libs/gamecode/pr_exec.c | 27 +++++++++++++++++++++------ libs/gamecode/pr_load.c | 6 ++++++ 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index c615e6d14..e2c077e02 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1690,6 +1690,15 @@ typedef struct { strref_t *tstr; ///< Linked list of temporary strings. } prstack_t; +typedef enum { + prd_none, + prd_trace, + prd_breakpoint, + prd_watchpoint, + prd_runerror, + prd_error, // lower level error thann prd_runerror +} prdebug_t; + struct progs_s { int (*parse_field) (progs_t *pr, const char *key, const char *value); @@ -1831,7 +1840,9 @@ struct progs_s { /// \name debugging ///@{ struct prdeb_resources_s *pr_debug_resources; - void (*breakpoint_handler) (progs_t *pr); + void (*debug_handler) (prdebug_t event, void *data); + void *debug_data; + const char *error_string; pr_type_t *watch; int wp_conditional; pr_type_t wp_val; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 397eb7bde..94018943b 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -62,6 +62,12 @@ PR_RunError (progs_t * pr, const char *error, ...) dvsprintf (string, error, argptr); va_end (argptr); + if (pr->debug_handler) { + pr->error_string = string->str; + pr->debug_handler (prd_runerror, pr->debug_data); + // not expected to return, but if so, behave as if there was no handler + } + Sys_Printf ("%s\n", string->str); PR_DumpState (pr); @@ -477,12 +483,17 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) op_b = pr->pr_globals + st->b; op_c = pr->pr_globals + st->c; - if (pr->pr_trace) - PR_PrintStatement (pr, st, 1); + if (pr->pr_trace) { + if (pr->debug_handler) { + pr->debug_handler (prd_trace, pr->debug_data); + } else { + PR_PrintStatement (pr, st, 1); + } + } if (st->op & OP_BREAK) { - if (pr->breakpoint_handler) { - pr->breakpoint_handler (pr); + if (pr->debug_handler) { + pr->debug_handler (prd_breakpoint, pr->debug_data); } else { PR_RunError (pr, "breakpoint hit"); } @@ -1701,8 +1712,12 @@ op_call: if (watch && watch->integer_var != old_val.integer_var) { if (!pr->wp_conditional || watch->integer_var == pr->wp_val.integer_var) { - PR_RunError (pr, "watchpoint hit: %d -> %d", - old_val.integer_var, watch->integer_var); + if (pr->debug_handler) { + pr->debug_handler (prd_watchpoint, pr->debug_data); + } else { + PR_RunError (pr, "watchpoint hit: %d -> %d", + old_val.integer_var, watch->integer_var); + } } old_val.integer_var = watch->integer_var; } diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index d385dff12..2bae32dfe 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -323,6 +323,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) def->type_encoding = xdef->type; } } + pr->error_string = 0; pr->pr_trace = 0; pr->pr_trace_depth = 0; pr->pr_xfunction = 0; @@ -485,5 +486,10 @@ PR_Error (progs_t *pr, const char *error, ...) dvsprintf (string, error, argptr); va_end (argptr); + if (pr->debug_handler) { + pr->error_string = string->str; + pr->debug_handler (prd_error, pr->debug_data); + // not expected to return, but if so, behave as if there was no handler + } Sys_Error ("%s: %s", pr->progs_name, string->str); } From d867a1a9f10c697ef619082ef74bc7ac70383723 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 19:45:39 +0900 Subject: [PATCH 0840/3664] [gamecode] Allow watch-point to be updated With the watch-point address cached in a local var, it was not possible to update the watch-point while the progs were executing. --- libs/gamecode/pr_exec.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 94018943b..0441e9b83 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -448,7 +448,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) dstatement_t *st; edict_t *ed; pr_type_t *ptr; - pr_type_t old_val = {0}, *watch = 0; + pr_type_t old_val = {0}; // make a stack frame exitdepth = pr->pr_depth; @@ -464,8 +464,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) st = pr->pr_statements + pr->pr_xstatement; if (pr->watch) { - watch = pr->watch; - old_val = *watch; + old_val = pr->watch; } while (1) { @@ -1709,9 +1708,9 @@ op_call: default: PR_RunError (pr, "Bad opcode %i", st->op); } - if (watch && watch->integer_var != old_val.integer_var) { + if (pr->watch && pr->watch->integer_var != old_val.integer_var) { if (!pr->wp_conditional - || watch->integer_var == pr->wp_val.integer_var) { + || pr->watch->integer_var == pr->wp_val.integer_var) { if (pr->debug_handler) { pr->debug_handler (prd_watchpoint, pr->debug_data); } else { From baff8913458db08c8f3c95160281fa08b3f6b935 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 19:48:20 +0900 Subject: [PATCH 0841/3664] [qwaq] Rename cond_t to rwcond_t --- ruamoko/qwaq/qwaq-curses.c | 2 +- ruamoko/qwaq/qwaq-curses.h | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 453ff72bf..9473a1e20 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1863,7 +1863,7 @@ qwaq_print (const char *fmt, va_list args) } static void -qwaq_init_cond (cond_t *cond) +qwaq_init_cond (rwcond_t *cond) { pthread_cond_init (&cond->rcond, 0); pthread_cond_init (&cond->wcond, 0); diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index f04c0dd1a..50f8ce762 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -157,11 +157,11 @@ typedef struct panel_s { int window_id; } panel_t; -typedef struct cond_s { +typedef struct rwcond_s { pthread_cond_t rcond; pthread_cond_t wcond; pthread_mutex_t mut; -} cond_t; +} rwcond_t; typedef enum { esc_ground, @@ -178,13 +178,13 @@ typedef struct qwaq_resources_s { window_t stdscr; PR_RESMAP (window_t) window_map; PR_RESMAP (panel_t) panel_map; - cond_t event_cond; + rwcond_t event_cond; RING_BUFFER (qwaq_event_t, QUEUE_SIZE) event_queue; - cond_t command_cond; + rwcond_t command_cond; RING_BUFFER (int, COMMAND_QUEUE_SIZE) command_queue; - cond_t results_cond; + rwcond_t results_cond; RING_BUFFER (int, COMMAND_QUEUE_SIZE) results; - cond_t string_id_cond; + rwcond_t string_id_cond; RING_BUFFER (int, STRING_ID_QUEUE_SIZE) string_ids; dstring_t strings[STRING_ID_QUEUE_SIZE - 1]; From 60f9f4815ad293f15fdbbc642e15802d5d28f72f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 19:48:57 +0900 Subject: [PATCH 0842/3664] [qwaq] Make qwaq_cond_init public --- ruamoko/qwaq/qwaq-curses.c | 2 +- ruamoko/qwaq/qwaq-curses.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 9473a1e20..360c68bec 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1862,7 +1862,7 @@ qwaq_print (const char *fmt, va_list args) fflush (logfile); } -static void +void qwaq_init_cond (rwcond_t *cond) { pthread_cond_init (&cond->rcond, 0); diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 50f8ce762..738f6befe 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -202,6 +202,7 @@ void qwaq_input_init (qwaq_resources_t *res); void qwaq_input_shutdown (qwaq_resources_t *res); void qwaq_process_input (qwaq_resources_t *res); void qwaq_init_timeout (struct timespec *timeout, long time); +void qwaq_init_cond (rwcond_t *cond); #endif #endif//__qwaq_curses_h From 0bbef18786fcc84ba700055fbbbdac0340765f0a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 19:50:05 +0900 Subject: [PATCH 0843/3664] [qwaq] Make qwaq_add_event public --- ruamoko/qwaq/qwaq-curses.h | 1 + ruamoko/qwaq/qwaq-input.c | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 738f6befe..111ada434 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -202,6 +202,7 @@ void qwaq_input_init (qwaq_resources_t *res); void qwaq_input_shutdown (qwaq_resources_t *res); void qwaq_process_input (qwaq_resources_t *res); void qwaq_init_timeout (struct timespec *timeout, long time); +int qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event); void qwaq_init_cond (rwcond_t *cond); #endif diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c index b0d0da742..ba7dca6e9 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/qwaq-input.c @@ -174,8 +174,8 @@ handle_winch (int sig) winch_arrived = 1; } -static void -add_event (qwaq_resources_t *res, qwaq_event_t *event) +int +qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event) { struct timespec timeout; int merged = 0; @@ -192,7 +192,7 @@ add_event (qwaq_resources_t *res, qwaq_event_t *event) } pthread_mutex_unlock (&res->event_cond.mut); if (merged) { - return; + return 0; } pthread_mutex_lock (&res->event_cond.mut); @@ -204,6 +204,7 @@ add_event (qwaq_resources_t *res, qwaq_event_t *event) RB_WRITE_DATA (res->event_queue, event, 1); pthread_cond_broadcast (&res->event_cond.rcond); pthread_mutex_unlock (&res->event_cond.mut); + return ret; } static void @@ -217,7 +218,7 @@ resize_event (qwaq_resources_t *res) event.what = qe_resize; event.resize.width = size.ws_col; event.resize.height = size.ws_row; - add_event (res, &event); + qwaq_add_event (res, &event); } static void @@ -228,7 +229,7 @@ key_event (qwaq_resources_t *res, int key, unsigned shift) event.when = Sys_DoubleTime (); event.key.code = key; event.key.shift = shift; - add_event (res, &event); + qwaq_add_event (res, &event); } static void @@ -254,7 +255,7 @@ mouse_event (qwaq_resources_t *res, int what, int x, int y) // scroll button event, so always single click event.mouse.click = 1; } - add_event (res, &event); + qwaq_add_event (res, &event); } static void From e56d00f27fbd76b14a71869c2a5d83e19fdeaa58 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 19:51:01 +0900 Subject: [PATCH 0844/3664] [qwaq] Make qwaq_message_t more useful Couldn't use @param because of its use in gcc as well as qfcc. --- ruamoko/qwaq/event.h | 16 +++++++++++++--- ruamoko/qwaq/qwaq-app.r | 8 ++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/event.h index 1f122fc44..d11fd195e 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/event.h @@ -23,7 +23,7 @@ typedef enum { qe_none = 0x0000, qe_mouse = 0x001f, qe_key = 0x0020, - qe_system = 0x01c0, + qe_system = 0x01c0, //FIXME this isn't very manageable qe_message = 0xfe00, qe_focused = qe_key | qe_command, @@ -52,8 +52,18 @@ typedef struct qwaq_resize_s { int height; } qwaq_resize_t; -typedef struct qwaq_message_s { - qwaq_command command; +typedef union qwaq_message_s { + int int_val; + float float_val; + float vector_val[4]; // vector and quaternion + double double_val; +#ifdef __QFCC__ + void *pointer_val; + string string_val; +#else + pointer_t pointer_val; + string_t string_val; +#endif } qwaq_message_t; typedef struct qwaq_event_s { diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 04c9a95ed..4d46e53e6 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -106,12 +106,12 @@ arp_end (void) if (event.what == qe_key && (event.key.code == '\x18' || event.key.code == '\x11')) { event.what = qe_command; - event.message.command = qc_exit; + event.message.int_val = qc_exit; } if (event.what == qe_command - && (event.message.command == qc_exit - || event.message.command == qc_error)) { - endState = event.message.command; + && (event.message.int_val == qc_exit + || event.message.int_val == qc_error)) { + endState = event.message.int_val;; } [objects handleEvent: event]; return self; From 12f7b52fff8dab33fd0d2316f659ac38d2e01942 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 19:52:35 +0900 Subject: [PATCH 0845/3664] [qwaq] Add initial qwaq debugger system It's not hooked up yet, and only very basic functionality is implemented, but I think this approach will work. --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/qwaq-debug.c | 321 +++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-debug.h | 31 ++++ ruamoko/qwaq/qwaq-editbuffer.h | 3 + 4 files changed, 356 insertions(+) create mode 100644 ruamoko/qwaq/qwaq-debug.c create mode 100644 ruamoko/qwaq/qwaq-debug.h diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 194c31933..182ed2565 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -47,6 +47,7 @@ qwaq_curses_libs= \ qwaq_curses_SOURCES= \ main.c \ qwaq-curses.c \ + qwaq-debug.c \ qwaq-editbuffer-bi.c \ qwaq-input.c qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ diff --git a/ruamoko/qwaq/qwaq-debug.c b/ruamoko/qwaq/qwaq-debug.c new file mode 100644 index 000000000..8edcf992d --- /dev/null +++ b/ruamoko/qwaq/qwaq-debug.c @@ -0,0 +1,321 @@ +/* + qwaq-debug.c + + Debugging support + + Copyright (C) 2020 Bill Currie + + Author: Bill Currie + Date: 2020/03/24 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/keys.h" +#include "QF/sys.h" + +#include "qwaq.h" +#include "event.h" +#include "qwaq-curses.h" +#include "qwaq-debug.h" + +typedef struct qwaq_target_s { + progs_t *pr; + struct qwaq_debug_s *debugger; + int handle; + prdebug_t event; + rwcond_t run_cond; +} qwaq_target_t; + +typedef struct qwaq_debug_s { + progs_t *pr; + qwaq_resources_t *qwaq; // to communicate with the debugger thread + PR_RESMAP (qwaq_target_t) targets; +} qwaq_debug_t; + +#define always_inline inline __attribute__((__always_inline__)) + +static qwaq_target_t * +target_new (qwaq_debug_t *debug) +{ + PR_RESNEW (qwaq_target_t, debug->targets); +} + +static void +target_free (qwaq_debug_t *debug, qwaq_target_t *target) +{ + PR_RESFREE (qwaq_target_t, debug->targets, target); +} + +static void +target_reset (qwaq_debug_t *debug) +{ + PR_RESRESET (qwaq_target_t, debug->targets); +} + +static inline qwaq_target_t * +target_get (qwaq_debug_t *debug, unsigned index) +{ + PR_RESGET (debug->targets, index); +} + +static inline int +target_index (qwaq_debug_t *debug, qwaq_target_t *target) +{ + PR_RESINDEX (debug->targets, target); +} + +static always_inline qwaq_target_t * __attribute__((pure)) +get_target (qwaq_debug_t *debug, const char *name, int handle) +{ + qwaq_target_t *target = target_get (debug, handle); + + if (!target || !target->debugger) { + PR_RunError (debug->pr, "invalid target passed to %s", name + 4); + } + return target; +} + +static void +qwaq_debug_handler (prdebug_t debug_event, void *data) +{ + __auto_type target = (qwaq_target_t *) data; + qwaq_debug_t *debug = target->debugger; + qwaq_event_t event = {}; + int ret; + + target->event = debug_event; + event.what = qe_debug_event; + event.message.pointer_val = target->handle; + + while ((ret = qwaq_add_event (debug->qwaq, &event)) == ETIMEDOUT) { + // spin + } + if (ret == EINVAL) { + Sys_Error ("event queue broke"); + } + pthread_mutex_lock (&target->run_cond.mut); + pthread_cond_wait (&target->run_cond.rcond, &target->run_cond.mut); + pthread_mutex_unlock (&target->run_cond.mut); + if (debug_event == prd_runerror || debug_event == prd_error) { + pthread_exit ((void *) target->pr->error_string); + } +} + +static void +qwaq_debug_clear (progs_t *pr, void *data) +{ + __auto_type debug = (qwaq_debug_t *) data; + target_reset (debug); +} + +static void +qwaq_target_clear (progs_t *pr, void *data) +{ + qwaq_target_t *target = pr->debug_data; + target_free (target->debugger, target); +} + +//FIXME need a better way to get this from one thread to the others +static qwaq_debug_t *qwaq_debug_data; + +static int +qwaq_target_load (progs_t *pr) +{ + qwaq_target_t *target = target_new (qwaq_debug_data); + target->pr = pr; + target->debugger = qwaq_debug_data; + target->handle = target_index (qwaq_debug_data, target); + qwaq_init_cond (&target->run_cond); + + pr->debug_handler = qwaq_debug_handler; + pr->debug_data = target; + + // start tracing immediately so the debugger has a chance to start up + // before the target progs begin running + pr->pr_trace = 1; + pr->pr_trace_depth = -1; + + return 1; +} + +static void +qdb_set_trace (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + int state = P_INT (pr, 1); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + + tpr->pr_trace = state; +} + +static void +qdb_set_breakpoint (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + unsigned staddr = P_INT (pr, 1); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + + if (staddr >= tpr->progs->numstatements) { + R_INT (pr) = -1; + return; + } + tpr->pr_statements[staddr].op |= OP_BREAK; + R_INT (pr) = 0; +} + +static void +qdb_clear_breakpoint (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + unsigned staddr = P_UINT (pr, 1); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + + if (staddr >= tpr->progs->numstatements) { + R_INT (pr) = -1; + return; + } + tpr->pr_statements[staddr].op &= ~OP_BREAK; + R_INT (pr) = 0; +} + +static void +qdb_set_watchpoint (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + pointer_t offset = P_UINT (pr, 1); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + + if (offset >= tpr->globals_size) { + R_INT (pr) = -1; + return; + } + tpr->watch = &tpr->pr_globals[offset]; + R_INT (pr) = 0; +} + +static void +qdb_clear_watchpoint (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + + tpr->watch = 0; + R_INT (pr) = 0; +} + +static void +qdb_continue (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + + pthread_mutex_lock (&target->run_cond.mut); + pthread_cond_signal (&target->run_cond.rcond); + pthread_mutex_unlock (&target->run_cond.mut); +} + +static void +qdb_get_state (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + pr_lineno_t *lineno; + pr_auxfunction_t *f; + string_t file = 0; + unsigned line = 0; + unsigned staddr = tpr->pr_xstatement; + func_t func = tpr->pr_xfunction - tpr->function_table; + + lineno = PR_Find_Lineno (tpr, staddr); + if (lineno) { + f = PR_Get_Lineno_Func (pr, lineno); + file = pr->pr_functions[f->function].s_file; + func = f->function; + line = PR_Get_Lineno_Line (pr, lineno); + line += f->source_line; + } + + qdb_state_t state = {}; + state.staddr = staddr; + state.func = func; + state.file = file; + state.line = line; + + R_PACKED (pr, qdb_state_t) = state; +} + +static builtin_t builtins[] = { + {"qdb_set_trace", qdb_set_trace, -1}, + {"qdb_set_breakpoint", qdb_set_breakpoint, -1}, + {"qdb_clear_breakpoint", qdb_clear_breakpoint, -1}, + {"qdb_set_watchpoint", qdb_set_watchpoint, -1}, + {"qdb_clear_watchpoint", qdb_clear_watchpoint, -1}, + {"qdb_continue", qdb_continue, -1}, + {"qdb_get_state", qdb_get_state, -1}, + {} +}; + +void +QWAQ_Debug_Init (progs_t *pr) +{ + qwaq_debug_t *debug = calloc (sizeof (*debug), 1); + qwaq_debug_data = debug; // FIXME ? see decl + debug->pr = pr; + debug->qwaq = PR_Resources_Find (pr, "qwaq"); + + PR_Resources_Register (pr, "qwaq-debug", debug, qwaq_debug_clear); + PR_RegisterBuiltins (pr, builtins); +} + +void +QWAQ_DebugTarget_Init (progs_t *pr) +{ + PR_AddLoadFunc (pr, qwaq_target_load); + PR_Resources_Register (pr, "qwaq-target", 0, qwaq_target_clear); +} diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h new file mode 100644 index 000000000..c95788951 --- /dev/null +++ b/ruamoko/qwaq/qwaq-debug.h @@ -0,0 +1,31 @@ +#ifndef __qwaq_debug_h +#define __qwaq_debug_h + +#include "event.h" + +enum { + qe_debug_event = 0x0100, +} qwaq_debug_messages; + +#ifdef __QFCC__ + +//FIXME add unsigned to qfcc +#ifndef unsigned +#define unsigned int +#define umax 0x7fffffff +#endif + +#else//GCC +#endif + +typedef struct qdb_state_s { + unsigned staddr; + unsigned func; + unsigned file; + unsigned line; +} qdb_state_t; + +void QWAQ_Debug_Init (progs_t *pr); +void QWAQ_DebugTarget_Init (progs_t *pr); + +#endif//__qwaq_debug_h diff --git a/ruamoko/qwaq/qwaq-editbuffer.h b/ruamoko/qwaq/qwaq-editbuffer.h index 215937a55..4e5062ab2 100644 --- a/ruamoko/qwaq/qwaq-editbuffer.h +++ b/ruamoko/qwaq/qwaq-editbuffer.h @@ -5,8 +5,11 @@ #include //FIXME add unsigned to qfcc +#ifndef unsigned #define unsigned int #define umax 0x7fffffff +#endif + #endif//__QFCC__ typedef struct eb_sel_s { From 32d77eabac451b03c60e7fbbf869785fbe1c92f7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 20:15:35 +0900 Subject: [PATCH 0846/3664] [qwaq] Hook up the debugger modules Now to write all the high level stuff. Wheeeee --- ruamoko/qwaq/main.c | 35 +++++++++++++++++++++++++++-------- ruamoko/qwaq/qwaq-debug.h | 2 +- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 1e7bfa28f..3972acbc3 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -53,6 +53,7 @@ #include "QF/zone.h" #include "qwaq.h" +#include "qwaq-debug.h" #define MAX_EDICTS 1024 @@ -141,8 +142,10 @@ init_qf (void) } +typedef void (*progsinit_f) (progs_t *pr); + static progs_t * -create_progs (void) +create_progs (progsinit_f *funcs) { progs_t *pr = calloc (1, sizeof (*pr)); @@ -154,10 +157,9 @@ create_progs (void) PR_Init_Cvars (); PR_Init (pr); RUA_Init (pr, 0); - Key_Progs_Init (pr); // FIXME not all threads - PR_Cmds_Init (pr); // FIXME not all threads - BI_Init (pr); // FIXME not all threads - QWAQ_EditBuffer_Init (pr); // FIXME not all threads + while (*funcs) { + (*funcs++) (pr); + } return pr; } @@ -183,7 +185,7 @@ load_progs (progs_t *pr, const char *name) } static void -spawn_progs (qwaq_thread_t *thread) +spawn_progs (qwaq_thread_t *thread, progsinit_f *funcs) { dfunction_t *dfunc; const char *name = 0; @@ -192,7 +194,7 @@ spawn_progs (qwaq_thread_t *thread) progs_t *pr; thread->main_func = 0; - pr = thread->pr = create_progs (); + pr = thread->pr = create_progs (funcs); if (thread->args.size) { name = thread->args.a[0]; } @@ -321,6 +323,20 @@ done: return qargs_ind; } +static progsinit_f main_app[] = { + Key_Progs_Init, + PR_Cmds_Init, + BI_Init, + QWAQ_EditBuffer_Init, + QWAQ_Debug_Init, + 0 +}; + +static progsinit_f target_app[] = { + QWAQ_DebugTarget_Init, + 0 +}; + int main (int argc, char **argv) { @@ -378,6 +394,8 @@ main (int argc, char **argv) for (size_t i = 1, thread_ind = 0; i < thread_data.size; i++) { qwaq_thread_t *thread = thread_data.a[i]; + progsinit_f *app_funcs = target_app; + if (thread->args.size && thread->args.a[0] && strcmp (thread->args.a[0], "--qargs")) { // skip the args set that's passed to qargs @@ -391,8 +409,9 @@ main (int argc, char **argv) } if (main_ind < 0) { main_ind = i; + app_funcs = main_app; } - spawn_progs (thread); + spawn_progs (thread, app_funcs); } if (main_ind >= 0) { // threads might start new threads before the end is reached diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h index c95788951..f54d25636 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/qwaq-debug.h @@ -3,7 +3,7 @@ #include "event.h" -enum { +typedef enum { qe_debug_event = 0x0100, } qwaq_debug_messages; From d73f380ba4c2c271e1aac4200294991dab69e74a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 21:01:48 +0900 Subject: [PATCH 0847/3664] [qwaq] Add -hide to View's interface Missed it somehow. --- ruamoko/qwaq/qwaq-view.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 4d4456451..50ca22462 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -89,6 +89,7 @@ enum { -setContext: (id) context; -draw; +-hide; -redraw; -move: (Point) delta; -resize: (Extent) delta; From 05e377c3acaa96ebeb25596d52f6b82966a87c26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 21:02:26 +0900 Subject: [PATCH 0848/3664] [qwaq] Make a View protocol --- ruamoko/qwaq/qwaq-view.h | 60 +++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 50ca22462..b8d61d1f0 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -43,36 +43,8 @@ enum { gfGrowY = gfGrowLoY | gfGrowHiY, gfGrowAll = gfGrowX | gfGrowY, }; -@interface View: Object -{ - union { - Rect rect; - struct { - int xpos; - int ypos; - int xlen; - int ylen; - }; - struct { - Point pos; - Extent size; - }; - }; - Rect absRect; - Point point; // can't be local :( - Group *owner; - id textContext; - int state; - int options; - int growMode; - int cursorState; - Point cursor; - ListenerGroup *onReceiveFocus; - ListenerGroup *onReleaseFocus; -} --initWithRect: (Rect) rect; -- (void) dealloc; +@protocol View -setOwner: (Group *) owner; -setGrowMode: (int) mode; @@ -109,6 +81,36 @@ enum { - (void) mvaddch: (Point) pos, int ch; @end +@interface View: Object +{ + union { + Rect rect; + struct { + int xpos; + int ypos; + int xlen; + int ylen; + }; + struct { + Point pos; + Extent size; + }; + }; + Rect absRect; + Point point; // can't be local :( + Group *owner; + id textContext; + int state; + int options; + int growMode; + int cursorState; + Point cursor; + ListenerGroup *onReceiveFocus; + ListenerGroup *onReleaseFocus; +} +-initWithRect: (Rect) rect; +@end + @interface View (TextContext) @end From fd0700f9ae1654c40b0434b82f45ea25776ab222 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 21:02:54 +0900 Subject: [PATCH 0849/3664] [qwaq] Add a proxy view class The idea is that the view can be switched out readily: the proxy simply passes all messages to its view object. --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/qwaq-proxyview.h | 17 ++++++++++++++++ ruamoko/qwaq/qwaq-proxyview.r | 38 +++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 ruamoko/qwaq/qwaq-proxyview.h create mode 100644 ruamoko/qwaq/qwaq-proxyview.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 182ed2565..c61fbafb7 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -32,6 +32,7 @@ qwaq_app_dat_src= \ qwaq-garray.r \ qwaq-group.r \ qwaq-listener.r \ + qwaq-proxyview.r \ qwaq-rect.r \ qwaq-screen.r \ qwaq-textcontext.r \ diff --git a/ruamoko/qwaq/qwaq-proxyview.h b/ruamoko/qwaq/qwaq-proxyview.h new file mode 100644 index 000000000..7789678fc --- /dev/null +++ b/ruamoko/qwaq/qwaq-proxyview.h @@ -0,0 +1,17 @@ +#ifndef __qwaq_proxyview_h +#define __qwaq_proxyview_h + +#include "qwaq-view.h" + +@interface ProxyView : Object +{ + View *view; +} +-initWithView:(View *) view; +-setView: (View *) view; +@end + +@interface ProxyView (View) +@end + +#endif//__qwaq_proxyview_h diff --git a/ruamoko/qwaq/qwaq-proxyview.r b/ruamoko/qwaq/qwaq-proxyview.r new file mode 100644 index 000000000..a29b1dedd --- /dev/null +++ b/ruamoko/qwaq/qwaq-proxyview.r @@ -0,0 +1,38 @@ +#include "qwaq-proxyview.h" + +@implementation ProxyView +- (void) forward: (SEL) sel : (@va_list) args +{ + if (!view) { + return; + } + obj_msg_sendv (view, sel, args); +} + +-initWithView:(View *) view +{ + if (!(self = [super init])) { + return nil; + } + self.view = view; + return self; +} + +-setView:(View *) view +{ + int state = [self.view state]; + if (state & sfInFocus) { + [self.view loseFocus]; + [self.view hide]; + } + + self.view = view; + if (state & sfDrawn) { + [view draw]; + } + if (state & sfInFocus) { + [view takeFocus]; + } + return self; +} +@end From 9bfd14b687c6782f35bda14ceec115bbb51878d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 23:02:19 +0900 Subject: [PATCH 0850/3664] [qwaq] Bring in qc gcd to use for debugger testing It was even recent enough to compile first try. --- ruamoko/qwaq/Makefile.am | 10 +++++++++- {tools/qfcc/test/old => ruamoko/qwaq}/gcd.r | 0 2 files changed, 9 insertions(+), 1 deletion(-) rename {tools/qfcc/test/old => ruamoko/qwaq}/gcd.r (100%) diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index c61fbafb7..3a65cfbbf 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -6,7 +6,7 @@ QWAQ_INCS=@QWAQ_INCS@ AM_CPPFLAGS= -I$(top_srcdir)/include $(QWAQ_INCS) $(PTHREAD_CFLAGS) -noinst_PROGRAMS=@QWAQ_TARGETS@ qwaq-app.dat$(EXEEXT) +noinst_PROGRAMS=@QWAQ_TARGETS@ qwaq-app.dat$(EXEEXT) gcd.dat$(EXEEXT) QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(top_builddir)/tools/qfcc/source/qfcc @@ -90,6 +90,14 @@ qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) include $(qwaq_app_dep) # am--include-marker r_depfiles_remade += $(qwaq_app_dep) +gcd_dat_SOURCES=gcd.r +gcd_obj=$(gcd_dat_SOURCES:.r=.o) +gcd_dep=$(addprefix ./$(DEPDIR)/,$(gcd_obj:.o=.Qo)) +gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) + $(QLINK) -o $@ $(gcd_obj) -lcsqc -lr +include $(gcd_dep) # am--include-marker +r_depfiles_remade += $(gcd_dep) + $(r_depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ diff --git a/tools/qfcc/test/old/gcd.r b/ruamoko/qwaq/gcd.r similarity index 100% rename from tools/qfcc/test/old/gcd.r rename to ruamoko/qwaq/gcd.r From c945c42989bfc91a3d02fe15062a60ce24e98dd6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Mar 2020 23:16:25 +0900 Subject: [PATCH 0851/3664] [gamecode] Fix some silly errors I forgot to compile-test :( --- libs/gamecode/pr_exec.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 0441e9b83..43681da79 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -292,8 +292,10 @@ PR_LeaveFunction (progs_t *pr, int to_engine) Sys_Printf ("Returning to engine\n"); } else { bfunction_t *rf = pr->pr_xfunction; - Sys_Printf ("Returning to function %s\n", - PR_GetString (pr, rf->descriptor->s_name)); + if (rf) { + Sys_Printf ("Returning to function %s\n", + PR_GetString (pr, rf->descriptor->s_name)); + } } } @@ -464,7 +466,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) st = pr->pr_statements + pr->pr_xstatement; if (pr->watch) { - old_val = pr->watch; + old_val = *pr->watch; } while (1) { @@ -1715,10 +1717,10 @@ op_call: pr->debug_handler (prd_watchpoint, pr->debug_data); } else { PR_RunError (pr, "watchpoint hit: %d -> %d", - old_val.integer_var, watch->integer_var); + old_val.integer_var, pr->watch->integer_var); } } - old_val.integer_var = watch->integer_var; + old_val.integer_var = pr->watch->integer_var; } } exit_program: From 0ad9f559ead67bdb88bf6147ebdc8d77584d174a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 00:04:20 +0900 Subject: [PATCH 0852/3664] [ruamoko] Move some string functions sprintf, vsprintf and strlen now in rua_strings, and strlen now returns int like it should. --- libs/ruamoko/pr_cmds.c | 52 --------------------------------- libs/ruamoko/rua_string.c | 45 ++++++++++++++++++++++++++++ ruamoko/cl_menu/CvarRangeView.r | 1 + ruamoko/cl_menu/controls_o.r | 1 + ruamoko/cl_menu/plistmenu.r | 1 + ruamoko/include/Makefile.am | 1 + ruamoko/include/legacy_string.h | 12 ++++++++ ruamoko/include/string.h | 10 +------ ruamoko/lib/Makefile.am | 2 +- ruamoko/lib/legacy_string.r | 9 ++++++ ruamoko/lib/string.r | 12 ++------ ruamoko/scheme/Lexer.r | 1 + ruamoko/scheme/Number.r | 1 + 13 files changed, 76 insertions(+), 72 deletions(-) create mode 100644 ruamoko/include/legacy_string.h create mode 100644 ruamoko/lib/legacy_string.r diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 9a531fb14..db99849e3 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -521,18 +521,6 @@ PF_vtos (progs_t *pr) RETURN_STRING (pr, string); } -/* - float (string s) strlen -*/ -static void -PF_strlen (progs_t *pr) -{ - const char *s; - - s = P_GSTRING (pr, 0); - R_FLOAT (pr) = strlen(s); -} - /* float (string char, string s) charcount */ @@ -565,43 +553,6 @@ PF_charcount (progs_t *pr) # define INT_WIDTH 20 #endif -#define MAX_ARG 7 -/* - string (...) sprintf -*/ -static void -PF_sprintf (progs_t *pr) -{ - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; - dstring_t *dstr; - - dstr = dstring_newstr (); - PR_Sprintf (pr, dstr, "PF_sprintf", fmt, count, args); - RETURN_STRING (pr, dstr->str); - dstring_delete (dstr); -} - -static void -PF_vsprintf (progs_t *pr) -{ - const char *fmt = P_GSTRING (pr, 0); - __auto_type args = &P_PACKED (pr, pr_va_list_t, 1); - pr_type_t *list_start = PR_GetPointer (pr, args->list); - pr_type_t **list = alloca (args->count * sizeof (*list)); - dstring_t *dstr; - - for (int i = 0; i < args->count; i++) { - list[i] = list_start + i * pr->pr_param_size; - } - - dstr = dstring_newstr (); - PR_Sprintf (pr, dstr, "PF_vsprintf", fmt, args->count, list); - RETURN_STRING (pr, dstr->str); - dstring_delete (dstr); -} - /* string () gametype */ @@ -659,10 +610,7 @@ static builtin_t builtins[] = { {"stof", PF_stof, 81}, - {"strlen", PF_strlen, QF 100}, {"charcount", PF_charcount, QF 101}, - {"sprintf", PF_sprintf, QF 109}, - {"vsprintf", PF_vsprintf, -1}, {"ftoi", PF_ftoi, QF 110}, {"itof", PF_itof, QF 111}, {"itos", PF_itos, QF 112}, diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index c96f44e57..4ec5eb2a9 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -50,6 +50,48 @@ #include "rua_internal.h" +static void +bi_strlen (progs_t *pr) +{ + const char *s; + + s = P_GSTRING (pr, 0); + R_INT (pr) = strlen(s); +} + +static void +bi_sprintf (progs_t *pr) +{ + const char *fmt = P_GSTRING (pr, 0); + int count = pr->pr_argc - 1; + pr_type_t **args = pr->pr_params + 1; + dstring_t *dstr; + + dstr = dstring_newstr (); + PR_Sprintf (pr, dstr, "bi_sprintf", fmt, count, args); + RETURN_STRING (pr, dstr->str); + dstring_delete (dstr); +} + +static void +bi_vsprintf (progs_t *pr) +{ + const char *fmt = P_GSTRING (pr, 0); + __auto_type args = &P_PACKED (pr, pr_va_list_t, 1); + pr_type_t *list_start = PR_GetPointer (pr, args->list); + pr_type_t **list = alloca (args->count * sizeof (*list)); + dstring_t *dstr; + + for (int i = 0; i < args->count; i++) { + list[i] = list_start + i * pr->pr_param_size; + } + + dstr = dstring_newstr (); + PR_Sprintf (pr, dstr, "bi_vsprintf", fmt, args->count, list); + RETURN_STRING (pr, dstr->str); + dstring_delete (dstr); +} + static void bi_str_new (progs_t *pr) { @@ -147,6 +189,9 @@ bi_str_char (progs_t *pr) } static builtin_t builtins[] = { + {"strlen", bi_strlen, -1}, + {"sprintf", bi_sprintf, -1}, + {"vsprintf", bi_vsprintf, -1}, {"str_new", bi_str_new, -1}, {"str_free", bi_str_free, -1}, {"str_copy", bi_str_copy, -1}, diff --git a/ruamoko/cl_menu/CvarRangeView.r b/ruamoko/cl_menu/CvarRangeView.r index f32d37b6d..b9980ca0a 100644 --- a/ruamoko/cl_menu/CvarRangeView.r +++ b/ruamoko/cl_menu/CvarRangeView.r @@ -1,5 +1,6 @@ #include "key.h" #include "sound.h" +#include "legacy_string.h" #include "string.h" #include "gui/Text.h" diff --git a/ruamoko/cl_menu/controls_o.r b/ruamoko/cl_menu/controls_o.r index 5c389d88e..3ae1b60c2 100644 --- a/ruamoko/cl_menu/controls_o.r +++ b/ruamoko/cl_menu/controls_o.r @@ -30,6 +30,7 @@ #include "draw.h" #include "system.h" #include "debug.h" +#include "legacy_string.h" #include "string.h" #include "key.h" #include "options_util.h" diff --git a/ruamoko/cl_menu/plistmenu.r b/ruamoko/cl_menu/plistmenu.r index 00d2a61e0..a4daadbbf 100644 --- a/ruamoko/cl_menu/plistmenu.r +++ b/ruamoko/cl_menu/plistmenu.r @@ -25,6 +25,7 @@ */ #include "debug.h" +#include "legacy_string.h" #include "string.h" #include "qfs.h" diff --git a/ruamoko/include/Makefile.am b/ruamoko/include/Makefile.am index 17167cbec..0964419bf 100644 --- a/ruamoko/include/Makefile.am +++ b/ruamoko/include/Makefile.am @@ -4,6 +4,7 @@ nobase_pkginclude_HEADERS= \ crudefile.h debug.h entities.h infokey.h math.h message.h nq_message.h \ physics.h msgbuf.h qfile.h qfs.h qw_message.h qw_physics.h qw_sys.h \ server.h sound.h script.h string.h sv_sound.h system.h types.h \ + legacy_string.h \ \ draw.h key.h \ \ diff --git a/ruamoko/include/legacy_string.h b/ruamoko/include/legacy_string.h new file mode 100644 index 000000000..34e47817a --- /dev/null +++ b/ruamoko/include/legacy_string.h @@ -0,0 +1,12 @@ +#ifndef __ruamoko_legacy_string_h +#define __ruamoko_legacy_string_h + +@extern string ftos (float f); +@extern string vtos (vector v); +@extern float stof (string s); +@extern float charcount (string goal, string s); +@extern string itos (int i); +@extern int stoi (string s); +@extern vector stov (string s); + +#endif//__ruamoko_legacy_string_h diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index 3951c94c5..7f63f573e 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -1,17 +1,9 @@ #ifndef __ruamoko_string_h #define __ruamoko_string_h -@extern string ftos (float f); -@extern string vtos (vector v); -@extern float stof (string s); -@extern float strlen (string s); -@extern float charcount (string goal, string s); +@extern int strlen (string s); @extern string sprintf (string fmt, ...); @extern string vsprintf (string fmt, @va_list args); -@extern string itos (int i); -@extern int stoi (string s); -@extern vector stov (string s); - @extern string str_new (void); @extern string str_free (string str); @extern string str_copy (string dst, string src); diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index da1157a82..49107b28f 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -46,7 +46,7 @@ libr_a_AR=$(PAK) -cf include $(libr_a_dep) # am--include-marker r_depfiles_remade += $(libr_a_dep) -common_src=debug.r system.r +common_src=debug.r system.r legacy_string.r server_src= \ crudefile.r entities.r infokey.r message.r \ physics.r server.r sv_sound.r diff --git a/ruamoko/lib/legacy_string.r b/ruamoko/lib/legacy_string.r new file mode 100644 index 000000000..258a33ade --- /dev/null +++ b/ruamoko/lib/legacy_string.r @@ -0,0 +1,9 @@ +#include + +string (float f) ftos = #26; +string (vector v) vtos = #27; +float (string s) stof = #81; +float (string goal, string s) charcount = #0x000f0000 + 101; +string (int i) itos = #0x000f0000 + 112; +int (string s) stoi = #0x000f0000 + 113; +vector (string s) stov = #0x000f0000 + 114; diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index 58f64911a..a23a6aa98 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -1,16 +1,8 @@ #include -string (float f) ftos = #26; -string (vector v) vtos = #27; -float (string s) stof = #81; -float (string s) strlen = #0x000f0000 + 100; -float (string goal, string s) charcount = #0x000f0000 + 101; -string (string fmt, ...) sprintf = #0x000f0000 + 109; +int (string s) strlen = #0; +string (string fmt, ...) sprintf = #0; string vsprintf (string fmt, @va_list args) = #0; -string (int i) itos = #0x000f0000 + 112; -int (string s) stoi = #0x000f0000 + 113; -vector (string s) stov = #0x000f0000 + 114; - string (void) str_new = #0; string (string str) str_free = #0; string (string dst, string src) str_copy = #0; diff --git a/ruamoko/scheme/Lexer.r b/ruamoko/scheme/Lexer.r index 20b026599..32d2958a5 100644 --- a/ruamoko/scheme/Lexer.r +++ b/ruamoko/scheme/Lexer.r @@ -1,5 +1,6 @@ #include "Lexer.h" #include "Number.h" +#include "legacy_string.h" #include "string.h" #include "Boolean.h" #include "Error.h" diff --git a/ruamoko/scheme/Number.r b/ruamoko/scheme/Number.r index 53e7f6975..530bcd46a 100644 --- a/ruamoko/scheme/Number.r +++ b/ruamoko/scheme/Number.r @@ -1,4 +1,5 @@ #include "Number.h" +#include "legacy_string.h" #include "string.h" @implementation Number From 48c65b3363a421724f35de75679744e8575c2ec3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 00:41:14 +0900 Subject: [PATCH 0853/3664] [qwaq] Move builtin printf to main.c and add traceon/traceoff defs (that don't need PF_Cmds). This lets gcd.dat load in the second progs thread. --- ruamoko/qwaq/main.c | 46 ++++++++++++++++++++++++++++++++++---- ruamoko/qwaq/qwaq-curses.c | 16 ------------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 3972acbc3..79a4e6f96 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -203,9 +203,6 @@ spawn_progs (qwaq_thread_t *thread, progsinit_f *funcs) Sys_Error ("couldn't load %s", name); } - //pr->pr_trace = 1; - //pr->pr_trace_depth = -1; - PR_PushFrame (pr); if (thread->args.size > 2) { pr_argc = thread->args.size - 1; @@ -323,16 +320,57 @@ done: return qargs_ind; } +static void +bi_printf (progs_t *pr) +{ + const char *fmt = P_GSTRING (pr, 0); + int count = pr->pr_argc - 1; + pr_type_t **args = pr->pr_params + 1; + dstring_t *dstr = dstring_new (); + + PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); + if (dstr->str) + Sys_Printf (dstr->str, stdout); + dstring_delete (dstr); +} + +static void +bi_traceon (progs_t *pr) +{ + pr->pr_trace = true; + pr->pr_trace_depth = pr->pr_depth; +} + +static void +bi_traceoff (progs_t *pr) +{ + pr->pr_trace = false; +} + +static builtin_t common_builtins[] = { + {"printf", bi_printf, -1}, + {"traceon", bi_traceon, -1}, + {"traceoff", bi_traceoff, -1}, + {}, +}; + +static void +common_builtins_init (progs_t *pr) +{ + PR_RegisterBuiltins (pr, common_builtins); +} + static progsinit_f main_app[] = { Key_Progs_Init, - PR_Cmds_Init, BI_Init, + common_builtins_init, QWAQ_EditBuffer_Init, QWAQ_Debug_Init, 0 }; static progsinit_f target_app[] = { + common_builtins_init, QWAQ_DebugTarget_Init, 0 }; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 360c68bec..b8f8670b5 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1544,20 +1544,6 @@ bi_initialize (progs_t *pr) create_thread (qwaq_curses_thread, res); } -static void -bi_printf (progs_t *pr) -{ - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; - dstring_t *dstr = dstring_new (); - - PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); - if (dstr->str) - Sys_Printf (dstr->str, stdout); - dstring_delete (dstr); -} - static void bi_c_TextContext__is_initialized (progs_t *pr) { @@ -1824,8 +1810,6 @@ static builtin_t builtins[] = { {"wresize", bi_wresize, -1}, {"resizeterm", bi_resizeterm, -1}, - {"printf", bi_printf, -1}, - {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, {"_c_TextContext__max_color_pairs", bi_c_TextContext__max_color_pairs, -1}, From 1e56a8efbc8d0cfdf229a1dcc4e348d15bd7c8fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 00:44:04 +0900 Subject: [PATCH 0854/3664] [qwaq] Fix a silly that caused qwaq-app to spawn twice progs_t is very much most definitely NOT thread-safe (ie, two threads using the same progs_t). It was actually rather funny when I figured out what was going on to cause qwaq's universe to explode. --- ruamoko/qwaq/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 79a4e6f96..87df0a035 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -456,7 +456,7 @@ main (int argc, char **argv) size_t count = thread_data.size; for (size_t i = 0; i < count; i++) { if (thread_data.a[i]->pr && thread_data.a[i]->main_func) { - start_progs_thread (thread_data.a[main_ind]); + start_progs_thread (thread_data.a[i]); } } pthread_join (thread_data.a[main_ind]->thread_id, 0); From e69c430abce76518f1b13a14196621585596caff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 01:06:20 +0900 Subject: [PATCH 0855/3664] [qwaq] Clean up QwaqApplication It doesn't need to be fun little tests any more. --- ruamoko/qwaq/qwaq-app.h | 6 ++-- ruamoko/qwaq/qwaq-app.r | 60 +++++++++++++++++++------------------- ruamoko/qwaq/qwaq-curses.c | 5 ++-- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index acf63f679..40681d940 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -20,9 +20,11 @@ Extent screenSize; int autocount; } +-(Extent)size; +-(TextContext *)screen; -run; --draw; --handleEvent: (qwaq_event_t *) event; @end +@extern QwaqApplication *application; + #endif//__qwaq_app_h diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 4d46e53e6..aba239607 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -5,13 +5,8 @@ int fence; #include "color.h" #include "qwaq-app.h" -#include "qwaq-button.h" #include "qwaq-curses.h" -#include "qwaq-editor.h" #include "qwaq-group.h" -#include "qwaq-listener.h" -#include "qwaq-window.h" -#include "qwaq-screen.h" #include "qwaq-view.h" static AutoreleasePool *autorelease_pool; @@ -52,33 +47,19 @@ arp_end (void) [screen bkgd: COLOR_PAIR (1)]; [screen scrollok: 1]; - Rect r = {nil, screenSize}; - r.offset.x = r.extent.width / 4; - r.offset.y = r.extent.height / 4; - r.extent.width /= 2; - r.extent.height /= 2; - Window *w; - [objects insertSelected: w = [[Window windowWithRect: r] setBackground: COLOR_PAIR (2)]]; - r = {{1, 1}, {r.extent.width - 2, r.extent.height - 2}}; - [w insertSelected: [[Editor alloc] initWithRect: r file: "Makefile"]]; + [screen clear]; + wrefresh (stdscr);//FIXME return self; } --run +-(Extent)size { - [objects takeFocus]; - [self draw]; - do { - arp_start (); + return screenSize; +} - get_event (&event); - if (event.what != qe_none) { - [self handleEvent: &event]; - } - - arp_end (); - } while (!endState); - return self; +-(TextContext *)screen +{ + return screen; } -draw @@ -116,17 +97,36 @@ arp_end (void) [objects handleEvent: event]; return self; } + +-run +{ + [objects takeFocus]; + [self draw]; + do { + arp_start (); + + get_event (&event); + if (event.what != qe_none) { + [self handleEvent: &event]; + } + + arp_end (); + } while (!endState); + return self; +} @end +QwaqApplication *application; + int main (int argc, string *argv) { fence = 0; //while (!fence) {} - id app = [[QwaqApplication app] retain]; + application = [[QwaqApplication app] retain]; - [app run]; - [app release]; + [application run]; + [application release]; qwaq_event_t event; get_event (&event); // XXX need a "wait for queue idle" return 0; diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index b8f8670b5..8c1d30c7d 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -1731,8 +1731,9 @@ bi_i_TextContext__bkgd_ (progs_t *pr) static void bi_i_TextContext__clear (progs_t *pr) { - int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; - int ch = P_INT (pr, 2); + __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); + int window_id = self->window; + int ch = self->background; qwaq_werase (pr, window_id, ch); } From c7597b94d2aca9a601440708f744fc3a49857e41 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 01:07:58 +0900 Subject: [PATCH 0856/3664] [qwaq] Create a debugger class Each debugger manages a single target. --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/qwaq-debug.c | 12 ++++--- ruamoko/qwaq/qwaq-debug.h | 21 +++++++++-- ruamoko/qwaq/qwaq-debugger.h | 25 +++++++++++++ ruamoko/qwaq/qwaq-debugger.r | 68 ++++++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-editor.h | 2 ++ ruamoko/qwaq/qwaq-editor.r | 6 ++++ 7 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 ruamoko/qwaq/qwaq-debugger.h create mode 100644 ruamoko/qwaq/qwaq-debugger.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 3a65cfbbf..4f81c8424 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -26,6 +26,7 @@ SUFFIXES=.o .r qwaq_app_dat_src= \ qwaq-app.r \ qwaq-button.r \ + qwaq-debugger.r \ qwaq-draw.r \ qwaq-editbuffer.r \ qwaq-editor.r \ diff --git a/ruamoko/qwaq/qwaq-debug.c b/ruamoko/qwaq/qwaq-debug.c index 8edcf992d..ea40ab2e4 100644 --- a/ruamoko/qwaq/qwaq-debug.c +++ b/ruamoko/qwaq/qwaq-debug.c @@ -145,7 +145,9 @@ static void qwaq_target_clear (progs_t *pr, void *data) { qwaq_target_t *target = pr->debug_data; - target_free (target->debugger, target); + if (target) { + target_free (target->debugger, target); + } } //FIXME need a better way to get this from one thread to the others @@ -274,10 +276,12 @@ qdb_get_state (progs_t *pr) lineno = PR_Find_Lineno (tpr, staddr); if (lineno) { - f = PR_Get_Lineno_Func (pr, lineno); - file = pr->pr_functions[f->function].s_file; + f = PR_Get_Lineno_Func (tpr, lineno); + //FIXME file is a permanent string. dynamic would be better + //but they're not merged (and would need refcounting) + file = PR_SetString (pr, PR_Get_Source_File (tpr, lineno)); func = f->function; - line = PR_Get_Lineno_Line (pr, lineno); + line = PR_Get_Lineno_Line (tpr, lineno); line += f->source_line; } diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h index f54d25636..0eb13d4a5 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/qwaq-debug.h @@ -15,17 +15,34 @@ typedef enum { #define umax 0x7fffffff #endif -#else//GCC +typedef string string_t; + #endif typedef struct qdb_state_s { unsigned staddr; unsigned func; - unsigned file; + string_t file; unsigned line; } qdb_state_t; +#ifdef __QFCC__ + +typedef struct qdb_target_s { int handle; } qdb_target_t; + +@extern void qdb_set_trace (qdb_target_t target, int state); +@extern int qdb_set_breakpoint (qdb_target_t target, unsigned staddr); +@extern int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr); +@extern int qdb_set_watchpoint (qdb_target_t target, unsigned offset); +@extern int qdb_clear_watchpoint (qdb_target_t target); +@extern int qdb_continue (qdb_target_t target); +@extern qdb_state_t qdb_get_state (qdb_target_t target); + +#else//GCC + void QWAQ_Debug_Init (progs_t *pr); void QWAQ_DebugTarget_Init (progs_t *pr); +#endif + #endif//__qwaq_debug_h diff --git a/ruamoko/qwaq/qwaq-debugger.h b/ruamoko/qwaq/qwaq-debugger.h new file mode 100644 index 000000000..34809def2 --- /dev/null +++ b/ruamoko/qwaq/qwaq-debugger.h @@ -0,0 +1,25 @@ +#ifndef __qwaq_debugger_h +#define __qwaq_debugger_h + +#include + +#include "qwaq-debug.h" + +@class ProxyView; +@class Editor; +@class Window; +@class Array; + +@interface Debugger : Object +{ + Window *source_window; + ProxyView *file_proxy; + Array *files; + Editor *current_file; + qdb_target_t debug_target; +} +-initWithTarget:(qdb_target_t) target; +-handleDebugEvent; +@end + +#endif//__qwaq_debugger_h diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r new file mode 100644 index 000000000..bd771c679 --- /dev/null +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -0,0 +1,68 @@ +#include + +#include "qwaq-curses.h" +#include "qwaq-debugger.h" +#include "qwaq-editor.h" +#include "qwaq-proxyview.h" +#include "qwaq-window.h" + +@implementation Debugger + +-initWithTarget:(qdb_target_t) target +{ + if (!(self = [super init])) { + return nil; + } + debug_target = target; + + files = [[Array array] retain]; + //FIXME need a window manager + source_window = [[Window alloc] initWithRect: getwrect (stdscr)]; + + return self; +} + +-(Editor *) find_file:(string) filename +{ + Editor *file; + for (int i = [files count]; i-- > 0; ) { + file = [files objectAtIndex: i]; + if ([file filename] == filename) { + return file; + } + } + Rect rect = {{1, 1}, [source_window size]}; + rect.extent.width -= 2; + rect.extent.height -= 2; + file = [[Editor alloc] initWithRect: rect file: filename]; + [files addObject: file]; + return file; +} + +-(void) setup +{ + qdb_state_t state = qdb_get_state (debug_target); + + current_file = [self find_file: state.file]; + file_proxy = [[ProxyView alloc] initWithView: current_file]; + //FIXME id? + [source_window insertSelected: (View *) file_proxy]; +} + +-handleDebugEvent +{ + if (!file_proxy) { + [self setup]; + } + return self; +} + +@end + +void qdb_set_trace (qdb_target_t target, int state) = #0; +int qdb_set_breakpoint (qdb_target_t target, unsigned staddr) = #0; +int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr) = #0; +int qdb_set_watchpoint (qdb_target_t target, unsigned offset) = #0; +int qdb_clear_watchpoint (qdb_target_t target) = #0; +int qdb_continue (qdb_target_t target) = #0; +qdb_state_t qdb_get_state (qdb_target_t target) = #0; diff --git a/ruamoko/qwaq/qwaq-editor.h b/ruamoko/qwaq/qwaq-editor.h index 2a480103e..0680cc9dc 100644 --- a/ruamoko/qwaq/qwaq-editor.h +++ b/ruamoko/qwaq/qwaq-editor.h @@ -18,8 +18,10 @@ unsigned old_cind; // previous character Point cursor; unsigned line_count; + string filename; } -initWithRect:(Rect) rect file:(string) filename; +-(string)filename; -scrollUp:(unsigned) count; -scrollDown:(unsigned) count; -scrollLeft:(unsigned) count; diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 9d36e27ac..0c0767c6d 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -9,6 +9,7 @@ if (!(self = [super initWithRect: rect])) { return nil; } + self.filename = filename; buffer = [[EditBuffer alloc] initWithFile: filename]; line_count = [buffer countLines: {0, [buffer textSize]}]; linebuffer = [DrawBuffer buffer: { xlen, 1 }]; @@ -17,6 +18,11 @@ return self; } +-(string)filename +{ + return filename; +} + -draw { [super draw]; From 0d8815f27410b4d1c3a4196183c5e6f18715e00c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 01:32:52 +0900 Subject: [PATCH 0857/3664] [qwaq] Handle debug events at the app level The debugger displays the source file but doesn't highlight the current line yet. --- ruamoko/qwaq/qwaq-app.h | 5 +++ ruamoko/qwaq/qwaq-app.r | 70 +++++++++++++++++++++++++----------- ruamoko/qwaq/qwaq-debugger.h | 1 + ruamoko/qwaq/qwaq-debugger.r | 10 ++++-- 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index 40681d940..3facb0bc6 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -6,8 +6,10 @@ #include "event.h" #include "qwaq-rect.h" +@class Array; @class Group; @class TextContext; +@class View; @interface QwaqApplication: Object { @@ -19,9 +21,12 @@ TextContext *screen; Extent screenSize; int autocount; + + Array *debuggers; } -(Extent)size; -(TextContext *)screen; +-addView:(View *)view; -run; @end diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index aba239607..7a9e6ed97 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -6,6 +6,7 @@ int fence; #include "color.h" #include "qwaq-app.h" #include "qwaq-curses.h" +#include "qwaq-debugger.h" #include "qwaq-group.h" #include "qwaq-view.h" @@ -49,6 +50,8 @@ arp_end (void) [screen scrollok: 1]; [screen clear]; wrefresh (stdscr);//FIXME + + debuggers = [[Array array] retain]; return self; } @@ -69,32 +72,50 @@ arp_end (void) return self; } +-(Debugger *)find_debugger:(qdb_target_t) target +{ + Debugger *debugger; + + for (int i = [debuggers count]; i-- > 0; ) { + debugger = [debuggers objectAtIndex: i]; + if ([debugger debug_target].handle == target.handle) { + return debugger; + } + } + debugger = [[Debugger alloc] initWithTarget: target]; + [debuggers addObject: debugger]; + return debugger; +} + -handleEvent: (qwaq_event_t *) event { - if (event.what == qe_resize) { - Extent delta; - delta.width = event.resize.width - screenSize.width; - delta.height = event.resize.height - screenSize.height; + switch (event.what) { + case qe_resize: + Extent delta; + delta.width = event.resize.width - screenSize.width; + delta.height = event.resize.height - screenSize.height; - resizeterm (event.resize.width, event.resize.height); - [screen resizeTo: {event.resize.width, event.resize.height}]; - screenSize = [screen size]; - [objects resize: delta]; - [screen refresh]; - event.what = qe_none; - return self; + resizeterm (event.resize.width, event.resize.height); + [screen resizeTo: {event.resize.width, event.resize.height}]; + screenSize = [screen size]; + [objects resize: delta]; + [screen refresh]; + event.what = qe_none; + break; + case qe_key: + if (event.key.code == '\x18' || event.key.code == '\x11') { + endState = event.message.int_val; + event.what = qe_none; + } + break; + case qe_debug_event: + [[self find_debugger:{event.message.int_val}] handleDebugEvent]; + event.what = qe_none; + break; } - if (event.what == qe_key - && (event.key.code == '\x18' || event.key.code == '\x11')) { - event.what = qe_command; - event.message.int_val = qc_exit; + if (event.what != qe_none) { + [objects handleEvent: event]; } - if (event.what == qe_command - && (event.message.int_val == qc_exit - || event.message.int_val == qc_error)) { - endState = event.message.int_val;; - } - [objects handleEvent: event]; return self; } @@ -114,6 +135,13 @@ arp_end (void) } while (!endState); return self; } + +-addView:(View *)view +{ + [objects insertSelected: view]; + [screen refresh]; + return self; +} @end QwaqApplication *application; diff --git a/ruamoko/qwaq/qwaq-debugger.h b/ruamoko/qwaq/qwaq-debugger.h index 34809def2..2a1e3a2b3 100644 --- a/ruamoko/qwaq/qwaq-debugger.h +++ b/ruamoko/qwaq/qwaq-debugger.h @@ -18,6 +18,7 @@ Editor *current_file; qdb_target_t debug_target; } +-(qdb_target_t)debug_target; -initWithTarget:(qdb_target_t) target; -handleDebugEvent; @end diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index bd771c679..aea913dc8 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -1,5 +1,6 @@ #include +#include "qwaq-app.h" #include "qwaq-curses.h" #include "qwaq-debugger.h" #include "qwaq-editor.h" @@ -7,6 +8,10 @@ #include "qwaq-window.h" @implementation Debugger +-(qdb_target_t)debug_target +{ + return debug_target; +} -initWithTarget:(qdb_target_t) target { @@ -16,8 +21,8 @@ debug_target = target; files = [[Array array] retain]; - //FIXME need a window manager - source_window = [[Window alloc] initWithRect: getwrect (stdscr)]; + source_window = [[Window alloc] initWithRect: {nil, [application size]}]; + [application addView:source_window]; return self; } @@ -47,6 +52,7 @@ file_proxy = [[ProxyView alloc] initWithView: current_file]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; + [source_window redraw]; } -handleDebugEvent From 1c3e503ad2cdaebcea72f17b10281986a5897dca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 01:39:56 +0900 Subject: [PATCH 0858/3664] [qwaq] Set the window title to the file name --- ruamoko/qwaq/qwaq-debugger.r | 1 + ruamoko/qwaq/qwaq-window.h | 3 +++ ruamoko/qwaq/qwaq-window.r | 8 +++++++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index aea913dc8..27c76510e 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -52,6 +52,7 @@ file_proxy = [[ProxyView alloc] initWithView: current_file]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; + [source_window setTitle: [current_file filename]]; [source_window redraw]; } diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/qwaq-window.h index 1e5598856..a559ed862 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/qwaq-window.h @@ -5,6 +5,7 @@ @class Group; @class Button; +@class TitleBar; #include "qwaq-draw.h" #include "qwaq-rect.h" @@ -25,8 +26,10 @@ Button *bottomLeftDrag; Button *bottomRightDrag; Button *bottomDrag; + TitleBar *titleBar; } +windowWithRect: (Rect) rect; +-setTitle:(string) title; -setBackground: (int) ch; -insert: (View *) view; -insertDrawn: (View *) view; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 6071130eb..6b687044b 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -28,7 +28,7 @@ objects = [[Group alloc] initWithContext: textContext owner: self]; - [self insert: [[TitleBar alloc] initWithTitle:"drag me"]]; + [self insert: titleBar = [[TitleBar alloc] initWithTitle:""]]; topDrag = [[Button alloc] initWithRect: {{2, 0}, {xlen - 4, 1}}]; @@ -74,6 +74,12 @@ return self; } +-setTitle:(string) title +{ + [titleBar setTitle:title]; + return self; +} + #ifndef max # define max(a,b) ((a) > (b) ? (a) : (b)) #endif From 9a2ea54e78875946dccdcc702456ef7557114220 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 08:28:12 +0900 Subject: [PATCH 0859/3664] [qwaq] Highlight the current line --- ruamoko/qwaq/qwaq-debugger.r | 1 + ruamoko/qwaq/qwaq-editbuffer-bi.c | 1 - ruamoko/qwaq/qwaq-editor.h | 6 +++- ruamoko/qwaq/qwaq-editor.r | 58 +++++++++++++++++++++++++++---- 4 files changed, 57 insertions(+), 9 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index 27c76510e..0c2753df2 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -50,6 +50,7 @@ current_file = [self find_file: state.file]; file_proxy = [[ProxyView alloc] initWithView: current_file]; + [[current_file gotoLine:state.line - 1] highlightLine]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; [source_window setTitle: [current_file filename]]; diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/qwaq-editbuffer-bi.c index 1beb6eabd..02ae29370 100644 --- a/ruamoko/qwaq/qwaq-editbuffer-bi.c +++ b/ruamoko/qwaq/qwaq-editbuffer-bi.c @@ -496,7 +496,6 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, while (c != '\n' && ptr < buffer->textSize) { c = getChar (buffer, ptr++); } - col = ptr >= sels && ptr < sele ? cols : coln; while (length-- > 0) { *dst++ = col | ' '; } diff --git a/ruamoko/qwaq/qwaq-editor.h b/ruamoko/qwaq/qwaq-editor.h index 0680cc9dc..52afdd143 100644 --- a/ruamoko/qwaq/qwaq-editor.h +++ b/ruamoko/qwaq/qwaq-editor.h @@ -13,9 +13,9 @@ eb_sel_t selection; unsigned base_index; // top left corner unsigned line_index; // current line - unsigned x_index; // horizontal scrolling unsigned char_index; // current character unsigned old_cind; // previous character + Point scroll; Point cursor; unsigned line_count; string filename; @@ -26,6 +26,10 @@ -scrollDown:(unsigned) count; -scrollLeft:(unsigned) count; -scrollRight:(unsigned) count; + +-recenter:(int) force; +-gotoLine:(unsigned) line; +-highlightLine; @end #endif//__qwaq_editor_h diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 0c0767c6d..843b09720 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -29,7 +29,7 @@ unsigned lind = base_index; int *lbuf = [linebuffer buffer]; for (int y = 0; y < ylen; y++) { - lind = [buffer formatLine:lind from:x_index into:lbuf width:xlen + lind = [buffer formatLine:lind from:scroll.x into:lbuf width:xlen highlight:selection colors: {COLOR_PAIR (1), COLOR_PAIR(2)}]; [textContext blitFromBuffer: linebuffer to: {xpos, ypos + y} from: [linebuffer rect]]; @@ -99,10 +99,10 @@ -scrollLeft:(unsigned) count { - if (x_index > count) { - x_index -= count; + if (scroll.x > count) { + scroll.x -= count; } else { - x_index = 0; + scroll.x = 0; } [self redraw]; return self; @@ -110,13 +110,57 @@ -scrollRight:(unsigned) count { - if (1024 - x_index > count) { - x_index += count; + if (1024 - scroll.x > count) { + scroll.x += count; } else { - x_index = 1024; + scroll.x = 1024; } [self redraw]; return self; } +-recenter:(int) force +{ + if (!force) { + if (cursor.y >= scroll.y && cursor.y - scroll.y < ylen) { + return self; + } + } + unsigned target; + if (cursor.y < ylen / 2) { + target = 0; + } else { + target = cursor.y - ylen / 2; + } + if (target > scroll.y) { + base_index = [buffer nextLine:base_index :target - scroll.y]; + } else if (target < scroll.y) { + base_index = [buffer prevLine:base_index :scroll.y - target]; + } + scroll.y = target; + return self; +} + +-gotoLine:(unsigned) line +{ + if (line > cursor.y) { + line_index = [buffer nextLine:line_index :line - cursor.y]; + } else if (line < cursor.y) { + line_index = [buffer prevLine:line_index :cursor.y - line]; + } + cursor.y = line; + [self recenter: 0]; + return self; +} + +-highlightLine +{ + selection.start = line_index; + selection.length = [buffer nextLine: line_index] - line_index; + if (!selection.length) { + selection.length = [buffer getEOL: line_index] - line_index; + } + return self; +} + @end From d96059c70e8405bac798a645444af94513f8d186 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 09:20:40 +0900 Subject: [PATCH 0860/3664] [qwaq] Change listener respond param to void * Avoids writing another method for Array, so probably only for now. --- ruamoko/qwaq/qwaq-listener.h | 4 ++-- ruamoko/qwaq/qwaq-listener.r | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ruamoko/qwaq/qwaq-listener.h b/ruamoko/qwaq/qwaq-listener.h index 2f7ec02b3..59c96ff1d 100644 --- a/ruamoko/qwaq/qwaq-listener.h +++ b/ruamoko/qwaq/qwaq-listener.h @@ -12,7 +12,7 @@ IMP imp; } -initWithResponder: (id) responder :(SEL)message; --(void) respond: (id) caller; +-(void) respond: (void *) caller_data; -(BOOL) matchResponder: (id) responder :(SEL)message; @end @@ -23,7 +23,7 @@ -init; -addListener: (id) responder :(SEL)message; -removeListener: (id) responder :(SEL)message; --(void) respond: (id) caller; +-(void) respond: (void *) caller_data; @end #endif//__qwaq_listener_h diff --git a/ruamoko/qwaq/qwaq-listener.r b/ruamoko/qwaq/qwaq-listener.r index 26e6f28c5..12d786de3 100644 --- a/ruamoko/qwaq/qwaq-listener.r +++ b/ruamoko/qwaq/qwaq-listener.r @@ -16,9 +16,9 @@ return self; } --(void)respond: (id) caller +-(void)respond: (void *) caller_data { - imp (responder, message, caller); + imp (responder, message, caller_data); } -(BOOL) matchResponder: (id) responder :(SEL)message @@ -58,9 +58,9 @@ return self; } --(void)respond: (id) caller +-(void)respond: (void *) caller_data { [listeners makeObjectsPerformSelector: @selector (respond:) - withObject: caller]; + withObject: caller_data]; } @end From 16bd047022809fc2ed0511a457be3048876c4eea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 09:22:54 +0900 Subject: [PATCH 0861/3664] [qwaq] Add a key event listener to Editor This will allow for easy expansion of editor functionality without messing with the editor itself. In particularly, an editor normally doesn't need to know anything about debugger hot keys. --- ruamoko/qwaq/qwaq-editor.h | 11 +++++++++++ ruamoko/qwaq/qwaq-editor.r | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/ruamoko/qwaq/qwaq-editor.h b/ruamoko/qwaq/qwaq-editor.h index 52afdd143..29bf1c8b7 100644 --- a/ruamoko/qwaq/qwaq-editor.h +++ b/ruamoko/qwaq/qwaq-editor.h @@ -4,7 +4,15 @@ #include "qwaq-editbuffer.h" #include "qwaq-view.h" +@class Editor; @class EditBuffer; +@class ListenerGroup; + +// Data sent to onKeyEvent listeners +typedef struct ed_event_s { + Editor *editor; + struct qwaq_event_s *event; +} ed_event_t; @interface Editor : View { @@ -19,8 +27,11 @@ Point cursor; unsigned line_count; string filename; + ListenerGroup *onEvent; + ed_event_t _event; } -initWithRect:(Rect) rect file:(string) filename; +-(ListenerGroup *)onEvent; -(string)filename; -scrollUp:(unsigned) count; -scrollDown:(unsigned) count; diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 843b09720..dfd863569 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -1,6 +1,7 @@ #include #include "color.h" #include "qwaq-editor.h" +#include "qwaq-listener.h" @implementation Editor @@ -15,9 +16,15 @@ linebuffer = [DrawBuffer buffer: { xlen, 1 }]; growMode = gfGrowHi; options = ofCanFocus; + onEvent = [[ListenerGroup alloc] init]; return self; } +-(ListenerGroup *)onEvent +{ + return onEvent; +} + -(string)filename { return filename; @@ -46,6 +53,10 @@ -handleEvent:(qwaq_event_t *) event { + // give any listeners a chance to override or extend event handling + _event.editor = self; + _event.event = event; + [onEvent respond: &_event]; if (event.what & qe_mouse) { if (event.what == qe_mouseclick) { if (event.mouse.buttons & (1 << 3)) { From 257b6580597ae0bb9b18a3cbedcd25ddc4cbaa5c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 10:00:18 +0900 Subject: [PATCH 0862/3664] [qfcc] Implement single-stepping That... worked nicely. Program exit needs some work because exiting terminates the thread and the debugger has no clue about it, but I was able to single-step through gcd.r quite nicely. --- ruamoko/qwaq/qwaq-debugger.r | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index 0c2753df2..7000836c0 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -1,9 +1,11 @@ #include +#include #include "qwaq-app.h" #include "qwaq-curses.h" #include "qwaq-debugger.h" #include "qwaq-editor.h" +#include "qwaq-listener.h" #include "qwaq-proxyview.h" #include "qwaq-window.h" @@ -51,17 +53,52 @@ current_file = [self find_file: state.file]; file_proxy = [[ProxyView alloc] initWithView: current_file]; [[current_file gotoLine:state.line - 1] highlightLine]; + [[current_file onEvent] addListener: self :@selector(key_event:)]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; [source_window setTitle: [current_file filename]]; [source_window redraw]; } +-(void) show_line +{ + qdb_state_t state = qdb_get_state (debug_target); + Editor *file = [self find_file: state.file]; + + printf ("%s:%d\n", state.file, state.line); + if (current_file != file) { + [[current_file onEvent] removeListener:self :@selector(key_event:)]; + [file_proxy setView:file]; + [[file onEvent] addListener:self :@selector(key_event:)]; + [source_window setTitle: [file filename]]; + current_file = file; + } + [[current_file gotoLine:state.line - 1] highlightLine]; + [source_window redraw]; +} + +-(void)key_event: (ed_event_t *)_event +{ + qwaq_event_t *event = _event.event; + if (event.what == qe_keydown) { + switch (event.key.code) { + case QFK_F7: + qdb_set_trace (debug_target, 1); + qdb_continue (debug_target); + break; + default: + return; + } + } + event.what = qe_none; +} + -handleDebugEvent { if (!file_proxy) { [self setup]; } + [self show_line]; return self; } From 42f20f200ddd367e082ccbe25e7c7f331c46b0d4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 11:18:07 +0900 Subject: [PATCH 0863/3664] [qwaq] Fix window resize bounds logic Have a lot of HoM going on, though :( --- ruamoko/qwaq/qwaq-window.r | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 6b687044b..561e306f6 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -95,39 +95,39 @@ Point delta = [sender delta]; Point dp = nil; Point ds = nil; - Extent bounds = [owner size]; + Extent b = [owner size]; if (sender == topDrag) { - dp.x = bound (0, xpos + delta.x, bounds.width - xlen) - xpos; - dp.y = bound (0, ypos + delta.y, bounds.height - ylen) - ypos; + dp.x = bound (0, xpos + delta.x, b.width - xlen) - xpos; + dp.y = bound (0, ypos + delta.y, b.height - ylen) - ypos; } else if (sender == topLeftDrag) { - dp.x = bound (0, xpos + delta.x, xpos + xlen - 1) - xpos; - dp.y = bound (0, ypos + delta.y, ypos + ylen - 1) - ypos; - ds.x = bound (1, xlen - delta.x, bounds.width - xpos) - xlen; - ds.y = bound (1, ylen - delta.y, bounds.width - ypos) - ylen; + dp.x = bound (0, xpos + delta.x, xpos + xlen - delta.x - 1) - xpos; + dp.y = bound (0, ypos + delta.y, ypos + ylen - delta.y - 1) - ypos; + ds.x = bound (1, xlen - delta.x, b.width - xpos - delta.x) - xlen; + ds.y = bound (1, ylen - delta.y, b.height - ypos - delta.y) - ylen; } else if (sender == topRightDrag) { - dp.y = bound (0, ypos + delta.y, ypos + ylen - 1) - ypos; - ds.x = bound (1, xlen + delta.x, bounds.width - xpos) - xlen; - ds.y = bound (1, ylen - delta.y, bounds.width - ypos) - ylen; + dp.y = bound (0, ypos + delta.y, ypos + ylen - delta.y - 1) - ypos; + ds.x = bound (1, xlen + delta.x, b.width - xpos) - xlen; + ds.y = bound (1, ylen - delta.y, b.height - ypos - delta.y) - ylen; } else if (sender == leftDrag) { - dp.x = bound (0, xpos + delta.x, xpos + xlen - 1) - xpos; - ds.x = bound (1, xlen - delta.x, bounds.width - xpos) - xlen; + dp.x = bound (0, xpos + delta.x, xpos + xlen - delta.x - 1) - xpos; + ds.x = bound (1, xlen - delta.x, b.width - xpos - delta.x) - xlen; } else if (sender == rightDrag) { - ds.x = bound (1, xlen + delta.x, bounds.width - xpos) - xlen; + ds.x = bound (1, xlen + delta.x, b.width - xpos) - xlen; } else if (sender == bottomLeftDrag) { - dp.x = bound (0, xpos + delta.x, xpos + xlen - 1) - xpos; - ds.x = bound (1, xlen - delta.x, bounds.width - xpos) - xlen; - ds.y = bound (1, ylen + delta.y, bounds.width - ypos) - ylen; + dp.x = bound (0, xpos + delta.x, xpos + xlen - delta.x - 1) - xpos; + ds.x = bound (1, xlen - delta.x, b.width - xpos) - xlen; + ds.y = bound (1, ylen + delta.y, b.height - ypos) - ylen; } else if (sender == bottomRightDrag) { - ds.x = bound (1, xlen + delta.x, bounds.width - xpos) - xlen; - ds.y = bound (1, ylen + delta.y, bounds.width - ypos) - ylen; + ds.x = bound (1, xlen + delta.x, b.width - xpos) - xlen; + ds.y = bound (1, ylen + delta.y, b.height - ypos) - ylen; } else if (sender == bottomDrag) { - ds.y = bound (1, ylen + delta.y, bounds.width - ypos) - ylen; + ds.y = bound (1, ylen + delta.y, b.height - ypos) - ylen; } int save_state = state; state &= ~sfDrawn; - [self move: dp]; [self resize: {ds.x, ds.y}]; + [self move: dp]; state = save_state; [self redraw]; } From e554202c24faac654e8f74d41b69ad49b4dbfb60 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 14:39:37 +0900 Subject: [PATCH 0864/3664] [qwaq] Add combined move and resize method This fixes the hall of mirrors bug (needed to move, resize, then move the window). --- ruamoko/qwaq/qwaq-view.h | 1 + ruamoko/qwaq/qwaq-view.r | 10 ++++++++-- ruamoko/qwaq/qwaq-window.r | 27 +++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index b8d61d1f0..db4862929 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -65,6 +65,7 @@ enum { -redraw; -move: (Point) delta; -resize: (Extent) delta; +-move:(Point)dpos andResize:(Extent)dsize; -grow: (Extent) delta; -handleEvent: (qwaq_event_t *) event; -takeFocus; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 76a6fd532..3300a0d05 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -220,6 +220,13 @@ updateScreenCursor (View *view) return self; } +-move:(Point)dpos andResize:(Extent)dsize +{ + [self move: dpos]; + [self resize: dsize]; + return self; +} + -grow: (Extent) delta { Point dpos = {}; @@ -241,8 +248,7 @@ updateScreenCursor (View *view) } int save_state = state; state &= ~sfDrawn; - [self move: dpos]; - [self resize: dsize]; + [self move: dpos andResize: dsize]; state = save_state; [self redraw]; return self; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 561e306f6..37eb76918 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -126,8 +126,7 @@ } int save_state = state; state &= ~sfDrawn; - [self resize: {ds.x, ds.y}]; - [self move: dp]; + [self move:dp andResize:{ds.x, ds.y}]; state = save_state; [self redraw]; } @@ -137,6 +136,30 @@ return self; } +-move:(Point)dpos andResize:(Extent)dsize +{ + int save_state = state; + state &= ~sfDrawn; + + Point pos = self.pos; + Extent size = self.size; + [super resize: dsize]; + [super move: dpos]; + // need to move the panel both before and after the resize to avoid + // HoM effects or window/panel possition errors + move_panel (panel, xpos, ypos); + [(id)textContext resizeTo: self.size]; + replace_panel (panel, [(id)textContext window]); + move_panel (panel, xpos, ypos); + + dsize = {self.size.width - size.width, self.size.height - size.height}; + [objects resize:dsize]; + + state = save_state; + [self redraw]; + return self; +} + -move: (Point) delta { int save_state = state; From ee6b078f18f904db058bc1b1949fcf40f63753b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 14:45:55 +0900 Subject: [PATCH 0865/3664] [qwaq] Fix last window drag-resize corner case I think I got distracted by the HoM bug while testing corners. Anyway, with this, window resize by dragging seems to work well. --- ruamoko/qwaq/qwaq-window.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 37eb76918..8fde82d79 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -116,7 +116,7 @@ ds.x = bound (1, xlen + delta.x, b.width - xpos) - xlen; } else if (sender == bottomLeftDrag) { dp.x = bound (0, xpos + delta.x, xpos + xlen - delta.x - 1) - xpos; - ds.x = bound (1, xlen - delta.x, b.width - xpos) - xlen; + ds.x = bound (1, xlen - delta.x, b.width - xpos - delta.x) - xlen; ds.y = bound (1, ylen + delta.y, b.height - ypos) - ylen; } else if (sender == bottomRightDrag) { ds.x = bound (1, xlen + delta.x, b.width - xpos) - xlen; From 4cef9792f4b87027d6473f8759cebdbe74de5ef8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 15:43:16 +0900 Subject: [PATCH 0866/3664] [util] Make hash-tables semi-thread-safe They take a pointer to a free-list used for hashlinks so the hashlink pools can be per-thread. However, hash tables that are not updated are always thread-safe, so this affects only updates. progs_t has been set up such that it is easy for multiple progs within one thread can share hashlinks. --- include/QF/hash.h | 11 ++++++- include/QF/progs.h | 1 + libs/audio/renderer/snd_sfx.c | 2 +- libs/console/menu.c | 2 +- libs/gamecode/pr_builtins.c | 6 ++-- libs/gamecode/pr_debug.c | 3 +- libs/gamecode/pr_load.c | 9 ++++-- libs/gamecode/pr_opcode.c | 2 +- libs/gamecode/pr_resource.c | 3 +- libs/gamecode/pr_strings.c | 2 +- libs/gib/bi_gib.c | 3 +- libs/gib/gib_builtin.c | 2 +- libs/gib/gib_classes.c | 3 +- libs/gib/gib_function.c | 4 +-- libs/gib/gib_object.c | 8 +++-- libs/gib/gib_regex.c | 2 +- libs/gib/gib_thread.c | 2 +- libs/gib/gib_vars.c | 15 +++++---- libs/models/iqm/model_iqm.c | 2 +- libs/models/skin.c | 2 +- libs/ruamoko/rua_cmd.c | 3 +- libs/ruamoko/rua_hash.c | 2 +- libs/ruamoko/rua_obj.c | 12 ++++--- libs/ruamoko/rua_plist.c | 2 +- libs/util/cmd.c | 8 +++-- libs/util/cvar.c | 4 +-- libs/util/hash.c | 44 +++++++++++++++----------- libs/util/info.c | 2 +- libs/util/pakfile.c | 2 +- libs/util/plugin.c | 4 +-- libs/util/qfplist.c | 3 +- libs/util/quakefs.c | 4 +-- libs/util/segtext.c | 2 +- libs/util/wadfile.c | 2 +- libs/video/renderer/glsl/glsl_draw.c | 2 +- libs/video/renderer/glsl/glsl_shader.c | 2 +- libs/video/renderer/r_progs.c | 3 +- libs/video/targets/old_keys.c | 2 +- qtv/source/client.c | 2 +- qtv/source/connection.c | 2 +- qtv/source/server.c | 2 +- qw/source/sv_user.c | 2 +- ruamoko/qwaq/qwaq-input.c | 6 +++- tools/qfbsp/source/map.c | 2 +- tools/qfcc/source/class.c | 11 ++++--- tools/qfcc/source/function.c | 4 +-- tools/qfcc/source/grab.c | 4 +-- tools/qfcc/source/linker.c | 12 +++---- tools/qfcc/source/method.c | 9 +++--- tools/qfcc/source/opcodes.c | 4 +-- tools/qfcc/source/qc-lex.l | 8 ++--- tools/qfcc/source/qfprogs.c | 2 +- tools/qfcc/source/qp-lex.l | 2 +- tools/qfcc/source/strpool.c | 6 ++-- tools/qfcc/source/switch.c | 2 +- tools/qfcc/source/symtab.c | 2 +- tools/qfcc/source/value.c | 36 ++++++++++++--------- 57 files changed, 177 insertions(+), 128 deletions(-) diff --git a/include/QF/hash.h b/include/QF/hash.h index 7a31a06db..fde2eed97 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -37,6 +37,7 @@ ///@{ typedef struct hashtab_s hashtab_t; +typedef struct hashlink_s hashlink_t; /** create a new hash table. \param tsize table size. larger values will give better distribution, but @@ -50,6 +51,13 @@ typedef struct hashtab_s hashtab_t; element to be freed and the second is the user data pointer. \param ud user data pointer. set to whatever you want, it will be passed to the get key and free functions as the second parameter. + \param hlfl Address of opaque pointer used for per-thread allocation of + internal memory. If null, a local static pointer will be used, + but the hash table will not be thread-safe unless all tables + created with a null \a hlfl (hashlink freelist) are used in + only the one thread. However, this applys only to updating a + hash table; hash tables that are not updated can be safely + shared between threads. \return pointer to the hash table (to be passed to the other functions) or 0 on error. @@ -59,7 +67,8 @@ typedef struct hashtab_s hashtab_t; previous ones until the later one is removed (Hash_Del). */ hashtab_t *Hash_NewTable (int tsize, const char *(*gk)(const void*,void*), - void (*f)(void*,void*), void *ud); + void (*f)(void*,void*), void *ud, + hashlink_t **hlfl); /** change the hash and compare functions used by the Hash_*Element functions. the default hash function just returns the address of the element, and the diff --git a/include/QF/progs.h b/include/QF/progs.h index e2c077e02..841b586d3 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1705,6 +1705,7 @@ struct progs_s { int null_bad; int no_exec_limit; + struct hashlink_s **hashlink_freelist; void (*file_error) (progs_t *pr, const char *path); void *(*load_file) (progs_t *pr, const char *path, off_t *size); void *(*allocate_progs_mem) (progs_t *pr, int size); diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 25d023de8..4dc57ee90 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -245,7 +245,7 @@ s_soundlist_f (void) void SND_SFX_Init (void) { - snd_sfx_hash = Hash_NewTable (511, snd_sfx_getkey, snd_sfx_free, 0); + snd_sfx_hash = Hash_NewTable (511, snd_sfx_getkey, snd_sfx_free, 0, 0); precache = Cvar_Get ("precache", "1", CVAR_NONE, NULL, "Toggle the use of a precache"); diff --git a/libs/console/menu.c b/libs/console/menu.c index ec9fc3355..90eaeca75 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -586,7 +586,7 @@ Menu_Init (void) PR_Init (&menu_pr_state); - menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0); + menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0, 0); PR_RegisterBuiltins (&menu_pr_state, builtins); diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index 7e4bb4431..6d738e6bc 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -92,8 +92,10 @@ PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins) int count; if (!pr->builtin_hash) { - pr->builtin_hash = Hash_NewTable (1021, builtin_get_key, 0, pr); - pr->builtin_num_hash = Hash_NewTable (1021, 0, 0, pr); + pr->builtin_hash = Hash_NewTable (1021, builtin_get_key, 0, pr, + pr->hashlink_freelist); + pr->builtin_num_hash = Hash_NewTable (1021, 0, 0, pr, + pr->hashlink_freelist); Hash_SetHashCompare (pr->builtin_num_hash, builtin_get_hash, builtin_compare); } diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index d2ed5e7f1..63f4444b4 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1610,7 +1610,8 @@ PR_Debug_Init (progs_t *pr) PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); if (!file_hash) { - file_hash = Hash_NewTable (1024, file_get_key, file_free, 0); + file_hash = Hash_NewTable (1024, file_get_key, file_free, 0, + pr->hashlink_freelist); } PR_AddLoadFunc (pr, PR_LoadDebug); } diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 2bae32dfe..9ea30a037 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -234,17 +234,20 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) if (pr->function_hash) { Hash_FlushTable (pr->function_hash); } else { - pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr); + pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr, + pr->hashlink_freelist); } if (pr->global_hash) { Hash_FlushTable (pr->global_hash); } else { - pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr); + pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr, + pr->hashlink_freelist); } if (pr->field_hash) { Hash_FlushTable (pr->field_hash); } else { - pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr); + pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr, + pr->hashlink_freelist); } // byte swap the lumps diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 30ad8b06e..15cdb93ad 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -1513,7 +1513,7 @@ PR_Opcode_Init (void) // already initialized return; } - opcode_table = Hash_NewTable (1021, 0, 0, 0); + opcode_table = Hash_NewTable (1021, 0, 0, 0, 0); Hash_SetHashCompare (opcode_table, opcode_get_hash, opcode_compare); for (op = pr_opcodes; op->name; op++) { diff --git a/libs/gamecode/pr_resource.c b/libs/gamecode/pr_resource.c index 14cd4a38b..9a86d2302 100644 --- a/libs/gamecode/pr_resource.c +++ b/libs/gamecode/pr_resource.c @@ -53,7 +53,8 @@ resource_get_key (const void *r, void *unused) VISIBLE void PR_Resources_Init (progs_t *pr) { - pr->resource_hash = Hash_NewTable (1021, resource_get_key, 0, 0); + pr->resource_hash = Hash_NewTable (1021, resource_get_key, 0, 0, + pr->hashlink_freelist); pr->resources = 0; } diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 00bb16e4f..6bbca3481 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -259,7 +259,7 @@ PR_LoadStrings (progs_t *pr) Hash_FlushTable (res->strref_hash); } else { res->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free, - res); + res, pr->hashlink_freelist); res->string_map = 0; res->free_string_refs = 0; res->dyn_str_size = 0; diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index 3c462712c..2b1c6c5b4 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -193,7 +193,8 @@ GIB_Progs_Init (progs_t *pr) PR_Resources_Register (pr, "GIB", res, bi_gib_builtin_clear); bi_gib_builtins = Hash_NewTable (1021, bi_gib_builtin_get_key, - bi_gib_builtin_free, 0); + bi_gib_builtin_free, 0, + pr->hashlink_freelist); PR_RegisterBuiltins (pr, builtins); } diff --git a/libs/gib/gib_builtin.c b/libs/gib/gib_builtin.c index 6f6e857bd..b7f571458 100644 --- a/libs/gib/gib_builtin.c +++ b/libs/gib/gib_builtin.c @@ -99,7 +99,7 @@ GIB_Builtin_Add (const char *name, void (*func) (void)) if (!gib_builtins) gib_builtins = - Hash_NewTable (1024, GIB_Builtin_Get_Key, GIB_Builtin_Free, 0); + Hash_NewTable (1024, GIB_Builtin_Get_Key, GIB_Builtin_Free, 0, 0); new = calloc (1, sizeof (gib_builtin_t)); new->func = func; diff --git a/libs/gib/gib_classes.c b/libs/gib/gib_classes.c index 8258e7882..88922af50 100644 --- a/libs/gib/gib_classes.c +++ b/libs/gib/gib_classes.c @@ -388,8 +388,7 @@ ObjectHash_Construct (gib_object_t *obj) { ObjectHash_t *data = malloc (sizeof (ObjectHash_t)); - data->objects = Hash_NewTable (1024, ObjRef_Get_Key, ObjRef_Free, - NULL); + data->objects = Hash_NewTable (1024, ObjRef_Get_Key, ObjRef_Free, NULL, 0); return data; } diff --git a/libs/gib/gib_function.c b/libs/gib/gib_function.c index 5c5403277..c960a7d49 100644 --- a/libs/gib/gib_function.c +++ b/libs/gib/gib_function.c @@ -117,8 +117,8 @@ GIB_Function_Define (const char *name, const char *text, gib_tree_t * program, if (script) script->refs++; if (!gib_functions) - gib_functions = - Hash_NewTable (1024, GIB_Function_Get_Key, GIB_Function_Free, 0); + gib_functions = Hash_NewTable (1024, GIB_Function_Get_Key, + GIB_Function_Free, 0, 0); func = Hash_Find (gib_functions, name); if (func) { diff --git a/libs/gib/gib_object.c b/libs/gib/gib_object.c index a4954762b..3d69b887e 100644 --- a/libs/gib/gib_object.c +++ b/libs/gib/gib_object.c @@ -125,7 +125,8 @@ GIB_Method_Build_Hash (gib_class_t *class, hashtab_t *inherited, { gib_methodtab_t *m; gib_method_t *method; - hashtab_t *new = Hash_NewTable (1024, GIB_Method_Get_Key, GIB_Method_Free, 0); + hashtab_t *new = Hash_NewTable (1024, GIB_Method_Get_Key, + GIB_Method_Free, 0, 0); for (m = methods; m->name; m++) { method = malloc (sizeof (gib_method_t)); @@ -207,7 +208,7 @@ GIB_Object_Create (const char *classname, qboolean classobj) obj->handstr = strdup (va ("%lu", obj->handle)); obj->refs = 1; obj->signals = Hash_NewTable (128, GIB_Signal_Get_Key, - GIB_Signal_Free, NULL); + GIB_Signal_Free, NULL, 0); obj->slots = llist_new (GIB_Slot_Free, NULL, NULL); if (classobj) { @@ -392,7 +393,8 @@ GIB_Object_Signal_Emit (gib_object_t *sender, int argc, const char **argv) void GIB_Object_Init (void) { - gib_classes = Hash_NewTable (1024, GIB_Class_Get_Key, GIB_Class_Free, 0); + gib_classes = Hash_NewTable (1024, GIB_Class_Get_Key, + GIB_Class_Free, 0, 0); GIB_Classes_Init (); } diff --git a/libs/gib/gib_regex.c b/libs/gib/gib_regex.c index e808532d6..dbe43cf04 100644 --- a/libs/gib/gib_regex.c +++ b/libs/gib/gib_regex.c @@ -63,7 +63,7 @@ GIB_Regex_Free (void *ele, void *ptr) void GIB_Regex_Init (void) { - gib_regexs = Hash_NewTable (512, GIB_Regex_Get_Key, GIB_Regex_Free, 0); + gib_regexs = Hash_NewTable (512, GIB_Regex_Get_Key, GIB_Regex_Free, 0, 0); } regex_t * diff --git a/libs/gib/gib_thread.c b/libs/gib/gib_thread.c index 9c317d9fe..01d1fd98f 100644 --- a/libs/gib/gib_thread.c +++ b/libs/gib/gib_thread.c @@ -171,5 +171,5 @@ GIB_Event_Callback (gib_event_t * event, unsigned int argc, ...) void GIB_Event_Init (void) { - gib_events = Hash_NewTable (1024, GIB_Event_Get_Key, GIB_Event_Free, 0); + gib_events = Hash_NewTable (1024, GIB_Event_Get_Key, GIB_Event_Free, 0, 0); } diff --git a/libs/gib/gib_vars.c b/libs/gib/gib_vars.c index e8b7f8a3a..31d7b3c6a 100644 --- a/libs/gib/gib_vars.c +++ b/libs/gib/gib_vars.c @@ -117,7 +117,8 @@ GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key, if (!(var = GIB_Var_Get (*first, *second, key+start)) && create) { var = GIB_Var_New (key+start); if (!*first) - *first = Hash_NewTable (256, GIB_Var_Get_Key, GIB_Var_Free, 0); + *first = Hash_NewTable (256, GIB_Var_Get_Key, + GIB_Var_Free, 0, 0); Hash_Add (*first, var); } @@ -181,7 +182,8 @@ GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *ke if (create) { var = GIB_Var_New (key->str+start); if (!*first) - *first = Hash_NewTable (256, GIB_Var_Get_Key, GIB_Var_Free, 0); + *first = Hash_NewTable (256, GIB_Var_Get_Key, + GIB_Var_Free, 0, 0); Hash_Add (*first, var); } else return 0; @@ -293,7 +295,7 @@ GIB_Domain_Get (const char *name) if (!d) { d = calloc (1, sizeof (gib_domain_t)); d->name = strdup (name); - d->vars = Hash_NewTable (1024, GIB_Var_Get_Key, GIB_Var_Free, 0); + d->vars = Hash_NewTable (1024, GIB_Var_Get_Key, GIB_Var_Free, 0, 0); Hash_Add (gib_domains, d); } return d->vars; @@ -302,12 +304,13 @@ GIB_Domain_Get (const char *name) hashtab_t * GIB_Var_Hash_New (void) { - return Hash_NewTable (1024, GIB_Var_Get_Key, GIB_Var_Free, 0); + return Hash_NewTable (1024, GIB_Var_Get_Key, GIB_Var_Free, 0, 0); } void GIB_Var_Init (void) { - gib_globals = Hash_NewTable (1024, GIB_Var_Get_Key, GIB_Var_Free, 0); - gib_domains = Hash_NewTable (1024, GIB_Domain_Get_Key, GIB_Domain_Free, 0); + gib_globals = Hash_NewTable (1024, GIB_Var_Get_Key, GIB_Var_Free, 0, 0); + gib_domains = Hash_NewTable (1024, GIB_Domain_Get_Key, + GIB_Domain_Free, 0, 0); } diff --git a/libs/models/iqm/model_iqm.c b/libs/models/iqm/model_iqm.c index 6d6e8de0b..4940da557 100644 --- a/libs/models/iqm/model_iqm.c +++ b/libs/models/iqm/model_iqm.c @@ -600,7 +600,7 @@ Mod_IQMBuildBlendPalette (iqm_t *iqm, int *size) } num_blends = iqm->num_joints; - blend_hash = Hash_NewTable (1023, 0, 0, 0); + blend_hash = Hash_NewTable (1023, 0, 0, 0, 0); Hash_SetHashCompare (blend_hash, blend_get_hash, blend_compare); for (i = 0; i < iqm->num_verts; i++) { diff --git a/libs/models/skin.c b/libs/models/skin.c index 14c21cd81..9583383cc 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -242,6 +242,6 @@ skin_free (void *_sb, void *unused) void Skin_Init (void) { - skin_cache = Hash_NewTable (127, skin_getkey, skin_free, 0); + skin_cache = Hash_NewTable (127, skin_getkey, skin_free, 0, 0); m_funcs->Skin_InitTranslations (); } diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index a18e2805e..8efcfb2a5 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -162,7 +162,8 @@ RUA_Cmd_Init (progs_t *pr, int secure) PR_Resources_Register (pr, "Cmd", res, bi_cmd_clear); if (!bi_cmds) - bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0); + bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0, + pr->hashlink_freelist); PR_RegisterBuiltins (pr, builtins); } diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index fedb8c288..cff92eb4e 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -162,7 +162,7 @@ bi_Hash_NewTable (progs_t *pr) gk = ht->gk ? bi_get_key : 0; f = ht->f ? bi_free : 0; - ht->tab = Hash_NewTable (tsize, gk, f, ht); + ht->tab = Hash_NewTable (tsize, gk, f, ht, pr->hashlink_freelist); R_INT (pr) = table_index (res, ht); } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 854341b56..3d69eba11 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -2215,10 +2215,14 @@ RUA_Obj_Init (progs_t *pr, int secure) probj_t *probj = calloc (1, sizeof (*probj)); probj->pr = pr; - probj->selector_hash = Hash_NewTable (1021, selector_get_key, 0, probj); - probj->classes = Hash_NewTable (1021, class_get_key, 0, probj); - probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj); - probj->load_methods = Hash_NewTable (1021, 0, 0, probj); + probj->selector_hash = Hash_NewTable (1021, selector_get_key, 0, probj, + pr->hashlink_freelist); + probj->classes = Hash_NewTable (1021, class_get_key, 0, probj, + pr->hashlink_freelist); + probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj, + pr->hashlink_freelist); + probj->load_methods = Hash_NewTable (1021, 0, 0, probj, + pr->hashlink_freelist); probj->msg = dstring_newstr(); Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, load_methods_compare); diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 0fdb1ff8d..9732b75c3 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -455,7 +455,7 @@ void RUA_Plist_Init (progs_t *pr, int secure) { plist_resources_t *res = calloc (1, sizeof (plist_resources_t)); - res->plist_tab = Hash_NewTable (1021, 0, 0, 0); + res->plist_tab = Hash_NewTable (1021, 0, 0, 0, pr->hashlink_freelist); Hash_SetHashCompare (res->plist_tab, plist_get_hash, plist_compare); PR_Resources_Register (pr, "plist", res, bi_plist_clear); diff --git a/libs/util/cmd.c b/libs/util/cmd.c index dcdbe6855..aede64982 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -583,9 +583,11 @@ Cmd_StuffCmds_f (void) VISIBLE void Cmd_Init_Hash (void) { - cmd_hash = Hash_NewTable (1021, cmd_get_key, 0, 0); - cmd_alias_hash = Hash_NewTable (1021, cmd_alias_get_key, cmd_alias_free, 0); - cmd_provider_hash = Hash_NewTable(1021, cmd_provider_get_key, cmd_provider_free, 0); + cmd_hash = Hash_NewTable (1021, cmd_get_key, 0, 0, 0); + cmd_alias_hash = Hash_NewTable (1021, cmd_alias_get_key, + cmd_alias_free, 0, 0); + cmd_provider_hash = Hash_NewTable(1021, cmd_provider_get_key, + cmd_provider_free, 0, 0); } VISIBLE void diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 64ef200ab..99f016d85 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -580,8 +580,8 @@ calias_get_key (const void *c, void *unused) VISIBLE void Cvar_Init_Hash (void) { - cvar_hash = Hash_NewTable (1021, cvar_get_key, cvar_free, 0); - calias_hash = Hash_NewTable (1021, calias_get_key, calias_free, 0); + cvar_hash = Hash_NewTable (1021, cvar_get_key, cvar_free, 0, 0); + calias_hash = Hash_NewTable (1021, calias_get_key, calias_free, 0, 0); } VISIBLE void diff --git a/libs/util/hash.c b/libs/util/hash.c index 587e4a24d..13c090132 100644 --- a/libs/util/hash.c +++ b/libs/util/hash.c @@ -45,11 +45,11 @@ #include "compat.h" -typedef struct hashlink_s { +struct hashlink_s { struct hashlink_s *next; struct hashlink_s **prev; void *data; -} hashlink_t; +}; struct hashtab_s { size_t tab_size; @@ -60,38 +60,39 @@ struct hashtab_s { uintptr_t (*get_hash)(const void*,void*); const char *(*get_key)(const void*,void*); void (*free_ele)(void*,void*); + hashlink_t **hashlink_freelist; hashlink_t *tab[1]; // variable size }; -static hashlink_t *free_hashlinks; - static hashlink_t * -new_hashlink (void) +new_hashlink (hashlink_t **free_hashlinks) { hashlink_t *link; - if (!free_hashlinks) { + if (!*free_hashlinks) { int i; - if (!(free_hashlinks = calloc (1024, sizeof (hashlink_t)))) + if (!(*free_hashlinks = calloc (1024, sizeof (hashlink_t)))) return 0; - for (i = 0, link = free_hashlinks; i < 1023; i++, link++) + for (i = 0, link = *free_hashlinks; i < 1023; i++, link++) link->next = link + 1; link->next = 0; } - link = free_hashlinks; - free_hashlinks = link->next; + link = *free_hashlinks; + *free_hashlinks = link->next; link->next = 0; return link; } static void -free_hashlink (hashlink_t *link) +free_hashlink (hashlink_t *link, hashlink_t **free_hashlinks) { - link->next = free_hashlinks; - free_hashlinks = link; + link->next = *free_hashlinks; + *free_hashlinks = link; } +static hashlink_t *default_hashlink_freelist; + VISIBLE unsigned long Hash_String (const char *str) { @@ -183,7 +184,8 @@ get_index (uintptr_t hash, size_t size, size_t bits) VISIBLE hashtab_t * Hash_NewTable (int tsize, const char *(*gk)(const void*,void*), - void (*f)(void*,void*), void *ud) + void (*f)(void*,void*), void *ud, + hashlink_t **hashlink_freelist) { hashtab_t *tab = calloc (1, field_offset (hashtab_t, tab[tsize])); if (!tab) @@ -192,6 +194,10 @@ Hash_NewTable (int tsize, const char *(*gk)(const void*,void*), tab->user_data = ud; tab->get_key = gk; tab->free_ele = f; + if (!hashlink_freelist) { + hashlink_freelist = &default_hashlink_freelist; + } + tab->hashlink_freelist = hashlink_freelist; while (tsize) { tab->size_bits++; @@ -228,7 +234,7 @@ Hash_FlushTable (hashtab_t *tab) hashlink_t *t = tab->tab[i]->next; void *data = tab->tab[i]->data; - free_hashlink (tab->tab[i]); + free_hashlink (tab->tab[i], tab->hashlink_freelist); tab->tab[i] = t; if (tab->free_ele) tab->free_ele (data, tab->user_data); @@ -242,7 +248,7 @@ Hash_Add (hashtab_t *tab, void *ele) { unsigned long h = Hash_String (tab->get_key(ele, tab->user_data)); size_t ind = get_index (h, tab->tab_size, tab->size_bits); - hashlink_t *lnk = new_hashlink (); + hashlink_t *lnk = new_hashlink (tab->hashlink_freelist); if (!lnk) return -1; @@ -261,7 +267,7 @@ Hash_AddElement (hashtab_t *tab, void *ele) { unsigned long h = tab->get_hash (ele, tab->user_data); size_t ind = get_index (h, tab->tab_size, tab->size_bits); - hashlink_t *lnk = new_hashlink (); + hashlink_t *lnk = new_hashlink (tab->hashlink_freelist); if (!lnk) return -1; @@ -375,7 +381,7 @@ Hash_Del (hashtab_t *tab, const char *key) if (lnk->next) lnk->next->prev = lnk->prev; *lnk->prev = lnk->next; - free_hashlink (lnk); + free_hashlink (lnk, tab->hashlink_freelist); tab->num_ele--; return data; } @@ -398,7 +404,7 @@ Hash_DelElement (hashtab_t *tab, void *ele) if (lnk->next) lnk->next->prev = lnk->prev; *lnk->prev = lnk->next; - free_hashlink (lnk); + free_hashlink (lnk, tab->hashlink_freelist); tab->num_ele--; return data; } diff --git a/libs/util/info.c b/libs/util/info.c index e9e8e9727..9758942a4 100644 --- a/libs/util/info.c +++ b/libs/util/info.c @@ -228,7 +228,7 @@ Info_ParseString (const char *s, int maxsize, int flags) char *key, *value, *end; info = malloc (sizeof (info_t)); - info->tab = Hash_NewTable (61, info_get_key, free_key, 0); + info->tab = Hash_NewTable (61, info_get_key, free_key, 0, 0); info->maxsize = maxsize; info->cursize = 0; diff --git a/libs/util/pakfile.c b/libs/util/pakfile.c index 9cfcb9924..f3f0352ed 100644 --- a/libs/util/pakfile.c +++ b/libs/util/pakfile.c @@ -66,7 +66,7 @@ pack_new (const char *name) free (pack); return 0; } - pack->file_hash = Hash_NewTable (1021, pack_get_key, 0, 0); + pack->file_hash = Hash_NewTable (1021, pack_get_key, 0, 0, 0); if (!pack->file_hash) { free (pack->filename); free (pack); diff --git a/libs/util/plugin.c b/libs/util/plugin.c index 7baa8df72..f625ddd15 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -241,9 +241,9 @@ VISIBLE void PI_Init (void) { PI_InitCvars (); - registered_plugins = Hash_NewTable (253, plugin_get_key, 0, 0); + registered_plugins = Hash_NewTable (253, plugin_get_key, 0, 0, 0); loaded_plugins = Hash_NewTable(253, loaded_plugin_get_key, - loaded_plugin_delete, 0); + loaded_plugin_delete, 0, 0); Cmd_AddCommand("plugin_load", PI_Plugin_Load_f, "load the plugin of the given type name and name"); Cmd_AddCommand("plugin_unload", PI_Plugin_Unload_f, diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 03a85b5b2..0bda96e59 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -149,7 +149,8 @@ VISIBLE plitem_t * PL_NewDictionary (void) { plitem_t *item = PL_NewItem (QFDictionary); - hashtab_t *dict = Hash_NewTable (1021, dict_get_key, dict_free, NULL); + //FIXME need a per-thread hashlink freelist for plist to be thread-safe + hashtab_t *dict = Hash_NewTable (1021, dict_get_key, dict_free, NULL, 0); item->data = dict; return item; } diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index edbb39c6c..039548130 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -307,7 +307,7 @@ qfs_var_free (void *_v, void *unused) static hashtab_t * qfs_new_vars (void) { - return Hash_NewTable (61, qfs_var_get_key, qfs_var_free, 0); + return Hash_NewTable (61, qfs_var_get_key, qfs_var_free, 0, 0); } static void @@ -549,7 +549,7 @@ qfs_build_gamedir (const char **list) gamedir_t *gamedir; plitem_t *gdpl; dstring_t *path; - hashtab_t *dirs = Hash_NewTable (31, qfs_dir_get_key, qfs_dir_free, 0); + hashtab_t *dirs = Hash_NewTable (31, qfs_dir_get_key, qfs_dir_free, 0, 0); hashtab_t *vars = qfs_new_vars (); const char *dir = 0; diff --git a/libs/util/segtext.c b/libs/util/segtext.c index 742983be1..ffee78d77 100644 --- a/libs/util/segtext.c +++ b/libs/util/segtext.c @@ -140,7 +140,7 @@ Segtext_new (const char *source_string) if (!source_string) return 0; text = new_text (); - text->tab = Hash_NewTable (61, segtext_getkey, 0, 0); + text->tab = Hash_NewTable (61, segtext_getkey, 0, 0, 0); src = strdup (source_string); // The first chunk is special in that it holds the pointer to the copied diff --git a/libs/util/wadfile.c b/libs/util/wadfile.c index 3175f22c7..3d8a709ca 100644 --- a/libs/util/wadfile.c +++ b/libs/util/wadfile.c @@ -86,7 +86,7 @@ wad_new (const char *name) free (wad); return 0; } - wad->lump_hash = Hash_NewTable (1021, 0, 0, 0); + wad->lump_hash = Hash_NewTable (1021, 0, 0, 0, 0); if (!wad->lump_hash) { free (wad->filename); free (wad); diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 6a8ef0268..6d1f14f0b 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -375,7 +375,7 @@ glsl_Draw_Init (void) qpic_t *pic; //FIXME glpic_t *gl; - pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, 0); + pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, 0, 0); QFS_GamedirCallback (Draw_ClearCache); //FIXME temporary work around for the timing of cvar creation and palette //loading diff --git a/libs/video/renderer/glsl/glsl_shader.c b/libs/video/renderer/glsl/glsl_shader.c index d38bb2c29..c45494dc0 100644 --- a/libs/video/renderer/glsl/glsl_shader.c +++ b/libs/video/renderer/glsl/glsl_shader.c @@ -72,7 +72,7 @@ GLSL_RegisterEffect (const char *name, const char *src) segtext_t *text; if (!effect_tab) - effect_tab = Hash_NewTable (61, effect_get_key, 0, 0); + effect_tab = Hash_NewTable (61, effect_get_key, 0, 0, 0); if (Hash_Find (effect_tab, name)) { Sys_Printf ("WARNING: ignoring duplicate '%s' effect\n", name); diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 66ae9072f..aba1de6ea 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -345,7 +345,8 @@ void R_Progs_Init (progs_t *pr) { draw_resources_t *res = calloc (1, sizeof (draw_resources_t)); - res->pic_hash = Hash_NewTable (61, bi_draw_get_key, 0, 0); + res->pic_hash = Hash_NewTable (61, bi_draw_get_key, 0, 0, + pr->hashlink_freelist); PR_Resources_Register (pr, "Draw", res, bi_draw_clear); PR_RegisterBuiltins (pr, builtins); diff --git a/libs/video/targets/old_keys.c b/libs/video/targets/old_keys.c index 99b87f4c4..e96cc02ff 100644 --- a/libs/video/targets/old_keys.c +++ b/libs/video/targets/old_keys.c @@ -233,7 +233,7 @@ OK_Init (void) { old_keyname_t *ok; - old_key_table = Hash_NewTable (1021, ok_get_key, 0, 0); + old_key_table = Hash_NewTable (1021, ok_get_key, 0, 0, 0); for (ok = old_keynames; ok->old_name; ok++) Hash_Add (old_key_table, ok); } diff --git a/qtv/source/client.c b/qtv/source/client.c index d53849f7f..24b0e23b2 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -1204,7 +1204,7 @@ Client_Init (void) { size_t i; - ucmd_table = Hash_NewTable (251, ucmds_getkey, 0, 0); + ucmd_table = Hash_NewTable (251, ucmds_getkey, 0, 0, 0); for (i = 0; i < sizeof (ucmds) / sizeof (ucmds[0]); i++) Hash_Add (ucmd_table, &ucmds[i]); } diff --git a/qtv/source/connection.c b/qtv/source/connection.c index 0ff5d4464..52f159060 100644 --- a/qtv/source/connection.c +++ b/qtv/source/connection.c @@ -79,7 +79,7 @@ connection_compare (const void *_c1, const void *_c2, void *unused) void Connection_Init (void) { - connections = Hash_NewTable (1023, 0, connection_free, 0); + connections = Hash_NewTable (1023, 0, connection_free, 0, 0); Hash_SetHashCompare (connections, connection_get_hash, connection_compare); } diff --git a/qtv/source/server.c b/qtv/source/server.c index c36465d31..855bc492c 100644 --- a/qtv/source/server.c +++ b/qtv/source/server.c @@ -541,7 +541,7 @@ void Server_Init (void) { Sys_RegisterShutdown (server_shutdown, 0); - server_hash = Hash_NewTable (61, server_get_key, server_free, 0); + server_hash = Hash_NewTable (61, server_get_key, server_free, 0, 0); Cmd_AddCommand ("sv_new", sv_new_f, "Add a new server"); Cmd_AddCommand ("sv_del", sv_del_f, "Remove an existing server"); Cmd_AddCommand ("sv_list", sv_list_f, "List available servers"); diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index a6b56c219..b8aa5e8d4 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -2009,7 +2009,7 @@ static builtin_t builtins[] = { void SV_UserInit (void) { - ucmd_table = Hash_NewTable (251, ucmds_getkey, ucmds_free, 0); + ucmd_table = Hash_NewTable (251, ucmds_getkey, ucmds_free, 0, 0); Hash_SetHashCompare (ucmd_table, ucmd_get_hash, ucmd_compare); PR_RegisterBuiltins (&sv_pr_state, builtins); cl_rollspeed = Cvar_Get ("cl_rollspeed", "200", CVAR_NONE, NULL, diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/qwaq-input.c index ba7dca6e9..543971d44 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/qwaq-input.c @@ -323,7 +323,10 @@ parse_key (qwaq_resources_t *res) { qwaq_key_t *key = Hash_Find (res->key_sequences, res->escbuff.str); + //Sys_Printf ("parse_key: %s\n", res->escbuff.str + 1); if (key) { + //Sys_Printf (" %d %03x %s\n", key->key, key->shift, + // Key_KeynumToString (key->key)); key_event (res, key->key, key->shift); } } @@ -417,7 +420,8 @@ void qwaq_input_init (qwaq_resources_t *res) if (res->key_sequences) { Hash_FlushTable (res->key_sequences); } else { - res->key_sequences = Hash_NewTable (127, key_sequence_getkey, 0, 0); + res->key_sequences = Hash_NewTable (127, key_sequence_getkey, 0, 0, + res->pr->hashlink_freelist); } for (size_t i = 0; i < sizeof (default_keys) / sizeof (default_keys[0]); i++) { diff --git a/tools/qfbsp/source/map.c b/tools/qfbsp/source/map.c index f2038e44d..c258b73df 100644 --- a/tools/qfbsp/source/map.c +++ b/tools/qfbsp/source/map.c @@ -97,7 +97,7 @@ FindMiptex (const char *name) if (strcmp (name, "skip") == 0) return TEX_SKIP; if (!miptex_hash) - miptex_hash = Hash_NewTable (1023, miptex_getkey, 0, 0); + miptex_hash = Hash_NewTable (1023, miptex_getkey, 0, 0, 0); if (miptexnames) { index = (intptr_t) Hash_Find (miptex_hash, mpname); if (index) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 6f4473e1d..8b2081e82 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -192,9 +192,10 @@ add_static_instance (const char *class, def_t *instance_def) static_instance_t *instance = malloc (sizeof (*instance)); if (!static_instances) { - static_instances = Hash_NewTable (1021, static_instance_get_key, 0, 0); + static_instances = Hash_NewTable (1021, static_instance_get_key, + 0, 0, 0); static_instance_classes = Hash_NewTable (1021, static_instance_get_key, - 0, 0); + 0, 0, 0); } instance->class = save_string (class); @@ -561,7 +562,7 @@ _get_class (symbol_t *sym, int create) class_t *c; if (!class_hash) - class_hash = Hash_NewTable (1021, class_get_key, 0, 0); + class_hash = Hash_NewTable (1021, class_get_key, 0, 0, 0); if (sym) { c = Hash_Find (class_hash, sym->name); if (c || !create) @@ -1272,7 +1273,7 @@ get_category (symbol_t *class_name, const char *category_name, int create) class_t *class; if (!category_hash) { - category_hash = Hash_NewTable (1021, 0, 0, 0); + category_hash = Hash_NewTable (1021, 0, 0, 0, 0); Hash_SetHashCompare (category_hash, category_get_hash, category_compare); } @@ -1549,7 +1550,7 @@ get_protocol (const char *name, int create) protocol_t *p; if (!protocol_hash) - protocol_hash = Hash_NewTable (1021, protocol_get_key, 0, 0); + protocol_hash = Hash_NewTable (1021, protocol_get_key, 0, 0, 0); if (name) { p = Hash_Find (protocol_hash, name); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index c9e5474a5..234d622d9 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -241,8 +241,8 @@ get_function (const char *name, type_t *type, int overload, int create) overloaded_function_t *func; if (!overloaded_functions) { - overloaded_functions = Hash_NewTable (1021, ol_func_get_key, 0, 0); - function_map = Hash_NewTable (1021, func_map_get_key, 0, 0); + overloaded_functions = Hash_NewTable (1021, ol_func_get_key, 0, 0, 0); + function_map = Hash_NewTable (1021, func_map_get_key, 0, 0, 0); } name = save_string (name); diff --git a/tools/qfcc/source/grab.c b/tools/qfcc/source/grab.c index 520c40492..27f726519 100644 --- a/tools/qfcc/source/grab.c +++ b/tools/qfcc/source/grab.c @@ -105,8 +105,8 @@ do_grab (const char *token) size_t i; initialized = 1; - frame_tab = Hash_NewTable (1021, frame_get_key, frame_free, 0); - grab_tab = Hash_NewTable (1021, frame_get_key, 0, 0); + frame_tab = Hash_NewTable (1021, frame_get_key, frame_free, 0, 0); + grab_tab = Hash_NewTable (1021, frame_get_key, 0, 0, 0); for (i = 0; i < sizeof (grab_list) / sizeof (grab_list[0]); i++) Hash_Add (grab_tab, &grab_list[i]); } diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index de107d1b4..017461de0 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -642,14 +642,14 @@ linker_begin (void) linker_current_file = dstring_newstr (); - extern_data_defs = Hash_NewTable (16381, defs_get_key, 0, 0); - defined_data_defs = Hash_NewTable (16381, defs_get_key, 0, 0); + extern_data_defs = Hash_NewTable (16381, defs_get_key, 0, 0, 0); + defined_data_defs = Hash_NewTable (16381, defs_get_key, 0, 0, 0); - extern_field_defs = Hash_NewTable (16381, defs_get_key, 0, 0); - defined_field_defs = Hash_NewTable (16381, defs_get_key, 0, 0); + extern_field_defs = Hash_NewTable (16381, defs_get_key, 0, 0, 0); + defined_field_defs = Hash_NewTable (16381, defs_get_key, 0, 0, 0); - extern_type_defs = Hash_NewTable (16381, defs_get_key, 0, 0); - defined_type_defs = Hash_NewTable (16381, defs_get_key, 0, 0); + extern_type_defs = Hash_NewTable (16381, defs_get_key, 0, 0, 0); + defined_type_defs = Hash_NewTable (16381, defs_get_key, 0, 0, 0); work_strings = strpool_new (); work_code = codespace_new (); diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index e8e342c7a..458fb00b2 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -113,7 +113,8 @@ new_method (type_t *ret_type, param_t *selector, param_t *opt_params) meth->def = 0; if (!known_methods) - known_methods = Hash_NewTable (1021, method_get_key, method_free, 0); + known_methods = Hash_NewTable (1021, method_get_key, + method_free, 0, 0); Hash_Add (known_methods, meth); return meth; @@ -230,7 +231,7 @@ methodset_t * new_methodset (void) { methodset_t *s = malloc (sizeof (*s)); - s->tab = Hash_NewTable (31, 0, 0, 0); + s->tab = Hash_NewTable (31, 0, 0, 0, 0); Hash_SetHashCompare (s->tab, methodset_get_hash, methodset_compare); return s; } @@ -455,9 +456,9 @@ selector_index (const char *sel_id) selector_t *sel = &_sel; if (!sel_hash) { - sel_hash = Hash_NewTable (1021, 0, 0, 0); + sel_hash = Hash_NewTable (1021, 0, 0, 0, 0); Hash_SetHashCompare (sel_hash, sel_get_hash, sel_compare); - sel_index_hash = Hash_NewTable (1021, 0, 0, 0); + sel_index_hash = Hash_NewTable (1021, 0, 0, 0, 0); Hash_SetHashCompare (sel_index_hash, sel_index_get_hash, sel_index_compare); } diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index bbf10250a..045d14404 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -139,9 +139,9 @@ opcode_init (void) Hash_FlushTable (opcode_type_table); } else { PR_Opcode_Init (); - opcode_type_table = Hash_NewTable (1021, 0, opcode_free, 0); + opcode_type_table = Hash_NewTable (1021, 0, opcode_free, 0, 0); Hash_SetHashCompare (opcode_type_table, get_hash, compare); - opcode_void_table = Hash_NewTable (1021, get_key, 0, 0); + opcode_void_table = Hash_NewTable (1021, get_key, 0, 0, 0); } for (op = pr_opcodes; op->name; op++) { if (op->min_version > options.code.progsversion) diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 9d5c5a1b9..3406380ef 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -439,10 +439,10 @@ keyword_or_id (char *token) if (!keyword_tab) { size_t i; - keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0); - qf_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0); - at_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0); - obj_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0); + keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); + qf_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); + at_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); + obj_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); #define NUMKEYS(_k) (sizeof (_k) / sizeof (_k[0])) diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 02f05bce9..8a8f2ffc0 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -247,7 +247,7 @@ init_qf (void) PR_Init (&pr); - func_tab = Hash_NewTable (1021, 0, 0, 0); + func_tab = Hash_NewTable (1021, 0, 0, 0, 0); Hash_SetHashCompare (func_tab, func_hash, func_compare); } diff --git a/tools/qfcc/source/qp-lex.l b/tools/qfcc/source/qp-lex.l index 423aaf4e0..5947f5846 100644 --- a/tools/qfcc/source/qp-lex.l +++ b/tools/qfcc/source/qp-lex.l @@ -248,7 +248,7 @@ keyword_or_id (const char *token) if (!keyword_tab) { size_t i; - keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0); + keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0, 0); for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++) Hash_Add (keyword_tab, &keywords[i]); } diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index 0b59d5b9d..8fb7642e6 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -63,7 +63,7 @@ strpool_new (void) { strpool_t *strpool = calloc (1, sizeof (strpool_t)); - strpool->str_tab = Hash_NewTable (16381, strpool_get_key, 0, strpool); + strpool->str_tab = Hash_NewTable (16381, strpool_get_key, 0, strpool, 0); strpool->size = 1; strpool->max_size = 16384; strpool->strings = malloc (strpool->max_size); @@ -77,7 +77,7 @@ strpool_build (const char *strings, int size) intptr_t s; strpool_t *strpool = malloc (sizeof (strpool_t)); - strpool->str_tab = Hash_NewTable (16381, strpool_get_key, 0, strpool); + strpool->str_tab = Hash_NewTable (16381, strpool_get_key, 0, strpool, 0); strpool->size = size + (*strings != 0); strpool->max_size = (strpool->size + 16383) & ~16383; strpool->strings = malloc (strpool->max_size); @@ -131,7 +131,7 @@ save_string (const char *str) { char *s; if (!saved_strings) - saved_strings = Hash_NewTable (16381, ss_get_key, 0, 0); + saved_strings = Hash_NewTable (16381, ss_get_key, 0, 0, 0); s = Hash_Find (saved_strings, str); if (s) return s; diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 967a7b73f..88ba6a60e 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -166,7 +166,7 @@ new_switch_block (void) switch_block_t *switch_block = malloc (sizeof (switch_block_t)); SYS_CHECKMEM (switch_block); - switch_block->labels = Hash_NewTable (127, 0, 0, 0); + switch_block->labels = Hash_NewTable (127, 0, 0, 0, 0); Hash_SetHashCompare (switch_block->labels, get_hash, compare); switch_block->test = 0; return switch_block; diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 353e29142..961c00b1a 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -106,7 +106,7 @@ new_symtab (symtab_t *parent, stab_type_e type) symtab->type = type; if (symtab->type == stab_global) tabsize = 1023; - symtab->tab = Hash_NewTable (tabsize, sym_getkey, 0, 0); + symtab->tab = Hash_NewTable (tabsize, sym_getkey, 0, 0, 0); symtab->symtail = &symtab->symbols; return symtab; } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 2ee44db06..3233385bf 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -640,41 +640,47 @@ clear_immediates (void) Hash_FlushTable (integer_imm_defs); Hash_FlushTable (double_imm_defs); } else { - value_table = Hash_NewTable (16381, 0, 0, 0); + value_table = Hash_NewTable (16381, 0, 0, 0, 0); Hash_SetHashCompare (value_table, value_get_hash, value_compare); - string_imm_defs = Hash_NewTable (16381, 0, imm_free, &string_imm_defs); + string_imm_defs = Hash_NewTable (16381, 0, imm_free, + &string_imm_defs, 0); Hash_SetHashCompare (string_imm_defs, imm_get_hash, imm_compare); - float_imm_defs = Hash_NewTable (16381, 0, imm_free, &float_imm_defs); + float_imm_defs = Hash_NewTable (16381, 0, imm_free, + &float_imm_defs, 0); Hash_SetHashCompare (float_imm_defs, imm_get_hash, imm_compare); - vector_imm_defs = Hash_NewTable (16381, 0, imm_free, &vector_imm_defs); + vector_imm_defs = Hash_NewTable (16381, 0, imm_free, + &vector_imm_defs, 0); Hash_SetHashCompare (vector_imm_defs, imm_get_hash, imm_compare); - entity_imm_defs = Hash_NewTable (16381, 0, imm_free, &entity_imm_defs); + entity_imm_defs = Hash_NewTable (16381, 0, imm_free, + &entity_imm_defs, 0); Hash_SetHashCompare (entity_imm_defs, imm_get_hash, imm_compare); - field_imm_defs = Hash_NewTable (16381, 0, imm_free, &field_imm_defs); + field_imm_defs = Hash_NewTable (16381, 0, imm_free, + &field_imm_defs, 0); Hash_SetHashCompare (field_imm_defs, imm_get_hash, imm_compare); - func_imm_defs = Hash_NewTable (16381, 0, imm_free, &func_imm_defs); + func_imm_defs = Hash_NewTable (16381, 0, imm_free, + &func_imm_defs, 0); Hash_SetHashCompare (func_imm_defs, imm_get_hash, imm_compare); - pointer_imm_defs = - Hash_NewTable (16381, 0, imm_free, &pointer_imm_defs); + pointer_imm_defs = Hash_NewTable (16381, 0, imm_free, + &pointer_imm_defs, 0); Hash_SetHashCompare (pointer_imm_defs, imm_get_hash, imm_compare); - quaternion_imm_defs = - Hash_NewTable (16381, 0, imm_free, &quaternion_imm_defs); + quaternion_imm_defs = Hash_NewTable (16381, 0, imm_free, + &quaternion_imm_defs, 0); Hash_SetHashCompare (quaternion_imm_defs, imm_get_hash, imm_compare); - integer_imm_defs = - Hash_NewTable (16381, 0, imm_free, &integer_imm_defs); + integer_imm_defs = Hash_NewTable (16381, 0, imm_free, + &integer_imm_defs, 0); Hash_SetHashCompare (integer_imm_defs, imm_get_hash, imm_compare); - double_imm_defs = - Hash_NewTable (16381, 0, imm_free, &double_imm_defs); + double_imm_defs = Hash_NewTable (16381, 0, imm_free, + &double_imm_defs, 0); Hash_SetHashCompare (double_imm_defs, imm_get_hash, imm_compare); } From 585b33c111cf18f3a1ad896dbc657d5382fbe0e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 16:18:14 +0900 Subject: [PATCH 0867/3664] [qwaq] Close up race-condition hole After a lot of thought, I have come to the conclusion that the weird crash the other day was caused by a race while the command ring buffer had just been emptied: the command submission code opened up space for writing, threads switched, and command processing saw the available data and pounced on it before the submit code could write valid data. Thus include the while header in the lock, and move the loop-end release outside the lock. It may be a little confusing, but it seems to work. --- ruamoko/qwaq/qwaq-curses.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index 8c1d30c7d..d83f59c15 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -640,10 +640,14 @@ process_commands (qwaq_resources_t *res) ret = pthread_cond_timedwait (&res->command_cond.rcond, &res->command_cond.mut, &timeout); } - pthread_mutex_unlock (&res->command_cond.mut); - + // The mutex is unlocked at the top of the loop and locked again + // (for broadcast) at the bottom, then finally unlocked after the loop. + // It should be only the data availability check that's not threadsafe + // as the mutex is not released until after the data has been written to + // the buffer. while ((avail = RB_DATA_AVAILABLE (res->command_queue)) >= 2 && avail >= (len = RB_PEEK_DATA (res->command_queue, 1))) { + pthread_mutex_unlock (&res->command_cond.mut); dump_command (res, len); qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); switch (cmd) { @@ -738,8 +742,10 @@ process_commands (qwaq_resources_t *res) pthread_mutex_lock (&res->command_cond.mut); RB_DROP_DATA (res->command_queue, len); pthread_cond_broadcast (&res->command_cond.wcond); - pthread_mutex_unlock (&res->command_cond.mut); + // unlocked at top of top if there's more data, otherwise just after + // the loop } + pthread_mutex_unlock (&res->command_cond.mut); } static int From 7b9177ec568fd139c84829b78572fc650e6dc11c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 17:29:08 +0900 Subject: [PATCH 0868/3664] [qwaq] Extract the double-clicked word The plan is to use it for variable lookups etc. --- ruamoko/qwaq/qwaq-debugger.r | 6 +++- ruamoko/qwaq/qwaq-editbuffer-bi.c | 35 +++++++++++++++++++++ ruamoko/qwaq/qwaq-editbuffer.h | 1 + ruamoko/qwaq/qwaq-editbuffer.r | 1 + ruamoko/qwaq/qwaq-editor.h | 1 + ruamoko/qwaq/qwaq-editor.r | 51 +++++++++++++++++++++++++------ 6 files changed, 84 insertions(+), 11 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index 7000836c0..db5e78eb0 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -79,8 +79,12 @@ -(void)key_event: (ed_event_t *)_event { + Editor *file = _event.editor; qwaq_event_t *event = _event.event; - if (event.what == qe_keydown) { + if (event.what == qe_mouseclick) { + printf ("%s\n", [file getWordAt: {event.mouse.x, event.mouse.y}]); + [source_window redraw]; + } else if (event.what == qe_keydown) { switch (event.key.code) { case QFK_F7: qdb_set_trace (debug_target, 1); diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/qwaq-editbuffer-bi.c index 02ae29370..9f457bf10 100644 --- a/ruamoko/qwaq/qwaq-editbuffer-bi.c +++ b/ruamoko/qwaq/qwaq-editbuffer-bi.c @@ -277,6 +277,25 @@ getEOL (txtbuffer_t *buffer, unsigned ptr) return ptr; } +static always_inline void +readString (txtbuffer_t *buffer, eb_sel_t *sel, char *str) +{ + unsigned start = sel->start; + unsigned length = sel->length; + unsigned end = sel->start + sel->length; + const char *ptr = buffer->text + spanGap (buffer, start); + if ((start < buffer->gapOffset && end <= buffer->gapOffset) + || start > buffer->gapOffset) { + memcpy (str, ptr, length); + } else { + length = buffer->gapOffset - start; + memcpy (str, ptr, length); + str += length; + ptr += length + buffer->gapOffset; + memcpy (str, ptr, sel->length - length); + } +} + static always_inline unsigned getBOL (txtbuffer_t *buffer, unsigned ptr) { @@ -773,6 +792,21 @@ bi_i_EditBuffer__getEOT (progs_t *pr) R_INT (pr) = buffer->txtbuffer->textSize; } +static void +bi_i_EditBuffer__readString_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); + + char *str = alloca (selection->length + 1); + str[selection->length] = 0; + readString (buffer->txtbuffer, selection, str); + + RETURN_STRING (pr, str); +} + static void bi_i_EditBuffer__countLines_ (progs_t *pr) { @@ -901,6 +935,7 @@ static builtin_t builtins[] = { {"_i_EditBuffer__getEOL_", bi_i_EditBuffer__getEOL_, -1}, {"_i_EditBuffer__getBOT", bi_i_EditBuffer__getBOT, -1}, {"_i_EditBuffer__getEOT", bi_i_EditBuffer__getEOT, -1}, + {"_i_EditBuffer__readString_", bi_i_EditBuffer__readString_, -1}, {"_i_EditBuffer__countLines_", bi_i_EditBuffer__countLines_, -1}, {"_i_EditBuffer__search_for_direction_", bi_i_EditBuffer__search_for_direction_, -1}, diff --git a/ruamoko/qwaq/qwaq-editbuffer.h b/ruamoko/qwaq/qwaq-editbuffer.h index 4e5062ab2..ad2e6084e 100644 --- a/ruamoko/qwaq/qwaq-editbuffer.h +++ b/ruamoko/qwaq/qwaq-editbuffer.h @@ -49,6 +49,7 @@ typedef struct eb_color_s { - (unsigned) getEOL: (unsigned) linePtr; - (unsigned) getBOT; - (unsigned) getEOT; +- (string) readString: (eb_sel_t) selection; - (unsigned) countLines: (eb_sel_t) selection; - (eb_sel_t) search: (eb_sel_t) selection diff --git a/ruamoko/qwaq/qwaq-editbuffer.r b/ruamoko/qwaq/qwaq-editbuffer.r index ce12a6edf..d0900a108 100644 --- a/ruamoko/qwaq/qwaq-editbuffer.r +++ b/ruamoko/qwaq/qwaq-editbuffer.r @@ -26,6 +26,7 @@ - (unsigned) getEOL: (unsigned) linePtr = #0; - (unsigned) getBOT = #0; - (unsigned) getEOT = #0; +- (string) readString: (eb_sel_t) selection = #0; - (unsigned) countLines: (eb_sel_t) selection = #0; - (eb_sel_t) search: (eb_sel_t) selection diff --git a/ruamoko/qwaq/qwaq-editor.h b/ruamoko/qwaq/qwaq-editor.h index 29bf1c8b7..b861e15ad 100644 --- a/ruamoko/qwaq/qwaq-editor.h +++ b/ruamoko/qwaq/qwaq-editor.h @@ -41,6 +41,7 @@ typedef struct ed_event_s { -recenter:(int) force; -gotoLine:(unsigned) line; -highlightLine; +-(string)getWordAt:(Point) pos; // view relative coordinates @end #endif//__qwaq_editor_h diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index dfd863569..6bf9e3389 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -51,38 +51,57 @@ return self; } --handleEvent:(qwaq_event_t *) event +static int handleEvent (Editor *self, qwaq_event_t *event) { - // give any listeners a chance to override or extend event handling - _event.editor = self; - _event.event = event; - [onEvent respond: &_event]; if (event.what & qe_mouse) { if (event.what == qe_mouseclick) { if (event.mouse.buttons & (1 << 3)) { [self scrollUp: 1]; + return 1; } if (event.mouse.buttons & (1 << 4)) { [self scrollDown: 1]; + return 1; } if (event.mouse.buttons & (1 << 5)) { [self scrollLeft: 1]; + return 1; } if (event.mouse.buttons & (1 << 6)) { [self scrollRight: 1]; + return 1; } } } else if (event.what == qe_keydown) { switch (event.key.code) { case QFK_PAGEUP: - [self scrollUp: ylen]; - break; + [self scrollUp: self.ylen]; + return 1; case QFK_PAGEDOWN: - [self scrollDown: ylen]; - break; + [self scrollDown: self.ylen]; + return 1; } } - event.what = qe_none; + return 0; +} + +-handleEvent:(qwaq_event_t *) event +{ + // give any listeners a chance to override or extend event handling + _event.editor = self; + _event.event = event; + if (event.what & qe_positional) { + event.mouse.x -= xpos; + event.mouse.y -= ypos; + } + [onEvent respond: &_event]; + if (handleEvent (self, event)) { + event.what = qe_none; + } + if (event.what & qe_positional) { + event.mouse.x += xpos; + event.mouse.y += ypos; + } return self; } @@ -174,4 +193,16 @@ return self; } +-(string)getWordAt:(Point) pos +{ + if (pos.x < 0 || pos.y < 0 || pos.x >= xlen || pos.y >= ylen) { + return nil; + } + pos.x += scroll.x; + unsigned lind = [buffer nextLine:base_index :pos.y]; + unsigned cind = [buffer charPtr:lind at:pos.x]; + eb_sel_t word = [buffer getWord: cind]; + return [buffer readString:word]; +} + @end From 6f7ddf52acf67a60e296d4ac5e847da95e2304a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 18:28:28 +0900 Subject: [PATCH 0869/3664] [gamecode] Add an exit debug event type The VM never sends it because it cannot know if its exit is program exit or just sub-program exit, but it's available for host systems to send. --- include/QF/progs.h | 1 + ruamoko/qwaq/main.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 841b586d3..a42ae8f1f 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1695,6 +1695,7 @@ typedef enum { prd_trace, prd_breakpoint, prd_watchpoint, + prd_exit, // not sent by VM prd_runerror, prd_error, // lower level error thann prd_runerror } prdebug_t; diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 87df0a035..46e1d8e4b 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -232,6 +232,9 @@ run_progs (void *data) PR_ExecuteProgram (thread->pr, thread->main_func); PR_PopFrame (thread->pr); + if (thread->pr->debug_handler) { + thread->pr->debug_handler (prd_exit, thread->pr->debug_data); + } thread->return_code = R_INT (thread->pr); return thread; } From 1f8cc7186c61c9212c799dbac6299b9e522b3714 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 21:04:22 +0900 Subject: [PATCH 0870/3664] [qfcc] Hide "function" type behind an @ I'm not sure it's all that useful and thus it clutters the namespace. --- ruamoko/lib/Entity.r | 4 ++-- tools/qfcc/source/qc-lex.l | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ruamoko/lib/Entity.r b/ruamoko/lib/Entity.r index 474bc3db1..e2ea25000 100644 --- a/ruamoko/lib/Entity.r +++ b/ruamoko/lib/Entity.r @@ -9,7 +9,7 @@ typedef void () void_function; int PR_SetField (entity ent, string field, string value) = #0; -function PR_FindFunction (string func) = #0; +@function PR_FindFunction (string func) = #0; @static void ParseEntities (string ent_data); @@ -66,7 +66,7 @@ function PR_FindFunction (string func) = #0; local int count; local string field, value; local plitem_t keys; - local function func; + local @function func; local Entity *e; classname = PL_String (PL_ObjectForKey (dict, "classname")); diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 3406380ef..cccc43afd 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -378,8 +378,8 @@ static keyword_t qf_keywords[] = { {"double", TYPE, &type_double}, {"int", TYPE, &type_integer }, {"unsigned", TYPE, &type_integer },//FIXME - {"function", TYPE, &type_function }, + {"@function", TYPE, &type_function }, {"@args", ARGS, 0 }, {"@va_list", TYPE, &type_va_list }, {"@param", TYPE, &type_param }, From 48f737ecb6e49b47c0db09c9f98d05e4f566104f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 21:05:25 +0900 Subject: [PATCH 0871/3664] [gamecode] Tweak types in dfunction_t Mostly minor corrections to make more sense when reading them. --- include/QF/pr_comp.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 3c6ccc8fe..a84e56953 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -457,13 +457,13 @@ typedef struct dparmsize_s { typedef struct dfunction_s { pr_int_t first_statement; // negative numbers are builtins - pr_int_t parm_start; + pr_uint_t parm_start; pr_uint_t locals; // total ints of parms + locals pr_uint_t profile; // runtime string_t s_name; - pr_int_t s_file; // source file defined in + string_t s_file; // source file defined in pr_int_t numparms; dparmsize_t parm_size[MAX_PARMS]; From 52dcb0a6e21ca21993a17d2b8df0c44494306885 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 22:36:04 +0900 Subject: [PATCH 0872/3664] [gamecode] Add G_PACKED macro Not sure when I'll use it, but as it avoids the null pointer check, it should make for faster access to structs when reading or writing multiple fields. --- include/QF/progs.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index a42ae8f1f..3cd6a5c6c 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -362,6 +362,21 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define G_var(p,o,t) ((p)->pr_globals[o].t##_var) +/** Access a global as an arbitray type. + + More direct than G_STRUCT + \par QC type: + \c struct etc small enough to fit in a single parameter + \param p pointer to ::progs_t VM struct + \param t C type of the structure + \param o offset into global data space + \return structure lvalue. use & to make a pointer of the + appropriate type. + + \hideinitializer +*/ +#define G_PACKED(p,t,o) (*(t *) &(p)->pr_globals[o]) + /** Access a float global. Can be assigned to. \par QC type: From 513bb868fc784ece78e72b66f13cdf6e42363a26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 22:37:38 +0900 Subject: [PATCH 0873/3664] [qfcc] Remove unsigned define I had forgotten that qfcc supports the keyword, just not the type yet. --- ruamoko/qwaq/qwaq-debug.h | 5 ++--- ruamoko/qwaq/qwaq-editbuffer.h | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h index 0eb13d4a5..11d6d6555 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/qwaq-debug.h @@ -9,9 +9,8 @@ typedef enum { #ifdef __QFCC__ -//FIXME add unsigned to qfcc -#ifndef unsigned -#define unsigned int +//FIXME finish unsigned in qfcc +#ifndef umax #define umax 0x7fffffff #endif diff --git a/ruamoko/qwaq/qwaq-editbuffer.h b/ruamoko/qwaq/qwaq-editbuffer.h index ad2e6084e..67976d244 100644 --- a/ruamoko/qwaq/qwaq-editbuffer.h +++ b/ruamoko/qwaq/qwaq-editbuffer.h @@ -4,9 +4,8 @@ #ifdef __QFCC__ #include -//FIXME add unsigned to qfcc -#ifndef unsigned -#define unsigned int +//FIXME finish unsigned in qfcc +#ifndef umax #define umax 0x7fffffff #endif From 3ea16c2764ce2c4af1f1152e298559f2b69519d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Mar 2020 22:39:17 +0900 Subject: [PATCH 0874/3664] [qwaq] Add support for getting data, defs and functions This will allow for really probing the target progs. --- ruamoko/qwaq/qwaq-debug.c | 150 +++++++++++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-debug.h | 34 ++++++++ ruamoko/qwaq/qwaq-debugger.r | 8 ++ 3 files changed, 192 insertions(+) diff --git a/ruamoko/qwaq/qwaq-debug.c b/ruamoko/qwaq/qwaq-debug.c index ea40ab2e4..fd63fc8aa 100644 --- a/ruamoko/qwaq/qwaq-debug.c +++ b/ruamoko/qwaq/qwaq-debug.c @@ -294,6 +294,150 @@ qdb_get_state (progs_t *pr) R_PACKED (pr, qdb_state_t) = state; } +static void +qdb_get_data (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + pointer_t srcoff = P_POINTER (pr, 1); + unsigned length = P_UINT (pr, 2); + pointer_t dstoff = P_POINTER(pr, 3); + + pr_type_t *src = PR_GetPointer(tpr, srcoff); + pr_type_t *dst = PR_GetPointer(pr, dstoff); + + if (srcoff >= tpr->globals_size || srcoff + length >= tpr->globals_size) { + R_INT (pr) = -1; + return; + } + if (dstoff >= pr->globals_size || dstoff + length >= pr->globals_size) { + R_INT (pr) = -1; + return; + } + memcpy (dst, src, length * sizeof (pr_type_t)); + R_INT (pr) = 0; +} + +static void +qdb_find_global (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + const char *name = P_GSTRING (pr, 1); + pr_def_t *def = PR_FindGlobal (tpr, name); + + if (def) { + R_PACKED (pr, qdb_def_t).type_size = (def->size << 16) | def->type; + R_PACKED (pr, qdb_def_t).offset = def->ofs; + R_PACKED (pr, qdb_def_t).name = def->name; + R_PACKED (pr, qdb_def_t).type_encoding = def->type_encoding; + } else { + memset (&R_PACKED (pr, qdb_def_t), 0, sizeof (qdb_def_t)); + } +} + +static void +qdb_find_field (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + const char *name = P_GSTRING (pr, 1); + pr_def_t *def = PR_FindField (tpr, name); + + if (def) { + R_PACKED (pr, qdb_def_t).type_size = (def->size << 16) | def->type; + R_PACKED (pr, qdb_def_t).offset = def->ofs; + R_PACKED (pr, qdb_def_t).name = def->name; + R_PACKED (pr, qdb_def_t).type_encoding = def->type_encoding; + } else { + memset (&R_PACKED (pr, qdb_def_t), 0, sizeof (qdb_def_t)); + } +} + +static void +qdb_find_function (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + const char *name = P_GSTRING (pr, 1); + dfunction_t *func = PR_FindFunction (tpr, name); + + R_INT (pr) = 0; + if (func) { + __auto_type f + = (qdb_function_t *) PR_Zone_Malloc (pr, sizeof (qdb_function_t)); + f->staddr = func->first_statement; + f->local_data = func->parm_start; + f->local_size = func->locals; + f->profile = func->profile; + f->name = func->s_name; + f->file = func->s_file; + f->num_params = func->numparms; + R_INT (pr) = PR_SetPointer (pr, f); + } +} + +static void +qdb_find_auxfunction (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + const char *name = P_GSTRING (pr, 1); + dfunction_t *func = PR_FindFunction (tpr, name); + size_t fnum = func - tpr->pr_functions; + pr_auxfunction_t *aux_func = PR_Debug_MappedAuxFunction (tpr, fnum); + + R_INT (pr) = 0; + if (aux_func) { + __auto_type f + = (qdb_auxfunction_t *) PR_Zone_Malloc (pr, + sizeof (qdb_auxfunction_t)); + f->function = aux_func->function; + f->source_line = aux_func->source_line; + f->line_info = aux_func->line_info; + f->local_defs = aux_func->local_defs; + f->num_locals = aux_func->num_locals; + f->return_type = aux_func->return_type; + R_INT (pr) = PR_SetPointer (pr, f); + } +} + +static void +qdb_get_local_defs (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + size_t fnum = P_UINT (pr, 1); + pr_auxfunction_t *auxfunc = PR_Debug_MappedAuxFunction (tpr, fnum); + + R_INT (pr) = 0; + if (auxfunc) { + pr_def_t *defs = PR_Debug_LocalDefs (tpr, auxfunc); + __auto_type qdefs + = (qdb_def_t *) PR_Zone_Malloc (pr, + auxfunc->num_locals * sizeof (qdb_def_t)); + for (unsigned i = 0; i < auxfunc->num_locals; i++) { + qdefs[i].type_size = (defs[i].size << 16) | defs[i].type; + qdefs[i].offset = defs[i].ofs; + qdefs[i].name = defs[i].name; + qdefs[i].type_encoding = defs[i].type_encoding; + } + R_INT (pr) = PR_SetPointer (pr, qdefs); + } +} + static builtin_t builtins[] = { {"qdb_set_trace", qdb_set_trace, -1}, {"qdb_set_breakpoint", qdb_set_breakpoint, -1}, @@ -302,6 +446,12 @@ static builtin_t builtins[] = { {"qdb_clear_watchpoint", qdb_clear_watchpoint, -1}, {"qdb_continue", qdb_continue, -1}, {"qdb_get_state", qdb_get_state, -1}, + {"qdb_get_data", qdb_get_data, -1}, + {"qdb_find_global", qdb_find_global, -1}, + {"qdb_find_field", qdb_find_field, -1}, + {"qdb_find_function", qdb_find_function, -1}, + {"qdb_find_auxfunction", qdb_find_auxfunction, -1}, + {"qdb_get_local_defs", qdb_get_local_defs, -1}, {} }; diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h index 11d6d6555..60d2952d8 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/qwaq-debug.h @@ -25,6 +25,32 @@ typedef struct qdb_state_s { unsigned line; } qdb_state_t; +typedef struct qdb_def_s { + unsigned type_size; // type in lower 16, size in upper 16 + unsigned offset; + string_t name; + unsigned type_encoding; +} qdb_def_t; + +typedef struct qdb_function_s { + int staddr; + unsigned local_data; + unsigned local_size; + unsigned profile; + string_t name; + string_t file; + unsigned num_params; +} qdb_function_t; + +typedef struct qdb_auxfunction_s { + unsigned function; + unsigned source_line; + unsigned line_info; + unsigned local_defs; + unsigned num_locals; + unsigned return_type; +} qdb_auxfunction_t; + #ifdef __QFCC__ typedef struct qdb_target_s { int handle; } qdb_target_t; @@ -36,6 +62,14 @@ typedef struct qdb_target_s { int handle; } qdb_target_t; @extern int qdb_clear_watchpoint (qdb_target_t target); @extern int qdb_continue (qdb_target_t target); @extern qdb_state_t qdb_get_state (qdb_target_t target); +@extern int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, + void *dst); +@extern qdb_def_t qdb_find_global (qdb_target_t target, string name); +@extern qdb_def_t qdb_find_field (qdb_target_t target, string name); +@extern qdb_function_t *qdb_find_function (qdb_target_t target, string name); +@extern qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, + string name); +@extern qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum); #else//GCC diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index db5e78eb0..3a927e873 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -115,3 +115,11 @@ int qdb_set_watchpoint (qdb_target_t target, unsigned offset) = #0; int qdb_clear_watchpoint (qdb_target_t target) = #0; int qdb_continue (qdb_target_t target) = #0; qdb_state_t qdb_get_state (qdb_target_t target) = #0; +int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, + void *dst) = #0; +qdb_def_t qdb_find_global (qdb_target_t target, string name) = #0; +qdb_def_t qdb_find_field (qdb_target_t target, string name) = #0; +qdb_function_t *qdb_find_function (qdb_target_t target, string name) = #0; +qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, + string name) = #0; +qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum) = #0; From 115541877a8a1ab83a5de079b9d9087e2fefee51 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 09:01:39 +0900 Subject: [PATCH 0875/3664] [qwaq] Set up an application color palette Nothing special, just all the combinations of the 8 colors --- ruamoko/qwaq/qwaq-app.h | 2 ++ ruamoko/qwaq/qwaq-app.r | 12 +++++++----- ruamoko/qwaq/qwaq-editor.r | 5 +++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index 3facb0bc6..36cb41cef 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -11,6 +11,8 @@ @class TextContext; @class View; +extern int color_palette[64]; + @interface QwaqApplication: Object { qwaq_event_t event; diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 7a9e6ed97..19c9740c1 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -10,6 +10,8 @@ int fence; #include "qwaq-group.h" #include "qwaq-view.h" +int color_palette[64]; + static AutoreleasePool *autorelease_pool; static void arp_start (void) @@ -37,16 +39,16 @@ arp_end (void) } initialize (); - init_pair (1, COLOR_WHITE, COLOR_BLUE); - init_pair (2, COLOR_WHITE, COLOR_BLACK); - init_pair (3, COLOR_BLACK, COLOR_GREEN); - init_pair (4, COLOR_YELLOW, COLOR_RED); + for (int i = 1; i < 64; i++) { + init_pair (i, i & 0x7, i >> 3); + color_palette[i] = COLOR_PAIR (i); + } screen = [TextContext screen]; screenSize = [screen size]; objects = [[Group alloc] initWithContext: screen owner: nil]; - [screen bkgd: COLOR_PAIR (1)]; + [screen bkgd: color_palette[047]]; [screen scrollok: 1]; [screen clear]; wrefresh (stdscr);//FIXME diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 6bf9e3389..770b4158d 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -1,5 +1,5 @@ #include -#include "color.h" +#include "qwaq-app.h" #include "qwaq-editor.h" #include "qwaq-listener.h" @@ -37,7 +37,8 @@ int *lbuf = [linebuffer buffer]; for (int y = 0; y < ylen; y++) { lind = [buffer formatLine:lind from:scroll.x into:lbuf width:xlen - highlight:selection colors: {COLOR_PAIR (1), COLOR_PAIR(2)}]; + highlight:selection colors: {color_palette[047], + color_palette[007]}]; [textContext blitFromBuffer: linebuffer to: {xpos, ypos + y} from: [linebuffer rect]]; } From e579ffcb00b834f654f6db2a3e2722b9b9b87cae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 09:03:44 +0900 Subject: [PATCH 0876/3664] [qwaq] Add functions to get functions by number --- ruamoko/qwaq/qwaq-debug.c | 92 +++++++++++++++++++++++++++--------- ruamoko/qwaq/qwaq-debug.h | 3 ++ ruamoko/qwaq/qwaq-debugger.r | 3 ++ 3 files changed, 75 insertions(+), 23 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debug.c b/ruamoko/qwaq/qwaq-debug.c index fd63fc8aa..40effa817 100644 --- a/ruamoko/qwaq/qwaq-debug.c +++ b/ruamoko/qwaq/qwaq-debug.c @@ -361,15 +361,8 @@ qdb_find_field (progs_t *pr) } static void -qdb_find_function (progs_t *pr) +return_function (progs_t *pr, dfunction_t *func) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); - qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); - progs_t *tpr = target->pr; - const char *name = P_GSTRING (pr, 1); - dfunction_t *func = PR_FindFunction (tpr, name); - R_INT (pr) = 0; if (func) { __auto_type f @@ -385,6 +378,53 @@ qdb_find_function (progs_t *pr) } } +static void +qdb_find_function (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + const char *name = P_GSTRING (pr, 1); + dfunction_t *func = PR_FindFunction (tpr, name); + + return_function (pr, func); +} + +static void +qdb_get_function (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + pr_uint_t fnum = P_INT (pr, 1); + dfunction_t *func = tpr->pr_functions + fnum; + + if (fnum >= tpr->progs->numfunctions) { + func = 0; + } + return_function (pr, func); +} + +static void +return_auxfunction (progs_t *pr, pr_auxfunction_t *auxfunc) +{ + R_INT (pr) = 0; + if (auxfunc) { + __auto_type f + = (qdb_auxfunction_t *) PR_Zone_Malloc (pr, + sizeof (qdb_auxfunction_t)); + f->function = auxfunc->function; + f->source_line = auxfunc->source_line; + f->line_info = auxfunc->line_info; + f->local_defs = auxfunc->local_defs; + f->num_locals = auxfunc->num_locals; + f->return_type = auxfunc->return_type; + R_INT (pr) = PR_SetPointer (pr, f); + } +} + static void qdb_find_auxfunction (progs_t *pr) { @@ -394,22 +434,26 @@ qdb_find_auxfunction (progs_t *pr) progs_t *tpr = target->pr; const char *name = P_GSTRING (pr, 1); dfunction_t *func = PR_FindFunction (tpr, name); - size_t fnum = func - tpr->pr_functions; - pr_auxfunction_t *aux_func = PR_Debug_MappedAuxFunction (tpr, fnum); + pr_uint_t fnum = func - tpr->pr_functions; + pr_auxfunction_t *auxfunc = PR_Debug_MappedAuxFunction (tpr, fnum); - R_INT (pr) = 0; - if (aux_func) { - __auto_type f - = (qdb_auxfunction_t *) PR_Zone_Malloc (pr, - sizeof (qdb_auxfunction_t)); - f->function = aux_func->function; - f->source_line = aux_func->source_line; - f->line_info = aux_func->line_info; - f->local_defs = aux_func->local_defs; - f->num_locals = aux_func->num_locals; - f->return_type = aux_func->return_type; - R_INT (pr) = PR_SetPointer (pr, f); + if (fnum >= tpr->progs->numfunctions) { + func = 0; } + return_auxfunction (pr, auxfunc); +} + +static void +qdb_get_auxfunction (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + pr_uint_t fnum = P_UINT (pr, 1); + pr_auxfunction_t *auxfunc = PR_Debug_MappedAuxFunction (tpr, fnum); + + return_auxfunction (pr, auxfunc); } static void @@ -419,7 +463,7 @@ qdb_get_local_defs (progs_t *pr) pointer_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; - size_t fnum = P_UINT (pr, 1); + pr_uint_t fnum = P_UINT (pr, 1); pr_auxfunction_t *auxfunc = PR_Debug_MappedAuxFunction (tpr, fnum); R_INT (pr) = 0; @@ -450,7 +494,9 @@ static builtin_t builtins[] = { {"qdb_find_global", qdb_find_global, -1}, {"qdb_find_field", qdb_find_field, -1}, {"qdb_find_function", qdb_find_function, -1}, + {"qdb_get_function", qdb_get_function, -1}, {"qdb_find_auxfunction", qdb_find_auxfunction, -1}, + {"qdb_get_auxfunction", qdb_get_auxfunction, -1}, {"qdb_get_local_defs", qdb_get_local_defs, -1}, {} }; diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h index 60d2952d8..302f9cd6e 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/qwaq-debug.h @@ -67,8 +67,11 @@ typedef struct qdb_target_s { int handle; } qdb_target_t; @extern qdb_def_t qdb_find_global (qdb_target_t target, string name); @extern qdb_def_t qdb_find_field (qdb_target_t target, string name); @extern qdb_function_t *qdb_find_function (qdb_target_t target, string name); +@extern qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum); @extern qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, string name); +@extern qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, + unsigned fnum); @extern qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum); #else//GCC diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index 3a927e873..e1c014dff 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -120,6 +120,9 @@ int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, qdb_def_t qdb_find_global (qdb_target_t target, string name) = #0; qdb_def_t qdb_find_field (qdb_target_t target, string name) = #0; qdb_function_t *qdb_find_function (qdb_target_t target, string name) = #0; +qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum) = #0; qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, string name) = #0; +qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, + unsigned fnum) = #0; qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum) = #0; From 22d173068b4be7301452261291ba25ecf0406708 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 09:04:31 +0900 Subject: [PATCH 0877/3664] [qwaq] Make a start on a locals viewer It's just a data dump for now. Also, found a bug... --- ruamoko/qwaq/qwaq-debugger.h | 12 +++++++- ruamoko/qwaq/qwaq-debugger.r | 59 ++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-debugger.h b/ruamoko/qwaq/qwaq-debugger.h index 2a1e3a2b3..513ae211b 100644 --- a/ruamoko/qwaq/qwaq-debugger.h +++ b/ruamoko/qwaq/qwaq-debugger.h @@ -12,11 +12,21 @@ @interface Debugger : Object { + qdb_target_t debug_target; + Window *source_window; ProxyView *file_proxy; Array *files; Editor *current_file; - qdb_target_t debug_target; + + Window *locals_window; + View *locals_view; + + unsigned current_fnum; + qdb_function_t *func; + qdb_auxfunction_t *aux_func; + qdb_def_t *local_defs; + void *local_data; } -(qdb_target_t)debug_target; -initWithTarget:(qdb_target_t) target; diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index e1c014dff..a90eb1216 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -58,6 +58,13 @@ [source_window insertSelected: (View *) file_proxy]; [source_window setTitle: [current_file filename]]; [source_window redraw]; + + locals_window = [[Window alloc] initWithRect: {{0, 0}, {40, 10}}]; + [locals_window setBackground: color_palette[064]]; + [locals_window setTitle: "Locals"]; + locals_view = [[View alloc] initWithRect: {{1, 1}, {38, 8}}]; + [locals_window insertSelected: locals_view]; + [application addView: locals_window]; } -(void) show_line @@ -77,6 +84,57 @@ [source_window redraw]; } +static void +update_current_func (Debugger *self, unsigned fnum) +{ + self.current_fnum = fnum; + if (self.aux_func) { + obj_free (self.aux_func); + self.aux_func = nil; + } + if (self.local_defs) { + obj_free (self.local_defs); + } + if (self.local_data) { + obj_free (self.local_data); + } + self.func = qdb_get_function (self.debug_target, fnum); + self.aux_func = qdb_get_auxfunction (self.debug_target, fnum); + if (self.aux_func) { + self.local_defs = qdb_get_local_defs (self.debug_target, fnum); + } + if (self.func) { + self.local_data = obj_malloc (self.func.local_size); + } +} + +void traceon() = #0; + +-(void)update_watchvars +{ + qdb_state_t state = qdb_get_state (debug_target); + if (state.func != current_fnum) { + update_current_func (self, state.func); + } + if (!local_data) { + return; + } + qdb_get_data (debug_target, func.local_data, func.local_size, local_data); + [locals_view mvprintf:{0,0}, "%d", func.local_size]; + for (int y = 1; y < [locals_view size].height; y++) { + unsigned ind = (y - 1) * 4; + if (ind < func.local_size) { + [locals_view mvprintf:{0, y}, "%02x", ind]; + for (int x = 0; x < 4 && ind < func.local_size; x++, ind++) { + [locals_view mvprintf:{x * 9 + 3, y}, "%08x", local_data[ind]]; + } + } else { + break; + } + } + [TextContext refresh]; +} + -(void)key_event: (ed_event_t *)_event { Editor *file = _event.editor; @@ -103,6 +161,7 @@ [self setup]; } [self show_line]; + [self update_watchvars]; return self; } From fd73daea4b5e5ff167855b28b5d558aab7d6295c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 09:07:19 +0900 Subject: [PATCH 0878/3664] [qwaq] Correct mangled params to qwaq_mvwvprintf --- ruamoko/qwaq/qwaq-curses.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index d83f59c15..d25604135 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -158,7 +158,8 @@ get_window (qwaq_resources_t *res, const char *name, int handle) window_t *window = window_get (res, handle); if (!window || !window->win) { - PR_RunError (res->pr, "invalid window passed to %s", name + 5); + PR_RunError (res->pr, "invalid window %d passed to %s", + handle, name + 5); } return window; } @@ -1256,7 +1257,7 @@ bi_mvwvprintf (progs_t *pr) const char *fmt = P_GSTRING (pr, 2); __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 3); - qwaq_mvwvprintf (pr, x, y, window_id, fmt, args); + qwaq_mvwvprintf (pr, window_id, x, y, fmt, args); } static void @@ -1666,9 +1667,9 @@ bi_i_TextContext__mvvprintf_ (progs_t *pr) int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); const char *fmt = P_GSTRING (pr, 3); - __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 4); + __auto_type args = &P_PACKED (pr, pr_va_list_t, 4); - qwaq_mvwvprintf (pr, pos->x, pos->y, window_id, fmt, args); + qwaq_mvwvprintf (pr, window_id, pos->x, pos->y, fmt, args); } static void From 1f8301774c59e539e5fa3e841f53c262554904dd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 09:19:22 +0900 Subject: [PATCH 0879/3664] [qwaq] Fix over-consumption of editor events This lets the window scroll again. --- ruamoko/qwaq/qwaq-debugger.r | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index a90eb1216..d944abcd5 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -135,24 +135,28 @@ void traceon() = #0; [TextContext refresh]; } --(void)key_event: (ed_event_t *)_event +static int +key_event (Debugger *self, Editor *file, qwaq_event_t *event) { - Editor *file = _event.editor; - qwaq_event_t *event = _event.event; - if (event.what == qe_mouseclick) { + if (event.what == qe_mouseclick && !(event.mouse.buttons & 0x78)) { printf ("%s\n", [file getWordAt: {event.mouse.x, event.mouse.y}]); - [source_window redraw]; + [self.source_window redraw]; } else if (event.what == qe_keydown) { switch (event.key.code) { case QFK_F7: - qdb_set_trace (debug_target, 1); - qdb_continue (debug_target); - break; - default: - return; + qdb_set_trace (self.debug_target, 1); + qdb_continue (self.debug_target); + return 1; } } - event.what = qe_none; + return 0; +} + +-(void)key_event: (ed_event_t *)event +{ + if (key_event (self, event.editor, event.event)) { + event.event.what = qe_none; + } } -handleDebugEvent From af0333a172d77a8ad02ba571eeb396362fa20380 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 11:04:57 +0900 Subject: [PATCH 0880/3664] [qwaq] Ensure super's handleEvent is called This fixes the inability to single-step (debug window couldn't regain focus). --- ruamoko/qwaq/qwaq-button.r | 2 ++ ruamoko/qwaq/qwaq-editor.r | 2 ++ ruamoko/qwaq/qwaq-window.r | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/qwaq-button.r index 3f72d2ca8..a02a738c0 100644 --- a/ruamoko/qwaq/qwaq-button.r +++ b/ruamoko/qwaq/qwaq-button.r @@ -52,6 +52,8 @@ { ListenerGroup *action = nil; + [super handleEvent: event]; + if (event.what & qe_mouse) { switch ((qwaq_mouse_event) (event.what & qe_mouse)) { case qe_mousedown: diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 770b4158d..80b40bf1c 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -88,6 +88,8 @@ static int handleEvent (Editor *self, qwaq_event_t *event) -handleEvent:(qwaq_event_t *) event { + [super handleEvent: event]; + // give any listeners a chance to override or extend event handling _event.editor = self; _event.event = event; diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 8fde82d79..60c88bdd8 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -184,8 +184,9 @@ -handleEvent: (qwaq_event_t *) event { - int offset = event.what & qe_positional; + [super handleEvent: event]; + int offset = event.what & qe_positional; if (offset) { event.mouse.x -= xpos; event.mouse.y -= ypos; From 35bb3a38540fe09c56e18c20640163da07938cc0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 11:18:00 +0900 Subject: [PATCH 0881/3664] [qwaq] Raise windows when clicked --- ruamoko/qwaq/qwaq-group.r | 1 + ruamoko/qwaq/qwaq-view.h | 1 + ruamoko/qwaq/qwaq-view.r | 5 +++++ ruamoko/qwaq/qwaq-window.r | 7 +++++++ 4 files changed, 14 insertions(+) diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 8743e995d..a78837c5a 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -76,6 +76,7 @@ makeFirst (Group *self, int viewIndex) [self.views addObject: view]; [self.views removeObjectAtIndex: viewIndex]; + [view raise]; return [self.views count] - 1; } diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index db4862929..76b3607d5 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -72,6 +72,7 @@ enum { -loseFocus; -(ListenerGroup *) onReceiveFocus; -(ListenerGroup *) onReleaseFocus; +-raise; - (void) onMouseEnter: (Point) pos; - (void) onMouseLeave: (Point) pos; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 3300a0d05..7a5cd01f0 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -288,6 +288,11 @@ updateScreenCursor (View *view) return onReleaseFocus; } +-raise +{ + return self; +} + - (void) onMouseEnter: (Point) pos { } diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 60c88bdd8..2d9c1b549 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -213,6 +213,13 @@ return self; } +-raise +{ + top_panel (panel); + [self redraw]; + return self; +} + -insert: (View *) view { [objects insert: view]; From 1bd8e2ee8560a67fe5f055178edc13f910b71a88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 11:44:02 +0900 Subject: [PATCH 0882/3664] [gamecode] Add a param pointer to debug_handler I decided I want events for VM enter/exit but enter needs to somehow pass the function which will be executed (even if a builtin). A generic void * param seemed the best idea, which meant the error string could be passed via the param instead of a "global" string in the progs struct. --- include/QF/progs.h | 3 +-- libs/gamecode/pr_exec.c | 11 +++++------ libs/gamecode/pr_load.c | 6 ++---- ruamoko/qwaq/main.c | 2 +- ruamoko/qwaq/qwaq-debug.c | 4 ++-- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 3cd6a5c6c..c393be5a5 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1857,9 +1857,8 @@ struct progs_s { /// \name debugging ///@{ struct prdeb_resources_s *pr_debug_resources; - void (*debug_handler) (prdebug_t event, void *data); + void (*debug_handler) (prdebug_t event, void *param, void *data); void *debug_data; - const char *error_string; pr_type_t *watch; int wp_conditional; pr_type_t wp_val; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 43681da79..425ec5f64 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -55,7 +55,7 @@ VISIBLE void PR_RunError (progs_t * pr, const char *error, ...) { - dstring_t *string = dstring_new (); + dstring_t *string = dstring_new ();//FIXME leaks when debugging va_list argptr; va_start (argptr, error); @@ -63,8 +63,7 @@ PR_RunError (progs_t * pr, const char *error, ...) va_end (argptr); if (pr->debug_handler) { - pr->error_string = string->str; - pr->debug_handler (prd_runerror, pr->debug_data); + pr->debug_handler (prd_runerror, string->str, pr->debug_data); // not expected to return, but if so, behave as if there was no handler } @@ -486,7 +485,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) if (pr->pr_trace) { if (pr->debug_handler) { - pr->debug_handler (prd_trace, pr->debug_data); + pr->debug_handler (prd_trace, 0, pr->debug_data); } else { PR_PrintStatement (pr, st, 1); } @@ -494,7 +493,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) if (st->op & OP_BREAK) { if (pr->debug_handler) { - pr->debug_handler (prd_breakpoint, pr->debug_data); + pr->debug_handler (prd_breakpoint, 0, pr->debug_data); } else { PR_RunError (pr, "breakpoint hit"); } @@ -1714,7 +1713,7 @@ op_call: if (!pr->wp_conditional || pr->watch->integer_var == pr->wp_val.integer_var) { if (pr->debug_handler) { - pr->debug_handler (prd_watchpoint, pr->debug_data); + pr->debug_handler (prd_watchpoint, 0, pr->debug_data); } else { PR_RunError (pr, "watchpoint hit: %d -> %d", old_val.integer_var, pr->watch->integer_var); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 9ea30a037..dd405769a 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -326,7 +326,6 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) def->type_encoding = xdef->type; } } - pr->error_string = 0; pr->pr_trace = 0; pr->pr_trace_depth = 0; pr->pr_xfunction = 0; @@ -483,15 +482,14 @@ VISIBLE void PR_Error (progs_t *pr, const char *error, ...) { va_list argptr; - dstring_t *string = dstring_new (); + dstring_t *string = dstring_new ();//FIXME leaks when debugging va_start (argptr, error); dvsprintf (string, error, argptr); va_end (argptr); if (pr->debug_handler) { - pr->error_string = string->str; - pr->debug_handler (prd_error, pr->debug_data); + pr->debug_handler (prd_error, string->str, pr->debug_data); // not expected to return, but if so, behave as if there was no handler } Sys_Error ("%s: %s", pr->progs_name, string->str); diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 46e1d8e4b..8c9650786 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -233,7 +233,7 @@ run_progs (void *data) PR_ExecuteProgram (thread->pr, thread->main_func); PR_PopFrame (thread->pr); if (thread->pr->debug_handler) { - thread->pr->debug_handler (prd_exit, thread->pr->debug_data); + thread->pr->debug_handler (prd_exit, 0, thread->pr->debug_data); } thread->return_code = R_INT (thread->pr); return thread; diff --git a/ruamoko/qwaq/qwaq-debug.c b/ruamoko/qwaq/qwaq-debug.c index 40effa817..b7fcab168 100644 --- a/ruamoko/qwaq/qwaq-debug.c +++ b/ruamoko/qwaq/qwaq-debug.c @@ -109,7 +109,7 @@ get_target (qwaq_debug_t *debug, const char *name, int handle) } static void -qwaq_debug_handler (prdebug_t debug_event, void *data) +qwaq_debug_handler (prdebug_t debug_event, void *param, void *data) { __auto_type target = (qwaq_target_t *) data; qwaq_debug_t *debug = target->debugger; @@ -130,7 +130,7 @@ qwaq_debug_handler (prdebug_t debug_event, void *data) pthread_cond_wait (&target->run_cond.rcond, &target->run_cond.mut); pthread_mutex_unlock (&target->run_cond.mut); if (debug_event == prd_runerror || debug_event == prd_error) { - pthread_exit ((void *) target->pr->error_string); + pthread_exit (param); } } From 2d5df34234d02ba6bd0e9bac5d7c0ab5d659c2d3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 12:30:32 +0900 Subject: [PATCH 0883/3664] [gamecode] Add VM enter/exit events And rename prd_exit to prd_terminate (the idea is the host will terminate the VM). This makes it possible for the debugger to pause the VM before any code, even a builtin function, is executed. Breaks the debugger source window, but only because it's not updating on file change (I think). --- include/QF/progs.h | 4 +++- libs/gamecode/pr_exec.c | 7 +++++++ ruamoko/qwaq/main.c | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index c393be5a5..c08bf12d5 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1710,7 +1710,9 @@ typedef enum { prd_trace, prd_breakpoint, prd_watchpoint, - prd_exit, // not sent by VM + prd_subenter, + prd_subexit, // current invocation of PR_ExecuteProgram finished + prd_terminate, // not sent by VM prd_runerror, prd_error, // lower level error thann prd_runerror } prdebug_t; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 425ec5f64..b0a7cb820 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -458,6 +458,10 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) Sys_PushSignalHook (signal_hook, pr); Sys_PushErrorHandler (error_handler, pr); + if (pr->debug_handler) { + pr->debug_handler (prd_subenter, &fnum, pr->debug_data); + } + if (!PR_CallFunction (pr, fnum)) { // called a builtin instead of progs code goto exit_program; @@ -1723,6 +1727,9 @@ op_call: } } exit_program: + if (pr->debug_handler) { + pr->debug_handler (prd_subexit, 0, pr->debug_data); + } pr->pr_argc = 0; Sys_PopErrorHandler (); Sys_PopSignalHook (); diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/main.c index 8c9650786..bbd66bac1 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/main.c @@ -233,7 +233,7 @@ run_progs (void *data) PR_ExecuteProgram (thread->pr, thread->main_func); PR_PopFrame (thread->pr); if (thread->pr->debug_handler) { - thread->pr->debug_handler (prd_exit, 0, thread->pr->debug_data); + thread->pr->debug_handler (prd_terminate, 0, thread->pr->debug_data); } thread->return_code = R_INT (thread->pr); return thread; From dbb3802740a214f7578e6d2e9c6b309086c2e346 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 13:20:10 +0900 Subject: [PATCH 0884/3664] [qwaq] Transfer context to new view in proxy This fixes the broken source window on file change. --- ruamoko/qwaq/qwaq-proxyview.r | 6 +++++- ruamoko/qwaq/qwaq-view.h | 1 + ruamoko/qwaq/qwaq-view.r | 7 ++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-proxyview.r b/ruamoko/qwaq/qwaq-proxyview.r index a29b1dedd..e0f2bb469 100644 --- a/ruamoko/qwaq/qwaq-proxyview.r +++ b/ruamoko/qwaq/qwaq-proxyview.r @@ -21,12 +21,16 @@ -setView:(View *) view { int state = [self.view state]; + id context = [self.view context]; + if (state & sfInFocus) { [self.view loseFocus]; - [self.view hide]; } + [self.view hide]; + [self.view setContext:nil]; self.view = view; + [view setContext:context]; if (state & sfDrawn) { [view draw]; } diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 76b3607d5..b2c98c88b 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -59,6 +59,7 @@ enum { -(int) options; -(int) state; +-(id)context; -setContext: (id) context; -draw; -hide; diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 7a5cd01f0..707fd056e 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -35,7 +35,12 @@ [super dealloc]; } -- setContext: (id) context +-(id)context +{ + return textContext; +} + +-setContext: (id) context { textContext = context; return self; From 30b97af65a00e7033d1d63758c3a1b5da20ec876 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 13:21:05 +0900 Subject: [PATCH 0885/3664] [qwaq] Actually send on receive/release focus messages Noticed while tracking down the proxy view switch issue. --- ruamoko/qwaq/qwaq-view.r | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 707fd056e..caeab8286 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -274,12 +274,14 @@ updateScreenCursor (View *view) -takeFocus { state |= sfInFocus; + [onReceiveFocus respond:self]; return self; } -loseFocus { state &= ~sfInFocus; + [onReleaseFocus respond:self]; return self; } From a28e7417e6eed68013b8cabfe6dc28b86b429f99 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 13:27:53 +0900 Subject: [PATCH 0886/3664] [qwaq] Make traceon and traceoff always available Tired of adding and removing them all the time. --- ruamoko/qwaq/qwaq-debug.h | 3 +++ ruamoko/qwaq/qwaq-debugger.r | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h index 302f9cd6e..e4de7c12c 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/qwaq-debug.h @@ -74,6 +74,9 @@ typedef struct qdb_target_s { int handle; } qdb_target_t; unsigned fnum); @extern qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum); +@extern void traceon(); +@extern void traceoff(); + #else//GCC void QWAQ_Debug_Init (progs_t *pr); diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index d944abcd5..8beec60ec 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -108,8 +108,6 @@ update_current_func (Debugger *self, unsigned fnum) } } -void traceon() = #0; - -(void)update_watchvars { qdb_state_t state = qdb_get_state (debug_target); @@ -171,6 +169,9 @@ key_event (Debugger *self, Editor *file, qwaq_event_t *event) @end +void traceon() = #0; +void traceoff() = #0; + void qdb_set_trace (qdb_target_t target, int state) = #0; int qdb_set_breakpoint (qdb_target_t target, unsigned staddr) = #0; int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr) = #0; From 6e74f2a03fef8b496d1fb56bc53892de163769b6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 13:30:33 +0900 Subject: [PATCH 0887/3664] [qwaq] remove @ from externs I had forgotten that extern worked and that @extern was for headers that might be compiled in traditional or extended modes. --- ruamoko/qwaq/qwaq-app.h | 2 +- ruamoko/qwaq/qwaq-curses.h | 82 +++++++++++++++++++------------------- ruamoko/qwaq/qwaq-debug.h | 40 +++++++++---------- ruamoko/qwaq/qwaq-rect.h | 12 +++--- 4 files changed, 68 insertions(+), 68 deletions(-) diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index 36cb41cef..c88d79cec 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -32,6 +32,6 @@ extern int color_palette[64]; -run; @end -@extern QwaqApplication *application; +extern QwaqApplication *application; #endif//__qwaq_app_h diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 111ada434..c43f08d13 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -84,55 +84,55 @@ typedef enum { typedef struct window_s *window_t; typedef struct panel_s *panel_t; -@extern window_t stdscr; +extern window_t stdscr; -@extern void initialize (void); -@extern window_t create_window (int xpos, int ypos, int xlen, int ylen); -@extern void destroy_window (window_t win); -@extern void mvwprintf (window_t win, int x, int y, string fmt, ...); -@extern void wprintf (window_t win, string fmt, ...); -@extern void wvprintf (window_t win, string fmt, @va_list args); -@extern void mvwvprintf (window_t win, int x, int y, +extern void initialize (void); +extern window_t create_window (int xpos, int ypos, int xlen, int ylen); +extern void destroy_window (window_t win); +extern void mvwprintf (window_t win, int x, int y, string fmt, ...); +extern void wprintf (window_t win, string fmt, ...); +extern void wvprintf (window_t win, string fmt, @va_list args); +extern void mvwvprintf (window_t win, int x, int y, string fmt, @va_list args); -@extern void wrefresh (window_t win); -@extern void mvwaddch (window_t win, int x, int y, int ch); -@extern void waddch (window_t win, int ch); -@extern void mvwaddstr (window_t win, int x, int y, string str); -@extern void waddstr (window_t win, string str); +extern void wrefresh (window_t win); +extern void mvwaddch (window_t win, int x, int y, int ch); +extern void waddch (window_t win, int ch); +extern void mvwaddstr (window_t win, int x, int y, string str); +extern void waddstr (window_t win, string str); -@extern panel_t create_panel (window_t window); -@extern void destroy_panel (panel_t panel); -@extern void hide_panel (panel_t panel); -@extern void show_panel (panel_t panel); -@extern void top_panel (panel_t panel); -@extern void bottom_panel (panel_t panel); -@extern void move_panel (panel_t panel, int x, int y); -@extern window_t panel_window (panel_t panel); -@extern void update_panels (void); -@extern void replace_panel (panel_t panel, window_t window); -@extern void doupdate (void); +extern panel_t create_panel (window_t window); +extern void destroy_panel (panel_t panel); +extern void hide_panel (panel_t panel); +extern void show_panel (panel_t panel); +extern void top_panel (panel_t panel); +extern void bottom_panel (panel_t panel); +extern void move_panel (panel_t panel, int x, int y); +extern window_t panel_window (panel_t panel); +extern void update_panels (void); +extern void replace_panel (panel_t panel, window_t window); +extern void doupdate (void); -@extern int get_event (qwaq_event_t *event); -@extern int max_colors (void); -@extern int max_color_pairs (void); -@extern int init_pair (int pair, int f, int b); -@extern void wbkgd (window_t win, int ch); -@extern void werase (window_t win); -@extern void scrollok (window_t win, int flag); +extern int get_event (qwaq_event_t *event); +extern int max_colors (void); +extern int max_color_pairs (void); +extern int init_pair (int pair, int f, int b); +extern void wbkgd (window_t win, int ch); +extern void werase (window_t win); +extern void scrollok (window_t win, int flag); -@extern int acs_char (int acs); -@extern int curs_set (int visibility); -@extern int move (int x, int y); +extern int acs_char (int acs); +extern int curs_set (int visibility); +extern int move (int x, int y); -@extern void wborder (window_t window, - box_sides_t sides, box_corners_t corners); -@extern void mvwblit_line (window_t window, int x, int y, int *wch, int len); -@extern void wresize (window_t window, int width, int height); -@extern void resizeterm (int width, int height); +extern void wborder (window_t window, + box_sides_t sides, box_corners_t corners); +extern void mvwblit_line (window_t window, int x, int y, int *wch, int len); +extern void wresize (window_t window, int width, int height); +extern void resizeterm (int width, int height); -@extern Rect getwrect (struct window_s *window); +extern Rect getwrect (struct window_s *window); -@extern void printf(string fmt, ...); +extern void printf(string fmt, ...); // qfcc stuff #else // gcc stuff diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h index e4de7c12c..630c9097a 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/qwaq-debug.h @@ -55,27 +55,27 @@ typedef struct qdb_auxfunction_s { typedef struct qdb_target_s { int handle; } qdb_target_t; -@extern void qdb_set_trace (qdb_target_t target, int state); -@extern int qdb_set_breakpoint (qdb_target_t target, unsigned staddr); -@extern int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr); -@extern int qdb_set_watchpoint (qdb_target_t target, unsigned offset); -@extern int qdb_clear_watchpoint (qdb_target_t target); -@extern int qdb_continue (qdb_target_t target); -@extern qdb_state_t qdb_get_state (qdb_target_t target); -@extern int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, - void *dst); -@extern qdb_def_t qdb_find_global (qdb_target_t target, string name); -@extern qdb_def_t qdb_find_field (qdb_target_t target, string name); -@extern qdb_function_t *qdb_find_function (qdb_target_t target, string name); -@extern qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum); -@extern qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, - string name); -@extern qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, - unsigned fnum); -@extern qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum); +extern void qdb_set_trace (qdb_target_t target, int state); +extern int qdb_set_breakpoint (qdb_target_t target, unsigned staddr); +extern int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr); +extern int qdb_set_watchpoint (qdb_target_t target, unsigned offset); +extern int qdb_clear_watchpoint (qdb_target_t target); +extern int qdb_continue (qdb_target_t target); +extern qdb_state_t qdb_get_state (qdb_target_t target); +extern int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, + void *dst); +extern qdb_def_t qdb_find_global (qdb_target_t target, string name); +extern qdb_def_t qdb_find_field (qdb_target_t target, string name); +extern qdb_function_t *qdb_find_function (qdb_target_t target, string name); +extern qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum); +extern qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, + string name); +extern qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, + unsigned fnum); +extern qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum); -@extern void traceon(); -@extern void traceoff(); +extern void traceon(); +extern void traceoff(); #else//GCC diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index ba1e47c10..2f7915ff1 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -17,12 +17,12 @@ typedef struct Rect_s { } Rect; #ifdef __QFCC__ -@extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); -@extern Point makePoint (int x, int y); -@extern Extent makeExtent (int width, int height); -@extern Extent mergeExtents (Extent a, Extent b); -@extern int rectContainsPoint (Rect rect, Point point); -@extern Rect clipRect (Rect clipRect, Rect rect); +extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); +extern Point makePoint (int x, int y); +extern Extent makeExtent (int width, int height); +extern Extent mergeExtents (Extent a, Extent b); +extern int rectContainsPoint (Rect rect, Point point); +extern Rect clipRect (Rect clipRect, Rect rect); #endif #endif//__qwaq_rect_h From 6e473dc8f26049c4a2fa251a5dd41bb16467ca7e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 14:13:05 +0900 Subject: [PATCH 0888/3664] [ruamoko] Return nil IMP for nil method Fixes a segfault. --- libs/ruamoko/rua_obj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 3d69eba11..1cdf8ed86 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1800,7 +1800,7 @@ rua_method_get_imp (progs_t *pr) { pr_method_t *method = &P_STRUCT (pr, pr_method_t, 0); - R_INT (pr) = method->method_imp; + R_INT (pr) = method ? method->method_imp : 0; } static void From 983a7422db44bb65409928a42b53a3cee4b3c191 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 14:14:04 +0900 Subject: [PATCH 0889/3664] [libr] Add a two-object Array perform method I decided it was worth doing after all. This cleans up event forwarding in qwaq. --- ruamoko/include/Array.h | 9 +++++++++ ruamoko/lib/Array.r | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/ruamoko/include/Array.h b/ruamoko/include/Array.h index 060f50956..cfc95f595 100644 --- a/ruamoko/include/Array.h +++ b/ruamoko/include/Array.h @@ -274,6 +274,15 @@ withObject: (void *)arg; //\} +/** + Iteratively sends #performSelector:withObject:withObject: to each + contained object. +*/ +- (void) makeObjectsPerformSelector: (SEL)selector + withObject: (void *)arg + withObject: (void *)arg2; +//\} + @end #endif//__ruamoko_Array_h diff --git a/ruamoko/lib/Array.r b/ruamoko/lib/Array.r index 2946141cc..5fbaa9e56 100644 --- a/ruamoko/lib/Array.r +++ b/ruamoko/lib/Array.r @@ -410,6 +410,19 @@ } } +- (void) makeObjectsPerformSelector: (SEL)selector + withObject: (void *)anObject + withObject: (void *)anotherObject +{ + local int i; + + for (i = 0; i < [self count]; i++) { + [[self objectAtIndex: i] performSelector: selector + withObject: anObject + withObject: anotherObject]; + } +} + - (void) dealloc { local unsigned i; From aac732fc6350c5a62acd008c1e29067cd8985fc1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 14:16:07 +0900 Subject: [PATCH 0890/3664] [qwaq] Support an actual parameter for listeners --- ruamoko/qwaq/qwaq-listener.h | 2 ++ ruamoko/qwaq/qwaq-listener.r | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/ruamoko/qwaq/qwaq-listener.h b/ruamoko/qwaq/qwaq-listener.h index 59c96ff1d..0dd388c2e 100644 --- a/ruamoko/qwaq/qwaq-listener.h +++ b/ruamoko/qwaq/qwaq-listener.h @@ -13,6 +13,7 @@ } -initWithResponder: (id) responder :(SEL)message; -(void) respond: (void *) caller_data; +-(void) respond: (void *) caller_data withObject:(void *)anObject; -(BOOL) matchResponder: (id) responder :(SEL)message; @end @@ -24,6 +25,7 @@ -addListener: (id) responder :(SEL)message; -removeListener: (id) responder :(SEL)message; -(void) respond: (void *) caller_data; +-(void) respond: (void *) caller_data withObject:(void *)anObject; @end #endif//__qwaq_listener_h diff --git a/ruamoko/qwaq/qwaq-listener.r b/ruamoko/qwaq/qwaq-listener.r index 12d786de3..95c27f04c 100644 --- a/ruamoko/qwaq/qwaq-listener.r +++ b/ruamoko/qwaq/qwaq-listener.r @@ -21,6 +21,11 @@ imp (responder, message, caller_data); } +-(void)respond: (void *) caller_data withObject:(void *)anObject +{ + imp (responder, message, caller_data, anObject); +} + -(BOOL) matchResponder: (id) responder :(SEL)message { return self.responder == responder && self.message == message; @@ -63,4 +68,11 @@ [listeners makeObjectsPerformSelector: @selector (respond:) withObject: caller_data]; } + +-(void)respond: (void *) caller_data withObject:(void *)anObject +{ + [listeners makeObjectsPerformSelector: @selector (respond:) + withObject: caller_data + withObject: anObject]; +} @end From e018f5cf71f08d3dbe4cf629b1a8c79ede804a04 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 14:16:58 +0900 Subject: [PATCH 0891/3664] [qwaq] Clean up Editor's event forwarding Much less clunky with that container object. With this, I think it will be useful moving the forwarding into View. Still unsure on that, though. --- ruamoko/qwaq/qwaq-debugger.r | 12 ++++++------ ruamoko/qwaq/qwaq-editor.h | 7 ------- ruamoko/qwaq/qwaq-editor.r | 4 +--- 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index 8beec60ec..a7c2b7a24 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -53,7 +53,7 @@ current_file = [self find_file: state.file]; file_proxy = [[ProxyView alloc] initWithView: current_file]; [[current_file gotoLine:state.line - 1] highlightLine]; - [[current_file onEvent] addListener: self :@selector(key_event:)]; + [[current_file onEvent] addListener: self :@selector(key_event::)]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; [source_window setTitle: [current_file filename]]; @@ -74,9 +74,9 @@ printf ("%s:%d\n", state.file, state.line); if (current_file != file) { - [[current_file onEvent] removeListener:self :@selector(key_event:)]; + [[current_file onEvent] removeListener:self :@selector(key_event::)]; [file_proxy setView:file]; - [[file onEvent] addListener:self :@selector(key_event:)]; + [[file onEvent] addListener:self :@selector(key_event::)]; [source_window setTitle: [file filename]]; current_file = file; } @@ -150,10 +150,10 @@ key_event (Debugger *self, Editor *file, qwaq_event_t *event) return 0; } --(void)key_event: (ed_event_t *)event +-(void)key_event:(Editor *)editor :(qwaq_event_t *)event { - if (key_event (self, event.editor, event.event)) { - event.event.what = qe_none; + if (key_event (self, editor, event)) { + event.what = qe_none; } } diff --git a/ruamoko/qwaq/qwaq-editor.h b/ruamoko/qwaq/qwaq-editor.h index b861e15ad..1d6a261d5 100644 --- a/ruamoko/qwaq/qwaq-editor.h +++ b/ruamoko/qwaq/qwaq-editor.h @@ -8,12 +8,6 @@ @class EditBuffer; @class ListenerGroup; -// Data sent to onKeyEvent listeners -typedef struct ed_event_s { - Editor *editor; - struct qwaq_event_s *event; -} ed_event_t; - @interface Editor : View { EditBuffer *buffer; @@ -28,7 +22,6 @@ typedef struct ed_event_s { unsigned line_count; string filename; ListenerGroup *onEvent; - ed_event_t _event; } -initWithRect:(Rect) rect file:(string) filename; -(ListenerGroup *)onEvent; diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 80b40bf1c..2428bd45f 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -91,13 +91,11 @@ static int handleEvent (Editor *self, qwaq_event_t *event) [super handleEvent: event]; // give any listeners a chance to override or extend event handling - _event.editor = self; - _event.event = event; if (event.what & qe_positional) { event.mouse.x -= xpos; event.mouse.y -= ypos; } - [onEvent respond: &_event]; + [onEvent respond:self withObject:event]; if (handleEvent (self, event)) { event.what = qe_none; } From e893421dba5e8fd952a0e39d9a3e4b9e650b5b6f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 14:46:48 +0900 Subject: [PATCH 0892/3664] [qwaq] Get context from owner instead of prev view The previous view might be nil, which would result in the new view not getting a context. --- ruamoko/qwaq/qwaq-group.h | 2 ++ ruamoko/qwaq/qwaq-group.r | 11 +++++++++++ ruamoko/qwaq/qwaq-proxyview.h | 3 +++ ruamoko/qwaq/qwaq-proxyview.r | 10 ++++++++-- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/qwaq-group.h index 3d9c53e65..70e2663a0 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/qwaq-group.h @@ -18,6 +18,8 @@ id context; } -initWithContext: (id) context owner: (View *) owner; +-(id)context; +-setContext: (id) context; -insert: (View *) view; -insertDrawn: (View *) view; -insertSelected: (View *) view; diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index a78837c5a..5ae197a2a 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -24,6 +24,17 @@ [views release]; } +-(id)context +{ + return context; +} + +-setContext: (id) context +{ + self.context = context; + return self; +} + -insert: (View *) view { [views addObject: view]; diff --git a/ruamoko/qwaq/qwaq-proxyview.h b/ruamoko/qwaq/qwaq-proxyview.h index 7789678fc..449ac5fd6 100644 --- a/ruamoko/qwaq/qwaq-proxyview.h +++ b/ruamoko/qwaq/qwaq-proxyview.h @@ -3,9 +3,12 @@ #include "qwaq-view.h" +@class Group; + @interface ProxyView : Object { View *view; + Group *owner; } -initWithView:(View *) view; -setView: (View *) view; diff --git a/ruamoko/qwaq/qwaq-proxyview.r b/ruamoko/qwaq/qwaq-proxyview.r index e0f2bb469..b5946eba5 100644 --- a/ruamoko/qwaq/qwaq-proxyview.r +++ b/ruamoko/qwaq/qwaq-proxyview.r @@ -1,3 +1,4 @@ +#include "qwaq-group.h" #include "qwaq-proxyview.h" @implementation ProxyView @@ -18,10 +19,15 @@ return self; } +-setOwner:(Group *)owner +{ + self.owner = owner; + return [view setOwner:owner]; +} + -setView:(View *) view { int state = [self.view state]; - id context = [self.view context]; if (state & sfInFocus) { [self.view loseFocus]; @@ -30,7 +36,7 @@ [self.view setContext:nil]; self.view = view; - [view setContext:context]; + [view setContext:[owner context]]; if (state & sfDrawn) { [view draw]; } From 22e2695f80b91cad6586da827cfe4f09cb2c35dd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 15:36:46 +0900 Subject: [PATCH 0893/3664] [gamecode] Add VISIBLE to some missed functions --- libs/gamecode/pr_strings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 6bbca3481..831b90a56 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -560,7 +560,7 @@ PR_SetDynamicString (progs_t *pr, const char *s) return string_index (res, sr); } -void +VISIBLE void PR_MakeTempString (progs_t *pr, string_t str) { prstr_resources_t *res = pr->pr_string_resources; @@ -619,7 +619,7 @@ PR_FreeString (progs_t *pr, string_t str) PR_RunError (pr, "attempt to free invalid string %d", str); } -void +VISIBLE void PR_FreeTempStrings (progs_t *pr) { prstr_resources_t *res = pr->pr_string_resources; From b4874f7d9beeb1fe3e6cb7c39436caa0b2d957d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 15:37:20 +0900 Subject: [PATCH 0894/3664] [gamecode] Make PR_FreeString a little more forgiving It treats only strings that are actually invalid as invalid. That is, now it is safe to "free" a static string: it's just a no-op. --- libs/gamecode/pr_strings.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 831b90a56..754ab7e38 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -602,6 +602,7 @@ PR_FreeString (progs_t *pr, string_t str) switch (sr->type) { case str_static: case str_temp: + case str_return: return; case str_mutable: dstring_delete (sr->s.dstring); @@ -609,14 +610,15 @@ PR_FreeString (progs_t *pr, string_t str) case str_dynamic: pr_strfree (pr, sr->s.string); break; - case str_return: default: PR_Error (pr, "internal string error: %d", __LINE__); } free_string_ref (res, sr); return; } - PR_RunError (pr, "attempt to free invalid string %d", str); + if (!PR_StringValid (pr, str)) { + PR_RunError (pr, "attempt to free invalid string %d", str); + } } VISIBLE void From ec82d6b027bd7e3633732a93ab0b782dcc2e445b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 16:36:29 +0900 Subject: [PATCH 0895/3664] [gamecode] Add support for holding ephemeral strings PR_HoldString converts ephemeral (temp and return) strings to dynamic strings. This makes dealing with strings in progs a little easier. --- include/QF/progs.h | 12 ++++++++++++ libs/gamecode/pr_strings.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index c08bf12d5..760819941 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1344,6 +1344,18 @@ string_t PR_NewMutableString (progs_t *pr); */ string_t PR_SetDynamicString (progs_t *pr, const char *s); +/** Convert an ephemeral string to a dynamic string. + + Valid strings that are not ephemeral (static, dynamic, mutable) will not + be affected, but temp and return strings will be marked dynamic, requiring + a call to PR_FreeString to return their memory. + + \param pr pointer to ::progs_t VM struct + \param str The string to be "held" (made non-ephemeral). Safe to call + on any valid string, but affects only ephemeral strings. +*/ +void PR_HoldString (progs_t *pr, string_t str); + /** Destroy a mutable, dynamic or temporary string. \param pr pointer to ::progs_t VM struct \param str string index of the string to be destroyed diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 754ab7e38..f2db346f0 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -449,8 +449,8 @@ PR_SetReturnString (progs_t *pr, const char *s) } // grab the string ref from the oldest slot, or make a new one if the - // slot is empty - if ((sr = res->rs_slot->strref)) { + // slot is empty or the string has been held + if ((sr = res->rs_slot->strref) && sr->type != str_dynamic) { if (sr->type != str_return || sr->rs_slot != res->rs_slot) { PR_Error (pr, "internal string error: %d", __LINE__); } @@ -592,6 +592,33 @@ PR_NewMutableString (progs_t *pr) return string_index (res, sr); } +VISIBLE void +PR_HoldString (progs_t *pr, string_t str) +{ + prstr_resources_t *res = pr->pr_string_resources; + strref_t *sr = get_strref (res, str); + + if (sr) { + switch (sr->type) { + case str_temp: + case str_return: + break; + case str_static: + case str_mutable: + case str_dynamic: + // non-ephemeral string, no-op + return; + default: + PR_Error (pr, "internal string error: %d", __LINE__); + } + sr->type = str_dynamic; + return; + } + if (!PR_StringValid (pr, str)) { + PR_RunError (pr, "attempt to hold invalid string %d", str); + } +} + VISIBLE void PR_FreeString (progs_t *pr, string_t str) { @@ -629,6 +656,11 @@ PR_FreeTempStrings (progs_t *pr) for (sr = pr->pr_xtstr; sr; sr = t) { t = sr->next; + if (sr->type == str_dynamic) { + // the string has been held, so simply remove the ref from the + // queue + continue; + } if (sr->type != str_temp) PR_Error (pr, "internal string error: %d", __LINE__); if (R_STRING (pr) < 0 && string_index (res, sr) == R_STRING (pr) From 1586df4dfc8ad1eafd6793d3010c4abe13e7c50a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 16:38:09 +0900 Subject: [PATCH 0896/3664] [gamecode] Make it possible to check string mutability --- include/QF/progs.h | 7 +++++++ libs/gamecode/pr_strings.c | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 760819941..7567ddc09 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1251,6 +1251,13 @@ void PR_Strings_Init (progs_t *pr); */ qboolean PR_StringValid (progs_t *pr, string_t num) __attribute__((pure)); +/** Check if a string is valid and mutable. + \param pr pointer to ::progs_t VM struct + \param num string index to be checked + \return true if the string is valid and mutable, false otherwise +*/ +qboolean PR_StringMutable (progs_t *pr, string_t num) __attribute__((pure)); + /** Convert a string index to a C string. \param pr pointer to ::progs_t VM struct \param num string index to be converted diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index f2db346f0..194dbc05c 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -361,6 +361,17 @@ PR_StringValid (progs_t *pr, string_t num) return get_strref (pr->pr_string_resources, num) != 0; } +VISIBLE qboolean +PR_StringMutable (progs_t *pr, string_t num) +{ + strref_t *sr; + if (num >= 0) { + return 0; + } + sr = get_strref (pr->pr_string_resources, num); + return sr && sr->type == str_mutable; +} + VISIBLE const char * PR_GetString (progs_t *pr, string_t num) { From 58ebbb147db92fae2d2a41120234b4e35b8caea9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 16:39:21 +0900 Subject: [PATCH 0897/3664] [ruamoko] Add some new string builtins Wrappers for hold, valid and mutable. I have no idea why I didn't think of wrapping string validation years ago. --- libs/ruamoko/rua_string.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 4ec5eb2a9..a8240a85c 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -104,6 +104,26 @@ bi_str_free (progs_t *pr) PR_FreeString (pr, P_STRING (pr, 0)); } +static void +bi_str_hold (progs_t *pr) +{ + string_t str = P_STRING (pr, 0); + PR_HoldString (pr, str); + R_STRING (pr) = str; +} + +static void +bi_str_valid (progs_t *pr) +{ + R_INT (pr) = PR_StringValid (pr, P_STRING (pr, 0)); +} + +static void +bi_str_mutable (progs_t *pr) +{ + R_INT (pr) = PR_StringMutable (pr, P_STRING (pr, 0)); +} + static void bi_str_copy (progs_t *pr) { @@ -194,6 +214,9 @@ static builtin_t builtins[] = { {"vsprintf", bi_vsprintf, -1}, {"str_new", bi_str_new, -1}, {"str_free", bi_str_free, -1}, + {"str_hold", bi_str_hold, -1}, + {"str_valid", bi_str_valid, -1}, + {"str_mutable", bi_str_mutable, -1}, {"str_copy", bi_str_copy, -1}, {"str_cat", bi_str_cat, -1}, {"str_clear", bi_str_clear, -1}, From 45d23ce521198959d566121ece8cdd1824dfbf80 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 16:49:09 +0900 Subject: [PATCH 0898/3664] [libr] Add bindings for new string functions And correct str_free's return type. --- ruamoko/include/string.h | 5 ++++- ruamoko/lib/string.r | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index 7f63f573e..b374b8335 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -5,7 +5,10 @@ @extern string sprintf (string fmt, ...); @extern string vsprintf (string fmt, @va_list args); @extern string str_new (void); -@extern string str_free (string str); +@extern void str_free (string str); +@extern string str_hold (string str); +@extern int str_valid (string str); +@extern int str_mutable (string str); @extern string str_copy (string dst, string src); @extern string str_cat (string dst, string src); @extern string str_clear (string str); diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index a23a6aa98..89ecc6aef 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -4,7 +4,10 @@ int (string s) strlen = #0; string (string fmt, ...) sprintf = #0; string vsprintf (string fmt, @va_list args) = #0; string (void) str_new = #0; -string (string str) str_free = #0; +void (string str) str_free = #0; +string str_hold (string str) = #0; +int str_valid (string str) = #0; +int str_mutable (string str) = #0; string (string dst, string src) str_copy = #0; string (string dst, string src) str_cat = #0; string (string str) str_clear = #0; From 91c5283af5209d2873e62e4ad2a9eae41b873966 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 16:53:53 +0900 Subject: [PATCH 0899/3664] [build] Fix ruamoko/gui's auto dependencies Changing str_free's return type highlighted that I'd missed an edit when I did the big ruamoko build cleanup. Also silence the sed/mv noise now that things are working nicely. --- ruamoko/cl_menu/Makefile.am | 4 ++-- ruamoko/game/Makefile.am | 4 ++-- ruamoko/gui/Makefile.am | 4 +++- ruamoko/lib/Makefile.am | 4 ++-- ruamoko/qwaq/Makefile.am | 4 ++-- ruamoko/scheme/Makefile.am | 4 ++-- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ruamoko/cl_menu/Makefile.am b/ruamoko/cl_menu/Makefile.am index ceaef7fe5..2d2b0c4d0 100644 --- a/ruamoko/cl_menu/Makefile.am +++ b/ruamoko/cl_menu/Makefile.am @@ -32,8 +32,8 @@ STRIP=`echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c` SUFFIXES=.o .r .r.o: $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< - sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo + @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo menu_src= \ client_menu.r controls_o.r options.r options_util.r servlist.r \ diff --git a/ruamoko/game/Makefile.am b/ruamoko/game/Makefile.am index 95093647f..e7cee8113 100644 --- a/ruamoko/game/Makefile.am +++ b/ruamoko/game/Makefile.am @@ -30,8 +30,8 @@ STRIP=`echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c` SUFFIXES=.o .r .r.o: $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< - sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo + @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo game_src= Axe.r GameEntity.r World.r tempent.r diff --git a/ruamoko/gui/Makefile.am b/ruamoko/gui/Makefile.am index 35d2624df..7edb5f173 100644 --- a/ruamoko/gui/Makefile.am +++ b/ruamoko/gui/Makefile.am @@ -26,7 +26,9 @@ RANLIB=touch SUFFIXES= .o .r .r.o: - $(QFCC) $(QCFLAGS) $(QCPPFLAGS) -c -o $@ $< + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo r_depfiles_remade= diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index 49107b28f..2f67f04fd 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -29,8 +29,8 @@ RANLIB=touch SUFFIXES= .o .r .r.o: $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< - sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo + @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo r_depfiles_remade= diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 4f81c8424..b615f11ba 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -20,8 +20,8 @@ QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) SUFFIXES=.o .r .r.o: $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo + @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo qwaq_app_dat_src= \ qwaq-app.r \ diff --git a/ruamoko/scheme/Makefile.am b/ruamoko/scheme/Makefile.am index f62c36191..3d4319863 100644 --- a/ruamoko/scheme/Makefile.am +++ b/ruamoko/scheme/Makefile.am @@ -36,8 +36,8 @@ RANLIB=touch SUFFIXES=.o .r .r.o: $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< - sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo + @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo r_depfiles_remade= From 90d89e887420a701b8a88e7fdeb069b9a7f304e3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 17:28:38 +0900 Subject: [PATCH 0900/3664] [qwaq] Move onEvent into View In the end, it did make sense since it seems to facilitate MVC nicely. --- ruamoko/qwaq/qwaq-editor.h | 2 -- ruamoko/qwaq/qwaq-editor.r | 17 +---------------- ruamoko/qwaq/qwaq-group.r | 23 +++++++++++++++++++++-- ruamoko/qwaq/qwaq-view.h | 15 ++++++++------- ruamoko/qwaq/qwaq-view.r | 7 +++++++ 5 files changed, 37 insertions(+), 27 deletions(-) diff --git a/ruamoko/qwaq/qwaq-editor.h b/ruamoko/qwaq/qwaq-editor.h index 1d6a261d5..01ef35f30 100644 --- a/ruamoko/qwaq/qwaq-editor.h +++ b/ruamoko/qwaq/qwaq-editor.h @@ -21,10 +21,8 @@ Point cursor; unsigned line_count; string filename; - ListenerGroup *onEvent; } -initWithRect:(Rect) rect file:(string) filename; --(ListenerGroup *)onEvent; -(string)filename; -scrollUp:(unsigned) count; -scrollDown:(unsigned) count; diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index 2428bd45f..a7163c9b6 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -15,16 +15,11 @@ line_count = [buffer countLines: {0, [buffer textSize]}]; linebuffer = [DrawBuffer buffer: { xlen, 1 }]; growMode = gfGrowHi; - options = ofCanFocus; + options = ofCanFocus | ofRelativeEvents; onEvent = [[ListenerGroup alloc] init]; return self; } --(ListenerGroup *)onEvent -{ - return onEvent; -} - -(string)filename { return filename; @@ -90,19 +85,9 @@ static int handleEvent (Editor *self, qwaq_event_t *event) { [super handleEvent: event]; - // give any listeners a chance to override or extend event handling - if (event.what & qe_positional) { - event.mouse.x -= xpos; - event.mouse.y -= ypos; - } - [onEvent respond:self withObject:event]; if (handleEvent (self, event)) { event.what = qe_none; } - if (event.what & qe_positional) { - event.mouse.x += xpos; - event.mouse.y += ypos; - } return self; } diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 5ae197a2a..11f724422 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -245,6 +245,25 @@ find_mouse_view(Group *group, Point pos) return nil; } +static void +handlePositionalEvent (qwaq_event_t *event, View *view) +{ + Point pos = [view origin]; + int options = [view options]; + + if (options & ofRelativeEvents) { + event.mouse.x -= pos.x; + event.mouse.y -= pos.y; + } + + [view handleEvent: event]; + + if (options & ofRelativeEvents) { + event.mouse.x += pos.x; + event.mouse.y += pos.y; + } +} + -handleEvent: (qwaq_event_t *) event { if (event.what & qe_focused) { @@ -253,7 +272,7 @@ find_mouse_view(Group *group, Point pos) } } else if (event.what & qe_positional) { if (mouse_grabbed) { - [mouse_grabbed handleEvent: event]; + handlePositionalEvent (event, mouse_grabbed); } else { Point pos = {event.mouse.x, event.mouse.y}; View *mouse_view = find_mouse_view (self, pos); @@ -263,7 +282,7 @@ find_mouse_view(Group *group, Point pos) mouse_within = mouse_view; } if (mouse_within) { - [mouse_within handleEvent: event]; + handlePositionalEvent (event, mouse_within); } } } else { diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index b2c98c88b..5eaccc5b6 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -14,12 +14,12 @@ enum { ofCanFocus = 0x0001, ofFirstClick = 0x0002, - ofDontDraw = 0x0004, - ofPreProcess = 0x0008, - ofPostProcess = 0x0010, - ofMakeFirst = 0x0020, - ofTileable = 0x0040, - ofCentered = 0x0080, + ofMakeFirst = 0x0004, + ofDontDraw = 0x0008, + ofRelativeEvents= 0x0010, + + ofTileable = 0x0020, + ofCentered = 0x0040, }; enum { @@ -68,6 +68,7 @@ enum { -resize: (Extent) delta; -move:(Point)dpos andResize:(Extent)dsize; -grow: (Extent) delta; +-(ListenerGroup *)onEvent; -handleEvent: (qwaq_event_t *) event; -takeFocus; -loseFocus; @@ -100,7 +101,6 @@ enum { }; }; Rect absRect; - Point point; // can't be local :( Group *owner; id textContext; int state; @@ -110,6 +110,7 @@ enum { Point cursor; ListenerGroup *onReceiveFocus; ListenerGroup *onReleaseFocus; + ListenerGroup *onEvent; } -initWithRect: (Rect) rect; @end diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index caeab8286..1d5fb2e29 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -259,8 +259,15 @@ updateScreenCursor (View *view) return self; } +-(ListenerGroup *)onEvent +{ + return onEvent; +} + -handleEvent: (qwaq_event_t *) event { + // give any listeners a chance to override or extend event handling + [onEvent respond:self withObject:event]; if (event.what & (qe_mousedown | qe_mouseclick) && options & ofCanFocus && !(state & (sfDisabled | sfInFocus))) { [owner selectView: self]; From 48f41142f599104468099b84d9a912848f7278be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 18:14:20 +0900 Subject: [PATCH 0901/3664] [qwaq] Add function to get a string from the target --- ruamoko/qwaq/qwaq-debug.c | 16 ++++++++++++++++ ruamoko/qwaq/qwaq-debug.h | 7 ++++--- ruamoko/qwaq/qwaq-debugger.r | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debug.c b/ruamoko/qwaq/qwaq-debug.c index b7fcab168..4938d8211 100644 --- a/ruamoko/qwaq/qwaq-debug.c +++ b/ruamoko/qwaq/qwaq-debug.c @@ -320,6 +320,21 @@ qdb_get_data (progs_t *pr) R_INT (pr) = 0; } +static void +qdb_get_string (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + string_t string = P_STRING (pr, 1); + + R_STRING (pr) = 0; + if (PR_StringValid (tpr, string)) { + RETURN_STRING (pr, PR_GetString (tpr, string)); + } +} + static void qdb_find_global (progs_t *pr) { @@ -491,6 +506,7 @@ static builtin_t builtins[] = { {"qdb_continue", qdb_continue, -1}, {"qdb_get_state", qdb_get_state, -1}, {"qdb_get_data", qdb_get_data, -1}, + {"qdb_get_string", qdb_get_string, -1}, {"qdb_find_global", qdb_find_global, -1}, {"qdb_find_field", qdb_find_field, -1}, {"qdb_find_function", qdb_find_function, -1}, diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h index 630c9097a..287e1282c 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/qwaq-debug.h @@ -28,7 +28,7 @@ typedef struct qdb_state_s { typedef struct qdb_def_s { unsigned type_size; // type in lower 16, size in upper 16 unsigned offset; - string_t name; + unsigned name; // string unsigned type_encoding; } qdb_def_t; @@ -37,8 +37,8 @@ typedef struct qdb_function_s { unsigned local_data; unsigned local_size; unsigned profile; - string_t name; - string_t file; + unsigned name; // string + unsigned file; // string unsigned num_params; } qdb_function_t; @@ -64,6 +64,7 @@ extern int qdb_continue (qdb_target_t target); extern qdb_state_t qdb_get_state (qdb_target_t target); extern int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst); +extern string qdb_get_string (qdb_target_t target, unsigned str); extern qdb_def_t qdb_find_global (qdb_target_t target, string name); extern qdb_def_t qdb_find_field (qdb_target_t target, string name); extern qdb_function_t *qdb_find_function (qdb_target_t target, string name); diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index a7c2b7a24..632a16ca0 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -181,6 +181,7 @@ int qdb_continue (qdb_target_t target) = #0; qdb_state_t qdb_get_state (qdb_target_t target) = #0; int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst) = #0; +string qdb_get_string (qdb_target_t target, unsigned str) = #0; qdb_def_t qdb_find_global (qdb_target_t target, string name) = #0; qdb_def_t qdb_find_field (qdb_target_t target, string name) = #0; qdb_function_t *qdb_find_function (qdb_target_t target, string name) = #0; From 6ec7b96693f506db9267dd3730dd46e1675a068e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 18:16:57 +0900 Subject: [PATCH 0902/3664] [qwaq] Initialize onEvent sigh --- ruamoko/qwaq/qwaq-editor.r | 1 - ruamoko/qwaq/qwaq-view.r | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/qwaq-editor.r index a7163c9b6..f45de395f 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/qwaq-editor.r @@ -16,7 +16,6 @@ linebuffer = [DrawBuffer buffer: { xlen, 1 }]; growMode = gfGrowHi; options = ofCanFocus | ofRelativeEvents; - onEvent = [[ListenerGroup alloc] init]; return self; } diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 1d5fb2e29..d7cbdb4a1 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -12,6 +12,7 @@ } onReceiveFocus = [[ListenerGroup alloc] init]; onReleaseFocus = [[ListenerGroup alloc] init]; + onEvent = [[ListenerGroup alloc] init]; return self; } @@ -24,6 +25,7 @@ self.absRect = rect; onReceiveFocus = [[ListenerGroup alloc] init]; onReleaseFocus = [[ListenerGroup alloc] init]; + onEvent = [[ListenerGroup alloc] init]; return self; } From bd8d09479f2c9fc10776e2fc4088263e469ae8ef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 18:19:25 +0900 Subject: [PATCH 0903/3664] [qwaq] Start work on displaying local defs The names show for the first function, but there are problems after that. --- ruamoko/qwaq/qwaq-debugger.r | 58 +++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index 632a16ca0..084ac534d 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -1,5 +1,7 @@ -#include #include +#include +#include +#include #include "qwaq-app.h" #include "qwaq-curses.h" @@ -118,16 +120,52 @@ update_current_func (Debugger *self, unsigned fnum) return; } qdb_get_data (debug_target, func.local_data, func.local_size, local_data); - [locals_view mvprintf:{0,0}, "%d", func.local_size]; - for (int y = 1; y < [locals_view size].height; y++) { - unsigned ind = (y - 1) * 4; - if (ind < func.local_size) { - [locals_view mvprintf:{0, y}, "%02x", ind]; - for (int x = 0; x < 4 && ind < func.local_size; x++, ind++) { - [locals_view mvprintf:{x * 9 + 3, y}, "%08x", local_data[ind]]; + if (!local_defs) { + [locals_view mvprintf:{0,0}, "%d", func.local_size]; + for (int y = 1; y < [locals_view size].height; y++) { + unsigned ind = (y - 1) * 4; + if (ind < func.local_size) { + [locals_view mvprintf:{0, y}, "%02x", ind]; + for (int x = 0; x < 4 && ind < func.local_size; x++, ind++) { + [locals_view mvprintf:{x * 9 + 3, y}, "%08x", + local_data[ind]]; + } + } else { + break; } - } else { - break; + } + } else { + for (int y = 0; y < [locals_view size].height; y++) { + if (y >= aux_func.num_locals) { + break; + } + qdb_def_t *def = local_defs + y; + [locals_view mvprintf:{0, y}, "%s", + qdb_get_string (debug_target, def.name)]; + string valstr = "--"; + printf ("def type_size %d\n", def.type_size); + switch (def.type_size & 0xffff) { + case ev_void: + case ev_invalid: + case ev_type_count: + break; + case ev_string: + case ev_float: + case ev_vector: + case ev_entity: + case ev_field: + case ev_func: + case ev_pointer: + case ev_quat: + case ev_integer: + case ev_uinteger: + case ev_short: + case ev_double: + valstr = sprintf ("%d", def.type_size >> 16); + break; + } + int x = [locals_view size].width - strlen (valstr) - 1; + [locals_view mvaddstr:{x, y}, valstr]; } } [TextContext refresh]; From b2814700b9af16ce25410b99162247c6a0efa535 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 18:22:40 +0900 Subject: [PATCH 0904/3664] [qwaq] Hook up locals view for events The same debugger method is used because the idea is that all the window in a group respond to the same commands in general. --- ruamoko/qwaq/qwaq-debugger.r | 24 +++++++++++++++--------- ruamoko/qwaq/qwaq-view.h | 1 + ruamoko/qwaq/qwaq-view.r | 14 ++++++++++++++ ruamoko/qwaq/qwaq-window.r | 7 ++++++- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index 084ac534d..564e376b1 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -55,7 +55,7 @@ current_file = [self find_file: state.file]; file_proxy = [[ProxyView alloc] initWithView: current_file]; [[current_file gotoLine:state.line - 1] highlightLine]; - [[current_file onEvent] addListener: self :@selector(key_event::)]; + [[current_file onEvent] addListener: self :@selector(proxy_event::)]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; [source_window setTitle: [current_file filename]]; @@ -64,9 +64,12 @@ locals_window = [[Window alloc] initWithRect: {{0, 0}, {40, 10}}]; [locals_window setBackground: color_palette[064]]; [locals_window setTitle: "Locals"]; - locals_view = [[View alloc] initWithRect: {{1, 1}, {38, 8}}]; + locals_view = [[View alloc] initWithRect: {{1, 1}, {38, 8}} + options: ofCanFocus]; [locals_window insertSelected: locals_view]; [application addView: locals_window]; + + [[locals_view onEvent] addListener:self :@selector(proxy_event::)]; } -(void) show_line @@ -76,9 +79,9 @@ printf ("%s:%d\n", state.file, state.line); if (current_file != file) { - [[current_file onEvent] removeListener:self :@selector(key_event::)]; + [[current_file onEvent] removeListener:self :@selector(proxy_event::)]; [file_proxy setView:file]; - [[file onEvent] addListener:self :@selector(key_event::)]; + [[file onEvent] addListener:self :@selector(proxy_event::)]; [source_window setTitle: [file filename]]; current_file = file; } @@ -172,11 +175,14 @@ update_current_func (Debugger *self, unsigned fnum) } static int -key_event (Debugger *self, Editor *file, qwaq_event_t *event) +proxy_event (Debugger *self, id proxy, qwaq_event_t *event) { if (event.what == qe_mouseclick && !(event.mouse.buttons & 0x78)) { - printf ("%s\n", [file getWordAt: {event.mouse.x, event.mouse.y}]); - [self.source_window redraw]; + if (proxy == self.current_file) { + printf ("%s\n", [proxy getWordAt: {event.mouse.x, event.mouse.y}]); + [self.source_window redraw]; + return 1; + } } else if (event.what == qe_keydown) { switch (event.key.code) { case QFK_F7: @@ -188,9 +194,9 @@ key_event (Debugger *self, Editor *file, qwaq_event_t *event) return 0; } --(void)key_event:(Editor *)editor :(qwaq_event_t *)event +-(void)proxy_event:(id)proxy :(qwaq_event_t *)event { - if (key_event (self, editor, event)) { + if (proxy_event (self, proxy, event)) { event.what = qe_none; } } diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 5eaccc5b6..27b0ddd43 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -113,6 +113,7 @@ enum { ListenerGroup *onEvent; } -initWithRect: (Rect) rect; +-initWithRect: (Rect) rect options:(int)options; @end @interface View (TextContext) diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index d7cbdb4a1..24b6b77ba 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -29,6 +29,20 @@ return self; } +-initWithRect: (Rect) rect options:(int)options +{ + if (!(self = [super init])) { + return nil; + } + self.rect = rect; + self.absRect = rect; + self.options = options; + onReceiveFocus = [[ListenerGroup alloc] init]; + onReleaseFocus = [[ListenerGroup alloc] init]; + onEvent = [[ListenerGroup alloc] init]; + return self; +} + - (void) dealloc { if (owner) { diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/qwaq-window.r index 2d9c1b549..3741d9acc 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/qwaq-window.r @@ -18,6 +18,11 @@ } -initWithRect: (Rect) rect +{ + return [self initWithRect: rect options:ofCanFocus | ofMakeFirst]; +} + +-initWithRect: (Rect) rect options:(int)options { if (!(self = [super init])) { return nil; @@ -70,7 +75,7 @@ [buf mvaddstr: {0, 2}, "XOX"]; growMode = gfGrowHi; - options = ofCanFocus | ofMakeFirst; + self.options = options; return self; } From adb7b018d96a14061712e4b6ac57174b19b1057e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 18:27:02 +0900 Subject: [PATCH 0905/3664] [qwaq] Improve focus setting The view is recorded as having focus but is not given focus until the parent view is actually in focus. This fixes the locals view not having focus at startup and thus blocking F7. --- ruamoko/qwaq/qwaq-group.r | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/qwaq-group.r index 11f724422..d94d0585f 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/qwaq-group.r @@ -97,7 +97,7 @@ trySetFocus (Group *self, int viewIndex) View *view = [self.views objectAtIndex:viewIndex]; if (([view state] & (sfDrawn | sfDisabled)) == sfDrawn && [view options] & ofCanFocus) { - if (!self.owner || [self.owner state] & sfInFocus) { + if (!self.owner || ([self.owner state] & sfInFocus)) { if (self.focused >= 0) { [[self.views objectAtIndex: self.focused] loseFocus]; } @@ -106,6 +106,8 @@ trySetFocus (Group *self, int viewIndex) self.focused = makeFirst (self, viewIndex); } [view takeFocus]; + } else { + self.focused = viewIndex; } return 1; } From 5fd63b95db77174779c894dca4c95240e04f5ecc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 19:22:41 +0900 Subject: [PATCH 0906/3664] [qfcc] Add a new failing test The struct alias is somehow blocking the detection of the call so the return value gets corrupted. --- tools/qfcc/test/func-expr2.r | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tools/qfcc/test/func-expr2.r diff --git a/tools/qfcc/test/func-expr2.r b/tools/qfcc/test/func-expr2.r new file mode 100644 index 000000000..32dad106d --- /dev/null +++ b/tools/qfcc/test/func-expr2.r @@ -0,0 +1,23 @@ +typedef struct Extent_s { + int width; + int height; +} Extent; + +extern Extent get_size (void); +extern int getlen(void); + +int main (void) +{ + int x = get_size().width - getlen() - 1; + return x != 29; +} + +Extent get_size (void) +{ + return {38, 8}; +} + +int getlen (void) +{ + return 8; +} From 15d4186fff5b4d8f7be9249d891ba18fc1ff4d46 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 20:15:50 +0900 Subject: [PATCH 0907/3664] [qfcc] Show line numbers in block sub expressions Seems more useful than expression index. --- tools/qfcc/source/dot_expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 27d535845..f66298b40 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -249,7 +249,7 @@ print_block (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) "\n", indent + 4, ""); for (se = e->e.block.head, i = 0; se; se = se->next, i++) dasprintf (dstr, "%*s%d%s\n", - indent + 4, "", i, i, expr_names[se->type]); + indent + 4, "", se->line, i, expr_names[se->type]); dasprintf (dstr, "%*s\n", indent + 2, ""); dasprintf (dstr, "%*s>];\n", indent, ""); From 98eac2afbc202edcf12d06f9f56104b0444e78db Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 20:16:32 +0900 Subject: [PATCH 0908/3664] [qfcc] Hide dependency generation commands --- tools/qfcc/test/Makefile.am | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index f6f0c6043..8560e693f 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -16,12 +16,12 @@ QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) SUFFIXES=.qfo .r .pas .r.qfo: $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo + @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo .pas.qfo: $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - $(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo + @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo + @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo QFCC_TEST_LIBS=@QFCC_TEST_LIBS@ QFCC_TEST_DEPS=@QFCC_TEST_DEPS@ @@ -46,6 +46,7 @@ test_progs_dat=\ enum.dat \ fordecl.dat \ func-expr.dat \ + func-expr2.dat \ func-static.dat \ gcd.dat \ infloop.dat \ @@ -258,6 +259,15 @@ func-expr.run: Makefile build-run include ./$(DEPDIR)/func-expr.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/func-expr.Qo +func_expr2_dat_SOURCES=func-expr2.r +func_expr2_obj=$(func_expr2_dat_SOURCES:.r=.qfo) +func-expr2.dat$(EXEEXT): $(func_expr2_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(func_expr2_obj) +func-expr2.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/func-expr2.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/func-expr2.Qo + func_static_dat_SOURCES=func-static.r func_static_obj=$(func_static_dat_SOURCES:.r=.qfo) func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) From 4de2c6b30ef923862ba453e940171203e7b6a02f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 20:16:52 +0900 Subject: [PATCH 0909/3664] [qfcc] Move alias expr inside call block expression This fixes the trampled return value when the first expression aliases the return result. --- tools/qfcc/source/expr_binary.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index b7b526853..cc75bcbcf 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -952,6 +952,11 @@ check_precedence (int op, expr_t *e1, expr_t *e2) return 0; } +static int is_call (expr_t *e) +{ + return e->type == ex_block && e->e.block.is_call; +} + expr_t * binary_expr (int op, expr_t *e1, expr_t *e2) { @@ -964,8 +969,19 @@ binary_expr (int op, expr_t *e1, expr_t *e2) e1 = convert_vector (e1); // FIXME this is target-specific info and should not be in the // expression tree + if ((e1->type == ex_expr || e1->type == ex_uexpr) && e1->e.expr.op == 'A' + && is_call (e1->e.expr.e1)) { + // move the alias expression inside the block so the following check + // can detect the call and move the temp assignment into the block + expr_t *block = e1->e.expr.e1; + e1->e.expr.e1 = block->e.block.result; + block->e.block.result = e1; + e1 = block; + } if (e1->type == ex_block && e1->e.block.is_call && has_function_call (e2) && e1->e.block.result) { + // the temp assignment needs to be insided the block so assignment + // code generation doesn't see it when applying right-associativity expr_t *tmp = new_temp_def_expr (get_type (e1->e.block.result)); e = assign_expr (tmp, e1->e.block.result); append_expr (e1, e); From 8dcb3fefb3b6793e2065bdf5334eeff978830e44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 20:31:14 +0900 Subject: [PATCH 0910/3664] [qwaq] Offset position when forwardning mvaddstr --- ruamoko/qwaq/qwaq-view.r | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 24b6b77ba..9e28c7a68 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -206,6 +206,13 @@ updateScreenCursor (View *view) [textContext mvaddch: pos, ch]; } +- (void) mvaddstr: (Point) pos, string str +{ + pos.x += xpos; + pos.y += ypos; + [textContext mvaddstr: pos, str]; +} + -move: (Point) delta { xpos += delta.x; From b2de2a9f3be4965774696155f79956bfb4d7df9e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 Mar 2020 21:01:39 +0900 Subject: [PATCH 0911/3664] [qwaq] Display values for simple defs Mostly works, but need to sort out clearing the view without clearing the window (silly curses and its full-line clears) --- ruamoko/qwaq/qwaq-debugger.r | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index 564e376b1..a33ec59b1 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -145,29 +145,57 @@ update_current_func (Debugger *self, unsigned fnum) qdb_def_t *def = local_defs + y; [locals_view mvprintf:{0, y}, "%s", qdb_get_string (debug_target, def.name)]; + @param value = nil; string valstr = "--"; - printf ("def type_size %d\n", def.type_size); + unsigned offset = func.local_data + def.offset; + printf ("%d %d %s %d\n", def.type_size, offset, + qdb_get_string (debug_target, def.name), + def.type_encoding); + qdb_get_data (debug_target, offset, def.type_size >> 16, + &value); switch (def.type_size & 0xffff) { case ev_void: case ev_invalid: case ev_type_count: break; case ev_string: + valstr = qdb_get_string (debug_target, value.integer_val); + break; case ev_float: + valstr = sprintf ("%.9g", value.float_val); + break; case ev_vector: + valstr = sprintf ("%.9v", value.vector_val); + break; case ev_entity: + valstr = sprintf ("%e", value.entity_val); + break; case ev_field: + valstr = sprintf ("[%x]", value.field_val); + break; case ev_func: + valstr = sprintf ("[%x]", value.func_val); + break; case ev_pointer: + valstr = sprintf ("[%x]", value.pointer_val); + break; case ev_quat: + valstr = sprintf ("[%q]", value.quaternion_val); + break; case ev_integer: + valstr = sprintf ("%d", value.integer_val); + break; case ev_uinteger: + valstr = sprintf ("%d", value.integer_val); + break; case ev_short: + valstr = sprintf ("%d", value.integer_val); + break; case ev_double: - valstr = sprintf ("%d", def.type_size >> 16); + valstr = sprintf ("%.17g", value.double_val); break; } - int x = [locals_view size].width - strlen (valstr) - 1; + int x = [locals_view size].width - strlen (valstr); [locals_view mvaddstr:{x, y}, valstr]; } } From 75394cc4f83d7cf734e0838f58f695ba5a6c4f83 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 12:24:14 +0900 Subject: [PATCH 0912/3664] [gamecode,qfcc] Use enums for type encoding types The enums are forced to 32 bits via bitfield spec, so can't use sizeof on them, but this makes switch enum checks work in gcc. --- include/QF/pr_type.h | 4 ++-- tools/qfcc/source/obj_type.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index c9e45185c..a0a0f0ad0 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -94,11 +94,11 @@ typedef struct qfot_array_s { arrays. */ typedef struct qfot_type_s { - pr_int_t meta; ///< meta type: ty_meta_e + ty_meta_e meta:32; ///< meta type pr_int_t size; ///< total word size of this encoding string_t encoding; ///< Objective-QC encoding union { - pr_int_t type; ///< ty_basic: etype_t + etype_t type:32; ///< ty_basic: etype_t qfot_fldptr_t fldptr; ///< ty_basic, ev_pointer/ev_field qfot_func_t func; ///< ty_basic, ev_func qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index c21e7e576..d12c196dc 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -151,7 +151,8 @@ qfo_encode_none (type_t *type) else if (type->type == ev_pointer || type->type == ev_field) return qfo_encode_fldptr (type); - def = qfo_new_encoding (type, sizeof (enc->t.type)); + // can't use sizeof on enc->t.type, but pr_uint_t is the backing type + def = qfo_new_encoding (type, sizeof (pr_uint_t)); enc = D_POINTER (qfot_type_t, def); enc->t.type = type->type; return def; From 53fd55143ef94a91d34727941181d576f522f2a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 12:26:44 +0900 Subject: [PATCH 0913/3664] [qfcc] Fix missed none->basic rename --- tools/qfcc/source/obj_type.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index d12c196dc..38a28a9e8 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -141,7 +141,7 @@ qfo_encode_fldptr (type_t *type) } static def_t * -qfo_encode_none (type_t *type) +qfo_encode_basic (type_t *type) { qfot_type_t *enc; def_t *def; @@ -260,7 +260,7 @@ qfo_encode_type (type_t *type) reloc_t *relocs = 0; static encode_f funcs[] = { - qfo_encode_none, // ty_none + qfo_encode_basic, // ty_basic qfo_encode_struct, // ty_struct qfo_encode_struct, // ty_union qfo_encode_struct, // ty_enum From 8b1e4eea58d03806a32d8d60f1fb59b3b39927cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 12:27:46 +0900 Subject: [PATCH 0914/3664] [qfcc] Bring back the core of type aliasing No aliasing is done yet, but most of the infrastructure is there again. --- include/QF/pr_type.h | 7 +++++++ libs/gamecode/pr_debug.c | 6 ++++++ tools/qfcc/include/type.h | 5 +++++ tools/qfcc/source/dump_globals.c | 4 ++++ tools/qfcc/source/obj_file.c | 5 +++++ tools/qfcc/source/type.c | 17 +++++++++++++++++ 6 files changed, 44 insertions(+) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index a0a0f0ad0..db3376684 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -47,8 +47,14 @@ typedef enum { ty_enum, ty_array, ty_class, + ty_alias, } ty_meta_e; +typedef struct qfot_alias_s { + pr_int_t type; ///< type at end of alias chain + pointer_t aux_type; ///< referenced type + string_t name; ///< alias name +} qfot_alias_t; typedef struct qfot_fldptr_s { pr_int_t type; ///< ev_field or ev_pointer @@ -104,6 +110,7 @@ typedef struct qfot_type_s { qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum qfot_array_t array; ///< ty_array string_t class; ///< ty_class + qfot_alias_t alias; ///< ty_alias } t; } qfot_type_t; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 63f4444b4..dabaf227f 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -234,6 +234,9 @@ pr_debug_type_size (const progs_t *pr, const qfot_type_t *type) return type->t.array.size * size; case ty_class: return 1; //FIXME or should it return sizeof class struct? + case ty_alias: + aux_type = &G_STRUCT (pr, qfot_type_t, type->t.alias.aux_type); + return pr_debug_type_size (pr, aux_type); } return 0; } @@ -883,6 +886,9 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) case ty_class: raw_type_view.class_view (type, value, data); break; + case ty_alias://XXX + type = &G_STRUCT (data->pr, qfot_type_t, type->t.alias.aux_type); + return value_string (data, type, value); } return data->dstr->str; } diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index ba3b82f1e..bb6133bb1 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -51,6 +51,10 @@ typedef struct ty_array_s { int size; } ty_array_t; +typedef struct ty_alias_s { + struct type_s *type; +} ty_alias_t; + typedef struct type_s { etype_t type; ///< ev_invalid means structure/array etc const char *name; @@ -64,6 +68,7 @@ typedef struct type_s { ty_array_t array; struct symtab_s *symtab; struct class_s *class; + ty_alias_t alias; } t; struct type_s *next; int freeable; diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 9b5900454..198a952cb 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -556,6 +556,10 @@ dump_qfo_types (qfo_t *qfo, int base_address) case ty_class: printf (" %-5x\n", type->t.class); break; + case ty_alias: + printf (" %s %d %-5x\n", QFO_GETSTR (qfo, type->t.alias.name), + type->t.alias.type, type->t.alias.aux_type); + break; } } } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 45d01be47..0c08810f0 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -649,6 +649,7 @@ get_def_type (qfo_t *qfo, pointer_t type) return ev_void; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { + case ty_alias: //XXX case ty_basic: // field, pointer and function types store their basic type in // the same location. @@ -676,6 +677,8 @@ get_type_size (qfo_t *qfo, pointer_t type) return 1; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { + case ty_alias: + return get_type_size (qfo, type_def->t.alias.aux_type); case ty_basic: // field, pointer and function types store their basic type in // the same location. @@ -724,6 +727,8 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) return 0; type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { + case ty_alias: + return get_type_alignment_log (qfo, type_def->t.alias.aux_type); case ty_basic: // field, pointer and function types store their basic type in // the same location. diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 4404f2ed0..dc09104c3 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -297,6 +297,8 @@ types_same (type_t *a, type_t *b) if (a->t.class != b->t.class) return 0; return compare_protocols (a->protos, b->protos); + case ty_alias: + return !strcmp (a->name, b->name); } internal_error (0, "we be broke"); } @@ -346,6 +348,9 @@ find_type (type_t *type) break; case ty_class: break; + case ty_alias: + type->t.alias.type = find_type (type->t.alias.type); + break; } } @@ -453,6 +458,11 @@ print_type_str (dstring_t *str, const type_t *type) return; } switch (type->meta) { + case ty_alias: + dasprintf (str, "({%s=", type->name); + print_type_str (str, type->t.alias.type); + dstring_appendstr (str, "})"); + return; case ty_class: dasprintf (str, " %s", type->t.class->name); if (type->protos) @@ -610,6 +620,11 @@ encode_type (dstring_t *encoding, const type_t *type) if (!type) return; switch (type->meta) { + case ty_alias: // XXX do I want this, or just the unaliased type? + dasprintf (encoding, "{%s>", type->name); + encode_type (encoding, type->t.alias.type); + dasprintf (encoding, "}"); + return; case ty_class: encode_class (encoding, type); return; @@ -936,6 +951,8 @@ type_size (const type_t *type) size += type_size (class->super_class->type); return size; } + case ty_alias: + return type_size (type->t.alias.type); } return 0; } From ab3d91f0c35acc76b624f4e6a71dc5c789fe2d2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 15:16:41 +0900 Subject: [PATCH 0915/3664] [qfcc] Clean up simple type checking All simple type checks are now done using is_* helper functions. This will help hide the implementation details of the type system from the rest of the compiler (especially the changes needed for type aliasing). --- tools/qfcc/include/class.h | 12 +++-- tools/qfcc/source/class.c | 90 +++++++++++++++++++++------------ tools/qfcc/source/constfold.c | 36 ++++++------- tools/qfcc/source/def.c | 8 +-- tools/qfcc/source/dot_expr.c | 4 +- tools/qfcc/source/expr.c | 26 +++++----- tools/qfcc/source/expr_assign.c | 4 +- tools/qfcc/source/expr_bool.c | 6 +-- tools/qfcc/source/function.c | 6 +-- tools/qfcc/source/method.c | 12 ++--- tools/qfcc/source/qc-parse.y | 6 +-- tools/qfcc/source/statements.c | 4 +- tools/qfcc/source/struct.c | 2 +- tools/qfcc/source/stub.c | 4 +- tools/qfcc/source/switch.c | 5 +- tools/qfcc/source/type.c | 10 ++-- tools/qfcc/source/value.c | 2 +- 17 files changed, 133 insertions(+), 104 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index 68cefcd12..e9bcb9c71 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -115,10 +115,14 @@ struct method_s; struct symbol_s; struct selector_s; -int obj_is_id (const struct type_s *type) __attribute__((pure)); -int obj_is_class (const struct type_s *type) __attribute__((pure)); -int obj_is_Class (const struct type_s *type) __attribute__((const)); -int obj_is_classptr (const struct type_s *type) __attribute__((pure)); +int is_id (const struct type_s *type) __attribute__((pure)); +int is_class (const struct type_s *type) __attribute__((pure)); +int is_Class (const struct type_s *type) __attribute__((const)); +int is_classptr (const struct type_s *type) __attribute__((pure)); +int is_SEL (const struct type_s *type) __attribute__((pure)); +int is_object (const struct type_s *type) __attribute__((pure)); +int is_method (const struct type_s *type) __attribute__((pure)); +int is_method_description (const struct type_s *type) __attribute__((pure)); int obj_types_assignable (const struct type_s *dst, const struct type_s *src); class_t *extract_class (class_type_t *class_type) __attribute__((pure)); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 8b2081e82..9c962d50e 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -218,7 +218,7 @@ emit_instance_classname (def_t *def, void *data, int index) { obj_static_instances_data_t *da = (obj_static_instances_data_t *)data; - if (def->type != &type_string) + if (!is_string(def->type)) internal_error (0, "%s: expected string def", __FUNCTION__); EMIT_STRING (def->space, D_STRING (def), da->class_name); } @@ -317,7 +317,7 @@ emit_static_instances_list (void) } int -obj_is_id (const type_t *type) +is_id (const type_t *type) { if (type == &type_id) return 1; @@ -334,7 +334,7 @@ obj_is_id (const type_t *type) } int -obj_is_class (const type_t *type) +is_class (const type_t *type) { if (type->type == ev_invalid && type->meta == ty_class) return 1; @@ -342,7 +342,7 @@ obj_is_class (const type_t *type) } int -obj_is_Class (const type_t *type) +is_Class (const type_t *type) { if (type == &type_Class) return 1; @@ -350,25 +350,49 @@ obj_is_Class (const type_t *type) } int -obj_is_classptr (const type_t *type) +is_classptr (const type_t *type) { // easy cases first :) - if (obj_is_id (type) || obj_is_Class (type)) + if (is_id (type) || is_Class (type)) return 1; if (type->type != ev_pointer) return 0; type = type->t.fldptr.type; - if (obj_is_class (type)) + if (is_class (type)) return 1; return 0; } +int +is_SEL (const type_t *type) +{ + return type == &type_SEL; +} + +int +is_object (const type_t *type) +{ + return type == &type_obj_object; +} + +int +is_method (const type_t *type) +{ + return type == &type_obj_method; +} + +int +is_method_description (const type_t *type) +{ + return type == &type_obj_method_description; +} + static protocollist_t * obj_get_class_protos (const type_t *type) { if (is_pointer (type)) type = type->t.fldptr.type; - if (obj_is_class (type)) + if (is_class (type)) return type->t.class->protocols; return 0; } @@ -386,7 +410,7 @@ obj_get_categories (const type_t *type) { if (is_pointer (type)) type = type->t.fldptr.type; - if (obj_is_class (type)) + if (is_class (type)) return type->t.class->categories; return 0; } @@ -400,14 +424,14 @@ obj_classname (const type_t *type) if (!str) str = dstring_new (); dstring_clearstr (str); - if (obj_is_id (type)) { + if (is_id (type)) { dstring_copystr (str, "id"); - } else if (obj_is_Class (type)) { + } else if (is_Class (type)) { dstring_copystr (str, "Class"); } else { if (is_pointer (type)) type = type->t.fldptr.type; - if (obj_is_class (type)) + if (is_class (type)) dstring_copystr (str, type->t.class->name); } if ((protos = obj_get_protos (type))) @@ -437,17 +461,17 @@ obj_types_assignable (const type_t *dst, const type_t *src) int i; //puts ("%$$\"$#%"); - if (!obj_is_classptr (src)) { + if (!is_classptr (src)) { // if dst is a class pointer, then the types are not compatible, // otherwise unknown - return obj_is_classptr (dst) - 1; + return is_classptr (dst) - 1; } - if (!obj_is_classptr (dst)) { + if (!is_classptr (dst)) { return -1; } - dst_is_proto = obj_is_id (dst) && (dst_protos = obj_get_protos (dst)); - src_is_proto = obj_is_id (src) && (src_protos = obj_get_protos (src)); + dst_is_proto = is_id (dst) && (dst_protos = obj_get_protos (dst)); + src_is_proto = is_id (src) && (src_protos = obj_get_protos (src)); if (dst_is_proto) { if (src_is_proto) { @@ -460,7 +484,7 @@ obj_types_assignable (const type_t *dst, const type_t *src) return 1; } } - } else if (!obj_is_id (src)) { + } else if (!is_id (src)) { src_protos = obj_get_class_protos (src); for (i = 0; i < dst_protos->count; i++) { if (procollist_find_protocol (src_protos, dst_protos->list[i])) @@ -477,7 +501,7 @@ obj_types_assignable (const type_t *dst, const type_t *src) } else if (src_is_proto) { } else { } - if (obj_is_id (dst) || obj_is_id (src)) + if (is_id (dst) || is_id (src)) return 1; // check dst is a base class of src @@ -700,7 +724,7 @@ emit_ivar_count (def_t *def, void *data, int index) { ivar_data_t *ivar_data = (ivar_data_t *) data; - if (def->type != &type_integer) + if (!is_integer(def->type)) internal_error (0, "%s: expected integer def", __FUNCTION__); D_INT (def) = ivar_data->count; } @@ -1132,11 +1156,11 @@ class_message_response (type_t *clstype, int class_msg, expr_t *sel) if (!selector) return 0; - if (!obj_is_classptr (clstype) && !obj_is_class (clstype)) { + if (!is_classptr (clstype) && !is_class (clstype)) { error (0, "neither class nor object"); return 0; } - if (obj_is_id (clstype)) { + if (is_id (clstype)) { protocollist_t *protos = clstype->t.fldptr.type->protos; if (protos) { if ((m = protocollist_find_method (protos, selector, !class_msg))) { @@ -1149,12 +1173,12 @@ class_message_response (type_t *clstype, int class_msg, expr_t *sel) dstring_delete (dstr); } } else { - if (obj_is_class (clstype)) { + if (is_class (clstype)) { class = clstype->t.class; - } else if (obj_is_class (clstype->t.fldptr.type)) { + } else if (is_class (clstype->t.fldptr.type)) { class = clstype->t.fldptr.type->t.class; } - if (class && class->type != &type_obj_object) { + if (class && !is_object(class->type)) { if (!class->interface_declared) { class->interface_declared = 1; warning (0, "cannot find interface declaration for `%s'", @@ -1180,7 +1204,7 @@ class_message_response (type_t *clstype, int class_msg, expr_t *sel) } } m = find_method (selector->name); - if (!m && (!class || class->type == &type_obj_object)) { + if (!m && (!class || is_object(class->type))) { warning (sel, "could not find method for %c%s", class_msg ? '+' : '-', selector->name); } @@ -1383,7 +1407,7 @@ emit_symtab_ref_cnt (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (def->type != &type_integer) + if (!is_integer(def->type)) internal_error (0, "%s: expected integer def", __FUNCTION__); D_INT (def) = 0; if (da->refs) @@ -1395,7 +1419,7 @@ emit_symtab_refs (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (def->type != &type_SEL) + if (!is_SEL(def->type)) internal_error (0, "%s: expected SEL def", __FUNCTION__); D_INT (def) = 0; if (da->refs) @@ -1407,7 +1431,7 @@ emit_symtab_cls_def_cnt (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (def->type != &type_integer) + if (!is_integer(def->type)) internal_error (0, "%s: expected integer def", __FUNCTION__); D_INT (def) = da->cls_def_cnt; } @@ -1417,7 +1441,7 @@ emit_symtab_cat_def_cnt (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (def->type != &type_integer) + if (!is_integer(def->type)) internal_error (0, "%s: expected integer def", __FUNCTION__); D_INT (def) = da->cat_def_cnt; } @@ -1716,7 +1740,7 @@ emit_protocol (protocol_t *protocol) static void emit_protocol_next (def_t *def, void *data, int index) { - if (def->type != &type_pointer) { + if (!is_pointer(def->type)) { internal_error (0, "%s: expected pointer def", __FUNCTION__); } D_INT (def) = 0; @@ -1727,7 +1751,7 @@ emit_protocol_count (def_t *def, void *data, int index) { protocollist_t *protocols = (protocollist_t *) data; - if (def->type != &type_integer) { + if (!is_integer(def->type)) { internal_error (0, "%s: expected integer def", __FUNCTION__); } D_INT (def) = protocols->count; @@ -1739,7 +1763,7 @@ emit_protocol_list_item (def_t *def, void *data, int index) protocollist_t *protocols = (protocollist_t *) data; protocol_t *protocol = protocols->list[index]; - if (!is_array (def->type) || def->type->t.array.type != &type_pointer) { + if (!is_array (def->type) || !is_pointer(def->type->t.array.type)) { internal_error (0, "%s: expected array of pointer def", __FUNCTION__); } if (index < 0 || index >= protocols->count) { diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index f367987a3..439f4760f 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -146,7 +146,7 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) static expr_t * convert_to_float (expr_t *e) { - if (get_type (e) == &type_float) + if (is_float(get_type (e))) return e; switch (e->type) { @@ -181,7 +181,7 @@ convert_to_float (expr_t *e) static expr_t * convert_to_double (expr_t *e) { - if (get_type (e) == &type_double) + if (is_double(get_type (e))) return e; switch (e->type) { @@ -227,7 +227,7 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) return error (e1, "invalid operator for float"); if (op == '=') { - if ((type = get_type (e1)) != &type_float) { + if (!is_float(type = get_type (e1))) { //FIXME optimize casting a constant e->e.expr.e2 = e2 = cf_cast_expr (type, e2); } else if ((conv = convert_to_float (e2)) != e2) { @@ -356,7 +356,7 @@ do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2) return error (e1, "invalid operator for double"); if (op == '=') { - if ((type = get_type (e1)) != &type_double) { + if (!is_double(type = get_type (e1))) { //FIXME optimize casting a constant e->e.expr.e2 = e2 = cf_cast_expr (type, e2); } else if ((conv = convert_to_double (e2)) != e2) { @@ -454,7 +454,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) static int valid[] = {'=', '+', '-', '*', EQ, NE, 0}; expr_t *t; - if (get_type (e1) != &type_vector) { + if (!is_vector(get_type (e1))) { if (op != '*') return error (e1, "invalid operator for vector"); @@ -463,7 +463,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.e1 = e1 = e2; e2 = t; } - if (get_type (e2) != &type_vector) { + if (!is_vector(get_type (e2))) { e->e.expr.e2 = e2 = convert_to_float (e2); if (op != '*' && op != '/') return error (e1, "invalid operator for vector"); @@ -476,7 +476,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_integer; else e->e.expr.type = &type_float; - } else if (op == '*' && get_type (e2) == &type_vector) { + } else if (op == '*' && is_vector(get_type (e2))) { e->e.expr.type = &type_float; } else if (op == '/' && !is_constant (e1)) { e2 = fold_constants (binary_expr ('/', new_float_expr (1), e2)); @@ -541,7 +541,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) e = new_vector_expr (v); break; case '*': - if (get_type (e2) == &type_vector) { + if (is_vector(get_type (e2))) { e = new_float_expr (DotProduct (v1, v2)); } else { VectorScale (v1, v2[0], v); @@ -577,7 +577,7 @@ do_op_entity (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_float; return e; } - if (op != '=' || type != &type_entity) + if (op != '=' || !is_entity(type)) return error (e1, "invalid operator for entity"); e->e.expr.type = &type_entity; return e; @@ -649,7 +649,7 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op != '.' && op != '&' && op != 'M' && extract_type (e1) != extract_type (e2)) return type_mismatch (e1, e2, op); - if ((op == '.' || op == '&') && get_type (e2) == &type_uinteger) + if ((op == '.' || op == '&') && is_uinteger(get_type (e2))) e->e.expr.e2 = cf_cast_expr (&type_integer, e2); return e; } @@ -684,7 +684,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) static int valid[] = {'=', '+', '-', '*', EQ, NE, 0}; expr_t *t; - if (get_type (e1) != &type_quaternion) { + if (!is_quaternion(get_type (e1))) { if (op != '*' && op != '/') return error (e1, "invalid operator for quaternion"); @@ -695,7 +695,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) e2 = t; } } - if (get_type (e2) != &type_quaternion) { + if (!is_quaternion(get_type (e2))) { e->e.expr.e2 = e2 = convert_to_float (e2); if (op != '*' && op != '/') return error (e1, "invalid operator for quaternion"); @@ -765,7 +765,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) e = new_quaternion_expr (q); break; case '*': - if (get_type (e2) == &type_quaternion) { + if (is_quaternion(get_type (e2))) { QuatMult (q1, q2, q); } else { QuatScale (q1, q2[3], q); @@ -1397,7 +1397,7 @@ uop_float (int op, expr_t *e, expr_t *e1) if (op == '+') return e1; type = get_type (e); - if (op == 'C' && type != &type_integer && type != &type_double) + if (op == 'C' && !is_integer(type) && !is_double(type)) return error (e1, "invalid cast of float"); if (!is_constant (e1)) return e; @@ -1410,7 +1410,7 @@ uop_float (int op, expr_t *e, expr_t *e1) case '~': return new_float_expr (~(int) expr_float (e1)); case 'C': - if (type == &type_integer) { + if (is_integer(type)) { return new_integer_expr (expr_float (e1)); } else { return new_double_expr (expr_float (e1)); @@ -1549,7 +1549,7 @@ uop_integer (int op, expr_t *e, expr_t *e1) get_op_string (op)); if (op == '+') return e1; - if (op == 'C' && get_type (e) != &type_float) + if (op == 'C' && !is_float(get_type (e))) return error (e1, "invalid cast of int"); if (!is_constant (e1)) return e; @@ -1624,7 +1624,7 @@ uop_double (int op, expr_t *e, expr_t *e1) if (op == '+') return e1; type = get_type (e); - if (op == 'C' && type != &type_integer && type != &type_float) + if (op == 'C' && !is_integer(type) && !is_float(type)) return error (e1, "invalid cast of double"); if (!is_constant (e1)) return e; @@ -1635,7 +1635,7 @@ uop_double (int op, expr_t *e, expr_t *e1) print_type (get_type (e)); return cmp_result_expr (!expr_double (e1)); case 'C': - if (type == &type_integer) { + if (is_integer(type)) { return new_integer_expr (expr_double (e1)); } else { return new_float_expr (expr_double (e1)); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 2fbf0bf08..7c671fb3d 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -140,7 +140,7 @@ new_def (const char *name, type_t *type, defspace_t *space, if (!space && storage != sc_extern) internal_error (0, "non-external def with no storage space"); - if (obj_is_class (type)) { + if (is_class (type)) { error (0, "statically allocated instance of class %s", type->t.class->name); return def; @@ -498,7 +498,7 @@ init_field_def (def_t *def, expr_t *init, storage_class_t storage) def->nosave = 1; } // no support for initialized field vector componets (yet?) - if (type == &type_vector && options.code.vector_components) + if (is_vector(type) && options.code.vector_components) init_vector_components (field_sym, 1); } else if (init->type == ex_symbol) { symbol_t *sym = init->e.symbol; @@ -566,7 +566,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, sym->s.def = new_def (sym->name, sym->type, space, storage); reloc_attach_relocs (relocs, &sym->s.def->relocs); } - if (sym->type == &type_vector && options.code.vector_components) + if (is_vector(sym->type) && options.code.vector_components) init_vector_components (sym, 0); if (sym->type->type == ev_field && storage != sc_local && storage != sc_param) @@ -582,7 +582,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, if (init->type == ex_error) return; if ((is_array (sym->type) || is_struct (sym->type) - || sym->type == &type_vector || sym->type == &type_quaternion) + || is_vector(sym->type) || is_quaternion(sym->type)) && ((init->type == ex_compound) || init->type == ex_nil)) { init_elements (sym->s.def, init); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index f66298b40..82c29c8d6 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -387,7 +387,7 @@ print_vector (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - if (e->e.vector.type == &type_vector) { + if (is_vector(e->e.vector.type)) { expr_t *x = e->e.vector.list; expr_t *y = x->next; expr_t *z = y->next; @@ -398,7 +398,7 @@ print_vector (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, y); dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, z); } - if (e->e.vector.type == &type_quaternion) { + if (is_quaternion(e->e.vector.type)) { if (e->e.vector.list->next->next) { expr_t *x = e->e.vector.list; expr_t *y = x->next; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index ac128e378..f4291bb33 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -133,7 +133,7 @@ convert_vector (expr_t *e) if (e->type != ex_vector) return e; - if (e->e.vector.type == &type_vector) { + if (is_vector(e->e.vector.type)) { // guaranteed to have three elements expr_t *x = e->e.vector.list; expr_t *y = x->next; @@ -155,7 +155,7 @@ convert_vector (expr_t *e) e->e.vector.list = x; return e; } - if (e->e.vector.type == &type_quaternion) { + if (is_quaternion(e->e.vector.type)) { // guaranteed to have two or four elements if (e->e.vector.list->next->next) { // four vals: x, y, z, w @@ -1321,7 +1321,7 @@ get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2) return 0; } field = symtab_lookup (strct, sym->name); - if (!field && t1 != &type_entity) { + if (!field && !is_entity(t1)) { error (e2, "'%s' has no member named '%s'", t1->name + 4, sym->name); e1->type = ex_error; } @@ -1370,7 +1370,7 @@ field_expr (expr_t *e1, expr_t *e2) e = new_binary_expr ('&', e1, e2); e->e.expr.type = pointer_type (field->type); return unary_expr ('.', e); - } else if (obj_is_class (t1->t.fldptr.type)) { + } else if (is_class (t1->t.fldptr.type)) { class_t *class = t1->t.fldptr.type->t.class; symbol_t *sym = e2->e.symbol;//FIXME need to check symbol_t *ivar; @@ -1394,7 +1394,7 @@ field_expr (expr_t *e1, expr_t *e2) return e1; if (e1->type == ex_expr && e1->e.expr.op == '.' - && get_type (e1->e.expr.e1) == &type_entity) { + && is_entity(get_type (e1->e.expr.e1))) { // undo the . expression e2 = e1->e.expr.e2; e1 = e1->e.expr.e1; @@ -1426,7 +1426,7 @@ field_expr (expr_t *e1, expr_t *e2) return new_offset_alias_expr (field->type, e1, field->s.offset); } } - } else if (obj_is_class (t1)) { + } else if (is_class (t1)) { //Class instance variables aren't allowed and thus declaring one //is treated as an error, so this is a follow-on error. return error (e1, "class instance access"); @@ -1794,8 +1794,8 @@ bitnot_expr: expr_t *n = new_unary_expr (op, e); type_t *t = get_type (e); - if (t != &type_integer && t != &type_float - && t != &type_quaternion) + if (!is_integer(t) && !is_float(t) + && !is_quaternion(t)) return error (e, "invalid type for unary ~"); n->e.expr.type = t; return n; @@ -1963,7 +1963,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) e = expr_file_line (new_binary_expr ('c', fexpr, args), fexpr); e->e.expr.type = ftype->t.func.type; append_expr (call, e); - if (ftype->t.func.type != &type_void) { + if (!is_void(ftype->t.func.type)) { call->e.block.result = new_ret_expr (ftype->t.func.type); } else if (options.traditional) { call->e.block.result = new_ret_expr (&type_float); @@ -2030,7 +2030,7 @@ return_expr (function_t *f, expr_t *e) type_t *ret_type = f->sym->type->t.func.type; if (!e) { - if (ret_type != &type_void) { + if (!is_void(ret_type)) { if (options.traditional) { if (options.warnings.traditional) warning (e, @@ -2057,7 +2057,7 @@ return_expr (function_t *f, expr_t *e) if (e->type == ex_error) { return e; } - if (ret_type == &type_void) { + if (is_void(ret_type)) { if (!options.traditional) return error (e, "returning a value for a void function"); if (options.warnings.traditional) @@ -2066,11 +2066,11 @@ return_expr (function_t *f, expr_t *e) if (e->type == ex_bool) { e = convert_from_bool (e, ret_type); } - if (ret_type == &type_float && is_integer_val (e)) { + if (is_float(ret_type) && is_integer_val (e)) { convert_int (e); t = &type_float; } - if (t == &type_void) { + if (is_void(t)) { if (e->type == ex_nil) { t = ret_type; convert_nil (e, t); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 7d1f1aab9..937da6d5c 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -222,7 +222,7 @@ assign_vector_expr (expr_t *dst, expr_t *src) } } if (src->type == ex_vector && dst->type != ex_vector) { - if (src->e.vector.type == &type_vector) { + if (is_vector(src->e.vector.type)) { // guaranteed to have three elements sx = src->e.vector.list; sy = sx->next; @@ -237,7 +237,7 @@ assign_vector_expr (expr_t *dst, expr_t *src) block->e.block.result = dst; return block; } - if (src->e.vector.type == &type_quaternion) { + if (is_quaternion(src->e.vector.type)) { // guaranteed to have two or four elements if (src->e.vector.list->next->next) { // four vals: x, y, z, w diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 74f8d24de..0fcb8b394 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -96,7 +96,7 @@ test_expr (expr_t *e) case ev_uinteger: case ev_integer: case ev_short: - if (type_default != &type_integer) { + if (!is_integer(type_default)) { if (is_constant (e)) { return cast_expr (type_default, e); } @@ -106,7 +106,7 @@ test_expr (expr_t *e) case ev_float: if (options.code.fast_float || options.code.progsversion == PROG_ID_VERSION) { - if (type_default != &type_float) { + if (!is_float(type_default)) { if (is_constant (e)) { return cast_expr (type_default, e); } @@ -270,7 +270,7 @@ convert_bool (expr_t *e, int block) } if (e->type == ex_uexpr && e->e.expr.op == '!' - && get_type (e->e.expr.e1) != &type_string) { + && !is_string(get_type (e->e.expr.e1))) { e = convert_bool (e->e.expr.e1, 0); if (e->type == ex_error) return e; diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 234d622d9..e9cb0c823 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -172,7 +172,7 @@ parse_params (type_t *type, param_t *parms) type_t *new; int count = 0; - if (type && obj_is_class (type)) { + if (type && is_class (type)) { error (0, "cannot return an object (forgot *?)"); type = &type_id; } @@ -197,7 +197,7 @@ parse_params (type_t *type, param_t *parms) internal_error (0, 0); new->t.func.num_params = -(new->t.func.num_params + 1); } else if (p->type) { - if (obj_is_class (p->type)) { + if (is_class (p->type)) { error (0, "cannot use an object as a parameter (forgot *?)"); p->type = &type_id; } @@ -216,7 +216,7 @@ check_params (param_t *params) if (!params) return 0; while (p) { - if (p->type == &type_void) { + if (p->type && is_void(p->type)) { if (p->name) { error (0, "parameter %d ('%s') has incomplete type", num, p->name); diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 458fb00b2..74971ef1c 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -480,7 +480,7 @@ get_selector (expr_t *sel) selector_t _sel = {0, 0, 0}; if (sel->type != ex_expr && sel->e.expr.op != '&' - && sel->e.expr.type != &type_SEL) { + && !is_SEL(sel->e.expr.type)) { error (sel, "not a selector"); return 0; } @@ -525,7 +525,7 @@ emit_selectors (void) static void emit_methods_next (def_t *def, void *data, int index) { - if (def->type != &type_pointer) + if (!is_pointer(def->type)) internal_error (0, "%s: expected pointer def", __FUNCTION__); D_INT (def) = 0; } @@ -535,7 +535,7 @@ emit_methods_count (def_t *def, void *data, int index) { methodlist_t *methods = (methodlist_t *) data; - if (def->type != &type_integer) + if (!is_integer(def->type)) internal_error (0, "%s: expected integer def", __FUNCTION__); D_INT (def) = methods->count; } @@ -547,7 +547,7 @@ emit_methods_list_item (def_t *def, void *data, int index) method_t *m; pr_method_t *meth; - if (!is_array (def->type) || def->type->t.array.type != &type_obj_method) + if (!is_array (def->type) || !is_method(def->type->t.array.type)) internal_error (0, "%s: expected array of method def", __FUNCTION__); if (index < 0 || index >= methods->count) @@ -614,7 +614,7 @@ emit_method_list_count (def_t *def, void *data, int index) { methodlist_t *methods = (methodlist_t *) data; - if (def->type != &type_integer) + if (!is_integer(def->type)) internal_error (0, "%s: expected integer def", __FUNCTION__); D_INT (def) = methods->count; } @@ -627,7 +627,7 @@ emit_method_list_item (def_t *def, void *data, int index) pr_method_description_t *desc; if (!is_array (def->type) - || def->type->t.array.type != &type_obj_method_description) { + || !is_method_description(def->type->t.array.type)) { internal_error (0, "%s: expected array of method_description def", __FUNCTION__); } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 4e49397bc..70ca90fc3 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -704,7 +704,7 @@ struct_defs | DEFS '(' identifier ')' { $3 = check_undefined ($3); - if (!$3->type || !obj_is_class ($3->type)) { + if (!$3->type || !is_class ($3->type)) { error (0, "`%s' is not a class", $3->name); } else { // replace the struct symbol table with one built from @@ -860,7 +860,7 @@ qc_func_params | '(' ps qc_var_list ')' { $$ = check_params ($3); } | '(' ps TYPE ')' { - if ($3 != &type_void) + if (!is_void ($3)) PARSE_ERROR; $$ = 0; } @@ -1629,7 +1629,7 @@ class_name if (!$1->table) { symtab_addsymbol (current_symtab, $1); } - } else if (!obj_is_class ($1->type)) { + } else if (!is_class ($1->type)) { error (0, "`%s' is not a class", $1->name); $$ = get_class (0, 1); } else { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ba7af0765..bd2508e54 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1347,7 +1347,7 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) pr.source_line = e->line; tmp = new_temp_def_expr (vec_type); - if (vec_type == &type_vector) { + if (is_vector(vec_type)) { // guaranteed to have three elements x = e->e.vector.list; y = x->next; @@ -2017,7 +2017,7 @@ check_final_block (sblock_t *sblock) if (statement_is_return (s)) return; } - if (current_func->sym->type->t.func.type != &type_void) + if (!is_void(current_func->sym->type->t.func.type)) warning (0, "control reaches end of non-void function"); if (s && s->type >= st_func) { // func and flow end blocks, so we need to add a new block to take the diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 85c8a85ba..2e828de1b 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -125,7 +125,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) for (s = symtab->symbols; s; s = s->next) { if (s->sy_type != sy_var) continue; - if (obj_is_class (s->type)) { + if (is_class (s->type)) { error (0, "statically allocated instance of class %s", s->type->t.class->name); } diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index 4ff08975c..405104126 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -45,5 +45,7 @@ __attribute__((const)) symbol_t *new_symbol_type (const char *name, type_t *type __attribute__((const)) def_t *qfo_encode_type (type_t *type) {return 0;} __attribute__((const)) int obj_types_assignable (const type_t *dst, const type_t *src) {return 0;} void print_protocollist (struct dstring_s *dstr, protocollist_t *protocollist) {} -int obj_is_id (const type_t *type){return type->type;} +int is_id (const type_t *type){return type->type;} +int is_SEL (const type_t *type){return type->type;} +int is_Class (const type_t *type){return type->type;} int compare_protocols (protocollist_t *protos1, protocollist_t *protos2){return protos1->count - protos2->count;} diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 88ba6a60e..77e79f3a4 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -429,8 +429,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, for (l = labels; *l; l++) num_labels++; if (options.code.progsversion == PROG_ID_VERSION - || (type != &type_string - && type != &type_float && !is_integral (type)) + || (!is_string(type) && !is_float(type) && !is_integral (type)) || num_labels < 8) { for (l = labels; *l; l++) { expr_t *cmp = binary_expr (EQ, sw_val, (*l)->value); @@ -446,7 +445,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, int op; case_node_t *case_tree; - if (type == &type_string) + if (is_string(type)) temp = new_temp_def_expr (&type_integer); else temp = new_temp_def_expr (type); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index dc09104c3..0b54267b6 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -513,13 +513,13 @@ print_type_str (dstring_t *str, const type_t *type) } return; case ev_pointer: - if (obj_is_id (type)) { + if (is_id (type)) { dasprintf (str, "id"); if (type->t.fldptr.type->protos) print_protocollist (str, type->t.fldptr.type->protos); return; } - if (type == &type_SEL) { + if (is_SEL(type)) { dasprintf (str, "SEL"); return; } @@ -674,15 +674,15 @@ encode_type (dstring_t *encoding, const type_t *type) dasprintf (encoding, "%s)", encode_params (type)); return; case ev_pointer: - if (type == &type_id) { + if (is_id(type)) { dasprintf (encoding, "@"); return; } - if (type == &type_SEL) { + if (is_SEL(type)) { dasprintf (encoding, ":"); return; } - if (type == &type_Class) { + if (is_Class(type)) { dasprintf (encoding, "#"); return; } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 3233385bf..b2182497e 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -513,7 +513,7 @@ emit_value (ex_value_t *value, def_t *def) break; case ev_integer: case ev_uinteger: - if (!def || def->type != &type_float) { + if (!def || !is_float(def->type)) { tab = integer_imm_defs; type = &type_integer; break; From 498dfdbfef1677ce50fb2717394487d8b54f72ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 15:33:53 +0900 Subject: [PATCH 0916/3664] [qfcc] Clean up Obj-QC type struct names I decided that the obj_ tag was unnecessary. --- tools/qfcc/include/class.h | 16 +++--- tools/qfcc/source/class.c | 108 +++++++++++++++++------------------ tools/qfcc/source/expr_obj.c | 2 +- tools/qfcc/source/method.c | 5 +- tools/qfcc/source/qc-lex.l | 4 +- 5 files changed, 66 insertions(+), 69 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index e9bcb9c71..048ae8227 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -90,18 +90,18 @@ typedef struct static_instance_s { } static_instance_t; extern struct type_s type_id; -extern struct type_s type_obj_object; -extern struct type_s type_obj_class; +extern struct type_s type_object; +extern struct type_s type_class; extern struct type_s type_Class; -extern struct type_s type_obj_protocol; +extern struct type_s type_protocol; extern struct type_s type_SEL; extern struct type_s type_IMP; extern struct type_s type_supermsg; -extern struct type_s type_obj_exec_class; -extern struct type_s type_obj_method; -extern struct type_s type_obj_super; -extern struct type_s type_obj_method_description; -extern struct type_s type_obj_category; +extern struct type_s type_exec_class; +extern struct type_s type_method; +extern struct type_s type_super; +extern struct type_s type_method_description; +extern struct type_s type_category; extern struct type_s type_ivar; extern struct type_s type_module; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 9c962d50e..c9dceb358 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -70,33 +70,31 @@ static hashtab_t *static_instances; static hashtab_t *static_instance_classes; // these will be built up further -type_t type_obj_selector = { ev_invalid, 0, 0, ty_struct}; -type_t type_SEL = { ev_pointer, "SEL", 1, ty_basic, - {{&type_obj_selector}}}; +type_t type_selector = { ev_invalid, 0, 0, ty_struct}; +type_t type_SEL = { ev_pointer, "SEL", 1, ty_basic, {{&type_selector}}}; type_t *IMP_params[] = {&type_id, &type_SEL}; type_t type_IMP = { ev_func, "IMP", 1, ty_basic, {{&type_id, -3, IMP_params}}}; -type_t type_obj_super = { ev_invalid, 0, 0 }; -type_t type_SuperPtr = { ev_pointer, 0, 1, ty_basic, {{&type_obj_super}}}; +type_t type_super = { ev_invalid, 0, 0 }; +type_t type_SuperPtr = { ev_pointer, 0, 1, ty_basic, {{&type_super}}}; type_t *supermsg_params[] = {&type_SuperPtr, &type_SEL}; type_t type_supermsg = { ev_func, ".supermsg", 1, ty_basic, {{&type_id, -3, supermsg_params}}}; -type_t type_obj_method = { ev_invalid, 0, 0, ty_struct }; -type_t type_obj_method_description = { ev_invalid, 0, 0, ty_struct }; -type_t type_obj_category = { ev_invalid, 0, 0, ty_struct}; -type_t type_obj_ivar = { ev_invalid, 0, 0, ty_struct}; -type_t type_obj_module = { ev_invalid, 0, 0, ty_struct}; -type_t type_moduleptr = { ev_pointer, 0, 1, ty_basic, - {{&type_obj_module}}}; +type_t type_method = { ev_invalid, 0, 0, ty_struct }; +type_t type_method_description = { ev_invalid, 0, 0, ty_struct }; +type_t type_category = { ev_invalid, 0, 0, ty_struct}; +type_t type_ivar = { ev_invalid, 0, 0, ty_struct}; +type_t type_module = { ev_invalid, 0, 0, ty_struct}; +type_t type_moduleptr = { ev_pointer, 0, 1, ty_basic, {{&type_module}}}; type_t *obj_exec_class_params[] = { &type_moduleptr }; -type_t type_obj_exec_class = { ev_func, 0, 1, ty_basic, - {{&type_void, 1, obj_exec_class_params}}}; +type_t type_exec_class = { ev_func, 0, 1, ty_basic, + {{&type_void, 1, obj_exec_class_params}}}; -type_t type_obj_object = {ev_invalid, 0, 0, ty_struct}; -type_t type_id = { ev_pointer, "id", 1, ty_basic, {{&type_obj_object}}}; -type_t type_obj_class = { ev_invalid, 0, 0, ty_struct}; -type_t type_Class = { ev_pointer, 0, 1, ty_basic, {{&type_obj_class}}}; -type_t type_obj_protocol = { ev_invalid, 0, 0, ty_struct}; +type_t type_object = {ev_invalid, 0, 0, ty_struct}; +type_t type_id = { ev_pointer, "id", 1, ty_basic, {{&type_object}}}; +type_t type_class = { ev_invalid, 0, 0, ty_struct}; +type_t type_Class = { ev_pointer, 0, 1, ty_basic, {{&type_class}}}; +type_t type_protocol = { ev_invalid, 0, 0, ty_struct}; int obj_initialized = 0; @@ -328,7 +326,7 @@ is_id (const type_t *type) if (!is_struct (type->t.fldptr.type)) return 0; // if the the symtabs match, then type is id in disguise - if (type->t.fldptr.type->t.symtab == type_obj_object.t.symtab) + if (type->t.fldptr.type->t.symtab == type_object.t.symtab) return 1; return 0; } @@ -372,19 +370,19 @@ is_SEL (const type_t *type) int is_object (const type_t *type) { - return type == &type_obj_object; + return type == &type_object; } int is_method (const type_t *type) { - return type == &type_obj_method; + return type == &type_method; } int is_method_description (const type_t *type) { - return type == &type_obj_method_description; + return type == &type_method_description; } static protocollist_t * @@ -564,11 +562,11 @@ class_symbol (class_type_t *class_type, int external) name = va ("_OBJ_CATEGORY_%s_%s", class_type->c.category->class->name, class_type->c.category->name); - type = &type_obj_category; + type = &type_category; break; case ct_class: name = va ("_OBJ_CLASS_%s", class_type->c.class->name); - type = &type_obj_class; + type = &type_class; break; case ct_protocol: return 0; // probably in error recovery @@ -784,7 +782,7 @@ emit_ivars (symtab_t *ivars, const char *name) if (s->sy_type == sy_var) ivar_data.count++; } - ivar_list_struct[1].type = array_type (&type_obj_ivar, ivar_data.count); + ivar_list_struct[1].type = array_type (&type_ivar, ivar_data.count); def = emit_structure (va ("_OBJ_INSTANCE_VARIABLES_%s", name), 's', ivar_list_struct, 0, &ivar_data, sc_static); @@ -804,7 +802,7 @@ begin_class (class_t *class) defspace_t *space; sym = make_symbol (va ("_OBJ_METACLASS_%s", class->name), - &type_obj_class, pr.far_data, sc_static); + &type_class, pr.far_data, sc_static); meta_def = sym->s.def; meta_def->initialized = meta_def->constant = meta_def->nosave = 1; space = meta_def->space; @@ -814,13 +812,13 @@ begin_class (class_t *class) EMIT_STRING (space, meta->super_class, class->super_class->name); EMIT_STRING (space, meta->name, class->name); meta->info = _PR_CLS_META; - meta->instance_size = type_size (&type_obj_class); + meta->instance_size = type_size (&type_class); if (!class->super_class) { // The ivars list for the meta class struct get emitted only for the // root class of the hierachy. - // NOTE: type_obj_class is not actually a class + // NOTE: type_class is not actually a class EMIT_DEF (space, meta->ivars, - emit_ivars (type_obj_class.t.symtab, "Class")); + emit_ivars (type_class.t.symtab, "Class")); } else { meta->ivars = 0; } @@ -1532,11 +1530,11 @@ class_finish_module (void) free (data.classes); free (data.categories); - module_sym = make_symbol ("_OBJ_MODULE", &type_obj_module, pr.far_data, + module_sym = make_symbol ("_OBJ_MODULE", &type_module, pr.far_data, sc_static); symtab_addsymbol (current_symtab, module_sym); module = &D_STRUCT (pr_module_t, module_sym->s.def); - module->size = type_size (&type_obj_module); + module->size = type_size (&type_module); EMIT_STRING (module_sym->s.def->space, module->name, GETSTR (pr.source_file)); EMIT_DEF (module_sym->s.def->space, module->symtab, symtab_def); @@ -1544,7 +1542,7 @@ class_finish_module (void) exec_class_sym = symtab_lookup (pr.symtab, "__obj_exec_class"); if (!exec_class_sym) { exec_class_sym = new_symbol_type ("__obj_exec_class", - &type_obj_exec_class); + &type_exec_class); exec_class_sym = function_symbol (exec_class_sym, 0, 1); make_function (exec_class_sym, 0, exec_class_sym->table->space, sc_extern); @@ -1717,7 +1715,7 @@ emit_protocol (protocol_t *protocol) defspace_t *space; proto_def = make_symbol (va ("_OBJ_PROTOCOL_%s", protocol->name), - &type_obj_protocol, pr.far_data, sc_static)->s.def; + &type_protocol, pr.far_data, sc_static)->s.def; if (proto_def->initialized) return proto_def; proto_def->initialized = proto_def->constant = 1; @@ -1884,26 +1882,26 @@ class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope, static void init_objective_structs (void) { - make_structure ("obj_selector", 's', sel_struct, &type_obj_selector); - chain_type (&type_obj_selector); + make_structure ("obj_selector", 's', sel_struct, &type_selector); + chain_type (&type_selector); chain_type (&type_SEL); chain_type (&type_IMP); - make_structure ("obj_method", 's', method_struct, &type_obj_method); - chain_type (&type_obj_method); + make_structure ("obj_method", 's', method_struct, &type_method); + chain_type (&type_method); make_structure ("obj_method_description", 's', method_desc_struct, - &type_obj_method_description); - chain_type (&type_obj_method_description); + &type_method_description); + chain_type (&type_method_description); - make_structure ("obj_category", 's', category_struct, &type_obj_category); - chain_type (&type_obj_category); + make_structure ("obj_category", 's', category_struct, &type_category); + chain_type (&type_category); - make_structure ("obj_ivar", 's', ivar_struct, &type_obj_ivar); - chain_type (&type_obj_ivar); + make_structure ("obj_ivar", 's', ivar_struct, &type_ivar); + chain_type (&type_ivar); - make_structure ("obj_super", 's', super_struct, &type_obj_super); - chain_type (&type_obj_super); + make_structure ("obj_super", 's', super_struct, &type_super); + chain_type (&type_super); chain_type (&type_SuperPtr); chain_type (&type_supermsg); @@ -1913,24 +1911,24 @@ init_objective_structs (void) static void init_classes (void) { - make_structure ("obj_class", 's', class_struct, &type_obj_class); - chain_type (&type_obj_class); + make_structure ("obj_class", 's', class_struct, &type_class); + chain_type (&type_class); chain_type (&type_Class); - make_structure ("obj_object", 's', object_struct, &type_obj_object); - chain_type (&type_obj_object); + make_structure ("obj_object", 's', object_struct, &type_object); + chain_type (&type_object); chain_type (&type_id); - make_structure ("obj_protocol", 's', protocol_struct, &type_obj_protocol); - chain_type (&type_obj_protocol); + make_structure ("obj_protocol", 's', protocol_struct, &type_protocol); + chain_type (&type_protocol); } static void class_init_obj_module (void) { - make_structure ("obj_module", 's', module_struct, &type_obj_module); + make_structure ("obj_module", 's', module_struct, &type_module); - chain_type (&type_obj_module); + chain_type (&type_module); chain_type (&type_moduleptr); - chain_type (&type_obj_exec_class); + chain_type (&type_exec_class); } void diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index 6858adb54..db0b2fe4a 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -151,7 +151,7 @@ super_expr (class_type_t *class_type) sym = symtab_lookup (current_symtab, ".super"); if (!sym || sym->table != current_symtab) { - sym = new_symbol_type (".super", &type_obj_super); + sym = new_symbol_type (".super", &type_super); initialize_def (sym, 0, current_symtab->space, sc_local); } super = new_symbol_expr (sym); diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 74971ef1c..833a03f1f 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -604,7 +604,7 @@ emit_methods (methodlist_t *methods, const char *name, int instance) methods->count = count; methods->instance = instance; - methods_struct[2].type = array_type (&type_obj_method, count); + methods_struct[2].type = array_type (&type_method, count); return emit_structure (va ("_OBJ_%s_METHODS_%s", type, name), 's', methods_struct, 0, methods, sc_static); } @@ -672,8 +672,7 @@ emit_method_descriptions (methodlist_t *methods, const char *name, methods->count = count; methods->instance = instance; - method_list_struct[1].type = array_type (&type_obj_method_description, - count); + method_list_struct[1].type = array_type (&type_method_description, count); return emit_structure (va ("_OBJ_%s_METHODS_%s", type, name), 's', method_list_struct, 0, methods, sc_static); } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index cccc43afd..a2a8295bd 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -319,8 +319,8 @@ typedef struct { static keyword_t obj_keywords[] = { {"id", OBJECT, &type_id }, {"Class", TYPE, &type_Class }, - {"Method", TYPE, &type_obj_method}, - {"Super", TYPE, &type_obj_super }, + {"Method", TYPE, &type_method }, + {"Super", TYPE, &type_super }, {"SEL", TYPE, &type_SEL }, {"IMP", TYPE, &type_IMP }, From 643711ef4020291c1436d6487971b312988a49e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 17:29:42 +0900 Subject: [PATCH 0917/3664] [qfcc] Pre-initialize type_object's strct pointer This ensures that pointers to incomplete struct types are not misidentified as id before the class system has been initialized. --- tools/qfcc/source/class.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index c9dceb358..f7d52e29c 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -89,8 +89,10 @@ type_t type_moduleptr = { ev_pointer, 0, 1, ty_basic, {{&type_module}}}; type_t *obj_exec_class_params[] = { &type_moduleptr }; type_t type_exec_class = { ev_func, 0, 1, ty_basic, {{&type_void, 1, obj_exec_class_params}}}; - -type_t type_object = {ev_invalid, 0, 0, ty_struct}; +// the cast of 1 in the init is to ensure pointers to incomplete types +// are never misidentified as id. It will be set to the correct value +// when the obj system is initialized. +type_t type_object = {ev_invalid, 0, 0, ty_struct, {{(type_t *)1}}}; type_t type_id = { ev_pointer, "id", 1, ty_basic, {{&type_object}}}; type_t type_class = { ev_invalid, 0, 0, ty_struct}; type_t type_Class = { ev_pointer, 0, 1, ty_basic, {{&type_class}}}; From 01cf28e436ea22256280f1681af53ea957bf4e3b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 18:08:26 +0900 Subject: [PATCH 0918/3664] [qfcc] Treat C-style function decls as prototypes This removes the need for extern from the declaration. --- tools/qfcc/source/qc-parse.y | 3 --- tools/qfcc/source/statements.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 70ca90fc3..516c0b491 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -487,9 +487,6 @@ external_decl symtab_addsymbol (current_symtab, $1); } else { $1 = function_symbol ($1, spec.is_overload, 1); - // things might be a confused mess from earlier errors - if ($1->sy_type == sy_func) - make_function ($1, 0, $1->table->space, spec.storage); } } ; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index bd2508e54..6dbbbd99c 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1314,6 +1314,9 @@ expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op) } else if (sym->sy_type == sy_const) { *op = value_operand (sym->s.value, e); } else if (sym->sy_type == sy_func) { + if (!sym->s.func) { + make_function (sym, 0, pr.symtab->space, sc_extern); + } *op = def_operand (sym->s.func->def, 0, e); } else { internal_error (e, "unexpected symbol type: %s for %s", From 09d3e1b59fc57c0ca47eff5f5add8c28bd2cb3ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 18:17:24 +0900 Subject: [PATCH 0919/3664] [qwaq] Remove extern from function prototypes Yay. --- ruamoko/qwaq/qwaq-curses.h | 80 +++++++++++++++++++------------------- ruamoko/qwaq/qwaq-debug.h | 39 +++++++++---------- ruamoko/qwaq/qwaq-rect.h | 12 +++--- 3 files changed, 63 insertions(+), 68 deletions(-) diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index c43f08d13..5a6546955 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -86,53 +86,51 @@ typedef struct panel_s *panel_t; extern window_t stdscr; -extern void initialize (void); -extern window_t create_window (int xpos, int ypos, int xlen, int ylen); -extern void destroy_window (window_t win); -extern void mvwprintf (window_t win, int x, int y, string fmt, ...); -extern void wprintf (window_t win, string fmt, ...); -extern void wvprintf (window_t win, string fmt, @va_list args); -extern void mvwvprintf (window_t win, int x, int y, - string fmt, @va_list args); -extern void wrefresh (window_t win); -extern void mvwaddch (window_t win, int x, int y, int ch); -extern void waddch (window_t win, int ch); -extern void mvwaddstr (window_t win, int x, int y, string str); -extern void waddstr (window_t win, string str); +void initialize (void); +window_t create_window (int xpos, int ypos, int xlen, int ylen); +void destroy_window (window_t win); +void mvwprintf (window_t win, int x, int y, string fmt, ...); +void wprintf (window_t win, string fmt, ...); +void wvprintf (window_t win, string fmt, @va_list args); +void mvwvprintf (window_t win, int x, int y, string fmt, @va_list args); +void wrefresh (window_t win); +void mvwaddch (window_t win, int x, int y, int ch); +void waddch (window_t win, int ch); +void mvwaddstr (window_t win, int x, int y, string str); +void waddstr (window_t win, string str); -extern panel_t create_panel (window_t window); -extern void destroy_panel (panel_t panel); -extern void hide_panel (panel_t panel); -extern void show_panel (panel_t panel); -extern void top_panel (panel_t panel); -extern void bottom_panel (panel_t panel); -extern void move_panel (panel_t panel, int x, int y); -extern window_t panel_window (panel_t panel); -extern void update_panels (void); -extern void replace_panel (panel_t panel, window_t window); -extern void doupdate (void); +panel_t create_panel (window_t window); +void destroy_panel (panel_t panel); +void hide_panel (panel_t panel); +void show_panel (panel_t panel); +void top_panel (panel_t panel); +void bottom_panel (panel_t panel); +void move_panel (panel_t panel, int x, int y); +window_t panel_window (panel_t panel); +void update_panels (void); +void replace_panel (panel_t panel, window_t window); +void doupdate (void); -extern int get_event (qwaq_event_t *event); -extern int max_colors (void); -extern int max_color_pairs (void); -extern int init_pair (int pair, int f, int b); -extern void wbkgd (window_t win, int ch); -extern void werase (window_t win); -extern void scrollok (window_t win, int flag); +int get_event (qwaq_event_t *event); +int max_colors (void); +int max_color_pairs (void); +int init_pair (int pair, int f, int b); +void wbkgd (window_t win, int ch); +void werase (window_t win); +void scrollok (window_t win, int flag); -extern int acs_char (int acs); -extern int curs_set (int visibility); -extern int move (int x, int y); +int acs_char (int acs); +int curs_set (int visibility); +int move (int x, int y); -extern void wborder (window_t window, - box_sides_t sides, box_corners_t corners); -extern void mvwblit_line (window_t window, int x, int y, int *wch, int len); -extern void wresize (window_t window, int width, int height); -extern void resizeterm (int width, int height); +void wborder (window_t window, box_sides_t sides, box_corners_t corners); +void mvwblit_line (window_t window, int x, int y, int *wch, int len); +void wresize (window_t window, int width, int height); +void resizeterm (int width, int height); -extern Rect getwrect (struct window_s *window); +Rect getwrect (struct window_s *window); -extern void printf(string fmt, ...); +void printf(string fmt, ...); // qfcc stuff #else // gcc stuff diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/qwaq-debug.h index 287e1282c..b233f2b07 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/qwaq-debug.h @@ -55,28 +55,25 @@ typedef struct qdb_auxfunction_s { typedef struct qdb_target_s { int handle; } qdb_target_t; -extern void qdb_set_trace (qdb_target_t target, int state); -extern int qdb_set_breakpoint (qdb_target_t target, unsigned staddr); -extern int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr); -extern int qdb_set_watchpoint (qdb_target_t target, unsigned offset); -extern int qdb_clear_watchpoint (qdb_target_t target); -extern int qdb_continue (qdb_target_t target); -extern qdb_state_t qdb_get_state (qdb_target_t target); -extern int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, - void *dst); -extern string qdb_get_string (qdb_target_t target, unsigned str); -extern qdb_def_t qdb_find_global (qdb_target_t target, string name); -extern qdb_def_t qdb_find_field (qdb_target_t target, string name); -extern qdb_function_t *qdb_find_function (qdb_target_t target, string name); -extern qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum); -extern qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, - string name); -extern qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, - unsigned fnum); -extern qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum); +void qdb_set_trace (qdb_target_t target, int state); +int qdb_set_breakpoint (qdb_target_t target, unsigned staddr); +int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr); +int qdb_set_watchpoint (qdb_target_t target, unsigned offset); +int qdb_clear_watchpoint (qdb_target_t target); +int qdb_continue (qdb_target_t target); +qdb_state_t qdb_get_state (qdb_target_t target); +int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst); +string qdb_get_string (qdb_target_t target, unsigned str); +qdb_def_t qdb_find_global (qdb_target_t target, string name); +qdb_def_t qdb_find_field (qdb_target_t target, string name); +qdb_function_t *qdb_find_function (qdb_target_t target, string name); +qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum); +qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, string name); +qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, unsigned fnum); +qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum); -extern void traceon(); -extern void traceoff(); +void traceon(); +void traceoff(); #else//GCC diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/qwaq-rect.h index 2f7915ff1..a26f74565 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/qwaq-rect.h @@ -17,12 +17,12 @@ typedef struct Rect_s { } Rect; #ifdef __QFCC__ -extern Rect makeRect (int xpos, int ypos, int xlen, int ylen); -extern Point makePoint (int x, int y); -extern Extent makeExtent (int width, int height); -extern Extent mergeExtents (Extent a, Extent b); -extern int rectContainsPoint (Rect rect, Point point); -extern Rect clipRect (Rect clipRect, Rect rect); +Rect makeRect (int xpos, int ypos, int xlen, int ylen); +Point makePoint (int x, int y); +Extent makeExtent (int width, int height); +Extent mergeExtents (Extent a, Extent b); +int rectContainsPoint (Rect rect, Point point); +Rect clipRect (Rect clipRect, Rect rect); #endif #endif//__qwaq_rect_h From 9e529d1508ec2c681208a59bce23945dccb5097a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 19:00:14 +0900 Subject: [PATCH 0920/3664] [qfcc] Fix some incorrect test runs Checking for float return when should be checking for int return. Fortunately, the tests still passed. --- tools/qfcc/test/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 8560e693f..dae61f2ab 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -309,7 +309,7 @@ methodparams_obj=$(methodparams_dat_SOURCES:.r=.qfo) methodparams.dat$(EXEEXT): $(methodparams_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(methodparams_obj) methodparams.run: Makefile build-run - @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/methodparams.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/methodparams.Qo @@ -327,7 +327,7 @@ paramret_obj=$(paramret_dat_SOURCES:.r=.qfo) paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) paramret.run: Makefile build-run - @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ + @$(srcdir)/build-run $@ include ./$(DEPDIR)/paramret.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/paramret.Qo From 9c556c07bb0b4365776b7f27e0e7838104a2acf3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 19:01:26 +0900 Subject: [PATCH 0921/3664] [qfcc] Add failing nil return through @param bug I suspect it's general for struts, but nil really is a troubling character sometimes. --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/nilparamret.r | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tools/qfcc/test/nilparamret.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index dae61f2ab..4e213e66e 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -53,6 +53,7 @@ test_progs_dat=\ ivar-struct-return.dat \ methodparams.dat \ modulo.dat \ + nilparamret.dat \ paramret.dat \ quaternion.dat \ return-ivar.dat \ @@ -322,6 +323,15 @@ modulo.run: Makefile build-run include ./$(DEPDIR)/modulo.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/modulo.Qo +nilparamret_dat_SOURCES=nilparamret.r +nilparamret_obj=$(nilparamret_dat_SOURCES:.r=.qfo) +nilparamret.dat$(EXEEXT): $(nilparamret_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(nilparamret_obj) +nilparamret.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/nilparamret.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/nilparamret.Qo + paramret_dat_SOURCES=paramret.r paramret_obj=$(paramret_dat_SOURCES:.r=.qfo) paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/nilparamret.r b/tools/qfcc/test/nilparamret.r new file mode 100644 index 000000000..fbe0b7dc5 --- /dev/null +++ b/tools/qfcc/test/nilparamret.r @@ -0,0 +1,26 @@ +typedef struct bar { + float x, y, z, w; +} bar; + +bar set_return(); + +@param foo() +{ + set_return(); + return nil; +} + +bar set_return() +{ + return {1, 2, 3, 4}; +} +void printf (string fmt, ...) = #0; +int main() +{ + @param r = foo(); + printf("%q\n", r); + return !(r.quaternion_val.x == 0 + && r.quaternion_val.y == 0 + && r.quaternion_val.z == 0 + && r.quaternion_val.w == 0); +} From fdf6fac0770dec9c108a581d6326c770272e9447 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 20:31:11 +0900 Subject: [PATCH 0922/3664] [qfcc] Rewrite expr_nil to use memset if necessary This fixes the problem with returning nil through @param (and probably structs in general). --- tools/qfcc/source/statements.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 6dbbbd99c..bda98b287 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1406,16 +1406,34 @@ static sblock_t * expr_nil (sblock_t *sblock, expr_t *e, operand_t **op) { type_t *nil = e->e.nil; - expr_t *ptr; + expr_t *size_expr; + size_t nil_size; + operand_t *zero; + operand_t *size; + statement_t *s; + if (!is_struct (nil) && !is_array (nil)) { *op = value_operand (new_nil_val (nil), e); return sblock; } - ptr = expr_file_line (address_expr (new_temp_def_expr (nil), 0, 0), e); - expr_file_line (ptr, e); - sblock = statement_subexpr (sblock, ptr, op); - e = expr_file_line (new_memset_expr (ptr, new_integer_expr (0), nil), e); - sblock = statement_slist (sblock, e); + if (!*op) { + *op = temp_operand (nil, e); + } + nil_size = type_size (nil); + if (nil_size < 0x10000) { + size_expr = new_short_expr (nil_size); + } else { + size_expr = new_integer_expr (nil_size); + } + sblock = statement_subexpr (sblock, new_integer_expr(0), &zero); + sblock = statement_subexpr (sblock, size_expr, &size); + + s = new_statement (st_move, "", e); + s->opa = zero; + s->opb = size; + s->opc = *op; + sblock_add_statement (sblock, s); + return sblock; } From 4d616fab4a5456b3873fa6006e78cf49ce04227d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 20:47:42 +0900 Subject: [PATCH 0923/3664] [qfcc] Use the correct statement type for memset --- tools/qfcc/source/statements.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index bda98b287..ba0e07331 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1428,7 +1428,7 @@ expr_nil (sblock_t *sblock, expr_t *e, operand_t **op) sblock = statement_subexpr (sblock, new_integer_expr(0), &zero); sblock = statement_subexpr (sblock, size_expr, &size); - s = new_statement (st_move, "", e); + s = new_statement (st_memset, "", e); s->opa = zero; s->opb = size; s->opc = *op; From c6483b617c772a4ea281c64229479e3084a05fe3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 20:52:37 +0900 Subject: [PATCH 0924/3664] [qfcc] Remove obsolete notes nil seems to have sorted himself out with the recent reworking of how qfcc handles nil. --- tools/qfcc/source/problem_with_nil.txt | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 tools/qfcc/source/problem_with_nil.txt diff --git a/tools/qfcc/source/problem_with_nil.txt b/tools/qfcc/source/problem_with_nil.txt deleted file mode 100644 index 4172aea0e..000000000 --- a/tools/qfcc/source/problem_with_nil.txt +++ /dev/null @@ -1,12 +0,0 @@ -The problem with nil is more a problem with @param and values. - -@param values used type_nil's low-level type, which is either quaternion -or vector (v6 progs). Thus returning (or passing?) nil through @param -creates a value that has type_param built low-level type quaternion. -Then assigning nil to a quaternion finds the param nil (because the -value and low-level type is checked) which has the wrong type for type -checks. - -one solution is to create an ev_param type (convert to quaternion or -vector for v6 progs) that the VM either ignores or can copy around -ev_param data. From 653eabfdbfb745464d21f0df67a7b5a6cbec867d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 22:11:18 +0900 Subject: [PATCH 0925/3664] [qfcc] Clean up inconsistent type building idioms --- tools/qfcc/source/qc-parse.y | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 516c0b491..bdac72d30 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -762,8 +762,7 @@ struct_decl { if (!$0.type) $0.type = type_default; - $1->type = append_type ($1->type, $0.type); - $1->type = find_type ($1->type); + $1->type = find_type (append_type ($1->type, $0.type)); $1->sy_type = sy_var; $1->visibility = current_visibility; symtab_addsymbol (current_symtab, $1); @@ -775,8 +774,7 @@ struct_decl { if (!$0.type) $0.type = type_default; - $1->type = append_type ($1->type, $0.type); - $1->type = find_type ($1->type); + $1->type = find_type (append_type ($1->type, $0.type)); $1->sy_type = sy_var; $1->visibility = current_visibility; symtab_addsymbol (current_symtab, $1); @@ -1419,8 +1417,7 @@ init_var_decl : var_decl opt_initializer { specifier_t spec = $0; - $1->type = append_type ($1->type, spec.type); - $1->type = find_type ($1->type); + $1->type = find_type (append_type ($1->type, spec.type)); $1->sy_type = sy_var; initialize_def ($1, 0, current_symtab->space, spec.storage); $$ = assign_expr (new_symbol_expr ($1), $2); From 1efbb2ab496a689a40b15aea5e60a37682890fff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 22:12:45 +0900 Subject: [PATCH 0926/3664] [cl_menu] Remove a stale FIXME --- ruamoko/cl_menu/plistmenu.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/cl_menu/plistmenu.r b/ruamoko/cl_menu/plistmenu.r index a4daadbbf..351e974e1 100644 --- a/ruamoko/cl_menu/plistmenu.r +++ b/ruamoko/cl_menu/plistmenu.r @@ -145,7 +145,7 @@ string_from_plist (PLString *plstring) local @param ret; local string str = [plstring string]; - ret = nil; //FIXME should be ret = nil; + ret = nil; if (str_mid (str, 0, 1) == "[") return rect_from_plist (plstring); From 1da6eb5f512703668f7cd75a8b3bdea3679075c2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 22:17:36 +0900 Subject: [PATCH 0927/3664] [qfcc] Fix a typo in a comment --- tools/qfcc/include/def.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index df0104178..691c5d602 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -110,7 +110,7 @@ typedef struct def_s { /** Specify the storage class of a def. */ typedef enum storage_class_e { - sc_global, ///< def is globally visibil across units + sc_global, ///< def is globally visible across units sc_system, ///< def may be redefined once sc_extern, ///< def is externally allocated sc_static, ///< def is private to the current unit From c6746fa3917b561f924ae34fa51945de51867aa2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Mar 2020 22:48:38 +0900 Subject: [PATCH 0928/3664] [qfcc] Fix out-by-one in type meta check --- tools/qfcc/source/obj_type.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 38a28a9e8..d56cd98b9 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -275,7 +275,7 @@ qfo_encode_type (type_t *type) } if (type->type_def) return type->type_def; - if (type->meta > sizeof (funcs) / (sizeof (funcs[0]))) + if (type->meta >= sizeof (funcs) / (sizeof (funcs[0]))) internal_error (0, "bad type meta type"); if (!type->encoding) type->encoding = type_get_encoding (type); From 8997c81bd1f721f2bc62bea4bbfd4fb74fee1afa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 09:41:54 +0900 Subject: [PATCH 0929/3664] [qwaq] Implement rectangular region clearing You'd think ncurses would have this, but I guess it's too window-oriented. --- ruamoko/qwaq/qwaq-curses.c | 61 ++++++++++++++++++++++++++++++++- ruamoko/qwaq/qwaq-curses.h | 1 + ruamoko/qwaq/qwaq-debugger.r | 1 + ruamoko/qwaq/qwaq-draw.h | 1 + ruamoko/qwaq/qwaq-draw.r | 41 ++++++++++++++++++++++ ruamoko/qwaq/qwaq-textcontext.h | 3 ++ ruamoko/qwaq/qwaq-textcontext.r | 39 +++++++++++++++++++++ ruamoko/qwaq/qwaq-view.h | 1 + ruamoko/qwaq/qwaq-view.r | 6 ++++ 9 files changed, 153 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/qwaq-curses.c index d25604135..26a17b37b 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/qwaq-curses.c @@ -84,6 +84,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_mvwblit_line, qwaq_cmd_wresize, qwaq_cmd_resizeterm, + qwaq_cmd_mvwhline, } qwaq_commands; static const char *qwaq_command_names[]= { @@ -116,6 +117,7 @@ static const char *qwaq_command_names[]= { "mvwblit_line", "wresize", "resizeterm", + "mvwhline" }; static window_t * @@ -600,10 +602,23 @@ cmd_resizeterm (qwaq_resources_t *res) resizeterm (height, width); } +static void +cmd_mvwhline (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int x = RB_PEEK_DATA (res->command_queue, 3); + int y = RB_PEEK_DATA (res->command_queue, 4); + int ch = RB_PEEK_DATA (res->command_queue, 5); + int n = RB_PEEK_DATA (res->command_queue, 6); + + window_t *window = get_window (res, __FUNCTION__, window_id); + mvwhline (window->win, y, x, ch, n); +} + static void dump_command (qwaq_resources_t *res, int len) { - if (0) { + if (1) { qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); for (int i = 2; i < len; i++) { @@ -739,6 +754,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_resizeterm: cmd_resizeterm (res); break; + case qwaq_cmd_mvwhline: + cmd_mvwhline (res); + break; } pthread_mutex_lock (&res->command_cond.mut); RB_DROP_DATA (res->command_queue, len); @@ -1064,6 +1082,33 @@ bi_resizeterm (progs_t *pr) qwaq_resizeterm (pr, width, height); } +static void +qwaq_mvwhline (progs_t *pr, int window_id, int x, int y, int ch, int n) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { + qwaq_cmd_mvwhline, 0, + window_id, x, y, ch, n + }; + + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} +static void +bi_mvwhline (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + int ch = P_INT (pr, 3); + int n = P_INT (pr, 4); + + qwaq_mvwhline (pr, window_id, x, y, ch, n); +} + static void qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str) { @@ -1764,6 +1809,18 @@ bi_i_TextContext__border_ (progs_t *pr) qwaq_wborder (pr, window_id, sides, corns); } +static void +bi_i_TextContext__mvhline_ (progs_t *pr) +{ + __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); + int window_id = self->window; + __auto_type pos = &P_PACKED (pr, Point, 2); + int ch = P_INT (pr, 3); + int n = P_INT (pr, 4); + + qwaq_mvwhline (pr, window_id, pos->x, pos->y, ch, n); +} + static void bi_qwaq_clear (progs_t *pr, void *data) { @@ -1817,6 +1874,7 @@ static builtin_t builtins[] = { {"mvwblit_line", bi_mvwblit_line, -1}, {"wresize", bi_wresize, -1}, {"resizeterm", bi_resizeterm, -1}, + {"mvwhline", bi_mvwhline, -1}, {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, @@ -1841,6 +1899,7 @@ static builtin_t builtins[] = { {"_i_TextContext__clear", bi_i_TextContext__clear, -1}, {"_i_TextContext__scrollok_", bi_i_TextContext__scrollok_, -1}, {"_i_TextContext__border_", bi_i_TextContext__border_, -1}, + {"_i_TextContext__mvhline_", bi_i_TextContext__mvhline_, -1}, {0} }; diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/qwaq-curses.h index 5a6546955..37c9c0712 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/qwaq-curses.h @@ -98,6 +98,7 @@ void mvwaddch (window_t win, int x, int y, int ch); void waddch (window_t win, int ch); void mvwaddstr (window_t win, int x, int y, string str); void waddstr (window_t win, string str); +void mvwhline (window_t win, int x, int y, int ch, int n); panel_t create_panel (window_t window); void destroy_panel (panel_t panel); diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/qwaq-debugger.r index a33ec59b1..a15b6c7de 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/qwaq-debugger.r @@ -123,6 +123,7 @@ update_current_func (Debugger *self, unsigned fnum) return; } qdb_get_data (debug_target, func.local_data, func.local_size, local_data); + [locals_view clear]; if (!local_defs) { [locals_view mvprintf:{0,0}, "%d", func.local_size]; for (int y = 1; y < [locals_view size].height; y++) { diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/qwaq-draw.h index 3092cc77f..e7eff51ab 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/qwaq-draw.h @@ -16,6 +16,7 @@ @protocol TextContext - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; +- clearReact: (Rect) rect; - (Extent) size; - (void) resizeTo: (Extent) newSize; // absolute size diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/qwaq-draw.r index ed1f8837a..7d1fbcd58 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/qwaq-draw.r @@ -86,6 +86,47 @@ return self; } +- clearReact: (Rect) rect +{ + Point pos = rect.offset; + int len = rect.extent.width; + int count = rect.extent.height; + + if (pos.x + len > size.width) { + len = size.width - pos.x; + } + if (pos.x < 0) { + len += pos.x; + pos.x = 0; + } + if (len < 1) { + return self; + } + if (pos.y + count > size.height) { + count = size.height - pos.y; + } + if (pos.y < 0) { + count += pos.y; + pos.y = 0; + } + if (count < 1) { + return self; + } + int width = size.width; + int ch = background; + if (!(ch & 0xff)) { + ch |= ' '; + } + while (count-- > 0) { + int *p = buffer + pos.y * width + pos.x; + for (int i = 0; i < len; i++) { + *p++ = ch; + } + pos.y++; + } + return self; +} + - (void) bkgd: (int) ch { background = ch; diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/qwaq-textcontext.h index e2db46da4..2b979c415 100644 --- a/ruamoko/qwaq/qwaq-textcontext.h +++ b/ruamoko/qwaq/qwaq-textcontext.h @@ -25,6 +25,7 @@ int ylen; }; }; + int background; } + (int) max_colors; + (int) max_color_pairs; @@ -49,6 +50,8 @@ - (void) bkgd: (int) ch; - (void) scrollok: (int) flag; - (void) border: (box_sides_t) sides, box_corners_t corners; +- (void) mvhline: (Point) pos, int ch, int n; +-clearReact: (Rect) rect; @end #else diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/qwaq-textcontext.r index 972bd8a99..421cdf8eb 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/qwaq-textcontext.r @@ -101,6 +101,43 @@ static TextContext *screen; return self; } +-clearReact: (Rect) rect +{ + Point pos = rect.offset; + int len = rect.extent.width; + int count = rect.extent.height; + + if (pos.x + len > xlen) { + len = xlen - pos.x; + } + if (pos.x < 0) { + len += pos.x; + pos.x = 0; + } + if (len < 1) { + return self; + } + if (pos.y + count > ylen) { + count = ylen - pos.y; + } + if (pos.y < 0) { + count += pos.y; + pos.y = 0; + } + if (count < 1) { + return self; + } + int ch = background; + if (!(ch & 0xff)) { + ch |= ' '; + } + while (count-- > 0) { + [self mvhline:pos, ch, len]; + pos.y++; + } + return self; +} + - (void) printf: (string) fmt, ... = #0; - (void) vprintf: (string) mft, @va_list args = #0; - (void) addch: (int) ch = #0; @@ -110,6 +147,7 @@ static TextContext *screen; - (void) mvvprintf: (Point) pos, string mft, @va_list args = #0; - (void) mvaddch: (Point) pos, int ch = #0; - (void) mvaddstr: (Point) pos, string str = #0; +- (void) mvhline: (Point) pos, int ch, int n = #0; - (void) resizeTo: (Extent) newSize = #0; // absolute size - (void) refresh = #0; @@ -164,5 +202,6 @@ void mvwblit_line (window_t window, int x, int y, int *wch, int len) = #0; void wresize (window_t window, int width, int height) = #0; void resizeterm (int width, int height) = #0; Rect getwrect (window_t window) = #0; +void mvwhline (window_t win, int x, int y, int ch, int n) = #0; void printf(string fmt, ...) = #0; diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/qwaq-view.h index 27b0ddd43..052bb2ada 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/qwaq-view.h @@ -83,6 +83,7 @@ enum { - (void) mvprintf: (Point) pos, string fmt, ...; - (void) mvvprintf: (Point) pos, string fmt, @va_list args; - (void) mvaddch: (Point) pos, int ch; +-clear; @end @interface View: Object diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/qwaq-view.r index 9e28c7a68..8b4077938 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/qwaq-view.r @@ -213,6 +213,12 @@ updateScreenCursor (View *view) [textContext mvaddstr: pos, str]; } +-clear +{ + [textContext clearReact:rect]; + return self; +} + -move: (Point) delta { xpos += delta.x; From e31f03fd36045a54098570bdd1f524177092fdac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 09:59:01 +0900 Subject: [PATCH 0930/3664] [qfcc] Add type aliasing test again --- tools/qfcc/test/Makefile.am | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 4e213e66e..fe78065d7 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -67,6 +67,7 @@ test_progs_dat=\ structstruct.dat \ swap.dat \ triangle.dat \ + typedef.dat \ vecaddr.dat \ vecexpr.dat \ vecinit.dat \ @@ -449,14 +450,14 @@ triangle.run: Makefile build-run include ./$(DEPDIR)/triangle.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/triangle.Qo -#typedef_dat_SOURCES=typedef.r -#typedef_obj=$(typedef_dat_SOURCES:.r=.qfo) -#typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) -# $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) -#typedef.run: Makefile build-run -# @$(srcdir)/build-run $@ -#include ./$(DEPDIR)/typedef.Qo # am--include-marker -#r_depfiles_remade += ./$(DEPDIR)/typedef.Qo +typedef_dat_SOURCES=typedef.r +typedef_obj=$(typedef_dat_SOURCES:.r=.qfo) +typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) +typedef.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/typedef.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/typedef.Qo vecaddr_dat_SOURCES=vecaddr.r vecaddr_obj=$(vecaddr_dat_SOURCES:.r=.qfo) From 734f10d43e49849ef0ac4364a03732b9baa6f94f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 12:06:34 +0900 Subject: [PATCH 0931/3664] [qfcc] Dump local defs for qfo functions --- tools/qfcc/source/dump_globals.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 198a952cb..e02d35753 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -446,8 +446,9 @@ qfo_functions (qfo_t *qfo) { qfo_def_t *def; qfo_func_t *func; - unsigned i, d; + unsigned i, j, d; unsigned space; + qfo_mspace_t *locals; for (i = 0; i < qfo->num_funcs; i++) { func = &qfo->funcs[i]; @@ -471,7 +472,29 @@ qfo_functions (qfo_t *qfo) printf (" @ %x", func->code); else printf (" = #%d", -func->code); - puts (""); + printf (" loc: %d\n", func->locals_space); + if (func->locals_space) { + locals = &qfo->spaces[func->locals_space]; + printf ("%*s%d %p %d %p %d %d\n", 16, "", locals->type, + locals->defs, locals->num_defs, + locals->d.data, locals->data_size, locals->id); + for (j = 0; j < locals->num_defs; j++) { + qfo_def_t *def = locals->defs + j; + int offset; + const char *typestr; + const char *name; + qfot_type_t *type; + + name = QFO_GETSTR (qfo, def->name); + //FIXME check type + type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, + def->type); + typestr = QFO_GETSTR (qfo, type->encoding); + offset = def->offset; + + printf ("%*s%d %s %s\n", 20, "", offset, name, typestr); + } + } } } From 1eef2a8b5e97e16166c0e51b4d345378ab2a725e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 12:10:23 +0900 Subject: [PATCH 0932/3664] [qfcc] Implement type aliasing again When a type is aliased, the alias has two type chains: the simple type chain with all other aliases stripped, and the full type chain. There are still plenty of bugs in it, but having the clean type chain takes care of the major issue that was in the previous attempt as only the head of the type-chain needs to be skipped for type comparison. Most of the bugs are in finding the locations where the head needs to be skipped. --- include/QF/pr_type.h | 7 +- ruamoko/include/types.h | 1 + tools/qfcc/include/expr.h | 7 +- tools/qfcc/include/type.h | 5 +- tools/qfcc/source/dump_globals.c | 6 +- tools/qfcc/source/expr.c | 31 ++++--- tools/qfcc/source/expr_compound.c | 7 +- tools/qfcc/source/function.c | 11 +-- tools/qfcc/source/obj_file.c | 10 ++- tools/qfcc/source/obj_type.c | 23 ++++++ tools/qfcc/source/qc-parse.y | 3 + tools/qfcc/source/type.c | 133 ++++++++++++++++++++++-------- 12 files changed, 180 insertions(+), 64 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index db3376684..c74ad3c26 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -52,8 +52,9 @@ typedef enum { typedef struct qfot_alias_s { pr_int_t type; ///< type at end of alias chain - pointer_t aux_type; ///< referenced type - string_t name; ///< alias name + pointer_t aux_type; ///< referenced type: stripped of aliases + pointer_t full_type; ///< includes full alias info + string_t name; ///< alias name, may be null } qfot_alias_t; typedef struct qfot_fldptr_s { @@ -101,7 +102,7 @@ typedef struct qfot_array_s { */ typedef struct qfot_type_s { ty_meta_e meta:32; ///< meta type - pr_int_t size; ///< total word size of this encoding + pr_uint_t size; ///< total word size of this encoding string_t encoding; ///< Objective-QC encoding union { etype_t type:32; ///< ty_basic: etype_t diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index b435a6bab..c57603ada 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -33,6 +33,7 @@ typedef enum { typedef struct qfot_alias_s { etype_t type; struct qfot_type_s *aux_type; + struct qfot_type_s *full_type; string name; } qfot_alias_t; diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index be1640ffc..79fd77f99 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -380,10 +380,11 @@ expr_t *build_block_expr (expr_t *expr_list); element_t *new_element (expr_t *expr, struct symbol_s *symbol); expr_t *new_compound_init (void); expr_t *append_element (expr_t *compound, element_t *element); -expr_t *initialized_temp_expr (struct type_s *type, expr_t *compound); +expr_t *initialized_temp_expr (const struct type_s *type, expr_t *compound); void assign_elements (expr_t *local_expr, expr_t *ptr, element_chain_t *element_chain); -void build_element_chain (element_chain_t *element_chain, struct type_s *type, +void build_element_chain (element_chain_t *element_chain, + const struct type_s *type, expr_t *eles, int base_offset); void free_element_chain (element_chain_t *element_chain); @@ -433,7 +434,7 @@ expr_t *new_symbol_expr (struct symbol_s *symbol); \param type The type of the temporary variable. \return The new temporary variable expression node (ex_temp_t). */ -expr_t *new_temp_def_expr (struct type_s *type); +expr_t *new_temp_def_expr (const struct type_s *type); /** Create a new nil expression node. diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index bb6133bb1..70c650c52 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -52,7 +52,8 @@ typedef struct ty_array_s { } ty_array_t; typedef struct ty_alias_s { - struct type_s *type; + struct type_s *aux_type; ///< other aliases stripped + struct type_s *full_type; ///< full alias chain } ty_alias_t; typedef struct type_s { @@ -148,6 +149,8 @@ type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); type_t *array_type (type_t *aux, int size); type_t *based_array_type (type_t *aux, int base, int top); +type_t *alias_type (type_t *type, type_t *alias_chain, const char *name); +const type_t *unalias_type (const type_t *type) __attribute__((pure)); void print_type_str (struct dstring_s *str, const type_t *type); void print_type (const type_t *type); const char *encode_params (const type_t *type); diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index e02d35753..1695769e0 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -580,8 +580,10 @@ dump_qfo_types (qfo_t *qfo, int base_address) printf (" %-5x\n", type->t.class); break; case ty_alias: - printf (" %s %d %-5x\n", QFO_GETSTR (qfo, type->t.alias.name), - type->t.alias.type, type->t.alias.aux_type); + printf (" %s %d %5x %5x\n", + QFO_GETSTR (qfo, type->t.alias.name), + type->t.alias.type, type->t.alias.aux_type, + type->t.alias.full_type); break; } } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index f4291bb33..73151b902 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -211,6 +211,7 @@ convert_vector (expr_t *e) type_t * get_type (expr_t *e) { + const type_t *type = 0; convert_name (e); switch (e->type) { case ex_labelref: @@ -238,19 +239,23 @@ get_type (expr_t *e) return &type_void; case ex_expr: case ex_uexpr: - return e->e.expr.type; + type = e->e.expr.type; + break; case ex_def: - return e->e.def->type; + type = e->e.def->type; + break; case ex_symbol: - return e->e.symbol->type; + type = e->e.symbol->type; + break; case ex_temp: return e->e.temp.type; case ex_value: - return e->e.value->type; + type = e->e.value->type; + break; case ex_vector: return e->e.vector.type; } - return 0; + return (type_t *) unalias_type (type);//FIXME cast } etype_t @@ -632,12 +637,12 @@ new_symbol_expr (symbol_t *symbol) } expr_t * -new_temp_def_expr (type_t *type) +new_temp_def_expr (const type_t *type) { expr_t *e = new_expr (); e->type = ex_temp; - e->e.temp.type = type; + e->e.temp.type = (type_t *) unalias_type (type); // FIXME cast return e; } @@ -2026,8 +2031,9 @@ goto_expr (expr_t *label) expr_t * return_expr (function_t *f, expr_t *e) { - type_t *t; - type_t *ret_type = f->sym->type->t.func.type; + const type_t *t; + const type_t *func_type = unalias_type (f->sym->type); + const type_t *ret_type = unalias_type (func_type->t.func.type); if (!e) { if (!is_void(ret_type)) { @@ -2064,7 +2070,7 @@ return_expr (function_t *f, expr_t *e) warning (e, "returning a value for a void function"); } if (e->type == ex_bool) { - e = convert_from_bool (e, ret_type); + e = convert_from_bool (e, (type_t *) ret_type); //FIXME cast } if (is_float(ret_type) && is_integer_val (e)) { convert_int (e); @@ -2073,7 +2079,7 @@ return_expr (function_t *f, expr_t *e) if (is_void(t)) { if (e->type == ex_nil) { t = ret_type; - convert_nil (e, t); + convert_nil (e, (type_t *) t);//FIXME cast } else { if (!options.traditional) return error (e, "void value not ignored as it ought to be"); @@ -2091,7 +2097,7 @@ return_expr (function_t *f, expr_t *e) f->sym->name); } else { if (ret_type != t) { - e = cast_expr (ret_type, e); + e = cast_expr ((type_t *) ret_type, e);//FIXME cast t = f->sym->type->t.func.type; } } @@ -2621,6 +2627,7 @@ cast_expr (type_t *dstType, expr_t *e) if (e->type == ex_error) return e; + dstType = (type_t *) unalias_type (dstType); //FIXME cast srcType = get_type (e); if (dstType == srcType) diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c index 5ead7de7a..40b4e01c5 100644 --- a/tools/qfcc/source/expr_compound.c +++ b/tools/qfcc/source/expr_compound.c @@ -83,11 +83,13 @@ new_compound_init (void) } void -build_element_chain (element_chain_t *element_chain, type_t *type, +build_element_chain (element_chain_t *element_chain, const type_t *type, expr_t *eles, int base_offset) { element_t *ele = eles->e.compound.head; + type = unalias_type (type); + if (is_array (type)) { type_t *array_type = type->t.array.type; int array_size = type->t.array.size; @@ -193,8 +195,9 @@ assign_elements (expr_t *local_expr, expr_t *init, } expr_t * -initialized_temp_expr (type_t *type, expr_t *compound) +initialized_temp_expr (const type_t *type, expr_t *compound) { + type = unalias_type (type); element_chain_t element_chain; expr_t *temp = new_temp_def_expr (type); expr_t *block = new_block_expr (); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index e9cb0c823..5758eabd5 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -235,7 +235,7 @@ check_params (param_t *params) } static overloaded_function_t * -get_function (const char *name, type_t *type, int overload, int create) +get_function (const char *name, const type_t *type, int overload, int create) { const char *full_name; overloaded_function_t *func; @@ -251,7 +251,7 @@ get_function (const char *name, type_t *type, int overload, int create) func = Hash_Find (overloaded_functions, full_name); if (func) { - if (func->type != type) { + if (unalias_type (func->type) != type) { error (0, "can't overload on return types"); return func; } @@ -277,7 +277,7 @@ get_function (const char *name, type_t *type, int overload, int create) func = calloc (1, sizeof (overloaded_function_t)); func->name = name; func->full_name = full_name; - func->type = type; + func->type = (type_t *) type; //FIXME cast func->overloaded = overload; func->file = pr.source_file; func->line = pr.source_line; @@ -294,7 +294,7 @@ function_symbol (symbol_t *sym, int overload, int create) overloaded_function_t *func; symbol_t *s; - func = get_function (name, sym->type, overload, create); + func = get_function (name, unalias_type (sym->type), overload, create); if (func && func->overloaded) name = func->full_name; @@ -615,7 +615,8 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, static void build_function (symbol_t *fsym) { - if (fsym->type->t.func.num_params > MAX_PARMS) { + const type_t *func_type = unalias_type (fsym->type); + if (func_type->t.func.num_params > MAX_PARMS) { error (0, "too many params"); } // FIXME diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 0c08810f0..be76f06c4 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -774,7 +774,11 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) if (func->type >= qfo->spaces[qfo_type_space].data_size) return; type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); - if (type->meta != ty_basic && type->t.type != ev_func) + if (type->meta == ty_alias) { + type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, + type->t.alias.aux_type); + } + if (type->meta != ty_basic || type->t.type != ev_func) return; df->numparms = num_params = type->t.func.num_params; if (num_params < 0) @@ -1228,6 +1232,10 @@ qfo_to_sym (qfo_t *qfo, int *size) aux->num_locals = num_locals; //FIXME check type type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); + if (type->meta == ty_alias) { + type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, + type->t.alias.aux_type); + } aux->return_type = type->t.func.return_type; aux++; } diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index d56cd98b9..8850ebac6 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -254,6 +254,28 @@ qfo_encode_class (type_t *type) return def; } +static def_t * +qfo_encode_alias (type_t *type) +{ + qfot_type_t *enc; + def_t *def; + def_t *type_def; + def_t *full_def; + + type_def = qfo_encode_type (type->t.alias.aux_type); + full_def = qfo_encode_type (type->t.alias.full_type); + + def = qfo_new_encoding (type, sizeof (enc->t.alias)); + enc = D_POINTER (qfot_type_t, def); + enc->t.alias.type = type->type; + ENC_DEF (enc->t.alias.aux_type, type_def); + ENC_DEF (enc->t.alias.full_type, full_def); + if (type->name) { + ENC_STR (enc->t.alias.name, type->name); + } + return def; +} + def_t * qfo_encode_type (type_t *type) { @@ -266,6 +288,7 @@ qfo_encode_type (type_t *type) qfo_encode_struct, // ty_enum qfo_encode_array, // ty_array qfo_encode_class, // ty_class + qfo_encode_alias, // ty_alias }; if (type->type_def && type->type_def->external) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index bdac72d30..3529c1a1f 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -456,6 +456,7 @@ external_decl $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; + $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { initialize_def ($1, 0, current_symtab->space, spec.storage); @@ -471,6 +472,7 @@ external_decl if (spec.is_typedef) { error (0, "typedef %s is initialized", $1->name); $1->sy_type = sy_type; + $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { initialize_def ($1, $2, current_symtab->space, spec.storage); @@ -484,6 +486,7 @@ external_decl $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; + $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { $1 = function_symbol ($1, spec.is_overload, 1); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 0b54267b6..475a4e1aa 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -213,39 +213,53 @@ append_type (type_t *type, type_t *new) type_t **t = &type; while (*t) { - switch ((*t)->type) { - case ev_void: - case ev_string: - case ev_float: - case ev_vector: - case ev_entity: - case ev_type_count: - case ev_quat: - case ev_integer: - case ev_uinteger: - case ev_short: - case ev_double: - internal_error (0, "append to basic type"); - case ev_field: - case ev_pointer: - t = &(*t)->t.fldptr.type; - type->alignment = 1; - break; - case ev_func: - t = &(*t)->t.func.type; - type->alignment = 1; - break; - case ev_invalid: - if ((*t)->meta == ty_array) { - t = &(*t)->t.array.type; - type->alignment = new->alignment; - } else { - internal_error (0, "append to object type"); + switch ((*t)->meta) { + case ty_basic: + switch ((*t)->type) { + case ev_void: + case ev_string: + case ev_float: + case ev_vector: + case ev_entity: + case ev_type_count: + case ev_quat: + case ev_integer: + case ev_uinteger: + case ev_short: + case ev_double: + internal_error (0, "append to basic type"); + case ev_field: + case ev_pointer: + t = &(*t)->t.fldptr.type; + type->alignment = 1; + break; + case ev_func: + t = &(*t)->t.func.type; + type->alignment = 1; + break; + case ev_invalid: + internal_error (0, "invalid basic type"); + break; } break; + case ty_array: + t = &(*t)->t.array.type; + type->alignment = new->alignment; + break; + case ty_struct: + case ty_union: + case ty_enum: + case ty_class: + case ty_alias: //XXX is this correct? + internal_error (0, "append to object type"); } } - *t = new; + if (new->meta == ty_alias) { + *t = new->t.alias.aux_type; + type = alias_type (type, new, 0); + } else { + *t = new; + } return type; } @@ -298,7 +312,10 @@ types_same (type_t *a, type_t *b) return 0; return compare_protocols (a->protos, b->protos); case ty_alias: - return !strcmp (a->name, b->name); + // names have gone through save_string + return (a->name == b->name + && a->t.alias.aux_type == b->t.alias.aux_type + && a->t.alias.full_type == b->t.alias.full_type); } internal_error (0, "we be broke"); } @@ -349,7 +366,7 @@ find_type (type_t *type) case ty_class: break; case ty_alias: - type->t.alias.type = find_type (type->t.alias.type); + type->t.alias.aux_type = find_type (type->t.alias.aux_type); break; } } @@ -450,6 +467,30 @@ based_array_type (type_t *aux, int base, int top) return new; } +type_t * +alias_type (type_t *type, type_t *alias_chain, const char *name) +{ + type_t *alias = new_type (); + alias->meta = ty_alias; + alias->type = type->type; + alias->alignment = type->alignment; + alias->t.alias.aux_type = type; + alias->t.alias.full_type = alias_chain; + if (name) { + alias->name = save_string (name); + } + return alias; +} + +const type_t * +unalias_type (const type_t *type) +{ + if (type->meta == ty_alias) { + return type->t.alias.aux_type; + } + return type; +} + void print_type_str (dstring_t *str, const type_t *type) { @@ -460,7 +501,7 @@ print_type_str (dstring_t *str, const type_t *type) switch (type->meta) { case ty_alias: dasprintf (str, "({%s=", type->name); - print_type_str (str, type->t.alias.type); + print_type_str (str, type->t.alias.aux_type); dstring_appendstr (str, "})"); return; case ty_class: @@ -569,7 +610,7 @@ encode_params (const type_t *type) else count = type->t.func.num_params; for (i = 0; i < count; i++) - encode_type (encoding, type->t.func.param_types[i]); + encode_type (encoding, unalias_type (type->t.func.param_types[i])); if (type->t.func.num_params < 0) dasprintf (encoding, "."); @@ -622,7 +663,7 @@ encode_type (dstring_t *encoding, const type_t *type) switch (type->meta) { case ty_alias: // XXX do I want this, or just the unaliased type? dasprintf (encoding, "{%s>", type->name); - encode_type (encoding, type->t.alias.type); + encode_type (encoding, type->t.alias.aux_type); dasprintf (encoding, "}"); return; case ty_class: @@ -714,12 +755,14 @@ encode_type (dstring_t *encoding, const type_t *type) int is_void (const type_t *type) { + type = unalias_type (type); return type->type == ev_void; } int is_enum (const type_t *type) { + type = unalias_type (type); if (type->type == ev_invalid && type->meta == ty_enum) return 1; return 0; @@ -728,6 +771,7 @@ is_enum (const type_t *type) int is_integer (const type_t *type) { + type = unalias_type (type); etype_t t = type->type; if (t == ev_integer) @@ -738,6 +782,7 @@ is_integer (const type_t *type) int is_uinteger (const type_t *type) { + type = unalias_type (type); etype_t t = type->type; if (t == ev_uinteger) @@ -748,6 +793,7 @@ is_uinteger (const type_t *type) int is_short (const type_t *type) { + type = unalias_type (type); etype_t t = type->type; if (t == ev_short) @@ -758,6 +804,7 @@ is_short (const type_t *type) int is_integral (const type_t *type) { + type = unalias_type (type); if (is_integer (type) || is_uinteger (type) || is_short (type)) return 1; return is_enum (type); @@ -766,36 +813,42 @@ is_integral (const type_t *type) int is_double (const type_t *type) { + type = unalias_type (type); return type->type == ev_double; } int is_float (const type_t *type) { + type = unalias_type (type); return type->type == ev_float; } int is_scalar (const type_t *type) { + type = unalias_type (type); return is_float (type) || is_integral (type) || is_double (type); } int is_vector (const type_t *type) { + type = unalias_type (type); return type->type == ev_vector; } int is_quaternion (const type_t *type) { + type = unalias_type (type); return type->type == ev_quat; } int is_math (const type_t *type) { + type = unalias_type (type); etype_t t = type->type; return t == ev_vector || t == ev_quat || is_scalar (type); @@ -804,6 +857,7 @@ is_math (const type_t *type) int is_struct (const type_t *type) { + type = unalias_type (type); if (type->type == ev_invalid && (type->meta == ty_struct || type->meta == ty_union)) return 1; @@ -813,6 +867,7 @@ is_struct (const type_t *type) int is_pointer (const type_t *type) { + type = unalias_type (type); if (type->type == ev_pointer) return 1; return 0; @@ -821,6 +876,7 @@ is_pointer (const type_t *type) int is_field (const type_t *type) { + type = unalias_type (type); if (type->type == ev_field) return 1; return 0; @@ -829,6 +885,7 @@ is_field (const type_t *type) int is_entity (const type_t *type) { + type = unalias_type (type); if (type->type == ev_entity) return 1; return 0; @@ -837,6 +894,7 @@ is_entity (const type_t *type) int is_array (const type_t *type) { + type = unalias_type (type); if (type->type == ev_invalid && type->meta == ty_array) return 1; return 0; @@ -845,6 +903,7 @@ is_array (const type_t *type) int is_func (const type_t *type) { + type = unalias_type (type); if (type->type == ev_func) return 1; return 0; @@ -853,12 +912,14 @@ is_func (const type_t *type) int is_structural (const type_t *type) { + type = unalias_type (type); return is_struct (type) || is_array (type); } int is_string (const type_t *type) { + type = unalias_type (type); if (type->type == ev_string) return 1; return 0; @@ -888,6 +949,8 @@ type_assignable (const type_t *dst, const type_t *src) { int ret; + dst = unalias_type (dst); + src = unalias_type (src); // same type if (dst == src) return 1; @@ -952,7 +1015,7 @@ type_size (const type_t *type) return size; } case ty_alias: - return type_size (type->t.alias.type); + return type_size (type->t.alias.aux_type); } return 0; } From 8479cad8a8df41272392e41abfce81c9ec3e307d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 13:38:26 +0900 Subject: [PATCH 0933/3664] [qfcc] Record alias-free type in function_t This eases type unaliasing on functions a little. Still more to to go, but this fixes a really hair-pulling bug: linux's heap randomiser was making the typedef test fail randomly whenever typedef.qfo was compiled. --- tools/qfcc/include/function.h | 3 ++- tools/qfcc/source/expr.c | 3 +-- tools/qfcc/source/function.c | 21 ++++++++++++++------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 951b40597..3ae7c845f 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -51,7 +51,7 @@ typedef struct overloaded_function_s { const char *name; ///< source level name of function const char *full_name; ///< progs name of function, with type ///< encoding - struct type_s *type; ///< type of this function + const struct type_s *type; ///< type of this function int overloaded; ///< is this function overloaded string_t file; ///< source file of the function int line; ///< source line of this function @@ -68,6 +68,7 @@ typedef struct function_s { int local_defs; string_t s_file; ///< source file with definition string_t s_name; ///< name of function in output + const struct type_s *type; ///< function's type without aliases int temp_num; ///< number for next temp var struct def_s *temp_defs[4]; ///< freed temp vars (by size) struct def_s *def; ///< output def holding function number diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 73151b902..6bbc7b742 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2032,8 +2032,7 @@ expr_t * return_expr (function_t *f, expr_t *e) { const type_t *t; - const type_t *func_type = unalias_type (f->sym->type); - const type_t *ret_type = unalias_type (func_type->t.func.type); + const type_t *ret_type = unalias_type (f->type->t.func.type); if (!e) { if (!is_void(ret_type)) { diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 5758eabd5..81a36607a 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -251,7 +251,7 @@ get_function (const char *name, const type_t *type, int overload, int create) func = Hash_Find (overloaded_functions, full_name); if (func) { - if (unalias_type (func->type) != type) { + if (func->type != type) { error (0, "can't overload on return types"); return func; } @@ -277,7 +277,7 @@ get_function (const char *name, const type_t *type, int overload, int create) func = calloc (1, sizeof (overloaded_function_t)); func->name = name; func->full_name = full_name; - func->type = (type_t *) type; //FIXME cast + func->type = type; func->overloaded = overload; func->file = pr.source_file; func->line = pr.source_line; @@ -302,7 +302,7 @@ function_symbol (symbol_t *sym, int overload, int create) if ((!s || s->table != current_symtab) && create) { s = new_symbol (name); s->sy_type = sy_func; - s->type = sym->type; + s->type = (type_t *) unalias_type (sym->type); // FIXME cast s->params = sym->params; s->s.func = 0; // function not yet defined symtab_addsymbol (current_symtab, s); @@ -316,8 +316,8 @@ func_compare (const void *a, const void *b) { overloaded_function_t *fa = *(overloaded_function_t **) a; overloaded_function_t *fb = *(overloaded_function_t **) b; - type_t *ta = fa->type; - type_t *tb = fb->type; + const type_t *ta = fa->type; + const type_t *tb = fb->type; int na = ta->t.func.num_params; int nb = tb->t.func.num_params; int ret, i; @@ -497,7 +497,13 @@ build_scope (symbol_t *fsym, symtab_t *parent) symtab->space = defspace_new (ds_virtual); current_symtab = symtab; - if (fsym->type->t.func.num_params < 0) { + if (!fsym->s.func) { + internal_error (0, "function %s not defined", fsym->name); + } + if (!is_func (fsym->s.func->type)) { + internal_error (0, "function type %s not a funciton", fsym->name); + } + if (fsym->s.func->type->t.func.num_params < 0) { args = new_symbol_type (".args", &type_va_list); initialize_def (args, 0, symtab->space, sc_param); } @@ -551,6 +557,7 @@ make_function (symbol_t *sym, const char *nice_name, defspace_t *space, if (!sym->s.func) { sym->s.func = new_function (sym->name, nice_name); sym->s.func->sym = sym; + sym->s.func->type = unalias_type (sym->type); } if (sym->s.func->def && sym->s.func->def->external && storage != sc_extern) { @@ -615,7 +622,7 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, static void build_function (symbol_t *fsym) { - const type_t *func_type = unalias_type (fsym->type); + const type_t *func_type = fsym->s.func->type; if (func_type->t.func.num_params > MAX_PARMS) { error (0, "too many params"); } From ec3c2426ff94ed7a95c9ecd0715d084c74d43c15 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 15:34:34 +0900 Subject: [PATCH 0934/3664] [qfcc] Add type dot dumping It's not connected up yet because I'm unsure of just where to put things (it gets messy fast), but just being able to see the structure of complex types is nice. --- tools/qfcc/include/type.h | 2 + tools/qfcc/source/Makefile.am | 4 +- tools/qfcc/source/dot.c | 8 +- tools/qfcc/source/dot_type.c | 283 ++++++++++++++++++++++++++++++++++ tools/qfcc/source/stub.c | 4 + tools/qfcc/source/type.c | 1 + 6 files changed, 299 insertions(+), 3 deletions(-) create mode 100644 tools/qfcc/source/dot_type.c diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 70c650c52..686e864e1 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -74,6 +74,7 @@ typedef struct type_s { struct type_s *next; int freeable; int allocated; + int printid; ///< for dot output struct protocollist_s *protos; const char *encoding; ///< Objective-QC encoding struct def_s *type_def; ///< offset of qfo encodoing @@ -153,6 +154,7 @@ type_t *alias_type (type_t *type, type_t *alias_chain, const char *name); const type_t *unalias_type (const type_t *type) __attribute__((pure)); void print_type_str (struct dstring_s *str, const type_t *type); void print_type (const type_t *type); +void dump_dot_type (void *t, const char *filename); const char *encode_params (const type_t *type); void encode_type (struct dstring_s *encoding, const type_t *type); const char *type_get_encoding (const type_t *type); diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index bbaf06ee6..b69dd6323 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -40,7 +40,9 @@ bin_SCRIPTS= qfpreqcc common_src=\ class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \ - diagnostic.c dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c emit.c \ + diagnostic.c \ + dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c dot_type.c \ + emit.c \ expr.c expr_assign.c expr_binary.c expr_bool.c expr_compound.c expr_obj.c \ flow.c function.c grab.c \ idstuff.c \ diff --git a/tools/qfcc/source/dot.c b/tools/qfcc/source/dot.c index 5d72b5150..51d82993a 100644 --- a/tools/qfcc/source/dot.c +++ b/tools/qfcc/source/dot.c @@ -55,8 +55,12 @@ dump_dot (const char *stage, void *data, } else { dot_index++; } - fname = nva ("%s.%s.%03d.%s.dot", options.output_file, current_func->name, - dot_index, stage); + if (current_func) { + fname = nva ("%s.%s.%03d.%s.dot", options.output_file, + current_func->name, dot_index, stage); + } else { + fname = nva ("%s.%03d.%s.dot", options.output_file, dot_index, stage); + } dump_func (data, fname); free (fname); } diff --git a/tools/qfcc/source/dot_type.c b/tools/qfcc/source/dot_type.c new file mode 100644 index 000000000..bffa4aa70 --- /dev/null +++ b/tools/qfcc/source/dot_type.c @@ -0,0 +1,283 @@ +/* + dot_type.c + + "emit" types to dot (graphvis). + + Copyright (C) 2020 Bill Currie + + Author: Bill Currie + Date: 2020/03/28 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include +#include +#include +#include + +#include "class.h" +#include "symtab.h" +#include "type.h" +#include "qc-parse.h" +#include "strpool.h" + +typedef void (*print_f) (dstring_t *dstr, type_t *, int, int); +static void dot_print_type (dstring_t *dstr, type_t *t, int level, int id); + +static void +print_pointer (dstring_t *dstr, type_t *t, int level, int id) +{ + int indent = level * 2 + 2; + type_t *aux = t->t.fldptr.type; + + dot_print_type (dstr, aux, level, id); + dasprintf (dstr, "%*st_%p -> \"t_%p\";\n", indent, "", t, aux); + dasprintf (dstr, "%*st_%p [label=\"%c\"];\n", indent, "", t, + t->type == ev_pointer ? '*' : '.'); +} + +static void +print_ellipsis (dstring_t *dstr, int level, int id) +{ + static int ellipsis_id; + int indent = level * 2 + 2; + + if (ellipsis_id == id) { + return; + } + ellipsis_id = id; + dasprintf (dstr, "%*st_ellipsis [label=\"...\"];\n", indent, ""); +} + +static void +print_function (dstring_t *dstr, type_t *t, int level, int id) +{ + int indent = level * 2 + 2; + const ty_func_t *func = &t->t.func; + type_t *ret = func->type; + type_t *param; + + dot_print_type (dstr, ret, level + 1, id); + if (func->num_params < 0) { + for (int i = 0; i < ~func->num_params; i++) { + param = func->param_types[i]; + dot_print_type (dstr, param, level + 1, id); + } + print_ellipsis (dstr, level, id); + } else { + for (int i = 0; i < func->num_params; i++) { + param = func->param_types[i]; + dot_print_type (dstr, param, level + 1, id); + } + } + dasprintf (dstr, "%*st_%p -> \"t_%p\" [label=\"r\"];\n", indent, "", + t, ret); + if (func->num_params < 0) { + for (int i = 0; i < ~func->num_params; i++) { + param = func->param_types[i]; + dasprintf (dstr, "%*st_%p -> \"t_%p\";\n", indent, "", t, param); + } + dasprintf (dstr, "%*st_%p -> \"t_ellipsis\";\n", indent, "", t); + } else { + for (int i = 0; i < func->num_params; i++) { + param = func->param_types[i]; + dasprintf (dstr, "%*st_%p -> \"t_%p\";\n", indent, "", t, param); + } + } + dasprintf (dstr, "%*st_%p [label=\"( )\"];\n", indent, "", t); +} + +static void +print_basic (dstring_t *dstr, type_t *t, int level, int id) +{ + if (t->type == ev_pointer || t->type == ev_field) { + print_pointer (dstr, t, level, id); + } else if (t->type == ev_func) { + print_function (dstr, t, level, id); + } else { + int indent = level * 2 + 2; + dasprintf (dstr, "%*st_%p [label=\"%s\"];\n", indent, "", t, t->name); + } +} + +static void +print_struct (dstring_t *dstr, type_t *t, int level, int id) +{ + int indent = level * 2 + 2; + const symtab_t *symtab = t->t.symtab; + const symbol_t *sym; + int pnum; + static const char *struct_type_names[3] = {"struct", "union", "enum"}; + const char *struct_type = struct_type_names[t->meta - ty_struct]; + + if (!symtab) { + dasprintf (dstr, "%*st_%p [label=\"%s %s\"];\n", indent, "", t, + struct_type, quote_string (t->name)); + return; + } + if (t->meta != ty_enum) { + for (sym = symtab->symbols; sym; sym = sym->next) { + if (sym->sy_type != sy_var) { + continue; + } + dot_print_type (dstr, sym->type, level, id); + } + for (pnum = 0, sym = symtab->symbols; sym; sym = sym->next) { + if (sym->sy_type != sy_var) { + continue; + } + dasprintf (dstr, "%*st_%p:f%d -> \"t_%p\";\n", indent, "", + t, pnum++, sym->type); + } + } + dasprintf (dstr, "%*st_%p [shape=none,label=<\n", indent, "", t); + dasprintf (dstr, "%*s\n", + indent + 2, ""); + dasprintf (dstr, "%*s\n", + indent + 4, "", + struct_type, quote_string (t->name)); + for (pnum = 0, sym = symtab->symbols; sym; sym = sym->next) { + int val; + const char *port = ""; + if (sym->sy_type == sy_const) { + val = sym->s.value->v.integer_val; + } else { + if (sym->sy_type != sy_var) { + continue; + } + val = sym->s.offset; + port = va (" port=\"f%d\"", pnum++); + } + dasprintf (dstr, "%*s%d\n", + indent + 4, "", + quote_string (sym->name), port, val); + } + dasprintf (dstr, "%*s
%s %s
%s
\n", indent + 2, ""); + dasprintf (dstr, "%*s>];\n", indent, ""); +} + +static void +print_array (dstring_t *dstr, type_t *t, int level, int id) +{ + int indent = level * 2 + 2; + type_t *type = t->t.array.type; + + dot_print_type (dstr, type, level, id); + dasprintf (dstr, "%*st_%p -> \"t_%p\";\n", indent, "", t, type); + if (t->t.array.base) { + dasprintf (dstr, "%*st_%p [label=\"[%d..%d]\"];\n", indent, "", t, + t->t.array.base, + t->t.array.base + t->t.array.size - 1); + } else { + dasprintf (dstr, "%*st_%p [label=\"[%d]\"];\n", indent, "", t, + t->t.array.size); + } +} + +static void +print_class (dstring_t *dstr, type_t *t, int level, int id) +{ + int indent = level * 2 + 2; + dasprintf (dstr, "%*st_%p [label=\"class '%s'\"];\n", indent, "", t, + t->t.class->name); +} + +static void +print_alias (dstring_t *dstr, type_t *t, int level, int id) +{ + int indent = level * 2 + 2; + type_t *aux = t->t.alias.aux_type; + type_t *full = t->t.alias.full_type; + + dot_print_type (dstr, aux, level, id); + dot_print_type (dstr, full, level, id); + dasprintf (dstr, "%*st_%p -> \"t_%p\";\n", indent, "", t, aux); + dasprintf (dstr, "%*st_%p -> \"t_%p\";\n", indent, "", t, full); + dasprintf (dstr, "%*st_%p [label=\"alias '%s'\"];\n", indent, "", t, + t->name); +} + +static void +dot_print_type (dstring_t *dstr, type_t *t, int level, int id) +{ + static print_f print_funcs[] = { + print_basic, + print_struct, + print_struct, + print_struct, + print_array, + print_class, + print_alias, + }; + int indent = level * 2 + 2; + + if (!t) { + dasprintf (dstr, "%*s\"e_%p\" [label=\"(null)\"];\n", indent, "", t); + return; + } + if (t->printid == id) // already printed this type + return; + t->printid = id; + + if ((unsigned) t->meta >= sizeof (print_funcs) / sizeof (print_funcs[0])) { + dasprintf (dstr, "%*se_%p [label=\"(bad type meta)\\n%d\"];\n", + indent, "", t, t->meta); + return; + } + print_funcs [t->meta] (dstr, t, level, id); +} + +void +dump_dot_type (void *_t, const char *filename) +{ + static int id = 0; + dstring_t *dstr = dstring_newstr (); + type_t *t = (type_t *) _t; + + dasprintf (dstr, "digraph type_%p {\n", t); + dasprintf (dstr, " graph [label=\"%s\"];\n", quote_string (filename)); + dasprintf (dstr, " layout=dot; rankdir=TB; compound=true;\n"); + dot_print_type (dstr, t, 0, ++id); + dasprintf (dstr, "}\n"); + + if (filename) { + QFile *file; + + file = Qopen (filename, "wt"); + Qwrite (file, dstr->str, dstr->size - 1); + Qclose (file); + } else { + fputs (dstr->str, stdout); + } + dstring_delete (dstr); +} diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index 405104126..f3601d04b 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -7,6 +7,7 @@ #include "class.h" #include "codespace.h" #include "diagnostic.h" +#include "dot.h" #include "debug.h" #include "def.h" #include "defspace.h" @@ -49,3 +50,6 @@ int is_id (const type_t *type){return type->type;} int is_SEL (const type_t *type){return type->type;} int is_Class (const type_t *type){return type->type;} int compare_protocols (protocollist_t *protos1, protocollist_t *protos2){return protos1->count - protos2->count;} +void dump_dot (const char *stage, void *data, + void (*dump_func) (void *data, const char *fname)){} +void dump_dot_type (void *_t, const char *filename){} diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 475a4e1aa..5bb93b787 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -50,6 +50,7 @@ #include "class.h" #include "def.h" #include "diagnostic.h" +#include "dot.h" #include "expr.h" #include "function.h" #include "obj_type.h" From da39e675b8d09e45f66eb4f89753fa34631ef554 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 17:13:47 +0900 Subject: [PATCH 0935/3664] [qfcc] Copy type chain for type aliases The full_type branch of an alias splitter (alias with null name) needs to mirror the clean side up to the type alias. It is causing problems with functions, but that's expected because parameters complicate things. --- tools/qfcc/source/type.c | 60 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 5bb93b787..e6d3e4b9f 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -50,7 +50,6 @@ #include "class.h" #include "def.h" #include "diagnostic.h" -#include "dot.h" #include "expr.h" #include "function.h" #include "obj_type.h" @@ -208,6 +207,60 @@ free_type (type_t *type) FREE (types, type); } +static type_t * +copy_chain (type_t *type, type_t *append) +{ + type_t *new = 0; + type_t **n = &new; + + while (type) { + *n = new_type (); + **n = *type; + switch (type->meta) { + case ty_basic: + switch (type->type) { + case ev_void: + case ev_string: + case ev_float: + case ev_vector: + case ev_entity: + case ev_type_count: + case ev_quat: + case ev_integer: + case ev_uinteger: + case ev_short: + case ev_double: + internal_error (0, "copy basic type"); + case ev_field: + case ev_pointer: + n = &(*n)->t.fldptr.type; + type = type->t.fldptr.type; + break; + case ev_func: + n = &(*n)->t.func.type; + type = type->t.func.type; + break; + case ev_invalid: + internal_error (0, "invalid basic type"); + break; + } + break; + case ty_array: + n = &(*n)->t.array.type; + type = type->t.array.type; + break; + case ty_struct: + case ty_union: + case ty_enum: + case ty_class: + case ty_alias: //XXX is this correct? + internal_error (0, "copy object type %d", type->meta); + } + } + *n = append; + return new; +} + type_t * append_type (type_t *type, type_t *new) { @@ -255,9 +308,10 @@ append_type (type_t *type, type_t *new) internal_error (0, "append to object type"); } } - if (new->meta == ty_alias) { + if (type && new->meta == ty_alias) { + type_t *chain = find_type (copy_chain (type, new)); *t = new->t.alias.aux_type; - type = alias_type (type, new, 0); + type = alias_type (type, chain, 0); } else { *t = new; } From 69037fe5eb82b9211c621c6945dc7d8bc808e85d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 18:51:38 +0900 Subject: [PATCH 0936/3664] [qfcc] Strip alias info off function params For now. This fixes many problems but does lose type aliasing info from function parameters. --- tools/qfcc/source/function.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 81a36607a..b199bf51d 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -170,6 +170,7 @@ parse_params (type_t *type, param_t *parms) { param_t *p; type_t *new; + type_t *ptype; int count = 0; if (type && is_class (type)) { @@ -201,7 +202,8 @@ parse_params (type_t *type, param_t *parms) error (0, "cannot use an object as a parameter (forgot *?)"); p->type = &type_id; } - new->t.func.param_types[new->t.func.num_params] = p->type; + ptype = (type_t *) unalias_type (p->type); //FIXME cast + new->t.func.param_types[new->t.func.num_params] = ptype; new->t.func.num_params++; } } From eacdd0d3dea8f5c682462a33ec2eff15244442e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 18:52:57 +0900 Subject: [PATCH 0937/3664] [qfcc] Make file_basename accessible and more usable --- tools/qfcc/include/qfcc.h | 1 + tools/qfcc/source/qfcc.c | 13 +++++++------ tools/qfcc/source/stub.c | 2 ++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index e428831cb..dc8dddac2 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -109,6 +109,7 @@ extern pr_info_t pr; #define POINTER_OFS(s,p) ((pr_type_t *) (p) - (s)->data) const char *strip_path (const char *filename) __attribute__((pure)); +const char *file_basename (const char *filename, int keepdot) __attribute__((pure)); extern FILE *qc_yyin; extern FILE *qp_yyin; diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 7d0f8c800..15f3d31d7 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -313,8 +313,8 @@ strip_path (const char *filename) return filename; } -static const char * -file_basename (const char *filename) +const char * +file_basename (const char *filename, int keepdot) { const char *p; const char *dot; @@ -325,7 +325,7 @@ file_basename (const char *filename) for (dot = p = filename + strlen (filename); p > filename; p--) { if (p[-1] == '/' || p[-1] == '\\') break; - if (p[0] == '.') + if (!keepdot && p[0] == '.') dot = p; } dstring_copysubstr (base, p, dot - p); @@ -395,7 +395,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) } } if (options.frames_files) { - write_frame_macros (va ("%s.frame", file_basename (file))); + write_frame_macros (va ("%s.frame", file_basename (file, 0))); } if (!err) { qfo_t *qfo; @@ -753,13 +753,14 @@ progs_src_compile (void) fprintf (single, "#include \"%s\"\n", qc_filename->str); if (options.frames_files) fprintf (single, "$frame_write \"%s.frame\"\n", - file_basename (qc_filename->str)); + file_basename (qc_filename->str, 0)); } else { if (compile_file (qc_filename->str)) return 1; if (options.frames_files) { write_frame_macros (va ("%s.frame", - file_basename (qc_filename->str))); + file_basename (qc_filename->str, + 0))); } } if (!Script_TokenAvailable (script, 0)) diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index f3601d04b..7180f9e88 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -53,3 +53,5 @@ int compare_protocols (protocollist_t *protos1, protocollist_t *protos2){return void dump_dot (const char *stage, void *data, void (*dump_func) (void *data, const char *fname)){} void dump_dot_type (void *_t, const char *filename){} +const char *strip_path(const char *p) { return p;} +const char *file_basename(const char *p, int keepdot) { return p;} From b6ea47dca690e345e75ca4917db35df471237220 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 18:58:08 +0900 Subject: [PATCH 0938/3664] [qfcc] Add failing function overload test This is a bit of a weird one because it's a combination of the aliasing code and mixing C prototypes with QuakeC function definitions, and the function type rebuilding in qc-parse.y not being very "consistent" in its abuse of the type system. --- tools/qfcc/test/Makefile.am | 12 +++++++++++- tools/qfcc/test/old/overload.r | 30 ------------------------------ tools/qfcc/test/overload.r | 23 +++++++++++++++++++++++ 3 files changed, 34 insertions(+), 31 deletions(-) delete mode 100644 tools/qfcc/test/old/overload.r create mode 100644 tools/qfcc/test/overload.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index fe78065d7..73528545d 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -54,6 +54,7 @@ test_progs_dat=\ methodparams.dat \ modulo.dat \ nilparamret.dat \ + overload.dat \ paramret.dat \ quaternion.dat \ return-ivar.dat \ @@ -333,6 +334,15 @@ nilparamret.run: Makefile build-run include ./$(DEPDIR)/nilparamret.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/nilparamret.Qo +overload_dat_SOURCES=overload.r +overload_obj=$(overload_dat_SOURCES:.r=.qfo) +overload.dat$(EXEEXT): $(overload_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(overload_obj) +overload.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/overload.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/overload.Qo + paramret_dat_SOURCES=paramret.r paramret_obj=$(paramret_dat_SOURCES:.r=.qfo) paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) @@ -512,4 +522,4 @@ $(r_depfiles_remade): am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) EXTRA_DIST= test-bi.h build-run test-defspace.h -CLEANFILES= *.dat *.sym *.qfo *.run *.frame +CLEANFILES= *.dat *.sym *.qfo *.run *.frame *.log *.trs diff --git a/tools/qfcc/test/old/overload.r b/tools/qfcc/test/old/overload.r deleted file mode 100644 index 60bd5cf46..000000000 --- a/tools/qfcc/test/old/overload.r +++ /dev/null @@ -1,30 +0,0 @@ -//integer foo; -//typedef integer foo; -//integer (void) foo = #0; -//integer (bag); -//.integer (sack); -//.integer (float sack)x; -//integer *bar, baz; -//integer snafu(void) -//{ -//} -//integer [8]blah; - -@overload void func (integer a, integer b, integer c); -@overload void func (integer a, integer b); -@overload void func (integer a, ...); -//@overload void func (integer a, integer b, ...); -@overload void func (string y); -//@overload void func (...); -void func (integer x) -{ -// func (""); -} -void func (string y) -{ -// func (0.0); -// func (0, 0.0); -// func (0, 0, 0.0); - func (0.0, ""); -// func (0, 0, 0, 0, 0.0); -} diff --git a/tools/qfcc/test/overload.r b/tools/qfcc/test/overload.r new file mode 100644 index 000000000..97c77bbdf --- /dev/null +++ b/tools/qfcc/test/overload.r @@ -0,0 +1,23 @@ +typedef enum { + NO = 0, + YES +} BOOL; + +@extern BOOL sel_is_mapped (SEL aSel); +BOOL (SEL aSel) sel_is_mapped = #0; + +@overload int foo(int x) +{ + return 1; +} + +@overload int foo(float x) +{ + return 2; +} + +int main() +{ + //FIXME fails on implicit cast of double to float + return !(foo(5) == 1 && foo (5.0f) == 2); +} From f224eadbb8eefaa22dee6a4cebcf4230e9d0b454 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 19:01:49 +0900 Subject: [PATCH 0939/3664] [qfcc] Rework QuakeC function type manging It is now "consistent" with the rest of the type building in that it uses find_type(append_type(return, params)) like the C version, thus allowing append_type to do its thing with type aliases. This fixes the overload test. --- tools/qfcc/source/qc-parse.y | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 3529c1a1f..f759a4964 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -366,14 +366,17 @@ external_def | optional_specifiers qc_func_params { type_t **type; + type_t *ret_type; $$ = $1; // copy spec bits and storage // .float () foo; is a field holding a function variable rather // than a function that returns a float field. - for (type = &$$.type; *type && (*type)->type == ev_field; - type = &(*type)->t.fldptr.type) - ; - *type = parse_params (*type, $2); - $$.type = find_type ($$.type); + for (type = &$1.type; *type && (*type)->type == ev_field; + type = &(*type)->t.fldptr.type) { + } + ret_type = *type; + *type = 0; + *type = parse_params (0, $2); + $$.type = find_type (append_type ($1.type, ret_type)); if ($$.type->type != ev_field) $$.params = $2; } From 262c6a61f5e116cf90b48e6065bc42f059c32e07 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 21:11:42 +0900 Subject: [PATCH 0940/3664] [qfcc] Add failing test for linker zero/param issue This tests issue #6 --- tools/qfcc/test/Makefile.am | 13 ++++++++++- tools/qfcc/test/zerolinker.r | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tools/qfcc/test/zerolinker.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 73528545d..d43706b9b 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -73,7 +73,9 @@ test_progs_dat=\ vecexpr.dat \ vecinit.dat \ voidfor.dat \ - while.dat + while.dat \ + zerolinker.dat \ + $e fail_progs_dat= @@ -514,6 +516,15 @@ while.run: Makefile build-run include ./$(DEPDIR)/while.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/while.Qo +zerolinker_dat_SOURCES=zerolinker.r +zerolinker_obj=$(zerolinker_dat_SOURCES:.r=.qfo) +zerolinker.dat$(EXEEXT): $(zerolinker_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(zerolinker_obj) +zerolinker.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/zerolinker.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/zerolinker.Qo + $(r_depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ diff --git a/tools/qfcc/test/zerolinker.r b/tools/qfcc/test/zerolinker.r new file mode 100644 index 000000000..2babf2b1c --- /dev/null +++ b/tools/qfcc/test/zerolinker.r @@ -0,0 +1,45 @@ +#include + +// can't link against libr.a (may not be built) +void *PR_FindGlobal (string name) = #0; +void printf (string fmt, ...) = #0; + +qfot_type_encodings_t *encodings; + +qfot_type_t * +next_type (qfot_type_t *type) +{ + int size = type.size; + if (!size) + size = 4; + return (qfot_type_t *) ((int *) type + size); +} + +int +main (void) +{ + int found_param = 0; + int found_zero = 0; + qfot_type_t *type; + + encodings = PR_FindGlobal (".type_encodings"); + + for (type = encodings.types; + ((int *)type - (int *) encodings.types) < encodings.size; + type = next_type (type)) { + if (type.meta == ty_struct) { + if (type.t.strct.tag == "tag @param") { + found_param = 1; + } + if (type.t.strct.tag == "tag @zero") { + found_zero = 1; + } + } + } + if (!(found_param && found_zero)) { + printf ("missing struct: param: %d zero:%d\n", + found_param, found_zero); + return 1; + } + return 0; +} From 7218af6be45827a63f9076cf3fe287bb14e86dc1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 21:19:20 +0900 Subject: [PATCH 0941/3664] [qfcc] Print qfo def type address --- tools/qfcc/source/dump_globals.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 1695769e0..ab15b0c4d 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -320,9 +320,10 @@ qfo_globals (qfo_t *qfo) for (space = 0; space < qfo->num_spaces; space++) { for (i = 0; i < qfo->spaces[space].num_defs; i++, count++) { def = &qfo->spaces[space].defs[i]; - printf ("%-5d %2d:%-5x %s %s %s", count, space, def->offset, + printf ("%-5d %2d:%-5x %s %s %x %s", count, space, def->offset, flags_string (def->flags), QFO_GETSTR (qfo, def->name), + def->type, QFO_TYPESTR (qfo, def->type)); if (!(def->flags & QFOD_EXTERNAL) && qfo->spaces[space].d.data) printf (" %d", From 869efa723999b70ace2f25e5042b81e806f44906 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 21:19:55 +0900 Subject: [PATCH 0942/3664] [gamecode] Use etype_t in more places But forget about bitfields. If enum isn't int and int isn't 32-bits, we've probably got other problems (and there may be a better way). --- include/QF/pr_type.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index c74ad3c26..d8c706fae 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -51,19 +51,19 @@ typedef enum { } ty_meta_e; typedef struct qfot_alias_s { - pr_int_t type; ///< type at end of alias chain + etype_t type; ///< type at end of alias chain pointer_t aux_type; ///< referenced type: stripped of aliases pointer_t full_type; ///< includes full alias info string_t name; ///< alias name, may be null } qfot_alias_t; typedef struct qfot_fldptr_s { - pr_int_t type; ///< ev_field or ev_pointer + etype_t type; ///< ev_field or ev_pointer pointer_t aux_type; ///< referenced type } qfot_fldptr_t; typedef struct qfot_func_s { - pr_int_t type; ///< always ev_func + etype_t type; ///< always ev_func pointer_t return_type; ///< return type of the function pr_int_t num_params; ///< ones compliment count of the ///< parameters. -ve values indicate the @@ -101,11 +101,11 @@ typedef struct qfot_array_s { arrays. */ typedef struct qfot_type_s { - ty_meta_e meta:32; ///< meta type + ty_meta_e meta; ///< meta type pr_uint_t size; ///< total word size of this encoding string_t encoding; ///< Objective-QC encoding union { - etype_t type:32; ///< ty_basic: etype_t + etype_t type; ///< ty_basic: etype_t qfot_fldptr_t fldptr; ///< ty_basic, ev_pointer/ev_field qfot_func_t func; ///< ty_basic, ev_func qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum From 1cd7bd2bf09d1c0419d339b5289a5204f3ee208e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 21:31:04 +0900 Subject: [PATCH 0943/3664] [qfcc] Use correct meta for zerolinker test Still fails, of course :) --- tools/qfcc/test/zerolinker.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/test/zerolinker.r b/tools/qfcc/test/zerolinker.r index 2babf2b1c..a5c6f7039 100644 --- a/tools/qfcc/test/zerolinker.r +++ b/tools/qfcc/test/zerolinker.r @@ -27,7 +27,7 @@ main (void) for (type = encodings.types; ((int *)type - (int *) encodings.types) < encodings.size; type = next_type (type)) { - if (type.meta == ty_struct) { + if (type.meta == ty_union) { if (type.t.strct.tag == "tag @param") { found_param = 1; } From ac9f3404ef9658dcd0682cacd56fd39b566d2560 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 21:46:46 +0900 Subject: [PATCH 0944/3664] [qfcc] Improve string quoting when dumping strings Not knowing if a blank line is an empty string or spaces... --- tools/qfcc/source/dump_strings.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/dump_strings.c b/tools/qfcc/source/dump_strings.c index 77f3c0ae4..5f119e7cc 100644 --- a/tools/qfcc/source/dump_strings.c +++ b/tools/qfcc/source/dump_strings.c @@ -44,14 +44,14 @@ dump_string_block (const char *strblock, unsigned size) { const char *s = strblock; - printf ("%x ", 0); + printf ("%x \"", 0); while (s - strblock < size) { char c = *s++; switch (c) { case 0: - fputs ("\n", stdout); + fputs ("\"\n", stdout); if (s - strblock < size) - printf ("%lx ", s - strblock); + printf ("%lx \"", s - strblock); break; case 9: fputs ("\\t", stdout); @@ -62,6 +62,12 @@ dump_string_block (const char *strblock, unsigned size) case 13: fputs ("\\r", stdout); break; + case '\"': + fputs ("\\\"", stdout); + break; + case '\\': + fputs ("\\\\", stdout); + break; default: fputc (sys_char_map[(unsigned char)c], stdout); break; From 54a9305dbfbf4d04b860f02920abdb17eec8fec0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 22:02:42 +0900 Subject: [PATCH 0945/3664] [qfcc] Use right object for sizeof Since the bitfield has been abandoned, can use sizeof on the field again. --- tools/qfcc/source/obj_type.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 8850ebac6..b823f0355 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -151,8 +151,7 @@ qfo_encode_basic (type_t *type) else if (type->type == ev_pointer || type->type == ev_field) return qfo_encode_fldptr (type); - // can't use sizeof on enc->t.type, but pr_uint_t is the backing type - def = qfo_new_encoding (type, sizeof (pr_uint_t)); + def = qfo_new_encoding (type, sizeof (enc->t.type)); enc = D_POINTER (qfot_type_t, def); enc->t.type = type->type; return def; From 31ea3814bb633bb3720a8591baadaea0bae8b914 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 22:15:06 +0900 Subject: [PATCH 0946/3664] [qfcc] Decouple type encoding from the pr struct This will allow encoding types correctly in the linker. --- tools/qfcc/include/obj_type.h | 3 +- tools/qfcc/source/obj_type.c | 57 ++++++++++++++++++----------------- tools/qfcc/source/struct.c | 2 +- tools/qfcc/source/stub.c | 2 +- tools/qfcc/source/type.c | 2 +- 5 files changed, 34 insertions(+), 32 deletions(-) diff --git a/tools/qfcc/include/obj_type.h b/tools/qfcc/include/obj_type.h index 13ce701e4..a8c546703 100644 --- a/tools/qfcc/include/obj_type.h +++ b/tools/qfcc/include/obj_type.h @@ -35,7 +35,8 @@ #include "type.h" +struct defspace_s; struct type_s; -struct def_s *qfo_encode_type (struct type_s *type); +struct def_s *qfo_encode_type (struct type_s *type, struct defspace_s *space); #endif//__obj_type_h diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index b823f0355..78d7fc868 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -63,7 +63,7 @@ reloc_def_string (&loc); \ } while (0) -typedef def_t *(*encode_f) (type_t *type); +typedef def_t *(*encode_f) (type_t *type, defspace_t *space); static string_t encoding_string (const char *string) @@ -75,7 +75,7 @@ encoding_string (const char *string) } static def_t * -qfo_new_encoding (type_t *type, int size) +qfo_new_encoding (type_t *type, int size, defspace_t *space) { qfot_type_t *enc; def_t *def; @@ -83,7 +83,7 @@ qfo_new_encoding (type_t *type, int size) size += sizeof (qfot_type_t) - sizeof (enc->t); size /= sizeof (pr_type_t); - def = new_def (type->encoding, 0, pr.type_data, sc_static); + def = new_def (type->encoding, 0, space, sc_static); def->offset = defspace_alloc_loc (pr.type_data, size); enc = D_POINTER (qfot_type_t, def); @@ -94,7 +94,7 @@ qfo_new_encoding (type_t *type, int size) } static def_t * -qfo_encode_func (type_t *type) +qfo_encode_func (type_t *type, defspace_t *space) { int param_count; int size; @@ -109,12 +109,13 @@ qfo_encode_func (type_t *type) if (param_count < 0) param_count = ~param_count; param_type_defs = alloca (param_count * sizeof (def_t *)); - return_type_def = qfo_encode_type (type->t.func.type); + return_type_def = qfo_encode_type (type->t.func.type, space); for (i = 0; i < param_count; i++) - param_type_defs[i] = qfo_encode_type (type->t.func.param_types[i]); + param_type_defs[i] = qfo_encode_type (type->t.func.param_types[i], + space); size = field_offset (qfot_func_t, param_types[param_count]); - def = qfo_new_encoding (type, size); + def = qfo_new_encoding (type, size, space); enc = D_POINTER (qfot_type_t, def); func = &enc->t.func; func->type = ev_func; @@ -126,14 +127,14 @@ qfo_encode_func (type_t *type) } static def_t * -qfo_encode_fldptr (type_t *type) +qfo_encode_fldptr (type_t *type, defspace_t *space) { qfot_type_t *enc; def_t *def; def_t *type_def; - type_def = qfo_encode_type (type->t.fldptr.type); - def = qfo_new_encoding (type, sizeof (enc->t.fldptr)); + type_def = qfo_encode_type (type->t.fldptr.type, space); + def = qfo_new_encoding (type, sizeof (enc->t.fldptr), space); enc = D_POINTER (qfot_type_t, def); enc->t.fldptr.type = type->type; ENC_DEF (enc->t.fldptr.aux_type, type_def); @@ -141,24 +142,24 @@ qfo_encode_fldptr (type_t *type) } static def_t * -qfo_encode_basic (type_t *type) +qfo_encode_basic (type_t *type, defspace_t *space) { qfot_type_t *enc; def_t *def; if (type->type == ev_func) - return qfo_encode_func (type); + return qfo_encode_func (type, space); else if (type->type == ev_pointer || type->type == ev_field) - return qfo_encode_fldptr (type); + return qfo_encode_fldptr (type, space); - def = qfo_new_encoding (type, sizeof (enc->t.type)); + def = qfo_new_encoding (type, sizeof (enc->t.type), space); enc = D_POINTER (qfot_type_t, def); enc->t.type = type->type; return def; } static def_t * -qfo_encode_struct (type_t *type) +qfo_encode_struct (type_t *type, defspace_t *space) { sy_type_e sy; int num_fields; @@ -185,7 +186,7 @@ qfo_encode_struct (type_t *type) } size = field_offset (qfot_struct_t, fields[num_fields]); - def = qfo_new_encoding (type, size); + def = qfo_new_encoding (type, size, space); enc = D_POINTER (qfot_type_t, def); strct = &enc->t.strct; ENC_STR (strct->tag, type->name); @@ -200,7 +201,7 @@ qfo_encode_struct (type_t *type) if (i == num_fields) internal_error (0, "whoa, what happened?"); if (type->meta != ty_enum) { - field_types[i] = qfo_encode_type (sym->type); + field_types[i] = qfo_encode_type (sym->type, space); } else { field_types[i] = type_default->type_def; } @@ -225,15 +226,15 @@ qfo_encode_struct (type_t *type) } static def_t * -qfo_encode_array (type_t *type) +qfo_encode_array (type_t *type, defspace_t *space) { qfot_type_t *enc; def_t *def; def_t *array_type_def; - array_type_def = qfo_encode_type (type->t.array.type); + array_type_def = qfo_encode_type (type->t.array.type, space); - def = qfo_new_encoding (type, sizeof (enc->t.array)); + def = qfo_new_encoding (type, sizeof (enc->t.array), space); enc = D_POINTER (qfot_type_t, def); ENC_DEF (enc->t.array.type, array_type_def); enc->t.array.base = type->t.array.base; @@ -242,29 +243,29 @@ qfo_encode_array (type_t *type) } static def_t * -qfo_encode_class (type_t *type) +qfo_encode_class (type_t *type, defspace_t *space) { qfot_type_t *enc; def_t *def; - def = qfo_new_encoding (type, sizeof (enc->t.class)); + def = qfo_new_encoding (type, sizeof (enc->t.class), space); enc = D_POINTER (qfot_type_t, def); ENC_STR (enc->t.class, type->t.class->name); return def; } static def_t * -qfo_encode_alias (type_t *type) +qfo_encode_alias (type_t *type, defspace_t *space) { qfot_type_t *enc; def_t *def; def_t *type_def; def_t *full_def; - type_def = qfo_encode_type (type->t.alias.aux_type); - full_def = qfo_encode_type (type->t.alias.full_type); + type_def = qfo_encode_type (type->t.alias.aux_type, space); + full_def = qfo_encode_type (type->t.alias.full_type, space); - def = qfo_new_encoding (type, sizeof (enc->t.alias)); + def = qfo_new_encoding (type, sizeof (enc->t.alias), space); enc = D_POINTER (qfot_type_t, def); enc->t.alias.type = type->type; ENC_DEF (enc->t.alias.aux_type, type_def); @@ -276,7 +277,7 @@ qfo_encode_alias (type_t *type) } def_t * -qfo_encode_type (type_t *type) +qfo_encode_type (type_t *type, defspace_t *space) { reloc_t *relocs = 0; @@ -301,7 +302,7 @@ qfo_encode_type (type_t *type) internal_error (0, "bad type meta type"); if (!type->encoding) type->encoding = type_get_encoding (type); - type->type_def = funcs[type->meta] (type); + type->type_def = funcs[type->meta] (type, space); reloc_attach_relocs (relocs, &type->type_def->relocs); return type->type_def; } diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 2e828de1b..59ac6fe7a 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -173,7 +173,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) sym->type->t.symtab = symtab; sym->type->alignment = alignment; if (!type && sym->type->type_def->external) //FIXME should not be necessary - sym->type->type_def = qfo_encode_type (sym->type); + sym->type->type_def = qfo_encode_type (sym->type, pr.type_data); return sym; } diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index 7180f9e88..b7d73cd68 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -43,7 +43,7 @@ __attribute__((const)) expr_t *_error (expr_t *e, const char *file, int line, co __attribute__((const)) symbol_t *make_structure (const char *name, int su, struct_def_t *defs, type_t *type) {return 0;} __attribute__((const)) symbol_t *symtab_addsymbol (symtab_t *symtab, symbol_t *symbol) {return 0;} __attribute__((const)) symbol_t *new_symbol_type (const char *name, type_t *type) {return 0;} -__attribute__((const)) def_t *qfo_encode_type (type_t *type) {return 0;} +__attribute__((const)) def_t *qfo_encode_type (type_t *type, defspace_t *space) {return 0;} __attribute__((const)) int obj_types_assignable (const type_t *dst, const type_t *src) {return 0;} void print_protocollist (struct dstring_s *dstr, protocollist_t *protocollist) {} int is_id (const type_t *type){return type->type;} diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index e6d3e4b9f..8bb0b5673 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -156,7 +156,7 @@ chain_type (type_t *type) if (!type->encoding) type->encoding = type_get_encoding (type); if (!type->type_def) - type->type_def = qfo_encode_type (type); + type->type_def = qfo_encode_type (type, pr.type_data); } type_t * From c13162e41e90904f5dd3cf3a6a96450424e765bd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 22:53:35 +0900 Subject: [PATCH 0947/3664] [qfcc] Rearrange type initialization Fixes #6 It turned out that the problem with @zero was caused by initial type chaining occurring before the structures had been initialized and thus the linker's @zero type encoding string was incorrect: {?=} instead of {tag @zero-}, thus when the actual type encoding supplied by an object file came along (with the correct encoding string), it wasn't found. --- tools/qfcc/source/qfcc.c | 5 ++- tools/qfcc/source/type.c | 93 ++++++++++++++++++++++------------------ 2 files changed, 56 insertions(+), 42 deletions(-) diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 15f3d31d7..1167611ad 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -181,7 +181,6 @@ InitData (void) clear_classes (); clear_immediates (); clear_selectors (); - chain_initial_types (); } static int @@ -384,6 +383,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) return !options.preprocess_only; InitData (); + chain_initial_types (); begin_compilation (); pr.source_file = ReuseString (strip_path (file)); err = yyparse () || pr.error_count; @@ -549,6 +549,7 @@ separate_compile (void) dstring_delete (extension); if (!err && !options.compile) { InitData (); + chain_initial_types (); linker_begin (); for (file = source_files; *file; file++) { if (strncmp (*file, "-l", 2)) { @@ -726,6 +727,7 @@ progs_src_compile (void) setup_sym_file (options.output_file); InitData (); + chain_initial_types (); begin_compilation (); @@ -830,6 +832,7 @@ main (int argc, char **argv) parse_cpp_name (); opcode_init (); + InitData (); init_types (); clear_immediates (); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 8bb0b5673..08a02855b 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -1075,6 +1075,47 @@ type_size (const type_t *type) return 0; } +static void +chain_basic_types (void) +{ + chain_type (&type_void); + chain_type (&type_string); + chain_type (&type_float); + chain_type (&type_vector); + type_entity.t.symtab = pr.entity_fields; + chain_type (&type_entity); + chain_type (&type_field); + chain_type (&type_function); + chain_type (&type_pointer); + chain_type (&type_floatfield); + if (!options.traditional) { + chain_type (&type_quaternion); + chain_type (&type_integer); + chain_type (&type_uinteger); + chain_type (&type_short); + chain_type (&type_double); + } +} + +static void +chain_structural_types (void) +{ + chain_type (&type_param); + chain_type (&type_zero); + chain_type (&type_type_encodings); + chain_type (&type_xdef); + chain_type (&type_xdef_pointer); + chain_type (&type_xdefs); + chain_type (&type_va_list); +} + +void +chain_initial_types (void) +{ + chain_basic_types (); + chain_structural_types (); +} + void init_types (void) { @@ -1136,6 +1177,13 @@ init_types (void) {"num_xdefs", &type_pointer}, {0, 0} }; + static struct_def_t va_list_struct[] = { + {"count", &type_integer}, + {"list", 0}, // type will be filled in at runtime + {0, 0} + }; + + chain_basic_types (); type_nil = &type_quaternion; type_default = &type_integer; @@ -1160,8 +1208,8 @@ init_types (void) make_structure ("@xdef", 's', xdef_struct, &type_xdef); make_structure ("@xdefs", 's', xdefs_struct, &type_xdefs); - if (options.traditional) - return; + va_list_struct[1].type = pointer_type (&type_param); + make_structure ("@va_list", 's', va_list_struct, &type_va_list); make_structure ("@quaternion", 's', quaternion_struct, &type_quaternion); type_quaternion.type = ev_quat; @@ -1181,43 +1229,6 @@ init_types (void) sym->s.offset = 3; symtab_addsymbol (type_quaternion.t.symtab, sym); } -} - -void -chain_initial_types (void) -{ - static struct_def_t va_list_struct[] = { - {"count", &type_integer}, - {"list", 0}, // type will be filled in at runtime - {0, 0} - }; - - chain_type (&type_void); - chain_type (&type_string); - chain_type (&type_float); - chain_type (&type_vector); - type_entity.t.symtab = pr.entity_fields; - chain_type (&type_entity); - chain_type (&type_field); - chain_type (&type_function); - chain_type (&type_pointer); - chain_type (&type_floatfield); - if (!options.traditional) { - chain_type (&type_quaternion); - chain_type (&type_integer); - chain_type (&type_uinteger); - chain_type (&type_short); - chain_type (&type_double); - } - - chain_type (&type_param); - chain_type (&type_zero); - chain_type (&type_type_encodings); - chain_type (&type_xdef); - chain_type (&type_xdef_pointer); - chain_type (&type_xdefs); - - va_list_struct[1].type = pointer_type (&type_param); - make_structure ("@va_list", 's', va_list_struct, &type_va_list); - chain_type (&type_va_list); + + chain_structural_types (); } From 8ba3ab89d5316872c0bb4f7b88e7afaf2d9807e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Mar 2020 23:30:05 +0900 Subject: [PATCH 0948/3664] [qfcc] Add failing aliased type linking test --- tools/qfcc/test/Makefile.am | 10 ++++++++++ tools/qfcc/test/typelinker.h | 3 +++ tools/qfcc/test/typelinker_a.r | 7 +++++++ tools/qfcc/test/typelinker_b.r | 3 +++ 4 files changed, 23 insertions(+) create mode 100644 tools/qfcc/test/typelinker.h create mode 100644 tools/qfcc/test/typelinker_a.r create mode 100644 tools/qfcc/test/typelinker_b.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index d43706b9b..fe61451b9 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -69,6 +69,7 @@ test_progs_dat=\ swap.dat \ triangle.dat \ typedef.dat \ + typelinker.dat \ vecaddr.dat \ vecexpr.dat \ vecinit.dat \ @@ -471,6 +472,15 @@ typedef.run: Makefile build-run include ./$(DEPDIR)/typedef.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/typedef.Qo +typelinker_dat_SOURCES=typelinker_a.r typelinker_b.r +typelinker_obj=$(typelinker_dat_SOURCES:.r=.qfo) +typelinker.dat$(EXEEXT): $(typelinker_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(typelinker_obj) +typelinker.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/typelinker.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/typelinker.Qo + vecaddr_dat_SOURCES=vecaddr.r vecaddr_obj=$(vecaddr_dat_SOURCES:.r=.qfo) vecaddr.dat$(EXEEXT): $(vecaddr_obj) $(QFCC_DEP) diff --git a/tools/qfcc/test/typelinker.h b/tools/qfcc/test/typelinker.h new file mode 100644 index 000000000..1968a52cc --- /dev/null +++ b/tools/qfcc/test/typelinker.h @@ -0,0 +1,3 @@ +typedef struct plitem_s *plitem_t; + +@extern plitem_t PL_GetPropertyList (string str); diff --git a/tools/qfcc/test/typelinker_a.r b/tools/qfcc/test/typelinker_a.r new file mode 100644 index 000000000..57c98ca76 --- /dev/null +++ b/tools/qfcc/test/typelinker_a.r @@ -0,0 +1,7 @@ +#include "typelinker.h" + +int main () +{ + PL_GetPropertyList ("{}"); + return 0; +} diff --git a/tools/qfcc/test/typelinker_b.r b/tools/qfcc/test/typelinker_b.r new file mode 100644 index 000000000..54336eae3 --- /dev/null +++ b/tools/qfcc/test/typelinker_b.r @@ -0,0 +1,3 @@ +#include "typelinker.h" + +plitem_t PL_GetPropertyList (string str) = #0; From 6f871a8af9a641f58b4fe407771e1f71a8117ac5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 Mar 2020 00:58:02 +0900 Subject: [PATCH 0949/3664] [qfcc] Unalias def types before checking This fixes the typelinker test, but not the linking error in ruamoko/game that it was supposed to represent. I guess there's something more going on (maybe type encoding relocation issues). --- tools/qfcc/source/linker.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 017461de0..ce708375e 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -282,6 +282,8 @@ alloc_data (int space, int size) static void resolve_external_def (defref_t *ext, defref_t *def) { + qfot_type_t *ext_type; + qfot_type_t *def_type; if (!(REF (ext)->flags & QFOD_EXTERNAL)) { def_error (REF (ext), "%s %x", WORKSTR (REF (ext)->name), REF (ext)->flags); @@ -292,7 +294,15 @@ resolve_external_def (defref_t *ext, defref_t *def) REF (def)->flags); linker_internal_error ("def is an external or local def"); } - if (REF (ext)->type != REF (def)->type) { + ext_type = WORKTYPE (REF(ext)->type); + if (ext_type->meta == ty_alias) { + ext_type = WORKTYPE (ext_type->t.alias.aux_type); + } + def_type = WORKTYPE (REF (def)->type); + if (def_type->meta == ty_alias) { + def_type = WORKTYPE (def_type->t.alias.aux_type); + } + if (ext_type != def_type) { linker_type_mismatch (REF (ext), REF (def)); return; } From 78962cb205cf5d36b7f58e795b736ae4ecd9005b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 Mar 2020 10:27:16 +0900 Subject: [PATCH 0950/3664] [qwaq] Use append_type in field/pointer/array_type This fixes the missing alias chain splitter, allowing scheme to compile again. --- tools/qfcc/source/type.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 08a02855b..dab0b844e 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -453,9 +453,9 @@ field_type (type_t *aux) new = new_type (); new->type = ev_field; new->alignment = 1; - new->t.fldptr.type = aux; - if (aux) - new = find_type (new); + if (aux) { + new = find_type (append_type (new, aux)); + } return new; } @@ -471,9 +471,9 @@ pointer_type (type_t *aux) new = new_type (); new->type = ev_pointer; new->alignment = 1; - new->t.fldptr.type = aux; - if (aux) - new = find_type (new); + if (aux) { + new = find_type (append_type (new, aux)); + } return new; } @@ -487,15 +487,15 @@ array_type (type_t *aux, int size) memset (&_new, 0, sizeof (_new)); else new = new_type (); + new->meta = ty_array; new->type = ev_invalid; if (aux) { new->alignment = aux->alignment; } - new->meta = ty_array; - new->t.array.type = aux; new->t.array.size = size; - if (aux) - new = find_type (new); + if (aux) { + new = find_type (append_type (new, aux)); + } return new; } From 218cca71b8929142a5ee49f026f59b3ddf779e6e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 Mar 2020 11:29:15 +0900 Subject: [PATCH 0951/3664] [qfcc] Take special care when aliasing aliased types When aliasing a type that already has aliases, the top node needs to be replaced if it is unnamed, or the alias-free branch of the new node needs to reach around to the alias-free branch of the existing node. This fixes the bogus param counts in qwaq. --- tools/qfcc/source/expr.c | 3 ++- tools/qfcc/source/type.c | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 6bbc7b742..058292b1d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -248,7 +248,8 @@ get_type (expr_t *e) type = e->e.symbol->type; break; case ex_temp: - return e->e.temp.type; + type = e->e.temp.type; + break; case ex_value: type = e->e.value->type; break; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index dab0b844e..8e34a910e 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -529,6 +529,16 @@ alias_type (type_t *type, type_t *alias_chain, const char *name) alias->meta = ty_alias; alias->type = type->type; alias->alignment = type->alignment; + if (type == alias_chain && type->meta == ty_alias) { + // typedef of a type that contains a typedef somewhere + // grab the alias-free branch for type + type = alias_chain->t.alias.aux_type; + if (!alias_chain->name) { + // the other typedef is further inside, so replace the unnamed + // alias node with the typedef + alias_chain = alias_chain->t.alias.full_type; + } + } alias->t.alias.aux_type = type; alias->t.alias.full_type = alias_chain; if (name) { From 361b3ff422bfa880f27d7152d21aa9552ba54390 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 Mar 2020 11:49:07 +0900 Subject: [PATCH 0952/3664] [qfcc] Treat alias nodes in alias-free branch as ICE --- tools/qfcc/source/type.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 8e34a910e..753ccae10 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -551,7 +551,10 @@ const type_t * unalias_type (const type_t *type) { if (type->meta == ty_alias) { - return type->t.alias.aux_type; + type = type->t.alias.aux_type; + if (type->meta == ty_alias) { + internal_error (0, "alias type node in alias-free chain"); + } } return type; } From 62b6e95746773d620b9bdf9119bfa036f9a88299 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 Mar 2020 14:40:15 +0900 Subject: [PATCH 0953/3664] [qfcc] Show a marker at first unbound reloc --- tools/qfcc/source/dump_globals.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index ab15b0c4d..86a9c1525 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -344,6 +344,9 @@ qfo_relocs (qfo_t *qfo) unsigned i; for (i = 0; i < qfo->num_relocs; i++) { + if (i == qfo->num_relocs - qfo->num_loose_relocs) { + printf ("---- unbound relocs ----\n"); + } reloc = qfo->relocs + i; if ((unsigned) reloc->type > rel_def_field_ofs) { printf ("%d unknown reloc: %d\n", i, reloc->type); From c6d5ceab0e431493f773f23134dfa2ca746c5c79 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 Mar 2020 16:26:36 +0900 Subject: [PATCH 0954/3664] [qfcc] Make things clearer about relocated types I was very uncertain about the validity of messing with the old type encoding that way, but adding the check to ensure the type has been processed never fired, so it seems ok. And the comments help me a lot :) --- tools/qfcc/source/linker.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index ce708375e..951a0b8df 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -495,8 +495,20 @@ add_defs (qfo_t *qfo, qfo_mspace_t *space, qfo_mspace_t *dest_space, odef->file = linker_add_string (QFOSTR (qfo, idef->file)); idef->file = -1; // mark def as copied idef->line = num_work_defrefs; // so def can be found + // In the first passs, process_type_def sets the type meta to -1 and + // class to the offset of the copied type, but the null type encodiing + // is not modified. Other defs are processed in the second pass. type = QFOTYPE(idef->type); + if (idef->type && (int) type->meta != -1) { + linker_internal_error ("reference to type that has not been " + "relocated"); + } + // Type encodings have no type (type = 0) so setting the type + // to the idef type class has no effect. odef->type = type->t.class; // pointer to type in work + // don't add unused (no attached relocs) external defs to the work + // defref list so they will not cause unused object files to be + // pulled in from libraries if (odef->flags & QFOD_EXTERNAL && !odef->num_relocs) continue; ref = get_defref (odef, dest_space); From 188a1ea105bd713c859bdfa8bbd3eca9e0a2c030 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 Mar 2020 18:18:27 +0900 Subject: [PATCH 0955/3664] [qfcc] Add more comments to the linker It's a horribly hairy beast to understand, especially anything to do with relocs and type encodings. --- tools/qfcc/source/linker.c | 39 +++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 951a0b8df..e5c019e32 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -418,10 +418,13 @@ process_type_def (defref_t *ref, qfo_mspace_t *space, qfo_def_t *old) memcpy (new_type, old_type, old_type->size * sizeof (pr_type_t)); define_def (ref, extern_type_defs, defined_type_defs); } - // save the new address in the old def's type field so relocation - // records can be updated. + // Save the new address in the old def's type field so relocation + // records can be updated. Type encoding defs start with no type + // (type = 0). The old def's offset is not modified because it is used + // for finding the def when adjusting relocation records that point + // to fields inside the type encoding. old->type = REF (ref)->offset; - // mark the old type encoding as having been transfered, and save the + // Mark the old type encoding as having been transfered, and save the // new address in the encoding's class field so def and function types // can be updated easily. old_type->meta = -1; @@ -456,6 +459,8 @@ add_relocs (qfo_t *qfo, int start, int count, int target) oreloc = work->relocs + work->num_relocs; for ( ; work->num_relocs < size; ireloc++, oreloc++) { *oreloc = *ireloc; + // Mark the reloc as having been copied and record the new reloc record + // number in the old reloc's offset ireloc->type = -1; ireloc->offset = work->num_relocs++; if (oreloc->space >= qfo->num_spaces) { @@ -814,15 +819,22 @@ update_type_space_reloc (qfo_mspace_t *space, qfo_reloc_t *reloc) qfo_def_t dummy; qfo_def_t *def; - if (reloc->type == -1) + if (reloc->type == -1) { + // The reloc has been copied, and the record number of the new reloc + // is in the old reloc's offset. reloc = work->relocs + reloc->offset; + } dummy.offset = reloc->offset; def = (qfo_def_t *) bsearch (&dummy, space->defs, space->num_defs, sizeof (qfo_def_t), type_def_compare); - if (!def) + if (!def) { linker_internal_error ("relocation record with invalid address. " "corrupt object file?"); - reloc->offset += def->type - def->offset; + } + // The new offset of the type encoding is stored in the def's type field. + // The old offset is in the def's offset field. The reloc's offset points + // to somewhere within the type encoding. + reloc->offset = def->type + (reloc->offset - def->offset); } static int @@ -838,14 +850,15 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass) } qfo_type_defs = space; add_defs (qfo, space, work->spaces + qfo_type_space, process_type_def); - // the defs in qfo are no longer needed by the rest of the linker, so - // we're free to mess around with them + // The defs in qfo are no longer needed by the rest of the linker, so + // we're free to mess around with them. - // sort the defs by addres. Unfortunately, they will usually be in order, - // so qsort will likely be pessimistic, but oh well. + // Sort the defs by addres so they can found using bsearch when adjusting + // the targets of type encoding relocs. Unfortunately, they will usually + // be in order, so qsort will likely be pessimistic, but oh well. qsort (space->defs, space->num_defs, sizeof (qfo_def_t), type_def_compare); - // update the offsets of all relocation records that point into the type + // Update the offsets of all relocation records that point into the type // encoding space. for (i = 0; i < qfo->num_relocs; i++) { qfo_reloc_t *reloc = qfo->relocs + i; @@ -853,8 +866,8 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass) if (reloc->space != space->id) continue; update_type_space_reloc (space, reloc); - // while we're at it, update the strings so the type space strings - // are always correct. + // while we're at it, relocate all references in the type encoding + // space so the type encodings are always correct. if (reloc->type == rel_def_string) { string_t str; str = linker_add_string (QFOSTR (qfo, reloc->target)); From d4de1d741881cd6487d03d3655e667a5dabdcc8a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 Mar 2020 18:19:36 +0900 Subject: [PATCH 0956/3664] [qfcc] Do full type encoding relocation early Because type aliases need to be unaliased, the type pointers in the type encodings need to be correct when it comes to linking defs and functions. This fixes the linking errors in ruamoko/game. --- tools/qfcc/source/linker.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index e5c019e32..14d963b73 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -872,6 +872,20 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass) string_t str; str = linker_add_string (QFOSTR (qfo, reloc->target)); QFO_STRING (work, reloc->space, reloc->offset) = str; + } else if (reloc->type == rel_def_def || reloc->type == -1) { + qfo_def_t *def; + if (reloc->type == -1) { + // The reloc has been copied, and the record number of the new + // reloc is in the old reloc's offset. + reloc = work->relocs + reloc->offset; + } + if (reloc->target >= work->spaces[reloc->space].num_defs) { + linker_error ("Invalid reloc target def %d / %d.\n", + reloc->target, qfo->num_defs); + continue; + } + def = work->spaces[reloc->space].defs + reloc->target; + QFO_INT (work, reloc->space, reloc->offset) = def->offset; } } for (i = 0; i < num_builtins; i++) { @@ -1316,22 +1330,6 @@ build_qfo (void) reloc++; } } - for (i = 0; i < qfo->num_relocs; i++) { - qfo_def_t *def; - - reloc = qfo->relocs + i; - if (reloc->space != qfo_type_space) - continue; - if (reloc->type != rel_def_def) - continue; - if (reloc->target >= qfo->num_defs) { - linker_error ("Invalid reloc target def %d / %d.\n", - reloc->target, qfo->num_defs); - continue; - } - def = qfo->defs + reloc->target; - QFO_INT (qfo, reloc->space, reloc->offset) = def->offset; - } return qfo; } From 4c5ab07347c3bd72558386a02218451f4c8116cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 00:58:25 +0900 Subject: [PATCH 0957/3664] [qwaq] Remove obsolete screen class --- ruamoko/qwaq/qwaq-screen.h | 15 ------------- ruamoko/qwaq/qwaq-screen.r | 43 -------------------------------------- 2 files changed, 58 deletions(-) delete mode 100644 ruamoko/qwaq/qwaq-screen.h delete mode 100644 ruamoko/qwaq/qwaq-screen.r diff --git a/ruamoko/qwaq/qwaq-screen.h b/ruamoko/qwaq/qwaq-screen.h deleted file mode 100644 index 9ec2ba8f3..000000000 --- a/ruamoko/qwaq/qwaq-screen.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __qwaq_screen_h -#define __qwaq_screen_h - -#include "qwaq-draw.h" -#include "qwaq-rect.h" -#include "qwaq-view.h" - -@interface Screen: View -{ -} -+(Screen *) screen; --handleEvent: (qwaq_event_t *) event; -@end - -#endif//__qwaq_screen_h diff --git a/ruamoko/qwaq/qwaq-screen.r b/ruamoko/qwaq/qwaq-screen.r deleted file mode 100644 index b6149db25..000000000 --- a/ruamoko/qwaq/qwaq-screen.r +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include "qwaq-curses.h" -#include "qwaq-screen.h" - -@implementation Screen -+(Screen *) screen -{ - return [[[self alloc] init] autorelease]; -} - --init -{ - if (!(self = [super initWithRect:getwrect (stdscr)])) { - return nil; - } - textContext = [TextContext screen]; - [(id)textContext scrollok: 1]; - return self; -} - --handleEvent: (qwaq_event_t *) event -{ - if (event.what & qe_mouse) { - [self printf:"%04x %2d %2d %d %08x \r", event.what, event.mouse.x, event.mouse.y, event.mouse.click, event.mouse.buttons]; - [self redraw]; - } - return self; -} - --draw -{ - return self; -} - --redraw -{ - //update_panels (); - [TextContext refresh]; - //[TextContext doupdate]; - return self; -} - -@end From 6ff5b5c101467b16c042caab6f2ad08fd7b2d269 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 02:34:08 +0900 Subject: [PATCH 0958/3664] [qwaq] Clean up the qwaq directory Things were getting rather cluttered with everything being qwaq-* and all in one directory. Now most have lost the qwaq- prefix and have been moved into subdirectories (non-recursive make). --- ruamoko/qwaq/Makefile.am | 55 ++++++++++--------- ruamoko/qwaq/{ => builtins}/builtins.c | 0 .../qwaq/{qwaq-curses.c => builtins/curses.c} | 8 +-- .../qwaq/{qwaq-debug.c => builtins/debug.c} | 8 +-- .../editbuffer.c} | 2 +- .../qwaq/{qwaq-input.c => builtins/input.c} | 6 +- ruamoko/qwaq/{ => builtins}/main.c | 2 +- ruamoko/qwaq/{ => builtins}/qwaq-bi.c | 0 ruamoko/qwaq/{ => builtins}/qwaq.c | 0 .../qwaq/{qwaq-debug.h => debugger/debug.h} | 8 +-- .../{qwaq-debugger.h => debugger/debugger.h} | 8 +-- .../{qwaq-debugger.r => debugger/debugger.r} | 13 +++-- .../editbuffer.h} | 6 +- .../editbuffer.r} | 2 +- .../qwaq/{qwaq-editor.h => editor/editor.h} | 10 ++-- .../qwaq/{qwaq-editor.r => editor/editor.r} | 4 +- ruamoko/qwaq/progs.src.in | 16 ------ ruamoko/qwaq/qwaq-app.h | 4 +- ruamoko/qwaq/qwaq-app.r | 10 ++-- ruamoko/qwaq/{qwaq-button.h => ui/button.h} | 10 ++-- ruamoko/qwaq/{qwaq-button.r => ui/button.r} | 4 +- ruamoko/qwaq/{ => ui}/color.h | 6 +- ruamoko/qwaq/{qwaq-curses.h => ui/curses.h} | 10 ++-- ruamoko/qwaq/{qwaq-draw.h => ui/draw.h} | 8 +-- ruamoko/qwaq/{qwaq-draw.r => ui/draw.r} | 4 +- ruamoko/qwaq/{ => ui}/event.h | 6 +- ruamoko/qwaq/{qwaq-garray.h => ui/garray.h} | 6 +- ruamoko/qwaq/{qwaq-garray.r => ui/garray.r} | 4 +- ruamoko/qwaq/{qwaq-group.h => ui/group.h} | 10 ++-- ruamoko/qwaq/{qwaq-group.r => ui/group.r} | 10 ++-- .../qwaq/{qwaq-listener.h => ui/listener.h} | 6 +- .../qwaq/{qwaq-listener.r => ui/listener.r} | 2 +- .../qwaq/{qwaq-proxyview.h => ui/proxyview.h} | 8 +-- .../qwaq/{qwaq-proxyview.r => ui/proxyview.r} | 4 +- ruamoko/qwaq/{qwaq-rect.h => ui/rect.h} | 6 +- ruamoko/qwaq/{qwaq-rect.r => ui/rect.r} | 2 +- .../{qwaq-textcontext.h => ui/textcontext.h} | 12 ++-- .../{qwaq-textcontext.r => ui/textcontext.r} | 4 +- .../qwaq/{qwaq-titlebar.h => ui/titlebar.h} | 8 +-- .../qwaq/{qwaq-titlebar.r => ui/titlebar.r} | 4 +- ruamoko/qwaq/{qwaq-view.h => ui/view.h} | 12 ++-- ruamoko/qwaq/{qwaq-view.r => ui/view.r} | 8 +-- ruamoko/qwaq/{qwaq-window.h => ui/window.h} | 12 ++-- ruamoko/qwaq/{qwaq-window.r => ui/window.r} | 16 +++--- 44 files changed, 167 insertions(+), 177 deletions(-) rename ruamoko/qwaq/{ => builtins}/builtins.c (100%) rename ruamoko/qwaq/{qwaq-curses.c => builtins/curses.c} (99%) rename ruamoko/qwaq/{qwaq-debug.c => builtins/debug.c} (99%) rename ruamoko/qwaq/{qwaq-editbuffer-bi.c => builtins/editbuffer.c} (99%) rename ruamoko/qwaq/{qwaq-input.c => builtins/input.c} (99%) rename ruamoko/qwaq/{ => builtins}/main.c (99%) rename ruamoko/qwaq/{ => builtins}/qwaq-bi.c (100%) rename ruamoko/qwaq/{ => builtins}/qwaq.c (100%) rename ruamoko/qwaq/{qwaq-debug.h => debugger/debug.h} (94%) rename ruamoko/qwaq/{qwaq-debugger.h => debugger/debugger.h} (79%) rename ruamoko/qwaq/{qwaq-debugger.r => debugger/debugger.r} (97%) rename ruamoko/qwaq/{qwaq-editbuffer.h => editor/editbuffer.h} (94%) rename ruamoko/qwaq/{qwaq-editbuffer.r => editor/editbuffer.r} (98%) rename ruamoko/qwaq/{qwaq-editor.h => editor/editor.h} (83%) rename ruamoko/qwaq/{qwaq-editor.r => editor/editor.r} (98%) delete mode 100644 ruamoko/qwaq/progs.src.in rename ruamoko/qwaq/{qwaq-button.h => ui/button.h} (84%) rename ruamoko/qwaq/{qwaq-button.r => ui/button.r} (98%) rename ruamoko/qwaq/{ => ui}/color.h (81%) rename ruamoko/qwaq/{qwaq-curses.h => ui/curses.h} (97%) rename ruamoko/qwaq/{qwaq-draw.h => ui/draw.h} (91%) rename ruamoko/qwaq/{qwaq-draw.r => ui/draw.r} (98%) rename ruamoko/qwaq/{ => ui}/event.h (95%) rename ruamoko/qwaq/{qwaq-garray.h => ui/garray.h} (91%) rename ruamoko/qwaq/{qwaq-garray.r => ui/garray.r} (97%) rename ruamoko/qwaq/{qwaq-group.h => ui/group.h} (85%) rename ruamoko/qwaq/{qwaq-group.r => ui/group.r} (97%) rename ruamoko/qwaq/{qwaq-listener.h => ui/listener.h} (87%) rename ruamoko/qwaq/{qwaq-listener.r => ui/listener.r} (98%) rename ruamoko/qwaq/{qwaq-proxyview.h => ui/proxyview.h} (64%) rename ruamoko/qwaq/{qwaq-proxyview.r => ui/proxyview.r} (92%) rename ruamoko/qwaq/{qwaq-rect.h => ui/rect.h} (87%) rename ruamoko/qwaq/{qwaq-rect.r => ui/rect.r} (98%) rename ruamoko/qwaq/{qwaq-textcontext.h => ui/textcontext.h} (89%) rename ruamoko/qwaq/{qwaq-textcontext.r => ui/textcontext.r} (98%) rename ruamoko/qwaq/{qwaq-titlebar.h => ui/titlebar.h} (62%) rename ruamoko/qwaq/{qwaq-titlebar.r => ui/titlebar.r} (90%) rename ruamoko/qwaq/{qwaq-view.h => ui/view.h} (93%) rename ruamoko/qwaq/{qwaq-view.r => ui/view.r} (98%) rename ruamoko/qwaq/{qwaq-window.h => ui/window.h} (81%) rename ruamoko/qwaq/{qwaq-window.r => ui/window.r} (97%) diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index b615f11ba..5bb8f0761 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -1,18 +1,20 @@ -AUTOMAKE_OPTIONS= foreign +AUTOMAKE_OPTIONS= foreign subdir-objects QWAQ_LIBS=@QWAQ_LIBS@ QWAQ_DEPS=@QWAQ_DEPS@ QWAQ_INCS=@QWAQ_INCS@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(QWAQ_INCS) $(PTHREAD_CFLAGS) +AM_CPPFLAGS= -I$(srcdir) -I$(top_srcdir)/include $(QWAQ_INCS) $(PTHREAD_CFLAGS) noinst_PROGRAMS=@QWAQ_TARGETS@ qwaq-app.dat$(EXEEXT) gcd.dat$(EXEEXT) QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) QFCC=$(top_builddir)/tools/qfcc/source/qfcc +QCSYSTEM=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +QWAQ_INC=-I$(srcdir) -I$(srcdir)/builtins -I$(srcdir)/debugger -I$(srcdir)/editor -I$(srcdir)/ui QCFLAGS=-qq -O -g -Werror -QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +QCPPFLAGS=$(QCSYSTEM) -I$(srcdir) QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) @@ -24,34 +26,37 @@ SUFFIXES=.o .r @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo qwaq_app_dat_src= \ - qwaq-app.r \ - qwaq-button.r \ - qwaq-debugger.r \ - qwaq-draw.r \ - qwaq-editbuffer.r \ - qwaq-editor.r \ - qwaq-garray.r \ - qwaq-group.r \ - qwaq-listener.r \ - qwaq-proxyview.r \ - qwaq-rect.r \ - qwaq-screen.r \ - qwaq-textcontext.r \ - qwaq-titlebar.r \ - qwaq-view.r \ - qwaq-window.r + qwaq-app.r \ + debugger/debugger.r \ + editor/editbuffer.r \ + editor/editor.r \ + ui/button.r \ + ui/draw.r \ + ui/garray.r \ + ui/group.r \ + ui/listener.r \ + ui/proxyview.r \ + ui/rect.r \ + ui/textcontext.r \ + ui/titlebar.r \ + ui/view.r \ + ui/window.r \ + $e #FIXME this coupling is horrible qwaq_curses_libs= \ $(top_builddir)/libs/video/targets/libvid_common.la \ $(top_builddir)/libs/console/libQFconsole.la \ $(top_builddir)/libs/gib/libQFgib.la + qwaq_curses_SOURCES= \ - main.c \ - qwaq-curses.c \ - qwaq-debug.c \ - qwaq-editbuffer-bi.c \ - qwaq-input.c + builtins/main.c \ + builtins/curses.c \ + builtins/debug.c \ + builtins/editbuffer.c \ + builtins/input.c \ + $e + qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ $(PANEL_LIBS) $(CURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) qwaq_curses_LDFLAGS= @@ -74,7 +79,7 @@ qwaq_x11_libs= \ $(top_builddir)/libs/video/targets/libQFx11.la \ $(client_libs) \ $(top_builddir)/libs/gib/libQFgib.la -qwaq_x11_SOURCES=qwaq.c qwaq-bi.c +qwaq_x11_SOURCES=builtins/qwaq.c builtins/qwaq-bi.c qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \ $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ $(X_EXTRA_LIBS) $(X_SHM_LIB) $(DL_LIBS) diff --git a/ruamoko/qwaq/builtins.c b/ruamoko/qwaq/builtins/builtins.c similarity index 100% rename from ruamoko/qwaq/builtins.c rename to ruamoko/qwaq/builtins/builtins.c diff --git a/ruamoko/qwaq/qwaq-curses.c b/ruamoko/qwaq/builtins/curses.c similarity index 99% rename from ruamoko/qwaq/qwaq-curses.c rename to ruamoko/qwaq/builtins/curses.c index 26a17b37b..f4db018a0 100644 --- a/ruamoko/qwaq/qwaq-curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -1,5 +1,5 @@ /* - qwaq-curses.c + curses.c Ruamoko ncurses wrapper using threading @@ -47,9 +47,9 @@ #include "QF/sys.h" #include "qwaq.h" -#include "qwaq-curses.h" -#include "qwaq-rect.h" -#include "qwaq-textcontext.h" +#include "ui/curses.h" +#include "ui/rect.h" +#include "ui/textcontext.h" #define always_inline inline __attribute__((__always_inline__)) #define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) diff --git a/ruamoko/qwaq/qwaq-debug.c b/ruamoko/qwaq/builtins/debug.c similarity index 99% rename from ruamoko/qwaq/qwaq-debug.c rename to ruamoko/qwaq/builtins/debug.c index 4938d8211..c1835f99d 100644 --- a/ruamoko/qwaq/qwaq-debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -1,5 +1,5 @@ /* - qwaq-debug.c + debug.c Debugging support @@ -47,9 +47,9 @@ #include "QF/sys.h" #include "qwaq.h" -#include "event.h" -#include "qwaq-curses.h" -#include "qwaq-debug.h" +#include "ui/event.h" +#include "ui/curses.h" +#include "debugger/debug.h" typedef struct qwaq_target_s { progs_t *pr; diff --git a/ruamoko/qwaq/qwaq-editbuffer-bi.c b/ruamoko/qwaq/builtins/editbuffer.c similarity index 99% rename from ruamoko/qwaq/qwaq-editbuffer-bi.c rename to ruamoko/qwaq/builtins/editbuffer.c index 9f457bf10..f834f258c 100644 --- a/ruamoko/qwaq/qwaq-editbuffer-bi.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -11,7 +11,7 @@ #include "QF/txtbuffer.h" #include "qwaq.h" -#include "qwaq-editbuffer.h" +#include "editor/editbuffer.h" #define always_inline inline __attribute__((__always_inline__)) diff --git a/ruamoko/qwaq/qwaq-input.c b/ruamoko/qwaq/builtins/input.c similarity index 99% rename from ruamoko/qwaq/qwaq-input.c rename to ruamoko/qwaq/builtins/input.c index 543971d44..29d5a6088 100644 --- a/ruamoko/qwaq/qwaq-input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -1,5 +1,5 @@ /* - qwaq-input.c + input.c Input handling @@ -47,8 +47,8 @@ #include "QF/sys.h" #include "qwaq.h" -#include "event.h" -#include "qwaq-curses.h" +#include "ui/event.h" +#include "ui/curses.h" #define always_inline inline __attribute__((__always_inline__)) diff --git a/ruamoko/qwaq/main.c b/ruamoko/qwaq/builtins/main.c similarity index 99% rename from ruamoko/qwaq/main.c rename to ruamoko/qwaq/builtins/main.c index bbd66bac1..c78a9f9e5 100644 --- a/ruamoko/qwaq/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -53,7 +53,7 @@ #include "QF/zone.h" #include "qwaq.h" -#include "qwaq-debug.h" +#include "debugger/debug.h" #define MAX_EDICTS 1024 diff --git a/ruamoko/qwaq/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c similarity index 100% rename from ruamoko/qwaq/qwaq-bi.c rename to ruamoko/qwaq/builtins/qwaq-bi.c diff --git a/ruamoko/qwaq/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c similarity index 100% rename from ruamoko/qwaq/qwaq.c rename to ruamoko/qwaq/builtins/qwaq.c diff --git a/ruamoko/qwaq/qwaq-debug.h b/ruamoko/qwaq/debugger/debug.h similarity index 94% rename from ruamoko/qwaq/qwaq-debug.h rename to ruamoko/qwaq/debugger/debug.h index b233f2b07..74ebf1c39 100644 --- a/ruamoko/qwaq/qwaq-debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -1,7 +1,7 @@ -#ifndef __qwaq_debug_h -#define __qwaq_debug_h +#ifndef __qwaq_debugger_debug_h +#define __qwaq_debugger_debug_h -#include "event.h" +#include "ui/event.h" typedef enum { qe_debug_event = 0x0100, @@ -82,4 +82,4 @@ void QWAQ_DebugTarget_Init (progs_t *pr); #endif -#endif//__qwaq_debug_h +#endif//__qwaq_debugger_debug_h diff --git a/ruamoko/qwaq/qwaq-debugger.h b/ruamoko/qwaq/debugger/debugger.h similarity index 79% rename from ruamoko/qwaq/qwaq-debugger.h rename to ruamoko/qwaq/debugger/debugger.h index 513ae211b..2fc402291 100644 --- a/ruamoko/qwaq/qwaq-debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -1,9 +1,9 @@ -#ifndef __qwaq_debugger_h -#define __qwaq_debugger_h +#ifndef __qwaq_debugger_debugger_h +#define __qwaq_debugger_debugger_h #include -#include "qwaq-debug.h" +#include "debugger/debug.h" @class ProxyView; @class Editor; @@ -33,4 +33,4 @@ -handleDebugEvent; @end -#endif//__qwaq_debugger_h +#endif//__qwaq_debugger_debugger_h diff --git a/ruamoko/qwaq/qwaq-debugger.r b/ruamoko/qwaq/debugger/debugger.r similarity index 97% rename from ruamoko/qwaq/qwaq-debugger.r rename to ruamoko/qwaq/debugger/debugger.r index a15b6c7de..dde372e36 100644 --- a/ruamoko/qwaq/qwaq-debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -3,13 +3,13 @@ #include #include +#include "ui/curses.h" +#include "ui/listener.h" +#include "ui/proxyview.h" +#include "ui/window.h" +#include "debugger/debugger.h" +#include "editor/editor.h" #include "qwaq-app.h" -#include "qwaq-curses.h" -#include "qwaq-debugger.h" -#include "qwaq-editor.h" -#include "qwaq-listener.h" -#include "qwaq-proxyview.h" -#include "qwaq-window.h" @implementation Debugger -(qdb_target_t)debug_target @@ -66,6 +66,7 @@ [locals_window setTitle: "Locals"]; locals_view = [[View alloc] initWithRect: {{1, 1}, {38, 8}} options: ofCanFocus]; + [locals_view setGrowMode:gfGrowHi]; [locals_window insertSelected: locals_view]; [application addView: locals_window]; diff --git a/ruamoko/qwaq/qwaq-editbuffer.h b/ruamoko/qwaq/editor/editbuffer.h similarity index 94% rename from ruamoko/qwaq/qwaq-editbuffer.h rename to ruamoko/qwaq/editor/editbuffer.h index 67976d244..72ee9db65 100644 --- a/ruamoko/qwaq/qwaq-editbuffer.h +++ b/ruamoko/qwaq/editor/editbuffer.h @@ -1,5 +1,5 @@ -#ifndef __qwaq_editbuffer_h -#define __qwaq_editbuffer_h +#ifndef __qwaq_editor_editbuffer_h +#define __qwaq_editor_editbuffer_h #ifdef __QFCC__ #include @@ -79,4 +79,4 @@ typedef struct qwaq_editbuffer_s { #endif//!__QFCC__ -#endif//__qwaq_editbuffer_h +#endif//__qwaq_editor_editbuffer_h diff --git a/ruamoko/qwaq/qwaq-editbuffer.r b/ruamoko/qwaq/editor/editbuffer.r similarity index 98% rename from ruamoko/qwaq/qwaq-editbuffer.r rename to ruamoko/qwaq/editor/editbuffer.r index d0900a108..2d58e0361 100644 --- a/ruamoko/qwaq/qwaq-editbuffer.r +++ b/ruamoko/qwaq/editor/editbuffer.r @@ -1,4 +1,4 @@ -#include "qwaq-editbuffer.h" +#include "editor/editbuffer.h" @implementation EditBuffer - init = #0; diff --git a/ruamoko/qwaq/qwaq-editor.h b/ruamoko/qwaq/editor/editor.h similarity index 83% rename from ruamoko/qwaq/qwaq-editor.h rename to ruamoko/qwaq/editor/editor.h index 01ef35f30..099ae78a3 100644 --- a/ruamoko/qwaq/qwaq-editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -1,8 +1,8 @@ -#ifndef __qwaq_editor_h -#define __qwaq_editor_h +#ifndef __qwaq_editor_editor_h +#define __qwaq_editor_editor_h -#include "qwaq-editbuffer.h" -#include "qwaq-view.h" +#include "editor/editbuffer.h" +#include "ui/view.h" @class Editor; @class EditBuffer; @@ -35,4 +35,4 @@ -(string)getWordAt:(Point) pos; // view relative coordinates @end -#endif//__qwaq_editor_h +#endif//__qwaq_editor_editor_h diff --git a/ruamoko/qwaq/qwaq-editor.r b/ruamoko/qwaq/editor/editor.r similarity index 98% rename from ruamoko/qwaq/qwaq-editor.r rename to ruamoko/qwaq/editor/editor.r index f45de395f..f6f78d575 100644 --- a/ruamoko/qwaq/qwaq-editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -1,7 +1,7 @@ #include #include "qwaq-app.h" -#include "qwaq-editor.h" -#include "qwaq-listener.h" +#include "editor/editor.h" +#include "ui/listener.h" @implementation Editor diff --git a/ruamoko/qwaq/progs.src.in b/ruamoko/qwaq/progs.src.in deleted file mode 100644 index c6d4f7070..000000000 --- a/ruamoko/qwaq/progs.src.in +++ /dev/null @@ -1,16 +0,0 @@ -qwaq.dat - -@srcdir@/defs.qc - -@top_srcdir@/ruamoko/lib/plist.r -@top_srcdir@/ruamoko/lib/qfile.r -@top_srcdir@/ruamoko/lib/script.r -@top_srcdir@/ruamoko/lib/string.r -@top_srcdir@/ruamoko/lib/Object.r -@top_srcdir@/ruamoko/lib/Protocol.r -@top_srcdir@/ruamoko/lib/Array.r -@top_srcdir@/ruamoko/lib/Array+Private.r -@top_srcdir@/ruamoko/lib/AutoreleasePool.r -@srcdir@/test.r -@srcdir@/types.r -@srcdir@/main.qc diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index c88d79cec..bf6255740 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -3,8 +3,8 @@ #include -#include "event.h" -#include "qwaq-rect.h" +#include "ui/event.h" +#include "ui/rect.h" @class Array; @class Group; diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 19c9740c1..19daf643a 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -3,12 +3,12 @@ int fence; #include #include -#include "color.h" +#include "ui/color.h" +#include "ui/curses.h" +#include "ui/group.h" +#include "ui/view.h" +#include "debugger/debugger.h" #include "qwaq-app.h" -#include "qwaq-curses.h" -#include "qwaq-debugger.h" -#include "qwaq-group.h" -#include "qwaq-view.h" int color_palette[64]; diff --git a/ruamoko/qwaq/qwaq-button.h b/ruamoko/qwaq/ui/button.h similarity index 84% rename from ruamoko/qwaq/qwaq-button.h rename to ruamoko/qwaq/ui/button.h index c855505a9..d407fbbff 100644 --- a/ruamoko/qwaq/qwaq-button.h +++ b/ruamoko/qwaq/ui/button.h @@ -1,8 +1,8 @@ -#ifndef __qwaq_button_h -#define __qwaq_button_h +#ifndef __qwaq_ui_button_h +#define __qwaq_ui_button_h -#include "qwaq-draw.h" -#include "qwaq-view.h" +#include "ui/draw.h" +#include "ui/view.h" @class ListenerGroup; @@ -34,4 +34,4 @@ - (Point) delta; @end -#endif//__qwaq_button_h +#endif//__qwaq_ui_button_h diff --git a/ruamoko/qwaq/qwaq-button.r b/ruamoko/qwaq/ui/button.r similarity index 98% rename from ruamoko/qwaq/qwaq-button.r rename to ruamoko/qwaq/ui/button.r index a02a738c0..38d0690c4 100644 --- a/ruamoko/qwaq/qwaq-button.r +++ b/ruamoko/qwaq/ui/button.r @@ -1,5 +1,5 @@ -#include "qwaq-button.h" -#include "qwaq-listener.h" +#include "ui/button.h" +#include "ui/listener.h" @implementation Button -initWithPos: (Point) pos releasedIcon: (DrawBuffer *) released diff --git a/ruamoko/qwaq/color.h b/ruamoko/qwaq/ui/color.h similarity index 81% rename from ruamoko/qwaq/color.h rename to ruamoko/qwaq/ui/color.h index 95067b5de..3b5ce2b2a 100644 --- a/ruamoko/qwaq/color.h +++ b/ruamoko/qwaq/ui/color.h @@ -1,5 +1,5 @@ -#ifndef __qwaq_color_h -#define __qwaq_color_h +#ifndef __qwaq_ui_color_h +#define __qwaq_ui_color_h #ifndef COLOR_PAIR // double protection in case this header is included in a C file @@ -18,4 +18,4 @@ #endif -#endif//__qwaq_color_h +#endif//__qwaq_ui_color_h diff --git a/ruamoko/qwaq/qwaq-curses.h b/ruamoko/qwaq/ui/curses.h similarity index 97% rename from ruamoko/qwaq/qwaq-curses.h rename to ruamoko/qwaq/ui/curses.h index 37c9c0712..65143159f 100644 --- a/ruamoko/qwaq/qwaq-curses.h +++ b/ruamoko/qwaq/ui/curses.h @@ -1,7 +1,7 @@ -#ifndef __qwaq_curses_h -#define __qwaq_curses_h +#ifndef __qwaq_ui_curses_h +#define __qwaq_ui_curses_h -#include "event.h" +#include "ui/event.h" typedef struct box_sides_s { int ls; @@ -18,7 +18,7 @@ typedef struct box_corners_s { } box_corners_t; #ifdef __QFCC__ -#include "qwaq-rect.h" +#include "ui/rect.h" // names, order and comments lifted from ncurses.h typedef enum { @@ -205,4 +205,4 @@ int qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event); void qwaq_init_cond (rwcond_t *cond); #endif -#endif//__qwaq_curses_h +#endif//__qwaq_ui_curses_h diff --git a/ruamoko/qwaq/qwaq-draw.h b/ruamoko/qwaq/ui/draw.h similarity index 91% rename from ruamoko/qwaq/qwaq-draw.h rename to ruamoko/qwaq/ui/draw.h index e7eff51ab..72be7fbf0 100644 --- a/ruamoko/qwaq/qwaq-draw.h +++ b/ruamoko/qwaq/ui/draw.h @@ -1,9 +1,9 @@ -#ifndef __qwaq_draw_h -#define __qwaq_draw_h +#ifndef __qwaq_ui_draw_h +#define __qwaq_ui_draw_h #include -#include "qwaq-rect.h" +#include "ui/rect.h" @class DrawBuffer; @@ -43,4 +43,4 @@ - initWithSize: (Extent) size; @end -#endif +#endif//__qwaq_ui_draw_h diff --git a/ruamoko/qwaq/qwaq-draw.r b/ruamoko/qwaq/ui/draw.r similarity index 98% rename from ruamoko/qwaq/qwaq-draw.r rename to ruamoko/qwaq/ui/draw.r index 7d1fbcd58..b9864af6d 100644 --- a/ruamoko/qwaq/qwaq-draw.r +++ b/ruamoko/qwaq/ui/draw.r @@ -1,7 +1,7 @@ #include -#include "qwaq-curses.h" -#include "qwaq-draw.h" +#include "ui/curses.h" +#include "ui/draw.h" @implementation DrawBuffer diff --git a/ruamoko/qwaq/event.h b/ruamoko/qwaq/ui/event.h similarity index 95% rename from ruamoko/qwaq/event.h rename to ruamoko/qwaq/ui/event.h index d11fd195e..d8fe09c6c 100644 --- a/ruamoko/qwaq/event.h +++ b/ruamoko/qwaq/ui/event.h @@ -1,5 +1,5 @@ -#ifndef __qwaq_event_h -#define __qwaq_event_h +#ifndef __qwaq_ui_event_h +#define __qwaq_ui_event_h typedef enum { qe_mousedown = 0x0001, @@ -77,4 +77,4 @@ typedef struct qwaq_event_s { }; } qwaq_event_t; -#endif//__qwaq_event_h +#endif//__qwaq_ui_event_h diff --git a/ruamoko/qwaq/qwaq-garray.h b/ruamoko/qwaq/ui/garray.h similarity index 91% rename from ruamoko/qwaq/qwaq-garray.h rename to ruamoko/qwaq/ui/garray.h index 1a2e53576..3ba1a0ef2 100644 --- a/ruamoko/qwaq/qwaq-garray.h +++ b/ruamoko/qwaq/ui/garray.h @@ -1,5 +1,5 @@ -#ifndef __qwaq_garray_h -#define __qwaq_garray_h +#ifndef __qwaq_ui_garray_h +#define __qwaq_ui_garray_h #include @@ -26,4 +26,4 @@ typedef BOOL condition_func2 (id object, void *anObject, void *data); with: (void *)data; @end -#endif//__qwaq_garray_h +#endif//__qwaq_ui_garray_h diff --git a/ruamoko/qwaq/qwaq-garray.r b/ruamoko/qwaq/ui/garray.r similarity index 97% rename from ruamoko/qwaq/qwaq-garray.r rename to ruamoko/qwaq/ui/garray.r index b3298ffa4..ee6bd0191 100644 --- a/ruamoko/qwaq/qwaq-garray.r +++ b/ruamoko/qwaq/ui/garray.r @@ -1,6 +1,6 @@ #include -#include "event.h" -#include "qwaq-garray.h" +#include "ui/event.h" +#include "ui/garray.h" @implementation Array (Group) - (void) makeObjectsPerformSelector: (SEL)selector diff --git a/ruamoko/qwaq/qwaq-group.h b/ruamoko/qwaq/ui/group.h similarity index 85% rename from ruamoko/qwaq/qwaq-group.h rename to ruamoko/qwaq/ui/group.h index 70e2663a0..b243166b2 100644 --- a/ruamoko/qwaq/qwaq-group.h +++ b/ruamoko/qwaq/ui/group.h @@ -1,10 +1,10 @@ -#ifndef __qwaq_group_h -#define __qwaq_group_h +#ifndef __qwaq_ui_group_h +#define __qwaq_ui_group_h #include -#include "event.h" -#include "qwaq-draw.h" +#include "ui/event.h" +#include "ui/draw.h" @class View; @@ -40,4 +40,4 @@ -(void) releaseMouse; @end -#endif//__qwaq_group_h +#endif//__qwaq_ui_group_h diff --git a/ruamoko/qwaq/qwaq-group.r b/ruamoko/qwaq/ui/group.r similarity index 97% rename from ruamoko/qwaq/qwaq-group.r rename to ruamoko/qwaq/ui/group.r index d94d0585f..aa4fb117e 100644 --- a/ruamoko/qwaq/qwaq-group.r +++ b/ruamoko/qwaq/ui/group.r @@ -1,9 +1,9 @@ #include -#include "event.h" -#include "qwaq-draw.h" -#include "qwaq-garray.h" -#include "qwaq-group.h" -#include "qwaq-view.h" +#include "ui/event.h" +#include "ui/draw.h" +#include "ui/garray.h" +#include "ui/group.h" +#include "ui/view.h" @implementation Group diff --git a/ruamoko/qwaq/qwaq-listener.h b/ruamoko/qwaq/ui/listener.h similarity index 87% rename from ruamoko/qwaq/qwaq-listener.h rename to ruamoko/qwaq/ui/listener.h index 0dd388c2e..e07356ad5 100644 --- a/ruamoko/qwaq/qwaq-listener.h +++ b/ruamoko/qwaq/ui/listener.h @@ -1,5 +1,5 @@ -#ifndef __qwaq_listener_h -#define __qwaq_listener_h +#ifndef __qwaq_ui_listener_h +#define __qwaq_ui_listener_h #include @@ -28,4 +28,4 @@ -(void) respond: (void *) caller_data withObject:(void *)anObject; @end -#endif//__qwaq_listener_h +#endif//__qwaq_ui_listener_h diff --git a/ruamoko/qwaq/qwaq-listener.r b/ruamoko/qwaq/ui/listener.r similarity index 98% rename from ruamoko/qwaq/qwaq-listener.r rename to ruamoko/qwaq/ui/listener.r index 95c27f04c..bdb36ac51 100644 --- a/ruamoko/qwaq/qwaq-listener.r +++ b/ruamoko/qwaq/ui/listener.r @@ -1,6 +1,6 @@ #include -#include "qwaq-listener.h" +#include "ui/listener.h" @class Array; diff --git a/ruamoko/qwaq/qwaq-proxyview.h b/ruamoko/qwaq/ui/proxyview.h similarity index 64% rename from ruamoko/qwaq/qwaq-proxyview.h rename to ruamoko/qwaq/ui/proxyview.h index 449ac5fd6..9a2c23c2e 100644 --- a/ruamoko/qwaq/qwaq-proxyview.h +++ b/ruamoko/qwaq/ui/proxyview.h @@ -1,7 +1,7 @@ -#ifndef __qwaq_proxyview_h -#define __qwaq_proxyview_h +#ifndef __qwaq_ui_proxyview_h +#define __qwaq_ui_proxyview_h -#include "qwaq-view.h" +#include "ui/view.h" @class Group; @@ -17,4 +17,4 @@ @interface ProxyView (View) @end -#endif//__qwaq_proxyview_h +#endif//__qwaq_ui_proxyview_h diff --git a/ruamoko/qwaq/qwaq-proxyview.r b/ruamoko/qwaq/ui/proxyview.r similarity index 92% rename from ruamoko/qwaq/qwaq-proxyview.r rename to ruamoko/qwaq/ui/proxyview.r index b5946eba5..a94c738dc 100644 --- a/ruamoko/qwaq/qwaq-proxyview.r +++ b/ruamoko/qwaq/ui/proxyview.r @@ -1,5 +1,5 @@ -#include "qwaq-group.h" -#include "qwaq-proxyview.h" +#include "ui/group.h" +#include "ui/proxyview.h" @implementation ProxyView - (void) forward: (SEL) sel : (@va_list) args diff --git a/ruamoko/qwaq/qwaq-rect.h b/ruamoko/qwaq/ui/rect.h similarity index 87% rename from ruamoko/qwaq/qwaq-rect.h rename to ruamoko/qwaq/ui/rect.h index a26f74565..007dcb9e6 100644 --- a/ruamoko/qwaq/qwaq-rect.h +++ b/ruamoko/qwaq/ui/rect.h @@ -1,5 +1,5 @@ -#ifndef __qwaq_rect_h -#define __qwaq_rect_h +#ifndef __qwaq_ui_rect_h +#define __qwaq_ui_rect_h typedef struct Point_s { int x; @@ -25,4 +25,4 @@ int rectContainsPoint (Rect rect, Point point); Rect clipRect (Rect clipRect, Rect rect); #endif -#endif//__qwaq_rect_h +#endif//__qwaq_ui_rect_h diff --git a/ruamoko/qwaq/qwaq-rect.r b/ruamoko/qwaq/ui/rect.r similarity index 98% rename from ruamoko/qwaq/qwaq-rect.r rename to ruamoko/qwaq/ui/rect.r index c2677decc..f2a51cf8d 100644 --- a/ruamoko/qwaq/qwaq-rect.r +++ b/ruamoko/qwaq/ui/rect.r @@ -1,4 +1,4 @@ -#include "qwaq-rect.h" +#include "ui/rect.h" Rect clipRect (Rect clipRect, Rect rect) diff --git a/ruamoko/qwaq/qwaq-textcontext.h b/ruamoko/qwaq/ui/textcontext.h similarity index 89% rename from ruamoko/qwaq/qwaq-textcontext.h rename to ruamoko/qwaq/ui/textcontext.h index 2b979c415..898a62c60 100644 --- a/ruamoko/qwaq/qwaq-textcontext.h +++ b/ruamoko/qwaq/ui/textcontext.h @@ -1,11 +1,11 @@ -#ifndef __qwaq_textcontect_h -#define __qwaq_textcontect_h +#ifndef __qwaq_ui_textcontect_h +#define __qwaq_ui_textcontect_h #ifdef __QFCC__ #include -#include "qwaq-curses.h" -#include "qwaq-draw.h" -#include "qwaq-rect.h" +#include "ui/curses.h" +#include "ui/draw.h" +#include "ui/rect.h" @class DrawBuffer; @@ -79,4 +79,4 @@ typedef struct qwaq_textcontext_s { #endif -#endif//__qwaq_textcontect_h +#endif//__qwaq_ui_textcontect_h diff --git a/ruamoko/qwaq/qwaq-textcontext.r b/ruamoko/qwaq/ui/textcontext.r similarity index 98% rename from ruamoko/qwaq/qwaq-textcontext.r rename to ruamoko/qwaq/ui/textcontext.r index 421cdf8eb..6dffaa3e4 100644 --- a/ruamoko/qwaq/qwaq-textcontext.r +++ b/ruamoko/qwaq/ui/textcontext.r @@ -1,5 +1,5 @@ -#include "qwaq-draw.h" -#include "qwaq-textcontext.h" +#include "ui/draw.h" +#include "ui/textcontext.h" @implementation TextContext + (int) is_initialized = #0; diff --git a/ruamoko/qwaq/qwaq-titlebar.h b/ruamoko/qwaq/ui/titlebar.h similarity index 62% rename from ruamoko/qwaq/qwaq-titlebar.h rename to ruamoko/qwaq/ui/titlebar.h index addfdde4e..b623c52dc 100644 --- a/ruamoko/qwaq/qwaq-titlebar.h +++ b/ruamoko/qwaq/ui/titlebar.h @@ -1,7 +1,7 @@ -#ifndef __qwaq_titlebar_h -#define __qwaq_titlebar_h +#ifndef __qwaq_ui_titlebar_h +#define __qwaq_ui_titlebar_h -#include "qwaq-view.h" +#include "ui/view.h" @interface TitleBar : View { @@ -13,4 +13,4 @@ -setTitle:(string) newTitle; @end -#endif//__qwaq_titlebar_h +#endif//__qwaq_ui_titlebar_h diff --git a/ruamoko/qwaq/qwaq-titlebar.r b/ruamoko/qwaq/ui/titlebar.r similarity index 90% rename from ruamoko/qwaq/qwaq-titlebar.r rename to ruamoko/qwaq/ui/titlebar.r index 3a5bcfcda..96432280d 100644 --- a/ruamoko/qwaq/qwaq-titlebar.r +++ b/ruamoko/qwaq/ui/titlebar.r @@ -1,7 +1,7 @@ #include -#include "qwaq-group.h" -#include "qwaq-titlebar.h" +#include "ui/group.h" +#include "ui/titlebar.h" @implementation TitleBar diff --git a/ruamoko/qwaq/qwaq-view.h b/ruamoko/qwaq/ui/view.h similarity index 93% rename from ruamoko/qwaq/qwaq-view.h rename to ruamoko/qwaq/ui/view.h index 052bb2ada..eaa96063b 100644 --- a/ruamoko/qwaq/qwaq-view.h +++ b/ruamoko/qwaq/ui/view.h @@ -1,12 +1,12 @@ -#ifndef __qwaq_view_h -#define __qwaq_view_h +#ifndef __qwaq_ui_view_h +#define __qwaq_ui_view_h #include #include -#include "qwaq-draw.h" -#include "qwaq-rect.h" -#include "qwaq-textcontext.h" +#include "ui/draw.h" +#include "ui/rect.h" +#include "ui/textcontext.h" @class Group; @class ListenerGroup; @@ -120,4 +120,4 @@ enum { @interface View (TextContext) @end -#endif//__qwaq_view_h +#endif//__qwaq_ui_view_h diff --git a/ruamoko/qwaq/qwaq-view.r b/ruamoko/qwaq/ui/view.r similarity index 98% rename from ruamoko/qwaq/qwaq-view.r rename to ruamoko/qwaq/ui/view.r index 8b4077938..e352c8ce3 100644 --- a/ruamoko/qwaq/qwaq-view.r +++ b/ruamoko/qwaq/ui/view.r @@ -1,7 +1,7 @@ -#include "qwaq-curses.h" -#include "qwaq-listener.h" -#include "qwaq-view.h" -#include "qwaq-group.h" +#include "ui/curses.h" +#include "ui/listener.h" +#include "ui/view.h" +#include "ui/group.h" @implementation View diff --git a/ruamoko/qwaq/qwaq-window.h b/ruamoko/qwaq/ui/window.h similarity index 81% rename from ruamoko/qwaq/qwaq-window.h rename to ruamoko/qwaq/ui/window.h index a559ed862..bfb25c65a 100644 --- a/ruamoko/qwaq/qwaq-window.h +++ b/ruamoko/qwaq/ui/window.h @@ -1,5 +1,5 @@ -#ifndef __qwaq_window_h -#define __qwaq_window_h +#ifndef __qwaq_ui_window_h +#define __qwaq_ui_window_h #include "Object.h" @@ -7,9 +7,9 @@ @class Button; @class TitleBar; -#include "qwaq-draw.h" -#include "qwaq-rect.h" -#include "qwaq-view.h" +#include "ui/draw.h" +#include "ui/rect.h" +#include "ui/view.h" @interface Window: View { @@ -36,4 +36,4 @@ -insertSelected: (View *) view; @end -#endif//__qwaq_window_h +#endif//__qwaq_ui_window_h diff --git a/ruamoko/qwaq/qwaq-window.r b/ruamoko/qwaq/ui/window.r similarity index 97% rename from ruamoko/qwaq/qwaq-window.r rename to ruamoko/qwaq/ui/window.r index 3741d9acc..e3809bf77 100644 --- a/ruamoko/qwaq/qwaq-window.r +++ b/ruamoko/qwaq/ui/window.r @@ -1,14 +1,14 @@ #include #include -#include "event.h" -#include "qwaq-button.h" -#include "qwaq-curses.h" -#include "qwaq-group.h" -#include "qwaq-listener.h" -#include "qwaq-titlebar.h" -#include "qwaq-window.h" -#include "qwaq-view.h" +#include "ui/event.h" +#include "ui/button.h" +#include "ui/curses.h" +#include "ui/group.h" +#include "ui/listener.h" +#include "ui/titlebar.h" +#include "ui/window.h" +#include "ui/view.h" @implementation Window From eccf1cb962bcedea466505030aa728bc88d875ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 09:38:22 +0900 Subject: [PATCH 0959/3664] [qwaq] Move the debug builtin bindings --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/debugger/debug.r | 24 ++++++++++++++++++++++++ ruamoko/qwaq/debugger/debugger.r | 23 ----------------------- 3 files changed, 25 insertions(+), 23 deletions(-) create mode 100644 ruamoko/qwaq/debugger/debug.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 5bb8f0761..99f59b474 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -27,6 +27,7 @@ SUFFIXES=.o .r qwaq_app_dat_src= \ qwaq-app.r \ + debugger/debug.r \ debugger/debugger.r \ editor/editbuffer.r \ editor/editor.r \ diff --git a/ruamoko/qwaq/debugger/debug.r b/ruamoko/qwaq/debugger/debug.r new file mode 100644 index 000000000..b4175fbbb --- /dev/null +++ b/ruamoko/qwaq/debugger/debug.r @@ -0,0 +1,24 @@ +#include "debugger/debug.h" + +void traceon() = #0; +void traceoff() = #0; + +void qdb_set_trace (qdb_target_t target, int state) = #0; +int qdb_set_breakpoint (qdb_target_t target, unsigned staddr) = #0; +int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr) = #0; +int qdb_set_watchpoint (qdb_target_t target, unsigned offset) = #0; +int qdb_clear_watchpoint (qdb_target_t target) = #0; +int qdb_continue (qdb_target_t target) = #0; +qdb_state_t qdb_get_state (qdb_target_t target) = #0; +int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, + void *dst) = #0; +string qdb_get_string (qdb_target_t target, unsigned str) = #0; +qdb_def_t qdb_find_global (qdb_target_t target, string name) = #0; +qdb_def_t qdb_find_field (qdb_target_t target, string name) = #0; +qdb_function_t *qdb_find_function (qdb_target_t target, string name) = #0; +qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum) = #0; +qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, + string name) = #0; +qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, + unsigned fnum) = #0; +qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum) = #0; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index dde372e36..3948c0b0e 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -242,26 +242,3 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) } @end - -void traceon() = #0; -void traceoff() = #0; - -void qdb_set_trace (qdb_target_t target, int state) = #0; -int qdb_set_breakpoint (qdb_target_t target, unsigned staddr) = #0; -int qdb_clear_breakpoint (qdb_target_t target, unsigned staddr) = #0; -int qdb_set_watchpoint (qdb_target_t target, unsigned offset) = #0; -int qdb_clear_watchpoint (qdb_target_t target) = #0; -int qdb_continue (qdb_target_t target) = #0; -qdb_state_t qdb_get_state (qdb_target_t target) = #0; -int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, - void *dst) = #0; -string qdb_get_string (qdb_target_t target, unsigned str) = #0; -qdb_def_t qdb_find_global (qdb_target_t target, string name) = #0; -qdb_def_t qdb_find_field (qdb_target_t target, string name) = #0; -qdb_function_t *qdb_find_function (qdb_target_t target, string name) = #0; -qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum) = #0; -qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, - string name) = #0; -qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, - unsigned fnum) = #0; -qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum) = #0; From ddec80edc1d1b20dbf2063322ffd902da59c9d20 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 11:10:05 +0900 Subject: [PATCH 0960/3664] [qfcc] Make type encoding union anonymous I'd do more, but things get messy with direct access to unions that I want to be anonymous. --- include/QF/pr_type.h | 2 +- libs/gamecode/pr_debug.c | 30 +++++++++++------------ ruamoko/include/types.h | 2 +- tools/qfcc/source/dump_globals.c | 42 ++++++++++++++++---------------- tools/qfcc/source/dump_lines.c | 2 +- tools/qfcc/source/linker.c | 10 ++++---- tools/qfcc/source/obj_file.c | 40 +++++++++++++++--------------- tools/qfcc/source/obj_type.c | 38 ++++++++++++++--------------- 8 files changed, 83 insertions(+), 83 deletions(-) diff --git a/include/QF/pr_type.h b/include/QF/pr_type.h index d8c706fae..56915724b 100644 --- a/include/QF/pr_type.h +++ b/include/QF/pr_type.h @@ -112,7 +112,7 @@ typedef struct qfot_type_s { qfot_array_t array; ///< ty_array string_t class; ///< ty_class qfot_alias_t alias; ///< ty_alias - } t; + }; } qfot_type_t; typedef struct qfot_type_encodings_s { diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index dabaf227f..b1b7d217c 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -215,12 +215,12 @@ pr_debug_type_size (const progs_t *pr, const qfot_type_t *type) qfot_type_t *aux_type; switch (type->meta) { case ty_basic: - return pr_type_size[type->t.type]; + return pr_type_size[type->type]; case ty_struct: case ty_union: size = 0; - for (pr_int_t i = 0; i < type->t.strct.num_fields; i++) { - const qfot_var_t *field = &type->t.strct.fields[i]; + for (pr_int_t i = 0; i < type->strct.num_fields; i++) { + const qfot_var_t *field = &type->strct.fields[i]; aux_type = &G_STRUCT (pr, qfot_type_t, field->type); size = max (size, field->offset + pr_debug_type_size (pr, aux_type)); @@ -229,13 +229,13 @@ pr_debug_type_size (const progs_t *pr, const qfot_type_t *type) case ty_enum: return pr_type_size[ev_integer]; case ty_array: - aux_type = &G_STRUCT (pr, qfot_type_t, type->t.array.type); + aux_type = &G_STRUCT (pr, qfot_type_t, type->array.type); size = pr_debug_type_size (pr, aux_type); - return type->t.array.size * size; + return type->array.size * size; case ty_class: return 1; //FIXME or should it return sizeof class struct? case ty_alias: - aux_type = &G_STRUCT (pr, qfot_type_t, type->t.alias.aux_type); + aux_type = &G_STRUCT (pr, qfot_type_t, type->alias.aux_type); return pr_debug_type_size (pr, aux_type); } return 0; @@ -248,7 +248,7 @@ get_def_type (progs_t *pr, pr_def_t *def, qfot_type_t *type) // no type encoding, so use basic type data to fill in and return // the dummy encoding memset (type, 0, sizeof (*type)); - type->t.type = def->type; + type->type = def->type; } else { type = &G_STRUCT (pr, qfot_type_t, def->type_encoding); if (!def->size) { @@ -543,8 +543,8 @@ PR_LoadDebug (progs_t *pr) type_ptr += type->size) { type = &G_STRUCT (pr, qfot_type_t, type_encodings + type_ptr); if (type->meta == ty_basic - && type->t.type >= 0 && type->t.type < ev_type_count) { - res->type_encodings[type->t.type] = type; + && type->type >= 0 && type->type < ev_type_count) { + res->type_encodings[type->type] = type; } } } @@ -826,7 +826,7 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) { switch (type->meta) { case ty_basic: - switch (type->t.type) { + switch (type->type) { case ev_void: raw_type_view.void_view (type, value, data); break; @@ -887,7 +887,7 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) raw_type_view.class_view (type, value, data); break; case ty_alias://XXX - type = &G_STRUCT (data->pr, qfot_type_t, type->t.alias.aux_type); + type = &G_STRUCT (data->pr, qfot_type_t, type->alias.aux_type); return value_string (data, type, value); } return data->dstr->str; @@ -928,7 +928,7 @@ global_string (pr_debug_data_t *data, pointer_t offset, qfot_type_t *type, dstring_clearstr (dstr); - if (type && type->meta == ty_basic && type->t.type == ev_short) { + if (type && type->meta == ty_basic && type->type == ev_short) { dsprintf (dstr, "%04x", (short) offset); return dstr->str; } @@ -961,7 +961,7 @@ global_string (pr_debug_data_t *data, pointer_t offset, qfot_type_t *type, if (!type) { if (def) { if (!def->type_encoding) { - dummy_type.t.type = def->type; + dummy_type.type = def->type; type = &dummy_type; } else { type = &G_STRUCT (pr, qfot_type_t, def->type_encoding); @@ -1176,7 +1176,7 @@ pr_dump_struct (qfot_type_t *type, pr_type_t *value, void *_data, __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - qfot_struct_t *strct = &type->t.strct; + qfot_struct_t *strct = &type->strct; dstring_appendstr (dstr, "{"); for (int i = 0; i < strct->num_fields; i++) { @@ -1609,7 +1609,7 @@ PR_Debug_Init (progs_t *pr) res->void_type.meta = ty_basic; res->void_type.size = 4; res->void_type.encoding = 0; - res->void_type.t.type = ev_void; + res->void_type.type = ev_void; for (int i = 0; i < ev_type_count; i++ ) { res->type_encodings[i] = &res->void_type; } diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index c57603ada..530bfad1f 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -79,7 +79,7 @@ typedef struct qfot_type_s { qfot_array_t array; string class; qfot_alias_t alias; - } t; + }; } qfot_type_t; typedef struct qfot_type_encodings_s { diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 86a9c1525..49c78fa5d 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -548,46 +548,46 @@ dump_qfo_types (qfo_t *qfo, int base_address) } switch ((ty_meta_e) type->meta) { case ty_basic: - printf (" %-10s", (type->t.type < 0 - || type->t.type >= ev_type_count) + printf (" %-10s", (type->type < 0 + || type->type >= ev_type_count) ? "invalid type" - : pr_type_name[type->t.type]); - if (type->t.type == ev_func) { - printf (" %4x %d", type->t.func.return_type, - count = type->t.func.num_params); + : pr_type_name[type->type]); + if (type->type == ev_func) { + printf (" %4x %d", type->func.return_type, + count = type->func.num_params); if (count < 0) count = ~count; //ones complement for (i = 0; i < count; i++) - printf (" %x", type->t.func.param_types[i]); - } else if (type->t.type == ev_pointer - || type->t.type == ev_field) { - printf (" %4x", type->t.fldptr.aux_type); + printf (" %x", type->func.param_types[i]); + } else if (type->type == ev_pointer + || type->type == ev_field) { + printf (" %4x", type->fldptr.aux_type); } printf ("\n"); break; case ty_struct: case ty_union: case ty_enum: - printf (" %s\n", QFO_GETSTR (qfo, type->t.strct.tag)); - for (i = 0; i < type->t.strct.num_fields; i++) { + printf (" %s\n", QFO_GETSTR (qfo, type->strct.tag)); + for (i = 0; i < type->strct.num_fields; i++) { printf (" %-5x %4x %s\n", - type->t.strct.fields[i].type, - type->t.strct.fields[i].offset, - QFO_GETSTR (qfo, type->t.strct.fields[i].name)); + type->strct.fields[i].type, + type->strct.fields[i].offset, + QFO_GETSTR (qfo, type->strct.fields[i].name)); } break; case ty_array: - printf (" %-5x %d %d\n", type->t.array.type, - type->t.array.base, type->t.array.size); + printf (" %-5x %d %d\n", type->array.type, + type->array.base, type->array.size); break; case ty_class: - printf (" %-5x\n", type->t.class); + printf (" %-5x\n", type->class); break; case ty_alias: printf (" %s %d %5x %5x\n", - QFO_GETSTR (qfo, type->t.alias.name), - type->t.alias.type, type->t.alias.aux_type, - type->t.alias.full_type); + QFO_GETSTR (qfo, type->alias.name), + type->alias.type, type->alias.aux_type, + type->alias.full_type); break; } } diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index 966203a72..c98bfa0aa 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -147,7 +147,7 @@ qfo_set_func_data (qfo_t *qfo, qfo_func_t *func, func_data_t *func_data) func_data->source_line = func->line; //FIXME check type type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); - func_data->return_type = type->t.func.return_type; + func_data->return_type = type->func.return_type; func_data->num_locals = -1; if (func->locals_space < qfo->num_spaces) { func_data->num_locals = qfo->spaces[func->locals_space].num_defs; diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 14d963b73..51f03f948 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -296,11 +296,11 @@ resolve_external_def (defref_t *ext, defref_t *def) } ext_type = WORKTYPE (REF(ext)->type); if (ext_type->meta == ty_alias) { - ext_type = WORKTYPE (ext_type->t.alias.aux_type); + ext_type = WORKTYPE (ext_type->alias.aux_type); } def_type = WORKTYPE (REF (def)->type); if (def_type->meta == ty_alias) { - def_type = WORKTYPE (def_type->t.alias.aux_type); + def_type = WORKTYPE (def_type->alias.aux_type); } if (ext_type != def_type) { linker_type_mismatch (REF (ext), REF (def)); @@ -428,7 +428,7 @@ process_type_def (defref_t *ref, qfo_mspace_t *space, qfo_def_t *old) // new address in the encoding's class field so def and function types // can be updated easily. old_type->meta = -1; - old_type->t.class = REF (ref)->offset; + old_type->class = REF (ref)->offset; } } @@ -510,7 +510,7 @@ add_defs (qfo_t *qfo, qfo_mspace_t *space, qfo_mspace_t *dest_space, } // Type encodings have no type (type = 0) so setting the type // to the idef type class has no effect. - odef->type = type->t.class; // pointer to type in work + odef->type = type->class; // pointer to type in work // don't add unused (no attached relocs) external defs to the work // defref list so they will not cause unused object files to be // pulled in from libraries @@ -920,7 +920,7 @@ process_funcs (qfo_t *qfo) while (work->num_funcs < size) { func = work->funcs + work->num_funcs++; type = QFOTYPE(func->type); - func->type = type->t.class; + func->type = type->class; func->name = linker_add_string (QFOSTR (qfo, func->name)); func->file = linker_add_string (QFOSTR (qfo, func->file)); if (func->code > 0) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index be76f06c4..b6e3e6f82 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -653,7 +653,7 @@ get_def_type (qfo_t *qfo, pointer_t type) case ty_basic: // field, pointer and function types store their basic type in // the same location. - return type_def->t.type; + return type_def->type; case ty_struct: case ty_union: return ev_invalid; @@ -678,19 +678,19 @@ get_type_size (qfo_t *qfo, pointer_t type) type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { case ty_alias: - return get_type_size (qfo, type_def->t.alias.aux_type); + return get_type_size (qfo, type_def->alias.aux_type); case ty_basic: // field, pointer and function types store their basic type in // the same location. - return pr_type_size[type_def->t.type]; + return pr_type_size[type_def->type]; case ty_struct: - for (i = size = 0; i < type_def->t.strct.num_fields; i++) - size += get_type_size (qfo, type_def->t.strct.fields[i].type); + for (i = size = 0; i < type_def->strct.num_fields; i++) + size += get_type_size (qfo, type_def->strct.fields[i].type); return size; case ty_union: - for (i = size = 0; i < type_def->t.strct.num_fields; i++) { + for (i = size = 0; i < type_def->strct.num_fields; i++) { int s; - s = get_type_size (qfo, type_def->t.strct.fields[i].type); + s = get_type_size (qfo, type_def->strct.fields[i].type); if (s > size) size = s; } @@ -698,8 +698,8 @@ get_type_size (qfo_t *qfo, pointer_t type) case ty_enum: return pr_type_size[ev_integer]; case ty_array: - return type_def->t.array.size - * get_type_size (qfo, type_def->t.array.type); + return type_def->array.size + * get_type_size (qfo, type_def->array.type); case ty_class: return 0; // FIXME } @@ -728,15 +728,15 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) type_def = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, type); switch ((ty_meta_e)type_def->meta) { case ty_alias: - return get_type_alignment_log (qfo, type_def->t.alias.aux_type); + return get_type_alignment_log (qfo, type_def->alias.aux_type); case ty_basic: // field, pointer and function types store their basic type in // the same location. - return qfo_log2 (ev_types[type_def->t.type]->alignment); + return qfo_log2 (ev_types[type_def->type]->alignment); case ty_struct: case ty_union: - for (i = alignment = 0; i < type_def->t.strct.num_fields; i++) { - qfot_var_t *field = type_def->t.strct.fields + i; + for (i = alignment = 0; i < type_def->strct.num_fields; i++) { + qfot_var_t *field = type_def->strct.fields + i; int a; a = get_type_alignment_log (qfo, field->type); if (a > alignment) { @@ -747,7 +747,7 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) case ty_enum: return qfo_log2 (ev_types[ev_integer]->alignment); case ty_array: - return get_type_alignment_log (qfo, type_def->t.array.type); + return get_type_alignment_log (qfo, type_def->array.type); case ty_class: return 0; // FIXME } @@ -776,15 +776,15 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); if (type->meta == ty_alias) { type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, - type->t.alias.aux_type); + type->alias.aux_type); } - if (type->meta != ty_basic || type->t.type != ev_func) + if (type->meta != ty_basic || type->type != ev_func) return; - df->numparms = num_params = type->t.func.num_params; + df->numparms = num_params = type->func.num_params; if (num_params < 0) num_params = ~num_params; for (i = 0; i < num_params; i++) { - df->parm_size[i] = get_parmsize (qfo, type->t.func.param_types[i]); + df->parm_size[i] = get_parmsize (qfo, type->func.param_types[i]); } } @@ -1234,9 +1234,9 @@ qfo_to_sym (qfo_t *qfo, int *size) type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, func->type); if (type->meta == ty_alias) { type = QFO_POINTER (qfo, qfo_type_space, qfot_type_t, - type->t.alias.aux_type); + type->alias.aux_type); } - aux->return_type = type->t.func.return_type; + aux->return_type = type->func.return_type; aux++; } memcpy (linenos, qfo->lines, qfo->num_lines * sizeof (pr_lineno_t)); diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 78d7fc868..6838c0824 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -80,7 +80,7 @@ qfo_new_encoding (type_t *type, int size, defspace_t *space) qfot_type_t *enc; def_t *def; - size += sizeof (qfot_type_t) - sizeof (enc->t); + size += field_offset (qfot_type_t, type); size /= sizeof (pr_type_t); def = new_def (type->encoding, 0, space, sc_static); @@ -117,7 +117,7 @@ qfo_encode_func (type_t *type, defspace_t *space) def = qfo_new_encoding (type, size, space); enc = D_POINTER (qfot_type_t, def); - func = &enc->t.func; + func = &enc->func; func->type = ev_func; ENC_DEF (func->return_type, return_type_def); func->num_params = type->t.func.num_params; @@ -134,10 +134,10 @@ qfo_encode_fldptr (type_t *type, defspace_t *space) def_t *type_def; type_def = qfo_encode_type (type->t.fldptr.type, space); - def = qfo_new_encoding (type, sizeof (enc->t.fldptr), space); + def = qfo_new_encoding (type, sizeof (enc->fldptr), space); enc = D_POINTER (qfot_type_t, def); - enc->t.fldptr.type = type->type; - ENC_DEF (enc->t.fldptr.aux_type, type_def); + enc->fldptr.type = type->type; + ENC_DEF (enc->fldptr.aux_type, type_def); return def; } @@ -152,9 +152,9 @@ qfo_encode_basic (type_t *type, defspace_t *space) else if (type->type == ev_pointer || type->type == ev_field) return qfo_encode_fldptr (type, space); - def = qfo_new_encoding (type, sizeof (enc->t.type), space); + def = qfo_new_encoding (type, sizeof (enc->type), space); enc = D_POINTER (qfot_type_t, def); - enc->t.type = type->type; + enc->type = type->type; return def; } @@ -188,7 +188,7 @@ qfo_encode_struct (type_t *type, defspace_t *space) size = field_offset (qfot_struct_t, fields[num_fields]); def = qfo_new_encoding (type, size, space); enc = D_POINTER (qfot_type_t, def); - strct = &enc->t.strct; + strct = &enc->strct; ENC_STR (strct->tag, type->name); strct->num_fields = num_fields; @@ -234,11 +234,11 @@ qfo_encode_array (type_t *type, defspace_t *space) array_type_def = qfo_encode_type (type->t.array.type, space); - def = qfo_new_encoding (type, sizeof (enc->t.array), space); + def = qfo_new_encoding (type, sizeof (enc->array), space); enc = D_POINTER (qfot_type_t, def); - ENC_DEF (enc->t.array.type, array_type_def); - enc->t.array.base = type->t.array.base; - enc->t.array.size = type->t.array.size; + ENC_DEF (enc->array.type, array_type_def); + enc->array.base = type->t.array.base; + enc->array.size = type->t.array.size; return def; } @@ -248,9 +248,9 @@ qfo_encode_class (type_t *type, defspace_t *space) qfot_type_t *enc; def_t *def; - def = qfo_new_encoding (type, sizeof (enc->t.class), space); + def = qfo_new_encoding (type, sizeof (enc->class), space); enc = D_POINTER (qfot_type_t, def); - ENC_STR (enc->t.class, type->t.class->name); + ENC_STR (enc->class, type->t.class->name); return def; } @@ -265,13 +265,13 @@ qfo_encode_alias (type_t *type, defspace_t *space) type_def = qfo_encode_type (type->t.alias.aux_type, space); full_def = qfo_encode_type (type->t.alias.full_type, space); - def = qfo_new_encoding (type, sizeof (enc->t.alias), space); + def = qfo_new_encoding (type, sizeof (enc->alias), space); enc = D_POINTER (qfot_type_t, def); - enc->t.alias.type = type->type; - ENC_DEF (enc->t.alias.aux_type, type_def); - ENC_DEF (enc->t.alias.full_type, full_def); + enc->alias.type = type->type; + ENC_DEF (enc->alias.aux_type, type_def); + ENC_DEF (enc->alias.full_type, full_def); if (type->name) { - ENC_STR (enc->t.alias.name, type->name); + ENC_STR (enc->alias.name, type->name); } return def; } From 1c13339bbec605ff1a490460e7b1dc7154a323e3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 12:43:02 +0900 Subject: [PATCH 0961/3664] [qwaq] Create a type encoding class For now it just manages type encodings via their encoding string, ensuring types are fetched from the target only once, if at all (may already have the type due to it being common). --- ruamoko/include/types.h | 3 + ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/builtins/curses.c | 2 +- ruamoko/qwaq/builtins/debug.c | 3 +- ruamoko/qwaq/debugger/debug.h | 5 +- ruamoko/qwaq/debugger/debug.r | 1 + ruamoko/qwaq/debugger/debugger.h | 6 +- ruamoko/qwaq/debugger/debugger.r | 40 ++++--- ruamoko/qwaq/debugger/typeencodings.h | 13 +++ ruamoko/qwaq/debugger/typeencodings.r | 146 ++++++++++++++++++++++++++ ruamoko/qwaq/qwaq-app.r | 2 +- 11 files changed, 199 insertions(+), 23 deletions(-) create mode 100644 ruamoko/qwaq/debugger/typeencodings.h create mode 100644 ruamoko/qwaq/debugger/typeencodings.r diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index 530bfad1f..a1527d890 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -82,6 +82,9 @@ typedef struct qfot_type_s { }; } qfot_type_t; +// the minimum size of a type encoding +#define TYPESIZE 4 + typedef struct qfot_type_encodings_s { qfot_type_t *types; int size; diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 99f59b474..ab3b5459b 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -29,6 +29,7 @@ qwaq_app_dat_src= \ qwaq-app.r \ debugger/debug.r \ debugger/debugger.r \ + debugger/typeencodings.r \ editor/editbuffer.r \ editor/editor.r \ ui/button.r \ diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index f4db018a0..3f757b124 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -618,7 +618,7 @@ cmd_mvwhline (qwaq_resources_t *res) static void dump_command (qwaq_resources_t *res, int len) { - if (1) { + if (0) { qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); for (int i = 2; i < len; i++) { diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index c1835f99d..218a953cb 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -506,7 +506,8 @@ static builtin_t builtins[] = { {"qdb_continue", qdb_continue, -1}, {"qdb_get_state", qdb_get_state, -1}, {"qdb_get_data", qdb_get_data, -1}, - {"qdb_get_string", qdb_get_string, -1}, + {"qdb_get_string|{tag qdb_target_s=}i", qdb_get_string, -1}, + {"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1}, {"qdb_find_global", qdb_find_global, -1}, {"qdb_find_field", qdb_find_field, -1}, {"qdb_find_function", qdb_find_function, -1}, diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index 74ebf1c39..161014b84 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -63,7 +63,10 @@ int qdb_clear_watchpoint (qdb_target_t target); int qdb_continue (qdb_target_t target); qdb_state_t qdb_get_state (qdb_target_t target); int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst); -string qdb_get_string (qdb_target_t target, unsigned str); +@overload string qdb_get_string (qdb_target_t target, unsigned str); +// note: str is likely not valid in the host progs, it's just a convinience to +// avoid cast shenanigans when getting type encoding strings +@overload string qdb_get_string (qdb_target_t target, string str); qdb_def_t qdb_find_global (qdb_target_t target, string name); qdb_def_t qdb_find_field (qdb_target_t target, string name); qdb_function_t *qdb_find_function (qdb_target_t target, string name); diff --git a/ruamoko/qwaq/debugger/debug.r b/ruamoko/qwaq/debugger/debug.r index b4175fbbb..7ad286cf7 100644 --- a/ruamoko/qwaq/debugger/debug.r +++ b/ruamoko/qwaq/debugger/debug.r @@ -13,6 +13,7 @@ qdb_state_t qdb_get_state (qdb_target_t target) = #0; int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst) = #0; string qdb_get_string (qdb_target_t target, unsigned str) = #0; +string qdb_get_string (qdb_target_t target, string str) = #0; qdb_def_t qdb_find_global (qdb_target_t target, string name) = #0; qdb_def_t qdb_find_field (qdb_target_t target, string name) = #0; qdb_function_t *qdb_find_function (qdb_target_t target, string name) = #0; diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 2fc402291..04a6a3354 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -1,6 +1,7 @@ #ifndef __qwaq_debugger_debugger_h #define __qwaq_debugger_debugger_h +#include #include #include "debugger/debug.h" @@ -12,7 +13,8 @@ @interface Debugger : Object { - qdb_target_t debug_target; + qdb_target_t target; + qfot_type_encodings_t target_encodings; Window *source_window; ProxyView *file_proxy; @@ -28,7 +30,7 @@ qdb_def_t *local_defs; void *local_data; } --(qdb_target_t)debug_target; +-(qdb_target_t)target; -initWithTarget:(qdb_target_t) target; -handleDebugEvent; @end diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 3948c0b0e..44075babf 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -8,13 +8,14 @@ #include "ui/proxyview.h" #include "ui/window.h" #include "debugger/debugger.h" +#include "debugger/typeencodings.h" #include "editor/editor.h" #include "qwaq-app.h" @implementation Debugger --(qdb_target_t)debug_target +-(qdb_target_t)target { - return debug_target; + return target; } -initWithTarget:(qdb_target_t) target @@ -22,12 +23,15 @@ if (!(self = [super init])) { return nil; } - debug_target = target; + self.target = target; files = [[Array array] retain]; source_window = [[Window alloc] initWithRect: {nil, [application size]}]; [application addView:source_window]; + qdb_def_t encodings_def = qdb_find_global (target, ".type_encodings"); + qdb_get_data (target, encodings_def.offset, sizeof(target_encodings), + &target_encodings); return self; } @@ -50,7 +54,7 @@ -(void) setup { - qdb_state_t state = qdb_get_state (debug_target); + qdb_state_t state = qdb_get_state (target); current_file = [self find_file: state.file]; file_proxy = [[ProxyView alloc] initWithView: current_file]; @@ -75,7 +79,7 @@ -(void) show_line { - qdb_state_t state = qdb_get_state (debug_target); + qdb_state_t state = qdb_get_state (target); Editor *file = [self find_file: state.file]; printf ("%s:%d\n", state.file, state.line); @@ -104,10 +108,10 @@ update_current_func (Debugger *self, unsigned fnum) if (self.local_data) { obj_free (self.local_data); } - self.func = qdb_get_function (self.debug_target, fnum); - self.aux_func = qdb_get_auxfunction (self.debug_target, fnum); + self.func = qdb_get_function (self.target, fnum); + self.aux_func = qdb_get_auxfunction (self.target, fnum); if (self.aux_func) { - self.local_defs = qdb_get_local_defs (self.debug_target, fnum); + self.local_defs = qdb_get_local_defs (self.target, fnum); } if (self.func) { self.local_data = obj_malloc (self.func.local_size); @@ -116,14 +120,14 @@ update_current_func (Debugger *self, unsigned fnum) -(void)update_watchvars { - qdb_state_t state = qdb_get_state (debug_target); + qdb_state_t state = qdb_get_state (target); if (state.func != current_fnum) { update_current_func (self, state.func); } if (!local_data) { return; } - qdb_get_data (debug_target, func.local_data, func.local_size, local_data); + qdb_get_data (target, func.local_data, func.local_size, local_data); [locals_view clear]; if (!local_defs) { [locals_view mvprintf:{0,0}, "%d", func.local_size]; @@ -145,23 +149,25 @@ update_current_func (Debugger *self, unsigned fnum) break; } qdb_def_t *def = local_defs + y; + unsigned te = def.type_encoding + (int) target_encodings.types; + qfot_type_t *type; + type = [TypeEncodings getType:te fromTarget:target]; [locals_view mvprintf:{0, y}, "%s", - qdb_get_string (debug_target, def.name)]; + qdb_get_string (target, def.name)]; @param value = nil; string valstr = "--"; unsigned offset = func.local_data + def.offset; printf ("%d %d %s %d\n", def.type_size, offset, - qdb_get_string (debug_target, def.name), + qdb_get_string (target, def.name), def.type_encoding); - qdb_get_data (debug_target, offset, def.type_size >> 16, - &value); + qdb_get_data (target, offset, def.type_size >> 16, &value); switch (def.type_size & 0xffff) { case ev_void: case ev_invalid: case ev_type_count: break; case ev_string: - valstr = qdb_get_string (debug_target, value.integer_val); + valstr = qdb_get_string (target, value.integer_val); break; case ev_float: valstr = sprintf ("%.9g", value.float_val); @@ -216,8 +222,8 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) } else if (event.what == qe_keydown) { switch (event.key.code) { case QFK_F7: - qdb_set_trace (self.debug_target, 1); - qdb_continue (self.debug_target); + qdb_set_trace (self.target, 1); + qdb_continue (self.target); return 1; } } diff --git a/ruamoko/qwaq/debugger/typeencodings.h b/ruamoko/qwaq/debugger/typeencodings.h new file mode 100644 index 000000000..213dad8a7 --- /dev/null +++ b/ruamoko/qwaq/debugger/typeencodings.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_typeencodings_h +#define __qwaq_debugger_typeencodings_h + +#include +#include + +#include "debugger/debug.h" + +@interface TypeEncodings : Object ++(qfot_type_t *)getType:(unsigned)typeAddr fromTarget:(qdb_target_t)target; +@end + +#endif//__qwaq_debugger_typeencodings_h diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r new file mode 100644 index 000000000..30ff48181 --- /dev/null +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -0,0 +1,146 @@ +#include +#include +#include +#include // printf FIXME + +#include "debugger/typeencodings.h" + +@implementation TypeEncodings + +// these are encodings that we already have so don't need to copy them from +// the target +static hashtab_t *static_encodings; +// these are condings that had to be copied from the target +static hashtab_t *dynamic_encodings; + +static qfot_type_t * +next_type (qfot_type_t *type) +{ + int size = type.size; + + if (!size) { // null type + size = TYPESIZE; + } + return (qfot_type_t *) ((int *) type + size); +} + +static string +type_get_key (void *t, void *unusded) +{ + qfot_type_t *type = (qfot_type_t *) t; + return type.encoding; +} + +static void type_free (void *t, void *unused) +{ + qfot_type_t *type = (qfot_type_t *) t; + str_free (type.encoding); + switch (type.meta) { + case ty_basic: + case ty_array: + break; + case ty_struct: + case ty_union: + case ty_enum: + str_free (type.strct.tag); + for (int i = 0; i < type.strct.num_fields; i++) { + str_free (type.strct.fields[i].name); + } + break; + case ty_class: + str_free (type.class); + break; + case ty_alias: + str_free (type.alias.name); + break; + } + obj_free (t); +} + ++initialize +{ + qfot_type_encodings_t *encodings; + qfot_type_t *type; + + static_encodings = Hash_NewTable (1023, type_get_key, nil, nil); + dynamic_encodings = Hash_NewTable (1023, type_get_key, type_free, nil); + + encodings = PR_FindGlobal (".type_encodings"); + for (type = encodings.types; + ((int *)type - (int *) encodings.types) < encodings.size; + type = next_type (type)) { + printf ("%s\n", type.encoding); + Hash_Add (static_encodings, type); + } + return self; +} + ++(qfot_type_t *) getType:(unsigned)typeAddr fromTarget:(qdb_target_t)target +{ + qfot_type_t buffer = {}; + string encoding; + qfot_type_t *type; + + if (!qdb_get_data (target, typeAddr, TYPESIZE, &buffer)) { + return nil; + } + if (!buffer.encoding) { + return nil; + } + encoding = qdb_get_string (target, buffer.encoding); + if (!encoding) { + return nil; + } + if ((type = Hash_Find (static_encodings, encoding))) { + return type; + } + if ((type = Hash_Find (dynamic_encodings, encoding))) { + return type; + } + type = obj_calloc (1, buffer.size); + if (!qdb_get_data (target, typeAddr, TYPESIZE, &buffer)) { + goto error; + } + if (!(type.encoding = qdb_get_string (target, type.encoding))) { + goto error; + } + switch (type.meta) { + case ty_basic: + case ty_array: + goto hash_type; + case ty_struct: + case ty_union: + case ty_enum: + if (!(type.strct.tag = qdb_get_string (target, type.strct.tag))) { + goto error; + } + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (!(var.name = qdb_get_string (target, var.name))) { + goto error; + } + } + goto hash_type; + case ty_class: + if (!(type.class = qdb_get_string (target, type.class))) { + goto error; + } + goto hash_type; + case ty_alias: + if (!(type.alias.name = qdb_get_string (target, type.alias.name))) { + goto error; + } + goto hash_type; + } + goto error; +hash_type: + printf ("fetched type %s\n", type.encoding); + Hash_Add (dynamic_encodings, type); + return type; + // not a valid type +error: + type_free (type, nil); + return nil; +} + +@end diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 19daf643a..a17312ead 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -80,7 +80,7 @@ arp_end (void) for (int i = [debuggers count]; i-- > 0; ) { debugger = [debuggers objectAtIndex: i]; - if ([debugger debug_target].handle == target.handle) { + if ([debugger target].handle == target.handle) { return debugger; } } From 6d3fadfe6ebbe785269e202a415cac62b177a21b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 13:42:31 +0900 Subject: [PATCH 0962/3664] [qwaq] Move local defs viewer to its own class While trying to build a view without deriving from it was a neat idea, it doesn't work so well because a view really needs to know how to draw itself. This even fixes the segfault when stepping past the end of the program. --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/debugger/debugger.h | 10 +- ruamoko/qwaq/debugger/debugger.r | 121 +----------------------- ruamoko/qwaq/debugger/localsview.h | 22 +++++ ruamoko/qwaq/debugger/localsview.r | 142 +++++++++++++++++++++++++++++ 5 files changed, 171 insertions(+), 125 deletions(-) create mode 100644 ruamoko/qwaq/debugger/localsview.h create mode 100644 ruamoko/qwaq/debugger/localsview.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index ab3b5459b..d124b732a 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -29,6 +29,7 @@ qwaq_app_dat_src= \ qwaq-app.r \ debugger/debug.r \ debugger/debugger.r \ + debugger/localsview.r \ debugger/typeencodings.r \ editor/editbuffer.r \ editor/editor.r \ diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 04a6a3354..d43ad990c 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -5,6 +5,7 @@ #include #include "debugger/debug.h" +#include "debugger/localsview.h" @class ProxyView; @class Editor; @@ -14,7 +15,6 @@ @interface Debugger : Object { qdb_target_t target; - qfot_type_encodings_t target_encodings; Window *source_window; ProxyView *file_proxy; @@ -22,13 +22,7 @@ Editor *current_file; Window *locals_window; - View *locals_view; - - unsigned current_fnum; - qdb_function_t *func; - qdb_auxfunction_t *aux_func; - qdb_def_t *local_defs; - void *local_data; + LocalsView *locals_view; } -(qdb_target_t)target; -initWithTarget:(qdb_target_t) target; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 44075babf..4d1249702 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -29,9 +29,6 @@ source_window = [[Window alloc] initWithRect: {nil, [application size]}]; [application addView:source_window]; - qdb_def_t encodings_def = qdb_find_global (target, ".type_encodings"); - qdb_get_data (target, encodings_def.offset, sizeof(target_encodings), - &target_encodings); return self; } @@ -68,9 +65,8 @@ locals_window = [[Window alloc] initWithRect: {{0, 0}, {40, 10}}]; [locals_window setBackground: color_palette[064]]; [locals_window setTitle: "Locals"]; - locals_view = [[View alloc] initWithRect: {{1, 1}, {38, 8}} - options: ofCanFocus]; - [locals_view setGrowMode:gfGrowHi]; + locals_view = [[LocalsView alloc] initWithRect: {{1, 1}, {38, 8}} + target: target]; [locals_window insertSelected: locals_view]; [application addView: locals_window]; @@ -94,120 +90,11 @@ [source_window redraw]; } -static void -update_current_func (Debugger *self, unsigned fnum) -{ - self.current_fnum = fnum; - if (self.aux_func) { - obj_free (self.aux_func); - self.aux_func = nil; - } - if (self.local_defs) { - obj_free (self.local_defs); - } - if (self.local_data) { - obj_free (self.local_data); - } - self.func = qdb_get_function (self.target, fnum); - self.aux_func = qdb_get_auxfunction (self.target, fnum); - if (self.aux_func) { - self.local_defs = qdb_get_local_defs (self.target, fnum); - } - if (self.func) { - self.local_data = obj_malloc (self.func.local_size); - } -} - -(void)update_watchvars { qdb_state_t state = qdb_get_state (target); - if (state.func != current_fnum) { - update_current_func (self, state.func); - } - if (!local_data) { - return; - } - qdb_get_data (target, func.local_data, func.local_size, local_data); - [locals_view clear]; - if (!local_defs) { - [locals_view mvprintf:{0,0}, "%d", func.local_size]; - for (int y = 1; y < [locals_view size].height; y++) { - unsigned ind = (y - 1) * 4; - if (ind < func.local_size) { - [locals_view mvprintf:{0, y}, "%02x", ind]; - for (int x = 0; x < 4 && ind < func.local_size; x++, ind++) { - [locals_view mvprintf:{x * 9 + 3, y}, "%08x", - local_data[ind]]; - } - } else { - break; - } - } - } else { - for (int y = 0; y < [locals_view size].height; y++) { - if (y >= aux_func.num_locals) { - break; - } - qdb_def_t *def = local_defs + y; - unsigned te = def.type_encoding + (int) target_encodings.types; - qfot_type_t *type; - type = [TypeEncodings getType:te fromTarget:target]; - [locals_view mvprintf:{0, y}, "%s", - qdb_get_string (target, def.name)]; - @param value = nil; - string valstr = "--"; - unsigned offset = func.local_data + def.offset; - printf ("%d %d %s %d\n", def.type_size, offset, - qdb_get_string (target, def.name), - def.type_encoding); - qdb_get_data (target, offset, def.type_size >> 16, &value); - switch (def.type_size & 0xffff) { - case ev_void: - case ev_invalid: - case ev_type_count: - break; - case ev_string: - valstr = qdb_get_string (target, value.integer_val); - break; - case ev_float: - valstr = sprintf ("%.9g", value.float_val); - break; - case ev_vector: - valstr = sprintf ("%.9v", value.vector_val); - break; - case ev_entity: - valstr = sprintf ("%e", value.entity_val); - break; - case ev_field: - valstr = sprintf ("[%x]", value.field_val); - break; - case ev_func: - valstr = sprintf ("[%x]", value.func_val); - break; - case ev_pointer: - valstr = sprintf ("[%x]", value.pointer_val); - break; - case ev_quat: - valstr = sprintf ("[%q]", value.quaternion_val); - break; - case ev_integer: - valstr = sprintf ("%d", value.integer_val); - break; - case ev_uinteger: - valstr = sprintf ("%d", value.integer_val); - break; - case ev_short: - valstr = sprintf ("%d", value.integer_val); - break; - case ev_double: - valstr = sprintf ("%.17g", value.double_val); - break; - } - int x = [locals_view size].width - strlen (valstr); - [locals_view mvaddstr:{x, y}, valstr]; - } - } - [TextContext refresh]; + [locals_view setFunction:state.func]; + [locals_view redraw]; } static int diff --git a/ruamoko/qwaq/debugger/localsview.h b/ruamoko/qwaq/debugger/localsview.h new file mode 100644 index 000000000..c10101e07 --- /dev/null +++ b/ruamoko/qwaq/debugger/localsview.h @@ -0,0 +1,22 @@ +#ifndef __qwaq_debugger_localsview_h +#define __qwaq_debugger_localsview_h + +#include +#include "ui/view.h" +#include "debugger/debug.h" + +@interface LocalsView : View +{ + qdb_target_t target; + qfot_type_encodings_t target_encodings; + unsigned current_fnum; + qdb_function_t *func; + qdb_auxfunction_t *aux_func; + qdb_def_t *defs; + void *data; +} +-initWithRect:(Rect)rect target:(qdb_target_t) target; +-setFunction:(unsigned) fnum; +@end + +#endif diff --git a/ruamoko/qwaq/debugger/localsview.r b/ruamoko/qwaq/debugger/localsview.r new file mode 100644 index 000000000..af48edcc9 --- /dev/null +++ b/ruamoko/qwaq/debugger/localsview.r @@ -0,0 +1,142 @@ +#include +#include +#include "debugger/localsview.h" +#include "debugger/typeencodings.h" + +@implementation LocalsView + +-initWithRect:(Rect)rect target:(qdb_target_t) target +{ + if (!(self = [super initWithRect:rect])) { + return nil; + } + options = ofCanFocus; + growMode = gfGrowHi; + + self.target = target; + + qdb_def_t encodings_def = qdb_find_global (target, ".type_encodings"); + qdb_get_data (target, encodings_def.offset, sizeof(target_encodings), + &target_encodings); + + return self; +} + +-setFunction:(unsigned) fnum +{ + if (current_fnum == fnum) { + return self; + } + current_fnum =fnum; + + if (defs) { + obj_free (defs); + defs = nil; + } + if (data) { + obj_free (data); + data = nil; + } + func = qdb_get_function (target, fnum); + aux_func = qdb_get_auxfunction (target, fnum); + if (aux_func) { + defs = qdb_get_local_defs (target, fnum); + } + if (func) { + data = obj_malloc (func.local_size); + } + return self; +} + +-draw +{ + [super draw]; + + if (!data) { + return self; + } + qdb_get_data (target, func.local_data, func.local_size, data); + [self clear]; + if (!defs) { + [self mvprintf:{0,0}, "%d", func.local_size]; + for (int y = 1; y < ylen; y++) { + unsigned ind = (y - 1) * 4; + if (ind < func.local_size) { + [self mvprintf:{0, y}, "%02x", ind]; + for (int x = 0; x < 4 && ind < func.local_size; x++, ind++) { + [self mvprintf:{x * 9 + 3, y}, "%08x", + data[ind]]; + } + } else { + break; + } + } + } else { + for (int y = 0; y < ylen; y++) { + if (y >= aux_func.num_locals) { + break; + } + qdb_def_t *def = defs + y; + unsigned te = def.type_encoding + (int) target_encodings.types; + qfot_type_t *type; + type = [TypeEncodings getType:te fromTarget:target]; + [self mvprintf:{0, y}, "%s", + qdb_get_string (target, def.name)]; + @param value = nil; + string valstr = "--"; + unsigned offset = func.local_data + def.offset; + printf ("%d %d %s %d\n", def.type_size, offset, + qdb_get_string (target, def.name), + def.type_encoding); + qdb_get_data (target, offset, def.type_size >> 16, &value); + switch (def.type_size & 0xffff) { + case ev_void: + case ev_invalid: + case ev_type_count: + break; + case ev_string: + valstr = qdb_get_string (target, value.integer_val); + break; + case ev_float: + valstr = sprintf ("%.9g", value.float_val); + break; + case ev_vector: + valstr = sprintf ("%.9v", value.vector_val); + break; + case ev_entity: + valstr = sprintf ("%e", value.entity_val); + break; + case ev_field: + valstr = sprintf ("[%x]", value.field_val); + break; + case ev_func: + valstr = sprintf ("[%x]", value.func_val); + break; + case ev_pointer: + valstr = sprintf ("[%x]", value.pointer_val); + break; + case ev_quat: + valstr = sprintf ("[%q]", value.quaternion_val); + break; + case ev_integer: + valstr = sprintf ("%d", value.integer_val); + break; + case ev_uinteger: + valstr = sprintf ("%d", value.integer_val); + break; + case ev_short: + valstr = sprintf ("%d", value.integer_val); + break; + case ev_double: + valstr = sprintf ("%.17g", value.double_val); + break; + } + int x = xlen - strlen (valstr); + [self mvaddstr:{x, y}, valstr]; + } + } + + return self; +} + +@end From 0a63d0a0de755a1be8f9de87acc9d178d175fd87 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 16:25:54 +0900 Subject: [PATCH 0963/3664] [libr] Fix loop counter in removeObjectNoRelease It would do 4G iterations if count was 0. --- ruamoko/lib/Array+Private.r | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ruamoko/lib/Array+Private.r b/ruamoko/lib/Array+Private.r index 167404e5c..2cdea39cf 100644 --- a/ruamoko/lib/Array+Private.r +++ b/ruamoko/lib/Array+Private.r @@ -20,14 +20,14 @@ local unsigned i = count; local unsigned tmp; - do { - if (_objs[--i] == anObject) { + while (i-- > 0) { + if (_objs[i] == anObject) { for (tmp = i; tmp < count - 1; tmp++) { _objs[tmp] = _objs[tmp + 1]; } count--; } - } while (i); + } } @end From d7df2fa63db9771da1752e5789fd1b902f3eda3d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 16:27:47 +0900 Subject: [PATCH 0964/3664] [qwaq] Fix library dependencies Forgot to add them. --- ruamoko/qwaq/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index d124b732a..9b8abcd18 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -94,7 +94,7 @@ r_depfiles_remade= qwaq_app_dat_SOURCES=$(qwaq_app_dat_src) qwaq_app_obj=$(qwaq_app_dat_SOURCES:.r=.o) qwaq_app_dep=$(addprefix ./$(DEPDIR)/,$(qwaq_app_obj:.o=.Qo)) -qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) +qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) ../lib/libcsqc.a ../lib/libr.a $(QLINK) -o $@ $(qwaq_app_obj) -lcsqc -lr include $(qwaq_app_dep) # am--include-marker r_depfiles_remade += $(qwaq_app_dep) @@ -102,7 +102,7 @@ r_depfiles_remade += $(qwaq_app_dep) gcd_dat_SOURCES=gcd.r gcd_obj=$(gcd_dat_SOURCES:.r=.o) gcd_dep=$(addprefix ./$(DEPDIR)/,$(gcd_obj:.o=.Qo)) -gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) +gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) ../lib/libcsqc.a ../lib/libr.a $(QLINK) -o $@ $(gcd_obj) -lcsqc -lr include $(gcd_dep) # am--include-marker r_depfiles_remade += $(gcd_dep) From 8a7fbdfc9f6a8696ac8bdf2350128dd06df25bfe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 16:30:58 +0900 Subject: [PATCH 0965/3664] [qwaq] Rework allocation to use retain/release It currently dies when single stepping or exiting due to EditBuffer's retain count not getting incremented when initialized. This is because EditBuffer is initialized in C and thus does not call Object's -init. --- ruamoko/qwaq/debugger/debugger.h | 3 +- ruamoko/qwaq/debugger/debugger.r | 22 ++++++++++---- ruamoko/qwaq/debugger/localsview.h | 5 +-- ruamoko/qwaq/debugger/localsview.r | 17 +++++++++++ ruamoko/qwaq/editor/editbuffer.h | 2 ++ ruamoko/qwaq/editor/editbuffer.r | 10 ++++++ ruamoko/qwaq/editor/editor.h | 1 + ruamoko/qwaq/editor/editor.r | 16 ++++++++-- ruamoko/qwaq/qwaq-app.r | 7 +++-- ruamoko/qwaq/ui/button.h | 3 ++ ruamoko/qwaq/ui/button.r | 49 +++++++++++++++++++++--------- ruamoko/qwaq/ui/draw.h | 4 +-- ruamoko/qwaq/ui/draw.r | 10 ++++-- ruamoko/qwaq/ui/group.h | 3 +- ruamoko/qwaq/ui/group.r | 7 +++++ ruamoko/qwaq/ui/listener.h | 2 ++ ruamoko/qwaq/ui/listener.r | 15 +++++++-- ruamoko/qwaq/ui/proxyview.h | 5 +-- ruamoko/qwaq/ui/proxyview.r | 10 +++++- ruamoko/qwaq/ui/textcontext.h | 4 +++ ruamoko/qwaq/ui/textcontext.r | 17 ++++++++++- ruamoko/qwaq/ui/titlebar.h | 5 +-- ruamoko/qwaq/ui/titlebar.r | 5 +++ ruamoko/qwaq/ui/view.h | 7 +++-- ruamoko/qwaq/ui/view.r | 34 +++++++++++++++------ ruamoko/qwaq/ui/window.h | 2 +- ruamoko/qwaq/ui/window.r | 32 ++++++++----------- 27 files changed, 224 insertions(+), 73 deletions(-) diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index d43ad990c..95379099d 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -24,8 +24,9 @@ Window *locals_window; LocalsView *locals_view; } --(qdb_target_t)target; ++(Debugger *)withTarget:(qdb_target_t)target; -initWithTarget:(qdb_target_t) target; +-(qdb_target_t)target; -handleDebugEvent; @end diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 4d1249702..d54489788 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -13,6 +13,11 @@ #include "qwaq-app.h" @implementation Debugger ++(Debugger *)withTarget:(qdb_target_t)target +{ + return [[[self alloc] initWithTarget:target] autorelease]; +} + -(qdb_target_t)target { return target; @@ -26,12 +31,18 @@ self.target = target; files = [[Array array] retain]; - source_window = [[Window alloc] initWithRect: {nil, [application size]}]; + source_window = [Window withRect: {nil, [application size]}]; [application addView:source_window]; return self; } +-(void)dealloc +{ + [files release]; + [super dealloc]; +} + -(Editor *) find_file:(string) filename { Editor *file; @@ -44,7 +55,7 @@ Rect rect = {{1, 1}, [source_window size]}; rect.extent.width -= 2; rect.extent.height -= 2; - file = [[Editor alloc] initWithRect: rect file: filename]; + file = [Editor withRect:rect file:filename]; [files addObject: file]; return file; } @@ -54,7 +65,7 @@ qdb_state_t state = qdb_get_state (target); current_file = [self find_file: state.file]; - file_proxy = [[ProxyView alloc] initWithView: current_file]; + file_proxy = [ProxyView withView: current_file]; [[current_file gotoLine:state.line - 1] highlightLine]; [[current_file onEvent] addListener: self :@selector(proxy_event::)]; //FIXME id? @@ -62,11 +73,10 @@ [source_window setTitle: [current_file filename]]; [source_window redraw]; - locals_window = [[Window alloc] initWithRect: {{0, 0}, {40, 10}}]; + locals_window = [Window withRect:{{0, 0}, {40, 10}}]; [locals_window setBackground: color_palette[064]]; [locals_window setTitle: "Locals"]; - locals_view = [[LocalsView alloc] initWithRect: {{1, 1}, {38, 8}} - target: target]; + locals_view = [LocalsView withRect:{{1, 1}, {38, 8}} target:target]; [locals_window insertSelected: locals_view]; [application addView: locals_window]; diff --git a/ruamoko/qwaq/debugger/localsview.h b/ruamoko/qwaq/debugger/localsview.h index c10101e07..71886daaf 100644 --- a/ruamoko/qwaq/debugger/localsview.h +++ b/ruamoko/qwaq/debugger/localsview.h @@ -15,8 +15,9 @@ qdb_def_t *defs; void *data; } --initWithRect:(Rect)rect target:(qdb_target_t) target; --setFunction:(unsigned) fnum; ++(LocalsView *)withRect:(Rect)rect target:(qdb_target_t)target; +-initWithRect:(Rect)rect target:(qdb_target_t)target; +-setFunction:(unsigned)fnum; @end #endif diff --git a/ruamoko/qwaq/debugger/localsview.r b/ruamoko/qwaq/debugger/localsview.r index af48edcc9..f90d429fb 100644 --- a/ruamoko/qwaq/debugger/localsview.r +++ b/ruamoko/qwaq/debugger/localsview.r @@ -5,6 +5,11 @@ @implementation LocalsView ++(LocalsView *)withRect:(Rect)rect target:(qdb_target_t)target +{ + return [[[self alloc] initWithRect:rect target:target] autorelease]; +} + -initWithRect:(Rect)rect target:(qdb_target_t) target { if (!(self = [super initWithRect:rect])) { @@ -22,6 +27,18 @@ return self; } +-(void)dealloc +{ + if (defs) { + obj_free (defs); + defs = nil; + } + if (data) { + obj_free (data); + data = nil; + } +} + -setFunction:(unsigned) fnum { if (current_fnum == fnum) { diff --git a/ruamoko/qwaq/editor/editbuffer.h b/ruamoko/qwaq/editor/editbuffer.h index 72ee9db65..a1bfae616 100644 --- a/ruamoko/qwaq/editor/editbuffer.h +++ b/ruamoko/qwaq/editor/editbuffer.h @@ -26,6 +26,8 @@ typedef struct eb_color_s { { struct edit_buffer_s *buffer; } ++(EditBuffer *)buffer; ++(EditBuffer *)withFile:(string)filename; -init; -initWithFile: (string) filename; - (unsigned) nextChar: (unsigned) charPtr; diff --git a/ruamoko/qwaq/editor/editbuffer.r b/ruamoko/qwaq/editor/editbuffer.r index 2d58e0361..9a6da8396 100644 --- a/ruamoko/qwaq/editor/editbuffer.r +++ b/ruamoko/qwaq/editor/editbuffer.r @@ -1,6 +1,16 @@ #include "editor/editbuffer.h" @implementation EditBuffer ++(EditBuffer *)buffer +{ + return [[[self alloc] init] autorelease]; +} + ++(EditBuffer *)withFile:(string)filename +{ + return [[[self alloc] initWithFile:filename] autorelease]; +} + - init = #0; - initWithFile: (string) filename = #0; - (void) dealloc = #0; diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index 099ae78a3..fb5aaa7d3 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -22,6 +22,7 @@ unsigned line_count; string filename; } ++(Editor *)withRect:(Rect)rect file:(string)filename; -initWithRect:(Rect) rect file:(string) filename; -(string)filename; -scrollUp:(unsigned) count; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index f6f78d575..25e87c7db 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -5,20 +5,32 @@ @implementation Editor ++(Editor *)withRect:(Rect)rect file:(string)filename +{ + return [[[self alloc] initWithRect:rect file:filename] autorelease]; +} + -initWithRect:(Rect) rect file:(string) filename { if (!(self = [super initWithRect: rect])) { return nil; } self.filename = filename; - buffer = [[EditBuffer alloc] initWithFile: filename]; + buffer = [[EditBuffer withFile:filename] retain]; line_count = [buffer countLines: {0, [buffer textSize]}]; - linebuffer = [DrawBuffer buffer: { xlen, 1 }]; + linebuffer = [[DrawBuffer buffer: { xlen, 1 }] retain]; growMode = gfGrowHi; options = ofCanFocus | ofRelativeEvents; return self; } +-(void)dealloc +{ + [buffer release]; + [linebuffer release]; + [super dealloc]; +} + -(string)filename { return filename; diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index a17312ead..e98f4d03f 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -46,7 +46,7 @@ arp_end (void) screen = [TextContext screen]; screenSize = [screen size]; - objects = [[Group alloc] initWithContext: screen owner: nil]; + objects = [[Group withContext: screen owner: nil] retain]; [screen bkgd: color_palette[047]]; [screen scrollok: 1]; @@ -84,7 +84,7 @@ arp_end (void) return debugger; } } - debugger = [[Debugger alloc] initWithTarget: target]; + debugger = [Debugger withTarget: target]; [debuggers addObject: debugger]; return debugger; } @@ -153,11 +153,14 @@ int main (int argc, string *argv) fence = 0; //while (!fence) {} + arp_start (); application = [[QwaqApplication app] retain]; + arp_end (); [application run]; [application release]; qwaq_event_t event; get_event (&event); // XXX need a "wait for queue idle" + return 0; } diff --git a/ruamoko/qwaq/ui/button.h b/ruamoko/qwaq/ui/button.h index d407fbbff..8db47b4f8 100644 --- a/ruamoko/qwaq/ui/button.h +++ b/ruamoko/qwaq/ui/button.h @@ -20,6 +20,9 @@ ListenerGroup *onAuto; ListenerGroup *onHover; } ++(Button *)withPos: (Point) pos releasedIcon: (DrawBuffer *) released + pressedIcon: (DrawBuffer *) pressed; ++(Button *)withRect: (Rect) rect; // invisible button -initWithPos: (Point) pos releasedIcon: (DrawBuffer *) released pressedIcon: (DrawBuffer *) pressed; -initWithRect: (Rect) rect; // invisible button diff --git a/ruamoko/qwaq/ui/button.r b/ruamoko/qwaq/ui/button.r index 38d0690c4..1d6228571 100644 --- a/ruamoko/qwaq/ui/button.r +++ b/ruamoko/qwaq/ui/button.r @@ -2,6 +2,20 @@ #include "ui/listener.h" @implementation Button + ++(Button *)withPos:(Point)pos releasedIcon:(DrawBuffer *)released + pressedIcon:(DrawBuffer *)pressed +{ + return [[[self alloc] initWithPos:pos + releasedIcon:released + pressedIcon:pressed] autorelease]; +} + ++(Button *)withRect:(Rect)rect +{ + return [[[self alloc] initWithRect:rect] autorelease]; +} + -initWithPos: (Point) pos releasedIcon: (DrawBuffer *) released pressedIcon: (DrawBuffer *) pressed { @@ -10,14 +24,14 @@ if (!(self = [super initWithRect: {pos, size}])) { return nil; } - icon[0] = released; - icon[1] = pressed; - onPress = [[ListenerGroup alloc] init]; - onRelease = [[ListenerGroup alloc] init]; - onClick = [[ListenerGroup alloc] init]; - onDrag = [[ListenerGroup alloc] init]; - onAuto = [[ListenerGroup alloc] init]; - onHover = [[ListenerGroup alloc] init]; + icon[0] = [released retain]; + icon[1] = [pressed retain]; + onPress = [ListenerGroup listener]; + onRelease = [ListenerGroup listener]; + onClick = [ListenerGroup listener]; + onDrag = [ListenerGroup listener]; + onAuto = [ListenerGroup listener]; + onHover = [ListenerGroup listener]; return self; } @@ -28,15 +42,22 @@ } icon[0] = nil; icon[1] = nil; - onPress = [[ListenerGroup alloc] init]; - onRelease = [[ListenerGroup alloc] init]; - onClick = [[ListenerGroup alloc] init]; - onDrag = [[ListenerGroup alloc] init]; - onAuto = [[ListenerGroup alloc] init]; - onHover = [[ListenerGroup alloc] init]; + onPress = [ListenerGroup listener]; + onRelease = [ListenerGroup listener]; + onClick = [ListenerGroup listener]; + onDrag = [ListenerGroup listener]; + onAuto = [ListenerGroup listener]; + onHover = [ListenerGroup listener]; return self; } +-(void)dealloc +{ + [icon[0] release]; + [icon[1] release]; + [super dealloc]; +} + -draw { [super draw]; diff --git a/ruamoko/qwaq/ui/draw.h b/ruamoko/qwaq/ui/draw.h index 72be7fbf0..708bad192 100644 --- a/ruamoko/qwaq/ui/draw.h +++ b/ruamoko/qwaq/ui/draw.h @@ -39,8 +39,8 @@ Point cursor; int background; } -+ (DrawBuffer *) buffer: (Extent) size; -- initWithSize: (Extent) size; ++(DrawBuffer *)buffer:(Extent)size; +-initWithSize:(Extent)size; @end #endif//__qwaq_ui_draw_h diff --git a/ruamoko/qwaq/ui/draw.r b/ruamoko/qwaq/ui/draw.r index b9864af6d..b9f181a8e 100644 --- a/ruamoko/qwaq/ui/draw.r +++ b/ruamoko/qwaq/ui/draw.r @@ -5,9 +5,9 @@ @implementation DrawBuffer -+ (DrawBuffer *) buffer: (Extent) size ++(DrawBuffer *)buffer:(Extent)size { - return [[self alloc] initWithSize: size]; + return [[[self alloc] initWithSize: size] autorelease]; } - initWithSize: (Extent) size @@ -20,6 +20,12 @@ return self; } +-(void)dealloc +{ + obj_free (buffer); + [super dealloc]; +} + - (Extent) size { return size; diff --git a/ruamoko/qwaq/ui/group.h b/ruamoko/qwaq/ui/group.h index b243166b2..071ee53f0 100644 --- a/ruamoko/qwaq/ui/group.h +++ b/ruamoko/qwaq/ui/group.h @@ -17,7 +17,8 @@ int focused; id context; } --initWithContext: (id) context owner: (View *) owner; ++(Group *)withContext:(id)context owner:(View *)owner; +-initWithContext:(id)context owner:(View *)owner; -(id)context; -setContext: (id) context; -insert: (View *) view; diff --git a/ruamoko/qwaq/ui/group.r b/ruamoko/qwaq/ui/group.r index aa4fb117e..adaa21958 100644 --- a/ruamoko/qwaq/ui/group.r +++ b/ruamoko/qwaq/ui/group.r @@ -7,6 +7,11 @@ @implementation Group ++(Group *)withContext:(id)context owner:(View *)owner +{ + return [[[self alloc] initWithContext:context owner:owner] autorelease]; +} + -initWithContext: (id) context owner: (View *) owner { if (!(self = [super init])) { @@ -22,6 +27,7 @@ -(void)dealloc { [views release]; + [super dealloc]; } -(id)context @@ -85,6 +91,7 @@ makeFirst (Group *self, int viewIndex) { View *view = [self.views objectAtIndex: viewIndex]; + // add before remove to avoid freeing view [self.views addObject: view]; [self.views removeObjectAtIndex: viewIndex]; [view raise]; diff --git a/ruamoko/qwaq/ui/listener.h b/ruamoko/qwaq/ui/listener.h index e07356ad5..8df0c949c 100644 --- a/ruamoko/qwaq/ui/listener.h +++ b/ruamoko/qwaq/ui/listener.h @@ -11,6 +11,7 @@ SEL message; IMP imp; } ++(Listener *)listenerWithResponder:(id)responder :(SEL)message; -initWithResponder: (id) responder :(SEL)message; -(void) respond: (void *) caller_data; -(void) respond: (void *) caller_data withObject:(void *)anObject; @@ -21,6 +22,7 @@ { Array *listeners; } ++(ListenerGroup *)listener; -init; -addListener: (id) responder :(SEL)message; -removeListener: (id) responder :(SEL)message; diff --git a/ruamoko/qwaq/ui/listener.r b/ruamoko/qwaq/ui/listener.r index bdb36ac51..5035a4324 100644 --- a/ruamoko/qwaq/ui/listener.r +++ b/ruamoko/qwaq/ui/listener.r @@ -5,6 +5,11 @@ @class Array; @implementation Listener ++(Listener *)listenerWithResponder:(id)responder :(SEL)message +{ + return [[[self alloc] initWithResponder:responder :message] autorelease]; +} + -initWithResponder: (id) responder :(SEL)message { if (!(self = [super init])) { @@ -33,6 +38,11 @@ @end @implementation ListenerGroup : Object ++(ListenerGroup *)listener +{ + return [[[self alloc] init] autorelease]; +} + -init { if (!(self = [super init])) { @@ -44,10 +54,9 @@ -addListener: (id) responder :(SEL)message { - Listener *listener = [[Listener alloc] initWithResponder: responder - : message]; + Listener *listener = [Listener listenerWithResponder:responder :message]; if (listener) { - [listeners addObject: listener]; + [listeners addObject:listener]; } return self; } diff --git a/ruamoko/qwaq/ui/proxyview.h b/ruamoko/qwaq/ui/proxyview.h index 9a2c23c2e..d19a47ef0 100644 --- a/ruamoko/qwaq/ui/proxyview.h +++ b/ruamoko/qwaq/ui/proxyview.h @@ -10,8 +10,9 @@ View *view; Group *owner; } --initWithView:(View *) view; --setView: (View *) view; ++(ProxyView *)withView:(View *)view; +-initWithView:(View *)view; +-setView:(View *)view; @end @interface ProxyView (View) diff --git a/ruamoko/qwaq/ui/proxyview.r b/ruamoko/qwaq/ui/proxyview.r index a94c738dc..e4a10598e 100644 --- a/ruamoko/qwaq/ui/proxyview.r +++ b/ruamoko/qwaq/ui/proxyview.r @@ -2,6 +2,11 @@ #include "ui/proxyview.h" @implementation ProxyView ++(ProxyView *)withView:(View *)view +{ + return [[[self alloc] initWithView:view] autorelease]; +} + - (void) forward: (SEL) sel : (@va_list) args { if (!view) { @@ -15,7 +20,7 @@ if (!(self = [super init])) { return nil; } - self.view = view; + self.view = [view retain]; return self; } @@ -35,7 +40,10 @@ [self.view hide]; [self.view setContext:nil]; + [view retain]; + [self.view release]; self.view = view; + [view setContext:[owner context]]; if (state & sfDrawn) { [view draw]; diff --git a/ruamoko/qwaq/ui/textcontext.h b/ruamoko/qwaq/ui/textcontext.h index 898a62c60..f68ae1aa1 100644 --- a/ruamoko/qwaq/ui/textcontext.h +++ b/ruamoko/qwaq/ui/textcontext.h @@ -36,6 +36,10 @@ + (void) doupdate; + (TextContext *) screen; ++(TextContext *)textContext; ++(TextContext *)withRect:(Rect)rect; ++(TextContext *)withWindow:(window_t)window; + -init; -initWithRect: (Rect) rect; -initWithWindow: (window_t) window; diff --git a/ruamoko/qwaq/ui/textcontext.r b/ruamoko/qwaq/ui/textcontext.r index 6dffaa3e4..8867f1472 100644 --- a/ruamoko/qwaq/ui/textcontext.r +++ b/ruamoko/qwaq/ui/textcontext.r @@ -22,11 +22,26 @@ static TextContext *screen; + (TextContext *) screen { if (!screen) { - screen = [[TextContext alloc] init]; + screen = [[TextContext textContext] retain]; } return screen; } ++(TextContext *)textContext +{ + return [[[self alloc] init] autorelease]; +} + ++(TextContext *)withRect:(Rect)rect +{ + return [[[self alloc] initWithRect:rect] autorelease]; +} + ++(TextContext *)withWindow:(window_t)window +{ + return [[[self alloc] initWithWindow:window] autorelease]; +} + - init { if (!(self = [super init])) { diff --git a/ruamoko/qwaq/ui/titlebar.h b/ruamoko/qwaq/ui/titlebar.h index b623c52dc..e71a41a25 100644 --- a/ruamoko/qwaq/ui/titlebar.h +++ b/ruamoko/qwaq/ui/titlebar.h @@ -9,8 +9,9 @@ int length; } // title always centered at top of owner --initWithTitle:(string) title; --setTitle:(string) newTitle; ++(TitleBar *)withTitle:(string)title; +-initWithTitle:(string)title; +-setTitle:(string)newTitle; @end #endif//__qwaq_ui_titlebar_h diff --git a/ruamoko/qwaq/ui/titlebar.r b/ruamoko/qwaq/ui/titlebar.r index 96432280d..db1f717de 100644 --- a/ruamoko/qwaq/ui/titlebar.r +++ b/ruamoko/qwaq/ui/titlebar.r @@ -5,6 +5,11 @@ @implementation TitleBar ++(TitleBar *)withTitle:(string)title +{ + return [[[self alloc] initWithTitle:title] autorelease]; +} + -initWithTitle:(string) title { if (!(self = [super init])) { diff --git a/ruamoko/qwaq/ui/view.h b/ruamoko/qwaq/ui/view.h index eaa96063b..09a8ab8ba 100644 --- a/ruamoko/qwaq/ui/view.h +++ b/ruamoko/qwaq/ui/view.h @@ -113,8 +113,11 @@ enum { ListenerGroup *onReleaseFocus; ListenerGroup *onEvent; } --initWithRect: (Rect) rect; --initWithRect: (Rect) rect options:(int)options; ++(View *)viewWithRect:(Rect)rect; ++(View *)viewWithRect:(Rect)rect options:(int)options; + +-initWithRect:(Rect)rect; +-initWithRect:(Rect)rect options:(int)options; @end @interface View (TextContext) diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index e352c8ce3..f47d85f63 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -5,14 +5,29 @@ @implementation View ++(View *)viewWithRect:(Rect)rect +{ + return [[[self alloc] initWithRect:rect] autorelease]; +} + ++(View *)viewWithRect:(Rect)rect options:(int)options +{ + return [[[self alloc] initWithRect:rect options:options] autorelease]; +} + +static void view_init(View *self) +{ + self.onReceiveFocus = [ListenerGroup listener]; + self.onReleaseFocus = [ListenerGroup listener]; + self.onEvent = [ListenerGroup listener]; +} + -init { if (!(self = [super init])) { return nil; } - onReceiveFocus = [[ListenerGroup alloc] init]; - onReleaseFocus = [[ListenerGroup alloc] init]; - onEvent = [[ListenerGroup alloc] init]; + view_init (self); return self; } @@ -21,11 +36,10 @@ if (!(self = [super init])) { return nil; } + view_init (self); + self.rect = rect; self.absRect = rect; - onReceiveFocus = [[ListenerGroup alloc] init]; - onReleaseFocus = [[ListenerGroup alloc] init]; - onEvent = [[ListenerGroup alloc] init]; return self; } @@ -34,12 +48,11 @@ if (!(self = [super init])) { return nil; } + view_init (self); + self.rect = rect; self.absRect = rect; self.options = options; - onReceiveFocus = [[ListenerGroup alloc] init]; - onReleaseFocus = [[ListenerGroup alloc] init]; - onEvent = [[ListenerGroup alloc] init]; return self; } @@ -48,6 +61,9 @@ if (owner) { [owner remove:self]; } + [onReceiveFocus release]; + [onReleaseFocus release]; + [onEvent release]; [super dealloc]; } diff --git a/ruamoko/qwaq/ui/window.h b/ruamoko/qwaq/ui/window.h index bfb25c65a..67a0608e2 100644 --- a/ruamoko/qwaq/ui/window.h +++ b/ruamoko/qwaq/ui/window.h @@ -28,7 +28,7 @@ Button *bottomDrag; TitleBar *titleBar; } -+windowWithRect: (Rect) rect; ++(Window *)withRect: (Rect) rect; -setTitle:(string) title; -setBackground: (int) ch; -insert: (View *) view; diff --git a/ruamoko/qwaq/ui/window.r b/ruamoko/qwaq/ui/window.r index e3809bf77..ea966d473 100644 --- a/ruamoko/qwaq/ui/window.r +++ b/ruamoko/qwaq/ui/window.r @@ -12,7 +12,7 @@ @implementation Window -+windowWithRect: (Rect) rect ++(Window *)withRect: (Rect) rect { return [[[self alloc] initWithRect: rect] autorelease]; } @@ -28,29 +28,21 @@ return nil; } self.rect = rect; - textContext = [[TextContext alloc] initWithRect: rect]; + textContext = [[TextContext withRect: rect] retain]; panel = create_panel ([(id)textContext window]); - objects = [[Group alloc] initWithContext: textContext owner: self]; + objects = [[Group withContext:textContext owner:self] retain]; - [self insert: titleBar = [[TitleBar alloc] initWithTitle:""]]; + [self insert:titleBar = [TitleBar withTitle:""]]; - topDrag = [[Button alloc] initWithRect: {{2, 0}, - {xlen - 4, 1}}]; - topLeftDrag = [[Button alloc] initWithRect: {{0, 0}, - {2, 2}}]; - topRightDrag = [[Button alloc] initWithRect: {{xlen - 2, 0}, - {2, 2}}]; - leftDrag = [[Button alloc] initWithRect: {{0, 2}, - {1, ylen - 4}}]; - rightDrag = [[Button alloc] initWithRect: {{xlen - 1, 2}, - {1, ylen - 4}}]; - bottomLeftDrag = [[Button alloc] initWithRect: {{0, ylen - 2}, - {2, 2}}]; - bottomRightDrag = [[Button alloc] initWithRect: {{xlen - 2, ylen - 2}, - {2, 2}}]; - bottomDrag = [[Button alloc] initWithRect: {{2, ylen - 1}, - {xlen - 4, 1}}]; + topDrag = [Button withRect:{{2, 0}, {xlen - 4, 1}}]; + topLeftDrag = [Button withRect:{{0, 0}, {2, 2}}]; + topRightDrag = [Button withRect:{{xlen - 2, 0}, {2, 2}}]; + leftDrag = [Button withRect:{{0, 2}, {1, ylen - 4}}]; + rightDrag = [Button withRect:{{xlen - 1, 2}, {1, ylen - 4}}]; + bottomLeftDrag = [Button withRect:{{0, ylen - 2} , {2, 2}}]; + bottomRightDrag = [Button withRect:{{xlen - 2, ylen - 2}, {2, 2}}]; + bottomDrag = [Button withRect:{{2, ylen - 1}, {xlen - 4, 1}}]; [self insert: [topDrag setGrowMode: gfGrowHiX]]; [self insert: [topLeftDrag setGrowMode: gfGrowNone]]; [self insert: [topRightDrag setGrowMode: gfGrowX]]; From c23c68cf7f3789f20fd598d3d7ff1871a9a8d159 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 16:49:57 +0900 Subject: [PATCH 0966/3664] [ruamoko] Allow builtins to inc/dec retain count Needed for classes that are implemented entirely in C. --- include/QF/ruamoko.h | 7 ++++++- libs/ruamoko/rua_obj.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/QF/ruamoko.h b/include/QF/ruamoko.h index a2dcd6366..956465268 100644 --- a/include/QF/ruamoko.h +++ b/include/QF/ruamoko.h @@ -31,7 +31,7 @@ #ifndef __QF_ruamoko_h #define __QF_ruamoko_h -#include "QF/pr_comp.h" +#include "QF/pr_obj.h" struct progs_s; struct cbuf_s; @@ -40,4 +40,9 @@ void RUA_Init (struct progs_s *pr, int secure); void RUA_Cbuf_SetCbuf (struct progs_s *pr, struct cbuf_s *cbuf); func_t RUA_Obj_msg_lookup (struct progs_s *pr, pointer_t _self, pointer_t __cmd); +// self is expected in param 0 +int RUA_obj_increment_retaincount (struct progs_s *pr); +// self is expected in param 0 +int RUA_obj_decrement_retaincount (struct progs_s *pr); + #endif//__QF_ruamoko_h diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 1cdf8ed86..5bd5e3871 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -2254,3 +2254,17 @@ RUA_Obj_msg_lookup (progs_t *pr, pointer_t _self, pointer_t __cmd) return imp; } + +int +RUA_obj_increment_retaincount (progs_t *pr) +{ + rua_obj_increment_retaincount (pr); + return R_INT (pr); +} + +int +RUA_obj_decrement_retaincount (progs_t *pr) +{ + rua_obj_decrement_retaincount (pr); + return R_INT (pr); +} From 101574e697d46de02a04ed926e6f9f2c333a6539 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 16:51:09 +0900 Subject: [PATCH 0967/3664] [qwaq] Pretend to call super init in edit buffer This fixes the early deallocation of the edit buffer. --- ruamoko/qwaq/builtins/editbuffer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index f834f258c..ab1c161c3 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -7,6 +7,7 @@ #include #include "QF/progs.h" +#include "QF/ruamoko.h" #include "QF/quakeio.h" #include "QF/txtbuffer.h" @@ -532,6 +533,7 @@ bi_i_EditBuffer__init (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); + RUA_obj_increment_retaincount (pr);// [super init]; txtbuffer_t *txtbuffer = TextBuffer_Create (); editbuffer_t *buffer = editbuffer_new (res); @@ -547,6 +549,7 @@ bi_i_EditBuffer__initWithFile_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); + RUA_obj_increment_retaincount (pr);// [super init]; const char *filename = P_GSTRING (pr, 2); txtbuffer_t *txtbuffer = TextBuffer_Create (); editbuffer_t *buffer = editbuffer_new (res); From 0de9b027268c4ec01aeabb80c5f7db86f1b75957 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 18:55:04 +0900 Subject: [PATCH 0968/3664] [qfcc] Catch declarations of arrays of class They're still static instances. --- tools/qfcc/source/def.c | 4 ++-- tools/qfcc/test/Makefile.am | 4 ++++ tools/qfcc/test/build-compile-fail-run | 2 +- tools/qfcc/test/classarray.r | 10 ++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tools/qfcc/test/classarray.r diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 7c671fb3d..1450f0f45 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -140,7 +140,7 @@ new_def (const char *name, type_t *type, defspace_t *space, if (!space && storage != sc_extern) internal_error (0, "non-external def with no storage space"); - if (is_class (type)) { + if (is_class (type) || (is_array (type) && is_class(type->t.array.type))) { error (0, "statically allocated instance of class %s", type->t.class->name); return def; @@ -157,7 +157,7 @@ new_def (const char *name, type_t *type, defspace_t *space, } if (alignment < 1) { print_type (type); - internal_error (0, "temp type has no alignment"); + internal_error (0, "type has no alignment"); } def->offset = defspace_alloc_aligned_loc (space, size, alignment); } diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index fe61451b9..a7b10901f 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -81,6 +81,7 @@ test_progs_dat=\ fail_progs_dat= test_build_errors=\ + classarray.r \ double-demote-float.r \ double-demote-float-ainit.r \ double-demote-float-ginit.r \ @@ -208,6 +209,9 @@ double.run: Makefile build-run include ./$(DEPDIR)/double.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/double.Qo +classarray.run$(EXEEXT): classarray.r Makefile build-compile-fail-run + @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + double-demote-int.run$(EXEEXT): double-demote-int.r Makefile build-compile-fail-run @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/build-compile-fail-run b/tools/qfcc/test/build-compile-fail-run index 294727d96..415e894e7 100755 --- a/tools/qfcc/test/build-compile-fail-run +++ b/tools/qfcc/test/build-compile-fail-run @@ -5,7 +5,7 @@ shift cat > $script < Date: Mon, 30 Mar 2020 19:02:54 +0900 Subject: [PATCH 0969/3664] [qfcc] Fix missed t enum cleanup --- tools/qfcc/test/typedef.r | 18 +++++++++--------- tools/qfcc/test/zerolinker.r | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/test/typedef.r b/tools/qfcc/test/typedef.r index e6e80a92b..9dbd7f40b 100644 --- a/tools/qfcc/test/typedef.r +++ b/tools/qfcc/test/typedef.r @@ -24,9 +24,9 @@ next_type (qfot_type_t *type) int check_alias (string name, qfot_type_t *alias) { - if (alias.meta != ty_basic || alias.t.type != ev_pointer - || alias.t.fldptr.aux_type.meta != ty_basic - || alias.t.fldptr.aux_type.t.type != ev_integer) { + if (alias.meta != ty_basic || alias.type != ev_pointer + || alias.fldptr.aux_type.meta != ty_basic + || alias.fldptr.aux_type.type != ev_integer) { printf ("%s is not a *int alias\n", name); return 0; } @@ -48,13 +48,13 @@ main (void) ((int *)type - (int *) encodings.types) < encodings.size; type = next_type (type)) { if (type.meta == ty_alias) { - if (type.t.alias.name == "foo") { - found_foo = check_alias (type.t.alias.name, - type.t.alias.aux_type); + if (type.alias.name == "foo") { + found_foo = check_alias (type.alias.name, + type.alias.aux_type); } - if (type.t.alias.name == "bar") { - found_bar = check_alias (type.t.alias.name, - type.t.alias.aux_type); + if (type.alias.name == "bar") { + found_bar = check_alias (type.alias.name, + type.alias.aux_type); } } } diff --git a/tools/qfcc/test/zerolinker.r b/tools/qfcc/test/zerolinker.r index a5c6f7039..7b14f4a6e 100644 --- a/tools/qfcc/test/zerolinker.r +++ b/tools/qfcc/test/zerolinker.r @@ -28,10 +28,10 @@ main (void) ((int *)type - (int *) encodings.types) < encodings.size; type = next_type (type)) { if (type.meta == ty_union) { - if (type.t.strct.tag == "tag @param") { + if (type.strct.tag == "tag @param") { found_param = 1; } - if (type.t.strct.tag == "tag @zero") { + if (type.strct.tag == "tag @zero") { found_zero = 1; } } From 5bc57518b78909d32160704489c9ffc29788af44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 20:29:48 +0900 Subject: [PATCH 0970/3664] [qwaq] Add a scrollbar view --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/builtins/curses.c | 59 +++++++++ ruamoko/qwaq/ui/draw.h | 2 + ruamoko/qwaq/ui/draw.r | 16 +++ ruamoko/qwaq/ui/scrollbar.h | 35 ++++++ ruamoko/qwaq/ui/scrollbar.r | 216 +++++++++++++++++++++++++++++++++ ruamoko/qwaq/ui/textcontext.h | 1 + ruamoko/qwaq/ui/textcontext.r | 2 + 8 files changed, 332 insertions(+) create mode 100644 ruamoko/qwaq/ui/scrollbar.h create mode 100644 ruamoko/qwaq/ui/scrollbar.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 9b8abcd18..94d8c3f95 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -40,6 +40,7 @@ qwaq_app_dat_src= \ ui/listener.r \ ui/proxyview.r \ ui/rect.r \ + ui/scrollbar.r \ ui/textcontext.r \ ui/titlebar.r \ ui/view.r \ diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 3f757b124..b03533db4 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -85,6 +85,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_wresize, qwaq_cmd_resizeterm, qwaq_cmd_mvwhline, + qwaq_cmd_mvwvline, } qwaq_commands; static const char *qwaq_command_names[]= { @@ -118,6 +119,7 @@ static const char *qwaq_command_names[]= { "wresize", "resizeterm", "mvwhline" + "mvwvline" }; static window_t * @@ -615,6 +617,19 @@ cmd_mvwhline (qwaq_resources_t *res) mvwhline (window->win, y, x, ch, n); } +static void +cmd_mvwvline (qwaq_resources_t *res) +{ + int window_id = RB_PEEK_DATA (res->command_queue, 2); + int x = RB_PEEK_DATA (res->command_queue, 3); + int y = RB_PEEK_DATA (res->command_queue, 4); + int ch = RB_PEEK_DATA (res->command_queue, 5); + int n = RB_PEEK_DATA (res->command_queue, 6); + + window_t *window = get_window (res, __FUNCTION__, window_id); + mvwvline (window->win, y, x, ch, n); +} + static void dump_command (qwaq_resources_t *res, int len) { @@ -757,6 +772,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_mvwhline: cmd_mvwhline (res); break; + case qwaq_cmd_mvwvline: + cmd_mvwvline (res); + break; } pthread_mutex_lock (&res->command_cond.mut); RB_DROP_DATA (res->command_queue, len); @@ -1109,6 +1127,33 @@ bi_mvwhline (progs_t *pr) qwaq_mvwhline (pr, window_id, x, y, ch, n); } +static void +qwaq_mvwvline (progs_t *pr, int window_id, int x, int y, int ch, int n) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { + qwaq_cmd_mvwvline, 0, + window_id, x, y, ch, n + }; + + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} +static void +bi_mvwvline (progs_t *pr) +{ + int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + int ch = P_INT (pr, 3); + int n = P_INT (pr, 4); + + qwaq_mvwvline (pr, window_id, x, y, ch, n); +} + static void qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str) { @@ -1821,6 +1866,18 @@ bi_i_TextContext__mvhline_ (progs_t *pr) qwaq_mvwhline (pr, window_id, pos->x, pos->y, ch, n); } +static void +bi_i_TextContext__mvvline_ (progs_t *pr) +{ + __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); + int window_id = self->window; + __auto_type pos = &P_PACKED (pr, Point, 2); + int ch = P_INT (pr, 3); + int n = P_INT (pr, 4); + + qwaq_mvwvline (pr, window_id, pos->x, pos->y, ch, n); +} + static void bi_qwaq_clear (progs_t *pr, void *data) { @@ -1875,6 +1932,7 @@ static builtin_t builtins[] = { {"wresize", bi_wresize, -1}, {"resizeterm", bi_resizeterm, -1}, {"mvwhline", bi_mvwhline, -1}, + {"mvwvline", bi_mvwvline, -1}, {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, @@ -1900,6 +1958,7 @@ static builtin_t builtins[] = { {"_i_TextContext__scrollok_", bi_i_TextContext__scrollok_, -1}, {"_i_TextContext__border_", bi_i_TextContext__border_, -1}, {"_i_TextContext__mvhline_", bi_i_TextContext__mvhline_, -1}, + {"_i_TextContext__mvvline_", bi_i_TextContext__mvvline_, -1}, {0} }; diff --git a/ruamoko/qwaq/ui/draw.h b/ruamoko/qwaq/ui/draw.h index 708bad192..eb7379fe4 100644 --- a/ruamoko/qwaq/ui/draw.h +++ b/ruamoko/qwaq/ui/draw.h @@ -30,6 +30,8 @@ - (void) mvvprintf: (Point) pos, string fmt, @va_list args; - (void) mvaddch: (Point) pos, int ch; - (void) mvaddstr: (Point) pos, string str; +- (void) mvhline:(Point)pos, int ch, int len; +- (void) mvvline:(Point)pos, int ch, int len; @end @interface DrawBuffer : Object diff --git a/ruamoko/qwaq/ui/draw.r b/ruamoko/qwaq/ui/draw.r index b9f181a8e..37be4e6c0 100644 --- a/ruamoko/qwaq/ui/draw.r +++ b/ruamoko/qwaq/ui/draw.r @@ -248,4 +248,20 @@ [self addstr: str]; } +- (void) mvhline:(Point)pos, int ch, int len +{ + while (len-- > 0) { + [self mvaddch:pos, ch]; + pos.x++; + } +} + +- (void) mvvline:(Point)pos, int ch, int len +{ + while (len-- > 0) { + [self mvaddch:pos, ch]; + pos.y++; + } +} + @end diff --git a/ruamoko/qwaq/ui/scrollbar.h b/ruamoko/qwaq/ui/scrollbar.h new file mode 100644 index 000000000..7f710a25b --- /dev/null +++ b/ruamoko/qwaq/ui/scrollbar.h @@ -0,0 +1,35 @@ +#ifndef __qwaq_ui_scrollbar_h +#define __qwaq_ui_scrollbar_h + +#include "ui/view.h" + +@class Button; +@class Group; +@class ListenerGroup; + +@interface ScrollBar : View +{ + int vertical; + int bgchar; + Point mouseStart; + Button *backButton; + Button *forwardButton; + Button *thumbTab; + Group *objects; + ListenerGroup *onScroll; + + unsigned pageStep; + unsigned singleStep; + unsigned range; + unsigned index; +} ++(ScrollBar *)horizontal:(unsigned)len at:(Point)pos; ++(ScrollBar *)vertical:(unsigned)len at:(Point)pos; +-(ListenerGroup *)onScroll; +-setRange:(unsigned)range; +-setPageStep:(unsigned)pageStep; +-setSingleStep:(unsigned)singleStep; +-setIndex:(unsigned)index; +@end + +#endif//__qwaq_ui_scrollbar_h diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r new file mode 100644 index 000000000..78b8ab631 --- /dev/null +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -0,0 +1,216 @@ +#include "ui/button.h" +#include "ui/group.h" +#include "ui/listener.h" +#include "ui/scrollbar.h" + +@implementation ScrollBar + +-initWithRect:(Rect)rect +{ + if (!(self = [super initWithRect:rect])) { + return nil; + } + objects = [[Group withContext:textContext owner:self] retain]; + onScroll = [[ListenerGroup listener] retain]; + vertical = xlen == 1; + DrawBuffer *icons[3] = { + [DrawBuffer buffer:{1, 1}], + [DrawBuffer buffer:{1, 1}], + [DrawBuffer buffer:{1, 1}], + }; + [icons[2] addch:acs_char (ACS_DIAMOND)]; + Point thumbPos; + SEL thumbSel; + growMode = gfGrowAll; + if (vertical) { + [icons[0]addch:acs_char (ACS_UARROW)]; + [icons[1]addch:acs_char (ACS_DARROW)]; + thumbPos = {0, 1}; + thumbSel = @selector(verticalSlide); + growMode &= ~gfGrowLoY; + } else { + [icons[0]addch:acs_char (ACS_LARROW)]; + [icons[1]addch:acs_char (ACS_RARROW)]; + thumbPos = {1, 0}; + thumbSel = @selector(horizontalSlide); + growMode &= ~gfGrowLoX; + } + bgchar = acs_char (ACS_CKBOARD); + backButton = [Button withPos:{0, 0} + releasedIcon:icons[0] pressedIcon:icons[0]]; + forwardButton = [Button withPos:{xlen - 1, ylen - 1} + releasedIcon:icons[1] pressedIcon:icons[1]]; + thumbTab = [Button withPos:thumbPos + releasedIcon:icons[2] pressedIcon:icons[2]]; + + [[backButton onPress] addListener:self :@selector(scrollBack:)]; + [[forwardButton onPress] addListener:self :@selector(scrollForward:)]; + [[thumbTab onPress] addListener:self :thumbSel]; + + singleStep = 1; + + [objects insert:backButton]; + [objects insert:forwardButton]; + [objects insert:thumbTab]; + return self; +} + ++(ScrollBar *)horizontal:(unsigned)len at:(Point)pos +{ + if (len == 1) { + [self error:"can't make scrollbar of length 1"]; + } + return [[[self alloc] initWithRect:{pos, {len, 1}}] autorelease]; +} + ++(ScrollBar *)vertical:(unsigned)len at:(Point)pos +{ + if (len == 1) { + [self error:"can't make scrollbar of length 1"]; + } + return [[[self alloc] initWithRect:{pos, {1, len}}] autorelease]; +} + +-(ListenerGroup *)onScroll +{ + return onScroll; +} + +-draw +{ + if (vertical) { + [self mvvline:pos, bgchar, ylen]; + } else { + [self mvhline:pos, bgchar, xlen]; + } + [super draw]; + [objects draw]; + return self; +} + +static void +position_tab (ScrollBar *self) +{ + Point p = {0, 0}; + Point o = [self.thumbTab origin]; + if (self.range > 0) { + if (self.vertical) { + p.y = 1 + self.index * (self.ylen - 2) / (self.range - 1); + } else { + p.x = 1 + self.index * (self.xlen - 2) / (self.range - 1); + } + } + [self.thumbTab move:{p.x - o.x, p.y - o.y}]; +} + +-resize:(Extent)delta +{ + Extent size = self.size; + [super resize:delta]; + delta = {self.size.width - size.width, self.size.height - size.height}; + [objects resize:delta]; + position_tab (self); + return self; +} + +-page:(unsigned)step dir:(unsigned) dir +{ + unsigned oind = index; + + if (dir) { + if (range - 1 - index < step) { + step = range - 1 - index; + } + index += step; + } else { + if (index < step) { + step = index; + } + index -= step; + } + + if (index != oind) { + position_tab (self); + [onScroll respond:self]; + } + return self; +} + +static void +page (ScrollBar *self, Point pos) +{ + unsigned pageDir = 0; + if (self.vertical) { + if (pos.y < [self.thumbTab origin].y) { + pageDir = 0; + } else { + pageDir = 1; + } + } else { + if (pos.x < [self.thumbTab origin].x) { + pageDir = 0; + } else { + pageDir = 1; + } + } + [self page:self.pageStep dir:pageDir]; +} + +-(void)scrollBack:(id)sender +{ + [self page:singleStep dir:0]; +} + +-(void)scrollForward:(id)sender +{ + [self page:singleStep dir:1]; +} + +-handleEvent:(qwaq_event_t *)event +{ + [super handleEvent: event]; + [objects handleEvent: event]; + if (event.what == qe_mousedown) { + [self grabMouse]; + mouseStart = {event.mouse.x, event.mouse.y}; + page(self, mouseStart); + event.what = qe_none; + } else if (event.what==qe_mouseauto) { + page(self, mouseStart); + event.what = qe_none; + } else if (event.what == qe_mouseup) { + [self releaseMouse]; + event.what = qe_none; + } + return self; +} + +-setRange:(unsigned)range +{ + self.range = range; + return self; +} + +-setPageStep:(unsigned)pageStep +{ + self.pageStep = pageStep; + return self; +} + +-setSingleStep:(unsigned)singleStep +{ + self.singleStep = singleStep; + return self; +} + +-setIndex:(unsigned)index +{ + if (index > self.index) { + [self page:index - self.index dir:1]; + } else { + [self page:self.index - index dir:0]; + } + return self; +} + +@end diff --git a/ruamoko/qwaq/ui/textcontext.h b/ruamoko/qwaq/ui/textcontext.h index f68ae1aa1..2369dfeee 100644 --- a/ruamoko/qwaq/ui/textcontext.h +++ b/ruamoko/qwaq/ui/textcontext.h @@ -55,6 +55,7 @@ - (void) scrollok: (int) flag; - (void) border: (box_sides_t) sides, box_corners_t corners; - (void) mvhline: (Point) pos, int ch, int n; +- (void) mvvline: (Point) pos, int ch, int n; -clearReact: (Rect) rect; @end diff --git a/ruamoko/qwaq/ui/textcontext.r b/ruamoko/qwaq/ui/textcontext.r index 8867f1472..1f2ddd066 100644 --- a/ruamoko/qwaq/ui/textcontext.r +++ b/ruamoko/qwaq/ui/textcontext.r @@ -163,6 +163,7 @@ static TextContext *screen; - (void) mvaddch: (Point) pos, int ch = #0; - (void) mvaddstr: (Point) pos, string str = #0; - (void) mvhline: (Point) pos, int ch, int n = #0; +- (void) mvvline: (Point) pos, int ch, int n = #0; - (void) resizeTo: (Extent) newSize = #0; // absolute size - (void) refresh = #0; @@ -218,5 +219,6 @@ void wresize (window_t window, int width, int height) = #0; void resizeterm (int width, int height) = #0; Rect getwrect (window_t window) = #0; void mvwhline (window_t win, int x, int y, int ch, int n) = #0; +void mvwvline (window_t win, int x, int y, int ch, int n) = #0; void printf(string fmt, ...) = #0; From dbbdb31cb1d9f3fd77ffff2ad56e8dba8db2ad9a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 21:58:06 +0900 Subject: [PATCH 0971/3664] [qwaq] Add a synchronous printf command This puts a print command (to Sys_Printf) into the queue making it easier to check command sequences since regular printf is asynchronous with the stream. --- ruamoko/qwaq/builtins/curses.c | 48 ++++++++++++++++++++++++++++++---- ruamoko/qwaq/ui/curses.h | 1 + ruamoko/qwaq/ui/textcontext.r | 1 + 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index b03533db4..04ef11516 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -55,6 +55,7 @@ #define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) typedef enum qwaq_commands_e { + qwaq_cmd_syncprint, qwaq_cmd_newwin, qwaq_cmd_delwin, qwaq_cmd_getwrect, @@ -89,6 +90,7 @@ typedef enum qwaq_commands_e { } qwaq_commands; static const char *qwaq_command_names[]= { + "syncprint", "newwin", "delwin", "getwrect", @@ -118,8 +120,8 @@ static const char *qwaq_command_names[]= { "mvwblit_line", "wresize", "resizeterm", - "mvwhline" - "mvwvline" + "mvwhline", + "mvwvline", }; static window_t * @@ -280,6 +282,15 @@ qwaq_wait_result (qwaq_resources_t *res, int *result, int cmd, unsigned len) pthread_mutex_unlock (&res->results_cond.mut); } +static void +cmd_syncprint (qwaq_resources_t *res) +{ + int string_id = RB_PEEK_DATA (res->command_queue, 2); + + Sys_Printf ("%s\n", res->strings[string_id].str); + release_string (res, string_id); +} + static void cmd_newwin (qwaq_resources_t *res) { @@ -636,10 +647,14 @@ dump_command (qwaq_resources_t *res, int len) if (0) { qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); - for (int i = 2; i < len; i++) { - Sys_Printf (" %d", RB_PEEK_DATA (res->command_queue, i)); + if (cmd == qwaq_cmd_syncprint) { + Sys_Printf (" "); + } else { + for (int i = 2; i < len; i++) { + Sys_Printf (" %d", RB_PEEK_DATA (res->command_queue, i)); + } + Sys_Printf ("\n"); } - Sys_Printf ("\n"); } } @@ -682,6 +697,9 @@ process_commands (qwaq_resources_t *res) dump_command (res, len); qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); switch (cmd) { + case qwaq_cmd_syncprint: + cmd_syncprint (res); + break; case qwaq_cmd_newwin: cmd_newwin (res); break; @@ -829,6 +847,25 @@ bi_shutdown (void *_pr) } } +static void +bi_syncprintf (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + const char *fmt = P_GSTRING (pr, 0); + int count = pr->pr_argc - 1; + pr_type_t **args = pr->pr_params + 1; + int string_id = acquire_string (res); + dstring_t *print_buffer = res->strings + string_id; + int command[] = { qwaq_cmd_syncprint, 0, string_id }; + + command[1] = CMD_SIZE(command); + + dstring_clearstr (print_buffer); + PR_Sprintf (pr, print_buffer, "mvwaddstr", fmt, count, args); + + qwaq_submit_command (res, command); +} + static void bi_newwin (progs_t *pr) { @@ -1894,6 +1931,7 @@ bi_qwaq_clear (progs_t *pr, void *data) static builtin_t builtins[] = { {"initialize", bi_initialize, -1}, + {"syncprintf", bi_syncprintf, -1}, {"create_window", bi_newwin, -1}, {"destroy_window", bi_delwin, -1}, {"getwrect", bi_getwrect, -1}, diff --git a/ruamoko/qwaq/ui/curses.h b/ruamoko/qwaq/ui/curses.h index 65143159f..1849a6440 100644 --- a/ruamoko/qwaq/ui/curses.h +++ b/ruamoko/qwaq/ui/curses.h @@ -87,6 +87,7 @@ typedef struct panel_s *panel_t; extern window_t stdscr; void initialize (void); +void syncprintf (string fnt, ...); window_t create_window (int xpos, int ypos, int xlen, int ylen); void destroy_window (window_t win); void mvwprintf (window_t win, int x, int y, string fmt, ...); diff --git a/ruamoko/qwaq/ui/textcontext.r b/ruamoko/qwaq/ui/textcontext.r index 1f2ddd066..bbe7a9476 100644 --- a/ruamoko/qwaq/ui/textcontext.r +++ b/ruamoko/qwaq/ui/textcontext.r @@ -179,6 +179,7 @@ static TextContext *screen; window_t stdscr = (window_t) 1; void initialize (void) = #0; +void syncprintf (string fnt, ...) = #0; window_t create_window (int xpos, int ypos, int xlen, int ylen) = #0; void destroy_window (window_t win) = #0; void mvwprintf (window_t win, int x, int y, string fmt, ...) = #0; From 02f8cc976027272ef721406d4790d156f0766eb6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 22:01:17 +0900 Subject: [PATCH 0972/3664] [qwaq] Fix a bunch of issues with the scrollbar Leaking memory. And worse, it wasn't drawing its buttons (group wasn't setting view contexts) and then the buttons were in the wrong place, so had to add a backing buffer for the buttons. --- ruamoko/qwaq/ui/group.r | 2 ++ ruamoko/qwaq/ui/scrollbar.h | 2 ++ ruamoko/qwaq/ui/scrollbar.r | 21 ++++++++++++++++----- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/ruamoko/qwaq/ui/group.r b/ruamoko/qwaq/ui/group.r index adaa21958..8bbca6d9b 100644 --- a/ruamoko/qwaq/ui/group.r +++ b/ruamoko/qwaq/ui/group.r @@ -38,6 +38,8 @@ -setContext: (id) context { self.context = context; + [views makeObjectsPerformSelector:@selector(setContext:) + withObject:context]; return self; } diff --git a/ruamoko/qwaq/ui/scrollbar.h b/ruamoko/qwaq/ui/scrollbar.h index 7f710a25b..08d8ea6d6 100644 --- a/ruamoko/qwaq/ui/scrollbar.h +++ b/ruamoko/qwaq/ui/scrollbar.h @@ -4,6 +4,7 @@ #include "ui/view.h" @class Button; +@class DrawBuffer; @class Group; @class ListenerGroup; @@ -12,6 +13,7 @@ int vertical; int bgchar; Point mouseStart; + DrawBuffer *buffer; Button *backButton; Button *forwardButton; Button *thumbTab; diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index 78b8ab631..86b2a6071 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -10,7 +10,8 @@ if (!(self = [super initWithRect:rect])) { return nil; } - objects = [[Group withContext:textContext owner:self] retain]; + buffer = [[DrawBuffer buffer:size] retain]; + objects = [[Group withContext:buffer owner:self] retain]; onScroll = [[ListenerGroup listener] retain]; vertical = xlen == 1; DrawBuffer *icons[3] = { @@ -23,14 +24,14 @@ SEL thumbSel; growMode = gfGrowAll; if (vertical) { - [icons[0]addch:acs_char (ACS_UARROW)]; - [icons[1]addch:acs_char (ACS_DARROW)]; + [icons[0] addch:acs_char (ACS_UARROW)]; + [icons[1] addch:acs_char (ACS_DARROW)]; thumbPos = {0, 1}; thumbSel = @selector(verticalSlide); growMode &= ~gfGrowLoY; } else { - [icons[0]addch:acs_char (ACS_LARROW)]; - [icons[1]addch:acs_char (ACS_RARROW)]; + [icons[0] addch:acs_char (ACS_LARROW)]; + [icons[1] addch:acs_char (ACS_RARROW)]; thumbPos = {1, 0}; thumbSel = @selector(horizontalSlide); growMode &= ~gfGrowLoX; @@ -55,6 +56,13 @@ return self; } +-(void)dealloc +{ + [objects release]; + [buffer release]; + [onScroll release]; +} + +(ScrollBar *)horizontal:(unsigned)len at:(Point)pos { if (len == 1) { @@ -78,6 +86,7 @@ -draw { + syncprintf("scrollbar start"); if (vertical) { [self mvvline:pos, bgchar, ylen]; } else { @@ -85,6 +94,8 @@ } [super draw]; [objects draw]; + [textContext blitFromBuffer:buffer to:pos from:[buffer rect]]; + syncprintf("scrollbar end"); return self; } From b8005a99c9f21a3b9f91d91c93f2534693ae04f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 22:02:58 +0900 Subject: [PATCH 0973/3664] [qwaq] Add a scroll bar to the debug source window It's not quite hooked up properly yet (Editor ignores the message), but it did help get ScrollBar displaying properly. --- ruamoko/qwaq/debugger/debugger.h | 2 ++ ruamoko/qwaq/debugger/debugger.r | 7 ++++++- ruamoko/qwaq/editor/editor.h | 4 +++- ruamoko/qwaq/editor/editor.r | 28 +++++++++++++++++++++++----- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 95379099d..0b3b75f50 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -9,6 +9,7 @@ @class ProxyView; @class Editor; +@class ScrollBar; @class Window; @class Array; @@ -22,6 +23,7 @@ Editor *current_file; Window *locals_window; + ScrollBar *scrollbar; LocalsView *locals_view; } +(Debugger *)withTarget:(qdb_target_t)target; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index d54489788..3e64424d2 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -6,6 +6,7 @@ #include "ui/curses.h" #include "ui/listener.h" #include "ui/proxyview.h" +#include "ui/scrollbar.h" #include "ui/window.h" #include "debugger/debugger.h" #include "debugger/typeencodings.h" @@ -30,10 +31,14 @@ } self.target = target; + Extent s = [application size]; files = [[Array array] retain]; - source_window = [Window withRect: {nil, [application size]}]; + source_window = [Window withRect: {nil, s}]; [application addView:source_window]; + scrollbar = [ScrollBar vertical:s.height - 2 at:{s.width - 1, 1}]; + [source_window insert:scrollbar]; + return self; } diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index fb5aaa7d3..3a2cd48c5 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -7,11 +7,13 @@ @class Editor; @class EditBuffer; @class ListenerGroup; +@class ScrollBar; @interface Editor : View { EditBuffer *buffer; DrawBuffer *linebuffer; + ScrollBar *vScrollBar; eb_sel_t selection; unsigned base_index; // top left corner unsigned line_index; // current line @@ -23,7 +25,7 @@ string filename; } +(Editor *)withRect:(Rect)rect file:(string)filename; --initWithRect:(Rect) rect file:(string) filename; +-setVerticalScrollBar:(ScrollBar *)scrollbar; -(string)filename; -scrollUp:(unsigned) count; -scrollDown:(unsigned) count; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index 25e87c7db..3248ce59d 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -2,14 +2,10 @@ #include "qwaq-app.h" #include "editor/editor.h" #include "ui/listener.h" +#include "ui/scrollbar.h" @implementation Editor -+(Editor *)withRect:(Rect)rect file:(string)filename -{ - return [[[self alloc] initWithRect:rect file:filename] autorelease]; -} - -initWithRect:(Rect) rect file:(string) filename { if (!(self = [super initWithRect: rect])) { @@ -24,8 +20,30 @@ return self; } ++(Editor *)withRect:(Rect)rect file:(string)filename +{ + return [[[self alloc] initWithRect:rect file:filename] autorelease]; +} + +-(void)onScroll:(id)sender +{ +} + +-setVerticalScrollBar:(ScrollBar *)scrollbar +{ + [scrollbar retain]; + [[vScrollBar onScroll] removeListener:self :@selector(onScroll)]; + [vScrollBar release]; + + vScrollBar = scrollbar; + [vScrollBar setRange:line_count]; + [[vScrollBar onScroll] addListener:self :@selector(onScroll)]; + return self; +} + -(void)dealloc { + [vScrollBar release]; [buffer release]; [linebuffer release]; [super dealloc]; From 1a34f3663aa20b94f886cb7af6ca3d4a8096ca51 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 22:50:29 +0900 Subject: [PATCH 0974/3664] [qwaq] Hook up the scroll bar It's mostly working now, just some issues with clicking on the bar and the thumb tab doesn't work. --- ruamoko/qwaq/debugger/debugger.r | 3 +++ ruamoko/qwaq/editor/editor.r | 31 +++++++++++++++++----------- ruamoko/qwaq/ui/scrollbar.h | 1 + ruamoko/qwaq/ui/scrollbar.r | 35 ++++++++++++++++++++++---------- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 3e64424d2..6c16655e8 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -73,6 +73,7 @@ file_proxy = [ProxyView withView: current_file]; [[current_file gotoLine:state.line - 1] highlightLine]; [[current_file onEvent] addListener: self :@selector(proxy_event::)]; + [current_file setVerticalScrollBar:scrollbar]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; [source_window setTitle: [current_file filename]]; @@ -95,9 +96,11 @@ printf ("%s:%d\n", state.file, state.line); if (current_file != file) { + [current_file setVerticalScrollBar:nil]; [[current_file onEvent] removeListener:self :@selector(proxy_event::)]; [file_proxy setView:file]; [[file onEvent] addListener:self :@selector(proxy_event::)]; + [file setVerticalScrollBar:scrollbar]; [source_window setTitle: [file filename]]; current_file = file; } diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index 3248ce59d..64daf5773 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -25,19 +25,15 @@ return [[[self alloc] initWithRect:rect file:filename] autorelease]; } --(void)onScroll:(id)sender -{ -} - -setVerticalScrollBar:(ScrollBar *)scrollbar { [scrollbar retain]; - [[vScrollBar onScroll] removeListener:self :@selector(onScroll)]; + [[vScrollBar onScroll] removeListener:self :@selector(onScroll:)]; [vScrollBar release]; vScrollBar = scrollbar; [vScrollBar setRange:line_count]; - [[vScrollBar onScroll] addListener:self :@selector(onScroll)]; + [[vScrollBar onScroll] addListener:self :@selector(onScroll:)]; return self; } @@ -164,6 +160,22 @@ static int handleEvent (Editor *self, qwaq_event_t *event) return self; } +-scrollTo:(unsigned)target +{ + if (target > scroll.y) { + base_index = [buffer nextLine:base_index :target - scroll.y]; + } else if (target < scroll.y) { + base_index = [buffer prevLine:base_index :scroll.y - target]; + } + scroll.y = target; + return self; +} + +-(void)onScroll:(id)sender +{ + [self scrollTo:[sender index]]; +} + -recenter:(int) force { if (!force) { @@ -177,12 +189,7 @@ static int handleEvent (Editor *self, qwaq_event_t *event) } else { target = cursor.y - ylen / 2; } - if (target > scroll.y) { - base_index = [buffer nextLine:base_index :target - scroll.y]; - } else if (target < scroll.y) { - base_index = [buffer prevLine:base_index :scroll.y - target]; - } - scroll.y = target; + [self scrollTo:target]; return self; } diff --git a/ruamoko/qwaq/ui/scrollbar.h b/ruamoko/qwaq/ui/scrollbar.h index 08d8ea6d6..190b5a59b 100644 --- a/ruamoko/qwaq/ui/scrollbar.h +++ b/ruamoko/qwaq/ui/scrollbar.h @@ -32,6 +32,7 @@ -setPageStep:(unsigned)pageStep; -setSingleStep:(unsigned)singleStep; -setIndex:(unsigned)index; +-(unsigned)index; @end #endif//__qwaq_ui_scrollbar_h diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index 86b2a6071..e90ad70e7 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -10,6 +10,7 @@ if (!(self = [super initWithRect:rect])) { return nil; } + options = ofRelativeEvents; buffer = [[DrawBuffer buffer:size] retain]; objects = [[Group withContext:buffer owner:self] retain]; onScroll = [[ListenerGroup listener] retain]; @@ -27,13 +28,13 @@ [icons[0] addch:acs_char (ACS_UARROW)]; [icons[1] addch:acs_char (ACS_DARROW)]; thumbPos = {0, 1}; - thumbSel = @selector(verticalSlide); + thumbSel = @selector(verticalSlide:); growMode &= ~gfGrowLoY; } else { [icons[0] addch:acs_char (ACS_LARROW)]; [icons[1] addch:acs_char (ACS_RARROW)]; thumbPos = {1, 0}; - thumbSel = @selector(horizontalSlide); + thumbSel = @selector(horizontalSlide:); growMode &= ~gfGrowLoX; } bgchar = acs_char (ACS_CKBOARD); @@ -44,8 +45,8 @@ thumbTab = [Button withPos:thumbPos releasedIcon:icons[2] pressedIcon:icons[2]]; - [[backButton onPress] addListener:self :@selector(scrollBack:)]; - [[forwardButton onPress] addListener:self :@selector(scrollForward:)]; + [[backButton onClick] addListener:self :@selector(scrollBack:)]; + [[forwardButton onClick] addListener:self :@selector(scrollForward:)]; [[thumbTab onPress] addListener:self :thumbSel]; singleStep = 1; @@ -86,16 +87,14 @@ -draw { - syncprintf("scrollbar start"); - if (vertical) { - [self mvvline:pos, bgchar, ylen]; - } else { - [self mvhline:pos, bgchar, xlen]; - } [super draw]; + if (vertical) { + [buffer mvvline:{0,0}, bgchar, ylen]; + } else { + [buffer mvhline:{0,0}, bgchar, xlen]; + } [objects draw]; [textContext blitFromBuffer:buffer to:pos from:[buffer rect]]; - syncprintf("scrollbar end"); return self; } @@ -112,6 +111,7 @@ position_tab (ScrollBar *self) } } [self.thumbTab move:{p.x - o.x, p.y - o.y}]; + [self redraw]; } -resize:(Extent)delta @@ -177,6 +177,14 @@ page (ScrollBar *self, Point pos) [self page:singleStep dir:1]; } +-(void)horizontalSlide:(id)sender +{ +} + +-(void)verticalSlide:(id)sender +{ +} + -handleEvent:(qwaq_event_t *)event { [super handleEvent: event]; @@ -224,4 +232,9 @@ page (ScrollBar *self, Point pos) return self; } +-(unsigned)index +{ + return index; +} + @end From 2e1bddb94c0e1df4955fee02d4aa6289bfb75409 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 22:51:18 +0900 Subject: [PATCH 0975/3664] [qwaq] Catch adding bad messages to listeners Better an informative error than a "null function" error. --- ruamoko/qwaq/ui/listener.r | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ruamoko/qwaq/ui/listener.r b/ruamoko/qwaq/ui/listener.r index 5035a4324..3664040d2 100644 --- a/ruamoko/qwaq/ui/listener.r +++ b/ruamoko/qwaq/ui/listener.r @@ -18,6 +18,9 @@ self.responder = responder; self.message = message; imp = [responder methodForSelector: message]; + if (!imp) { + [self error:"method not found: %s", sel_get_name (message)]; + } return self; } From 655ec3e02b9591aa9f142b78f9ea7eb7bd4ced05 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 23:41:20 +0900 Subject: [PATCH 0976/3664] [qwaq] Set event.when for mouseauto events --- ruamoko/qwaq/builtins/curses.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 04ef11516..3075f9412 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -822,6 +822,7 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) was_event = 1; } else if (res->button_state) { event->what = qe_mouseauto; + event->when = Sys_DoubleTime (); event->mouse.buttons = res->button_state; event->mouse.x = res->mouse_x; event->mouse.y = res->mouse_y; From af64e36653dc17cf45774ced5e3d16c3bf84e676 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Mar 2020 23:42:06 +0900 Subject: [PATCH 0977/3664] [qwaq] Get the scrollbar working nicely --- ruamoko/qwaq/editor/editor.r | 1 + ruamoko/qwaq/ui/button.r | 1 + ruamoko/qwaq/ui/scrollbar.h | 2 ++ ruamoko/qwaq/ui/scrollbar.r | 17 +++++++++++------ 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index 64daf5773..0f6e3283c 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -33,6 +33,7 @@ vScrollBar = scrollbar; [vScrollBar setRange:line_count]; + [vScrollBar setPageStep: ylen]; [[vScrollBar onScroll] addListener:self :@selector(onScroll:)]; return self; } diff --git a/ruamoko/qwaq/ui/button.r b/ruamoko/qwaq/ui/button.r index 1d6228571..51e9d36b3 100644 --- a/ruamoko/qwaq/ui/button.r +++ b/ruamoko/qwaq/ui/button.r @@ -117,6 +117,7 @@ if (action) { [action respond: self]; } + event.what = qe_none; } return self; } diff --git a/ruamoko/qwaq/ui/scrollbar.h b/ruamoko/qwaq/ui/scrollbar.h index 190b5a59b..bb0f5c25c 100644 --- a/ruamoko/qwaq/ui/scrollbar.h +++ b/ruamoko/qwaq/ui/scrollbar.h @@ -12,7 +12,9 @@ { int vertical; int bgchar; + double mouseTime; Point mouseStart; + Point tabStart; DrawBuffer *buffer; Button *backButton; Button *forwardButton; diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index e90ad70e7..3364192e9 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -141,24 +141,24 @@ position_tab (ScrollBar *self) } if (index != oind) { - position_tab (self); [onScroll respond:self]; + position_tab (self); } return self; } static void -page (ScrollBar *self, Point pos) +page (ScrollBar *self, Point pos, Point thumb) { unsigned pageDir = 0; if (self.vertical) { - if (pos.y < [self.thumbTab origin].y) { + if (pos.y < thumb.y) { pageDir = 0; } else { pageDir = 1; } } else { - if (pos.x < [self.thumbTab origin].x) { + if (pos.x < thumb.x) { pageDir = 0; } else { pageDir = 1; @@ -191,11 +191,16 @@ page (ScrollBar *self, Point pos) [objects handleEvent: event]; if (event.what == qe_mousedown) { [self grabMouse]; + mouseTime = event.when; mouseStart = {event.mouse.x, event.mouse.y}; - page(self, mouseStart); + tabStart = [thumbTab origin]; + page(self, mouseStart, tabStart); event.what = qe_none; } else if (event.what==qe_mouseauto) { - page(self, mouseStart); + if (event.when - mouseTime > 0.1) { + mouseTime = event.when; + page(self, mouseStart, tabStart); + } event.what = qe_none; } else if (event.what == qe_mouseup) { [self releaseMouse]; From 5bb71c208949c3e3708527960e98b5e7d83b562c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 01:18:16 +0900 Subject: [PATCH 0978/3664] [qwaq] Clean up some debug prints --- ruamoko/qwaq/debugger/debugger.r | 1 - ruamoko/qwaq/debugger/localsview.r | 3 --- 2 files changed, 4 deletions(-) diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 6c16655e8..22a450e10 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -94,7 +94,6 @@ qdb_state_t state = qdb_get_state (target); Editor *file = [self find_file: state.file]; - printf ("%s:%d\n", state.file, state.line); if (current_file != file) { [current_file setVerticalScrollBar:nil]; [[current_file onEvent] removeListener:self :@selector(proxy_event::)]; diff --git a/ruamoko/qwaq/debugger/localsview.r b/ruamoko/qwaq/debugger/localsview.r index f90d429fb..77d2f150f 100644 --- a/ruamoko/qwaq/debugger/localsview.r +++ b/ruamoko/qwaq/debugger/localsview.r @@ -102,9 +102,6 @@ @param value = nil; string valstr = "--"; unsigned offset = func.local_data + def.offset; - printf ("%d %d %s %d\n", def.type_size, offset, - qdb_get_string (target, def.name), - def.type_encoding); qdb_get_data (target, offset, def.type_size >> 16, &value); switch (def.type_size & 0xffff) { case ev_void: From 17da19b979bd256dcc275054a73d2de6aeefd8f2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 01:22:54 +0900 Subject: [PATCH 0979/3664] [qwaq] Set view owner when setting proxy view This fixes the debug editor's redraw issues. --- ruamoko/qwaq/ui/proxyview.r | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ruamoko/qwaq/ui/proxyview.r b/ruamoko/qwaq/ui/proxyview.r index e4a10598e..71a85e36d 100644 --- a/ruamoko/qwaq/ui/proxyview.r +++ b/ruamoko/qwaq/ui/proxyview.r @@ -39,11 +39,13 @@ } [self.view hide]; [self.view setContext:nil]; + [self.view setOwner:nil]; [view retain]; [self.view release]; self.view = view; + [view setOwner:owner]; [view setContext:[owner context]]; if (state & sfDrawn) { [view draw]; From 34706906f5a3aa667e2dca1e4779ba587ca8e7e4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 10:54:15 +0900 Subject: [PATCH 0980/3664] [qwaq] Allow views to be moved/resized without redraw The move is to a specified point and resize to a specified size rather than a delta. --- ruamoko/qwaq/ui/view.h | 2 ++ ruamoko/qwaq/ui/view.r | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/ruamoko/qwaq/ui/view.h b/ruamoko/qwaq/ui/view.h index 09a8ab8ba..4752c4349 100644 --- a/ruamoko/qwaq/ui/view.h +++ b/ruamoko/qwaq/ui/view.h @@ -67,6 +67,8 @@ enum { -move: (Point) delta; -resize: (Extent) delta; -move:(Point)dpos andResize:(Extent)dsize; +-moveTo:(Point)pos; // does not redraw +-resizeTo:(Extent)size; // does not redraw -grow: (Extent) delta; -(ListenerGroup *)onEvent; -handleEvent: (qwaq_event_t *) event; diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index f47d85f63..a6817b81d 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -277,6 +277,18 @@ updateScreenCursor (View *view) return self; } +-moveTo:(Point)pos +{ + self.pos = pos; + return self; +} + +-resizeTo:(Extent)size +{ + self.size = size; + return self; +} + -grow: (Extent) delta { Point dpos = {}; From 4bc6aab7ec6af26d698d6fea9c93a3a6d863ee86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 10:55:18 +0900 Subject: [PATCH 0981/3664] [qwaq] Resize the scrollbar's draw buffer --- ruamoko/qwaq/ui/scrollbar.r | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index 3364192e9..4c080009d 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -120,6 +120,7 @@ position_tab (ScrollBar *self) [super resize:delta]; delta = {self.size.width - size.width, self.size.height - size.height}; [objects resize:delta]; + [buffer resizeTo:self.size]; position_tab (self); return self; } From e15f2097df6301408dde36001333ba866d490adb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 11:21:47 +0900 Subject: [PATCH 0982/3664] [qwaq] Move scroll bar management into View Putting it in Editor worked as a proof of concept, but it seems those always turn out to need tweaking like this because the concept proves itself to be generally worthwhile :P --- ruamoko/qwaq/editor/editor.h | 5 +--- ruamoko/qwaq/editor/editor.r | 53 +++++++++++++++++------------------- ruamoko/qwaq/ui/scrollbar.h | 4 +-- ruamoko/qwaq/ui/scrollbar.r | 10 +++---- ruamoko/qwaq/ui/view.h | 9 ++++++ ruamoko/qwaq/ui/view.r | 44 +++++++++++++++++++++++++++++- 6 files changed, 85 insertions(+), 40 deletions(-) diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index 3a2cd48c5..b5bd4b7d5 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -7,25 +7,22 @@ @class Editor; @class EditBuffer; @class ListenerGroup; -@class ScrollBar; @interface Editor : View { EditBuffer *buffer; DrawBuffer *linebuffer; - ScrollBar *vScrollBar; eb_sel_t selection; unsigned base_index; // top left corner unsigned line_index; // current line unsigned char_index; // current character unsigned old_cind; // previous character - Point scroll; + Point base; Point cursor; unsigned line_count; string filename; } +(Editor *)withRect:(Rect)rect file:(string)filename; --setVerticalScrollBar:(ScrollBar *)scrollbar; -(string)filename; -scrollUp:(unsigned) count; -scrollDown:(unsigned) count; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index 0f6e3283c..d66407564 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -17,6 +17,7 @@ linebuffer = [[DrawBuffer buffer: { xlen, 1 }] retain]; growMode = gfGrowHi; options = ofCanFocus | ofRelativeEvents; + [onViewScrolled addListener:self :@selector(onScroll:)]; return self; } @@ -25,19 +26,6 @@ return [[[self alloc] initWithRect:rect file:filename] autorelease]; } --setVerticalScrollBar:(ScrollBar *)scrollbar -{ - [scrollbar retain]; - [[vScrollBar onScroll] removeListener:self :@selector(onScroll:)]; - [vScrollBar release]; - - vScrollBar = scrollbar; - [vScrollBar setRange:line_count]; - [vScrollBar setPageStep: ylen]; - [[vScrollBar onScroll] addListener:self :@selector(onScroll:)]; - return self; -} - -(void)dealloc { [vScrollBar release]; @@ -57,7 +45,7 @@ unsigned lind = base_index; int *lbuf = [linebuffer buffer]; for (int y = 0; y < ylen; y++) { - lind = [buffer formatLine:lind from:scroll.x into:lbuf width:xlen + lind = [buffer formatLine:lind from:base.x into:lbuf width:xlen highlight:selection colors: {color_palette[047], color_palette[007]}]; [textContext blitFromBuffer: linebuffer to: {xpos, ypos + y} @@ -141,10 +129,10 @@ static int handleEvent (Editor *self, qwaq_event_t *event) -scrollLeft:(unsigned) count { - if (scroll.x > count) { - scroll.x -= count; + if (base.x > count) { + base.x -= count; } else { - scroll.x = 0; + base.x = 0; } [self redraw]; return self; @@ -152,10 +140,10 @@ static int handleEvent (Editor *self, qwaq_event_t *event) -scrollRight:(unsigned) count { - if (1024 - scroll.x > count) { - scroll.x += count; + if (1024 - base.x > count) { + base.x += count; } else { - scroll.x = 1024; + base.x = 1024; } [self redraw]; return self; @@ -163,24 +151,33 @@ static int handleEvent (Editor *self, qwaq_event_t *event) -scrollTo:(unsigned)target { - if (target > scroll.y) { - base_index = [buffer nextLine:base_index :target - scroll.y]; - } else if (target < scroll.y) { - base_index = [buffer prevLine:base_index :scroll.y - target]; + if (target > base.y) { + base_index = [buffer nextLine:base_index :target - base.y]; + } else if (target < base.y) { + base_index = [buffer prevLine:base_index :base.y - target]; } - scroll.y = target; + base.y = target; return self; } -(void)onScroll:(id)sender { - [self scrollTo:[sender index]]; + base.x = scroll.x; + [self scrollTo:scroll.y]; +} + +-setVerticalScrollBar:(ScrollBar *)scrollbar +{ + [super setVerticalScrollBar:scrollbar]; + [vScrollBar setRange:line_count]; + [vScrollBar setPageStep: ylen]; + return self; } -recenter:(int) force { if (!force) { - if (cursor.y >= scroll.y && cursor.y - scroll.y < ylen) { + if (cursor.y >= base.y && cursor.y - base.y < ylen) { return self; } } @@ -221,7 +218,7 @@ static int handleEvent (Editor *self, qwaq_event_t *event) if (pos.x < 0 || pos.y < 0 || pos.x >= xlen || pos.y >= ylen) { return nil; } - pos.x += scroll.x; + pos.x += base.x; unsigned lind = [buffer nextLine:base_index :pos.y]; unsigned cind = [buffer charPtr:lind at:pos.x]; eb_sel_t word = [buffer getWord: cind]; diff --git a/ruamoko/qwaq/ui/scrollbar.h b/ruamoko/qwaq/ui/scrollbar.h index bb0f5c25c..986646878 100644 --- a/ruamoko/qwaq/ui/scrollbar.h +++ b/ruamoko/qwaq/ui/scrollbar.h @@ -20,7 +20,7 @@ Button *forwardButton; Button *thumbTab; Group *objects; - ListenerGroup *onScroll; + ListenerGroup *onScrollBarModified; unsigned pageStep; unsigned singleStep; @@ -29,7 +29,7 @@ } +(ScrollBar *)horizontal:(unsigned)len at:(Point)pos; +(ScrollBar *)vertical:(unsigned)len at:(Point)pos; --(ListenerGroup *)onScroll; +-(ListenerGroup *)onScrollBarModified; -setRange:(unsigned)range; -setPageStep:(unsigned)pageStep; -setSingleStep:(unsigned)singleStep; diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index 4c080009d..411e7d344 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -13,7 +13,7 @@ options = ofRelativeEvents; buffer = [[DrawBuffer buffer:size] retain]; objects = [[Group withContext:buffer owner:self] retain]; - onScroll = [[ListenerGroup listener] retain]; + onScrollBarModified = [[ListenerGroup listener] retain]; vertical = xlen == 1; DrawBuffer *icons[3] = { [DrawBuffer buffer:{1, 1}], @@ -61,7 +61,7 @@ { [objects release]; [buffer release]; - [onScroll release]; + [onScrollBarModified release]; } +(ScrollBar *)horizontal:(unsigned)len at:(Point)pos @@ -80,9 +80,9 @@ return [[[self alloc] initWithRect:{pos, {1, len}}] autorelease]; } --(ListenerGroup *)onScroll +-(ListenerGroup *)onScrollBarModified { - return onScroll; + return onScrollBarModified; } -draw @@ -142,7 +142,7 @@ position_tab (ScrollBar *self) } if (index != oind) { - [onScroll respond:self]; + [onScrollBarModified respond:self]; position_tab (self); } return self; diff --git a/ruamoko/qwaq/ui/view.h b/ruamoko/qwaq/ui/view.h index 4752c4349..e0da51a28 100644 --- a/ruamoko/qwaq/ui/view.h +++ b/ruamoko/qwaq/ui/view.h @@ -10,6 +10,7 @@ @class Group; @class ListenerGroup; +@class ScrollBar; enum { ofCanFocus = 0x0001, @@ -59,6 +60,10 @@ enum { -(int) options; -(int) state; +-setVerticalScrollBar:(ScrollBar *)scrollbar; +-setHorizontalScrollBar:(ScrollBar *)scrollbar; +-(ListenerGroup *) onViewScrolled; + -(id)context; -setContext: (id) context; -draw; @@ -114,6 +119,10 @@ enum { ListenerGroup *onReceiveFocus; ListenerGroup *onReleaseFocus; ListenerGroup *onEvent; + ListenerGroup *onViewScrolled; + ScrollBar *hScrollBar; + ScrollBar *vScrollBar; + Point scroll; } +(View *)viewWithRect:(Rect)rect; +(View *)viewWithRect:(Rect)rect options:(int)options; diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index a6817b81d..ba2f170ad 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -1,7 +1,8 @@ #include "ui/curses.h" #include "ui/listener.h" -#include "ui/view.h" #include "ui/group.h" +#include "ui/scrollbar.h" +#include "ui/view.h" @implementation View @@ -20,6 +21,7 @@ static void view_init(View *self) self.onReceiveFocus = [ListenerGroup listener]; self.onReleaseFocus = [ListenerGroup listener]; self.onEvent = [ListenerGroup listener]; + self.onViewScrolled = [ListenerGroup listener]; } -init @@ -64,6 +66,7 @@ static void view_init(View *self) [onReceiveFocus release]; [onReleaseFocus release]; [onEvent release]; + [onViewScrolled release]; [super dealloc]; } @@ -88,6 +91,40 @@ static void view_init(View *self) return state; } +-(void)onScrollBarModified:(id)sender +{ + if (sender == vScrollBar) { + scroll.y = [sender index]; + } else if (sender == hScrollBar) { + scroll.x = [sender index]; + } + [onViewScrolled respond:self]; +} + +static void +setScrollBar (View *self, ScrollBar **sb, ScrollBar *scrollbar) +{ + SEL sel = @selector(onScrollBarModified:); + [scrollbar retain]; + [[*sb onScrollBarModified] removeListener:self :sel]; + [*sb release]; + + *sb = scrollbar; + [[*sb onScrollBarModified] addListener:self :sel]; +} + +-setVerticalScrollBar:(ScrollBar *)scrollbar +{ + setScrollBar (self, &vScrollBar, scrollbar); + return self; +} + +-setHorizontalScrollBar:(ScrollBar *)scrollbar +{ + setScrollBar (self, &hScrollBar, scrollbar); + return self; +} + static void updateScreenCursor (View *view) { @@ -321,6 +358,11 @@ updateScreenCursor (View *view) return onEvent; } +-(ListenerGroup *) onViewScrolled +{ + return onViewScrolled; +} + -handleEvent: (qwaq_event_t *) event { // give any listeners a chance to override or extend event handling From a1f67b5d6fffdd46a6f28d2e6866ce5fb208263d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 10:55:39 +0900 Subject: [PATCH 0983/3664] [qwaq] Implement a very simple table view class It's nowhere near as sophisticated as NSTableView, but this is text, not graphics. --- ruamoko/qwaq/Makefile.am | 1 + ruamoko/qwaq/ui/tableview.h | 44 +++++++++++++ ruamoko/qwaq/ui/tableview.r | 121 ++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 ruamoko/qwaq/ui/tableview.h create mode 100644 ruamoko/qwaq/ui/tableview.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 94d8c3f95..4f1c84296 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -41,6 +41,7 @@ qwaq_app_dat_src= \ ui/proxyview.r \ ui/rect.r \ ui/scrollbar.r \ + ui/tableview.r \ ui/textcontext.r \ ui/titlebar.r \ ui/view.r \ diff --git a/ruamoko/qwaq/ui/tableview.h b/ruamoko/qwaq/ui/tableview.h new file mode 100644 index 000000000..b21279b0a --- /dev/null +++ b/ruamoko/qwaq/ui/tableview.h @@ -0,0 +1,44 @@ +#ifndef __qwaq_ui_tableview_h +#define __qwaq_ui_tableview_h + +#include "ui/view.h" + +@class DrawBuffer; +@class TableView; +@class TableViewColumn; +@class Array; + +@protocol TableViewDataSource +-(int)numberOfRows:(TableView *)tableview; +-(View *)tableView:(TableView *)tableView + forColumn:(TableViewColumn *)column + row:(int)row; +-retain; +-release; +@end + +@interface TableViewColumn : Object +{ + string name; + int width; +} ++(TableViewColumn *)named:(string)name; ++(TableViewColumn *)named:(string)name width:(int)width; +-(string)name; +-(int)width; +@end + +@interface TableView : View +{ + Array *columns; + DrawBuffer *buffer; + int columns_dirty; + id dataSource; + Point base; +} ++(TableView *)withRect:(Rect)rect; +-addColumn:(TableViewColumn *)column; +-setDataSource:(id)dataSource; +@end + +#endif//__qwaq_ui_tableview_h diff --git a/ruamoko/qwaq/ui/tableview.r b/ruamoko/qwaq/ui/tableview.r new file mode 100644 index 000000000..fa2772eae --- /dev/null +++ b/ruamoko/qwaq/ui/tableview.r @@ -0,0 +1,121 @@ +#include +#include "ui/listener.h" +#include "ui/tableview.h" + +@implementation TableViewColumn +-initWithName:(string)name width:(int)width +{ + if (!(self = [super init])) { + return nil; + } + self.name = name; + self.width = width; + return self; +} + ++(TableViewColumn *)named:(string)name +{ + return [[[self alloc] initWithName:name width:-1] autorelease]; +} + ++(TableViewColumn *)named:(string)name width:(int)width +{ + return [[[self alloc] initWithName:name width:width] autorelease]; +} + +-(string)name +{ + return name; +} + +-(int)width +{ + return width; +} + +-setWidth:(int)width +{ + self.width = width; + return self; +} +@end + +@implementation TableView +-initWithRect:(Rect)rect +{ + if (!(self = [super initWithRect:rect])) { + return nil; + } + options = ofCanFocus | ofRelativeEvents; + columns = [[Array array] retain]; + buffer = [[DrawBuffer buffer:size] retain]; + [onViewScrolled addListener:self :@selector(onScroll:)]; + return self; +} + +-(void)dealloc +{ + [columns release]; + [buffer release]; + [dataSource release]; +} + ++(TableView *)withRect:(Rect)rect +{ + return [[[self alloc] initWithRect:rect] autorelease]; +} + +-addColumn:(TableViewColumn *)column +{ + [columns addObject:column]; + columns_dirty = 1; + return self; +} + +-setDataSource:(id)dataSource +{ + self.dataSource = [dataSource retain]; + return self; +} + +-resize:(Extent)delta +{ + Extent size = self.size; + [super resize:delta]; + [buffer resizeTo:self.size]; + return self; +} + +-draw +{ + View *cell; + TableViewColumn *col; + [super draw]; + int numCols = [columns count]; + int numRows = [dataSource numberOfRows:self]; + [buffer clear]; + for (int y = 0; y < ylen; y++) { + for (int i = 0, x = 0; i < numCols; i++) { + int row = base.y + y; + if (row >= numRows) { + break; + } + col = [columns objectAtIndex:i]; + cell = [dataSource tableView:self forColumn:col row:row]; + [[[cell setContext:buffer] moveTo:{x, y}] draw]; + x += [col width]; + } + } + [textContext blitFromBuffer:buffer to:pos from:[buffer rect]]; + return self; +} + +-(void)onScroll:(id)sender +{ + if (base.y != scroll.y) { + base.y = scroll.y; + [self redraw]; + } +} + +@end From 59481bdf613f705d96a742dbbe0326ea547e2229 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 13:56:40 +0900 Subject: [PATCH 0984/3664] [ruamoko] Report class name in obj_verror --- libs/ruamoko/rua_obj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 5bd5e3871..53b4d3e80 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1021,10 +1021,11 @@ obj_verror (probj_t *probj, pr_id_t *object, int code, const char *fmt, int coun pr_type_t **args) { progs_t *pr = probj->pr; + __auto_type class = &G_STRUCT (pr, pr_class_t, object->class_pointer); dstring_t *dstr = dstring_newstr (); PR_Sprintf (pr, dstr, "obj_verror", fmt, count, args); - PR_RunError (pr, "%s", dstr->str); + PR_RunError (pr, "%s: %s", PR_GetString (pr, class->name), dstr->str); } static void From 7ca3dc9db1422126e0968c61c631da25b3b72687 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 13:57:22 +0900 Subject: [PATCH 0985/3664] [qwaq] Fix some missed retain/release messages --- ruamoko/qwaq/ui/button.r | 30 ++++++++++++++++++------------ ruamoko/qwaq/ui/view.r | 8 ++++---- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/ruamoko/qwaq/ui/button.r b/ruamoko/qwaq/ui/button.r index 51e9d36b3..f2951d2f2 100644 --- a/ruamoko/qwaq/ui/button.r +++ b/ruamoko/qwaq/ui/button.r @@ -26,12 +26,12 @@ } icon[0] = [released retain]; icon[1] = [pressed retain]; - onPress = [ListenerGroup listener]; - onRelease = [ListenerGroup listener]; - onClick = [ListenerGroup listener]; - onDrag = [ListenerGroup listener]; - onAuto = [ListenerGroup listener]; - onHover = [ListenerGroup listener]; + onPress = [[ListenerGroup listener] retain]; + onRelease = [[ListenerGroup listener] retain]; + onClick = [[ListenerGroup listener] retain]; + onDrag = [[ListenerGroup listener] retain]; + onAuto = [[ListenerGroup listener] retain]; + onHover = [[ListenerGroup listener] retain]; return self; } @@ -42,12 +42,12 @@ } icon[0] = nil; icon[1] = nil; - onPress = [ListenerGroup listener]; - onRelease = [ListenerGroup listener]; - onClick = [ListenerGroup listener]; - onDrag = [ListenerGroup listener]; - onAuto = [ListenerGroup listener]; - onHover = [ListenerGroup listener]; + onPress = [[ListenerGroup listener] retain]; + onRelease = [[ListenerGroup listener] retain]; + onClick = [[ListenerGroup listener] retain]; + onDrag = [[ListenerGroup listener] retain]; + onAuto = [[ListenerGroup listener] retain]; + onHover = [[ListenerGroup listener] retain]; return self; } @@ -55,6 +55,12 @@ { [icon[0] release]; [icon[1] release]; + [onPress release]; + [onRelease release]; + [onClick release]; + [onDrag release]; + [onAuto release]; + [onHover release]; [super dealloc]; } diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index ba2f170ad..5dc0da9e6 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -18,10 +18,10 @@ static void view_init(View *self) { - self.onReceiveFocus = [ListenerGroup listener]; - self.onReleaseFocus = [ListenerGroup listener]; - self.onEvent = [ListenerGroup listener]; - self.onViewScrolled = [ListenerGroup listener]; + self.onReceiveFocus = [[ListenerGroup listener] retain]; + self.onReleaseFocus = [[ListenerGroup listener] retain]; + self.onEvent = [[ListenerGroup listener] retain]; + self.onViewScrolled = [[ListenerGroup listener] retain]; } -init From e2d1a0f7d255a101543094d81d6552ab599c8e45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 16:03:54 +0900 Subject: [PATCH 0986/3664] [ruamoko] Tag object memory with the class name This makes it a lot easier to see what's leaking. --- include/QF/progs.h | 1 + libs/gamecode/pr_zone.c | 9 +++++++++ libs/ruamoko/rua_obj.c | 4 ++-- libs/util/zone.c | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 7567ddc09..95d5db44c 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1614,6 +1614,7 @@ void PR_Zone_Init (progs_t *pr); void PR_Zone_Free (progs_t *pr, void *ptr); void *PR_Zone_Malloc (progs_t *pr, pr_int_t size); void *PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size); +void *PR_Zone_TagMalloc (progs_t *pr, int size, int tag); ///@} diff --git a/libs/gamecode/pr_zone.c b/libs/gamecode/pr_zone.c index e7239bc0c..5b85a7ffd 100644 --- a/libs/gamecode/pr_zone.c +++ b/libs/gamecode/pr_zone.c @@ -49,6 +49,7 @@ static void pr_zone_error (void *_pr, const char *msg) { progs_t *pr = (progs_t *) _pr; + Z_Print (pr->zone); PR_RunError (pr, "%s", msg); } @@ -74,6 +75,14 @@ PR_Zone_Malloc (progs_t *pr, pr_int_t size) return Z_Malloc (pr->zone, size); } +VISIBLE void * +PR_Zone_TagMalloc (progs_t *pr, int size, int tag) +{ + if (size <= 0) + PR_RunError (pr, "attempt to allocate less than 1 byte"); + return Z_TagMalloc (pr->zone, size, tag); +} + VISIBLE void * PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size) { diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 53b4d3e80..91b9e5692 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1702,8 +1702,8 @@ class_create_instance (progs_t *pr, pr_class_t *class) pr_type_t *mem; pr_id_t *id; - mem = PR_Zone_Malloc (pr, size); - // redundant memset (id, 0, size); + mem = PR_Zone_TagMalloc (pr, size, class->name); + memset (mem, 0, size); id = (pr_id_t *) (mem + 1); id->class_pointer = PR_SetPointer (pr, class); return id; diff --git a/libs/util/zone.c b/libs/util/zone.c index f5c90a379..40af412ba 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -337,7 +337,7 @@ Z_Print (memzone_t *zone) zone->size, zone, zone->used); for (block = zone->blocklist.next ; ; block = block->next) { - Sys_Printf ("block:%p size:%7i tag:%3i ofs:%x\n", + Sys_Printf ("block:%p size:%7i tag:%5x ofs:%x\n", block, z_block_size (block), block->tag, z_offset (zone, block)); From 58acc483fdf69f9f8b2c86b7c8b8fde24fa0ed44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 20:38:41 +0900 Subject: [PATCH 0987/3664] [gamecode] Save new string ref in return slot This plugs the memory leak that caused qwaq to crash after resizing the locals window a "few" times (several seconds of playing with the size). --- libs/gamecode/pr_strings.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 194dbc05c..7781865a7 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -468,6 +468,7 @@ PR_SetReturnString (progs_t *pr, const char *s) pr_strfree (pr, sr->s.string); } else { sr = new_string_ref (res); + res->rs_slot->strref = sr; } sr->type = str_return; sr->rs_slot = res->rs_slot; From 0da92e33f6fb78e3f6ba2e6800763fad7f7b9186 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 20:48:38 +0900 Subject: [PATCH 0988/3664] [qwaq] Use TableView to show locals This is much nicer (even though things aren't quite right yet) --- ruamoko/qwaq/Makefile.am | 17 +- ruamoko/qwaq/debugger/basicview.h | 11 ++ ruamoko/qwaq/debugger/basicview.r | 48 ++++++ ruamoko/qwaq/debugger/debugger.h | 8 +- ruamoko/qwaq/debugger/debugger.r | 21 ++- ruamoko/qwaq/debugger/defview.h | 15 ++ ruamoko/qwaq/debugger/defview.r | 52 ++++++ ruamoko/qwaq/debugger/doubleview.h | 13 ++ ruamoko/qwaq/debugger/doubleview.r | 28 ++++ ruamoko/qwaq/debugger/entityview.h | 13 ++ ruamoko/qwaq/debugger/entityview.r | 28 ++++ ruamoko/qwaq/debugger/fieldview.h | 13 ++ ruamoko/qwaq/debugger/fieldview.r | 28 ++++ ruamoko/qwaq/debugger/floatview.h | 13 ++ ruamoko/qwaq/debugger/floatview.r | 28 ++++ ruamoko/qwaq/debugger/funcview.h | 13 ++ ruamoko/qwaq/debugger/funcview.r | 28 ++++ ruamoko/qwaq/debugger/intview.h | 13 ++ ruamoko/qwaq/debugger/intview.r | 28 ++++ .../debugger/{localsview.h => localsdata.h} | 7 +- ruamoko/qwaq/debugger/localsdata.r | 100 +++++++++++ ruamoko/qwaq/debugger/localsview.r | 156 ------------------ ruamoko/qwaq/debugger/nameview.h | 13 ++ ruamoko/qwaq/debugger/nameview.r | 33 ++++ ruamoko/qwaq/debugger/pointerview.h | 13 ++ ruamoko/qwaq/debugger/pointerview.r | 28 ++++ ruamoko/qwaq/debugger/quatview.h | 13 ++ ruamoko/qwaq/debugger/quatview.r | 28 ++++ ruamoko/qwaq/debugger/stringview.h | 13 ++ ruamoko/qwaq/debugger/stringview.r | 28 ++++ ruamoko/qwaq/debugger/typeencodings.r | 1 - ruamoko/qwaq/debugger/uintview.h | 13 ++ ruamoko/qwaq/debugger/uintview.r | 28 ++++ ruamoko/qwaq/debugger/vectorview.h | 13 ++ ruamoko/qwaq/debugger/vectorview.r | 28 ++++ ruamoko/qwaq/debugger/voidview.h | 13 ++ ruamoko/qwaq/debugger/voidview.r | 29 ++++ ruamoko/qwaq/ui/listener.r | 7 + ruamoko/qwaq/ui/scrollbar.r | 1 + ruamoko/qwaq/ui/tableview.r | 2 + ruamoko/qwaq/ui/view.r | 23 ++- 41 files changed, 824 insertions(+), 184 deletions(-) create mode 100644 ruamoko/qwaq/debugger/basicview.h create mode 100644 ruamoko/qwaq/debugger/basicview.r create mode 100644 ruamoko/qwaq/debugger/defview.h create mode 100644 ruamoko/qwaq/debugger/defview.r create mode 100644 ruamoko/qwaq/debugger/doubleview.h create mode 100644 ruamoko/qwaq/debugger/doubleview.r create mode 100644 ruamoko/qwaq/debugger/entityview.h create mode 100644 ruamoko/qwaq/debugger/entityview.r create mode 100644 ruamoko/qwaq/debugger/fieldview.h create mode 100644 ruamoko/qwaq/debugger/fieldview.r create mode 100644 ruamoko/qwaq/debugger/floatview.h create mode 100644 ruamoko/qwaq/debugger/floatview.r create mode 100644 ruamoko/qwaq/debugger/funcview.h create mode 100644 ruamoko/qwaq/debugger/funcview.r create mode 100644 ruamoko/qwaq/debugger/intview.h create mode 100644 ruamoko/qwaq/debugger/intview.r rename ruamoko/qwaq/debugger/{localsview.h => localsdata.h} (67%) create mode 100644 ruamoko/qwaq/debugger/localsdata.r delete mode 100644 ruamoko/qwaq/debugger/localsview.r create mode 100644 ruamoko/qwaq/debugger/nameview.h create mode 100644 ruamoko/qwaq/debugger/nameview.r create mode 100644 ruamoko/qwaq/debugger/pointerview.h create mode 100644 ruamoko/qwaq/debugger/pointerview.r create mode 100644 ruamoko/qwaq/debugger/quatview.h create mode 100644 ruamoko/qwaq/debugger/quatview.r create mode 100644 ruamoko/qwaq/debugger/stringview.h create mode 100644 ruamoko/qwaq/debugger/stringview.r create mode 100644 ruamoko/qwaq/debugger/uintview.h create mode 100644 ruamoko/qwaq/debugger/uintview.r create mode 100644 ruamoko/qwaq/debugger/vectorview.h create mode 100644 ruamoko/qwaq/debugger/vectorview.r create mode 100644 ruamoko/qwaq/debugger/voidview.h create mode 100644 ruamoko/qwaq/debugger/voidview.r diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index 4f1c84296..b4e513314 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -27,9 +27,24 @@ SUFFIXES=.o .r qwaq_app_dat_src= \ qwaq-app.r \ + debugger/defview.r \ + debugger/nameview.r \ + debugger/basicview.r \ + debugger/doubleview.r \ + debugger/entityview.r \ + debugger/fieldview.r \ + debugger/floatview.r \ + debugger/funcview.r \ + debugger/intview.r \ + debugger/pointerview.r \ + debugger/quatview.r \ + debugger/stringview.r \ + debugger/uintview.r \ + debugger/vectorview.r \ + debugger/voidview.r \ debugger/debug.r \ debugger/debugger.r \ - debugger/localsview.r \ + debugger/localsdata.r \ debugger/typeencodings.r \ editor/editbuffer.r \ editor/editor.r \ diff --git a/ruamoko/qwaq/debugger/basicview.h b/ruamoko/qwaq/debugger/basicview.h new file mode 100644 index 000000000..773ab6794 --- /dev/null +++ b/ruamoko/qwaq/debugger/basicview.h @@ -0,0 +1,11 @@ +#ifndef __qwaq_debugger_basicview_h +#define __qwaq_debugger_basicview_h + +#include "debugger/defview.h" + +@interface BasicView : DefView +// might return a NameView (which is also a DefView) ++(DefView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_basicview_h diff --git a/ruamoko/qwaq/debugger/basicview.r b/ruamoko/qwaq/debugger/basicview.r new file mode 100644 index 000000000..4404f43e6 --- /dev/null +++ b/ruamoko/qwaq/debugger/basicview.r @@ -0,0 +1,48 @@ +#include +#include "debugger/basicview.h" +#include "debugger/nameview.h" + +static string type_views[] = { + "VoidView", + "StringView", + "FloatView", + "VectorView", + "EntityView", + "FieldView", + "FuncView", + "PointerView", + "QuatView", + "IntView", + "UIntView", // uinteger + "IntView", // short + "DoubleView", +}; + +@implementation BasicView + +-init +{ + if (!(self = [super init])) { + return nil; + } + return self; +} + ++(DefView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + string typename = nil; + if (type.type == ty_alias) { + type = type.alias.aux_type; + } + if (type.type >= 0 + && type.type < sizeof(type_views) / sizeof (type_views[0])) { + typename = type_views[type.type]; + } + id class = obj_lookup_class (typename); + if (class) { + return [class withType:type at:offset in:data]; + } + return [NameView withName:"Invalid Meta"]; +} + +@end diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 0b3b75f50..9e827c73d 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -5,26 +5,28 @@ #include #include "debugger/debug.h" -#include "debugger/localsview.h" +#include "debugger/localsdata.h" @class ProxyView; @class Editor; @class ScrollBar; @class Window; @class Array; +@class TableView; @interface Debugger : Object { qdb_target_t target; Window *source_window; + ScrollBar *source_scrollbar; ProxyView *file_proxy; Array *files; Editor *current_file; Window *locals_window; - ScrollBar *scrollbar; - LocalsView *locals_view; + LocalsData *locals_data; + TableView *locals_view; } +(Debugger *)withTarget:(qdb_target_t)target; -initWithTarget:(qdb_target_t) target; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 22a450e10..85ae89efd 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -7,6 +7,7 @@ #include "ui/listener.h" #include "ui/proxyview.h" #include "ui/scrollbar.h" +#include "ui/tableview.h" #include "ui/window.h" #include "debugger/debugger.h" #include "debugger/typeencodings.h" @@ -36,8 +37,8 @@ source_window = [Window withRect: {nil, s}]; [application addView:source_window]; - scrollbar = [ScrollBar vertical:s.height - 2 at:{s.width - 1, 1}]; - [source_window insert:scrollbar]; + source_scrollbar = [ScrollBar vertical:s.height - 2 at:{s.width - 1, 1}]; + [source_window insert:source_scrollbar]; return self; } @@ -45,6 +46,7 @@ -(void)dealloc { [files release]; + [locals_data release]; [super dealloc]; } @@ -73,7 +75,7 @@ file_proxy = [ProxyView withView: current_file]; [[current_file gotoLine:state.line - 1] highlightLine]; [[current_file onEvent] addListener: self :@selector(proxy_event::)]; - [current_file setVerticalScrollBar:scrollbar]; + [current_file setVerticalScrollBar:source_scrollbar]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; [source_window setTitle: [current_file filename]]; @@ -82,8 +84,15 @@ locals_window = [Window withRect:{{0, 0}, {40, 10}}]; [locals_window setBackground: color_palette[064]]; [locals_window setTitle: "Locals"]; - locals_view = [LocalsView withRect:{{1, 1}, {38, 8}} target:target]; + locals_data = [[LocalsData withTarget:target] retain]; + locals_view = [TableView withRect:{{1, 1}, {38, 8}}]; + [locals_view addColumn:[TableViewColumn named:"name" width:12]]; + [locals_view addColumn:[TableViewColumn named:"value" width:26]]; + ScrollBar *sb = [ScrollBar vertical:8 at:{39, 1}]; + [locals_view setVerticalScrollBar:sb]; + [locals_view setDataSource:locals_data]; [locals_window insertSelected: locals_view]; + [locals_window insert: sb]; [application addView: locals_window]; [[locals_view onEvent] addListener:self :@selector(proxy_event::)]; @@ -99,7 +108,7 @@ [[current_file onEvent] removeListener:self :@selector(proxy_event::)]; [file_proxy setView:file]; [[file onEvent] addListener:self :@selector(proxy_event::)]; - [file setVerticalScrollBar:scrollbar]; + [file setVerticalScrollBar:source_scrollbar]; [source_window setTitle: [file filename]]; current_file = file; } @@ -110,7 +119,7 @@ -(void)update_watchvars { qdb_state_t state = qdb_get_state (target); - [locals_view setFunction:state.func]; + [locals_data setFunction:state.func]; [locals_view redraw]; } diff --git a/ruamoko/qwaq/debugger/defview.h b/ruamoko/qwaq/debugger/defview.h new file mode 100644 index 000000000..69553620b --- /dev/null +++ b/ruamoko/qwaq/debugger/defview.h @@ -0,0 +1,15 @@ +#ifndef __qwaq_debugger_defview_h +#define __qwaq_debugger_defview_h + +#include +#include "ui/view.h" + +@interface DefView : View +{ + qfot_type_t *type; +} ++(DefView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +-initWithType:(qfot_type_t *)type; +@end + +#endif//__qwaq_debugger_defview_h diff --git a/ruamoko/qwaq/debugger/defview.r b/ruamoko/qwaq/debugger/defview.r new file mode 100644 index 000000000..5768a14f5 --- /dev/null +++ b/ruamoko/qwaq/debugger/defview.r @@ -0,0 +1,52 @@ +#include +#include "debugger/defview.h" +#include "debugger/nameview.h" + +static string meta_views[] = { + "BasicView", + "StructView", + "UnionView", + "EnumView", + "ArrayView", + "ClassView", + "AliasView", // shouldn't happen, but... +}; + +@implementation DefView + +-init +{ + if (!(self = [super init])) { + return nil; + } + return self; +} + +-initWithType:(qfot_type_t *)type +{ + if (!(self = [super init])) { + return nil; + } + self.type = type; + return self; +} + ++(DefView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + string metaname = nil; + //printf("%d %d %d %d\n", type.meta, type.size, type.encoding, type.type); + if (type.meta == ty_alias) { + type = type.alias.aux_type; + } + if (type.meta >= 0 + && type.meta < sizeof(meta_views) / sizeof (meta_views[0])) { + metaname = meta_views[type.meta]; + } + id class = obj_lookup_class (metaname); + if (class) { + return [class withType:type at:offset in:data]; + } + return [NameView withName:"Invalid Meta"]; +} + +@end diff --git a/ruamoko/qwaq/debugger/doubleview.h b/ruamoko/qwaq/debugger/doubleview.h new file mode 100644 index 000000000..0ddea40c1 --- /dev/null +++ b/ruamoko/qwaq/debugger/doubleview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_doubleview_h +#define __qwaq_debugger_doubleview_h + +#include "debugger/defview.h" + +@interface DoubleView : DefView +{ + double *data; +} ++(DoubleView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_doubleview_h diff --git a/ruamoko/qwaq/debugger/doubleview.r b/ruamoko/qwaq/debugger/doubleview.r new file mode 100644 index 000000000..2a76033b5 --- /dev/null +++ b/ruamoko/qwaq/debugger/doubleview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/doubleview.h" + +@implementation DoubleView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (double *)(data + offset); + return self; +} + ++(DoubleView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("%.17g", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/entityview.h b/ruamoko/qwaq/debugger/entityview.h new file mode 100644 index 000000000..81ba29e9c --- /dev/null +++ b/ruamoko/qwaq/debugger/entityview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_entityview_h +#define __qwaq_debugger_entityview_h + +#include "debugger/defview.h" + +@interface EntityView : DefView +{ + entity *data; +} ++(EntityView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_entityview_h diff --git a/ruamoko/qwaq/debugger/entityview.r b/ruamoko/qwaq/debugger/entityview.r new file mode 100644 index 000000000..6990886e6 --- /dev/null +++ b/ruamoko/qwaq/debugger/entityview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/entityview.h" + +@implementation EntityView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (entity *)(data + offset); + return self; +} + ++(EntityView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("FIXME [%x]", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/fieldview.h b/ruamoko/qwaq/debugger/fieldview.h new file mode 100644 index 000000000..bf793ec00 --- /dev/null +++ b/ruamoko/qwaq/debugger/fieldview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_fieldview_h +#define __qwaq_debugger_fieldview_h + +#include "debugger/defview.h" + +@interface FieldView : DefView +{ + unsigned *data; +} ++(FieldView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_fieldview_h diff --git a/ruamoko/qwaq/debugger/fieldview.r b/ruamoko/qwaq/debugger/fieldview.r new file mode 100644 index 000000000..ea00ff14f --- /dev/null +++ b/ruamoko/qwaq/debugger/fieldview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/fieldview.h" + +@implementation FieldView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (unsigned *)(data + offset); + return self; +} + ++(FieldView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("FIXME [%x]", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/floatview.h b/ruamoko/qwaq/debugger/floatview.h new file mode 100644 index 000000000..4fa32be05 --- /dev/null +++ b/ruamoko/qwaq/debugger/floatview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_floatview_h +#define __qwaq_debugger_floatview_h + +#include "debugger/defview.h" + +@interface FloatView : DefView +{ + float *data; +} ++(FloatView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_floatview_h diff --git a/ruamoko/qwaq/debugger/floatview.r b/ruamoko/qwaq/debugger/floatview.r new file mode 100644 index 000000000..1e90f8320 --- /dev/null +++ b/ruamoko/qwaq/debugger/floatview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/floatview.h" + +@implementation FloatView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (float *)(data + offset); + return self; +} + ++(FloatView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("%.9", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/funcview.h b/ruamoko/qwaq/debugger/funcview.h new file mode 100644 index 000000000..43cce6512 --- /dev/null +++ b/ruamoko/qwaq/debugger/funcview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_funcview_h +#define __qwaq_debugger_funcview_h + +#include "debugger/defview.h" + +@interface FuncView : DefView +{ + unsigned *data; +} ++(FuncView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_funcview_h diff --git a/ruamoko/qwaq/debugger/funcview.r b/ruamoko/qwaq/debugger/funcview.r new file mode 100644 index 000000000..b9f540807 --- /dev/null +++ b/ruamoko/qwaq/debugger/funcview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/funcview.h" + +@implementation FuncView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (unsigned *)(data + offset); + return self; +} + ++(FuncView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("FIXME [%x]", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/intview.h b/ruamoko/qwaq/debugger/intview.h new file mode 100644 index 000000000..531da879d --- /dev/null +++ b/ruamoko/qwaq/debugger/intview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_intview_h +#define __qwaq_debugger_intview_h + +#include "debugger/defview.h" + +@interface IntView : DefView +{ + int *data; +} ++(IntView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_intview_h diff --git a/ruamoko/qwaq/debugger/intview.r b/ruamoko/qwaq/debugger/intview.r new file mode 100644 index 000000000..aeedd0640 --- /dev/null +++ b/ruamoko/qwaq/debugger/intview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/intview.h" + +@implementation IntView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (int *)(data + offset); + return self; +} + ++(IntView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("%d", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/localsview.h b/ruamoko/qwaq/debugger/localsdata.h similarity index 67% rename from ruamoko/qwaq/debugger/localsview.h rename to ruamoko/qwaq/debugger/localsdata.h index 71886daaf..976b2ecf1 100644 --- a/ruamoko/qwaq/debugger/localsview.h +++ b/ruamoko/qwaq/debugger/localsdata.h @@ -2,10 +2,10 @@ #define __qwaq_debugger_localsview_h #include -#include "ui/view.h" +#include "ui/tableview.h" #include "debugger/debug.h" -@interface LocalsView : View +@interface LocalsData : Object { qdb_target_t target; qfot_type_encodings_t target_encodings; @@ -15,8 +15,7 @@ qdb_def_t *defs; void *data; } -+(LocalsView *)withRect:(Rect)rect target:(qdb_target_t)target; --initWithRect:(Rect)rect target:(qdb_target_t)target; ++(LocalsData *)withTarget:(qdb_target_t)target; -setFunction:(unsigned)fnum; @end diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r new file mode 100644 index 000000000..48019aaed --- /dev/null +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -0,0 +1,100 @@ +#include +#include +#include "debugger/defview.h" +#include "debugger/nameview.h" +#include "debugger/localsdata.h" +#include "debugger/typeencodings.h" + +@implementation LocalsData + +-initWithTarget:(qdb_target_t) target +{ + if (!(self = [super init])) { + return nil; + } + self.target = target; + + qdb_def_t encodings_def = qdb_find_global (target, ".type_encodings"); + qdb_get_data (target, encodings_def.offset, sizeof(target_encodings), + &target_encodings); + + return self; +} + ++(LocalsData *)withTarget:(qdb_target_t)target +{ + return [[[self alloc] initWithTarget:target] autorelease]; +} + +-(void)dealloc +{ + if (defs) { + obj_free (defs); + defs = nil; + } + if (data) { + obj_free (data); + data = nil; + } +} + +-setFunction:(unsigned) fnum +{ + if (current_fnum == fnum) { + return self; + } + current_fnum =fnum; + + if (defs) { + obj_free (defs); + defs = nil; + } + if (data) { + obj_free (data); + data = nil; + } + func = qdb_get_function (target, fnum); + aux_func = qdb_get_auxfunction (target, fnum); + if (aux_func) { + defs = qdb_get_local_defs (target, fnum); + } + if (func) { + data = obj_malloc (func.local_size); + } + return self; +} + +-(int)numberOfRows:(TableView *)tableview +{ + if (aux_func) { + return aux_func.num_locals; + } else if (func) { + return (func.local_size + 3) / 4; + } + return 0; +} + +-(qfot_type_t *)type:(qdb_def_t *)def +{ + unsigned encoding = def.type_encoding + (unsigned) target_encodings.types; + return [TypeEncodings getType:encoding fromTarget:target]; +} + +-(View *)tableView:(TableView *)tableview + forColumn:(TableViewColumn *)column + row:(int)row +{ + View *view; + + if ([column name] == "name") { + view = [NameView withName:qdb_get_string (target, defs[row].name)]; + } else { + qfot_type_t *type = [self type:&defs[row]]; + unsigned offset = defs[row].offset; + view = [DefView withType:type at:offset in:data]; + } + [view resizeTo:{[column width], 1}]; + return view; +} + +@end diff --git a/ruamoko/qwaq/debugger/localsview.r b/ruamoko/qwaq/debugger/localsview.r deleted file mode 100644 index 77d2f150f..000000000 --- a/ruamoko/qwaq/debugger/localsview.r +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include "debugger/localsview.h" -#include "debugger/typeencodings.h" - -@implementation LocalsView - -+(LocalsView *)withRect:(Rect)rect target:(qdb_target_t)target -{ - return [[[self alloc] initWithRect:rect target:target] autorelease]; -} - --initWithRect:(Rect)rect target:(qdb_target_t) target -{ - if (!(self = [super initWithRect:rect])) { - return nil; - } - options = ofCanFocus; - growMode = gfGrowHi; - - self.target = target; - - qdb_def_t encodings_def = qdb_find_global (target, ".type_encodings"); - qdb_get_data (target, encodings_def.offset, sizeof(target_encodings), - &target_encodings); - - return self; -} - --(void)dealloc -{ - if (defs) { - obj_free (defs); - defs = nil; - } - if (data) { - obj_free (data); - data = nil; - } -} - --setFunction:(unsigned) fnum -{ - if (current_fnum == fnum) { - return self; - } - current_fnum =fnum; - - if (defs) { - obj_free (defs); - defs = nil; - } - if (data) { - obj_free (data); - data = nil; - } - func = qdb_get_function (target, fnum); - aux_func = qdb_get_auxfunction (target, fnum); - if (aux_func) { - defs = qdb_get_local_defs (target, fnum); - } - if (func) { - data = obj_malloc (func.local_size); - } - return self; -} - --draw -{ - [super draw]; - - if (!data) { - return self; - } - qdb_get_data (target, func.local_data, func.local_size, data); - [self clear]; - if (!defs) { - [self mvprintf:{0,0}, "%d", func.local_size]; - for (int y = 1; y < ylen; y++) { - unsigned ind = (y - 1) * 4; - if (ind < func.local_size) { - [self mvprintf:{0, y}, "%02x", ind]; - for (int x = 0; x < 4 && ind < func.local_size; x++, ind++) { - [self mvprintf:{x * 9 + 3, y}, "%08x", - data[ind]]; - } - } else { - break; - } - } - } else { - for (int y = 0; y < ylen; y++) { - if (y >= aux_func.num_locals) { - break; - } - qdb_def_t *def = defs + y; - unsigned te = def.type_encoding + (int) target_encodings.types; - qfot_type_t *type; - type = [TypeEncodings getType:te fromTarget:target]; - [self mvprintf:{0, y}, "%s", - qdb_get_string (target, def.name)]; - @param value = nil; - string valstr = "--"; - unsigned offset = func.local_data + def.offset; - qdb_get_data (target, offset, def.type_size >> 16, &value); - switch (def.type_size & 0xffff) { - case ev_void: - case ev_invalid: - case ev_type_count: - break; - case ev_string: - valstr = qdb_get_string (target, value.integer_val); - break; - case ev_float: - valstr = sprintf ("%.9g", value.float_val); - break; - case ev_vector: - valstr = sprintf ("%.9v", value.vector_val); - break; - case ev_entity: - valstr = sprintf ("%e", value.entity_val); - break; - case ev_field: - valstr = sprintf ("[%x]", value.field_val); - break; - case ev_func: - valstr = sprintf ("[%x]", value.func_val); - break; - case ev_pointer: - valstr = sprintf ("[%x]", value.pointer_val); - break; - case ev_quat: - valstr = sprintf ("[%q]", value.quaternion_val); - break; - case ev_integer: - valstr = sprintf ("%d", value.integer_val); - break; - case ev_uinteger: - valstr = sprintf ("%d", value.integer_val); - break; - case ev_short: - valstr = sprintf ("%d", value.integer_val); - break; - case ev_double: - valstr = sprintf ("%.17g", value.double_val); - break; - } - int x = xlen - strlen (valstr); - [self mvaddstr:{x, y}, valstr]; - } - } - - return self; -} - -@end diff --git a/ruamoko/qwaq/debugger/nameview.h b/ruamoko/qwaq/debugger/nameview.h new file mode 100644 index 000000000..1822df98e --- /dev/null +++ b/ruamoko/qwaq/debugger/nameview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_nameview_h +#define __qwaq_debugger_nameview_h + +#include "debugger/defview.h" + +@interface NameView : DefView +{ + string name; +} ++(NameView *)withName:(string)name; +@end + +#endif//__qwaq_debugger_nameview_h diff --git a/ruamoko/qwaq/debugger/nameview.r b/ruamoko/qwaq/debugger/nameview.r new file mode 100644 index 000000000..52710170a --- /dev/null +++ b/ruamoko/qwaq/debugger/nameview.r @@ -0,0 +1,33 @@ +#include +#include "debugger/nameview.h" + +@implementation NameView + +-initWithName:(string)name +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.name = name; + return self; +} + +-(void)dealloc +{ + str_free (name); + [super dealloc]; +} + ++(NameView *)withName:(string)name +{ + return [[[self alloc] initWithName:name] autorelease]; +} + +-draw +{ + [super draw]; + [self mvaddstr:{0, 0}, str_mid (name, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/pointerview.h b/ruamoko/qwaq/debugger/pointerview.h new file mode 100644 index 000000000..6891d5f50 --- /dev/null +++ b/ruamoko/qwaq/debugger/pointerview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_pointerview_h +#define __qwaq_debugger_pointerview_h + +#include "debugger/defview.h" + +@interface PointerView : DefView +{ + unsigned *data; +} ++(PointerView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_pointerview_h diff --git a/ruamoko/qwaq/debugger/pointerview.r b/ruamoko/qwaq/debugger/pointerview.r new file mode 100644 index 000000000..680b8accc --- /dev/null +++ b/ruamoko/qwaq/debugger/pointerview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/pointerview.h" + +@implementation PointerView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (unsigned *)(data + offset); + return self; +} + ++(PointerView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("FIXME [%x]", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/quatview.h b/ruamoko/qwaq/debugger/quatview.h new file mode 100644 index 000000000..2ea1934cd --- /dev/null +++ b/ruamoko/qwaq/debugger/quatview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_quatview_h +#define __qwaq_debugger_quatview_h + +#include "debugger/defview.h" + +@interface QuatView : DefView +{ + quaternion *data; +} ++(QuatView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_quatview_h diff --git a/ruamoko/qwaq/debugger/quatview.r b/ruamoko/qwaq/debugger/quatview.r new file mode 100644 index 000000000..944a02e58 --- /dev/null +++ b/ruamoko/qwaq/debugger/quatview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/quatview.h" + +@implementation QuatView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (quaternion *)(data + offset); + return self; +} + ++(QuatView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("%.9q", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/stringview.h b/ruamoko/qwaq/debugger/stringview.h new file mode 100644 index 000000000..708ef72ca --- /dev/null +++ b/ruamoko/qwaq/debugger/stringview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_stringview_h +#define __qwaq_debugger_stringview_h + +#include "debugger/defview.h" + +@interface StringView : DefView +{ + string *data; +} ++(StringView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_stringview_h diff --git a/ruamoko/qwaq/debugger/stringview.r b/ruamoko/qwaq/debugger/stringview.r new file mode 100644 index 000000000..81dc7cb78 --- /dev/null +++ b/ruamoko/qwaq/debugger/stringview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/stringview.h" + +@implementation StringView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (string *)(data + offset); + return self; +} + ++(StringView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("FIXME %s", data[0]);// quote string + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index 30ff48181..f5184c0eb 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -69,7 +69,6 @@ static void type_free (void *t, void *unused) for (type = encodings.types; ((int *)type - (int *) encodings.types) < encodings.size; type = next_type (type)) { - printf ("%s\n", type.encoding); Hash_Add (static_encodings, type); } return self; diff --git a/ruamoko/qwaq/debugger/uintview.h b/ruamoko/qwaq/debugger/uintview.h new file mode 100644 index 000000000..752db5a20 --- /dev/null +++ b/ruamoko/qwaq/debugger/uintview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_uintview_h +#define __qwaq_debugger_uintview_h + +#include "debugger/defview.h" + +@interface UIntView : DefView +{ + unsigned *data; +} ++(UIntView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_uintview_h diff --git a/ruamoko/qwaq/debugger/uintview.r b/ruamoko/qwaq/debugger/uintview.r new file mode 100644 index 000000000..d1efc4a17 --- /dev/null +++ b/ruamoko/qwaq/debugger/uintview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/uintview.h" + +@implementation UIntView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (unsigned *)(data + offset); + return self; +} + ++(UIntView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("%u", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/vectorview.h b/ruamoko/qwaq/debugger/vectorview.h new file mode 100644 index 000000000..51d2ffc34 --- /dev/null +++ b/ruamoko/qwaq/debugger/vectorview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_vectorview_h +#define __qwaq_debugger_vectorview_h + +#include "debugger/defview.h" + +@interface VectorView : DefView +{ + vector *data; +} ++(VectorView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_vectorview_h diff --git a/ruamoko/qwaq/debugger/vectorview.r b/ruamoko/qwaq/debugger/vectorview.r new file mode 100644 index 000000000..0d29865d3 --- /dev/null +++ b/ruamoko/qwaq/debugger/vectorview.r @@ -0,0 +1,28 @@ +#include +#include "debugger/vectorview.h" + +@implementation VectorView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (vector *)(data + offset); + return self; +} + ++(VectorView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("%.9v", data[0]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/voidview.h b/ruamoko/qwaq/debugger/voidview.h new file mode 100644 index 000000000..e0e19c675 --- /dev/null +++ b/ruamoko/qwaq/debugger/voidview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_voidview_h +#define __qwaq_debugger_voidview_h + +#include "debugger/defview.h" + +@interface VoidView : DefView +{ + unsigned *data; +} ++(VoidView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; +@end + +#endif//__qwaq_debugger_voidview_h diff --git a/ruamoko/qwaq/debugger/voidview.r b/ruamoko/qwaq/debugger/voidview.r new file mode 100644 index 000000000..3683a08f3 --- /dev/null +++ b/ruamoko/qwaq/debugger/voidview.r @@ -0,0 +1,29 @@ +#include +#include "debugger/voidview.h" + +@implementation VoidView + +-initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + if (!(self = [super initWithType:type])) { + return nil; + } + self.data = (unsigned *) (data + offset); + return self; +} + ++(VoidView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [[[self alloc] initWithType:type at:offset in:data] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("%08x %08x %08x %08x", + data[0], data[1], data[2], data[3]); + [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/ui/listener.r b/ruamoko/qwaq/ui/listener.r index 3664040d2..31dd001fa 100644 --- a/ruamoko/qwaq/ui/listener.r +++ b/ruamoko/qwaq/ui/listener.r @@ -1,6 +1,7 @@ #include #include "ui/listener.h" +#include "ui/curses.h" @class Array; @@ -55,6 +56,12 @@ return self; } +-(void)dealloc +{ + [listeners release]; + [super dealloc]; +} + -addListener: (id) responder :(SEL)message { Listener *listener = [Listener listenerWithResponder:responder :message]; diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index 411e7d344..b8b005aa8 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -62,6 +62,7 @@ [objects release]; [buffer release]; [onScrollBarModified release]; + [super dealloc]; } +(ScrollBar *)horizontal:(unsigned)len at:(Point)pos diff --git a/ruamoko/qwaq/ui/tableview.r b/ruamoko/qwaq/ui/tableview.r index fa2772eae..625849a4d 100644 --- a/ruamoko/qwaq/ui/tableview.r +++ b/ruamoko/qwaq/ui/tableview.r @@ -49,6 +49,7 @@ options = ofCanFocus | ofRelativeEvents; columns = [[Array array] retain]; buffer = [[DrawBuffer buffer:size] retain]; + [buffer bkgd:' ']; [onViewScrolled addListener:self :@selector(onScroll:)]; return self; } @@ -58,6 +59,7 @@ [columns release]; [buffer release]; [dataSource release]; + [super dealloc]; } +(TableView *)withRect:(Rect)rect diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index 5dc0da9e6..31005878f 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -60,9 +60,6 @@ static void view_init(View *self) - (void) dealloc { - if (owner) { - [owner remove:self]; - } [onReceiveFocus release]; [onReleaseFocus release]; [onEvent release]; @@ -353,6 +350,16 @@ updateScreenCursor (View *view) return self; } +-(ListenerGroup *) onReceiveFocus +{ + return onReceiveFocus; +} + +-(ListenerGroup *) onReleaseFocus +{ + return onReleaseFocus; +} + -(ListenerGroup *)onEvent { return onEvent; @@ -391,16 +398,6 @@ updateScreenCursor (View *view) return self; } --(ListenerGroup *) onReceiveFocus -{ - return onReceiveFocus; -} - --(ListenerGroup *) onReleaseFocus -{ - return onReleaseFocus; -} - -raise { return self; From beecdcadbf023f9ff06997c64595766f069dfce5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 22:03:56 +0900 Subject: [PATCH 0989/3664] [qwaq] Support resizing the table view --- ruamoko/qwaq/debugger/debugger.r | 3 ++- ruamoko/qwaq/ui/tableview.h | 5 +++++ ruamoko/qwaq/ui/tableview.r | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 85ae89efd..afb922a38 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -87,7 +87,8 @@ locals_data = [[LocalsData withTarget:target] retain]; locals_view = [TableView withRect:{{1, 1}, {38, 8}}]; [locals_view addColumn:[TableViewColumn named:"name" width:12]]; - [locals_view addColumn:[TableViewColumn named:"value" width:26]]; + [locals_view addColumn:[[TableViewColumn named:"value" width:26] + setGrowMode:gfGrowHiX]]; ScrollBar *sb = [ScrollBar vertical:8 at:{39, 1}]; [locals_view setVerticalScrollBar:sb]; [locals_view setDataSource:locals_data]; diff --git a/ruamoko/qwaq/ui/tableview.h b/ruamoko/qwaq/ui/tableview.h index b21279b0a..9a6233333 100644 --- a/ruamoko/qwaq/ui/tableview.h +++ b/ruamoko/qwaq/ui/tableview.h @@ -21,9 +21,14 @@ { string name; int width; + int growMode; // Y flags ignored } +(TableViewColumn *)named:(string)name; +(TableViewColumn *)named:(string)name width:(int)width; + +-setGrowMode: (int) mode; +-(int)growMode; + -(string)name; -(int)width; @end diff --git a/ruamoko/qwaq/ui/tableview.r b/ruamoko/qwaq/ui/tableview.r index 625849a4d..cb1a3f94c 100644 --- a/ruamoko/qwaq/ui/tableview.r +++ b/ruamoko/qwaq/ui/tableview.r @@ -23,6 +23,17 @@ return [[[self alloc] initWithName:name width:width] autorelease]; } +-setGrowMode: (int) mode +{ + growMode = mode; + return self; +} + +-(int)growMode +{ + return growMode; +} + -(string)name { return name; @@ -38,6 +49,14 @@ self.width = width; return self; } + +-grow:(Extent)delta +{ + if (growMode & gfGrowHiX) { + width += delta.width; + } + return self; +} @end @implementation TableView @@ -51,6 +70,7 @@ buffer = [[DrawBuffer buffer:size] retain]; [buffer bkgd:' ']; [onViewScrolled addListener:self :@selector(onScroll:)]; + growMode = gfGrowHi; return self; } @@ -85,6 +105,9 @@ Extent size = self.size; [super resize:delta]; [buffer resizeTo:self.size]; + for (int i = [columns count]; i-- > 0; ) { + [[columns objectAtIndex: i] grow: delta]; + } return self; } From c515d63d9712419892137df03b0dcf9f6992a7a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 Mar 2020 23:23:18 +0900 Subject: [PATCH 0990/3664] [qwaq] Get the locals view working All because I forgot I went the unixy way for qdb_get_data. --- ruamoko/qwaq/debugger/debugger.r | 1 + ruamoko/qwaq/debugger/localsdata.h | 1 + ruamoko/qwaq/debugger/localsdata.r | 15 ++++++++------- ruamoko/qwaq/debugger/typeencodings.r | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index afb922a38..1cdad5e8d 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -121,6 +121,7 @@ { qdb_state_t state = qdb_get_state (target); [locals_data setFunction:state.func]; + [locals_data fetchData]; [locals_view redraw]; } diff --git a/ruamoko/qwaq/debugger/localsdata.h b/ruamoko/qwaq/debugger/localsdata.h index 976b2ecf1..9562921c1 100644 --- a/ruamoko/qwaq/debugger/localsdata.h +++ b/ruamoko/qwaq/debugger/localsdata.h @@ -17,6 +17,7 @@ } +(LocalsData *)withTarget:(qdb_target_t)target; -setFunction:(unsigned)fnum; +-fetchData; @end #endif diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index 48019aaed..bdaa3dd79 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -64,6 +64,12 @@ return self; } +-fetchData +{ + qdb_get_data (target, func.local_data, func.local_size, data); + return self; +} + -(int)numberOfRows:(TableView *)tableview { if (aux_func) { @@ -74,12 +80,6 @@ return 0; } --(qfot_type_t *)type:(qdb_def_t *)def -{ - unsigned encoding = def.type_encoding + (unsigned) target_encodings.types; - return [TypeEncodings getType:encoding fromTarget:target]; -} - -(View *)tableView:(TableView *)tableview forColumn:(TableViewColumn *)column row:(int)row @@ -89,7 +89,8 @@ if ([column name] == "name") { view = [NameView withName:qdb_get_string (target, defs[row].name)]; } else { - qfot_type_t *type = [self type:&defs[row]]; + qfot_type_t *type = [TypeEncodings getType:defs[row].type_encoding + fromTarget:target]; unsigned offset = defs[row].offset; view = [DefView withType:type at:offset in:data]; } diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index f5184c0eb..0e2f4fc44 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -80,7 +80,7 @@ static void type_free (void *t, void *unused) string encoding; qfot_type_t *type; - if (!qdb_get_data (target, typeAddr, TYPESIZE, &buffer)) { + if (qdb_get_data (target, typeAddr, TYPESIZE, &buffer) < 0) { return nil; } if (!buffer.encoding) { From bd7212a411489d5e3be165a34d1ce692078d7690 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 00:03:53 +0900 Subject: [PATCH 0991/3664] [qwaq] Pass debug target into the def views Needed for any views that have to fetch additional data (strings, fields, etc). --- ruamoko/qwaq/debugger/defview.h | 7 ++++++- ruamoko/qwaq/debugger/defview.r | 17 +++++++++++++++-- ruamoko/qwaq/debugger/localsdata.r | 2 +- ruamoko/qwaq/debugger/stringview.h | 2 +- ruamoko/qwaq/debugger/stringview.r | 4 ++-- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/ruamoko/qwaq/debugger/defview.h b/ruamoko/qwaq/debugger/defview.h index 69553620b..4760abcad 100644 --- a/ruamoko/qwaq/debugger/defview.h +++ b/ruamoko/qwaq/debugger/defview.h @@ -3,12 +3,17 @@ #include #include "ui/view.h" +#include "debugger/debug.h" @interface DefView : View { qfot_type_t *type; + qdb_target_t target; } -+(DefView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(DefView *)withType:(qfot_type_t *)type + at:(unsigned)offset + in:(void *)data + target:(qdb_target_t)target; -initWithType:(qfot_type_t *)type; @end diff --git a/ruamoko/qwaq/debugger/defview.r b/ruamoko/qwaq/debugger/defview.r index 5768a14f5..f115c8e61 100644 --- a/ruamoko/qwaq/debugger/defview.r +++ b/ruamoko/qwaq/debugger/defview.r @@ -31,10 +31,23 @@ static string meta_views[] = { return self; } +-setTarget:(qdb_target_t)target +{ + self.target = target; + return self; +} + +(DefView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +{ + return [self withType:type at:offset in:data target:nil]; +} + ++(DefView *)withType:(qfot_type_t *)type + at:(unsigned)offset + in:(void *)data + target:(qdb_target_t)target { string metaname = nil; - //printf("%d %d %d %d\n", type.meta, type.size, type.encoding, type.type); if (type.meta == ty_alias) { type = type.alias.aux_type; } @@ -44,7 +57,7 @@ static string meta_views[] = { } id class = obj_lookup_class (metaname); if (class) { - return [class withType:type at:offset in:data]; + return [[class withType:type at:offset in:data] setTarget:target]; } return [NameView withName:"Invalid Meta"]; } diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index bdaa3dd79..7e6472191 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -92,7 +92,7 @@ qfot_type_t *type = [TypeEncodings getType:defs[row].type_encoding fromTarget:target]; unsigned offset = defs[row].offset; - view = [DefView withType:type at:offset in:data]; + view = [DefView withType:type at:offset in:data target:target]; } [view resizeTo:{[column width], 1}]; return view; diff --git a/ruamoko/qwaq/debugger/stringview.h b/ruamoko/qwaq/debugger/stringview.h index 708ef72ca..62b009e5d 100644 --- a/ruamoko/qwaq/debugger/stringview.h +++ b/ruamoko/qwaq/debugger/stringview.h @@ -5,7 +5,7 @@ @interface StringView : DefView { - string *data; + int *data; } +(StringView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; @end diff --git a/ruamoko/qwaq/debugger/stringview.r b/ruamoko/qwaq/debugger/stringview.r index 81dc7cb78..445ccfdbf 100644 --- a/ruamoko/qwaq/debugger/stringview.r +++ b/ruamoko/qwaq/debugger/stringview.r @@ -8,7 +8,7 @@ if (!(self = [super initWithType:type])) { return nil; } - self.data = (string *)(data + offset); + self.data = (int *)(data + offset); return self; } @@ -20,7 +20,7 @@ -draw { [super draw]; - string val = sprintf ("FIXME %s", data[0]);// quote string + string val = sprintf ("FIXME %s", qdb_get_string (target, data[0]));// quote string [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; return self; } From e9733416f4903150959eaa255213524ad24acd26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 00:09:34 +0900 Subject: [PATCH 0992/3664] [gamecode] Hide trace messages when debugger is attached --- libs/gamecode/pr_exec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index b0a7cb820..9a287b4f9 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -193,7 +193,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) pr_type_t *dstParams[MAX_PARMS]; pointer_t paramofs = 0; - if (pr->pr_trace) { + if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Entering function %s\n", PR_GetString (pr, f->descriptor->s_name)); } @@ -284,7 +284,7 @@ PR_LeaveFunction (progs_t *pr, int to_engine) PR_PopFrame (pr); - if (pr->pr_trace) { + if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Leaving function %s\n", PR_GetString (pr, f->descriptor->s_name)); if (to_engine) { @@ -405,7 +405,7 @@ PR_CallFunction (progs_t *pr, func_t fnum) f = pr->function_table + fnum; if (f->first_statement < 0) { // negative statements are built in functions - if (pr->pr_trace) { + if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Calling builtin %s @ %p\n", PR_GetString (pr, f->descriptor->s_name), f->func); } From a7956c73115aa287751d37dc40f8e29fc8b16d6c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 11:19:56 +0900 Subject: [PATCH 0993/3664] [gamecode] Move format state into a state struct This is the first step in reworking PR_Sprintf to use a state machine. The goal is to make it more robust against errors and easier to extend (eg, * width and precision). --- libs/gamecode/pr_strings.c | 241 +++++++++++++++++++------------------ 1 file changed, 124 insertions(+), 117 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 7781865a7..78cdc8120 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -808,6 +808,14 @@ free_fmt_item (prstr_resources_t *res, fmt_item_t *fi) res->free_fmt_items = fi; } +typedef struct fmtstate_s { + const char *c; + const char *l; + fmt_item_t *fmt_items; + fmt_item_t **fi; + int fmt_count; +} fmt_state_t; + #undef P_var #define P_var(p,n,t) (args[n]->t##_var) #undef P_DOUBLE @@ -817,229 +825,228 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, const char *format, int count, pr_type_t **args) { prstr_resources_t *res = pr->pr_string_resources; - const char *c, *l; const char *msg = ""; - fmt_item_t *fmt_items = 0; - fmt_item_t **fi = &fmt_items; - int fmt_count = 0; + fmt_state_t state = { }; + + state.fi = &state.fmt_items; if (!name) name = "PR_Sprintf"; - *fi = new_fmt_item (res); - c = l = format; - while (*c) { - if (*c++ == '%') { - if (c != l + 1) { + *state.fi = new_fmt_item (res); + state.c = state.l = format; + while (*state.c) { + if (*state.c++ == '%') { + if (state.c != state.l + 1) { // have some unformatted text to print - (*fi)->precision = c - l - 1; - (*fi)->type = 's'; - (*fi)->data.string_var = l; + (*state.fi)->precision = state.c - state.l - 1; + (*state.fi)->type = 's'; + (*state.fi)->data.string_var = state.l; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; } - if (*c == '%') { - (*fi)->type = 's'; - (*fi)->data.string_var = "%"; + if (*state.c == '%') { + (*state.fi)->type = 's'; + (*state.fi)->data.string_var = "%"; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; } else { do { - switch (*c) { + switch (*state.c) { // format options case '\0': msg = "Unexpected end of format string"; goto error; case '0': - (*fi)->flags |= FMT_ZEROPAD; - c++; + (*state.fi)->flags |= FMT_ZEROPAD; + state.c++; continue; case '#': - (*fi)->flags |= FMT_ALTFORM; - c++; + (*state.fi)->flags |= FMT_ALTFORM; + state.c++; continue; case ' ': - (*fi)->flags |= FMT_ADDBLANK; - c++; + (*state.fi)->flags |= FMT_ADDBLANK; + state.c++; continue; case '-': - (*fi)->flags |= FMT_LJUSTIFY; - c++; + (*state.fi)->flags |= FMT_LJUSTIFY; + state.c++; continue; case '+': - (*fi)->flags |= FMT_ADDSIGN; - c++; + (*state.fi)->flags |= FMT_ADDSIGN; + state.c++; continue; case '.': - (*fi)->precision = 0; - c++; - while (isdigit ((byte )*c)) { - (*fi)->precision *= 10; - (*fi)->precision += *c++ - '0'; + (*state.fi)->precision = 0; + state.c++; + while (isdigit ((byte )*state.c)) { + (*state.fi)->precision *= 10; + (*state.fi)->precision += *state.c++ - '0'; } continue; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - while (isdigit ((byte )*c)) { - (*fi)->minFieldWidth *= 10; - (*fi)->minFieldWidth += *c++ - '0'; + while (isdigit ((byte )*state.c)) { + (*state.fi)->minFieldWidth *= 10; + (*state.fi)->minFieldWidth += *state.c++ - '0'; } continue; // format types case '@': // object - fmt_count++; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + state.fmt_count++; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; break; case 'e': // entity - (*fi)->type = 'i'; - (*fi)->data.integer_var = - P_EDICTNUM (pr, fmt_count); + (*state.fi)->type = 'i'; + (*state.fi)->data.integer_var = + P_EDICTNUM (pr, state.fmt_count); - fmt_count++; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + state.fmt_count++; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; break; case 'i': case 'd': case 'c': // integer - (*fi)->type = *c; - (*fi)->data.integer_var = P_INT (pr, fmt_count); + (*state.fi)->type = *state.c; + (*state.fi)->data.integer_var = P_INT (pr, state.fmt_count); - fmt_count++; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + state.fmt_count++; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; break; case 'f': // float or double case 'g': // float or double, no trailing zeroes, trim "." // if nothing after - (*fi)->type = *c; + (*state.fi)->type = *state.c; if (pr->float_promoted) { - (*fi)->flags |= FMT_LONG; - (*fi)->data.double_var - = P_DOUBLE (pr, fmt_count); + (*state.fi)->flags |= FMT_LONG; + (*state.fi)->data.double_var + = P_DOUBLE (pr, state.fmt_count); } else { - (*fi)->data.float_var - = P_FLOAT (pr, fmt_count); + (*state.fi)->data.float_var + = P_FLOAT (pr, state.fmt_count); } - fmt_count++; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + state.fmt_count++; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; break; case 'p': // pointer - (*fi)->flags |= FMT_ALTFORM; - (*fi)->type = 'x'; - (*fi)->data.uinteger_var = P_UINT (pr, fmt_count); + (*state.fi)->flags |= FMT_ALTFORM; + (*state.fi)->type = 'x'; + (*state.fi)->data.uinteger_var = P_UINT (pr, state.fmt_count); - fmt_count++; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + state.fmt_count++; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; break; case 's': // string - (*fi)->type = *c; - (*fi)->data.string_var = P_GSTRING (pr, fmt_count); + (*state.fi)->type = *state.c; + (*state.fi)->data.string_var = P_GSTRING (pr, state.fmt_count); - fmt_count++; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + state.fmt_count++; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; break; case 'v': case 'q': // vector { int i, count = 3; - int flags = (*fi)->flags; - int precision = (*fi)->precision; - unsigned minWidth = (*fi)->minFieldWidth; + int flags = (*state.fi)->flags; + int precision = (*state.fi)->precision; + unsigned minWidth = (*state.fi)->minFieldWidth; - (*fi)->flags = 0; - (*fi)->precision = -1; - (*fi)->minFieldWidth = 0; + (*state.fi)->flags = 0; + (*state.fi)->precision = -1; + (*state.fi)->minFieldWidth = 0; - if (*c == 'q') + if (*state.c == 'q') count = 4; for (i = 0; i < count; i++) { if (i == 0) { - (*fi)->type = 's'; - (*fi)->data.string_var = "'"; + (*state.fi)->type = 's'; + (*state.fi)->data.string_var = "'"; } else { - (*fi)->type = 's'; - (*fi)->data.string_var = " "; + (*state.fi)->type = 's'; + (*state.fi)->data.string_var = " "; } - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; - (*fi)->flags = flags; - (*fi)->precision = precision; - (*fi)->minFieldWidth = minWidth; - (*fi)->type = 'g'; - (*fi)->data.float_var = - P_VECTOR (pr, fmt_count)[i]; + (*state.fi)->flags = flags; + (*state.fi)->precision = precision; + (*state.fi)->minFieldWidth = minWidth; + (*state.fi)->type = 'g'; + (*state.fi)->data.float_var = + P_VECTOR (pr, state.fmt_count)[i]; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; } } - (*fi)->type = 's'; - (*fi)->data.string_var = "'"; + (*state.fi)->type = 's'; + (*state.fi)->data.string_var = "'"; - fmt_count++; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + state.fmt_count++; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; break; case 'x': // integer, hex notation - (*fi)->type = *c; - (*fi)->data.uinteger_var = P_UINT (pr, fmt_count); + (*state.fi)->type = *state.c; + (*state.fi)->data.uinteger_var = P_UINT (pr, state.fmt_count); - fmt_count++; - (*fi)->next = new_fmt_item (res); - fi = &(*fi)->next; + state.fmt_count++; + (*state.fi)->next = new_fmt_item (res); + state.fi = &(*state.fi)->next; break; } break; } while (1); } - l = ++c; + state.l = ++state.c; } } - if (c != l) { + if (state.c != state.l) { // have some unformatted text to print - (*fi)->precision = c - l; - (*fi)->type = 's'; - (*fi)->data.string_var = l; + (*state.fi)->precision = state.c - state.l; + (*state.fi)->type = 's'; + (*state.fi)->data.string_var = state.l; - (*fi)->next = new_fmt_item (res); + (*state.fi)->next = new_fmt_item (res); } - if (fmt_count != count) { - if (fmt_count > count) + if (state.fmt_count != count) { + if (state.fmt_count > count) msg = "Not enough arguments for format string."; else msg = "Too many arguments for format string."; - dsprintf (res->print_str, "%s: %d %d", msg, fmt_count, count); + dsprintf (res->print_str, "%s: %d %d", msg, state.fmt_count, count); msg = res->print_str->str; goto error; } dstring_clear (res->print_str); - I_DoPrint (res->print_str, result, fmt_items); - while (fmt_items) { - fmt_item_t *t = fmt_items->next; - free_fmt_item (res, fmt_items); - fmt_items = t; + I_DoPrint (res->print_str, result, state.fmt_items); + while (state.fmt_items) { + fmt_item_t *t = state.fmt_items->next; + free_fmt_item (res, state.fmt_items); + state.fmt_items = t; } return; error: From 7f86fb55296d725abbb2162ee0c4ac825d248e0f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 13:32:07 +0900 Subject: [PATCH 0994/3664] [gamecode] Rework PR_Sprintf to use a state machine This makes it much easier to extend. There are even stubs for variable field width and precision (not set yet). --- libs/gamecode/pr_strings.c | 509 ++++++++++++++++++++++--------------- 1 file changed, 302 insertions(+), 207 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 78cdc8120..31c387575 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -808,236 +808,331 @@ free_fmt_item (prstr_resources_t *res, fmt_item_t *fi) res->free_fmt_items = fi; } -typedef struct fmtstate_s { +struct fmt_state_s; +typedef void (*fmt_state_f) (struct fmt_state_s *); + +typedef struct fmt_state_s { + fmt_state_f state; + prstr_resources_t *res; + progs_t *pr; + pr_type_t **args; const char *c; - const char *l; + const char *msg; fmt_item_t *fmt_items; fmt_item_t **fi; int fmt_count; } fmt_state_t; +static inline void +fmt_append_item (fmt_state_t *state) +{ + (*state->fi)->next = new_fmt_item (state->res); + state->fi = &(*state->fi)->next; +} + #undef P_var -#define P_var(p,n,t) (args[n]->t##_var) +#define P_var(p,n,t) (state->args[n]->t##_var) #undef P_DOUBLE -#define P_DOUBLE(p,n) (*(double *) (args[n])) +#define P_DOUBLE(p,n) (*(double *) (state->args[n])) + +static void fmt_state_format (fmt_state_t *state); +static void fmt_state_flags (fmt_state_t *state); +static void fmt_state_var_field_width (fmt_state_t *state); +static void fmt_state_field_width (fmt_state_t *state); +static void fmt_state_precision (fmt_state_t *state); +static void fmt_state_var_precision (fmt_state_t *state); +static void fmt_state_fixed_precision (fmt_state_t *state); +static void fmt_state_modifiers (fmt_state_t *state); +static void fmt_state_conversion (fmt_state_t *state); + +static void +fmt_state_flags (fmt_state_t *state) +{ + state->c++; // skip over % + while (1) { + switch (*state->c) { + case '0': + (*state->fi)->flags |= FMT_ZEROPAD; + break; + case '#': + (*state->fi)->flags |= FMT_ALTFORM; + break; + case ' ': + (*state->fi)->flags |= FMT_ADDBLANK; + break; + case '-': + (*state->fi)->flags |= FMT_LJUSTIFY; + break; + case '+': + (*state->fi)->flags |= FMT_ADDSIGN; + break; + case '*': + state->state = fmt_state_var_field_width; + return; + case '.': + state->state = fmt_state_precision; + return; + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + state->state = fmt_state_field_width; + return; + default: + state->state = fmt_state_modifiers; + return; + } + state->c++; + } +} + +static void +fmt_state_var_field_width (fmt_state_t *state) +{ + // XXX record width + if (*++state->c == '.') { + state->state = fmt_state_precision; + } else { + state->state = fmt_state_modifiers; + } +} + +static void +fmt_state_field_width (fmt_state_t *state) +{ + while (isdigit ((byte )*state->c)) { + (*state->fi)->minFieldWidth *= 10; + (*state->fi)->minFieldWidth += *state->c++ - '0'; + } + if (*state->c == '.') { + state->state = fmt_state_precision; + } else { + state->state = fmt_state_modifiers; + } +} + +static void +fmt_state_precision (fmt_state_t *state) +{ + state->c++; // skip over . + (*state->fi)->precision = 0; + if (isdigit ((byte )*state->c)) { + state->state = fmt_state_fixed_precision; + } else if (*state->c == '*') { + state->state = fmt_state_var_precision; + } else { + state->state = fmt_state_modifiers; + } +} + +static void +fmt_state_var_precision (fmt_state_t *state) +{ + // XXX record precision + state->state = fmt_state_modifiers; +} + +static void +fmt_state_fixed_precision (fmt_state_t *state) +{ + while (isdigit ((byte )*state->c)) { + (*state->fi)->precision *= 10; + (*state->fi)->precision += *state->c++ - '0'; + } + state->state = fmt_state_modifiers; +} + +static void +fmt_state_modifiers (fmt_state_t *state) +{ + // no modifiers supported + state->state = fmt_state_conversion; +} + +static void +fmt_state_conversion (fmt_state_t *state) +{ + progs_t *pr = state->pr; + char conv; + switch ((conv = *state->c++)) { + case '@': + // object + state->fmt_count++; + fmt_append_item (state); + break; + case 'e': + // entity + (*state->fi)->type = 'i'; + (*state->fi)->data.integer_var = + P_EDICTNUM (pr, state->fmt_count); + + state->fmt_count++; + fmt_append_item (state); + break; + case 'i': + case 'd': + case 'c': + // integer + (*state->fi)->type = conv; + (*state->fi)->data.integer_var = P_INT (pr, state->fmt_count); + + state->fmt_count++; + fmt_append_item (state); + break; + case 'f': + // float or double + case 'g': + // float or double, no trailing zeroes, trim "." + // if nothing after + (*state->fi)->type = conv; + if (pr->float_promoted) { + (*state->fi)->flags |= FMT_LONG; + (*state->fi)->data.double_var + = P_DOUBLE (pr, state->fmt_count); + } else { + (*state->fi)->data.float_var + = P_FLOAT (pr, state->fmt_count); + } + + state->fmt_count++; + fmt_append_item (state); + break; + case 'p': + // pointer + (*state->fi)->flags |= FMT_ALTFORM; + (*state->fi)->type = 'x'; + (*state->fi)->data.uinteger_var = P_UINT (pr, state->fmt_count); + + state->fmt_count++; + fmt_append_item (state); + break; + case 's': + // string + (*state->fi)->type = conv; + (*state->fi)->data.string_var = P_GSTRING (pr, state->fmt_count); + + state->fmt_count++; + fmt_append_item (state); + break; + case 'v': + case 'q': + // vector + { + int i, count = 3; + int flags = (*state->fi)->flags; + int precision = (*state->fi)->precision; + unsigned minWidth = (*state->fi)->minFieldWidth; + + (*state->fi)->flags = 0; + (*state->fi)->precision = -1; + (*state->fi)->minFieldWidth = 0; + + if (conv == 'q') + count = 4; + + for (i = 0; i < count; i++) { + if (i == 0) { + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = "'"; + } else { + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = " "; + } + fmt_append_item (state); + + (*state->fi)->flags = flags; + (*state->fi)->precision = precision; + (*state->fi)->minFieldWidth = minWidth; + (*state->fi)->type = 'g'; + (*state->fi)->data.float_var = + P_VECTOR (pr, state->fmt_count)[i]; + + fmt_append_item (state); + } + } + + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = "'"; + + state->fmt_count++; + fmt_append_item (state); + break; + case '%': + (*state->fi)->flags = 0; + (*state->fi)->precision = 0; + (*state->fi)->minFieldWidth = 0; + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = "%"; + + fmt_append_item (state); + break; + case 'x': + // integer, hex notation + (*state->fi)->type = conv; + (*state->fi)->data.uinteger_var = P_UINT (pr, state->fmt_count); + + state->fmt_count++; + fmt_append_item (state); + break; + } + state->state = fmt_state_format; +} + +static void +fmt_state_format (fmt_state_t *state) +{ + const char *l = state->c; + while (*state->c && *state->c != '%') { + state->c++; + } + if (state->c != l) { + // have some unformatted text to print + (*state->fi)->precision = state->c - l; + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = l; + if (*state->c) { + fmt_append_item (state); + } + } + if (*state->c) { + state->state = fmt_state_flags; + } else { + state->state = 0; // finished + } +} + VISIBLE void PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, const char *format, int count, pr_type_t **args) { prstr_resources_t *res = pr->pr_string_resources; - const char *msg = ""; fmt_state_t state = { }; + state.pr = pr; + state.res = res; + state.args = args; state.fi = &state.fmt_items; + *state.fi = new_fmt_item (res); + state.c = format; + state.state = fmt_state_format; if (!name) name = "PR_Sprintf"; - *state.fi = new_fmt_item (res); - state.c = state.l = format; - while (*state.c) { - if (*state.c++ == '%') { - if (state.c != state.l + 1) { - // have some unformatted text to print - (*state.fi)->precision = state.c - state.l - 1; - (*state.fi)->type = 's'; - (*state.fi)->data.string_var = state.l; - - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - } - if (*state.c == '%') { - (*state.fi)->type = 's'; - (*state.fi)->data.string_var = "%"; - - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - } else { - do { - switch (*state.c) { - // format options - case '\0': - msg = "Unexpected end of format string"; - goto error; - case '0': - (*state.fi)->flags |= FMT_ZEROPAD; - state.c++; - continue; - case '#': - (*state.fi)->flags |= FMT_ALTFORM; - state.c++; - continue; - case ' ': - (*state.fi)->flags |= FMT_ADDBLANK; - state.c++; - continue; - case '-': - (*state.fi)->flags |= FMT_LJUSTIFY; - state.c++; - continue; - case '+': - (*state.fi)->flags |= FMT_ADDSIGN; - state.c++; - continue; - case '.': - (*state.fi)->precision = 0; - state.c++; - while (isdigit ((byte )*state.c)) { - (*state.fi)->precision *= 10; - (*state.fi)->precision += *state.c++ - '0'; - } - continue; - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - while (isdigit ((byte )*state.c)) { - (*state.fi)->minFieldWidth *= 10; - (*state.fi)->minFieldWidth += *state.c++ - '0'; - } - continue; - // format types - case '@': - // object - state.fmt_count++; - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - break; - case 'e': - // entity - (*state.fi)->type = 'i'; - (*state.fi)->data.integer_var = - P_EDICTNUM (pr, state.fmt_count); - - state.fmt_count++; - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - break; - case 'i': - case 'd': - case 'c': - // integer - (*state.fi)->type = *state.c; - (*state.fi)->data.integer_var = P_INT (pr, state.fmt_count); - - state.fmt_count++; - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - break; - case 'f': - // float or double - case 'g': - // float or double, no trailing zeroes, trim "." - // if nothing after - (*state.fi)->type = *state.c; - if (pr->float_promoted) { - (*state.fi)->flags |= FMT_LONG; - (*state.fi)->data.double_var - = P_DOUBLE (pr, state.fmt_count); - } else { - (*state.fi)->data.float_var - = P_FLOAT (pr, state.fmt_count); - } - - state.fmt_count++; - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - break; - case 'p': - // pointer - (*state.fi)->flags |= FMT_ALTFORM; - (*state.fi)->type = 'x'; - (*state.fi)->data.uinteger_var = P_UINT (pr, state.fmt_count); - - state.fmt_count++; - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - break; - case 's': - // string - (*state.fi)->type = *state.c; - (*state.fi)->data.string_var = P_GSTRING (pr, state.fmt_count); - - state.fmt_count++; - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - break; - case 'v': - case 'q': - // vector - { - int i, count = 3; - int flags = (*state.fi)->flags; - int precision = (*state.fi)->precision; - unsigned minWidth = (*state.fi)->minFieldWidth; - - (*state.fi)->flags = 0; - (*state.fi)->precision = -1; - (*state.fi)->minFieldWidth = 0; - - if (*state.c == 'q') - count = 4; - - for (i = 0; i < count; i++) { - if (i == 0) { - (*state.fi)->type = 's'; - (*state.fi)->data.string_var = "'"; - } else { - (*state.fi)->type = 's'; - (*state.fi)->data.string_var = " "; - } - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - - (*state.fi)->flags = flags; - (*state.fi)->precision = precision; - (*state.fi)->minFieldWidth = minWidth; - (*state.fi)->type = 'g'; - (*state.fi)->data.float_var = - P_VECTOR (pr, state.fmt_count)[i]; - - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - } - } - - (*state.fi)->type = 's'; - (*state.fi)->data.string_var = "'"; - - state.fmt_count++; - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - break; - case 'x': - // integer, hex notation - (*state.fi)->type = *state.c; - (*state.fi)->data.uinteger_var = P_UINT (pr, state.fmt_count); - - state.fmt_count++; - (*state.fi)->next = new_fmt_item (res); - state.fi = &(*state.fi)->next; - break; - } - break; - } while (1); - } - state.l = ++state.c; - } - } - if (state.c != state.l) { - // have some unformatted text to print - (*state.fi)->precision = state.c - state.l; - (*state.fi)->type = 's'; - (*state.fi)->data.string_var = state.l; - - (*state.fi)->next = new_fmt_item (res); + while (*state.c && state.state) { + state.state (&state); } - if (state.fmt_count != count) { + if (state.state) { + state.msg = "Unexpected end of format string"; + } else if (state.fmt_count != count) { if (state.fmt_count > count) - msg = "Not enough arguments for format string."; + state.msg = "Not enough arguments for format string."; else - msg = "Too many arguments for format string."; - dsprintf (res->print_str, "%s: %d %d", msg, state.fmt_count, count); - msg = res->print_str->str; + state.msg = "Too many arguments for format string."; + } + if (state.msg) { + dsprintf (res->print_str, "%s: %d %d", state.msg, state.fmt_count, + count); + state.msg = res->print_str->str; goto error; } @@ -1050,7 +1145,7 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, } return; error: - PR_RunError (pr, "%s: %s", name, msg); + PR_RunError (pr, "%s: %s", name, state.msg); } void From 842125faf89af8425906ff329d4e16a9cae76f0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 13:45:22 +0900 Subject: [PATCH 0995/3664] [qfcc] Add a failing test for aliased live vars I'm not sure if it's due more to doubles or unions, but the bug was found via double. It seems the dags code generator doesn't see that the assignment to the union's double field kills the two int fields. The test passes when NOT optimizing. --- tools/qfcc/test/Makefile.am | 10 +++++++++ tools/qfcc/test/double-alias.r | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tools/qfcc/test/double-alias.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index a7b10901f..2b454b7a5 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -43,6 +43,7 @@ test_progs_dat=\ compound.dat \ deadbool.dat \ double.dat \ + double-alias.dat \ enum.dat \ fordecl.dat \ func-expr.dat \ @@ -209,6 +210,15 @@ double.run: Makefile build-run include ./$(DEPDIR)/double.Qo # am--include-marker r_depfiles_remade += ./$(DEPDIR)/double.Qo +double_alias_dat_SOURCES=double-alias.r +double_alias_obj=$(double_alias_dat_SOURCES:.r=.qfo) +double-alias.dat$(EXEEXT): $(double_alias_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(double_alias_obj) +double-alias.run: Makefile build-run + @$(srcdir)/build-run $@ +include ./$(DEPDIR)/double-alias.Qo # am--include-marker +r_depfiles_remade += ./$(DEPDIR)/double-alias.Qo + classarray.run$(EXEEXT): classarray.r Makefile build-compile-fail-run @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/double-alias.r b/tools/qfcc/test/double-alias.r new file mode 100644 index 000000000..6050d2f6d --- /dev/null +++ b/tools/qfcc/test/double-alias.r @@ -0,0 +1,41 @@ +void printf (string fmt, ...) = #0; +# define M_PI 3.14159265358979323846 + +union { + double d; + int i[2]; +} type_pun; + +int alias_printf (string fmt, ...); + +int +test_alias () +{ + int fail = 0; + type_pun.d = M_PI; + fail = alias_printf ("%g %08x%08x\n", type_pun.d, + type_pun.i[1], type_pun.i[0]); + return fail; +} + +int +alias_printf (string fmt, ...) +{ + int fail = 0; + // this will fail on big-endian systems + fail = (@args.list[2].integer_val != 0x54442d18 + || @args.list[1].integer_val != 0x400921fb); + printf ("%g %08x%08x\n", + @args.list[0].integer_val, + @args.list[2].integer_val, + @args.list[1].integer_val); + return fail; +} + +int +main () +{ + int fail = 0; + fail |= test_alias (); + return fail; +} From 4c79c9ffaf46b8c2c35c8ce8205ed2a403b6ab1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 16:03:12 +0900 Subject: [PATCH 0996/3664] [qfcc] Do a dags pre-pass to give operands leafs The reason double-alias fails is when the double assignment occurs, the int operands don't yet have leaf nodes and thus the nodes cannot be killed. This doesn't fix the bug. --- tools/qfcc/source/dags.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 8b352e1c1..83c30b8b7 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -245,7 +245,21 @@ dag_node (operand_t *op) } static void -dag_make_children (dag_t *dag, statement_t *s, operand_t *operands[4], +dag_make_leafs (dag_t *dag, statement_t *s, operand_t *operands[FLOW_OPERANDS]) +{ + int i; + + flow_analyze_statement (s, 0, 0, 0, operands); + for (i = 1; i < FLOW_OPERANDS; i++) { + if (!dag_node (operands[i])) { + leaf_node (dag, operands[i], s->expr); + } + } +} + +static void +dag_make_children (dag_t *dag, statement_t *s, + operand_t *operands[FLOW_OPERANDS], dagnode_t *children[3]) { int i; @@ -730,6 +744,13 @@ dag_create (flownode_t *flownode) dag->labels = alloca (num_lables * sizeof (daglabel_t)); dag->roots = set_new (); + // do a first pass to ensure all operands have an "x_0" leaf node + // prior do actual dag creation + for (s = block->statements; s; s = s->next) { + operand_t *operands[FLOW_OPERANDS]; + dag_make_leafs (dag, s, operands); + } + // actual dag creation for (s = block->statements; s; s = s->next) { operand_t *operands[FLOW_OPERANDS]; dagnode_t *n = 0, *children[3] = {0, 0, 0}; From 199b3e82d9044394029f33ed6937b8677dc4b5be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 16:05:26 +0900 Subject: [PATCH 0997/3664] [qfcc] Add killer node to replacement node's edges When an operand refers to a killed node, it needs to be evaluated AFTER the killing node is evaluated. This fixes the double-alias bug. --- tools/qfcc/include/dags.h | 2 +- tools/qfcc/source/dags.c | 27 ++++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index c83c029f6..534e58511 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -59,7 +59,7 @@ typedef struct dagnode_s { int topo; ///< topological sort order struct set_s *parents; ///< empty if root node int cost; ///< cost of this node in temp vars - unsigned killed:1; ///< node is unavailable for cse + struct dagnode_s *killed; ///< node is unavailable for cse (by node) st_type_t type; ///< type of node (st_none = leaf) daglabel_t *label; ///< ident/const if leaf node, or operator struct type_s *tl; diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 83c30b8b7..a2d29c371 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -239,8 +239,6 @@ dag_node (operand_t *op) if (op->o.label->daglabel) node = op->o.label->daglabel->dagnode; } - if (node && node->killed) - node = 0; return node; } @@ -266,8 +264,19 @@ dag_make_children (dag_t *dag, statement_t *s, flow_analyze_statement (s, 0, 0, 0, operands); for (i = 0; i < 3; i++) { - if (!(children[i] = dag_node (operands[i + 1]))) - children[i] = leaf_node (dag, operands[i + 1], s->expr); + dagnode_t *node = dag_node (operands[i + 1]); + dagnode_t *killer = 0; + if (node && node->killed) { + killer = node->killed; + node = 0; + } + if (!node) { + node = leaf_node (dag, operands[i + 1], s->expr); + } + if (killer) { + set_add (node->edges, killer->number); + } + children[i] = node; } } @@ -473,7 +482,7 @@ static int dag_tempop_kill_aliases_visit (tempop_t *tempop, void *_l) { daglabel_t *l = (daglabel_t *) _l; - dagnode_t *node = l->dagnode;; + dagnode_t *node = l->dagnode; daglabel_t *label; if (tempop == &l->op->o.tempop) @@ -482,7 +491,7 @@ dag_tempop_kill_aliases_visit (tempop_t *tempop, void *_l) if (label && label->dagnode) { set_add (node->edges, label->dagnode->number); set_remove (node->edges, node->number); - label->dagnode->killed = 1; + label->dagnode->killed = node; } return 0; } @@ -500,7 +509,7 @@ dag_def_kill_aliases_visit (def_t *def, void *_l) if (label && label->dagnode) { set_add (node->edges, label->dagnode->number); set_remove (node->edges, node->number); - label->dagnode->killed = 1; + label->dagnode->killed = node; } return 0; } @@ -584,7 +593,7 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l) // if the node is a leaf, then kill its value so no attempt is made // to reuse it. if (l->dagnode->type == st_none) { - l->dagnode->killed = 1; + l->dagnode->killed = n; } dagnode_t *node = l->dagnode; set_union (n->edges, node->parents); @@ -707,7 +716,7 @@ dag_kill_nodes (dag_t *dag, dagnode_t *n) // operations. continue; } - node->killed = 1; + node->killed = n; } n->killed = 0; } From 17bb408b57259f439f5d922ed1d99cab998c968c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 16:06:45 +0900 Subject: [PATCH 0998/3664] [qfcc] Clean up stray dags edges Killed nodes can leave stray (dangling) edges that cause some confusion in the dot graphs and may cause problems later on down the track, so ensure there are no dangling edges. --- tools/qfcc/source/dags.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index a2d29c371..680abca84 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -1163,6 +1163,19 @@ dag_remove_dead_nodes (dag_t *dag) } } } while (added_root); + + // clean up any stray edges that point to removed nodes + for (int i = 0; i < dag->num_nodes; i++) { + node = dag->nodes[i]; + for (child_i = set_first (node->edges); child_i; + child_i = set_next (child_i)) { + child = dag->nodes[child_i->element]; + if (!set_is_member (dag->roots, child->number) + && set_is_empty (child->parents)) { + set_remove (node->edges, child->number); + } + } + } dag_sort_nodes (dag); } From 7f4d2215e2b13d1f6bcbae4327cadd25fd014829 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 18:32:30 +0900 Subject: [PATCH 0999/3664] [gamecode] Accept EOS at end of conversion specifier --- libs/gamecode/pr_strings.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 31c387575..195dd5980 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -1073,7 +1073,11 @@ fmt_state_conversion (fmt_state_t *state) fmt_append_item (state); break; } - state->state = fmt_state_format; + if (*state->c) { + state->state = fmt_state_format; + } else { + state->state = 0; // finished + } } static void From a36f72f7b43c7b9074566ce303a2a3175aa9f1ca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 19:45:33 +0900 Subject: [PATCH 1000/3664] [gamecode] Support variable field width and precision --- libs/gamecode/pr_strings.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 195dd5980..d9d3f69df 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -887,7 +887,8 @@ fmt_state_flags (fmt_state_t *state) static void fmt_state_var_field_width (fmt_state_t *state) { - // XXX record width + (*state->fi)->minFieldWidth = P_INT (pr, state->fmt_count); + state->fmt_count++; if (*++state->c == '.') { state->state = fmt_state_precision; } else { @@ -926,7 +927,9 @@ fmt_state_precision (fmt_state_t *state) static void fmt_state_var_precision (fmt_state_t *state) { - // XXX record precision + state->c++; // skip over * + (*state->fi)->precision = P_INT (pr, state->fmt_count); + state->fmt_count++; state->state = fmt_state_modifiers; } From 535a2363bb464b92cc41c232380a5e91feeb4096 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 19:48:05 +0900 Subject: [PATCH 1001/3664] [ruamoko] Create a va_copy for progs In testing variable fw/precision in PR_Sprintf, I got a nasty reminder of the limitations of the current progs ABI: passing @args to another QC function does not work because the args list gets trampled but the called function's locals. Thus, the need for a va_copy. It's not quite the same as C's as it returns the destination args instead of copying like memcpy, but it does copy the list from the source args to a temporary buffer that is freed when the calling function returns. --- include/rua_internal.h | 2 + libs/ruamoko/Makefile.am | 2 +- libs/ruamoko/rua_init.c | 1 + libs/ruamoko/rua_runtime.c | 76 ++++++++++++++++++++++++++++++++++++++ ruamoko/include/runtime.h | 4 ++ ruamoko/lib/Makefile.am | 2 +- ruamoko/lib/va_list.r | 3 ++ ruamoko/qwaq/ui/view.r | 2 +- 8 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 libs/ruamoko/rua_runtime.c create mode 100644 ruamoko/lib/va_list.r diff --git a/include/rua_internal.h b/include/rua_internal.h index 158d6e477..7bde98a77 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -49,6 +49,8 @@ void RUA_Obj_Init (struct progs_s *pr, int secure); void RUA_Plist_Init (struct progs_s *pr, int secure); +void RUA_Runtime_Init (struct progs_s *pr, int secure); + void RUA_Script_Init (progs_t *pr, int secure); void RUA_Set_Init (progs_t *pr, int secure); diff --git a/libs/ruamoko/Makefile.am b/libs/ruamoko/Makefile.am index 15d4c4360..2d4777c14 100644 --- a/libs/ruamoko/Makefile.am +++ b/libs/ruamoko/Makefile.am @@ -18,4 +18,4 @@ libQFruamoko_la_SOURCES= \ pr_cmds.c \ rua_cbuf.c rua_cmd.c rua_cvar.c rua_hash.c rua_init.c \ rua_math.c rua_msgbuf.c rua_obj.c rua_plist.c rua_qfile.c rua_qfs.c \ - rua_script.c rua_set.c rua_string.c + rua_runtime.c rua_script.c rua_set.c rua_string.c diff --git a/libs/ruamoko/rua_init.c b/libs/ruamoko/rua_init.c index 7741405a5..6e4333998 100644 --- a/libs/ruamoko/rua_init.c +++ b/libs/ruamoko/rua_init.c @@ -45,6 +45,7 @@ static void (*init_funcs[])(progs_t *, int) = { RUA_Plist_Init, RUA_QFile_Init, RUA_QFS_Init, + RUA_Runtime_Init, RUA_Script_Init, RUA_Set_Init, RUA_String_Init, diff --git a/libs/ruamoko/rua_runtime.c b/libs/ruamoko/rua_runtime.c new file mode 100644 index 000000000..697fc720b --- /dev/null +++ b/libs/ruamoko/rua_runtime.c @@ -0,0 +1,76 @@ +/* + bi_runtime.c + + QuakeC runtime api + + Copyright (C) 2020 Bill Currie + + Author: Bill Currie + Date: 2020/4/1 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "qfalloca.h" + +#if defined(_WIN32) && defined(HAVE_MALLOC_H) +#include +#endif + +#include "QF/progs.h" + +#include "rua_internal.h" + +static void +bi_va_copy (progs_t *pr) +{ + __auto_type src_args = (pr_va_list_t *) &P_POINTER (pr, 0); + __auto_type src_list = &G_STRUCT (pr, pr_type_t, src_args->list); + size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); + size_t size = src_args->count * parm_size; + string_t dst_list_block = PR_AllocTempBlock (pr, size); + __auto_type dst_list = (pr_type_t *) PR_GetString (pr, dst_list_block); + + memcpy (dst_list, src_list, size); + R_PACKED (pr, pr_va_list_t).count = src_args->count; + R_PACKED (pr, pr_va_list_t).list = PR_SetPointer (pr, dst_list); +} + +static builtin_t builtins[] = { + {"va_copy", bi_va_copy, -1}, + {0} +}; + +void +RUA_Runtime_Init (progs_t *pr, int secure) +{ + PR_RegisterBuiltins (pr, builtins); +} diff --git a/ruamoko/include/runtime.h b/ruamoko/include/runtime.h index 80e0aff7e..276d270fb 100644 --- a/ruamoko/include/runtime.h +++ b/ruamoko/include/runtime.h @@ -100,6 +100,10 @@ typedef enum { @extern void *PR_FindGlobal (string name); //FIXME where? +// copies the list in src to a temporary buffer that will be freed when the +// calling function returns, and places the pointer to the buffer into the +// returned va_list. The count is copies as-is. +@extern @va_list va_copy(@va_list src); #endif //__ruamoko_runtime_h_ /** \} diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index 2f67f04fd..cf0e50154 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -36,7 +36,7 @@ r_depfiles_remade= libr_a_SOURCES=\ cbuf.r cmd.r cvar.r hash.r msgbuf.r plist.r qfile.r qfs.r script.r \ - sound.r string.r math.r types.r \ + sound.r string.r math.r types.r va_list.r \ obj_forward.r \ Object.r Protocol.r \ AutoreleasePool.r Array.r Array+Private.r Entity.r PropertyList.r Set.r diff --git a/ruamoko/lib/va_list.r b/ruamoko/lib/va_list.r new file mode 100644 index 000000000..399e05933 --- /dev/null +++ b/ruamoko/lib/va_list.r @@ -0,0 +1,3 @@ +#include + +@va_list va_copy(@va_list src) = #0; diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index 31005878f..579f804c1 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -239,7 +239,7 @@ updateScreenCursor (View *view) { pos.x += xpos; pos.y += ypos; - [textContext mvvprintf: pos, fmt, @args]; + [textContext mvvprintf: pos, fmt, va_copy (@args)]; } - (void) mvvprintf: (Point) pos, string fmt, @va_list args From 0e7c7640f4ebeaa9deae8841ecc327df1f0b4dfa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 19:57:24 +0900 Subject: [PATCH 1002/3664] [qwaq] Right-justify def value display Now that *printf("%*.*s") works :) --- ruamoko/qwaq/debugger/basicview.r | 2 +- ruamoko/qwaq/debugger/doubleview.r | 2 +- ruamoko/qwaq/debugger/entityview.r | 2 +- ruamoko/qwaq/debugger/fieldview.r | 2 +- ruamoko/qwaq/debugger/floatview.r | 2 +- ruamoko/qwaq/debugger/funcview.r | 2 +- ruamoko/qwaq/debugger/intview.r | 2 +- ruamoko/qwaq/debugger/pointerview.r | 2 +- ruamoko/qwaq/debugger/quatview.r | 2 +- ruamoko/qwaq/debugger/stringview.r | 2 +- ruamoko/qwaq/debugger/uintview.r | 2 +- ruamoko/qwaq/debugger/vectorview.r | 2 +- ruamoko/qwaq/debugger/voidview.r | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ruamoko/qwaq/debugger/basicview.r b/ruamoko/qwaq/debugger/basicview.r index 4404f43e6..5701a27d3 100644 --- a/ruamoko/qwaq/debugger/basicview.r +++ b/ruamoko/qwaq/debugger/basicview.r @@ -42,7 +42,7 @@ static string type_views[] = { if (class) { return [class withType:type at:offset in:data]; } - return [NameView withName:"Invalid Meta"]; + return [NameView withName:"Invalid Type"]; } @end diff --git a/ruamoko/qwaq/debugger/doubleview.r b/ruamoko/qwaq/debugger/doubleview.r index 2a76033b5..977adbe28 100644 --- a/ruamoko/qwaq/debugger/doubleview.r +++ b/ruamoko/qwaq/debugger/doubleview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("%.17g", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/entityview.r b/ruamoko/qwaq/debugger/entityview.r index 6990886e6..52d152dae 100644 --- a/ruamoko/qwaq/debugger/entityview.r +++ b/ruamoko/qwaq/debugger/entityview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("FIXME [%x]", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/fieldview.r b/ruamoko/qwaq/debugger/fieldview.r index ea00ff14f..657e75cc9 100644 --- a/ruamoko/qwaq/debugger/fieldview.r +++ b/ruamoko/qwaq/debugger/fieldview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("FIXME [%x]", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/floatview.r b/ruamoko/qwaq/debugger/floatview.r index 1e90f8320..8abc6a1b4 100644 --- a/ruamoko/qwaq/debugger/floatview.r +++ b/ruamoko/qwaq/debugger/floatview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("%.9", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/funcview.r b/ruamoko/qwaq/debugger/funcview.r index b9f540807..540e75013 100644 --- a/ruamoko/qwaq/debugger/funcview.r +++ b/ruamoko/qwaq/debugger/funcview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("FIXME [%x]", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/intview.r b/ruamoko/qwaq/debugger/intview.r index aeedd0640..613f4e787 100644 --- a/ruamoko/qwaq/debugger/intview.r +++ b/ruamoko/qwaq/debugger/intview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("%d", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/pointerview.r b/ruamoko/qwaq/debugger/pointerview.r index 680b8accc..1159bf6ab 100644 --- a/ruamoko/qwaq/debugger/pointerview.r +++ b/ruamoko/qwaq/debugger/pointerview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("FIXME [%x]", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/quatview.r b/ruamoko/qwaq/debugger/quatview.r index 944a02e58..bd79e9ae9 100644 --- a/ruamoko/qwaq/debugger/quatview.r +++ b/ruamoko/qwaq/debugger/quatview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("%.9q", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/stringview.r b/ruamoko/qwaq/debugger/stringview.r index 445ccfdbf..00e0e583c 100644 --- a/ruamoko/qwaq/debugger/stringview.r +++ b/ruamoko/qwaq/debugger/stringview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("FIXME %s", qdb_get_string (target, data[0]));// quote string - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/uintview.r b/ruamoko/qwaq/debugger/uintview.r index d1efc4a17..0969567d3 100644 --- a/ruamoko/qwaq/debugger/uintview.r +++ b/ruamoko/qwaq/debugger/uintview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("%u", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/vectorview.r b/ruamoko/qwaq/debugger/vectorview.r index 0d29865d3..028dc889f 100644 --- a/ruamoko/qwaq/debugger/vectorview.r +++ b/ruamoko/qwaq/debugger/vectorview.r @@ -21,7 +21,7 @@ { [super draw]; string val = sprintf ("%.9v", data[0]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/debugger/voidview.r b/ruamoko/qwaq/debugger/voidview.r index 3683a08f3..e50f66873 100644 --- a/ruamoko/qwaq/debugger/voidview.r +++ b/ruamoko/qwaq/debugger/voidview.r @@ -22,7 +22,7 @@ [super draw]; string val = sprintf ("%08x %08x %08x %08x", data[0], data[1], data[2], data[3]); - [self mvaddstr:{0, 0}, str_mid (val, 0, xlen)]; + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } From 41184bd97d884210f4c9ebee04eaa1b5e94bfac0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 20:50:42 +0900 Subject: [PATCH 1003/3664] [gamecode] Document the format state machine --- libs/gamecode/pr_strings.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index d9d3f69df..1b5051859 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -835,6 +835,37 @@ fmt_append_item (fmt_state_t *state) #undef P_DOUBLE #define P_DOUBLE(p,n) (*(double *) (state->args[n])) +/** State machine for PR_Sprintf + * + * Parsing of the format string is implemented via the following state + * machine. Note that in all states, end-of-string terminates the machine. + * If the machine terminates in any state other than format or conversion, + * an error is generated. + * \dot + * digraph PR_Sprintf_fmt_state_machine { + * format -> flags [label="{%}"]; + * flags -> flags [label="{#+0 -}"]; + * flags -> var_field_width [label="{*}"]; + * flags -> precision [label="{.}"]; + * flags -> field_width [label="{[1-9]}"]; + * flags -> modifiers [label="other"]; + * var_field_width -> precision [label="{.}"]; + * var_field_width -> modifiers [label="other"]; + * field_width -> field_width [label="{[0-9]}"]; + * field_width -> precision [label="{.}"]; + * field_width -> modifiers [label="other"]; + * precision -> var_precision [label="{*}"]; + * precision -> fixed_precision [label="{[0-9]}"]; + * precision -> modifiers [label="other"]; + * var_precision -> modifiers [label="instant"]; + * fixed_precision -> fixed_precision [label="{[0-9]}"]; + * fixed_precision -> modifiers [label="other"]; + * modifiers -> conversion [label="instant/other"]; + * conversion -> format [label="other"]; + * } + * \enddot + */ +///@{ static void fmt_state_format (fmt_state_t *state); static void fmt_state_flags (fmt_state_t *state); static void fmt_state_var_field_width (fmt_state_t *state); @@ -1105,6 +1136,7 @@ fmt_state_format (fmt_state_t *state) state->state = 0; // finished } } +///@} VISIBLE void PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, From a09eabeb4d772d9b8afd7f7134c1be37ca8ea150 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 21:17:13 +0900 Subject: [PATCH 1004/3664] [qfcc] Fix some const attribute warnings Try to anticipate gcc's warnings and it one-ups you :P --- tools/qfcc/include/class.h | 8 ++++---- tools/qfcc/source/stub.c | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index 048ae8227..ec160e1d9 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -119,10 +119,10 @@ int is_id (const struct type_s *type) __attribute__((pure)); int is_class (const struct type_s *type) __attribute__((pure)); int is_Class (const struct type_s *type) __attribute__((const)); int is_classptr (const struct type_s *type) __attribute__((pure)); -int is_SEL (const struct type_s *type) __attribute__((pure)); -int is_object (const struct type_s *type) __attribute__((pure)); -int is_method (const struct type_s *type) __attribute__((pure)); -int is_method_description (const struct type_s *type) __attribute__((pure)); +int is_SEL (const struct type_s *type) __attribute__((const)); +int is_object (const struct type_s *type) __attribute__((const)); +int is_method (const struct type_s *type) __attribute__((const)); +int is_method_description (const struct type_s *type) __attribute__((const)); int obj_types_assignable (const struct type_s *dst, const struct type_s *src); class_t *extract_class (class_type_t *class_type) __attribute__((pure)); diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index b7d73cd68..449e62436 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -53,5 +53,6 @@ int compare_protocols (protocollist_t *protos1, protocollist_t *protos2){return void dump_dot (const char *stage, void *data, void (*dump_func) (void *data, const char *fname)){} void dump_dot_type (void *_t, const char *filename){} -const char *strip_path(const char *p) { return p;} -const char *file_basename(const char *p, int keepdot) { return p;} +char *fubar; +const char *strip_path(const char *p) { return fubar;} +const char *file_basename(const char *p, int keepdot) { return fubar;} From 6b9d4a747d844d3522b2511f61da754b3a06f0d6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 21:28:25 +0900 Subject: [PATCH 1005/3664] [ruamoko] Add a builtin to quote strings All unprintable chars are converted to either standard escape sequences or \xHH. --- libs/ruamoko/rua_string.c | 40 +++++++++++++++++++++++++++++++++++++++ ruamoko/include/string.h | 1 + ruamoko/lib/string.r | 1 + 3 files changed, 42 insertions(+) diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index a8240a85c..6de9c5c01 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -208,6 +208,45 @@ bi_str_char (progs_t *pr) R_INT (pr) = str[ind]; } +static void +bi_str_quote (progs_t *pr) +{ + const char *str = P_GSTRING (pr, 0); + // can have up to 4 chars per char (a -> \x61) + char *quote = alloca (strlen (str) * 4 + 1); + char *q = quote; + char c; + int h; + + while ((c = *str++)) { + if (c >= ' ' && c < 127 && c != '\"') { + *q++ = c; + } else { + *q++ = '\\'; + switch (c) { + case '\a': c = 'a'; break; + case '\b': c = 'b'; break; + case '\f': c = 'f'; break; + case '\n': c = 'n'; break; + case '\r': c = 'r'; break; + case '\t': c = 't'; break; + case '\"': c = '\"'; break; + default: + *q++ = 'x'; + h = (c & 0xf0) >> 4; + *q++ = h > 9 ? h + 'a' - 10 : h + '0'; + h = (c & 0x0f); + c = h > 9 ? h + 'a' - 10 : h + '0'; + break; + } + *q++ = c; + } + } + *q++ = 0; + + RETURN_STRING (pr, quote); +} + static builtin_t builtins[] = { {"strlen", bi_strlen, -1}, {"sprintf", bi_sprintf, -1}, @@ -224,6 +263,7 @@ static builtin_t builtins[] = { {"str_mid|*ii", bi_str_mid, -1}, {"str_str", bi_str_str, -1}, {"str_char", bi_str_char, -1}, + {"str_quote", bi_str_quote, -1}, {0} }; diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index b374b8335..008e7d883 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -16,5 +16,6 @@ @extern @overload string str_mid (string str, int start, int len); @extern string str_str (string haystack, string needle); @extern int str_char (string str, int ind); +string str_quote (string str); #endif//__ruamoko_string_h diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index 89ecc6aef..48a9a7bf7 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -15,3 +15,4 @@ string (string str, int start) str_mid = #0; string (string str, int start, int len) str_mid = #0; string (string haystack, string needle) str_str = #0; int str_char (string str, int ind) = #0; +string str_quote (string str) = #0; From 154da7653dbaab1abb151a5445060d613845d5d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 21:29:42 +0900 Subject: [PATCH 1006/3664] [qwaq] Quote the string value before display --- ruamoko/qwaq/debugger/stringview.r | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/debugger/stringview.r b/ruamoko/qwaq/debugger/stringview.r index 00e0e583c..0cf53752d 100644 --- a/ruamoko/qwaq/debugger/stringview.r +++ b/ruamoko/qwaq/debugger/stringview.r @@ -20,7 +20,8 @@ -draw { [super draw]; - string val = sprintf ("FIXME %s", qdb_get_string (target, data[0]));// quote string + string val = sprintf ("\"%s\"", + str_quote (qdb_get_string (target, data[0]))); [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } From d9668a1185159abdc15fc5fd58ef910b8fe6f9e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 00:11:34 +0900 Subject: [PATCH 1007/3664] [qwaq] Silence some more debug I was wondering where those sprintfs were going --- ruamoko/qwaq/ui/draw.r | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/ui/draw.r b/ruamoko/qwaq/ui/draw.r index 37be4e6c0..ebb75fcbd 100644 --- a/ruamoko/qwaq/ui/draw.r +++ b/ruamoko/qwaq/ui/draw.r @@ -53,8 +53,8 @@ Rect r = { {}, size }; Rect t = { pos, rect.extent }; - wprintf (stdscr, "src: %p\n", srcBuffer); - wprintf (stdscr, "srcSize: %d %d\n", srcSize.width, srcSize.height); + //wprintf (stdscr, "src: %p\n", srcBuffer); + //wprintf (stdscr, "srcSize: %d %d\n", srcSize.width, srcSize.height); t = clipRect (r, t); if (t.extent.width < 0 || t.extent.height < 0) { From 1d5058d2677f74a331c1ef8808932a4494929ea3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 00:11:47 +0900 Subject: [PATCH 1008/3664] [qwaq] Move progs create and load into the threads While this does answer the question of how I'll go about restarting the target progs (when I get to that point), it was required just to start full-on ruamoko progs because .ctor was getting run in the main thread and blocking due to trace. --- ruamoko/qwaq/builtins/main.c | 20 +++++++++++++------- ruamoko/qwaq/qwaq.h | 4 ++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index c78a9f9e5..9077054b2 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -140,19 +140,22 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); + // Normally, this is done by PR_Init, but PR_Init is not called in the main + // thread. However, PR_Opcode_Init() is idempotent. + PR_Opcode_Init (); } -typedef void (*progsinit_f) (progs_t *pr); - static progs_t * -create_progs (progsinit_f *funcs) +create_progs (qwaq_thread_t *thread) { progs_t *pr = calloc (1, sizeof (*pr)); + progsinit_f *funcs = thread->progsinit; pr->load_file = load_file; pr->allocate_progs_mem = allocate_progs_mem; pr->free_progs_mem = free_progs_mem; pr->no_exec_limit = 1; + pr->hashlink_freelist = &thread->hashlink_freelist; PR_Init_Cvars (); PR_Init (pr); @@ -185,7 +188,7 @@ load_progs (progs_t *pr, const char *name) } static void -spawn_progs (qwaq_thread_t *thread, progsinit_f *funcs) +spawn_progs (qwaq_thread_t *thread) { dfunction_t *dfunc; const char *name = 0; @@ -194,7 +197,7 @@ spawn_progs (qwaq_thread_t *thread, progsinit_f *funcs) progs_t *pr; thread->main_func = 0; - pr = thread->pr = create_progs (funcs); + pr = thread->pr = create_progs (thread); if (thread->args.size) { name = thread->args.a[0]; } @@ -230,6 +233,9 @@ run_progs (void *data) { __auto_type thread = (qwaq_thread_t *) data; + spawn_progs (thread); + Sys_Printf ("starthing thread for %s\n", thread->args.a[0]); + PR_ExecuteProgram (thread->pr, thread->main_func); PR_PopFrame (thread->pr); if (thread->pr->debug_handler) { @@ -452,13 +458,13 @@ main (int argc, char **argv) main_ind = i; app_funcs = main_app; } - spawn_progs (thread, app_funcs); + thread->progsinit = app_funcs; } if (main_ind >= 0) { // threads might start new threads before the end is reached size_t count = thread_data.size; for (size_t i = 0; i < count; i++) { - if (thread_data.a[i]->pr && thread_data.a[i]->main_func) { + if (thread_data.a[i]->progsinit) { start_progs_thread (thread_data.a[i]); } } diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index da9ec6e98..43efc4700 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -5,12 +5,16 @@ #include "QF/progs.h" #include "QF/sys.h" +typedef void (*progsinit_f) (progs_t *pr); + typedef struct qwaq_thread_s { pthread_t thread_id; int return_code; struct DARRAY_TYPE (const char *) args; sys_printf_t sys_printf; + progsinit_f*progsinit; progs_t *pr; + struct hashlink_s *hashlink_freelist; func_t main_func; void *data; } qwaq_thread_t; From 118fba8df5445007c2d7a2d55588d4901ff36ee6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 00:51:22 +0900 Subject: [PATCH 1009/3664] [qwaq] Cope with functions that don't have locals In this case, .ctor functions. --- ruamoko/qwaq/builtins/debug.c | 2 +- ruamoko/qwaq/debugger/localsdata.r | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 218a953cb..2b2bd2415 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -482,7 +482,7 @@ qdb_get_local_defs (progs_t *pr) pr_auxfunction_t *auxfunc = PR_Debug_MappedAuxFunction (tpr, fnum); R_INT (pr) = 0; - if (auxfunc) { + if (auxfunc && auxfunc->num_locals) { pr_def_t *defs = PR_Debug_LocalDefs (tpr, auxfunc); __auto_type qdefs = (qdb_def_t *) PR_Zone_Malloc (pr, diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index 7e6472191..45d15fc8e 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -58,7 +58,7 @@ if (aux_func) { defs = qdb_get_local_defs (target, fnum); } - if (func) { + if (func && func.local_size) { data = obj_malloc (func.local_size); } return self; From c920c746f3f97097ea3bb3f7c11b029431114aff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 10:39:12 +0900 Subject: [PATCH 1010/3664] [gamecode] Move debug even enum to pr_debug.h --- include/QF/pr_debug.h | 14 ++++++++++++++ include/QF/progs.h | 12 ------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/QF/pr_debug.h b/include/QF/pr_debug.h index be398f056..9811afe67 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/pr_debug.h @@ -31,6 +31,7 @@ #ifndef __QF_pr_debug_h #define __QF_pr_debug_h +#ifndef __QFCC__ #include "QF/pr_comp.h" typedef struct pr_auxfunction_s { @@ -63,5 +64,18 @@ typedef struct pr_debug_header_s { pr_uint_t locals; pr_uint_t num_locals; } pr_debug_header_t; +#endif + +typedef enum prdebug_e { + prd_none, + prd_trace, + prd_breakpoint, + prd_watchpoint, + prd_subenter, + prd_subexit, // current invocation of PR_ExecuteProgram finished + prd_terminate, // not sent by VM + prd_runerror, + prd_error, // lower level error thann prd_runerror +} prdebug_t; #endif//__QF_pr_debug_h diff --git a/include/QF/progs.h b/include/QF/progs.h index 95d5db44c..d9f738846 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1725,18 +1725,6 @@ typedef struct { strref_t *tstr; ///< Linked list of temporary strings. } prstack_t; -typedef enum { - prd_none, - prd_trace, - prd_breakpoint, - prd_watchpoint, - prd_subenter, - prd_subexit, // current invocation of PR_ExecuteProgram finished - prd_terminate, // not sent by VM - prd_runerror, - prd_error, // lower level error thann prd_runerror -} prdebug_t; - struct progs_s { int (*parse_field) (progs_t *pr, const char *key, const char *value); From 6d8bc395f428e98080cda1bc7a4ed255699b4248 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 10:44:16 +0900 Subject: [PATCH 1011/3664] [qwaq] Make debug event data available --- ruamoko/qwaq/builtins/debug.c | 34 ++++++++++++++++++++++++++++++++++ ruamoko/qwaq/builtins/main.c | 7 ++++--- ruamoko/qwaq/debugger/debug.h | 12 ++++++++++++ ruamoko/qwaq/debugger/debug.r | 1 + 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 2b2bd2415..287b5bcbe 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -56,6 +56,7 @@ typedef struct qwaq_target_s { struct qwaq_debug_s *debugger; int handle; prdebug_t event; + void *param; rwcond_t run_cond; } qwaq_target_t; @@ -117,6 +118,7 @@ qwaq_debug_handler (prdebug_t debug_event, void *param, void *data) int ret; target->event = debug_event; + target->param = param; event.what = qe_debug_event; event.message.pointer_val = target->handle; @@ -294,6 +296,37 @@ qdb_get_state (progs_t *pr) R_PACKED (pr, qdb_state_t) = state; } +static void +qdb_get_event (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + __auto_type event = &G_STRUCT (pr, qdb_event_t, P_INT (pr, 1)); + + memset (event, 0, sizeof (*event)); + event->what = target->event; + switch (event->what) { + case prd_subenter: + event->func = *(func_t *) target->param; + break; + case prd_runerror: + case prd_error: + event->message = PR_SetReturnString (pr, *(char **) target->param); + break; + case prd_terminate: + event->exit_code = *(int *) target->param; + break; + case prd_trace: + case prd_breakpoint: + case prd_watchpoint: + case prd_subexit: + case prd_none: + break; + } + R_INT (pr) = target->event != prd_none; +} + static void qdb_get_data (progs_t *pr) { @@ -505,6 +538,7 @@ static builtin_t builtins[] = { {"qdb_clear_watchpoint", qdb_clear_watchpoint, -1}, {"qdb_continue", qdb_continue, -1}, {"qdb_get_state", qdb_get_state, -1}, + {"qdb_get_event", qdb_get_event, -1}, {"qdb_get_data", qdb_get_data, -1}, {"qdb_get_string|{tag qdb_target_s=}i", qdb_get_string, -1}, {"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1}, diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 9077054b2..077b4674f 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -238,10 +238,11 @@ run_progs (void *data) PR_ExecuteProgram (thread->pr, thread->main_func); PR_PopFrame (thread->pr); - if (thread->pr->debug_handler) { - thread->pr->debug_handler (prd_terminate, 0, thread->pr->debug_data); - } thread->return_code = R_INT (thread->pr); + if (thread->pr->debug_handler) { + thread->pr->debug_handler (prd_terminate, &thread->return_code, + thread->pr->debug_data); + } return thread; } diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index 161014b84..b7ead7c92 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -9,6 +9,8 @@ typedef enum { #ifdef __QFCC__ +#include + //FIXME finish unsigned in qfcc #ifndef umax #define umax 0x7fffffff @@ -18,6 +20,15 @@ typedef string string_t; #endif +typedef struct qdb_event_s { + prdebug_t what; + union { + string_t message; + unsigned func; + int exit_code; + }; +} qdb_event_t; + typedef struct qdb_state_s { unsigned staddr; unsigned func; @@ -62,6 +73,7 @@ int qdb_set_watchpoint (qdb_target_t target, unsigned offset); int qdb_clear_watchpoint (qdb_target_t target); int qdb_continue (qdb_target_t target); qdb_state_t qdb_get_state (qdb_target_t target); +int qdb_get_event (qdb_target_t target, qdb_event_t *event); int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst); @overload string qdb_get_string (qdb_target_t target, unsigned str); // note: str is likely not valid in the host progs, it's just a convinience to diff --git a/ruamoko/qwaq/debugger/debug.r b/ruamoko/qwaq/debugger/debug.r index 7ad286cf7..7aa1b457c 100644 --- a/ruamoko/qwaq/debugger/debug.r +++ b/ruamoko/qwaq/debugger/debug.r @@ -10,6 +10,7 @@ int qdb_set_watchpoint (qdb_target_t target, unsigned offset) = #0; int qdb_clear_watchpoint (qdb_target_t target) = #0; int qdb_continue (qdb_target_t target) = #0; qdb_state_t qdb_get_state (qdb_target_t target) = #0; +int qdb_get_event (qdb_target_t target, qdb_event_t *event) = #0; int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst) = #0; string qdb_get_string (qdb_target_t target, unsigned str) = #0; From 7e51f26b108f38858d02e5e41fff1aff53947a84 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 13:06:31 +0900 Subject: [PATCH 1012/3664] [qwaq] Move all the def views into a subdirectory More declutter. --- ruamoko/qwaq/Makefile.am | 30 +++++++++---------- ruamoko/qwaq/debugger/localsdata.r | 4 +-- ruamoko/qwaq/debugger/{ => views}/basicview.h | 2 +- ruamoko/qwaq/debugger/{ => views}/basicview.r | 4 +-- ruamoko/qwaq/debugger/{ => views}/defview.h | 0 ruamoko/qwaq/debugger/{ => views}/defview.r | 4 +-- .../qwaq/debugger/{ => views}/doubleview.h | 2 +- .../qwaq/debugger/{ => views}/doubleview.r | 2 +- .../qwaq/debugger/{ => views}/entityview.h | 2 +- .../qwaq/debugger/{ => views}/entityview.r | 2 +- ruamoko/qwaq/debugger/{ => views}/fieldview.h | 2 +- ruamoko/qwaq/debugger/{ => views}/fieldview.r | 2 +- ruamoko/qwaq/debugger/{ => views}/floatview.h | 2 +- ruamoko/qwaq/debugger/{ => views}/floatview.r | 2 +- ruamoko/qwaq/debugger/{ => views}/funcview.h | 2 +- ruamoko/qwaq/debugger/{ => views}/funcview.r | 2 +- ruamoko/qwaq/debugger/{ => views}/intview.h | 2 +- ruamoko/qwaq/debugger/{ => views}/intview.r | 2 +- ruamoko/qwaq/debugger/{ => views}/nameview.h | 2 +- ruamoko/qwaq/debugger/{ => views}/nameview.r | 2 +- .../qwaq/debugger/{ => views}/pointerview.h | 2 +- .../qwaq/debugger/{ => views}/pointerview.r | 2 +- ruamoko/qwaq/debugger/{ => views}/quatview.h | 2 +- ruamoko/qwaq/debugger/{ => views}/quatview.r | 2 +- .../qwaq/debugger/{ => views}/stringview.h | 2 +- .../qwaq/debugger/{ => views}/stringview.r | 2 +- ruamoko/qwaq/debugger/{ => views}/uintview.h | 2 +- ruamoko/qwaq/debugger/{ => views}/uintview.r | 2 +- .../qwaq/debugger/{ => views}/vectorview.h | 2 +- .../qwaq/debugger/{ => views}/vectorview.r | 2 +- ruamoko/qwaq/debugger/{ => views}/voidview.h | 2 +- ruamoko/qwaq/debugger/{ => views}/voidview.r | 2 +- 32 files changed, 48 insertions(+), 48 deletions(-) rename ruamoko/qwaq/debugger/{ => views}/basicview.h (88%) rename ruamoko/qwaq/debugger/{ => views}/basicview.r (91%) rename ruamoko/qwaq/debugger/{ => views}/defview.h (100%) rename ruamoko/qwaq/debugger/{ => views}/defview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/doubleview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/doubleview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/entityview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/entityview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/fieldview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/fieldview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/floatview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/floatview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/funcview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/funcview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/intview.h (86%) rename ruamoko/qwaq/debugger/{ => views}/intview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/nameview.h (84%) rename ruamoko/qwaq/debugger/{ => views}/nameview.r (91%) rename ruamoko/qwaq/debugger/{ => views}/pointerview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/pointerview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/quatview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/quatview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/stringview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/stringview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/uintview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/uintview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/vectorview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/vectorview.r (93%) rename ruamoko/qwaq/debugger/{ => views}/voidview.h (87%) rename ruamoko/qwaq/debugger/{ => views}/voidview.r (94%) diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am index b4e513314..2208777f5 100644 --- a/ruamoko/qwaq/Makefile.am +++ b/ruamoko/qwaq/Makefile.am @@ -27,21 +27,21 @@ SUFFIXES=.o .r qwaq_app_dat_src= \ qwaq-app.r \ - debugger/defview.r \ - debugger/nameview.r \ - debugger/basicview.r \ - debugger/doubleview.r \ - debugger/entityview.r \ - debugger/fieldview.r \ - debugger/floatview.r \ - debugger/funcview.r \ - debugger/intview.r \ - debugger/pointerview.r \ - debugger/quatview.r \ - debugger/stringview.r \ - debugger/uintview.r \ - debugger/vectorview.r \ - debugger/voidview.r \ + debugger/views/basicview.r \ + debugger/views/defview.r \ + debugger/views/doubleview.r \ + debugger/views/entityview.r \ + debugger/views/fieldview.r \ + debugger/views/floatview.r \ + debugger/views/funcview.r \ + debugger/views/intview.r \ + debugger/views/nameview.r \ + debugger/views/pointerview.r\ + debugger/views/quatview.r \ + debugger/views/stringview.r \ + debugger/views/uintview.r \ + debugger/views/vectorview.r \ + debugger/views/voidview.r \ debugger/debug.r \ debugger/debugger.r \ debugger/localsdata.r \ diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index 45d15fc8e..d380f9fe5 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -1,7 +1,7 @@ #include #include -#include "debugger/defview.h" -#include "debugger/nameview.h" +#include "debugger/views/defview.h" +#include "debugger/views/nameview.h" #include "debugger/localsdata.h" #include "debugger/typeencodings.h" diff --git a/ruamoko/qwaq/debugger/basicview.h b/ruamoko/qwaq/debugger/views/basicview.h similarity index 88% rename from ruamoko/qwaq/debugger/basicview.h rename to ruamoko/qwaq/debugger/views/basicview.h index 773ab6794..d9289889f 100644 --- a/ruamoko/qwaq/debugger/basicview.h +++ b/ruamoko/qwaq/debugger/views/basicview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_basicview_h #define __qwaq_debugger_basicview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface BasicView : DefView // might return a NameView (which is also a DefView) diff --git a/ruamoko/qwaq/debugger/basicview.r b/ruamoko/qwaq/debugger/views/basicview.r similarity index 91% rename from ruamoko/qwaq/debugger/basicview.r rename to ruamoko/qwaq/debugger/views/basicview.r index 5701a27d3..8a2067285 100644 --- a/ruamoko/qwaq/debugger/basicview.r +++ b/ruamoko/qwaq/debugger/views/basicview.r @@ -1,6 +1,6 @@ #include -#include "debugger/basicview.h" -#include "debugger/nameview.h" +#include "debugger/views/basicview.h" +#include "debugger/views/nameview.h" static string type_views[] = { "VoidView", diff --git a/ruamoko/qwaq/debugger/defview.h b/ruamoko/qwaq/debugger/views/defview.h similarity index 100% rename from ruamoko/qwaq/debugger/defview.h rename to ruamoko/qwaq/debugger/views/defview.h diff --git a/ruamoko/qwaq/debugger/defview.r b/ruamoko/qwaq/debugger/views/defview.r similarity index 93% rename from ruamoko/qwaq/debugger/defview.r rename to ruamoko/qwaq/debugger/views/defview.r index f115c8e61..ee681e23e 100644 --- a/ruamoko/qwaq/debugger/defview.r +++ b/ruamoko/qwaq/debugger/views/defview.r @@ -1,6 +1,6 @@ #include -#include "debugger/defview.h" -#include "debugger/nameview.h" +#include "debugger/views/defview.h" +#include "debugger/views/nameview.h" static string meta_views[] = { "BasicView", diff --git a/ruamoko/qwaq/debugger/doubleview.h b/ruamoko/qwaq/debugger/views/doubleview.h similarity index 87% rename from ruamoko/qwaq/debugger/doubleview.h rename to ruamoko/qwaq/debugger/views/doubleview.h index 0ddea40c1..8fda5ac24 100644 --- a/ruamoko/qwaq/debugger/doubleview.h +++ b/ruamoko/qwaq/debugger/views/doubleview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_doubleview_h #define __qwaq_debugger_doubleview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface DoubleView : DefView { diff --git a/ruamoko/qwaq/debugger/doubleview.r b/ruamoko/qwaq/debugger/views/doubleview.r similarity index 93% rename from ruamoko/qwaq/debugger/doubleview.r rename to ruamoko/qwaq/debugger/views/doubleview.r index 977adbe28..36fbfd59d 100644 --- a/ruamoko/qwaq/debugger/doubleview.r +++ b/ruamoko/qwaq/debugger/views/doubleview.r @@ -1,5 +1,5 @@ #include -#include "debugger/doubleview.h" +#include "debugger/views/doubleview.h" @implementation DoubleView diff --git a/ruamoko/qwaq/debugger/entityview.h b/ruamoko/qwaq/debugger/views/entityview.h similarity index 87% rename from ruamoko/qwaq/debugger/entityview.h rename to ruamoko/qwaq/debugger/views/entityview.h index 81ba29e9c..df8de2c3d 100644 --- a/ruamoko/qwaq/debugger/entityview.h +++ b/ruamoko/qwaq/debugger/views/entityview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_entityview_h #define __qwaq_debugger_entityview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface EntityView : DefView { diff --git a/ruamoko/qwaq/debugger/entityview.r b/ruamoko/qwaq/debugger/views/entityview.r similarity index 93% rename from ruamoko/qwaq/debugger/entityview.r rename to ruamoko/qwaq/debugger/views/entityview.r index 52d152dae..49180e914 100644 --- a/ruamoko/qwaq/debugger/entityview.r +++ b/ruamoko/qwaq/debugger/views/entityview.r @@ -1,5 +1,5 @@ #include -#include "debugger/entityview.h" +#include "debugger/views/entityview.h" @implementation EntityView diff --git a/ruamoko/qwaq/debugger/fieldview.h b/ruamoko/qwaq/debugger/views/fieldview.h similarity index 87% rename from ruamoko/qwaq/debugger/fieldview.h rename to ruamoko/qwaq/debugger/views/fieldview.h index bf793ec00..5d90bf77f 100644 --- a/ruamoko/qwaq/debugger/fieldview.h +++ b/ruamoko/qwaq/debugger/views/fieldview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_fieldview_h #define __qwaq_debugger_fieldview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface FieldView : DefView { diff --git a/ruamoko/qwaq/debugger/fieldview.r b/ruamoko/qwaq/debugger/views/fieldview.r similarity index 93% rename from ruamoko/qwaq/debugger/fieldview.r rename to ruamoko/qwaq/debugger/views/fieldview.r index 657e75cc9..49bf7282b 100644 --- a/ruamoko/qwaq/debugger/fieldview.r +++ b/ruamoko/qwaq/debugger/views/fieldview.r @@ -1,5 +1,5 @@ #include -#include "debugger/fieldview.h" +#include "debugger/views/fieldview.h" @implementation FieldView diff --git a/ruamoko/qwaq/debugger/floatview.h b/ruamoko/qwaq/debugger/views/floatview.h similarity index 87% rename from ruamoko/qwaq/debugger/floatview.h rename to ruamoko/qwaq/debugger/views/floatview.h index 4fa32be05..a51469709 100644 --- a/ruamoko/qwaq/debugger/floatview.h +++ b/ruamoko/qwaq/debugger/views/floatview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_floatview_h #define __qwaq_debugger_floatview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface FloatView : DefView { diff --git a/ruamoko/qwaq/debugger/floatview.r b/ruamoko/qwaq/debugger/views/floatview.r similarity index 93% rename from ruamoko/qwaq/debugger/floatview.r rename to ruamoko/qwaq/debugger/views/floatview.r index 8abc6a1b4..e98e9e8a8 100644 --- a/ruamoko/qwaq/debugger/floatview.r +++ b/ruamoko/qwaq/debugger/views/floatview.r @@ -1,5 +1,5 @@ #include -#include "debugger/floatview.h" +#include "debugger/views/floatview.h" @implementation FloatView diff --git a/ruamoko/qwaq/debugger/funcview.h b/ruamoko/qwaq/debugger/views/funcview.h similarity index 87% rename from ruamoko/qwaq/debugger/funcview.h rename to ruamoko/qwaq/debugger/views/funcview.h index 43cce6512..5a004800c 100644 --- a/ruamoko/qwaq/debugger/funcview.h +++ b/ruamoko/qwaq/debugger/views/funcview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_funcview_h #define __qwaq_debugger_funcview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface FuncView : DefView { diff --git a/ruamoko/qwaq/debugger/funcview.r b/ruamoko/qwaq/debugger/views/funcview.r similarity index 93% rename from ruamoko/qwaq/debugger/funcview.r rename to ruamoko/qwaq/debugger/views/funcview.r index 540e75013..c102bfce1 100644 --- a/ruamoko/qwaq/debugger/funcview.r +++ b/ruamoko/qwaq/debugger/views/funcview.r @@ -1,5 +1,5 @@ #include -#include "debugger/funcview.h" +#include "debugger/views/funcview.h" @implementation FuncView diff --git a/ruamoko/qwaq/debugger/intview.h b/ruamoko/qwaq/debugger/views/intview.h similarity index 86% rename from ruamoko/qwaq/debugger/intview.h rename to ruamoko/qwaq/debugger/views/intview.h index 531da879d..fddb2f2d5 100644 --- a/ruamoko/qwaq/debugger/intview.h +++ b/ruamoko/qwaq/debugger/views/intview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_intview_h #define __qwaq_debugger_intview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface IntView : DefView { diff --git a/ruamoko/qwaq/debugger/intview.r b/ruamoko/qwaq/debugger/views/intview.r similarity index 93% rename from ruamoko/qwaq/debugger/intview.r rename to ruamoko/qwaq/debugger/views/intview.r index 613f4e787..6caad42ac 100644 --- a/ruamoko/qwaq/debugger/intview.r +++ b/ruamoko/qwaq/debugger/views/intview.r @@ -1,5 +1,5 @@ #include -#include "debugger/intview.h" +#include "debugger/views/intview.h" @implementation IntView diff --git a/ruamoko/qwaq/debugger/nameview.h b/ruamoko/qwaq/debugger/views/nameview.h similarity index 84% rename from ruamoko/qwaq/debugger/nameview.h rename to ruamoko/qwaq/debugger/views/nameview.h index 1822df98e..7d5838bce 100644 --- a/ruamoko/qwaq/debugger/nameview.h +++ b/ruamoko/qwaq/debugger/views/nameview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_nameview_h #define __qwaq_debugger_nameview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface NameView : DefView { diff --git a/ruamoko/qwaq/debugger/nameview.r b/ruamoko/qwaq/debugger/views/nameview.r similarity index 91% rename from ruamoko/qwaq/debugger/nameview.r rename to ruamoko/qwaq/debugger/views/nameview.r index 52710170a..9764fedaf 100644 --- a/ruamoko/qwaq/debugger/nameview.r +++ b/ruamoko/qwaq/debugger/views/nameview.r @@ -1,5 +1,5 @@ #include -#include "debugger/nameview.h" +#include "debugger/views/nameview.h" @implementation NameView diff --git a/ruamoko/qwaq/debugger/pointerview.h b/ruamoko/qwaq/debugger/views/pointerview.h similarity index 87% rename from ruamoko/qwaq/debugger/pointerview.h rename to ruamoko/qwaq/debugger/views/pointerview.h index 6891d5f50..4853958e9 100644 --- a/ruamoko/qwaq/debugger/pointerview.h +++ b/ruamoko/qwaq/debugger/views/pointerview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_pointerview_h #define __qwaq_debugger_pointerview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface PointerView : DefView { diff --git a/ruamoko/qwaq/debugger/pointerview.r b/ruamoko/qwaq/debugger/views/pointerview.r similarity index 93% rename from ruamoko/qwaq/debugger/pointerview.r rename to ruamoko/qwaq/debugger/views/pointerview.r index 1159bf6ab..20743ea19 100644 --- a/ruamoko/qwaq/debugger/pointerview.r +++ b/ruamoko/qwaq/debugger/views/pointerview.r @@ -1,5 +1,5 @@ #include -#include "debugger/pointerview.h" +#include "debugger/views/pointerview.h" @implementation PointerView diff --git a/ruamoko/qwaq/debugger/quatview.h b/ruamoko/qwaq/debugger/views/quatview.h similarity index 87% rename from ruamoko/qwaq/debugger/quatview.h rename to ruamoko/qwaq/debugger/views/quatview.h index 2ea1934cd..189a600f8 100644 --- a/ruamoko/qwaq/debugger/quatview.h +++ b/ruamoko/qwaq/debugger/views/quatview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_quatview_h #define __qwaq_debugger_quatview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface QuatView : DefView { diff --git a/ruamoko/qwaq/debugger/quatview.r b/ruamoko/qwaq/debugger/views/quatview.r similarity index 93% rename from ruamoko/qwaq/debugger/quatview.r rename to ruamoko/qwaq/debugger/views/quatview.r index bd79e9ae9..ba98e9d2b 100644 --- a/ruamoko/qwaq/debugger/quatview.r +++ b/ruamoko/qwaq/debugger/views/quatview.r @@ -1,5 +1,5 @@ #include -#include "debugger/quatview.h" +#include "debugger/views/quatview.h" @implementation QuatView diff --git a/ruamoko/qwaq/debugger/stringview.h b/ruamoko/qwaq/debugger/views/stringview.h similarity index 87% rename from ruamoko/qwaq/debugger/stringview.h rename to ruamoko/qwaq/debugger/views/stringview.h index 62b009e5d..5cabaf674 100644 --- a/ruamoko/qwaq/debugger/stringview.h +++ b/ruamoko/qwaq/debugger/views/stringview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_stringview_h #define __qwaq_debugger_stringview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface StringView : DefView { diff --git a/ruamoko/qwaq/debugger/stringview.r b/ruamoko/qwaq/debugger/views/stringview.r similarity index 93% rename from ruamoko/qwaq/debugger/stringview.r rename to ruamoko/qwaq/debugger/views/stringview.r index 0cf53752d..79ef75212 100644 --- a/ruamoko/qwaq/debugger/stringview.r +++ b/ruamoko/qwaq/debugger/views/stringview.r @@ -1,5 +1,5 @@ #include -#include "debugger/stringview.h" +#include "debugger/views/stringview.h" @implementation StringView diff --git a/ruamoko/qwaq/debugger/uintview.h b/ruamoko/qwaq/debugger/views/uintview.h similarity index 87% rename from ruamoko/qwaq/debugger/uintview.h rename to ruamoko/qwaq/debugger/views/uintview.h index 752db5a20..9597c5519 100644 --- a/ruamoko/qwaq/debugger/uintview.h +++ b/ruamoko/qwaq/debugger/views/uintview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_uintview_h #define __qwaq_debugger_uintview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface UIntView : DefView { diff --git a/ruamoko/qwaq/debugger/uintview.r b/ruamoko/qwaq/debugger/views/uintview.r similarity index 93% rename from ruamoko/qwaq/debugger/uintview.r rename to ruamoko/qwaq/debugger/views/uintview.r index 0969567d3..e06ac32fa 100644 --- a/ruamoko/qwaq/debugger/uintview.r +++ b/ruamoko/qwaq/debugger/views/uintview.r @@ -1,5 +1,5 @@ #include -#include "debugger/uintview.h" +#include "debugger/views/uintview.h" @implementation UIntView diff --git a/ruamoko/qwaq/debugger/vectorview.h b/ruamoko/qwaq/debugger/views/vectorview.h similarity index 87% rename from ruamoko/qwaq/debugger/vectorview.h rename to ruamoko/qwaq/debugger/views/vectorview.h index 51d2ffc34..b6b95fa34 100644 --- a/ruamoko/qwaq/debugger/vectorview.h +++ b/ruamoko/qwaq/debugger/views/vectorview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_vectorview_h #define __qwaq_debugger_vectorview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface VectorView : DefView { diff --git a/ruamoko/qwaq/debugger/vectorview.r b/ruamoko/qwaq/debugger/views/vectorview.r similarity index 93% rename from ruamoko/qwaq/debugger/vectorview.r rename to ruamoko/qwaq/debugger/views/vectorview.r index 028dc889f..2fa8b41ed 100644 --- a/ruamoko/qwaq/debugger/vectorview.r +++ b/ruamoko/qwaq/debugger/views/vectorview.r @@ -1,5 +1,5 @@ #include -#include "debugger/vectorview.h" +#include "debugger/views/vectorview.h" @implementation VectorView diff --git a/ruamoko/qwaq/debugger/voidview.h b/ruamoko/qwaq/debugger/views/voidview.h similarity index 87% rename from ruamoko/qwaq/debugger/voidview.h rename to ruamoko/qwaq/debugger/views/voidview.h index e0e19c675..6232968e0 100644 --- a/ruamoko/qwaq/debugger/voidview.h +++ b/ruamoko/qwaq/debugger/views/voidview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_voidview_h #define __qwaq_debugger_voidview_h -#include "debugger/defview.h" +#include "debugger/views/defview.h" @interface VoidView : DefView { diff --git a/ruamoko/qwaq/debugger/voidview.r b/ruamoko/qwaq/debugger/views/voidview.r similarity index 94% rename from ruamoko/qwaq/debugger/voidview.r rename to ruamoko/qwaq/debugger/views/voidview.r index e50f66873..440edece2 100644 --- a/ruamoko/qwaq/debugger/voidview.r +++ b/ruamoko/qwaq/debugger/views/voidview.r @@ -1,5 +1,5 @@ #include -#include "debugger/voidview.h" +#include "debugger/views/voidview.h" @implementation VoidView From ea1e85905cdf1046406d5f2a98cd542b1e5556db Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 13:07:50 +0900 Subject: [PATCH 1013/3664] [qwaq] Implement source-level stepping Now the debugger stops only when the source line has changed or the statement address is stuck. --- ruamoko/qwaq/debugger/debugger.h | 2 ++ ruamoko/qwaq/debugger/debugger.r | 54 +++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 9e827c73d..627558f1f 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -17,6 +17,8 @@ @interface Debugger : Object { qdb_target_t target; + qdb_event_t event; + qdb_state_t last_state; Window *source_window; ScrollBar *source_scrollbar; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 1cdad5e8d..0f78f2e7a 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -138,6 +138,7 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) switch (event.key.code) { case QFK_F7: qdb_set_trace (self.target, 1); + self.last_state = qdb_get_state (self.target); qdb_continue (self.target); return 1; } @@ -152,7 +153,7 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) } } --handleDebugEvent +-stop:(prdebug_t)reason { if (!file_proxy) { [self setup]; @@ -162,4 +163,55 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) return self; } +-trace +{ + qdb_state_t state = qdb_get_state (target); + + // stop only if the progs have not advanced (may be a broken jump) + // or the progs have advanced to a different source line + if (last_state.staddr != state.staddr + && last_state.func == state.func + && last_state.file == state.file + && last_state.line == state.line) { + last_state = state; + qdb_continue (self.target); + return self; + } + [self stop:prd_trace]; + return self; +} + +-handleDebugEvent +{ + if (qdb_get_event (target, &event)) { + switch (event.what) { + case prd_none: + break; // shouldn't happen + case prd_trace: + [self trace]; + break; + case prd_breakpoint: + case prd_watchpoint: + [self stop:event.what]; + break; + case prd_subenter: + [self stop:event.what]; + break; + case prd_subexit: + [self stop:event.what]; + break; + case prd_terminate: + wprintf(stdscr, "Program ended: %d\n", event.exit_code); + [self stop:event.what]; + break; + case prd_runerror: + case prd_error: + wprintf(stdscr, "%s\n", event.message); + [self stop:event.what]; + break; + } + } + return self; +} + @end From f90613bc3a1423b7b380f38d55c27df9eb107a4e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 15:00:01 +0900 Subject: [PATCH 1014/3664] [gamecode] Rename fields in pr_stack_t s and f are a little too succinct. --- include/QF/progs.h | 4 ++-- libs/gamecode/pr_debug.c | 18 +++++++++--------- libs/gamecode/pr_exec.c | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index d9f738846..db969f6af 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1720,8 +1720,8 @@ extern const char *pr_gametype; typedef struct strref_s strref_t; typedef struct { - pr_int_t s; ///< Return statement. - bfunction_t *f; ///< Calling function. + pr_int_t staddr; ///< Return statement. + bfunction_t *func; ///< Calling function. strref_t *tstr; ///< Linked list of temporary strings. } prstack_t; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index b1b7d217c..61e45ce8b 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1464,35 +1464,35 @@ static void dump_frame (progs_t *pr, prstack_t *frame) { prdeb_resources_t *res = pr->pr_debug_resources; - dfunction_t *f = frame->f ? frame->f->descriptor : 0; + dfunction_t *f = frame->func ? frame->func->descriptor : 0; if (!f) { Sys_Printf ("\n"); return; } if (pr_debug->int_val && res->debug) { - pr_lineno_t *lineno = PR_Find_Lineno (pr, frame->s); + pr_lineno_t *lineno = PR_Find_Lineno (pr, frame->staddr); pr_auxfunction_t *func = PR_Get_Lineno_Func (pr, lineno); pr_uint_t line = PR_Get_Lineno_Line (pr, lineno); pr_int_t addr = PR_Get_Lineno_Addr (pr, lineno); line += func->source_line; - if (addr == frame->s) { + if (addr == frame->staddr) { Sys_Printf ("%12s:%u : %s: %x\n", PR_GetString (pr, f->s_file), line, PR_GetString (pr, f->s_name), - frame->s); + frame->staddr); } else { Sys_Printf ("%12s:%u+%d : %s: %x\n", PR_GetString (pr, f->s_file), - line, frame->s - addr, + line, frame->staddr - addr, PR_GetString (pr, f->s_name), - frame->s); + frame->staddr); } } else { Sys_Printf ("%12s : %s: %x\n", PR_GetString (pr, f->s_file), - PR_GetString (pr, f->s_name), frame->s); + PR_GetString (pr, f->s_name), frame->staddr); } } @@ -1507,8 +1507,8 @@ PR_StackTrace (progs_t *pr) return; } - top.s = pr->pr_xstatement; - top.f = pr->pr_xfunction; + top.staddr = pr->pr_xstatement; + top.func = pr->pr_xfunction; dump_frame (pr, &top); for (i = pr->pr_depth - 1; i >= 0; i--) dump_frame (pr, pr->pr_stack + i); diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 9a287b4f9..4a79f8173 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -124,9 +124,9 @@ PR_PushFrame (progs_t *pr) frame = pr->pr_stack + pr->pr_depth++; - frame->s = pr->pr_xstatement; - frame->f = pr->pr_xfunction; - frame->tstr = pr->pr_xtstr; + frame->staddr = pr->pr_xstatement; + frame->func = pr->pr_xfunction; + frame->tstr = pr->pr_xtstr; pr->pr_xtstr = pr->pr_pushtstr; pr->pr_pushtstr = 0; @@ -158,8 +158,8 @@ PR_PopFrame (progs_t *pr) // up stack frame = pr->pr_stack + --pr->pr_depth; - pr->pr_xfunction = frame->f; - pr->pr_xstatement = frame->s; + pr->pr_xfunction = frame->func; + pr->pr_xstatement = frame->staddr; pr->pr_xtstr = frame->tstr; } From c09f57c39ed3fed8c812199904c66af7ad3d4ac4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 17:28:37 +0900 Subject: [PATCH 1015/3664] [gamecode] Delay .ctor calls if debugging This allows a debugger to do any symbol lookups and other preparations between loading progs and the first code execution. .ctors are called as per normal if debug_handler is not set. --- include/QF/progs.h | 20 +++++++++++++++----- libs/gamecode/pr_load.c | 12 +++++++++++- ruamoko/qwaq/builtins/main.c | 17 +++++++++++------ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index db969f6af..fd9d653f7 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -236,14 +236,24 @@ void PR_AddLoadFinishFunc (progs_t *pr, pr_load_func_t *func); \return true for success, false for failure Calls the first set of internal load functions followed by the supplied - symbol resolution function, if any (progs_t::resolve), the second set of - internal load functions. After that, any primary load functions are called - in order of registration followed by any \c .ctor functions in the progs, - then any secondary load functions the primary load functions registered - in \e reverse order of registration. + symbol resolution function, if any (progs_t::resolve), then the second set + of internal load functions. After that, any primary load functions are + called in order of registration, and if there is no debug handler, + PR_RunPostLoadFuncs() is called. */ int PR_RunLoadFuncs (progs_t *pr); +/** Run any progs-dependent load functions. + \param pr pointer to ::progs_t VM struct + \return true for success, false for failure + This means any \c .ctor functions in the progs, followed by any secondary + load functions registered by either the primary load functions or the + \.c ctor functions in \e reverse order of registration. This is called + automatically by PR_RunLoadFuncs() if there is no debug handler, otherwise + it is up to the host to call this function. +*/ +int PR_RunPostLoadFuncs (progs_t *pr); + /** Validate the opcodes and statement addresses in the progs. This is an internal load function. \param pr pointer to ::progs_t VM struct diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index dd405769a..6ef18cc15 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -422,6 +422,12 @@ PR_RunLoadFuncs (progs_t *pr) if (!pr->load_funcs[i] (pr)) return 0; + return 1; +} + +VISIBLE int +PR_RunPostLoadFuncs (progs_t *pr) +{ if (!pr_run_ctors (pr)) return 0; @@ -449,8 +455,12 @@ PR_LoadProgs (progs_t *pr, const char *progsname) if (!pr->progs) return; - if (!PR_RunLoadFuncs (pr)) + if (!PR_RunLoadFuncs (pr)) { PR_Error (pr, "unable to load %s", progsname); + } + if (!pr->debug_handler && !PR_RunPostLoadFuncs (pr)) { + PR_Error (pr, "unable to load %s", progsname); + } } VISIBLE void diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 077b4674f..491a35277 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -206,6 +206,17 @@ spawn_progs (qwaq_thread_t *thread) Sys_Error ("couldn't load %s", name); } + if ((dfunc = PR_FindFunction (pr, ".main")) + || (dfunc = PR_FindFunction (pr, "main"))) { + thread->main_func = dfunc - pr->pr_functions; + } else { + PR_Undefined (pr, "function", "main"); + } + + if (!PR_RunPostLoadFuncs (pr)) { + PR_Error (pr, "unable to load %s", pr->progs_name); + } + PR_PushFrame (pr); if (thread->args.size > 2) { pr_argc = thread->args.size - 1; @@ -216,12 +227,6 @@ spawn_progs (qwaq_thread_t *thread) pr_argv[i] = PR_SetTempString (pr, thread->args.a[1 + i]); pr_argv[i] = 0; - if ((dfunc = PR_FindFunction (pr, ".main")) - || (dfunc = PR_FindFunction (pr, "main"))) { - thread->main_func = dfunc - pr->pr_functions; - } else { - PR_Undefined (pr, "function", "main"); - } PR_RESET_PARAMS (pr); P_INT (pr, 0) = pr_argc; P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv); From 63caa5794d93cba8a74f7e6548e2f59ad9dc90a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 17:44:53 +0900 Subject: [PATCH 1016/3664] [qwaq] Implement step-over tracing I decided that stopping in between function calls that are on the same line is a good thing as it gives a chance to skip over the first but step into the second. --- include/QF/pr_debug.h | 1 + ruamoko/qwaq/builtins/debug.c | 54 +++++++++++++++++++--- ruamoko/qwaq/builtins/main.c | 5 ++ ruamoko/qwaq/debugger/debug.h | 10 +++- ruamoko/qwaq/debugger/debug.r | 2 + ruamoko/qwaq/debugger/debugger.h | 11 ++++- ruamoko/qwaq/debugger/debugger.r | 79 ++++++++++++++++++++++++++------ 7 files changed, 140 insertions(+), 22 deletions(-) diff --git a/include/QF/pr_debug.h b/include/QF/pr_debug.h index 9811afe67..4b87ee897 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/pr_debug.h @@ -73,6 +73,7 @@ typedef enum prdebug_e { prd_watchpoint, prd_subenter, prd_subexit, // current invocation of PR_ExecuteProgram finished + prd_begin, // not sent by VM prd_terminate, // not sent by VM prd_runerror, prd_error, // lower level error thann prd_runerror diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 287b5bcbe..4fec2a1ac 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -296,6 +296,41 @@ qdb_get_state (progs_t *pr) R_PACKED (pr, qdb_state_t) = state; } +static void +qdb_get_stack_depth (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + + R_INT (pr) = tpr->pr_depth; +} + +static void +qdb_get_stack (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + int count = tpr->pr_depth; + + R_POINTER (pr) = 0; + if (count > 0) { + size_t size = count * sizeof (qdb_stack_t); + string_t stack_block = PR_AllocTempBlock (pr, size); + __auto_type stack = (qdb_stack_t *) PR_GetString (pr, stack_block); + + for (int i = 0; i < count; i++) { + stack[i].staddr = tpr->pr_stack[i].staddr; + stack[i].func = tpr->pr_stack[i].func - tpr->pr_xfunction; + //XXX temp strings (need access somehow) + } + R_POINTER (pr) = PR_SetPointer (pr, stack); + } +} + static void qdb_get_event (progs_t *pr) { @@ -308,12 +343,15 @@ qdb_get_event (progs_t *pr) event->what = target->event; switch (event->what) { case prd_subenter: - event->func = *(func_t *) target->param; + event->function = *(func_t *) target->param; break; case prd_runerror: case prd_error: event->message = PR_SetReturnString (pr, *(char **) target->param); break; + case prd_begin: + event->function = *(func_t *) target->param; + break; case prd_terminate: event->exit_code = *(int *) target->param; break; @@ -411,7 +449,7 @@ qdb_find_field (progs_t *pr) static void return_function (progs_t *pr, dfunction_t *func) { - R_INT (pr) = 0; + R_POINTER (pr) = 0; if (func) { __auto_type f = (qdb_function_t *) PR_Zone_Malloc (pr, sizeof (qdb_function_t)); @@ -422,7 +460,7 @@ return_function (progs_t *pr, dfunction_t *func) f->name = func->s_name; f->file = func->s_file; f->num_params = func->numparms; - R_INT (pr) = PR_SetPointer (pr, f); + R_POINTER (pr) = PR_SetPointer (pr, f); } } @@ -458,7 +496,7 @@ qdb_get_function (progs_t *pr) static void return_auxfunction (progs_t *pr, pr_auxfunction_t *auxfunc) { - R_INT (pr) = 0; + R_POINTER (pr) = 0; if (auxfunc) { __auto_type f = (qdb_auxfunction_t *) PR_Zone_Malloc (pr, @@ -469,7 +507,7 @@ return_auxfunction (progs_t *pr, pr_auxfunction_t *auxfunc) f->local_defs = auxfunc->local_defs; f->num_locals = auxfunc->num_locals; f->return_type = auxfunc->return_type; - R_INT (pr) = PR_SetPointer (pr, f); + R_POINTER (pr) = PR_SetPointer (pr, f); } } @@ -514,7 +552,7 @@ qdb_get_local_defs (progs_t *pr) pr_uint_t fnum = P_UINT (pr, 1); pr_auxfunction_t *auxfunc = PR_Debug_MappedAuxFunction (tpr, fnum); - R_INT (pr) = 0; + R_POINTER (pr) = 0; if (auxfunc && auxfunc->num_locals) { pr_def_t *defs = PR_Debug_LocalDefs (tpr, auxfunc); __auto_type qdefs @@ -526,7 +564,7 @@ qdb_get_local_defs (progs_t *pr) qdefs[i].name = defs[i].name; qdefs[i].type_encoding = defs[i].type_encoding; } - R_INT (pr) = PR_SetPointer (pr, qdefs); + R_POINTER (pr) = PR_SetPointer (pr, qdefs); } } @@ -538,6 +576,8 @@ static builtin_t builtins[] = { {"qdb_clear_watchpoint", qdb_clear_watchpoint, -1}, {"qdb_continue", qdb_continue, -1}, {"qdb_get_state", qdb_get_state, -1}, + {"qdb_get_stack_depth", qdb_get_stack_depth, -1}, + {"qdb_get_stack", qdb_get_stack, -1}, {"qdb_get_event", qdb_get_event, -1}, {"qdb_get_data", qdb_get_data, -1}, {"qdb_get_string|{tag qdb_target_s=}i", qdb_get_string, -1}, diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 491a35277..db4f8da59 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -213,6 +213,11 @@ spawn_progs (qwaq_thread_t *thread) PR_Undefined (pr, "function", "main"); } + if (thread->pr->debug_handler) { + thread->pr->debug_handler (prd_begin, &thread->main_func, + thread->pr->debug_data); + } + if (!PR_RunPostLoadFuncs (pr)) { PR_Error (pr, "unable to load %s", pr->progs_name); } diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index b7ead7c92..6dc86ab1c 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -24,7 +24,7 @@ typedef struct qdb_event_s { prdebug_t what; union { string_t message; - unsigned func; + unsigned function; int exit_code; }; } qdb_event_t; @@ -36,6 +36,12 @@ typedef struct qdb_state_s { unsigned line; } qdb_state_t; +typedef struct qdb_stack_s { + unsigned staddr; // return address + unsigned func; // calling function + // FIXME temp strings +} qdb_stack_t; + typedef struct qdb_def_s { unsigned type_size; // type in lower 16, size in upper 16 unsigned offset; @@ -73,6 +79,8 @@ int qdb_set_watchpoint (qdb_target_t target, unsigned offset); int qdb_clear_watchpoint (qdb_target_t target); int qdb_continue (qdb_target_t target); qdb_state_t qdb_get_state (qdb_target_t target); +int qdb_get_stack_depth (qdb_target_t target); +qdb_stack_t *qdb_get_stack (qdb_target_t target); int qdb_get_event (qdb_target_t target, qdb_event_t *event); int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst); @overload string qdb_get_string (qdb_target_t target, unsigned str); diff --git a/ruamoko/qwaq/debugger/debug.r b/ruamoko/qwaq/debugger/debug.r index 7aa1b457c..792b20d61 100644 --- a/ruamoko/qwaq/debugger/debug.r +++ b/ruamoko/qwaq/debugger/debug.r @@ -10,6 +10,8 @@ int qdb_set_watchpoint (qdb_target_t target, unsigned offset) = #0; int qdb_clear_watchpoint (qdb_target_t target) = #0; int qdb_continue (qdb_target_t target) = #0; qdb_state_t qdb_get_state (qdb_target_t target) = #0; +int qdb_get_stack_depth (qdb_target_t target) = #0; +qdb_stack_t *qdb_get_stack (qdb_target_t target) = #0; int qdb_get_event (qdb_target_t target, qdb_event_t *event) = #0; int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst) = #0; diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 627558f1f..13adcf752 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -18,7 +18,16 @@ { qdb_target_t target; qdb_event_t event; - qdb_state_t last_state; + struct { + qdb_state_t state; + int depth; + int until_function; + } trace_cond; + struct { + int onEnter; + int onExit; + } sub_cond; + SEL traceHandler; Window *source_window; ScrollBar *source_scrollbar; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 0f78f2e7a..4fbba26a4 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -137,8 +137,18 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) } else if (event.what == qe_keydown) { switch (event.key.code) { case QFK_F7: + case 's': + self.traceHandler = @selector(traceStep); qdb_set_trace (self.target, 1); - self.last_state = qdb_get_state (self.target); + self.trace_cond.state = qdb_get_state (self.target); + qdb_continue (self.target); + return 1; + case QFK_F8: + case 'n': + self.traceHandler = @selector(traceNext); + qdb_set_trace (self.target, 1); + self.trace_cond.state = qdb_get_state (self.target); + self.trace_cond.depth = qdb_get_stack_depth (self.target); qdb_continue (self.target); return 1; } @@ -163,21 +173,50 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) return self; } --trace +// stop only if the progs have not advanced (may be a broken jump) +// or the progs have advanced to a different source line +static int +is_new_line (qdb_state_t last_state, qdb_state_t state) +{ + return !(last_state.staddr != state.staddr + && last_state.func == state.func + && last_state.file == state.file + && last_state.line == state.line); +} + +-traceStep { qdb_state_t state = qdb_get_state (target); - // stop only if the progs have not advanced (may be a broken jump) - // or the progs have advanced to a different source line - if (last_state.staddr != state.staddr - && last_state.func == state.func - && last_state.file == state.file - && last_state.line == state.line) { - last_state = state; - qdb_continue (self.target); + if (trace_cond.until_function && trace_cond.until_function == state.func) { + trace_cond.until_function = 0; + [self stop:prd_trace]; return self; } - [self stop:prd_trace]; + if (is_new_line(trace_cond.state, state)) { + [self stop:prd_trace]; + return self; + } + trace_cond.state = state; + qdb_continue (self.target); + return self; +} + +-traceNext +{ + qdb_state_t state = qdb_get_state (target); + if (trace_cond.until_function && trace_cond.until_function == state.func) { + trace_cond.until_function = 0; + [self stop:prd_trace]; + return self; + } + if (is_new_line(trace_cond.state, state) + && qdb_get_stack_depth (target) <= trace_cond.depth) { + [self stop:prd_trace]; + return self; + } + trace_cond.state = state; + qdb_continue (self.target); return self; } @@ -188,16 +227,30 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) case prd_none: break; // shouldn't happen case prd_trace: - [self trace]; + [self performSelector:traceHandler]; break; case prd_breakpoint: case prd_watchpoint: [self stop:event.what]; break; case prd_subenter: - [self stop:event.what]; + printf("subenter\n"); + if (sub_cond.onEnter) { + [self stop:event.what]; + } else { + qdb_continue (self.target); + } break; case prd_subexit: + printf("subexit\n"); + if (sub_cond.onExit) { + [self stop:event.what]; + } else { + qdb_continue (self.target); + } + break; + case prd_begin: + trace_cond.until_function = event.function; [self stop:event.what]; break; case prd_terminate: From 17871b979d504f89e6c4be8a6d9525768267348c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 19:29:54 +0900 Subject: [PATCH 1017/3664] [ruamoko] Implement obj_calloc correctly Forgetting to multiply by the second term leads to not good things. --- libs/ruamoko/rua_obj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 91b9e5692..7ecc8ef28 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1489,7 +1489,7 @@ rua_obj_realloc (progs_t *pr) static void rua_obj_calloc (progs_t *pr) { - int size = P_INT (pr, 0) * sizeof (pr_type_t); + int size = P_INT (pr, 0) * P_INT (pr, 1) * sizeof (pr_type_t); void *mem = PR_Zone_Malloc (pr, size); memset (mem, 0, size); From 9b1ce44fda207abd64b712295fdca65553dad745 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Apr 2020 19:31:11 +0900 Subject: [PATCH 1018/3664] [qwaq] Fix some issues with fetching type encodings Now struct defs show FIXME instead of void data. --- ruamoko/qwaq/debugger/debugger.r | 2 -- ruamoko/qwaq/debugger/localsdata.r | 4 +++- ruamoko/qwaq/debugger/typeencodings.r | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 4fbba26a4..425a4f4d7 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -234,7 +234,6 @@ is_new_line (qdb_state_t last_state, qdb_state_t state) [self stop:event.what]; break; case prd_subenter: - printf("subenter\n"); if (sub_cond.onEnter) { [self stop:event.what]; } else { @@ -242,7 +241,6 @@ is_new_line (qdb_state_t last_state, qdb_state_t state) } break; case prd_subexit: - printf("subexit\n"); if (sub_cond.onExit) { [self stop:event.what]; } else { diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index d380f9fe5..d65869491 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -66,7 +66,9 @@ -fetchData { - qdb_get_data (target, func.local_data, func.local_size, data); + if (data && func.local_size && func.local_data) { + qdb_get_data (target, func.local_data, func.local_size, data); + } return self; } diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index 0e2f4fc44..ad04dbbcd 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -83,7 +83,7 @@ static void type_free (void *t, void *unused) if (qdb_get_data (target, typeAddr, TYPESIZE, &buffer) < 0) { return nil; } - if (!buffer.encoding) { + if (!buffer.size) { return nil; } encoding = qdb_get_string (target, buffer.encoding); @@ -97,7 +97,7 @@ static void type_free (void *t, void *unused) return type; } type = obj_calloc (1, buffer.size); - if (!qdb_get_data (target, typeAddr, TYPESIZE, &buffer)) { + if (qdb_get_data (target, typeAddr, buffer.size, type) < 0) { goto error; } if (!(type.encoding = qdb_get_string (target, type.encoding))) { From 5d065968147b75d47dfcb5f263f184d8d3aa1752 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 00:20:39 +0900 Subject: [PATCH 1019/3664] [qfcc] Fix test harness after .ctor change --- tools/qfcc/test/test-harness.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 934c02cb0..ba9759c19 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -177,6 +177,8 @@ load_progs (const char *name) Qclose (file); if (!PR_RunLoadFuncs (&pr)) PR_Error (&pr, "unable to load %s", pr.progs_name); + if (!PR_RunPostLoadFuncs (&pr)) + PR_Error (&pr, "unable to load %s", pr.progs_name); pr.pr_trace_depth = -1; pr.pr_trace = options.trace; return 1; From d69db50cf971cc79b2c64707cfc423cbe106d362 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 00:45:54 +0900 Subject: [PATCH 1020/3664] [qfcc] Remove path stripping It never really helped sort out the path issues when using build directories. It worked well enough for single directory projects, but things got messy very quickly, especially when mixing ruamoko libs with external progs. A better method based on dwarf is coming. --- ruamoko/cl_menu/Makefile.am | 5 ++--- ruamoko/game/Makefile.am | 5 ++--- ruamoko/gui/Makefile.am | 2 +- ruamoko/lib/Makefile.am | 2 +- ruamoko/scheme/Makefile.am | 5 ++--- tools/qfcc/doc/man/qfcc.1 | 9 --------- tools/qfcc/include/options.h | 2 -- tools/qfcc/include/qfcc.h | 1 - tools/qfcc/source/debug.c | 2 +- tools/qfcc/source/options.c | 8 -------- tools/qfcc/source/qfcc.c | 20 ++------------------ tools/qfcc/source/stub.c | 1 - 12 files changed, 11 insertions(+), 51 deletions(-) diff --git a/ruamoko/cl_menu/Makefile.am b/ruamoko/cl_menu/Makefile.am index 2d2b0c4d0..8c759d410 100644 --- a/ruamoko/cl_menu/Makefile.am +++ b/ruamoko/cl_menu/Makefile.am @@ -27,11 +27,10 @@ am__mv = mv -f GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi # BSD make can't handle $(shell foo) directives, and GNU make can't handle |= # so we have to bite the bullet and pass this to the shell every time. -STRIP=`echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c` SUFFIXES=.o .r .r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo @@ -50,7 +49,7 @@ menu_dat_SOURCES=$(menu_src) menu_obj=$(menu_src:.r=.o) menu_dep=$(addprefix ./$(DEPDIR)/,$(menu_obj:.o=.Qo)) menu.dat: $(menu_obj) $(QFCC_DEP) ../lib/libcsqc.a ../lib/libr.a ../gui/libgui.a - $(QLINK) -p $(STRIP) -o menu.dat $(menu_obj) ../gui/libgui.a ../lib/libcsqc.a ../lib/libr.a + $(QLINK) -o menu.dat $(menu_obj) ../gui/libgui.a ../lib/libcsqc.a ../lib/libr.a include $(menu_dep) # am--include-marker r_depfiles_remade += $(menu_dep) diff --git a/ruamoko/game/Makefile.am b/ruamoko/game/Makefile.am index e7cee8113..fe9a38f5f 100644 --- a/ruamoko/game/Makefile.am +++ b/ruamoko/game/Makefile.am @@ -25,11 +25,10 @@ am__mv = mv -f GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi # BSD make can't handle $(shell foo) directives, and GNU make can't handle |= # so we have to bite the bullet and pass this to the shell every time. -STRIP=`echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c` SUFFIXES=.o .r .r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo @@ -41,7 +40,7 @@ game_dat_SOURCES=$(game_src) game_obj=$(game_src:.r=.o) game_dep=$(addprefix ./$(DEPDIR)/,$(game_obj:.o=.Qo)) game.dat: $(game_obj) $(QFCC_DEP) ../lib/libr.a ../lib/libqw.a - $(QLINK) -p $(STRIP) -o game.dat $(game_obj) ../lib/libr.a ../lib/libqw.a ../lib/libr.a + $(QLINK) -o game.dat $(game_obj) ../lib/libr.a ../lib/libqw.a ../lib/libr.a include $(game_dep) # am--include-marker r_depfiles_remade += $(game_dep) diff --git a/ruamoko/gui/Makefile.am b/ruamoko/gui/Makefile.am index 7edb5f173..0edd447d4 100644 --- a/ruamoko/gui/Makefile.am +++ b/ruamoko/gui/Makefile.am @@ -26,7 +26,7 @@ RANLIB=touch SUFFIXES= .o .r .r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am index cf0e50154..b05db7299 100644 --- a/ruamoko/lib/Makefile.am +++ b/ruamoko/lib/Makefile.am @@ -28,7 +28,7 @@ RANLIB=touch SUFFIXES= .o .r .r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo diff --git a/ruamoko/scheme/Makefile.am b/ruamoko/scheme/Makefile.am index 3d4319863..9a5fb71a8 100644 --- a/ruamoko/scheme/Makefile.am +++ b/ruamoko/scheme/Makefile.am @@ -30,12 +30,11 @@ PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi # BSD make can't handle $(shell foo) directives, and GNU make can't handle |= # so we have to bite the bullet and pass this to the shell every time. -STRIP=`echo -n $(srcdir)/ | sed -e 's/[^/]//g' | wc -c` RANLIB=touch SUFFIXES=.o .r .r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -p $(STRIP) -c -o $@ $< + $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo @@ -59,7 +58,7 @@ main_dat_SOURCES=$(scheme_src) main_obj=$(scheme_src:.r=.o) main_dep=$(addprefix ./$(DEPDIR)/,$(main_obj:.o=.Qo)) main.dat: $(main_obj) $(QFCC_DEP) libscheme.a ../lib/libcsqc.a ../lib/libr.a - $(QLINK) -p $(STRIP) -o main.dat $(main_obj) libscheme.a ../lib/libcsqc.a ../lib/libr.a + $(QLINK) -o main.dat $(main_obj) libscheme.a ../lib/libcsqc.a ../lib/libr.a include $(main_dep) # am--include-marker r_depfiles_remade += $(main_dep) diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index 3162f813d..4105eaa1d 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -168,15 +168,6 @@ No effect in separate compilation mode. Use QCCX escape sequences instead of standard C/QuakeForge sequences in strings. See \fBESCAPE SEQUENCES\fP for details. -.TP -.B \-p, \-\-strip\-path NUM -Strip NUM leading path elements from file names. -eg. -p 3 will strip the -.I ../../../ -from -.I ../../../src/foo.r -when embedding the source file name in the output code. - .TP .B \-q, \-\-quiet Inhibit some of \*[qfcc]'s normal output. diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index a43c908b6..580f97370 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -114,8 +114,6 @@ typedef struct { qboolean partial_link; // partial linking qboolean preprocess_only;// run only cpp, don't compile qboolean gzip; // compress qfo files when writing - int strip_path; // number of leading path elements to strip - // from source file names const char *output_file; const char *debug_file; } options_t; diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index dc8dddac2..eedafdadd 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -108,7 +108,6 @@ extern pr_info_t pr; #define POINTER_OFS(s,p) ((pr_type_t *) (p) - (s)->data) -const char *strip_path (const char *filename) __attribute__((pure)); const char *file_basename (const char *filename, int keepdot) __attribute__((pure)); extern FILE *qc_yyin; diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index 5d6f1f5f5..f56e177fb 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -111,7 +111,7 @@ line_info (char *text) while (*p && *p != '\n') // ignore rest p++; pr.source_line = line - 1; - pr.source_file = ReuseString (strip_path (str)); + pr.source_file = ReuseString (str); } pr_lineno_t * diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 6f972fd82..e3f9e504e 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -94,7 +94,6 @@ static struct option const long_options[] = { {"relocatable", no_argument, 0, 'r'}, {"save-temps", no_argument, 0, 'S'}, {"source", required_argument, 0, 's'}, - {"strip-path", required_argument, 0, 'p'}, {"traditional", no_argument, 0, OPT_TRADITIONAL}, {"undefine", required_argument, 0, 'U'}, {"verbose", no_argument, 0, 'v'}, @@ -120,7 +119,6 @@ static const char *short_options = "o:" // output file "O" // optimize "P:" // progs.src name - "p:" // strip path "q" // quiet "r" // partial linking "S" // save temps @@ -166,8 +164,6 @@ usage (int status) " -o, --output-file FILE Specify output file name\n" " --progdefs Genderate progdefs.h\n" " -P, --progs-src FILE File to use instead of progs.src\n" -" -p, --strip-path NUM Strip NUM leading path elements from file\n" -" names\n" " --qccx-escapes Use QCCX escape sequences instead of standard\n" " C/QuakeForge sequences.\n" " -q, --quiet Inhibit usual output\n" @@ -325,7 +321,6 @@ DecodeArgs (int argc, char **argv) options.single_cpp = true; options.save_temps = false; options.verbosity = 0; - options.strip_path = 0; sourcedir = ""; progs_src = "progs.src"; @@ -364,9 +359,6 @@ DecodeArgs (int argc, char **argv) case 'P': // progs-src progs_src = save_string (NORMALIZE (optarg)); break; - case 'p': - options.strip_path = atoi (optarg); - break; case 'F': options.files_dat = true; break; diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 1167611ad..007c7f795 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -296,22 +296,6 @@ begin_compilation (void) pr.error_count = 0; } -const char * -strip_path (const char *filename) -{ - const char *p = filename; - int i = options.strip_path; - - while (i-- > 0) { - while (*p && *p != '/') - p++; - if (!*p) - break; - filename = ++p; - } - return filename; -} - const char * file_basename (const char *filename, int keepdot) { @@ -385,7 +369,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) InitData (); chain_initial_types (); begin_compilation (); - pr.source_file = ReuseString (strip_path (file)); + pr.source_file = ReuseString (file); err = yyparse () || pr.error_count; fclose (*yyin); if (cpp_name && !options.save_temps) { @@ -641,7 +625,7 @@ compile_file (const char *filename) if (!*yyin) return !options.preprocess_only; - pr.source_file = ReuseString (strip_path (filename)); + pr.source_file = ReuseString (filename); pr.source_line = 1; clear_frame_macros (); err = yyparse () || pr.error_count; diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index 449e62436..411a8d3a6 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -54,5 +54,4 @@ void dump_dot (const char *stage, void *data, void (*dump_func) (void *data, const char *fname)){} void dump_dot_type (void *_t, const char *filename){} char *fubar; -const char *strip_path(const char *p) { return fubar;} const char *file_basename(const char *p, int keepdot) { return fubar;} From f8d9b720dee213b373855027ef6ac4ce9c833a14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 14:14:34 +0900 Subject: [PATCH 1021/3664] [qfcc] Free data spaces between compiliations --- tools/qfcc/include/defspace.h | 2 ++ tools/qfcc/source/defspace.c | 22 ++++++++++++++++++++++ tools/qfcc/source/qfcc.c | 7 ++++++- tools/qfcc/test/test-defspace.c | 6 ++++++ 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index ef6036286..e0414f1c9 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -90,6 +90,8 @@ typedef struct defspace_s { */ defspace_t *defspace_new (ds_type_t type); +void defspace_delete (defspace_t *defspace); + /** Allocate space from the defspace's backing memory. If the memory is fragmented, then the first available location at least diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index f2c9f7011..4c3b80ab9 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -139,6 +139,28 @@ defspace_new (ds_type_t type) return space; } +void +defspace_delete (defspace_t *space) +{ + locref_t **lr; + + for (lr = &space->free_locs; *lr; lr = &(*lr)->next) { + } + *lr = locrefs_freelist; + locrefs_freelist = space->free_locs; + + if (space->data) { + free (space->data); + } + + while (space->defs) { + def_t *def = space->defs; + space->defs = def->next; + def->space = 0; + free_def (def); + } +} + int defspace_alloc_loc (defspace_t *space, int size) { diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 007c7f795..c606fb414 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -137,10 +137,15 @@ InitData (void) if (pr.code) { codespace_delete (pr.code); strpool_delete (pr.strings); + defspace_delete (pr.near_data); + defspace_delete (pr.far_data); + defspace_delete (pr.entity_data); + defspace_delete (pr.type_data); } - if (pr.linenos) + if (pr.linenos) { free (pr.linenos); + } memset (&pr, 0, sizeof (pr)); pr.source_line = 1; diff --git a/tools/qfcc/test/test-defspace.c b/tools/qfcc/test/test-defspace.c index 5d14c5013..f0f40a692 100644 --- a/tools/qfcc/test/test-defspace.c +++ b/tools/qfcc/test/test-defspace.c @@ -18,6 +18,12 @@ pr_info_t pr; function_t *current_func; class_type_t *current_class; +void +free_def (def_t *def) +{ + if (0) free (def); +} + __attribute__((const))const char * get_class_name (class_type_t *class_type, int prett) { From 4b34bf3d95d9733c537409dd98ff514c5452811d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 14:16:16 +0900 Subject: [PATCH 1022/3664] [qfcc] Take optional space param for emit_structure If the space param is null, the far data space is used. --- tools/qfcc/include/struct.h | 1 + tools/qfcc/source/class.c | 8 ++++---- tools/qfcc/source/method.c | 4 ++-- tools/qfcc/source/struct.c | 7 +++++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/include/struct.h b/tools/qfcc/include/struct.h index 8f50845cf..4438ec600 100644 --- a/tools/qfcc/include/struct.h +++ b/tools/qfcc/include/struct.h @@ -59,6 +59,7 @@ struct symbol_s *make_structure (const char *name, int su, struct_def_t *defs, struct type_s *type); struct def_s * emit_structure (const char *name, int su, struct_def_t *defs, struct type_s *type, void *data, + struct defspace_s *space, enum storage_class_e storage); #endif//__struct_h diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index f7d52e29c..38ffd54a8 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -260,7 +260,7 @@ emit_static_instances (const char *classname) data.num_instances + 1); instances_def = emit_structure (va ("_OBJ_STATIC_INSTANCES_%s", classname), 's', instances_struct, 0, &data, - sc_static); + 0, sc_static); free (data.instances); return instances_def; } @@ -787,7 +787,7 @@ emit_ivars (symtab_t *ivars, const char *name) ivar_list_struct[1].type = array_type (&type_ivar, ivar_data.count); def = emit_structure (va ("_OBJ_INSTANCE_VARIABLES_%s", name), 's', - ivar_list_struct, 0, &ivar_data, sc_static); + ivar_list_struct, 0, &ivar_data, 0, sc_static); dstring_delete (ivar_data.encoding); return def; @@ -1528,7 +1528,7 @@ class_finish_module (void) + data.cat_def_cnt + 1); symtab_def = emit_structure ("_OBJ_SYMTAB", 's', symtab_struct, 0, &data, - sc_static); + 0, sc_static); free (data.classes); free (data.categories); @@ -1787,7 +1787,7 @@ emit_protocol_list (protocollist_t *protocols, const char *name) return 0; proto_list_struct[2].type = array_type (&type_pointer, protocols->count); return emit_structure (va ("_OBJ_PROTOCOLS_%s", name), 's', - proto_list_struct, 0, protocols, sc_static); + proto_list_struct, 0, protocols, 0, sc_static); } void diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 833a03f1f..ae3d031e1 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -606,7 +606,7 @@ emit_methods (methodlist_t *methods, const char *name, int instance) methods_struct[2].type = array_type (&type_method, count); return emit_structure (va ("_OBJ_%s_METHODS_%s", type, name), 's', - methods_struct, 0, methods, sc_static); + methods_struct, 0, methods, 0, sc_static); } static void @@ -674,7 +674,7 @@ emit_method_descriptions (methodlist_t *methods, const char *name, method_list_struct[1].type = array_type (&type_method_description, count); return emit_structure (va ("_OBJ_%s_METHODS_%s", type, name), 's', - method_list_struct, 0, methods, sc_static); + method_list_struct, 0, methods, 0, sc_static); } void diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 59ac6fe7a..64553a8df 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -306,7 +306,7 @@ make_structure (const char *name, int su, struct_def_t *defs, type_t *type) def_t * emit_structure (const char *name, int su, struct_def_t *defs, type_t *type, - void *data, storage_class_t storage) + void *data, defspace_t *space, storage_class_t storage) { int i, j; int saw_null = 0; @@ -341,7 +341,10 @@ emit_structure (const char *name, int su, struct_def_t *defs, type_t *type, if (storage != sc_global && storage != sc_static) internal_error (0, "structure %s must be global or static", name); - struct_sym = make_symbol (name, type, pr.far_data, storage); + if (!space) { + space = pr.far_data; + } + struct_sym = make_symbol (name, type, space, storage); struct_def = struct_sym->s.def; if (struct_def->initialized) From 9089744290a277fbec5e8220932d4d9e9de42740 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 14:20:40 +0900 Subject: [PATCH 1023/3664] [qfcc] Add a function to safely get cwd getcwd is assumed to use malloc if its buff param is null. This may need fixing in the future, but it's in one spot. The result in "saved" in the non-progs pool. --- tools/qfcc/include/strpool.h | 2 ++ tools/qfcc/source/strpool.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/tools/qfcc/include/strpool.h b/tools/qfcc/include/strpool.h index e6e065cb8..6cdc8eb83 100644 --- a/tools/qfcc/include/strpool.h +++ b/tools/qfcc/include/strpool.h @@ -53,6 +53,8 @@ int strpool_addstr (strpool_t *strpool, const char *str); */ const char *save_string (const char *str); +const char *save_cwd (void); + const char *make_string (char *token, char **end); const char *html_string (const char *str); diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index 8fb7642e6..0f10f81ee 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -39,6 +39,7 @@ #endif #include #include +#include #include "QF/dstring.h" #include "QF/hash.h" @@ -140,6 +141,15 @@ save_string (const char *str) return s; } +const char * +save_cwd (void) +{ + char *cwd = getcwd (0, 0); + const char *str = save_string (cwd); + free (cwd); + return str; +} + const char * make_string (char *token, char **end) { From 65e7df44d3d98cade6ab1ab4d0c3fa1ecb07c9d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 14:22:44 +0900 Subject: [PATCH 1024/3664] [qfcc] Add function to see if a string is in a pool Makes for a nice string set. --- tools/qfcc/include/strpool.h | 1 + tools/qfcc/source/strpool.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/tools/qfcc/include/strpool.h b/tools/qfcc/include/strpool.h index 6cdc8eb83..fbb4bc049 100644 --- a/tools/qfcc/include/strpool.h +++ b/tools/qfcc/include/strpool.h @@ -42,6 +42,7 @@ strpool_t *strpool_new (void); strpool_t *strpool_build (const char *strings, int size); void strpool_delete (strpool_t *strpool); int strpool_addstr (strpool_t *strpool, const char *str); +int strpool_findstr (strpool_t *strpool, const char *str); /** Smart strdup. diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index 0f10f81ee..d3ab07a1c 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -121,6 +121,14 @@ strpool_addstr (strpool_t *strpool, const char *str) return s; } +int +strpool_findstr (strpool_t *strpool, const char *str) +{ + if (!str) + return 0; + return (intptr_t) Hash_Find (strpool->str_tab, str); +} + static const char * ss_get_key (const void *s, void *unused) { From 049b8f392c78b4b4c192137a1bf97e5b12c407fc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 14:27:22 +0900 Subject: [PATCH 1025/3664] [qfcc] create a compilation unit for debug data The compilation unit stores the directory from which qfcc was run and any source files mentioned. This is similar to dwarf's compilation unit. Right now, this is the only data in the new debug space, but more might come in the future so it seems best to treat the debug space separately in the object files. --- include/QF/pr_debug.h | 7 +++ tools/qfcc/include/debug.h | 2 + tools/qfcc/include/obj_file.h | 2 + tools/qfcc/include/qfcc.h | 6 +++ tools/qfcc/source/debug.c | 83 ++++++++++++++++++++++++++++++++++- tools/qfcc/source/linker.c | 23 +++++++++- tools/qfcc/source/obj_file.c | 25 +++++++++++ tools/qfcc/source/qfcc.c | 17 ++++++- 8 files changed, 161 insertions(+), 4 deletions(-) diff --git a/include/QF/pr_debug.h b/include/QF/pr_debug.h index 4b87ee897..ab10b62a2 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/pr_debug.h @@ -34,6 +34,13 @@ #ifndef __QFCC__ #include "QF/pr_comp.h" +typedef struct pr_compunit_s { + pr_uint_t unit_name; + pr_uint_t basedir; + pr_uint_t num_files; + pr_uint_t files[1]; +} pr_compunit_t; + typedef struct pr_auxfunction_s { pr_uint_t function; // function def this aux info is for pr_uint_t source_line; // first source line for this function diff --git a/tools/qfcc/include/debug.h b/tools/qfcc/include/debug.h index a5d5b5a1f..af5f322b7 100644 --- a/tools/qfcc/include/debug.h +++ b/tools/qfcc/include/debug.h @@ -35,6 +35,8 @@ void line_info (char *text); pr_lineno_t *new_lineno (void); +void add_source_file (const char *file); +void debug_finish_module (const char *modname); extern int lineno_base; diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 62d7b80f0..55a93542b 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -77,6 +77,7 @@ typedef enum qfos_type_e { qfos_string, ///< strings. char data qfos_entity, ///< entity field defs. no data qfos_type, ///< type encodings + qfos_debug, ///< debug data } qfos_type_t; /** Representation of a space in the object file. @@ -283,6 +284,7 @@ enum { qfo_far_data_space, qfo_entity_space, qfo_type_space, + qfo_debug_space, qfo_num_spaces }; diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index eedafdadd..6fac011ce 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -34,6 +34,7 @@ */ #include +#include "QF/darray.h" #include "QF/pr_comp.h" /** \defgroup qfcc_general General functions @@ -68,6 +69,11 @@ typedef struct pr_info_s { struct defspace_s *entity_data; ///< entity field address space. no ///< data is stored in the progs file struct defspace_s *type_data; ///< encoded type information. + struct defspace_s *debug_data; ///< additional debug data. + struct strpool_s *comp_file_set; + struct DARRAY_TYPE (const char *) comp_files; + const char *comp_dir; + const char *unit_name; struct symtab_s *symtab; struct symtab_s *entity_fields; diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index f56e177fb..d433304e2 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -44,10 +44,16 @@ #include "QF/pr_comp.h" #include "debug.h" +#include "def.h" +#include "defspace.h" #include "diagnostic.h" +#include "emit.h" #include "expr.h" #include "qfcc.h" +#include "reloc.h" #include "strpool.h" +#include "struct.h" +#include "type.h" #include "value.h" int lineno_base; @@ -79,6 +85,17 @@ pop_source_file (void) FREE (srclines, tmp); } +#define Sys_Error(fmt...) internal_error(0, fmt) +void +add_source_file (const char *file) +{ + pr.source_file = ReuseString (file); + if (!strpool_findstr (pr.comp_file_set, file)) { + strpool_addstr (pr.comp_file_set, file); + DARRAY_APPEND (&pr.comp_files, save_string (file)); + } +} + void line_info (char *text) { @@ -111,7 +128,7 @@ line_info (char *text) while (*p && *p != '\n') // ignore rest p++; pr.source_line = line - 1; - pr.source_file = ReuseString (str); + add_source_file (str); } pr_lineno_t * @@ -125,3 +142,67 @@ new_lineno (void) memset (&pr.linenos[pr.num_linenos], 0, sizeof (pr_lineno_t)); return &pr.linenos[pr.num_linenos++]; } + +static void +emit_unit_name (def_t *def, void *data, int index) +{ + if (!is_string (def->type)) { + internal_error (0, "%s: expected string def", __FUNCTION__); + } + EMIT_STRING (def->space, D_STRING (def), pr.unit_name); +} + +static void +emit_basedir (def_t *def, void *data, int index) +{ + if (!is_string (def->type)) { + internal_error (0, "%s: expected string def", __FUNCTION__); + } + EMIT_STRING (def->space, D_STRING (def), pr.comp_dir); +} + +static void +emit_num_files (def_t *def, void *data, int index) +{ + if (!is_integer (def->type)) { + internal_error (0, "%s: expected int def", __FUNCTION__); + } + D_INT (def) = pr.comp_files.size; +} + +static void +emit_files_item (def_t *def, void *data, int index) +{ + if (!is_array (def->type) || !is_string (def->type->t.array.type)) { + internal_error (0, "%s: expected array of string def", __FUNCTION__); + } + if ((unsigned) index >= pr.comp_files.size) { + internal_error (0, "%s: out of bounds index: %d %zd", + __FUNCTION__, index, pr.comp_files.size); + } + EMIT_STRING (def->space, D_STRING (def), pr.comp_files.a[index]); +} + +static def_t * +emit_compunit (const char *modname) +{ + static struct_def_t compunit_struct[] = { + {"unit_name", &type_string, emit_unit_name}, + {"basedir", &type_string, emit_basedir}, + {"num_files", &type_integer, emit_num_files}, + {"files", 0, emit_files_item}, + {0, 0} + }; + int count = pr.comp_files.size; + + pr.unit_name = modname; + compunit_struct[3].type = array_type (&type_string, count); + return emit_structure ("compile_unit", 's', compunit_struct, 0, &pr, + pr.debug_data, sc_static); +} + +void +debug_finish_module (const char *modname) +{ + emit_compunit (modname); +} diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 51f03f948..06fd67cb1 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -154,6 +154,7 @@ static defspace_t *work_near_data; static defspace_t *work_far_data; static defspace_t *work_entity_data; static defspace_t *work_type_data; +static defspace_t *work_debug_data; static qfo_reloc_t *work_loose_relocs; static int work_num_loose_relocs; @@ -163,6 +164,7 @@ static defspace_t **work_spaces[qfo_num_spaces] = { &work_far_data, &work_entity_data, &work_type_data, + &work_debug_data, }; static dstring_t *linker_current_file; @@ -684,6 +686,7 @@ linker_begin (void) work_far_data = defspace_new (ds_backed); work_entity_data = defspace_new (ds_virtual); work_type_data = defspace_new (ds_backed); + work_debug_data = defspace_new (ds_backed); pr.strings = work_strings; @@ -709,6 +712,9 @@ linker_begin (void) work->spaces[qfo_type_space].type = qfos_type; work->spaces[qfo_type_space].d.data = work_type_data->data; work->spaces[qfo_type_space].data_size = work_type_data->size; + work->spaces[qfo_debug_space].type = qfos_debug; + work->spaces[qfo_debug_space].d.data = work_type_data->data; + work->spaces[qfo_debug_space].data_size = work_type_data->size; for (i = 0; i < qfo_num_spaces; i++) work->spaces[i].id = i; @@ -906,6 +912,20 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass) return 0; } +static int +process_debug_space (qfo_t *qfo, qfo_mspace_t *space, int pass) +{ + if (pass != 1) + return 0; + if (space->type != qfos_debug) { + linker_internal_error ("bad space type for add_data_space (): %d", + space->type); + } + add_defs (qfo, space, work->spaces + qfo_debug_space, process_data_def); + add_data (qfo_debug_space, space); + return 0; +} + static void process_funcs (qfo_t *qfo) { @@ -1002,6 +1022,7 @@ linker_add_qfo (qfo_t *qfo) process_strings_space, process_entity_space, process_type_space, + process_debug_space, }; unsigned i; int pass; @@ -1014,7 +1035,7 @@ linker_add_qfo (qfo_t *qfo) work_func_base = work->num_funcs; for (pass = 0; pass < 2; pass++) { for (i = 0, space = qfo->spaces; i < qfo->num_spaces; i++, space++) { - if ((int) space->type < 0 || space->type > qfos_type) { + if ((int) space->type < 0 || space->type > qfos_debug) { linker_error ("bad space type"); return 1; } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index b6e3e6f82..a7e419c62 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -183,6 +183,7 @@ qfo_count_stuff (qfo_t *qfo, pr_info_t *pr) qfo_count_space_stuff (qfo, pr->far_data); qfo_count_space_stuff (qfo, pr->entity_data); qfo_count_space_stuff (qfo, pr->type_data); + qfo_count_space_stuff (qfo, pr->debug_data); qfo_count_function_stuff (qfo, pr->func_head); qfo->num_relocs += count_relocs (pr->relocs); } @@ -269,6 +270,24 @@ qfo_init_type_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->id = qfo_type_space; } +static void +qfo_init_debug_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, + qfo_mspace_t *space, defspace_t *data) +{ + size_t size = data->size * sizeof (*data->data); + data->qfo_space = space - qfo->spaces; + space->type = qfos_debug; + space->defs = *defs; + space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); + space->d.data = 0; + if (data->data) { + space->d.data = malloc (size); + memcpy (space->d.data, data->data, size); + } + space->data_size = data->size; + space->id = qfo_debug_space; +} + static void qfo_encode_functions (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, qfo_mspace_t *space, function_t *functions) @@ -333,6 +352,8 @@ qfo_from_progs (pr_info_t *pr) pr->entity_data); qfo_init_type_space (qfo, &def, &reloc, &qfo->spaces[qfo_type_space], pr->type_data); + qfo_init_debug_space (qfo, &def, &reloc, &qfo->spaces[qfo_debug_space], + pr->debug_data); qfo_encode_functions (qfo, &def, &reloc, qfo->spaces + qfo_num_spaces, pr->func_head); @@ -382,6 +403,8 @@ qfo_space_size (qfo_mspace_t *space) return 0; case qfos_type: return space->data_size * sizeof (*space->d.data); + case qfos_debug: + return space->data_size * sizeof (*space->d.data); } return 0; } @@ -407,6 +430,7 @@ qfo_byteswap_space (void *space, int size, qfos_type_t type) case qfos_data: case qfos_entity: case qfos_type: + case qfos_debug: for (val = (pr_type_t *) space, c = 0; c < size; c++, val++) val->integer_var = LittleLong (val->integer_var); break; @@ -949,6 +973,7 @@ qfo_to_progs (qfo_t *qfo, int *size) progs->numglobals += progs->numglobaldefs * type_size (&type_xdef); progs->numglobals += progs->numfielddefs * type_size (&type_xdef); progs->entityfields = qfo->spaces[qfo_entity_space].data_size; + // qfo_debug_space does not go in the progs file *size += progs->numstatements * sizeof (dstatement_t); *size += progs->numglobaldefs * sizeof (ddef_t); *size += progs->numfielddefs * sizeof (ddef_t); diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index c606fb414..603c86377 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -141,6 +141,12 @@ InitData (void) defspace_delete (pr.far_data); defspace_delete (pr.entity_data); defspace_delete (pr.type_data); + defspace_delete (pr.debug_data); + strpool_delete (pr.comp_file_set); + } + + if (pr.comp_files.a) { + DARRAY_CLEAR (&pr.comp_files); } if (pr.linenos) { @@ -173,6 +179,10 @@ InitData (void) pr.type_data = defspace_new (ds_backed); defspace_alloc_loc (pr.type_data, 4);// reserve space for a null descriptor + pr.debug_data = defspace_new (ds_backed); + pr.comp_file_set = strpool_new (); + DARRAY_INIT (&pr.comp_files, 16); + pr.symtab = new_symtab (0, stab_global); pr.symtab->space = pr.near_data; current_symtab = pr.symtab; @@ -374,7 +384,8 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) InitData (); chain_initial_types (); begin_compilation (); - pr.source_file = ReuseString (file); + pr.comp_dir = save_cwd (); + add_source_file (file); err = yyparse () || pr.error_count; fclose (*yyin); if (cpp_name && !options.save_temps) { @@ -392,6 +403,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) class_finish_module (); err = pr.error_count; if (!err) { + debug_finish_module (obj); qfo = qfo_from_progs (&pr); err = qfo_write (qfo, obj); qfo_delete (qfo); @@ -630,7 +642,7 @@ compile_file (const char *filename) if (!*yyin) return !options.preprocess_only; - pr.source_file = ReuseString (filename); + add_source_file (filename); pr.source_line = 1; clear_frame_macros (); err = yyparse () || pr.error_count; @@ -774,6 +786,7 @@ progs_src_compile (void) } class_finish_module (); + debug_finish_module (options.output_file); qfo = qfo_from_progs (&pr); if (options.compile) { qfo_write (qfo, options.output_file); From 718f243f696e6af91c838dfc06635872f975e993 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 15:58:22 +0900 Subject: [PATCH 1026/3664] [qfcc] Relocate loose string relocs when linking This helps make partially linked object files make more sense when looking at strings in data spaces. --- tools/qfcc/source/linker.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 06fd67cb1..dd0e48722 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -1009,6 +1009,9 @@ process_loose_relocs (qfo_t *qfo) if (reloc->type == rel_def_op) reloc->target += work_base[qfo_code_space]; adjust_reloc_offset (reloc); + if (reloc->type == rel_def_string) { + QFO_STRING (work, reloc->space, reloc->offset) = reloc->target; + } } } From 453c646d859009f6fba3144269a5454f29a1ad11 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 19:54:25 +0900 Subject: [PATCH 1027/3664] [qfcc] Improve dependency checks for tests They worked well if there was only one source file in the test, but failed if there were two or more. While only typelinker needed the enhanced macros, I got them all because I generally copy the nearest block when adding a new test thus it's best if they're all "correct". --- tools/qfcc/test/Makefile.am | 220 +++++++++++++++++++++--------------- 1 file changed, 132 insertions(+), 88 deletions(-) diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 2b454b7a5..9c5e0799c 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -122,102 +122,113 @@ r_depfiles_remade= address_cast_dat_SOURCES=address-cast.r address_cast_obj=$(address_cast_dat_SOURCES:.r=.qfo) +address_cast_dep=$(addprefix ./$(DEPDIR)/,$(address_cast_obj:.qfo=.Qo)) address-cast.dat$(EXEEXT): $(address_cast_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(address_cast_obj) address-cast.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/address-cast.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/address-cast.Qo +include $(address_cast_dep) # am--include-marker +r_depfiles_remade += $(address_cast_dep) alignment_dat_SOURCES=alignment.r alignment_obj=$(alignment_dat_SOURCES:.r=.qfo) +alignment_dep=$(addprefix ./$(DEPDIR)/,$(alignment_obj:.qfo=.Qo)) alignment.dat$(EXEEXT): $(alignment_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(alignment_obj) alignment.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/alignment.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/alignment.Qo +include $(alignment_dep) # am--include-marker +r_depfiles_remade += $(alignment_dep) anonstruct_dat_SOURCES=anonstruct.r anonstruct_obj=$(anonstruct_dat_SOURCES:.r=.qfo) +anonstruct_dep=$(addprefix ./$(DEPDIR)/,$(anonstruct_obj:.qfo=.Qo)) anonstruct.dat$(EXEEXT): $(anonstruct_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(anonstruct_obj) anonstruct.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/anonstruct.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/anonstruct.Qo +include $(anonstruct_dep) # am--include-marker +r_depfiles_remade += $(anonstruct_dep) assignchain_dat_SOURCES=assignchain.r assignchain_obj=$(assignchain_dat_SOURCES:.r=.qfo) +assignchain_dep=$(addprefix ./$(DEPDIR)/,$(assignchain_obj:.qfo=.Qo)) assignchain.dat$(EXEEXT): $(assignchain_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(assignchain_obj) assignchain.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/assignchain.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/assignchain.Qo +include $(assignchain_dep) # am--include-marker +r_depfiles_remade += $(assignchain_dep) chewed_alias_dat_SOURCES=chewed-alias.r chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo) +chewed_alias_dep=$(addprefix ./$(DEPDIR)/,$(chewed_alias_obj:.qfo=.Qo)) chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_alias_obj) chewed-alias.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/chewed-alias.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/chewed-alias.Qo +include $(chewed_alias_dep) # am--include-marker +r_depfiles_remade += $(chewed_alias_dep) chewed_return_dat_SOURCES=chewed-return.r chewed_return_obj=$(chewed_return_dat_SOURCES:.r=.qfo) +chewed_return_dep=$(addprefix ./$(DEPDIR)/,$(chewed_return_obj:.qfo=.Qo)) chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(chewed_return_obj) chewed-return.run: Makefile build-run @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ -include ./$(DEPDIR)/chewed-return.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/chewed-return.Qo +include $(chewed_return_dep) # am--include-marker +r_depfiles_remade += $(chewed_return_dep) comma_expr_dat_SOURCES=comma-expr.r comma_expr_obj=$(comma_expr_dat_SOURCES:.r=.qfo) +comma_expr_dep=$(addprefix ./$(DEPDIR)/,$(comma_expr_obj:.qfo=.Qo)) comma-expr.dat$(EXEEXT): $(comma_expr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(comma_expr_obj) comma-expr.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/comma-expr.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/comma-expr.Qo +include $(comma_expr_dep) # am--include-marker +r_depfiles_remade += $(comma_expr_dep) compound_dat_SOURCES=compound.r compound_obj=$(compound_dat_SOURCES:.r=.qfo) +compound_dep=$(addprefix ./$(DEPDIR)/,$(compound_obj:.qfo=.Qo)) compound.dat$(EXEEXT): $(compound_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(compound_obj) compound.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/compound.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/compound.Qo +include $(compound_dep) # am--include-marker +r_depfiles_remade += $(compound_dep) deadbool_dat_SOURCES=deadbool.r deadbool_obj=$(deadbool_dat_SOURCES:.r=.qfo) +deadbool_dep=$(addprefix ./$(DEPDIR)/,$(deadbool_obj:.qfo=.Qo)) deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(deadbool_obj) deadbool.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/deadbool.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/deadbool.Qo +include $(deadbool_dep) # am--include-marker +r_depfiles_remade += $(deadbool_dep) double_dat_SOURCES=double.r double_obj=$(double_dat_SOURCES:.r=.qfo) +double_dep=$(addprefix ./$(DEPDIR)/,$(double_obj:.qfo=.Qo)) double.dat$(EXEEXT): $(double_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(double_obj) double.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/double.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/double.Qo +include $(double_dep) # am--include-marker +r_depfiles_remade += $(double_dep) double_alias_dat_SOURCES=double-alias.r double_alias_obj=$(double_alias_dat_SOURCES:.r=.qfo) +double_alias_dep=$(addprefix ./$(DEPDIR)/,$(double_alias_obj:.qfo=.Qo)) double-alias.dat$(EXEEXT): $(double_alias_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(double_alias_obj) double-alias.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/double-alias.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/double-alias.Qo +include $(double_alias_dep) # am--include-marker +r_depfiles_remade += $(double_alias_dep) classarray.run$(EXEEXT): classarray.r Makefile build-compile-fail-run @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< @@ -254,300 +265,333 @@ double-float-compare.run$(EXEEXT): double-float-compare.r Makefile build-compile enum_dat_SOURCES=enum.r enum_obj=$(enum_dat_SOURCES:.r=.qfo) +enum_dep=$(addprefix ./$(DEPDIR)/,$(enum_obj:.qfo=.Qo)) enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(enum_obj) enum.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/enum.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/enum.Qo +include $(enum_dep) # am--include-marker +r_depfiles_remade += $(enum_dep) fordecl_dat_SOURCES=fordecl.r fordecl_obj=$(fordecl_dat_SOURCES:.r=.qfo) +fordecl_dep=$(addprefix ./$(DEPDIR)/,$(fordecl_obj:.qfo=.Qo)) fordecl.dat$(EXEEXT): $(fordecl_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(fordecl_obj) fordecl.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/fordecl.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/fordecl.Qo +include $(fordecl_dep) # am--include-marker +r_depfiles_remade += $(fordecl_dep) func_expr_dat_SOURCES=func-expr.r func_expr_obj=$(func_expr_dat_SOURCES:.r=.qfo) +func_expr_dep=$(addprefix ./$(DEPDIR)/,$(func_expr_obj:.qfo=.Qo)) func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) func-expr.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/func-expr.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/func-expr.Qo +include $(func_expr_dep) # am--include-marker +r_depfiles_remade += $(func_expr_dep) func_expr2_dat_SOURCES=func-expr2.r func_expr2_obj=$(func_expr2_dat_SOURCES:.r=.qfo) +func_expr2_dep=$(addprefix ./$(DEPDIR)/,$(func_expr2_obj:.qfo=.Qo)) func-expr2.dat$(EXEEXT): $(func_expr2_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(func_expr2_obj) func-expr2.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/func-expr2.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/func-expr2.Qo +include $(func_expr2_dep) # am--include-marker +r_depfiles_remade += $(func_expr2_dep) func_static_dat_SOURCES=func-static.r func_static_obj=$(func_static_dat_SOURCES:.r=.qfo) +func_static_dep=$(addprefix ./$(DEPDIR)/,$(func_static_obj:.qfo=.Qo)) func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) func-static.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/func-static.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/func-static.Qo +include $(func_static_dep) # am--include-marker +r_depfiles_remade += $(func_static_dep) gcd_dat_SOURCES=gcd.pas gcd_obj=$(gcd_dat_SOURCES:.pas=.qfo) +gcd_dep=$(addprefix ./$(DEPDIR)/,$(gcd_obj:.qfo=.Qo)) gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(gcd_obj) gcd.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/gcd.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/gcd.Qo +include $(gcd_dep) # am--include-marker +r_depfiles_remade += $(gcd_dep) infloop_dat_SOURCES=infloop.r infloop_obj=$(infloop_dat_SOURCES:.r=.qfo) +infloop_dep=$(addprefix ./$(DEPDIR)/,$(infloop_obj:.qfo=.Qo)) infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(infloop_obj) infloop.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/infloop.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/infloop.Qo +include $(infloop_dep) # am--include-marker +r_depfiles_remade += $(infloop_dep) ivar_struct_return_dat_SOURCES=ivar-struct-return.r ivar_struct_return_obj=$(ivar_struct_return_dat_SOURCES:.r=.qfo) +ivar_struct_return_dep=$(addprefix ./$(DEPDIR)/,$(ivar_struct_return_obj:.qfo=.Qo)) ivar-struct-return.dat$(EXEEXT): $(ivar_struct_return_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(ivar_struct_return_obj) ivar-struct-return.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/ivar-struct-return.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/ivar-struct-return.Qo +include $(ivar_struct_return_dep) # am--include-marker +r_depfiles_remade += $(ivar_struct_return_dep) methodparams_dat_SOURCES=methodparams.r methodparams_obj=$(methodparams_dat_SOURCES:.r=.qfo) +methodparams_dep=$(addprefix ./$(DEPDIR)/,$(methodparams_obj:.qfo=.Qo)) methodparams.dat$(EXEEXT): $(methodparams_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(methodparams_obj) methodparams.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/methodparams.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/methodparams.Qo +include $(methodparams_dep) # am--include-marker +r_depfiles_remade += $(methodparams_dep) modulo_dat_SOURCES=modulo.r modulo_obj=$(modulo_dat_SOURCES:.r=.qfo) +modulo_dep=$(addprefix ./$(DEPDIR)/,$(modulo_obj:.qfo=.Qo)) modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(modulo_obj) modulo.run: Makefile build-run @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ -include ./$(DEPDIR)/modulo.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/modulo.Qo +include $(modulo_dep) # am--include-marker +r_depfiles_remade += $(modulo_dep) nilparamret_dat_SOURCES=nilparamret.r nilparamret_obj=$(nilparamret_dat_SOURCES:.r=.qfo) +nilparamret_dep=$(addprefix ./$(DEPDIR)/,$(nilparamret_obj:.qfo=.Qo)) nilparamret.dat$(EXEEXT): $(nilparamret_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(nilparamret_obj) nilparamret.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/nilparamret.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/nilparamret.Qo +include $(nilparamret_dep) # am--include-marker +r_depfiles_remade += $(nilparamret_dep) overload_dat_SOURCES=overload.r overload_obj=$(overload_dat_SOURCES:.r=.qfo) +overload_dep=$(addprefix ./$(DEPDIR)/,$(overload_obj:.qfo=.Qo)) overload.dat$(EXEEXT): $(overload_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(overload_obj) overload.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/overload.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/overload.Qo +include $(overload_dep) # am--include-marker +r_depfiles_remade += $(overload_dep) paramret_dat_SOURCES=paramret.r paramret_obj=$(paramret_dat_SOURCES:.r=.qfo) +paramret_dep=$(addprefix ./$(DEPDIR)/,$(paramret_obj:.qfo=.Qo)) paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) paramret.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/paramret.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/paramret.Qo +include $(paramret_dep) # am--include-marker +r_depfiles_remade += $(paramret_dep) quaternion_dat_SOURCES=quaternion.r quaternion_obj=$(quaternion_dat_SOURCES:.r=.qfo) +quaternion_dep=$(addprefix ./$(DEPDIR)/,$(quaternion_obj:.qfo=.Qo)) quaternion.dat$(EXEEXT): $(quaternion_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(quaternion_obj) quaternion.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/quaternion.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/quaternion.Qo +include $(quaternion_dep) # am--include-marker +r_depfiles_remade += $(quaternion_dep) return_ivar_dat_SOURCES=return-ivar.r return_ivar_obj=$(return_ivar_dat_SOURCES:.r=.qfo) +return_ivar_dep=$(addprefix ./$(DEPDIR)/,$(return_ivar_obj:.qfo=.Qo)) return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(return_ivar_obj) return-ivar.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/return-ivar.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/return-ivar.Qo +include $(return_ivar_dep) # am--include-marker +r_depfiles_remade += $(return_ivar_dep) sendv_dat_SOURCES=sendv.r sendv_obj=$(sendv_dat_SOURCES:.r=.qfo) +sendv_dep=$(addprefix ./$(DEPDIR)/,$(sendv_obj:.qfo=.Qo)) sendv.dat$(EXEEXT): $(sendv_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(sendv_obj) sendv.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/sendv.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/sendv.Qo +include $(sendv_dep) # am--include-marker +r_depfiles_remade += $(sendv_dep) state_dat_SOURCES=state.r state_obj=$(state_dat_SOURCES:.r=.qfo) +state_dep=$(addprefix ./$(DEPDIR)/,$(state_obj:.qfo=.Qo)) state.dat$(EXEEXT): $(state_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(state_obj) state.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/state.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/state.Qo +include $(state_dep) # am--include-marker +r_depfiles_remade += $(state_dep) struct_init_param_dat_SOURCES=struct-init-param.r struct_init_param_obj=$(struct_init_param_dat_SOURCES:.r=.qfo) +struct_init_param_dep=$(addprefix ./$(DEPDIR)/,$(struct_init_param_obj:.qfo=.Qo)) struct-init-param.dat$(EXEEXT): $(struct_init_param_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(struct_init_param_obj) struct-init-param.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/struct-init-param.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/struct-init-param.Qo +include $(struct_init_param_dep) # am--include-marker +r_depfiles_remade += $(struct_init_param_dep) struct_nil_init_dat_SOURCES=struct-nil-init.r struct_nil_init_obj=$(struct_nil_init_dat_SOURCES:.r=.qfo) +struct_nil_init_dep=$(addprefix ./$(DEPDIR)/,$(struct_nil_init_obj:.qfo=.Qo)) struct-nil-init.dat$(EXEEXT): $(struct_nil_init_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(struct_nil_init_obj) struct-nil-init.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/struct-nil-init.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/struct-nil-init.Qo +include $(struct_nil_init_dep) # am--include-marker +r_depfiles_remade += $(struct_nil_init_dep) structarray_dat_SOURCES=structarray.r structarray_obj=$(structarray_dat_SOURCES:.r=.qfo) +structarray_dep=$(addprefix ./$(DEPDIR)/,$(structarray_obj:.qfo=.Qo)) structarray.dat$(EXEEXT): $(structarray_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structarray_obj) structarray.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/structarray.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/structarray.Qo +include $(structarray_dep) # am--include-marker +r_depfiles_remade += $(structarray_dep) structlive_dat_SOURCES=structlive.r structlive_obj=$(structlive_dat_SOURCES:.r=.qfo) +structlive_dep=$(addprefix ./$(DEPDIR)/,$(structlive_obj:.qfo=.Qo)) structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structlive_obj) structlive.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/structlive.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/structlive.Qo +include $(structlive_dep) # am--include-marker +r_depfiles_remade += $(structlive_dep) structptr_dat_SOURCES=structptr.r structptr_obj=$(structptr_dat_SOURCES:.r=.qfo) +structptr_dep=$(addprefix ./$(DEPDIR)/,$(structptr_obj:.qfo=.Qo)) structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structptr_obj) structptr.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/structptr.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/structptr.Qo +include $(structptr_dep) # am--include-marker +r_depfiles_remade += $(structptr_dep) structstruct_dat_SOURCES=structstruct.r structstruct_obj=$(structstruct_dat_SOURCES:.r=.qfo) +structstruct_dep=$(addprefix ./$(DEPDIR)/,$(structstruct_obj:.qfo=.Qo)) structstruct.dat$(EXEEXT): $(structstruct_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(structstruct_obj) structstruct.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/structstruct.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/structstruct.Qo +include $(structstruct_dep) # am--include-marker +r_depfiles_remade += $(structstruct_dep) swap_dat_SOURCES=swap.r swap_obj=$(swap_dat_SOURCES:.r=.qfo) +swap_dep=$(addprefix ./$(DEPDIR)/,$(swap_obj:.qfo=.Qo)) swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(swap_obj) swap.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/swap.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/swap.Qo +include $(swap_dep) # am--include-marker +r_depfiles_remade += $(swap_dep) triangle_dat_SOURCES=triangle.r triangle_obj=$(triangle_dat_SOURCES:.r=.qfo) +triangle_dep=$(addprefix ./$(DEPDIR)/,$(triangle_obj:.qfo=.Qo)) triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) triangle.run: Makefile build-run @$(srcdir)/build-run $@ 100000 100000 1.00005 50002.4961 -include ./$(DEPDIR)/triangle.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/triangle.Qo +include $(triangle_dep) # am--include-marker +r_depfiles_remade += $(triangle_dep) typedef_dat_SOURCES=typedef.r typedef_obj=$(typedef_dat_SOURCES:.r=.qfo) +typedef_dep=$(addprefix ./$(DEPDIR)/,$(typedef_obj:.qfo=.Qo)) typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) typedef.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/typedef.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/typedef.Qo +include $(typedef_dep) # am--include-marker +r_depfiles_remade += $(typedef_dep) typelinker_dat_SOURCES=typelinker_a.r typelinker_b.r typelinker_obj=$(typelinker_dat_SOURCES:.r=.qfo) +typelinker_dep=$(addprefix ./$(DEPDIR)/,$(typelinker_obj:.qfo=.Qo)) typelinker.dat$(EXEEXT): $(typelinker_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(typelinker_obj) typelinker.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/typelinker.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/typelinker.Qo +include $(typelinker_dep) # am--include-marker +r_depfiles_remade += $(typelinker_dep) vecaddr_dat_SOURCES=vecaddr.r vecaddr_obj=$(vecaddr_dat_SOURCES:.r=.qfo) +vecaddr_dep=$(addprefix ./$(DEPDIR)/,$(vecaddr_obj:.qfo=.Qo)) vecaddr.dat$(EXEEXT): $(vecaddr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(vecaddr_obj) vecaddr.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/vecaddr.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/vecaddr.Qo +include $(vecaddr_dep) # am--include-marker +r_depfiles_remade += $(vecaddr_dep) vecexpr_dat_SOURCES=vecexpr.r vecexpr_obj=$(vecexpr_dat_SOURCES:.r=.qfo) +vecexpr_dep=$(addprefix ./$(DEPDIR)/,$(vecexpr_obj:.qfo=.Qo)) vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(vecexpr_obj) vecexpr.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/vecexpr.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/vecexpr.Qo +include $(vecexpr_dep) # am--include-marker +r_depfiles_remade += $(vecexpr_dep) vecinit_dat_SOURCES=vecinit.r vecinit_obj=$(vecinit_dat_SOURCES:.r=.qfo) +vecinit_dep=$(addprefix ./$(DEPDIR)/,$(vecinit_obj:.qfo=.Qo)) vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(vecinit_obj) vecinit.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/vecinit.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/vecinit.Qo +include $(vecinit_dep) # am--include-marker +r_depfiles_remade += $(vecinit_dep) voidfor_dat_SOURCES=voidfor.r voidfor_obj=$(voidfor_dat_SOURCES:.r=.qfo) +voidfor_dep=$(addprefix ./$(DEPDIR)/,$(voidfor_obj:.qfo=.Qo)) voidfor.dat$(EXEEXT): $(voidfor_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj) voidfor.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/voidfor.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/voidfor.Qo +include $(voidfor_dep) # am--include-marker +r_depfiles_remade += $(voidfor_dep) while_dat_SOURCES=while.r while_obj=$(while_dat_SOURCES:.r=.qfo) +while_dep=$(addprefix ./$(DEPDIR)/,$(while_obj:.qfo=.Qo)) while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(while_obj) while.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/while.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/while.Qo +include $(while_dep) # am--include-marker +r_depfiles_remade += $(while_dep) zerolinker_dat_SOURCES=zerolinker.r zerolinker_obj=$(zerolinker_dat_SOURCES:.r=.qfo) +zerolinker_dep=$(addprefix ./$(DEPDIR)/,$(zerolinker_obj:.qfo=.Qo)) zerolinker.dat$(EXEEXT): $(zerolinker_obj) $(QFCC_DEP) $(QFCC) $(QCFLAGS) -o $@ $(zerolinker_obj) zerolinker.run: Makefile build-run @$(srcdir)/build-run $@ -include ./$(DEPDIR)/zerolinker.Qo # am--include-marker -r_depfiles_remade += ./$(DEPDIR)/zerolinker.Qo +include $(zerolinker_dep) # am--include-marker +r_depfiles_remade += $(zerolinker_dep) $(r_depfiles_remade): @$(MKDIR_P) $(@D) From 9400b9b1158e5a09d02fbfd48e900a1fab48fa3b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 19:56:07 +0900 Subject: [PATCH 1028/3664] [qfcc] Add a leading . to the compile_unit def --- tools/qfcc/source/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index d433304e2..7086f44dc 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -197,7 +197,7 @@ emit_compunit (const char *modname) pr.unit_name = modname; compunit_struct[3].type = array_type (&type_string, count); - return emit_structure ("compile_unit", 's', compunit_struct, 0, &pr, + return emit_structure (".compile_unit", 's', compunit_struct, 0, &pr, pr.debug_data, sc_static); } From 7c5c4625875547003ee7c11c196008d4e625ff03 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 21:25:47 +0900 Subject: [PATCH 1029/3664] [qfcc] Write debug data space to sym file This should keep things nicely extensible, since additional data can be done in the data space and found using defs. This gets the compilation units into the sym file. --- include/QF/pr_debug.h | 6 +++++- tools/qfcc/source/obj_file.c | 42 +++++++++++++++++++++++++++--------- tools/qfcc/source/qfcc.c | 24 +++++++++++++++++---- 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/include/QF/pr_debug.h b/include/QF/pr_debug.h index ab10b62a2..4015f6f65 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/pr_debug.h @@ -58,7 +58,7 @@ typedef struct pr_lineno_s { pr_uint_t line; } pr_lineno_t; -#define PROG_DEBUG_VERSION 0x00001003 // MMmmmRRR 0.001.002 (hex) +#define PROG_DEBUG_VERSION 0x00001004 // MMmmmRRR 0.001.004 (hex) typedef struct pr_debug_header_s { pr_int_t version; @@ -70,6 +70,10 @@ typedef struct pr_debug_header_s { pr_uint_t num_linenos; pr_uint_t locals; pr_uint_t num_locals; + pr_uint_t debug_defs; + pr_uint_t num_debug_defs; + pr_uint_t debug_data; + pr_uint_t debug_data_size; } pr_debug_header_t; #endif diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index a7e419c62..dcc1543d4 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -813,7 +813,7 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) } static void -convert_def (qfo_t *qfo, const qfo_def_t *def, ddef_t *ddef) +qfo_def_to_ddef (qfo_t *qfo, const qfo_def_t *def, ddef_t *ddef) { ddef->type = get_def_type (qfo, def->type); ddef->ofs = def->offset; @@ -826,6 +826,16 @@ convert_def (qfo_t *qfo, const qfo_def_t *def, ddef_t *ddef) ddef->type |= DEF_SAVEGLOBAL; } +static void +qfo_def_to_prdef (qfo_t *qfo, const qfo_def_t *def, pr_def_t *prdef) +{ + prdef->type = get_def_type (qfo, def->type); + prdef->size = get_type_size (qfo, def->type); + prdef->ofs = def->offset; + prdef->name = def->name; + prdef->type_encoding = def->type; +} + static void qfo_relocate_refs (qfo_t *qfo) { @@ -1072,14 +1082,14 @@ qfo_to_progs (qfo_t *qfo, int *size) types_def = def; if (!strcmp (defname, ".xdefs")) xdefs_def = def; - convert_def (qfo, def, globaldefs++); + qfo_def_to_ddef (qfo, def, globaldefs++); } for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { unsigned ind = far_def_indices[i]; qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + ind; def->offset += far_data - globals; - convert_def (qfo, def, globaldefs); + qfo_def_to_ddef (qfo, def, globaldefs); // the correct offset will be written to the far data space globaldefs->ofs = -1; globaldefs++; @@ -1091,7 +1101,7 @@ qfo_to_progs (qfo_t *qfo, int *size) for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { unsigned ind = field_def_indices[i]; - convert_def (qfo, qfo->spaces[qfo_entity_space].defs + ind, + qfo_def_to_ddef (qfo, qfo->spaces[qfo_entity_space].defs + ind, fielddefs + i); } @@ -1192,7 +1202,8 @@ qfo_to_sym (qfo_t *qfo, int *size) pr_auxfunction_t *auxfuncs; pr_auxfunction_t *aux; pr_lineno_t *linenos; - pr_def_t *locals, *ld; + pr_def_t *locals, *ld, *debug_defs; + pr_type_t *debug_data; *size = sizeof (pr_debug_header_t); sym = calloc (1, *size); @@ -1210,19 +1221,27 @@ qfo_to_sym (qfo_t *qfo, int *size) sym->num_locals += num_locals; } sym->num_linenos = qfo->num_lines; + sym->num_debug_defs = qfo->spaces[qfo_debug_space].num_defs; + sym->debug_data_size = qfo->spaces[qfo_debug_space].data_size; *size += sym->num_auxfunctions * sizeof (pr_auxfunction_t); *size += sym->num_linenos * sizeof (pr_lineno_t); *size += sym->num_locals * sizeof (pr_def_t); + *size += sym->num_debug_defs * sizeof (pr_def_t); + *size += sym->debug_data_size * sizeof (pr_type_t); sym = realloc (sym, *size); auxfuncs = (pr_auxfunction_t *)(sym + 1); linenos = (pr_lineno_t *)(auxfuncs + sym->num_auxfunctions); locals = (pr_def_t *)(linenos + sym->num_linenos); + debug_defs = locals + sym->num_locals; + debug_data = (pr_type_t *)(debug_defs + sym->num_debug_defs); sym->auxfunctions = (char *) auxfuncs - (char *) sym; sym->linenos = (char *) linenos - (char *) sym; sym->locals = (char *) locals - (char *) sym; + sym->debug_defs = (char *) debug_defs - (char *) sym; + sym->debug_data = (char *) debug_data - (char *) sym; ld = locals; @@ -1247,11 +1266,7 @@ qfo_to_sym (qfo_t *qfo, int *size) if (num_locals) { aux->local_defs = ld - locals; for (j = 0; j < num_locals; j++, def++, ld++) { - ld->type = get_def_type (qfo, def->type); - ld->size = get_type_size (qfo, def->type); - ld->ofs = def->offset; - ld->name = def->name; - ld->type_encoding = def->type; + qfo_def_to_prdef (qfo, def, ld); } } aux->num_locals = num_locals; @@ -1265,5 +1280,12 @@ qfo_to_sym (qfo_t *qfo, int *size) aux++; } memcpy (linenos, qfo->lines, qfo->num_lines * sizeof (pr_lineno_t)); + for (i = 0; i < sym->num_debug_defs; i++) { + qfo_def_t *def = &qfo->spaces[qfo_debug_space].defs[i]; + pr_def_t *prdef = &debug_defs[i]; + qfo_def_to_prdef (qfo, def, prdef); + } + memcpy (debug_data, qfo->spaces[qfo_debug_space].d.data, + sym->debug_data_size * sizeof (*debug_data)); return sym; } diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 603c86377..c0739e9f0 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -266,12 +266,16 @@ WriteSym (pr_debug_header_t *sym, int size) pr_auxfunction_t *auxfunctions; pr_lineno_t *linenos; - ddef_t *locals; + pr_def_t *locals; + pr_def_t *debug_defs; + pr_type_t *debug_data; #define P(t,o) ((t *)((char *)sym + sym->o)) auxfunctions = P (pr_auxfunction_t, auxfunctions); linenos = P (pr_lineno_t, linenos); - locals = P (ddef_t, locals); + locals = P (pr_def_t, locals); + debug_defs = P (pr_def_t, debug_defs); + debug_data = P (pr_type_t, debug_data); #undef P for (i = 0; i < sym->num_auxfunctions; i++) { @@ -290,8 +294,20 @@ WriteSym (pr_debug_header_t *sym, int size) } for (i = 0; i < sym->num_locals; i++) { locals[i].type = LittleShort (locals[i].type); - locals[i].ofs = LittleShort (locals[i].ofs); - locals[i].s_name = LittleLong (locals[i].s_name); + locals[i].size = LittleShort (locals[i].size); + locals[i].ofs = LittleLong (locals[i].ofs); + locals[i].name = LittleLong (locals[i].name); + locals[i].type_encoding = LittleLong (locals[i].type_encoding); + } + for (i = 0; i < sym->num_debug_defs; i++) { + debug_defs[i].type = LittleShort (debug_defs[i].type); + debug_defs[i].size = LittleShort (debug_defs[i].size); + debug_defs[i].ofs = LittleLong (debug_defs[i].ofs); + debug_defs[i].name = LittleLong (debug_defs[i].name); + debug_defs[i].type_encoding = LittleLong (debug_defs[i].type_encoding); + } + for (i = 0; i < sym->debug_data_size; i++) { + debug_data[i].integer_var = LittleLong (debug_data[i].integer_var); } if (!(h = Qopen (options.debug_file, "wb"))) From fbbe144399f76a9f9b56ea2ad8cc702ad2a4cca9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 22:35:55 +0900 Subject: [PATCH 1030/3664] [gamecode] Clean up some stray "struct" Left over from moving debug data from progs.h to pr_debug.c --- libs/gamecode/pr_debug.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 61e45ce8b..90f936013 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -77,10 +77,10 @@ typedef struct prdeb_resources_s { dstring_t *line; dstring_t *dstr; const char *debugfile; - struct pr_debug_header_s *debug; - struct pr_auxfunction_s *auxfunctions; - struct pr_auxfunction_s **auxfunction_map; - struct pr_lineno_s *linenos; + pr_debug_header_t *debug; + pr_auxfunction_t *auxfunctions; + pr_auxfunction_t **auxfunction_map; + pr_lineno_t *linenos; pr_def_t *local_defs; pr_def_t *type_encodings_def; qfot_type_t void_type; From 7bcfd2f2beaffb29556585c68ea6fedf69834355 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Apr 2020 22:39:27 +0900 Subject: [PATCH 1031/3664] [gamecode] Move file_hash into debug resources I don't remember why I didn't do this earlier when I thread-safed progs. --- libs/gamecode/pr_debug.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 90f936013..f5f1650af 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -85,6 +85,7 @@ typedef struct prdeb_resources_s { pr_def_t *type_encodings_def; qfot_type_t void_type; qfot_type_t *type_encodings[ev_type_count]; + hashtab_t *file_hash; } prdeb_resources_t; typedef struct { @@ -94,9 +95,8 @@ typedef struct { cvar_t *pr_debug; cvar_t *pr_source_path; -static hashtab_t *file_hash; -static char *source_path_string; -static char **source_paths; +static char *source_path_string; +static char **source_paths; static void pr_debug_void_view (qfot_type_t *type, pr_type_t *value, void *_data); @@ -345,6 +345,9 @@ pr_debug_clear (progs_t *pr, void *data) if (res->debug) pr->free_progs_mem (pr, res->debug); + if (res->file_hash) { + Hash_FlushTable (res->file_hash); + } res->debug = 0; res->auxfunctions = 0; if (res->auxfunction_map) @@ -368,7 +371,7 @@ PR_Load_Source_File (progs_t *pr, const char *fname) { prdeb_resources_t *res = pr->pr_debug_resources; char *l, *p, **dir; - file_t *f = Hash_Find (file_hash, fname); + file_t *f = Hash_Find (res->file_hash, fname); if (f) return f; @@ -415,7 +418,7 @@ PR_Load_Source_File (progs_t *pr, const char *fname) f->num_lines++; } f->pr = pr; - Hash_Add (file_hash, f); + Hash_Add (res->file_hash, f); return f; } @@ -441,7 +444,6 @@ PR_LoadDebug (progs_t *pr) if (def) str = &pr->pr_globals[def->ofs]; - Hash_FlushTable (file_hash); if (!str) return 1; res->debugfile = PR_GetString (pr, str->string_var); @@ -1613,12 +1615,10 @@ PR_Debug_Init (progs_t *pr) for (int i = 0; i < ev_type_count; i++ ) { res->type_encodings[i] = &res->void_type; } + res->file_hash = Hash_NewTable (1024, file_get_key, file_free, 0, + pr->hashlink_freelist); PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); - if (!file_hash) { - file_hash = Hash_NewTable (1024, file_get_key, file_free, 0, - pr->hashlink_freelist); - } PR_AddLoadFunc (pr, PR_LoadDebug); } From 686fc4c43e53a1b86d37242d5b0241e4e0ce88be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Apr 2020 10:58:53 +0900 Subject: [PATCH 1032/3664] [qwaq] Guard qwaq_debug_data with a pthread cond I should have realized this would be prone to races. --- ruamoko/qwaq/builtins/debug.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 4fec2a1ac..2eb61e7b1 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -136,6 +136,24 @@ qwaq_debug_handler (prdebug_t debug_event, void *param, void *data) } } +//FIXME need a better way to get this from one thread to the others +pthread_cond_t debug_data_cond = PTHREAD_COND_INITIALIZER; +pthread_mutex_t debug_data_mutex = PTHREAD_MUTEX_INITIALIZER; +static qwaq_debug_t *qwaq_debug_data; + +static int +qwaq_debug_load (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + + pthread_mutex_lock (&debug_data_mutex); + qwaq_debug_data = debug; // FIXME ? see decl + pthread_cond_broadcast (&debug_data_cond); + pthread_mutex_unlock (&debug_data_mutex); + + return 1; +} + static void qwaq_debug_clear (progs_t *pr, void *data) { @@ -152,12 +170,15 @@ qwaq_target_clear (progs_t *pr, void *data) } } -//FIXME need a better way to get this from one thread to the others -static qwaq_debug_t *qwaq_debug_data; - static int qwaq_target_load (progs_t *pr) { + pthread_mutex_lock (&debug_data_mutex); + while (!qwaq_debug_data) { + pthread_cond_wait (&debug_data_cond, &debug_data_mutex); + } + pthread_mutex_unlock (&debug_data_mutex); + qwaq_target_t *target = target_new (qwaq_debug_data); target->pr = pr; target->debugger = qwaq_debug_data; @@ -596,10 +617,11 @@ void QWAQ_Debug_Init (progs_t *pr) { qwaq_debug_t *debug = calloc (sizeof (*debug), 1); - qwaq_debug_data = debug; // FIXME ? see decl + debug->pr = pr; debug->qwaq = PR_Resources_Find (pr, "qwaq"); + PR_AddLoadFunc (pr, qwaq_debug_load); PR_Resources_Register (pr, "qwaq-debug", debug, qwaq_debug_clear); PR_RegisterBuiltins (pr, builtins); } From 59f48e5e32c6688b0c654515c14fb0abf327b1b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Apr 2020 12:32:12 +0900 Subject: [PATCH 1033/3664] [gamecode] Add function to test if string exists As it returns the string id, it is useful for getting an string id without risking creating a new one. --- include/QF/progs.h | 9 +++++++++ libs/gamecode/pr_strings.c | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index fd9d653f7..1445081fd 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1290,6 +1290,15 @@ struct dstring_s *PR_GetMutableString(progs_t *pr, string_t num) __attribute__(( */ string_t PR_SetString(progs_t *pr, const char *s); +/** Get the progs string if it exists. + Only static strings are searched. + \param pr pointer to ::progs_t VM struct + \param s C string to be found + \return string index of the progs string if it exists, otherwise + 0 (ambiguous with ""). +*/ +string_t PR_FindString(progs_t *pr, const char *s); + /** Make a temporary progs string that will survive across function returns. Will not duplicate a permanent string. If a new progs string is created, it will be freed after ::PR_RS_SLOTS calls to this function. ie, up to diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 1b5051859..00a7d67df 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -440,6 +440,22 @@ PR_SetString (progs_t *pr, const char *s) return string_index (res, sr); } +VISIBLE string_t +PR_FindString (progs_t *pr, const char *s) +{ + prstr_resources_t *res = pr->pr_string_resources; + strref_t *sr; + + if (!s) + s = ""; + sr = Hash_Find (res->strref_hash, s); + + if (sr) { + return string_index (res, sr); + } + return 0; +} + VISIBLE string_t PR_SetReturnString (progs_t *pr, const char *s) { From cf7c4780eb2ec6f1e650487ca78427bbb3f1d0cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Apr 2020 12:50:25 +0900 Subject: [PATCH 1034/3664] [gamecode] Load extended debug data And add function to get a source file's base directory if available. --- include/QF/progs.h | 1 + libs/gamecode/pr_debug.c | 107 +++++++++++++++++++++++++++++++++++---- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 1445081fd..abc92f7f5 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1689,6 +1689,7 @@ typedef struct type_view_s { void PR_Debug_Init (progs_t *pr); void PR_Debug_Init_Cvars (void); int PR_LoadDebug (progs_t *pr); +const char *PR_Debug_GetBaseDirectory (progs_t *pr, const char *file); void PR_Debug_Watch (progs_t *pr, const char *expr); void PR_Debug_Print (progs_t *pr, const char *expr); pr_auxfunction_t *PR_Debug_AuxFunction (progs_t *pr, pr_uint_t func) __attribute__((pure)); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index f5f1650af..3d99da30a 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -70,6 +70,11 @@ typedef struct { progs_t *pr; } file_t; +typedef struct compunit_s { + const char *file; + pr_compunit_t *unit; +} compunit_t; + typedef struct prdeb_resources_s { progs_t *pr; dstring_t *string; @@ -85,6 +90,11 @@ typedef struct prdeb_resources_s { pr_def_t *type_encodings_def; qfot_type_t void_type; qfot_type_t *type_encodings[ev_type_count]; + pr_def_t *debug_defs; + pr_type_t *debug_data; + hashtab_t *debug_syms; + hashtab_t *compunits; // by source file + PR_RESMAP (compunit_t) compmap; // handy allocation/freeing hashtab_t *file_hash; } prdeb_resources_t; @@ -174,6 +184,21 @@ file_free (void *_f, void *unused) free (f); } +static const char * +def_get_key (const void *d, void *p) +{ + __auto_type def = (pr_def_t *) d; + __auto_type pr = (progs_t *) p; + return PR_GetString (pr, def->name); +} + +static const char * +compunit_get_key (const void *cu, void *p) +{ + __auto_type compunit = (compunit_t *) cu; + return compunit->file; +} + static void source_path_f (cvar_t *var) { @@ -345,9 +370,10 @@ pr_debug_clear (progs_t *pr, void *data) if (res->debug) pr->free_progs_mem (pr, res->debug); - if (res->file_hash) { - Hash_FlushTable (res->file_hash); - } + Hash_FlushTable (res->file_hash); + Hash_FlushTable (res->debug_syms); + Hash_FlushTable (res->compunits); + PR_RESRESET (compunit_t, res->compmap); res->debug = 0; res->auxfunctions = 0; if (res->auxfunction_map) @@ -422,6 +448,36 @@ PR_Load_Source_File (progs_t *pr, const char *fname) return f; } +static void +byteswap_def (pr_def_t *def) +{ + def->type = LittleShort (def->type); + def->size = LittleShort (def->size); + def->ofs = LittleLong (def->ofs); + def->name = LittleLong (def->name); + def->type_encoding = LittleLong (def->type_encoding); +} + +static compunit_t * +new_compunit (prdeb_resources_t *res) +{ + PR_RESNEW (compunit_t, res->compmap); +} + +static void +process_compunit (prdeb_resources_t *res, pr_def_t *def) +{ + progs_t *pr = res->pr; + __auto_type compunit = (pr_compunit_t *) (res->debug_data + def->ofs); + + for (unsigned i = 0; i < compunit->num_files; i++) { + compunit_t *cu = new_compunit (res); + cu->unit = compunit; + cu->file = PR_GetString (pr, compunit->files[i]); + Hash_Add (res->compunits, cu); + } +} + VISIBLE int PR_LoadDebug (progs_t *pr) { @@ -436,7 +492,9 @@ PR_LoadDebug (progs_t *pr) pointer_t type_encodings = 0; pointer_t type_ptr; qfot_type_t *type; + string_t compunit_str; + pr->pr_debug_resources = res; if (!pr_debug->int_val) return 1; @@ -490,11 +548,17 @@ PR_LoadDebug (progs_t *pr) res->debug->num_linenos = LittleLong (res->debug->num_linenos); res->debug->locals = LittleLong (res->debug->locals); res->debug->num_locals = LittleLong (res->debug->num_locals); + res->debug->debug_defs = LittleLong (res->debug->debug_defs); + res->debug->num_debug_defs = LittleLong (res->debug->num_debug_defs); + res->debug->debug_data = LittleLong (res->debug->debug_data); + res->debug->debug_data_size = LittleLong (res->debug->debug_data_size); res->auxfunctions = (pr_auxfunction_t*)((char*)res->debug + res->debug->auxfunctions); res->linenos = (pr_lineno_t*)((char*)res->debug + res->debug->linenos); res->local_defs = (pr_def_t*)((char*)res->debug + res->debug->locals); + res->debug_defs = (pr_def_t*)((char*)res->debug + res->debug->debug_defs); + res->debug_data = (pr_type_t*)((char*)res->debug + res->debug->debug_data); i = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); res->auxfunction_map = pr->allocate_progs_mem (pr, i); @@ -530,16 +594,23 @@ PR_LoadDebug (progs_t *pr) res->linenos[i].line = LittleLong (res->linenos[i].line); } for (i = 0; i < res->debug->num_locals; i++) { - res->local_defs[i].type = LittleShort (res->local_defs[i].type); - res->local_defs[i].size = LittleShort (res->local_defs[i].size); - res->local_defs[i].ofs = LittleLong (res->local_defs[i].ofs); - res->local_defs[i].name = LittleLong (res->local_defs[i].name); - res->local_defs[i].type_encoding - = LittleLong (res->local_defs[i].type_encoding); + byteswap_def (&res->local_defs[i]); if (type_encodings) { res->local_defs[i].type_encoding += type_encodings; } } + compunit_str = PR_FindString (pr, ".compile_unit"); + for (i = 0; i < res->debug->num_debug_defs; i++) { + pr_def_t *def = &res->debug_defs[i]; + byteswap_def (def); + if (type_encodings) { + def->type_encoding += type_encodings; + } + Hash_Add (res->debug_syms, def); + if (def->name == compunit_str) { + process_compunit (res, def); + } + } if (encodings) { for (type_ptr = 4; type_ptr < encodings->size; type_ptr += type->size) { @@ -553,6 +624,18 @@ PR_LoadDebug (progs_t *pr) return 1; } +VISIBLE const char * +PR_Debug_GetBaseDirectory (progs_t *pr, const char *file) +{ + prdeb_resources_t *res = pr->pr_debug_resources; + __auto_type cu = (compunit_t *) Hash_Find (res->compunits, file); + + if (cu) { + return PR_GetString (pr, cu->unit->basedir); + } + return 0; +} + VISIBLE pr_auxfunction_t * PR_Debug_AuxFunction (progs_t *pr, pr_uint_t func) { @@ -1615,7 +1698,11 @@ PR_Debug_Init (progs_t *pr) for (int i = 0; i < ev_type_count; i++ ) { res->type_encodings[i] = &res->void_type; } - res->file_hash = Hash_NewTable (1024, file_get_key, file_free, 0, + res->file_hash = Hash_NewTable (509, file_get_key, file_free, 0, + pr->hashlink_freelist); + res->debug_syms = Hash_NewTable (509, def_get_key, 0, pr, + pr->hashlink_freelist); + res->compunits = Hash_NewTable (509, compunit_get_key, 0, pr, pr->hashlink_freelist); PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); From 63714c7c55828accd63eeaf7e6a9a0dcf03b5c61 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Apr 2020 12:51:42 +0900 Subject: [PATCH 1035/3664] [qwaq] Add builtin to get a file's full path If the file's base directory cannot be found, the file name is returned as-is. --- ruamoko/qwaq/builtins/debug.c | 27 +++++++++++++++++++++++++++ ruamoko/qwaq/debugger/debug.h | 1 + ruamoko/qwaq/debugger/debug.r | 1 + 3 files changed, 29 insertions(+) diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 2eb61e7b1..be143ec87 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -44,6 +44,7 @@ #include "QF/dstring.h" #include "QF/hash.h" #include "QF/keys.h" +#include "QF/quakefs.h" #include "QF/sys.h" #include "qwaq.h" @@ -427,6 +428,31 @@ qdb_get_string (progs_t *pr) } } +static void +qdb_get_file_path (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + const char *file = P_GSTRING (pr, 1); + const char *basedir = PR_Debug_GetBaseDirectory (tpr, file); + + if (basedir) { + size_t baselen = strlen (basedir); + size_t filelen = strlen (file); + char *path = alloca (baselen + filelen + 2); + strcpy (path, basedir); + path[baselen] = '/'; + strcpy (path + baselen + 1, file); + path = QFS_CompressPath (path); + RETURN_STRING (pr, path); + free (path); + } else { + R_STRING (pr) = P_STRING (pr, 1); + } +} + static void qdb_find_global (progs_t *pr) { @@ -603,6 +629,7 @@ static builtin_t builtins[] = { {"qdb_get_data", qdb_get_data, -1}, {"qdb_get_string|{tag qdb_target_s=}i", qdb_get_string, -1}, {"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1}, + {"qdb_get_file_path", qdb_get_file_path, -1}, {"qdb_find_global", qdb_find_global, -1}, {"qdb_find_field", qdb_find_field, -1}, {"qdb_find_function", qdb_find_function, -1}, diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index 6dc86ab1c..6efeb5fb2 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -87,6 +87,7 @@ int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst); // note: str is likely not valid in the host progs, it's just a convinience to // avoid cast shenanigans when getting type encoding strings @overload string qdb_get_string (qdb_target_t target, string str); +string qdb_get_file_path (qdb_target_t target, string file); qdb_def_t qdb_find_global (qdb_target_t target, string name); qdb_def_t qdb_find_field (qdb_target_t target, string name); qdb_function_t *qdb_find_function (qdb_target_t target, string name); diff --git a/ruamoko/qwaq/debugger/debug.r b/ruamoko/qwaq/debugger/debug.r index 792b20d61..20ccc57b3 100644 --- a/ruamoko/qwaq/debugger/debug.r +++ b/ruamoko/qwaq/debugger/debug.r @@ -17,6 +17,7 @@ int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst) = #0; string qdb_get_string (qdb_target_t target, unsigned str) = #0; string qdb_get_string (qdb_target_t target, string str) = #0; +string qdb_get_file_path (qdb_target_t target, string file) = #0; qdb_def_t qdb_find_global (qdb_target_t target, string name) = #0; qdb_def_t qdb_find_field (qdb_target_t target, string name) = #0; qdb_function_t *qdb_find_function (qdb_target_t target, string name) = #0; From 2bec2527b4a875c7f34bca7c208781281fba7b39 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Apr 2020 14:30:50 +0900 Subject: [PATCH 1036/3664] [gamecode] Re-expose PR_LoadStrings It's required for qfprogs now that PR_LoadDebug reads strings early. --- include/QF/progs.h | 7 +++++++ libs/gamecode/pr_strings.c | 2 +- tools/qfcc/source/qfprogs.c | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index abc92f7f5..8a78926bf 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1254,6 +1254,13 @@ int PR_RelocateBuiltins (progs_t *pr); */ void PR_Strings_Init (progs_t *pr); +/** Initialize the string tables using the strings supplied by the progs. + Called automatically during progs load. + \param pr pointer to ::progs_t VM struct + \return true for success, false for failure +*/ +int PR_LoadStrings (progs_t *pr); + /** Check the validity of a string index. \param pr pointer to ::progs_t VM struct \param num string index to be validated diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 00a7d67df..89d5ee60f 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -229,7 +229,7 @@ pr_strings_clear (progs_t *pr, void *data) pr->pr_xtstr = 0; } -static int +VISIBLE int PR_LoadStrings (progs_t *pr) { prstr_resources_t *res = PR_Resources_Find (pr, "Strings"); diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 8a8f2ffc0..787c9068a 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -289,6 +289,7 @@ load_progs (const char *name) return 0; PR_ResolveGlobals (&pr); + PR_LoadStrings (&pr); PR_LoadDebug (&pr); } for (i = 0; i < pr.progs->numfunctions; i++) { From 6291a3c503d5b7decfc549796e5f48462cc694f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Apr 2020 14:32:54 +0900 Subject: [PATCH 1037/3664] [qwaq] Hold the editor filename It may be an ephemeral string. --- ruamoko/qwaq/editor/editor.r | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index d66407564..8dd64c21d 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -1,4 +1,5 @@ #include +#include #include "qwaq-app.h" #include "editor/editor.h" #include "ui/listener.h" @@ -11,7 +12,7 @@ if (!(self = [super initWithRect: rect])) { return nil; } - self.filename = filename; + self.filename = str_hold (filename); buffer = [[EditBuffer withFile:filename] retain]; line_count = [buffer countLines: {0, [buffer textSize]}]; linebuffer = [[DrawBuffer buffer: { xlen, 1 }] retain]; @@ -28,6 +29,7 @@ -(void)dealloc { + str_free (filename); [vScrollBar release]; [buffer release]; [linebuffer release]; From e80344c58e320709c059748367e3bea98242267a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Apr 2020 14:34:18 +0900 Subject: [PATCH 1038/3664] [qwaq] Use full file path for loading source files --- ruamoko/qwaq/debugger/debugger.r | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 425a4f4d7..d46c78ab7 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -62,7 +62,8 @@ Rect rect = {{1, 1}, [source_window size]}; rect.extent.width -= 2; rect.extent.height -= 2; - file = [Editor withRect:rect file:filename]; + string filepath = qdb_get_file_path (target, filename); + file = [Editor withRect:rect file:filepath]; [files addObject: file]; return file; } @@ -78,7 +79,7 @@ [current_file setVerticalScrollBar:source_scrollbar]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; - [source_window setTitle: [current_file filename]]; + [source_window setTitle:[current_file filename]]; [source_window redraw]; locals_window = [Window withRect:{{0, 0}, {40, 10}}]; @@ -110,7 +111,7 @@ [file_proxy setView:file]; [[file onEvent] addListener:self :@selector(proxy_event::)]; [file setVerticalScrollBar:source_scrollbar]; - [source_window setTitle: [file filename]]; + [source_window setTitle:[file filename]]; current_file = file; } [[current_file gotoLine:state.line - 1] highlightLine]; From d88c1e2f405532a529460c935d221b28a26641e8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Apr 2020 15:46:37 +0900 Subject: [PATCH 1039/3664] [libr] Fix missing alias meta name --- ruamoko/include/types.h | 2 +- ruamoko/lib/types.r | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index a1527d890..c2f157e76 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -90,7 +90,7 @@ typedef struct qfot_type_encodings_s { int size; } qfot_type_encodings_t; -@extern string ty_meta_name[6]; +@extern string ty_meta_name[7]; @extern string pr_type_name[ev_type_count]; #endif diff --git a/ruamoko/lib/types.r b/ruamoko/lib/types.r index 66140b83f..aa1f65a02 100644 --- a/ruamoko/lib/types.r +++ b/ruamoko/lib/types.r @@ -1,13 +1,14 @@ #include #include -string ty_meta_name[6] = { +string ty_meta_name[7] = { "basic", "struct", "union", "enum", "array", "class", + "alias", }; string pr_type_name[ev_type_count] = { From d5604aef73e77839a25fd7cf68c5e895e24fb796 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Apr 2020 21:12:56 +0900 Subject: [PATCH 1040/3664] [qfcc] Add failing test for unary minus Producing a void type... very odd. --- tools/qfcc/test/Makefile.am | 11 +++++++++++ tools/qfcc/test/unaryminus.r | 13 +++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tools/qfcc/test/unaryminus.r diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am index 9c5e0799c..49ce3f51b 100644 --- a/tools/qfcc/test/Makefile.am +++ b/tools/qfcc/test/Makefile.am @@ -71,6 +71,7 @@ test_progs_dat=\ triangle.dat \ typedef.dat \ typelinker.dat \ + unaryminus.dat \ vecaddr.dat \ vecexpr.dat \ vecinit.dat \ @@ -533,6 +534,16 @@ typelinker.run: Makefile build-run include $(typelinker_dep) # am--include-marker r_depfiles_remade += $(typelinker_dep) +unaryminus_dat_SOURCES=unaryminus.r +unaryminus_obj=$(unaryminus_dat_SOURCES:.r=.qfo) +unaryminus_dep=$(addprefix ./$(DEPDIR)/,$(unaryminus_obj:.qfo=.Qo)) +unaryminus.dat$(EXEEXT): $(unaryminus_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(unaryminus_obj) +unaryminus.run: Makefile build-run + @$(srcdir)/build-run $@ +include $(unaryminus_dep) # am--include-marker +r_depfiles_remade += $(unaryminus_dep) + vecaddr_dat_SOURCES=vecaddr.r vecaddr_obj=$(vecaddr_dat_SOURCES:.r=.qfo) vecaddr_dep=$(addprefix ./$(DEPDIR)/,$(vecaddr_obj:.qfo=.Qo)) diff --git a/tools/qfcc/test/unaryminus.r b/tools/qfcc/test/unaryminus.r new file mode 100644 index 000000000..5149a224a --- /dev/null +++ b/tools/qfcc/test/unaryminus.r @@ -0,0 +1,13 @@ +int strlen (string s) = #0; + +int foo (string bar) +{ + int len; + len = -strlen (bar); + return len; +} + +int main (void) +{ + return 0; +} From 31abf6f95509c1a53285565028feed99aecd204a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Apr 2020 21:23:57 +0900 Subject: [PATCH 1041/3664] [qfcc] Fix some wrong fall-through cases This fixes the unary minus issue for now. unary_expr needs a rewrite, though: it's just horrible. --- tools/qfcc/source/expr.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 058292b1d..7faa52caf 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1636,11 +1636,25 @@ unary_expr (int op, expr_t *e) case ex_memset: internal_error (e, 0); case ex_uexpr: - if (e->e.expr.op == '-') + if (e->e.expr.op == '-') { return e->e.expr.e1; + } + { + expr_t *n = new_unary_expr (op, e); + + n->e.expr.type = get_type (e); + return n; + } case ex_block: - if (!e->e.block.result) + if (!e->e.block.result) { return error (e, "invalid type for unary -"); + } + { + expr_t *n = new_unary_expr (op, e); + + n->e.expr.type = get_type (e); + return n; + } case ex_expr: case ex_bool: case ex_temp: @@ -1648,7 +1662,7 @@ unary_expr (int op, expr_t *e) { expr_t *n = new_unary_expr (op, e); - n->e.expr.type = e->e.expr.type; + n->e.expr.type = get_type (e); return n; } case ex_def: From b7b8df08010d7626b2844d951499cabfbfd53fef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Apr 2020 21:53:53 +0900 Subject: [PATCH 1042/3664] [ruamoko] Add str_lower builtin This returns a string with all chars lower-cased. --- libs/ruamoko/rua_string.c | 18 ++++++++++++++++++ ruamoko/include/string.h | 1 + ruamoko/lib/string.r | 1 + 3 files changed, 20 insertions(+) diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 6de9c5c01..873d87717 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -38,6 +38,7 @@ # include #endif #include +#include #include "qfalloca.h" @@ -247,6 +248,22 @@ bi_str_quote (progs_t *pr) RETURN_STRING (pr, quote); } +static void +bi_str_lower (progs_t *pr) +{ + const char *str = P_GSTRING (pr, 0); + char *lower = alloca (strlen (str) + 1); + char *l = lower; + byte c; + + while ((c = *str++)) { + *l++ = tolower (c); + } + *l++ = 0; + + RETURN_STRING (pr, lower); +} + static builtin_t builtins[] = { {"strlen", bi_strlen, -1}, {"sprintf", bi_sprintf, -1}, @@ -264,6 +281,7 @@ static builtin_t builtins[] = { {"str_str", bi_str_str, -1}, {"str_char", bi_str_char, -1}, {"str_quote", bi_str_quote, -1}, + {"str_lower", bi_str_lower, -1}, {0} }; diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index 008e7d883..82abb2734 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -17,5 +17,6 @@ @extern string str_str (string haystack, string needle); @extern int str_char (string str, int ind); string str_quote (string str); +string str_lower (string str); #endif//__ruamoko_string_h diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index 48a9a7bf7..df6c6ad78 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -16,3 +16,4 @@ string (string str, int start, int len) str_mid = #0; string (string haystack, string needle) str_str = #0; int str_char (string str, int ind) = #0; string str_quote (string str) = #0; +string str_lower (string str) = #0; From 54f2e417dc38d4ad2226fe0e46358465ff8b7c06 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Apr 2020 21:54:41 +0900 Subject: [PATCH 1043/3664] [ruamoko] Fix daft str_str abi Returning a string was a bad idea as it makes str_str difficult to use with str_mid. (actually, iirc, it was the only reason I moved all strings into progs memory... hmm). --- libs/ruamoko/rua_string.c | 7 ++++--- ruamoko/cl_menu/plistmenu.r | 2 +- ruamoko/include/string.h | 2 +- ruamoko/lib/string.r | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 873d87717..31b717273 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -192,9 +192,10 @@ bi_str_str (progs_t *pr) const char *needle = P_GSTRING (pr, 1); char *res = strstr (haystack, needle); - R_STRING (pr) = 0; - if (res) - R_STRING (pr) = res - pr->pr_strings; + R_INT (pr) = -1; + if (res) { + R_INT (pr) = res - haystack; + } } static void diff --git a/ruamoko/cl_menu/plistmenu.r b/ruamoko/cl_menu/plistmenu.r index 351e974e1..f94e6bdfc 100644 --- a/ruamoko/cl_menu/plistmenu.r +++ b/ruamoko/cl_menu/plistmenu.r @@ -81,7 +81,7 @@ class_from_plist (PLDictionary *pldict) break; case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": - if (str_str (paramstr, ".")) + if (str_str (paramstr, ".") >= 0) va_list.list[j].float_val = stof (paramstr); else va_list.list[j].integer_val = stoi (paramstr); diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index 82abb2734..8087ef67e 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -14,7 +14,7 @@ @extern string str_clear (string str); @extern @overload string str_mid (string str, int start); @extern @overload string str_mid (string str, int start, int len); -@extern string str_str (string haystack, string needle); +int str_str (string haystack, string needle); @extern int str_char (string str, int ind); string str_quote (string str); string str_lower (string str); diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index df6c6ad78..3858ef7d6 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -13,7 +13,7 @@ string (string dst, string src) str_cat = #0; string (string str) str_clear = #0; string (string str, int start) str_mid = #0; string (string str, int start, int len) str_mid = #0; -string (string haystack, string needle) str_str = #0; +int str_str (string haystack, string needle) = #0; int str_char (string str, int ind) = #0; string str_quote (string str) = #0; string str_lower (string str) = #0; From 7c922d2320cd5cd930282e4912889cbd65b3376b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Apr 2020 00:24:20 +0900 Subject: [PATCH 1044/3664] Update the blender map editor for 2.80+ --- tools/io_qfmap/__init__.py | 339 +++++++--------------------------- tools/io_qfmap/entity.py | 89 +++++---- tools/io_qfmap/entityclass.py | 2 + tools/io_qfmap/import_map.py | 87 +++++---- tools/io_qfmap/init.py | 294 +++++++++++++++++++++++++++++ tools/io_qfmap/map.py | 4 +- 6 files changed, 468 insertions(+), 347 deletions(-) create mode 100644 tools/io_qfmap/init.py diff --git a/tools/io_qfmap/__init__.py b/tools/io_qfmap/__init__.py index 953750b63..2cabf517f 100644 --- a/tools/io_qfmap/__init__.py +++ b/tools/io_qfmap/__init__.py @@ -24,7 +24,7 @@ bl_info = { "name": "Quake map format", "author": "Bill Currie", - "blender": (2, 6, 3), + "blender": (2, 80, 0), "api": 35622, "location": "File > Import-Export", "description": "Import-Export Quake maps", @@ -34,286 +34,83 @@ bl_info = { # "support": 'OFFICIAL', "category": "Import-Export"} -# To support reload properly, try to access a package var, if it's there, -# reload everything -if "bpy" in locals(): - import imp - if "import_map" in locals(): - imp.reload(import_map) - if "export_map" in locals(): - imp.reload(export_map) - -from pprint import pprint +submodule_names = ( + "entity", + "entityclass", + "export_map", + "import_map", + "init", + "map", + "qfplist", + "quakechr", + "quakepal", + "wad", +) import bpy -from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty -from bpy.props import FloatVectorProperty, PointerProperty -from bpy_extras.io_utils import ExportHelper, ImportHelper, path_reference_mode, axis_conversion -from bpy.app.handlers import persistent +from bpy.props import PointerProperty +from bpy.utils import register_class, unregister_class -from .entityclass import EntityClassDict, EntityClassError -from . import entity -from . import import_map -from . import export_map +import importlib +import sys -def ecm_draw(self, context): - layout = self.layout - for item in self.menu_items: - if type(item[1]) is str: - ec = context.scene.qfmap.entity_classes[item[1]] - if ec.size: - icon = 'OBJECT_DATA' - else: - icon = 'MESH_DATA' - op = layout.operator("object.add_entity", text=item[0], icon=icon) - op.entclass=item[1] - if ec.comment: - pass - else: - layout.menu(item[1].bl_idname) +registered_submodules = [] -class EntityClassMenu: - @classmethod - def clear(cls): - while cls.menu_items: - if type(cls.menu_item[0][1]) is not str: - bpy.utils.unregister_class(cls.menu_items[0][1]) - cls.menu_items[0][1].clear() - del cls.menu_items[0] - @classmethod - def build(cls, menudict, name="INFO_MT_entity_add", label="entity"): - items = list(menudict.items()) - items.sort() - menu_items = [] - for i in items: - i = list(i) - if type(i[1]) is dict: - if i[0]: - nm = "_".join((name, i[0])) - else: - nm = name - i[1] = cls.build(i[1], nm, i[0]) - menu_items.append(i) - attrs = {} - attrs["menu_items"] = menu_items - attrs["draw"] = ecm_draw - attrs["bl_idname"] = name - attrs["bl_label"] = label - attrs["clear"] = cls.clear - menu = type(name, (bpy.types.Menu,), attrs) - bpy.utils.register_class(menu) - return menu +# When the addon is reloaded, this module gets reloaded, however none +# of the other modules from this addon get reloaded. As a result, they +# don't call register_submodules (only run when the module is loaded) and +# thus they don't end up registering everything. +# +# This is set before any loading starts (in register), to a set of all the +# names of the modules loaded as of when loading starts. While doing the +# module loading, check if a module is present in this list. If so, reload +# it and remove it from the set (to prevent it from getting reloaded twice). +preloaded_modules = None -@persistent -def scene_load_handler(dummy): - for scene in bpy.data.scenes: - if hasattr(scene, "qfmap"): - scene.qfmap.script_update(bpy.context) - -class MapeditMessage(bpy.types.Operator): - bl_idname = "qfmapedit.message" - bl_label = "Message" - type = StringProperty() - message = StringProperty() - - def execute(self, context): - self.report({'INFO'}, message) - return {'FINISHED'} - def invoke(self, context, event): - wm = context.window_manager - return wm.invoke_popup(self, width=400, height=200) - def draw(self, context): - self.layout.label(self.type, icon='ERROR') - self.layout.label(self.message) - -def scan_entity_classes(context): - qfmap = context.scene.qfmap - if not qfmap.dirpath: - return - qfmap.entity_classes.from_source_tree(qfmap.dirpath) - name = context.scene.name + '-EntityClasses' - if name in bpy.data.texts: - txt = bpy.data.texts[name] - else: - txt = bpy.data.texts.new(name) - txt.from_string(qfmap.entity_classes.to_plist()) - qfmap.script = name - -def parse_entity_classes(context): - context.scene.qfmap.script_update(context) - -def ec_dir_update(self, context): - try: - scan_entity_classes(context) - except EntityClassError as err: - self.dirpath = "" - bpy.ops.qfmapedit.message('INVOKE_DEFAULT', type="Error", - message="Entity Class Error: %s" % err) - -def ec_script_update(self, context): - self.script_update(context) - -class AddEntity(bpy.types.Operator): - '''Add an entity''' - bl_idname = "object.add_entity" - bl_label = "Entity" - entclass = StringProperty(name = "entclass") - - def execute(self, context): - keywords = self.as_keywords() - return entity.add_entity(self, context, **keywords) - -class QFEntityClassScan(bpy.types.Operator): - '''Rescan the specified QuakeC source tree''' - bl_idname = "scene.scan_entity_classes" - bl_label = "RELOAD" - - def execute(self, context): - scan_entity_classes(context) - return {'FINISHED'} - -class QFEntityClassParse(bpy.types.Operator): - '''Reparse the specified entity class script''' - bl_idname = "scene.parse_entity_classes" - bl_label = "RELOAD" - - def execute(self, context): - parse_entity_classes(context) - return {'FINISHED'} - -class QFEntityClasses(bpy.types.PropertyGroup): - wadpath = StringProperty( - name="wadpath", - description="Path to search for wad files", - subtype='DIR_PATH') - dirpath = StringProperty( - name="dirpath", - description="Path to qc source tree", - subtype='DIR_PATH', - update=ec_dir_update) - script = StringProperty( - name="script", - description="entity class storage", - update=ec_script_update) - entity_classes = EntityClassDict() - ecm = EntityClassMenu.build({}) - entity_targets = {} - target_entities = [] - - def script_update(self, context): - if self.script in bpy.data.texts: - script = bpy.data.texts[self.script].as_string() - self.entity_classes.from_plist(script) - menudict = {} - entclasses = self.entity_classes.keys() - for ec in entclasses: - ecsub = ec.split("_") - d = menudict - for sub in ecsub[:-1]: - if sub not in d: - d[sub] = {} - elif type(d[sub]) is str: - d[sub] = {"":d[sub]} - d = d[sub] - sub = ecsub[-1] - if sub in d: - d[sub][""] = ec - else: - d[sub] = ec - self.__class__.ecm = EntityClassMenu.build(menudict) - -class OBJECT_PT_QFECPanel(bpy.types.Panel): - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = 'scene' - bl_label = 'QF Entity Classes' - - @classmethod - def poll(cls, context): - return True - - def draw(self, context): - layout = self.layout - scene = context.scene - row = layout.row() - layout.prop(scene.qfmap, "wadpath") - row = layout.row() - row.prop(scene.qfmap, "dirpath") - row.operator("scene.scan_entity_classes", text="", icon="FILE_REFRESH") - row = layout.row() - row.prop(scene.qfmap, "script") - row.operator("scene.parse_entity_classes", text="", icon="FILE_REFRESH") - -class ImportPoints(bpy.types.Operator, ImportHelper): - '''Load a Quake points File''' - bl_idname = "import_mesh.quake_points" - bl_label = "Import points" - - filename_ext = ".pts" - filter_glob = StringProperty(default="*.pts", options={'HIDDEN'}) - - def execute(self, context): - keywords = self.as_keywords (ignore=("filter_glob",)) - return import_map.import_pts(self, context, **keywords) - -class ImportMap(bpy.types.Operator, ImportHelper): - '''Load a Quake map File''' - bl_idname = "import_mesh.quake_map" - bl_label = "Import map" - - filename_ext = ".map" - filter_glob = StringProperty(default="*.map", options={'HIDDEN'}) - - def execute(self, context): - keywords = self.as_keywords (ignore=("filter_glob",)) - return import_map.import_map(self, context, **keywords) - -class ExportMap(bpy.types.Operator, ExportHelper): - '''Save a Quake map File''' - - bl_idname = "export_mesh.quake_map" - bl_label = "Export map" - - filename_ext = ".map" - filter_glob = StringProperty(default="*.map", options={'HIDDEN'}) - - @classmethod - def poll(cls, context): - return True - - def execute(self, context): - keywords = self.as_keywords (ignore=("check_existing", "filter_glob")) - return export_map.export_map(self, context, **keywords) - -def menu_func_import(self, context): - self.layout.operator(ImportMap.bl_idname, text="Quake map (.map)") - self.layout.operator(ImportPoints.bl_idname, text="Quake points (.pts)") - -def menu_func_export(self, context): - self.layout.operator(ExportMap.bl_idname, text="Quake map (.map)") - -def menu_func_add(self, context): - self.layout.menu(context.scene.qfmap.ecm.bl_idname, icon='PLUGIN') +def register_submodules(name, submodule_names): + global preloaded_modules + module = __import__(name=name, fromlist=submodule_names) + submodules = [getattr(module, name) for name in submodule_names] + for mod in submodules: + # Look through the modules present when register was called. If this + # module was already loaded, then reload it. + if mod.__name__ in preloaded_modules: + mod = importlib.reload(mod) + # Prevent the module from getting reloaded more than once + preloaded_modules.remove(mod.__name__) + m = [(),(),()] + if hasattr(mod, "classes_to_register"): + m[0] = mod.classes_to_register + for cls in mod.classes_to_register: + register_class(cls) + if hasattr(mod, "menus_to_register"): + m[1] = mod.menus_to_register + for menu in mod.menus_to_register: + menu[0].append(menu[1]) + if hasattr(mod, "custom_properties_to_register"): + for prop in mod.custom_properties_to_register: + setattr(prop[0], prop[1], PointerProperty(type=prop[2])) + if hasattr(mod, "handlers_to_register"): + m[2] = mod.handlers_to_register + for handler in mod.handlers_to_register: + getattr(bpy.app.handlers, handler[0]).append(handler[1]) + if m[0] or m[1] or m[2]: + registered_submodules.append(m) def register(): - bpy.utils.register_module(__name__) - - bpy.types.Scene.qfmap = PointerProperty(type=QFEntityClasses) - - bpy.types.INFO_MT_file_import.append(menu_func_import) - bpy.types.INFO_MT_file_export.append(menu_func_export) - bpy.types.INFO_MT_add.append(menu_func_add) - - bpy.app.handlers.load_post.append(scene_load_handler) - entity.register() - + global preloaded_modules + preloaded_modules = set(sys.modules.keys()) + register_submodules(__name__, submodule_names) + preloaded_modules = None def unregister(): - bpy.utils.unregister_module(__name__) - - bpy.types.INFO_MT_file_import.remove(menu_func_import) - bpy.types.INFO_MT_file_export.remove(menu_func_export) - bpy.types.INFO_MT_add.remove(menu_func_add) + for mod in reversed(registered_submodules): + for handler in reversed(mod[2]): + getattr(bpy.app.handlers, handler[0]).remove(handler[1]) + for menu in reversed(mod[1]): + menu[0].remove(menu[1]) + for cls in reversed(mod[0]): + unregister_class(cls) if __name__ == "__main__": register() diff --git a/tools/io_qfmap/entity.py b/tools/io_qfmap/entity.py index 23f151f7e..86a316234 100644 --- a/tools/io_qfmap/entity.py +++ b/tools/io_qfmap/entity.py @@ -19,7 +19,8 @@ # -import bpy, bgl +import bpy, bgl, gpu +from gpu_extras.batch import batch_for_shader from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty from bpy.props import BoolVectorProperty, CollectionProperty, PointerProperty from bpy.props import FloatVectorProperty, IntProperty @@ -27,7 +28,8 @@ from mathutils import Vector from .entityclass import EntityClass -def draw_callback(self, context): + +def build_batch(qfmap): def obj_location(obj): ec = None if obj.qfentity.classname in entity_classes: @@ -38,13 +40,13 @@ def draw_callback(self, context): for i in range(8): loc += Vector(obj.bound_box[i]) return obj.location + loc/8.0 - qfmap = context.scene.qfmap entity_classes = qfmap.entity_classes entity_targets = qfmap.entity_targets target_entities = qfmap.target_entities - bgl.glLineWidth(3) ents = 0 targs = 0 + verts = [] + colors = [] for obj in target_entities: #obj = bpy.data.objects[objname] qfentity = obj.qfentity @@ -54,27 +56,37 @@ def draw_callback(self, context): ec = entity_classes[qfentity.classname] target = None killtarget = None - for field in qfentity.fields: - if field.name == "target" and field.value: - target = field.value - if field.name == "killtarget" and field.value: - killtarget = field.value + if "target" in qfentity.fields: + target = qfentity.fields["target"].value + if "killtarget" in qfentity.fields: + killtarget = qfentity.fields["killtarget"].value targetlist = [target, killtarget] if target == killtarget: del targetlist[1] for tname in targetlist: if tname and tname in entity_targets: targets = entity_targets[tname] - bgl.glColor4f(ec.color[0], ec.color[1], ec.color[2], 1) + color = (ec.color[0], ec.color[1], ec.color[2], 1) for ton in targets: targs += 1 to = bpy.data.objects[ton] - bgl.glBegin(bgl.GL_LINE_STRIP) - loc = obj_location(obj) - bgl.glVertex3f(loc.x, loc.y, loc.z) - loc = obj_location(to) - bgl.glVertex3f(loc.x, loc.y, loc.z) - bgl.glEnd() + start = obj_location(obj) + end = obj_location(to) + + verts.append(start) + colors.append(color) + verts.append(end) + colors.append(color) + return {"pos": verts, "color": colors} + +def draw_callback(self, context): + #FIXME horribly inefficient + qfmap = context.scene.qfmap + content = build_batch(qfmap) + shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR') + batch = batch_for_shader(shader, 'LINES', content) + bgl.glLineWidth(3) + batch.draw(shader) bgl.glLineWidth(1) class VIEW3D_PT_QFEntityRelations(bpy.types.Panel): @@ -103,27 +115,27 @@ class VIEW3D_PT_QFEntityRelations(bpy.types.Panel): class OBJECT_UL_EntityField_list(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): - layout.label(item.name) - layout.label(item.value) + layout.label(text=item.name) + layout.label(text=item.value) def qfentity_items(self, context): qfmap = context.scene.qfmap entclasses = qfmap.entity_classes eclist = list(entclasses.keys()) eclist.sort() - enum = (('', "--", ""),) + enum = (('.', "--", ""),) enum += tuple(map(lambda ec: (ec, ec, ""), eclist)) return enum class QFEntityProp(bpy.types.PropertyGroup): - value = StringProperty(name="") - template_list_controls = StringProperty(default="value", options={'HIDDEN'}) + value: StringProperty(name="") + template_list_controls: StringProperty(default="value", options={'HIDDEN'}) class QFEntity(bpy.types.PropertyGroup): - classname = EnumProperty(items = qfentity_items, name = "Entity Class") - flags = BoolVectorProperty(size=12) - fields = CollectionProperty(type=QFEntityProp, name="Fields") - field_idx = IntProperty() + classname: EnumProperty(items = qfentity_items, name = "Entity Class") + flags: BoolVectorProperty(size=12) + fields: CollectionProperty(type=QFEntityProp, name="Fields") + field_idx: IntProperty() class QFEntpropAdd(bpy.types.Operator): '''Add an entity field/value pair''' @@ -188,7 +200,7 @@ class OBJECT_PT_EntityPanel(bpy.types.Panel): box=layout.box() lines = reflow_text(ec.comment, 40) for l in lines: - box.label(l) + box.label(text=l) row = layout.row() for c in range(3): col = row.column() @@ -201,8 +213,8 @@ class OBJECT_PT_EntityPanel(bpy.types.Panel): col.template_list("OBJECT_UL_EntityField_list", "", qfentity, "fields", qfentity, "field_idx", rows=3) col = row.column(align=True) - col.operator("object.entprop_add", icon='ZOOMIN', text="") - col.operator("object.entprop_remove", icon='ZOOMOUT', text="") + col.operator("object.entprop_add", icon='ADD', text="") + col.operator("object.entprop_remove", icon='REMOVE', text="") if len(qfentity.fields) > qfentity.field_idx >= 0: row = layout.row() field = qfentity.fields[qfentity.field_idx] @@ -246,8 +258,7 @@ def entity_box(entityclass): mesh = bpy.data.meshes.new(name) mesh.from_pydata(verts, [], faces) mat = bpy.data.materials.new(name) - mat.diffuse_color = color - mat.use_raytrace = False + mat.diffuse_color = color + (1,) mesh.materials.append(mat) return mesh @@ -258,7 +269,7 @@ def set_entity_props(obj, ent): qfe.classname = ent.d["classname"] except TypeError: #FIXME hmm, maybe an enum wasn't the most brilliant idea? - qfe.classname + qfe.classname = '' if "spawnflags" in ent.d: flags = int(float(ent.d["spawnflags"])) for i in range(12): @@ -296,5 +307,17 @@ def add_entity(self, context, entclass): context.user_preferences.edit.use_global_undo = True return {'FINISHED'} -def register(): - bpy.types.Object.qfentity = PointerProperty(type=QFEntity) +classes_to_register = ( + VIEW3D_PT_QFEntityRelations, + OBJECT_UL_EntityField_list, + QFEntityProp, + QFEntity, + QFEntpropAdd, + QFEntpropRemove, + OBJECT_PT_EntityPanel, +) +menus_to_register = ( +) +custom_properties_to_register = ( + (bpy.types.Object, "qfentity", QFEntity), +) diff --git a/tools/io_qfmap/entityclass.py b/tools/io_qfmap/entityclass.py index f659c5d53..c7b9cbd0e 100644 --- a/tools/io_qfmap/entityclass.py +++ b/tools/io_qfmap/entityclass.py @@ -140,6 +140,8 @@ class EntityClassDict: def __len__(self): return self.entity_classes.__len__() def __getitem__(self, key): + if key == '.': + return EntityClass.null() return self.entity_classes.__getitem__(key) def __iter__(self): return self.entity_classes.__iter__() diff --git a/tools/io_qfmap/import_map.py b/tools/io_qfmap/import_map.py index 7d22912a0..c247d4920 100644 --- a/tools/io_qfmap/import_map.py +++ b/tools/io_qfmap/import_map.py @@ -61,9 +61,8 @@ def load_material(tx): if tx.name in bpy.data.materials: return bpy.data.materials[tx.name] mat = bpy.data.materials.new(tx.name) - mat.diffuse_color = (1, 1, 1) + mat.diffuse_color = (1, 1, 1, 1) mat.specular_intensity = 0 - mat.use_raytrace = False if tx.image: tex = bpy.data.textures.new(tx.name, 'IMAGE') tex.extension = 'REPEAT' @@ -77,19 +76,23 @@ def load_material(tx): return mat def load_textures(texdefs, wads): + class MT: + def __init__(self, x, y): + self.width = x + self.height = y for tx in texdefs: if hasattr(tx, "miptex"): continue - try: - tx.miptex = wads[0].getData(tx.name) - tx.image = load_image(tx) - except KeyError: - class MT: - def __init__(self, x, y): - self.width = x - self.height = y + if not wads or not wads[0]: tx.miptex = MT(64,64) tx.image = None + else: + try: + tx.miptex = wads[0].getData(tx.name) + tx.image = load_image(tx) + except KeyError: + tx.miptex = MT(64,64) + tx.image = None tx.material = load_material(tx) def build_uvs(verts, faces, texdefs): @@ -110,7 +113,7 @@ def process_entity(ent, wads): classname = ent.d["classname"] name = classname if "classname" in ent.d and ent.d["classname"][:5] == "light": - light = bpy.data.lamps.new("light", 'POINT') + light = bpy.data.lights.new("light", 'POINT') if "light" in ent.d: light.distance = float(ent.d["light"]) elif "_light" in ent.d: @@ -150,7 +153,7 @@ def process_entity(ent, wads): tx.matindex = len(mesh.materials) mesh.materials.append(tx.material) mesh.from_pydata(verts, [], faces) - uvlay = mesh.uv_textures.new(name) + """uvlay = mesh.uv_textures.new(name) uvloop = mesh.uv_layers[0] for i, texpoly in enumerate(uvlay.data): poly = mesh.polygons[i] @@ -159,7 +162,7 @@ def process_entity(ent, wads): texpoly.image = tx.image poly.material_index = tx.matindex for j, k in enumerate(poly.loop_indices): - uvloop.data[k].uv = uv[j] + uvloop.data[k].uv = uv[j]"""#FIXME mesh.update() obj = bpy.data.objects.new(name, mesh) else: @@ -189,50 +192,52 @@ def process_entity(ent, wads): del ent.d["angles"] obj.rotation_mode = 'XZY' obj.rotation_euler = angles * pi / 180 - bpy.context.scene.objects.link(obj) - bpy.context.scene.objects.active=obj - obj.select = True + bpy.context.layer_collection.collection.objects.link(obj) + bpy.context.view_layer.objects.active = obj + obj.select_set(True) set_entity_props(obj, ent) def import_map(operator, context, filepath): - bpy.context.user_preferences.edit.use_global_undo = False - - for obj in bpy.context.scene.objects: - obj.select = False + undo = bpy.context.preferences.edit.use_global_undo + bpy.context.preferences.edit.use_global_undo = False try: + for obj in bpy.context.scene.objects: + obj.select_set(False) entities = parse_map (filepath) except MapError as err: operator.report({'ERROR'}, repr(err)) return {'CANCELLED'} - wads=[] - if entities: - if "_wad" in entities[0].d: - wads = entities[0].d["_wad"].split(";") - elif "wad" in entities[0].d: - wads = entities[0].d["wad"].split(";") - wadpath = bpy.context.scene.qfmap.wadpath - for i in range(len(wads)): - try: - wads[i] = WadFile.load(os.path.join(wadpath, wads[i])) - except IOError: + else: + wads=[] + if entities: + if "_wad" in entities[0].d: + wads = entities[0].d["_wad"].split(";") + elif "wad" in entities[0].d: + wads = entities[0].d["wad"].split(";") + wadpath = bpy.context.scene.qfmap.wadpath + for i in range(len(wads)): try: - wads[i] = WadFile.load(os.path.join(wadpath, - os.path.basename(wads[i]))) + wads[i] = WadFile.load(os.path.join(wadpath, wads[i])) except IOError: - #give up - operator.report({'INFO'}, "Cant't find %s" % wads[i]) - wads[i] = None - for ent in entities: - process_entity(ent, wads) - bpy.context.user_preferences.edit.use_global_undo = True + try: + wads[i] = WadFile.load(os.path.join(wadpath, + os.path.basename(wads[i]))) + except IOError: + #give up + operator.report({'INFO'}, "Cant't find %s" % wads[i]) + wads[i] = None + for ent in entities: + process_entity(ent, wads) + finally: + bpy.context.preferences.edit.use_global_undo = undo return {'FINISHED'} def import_pts(operator, context, filepath): bpy.context.user_preferences.edit.use_global_undo = False for obj in bpy.context.scene.objects: - obj.select = False + obj.select_set(False) lines = open(filepath, "rt").readlines() verts = [None] * len(lines) @@ -248,6 +253,6 @@ def import_pts(operator, context, filepath): obj = bpy.data.objects.new("leak points", mesh) bpy.context.scene.objects.link(obj) bpy.context.scene.objects.active=obj - obj.select = True + obj.select_set(True) bpy.context.user_preferences.edit.use_global_undo = True return {'FINISHED'} diff --git a/tools/io_qfmap/init.py b/tools/io_qfmap/init.py new file mode 100644 index 000000000..199bb71fa --- /dev/null +++ b/tools/io_qfmap/init.py @@ -0,0 +1,294 @@ +# vim:ts=4:et +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# 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 2 +# 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, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# + +import bpy +from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty +from bpy.props import FloatVectorProperty, PointerProperty +from bpy_extras.io_utils import ExportHelper, ImportHelper, path_reference_mode, axis_conversion +from bpy.app.handlers import persistent + +from .entityclass import EntityClassDict, EntityClassError +from . import entity +from . import import_map +from . import export_map + +def ecm_draw(self, context): + layout = self.layout + for item in self.menu_items: + if type(item[1]) is str: + ec = context.scene.qfmap.entity_classes[item[1]] + if ec.size: + icon = 'OBJECT_DATA' + else: + icon = 'MESH_DATA' + op = layout.operator("object.add_entity", text=item[0], icon=icon) + op.entclass=item[1] + if ec.comment: + pass + else: + layout.menu(item[1].bl_idname) + +class EntityClassMenu: + @classmethod + def clear(cls): + while cls.menu_items: + if type(cls.menu_item[0][1]) is not str: + bpy.utils.unregister_class(cls.menu_items[0][1]) + cls.menu_items[0][1].clear() + del cls.menu_items[0] + @classmethod + def build(cls, menudict, name="INFO_MT_entity_add", label="entity"): + items = list(menudict.items()) + items.sort() + menu_items = [] + for i in items: + i = list(i) + if type(i[1]) is dict: + if i[0]: + nm = "_".join((name, i[0])) + else: + nm = name + i[1] = cls.build(i[1], nm, i[0]) + menu_items.append(i) + attrs = {} + attrs["menu_items"] = menu_items + attrs["draw"] = ecm_draw + attrs["bl_idname"] = name + attrs["bl_label"] = label + attrs["clear"] = cls.clear + menu = type(name, (bpy.types.Menu,), attrs) + bpy.utils.register_class(menu) + return menu + +@persistent +def scene_load_handler(dummy): + for scene in bpy.data.scenes: + if hasattr(scene, "qfmap"): + scene.qfmap.script_update(bpy.context) + +class MapeditMessage(bpy.types.Operator): + bl_idname = "qfmapedit.message" + bl_label = "Message" + type: StringProperty() + message: StringProperty() + + def execute(self, context): + self.report({'INFO'}, message) + return {'FINISHED'} + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_popup(self, width=400, height=200) + def draw(self, context): + self.layout.label(self.type, icon='ERROR') + self.layout.label(self.message) + +def scan_entity_classes(context): + qfmap = context.scene.qfmap + if not qfmap.dirpath: + return + qfmap.entity_classes.from_source_tree(qfmap.dirpath) + name = context.scene.name + '-EntityClasses' + if name in bpy.data.texts: + txt = bpy.data.texts[name] + else: + txt = bpy.data.texts.new(name) + txt.from_string(qfmap.entity_classes.to_plist()) + qfmap.script = name + +def parse_entity_classes(context): + context.scene.qfmap.script_update(context) + +def ec_dir_update(self, context): + try: + scan_entity_classes(context) + except EntityClassError as err: + self.dirpath = "" + bpy.ops.qfmapedit.message('INVOKE_DEFAULT', type="Error", + message="Entity Class Error: %s" % err) + +def ec_script_update(self, context): + self.script_update(context) + +class AddEntity(bpy.types.Operator): + '''Add an entity''' + bl_idname = "object.add_entity" + bl_label = "Entity" + entclass: StringProperty(name = "entclass") + + def execute(self, context): + keywords = self.as_keywords() + return entity.add_entity(self, context, **keywords) + +class QFEntityClassScan(bpy.types.Operator): + '''Rescan the specified QuakeC source tree''' + bl_idname = "scene.scan_entity_classes" + bl_label = "RELOAD" + + def execute(self, context): + scan_entity_classes(context) + return {'FINISHED'} + +class QFEntityClassParse(bpy.types.Operator): + '''Reparse the specified entity class script''' + bl_idname = "scene.parse_entity_classes" + bl_label = "RELOAD" + + def execute(self, context): + parse_entity_classes(context) + return {'FINISHED'} + +class QFEntityClasses(bpy.types.PropertyGroup): + wadpath: StringProperty( + name="wadpath", + description="Path to search for wad files", + subtype='DIR_PATH') + dirpath: StringProperty( + name="dirpath", + description="Path to qc source tree", + subtype='DIR_PATH', + update=ec_dir_update) + script: StringProperty( + name="script", + description="entity class storage", + update=ec_script_update) + entity_classes = EntityClassDict() + ecm = EntityClassMenu.build({}) + entity_targets = {} + target_entities = [] + + def script_update(self, context): + if self.script in bpy.data.texts: + script = bpy.data.texts[self.script].as_string() + self.entity_classes.from_plist(script) + menudict = {} + entclasses = self.entity_classes.keys() + for ec in entclasses: + ecsub = ec.split("_") + d = menudict + for sub in ecsub[:-1]: + if sub not in d: + d[sub] = {} + elif type(d[sub]) is str: + d[sub] = {"":d[sub]} + d = d[sub] + sub = ecsub[-1] + if sub in d: + d[sub][""] = ec + else: + d[sub] = ec + self.__class__.ecm = EntityClassMenu.build(menudict) + +class OBJECT_PT_QFECPanel(bpy.types.Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'UI' + #bl_context = 'scene' + bl_category = "View" + bl_label = 'QF Entity Classes' + + @classmethod + def poll(cls, context): + return True + + def draw(self, context): + layout = self.layout + scene = context.scene + row = layout.row() + layout.prop(scene.qfmap, "wadpath") + row = layout.row() + row.prop(scene.qfmap, "dirpath") + row.operator("scene.scan_entity_classes", text="", icon="FILE_REFRESH") + row = layout.row() + row.prop(scene.qfmap, "script") + row.operator("scene.parse_entity_classes", text="", icon="FILE_REFRESH") + +class ImportPoints(bpy.types.Operator, ImportHelper): + '''Load a Quake points File''' + bl_idname = "import_mesh.quake_points" + bl_label = "Import points" + + filename_ext = ".pts" + filter_glob: StringProperty(default="*.pts", options={'HIDDEN'}) + + def execute(self, context): + keywords = self.as_keywords (ignore=("filter_glob",)) + return import_map.import_pts(self, context, **keywords) + +class ImportMap(bpy.types.Operator, ImportHelper): + '''Load a Quake map File''' + bl_idname = "import_mesh.quake_map" + bl_label = "Import map" + + filename_ext = ".map" + filter_glob: StringProperty(default="*.map", options={'HIDDEN'}) + + def execute(self, context): + keywords = self.as_keywords (ignore=("filter_glob",)) + return import_map.import_map(self, context, **keywords) + +class ExportMap(bpy.types.Operator, ExportHelper): + '''Save a Quake map File''' + + bl_idname = "export_mesh.quake_map" + bl_label = "Export map" + + filename_ext = ".map" + filter_glob: StringProperty(default="*.map", options={'HIDDEN'}) + + @classmethod + def poll(cls, context): + return True + + def execute(self, context): + keywords = self.as_keywords (ignore=("check_existing", "filter_glob")) + return export_map.export_map(self, context, **keywords) + +def menu_func_import(self, context): + self.layout.operator(ImportMap.bl_idname, text="Quake map (.map)") + self.layout.operator(ImportPoints.bl_idname, text="Quake points (.pts)") + +def menu_func_export(self, context): + self.layout.operator(ExportMap.bl_idname, text="Quake map (.map)") + +def menu_func_add(self, context): + self.layout.menu(context.scene.qfmap.ecm.bl_idname, icon='PLUGIN') + +classes_to_register = ( + MapeditMessage, + AddEntity, + QFEntityClassScan, + QFEntityClassParse, + QFEntityClasses, + OBJECT_PT_QFECPanel, + ImportPoints, + ImportMap, + ExportMap, +) +menus_to_register = ( + (bpy.types.TOPBAR_MT_file_import, menu_func_import), + (bpy.types.TOPBAR_MT_file_export, menu_func_export), + (bpy.types.VIEW3D_MT_add, menu_func_add), +) +custom_properties_to_register = ( + (bpy.types.Scene, "qfmap", QFEntityClasses), +) +handlers_to_register = ( + ("load_post", scene_load_handler), +) diff --git a/tools/io_qfmap/map.py b/tools/io_qfmap/map.py index b0820de69..e47b7563a 100644 --- a/tools/io_qfmap/map.py +++ b/tools/io_qfmap/map.py @@ -38,8 +38,8 @@ class Texinfo: norm = s_vec.cross(t_vec) q = Quaternion(norm, rotate * pi / 180) self.vecs = [None] * 2 - self.vecs[0] = (q * s_vec / scale[0], s_offs) - self.vecs[1] = (q * t_vec / scale[1], t_offs) + self.vecs[0] = (q @ s_vec / scale[0], s_offs) + self.vecs[1] = (q @ t_vec / scale[1], t_offs) def __cmp__(self, other): return self.name == other.name and self.vecs == other.vecs @classmethod From 7ae047654bb70af4e2c3f8b7f2e661eaf5c5adf8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Jun 2020 17:07:54 +0900 Subject: [PATCH 1045/3664] [util] Rework SEB affine/convex testing When I ported SEB to python, I discovered that I apparently didn't really understand the paper's description of the end condition and the usage of the affine and convex sets for center testing. This cleans up the test and makes SEB more correct for the cases that have less than 4 supporting points (especially when there are less than 4 points total). --- libs/util/mathlib.c | 117 +++++++++++++++++++++++++++----------- libs/util/test/test-seb.c | 2 +- 2 files changed, 84 insertions(+), 35 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index db68455f3..0ca7ae1b7 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -1259,7 +1259,6 @@ circum_circle (const vec_t **points, int num_points, sphere_t *sphere) VectorMultAdd (sphere->center, bb, ca, sphere->center); VectorMultAdd (sphere->center, cc, ab, sphere->center); VectorAdd (sphere->center, points[0], sphere->center); - sphere->radius = VectorDistance (sphere->center, points[0]); return 1; } return 0; @@ -1286,8 +1285,8 @@ CircumSphere (const vec3_t points[], int num_points, sphere_t *sphere) } static void -closest_point (const vec_t **points, int num_points, const vec3_t x, - vec3_t closest) +closest_affine_point (const vec_t **points, int num_points, const vec3_t x, + vec3_t closest) { vec3_t a, b, n, d; vec_t l; @@ -1314,6 +1313,74 @@ closest_point (const vec_t **points, int num_points, const vec3_t x, } } +static int +test_support_points(const vec_t **points, int *num_points, const vec3_t center) +{ + int in_affine = 0; + int in_convex = 0; + vec3_t v, d, n, a, b; + vec_t nn, dd, vv, dn; + + switch (*num_points) { + case 1: + in_affine = VectorCompare (points[0], center); + // the convex hull and affine hull for a single point are the same + in_convex = in_affine; + break; + case 2: + VectorSubtract (points[1], points[0], v); + VectorSubtract (center, points[0], d); + CrossProduct (v, d, n); + nn = DotProduct (n, n); + dd = DotProduct (d, d); + vv = DotProduct (v, v); + in_affine = nn < 1e-8 * vv * dd; + break; + case 3: + VectorSubtract (points[1], points[0], a); + VectorSubtract (points[2], points[0], b); + VectorSubtract (center, points[0], d); + CrossProduct (a, b, n); + dn = DotProduct (d, n); + dd = DotProduct (d, d); + nn = DotProduct (n, n); + in_affine = dn * dn < 1e-8 * dd * nn; + break; + case 4: + in_affine = 1; + break; + default: + Sys_Error ("Invalid number of points (%d) in test_support_points", + *num_points); + } + + // if in_convex is not true while in_affine is, then need to test as + // there is more than one dimension for the affine hull (a single support + // point is never dropped as it cannot be redundant) + if (in_affine && !in_convex) { + vec_t lambda[4]; + int dropped = 0; + int count = *num_points; + + BarycentricCoords (points, count, center, lambda); + + for (int i = 0; i < count; i++) { + points[i - dropped] = points[i]; + if (lambda[i] < -1e-4) { + dropped++; + (*num_points)--; + } + } + in_convex = !dropped; + if (dropped) { + for (int i = count - dropped; i < count; i++) { + points[i] = 0; + } + } + } + return in_convex; +} + sphere_t SmallestEnclosingBall (const vec3_t points[], int num_points) { @@ -1323,10 +1390,11 @@ SmallestEnclosingBall (const vec3_t points[], int num_points) int num_support; vec_t dist, best_dist; int i; - int itters = 0; + int iters = 0; - if (num_points < 3) { - CircumSphere (points, num_points, &sphere); + if (num_points < 1) { + VectorZero (sphere.center); + sphere.radius = 0; return sphere; } @@ -1335,7 +1403,7 @@ SmallestEnclosingBall (const vec3_t points[], int num_points) VectorCopy (points[0], sphere.center); best_dist = dist = 0; - best = 0; + best = points[0]; for (i = 1; i < num_points; i++) { dist = VectorDistance_fast (points[i], sphere.center); if (dist > best_dist) { @@ -1347,41 +1415,22 @@ SmallestEnclosingBall (const vec3_t points[], int num_points) support[0] = best; sphere.radius = best_dist; // note: radius squared until the end - while (1) { + while (!test_support_points (support, &num_support, sphere.center)) { vec3_t affine; vec3_t center_to_affine, center_to_point; vec_t affine_dist, point_proj, point_dist, bound; vec_t scale = 1; int i; - if (itters++ > 10) + if (iters++ > 10) Sys_Error ("stuck SEB"); best = 0; - if (num_support == 4) { - vec_t lambda[4]; - int dropped = 0; - - BarycentricCoords (support, 4, sphere.center, lambda); - for (i = 0; i < 4; i++) { - support[i - dropped] = support[i]; - if (lambda[i] < 0) { - dropped++; - num_support--; - } - } - if (!dropped) - break; - for (i = 4 - dropped; i < 4; i++) - support[i] = 0; - } - closest_point (support, num_support, sphere.center, affine); + closest_affine_point (support, num_support, sphere.center, affine); VectorSubtract (affine, sphere.center, center_to_affine); affine_dist = DotProduct (center_to_affine, center_to_affine); - if (affine_dist < 1e-2 * sphere.radius) - break; for (i = 0; i < num_points; i++) { - if (points[i] == support [0] || points[i] == support[1] + if (points[i] == support[0] || points[i] == support[1] || points[i] == support[2]) continue; VectorSubtract (points[i], sphere.center, center_to_point); @@ -1399,10 +1448,10 @@ SmallestEnclosingBall (const vec3_t points[], int num_points) } } VectorMultAdd (sphere.center, scale, center_to_affine, sphere.center); - if (!best) - break; - sphere.radius = VectorDistance_fast (sphere.center, best); - support[num_support++] = best; + sphere.radius = VectorDistance_fast (sphere.center, support[0]); + if (best) { + support[num_support++] = best; + } } best_dist = 0; for (i = 0; i < num_points; i++) { diff --git a/libs/util/test/test-seb.c b/libs/util/test/test-seb.c index 801e1ff88..d5e900972 100644 --- a/libs/util/test/test-seb.c +++ b/libs/util/test/test-seb.c @@ -96,7 +96,7 @@ main (int argc, const char **argv) } } end = Sys_DoubleTime (); - printf ("%d itterations in %gs: %g itters/second\n", (int) i, end - start, + printf ("%d iterations in %gs: %g iters/second\n", (int) i, end - start, i / (end - start)); return res; } From df89e37afc1e38679edb73747ef8a771be385d1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 Jun 2020 22:47:12 +0900 Subject: [PATCH 1046/3664] [console] Call PR_RunPostLoadFuncs This fixes the segfault when loading the menu progs. I had forgotten that the menu code doesn't use PR_LoadProgs (I don't remember why. Obsolete reason?). --- libs/console/menu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/console/menu.c b/libs/console/menu.c index 90eaeca75..d1a5e9c76 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -628,7 +628,8 @@ Menu_Load (void) PR_LoadProgsFile (&menu_pr_state, file, size); Qclose (file); - if (!PR_RunLoadFuncs (&menu_pr_state)) { + if (!PR_RunLoadFuncs (&menu_pr_state) + || !PR_RunPostLoadFuncs (&menu_pr_state)) { free (menu_pr_state.progs); menu_pr_state.progs = 0; } From 6d5ffa9f8e8daf04b560036d833f24acb332d123 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Jun 2020 23:15:17 +0900 Subject: [PATCH 1047/3664] [build] Move to non-recursive make There's still some cleanup to do, but everything seems to be working nicely: `make -j` works, `make distcheck` passes. There is probably plenty of bitrot in the package directories (RPM, debian), though. The vc project files have been removed since those versions are way out of date and quakeforge is pretty much dependent on gcc now anyway. Most of the old Makefile.am files are now Makemodule.am. This should allow for new Makefile.am files that allow local building (to be added on an as-needed bases). The current remaining Makefile.am files are for standalone sub-projects.a The installable bins are currently built in the top-level build directory. This may change if the clutter gets to be too much. While this does make a noticeable difference in build times, the main reason for the switch was to take care of the growing dependency issues: now it's possible to build tools for code generation (eg, using qfcc and ruamoko programs for code-gen). --- Makefile.am | 113 +- RPM/Makefile.am | 9 - RPM/Makemodule.am | 6 + bootstrap | 2 +- config.d/ac_config_files.m4 | 98 -- config.d/build_control.m4 | 90 +- config.d/rpm.m4 | 2 +- configure.ac | 2 +- debian/Makefile.am | 23 - debian/Makemodule.am | 28 + desktop/Makefile.am | 49 - desktop/Makemodule.am | 10 + desktop/quakeforge-nq-glx.desktop | 18 - desktop/quakeforge-nq-sdl32.desktop | 18 - desktop/quakeforge-nq-sgl.desktop | 18 - desktop/quakeforge-qw-glx.desktop | 18 - desktop/quakeforge-qw-sdl32.desktop | 18 - desktop/quakeforge-qw-sgl.desktop | 18 - doc/Makefile.am | 55 - doc/Makemodule.am | 80 ++ doc/man/Makefile.am | 4 - hw/Makefile.am | 4 - hw/Makemodule.am | 1 + hw/include/Makefile.am | 4 - hw/source/{Makefile.am => Makemodule.am} | 22 +- include/Makefile.am | 26 - include/Makemodule.am | 88 ++ include/QF/Makefile.am | 38 - include/QF/Makemodule.am | 151 +++ libs/Makefile.am | 12 - libs/Makemodule.am | 13 + libs/audio/Makefile.am | 77 -- libs/audio/Makemodule.am | 67 ++ libs/audio/renderer/Makefile.am | 55 - libs/audio/renderer/Makemodule.am | 46 + libs/audio/targets/Makefile.am | 62 -- libs/audio/targets/Makemodule.am | 54 + libs/audio/test/Makefile.am | 6 +- libs/client/Makefile.am | 11 - libs/client/Makemodule.am | 6 + libs/console/Makefile.am | 43 - libs/console/Makemodule.am | 33 + libs/gamecode/Makefile.am | 16 - libs/gamecode/Makemodule.am | 19 + libs/gib/Makefile.am | 22 - libs/gib/Makemodule.am | 29 + libs/image/Makefile.am | 18 - libs/image/Makemodule.am | 9 + libs/models/Makefile.am | 58 -- libs/models/Makemodule.am | 55 + libs/models/alias/Makefile.am | 20 - libs/models/alias/Makemodule.am | 15 + libs/models/brush/Makefile.am | 22 - libs/models/brush/Makemodule.am | 17 + libs/models/iqm/Makefile.am | 20 - libs/models/iqm/Makemodule.am | 15 + libs/models/sprite/Makefile.am | 20 - libs/models/sprite/Makemodule.am | 15 + libs/models/test/Makefile.am | 24 - libs/models/test/Makemodule.am | 36 + libs/net/Makefile.am | 19 - libs/net/Makemodule.am | 14 + libs/net/nc/Makefile.am | 17 - libs/net/nc/Makemodule.am | 8 + libs/net/nm/Makefile.am | 18 - libs/net/nm/Makemodule.am | 8 + libs/qw/Makefile.am | 8 - libs/qw/Makemodule.am | 4 + libs/ruamoko/Makefile.am | 21 - libs/ruamoko/Makemodule.am | 26 + libs/util/Makefile.am | 60 -- libs/util/Makemodule.am | 84 ++ libs/util/test/Makefile.am | 70 -- libs/util/test/Makemodule.am | 79 ++ libs/video/Makefile.am | 6 - libs/video/Makemodule.am | 2 + libs/video/renderer/Makefile.am | 65 -- libs/video/renderer/Makemodule.am | 185 ++++ libs/video/renderer/gl/Makefile.am | 16 - libs/video/renderer/glsl/Makefile.am | 28 - libs/video/renderer/glsl/vid_common_glsl.c | 2 +- libs/video/renderer/sw/Makefile.am | 33 - libs/video/renderer/sw32/Makefile.am | 18 - libs/video/targets/Makefile.am | 117 --- libs/video/targets/Makemodule.am | 115 +++ m4/quakeforge.m4 | 16 +- nq/Makefile.am | 4 - nq/Makemodule.am | 3 + nq/include/Makefile.am | 5 - nq/include/Makemodule.am | 11 + nq/source/Makefile.am | 176 ---- nq/source/Makemodule.am | 164 +++ nq/source/cl_chase.c | 5 +- nq/source/cl_cmd.c | 2 +- nq/source/cl_demo.c | 5 +- nq/source/cl_ents.c | 11 +- nq/source/cl_input.c | 7 +- nq/source/cl_main.c | 15 +- nq/source/cl_parse.c | 9 +- nq/source/cl_screen.c | 3 +- nq/source/cl_tent.c | 3 +- nq/source/cl_view.c | 7 +- nq/source/game.c | 4 +- nq/source/host.c | 9 +- nq/source/host_cmd.c | 9 +- nq/source/sbar.c | 7 +- nq/source/sv_cl_phys.c | 7 +- nq/source/sv_cvar.c | 2 +- nq/source/sv_ded.c | 4 +- nq/source/sv_main.c | 7 +- nq/source/sv_move.c | 5 +- nq/source/sv_phys.c | 5 +- nq/source/sv_pr_cmds.c | 7 +- nq/source/sv_progs.c | 7 +- nq/source/sv_user.c | 7 +- nq/source/sys_sdl.c | 6 +- nq/source/sys_unix.c | 4 +- nq/source/sys_unixd.c | 2 +- nq/source/sys_win.c | 4 +- nq/source/sys_wind.c | 2 +- nq/source/world.c | 5 +- pkg-config/Makefile.am | 5 - pkg-config/Makemodule.am | 5 + qtv/Makefile.am | 4 - qtv/Makemodule.am | 2 + qtv/include/Makefile.am | 4 - qtv/include/Makemodule.am | 5 + qtv/source/{Makefile.am => Makemodule.am} | 29 +- qtv/source/client.c | 8 +- qtv/source/connection.c | 2 +- qtv/source/qtv.c | 13 +- qtv/source/sbar.c | 7 +- qtv/source/server.c | 8 +- qtv/source/sv_parse.c | 8 +- qw/Makefile.am | 4 - qw/Makemodule.am | 2 + qw/include/Makefile.am | 9 - qw/include/Makemodule.am | 28 + qw/source/Makefile.am | 191 ---- qw/source/Makemodule.am | 175 ++++ qw/source/cl_cam.c | 11 +- qw/source/cl_chase.c | 6 +- qw/source/cl_chat.c | 4 +- qw/source/cl_cmd.c | 2 +- qw/source/cl_cvar.c | 3 +- qw/source/cl_demo.c | 13 +- qw/source/cl_entparse.c | 24 +- qw/source/cl_ents.c | 25 +- qw/source/cl_http.c | 8 +- qw/source/cl_input.c | 19 +- qw/source/cl_main.c | 42 +- qw/source/cl_ngraph.c | 5 +- qw/source/cl_parse.c | 32 +- qw/source/cl_pred.c | 9 +- qw/source/cl_rss.c | 4 +- qw/source/cl_screen.c | 3 +- qw/source/cl_skin.c | 9 +- qw/source/cl_slist.c | 6 +- qw/source/cl_sys_sdl.c | 3 +- qw/source/cl_sys_unix.c | 3 +- qw/source/cl_sys_win.c | 4 +- qw/source/cl_tent.c | 11 +- qw/source/cl_view.c | 16 +- qw/source/crudefile.c | 3 +- qw/source/game.c | 4 +- qw/source/locs.c | 3 +- qw/source/map_cfg.c | 2 +- qw/source/net_packetlog.c | 3 +- qw/source/pmove.c | 3 +- qw/source/pmovetst.c | 1 + qw/source/sbar.c | 9 +- qw/source/sv_ccmds.c | 13 +- qw/source/sv_demo.c | 9 +- qw/source/sv_ents.c | 7 +- qw/source/sv_gib.c | 4 +- qw/source/sv_init.c | 11 +- qw/source/sv_main.c | 19 +- qw/source/sv_move.c | 4 +- qw/source/sv_phys.c | 4 +- qw/source/sv_pr_cmds.c | 11 +- qw/source/sv_pr_cpqw.c | 6 +- qw/source/sv_pr_qwe.c | 8 +- qw/source/sv_progs.c | 9 +- qw/source/sv_qtv.c | 7 +- qw/source/sv_recorder.c | 8 +- qw/source/sv_sbar.c | 5 +- qw/source/sv_send.c | 9 +- qw/source/sv_sys_unix.c | 2 +- qw/source/sv_sys_win.c | 2 +- qw/source/sv_user.c | 11 +- qw/source/teamplay.c | 7 +- qw/source/world.c | 5 +- ruamoko/Makefile.am | 8 - ruamoko/Makemodule.am | 10 + ruamoko/cl_menu/Makefile.am | 71 -- ruamoko/cl_menu/Makemodule.am | 77 ++ ruamoko/game/Makefile.am | 56 - ruamoko/game/Makemodule.am | 27 + ruamoko/gui/Makefile.am | 50 - ruamoko/gui/Makemodule.am | 25 + ruamoko/include/Makefile.am | 16 - ruamoko/include/Makemodule.am | 56 + ruamoko/lib/Makefile.am | 96 -- ruamoko/lib/Makemodule.am | 87 ++ ruamoko/qwaq/Makefile.am | 135 --- ruamoko/qwaq/Makemodule.am | 149 +++ ruamoko/qwaq/builtins/builtins.c | 2 +- ruamoko/qwaq/builtins/curses.c | 8 +- ruamoko/qwaq/builtins/debug.c | 8 +- ruamoko/qwaq/builtins/editbuffer.c | 4 +- ruamoko/qwaq/builtins/input.c | 6 +- ruamoko/qwaq/builtins/main.c | 4 +- ruamoko/qwaq/builtins/qwaq-bi.c | 2 +- ruamoko/qwaq/builtins/qwaq.c | 2 +- ruamoko/qwaq/debugger/debug.h | 2 +- ruamoko/qwaq/debugger/debug.r | 2 +- ruamoko/qwaq/debugger/debugger.h | 4 +- ruamoko/qwaq/debugger/debugger.r | 20 +- ruamoko/qwaq/debugger/localsdata.h | 4 +- ruamoko/qwaq/debugger/localsdata.r | 8 +- ruamoko/qwaq/debugger/typeencodings.h | 2 +- ruamoko/qwaq/debugger/typeencodings.r | 4 +- ruamoko/qwaq/debugger/views/basicview.h | 2 +- ruamoko/qwaq/debugger/views/basicview.r | 4 +- ruamoko/qwaq/debugger/views/defview.h | 4 +- ruamoko/qwaq/debugger/views/defview.r | 4 +- ruamoko/qwaq/debugger/views/doubleview.h | 2 +- ruamoko/qwaq/debugger/views/doubleview.r | 2 +- ruamoko/qwaq/debugger/views/entityview.h | 2 +- ruamoko/qwaq/debugger/views/entityview.r | 2 +- ruamoko/qwaq/debugger/views/fieldview.h | 2 +- ruamoko/qwaq/debugger/views/fieldview.r | 2 +- ruamoko/qwaq/debugger/views/floatview.h | 2 +- ruamoko/qwaq/debugger/views/floatview.r | 2 +- ruamoko/qwaq/debugger/views/funcview.h | 2 +- ruamoko/qwaq/debugger/views/funcview.r | 2 +- ruamoko/qwaq/debugger/views/intview.h | 2 +- ruamoko/qwaq/debugger/views/intview.r | 2 +- ruamoko/qwaq/debugger/views/nameview.h | 2 +- ruamoko/qwaq/debugger/views/nameview.r | 2 +- ruamoko/qwaq/debugger/views/pointerview.h | 2 +- ruamoko/qwaq/debugger/views/pointerview.r | 2 +- ruamoko/qwaq/debugger/views/quatview.h | 2 +- ruamoko/qwaq/debugger/views/quatview.r | 2 +- ruamoko/qwaq/debugger/views/stringview.h | 2 +- ruamoko/qwaq/debugger/views/stringview.r | 2 +- ruamoko/qwaq/debugger/views/uintview.h | 2 +- ruamoko/qwaq/debugger/views/uintview.r | 2 +- ruamoko/qwaq/debugger/views/vectorview.h | 2 +- ruamoko/qwaq/debugger/views/vectorview.r | 2 +- ruamoko/qwaq/debugger/views/voidview.h | 2 +- ruamoko/qwaq/debugger/views/voidview.r | 2 +- ruamoko/qwaq/editor/editbuffer.r | 2 +- ruamoko/qwaq/editor/editor.h | 4 +- ruamoko/qwaq/editor/editor.r | 8 +- ruamoko/qwaq/qwaq-app.h | 4 +- ruamoko/qwaq/qwaq-app.r | 12 +- ruamoko/qwaq/ui/button.h | 4 +- ruamoko/qwaq/ui/button.r | 4 +- ruamoko/qwaq/ui/curses.h | 4 +- ruamoko/qwaq/ui/draw.h | 2 +- ruamoko/qwaq/ui/draw.r | 4 +- ruamoko/qwaq/ui/garray.r | 4 +- ruamoko/qwaq/ui/group.h | 4 +- ruamoko/qwaq/ui/group.r | 10 +- ruamoko/qwaq/ui/listener.r | 4 +- ruamoko/qwaq/ui/proxyview.h | 2 +- ruamoko/qwaq/ui/proxyview.r | 4 +- ruamoko/qwaq/ui/rect.r | 2 +- ruamoko/qwaq/ui/scrollbar.h | 2 +- ruamoko/qwaq/ui/scrollbar.r | 8 +- ruamoko/qwaq/ui/tableview.h | 2 +- ruamoko/qwaq/ui/tableview.r | 4 +- ruamoko/qwaq/ui/textcontext.h | 6 +- ruamoko/qwaq/ui/textcontext.r | 4 +- ruamoko/qwaq/ui/titlebar.h | 2 +- ruamoko/qwaq/ui/titlebar.r | 4 +- ruamoko/qwaq/ui/view.h | 6 +- ruamoko/qwaq/ui/view.r | 10 +- ruamoko/qwaq/ui/window.h | 6 +- ruamoko/qwaq/ui/window.r | 16 +- ruamoko/scheme/Makefile.am | 81 -- ruamoko/scheme/Makemodule.am | 88 ++ tools/Makefile.am | 6 - tools/Makemodule.am | 20 + tools/bsp2img/{Makefile.am => Makemodule.am} | 6 +- tools/carne/Makefile.am | 13 - tools/carne/Makemodule.am | 8 + tools/pak/Makefile.am | 19 - tools/pak/Makemodule.am | 14 + tools/qfbsp/Makefile.am | 3 - tools/qfbsp/Makemodule.am | 2 + tools/qfbsp/include/Makefile.am | 5 - tools/qfbsp/include/Makemodule.am | 16 + tools/qfbsp/source/Makefile.am | 16 - tools/qfbsp/source/Makemodule.am | 25 + tools/qfbsp/source/brush.c | 10 +- tools/qfbsp/source/csg4.c | 14 +- tools/qfbsp/source/map.c | 2 +- tools/qfbsp/source/merge.c | 12 +- tools/qfbsp/source/nodraw.c | 2 +- tools/qfbsp/source/options.c | 2 +- tools/qfbsp/source/outside.c | 12 +- tools/qfbsp/source/portals.c | 10 +- tools/qfbsp/source/qfbsp.c | 24 +- tools/qfbsp/source/readbsp.c | 10 +- tools/qfbsp/source/region.c | 6 +- tools/qfbsp/source/solidbsp.c | 12 +- tools/qfbsp/source/surfaces.c | 10 +- tools/qfbsp/source/tjunc.c | 8 +- tools/qfbsp/source/writebsp.c | 8 +- tools/qfcc/Makefile.am | 48 - tools/qfcc/Makemodule.am | 4 + tools/qfcc/bootstrap | 3 - tools/qfcc/configure.in | 144 --- tools/qfcc/doc/Makefile.am | 6 - tools/qfcc/doc/Makemodule.am | 5 + tools/qfcc/doc/man/Makefile.am | 4 - tools/qfcc/include/Makefile.am | 7 - tools/qfcc/include/Makemodule.am | 34 + tools/qfcc/source/Makefile.am | 76 -- tools/qfcc/source/Makemodule.am | 92 ++ tools/qfcc/source/class.c | 34 +- tools/qfcc/source/codespace.c | 2 +- tools/qfcc/source/constfold.c | 17 +- tools/qfcc/source/cpp.c | 6 +- tools/qfcc/source/dags.c | 24 +- tools/qfcc/source/debug.c | 24 +- tools/qfcc/source/def.c | 32 +- tools/qfcc/source/defspace.c | 18 +- tools/qfcc/source/diagnostic.c | 14 +- tools/qfcc/source/disassemble.c | 2 +- tools/qfcc/source/dot.c | 8 +- tools/qfcc/source/dot_dag.c | 10 +- tools/qfcc/source/dot_expr.c | 11 +- tools/qfcc/source/dot_flow.c | 12 +- tools/qfcc/source/dot_sblock.c | 18 +- tools/qfcc/source/dot_type.c | 9 +- tools/qfcc/source/dump_globals.c | 10 +- tools/qfcc/source/dump_lines.c | 4 +- tools/qfcc/source/dump_modules.c | 2 +- tools/qfcc/source/dump_strings.c | 4 +- tools/qfcc/source/emit.c | 30 +- tools/qfcc/source/expr.c | 39 +- tools/qfcc/source/expr_assign.c | 37 +- tools/qfcc/source/expr_binary.c | 11 +- tools/qfcc/source/expr_bool.c | 39 +- tools/qfcc/source/expr_compound.c | 10 +- tools/qfcc/source/expr_obj.c | 37 +- tools/qfcc/source/flow.c | 24 +- tools/qfcc/source/function.c | 40 +- tools/qfcc/source/grab.c | 12 +- tools/qfcc/source/idstuff.c | 20 +- tools/qfcc/source/linker.c | 30 +- tools/qfcc/source/method.c | 32 +- tools/qfcc/source/obj_file.c | 34 +- tools/qfcc/source/obj_type.c | 20 +- tools/qfcc/source/opcodes.c | 10 +- tools/qfcc/source/options.c | 10 +- tools/qfcc/source/pragma.c | 12 +- tools/qfcc/source/qc-lex.l | 30 +- tools/qfcc/source/qc-parse.y | 36 +- tools/qfcc/source/qfcc.c | 50 +- tools/qfcc/source/qfprogs.c | 8 +- tools/qfcc/source/qp-lex.l | 20 +- tools/qfcc/source/qp-parse.y | 18 +- tools/qfcc/source/reloc.c | 18 +- tools/qfcc/source/shared.c | 16 +- tools/qfcc/source/statements.c | 29 +- tools/qfcc/source/strpool.c | 6 +- tools/qfcc/source/struct.c | 30 +- tools/qfcc/source/stub.c | 38 +- tools/qfcc/source/switch.c | 22 +- tools/qfcc/source/symtab.c | 20 +- tools/qfcc/source/type.c | 24 +- tools/qfcc/source/value.c | 22 +- tools/qfcc/test/Makefile.am | 615 ----------- tools/qfcc/test/Makemodule.am | 599 +++++++++++ tools/qfcc/test/build-run | 4 +- tools/qfcc/test/test-defspace.c | 14 +- tools/qfcc/test/test-defspace.h | 4 +- tools/qflight/Makefile.am | 7 - tools/qflight/Makemodule.am | 4 + tools/qflight/include/Makefile.am | 3 - tools/qflight/include/Makemodule.am | 7 + tools/qflight/source/Makefile.am | 20 - tools/qflight/source/Makemodule.am | 20 + tools/qflight/source/entities.c | 10 +- tools/qflight/source/ltface.c | 10 +- tools/qflight/source/noise.c | 2 +- tools/qflight/source/options.c | 6 +- tools/qflight/source/properties.c | 8 +- tools/qflight/source/qflight.c | 10 +- tools/qflight/source/threads.c | 6 +- tools/qflight/source/trace.c | 4 +- tools/qflight/source/vis.c | 8 +- tools/qflmp/Makefile.am | 18 - tools/qflmp/Makemodule.am | 14 + tools/qfmodelgen/Makefile.am | 7 - tools/qfmodelgen/Makemodule.am | 2 + tools/qfmodelgen/include/Makefile.am | 3 - tools/qfmodelgen/include/Makemodule.am | 3 + .../source/{Makefile.am => Makemodule.am} | 11 +- tools/qfmodelgen/source/lbmlib.c | 2 +- tools/qfmodelgen/source/modelgen.c | 5 +- tools/qfmodelgen/source/trilib.c | 2 +- .../{Makefile.am => Makemodule.am} | 8 +- tools/qfvis/Makefile.am | 7 - tools/qfvis/Makemodule.am | 4 + tools/qfvis/include/Makefile.am | 3 - tools/qfvis/include/Makemodule.am | 3 + tools/qfvis/source/Makefile.am | 17 - tools/qfvis/source/Makemodule.am | 16 + tools/qfvis/source/base-vis.c | 4 +- tools/qfvis/source/flow.c | 4 +- tools/qfvis/source/options.c | 4 +- tools/qfvis/source/qfvis.c | 4 +- tools/qfvis/source/soundphs.c | 2 +- tools/wad/Makefile.am | 19 - tools/wad/Makemodule.am | 13 + tools/wav/Makefile.am | 18 - tools/wav/Makemodule.am | 11 + vc2005/Makefile.am | 24 - vc2005/QuakeForge-VS8-Express.sln | 935 ----------------- vc2005/QuakeForge-VS8.sln | 966 ----------------- vc2005/bsp2img/bsp2img.vcproj | 567 ---------- vc2005/builtins/builtins.vcproj | 473 --------- vc2005/clean.ps1 | 3 - vc2005/common/common.vcproj | 489 --------- vc2005/console/console.vcproj | 493 --------- vc2005/console_client/console_client.vcproj | 481 --------- vc2005/console_server/console_server.vcproj | 469 --------- vc2005/engine/engine.vcproj | 509 --------- vc2005/gib/gib.vcproj | 537 ---------- vc2005/hw-master/hw-master.vcproj | 567 ---------- vc2005/image/image.vcproj | 481 --------- vc2005/include/config.h | 740 ------------- vc2005/models-sw/models-sw.vcproj | 511 --------- vc2005/models/models.vcproj | 489 --------- vc2005/modelsgl/modelsgl.vcproj | 521 ---------- vc2005/net-main/net-main.vcproj | 487 --------- vc2005/net/net.vcproj | 473 --------- vc2005/nq-common/nq-common.vcproj | 515 ---------- vc2005/nq-sdl/nq-sdl.vcproj | 561 ---------- vc2005/nq-sdl32/nq-sdl32.vcproj | 567 ---------- vc2005/nq-server/nq-server.vcproj | 571 ----------- vc2005/nq-sgl/nq-sgl.vcproj | 567 ---------- vc2005/nq-wgl/nq-wgl.vcproj | 567 ---------- vc2005/nq/nq.vcproj | 543 ---------- vc2005/pak/pak.vcproj | 571 ----------- vc2005/qfbsp/qfbsp.vcproj | 637 ------------ vc2005/qfcc/FlexBison.rules | 246 ----- vc2005/qfcc/qfcc.vcproj | 970 ------------------ vc2005/qfclient/qfclient.vcproj | 625 ----------- vc2005/qflight/qflight.vcproj | 625 ----------- vc2005/qfmodelgen/qfmodelgen.vcproj | 583 ----------- vc2005/qfprogs/qfprogs.vcproj | 595 ----------- vc2005/qfserver/qfserver.vcproj | 677 ------------ vc2005/qfvis/qfvis.vcproj | 593 ----------- vc2005/qfwavinfo/qfwavinfo.vcproj | 567 ---------- vc2005/qtv/qtv.vcproj | 599 ----------- vc2005/qw-client-sdl/qw-client-sdl.vcproj | 563 ---------- vc2005/qw-client-sdl32/qw-client-sdl32.vcproj | 567 ---------- vc2005/qw-client-sgl/qw-client-sgl.vcproj | 567 ---------- vc2005/qw-client-wgl/qw-client-wgl.vcproj | 563 ---------- vc2005/qw-master/qw-master.vcproj | 567 ---------- vc2005/qw/qw.vcproj | 473 --------- vc2005/readme.txt | 27 - vc2005/ruamoko/ruamoko.vcproj | 517 ---------- vc2005/sound/sound.vcproj | 513 --------- vc2005/util/util.vcproj | 617 ----------- vc2005/video-sdl/video-sdl.vcproj | 471 --------- vc2005/video-sgl/video-sgl.vcproj | 467 --------- vc2005/video-sw/video-sw.vcproj | 595 ----------- vc2005/video-sw32/video-sw32.vcproj | 571 ----------- vc2005/video-wgl/video-wgl.vcproj | 471 --------- vc2005/video/video.vcproj | 537 ---------- vc2005/videogl/videogl.vcproj | 555 ---------- vc2005/wad/wad.vcproj | 579 ----------- vc2008/Makefile.am | 24 - vc2008/QuakeForge.sln | 966 ----------------- vc2008/bsp2img/bsp2img.vcproj | 562 ---------- vc2008/builtins/builtins.vcproj | 474 --------- vc2008/clean.ps1 | 3 - vc2008/common/common.vcproj | 490 --------- vc2008/console/console.vcproj | 494 --------- vc2008/console_client/console_client.vcproj | 482 --------- vc2008/console_server/console_server.vcproj | 470 --------- vc2008/engine/engine.vcproj | 510 --------- vc2008/gib/gib.vcproj | 538 ---------- vc2008/hw-master/hw-master.vcproj | 562 ---------- vc2008/image/image.vcproj | 482 --------- vc2008/include/config.h | 740 ------------- vc2008/models-sw/models-sw.vcproj | 512 --------- vc2008/models/models.vcproj | 490 --------- vc2008/modelsgl/modelsgl.vcproj | 522 ---------- vc2008/net-main/net-main.vcproj | 488 --------- vc2008/net/net.vcproj | 474 --------- vc2008/nq-common/nq-common.vcproj | 516 ---------- vc2008/nq-sdl/nq-sdl.vcproj | 556 ---------- vc2008/nq-sdl32/nq-sdl32.vcproj | 562 ---------- vc2008/nq-server/nq-server.vcproj | 566 ---------- vc2008/nq-sgl/nq-sgl.vcproj | 562 ---------- vc2008/nq-wgl/nq-wgl.vcproj | 562 ---------- vc2008/nq/nq.vcproj | 544 ---------- vc2008/pak/pak.vcproj | 566 ---------- vc2008/qfbsp/qfbsp.vcproj | 632 ------------ vc2008/qfcc/FlexBison.rules | 246 ----- vc2008/qfcc/qfcc.vcproj | 965 ----------------- vc2008/qfclient/qfclient.vcproj | 626 ----------- vc2008/qflight/qflight.vcproj | 620 ----------- vc2008/qfmodelgen/qfmodelgen.vcproj | 578 ----------- vc2008/qfprogs/qfprogs.vcproj | 590 ----------- vc2008/qfserver/qfserver.vcproj | 672 ------------ vc2008/qfvis/qfvis.vcproj | 588 ----------- vc2008/qfwavinfo/qfwavinfo.vcproj | 562 ---------- vc2008/qtv/qtv.vcproj | 594 ----------- vc2008/qw-client-sdl/qw-client-sdl.vcproj | 558 ---------- vc2008/qw-client-sdl32/qw-client-sdl32.vcproj | 562 ---------- vc2008/qw-client-sgl/qw-client-sgl.vcproj | 562 ---------- vc2008/qw-client-wgl/qw-client-wgl.vcproj | 558 ---------- vc2008/qw-master/qw-master.vcproj | 562 ---------- vc2008/qw/qw.vcproj | 474 --------- vc2008/readme.txt | 25 - vc2008/ruamoko/ruamoko.vcproj | 518 ---------- vc2008/sound/sound.vcproj | 514 ---------- vc2008/util/util.vcproj | 618 ----------- vc2008/video-sdl/video-sdl.vcproj | 472 --------- vc2008/video-sgl/video-sgl.vcproj | 468 --------- vc2008/video-sw/video-sw.vcproj | 596 ----------- vc2008/video-sw32/video-sw32.vcproj | 572 ----------- vc2008/video-wgl/video-wgl.vcproj | 472 --------- vc2008/video/video.vcproj | 538 ---------- vc2008/videogl/videogl.vcproj | 556 ---------- vc2008/wad/wad.vcproj | 574 ----------- 535 files changed, 4528 insertions(+), 64841 deletions(-) delete mode 100644 RPM/Makefile.am create mode 100644 RPM/Makemodule.am delete mode 100644 debian/Makefile.am create mode 100644 debian/Makemodule.am delete mode 100644 desktop/Makefile.am create mode 100644 desktop/Makemodule.am delete mode 100644 desktop/quakeforge-nq-glx.desktop delete mode 100644 desktop/quakeforge-nq-sdl32.desktop delete mode 100644 desktop/quakeforge-nq-sgl.desktop delete mode 100644 desktop/quakeforge-qw-glx.desktop delete mode 100644 desktop/quakeforge-qw-sdl32.desktop delete mode 100644 desktop/quakeforge-qw-sgl.desktop delete mode 100644 doc/Makefile.am create mode 100644 doc/Makemodule.am delete mode 100644 doc/man/Makefile.am delete mode 100644 hw/Makefile.am create mode 100644 hw/Makemodule.am delete mode 100644 hw/include/Makefile.am rename hw/source/{Makefile.am => Makemodule.am} (69%) delete mode 100644 include/Makefile.am create mode 100644 include/Makemodule.am delete mode 100644 include/QF/Makefile.am create mode 100644 include/QF/Makemodule.am delete mode 100644 libs/Makefile.am create mode 100644 libs/Makemodule.am delete mode 100644 libs/audio/Makefile.am create mode 100644 libs/audio/Makemodule.am delete mode 100644 libs/audio/renderer/Makefile.am create mode 100644 libs/audio/renderer/Makemodule.am delete mode 100644 libs/audio/targets/Makefile.am create mode 100644 libs/audio/targets/Makemodule.am delete mode 100644 libs/client/Makefile.am create mode 100644 libs/client/Makemodule.am delete mode 100644 libs/console/Makefile.am create mode 100644 libs/console/Makemodule.am delete mode 100644 libs/gamecode/Makefile.am create mode 100644 libs/gamecode/Makemodule.am delete mode 100644 libs/gib/Makefile.am create mode 100644 libs/gib/Makemodule.am delete mode 100644 libs/image/Makefile.am create mode 100644 libs/image/Makemodule.am delete mode 100644 libs/models/Makefile.am create mode 100644 libs/models/Makemodule.am delete mode 100644 libs/models/alias/Makefile.am create mode 100644 libs/models/alias/Makemodule.am delete mode 100644 libs/models/brush/Makefile.am create mode 100644 libs/models/brush/Makemodule.am delete mode 100644 libs/models/iqm/Makefile.am create mode 100644 libs/models/iqm/Makemodule.am delete mode 100644 libs/models/sprite/Makefile.am create mode 100644 libs/models/sprite/Makemodule.am delete mode 100644 libs/models/test/Makefile.am create mode 100644 libs/models/test/Makemodule.am delete mode 100644 libs/net/Makefile.am create mode 100644 libs/net/Makemodule.am delete mode 100644 libs/net/nc/Makefile.am create mode 100644 libs/net/nc/Makemodule.am delete mode 100644 libs/net/nm/Makefile.am create mode 100644 libs/net/nm/Makemodule.am delete mode 100644 libs/qw/Makefile.am create mode 100644 libs/qw/Makemodule.am delete mode 100644 libs/ruamoko/Makefile.am create mode 100644 libs/ruamoko/Makemodule.am delete mode 100644 libs/util/Makefile.am create mode 100644 libs/util/Makemodule.am delete mode 100644 libs/util/test/Makefile.am create mode 100644 libs/util/test/Makemodule.am delete mode 100644 libs/video/Makefile.am create mode 100644 libs/video/Makemodule.am delete mode 100644 libs/video/renderer/Makefile.am create mode 100644 libs/video/renderer/Makemodule.am delete mode 100644 libs/video/renderer/gl/Makefile.am delete mode 100644 libs/video/renderer/glsl/Makefile.am delete mode 100644 libs/video/renderer/sw/Makefile.am delete mode 100644 libs/video/renderer/sw32/Makefile.am delete mode 100644 libs/video/targets/Makefile.am create mode 100644 libs/video/targets/Makemodule.am delete mode 100644 nq/Makefile.am create mode 100644 nq/Makemodule.am delete mode 100644 nq/include/Makefile.am create mode 100644 nq/include/Makemodule.am delete mode 100644 nq/source/Makefile.am create mode 100644 nq/source/Makemodule.am delete mode 100644 pkg-config/Makefile.am create mode 100644 pkg-config/Makemodule.am delete mode 100644 qtv/Makefile.am create mode 100644 qtv/Makemodule.am delete mode 100644 qtv/include/Makefile.am create mode 100644 qtv/include/Makemodule.am rename qtv/source/{Makefile.am => Makemodule.am} (61%) delete mode 100644 qw/Makefile.am create mode 100644 qw/Makemodule.am delete mode 100644 qw/include/Makefile.am create mode 100644 qw/include/Makemodule.am delete mode 100644 qw/source/Makefile.am create mode 100644 qw/source/Makemodule.am delete mode 100644 ruamoko/Makefile.am create mode 100644 ruamoko/Makemodule.am delete mode 100644 ruamoko/cl_menu/Makefile.am create mode 100644 ruamoko/cl_menu/Makemodule.am delete mode 100644 ruamoko/game/Makefile.am create mode 100644 ruamoko/game/Makemodule.am delete mode 100644 ruamoko/gui/Makefile.am create mode 100644 ruamoko/gui/Makemodule.am delete mode 100644 ruamoko/include/Makefile.am create mode 100644 ruamoko/include/Makemodule.am delete mode 100644 ruamoko/lib/Makefile.am create mode 100644 ruamoko/lib/Makemodule.am delete mode 100644 ruamoko/qwaq/Makefile.am create mode 100644 ruamoko/qwaq/Makemodule.am delete mode 100644 ruamoko/scheme/Makefile.am create mode 100644 ruamoko/scheme/Makemodule.am delete mode 100644 tools/Makefile.am create mode 100644 tools/Makemodule.am rename tools/bsp2img/{Makefile.am => Makemodule.am} (60%) delete mode 100644 tools/carne/Makefile.am create mode 100644 tools/carne/Makemodule.am delete mode 100644 tools/pak/Makefile.am create mode 100644 tools/pak/Makemodule.am delete mode 100644 tools/qfbsp/Makefile.am create mode 100644 tools/qfbsp/Makemodule.am delete mode 100644 tools/qfbsp/include/Makefile.am create mode 100644 tools/qfbsp/include/Makemodule.am delete mode 100644 tools/qfbsp/source/Makefile.am create mode 100644 tools/qfbsp/source/Makemodule.am delete mode 100644 tools/qfcc/Makefile.am create mode 100644 tools/qfcc/Makemodule.am delete mode 100755 tools/qfcc/bootstrap delete mode 100644 tools/qfcc/configure.in delete mode 100644 tools/qfcc/doc/Makefile.am create mode 100644 tools/qfcc/doc/Makemodule.am delete mode 100644 tools/qfcc/doc/man/Makefile.am delete mode 100644 tools/qfcc/include/Makefile.am create mode 100644 tools/qfcc/include/Makemodule.am delete mode 100644 tools/qfcc/source/Makefile.am create mode 100644 tools/qfcc/source/Makemodule.am delete mode 100644 tools/qfcc/test/Makefile.am create mode 100644 tools/qfcc/test/Makemodule.am delete mode 100644 tools/qflight/Makefile.am create mode 100644 tools/qflight/Makemodule.am delete mode 100644 tools/qflight/include/Makefile.am create mode 100644 tools/qflight/include/Makemodule.am delete mode 100644 tools/qflight/source/Makefile.am create mode 100644 tools/qflight/source/Makemodule.am delete mode 100644 tools/qflmp/Makefile.am create mode 100644 tools/qflmp/Makemodule.am delete mode 100644 tools/qfmodelgen/Makefile.am create mode 100644 tools/qfmodelgen/Makemodule.am delete mode 100644 tools/qfmodelgen/include/Makefile.am create mode 100644 tools/qfmodelgen/include/Makemodule.am rename tools/qfmodelgen/source/{Makefile.am => Makemodule.am} (54%) rename tools/qfspritegen/{Makefile.am => Makemodule.am} (57%) delete mode 100644 tools/qfvis/Makefile.am create mode 100644 tools/qfvis/Makemodule.am delete mode 100644 tools/qfvis/include/Makefile.am create mode 100644 tools/qfvis/include/Makemodule.am delete mode 100644 tools/qfvis/source/Makefile.am create mode 100644 tools/qfvis/source/Makemodule.am delete mode 100644 tools/wad/Makefile.am create mode 100644 tools/wad/Makemodule.am delete mode 100644 tools/wav/Makefile.am create mode 100644 tools/wav/Makemodule.am delete mode 100644 vc2005/Makefile.am delete mode 100644 vc2005/QuakeForge-VS8-Express.sln delete mode 100644 vc2005/QuakeForge-VS8.sln delete mode 100644 vc2005/bsp2img/bsp2img.vcproj delete mode 100644 vc2005/builtins/builtins.vcproj delete mode 100644 vc2005/clean.ps1 delete mode 100644 vc2005/common/common.vcproj delete mode 100644 vc2005/console/console.vcproj delete mode 100644 vc2005/console_client/console_client.vcproj delete mode 100644 vc2005/console_server/console_server.vcproj delete mode 100644 vc2005/engine/engine.vcproj delete mode 100644 vc2005/gib/gib.vcproj delete mode 100644 vc2005/hw-master/hw-master.vcproj delete mode 100644 vc2005/image/image.vcproj delete mode 100644 vc2005/include/config.h delete mode 100644 vc2005/models-sw/models-sw.vcproj delete mode 100644 vc2005/models/models.vcproj delete mode 100644 vc2005/modelsgl/modelsgl.vcproj delete mode 100644 vc2005/net-main/net-main.vcproj delete mode 100644 vc2005/net/net.vcproj delete mode 100644 vc2005/nq-common/nq-common.vcproj delete mode 100644 vc2005/nq-sdl/nq-sdl.vcproj delete mode 100644 vc2005/nq-sdl32/nq-sdl32.vcproj delete mode 100644 vc2005/nq-server/nq-server.vcproj delete mode 100644 vc2005/nq-sgl/nq-sgl.vcproj delete mode 100644 vc2005/nq-wgl/nq-wgl.vcproj delete mode 100644 vc2005/nq/nq.vcproj delete mode 100644 vc2005/pak/pak.vcproj delete mode 100644 vc2005/qfbsp/qfbsp.vcproj delete mode 100644 vc2005/qfcc/FlexBison.rules delete mode 100644 vc2005/qfcc/qfcc.vcproj delete mode 100644 vc2005/qfclient/qfclient.vcproj delete mode 100644 vc2005/qflight/qflight.vcproj delete mode 100644 vc2005/qfmodelgen/qfmodelgen.vcproj delete mode 100644 vc2005/qfprogs/qfprogs.vcproj delete mode 100644 vc2005/qfserver/qfserver.vcproj delete mode 100644 vc2005/qfvis/qfvis.vcproj delete mode 100644 vc2005/qfwavinfo/qfwavinfo.vcproj delete mode 100644 vc2005/qtv/qtv.vcproj delete mode 100644 vc2005/qw-client-sdl/qw-client-sdl.vcproj delete mode 100644 vc2005/qw-client-sdl32/qw-client-sdl32.vcproj delete mode 100644 vc2005/qw-client-sgl/qw-client-sgl.vcproj delete mode 100644 vc2005/qw-client-wgl/qw-client-wgl.vcproj delete mode 100644 vc2005/qw-master/qw-master.vcproj delete mode 100644 vc2005/qw/qw.vcproj delete mode 100644 vc2005/readme.txt delete mode 100644 vc2005/ruamoko/ruamoko.vcproj delete mode 100644 vc2005/sound/sound.vcproj delete mode 100644 vc2005/util/util.vcproj delete mode 100644 vc2005/video-sdl/video-sdl.vcproj delete mode 100644 vc2005/video-sgl/video-sgl.vcproj delete mode 100644 vc2005/video-sw/video-sw.vcproj delete mode 100644 vc2005/video-sw32/video-sw32.vcproj delete mode 100644 vc2005/video-wgl/video-wgl.vcproj delete mode 100644 vc2005/video/video.vcproj delete mode 100644 vc2005/videogl/videogl.vcproj delete mode 100644 vc2005/wad/wad.vcproj delete mode 100644 vc2008/Makefile.am delete mode 100644 vc2008/QuakeForge.sln delete mode 100644 vc2008/bsp2img/bsp2img.vcproj delete mode 100644 vc2008/builtins/builtins.vcproj delete mode 100644 vc2008/clean.ps1 delete mode 100644 vc2008/common/common.vcproj delete mode 100644 vc2008/console/console.vcproj delete mode 100644 vc2008/console_client/console_client.vcproj delete mode 100644 vc2008/console_server/console_server.vcproj delete mode 100644 vc2008/engine/engine.vcproj delete mode 100644 vc2008/gib/gib.vcproj delete mode 100644 vc2008/hw-master/hw-master.vcproj delete mode 100644 vc2008/image/image.vcproj delete mode 100644 vc2008/include/config.h delete mode 100644 vc2008/models-sw/models-sw.vcproj delete mode 100644 vc2008/models/models.vcproj delete mode 100644 vc2008/modelsgl/modelsgl.vcproj delete mode 100644 vc2008/net-main/net-main.vcproj delete mode 100644 vc2008/net/net.vcproj delete mode 100644 vc2008/nq-common/nq-common.vcproj delete mode 100644 vc2008/nq-sdl/nq-sdl.vcproj delete mode 100644 vc2008/nq-sdl32/nq-sdl32.vcproj delete mode 100644 vc2008/nq-server/nq-server.vcproj delete mode 100644 vc2008/nq-sgl/nq-sgl.vcproj delete mode 100644 vc2008/nq-wgl/nq-wgl.vcproj delete mode 100644 vc2008/nq/nq.vcproj delete mode 100644 vc2008/pak/pak.vcproj delete mode 100644 vc2008/qfbsp/qfbsp.vcproj delete mode 100644 vc2008/qfcc/FlexBison.rules delete mode 100644 vc2008/qfcc/qfcc.vcproj delete mode 100644 vc2008/qfclient/qfclient.vcproj delete mode 100644 vc2008/qflight/qflight.vcproj delete mode 100644 vc2008/qfmodelgen/qfmodelgen.vcproj delete mode 100644 vc2008/qfprogs/qfprogs.vcproj delete mode 100644 vc2008/qfserver/qfserver.vcproj delete mode 100644 vc2008/qfvis/qfvis.vcproj delete mode 100644 vc2008/qfwavinfo/qfwavinfo.vcproj delete mode 100644 vc2008/qtv/qtv.vcproj delete mode 100644 vc2008/qw-client-sdl/qw-client-sdl.vcproj delete mode 100644 vc2008/qw-client-sdl32/qw-client-sdl32.vcproj delete mode 100644 vc2008/qw-client-sgl/qw-client-sgl.vcproj delete mode 100644 vc2008/qw-client-wgl/qw-client-wgl.vcproj delete mode 100644 vc2008/qw-master/qw-master.vcproj delete mode 100644 vc2008/qw/qw.vcproj delete mode 100644 vc2008/readme.txt delete mode 100644 vc2008/ruamoko/ruamoko.vcproj delete mode 100644 vc2008/sound/sound.vcproj delete mode 100644 vc2008/util/util.vcproj delete mode 100644 vc2008/video-sdl/video-sdl.vcproj delete mode 100644 vc2008/video-sgl/video-sgl.vcproj delete mode 100644 vc2008/video-sw/video-sw.vcproj delete mode 100644 vc2008/video-sw32/video-sw32.vcproj delete mode 100644 vc2008/video-wgl/video-wgl.vcproj delete mode 100644 vc2008/video/video.vcproj delete mode 100644 vc2008/videogl/videogl.vcproj delete mode 100644 vc2008/wad/wad.vcproj diff --git a/Makefile.am b/Makefile.am index 1b33ee233..9e68af2a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,15 +1,9 @@ ## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign ACLOCAL_AMFLAGS = -I m4 -SUBDIRS=desktop pkg-config include @top_dirs@ -DIST_SUBDIRS=desktop pkg-config include \ - libs hw nq qtv qw tools ruamoko\ - RPM debian doc vc2005 vc2008 - -## configure.ac needs to be listed here for older autoconfs -EXTRA_DIST= ChangeLog configure.ac bootstrap \ +EXTRA_DIST = \ + ChangeLog configure.ac bootstrap \ $(top_srcdir)/.version \ config.d/git-version-gen \ tools/cross/droid/cross-configure.sh \ @@ -26,9 +20,109 @@ EXTRA_DIST= ChangeLog configure.ac bootstrap \ tools/gas2masm/gas2masm.dsp tools/gas2masm/gas2masm.dsw \ tools/gas2masm/gas2masm.mak tools/gas2masm/gas2masm.mdp -NOCONV_DIST= $(distdir)/include/win32/resources/icon1Vista.ico \ +NOCONV_DIST= \ + $(distdir)/include/win32/resources/icon1Vista.ico \ $(distdir)/include/win32/resources/icon1XP.ico +BUILT_SOURCES = $(top_srcdir)/.version +#AM_CFLAGS= @PREFER_NON_PIC@ +AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) + +common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@ + +TESTS = +XFAIL_TESTS = +bin_PROGRAMS = +bin_SCRIPTS = +check_PROGRAMS = +lib_LTLIBRARIES = +man_MANS = +noinst_LTLIBRARIES = +noinst_LIBRARIES = +noinst_PROGRAMS = +noinst_HEADERS = +plugin_LTLIBRARIES = + +RANLIB=touch + +EXTRA_HEADERS = +EXTRA_LTLIBRARIES = +EXTRA_PROGRAMS = +EXTRA_LIBRARIES = + +CLEANFILES = +DISTCLEANFILES = + +YFLAGS = -v -d -Wno-yacc -Werror +PTHREAD_LDFLAGS=@PTHREAD_LDFLAGS@ +PTHREAD_CFLAGS=@PTHREAD_CFLAGS@ + +lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ + -rpath $(libdir) -no-undefined +plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) +plugin_libadd= @plugin_libadd@ + +SDL_LIBS= @SDL_LIBS@ +XMMS_LIBS= @XMMS_LIBS@ + +PAK=$(top_builddir)/pak$(EXEEXT) +QFCC_DEP=qfcc$(EXEEXT) +QFCC=$(top_builddir)/$(QFCC_DEP) +GZ=@progs_gz@ + +QCSYSTEM=--no-default-paths -I$(top_srcdir) -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include +QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide +QCPPFLAGS=$(QCSYSTEM) +QCLINKFLAGS=--no-default-paths -Lruamoko/lib +QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) +QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) +MKDIR_P = @MKDIR_P@ + +am__mv = mv -f + +SUFFIXES=.o .r .pas +.r.o: + depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(QCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tqo -c -o $@ $< &&\ + sed -i -e '1s@:@: $(QFCC_DEP)@' $$depbase.Tqo &&\ + $(am__mv) $$depbase.Tqo $$depbase.Qo +.pas.o: + depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(QCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tqo -c -o $@ $< &&\ + sed -i -e '1s@:@: $(QFCC_DEP)@' $$depbase.Tqo &&\ + $(am__mv) $$depbase.Tqo $$depbase.Qo + +qcautodep = $(join $(addsuffix $(DEPDIR)/,$(dir $(basename $(1)))),$(addsuffix .Qo,$(notdir $(basename $(basename $(1)))))) +r_depfiles_remade= +pas_depfiles_remade= + +include doc/Makemodule.am +include RPM/Makemodule.am +include debian/Makemodule.am +include desktop/Makemodule.am +include pkg-config/Makemodule.am +include include/Makemodule.am +include libs/Makemodule.am +include hw/Makemodule.am +include nq/Makemodule.am +include qtv/Makemodule.am +include qw/Makemodule.am +include tools/Makemodule.am +include ruamoko/Makemodule.am + +DISTCLEANFILES += $(r_depfiles_remade) $(pas_depfiles_remade) + +$(r_depfiles_remade): + $(MKDIR_P) $(@D) + echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.r qfcc@' >$@-t && $(am__mv) $@-t $@ + +$(pas_depfiles_remade): + $(MKDIR_P) $(@D) + echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.pas qfcc@' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) $(pas_depfiles_remade) + echo findme $(ruamoko_gui_libgui_a_dep) + changelog: ChangeLog ChangeLog: FORCE @if test -d "$(top_srcdir)/.git"; then \ @@ -63,7 +157,6 @@ dist-all-local: distdir ZIP="-r9ql" zip $(distdir).zip $(distdir) -rm -rf $(distdir) -BUILT_SOURCES = $(top_srcdir)/.version $(top_srcdir)/.version: echo $(VERSION) > $@-t && mv $@-t $@ dist-hook: diff --git a/RPM/Makefile.am b/RPM/Makefile.am deleted file mode 100644 index 13616e183..000000000 --- a/RPM/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST= build_rpm.in quakeforge.conf.in quakeforge.spec.in - -rpm: build_rpm quakeforge.conf quakeforge.spec - ./build_rpm - -CLEANFILES = *.rpm diff --git a/RPM/Makemodule.am b/RPM/Makemodule.am new file mode 100644 index 000000000..583cc8506 --- /dev/null +++ b/RPM/Makemodule.am @@ -0,0 +1,6 @@ +EXTRA_DIST += RPM/build_rpm.in RPM/quakeforge.conf.in RPM/quakeforge.spec.in + +rpm: RPM/build_rpm RPM/quakeforge.conf RPM/quakeforge.spec + cd RPM && ./build_rpm + +CLEANFILES += rpm/*.rpm diff --git a/bootstrap b/bootstrap index 4986a6ca4..abd34252f 100755 --- a/bootstrap +++ b/bootstrap @@ -18,7 +18,7 @@ if test "$1" = "clean"; then find . -name '*.orig' -type f -print0 | xargs $ARGS rm -f rm -f aclocal.m4 build-stamp changelog-stamp config.cache config.log \ config.status configure configure-stamp install-sh libtool missing \ - mkinstalldirs quakeforge-config quakeforge.lsm + mkinstalldirs quakeforge-config quakeforge.lsm test-driver rm -f compile config.guess config.sub depcomp ltmain.sh ylwrap rm -rf autom4te.cache rm -f m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \ diff --git a/config.d/ac_config_files.m4 b/config.d/ac_config_files.m4 index 6f49d4bb5..d84505483 100644 --- a/config.d/ac_config_files.m4 +++ b/config.d/ac_config_files.m4 @@ -1,102 +1,4 @@ Makefile - - include/Makefile - include/QF/Makefile - - libs/Makefile - libs/audio/Makefile - libs/audio/targets/Makefile - libs/audio/renderer/Makefile - libs/audio/test/Makefile - libs/console/Makefile - libs/client/Makefile - libs/gamecode/Makefile - libs/gib/Makefile - libs/image/Makefile - libs/models/Makefile - libs/models/alias/Makefile - libs/models/brush/Makefile - libs/models/iqm/Makefile - libs/models/sprite/Makefile - libs/models/test/Makefile - libs/net/Makefile - libs/net/nc/Makefile - libs/net/nm/Makefile - libs/qw/Makefile - libs/ruamoko/Makefile - libs/util/Makefile - libs/util/test/Makefile - libs/video/Makefile - libs/video/renderer/Makefile - libs/video/renderer/gl/Makefile - libs/video/renderer/glsl/Makefile - libs/video/renderer/sw/Makefile - libs/video/renderer/sw32/Makefile - libs/video/targets/Makefile - - hw/Makefile - hw/include/Makefile - hw/source/Makefile - - nq/Makefile - nq/include/Makefile - nq/source/Makefile - - qtv/Makefile - qtv/include/Makefile - qtv/source/Makefile - - qw/Makefile - qw/include/Makefile - qw/source/Makefile - - tools/Makefile - tools/bsp2img/Makefile - tools/carne/Makefile - tools/pak/Makefile - tools/qfbsp/Makefile - tools/qfbsp/include/Makefile - tools/qfbsp/source/Makefile - tools/qfcc/Makefile - tools/qfcc/doc/Makefile - tools/qfcc/doc/man/Makefile - tools/qfcc/include/Makefile - tools/qfcc/source/Makefile - tools/qfcc/test/Makefile - tools/qflight/Makefile - tools/qflight/include/Makefile - tools/qflight/source/Makefile - tools/qflmp/Makefile - tools/qfmodelgen/Makefile - tools/qfmodelgen/include/Makefile - tools/qfmodelgen/source/Makefile - tools/qfspritegen/Makefile - tools/qfvis/Makefile - tools/qfvis/include/Makefile - tools/qfvis/source/Makefile - tools/wad/Makefile - tools/wav/Makefile - - ruamoko/Makefile - ruamoko/Doxyfile - ruamoko/include/Makefile - ruamoko/lib/Makefile - ruamoko/game/Makefile - ruamoko/gui/Makefile - ruamoko/cl_menu/Makefile - ruamoko/scheme/Makefile - ruamoko/qwaq/Makefile - - pkg-config/Makefile pkg-config/qfcc.pc pkg-config/quakeforge.pc - - doc/Makefile doc/quakeforge.dox.conf - doc/man/Makefile - - debian/Makefile - desktop/Makefile - - vc2005/Makefile - vc2008/Makefile diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 88b58e610..34227595f 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -39,7 +39,7 @@ if test "x$HAVE_FBDEV" = xyes; then QW_TARGETS="$QW_TARGETS qw-client-fbdev\$(EXEEXT)" NQ_TARGETS="$NQ_TARGETS nq-fbdev\$(EXEEXT)" CL_TARGETS="$CL_TARGETS FBDEV" - VID_TARGETS="$VID_TARGETS libQFfbdev.la" + VID_TARGETS="$VID_TARGETS libs/video/targets/libQFfbdev.la" QF_NEED(vid_render, [sw]) QF_NEED(models, [sw]) QF_NEED(alias, [sw]) @@ -66,11 +66,11 @@ if test "x$HAVE_X" = xyes; then if test "x$ENABLE_clients_x11" = xyes; then QW_TARGETS="$QW_TARGETS qw-client-x11\$(EXEEXT)" NQ_TARGETS="$NQ_TARGETS nq-x11\$(EXEEXT)" - QWAQ_TARGETS="$QWAQ_TARGETS qwaq-x11\$(EXEEXT)" - QW_DESKTOP_DATA="$QW_DESKTOP_DATA quakeforge-qw-x11.desktop" - NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA quakeforge-nq-x11.desktop" + QWAQ_TARGETS="$QWAQ_TARGETS ruamoko/qwaq/qwaq-x11\$(EXEEXT)" + QW_DESKTOP_DATA="$QW_DESKTOP_DATA desktop/quakeforge-qw-x11.desktop" + NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA desktop/quakeforge-nq-x11.desktop" CL_TARGETS="$CL_TARGETS X11" - VID_TARGETS="$VID_TARGETS libQFx11.la" + VID_TARGETS="$VID_TARGETS libs/video/targets/libQFx11.la" QF_NEED(vid_render, [sw sw32 gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) @@ -91,10 +91,10 @@ if test "x$HAVE_SDL" = xyes; then if test "x$ENABLE_clients_sdl" = xyes; then QW_TARGETS="$QW_TARGETS qw-client-sdl\$(EXEEXT)" NQ_TARGETS="$NQ_TARGETS nq-sdl\$(EXEEXT)" - QW_DESKTOP_DATA="$QW_DESKTOP_DATA quakeforge-qw-sdl.desktop" - NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA quakeforge-nq-sdl.desktop" + QW_DESKTOP_DATA="$QW_DESKTOP_DATA desktop/quakeforge-qw-sdl.desktop" + NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA desktop/quakeforge-nq-sdl.desktop" CL_TARGETS="$CL_TARGETS SDL" - VID_TARGETS="$VID_TARGETS libQFsdl.la" + VID_TARGETS="$VID_TARGETS libs/video/targets/libQFsdl.la" QF_NEED(vid_render, [sw sw32 gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) @@ -116,7 +116,7 @@ if test "x$HAVE_SVGA" = xyes; then QW_TARGETS="$QW_TARGETS qw-client-svga\$(EXEEXT)" NQ_TARGETS="$NQ_TARGETS nq-svga\$(EXEEXT)" CL_TARGETS="$CL_TARGETS SVGAlib" - VID_TARGETS="$VID_TARGETS libQFsvga.la" + VID_TARGETS="$VID_TARGETS libs/video/targets/libQFsvga.la" QF_NEED(vid_render, [sw]) QF_NEED(models, [sw]) QF_NEED(alias, [sw]) @@ -138,7 +138,7 @@ fi # QW_TARGETS="$QW_TARGETS qw-client-wgl\$(EXEEXT)" # NQ_TARGETS="$NQ_TARGETS nq-wgl\$(EXEEXT)" # CL_TARGETS="$CL_TARGETS WGL" -# VID_TARGETS="$VID_TARGETS libQFwgl.la" +# VID_TARGETS="$VID_TARGETS libs/video/targets/libQFwgl.la" # QF_NEED(vid_render, [gl]) # QF_NEED(models, [gl]) # QF_NEED(alias, [gl]) @@ -163,8 +163,8 @@ if test "x$ENABLE_servers_nq" = xyes; then QF_NEED(libs,[util gamecode ruamoko gib image models console net]) fi if test "x$ENABLE_servers_qtv" = xyes; then - QTV_TARGETS="qtv\$(EXEEXT) $QTV_TARGETS" - SV_TARGETS="$SV_TARGETS qtv" + QTV_TARGETS="qtv-server\$(EXEEXT) $QTV_TARGETS" + SV_TARGETS="$SV_TARGETS qtv-server" # QF_NEED(qtv, [common server]) QF_NEED(console, [server]) QF_NEED(top, [qtv]) @@ -228,7 +228,7 @@ if test "x$ENABLE_tools_qfvis" = xyes; then fi if test "x$ENABLE_tools_qwaq" = xyes; then if test "x$HAVE_PANEL" = xyes -a "x$HAVE_PTHREAD" = xyes; then - QWAQ_TARGETS="$QWAQ_TARGETS qwaq-curses\$(EXEEXT)" + QWAQ_TARGETS="$QWAQ_TARGETS ruamoko/qwaq/qwaq-curses\$(EXEEXT)" fi QF_NEED(tools,[qfcc]) QF_NEED(ruamoko,[qwaq]) @@ -254,14 +254,22 @@ QF_PROCESS_NEED_DIRS(ruamoko,[qwaq]) if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) - qfcc_include_qf="\$(qfcc_include_qf)" + qfac_qfcc_include_qf="\$(qfcc_include_qf)" fi -QF_SUBST(qfcc_include_qf) +QF_SUBST(qfac_qfcc_include_qf) if test x"${top_need_libs}" = xyes; then - include_qf="\$(include_qf)" + qfac_include_qf="\$(include_qf)" + qfac_include_qf_gl="\$(include_qf_gl)" + qfac_include_qf_glsl="\$(include_qf_glsl)" + qfac_include_qf_math="\$(include_qf_math)" + qfac_include_qf_plugin="\$(include_qf_plugin)" fi -QF_SUBST(include_qf) +QF_SUBST(qfac_include_qf) +QF_SUBST(qfac_include_qf_gl) +QF_SUBST(qfac_include_qf_glsl) +QF_SUBST(qfac_include_qf_math) +QF_SUBST(qfac_include_qf_plugin) progs_gz= if test "$HAVE_ZLIB" = "yes"; then @@ -273,21 +281,21 @@ QF_PROCESS_NEED_DIRS(top, [libs hw nq qtv qw tools ruamoko]) QF_PROCESS_NEED_LIBS(swrend, [asm]) QF_PROCESS_NEED_DIRS(vid_render, [gl glsl sw sw32]) -QF_PROCESS_NEED_LIBS(models, [gl glsl sw]) -QF_PROCESS_NEED_LIBS(alias, [gl glsl sw]) -QF_PROCESS_NEED_LIBS(brush, [gl glsl sw]) -QF_PROCESS_NEED_LIBS(iqm, [gl glsl sw]) -QF_PROCESS_NEED_LIBS(sprite, [gl glsl sw]) +QF_PROCESS_NEED_LIBS(models, [gl glsl sw], [libs/models]) +QF_PROCESS_NEED_LIBS(alias, [gl glsl sw], [libs/models/alias]) +QF_PROCESS_NEED_LIBS(brush, [gl glsl sw], [libs/models/brush]) +QF_PROCESS_NEED_LIBS(iqm, [gl glsl sw], [libs/models/iqm]) +QF_PROCESS_NEED_LIBS(sprite, [gl glsl sw], [libs/models/sprite]) -QF_PROCESS_NEED_LIBS(vid, [common sdl svga x11]) -QF_PROCESS_NEED_LIBS(qw, [client common sdl server], a) -QF_PROCESS_NEED_LIBS(nq, [client common sdl server], a) +QF_PROCESS_NEED_LIBS(vid, [common sdl svga x11], [libs/video/targets]) +QF_PROCESS_NEED_LIBS(qw, [client common sdl server], [qw/source], a) +QF_PROCESS_NEED_LIBS(nq, [client common sdl server], [nq/source], a) if test -n "$CL_TARGETS"; then - CD_TARGETS="libQFcd.la" - SND_TARGETS="libQFsound.la" + CD_TARGETS="libs/audio/libQFcd.la" + SND_TARGETS="libs/audio/libQFsound.la" AUDIO_TARGETS="testsound\$(EXEEXT)" - JOY_TARGETS="libQFjs.la" + JOY_TARGETS="libs/video/targets/libQFjs.la" else unset CDTYPE unset SOUND_TYPES @@ -322,13 +330,13 @@ if test "x$static_plugins" = xauto; then fi fi if test "x$static_plugins" = xyes; then - QF_PROCESS_NEED_STATIC_PLUGINS(vid_render, [sw sw32 glsl gl]) - QF_PROCESS_NEED_STATIC_PLUGINS(console, [server], [\$(top_builddir)/libs/console], [server]) - QF_PROCESS_NEED_STATIC_PLUGINS(console, [client], [\$(top_builddir)/libs/console], [client]) + QF_PROCESS_NEED_STATIC_PLUGINS(vid_render, [sw sw32 glsl gl], [libs/video/renderer]) + QF_PROCESS_NEED_STATIC_PLUGINS(console, [server], [libs/console], [server]) + QF_PROCESS_NEED_STATIC_PLUGINS(console, [client], [libs/console], [client]) - QF_PROCESS_NEED_STATIC_PLUGINS(snd_output, [sdl mme sgi sun win dx oss alsa], [targets]) - QF_PROCESS_NEED_STATIC_PLUGINS(snd_render, [jack default], [renderer]) - QF_PROCESS_NEED_STATIC_PLUGINS(cd, [xmms sdl sgi win linux file]) + QF_PROCESS_NEED_STATIC_PLUGINS(snd_output, [sdl mme sgi sun win dx oss alsa], [libs/audio/targets]) + QF_PROCESS_NEED_STATIC_PLUGINS(snd_render, [jack default], [libs/audio/renderer]) + QF_PROCESS_NEED_STATIC_PLUGINS(cd, [xmms sdl sgi win linux file], [libs/audio]) AC_DEFINE(STATIC_PLUGINS, 1, [Define this if you are building static plugins]) if test -n "$SOUND_TYPES"; then SOUND_TYPES="$SOUND_TYPES (static)" @@ -337,12 +345,12 @@ if test "x$static_plugins" = xyes; then CDTYPE="$CDTYPE (static)" fi else - QF_PROCESS_NEED_PLUGINS(vid_render, [sw sw32 glsl gl]) - QF_PROCESS_NEED_PLUGINS(console, [server], [server]) - QF_PROCESS_NEED_PLUGINS(console, [client], [client]) - QF_PROCESS_NEED_PLUGINS(snd_output, [sdl mme sgi sun win dx oss alsa]) - QF_PROCESS_NEED_PLUGINS(snd_render, [jack default]) - QF_PROCESS_NEED_PLUGINS(cd, [xmms sdl sgi win linux file]) + QF_PROCESS_NEED_PLUGINS(vid_render, [sw sw32 glsl gl], [libs/video/renderer]) + QF_PROCESS_NEED_PLUGINS(console, [server], [libs/console], [server]) + QF_PROCESS_NEED_PLUGINS(console, [client], [libs/console], [client]) + QF_PROCESS_NEED_PLUGINS(snd_output, [sdl mme sgi sun win dx oss alsa], [libs/audio/targets]) + QF_PROCESS_NEED_PLUGINS(snd_render, [jack default], [libs/audio/renderer]) + QF_PROCESS_NEED_PLUGINS(cd, [xmms sdl sgi win linux file], [libs/audio]) fi dnl Do not use -module here, it belongs in makefile.am due to automake @@ -419,7 +427,7 @@ QF_DEPS(QFVIS, [$(WIN32_LIBS)], ) QF_DEPS(QWAQ, - [], + [-I$(top_srcdir)/ruamoko/qwaq], [$(top_builddir)/libs/ruamoko/libQFruamoko.la $(top_builddir)/libs/gamecode/libQFgamecode.la $(top_builddir)/libs/util/libQFutil.la], diff --git a/config.d/rpm.m4 b/config.d/rpm.m4 index 95ac34cf7..d4406cf2a 100644 --- a/config.d/rpm.m4 +++ b/config.d/rpm.m4 @@ -1,2 +1,2 @@ -AC_CONFIG_FILES(RPM/Makefile RPM/quakeforge.conf RPM/quakeforge.spec) +AC_CONFIG_FILES(RPM/quakeforge.conf RPM/quakeforge.spec) AC_CONFIG_FILES(RPM/build_rpm, [chmod +x RPM/build_rpm]) diff --git a/configure.ac b/configure.ac index ea203472c..591470b23 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.61) dnl This is the only place where the package name and version appear AC_INIT([QuakeForge], m4_esyscmd([config.d/git-version-gen --prefix '' .tarball-version])) -AM_INIT_AUTOMAKE([foreign]) +AM_INIT_AUTOMAKE([foreign subdir-objects]) dnl LT_INIT messes with CFLAGS (evil bastard) if test "x${CFLAGS-unset}" = xunset; then diff --git a/debian/Makefile.am b/debian/Makefile.am deleted file mode 100644 index ec13849c4..000000000 --- a/debian/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -# find -type f | sed -e 's:^\./::g' | grep -v Makefile | sort >> Makefile.am - -EXTRA_DIST= \ - changelog control copyright quakeforge.conf rules source/format \ - qfcc.install \ - quakeforge-alsa.install quakeforge-alsa.postinst quakeforge-alsa.prerm \ - quakeforge-common.install quakeforge-common.postinst \ - quakeforge-dev.install \ - quakeforge-gl.install \ - quakeforge-glsl.install \ - quakeforge-jack.install \ - quakeforge-maptools.install \ - quakeforge-oss.install quakeforge-oss.postinst quakeforge-oss.prerm \ - quakeforge-sdl.install \ - quakeforge-servers.install \ - quakeforge-stub.postinst \ - quakeforge-sw32.install \ - quakeforge-sw.install \ - quakeforge-utils.install \ - quakeforge-x11.install diff --git a/debian/Makemodule.am b/debian/Makemodule.am new file mode 100644 index 000000000..9ef80d06a --- /dev/null +++ b/debian/Makemodule.am @@ -0,0 +1,28 @@ +EXTRA_DIST += \ + debian/changelog \ + debian/control \ + debian/copyright \ + debian/quakeforge.conf \ + debian/rules \ + debian/source/format \ + debian/qfcc.install \ + debian/quakeforge-alsa.install \ + debian/quakeforge-alsa.postinst \ + debian/quakeforge-alsa.prerm \ + debian/quakeforge-common.install \ + debian/quakeforge-common.postinst \ + debian/quakeforge-dev.install \ + debian/quakeforge-gl.install \ + debian/quakeforge-glsl.install \ + debian/quakeforge-jack.install \ + debian/quakeforge-maptools.install \ + debian/quakeforge-oss.install \ + debian/quakeforge-oss.postinst \ + debian/quakeforge-oss.prerm \ + debian/quakeforge-sdl.install \ + debian/quakeforge-servers.install \ + debian/quakeforge-stub.postinst \ + debian/quakeforge-sw32.install \ + debian/quakeforge-sw.install \ + debian/quakeforge-utils.install \ + debian/quakeforge-x11.install diff --git a/desktop/Makefile.am b/desktop/Makefile.am deleted file mode 100644 index 5aa61578b..000000000 --- a/desktop/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -## Process this file with automake to produce Makefile.in -# -# Makefile.am -# -# Automake-using build system for QuakeForge -# -# Copyright (C) 2000 Jeff Teunissen -# -# This Makefile 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 2 -# 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, write to: -# -# Free Software Foundation, Inc. -# 59 Temple Place - Suite 330 -# Boston, MA 02111-1307, USA -# -# $Id$ -# - -AUTOMAKE_OPTIONS= foreign - -# Stuff that is common to both client and server -# Desktop files -if HAVE_XDG -desktopdir=$(datarootdir)/applications -desktop_DATA= @NQ_DESKTOP_DATA@ @QW_DESKTOP_DATA@ -endif - -# Stuff that doesn't get linked into an executable NEEDS to be mentioned here, -# or it won't be distributed with 'make dist' - -EXTRA_DIST= quakeforge-nq-glx.desktop quakeforge-nq-sdl.desktop \ - quakeforge-nq-sdl32.desktop quakeforge-nq-sgl.desktop \ - quakeforge-nq-x11.desktop quakeforge-qw-glx.desktop \ - quakeforge-qw-sdl.desktop quakeforge-qw-sdl32.desktop \ - quakeforge-qw-sgl.desktop quakeforge-qw-x11.desktop - -# Kill the temp files, hopefully. -CLEANFILES = *.i *.s $(YACCLEX_CLEANFILES) diff --git a/desktop/Makemodule.am b/desktop/Makemodule.am new file mode 100644 index 000000000..bb0acd969 --- /dev/null +++ b/desktop/Makemodule.am @@ -0,0 +1,10 @@ +if HAVE_XDG +desktopdir=$(datarootdir)/applications +desktop_DATA = @NQ_DESKTOP_DATA@ @QW_DESKTOP_DATA@ +endif + +EXTRA_DIST += \ + desktop/quakeforge-nq-sdl.desktop \ + desktop/quakeforge-nq-x11.desktop \ + desktop/quakeforge-qw-sdl.desktop \ + desktop/quakeforge-qw-x11.desktop diff --git a/desktop/quakeforge-nq-glx.desktop b/desktop/quakeforge-nq-glx.desktop deleted file mode 100644 index 67c4ca509..000000000 --- a/desktop/quakeforge-nq-glx.desktop +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -Version=1.0 - -Type=Application - -Name=QuakeForge (GLX) -GenericName=Quake (GLX) -Comment=A first person shooter game -Comment[fr]=Un jeu de tir subjectif -Comment[it]=Sparatutto in prima persona -Icon=quake - -Categories=Game;ActionGame; - -Exec=nq-glx -TryExec=nq-glx -Terminal=false -StartupNotify=false diff --git a/desktop/quakeforge-nq-sdl32.desktop b/desktop/quakeforge-nq-sdl32.desktop deleted file mode 100644 index f39050155..000000000 --- a/desktop/quakeforge-nq-sdl32.desktop +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -Version=1.0 - -Type=Application - -Name=QuakeForge (SDL32) -GenericName=Quake (SDL32) -Comment=A first person shooter game -Comment[fr]=Un jeu de tir subjectif -Comment[it]=Sparatutto in prima persona -Icon=quake - -Categories=SDL;Game;ActionGame; - -Exec=nq-sdl32 -TryExec=nq-sdl32 -Terminal=false -StartupNotify=false diff --git a/desktop/quakeforge-nq-sgl.desktop b/desktop/quakeforge-nq-sgl.desktop deleted file mode 100644 index 82645eeb6..000000000 --- a/desktop/quakeforge-nq-sgl.desktop +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -Version=1.0 - -Type=Application - -Name=QuakeForge (SDL GL) -GenericName=Quake (SDL GL) -Comment=A first person shooter game -Comment[fr]=Un jeu de tir subjectif -Comment[it]=Sparatutto in prima persona -Icon=quake - -Categories=SDL;Game;ActionGame; - -Exec=nq-sgl -TryExec=nq-sgl -Terminal=false -StartupNotify=false diff --git a/desktop/quakeforge-qw-glx.desktop b/desktop/quakeforge-qw-glx.desktop deleted file mode 100644 index fab7cab4e..000000000 --- a/desktop/quakeforge-qw-glx.desktop +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -Version=1.0 - -Type=Application - -Name=QuakeForge QuakeWorld (GLX) -GenericName=QuakeWorld (GLX) -Comment=A first person shooter game -Comment[fr]=Un jeu de tir subjectif -Comment[it]=Sparatutto in prima persona -Icon=quake - -Categories=Game;ActionGame; - -Exec=qw-client-glx -TryExec=qw-client-glx -Terminal=false -StartupNotify=false diff --git a/desktop/quakeforge-qw-sdl32.desktop b/desktop/quakeforge-qw-sdl32.desktop deleted file mode 100644 index d2862ecb6..000000000 --- a/desktop/quakeforge-qw-sdl32.desktop +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -Version=1.0 - -Type=Application - -Name=QuakeForge QuakeWorld (SDL32) -GenericName=QuakeWorld (SDL32) -Comment=A first person shooter game -Comment[fr]=Un jeu de tir subjectif -Comment[it]=Sparatutto in prima persona -Icon=quake - -Categories=SDL;Game;ActionGame; - -Exec=qw-client-sdl32 -TryExec=qw-client-sdl32 -Terminal=false -StartupNotify=false diff --git a/desktop/quakeforge-qw-sgl.desktop b/desktop/quakeforge-qw-sgl.desktop deleted file mode 100644 index 36ae08f24..000000000 --- a/desktop/quakeforge-qw-sgl.desktop +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -Version=1.0 - -Type=Application - -Name=QuakeForge QuakeWorld (SDL GL) -GenericName=QuakeWorld (SDL GL) -Comment=A first person shooter game -Comment[fr]=Un jeu de tir subjectif -Comment[it]=Sparatutto in prima persona -Icon=quake - -Categories=SDL;Game;ActionGame; - -Exec=qw-client-sgl -TryExec=qw-client-sgl -Terminal=false -StartupNotify=false diff --git a/doc/Makefile.am b/doc/Makefile.am deleted file mode 100644 index 8511d72f3..000000000 --- a/doc/Makefile.am +++ /dev/null @@ -1,55 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= man - -DOX= \ - bind.dox config.dox connect.dox cshifts.dox dirconf.dox faq.dox \ - filesystem.dox mapformat.dox property-list.dox qtv.dox quakeforge.dox \ - qw-cap-spec.dox qw-download-spec.dox sound.dox specifications.dox \ - surround-sound.dox timestamps.dox - -GIB= \ - gib/GIB.lyx gib/break.gib gib/continue.gib gib/curly.gib gib/examples.sh \ - gib/for.gib gib/gib_head.eps gib/if-chain.gib gib/if-else.gib \ - gib/if-simple.gib gib/while.gib - -PROGS= \ - progs/vm-exec.c progs/vm-mem.fig - -EXTRA_DIST= qf.ico \ - \ - skybox.fig template.c template.h \ - quakeforge.dox.conf.in \ - \ - ${DOX} ${GIB} ${PROGS} \ - \ - config/glspeed-v1.cfg config/glspeed-v3.cfg config/swspeed.cfg \ - \ - config/gib/adjustvolume.gib config/gib/infobot.gib config/gib/ln.gib \ - config/gib/qfadmin.gib config/gib/sshot.gib config/gib/zoom.gib \ - \ - qtv/qwtv.fig - -SUFFIXES=.eps .fig .png -.fig.png: - @mkdir -p `dirname $@` - fig2dev -L png $< $@ - -.fig.eps: - @mkdir -p `dirname $@` - fig2dev -L ps $< $@ - -.fig.svg: - @mkdir -p `dirname $@` - fig2dev -L svg $< $@ - -clean-local: - -rm -fr doxygen - -progs/vm-mem.svg: progs/vm-mem.fig -progs/vm-mem.eps: progs/vm-mem.fig -qtv/qwtv.svg: qtv/qwtv.fig -qtv/qwtv.eps: qtv/qwtv.fig - -doc: quakeforge.dox.conf progs/vm-mem.svg progs/vm-mem.eps qtv/qwtv.svg qtv/qwtv.eps ${DOX} - doxygen quakeforge.dox.conf diff --git a/doc/Makemodule.am b/doc/Makemodule.am new file mode 100644 index 000000000..b26d57841 --- /dev/null +++ b/doc/Makemodule.am @@ -0,0 +1,80 @@ +man_MANS += doc/man/quakeforge.1 + +DOX= \ + doc/bind.dox \ + doc/config.dox \ + doc/connect.dox \ + doc/cshifts.dox \ + doc/dirconf.dox \ + doc/faq.dox \ + doc/filesystem.dox \ + doc/mapformat.dox \ + doc/property-list.dox \ + doc/qtv.dox \ + doc/quakeforge.dox \ + doc/qw-cap-spec.dox \ + doc/qw-download-spec.dox \ + doc/sound.dox \ + doc/specifications.dox \ + doc/surround-sound.dox \ + doc/timestamps.dox + +GIB= \ + doc/gib/GIB.lyx \ + doc/gib/break.gib \ + doc/gib/continue.gib \ + doc/gib/curly.gib \ + doc/gib/examples.sh \ + doc/gib/for.gib \ + doc/gib/gib_head.eps \ + doc/gib/if-chain.gib \ + doc/gib/if-else.gib \ + doc/gib/if-simple.gib \ + doc/gib/while.gib + +PROGS= \ + doc/progs/vm-exec.c \ + doc/progs/vm-mem.fig + +EXTRA_DIST += \ + ${DOX} ${GIB} ${PROGS} \ + doc/qf.ico \ + doc/skybox.fig \ + doc/template.c \ + doc/template.h \ + doc/quakeforge.dox.conf.in \ + doc/config/glspeed-v1.cfg \ + doc/config/glspeed-v3.cfg \ + doc/config/swspeed.cfg \ + doc/config/gib/adjustvolume.gib \ + doc/config/gib/infobot.gib \ + doc/config/gib/ln.gib \ + doc/config/gib/qfadmin.gib \ + doc/config/gib/sshot.gib \ + doc/config/gib/zoom.gib \ + doc/man/quakeforge.1 \ + doc/qtv/qwtv.fig + +SUFFIXES += .eps .fig .png +.fig.png: + @mkdir -p `dirname $@` + fig2dev -L png $< $@ + +.fig.eps: + @mkdir -p `dirname $@` + fig2dev -L ps $< $@ + +.fig.svg: + @mkdir -p `dirname $@` + fig2dev -L svg $< $@ + +clean-local: + -rm -fr doxygen + +doc/progs/vm-mem.svg: doc/progs/vm-mem.fig +doc/progs/vm-mem.eps: doc/progs/vm-mem.fig +doc/qtv/qwtv.svg: doc/qtv/qwtv.fig +doc/qtv/qwtv.eps: doc/qtv/qwtv.fig + +doc: doc/quakeforge.dox.conf doc/progs/vm-mem.svg doc/progs/vm-mem.eps doc/qtv/qwtv.svg qtv/qwtv.eps ${DOX} + doxygen doc/quakeforge.dox.conf diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am deleted file mode 100644 index 5249e3a26..000000000 --- a/doc/man/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST= quakeforge.1 diff --git a/hw/Makefile.am b/hw/Makefile.am deleted file mode 100644 index 77e3cbf5b..000000000 --- a/hw/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= include source diff --git a/hw/Makemodule.am b/hw/Makemodule.am new file mode 100644 index 000000000..cfd2f1e31 --- /dev/null +++ b/hw/Makemodule.am @@ -0,0 +1 @@ +include hw/source/Makemodule.am diff --git a/hw/include/Makefile.am b/hw/include/Makefile.am deleted file mode 100644 index b36df17ad..000000000 --- a/hw/include/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST = diff --git a/hw/source/Makefile.am b/hw/source/Makemodule.am similarity index 69% rename from hw/source/Makefile.am rename to hw/source/Makemodule.am index d5ad0658e..9f86d3283 100644 --- a/hw/source/Makefile.am +++ b/hw/source/Makemodule.am @@ -27,27 +27,17 @@ # $Id$ # -AUTOMAKE_OPTIONS= foreign +bin_PROGRAMS += @HW_TARGETS@ -# Stuff that is common to both client and server -AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/hw/include -SDL_LIBS = @SDL_LIBS@ +EXTRA_PROGRAMS += hw-master -bin_PROGRAMS= @HW_TARGETS@ - -EXTRA_PROGRAMS= hw-master - -common_ldflags= -export-dynamic hw_master_libs= \ - $(top_builddir)/libs/net/libnet_chan.la \ + libs/net/libnet_chan.la \ @server_static_plugin_libs@ \ - $(top_builddir)/libs/console/libQFconsole.la \ - $(top_builddir)/libs/util/libQFutil.la + libs/console/libQFconsole.la \ + libs/util/libQFutil.la hw_master_LDFLAGS= $(common_ldflags) hw_master_LDADD= $(hw_master_libs) $(NET_LIBS) hw_master_DEPENDENCIES= $(hw_master_libs) -hw_master_SOURCES= master.c - -# Kill the temp files, hopefully. -CLEANFILES = *.i *.s +hw_master_SOURCES= hw/source/master.c diff --git a/include/Makefile.am b/include/Makefile.am deleted file mode 100644 index 56b084ae1..000000000 --- a/include/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign -SUBDIRS = QF -EXTRA_DIST = \ - adivtab.h alsa_funcs_list.h anorm_dots.h anorms.h asm_draw.h asm_i386.h \ - block16.h block8.h buildnum.h clview.h compat.h context_sdl.h \ - context_x11.h d_iface.h d_ifacea.h d_local.h dga_check.h exp.h fbset.h \ - garbage.h getopt.h gib_buffer.h gib_builtin.h gib_classes.h \ - gib_execute.h gib_function.h gib_handle.h gib_object.h gib_parse.h \ - gib_process.h gib_regex.h gib_semantics.h gib_thread.h gib_tree.h \ - gib_vars.h gl_warp_sin.h in_win.h logos.h mod_internal.h net_dgrm.h \ - net_loop.h net_udp.h net_vcr.h net_wins.h netchan.h netmain.h \ - noisetextures.h old_keys.h ops.h pstdint.h qfalloca.h qstring.h \ - quakeasm.h r_cvar.h r_dynamic.h r_internal.h r_local.h r_screen.h \ - r_shared.h regex.h rua_internal.h sbar.h skin_stencil.h snd_internal.h \ - sv_console.h varrays.h vgamodes.h vid_internal.h vregset.h winquake.h \ - world.h \ - \ - client/entities.h \ - \ - qw/bothdefs.h qw/msg_backbuf.h qw/msg_ucmd.h qw/pmove.h qw/protocol.h \ - \ - win32/dirent.h win32/fnmatch.h win32/stdint.h \ - \ - win32/resources/icon1Vista.ico win32/resources/icon1XP.ico \ - win32/resources/quakeforge.rc win32/resources/resource.h diff --git a/include/Makemodule.am b/include/Makemodule.am new file mode 100644 index 000000000..ac6108f67 --- /dev/null +++ b/include/Makemodule.am @@ -0,0 +1,88 @@ +## Process this file with automake to produce Makefile.in +include include/QF/Makemodule.am + +EXTRA_DIST += \ + include/adivtab.h \ + include/alsa_funcs_list.h \ + include/anorm_dots.h \ + include/anorms.h \ + include/asm_draw.h \ + include/asm_i386.h \ + include/block16.h \ + include/block8.h \ + include/buildnum.h \ + include/clview.h \ + include/compat.h \ + include/context_sdl.h \ + include/context_x11.h \ + include/d_iface.h \ + include/d_ifacea.h \ + include/d_local.h \ + include/dga_check.h \ + include/exp.h \ + include/fbset.h \ + include/garbage.h \ + include/getopt.h \ + include/gib_buffer.h \ + include/gib_builtin.h \ + include/gib_classes.h \ + include/gib_execute.h \ + include/gib_function.h \ + include/gib_handle.h \ + include/gib_object.h \ + include/gib_parse.h \ + include/gib_process.h \ + include/gib_regex.h \ + include/gib_semantics.h \ + include/gib_thread.h \ + include/gib_tree.h \ + include/gib_vars.h \ + include/gl_warp_sin.h \ + include/in_win.h \ + include/logos.h \ + include/mod_internal.h \ + include/net_dgrm.h \ + include/net_loop.h \ + include/net_udp.h \ + include/net_vcr.h \ + include/net_wins.h \ + include/netchan.h \ + include/netmain.h \ + include/noisetextures.h \ + include/old_keys.h \ + include/ops.h \ + include/pstdint.h \ + include/qfalloca.h \ + include/qstring.h \ + include/quakeasm.h \ + include/r_cvar.h \ + include/r_dynamic.h \ + include/r_internal.h \ + include/r_local.h \ + include/r_screen.h \ + include/r_shared.h \ + include/regex.h \ + include/rua_internal.h \ + include/sbar.h \ + include/skin_stencil.h \ + include/snd_internal.h \ + include/sv_console.h \ + include/varrays.h \ + include/vgamodes.h \ + include/vid_internal.h \ + include/vregset.h \ + include/winquake.h \ + include/world.h \ + include/client/entities.h \ + include/qw/bothdefs.h \ + include/qw/msg_backbuf.h \ + include/qw/msg_ucmd.h \ + include/qw/pmove.h \ + include/qw/protocol.h \ + include/win32/dirent.h \ + include/win32/fnmatch.h \ + include/win32/stdint.h \ + include/win32/resources/icon1Vista.ico \ + include/win32/resources/icon1XP.ico \ + include/win32/resources/quakeforge.rc \ + include/win32/resources/resource.h diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am deleted file mode 100644 index bb6b0d2da..000000000 --- a/include/QF/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -AUTOMAKE_OPTIONS = foreign -pkgincludedir = $(includedir)/QF -#for header files that qfcc (ruamoko) will use -pkgdatadir = $(datarootdir)/qfcc/include/QF - -include_qf= \ - alloc.h bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \ - console.h crc.h csqc.h cvar.h darray.h dstring.h draw.h gib.h hash.h \ - idparse.h image.h in_event.h info.h input.h iqm.h joystick.h keys.h \ - link.h llist.h locs.h mathlib.h mdfour.h mersenne.h model.h modelgen.h \ - msg.h object.h pak.h pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h \ - pr_obj.h pr_type.h progs.h qargs.h qdefs.h qendian.h qfplist.h qtypes.h \ - quakefs.h \ - quakeio.h render.h riff.h ringbuffer.h ruamoko.h \ - screen.h script.h segtext.h set.h \ - sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h tga.h va.h \ - ver_check.h vid.h vrect.h view.h wad.h wadfile.h winding.h zone.h \ - \ - GL/ati.h GL/defines.h GL/extensions.h GL/funcs.h GL/qf_draw.h \ - GL/qf_explosions.h GL/qf_funcs_list.h GL/qf_iqm.h GL/qf_lightmap.h \ - GL/qf_rlight.h GL/qf_rmain.h GL/qf_rsurf.h GL/qf_sky.h GL/qf_textures.h \ - GL/qf_vid.h GL/types.h \ - \ - GLSL/defines.h GLSL/funcs.h GLSL/qf_alias.h GLSL/qf_bsp.h GLSL/qf_draw.h \ - GLSL/qf_funcs_list.h GLSL/qf_iqm.h GLSL/qf_lightmap.h GLSL/qf_particles.h \ - GLSL/qf_textures.h GLSL/qf_vid.h GLSL/types.h \ - \ - math/dual.h math/half.h math/matrix3.h math/matrix4.h math/quaternion.h \ - math/vector.h \ - \ - plugin/cd.h plugin/console.h plugin/general.h plugin/input.h \ - plugin/snd_output.h plugin/snd_render.h plugin/vid_render.h - -qfcc_include_qf=keys.h -nobase_pkginclude_HEADERS = @include_qf@ -pkgdata_DATA=@qfcc_include_qf@ - -EXTRA_HEADERS = $(include_qf) $(qfcc_include_qf) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am new file mode 100644 index 000000000..5ef2c4423 --- /dev/null +++ b/include/QF/Makemodule.am @@ -0,0 +1,151 @@ +include_qf = \ + include/QF/alloc.h \ + include/QF/bspfile.h \ + include/QF/cbuf.h \ + include/QF/cdaudio.h \ + include/QF/checksum.h \ + include/QF/clip_hull.h \ + include/QF/cmd.h \ + include/QF/console.h \ + include/QF/crc.h \ + include/QF/csqc.h \ + include/QF/cvar.h \ + include/QF/darray.h \ + include/QF/dstring.h \ + include/QF/draw.h \ + include/QF/gib.h \ + include/QF/hash.h \ + include/QF/idparse.h \ + include/QF/image.h \ + include/QF/in_event.h \ + include/QF/info.h \ + include/QF/input.h \ + include/QF/iqm.h \ + include/QF/joystick.h \ + include/QF/keys.h \ + include/QF/link.h \ + include/QF/llist.h \ + include/QF/locs.h \ + include/QF/mathlib.h \ + include/QF/mdfour.h \ + include/QF/mersenne.h \ + include/QF/model.h \ + include/QF/modelgen.h \ + include/QF/msg.h \ + include/QF/object.h \ + include/QF/pak.h \ + include/QF/pakfile.h \ + include/QF/pcx.h \ + include/QF/png.h \ + include/QF/plugin.h \ + include/QF/pr_comp.h \ + include/QF/pr_debug.h \ + include/QF/pr_obj.h \ + include/QF/pr_type.h \ + include/QF/progs.h \ + include/QF/qargs.h \ + include/QF/qdefs.h \ + include/QF/qendian.h \ + include/QF/qfplist.h \ + include/QF/qtypes.h \ + include/QF/quakefs.h \ + include/QF/quakeio.h \ + include/QF/render.h \ + include/QF/riff.h \ + include/QF/ringbuffer.h \ + include/QF/ruamoko.h \ + include/QF/screen.h \ + include/QF/script.h \ + include/QF/segtext.h \ + include/QF/set.h \ + include/QF/sizebuf.h \ + include/QF/skin.h \ + include/QF/sound.h \ + include/QF/spritegn.h \ + include/QF/sys.h \ + include/QF/teamplay.h \ + include/QF/tga.h \ + include/QF/txtbuffer.h \ + include/QF/va.h \ + include/QF/ver_check.h \ + include/QF/vid.h \ + include/QF/vrect.h \ + include/QF/view.h \ + include/QF/wad.h \ + include/QF/wadfile.h \ + include/QF/winding.h \ + include/QF/zone.h + +include_qf_gl = \ + include/QF/GL/ati.h \ + include/QF/GL/defines.h \ + include/QF/GL/extensions.h \ + include/QF/GL/funcs.h \ + include/QF/GL/qf_draw.h \ + include/QF/GL/qf_explosions.h \ + include/QF/GL/qf_funcs_list.h \ + include/QF/GL/qf_iqm.h \ + include/QF/GL/qf_lightmap.h \ + include/QF/GL/qf_rlight.h \ + include/QF/GL/qf_rmain.h \ + include/QF/GL/qf_rsurf.h \ + include/QF/GL/qf_sky.h \ + include/QF/GL/qf_textures.h \ + include/QF/GL/qf_vid.h \ + include/QF/GL/types.h + +include_qf_glsl = \ + include/QF/GLSL/defines.h \ + include/QF/GLSL/funcs.h \ + include/QF/GLSL/qf_alias.h \ + include/QF/GLSL/qf_bsp.h \ + include/QF/GLSL/qf_draw.h \ + include/QF/GLSL/qf_funcs_list.h \ + include/QF/GLSL/qf_iqm.h \ + include/QF/GLSL/qf_lightmap.h \ + include/QF/GLSL/qf_particles.h \ + include/QF/GLSL/qf_textures.h \ + include/QF/GLSL/qf_vid.h \ + include/QF/GLSL/types.h + +include_qf_math = \ + include/QF/math/dual.h \ + include/QF/math/half.h \ + include/QF/math/matrix3.h \ + include/QF/math/matrix4.h \ + include/QF/math/quaternion.h \ + include/QF/math/vector.h + +include_qf_plugin = \ + include/QF/plugin/cd.h \ + include/QF/plugin/console.h \ + include/QF/plugin/general.h \ + include/QF/plugin/input.h \ + include/QF/plugin/snd_output.h \ + include/QF/plugin/snd_render.h \ + include/QF/plugin/vid_render.h + +# headers shared with ruamoko +qfcc_include_qf = include/QF/keys.h + +qf_includedir = $(includedir)/QF +qf_gl_includedir = $(includedir)/QF/GL +qf_glsl_includedir = $(includedir)/QF/GLSL +qf_math_includedir = $(includedir)/QF/math +qf_plugin_includedir = $(includedir)/QF/plugin +qf_include_HEADERS = @qfac_include_qf@ +qf_gl_include_HEADERS = @qfac_include_qf_gl@ +qf_glsl_include_HEADERS = @qfac_include_qf_glsl@ +qf_math_include_HEADERS = @qfac_include_qf_math@ +qf_plugin_include_HEADERS = @qfac_include_qf_plugin@ + +ruamoko_qf_includedir = $(ruamoko_includedir)/QF +ruamoko_qf_include_HEADERS = @qfac_qfcc_include_qf@ + +EXTRA_HEADERS += \ + $(include_qf) \ + $(include_qf_gl) \ + $(include_qf_glsl) \ + $(include_qf_math) \ + $(include_qf_plugin) \ + $(qfcc_include_qf) diff --git a/libs/Makefile.am b/libs/Makefile.am deleted file mode 100644 index 5c14c7d00..000000000 --- a/libs/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -# everything depends on util -# ruamoko depends on gamecode -# gib depends on ruamoko -# audio depends on gamecode -# models depends on image -# video depends on models(?), image(?) and ruamoko -# console depends on video, ruamoko and audio -SUBDIRS=@libs_dirs@ -DIST_SUBDIRS=util gamecode ruamoko gib audio image models video console \ - net qw client diff --git a/libs/Makemodule.am b/libs/Makemodule.am new file mode 100644 index 000000000..5a68c67ba --- /dev/null +++ b/libs/Makemodule.am @@ -0,0 +1,13 @@ +include libs/util/Makemodule.am +include libs/gamecode/Makemodule.am +include libs/ruamoko/Makemodule.am +include libs/gib/Makemodule.am +include libs/audio/Makemodule.am +include libs/image/Makemodule.am +include libs/models/Makemodule.am +include libs/video/Makemodule.am +include libs/console/Makemodule.am + +include libs/net/Makemodule.am +include libs/client/Makemodule.am +include libs/qw/Makemodule.am diff --git a/libs/audio/Makefile.am b/libs/audio/Makefile.am deleted file mode 100644 index 5521b3e2f..000000000 --- a/libs/audio/Makefile.am +++ /dev/null @@ -1,77 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= targets renderer . test -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include -SDL_LIBS= @SDL_LIBS@ -XMMS_LIBS= @XMMS_LIBS@ -plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) -plugin_libadd= @plugin_libadd@ -lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ - -rpath $(libdir) -no-undefined -EXEEXT= - -plugin_LTLIBRARIES= @cd_plugins@ -noinst_LTLIBRARIES= @cd_static_plugins@ -lib_LTLIBRARIES= @CD_TARGETS@ @SND_TARGETS@ -EXTRA_LTLIBRARIES= libQFsound.la libQFcd.la \ - cd_file.la cd_linux.la cd_sdl.la cd_sgi.la cd_win.la \ - cd_xmms.la - -cd_plug_libs=$(top_builddir)/libs/util/libQFutil.la - -cd_file_libs= \ - libQFsound.la \ - $(cd_plug_libs) - -cd_file_la_LDFLAGS= $(plugin_ldflags) -cd_file_la_LIBADD= $(cd_file_libs) -cd_file_la_DEPENDENCIES= $(cd_file_libs) -cd_file_la_SOURCES= cd_file.c - -cd_linux_la_LDFLAGS= $(plugin_ldflags) -cd_linux_la_LIBADD= $(cd_plug_libs) -cd_linux_la_DEPENDENCIES= $(cd_plug_libs) -cd_linux_la_SOURCES= cd_linux.c - -cd_sdl_la_LDFLAGS= $(plugin_ldflags) -cd_sdl_la_LIBADD= $(cd_plug_libs) $(SDL_LIBS) $(plugin_libadd) -cd_sdl_la_DEPENDENCIES= $(cd_plug_libs) -cd_sdl_la_CFLAGS= $(SDL_CFLAGS) -cd_sdl_la_SOURCES= cd_sdl.c - -cd_sgi_la_LDFLAGS= $(plugin_ldflags) -cd_sgi_la_LIBADD= $(cd_plug_libs) $(SGI_CD_LIBS) -cd_sgi_la_DEPENDENCIES= $(cd_plug_libs) -cd_sgi_la_SOURCES= cd_sgi.c - -cd_win_la_LDFLAGS= $(plugin_ldflags) -cd_win_la_LIBADD= $(cd_plug_libs) $(plugin_libadd) -cd_win_la_DEPENDENCIES= $(cd_plug_libs) -cd_win_la_SOURCES= cd_win.c - -cd_xmms_la_LDFLAGS= $(plugin_ldflags) -cd_xmms_la_LIBADD= $(cd_plug_libs) $(XMMS_LIBS) -cd_xmms_la_DEPENDENCIES= $(cd_plug_libs) -cd_xmms_la_CFLAGS= $(XMMS_CFLAGS) -cd_xmms_la_SOURCES= cd_xmms.c - -sound_libs= \ - @snd_output_static_plugin_libs@ \ - @snd_render_static_plugin_libs@ \ - $(top_builddir)/libs/ruamoko/libQFruamoko.la \ - $(top_builddir)/libs/util/libQFutil.la - -cd_libs= \ - @cd_static_plugin_libs@ \ - $(top_builddir)/libs/util/libQFutil.la - -libQFsound_la_LDFLAGS= $(lib_ldflags) -libQFsound_la_LIBADD= $(sound_libs) -libQFsound_la_DEPENDENCIES= $(sound_libs) -libQFsound_la_SOURCES= snd.c snd_progs.c - -libQFcd_la_LDFLAGS= $(lib_ldflags) -libQFcd_la_LIBADD= $(cd_libs) -libQFcd_la_DEPENDENCIES= $(cd_libs) -libQFcd_la_SOURCES= cd.c diff --git a/libs/audio/Makemodule.am b/libs/audio/Makemodule.am new file mode 100644 index 000000000..c649c7351 --- /dev/null +++ b/libs/audio/Makemodule.am @@ -0,0 +1,67 @@ +include libs/audio/targets/Makemodule.am +include libs/audio/renderer/Makemodule.am + +plugin_LTLIBRARIES += @cd_plugins@ +noinst_LTLIBRARIES += @cd_static_plugins@ +lib_LTLIBRARIES += @CD_TARGETS@ @SND_TARGETS@ +EXTRA_LTLIBRARIES += \ + libs/audio/libQFsound.la \ + libs/audio/libQFcd.la \ + libs/audio/cd_file.la \ + libs/audio/cd_linux.la \ + libs/audio/cd_sdl.la \ + libs/audio/cd_sgi.la \ + libs/audio/cd_win.la \ + libs/audio/cd_xmms.la + +cd_plug_libs=libs/util/libQFutil.la + +cd_file_libs= \ + libs/audio/libQFsound.la \ + $(cd_plug_libs) + +libs_audio_cd_file_la_LDFLAGS= $(plugin_ldflags) +libs_audio_cd_file_la_LIBADD= $(cd_file_libs) +libs_audio_cd_file_la_SOURCES= libs/audio/cd_file.c + +libs_audio_cd_linux_la_LDFLAGS= $(plugin_ldflags) +libs_audio_cd_linux_la_LIBADD= $(cd_plug_libs) +libs_audio_cd_linux_la_SOURCES= libs/audio/cd_linux.c + +libs_audio_cd_sdl_la_LDFLAGS= $(plugin_ldflags) +libs_audio_cd_sdl_la_LIBADD= $(cd_plug_libs) $(SDL_LIBS) $(plugin_libadd) +libs_audio_cd_sdl_la_CFLAGS= $(SDL_CFLAGS) +libs_audio_cd_sdl_la_SOURCES= libs/audio/cd_sdl.c + +libs_audio_cd_sgi_la_LDFLAGS= $(plugin_ldflags) +libs_audio_cd_sgi_la_LIBADD= $(cd_plug_libs) $(SGI_CD_LIBS) +libs_audio_cd_sgi_la_SOURCES= libs/audio/cd_sgi.c + +libs_audio_cd_win_la_LDFLAGS= $(plugin_ldflags) +libs_audio_cd_win_la_LIBADD= $(cd_plug_libs) $(plugin_libadd) +libs_audio_cd_win_la_SOURCES= libs/audio/cd_win.c + +libs_audio_cd_xmms_la_LDFLAGS= $(plugin_ldflags) +libs_audio_cd_xmms_la_LIBADD= $(cd_plug_libs) $(XMMS_LIBS) +libs_audio_cd_xmms_la_CFLAGS= $(XMMS_CFLAGS) +libs_audio_cd_xmms_la_SOURCES= libs/audio/cd_xmms.c + +sound_libs= \ + @snd_output_static_plugin_libs@ \ + @snd_render_static_plugin_libs@ \ + libs/ruamoko/libQFruamoko.la \ + libs/util/libQFutil.la + +cd_libs= \ + @cd_static_plugin_libs@ \ + libs/util/libQFutil.la + +libs_audio_libQFsound_la_LDFLAGS= $(lib_ldflags) +libs_audio_libQFsound_la_DEPENDENCIES= $(sound_libs) +libs_audio_libQFsound_la_LIBADD= $(sound_libs) +libs_audio_libQFsound_la_SOURCES= libs/audio/snd.c libs/audio/snd_progs.c + +libs_audio_libQFcd_la_LDFLAGS= $(lib_ldflags) +libs_audio_libQFcd_la_DEPENDENCIES= $(cd_libs) +libs_audio_libQFcd_la_LIBADD= $(cd_libs) +libs_audio_libQFcd_la_SOURCES= libs/audio/cd.c diff --git a/libs/audio/renderer/Makefile.am b/libs/audio/renderer/Makefile.am deleted file mode 100644 index 0c3bcd719..000000000 --- a/libs/audio/renderer/Makefile.am +++ /dev/null @@ -1,55 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ \ - $(VORBIS_CFLAGS) $(OGG_CFLAGS) $(SAMPLERATE_CFLAGS) $(JACK_CFLAGS) -AM_CPPFLAGS= -I$(top_srcdir)/include -plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) -plugin_libadd= @plugin_libadd@ -EXEEXT= - -plugin_LTLIBRARIES= @snd_render_plugins@ -noinst_LTLIBRARIES= @snd_render_static_plugins@ -EXTRA_LTLIBRARIES= snd_render_default.la snd_render_jack.la - -flac_src=flac.c -midi_src=midi.c -vorbis_src=vorbis.c -wav_src=wav.c - -if HAVE_FLAC -have_flac_src=$(flac_src) -else -have_flac_src= -endif -if HAVE_MIDI -have_midi_src=$(midi_src) -else -have_midi_src= -endif -if HAVE_VORBIS -have_vorbis_src=$(vorbis_src) -else -have_vorbis_src= -endif -have_wav_src=$(wav_src) - -format_src=$(have_flac_src) $(have_midi_src) $(have_vorbis_src) $(have_wav_src) -format_libs= \ - $(SAMPLERATE_LIBS) $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(FLAC_LIBS) \ - $(OGG_LIBS) $(WM_LIBS) -extra_format_src=flac.c midi.c vorbis.c wav.c -snd_common=snd_channels.c snd_mem.c snd_mix.c snd_resample.c snd_sfx.c -snd_libs= \ - $(top_builddir)/libs/util/libQFutil.la - -snd_render_default_la_LDFLAGS= $(plugin_ldflags) -snd_render_default_la_SOURCES= snd_dma.c $(snd_common) $(format_src) -snd_render_default_la_LIBADD= $(snd_libs) $(format_libs) -snd_render_default_la_DEPENDENCIES= $(snd_libs) -EXTRA_snd_render_default_la_SOURCES=$(extra_format_src) - -snd_render_jack_la_LDFLAGS= $(plugin_ldflags) -snd_render_jack_la_SOURCES= snd_jack.c $(snd_common) $(format_src) -snd_render_jack_la_LIBADD= $(snd_libs) $(format_libs) $(JACK_LIBS) -snd_render_jack_la_DEPENDENCIES= $(snd_libs) -EXTRA_snd_render_jack_la_SOURCES= $(extra_format_src) diff --git a/libs/audio/renderer/Makemodule.am b/libs/audio/renderer/Makemodule.am new file mode 100644 index 000000000..0ef8bda4f --- /dev/null +++ b/libs/audio/renderer/Makemodule.am @@ -0,0 +1,46 @@ +plugin_LTLIBRARIES += @snd_render_plugins@ +noinst_LTLIBRARIES += @snd_render_static_plugins@ +EXTRA_LTLIBRARIES += libs/audio/renderer/snd_render_default.la libs/audio/renderer/snd_render_jack.la + +flac_src=libs/audio/renderer/flac.c +midi_src=libs/audio/renderer/midi.c +vorbis_src=libs/audio/renderer/vorbis.c +wav_src=libs/audio/renderer/wav.c + +if HAVE_FLAC +have_flac_src=$(flac_src) +else +have_flac_src= +endif +if HAVE_MIDI +have_midi_src=$(midi_src) +else +have_midi_src= +endif +if HAVE_VORBIS +have_vorbis_src=$(vorbis_src) +else +have_vorbis_src= +endif +have_wav_src=$(wav_src) + +format_src=$(have_flac_src) $(have_midi_src) $(have_vorbis_src) $(have_wav_src) +format_libs= \ + $(SAMPLERATE_LIBS) $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(FLAC_LIBS) \ + $(OGG_LIBS) $(WM_LIBS) +extra_format_src=libs/audio/renderer/flac.c libs/audio/renderer/midi.c libs/audio/renderer/vorbis.c libs/audio/renderer/wav.c +snd_common=libs/audio/renderer/snd_channels.c libs/audio/renderer/snd_mem.c libs/audio/renderer/snd_mix.c libs/audio/renderer/snd_resample.c libs/audio/renderer/snd_sfx.c +snd_libs= \ + libs/util/libQFutil.la + +libs_audio_renderer_snd_render_default_la_LDFLAGS= $(plugin_ldflags) +libs_audio_renderer_snd_render_default_la_SOURCES= libs/audio/renderer/snd_dma.c $(snd_common) $(format_src) +libs_audio_renderer_snd_render_default_la_LIBADD= $(snd_libs) $(format_libs) +libs_audio_renderer_snd_render_default_la_DEPENDENCIES= $(snd_libs) +EXTRA_libs_audio_renderer_snd_render_default_la_SOURCES=$(extra_format_src) + +libs_audio_renderer_snd_render_jack_la_LDFLAGS= $(plugin_ldflags) +libs_audio_renderer_snd_render_jack_la_SOURCES= libs/audio/renderer/snd_jack.c $(snd_common) $(format_src) +libs_audio_renderer_snd_render_jack_la_LIBADD= $(snd_libs) $(format_libs) $(JACK_LIBS) +libs_audio_renderer_snd_render_jack_la_DEPENDENCIES= $(snd_libs) +EXTRA_libs_audio_renderer_snd_render_jack_la_SOURCES= $(extra_format_src) diff --git a/libs/audio/targets/Makefile.am b/libs/audio/targets/Makefile.am deleted file mode 100644 index ff0411354..000000000 --- a/libs/audio/targets/Makefile.am +++ /dev/null @@ -1,62 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include -SDL_LIBS = @SDL_LIBS@ -plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) -plugin_libadd= @plugin_libadd@ -EXEEXT= -snd_deps=$(top_builddir)/libs/util/libQFutil.la - -plugin_LTLIBRARIES= @snd_output_plugins@ -noinst_LTLIBRARIES= @snd_output_static_plugins@ -EXTRA_LTLIBRARIES= \ - snd_output_sdl.la snd_output_alsa.la snd_output_oss.la snd_output_sgi.la \ - snd_output_sun.la snd_output_win.la snd_output_dx.la snd_output_disk.la - -snd_output_sdl_la_LDFLAGS= $(plugin_ldflags) -snd_output_sdl_la_LIBADD= $(snd_deps) $(SDL_LIBS) $(plugin_libadd) -snd_output_sdl_la_DEPENDENCIES= $(snd_deps) -snd_output_sdl_la_CFLAGS= $(SDL_CFLAGS) -snd_output_sdl_la_SOURCES= snd_sdl.c - -snd_output_alsa_la_LDFLAGS= $(plugin_ldflags) -snd_output_alsa_la_LIBADD= $(snd_deps) -snd_output_alsa_la_DEPENDENCIES=$(snd_deps) -snd_output_alsa_la_CFLAGS= $(ALSA_CFLAGS) -snd_output_alsa_la_SOURCES= snd_alsa.c - -snd_output_oss_la_LDFLAGS= $(plugin_ldflags) -snd_output_oss_la_LIBADD= $(snd_deps) $(OSS_LIBS) -snd_output_oss_la_DEPENDENCIES= $(snd_deps) -snd_output_oss_la_CFLAGS= $(OSS_CFLAGS) -snd_output_oss_la_SOURCES= snd_oss.c - -snd_output_sgi_la_LDFLAGS= $(plugin_ldflags) -snd_output_sgi_la_LIBADD= $(snd_deps) $(SGISND_LIBS) -snd_output_sgi_la_DEPENDENCIES= $(snd_deps) -snd_output_sgi_la_CFLAGS= $(SGISND_CFLAGS) -snd_output_sgi_la_SOURCES= snd_sgi.c - -snd_output_sun_la_LDFLAGS= $(plugin_ldflags) -snd_output_sun_la_DEPENDENCIES= $(snd_deps) -snd_output_sun_la_CFLAGS= $(SUNSND_CFLAGS) -snd_output_sun_la_SOURCES= snd_sun.c - -snd_output_win_la_LDFLAGS= $(plugin_ldflags) -snd_output_win_la_LIBADD= $(snd_deps) $(WINSND_LIBS) $(plugin_libadd) -snd_output_win_la_DEPENDENCIES= $(snd_deps) -snd_output_win_la_CFLAGS= $(WIN32SND_CFLAGS) -snd_output_win_la_SOURCES= snd_win.c - -snd_output_dx_la_LDFLAGS= $(plugin_ldflags) -snd_output_dx_la_LIBADD= $(snd_deps) $(WINSND_LIBS) $(plugin_libadd) -snd_output_dx_la_DEPENDENCIES= $(snd_deps) -snd_output_dx_la_CFLAGS= $(WIN32SND_CFLAGS) -snd_output_dx_la_SOURCES= snd_dx.c - -snd_output_disk_la_LDFLAGS= $(plugin_ldflags) -snd_output_disk_la_LIBADD= $(snd_deps) $(plugin_libadd) -snd_output_disk_la_DEPENDENCIES=$(snd_deps) -snd_output_disk_la_CFLAGS= -snd_output_disk_la_SOURCES= snd_disk.c diff --git a/libs/audio/targets/Makemodule.am b/libs/audio/targets/Makemodule.am new file mode 100644 index 000000000..dfc566f2a --- /dev/null +++ b/libs/audio/targets/Makemodule.am @@ -0,0 +1,54 @@ +plugin_LTLIBRARIES += @snd_output_plugins@ +noinst_LTLIBRARIES += @snd_output_static_plugins@ +EXTRA_LTLIBRARIES += \ + libs/audio/targets/snd_output_sdl.la libs/audio/targets/snd_output_alsa.la libs/audio/targets/snd_output_oss.la libs/audio/targets/snd_output_sgi.la \ + libs/audio/targets/snd_output_sun.la libs/audio/targets/snd_output_win.la libs/audio/targets/snd_output_dx.la libs/audio/targets/snd_output_disk.la + +snd_deps=libs/util/libQFutil.la + +libs_audio_targets_snd_output_sdl_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_sdl_la_LIBADD= $(snd_deps) $(SDL_LIBS) $(plugin_libadd) +libs_audio_targets_snd_output_sdl_la_DEPENDENCIES= $(snd_deps) +libs_audio_targets_snd_output_sdl_la_CFLAGS= $(SDL_CFLAGS) +libs_audio_targets_snd_output_sdl_la_SOURCES= libs/audio/targets/snd_sdl.c + +libs_audio_targets_snd_output_alsa_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_alsa_la_LIBADD= $(snd_deps) +libs_audio_targets_snd_output_alsa_la_DEPENDENCIES=$(snd_deps) +libs_audio_targets_snd_output_alsa_la_CFLAGS= $(ALSA_CFLAGS) +libs_audio_targets_snd_output_alsa_la_SOURCES= libs/audio/targets/snd_alsa.c + +libs_audio_targets_snd_output_oss_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_oss_la_LIBADD= $(snd_deps) $(OSS_LIBS) +libs_audio_targets_snd_output_oss_la_DEPENDENCIES= $(snd_deps) +libs_audio_targets_snd_output_oss_la_CFLAGS= $(OSS_CFLAGS) +libs_audio_targets_snd_output_oss_la_SOURCES= libs/audio/targets/snd_oss.c + +libs_audio_targets_snd_output_sgi_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_sgi_la_LIBADD= $(snd_deps) $(SGISND_LIBS) +libs_audio_targets_snd_output_sgi_la_DEPENDENCIES= $(snd_deps) +libs_audio_targets_snd_output_sgi_la_CFLAGS= $(SGISND_CFLAGS) +libs_audio_targets_snd_output_sgi_la_SOURCES= libs/audio/targets/snd_sgi.c + +libs_audio_targets_snd_output_sun_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_sun_la_DEPENDENCIES= $(snd_deps) +libs_audio_targets_snd_output_sun_la_CFLAGS= $(SUNSND_CFLAGS) +libs_audio_targets_snd_output_sun_la_SOURCES= libs/audio/targets/snd_sun.c + +libs_audio_targets_snd_output_win_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_win_la_LIBADD= $(snd_deps) $(WINSND_LIBS) $(plugin_libadd) +libs_audio_targets_snd_output_win_la_DEPENDENCIES= $(snd_deps) +libs_audio_targets_snd_output_win_la_CFLAGS= $(WIN32SND_CFLAGS) +libs_audio_targets_snd_output_win_la_SOURCES= libs/audio/targets/snd_win.c + +libs_audio_targets_snd_output_dx_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_dx_la_LIBADD= $(snd_deps) $(WINSND_LIBS) $(plugin_libadd) +libs_audio_targets_snd_output_dx_la_DEPENDENCIES= $(snd_deps) +libs_audio_targets_snd_output_dx_la_CFLAGS= $(WIN32SND_CFLAGS) +libs_audio_targets_snd_output_dx_la_SOURCES= libs/audio/targets/snd_dx.c + +libs_audio_targets_snd_output_disk_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_disk_la_LIBADD= $(snd_deps) $(plugin_libadd) +libs_audio_targets_snd_output_disk_la_DEPENDENCIES=$(snd_deps) +libs_audio_targets_snd_output_disk_la_CFLAGS= +libs_audio_targets_snd_output_disk_la_SOURCES= libs/audio/targets/snd_disk.c diff --git a/libs/audio/test/Makefile.am b/libs/audio/test/Makefile.am index 410be4f4e..ff6d259a4 100644 --- a/libs/audio/test/Makefile.am +++ b/libs/audio/test/Makefile.am @@ -7,9 +7,9 @@ noinst_PROGRAMS= @AUDIO_TARGETS@ EXTRA_PROGRAMS= testsound test_libs= \ - $(top_builddir)/libs/audio/libQFsound.la \ - $(top_builddir)/libs/ruamoko/libQFruamoko.la \ - $(top_builddir)/libs/util/libQFutil.la + libs/audio/libQFsound.la \ + libs/ruamoko/libQFruamoko.la \ + libs/util/libQFutil.la testsound_SOURCES= testsound.c testsound_LDADD= $(test_libs) diff --git a/libs/client/Makefile.am b/libs/client/Makefile.am deleted file mode 100644 index d9fc98a77..000000000 --- a/libs/client/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LTLIBRARIES= libQFclient.la - -libQFclient_la_LDFLAGS= @STATIC@ -libQFclient_la_LIBADD= $(top_builddir)/libs/gamecode/libQFgamecode.la $(top_builddir)/libs/util/libQFutil.la -libQFclient_la_SOURCES= \ - cl_entities.c diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am new file mode 100644 index 000000000..962430a4b --- /dev/null +++ b/libs/client/Makemodule.am @@ -0,0 +1,6 @@ +noinst_LTLIBRARIES += libs/client/libQFclient.la + +libs_client_libQFclient_la_LDFLAGS= @STATIC@ +libs_client_libQFclient_la_LIBADD= libs/gamecode/libQFgamecode.la libs/util/libQFutil.la +libs_client_libQFclient_la_SOURCES= \ + libs/client/cl_entities.c diff --git a/libs/console/Makefile.am b/libs/console/Makefile.am deleted file mode 100644 index d7cce92e7..000000000 --- a/libs/console/Makefile.am +++ /dev/null @@ -1,43 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(FNM_FLAGS) -plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) -plugin_libadd= @plugin_libadd@ -lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ - -rpath $(libdir) -no-undefined -EXEEXT= - -lib_LTLIBRARIES= libQFconsole.la -plugin_LTLIBRARIES= @console_plugins@ -noinst_LTLIBRARIES= @client_static_plugins@ @server_static_plugins@ -EXTRA_LTLIBRARIES= console_server.la console_client.la - -common_sources= \ - buffer.c complete.c console.c inputline.c list.c filelist.c view.c -client_sources= bi_inputline.c client.c menu.c -server_sources= server.c - -console_deps=$(top_builddir)/libs/util/libQFutil.la -client_deps= libQFconsole.la \ - $(top_builddir)/libs/audio/libQFsound.la \ - $(top_builddir)/libs/ruamoko/libQFruamoko.la \ - $(top_builddir)/libs/gib/libQFgib.la \ - $(top_builddir)/libs/ruamoko/libQFruamoko.la \ - $(console_deps) -server_deps= libQFconsole.la $(console_deps) - -libQFconsole_la_LDFLAGS= $(lib_ldflags) -libQFconsole_la_LIBADD= $(console_deps) $(plugin_libadd) -libQFconsole_la_DEPENDENCIES= $(console_deps) -libQFconsole_la_SOURCES= $(common_sources) - -console_client_la_LDFLAGS= $(plugin_ldflags) -console_client_la_LIBADD= $(client_deps) $(plugin_libadd) -console_client_la_DEPENDENCIES= $(client_deps) -console_client_la_SOURCES= $(client_sources) - -console_server_la_LDFLAGS= $(plugin_ldflags) -console_server_la_LIBADD= $(server_deps) $(CURSES_LIBS) $(plugin_libadd) -console_server_la_DEPENDENCIES= $(server_deps) -console_server_la_SOURCES= $(server_sources) diff --git a/libs/console/Makemodule.am b/libs/console/Makemodule.am new file mode 100644 index 000000000..bd745a2e2 --- /dev/null +++ b/libs/console/Makemodule.am @@ -0,0 +1,33 @@ +lib_LTLIBRARIES += libs/console/libQFconsole.la +plugin_LTLIBRARIES += @console_plugins@ +noinst_LTLIBRARIES += @client_static_plugins@ @server_static_plugins@ +EXTRA_LTLIBRARIES += libs/console/console_server.la libs/console/console_client.la + +console_common_sources= \ + libs/console/buffer.c libs/console/complete.c libs/console/console.c libs/console/inputline.c libs/console/list.c libs/console/filelist.c libs/console/view.c +client_sources= libs/console/bi_inputline.c libs/console/client.c libs/console/menu.c +server_sources= libs/console/server.c + +console_deps=libs/util/libQFutil.la +client_deps= libs/console/libQFconsole.la \ + libs/audio/libQFsound.la \ + libs/ruamoko/libQFruamoko.la \ + libs/gib/libQFgib.la \ + libs/ruamoko/libQFruamoko.la \ + $(console_deps) +server_deps= libs/console/libQFconsole.la $(console_deps) + +libs_console_libQFconsole_la_LDFLAGS= $(lib_ldflags) +libs_console_libQFconsole_la_LIBADD= $(console_deps) $(plugin_libadd) +libs_console_libQFconsole_la_DEPENDENCIES= $(console_deps) +libs_console_libQFconsole_la_SOURCES= $(console_common_sources) + +libs_console_console_client_la_LDFLAGS= $(plugin_ldflags) +libs_console_console_client_la_LIBADD= $(client_deps) $(plugin_libadd) +libs_console_console_client_la_DEPENDENCIES= $(client_deps) +libs_console_console_client_la_SOURCES= $(client_sources) + +libs_console_console_server_la_LDFLAGS= $(plugin_ldflags) +libs_console_console_server_la_LIBADD= $(server_deps) $(CURSES_LIBS) $(plugin_libadd) +libs_console_console_server_la_DEPENDENCIES= $(server_deps) +libs_console_console_server_la_SOURCES= $(server_sources) diff --git a/libs/gamecode/Makefile.am b/libs/gamecode/Makefile.am deleted file mode 100644 index 6d31504a8..000000000 --- a/libs/gamecode/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include -lib_ldflags= - -gc_deps=$(top_builddir)/libs/util/libQFutil.la - -noinst_LTLIBRARIES= libQFgamecode.la - -libQFgamecode_la_LDFLAGS= $(lib_ldflags) -libQFgamecode_la_LIBADD= $(gc_deps) -libQFgamecode_la_DEPENDENCIES= $(gc_deps) -libQFgamecode_la_SOURCES= \ - pr_builtins.c pr_edict.c pr_debug.c pr_exec.c pr_load.c pr_parse.c \ - pr_opcode.c pr_resolve.c pr_resource.c pr_strings.c pr_zone.c diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am new file mode 100644 index 000000000..dfae7c388 --- /dev/null +++ b/libs/gamecode/Makemodule.am @@ -0,0 +1,19 @@ +gc_deps=libs/util/libQFutil.la + +noinst_LTLIBRARIES += libs/gamecode/libQFgamecode.la + +libs_gamecode_libQFgamecode_la_LDFLAGS= +libs_gamecode_libQFgamecode_la_LIBADD= $(gc_deps) +libs_gamecode_libQFgamecode_la_DEPENDENCIES=$(gc_deps) +libs_gamecode_libQFgamecode_la_SOURCES= \ + libs/gamecode/pr_builtins.c \ + libs/gamecode/pr_edict.c \ + libs/gamecode/pr_debug.c \ + libs/gamecode/pr_exec.c \ + libs/gamecode/pr_load.c \ + libs/gamecode/pr_parse.c \ + libs/gamecode/pr_opcode.c \ + libs/gamecode/pr_resolve.c \ + libs/gamecode/pr_resource.c \ + libs/gamecode/pr_strings.c \ + libs/gamecode/pr_zone.c diff --git a/libs/gib/Makefile.am b/libs/gib/Makefile.am deleted file mode 100644 index 80ea92067..000000000 --- a/libs/gib/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -AUTOMAKE_OPTIONS= foreign -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(FNM_FLAGS) - -lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ - -rpath $(libdir) -no-undefined - -gib_deps= \ - $(top_builddir)/libs/ruamoko/libQFruamoko.la \ - $(top_builddir)/libs/util/libQFutil.la - -lib_LTLIBRARIES= libQFgib.la - -libQFgib_la_LDFLAGS= $(lib_ldflags) -libQFgib_la_LIBADD= $(gib_deps) -libQFgib_la_DEPENDENCIES= $(gib_deps) -libQFgib_la_SOURCES= \ - bi_gib.c \ - gib_buffer.c gib_builtin.c gib_classes.c gib_execute.c gib_function.c \ - gib_parse.c gib_handle.c gib_object.c gib_process.c gib_regex.c \ - gib_thread.c gib_vars.c gib_init.c gib_tree.c \ - gib_semantics.c ops.c exp.c regex.c diff --git a/libs/gib/Makemodule.am b/libs/gib/Makemodule.am new file mode 100644 index 000000000..e0fbe14c2 --- /dev/null +++ b/libs/gib/Makemodule.am @@ -0,0 +1,29 @@ +gib_deps= \ + libs/ruamoko/libQFruamoko.la \ + libs/util/libQFutil.la + +lib_LTLIBRARIES += libs/gib/libQFgib.la + +libs_gib_libQFgib_la_LDFLAGS= $(lib_ldflags) +libs_gib_libQFgib_la_LIBADD= $(gib_deps) +libs_gib_libQFgib_la_DEPENDENCIES= $(gib_deps) +libs_gib_libQFgib_la_SOURCES= \ + libs/gib/bi_gib.c \ + libs/gib/gib_buffer.c \ + libs/gib/gib_builtin.c \ + libs/gib/gib_classes.c \ + libs/gib/gib_execute.c \ + libs/gib/gib_function.c \ + libs/gib/gib_parse.c \ + libs/gib/gib_handle.c \ + libs/gib/gib_object.c \ + libs/gib/gib_process.c \ + libs/gib/gib_regex.c \ + libs/gib/gib_thread.c \ + libs/gib/gib_vars.c \ + libs/gib/gib_init.c \ + libs/gib/gib_tree.c \ + libs/gib/gib_semantics.c \ + libs/gib/ops.c \ + libs/gib/exp.c \ + libs/gib/regex.c diff --git a/libs/image/Makefile.am b/libs/image/Makefile.am deleted file mode 100644 index 344bd7dd7..000000000 --- a/libs/image/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -AUTOMAKE_OPTIONS= foreign -AM_CFLAGS= @PREFER_PIC@ $(Z_CFLAGS) $(PNG_CFLAGS) -AM_CPPFLAGS= -I$(top_srcdir)/include - -lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ - -rpath $(libdir) -no-undefined - -image_deps=$(top_builddir)/libs/util/libQFutil.la - -lib_LTLIBRARIES= libQFimage.la - -libQFimage_la_LDFLAGS= $(lib_ldflags) -libQFimage_la_LIBADD= $(image_deps) $(PNG_LIBS) -libQFimage_la_DEPENDENCIES= $(pmage_deps) -libQFimage_la_SOURCES= \ - image.c pcx.c png.c tga.c - -EXTRA_DIST= diff --git a/libs/image/Makemodule.am b/libs/image/Makemodule.am new file mode 100644 index 000000000..786545ad2 --- /dev/null +++ b/libs/image/Makemodule.am @@ -0,0 +1,9 @@ +image_deps=libs/util/libQFutil.la + +lib_LTLIBRARIES += libs/image/libQFimage.la + +libs_image_libQFimage_la_LDFLAGS= $(lib_ldflags) +libs_image_libQFimage_la_LIBADD= $(image_deps) $(PNG_LIBS) +libs_image_libQFimage_la_DEPENDENCIES= $(image_deps) +libs_image_libQFimage_la_SOURCES= \ + libs/image/image.c libs/image/pcx.c libs/image/png.c libs/image/tga.c diff --git a/libs/models/Makefile.am b/libs/models/Makefile.am deleted file mode 100644 index 2fa145649..000000000 --- a/libs/models/Makefile.am +++ /dev/null @@ -1,58 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= alias brush iqm sprite . test -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -lib_LTLIBRARIES= libQFmodels.la -noinst_LTLIBRARIES= @models_libs@ -EXTRA_LTLIBRARIES= libmodels_gl.la libmodels_glsl.la libmodels_sw.la - -lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ - -rpath $(libdir) -no-undefined - -models_sources = clip_hull.c model.c portal.c trace.c winding.c - -common_libs = \ - $(top_builddir)/libs/util/libQFutil.la - -models_libs=brush/libbrush.la $(common_libs) - -libQFmodels_la_LDFLAGS= $(lib_ldflags) -libQFmodels_la_LIBADD= $(models_libs) -libQFmodels_la_DEPENDENCIES= $(models_libs) -libQFmodels_la_SOURCES= $(models_sources) - -gl_sources=gl_model_fullbright.c gl_skin.c skin.c -gl_libs= \ - alias/libalias_gl.la \ - brush/libbrush_gl.la \ - iqm/libiqm_gl.la \ - sprite/libsprite_gl.la \ - $(top_builddir)/libs/image/libQFimage.la -libmodels_gl_la_LDFLAGS= -libmodels_gl_la_LIBADD= $(gl_libs) -libmodels_gl_la_DEPENDENCIES= $(gl_libs) -libmodels_gl_la_SOURCES= $(gl_sources) - -glsl_libs= \ - alias/libalias_glsl.la \ - brush/libbrush_glsl.la \ - iqm/libiqm_glsl.la \ - sprite/libsprite_glsl.la \ - $(top_builddir)/libs/image/libQFimage.la -libmodels_glsl_la_LDFLAGS= -libmodels_glsl_la_LIBADD= $(glsl_libs) -libmodels_glsl_la_DEPENDENCIES= $(glsl_libs) -libmodels_glsl_la_SOURCES= glsl_skin.c skin.c - -sw_libs= \ - alias/libalias_sw.la \ - brush/libbrush_sw.la \ - iqm/libiqm_sw.la \ - sprite/libsprite_sw.la \ - $(top_builddir)/libs/image/libQFimage.la -libmodels_sw_la_LDFLAGS= -libmodels_sw_la_LIBADD= $(sw_libs) -libmodels_sw_la_DEPENDENCIES= $(sw_libs) -libmodels_sw_la_SOURCES= sw_skin.c skin.c diff --git a/libs/models/Makemodule.am b/libs/models/Makemodule.am new file mode 100644 index 000000000..2fbc7380d --- /dev/null +++ b/libs/models/Makemodule.am @@ -0,0 +1,55 @@ +include libs/models/alias/Makemodule.am +include libs/models/brush/Makemodule.am +include libs/models/iqm/Makemodule.am +include libs/models/sprite/Makemodule.am +include libs/models/test/Makemodule.am + +lib_LTLIBRARIES += libs/models/libQFmodels.la +noinst_LTLIBRARIES += @models_libs@ +EXTRA_LTLIBRARIES += libs/models/libmodels_gl.la libs/models/libmodels_glsl.la libs/models/libmodels_sw.la + +models_sources = libs/models/clip_hull.c libs/models/model.c libs/models/portal.c libs/models/trace.c libs/models/winding.c + +common_libs = \ + libs/util/libQFutil.la + +models_libs=libs/models/brush/libbrush.la $(common_libs) + +libs_models_libQFmodels_la_LDFLAGS= $(lib_ldflags) +libs_models_libQFmodels_la_LIBADD= $(models_libs) +libs_models_libQFmodels_la_DEPENDENCIES= $(models_libs) +libs_models_libQFmodels_la_SOURCES= $(models_sources) + +gl_sources=libs/models/gl_model_fullbright.c libs/models/gl_skin.c libs/models/skin.c +gl_libs= \ + libs/models/alias/libalias_gl.la \ + libs/models/brush/libbrush_gl.la \ + libs/models/iqm/libiqm_gl.la \ + libs/models/sprite/libsprite_gl.la \ + libs/image/libQFimage.la +libs_models_libmodels_gl_la_LDFLAGS= +libs_models_libmodels_gl_la_LIBADD= $(gl_libs) +libs_models_libmodels_gl_la_DEPENDENCIES= $(gl_libs) +libs_models_libmodels_gl_la_SOURCES= $(gl_sources) + +glsl_libs= \ + libs/models/alias/libalias_glsl.la \ + libs/models/brush/libbrush_glsl.la \ + libs/models/iqm/libiqm_glsl.la \ + libs/models/sprite/libsprite_glsl.la \ + libs/image/libQFimage.la +libs_models_libmodels_glsl_la_LDFLAGS= +libs_models_libmodels_glsl_la_LIBADD= $(glsl_libs) +libs_models_libmodels_glsl_la_DEPENDENCIES= $(glsl_libs) +libs_models_libmodels_glsl_la_SOURCES= libs/models/glsl_skin.c libs/models/skin.c + +sw_libs= \ + libs/models/alias/libalias_sw.la \ + libs/models/brush/libbrush_sw.la \ + libs/models/iqm/libiqm_sw.la \ + libs/models/sprite/libsprite_sw.la \ + libs/image/libQFimage.la +libs_models_libmodels_sw_la_LDFLAGS= +libs_models_libmodels_sw_la_LIBADD= $(sw_libs) +libs_models_libmodels_sw_la_DEPENDENCIES= $(sw_libs) +libs_models_libmodels_sw_la_SOURCES= libs/models/sw_skin.c libs/models/skin.c diff --git a/libs/models/alias/Makefile.am b/libs/models/alias/Makefile.am deleted file mode 100644 index e74edfeda..000000000 --- a/libs/models/alias/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LTLIBRARIES= @alias_libs@ -EXTRA_LTLIBRARIES=libalias_gl.la libalias_glsl.la libalias_sw.la - -alias_src= model_alias.c -gl_src= gl_mesh.c gl_model_alias.c floodfill.c -glsl_src= glsl_model_alias.c floodfill.c -sw_src= sw_model_alias.c - -libalias_gl_la_SOURCES= $(gl_src) $(alias_src) - -libalias_glsl_la_SOURCES= $(glsl_src) $(alias_src) - -libalias_sw_la_SOURCES= $(sw_src) $(alias_src) - -EXTRA_DIST= $(gl_src) $(glsl_src) $(sw_src) $(alias_src) diff --git a/libs/models/alias/Makemodule.am b/libs/models/alias/Makemodule.am new file mode 100644 index 000000000..42f2c5a73 --- /dev/null +++ b/libs/models/alias/Makemodule.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES += @alias_libs@ +EXTRA_LTLIBRARIES += libs/models/alias/libalias_gl.la libs/models/alias/libalias_glsl.la libs/models/alias/libalias_sw.la + +alias_src= libs/models/alias/model_alias.c +alias_gl_src= libs/models/alias/gl_mesh.c libs/models/alias/gl_model_alias.c libs/models/alias/floodfill.c +alias_glsl_src= libs/models/alias/glsl_model_alias.c libs/models/alias/floodfill.c +alias_sw_src= libs/models/alias/sw_model_alias.c + +libs_models_alias_libalias_gl_la_SOURCES= $(alias_gl_src) $(alias_src) + +libs_models_alias_libalias_glsl_la_SOURCES= $(alias_glsl_src) $(alias_src) + +libs_models_alias_libalias_sw_la_SOURCES= $(alias_sw_src) $(alias_src) + +EXTRA_DIST += $(alias_gl_src) $(alias_glsl_src) $(alias_sw_src) $(alias_src) diff --git a/libs/models/brush/Makefile.am b/libs/models/brush/Makefile.am deleted file mode 100644 index cd728baed..000000000 --- a/libs/models/brush/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LTLIBRARIES= libbrush.la @brush_libs@ -EXTRA_LTLIBRARIES=libbrush_gl.la libbrush_glsl.la libbrush_sw.la - -brush_src= model_brush.c -gl_src= gl_model_brush.c -glsl_src= glsl_model_brush.c -sw_src= sw_model_brush.c - -libbrush_la_SOURCES= $(brush_src) - -libbrush_gl_la_SOURCES= $(gl_src) $(brush_src) - -libbrush_glsl_la_SOURCES= $(glsl_src) $(brush_src) - -libbrush_sw_la_SOURCES= $(sw_src) $(brush_src) - -EXTRA_DIST= $(gl_src) $(glsl_src) $(sw_src) $(brush_src) diff --git a/libs/models/brush/Makemodule.am b/libs/models/brush/Makemodule.am new file mode 100644 index 000000000..a07ce0726 --- /dev/null +++ b/libs/models/brush/Makemodule.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES += libs/models/brush/libbrush.la @brush_libs@ +EXTRA_LTLIBRARIES += libs/models/brush/libbrush_gl.la libs/models/brush/libbrush_glsl.la libs/models/brush/libbrush_sw.la + +brush_src= libs/models/brush/model_brush.c +brush_gl_src= libs/models/brush/gl_model_brush.c +brush_glsl_src= libs/models/brush/glsl_model_brush.c +brush_sw_src= libs/models/brush/sw_model_brush.c + +libs_models_brush_libbrush_la_SOURCES= $(brush_src) + +libs_models_brush_libbrush_gl_la_SOURCES= $(brush_gl_src) $(brush_src) + +libs_models_brush_libbrush_glsl_la_SOURCES= $(brush_glsl_src) $(brush_src) + +libs_models_brush_libbrush_sw_la_SOURCES= $(brush_sw_src) $(brush_src) + +EXTRA_DIST += $(brush_gl_src) $(brush_glsl_src) $(brush_sw_src) $(brush_src) diff --git a/libs/models/iqm/Makefile.am b/libs/models/iqm/Makefile.am deleted file mode 100644 index 71f54f576..000000000 --- a/libs/models/iqm/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LTLIBRARIES= @iqm_libs@ -EXTRA_LTLIBRARIES=libiqm_gl.la libiqm_glsl.la libiqm_sw.la - -iqm_src= model_iqm.c -gl_src= gl_model_iqm.c -glsl_src= glsl_model_iqm.c -sw_src= sw_model_iqm.c - -libiqm_gl_la_SOURCES= $(gl_src) $(iqm_src) - -libiqm_glsl_la_SOURCES= $(glsl_src) $(iqm_src) - -libiqm_sw_la_SOURCES= $(sw_src) $(iqm_src) - -EXTRA_DIST= $(gl_src) $(glsl_src) $(sw_src) $(iqm_src) diff --git a/libs/models/iqm/Makemodule.am b/libs/models/iqm/Makemodule.am new file mode 100644 index 000000000..20c29548b --- /dev/null +++ b/libs/models/iqm/Makemodule.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES += @iqm_libs@ +EXTRA_LTLIBRARIES += libs/models/iqm/libiqm_gl.la libs/models/iqm/libiqm_glsl.la libs/models/iqm/libiqm_sw.la + +iqm_src= libs/models/iqm/model_iqm.c +iqm_gl_src= libs/models/iqm/gl_model_iqm.c +iqm_glsl_src= libs/models/iqm/glsl_model_iqm.c +iqm_sw_src= libs/models/iqm/sw_model_iqm.c + +libs_models_iqm_libiqm_gl_la_SOURCES= $(iqm_gl_src) $(iqm_src) + +libs_models_iqm_libiqm_glsl_la_SOURCES= $(iqm_glsl_src) $(iqm_src) + +libs_models_iqm_libiqm_sw_la_SOURCES= $(iqm_sw_src) $(iqm_src) + +EXTRA_DIST += $(iqm_gl_src) $(iqm_glsl_src) $(iqm_sw_src) $(iqm_src) diff --git a/libs/models/sprite/Makefile.am b/libs/models/sprite/Makefile.am deleted file mode 100644 index 3c6c023d1..000000000 --- a/libs/models/sprite/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LTLIBRARIES= @sprite_libs@ -EXTRA_LTLIBRARIES=libsprite_gl.la libsprite_glsl.la libsprite_sw.la - -sprite_src= model_sprite.c -gl_src= gl_model_sprite.c -glsl_src= glsl_model_sprite.c -sw_src= sw_model_sprite.c - -libsprite_gl_la_SOURCES= $(gl_src) $(sprite_src) - -libsprite_glsl_la_SOURCES= $(glsl_src) $(sprite_src) - -libsprite_sw_la_SOURCES= $(sw_src) $(sprite_src) - -EXTRA_DIST= $(gl_src) $(glsl_src) $(sw_src) $(sprite_src) diff --git a/libs/models/sprite/Makemodule.am b/libs/models/sprite/Makemodule.am new file mode 100644 index 000000000..76b9fa714 --- /dev/null +++ b/libs/models/sprite/Makemodule.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES += @sprite_libs@ +EXTRA_LTLIBRARIES += libs/models/sprite/libsprite_gl.la libs/models/sprite/libsprite_glsl.la libs/models/sprite/libsprite_sw.la + +sprite_src= libs/models/sprite/model_sprite.c +sprite_gl_src= libs/models/sprite/gl_model_sprite.c +sprite_glsl_src= libs/models/sprite/glsl_model_sprite.c +sprite_sw_src= libs/models/sprite/sw_model_sprite.c + +libs_models_sprite_libsprite_gl_la_SOURCES= $(sprite_gl_src) $(sprite_src) + +libs_models_sprite_libsprite_glsl_la_SOURCES= $(sprite_glsl_src) $(sprite_src) + +libs_models_sprite_libsprite_sw_la_SOURCES= $(sprite_sw_src) $(sprite_src) + +EXTRA_DIST += $(sprite_gl_src) $(sprite_glsl_src) $(sprite_sw_src) $(sprite_src) diff --git a/libs/models/test/Makefile.am b/libs/models/test/Makefile.am deleted file mode 100644 index 2718f5ddd..000000000 --- a/libs/models/test/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CPPFLAGS= -I$(srcdir) -I$(top_srcdir)/include - -check_PROGRAMS=testclip testcontents testportals -EXTRA_DIST= trace-id.c trace-qf-bad.c hulls.h main.c - -test_libs= \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/util/libQFutil.la - -testclip_SOURCES= testclip.c hulls.c -testclip_LDADD= $(test_libs) -testclip_DEPENDENCIES= $(test_libs) - -testcontents_SOURCES= testcontents.c hulls.c -testcontents_LDADD= $(test_libs) -testcontents_DEPENDENCIES= $(test_libs) - -testportals_SOURCES= testportals.c hulls.c -testportals_LDADD= $(test_libs) -testportals_DEPENDENCIES= $(test_libs) - -TESTS=$(check_PROGRAMS) diff --git a/libs/models/test/Makemodule.am b/libs/models/test/Makemodule.am new file mode 100644 index 000000000..15cbe5e35 --- /dev/null +++ b/libs/models/test/Makemodule.am @@ -0,0 +1,36 @@ +libs_model_tests = \ + libs/models/test/testclip \ + libs/models/test/testcontents \ + libs/models/test/testportals + +TESTS += $(libs_model_tests) + +check_PROGRAMS += $(libs_model_tests) + +EXTRA_DIST += \ + libs/models/test/trace-id.c \ + libs/models/test/trace-qf-bad.c \ + libs/models/test/hulls.h \ + libs/models/test/main.c + +test_libs= \ + libs/models/libQFmodels.la \ + libs/util/libQFutil.la + +libs_models_test_testclip_SOURCES= \ + libs/models/test/testclip.c \ + libs/models/test/hulls.c +libs_models_test_testclip_LDADD= $(test_libs) +libs_models_test_testclip_DEPENDENCIES= $(test_libs) + +libs_models_test_testcontents_SOURCES= \ + libs/models/test/testcontents.c \ + libs/models/test/hulls.c +libs_models_test_testcontents_LDADD= $(test_libs) +libs_models_test_testcontents_DEPENDENCIES= $(test_libs) + +libs_models_test_testportals_SOURCES= \ + libs/models/test/testportals.c \ + libs/models/test/hulls.c +libs_models_test_testportals_LDADD= $(test_libs) +libs_models_test_testportals_DEPENDENCIES= $(test_libs) diff --git a/libs/net/Makefile.am b/libs/net/Makefile.am deleted file mode 100644 index 69f2fbb6c..000000000 --- a/libs/net/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= nc nm -AM_CFLAGS= @PREFER_NON_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LTLIBRARIES= libnet_chan.la libnet_main.la - -nc_libs=nc/libnc.la -libnet_chan_la_LDFLAGS= @STATIC@ -libnet_chan_la_LIBADD= $(nc_libs) -libnet_chan_la_DEPENDENCIES=$(nc_libs) -libnet_chan_la_SOURCES= net_chan.c - -nm_libs=nm/libnm.la -libnet_main_la_LDFLAGS= @STATIC@ -libnet_main_la_LIBADD= $(nm_libs) -libnet_main_la_DEPENDENCIES=$(nm_libs) -libnet_main_la_SOURCES= net_main.c diff --git a/libs/net/Makemodule.am b/libs/net/Makemodule.am new file mode 100644 index 000000000..05d0d0136 --- /dev/null +++ b/libs/net/Makemodule.am @@ -0,0 +1,14 @@ + +noinst_LTLIBRARIES += libs/net/libnet_chan.la libs/net/libnet_main.la + +include libs/net/nc/Makemodule.am +include libs/net/nm/Makemodule.am + +libs_net_libnet_chan_la_LDFLAGS= @STATIC@ +libs_net_libnet_chan_la_SOURCES= libs/net/net_chan.c ${nc_src} +EXTRA_libs_net_libnet_chan_la_SOURCES = $(ipv4_src) $(ipv6_src) + +nm_libs=nm/libnm.la +libs_net_libnet_main_la_LDFLAGS= @STATIC@ +libs_net_libnet_main_la_SOURCES= libs/net/net_main.c ${nm_src} +EXTRA_libs_net_libnet_main_la_SOURCES = $(nm_extra) diff --git a/libs/net/nc/Makefile.am b/libs/net/nc/Makefile.am deleted file mode 100644 index 08b0cb810..000000000 --- a/libs/net/nc/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_NON_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LTLIBRARIES= libnc.la - -ipv6_src= net_udp6.c -ipv4_src= net_udp.c -if NETTYPE_IPV6 -ipvX_src= $(ipv6_src) -else -ipvX_src= $(ipv4_src) -endif -libnc_la_SOURCES= $(ipvX_src) -libnc_la_LDFLAGS= @STATIC@ -EXTRA_libnc_la_SOURCES= $(ipv4_src) $(ipv6_src) diff --git a/libs/net/nc/Makemodule.am b/libs/net/nc/Makemodule.am new file mode 100644 index 000000000..ae51d29e2 --- /dev/null +++ b/libs/net/nc/Makemodule.am @@ -0,0 +1,8 @@ +ipv6_src= libs/net/nc/net_udp6.c +ipv4_src= libs/net/nc/net_udp.c +if NETTYPE_IPV6 +ipvX_src= $(ipv6_src) +else +ipvX_src= $(ipv4_src) +endif +nc_src= $(ipvX_src) diff --git a/libs/net/nm/Makefile.am b/libs/net/nm/Makefile.am deleted file mode 100644 index cfdaae275..000000000 --- a/libs/net/nm/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_NON_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LTLIBRARIES= libnm.la - -if SYSTYPE_WIN32 -net_sources= net_win.c net_wins.c -else -net_sources= net_bsd.c net_udp.c -endif -libnm_la_SOURCES= net_dgrm.c net_loop.c net_vcr.c $(net_sources) -libnm_la_LDFLAGS= @STATIC@ - - -EXTRA_libnm_la_SOURCES= \ - net_bsd.c net_win.c net_wins.c net_udp.c diff --git a/libs/net/nm/Makemodule.am b/libs/net/nm/Makemodule.am new file mode 100644 index 000000000..002b24b02 --- /dev/null +++ b/libs/net/nm/Makemodule.am @@ -0,0 +1,8 @@ +if SYSTYPE_WIN32 +net_sources= libs/net/nm/net_win.c libs/net/nm/net_wins.c +else +net_sources= libs/net/nm/net_bsd.c libs/net/nm/net_udp.c +endif +nm_src= libs/net/nm/net_dgrm.c libs/net/nm/net_loop.c libs/net/nm/net_vcr.c $(net_sources) + +nm_extra = libs/net/nm/net_bsd.c libs/net/nm/net_win.c libs/net/nm/net_wins.c libs/net/nm/net_udp.c diff --git a/libs/qw/Makefile.am b/libs/qw/Makefile.am deleted file mode 100644 index 48a58fa72..000000000 --- a/libs/qw/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LIBRARIES= libqw.a - -libqw_a_SOURCES= \ - msg_backbuf.c msg_ucmd.c diff --git a/libs/qw/Makemodule.am b/libs/qw/Makemodule.am new file mode 100644 index 000000000..42834b43a --- /dev/null +++ b/libs/qw/Makemodule.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES += libs/qw/libqw.a + +libs_qw_libqw_a_SOURCES= \ + libs/qw/msg_backbuf.c libs/qw/msg_ucmd.c diff --git a/libs/ruamoko/Makefile.am b/libs/ruamoko/Makefile.am deleted file mode 100644 index 2d4777c14..000000000 --- a/libs/ruamoko/Makefile.am +++ /dev/null @@ -1,21 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(FNM_FLAGS) - -lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ - -rpath $(libdir) -no-undefined -rua_libs= \ - $(top_builddir)/libs/gamecode/libQFgamecode.la \ - $(top_builddir)/libs/util/libQFutil.la - -lib_LTLIBRARIES= libQFruamoko.la - -libQFruamoko_la_LDFLAGS= $(lib_ldflags) -libQFruamoko_la_LIBADD= $(rua_libs) -libQFruamoko_la_DEPENDENCIES= $(rua_libs) -libQFruamoko_la_SOURCES= \ - pr_cmds.c \ - rua_cbuf.c rua_cmd.c rua_cvar.c rua_hash.c rua_init.c \ - rua_math.c rua_msgbuf.c rua_obj.c rua_plist.c rua_qfile.c rua_qfs.c \ - rua_runtime.c rua_script.c rua_set.c rua_string.c diff --git a/libs/ruamoko/Makemodule.am b/libs/ruamoko/Makemodule.am new file mode 100644 index 000000000..c3ed37383 --- /dev/null +++ b/libs/ruamoko/Makemodule.am @@ -0,0 +1,26 @@ +ruamoko_rua_libs= \ + libs/gamecode/libQFgamecode.la \ + libs/util/libQFutil.la + +lib_LTLIBRARIES += libs/ruamoko/libQFruamoko.la + +libs_ruamoko_libQFruamoko_la_LDFLAGS= $(lib_ldflags) +libs_ruamoko_libQFruamoko_la_LIBADD= $(ruamoko_rua_libs) +libs_ruamoko_libQFruamoko_la_DEPENDENCIES= $(ruamoko_rua_libs) +libs_ruamoko_libQFruamoko_la_SOURCES= \ + libs/ruamoko/pr_cmds.c \ + libs/ruamoko/rua_cbuf.c \ + libs/ruamoko/rua_cmd.c \ + libs/ruamoko/rua_cvar.c \ + libs/ruamoko/rua_hash.c \ + libs/ruamoko/rua_init.c \ + libs/ruamoko/rua_math.c \ + libs/ruamoko/rua_msgbuf.c \ + libs/ruamoko/rua_obj.c \ + libs/ruamoko/rua_plist.c \ + libs/ruamoko/rua_qfile.c \ + libs/ruamoko/rua_qfs.c \ + libs/ruamoko/rua_runtime.c \ + libs/ruamoko/rua_script.c \ + libs/ruamoko/rua_set.c \ + libs/ruamoko/rua_string.c diff --git a/libs/util/Makefile.am b/libs/util/Makefile.am deleted file mode 100644 index c35e4e305..000000000 --- a/libs/util/Makefile.am +++ /dev/null @@ -1,60 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= . test - -AM_CFLAGS= @PREFER_PIC@ -CCASFLAGS+= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(Z_CFLAGS) $(FNM_FLAGS) - -lib_LTLIBRARIES= libQFutil.la - -lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ - -rpath $(libdir) -no-undefined - -if ASM_ARCH -asm= libasm.la -else -asm= -endif - -noinst_LTLIBRARIES= $(asm) -#EXTRA_LTLIBRARIES= libasm.la - -libasm_la_SOURCES= math.S sys_ia32.S - - -dirent_src= dirent.c -fnmatch_src= fnmatch.c -getopt_src= getopt.c getopt1.c - -if BUILD_DIRENT -dirent= $(dirent_src) -else -dirent= -endif - -if BUILD_FNMATCH -fnmatch= $(fnmatch_src) -else -fnmatch= -endif - -if BUILD_GETOPT -getopt= $(getopt_src) -else -getopt= -endif - -libQFutil_la_LDFLAGS= $(lib_ldflags) -libQFutil_la_LIBADD= $(asm) $(Z_LIBS) $(DL_LIBS) $(WIN32_LIBS) -libQFutil_la_DEPENDENCIES= $(asm) -libQFutil_la_SOURCES= \ - bspfile.c buildnum.c cbuf.c checksum.c cmd.c crc.c cvar.c dstring.c \ - fendian.c hash.c idparse.c info.c link.c llist.c \ - mathlib.c mdfour.c mersenne.c msg.c pakfile.c plugin.c qargs.c qendian.c \ - qfplist.c quakefs.c quakeio.c riff.c script.c segtext.c set.c sizebuf.c \ - string.c sys.c txtbuffer.c va.c ver_check.c vrect.c wad.c wadfile.c \ - zone.c \ - $(dirent) $(fnmatch) $(getopt) - -EXTRA_DIST= $(fnmatch_src) $(getopt_src) diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am new file mode 100644 index 000000000..272459d4d --- /dev/null +++ b/libs/util/Makemodule.am @@ -0,0 +1,84 @@ +include libs/util/test/Makemodule.am + +lib_LTLIBRARIES += libs/util/libQFutil.la + +if ASM_ARCH +util_asm= libs/util/libasm.la +else +util_asm= +endif + +noinst_LTLIBRARIES += $(util_asm) +#EXTRA_LTLIBRARIES += libasm.la + +libs_util_libasm_la_SOURCES = libs/util/math.S libs/util/sys_ia32.S + + +dirent_src= libs/util/dirent.c +fnmatch_src= libs/util/fnmatch.c +getopt_src= libs/util/getopt.c libs/util/getopt1.c + +if BUILD_DIRENT +dirent= $(dirent_src) +else +dirent= +endif + +if BUILD_FNMATCH +fnmatch= $(fnmatch_src) +else +fnmatch= +endif + +if BUILD_GETOPT +getopt= $(getopt_src) +else +getopt= +endif + +libs_util_libQFutil_la_LDFLAGS= $(lib_ldflags) +libs_util_libQFutil_la_LIBADD= $(util_asm) $(Z_LIBS) $(DL_LIBS) $(WIN32_LIBS) +libs_util_libQFutil_la_DEPENDENCIES= $(util_asm) +libs_util_libQFutil_la_SOURCES= \ + libs/util/bspfile.c \ + libs/util/buildnum.c \ + libs/util/cbuf.c \ + libs/util/checksum.c \ + libs/util/cmd.c \ + libs/util/crc.c \ + libs/util/cvar.c \ + libs/util/dstring.c \ + libs/util/fendian.c \ + libs/util/hash.c \ + libs/util/idparse.c \ + libs/util/info.c \ + libs/util/link.c \ + libs/util/llist.c \ + libs/util/mathlib.c \ + libs/util/mdfour.c \ + libs/util/mersenne.c \ + libs/util/msg.c \ + libs/util/pakfile.c \ + libs/util/plugin.c \ + libs/util/qargs.c \ + libs/util/qendian.c \ + libs/util/qfplist.c \ + libs/util/quakefs.c \ + libs/util/quakeio.c \ + libs/util/riff.c \ + libs/util/script.c \ + libs/util/segtext.c \ + libs/util/set.c \ + libs/util/sizebuf.c \ + libs/util/string.c \ + libs/util/sys.c \ + libs/util/txtbuffer.c \ + libs/util/va.c \ + libs/util/ver_check.c \ + libs/util/vrect.c \ + libs/util/wad.c \ + libs/util/wadfile.c \ + libs/util/zone.c \ + $(dirent) $(fnmatch) $(getopt) + +EXTRA_DIST += $(fnmatch_src) $(getopt_src) diff --git a/libs/util/test/Makefile.am b/libs/util/test/Makefile.am deleted file mode 100644 index 74d9a2f4e..000000000 --- a/libs/util/test/Makefile.am +++ /dev/null @@ -1,70 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CPPFLAGS= -I$(top_srcdir)/include - -check_PROGRAMS= \ - test-bary test-cs test-darray test-dq test-half test-mat3 test-mat4 \ - test-plist test-qfs test-quat test-seb test-seg test-set test-txtbuffer \ - test-vrect - -test_bary_SOURCES=test-bary.c -test_bary_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_bary_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_cs_SOURCES=test-cs.c -test_cs_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_cs_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_darray_SOURCES=test-darray.c -test_darray_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_darray_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_dq_SOURCES=test-dq.c -test_dq_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_dq_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_half_SOURCES=test-half.c -test_half_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_half_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_mat3_SOURCES=test-mat3.c -test_mat3_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_mat3_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_mat4_SOURCES=test-mat4.c -test_mat4_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_mat4_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_plist_SOURCES=test-plist.c -test_plist_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_plist_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_qfs_SOURCES=test-qfs.c -test_qfs_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_qfs_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_quat_SOURCES=test-quat.c -test_quat_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_quat_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_seb_SOURCES=test-seb.c -test_seb_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_seb_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_seg_SOURCES=test-seg.c -test_seg_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_seg_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_set_SOURCES=test-set.c -test_set_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_set_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_txtbuffer_SOURCES=test-txtbuffer.c -test_txtbuffer_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_txtbuffer_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -test_vrect_SOURCES=test-vrect.c -test_vrect_LDADD=$(top_builddir)/libs/util/libQFutil.la -test_vrect_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la - -TESTS=$(check_PROGRAMS) diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am new file mode 100644 index 000000000..cf35f885c --- /dev/null +++ b/libs/util/test/Makemodule.am @@ -0,0 +1,79 @@ +libs_util_tests = \ + libs/util/test/test-bary \ + libs/util/test/test-cs \ + libs/util/test/test-darray \ + libs/util/test/test-dq \ + libs/util/test/test-half \ + libs/util/test/test-mat3 \ + libs/util/test/test-mat4 \ + libs/util/test/test-plist \ + libs/util/test/test-qfs \ + libs/util/test/test-quat \ + libs/util/test/test-seb \ + libs/util/test/test-seg \ + libs/util/test/test-set \ + libs/util/test/test-txtbuffer \ + libs/util/test/test-vrect +check_PROGRAMS += $(libs_util_tests) + +TESTS += $(libs_model_tests) + +libs_util_test_test_bary_SOURCES=libs/util/test/test-bary.c +libs_util_test_test_bary_LDADD=libs/util/libQFutil.la +libs_util_test_test_bary_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_cs_SOURCES=libs/util/test/test-cs.c +libs_util_test_test_cs_LDADD=libs/util/libQFutil.la +libs_util_test_test_cs_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_darray_SOURCES=libs/util/test/test-darray.c +libs_util_test_test_darray_LDADD=libs/util/libQFutil.la +libs_util_test_test_darray_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_dq_SOURCES=libs/util/test/test-dq.c +libs_util_test_test_dq_LDADD=libs/util/libQFutil.la +libs_util_test_test_dq_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_half_SOURCES=libs/util/test/test-half.c +libs_util_test_test_half_LDADD=libs/util/libQFutil.la +libs_util_test_test_half_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_mat3_SOURCES=libs/util/test/test-mat3.c +libs_util_test_test_mat3_LDADD=libs/util/libQFutil.la +libs_util_test_test_mat3_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_mat4_SOURCES=libs/util/test/test-mat4.c +libs_util_test_test_mat4_LDADD=libs/util/libQFutil.la +libs_util_test_test_mat4_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_plist_SOURCES=libs/util/test/test-plist.c +libs_util_test_test_plist_LDADD=libs/util/libQFutil.la +libs_util_test_test_plist_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_qfs_SOURCES=libs/util/test/test-qfs.c +libs_util_test_test_qfs_LDADD=libs/util/libQFutil.la +libs_util_test_test_qfs_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_quat_SOURCES=libs/util/test/test-quat.c +libs_util_test_test_quat_LDADD=libs/util/libQFutil.la +libs_util_test_test_quat_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_seb_SOURCES=libs/util/test/test-seb.c +libs_util_test_test_seb_LDADD=libs/util/libQFutil.la +libs_util_test_test_seb_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_seg_SOURCES=libs/util/test/test-seg.c +libs_util_test_test_seg_LDADD=libs/util/libQFutil.la +libs_util_test_test_seg_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_set_SOURCES=libs/util/test/test-set.c +libs_util_test_test_set_LDADD=libs/util/libQFutil.la +libs_util_test_test_set_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_txtbuffer_SOURCES=libs/util/test/test-txtbuffer.c +libs_util_test_test_txtbuffer_LDADD=libs/util/libQFutil.la +libs_util_test_test_txtbuffer_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_vrect_SOURCES=libs/util/test/test-vrect.c +libs_util_test_test_vrect_LDADD=libs/util/libQFutil.la +libs_util_test_test_vrect_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/video/Makefile.am b/libs/video/Makefile.am deleted file mode 100644 index 25b787b7c..000000000 --- a/libs/video/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= targets renderer - -clean-local: - rm -f *.a diff --git a/libs/video/Makemodule.am b/libs/video/Makemodule.am new file mode 100644 index 000000000..ae3d3ca44 --- /dev/null +++ b/libs/video/Makemodule.am @@ -0,0 +1,2 @@ +include libs/video/renderer/Makemodule.am +include libs/video/targets/Makemodule.am diff --git a/libs/video/renderer/Makefile.am b/libs/video/renderer/Makefile.am deleted file mode 100644 index 2c234fe33..000000000 --- a/libs/video/renderer/Makefile.am +++ /dev/null @@ -1,65 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= @vid_render_dirs@ -DIST_SUBDIRS= gl glsl sw sw32 -AM_CPPFLAGS= -I$(top_srcdir)/include - -lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ - -rpath $(libdir) -no-undefined -plugin_ldflags= @plugin_ldflags@ -avoid-version -module -rpath $(plugindir) -plugin_libadd= @plugin_libadd@ -EXEEXT= - -#lib_LTLIBRARIES= @VID_REND_TARGETS@ -plugin_LTLIBRARIES= @vid_render_plugins@ -noinst_LTLIBRARIES= libQFrenderer.la @vid_render_static_plugins@ - -EXTRA_LTLIBRARIES= \ - vid_render_sw.la vid_render_sw32.la \ - vid_render_gl.la vid_render_glsl.la - -common_sources= \ - crosshair.c noisetextures.c r_alias.c r_bsp.c r_cvar.c r_dyn_textures.c \ - r_efrag.c r_ent.c r_graph.c r_iqm.c r_light.c r_main.c r_part.c \ - r_screen.c vid_common.c - -renderer_libs= \ - @vid_render_static_plugin_libs@ \ - $(top_builddir)/libs/util/libQFutil.la - -libQFrenderer_la_LDFLAGS= @STATIC@ -libQFrenderer_la_LIBADD= $(renderer_libs) -libQFrenderer_la_DEPENDENCIES= $(renderer_libs) -libQFrenderer_la_SOURCES= r_init.c r_progs.c - -gl_libs= \ - gl/libgl.la \ - $(top_builddir)/libs/models/libmodels_gl.la -vid_render_gl_la_LDFLAGS= $(plugin_ldflags) -vid_render_gl_la_LIBADD= $(gl_libs) -vid_render_gl_la_DEPENDENCIES= $(gl_libs) -vid_render_gl_la_SOURCES= $(common_sources) vid_render_gl.c - -glsl_libs= \ - glsl/libglsl.la \ - $(top_builddir)/libs/models/libmodels_glsl.la -vid_render_glsl_la_LDFLAGS= $(plugin_ldflags) -vid_render_glsl_la_LIBADD= $(glsl_libs) -vid_render_glsl_la_DEPENDENCIES=$(glsl_libs) -vid_render_glsl_la_SOURCES= $(common_sources) vid_render_glsl.c - -sw_libs= \ - sw/libsw.la \ - $(top_builddir)/libs/models/libmodels_sw.la -vid_render_sw_la_LDFLAGS= $(plugin_ldflags) -vid_render_sw_la_LIBADD= $(sw_libs) -vid_render_sw_la_DEPENDENCIES= $(sw_libs) -vid_render_sw_la_SOURCES= $(common_sources) vid_render_sw.c - -sw32_libs= \ - sw32/libsw32.la \ - $(top_builddir)/libs/models/libmodels_sw.la -vid_render_sw32_la_LDFLAGS= $(plugin_ldflags) -vid_render_sw32_la_LIBADD= $(sw32_libs) -vid_render_sw32_la_DEPENDENCIES=$(sw32_libs) -vid_render_sw32_la_SOURCES= $(common_sources) vid_render_sw32.c diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am new file mode 100644 index 000000000..2e56a95ae --- /dev/null +++ b/libs/video/renderer/Makemodule.am @@ -0,0 +1,185 @@ +#lib_LTLIBRARIES += @VID_REND_TARGETS@ +plugin_LTLIBRARIES += @vid_render_plugins@ +noinst_LTLIBRARIES += libs/video/renderer/libQFrenderer.la @vid_render_static_plugins@ + +EXTRA_LTLIBRARIES += \ + libs/video/renderer/vid_render_sw.la libs/video/renderer/vid_render_sw32.la \ + libs/video/renderer/vid_render_gl.la libs/video/renderer/vid_render_glsl.la + +video_renderer_common_sources= \ + libs/video/renderer/crosshair.c libs/video/renderer/noisetextures.c libs/video/renderer/r_alias.c libs/video/renderer/r_bsp.c libs/video/renderer/r_cvar.c libs/video/renderer/r_dyn_textures.c \ + libs/video/renderer/r_efrag.c libs/video/renderer/r_ent.c libs/video/renderer/r_graph.c libs/video/renderer/r_iqm.c libs/video/renderer/r_light.c libs/video/renderer/r_main.c libs/video/renderer/r_part.c \ + libs/video/renderer/r_screen.c libs/video/renderer/vid_common.c + +renderer_libs= \ + @vid_render_static_plugin_libs@ \ + libs/util/libQFutil.la + +libs_video_renderer_libQFrenderer_la_LDFLAGS= @STATIC@ +libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libs) +libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs) +libs_video_renderer_libQFrenderer_la_SOURCES=\ + libs/video/renderer/r_init.c \ + libs/video/renderer/r_progs.c + +video_renderer_gl_libs= \ + libs/models/libmodels_gl.la +libs_video_renderer_vid_render_gl_la_LDFLAGS= $(plugin_ldflags) +libs_video_renderer_vid_render_gl_la_LIBADD= $(video_renderer_gl_libs) +libs_video_renderer_vid_render_gl_la_DEPENDENCIES= $(video_renderer_gl_libs) +libs_video_renderer_vid_render_gl_la_SOURCES=\ + $(video_renderer_common_sources) \ + libs/video/renderer/vid_render_gl.c \ + libs/video/renderer/gl/gl_draw.c \ + libs/video/renderer/gl/gl_dyn_lights.c \ + libs/video/renderer/gl/gl_dyn_part.c \ + libs/video/renderer/gl/gl_dyn_textures.c \ + libs/video/renderer/gl/gl_fog.c \ + libs/video/renderer/gl/gl_graph.c \ + libs/video/renderer/gl/gl_lightmap.c \ + libs/video/renderer/gl/gl_mod_alias.c \ + libs/video/renderer/gl/gl_mod_iqm.c \ + libs/video/renderer/gl/gl_mod_sprite.c \ + libs/video/renderer/gl/gl_rmain.c \ + libs/video/renderer/gl/gl_rmisc.c \ + libs/video/renderer/gl/gl_rsurf.c \ + libs/video/renderer/gl/gl_screen.c \ + libs/video/renderer/gl/gl_sky.c \ + libs/video/renderer/gl/gl_sky_clip.c \ + libs/video/renderer/gl/gl_textures.c \ + libs/video/renderer/gl/gl_warp.c \ + libs/video/renderer/gl/namehack.h \ + libs/video/renderer/gl/qfgl_ext.c \ + libs/video/renderer/gl/vid_common_gl.c \ + libs/video/renderer/gl/vtxarray.c + +shader_src= libs/video/renderer/glsl/quakeforge.glsl +shader_gen= libs/video/renderer/glsl/quakeforge.slc + +BUILT_SOURCES += $(shader_gen) + +SUFFICES=.frag .vert .fc .vc .slc .glsl +.glsl.slc: + sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ + +video_renderer_glsl_libs= \ + libs/models/libmodels_glsl.la +libs_video_renderer_vid_render_glsl_la_LDFLAGS= $(plugin_ldflags) +libs_video_renderer_vid_render_glsl_la_LIBADD= $(video_renderer_glsl_libs) +libs_video_renderer_vid_render_glsl_la_DEPENDENCIES=$(video_renderer_glsl_libs) +libs_video_renderer_vid_render_glsl_la_SOURCES=\ + $(video_renderer_common_sources) \ + libs/video/renderer/vid_render_glsl.c \ + libs/video/renderer/glsl/glsl_alias.c \ + libs/video/renderer/glsl/glsl_bsp.c \ + libs/video/renderer/glsl/glsl_draw.c \ + libs/video/renderer/glsl/glsl_fog.c \ + libs/video/renderer/glsl/glsl_iqm.c \ + libs/video/renderer/glsl/glsl_lightmap.c \ + libs/video/renderer/glsl/glsl_main.c \ + libs/video/renderer/glsl/glsl_particles.c \ + libs/video/renderer/glsl/glsl_screen.c \ + libs/video/renderer/glsl/glsl_shader.c \ + libs/video/renderer/glsl/glsl_sprite.c \ + libs/video/renderer/glsl/glsl_textures.c \ + libs/video/renderer/glsl/namehack.h \ + libs/video/renderer/glsl/qfglsl.c \ + libs/video/renderer/glsl/quakeforge.glsl \ + libs/video/renderer/glsl/vid_common_glsl.c + +video_renderer_sw_libs= \ + libs/models/libmodels_sw.la +libs_video_renderer_vid_render_sw_la_LDFLAGS= $(plugin_ldflags) +libs_video_renderer_vid_render_sw_la_LIBADD= $(video_renderer_sw_libs) +libs_video_renderer_vid_render_sw_la_DEPENDENCIES= $(video_renderer_sw_libs) +libs_video_renderer_vid_render_sw_la_SOURCES=\ + $(video_renderer_common_sources) \ + libs/video/renderer/vid_render_sw.c \ + libs/video/renderer/sw/d_copy.S \ + libs/video/renderer/sw/d_draw.S \ + libs/video/renderer/sw/d_edge.c \ + libs/video/renderer/sw/d_fill.c \ + libs/video/renderer/sw/d_init.c \ + libs/video/renderer/sw/d_modech.c \ + libs/video/renderer/sw/d_part.c \ + libs/video/renderer/sw/d_parta.S \ + libs/video/renderer/sw/d_polysa.S \ + libs/video/renderer/sw/d_polyse.c \ + libs/video/renderer/sw/d_scan.c \ + libs/video/renderer/sw/d_scana.S \ + libs/video/renderer/sw/d_sky.c \ + libs/video/renderer/sw/d_spr8.S \ + libs/video/renderer/sw/d_sprite.c \ + libs/video/renderer/sw/d_surf.c \ + libs/video/renderer/sw/d_vars.c \ + libs/video/renderer/sw/d_varsa.S \ + libs/video/renderer/sw/d_zpoint.c \ + libs/video/renderer/sw/draw.c \ + libs/video/renderer/sw/fpu.c \ + libs/video/renderer/sw/fpua.S \ + libs/video/renderer/sw/nonintel.c \ + libs/video/renderer/sw/screen.c \ + libs/video/renderer/sw/surf8.S \ + libs/video/renderer/sw/sw_graph.c \ + libs/video/renderer/sw/sw_raclip.c \ + libs/video/renderer/sw/sw_raclipa.S \ + libs/video/renderer/sw/sw_ralias.c \ + libs/video/renderer/sw/sw_raliasa.S \ + libs/video/renderer/sw/sw_rbsp.c \ + libs/video/renderer/sw/sw_rdraw.c \ + libs/video/renderer/sw/sw_rdrawa.S \ + libs/video/renderer/sw/sw_redge.c \ + libs/video/renderer/sw/sw_redgea.S \ + libs/video/renderer/sw/sw_riqm.c \ + libs/video/renderer/sw/sw_rmain.c \ + libs/video/renderer/sw/sw_rmisc.c \ + libs/video/renderer/sw/sw_rpart.c \ + libs/video/renderer/sw/sw_rsky.c \ + libs/video/renderer/sw/sw_rsprite.c \ + libs/video/renderer/sw/sw_rsurf.c \ + libs/video/renderer/sw/sw_rvarsa.S \ + libs/video/renderer/sw/transform.S \ + libs/video/renderer/sw/vid_common_sw.c + +video_renderer_sw32_libs= \ + libs/models/libmodels_sw.la +libs_video_renderer_vid_render_sw32_la_LDFLAGS= $(plugin_ldflags) +libs_video_renderer_vid_render_sw32_la_LIBADD= $(video_renderer_sw32_libs) +libs_video_renderer_vid_render_sw32_la_DEPENDENCIES=$(video_renderer_sw32_libs) +libs_video_renderer_vid_render_sw32_la_SOURCES=\ + $(video_renderer_common_sources) \ + libs/video/renderer/vid_render_sw32.c \ + libs/video/renderer/sw32/d_edge.c \ + libs/video/renderer/sw32/d_fill.c \ + libs/video/renderer/sw32/d_init.c \ + libs/video/renderer/sw32/d_modech.c \ + libs/video/renderer/sw32/d_part.c \ + libs/video/renderer/sw32/d_polyse.c \ + libs/video/renderer/sw32/d_scan.c \ + libs/video/renderer/sw32/d_sky.c \ + libs/video/renderer/sw32/d_sprite.c \ + libs/video/renderer/sw32/d_surf.c \ + libs/video/renderer/sw32/d_vars.c \ + libs/video/renderer/sw32/d_zpoint.c \ + libs/video/renderer/sw32/draw.c \ + libs/video/renderer/sw32/namehack.h \ + libs/video/renderer/sw32/screen.c \ + libs/video/renderer/sw32/sw32_graph.c \ + libs/video/renderer/sw32/sw32_raclip.c \ + libs/video/renderer/sw32/sw32_ralias.c \ + libs/video/renderer/sw32/sw32_rbsp.c \ + libs/video/renderer/sw32/sw32_rdraw.c \ + libs/video/renderer/sw32/sw32_redge.c \ + libs/video/renderer/sw32/sw32_riqm.c \ + libs/video/renderer/sw32/sw32_rmain.c \ + libs/video/renderer/sw32/sw32_rmisc.c \ + libs/video/renderer/sw32/sw32_rpart.c \ + libs/video/renderer/sw32/sw32_rsky.c \ + libs/video/renderer/sw32/sw32_rsprite.c \ + libs/video/renderer/sw32/sw32_rsurf.c \ + libs/video/renderer/sw32/vid_common_sw32.c + +CLEANFILES += \ + libs/video/renderer/glsl/*.vc \ + libs/video/renderer/glsl/*.fc \ + libs/video/renderer/glsl/*.slc diff --git a/libs/video/renderer/gl/Makefile.am b/libs/video/renderer/gl/Makefile.am deleted file mode 100644 index 041db8546..000000000 --- a/libs/video/renderer/gl/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) - -noinst_LTLIBRARIES= libgl.la - -gl_src = \ - gl_draw.c gl_dyn_lights.c gl_dyn_part.c gl_dyn_textures.c \ - gl_fog.c gl_graph.c gl_lightmap.c gl_mod_alias.c gl_mod_iqm.c \ - gl_mod_sprite.c gl_rmain.c gl_rmisc.c gl_rsurf.c gl_screen.c gl_sky.c \ - gl_sky_clip.c gl_textures.c gl_warp.c qfgl_ext.c vid_common_gl.c vtxarray.c - -libgl_la_SOURCES= $(gl_src) - -EXTRA_DIST = $(gl_src) namehack.h diff --git a/libs/video/renderer/glsl/Makefile.am b/libs/video/renderer/glsl/Makefile.am deleted file mode 100644 index ca8f4314a..000000000 --- a/libs/video/renderer/glsl/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) - -shader_src= quakeforge.glsl -shader_gen= quakeforge.slc - -glsl_src = \ - glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ - glsl_main.c glsl_particles.c glsl_screen.c glsl_shader.c glsl_sprite.c \ - glsl_textures.c qfglsl.c vid_common_glsl.c - -noinst_LTLIBRARIES= libglsl.la -BUILT_SOURCES= $(shader_gen) - -SUFFICES=.frag .vert .fc .vc .slc .glsl -.glsl.slc: - sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ -.frag.fc: - sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ -.vert.vc: - sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ - -libglsl_la_SOURCES= $(glsl_src) - -EXTRA_DIST = $(glsl_src) $(shader_src) namehack.h -CLEANFILES= *.vc *.fc *.slc diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index d684fd4ff..a437fd96e 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -57,7 +57,7 @@ #include "r_internal.h" static const char quakeforge_effect[] = -#include "quakeforge.slc" +#include "libs/video/renderer/glsl/quakeforge.slc" ; int glsl_palette; diff --git a/libs/video/renderer/sw/Makefile.am b/libs/video/renderer/sw/Makefile.am deleted file mode 100644 index 62f64e689..000000000 --- a/libs/video/renderer/sw/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -CCASFLAGS+= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -asm = @swrend_libs@ - -noinst_LTLIBRARIES= libsw.la $(asm) -EXTRA_LTLIBRARIES=libswrend_asm.la - -asm_src= \ - d_copy.S d_draw.S d_parta.S d_polysa.S d_scana.S d_spr8.S d_varsa.S \ - fpua.S surf8.S sw_raclipa.S sw_raliasa.S sw_rdrawa.S sw_redgea.S \ - sw_rvarsa.S transform.S - -sw_src= \ - d_edge.c d_fill.c d_init.c d_modech.c d_part.c d_polyse.c d_scan.c \ - d_sky.c d_sprite.c d_surf.c d_vars.c d_zpoint.c draw.c fpu.c nonintel.c \ - screen.c sw_graph.c sw_raclip.c sw_ralias.c sw_rbsp.c sw_rdraw.c \ - sw_redge.c sw_riqm.c sw_rmain.c sw_rmisc.c sw_rpart.c sw_rsky.c \ - sw_rsprite.c sw_rsurf.c \ - vid_common_sw.c - -libswrend_asm_la_LDFLAGS= @STATIC@ -libswrend_asm_la_SOURCES= $(asm_src) - -libsw_la_LDFLAGS= @STATIC@ -libsw_la_SOURCES= $(sw_src) -libsw_la_LIBADD= $(asm) -libsw_la_DEPENDENCIES= $(asm) - -EXTRA_DIST= $(sw_src) $(asm_src) diff --git a/libs/video/renderer/sw32/Makefile.am b/libs/video/renderer/sw32/Makefile.am deleted file mode 100644 index 5d078e90c..000000000 --- a/libs/video/renderer/sw32/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_LTLIBRARIES= libsw32.la - -sw32_src= \ - d_edge.c d_fill.c d_init.c d_modech.c d_part.c d_polyse.c d_scan.c \ - d_sky.c d_sprite.c d_surf.c d_vars.c d_zpoint.c draw.c screen.c \ - sw32_graph.c sw32_raclip.c sw32_ralias.c sw32_rbsp.c sw32_rdraw.c \ - sw32_redge.c sw32_riqm.c sw32_rmain.c sw32_rmisc.c sw32_rpart.c \ - sw32_rsky.c sw32_rsprite.c sw32_rsurf.c \ - vid_common_sw32.c - -libsw32_la_SOURCES= $(sw32_src) - -EXTRA_DIST= $(sw32_src) namehack.h diff --git a/libs/video/targets/Makefile.am b/libs/video/targets/Makefile.am deleted file mode 100644 index b883b676b..000000000 --- a/libs/video/targets/Makefile.am +++ /dev/null @@ -1,117 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CPPFLAGS= -I$(top_srcdir)/include - -lib_ldflags=-version-info $(QUAKE_LIBRARY_VERSION_INFO) \ - -rpath $(libdir) -no-undefined - -lib_LTLIBRARIES= @JOY_TARGETS@ - -noinst_LTLIBRARIES= @VID_TARGETS@ @vid_libs@ - -EXTRA_LTLIBRARIES= \ - libQFjs.la libQFfbdev.la libQFsvga.la libQFx11.la libQFsdl.la libQFwgl.la \ - libvid_common.la libvid_sdl.la \ - libvid_svga.la libvid_x11.la - -joy_linux_src= joy_linux.c -joy_win_src= joy_win.c -joy_null_src= joy_null.c -if JOYTYPE_LINUX -joy_src= $(joy_linux_src) -else -if JOYTYPE_WIN32 -joy_src= $(joy_win_src) -else -joy_src= $(joy_null_src) -endif -endif - -js_libs=$(top_builddir)/libs/util/libQFutil.la - -libQFjs_la_LDFLAGS= $(lib_ldflags) -libQFjs_la_LIBADD= $(js_libs) -libQFjs_la_DEPENDENCIES=$(js_libs) -libQFjs_la_CFLAGS= @PREFER_PIC@ $(JOY_CFLAGS) -libQFjs_la_SOURCES= joy.c $(joy_src) -EXTRA_libQFjs_la_SOURCES= $(joy_linux_src) $(joy_win_src) $(joy_null_src) - -libvid_common_la_SOURCES= \ - in_common.c in_event.c keys.c old_keys.c pr_keys.c vid.c -libvid_common_la_CFLAGS= @PREFER_NON_PIC@ -libvid_common_la_LDFLAGS= @STATIC@ - -libvid_x11_la_SOURCES= in_x11.c context_x11.c dga_check.c -libvid_x11_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) -libvid_x11_la_LDFLAGS= @STATIC@ - -libvid_svga_la_SOURCES= in_svgalib.c -libvid_svga_la_CFLAGS= @PREFER_NON_PIC@ $(SVGA_CFLAGS) -libvid_svga_la_LDFLAGS= @STATIC@ - -libvid_sdl_la_SOURCES= in_sdl.c context_sdl.c -libvid_sdl_la_CFLAGS= @PREFER_NON_PIC@ $(SDL_CFLAGS) -libvid_sdl_la_LDFLAGS= @STATIC@ - -# -# Linux FBdev -# -fbdev_c= fbset_modes_y.c fbset_modes_l.c -fbdev_h= fbset_modes_y.h -YFLAGS = -d -YACCLEX_CLEANFILES= $(fbdev_c) $(fbdev_h) -BUILT_SOURCES= $(fbdev_c) $(fbdev_h) - -fbdev_libs=libvid_common.la -libQFfbdev_la_CFLAGS= @PREFER_NON_PIC@ -libQFfbdev_la_SOURCES= fbset.c fbset_modes_y.y fbset_modes_l.l \ - in_fbdev.c vid_fbdev.c -libQFfbdev_la_LDFLAGS= @STATIC@ -libQFfbdev_la_LIBADD= $(fbdev_libs) -libQFfbdev_la_DEPENDENCIES= $(fbdev_libs) - - -# -# Simple DirectMedia Library -# -sdl_libs=libvid_common.la libvid_sdl.la -libQFsdl_la_CFLAGS= @PREFER_NON_PIC@ $(SDL_CFLAGS) -libQFsdl_la_SOURCES= vid_sdl.c -libQFsdl_la_LDFLAGS= @STATIC@ -libQFsdl_la_LIBADD= $(sdl_libs) -libQFsdl_la_DEPENDENCIES= $(sdl_libs) - -# -# SVGAlib -# -svga_libs=libvid_common.la libvid_svga.la -libQFsvga_la_CFLAGS= @PREFER_NON_PIC@ $(SVGA_CFLAGS) -libQFsvga_la_SOURCES= vid_svgalib.c -libQFsvga_la_LDFLAGS= @STATIC@ -libQFsvga_la_LIBADD= $(svga_libs) -libQFsvga_la_DEPENDENCIES= $(svga_libs) - -# -# OpenGL in Win32 -# -wgl_libs=libvid_common.la libvid_gl.la -libQFwgl_la_CFLAGS= @PREFER_NON_PIC@ $(WGL_CFLAGS) -libQFwgl_la_SOURCES= in_win.c vid_wgl.c -libQFwgl_la_LDFLAGS= @STATIC@ -libQFwgl_la_LIBADD= $(wgl_libs) -libQFwgl_la_DEPENDENCIES= $(wgl_libs) - -# -# X11 software rendering -# -x11_libs=libvid_common.la libvid_x11.la -libQFx11_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) -libQFx11_la_SOURCES= vid_x11.c -libQFx11_la_LDFLAGS= @STATIC@ -libQFx11_la_LIBADD= $(x11_libs) -libQFx11_la_DEPENDENCIES= $(x11_libs) - -# Kill the temp files, hopefully. -CLEANFILES = *.i *.s $(YACCLEX_CLEANFILES) - -EXTRA_DIST= $(fbdev_c) $(fbdev_h) diff --git a/libs/video/targets/Makemodule.am b/libs/video/targets/Makemodule.am new file mode 100644 index 000000000..2a279c7a8 --- /dev/null +++ b/libs/video/targets/Makemodule.am @@ -0,0 +1,115 @@ +lib_LTLIBRARIES += @JOY_TARGETS@ + +noinst_LTLIBRARIES += @VID_TARGETS@ @vid_libs@ + +EXTRA_LTLIBRARIES += \ + libs/video/targets/libQFjs.la \ + libs/video/targets/libQFfbdev.la \ + libs/video/targets/libQFsvga.la \ + libs/video/targets/libQFx11.la \ + libs/video/targets/libQFsdl.la \ + libs/video/targets/libQFwgl.la \ + libs/video/targets/libvid_common.la \ + libs/video/targets/libvid_sdl.la \ + libs/video/targets/libvid_svga.la \ + libs/video/targets/libvid_x11.la + +joy_linux_src= libs/video/targets/joy_linux.c +joy_win_src= libs/video/targets/joy_win.c +joy_null_src= libs/video/targets/joy_null.c +if JOYTYPE_LINUX +joy_src= $(joy_linux_src) +else +if JOYTYPE_WIN32 +joy_src= $(joy_win_src) +else +joy_src= $(joy_null_src) +endif +endif + +js_libs=libs/util/libQFutil.la + +libs_video_targets_libQFjs_la_LDFLAGS= $(lib_ldflags) +libs_video_targets_libQFjs_la_LIBADD= $(js_libs) +libs_video_targets_libQFjs_la_DEPENDENCIES=$(js_libs) +libs_video_targets_libQFjs_la_CFLAGS= @PREFER_PIC@ $(JOY_CFLAGS) +libs_video_targets_libQFjs_la_SOURCES= libs/video/targets/joy.c $(joy_src) +EXTRA_libs_video_targets_libQFjs_la_SOURCES= $(joy_linux_src) $(joy_win_src) $(joy_null_src) + +libs_video_targets_libvid_common_la_SOURCES= \ + libs/video/targets/in_common.c libs/video/targets/in_event.c libs/video/targets/keys.c libs/video/targets/old_keys.c libs/video/targets/pr_keys.c libs/video/targets/vid.c +libs_video_targets_libvid_common_la_CFLAGS= @PREFER_NON_PIC@ +libs_video_targets_libvid_common_la_LDFLAGS= @STATIC@ + +libs_video_targets_libvid_x11_la_SOURCES= libs/video/targets/in_x11.c libs/video/targets/context_x11.c libs/video/targets/dga_check.c +libs_video_targets_libvid_x11_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) +libs_video_targets_libvid_x11_la_LDFLAGS= @STATIC@ + +libs_video_targets_libvid_svga_la_SOURCES= libs/video/targets/in_svgalib.c +libs_video_targets_libvid_svga_la_CFLAGS= @PREFER_NON_PIC@ $(SVGA_CFLAGS) +libs_video_targets_libvid_svga_la_LDFLAGS= @STATIC@ + +libs_video_targets_libvid_sdl_la_SOURCES= libs/video/targets/in_sdl.c libs/video/targets/context_sdl.c +libs_video_targets_libvid_sdl_la_CFLAGS= @PREFER_NON_PIC@ $(SDL_CFLAGS) +libs_video_targets_libvid_sdl_la_LDFLAGS= @STATIC@ + +# +# Linux FBdev +# +fbdev_c= libs/video/targets/fbset_modes_y.c libs/video/targets/fbset_modes_l.c +fbdev_h= libs/video/targets/fbset_modes_y.h +YACCLEX_CLEANFILES = $(fbdev_c) $(fbdev_h) +BUILT_SOURCES += $(fbdev_c) $(fbdev_h) + +fbdev_libs=libs/video/targets/libvid_common.la +libs_video_targets_libQFfbdev_la_CFLAGS= @PREFER_NON_PIC@ +libs_video_targets_libQFfbdev_la_SOURCES= libs/video/targets/fbset.c libs/video/targets/fbset_modes_y.y libs/video/targets/fbset_modes_l.l \ + libs/video/targets/in_fbdev.c libs/video/targets/vid_fbdev.c +libs_video_targets_libQFfbdev_la_LDFLAGS= @STATIC@ +libs_video_targets_libQFfbdev_la_LIBADD= $(fbdev_libs) +libs_video_targets_libQFfbdev_la_DEPENDENCIES= $(fbdev_libs) + + +# +# Simple DirectMedia Library +# +sdl_libs=libs/video/targets/libvid_common.la libs/video/targets/libvid_sdl.la +libs_video_targets_libQFsdl_la_CFLAGS= @PREFER_NON_PIC@ $(SDL_CFLAGS) +libs_video_targets_libQFsdl_la_SOURCES= libs/video/targets/vid_sdl.c +libs_video_targets_libQFsdl_la_LDFLAGS= @STATIC@ +libs_video_targets_libQFsdl_la_LIBADD= $(sdl_libs) +libs_video_targets_libQFsdl_la_DEPENDENCIES= $(sdl_libs) + +# +# SVGAlib +# +svga_libs=libs/video/targets/libvid_common.la libs/video/targets/libvid_svga.la +libs_video_targets_libQFsvga_la_CFLAGS= @PREFER_NON_PIC@ $(SVGA_CFLAGS) +libs_video_targets_libQFsvga_la_SOURCES= libs/video/targets/vid_svgalib.c +libs_video_targets_libQFsvga_la_LDFLAGS= @STATIC@ +libs_video_targets_libQFsvga_la_LIBADD= $(svga_libs) +libs_video_targets_libQFsvga_la_DEPENDENCIES= $(svga_libs) + +# +# OpenGL in Win32 +# +wgl_libs=libs/video/targets/libvid_common.la libs/video/targets/libvid_gl.la +libs_video_targets_libQFwgl_la_CFLAGS= @PREFER_NON_PIC@ $(WGL_CFLAGS) +libs_video_targets_libQFwgl_la_SOURCES= libs/video/targets/in_win.c libs/video/targets/vid_wgl.c +libs_video_targets_libQFwgl_la_LDFLAGS= @STATIC@ +libs_video_targets_libQFwgl_la_LIBADD= $(wgl_libs) +libs_video_targets_libQFwgl_la_DEPENDENCIES= $(wgl_libs) + +# +# X11 software rendering +# +x11_libs=libs/video/targets/libvid_common.la libs/video/targets/libvid_x11.la +libs_video_targets_libQFx11_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) +libs_video_targets_libQFx11_la_SOURCES= libs/video/targets/vid_x11.c +libs_video_targets_libQFx11_la_LDFLAGS= @STATIC@ +libs_video_targets_libQFx11_la_LIBADD= $(x11_libs) +libs_video_targets_libQFx11_la_DEPENDENCIES= $(x11_libs) + +CLEANFILES += *.i *.s $(YACCLEX_CLEANFILES) + +EXTRA_DIST += $(fbdev_c) $(fbdev_h) diff --git a/m4/quakeforge.m4 b/m4/quakeforge.m4 index 2c3139733..984cd71f7 100644 --- a/m4/quakeforge.m4 +++ b/m4/quakeforge.m4 @@ -93,7 +93,7 @@ AC_DEFUN([QF_NEED], [m4_map_args_w([$2], [$1_need_], [=yes], [;])]) AC_DEFUN([QF_PROCESS_NEED_subroutine], [m4_foreach_w([qfn_need], [$5], [if test x"${$2[_need_]qfn_need}" = xyes; then - $4="${$4} $1[]qfn_need[]$3" + $4="${$4} m4_join([/],[$6],[$1])[]qfn_need[]$3" fi ])]) @@ -105,8 +105,8 @@ fi ])]) AC_DEFUN([QF_PROCESS_NEED_LIBS], -[m4_define([qfn_ext], m4_default($3,[la])) -QF_PROCESS_NEED_subroutine([lib$1_],[$1],[.]qfn_ext,[$1_libs],[$2]) +[m4_define([qfn_ext], m4_default($4,[la])) +QF_PROCESS_NEED_subroutine([lib$1_],[$1],[.]qfn_ext,[$1_libs],[$2],[$3]) QF_SUBST([$1_libs])]) AC_DEFUN([QF_PROCESS_NEED_DIRS], @@ -122,11 +122,11 @@ AC_DEFINE_UNQUOTED(m4_toupper(qfn_default), ["${qfn_default}"], [Define to defau ]) AC_DEFUN([QF_PROCESS_NEED_PLUGINS], -[QF_PROCESS_NEED_subroutine([$1_],[$1],[.la],[$1_plugins],[$2]) +[QF_PROCESS_NEED_subroutine([$1_],[$1],[.la],[$1_plugins],[$2],[$3]) QF_SUBST([$1_plugins]) -QF_DEFAULT_PLUGIN([$1],[$2],[$3]) -AC_DEFINE_UNQUOTED(m4_toupper(m4_default($3,$1)[_plugin_protos]), [], [list of $1 plugin prototypes]) -AC_DEFINE_UNQUOTED(m4_toupper(m4_default($3,$1)[_plugin_list]), [{0, 0}], [list of $1 plugins]) +QF_DEFAULT_PLUGIN([$1],[$2],[$4]) +AC_DEFINE_UNQUOTED(m4_toupper(m4_default($4,$1)[_plugin_protos]), [], [list of $1 plugin prototypes]) +AC_DEFINE_UNQUOTED(m4_toupper(m4_default($4,$1)[_plugin_list]), [{0, 0}], [list of $1 plugins]) ]) AC_DEFUN([QF_STATIC_PLUGIN_LIBS], @@ -147,7 +147,7 @@ fi AC_DEFINE_UNQUOTED(m4_toupper([$1_plugin_list]), [${$1_plugin_list}], [list of $1 plugins])]) AC_DEFUN([QF_PROCESS_NEED_STATIC_PLUGINS], -[QF_PROCESS_NEED_subroutine([$1_],[$1],[.la],m4_default($4,$1)[_static_plugins],[$2]) +[QF_PROCESS_NEED_subroutine([$1_],[$1],[.la],m4_default($4,$1)[_static_plugins],[$2],[$3]) QF_SUBST(m4_default($4,$1)[_static_plugins]) QF_DEFAULT_PLUGIN([$1],[$2],[$4]) QF_STATIC_PLUGIN_LIBS(m4_default($4,$1),[$1],[$2],[$3]) diff --git a/nq/Makefile.am b/nq/Makefile.am deleted file mode 100644 index 77e3cbf5b..000000000 --- a/nq/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= include source diff --git a/nq/Makemodule.am b/nq/Makemodule.am new file mode 100644 index 000000000..7e28f6401 --- /dev/null +++ b/nq/Makemodule.am @@ -0,0 +1,3 @@ +## Process this file with automake to produce Makefile.in +include nq/include/Makemodule.am +include nq/source/Makemodule.am diff --git a/nq/include/Makefile.am b/nq/include/Makefile.am deleted file mode 100644 index 60374efe3..000000000 --- a/nq/include/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -## Process this file with automake to produce Makefile.in -EXTRA_DIST= chase.h cl_skin.h client.h game.h host.h protocol.h server.h \ - sv_pr_cmds.h sv_progs.h diff --git a/nq/include/Makemodule.am b/nq/include/Makemodule.am new file mode 100644 index 000000000..ba1076749 --- /dev/null +++ b/nq/include/Makemodule.am @@ -0,0 +1,11 @@ +## Process this file with automake to produce Makefile.in +EXTRA_DIST += \ + nq/include/chase.h \ + nq/include/cl_skin.h \ + nq/include/client.h \ + nq/include/game.h \ + nq/include/host.h \ + nq/include/protocol.h \ + nq/include/server.h \ + nq/include/sv_pr_cmds.h \ + nq/include/sv_progs.h diff --git a/nq/source/Makefile.am b/nq/source/Makefile.am deleted file mode 100644 index 71cb290e8..000000000 --- a/nq/source/Makefile.am +++ /dev/null @@ -1,176 +0,0 @@ -## Process this file with automake to produce Makefile.in -# -# Makefile.am -# -# Automake-using build system for QuakeForge -# -# Copyright (C) 2000 Jeff Teunissen -# -# This Makefile 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 2 -# 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, write to: -# -# Free Software Foundation, Inc. -# 59 Temple Place - Suite 330 -# Boston, MA 02111-1307, USA -# -# $Id$ -# -AUTOMAKE_OPTIONS= foreign - -# Stuff that is common to both client and server -# -AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/nq/include -SDL_LIBS = @SDL_LIBS@ -AM_CFLAGS= @PTHREAD_CFLAGS@ - -bin_PROGRAMS= @NQ_TARGETS@ - -EXTRA_PROGRAMS= nq-fbdev nq-sdl nq-svga nq-wgl nq-x11 nq-server - -noinst_LIBRARIES= @nq_libs@ -EXTRA_LIBRARIES=libnq_client.a libnq_common.a libnq_sdl.a libnq_server.a - -libnq_common_a_SOURCES=game.c world.c -libnq_sdl_a_SOURCES= sys_sdl.c -libnq_sdl_a_CFLAGS= $(SDL_CFLAGS) - -common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@ - -cl_plugin_LIBS= \ - @server_static_plugin_libs@ \ - @client_static_plugin_libs@ - -client_LIBFILES= \ - $(top_builddir)/libs/video/targets/libQFjs.la \ - $(top_builddir)/libs/audio/libQFcd.la \ - $(top_builddir)/libs/audio/libQFsound.la - -server_LIBFILES= \ - @server_static_plugin_libs@ \ - $(top_builddir)/libs/models/libQFmodels.la - -common_LIBFILES= \ - $(top_builddir)/libs/net/libnet_main.la \ - $(top_builddir)/libs/console/libQFconsole.la \ - $(top_builddir)/libs/image/libQFimage.la \ - $(top_builddir)/libs/gib/libQFgib.la \ - $(top_builddir)/libs/ruamoko/libQFruamoko.la \ - $(top_builddir)/libs/util/libQFutil.la - -client_LIBS= $(client_LIBFILES) $(common_LIBFILES) - -server_LIBS= $(server_LIBFILES) $(common_LIBFILES) $(NET_LIBS) -server_LIB_DEPS=$(server_LIBFILES) $(common_LIBFILES) - -libnq_client_a_SOURCES= \ - cl_chase.c cl_cmd.c cl_demo.c cl_ents.c cl_input.c cl_main.c \ - cl_screen.c cl_parse.c cl_tent.c cl_view.c sbar.c - -libnq_server_a_SOURCES= \ - host.c host_cmd.c sv_cl_phys.c sv_cvar.c sv_main.c \ - sv_move.c sv_phys.c sv_pr_cmds.c sv_progs.c sv_user.c - -client_libs= libnq_server.a libnq_client.a libnq_common.a \ - $(top_builddir)/libs/client/libQFclient.la -server_libs = libnq_server.a libnq_common.a - -# Software-rendering targets - -# ... Linux FBDev -nq_fbdev_libs= \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(top_builddir)/libs/video/renderer/libQFrenderer.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/video/targets/libQFfbdev.la \ - $(client_LIBS) -nq_fbdev_SOURCES= sys_unix.c -nq_fbdev_LDADD= $(nq_fbdev_libs) $(NET_LIBS) -nq_fbdev_LDFLAGS= $(common_ldflags) -nq_fbdev_DEPENDENCIES= $(nq_fbdev_libs) - -# ... SDL, version 1.2 and higher -nq_sdl_libs= \ - libnq_sdl.a \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(top_builddir)/libs/video/renderer/libQFrenderer.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/video/targets/libQFsdl.la \ - $(client_LIBS) -nq_sdl_SOURCES=sdl_link.c -nq_sdl_LDADD= $(nq_sdl_libs) $(SDL_LIBS) $(NET_LIBS) -nq_sdl_LDFLAGS= $(common_ldflags) -nq_sdl_DEPENDENCIES= $(nq_sdl_libs) - -# ... Linux SVGAlib -nq_svga_libs= \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(top_builddir)/libs/video/renderer/libQFrenderer.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/video/targets/libQFsvga.la \ - $(client_LIBS) -nq_svga_SOURCES= sys_unix.c -nq_svga_LDADD= $(nq_svga_libs) $(SVGA_LIBS) $(NET_LIBS) -nq_svga_LDFLAGS= $(common_ldflags) -nq_svga_DEPENDENCIES= $(nq_svga_libs) - -# ... X11 -nq_x11_libs= \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(top_builddir)/libs/video/renderer/libQFrenderer.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/video/targets/libQFx11.la \ - $(client_LIBS) -nq_x11_SOURCES= sys_unix.c -nq_x11_LDADD= $(nq_x11_libs) \ - $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ - $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(DL_LIBS) -nq_x11_LDFLAGS= $(common_ldflags) -nq_x11_DEPENDENCIES= $(nq_x11_libs) - -# OpenGL-using targets - -# ... SGI/Microsoft WGL (Windows OpenGL) -nq_wgl_libs= \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(opengl_QFLIBS) \ - $(top_builddir)/libs/video/targets/libQFwgl.la \ - $(client_LIBS) -nq_wgl_SOURCES= sys_win.c -nq_wgl_LDADD= $(nq_wgl_libs) -lgdi32 -lcomctl32 -lwinmm $(NET_LIBS) -nq_wgl_LDFLAGS= $(common_ldflags) -nq_wgl_DEPENDENCIES= $(nq_wgl_libs) - -# Dedicated Server -if SYSTYPE_WIN32 -ded_sources= sys_wind.c sv_ded.c -else -ded_sources= sys_unixd.c sv_ded.c -endif -EXTRA_DIST=sys_wind.c sys_unixd.c sv_ded.c - -nq_server_LDFLAGS= $(common_ldflags) -nq_server_SOURCES= $(ded_sources) -nq_server_LDADD= $(server_libs) $(server_LIBS) -nq_server_DEPENDENCIES= $(server_libs) $(server_LIB_DEPS) - -# Stuff that doesn't get linked into an executable NEEDS to be mentioned here, -# or it won't be distributed with 'make dist' - -# Kill the temp files, hopefully. -CLEANFILES = *.i *.s $(YACCLEX_CLEANFILES) diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am new file mode 100644 index 000000000..2157cd42b --- /dev/null +++ b/nq/source/Makemodule.am @@ -0,0 +1,164 @@ +## Process this file with automake to produce Makefile.in +# +# Makefile.am +# +# Automake-using build system for QuakeForge +# +# Copyright (C) 2000 Jeff Teunissen +# +# This Makefile 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 2 +# 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, write to: +# +# Free Software Foundation, Inc. +# 59 Temple Place - Suite 330 +# Boston, MA 02111-1307, USA +# +# $Id$ +# + +# Stuff that is common to both client and server +# +bin_PROGRAMS += @NQ_TARGETS@ + +EXTRA_PROGRAMS += nq-fbdev nq-sdl nq-svga nq-wgl nq-x11 nq-server + +noinst_LIBRARIES += @nq_libs@ +EXTRA_LIBRARIES += nq/source/libnq_client.a nq/source/libnq_common.a nq/source/libnq_sdl.a nq/source/libnq_server.a + +nq_source_libnq_common_a_SOURCES= nq/source/game.c nq/source/world.c +nq_source_libnq_sdl_a_SOURCES= nq/source/sys_sdl.c +nq_source_libnq_sdl_a_CFLAGS= $(SDL_CFLAGS) + +nq_cl_plugin_LIBS= \ + @server_static_plugin_libs@ \ + @client_static_plugin_libs@ + +nq_client_LIBFILES= \ + libs/video/targets/libQFjs.la \ + libs/audio/libQFcd.la \ + libs/audio/libQFsound.la + +nq_server_LIBFILES= \ + @server_static_plugin_libs@ \ + libs/models/libQFmodels.la + +nq_common_LIBFILES= \ + libs/net/libnet_main.la \ + libs/console/libQFconsole.la \ + libs/image/libQFimage.la \ + libs/gib/libQFgib.la \ + libs/ruamoko/libQFruamoko.la \ + libs/gamecode/libQFgamecode.la \ + libs/util/libQFutil.la + +nq_client_LIBS= $(nq_client_LIBFILES) $(nq_common_LIBFILES) + +nq_server_LIBS= $(nq_server_LIBFILES) $(nq_common_LIBFILES) $(NET_LIBS) +nq_server_LIB_DEPS=$(nq_server_LIBFILES) $(nq_common_LIBFILES) + +nq_source_libnq_client_a_SOURCES= \ + nq/source/cl_chase.c nq/source/cl_cmd.c nq/source/cl_demo.c nq/source/cl_ents.c nq/source/cl_input.c nq/source/cl_main.c \ + nq/source/cl_screen.c nq/source/cl_parse.c nq/source/cl_tent.c nq/source/cl_view.c nq/source/sbar.c + +nq_source_libnq_server_a_SOURCES= \ + nq/source/host.c nq/source/host_cmd.c nq/source/sv_cl_phys.c nq/source/sv_cvar.c nq/source/sv_main.c \ + nq/source/sv_move.c nq/source/sv_phys.c nq/source/sv_pr_cmds.c nq/source/sv_progs.c nq/source/sv_user.c + +nq_client_libs= nq/source/libnq_server.a nq/source/libnq_client.a nq/source/libnq_common.a \ + libs/client/libQFclient.la +server_libs = nq/source/libnq_server.a nq/source/libnq_common.a + +# Software-rendering targets + +# ... Linux FBDev +nq_fbdev_libs= \ + $(nq_client_libs) \ + $(nq_cl_plugin_LIBS) \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFfbdev.la \ + $(nq_client_LIBS) +nq_fbdev_SOURCES= nq/source/sys_unix.c +nq_fbdev_LDADD= $(nq_fbdev_libs) $(NET_LIBS) +nq_fbdev_LDFLAGS= $(common_ldflags) +nq_fbdev_DEPENDENCIES= $(nq_fbdev_libs) + +# ... SDL, version 1.2 and higher +nq_sdl_libs= \ + nq/source/libnq_sdl.a \ + $(nq_client_libs) \ + $(nq_cl_plugin_LIBS) \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFsdl.la \ + $(nq_client_LIBS) +nq_sdl_SOURCES=nq/source/sdl_link.c +nq_sdl_LDADD= $(nq_sdl_libs) $(SDL_LIBS) $(NET_LIBS) +nq_sdl_LDFLAGS= $(common_ldflags) +nq_sdl_DEPENDENCIES= $(nq_sdl_libs) + +# ... Linux SVGAlib +nq_svga_libs= \ + $(nq_client_libs) \ + $(nq_cl_plugin_LIBS) \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFsvga.la \ + $(nq_client_LIBS) +nq_svga_SOURCES= nq/source/sys_unix.c +nq_svga_LDADD= $(nq_svga_libs) $(SVGA_LIBS) $(NET_LIBS) +nq_svga_LDFLAGS= $(common_ldflags) +nq_svga_DEPENDENCIES= $(nq_svga_libs) + +# ... X11 +nq_x11_libs= \ + $(nq_client_libs) \ + $(nq_cl_plugin_LIBS) \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFx11.la \ + $(nq_client_LIBS) +nq_x11_SOURCES= nq/source/sys_unix.c +nq_x11_LDADD= $(nq_x11_libs) \ + $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ + $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(DL_LIBS) +nq_x11_LDFLAGS= $(common_ldflags) +nq_x11_DEPENDENCIES= $(nq_x11_libs) + +# OpenGL-using targets + +# ... SGI/Microsoft WGL (Windows OpenGL) +nq_wgl_libs= \ + $(nq_client_libs) \ + $(nq_cl_plugin_LIBS) \ + $(opengl_QFLIBS) \ + libs/video/targets/libQFwgl.la \ + $(nq_client_LIBS) +nq_wgl_SOURCES= nq/source/sys_win.c +nq_wgl_LDADD= $(nq_wgl_libs) -lgdi32 -lcomctl32 -lwinmm $(NET_LIBS) +nq_wgl_LDFLAGS= $(common_ldflags) +nq_wgl_DEPENDENCIES= $(nq_wgl_libs) + +# Dedicated Server +if SYSTYPE_WIN32 +ded_sources= nq/source/sys_wind.c nq/source/sv_ded.c +else +ded_sources= nq/source/sys_unixd.c nq/source/sv_ded.c +endif +EXTRA_DIST += nq/source/sys_wind.c nq/source/sys_unixd.c nq/source/sv_ded.c + +nq_server_LDFLAGS= $(common_ldflags) +nq_server_SOURCES= $(ded_sources) +nq_server_LDADD= $(server_libs) $(nq_server_LIBS) +nq_server_DEPENDENCIES= $(server_libs) $(nq_server_LIB_DEPS) diff --git a/nq/source/cl_chase.c b/nq/source/cl_chase.c index c492ff609..92903bbfc 100644 --- a/nq/source/cl_chase.c +++ b/nq/source/cl_chase.c @@ -42,10 +42,11 @@ #include "QF/plugin/vid_render.h" -#include "chase.h" -#include "client.h" #include "world.h" +#include "nq/include/chase.h" +#include "nq/include/client.h" + vec3_t camera_origin = {0,0,0}; vec3_t camera_angles = {0,0,0}; vec3_t player_origin = {0,0,0}; diff --git a/nq/source/cl_cmd.c b/nq/source/cl_cmd.c index fabc6e226..33689dc5e 100644 --- a/nq/source/cl_cmd.c +++ b/nq/source/cl_cmd.c @@ -40,7 +40,7 @@ #include "QF/sizebuf.h" #include "QF/sys.h" -#include "client.h" +#include "nq/include/client.h" /* diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 7d47eb627..55a10af26 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -46,9 +46,10 @@ #include "QF/sys.h" #include "QF/va.h" -#include "client.h" #include "compat.h" -#include "host.h" + +#include "nq/include/client.h" +#include "nq/include/host.h" typedef struct { int frames; diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index b6bac93cd..6f6e90e29 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -44,12 +44,13 @@ #include "QF/plugin/vid_render.h" -#include "chase.h" -#include "client.h" #include "compat.h" -#include "host.h" -#include "host.h" -#include "server.h" + +#include "nq/include/chase.h" +#include "nq/include/client.h" +#include "nq/include/host.h" +#include "nq/include/host.h" +#include "nq/include/server.h" entity_t cl_entities[MAX_EDICTS]; double cl_msgtime[MAX_EDICTS]; diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index f4d175723..dd980e814 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -44,10 +44,11 @@ #include "QF/plugin/vid_render.h" -#include "chase.h" -#include "client.h" #include "compat.h" -#include "host.h" + +#include "nq/include/chase.h" +#include "nq/include/client.h" +#include "nq/include/host.h" /* KEY BUTTONS diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 7f6dd9e82..e7b90a9fb 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -48,16 +48,17 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" -#include "chase.h" -#include "cl_skin.h" -#include "client.h" -#include "clview.h" #include "compat.h" -#include "host.h" -#include "host.h" -#include "server.h" +#include "clview.h" #include "sbar.h" +#include "nq/include/chase.h" +#include "nq/include/cl_skin.h" +#include "nq/include/client.h" +#include "nq/include/host.h" +#include "nq/include/host.h" +#include "nq/include/server.h" + CLIENT_PLUGIN_PROTOS static plugin_list_t client_plugin_list[] = { CLIENT_PLUGIN_LIST diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index ea12152ff..bf9ce6418 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -53,12 +53,13 @@ #include "QF/plugin/vid_render.h" -#include "client.h" #include "compat.h" -#include "host.h" #include "sbar.h" -#include "server.h" -#include "game.h" + +#include "nq/include/client.h" +#include "nq/include/host.h" +#include "nq/include/server.h" +#include "nq/include/game.h" const char *svc_strings[] = { "svc_bad", diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 1a0f8e7be..c7940e305 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -46,9 +46,10 @@ #include "QF/plugin/vid_render.h" -#include "client.h" #include "sbar.h" +#include "nq/include/client.h" + static qpic_t *scr_net; static void diff --git a/nq/source/cl_tent.c b/nq/source/cl_tent.c index 8aa7dd2e7..89f05ee74 100644 --- a/nq/source/cl_tent.c +++ b/nq/source/cl_tent.c @@ -45,9 +45,10 @@ #include "QF/plugin/vid_render.h" -#include "client.h" #include "compat.h" +#include "nq/include/client.h" + typedef struct tent_s { struct tent_s *next; entity_t ent; diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index 6def74958..71383ff08 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -35,12 +35,13 @@ #include "QF/plugin/vid_render.h" -#include "chase.h" -#include "client.h" #include "compat.h" -#include "host.h" #include "clview.h" +#include "nq/include/chase.h" +#include "nq/include/client.h" +#include "nq/include/host.h" + /* The view is allowed to move slightly from it's true position for bobbing, but if it exceeds 8 pixels linear distance (spherical, not box), the list diff --git a/nq/source/game.c b/nq/source/game.c index f67104472..356cbb05b 100644 --- a/nq/source/game.c +++ b/nq/source/game.c @@ -35,8 +35,8 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "game.h" -#include "server.h" +#include "nq/include/game.h" +#include "nq/include/server.h" qboolean standard_quake = false; diff --git a/nq/source/host.c b/nq/source/host.c index c08a4c093..8ee5a2859 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -56,11 +56,12 @@ #include "QF/plugin/vid_render.h" #include "buildnum.h" -#include "chase.h" #include "compat.h" -#include "host.h" -#include "server.h" -#include "sv_progs.h" + +#include "nq/include/chase.h" +#include "nq/include/host.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" /* diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 31bf539b5..ce79f1212 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -50,13 +50,14 @@ #include "QF/sys.h" #include "QF/va.h" -#include "client.h" #include "compat.h" -#include "host.h" -#include "server.h" -#include "sv_progs.h" #include "world.h" +#include "nq/include/client.h" +#include "nq/include/host.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" + int current_skill; void diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 44d911118..dd8c9adef 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -53,11 +53,12 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" -#include "client.h" #include "compat.h" -#include "game.h" #include "sbar.h" -#include "server.h" + +#include "nq/include/client.h" +#include "nq/include/game.h" +#include "nq/include/server.h" int sb_updates; // if >= vid.numpages, no update needed diff --git a/nq/source/sv_cl_phys.c b/nq/source/sv_cl_phys.c index accf26af9..1b9517ccc 100644 --- a/nq/source/sv_cl_phys.c +++ b/nq/source/sv_cl_phys.c @@ -31,11 +31,12 @@ #include "QF/cvar.h" #include "QF/sys.h" -#include "host.h" -#include "server.h" -#include "sv_progs.h" #include "world.h" +#include "nq/include/host.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" + #define sv_frametime host_frametime cvar_t *sv_nostep; diff --git a/nq/source/sv_cvar.c b/nq/source/sv_cvar.c index 4d9082c96..0e8e35383 100644 --- a/nq/source/sv_cvar.c +++ b/nq/source/sv_cvar.c @@ -32,7 +32,7 @@ #include "QF/cvar.h" -#include "server.h" +#include "nq/include/server.h" void Cvar_Info (cvar_t *var) diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index c22f9cc3a..0b0cc7d0f 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -36,8 +36,8 @@ #include "QF/plugin/vid_render.h" -#include "host.h" -#include "server.h" +#include "nq/include/host.h" +#include "nq/include/server.h" client_state_t cl; client_static_t cls; diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index b666516f6..70b3d91f4 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -36,11 +36,12 @@ #include "QF/va.h" #include "compat.h" -#include "host.h" -#include "server.h" -#include "sv_progs.h" #include "world.h" +#include "nq/include/host.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" + server_t sv; server_static_t svs; double sv_frametime; diff --git a/nq/source/sv_move.c b/nq/source/sv_move.c index 013e4d48e..494fc7083 100644 --- a/nq/source/sv_move.c +++ b/nq/source/sv_move.c @@ -28,10 +28,11 @@ # include "config.h" #endif -#include "server.h" -#include "sv_progs.h" #include "world.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" + #define STEPSIZE 18 int c_yes, c_no; diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index 795fc0f6d..f36dcfde9 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -31,10 +31,11 @@ #include "QF/cvar.h" #include "QF/sys.h" -#include "server.h" -#include "sv_progs.h" #include "world.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" + /* pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index d6982bc3a..d5dcc4bb4 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -46,11 +46,12 @@ #include "QF/va.h" #include "compat.h" -#include "host.h" -#include "server.h" -#include "sv_progs.h" #include "world.h" +#include "nq/include/host.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" + /* BUILT-IN FUNCTIONS */ diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 8626ade59..baf8ad0a3 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -41,11 +41,12 @@ #include "QF/sys.h" #include "compat.h" -#include "host.h" -#include "server.h" -#include "sv_progs.h" #include "world.h" +#include "nq/include/host.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" + progs_t sv_pr_state; sv_globals_t sv_globals; sv_funcs_t sv_funcs; diff --git a/nq/source/sv_user.c b/nq/source/sv_user.c index c1db350a8..95bd01ac9 100644 --- a/nq/source/sv_user.c +++ b/nq/source/sv_user.c @@ -42,11 +42,12 @@ #include "QF/msg.h" #include "QF/sys.h" -#include "host.h" -#include "server.h" -#include "sv_progs.h" #include "world.h" +#include "nq/include/host.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" + cvar_t *sv_rollangle; cvar_t *sv_rollspeed; diff --git a/nq/source/sys_sdl.c b/nq/source/sys_sdl.c index 37ff959aa..ddc4a8df7 100644 --- a/nq/source/sys_sdl.c +++ b/nq/source/sys_sdl.c @@ -51,11 +51,11 @@ #include "QF/qargs.h" #include "QF/sys.h" -#include "client.h" -#include "host.h" +#include "nq/include/client.h" +#include "nq/include/host.h" #ifdef _WIN32 -# include "winquake.h" +# include "nq/include/winquake.h" #endif int qf_sdl_link; diff --git a/nq/source/sys_unix.c b/nq/source/sys_unix.c index 2803d31f6..20cce79a5 100644 --- a/nq/source/sys_unix.c +++ b/nq/source/sys_unix.c @@ -49,8 +49,8 @@ #include "QF/qargs.h" #include "QF/sys.h" -#include "client.h" -#include "host.h" +#include "nq/include/client.h" +#include "nq/include/host.h" qboolean isDedicated = false; diff --git a/nq/source/sys_unixd.c b/nq/source/sys_unixd.c index f9ff4ca74..18e45a8ad 100644 --- a/nq/source/sys_unixd.c +++ b/nq/source/sys_unixd.c @@ -48,7 +48,7 @@ #include "QF/qargs.h" #include "QF/sys.h" -#include "host.h" +#include "nq/include/host.h" qboolean isDedicated = true; diff --git a/nq/source/sys_win.c b/nq/source/sys_win.c index e4593ffd0..ee040f956 100644 --- a/nq/source/sys_win.c +++ b/nq/source/sys_win.c @@ -36,8 +36,8 @@ #include "QF/screen.h" #include "QF/sys.h" -#include "client.h" -#include "host.h" +#include "nq/include/client.h" +#include "nq/include/host.h" qboolean isDedicated = false; diff --git a/nq/source/sys_wind.c b/nq/source/sys_wind.c index b0555ec43..69393dfd6 100644 --- a/nq/source/sys_wind.c +++ b/nq/source/sys_wind.c @@ -34,7 +34,7 @@ #include "QF/qargs.h" #include "QF/sys.h" -#include "host.h" +#include "nq/include/host.h" qboolean isDedicated = true; diff --git a/nq/source/world.c b/nq/source/world.c index 6d404f39c..f7d379a2d 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -43,10 +43,11 @@ #include "QF/sys.h" #include "compat.h" -#include "server.h" -#include "sv_progs.h" #include "world.h" +#include "nq/include/server.h" +#include "nq/include/sv_progs.h" + #define always_inline inline __attribute__((__always_inline__)) #define EDICT_LEAFS 32 diff --git a/pkg-config/Makefile.am b/pkg-config/Makefile.am deleted file mode 100644 index 48f4005f1..000000000 --- a/pkg-config/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -pkgdatadir=@libdir@/pkgconfig - -pkgdata_DATA=quakeforge.pc qfcc.pc - -EXTRA_DIST=quakeforge.pc.in qfcc.pc.in diff --git a/pkg-config/Makemodule.am b/pkg-config/Makemodule.am new file mode 100644 index 000000000..dca513fae --- /dev/null +++ b/pkg-config/Makemodule.am @@ -0,0 +1,5 @@ +pkgconfigdir = @libdir@/pkgconfig + +pkgconfig_DATA = pkg-config/quakeforge.pc pkg-config/qfcc.pc + +EXTRA_DIST += pkg-config/quakeforge.pc.in pkg-config/qfcc.pc.in diff --git a/qtv/Makefile.am b/qtv/Makefile.am deleted file mode 100644 index 77e3cbf5b..000000000 --- a/qtv/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= include source diff --git a/qtv/Makemodule.am b/qtv/Makemodule.am new file mode 100644 index 000000000..562039b04 --- /dev/null +++ b/qtv/Makemodule.am @@ -0,0 +1,2 @@ +include qtv/include/Makemodule.am +include qtv/source/Makemodule.am diff --git a/qtv/include/Makefile.am b/qtv/include/Makefile.am deleted file mode 100644 index 19df055f3..000000000 --- a/qtv/include/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST = client.h connection.h qtv.h server.h diff --git a/qtv/include/Makemodule.am b/qtv/include/Makemodule.am new file mode 100644 index 000000000..346c1716d --- /dev/null +++ b/qtv/include/Makemodule.am @@ -0,0 +1,5 @@ +EXTRA_DIST += \ + qtv/include/client.h \ + qtv/include/connection.h \ + qtv/include/qtv.h \ + qtv/include/server.h diff --git a/qtv/source/Makefile.am b/qtv/source/Makemodule.am similarity index 61% rename from qtv/source/Makefile.am rename to qtv/source/Makemodule.am index fa73f8de8..3560edecf 100644 --- a/qtv/source/Makefile.am +++ b/qtv/source/Makemodule.am @@ -27,27 +27,18 @@ # $Id$ # -AUTOMAKE_OPTIONS= foreign +bin_PROGRAMS += @QTV_TARGETS@ -AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/qtv/include - -bin_PROGRAMS= @QTV_TARGETS@ - -EXTRA_PROGRAMS= qtv - -common_ldflags= -export-dynamic +EXTRA_PROGRAMS += qtv-server qtv_LIBS= \ @server_static_plugin_libs@ \ - $(top_builddir)/libs/qw/libqw.a \ - $(top_builddir)/libs/net/libnet_chan.la \ - $(top_builddir)/libs/console/libQFconsole.la \ - $(top_builddir)/libs/util/libQFutil.la + libs/qw/libqw.a \ + libs/net/libnet_chan.la \ + libs/console/libQFconsole.la \ + libs/util/libQFutil.la -qtv_SOURCES= client.c connection.c qtv.c sbar.c server.c sv_parse.c -qtv_LDADD= $(qtv_LIBS) $(NET_LIBS) $(DL_LIBS) $(CURSES_LIBS) -qtv_LDFLAGS= $(common_ldflags) -qtv_DEPENDENCIES= $(qtv_LIBS) - -# Kill the temp files, hopefully. -CLEANFILES = *.i *.s +qtv_server_SOURCES= qtv/source/client.c qtv/source/connection.c qtv/source/qtv.c qtv/source/sbar.c qtv/source/server.c qtv/source/sv_parse.c +qtv_server_LDADD= $(qtv_LIBS) $(NET_LIBS) $(DL_LIBS) $(CURSES_LIBS) +qtv_server_LDFLAGS= $(common_ldflags) +qtv_server_DEPENDENCIES= $(qtv_LIBS) diff --git a/qtv/source/client.c b/qtv/source/client.c index 24b0e23b2..06955b12f 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -55,10 +55,10 @@ #include "qw/msg_ucmd.h" #include "qw/protocol.h" -#include "client.h" -#include "connection.h" -#include "qtv.h" -#include "server.h" +#include "qtv/include/client.h" +#include "qtv/include/connection.h" +#include "qtv/include/qtv.h" +#include "qtv/include/server.h" int client_count; static client_t *clients; diff --git a/qtv/source/connection.c b/qtv/source/connection.c index 52f159060..e670880f3 100644 --- a/qtv/source/connection.c +++ b/qtv/source/connection.c @@ -46,7 +46,7 @@ #include "QF/hash.h" #include "QF/sys.h" -#include "connection.h" +#include "qtv/include/connection.h" static hashtab_t *connections; diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 1274254d5..a44fdf45d 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -56,14 +56,15 @@ #include "QF/plugin/console.h" +#include "compat.h" +#include "netchan.h" + #include "qw/protocol.h" -#include "client.h" -#include "compat.h" -#include "connection.h" -#include "netchan.h" -#include "qtv.h" -#include "server.h" +#include "qtv/include/client.h" +#include "qtv/include/connection.h" +#include "qtv/include/qtv.h" +#include "qtv/include/server.h" #undef qtv_print diff --git a/qtv/source/sbar.c b/qtv/source/sbar.c index 73015d00a..092c85ea1 100644 --- a/qtv/source/sbar.c +++ b/qtv/source/sbar.c @@ -37,10 +37,11 @@ #include "QF/plugin/console.h" -#include "client.h" -#include "server.h" #include "sv_console.h" -#include "qtv.h" + +#include "qtv/include/client.h" +#include "qtv/include/server.h" +#include "qtv/include/qtv.h" static void draw_clients (view_t *view) diff --git a/qtv/source/server.c b/qtv/source/server.c index 855bc492c..c376905d2 100644 --- a/qtv/source/server.c +++ b/qtv/source/server.c @@ -54,10 +54,10 @@ #include "qw/protocol.h" -#include "client.h" -#include "connection.h" -#include "qtv.h" -#include "server.h" +#include "qtv/include/client.h" +#include "qtv/include/connection.h" +#include "qtv/include/qtv.h" +#include "qtv/include/server.h" int server_count; static hashtab_t *server_hash; diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index 48198e809..c179d125e 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -56,10 +56,10 @@ #include "qw/msg_ucmd.h" #include "qw/protocol.h" -#include "client.h" -#include "connection.h" -#include "qtv.h" -#include "server.h" +#include "qtv/include/client.h" +#include "qtv/include/connection.h" +#include "qtv/include/qtv.h" +#include "qtv/include/server.h" static void sv_serverdata (server_t *sv, qmsg_t *msg) diff --git a/qw/Makefile.am b/qw/Makefile.am deleted file mode 100644 index 77e3cbf5b..000000000 --- a/qw/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= include source diff --git a/qw/Makemodule.am b/qw/Makemodule.am new file mode 100644 index 000000000..9fca70d9b --- /dev/null +++ b/qw/Makemodule.am @@ -0,0 +1,2 @@ +include qw/include/Makemodule.am +include qw/source/Makemodule.am diff --git a/qw/include/Makefile.am b/qw/include/Makefile.am deleted file mode 100644 index 67535b195..000000000 --- a/qw/include/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST = \ - chase.h cl_cam.h cl_chat.h cl_demo.h cl_ents.h cl_http.h cl_input.h \ - cl_main.h cl_parse.h cl_pred.h cl_skin.h cl_slist.h cl_tent.h \ - client.h crudefile.h game.h host.h map_cfg.h server.h sv_gib.h \ - sv_demo.h sv_pr_cmds.h sv_pr_cpqw.h sv_pr_qwe.h sv_progs.h sv_qtv.h \ - sv_recorder.h diff --git a/qw/include/Makemodule.am b/qw/include/Makemodule.am new file mode 100644 index 000000000..2f5076b12 --- /dev/null +++ b/qw/include/Makemodule.am @@ -0,0 +1,28 @@ +EXTRA_DIST += \ + qw/include/chase.h \ + qw/include/cl_cam.h \ + qw/include/cl_chat.h \ + qw/include/cl_demo.h \ + qw/include/cl_ents.h \ + qw/include/cl_http.h \ + qw/include/cl_input.h \ + qw/include/cl_main.h \ + qw/include/cl_parse.h \ + qw/include/cl_pred.h \ + qw/include/cl_skin.h \ + qw/include/cl_slist.h \ + qw/include/cl_tent.h \ + qw/include/client.h \ + qw/include/crudefile.h \ + qw/include/game.h \ + qw/include/host.h \ + qw/include/map_cfg.h \ + qw/include/server.h \ + qw/include/sv_gib.h \ + qw/include/sv_demo.h \ + qw/include/sv_pr_cmds.h \ + qw/include/sv_pr_cpqw.h \ + qw/include/sv_pr_qwe.h \ + qw/include/sv_progs.h \ + qw/include/sv_qtv.h \ + qw/include/sv_recorder.h diff --git a/qw/source/Makefile.am b/qw/source/Makefile.am deleted file mode 100644 index 9afe77ae1..000000000 --- a/qw/source/Makefile.am +++ /dev/null @@ -1,191 +0,0 @@ -## Process this file with automake to produce Makefile.in -# -# Makefile.am -# -# Automake-using build system for QuakeForge -# -# Copyright (C) 2000 Jeff Teunissen -# -# This Makefile 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 2 -# 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, write to: -# -# Free Software Foundation, Inc. -# 59 Temple Place - Suite 330 -# Boston, MA 02111-1307, USA -# -# $Id$ -# - -AUTOMAKE_OPTIONS= foreign - -# Stuff that is common to both client and server -AM_CPPFLAGS= -I$(top_srcdir)/include -I$(top_srcdir)/qw/include @LIBCURL_CFLAGS@ -SDL_LIBS = @SDL_LIBS@ -AM_CFLAGS= @PTHREAD_CFLAGS@ - -bin_PROGRAMS= @QW_TARGETS@ - -EXTRA_PROGRAMS= \ - qw-client-fbdev qw-client-sdl qw-client-svga qw-client-wgl qw-client-x11 \ - qw-server qw-master - -noinst_LIBRARIES= @qw_libs@ -EXTRA_LIBRARIES=libqw_client.a libqw_common.a libqw_sdl.a libqw_server.a - - -libqw_common_a_SOURCES=\ - game.c map_cfg.c pmove.c pmovetst.c net_packetlog.c -libqw_sdl_a_SOURCES=cl_sys_sdl.c -libqw_sdl_a_CFLAGS=$(SDL_CFLAGS) - -common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@ - -# Server builds -# -# ... System type -if SYSTYPE_WIN32 -syssv_SRC= sv_sys_win.c -else -syssv_SRC= sv_sys_unix.c -endif - -EXTRA_DIST=sv_sys_win.c sv_sys_unix.c - -libqw_server_a_SOURCES= \ - crudefile.c sv_ccmds.c sv_demo.c sv_ents.c sv_gib.c sv_init.c sv_main.c \ - sv_move.c sv_phys.c sv_pr_cmds.c sv_pr_cpqw.c sv_pr_qwe.c sv_progs.c \ - sv_qtv.c sv_recorder.c sv_sbar.c sv_send.c sv_user.c world.c - -qw_server_LIBS= \ - @server_static_plugin_libs@ \ - $(top_builddir)/libs/qw/libqw.a \ - $(top_builddir)/libs/net/libnet_chan.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/gib/libQFgib.la \ - $(top_builddir)/libs/ruamoko/libQFruamoko.la \ - $(top_builddir)/libs/console/libQFconsole.la \ - $(top_builddir)/libs/util/libQFutil.la - -qw_server_deps=libqw_server.a libqw_common.a $(qw_server_LIBS) -qw_server_SOURCES= $(syssv_SRC) -qw_server_LDADD= $(qw_server_deps) $(NET_LIBS) $(DL_LIBS) $(CURSES_LIBS) -qw_server_LDFLAGS= $(common_ldflags) -qw_server_DEPENDENCIES= $(qw_server_deps) - -qw_master_deps=$(top_builddir)/libs/util/libQFutil.la -qw_master_SOURCES= master.c -qw_master_LDADD= $(qw_master_deps) $(NET_LIBS) -qw_master_DEPENDENCIES= $(qw_master_deps) -qw_master_LDFLAGS= $(common_ldflags) - -cl_plugin_LIBS= \ - @client_static_plugin_libs@ - -qw_client_LIBS= \ - $(top_builddir)/libs/qw/libqw.a \ - $(top_builddir)/libs/net/libnet_chan.la \ - $(top_builddir)/libs/console/libQFconsole.la \ - $(top_builddir)/libs/video/targets/libQFjs.la \ - $(top_builddir)/libs/audio/libQFcd.la \ - $(top_builddir)/libs/audio/libQFsound.la \ - $(top_builddir)/libs/image/libQFimage.la \ - $(top_builddir)/libs/gib/libQFgib.la \ - $(top_builddir)/libs/ruamoko/libQFruamoko.la \ - $(top_builddir)/libs/util/libQFutil.la - -client_LIBS= $(qw_client_LIBS) -client_libs= libqw_client.a libqw_common.a \ - $(top_builddir)/libs/client/libQFclient.la - -libqw_client_a_SOURCES= \ - cl_cam.c cl_chase.c cl_chat.c cl_cmd.c cl_cvar.c cl_demo.c \ - cl_entparse.c cl_ents.c cl_http.c cl_input.c cl_main.c cl_ngraph.c \ - cl_parse.c cl_pred.c cl_rss.c cl_screen.c cl_skin.c cl_slist.c \ - cl_tent.c cl_view.c \ - locs.c sbar.c teamplay.c - -# Software-rendering clients - -# ... Linux FBDev -qw_client_fbdev_libs= \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(top_builddir)/libs/video/renderer/libQFrenderer.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/video/targets/libQFfbdev.la \ - $(client_LIBS) -qw_client_fbdev_SOURCES= cl_sys_unix.c -qw_client_fbdev_LDADD= $(qw_client_fbdev_libs) $(NET_LIBS) $(LIBCURL_LIBS) -qw_client_fbdev_LDFLAGS= $(common_ldflags) -qw_client_fbdev_DEPENDENCIES= $(qw_client_fbdev_libs) - -# ... Simple DirectMedia Layer, version 1.2 and higher -qw_client_sdl_libs= \ - libqw_sdl.a \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(top_builddir)/libs/video/renderer/libQFrenderer.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/video/targets/libQFsdl.la \ - $(client_LIBS) -qw_client_sdl_SOURCES=sdl_link.c -qw_client_sdl_LDADD= libqw_sdl.a $(qw_client_sdl_libs) $(SDL_LIBS) $(NET_LIBS) $(LIBCURL_LIBS) -qw_client_sdl_LDFLAGS= $(common_ldflags) -qw_client_sdl_DEPENDENCIES= libqw_sdl.a $(qw_client_sdl_libs) - -# ... Linux SVGAlib -qw_client_svga_libs= \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(top_builddir)/libs/video/renderer/libQFrenderer.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/video/targets/libQFsvga.la \ - $(client_LIBS) -qw_client_svga_SOURCES= cl_sys_unix.c -qw_client_svga_LDADD= $(qw_client_svga_libs) $(SVGA_LIBS) $(NET_LIBS) $(LIBCURL_LIBS) -qw_client_svga_LDFLAGS= $(common_ldflags) -qw_client_svga_DEPENDENCIES= $(qw_client_svga_libs) - -# ... X11 -qw_client_x11_libs= \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(top_builddir)/libs/video/renderer/libQFrenderer.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/video/targets/libQFx11.la \ - $(client_LIBS) -qw_client_x11_SOURCES= cl_sys_unix.c -qw_client_x11_LDADD= $(qw_client_x11_libs) \ - $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ - $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(LIBCURL_LIBS) $(DL_LIBS) -qw_client_x11_LDFLAGS= $(common_ldflags) -qw_client_x11_DEPENDENCIES= $(qw_client_x11_libs) - -# ... SGI/Microsoft WGL (Windows OpenGL) -qw_client_wgl_libs= \ - $(client_libs) \ - $(cl_plugin_LIBS) \ - $(opengl_LIBS) \ - $(top_builddir)/libs/video/targets/libQFwgl.la \ - $(client_LIBS) -qw_client_wgl_SOURCES= cl_sys_win.c -qw_client_wgl_LDADD= $(qw_client_wgl_libs) -lgdi32 -lwinmm $(NET_LIBS) $(LIBCURL_LIBS) -qw_client_wgl_LDFLAGS= $(common_ldflags) -qw_client_wgl_DEPENDENCIES= $(qw_client_wgl_libs) - -# Stuff that doesn't get linked into an executable NEEDS to be mentioned here, -# or it won't be distributed with 'make dist' - -# Kill the temp files, hopefully. -CLEANFILES = *.i *.s $(YACCLEX_CLEANFILES) diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am new file mode 100644 index 000000000..553a32f65 --- /dev/null +++ b/qw/source/Makemodule.am @@ -0,0 +1,175 @@ +## Process this file with automake to produce Makefile.in +# +# Makefile.am +# +# Automake-using build system for QuakeForge +# +# Copyright (C) 2000 Jeff Teunissen +# +# This Makefile 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 2 +# 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, write to: +# +# Free Software Foundation, Inc. +# 59 Temple Place - Suite 330 +# Boston, MA 02111-1307, USA +# +# $Id$ +# + +bin_PROGRAMS += @QW_TARGETS@ + +EXTRA_PROGRAMS += \ + qw-client-fbdev qw-client-sdl qw-client-svga qw-client-wgl qw-client-x11 \ + qw-server qw-master + +noinst_LIBRARIES += @qw_libs@ +EXTRA_LIBRARIES += qw/source/libqw_client.a qw/source/libqw_common.a qw/source/libqw_sdl.a qw/source/libqw_server.a + + +qw_source_libqw_common_a_SOURCES=\ + qw/source/game.c qw/source/map_cfg.c qw/source/pmove.c qw/source/pmovetst.c qw/source/net_packetlog.c +qw_source_libqw_sdl_a_SOURCES=qw/source/cl_sys_sdl.c +qw_source_libqw_sdl_a_CFLAGS=$(SDL_CFLAGS) + +# Server builds +# +# ... System type +if SYSTYPE_WIN32 +syssv_SRC= qw/source/sv_sys_win.c +else +syssv_SRC= qw/source/sv_sys_unix.c +endif + +EXTRA_DIST+=qw/source/sv_sys_win.c qw/source/sv_sys_unix.c + +qw_source_libqw_server_a_SOURCES= \ + qw/source/crudefile.c qw/source/sv_ccmds.c qw/source/sv_demo.c qw/source/sv_ents.c qw/source/sv_gib.c qw/source/sv_init.c qw/source/sv_main.c \ + qw/source/sv_move.c qw/source/sv_phys.c qw/source/sv_pr_cmds.c qw/source/sv_pr_cpqw.c qw/source/sv_pr_qwe.c qw/source/sv_progs.c \ + qw/source/sv_qtv.c qw/source/sv_recorder.c qw/source/sv_sbar.c qw/source/sv_send.c qw/source/sv_user.c qw/source/world.c + +qw_server_LIBS= \ + @server_static_plugin_libs@ \ + libs/qw/libqw.a \ + libs/net/libnet_chan.la \ + libs/models/libQFmodels.la \ + libs/gib/libQFgib.la \ + libs/ruamoko/libQFruamoko.la \ + libs/gamecode/libQFgamecode.la \ + libs/console/libQFconsole.la \ + libs/util/libQFutil.la + +qw_server_deps=qw/source/libqw_server.a qw/source/libqw_common.a $(qw_server_LIBS) +qw_server_SOURCES= $(syssv_SRC) +qw_server_LDADD= $(qw_server_deps) $(NET_LIBS) $(DL_LIBS) $(CURSES_LIBS) +qw_server_LDFLAGS= $(common_ldflags) +qw_server_DEPENDENCIES= $(qw_server_deps) + +qw_master_deps=libs/util/libQFutil.la +qw_master_SOURCES= qw/source/master.c +qw_master_LDADD= $(qw_master_deps) $(NET_LIBS) +qw_master_DEPENDENCIES= $(qw_master_deps) +qw_master_LDFLAGS= $(common_ldflags) + +qw_cl_plugin_LIBS= \ + @client_static_plugin_libs@ + +qw_client_LIBS= \ + libs/qw/libqw.a \ + libs/net/libnet_chan.la \ + libs/console/libQFconsole.la \ + libs/video/targets/libQFjs.la \ + libs/audio/libQFcd.la \ + libs/audio/libQFsound.la \ + libs/image/libQFimage.la \ + libs/gib/libQFgib.la \ + libs/ruamoko/libQFruamoko.la \ + libs/util/libQFutil.la +qw_client_libs= qw/source/libqw_client.a qw/source/libqw_common.a \ + libs/client/libQFclient.la + +qw_source_libqw_client_a_SOURCES= \ + qw/source/cl_cam.c qw/source/cl_chase.c qw/source/cl_chat.c qw/source/cl_cmd.c qw/source/cl_cvar.c qw/source/cl_demo.c \ + qw/source/cl_entparse.c qw/source/cl_ents.c qw/source/cl_http.c qw/source/cl_input.c qw/source/cl_main.c qw/source/cl_ngraph.c \ + qw/source/cl_parse.c qw/source/cl_pred.c qw/source/cl_rss.c qw/source/cl_screen.c qw/source/cl_skin.c qw/source/cl_slist.c \ + qw/source/cl_tent.c qw/source/cl_view.c \ + qw/source/locs.c qw/source/sbar.c qw/source/teamplay.c + +# Software-rendering clients + +# ... Linux FBDev +qw_client_fbdev_libs= \ + $(qw_client_libs) \ + $(qw_cl_plugin_LIBS) \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFfbdev.la \ + $(qw_client_LIBS) +qw_client_fbdev_SOURCES= qw/source/cl_sys_unix.c +qw_client_fbdev_LDADD= $(qw_client_fbdev_libs) $(NET_LIBS) $(LIBCURL_LIBS) +qw_client_fbdev_LDFLAGS= $(common_ldflags) +qw_client_fbdev_DEPENDENCIES= $(qw_client_fbdev_libs) + +# ... Simple DirectMedia Layer, version 1.2 and higher +qw_client_sdl_libs= \ + qw/source/libqw_sdl.a \ + $(qw_client_libs) \ + $(qw_cl_plugin_LIBS) \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFsdl.la \ + $(qw_client_LIBS) +qw_client_sdl_SOURCES=qw/source/sdl_link.c +qw_client_sdl_LDADD= qw/source/libqw_sdl.a $(qw_client_sdl_libs) $(SDL_LIBS) $(NET_LIBS) $(LIBCURL_LIBS) +qw_client_sdl_LDFLAGS= $(common_ldflags) +qw_client_sdl_DEPENDENCIES= qw/source/libqw_sdl.a $(qw_client_sdl_libs) + +# ... Linux SVGAlib +qw_client_svga_libs= \ + $(qw_client_libs) \ + $(qw_cl_plugin_LIBS) \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFsvga.la \ + $(qw_client_LIBS) +qw_client_svga_SOURCES= qw/source/cl_sys_unix.c +qw_client_svga_LDADD= $(qw_client_svga_libs) $(SVGA_LIBS) $(NET_LIBS) $(LIBCURL_LIBS) +qw_client_svga_LDFLAGS= $(common_ldflags) +qw_client_svga_DEPENDENCIES= $(qw_client_svga_libs) + +# ... X11 +qw_client_x11_libs= \ + $(qw_client_libs) \ + $(qw_cl_plugin_LIBS) \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFx11.la \ + $(qw_client_LIBS) +qw_client_x11_SOURCES= qw/source/cl_sys_unix.c +qw_client_x11_LDADD= $(qw_client_x11_libs) \ + $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ + $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(LIBCURL_LIBS) $(DL_LIBS) +qw_client_x11_LDFLAGS= $(common_ldflags) +qw_client_x11_DEPENDENCIES= $(qw_client_x11_libs) + +# ... SGI/Microsoft WGL (Windows OpenGL) +qw_client_wgl_libs= \ + $(qw_client_libs) \ + $(qw_cl_plugin_LIBS) \ + $(opengl_LIBS) \ + libs/video/targets/libQFwgl.la \ + $(qw_client_LIBS) +qw_client_wgl_SOURCES= qw/source/cl_sys_win.c +qw_client_wgl_LDADD= $(qw_client_wgl_libs) -lgdi32 -lwinmm $(NET_LIBS) $(LIBCURL_LIBS) +qw_client_wgl_LDFLAGS= $(common_ldflags) +qw_client_wgl_DEPENDENCIES= $(qw_client_wgl_libs) diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index f7e9adf44..5a7f0d486 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -45,14 +45,15 @@ #include "QF/cvar.h" #include "QF/msg.h" -#include "chase.h" -#include "cl_cam.h" -#include "cl_input.h" -#include "client.h" #include "compat.h" -#include "qw/pmove.h" #include "sbar.h" +#include "qw/include/chase.h" +#include "qw/include/cl_cam.h" +#include "qw/include/cl_input.h" +#include "qw/include/client.h" +#include "qw/pmove.h" + #define PM_SPECTATORMAXSPEED 500 #define PM_STOPSPEED 100 #define PM_MAXSPEED 320 diff --git a/qw/source/cl_chase.c b/qw/source/cl_chase.c index 26f5b02b4..2e5583429 100644 --- a/qw/source/cl_chase.c +++ b/qw/source/cl_chase.c @@ -42,9 +42,9 @@ #include "QF/plugin/vid_render.h" -#include "chase.h" -#include "cl_input.h" -#include "client.h" +#include "qw/include/chase.h" +#include "qw/include/cl_input.h" +#include "qw/include/client.h" #include "world.h" vec3_t camera_origin = {0,0,0}; diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index 2b40e64dd..7a3dcb186 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -44,8 +44,8 @@ #include "QF/sys.h" #include "QF/va.h" -#include "client.h" -#include "cl_chat.h" +#include "qw/include/client.h" +#include "qw/include/cl_chat.h" llist_t *ignore_list, *dead_ignore_list; diff --git a/qw/source/cl_cmd.c b/qw/source/cl_cmd.c index a38dbc875..3b0f7b072 100644 --- a/qw/source/cl_cmd.c +++ b/qw/source/cl_cmd.c @@ -42,7 +42,7 @@ #include "QF/sys.h" #include "QF/teamplay.h" -#include "client.h" +#include "qw/include/client.h" static void send_say (const char *str) diff --git a/qw/source/cl_cvar.c b/qw/source/cl_cvar.c index c92322c7c..ebd569ba8 100644 --- a/qw/source/cl_cvar.c +++ b/qw/source/cl_cvar.c @@ -39,9 +39,10 @@ #include "QF/msg.h" #include "QF/va.h" -#include "client.h" #include "compat.h" +#include "qw/include/client.h" + void Cvar_Info (cvar_t *var) { diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 04ccbdf55..51c709adc 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -54,13 +54,14 @@ #include "QF/sys.h" #include "QF/va.h" -#include "cl_cam.h" -#include "cl_demo.h" -#include "cl_ents.h" -#include "cl_main.h" -#include "client.h" #include "compat.h" -#include "host.h" + +#include "qw/include/cl_cam.h" +#include "qw/include/cl_demo.h" +#include "qw/include/cl_ents.h" +#include "qw/include/cl_main.h" +#include "qw/include/client.h" +#include "qw/include/host.h" #include "qw/pmove.h" typedef struct { diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index ffad98174..3fdeda901 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -42,21 +42,21 @@ #include "QF/skin.h" #include "QF/sys.h" -#include "qw/msg_ucmd.h" - -#include "qw/bothdefs.h" -#include "cl_cam.h" -#include "cl_ents.h" -#include "cl_main.h" -#include "cl_parse.h" -#include "cl_pred.h" -#include "cl_tent.h" #include "compat.h" -#include "d_iface.h" -#include "host.h" -#include "qw/pmove.h" #include "clview.h" +#include "qw/msg_ucmd.h" +#include "qw/pmove.h" +#include "qw/bothdefs.h" + +#include "qw/include/cl_cam.h" +#include "qw/include/cl_ents.h" +#include "qw/include/cl_main.h" +#include "qw/include/cl_parse.h" +#include "qw/include/cl_pred.h" +#include "qw/include/cl_tent.h" +#include "qw/include/host.h" + static struct predicted_player { int flags; qboolean active; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index edd048090..24f14933b 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -42,21 +42,22 @@ #include "QF/skin.h" #include "QF/sys.h" -#include "qw/msg_ucmd.h" +#include "compat.h" +#include "clview.h" +#include "d_iface.h" #include "qw/bothdefs.h" -#include "chase.h" -#include "cl_cam.h" -#include "cl_ents.h" -#include "cl_main.h" -#include "cl_parse.h" -#include "cl_pred.h" -#include "cl_tent.h" -#include "compat.h" -#include "d_iface.h" -#include "host.h" +#include "qw/msg_ucmd.h" #include "qw/pmove.h" -#include "clview.h" + +#include "qw/include/chase.h" +#include "qw/include/cl_cam.h" +#include "qw/include/cl_ents.h" +#include "qw/include/cl_main.h" +#include "qw/include/cl_parse.h" +#include "qw/include/cl_pred.h" +#include "qw/include/cl_tent.h" +#include "qw/include/host.h" entity_t cl_player_ents[MAX_CLIENTS]; entity_t cl_flag_ents[MAX_CLIENTS]; diff --git a/qw/source/cl_http.c b/qw/source/cl_http.c index 38bd9f204..b13986cf2 100644 --- a/qw/source/cl_http.c +++ b/qw/source/cl_http.c @@ -38,9 +38,9 @@ #include "QF/dstring.h" #include "QF/sys.h" -#include "cl_http.h" -#include "cl_parse.h" -#include "client.h" +#include "qw/include/cl_http.h" +#include "qw/include/cl_parse.h" +#include "qw/include/client.h" static int curl_borked; static CURL *easy_handle; @@ -129,7 +129,7 @@ CL_HTTP_Reset (void) #else -#include "cl_http.h" +#include "qw/include/cl_http.h" void CL_HTTP_Init (void) {} void CL_HTTP_Shutdown (void) {} diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index e80ea4714..55ef38f5d 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -45,17 +45,18 @@ #include "QF/teamplay.h" #include "QF/va.h" +#include "compat.h" +#include "clview.h" + #include "qw/msg_ucmd.h" -#include "chase.h" -#include "cl_cam.h" -#include "cl_demo.h" -#include "cl_input.h" -#include "cl_parse.h" -#include "client.h" -#include "compat.h" -#include "host.h" -#include "clview.h" +#include "qw/include/chase.h" +#include "qw/include/cl_cam.h" +#include "qw/include/cl_demo.h" +#include "qw/include/cl_input.h" +#include "qw/include/cl_parse.h" +#include "qw/include/client.h" +#include "qw/include/host.h" cvar_t *cl_nodelta; cvar_t *cl_maxnetfps; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index b78038ca9..08754ffc2 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -91,28 +91,30 @@ #include "QF/plugin/console.h" -#include "qw/bothdefs.h" #include "buildnum.h" -#include "cl_cam.h" -#include "cl_chat.h" -#include "cl_demo.h" -#include "cl_ents.h" -#include "cl_http.h" -#include "cl_input.h" -#include "cl_main.h" -#include "cl_parse.h" -#include "cl_pred.h" -#include "cl_skin.h" -#include "cl_slist.h" -#include "cl_tent.h" -#include "client.h" -#include "compat.h" -#include "game.h" -#include "host.h" -#include "netchan.h" -#include "qw/pmove.h" -#include "sbar.h" #include "clview.h" +#include "compat.h" +#include "sbar.h" + +#include "qw/bothdefs.h" +#include "qw/pmove.h" + +#include "qw/include/cl_cam.h" +#include "qw/include/cl_chat.h" +#include "qw/include/cl_demo.h" +#include "qw/include/cl_ents.h" +#include "qw/include/cl_http.h" +#include "qw/include/cl_input.h" +#include "qw/include/cl_main.h" +#include "qw/include/cl_parse.h" +#include "qw/include/cl_pred.h" +#include "qw/include/cl_skin.h" +#include "qw/include/cl_slist.h" +#include "qw/include/cl_tent.h" +#include "qw/include/client.h" +#include "qw/include/game.h" +#include "qw/include/host.h" +#include "netchan.h" CLIENT_PLUGIN_PROTOS static plugin_list_t client_plugin_list[] = { diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 2503c8ee4..21891f471 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -41,8 +41,9 @@ #include "QF/screen.h" #include "compat.h" -#include "cl_parse.h" -#include "client.h" + +#include "qw/include/cl_parse.h" +#include "qw/include/client.h" #include "sbar.h" cvar_t *r_netgraph; diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index a271c1197..2446413d6 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -61,24 +61,26 @@ #include "QF/teamplay.h" #include "QF/va.h" -#include "qw/bothdefs.h" -#include "cl_cam.h" -#include "cl_chat.h" -#include "cl_ents.h" -#include "cl_http.h" -#include "cl_input.h" -#include "cl_main.h" -#include "cl_parse.h" -#include "cl_skin.h" -#include "cl_tent.h" -#include "client.h" #include "compat.h" -#include "host.h" -#include "map_cfg.h" +#include "clview.h" +#include "sbar.h" + +#include "qw/bothdefs.h" #include "qw/pmove.h" #include "qw/protocol.h" -#include "sbar.h" -#include "clview.h" + +#include "qw/include/cl_cam.h" +#include "qw/include/cl_chat.h" +#include "qw/include/cl_ents.h" +#include "qw/include/cl_http.h" +#include "qw/include/cl_input.h" +#include "qw/include/cl_main.h" +#include "qw/include/cl_parse.h" +#include "qw/include/cl_skin.h" +#include "qw/include/cl_tent.h" +#include "qw/include/client.h" +#include "qw/include/host.h" +#include "qw/include/map_cfg.h" const char *svc_strings[] = { "svc_bad", diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index 6b110e46c..1ac6e5ca1 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -34,11 +34,12 @@ #include "QF/cvar.h" #include "QF/keys.h" -#include "qw/bothdefs.h" #include "compat.h" -#include "cl_ents.h" -#include "cl_pred.h" -#include "client.h" + +#include "qw/bothdefs.h" +#include "qw/include/cl_ents.h" +#include "qw/include/cl_pred.h" +#include "qw/include/client.h" #include "qw/pmove.h" cvar_t *cl_predict; diff --git a/qw/source/cl_rss.c b/qw/source/cl_rss.c index 447e25dcc..bb4cbd993 100644 --- a/qw/source/cl_rss.c +++ b/qw/source/cl_rss.c @@ -42,8 +42,8 @@ #include "QF/pcx.h" #include "QF/sys.h" -#include "cl_parse.h" -#include "client.h" +#include "qw/include/cl_parse.h" +#include "qw/include/client.h" void CL_RSShot_f (void) diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index adf20f7e4..5b81f65a7 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -44,10 +44,11 @@ #include "QF/pcx.h" #include "QF/screen.h" -#include "client.h" #include "clview.h" #include "sbar.h" +#include "qw/include/client.h" + static qpic_t *scr_net; static void diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index d533a58d3..21a9afea7 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -43,11 +43,12 @@ #include "QF/sys.h" #include "QF/va.h" -#include "cl_parse.h" -#include "cl_skin.h" -#include "client.h" #include "compat.h" -#include "host.h" + +#include "qw/include/cl_parse.h" +#include "qw/include/cl_skin.h" +#include "qw/include/client.h" +#include "qw/include/host.h" cvar_t *noskins; //XXX FIXME cvar_t *skin; diff --git a/qw/source/cl_slist.c b/qw/source/cl_slist.c index 21497f142..4b5ea16b8 100644 --- a/qw/source/cl_slist.c +++ b/qw/source/cl_slist.c @@ -68,9 +68,9 @@ #include "QF/va.h" #include "qw/bothdefs.h" -#include "cl_main.h" -#include "cl_slist.h" -#include "client.h" +#include "qw/include/cl_main.h" +#include "qw/include/cl_slist.h" +#include "qw/include/client.h" typedef struct server_entry_s { char *server; diff --git a/qw/source/cl_sys_sdl.c b/qw/source/cl_sys_sdl.c index 3a5f1385b..c3b620ca8 100644 --- a/qw/source/cl_sys_sdl.c +++ b/qw/source/cl_sys_sdl.c @@ -56,9 +56,10 @@ #include "QF/qargs.h" #include "QF/sys.h" -#include "host.h" #include "netchan.h" +#include "qw/include/host.h" + #ifdef _WIN32 # include "winquake.h" #endif diff --git a/qw/source/cl_sys_unix.c b/qw/source/cl_sys_unix.c index 4c7071ba2..d0ef58225 100644 --- a/qw/source/cl_sys_unix.c +++ b/qw/source/cl_sys_unix.c @@ -48,9 +48,10 @@ #include "QF/qargs.h" #include "QF/sys.h" -#include "host.h" #include "netchan.h" +#include "qw/include/host.h" + static void shutdown_f (void *data) { diff --git a/qw/source/cl_sys_win.c b/qw/source/cl_sys_win.c index 388166e7a..6fe2fbe06 100644 --- a/qw/source/cl_sys_win.c +++ b/qw/source/cl_sys_win.c @@ -34,8 +34,8 @@ #include "QF/screen.h" #include "QF/sys.h" -#include "client.h" -#include "host.h" +#include "qw/include/client.h" +#include "qw/include/host.h" #define MAXIMUM_WIN_MEMORY 0x1000000 #define MINIMUM_WIN_MEMORY 0x0c00000 diff --git a/qw/source/cl_tent.c b/qw/source/cl_tent.c index 43e5930d0..950734bea 100644 --- a/qw/source/cl_tent.c +++ b/qw/source/cl_tent.c @@ -44,13 +44,14 @@ #include "QF/sound.h" #include "QF/sys.h" -#include "cl_ents.h" -#include "cl_main.h" -#include "cl_parse.h" -#include "cl_tent.h" -#include "client.h" #include "compat.h" +#include "qw/include/cl_ents.h" +#include "qw/include/cl_main.h" +#include "qw/include/cl_parse.h" +#include "qw/include/cl_tent.h" +#include "qw/include/client.h" + typedef struct tent_s { struct tent_s *next; entity_t ent; diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 09633388b..4ad5da14f 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -33,16 +33,18 @@ #include "QF/msg.h" #include "QF/screen.h" -#include "qw/bothdefs.h" -#include "chase.h" -#include "cl_cam.h" -#include "cl_ents.h" -#include "cl_main.h" -#include "client.h" #include "compat.h" -#include "host.h" #include "clview.h" +#include "qw/bothdefs.h" + +#include "qw/include/chase.h" +#include "qw/include/cl_cam.h" +#include "qw/include/cl_ents.h" +#include "qw/include/cl_main.h" +#include "qw/include/client.h" +#include "qw/include/host.h" + /* The view is allowed to move slightly from it's true position for bobbing, but if it exceeds 8 pixels linear distance (spherical, not box), the list diff --git a/qw/source/crudefile.c b/qw/source/crudefile.c index 58426ad4d..3050a6efc 100644 --- a/qw/source/crudefile.c +++ b/qw/source/crudefile.c @@ -50,7 +50,8 @@ #include "QF/zone.h" #include "compat.h" -#include "crudefile.h" + +#include "qw/include/crudefile.h" int cf_maxsize; // max combined file size (eg quota) int cf_cursize; // current combined file size diff --git a/qw/source/game.c b/qw/source/game.c index ac69d83ea..df180b306 100644 --- a/qw/source/game.c +++ b/qw/source/game.c @@ -43,8 +43,8 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "game.h" -#include "server.h" +#include "qw/include/game.h" +#include "qw/include/server.h" cvar_t *registered; int static_registered = 1; // only for startup check, then set diff --git a/qw/source/locs.c b/qw/source/locs.c index 2f94da0f8..c30080dd7 100644 --- a/qw/source/locs.c +++ b/qw/source/locs.c @@ -47,9 +47,10 @@ #include "QF/sys.h" #include "QF/va.h" -#include "client.h" #include "compat.h" +#include "qw/include/client.h" + #define LOCATION_BLOCK 128 // 128 locations per block. location_t **locations = NULL; diff --git a/qw/source/map_cfg.c b/qw/source/map_cfg.c index 10b4a5cd5..296bad56b 100644 --- a/qw/source/map_cfg.c +++ b/qw/source/map_cfg.c @@ -44,7 +44,7 @@ #include "QF/idparse.h" #include "QF/quakefs.h" -#include "map_cfg.h" +#include "qw/include/map_cfg.h" void map_cfg (const char *mapname, int all) diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index 189c6fefe..3d2c58dc8 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -54,9 +54,10 @@ #include "QF/va.h" #include "compat.h" + #include "netchan.h" #include "qw/protocol.h" -#include "server.h" +#include "qw/include/server.h" cvar_t *net_packetlog; cvar_t *net_loglevel; diff --git a/qw/source/pmove.c b/qw/source/pmove.c index 31702c2f3..637528afa 100644 --- a/qw/source/pmove.c +++ b/qw/source/pmove.c @@ -34,8 +34,9 @@ #include "QF/qtypes.h" #include "QF/sys.h" -#include "client.h" #include "compat.h" + +#include "qw/include/client.h" #include "qw/pmove.h" cvar_t *no_pogo_stick; diff --git a/qw/source/pmovetst.c b/qw/source/pmovetst.c index da23aef9d..6b3857feb 100644 --- a/qw/source/pmovetst.c +++ b/qw/source/pmovetst.c @@ -41,6 +41,7 @@ #include "QF/sys.h" #include "compat.h" + #include "qw/pmove.h" #include "world.h" diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 34490e43e..3a6e97778 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -54,11 +54,12 @@ #include "QF/plugin/console.h" -#include "qw/bothdefs.h" -#include "cl_cam.h" -#include "cl_parse.h" -#include "client.h" #include "compat.h" + +#include "qw/bothdefs.h" +#include "qw/include/cl_cam.h" +#include "qw/include/cl_parse.h" +#include "qw/include/client.h" #include "sbar.h" int sb_updates; // if >= vid.numpages, no update needed diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index 93c5247f6..aef14bea6 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -49,13 +49,14 @@ #include "QF/sys.h" #include "QF/va.h" -#include "qw/bothdefs.h" #include "compat.h" -#include "server.h" -#include "sv_demo.h" -#include "sv_progs.h" -#include "sv_qtv.h" -#include "sv_recorder.h" + +#include "qw/bothdefs.h" +#include "qw/include/server.h" +#include "qw/include/sv_demo.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_qtv.h" +#include "qw/include/sv_recorder.h" qboolean sv_allow_cheats; diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index 65b6d397c..cc53372a8 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -47,11 +47,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "QF/va.h" #include "compat.h" + #include "qw/pmove.h" -#include "server.h" -#include "sv_demo.h" -#include "sv_progs.h" -#include "sv_recorder.h" +#include "qw/include/server.h" +#include "qw/include/sv_demo.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_recorder.h" static QFile *demo_file; static byte *demo_mfile; diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index f6682337c..09e19ba83 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -39,11 +39,12 @@ #include "QF/msg.h" #include "QF/sys.h" +#include "compat.h" + #include "qw/msg_ucmd.h" -#include "compat.h" -#include "server.h" -#include "sv_progs.h" +#include "qw/include/server.h" +#include "qw/include/sv_progs.h" /* diff --git a/qw/source/sv_gib.c b/qw/source/sv_gib.c index 7600805d2..3e4d5421c 100644 --- a/qw/source/sv_gib.c +++ b/qw/source/sv_gib.c @@ -39,8 +39,8 @@ #include "QF/info.h" #include "QF/gib.h" -#include "server.h" -#include "client.h" +#include "qw/include/server.h" +#include "qw/include/client.h" gib_event_t *sv_chat_e; gib_event_t *sv_client_connect_e; diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 7d8c894d1..d5b6d0d2c 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -44,12 +44,13 @@ #include "QF/va.h" #include "compat.h" -#include "crudefile.h" -#include "map_cfg.h" + +#include "qw/include/crudefile.h" +#include "qw/include/map_cfg.h" #include "qw/pmove.h" -#include "server.h" -#include "sv_progs.h" -#include "sv_gib.h" +#include "qw/include/server.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_gib.h" #include "world.h" info_t *localinfo; // local game info diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 56d135e16..81d605e37 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -77,19 +77,20 @@ #include "QF/plugin/console.h" -#include "qw/bothdefs.h" #include "buildnum.h" #include "compat.h" -#include "crudefile.h" -#include "game.h" #include "netchan.h" + +#include "qw/bothdefs.h" +#include "qw/include/crudefile.h" +#include "qw/include/game.h" #include "qw/pmove.h" -#include "server.h" -#include "sv_demo.h" -#include "sv_progs.h" -#include "sv_gib.h" -#include "sv_qtv.h" -#include "sv_recorder.h" +#include "qw/include/server.h" +#include "qw/include/sv_demo.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_gib.h" +#include "qw/include/sv_qtv.h" +#include "qw/include/sv_recorder.h" SERVER_PLUGIN_PROTOS static plugin_list_t server_plugin_list[] = { diff --git a/qw/source/sv_move.c b/qw/source/sv_move.c index 013e4d48e..75b4f8e01 100644 --- a/qw/source/sv_move.c +++ b/qw/source/sv_move.c @@ -28,8 +28,8 @@ # include "config.h" #endif -#include "server.h" -#include "sv_progs.h" +#include "qw/include/server.h" +#include "qw/include/sv_progs.h" #include "world.h" #define STEPSIZE 18 diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index e2d08e814..9c627f9e9 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -31,8 +31,8 @@ #include "QF/cvar.h" #include "QF/sys.h" -#include "server.h" -#include "sv_progs.h" +#include "qw/include/server.h" +#include "qw/include/sv_progs.h" #include "world.h" /* diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 46a9cc4e3..49f0cc332 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -46,11 +46,12 @@ #include "QF/va.h" #include "compat.h" -#include "crudefile.h" -#include "server.h" -#include "sv_gib.h" -#include "sv_progs.h" -#include "sv_recorder.h" + +#include "qw/include/crudefile.h" +#include "qw/include/server.h" +#include "qw/include/sv_gib.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_recorder.h" #include "world.h" /* BUILT-IN FUNCTIONS */ diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index 4263cc097..e2ac3ffd2 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -39,9 +39,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "QF/quakefs.h" #include "QF/sys.h" -#include "server.h" -#include "sv_pr_cpqw.h" -#include "sv_progs.h" +#include "qw/include/server.h" +#include "qw/include/sv_pr_cpqw.h" +#include "qw/include/sv_progs.h" #include "world.h" static struct { diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index 9a84892cf..010c8a5a6 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -50,10 +50,10 @@ #include "QF/sys.h" #include "QF/va.h" -#include "server.h" -#include "sv_pr_qwe.h" -#include "sv_progs.h" -#include "sv_recorder.h" +#include "qw/include/server.h" +#include "qw/include/sv_pr_qwe.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_recorder.h" typedef struct { func_t timeofday; diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 2c4ff5c3f..276ee2875 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -42,10 +42,11 @@ #include "QF/sys.h" #include "compat.h" -#include "server.h" -#include "sv_progs.h" -#include "sv_pr_cpqw.h" -#include "sv_pr_qwe.h" + +#include "qw/include/server.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_pr_cpqw.h" +#include "qw/include/sv_pr_qwe.h" #include "world.h" progs_t sv_pr_state; diff --git a/qw/source/sv_qtv.c b/qw/source/sv_qtv.c index a36b1c3cc..6804a51e3 100644 --- a/qw/source/sv_qtv.c +++ b/qw/source/sv_qtv.c @@ -48,9 +48,10 @@ #include "QF/va.h" #include "compat.h" -#include "server.h" -#include "sv_qtv.h" -#include "sv_recorder.h" + +#include "qw/include/server.h" +#include "qw/include/sv_qtv.h" +#include "qw/include/sv_recorder.h" typedef struct { netchan_t netchan; diff --git a/qw/source/sv_recorder.c b/qw/source/sv_recorder.c index 562fd94d3..d2555862e 100644 --- a/qw/source/sv_recorder.c +++ b/qw/source/sv_recorder.c @@ -49,10 +49,10 @@ #include "QF/sys.h" #include "qw/bothdefs.h" -#include "server.h" -#include "sv_demo.h" -#include "sv_progs.h" -#include "sv_recorder.h" +#include "qw/include/server.h" +#include "qw/include/sv_demo.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_recorder.h" typedef struct dbuffer_s { byte *data; diff --git a/qw/source/sv_sbar.c b/qw/source/sv_sbar.c index a76729789..012a38835 100644 --- a/qw/source/sv_sbar.c +++ b/qw/source/sv_sbar.c @@ -37,9 +37,10 @@ #include "QF/plugin/console.h" -#include "server.h" #include "sv_console.h" -#include "sv_recorder.h" + +#include "qw/include/server.h" +#include "qw/include/sv_recorder.h" static void draw_cpu (view_t *view) diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index 54e53d347..400b9484e 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -46,11 +46,12 @@ #include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_* #include "QF/sys.h" -#include "qw/bothdefs.h" #include "compat.h" -#include "server.h" -#include "sv_progs.h" -#include "sv_recorder.h" + +#include "qw/bothdefs.h" +#include "qw/include/server.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_recorder.h" #define CHAN_AUTO 0 #define CHAN_WEAPON 1 diff --git a/qw/source/sv_sys_unix.c b/qw/source/sv_sys_unix.c index 24b3adb4b..cb7aabbdd 100644 --- a/qw/source/sv_sys_unix.c +++ b/qw/source/sv_sys_unix.c @@ -43,7 +43,7 @@ #include "QF/qargs.h" #include "QF/sys.h" -#include "server.h" +#include "qw/include/server.h" #ifdef NeXT # include diff --git a/qw/source/sv_sys_win.c b/qw/source/sv_sys_win.c index 52f3b230a..20fbdfb4e 100644 --- a/qw/source/sv_sys_win.c +++ b/qw/source/sv_sys_win.c @@ -36,7 +36,7 @@ #include "QF/qargs.h" #include "QF/sys.h" -#include "server.h" +#include "qw/include/server.h" qboolean WinNT; server_static_t svs; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index b8aa5e8d4..f9c44f48f 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -53,16 +53,17 @@ #include "QF/sys.h" #include "QF/va.h" +#include "compat.h" + #include "qw/msg_ucmd.h" #include "qw/msg_ucmd.h" #include "qw/bothdefs.h" -#include "compat.h" #include "qw/pmove.h" -#include "server.h" -#include "sv_gib.h" -#include "sv_progs.h" -#include "sv_recorder.h" +#include "qw/include/server.h" +#include "qw/include/sv_gib.h" +#include "qw/include/sv_progs.h" +#include "qw/include/sv_recorder.h" #include "world.h" typedef struct ucmd_s { diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index 5da9dace2..c5df33cd3 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -50,11 +50,12 @@ #include "QF/sys.h" #include "QF/teamplay.h" -#include "qw/bothdefs.h" -#include "cl_input.h" -#include "client.h" #include "compat.h" +#include "qw/bothdefs.h" +#include "qw/include/cl_input.h" +#include "qw/include/client.h" + static qboolean died = false, recorded_location = false; static vec3_t death_location, last_recorded_location; diff --git a/qw/source/world.c b/qw/source/world.c index 0664c197e..bbf4d930e 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -43,8 +43,9 @@ #include "QF/sys.h" #include "compat.h" -#include "server.h" -#include "sv_progs.h" + +#include "qw/include/server.h" +#include "qw/include/sv_progs.h" #include "world.h" #define always_inline inline __attribute__((__always_inline__)) diff --git a/ruamoko/Makefile.am b/ruamoko/Makefile.am deleted file mode 100644 index b899690f8..000000000 --- a/ruamoko/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -SUBDIRS= include lib game gui cl_menu scheme @ruamoko_dirs@ -DIST_SUBDIRS=qwaq - -doc: Doxyfile - doxygen - -clean-local: - -rm -fr doxygen diff --git a/ruamoko/Makemodule.am b/ruamoko/Makemodule.am new file mode 100644 index 000000000..202fbffb6 --- /dev/null +++ b/ruamoko/Makemodule.am @@ -0,0 +1,10 @@ +ruamoko_libdir = $(datarootdir)/qfcc/lib +ruamoko_lib_LIBRARIES = + +include ruamoko/include/Makemodule.am +include ruamoko/lib/Makemodule.am +include ruamoko/game/Makemodule.am +include ruamoko/gui/Makemodule.am +include ruamoko/cl_menu/Makemodule.am +include ruamoko/scheme/Makemodule.am +include ruamoko/qwaq/Makemodule.am diff --git a/ruamoko/cl_menu/Makefile.am b/ruamoko/cl_menu/Makefile.am deleted file mode 100644 index 8c759d410..000000000 --- a/ruamoko/cl_menu/Makefile.am +++ /dev/null @@ -1,71 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign no-exeext - -QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) -QFCC=$(QFCC_DEP) - -GZ=@progs_gz@ -menu_libexec=menu.dat -menu_data=menu.plist menu.sym - -pkglibexecdir=@sharepath@/QF -pkgdatadir=@sharepath@/QF - -pkgdata_DATA= $(menu_data) -pkglibexec_PROGRAMS= $(menu_libexec) -EXTRA_PROGRAMS= $(menu_libexec) - -QCFLAGS=-qq -O -g -Wall -Werror -Wno-integer-divide -QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include -QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib -QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) -QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) - -MKDIR_P = @MKDIR_P@ -am__mv = mv -f - -GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi -# BSD make can't handle $(shell foo) directives, and GNU make can't handle |= -# so we have to bite the bullet and pass this to the shell every time. - -SUFFIXES=.o .r -.r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo - -menu_src= \ - client_menu.r controls_o.r options.r options_util.r servlist.r \ - Frame.r HUD.r menu.r plistmenu.r \ - \ - CrosshairCvar.r CrosshairView.r CvarColor.r CvarColorView.r \ - CvarObject.r CvarRange.r CvarRangeView.r CvarString.r CvarStringView.r \ - CvarToggle.r CvarToggleView.r \ - MenuGroup.r MouseToggle.r ProxyView.r RunToggle.r SubMenu.r - -r_depfiles_remade= - -menu_dat_SOURCES=$(menu_src) -menu_obj=$(menu_src:.r=.o) -menu_dep=$(addprefix ./$(DEPDIR)/,$(menu_obj:.o=.Qo)) -menu.dat: $(menu_obj) $(QFCC_DEP) ../lib/libcsqc.a ../lib/libr.a ../gui/libgui.a - $(QLINK) -o menu.dat $(menu_obj) ../gui/libgui.a ../lib/libcsqc.a ../lib/libr.a -include $(menu_dep) # am--include-marker -r_depfiles_remade += $(menu_dep) - -menu.sym: menu.dat - -$(r_depfiles_remade): - $(MKDIR_P) $(@D) - echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) - -EXTRA_DIST= $(menu_src) \ - CrosshairCvar.h CrosshairView.h CvarColor.h CvarColorView.h CvarObject.h \ - CvarRange.h CvarRangeView.h CvarString.h CvarStringView.h \ - CvarToggle.h CvarToggleView.h Frame.h HUD.h \ - MenuGroup.h MouseToggle.h ProxyView.h RunToggle.h SubMenu.h client_menu.h \ - controls_o.h menu.h options.h options_util.h plistmenu.h servlist.h \ - menu.plist -CLEANFILES= *.dat *.sym *.gz *.qfo *.o diff --git a/ruamoko/cl_menu/Makemodule.am b/ruamoko/cl_menu/Makemodule.am new file mode 100644 index 000000000..dfa7635ba --- /dev/null +++ b/ruamoko/cl_menu/Makemodule.am @@ -0,0 +1,77 @@ +ruamoko_cl_menu_libexec=ruamoko/cl_menu/menu.dat$(EXEEXT) +ruamoko_cl_menu_data=ruamoko/cl_menu/menu.plist ruamoko/cl_menu/menu.sym + +ruamoko_cl_menudir = @sharepath@/QF +ruamoko_cl_menu_DATA = $(ruamoko_cl_menu_data) +ruamoko_cl_menu_PROGRAMS = $(ruamoko_cl_menu_libexec) +EXTRA_PROGRAMS += $(ruamoko_cl_menu_libexec) + +ruamoko_menu_src= \ + ruamoko/cl_menu/client_menu.r \ + ruamoko/cl_menu/controls_o.r \ + ruamoko/cl_menu/options.r \ + ruamoko/cl_menu/options_util.r \ + ruamoko/cl_menu/servlist.r \ + ruamoko/cl_menu/Frame.r \ + ruamoko/cl_menu/HUD.r \ + ruamoko/cl_menu/menu.r \ + ruamoko/cl_menu/plistmenu.r \ + ruamoko/cl_menu/CrosshairCvar.r \ + ruamoko/cl_menu/CrosshairView.r \ + ruamoko/cl_menu/CvarColor.r \ + ruamoko/cl_menu/CvarColorView.r \ + ruamoko/cl_menu/CvarObject.r \ + ruamoko/cl_menu/CvarRange.r \ + ruamoko/cl_menu/CvarRangeView.r \ + ruamoko/cl_menu/CvarString.r \ + ruamoko/cl_menu/CvarStringView.r \ + ruamoko/cl_menu/CvarToggle.r \ + ruamoko/cl_menu/CvarToggleView.r \ + ruamoko/cl_menu/MenuGroup.r \ + ruamoko/cl_menu/MouseToggle.r \ + ruamoko/cl_menu/ProxyView.r \ + ruamoko/cl_menu/RunToggle.r \ + ruamoko/cl_menu/SubMenu.r + +ruamoko_cl_menu_menu_dat_SOURCES=$(ruamoko_menu_src) +ruamoko_menu_obj=$(ruamoko_cl_menu_menu_dat_SOURCES:.r=.o) +ruamoko_menu_dep=$(call qcautodep,$(ruamoko_cl_menu_menu_dat_SOURCES)) +ruamoko/cl_menu/menu.dat$(EXEEXT): $(ruamoko_menu_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a ruamoko/gui/libgui.a + $(QLINK) -o $@ $(ruamoko_menu_obj) -Lruamoko/gui -lgui -lcsqc -lr +include $(ruamoko_menu_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_menu_dep) + +ruamoko/cl_menu/menu.sym: ruamoko/cl_menu/menu.dat + +EXTRA_DIST += \ + ruamoko/cl_menu/CrosshairCvar.h \ + ruamoko/cl_menu/CrosshairView.h \ + ruamoko/cl_menu/CvarColor.h \ + ruamoko/cl_menu/CvarColorView.h \ + ruamoko/cl_menu/CvarObject.h \ + ruamoko/cl_menu/CvarRange.h \ + ruamoko/cl_menu/CvarRangeView.h \ + ruamoko/cl_menu/CvarString.h \ + ruamoko/cl_menu/CvarStringView.h \ + ruamoko/cl_menu/CvarToggle.h \ + ruamoko/cl_menu/CvarToggleView.h \ + ruamoko/cl_menu/Frame.h \ + ruamoko/cl_menu/HUD.h \ + ruamoko/cl_menu/MenuGroup.h \ + ruamoko/cl_menu/MouseToggle.h \ + ruamoko/cl_menu/ProxyView.h \ + ruamoko/cl_menu/RunToggle.h \ + ruamoko/cl_menu/SubMenu.h \ + ruamoko/cl_menu/client_menu.h \ + ruamoko/cl_menu/controls_o.h \ + ruamoko/cl_menu/menu.h \ + ruamoko/cl_menu/options.h \ + ruamoko/cl_menu/options_util.h \ + ruamoko/cl_menu/plistmenu.h \ + ruamoko/cl_menu/servlist.h \ + ruamoko/cl_menu/menu.plist + +CLEANFILES += \ + ruamoko/cl_menu/*.dat \ + ruamoko/cl_menu/*.sym +DISTCLEANFILES += $(ruamoko_menu_dep) diff --git a/ruamoko/game/Makefile.am b/ruamoko/game/Makefile.am deleted file mode 100644 index fe9a38f5f..000000000 --- a/ruamoko/game/Makefile.am +++ /dev/null @@ -1,56 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign no-exeext - -QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) -QFCC=$(QFCC_DEP) - -GZ=@progs_gz@ -game_libexec=game.dat - -pkglibexecdir=@sharepath@/QF - -# this will eventually go into pkglibexecdir, but for now... -noinst_PROGRAMS= $(game_libexec) -EXTRA_PROGRAMS= $(game_libexec) - -QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide -QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib -QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) -QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) - -MKDIR_P = @MKDIR_P@ -am__mv = mv -f - -GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi -# BSD make can't handle $(shell foo) directives, and GNU make can't handle |= -# so we have to bite the bullet and pass this to the shell every time. - -SUFFIXES=.o .r -.r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo - -game_src= Axe.r GameEntity.r World.r tempent.r - -r_depfiles_remade= - -game_dat_SOURCES=$(game_src) -game_obj=$(game_src:.r=.o) -game_dep=$(addprefix ./$(DEPDIR)/,$(game_obj:.o=.Qo)) -game.dat: $(game_obj) $(QFCC_DEP) ../lib/libr.a ../lib/libqw.a - $(QLINK) -o game.dat $(game_obj) ../lib/libr.a ../lib/libqw.a ../lib/libr.a -include $(game_dep) # am--include-marker -r_depfiles_remade += $(game_dep) - -game.sym: game.dat - -$(r_depfiles_remade): - $(MKDIR_P) $(@D) - echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) - -EXTRA_DIST= $(game_src) Axe.h GameEntity.h tempent.h Weapon.h World.h -CLEANFILES= *.dat *.sym *.gz *.o *.qfo diff --git a/ruamoko/game/Makemodule.am b/ruamoko/game/Makemodule.am new file mode 100644 index 000000000..4063e9a62 --- /dev/null +++ b/ruamoko/game/Makemodule.am @@ -0,0 +1,27 @@ +ruamoko_game_libexec=ruamoko/game/game.dat$(EXEEXT) + +noinst_PROGRAMS += $(ruamoko_game_libexec) +EXTRA_PROGRAMS += $(ruamoko_game_libexec) + +ruamoko_game_src= ruamoko/game/Axe.r ruamoko/game/GameEntity.r ruamoko/game/World.r ruamoko/game/tempent.r + +ruamoko_game_game_dat_SOURCES=$(ruamoko_game_src) +ruamoko_game_obj=$(ruamoko_game_game_dat_SOURCES:.r=.o) +ruamoko_game_dep=$(call qcautodep,$(ruamoko_game_game_dat_SOURCES)) +ruamoko/game/game.dat$(EXEEXT): $(ruamoko_game_obj) $(QFCC_DEP) ruamoko/lib/libr.a ruamoko/lib/libqw.a + $(QLINK) -o $@ $(ruamoko_game_obj) -lqw -lr +include $(ruamoko_game_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_game_dep) + +ruamoko/game/game.sym: ruamoko/game/game.dat + +EXTRA_DIST += $(ruamoko_game_src) \ + ruamoko/game/Axe.h \ + ruamoko/game/GameEntity.h \ + ruamoko/game/tempent.h \ + ruamoko/game/Weapon.h \ + ruamoko/game/World.h +CLEANFILES += \ + ruamoko/game/*.dat \ + ruamoko/game/*.sym +DISTCLEANFILES += $(ruamoko_game_dep) diff --git a/ruamoko/gui/Makefile.am b/ruamoko/gui/Makefile.am deleted file mode 100644 index 0edd447d4..000000000 --- a/ruamoko/gui/Makefile.am +++ /dev/null @@ -1,50 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) -QFCC=$(QFCC_DEP) - -gui_libs=libgui.a -libs=$(gui_libs) - -pkglibdir=$(datarootdir)/qfcc/lib - -pkglib_LIBRARIES= $(libs) -EXTRA_LIBRARIES= $(gui_libs) - -QFCC=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) -QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide --no-default-paths -QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib -QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) -QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) - -MKDIR_P = @MKDIR_P@ -am__mv = mv -f - -PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) -RANLIB=touch - -SUFFIXES= .o .r -.r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo - -r_depfiles_remade= - -libgui_a_SOURCES= \ - Group.r InputLine.r Pic.r Point.r Rect.r Size.r Slider.r Text.r View.r -libgui_a_obj=$(libgui_a_SOURCES:.r=.o) -libgui_a_dep=$(addprefix ./$(DEPDIR)/,$(libgui_a_obj:.o=.Qo)) -libgui_a_AR= $(PAK) -cf -include $(libgui_a_dep) # am--include-marker -r_depfiles_remade += $(libgui_a_dep) - -$(r_depfiles_remade): - $(MKDIR_P) $(@D) - echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) - - -CLEANFILES= *.qfo *.o diff --git a/ruamoko/gui/Makemodule.am b/ruamoko/gui/Makemodule.am new file mode 100644 index 000000000..ee25d5111 --- /dev/null +++ b/ruamoko/gui/Makemodule.am @@ -0,0 +1,25 @@ +ruamoko_gui_gui_libs=ruamoko/gui/libgui.a + +ruamoko_lib_LIBRARIES += $(ruamoko_gui_gui_libs) +EXTRA_LIBRARIES += $(ruamoko_gui_gui_libs) + +ruamoko_gui_libgui_a_SOURCES= \ + ruamoko/gui/Group.r \ + ruamoko/gui/InputLine.r \ + ruamoko/gui/Pic.r \ + ruamoko/gui/Point.r \ + ruamoko/gui/Rect.r \ + ruamoko/gui/Size.r \ + ruamoko/gui/Slider.r \ + ruamoko/gui/Text.r \ + ruamoko/gui/View.r +ruamoko_gui_libgui_a_dep=$(call qcautodep,$(ruamoko_gui_libgui_a_SOURCES)) +ruamoko_gui_libgui_a_AR= $(PAK) -cf +EXTRA_ruamoko_gui_libgui_a_DEPENDENCIES=pak +include $(ruamoko_gui_libgui_a_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_gui_libgui_a_dep) + +CLEANFILES += \ + ruamoko/gui/*.dat \ + ruamoko/gui/*.sym +DISTCLEANFILES += $(ruamoko_gui_libgui_a_dep) diff --git a/ruamoko/include/Makefile.am b/ruamoko/include/Makefile.am deleted file mode 100644 index 0964419bf..000000000 --- a/ruamoko/include/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -AUTOMAKE_OPTIONS= foreign -pkgincludedir= $(datarootdir)/qfcc/include -nobase_pkginclude_HEADERS= \ - crudefile.h debug.h entities.h infokey.h math.h message.h nq_message.h \ - physics.h msgbuf.h qfile.h qfs.h qw_message.h qw_physics.h qw_sys.h \ - server.h sound.h script.h string.h sv_sound.h system.h types.h \ - legacy_string.h \ - \ - draw.h key.h \ - \ - cbuf.h cmd.h cvar.h gib.h hash.h plist.h runtime.h \ - Object.h Protocol.h \ - AutoreleasePool.h Array.h Entity.h PropertyList.h Set.h \ - \ - gui/Group.h gui/InputLine.h gui/Pic.h gui/Point.h gui/Rect.h gui/Size.h \ - gui/Slider.h gui/Text.h gui/View.h diff --git a/ruamoko/include/Makemodule.am b/ruamoko/include/Makemodule.am new file mode 100644 index 000000000..d53289e72 --- /dev/null +++ b/ruamoko/include/Makemodule.am @@ -0,0 +1,56 @@ +ruamoko_include = \ + ruamoko/include/crudefile.h \ + ruamoko/include/debug.h \ + ruamoko/include/entities.h \ + ruamoko/include/infokey.h \ + ruamoko/include/math.h \ + ruamoko/include/message.h \ + ruamoko/include/nq_message.h \ + ruamoko/include/physics.h \ + ruamoko/include/msgbuf.h \ + ruamoko/include/qfile.h \ + ruamoko/include/qfs.h \ + ruamoko/include/qw_message.h \ + ruamoko/include/qw_physics.h \ + ruamoko/include/qw_sys.h \ + ruamoko/include/server.h \ + ruamoko/include/sound.h \ + ruamoko/include/script.h \ + ruamoko/include/string.h \ + ruamoko/include/sv_sound.h \ + ruamoko/include/system.h \ + ruamoko/include/types.h \ + ruamoko/include/legacy_string.h \ + ruamoko/include/draw.h \ + ruamoko/include/key.h \ + ruamoko/include/cbuf.h \ + ruamoko/include/cmd.h \ + ruamoko/include/cvar.h \ + ruamoko/include/gib.h \ + ruamoko/include/hash.h \ + ruamoko/include/plist.h \ + ruamoko/include/runtime.h \ + ruamoko/include/Object.h \ + ruamoko/include/Protocol.h \ + ruamoko/include/AutoreleasePool.h \ + ruamoko/include/Array.h \ + ruamoko/include/Entity.h \ + ruamoko/include/PropertyList.h \ + ruamoko/include/Set.h + +ruamoko_gui_include = \ + ruamoko/include/gui/Group.h \ + ruamoko/include/gui/InputLine.h \ + ruamoko/include/gui/Pic.h \ + ruamoko/include/gui/Point.h \ + ruamoko/include/gui/Rect.h \ + ruamoko/include/gui/Size.h \ + ruamoko/include/gui/Slider.h \ + ruamoko/include/gui/Text.h \ + ruamoko/include/gui/View.h + +ruamoko_includedir = $(datarootdir)/qfcc/include +ruamoko_gui_includedir = $(datarootdir)/qfcc/include/gui + +ruamoko_include_HEADERS = $(ruamoko_include) +ruamoko_gui_include_HEADERS = $(ruamoko_gui_include) diff --git a/ruamoko/lib/Makefile.am b/ruamoko/lib/Makefile.am deleted file mode 100644 index b05db7299..000000000 --- a/ruamoko/lib/Makefile.am +++ /dev/null @@ -1,96 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) -QFCC=$(QFCC_DEP) - -ruamoko_libs=libr.a libqw.a libnq.a libcsqc.a -libs=$(ruamoko_libs) - -pkglibdir=$(datarootdir)/qfcc/lib - -pkglib_LIBRARIES= $(libs) -EXTRA_LIBRARIES= $(ruamoko_libs) - -noinst_HEADERS= \ - Array+Private.h - -QCFLAGS=-qq -O -g -Wall -Wno-integer-divide -Werror -QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include -QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib -QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) -QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) - -MKDIR_P = @MKDIR_P@ -am__mv = mv -f - -PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) -RANLIB=touch - -SUFFIXES= .o .r -.r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo - -r_depfiles_remade= - -libr_a_SOURCES=\ - cbuf.r cmd.r cvar.r hash.r msgbuf.r plist.r qfile.r qfs.r script.r \ - sound.r string.r math.r types.r va_list.r \ - obj_forward.r \ - Object.r Protocol.r \ - AutoreleasePool.r Array.r Array+Private.r Entity.r PropertyList.r Set.r -libr_a_obj=$(libr_a_SOURCES:.r=.o) -libr_a_dep=$(addprefix ./$(DEPDIR)/,$(libr_a_obj:.o=.Qo)) -libr_a_AR=$(PAK) -cf -include $(libr_a_dep) # am--include-marker -r_depfiles_remade += $(libr_a_dep) - -common_src=debug.r system.r legacy_string.r -server_src= \ - crudefile.r entities.r infokey.r message.r \ - physics.r server.r sv_sound.r -libqw_a_src= \ - qw_message.r qw_physics.r qw_sys.r -libnq_a_src= \ - nq_message.r -libcsqc_a_src= draw.r gib.r key.r - -common_obj=$(common_src:.r=.o) -common_dep=$(addprefix ./$(DEPDIR)/,$(common_obj:.o=.Qo)) -include $(common_dep) # am--include-marker -r_depfiles_remade += $(common_dep) - -server_obj=$(server_src:.r=.o) -server_dep=$(addprefix ./$(DEPDIR)/,$(server_obj:.o=.Qo)) -include $(server_dep) # am--include-marker -r_depfiles_remade += $(server_dep) - -libqw_a_SOURCES=$(libqw_a_src) $(common_src) $(server_src) math.r -libqw_a_obj=$(libqw_a_src:.r=.o) -libqw_a_dep=$(addprefix ./$(DEPDIR)/,$(libqw_a_obj:.o=.Qo)) -libqw_a_AR=$(PAK) -cf -include $(libqw_a_dep) # am--include-marker -r_depfiles_remade += $(libqw_a_dep) - -libnq_a_SOURCES=$(libnq_a_src) $(common_src) $(server_src) math.r -libnq_a_obj=$(libnq_a_src:.r=.o) -libnq_a_dep=$(addprefix ./$(DEPDIR)/,$(libnq_a_obj:.o=.Qo)) -libnq_a_AR=$(PAK) -cf -include $(libnq_a_dep) # am--include-marker -r_depfiles_remade += $(libnq_a_dep) - -libcsqc_a_SOURCES=$(libcsqc_a_src) $(common_src) -libcsqc_a_obj=$(libcsqc_a_src:.r=.o) -libcsqc_a_dep=$(addprefix ./$(DEPDIR)/,$(libcsqc_a_obj:.o=.Qo)) -libcsqc_a_AR= $(PAK) -cf -include $(libcsqc_a_dep) # am--include-marker -r_depfiles_remade += $(libcsqc_a_dep) - -$(r_depfiles_remade): - $(MKDIR_P) $(@D) - echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) - -CLEANFILES= *.qfo *.o diff --git a/ruamoko/lib/Makemodule.am b/ruamoko/lib/Makemodule.am new file mode 100644 index 000000000..0d189f6b7 --- /dev/null +++ b/ruamoko/lib/Makemodule.am @@ -0,0 +1,87 @@ +ruamoko_libs=ruamoko/lib/libr.a ruamoko/lib/libqw.a ruamoko/lib/libnq.a ruamoko/lib/libcsqc.a + +ruamoko_lib_LIBRARIES += $(ruamoko_libs) +EXTRA_LIBRARIES += $(ruamoko_libs) + +noinst_HEADERS += \ + ruamoko/lib/Array+Private.h + +ruamoko_lib_libr_a_SOURCES=\ + ruamoko/lib/cbuf.r \ + ruamoko/lib/cmd.r \ + ruamoko/lib/cvar.r \ + ruamoko/lib/hash.r \ + ruamoko/lib/msgbuf.r \ + ruamoko/lib/plist.r \ + ruamoko/lib/qfile.r \ + ruamoko/lib/qfs.r \ + ruamoko/lib/script.r \ + ruamoko/lib/sound.r \ + ruamoko/lib/string.r \ + ruamoko/lib/math.r \ + ruamoko/lib/types.r \ + ruamoko/lib/va_list.r \ + ruamoko/lib/obj_forward.r \ + ruamoko/lib/Object.r \ + ruamoko/lib/Protocol.r \ + ruamoko/lib/AutoreleasePool.r \ + ruamoko/lib/Array.r \ + ruamoko/lib/Array+Private.r \ + ruamoko/lib/Entity.r \ + ruamoko/lib/PropertyList.r \ + ruamoko/lib/Set.r +ruamoko_lib_libr_a_dep=$(call qcautodep,$(ruamoko_lib_libr_a_SOURCES)) +ruamoko_lib_libr_a_AR=$(PAK) -cf +EXTRA_ruamoko_lib_libr_a_DEPENDENCIES=pak +include $(ruamoko_lib_libr_a_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_lib_libr_a_dep) + +ruamoko_lib_common_src=ruamoko/lib/debug.r ruamoko/lib/system.r ruamoko/lib/legacy_string.r +ruamoko_lib_server_src= \ + ruamoko/lib/crudefile.r ruamoko/lib/entities.r ruamoko/lib/infokey.r ruamoko/lib/message.r \ + ruamoko/lib/physics.r ruamoko/lib/server.r ruamoko/lib/sv_sound.r +ruamoko_lib_libqw_a_src= \ + ruamoko/lib/qw_message.r ruamoko/lib/qw_physics.r ruamoko/lib/qw_sys.r +ruamoko_lib_libnq_a_src= \ + ruamoko/lib/nq_message.r +ruamoko_lib_libcsqc_a_src= ruamoko/lib/draw.r ruamoko/lib/gib.r ruamoko/lib/key.r + +ruamoko_lib_common_dep=$(call qcautodep,$(ruamoko_lib_common_src)) +include $(ruamoko_lib_common_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_lib_common_dep) + +ruamoko_lib_server_dep=$(call qcautodep,$(ruamoko_lib_server_src)) +include $(ruamoko_lib_server_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_lib_server_dep) + +ruamoko_lib_libqw_a_SOURCES=$(ruamoko_lib_libqw_a_src) $(ruamoko_lib_common_src) $(ruamoko_lib_server_src) ruamoko/lib/math.r +ruamoko_lib_libqw_a_dep=$(call qcautodep,$(ruamoko_lib_libqw_a_src)) +ruamoko_lib_libqw_a_AR=$(PAK) -cf +EXTRA_ruamoko_lib_libqw_a_DEPENDENCIES=pak +include $(ruamoko_lib_libqw_a_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_lib_libqw_a_dep) + +ruamoko_lib_libnq_a_SOURCES=$(ruamoko_lib_libnq_a_src) $(ruamoko_lib_common_src) $(ruamoko_lib_server_src) ruamoko/lib/math.r +ruamoko_lib_libnq_a_dep=$(call qcautodep,$(ruamoko_lib_libnq_a_src)) +ruamoko_lib_libnq_a_AR=$(PAK) -cf +EXTRA_ruamoko_lib_libnq_a_DEPENDENCIES=pak +include $(ruamoko_lib_libnq_a_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_lib_libnq_a_dep) + +ruamoko_lib_libcsqc_a_SOURCES=$(ruamoko_lib_libcsqc_a_src) $(ruamoko_lib_common_src) +ruamoko_lib_libcsqc_a_dep=$(call qcautodep,$(ruamoko_lib_libcsqc_a_src)) +ruamoko_lib_libcsqc_a_AR= $(PAK) -cf +EXTRA_ruamoko_lib_libcsqc_a_DEPENDENCIES=pak +include $(ruamoko_lib_libcsqc_a_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_lib_libcsqc_a_dep) + +CLEANFILES += \ + ruamoko/lib/*.dat \ + ruamoko/lib/*.sym +DISTCLEANFILES += \ + $(ruamoko_lib_libr_a_dep) \ + $(ruamoko_lib_common_dep) \ + $(ruamoko_lib_server_dep) \ + $(ruamoko_lib_libqw_a_dep) \ + $(ruamoko_lib_libnq_a_dep) \ + $(ruamoko_lib_libcsqc_a_dep) diff --git a/ruamoko/qwaq/Makefile.am b/ruamoko/qwaq/Makefile.am deleted file mode 100644 index 2208777f5..000000000 --- a/ruamoko/qwaq/Makefile.am +++ /dev/null @@ -1,135 +0,0 @@ -AUTOMAKE_OPTIONS= foreign subdir-objects - -QWAQ_LIBS=@QWAQ_LIBS@ -QWAQ_DEPS=@QWAQ_DEPS@ -QWAQ_INCS=@QWAQ_INCS@ - -AM_CPPFLAGS= -I$(srcdir) -I$(top_srcdir)/include $(QWAQ_INCS) $(PTHREAD_CFLAGS) - -noinst_PROGRAMS=@QWAQ_TARGETS@ qwaq-app.dat$(EXEEXT) gcd.dat$(EXEEXT) - -QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) -QFCC=$(top_builddir)/tools/qfcc/source/qfcc - -QCSYSTEM=--no-default-paths -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include -QWAQ_INC=-I$(srcdir) -I$(srcdir)/builtins -I$(srcdir)/debugger -I$(srcdir)/editor -I$(srcdir)/ui -QCFLAGS=-qq -O -g -Werror -QCPPFLAGS=$(QCSYSTEM) -I$(srcdir) -QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib -QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) -QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) - -SUFFIXES=.o .r -.r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo - -qwaq_app_dat_src= \ - qwaq-app.r \ - debugger/views/basicview.r \ - debugger/views/defview.r \ - debugger/views/doubleview.r \ - debugger/views/entityview.r \ - debugger/views/fieldview.r \ - debugger/views/floatview.r \ - debugger/views/funcview.r \ - debugger/views/intview.r \ - debugger/views/nameview.r \ - debugger/views/pointerview.r\ - debugger/views/quatview.r \ - debugger/views/stringview.r \ - debugger/views/uintview.r \ - debugger/views/vectorview.r \ - debugger/views/voidview.r \ - debugger/debug.r \ - debugger/debugger.r \ - debugger/localsdata.r \ - debugger/typeencodings.r \ - editor/editbuffer.r \ - editor/editor.r \ - ui/button.r \ - ui/draw.r \ - ui/garray.r \ - ui/group.r \ - ui/listener.r \ - ui/proxyview.r \ - ui/rect.r \ - ui/scrollbar.r \ - ui/tableview.r \ - ui/textcontext.r \ - ui/titlebar.r \ - ui/view.r \ - ui/window.r \ - $e - -#FIXME this coupling is horrible -qwaq_curses_libs= \ - $(top_builddir)/libs/video/targets/libvid_common.la \ - $(top_builddir)/libs/console/libQFconsole.la \ - $(top_builddir)/libs/gib/libQFgib.la - -qwaq_curses_SOURCES= \ - builtins/main.c \ - builtins/curses.c \ - builtins/debug.c \ - builtins/editbuffer.c \ - builtins/input.c \ - $e - -qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ - $(PANEL_LIBS) $(CURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) -qwaq_curses_LDFLAGS= -qwaq_curses_DEPENDENCIES= $(qwaq_curses_libs) $(QWAQ_DEPS) - -cl_plugin_libs= \ - @client_static_plugin_libs@ - -client_libs= \ - $(top_builddir)/libs/console/libQFconsole.la \ - $(top_builddir)/libs/video/targets/libQFjs.la \ - $(top_builddir)/libs/audio/libQFcd.la \ - $(top_builddir)/libs/audio/libQFsound.la \ - $(top_builddir)/libs/image/libQFimage.la - -qwaq_x11_libs= \ - $(cl_plugin_libs) \ - $(top_builddir)/libs/video/renderer/libQFrenderer.la \ - $(top_builddir)/libs/models/libQFmodels.la \ - $(top_builddir)/libs/video/targets/libQFx11.la \ - $(client_libs) \ - $(top_builddir)/libs/gib/libQFgib.la -qwaq_x11_SOURCES=builtins/qwaq.c builtins/qwaq-bi.c -qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \ - $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ - $(X_EXTRA_LIBS) $(X_SHM_LIB) $(DL_LIBS) -qwaq_x11_LDFLAGS= -qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) - -r_depfiles_remade= - -qwaq_app_dat_SOURCES=$(qwaq_app_dat_src) -qwaq_app_obj=$(qwaq_app_dat_SOURCES:.r=.o) -qwaq_app_dep=$(addprefix ./$(DEPDIR)/,$(qwaq_app_obj:.o=.Qo)) -qwaq-app.dat$(EXEEXT): $(qwaq_app_obj) $(QFCC_DEP) ../lib/libcsqc.a ../lib/libr.a - $(QLINK) -o $@ $(qwaq_app_obj) -lcsqc -lr -include $(qwaq_app_dep) # am--include-marker -r_depfiles_remade += $(qwaq_app_dep) - -gcd_dat_SOURCES=gcd.r -gcd_obj=$(gcd_dat_SOURCES:.r=.o) -gcd_dep=$(addprefix ./$(DEPDIR)/,$(gcd_obj:.o=.Qo)) -gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) ../lib/libcsqc.a ../lib/libr.a - $(QLINK) -o $@ $(gcd_obj) -lcsqc -lr -include $(gcd_dep) # am--include-marker -r_depfiles_remade += $(gcd_dep) - -$(r_depfiles_remade): - @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) - -EXTRA_PROGRAMS=qwaq-curses qwaq-x11 -EXTRA_DIST=$(qwaq_dat_src) qwaq.h -CLEANFILES= *.dat *.sym qwaq-curses.log diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am new file mode 100644 index 000000000..149213268 --- /dev/null +++ b/ruamoko/qwaq/Makemodule.am @@ -0,0 +1,149 @@ +QWAQ_LIBS=@QWAQ_LIBS@ +QWAQ_DEPS=@QWAQ_DEPS@ +QWAQ_INCS=@QWAQ_INCS@ + +noinst_PROGRAMS += @QWAQ_TARGETS@ ruamoko/qwaq/qwaq-app.dat$(EXEEXT) ruamoko/qwaq/gcd.dat$(EXEEXT) + +qwaq_app_dat_src= \ + ruamoko/qwaq/qwaq-app.r \ + ruamoko/qwaq/debugger/views/basicview.r \ + ruamoko/qwaq/debugger/views/defview.r \ + ruamoko/qwaq/debugger/views/doubleview.r \ + ruamoko/qwaq/debugger/views/entityview.r \ + ruamoko/qwaq/debugger/views/fieldview.r \ + ruamoko/qwaq/debugger/views/floatview.r \ + ruamoko/qwaq/debugger/views/funcview.r \ + ruamoko/qwaq/debugger/views/intview.r \ + ruamoko/qwaq/debugger/views/nameview.r \ + ruamoko/qwaq/debugger/views/pointerview.r\ + ruamoko/qwaq/debugger/views/quatview.r \ + ruamoko/qwaq/debugger/views/stringview.r \ + ruamoko/qwaq/debugger/views/uintview.r \ + ruamoko/qwaq/debugger/views/vectorview.r \ + ruamoko/qwaq/debugger/views/voidview.r \ + ruamoko/qwaq/debugger/debug.r \ + ruamoko/qwaq/debugger/debugger.r \ + ruamoko/qwaq/debugger/localsdata.r \ + ruamoko/qwaq/debugger/typeencodings.r \ + ruamoko/qwaq/editor/editbuffer.r \ + ruamoko/qwaq/editor/editor.r \ + ruamoko/qwaq/ui/button.r \ + ruamoko/qwaq/ui/draw.r \ + ruamoko/qwaq/ui/garray.r \ + ruamoko/qwaq/ui/group.r \ + ruamoko/qwaq/ui/listener.r \ + ruamoko/qwaq/ui/proxyview.r \ + ruamoko/qwaq/ui/rect.r \ + ruamoko/qwaq/ui/scrollbar.r \ + ruamoko/qwaq/ui/tableview.r \ + ruamoko/qwaq/ui/textcontext.r \ + ruamoko/qwaq/ui/titlebar.r \ + ruamoko/qwaq/ui/view.r \ + ruamoko/qwaq/ui/window.r \ + $e + +#FIXME this coupling is horrible +qwaq_curses_libs= \ + libs/video/targets/libvid_common.la \ + libs/console/libQFconsole.la \ + libs/gib/libQFgib.la + +ruamoko_qwaq_qwaq_curses_SOURCES= \ + ruamoko/qwaq/builtins/main.c \ + ruamoko/qwaq/builtins/curses.c \ + ruamoko/qwaq/builtins/debug.c \ + ruamoko/qwaq/builtins/editbuffer.c \ + ruamoko/qwaq/builtins/input.c \ + $e + +ruamoko_qwaq_qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ + $(PANEL_LIBS) $(CURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) +ruamoko_qwaq_qwaq_curses_LDFLAGS= +ruamoko_qwaq_qwaq_curses_DEPENDENCIES= $(qwaq_curses_libs) $(QWAQ_DEPS) + +qwaq_cl_plugin_libs= \ + @client_static_plugin_libs@ + +qwaq_client_libs= \ + $(top_builddir)/libs/console/libQFconsole.la \ + $(top_builddir)/libs/video/targets/libQFjs.la \ + $(top_builddir)/libs/audio/libQFcd.la \ + $(top_builddir)/libs/audio/libQFsound.la \ + $(top_builddir)/libs/image/libQFimage.la + +qwaq_x11_libs= \ + $(qwaq_cl_plugin_libs) \ + $(top_builddir)/libs/video/renderer/libQFrenderer.la \ + $(top_builddir)/libs/models/libQFmodels.la \ + $(top_builddir)/libs/video/targets/libQFx11.la \ + $(qwaq_client_libs) \ + $(top_builddir)/libs/gib/libQFgib.la +ruamoko_qwaq_qwaq_x11_SOURCES=ruamoko/qwaq/builtins/qwaq.c ruamoko/qwaq/builtins/qwaq-bi.c +ruamoko_qwaq_qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \ + $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ + $(X_EXTRA_LIBS) $(X_SHM_LIB) $(DL_LIBS) +ruamoko_qwaq_qwaq_x11_LDFLAGS= +ruamoko_qwaq_qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) + +ruamoko_qwaq_qwaq_app_dat_SOURCES=$(qwaq_app_dat_src) +ruamoko_qwaq_qwaq_app_obj=$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.r=.o) +ruamoko_qwaq_qwaq_app_dep=$(call qcautodep,$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.o=.Qo)) +ruamoko/qwaq/qwaq-app.dat$(EXEEXT): $(ruamoko_qwaq_qwaq_app_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a + $(QLINK) -o $@ $(ruamoko_qwaq_qwaq_app_obj) -lcsqc -lr +include $(ruamoko_qwaq_qwaq_app_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_qwaq_qwaq_app_dep) + +ruamoko_qwaq_gcd_dat_SOURCES=ruamoko/qwaq/gcd.r +ruamoko_qwaq_gcd_obj=$(ruamoko_qwaq_gcd_dat_SOURCES:.r=.o) +ruamoko_qwaq_gcd_dep=$(call qcautodep,$(ruamoko_qwaq_gcd_dat_SOURCES:.o=.Qo)) +ruamoko/qwaq/gcd.dat$(EXEEXT): $(ruamoko_qwaq_gcd_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a + $(QLINK) -o $@ $(ruamoko_qwaq_gcd_obj) -lcsqc -lr +include $(ruamoko_qwaq_gcd_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_qwaq_gcd_dep) + +EXTRA_PROGRAMS += ruamoko/qwaq/qwaq-curses ruamoko/qwaq/qwaq-x11 +EXTRA_DIST += \ + $(qwaq_dat_src) \ + ruamoko/qwaq/debugger/debug.h \ + ruamoko/qwaq/debugger/debugger.h \ + ruamoko/qwaq/debugger/localsdata.h \ + ruamoko/qwaq/debugger/typeencodings.h \ + ruamoko/qwaq/debugger/views/basicview.h \ + ruamoko/qwaq/debugger/views/defview.h \ + ruamoko/qwaq/debugger/views/doubleview.h \ + ruamoko/qwaq/debugger/views/entityview.h \ + ruamoko/qwaq/debugger/views/fieldview.h \ + ruamoko/qwaq/debugger/views/floatview.h \ + ruamoko/qwaq/debugger/views/funcview.h \ + ruamoko/qwaq/debugger/views/intview.h \ + ruamoko/qwaq/debugger/views/nameview.h \ + ruamoko/qwaq/debugger/views/pointerview.h \ + ruamoko/qwaq/debugger/views/quatview.h \ + ruamoko/qwaq/debugger/views/stringview.h \ + ruamoko/qwaq/debugger/views/uintview.h \ + ruamoko/qwaq/debugger/views/vectorview.h \ + ruamoko/qwaq/debugger/views/voidview.h \ + ruamoko/qwaq/editor/editbuffer.h \ + ruamoko/qwaq/editor/editor.h \ + ruamoko/qwaq/qwaq-app.h \ + ruamoko/qwaq/qwaq.h \ + ruamoko/qwaq/ui/button.h \ + ruamoko/qwaq/ui/color.h \ + ruamoko/qwaq/ui/curses.h \ + ruamoko/qwaq/ui/draw.h \ + ruamoko/qwaq/ui/event.h \ + ruamoko/qwaq/ui/garray.h \ + ruamoko/qwaq/ui/group.h \ + ruamoko/qwaq/ui/listener.h \ + ruamoko/qwaq/ui/proxyview.h \ + ruamoko/qwaq/ui/rect.h \ + ruamoko/qwaq/ui/scrollbar.h \ + ruamoko/qwaq/ui/tableview.h \ + ruamoko/qwaq/ui/textcontext.h \ + ruamoko/qwaq/ui/titlebar.h \ + ruamoko/qwaq/ui/view.h \ + ruamoko/qwaq/ui/window.h +CLEANFILES += \ + ruamoko/qwaq/qwaq-curses.log \ + ruamoko/qwaq/*.dat \ + ruamoko/qwaq/*.sym diff --git a/ruamoko/qwaq/builtins/builtins.c b/ruamoko/qwaq/builtins/builtins.c index 3976dc330..9f575617c 100644 --- a/ruamoko/qwaq/builtins/builtins.c +++ b/ruamoko/qwaq/builtins/builtins.c @@ -42,7 +42,7 @@ #include #include -#include "qwaq.h" +#include "ruamoko/qwaq/qwaq.h" static void bi_print (progs_t *pr) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 3075f9412..8f543f493 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -46,10 +46,10 @@ #include "QF/ringbuffer.h" #include "QF/sys.h" -#include "qwaq.h" -#include "ui/curses.h" -#include "ui/rect.h" -#include "ui/textcontext.h" +#include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/ui/curses.h" +#include "ruamoko/qwaq/ui/rect.h" +#include "ruamoko/qwaq/ui/textcontext.h" #define always_inline inline __attribute__((__always_inline__)) #define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index be143ec87..bb22d35e2 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -47,10 +47,10 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "qwaq.h" -#include "ui/event.h" -#include "ui/curses.h" -#include "debugger/debug.h" +#include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/ui/event.h" +#include "ruamoko/qwaq/ui/curses.h" +#include "ruamoko/qwaq/debugger/debug.h" typedef struct qwaq_target_s { progs_t *pr; diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index ab1c161c3..12cde52ab 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -11,8 +11,8 @@ #include "QF/quakeio.h" #include "QF/txtbuffer.h" -#include "qwaq.h" -#include "editor/editbuffer.h" +#include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/editor/editbuffer.h" #define always_inline inline __attribute__((__always_inline__)) diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 29d5a6088..ce2caec46 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -46,9 +46,9 @@ #include "QF/keys.h" #include "QF/sys.h" -#include "qwaq.h" -#include "ui/event.h" -#include "ui/curses.h" +#include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/ui/event.h" +#include "ruamoko/qwaq/ui/curses.h" #define always_inline inline __attribute__((__always_inline__)) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index db4f8da59..da3607c01 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -52,8 +52,8 @@ #include "QF/va.h" #include "QF/zone.h" -#include "qwaq.h" -#include "debugger/debug.h" +#include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/debugger/debug.h" #define MAX_EDICTS 1024 diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c index 82bce4996..602709bdf 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/qwaq-bi.c @@ -60,7 +60,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" -#include "qwaq.h" +#include "ruamoko/qwaq/qwaq.h" CLIENT_PLUGIN_PROTOS static plugin_list_t client_plugin_list[] = { diff --git a/ruamoko/qwaq/builtins/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c index 05d515f4e..111af8764 100644 --- a/ruamoko/qwaq/builtins/qwaq.c +++ b/ruamoko/qwaq/builtins/qwaq.c @@ -46,7 +46,7 @@ #include "QF/va.h" #include "QF/zone.h" -#include "qwaq.h" +#include "ruamoko/qwaq/qwaq.h" #define MAX_EDICTS 1024 diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index 6efeb5fb2..f6f58f5ed 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_debug_h #define __qwaq_debugger_debug_h -#include "ui/event.h" +#include "ruamoko/qwaq/ui/event.h" typedef enum { qe_debug_event = 0x0100, diff --git a/ruamoko/qwaq/debugger/debug.r b/ruamoko/qwaq/debugger/debug.r index 20ccc57b3..feb8adbdd 100644 --- a/ruamoko/qwaq/debugger/debug.r +++ b/ruamoko/qwaq/debugger/debug.r @@ -1,4 +1,4 @@ -#include "debugger/debug.h" +#include "ruamoko/qwaq/debugger/debug.h" void traceon() = #0; void traceoff() = #0; diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 13adcf752..9e6c750d2 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -4,8 +4,8 @@ #include #include -#include "debugger/debug.h" -#include "debugger/localsdata.h" +#include "ruamoko/qwaq/debugger/debug.h" +#include "ruamoko/qwaq/debugger/localsdata.h" @class ProxyView; @class Editor; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index d46c78ab7..2d51e3c60 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -3,16 +3,16 @@ #include #include -#include "ui/curses.h" -#include "ui/listener.h" -#include "ui/proxyview.h" -#include "ui/scrollbar.h" -#include "ui/tableview.h" -#include "ui/window.h" -#include "debugger/debugger.h" -#include "debugger/typeencodings.h" -#include "editor/editor.h" -#include "qwaq-app.h" +#include "ruamoko/qwaq/ui/curses.h" +#include "ruamoko/qwaq/ui/listener.h" +#include "ruamoko/qwaq/ui/proxyview.h" +#include "ruamoko/qwaq/ui/scrollbar.h" +#include "ruamoko/qwaq/ui/tableview.h" +#include "ruamoko/qwaq/ui/window.h" +#include "ruamoko/qwaq/debugger/debugger.h" +#include "ruamoko/qwaq/debugger/typeencodings.h" +#include "ruamoko/qwaq/editor/editor.h" +#include "ruamoko/qwaq/qwaq-app.h" @implementation Debugger +(Debugger *)withTarget:(qdb_target_t)target diff --git a/ruamoko/qwaq/debugger/localsdata.h b/ruamoko/qwaq/debugger/localsdata.h index 9562921c1..3428219cb 100644 --- a/ruamoko/qwaq/debugger/localsdata.h +++ b/ruamoko/qwaq/debugger/localsdata.h @@ -2,8 +2,8 @@ #define __qwaq_debugger_localsview_h #include -#include "ui/tableview.h" -#include "debugger/debug.h" +#include "ruamoko/qwaq/ui/tableview.h" +#include "ruamoko/qwaq/debugger/debug.h" @interface LocalsData : Object { diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index d65869491..c974cdd98 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -1,9 +1,9 @@ #include #include -#include "debugger/views/defview.h" -#include "debugger/views/nameview.h" -#include "debugger/localsdata.h" -#include "debugger/typeencodings.h" +#include "ruamoko/qwaq/debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/nameview.h" +#include "ruamoko/qwaq/debugger/localsdata.h" +#include "ruamoko/qwaq/debugger/typeencodings.h" @implementation LocalsData diff --git a/ruamoko/qwaq/debugger/typeencodings.h b/ruamoko/qwaq/debugger/typeencodings.h index 213dad8a7..11b78d0da 100644 --- a/ruamoko/qwaq/debugger/typeencodings.h +++ b/ruamoko/qwaq/debugger/typeencodings.h @@ -4,7 +4,7 @@ #include #include -#include "debugger/debug.h" +#include "ruamoko/qwaq/debugger/debug.h" @interface TypeEncodings : Object +(qfot_type_t *)getType:(unsigned)typeAddr fromTarget:(qdb_target_t)target; diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index ad04dbbcd..7a5fd26d7 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -1,9 +1,9 @@ #include #include #include -#include // printf FIXME -#include "debugger/typeencodings.h" +#include "ruamoko/qwaq/ui/curses.h" // printf FIXME +#include "ruamoko/qwaq/debugger/typeencodings.h" @implementation TypeEncodings diff --git a/ruamoko/qwaq/debugger/views/basicview.h b/ruamoko/qwaq/debugger/views/basicview.h index d9289889f..d5424c487 100644 --- a/ruamoko/qwaq/debugger/views/basicview.h +++ b/ruamoko/qwaq/debugger/views/basicview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_basicview_h #define __qwaq_debugger_basicview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface BasicView : DefView // might return a NameView (which is also a DefView) diff --git a/ruamoko/qwaq/debugger/views/basicview.r b/ruamoko/qwaq/debugger/views/basicview.r index 8a2067285..96abfc302 100644 --- a/ruamoko/qwaq/debugger/views/basicview.r +++ b/ruamoko/qwaq/debugger/views/basicview.r @@ -1,6 +1,6 @@ #include -#include "debugger/views/basicview.h" -#include "debugger/views/nameview.h" +#include "ruamoko/qwaq/debugger/views/basicview.h" +#include "ruamoko/qwaq/debugger/views/nameview.h" static string type_views[] = { "VoidView", diff --git a/ruamoko/qwaq/debugger/views/defview.h b/ruamoko/qwaq/debugger/views/defview.h index 4760abcad..7e2562104 100644 --- a/ruamoko/qwaq/debugger/views/defview.h +++ b/ruamoko/qwaq/debugger/views/defview.h @@ -2,8 +2,8 @@ #define __qwaq_debugger_defview_h #include -#include "ui/view.h" -#include "debugger/debug.h" +#include "ruamoko/qwaq/ui/view.h" +#include "ruamoko/qwaq/debugger/debug.h" @interface DefView : View { diff --git a/ruamoko/qwaq/debugger/views/defview.r b/ruamoko/qwaq/debugger/views/defview.r index ee681e23e..a972b972f 100644 --- a/ruamoko/qwaq/debugger/views/defview.r +++ b/ruamoko/qwaq/debugger/views/defview.r @@ -1,6 +1,6 @@ #include -#include "debugger/views/defview.h" -#include "debugger/views/nameview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/nameview.h" static string meta_views[] = { "BasicView", diff --git a/ruamoko/qwaq/debugger/views/doubleview.h b/ruamoko/qwaq/debugger/views/doubleview.h index 8fda5ac24..90637ecf3 100644 --- a/ruamoko/qwaq/debugger/views/doubleview.h +++ b/ruamoko/qwaq/debugger/views/doubleview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_doubleview_h #define __qwaq_debugger_doubleview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface DoubleView : DefView { diff --git a/ruamoko/qwaq/debugger/views/doubleview.r b/ruamoko/qwaq/debugger/views/doubleview.r index 36fbfd59d..d94f4e231 100644 --- a/ruamoko/qwaq/debugger/views/doubleview.r +++ b/ruamoko/qwaq/debugger/views/doubleview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/doubleview.h" +#include "ruamoko/qwaq/debugger/views/doubleview.h" @implementation DoubleView diff --git a/ruamoko/qwaq/debugger/views/entityview.h b/ruamoko/qwaq/debugger/views/entityview.h index df8de2c3d..5ad8bd908 100644 --- a/ruamoko/qwaq/debugger/views/entityview.h +++ b/ruamoko/qwaq/debugger/views/entityview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_entityview_h #define __qwaq_debugger_entityview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface EntityView : DefView { diff --git a/ruamoko/qwaq/debugger/views/entityview.r b/ruamoko/qwaq/debugger/views/entityview.r index 49180e914..1170a3f7d 100644 --- a/ruamoko/qwaq/debugger/views/entityview.r +++ b/ruamoko/qwaq/debugger/views/entityview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/entityview.h" +#include "ruamoko/qwaq/debugger/views/entityview.h" @implementation EntityView diff --git a/ruamoko/qwaq/debugger/views/fieldview.h b/ruamoko/qwaq/debugger/views/fieldview.h index 5d90bf77f..0cd314b6b 100644 --- a/ruamoko/qwaq/debugger/views/fieldview.h +++ b/ruamoko/qwaq/debugger/views/fieldview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_fieldview_h #define __qwaq_debugger_fieldview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface FieldView : DefView { diff --git a/ruamoko/qwaq/debugger/views/fieldview.r b/ruamoko/qwaq/debugger/views/fieldview.r index 49bf7282b..f8d1547e3 100644 --- a/ruamoko/qwaq/debugger/views/fieldview.r +++ b/ruamoko/qwaq/debugger/views/fieldview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/fieldview.h" +#include "ruamoko/qwaq/debugger/views/fieldview.h" @implementation FieldView diff --git a/ruamoko/qwaq/debugger/views/floatview.h b/ruamoko/qwaq/debugger/views/floatview.h index a51469709..5c33da88b 100644 --- a/ruamoko/qwaq/debugger/views/floatview.h +++ b/ruamoko/qwaq/debugger/views/floatview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_floatview_h #define __qwaq_debugger_floatview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface FloatView : DefView { diff --git a/ruamoko/qwaq/debugger/views/floatview.r b/ruamoko/qwaq/debugger/views/floatview.r index e98e9e8a8..5b4d534eb 100644 --- a/ruamoko/qwaq/debugger/views/floatview.r +++ b/ruamoko/qwaq/debugger/views/floatview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/floatview.h" +#include "ruamoko/qwaq/debugger/views/floatview.h" @implementation FloatView diff --git a/ruamoko/qwaq/debugger/views/funcview.h b/ruamoko/qwaq/debugger/views/funcview.h index 5a004800c..132812dd3 100644 --- a/ruamoko/qwaq/debugger/views/funcview.h +++ b/ruamoko/qwaq/debugger/views/funcview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_funcview_h #define __qwaq_debugger_funcview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface FuncView : DefView { diff --git a/ruamoko/qwaq/debugger/views/funcview.r b/ruamoko/qwaq/debugger/views/funcview.r index c102bfce1..2fa2218f0 100644 --- a/ruamoko/qwaq/debugger/views/funcview.r +++ b/ruamoko/qwaq/debugger/views/funcview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/funcview.h" +#include "ruamoko/qwaq/debugger/views/funcview.h" @implementation FuncView diff --git a/ruamoko/qwaq/debugger/views/intview.h b/ruamoko/qwaq/debugger/views/intview.h index fddb2f2d5..d2f271b21 100644 --- a/ruamoko/qwaq/debugger/views/intview.h +++ b/ruamoko/qwaq/debugger/views/intview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_intview_h #define __qwaq_debugger_intview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface IntView : DefView { diff --git a/ruamoko/qwaq/debugger/views/intview.r b/ruamoko/qwaq/debugger/views/intview.r index 6caad42ac..a7df120ed 100644 --- a/ruamoko/qwaq/debugger/views/intview.r +++ b/ruamoko/qwaq/debugger/views/intview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/intview.h" +#include "ruamoko/qwaq/debugger/views/intview.h" @implementation IntView diff --git a/ruamoko/qwaq/debugger/views/nameview.h b/ruamoko/qwaq/debugger/views/nameview.h index 7d5838bce..ee5622062 100644 --- a/ruamoko/qwaq/debugger/views/nameview.h +++ b/ruamoko/qwaq/debugger/views/nameview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_nameview_h #define __qwaq_debugger_nameview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface NameView : DefView { diff --git a/ruamoko/qwaq/debugger/views/nameview.r b/ruamoko/qwaq/debugger/views/nameview.r index 9764fedaf..0b66d838e 100644 --- a/ruamoko/qwaq/debugger/views/nameview.r +++ b/ruamoko/qwaq/debugger/views/nameview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/nameview.h" +#include "ruamoko/qwaq/debugger/views/nameview.h" @implementation NameView diff --git a/ruamoko/qwaq/debugger/views/pointerview.h b/ruamoko/qwaq/debugger/views/pointerview.h index 4853958e9..fb45f1ae3 100644 --- a/ruamoko/qwaq/debugger/views/pointerview.h +++ b/ruamoko/qwaq/debugger/views/pointerview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_pointerview_h #define __qwaq_debugger_pointerview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface PointerView : DefView { diff --git a/ruamoko/qwaq/debugger/views/pointerview.r b/ruamoko/qwaq/debugger/views/pointerview.r index 20743ea19..3a000ecf5 100644 --- a/ruamoko/qwaq/debugger/views/pointerview.r +++ b/ruamoko/qwaq/debugger/views/pointerview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/pointerview.h" +#include "ruamoko/qwaq/debugger/views/pointerview.h" @implementation PointerView diff --git a/ruamoko/qwaq/debugger/views/quatview.h b/ruamoko/qwaq/debugger/views/quatview.h index 189a600f8..b88f75811 100644 --- a/ruamoko/qwaq/debugger/views/quatview.h +++ b/ruamoko/qwaq/debugger/views/quatview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_quatview_h #define __qwaq_debugger_quatview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface QuatView : DefView { diff --git a/ruamoko/qwaq/debugger/views/quatview.r b/ruamoko/qwaq/debugger/views/quatview.r index ba98e9d2b..fe8ca0ea1 100644 --- a/ruamoko/qwaq/debugger/views/quatview.r +++ b/ruamoko/qwaq/debugger/views/quatview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/quatview.h" +#include "ruamoko/qwaq/debugger/views/quatview.h" @implementation QuatView diff --git a/ruamoko/qwaq/debugger/views/stringview.h b/ruamoko/qwaq/debugger/views/stringview.h index 5cabaf674..c8a49d131 100644 --- a/ruamoko/qwaq/debugger/views/stringview.h +++ b/ruamoko/qwaq/debugger/views/stringview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_stringview_h #define __qwaq_debugger_stringview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface StringView : DefView { diff --git a/ruamoko/qwaq/debugger/views/stringview.r b/ruamoko/qwaq/debugger/views/stringview.r index 79ef75212..d686fd636 100644 --- a/ruamoko/qwaq/debugger/views/stringview.r +++ b/ruamoko/qwaq/debugger/views/stringview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/stringview.h" +#include "ruamoko/qwaq/debugger/views/stringview.h" @implementation StringView diff --git a/ruamoko/qwaq/debugger/views/uintview.h b/ruamoko/qwaq/debugger/views/uintview.h index 9597c5519..5211b2ff7 100644 --- a/ruamoko/qwaq/debugger/views/uintview.h +++ b/ruamoko/qwaq/debugger/views/uintview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_uintview_h #define __qwaq_debugger_uintview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface UIntView : DefView { diff --git a/ruamoko/qwaq/debugger/views/uintview.r b/ruamoko/qwaq/debugger/views/uintview.r index e06ac32fa..c80b9b517 100644 --- a/ruamoko/qwaq/debugger/views/uintview.r +++ b/ruamoko/qwaq/debugger/views/uintview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/uintview.h" +#include "ruamoko/qwaq/debugger/views/uintview.h" @implementation UIntView diff --git a/ruamoko/qwaq/debugger/views/vectorview.h b/ruamoko/qwaq/debugger/views/vectorview.h index b6b95fa34..2a00c4e39 100644 --- a/ruamoko/qwaq/debugger/views/vectorview.h +++ b/ruamoko/qwaq/debugger/views/vectorview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_vectorview_h #define __qwaq_debugger_vectorview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface VectorView : DefView { diff --git a/ruamoko/qwaq/debugger/views/vectorview.r b/ruamoko/qwaq/debugger/views/vectorview.r index 2fa8b41ed..61a50c6af 100644 --- a/ruamoko/qwaq/debugger/views/vectorview.r +++ b/ruamoko/qwaq/debugger/views/vectorview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/vectorview.h" +#include "ruamoko/qwaq/debugger/views/vectorview.h" @implementation VectorView diff --git a/ruamoko/qwaq/debugger/views/voidview.h b/ruamoko/qwaq/debugger/views/voidview.h index 6232968e0..1c6655bb1 100644 --- a/ruamoko/qwaq/debugger/views/voidview.h +++ b/ruamoko/qwaq/debugger/views/voidview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_debugger_voidview_h #define __qwaq_debugger_voidview_h -#include "debugger/views/defview.h" +#include "ruamoko/qwaq/debugger/views/defview.h" @interface VoidView : DefView { diff --git a/ruamoko/qwaq/debugger/views/voidview.r b/ruamoko/qwaq/debugger/views/voidview.r index 440edece2..81e58b62c 100644 --- a/ruamoko/qwaq/debugger/views/voidview.r +++ b/ruamoko/qwaq/debugger/views/voidview.r @@ -1,5 +1,5 @@ #include -#include "debugger/views/voidview.h" +#include "ruamoko/qwaq/debugger/views/voidview.h" @implementation VoidView diff --git a/ruamoko/qwaq/editor/editbuffer.r b/ruamoko/qwaq/editor/editbuffer.r index 9a6da8396..cd7644f7d 100644 --- a/ruamoko/qwaq/editor/editbuffer.r +++ b/ruamoko/qwaq/editor/editbuffer.r @@ -1,4 +1,4 @@ -#include "editor/editbuffer.h" +#include "ruamoko/qwaq/editor/editbuffer.h" @implementation EditBuffer +(EditBuffer *)buffer diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index b5bd4b7d5..cd04f8a8e 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -1,8 +1,8 @@ #ifndef __qwaq_editor_editor_h #define __qwaq_editor_editor_h -#include "editor/editbuffer.h" -#include "ui/view.h" +#include "ruamoko/qwaq/editor/editbuffer.h" +#include "ruamoko/qwaq/ui/view.h" @class Editor; @class EditBuffer; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index 8dd64c21d..62158dfe9 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -1,9 +1,9 @@ #include #include -#include "qwaq-app.h" -#include "editor/editor.h" -#include "ui/listener.h" -#include "ui/scrollbar.h" +#include "ruamoko/qwaq/qwaq-app.h" +#include "ruamoko/qwaq/editor/editor.h" +#include "ruamoko/qwaq/ui/listener.h" +#include "ruamoko/qwaq/ui/scrollbar.h" @implementation Editor diff --git a/ruamoko/qwaq/qwaq-app.h b/ruamoko/qwaq/qwaq-app.h index bf6255740..a35cee787 100644 --- a/ruamoko/qwaq/qwaq-app.h +++ b/ruamoko/qwaq/qwaq-app.h @@ -3,8 +3,8 @@ #include -#include "ui/event.h" -#include "ui/rect.h" +#include "ruamoko/qwaq/ui/event.h" +#include "ruamoko/qwaq/ui/rect.h" @class Array; @class Group; diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index e98f4d03f..9520cf67e 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -3,12 +3,12 @@ int fence; #include #include -#include "ui/color.h" -#include "ui/curses.h" -#include "ui/group.h" -#include "ui/view.h" -#include "debugger/debugger.h" -#include "qwaq-app.h" +#include "ruamoko/qwaq/ui/color.h" +#include "ruamoko/qwaq/ui/curses.h" +#include "ruamoko/qwaq/ui/group.h" +#include "ruamoko/qwaq/ui/view.h" +#include "ruamoko/qwaq/debugger/debugger.h" +#include "ruamoko/qwaq/qwaq-app.h" int color_palette[64]; diff --git a/ruamoko/qwaq/ui/button.h b/ruamoko/qwaq/ui/button.h index 8db47b4f8..7fc2e9716 100644 --- a/ruamoko/qwaq/ui/button.h +++ b/ruamoko/qwaq/ui/button.h @@ -1,8 +1,8 @@ #ifndef __qwaq_ui_button_h #define __qwaq_ui_button_h -#include "ui/draw.h" -#include "ui/view.h" +#include "ruamoko/qwaq/ui/draw.h" +#include "ruamoko/qwaq/ui/view.h" @class ListenerGroup; diff --git a/ruamoko/qwaq/ui/button.r b/ruamoko/qwaq/ui/button.r index f2951d2f2..7f42fb3e4 100644 --- a/ruamoko/qwaq/ui/button.r +++ b/ruamoko/qwaq/ui/button.r @@ -1,5 +1,5 @@ -#include "ui/button.h" -#include "ui/listener.h" +#include "ruamoko/qwaq/ui/button.h" +#include "ruamoko/qwaq/ui/listener.h" @implementation Button diff --git a/ruamoko/qwaq/ui/curses.h b/ruamoko/qwaq/ui/curses.h index 1849a6440..f3038365e 100644 --- a/ruamoko/qwaq/ui/curses.h +++ b/ruamoko/qwaq/ui/curses.h @@ -1,7 +1,7 @@ #ifndef __qwaq_ui_curses_h #define __qwaq_ui_curses_h -#include "ui/event.h" +#include "ruamoko/qwaq/ui/event.h" typedef struct box_sides_s { int ls; @@ -18,7 +18,7 @@ typedef struct box_corners_s { } box_corners_t; #ifdef __QFCC__ -#include "ui/rect.h" +#include "ruamoko/qwaq/ui/rect.h" // names, order and comments lifted from ncurses.h typedef enum { diff --git a/ruamoko/qwaq/ui/draw.h b/ruamoko/qwaq/ui/draw.h index eb7379fe4..e9a9e44b5 100644 --- a/ruamoko/qwaq/ui/draw.h +++ b/ruamoko/qwaq/ui/draw.h @@ -3,7 +3,7 @@ #include -#include "ui/rect.h" +#include "ruamoko/qwaq/ui/rect.h" @class DrawBuffer; diff --git a/ruamoko/qwaq/ui/draw.r b/ruamoko/qwaq/ui/draw.r index ebb75fcbd..aeaa00475 100644 --- a/ruamoko/qwaq/ui/draw.r +++ b/ruamoko/qwaq/ui/draw.r @@ -1,7 +1,7 @@ #include -#include "ui/curses.h" -#include "ui/draw.h" +#include "ruamoko/qwaq/ui/curses.h" +#include "ruamoko/qwaq/ui/draw.h" @implementation DrawBuffer diff --git a/ruamoko/qwaq/ui/garray.r b/ruamoko/qwaq/ui/garray.r index ee6bd0191..55aa35e88 100644 --- a/ruamoko/qwaq/ui/garray.r +++ b/ruamoko/qwaq/ui/garray.r @@ -1,6 +1,6 @@ #include -#include "ui/event.h" -#include "ui/garray.h" +#include "ruamoko/qwaq/ui/event.h" +#include "ruamoko/qwaq/ui/garray.h" @implementation Array (Group) - (void) makeObjectsPerformSelector: (SEL)selector diff --git a/ruamoko/qwaq/ui/group.h b/ruamoko/qwaq/ui/group.h index 071ee53f0..c1b96b80d 100644 --- a/ruamoko/qwaq/ui/group.h +++ b/ruamoko/qwaq/ui/group.h @@ -3,8 +3,8 @@ #include -#include "ui/event.h" -#include "ui/draw.h" +#include "ruamoko/qwaq/ui/event.h" +#include "ruamoko/qwaq/ui/draw.h" @class View; diff --git a/ruamoko/qwaq/ui/group.r b/ruamoko/qwaq/ui/group.r index 8bbca6d9b..e2e8e1890 100644 --- a/ruamoko/qwaq/ui/group.r +++ b/ruamoko/qwaq/ui/group.r @@ -1,9 +1,9 @@ #include -#include "ui/event.h" -#include "ui/draw.h" -#include "ui/garray.h" -#include "ui/group.h" -#include "ui/view.h" +#include "ruamoko/qwaq/ui/event.h" +#include "ruamoko/qwaq/ui/draw.h" +#include "ruamoko/qwaq/ui/garray.h" +#include "ruamoko/qwaq/ui/group.h" +#include "ruamoko/qwaq/ui/view.h" @implementation Group diff --git a/ruamoko/qwaq/ui/listener.r b/ruamoko/qwaq/ui/listener.r index 31dd001fa..8fa43b01f 100644 --- a/ruamoko/qwaq/ui/listener.r +++ b/ruamoko/qwaq/ui/listener.r @@ -1,7 +1,7 @@ #include -#include "ui/listener.h" -#include "ui/curses.h" +#include "ruamoko/qwaq/ui/listener.h" +#include "ruamoko/qwaq/ui/curses.h" @class Array; diff --git a/ruamoko/qwaq/ui/proxyview.h b/ruamoko/qwaq/ui/proxyview.h index d19a47ef0..c7d062cdc 100644 --- a/ruamoko/qwaq/ui/proxyview.h +++ b/ruamoko/qwaq/ui/proxyview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_ui_proxyview_h #define __qwaq_ui_proxyview_h -#include "ui/view.h" +#include "ruamoko/qwaq/ui/view.h" @class Group; diff --git a/ruamoko/qwaq/ui/proxyview.r b/ruamoko/qwaq/ui/proxyview.r index 71a85e36d..714b3fd9d 100644 --- a/ruamoko/qwaq/ui/proxyview.r +++ b/ruamoko/qwaq/ui/proxyview.r @@ -1,5 +1,5 @@ -#include "ui/group.h" -#include "ui/proxyview.h" +#include "ruamoko/qwaq/ui/group.h" +#include "ruamoko/qwaq/ui/proxyview.h" @implementation ProxyView +(ProxyView *)withView:(View *)view diff --git a/ruamoko/qwaq/ui/rect.r b/ruamoko/qwaq/ui/rect.r index f2a51cf8d..905ee0385 100644 --- a/ruamoko/qwaq/ui/rect.r +++ b/ruamoko/qwaq/ui/rect.r @@ -1,4 +1,4 @@ -#include "ui/rect.h" +#include "ruamoko/qwaq/ui/rect.h" Rect clipRect (Rect clipRect, Rect rect) diff --git a/ruamoko/qwaq/ui/scrollbar.h b/ruamoko/qwaq/ui/scrollbar.h index 986646878..404dbfaf7 100644 --- a/ruamoko/qwaq/ui/scrollbar.h +++ b/ruamoko/qwaq/ui/scrollbar.h @@ -1,7 +1,7 @@ #ifndef __qwaq_ui_scrollbar_h #define __qwaq_ui_scrollbar_h -#include "ui/view.h" +#include "ruamoko/qwaq/ui/view.h" @class Button; @class DrawBuffer; diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index b8b005aa8..3d0eee6ce 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -1,7 +1,7 @@ -#include "ui/button.h" -#include "ui/group.h" -#include "ui/listener.h" -#include "ui/scrollbar.h" +#include "ruamoko/qwaq/ui/button.h" +#include "ruamoko/qwaq/ui/group.h" +#include "ruamoko/qwaq/ui/listener.h" +#include "ruamoko/qwaq/ui/scrollbar.h" @implementation ScrollBar diff --git a/ruamoko/qwaq/ui/tableview.h b/ruamoko/qwaq/ui/tableview.h index 9a6233333..52bca6880 100644 --- a/ruamoko/qwaq/ui/tableview.h +++ b/ruamoko/qwaq/ui/tableview.h @@ -1,7 +1,7 @@ #ifndef __qwaq_ui_tableview_h #define __qwaq_ui_tableview_h -#include "ui/view.h" +#include "ruamoko/qwaq/ui/view.h" @class DrawBuffer; @class TableView; diff --git a/ruamoko/qwaq/ui/tableview.r b/ruamoko/qwaq/ui/tableview.r index cb1a3f94c..940bf1793 100644 --- a/ruamoko/qwaq/ui/tableview.r +++ b/ruamoko/qwaq/ui/tableview.r @@ -1,6 +1,6 @@ #include -#include "ui/listener.h" -#include "ui/tableview.h" +#include "ruamoko/qwaq/ui/listener.h" +#include "ruamoko/qwaq/ui/tableview.h" @implementation TableViewColumn -initWithName:(string)name width:(int)width diff --git a/ruamoko/qwaq/ui/textcontext.h b/ruamoko/qwaq/ui/textcontext.h index 2369dfeee..21f21b5ae 100644 --- a/ruamoko/qwaq/ui/textcontext.h +++ b/ruamoko/qwaq/ui/textcontext.h @@ -3,9 +3,9 @@ #ifdef __QFCC__ #include -#include "ui/curses.h" -#include "ui/draw.h" -#include "ui/rect.h" +#include "ruamoko/qwaq/ui/curses.h" +#include "ruamoko/qwaq/ui/draw.h" +#include "ruamoko/qwaq/ui/rect.h" @class DrawBuffer; diff --git a/ruamoko/qwaq/ui/textcontext.r b/ruamoko/qwaq/ui/textcontext.r index bbe7a9476..9d05765d7 100644 --- a/ruamoko/qwaq/ui/textcontext.r +++ b/ruamoko/qwaq/ui/textcontext.r @@ -1,5 +1,5 @@ -#include "ui/draw.h" -#include "ui/textcontext.h" +#include "ruamoko/qwaq/ui/draw.h" +#include "ruamoko/qwaq/ui/textcontext.h" @implementation TextContext + (int) is_initialized = #0; diff --git a/ruamoko/qwaq/ui/titlebar.h b/ruamoko/qwaq/ui/titlebar.h index e71a41a25..a3290a20d 100644 --- a/ruamoko/qwaq/ui/titlebar.h +++ b/ruamoko/qwaq/ui/titlebar.h @@ -1,7 +1,7 @@ #ifndef __qwaq_ui_titlebar_h #define __qwaq_ui_titlebar_h -#include "ui/view.h" +#include "ruamoko/qwaq/ui/view.h" @interface TitleBar : View { diff --git a/ruamoko/qwaq/ui/titlebar.r b/ruamoko/qwaq/ui/titlebar.r index db1f717de..d6634c2ad 100644 --- a/ruamoko/qwaq/ui/titlebar.r +++ b/ruamoko/qwaq/ui/titlebar.r @@ -1,7 +1,7 @@ #include -#include "ui/group.h" -#include "ui/titlebar.h" +#include "ruamoko/qwaq/ui/group.h" +#include "ruamoko/qwaq/ui/titlebar.h" @implementation TitleBar diff --git a/ruamoko/qwaq/ui/view.h b/ruamoko/qwaq/ui/view.h index e0da51a28..15e8d22d3 100644 --- a/ruamoko/qwaq/ui/view.h +++ b/ruamoko/qwaq/ui/view.h @@ -4,9 +4,9 @@ #include #include -#include "ui/draw.h" -#include "ui/rect.h" -#include "ui/textcontext.h" +#include "ruamoko/qwaq/ui/draw.h" +#include "ruamoko/qwaq/ui/rect.h" +#include "ruamoko/qwaq/ui/textcontext.h" @class Group; @class ListenerGroup; diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index 579f804c1..014560ffd 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -1,8 +1,8 @@ -#include "ui/curses.h" -#include "ui/listener.h" -#include "ui/group.h" -#include "ui/scrollbar.h" -#include "ui/view.h" +#include "ruamoko/qwaq/ui/curses.h" +#include "ruamoko/qwaq/ui/listener.h" +#include "ruamoko/qwaq/ui/group.h" +#include "ruamoko/qwaq/ui/scrollbar.h" +#include "ruamoko/qwaq/ui/view.h" @implementation View diff --git a/ruamoko/qwaq/ui/window.h b/ruamoko/qwaq/ui/window.h index 67a0608e2..8464a68ee 100644 --- a/ruamoko/qwaq/ui/window.h +++ b/ruamoko/qwaq/ui/window.h @@ -7,9 +7,9 @@ @class Button; @class TitleBar; -#include "ui/draw.h" -#include "ui/rect.h" -#include "ui/view.h" +#include "ruamoko/qwaq/ui/draw.h" +#include "ruamoko/qwaq/ui/rect.h" +#include "ruamoko/qwaq/ui/view.h" @interface Window: View { diff --git a/ruamoko/qwaq/ui/window.r b/ruamoko/qwaq/ui/window.r index ea966d473..54dc574d6 100644 --- a/ruamoko/qwaq/ui/window.r +++ b/ruamoko/qwaq/ui/window.r @@ -1,14 +1,14 @@ #include #include -#include "ui/event.h" -#include "ui/button.h" -#include "ui/curses.h" -#include "ui/group.h" -#include "ui/listener.h" -#include "ui/titlebar.h" -#include "ui/window.h" -#include "ui/view.h" +#include "ruamoko/qwaq/ui/event.h" +#include "ruamoko/qwaq/ui/button.h" +#include "ruamoko/qwaq/ui/curses.h" +#include "ruamoko/qwaq/ui/group.h" +#include "ruamoko/qwaq/ui/listener.h" +#include "ruamoko/qwaq/ui/titlebar.h" +#include "ruamoko/qwaq/ui/window.h" +#include "ruamoko/qwaq/ui/view.h" @implementation Window diff --git a/ruamoko/scheme/Makefile.am b/ruamoko/scheme/Makefile.am deleted file mode 100644 index 9a5fb71a8..000000000 --- a/ruamoko/scheme/Makefile.am +++ /dev/null @@ -1,81 +0,0 @@ -AUTOMAKE_OPTIONS= foreign no-exeext - -QFCC_DEP=$(top_builddir)/tools/qfcc/source/qfcc$(EXEEXT) -QFCC=$(QFCC_DEP) - -GZ=@progs_gz@ -scheme_libs=libscheme.a -scheme_libexec=main.dat - -pkglibdir=$(datarootdir)/qfcc/lib -#FIXME where to put pkglibexec? -#pkglibexecdir=$(datarootdir)/qfcc/bin - -pkglib_LIBRARIES= $(scheme_libs) -EXTRA_LIBRARIES= $(scheme_libs) - -noinst_PROGRAMS= $(scheme_libexec) -EXTRA_PROGRAMS = $(scheme_libexec) - -QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide -QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -QCLINKFLAGS=--no-default-paths -L$(top_builddir)/ruamoko/lib -QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) -QLINK=$(QFCC) $(QCFLAGS) $(QCLINKFLAGS) - -MKDIR_P = @MKDIR_P@ -am__mv = mv -f - -PAK=$(top_builddir)/tools/pak/pak$(EXEEXT) -GZIP=if echo $@ | grep -q .gz; then gzip -f `basename $@ .gz`; if test -f `basename $@ .dat.gz`.sym; then gzip -f `basename $@ .dat.gz`.sym; fi; fi -# BSD make can't handle $(shell foo) directives, and GNU make can't handle |= -# so we have to bite the bullet and pass this to the shell every time. -RANLIB=touch - -SUFFIXES=.o .r -.r.o: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo - -r_depfiles_remade= - -libscheme_a_SOURCES=\ - SchemeObject.r Cons.r Number.r SchemeString.r Symbol.r Lexer.r Parser.r \ - Nil.r Procedure.r Primitive.r Lambda.r Scope.r Instruction.r builtins.r \ - Frame.r CompiledCode.r Compiler.r Continuation.r Machine.r Void.r \ - Error.r Boolean.r BaseContinuation.r -libscheme_a_obj=$(libscheme_a_SOURCES:.r=.o) -libscheme_a_dep=$(addprefix ./$(DEPDIR)/,$(libscheme_a_obj:.o=.Qo)) -libscheme_a_AR=$(PAK) -cf -include $(libscheme_a_dep) # am--include-marker -r_depfiles_remade += $(libscheme_a_dep) - -scheme_src=\ - main.r defs.r - -main_dat_SOURCES=$(scheme_src) -main_obj=$(scheme_src:.r=.o) -main_dep=$(addprefix ./$(DEPDIR)/,$(main_obj:.o=.Qo)) -main.dat: $(main_obj) $(QFCC_DEP) libscheme.a ../lib/libcsqc.a ../lib/libr.a - $(QLINK) -o main.dat $(main_obj) libscheme.a ../lib/libcsqc.a ../lib/libr.a -include $(main_dep) # am--include-marker -r_depfiles_remade += $(main_dep) - -main.sym: main.dat - -$(r_depfiles_remade): - $(MKDIR_P) $(@D) - echo '# dummy' >$@-t && $(am__mv) $@-t $@ - -am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) - -EXTRA_DIST = \ - BaseContinuation.h Boolean.h CompiledCode.h Compiler.h Cons.h \ - Continuation.h Error.h Frame.h Instruction.h Lambda.h Lexer.h \ - Machine.h Nil.h Number.h Parser.h Primitive.h Procedure.h \ - SchemeObject.h SchemeString.h Scope.h Symbol.h Void.h builtins.h \ - debug.h defs.h state.h \ - \ - main.r defs.r -CLEANFILES= *.dat *.sym *.gz *.qfo *.o diff --git a/ruamoko/scheme/Makemodule.am b/ruamoko/scheme/Makemodule.am new file mode 100644 index 000000000..b3fcfb5d9 --- /dev/null +++ b/ruamoko/scheme/Makemodule.am @@ -0,0 +1,88 @@ +ruamoko_scheme_libs=ruamoko/scheme/libscheme.a +ruamoko_scheme_libexec=ruamoko/scheme/main.dat$(EXEEXT) + +ruamoko_lib_LIBRARIES += $(ruamoko_scheme_libs) +EXTRA_LIBRARIES += $(ruamoko_scheme_libs) + +noinst_PROGRAMS += $(ruamoko_scheme_libexec) +EXTRA_PROGRAMS += $(ruamoko_scheme_libexec) + +ruamoko_scheme_libscheme_a_SOURCES=\ + ruamoko/scheme/SchemeObject.r \ + ruamoko/scheme/Cons.r \ + ruamoko/scheme/Number.r \ + ruamoko/scheme/SchemeString.r \ + ruamoko/scheme/Symbol.r \ + ruamoko/scheme/Lexer.r \ + ruamoko/scheme/Parser.r \ + ruamoko/scheme/Nil.r \ + ruamoko/scheme/Procedure.r \ + ruamoko/scheme/Primitive.r \ + ruamoko/scheme/Lambda.r \ + ruamoko/scheme/Scope.r \ + ruamoko/scheme/Instruction.r \ + ruamoko/scheme/builtins.r \ + ruamoko/scheme/Frame.r \ + ruamoko/scheme/CompiledCode.r \ + ruamoko/scheme/Compiler.r \ + ruamoko/scheme/Continuation.r \ + ruamoko/scheme/Machine.r \ + ruamoko/scheme/Void.r \ + ruamoko/scheme/Error.r \ + ruamoko/scheme/Boolean.r \ + ruamoko/scheme/BaseContinuation.r +ruamoko_scheme_libscheme_a_dep=$(call qcautodep,$(ruamoko_scheme_libscheme_a_SOURCES)) +ruamoko_scheme_libscheme_a_AR=$(PAK) -cf +EXTRA_ruamoko_scheme_libscheme_a_DEPENDENCIES=pak +include $(ruamoko_scheme_libscheme_a_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_scheme_libscheme_a_dep) + +ruamoko_scheme_src=\ + ruamoko/scheme/main.r \ + ruamoko/scheme/defs.r + +ruamoko_scheme_main_dat_SOURCES=$(ruamoko_scheme_src) +ruamoko_scheme_main_obj=$(ruamoko_scheme_main_dat_SOURCES:.r=.o) +ruamoko_scheme_main_dep=$(call qcautodep,$(ruamoko_scheme_main_dat_SOURCES)) +ruamoko/scheme/main.dat$(EXEEXT): $(ruamoko_scheme_main_obj) $(QFCC_DEP) ruamoko/scheme/libscheme.a ruamoko/lib/libcsqc.a ruamoko/lib/libr.a + $(QLINK) -o $@ $(ruamoko_scheme_main_obj) -Lruamoko/scheme -lscheme -lcsqc -lr +include $(ruamoko_scheme_main_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_scheme_main_dep) + +ruamoko/scheme/main.sym: ruamoko/scheme/main.dat$(EXEEXT) + +EXTRA_DIST += \ + ruamoko/scheme/BaseContinuation.h \ + ruamoko/scheme/Boolean.h \ + ruamoko/scheme/CompiledCode.h \ + ruamoko/scheme/Compiler.h \ + ruamoko/scheme/Cons.h \ + ruamoko/scheme/Continuation.h \ + ruamoko/scheme/Error.h \ + ruamoko/scheme/Frame.h \ + ruamoko/scheme/Instruction.h \ + ruamoko/scheme/Lambda.h \ + ruamoko/scheme/Lexer.h \ + ruamoko/scheme/Machine.h \ + ruamoko/scheme/Nil.h \ + ruamoko/scheme/Number.h \ + ruamoko/scheme/Parser.h \ + ruamoko/scheme/Primitive.h \ + ruamoko/scheme/Procedure.h \ + ruamoko/scheme/SchemeObject.h \ + ruamoko/scheme/SchemeString.h \ + ruamoko/scheme/Scope.h \ + ruamoko/scheme/Symbol.h \ + ruamoko/scheme/Void.h \ + ruamoko/scheme/builtins.h \ + ruamoko/scheme/debug.h \ + ruamoko/scheme/defs.h \ + ruamoko/scheme/state.h \ + ruamoko/scheme/main.r \ + ruamoko/scheme/defs.r +CLEANFILES += \ + ruamoko/scheme/*.dat \ + ruamoko/scheme/*.sym +DISTCLEANFILES += \ + $(ruamoko_scheme_libscheme_a_dep) \ + $(ruamoko_scheme_main_dep) diff --git a/tools/Makefile.am b/tools/Makefile.am deleted file mode 100644 index 768efdccb..000000000 --- a/tools/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -SUBDIRS=@tools_dirs@ -DIST_SUBDIRS=bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav -EXTRA_DIST= \ - io_mesh_qfmdl/export_mdl.py io_mesh_qfmdl/import_mdl.py \ - io_mesh_qfmdl/__init__.py io_mesh_qfmdl/mdl.py io_mesh_qfmdl/qfplist.py \ - io_mesh_qfmdl/quakepal.py diff --git a/tools/Makemodule.am b/tools/Makemodule.am new file mode 100644 index 000000000..7a3805526 --- /dev/null +++ b/tools/Makemodule.am @@ -0,0 +1,20 @@ +include tools/bsp2img/Makemodule.am +include tools/carne/Makemodule.am +include tools/pak/Makemodule.am +include tools/qfbsp/Makemodule.am +include tools/qfcc/Makemodule.am +include tools/qflight/Makemodule.am +include tools/qflmp/Makemodule.am +include tools/qfmodelgen/Makemodule.am +include tools/qfspritegen/Makemodule.am +include tools/qfvis/Makemodule.am +include tools/wad/Makemodule.am +include tools/wav/Makemodule.am + +EXTRA_DIST += \ + tools/io_mesh_qfmdl/export_mdl.py \ + tools/io_mesh_qfmdl/import_mdl.py \ + tools/io_mesh_qfmdl/__init__.py \ + tools/io_mesh_qfmdl/mdl.py \ + tools/io_mesh_qfmdl/qfplist.py \ + tools/io_mesh_qfmdl/quakepal.py diff --git a/tools/bsp2img/Makefile.am b/tools/bsp2img/Makemodule.am similarity index 60% rename from tools/bsp2img/Makefile.am rename to tools/bsp2img/Makemodule.am index ceaeca266..bf58c14aa 100644 --- a/tools/bsp2img/Makefile.am +++ b/tools/bsp2img/Makemodule.am @@ -2,10 +2,8 @@ BSP2IMG_LIBS=@BSP2IMG_LIBS@ BSP2IMG_DEPS=@BSP2IMG_DEPS@ BSP2IMG_INCS=@BSP2IMG_INCS@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(BSP2IMG_INCS) +bin_PROGRAMS += bsp2img -bin_PROGRAMS=bsp2img - -bsp2img_SOURCES= bsp2img.c +bsp2img_SOURCES= tools/bsp2img/bsp2img.c bsp2img_LDADD= $(BSP2IMG_LIBS) bsp2img_DEPENDENCIES= $(BSP2IMG_DEPS) diff --git a/tools/carne/Makefile.am b/tools/carne/Makefile.am deleted file mode 100644 index bec57857d..000000000 --- a/tools/carne/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -CARNE_LIBS=@CARNE_LIBS@ -CARNE_DEPS=@CARNE_DEPS@ -PAK_INCS=@CARNE_INCS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(CARNE_INCS) - -noinst_PROGRAMS= carne - -carne_SOURCES= main.c -carne_LDADD= $(CARNE_LIBS) -carne_DEPENDENCIES= $(CARNE_DEPS) diff --git a/tools/carne/Makemodule.am b/tools/carne/Makemodule.am new file mode 100644 index 000000000..24f5f056b --- /dev/null +++ b/tools/carne/Makemodule.am @@ -0,0 +1,8 @@ +CARNE_LIBS=@CARNE_LIBS@ +CARNE_DEPS=@CARNE_DEPS@ + +noinst_PROGRAMS += carne + +carne_SOURCES= tools/carne/main.c +carne_LDADD= $(CARNE_LIBS) +carne_DEPENDENCIES= $(CARNE_DEPS) diff --git a/tools/pak/Makefile.am b/tools/pak/Makefile.am deleted file mode 100644 index 5461c399e..000000000 --- a/tools/pak/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -PAK_LIBS=@PAK_LIBS@ -PAK_DEPS=@PAK_DEPS@ -PAK_INCS=@PAK_INCS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(PAK_INCS) - -bin_PROGRAMS= pak -bin_SCRIPTS= zpak - -mans= pak.1 zpak.1 -man_MANS= $(mans) - -pak_SOURCES= pak.c -pak_LDADD= $(PAK_LIBS) -pak_DEPENDENCIES= $(PAK_DEPS) - -EXTRA_DIST=pak.h zpak $(mans) diff --git a/tools/pak/Makemodule.am b/tools/pak/Makemodule.am new file mode 100644 index 000000000..d7a247e88 --- /dev/null +++ b/tools/pak/Makemodule.am @@ -0,0 +1,14 @@ +PAK_LIBS=@PAK_LIBS@ +PAK_DEPS=@PAK_DEPS@ +PAK_INCS=@PAK_INCS@ + +bin_PROGRAMS += pak +bin_SCRIPTS += tools/pak/zpak + +man_MANS += tools/pak/pak.1 tools/pak/zpak.1 + +pak_SOURCES= tools/pak/pak.c +pak_LDADD= $(PAK_LIBS) +pak_DEPENDENCIES= $(PAK_DEPS) + +EXTRA_DIST += tools/pak/pak.h tools/pak/zpak $(man_MANS) diff --git a/tools/qfbsp/Makefile.am b/tools/qfbsp/Makefile.am deleted file mode 100644 index f2bd807e0..000000000 --- a/tools/qfbsp/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= include source diff --git a/tools/qfbsp/Makemodule.am b/tools/qfbsp/Makemodule.am new file mode 100644 index 000000000..c73468397 --- /dev/null +++ b/tools/qfbsp/Makemodule.am @@ -0,0 +1,2 @@ +include tools/qfbsp/include/Makemodule.am +include tools/qfbsp/source/Makemodule.am diff --git a/tools/qfbsp/include/Makefile.am b/tools/qfbsp/include/Makefile.am deleted file mode 100644 index d4ab30d4e..000000000 --- a/tools/qfbsp/include/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST= brush.h bsp5.h csg4.h draw.h map.h merge.h options.h outside.h \ - portals.h readbsp.h region.h solidbsp.h surfaces.h tjunc.h \ - writebsp.h diff --git a/tools/qfbsp/include/Makemodule.am b/tools/qfbsp/include/Makemodule.am new file mode 100644 index 000000000..0cf8e31dd --- /dev/null +++ b/tools/qfbsp/include/Makemodule.am @@ -0,0 +1,16 @@ +EXTRA_DIST += \ + tools/qfbsp/include/brush.h \ + tools/qfbsp/include/bsp5.h \ + tools/qfbsp/include/csg4.h \ + tools/qfbsp/include/draw.h \ + tools/qfbsp/include/map.h \ + tools/qfbsp/include/merge.h \ + tools/qfbsp/include/options.h \ + tools/qfbsp/include/outside.h \ + tools/qfbsp/include/portals.h \ + tools/qfbsp/include/readbsp.h \ + tools/qfbsp/include/region.h \ + tools/qfbsp/include/solidbsp.h \ + tools/qfbsp/include/surfaces.h \ + tools/qfbsp/include/tjunc.h \ + tools/qfbsp/include/writebsp.h diff --git a/tools/qfbsp/source/Makefile.am b/tools/qfbsp/source/Makefile.am deleted file mode 100644 index 8fd7f660b..000000000 --- a/tools/qfbsp/source/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -QFBSP_LIBS=@QFBSP_LIBS@ -QFBSP_DEPS=@QFBSP_DEPS@ -QFBSP_INCS=@QFBSP_INCS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(QFBSP_INCS) - -bin_PROGRAMS= qfbsp - -qfbsp_SOURCES= \ - brush.c csg4.c map.c merge.c nodraw.c options.c outside.c portals.c \ - qfbsp.c readbsp.c region.c solidbsp.c surfaces.c tjunc.c writebsp.c - -qfbsp_LDADD= $(QFBSP_LIBS) -qfbsp_DEPENDENCIES= $(QFBSP_DEPS) diff --git a/tools/qfbsp/source/Makemodule.am b/tools/qfbsp/source/Makemodule.am new file mode 100644 index 000000000..2e3e9a524 --- /dev/null +++ b/tools/qfbsp/source/Makemodule.am @@ -0,0 +1,25 @@ +QFBSP_LIBS=@QFBSP_LIBS@ +QFBSP_DEPS=@QFBSP_DEPS@ +QFBSP_INCS=@QFBSP_INCS@ + +bin_PROGRAMS += qfbsp + +qfbsp_SOURCES= \ + tools/qfbsp/source/brush.c \ + tools/qfbsp/source/csg4.c \ + tools/qfbsp/source/map.c \ + tools/qfbsp/source/merge.c \ + tools/qfbsp/source/nodraw.c \ + tools/qfbsp/source/options.c \ + tools/qfbsp/source/outside.c \ + tools/qfbsp/source/portals.c \ + tools/qfbsp/source/qfbsp.c \ + tools/qfbsp/source/readbsp.c \ + tools/qfbsp/source/region.c \ + tools/qfbsp/source/solidbsp.c \ + tools/qfbsp/source/surfaces.c \ + tools/qfbsp/source/tjunc.c \ + tools/qfbsp/source/writebsp.c + +qfbsp_LDADD= $(QFBSP_LIBS) +qfbsp_DEPENDENCIES= $(QFBSP_DEPS) diff --git a/tools/qfbsp/source/brush.c b/tools/qfbsp/source/brush.c index 940fddfb4..97ddbfd4d 100644 --- a/tools/qfbsp/source/brush.c +++ b/tools/qfbsp/source/brush.c @@ -32,11 +32,11 @@ #include "compat.h" -#include "brush.h" -#include "bsp5.h" -#include "draw.h" -#include "options.h" -#include "surfaces.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/draw.h" +#include "tools/qfbsp/include/options.h" +#include "tools/qfbsp/include/surfaces.h" /** \addtogroup qfbsp_brush */ diff --git a/tools/qfbsp/source/csg4.c b/tools/qfbsp/source/csg4.c index 444627334..76d11e2d1 100644 --- a/tools/qfbsp/source/csg4.c +++ b/tools/qfbsp/source/csg4.c @@ -27,13 +27,13 @@ #include "QF/sys.h" -#include "brush.h" -#include "bsp5.h" -#include "csg4.h" -#include "draw.h" -#include "merge.h" -#include "solidbsp.h" -#include "surfaces.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/csg4.h" +#include "tools/qfbsp/include/draw.h" +#include "tools/qfbsp/include/merge.h" +#include "tools/qfbsp/include/solidbsp.h" +#include "tools/qfbsp/include/surfaces.h" /** \addtogroup qfbsp_csg4 */ diff --git a/tools/qfbsp/source/map.c b/tools/qfbsp/source/map.c index c258b73df..d8bb6c893 100644 --- a/tools/qfbsp/source/map.c +++ b/tools/qfbsp/source/map.c @@ -40,7 +40,7 @@ #include "compat.h" -#include "map.h" +#include "tools/qfbsp/include/map.h" /** \addtogroup qfbsp_map */ diff --git a/tools/qfbsp/source/merge.c b/tools/qfbsp/source/merge.c index 5692a6d83..480af3896 100644 --- a/tools/qfbsp/source/merge.c +++ b/tools/qfbsp/source/merge.c @@ -23,12 +23,12 @@ #include "QF/sys.h" -#include "brush.h" -#include "bsp5.h" -#include "csg4.h" -#include "draw.h" -#include "merge.h" -#include "surfaces.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/csg4.h" +#include "tools/qfbsp/include/draw.h" +#include "tools/qfbsp/include/merge.h" +#include "tools/qfbsp/include/surfaces.h" /** \addtogroup qfbsp_merge */ diff --git a/tools/qfbsp/source/nodraw.c b/tools/qfbsp/source/nodraw.c index c333313c5..b7db6dc94 100644 --- a/tools/qfbsp/source/nodraw.c +++ b/tools/qfbsp/source/nodraw.c @@ -21,7 +21,7 @@ # include "config.h" #endif -#include "draw.h" +#include "tools/qfbsp/include/draw.h" /** \addtogroup qfbsp_draw */ diff --git a/tools/qfbsp/source/options.c b/tools/qfbsp/source/options.c index 214065f9b..70b022b5d 100644 --- a/tools/qfbsp/source/options.c +++ b/tools/qfbsp/source/options.c @@ -40,7 +40,7 @@ #include "QF/quakefs.h" -#include "options.h" +#include "tools/qfbsp/include/options.h" /** \addtogroup qfbsp_options */ diff --git a/tools/qfbsp/source/outside.c b/tools/qfbsp/source/outside.c index 3002f468b..15da18dba 100644 --- a/tools/qfbsp/source/outside.c +++ b/tools/qfbsp/source/outside.c @@ -22,12 +22,12 @@ #include "QF/sys.h" -#include "brush.h" -#include "bsp5.h" -#include "draw.h" -#include "options.h" -#include "portals.h" -#include "outside.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/draw.h" +#include "tools/qfbsp/include/options.h" +#include "tools/qfbsp/include/portals.h" +#include "tools/qfbsp/include/outside.h" /** \addtogroup qfbsp_outside */ diff --git a/tools/qfbsp/source/portals.c b/tools/qfbsp/source/portals.c index 4871aefbe..cbc128f1e 100644 --- a/tools/qfbsp/source/portals.c +++ b/tools/qfbsp/source/portals.c @@ -28,11 +28,11 @@ #include "QF/sys.h" -#include "brush.h" -#include "bsp5.h" -#include "draw.h" -#include "options.h" -#include "portals.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/draw.h" +#include "tools/qfbsp/include/options.h" +#include "tools/qfbsp/include/portals.h" /** \addtogroup qfbsp_portals */ diff --git a/tools/qfbsp/source/qfbsp.c b/tools/qfbsp/source/qfbsp.c index e3948acb8..abbc81029 100644 --- a/tools/qfbsp/source/qfbsp.c +++ b/tools/qfbsp/source/qfbsp.c @@ -43,18 +43,18 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "csg4.h" -#include "brush.h" -#include "bsp5.h" -#include "merge.h" -#include "options.h" -#include "outside.h" -#include "portals.h" -#include "readbsp.h" -#include "solidbsp.h" -#include "surfaces.h" -#include "writebsp.h" -#include "tjunc.h" +#include "tools/qfbsp/include/csg4.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/merge.h" +#include "tools/qfbsp/include/options.h" +#include "tools/qfbsp/include/outside.h" +#include "tools/qfbsp/include/portals.h" +#include "tools/qfbsp/include/readbsp.h" +#include "tools/qfbsp/include/solidbsp.h" +#include "tools/qfbsp/include/surfaces.h" +#include "tools/qfbsp/include/writebsp.h" +#include "tools/qfbsp/include/tjunc.h" /** \addtogroup qfbsp */ diff --git a/tools/qfbsp/source/readbsp.c b/tools/qfbsp/source/readbsp.c index 4168a2ae5..caf69255b 100644 --- a/tools/qfbsp/source/readbsp.c +++ b/tools/qfbsp/source/readbsp.c @@ -48,11 +48,11 @@ #include "QF/va.h" #include "QF/wad.h" -#include "brush.h" -#include "bsp5.h" -#include "options.h" -#include "portals.h" -#include "readbsp.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/options.h" +#include "tools/qfbsp/include/portals.h" +#include "tools/qfbsp/include/readbsp.h" /** \addtogroup qfbsp_readbsp */ diff --git a/tools/qfbsp/source/region.c b/tools/qfbsp/source/region.c index b7c875a22..03dfd2efd 100644 --- a/tools/qfbsp/source/region.c +++ b/tools/qfbsp/source/region.c @@ -29,9 +29,9 @@ #include "compat.h" -#include "bsp5.h" -#include "region.h" -#include "surfaces.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/region.h" +#include "tools/qfbsp/include/surfaces.h" /** \addtogroup qfbsp_region */ diff --git a/tools/qfbsp/source/solidbsp.c b/tools/qfbsp/source/solidbsp.c index d4c9e0f7d..c49422c20 100644 --- a/tools/qfbsp/source/solidbsp.c +++ b/tools/qfbsp/source/solidbsp.c @@ -28,12 +28,12 @@ #include "QF/sys.h" -#include "brush.h" -#include "csg4.h" -#include "bsp5.h" -#include "draw.h" -#include "solidbsp.h" -#include "surfaces.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/csg4.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/draw.h" +#include "tools/qfbsp/include/solidbsp.h" +#include "tools/qfbsp/include/surfaces.h" /** \addtogroup qfbsp_solidbsp */ diff --git a/tools/qfbsp/source/surfaces.c b/tools/qfbsp/source/surfaces.c index 9c467c0e1..2c9c08897 100644 --- a/tools/qfbsp/source/surfaces.c +++ b/tools/qfbsp/source/surfaces.c @@ -28,11 +28,11 @@ #include "QF/sys.h" -#include "bsp5.h" -#include "csg4.h" -#include "options.h" -#include "region.h" -#include "surfaces.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/csg4.h" +#include "tools/qfbsp/include/options.h" +#include "tools/qfbsp/include/region.h" +#include "tools/qfbsp/include/surfaces.h" /** \addtogroup qfbsp_surface */ diff --git a/tools/qfbsp/source/tjunc.c b/tools/qfbsp/source/tjunc.c index 50882df87..64588837d 100644 --- a/tools/qfbsp/source/tjunc.c +++ b/tools/qfbsp/source/tjunc.c @@ -29,10 +29,10 @@ #include "compat.h" -#include "brush.h" -#include "bsp5.h" -#include "options.h" -#include "tjunc.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/options.h" +#include "tools/qfbsp/include/tjunc.h" /** \addtogroup qfbsp_tjunc */ diff --git a/tools/qfbsp/source/writebsp.c b/tools/qfbsp/source/writebsp.c index fa95b4d57..94f679313 100644 --- a/tools/qfbsp/source/writebsp.c +++ b/tools/qfbsp/source/writebsp.c @@ -37,10 +37,10 @@ #include "QF/va.h" #include "QF/wad.h" -#include "brush.h" -#include "bsp5.h" -#include "options.h" -#include "writebsp.h" +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/options.h" +#include "tools/qfbsp/include/writebsp.h" /** \addtogroup qfbsp_writebsp */ diff --git a/tools/qfcc/Makefile.am b/tools/qfcc/Makefile.am deleted file mode 100644 index b9050ce13..000000000 --- a/tools/qfcc/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ -# Makefile.am -# -# Automake-using build system for QuakeForge -# -# Copyright (C) 2000 Jeff Teunissen -# -# This Makefile 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 2 -# 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, write to: -# -# Free Software Foundation, Inc. -# 59 Temple Place - Suite 330 -# Boston, MA 02111-1307, USA -# -# $Id$ -# -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= include source doc test - -dist-zip: distdir - -chmod -R a+r $(distdir) - ZIP="-r9q" zip $(distdir).zip $(NOCONV_DIST) - ZIP="-r9ql" zip $(distdir).zip $(distdir) -x $(NOCONV_DIST) - -rm -rf $(distdir) - -dist-bz2: distdir - -chmod -R a+r $(distdir) - BZIP2="-9" $(TAR) Ichof $(distdir).tar.bz2 $(distdir) - -rm -rf $(distdir) - -dist-all-local: distdir - -chmod -R a+r $(distdir) - GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) - BZIP2="-9" $(TAR) Ichof $(distdir).tar.bz2 $(distdir) - ZIP="-r9q" zip $(distdir).zip $(NOCONV_DIST) - ZIP="-r9ql" zip $(distdir).zip $(distdir) -x $(NOCONV_DIST) - -rm -rf $(distdir) diff --git a/tools/qfcc/Makemodule.am b/tools/qfcc/Makemodule.am new file mode 100644 index 000000000..e4159fbf3 --- /dev/null +++ b/tools/qfcc/Makemodule.am @@ -0,0 +1,4 @@ +include tools/qfcc/include/Makemodule.am +include tools/qfcc/source/Makemodule.am +include tools/qfcc/doc/Makemodule.am +include tools/qfcc/test/Makemodule.am diff --git a/tools/qfcc/bootstrap b/tools/qfcc/bootstrap deleted file mode 100755 index 071d87a77..000000000 --- a/tools/qfcc/bootstrap +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -cd `dirname $0` -aclocal && autoheader && automake --add-missing && autoconf diff --git a/tools/qfcc/configure.in b/tools/qfcc/configure.in deleted file mode 100644 index 3c6383d5a..000000000 --- a/tools/qfcc/configure.in +++ /dev/null @@ -1,144 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. - -AC_PREREQ(2.13) -AC_INIT(source/qfcc.c) -AC_REVISION($Revision$) dnl -AM_CONFIG_HEADER(include/config.h) -AC_CANONICAL_SYSTEM - -dnl Every other copy of the package version number gets its value from here -AM_INIT_AUTOMAKE(qfcc, 0.1.0) - -AC_SUBST(VERSION) - -ISODATE=`date +%Y-%m-%d` -AC_SUBST(ISODATE) - -AC_LANG_C - -dnl Checks for programs. -AC_PROG_INSTALL -AC_PROG_CC -AC_PROG_CPP -AC_PROG_YACC -AM_PROG_LEX - -AC_ARG_WITH(cpp, -[ --with-cpp=CPP how qfcc should invoke cpp], - cpp_name="$withval", cpp_name=auto -) -if test "x$cpp_name" != xauto; then - CPP_NAME="$cpp_name" -else - CPP_NAME="cpp %u %d %s -o %o %i" - case "$target_os" in - *bsd*) - touch conftest.c - CPP_NAME="`(f=\`$CC -v -E -Dfoo conftest.c -o conftest.i 2>&1 | grep -e -Dfoo\`; set $f; echo "$1")` %d %i %o" - rm -f conftest.[ci] - ;; - esac -fi -AC_DEFINE_UNQUOTED(CPP_NAME, "$CPP_NAME", [Define this to the command line for the C preprocessor]) - -dnl We want warnings, lots of warnings... -if test "x$GCC" = xyes; then - CFLAGS="$CFLAGS -Wall -Werror" - # CFLAGS="$CFLAGS -Wall -pedantic" -fi - -dnl Checks for libraries. -AC_CHECK_LIB(z, gztell,, -) - -dnl Checks for header files. -AC_HEADER_STDC -AC_CHECK_HEADERS(process.h string.h strings.h fcntl.h sys/stat.h sys/types.h sys/wait.h unistd.h) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_ARG_ENABLE(profile, - [ --enable-profile compile with profiling (for development)], - profile=$enable_profile -) -if test "x$profile" = xyes; then - BUILD_TYPE="$BUILD_TYPE Profile" - if test "x$GCC" = xyes; then - CFLAGS="`echo $CFLAGS | sed -e 's/-fomit-frame-pointer//g'` -pg" - LDFLAGS="$LDFLAGS -pg" - else - CFLAGS="$CFLAGS -p" - fi -fi - -AC_DEFINE_UNQUOTED(PATH_SEPARATOR, '/', - [Define this to your operating system's path separator character]) - -dnl Checks for library functions. - -AC_CHECK_FUNCS(snprintf _snprintf vsnprintf _vsnprintf) - -AC_MSG_CHECKING(for timeGetTime in -lwinmm) -save_LIBS="$LIBS" -LIBS="$LIBS -lwinmm" -AC_TRY_COMPILE( - [#include ], - [timeGetTime ();], - AC_MSG_RESULT(yes), - LIBS="$save_LIBS" - AC_MSG_RESULT(no) -) - -AC_ARG_WITH(qf, -[ --with-qf=DIR location of QF libs and headers (prefix)], - if test "x$withval" != xyes ; then - LDFLAGS="$LDFLAGS -L${withval}/lib" - CFLAGS="$CFLAGS -I${withval}/include" - fi - , - HAVE_QF=auto -) -AC_MSG_CHECKING(for QF/qtypes.h) -AC_TRY_COMPILE( - [#include "QF/qtypes.h"], - [qboolean foo = false; - foo = true;], - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - HAVE_QF=no -) -if test "x$HAVE_QF" != xno; then - AC_CHECK_LIB(QFutil, Hash_NewTable, - :, HAVE_QF=no, - [] - ) -fi -if test "x$HAVE_QF" != xno; then - AC_CHECK_LIB(QFgamecode, PR_Opcode, - :, HAVE_QF=no, - [-lQFutil] - ) -fi - -QFCC_LIBS="-lQFgamecode -lQFutil" -QFCC_DEPS="" -QFCC_INCS="" - -if test "x$HAVE_QF" = xno; then - echo '***' - echo '*** You seem to not have the QuakeForge libs & headers installed' - echo '***' - exit 1 -fi - -AC_SUBST(QFCC_LIBS) -AC_SUBST(QFCC_DEPS) -AC_SUBST(QFCC_INCS) - -AC_OUTPUT( - doc/Makefile - doc/man/Makefile - include/Makefile - source/Makefile - Makefile - qfcc.lsm -) diff --git a/tools/qfcc/doc/Makefile.am b/tools/qfcc/doc/Makefile.am deleted file mode 100644 index 8d0026abb..000000000 --- a/tools/qfcc/doc/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= man - -EXTRA_DIST= expressions.txt \ - dot/vector-alias.dot diff --git a/tools/qfcc/doc/Makemodule.am b/tools/qfcc/doc/Makemodule.am new file mode 100644 index 000000000..121e06e82 --- /dev/null +++ b/tools/qfcc/doc/Makemodule.am @@ -0,0 +1,5 @@ +man_MANS += tools/qfcc/doc/man/qfcc.1 + +EXTRA_DIST += \ + tools/qfcc/doc/expressions.txt \ + tools/qfcc/doc/dot/vector-alias.dot diff --git a/tools/qfcc/doc/man/Makefile.am b/tools/qfcc/doc/man/Makefile.am deleted file mode 100644 index cca3e62a5..000000000 --- a/tools/qfcc/doc/man/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -man_MANS=qfcc.1 -EXTRA_DIST=qfcc.1 diff --git a/tools/qfcc/include/Makefile.am b/tools/qfcc/include/Makefile.am deleted file mode 100644 index 140cae90a..000000000 --- a/tools/qfcc/include/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST= class.h codespace.h cpp.h dags.h debug.h def.h defspace.h \ - diagnostic.h dot.h emit.h expr.h flow.h function.h grab.h idstuff.h \ - linker.h method.h obj_file.h obj_type.h opcodes.h options.h pragma.h \ - qfcc.h qfprogs.h reloc.h shared.h statements.h strpool.h struct.h \ - switch.h symtab.h type.h value.h diff --git a/tools/qfcc/include/Makemodule.am b/tools/qfcc/include/Makemodule.am new file mode 100644 index 000000000..689ebad68 --- /dev/null +++ b/tools/qfcc/include/Makemodule.am @@ -0,0 +1,34 @@ +EXTRA_DIST += \ + tools/qfcc/include/class.h \ + tools/qfcc/include/codespace.h \ + tools/qfcc/include/cpp.h \ + tools/qfcc/include/dags.h \ + tools/qfcc/include/debug.h \ + tools/qfcc/include/def.h \ + tools/qfcc/include/defspace.h \ + tools/qfcc/include/diagnostic.h \ + tools/qfcc/include/dot.h \ + tools/qfcc/include/emit.h \ + tools/qfcc/include/expr.h \ + tools/qfcc/include/flow.h \ + tools/qfcc/include/function.h \ + tools/qfcc/include/grab.h \ + tools/qfcc/include/idstuff.h \ + tools/qfcc/include/linker.h \ + tools/qfcc/include/method.h \ + tools/qfcc/include/obj_file.h \ + tools/qfcc/include/obj_type.h \ + tools/qfcc/include/opcodes.h \ + tools/qfcc/include/options.h \ + tools/qfcc/include/pragma.h \ + tools/qfcc/include/qfcc.h \ + tools/qfcc/include/qfprogs.h \ + tools/qfcc/include/reloc.h \ + tools/qfcc/include/shared.h \ + tools/qfcc/include/statements.h \ + tools/qfcc/include/strpool.h \ + tools/qfcc/include/struct.h \ + tools/qfcc/include/switch.h \ + tools/qfcc/include/symtab.h \ + tools/qfcc/include/type.h \ + tools/qfcc/include/value.h diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am deleted file mode 100644 index b69dd6323..000000000 --- a/tools/qfcc/source/Makefile.am +++ /dev/null @@ -1,76 +0,0 @@ -## Process this file with automake to produce Makefile.in -# -# Makefile.am -# -# Automake-using build system for QuakeForge -# -# Copyright (C) 2000 Jeff Teunissen -# -# This Makefile 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 2 -# 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, write to: -# -# Free Software Foundation, Inc. -# 59 Temple Place - Suite 330 -# Boston, MA 02111-1307, USA -# -# $Id$ -# -AUTOMAKE_OPTIONS= foreign - -QFCC_LIBS=@QFCC_LIBS@ -QFCC_DEPS=@QFCC_DEPS@ -QFCC_INCS=@QFCC_INCS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(QFCC_INCS) -YFLAGS = -v -d -Wno-yacc -Werror - -bin_PROGRAMS= qfcc qfprogs -bin_SCRIPTS= qfpreqcc - -common_src=\ - class.c codespace.c constfold.c cpp.c dags.c debug.c def.c defspace.c \ - diagnostic.c \ - dot.c dot_dag.c dot_expr.c dot_flow.c dot_sblock.c dot_type.c \ - emit.c \ - expr.c expr_assign.c expr_binary.c expr_bool.c expr_compound.c expr_obj.c \ - flow.c function.c grab.c \ - idstuff.c \ - linker.c method.c \ - obj_file.c \ - obj_type.c opcodes.c options.c pragma.c qfcc.c reloc.c shared.c \ - statements.c strpool.c struct.c switch.c symtab.c type.c value.c - -qfcc_SOURCES= qc-lex.l qc-parse.y qp-lex.l qp-parse.y $(common_src) -qfcc_LDADD= $(QFCC_LIBS) -qfcc_DEPENDENCIES= $(QFCC_DEPS) - -qfprogs_SOURCES= \ - disassemble.c dump_globals.c dump_lines.c dump_modules.c dump_strings.c \ - obj_file.c qfprogs.c strpool.c stub.c type.c -qfprogs_LDADD= $(QFCC_LIBS) -qfprogs_DEPENDENCIES= $(QFCC_DEPS) - -BUILT_SOURCES=qc-parse.c qc-parse.h qc-lex.c qp-parse.c qp-parse.h qp-lex.c - -qc-parse.c: qc-parse.y - $(YACC) $(YFLAGS) -Dapi.prefix={qc_yy} $< -o $@ -qc-lex.c: qc-lex.l qc-parse.h - $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqc_yy -o$@ $< -qp-parse.c: qp-parse.y - $(YACC) $(YFLAGS) -Dapi.prefix={qp_yy} $< -o $@ -qp-lex.c: qp-lex.l qp-parse.h - $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqp_yy -o$@ $< - -EXTRA_DIST=qc-lex.c qc-parse.c qc-parse.h qfpreqcc \ - qp-parse.c qp-parse.h qp-lex.c diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am new file mode 100644 index 000000000..d8db07b5c --- /dev/null +++ b/tools/qfcc/source/Makemodule.am @@ -0,0 +1,92 @@ +QFCC_LIBS=@QFCC_LIBS@ +QFCC_DEPS=@QFCC_DEPS@ +QFCC_INCS=@QFCC_INCS@ + +bin_PROGRAMS += qfcc qfprogs +bin_SCRIPTS += tools/qfcc/source/qfpreqcc + +qfcc_SOURCES = \ + tools/qfcc/source/class.c \ + tools/qfcc/source/codespace.c \ + tools/qfcc/source/constfold.c \ + tools/qfcc/source/cpp.c \ + tools/qfcc/source/dags.c \ + tools/qfcc/source/debug.c \ + tools/qfcc/source/def.c \ + tools/qfcc/source/defspace.c \ + tools/qfcc/source/diagnostic.c \ + tools/qfcc/source/dot.c \ + tools/qfcc/source/dot_dag.c \ + tools/qfcc/source/dot_expr.c \ + tools/qfcc/source/dot_flow.c \ + tools/qfcc/source/dot_sblock.c \ + tools/qfcc/source/dot_type.c \ + tools/qfcc/source/emit.c \ + tools/qfcc/source/expr.c \ + tools/qfcc/source/expr_assign.c \ + tools/qfcc/source/expr_binary.c \ + tools/qfcc/source/expr_bool.c \ + tools/qfcc/source/expr_compound.c \ + tools/qfcc/source/expr_obj.c \ + tools/qfcc/source/flow.c \ + tools/qfcc/source/function.c \ + tools/qfcc/source/grab.c \ + tools/qfcc/source/idstuff.c \ + tools/qfcc/source/linker.c \ + tools/qfcc/source/method.c \ + tools/qfcc/source/obj_file.c \ + tools/qfcc/source/obj_type.c \ + tools/qfcc/source/opcodes.c \ + tools/qfcc/source/options.c \ + tools/qfcc/source/pragma.c \ + tools/qfcc/source/qc-lex.l \ + tools/qfcc/source/qc-parse.y \ + tools/qfcc/source/qfcc.c \ + tools/qfcc/source/qp-lex.l \ + tools/qfcc/source/qp-parse.y \ + tools/qfcc/source/reloc.c \ + tools/qfcc/source/shared.c \ + tools/qfcc/source/statements.c \ + tools/qfcc/source/strpool.c \ + tools/qfcc/source/struct.c \ + tools/qfcc/source/switch.c \ + tools/qfcc/source/symtab.c \ + tools/qfcc/source/type.c \ + tools/qfcc/source/value.c + +qfcc_LDADD= $(QFCC_LIBS) +qfcc_DEPENDENCIES= $(QFCC_DEPS) + +qfprogs_SOURCES= \ + tools/qfcc/source/disassemble.c \ + tools/qfcc/source/dump_globals.c \ + tools/qfcc/source/dump_lines.c \ + tools/qfcc/source/dump_modules.c \ + tools/qfcc/source/dump_strings.c \ + tools/qfcc/source/obj_file.c \ + tools/qfcc/source/qfprogs.c \ + tools/qfcc/source/strpool.c \ + tools/qfcc/source/stub.c \ + tools/qfcc/source/type.c +qfprogs_LDADD= $(QFCC_LIBS) +qfprogs_DEPENDENCIES= $(QFCC_DEPS) + +BUILT_SOURCES += \ + tools/qfcc/source/qc-parse.c \ + tools/qfcc/source/qc-parse.h \ + tools/qfcc/source/qc-lex.c \ + tools/qfcc/source/qp-parse.c \ + tools/qfcc/source/qp-parse.h \ + tools/qfcc/source/qp-lex.c + +tools/qfcc/source/qc-parse.c: tools/qfcc/source/qc-parse.y + $(YACC) $(YFLAGS) -Dapi.prefix={qc_yy} $< -o $@ +tools/qfcc/source/qc-lex.c: tools/qfcc/source/qc-lex.l tools/qfcc/source/qc-parse.h + $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqc_yy -o$@ $< +tools/qfcc/source/qp-parse.c: tools/qfcc/source/qp-parse.y + $(YACC) $(YFLAGS) -Dapi.prefix={qp_yy} $< -o $@ +tools/qfcc/source/qp-lex.c: tools/qfcc/source/qp-lex.l tools/qfcc/source/qp-parse.h + $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqp_yy -o$@ $< + +EXTRA_DIST += \ + tools/qfcc/source/qfpreqcc diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 38ffd54a8..52a3e194a 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -44,24 +44,24 @@ #include "QF/pr_obj.h" #include "QF/va.h" -#include "qfcc.h" +#include "tools/qfcc/include/qfcc.h" -#include "codespace.h" -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "method.h" -#include "options.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/codespace.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" static hashtab_t *class_hash; static hashtab_t *category_hash; diff --git a/tools/qfcc/source/codespace.c b/tools/qfcc/source/codespace.c index 797bc5707..b7cd56bcc 100644 --- a/tools/qfcc/source/codespace.c +++ b/tools/qfcc/source/codespace.c @@ -41,7 +41,7 @@ #include "QF/pr_comp.h" -#include "codespace.h" +#include "tools/qfcc/include/codespace.h" codespace_t * codespace_new (void) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 439f4760f..2d2c1400d 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -42,14 +42,15 @@ #include #include -#include "diagnostic.h" -#include "expr.h" -#include "options.h" -#include "qfcc.h" -#include "strpool.h" -#include "type.h" -#include "value.h" -#include "qc-parse.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" + +#include "tools/qfcc/source/qc-parse.h" typedef expr_t *(*operation_t) (int op, expr_t *e, expr_t *e1, expr_t *e2); typedef expr_t *(*unaryop_t) (int op, expr_t *e, expr_t *e1); diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index 71b42c6d1..1adb1301b 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -54,9 +54,9 @@ #include "QF/dstring.h" -#include "cpp.h" -#include "diagnostic.h" -#include "options.h" +#include "tools/qfcc/include/cpp.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/options.h" typedef struct cpp_arg_s { struct cpp_arg_s *next; diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 680abca84..8dec15fa2 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -47,18 +47,18 @@ #include "QF/mathlib.h" #include "QF/set.h" -#include "dags.h" -#include "diagnostic.h" -#include "dot.h" -#include "flow.h" -#include "function.h" -#include "options.h" -#include "qfcc.h" -#include "statements.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/dags.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/dot.h" +#include "tools/qfcc/include/flow.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" static daglabel_t *labels_freelist; static dagnode_t *nodes_freelist; diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index 7086f44dc..ec0367fa0 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -43,18 +43,18 @@ #include "QF/alloc.h" #include "QF/pr_comp.h" -#include "debug.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "qfcc.h" -#include "reloc.h" -#include "strpool.h" -#include "struct.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/debug.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" int lineno_base; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 1450f0f45..1fb204a67 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -45,22 +45,22 @@ #include "QF/sys.h" #include "QF/va.h" -#include "qfcc.h" -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "options.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" static def_t *defs_freelist; diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index 4c3b80ab9..72537f2d0 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -44,15 +44,15 @@ #include "QF/sys.h" #include "QF/va.h" -#include "qfcc.h" -#include "defspace.h" -#include "diagnostic.h" -#include "expr.h" -#include "options.h" -#include "reloc.h" -#include "strpool.h" -#include "struct.h" -#include "type.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/type.h" typedef struct locref_s { struct locref_s *next; diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index ab830280a..d7f9fa1fb 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -33,13 +33,13 @@ #include -#include "qfcc.h" -#include "class.h" -#include "diagnostic.h" -#include "expr.h" -#include "function.h" -#include "options.h" -#include "strpool.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/strpool.h" diagnostic_hook bug_hook; diagnostic_hook error_hook; diff --git a/tools/qfcc/source/disassemble.c b/tools/qfcc/source/disassemble.c index 06624013c..7002510bc 100644 --- a/tools/qfcc/source/disassemble.c +++ b/tools/qfcc/source/disassemble.c @@ -56,7 +56,7 @@ #include "QF/progs.h" #include "QF/sys.h" -#include "qfprogs.h" +#include "tools/qfcc/include/qfprogs.h" void disassemble_progs (progs_t *pr) diff --git a/tools/qfcc/source/dot.c b/tools/qfcc/source/dot.c index 51d82993a..333104dad 100644 --- a/tools/qfcc/source/dot.c +++ b/tools/qfcc/source/dot.c @@ -35,10 +35,10 @@ #include "QF/va.h" -#include "dot.h" -#include "function.h" -#include "options.h" -#include "strpool.h" +#include "tools/qfcc/include/dot.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/strpool.h" static function_t *last_func; static int dot_index; diff --git a/tools/qfcc/source/dot_dag.c b/tools/qfcc/source/dot_dag.c index e954f75d3..541993735 100644 --- a/tools/qfcc/source/dot_dag.c +++ b/tools/qfcc/source/dot_dag.c @@ -44,11 +44,11 @@ #include "QF/set.h" #include "QF/va.h" -#include "dags.h" -#include "statements.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/dags.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" static void print_node_def (dstring_t *dstr, dag_t *dag, dagnode_t *node) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 82c29c8d6..4db09bc39 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -46,11 +46,12 @@ #include "qfalloca.h" -#include "expr.h" -#include "symtab.h" -#include "type.h" -#include "qc-parse.h" -#include "strpool.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/strpool.h" + +#include "tools/qfcc/source/qc-parse.h" const char *expr_names[] = { diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 68f043d98..0320ebb2d 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -44,12 +44,12 @@ #include "QF/set.h" #include "QF/va.h" -#include "dags.h" -#include "flow.h" -#include "function.h" -#include "expr.h" -#include "statements.h" -#include "strpool.h" +#include "tools/qfcc/include/dags.h" +#include "tools/qfcc/include/flow.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/strpool.h" typedef struct { void (*node) (dstring_t *, flowgraph_t *, flownode_t *, int); diff --git a/tools/qfcc/source/dot_sblock.c b/tools/qfcc/source/dot_sblock.c index 8e003aa6b..18089681c 100644 --- a/tools/qfcc/source/dot_sblock.c +++ b/tools/qfcc/source/dot_sblock.c @@ -44,15 +44,15 @@ #include #include -#include "dags.h" -#include "flow.h" -#include "expr.h" -#include "qfcc.h" -#include "function.h" -#include "statements.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/dags.h" +#include "tools/qfcc/include/flow.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" static void flow_statement (dstring_t *dstr, statement_t *s) diff --git a/tools/qfcc/source/dot_type.c b/tools/qfcc/source/dot_type.c index bffa4aa70..ae58552b4 100644 --- a/tools/qfcc/source/dot_type.c +++ b/tools/qfcc/source/dot_type.c @@ -44,11 +44,10 @@ #include #include -#include "class.h" -#include "symtab.h" -#include "type.h" -#include "qc-parse.h" -#include "strpool.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/strpool.h" typedef void (*print_f) (dstring_t *dstr, type_t *, int, int); static void dot_print_type (dstring_t *dstr, type_t *t, int level, int id); diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 49c78fa5d..fe166885c 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -43,11 +43,11 @@ #include "QF/progs.h" #include "QF/va.h" -#include "obj_file.h" -#include "obj_type.h" -#include "qfprogs.h" -#include "reloc.h" -#include "strpool.h" +#include "tools/qfcc/include/obj_file.h" +#include "tools/qfcc/include/obj_type.h" +#include "tools/qfcc/include/qfprogs.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/strpool.h" static int cmp (const void *_a, const void *_b) diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index c98bfa0aa..46382cf11 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -43,8 +43,8 @@ #include "QF/progs.h" #include "QF/pr_type.h" -#include "obj_file.h" -#include "qfprogs.h" +#include "tools/qfcc/include/obj_file.h" +#include "tools/qfcc/include/qfprogs.h" typedef struct { const char *source_name; diff --git a/tools/qfcc/source/dump_modules.c b/tools/qfcc/source/dump_modules.c index 68cee44eb..7516f323b 100644 --- a/tools/qfcc/source/dump_modules.c +++ b/tools/qfcc/source/dump_modules.c @@ -44,7 +44,7 @@ #include "QF/progs.h" #include "QF/va.h" -#include "qfprogs.h" +#include "tools/qfcc/include/qfprogs.h" static void dump_methods (progs_t *pr, pr_method_list_t *methods, int class) diff --git a/tools/qfcc/source/dump_strings.c b/tools/qfcc/source/dump_strings.c index 5f119e7cc..ce9627f32 100644 --- a/tools/qfcc/source/dump_strings.c +++ b/tools/qfcc/source/dump_strings.c @@ -36,8 +36,8 @@ #include "QF/progs.h" #include "QF/sys.h" -#include "obj_file.h" -#include "qfprogs.h" +#include "tools/qfcc/include/obj_file.h" +#include "tools/qfcc/include/qfprogs.h" static void dump_string_block (const char *strblock, unsigned size) diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index e7a4b2465..f61151da3 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -42,21 +42,21 @@ #include #include -#include "codespace.h" -#include "def.h" -#include "defspace.h" -#include "debug.h" -#include "diagnostic.h" -#include "emit.h" -#include "function.h" -#include "opcodes.h" -#include "options.h" -#include "qfcc.h" -#include "reloc.h" -#include "statements.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/codespace.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/debug.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/opcodes.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" static def_t zero_def; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 7faa52caf..9ecf0ad15 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -45,25 +45,26 @@ #include "QF/sys.h" #include "QF/va.h" -#include "qfcc.h" -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "idstuff.h" -#include "method.h" -#include "options.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" -#include "qc-parse.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/idstuff.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" + +#include "tools/qfcc/source/qc-parse.h" static expr_t *exprs_freelist; diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 937da6d5c..472c1f1a5 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -45,25 +45,24 @@ #include "QF/sys.h" #include "QF/va.h" -#include "qfcc.h" -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "idstuff.h" -#include "method.h" -#include "options.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" -#include "qc-parse.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/idstuff.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" static expr_t * check_assign_logic_precedence (expr_t *dst, expr_t *src) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index cc75bcbcf..616dc7ac4 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -31,11 +31,12 @@ # include "config.h" #endif -#include "diagnostic.h" -#include "expr.h" -#include "options.h" -#include "type.h" -#include "qc-parse.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/type.h" + +#include "tools/qfcc/source/qc-parse.h" typedef struct { int op; diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 0fcb8b394..fd21de053 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -45,25 +45,26 @@ #include "QF/sys.h" #include "QF/va.h" -#include "qfcc.h" -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "idstuff.h" -#include "method.h" -#include "options.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" -#include "qc-parse.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/idstuff.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" + +#include "tools/qfcc/source/qc-parse.h" expr_t * test_expr (expr_t *e) diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c index 40b4e01c5..e75bb5b70 100644 --- a/tools/qfcc/source/expr_compound.c +++ b/tools/qfcc/source/expr_compound.c @@ -45,11 +45,11 @@ #include "QF/sys.h" #include "QF/va.h" -#include "diagnostic.h" -#include "expr.h" -#include "options.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" static element_t *elements_freelist; diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index db0b2fe4a..17d53dfdb 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -45,25 +45,24 @@ #include "QF/sys.h" #include "QF/va.h" -#include "qfcc.h" -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "idstuff.h" -#include "method.h" -#include "options.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" -#include "qc-parse.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/idstuff.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" expr_t * new_self_expr (void) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 438ece827..e26bcef1b 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -44,18 +44,18 @@ #include "QF/set.h" #include "QF/va.h" -#include "dags.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "dot.h" -#include "flow.h" -#include "function.h" -#include "options.h" -#include "qfcc.h" -#include "statements.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/dags.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/dot.h" +#include "tools/qfcc/include/flow.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" /// \addtogroup qfcc_flow ///@{ diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index b199bf51d..940abf11e 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -44,27 +44,27 @@ #include "QF/hash.h" #include "QF/va.h" -#include "qfcc.h" +#include "tools/qfcc/include/qfcc.h" -#include "class.h" -#include "codespace.h" -#include "debug.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "flow.h" -#include "function.h" -#include "opcodes.h" -#include "options.h" -#include "reloc.h" -#include "shared.h" -#include "statements.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/codespace.h" +#include "tools/qfcc/include/debug.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/flow.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/opcodes.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" static param_t *params_freelist; static function_t *functions_freelist; diff --git a/tools/qfcc/source/grab.c b/tools/qfcc/source/grab.c index 27f726519..0d59c1217 100644 --- a/tools/qfcc/source/grab.c +++ b/tools/qfcc/source/grab.c @@ -44,12 +44,12 @@ #include "QF/hash.h" #include "QF/quakeio.h" -#include "diagnostic.h" -#include "expr.h" -#include "grab.h" -#include "options.h" -#include "qfcc.h" -#include "strpool.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/grab.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/strpool.h" int grab_frame; int grab_other; diff --git a/tools/qfcc/source/idstuff.c b/tools/qfcc/source/idstuff.c index 2f195b7e2..1bc222f49 100644 --- a/tools/qfcc/source/idstuff.c +++ b/tools/qfcc/source/idstuff.c @@ -43,16 +43,16 @@ #include #include -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "qfcc.h" -#include "expr.h" -#include "idstuff.h" -#include "options.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/idstuff.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" #define MAX_SOUNDS 1024 #define MAX_MODELS 1024 diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index dd0e48722..2f6e4a565 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -58,21 +58,21 @@ #include "QF/pakfile.h" #include "QF/va.h" -#include "class.h" -#include "codespace.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "linker.h" -#include "obj_file.h" -#include "obj_type.h" -#include "options.h" -#include "qfcc.h" -#include "reloc.h" -#include "strpool.h" -#include "type.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/codespace.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/linker.h" +#include "tools/qfcc/include/obj_file.h" +#include "tools/qfcc/include/obj_type.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/type.h" static void linker_internal_error (const char *fmt, ...) __attribute__ ((format (printf, 1, 2), noreturn)); diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index ae3d031e1..244ae1513 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -44,23 +44,23 @@ #include "QF/pr_obj.h" #include "QF/va.h" -#include "qfcc.h" +#include "tools/qfcc/include/qfcc.h" -#include "expr.h" -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "method.h" -#include "options.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" static hashtab_t *known_methods; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index dcc1543d4..76a5219d4 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -46,23 +46,23 @@ #include "QF/quakeio.h" #include "QF/va.h" -#include "codespace.h" -#include "debug.h" -#include "def.h" -#include "defspace.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "obj_file.h" -#include "obj_type.h" -#include "options.h" -#include "qfcc.h" -#include "reloc.h" -#include "statements.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/codespace.h" +#include "tools/qfcc/include/debug.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/obj_file.h" +#include "tools/qfcc/include/obj_type.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" static int count_relocs (reloc_t *r) diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 6838c0824..7f87e43df 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -42,16 +42,16 @@ #include "compat.h" -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "obj_type.h" -#include "qfcc.h" -#include "reloc.h" -#include "symtab.h" -#include "value.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/obj_type.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/value.h" #define ENC_DEF(dest,def) EMIT_DEF (pr.type_data, dest, def) #define ENC_STR(dest,str) \ diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 045d14404..a9bda7a3c 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -41,11 +41,11 @@ #include -#include "opcodes.h" -#include "options.h" -#include "qfcc.h" -#include "statements.h" -#include "type.h" +#include "tools/qfcc/include/opcodes.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/type.h" hashtab_t *opcode_type_table; hashtab_t *opcode_void_table; diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index e3f9e504e..758e388a3 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -45,11 +45,11 @@ #include "QF/pr_comp.h" #include "QF/va.h" -#include "cpp.h" -#include "linker.h" -#include "options.h" -#include "qfcc.h" -#include "strpool.h" +#include "tools/qfcc/include/cpp.h" +#include "tools/qfcc/include/linker.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/strpool.h" const char *this_program; const char **source_files; diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index e1a465b53..d82f2aef4 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -42,12 +42,12 @@ #include "QF/alloc.h" #include "QF/pr_comp.h" -#include "diagnostic.h" -#include "opcodes.h" -#include "options.h" -#include "pragma.h" -#include "strpool.h" -#include "type.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/opcodes.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/pragma.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/type.h" typedef struct pragma_arg_s { struct pragma_arg_s *next; diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index a2a8295bd..50e54817d 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -45,22 +45,22 @@ #include #include -#include "class.h" -#include "debug.h" -#include "diagnostic.h" -#include "expr.h" -#include "grab.h" -#include "options.h" -#include "pragma.h" -#include "qfcc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/debug.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/grab.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/pragma.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" -#include "qc-parse.h" +#include "tools/qfcc/source/qc-parse.h" #ifndef YY_PROTO # define YY_PROTO(x) x diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index f759a4964..b08884b92 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -44,24 +44,24 @@ #include #include -#include "class.h" -#include "debug.h" -#include "def.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "method.h" -#include "options.h" -#include "qfcc.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "switch.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/debug.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/switch.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" #define YYDEBUG 1 #define YYERROR_VERBOSE 1 diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index c0739e9f0..96c26e4b0 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -65,31 +65,31 @@ #include #include -#include "qfcc.h" -#include "class.h" -#include "codespace.h" -#include "cpp.h" -#include "debug.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "grab.h" -#include "idstuff.h" -#include "linker.h" -#include "method.h" -#include "obj_file.h" -#include "opcodes.h" -#include "options.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/codespace.h" +#include "tools/qfcc/include/cpp.h" +#include "tools/qfcc/include/debug.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/grab.h" +#include "tools/qfcc/include/idstuff.h" +#include "tools/qfcc/include/linker.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/obj_file.h" +#include "tools/qfcc/include/opcodes.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" options_t options; diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 787c9068a..03d09123d 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -63,10 +63,10 @@ #include "QF/va.h" #include "QF/zone.h" -#include "obj_file.h" -#include "obj_type.h" -#include "qfprogs.h" -#include "reloc.h" +#include "tools/qfcc/include/obj_file.h" +#include "tools/qfcc/include/obj_type.h" +#include "tools/qfcc/include/qfprogs.h" +#include "tools/qfcc/include/reloc.h" const char *reloc_names[] = { "none", diff --git a/tools/qfcc/source/qp-lex.l b/tools/qfcc/source/qp-lex.l index 5947f5846..a57185209 100644 --- a/tools/qfcc/source/qp-lex.l +++ b/tools/qfcc/source/qp-lex.l @@ -35,17 +35,17 @@ #include "QF/hash.h" -#include "debug.h" -#include "diagnostic.h" -#include "expr.h" -#include "grab.h" -#include "qfcc.h" -#include "shared.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/debug.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/grab.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" -#include "qp-parse.h" +#include "tools/qfcc/source/qp-parse.h" #ifndef YY_PROTO # define YY_PROTO(x) x diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 730eab57a..15159deb0 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -41,15 +41,15 @@ #include "QF/dstring.h" -#include "codespace.h" -#include "diagnostic.h" -#include "expr.h" -#include "function.h" -#include "qfcc.h" -#include "reloc.h" -#include "shared.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/codespace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" #define YYDEBUG 1 #define YYERROR_VERBOSE 1 diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 7c4ed3ce3..c1d471d0a 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -41,15 +41,15 @@ #include "QF/alloc.h" -#include "codespace.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "qfcc.h" -#include "reloc.h" +#include "tools/qfcc/include/codespace.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" static reloc_t *refs_freelist; diff --git a/tools/qfcc/source/shared.c b/tools/qfcc/source/shared.c index 25e0ac979..cee0d06c1 100644 --- a/tools/qfcc/source/shared.c +++ b/tools/qfcc/source/shared.c @@ -31,14 +31,14 @@ # include "config.h" #endif -#include "class.h" -#include "diagnostic.h" -#include "expr.h" -#include "function.h" -#include "options.h" -#include "shared.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" function_t *current_func; class_type_t *current_class; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ba0e07331..2383dcc84 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -45,20 +45,21 @@ #include "QF/mathlib.h" #include "QF/va.h" -#include "dags.h" -#include "diagnostic.h" -#include "dot.h" -#include "expr.h" -#include "function.h" -#include "options.h" -#include "qfcc.h" -#include "reloc.h" -#include "statements.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" -#include "value.h" -#include "qc-parse.h" +#include "tools/qfcc/include/dags.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/dot.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/statements.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" + +#include "tools/qfcc/source/qc-parse.h" const char *op_type_names[] = { "op_def", diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index d3ab07a1c..fa30c74d5 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -44,9 +44,9 @@ #include "QF/dstring.h" #include "QF/hash.h" -#include "diagnostic.h" -#include "options.h" -#include "strpool.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/strpool.h" static hashtab_t *saved_strings; diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 64553a8df..c42935dd2 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -47,21 +47,21 @@ #include #include -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "obj_type.h" -#include "qfcc.h" -#include "reloc.h" -#include "shared.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/obj_type.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" static symbol_t * find_tag (ty_meta_e meta, symbol_t *tag, type_t *type) diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index 411a8d3a6..af31e546f 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -4,25 +4,25 @@ #include -#include "class.h" -#include "codespace.h" -#include "diagnostic.h" -#include "dot.h" -#include "debug.h" -#include "def.h" -#include "defspace.h" -#include "emit.h" -#include "expr.h" -#include "function.h" -#include "obj_file.h" -#include "obj_type.h" -#include "options.h" -#include "qfcc.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/codespace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/dot.h" +#include "tools/qfcc/include/debug.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/obj_file.h" +#include "tools/qfcc/include/obj_type.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" struct dstring_s; options_t options; diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 77e79f3a4..77f490c76 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -42,18 +42,18 @@ #include #include -#include "def.h" -#include "diagnostic.h" -#include "expr.h" -#include "opcodes.h" -#include "options.h" -#include "qfcc.h" -#include "reloc.h" -#include "switch.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/opcodes.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/switch.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" -#include "qc-parse.h" +#include "tools/qfcc/source/qc-parse.h" typedef struct case_node_s { expr_t *low; diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 961c00b1a..ca08069bf 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -37,16 +37,16 @@ #include "QF/alloc.h" #include "QF/hash.h" -#include "class.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "function.h" -#include "qfcc.h" -#include "reloc.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" static symtab_t *symtabs_freelist; static symbol_t *symbols_freelist; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 753ccae10..c6b92b94e 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -47,18 +47,18 @@ #include "QF/sys.h" #include "QF/va.h" -#include "class.h" -#include "def.h" -#include "diagnostic.h" -#include "expr.h" -#include "function.h" -#include "obj_type.h" -#include "options.h" -#include "qfcc.h" -#include "strpool.h" -#include "struct.h" -#include "symtab.h" -#include "type.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/obj_type.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" // simple types. function types are dynamically allocated type_t type_invalid = { ev_invalid, "invalid" }; diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index b2182497e..db98cd60a 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -45,17 +45,17 @@ #include "QF/mathlib.h" #include "QF/va.h" -#include "qfcc.h" -#include "def.h" -#include "defspace.h" -#include "diagnostic.h" -#include "emit.h" -#include "expr.h" -#include "reloc.h" -#include "strpool.h" -#include "symtab.h" -#include "type.h" -#include "value.h" +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" typedef struct { def_t *def; diff --git a/tools/qfcc/test/Makefile.am b/tools/qfcc/test/Makefile.am deleted file mode 100644 index 49ce3f51b..000000000 --- a/tools/qfcc/test/Makefile.am +++ /dev/null @@ -1,615 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -QFCC_LIBS=@QFCC_LIBS@ -QFCC_DEPS=@QFCC_DEPS@ -QFCC_INCS=@QFCC_INCS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(QFCC_INCS) - -QFCC_DEP=$(builddir)/../source/qfcc$(EXEEXT) -QFCC=$(QFCC_DEP) - -QCFLAGS=-qq -O -g -Werror -QCPPFLAGS=--no-default-paths -I$(top_srcdir)/ruamoko/include -QCOMPILE=$(QFCC) $(QCFLAGS) $(QCPPFLAGS) - -SUFFIXES=.qfo .r .pas -.r.qfo: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo -.pas.qfo: - $(QCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tqo -c -o $@ $< - @sed -i -e '1s@:@: $(QFCC_DEP)@' $(DEPDIR)/$*.Tqo - @$(am__mv) $(DEPDIR)/$*.Tqo $(DEPDIR)/$*.Qo - -QFCC_TEST_LIBS=@QFCC_TEST_LIBS@ -QFCC_TEST_DEPS=@QFCC_TEST_DEPS@ -QFCC_TEST_INCS=@QFCC_TEST_INCS@ - -test_bins=\ - test-defspace - -fail_bins= - -test_progs_dat=\ - address-cast.dat \ - alignment.dat \ - assignchain.dat \ - anonstruct.dat \ - chewed-alias.dat \ - chewed-return.dat \ - comma-expr.dat \ - compound.dat \ - deadbool.dat \ - double.dat \ - double-alias.dat \ - enum.dat \ - fordecl.dat \ - func-expr.dat \ - func-expr2.dat \ - func-static.dat \ - gcd.dat \ - infloop.dat \ - ivar-struct-return.dat \ - methodparams.dat \ - modulo.dat \ - nilparamret.dat \ - overload.dat \ - paramret.dat \ - quaternion.dat \ - return-ivar.dat \ - sendv.dat \ - state.dat \ - struct-init-param.dat \ - struct-nil-init.dat \ - structarray.dat \ - structlive.dat \ - structptr.dat \ - structstruct.dat \ - swap.dat \ - triangle.dat \ - typedef.dat \ - typelinker.dat \ - unaryminus.dat \ - vecaddr.dat \ - vecexpr.dat \ - vecinit.dat \ - voidfor.dat \ - while.dat \ - zerolinker.dat \ - $e - -fail_progs_dat= - -test_build_errors=\ - classarray.r \ - double-demote-float.r \ - double-demote-float-ainit.r \ - double-demote-float-ginit.r \ - double-demote-float-linit.r \ - double-demote-int.r \ - double-demote-int-ainit.r \ - double-demote-int-ginit.r \ - double-demote-int-linit.r \ - double-int-compare.r \ - double-float-compare.r - -fail_build_errors= - -test_defspace_src=\ - tw-defspace.c tw-diagnostic.c tw-strpool.c - -TESTS=\ - $(test_bins) \ - $(test_progs_dat:.dat=.run) \ - $(test_build_errors:.r=.run) -XFAIL_TESTS=\ - $(fail_bins) \ - $(fail_progs_dat:.dat=.run) \ - $(fail_build_errors:.r=.run) - -check_PROGRAMS=test-harness $(test_progs_dat) $(test_bins) - -test_defspace_SOURCES= test-defspace.c $(test_defspace_src) -test_defspace_LDADD= $(QFCC_LIBS) -test_defspace_DEPENDENCIES= $(QFCC_DEPS) - -test_harness_SOURCES= test-bi.c test-harness.c -test_harness_LDADD= $(QFCC_TEST_LIBS) -test_harness_DEPENDENCIES= $(QFCC_TEST_DEPS) - -r_depfiles_remade= - -address_cast_dat_SOURCES=address-cast.r -address_cast_obj=$(address_cast_dat_SOURCES:.r=.qfo) -address_cast_dep=$(addprefix ./$(DEPDIR)/,$(address_cast_obj:.qfo=.Qo)) -address-cast.dat$(EXEEXT): $(address_cast_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(address_cast_obj) -address-cast.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(address_cast_dep) # am--include-marker -r_depfiles_remade += $(address_cast_dep) - -alignment_dat_SOURCES=alignment.r -alignment_obj=$(alignment_dat_SOURCES:.r=.qfo) -alignment_dep=$(addprefix ./$(DEPDIR)/,$(alignment_obj:.qfo=.Qo)) -alignment.dat$(EXEEXT): $(alignment_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(alignment_obj) -alignment.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(alignment_dep) # am--include-marker -r_depfiles_remade += $(alignment_dep) - -anonstruct_dat_SOURCES=anonstruct.r -anonstruct_obj=$(anonstruct_dat_SOURCES:.r=.qfo) -anonstruct_dep=$(addprefix ./$(DEPDIR)/,$(anonstruct_obj:.qfo=.Qo)) -anonstruct.dat$(EXEEXT): $(anonstruct_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(anonstruct_obj) -anonstruct.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(anonstruct_dep) # am--include-marker -r_depfiles_remade += $(anonstruct_dep) - -assignchain_dat_SOURCES=assignchain.r -assignchain_obj=$(assignchain_dat_SOURCES:.r=.qfo) -assignchain_dep=$(addprefix ./$(DEPDIR)/,$(assignchain_obj:.qfo=.Qo)) -assignchain.dat$(EXEEXT): $(assignchain_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(assignchain_obj) -assignchain.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(assignchain_dep) # am--include-marker -r_depfiles_remade += $(assignchain_dep) - -chewed_alias_dat_SOURCES=chewed-alias.r -chewed_alias_obj=$(chewed_alias_dat_SOURCES:.r=.qfo) -chewed_alias_dep=$(addprefix ./$(DEPDIR)/,$(chewed_alias_obj:.qfo=.Qo)) -chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(chewed_alias_obj) -chewed-alias.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(chewed_alias_dep) # am--include-marker -r_depfiles_remade += $(chewed_alias_dep) - -chewed_return_dat_SOURCES=chewed-return.r -chewed_return_obj=$(chewed_return_dat_SOURCES:.r=.qfo) -chewed_return_dep=$(addprefix ./$(DEPDIR)/,$(chewed_return_obj:.qfo=.Qo)) -chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(chewed_return_obj) -chewed-return.run: Makefile build-run - @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ -include $(chewed_return_dep) # am--include-marker -r_depfiles_remade += $(chewed_return_dep) - -comma_expr_dat_SOURCES=comma-expr.r -comma_expr_obj=$(comma_expr_dat_SOURCES:.r=.qfo) -comma_expr_dep=$(addprefix ./$(DEPDIR)/,$(comma_expr_obj:.qfo=.Qo)) -comma-expr.dat$(EXEEXT): $(comma_expr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(comma_expr_obj) -comma-expr.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(comma_expr_dep) # am--include-marker -r_depfiles_remade += $(comma_expr_dep) - -compound_dat_SOURCES=compound.r -compound_obj=$(compound_dat_SOURCES:.r=.qfo) -compound_dep=$(addprefix ./$(DEPDIR)/,$(compound_obj:.qfo=.Qo)) -compound.dat$(EXEEXT): $(compound_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(compound_obj) -compound.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(compound_dep) # am--include-marker -r_depfiles_remade += $(compound_dep) - -deadbool_dat_SOURCES=deadbool.r -deadbool_obj=$(deadbool_dat_SOURCES:.r=.qfo) -deadbool_dep=$(addprefix ./$(DEPDIR)/,$(deadbool_obj:.qfo=.Qo)) -deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(deadbool_obj) -deadbool.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(deadbool_dep) # am--include-marker -r_depfiles_remade += $(deadbool_dep) - -double_dat_SOURCES=double.r -double_obj=$(double_dat_SOURCES:.r=.qfo) -double_dep=$(addprefix ./$(DEPDIR)/,$(double_obj:.qfo=.Qo)) -double.dat$(EXEEXT): $(double_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(double_obj) -double.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(double_dep) # am--include-marker -r_depfiles_remade += $(double_dep) - -double_alias_dat_SOURCES=double-alias.r -double_alias_obj=$(double_alias_dat_SOURCES:.r=.qfo) -double_alias_dep=$(addprefix ./$(DEPDIR)/,$(double_alias_obj:.qfo=.Qo)) -double-alias.dat$(EXEEXT): $(double_alias_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(double_alias_obj) -double-alias.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(double_alias_dep) # am--include-marker -r_depfiles_remade += $(double_alias_dep) - -classarray.run$(EXEEXT): classarray.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-demote-int.run$(EXEEXT): double-demote-int.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-demote-float.run$(EXEEXT): double-demote-float.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-demote-int-ainit.run$(EXEEXT): double-demote-int-ainit.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-demote-float-ainit.run$(EXEEXT): double-demote-float-ainit.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-demote-int-ginit.run$(EXEEXT): double-demote-int-ginit.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-demote-float-ginit.run$(EXEEXT): double-demote-float-ginit.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-demote-int-linit.run$(EXEEXT): double-demote-int-linit.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-demote-float-linit.run$(EXEEXT): double-demote-float-linit.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-int-compare.run$(EXEEXT): double-int-compare.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -double-float-compare.run$(EXEEXT): double-float-compare.r Makefile build-compile-fail-run - @$(srcdir)/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< - -enum_dat_SOURCES=enum.r -enum_obj=$(enum_dat_SOURCES:.r=.qfo) -enum_dep=$(addprefix ./$(DEPDIR)/,$(enum_obj:.qfo=.Qo)) -enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(enum_obj) -enum.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(enum_dep) # am--include-marker -r_depfiles_remade += $(enum_dep) - -fordecl_dat_SOURCES=fordecl.r -fordecl_obj=$(fordecl_dat_SOURCES:.r=.qfo) -fordecl_dep=$(addprefix ./$(DEPDIR)/,$(fordecl_obj:.qfo=.Qo)) -fordecl.dat$(EXEEXT): $(fordecl_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(fordecl_obj) -fordecl.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(fordecl_dep) # am--include-marker -r_depfiles_remade += $(fordecl_dep) - -func_expr_dat_SOURCES=func-expr.r -func_expr_obj=$(func_expr_dat_SOURCES:.r=.qfo) -func_expr_dep=$(addprefix ./$(DEPDIR)/,$(func_expr_obj:.qfo=.Qo)) -func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) -func-expr.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(func_expr_dep) # am--include-marker -r_depfiles_remade += $(func_expr_dep) - -func_expr2_dat_SOURCES=func-expr2.r -func_expr2_obj=$(func_expr2_dat_SOURCES:.r=.qfo) -func_expr2_dep=$(addprefix ./$(DEPDIR)/,$(func_expr2_obj:.qfo=.Qo)) -func-expr2.dat$(EXEEXT): $(func_expr2_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_expr2_obj) -func-expr2.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(func_expr2_dep) # am--include-marker -r_depfiles_remade += $(func_expr2_dep) - -func_static_dat_SOURCES=func-static.r -func_static_obj=$(func_static_dat_SOURCES:.r=.qfo) -func_static_dep=$(addprefix ./$(DEPDIR)/,$(func_static_obj:.qfo=.Qo)) -func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) -func-static.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(func_static_dep) # am--include-marker -r_depfiles_remade += $(func_static_dep) - -gcd_dat_SOURCES=gcd.pas -gcd_obj=$(gcd_dat_SOURCES:.pas=.qfo) -gcd_dep=$(addprefix ./$(DEPDIR)/,$(gcd_obj:.qfo=.Qo)) -gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(gcd_obj) -gcd.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(gcd_dep) # am--include-marker -r_depfiles_remade += $(gcd_dep) - -infloop_dat_SOURCES=infloop.r -infloop_obj=$(infloop_dat_SOURCES:.r=.qfo) -infloop_dep=$(addprefix ./$(DEPDIR)/,$(infloop_obj:.qfo=.Qo)) -infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(infloop_obj) -infloop.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(infloop_dep) # am--include-marker -r_depfiles_remade += $(infloop_dep) - -ivar_struct_return_dat_SOURCES=ivar-struct-return.r -ivar_struct_return_obj=$(ivar_struct_return_dat_SOURCES:.r=.qfo) -ivar_struct_return_dep=$(addprefix ./$(DEPDIR)/,$(ivar_struct_return_obj:.qfo=.Qo)) -ivar-struct-return.dat$(EXEEXT): $(ivar_struct_return_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(ivar_struct_return_obj) -ivar-struct-return.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(ivar_struct_return_dep) # am--include-marker -r_depfiles_remade += $(ivar_struct_return_dep) - -methodparams_dat_SOURCES=methodparams.r -methodparams_obj=$(methodparams_dat_SOURCES:.r=.qfo) -methodparams_dep=$(addprefix ./$(DEPDIR)/,$(methodparams_obj:.qfo=.Qo)) -methodparams.dat$(EXEEXT): $(methodparams_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(methodparams_obj) -methodparams.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(methodparams_dep) # am--include-marker -r_depfiles_remade += $(methodparams_dep) - -modulo_dat_SOURCES=modulo.r -modulo_obj=$(modulo_dat_SOURCES:.r=.qfo) -modulo_dep=$(addprefix ./$(DEPDIR)/,$(modulo_obj:.qfo=.Qo)) -modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(modulo_obj) -modulo.run: Makefile build-run - @TEST_HARNESS_OPTS=--float $(srcdir)/build-run $@ -include $(modulo_dep) # am--include-marker -r_depfiles_remade += $(modulo_dep) - -nilparamret_dat_SOURCES=nilparamret.r -nilparamret_obj=$(nilparamret_dat_SOURCES:.r=.qfo) -nilparamret_dep=$(addprefix ./$(DEPDIR)/,$(nilparamret_obj:.qfo=.Qo)) -nilparamret.dat$(EXEEXT): $(nilparamret_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(nilparamret_obj) -nilparamret.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(nilparamret_dep) # am--include-marker -r_depfiles_remade += $(nilparamret_dep) - -overload_dat_SOURCES=overload.r -overload_obj=$(overload_dat_SOURCES:.r=.qfo) -overload_dep=$(addprefix ./$(DEPDIR)/,$(overload_obj:.qfo=.Qo)) -overload.dat$(EXEEXT): $(overload_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(overload_obj) -overload.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(overload_dep) # am--include-marker -r_depfiles_remade += $(overload_dep) - -paramret_dat_SOURCES=paramret.r -paramret_obj=$(paramret_dat_SOURCES:.r=.qfo) -paramret_dep=$(addprefix ./$(DEPDIR)/,$(paramret_obj:.qfo=.Qo)) -paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) -paramret.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(paramret_dep) # am--include-marker -r_depfiles_remade += $(paramret_dep) - -quaternion_dat_SOURCES=quaternion.r -quaternion_obj=$(quaternion_dat_SOURCES:.r=.qfo) -quaternion_dep=$(addprefix ./$(DEPDIR)/,$(quaternion_obj:.qfo=.Qo)) -quaternion.dat$(EXEEXT): $(quaternion_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(quaternion_obj) -quaternion.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(quaternion_dep) # am--include-marker -r_depfiles_remade += $(quaternion_dep) - -return_ivar_dat_SOURCES=return-ivar.r -return_ivar_obj=$(return_ivar_dat_SOURCES:.r=.qfo) -return_ivar_dep=$(addprefix ./$(DEPDIR)/,$(return_ivar_obj:.qfo=.Qo)) -return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(return_ivar_obj) -return-ivar.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(return_ivar_dep) # am--include-marker -r_depfiles_remade += $(return_ivar_dep) - -sendv_dat_SOURCES=sendv.r -sendv_obj=$(sendv_dat_SOURCES:.r=.qfo) -sendv_dep=$(addprefix ./$(DEPDIR)/,$(sendv_obj:.qfo=.Qo)) -sendv.dat$(EXEEXT): $(sendv_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(sendv_obj) -sendv.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(sendv_dep) # am--include-marker -r_depfiles_remade += $(sendv_dep) - -state_dat_SOURCES=state.r -state_obj=$(state_dat_SOURCES:.r=.qfo) -state_dep=$(addprefix ./$(DEPDIR)/,$(state_obj:.qfo=.Qo)) -state.dat$(EXEEXT): $(state_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(state_obj) -state.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(state_dep) # am--include-marker -r_depfiles_remade += $(state_dep) - -struct_init_param_dat_SOURCES=struct-init-param.r -struct_init_param_obj=$(struct_init_param_dat_SOURCES:.r=.qfo) -struct_init_param_dep=$(addprefix ./$(DEPDIR)/,$(struct_init_param_obj:.qfo=.Qo)) -struct-init-param.dat$(EXEEXT): $(struct_init_param_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(struct_init_param_obj) -struct-init-param.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(struct_init_param_dep) # am--include-marker -r_depfiles_remade += $(struct_init_param_dep) - -struct_nil_init_dat_SOURCES=struct-nil-init.r -struct_nil_init_obj=$(struct_nil_init_dat_SOURCES:.r=.qfo) -struct_nil_init_dep=$(addprefix ./$(DEPDIR)/,$(struct_nil_init_obj:.qfo=.Qo)) -struct-nil-init.dat$(EXEEXT): $(struct_nil_init_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(struct_nil_init_obj) -struct-nil-init.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(struct_nil_init_dep) # am--include-marker -r_depfiles_remade += $(struct_nil_init_dep) - -structarray_dat_SOURCES=structarray.r -structarray_obj=$(structarray_dat_SOURCES:.r=.qfo) -structarray_dep=$(addprefix ./$(DEPDIR)/,$(structarray_obj:.qfo=.Qo)) -structarray.dat$(EXEEXT): $(structarray_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structarray_obj) -structarray.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(structarray_dep) # am--include-marker -r_depfiles_remade += $(structarray_dep) - -structlive_dat_SOURCES=structlive.r -structlive_obj=$(structlive_dat_SOURCES:.r=.qfo) -structlive_dep=$(addprefix ./$(DEPDIR)/,$(structlive_obj:.qfo=.Qo)) -structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structlive_obj) -structlive.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(structlive_dep) # am--include-marker -r_depfiles_remade += $(structlive_dep) - -structptr_dat_SOURCES=structptr.r -structptr_obj=$(structptr_dat_SOURCES:.r=.qfo) -structptr_dep=$(addprefix ./$(DEPDIR)/,$(structptr_obj:.qfo=.Qo)) -structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structptr_obj) -structptr.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(structptr_dep) # am--include-marker -r_depfiles_remade += $(structptr_dep) - -structstruct_dat_SOURCES=structstruct.r -structstruct_obj=$(structstruct_dat_SOURCES:.r=.qfo) -structstruct_dep=$(addprefix ./$(DEPDIR)/,$(structstruct_obj:.qfo=.Qo)) -structstruct.dat$(EXEEXT): $(structstruct_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structstruct_obj) -structstruct.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(structstruct_dep) # am--include-marker -r_depfiles_remade += $(structstruct_dep) - -swap_dat_SOURCES=swap.r -swap_obj=$(swap_dat_SOURCES:.r=.qfo) -swap_dep=$(addprefix ./$(DEPDIR)/,$(swap_obj:.qfo=.Qo)) -swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(swap_obj) -swap.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(swap_dep) # am--include-marker -r_depfiles_remade += $(swap_dep) - -triangle_dat_SOURCES=triangle.r -triangle_obj=$(triangle_dat_SOURCES:.r=.qfo) -triangle_dep=$(addprefix ./$(DEPDIR)/,$(triangle_obj:.qfo=.Qo)) -triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) -triangle.run: Makefile build-run - @$(srcdir)/build-run $@ 100000 100000 1.00005 50002.4961 -include $(triangle_dep) # am--include-marker -r_depfiles_remade += $(triangle_dep) - -typedef_dat_SOURCES=typedef.r -typedef_obj=$(typedef_dat_SOURCES:.r=.qfo) -typedef_dep=$(addprefix ./$(DEPDIR)/,$(typedef_obj:.qfo=.Qo)) -typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) -typedef.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(typedef_dep) # am--include-marker -r_depfiles_remade += $(typedef_dep) - -typelinker_dat_SOURCES=typelinker_a.r typelinker_b.r -typelinker_obj=$(typelinker_dat_SOURCES:.r=.qfo) -typelinker_dep=$(addprefix ./$(DEPDIR)/,$(typelinker_obj:.qfo=.Qo)) -typelinker.dat$(EXEEXT): $(typelinker_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(typelinker_obj) -typelinker.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(typelinker_dep) # am--include-marker -r_depfiles_remade += $(typelinker_dep) - -unaryminus_dat_SOURCES=unaryminus.r -unaryminus_obj=$(unaryminus_dat_SOURCES:.r=.qfo) -unaryminus_dep=$(addprefix ./$(DEPDIR)/,$(unaryminus_obj:.qfo=.Qo)) -unaryminus.dat$(EXEEXT): $(unaryminus_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(unaryminus_obj) -unaryminus.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(unaryminus_dep) # am--include-marker -r_depfiles_remade += $(unaryminus_dep) - -vecaddr_dat_SOURCES=vecaddr.r -vecaddr_obj=$(vecaddr_dat_SOURCES:.r=.qfo) -vecaddr_dep=$(addprefix ./$(DEPDIR)/,$(vecaddr_obj:.qfo=.Qo)) -vecaddr.dat$(EXEEXT): $(vecaddr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(vecaddr_obj) -vecaddr.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(vecaddr_dep) # am--include-marker -r_depfiles_remade += $(vecaddr_dep) - -vecexpr_dat_SOURCES=vecexpr.r -vecexpr_obj=$(vecexpr_dat_SOURCES:.r=.qfo) -vecexpr_dep=$(addprefix ./$(DEPDIR)/,$(vecexpr_obj:.qfo=.Qo)) -vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(vecexpr_obj) -vecexpr.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(vecexpr_dep) # am--include-marker -r_depfiles_remade += $(vecexpr_dep) - -vecinit_dat_SOURCES=vecinit.r -vecinit_obj=$(vecinit_dat_SOURCES:.r=.qfo) -vecinit_dep=$(addprefix ./$(DEPDIR)/,$(vecinit_obj:.qfo=.Qo)) -vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(vecinit_obj) -vecinit.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(vecinit_dep) # am--include-marker -r_depfiles_remade += $(vecinit_dep) - -voidfor_dat_SOURCES=voidfor.r -voidfor_obj=$(voidfor_dat_SOURCES:.r=.qfo) -voidfor_dep=$(addprefix ./$(DEPDIR)/,$(voidfor_obj:.qfo=.Qo)) -voidfor.dat$(EXEEXT): $(voidfor_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj) -voidfor.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(voidfor_dep) # am--include-marker -r_depfiles_remade += $(voidfor_dep) - -while_dat_SOURCES=while.r -while_obj=$(while_dat_SOURCES:.r=.qfo) -while_dep=$(addprefix ./$(DEPDIR)/,$(while_obj:.qfo=.Qo)) -while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(while_obj) -while.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(while_dep) # am--include-marker -r_depfiles_remade += $(while_dep) - -zerolinker_dat_SOURCES=zerolinker.r -zerolinker_obj=$(zerolinker_dat_SOURCES:.r=.qfo) -zerolinker_dep=$(addprefix ./$(DEPDIR)/,$(zerolinker_obj:.qfo=.Qo)) -zerolinker.dat$(EXEEXT): $(zerolinker_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(zerolinker_obj) -zerolinker.run: Makefile build-run - @$(srcdir)/build-run $@ -include $(zerolinker_dep) # am--include-marker -r_depfiles_remade += $(zerolinker_dep) - -$(r_depfiles_remade): - @$(MKDIR_P) $(@D) - @echo '# dummy' >$@-t && $(am__mv) $@-t $@ - - -am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) - -EXTRA_DIST= test-bi.h build-run test-defspace.h -CLEANFILES= *.dat *.sym *.qfo *.run *.frame *.log *.trs diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am new file mode 100644 index 000000000..85f94b800 --- /dev/null +++ b/tools/qfcc/test/Makemodule.am @@ -0,0 +1,599 @@ +QFCC_TEST_LIBS=@QFCC_TEST_LIBS@ +QFCC_TEST_DEPS=@QFCC_TEST_DEPS@ +QFCC_TEST_INCS=@QFCC_TEST_INCS@ + +test_bins=\ + tools/qfcc/test/test-defspace + +fail_bins= + +test_progs_dat=\ + tools/qfcc/test/address-cast.dat \ + tools/qfcc/test/alignment.dat \ + tools/qfcc/test/assignchain.dat \ + tools/qfcc/test/anonstruct.dat \ + tools/qfcc/test/chewed-alias.dat \ + tools/qfcc/test/chewed-return.dat \ + tools/qfcc/test/comma-expr.dat \ + tools/qfcc/test/compound.dat \ + tools/qfcc/test/deadbool.dat \ + tools/qfcc/test/double.dat \ + tools/qfcc/test/double-alias.dat \ + tools/qfcc/test/enum.dat \ + tools/qfcc/test/fordecl.dat \ + tools/qfcc/test/func-expr.dat \ + tools/qfcc/test/func-expr2.dat \ + tools/qfcc/test/func-static.dat \ + tools/qfcc/test/gcd.dat \ + tools/qfcc/test/infloop.dat \ + tools/qfcc/test/ivar-struct-return.dat \ + tools/qfcc/test/methodparams.dat \ + tools/qfcc/test/modulo.dat \ + tools/qfcc/test/nilparamret.dat \ + tools/qfcc/test/overload.dat \ + tools/qfcc/test/paramret.dat \ + tools/qfcc/test/quaternion.dat \ + tools/qfcc/test/return-ivar.dat \ + tools/qfcc/test/sendv.dat \ + tools/qfcc/test/state.dat \ + tools/qfcc/test/struct-init-param.dat \ + tools/qfcc/test/struct-nil-init.dat \ + tools/qfcc/test/structarray.dat \ + tools/qfcc/test/structlive.dat \ + tools/qfcc/test/structptr.dat \ + tools/qfcc/test/structstruct.dat \ + tools/qfcc/test/swap.dat \ + tools/qfcc/test/triangle.dat \ + tools/qfcc/test/typedef.dat \ + tools/qfcc/test/typelinker.dat \ + tools/qfcc/test/unaryminus.dat \ + tools/qfcc/test/vecaddr.dat \ + tools/qfcc/test/vecexpr.dat \ + tools/qfcc/test/vecinit.dat \ + tools/qfcc/test/voidfor.dat \ + tools/qfcc/test/while.dat \ + tools/qfcc/test/zerolinker.dat + +fail_progs_dat= + +test_build_errors=\ + tools/qfcc/test/classarray.r \ + tools/qfcc/test/double-demote-float.r \ + tools/qfcc/test/double-demote-float-ainit.r \ + tools/qfcc/test/double-demote-float-ginit.r \ + tools/qfcc/test/double-demote-float-linit.r \ + tools/qfcc/test/double-demote-int.r \ + tools/qfcc/test/double-demote-int-ainit.r \ + tools/qfcc/test/double-demote-int-ginit.r \ + tools/qfcc/test/double-demote-int-linit.r \ + tools/qfcc/test/double-int-compare.r \ + tools/qfcc/test/double-float-compare.r + +fail_build_errors= + +test_defspace_src=\ + tools/qfcc/test/tw-defspace.c tools/qfcc/test/tw-diagnostic.c tools/qfcc/test/tw-strpool.c + +TESTS += \ + $(test_bins) \ + $(test_progs_dat:.dat=.run) \ + $(test_build_errors:.r=.run) +XFAIL_TESTS += \ + $(fail_bins) \ + $(fail_progs_dat:.dat=.run) \ + $(fail_build_errors:.r=.run) + +check_PROGRAMS += \ + tools/qfcc/test/test-harness \ + $(test_progs_dat) \ + $(test_bins) + +tools_qfcc_test_test_defspace_SOURCES= tools/qfcc/test/test-defspace.c $(test_defspace_src) +tools_qfcc_test_test_defspace_LDADD= $(QFCC_LIBS) +tools_qfcc_test_test_defspace_DEPENDENCIES= $(QFCC_DEPS) + +tools_qfcc_test_test_harness_SOURCES= tools/qfcc/test/test-bi.c tools/qfcc/test/test-harness.c +tools_qfcc_test_test_harness_LDADD= $(QFCC_TEST_LIBS) +tools_qfcc_test_test_harness_DEPENDENCIES= $(QFCC_TEST_DEPS) + +qfcc_test_run_deps = Makefile tools/qfcc/test/build-run +qfcc_fail_run_deps = Makefile tools/qfcc/test/build-compile-fail-run +tools_qfcc_test_address_cast_dat_SOURCES=tools/qfcc/test/address-cast.r +address_cast_obj=$(tools_qfcc_test_address_cast_dat_SOURCES:.r=.o) +address_cast_dep=$(call qcautodep,$(tools_qfcc_test_address_cast_dat_SOURCES)) +tools/qfcc/test/address-cast.dat$(EXEEXT): $(address_cast_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(address_cast_obj) +tools/qfcc/test/address-cast.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(address_cast_dep) # am--include-marker +r_depfiles_remade += $(address_cast_dep) + +tools_qfcc_test_alignment_dat_SOURCES=tools/qfcc/test/alignment.r +alignment_obj=$(tools_qfcc_test_alignment_dat_SOURCES:.r=.o) +alignment_dep=$(call qcautodep,$(tools_qfcc_test_alignment_dat_SOURCES)) +tools/qfcc/test/alignment.dat$(EXEEXT): $(alignment_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(alignment_obj) +tools/qfcc/test/alignment.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(alignment_dep) # am--include-marker +r_depfiles_remade += $(alignment_dep) + +tools_qfcc_test_anonstruct_dat_SOURCES=tools/qfcc/test/anonstruct.r +anonstruct_obj=$(tools_qfcc_test_anonstruct_dat_SOURCES:.r=.o) +anonstruct_dep=$(call qcautodep,$(tools_qfcc_test_anonstruct_dat_SOURCES)) +tools/qfcc/test/anonstruct.dat$(EXEEXT): $(anonstruct_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(anonstruct_obj) +tools/qfcc/test/anonstruct.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(anonstruct_dep) # am--include-marker +r_depfiles_remade += $(anonstruct_dep) + +tools_qfcc_test_assignchain_dat_SOURCES=tools/qfcc/test/assignchain.r +assignchain_obj=$(tools_qfcc_test_assignchain_dat_SOURCES:.r=.o) +assignchain_dep=$(call qcautodep,$(tools_qfcc_test_assignchain_dat_SOURCES)) +tools/qfcc/test/assignchain.dat$(EXEEXT): $(assignchain_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(assignchain_obj) +tools/qfcc/test/assignchain.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(assignchain_dep) # am--include-marker +r_depfiles_remade += $(assignchain_dep) + +tools_qfcc_test_chewed_alias_dat_SOURCES=tools/qfcc/test/chewed-alias.r +chewed_alias_obj=$(tools_qfcc_test_chewed_alias_dat_SOURCES:.r=.o) +chewed_alias_dep=$(call qcautodep,$(tools_qfcc_test_chewed_alias_dat_SOURCES)) +tools/qfcc/test/chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(chewed_alias_obj) +tools/qfcc/test/chewed-alias.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(chewed_alias_dep) # am--include-marker +r_depfiles_remade += $(chewed_alias_dep) + +tools_qfcc_test_chewed_return_dat_SOURCES=tools/qfcc/test/chewed-return.r +chewed_return_obj=$(tools_qfcc_test_chewed_return_dat_SOURCES:.r=.o) +chewed_return_dep=$(call qcautodep,$(tools_qfcc_test_chewed_return_dat_SOURCES)) +tools/qfcc/test/chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(chewed_return_obj) +tools/qfcc/test/chewed-return.run: $(qfcc_test_run_deps) + @TEST_HARNESS_OPTS=--float $(top_srcdir)/tools/qfcc/test/build-run $@ +include $(chewed_return_dep) # am--include-marker +r_depfiles_remade += $(chewed_return_dep) + +tools_qfcc_test_comma_expr_dat_SOURCES=tools/qfcc/test/comma-expr.r +comma_expr_obj=$(tools_qfcc_test_comma_expr_dat_SOURCES:.r=.o) +comma_expr_dep=$(call qcautodep,$(tools_qfcc_test_comma_expr_dat_SOURCES)) +tools/qfcc/test/comma-expr.dat$(EXEEXT): $(comma_expr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(comma_expr_obj) +tools/qfcc/test/comma-expr.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(comma_expr_dep) # am--include-marker +r_depfiles_remade += $(comma_expr_dep) + +tools_qfcc_test_compound_dat_SOURCES=tools/qfcc/test/compound.r +compound_obj=$(tools_qfcc_test_compound_dat_SOURCES:.r=.o) +compound_dep=$(call qcautodep,$(tools_qfcc_test_compound_dat_SOURCES)) +tools/qfcc/test/compound.dat$(EXEEXT): $(compound_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(compound_obj) +tools/qfcc/test/compound.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(compound_dep) # am--include-marker +r_depfiles_remade += $(compound_dep) + +tools_qfcc_test_deadbool_dat_SOURCES=tools/qfcc/test/deadbool.r +deadbool_obj=$(tools_qfcc_test_deadbool_dat_SOURCES:.r=.o) +deadbool_dep=$(call qcautodep,$(tools_qfcc_test_deadbool_dat_SOURCES)) +tools/qfcc/test/deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(deadbool_obj) +tools/qfcc/test/deadbool.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(deadbool_dep) # am--include-marker +r_depfiles_remade += $(deadbool_dep) + +tools_qfcc_test_double_dat_SOURCES=tools/qfcc/test/double.r +double_obj=$(tools_qfcc_test_double_dat_SOURCES:.r=.o) +double_dep=$(call qcautodep,$(tools_qfcc_test_double_dat_SOURCES)) +tools/qfcc/test/double.dat$(EXEEXT): $(double_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(double_obj) +tools/qfcc/test/double.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(double_dep) # am--include-marker +r_depfiles_remade += $(double_dep) + +tools_qfcc_test_double_alias_dat_SOURCES=tools/qfcc/test/double-alias.r +double_alias_obj=$(tools_qfcc_test_double_alias_dat_SOURCES:.r=.o) +double_alias_dep=$(call qcautodep,$(tools_qfcc_test_double_alias_dat_SOURCES)) +tools/qfcc/test/double-alias.dat$(EXEEXT): $(double_alias_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(double_alias_obj) +tools/qfcc/test/double-alias.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(double_alias_dep) # am--include-marker +r_depfiles_remade += $(double_alias_dep) + +tools/qfcc/test/classarray.run$(EXEEXT): tools/qfcc/test/classarray.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-demote-int.run$(EXEEXT): tools/qfcc/test/double-demote-int.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-demote-float.run$(EXEEXT): tools/qfcc/test/double-demote-float.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-demote-int-ainit.run$(EXEEXT): tools/qfcc/test/double-demote-int-ainit.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-demote-float-ainit.run$(EXEEXT): tools/qfcc/test/double-demote-float-ainit.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-demote-int-ginit.run$(EXEEXT): tools/qfcc/test/double-demote-int-ginit.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-demote-float-ginit.run$(EXEEXT): tools/qfcc/test/double-demote-float-ginit.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-demote-int-linit.run$(EXEEXT): tools/qfcc/test/double-demote-int-linit.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-demote-float-linit.run$(EXEEXT): tools/qfcc/test/double-demote-float-linit.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-int-compare.run$(EXEEXT): tools/qfcc/test/double-int-compare.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/double-float-compare.run$(EXEEXT): tools/qfcc/test/double-float-compare.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + +tools_qfcc_test_enum_dat_SOURCES=tools/qfcc/test/enum.r +enum_obj=$(tools_qfcc_test_enum_dat_SOURCES:.r=.o) +enum_dep=$(call qcautodep,$(tools_qfcc_test_enum_dat_SOURCES)) +tools/qfcc/test/enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(enum_obj) +tools/qfcc/test/enum.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(enum_dep) # am--include-marker +r_depfiles_remade += $(enum_dep) + +tools_qfcc_test_fordecl_dat_SOURCES=tools/qfcc/test/fordecl.r +fordecl_obj=$(tools_qfcc_test_fordecl_dat_SOURCES:.r=.o) +fordecl_dep=$(call qcautodep,$(tools_qfcc_test_fordecl_dat_SOURCES)) +tools/qfcc/test/fordecl.dat$(EXEEXT): $(fordecl_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(fordecl_obj) +tools/qfcc/test/fordecl.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(fordecl_dep) # am--include-marker +r_depfiles_remade += $(fordecl_dep) + +tools_qfcc_test_func_expr_dat_SOURCES=tools/qfcc/test/func-expr.r +func_expr_obj=$(tools_qfcc_test_func_expr_dat_SOURCES:.r=.o) +func_expr_dep=$(call qcautodep,$(tools_qfcc_test_func_expr_dat_SOURCES)) +tools/qfcc/test/func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) +tools/qfcc/test/func-expr.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(func_expr_dep) # am--include-marker +r_depfiles_remade += $(func_expr_dep) + +tools_qfcc_test_func_expr2_dat_SOURCES=tools/qfcc/test/func-expr2.r +func_expr2_obj=$(tools_qfcc_test_func_expr2_dat_SOURCES:.r=.o) +func_expr2_dep=$(call qcautodep,$(tools_qfcc_test_func_expr2_dat_SOURCES)) +tools/qfcc/test/func-expr2.dat$(EXEEXT): $(func_expr2_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(func_expr2_obj) +tools/qfcc/test/func-expr2.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(func_expr2_dep) # am--include-marker +r_depfiles_remade += $(func_expr2_dep) + +tools_qfcc_test_func_static_dat_SOURCES=tools/qfcc/test/func-static.r +func_static_obj=$(tools_qfcc_test_func_static_dat_SOURCES:.r=.o) +func_static_dep=$(call qcautodep,$(tools_qfcc_test_func_static_dat_SOURCES)) +tools/qfcc/test/func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) +tools/qfcc/test/func-static.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(func_static_dep) # am--include-marker +r_depfiles_remade += $(func_static_dep) + +tools_qfcc_test_gcd_dat_SOURCES=tools/qfcc/test/gcd.pas +gcd_obj=$(tools_qfcc_test_gcd_dat_SOURCES:.pas=.o) +gcd_dep=$(call qcautodep,$(tools_qfcc_test_gcd_dat_SOURCES)) +tools/qfcc/test/gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(gcd_obj) +tools/qfcc/test/gcd.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(gcd_dep) # am--include-marker +pas_depfiles_remade += $(gcd_dep) + +tools_qfcc_test_infloop_dat_SOURCES=tools/qfcc/test/infloop.r +infloop_obj=$(tools_qfcc_test_infloop_dat_SOURCES:.r=.o) +infloop_dep=$(call qcautodep,$(tools_qfcc_test_infloop_dat_SOURCES)) +tools/qfcc/test/infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(infloop_obj) +tools/qfcc/test/infloop.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(infloop_dep) # am--include-marker +r_depfiles_remade += $(infloop_dep) + +tools_qfcc_test_ivar_struct_return_dat_SOURCES=tools/qfcc/test/ivar-struct-return.r +ivar_struct_return_obj=$(tools_qfcc_test_ivar_struct_return_dat_SOURCES:.r=.o) +ivar_struct_return_dep=$(call qcautodep,$(tools_qfcc_test_ivar_struct_return_dat_SOURCES)) +tools/qfcc/test/ivar-struct-return.dat$(EXEEXT): $(ivar_struct_return_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(ivar_struct_return_obj) +tools/qfcc/test/ivar-struct-return.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(ivar_struct_return_dep) # am--include-marker +r_depfiles_remade += $(ivar_struct_return_dep) + +tools_qfcc_test_methodparams_dat_SOURCES=tools/qfcc/test/methodparams.r +methodparams_obj=$(tools_qfcc_test_methodparams_dat_SOURCES:.r=.o) +methodparams_dep=$(call qcautodep,$(tools_qfcc_test_methodparams_dat_SOURCES)) +tools/qfcc/test/methodparams.dat$(EXEEXT): $(methodparams_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(methodparams_obj) +tools/qfcc/test/methodparams.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(methodparams_dep) # am--include-marker +r_depfiles_remade += $(methodparams_dep) + +tools_qfcc_test_modulo_dat_SOURCES=tools/qfcc/test/modulo.r +modulo_obj=$(tools_qfcc_test_modulo_dat_SOURCES:.r=.o) +modulo_dep=$(call qcautodep,$(tools_qfcc_test_modulo_dat_SOURCES)) +tools/qfcc/test/modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(modulo_obj) +tools/qfcc/test/modulo.run: $(qfcc_test_run_deps) + @TEST_HARNESS_OPTS=--float $(top_srcdir)/tools/qfcc/test/build-run $@ +include $(modulo_dep) # am--include-marker +r_depfiles_remade += $(modulo_dep) + +tools_qfcc_test_nilparamret_dat_SOURCES=tools/qfcc/test/nilparamret.r +nilparamret_obj=$(tools_qfcc_test_nilparamret_dat_SOURCES:.r=.o) +nilparamret_dep=$(call qcautodep,$(tools_qfcc_test_nilparamret_dat_SOURCES)) +tools/qfcc/test/nilparamret.dat$(EXEEXT): $(nilparamret_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(nilparamret_obj) +tools/qfcc/test/nilparamret.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(nilparamret_dep) # am--include-marker +r_depfiles_remade += $(nilparamret_dep) + +tools_qfcc_test_overload_dat_SOURCES=tools/qfcc/test/overload.r +overload_obj=$(tools_qfcc_test_overload_dat_SOURCES:.r=.o) +overload_dep=$(call qcautodep,$(tools_qfcc_test_overload_dat_SOURCES)) +tools/qfcc/test/overload.dat$(EXEEXT): $(overload_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(overload_obj) +tools/qfcc/test/overload.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(overload_dep) # am--include-marker +r_depfiles_remade += $(overload_dep) + +tools_qfcc_test_paramret_dat_SOURCES=tools/qfcc/test/paramret.r +paramret_obj=$(tools_qfcc_test_paramret_dat_SOURCES:.r=.o) +paramret_dep=$(call qcautodep,$(tools_qfcc_test_paramret_dat_SOURCES)) +tools/qfcc/test/paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) +tools/qfcc/test/paramret.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(paramret_dep) # am--include-marker +r_depfiles_remade += $(paramret_dep) + +tools_qfcc_test_quaternion_dat_SOURCES=tools/qfcc/test/quaternion.r +quaternion_obj=$(tools_qfcc_test_quaternion_dat_SOURCES:.r=.o) +quaternion_dep=$(call qcautodep,$(tools_qfcc_test_quaternion_dat_SOURCES)) +tools/qfcc/test/quaternion.dat$(EXEEXT): $(quaternion_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(quaternion_obj) +tools/qfcc/test/quaternion.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(quaternion_dep) # am--include-marker +r_depfiles_remade += $(quaternion_dep) + +tools_qfcc_test_return_ivar_dat_SOURCES=tools/qfcc/test/return-ivar.r +return_ivar_obj=$(tools_qfcc_test_return_ivar_dat_SOURCES:.r=.o) +return_ivar_dep=$(call qcautodep,$(tools_qfcc_test_return_ivar_dat_SOURCES)) +tools/qfcc/test/return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(return_ivar_obj) +tools/qfcc/test/return-ivar.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(return_ivar_dep) # am--include-marker +r_depfiles_remade += $(return_ivar_dep) + +tools_qfcc_test_sendv_dat_SOURCES=tools/qfcc/test/sendv.r +sendv_obj=$(tools_qfcc_test_sendv_dat_SOURCES:.r=.o) +sendv_dep=$(call qcautodep,$(tools_qfcc_test_sendv_dat_SOURCES)) +tools/qfcc/test/sendv.dat$(EXEEXT): $(sendv_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(sendv_obj) +tools/qfcc/test/sendv.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(sendv_dep) # am--include-marker +r_depfiles_remade += $(sendv_dep) + +tools_qfcc_test_state_dat_SOURCES=tools/qfcc/test/state.r +state_obj=$(tools_qfcc_test_state_dat_SOURCES:.r=.o) +state_dep=$(call qcautodep,$(tools_qfcc_test_state_dat_SOURCES)) +tools/qfcc/test/state.dat$(EXEEXT): $(state_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(state_obj) +tools/qfcc/test/state.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(state_dep) # am--include-marker +r_depfiles_remade += $(state_dep) + +tools_qfcc_test_struct_init_param_dat_SOURCES=tools/qfcc/test/struct-init-param.r +struct_init_param_obj=$(tools_qfcc_test_struct_init_param_dat_SOURCES:.r=.o) +struct_init_param_dep=$(call qcautodep,$(tools_qfcc_test_struct_init_param_dat_SOURCES)) +tools/qfcc/test/struct-init-param.dat$(EXEEXT): $(struct_init_param_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(struct_init_param_obj) +tools/qfcc/test/struct-init-param.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(struct_init_param_dep) # am--include-marker +r_depfiles_remade += $(struct_init_param_dep) + +tools_qfcc_test_struct_nil_init_dat_SOURCES=tools/qfcc/test/struct-nil-init.r +struct_nil_init_obj=$(tools_qfcc_test_struct_nil_init_dat_SOURCES:.r=.o) +struct_nil_init_dep=$(call qcautodep,$(tools_qfcc_test_struct_nil_init_dat_SOURCES)) +tools/qfcc/test/struct-nil-init.dat$(EXEEXT): $(struct_nil_init_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(struct_nil_init_obj) +tools/qfcc/test/struct-nil-init.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(struct_nil_init_dep) # am--include-marker +r_depfiles_remade += $(struct_nil_init_dep) + +tools_qfcc_test_structarray_dat_SOURCES=tools/qfcc/test/structarray.r +structarray_obj=$(tools_qfcc_test_structarray_dat_SOURCES:.r=.o) +structarray_dep=$(call qcautodep,$(tools_qfcc_test_structarray_dat_SOURCES)) +tools/qfcc/test/structarray.dat$(EXEEXT): $(structarray_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(structarray_obj) +tools/qfcc/test/structarray.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(structarray_dep) # am--include-marker +r_depfiles_remade += $(structarray_dep) + +tools_qfcc_test_structlive_dat_SOURCES=tools/qfcc/test/structlive.r +structlive_obj=$(tools_qfcc_test_structlive_dat_SOURCES:.r=.o) +structlive_dep=$(call qcautodep,$(tools_qfcc_test_structlive_dat_SOURCES)) +tools/qfcc/test/structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(structlive_obj) +tools/qfcc/test/structlive.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(structlive_dep) # am--include-marker +r_depfiles_remade += $(structlive_dep) + +tools_qfcc_test_structptr_dat_SOURCES=tools/qfcc/test/structptr.r +structptr_obj=$(tools_qfcc_test_structptr_dat_SOURCES:.r=.o) +structptr_dep=$(call qcautodep,$(tools_qfcc_test_structptr_dat_SOURCES)) +tools/qfcc/test/structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(structptr_obj) +tools/qfcc/test/structptr.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(structptr_dep) # am--include-marker +r_depfiles_remade += $(structptr_dep) + +tools_qfcc_test_structstruct_dat_SOURCES=tools/qfcc/test/structstruct.r +structstruct_obj=$(tools_qfcc_test_structstruct_dat_SOURCES:.r=.o) +structstruct_dep=$(call qcautodep,$(tools_qfcc_test_structstruct_dat_SOURCES)) +tools/qfcc/test/structstruct.dat$(EXEEXT): $(structstruct_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(structstruct_obj) +tools/qfcc/test/structstruct.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(structstruct_dep) # am--include-marker +r_depfiles_remade += $(structstruct_dep) + +tools_qfcc_test_swap_dat_SOURCES=tools/qfcc/test/swap.r +swap_obj=$(tools_qfcc_test_swap_dat_SOURCES:.r=.o) +swap_dep=$(call qcautodep,$(tools_qfcc_test_swap_dat_SOURCES)) +tools/qfcc/test/swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(swap_obj) +tools/qfcc/test/swap.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(swap_dep) # am--include-marker +r_depfiles_remade += $(swap_dep) + +tools_qfcc_test_triangle_dat_SOURCES=tools/qfcc/test/triangle.r +triangle_obj=$(tools_qfcc_test_triangle_dat_SOURCES:.r=.o) +triangle_dep=$(call qcautodep,$(tools_qfcc_test_triangle_dat_SOURCES)) +tools/qfcc/test/triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) +tools/qfcc/test/triangle.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ 100000 100000 1.00005 50002.4961 +include $(triangle_dep) # am--include-marker +r_depfiles_remade += $(triangle_dep) + +tools_qfcc_test_typedef_dat_SOURCES=tools/qfcc/test/typedef.r +typedef_obj=$(tools_qfcc_test_typedef_dat_SOURCES:.r=.o) +typedef_dep=$(call qcautodep,$(tools_qfcc_test_typedef_dat_SOURCES)) +tools/qfcc/test/typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) +tools/qfcc/test/typedef.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(typedef_dep) # am--include-marker +r_depfiles_remade += $(typedef_dep) + +tools_qfcc_test_typelinker_dat_SOURCES=tools/qfcc/test/typelinker_a.r tools/qfcc/test/typelinker_b.r +typelinker_obj=$(tools_qfcc_test_typelinker_dat_SOURCES:.r=.o) +typelinker_dep=$(call qcautodep,$(tools_qfcc_test_typelinker_dat_SOURCES)) +tools/qfcc/test/typelinker.dat$(EXEEXT): $(typelinker_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(typelinker_obj) +tools/qfcc/test/typelinker.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(typelinker_dep) # am--include-marker +r_depfiles_remade += $(typelinker_dep) + +tools_qfcc_test_unaryminus_dat_SOURCES=tools/qfcc/test/unaryminus.r +unaryminus_obj=$(tools_qfcc_test_unaryminus_dat_SOURCES:.r=.o) +unaryminus_dep=$(call qcautodep,$(tools_qfcc_test_unaryminus_dat_SOURCES)) +tools/qfcc/test/unaryminus.dat$(EXEEXT): $(unaryminus_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(unaryminus_obj) +tools/qfcc/test/unaryminus.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(unaryminus_dep) # am--include-marker +r_depfiles_remade += $(unaryminus_dep) + +tools_qfcc_test_vecaddr_dat_SOURCES=tools/qfcc/test/vecaddr.r +vecaddr_obj=$(tools_qfcc_test_vecaddr_dat_SOURCES:.r=.o) +vecaddr_dep=$(call qcautodep,$(tools_qfcc_test_vecaddr_dat_SOURCES)) +tools/qfcc/test/vecaddr.dat$(EXEEXT): $(vecaddr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(vecaddr_obj) +tools/qfcc/test/vecaddr.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(vecaddr_dep) # am--include-marker +r_depfiles_remade += $(vecaddr_dep) + +tools_qfcc_test_vecexpr_dat_SOURCES=tools/qfcc/test/vecexpr.r +vecexpr_obj=$(tools_qfcc_test_vecexpr_dat_SOURCES:.r=.o) +vecexpr_dep=$(call qcautodep,$(tools_qfcc_test_vecexpr_dat_SOURCES)) +tools/qfcc/test/vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(vecexpr_obj) +tools/qfcc/test/vecexpr.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(vecexpr_dep) # am--include-marker +r_depfiles_remade += $(vecexpr_dep) + +tools_qfcc_test_vecinit_dat_SOURCES=tools/qfcc/test/vecinit.r +vecinit_obj=$(tools_qfcc_test_vecinit_dat_SOURCES:.r=.o) +vecinit_dep=$(call qcautodep,$(tools_qfcc_test_vecinit_dat_SOURCES)) +tools/qfcc/test/vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(vecinit_obj) +tools/qfcc/test/vecinit.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(vecinit_dep) # am--include-marker +r_depfiles_remade += $(vecinit_dep) + +tools_qfcc_test_voidfor_dat_SOURCES=tools/qfcc/test/voidfor.r +voidfor_obj=$(tools_qfcc_test_voidfor_dat_SOURCES:.r=.o) +voidfor_dep=$(call qcautodep,$(tools_qfcc_test_voidfor_dat_SOURCES)) +tools/qfcc/test/voidfor.dat$(EXEEXT): $(voidfor_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj) +tools/qfcc/test/voidfor.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(voidfor_dep) # am--include-marker +r_depfiles_remade += $(voidfor_dep) + +tools_qfcc_test_while_dat_SOURCES=tools/qfcc/test/while.r +while_obj=$(tools_qfcc_test_while_dat_SOURCES:.r=.o) +while_dep=$(call qcautodep,$(tools_qfcc_test_while_dat_SOURCES)) +tools/qfcc/test/while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(while_obj) +tools/qfcc/test/while.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(while_dep) # am--include-marker +r_depfiles_remade += $(while_dep) + +tools_qfcc_test_zerolinker_dat_SOURCES=tools/qfcc/test/zerolinker.r +zerolinker_obj=$(tools_qfcc_test_zerolinker_dat_SOURCES:.r=.o) +zerolinker_dep=$(call qcautodep,$(tools_qfcc_test_zerolinker_dat_SOURCES)) +tools/qfcc/test/zerolinker.dat$(EXEEXT): $(zerolinker_obj) $(QFCC_DEP) + $(QFCC) $(QCFLAGS) -o $@ $(zerolinker_obj) +tools/qfcc/test/zerolinker.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(zerolinker_dep) # am--include-marker +r_depfiles_remade += $(zerolinker_dep) + +EXTRA_DIST += \ + $(test_build_errors) \ + tools/qfcc/test/build-compile-fail-run \ + tools/qfcc/test/test-bi.h \ + tools/qfcc/test/build-run \ + tools/qfcc/test/test-defspace.h \ + tools/qfcc/test/test-harness.h \ + tools/qfcc/test/typelinker.h + +CLEANFILES += \ + tools/qfcc/test/*.dat \ + tools/qfcc/test/*.sym \ + tools/qfcc/test/*.run \ + tools/qfcc/test/*.frame \ + tools/qfcc/test/*.log \ + tools/qfcc/test/*.trs diff --git a/tools/qfcc/test/build-run b/tools/qfcc/test/build-run index 577355a80..b93854bf9 100755 --- a/tools/qfcc/test/build-run +++ b/tools/qfcc/test/build-run @@ -1,11 +1,11 @@ #! /bin/sh script=$1 -progs=`basename $script .run`.dat +progs=tools/qfcc/test/`basename $script .run`.dat shift cat > $script < #include -#include "class.h" -#include "expr.h" -#include "function.h" -#include "options.h" -#include "strpool.h" -#include "qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/qfcc.h" -#include "test-defspace.h" +#include "tools/qfcc/test/test-defspace.h" options_t options; pr_info_t pr; diff --git a/tools/qfcc/test/test-defspace.h b/tools/qfcc/test/test-defspace.h index 1735003bf..ab6fcd1e8 100644 --- a/tools/qfcc/test/test-defspace.h +++ b/tools/qfcc/test/test-defspace.h @@ -1,5 +1,5 @@ -#include "def.h" -#include "defspace.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" int def_list_is_empty (const defspace_t *space); int def_list_is_valid (const defspace_t *space); diff --git a/tools/qflight/Makefile.am b/tools/qflight/Makefile.am deleted file mode 100644 index e4102a7e9..000000000 --- a/tools/qflight/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= include source - -man_MANS= qflight.1 - -EXTRA_DIST= qflight.1 diff --git a/tools/qflight/Makemodule.am b/tools/qflight/Makemodule.am new file mode 100644 index 000000000..cd4d971c6 --- /dev/null +++ b/tools/qflight/Makemodule.am @@ -0,0 +1,4 @@ +include tools/qflight/include/Makemodule.am +include tools/qflight/source/Makemodule.am + +man_MANS += tools/qflight/qflight.1 diff --git a/tools/qflight/include/Makefile.am b/tools/qflight/include/Makefile.am deleted file mode 100644 index 3d7e10861..000000000 --- a/tools/qflight/include/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST= entities.h light.h noise.h options.h properties.h threads.h diff --git a/tools/qflight/include/Makemodule.am b/tools/qflight/include/Makemodule.am new file mode 100644 index 000000000..747bdca73 --- /dev/null +++ b/tools/qflight/include/Makemodule.am @@ -0,0 +1,7 @@ +EXTRA_DIST += \ + tools/qflight/include/entities.h \ + tools/qflight/include/light.h \ + tools/qflight/include/noise.h \ + tools/qflight/include/options.h \ + tools/qflight/include/properties.h \ + tools/qflight/include/threads.h diff --git a/tools/qflight/source/Makefile.am b/tools/qflight/source/Makefile.am deleted file mode 100644 index cdf5005fb..000000000 --- a/tools/qflight/source/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -QFLIGHT_LIBS=@QFLIGHT_LIBS@ -QFLIGHT_DEPS=@QFLIGHT_DEPS@ -QFLIGHT_INCS=@QFLIGHT_INCS@ -PTHREAD_LDFLAGS=@PTHREAD_LDFLAGS@ -PTHREAD_CFLAGS=@PTHREAD_CFLAGS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(QFLIGHT_INCS) $(PTHREAD_CFLAGS) - -bin_PROGRAMS= qflight - -qflight_SOURCES=\ - entities.c ltface.c noise.c options.c properties.c qflight.c \ - threads.c trace.c vis.c - - -qflight_LDFLAGS= $(PTHREAD_LDFLAGS) -qflight_LDADD= $(QFLIGHT_LIBS) -qflight_DEPENDENCIES= $(QFLIGHT_DEPS) diff --git a/tools/qflight/source/Makemodule.am b/tools/qflight/source/Makemodule.am new file mode 100644 index 000000000..0913e37a8 --- /dev/null +++ b/tools/qflight/source/Makemodule.am @@ -0,0 +1,20 @@ +QFLIGHT_LIBS=@QFLIGHT_LIBS@ +QFLIGHT_DEPS=@QFLIGHT_DEPS@ +QFLIGHT_INCS=@QFLIGHT_INCS@ + +bin_PROGRAMS += qflight + +qflight_SOURCES=\ + tools/qflight/source/entities.c \ + tools/qflight/source/ltface.c \ + tools/qflight/source/noise.c \ + tools/qflight/source/options.c \ + tools/qflight/source/properties.c \ + tools/qflight/source/qflight.c \ + tools/qflight/source/threads.c \ + tools/qflight/source/trace.c \ + tools/qflight/source/vis.c + +qflight_LDFLAGS= $(PTHREAD_LDFLAGS) +qflight_LDADD= $(QFLIGHT_LIBS) +qflight_DEPENDENCIES= $(QFLIGHT_DEPS) diff --git a/tools/qflight/source/entities.c b/tools/qflight/source/entities.c index 01c36077c..c9d262356 100644 --- a/tools/qflight/source/entities.c +++ b/tools/qflight/source/entities.c @@ -55,11 +55,11 @@ #include "QF/sys.h" #include "QF/va.h" -#include "light.h" -#include "threads.h" -#include "entities.h" -#include "options.h" -#include "properties.h" +#include "tools/qflight/include/light.h" +#include "tools/qflight/include/threads.h" +#include "tools/qflight/include/entities.h" +#include "tools/qflight/include/options.h" +#include "tools/qflight/include/properties.h" entity_t *entities; int num_entities; diff --git a/tools/qflight/source/ltface.c b/tools/qflight/source/ltface.c index 1864b7746..2b8eb1953 100644 --- a/tools/qflight/source/ltface.c +++ b/tools/qflight/source/ltface.c @@ -52,11 +52,11 @@ #include "compat.h" -#include "light.h" -#include "entities.h" -#include "noise.h" -#include "options.h" -#include "threads.h" +#include "tools/qflight/include/light.h" +#include "tools/qflight/include/entities.h" +#include "tools/qflight/include/noise.h" +#include "tools/qflight/include/options.h" +#include "tools/qflight/include/threads.h" int c_bad; int c_culldistplane, c_proper; diff --git a/tools/qflight/source/noise.c b/tools/qflight/source/noise.c index 8d8a87758..b34e31ee1 100644 --- a/tools/qflight/source/noise.c +++ b/tools/qflight/source/noise.c @@ -35,7 +35,7 @@ #include "QF/qtypes.h" -#include "noise.h" +#include "tools/qflight/include/noise.h" // returns the 3D noise value for a point in space float diff --git a/tools/qflight/source/options.c b/tools/qflight/source/options.c index 88a3584b9..b50753169 100644 --- a/tools/qflight/source/options.c +++ b/tools/qflight/source/options.c @@ -44,9 +44,9 @@ #include "compat.h" -#include "entities.h" -#include "options.h" -#include "properties.h" +#include "tools/qflight/include/entities.h" +#include "tools/qflight/include/options.h" +#include "tools/qflight/include/properties.h" const char *this_program; diff --git a/tools/qflight/source/properties.c b/tools/qflight/source/properties.c index 5cf957b7f..e7774f6d4 100644 --- a/tools/qflight/source/properties.c +++ b/tools/qflight/source/properties.c @@ -46,10 +46,10 @@ #include "compat.h" -#include "entities.h" -#include "light.h" -#include "options.h" -#include "properties.h" +#include "tools/qflight/include/entities.h" +#include "tools/qflight/include/light.h" +#include "tools/qflight/include/options.h" +#include "tools/qflight/include/properties.h" static plitem_t *properties; diff --git a/tools/qflight/source/qflight.c b/tools/qflight/source/qflight.c index 62eda9af1..4d2acfb73 100644 --- a/tools/qflight/source/qflight.c +++ b/tools/qflight/source/qflight.c @@ -53,11 +53,11 @@ #include "QF/sys.h" #include "QF/va.h" -#include "light.h" -#include "threads.h" -#include "entities.h" -#include "options.h" -#include "properties.h" +#include "tools/qflight/include/light.h" +#include "tools/qflight/include/threads.h" +#include "tools/qflight/include/entities.h" +#include "tools/qflight/include/options.h" +#include "tools/qflight/include/properties.h" options_t options; bsp_t *bsp; diff --git a/tools/qflight/source/threads.c b/tools/qflight/source/threads.c index 50e2709a0..8438f7b8e 100644 --- a/tools/qflight/source/threads.c +++ b/tools/qflight/source/threads.c @@ -46,9 +46,9 @@ #include "QF/qtypes.h" #include "QF/qendian.h" -#include "light.h" -#include "options.h" -#include "threads.h" +#include "tools/qflight/include/light.h" +#include "tools/qflight/include/options.h" +#include "tools/qflight/include/threads.h" #if defined (HAVE_PTHREAD_H) && defined (HAVE_PTHREAD) pthread_mutex_t *my_mutex; diff --git a/tools/qflight/source/trace.c b/tools/qflight/source/trace.c index 0f9df661e..aa5b4ce19 100644 --- a/tools/qflight/source/trace.c +++ b/tools/qflight/source/trace.c @@ -50,8 +50,8 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "light.h" -#include "options.h" +#include "tools/qflight/include/light.h" +#include "tools/qflight/include/options.h" typedef struct { int type; diff --git a/tools/qflight/source/vis.c b/tools/qflight/source/vis.c index e8267146c..a4f0e1114 100644 --- a/tools/qflight/source/vis.c +++ b/tools/qflight/source/vis.c @@ -47,10 +47,10 @@ #include "QF/bspfile.h" #include "QF/mathlib.h" -#include "entities.h" -#include "light.h" -#include "options.h" -#include "threads.h" +#include "tools/qflight/include/entities.h" +#include "tools/qflight/include/light.h" +#include "tools/qflight/include/options.h" +#include "tools/qflight/include/threads.h" static struct { int empty; diff --git a/tools/qflmp/Makefile.am b/tools/qflmp/Makefile.am deleted file mode 100644 index b9436172c..000000000 --- a/tools/qflmp/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -QFLMP_LIBS=@QFLMP_LIBS@ -QFLMP_DEPS=@QFLMP_DEPS@ -QFLMP_INCS=@QFLMP_INCS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(QFLMP_INCS) - -bin_PROGRAMS= qflmp - -#mans=qflmp.1 -man_MANS= $(mans) - -qflmp_SOURCES= lmp.c -qflmp_LDADD= $(QFLMP_LIBS) -qflmp_DEPENDENCIES= $(QFLMP_DEPS) - -EXTRA_DIST= lmp.h #lmp.1 diff --git a/tools/qflmp/Makemodule.am b/tools/qflmp/Makemodule.am new file mode 100644 index 000000000..78dd3a233 --- /dev/null +++ b/tools/qflmp/Makemodule.am @@ -0,0 +1,14 @@ +QFLMP_LIBS=@QFLMP_LIBS@ +QFLMP_DEPS=@QFLMP_DEPS@ +QFLMP_INCS=@QFLMP_INCS@ + +bin_PROGRAMS += qflmp + +#mans=qflmp.1 +man_MANS += $(mans) + +qflmp_SOURCES= tools/qflmp/lmp.c +qflmp_LDADD= $(QFLMP_LIBS) +qflmp_DEPENDENCIES= $(QFLMP_DEPS) + +EXTRA_DIST += tools/qflmp/lmp.h #lmp.1 diff --git a/tools/qfmodelgen/Makefile.am b/tools/qfmodelgen/Makefile.am deleted file mode 100644 index e5b93df89..000000000 --- a/tools/qfmodelgen/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= include source - -#man_MANS= qfmodelgen.1 - -#EXTRA_DIST= $(man_MANS) diff --git a/tools/qfmodelgen/Makemodule.am b/tools/qfmodelgen/Makemodule.am new file mode 100644 index 000000000..d397b4f91 --- /dev/null +++ b/tools/qfmodelgen/Makemodule.am @@ -0,0 +1,2 @@ +include tools/qfmodelgen/include/Makemodule.am +include tools/qfmodelgen/source/Makemodule.am diff --git a/tools/qfmodelgen/include/Makefile.am b/tools/qfmodelgen/include/Makefile.am deleted file mode 100644 index c4cc81268..000000000 --- a/tools/qfmodelgen/include/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST= lbmlib.h trilib.h diff --git a/tools/qfmodelgen/include/Makemodule.am b/tools/qfmodelgen/include/Makemodule.am new file mode 100644 index 000000000..0a5f0306d --- /dev/null +++ b/tools/qfmodelgen/include/Makemodule.am @@ -0,0 +1,3 @@ +EXTRA_DIST += \ + tools/qfmodelgen/include/lbmlib.h \ + tools/qfmodelgen/include/trilib.h diff --git a/tools/qfmodelgen/source/Makefile.am b/tools/qfmodelgen/source/Makemodule.am similarity index 54% rename from tools/qfmodelgen/source/Makefile.am rename to tools/qfmodelgen/source/Makemodule.am index 4bc3a0bda..9ca6ae7ef 100644 --- a/tools/qfmodelgen/source/Makefile.am +++ b/tools/qfmodelgen/source/Makemodule.am @@ -1,14 +1,13 @@ -AUTOMAKE_OPTIONS= foreign - QFMODELGEN_LIBS=@QFMODELGEN_LIBS@ QFMODELGEN_DEPS=@QFMODELGEN_DEPS@ QFMODELGEN_INCS=@QFMODELGEN_INCS@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(QFMODELGEN_INCS) +bin_PROGRAMS += qfmodelgen -bin_PROGRAMS= qfmodelgen - -qfmodelgen_SOURCES= lbmlib.c modelgen.c trilib.c +qfmodelgen_SOURCES = \ + tools/qfmodelgen/source/lbmlib.c \ + tools/qfmodelgen/source/modelgen.c \ + tools/qfmodelgen/source/trilib.c qfmodelgen_LDADD= $(QFMODELGEN_LIBS) qfmodelgen_DEPENDENCIES= $(QFMODELGEN_DEPS) diff --git a/tools/qfmodelgen/source/lbmlib.c b/tools/qfmodelgen/source/lbmlib.c index 77af86e92..1650bda86 100644 --- a/tools/qfmodelgen/source/lbmlib.c +++ b/tools/qfmodelgen/source/lbmlib.c @@ -30,7 +30,7 @@ #include "QF/quakeio.h" #include "QF/sys.h" -#include "lbmlib.h" +#include "tools/qfmodelgen/include/lbmlib.h" static int LoadFile (const char *fname, byte **buf) diff --git a/tools/qfmodelgen/source/modelgen.c b/tools/qfmodelgen/source/modelgen.c index 4905ad041..5d3eee4d0 100644 --- a/tools/qfmodelgen/source/modelgen.c +++ b/tools/qfmodelgen/source/modelgen.c @@ -45,10 +45,11 @@ #include "QF/script.h" #include "QF/sys.h" -#include "lbmlib.h" -#include "trilib.h" #include "compat.h" +#include "tools/qfmodelgen/include/lbmlib.h" +#include "tools/qfmodelgen/include/trilib.h" + #define MAXVERTS 2048 #define MAXFRAMES 256 #define MAXSKINS 100 diff --git a/tools/qfmodelgen/source/trilib.c b/tools/qfmodelgen/source/trilib.c index 41f6ffd42..a22721192 100644 --- a/tools/qfmodelgen/source/trilib.c +++ b/tools/qfmodelgen/source/trilib.c @@ -31,7 +31,7 @@ #include "QF/quakeio.h" #include "QF/sys.h" -#include "trilib.h" +#include "tools/qfmodelgen/include/trilib.h" // on disk representation of a face diff --git a/tools/qfspritegen/Makefile.am b/tools/qfspritegen/Makemodule.am similarity index 57% rename from tools/qfspritegen/Makefile.am rename to tools/qfspritegen/Makemodule.am index 05f321022..a12777453 100644 --- a/tools/qfspritegen/Makefile.am +++ b/tools/qfspritegen/Makemodule.am @@ -1,14 +1,10 @@ -AUTOMAKE_OPTIONS= foreign - QFSPRITEGEN_LIBS=@QFSPRITEGEN_LIBS@ QFSPRITEGEN_DEPS=@QFSPRITEGEN_DEPS@ QFSPRITEGEN_INCS=@QFSPRITEGEN_INCS@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(QFSPRITEGEN_INCS) +bin_PROGRAMS += qfspritegen -bin_PROGRAMS= qfspritegen - -qfspritegen_SOURCES= spritegen.c +qfspritegen_SOURCES= tools/qfspritegen/spritegen.c qfspritegen_LDADD= $(QFSPRITEGEN_LIBS) qfspritegen_DEPENDENCIES= $(QFSPRITEGEN_DEPS) diff --git a/tools/qfvis/Makefile.am b/tools/qfvis/Makefile.am deleted file mode 100644 index 52a798c6e..000000000 --- a/tools/qfvis/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -SUBDIRS= include source - -mans=qfvis.1 -man_MANS= $(mans) -EXTRA_DIST= $(mans) diff --git a/tools/qfvis/Makemodule.am b/tools/qfvis/Makemodule.am new file mode 100644 index 000000000..5840ea1f6 --- /dev/null +++ b/tools/qfvis/Makemodule.am @@ -0,0 +1,4 @@ +include tools/qfvis/include/Makemodule.am +include tools/qfvis/source/Makemodule.am + +man_MANS += tools/qfvis/qfvis.1 diff --git a/tools/qfvis/include/Makefile.am b/tools/qfvis/include/Makefile.am deleted file mode 100644 index 0bbb6480b..000000000 --- a/tools/qfvis/include/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -EXTRA_DIST= options.h vis.h diff --git a/tools/qfvis/include/Makemodule.am b/tools/qfvis/include/Makemodule.am new file mode 100644 index 000000000..eec0af5b0 --- /dev/null +++ b/tools/qfvis/include/Makemodule.am @@ -0,0 +1,3 @@ +EXTRA_DIST += \ + tools/qfvis/include/options.h \ + tools/qfvis/include/vis.h diff --git a/tools/qfvis/source/Makefile.am b/tools/qfvis/source/Makefile.am deleted file mode 100644 index e0a725ca0..000000000 --- a/tools/qfvis/source/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -QFVIS_LIBS=@QFVIS_LIBS@ -QFVIS_DEPS=@QFVIS_DEPS@ -QFVIS_INCS=@QFVIS_INCS@ -PTHREAD_LDFLAGS=@PTHREAD_LDFLAGS@ -PTHREAD_CFLAGS=@PTHREAD_CFLAGS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(QFVIS_INCS) $(PTHREAD_CFLAGS) - -bin_PROGRAMS= qfvis - -qfvis_SOURCES= base-vis.c flow.c options.c qfvis.c soundphs.c - -qfvis_LDFLAGS= $(PTHREAD_LDFLAGS) -qfvis_LDADD= $(QFVIS_LIBS) -qfvis_DEPENDENCIES= $(QFVIS_DEPS) diff --git a/tools/qfvis/source/Makemodule.am b/tools/qfvis/source/Makemodule.am new file mode 100644 index 000000000..73ccf547e --- /dev/null +++ b/tools/qfvis/source/Makemodule.am @@ -0,0 +1,16 @@ +QFVIS_LIBS=@QFVIS_LIBS@ +QFVIS_DEPS=@QFVIS_DEPS@ +QFVIS_INCS=@QFVIS_INCS@ + +bin_PROGRAMS += qfvis + +qfvis_SOURCES = \ + tools/qfvis/source/base-vis.c \ + tools/qfvis/source/flow.c \ + tools/qfvis/source/options.c \ + tools/qfvis/source/qfvis.c \ + tools/qfvis/source/soundphs.c + +qfvis_LDFLAGS= $(PTHREAD_LDFLAGS) +qfvis_LDADD= $(QFVIS_LIBS) +qfvis_DEPENDENCIES= $(QFVIS_DEPS) diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index ca4d912e0..99d5934df 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -54,8 +54,8 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "vis.h" -#include "options.h" +#include "tools/qfvis/include/vis.h" +#include "tools/qfvis/include/options.h" /* This is a rough first-order aproximation that is used to trivially reject diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 15af6524f..030ca7a43 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -55,8 +55,8 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "vis.h" -#include "options.h" +#include "tools/qfvis/include/vis.h" +#include "tools/qfvis/include/options.h" static int CheckStack (cluster_t *cluster, threaddata_t *thread) diff --git a/tools/qfvis/source/options.c b/tools/qfvis/source/options.c index 048f604b0..d9a5e3691 100644 --- a/tools/qfvis/source/options.c +++ b/tools/qfvis/source/options.c @@ -41,8 +41,8 @@ #include "QF/dstring.h" -#include "options.h" -#include "vis.h" +#include "tools/qfvis/include/options.h" +#include "tools/qfvis/include/vis.h" const char *this_program; diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 8c2cc6ed3..9ffb09e35 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -57,8 +57,8 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "vis.h" -#include "options.h" +#include "tools/qfvis/include/vis.h" +#include "tools/qfvis/include/options.h" #ifdef USE_PTHREADS pthread_attr_t threads_attrib; diff --git a/tools/qfvis/source/soundphs.c b/tools/qfvis/source/soundphs.c index 086e453cc..f21a9390d 100644 --- a/tools/qfvis/source/soundphs.c +++ b/tools/qfvis/source/soundphs.c @@ -54,7 +54,7 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "vis.h" +#include "tools/qfvis/include/vis.h" /* Some textures (sky, water, slime, lava) are considered ambient sound diff --git a/tools/wad/Makefile.am b/tools/wad/Makefile.am deleted file mode 100644 index 7db82d273..000000000 --- a/tools/wad/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -WAD_LIBS=@WAD_LIBS@ -WAD_DEPS=@WAD_DEPS@ -WAD_INCS=@WAD_INCS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(WAD_INCS) - - -bin_PROGRAMS= wad - -mans=wad.1 -man_MANS= $(mans) - -wad_SOURCES= grab.c script.c wad.c -wad_LDADD= $(WAD_LIBS) -wad_DEPENDENCIES= $(WAD_DEPS) - -EXTRA_DIST= wad.h $(mans) diff --git a/tools/wad/Makemodule.am b/tools/wad/Makemodule.am new file mode 100644 index 000000000..dd68d6842 --- /dev/null +++ b/tools/wad/Makemodule.am @@ -0,0 +1,13 @@ +WAD_LIBS=@WAD_LIBS@ +WAD_DEPS=@WAD_DEPS@ +WAD_INCS=@WAD_INCS@ + +bin_PROGRAMS += wad + +man_MANS += tools/wad/wad.1 + +wad_SOURCES= tools/wad/grab.c tools/wad/script.c tools/wad/wad.c +wad_LDADD= $(WAD_LIBS) +wad_DEPENDENCIES= $(WAD_DEPS) + +EXTRA_DIST += tools/wad/wad.h diff --git a/tools/wav/Makefile.am b/tools/wav/Makefile.am deleted file mode 100644 index 7e17fe376..000000000 --- a/tools/wav/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -WAV_LIBS=@WAV_LIBS@ -WAV_DEPS=@WAV_DEPS@ -WAV_INCS=@WAV_INCS@ - -AM_CPPFLAGS= -I$(top_srcdir)/include $(WAV_INCS) - -bin_PROGRAMS= qfwavinfo - -mans=qfwavinfo.1 -man_MANS= #$(mans) - -qfwavinfo_SOURCES= qfwavinfo.c -qfwavinfo_LDADD= $(WAV_LIBS) -qfwavinfo_DEPENDENCIES= $(WAV_DEPS) - -EXTRA_DIST=#$(mans) diff --git a/tools/wav/Makemodule.am b/tools/wav/Makemodule.am new file mode 100644 index 000000000..4a4726809 --- /dev/null +++ b/tools/wav/Makemodule.am @@ -0,0 +1,11 @@ +WAV_LIBS=@WAV_LIBS@ +WAV_DEPS=@WAV_DEPS@ +WAV_INCS=@WAV_INCS@ + +bin_PROGRAMS += qfwavinfo + +#man_MANS += tools/wav/qfwavinfo.1 + +qfwavinfo_SOURCES= tools/wav/qfwavinfo.c +qfwavinfo_LDADD= $(WAV_LIBS) +qfwavinfo_DEPENDENCIES= $(WAV_DEPS) diff --git a/vc2005/Makefile.am b/vc2005/Makefile.am deleted file mode 100644 index 7f616ef19..000000000 --- a/vc2005/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign -EXTRA_DIST = \ - Makefile.am QuakeForge-VS8-Express.sln QuakeForge-VS8.sln \ - bsp2img/bsp2img.vcproj builtins/builtins.vcproj clean.ps1 \ - common/common.vcproj console/console.vcproj \ - console_client/console_client.vcproj console_server/console_server.vcproj \ - engine/engine.vcproj gib/gib.vcproj hw-master/hw-master.vcproj \ - image/image.vcproj include/config.h models-sw/models-sw.vcproj \ - models/models.vcproj modelsgl/modelsgl.vcproj net-main/net-main.vcproj \ - net/net.vcproj nq-common/nq-common.vcproj nq-sdl/nq-sdl.vcproj \ - nq-sdl32/nq-sdl32.vcproj nq-server/nq-server.vcproj nq-sgl/nq-sgl.vcproj \ - nq-wgl/nq-wgl.vcproj nq/nq.vcproj pak/pak.vcproj qfbsp/qfbsp.vcproj \ - qfcc/FlexBison.rules qfcc/qfcc.vcproj qfclient/qfclient.vcproj \ - qflight/qflight.vcproj qfmodelgen/qfmodelgen.vcproj \ - qfprogs/qfprogs.vcproj qfserver/qfserver.vcproj qfvis/qfvis.vcproj \ - qfwavinfo/qfwavinfo.vcproj qtv/qtv.vcproj \ - qw-client-sdl/qw-client-sdl.vcproj qw-client-sdl32/qw-client-sdl32.vcproj \ - qw-client-sgl/qw-client-sgl.vcproj qw-client-wgl/qw-client-wgl.vcproj \ - qw-master/qw-master.vcproj qw/qw.vcproj readme.txt ruamoko/ruamoko.vcproj \ - sound/sound.vcproj util/util.vcproj video-sdl/video-sdl.vcproj \ - video-sgl/video-sgl.vcproj video-sw/video-sw.vcproj \ - video-sw32/video-sw32.vcproj video-wgl/video-wgl.vcproj \ - video/video.vcproj videogl/videogl.vcproj wad/wad.vcproj diff --git a/vc2005/QuakeForge-VS8-Express.sln b/vc2005/QuakeForge-VS8-Express.sln deleted file mode 100644 index 404f35ff4..000000000 --- a/vc2005/QuakeForge-VS8-Express.sln +++ /dev/null @@ -1,935 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client", "qfclient\qfclient.vcproj", "{9A942925-61E6-4975-935A-5D62E8248E64}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw", "qw\qw.vcproj", "{6ADA4322-693A-46BB-897B-17BB5BE9F08C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "net-chan", "net\net.vcproj", "{6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ruamoko", "ruamoko\ruamoko.vcproj", "{51028ACF-53D4-4478-8500-55E6B8A81375}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models-gl", "modelsgl\modelsgl.vcproj", "{1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console", "console\console.vcproj", "{ED4AFBF5-C247-4352-966D-048B8998C6A1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gib", "gib\gib.vcproj", "{01C3B138-9D45-4ED6-A763-893C067262C2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "util", "util\util.vcproj", "{ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine", "engine\engine.vcproj", "{2626C0E1-6F5C-47D3-B80D-93942D766DD7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "builtins", "builtins\builtins.vcproj", "{04FA9D77-E45F-4917-B972-B353BA6A6FA8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sound", "sound\sound.vcproj", "{BF149D97-7520-4788-9CD1-3D99C5C8150F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "image", "image\image.vcproj", "{5203F034-0047-4EC0-B7E9-D037FAF5D536}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video", "video\video.vcproj", "{E7B3D07D-2FE8-481B-8DAB-6255A412A42F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-common", "common\common.vcproj", "{BC1F021A-1EEC-4A7A-B746-5AA6048E478C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-server", "qfserver\qfserver.vcproj", "{544D097C-9C24-4C57-A171-8C8029421185}" - ProjectSection(ProjectDependencies) = postProject - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} = {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models", "models\models.vcproj", "{DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console-client", "console_client\console_client.vcproj", "{226D42CE-5833-444E-94FA-84C1D51892A8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console-server", "console_server\console_server.vcproj", "{B37FE734-01F4-4799-86B2-D084820715BE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfbsp", "qfbsp\qfbsp.vcproj", "{B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qflight", "qflight\qflight.vcproj", "{5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfvis", "qfvis\qfvis.vcproj", "{E5D842C5-669F-4FC7-A5E0-44B562F86435}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-master", "qw-master\qw-master.vcproj", "{445A2500-3BBC-449A-A929-C419C2A16051}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfmodelgen", "qfmodelgen\qfmodelgen.vcproj", "{052C34FE-C9E2-43ED-95DA-FB3F27B44E37}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfprogs", "qfprogs\qfprogs.vcproj", "{5FA27C8E-51B1-445A-A375-FBE74F0984B1}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfwavinfo", "qfwavinfo\qfwavinfo.vcproj", "{56BD559B-1590-4FC4-B441-AB1973BAC2BD}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wad", "wad\wad.vcproj", "{88422448-C5FB-46F3-A0B3-0811F90E537C}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pak", "pak\pak.vcproj", "{9EE8BD4B-47D3-4AD5-A8B9-831329792A05}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bsp2img", "bsp2img\bsp2img.vcproj", "{4605418D-2292-470A-AB18-C2119B016F71}" - ProjectSection(ProjectDependencies) = postProject - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtv", "qtv\qtv.vcproj", "{05E68E3B-5901-43A9-981D-CF392C0F5C6C}" - ProjectSection(ProjectDependencies) = postProject - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-common", "nq-common\nq-common.vcproj", "{6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-wgl", "nq-wgl\nq-wgl.vcproj", "{1CD1A18B-95D5-4EA4-917C-34B10066BFCC}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} = {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "net-main", "net-main\net-main.vcproj", "{053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-server", "nq-server\nq-server.vcproj", "{231C032C-DE16-459A-8E7D-6509C2EC3998}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} = {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hw-master", "hw-master\hw-master.vcproj", "{419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}" - ProjectSection(ProjectDependencies) = postProject - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfcc", "qfcc\qfcc.vcproj", "{40639893-4D75-48CD-811F-4B363CC71FFA}" - ProjectSection(ProjectDependencies) = postProject - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-wgl", "qw-client-wgl\qw-client-wgl.vcproj", "{5FD733BF-B3C6-4A96-BED7-35E2484448E1}" - ProjectSection(ProjectDependencies) = postProject - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} = {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-sgl", "qw-client-sgl\qw-client-sgl.vcproj", "{649C4168-1C65-4E41-818F-85A1C52C1B8F}" - ProjectSection(ProjectDependencies) = postProject - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {7E30C3B1-AEE7-483D-B231-C672365CD2D7} = {7E30C3B1-AEE7-483D-B231-C672365CD2D7} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-gl", "videogl\videogl.vcproj", "{C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sdl", "video-sdl\video-sdl.vcproj", "{44A18410-3AA8-4A64-935B-D20223AD6885}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-sdl", "qw-client-sdl\qw-client-sdl.vcproj", "{B44CB3E0-F2FD-4260-A632-C01FB881613E}" - ProjectSection(ProjectDependencies) = postProject - {66D3A191-E4D5-45F3-86BD-EFBB249CD554} = {66D3A191-E4D5-45F3-86BD-EFBB249CD554} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models-sw", "models-sw\models-sw.vcproj", "{F4A9881E-0EB0-44A1-9664-B6CBDE992861}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sw", "video-sw\video-sw.vcproj", "{66D3A191-E4D5-45F3-86BD-EFBB249CD554}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-sdl32", "qw-client-sdl32\qw-client-sdl32.vcproj", "{CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}" - ProjectSection(ProjectDependencies) = postProject - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {D5B9558F-EF25-4167-ACE4-723C7413B390} = {D5B9558F-EF25-4167-ACE4-723C7413B390} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sw32", "video-sw32\video-sw32.vcproj", "{D5B9558F-EF25-4167-ACE4-723C7413B390}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq", "nq\nq.vcproj", "{155112B9-A8A9-4E06-90F5-4AAAB32B2F70}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-wgl", "video-wgl\video-wgl.vcproj", "{178D81A7-F2FB-41D7-B300-9D1A4DE5E137}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sgl", "video-sgl\video-sgl.vcproj", "{7E30C3B1-AEE7-483D-B231-C672365CD2D7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-sgl", "nq-sgl\nq-sgl.vcproj", "{2E26DB8B-9E37-4072-B397-8A7086E0ACD0}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {7E30C3B1-AEE7-483D-B231-C672365CD2D7} = {7E30C3B1-AEE7-483D-B231-C672365CD2D7} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-sdl", "nq-sdl\nq-sdl.vcproj", "{2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}" - ProjectSection(ProjectDependencies) = postProject - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {66D3A191-E4D5-45F3-86BD-EFBB249CD554} = {66D3A191-E4D5-45F3-86BD-EFBB249CD554} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-sdl32", "nq-sdl32\nq-sdl32.vcproj", "{2CEB1965-A89C-4422-A9AC-B30FCE7913C3}" - ProjectSection(ProjectDependencies) = postProject - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {D5B9558F-EF25-4167-ACE4-723C7413B390} = {D5B9558F-EF25-4167-ACE4-723C7413B390} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release (static)|Win32 = Release (static)|Win32 - Release (static)|x64 = Release (static)|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|Win32.ActiveCfg = Debug|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|Win32.Build.0 = Debug|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|x64.ActiveCfg = Debug|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|x64.Build.0 = Debug|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|x64.Build.0 = Release (static)|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|Win32.ActiveCfg = Release|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|Win32.Build.0 = Release|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|x64.ActiveCfg = Release|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|x64.Build.0 = Release|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|Win32.ActiveCfg = Debug|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|Win32.Build.0 = Debug|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|x64.ActiveCfg = Debug|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|x64.Build.0 = Debug|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|x64.Build.0 = Release (static)|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|Win32.ActiveCfg = Release|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|Win32.Build.0 = Release|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|x64.ActiveCfg = Release|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|x64.Build.0 = Release|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|Win32.ActiveCfg = Debug|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|Win32.Build.0 = Debug|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|x64.ActiveCfg = Debug|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|x64.Build.0 = Debug|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|x64.Build.0 = Release (static)|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|Win32.ActiveCfg = Release|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|Win32.Build.0 = Release|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|x64.ActiveCfg = Release|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|x64.Build.0 = Release|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|Win32.ActiveCfg = Debug|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|Win32.Build.0 = Debug|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|x64.ActiveCfg = Debug|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|x64.Build.0 = Debug|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|x64.Build.0 = Release (static)|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|Win32.ActiveCfg = Release|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|Win32.Build.0 = Release|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|x64.ActiveCfg = Release|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|x64.Build.0 = Release|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|Win32.ActiveCfg = Debug|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|Win32.Build.0 = Debug|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|x64.ActiveCfg = Debug|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|x64.Build.0 = Debug|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|x64.Build.0 = Release (static)|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|Win32.ActiveCfg = Release|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|Win32.Build.0 = Release|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|x64.ActiveCfg = Release|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|x64.Build.0 = Release|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|Win32.ActiveCfg = Debug|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|Win32.Build.0 = Debug|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|x64.ActiveCfg = Debug|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|x64.Build.0 = Debug|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|x64.Build.0 = Release (static)|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|Win32.ActiveCfg = Release|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|Win32.Build.0 = Release|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|x64.ActiveCfg = Release|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|x64.Build.0 = Release|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|Win32.ActiveCfg = Debug|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|Win32.Build.0 = Debug|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|x64.ActiveCfg = Debug|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|x64.Build.0 = Debug|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|x64.Build.0 = Release (static)|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|Win32.ActiveCfg = Release|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|Win32.Build.0 = Release|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|x64.ActiveCfg = Release|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|x64.Build.0 = Release|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|Win32.ActiveCfg = Debug|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|Win32.Build.0 = Debug|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|x64.ActiveCfg = Debug|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|x64.Build.0 = Debug|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|x64.Build.0 = Release (static)|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|Win32.ActiveCfg = Release|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|Win32.Build.0 = Release|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|x64.ActiveCfg = Release|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|x64.Build.0 = Release|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|Win32.ActiveCfg = Debug|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|Win32.Build.0 = Debug|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|x64.ActiveCfg = Debug|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|x64.Build.0 = Debug|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|x64.Build.0 = Release (static)|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|Win32.ActiveCfg = Release|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|Win32.Build.0 = Release|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|x64.ActiveCfg = Release|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|x64.Build.0 = Release|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|Win32.ActiveCfg = Debug|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|Win32.Build.0 = Debug|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|x64.ActiveCfg = Debug|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|x64.Build.0 = Debug|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|x64.Build.0 = Release (static)|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|Win32.ActiveCfg = Release|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|Win32.Build.0 = Release|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|x64.ActiveCfg = Release|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|x64.Build.0 = Release|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|Win32.ActiveCfg = Debug|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|Win32.Build.0 = Debug|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|x64.ActiveCfg = Debug|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|x64.Build.0 = Debug|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|x64.Build.0 = Release (static)|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|Win32.ActiveCfg = Release|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|Win32.Build.0 = Release|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|x64.ActiveCfg = Release|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|x64.Build.0 = Release|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|Win32.ActiveCfg = Debug|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|Win32.Build.0 = Debug|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|x64.ActiveCfg = Debug|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|x64.Build.0 = Debug|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|x64.Build.0 = Release (static)|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|Win32.ActiveCfg = Release|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|Win32.Build.0 = Release|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|x64.ActiveCfg = Release|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|x64.Build.0 = Release|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|Win32.ActiveCfg = Debug|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|Win32.Build.0 = Debug|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|x64.ActiveCfg = Debug|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|x64.Build.0 = Debug|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|x64.Build.0 = Release (static)|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|Win32.ActiveCfg = Release|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|Win32.Build.0 = Release|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|x64.ActiveCfg = Release|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|x64.Build.0 = Release|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|Win32.ActiveCfg = Debug|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|Win32.Build.0 = Debug|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|x64.ActiveCfg = Debug|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|x64.Build.0 = Debug|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|x64.Build.0 = Release (static)|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|Win32.ActiveCfg = Release|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|Win32.Build.0 = Release|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|x64.ActiveCfg = Release|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|x64.Build.0 = Release|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|Win32.ActiveCfg = Debug|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|Win32.Build.0 = Debug|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|x64.ActiveCfg = Debug|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|x64.Build.0 = Debug|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|x64.Build.0 = Release (static)|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|Win32.ActiveCfg = Release|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|Win32.Build.0 = Release|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|x64.ActiveCfg = Release|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|x64.Build.0 = Release|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|Win32.ActiveCfg = Debug|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|Win32.Build.0 = Debug|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|x64.ActiveCfg = Debug|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|x64.Build.0 = Debug|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|x64.Build.0 = Release (static)|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|Win32.ActiveCfg = Release|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|Win32.Build.0 = Release|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|x64.ActiveCfg = Release|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|x64.Build.0 = Release|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|Win32.ActiveCfg = Debug|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|Win32.Build.0 = Debug|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|x64.ActiveCfg = Debug|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|x64.Build.0 = Debug|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|x64.Build.0 = Release (static)|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|Win32.ActiveCfg = Release|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|Win32.Build.0 = Release|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|x64.ActiveCfg = Release|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|x64.Build.0 = Release|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|Win32.Build.0 = Debug|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|x64.ActiveCfg = Debug|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|x64.Build.0 = Debug|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|x64.Build.0 = Release (static)|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|Win32.ActiveCfg = Release|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|Win32.Build.0 = Release|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|x64.ActiveCfg = Release|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|x64.Build.0 = Release|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|Win32.ActiveCfg = Debug|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|Win32.Build.0 = Debug|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|x64.ActiveCfg = Debug|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|x64.Build.0 = Debug|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|x64.Build.0 = Release (static)|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|Win32.ActiveCfg = Release|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|Win32.Build.0 = Release|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|x64.ActiveCfg = Release|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|x64.Build.0 = Release|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|Win32.ActiveCfg = Debug|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|Win32.Build.0 = Debug|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|x64.ActiveCfg = Debug|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|x64.Build.0 = Debug|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|x64.Build.0 = Release (static)|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|Win32.ActiveCfg = Release|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|Win32.Build.0 = Release|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|x64.ActiveCfg = Release|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|x64.Build.0 = Release|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|Win32.ActiveCfg = Debug|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|Win32.Build.0 = Debug|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|x64.ActiveCfg = Debug|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|x64.Build.0 = Debug|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|x64.Build.0 = Release (static)|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|Win32.ActiveCfg = Release|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|Win32.Build.0 = Release|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|x64.ActiveCfg = Release|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|x64.Build.0 = Release|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|Win32.ActiveCfg = Debug|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|Win32.Build.0 = Debug|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|x64.ActiveCfg = Debug|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|x64.Build.0 = Debug|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|x64.Build.0 = Release (static)|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|Win32.ActiveCfg = Release|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|Win32.Build.0 = Release|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|x64.ActiveCfg = Release|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|x64.Build.0 = Release|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|Win32.ActiveCfg = Debug|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|Win32.Build.0 = Debug|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|x64.ActiveCfg = Debug|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|x64.Build.0 = Debug|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|x64.Build.0 = Release (static)|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|Win32.ActiveCfg = Release|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|Win32.Build.0 = Release|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|x64.ActiveCfg = Release|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|x64.Build.0 = Release|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|Win32.ActiveCfg = Debug|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|Win32.Build.0 = Debug|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|x64.ActiveCfg = Debug|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|x64.Build.0 = Debug|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|x64.Build.0 = Release (static)|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|Win32.ActiveCfg = Release|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|Win32.Build.0 = Release|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|x64.ActiveCfg = Release|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|x64.Build.0 = Release|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|Win32.ActiveCfg = Debug|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|Win32.Build.0 = Debug|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|x64.ActiveCfg = Debug|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|x64.Build.0 = Debug|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|x64.Build.0 = Release (static)|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|Win32.ActiveCfg = Release|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|Win32.Build.0 = Release|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|x64.ActiveCfg = Release|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|x64.Build.0 = Release|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|Win32.ActiveCfg = Debug|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|Win32.Build.0 = Debug|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|x64.ActiveCfg = Debug|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|x64.Build.0 = Debug|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|x64.Build.0 = Release (static)|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|Win32.ActiveCfg = Release|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|Win32.Build.0 = Release|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|x64.ActiveCfg = Release|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|x64.Build.0 = Release|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|Win32.ActiveCfg = Debug|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|Win32.Build.0 = Debug|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|x64.ActiveCfg = Debug|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|x64.Build.0 = Debug|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|x64.Build.0 = Release (static)|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|Win32.ActiveCfg = Release|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|Win32.Build.0 = Release|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|x64.ActiveCfg = Release|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|x64.Build.0 = Release|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|Win32.ActiveCfg = Debug|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|Win32.Build.0 = Debug|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|x64.ActiveCfg = Debug|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|x64.Build.0 = Debug|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|x64.Build.0 = Release (static)|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|Win32.ActiveCfg = Release|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|Win32.Build.0 = Release|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|x64.ActiveCfg = Release|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|x64.Build.0 = Release|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|Win32.ActiveCfg = Debug|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|Win32.Build.0 = Debug|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|x64.ActiveCfg = Debug|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|x64.Build.0 = Debug|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|x64.Build.0 = Release (static)|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|Win32.ActiveCfg = Release|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|Win32.Build.0 = Release|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|x64.ActiveCfg = Release|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|x64.Build.0 = Release|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|Win32.ActiveCfg = Debug|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|Win32.Build.0 = Debug|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|x64.ActiveCfg = Debug|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|x64.Build.0 = Debug|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|x64.Build.0 = Release (static)|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|Win32.ActiveCfg = Release|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|Win32.Build.0 = Release|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|x64.ActiveCfg = Release|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|x64.Build.0 = Release|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|Win32.ActiveCfg = Debug|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|Win32.Build.0 = Debug|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|x64.ActiveCfg = Debug|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|x64.Build.0 = Debug|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|x64.Build.0 = Release (static)|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|Win32.ActiveCfg = Release|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|Win32.Build.0 = Release|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|x64.ActiveCfg = Release|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|x64.Build.0 = Release|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|Win32.ActiveCfg = Debug|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|Win32.Build.0 = Debug|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|x64.ActiveCfg = Debug|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|x64.Build.0 = Debug|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|x64.Build.0 = Release (static)|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|Win32.ActiveCfg = Release|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|Win32.Build.0 = Release|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|x64.ActiveCfg = Release|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|x64.Build.0 = Release|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|Win32.ActiveCfg = Debug|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|Win32.Build.0 = Debug|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|x64.ActiveCfg = Debug|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|x64.Build.0 = Debug|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|x64.Build.0 = Release (static)|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|Win32.ActiveCfg = Release|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|Win32.Build.0 = Release|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|x64.ActiveCfg = Release|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|x64.Build.0 = Release|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|Win32.ActiveCfg = Debug|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|Win32.Build.0 = Debug|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|x64.ActiveCfg = Debug|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|x64.Build.0 = Debug|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|x64.Build.0 = Release (static)|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|Win32.ActiveCfg = Release|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|Win32.Build.0 = Release|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|x64.ActiveCfg = Release|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|x64.Build.0 = Release|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|Win32.Build.0 = Debug|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|x64.ActiveCfg = Debug|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|x64.Build.0 = Debug|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|x64.Build.0 = Release (static)|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|Win32.ActiveCfg = Release|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|Win32.Build.0 = Release|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|x64.ActiveCfg = Release|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|x64.Build.0 = Release|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Debug|Win32.ActiveCfg = Debug|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Debug|Win32.Build.0 = Debug|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Debug|x64.ActiveCfg = Debug|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|x64.Build.0 = Release (static)|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|Win32.ActiveCfg = Release|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|Win32.Build.0 = Release|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|x64.ActiveCfg = Release|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|x64.Build.0 = Release|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Debug|Win32.ActiveCfg = Debug|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Debug|Win32.Build.0 = Debug|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Debug|x64.ActiveCfg = Debug|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|x64.Build.0 = Release (static)|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|Win32.ActiveCfg = Release|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|Win32.Build.0 = Release|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|x64.ActiveCfg = Release|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|x64.Build.0 = Release|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Debug|Win32.ActiveCfg = Debug|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Debug|Win32.Build.0 = Debug|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Debug|x64.ActiveCfg = Debug|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|x64.Build.0 = Release (static)|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|Win32.ActiveCfg = Release|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|Win32.Build.0 = Release|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|x64.ActiveCfg = Release|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|x64.Build.0 = Release|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Debug|Win32.ActiveCfg = Debug|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Debug|Win32.Build.0 = Debug|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Debug|x64.ActiveCfg = Debug|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|x64.Build.0 = Release (static)|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|Win32.ActiveCfg = Release|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|Win32.Build.0 = Release|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|x64.ActiveCfg = Release|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|x64.Build.0 = Release|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Debug|Win32.ActiveCfg = Debug|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Debug|Win32.Build.0 = Debug|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Debug|x64.ActiveCfg = Debug|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|x64.Build.0 = Release (static)|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|Win32.ActiveCfg = Release|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|Win32.Build.0 = Release|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|x64.ActiveCfg = Release|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|x64.Build.0 = Release|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Debug|Win32.ActiveCfg = Debug|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Debug|Win32.Build.0 = Debug|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Debug|x64.ActiveCfg = Debug|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|x64.Build.0 = Release (static)|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|Win32.ActiveCfg = Release|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|Win32.Build.0 = Release|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|x64.ActiveCfg = Release|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|x64.Build.0 = Release|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Debug|Win32.ActiveCfg = Debug|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Debug|Win32.Build.0 = Debug|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Debug|x64.ActiveCfg = Debug|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|x64.Build.0 = Release (static)|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|Win32.ActiveCfg = Release|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|Win32.Build.0 = Release|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|x64.ActiveCfg = Release|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|x64.Build.0 = Release|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Debug|Win32.ActiveCfg = Debug|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Debug|Win32.Build.0 = Debug|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Debug|x64.ActiveCfg = Debug|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|x64.Build.0 = Release (static)|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|Win32.ActiveCfg = Release|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|Win32.Build.0 = Release|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|x64.ActiveCfg = Release|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|x64.Build.0 = Release|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Debug|Win32.ActiveCfg = Debug|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Debug|Win32.Build.0 = Debug|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Debug|x64.ActiveCfg = Debug|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|x64.Build.0 = Release (static)|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|Win32.ActiveCfg = Release|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|Win32.Build.0 = Release|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|x64.ActiveCfg = Release|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|x64.Build.0 = Release|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Debug|Win32.ActiveCfg = Debug|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Debug|Win32.Build.0 = Debug|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Debug|x64.ActiveCfg = Debug|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|x64.Build.0 = Release (static)|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|Win32.ActiveCfg = Release|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|Win32.Build.0 = Release|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|x64.ActiveCfg = Release|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|x64.Build.0 = Release|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Debug|Win32.ActiveCfg = Debug|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Debug|Win32.Build.0 = Debug|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Debug|x64.ActiveCfg = Debug|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|x64.Build.0 = Release (static)|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|Win32.ActiveCfg = Release|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|Win32.Build.0 = Release|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|x64.ActiveCfg = Release|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|x64.Build.0 = Release|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Debug|Win32.ActiveCfg = Debug|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Debug|Win32.Build.0 = Debug|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Debug|x64.ActiveCfg = Debug|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|x64.Build.0 = Release (static)|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|Win32.ActiveCfg = Release|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|Win32.Build.0 = Release|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|x64.ActiveCfg = Release|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|x64.Build.0 = Release|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Debug|Win32.ActiveCfg = Debug|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Debug|Win32.Build.0 = Debug|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Debug|x64.ActiveCfg = Debug|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|x64.Build.0 = Release (static)|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|Win32.ActiveCfg = Release|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|Win32.Build.0 = Release|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|x64.ActiveCfg = Release|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|x64.Build.0 = Release|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Debug|Win32.ActiveCfg = Debug|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Debug|Win32.Build.0 = Debug|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Debug|x64.ActiveCfg = Debug|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|x64.Build.0 = Release (static)|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|Win32.ActiveCfg = Release|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|Win32.Build.0 = Release|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|x64.ActiveCfg = Release|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|x64.Build.0 = Release|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Debug|Win32.ActiveCfg = Debug|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Debug|Win32.Build.0 = Debug|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Debug|x64.ActiveCfg = Debug|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|x64.Build.0 = Release (static)|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|Win32.ActiveCfg = Release|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|Win32.Build.0 = Release|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|x64.ActiveCfg = Release|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/vc2005/QuakeForge-VS8.sln b/vc2005/QuakeForge-VS8.sln deleted file mode 100644 index de80d166d..000000000 --- a/vc2005/QuakeForge-VS8.sln +++ /dev/null @@ -1,966 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client", "qfclient\qfclient.vcproj", "{9A942925-61E6-4975-935A-5D62E8248E64}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw", "qw\qw.vcproj", "{6ADA4322-693A-46BB-897B-17BB5BE9F08C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "net-chan", "net\net.vcproj", "{6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ruamoko", "ruamoko\ruamoko.vcproj", "{51028ACF-53D4-4478-8500-55E6B8A81375}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models-gl", "modelsgl\modelsgl.vcproj", "{1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console", "console\console.vcproj", "{ED4AFBF5-C247-4352-966D-048B8998C6A1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gib", "gib\gib.vcproj", "{01C3B138-9D45-4ED6-A763-893C067262C2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "util", "util\util.vcproj", "{ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine", "engine\engine.vcproj", "{2626C0E1-6F5C-47D3-B80D-93942D766DD7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "builtins", "builtins\builtins.vcproj", "{04FA9D77-E45F-4917-B972-B353BA6A6FA8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sound", "sound\sound.vcproj", "{BF149D97-7520-4788-9CD1-3D99C5C8150F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "image", "image\image.vcproj", "{5203F034-0047-4EC0-B7E9-D037FAF5D536}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video", "video\video.vcproj", "{E7B3D07D-2FE8-481B-8DAB-6255A412A42F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-common", "common\common.vcproj", "{BC1F021A-1EEC-4A7A-B746-5AA6048E478C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-server", "qfserver\qfserver.vcproj", "{544D097C-9C24-4C57-A171-8C8029421185}" - ProjectSection(ProjectDependencies) = postProject - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} = {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models", "models\models.vcproj", "{DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console-client", "console_client\console_client.vcproj", "{226D42CE-5833-444E-94FA-84C1D51892A8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console-server", "console_server\console_server.vcproj", "{B37FE734-01F4-4799-86B2-D084820715BE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfbsp", "qfbsp\qfbsp.vcproj", "{B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qflight", "qflight\qflight.vcproj", "{5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfvis", "qfvis\qfvis.vcproj", "{E5D842C5-669F-4FC7-A5E0-44B562F86435}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-master", "qw-master\qw-master.vcproj", "{445A2500-3BBC-449A-A929-C419C2A16051}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfmodelgen", "qfmodelgen\qfmodelgen.vcproj", "{052C34FE-C9E2-43ED-95DA-FB3F27B44E37}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfprogs", "qfprogs\qfprogs.vcproj", "{5FA27C8E-51B1-445A-A375-FBE74F0984B1}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfwavinfo", "qfwavinfo\qfwavinfo.vcproj", "{56BD559B-1590-4FC4-B441-AB1973BAC2BD}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wad", "wad\wad.vcproj", "{88422448-C5FB-46F3-A0B3-0811F90E537C}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pak", "pak\pak.vcproj", "{9EE8BD4B-47D3-4AD5-A8B9-831329792A05}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bsp2img", "bsp2img\bsp2img.vcproj", "{4605418D-2292-470A-AB18-C2119B016F71}" - ProjectSection(ProjectDependencies) = postProject - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtv", "qtv\qtv.vcproj", "{05E68E3B-5901-43A9-981D-CF392C0F5C6C}" - ProjectSection(ProjectDependencies) = postProject - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-common", "nq-common\nq-common.vcproj", "{6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-wgl", "nq-wgl\nq-wgl.vcproj", "{1CD1A18B-95D5-4EA4-917C-34B10066BFCC}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} = {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "net-main", "net-main\net-main.vcproj", "{053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-server", "nq-server\nq-server.vcproj", "{231C032C-DE16-459A-8E7D-6509C2EC3998}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} = {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hw-master", "hw-master\hw-master.vcproj", "{419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}" - ProjectSection(ProjectDependencies) = postProject - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{3CDA2798-7565-47C5-B972-F9E63DBEFFFA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfcc", "qfcc\qfcc.vcproj", "{40639893-4D75-48CD-811F-4B363CC71FFA}" - ProjectSection(ProjectDependencies) = postProject - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-wgl", "qw-client-wgl\qw-client-wgl.vcproj", "{5FD733BF-B3C6-4A96-BED7-35E2484448E1}" - ProjectSection(ProjectDependencies) = postProject - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} = {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-sgl", "qw-client-sgl\qw-client-sgl.vcproj", "{649C4168-1C65-4E41-818F-85A1C52C1B8F}" - ProjectSection(ProjectDependencies) = postProject - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {7E30C3B1-AEE7-483D-B231-C672365CD2D7} = {7E30C3B1-AEE7-483D-B231-C672365CD2D7} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-gl", "videogl\videogl.vcproj", "{C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sdl", "video-sdl\video-sdl.vcproj", "{44A18410-3AA8-4A64-935B-D20223AD6885}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-sdl", "qw-client-sdl\qw-client-sdl.vcproj", "{B44CB3E0-F2FD-4260-A632-C01FB881613E}" - ProjectSection(ProjectDependencies) = postProject - {66D3A191-E4D5-45F3-86BD-EFBB249CD554} = {66D3A191-E4D5-45F3-86BD-EFBB249CD554} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models-sw", "models-sw\models-sw.vcproj", "{F4A9881E-0EB0-44A1-9664-B6CBDE992861}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sw", "video-sw\video-sw.vcproj", "{66D3A191-E4D5-45F3-86BD-EFBB249CD554}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-sdl32", "qw-client-sdl32\qw-client-sdl32.vcproj", "{CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}" - ProjectSection(ProjectDependencies) = postProject - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {D5B9558F-EF25-4167-ACE4-723C7413B390} = {D5B9558F-EF25-4167-ACE4-723C7413B390} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sw32", "video-sw32\video-sw32.vcproj", "{D5B9558F-EF25-4167-ACE4-723C7413B390}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq", "nq\nq.vcproj", "{155112B9-A8A9-4E06-90F5-4AAAB32B2F70}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-wgl", "video-wgl\video-wgl.vcproj", "{178D81A7-F2FB-41D7-B300-9D1A4DE5E137}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sgl", "video-sgl\video-sgl.vcproj", "{7E30C3B1-AEE7-483D-B231-C672365CD2D7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-sgl", "nq-sgl\nq-sgl.vcproj", "{2E26DB8B-9E37-4072-B397-8A7086E0ACD0}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {7E30C3B1-AEE7-483D-B231-C672365CD2D7} = {7E30C3B1-AEE7-483D-B231-C672365CD2D7} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-sdl", "nq-sdl\nq-sdl.vcproj", "{2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}" - ProjectSection(ProjectDependencies) = postProject - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {66D3A191-E4D5-45F3-86BD-EFBB249CD554} = {66D3A191-E4D5-45F3-86BD-EFBB249CD554} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-sdl32", "nq-sdl32\nq-sdl32.vcproj", "{2CEB1965-A89C-4422-A9AC-B30FCE7913C3}" - ProjectSection(ProjectDependencies) = postProject - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {D5B9558F-EF25-4167-ACE4-723C7413B390} = {D5B9558F-EF25-4167-ACE4-723C7413B390} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release (static)|Win32 = Release (static)|Win32 - Release (static)|x64 = Release (static)|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|Win32.ActiveCfg = Debug|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|Win32.Build.0 = Debug|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|x64.ActiveCfg = Debug|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|x64.Build.0 = Debug|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|x64.Build.0 = Release (static)|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|Win32.ActiveCfg = Release|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|Win32.Build.0 = Release|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|x64.ActiveCfg = Release|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|x64.Build.0 = Release|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|Win32.ActiveCfg = Debug|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|Win32.Build.0 = Debug|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|x64.ActiveCfg = Debug|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|x64.Build.0 = Debug|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|x64.Build.0 = Release (static)|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|Win32.ActiveCfg = Release|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|Win32.Build.0 = Release|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|x64.ActiveCfg = Release|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|x64.Build.0 = Release|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|Win32.ActiveCfg = Debug|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|Win32.Build.0 = Debug|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|x64.ActiveCfg = Debug|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|x64.Build.0 = Debug|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|x64.Build.0 = Release (static)|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|Win32.ActiveCfg = Release|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|Win32.Build.0 = Release|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|x64.ActiveCfg = Release|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|x64.Build.0 = Release|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|Win32.ActiveCfg = Debug|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|Win32.Build.0 = Debug|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|x64.ActiveCfg = Debug|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|x64.Build.0 = Debug|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|x64.Build.0 = Release (static)|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|Win32.ActiveCfg = Release|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|Win32.Build.0 = Release|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|x64.ActiveCfg = Release|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|x64.Build.0 = Release|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|Win32.ActiveCfg = Debug|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|Win32.Build.0 = Debug|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|x64.ActiveCfg = Debug|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|x64.Build.0 = Debug|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|x64.Build.0 = Release (static)|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|Win32.ActiveCfg = Release|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|Win32.Build.0 = Release|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|x64.ActiveCfg = Release|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|x64.Build.0 = Release|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|Win32.ActiveCfg = Debug|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|Win32.Build.0 = Debug|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|x64.ActiveCfg = Debug|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|x64.Build.0 = Debug|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|x64.Build.0 = Release (static)|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|Win32.ActiveCfg = Release|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|Win32.Build.0 = Release|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|x64.ActiveCfg = Release|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|x64.Build.0 = Release|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|Win32.ActiveCfg = Debug|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|Win32.Build.0 = Debug|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|x64.ActiveCfg = Debug|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|x64.Build.0 = Debug|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|x64.Build.0 = Release (static)|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|Win32.ActiveCfg = Release|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|Win32.Build.0 = Release|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|x64.ActiveCfg = Release|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|x64.Build.0 = Release|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|Win32.ActiveCfg = Debug|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|Win32.Build.0 = Debug|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|x64.ActiveCfg = Debug|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|x64.Build.0 = Debug|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|x64.Build.0 = Release (static)|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|Win32.ActiveCfg = Release|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|Win32.Build.0 = Release|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|x64.ActiveCfg = Release|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|x64.Build.0 = Release|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|Win32.ActiveCfg = Debug|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|Win32.Build.0 = Debug|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|x64.ActiveCfg = Debug|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|x64.Build.0 = Debug|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|x64.Build.0 = Release (static)|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|Win32.ActiveCfg = Release|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|Win32.Build.0 = Release|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|x64.ActiveCfg = Release|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|x64.Build.0 = Release|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|Win32.ActiveCfg = Debug|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|Win32.Build.0 = Debug|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|x64.ActiveCfg = Debug|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|x64.Build.0 = Debug|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|x64.Build.0 = Release (static)|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|Win32.ActiveCfg = Release|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|Win32.Build.0 = Release|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|x64.ActiveCfg = Release|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|x64.Build.0 = Release|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|Win32.ActiveCfg = Debug|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|Win32.Build.0 = Debug|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|x64.ActiveCfg = Debug|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|x64.Build.0 = Debug|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|x64.Build.0 = Release (static)|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|Win32.ActiveCfg = Release|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|Win32.Build.0 = Release|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|x64.ActiveCfg = Release|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|x64.Build.0 = Release|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|Win32.ActiveCfg = Debug|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|Win32.Build.0 = Debug|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|x64.ActiveCfg = Debug|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|x64.Build.0 = Debug|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|x64.Build.0 = Release (static)|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|Win32.ActiveCfg = Release|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|Win32.Build.0 = Release|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|x64.ActiveCfg = Release|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|x64.Build.0 = Release|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|Win32.ActiveCfg = Debug|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|Win32.Build.0 = Debug|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|x64.ActiveCfg = Debug|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|x64.Build.0 = Debug|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|x64.Build.0 = Release (static)|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|Win32.ActiveCfg = Release|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|Win32.Build.0 = Release|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|x64.ActiveCfg = Release|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|x64.Build.0 = Release|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|Win32.ActiveCfg = Debug|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|Win32.Build.0 = Debug|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|x64.ActiveCfg = Debug|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|x64.Build.0 = Debug|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|x64.Build.0 = Release (static)|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|Win32.ActiveCfg = Release|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|Win32.Build.0 = Release|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|x64.ActiveCfg = Release|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|x64.Build.0 = Release|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|Win32.ActiveCfg = Debug|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|Win32.Build.0 = Debug|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|x64.ActiveCfg = Debug|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|x64.Build.0 = Debug|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|x64.Build.0 = Release (static)|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|Win32.ActiveCfg = Release|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|Win32.Build.0 = Release|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|x64.ActiveCfg = Release|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|x64.Build.0 = Release|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|Win32.ActiveCfg = Debug|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|Win32.Build.0 = Debug|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|x64.ActiveCfg = Debug|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|x64.Build.0 = Debug|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|x64.Build.0 = Release (static)|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|Win32.ActiveCfg = Release|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|Win32.Build.0 = Release|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|x64.ActiveCfg = Release|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|x64.Build.0 = Release|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|Win32.ActiveCfg = Debug|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|Win32.Build.0 = Debug|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|x64.ActiveCfg = Debug|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|x64.Build.0 = Debug|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|x64.Build.0 = Release (static)|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|Win32.ActiveCfg = Release|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|Win32.Build.0 = Release|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|x64.ActiveCfg = Release|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|x64.Build.0 = Release|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|Win32.Build.0 = Debug|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|x64.ActiveCfg = Debug|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|x64.Build.0 = Debug|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|x64.Build.0 = Release (static)|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|Win32.ActiveCfg = Release|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|Win32.Build.0 = Release|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|x64.ActiveCfg = Release|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|x64.Build.0 = Release|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|Win32.ActiveCfg = Debug|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|Win32.Build.0 = Debug|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|x64.ActiveCfg = Debug|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|x64.Build.0 = Debug|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|x64.Build.0 = Release (static)|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|Win32.ActiveCfg = Release|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|Win32.Build.0 = Release|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|x64.ActiveCfg = Release|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|x64.Build.0 = Release|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|Win32.ActiveCfg = Debug|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|Win32.Build.0 = Debug|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|x64.ActiveCfg = Debug|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|x64.Build.0 = Debug|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|x64.Build.0 = Release (static)|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|Win32.ActiveCfg = Release|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|Win32.Build.0 = Release|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|x64.ActiveCfg = Release|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|x64.Build.0 = Release|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|Win32.ActiveCfg = Debug|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|Win32.Build.0 = Debug|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|x64.ActiveCfg = Debug|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|x64.Build.0 = Debug|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|x64.Build.0 = Release (static)|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|Win32.ActiveCfg = Release|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|Win32.Build.0 = Release|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|x64.ActiveCfg = Release|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|x64.Build.0 = Release|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|Win32.ActiveCfg = Debug|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|Win32.Build.0 = Debug|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|x64.ActiveCfg = Debug|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|x64.Build.0 = Debug|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|x64.Build.0 = Release (static)|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|Win32.ActiveCfg = Release|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|Win32.Build.0 = Release|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|x64.ActiveCfg = Release|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|x64.Build.0 = Release|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|Win32.ActiveCfg = Debug|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|Win32.Build.0 = Debug|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|x64.ActiveCfg = Debug|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|x64.Build.0 = Debug|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|x64.Build.0 = Release (static)|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|Win32.ActiveCfg = Release|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|Win32.Build.0 = Release|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|x64.ActiveCfg = Release|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|x64.Build.0 = Release|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|Win32.ActiveCfg = Debug|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|Win32.Build.0 = Debug|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|x64.ActiveCfg = Debug|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|x64.Build.0 = Debug|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|x64.Build.0 = Release (static)|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|Win32.ActiveCfg = Release|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|Win32.Build.0 = Release|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|x64.ActiveCfg = Release|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|x64.Build.0 = Release|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|Win32.ActiveCfg = Debug|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|Win32.Build.0 = Debug|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|x64.ActiveCfg = Debug|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|x64.Build.0 = Debug|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|x64.Build.0 = Release (static)|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|Win32.ActiveCfg = Release|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|Win32.Build.0 = Release|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|x64.ActiveCfg = Release|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|x64.Build.0 = Release|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|Win32.ActiveCfg = Debug|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|Win32.Build.0 = Debug|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|x64.ActiveCfg = Debug|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|x64.Build.0 = Debug|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|x64.Build.0 = Release (static)|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|Win32.ActiveCfg = Release|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|Win32.Build.0 = Release|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|x64.ActiveCfg = Release|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|x64.Build.0 = Release|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|Win32.ActiveCfg = Debug|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|Win32.Build.0 = Debug|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|x64.ActiveCfg = Debug|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|x64.Build.0 = Debug|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|x64.Build.0 = Release (static)|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|Win32.ActiveCfg = Release|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|Win32.Build.0 = Release|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|x64.ActiveCfg = Release|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|x64.Build.0 = Release|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|Win32.ActiveCfg = Debug|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|Win32.Build.0 = Debug|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|x64.ActiveCfg = Debug|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|x64.Build.0 = Debug|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|x64.Build.0 = Release (static)|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|Win32.ActiveCfg = Release|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|Win32.Build.0 = Release|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|x64.ActiveCfg = Release|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|x64.Build.0 = Release|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|Win32.ActiveCfg = Debug|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|Win32.Build.0 = Debug|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|x64.ActiveCfg = Debug|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|x64.Build.0 = Debug|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|x64.Build.0 = Release (static)|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|Win32.ActiveCfg = Release|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|Win32.Build.0 = Release|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|x64.ActiveCfg = Release|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|x64.Build.0 = Release|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|Win32.ActiveCfg = Debug|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|Win32.Build.0 = Debug|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|x64.ActiveCfg = Debug|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|x64.Build.0 = Debug|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|x64.Build.0 = Release (static)|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|Win32.ActiveCfg = Release|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|Win32.Build.0 = Release|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|x64.ActiveCfg = Release|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|x64.Build.0 = Release|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|Win32.ActiveCfg = Debug|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|Win32.Build.0 = Debug|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|x64.ActiveCfg = Debug|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|x64.Build.0 = Debug|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|x64.Build.0 = Release (static)|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|Win32.ActiveCfg = Release|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|Win32.Build.0 = Release|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|x64.ActiveCfg = Release|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|x64.Build.0 = Release|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|Win32.ActiveCfg = Debug|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|Win32.Build.0 = Debug|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|x64.ActiveCfg = Debug|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|x64.Build.0 = Debug|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|x64.Build.0 = Release (static)|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|Win32.ActiveCfg = Release|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|Win32.Build.0 = Release|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|x64.ActiveCfg = Release|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|x64.Build.0 = Release|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|Win32.ActiveCfg = Debug|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|Win32.Build.0 = Debug|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|x64.ActiveCfg = Debug|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|x64.Build.0 = Debug|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|x64.Build.0 = Release (static)|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|Win32.ActiveCfg = Release|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|Win32.Build.0 = Release|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|x64.ActiveCfg = Release|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|x64.Build.0 = Release|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|Win32.ActiveCfg = Debug|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|Win32.Build.0 = Debug|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|x64.ActiveCfg = Debug|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|x64.Build.0 = Debug|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|x64.Build.0 = Release (static)|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|Win32.ActiveCfg = Release|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|Win32.Build.0 = Release|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|x64.ActiveCfg = Release|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|x64.Build.0 = Release|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|Win32.Build.0 = Debug|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|x64.ActiveCfg = Debug|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|x64.Build.0 = Debug|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|x64.Build.0 = Release (static)|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|Win32.ActiveCfg = Release|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|Win32.Build.0 = Release|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|x64.ActiveCfg = Release|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|x64.Build.0 = Release|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Debug|Win32.ActiveCfg = Debug|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Debug|Win32.Build.0 = Debug|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Debug|x64.ActiveCfg = Debug|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|x64.Build.0 = Release (static)|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|Win32.ActiveCfg = Release|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|Win32.Build.0 = Release|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|x64.ActiveCfg = Release|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|x64.Build.0 = Release|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Debug|Win32.ActiveCfg = Debug|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Debug|Win32.Build.0 = Debug|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Debug|x64.ActiveCfg = Debug|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|x64.Build.0 = Release (static)|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|Win32.ActiveCfg = Release|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|Win32.Build.0 = Release|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|x64.ActiveCfg = Release|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|x64.Build.0 = Release|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Debug|Win32.ActiveCfg = Debug|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Debug|Win32.Build.0 = Debug|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Debug|x64.ActiveCfg = Debug|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|x64.Build.0 = Release (static)|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|Win32.ActiveCfg = Release|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|Win32.Build.0 = Release|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|x64.ActiveCfg = Release|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|x64.Build.0 = Release|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Debug|Win32.ActiveCfg = Debug|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Debug|Win32.Build.0 = Debug|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Debug|x64.ActiveCfg = Debug|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|x64.Build.0 = Release (static)|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|Win32.ActiveCfg = Release|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|Win32.Build.0 = Release|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|x64.ActiveCfg = Release|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|x64.Build.0 = Release|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Debug|Win32.ActiveCfg = Debug|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Debug|Win32.Build.0 = Debug|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Debug|x64.ActiveCfg = Debug|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|x64.Build.0 = Release (static)|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|Win32.ActiveCfg = Release|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|Win32.Build.0 = Release|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|x64.ActiveCfg = Release|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|x64.Build.0 = Release|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Debug|Win32.ActiveCfg = Debug|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Debug|Win32.Build.0 = Debug|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Debug|x64.ActiveCfg = Debug|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|x64.Build.0 = Release (static)|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|Win32.ActiveCfg = Release|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|Win32.Build.0 = Release|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|x64.ActiveCfg = Release|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|x64.Build.0 = Release|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Debug|Win32.ActiveCfg = Debug|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Debug|Win32.Build.0 = Debug|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Debug|x64.ActiveCfg = Debug|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|x64.Build.0 = Release (static)|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|Win32.ActiveCfg = Release|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|Win32.Build.0 = Release|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|x64.ActiveCfg = Release|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|x64.Build.0 = Release|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Debug|Win32.ActiveCfg = Debug|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Debug|Win32.Build.0 = Debug|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Debug|x64.ActiveCfg = Debug|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|x64.Build.0 = Release (static)|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|Win32.ActiveCfg = Release|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|Win32.Build.0 = Release|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|x64.ActiveCfg = Release|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|x64.Build.0 = Release|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Debug|Win32.ActiveCfg = Debug|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Debug|Win32.Build.0 = Debug|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Debug|x64.ActiveCfg = Debug|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|x64.Build.0 = Release (static)|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|Win32.ActiveCfg = Release|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|Win32.Build.0 = Release|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|x64.ActiveCfg = Release|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|x64.Build.0 = Release|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Debug|Win32.ActiveCfg = Debug|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Debug|Win32.Build.0 = Debug|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Debug|x64.ActiveCfg = Debug|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|x64.Build.0 = Release (static)|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|Win32.ActiveCfg = Release|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|Win32.Build.0 = Release|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|x64.ActiveCfg = Release|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|x64.Build.0 = Release|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Debug|Win32.ActiveCfg = Debug|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Debug|Win32.Build.0 = Debug|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Debug|x64.ActiveCfg = Debug|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|x64.Build.0 = Release (static)|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|Win32.ActiveCfg = Release|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|Win32.Build.0 = Release|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|x64.ActiveCfg = Release|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|x64.Build.0 = Release|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Debug|Win32.ActiveCfg = Debug|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Debug|Win32.Build.0 = Debug|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Debug|x64.ActiveCfg = Debug|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|x64.Build.0 = Release (static)|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|Win32.ActiveCfg = Release|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|Win32.Build.0 = Release|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|x64.ActiveCfg = Release|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|x64.Build.0 = Release|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Debug|Win32.ActiveCfg = Debug|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Debug|Win32.Build.0 = Debug|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Debug|x64.ActiveCfg = Debug|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|x64.Build.0 = Release (static)|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|Win32.ActiveCfg = Release|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|Win32.Build.0 = Release|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|x64.ActiveCfg = Release|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|x64.Build.0 = Release|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Debug|Win32.ActiveCfg = Debug|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Debug|Win32.Build.0 = Debug|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Debug|x64.ActiveCfg = Debug|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|x64.Build.0 = Release (static)|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|Win32.ActiveCfg = Release|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|Win32.Build.0 = Release|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|x64.ActiveCfg = Release|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|x64.Build.0 = Release|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Debug|Win32.ActiveCfg = Debug|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Debug|Win32.Build.0 = Debug|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Debug|x64.ActiveCfg = Debug|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|x64.Build.0 = Release (static)|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|Win32.ActiveCfg = Release|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|Win32.Build.0 = Release|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|x64.ActiveCfg = Release|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {B37FE734-01F4-4799-86B2-D084820715BE} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {9A942925-61E6-4975-935A-5D62E8248E64} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {66D3A191-E4D5-45F3-86BD-EFBB249CD554} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {D5B9558F-EF25-4167-ACE4-723C7413B390} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {7E30C3B1-AEE7-483D-B231-C672365CD2D7} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - EndGlobalSection -EndGlobal diff --git a/vc2005/bsp2img/bsp2img.vcproj b/vc2005/bsp2img/bsp2img.vcproj deleted file mode 100644 index 49beb4a45..000000000 --- a/vc2005/bsp2img/bsp2img.vcproj +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/builtins/builtins.vcproj b/vc2005/builtins/builtins.vcproj deleted file mode 100644 index 63e384c61..000000000 --- a/vc2005/builtins/builtins.vcproj +++ /dev/null @@ -1,473 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/clean.ps1 b/vc2005/clean.ps1 deleted file mode 100644 index b1e75f990..000000000 --- a/vc2005/clean.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -ls -recurse -include 'win32','x64','*.user' | rm -recurse -if(test-path QuakeForge.suo) { rm QuakeForge.suo -force } -if(test-path QuakeForge.ncb) { rm QuakeForge.ncb } \ No newline at end of file diff --git a/vc2005/common/common.vcproj b/vc2005/common/common.vcproj deleted file mode 100644 index e473c7cce..000000000 --- a/vc2005/common/common.vcproj +++ /dev/null @@ -1,489 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/console/console.vcproj b/vc2005/console/console.vcproj deleted file mode 100644 index b71cf236e..000000000 --- a/vc2005/console/console.vcproj +++ /dev/null @@ -1,493 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/console_client/console_client.vcproj b/vc2005/console_client/console_client.vcproj deleted file mode 100644 index b6ae66820..000000000 --- a/vc2005/console_client/console_client.vcproj +++ /dev/null @@ -1,481 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/console_server/console_server.vcproj b/vc2005/console_server/console_server.vcproj deleted file mode 100644 index 4c3347b3a..000000000 --- a/vc2005/console_server/console_server.vcproj +++ /dev/null @@ -1,469 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/engine/engine.vcproj b/vc2005/engine/engine.vcproj deleted file mode 100644 index f3b7665ff..000000000 --- a/vc2005/engine/engine.vcproj +++ /dev/null @@ -1,509 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/gib/gib.vcproj b/vc2005/gib/gib.vcproj deleted file mode 100644 index 4039956cb..000000000 --- a/vc2005/gib/gib.vcproj +++ /dev/null @@ -1,537 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/hw-master/hw-master.vcproj b/vc2005/hw-master/hw-master.vcproj deleted file mode 100644 index 133d54777..000000000 --- a/vc2005/hw-master/hw-master.vcproj +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/image/image.vcproj b/vc2005/image/image.vcproj deleted file mode 100644 index e32ffd958..000000000 --- a/vc2005/image/image.vcproj +++ /dev/null @@ -1,481 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/include/config.h b/vc2005/include/config.h deleted file mode 100644 index 1b787db16..000000000 --- a/vc2005/include/config.h +++ /dev/null @@ -1,740 +0,0 @@ -/* include/config.h. Generated from config.h.in by configure. */ -/* include/config.h.in. Generated from configure.ac by autoheader. */ - -/* list of cd plugins */ -#define CD_PLUGIN_LIST {"cd_win", cd_win_PluginInfo},{0, 0} - -/* list of cd prototypes */ -#define CD_PLUGIN_PROTOS extern plugin_t *cd_win_PluginInfo (void); - -/* list of client plugins */ -#define CLIENT_PLUGIN_LIST {"console_client", console_client_PluginInfo},{0, 0} - -/* list of client prototypes */ -#define CLIENT_PLUGIN_PROTOS extern plugin_t *console_client_PluginInfo (void); - -/* Define this to the command line for the C preprocessor */ -#define CPP_NAME "wave --c99 %d -o %o %i" - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Define this to the location of the global config file */ -#define FS_GLOBALCFG "~/quakeforge.conf" - -/* Define this to the path from which to load plugins */ -#define FS_PLUGINPATH "/usr/local/lib/quakeforge" - -/* Define this to the shared game directory root */ -#define FS_SHAREPATH "." - -/* Define this to the location of the user config file */ -#define FS_USERCFG "~/quakeforgerc" - -/* Define this to the unshared game directory root */ -#define FS_USERPATH "." - -/* Define this to the default GL dynamic lib */ -#define GL_DRIVER "OPENGL32.DLL" - -/* Define to 1 if you have the `access' function. */ -#define HAVE_ACCESS 1 - -/* Define to 1 if you have `alloca', as a function or macro. */ -#define HAVE_ALLOCA 1 - -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -/* #undef HAVE_ALLOCA_H */ - -/* Define this if alloca is prototyped */ -/* #undef HAVE_ALLOCA_PROTO */ -#ifndef HAVE_ALLOCA_PROTO -#ifndef QFASM -void *alloca (int size); -#endif -#endif - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALSA_ASOUNDLIB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ARPA_INET_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ASM_IO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_CONIO_H 1 - -/* Define to 1 if you have the `connect' function. */ -#define HAVE_CONNECT 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_CTYPE_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CURSES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DDRAW_H 1 - -/* Define if you have the XFree86 DGA extension */ -/* #undef HAVE_DGA */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DINPUT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DIRECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DIRENT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ - -/* Define if you have the dlopen function. */ -/* #undef HAVE_DLOPEN */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DMEDIA_AUDIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DMEDIA_CDAUDIO_H */ - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -/* #undef HAVE_DOPRNT */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DPMI_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DSOUND_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_EXECINFO_H */ - -/* Define this if you have FB_AUX_VGA_PLANES_CFB4 */ -/* #undef HAVE_FB_AUX_VGA_PLANES_CFB4 */ - -/* Define this if you have FB_AUX_VGA_PLANES_CFB4 */ -/* #undef HAVE_FB_AUX_VGA_PLANES_CFB8 */ - -/* Define this if you have FB_AUX_VGA_PLANES_VGA4 */ -/* #undef HAVE_FB_AUX_VGA_PLANES_VGA4 */ - -/* Define to 1 if you have the `fcntl' function. */ -/* #undef HAVE_FCNTL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* define this if you have flac libs */ -/* #undef HAVE_FLAC */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FNMATCH_H 1 - -/* Define this if fnmatch is prototyped in fnmatch.h */ -/* #undef HAVE_FNMATCH_PROTO */ - -/* Define this if FPOS_T is a struct */ -/* #undef HAVE_FPOS_T_STRUCT */ - -/* Define to 1 if you have the `ftime' function. */ -#define HAVE_FTIME 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `gethostbyname' function. */ -#define HAVE_GETHOSTBYNAME 1 - -/* Define to 1 if you have the `gethostname' function. */ -#define HAVE_GETHOSTNAME 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `getpagesize' function. */ -/* #undef HAVE_GETPAGESIZE */ - -/* Define to 1 if you have the `gettimeofday' function. */ -/* #undef HAVE_GETTIMEOFDAY */ - -/* Define to 1 if you have the `getwd' function. */ -/* #undef HAVE_GETWD */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ - -/* Define this if your system has struct in_pktinfo */ -/* #undef HAVE_IN_PKTINFO */ - -/* Define to 1 if you have the header file. */ -#define HAVE_IO_H 1 - -/* Define this if you want IPv6 support */ -/* #undef HAVE_IPV6 */ - -/* Define if you have libjack */ -/* #undef HAVE_JACK */ - -/* Define to 1 if you have a functional curl library. */ -#define HAVE_LIBCURL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LIBC_H */ - -/* Define to 1 if you have the `db' library (-ldb). */ -/* #undef HAVE_LIBDB */ - -/* Define to 1 if you have the `efence' library (-lefence). */ -/* #undef HAVE_LIBEFENCE */ - -/* Define to 1 if you have the `m' library (-lm). */ -/* #undef HAVE_LIBM */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_CDROM_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_FB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_JOYSTICK_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_SOUNDCARD_H */ - -/* Define to 1 if you support file names longer than 14 characters. */ -#define HAVE_LONG_FILE_NAMES 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACHINE_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MALLOC_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MATH_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MGRAPH_H */ - -/* Define to 1 if you have the `mkdir' function. */ -#define HAVE_MKDIR 1 - -/* Define to 1 if you have a working `mmap' system call. */ -/* #undef HAVE_MMAP */ - -/* Define to 1 if you have the `mprotect' function. */ -/* #undef HAVE_MPROTECT */ - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -/* #undef HAVE_NDIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETDB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_IN_H */ - -/* Define if you have libpng */ -/* #undef HAVE_PNG */ - -/* Define to 1 if you have the header file. */ -#define HAVE_PROCESS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PTHREAD_H */ - -/* Define to 1 if you have the `putenv' function. */ -#define HAVE_PUTENV 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PWD_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_RPC_TYPES_H */ - -/* Define this if you have sa_len member in struct sockaddr (BSD) */ -/* #undef HAVE_SA_LEN */ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SETJMP_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define this if you have sin6_len member in struct sockaddr_in6 (BSD) */ -/* #undef HAVE_SIN6_LEN */ - -/* Define this if your system has size_t */ -#define HAVE_SIZE_T 1 - -/* Define to 1 if you have the `snprintf' function. */ -#define HAVE_SNPRINTF 1 - -/* Define to 1 if you have the `socket' function. */ -#define HAVE_SOCKET 1 - -/* Define this if your system has socklen_t */ -/* #undef HAVE_SOCKLEN_T */ - -/* Define this if you have ss_len member in struct sockaddr_storage (BSD) */ -/* #undef HAVE_SS_LEN */ - -/* Define to 1 if you have the `stat' function. */ -#define HAVE_STAT 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strcasestr' function. */ -/* #undef HAVE_STRCASESTR */ - -/* Define this if strcasestr is prototyped in string.h */ -/* #undef HAVE_STRCASESTR_PROTO */ - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRINGS_H 1 */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strnlen' function. */ -#define HAVE_STRNLEN 1 - -/* Define this if strnlen is prototyped in string.h */ -#define HAVE_STRNLEN_PROTO 1 - -/* Define to 1 if you have the `strsep' function. */ -/* #undef HAVE_STRSEP */ - -/* Define to 1 if you have the `strstr' function. */ -#define HAVE_STRSTR 1 - -/* Define to 1 if `st_blksize' is member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */ - -/* Define to 1 if your `struct stat' has `st_blksize'. Deprecated, use - `HAVE_STRUCT_STAT_ST_BLKSIZE' instead. */ -/* #undef HAVE_ST_BLKSIZE */ - -/* Define this if C symbols are prefixed with an underscore */ -#define HAVE_SYM_PREFIX_UNDERSCORE 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_ASOUNDLIB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIOIO_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_FILIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_IOCTL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_IO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_IPC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_MMAN_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_PARAM_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_POLL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SHM_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SIGNAL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TIME_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_UIO_H */ - -/* Define to 1 if you have that is POSIX.1 compatible. */ -/* #undef HAVE_SYS_WAIT_H */ - -/* Define this if you have tchar.h */ -#define HAVE_TCHAR_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_TERMIOS_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_TIME_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ - -/* Define to 1 if you have the `usleep' function. */ -/* #undef HAVE_USLEEP */ - -/* Define if va_copy is available */ -/* #undef HAVE_VA_COPY */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_VGAKEYBOARD_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_VGAMOUSE_H */ - -/* Define if you have the XFree86 VIDMODE extension */ -/* #undef HAVE_VIDMODE */ - -/* define this if you have ogg/vorbis libs */ -/* #undef HAVE_VORBIS */ - -/* Define to 1 if you have the `vprintf' function. */ -#define HAVE_VPRINTF 1 - -/* Define to 1 if you have the `vsnprintf' function. */ -#define HAVE_VSNPRINTF 1 - -/* Define if you have WildMidi */ -/* #undef HAVE_WILDMIDI */ - -/* Define to 1 if you have the header file. */ -#define HAVE_WINDOWS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WINSOCK_H 1 - -/* Define if you have XMMS */ -/* #undef HAVE_XMMS */ - -/* Define if you have zlib */ -#define HAVE_ZLIB 1 - -/* Define to 1 if you have the `_access' function. */ -#define HAVE__ACCESS 1 - -/* Define to 1 if you have the `_ftime' function. */ -#define HAVE__FTIME 1 - -/* Define to 1 if you have the <_mingw.h> header file. */ -/* #undef HAVE__MINGW_H */ - -/* Define to 1 if you have the `_mkdir' function. */ -#define HAVE__MKDIR 1 - -/* Define this if you have _SC_PAGESIZE */ -/* #undef HAVE__SC_PAGESIZE */ - -/* Define to 1 if you have the `_snprintf' function. */ -#define HAVE__SNPRINTF 1 - -/* Define if __va_copy is available */ -/* #undef HAVE__VA_COPY */ - -/* Define to 1 if you have the `_vsnprintf' function. */ -#define HAVE__VSNPRINTF 1 - -/* Define this if the GCC __attribute__ keyword is available */ -/* #undef HAVE___ATTRIBUTE__ */ - -#ifndef HAVE___ATTRIBUTE__ -# define __attribute__(x) -#endif - -/* Define this if the GCC __attribute__ keyword is available */ -/* #undef HAVE___ATTRIBUTE__VISIBILITY */ - -#ifdef HAVE___ATTRIBUTE__VISIBILITY -# define VISIBLE __attribute__((visibility ("default"))) -#else -# define VISIBLE -#endif - -/* Define this if the GCC __builtin_expect keyword is available */ -/* #undef HAVE___BUILTIN_EXPECT */ - -#ifndef HAVE___BUILTIN_EXPECT -# define __builtin_expect(x,c) x -#endif - -/* Defined if libcurl supports AsynchDNS */ -/* #undef LIBCURL_FEATURE_ASYNCHDNS */ - -/* Defined if libcurl supports IDN */ -#define LIBCURL_FEATURE_IDN 1 - -/* Defined if libcurl supports IPv6 */ -#define LIBCURL_FEATURE_IPV6 1 - -/* Defined if libcurl supports KRB4 */ -/* #undef LIBCURL_FEATURE_KRB4 */ - -/* Defined if libcurl supports libz */ -#define LIBCURL_FEATURE_LIBZ 1 - -/* Defined if libcurl supports NTLM */ -#define LIBCURL_FEATURE_NTLM 1 - -/* Defined if libcurl supports SSL */ -/* #undef LIBCURL_FEATURE_SSL */ - -/* Defined if libcurl supports SSPI */ -#define LIBCURL_FEATURE_SSPI 1 - -/* Defined if libcurl supports DICT */ -/* #undef LIBCURL_PROTOCOL_DICT */ - -/* Defined if libcurl supports FILE */ -/* #undef LIBCURL_PROTOCOL_FILE */ - -/* Defined if libcurl supports FTP */ -#define LIBCURL_PROTOCOL_FTP 1 - -/* Defined if libcurl supports FTPS */ -/* #undef LIBCURL_PROTOCOL_FTPS */ - -/* Defined if libcurl supports HTTP */ -#define LIBCURL_PROTOCOL_HTTP 1 - -/* Defined if libcurl supports HTTPS */ -/* #undef LIBCURL_PROTOCOL_HTTPS */ - -/* Defined if libcurl supports LDAP */ -/* #undef LIBCURL_PROTOCOL_LDAP */ - -/* Defined if libcurl supports TELNET */ -/* #undef LIBCURL_PROTOCOL_TELNET */ - -/* Defined if libcurl supports TFTP */ -/* #undef LIBCURL_PROTOCOL_TFTP */ - -/* Define to 1 if `major', `minor', and `makedev' are declared in . - */ -/* #undef MAJOR_IN_MKDEV */ - -/* Define to 1 if `major', `minor', and `makedev' are declared in - . */ -/* #undef MAJOR_IN_SYSMACROS */ - -/* Define this to the QSG standard version you support in NetQuake */ -#define NQ_QSG_VERSION "1.0" - -/* Define this to the NetQuake standard version you support */ -#define NQ_VERSION "1.09" - -/* Name of package */ -#define PACKAGE "quakeforge" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* Define this to your operating system's path separator character */ -#define PATH_SEPARATOR '/' - -/* "Proper" package name */ -#define PROGRAM "QuakeForge" - -/* Define this to where qfcc should look for header files */ -#define QFCC_INCLUDE_PATH "/usr/local/include/QF/ruamoko" - -/* Define this to where qfcc should look for lib files */ -#define QFCC_LIB_PATH "/usr/local/lib/ruamoko" - -/* Define this to the QSG standard version you support in QuakeWorld */ -#define QW_QSG_VERSION "2.0" - -/* Define this to the QuakeWorld standard version you support */ -#define QW_VERSION "2.40" - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* list of server plugins */ -#define SERVER_PLUGIN_LIST {"console_server", console_server_PluginInfo},{0, 0} - -/* list of server prototypes */ -#define SERVER_PLUGIN_PROTOS extern plugin_t *console_server_PluginInfo (void); - -/* Define this to the default sound output driver. */ -#define SND_OUTPUT_DEFAULT "win" - -/* list of sound output plugins */ -#define SND_OUTPUT_LIST {"snd_output_win", snd_output_win_PluginInfo},{0, 0} - -/* list of sound output prototypes */ -#define SND_OUTPUT_PROTOS extern plugin_t *snd_output_win_PluginInfo (void); - -/* list of sound render plugins */ -#define SND_RENDER_LIST {"snd_render_default", snd_render_default_PluginInfo},{0, 0} - -/* list of sound render prototypes */ -#define SND_RENDER_PROTOS extern plugin_t *snd_render_default_PluginInfo (void); - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ - -/* Define this if you are building static plugins */ -#define STATIC_PLUGINS 1 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 if your declares `struct tm'. */ -/* #undef TM_IN_SYS_TIME */ - -/* Define this if you want progs typechecking */ -/* #undef TYPECHECK_PROGS */ - -/* Define this if you want to use Intel assembly optimizations */ -/* #undef USE_INTEL_ASM */ - -/* Define if va_list is an array */ -/* #undef VA_LIST_IS_ARRAY */ - -/* Version number of package */ -#define VERSION "0.5.5-SVN" - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Define to 1 if the X Window System is missing or not being used. */ -/* #undef X_DISPLAY_MISSING */ - -/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a - `char[]'. */ -/* #undef YYTEXT_POINTER */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define curl_free() as free() if our version of curl lacks curl_free. */ -/* #undef curl_free */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#define inline __inline -/* #undef inline */ -#endif - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -/* Define strcasecmp as stricmp if you have one but not the other */ -#define strcasecmp stricmp - -/* new stuff, for VC2005 compatibility (phrosty) */ - -#define _CRT_SECURE_NO_WARNINGS -#define _CRT_NONSTDC_NO_WARNINGS - -/* used in qfcc. should #define to _ReturnAddress()? */ -#define __builtin_return_address(x) (0) - -#define _WIN32_WINNT 0x0500 -#define DIRECTINPUT_VERSION 0x0600 - -#define INITGUID - -#define snprintf _snprintf -#define strncasecmp strnicmp - -#define ssize_t ptrdiff_t -#define S_ISDIR(mode) (mode & _S_IFDIR) - -/* used in access() */ -#define R_OK 04 - -/* - disable silent conversion warnings for fixing later.. - - 4047: 'operator' : 'identifier1' differs in levels of indirection from 'identifier2' - 4244: 'argument' : conversion from 'type1' to 'type2', possible loss of data - 4267: 'var' : conversion from 'size_t' to 'type', possible loss of data (/Wp64 warning) - 4305: 'identifier' : truncation from 'type1' to 'type2' - 4311: 'variable' : pointer truncation from 'type' to 'type' (/Wp64 warning) - 4312: 'operation' : conversion from 'type1' to 'type2' of greater size (/Wp64 warning) -*/ -#pragma warning(disable:4047 4244 4267 4305 4311 4312) diff --git a/vc2005/models-sw/models-sw.vcproj b/vc2005/models-sw/models-sw.vcproj deleted file mode 100644 index 6eb490b83..000000000 --- a/vc2005/models-sw/models-sw.vcproj +++ /dev/null @@ -1,511 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/models/models.vcproj b/vc2005/models/models.vcproj deleted file mode 100644 index 06c14ed04..000000000 --- a/vc2005/models/models.vcproj +++ /dev/null @@ -1,489 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/modelsgl/modelsgl.vcproj b/vc2005/modelsgl/modelsgl.vcproj deleted file mode 100644 index 4f455edbe..000000000 --- a/vc2005/modelsgl/modelsgl.vcproj +++ /dev/null @@ -1,521 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/net-main/net-main.vcproj b/vc2005/net-main/net-main.vcproj deleted file mode 100644 index d986b743a..000000000 --- a/vc2005/net-main/net-main.vcproj +++ /dev/null @@ -1,487 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/net/net.vcproj b/vc2005/net/net.vcproj deleted file mode 100644 index 5b43da9e5..000000000 --- a/vc2005/net/net.vcproj +++ /dev/null @@ -1,473 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/nq-common/nq-common.vcproj b/vc2005/nq-common/nq-common.vcproj deleted file mode 100644 index 0dccdd9a4..000000000 --- a/vc2005/nq-common/nq-common.vcproj +++ /dev/null @@ -1,515 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/nq-sdl/nq-sdl.vcproj b/vc2005/nq-sdl/nq-sdl.vcproj deleted file mode 100644 index f4813f262..000000000 --- a/vc2005/nq-sdl/nq-sdl.vcproj +++ /dev/null @@ -1,561 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/nq-sdl32/nq-sdl32.vcproj b/vc2005/nq-sdl32/nq-sdl32.vcproj deleted file mode 100644 index 9c46d06f4..000000000 --- a/vc2005/nq-sdl32/nq-sdl32.vcproj +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/nq-server/nq-server.vcproj b/vc2005/nq-server/nq-server.vcproj deleted file mode 100644 index 2b89d7bbe..000000000 --- a/vc2005/nq-server/nq-server.vcproj +++ /dev/null @@ -1,571 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/nq-sgl/nq-sgl.vcproj b/vc2005/nq-sgl/nq-sgl.vcproj deleted file mode 100644 index 3e61b1f10..000000000 --- a/vc2005/nq-sgl/nq-sgl.vcproj +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/nq-wgl/nq-wgl.vcproj b/vc2005/nq-wgl/nq-wgl.vcproj deleted file mode 100644 index a789c0871..000000000 --- a/vc2005/nq-wgl/nq-wgl.vcproj +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/nq/nq.vcproj b/vc2005/nq/nq.vcproj deleted file mode 100644 index 82cf3e55f..000000000 --- a/vc2005/nq/nq.vcproj +++ /dev/null @@ -1,543 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/pak/pak.vcproj b/vc2005/pak/pak.vcproj deleted file mode 100644 index 0daa6d627..000000000 --- a/vc2005/pak/pak.vcproj +++ /dev/null @@ -1,571 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qfbsp/qfbsp.vcproj b/vc2005/qfbsp/qfbsp.vcproj deleted file mode 100644 index 461d6734b..000000000 --- a/vc2005/qfbsp/qfbsp.vcproj +++ /dev/null @@ -1,637 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qfcc/FlexBison.rules b/vc2005/qfcc/FlexBison.rules deleted file mode 100644 index 0e4c1e3dc..000000000 --- a/vc2005/qfcc/FlexBison.rules +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qfcc/qfcc.vcproj b/vc2005/qfcc/qfcc.vcproj deleted file mode 100644 index 786974fe1..000000000 --- a/vc2005/qfcc/qfcc.vcproj +++ /dev/null @@ -1,970 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qfclient/qfclient.vcproj b/vc2005/qfclient/qfclient.vcproj deleted file mode 100644 index 19d1fac4d..000000000 --- a/vc2005/qfclient/qfclient.vcproj +++ /dev/null @@ -1,625 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qflight/qflight.vcproj b/vc2005/qflight/qflight.vcproj deleted file mode 100644 index 820cbc14a..000000000 --- a/vc2005/qflight/qflight.vcproj +++ /dev/null @@ -1,625 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qfmodelgen/qfmodelgen.vcproj b/vc2005/qfmodelgen/qfmodelgen.vcproj deleted file mode 100644 index 24436bea5..000000000 --- a/vc2005/qfmodelgen/qfmodelgen.vcproj +++ /dev/null @@ -1,583 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qfprogs/qfprogs.vcproj b/vc2005/qfprogs/qfprogs.vcproj deleted file mode 100644 index d77e43a2e..000000000 --- a/vc2005/qfprogs/qfprogs.vcproj +++ /dev/null @@ -1,595 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qfserver/qfserver.vcproj b/vc2005/qfserver/qfserver.vcproj deleted file mode 100644 index 2852ccec3..000000000 --- a/vc2005/qfserver/qfserver.vcproj +++ /dev/null @@ -1,677 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qfvis/qfvis.vcproj b/vc2005/qfvis/qfvis.vcproj deleted file mode 100644 index 4e34daab8..000000000 --- a/vc2005/qfvis/qfvis.vcproj +++ /dev/null @@ -1,593 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qfwavinfo/qfwavinfo.vcproj b/vc2005/qfwavinfo/qfwavinfo.vcproj deleted file mode 100644 index 9e2ead0d5..000000000 --- a/vc2005/qfwavinfo/qfwavinfo.vcproj +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qtv/qtv.vcproj b/vc2005/qtv/qtv.vcproj deleted file mode 100644 index 127035507..000000000 --- a/vc2005/qtv/qtv.vcproj +++ /dev/null @@ -1,599 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qw-client-sdl/qw-client-sdl.vcproj b/vc2005/qw-client-sdl/qw-client-sdl.vcproj deleted file mode 100644 index 188d11f88..000000000 --- a/vc2005/qw-client-sdl/qw-client-sdl.vcproj +++ /dev/null @@ -1,563 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qw-client-sdl32/qw-client-sdl32.vcproj b/vc2005/qw-client-sdl32/qw-client-sdl32.vcproj deleted file mode 100644 index ccbdb9c89..000000000 --- a/vc2005/qw-client-sdl32/qw-client-sdl32.vcproj +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qw-client-sgl/qw-client-sgl.vcproj b/vc2005/qw-client-sgl/qw-client-sgl.vcproj deleted file mode 100644 index 22adf9217..000000000 --- a/vc2005/qw-client-sgl/qw-client-sgl.vcproj +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qw-client-wgl/qw-client-wgl.vcproj b/vc2005/qw-client-wgl/qw-client-wgl.vcproj deleted file mode 100644 index 96fb8c16a..000000000 --- a/vc2005/qw-client-wgl/qw-client-wgl.vcproj +++ /dev/null @@ -1,563 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qw-master/qw-master.vcproj b/vc2005/qw-master/qw-master.vcproj deleted file mode 100644 index a8605e358..000000000 --- a/vc2005/qw-master/qw-master.vcproj +++ /dev/null @@ -1,567 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/qw/qw.vcproj b/vc2005/qw/qw.vcproj deleted file mode 100644 index d73566194..000000000 --- a/vc2005/qw/qw.vcproj +++ /dev/null @@ -1,473 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/readme.txt b/vc2005/readme.txt deleted file mode 100644 index 8c50717db..000000000 --- a/vc2005/readme.txt +++ /dev/null @@ -1,27 +0,0 @@ -Requirements -============= -- Visual C++ 2005 SP1 -- Windows Vista SDK (previous RC compilers won't recognize the - high-resolution Vista icon) -- DirectX SDK (for DirectInput) -- SDL (required for sdl, sdl32, and sgl builds) -- bison/flex (required for qfcc, needs to be in your compiler path) - -Optional -========= -- zlib (#undef HAVE_ZLIB from vc2005/include/config.h if you don't want - this). Expects zlib.lib and zlib.dll for Debug/Release builds, and - libzlib.lib for Release (static) build. -- libcurl (#undef HAVE_LIBCURL from vc2005/include/config.h if you don't - want this). Expects curl.lib and curl.dll for Debug/Release builds, - and libcurl.lib for Release (static) build. - -Notes -====== -By default, qfcc is configured to use the Boost Wave preprocessor. You -can get this from http://www.boost.org, or change the CPP_NAME #define in -vc2005/include/config.h to whatever preprocessor you want. If you have -GCC, you can simply replace "wave --c99" with "gcc" in the define and it -should work. - -clean.ps1 is a Windows Powershell script that cleans up any build files. diff --git a/vc2005/ruamoko/ruamoko.vcproj b/vc2005/ruamoko/ruamoko.vcproj deleted file mode 100644 index 93fd48673..000000000 --- a/vc2005/ruamoko/ruamoko.vcproj +++ /dev/null @@ -1,517 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/sound/sound.vcproj b/vc2005/sound/sound.vcproj deleted file mode 100644 index 50c25ce4c..000000000 --- a/vc2005/sound/sound.vcproj +++ /dev/null @@ -1,513 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/util/util.vcproj b/vc2005/util/util.vcproj deleted file mode 100644 index 021e3d655..000000000 --- a/vc2005/util/util.vcproj +++ /dev/null @@ -1,617 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/video-sdl/video-sdl.vcproj b/vc2005/video-sdl/video-sdl.vcproj deleted file mode 100644 index 5efd89c56..000000000 --- a/vc2005/video-sdl/video-sdl.vcproj +++ /dev/null @@ -1,471 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/video-sgl/video-sgl.vcproj b/vc2005/video-sgl/video-sgl.vcproj deleted file mode 100644 index 94be99a3a..000000000 --- a/vc2005/video-sgl/video-sgl.vcproj +++ /dev/null @@ -1,467 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/video-sw/video-sw.vcproj b/vc2005/video-sw/video-sw.vcproj deleted file mode 100644 index 9158369bf..000000000 --- a/vc2005/video-sw/video-sw.vcproj +++ /dev/null @@ -1,595 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/video-sw32/video-sw32.vcproj b/vc2005/video-sw32/video-sw32.vcproj deleted file mode 100644 index fd4ed7caa..000000000 --- a/vc2005/video-sw32/video-sw32.vcproj +++ /dev/null @@ -1,571 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/video-wgl/video-wgl.vcproj b/vc2005/video-wgl/video-wgl.vcproj deleted file mode 100644 index 0087c8b78..000000000 --- a/vc2005/video-wgl/video-wgl.vcproj +++ /dev/null @@ -1,471 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/video/video.vcproj b/vc2005/video/video.vcproj deleted file mode 100644 index 44213b2a4..000000000 --- a/vc2005/video/video.vcproj +++ /dev/null @@ -1,537 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/videogl/videogl.vcproj b/vc2005/videogl/videogl.vcproj deleted file mode 100644 index cfd456dc5..000000000 --- a/vc2005/videogl/videogl.vcproj +++ /dev/null @@ -1,555 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2005/wad/wad.vcproj b/vc2005/wad/wad.vcproj deleted file mode 100644 index 044bff20a..000000000 --- a/vc2005/wad/wad.vcproj +++ /dev/null @@ -1,579 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/Makefile.am b/vc2008/Makefile.am deleted file mode 100644 index 04c53f194..000000000 --- a/vc2008/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -## Process this file with automake to produce Makefile.in -AUTOMAKE_OPTIONS= foreign -EXTRA_DIST = \ - Makefile.am QuakeForge.sln bsp2img/bsp2img.vcproj \ - builtins/builtins.vcproj clean.ps1 common/common.vcproj \ - console/console.vcproj console_client/console_client.vcproj \ - console_server/console_server.vcproj engine/engine.vcproj gib/gib.vcproj \ - hw-master/hw-master.vcproj image/image.vcproj include/config.h \ - models-sw/models-sw.vcproj models/models.vcproj modelsgl/modelsgl.vcproj \ - net-main/net-main.vcproj net/net.vcproj nq-common/nq-common.vcproj \ - nq-sdl/nq-sdl.vcproj nq-sdl32/nq-sdl32.vcproj nq-server/nq-server.vcproj \ - nq-sgl/nq-sgl.vcproj nq-wgl/nq-wgl.vcproj nq/nq.vcproj pak/pak.vcproj \ - qfbsp/qfbsp.vcproj qfcc/FlexBison.rules qfcc/qfcc.vcproj \ - qfclient/qfclient.vcproj qflight/qflight.vcproj \ - qfmodelgen/qfmodelgen.vcproj qfprogs/qfprogs.vcproj \ - qfserver/qfserver.vcproj qfvis/qfvis.vcproj qfwavinfo/qfwavinfo.vcproj \ - qtv/qtv.vcproj qw-client-sdl/qw-client-sdl.vcproj \ - qw-client-sdl32/qw-client-sdl32.vcproj qw-client-sgl/qw-client-sgl.vcproj \ - qw-client-wgl/qw-client-wgl.vcproj qw-master/qw-master.vcproj \ - qw/qw.vcproj readme.txt ruamoko/ruamoko.vcproj sound/sound.vcproj \ - util/util.vcproj video-sdl/video-sdl.vcproj video-sgl/video-sgl.vcproj \ - video-sw/video-sw.vcproj video-sw32/video-sw32.vcproj \ - video-wgl/video-wgl.vcproj video/video.vcproj videogl/videogl.vcproj \ - wad/wad.vcproj diff --git a/vc2008/QuakeForge.sln b/vc2008/QuakeForge.sln deleted file mode 100644 index 296484c89..000000000 --- a/vc2008/QuakeForge.sln +++ /dev/null @@ -1,966 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{3CDA2798-7565-47C5-B972-F9E63DBEFFFA}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client", "qfclient\qfclient.vcproj", "{9A942925-61E6-4975-935A-5D62E8248E64}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw", "qw\qw.vcproj", "{6ADA4322-693A-46BB-897B-17BB5BE9F08C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "net-chan", "net\net.vcproj", "{6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ruamoko", "ruamoko\ruamoko.vcproj", "{51028ACF-53D4-4478-8500-55E6B8A81375}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models-gl", "modelsgl\modelsgl.vcproj", "{1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console", "console\console.vcproj", "{ED4AFBF5-C247-4352-966D-048B8998C6A1}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gib", "gib\gib.vcproj", "{01C3B138-9D45-4ED6-A763-893C067262C2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "util", "util\util.vcproj", "{ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine", "engine\engine.vcproj", "{2626C0E1-6F5C-47D3-B80D-93942D766DD7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "builtins", "builtins\builtins.vcproj", "{04FA9D77-E45F-4917-B972-B353BA6A6FA8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sound", "sound\sound.vcproj", "{BF149D97-7520-4788-9CD1-3D99C5C8150F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "image", "image\image.vcproj", "{5203F034-0047-4EC0-B7E9-D037FAF5D536}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video", "video\video.vcproj", "{E7B3D07D-2FE8-481B-8DAB-6255A412A42F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-common", "common\common.vcproj", "{BC1F021A-1EEC-4A7A-B746-5AA6048E478C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-server", "qfserver\qfserver.vcproj", "{544D097C-9C24-4C57-A171-8C8029421185}" - ProjectSection(ProjectDependencies) = postProject - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} = {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models", "models\models.vcproj", "{DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console-client", "console_client\console_client.vcproj", "{226D42CE-5833-444E-94FA-84C1D51892A8}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "console-server", "console_server\console_server.vcproj", "{B37FE734-01F4-4799-86B2-D084820715BE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfbsp", "qfbsp\qfbsp.vcproj", "{B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qflight", "qflight\qflight.vcproj", "{5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfvis", "qfvis\qfvis.vcproj", "{E5D842C5-669F-4FC7-A5E0-44B562F86435}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-master", "qw-master\qw-master.vcproj", "{445A2500-3BBC-449A-A929-C419C2A16051}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfmodelgen", "qfmodelgen\qfmodelgen.vcproj", "{052C34FE-C9E2-43ED-95DA-FB3F27B44E37}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfprogs", "qfprogs\qfprogs.vcproj", "{5FA27C8E-51B1-445A-A375-FBE74F0984B1}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfwavinfo", "qfwavinfo\qfwavinfo.vcproj", "{56BD559B-1590-4FC4-B441-AB1973BAC2BD}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wad", "wad\wad.vcproj", "{88422448-C5FB-46F3-A0B3-0811F90E537C}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pak", "pak\pak.vcproj", "{9EE8BD4B-47D3-4AD5-A8B9-831329792A05}" - ProjectSection(ProjectDependencies) = postProject - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bsp2img", "bsp2img\bsp2img.vcproj", "{4605418D-2292-470A-AB18-C2119B016F71}" - ProjectSection(ProjectDependencies) = postProject - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtv", "qtv\qtv.vcproj", "{05E68E3B-5901-43A9-981D-CF392C0F5C6C}" - ProjectSection(ProjectDependencies) = postProject - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-common", "nq-common\nq-common.vcproj", "{6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-wgl", "nq-wgl\nq-wgl.vcproj", "{1CD1A18B-95D5-4EA4-917C-34B10066BFCC}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} = {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "net-main", "net-main\net-main.vcproj", "{053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-server", "nq-server\nq-server.vcproj", "{231C032C-DE16-459A-8E7D-6509C2EC3998}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} = {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hw-master", "hw-master\hw-master.vcproj", "{419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}" - ProjectSection(ProjectDependencies) = postProject - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qfcc", "qfcc\qfcc.vcproj", "{40639893-4D75-48CD-811F-4B363CC71FFA}" - ProjectSection(ProjectDependencies) = postProject - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-wgl", "qw-client-wgl\qw-client-wgl.vcproj", "{5FD733BF-B3C6-4A96-BED7-35E2484448E1}" - ProjectSection(ProjectDependencies) = postProject - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} = {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-sgl", "qw-client-sgl\qw-client-sgl.vcproj", "{649C4168-1C65-4E41-818F-85A1C52C1B8F}" - ProjectSection(ProjectDependencies) = postProject - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {7E30C3B1-AEE7-483D-B231-C672365CD2D7} = {7E30C3B1-AEE7-483D-B231-C672365CD2D7} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-gl", "videogl\videogl.vcproj", "{C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sdl", "video-sdl\video-sdl.vcproj", "{44A18410-3AA8-4A64-935B-D20223AD6885}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-sdl", "qw-client-sdl\qw-client-sdl.vcproj", "{B44CB3E0-F2FD-4260-A632-C01FB881613E}" - ProjectSection(ProjectDependencies) = postProject - {66D3A191-E4D5-45F3-86BD-EFBB249CD554} = {66D3A191-E4D5-45F3-86BD-EFBB249CD554} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models-sw", "models-sw\models-sw.vcproj", "{F4A9881E-0EB0-44A1-9664-B6CBDE992861}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sw", "video-sw\video-sw.vcproj", "{66D3A191-E4D5-45F3-86BD-EFBB249CD554}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qw-client-sdl32", "qw-client-sdl32\qw-client-sdl32.vcproj", "{CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}" - ProjectSection(ProjectDependencies) = postProject - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {6ADA4322-693A-46BB-897B-17BB5BE9F08C} - {9A942925-61E6-4975-935A-5D62E8248E64} = {9A942925-61E6-4975-935A-5D62E8248E64} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {D5B9558F-EF25-4167-ACE4-723C7413B390} = {D5B9558F-EF25-4167-ACE4-723C7413B390} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sw32", "video-sw32\video-sw32.vcproj", "{D5B9558F-EF25-4167-ACE4-723C7413B390}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq", "nq\nq.vcproj", "{155112B9-A8A9-4E06-90F5-4AAAB32B2F70}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-wgl", "video-wgl\video-wgl.vcproj", "{178D81A7-F2FB-41D7-B300-9D1A4DE5E137}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "video-sgl", "video-sgl\video-sgl.vcproj", "{7E30C3B1-AEE7-483D-B231-C672365CD2D7}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-sgl", "nq-sgl\nq-sgl.vcproj", "{2E26DB8B-9E37-4072-B397-8A7086E0ACD0}" - ProjectSection(ProjectDependencies) = postProject - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {7E30C3B1-AEE7-483D-B231-C672365CD2D7} = {7E30C3B1-AEE7-483D-B231-C672365CD2D7} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-sdl", "nq-sdl\nq-sdl.vcproj", "{2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}" - ProjectSection(ProjectDependencies) = postProject - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {66D3A191-E4D5-45F3-86BD-EFBB249CD554} = {66D3A191-E4D5-45F3-86BD-EFBB249CD554} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nq-sdl32", "nq-sdl32\nq-sdl32.vcproj", "{2CEB1965-A89C-4422-A9AC-B30FCE7913C3}" - ProjectSection(ProjectDependencies) = postProject - {44A18410-3AA8-4A64-935B-D20223AD6885} = {44A18410-3AA8-4A64-935B-D20223AD6885} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {F4A9881E-0EB0-44A1-9664-B6CBDE992861} - {B37FE734-01F4-4799-86B2-D084820715BE} = {B37FE734-01F4-4799-86B2-D084820715BE} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {5203F034-0047-4EC0-B7E9-D037FAF5D536} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {01C3B138-9D45-4ED6-A763-893C067262C2} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {04FA9D77-E45F-4917-B972-B353BA6A6FA8} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} - {D5B9558F-EF25-4167-ACE4-723C7413B390} = {D5B9558F-EF25-4167-ACE4-723C7413B390} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {BF149D97-7520-4788-9CD1-3D99C5C8150F} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {226D42CE-5833-444E-94FA-84C1D51892A8} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {51028ACF-53D4-4478-8500-55E6B8A81375} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {2626C0E1-6F5C-47D3-B80D-93942D766DD7} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {ED4AFBF5-C247-4352-966D-048B8998C6A1} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release (static)|Win32 = Release (static)|Win32 - Release (static)|x64 = Release (static)|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|Win32.ActiveCfg = Debug|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|Win32.Build.0 = Debug|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|x64.ActiveCfg = Debug|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Debug|x64.Build.0 = Debug|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release (static)|x64.Build.0 = Release (static)|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|Win32.ActiveCfg = Release|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|Win32.Build.0 = Release|Win32 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|x64.ActiveCfg = Release|x64 - {9A942925-61E6-4975-935A-5D62E8248E64}.Release|x64.Build.0 = Release|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|Win32.ActiveCfg = Debug|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|Win32.Build.0 = Debug|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|x64.ActiveCfg = Debug|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Debug|x64.Build.0 = Debug|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release (static)|x64.Build.0 = Release (static)|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|Win32.ActiveCfg = Release|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|Win32.Build.0 = Release|Win32 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|x64.ActiveCfg = Release|x64 - {6ADA4322-693A-46BB-897B-17BB5BE9F08C}.Release|x64.Build.0 = Release|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|Win32.ActiveCfg = Debug|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|Win32.Build.0 = Debug|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|x64.ActiveCfg = Debug|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Debug|x64.Build.0 = Debug|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release (static)|x64.Build.0 = Release (static)|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|Win32.ActiveCfg = Release|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|Win32.Build.0 = Release|Win32 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|x64.ActiveCfg = Release|x64 - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0}.Release|x64.Build.0 = Release|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|Win32.ActiveCfg = Debug|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|Win32.Build.0 = Debug|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|x64.ActiveCfg = Debug|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Debug|x64.Build.0 = Debug|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release (static)|x64.Build.0 = Release (static)|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|Win32.ActiveCfg = Release|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|Win32.Build.0 = Release|Win32 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|x64.ActiveCfg = Release|x64 - {51028ACF-53D4-4478-8500-55E6B8A81375}.Release|x64.Build.0 = Release|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|Win32.ActiveCfg = Debug|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|Win32.Build.0 = Debug|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|x64.ActiveCfg = Debug|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Debug|x64.Build.0 = Debug|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release (static)|x64.Build.0 = Release (static)|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|Win32.ActiveCfg = Release|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|Win32.Build.0 = Release|Win32 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|x64.ActiveCfg = Release|x64 - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7}.Release|x64.Build.0 = Release|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|Win32.ActiveCfg = Debug|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|Win32.Build.0 = Debug|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|x64.ActiveCfg = Debug|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Debug|x64.Build.0 = Debug|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release (static)|x64.Build.0 = Release (static)|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|Win32.ActiveCfg = Release|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|Win32.Build.0 = Release|Win32 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|x64.ActiveCfg = Release|x64 - {ED4AFBF5-C247-4352-966D-048B8998C6A1}.Release|x64.Build.0 = Release|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|Win32.ActiveCfg = Debug|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|Win32.Build.0 = Debug|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|x64.ActiveCfg = Debug|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Debug|x64.Build.0 = Debug|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release (static)|x64.Build.0 = Release (static)|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|Win32.ActiveCfg = Release|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|Win32.Build.0 = Release|Win32 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|x64.ActiveCfg = Release|x64 - {01C3B138-9D45-4ED6-A763-893C067262C2}.Release|x64.Build.0 = Release|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|Win32.ActiveCfg = Debug|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|Win32.Build.0 = Debug|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|x64.ActiveCfg = Debug|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Debug|x64.Build.0 = Debug|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release (static)|x64.Build.0 = Release (static)|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|Win32.ActiveCfg = Release|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|Win32.Build.0 = Release|Win32 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|x64.ActiveCfg = Release|x64 - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB}.Release|x64.Build.0 = Release|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|Win32.ActiveCfg = Debug|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|Win32.Build.0 = Debug|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|x64.ActiveCfg = Debug|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Debug|x64.Build.0 = Debug|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release (static)|x64.Build.0 = Release (static)|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|Win32.ActiveCfg = Release|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|Win32.Build.0 = Release|Win32 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|x64.ActiveCfg = Release|x64 - {2626C0E1-6F5C-47D3-B80D-93942D766DD7}.Release|x64.Build.0 = Release|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|Win32.ActiveCfg = Debug|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|Win32.Build.0 = Debug|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|x64.ActiveCfg = Debug|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Debug|x64.Build.0 = Debug|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release (static)|x64.Build.0 = Release (static)|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|Win32.ActiveCfg = Release|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|Win32.Build.0 = Release|Win32 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|x64.ActiveCfg = Release|x64 - {04FA9D77-E45F-4917-B972-B353BA6A6FA8}.Release|x64.Build.0 = Release|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|Win32.ActiveCfg = Debug|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|Win32.Build.0 = Debug|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|x64.ActiveCfg = Debug|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Debug|x64.Build.0 = Debug|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release (static)|x64.Build.0 = Release (static)|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|Win32.ActiveCfg = Release|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|Win32.Build.0 = Release|Win32 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|x64.ActiveCfg = Release|x64 - {BF149D97-7520-4788-9CD1-3D99C5C8150F}.Release|x64.Build.0 = Release|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|Win32.ActiveCfg = Debug|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|Win32.Build.0 = Debug|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|x64.ActiveCfg = Debug|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Debug|x64.Build.0 = Debug|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release (static)|x64.Build.0 = Release (static)|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|Win32.ActiveCfg = Release|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|Win32.Build.0 = Release|Win32 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|x64.ActiveCfg = Release|x64 - {5203F034-0047-4EC0-B7E9-D037FAF5D536}.Release|x64.Build.0 = Release|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|Win32.ActiveCfg = Debug|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|Win32.Build.0 = Debug|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|x64.ActiveCfg = Debug|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Debug|x64.Build.0 = Debug|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release (static)|x64.Build.0 = Release (static)|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|Win32.ActiveCfg = Release|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|Win32.Build.0 = Release|Win32 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|x64.ActiveCfg = Release|x64 - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F}.Release|x64.Build.0 = Release|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|Win32.ActiveCfg = Debug|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|Win32.Build.0 = Debug|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|x64.ActiveCfg = Debug|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Debug|x64.Build.0 = Debug|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release (static)|x64.Build.0 = Release (static)|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|Win32.ActiveCfg = Release|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|Win32.Build.0 = Release|Win32 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|x64.ActiveCfg = Release|x64 - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C}.Release|x64.Build.0 = Release|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|Win32.ActiveCfg = Debug|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|Win32.Build.0 = Debug|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|x64.ActiveCfg = Debug|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Debug|x64.Build.0 = Debug|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release (static)|x64.Build.0 = Release (static)|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|Win32.ActiveCfg = Release|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|Win32.Build.0 = Release|Win32 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|x64.ActiveCfg = Release|x64 - {544D097C-9C24-4C57-A171-8C8029421185}.Release|x64.Build.0 = Release|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|Win32.ActiveCfg = Debug|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|Win32.Build.0 = Debug|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|x64.ActiveCfg = Debug|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Debug|x64.Build.0 = Debug|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release (static)|x64.Build.0 = Release (static)|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|Win32.ActiveCfg = Release|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|Win32.Build.0 = Release|Win32 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|x64.ActiveCfg = Release|x64 - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A}.Release|x64.Build.0 = Release|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|Win32.ActiveCfg = Debug|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|Win32.Build.0 = Debug|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|x64.ActiveCfg = Debug|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Debug|x64.Build.0 = Debug|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release (static)|x64.Build.0 = Release (static)|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|Win32.ActiveCfg = Release|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|Win32.Build.0 = Release|Win32 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|x64.ActiveCfg = Release|x64 - {226D42CE-5833-444E-94FA-84C1D51892A8}.Release|x64.Build.0 = Release|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|Win32.ActiveCfg = Debug|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|Win32.Build.0 = Debug|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|x64.ActiveCfg = Debug|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Debug|x64.Build.0 = Debug|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release (static)|x64.Build.0 = Release (static)|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|Win32.ActiveCfg = Release|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|Win32.Build.0 = Release|Win32 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|x64.ActiveCfg = Release|x64 - {B37FE734-01F4-4799-86B2-D084820715BE}.Release|x64.Build.0 = Release|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|Win32.ActiveCfg = Debug|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|Win32.Build.0 = Debug|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|x64.ActiveCfg = Debug|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Debug|x64.Build.0 = Debug|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release (static)|x64.Build.0 = Release (static)|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|Win32.ActiveCfg = Release|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|Win32.Build.0 = Release|Win32 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|x64.ActiveCfg = Release|x64 - {B00D4025-0437-4FF2-BD0E-D2AE6CF82AC2}.Release|x64.Build.0 = Release|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|Win32.ActiveCfg = Debug|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|Win32.Build.0 = Debug|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|x64.ActiveCfg = Debug|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Debug|x64.Build.0 = Debug|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release (static)|x64.Build.0 = Release (static)|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|Win32.ActiveCfg = Release|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|Win32.Build.0 = Release|Win32 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|x64.ActiveCfg = Release|x64 - {5E7E6110-89E8-4797-A8E3-EBEF0EF5CAF2}.Release|x64.Build.0 = Release|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|Win32.ActiveCfg = Debug|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|Win32.Build.0 = Debug|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|x64.ActiveCfg = Debug|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Debug|x64.Build.0 = Debug|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release (static)|x64.Build.0 = Release (static)|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|Win32.ActiveCfg = Release|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|Win32.Build.0 = Release|Win32 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|x64.ActiveCfg = Release|x64 - {E5D842C5-669F-4FC7-A5E0-44B562F86435}.Release|x64.Build.0 = Release|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|Win32.ActiveCfg = Debug|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|Win32.Build.0 = Debug|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|x64.ActiveCfg = Debug|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Debug|x64.Build.0 = Debug|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release (static)|x64.Build.0 = Release (static)|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|Win32.ActiveCfg = Release|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|Win32.Build.0 = Release|Win32 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|x64.ActiveCfg = Release|x64 - {445A2500-3BBC-449A-A929-C419C2A16051}.Release|x64.Build.0 = Release|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|Win32.ActiveCfg = Debug|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|Win32.Build.0 = Debug|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|x64.ActiveCfg = Debug|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Debug|x64.Build.0 = Debug|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release (static)|x64.Build.0 = Release (static)|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|Win32.ActiveCfg = Release|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|Win32.Build.0 = Release|Win32 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|x64.ActiveCfg = Release|x64 - {052C34FE-C9E2-43ED-95DA-FB3F27B44E37}.Release|x64.Build.0 = Release|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|Win32.ActiveCfg = Debug|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|Win32.Build.0 = Debug|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|x64.ActiveCfg = Debug|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Debug|x64.Build.0 = Debug|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release (static)|x64.Build.0 = Release (static)|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|Win32.ActiveCfg = Release|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|Win32.Build.0 = Release|Win32 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|x64.ActiveCfg = Release|x64 - {5FA27C8E-51B1-445A-A375-FBE74F0984B1}.Release|x64.Build.0 = Release|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|Win32.ActiveCfg = Debug|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|Win32.Build.0 = Debug|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|x64.ActiveCfg = Debug|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Debug|x64.Build.0 = Debug|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release (static)|x64.Build.0 = Release (static)|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|Win32.ActiveCfg = Release|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|Win32.Build.0 = Release|Win32 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|x64.ActiveCfg = Release|x64 - {56BD559B-1590-4FC4-B441-AB1973BAC2BD}.Release|x64.Build.0 = Release|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|Win32.ActiveCfg = Debug|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|Win32.Build.0 = Debug|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|x64.ActiveCfg = Debug|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Debug|x64.Build.0 = Debug|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release (static)|x64.Build.0 = Release (static)|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|Win32.ActiveCfg = Release|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|Win32.Build.0 = Release|Win32 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|x64.ActiveCfg = Release|x64 - {88422448-C5FB-46F3-A0B3-0811F90E537C}.Release|x64.Build.0 = Release|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|Win32.ActiveCfg = Debug|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|Win32.Build.0 = Debug|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|x64.ActiveCfg = Debug|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Debug|x64.Build.0 = Debug|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release (static)|x64.Build.0 = Release (static)|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|Win32.ActiveCfg = Release|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|Win32.Build.0 = Release|Win32 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|x64.ActiveCfg = Release|x64 - {9EE8BD4B-47D3-4AD5-A8B9-831329792A05}.Release|x64.Build.0 = Release|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|Win32.ActiveCfg = Debug|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|Win32.Build.0 = Debug|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|x64.ActiveCfg = Debug|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Debug|x64.Build.0 = Debug|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release (static)|x64.Build.0 = Release (static)|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|Win32.ActiveCfg = Release|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|Win32.Build.0 = Release|Win32 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|x64.ActiveCfg = Release|x64 - {4605418D-2292-470A-AB18-C2119B016F71}.Release|x64.Build.0 = Release|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|Win32.ActiveCfg = Debug|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|Win32.Build.0 = Debug|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|x64.ActiveCfg = Debug|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Debug|x64.Build.0 = Debug|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release (static)|x64.Build.0 = Release (static)|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|Win32.ActiveCfg = Release|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|Win32.Build.0 = Release|Win32 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|x64.ActiveCfg = Release|x64 - {05E68E3B-5901-43A9-981D-CF392C0F5C6C}.Release|x64.Build.0 = Release|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|Win32.ActiveCfg = Debug|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|Win32.Build.0 = Debug|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|x64.ActiveCfg = Debug|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Debug|x64.Build.0 = Debug|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release (static)|x64.Build.0 = Release (static)|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|Win32.ActiveCfg = Release|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|Win32.Build.0 = Release|Win32 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|x64.ActiveCfg = Release|x64 - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80}.Release|x64.Build.0 = Release|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|Win32.ActiveCfg = Debug|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|Win32.Build.0 = Debug|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|x64.ActiveCfg = Debug|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Debug|x64.Build.0 = Debug|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release (static)|x64.Build.0 = Release (static)|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|Win32.ActiveCfg = Release|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|Win32.Build.0 = Release|Win32 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|x64.ActiveCfg = Release|x64 - {1CD1A18B-95D5-4EA4-917C-34B10066BFCC}.Release|x64.Build.0 = Release|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|Win32.ActiveCfg = Debug|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|Win32.Build.0 = Debug|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|x64.ActiveCfg = Debug|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Debug|x64.Build.0 = Debug|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release (static)|x64.Build.0 = Release (static)|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|Win32.ActiveCfg = Release|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|Win32.Build.0 = Release|Win32 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|x64.ActiveCfg = Release|x64 - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5}.Release|x64.Build.0 = Release|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|Win32.ActiveCfg = Debug|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|Win32.Build.0 = Debug|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|x64.ActiveCfg = Debug|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Debug|x64.Build.0 = Debug|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release (static)|x64.Build.0 = Release (static)|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|Win32.ActiveCfg = Release|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|Win32.Build.0 = Release|Win32 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|x64.ActiveCfg = Release|x64 - {231C032C-DE16-459A-8E7D-6509C2EC3998}.Release|x64.Build.0 = Release|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|Win32.ActiveCfg = Debug|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|Win32.Build.0 = Debug|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|x64.ActiveCfg = Debug|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Debug|x64.Build.0 = Debug|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release (static)|x64.Build.0 = Release (static)|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|Win32.ActiveCfg = Release|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|Win32.Build.0 = Release|Win32 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|x64.ActiveCfg = Release|x64 - {419FEFBE-D9D5-4149-974B-0FFFC8D0D93F}.Release|x64.Build.0 = Release|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|Win32.ActiveCfg = Debug|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|Win32.Build.0 = Debug|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|x64.ActiveCfg = Debug|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Debug|x64.Build.0 = Debug|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release (static)|x64.Build.0 = Release (static)|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|Win32.ActiveCfg = Release|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|Win32.Build.0 = Release|Win32 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|x64.ActiveCfg = Release|x64 - {40639893-4D75-48CD-811F-4B363CC71FFA}.Release|x64.Build.0 = Release|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Debug|Win32.ActiveCfg = Debug|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Debug|Win32.Build.0 = Debug|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Debug|x64.ActiveCfg = Debug|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release (static)|x64.Build.0 = Release (static)|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|Win32.ActiveCfg = Release|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|Win32.Build.0 = Release|Win32 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|x64.ActiveCfg = Release|x64 - {5FD733BF-B3C6-4A96-BED7-35E2484448E1}.Release|x64.Build.0 = Release|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Debug|Win32.ActiveCfg = Debug|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Debug|Win32.Build.0 = Debug|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Debug|x64.ActiveCfg = Debug|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release (static)|x64.Build.0 = Release (static)|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|Win32.ActiveCfg = Release|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|Win32.Build.0 = Release|Win32 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|x64.ActiveCfg = Release|x64 - {649C4168-1C65-4E41-818F-85A1C52C1B8F}.Release|x64.Build.0 = Release|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Debug|Win32.ActiveCfg = Debug|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Debug|Win32.Build.0 = Debug|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Debug|x64.ActiveCfg = Debug|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release (static)|x64.Build.0 = Release (static)|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|Win32.ActiveCfg = Release|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|Win32.Build.0 = Release|Win32 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|x64.ActiveCfg = Release|x64 - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F}.Release|x64.Build.0 = Release|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Debug|Win32.ActiveCfg = Debug|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Debug|Win32.Build.0 = Debug|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Debug|x64.ActiveCfg = Debug|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release (static)|x64.Build.0 = Release (static)|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|Win32.ActiveCfg = Release|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|Win32.Build.0 = Release|Win32 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|x64.ActiveCfg = Release|x64 - {44A18410-3AA8-4A64-935B-D20223AD6885}.Release|x64.Build.0 = Release|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Debug|Win32.ActiveCfg = Debug|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Debug|Win32.Build.0 = Debug|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Debug|x64.ActiveCfg = Debug|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release (static)|x64.Build.0 = Release (static)|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|Win32.ActiveCfg = Release|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|Win32.Build.0 = Release|Win32 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|x64.ActiveCfg = Release|x64 - {B44CB3E0-F2FD-4260-A632-C01FB881613E}.Release|x64.Build.0 = Release|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Debug|Win32.ActiveCfg = Debug|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Debug|Win32.Build.0 = Debug|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Debug|x64.ActiveCfg = Debug|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release (static)|x64.Build.0 = Release (static)|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|Win32.ActiveCfg = Release|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|Win32.Build.0 = Release|Win32 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|x64.ActiveCfg = Release|x64 - {F4A9881E-0EB0-44A1-9664-B6CBDE992861}.Release|x64.Build.0 = Release|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Debug|Win32.ActiveCfg = Debug|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Debug|Win32.Build.0 = Debug|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Debug|x64.ActiveCfg = Debug|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release (static)|x64.Build.0 = Release (static)|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|Win32.ActiveCfg = Release|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|Win32.Build.0 = Release|Win32 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|x64.ActiveCfg = Release|x64 - {66D3A191-E4D5-45F3-86BD-EFBB249CD554}.Release|x64.Build.0 = Release|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Debug|Win32.ActiveCfg = Debug|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Debug|Win32.Build.0 = Debug|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Debug|x64.ActiveCfg = Debug|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release (static)|x64.Build.0 = Release (static)|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|Win32.ActiveCfg = Release|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|Win32.Build.0 = Release|Win32 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|x64.ActiveCfg = Release|x64 - {CBD0DD82-4DC7-4398-AF32-FD7BFFA3C2D5}.Release|x64.Build.0 = Release|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Debug|Win32.ActiveCfg = Debug|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Debug|Win32.Build.0 = Debug|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Debug|x64.ActiveCfg = Debug|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release (static)|x64.Build.0 = Release (static)|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|Win32.ActiveCfg = Release|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|Win32.Build.0 = Release|Win32 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|x64.ActiveCfg = Release|x64 - {D5B9558F-EF25-4167-ACE4-723C7413B390}.Release|x64.Build.0 = Release|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Debug|Win32.ActiveCfg = Debug|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Debug|Win32.Build.0 = Debug|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Debug|x64.ActiveCfg = Debug|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release (static)|x64.Build.0 = Release (static)|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|Win32.ActiveCfg = Release|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|Win32.Build.0 = Release|Win32 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|x64.ActiveCfg = Release|x64 - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70}.Release|x64.Build.0 = Release|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Debug|Win32.ActiveCfg = Debug|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Debug|Win32.Build.0 = Debug|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Debug|x64.ActiveCfg = Debug|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release (static)|x64.Build.0 = Release (static)|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|Win32.ActiveCfg = Release|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|Win32.Build.0 = Release|Win32 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|x64.ActiveCfg = Release|x64 - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137}.Release|x64.Build.0 = Release|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Debug|Win32.ActiveCfg = Debug|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Debug|Win32.Build.0 = Debug|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Debug|x64.ActiveCfg = Debug|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release (static)|x64.Build.0 = Release (static)|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|Win32.ActiveCfg = Release|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|Win32.Build.0 = Release|Win32 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|x64.ActiveCfg = Release|x64 - {7E30C3B1-AEE7-483D-B231-C672365CD2D7}.Release|x64.Build.0 = Release|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Debug|Win32.ActiveCfg = Debug|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Debug|Win32.Build.0 = Debug|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Debug|x64.ActiveCfg = Debug|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release (static)|x64.Build.0 = Release (static)|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|Win32.ActiveCfg = Release|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|Win32.Build.0 = Release|Win32 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|x64.ActiveCfg = Release|x64 - {2E26DB8B-9E37-4072-B397-8A7086E0ACD0}.Release|x64.Build.0 = Release|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Debug|Win32.ActiveCfg = Debug|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Debug|Win32.Build.0 = Debug|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Debug|x64.ActiveCfg = Debug|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release (static)|x64.Build.0 = Release (static)|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|Win32.ActiveCfg = Release|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|Win32.Build.0 = Release|Win32 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|x64.ActiveCfg = Release|x64 - {2736D4F9-EA8B-4ADF-B2D9-B705FF288A8A}.Release|x64.Build.0 = Release|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Debug|Win32.ActiveCfg = Debug|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Debug|Win32.Build.0 = Debug|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Debug|x64.ActiveCfg = Debug|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|Win32.ActiveCfg = Release (static)|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|Win32.Build.0 = Release (static)|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|x64.ActiveCfg = Release (static)|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release (static)|x64.Build.0 = Release (static)|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|Win32.ActiveCfg = Release|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|Win32.Build.0 = Release|Win32 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|x64.ActiveCfg = Release|x64 - {2CEB1965-A89C-4422-A9AC-B30FCE7913C3}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {9A942925-61E6-4975-935A-5D62E8248E64} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {6ADA4322-693A-46BB-897B-17BB5BE9F08C} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {6540C00F-C5EF-4C8B-824D-F2B7B302F0E0} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {51028ACF-53D4-4478-8500-55E6B8A81375} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {1311DEDF-B04C-4E96-BFDC-5D9FA0B05AC7} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {ED4AFBF5-C247-4352-966D-048B8998C6A1} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {01C3B138-9D45-4ED6-A763-893C067262C2} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {ACCC6F49-7E06-4395-AAF4-3C03A68F49EB} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {2626C0E1-6F5C-47D3-B80D-93942D766DD7} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {04FA9D77-E45F-4917-B972-B353BA6A6FA8} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {BF149D97-7520-4788-9CD1-3D99C5C8150F} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {5203F034-0047-4EC0-B7E9-D037FAF5D536} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {E7B3D07D-2FE8-481B-8DAB-6255A412A42F} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {BC1F021A-1EEC-4A7A-B746-5AA6048E478C} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {DE7E8FF8-0F5D-4062-A5C0-CFA3502E7A5A} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {226D42CE-5833-444E-94FA-84C1D51892A8} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {B37FE734-01F4-4799-86B2-D084820715BE} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {6BA39648-5BD0-4B8D-A8DD-8202FBA1AE80} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {053E1EE2-75B4-4D9A-B8AE-89600BCB60A5} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {C55D5FBF-43A0-4F6C-BCF6-BAE5705C121F} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {44A18410-3AA8-4A64-935B-D20223AD6885} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {F4A9881E-0EB0-44A1-9664-B6CBDE992861} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {66D3A191-E4D5-45F3-86BD-EFBB249CD554} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {D5B9558F-EF25-4167-ACE4-723C7413B390} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {155112B9-A8A9-4E06-90F5-4AAAB32B2F70} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {178D81A7-F2FB-41D7-B300-9D1A4DE5E137} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - {7E30C3B1-AEE7-483D-B231-C672365CD2D7} = {3CDA2798-7565-47C5-B972-F9E63DBEFFFA} - EndGlobalSection -EndGlobal diff --git a/vc2008/bsp2img/bsp2img.vcproj b/vc2008/bsp2img/bsp2img.vcproj deleted file mode 100644 index b4608c799..000000000 --- a/vc2008/bsp2img/bsp2img.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/builtins/builtins.vcproj b/vc2008/builtins/builtins.vcproj deleted file mode 100644 index 43fa081df..000000000 --- a/vc2008/builtins/builtins.vcproj +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/clean.ps1 b/vc2008/clean.ps1 deleted file mode 100644 index b1e75f990..000000000 --- a/vc2008/clean.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -ls -recurse -include 'win32','x64','*.user' | rm -recurse -if(test-path QuakeForge.suo) { rm QuakeForge.suo -force } -if(test-path QuakeForge.ncb) { rm QuakeForge.ncb } \ No newline at end of file diff --git a/vc2008/common/common.vcproj b/vc2008/common/common.vcproj deleted file mode 100644 index 7c1404ac7..000000000 --- a/vc2008/common/common.vcproj +++ /dev/null @@ -1,490 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/console/console.vcproj b/vc2008/console/console.vcproj deleted file mode 100644 index f93f3975f..000000000 --- a/vc2008/console/console.vcproj +++ /dev/null @@ -1,494 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/console_client/console_client.vcproj b/vc2008/console_client/console_client.vcproj deleted file mode 100644 index 0e2a378b0..000000000 --- a/vc2008/console_client/console_client.vcproj +++ /dev/null @@ -1,482 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/console_server/console_server.vcproj b/vc2008/console_server/console_server.vcproj deleted file mode 100644 index 33a611997..000000000 --- a/vc2008/console_server/console_server.vcproj +++ /dev/null @@ -1,470 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/engine/engine.vcproj b/vc2008/engine/engine.vcproj deleted file mode 100644 index 203710bf7..000000000 --- a/vc2008/engine/engine.vcproj +++ /dev/null @@ -1,510 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/gib/gib.vcproj b/vc2008/gib/gib.vcproj deleted file mode 100644 index 3fbb039b6..000000000 --- a/vc2008/gib/gib.vcproj +++ /dev/null @@ -1,538 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/hw-master/hw-master.vcproj b/vc2008/hw-master/hw-master.vcproj deleted file mode 100644 index 0e7273e3b..000000000 --- a/vc2008/hw-master/hw-master.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/image/image.vcproj b/vc2008/image/image.vcproj deleted file mode 100644 index 73970fb11..000000000 --- a/vc2008/image/image.vcproj +++ /dev/null @@ -1,482 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/include/config.h b/vc2008/include/config.h deleted file mode 100644 index 1b787db16..000000000 --- a/vc2008/include/config.h +++ /dev/null @@ -1,740 +0,0 @@ -/* include/config.h. Generated from config.h.in by configure. */ -/* include/config.h.in. Generated from configure.ac by autoheader. */ - -/* list of cd plugins */ -#define CD_PLUGIN_LIST {"cd_win", cd_win_PluginInfo},{0, 0} - -/* list of cd prototypes */ -#define CD_PLUGIN_PROTOS extern plugin_t *cd_win_PluginInfo (void); - -/* list of client plugins */ -#define CLIENT_PLUGIN_LIST {"console_client", console_client_PluginInfo},{0, 0} - -/* list of client prototypes */ -#define CLIENT_PLUGIN_PROTOS extern plugin_t *console_client_PluginInfo (void); - -/* Define this to the command line for the C preprocessor */ -#define CPP_NAME "wave --c99 %d -o %o %i" - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Define this to the location of the global config file */ -#define FS_GLOBALCFG "~/quakeforge.conf" - -/* Define this to the path from which to load plugins */ -#define FS_PLUGINPATH "/usr/local/lib/quakeforge" - -/* Define this to the shared game directory root */ -#define FS_SHAREPATH "." - -/* Define this to the location of the user config file */ -#define FS_USERCFG "~/quakeforgerc" - -/* Define this to the unshared game directory root */ -#define FS_USERPATH "." - -/* Define this to the default GL dynamic lib */ -#define GL_DRIVER "OPENGL32.DLL" - -/* Define to 1 if you have the `access' function. */ -#define HAVE_ACCESS 1 - -/* Define to 1 if you have `alloca', as a function or macro. */ -#define HAVE_ALLOCA 1 - -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -/* #undef HAVE_ALLOCA_H */ - -/* Define this if alloca is prototyped */ -/* #undef HAVE_ALLOCA_PROTO */ -#ifndef HAVE_ALLOCA_PROTO -#ifndef QFASM -void *alloca (int size); -#endif -#endif - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ALSA_ASOUNDLIB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ARPA_INET_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ASM_IO_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_CONIO_H 1 - -/* Define to 1 if you have the `connect' function. */ -#define HAVE_CONNECT 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_CTYPE_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_CURSES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DDRAW_H 1 - -/* Define if you have the XFree86 DGA extension */ -/* #undef HAVE_DGA */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DINPUT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DIRECT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DIRENT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DLFCN_H */ - -/* Define if you have the dlopen function. */ -/* #undef HAVE_DLOPEN */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DMEDIA_AUDIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DMEDIA_CDAUDIO_H */ - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -/* #undef HAVE_DOPRNT */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_DPMI_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_DSOUND_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_EXECINFO_H */ - -/* Define this if you have FB_AUX_VGA_PLANES_CFB4 */ -/* #undef HAVE_FB_AUX_VGA_PLANES_CFB4 */ - -/* Define this if you have FB_AUX_VGA_PLANES_CFB4 */ -/* #undef HAVE_FB_AUX_VGA_PLANES_CFB8 */ - -/* Define this if you have FB_AUX_VGA_PLANES_VGA4 */ -/* #undef HAVE_FB_AUX_VGA_PLANES_VGA4 */ - -/* Define to 1 if you have the `fcntl' function. */ -/* #undef HAVE_FCNTL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* define this if you have flac libs */ -/* #undef HAVE_FLAC */ - -/* Define to 1 if you have the header file. */ -#define HAVE_FNMATCH_H 1 - -/* Define this if fnmatch is prototyped in fnmatch.h */ -/* #undef HAVE_FNMATCH_PROTO */ - -/* Define this if FPOS_T is a struct */ -/* #undef HAVE_FPOS_T_STRUCT */ - -/* Define to 1 if you have the `ftime' function. */ -#define HAVE_FTIME 1 - -/* Define to 1 if you have the `getaddrinfo' function. */ -#define HAVE_GETADDRINFO 1 - -/* Define to 1 if you have the `gethostbyname' function. */ -#define HAVE_GETHOSTBYNAME 1 - -/* Define to 1 if you have the `gethostname' function. */ -#define HAVE_GETHOSTNAME 1 - -/* Define to 1 if you have the `getnameinfo' function. */ -#define HAVE_GETNAMEINFO 1 - -/* Define to 1 if you have the `getpagesize' function. */ -/* #undef HAVE_GETPAGESIZE */ - -/* Define to 1 if you have the `gettimeofday' function. */ -/* #undef HAVE_GETTIMEOFDAY */ - -/* Define to 1 if you have the `getwd' function. */ -/* #undef HAVE_GETWD */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ - -/* Define this if your system has struct in_pktinfo */ -/* #undef HAVE_IN_PKTINFO */ - -/* Define to 1 if you have the header file. */ -#define HAVE_IO_H 1 - -/* Define this if you want IPv6 support */ -/* #undef HAVE_IPV6 */ - -/* Define if you have libjack */ -/* #undef HAVE_JACK */ - -/* Define to 1 if you have a functional curl library. */ -#define HAVE_LIBCURL 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LIBC_H */ - -/* Define to 1 if you have the `db' library (-ldb). */ -/* #undef HAVE_LIBDB */ - -/* Define to 1 if you have the `efence' library (-lefence). */ -/* #undef HAVE_LIBEFENCE */ - -/* Define to 1 if you have the `m' library (-lm). */ -/* #undef HAVE_LIBM */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_CDROM_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_FB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_JOYSTICK_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_SOUNDCARD_H */ - -/* Define to 1 if you support file names longer than 14 characters. */ -#define HAVE_LONG_FILE_NAMES 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACHINE_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MALLOC_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MATH_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MGRAPH_H */ - -/* Define to 1 if you have the `mkdir' function. */ -#define HAVE_MKDIR 1 - -/* Define to 1 if you have a working `mmap' system call. */ -/* #undef HAVE_MMAP */ - -/* Define to 1 if you have the `mprotect' function. */ -/* #undef HAVE_MPROTECT */ - -/* Define to 1 if you have the header file, and it defines `DIR'. */ -/* #undef HAVE_NDIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETDB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_IN_H */ - -/* Define if you have libpng */ -/* #undef HAVE_PNG */ - -/* Define to 1 if you have the header file. */ -#define HAVE_PROCESS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PTHREAD_H */ - -/* Define to 1 if you have the `putenv' function. */ -#define HAVE_PUTENV 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_PWD_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_RPC_TYPES_H */ - -/* Define this if you have sa_len member in struct sockaddr (BSD) */ -/* #undef HAVE_SA_LEN */ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SETJMP_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define this if you have sin6_len member in struct sockaddr_in6 (BSD) */ -/* #undef HAVE_SIN6_LEN */ - -/* Define this if your system has size_t */ -#define HAVE_SIZE_T 1 - -/* Define to 1 if you have the `snprintf' function. */ -#define HAVE_SNPRINTF 1 - -/* Define to 1 if you have the `socket' function. */ -#define HAVE_SOCKET 1 - -/* Define this if your system has socklen_t */ -/* #undef HAVE_SOCKLEN_T */ - -/* Define this if you have ss_len member in struct sockaddr_storage (BSD) */ -/* #undef HAVE_SS_LEN */ - -/* Define to 1 if you have the `stat' function. */ -#define HAVE_STAT 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strcasestr' function. */ -/* #undef HAVE_STRCASESTR */ - -/* Define this if strcasestr is prototyped in string.h */ -/* #undef HAVE_STRCASESTR_PROTO */ - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STRINGS_H 1 */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strnlen' function. */ -#define HAVE_STRNLEN 1 - -/* Define this if strnlen is prototyped in string.h */ -#define HAVE_STRNLEN_PROTO 1 - -/* Define to 1 if you have the `strsep' function. */ -/* #undef HAVE_STRSEP */ - -/* Define to 1 if you have the `strstr' function. */ -#define HAVE_STRSTR 1 - -/* Define to 1 if `st_blksize' is member of `struct stat'. */ -/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */ - -/* Define to 1 if your `struct stat' has `st_blksize'. Deprecated, use - `HAVE_STRUCT_STAT_ST_BLKSIZE' instead. */ -/* #undef HAVE_ST_BLKSIZE */ - -/* Define this if C symbols are prefixed with an underscore */ -#define HAVE_SYM_PREFIX_UNDERSCORE 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_ASOUNDLIB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_AUDIOIO_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_FILIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_IOCTL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_IO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_IPC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_MMAN_H */ - -/* Define to 1 if you have the header file, and it defines `DIR'. - */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_PARAM_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_POLL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SHM_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SIGNAL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOUNDCARD_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_TIME_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_UIO_H */ - -/* Define to 1 if you have that is POSIX.1 compatible. */ -/* #undef HAVE_SYS_WAIT_H */ - -/* Define this if you have tchar.h */ -#define HAVE_TCHAR_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_TERMIOS_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_TIME_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ - -/* Define to 1 if you have the `usleep' function. */ -/* #undef HAVE_USLEEP */ - -/* Define if va_copy is available */ -/* #undef HAVE_VA_COPY */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_VGAKEYBOARD_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_VGAMOUSE_H */ - -/* Define if you have the XFree86 VIDMODE extension */ -/* #undef HAVE_VIDMODE */ - -/* define this if you have ogg/vorbis libs */ -/* #undef HAVE_VORBIS */ - -/* Define to 1 if you have the `vprintf' function. */ -#define HAVE_VPRINTF 1 - -/* Define to 1 if you have the `vsnprintf' function. */ -#define HAVE_VSNPRINTF 1 - -/* Define if you have WildMidi */ -/* #undef HAVE_WILDMIDI */ - -/* Define to 1 if you have the header file. */ -#define HAVE_WINDOWS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WINSOCK_H 1 - -/* Define if you have XMMS */ -/* #undef HAVE_XMMS */ - -/* Define if you have zlib */ -#define HAVE_ZLIB 1 - -/* Define to 1 if you have the `_access' function. */ -#define HAVE__ACCESS 1 - -/* Define to 1 if you have the `_ftime' function. */ -#define HAVE__FTIME 1 - -/* Define to 1 if you have the <_mingw.h> header file. */ -/* #undef HAVE__MINGW_H */ - -/* Define to 1 if you have the `_mkdir' function. */ -#define HAVE__MKDIR 1 - -/* Define this if you have _SC_PAGESIZE */ -/* #undef HAVE__SC_PAGESIZE */ - -/* Define to 1 if you have the `_snprintf' function. */ -#define HAVE__SNPRINTF 1 - -/* Define if __va_copy is available */ -/* #undef HAVE__VA_COPY */ - -/* Define to 1 if you have the `_vsnprintf' function. */ -#define HAVE__VSNPRINTF 1 - -/* Define this if the GCC __attribute__ keyword is available */ -/* #undef HAVE___ATTRIBUTE__ */ - -#ifndef HAVE___ATTRIBUTE__ -# define __attribute__(x) -#endif - -/* Define this if the GCC __attribute__ keyword is available */ -/* #undef HAVE___ATTRIBUTE__VISIBILITY */ - -#ifdef HAVE___ATTRIBUTE__VISIBILITY -# define VISIBLE __attribute__((visibility ("default"))) -#else -# define VISIBLE -#endif - -/* Define this if the GCC __builtin_expect keyword is available */ -/* #undef HAVE___BUILTIN_EXPECT */ - -#ifndef HAVE___BUILTIN_EXPECT -# define __builtin_expect(x,c) x -#endif - -/* Defined if libcurl supports AsynchDNS */ -/* #undef LIBCURL_FEATURE_ASYNCHDNS */ - -/* Defined if libcurl supports IDN */ -#define LIBCURL_FEATURE_IDN 1 - -/* Defined if libcurl supports IPv6 */ -#define LIBCURL_FEATURE_IPV6 1 - -/* Defined if libcurl supports KRB4 */ -/* #undef LIBCURL_FEATURE_KRB4 */ - -/* Defined if libcurl supports libz */ -#define LIBCURL_FEATURE_LIBZ 1 - -/* Defined if libcurl supports NTLM */ -#define LIBCURL_FEATURE_NTLM 1 - -/* Defined if libcurl supports SSL */ -/* #undef LIBCURL_FEATURE_SSL */ - -/* Defined if libcurl supports SSPI */ -#define LIBCURL_FEATURE_SSPI 1 - -/* Defined if libcurl supports DICT */ -/* #undef LIBCURL_PROTOCOL_DICT */ - -/* Defined if libcurl supports FILE */ -/* #undef LIBCURL_PROTOCOL_FILE */ - -/* Defined if libcurl supports FTP */ -#define LIBCURL_PROTOCOL_FTP 1 - -/* Defined if libcurl supports FTPS */ -/* #undef LIBCURL_PROTOCOL_FTPS */ - -/* Defined if libcurl supports HTTP */ -#define LIBCURL_PROTOCOL_HTTP 1 - -/* Defined if libcurl supports HTTPS */ -/* #undef LIBCURL_PROTOCOL_HTTPS */ - -/* Defined if libcurl supports LDAP */ -/* #undef LIBCURL_PROTOCOL_LDAP */ - -/* Defined if libcurl supports TELNET */ -/* #undef LIBCURL_PROTOCOL_TELNET */ - -/* Defined if libcurl supports TFTP */ -/* #undef LIBCURL_PROTOCOL_TFTP */ - -/* Define to 1 if `major', `minor', and `makedev' are declared in . - */ -/* #undef MAJOR_IN_MKDEV */ - -/* Define to 1 if `major', `minor', and `makedev' are declared in - . */ -/* #undef MAJOR_IN_SYSMACROS */ - -/* Define this to the QSG standard version you support in NetQuake */ -#define NQ_QSG_VERSION "1.0" - -/* Define this to the NetQuake standard version you support */ -#define NQ_VERSION "1.09" - -/* Name of package */ -#define PACKAGE "quakeforge" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* Define this to your operating system's path separator character */ -#define PATH_SEPARATOR '/' - -/* "Proper" package name */ -#define PROGRAM "QuakeForge" - -/* Define this to where qfcc should look for header files */ -#define QFCC_INCLUDE_PATH "/usr/local/include/QF/ruamoko" - -/* Define this to where qfcc should look for lib files */ -#define QFCC_LIB_PATH "/usr/local/lib/ruamoko" - -/* Define this to the QSG standard version you support in QuakeWorld */ -#define QW_QSG_VERSION "2.0" - -/* Define this to the QuakeWorld standard version you support */ -#define QW_VERSION "2.40" - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* list of server plugins */ -#define SERVER_PLUGIN_LIST {"console_server", console_server_PluginInfo},{0, 0} - -/* list of server prototypes */ -#define SERVER_PLUGIN_PROTOS extern plugin_t *console_server_PluginInfo (void); - -/* Define this to the default sound output driver. */ -#define SND_OUTPUT_DEFAULT "win" - -/* list of sound output plugins */ -#define SND_OUTPUT_LIST {"snd_output_win", snd_output_win_PluginInfo},{0, 0} - -/* list of sound output prototypes */ -#define SND_OUTPUT_PROTOS extern plugin_t *snd_output_win_PluginInfo (void); - -/* list of sound render plugins */ -#define SND_RENDER_LIST {"snd_render_default", snd_render_default_PluginInfo},{0, 0} - -/* list of sound render prototypes */ -#define SND_RENDER_PROTOS extern plugin_t *snd_render_default_PluginInfo (void); - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ - -/* Define this if you are building static plugins */ -#define STATIC_PLUGINS 1 - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 if your declares `struct tm'. */ -/* #undef TM_IN_SYS_TIME */ - -/* Define this if you want progs typechecking */ -/* #undef TYPECHECK_PROGS */ - -/* Define this if you want to use Intel assembly optimizations */ -/* #undef USE_INTEL_ASM */ - -/* Define if va_list is an array */ -/* #undef VA_LIST_IS_ARRAY */ - -/* Version number of package */ -#define VERSION "0.5.5-SVN" - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Define to 1 if the X Window System is missing or not being used. */ -/* #undef X_DISPLAY_MISSING */ - -/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a - `char[]'. */ -/* #undef YYTEXT_POINTER */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define curl_free() as free() if our version of curl lacks curl_free. */ -/* #undef curl_free */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#define inline __inline -/* #undef inline */ -#endif - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -/* Define strcasecmp as stricmp if you have one but not the other */ -#define strcasecmp stricmp - -/* new stuff, for VC2005 compatibility (phrosty) */ - -#define _CRT_SECURE_NO_WARNINGS -#define _CRT_NONSTDC_NO_WARNINGS - -/* used in qfcc. should #define to _ReturnAddress()? */ -#define __builtin_return_address(x) (0) - -#define _WIN32_WINNT 0x0500 -#define DIRECTINPUT_VERSION 0x0600 - -#define INITGUID - -#define snprintf _snprintf -#define strncasecmp strnicmp - -#define ssize_t ptrdiff_t -#define S_ISDIR(mode) (mode & _S_IFDIR) - -/* used in access() */ -#define R_OK 04 - -/* - disable silent conversion warnings for fixing later.. - - 4047: 'operator' : 'identifier1' differs in levels of indirection from 'identifier2' - 4244: 'argument' : conversion from 'type1' to 'type2', possible loss of data - 4267: 'var' : conversion from 'size_t' to 'type', possible loss of data (/Wp64 warning) - 4305: 'identifier' : truncation from 'type1' to 'type2' - 4311: 'variable' : pointer truncation from 'type' to 'type' (/Wp64 warning) - 4312: 'operation' : conversion from 'type1' to 'type2' of greater size (/Wp64 warning) -*/ -#pragma warning(disable:4047 4244 4267 4305 4311 4312) diff --git a/vc2008/models-sw/models-sw.vcproj b/vc2008/models-sw/models-sw.vcproj deleted file mode 100644 index e8aa3d541..000000000 --- a/vc2008/models-sw/models-sw.vcproj +++ /dev/null @@ -1,512 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/models/models.vcproj b/vc2008/models/models.vcproj deleted file mode 100644 index cacad0007..000000000 --- a/vc2008/models/models.vcproj +++ /dev/null @@ -1,490 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/modelsgl/modelsgl.vcproj b/vc2008/modelsgl/modelsgl.vcproj deleted file mode 100644 index 128903bd5..000000000 --- a/vc2008/modelsgl/modelsgl.vcproj +++ /dev/null @@ -1,522 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/net-main/net-main.vcproj b/vc2008/net-main/net-main.vcproj deleted file mode 100644 index 8f33ca46c..000000000 --- a/vc2008/net-main/net-main.vcproj +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/net/net.vcproj b/vc2008/net/net.vcproj deleted file mode 100644 index b79e2718b..000000000 --- a/vc2008/net/net.vcproj +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/nq-common/nq-common.vcproj b/vc2008/nq-common/nq-common.vcproj deleted file mode 100644 index f5e82ed15..000000000 --- a/vc2008/nq-common/nq-common.vcproj +++ /dev/null @@ -1,516 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/nq-sdl/nq-sdl.vcproj b/vc2008/nq-sdl/nq-sdl.vcproj deleted file mode 100644 index 73f38ada0..000000000 --- a/vc2008/nq-sdl/nq-sdl.vcproj +++ /dev/null @@ -1,556 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/nq-sdl32/nq-sdl32.vcproj b/vc2008/nq-sdl32/nq-sdl32.vcproj deleted file mode 100644 index 1e9ffcae2..000000000 --- a/vc2008/nq-sdl32/nq-sdl32.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/nq-server/nq-server.vcproj b/vc2008/nq-server/nq-server.vcproj deleted file mode 100644 index 202f9b6f2..000000000 --- a/vc2008/nq-server/nq-server.vcproj +++ /dev/null @@ -1,566 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/nq-sgl/nq-sgl.vcproj b/vc2008/nq-sgl/nq-sgl.vcproj deleted file mode 100644 index f6e9bc3b1..000000000 --- a/vc2008/nq-sgl/nq-sgl.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/nq-wgl/nq-wgl.vcproj b/vc2008/nq-wgl/nq-wgl.vcproj deleted file mode 100644 index 6453a12bd..000000000 --- a/vc2008/nq-wgl/nq-wgl.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/nq/nq.vcproj b/vc2008/nq/nq.vcproj deleted file mode 100644 index 220f0ff7a..000000000 --- a/vc2008/nq/nq.vcproj +++ /dev/null @@ -1,544 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/pak/pak.vcproj b/vc2008/pak/pak.vcproj deleted file mode 100644 index b5cd0bec8..000000000 --- a/vc2008/pak/pak.vcproj +++ /dev/null @@ -1,566 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qfbsp/qfbsp.vcproj b/vc2008/qfbsp/qfbsp.vcproj deleted file mode 100644 index 97462b79e..000000000 --- a/vc2008/qfbsp/qfbsp.vcproj +++ /dev/null @@ -1,632 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qfcc/FlexBison.rules b/vc2008/qfcc/FlexBison.rules deleted file mode 100644 index 0e4c1e3dc..000000000 --- a/vc2008/qfcc/FlexBison.rules +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qfcc/qfcc.vcproj b/vc2008/qfcc/qfcc.vcproj deleted file mode 100644 index 59bc03f84..000000000 --- a/vc2008/qfcc/qfcc.vcproj +++ /dev/null @@ -1,965 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qfclient/qfclient.vcproj b/vc2008/qfclient/qfclient.vcproj deleted file mode 100644 index 8739a5098..000000000 --- a/vc2008/qfclient/qfclient.vcproj +++ /dev/null @@ -1,626 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qflight/qflight.vcproj b/vc2008/qflight/qflight.vcproj deleted file mode 100644 index 3fc0ab1d6..000000000 --- a/vc2008/qflight/qflight.vcproj +++ /dev/null @@ -1,620 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qfmodelgen/qfmodelgen.vcproj b/vc2008/qfmodelgen/qfmodelgen.vcproj deleted file mode 100644 index 893da110a..000000000 --- a/vc2008/qfmodelgen/qfmodelgen.vcproj +++ /dev/null @@ -1,578 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qfprogs/qfprogs.vcproj b/vc2008/qfprogs/qfprogs.vcproj deleted file mode 100644 index 5141f8959..000000000 --- a/vc2008/qfprogs/qfprogs.vcproj +++ /dev/null @@ -1,590 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qfserver/qfserver.vcproj b/vc2008/qfserver/qfserver.vcproj deleted file mode 100644 index 909324104..000000000 --- a/vc2008/qfserver/qfserver.vcproj +++ /dev/null @@ -1,672 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qfvis/qfvis.vcproj b/vc2008/qfvis/qfvis.vcproj deleted file mode 100644 index 479049560..000000000 --- a/vc2008/qfvis/qfvis.vcproj +++ /dev/null @@ -1,588 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qfwavinfo/qfwavinfo.vcproj b/vc2008/qfwavinfo/qfwavinfo.vcproj deleted file mode 100644 index 40df9c014..000000000 --- a/vc2008/qfwavinfo/qfwavinfo.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qtv/qtv.vcproj b/vc2008/qtv/qtv.vcproj deleted file mode 100644 index 0e2bb2d4b..000000000 --- a/vc2008/qtv/qtv.vcproj +++ /dev/null @@ -1,594 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qw-client-sdl/qw-client-sdl.vcproj b/vc2008/qw-client-sdl/qw-client-sdl.vcproj deleted file mode 100644 index 983be0451..000000000 --- a/vc2008/qw-client-sdl/qw-client-sdl.vcproj +++ /dev/null @@ -1,558 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qw-client-sdl32/qw-client-sdl32.vcproj b/vc2008/qw-client-sdl32/qw-client-sdl32.vcproj deleted file mode 100644 index 33a31293d..000000000 --- a/vc2008/qw-client-sdl32/qw-client-sdl32.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qw-client-sgl/qw-client-sgl.vcproj b/vc2008/qw-client-sgl/qw-client-sgl.vcproj deleted file mode 100644 index 2842872d1..000000000 --- a/vc2008/qw-client-sgl/qw-client-sgl.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qw-client-wgl/qw-client-wgl.vcproj b/vc2008/qw-client-wgl/qw-client-wgl.vcproj deleted file mode 100644 index 0a2c37256..000000000 --- a/vc2008/qw-client-wgl/qw-client-wgl.vcproj +++ /dev/null @@ -1,558 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qw-master/qw-master.vcproj b/vc2008/qw-master/qw-master.vcproj deleted file mode 100644 index 4d7961feb..000000000 --- a/vc2008/qw-master/qw-master.vcproj +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/qw/qw.vcproj b/vc2008/qw/qw.vcproj deleted file mode 100644 index e5cb0be82..000000000 --- a/vc2008/qw/qw.vcproj +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/readme.txt b/vc2008/readme.txt deleted file mode 100644 index b4ad78741..000000000 --- a/vc2008/readme.txt +++ /dev/null @@ -1,25 +0,0 @@ -Requirements -============= -- Visual C++ 2008 SP1 -- DirectX SDK (for DirectInput) -- SDL (required for sdl, sdl32, and sgl builds) -- bison/flex (required for qfcc, needs to be in your compiler path) - -Optional -========= -- zlib (#undef HAVE_ZLIB from vc2008/include/config.h if you don't want - this). Expects zlib.lib and zlib.dll for Debug/Release builds, and - libzlib.lib for Release (static) build. -- libcurl (#undef HAVE_LIBCURL from vc2008/include/config.h if you don't - want this). Expects curl.lib and curl.dll for Debug/Release builds, - and libcurl.lib for Release (static) build. - -Notes -====== -By default, qfcc is configured to use the Boost Wave preprocessor. You -can get this from http://www.boost.org, or change the CPP_NAME #define in -vc2008/include/config.h to whatever preprocessor you want. If you have -GCC, you can simply replace "wave --c99" with "gcc" in the define and it -should work. - -clean.ps1 is a Windows Powershell script that cleans up any build files. diff --git a/vc2008/ruamoko/ruamoko.vcproj b/vc2008/ruamoko/ruamoko.vcproj deleted file mode 100644 index 924c02f7c..000000000 --- a/vc2008/ruamoko/ruamoko.vcproj +++ /dev/null @@ -1,518 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/sound/sound.vcproj b/vc2008/sound/sound.vcproj deleted file mode 100644 index fe681171d..000000000 --- a/vc2008/sound/sound.vcproj +++ /dev/null @@ -1,514 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/util/util.vcproj b/vc2008/util/util.vcproj deleted file mode 100644 index e680f491d..000000000 --- a/vc2008/util/util.vcproj +++ /dev/null @@ -1,618 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/video-sdl/video-sdl.vcproj b/vc2008/video-sdl/video-sdl.vcproj deleted file mode 100644 index 2b03f2566..000000000 --- a/vc2008/video-sdl/video-sdl.vcproj +++ /dev/null @@ -1,472 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/video-sgl/video-sgl.vcproj b/vc2008/video-sgl/video-sgl.vcproj deleted file mode 100644 index 920a06e47..000000000 --- a/vc2008/video-sgl/video-sgl.vcproj +++ /dev/null @@ -1,468 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/video-sw/video-sw.vcproj b/vc2008/video-sw/video-sw.vcproj deleted file mode 100644 index 75f419ae0..000000000 --- a/vc2008/video-sw/video-sw.vcproj +++ /dev/null @@ -1,596 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/video-sw32/video-sw32.vcproj b/vc2008/video-sw32/video-sw32.vcproj deleted file mode 100644 index fc6bc6054..000000000 --- a/vc2008/video-sw32/video-sw32.vcproj +++ /dev/null @@ -1,572 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/video-wgl/video-wgl.vcproj b/vc2008/video-wgl/video-wgl.vcproj deleted file mode 100644 index a0b315c7c..000000000 --- a/vc2008/video-wgl/video-wgl.vcproj +++ /dev/null @@ -1,472 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/video/video.vcproj b/vc2008/video/video.vcproj deleted file mode 100644 index 737ecfe59..000000000 --- a/vc2008/video/video.vcproj +++ /dev/null @@ -1,538 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/videogl/videogl.vcproj b/vc2008/videogl/videogl.vcproj deleted file mode 100644 index 44d30c3fc..000000000 --- a/vc2008/videogl/videogl.vcproj +++ /dev/null @@ -1,556 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vc2008/wad/wad.vcproj b/vc2008/wad/wad.vcproj deleted file mode 100644 index 11fc5737d..000000000 --- a/vc2008/wad/wad.vcproj +++ /dev/null @@ -1,574 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From c1ffb05b876c538a4de9914a7f6e1b5bc1192fe9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Jun 2020 16:14:39 +0900 Subject: [PATCH 1048/3664] Remove dead Makefile.am Forgot this in the merge. --- libs/video/renderer/vulkan/Makefile.am | 35 -------------------------- 1 file changed, 35 deletions(-) delete mode 100644 libs/video/renderer/vulkan/Makefile.am diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am deleted file mode 100644 index 707b6b064..000000000 --- a/libs/video/renderer/vulkan/Makefile.am +++ /dev/null @@ -1,35 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES - -vulkan_src = \ - buffer.c \ - command.c \ - descriptor.c \ - device.c \ - image.c \ - instance.c \ - memory.c \ - pipeline.c \ - renderpass.c \ - swapchain.c \ - util.c \ - vulkan_draw.c \ - vulkan_vid_common.c - -noinst_LTLIBRARIES= libvulkan.la -BUILT_SOURCES= $(shader_gen) - -SUFFICES=.frag .vert .fc .vc .slc .glsl -.glsl.slc: - sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ -.frag.fc: - sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ -.vert.vc: - sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ - -libvulkan_la_SOURCES= $(vulkan_src) - -EXTRA_DIST = $(vulkan_src) $(shader_src) namehack.h util.h -CLEANFILES= *.vc *.fc *.slc From c2559c7511d613c2ce80e9fc583c5463ff2df712 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Jun 2020 19:38:33 +0900 Subject: [PATCH 1049/3664] [qwaq] PR_RunPostLoadFuncs for qwaq-x11 Same issue as for the menus. But now I know why PR_LoadProgsFile is used instead of PR_LoadProgs (at least for qwaq): avoidance of the gamedir restriction (however, the menus are supposed to be restricted). --- ruamoko/qwaq/builtins/qwaq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c index 111af8764..0a8070825 100644 --- a/ruamoko/qwaq/builtins/qwaq.c +++ b/ruamoko/qwaq/builtins/qwaq.c @@ -149,7 +149,7 @@ load_progs (const char *name) pr.zone_size = 1024*1024; PR_LoadProgsFile (&pr, file, size); Qclose (file); - if (!PR_RunLoadFuncs (&pr)) + if (!PR_RunLoadFuncs (&pr) || !PR_RunPostLoadFuncs (&pr)) PR_Error (&pr, "unable to load %s", pr.progs_name); return 1; } From 8f2bc18a4ffc08dc5d29357a8c2b20ccdc252177 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Jun 2020 19:51:40 +0900 Subject: [PATCH 1050/3664] [build] Fix a merge error Messed up the vulkan headers. --- include/QF/Makemodule.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 9c691bddf..5282d5230 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -149,12 +149,13 @@ qf_gl_includedir = $(includedir)/QF/GL qf_glsl_includedir = $(includedir)/QF/GLSL qf_math_includedir = $(includedir)/QF/math qf_plugin_includedir = $(includedir)/QF/plugin +qf_vulkan_includedir = $(includedir)/QF/vulkan qf_include_HEADERS = @qfac_include_qf@ qf_gl_include_HEADERS = @qfac_include_qf_gl@ qf_glsl_include_HEADERS = @qfac_include_qf_glsl@ qf_math_include_HEADERS = @qfac_include_qf_math@ qf_plugin_include_HEADERS = @qfac_include_qf_plugin@ -qf_plugin_include_HEADERS = @qfac_include_qf_vulkan@ +qf_vulkan_include_HEADERS = @qfac_include_qf_vulkan@ ruamoko_qf_includedir = $(ruamoko_includedir)/QF ruamoko_qf_include_HEADERS = @qfac_qfcc_include_qf@ From ed42557dd1c0bc8fcd852917cdbb33ec693e6789 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Jun 2020 22:45:12 +0900 Subject: [PATCH 1051/3664] [qfcc] Reset flowvars for aliased global variables When a global variable is accessed via only an alias in a function the actual def's flowvar would remain in the state it was from the last function that accessed the global normally. This would result in invalid flowvar accesses which can be difficult to reproduce (thus no test case). --- tools/qfcc/source/flow.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index e26bcef1b..86f6dc9d5 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -463,6 +463,15 @@ flow_build_statements (function_t *func) } } +static int flow_def_clear_flowvars (def_t *def, void *data) +{ + if (def->flowvar) { + delete_flowvar (def->flowvar); + } + def->flowvar = 0; + return 0; +} + /** Build an array of all the variables used by a function * * The array exists so variables can be referenced by number and thus used @@ -517,17 +526,26 @@ flow_build_vars (function_t *func) set_iter_t *var_i; flowvar_t *var; - // first, count .return and .param_[0-7] as they are always needed + // First, run through the statements making sure any accessed variables + // have their flowvars reset. Local variables will be fine, but global + // variables make have had flowvars added in a previous function, and it's + // easier to just clear them all. + // This is done before .return and .param so they won't get reset just + // after being counted + for (i = 0; i < func->num_statements; i++) { + s = func->statements[i]; + flow_analyze_statement (s, 0, 0, 0, operands); + for (j = 0; j < FLOW_OPERANDS; j++) { + if (operands[j] && operands[j]->op_type == op_def) { + def_visit_all (operands[j]->o.def, 0, + flow_def_clear_flowvars, 0); + } + } + } + // count .return and .param_[0-7] as they are always needed for (i = 0; i < num_flow_params; i++) { def_t *def = param_symbol (flow_params[i].name)->s.def; - def_t *a; - for (a = def->alias_defs; a; a = a->next) { - if (a->flowvar) { - delete_flowvar (a->flowvar); - a->flowvar = 0; - } - //free_def (def->alias_defs); - } + def_visit_all (def, 0, flow_def_clear_flowvars, 0); flow_params[i].op.o.def = def; num_vars += count_operand (&flow_params[i].op); } From aa8aaaaca9ce36582b0ed04297d5eefa451b8b44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Jun 2020 10:52:06 +0900 Subject: [PATCH 1052/3664] [build] Support silent rules for qfcc --- Makefile.am | 14 +++++- ruamoko/cl_menu/Makemodule.am | 2 +- ruamoko/game/Makemodule.am | 2 +- ruamoko/qwaq/Makemodule.am | 4 +- ruamoko/scheme/Makemodule.am | 2 +- tools/qfcc/test/Makemodule.am | 90 +++++++++++++++++------------------ 6 files changed, 62 insertions(+), 52 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9e68af2a5..54ca7be00 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,6 +70,16 @@ QFCC_DEP=qfcc$(EXEEXT) QFCC=$(top_builddir)/$(QFCC_DEP) GZ=@progs_gz@ +V_QFCC = $(V_QFCC_@AM_V@) +V_QFCC_ = $(V_QFCC_@AM_DEFAULT_V@) +V_QFCC_0 = @echo " QFCC " $@; +V_QFCC_1 = + +V_QFCCLD = $(V_QFCCLD_@AM_V@) +V_QFCCLD_ = $(V_QFCCLD_@AM_DEFAULT_V@) +V_QFCCLD_0 = @echo " QFCCLD " $@; +V_QFCCLD_1 = + QCSYSTEM=--no-default-paths -I$(top_srcdir) -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide QCPPFLAGS=$(QCSYSTEM) @@ -82,12 +92,12 @@ am__mv = mv -f SUFFIXES=.o .r .pas .r.o: - depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(V_QFCC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ $(QCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tqo -c -o $@ $< &&\ sed -i -e '1s@:@: $(QFCC_DEP)@' $$depbase.Tqo &&\ $(am__mv) $$depbase.Tqo $$depbase.Qo .pas.o: - depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(V_QFCC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ $(QCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tqo -c -o $@ $< &&\ sed -i -e '1s@:@: $(QFCC_DEP)@' $$depbase.Tqo &&\ $(am__mv) $$depbase.Tqo $$depbase.Qo diff --git a/ruamoko/cl_menu/Makemodule.am b/ruamoko/cl_menu/Makemodule.am index dfa7635ba..c6c57aa7a 100644 --- a/ruamoko/cl_menu/Makemodule.am +++ b/ruamoko/cl_menu/Makemodule.am @@ -37,7 +37,7 @@ ruamoko_cl_menu_menu_dat_SOURCES=$(ruamoko_menu_src) ruamoko_menu_obj=$(ruamoko_cl_menu_menu_dat_SOURCES:.r=.o) ruamoko_menu_dep=$(call qcautodep,$(ruamoko_cl_menu_menu_dat_SOURCES)) ruamoko/cl_menu/menu.dat$(EXEEXT): $(ruamoko_menu_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a ruamoko/gui/libgui.a - $(QLINK) -o $@ $(ruamoko_menu_obj) -Lruamoko/gui -lgui -lcsqc -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_menu_obj) -Lruamoko/gui -lgui -lcsqc -lr include $(ruamoko_menu_dep) # am--include-marker r_depfiles_remade += $(ruamoko_menu_dep) diff --git a/ruamoko/game/Makemodule.am b/ruamoko/game/Makemodule.am index 4063e9a62..576867c27 100644 --- a/ruamoko/game/Makemodule.am +++ b/ruamoko/game/Makemodule.am @@ -9,7 +9,7 @@ ruamoko_game_game_dat_SOURCES=$(ruamoko_game_src) ruamoko_game_obj=$(ruamoko_game_game_dat_SOURCES:.r=.o) ruamoko_game_dep=$(call qcautodep,$(ruamoko_game_game_dat_SOURCES)) ruamoko/game/game.dat$(EXEEXT): $(ruamoko_game_obj) $(QFCC_DEP) ruamoko/lib/libr.a ruamoko/lib/libqw.a - $(QLINK) -o $@ $(ruamoko_game_obj) -lqw -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_game_obj) -lqw -lr include $(ruamoko_game_dep) # am--include-marker r_depfiles_remade += $(ruamoko_game_dep) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 149213268..bcb97af94 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -89,7 +89,7 @@ ruamoko_qwaq_qwaq_app_dat_SOURCES=$(qwaq_app_dat_src) ruamoko_qwaq_qwaq_app_obj=$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.r=.o) ruamoko_qwaq_qwaq_app_dep=$(call qcautodep,$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.o=.Qo)) ruamoko/qwaq/qwaq-app.dat$(EXEEXT): $(ruamoko_qwaq_qwaq_app_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(QLINK) -o $@ $(ruamoko_qwaq_qwaq_app_obj) -lcsqc -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_qwaq_app_obj) -lcsqc -lr include $(ruamoko_qwaq_qwaq_app_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_qwaq_app_dep) @@ -97,7 +97,7 @@ ruamoko_qwaq_gcd_dat_SOURCES=ruamoko/qwaq/gcd.r ruamoko_qwaq_gcd_obj=$(ruamoko_qwaq_gcd_dat_SOURCES:.r=.o) ruamoko_qwaq_gcd_dep=$(call qcautodep,$(ruamoko_qwaq_gcd_dat_SOURCES:.o=.Qo)) ruamoko/qwaq/gcd.dat$(EXEEXT): $(ruamoko_qwaq_gcd_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(QLINK) -o $@ $(ruamoko_qwaq_gcd_obj) -lcsqc -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_gcd_obj) -lcsqc -lr include $(ruamoko_qwaq_gcd_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_gcd_dep) diff --git a/ruamoko/scheme/Makemodule.am b/ruamoko/scheme/Makemodule.am index b3fcfb5d9..8c1d43622 100644 --- a/ruamoko/scheme/Makemodule.am +++ b/ruamoko/scheme/Makemodule.am @@ -45,7 +45,7 @@ ruamoko_scheme_main_dat_SOURCES=$(ruamoko_scheme_src) ruamoko_scheme_main_obj=$(ruamoko_scheme_main_dat_SOURCES:.r=.o) ruamoko_scheme_main_dep=$(call qcautodep,$(ruamoko_scheme_main_dat_SOURCES)) ruamoko/scheme/main.dat$(EXEEXT): $(ruamoko_scheme_main_obj) $(QFCC_DEP) ruamoko/scheme/libscheme.a ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(QLINK) -o $@ $(ruamoko_scheme_main_obj) -Lruamoko/scheme -lscheme -lcsqc -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_scheme_main_obj) -Lruamoko/scheme -lscheme -lcsqc -lr include $(ruamoko_scheme_main_dep) # am--include-marker r_depfiles_remade += $(ruamoko_scheme_main_dep) diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 85f94b800..3eb33892b 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -102,7 +102,7 @@ tools_qfcc_test_address_cast_dat_SOURCES=tools/qfcc/test/address-cast.r address_cast_obj=$(tools_qfcc_test_address_cast_dat_SOURCES:.r=.o) address_cast_dep=$(call qcautodep,$(tools_qfcc_test_address_cast_dat_SOURCES)) tools/qfcc/test/address-cast.dat$(EXEEXT): $(address_cast_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(address_cast_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(address_cast_obj) tools/qfcc/test/address-cast.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(address_cast_dep) # am--include-marker @@ -112,7 +112,7 @@ tools_qfcc_test_alignment_dat_SOURCES=tools/qfcc/test/alignment.r alignment_obj=$(tools_qfcc_test_alignment_dat_SOURCES:.r=.o) alignment_dep=$(call qcautodep,$(tools_qfcc_test_alignment_dat_SOURCES)) tools/qfcc/test/alignment.dat$(EXEEXT): $(alignment_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(alignment_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(alignment_obj) tools/qfcc/test/alignment.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(alignment_dep) # am--include-marker @@ -122,7 +122,7 @@ tools_qfcc_test_anonstruct_dat_SOURCES=tools/qfcc/test/anonstruct.r anonstruct_obj=$(tools_qfcc_test_anonstruct_dat_SOURCES:.r=.o) anonstruct_dep=$(call qcautodep,$(tools_qfcc_test_anonstruct_dat_SOURCES)) tools/qfcc/test/anonstruct.dat$(EXEEXT): $(anonstruct_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(anonstruct_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(anonstruct_obj) tools/qfcc/test/anonstruct.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(anonstruct_dep) # am--include-marker @@ -132,7 +132,7 @@ tools_qfcc_test_assignchain_dat_SOURCES=tools/qfcc/test/assignchain.r assignchain_obj=$(tools_qfcc_test_assignchain_dat_SOURCES:.r=.o) assignchain_dep=$(call qcautodep,$(tools_qfcc_test_assignchain_dat_SOURCES)) tools/qfcc/test/assignchain.dat$(EXEEXT): $(assignchain_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(assignchain_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(assignchain_obj) tools/qfcc/test/assignchain.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(assignchain_dep) # am--include-marker @@ -142,7 +142,7 @@ tools_qfcc_test_chewed_alias_dat_SOURCES=tools/qfcc/test/chewed-alias.r chewed_alias_obj=$(tools_qfcc_test_chewed_alias_dat_SOURCES:.r=.o) chewed_alias_dep=$(call qcautodep,$(tools_qfcc_test_chewed_alias_dat_SOURCES)) tools/qfcc/test/chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(chewed_alias_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(chewed_alias_obj) tools/qfcc/test/chewed-alias.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(chewed_alias_dep) # am--include-marker @@ -152,7 +152,7 @@ tools_qfcc_test_chewed_return_dat_SOURCES=tools/qfcc/test/chewed-return.r chewed_return_obj=$(tools_qfcc_test_chewed_return_dat_SOURCES:.r=.o) chewed_return_dep=$(call qcautodep,$(tools_qfcc_test_chewed_return_dat_SOURCES)) tools/qfcc/test/chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(chewed_return_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(chewed_return_obj) tools/qfcc/test/chewed-return.run: $(qfcc_test_run_deps) @TEST_HARNESS_OPTS=--float $(top_srcdir)/tools/qfcc/test/build-run $@ include $(chewed_return_dep) # am--include-marker @@ -162,7 +162,7 @@ tools_qfcc_test_comma_expr_dat_SOURCES=tools/qfcc/test/comma-expr.r comma_expr_obj=$(tools_qfcc_test_comma_expr_dat_SOURCES:.r=.o) comma_expr_dep=$(call qcautodep,$(tools_qfcc_test_comma_expr_dat_SOURCES)) tools/qfcc/test/comma-expr.dat$(EXEEXT): $(comma_expr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(comma_expr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(comma_expr_obj) tools/qfcc/test/comma-expr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(comma_expr_dep) # am--include-marker @@ -172,7 +172,7 @@ tools_qfcc_test_compound_dat_SOURCES=tools/qfcc/test/compound.r compound_obj=$(tools_qfcc_test_compound_dat_SOURCES:.r=.o) compound_dep=$(call qcautodep,$(tools_qfcc_test_compound_dat_SOURCES)) tools/qfcc/test/compound.dat$(EXEEXT): $(compound_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(compound_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(compound_obj) tools/qfcc/test/compound.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(compound_dep) # am--include-marker @@ -182,7 +182,7 @@ tools_qfcc_test_deadbool_dat_SOURCES=tools/qfcc/test/deadbool.r deadbool_obj=$(tools_qfcc_test_deadbool_dat_SOURCES:.r=.o) deadbool_dep=$(call qcautodep,$(tools_qfcc_test_deadbool_dat_SOURCES)) tools/qfcc/test/deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(deadbool_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(deadbool_obj) tools/qfcc/test/deadbool.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(deadbool_dep) # am--include-marker @@ -192,7 +192,7 @@ tools_qfcc_test_double_dat_SOURCES=tools/qfcc/test/double.r double_obj=$(tools_qfcc_test_double_dat_SOURCES:.r=.o) double_dep=$(call qcautodep,$(tools_qfcc_test_double_dat_SOURCES)) tools/qfcc/test/double.dat$(EXEEXT): $(double_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(double_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(double_obj) tools/qfcc/test/double.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(double_dep) # am--include-marker @@ -202,7 +202,7 @@ tools_qfcc_test_double_alias_dat_SOURCES=tools/qfcc/test/double-alias.r double_alias_obj=$(tools_qfcc_test_double_alias_dat_SOURCES:.r=.o) double_alias_dep=$(call qcautodep,$(tools_qfcc_test_double_alias_dat_SOURCES)) tools/qfcc/test/double-alias.dat$(EXEEXT): $(double_alias_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(double_alias_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(double_alias_obj) tools/qfcc/test/double-alias.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(double_alias_dep) # am--include-marker @@ -245,7 +245,7 @@ tools_qfcc_test_enum_dat_SOURCES=tools/qfcc/test/enum.r enum_obj=$(tools_qfcc_test_enum_dat_SOURCES:.r=.o) enum_dep=$(call qcautodep,$(tools_qfcc_test_enum_dat_SOURCES)) tools/qfcc/test/enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(enum_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(enum_obj) tools/qfcc/test/enum.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(enum_dep) # am--include-marker @@ -255,7 +255,7 @@ tools_qfcc_test_fordecl_dat_SOURCES=tools/qfcc/test/fordecl.r fordecl_obj=$(tools_qfcc_test_fordecl_dat_SOURCES:.r=.o) fordecl_dep=$(call qcautodep,$(tools_qfcc_test_fordecl_dat_SOURCES)) tools/qfcc/test/fordecl.dat$(EXEEXT): $(fordecl_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(fordecl_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(fordecl_obj) tools/qfcc/test/fordecl.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(fordecl_dep) # am--include-marker @@ -265,7 +265,7 @@ tools_qfcc_test_func_expr_dat_SOURCES=tools/qfcc/test/func-expr.r func_expr_obj=$(tools_qfcc_test_func_expr_dat_SOURCES:.r=.o) func_expr_dep=$(call qcautodep,$(tools_qfcc_test_func_expr_dat_SOURCES)) tools/qfcc/test/func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(func_expr_obj) tools/qfcc/test/func-expr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(func_expr_dep) # am--include-marker @@ -275,7 +275,7 @@ tools_qfcc_test_func_expr2_dat_SOURCES=tools/qfcc/test/func-expr2.r func_expr2_obj=$(tools_qfcc_test_func_expr2_dat_SOURCES:.r=.o) func_expr2_dep=$(call qcautodep,$(tools_qfcc_test_func_expr2_dat_SOURCES)) tools/qfcc/test/func-expr2.dat$(EXEEXT): $(func_expr2_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_expr2_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(func_expr2_obj) tools/qfcc/test/func-expr2.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(func_expr2_dep) # am--include-marker @@ -285,7 +285,7 @@ tools_qfcc_test_func_static_dat_SOURCES=tools/qfcc/test/func-static.r func_static_obj=$(tools_qfcc_test_func_static_dat_SOURCES:.r=.o) func_static_dep=$(call qcautodep,$(tools_qfcc_test_func_static_dat_SOURCES)) tools/qfcc/test/func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(func_static_obj) tools/qfcc/test/func-static.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(func_static_dep) # am--include-marker @@ -295,7 +295,7 @@ tools_qfcc_test_gcd_dat_SOURCES=tools/qfcc/test/gcd.pas gcd_obj=$(tools_qfcc_test_gcd_dat_SOURCES:.pas=.o) gcd_dep=$(call qcautodep,$(tools_qfcc_test_gcd_dat_SOURCES)) tools/qfcc/test/gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(gcd_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(gcd_obj) tools/qfcc/test/gcd.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(gcd_dep) # am--include-marker @@ -305,7 +305,7 @@ tools_qfcc_test_infloop_dat_SOURCES=tools/qfcc/test/infloop.r infloop_obj=$(tools_qfcc_test_infloop_dat_SOURCES:.r=.o) infloop_dep=$(call qcautodep,$(tools_qfcc_test_infloop_dat_SOURCES)) tools/qfcc/test/infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(infloop_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(infloop_obj) tools/qfcc/test/infloop.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(infloop_dep) # am--include-marker @@ -315,7 +315,7 @@ tools_qfcc_test_ivar_struct_return_dat_SOURCES=tools/qfcc/test/ivar-struct-retur ivar_struct_return_obj=$(tools_qfcc_test_ivar_struct_return_dat_SOURCES:.r=.o) ivar_struct_return_dep=$(call qcautodep,$(tools_qfcc_test_ivar_struct_return_dat_SOURCES)) tools/qfcc/test/ivar-struct-return.dat$(EXEEXT): $(ivar_struct_return_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(ivar_struct_return_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(ivar_struct_return_obj) tools/qfcc/test/ivar-struct-return.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(ivar_struct_return_dep) # am--include-marker @@ -325,7 +325,7 @@ tools_qfcc_test_methodparams_dat_SOURCES=tools/qfcc/test/methodparams.r methodparams_obj=$(tools_qfcc_test_methodparams_dat_SOURCES:.r=.o) methodparams_dep=$(call qcautodep,$(tools_qfcc_test_methodparams_dat_SOURCES)) tools/qfcc/test/methodparams.dat$(EXEEXT): $(methodparams_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(methodparams_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(methodparams_obj) tools/qfcc/test/methodparams.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(methodparams_dep) # am--include-marker @@ -335,7 +335,7 @@ tools_qfcc_test_modulo_dat_SOURCES=tools/qfcc/test/modulo.r modulo_obj=$(tools_qfcc_test_modulo_dat_SOURCES:.r=.o) modulo_dep=$(call qcautodep,$(tools_qfcc_test_modulo_dat_SOURCES)) tools/qfcc/test/modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(modulo_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(modulo_obj) tools/qfcc/test/modulo.run: $(qfcc_test_run_deps) @TEST_HARNESS_OPTS=--float $(top_srcdir)/tools/qfcc/test/build-run $@ include $(modulo_dep) # am--include-marker @@ -345,7 +345,7 @@ tools_qfcc_test_nilparamret_dat_SOURCES=tools/qfcc/test/nilparamret.r nilparamret_obj=$(tools_qfcc_test_nilparamret_dat_SOURCES:.r=.o) nilparamret_dep=$(call qcautodep,$(tools_qfcc_test_nilparamret_dat_SOURCES)) tools/qfcc/test/nilparamret.dat$(EXEEXT): $(nilparamret_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(nilparamret_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(nilparamret_obj) tools/qfcc/test/nilparamret.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(nilparamret_dep) # am--include-marker @@ -355,7 +355,7 @@ tools_qfcc_test_overload_dat_SOURCES=tools/qfcc/test/overload.r overload_obj=$(tools_qfcc_test_overload_dat_SOURCES:.r=.o) overload_dep=$(call qcautodep,$(tools_qfcc_test_overload_dat_SOURCES)) tools/qfcc/test/overload.dat$(EXEEXT): $(overload_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(overload_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(overload_obj) tools/qfcc/test/overload.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(overload_dep) # am--include-marker @@ -365,7 +365,7 @@ tools_qfcc_test_paramret_dat_SOURCES=tools/qfcc/test/paramret.r paramret_obj=$(tools_qfcc_test_paramret_dat_SOURCES:.r=.o) paramret_dep=$(call qcautodep,$(tools_qfcc_test_paramret_dat_SOURCES)) tools/qfcc/test/paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(paramret_obj) tools/qfcc/test/paramret.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(paramret_dep) # am--include-marker @@ -375,7 +375,7 @@ tools_qfcc_test_quaternion_dat_SOURCES=tools/qfcc/test/quaternion.r quaternion_obj=$(tools_qfcc_test_quaternion_dat_SOURCES:.r=.o) quaternion_dep=$(call qcautodep,$(tools_qfcc_test_quaternion_dat_SOURCES)) tools/qfcc/test/quaternion.dat$(EXEEXT): $(quaternion_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(quaternion_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(quaternion_obj) tools/qfcc/test/quaternion.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(quaternion_dep) # am--include-marker @@ -385,7 +385,7 @@ tools_qfcc_test_return_ivar_dat_SOURCES=tools/qfcc/test/return-ivar.r return_ivar_obj=$(tools_qfcc_test_return_ivar_dat_SOURCES:.r=.o) return_ivar_dep=$(call qcautodep,$(tools_qfcc_test_return_ivar_dat_SOURCES)) tools/qfcc/test/return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(return_ivar_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(return_ivar_obj) tools/qfcc/test/return-ivar.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(return_ivar_dep) # am--include-marker @@ -395,7 +395,7 @@ tools_qfcc_test_sendv_dat_SOURCES=tools/qfcc/test/sendv.r sendv_obj=$(tools_qfcc_test_sendv_dat_SOURCES:.r=.o) sendv_dep=$(call qcautodep,$(tools_qfcc_test_sendv_dat_SOURCES)) tools/qfcc/test/sendv.dat$(EXEEXT): $(sendv_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(sendv_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(sendv_obj) tools/qfcc/test/sendv.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(sendv_dep) # am--include-marker @@ -405,7 +405,7 @@ tools_qfcc_test_state_dat_SOURCES=tools/qfcc/test/state.r state_obj=$(tools_qfcc_test_state_dat_SOURCES:.r=.o) state_dep=$(call qcautodep,$(tools_qfcc_test_state_dat_SOURCES)) tools/qfcc/test/state.dat$(EXEEXT): $(state_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(state_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(state_obj) tools/qfcc/test/state.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(state_dep) # am--include-marker @@ -415,7 +415,7 @@ tools_qfcc_test_struct_init_param_dat_SOURCES=tools/qfcc/test/struct-init-param. struct_init_param_obj=$(tools_qfcc_test_struct_init_param_dat_SOURCES:.r=.o) struct_init_param_dep=$(call qcautodep,$(tools_qfcc_test_struct_init_param_dat_SOURCES)) tools/qfcc/test/struct-init-param.dat$(EXEEXT): $(struct_init_param_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(struct_init_param_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(struct_init_param_obj) tools/qfcc/test/struct-init-param.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(struct_init_param_dep) # am--include-marker @@ -425,7 +425,7 @@ tools_qfcc_test_struct_nil_init_dat_SOURCES=tools/qfcc/test/struct-nil-init.r struct_nil_init_obj=$(tools_qfcc_test_struct_nil_init_dat_SOURCES:.r=.o) struct_nil_init_dep=$(call qcautodep,$(tools_qfcc_test_struct_nil_init_dat_SOURCES)) tools/qfcc/test/struct-nil-init.dat$(EXEEXT): $(struct_nil_init_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(struct_nil_init_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(struct_nil_init_obj) tools/qfcc/test/struct-nil-init.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(struct_nil_init_dep) # am--include-marker @@ -435,7 +435,7 @@ tools_qfcc_test_structarray_dat_SOURCES=tools/qfcc/test/structarray.r structarray_obj=$(tools_qfcc_test_structarray_dat_SOURCES:.r=.o) structarray_dep=$(call qcautodep,$(tools_qfcc_test_structarray_dat_SOURCES)) tools/qfcc/test/structarray.dat$(EXEEXT): $(structarray_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structarray_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(structarray_obj) tools/qfcc/test/structarray.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(structarray_dep) # am--include-marker @@ -445,7 +445,7 @@ tools_qfcc_test_structlive_dat_SOURCES=tools/qfcc/test/structlive.r structlive_obj=$(tools_qfcc_test_structlive_dat_SOURCES:.r=.o) structlive_dep=$(call qcautodep,$(tools_qfcc_test_structlive_dat_SOURCES)) tools/qfcc/test/structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structlive_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(structlive_obj) tools/qfcc/test/structlive.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(structlive_dep) # am--include-marker @@ -455,7 +455,7 @@ tools_qfcc_test_structptr_dat_SOURCES=tools/qfcc/test/structptr.r structptr_obj=$(tools_qfcc_test_structptr_dat_SOURCES:.r=.o) structptr_dep=$(call qcautodep,$(tools_qfcc_test_structptr_dat_SOURCES)) tools/qfcc/test/structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structptr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(structptr_obj) tools/qfcc/test/structptr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(structptr_dep) # am--include-marker @@ -465,7 +465,7 @@ tools_qfcc_test_structstruct_dat_SOURCES=tools/qfcc/test/structstruct.r structstruct_obj=$(tools_qfcc_test_structstruct_dat_SOURCES:.r=.o) structstruct_dep=$(call qcautodep,$(tools_qfcc_test_structstruct_dat_SOURCES)) tools/qfcc/test/structstruct.dat$(EXEEXT): $(structstruct_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structstruct_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(structstruct_obj) tools/qfcc/test/structstruct.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(structstruct_dep) # am--include-marker @@ -475,7 +475,7 @@ tools_qfcc_test_swap_dat_SOURCES=tools/qfcc/test/swap.r swap_obj=$(tools_qfcc_test_swap_dat_SOURCES:.r=.o) swap_dep=$(call qcautodep,$(tools_qfcc_test_swap_dat_SOURCES)) tools/qfcc/test/swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(swap_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(swap_obj) tools/qfcc/test/swap.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(swap_dep) # am--include-marker @@ -485,7 +485,7 @@ tools_qfcc_test_triangle_dat_SOURCES=tools/qfcc/test/triangle.r triangle_obj=$(tools_qfcc_test_triangle_dat_SOURCES:.r=.o) triangle_dep=$(call qcautodep,$(tools_qfcc_test_triangle_dat_SOURCES)) tools/qfcc/test/triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(triangle_obj) tools/qfcc/test/triangle.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ 100000 100000 1.00005 50002.4961 include $(triangle_dep) # am--include-marker @@ -495,7 +495,7 @@ tools_qfcc_test_typedef_dat_SOURCES=tools/qfcc/test/typedef.r typedef_obj=$(tools_qfcc_test_typedef_dat_SOURCES:.r=.o) typedef_dep=$(call qcautodep,$(tools_qfcc_test_typedef_dat_SOURCES)) tools/qfcc/test/typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(typedef_obj) tools/qfcc/test/typedef.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(typedef_dep) # am--include-marker @@ -505,7 +505,7 @@ tools_qfcc_test_typelinker_dat_SOURCES=tools/qfcc/test/typelinker_a.r tools/qfcc typelinker_obj=$(tools_qfcc_test_typelinker_dat_SOURCES:.r=.o) typelinker_dep=$(call qcautodep,$(tools_qfcc_test_typelinker_dat_SOURCES)) tools/qfcc/test/typelinker.dat$(EXEEXT): $(typelinker_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(typelinker_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(typelinker_obj) tools/qfcc/test/typelinker.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(typelinker_dep) # am--include-marker @@ -515,7 +515,7 @@ tools_qfcc_test_unaryminus_dat_SOURCES=tools/qfcc/test/unaryminus.r unaryminus_obj=$(tools_qfcc_test_unaryminus_dat_SOURCES:.r=.o) unaryminus_dep=$(call qcautodep,$(tools_qfcc_test_unaryminus_dat_SOURCES)) tools/qfcc/test/unaryminus.dat$(EXEEXT): $(unaryminus_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(unaryminus_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(unaryminus_obj) tools/qfcc/test/unaryminus.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(unaryminus_dep) # am--include-marker @@ -525,7 +525,7 @@ tools_qfcc_test_vecaddr_dat_SOURCES=tools/qfcc/test/vecaddr.r vecaddr_obj=$(tools_qfcc_test_vecaddr_dat_SOURCES:.r=.o) vecaddr_dep=$(call qcautodep,$(tools_qfcc_test_vecaddr_dat_SOURCES)) tools/qfcc/test/vecaddr.dat$(EXEEXT): $(vecaddr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(vecaddr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(vecaddr_obj) tools/qfcc/test/vecaddr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(vecaddr_dep) # am--include-marker @@ -535,7 +535,7 @@ tools_qfcc_test_vecexpr_dat_SOURCES=tools/qfcc/test/vecexpr.r vecexpr_obj=$(tools_qfcc_test_vecexpr_dat_SOURCES:.r=.o) vecexpr_dep=$(call qcautodep,$(tools_qfcc_test_vecexpr_dat_SOURCES)) tools/qfcc/test/vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(vecexpr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(vecexpr_obj) tools/qfcc/test/vecexpr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(vecexpr_dep) # am--include-marker @@ -545,7 +545,7 @@ tools_qfcc_test_vecinit_dat_SOURCES=tools/qfcc/test/vecinit.r vecinit_obj=$(tools_qfcc_test_vecinit_dat_SOURCES:.r=.o) vecinit_dep=$(call qcautodep,$(tools_qfcc_test_vecinit_dat_SOURCES)) tools/qfcc/test/vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(vecinit_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(vecinit_obj) tools/qfcc/test/vecinit.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(vecinit_dep) # am--include-marker @@ -555,7 +555,7 @@ tools_qfcc_test_voidfor_dat_SOURCES=tools/qfcc/test/voidfor.r voidfor_obj=$(tools_qfcc_test_voidfor_dat_SOURCES:.r=.o) voidfor_dep=$(call qcautodep,$(tools_qfcc_test_voidfor_dat_SOURCES)) tools/qfcc/test/voidfor.dat$(EXEEXT): $(voidfor_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(voidfor_obj) tools/qfcc/test/voidfor.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(voidfor_dep) # am--include-marker @@ -565,7 +565,7 @@ tools_qfcc_test_while_dat_SOURCES=tools/qfcc/test/while.r while_obj=$(tools_qfcc_test_while_dat_SOURCES:.r=.o) while_dep=$(call qcautodep,$(tools_qfcc_test_while_dat_SOURCES)) tools/qfcc/test/while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(while_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(while_obj) tools/qfcc/test/while.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(while_dep) # am--include-marker @@ -575,7 +575,7 @@ tools_qfcc_test_zerolinker_dat_SOURCES=tools/qfcc/test/zerolinker.r zerolinker_obj=$(tools_qfcc_test_zerolinker_dat_SOURCES:.r=.o) zerolinker_dep=$(call qcautodep,$(tools_qfcc_test_zerolinker_dat_SOURCES)) tools/qfcc/test/zerolinker.dat$(EXEEXT): $(zerolinker_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(zerolinker_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(zerolinker_obj) tools/qfcc/test/zerolinker.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(zerolinker_dep) # am--include-marker From 19c75f5e499d569564cf61d95e91cd5cbba589df Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Jun 2020 13:53:11 +0900 Subject: [PATCH 1053/3664] [vulkan] Clean up QFV_CreateFramebuffer's prototype It now takes qfv_imageviewset_t instead of separate count and VkImageView array. --- include/QF/Vulkan/renderpass.h | 4 ++-- libs/video/renderer/vulkan/renderpass.c | 4 ++-- libs/video/renderer/vulkan/vulkan_vid_common.c | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index 9a197ac70..49134c730 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -28,6 +28,7 @@ typedef struct qfv_subpassdependency_s DARRAY_ALLOCFIXED (qfv_subpassdependency_t, num, allocator) struct qfv_device_s; +struct qfv_imageviewset_s; VkRenderPass QFV_CreateRenderPass (struct qfv_device_s *device, qfv_attachmentdescription_t *attachments, @@ -37,8 +38,7 @@ QFV_CreateRenderPass (struct qfv_device_s *device, VkFramebuffer QFV_CreateFramebuffer (struct qfv_device_s *device, VkRenderPass renderPass, - uint32_t numAttachments, - VkImageView *attachments, + struct qfv_imageviewset_s *attachments, VkExtent2D, uint32_t layers); #endif//__QF_Vulkan_renderpass_h diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index e61005278..40bc095ad 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -85,7 +85,7 @@ QFV_CreateRenderPass (qfv_device_t *device, VkFramebuffer QFV_CreateFramebuffer (qfv_device_t *device, VkRenderPass renderPass, - uint32_t numAttachments, VkImageView *attachments, + qfv_imageviewset_t *attachments, VkExtent2D extent, uint32_t layers) { VkDevice dev = device->dev; @@ -93,7 +93,7 @@ QFV_CreateFramebuffer (qfv_device_t *device, VkRenderPass renderPass, VkFramebufferCreateInfo createInfo = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 0, 0, - renderPass, numAttachments, attachments, + renderPass, attachments->size, attachments->a, extent.width, extent.height, layers, }; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 452a74eb8..68dd2bbe8 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -445,9 +445,8 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) attachments->a[2] = sc->imageViews->a[i]; __auto_type frame = &ctx->framebuffers.a[i]; frame->framebuffer = QFV_CreateFramebuffer (device, renderpass, - attachments->size, - attachments->a, - sc->extent, 1); + attachments, + sc->extent, 1); frame->fence = QFV_CreateFence (device, 1); frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); frame->renderDoneSemaphore = QFV_CreateSemaphore (device); From 7f96b0fbedb0a5a5e91bd20c9753c26321646898 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Jun 2020 18:30:01 +0900 Subject: [PATCH 1054/3664] [qwaq] Fix incorrect setting of progs argc/argv --- ruamoko/qwaq/builtins/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index da3607c01..931d33337 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -223,13 +223,13 @@ spawn_progs (qwaq_thread_t *thread) } PR_PushFrame (pr); - if (thread->args.size > 2) { - pr_argc = thread->args.size - 1; + if (thread->args.size) { + pr_argc = thread->args.size; } pr_argv = PR_Zone_Malloc (pr, (pr_argc + 1) * 4); pr_argv[0] = PR_SetTempString (pr, name); for (i = 1; i < pr_argc; i++) - pr_argv[i] = PR_SetTempString (pr, thread->args.a[1 + i]); + pr_argv[i] = PR_SetTempString (pr, thread->args.a[i]); pr_argv[i] = 0; PR_RESET_PARAMS (pr); From 6d4e370a258f2682c4c90c9a139f42f7579fbadf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Jun 2020 18:48:38 +0900 Subject: [PATCH 1055/3664] [ruamoko] Handle 0-length @va_list for va_copy Fixes a progs crash when using vsprintf with no format elements + params. --- libs/ruamoko/rua_runtime.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libs/ruamoko/rua_runtime.c b/libs/ruamoko/rua_runtime.c index 697fc720b..24a8a894d 100644 --- a/libs/ruamoko/rua_runtime.c +++ b/libs/ruamoko/rua_runtime.c @@ -56,8 +56,13 @@ bi_va_copy (progs_t *pr) __auto_type src_list = &G_STRUCT (pr, pr_type_t, src_args->list); size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); size_t size = src_args->count * parm_size; - string_t dst_list_block = PR_AllocTempBlock (pr, size); - __auto_type dst_list = (pr_type_t *) PR_GetString (pr, dst_list_block); + string_t dst_list_block = 0; + pr_type_t *dst_list = 0; + + if (size) { + dst_list_block = PR_AllocTempBlock (pr, size); + dst_list = (pr_type_t *) PR_GetString (pr, dst_list_block); + } memcpy (dst_list, src_list, size); R_PACKED (pr, pr_va_list_t).count = src_args->count; From cf3262991d68ca90ab71518592d45e4768b5d6ac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Jun 2020 19:08:18 +0900 Subject: [PATCH 1056/3664] [vulkan] Add a tool for making vulkan enum tables The tables are generated from the enums pulled out of the vulkan headers using a ruamoko program (thanks to its reflection capabilities). They will be used for parsing property lists used to create render passes and pipelines. --- libs/video/renderer/Makemodule.am | 7 + .../video/renderer/vulkan/vkgen/Makemodule.am | 34 ++ libs/video/renderer/vulkan/vkgen/stddef.h | 2 + libs/video/renderer/vulkan/vkgen/stdint.h | 11 + libs/video/renderer/vulkan/vkgen/vkgen.r | 431 ++++++++++++++++++ libs/video/renderer/vulkan/vkgen/vulkan.r | 2 + 6 files changed, 487 insertions(+) create mode 100644 libs/video/renderer/vulkan/vkgen/Makemodule.am create mode 100644 libs/video/renderer/vulkan/vkgen/stddef.h create mode 100644 libs/video/renderer/vulkan/vkgen/stdint.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkgen.r create mode 100644 libs/video/renderer/vulkan/vkgen/vulkan.r diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 65b594549..b1196dc2f 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -1,3 +1,5 @@ +include libs/video/renderer/vulkan/vkgen/Makemodule.am + #lib_LTLIBRARIES += @VID_REND_TARGETS@ plugin_LTLIBRARIES += @vid_render_plugins@ noinst_LTLIBRARIES += libs/video/renderer/libQFrenderer.la @vid_render_static_plugins@ @@ -217,6 +219,11 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_draw.c \ libs/video/renderer/vulkan/vulkan_vid_common.c +qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) +BUILT_SOURCES += libs/video/renderer/vulkan/vkenum.inc +libs/video/renderer/vulkan/vkenum.inc: $(vkgen) $(qwaq_curses) + $(qwaq_curses) $(vkgen) -- $@ + CLEANFILES += \ libs/video/renderer/glsl/*.vc \ libs/video/renderer/glsl/*.fc \ diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am new file mode 100644 index 000000000..901dea622 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -0,0 +1,34 @@ +vkgen = libs/video/renderer/vulkan/vkgen.dat$(EXEEXT) +noinst_PROGRAMS += $(vkgen) + +vkgen_dat_src= \ + libs/video/renderer/vulkan/vkgen/vkgen.r \ + libs/video/renderer/vulkan/vkgen/vulkan.r + +VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen + +libs_video_renderer_vulkan_vkgen_dat_SOURCES=$(vkgen_dat_src) +libs_video_renderer_vkgen_obj=$(libs_video_renderer_vulkan_vkgen_dat_SOURCES:.r=.o) +libs_video_renderer_vkgen_dep=$(call qcautodep,$(libs_video_renderer_vulkan_vkgen_dat_SOURCES:.o=.Qo)) +libs/video/renderer/vulkan/vkgen.dat$(EXEEXT): $(libs_video_renderer_vkgen_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(libs_video_renderer_vkgen_obj) -lcsqc -lr +include $(libs_video_renderer_vkgen_dep) # am--include-marker +r_depfiles_remade += $(libs_video_renderer_vkgen_dep) + +libs/video/renderer/vulkan/vkgen/vkgen.o: $(top_srcdir)/libs/video/renderer/vulkan/vkgen/vkgen.r + $(V_QFCC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(QCOMPILE) ${VKGENFLAGS} -MT $@ -MD -MP -MF $$depbase.Tqo -c -o $@ $< &&\ + sed -i -e '1s@:@: $(QFCC_DEP)@' $$depbase.Tqo &&\ + $(am__mv) $$depbase.Tqo $$depbase.Qo + +libs/video/renderer/vulkan/vkgen/vulkan.o: $(top_srcdir)/libs/video/renderer/vulkan/vkgen/vulkan.r + $(V_QFCC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(QCOMPILE) ${VKGENFLAGS} -MT $@ -MD -MP -MF $$depbase.Tqo -c -o $@ $< &&\ + sed -i -e '1s@:@: $(QFCC_DEP)@' $$depbase.Tqo &&\ + $(am__mv) $$depbase.Tqo $$depbase.Qo + +EXTRA_DIST += \ + libs/video/renderer/vulkan/vkgen/stddef.h \ + libs/video/renderer/vulkan/vkgen/stdint.h +CLEANFILES += \ + libs/video/renderer/vkgen/*.sym diff --git a/libs/video/renderer/vulkan/vkgen/stddef.h b/libs/video/renderer/vulkan/vkgen/stddef.h new file mode 100644 index 000000000..5252efc1d --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/stddef.h @@ -0,0 +1,2 @@ +#define const +#define __attribute__(x) diff --git a/libs/video/renderer/vulkan/vkgen/stdint.h b/libs/video/renderer/vulkan/vkgen/stdint.h new file mode 100644 index 000000000..04fc06933 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/stdint.h @@ -0,0 +1,11 @@ +typedef int uint8_t; +typedef int uint16_t; +typedef int uint32_t; +typedef int uint64_t; +typedef int int8_t; +typedef int int16_t; +typedef int int32_t; +typedef int int64_t; +typedef int size_t; +typedef int long; +typedef int char; diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r new file mode 100644 index 000000000..1400d3fbc --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -0,0 +1,431 @@ +#include +#include +#include +#include +#include +#include + +void printf (string fmt, ...) = #0; + +void fprintf (QFile file, string format, ...) +{ + printf("fprintf %d\n", @args.count); + Qputs (file, vsprintf (format, va_copy (@args))); +} + +typedef void varfunc (qfot_var_t *var); + +string search_names[] = { + "VkGraphicsPipelineCreateInfo", + "VkComputePipelineCreateInfo", +}; +#define numsearch (sizeof (search_names) / sizeof (search_names[0])) +hashtab_t *available_types; +hashtab_t *processed_types; +Array *queue; +Array *output_types; + +QFile output_file; + +@interface Enum: Object +{ + qfot_type_t *type; + int prefix_length; +} +-initWithType: (qfot_type_t *) type; +/** \warning returned string is ephemeral +*/ +-(string) name; +@end + +@implementation Enum +-(void)process +{ + string end = "_MAX_ENUM"; + int len; + string prefix = nil; + + if (str_mid([self name], -8) == "FlagBits") { + end = "_FLAG_BITS_MAX_ENUM"; + } + len = -strlen (end); + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (str_mid (var.name, len) == end) { + // len is negative so +1 consumes 1 more char (_) + prefix = str_hold (str_mid (var.name, 0, len + 1)); + } + } + if (prefix) { + prefix_length = strlen (prefix); + } +} + +-initWithType: (qfot_type_t *) type +{ + if (!(self = [super init])) { + return nil; + } + self.type = type; + [self process]; + return self; +} + +-(string) name +{ + return str_mid(type.strct.tag, 4); +} + +-(void) addToQueue +{ + string name = [self name]; + //printf (" +%s\n", name); + if (!Hash_Find (processed_types, name)) { + Hash_Add (processed_types, (void *) name); + [queue addObject: self]; + } +} + +-(void) writeTable +{ + int strip_bit = 0; + if (str_mid([self name], -8) == "FlagBits") { + strip_bit = 1; + } + + fprintf (output_file, "enumval_t %s_values[] = {\n", [self name]); + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (str_str (var.name, "_MAX_ENUM") >= 0 + || str_str (var.name, "_BEGIN_RANGE") >= 0 + || str_str (var.name, "_END_RANGE") >= 0 + || str_str (var.name, "_RANGE_SIZE") >= 0) { + continue; + } + fprintf (output_file, "\t{\"%s\", %d},\n", var.name, var.offset); + if (prefix_length) { + string shortname = str_mid (var.name, prefix_length); + if (strip_bit) { + int bit_pos = str_str (shortname, "_BIT"); + if (bit_pos >= 0) { + shortname = str_mid (shortname, 0, bit_pos); + } + } + fprintf (output_file, "\t{\"%s\", %d},\n", str_lower(shortname), + var.offset); + } + } + fprintf (output_file, "\t{ }\n"); + fprintf (output_file, "};\n"); +} +@end + +@interface Struct: Object +{ + qfot_type_t *type; +} +-initWithType: (qfot_type_t *) type; +/** \warning returned string is ephemeral +*/ +-(string) name; +-(void) forEachFieldCall: (varfunc) func; +@end + +@implementation Struct +-initWithType: (qfot_type_t *) type +{ + if (!(self = [super init])) { + return nil; + } + self.type = type; + return self; +} + +-(string) name +{ + return str_mid(type.strct.tag, 4); +} + +-(void) forEachFieldCall: (varfunc) func +{ + qfot_struct_t *strct =&type.strct; + + for (int i = 0; i < strct.num_fields; i++) { + func (&strct.fields[i]); + } +} + +-(void) addToQueue +{ + string name = [self name]; + //printf (" +%s\n", name); + if (!Hash_Find (processed_types, name)) { + Hash_Add (processed_types, (void *) name); + [queue addObject: self]; + } +} + +-(void) writeTable +{ + fprintf (output_file, "structfld_t %s_fields[] = {\n", [self name]); + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (var.name == "sType" || var.name == "pNext") { + continue; + } + string type_name = var.type.encoding; + fprintf (output_file, + "\t{\"%s\", field_offset (%s, %s), %s, %s}, // %s\n", + var.name, [self name], var.name, "0", "0", type_name); + } + fprintf (output_file, "\t{ }\n"); + fprintf (output_file, "};\n"); +} +@end + +qfot_type_encodings_t *encodings; + +qfot_type_t * +next_type (qfot_type_t *type) +{ + int size = type.size; + if (!size) + size = 4; + return (qfot_type_t *) ((int *) type + size); +} + +int +type_is_null (qfot_type_t *type) +{ + return type.size == 0; +} + +void print_type (qfot_type_t *type) +{ + printf ("type: %p %d %d %s", type, type.meta, type.size, type.encoding); + switch (type.meta) { + case ty_basic: + printf (" %d", type.type); + switch (type.type) { + case ev_pointer: + case ev_field: + printf (" "); + print_type (type.fldptr.aux_type); + break; + case ev_func: + printf (" %p %d\n", type.func.return_type, + type.func.num_params); + default: + printf ("\n"); + break; + } + break; + case ty_struct: + case ty_union: + case ty_enum: + printf (" %s %d\n", type.strct.tag, type.strct.num_fields); + break; + case ty_array: + printf (" %p %d %d\n", type.array.type, type.array.base, + type.array.size); + break; + case ty_class: + printf (" %s\n", type.class); + break; + case ty_alias: + printf (" %d %s ", type.alias.type, type.alias.name); + print_type (type.alias.aux_type); + break; + } +} + +void struct_func (qfot_var_t *var) +{ + qfot_type_t *alias; + if (var.type.meta == ty_enum) { + printf("%s a\n", var.name); + } else if (var.type.meta == ty_struct) { + printf("%s b\n", var.name); + } else if (var.type.meta == ty_union) { + printf("%s c\n", var.name); + } else if (var.type.meta == ty_alias) { + //printf("%s d\n", var.name); + // typedef fun ;) + alias = var.type.alias.full_type; + if (alias.meta == ty_alias) { + // double(+) typedef + if (alias.alias.name == "VkFlags") { + // enum flag fun :P + string tag = var.type.alias.name; + if (str_mid (tag, -5) == "Flags") { + tag = str_mid (tag, 0, -1) + "Bits"; + id enumObj = (id) Hash_Find (available_types, tag); + if (enumObj) { + [enumObj addToQueue]; + } + } + } else { + if (var.type.alias.name == "VkBool32") { + // drop + } else { + printf ("%s =%s\n", var.name, var.type.alias.name); + } + } + } else if (alias.meta == ty_enum) { + string tag = str_mid(alias.strct.tag, 4); + id enumObj = (id) Hash_Find (available_types, tag); + if (enumObj) { + [enumObj addToQueue]; + } + } else if (alias.meta == ty_basic && alias.type == ev_pointer) { + //printf("e\n"); + qfot_type_t *type = alias.fldptr.aux_type; + if (type.meta == ty_alias) { + id structObj = (id) Hash_Find (available_types, type.alias.name); + //printf (" a:%s %p\n", type.alias.name, structObj); + if (structObj) { + [structObj addToQueue]; + } + } else if (type_is_null (type)) { + // pointer to opaque struct. Probably VK_DEFINE_NON_DISPATCHABLE_HANDLE or VK_DEFINE_HANDLE + //drop + string createInfo = var.type.alias.name + "CreateInfo"; + id structObj = (id) Hash_Find (available_types, createInfo); + if (structObj) { + [structObj addToQueue]; + } else { + //printf(" b:%s\n", var.type.alias.name); + } + } else { + print_type (type); + printf("%s c:%s:%s\n", var.name, var.type.alias.name, pr_type_name[alias.type]); + } + } else if (alias.meta == ty_basic) { + //drop + //printf(" d:%s:%s\n", var.type.alias.name, pr_type_name[alias.type]); + } else if (alias.meta == ty_struct) { + string tag = str_mid(alias.strct.tag, 4); + id structObj = (id) Hash_Find (available_types, tag); + if (structObj) { + [structObj addToQueue]; + } + } else { + printf(" d:%s:%s\n", var.type.alias.name, ty_meta_name[alias.meta]); + } + } else if (var.type.meta == ty_basic && var.type.type == ev_pointer) { + qfot_type_t *type = var.type.fldptr.aux_type; + if (type.meta == ty_struct || type.meta == ty_union) { + printf("%s f\n", var.name); + } else if (type.meta == ty_alias) { + printf("%s --- %s\n", var.name, type.alias.name); + id obj = (id) Hash_Find (available_types, type.alias.name); + if (obj && [obj class] == [Struct class]) { + [obj forEachFieldCall:struct_func]; + } + } else if (type.meta == ty_basic && type.type == ev_void) { + //drop + } else { + printf("%s g\n", var.name); + print_type (var.type); + } + } else { + //drop + //printf(" %s:%s:%s\n", var.name, ty_meta_name[var.type.meta], pr_type_name[var.type.type]); + } +} + +void +scan_types (void) +{ + qfot_type_t *type; + + for (type = encodings.types; + ((int *)type - (int *) encodings.types) < encodings.size; + type = next_type (type)) { + if (!type.size + || (type.meta != ty_enum + && type.meta != ty_struct + && type.meta != ty_union)) { + continue; + } + string tag = str_mid(type.strct.tag, 4); + switch (type.meta) { + case ty_enum: + Hash_Add (available_types, [[Enum alloc] initWithType: type]); + //printf ("+ enum %s\n", tag); + break; + case ty_struct: + case ty_union: + Hash_Add (available_types, [[Struct alloc] initWithType: type]); + //printf ("+ struct %s\n", tag); + break; + case ty_basic: + case ty_array: + case ty_class: + case ty_alias: + break; + } + } +} + +static string +get_string_key (void *str, void *unused) +{ + return (string) str; +} + +static string +get_object_key (void *obj, void *unused) +{ + return [(id)obj name]; +} + +int +main(int argc, string *argv) +{ + encodings = PR_FindGlobal (".type_encodings"); + if (!encodings) { + printf ("Can't find encodings\n"); + return 1; + } + queue = [[Array alloc] init]; + output_types = [[Array alloc] init]; + available_types = Hash_NewTable (127, get_object_key, nil, nil); + processed_types = Hash_NewTable (127, get_string_key, nil, nil); + scan_types (); + + for (int i = 0; + i < sizeof (search_names) / sizeof (search_names[0]); i++) { + id obj = (id) Hash_Find (available_types, search_names[i]); + if (obj && [obj class] == [Struct class]) { + [obj addToQueue]; + } + } + + while ([queue count]) { + id obj = [queue objectAtIndex:0]; + [queue removeObjectAtIndex:0]; + if ([obj class] == [Struct class]) { + [obj forEachFieldCall:struct_func]; + } + [output_types addObject:obj]; + } + + for (int i = 0; i < argc; i++) { + printf ("vkgen %d %s\n", i, argv[i]); + } + + output_file = Qopen (argv[1], "wt"); + for (int i = [output_types count]; i-- > 0; ) { + id obj = [output_types objectAtIndex:i]; + if ([obj name] == "VkStructureType") { + continue; + } + if ([obj class] == [Struct class]) { + continue; + } + [obj writeTable]; + } + Qclose (output_file); + return 0; +} diff --git a/libs/video/renderer/vulkan/vkgen/vulkan.r b/libs/video/renderer/vulkan/vkgen/vulkan.r new file mode 100644 index 000000000..46b720d0c --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vulkan.r @@ -0,0 +1,2 @@ +#define __x86_64__ +#include From 12a35f3912f1008565dc3098aeaa8e279ea47481 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Jun 2020 23:32:38 +0900 Subject: [PATCH 1057/3664] [build] Put that ar warning to rest --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index 54ca7be00..71e429956 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,6 +44,7 @@ noinst_HEADERS = plugin_LTLIBRARIES = RANLIB=touch +ARFLAGS=cr EXTRA_HEADERS = EXTRA_LTLIBRARIES = From 0681136eb9036067c8cadae6be4b4a764315e848 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Jun 2020 19:38:33 +0900 Subject: [PATCH 1058/3664] [qwaq] PR_RunPostLoadFuncs for qwaq-x11 Same issue as for the menus. But now I know why PR_LoadProgsFile is used instead of PR_LoadProgs (at least for qwaq): avoidance of the gamedir restriction (however, the menus are supposed to be restricted). --- ruamoko/qwaq/builtins/qwaq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c index 111af8764..0a8070825 100644 --- a/ruamoko/qwaq/builtins/qwaq.c +++ b/ruamoko/qwaq/builtins/qwaq.c @@ -149,7 +149,7 @@ load_progs (const char *name) pr.zone_size = 1024*1024; PR_LoadProgsFile (&pr, file, size); Qclose (file); - if (!PR_RunLoadFuncs (&pr)) + if (!PR_RunLoadFuncs (&pr) || !PR_RunPostLoadFuncs (&pr)) PR_Error (&pr, "unable to load %s", pr.progs_name); return 1; } From 03f6af39f446ef86cec3ec42b49f7e714906a4bd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Jun 2020 22:45:12 +0900 Subject: [PATCH 1059/3664] [qfcc] Reset flowvars for aliased global variables When a global variable is accessed via only an alias in a function the actual def's flowvar would remain in the state it was from the last function that accessed the global normally. This would result in invalid flowvar accesses which can be difficult to reproduce (thus no test case). --- tools/qfcc/source/flow.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index e26bcef1b..86f6dc9d5 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -463,6 +463,15 @@ flow_build_statements (function_t *func) } } +static int flow_def_clear_flowvars (def_t *def, void *data) +{ + if (def->flowvar) { + delete_flowvar (def->flowvar); + } + def->flowvar = 0; + return 0; +} + /** Build an array of all the variables used by a function * * The array exists so variables can be referenced by number and thus used @@ -517,17 +526,26 @@ flow_build_vars (function_t *func) set_iter_t *var_i; flowvar_t *var; - // first, count .return and .param_[0-7] as they are always needed + // First, run through the statements making sure any accessed variables + // have their flowvars reset. Local variables will be fine, but global + // variables make have had flowvars added in a previous function, and it's + // easier to just clear them all. + // This is done before .return and .param so they won't get reset just + // after being counted + for (i = 0; i < func->num_statements; i++) { + s = func->statements[i]; + flow_analyze_statement (s, 0, 0, 0, operands); + for (j = 0; j < FLOW_OPERANDS; j++) { + if (operands[j] && operands[j]->op_type == op_def) { + def_visit_all (operands[j]->o.def, 0, + flow_def_clear_flowvars, 0); + } + } + } + // count .return and .param_[0-7] as they are always needed for (i = 0; i < num_flow_params; i++) { def_t *def = param_symbol (flow_params[i].name)->s.def; - def_t *a; - for (a = def->alias_defs; a; a = a->next) { - if (a->flowvar) { - delete_flowvar (a->flowvar); - a->flowvar = 0; - } - //free_def (def->alias_defs); - } + def_visit_all (def, 0, flow_def_clear_flowvars, 0); flow_params[i].op.o.def = def; num_vars += count_operand (&flow_params[i].op); } From a177f363f733251532130137d810211c62a00e8b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Jun 2020 10:52:06 +0900 Subject: [PATCH 1060/3664] [build] Support silent rules for qfcc --- Makefile.am | 14 +++++- ruamoko/cl_menu/Makemodule.am | 2 +- ruamoko/game/Makemodule.am | 2 +- ruamoko/qwaq/Makemodule.am | 4 +- ruamoko/scheme/Makemodule.am | 2 +- tools/qfcc/test/Makemodule.am | 90 +++++++++++++++++------------------ 6 files changed, 62 insertions(+), 52 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9e68af2a5..54ca7be00 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,6 +70,16 @@ QFCC_DEP=qfcc$(EXEEXT) QFCC=$(top_builddir)/$(QFCC_DEP) GZ=@progs_gz@ +V_QFCC = $(V_QFCC_@AM_V@) +V_QFCC_ = $(V_QFCC_@AM_DEFAULT_V@) +V_QFCC_0 = @echo " QFCC " $@; +V_QFCC_1 = + +V_QFCCLD = $(V_QFCCLD_@AM_V@) +V_QFCCLD_ = $(V_QFCCLD_@AM_DEFAULT_V@) +V_QFCCLD_0 = @echo " QFCCLD " $@; +V_QFCCLD_1 = + QCSYSTEM=--no-default-paths -I$(top_srcdir) -I$(top_srcdir)/ruamoko/include -I$(top_srcdir)/include QCFLAGS=-qq -O -g -Werror -Wall -Wno-integer-divide QCPPFLAGS=$(QCSYSTEM) @@ -82,12 +92,12 @@ am__mv = mv -f SUFFIXES=.o .r .pas .r.o: - depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(V_QFCC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ $(QCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tqo -c -o $@ $< &&\ sed -i -e '1s@:@: $(QFCC_DEP)@' $$depbase.Tqo &&\ $(am__mv) $$depbase.Tqo $$depbase.Qo .pas.o: - depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + $(V_QFCC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ $(QCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tqo -c -o $@ $< &&\ sed -i -e '1s@:@: $(QFCC_DEP)@' $$depbase.Tqo &&\ $(am__mv) $$depbase.Tqo $$depbase.Qo diff --git a/ruamoko/cl_menu/Makemodule.am b/ruamoko/cl_menu/Makemodule.am index dfa7635ba..c6c57aa7a 100644 --- a/ruamoko/cl_menu/Makemodule.am +++ b/ruamoko/cl_menu/Makemodule.am @@ -37,7 +37,7 @@ ruamoko_cl_menu_menu_dat_SOURCES=$(ruamoko_menu_src) ruamoko_menu_obj=$(ruamoko_cl_menu_menu_dat_SOURCES:.r=.o) ruamoko_menu_dep=$(call qcautodep,$(ruamoko_cl_menu_menu_dat_SOURCES)) ruamoko/cl_menu/menu.dat$(EXEEXT): $(ruamoko_menu_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a ruamoko/gui/libgui.a - $(QLINK) -o $@ $(ruamoko_menu_obj) -Lruamoko/gui -lgui -lcsqc -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_menu_obj) -Lruamoko/gui -lgui -lcsqc -lr include $(ruamoko_menu_dep) # am--include-marker r_depfiles_remade += $(ruamoko_menu_dep) diff --git a/ruamoko/game/Makemodule.am b/ruamoko/game/Makemodule.am index 4063e9a62..576867c27 100644 --- a/ruamoko/game/Makemodule.am +++ b/ruamoko/game/Makemodule.am @@ -9,7 +9,7 @@ ruamoko_game_game_dat_SOURCES=$(ruamoko_game_src) ruamoko_game_obj=$(ruamoko_game_game_dat_SOURCES:.r=.o) ruamoko_game_dep=$(call qcautodep,$(ruamoko_game_game_dat_SOURCES)) ruamoko/game/game.dat$(EXEEXT): $(ruamoko_game_obj) $(QFCC_DEP) ruamoko/lib/libr.a ruamoko/lib/libqw.a - $(QLINK) -o $@ $(ruamoko_game_obj) -lqw -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_game_obj) -lqw -lr include $(ruamoko_game_dep) # am--include-marker r_depfiles_remade += $(ruamoko_game_dep) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 149213268..bcb97af94 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -89,7 +89,7 @@ ruamoko_qwaq_qwaq_app_dat_SOURCES=$(qwaq_app_dat_src) ruamoko_qwaq_qwaq_app_obj=$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.r=.o) ruamoko_qwaq_qwaq_app_dep=$(call qcautodep,$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.o=.Qo)) ruamoko/qwaq/qwaq-app.dat$(EXEEXT): $(ruamoko_qwaq_qwaq_app_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(QLINK) -o $@ $(ruamoko_qwaq_qwaq_app_obj) -lcsqc -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_qwaq_app_obj) -lcsqc -lr include $(ruamoko_qwaq_qwaq_app_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_qwaq_app_dep) @@ -97,7 +97,7 @@ ruamoko_qwaq_gcd_dat_SOURCES=ruamoko/qwaq/gcd.r ruamoko_qwaq_gcd_obj=$(ruamoko_qwaq_gcd_dat_SOURCES:.r=.o) ruamoko_qwaq_gcd_dep=$(call qcautodep,$(ruamoko_qwaq_gcd_dat_SOURCES:.o=.Qo)) ruamoko/qwaq/gcd.dat$(EXEEXT): $(ruamoko_qwaq_gcd_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(QLINK) -o $@ $(ruamoko_qwaq_gcd_obj) -lcsqc -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_gcd_obj) -lcsqc -lr include $(ruamoko_qwaq_gcd_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_gcd_dep) diff --git a/ruamoko/scheme/Makemodule.am b/ruamoko/scheme/Makemodule.am index b3fcfb5d9..8c1d43622 100644 --- a/ruamoko/scheme/Makemodule.am +++ b/ruamoko/scheme/Makemodule.am @@ -45,7 +45,7 @@ ruamoko_scheme_main_dat_SOURCES=$(ruamoko_scheme_src) ruamoko_scheme_main_obj=$(ruamoko_scheme_main_dat_SOURCES:.r=.o) ruamoko_scheme_main_dep=$(call qcautodep,$(ruamoko_scheme_main_dat_SOURCES)) ruamoko/scheme/main.dat$(EXEEXT): $(ruamoko_scheme_main_obj) $(QFCC_DEP) ruamoko/scheme/libscheme.a ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(QLINK) -o $@ $(ruamoko_scheme_main_obj) -Lruamoko/scheme -lscheme -lcsqc -lr + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_scheme_main_obj) -Lruamoko/scheme -lscheme -lcsqc -lr include $(ruamoko_scheme_main_dep) # am--include-marker r_depfiles_remade += $(ruamoko_scheme_main_dep) diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 85f94b800..3eb33892b 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -102,7 +102,7 @@ tools_qfcc_test_address_cast_dat_SOURCES=tools/qfcc/test/address-cast.r address_cast_obj=$(tools_qfcc_test_address_cast_dat_SOURCES:.r=.o) address_cast_dep=$(call qcautodep,$(tools_qfcc_test_address_cast_dat_SOURCES)) tools/qfcc/test/address-cast.dat$(EXEEXT): $(address_cast_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(address_cast_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(address_cast_obj) tools/qfcc/test/address-cast.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(address_cast_dep) # am--include-marker @@ -112,7 +112,7 @@ tools_qfcc_test_alignment_dat_SOURCES=tools/qfcc/test/alignment.r alignment_obj=$(tools_qfcc_test_alignment_dat_SOURCES:.r=.o) alignment_dep=$(call qcautodep,$(tools_qfcc_test_alignment_dat_SOURCES)) tools/qfcc/test/alignment.dat$(EXEEXT): $(alignment_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(alignment_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(alignment_obj) tools/qfcc/test/alignment.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(alignment_dep) # am--include-marker @@ -122,7 +122,7 @@ tools_qfcc_test_anonstruct_dat_SOURCES=tools/qfcc/test/anonstruct.r anonstruct_obj=$(tools_qfcc_test_anonstruct_dat_SOURCES:.r=.o) anonstruct_dep=$(call qcautodep,$(tools_qfcc_test_anonstruct_dat_SOURCES)) tools/qfcc/test/anonstruct.dat$(EXEEXT): $(anonstruct_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(anonstruct_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(anonstruct_obj) tools/qfcc/test/anonstruct.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(anonstruct_dep) # am--include-marker @@ -132,7 +132,7 @@ tools_qfcc_test_assignchain_dat_SOURCES=tools/qfcc/test/assignchain.r assignchain_obj=$(tools_qfcc_test_assignchain_dat_SOURCES:.r=.o) assignchain_dep=$(call qcautodep,$(tools_qfcc_test_assignchain_dat_SOURCES)) tools/qfcc/test/assignchain.dat$(EXEEXT): $(assignchain_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(assignchain_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(assignchain_obj) tools/qfcc/test/assignchain.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(assignchain_dep) # am--include-marker @@ -142,7 +142,7 @@ tools_qfcc_test_chewed_alias_dat_SOURCES=tools/qfcc/test/chewed-alias.r chewed_alias_obj=$(tools_qfcc_test_chewed_alias_dat_SOURCES:.r=.o) chewed_alias_dep=$(call qcautodep,$(tools_qfcc_test_chewed_alias_dat_SOURCES)) tools/qfcc/test/chewed-alias.dat$(EXEEXT): $(chewed_alias_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(chewed_alias_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(chewed_alias_obj) tools/qfcc/test/chewed-alias.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(chewed_alias_dep) # am--include-marker @@ -152,7 +152,7 @@ tools_qfcc_test_chewed_return_dat_SOURCES=tools/qfcc/test/chewed-return.r chewed_return_obj=$(tools_qfcc_test_chewed_return_dat_SOURCES:.r=.o) chewed_return_dep=$(call qcautodep,$(tools_qfcc_test_chewed_return_dat_SOURCES)) tools/qfcc/test/chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(chewed_return_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(chewed_return_obj) tools/qfcc/test/chewed-return.run: $(qfcc_test_run_deps) @TEST_HARNESS_OPTS=--float $(top_srcdir)/tools/qfcc/test/build-run $@ include $(chewed_return_dep) # am--include-marker @@ -162,7 +162,7 @@ tools_qfcc_test_comma_expr_dat_SOURCES=tools/qfcc/test/comma-expr.r comma_expr_obj=$(tools_qfcc_test_comma_expr_dat_SOURCES:.r=.o) comma_expr_dep=$(call qcautodep,$(tools_qfcc_test_comma_expr_dat_SOURCES)) tools/qfcc/test/comma-expr.dat$(EXEEXT): $(comma_expr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(comma_expr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(comma_expr_obj) tools/qfcc/test/comma-expr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(comma_expr_dep) # am--include-marker @@ -172,7 +172,7 @@ tools_qfcc_test_compound_dat_SOURCES=tools/qfcc/test/compound.r compound_obj=$(tools_qfcc_test_compound_dat_SOURCES:.r=.o) compound_dep=$(call qcautodep,$(tools_qfcc_test_compound_dat_SOURCES)) tools/qfcc/test/compound.dat$(EXEEXT): $(compound_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(compound_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(compound_obj) tools/qfcc/test/compound.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(compound_dep) # am--include-marker @@ -182,7 +182,7 @@ tools_qfcc_test_deadbool_dat_SOURCES=tools/qfcc/test/deadbool.r deadbool_obj=$(tools_qfcc_test_deadbool_dat_SOURCES:.r=.o) deadbool_dep=$(call qcautodep,$(tools_qfcc_test_deadbool_dat_SOURCES)) tools/qfcc/test/deadbool.dat$(EXEEXT): $(deadbool_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(deadbool_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(deadbool_obj) tools/qfcc/test/deadbool.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(deadbool_dep) # am--include-marker @@ -192,7 +192,7 @@ tools_qfcc_test_double_dat_SOURCES=tools/qfcc/test/double.r double_obj=$(tools_qfcc_test_double_dat_SOURCES:.r=.o) double_dep=$(call qcautodep,$(tools_qfcc_test_double_dat_SOURCES)) tools/qfcc/test/double.dat$(EXEEXT): $(double_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(double_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(double_obj) tools/qfcc/test/double.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(double_dep) # am--include-marker @@ -202,7 +202,7 @@ tools_qfcc_test_double_alias_dat_SOURCES=tools/qfcc/test/double-alias.r double_alias_obj=$(tools_qfcc_test_double_alias_dat_SOURCES:.r=.o) double_alias_dep=$(call qcautodep,$(tools_qfcc_test_double_alias_dat_SOURCES)) tools/qfcc/test/double-alias.dat$(EXEEXT): $(double_alias_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(double_alias_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(double_alias_obj) tools/qfcc/test/double-alias.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(double_alias_dep) # am--include-marker @@ -245,7 +245,7 @@ tools_qfcc_test_enum_dat_SOURCES=tools/qfcc/test/enum.r enum_obj=$(tools_qfcc_test_enum_dat_SOURCES:.r=.o) enum_dep=$(call qcautodep,$(tools_qfcc_test_enum_dat_SOURCES)) tools/qfcc/test/enum.dat$(EXEEXT): $(enum_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(enum_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(enum_obj) tools/qfcc/test/enum.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(enum_dep) # am--include-marker @@ -255,7 +255,7 @@ tools_qfcc_test_fordecl_dat_SOURCES=tools/qfcc/test/fordecl.r fordecl_obj=$(tools_qfcc_test_fordecl_dat_SOURCES:.r=.o) fordecl_dep=$(call qcautodep,$(tools_qfcc_test_fordecl_dat_SOURCES)) tools/qfcc/test/fordecl.dat$(EXEEXT): $(fordecl_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(fordecl_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(fordecl_obj) tools/qfcc/test/fordecl.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(fordecl_dep) # am--include-marker @@ -265,7 +265,7 @@ tools_qfcc_test_func_expr_dat_SOURCES=tools/qfcc/test/func-expr.r func_expr_obj=$(tools_qfcc_test_func_expr_dat_SOURCES:.r=.o) func_expr_dep=$(call qcautodep,$(tools_qfcc_test_func_expr_dat_SOURCES)) tools/qfcc/test/func-expr.dat$(EXEEXT): $(func_expr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_expr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(func_expr_obj) tools/qfcc/test/func-expr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(func_expr_dep) # am--include-marker @@ -275,7 +275,7 @@ tools_qfcc_test_func_expr2_dat_SOURCES=tools/qfcc/test/func-expr2.r func_expr2_obj=$(tools_qfcc_test_func_expr2_dat_SOURCES:.r=.o) func_expr2_dep=$(call qcautodep,$(tools_qfcc_test_func_expr2_dat_SOURCES)) tools/qfcc/test/func-expr2.dat$(EXEEXT): $(func_expr2_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_expr2_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(func_expr2_obj) tools/qfcc/test/func-expr2.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(func_expr2_dep) # am--include-marker @@ -285,7 +285,7 @@ tools_qfcc_test_func_static_dat_SOURCES=tools/qfcc/test/func-static.r func_static_obj=$(tools_qfcc_test_func_static_dat_SOURCES:.r=.o) func_static_dep=$(call qcautodep,$(tools_qfcc_test_func_static_dat_SOURCES)) tools/qfcc/test/func-static.dat$(EXEEXT): $(func_static_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(func_static_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(func_static_obj) tools/qfcc/test/func-static.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(func_static_dep) # am--include-marker @@ -295,7 +295,7 @@ tools_qfcc_test_gcd_dat_SOURCES=tools/qfcc/test/gcd.pas gcd_obj=$(tools_qfcc_test_gcd_dat_SOURCES:.pas=.o) gcd_dep=$(call qcautodep,$(tools_qfcc_test_gcd_dat_SOURCES)) tools/qfcc/test/gcd.dat$(EXEEXT): $(gcd_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(gcd_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(gcd_obj) tools/qfcc/test/gcd.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(gcd_dep) # am--include-marker @@ -305,7 +305,7 @@ tools_qfcc_test_infloop_dat_SOURCES=tools/qfcc/test/infloop.r infloop_obj=$(tools_qfcc_test_infloop_dat_SOURCES:.r=.o) infloop_dep=$(call qcautodep,$(tools_qfcc_test_infloop_dat_SOURCES)) tools/qfcc/test/infloop.dat$(EXEEXT): $(infloop_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(infloop_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(infloop_obj) tools/qfcc/test/infloop.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(infloop_dep) # am--include-marker @@ -315,7 +315,7 @@ tools_qfcc_test_ivar_struct_return_dat_SOURCES=tools/qfcc/test/ivar-struct-retur ivar_struct_return_obj=$(tools_qfcc_test_ivar_struct_return_dat_SOURCES:.r=.o) ivar_struct_return_dep=$(call qcautodep,$(tools_qfcc_test_ivar_struct_return_dat_SOURCES)) tools/qfcc/test/ivar-struct-return.dat$(EXEEXT): $(ivar_struct_return_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(ivar_struct_return_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(ivar_struct_return_obj) tools/qfcc/test/ivar-struct-return.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(ivar_struct_return_dep) # am--include-marker @@ -325,7 +325,7 @@ tools_qfcc_test_methodparams_dat_SOURCES=tools/qfcc/test/methodparams.r methodparams_obj=$(tools_qfcc_test_methodparams_dat_SOURCES:.r=.o) methodparams_dep=$(call qcautodep,$(tools_qfcc_test_methodparams_dat_SOURCES)) tools/qfcc/test/methodparams.dat$(EXEEXT): $(methodparams_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(methodparams_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(methodparams_obj) tools/qfcc/test/methodparams.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(methodparams_dep) # am--include-marker @@ -335,7 +335,7 @@ tools_qfcc_test_modulo_dat_SOURCES=tools/qfcc/test/modulo.r modulo_obj=$(tools_qfcc_test_modulo_dat_SOURCES:.r=.o) modulo_dep=$(call qcautodep,$(tools_qfcc_test_modulo_dat_SOURCES)) tools/qfcc/test/modulo.dat$(EXEEXT): $(modulo_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(modulo_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(modulo_obj) tools/qfcc/test/modulo.run: $(qfcc_test_run_deps) @TEST_HARNESS_OPTS=--float $(top_srcdir)/tools/qfcc/test/build-run $@ include $(modulo_dep) # am--include-marker @@ -345,7 +345,7 @@ tools_qfcc_test_nilparamret_dat_SOURCES=tools/qfcc/test/nilparamret.r nilparamret_obj=$(tools_qfcc_test_nilparamret_dat_SOURCES:.r=.o) nilparamret_dep=$(call qcautodep,$(tools_qfcc_test_nilparamret_dat_SOURCES)) tools/qfcc/test/nilparamret.dat$(EXEEXT): $(nilparamret_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(nilparamret_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(nilparamret_obj) tools/qfcc/test/nilparamret.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(nilparamret_dep) # am--include-marker @@ -355,7 +355,7 @@ tools_qfcc_test_overload_dat_SOURCES=tools/qfcc/test/overload.r overload_obj=$(tools_qfcc_test_overload_dat_SOURCES:.r=.o) overload_dep=$(call qcautodep,$(tools_qfcc_test_overload_dat_SOURCES)) tools/qfcc/test/overload.dat$(EXEEXT): $(overload_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(overload_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(overload_obj) tools/qfcc/test/overload.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(overload_dep) # am--include-marker @@ -365,7 +365,7 @@ tools_qfcc_test_paramret_dat_SOURCES=tools/qfcc/test/paramret.r paramret_obj=$(tools_qfcc_test_paramret_dat_SOURCES:.r=.o) paramret_dep=$(call qcautodep,$(tools_qfcc_test_paramret_dat_SOURCES)) tools/qfcc/test/paramret.dat$(EXEEXT): $(paramret_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(paramret_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(paramret_obj) tools/qfcc/test/paramret.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(paramret_dep) # am--include-marker @@ -375,7 +375,7 @@ tools_qfcc_test_quaternion_dat_SOURCES=tools/qfcc/test/quaternion.r quaternion_obj=$(tools_qfcc_test_quaternion_dat_SOURCES:.r=.o) quaternion_dep=$(call qcautodep,$(tools_qfcc_test_quaternion_dat_SOURCES)) tools/qfcc/test/quaternion.dat$(EXEEXT): $(quaternion_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(quaternion_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(quaternion_obj) tools/qfcc/test/quaternion.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(quaternion_dep) # am--include-marker @@ -385,7 +385,7 @@ tools_qfcc_test_return_ivar_dat_SOURCES=tools/qfcc/test/return-ivar.r return_ivar_obj=$(tools_qfcc_test_return_ivar_dat_SOURCES:.r=.o) return_ivar_dep=$(call qcautodep,$(tools_qfcc_test_return_ivar_dat_SOURCES)) tools/qfcc/test/return-ivar.dat$(EXEEXT): $(return_ivar_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(return_ivar_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(return_ivar_obj) tools/qfcc/test/return-ivar.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(return_ivar_dep) # am--include-marker @@ -395,7 +395,7 @@ tools_qfcc_test_sendv_dat_SOURCES=tools/qfcc/test/sendv.r sendv_obj=$(tools_qfcc_test_sendv_dat_SOURCES:.r=.o) sendv_dep=$(call qcautodep,$(tools_qfcc_test_sendv_dat_SOURCES)) tools/qfcc/test/sendv.dat$(EXEEXT): $(sendv_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(sendv_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(sendv_obj) tools/qfcc/test/sendv.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(sendv_dep) # am--include-marker @@ -405,7 +405,7 @@ tools_qfcc_test_state_dat_SOURCES=tools/qfcc/test/state.r state_obj=$(tools_qfcc_test_state_dat_SOURCES:.r=.o) state_dep=$(call qcautodep,$(tools_qfcc_test_state_dat_SOURCES)) tools/qfcc/test/state.dat$(EXEEXT): $(state_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(state_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(state_obj) tools/qfcc/test/state.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(state_dep) # am--include-marker @@ -415,7 +415,7 @@ tools_qfcc_test_struct_init_param_dat_SOURCES=tools/qfcc/test/struct-init-param. struct_init_param_obj=$(tools_qfcc_test_struct_init_param_dat_SOURCES:.r=.o) struct_init_param_dep=$(call qcautodep,$(tools_qfcc_test_struct_init_param_dat_SOURCES)) tools/qfcc/test/struct-init-param.dat$(EXEEXT): $(struct_init_param_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(struct_init_param_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(struct_init_param_obj) tools/qfcc/test/struct-init-param.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(struct_init_param_dep) # am--include-marker @@ -425,7 +425,7 @@ tools_qfcc_test_struct_nil_init_dat_SOURCES=tools/qfcc/test/struct-nil-init.r struct_nil_init_obj=$(tools_qfcc_test_struct_nil_init_dat_SOURCES:.r=.o) struct_nil_init_dep=$(call qcautodep,$(tools_qfcc_test_struct_nil_init_dat_SOURCES)) tools/qfcc/test/struct-nil-init.dat$(EXEEXT): $(struct_nil_init_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(struct_nil_init_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(struct_nil_init_obj) tools/qfcc/test/struct-nil-init.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(struct_nil_init_dep) # am--include-marker @@ -435,7 +435,7 @@ tools_qfcc_test_structarray_dat_SOURCES=tools/qfcc/test/structarray.r structarray_obj=$(tools_qfcc_test_structarray_dat_SOURCES:.r=.o) structarray_dep=$(call qcautodep,$(tools_qfcc_test_structarray_dat_SOURCES)) tools/qfcc/test/structarray.dat$(EXEEXT): $(structarray_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structarray_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(structarray_obj) tools/qfcc/test/structarray.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(structarray_dep) # am--include-marker @@ -445,7 +445,7 @@ tools_qfcc_test_structlive_dat_SOURCES=tools/qfcc/test/structlive.r structlive_obj=$(tools_qfcc_test_structlive_dat_SOURCES:.r=.o) structlive_dep=$(call qcautodep,$(tools_qfcc_test_structlive_dat_SOURCES)) tools/qfcc/test/structlive.dat$(EXEEXT): $(structlive_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structlive_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(structlive_obj) tools/qfcc/test/structlive.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(structlive_dep) # am--include-marker @@ -455,7 +455,7 @@ tools_qfcc_test_structptr_dat_SOURCES=tools/qfcc/test/structptr.r structptr_obj=$(tools_qfcc_test_structptr_dat_SOURCES:.r=.o) structptr_dep=$(call qcautodep,$(tools_qfcc_test_structptr_dat_SOURCES)) tools/qfcc/test/structptr.dat$(EXEEXT): $(structptr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structptr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(structptr_obj) tools/qfcc/test/structptr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(structptr_dep) # am--include-marker @@ -465,7 +465,7 @@ tools_qfcc_test_structstruct_dat_SOURCES=tools/qfcc/test/structstruct.r structstruct_obj=$(tools_qfcc_test_structstruct_dat_SOURCES:.r=.o) structstruct_dep=$(call qcautodep,$(tools_qfcc_test_structstruct_dat_SOURCES)) tools/qfcc/test/structstruct.dat$(EXEEXT): $(structstruct_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(structstruct_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(structstruct_obj) tools/qfcc/test/structstruct.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(structstruct_dep) # am--include-marker @@ -475,7 +475,7 @@ tools_qfcc_test_swap_dat_SOURCES=tools/qfcc/test/swap.r swap_obj=$(tools_qfcc_test_swap_dat_SOURCES:.r=.o) swap_dep=$(call qcautodep,$(tools_qfcc_test_swap_dat_SOURCES)) tools/qfcc/test/swap.dat$(EXEEXT): $(swap_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(swap_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(swap_obj) tools/qfcc/test/swap.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(swap_dep) # am--include-marker @@ -485,7 +485,7 @@ tools_qfcc_test_triangle_dat_SOURCES=tools/qfcc/test/triangle.r triangle_obj=$(tools_qfcc_test_triangle_dat_SOURCES:.r=.o) triangle_dep=$(call qcautodep,$(tools_qfcc_test_triangle_dat_SOURCES)) tools/qfcc/test/triangle.dat$(EXEEXT): $(triangle_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(triangle_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(triangle_obj) tools/qfcc/test/triangle.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ 100000 100000 1.00005 50002.4961 include $(triangle_dep) # am--include-marker @@ -495,7 +495,7 @@ tools_qfcc_test_typedef_dat_SOURCES=tools/qfcc/test/typedef.r typedef_obj=$(tools_qfcc_test_typedef_dat_SOURCES:.r=.o) typedef_dep=$(call qcautodep,$(tools_qfcc_test_typedef_dat_SOURCES)) tools/qfcc/test/typedef.dat$(EXEEXT): $(typedef_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(typedef_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(typedef_obj) tools/qfcc/test/typedef.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(typedef_dep) # am--include-marker @@ -505,7 +505,7 @@ tools_qfcc_test_typelinker_dat_SOURCES=tools/qfcc/test/typelinker_a.r tools/qfcc typelinker_obj=$(tools_qfcc_test_typelinker_dat_SOURCES:.r=.o) typelinker_dep=$(call qcautodep,$(tools_qfcc_test_typelinker_dat_SOURCES)) tools/qfcc/test/typelinker.dat$(EXEEXT): $(typelinker_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(typelinker_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(typelinker_obj) tools/qfcc/test/typelinker.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(typelinker_dep) # am--include-marker @@ -515,7 +515,7 @@ tools_qfcc_test_unaryminus_dat_SOURCES=tools/qfcc/test/unaryminus.r unaryminus_obj=$(tools_qfcc_test_unaryminus_dat_SOURCES:.r=.o) unaryminus_dep=$(call qcautodep,$(tools_qfcc_test_unaryminus_dat_SOURCES)) tools/qfcc/test/unaryminus.dat$(EXEEXT): $(unaryminus_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(unaryminus_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(unaryminus_obj) tools/qfcc/test/unaryminus.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(unaryminus_dep) # am--include-marker @@ -525,7 +525,7 @@ tools_qfcc_test_vecaddr_dat_SOURCES=tools/qfcc/test/vecaddr.r vecaddr_obj=$(tools_qfcc_test_vecaddr_dat_SOURCES:.r=.o) vecaddr_dep=$(call qcautodep,$(tools_qfcc_test_vecaddr_dat_SOURCES)) tools/qfcc/test/vecaddr.dat$(EXEEXT): $(vecaddr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(vecaddr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(vecaddr_obj) tools/qfcc/test/vecaddr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(vecaddr_dep) # am--include-marker @@ -535,7 +535,7 @@ tools_qfcc_test_vecexpr_dat_SOURCES=tools/qfcc/test/vecexpr.r vecexpr_obj=$(tools_qfcc_test_vecexpr_dat_SOURCES:.r=.o) vecexpr_dep=$(call qcautodep,$(tools_qfcc_test_vecexpr_dat_SOURCES)) tools/qfcc/test/vecexpr.dat$(EXEEXT): $(vecexpr_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(vecexpr_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(vecexpr_obj) tools/qfcc/test/vecexpr.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(vecexpr_dep) # am--include-marker @@ -545,7 +545,7 @@ tools_qfcc_test_vecinit_dat_SOURCES=tools/qfcc/test/vecinit.r vecinit_obj=$(tools_qfcc_test_vecinit_dat_SOURCES:.r=.o) vecinit_dep=$(call qcautodep,$(tools_qfcc_test_vecinit_dat_SOURCES)) tools/qfcc/test/vecinit.dat$(EXEEXT): $(vecinit_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(vecinit_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(vecinit_obj) tools/qfcc/test/vecinit.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(vecinit_dep) # am--include-marker @@ -555,7 +555,7 @@ tools_qfcc_test_voidfor_dat_SOURCES=tools/qfcc/test/voidfor.r voidfor_obj=$(tools_qfcc_test_voidfor_dat_SOURCES:.r=.o) voidfor_dep=$(call qcautodep,$(tools_qfcc_test_voidfor_dat_SOURCES)) tools/qfcc/test/voidfor.dat$(EXEEXT): $(voidfor_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(voidfor_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(voidfor_obj) tools/qfcc/test/voidfor.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(voidfor_dep) # am--include-marker @@ -565,7 +565,7 @@ tools_qfcc_test_while_dat_SOURCES=tools/qfcc/test/while.r while_obj=$(tools_qfcc_test_while_dat_SOURCES:.r=.o) while_dep=$(call qcautodep,$(tools_qfcc_test_while_dat_SOURCES)) tools/qfcc/test/while.dat$(EXEEXT): $(while_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(while_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(while_obj) tools/qfcc/test/while.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(while_dep) # am--include-marker @@ -575,7 +575,7 @@ tools_qfcc_test_zerolinker_dat_SOURCES=tools/qfcc/test/zerolinker.r zerolinker_obj=$(tools_qfcc_test_zerolinker_dat_SOURCES:.r=.o) zerolinker_dep=$(call qcautodep,$(tools_qfcc_test_zerolinker_dat_SOURCES)) tools/qfcc/test/zerolinker.dat$(EXEEXT): $(zerolinker_obj) $(QFCC_DEP) - $(QFCC) $(QCFLAGS) -o $@ $(zerolinker_obj) + $(V_QFCCLD)$(QLINK) -o $@ $(zerolinker_obj) tools/qfcc/test/zerolinker.run: $(qfcc_test_run_deps) @$(top_srcdir)/tools/qfcc/test/build-run $@ include $(zerolinker_dep) # am--include-marker From 9347e4f9019c9ad69584a62f14c9fa4cefec293c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Jun 2020 18:30:01 +0900 Subject: [PATCH 1061/3664] [qwaq] Fix incorrect setting of progs argc/argv --- ruamoko/qwaq/builtins/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index da3607c01..931d33337 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -223,13 +223,13 @@ spawn_progs (qwaq_thread_t *thread) } PR_PushFrame (pr); - if (thread->args.size > 2) { - pr_argc = thread->args.size - 1; + if (thread->args.size) { + pr_argc = thread->args.size; } pr_argv = PR_Zone_Malloc (pr, (pr_argc + 1) * 4); pr_argv[0] = PR_SetTempString (pr, name); for (i = 1; i < pr_argc; i++) - pr_argv[i] = PR_SetTempString (pr, thread->args.a[1 + i]); + pr_argv[i] = PR_SetTempString (pr, thread->args.a[i]); pr_argv[i] = 0; PR_RESET_PARAMS (pr); From d90d409d2c8dfa017b978f3dfef6b3f698dd723b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Jun 2020 18:48:38 +0900 Subject: [PATCH 1062/3664] [ruamoko] Handle 0-length @va_list for va_copy Fixes a progs crash when using vsprintf with no format elements + params. --- libs/ruamoko/rua_runtime.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libs/ruamoko/rua_runtime.c b/libs/ruamoko/rua_runtime.c index 697fc720b..24a8a894d 100644 --- a/libs/ruamoko/rua_runtime.c +++ b/libs/ruamoko/rua_runtime.c @@ -56,8 +56,13 @@ bi_va_copy (progs_t *pr) __auto_type src_list = &G_STRUCT (pr, pr_type_t, src_args->list); size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); size_t size = src_args->count * parm_size; - string_t dst_list_block = PR_AllocTempBlock (pr, size); - __auto_type dst_list = (pr_type_t *) PR_GetString (pr, dst_list_block); + string_t dst_list_block = 0; + pr_type_t *dst_list = 0; + + if (size) { + dst_list_block = PR_AllocTempBlock (pr, size); + dst_list = (pr_type_t *) PR_GetString (pr, dst_list_block); + } memcpy (dst_list, src_list, size); R_PACKED (pr, pr_va_list_t).count = src_args->count; From c3ecd9c16dcfd99f0aa1d27923da5a5d5836bb54 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Jun 2020 23:32:38 +0900 Subject: [PATCH 1063/3664] [build] Put that ar warning to rest --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index 54ca7be00..71e429956 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,6 +44,7 @@ noinst_HEADERS = plugin_LTLIBRARIES = RANLIB=touch +ARFLAGS=cr EXTRA_HEADERS = EXTRA_LTLIBRARIES = From f6ea9e4d872b1585e2c1a1864caa3a9618755d79 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Jul 2020 21:47:09 +0900 Subject: [PATCH 1064/3664] [util] Store source line in plist items The first line of the parsed item is stored and can be retrieved using PL_Line. Line numbers not stored for dictionary keys yet. Will be 0 for any items generated by code rather than parsed from a file or string. --- include/QF/qfplist.h | 8 ++++++++ libs/util/qfplist.c | 24 +++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 7a12b7c4c..a7c73ec44 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -77,6 +77,14 @@ char *PL_WritePropertyList (plitem_t *pl); */ pltype_t PL_Type (plitem_t *item) __attribute__((pure)); +/** Retrieve the line number of an object. + + \param item The object + \return the line number on which the object began, or 0 if not from a + string +*/ +int PL_Line (plitem_t *item) __attribute__((pure)); + /** Retrieve a string from a string object. \param string The string object diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 0bda96e59..04dd32055 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -49,6 +49,7 @@ */ struct plitem_s { pltype_t type; + int line; void *data; }; @@ -176,17 +177,18 @@ PL_NewData (void *data, size_t size) } static plitem_t * -new_string (char *str) +new_string (char *str, int line) { plitem_t *item = PL_NewItem (QFString); item->data = str; + item->line = line; return item; } VISIBLE plitem_t * PL_NewString (const char *str) { - return new_string (strdup (str)); + return new_string (strdup (str), 0); } VISIBLE void @@ -688,6 +690,7 @@ PL_ParsePropertyListItem (pldata_t *pl) case '{': { item = PL_NewDictionary (); + item->line = pl->line; pl->pos++; @@ -767,6 +770,7 @@ PL_ParsePropertyListItem (pldata_t *pl) case '(': { item = PL_NewArray (); + item->line = pl->line; pl->pos++; @@ -812,27 +816,31 @@ PL_ParsePropertyListItem (pldata_t *pl) if (!str) { return NULL; } else { - return PL_NewData (str, len); + item = PL_NewData (str, len); + item->line = pl->line; + return item; } } case '"': { + int line = pl->line; char *str = PL_ParseQuotedString (pl); if (!str) { return NULL; } else { - return new_string (str); + return new_string (str, line); } } default: { + int line = pl->line; char *str = PL_ParseUnquotedString (pl); if (!str) { return NULL; } else { - return new_string (str); + return new_string (str, line); } } } // switch @@ -1038,3 +1046,9 @@ PL_Type (plitem_t *item) { return item->type; } + +VISIBLE int +PL_Line (plitem_t *item) +{ + return item->line; +} From 9785b944337cdba2707c2827b556e715812cef2e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Jul 2020 19:51:47 +0900 Subject: [PATCH 1065/3664] [qwaq] Fix a typo --- ruamoko/qwaq/builtins/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 931d33337..c4c426166 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -244,7 +244,7 @@ run_progs (void *data) __auto_type thread = (qwaq_thread_t *) data; spawn_progs (thread); - Sys_Printf ("starthing thread for %s\n", thread->args.a[0]); + Sys_Printf ("starting thread for %s\n", thread->args.a[0]); PR_ExecuteProgram (thread->pr, thread->main_func); PR_PopFrame (thread->pr); From 8bd5f4f201206bf64b03a757963fd8b5a5263a62 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Jul 2020 14:20:46 +0900 Subject: [PATCH 1066/3664] [util] Add code to parse a dictionary to a struct PL_ParseDictionary itself does only one level, but it takes care of the key-field mappings and property list item type checking leaving the actual parsing to a helper specified by the field. That helper is free to call PL_ParseDictionary recursively. --- include/QF/qfplist.h | 83 ++++++++++++++++++++++++++++ libs/util/qfplist.c | 125 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index a7c73ec44..5d719b840 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -53,6 +53,52 @@ typedef enum { */ typedef struct plitem_s plitem_t; +struct plfield_s; +/** Custom parser for the field. + + With this, custom parsing of any property list object type is + supported. For example, parsing of strings into numeric values, + converting binary objects to images, and deeper parsing of array and + dictionary objects. + + If null, then the default parser for the object type is used: + * QFString: the point to the actual string. The string continues + to be owned by the string object. + * QFBinary: pointer to fixed-size DARRAY_TYPE(byte) (so size isn't + lost) + * QFArray: pointer to fixed-size DARRAY_TYPE(plitem_t *) with the + indivisual objects. The individual objects continue to be owned + by the array object. + * QFDictionary: pointer to the hashtab_t hash table used for the + dictionary object. The hash table continues to be owned by the + dictionary object. + + \param field Pointer to this field item. + \param item The property list item being parsed into the field. + \param data Pointer to the field in the structure being parsed. + \param messages An array object the parser can use to store any + error messages. Messages should be strings, but no + checking is done: it is up to the top-level caller to + parse out the messages. + \return 0 for error, 1 for success. See \a PL_ParseDictionary. +*/ +typedef int (*plparser_t) (const struct plfield_s *field, + const struct plitem_s *item, + void *data, + struct plitem_s *messages); + +/** A field to be parsed from a dictionary item. + + something +*/ +typedef struct plfield_s { + const char *name; ///< matched by dictionary key + size_t offset; ///< the offset of the field within the structure + pltype_t type; ///< the required type of the dictionary object + plparser_t parser; ///< custom parser function + void *data; ///< additional data for \a parser +} plfield_t; + /** Create an in-memory representation of the contents of a property list. \param string the saved plist, as read from a file. @@ -234,6 +280,43 @@ plitem_t *PL_NewString (const char *str); */ void PL_Free (plitem_t *item); +/** Parse a dictionary object into a structure. + + For each key in the dictionary, the corresponding field item is used to + determine how to parse the object associated with that key. Duplicate + field items are ignored: only the first item is used, and no checking is + done. Fields for which there is no key in the dictionary are also ignored, + and the destination is left unmodified. However, keys that have no + corresponding field are treated as errors and a suitable message is added + to the \a messages object. + + When an error occurs (unknown key, incorrect item type (item type does not + match the type specified in the field item) or the field item's \a parser + returns 0), processing continues but the error result is returned. + + Can be used recursively to parse deep hierarchies. + + \param dict The dictionary object to parse + \param fields Array of field items describing the structure. Terminated + by a field item with a null \a name pointer. + \param data Pointer to the structure into which the data will be + parsed. + \param messages Array object supplied by the caller used for storing + messages. The messages may or may not indicate errors (its + contents are not checked). This function itself will add + only string objects. + If there are any errors, suitable messages will be found in + the \a messages object. However, just because there are no + errors doesn't mean that \a messages will remain empty as + a field's \a parser may add other messages. The standard + message format is "[line number]: [message]". If the line + number is 0, then the actual line is unknown (due to the + source item not being parsed from a file or string). + \return 0 if there are any errors, 1 if there are no errors. +*/ +int PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, + void *data, plitem_t *messages); + ///@} #endif//__QF_qfplist_h diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 04dd32055..35f136374 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -38,11 +38,13 @@ #include "qfalloca.h" +#include "QF/darray.h" #include "QF/dstring.h" #include "QF/hash.h" #include "QF/qfplist.h" #include "QF/qtypes.h" #include "QF/sys.h" +#include "QF/va.h" /* Generic property list item. @@ -97,6 +99,13 @@ typedef struct pldata_s { // Unparsed property list string : 10 + (inrange((ch), 'a', 'f') ? ((ch) - 'a') \ : ((ch) - 'A'))) +static const char *pl_types[] = { + "dictionary", + "array", + "biinary", + "string", +}; + static byte quotable_bitmap[32]; static inline int is_quotable (byte x) @@ -1052,3 +1061,119 @@ PL_Line (plitem_t *item) { return item->line; } + +static void __attribute__((format(printf,3,4))) +pl_message (plitem_t *messages, const plitem_t *item, const char *fmt, ...) +{ + va_list args; + dstring_t *string; + + string = dstring_new (); + + va_start (args, fmt); + dvsprintf (string, fmt, args); + va_end (args); + + if (item) { + PL_A_AddObject (messages, + PL_NewString (va ("%d: %s", item->line, string->str))); + } else { + PL_A_AddObject (messages, + PL_NewString (va ("internal: %s", string->str))); + } + dstring_delete (string); +} + +static int +pl_default_parser (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages) +{ + switch (field->type) { + case QFDictionary: + { + *(hashtab_t **)data = (hashtab_t *)item->data; + } + return 1; + case QFArray: + { + plarray_t *array = (plarray_t *)item->data; + typedef struct DARRAY_TYPE (plitem_t *) arraydata_t; + arraydata_t *arraydata = DARRAY_ALLOCFIXED(arraydata_t, + array->numvals, + malloc); + memcpy (arraydata->a, array->values, + array->numvals * sizeof (arraydata->a[0])); + } + return 1; + case QFBinary: + { + plbinary_t *binary = (plbinary_t *)item->data; + typedef struct DARRAY_TYPE (byte) bindata_t; + bindata_t *bindata = DARRAY_ALLOCFIXED(bindata_t, + binary->size, malloc); + memcpy (bindata->a, binary->data, binary->size); + *(bindata_t **)data = bindata; + } + return 1; + case QFString: + *(char **)data = (char *)item->data; + return 1; + } + pl_message (messages, 0, "invalid item type: %d", field->type); + return 0; +} + +VISIBLE int +PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, + plitem_t *messages) +{ + void **list, **l; + dictkey_t *current; + int result; + int (*parser) (const plfield_t *, const plitem_t *, void *, + plitem_t *); + + if (dict->type != QFDictionary) { + pl_message (messages, dict, "error: not a dictionary object"); + return 0; + } + + if (!(l = list = Hash_GetList ((hashtab_t *) dict->data))) { + // empty struct: leave as default + return 1; + } + + while ((current = (dictkey_t *) *l++)) { + const plfield_t *f; + for (f = fields; f->name; f++) { + if (strcmp (f->name, current->key) == 0) { + plitem_t *item = current->value; + void *flddata = (byte *)data + f->offset; + + if (f->parser) { + parser = f->parser; + } else { + parser = pl_default_parser; + } + if (item->type != f->type) { + pl_message (messages, item, "error: %s is the wrong type" + " Got %s, expected %s",current->key, + pl_types[f->type], + pl_types[item->type]); + result = 0; + } else { + if (!parser (f, item, flddata, messages)) { + result = 0; + } + } + } + } + if (!f->name) { + pl_message (messages, dict, "error: unknown field %s", + current->key); + result = 0; + } + } + free (list); + return result; +} From 2ca9f80d56cce3aed3fa89d1f0a9ed919d5b6028 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Jul 2020 14:24:39 +0900 Subject: [PATCH 1067/3664] [vulkan] Split up vkgen It worked as a proof of concept, but as the code itself needs to be a bit smarter, it would be a lot smarter to break up that code to make it easier to work on the individual parts. --- .../video/renderer/vulkan/vkgen/Makemodule.am | 9 +- libs/video/renderer/vulkan/vkgen/vkenum.h | 13 ++ libs/video/renderer/vulkan/vkgen/vkenum.r | 75 ++++++++ libs/video/renderer/vulkan/vkgen/vkgen.h | 18 ++ libs/video/renderer/vulkan/vkgen/vkgen.r | 162 +----------------- libs/video/renderer/vulkan/vkgen/vkstruct.h | 16 ++ libs/video/renderer/vulkan/vkgen/vkstruct.r | 43 +++++ libs/video/renderer/vulkan/vkgen/vktype.h | 18 ++ libs/video/renderer/vulkan/vkgen/vktype.r | 33 ++++ 9 files changed, 228 insertions(+), 159 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkenum.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkenum.r create mode 100644 libs/video/renderer/vulkan/vkgen/vkgen.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkstruct.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkstruct.r create mode 100644 libs/video/renderer/vulkan/vkgen/vktype.h create mode 100644 libs/video/renderer/vulkan/vkgen/vktype.r diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 901dea622..5eb099c9c 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -2,7 +2,10 @@ vkgen = libs/video/renderer/vulkan/vkgen.dat$(EXEEXT) noinst_PROGRAMS += $(vkgen) vkgen_dat_src= \ + libs/video/renderer/vulkan/vkgen/vkenum.r \ libs/video/renderer/vulkan/vkgen/vkgen.r \ + libs/video/renderer/vulkan/vkgen/vkstruct.r \ + libs/video/renderer/vulkan/vkgen/vktype.r \ libs/video/renderer/vulkan/vkgen/vulkan.r VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen @@ -29,6 +32,10 @@ libs/video/renderer/vulkan/vkgen/vulkan.o: $(top_srcdir)/libs/video/renderer/vul EXTRA_DIST += \ libs/video/renderer/vulkan/vkgen/stddef.h \ - libs/video/renderer/vulkan/vkgen/stdint.h + libs/video/renderer/vulkan/vkgen/stdint.h \ + libs/video/renderer/vulkan/vkgen/vkenum.h \ + libs/video/renderer/vulkan/vkgen/vkgen.h \ + libs/video/renderer/vulkan/vkgen/vkstruct.h \ + libs/video/renderer/vulkan/vkgen/vktype.h \ CLEANFILES += \ libs/video/renderer/vkgen/*.sym diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.h b/libs/video/renderer/vulkan/vkgen/vkenum.h new file mode 100644 index 000000000..5deb7ff6f --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkenum.h @@ -0,0 +1,13 @@ +#ifndef __renderer_vulkan_vkgen_vkenum_h +#define __renderer_vulkan_vkgen_vkenum_h + +#include "vktype.h" + +@interface Enum: Type +{ + int prefix_length; +} +-(void) writeTable; +@end + +#endif//__renderer_vulkan_vkgen_vkenum_h diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r new file mode 100644 index 000000000..898ef5c58 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -0,0 +1,75 @@ +#include + +#include "vkenum.h" +#include "vkgen.h" + +@implementation Enum +-(void)process +{ + string end = "_MAX_ENUM"; + int len; + string prefix = nil; + + if (str_mid([self name], -8) == "FlagBits") { + end = "_FLAG_BITS_MAX_ENUM"; + } + len = -strlen (end); + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (str_mid (var.name, len) == end) { + // len is negative so +1 consumes 1 more char (_) + prefix = str_hold (str_mid (var.name, 0, len + 1)); + } + } + if (prefix) { + prefix_length = strlen (prefix); + } +} + +-initWithType: (qfot_type_t *) type +{ + if (!(self = [super initWithType: type])) { + return nil; + } + [self process]; + return self; +} + +-(string) name +{ + return str_mid(type.strct.tag, 4); +} + +-(void) writeTable +{ + int strip_bit = 0; + if (str_mid([self name], -8) == "FlagBits") { + strip_bit = 1; + } + + fprintf (output_file, "enumval_t %s_values[] = {\n", [self name]); + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (str_str (var.name, "_MAX_ENUM") >= 0 + || str_str (var.name, "_BEGIN_RANGE") >= 0 + || str_str (var.name, "_END_RANGE") >= 0 + || str_str (var.name, "_RANGE_SIZE") >= 0) { + continue; + } + fprintf (output_file, "\t{\"%s\", %d},\n", var.name, var.offset); + if (prefix_length) { + string shortname = str_mid (var.name, prefix_length); + if (strip_bit) { + int bit_pos = str_str (shortname, "_BIT"); + if (bit_pos >= 0) { + shortname = str_mid (shortname, 0, bit_pos); + } + } + fprintf (output_file, "\t{\"%s\", %d},\n", str_lower(shortname), + var.offset); + } + } + fprintf (output_file, "\t{ }\n"); + fprintf (output_file, "};\n"); +} +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.h b/libs/video/renderer/vulkan/vkgen/vkgen.h new file mode 100644 index 000000000..3612a048f --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkgen.h @@ -0,0 +1,18 @@ +#ifndef __renderer_vulkan_vkgen_vkgen_h +#define __renderer_vulkan_vkgen_vkgen_h + +#include +#include +#include +#include + +typedef void varfunc (qfot_var_t *var); + +void printf (string fmt, ...); +void fprintf (QFile file, string format, ...); +extern Array *queue; +extern Array *output_types; +extern QFile output_file; +extern hashtab_t *processed_types; + +#endif//__renderer_vulkan_vkgen_vkgen_h diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 1400d3fbc..7ef9f3ff6 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -5,6 +5,10 @@ #include #include +#include "vkgen.h" +#include "vkstruct.h" +#include "vkenum.h" + void printf (string fmt, ...) = #0; void fprintf (QFile file, string format, ...) @@ -13,8 +17,6 @@ void fprintf (QFile file, string format, ...) Qputs (file, vsprintf (format, va_copy (@args))); } -typedef void varfunc (qfot_var_t *var); - string search_names[] = { "VkGraphicsPipelineCreateInfo", "VkComputePipelineCreateInfo", @@ -27,162 +29,6 @@ Array *output_types; QFile output_file; -@interface Enum: Object -{ - qfot_type_t *type; - int prefix_length; -} --initWithType: (qfot_type_t *) type; -/** \warning returned string is ephemeral -*/ --(string) name; -@end - -@implementation Enum --(void)process -{ - string end = "_MAX_ENUM"; - int len; - string prefix = nil; - - if (str_mid([self name], -8) == "FlagBits") { - end = "_FLAG_BITS_MAX_ENUM"; - } - len = -strlen (end); - for (int i = 0; i < type.strct.num_fields; i++) { - qfot_var_t *var = &type.strct.fields[i]; - if (str_mid (var.name, len) == end) { - // len is negative so +1 consumes 1 more char (_) - prefix = str_hold (str_mid (var.name, 0, len + 1)); - } - } - if (prefix) { - prefix_length = strlen (prefix); - } -} - --initWithType: (qfot_type_t *) type -{ - if (!(self = [super init])) { - return nil; - } - self.type = type; - [self process]; - return self; -} - --(string) name -{ - return str_mid(type.strct.tag, 4); -} - --(void) addToQueue -{ - string name = [self name]; - //printf (" +%s\n", name); - if (!Hash_Find (processed_types, name)) { - Hash_Add (processed_types, (void *) name); - [queue addObject: self]; - } -} - --(void) writeTable -{ - int strip_bit = 0; - if (str_mid([self name], -8) == "FlagBits") { - strip_bit = 1; - } - - fprintf (output_file, "enumval_t %s_values[] = {\n", [self name]); - for (int i = 0; i < type.strct.num_fields; i++) { - qfot_var_t *var = &type.strct.fields[i]; - if (str_str (var.name, "_MAX_ENUM") >= 0 - || str_str (var.name, "_BEGIN_RANGE") >= 0 - || str_str (var.name, "_END_RANGE") >= 0 - || str_str (var.name, "_RANGE_SIZE") >= 0) { - continue; - } - fprintf (output_file, "\t{\"%s\", %d},\n", var.name, var.offset); - if (prefix_length) { - string shortname = str_mid (var.name, prefix_length); - if (strip_bit) { - int bit_pos = str_str (shortname, "_BIT"); - if (bit_pos >= 0) { - shortname = str_mid (shortname, 0, bit_pos); - } - } - fprintf (output_file, "\t{\"%s\", %d},\n", str_lower(shortname), - var.offset); - } - } - fprintf (output_file, "\t{ }\n"); - fprintf (output_file, "};\n"); -} -@end - -@interface Struct: Object -{ - qfot_type_t *type; -} --initWithType: (qfot_type_t *) type; -/** \warning returned string is ephemeral -*/ --(string) name; --(void) forEachFieldCall: (varfunc) func; -@end - -@implementation Struct --initWithType: (qfot_type_t *) type -{ - if (!(self = [super init])) { - return nil; - } - self.type = type; - return self; -} - --(string) name -{ - return str_mid(type.strct.tag, 4); -} - --(void) forEachFieldCall: (varfunc) func -{ - qfot_struct_t *strct =&type.strct; - - for (int i = 0; i < strct.num_fields; i++) { - func (&strct.fields[i]); - } -} - --(void) addToQueue -{ - string name = [self name]; - //printf (" +%s\n", name); - if (!Hash_Find (processed_types, name)) { - Hash_Add (processed_types, (void *) name); - [queue addObject: self]; - } -} - --(void) writeTable -{ - fprintf (output_file, "structfld_t %s_fields[] = {\n", [self name]); - for (int i = 0; i < type.strct.num_fields; i++) { - qfot_var_t *var = &type.strct.fields[i]; - if (var.name == "sType" || var.name == "pNext") { - continue; - } - string type_name = var.type.encoding; - fprintf (output_file, - "\t{\"%s\", field_offset (%s, %s), %s, %s}, // %s\n", - var.name, [self name], var.name, "0", "0", type_name); - } - fprintf (output_file, "\t{ }\n"); - fprintf (output_file, "};\n"); -} -@end - qfot_type_encodings_t *encodings; qfot_type_t * diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h new file mode 100644 index 000000000..a8a0df7e9 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -0,0 +1,16 @@ +#ifndef __renderer_vulkan_vkgen_vkstruct_h +#define __renderer_vulkan_vkgen_vkstruct_h + +#include + +#include "vkgen.h" +#include "vktype.h" + +@interface Struct: Type +{ +} +-(void) forEachFieldCall: (varfunc) func; +-(void) writeTable; +@end + +#endif//__renderer_vulkan_vkgen_vkstruct_h diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r new file mode 100644 index 000000000..fa5193b11 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include + +#include "vkgen.h" +#include "vkstruct.h" + +@implementation Struct + +-(string) name +{ + return str_mid(type.strct.tag, 4); +} + +-(void) forEachFieldCall: (varfunc) func +{ + qfot_struct_t *strct =&type.strct; + + for (int i = 0; i < strct.num_fields; i++) { + func (&strct.fields[i]); + } +} + +-(void) writeTable +{ + fprintf (output_file, "structfld_t %s_fields[] = {\n", [self name]); + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (var.name == "sType" || var.name == "pNext") { + continue; + } + string type_name = var.type.encoding; + fprintf (output_file, + "\t{\"%s\", field_offset (%s, %s), %s, %s}, // %s\n", + var.name, [self name], var.name, "0", "0", type_name); + } + fprintf (output_file, "\t{ }\n"); + fprintf (output_file, "};\n"); +} +@end diff --git a/libs/video/renderer/vulkan/vkgen/vktype.h b/libs/video/renderer/vulkan/vkgen/vktype.h new file mode 100644 index 000000000..a4ffb83c4 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vktype.h @@ -0,0 +1,18 @@ +#ifndef __renderer_vulkan_vkgen_vktype_h +#define __renderer_vulkan_vkgen_vktype_h + +#include +#include + +@interface Type: Object +{ + qfot_type_t *type; +} +-initWithType: (qfot_type_t *) type; +/** \warning returned string is ephemeral +*/ +-(string) name; +-(void) addToQueue; +@end + +#endif//__renderer_vulkan_vkgen_vktype_h diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r new file mode 100644 index 000000000..b3a7bcf2c --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -0,0 +1,33 @@ +#include + +#include "vkgen.h" +#include "vktype.h" + +@implementation Type + +-initWithType: (qfot_type_t *) type +{ + if (!(self = [super init])) { + return nil; + } + self.type = type; + return self; +} + +-(string) name +{ + //FIXME extract alias name and return proper type name + return type.encoding; +} + +-(void) addToQueue +{ + string name = [self name]; + //printf (" +%s\n", name); + if (!Hash_Find (processed_types, name)) { + Hash_Add (processed_types, (void *) name); + [queue addObject: self]; + } +} + +@end From 64100efe7837ed50cbabdece17907352e9004cd2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Jul 2020 19:51:47 +0900 Subject: [PATCH 1068/3664] [qwaq] Fix a typo --- ruamoko/qwaq/builtins/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 931d33337..c4c426166 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -244,7 +244,7 @@ run_progs (void *data) __auto_type thread = (qwaq_thread_t *) data; spawn_progs (thread); - Sys_Printf ("starthing thread for %s\n", thread->args.a[0]); + Sys_Printf ("starting thread for %s\n", thread->args.a[0]); PR_ExecuteProgram (thread->pr, thread->main_func); PR_PopFrame (thread->pr); From 98795bf60443e0e36d37d23b0a462aa994afc0c5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jul 2020 21:40:40 +0900 Subject: [PATCH 1069/3664] [gamecode] Add a comment about returning temp strings --- libs/gamecode/pr_strings.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 89d5ee60f..e8e1dff85 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -693,6 +693,11 @@ PR_FreeTempStrings (progs_t *pr) PR_Error (pr, "internal string error: %d", __LINE__); if (R_STRING (pr) < 0 && string_index (res, sr) == R_STRING (pr) && pr->pr_depth) { + // It looks like the temp string is being returned. While this + // may be a false positive (just a random integer with the same + // value), it is better to hold onto the temp string a little + // longer than to remove it prematurely. This allows functions + // to return the result of "str a" + "str b" prstack_t *frame = pr->pr_stack + pr->pr_depth - 1; sr->next = frame->tstr; frame->tstr = sr; From 1910941426a2f17a900b463adfd3dd202b669d48 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jul 2020 21:41:51 +0900 Subject: [PATCH 1070/3664] [qwaq] Handle key events differently when running Pressing F8 (or n) while the debug target was running would cause it to stop at that point. While it's certainly desirable to stop a runaway target on demand, that should be with a different input. Now, commands that start the target running are ignored while the target is running. No commands for when the target is running have been implemented yet, but the provision is there. --- ruamoko/qwaq/debugger/debugger.h | 1 + ruamoko/qwaq/debugger/debugger.r | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 9e6c750d2..8694d06c0 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -28,6 +28,7 @@ int onExit; } sub_cond; SEL traceHandler; + int running; Window *source_window; ScrollBar *source_scrollbar; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 2d51e3c60..abd8a326b 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -127,7 +127,7 @@ } static int -proxy_event (Debugger *self, id proxy, qwaq_event_t *event) +proxy_event_stopped (Debugger *self, id proxy, qwaq_event_t *event) { if (event.what == qe_mouseclick && !(event.mouse.buttons & 0x78)) { if (proxy == self.current_file) { @@ -142,6 +142,7 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) self.traceHandler = @selector(traceStep); qdb_set_trace (self.target, 1); self.trace_cond.state = qdb_get_state (self.target); + self.running = 1; qdb_continue (self.target); return 1; case QFK_F8: @@ -150,6 +151,7 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) qdb_set_trace (self.target, 1); self.trace_cond.state = qdb_get_state (self.target); self.trace_cond.depth = qdb_get_stack_depth (self.target); + self.running = 1; qdb_continue (self.target); return 1; } @@ -157,15 +159,28 @@ proxy_event (Debugger *self, id proxy, qwaq_event_t *event) return 0; } +static int +proxy_event_running (Debugger *self, id proxy, qwaq_event_t *event) +{ + return 0; +} + -(void)proxy_event:(id)proxy :(qwaq_event_t *)event { - if (proxy_event (self, proxy, event)) { - event.what = qe_none; + if (running) { + if (proxy_event_running (self, proxy, event)) { + event.what = qe_none; + } + } else { + if (proxy_event_stopped (self, proxy, event)) { + event.what = qe_none; + } } } -stop:(prdebug_t)reason { + running = 0; if (!file_proxy) { [self setup]; } From 225ee0ed3c3cbaf797449a23490e857bd230a98a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jul 2020 21:46:09 +0900 Subject: [PATCH 1071/3664] [qwaq] Use an actual condition variable for control I think I wasn't sure at the time whether the simple variable was required for pthread_cond_wait (and friends) to work properly, but it is: the time between the target posting the debug event and the target waiting on the condition variable turns out to sometimes be enough for the debugger to handle the event and signal the target to continue, resulting in the target waiting on a signal that will never come because another debug event will not be sent by the target until AFTER it has exited from the debug handler. --- ruamoko/qwaq/builtins/debug.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index bb22d35e2..d16ac6f97 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -59,6 +59,7 @@ typedef struct qwaq_target_s { prdebug_t event; void *param; rwcond_t run_cond; + int run_command; } qwaq_target_t; typedef struct qwaq_debug_s { @@ -130,7 +131,10 @@ qwaq_debug_handler (prdebug_t debug_event, void *param, void *data) Sys_Error ("event queue broke"); } pthread_mutex_lock (&target->run_cond.mut); - pthread_cond_wait (&target->run_cond.rcond, &target->run_cond.mut); + while (!target->run_command) { + pthread_cond_wait (&target->run_cond.rcond, &target->run_cond.mut); + } + target->run_command = 0; pthread_mutex_unlock (&target->run_cond.mut); if (debug_event == prd_runerror || debug_event == prd_error) { pthread_exit (param); @@ -185,6 +189,7 @@ qwaq_target_load (progs_t *pr) target->debugger = qwaq_debug_data; target->handle = target_index (qwaq_debug_data, target); qwaq_init_cond (&target->run_cond); + target->run_command = 0; pr->debug_handler = qwaq_debug_handler; pr->debug_data = target; @@ -280,6 +285,7 @@ qdb_continue (progs_t *pr) qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); pthread_mutex_lock (&target->run_cond.mut); + target->run_command = 1; pthread_cond_signal (&target->run_cond.rcond); pthread_mutex_unlock (&target->run_cond.mut); } From 1914fa27565b68ae6b7193ac41f3ae4f51720a74 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jul 2020 01:36:46 +0900 Subject: [PATCH 1072/3664] [qwaq] Use full file path for file search Fixes the memory leak (over 300 editors...) --- ruamoko/qwaq/debugger/debugger.r | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index abd8a326b..3acf1707e 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -53,6 +53,7 @@ -(Editor *) find_file:(string) filename { Editor *file; + filename = qdb_get_file_path (target, filename); for (int i = [files count]; i-- > 0; ) { file = [files objectAtIndex: i]; if ([file filename] == filename) { @@ -62,8 +63,7 @@ Rect rect = {{1, 1}, [source_window size]}; rect.extent.width -= 2; rect.extent.height -= 2; - string filepath = qdb_get_file_path (target, filename); - file = [Editor withRect:rect file:filepath]; + file = [Editor withRect:rect file:filename]; [files addObject: file]; return file; } From e4ee5c70e0d8cc8adfeaa3becee78502f3f5c8d2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jul 2020 01:40:02 +0900 Subject: [PATCH 1073/3664] [vulkan] Rework vkgen alias handling This is much cleaner and now that all the types are there properly, doing a parser generator should be easier. --- libs/video/renderer/Makemodule.am | 19 ++- .../video/renderer/vulkan/vkgen/Makemodule.am | 2 + libs/video/renderer/vulkan/vkgen/vkalias.h | 11 ++ libs/video/renderer/vulkan/vkgen/vkalias.r | 52 ++++++ libs/video/renderer/vulkan/vkgen/vkenum.r | 10 ++ libs/video/renderer/vulkan/vkgen/vkgen.h | 1 + libs/video/renderer/vulkan/vkgen/vkgen.r | 158 +++++------------- libs/video/renderer/vulkan/vkgen/vkstruct.r | 10 ++ libs/video/renderer/vulkan/vkgen/vktype.h | 7 +- libs/video/renderer/vulkan/vkgen/vktype.r | 64 ++++++- 10 files changed, 209 insertions(+), 125 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkalias.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkalias.r diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index b1196dc2f..d6ae44226 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -219,12 +219,25 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_draw.c \ libs/video/renderer/vulkan/vulkan_vid_common.c +libs/video/renderer/vulkan/vulkan_vid_common.c: $(vkparse_src) + qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) -BUILT_SOURCES += libs/video/renderer/vulkan/vkenum.inc +vkparse_src = \ + libs/video/renderer/vulkan/vkenum.inc \ + libs/video/renderer/vulkan/vkstruct.inc + +V_VKGEN = $(V_VKGEN_@AM_V@) +V_VKGEN_ = $(V_VKGEN_@AM_DEFAULT_V@) +V_VKGEN_0 = @echo " VKGEN " $@; +V_VKGEN_1 = + libs/video/renderer/vulkan/vkenum.inc: $(vkgen) $(qwaq_curses) - $(qwaq_curses) $(vkgen) -- $@ + $(V_VKGEN)$(qwaq_curses) $(vkgen) -- enum $@ +libs/video/renderer/vulkan/vkstruct.inc: $(vkgen) $(qwaq_curses) + $(V_VKGEN)$(qwaq_curses) $(vkgen) -- struct $@ CLEANFILES += \ libs/video/renderer/glsl/*.vc \ libs/video/renderer/glsl/*.fc \ - libs/video/renderer/glsl/*.slc + libs/video/renderer/glsl/*.slc \ + $(vkparse_src) diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 5eb099c9c..66971a2c3 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -2,6 +2,7 @@ vkgen = libs/video/renderer/vulkan/vkgen.dat$(EXEEXT) noinst_PROGRAMS += $(vkgen) vkgen_dat_src= \ + libs/video/renderer/vulkan/vkgen/vkalias.r \ libs/video/renderer/vulkan/vkgen/vkenum.r \ libs/video/renderer/vulkan/vkgen/vkgen.r \ libs/video/renderer/vulkan/vkgen/vkstruct.r \ @@ -33,6 +34,7 @@ libs/video/renderer/vulkan/vkgen/vulkan.o: $(top_srcdir)/libs/video/renderer/vul EXTRA_DIST += \ libs/video/renderer/vulkan/vkgen/stddef.h \ libs/video/renderer/vulkan/vkgen/stdint.h \ + libs/video/renderer/vulkan/vkgen/vkalias.h \ libs/video/renderer/vulkan/vkgen/vkenum.h \ libs/video/renderer/vulkan/vkgen/vkgen.h \ libs/video/renderer/vulkan/vkgen/vkstruct.h \ diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.h b/libs/video/renderer/vulkan/vkgen/vkalias.h new file mode 100644 index 000000000..fadf6619f --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkalias.h @@ -0,0 +1,11 @@ +#ifndef __renderer_vulkan_vkgen_vkalias_h +#define __renderer_vulkan_vkgen_vkalias_h + +#include "vktype.h" + +@interface Alias: Type +{ +} +@end + +#endif//__renderer_vulkan_vkgen_vkalias_h diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r new file mode 100644 index 000000000..f37396097 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -0,0 +1,52 @@ +#include + +#include "vkalias.h" +#include "vkenum.h" +#include "vkgen.h" +#include "vkstruct.h" + +@implementation Alias +-(string) name +{ + return type.alias.name; +} + +-(Type *) resolveType +{ + return [Type findType: type.alias.aux_type]; +} + +-(void)addToQueue +{ + Type *alias = [Type findType:type.alias.full_type]; + string name = [self name]; + + if ([alias name] == "VkFlags") { + if (str_mid (name, -5) == "Flags") { + string tag = str_mid (name, 0, -1) + "Bits"; + id enumObj = [(id) Hash_Find (available_types, tag) resolveType]; + [enumObj addToQueue]; + } + } else if (name == "VkBool32") { + // drop + } else if ([alias class] == [Enum class] + || [alias class] == [Struct class]) { + [alias addToQueue]; + } else if (alias.type.meta == ty_basic && alias.type.type == ev_pointer) { + Type *type = [Type findType:alias.type.fldptr.aux_type]; + if (!type) { + // pointer to opaque struct. Probably VK_DEFINE_NON_DISPATCHABLE_HANDLE or VK_DEFINE_HANDLE + string createInfo = name + "CreateInfo"; + id structObj = (id) Hash_Find (available_types, createInfo); + if (structObj) { + [structObj addToQueue]; + } + } else if ([type class] == [Alias class]) { + type = [type resolveType]; + if ([type class] == [Struct class]) { + [type addToQueue]; + } + } + } +} +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 898ef5c58..10a476432 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -40,6 +40,16 @@ return str_mid(type.strct.tag, 4); } +-(void) addToQueue +{ + string name = [self name]; + if (!Hash_Find (processed_types, name)) { + printf (" +%s\n", name); + Hash_Add (processed_types, (void *) name); + [queue addObject: self]; + } +} + -(void) writeTable { int strip_bit = 0; diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.h b/libs/video/renderer/vulkan/vkgen/vkgen.h index 3612a048f..0d488abe8 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.h +++ b/libs/video/renderer/vulkan/vkgen/vkgen.h @@ -14,5 +14,6 @@ extern Array *queue; extern Array *output_types; extern QFile output_file; extern hashtab_t *processed_types; +extern hashtab_t *available_types; #endif//__renderer_vulkan_vkgen_vkgen_h diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 7ef9f3ff6..183ba591b 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -13,7 +13,6 @@ void printf (string fmt, ...) = #0; void fprintf (QFile file, string format, ...) { - printf("fprintf %d\n", @args.count); Qputs (file, vsprintf (format, va_copy (@args))); } @@ -87,97 +86,8 @@ void print_type (qfot_type_t *type) void struct_func (qfot_var_t *var) { - qfot_type_t *alias; - if (var.type.meta == ty_enum) { - printf("%s a\n", var.name); - } else if (var.type.meta == ty_struct) { - printf("%s b\n", var.name); - } else if (var.type.meta == ty_union) { - printf("%s c\n", var.name); - } else if (var.type.meta == ty_alias) { - //printf("%s d\n", var.name); - // typedef fun ;) - alias = var.type.alias.full_type; - if (alias.meta == ty_alias) { - // double(+) typedef - if (alias.alias.name == "VkFlags") { - // enum flag fun :P - string tag = var.type.alias.name; - if (str_mid (tag, -5) == "Flags") { - tag = str_mid (tag, 0, -1) + "Bits"; - id enumObj = (id) Hash_Find (available_types, tag); - if (enumObj) { - [enumObj addToQueue]; - } - } - } else { - if (var.type.alias.name == "VkBool32") { - // drop - } else { - printf ("%s =%s\n", var.name, var.type.alias.name); - } - } - } else if (alias.meta == ty_enum) { - string tag = str_mid(alias.strct.tag, 4); - id enumObj = (id) Hash_Find (available_types, tag); - if (enumObj) { - [enumObj addToQueue]; - } - } else if (alias.meta == ty_basic && alias.type == ev_pointer) { - //printf("e\n"); - qfot_type_t *type = alias.fldptr.aux_type; - if (type.meta == ty_alias) { - id structObj = (id) Hash_Find (available_types, type.alias.name); - //printf (" a:%s %p\n", type.alias.name, structObj); - if (structObj) { - [structObj addToQueue]; - } - } else if (type_is_null (type)) { - // pointer to opaque struct. Probably VK_DEFINE_NON_DISPATCHABLE_HANDLE or VK_DEFINE_HANDLE - //drop - string createInfo = var.type.alias.name + "CreateInfo"; - id structObj = (id) Hash_Find (available_types, createInfo); - if (structObj) { - [structObj addToQueue]; - } else { - //printf(" b:%s\n", var.type.alias.name); - } - } else { - print_type (type); - printf("%s c:%s:%s\n", var.name, var.type.alias.name, pr_type_name[alias.type]); - } - } else if (alias.meta == ty_basic) { - //drop - //printf(" d:%s:%s\n", var.type.alias.name, pr_type_name[alias.type]); - } else if (alias.meta == ty_struct) { - string tag = str_mid(alias.strct.tag, 4); - id structObj = (id) Hash_Find (available_types, tag); - if (structObj) { - [structObj addToQueue]; - } - } else { - printf(" d:%s:%s\n", var.type.alias.name, ty_meta_name[alias.meta]); - } - } else if (var.type.meta == ty_basic && var.type.type == ev_pointer) { - qfot_type_t *type = var.type.fldptr.aux_type; - if (type.meta == ty_struct || type.meta == ty_union) { - printf("%s f\n", var.name); - } else if (type.meta == ty_alias) { - printf("%s --- %s\n", var.name, type.alias.name); - id obj = (id) Hash_Find (available_types, type.alias.name); - if (obj && [obj class] == [Struct class]) { - [obj forEachFieldCall:struct_func]; - } - } else if (type.meta == ty_basic && type.type == ev_void) { - //drop - } else { - printf("%s g\n", var.name); - print_type (var.type); - } - } else { - //drop - //printf(" %s:%s:%s\n", var.name, ty_meta_name[var.type.meta], pr_type_name[var.type.type]); - } + Type *type = [Type findType:var.type]; + [type addToQueue]; } void @@ -188,30 +98,14 @@ scan_types (void) for (type = encodings.types; ((int *)type - (int *) encodings.types) < encodings.size; type = next_type (type)) { - if (!type.size - || (type.meta != ty_enum - && type.meta != ty_struct - && type.meta != ty_union)) { - continue; + if (type.size) { + string tag = str_mid(type.strct.tag, 4); + Type *avail_type = [Type fromType: type]; + if (avail_type) { + Hash_Add (available_types, avail_type); + } } - string tag = str_mid(type.strct.tag, 4); - switch (type.meta) { - case ty_enum: - Hash_Add (available_types, [[Enum alloc] initWithType: type]); - //printf ("+ enum %s\n", tag); - break; - case ty_struct: - case ty_union: - Hash_Add (available_types, [[Struct alloc] initWithType: type]); - //printf ("+ struct %s\n", tag); - break; - case ty_basic: - case ty_array: - case ty_class: - case ty_alias: - break; - } - } + } } static string @@ -226,9 +120,33 @@ get_object_key (void *obj, void *unused) return [(id)obj name]; } +void +usage (string name) +{ + printf ("%s [struct|enum] [output file]\n", name); +} + int main(int argc, string *argv) { + int do_struct = 0; + int do_enum = 0; + + if (argc != 3) { + usage (argv[0]); + return 1; + } + switch (argv[1]) { + case "struct": + do_struct = 1; + break; + case "enum": + do_enum = 1; + break; + default: + usage (argv[0]); + return 1; + } encodings = PR_FindGlobal (".type_encodings"); if (!encodings) { printf ("Can't find encodings\n"); @@ -243,6 +161,8 @@ main(int argc, string *argv) for (int i = 0; i < sizeof (search_names) / sizeof (search_names[0]); i++) { id obj = (id) Hash_Find (available_types, search_names[i]); + obj = [obj resolveType]; + printf("obj: %d %s\n", obj, class_get_class_name([obj class])); if (obj && [obj class] == [Struct class]) { [obj addToQueue]; } @@ -261,13 +181,17 @@ main(int argc, string *argv) printf ("vkgen %d %s\n", i, argv[i]); } - output_file = Qopen (argv[1], "wt"); + output_file = Qopen (argv[2], "wt"); for (int i = [output_types count]; i-- > 0; ) { id obj = [output_types objectAtIndex:i]; if ([obj name] == "VkStructureType") { continue; } - if ([obj class] == [Struct class]) { + printf("obj: %d %s\n", obj, class_get_class_name([obj class])); + if (do_struct && [obj class] != [Struct class]) { + continue; + } + if (do_enum && [obj class] != [Enum class]) { continue; } [obj writeTable]; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index fa5193b11..939f9094e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -15,6 +15,16 @@ return str_mid(type.strct.tag, 4); } +-(void) addToQueue +{ + string name = [self name]; + if (!Hash_Find (processed_types, name)) { + printf (" +%s\n", name); + Hash_Add (processed_types, (void *) name); + [queue addObject: self]; + } +} + -(void) forEachFieldCall: (varfunc) func { qfot_struct_t *strct =&type.strct; diff --git a/libs/video/renderer/vulkan/vkgen/vktype.h b/libs/video/renderer/vulkan/vkgen/vktype.h index a4ffb83c4..834bd1896 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.h +++ b/libs/video/renderer/vulkan/vkgen/vktype.h @@ -8,11 +8,16 @@ { qfot_type_t *type; } --initWithType: (qfot_type_t *) type; ++fromType: (qfot_type_t *) type; +/** \warning returned string is ephemeral +*/ +-(string) key; /** \warning returned string is ephemeral */ -(string) name; -(void) addToQueue; +-(Type *) resolveType; ++(Type *) findType: (qfot_type_t *) type; @end #endif//__renderer_vulkan_vkgen_vktype_h diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index b3a7bcf2c..c5a678c48 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -1,19 +1,72 @@ #include +#include "vkalias.h" +#include "vkenum.h" #include "vkgen.h" +#include "vkstruct.h" #include "vktype.h" @implementation Type +static hashtab_t *registered_types; + +static string get_type_key (void *type, void *unused) +{ + return ((Type *) type).type.encoding; +} + ++(void)initialize +{ + registered_types = Hash_NewTable (127, get_type_key, nil, nil); +} + -initWithType: (qfot_type_t *) type { if (!(self = [super init])) { return nil; } self.type = type; + Hash_Add (registered_types, self); return self; } ++(Type *) findType: (qfot_type_t *) type +{ + if (type.meta == ty_alias && !type.alias.name) { + type = type.alias.full_type; + } + return (Type *) Hash_Find (registered_types, type.encoding); +} + ++fromType: (qfot_type_t *) type +{ + if (type.size == 0) { + return nil; + } + switch (type.meta) { + case ty_basic: + case ty_array: + case ty_class: + return [[Type alloc] initWithType: type]; + case ty_enum: + return [[Enum alloc] initWithType: type]; + case ty_struct: + case ty_union: + return [[Struct alloc] initWithType: type]; + case ty_alias: + if (type.alias.name) { + return [[Alias alloc] initWithType: type]; + } + break; + } + return nil; +} + +-(string) key +{ + return type.encoding; +} + -(string) name { //FIXME extract alias name and return proper type name @@ -23,11 +76,14 @@ -(void) addToQueue { string name = [self name]; - //printf (" +%s\n", name); - if (!Hash_Find (processed_types, name)) { - Hash_Add (processed_types, (void *) name); - [queue addObject: self]; + if (type.meta == ty_basic && type.type == ev_pointer) { + [[Type findType: type.fldptr.aux_type] addToQueue]; } } +-(Type *) resolveType +{ + return self; +} + @end From f544a6f0b0401b0a7cff79988c9c152cc186c205 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jul 2020 12:39:11 +0900 Subject: [PATCH 1074/3664] [qfcc] Treat null method return type as id This prevents a segfault when the method's return type is undefined. --- tools/qfcc/source/method.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 244ae1513..1c461af85 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -89,6 +89,10 @@ new_method (type_t *ret_type, param_t *selector, param_t *opt_params) dstring_t *name = dstring_newstr (); dstring_t *types = dstring_newstr (); + if (!ret_type) { + ret_type = &type_id; + } + selector = reverse_params (selector); selector = append_params (selector, opt_params); cmd->next = selector; From 7a478b4ce7f7fdcb94ddac77ef471055b72b09da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jul 2020 14:38:44 +0900 Subject: [PATCH 1075/3664] [libr] Make PLItem more useful I can't say that I like what's there even now, but at least PLItem can be used without a lot of casting. Really, Ruamoko needs dictionary and string classes so reading a property list can build more natural object trees rather than this mess from when I knew too little. --- ruamoko/include/PropertyList.h | 44 ++++++++++++-------- ruamoko/lib/PropertyList.r | 75 ++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/ruamoko/include/PropertyList.h b/ruamoko/include/PropertyList.h index 3deb99a2b..c0c4bed35 100644 --- a/ruamoko/include/PropertyList.h +++ b/ruamoko/include/PropertyList.h @@ -4,7 +4,29 @@ #include #include -@interface PLItem: Object +@class PLItem; + +@protocol PLDictionary +- (int) count; +- (int) numKeys; +- (PLItem *) getObjectForKey:(string) key; +- (PLItem *) allKeys; +- addKey:(string) key value:(PLItem *) value; +@end + +@protocol PLArray +- (int) count; +- (int) numObjects; +- (PLItem *) getObjectAtIndex:(int) index; +- addObject:(PLItem *) object; +- insertObject:(PLItem *) object atIndex:(int) index; +@end + +@protocol PLString +- (string) string; +@end + +@interface PLItem: Object { plitem_t item; int own; @@ -22,34 +44,20 @@ - (pltype_t) type; @end -@interface PLDictionary: PLItem +@interface PLDictionary: PLItem + (PLDictionary *) new; - -- (int) count; -- (int) numKeys; -- (PLItem *) getObjectForKey:(string) key; -- (PLItem *) allKeys; -- addKey:(string) key value:(PLItem *) value; @end -@interface PLArray: PLItem +@interface PLArray: PLItem + (PLArray *) new; - -- (int) count; -- (int) numObjects; -- (PLItem *) getObjectAtIndex:(int) index; -- addObject:(PLItem *) object; -- insertObject:(PLItem *) object atIndex:(int) index; @end @interface PLData: PLItem + (PLData *) new:(void*) data size:(int) len; @end -@interface PLString: PLItem +@interface PLString: PLItem + (PLString *) new:(string) str; - -- (string) string; @end #endif//__ruamoko_PropertyList_h diff --git a/ruamoko/lib/PropertyList.r b/ruamoko/lib/PropertyList.r index b65edc85d..b8469e473 100644 --- a/ruamoko/lib/PropertyList.r +++ b/ruamoko/lib/PropertyList.r @@ -94,6 +94,81 @@ return PL_Type (item); } +- (int) count +{ + if ([self class] == [PLDictionary class]) { + return PL_D_NumKeys (item); + } else { + return PL_A_NumObjects (item); + } +} + +- (int) numKeys +{ + return PL_D_NumKeys (item); +} + +- (PLItem *) getObjectForKey:(string) key +{ + return [[PLItem itemClass: PL_ObjectForKey (item, key)] autorelease]; +} + +- (PLItem *) allKeys +{ + return [[PLItem itemClass: PL_D_AllKeys (item)] autorelease]; +} + +- addKey:(string) key value:(PLItem *) value +{ + if (!value.own) { + obj_error (self, 0, "add of unowned key/value to PLDictionary"); + return self; + } + PL_D_AddObject (item, key, value.item); + value.own = 0; + [value release]; + return self; +} + +- (int) numObjects +{ + return PL_A_NumObjects (item); +} + +- (PLItem *) getObjectAtIndex:(int) index +{ + return [[PLItem itemClass: PL_ObjectAtIndex (item, index)] autorelease]; +} + +- addObject:(PLItem *) object +{ + if (!object.own) { + obj_error (self, 0, "add of unowned object to PLArray"); + return self; + } + PL_A_AddObject (item, object.item); + object.own = 0; + [object release]; + return self; +} + +- insertObject:(PLItem *) object atIndex:(int) index +{ + if (!object.own) { + obj_error (self, 0, "add of unowned object to PLArray"); + return self; + } + PL_A_InsertObjectAtIndex (item, object.item, index); + object.own = 0; + [object release]; + return self; +} + +- (string) string +{ + return PL_String (item); +} + @end From 0945f30731ac47fa08088f20d5d3fcedc5420610 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jul 2020 14:59:56 +0900 Subject: [PATCH 1076/3664] [vulkan] Use a property list to drive code gen The property list specifies the base structures for which parser code will be generated (along with any structures and enums upon which those structures depend). It also defines option specialized parsers for better control. --- libs/video/renderer/Makemodule.am | 12 +- libs/video/renderer/vulkan/vkgen/vkalias.r | 54 ++++++++ libs/video/renderer/vulkan/vkgen/vkenum.r | 18 +++ libs/video/renderer/vulkan/vkgen/vkgen.r | 93 +++++++++---- libs/video/renderer/vulkan/vkgen/vkstruct.h | 4 +- libs/video/renderer/vulkan/vkgen/vkstruct.r | 141 ++++++++++++++++++-- libs/video/renderer/vulkan/vkgen/vktype.h | 7 + libs/video/renderer/vulkan/vkgen/vktype.r | 41 ++++++ libs/video/renderer/vulkan/vkparse.plist | 53 ++++++++ 9 files changed, 382 insertions(+), 41 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkparse.plist diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index d6ae44226..c41406663 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -223,18 +223,18 @@ libs/video/renderer/vulkan/vulkan_vid_common.c: $(vkparse_src) qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) vkparse_src = \ - libs/video/renderer/vulkan/vkenum.inc \ - libs/video/renderer/vulkan/vkstruct.inc + libs/video/renderer/vulkan/vkparse.inc +vkparse_plist = \ + $(srcdir)/libs/video/renderer/vulkan/vkparse.plist V_VKGEN = $(V_VKGEN_@AM_V@) V_VKGEN_ = $(V_VKGEN_@AM_DEFAULT_V@) V_VKGEN_0 = @echo " VKGEN " $@; V_VKGEN_1 = -libs/video/renderer/vulkan/vkenum.inc: $(vkgen) $(qwaq_curses) - $(V_VKGEN)$(qwaq_curses) $(vkgen) -- enum $@ -libs/video/renderer/vulkan/vkstruct.inc: $(vkgen) $(qwaq_curses) - $(V_VKGEN)$(qwaq_curses) $(vkgen) -- struct $@ +libs/video/renderer/vulkan/vkparse.inc: $(vkgen) $(qwaq_curses) $(vkparse_plist) + $(V_VKGEN)$(qwaq_curses) $(vkgen) -- $(vkparse_plist) $@.t &&\ + $(am__mv) $@.t $@ CLEANFILES += \ libs/video/renderer/glsl/*.vc \ diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index f37396097..6228ac230 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -49,4 +49,58 @@ } } } + +-(string) parseType +{ + Type *alias = [Type findType:type.alias.full_type]; + string name = [self name]; + + if ([alias name] == "VkFlags") { + if (str_mid (name, -5) == "Flags") { + string tag = str_mid (name, 0, -1) + "Bits"; + id enumObj = [(id) Hash_Find (available_types, tag) resolveType]; + return [enumObj parseType]; + } + } + if (name == "uint32_t") { + return "QFString"; + } + return [alias parseType]; +} + +-(string) parseFunc +{ + Type *alias = [Type findType:type.alias.full_type]; + string name = [self name]; + + if ([alias name] == "VkFlags") { + if (str_mid (name, -5) == "Flags") { + string tag = str_mid (name, 0, -1) + "Bits"; + id enumObj = [(id) Hash_Find (available_types, tag) resolveType]; + return [enumObj parseFunc]; + } + } + if (name == "uint32_t") { + return "parse_uint32_t"; + } + return [alias parseFunc]; +} + +-(string) parseData +{ + Type *alias = [Type findType:type.alias.full_type]; + string name = [self name]; + + if ([alias name] == "VkFlags") { + if (str_mid (name, -5) == "Flags") { + string tag = str_mid (name, 0, -1) + "Bits"; + id enumObj = [(id) Hash_Find (available_types, tag) resolveType]; + return [enumObj parseData]; + } + } + if (name == "uint32_t") { + return "0"; + } + return [alias parseData]; +} @end diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 10a476432..768e4b8d4 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -82,4 +82,22 @@ fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); } + +-(string) parseType +{ + return "QFString"; +} + +-(string) parseFunc +{ + if (str_mid([self name], -8) == "FlagBits") { + return "parse_flags"; + } + return "parse_enum"; +} + +-(string) parseData +{ + return [self name] + "_values"; +} @end diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 183ba591b..7744d0cdc 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -4,11 +4,28 @@ #include #include #include +#include +#include #include "vkgen.h" #include "vkstruct.h" #include "vkenum.h" +static AutoreleasePool *autorelease_pool; +static void +arp_start (void) +{ + autorelease_pool = [[AutoreleasePool alloc] init]; +} + +static void +arp_end (void) +{ + [autorelease_pool release]; + autorelease_pool = nil; +} + + void printf (string fmt, ...) = #0; void fprintf (QFile file, string format, ...) @@ -16,11 +33,6 @@ void fprintf (QFile file, string format, ...) Qputs (file, vsprintf (format, va_copy (@args))); } -string search_names[] = { - "VkGraphicsPipelineCreateInfo", - "VkComputePipelineCreateInfo", -}; -#define numsearch (sizeof (search_names) / sizeof (search_names[0])) hashtab_t *available_types; hashtab_t *processed_types; Array *queue; @@ -123,7 +135,7 @@ get_object_key (void *obj, void *unused) void usage (string name) { - printf ("%s [struct|enum] [output file]\n", name); + printf ("%s [plist file] [output file]\n", name); } int @@ -131,36 +143,51 @@ main(int argc, string *argv) { int do_struct = 0; int do_enum = 0; + string plist_filename; + QFile plist_file; + PLItem *plist; + PLItem *search; + PLItem *parse; + + arp_start (); if (argc != 3) { usage (argv[0]); return 1; } - switch (argv[1]) { - case "struct": - do_struct = 1; - break; - case "enum": - do_enum = 1; - break; - default: - usage (argv[0]); - return 1; + plist_filename = argv[1]; + plist_file = Qopen (plist_filename, "rt"); + if (!plist_file) { + printf ("could not open property list file: %s\n", plist_filename); + return 1; } + plist = [[PLItem fromFile: plist_file] retain]; + if (!plist) { + printf ("error parsing: %s\n", plist_filename); + return 1; + } + Qclose (plist_file); + if ([plist class] != [PLDictionary class]) { + printf ("%s not a dictionary\n", plist_filename); + } + search = [[plist getObjectForKey: "search"] retain]; + parse = [[plist getObjectForKey: "parse"] retain]; + encodings = PR_FindGlobal (".type_encodings"); if (!encodings) { printf ("Can't find encodings\n"); return 1; } - queue = [[Array alloc] init]; - output_types = [[Array alloc] init]; + queue = [[Array array] retain]; + output_types = [[Array array] retain]; available_types = Hash_NewTable (127, get_object_key, nil, nil); processed_types = Hash_NewTable (127, get_string_key, nil, nil); scan_types (); - for (int i = 0; - i < sizeof (search_names) / sizeof (search_names[0]); i++) { - id obj = (id) Hash_Find (available_types, search_names[i]); + for (int i = [search numObjects]; i-- > 0; ) { + PLString *str = (PLString *) [search getObjectAtIndex:i]; + string search_name = [str string]; + id obj = (id) Hash_Find (available_types, search_name); obj = [obj resolveType]; printf("obj: %d %s\n", obj, class_get_class_name([obj class])); if (obj && [obj class] == [Struct class]) { @@ -181,20 +208,34 @@ main(int argc, string *argv) printf ("vkgen %d %s\n", i, argv[i]); } + arp_end (); + output_file = Qopen (argv[2], "wt"); for (int i = [output_types count]; i-- > 0; ) { id obj = [output_types objectAtIndex:i]; if ([obj name] == "VkStructureType") { continue; } - printf("obj: %d %s\n", obj, class_get_class_name([obj class])); - if (do_struct && [obj class] != [Struct class]) { - continue; - } - if (do_enum && [obj class] != [Enum class]) { + if ([obj class] != [Enum class]) { continue; } + + arp_start (); [obj writeTable]; + arp_end (); + } + for (int i = [output_types count]; i-- > 0; ) { + id obj = [output_types objectAtIndex:i]; + if ([obj name] == "VkStructureType") { + continue; + } + if ([obj class] != [Struct class]) { + continue; + } + + arp_start (); + [obj writeTable:parse]; + arp_end (); } Qclose (output_file); return 0; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index a8a0df7e9..246d23070 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -6,11 +6,13 @@ #include "vkgen.h" #include "vktype.h" +@class PLItem; + @interface Struct: Type { } -(void) forEachFieldCall: (varfunc) func; --(void) writeTable; +-(void) writeTable: (PLItem *) parse; @end #endif//__renderer_vulkan_vkgen_vkstruct_h diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 939f9094e..ff364202b 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -4,6 +4,7 @@ #include #include #include +#include #include "vkgen.h" #include "vkstruct.h" @@ -34,20 +35,144 @@ } } --(void) writeTable +-(qfot_var_t *)findField:(string) fieldName { - fprintf (output_file, "structfld_t %s_fields[] = {\n", [self name]); for (int i = 0; i < type.strct.num_fields; i++) { qfot_var_t *var = &type.strct.fields[i]; - if (var.name == "sType" || var.name == "pNext") { - continue; + if (var.name == fieldName) { + return var; + } + } + return nil; +} + +-(void) writeTable: (PLItem *) parse +{ + PLItem *field_dict = [parse getObjectForKey:[self name]]; + PLItem *field_defs = [field_dict allKeys]; + Type *field_type; + + if (field_defs) { + PLItem *field_def; + qfot_var_t *field; + + for (int i = [field_defs count]; i-- > 0; ) { + string field_name = [[field_defs getObjectAtIndex:i] string]; + field_def = [field_dict getObjectForKey:field_name]; + PLItem *type_desc = [field_def getObjectForKey:"type"]; + string type_record; + string type_type; + string size_field = nil; + string value_field = nil; + + if (!type_desc) { + continue; + } + type_record = [[type_desc getObjectAtIndex:0] string]; + type_type = [[type_desc getObjectAtIndex:1] string]; + + field_type = [[Type lookup: type_type] dereference]; + fprintf (output_file, "static parse_%s_t parse_%s_%s_data = {\n", + type_record, [self name], field_name); + fprintf (output_file, "\tparse_%s,\n", type_type); + if (type_record == "single") { + value_field = [[field_def getObjectForKey:"value"] string]; + fprintf (output_file, "\tfield_offset (%s, %s),\n", + [self name], value_field); + } else { + value_field = [[field_def getObjectForKey:"values"] string]; + size_field = [[field_def getObjectForKey:"size"] string]; + fprintf (output_file, "\tfield_offset (%s, %s),\n", + [self name], value_field); + if (size_field) { + fprintf (output_file, "\tfield_offset (%s, %s),\n", + [self name], size_field); + } else { + fprintf (output_file, "\t-1,\n"); + } + } + fprintf (output_file, "};\n"); + } + } + fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self name]); + if (field_defs) { + PLItem *field_def; + qfot_var_t *field; + + for (int i = [field_defs count]; i-- > 0; ) { + string field_name = [[field_defs getObjectAtIndex:i] string]; + field_def = [field_dict getObjectForKey:field_name]; + if ([field_def string] == "auto") { + field = [self findField:field_name]; + if (!field) { + continue; + } + field_type = [Type findType: field.type]; + fprintf (output_file, + "\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n", + field_name, [self name], field_name, + [field_type parseType], [field_type parseFunc], + [field_type parseData]); + } else { + PLItem *type_desc = [field_def getObjectForKey:"type"]; + string type_record; + string type_type; + string parseType; + + type_record = [[type_desc getObjectAtIndex:0] string]; + type_type = [[type_desc getObjectAtIndex:1] string]; + + field_type = [[Type lookup: type_type] dereference]; + if (type_record == "single") { + parseType = [field_type parseType]; + } else { + parseType = "QFArray"; + } + fprintf (output_file, + "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", + field_name, parseType, type_record, + [self name], field_name); + } + } + } else { + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *field = &type.strct.fields[i]; + if (field.name == "sType" || field.name == "pNext") { + continue; + } + field_type = [Type findType: field.type]; + fprintf (output_file, + "\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n", + field.name, [self name], field.name, + [field_type parseType], [field_type parseFunc], + [field_type parseData]); } - string type_name = var.type.encoding; - fprintf (output_file, - "\t{\"%s\", field_offset (%s, %s), %s, %s}, // %s\n", - var.name, [self name], var.name, "0", "0", type_name); } fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); + + fprintf (output_file, "static int parse_%s (const plfield_t *field," + " const plitem_t *item, void *data, plitem_t *messages)\n", + [self name]); + fprintf (output_file, "{\n"); + fprintf (output_file, + "\treturn PL_ParseDictionary (%s_fields, item, data, messages);\n", + [self name]); + fprintf (output_file, "}\n"); +} + +-(string) parseType +{ + return "QFDictionary"; +} + +-(string) parseFunc +{ + return "fix me"; +} + +-(string) parseData +{ + return "0"; } @end diff --git a/libs/video/renderer/vulkan/vkgen/vktype.h b/libs/video/renderer/vulkan/vkgen/vktype.h index 834bd1896..fc5a53c84 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.h +++ b/libs/video/renderer/vulkan/vkgen/vktype.h @@ -18,6 +18,13 @@ -(void) addToQueue; -(Type *) resolveType; +(Type *) findType: (qfot_type_t *) type; ++(Type *) lookup: (string) name; +-(string) parseType; +-(string) parseFunc; +-(string) parseData; + +-(int) isPointer; +-(Type *) dereference; @end #endif//__renderer_vulkan_vkgen_vktype_h diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index c5a678c48..83373d47a 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -38,6 +38,11 @@ static string get_type_key (void *type, void *unused) return (Type *) Hash_Find (registered_types, type.encoding); } ++(Type *) lookup: (string) name +{ + return (Type *) Hash_Find (available_types, name); +} + +fromType: (qfot_type_t *) type { if (type.size == 0) { @@ -86,4 +91,40 @@ static string get_type_key (void *type, void *unused) return self; } +-(string) parseType +{ + return "no parse"; +} + +-(string) parseFunc +{ + return "0"; +} + +-(string) parseData +{ + return "0"; +} + +-(int) isPointer +{ + if ((type.meta == ty_basic || type.meta == ty_alias) + && type.type == ev_pointer) { + return 1; + } + return 0; +} + +-(Type *) dereference +{ + qfot_type_t *t = type; + if (t.meta == ty_alias) { + t = type.alias.full_type; + } + if (t.meta == ty_basic && t.type == ev_pointer) { + t = type.fldptr.aux_type; + } + return [Type findType:t]; +} + @end diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist new file mode 100644 index 000000000..3aae7c9c2 --- /dev/null +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -0,0 +1,53 @@ +{ + search = ( + VkRenderPassCreateInfo + ); + parse = { + VkRenderPassCreateInfo = { + flags = auto; + attachments = { + type = (array, VkAttachmentDescription); + size = attachmentCount; + values = pAttachments; + }; + subpasses = { + type = (array, VkSubpassDescription); + size = subpassCount; + values = pSubpasses; + }; + dependencies = { + type = (array, VkSubpassDependency); + size = dependencyCount; + values = pDependencies; + }; + }; + VkSubpassDescription = { + flags = auto; + pipelineBindPoint = auto; + inputAttachments = { + type = (array, VkAttachmentReference); + size = inputAttachmentCount; + values = pInputAttachments; + }; + colorAttachments = { + type = (array, VkAttachmentReference); + size = colorAttachmentCount; + values = pColorAttachments; + }; + resolveAttachments = { + type = (array, VkAttachmentReference); + values = pResolveAttachments; + matchSize = colorAttachments; + }; + depthStencilAttachment = { + type = (single, VkAttachmentReference); + value = pDepthStencilAttachment; + }; + preserveAttachments = { + type = (array, uint32_t); + size = preserveAttachmentCount; + values = pPreserveAttachments; + }; + } + } +} From c6a8829a52ae878466b9ce21ed2b4ea492d203d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Jul 2020 12:05:34 +0900 Subject: [PATCH 1077/3664] [util] Add code to parse a plist array to an array --- include/QF/qfplist.h | 10 +++++++++ libs/util/qfplist.c | 49 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 5d719b840..089c04856 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -99,6 +99,14 @@ typedef struct plfield_s { void *data; ///< additional data for \a parser } plfield_t; +typedef struct plelement_s { + pltype_t type; ///< the required type of the array elements + size_t stride; ///< the size of each element + void *(*alloc) (size_t size); ///< allocator for array memory + plparser_t parser; ///< custom parser function + void *data; ///< additional data for \a parser +} plelement_t; + /** Create an in-memory representation of the contents of a property list. \param string the saved plist, as read from a file. @@ -316,6 +324,8 @@ void PL_Free (plitem_t *item); */ int PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, plitem_t *messages); +int PL_ParseArray (const plfield_t *fields, const plitem_t *dict, + void *data, plitem_t *messages); ///@} diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 35f136374..6949d3e53 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1130,8 +1130,7 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, void **list, **l; dictkey_t *current; int result; - int (*parser) (const plfield_t *, const plitem_t *, void *, - plitem_t *); + plparser_t parser; if (dict->type != QFDictionary) { pl_message (messages, dict, "error: not a dictionary object"); @@ -1177,3 +1176,49 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, free (list); return result; } + +VISIBLE int +PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, + plitem_t *messages) +{ + int result; + plparser_t parser; + plarray_t *plarray = (plarray_t *) array->data; + plelement_t *element = (plelement_t *) field->data; + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr; + plfield_t f = { 0, 0, element->type, element->parser, element->data }; + + if (array->type != QFArray) { + pl_message (messages, array, "error: not an array object"); + return 0; + } + if (field->parser) { + parser = field->parser; + } else { + parser = pl_default_parser; + } + + arr = DARRAY_ALLOCFIXED (arr_t, plarray->numvals * element->stride, + element->alloc); + + for (int i = 0; i < plarray->numvals; i++) { + plitem_t *item = plarray->values[i]; + void *eledata = &arr->a[i * element->stride]; + + if (item->type != element->type) { + pl_message (messages, item, + "error: element %d is the wrong type" + " Got %s, expected %s", i, + pl_types[element->type], + pl_types[item->type]); + result = 0; + } else { + if (!parser (&f, item, eledata, messages)) { + result = 0; + } + } + } + *(arr_t **) data = arr; + return result; +} From 79177e96e8ac9057fd3179fc569e9216ea01b942 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Jul 2020 15:42:49 +0900 Subject: [PATCH 1078/3664] [vulkan] Start work on scripted pipeline Nothing is actually done yet other than parsing the built-in property list to property list items (the actual parser is just a skeleton), but everything compiles --- libs/video/renderer/Makemodule.am | 19 +- libs/video/renderer/vulkan/qfpipeline.plist | 71 +++++++ libs/video/renderer/vulkan/vkparse.c | 186 ++++++++++++++++++ libs/video/renderer/vulkan/vkparse.h | 10 + libs/video/renderer/vulkan/vkparse.plist | 22 +-- .../video/renderer/vulkan/vulkan_vid_common.c | 18 ++ 6 files changed, 303 insertions(+), 23 deletions(-) create mode 100644 libs/video/renderer/vulkan/qfpipeline.plist create mode 100644 libs/video/renderer/vulkan/vkparse.c create mode 100644 libs/video/renderer/vulkan/vkparse.h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index c41406663..0b68d0b41 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -73,12 +73,13 @@ libs_video_renderer_vid_render_gl_la_SOURCES=\ shader_src= libs/video/renderer/glsl/quakeforge.glsl shader_gen= libs/video/renderer/glsl/quakeforge.slc -BUILT_SOURCES += $(shader_gen) - -SUFFICES=.frag .vert .fc .vc .slc .glsl +SUFFICES=.frag .vert .fc .vc .slc .glsl .plist .plc .glsl.slc: sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ +.plist.plc: + sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ + video_renderer_glsl_libs= \ libs/models/libmodels_glsl.la libs_video_renderer_vid_render_glsl_la_LDFLAGS= $(plugin_ldflags) @@ -196,6 +197,9 @@ libs_video_renderer_vid_render_sw32_la_SOURCES=\ libs/video/renderer/sw32/sw32_rsurf.c \ libs/video/renderer/sw32/vid_common_sw32.c +pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist +pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc + vulkan_libs = libs_video_renderer_vid_render_vulkan_la_LDFLAGS= $(plugin_ldflags) libs_video_renderer_vid_render_vulkan_la_LIBADD= $(vulkan_libs) @@ -216,10 +220,14 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/swapchain.c \ libs/video/renderer/vulkan/util.c \ libs/video/renderer/vulkan/util.h \ + libs/video/renderer/vulkan/vkparse.c \ libs/video/renderer/vulkan/vulkan_draw.c \ libs/video/renderer/vulkan/vulkan_vid_common.c -libs/video/renderer/vulkan/vulkan_vid_common.c: $(vkparse_src) +libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vkparse_src) + +libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(pipeline_gen) + qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) vkparse_src = \ @@ -240,4 +248,7 @@ CLEANFILES += \ libs/video/renderer/glsl/*.vc \ libs/video/renderer/glsl/*.fc \ libs/video/renderer/glsl/*.slc \ + libs/video/renderer/vulkan/*.plc \ $(vkparse_src) + +BUILT_SOURCES += $(shader_gen) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist new file mode 100644 index 000000000..059405ceb --- /dev/null +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -0,0 +1,71 @@ +{ + renderpass = { + attachments = ( + { + flags = 0; + format = $swapchain.format; + samples = $msaaSamples; + loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + storeOp = VK_ATTACHMENT_STORE_OP_STORE; + stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + }, + { + flags = 0; + format = $swapchain.format; + samples = $msaaSamples; + loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + storeOp = VK_ATTACHMENT_STORE_OP_STORE; + stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + }, + { + flags = 0; + format = VK_FORMAT_D32_SFLOAT; + samples = VK_SAMPLE_COUNT_1_BIT; + loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + storeOp = VK_ATTACHMENT_STORE_OP_STORE; + stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + }, + ); + subpasses = ( + { + inputAttachments = ( + { + attachmeht = 0; + layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + ); + resolveAttachments = ( + { + attachmeht = 2; + layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + ); + depthStencilAttachment = { + attachmeht = 1; + layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + }; + preserveAttachments = (); + }, + ); + dependencies = ( + { + srcSubpass = VK_SUBPASS_EXTERNAL; + dstSubpass = 0; + srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + srcAccessMask = 0; + dstAccessMask = "VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT"; + dependencyFlags = 0; + } + ); + } +} diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c new file mode 100644 index 000000000..51df46a6e --- /dev/null +++ b/libs/video/renderer/vulkan/vkparse.c @@ -0,0 +1,186 @@ +/* + vkparse.c + + Parser for scripted vulkan structs + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/mathlib.h" +#include "QF/qargs.h" +#include "QF/qfplist.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/renderpass.h" +#include "QF/Vulkan/swapchain.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" +#include "vkparse.h" + +typedef struct enumval_s { + const char *name; + int value; +} enumval_t; + +typedef struct parse_single_s { + plparser_t parser; + size_t value_offset; +} parse_single_t; + +typedef struct parse_array_s { + plparser_t parser; + size_t size_offset; + size_t value_offset; +} parse_array_t; + +static int parse_uint32_t (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages) +{ + return 0; +} + +static int parse_enum (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages) +{ + return 0; +} + +static int parse_flags (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages) +{ + return 0; +} + +static int parse_single (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages) +{ + return 0; +} + +static int parse_array (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages) +{ + return 0; +} + +#include "libs/video/renderer/vulkan/vkparse.inc" + +typedef struct qfv_renderpass_s { + qfv_attachmentdescription_t *attachments; + qfv_subpassparametersset_t *subpasses; + qfv_subpassdependency_t *dependencies; +} qfv_renderpass_t; + +static plelement_t parse_qfv_renderpass_attachments_data = { + QFDictionary, + sizeof (VkAttachmentDescription), + malloc, + parse_VkAttachmentDescription, + 0, +}; + +static plelement_t parse_qfv_renderpass_subpasses_data = { + QFDictionary, + sizeof (VkSubpassDescription), + malloc, + parse_VkSubpassDescription, + 0, +}; + +static plelement_t parse_qfv_renderpass_dependencies_data = { + QFDictionary, + sizeof (VkSubpassDependency), + malloc, + parse_VkSubpassDependency, + 0, +}; + +static plfield_t renderpass_fields[] = { + { "attachments", field_offset (qfv_renderpass_t, attachments), QFArray, + parse_array, &parse_qfv_renderpass_attachments_data }, + { "subpasses", field_offset (qfv_renderpass_t, subpasses), QFArray, + parse_array, &parse_qfv_renderpass_subpasses_data }, + { "dependencies", field_offset (qfv_renderpass_t, dependencies), QFArray, + parse_array, &parse_qfv_renderpass_dependencies_data }, + {} +}; + +VkRenderPass +QFV_ParseRenderPass (qfv_device_t *device, plitem_t *plist) +{ + qfv_renderpass_t renderpass_data = {}; + plitem_t *messages = PL_NewArray (); + VkRenderPass renderpass; + + if (!PL_ParseDictionary (renderpass_fields, plist, + &renderpass_data, messages)) { + for (int i = 0; i < PL_A_NumObjects (messages); i++) { + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + } + return 0; + } + PL_Free (messages); + renderpass = QFV_CreateRenderPass (device, + renderpass_data.attachments, + renderpass_data.subpasses, + renderpass_data.dependencies); + + free (renderpass_data.attachments); + for (size_t i = 0; i < renderpass_data.subpasses->size; i++) { + free ((void *) renderpass_data.subpasses->a[i].pInputAttachments); + free ((void *) renderpass_data.subpasses->a[i].pColorAttachments); + free ((void *) renderpass_data.subpasses->a[i].pResolveAttachments); + free ((void *) renderpass_data.subpasses->a[i].pDepthStencilAttachment); + free ((void *) renderpass_data.subpasses->a[i].pPreserveAttachments); + } + free (renderpass_data.subpasses); + free (renderpass_data.dependencies); + return renderpass; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h new file mode 100644 index 000000000..0d14eecbe --- /dev/null +++ b/libs/video/renderer/vulkan/vkparse.h @@ -0,0 +1,10 @@ +#ifndef __vkparse_h +#define __vkparse_h + +#include "QF/Vulkan/renderpass.h" + +VkRenderPass +QFV_ParseRenderPass (qfv_device_t *device, plitem_t *plist); + + +#endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 3aae7c9c2..017025426 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -1,26 +1,10 @@ { search = ( - VkRenderPassCreateInfo + VkAttachmentDescription, + VkSubpassDescription, + VkSubpassDependency, ); parse = { - VkRenderPassCreateInfo = { - flags = auto; - attachments = { - type = (array, VkAttachmentDescription); - size = attachmentCount; - values = pAttachments; - }; - subpasses = { - type = (array, VkSubpassDescription); - size = subpassCount; - values = pSubpasses; - }; - dependencies = { - type = (array, VkSubpassDependency); - size = dependencyCount; - values = pDependencies; - }; - }; VkSubpassDescription = { flags = auto; pipelineBindPoint = auto; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 68dd2bbe8..6f0ba9892 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -44,6 +44,7 @@ #include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" +#include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/va.h" @@ -63,6 +64,10 @@ #include "util.h" +static const char quakeforge_pipeline[] = +#include "libs/video/renderer/vulkan/qfpipeline.plc" +; + cvar_t *vulkan_presentation_mode; static void @@ -232,9 +237,22 @@ static qfv_pipelinestagepair_t imageLayoutTransitionStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }, }; +static plitem_t * +qfv_load_pipeline (void) +{ + return PL_GetPropertyList (quakeforge_pipeline); +} + void Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) { + plitem_t *item = qfv_load_pipeline (); + + if (!item || !(item = PL_ObjectForKey (item, "renderpass"))) { + Sys_Printf ("error loading pipeline\n"); + } else { + Sys_Printf ("Found renderer def\n"); + } qfv_device_t *device = ctx->device; VkDevice dev = device->dev; qfv_devfuncs_t *df = device->funcs; From 8290e3800f684aac2abeb5e253978804dcadfff2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Jul 2020 15:44:37 +0900 Subject: [PATCH 1079/3664] [qwaq] Ensure main thread return code gets returned Needed for catching vkgen errors during the build. --- ruamoko/qwaq/builtins/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index c4c426166..0a4faf28b 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -480,6 +480,7 @@ main (int argc, char **argv) } } pthread_join (thread_data.a[main_ind]->thread_id, 0); + ret = thread_data.a[main_ind]->return_code; } Sys_Shutdown (); From 72f583f16f3c2a3b997bc73c323bea672ddbf65b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Jul 2020 21:12:05 +0900 Subject: [PATCH 1080/3664] [util] Fix some plist object parsing errors Forgot to break after finding the field when parsing a dictionary object, and use the correct parser for array objects. --- libs/util/qfplist.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 6949d3e53..26476e44d 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1165,6 +1165,7 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, result = 0; } } + break; } } if (!f->name) { @@ -1193,8 +1194,8 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, pl_message (messages, array, "error: not an array object"); return 0; } - if (field->parser) { - parser = field->parser; + if (f.parser) { + parser = f.parser; } else { parser = pl_default_parser; } From ef33adac568af526f66612b42335f62a33c8731c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Jul 2020 22:02:26 +0900 Subject: [PATCH 1081/3664] [util] Make PL_String const correct --- include/QF/qfplist.h | 2 +- libs/util/qfplist.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 089c04856..43eef595b 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -147,7 +147,7 @@ int PL_Line (plitem_t *item) __attribute__((pure)); \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ -const char *PL_String (plitem_t *string) __attribute__((pure)); +const char *PL_String (const plitem_t *string) __attribute__((pure)); /** Retrieve a value from a dictionary object. diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 26476e44d..650be7741 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -232,7 +232,7 @@ PL_Free (plitem_t *item) } VISIBLE const char * -PL_String (plitem_t *string) +PL_String (const plitem_t *string) { if (string->type != QFString) return NULL; From 26cd93f78877feb222349746a95de8b22994095b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Jul 2020 22:04:33 +0900 Subject: [PATCH 1082/3664] [util] Expose PL_Message It's far to useful elsewhere. --- include/QF/qfplist.h | 2 ++ libs/util/qfplist.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 43eef595b..011090818 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -326,6 +326,8 @@ int PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, plitem_t *messages); int PL_ParseArray (const plfield_t *fields, const plitem_t *dict, void *data, plitem_t *messages); +void __attribute__((format(printf,3,4))) +PL_Message (plitem_t *messages, const plitem_t *item, const char *fmt, ...); ///@} diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 650be7741..6d3ff018d 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1062,8 +1062,8 @@ PL_Line (plitem_t *item) return item->line; } -static void __attribute__((format(printf,3,4))) -pl_message (plitem_t *messages, const plitem_t *item, const char *fmt, ...) +VISIBLE void +PL_Message (plitem_t *messages, const plitem_t *item, const char *fmt, ...) { va_list args; dstring_t *string; @@ -1119,7 +1119,7 @@ pl_default_parser (const plfield_t *field, const plitem_t *item, void *data, *(char **)data = (char *)item->data; return 1; } - pl_message (messages, 0, "invalid item type: %d", field->type); + PL_Message (messages, 0, "invalid item type: %d", field->type); return 0; } @@ -1133,7 +1133,7 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, plparser_t parser; if (dict->type != QFDictionary) { - pl_message (messages, dict, "error: not a dictionary object"); + PL_Message (messages, dict, "error: not a dictionary object"); return 0; } @@ -1155,7 +1155,7 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, parser = pl_default_parser; } if (item->type != f->type) { - pl_message (messages, item, "error: %s is the wrong type" + PL_Message (messages, item, "error: %s is the wrong type" " Got %s, expected %s",current->key, pl_types[f->type], pl_types[item->type]); @@ -1169,7 +1169,7 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, } } if (!f->name) { - pl_message (messages, dict, "error: unknown field %s", + PL_Message (messages, dict, "error: unknown field %s", current->key); result = 0; } @@ -1191,7 +1191,7 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, plfield_t f = { 0, 0, element->type, element->parser, element->data }; if (array->type != QFArray) { - pl_message (messages, array, "error: not an array object"); + PL_Message (messages, array, "error: not an array object"); return 0; } if (f.parser) { @@ -1208,7 +1208,7 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, void *eledata = &arr->a[i * element->stride]; if (item->type != element->type) { - pl_message (messages, item, + PL_Message (messages, item, "error: element %d is the wrong type" " Got %s, expected %s", i, pl_types[element->type], From 16c6818612a9690a221f4b80e0ecf2242bb54fee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Jul 2020 22:05:15 +0900 Subject: [PATCH 1083/3664] [util] Set parsed array size correctly The array has to be allocated using byte elements and thus the size of the array is the number of bytes, but it needs to be the actual number of elements in the array. Problem caused by not knowing the actual type (and C not having type variables anyway). --- libs/util/qfplist.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 6d3ff018d..ab24a9499 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1202,6 +1202,10 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, arr = DARRAY_ALLOCFIXED (arr_t, plarray->numvals * element->stride, element->alloc); + memset (arr->a, 0, arr->size); + // the array is allocated using bytes, but need the actual number of + // elements in the array + arr->size = arr->maxSize = plarray->numvals; for (int i = 0; i < plarray->numvals; i++) { plitem_t *item = plarray->values[i]; From 2b23e01d9af5f2cbc7ecc841e8ebbd633e81e6ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Jul 2020 00:22:47 +0900 Subject: [PATCH 1084/3664] [util] Make PL_Type and PL_Line const-correct --- include/QF/qfplist.h | 4 ++-- libs/util/qfplist.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 011090818..3fdfa7825 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -129,7 +129,7 @@ char *PL_WritePropertyList (plitem_t *pl); \param item The object \return the type of the object */ -pltype_t PL_Type (plitem_t *item) __attribute__((pure)); +pltype_t PL_Type (const plitem_t *item) __attribute__((pure)); /** Retrieve the line number of an object. @@ -137,7 +137,7 @@ pltype_t PL_Type (plitem_t *item) __attribute__((pure)); \return the line number on which the object began, or 0 if not from a string */ -int PL_Line (plitem_t *item) __attribute__((pure)); +int PL_Line (const plitem_t *item) __attribute__((pure)); /** Retrieve a string from a string object. diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index ab24a9499..2b96ecdf4 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1051,13 +1051,13 @@ PL_WritePropertyList (plitem_t *pl) } VISIBLE pltype_t -PL_Type (plitem_t *item) +PL_Type (const plitem_t *item) { return item->type; } VISIBLE int -PL_Line (plitem_t *item) +PL_Line (const plitem_t *item) { return item->line; } From 9f4f63796beba75470ac87d86f8686946c3b9890 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Jul 2020 00:23:09 +0900 Subject: [PATCH 1085/3664] [util] Fix some unitialized vars Not sure how they got past gcc. Maybe a bug in 9.3.0? --- libs/util/qfplist.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 2b96ecdf4..8eb7e867c 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1129,7 +1129,7 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, { void **list, **l; dictkey_t *current; - int result; + int result = 1; plparser_t parser; if (dict->type != QFDictionary) { @@ -1182,7 +1182,7 @@ VISIBLE int PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, plitem_t *messages) { - int result; + int result = 1; plparser_t parser; plarray_t *plarray = (plarray_t *) array->data; plelement_t *element = (plelement_t *) field->data; From 8184c546dbed052ad807ef79ba0f4b948454e09f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Jul 2020 00:24:41 +0900 Subject: [PATCH 1086/3664] [vulkan] Fix dereference for non-pointer aliases Fixes breakage for uint32_t for array/single handling. --- libs/video/renderer/vulkan/vkgen/vktype.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index 83373d47a..caa7ac057 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -118,7 +118,7 @@ static string get_type_key (void *type, void *unused) -(Type *) dereference { qfot_type_t *t = type; - if (t.meta == ty_alias) { + if (t.meta == ty_alias && t.type == ev_pointer) { t = type.alias.full_type; } if (t.meta == ty_basic && t.type == ev_pointer) { From f4c8d341e13162aa5b65c1fd5609332948bfe122 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Jul 2020 00:29:53 +0900 Subject: [PATCH 1087/3664] [vulkan] Implement most of the parser This gets renderpass parsing almost working (not hooked up, though). The missing bits are support for expressions for flags (namely support for the | operator) and references (eg $swapchain.format). However, this shows that the basic concept for the parser is working. --- libs/video/renderer/vulkan/vkgen/vkstruct.r | 2 + libs/video/renderer/vulkan/vkparse.c | 133 ++++++++++++++++++-- 2 files changed, 126 insertions(+), 9 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index ff364202b..dc6aa39d6 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -74,6 +74,8 @@ field_type = [[Type lookup: type_type] dereference]; fprintf (output_file, "static parse_%s_t parse_%s_%s_data = {\n", type_record, [self name], field_name); + fprintf (output_file, "\t%s,\n", [field_type parseType]); + fprintf (output_file, "\tsizeof (%s),\n", type_type); fprintf (output_file, "\tparse_%s,\n", type_type); if (type_record == "single") { value_field = [[field_def getObjectForKey:"value"] string]; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 51df46a6e..7fb137b29 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -70,44 +70,159 @@ typedef struct enumval_s { } enumval_t; typedef struct parse_single_s { + pltype_t type; + size_t stride; plparser_t parser; size_t value_offset; } parse_single_t; typedef struct parse_array_s { + pltype_t type; + size_t stride; plparser_t parser; - size_t size_offset; size_t value_offset; + size_t size_offset; } parse_array_t; +static int find_enum (const char *valstr, enumval_t *enumval, int *val) +{ + while (enumval->name && strcmp (enumval->name, valstr) != 0) { + enumval++; + } + if (enumval->name) { + *val = enumval->value; + return 1; + } + return 0; +} + static int parse_uint32_t (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages) { - return 0; + int ret = 1; + const char *valstr = PL_String (item); + //Sys_Printf ("parse_uint32_t: %s %zd %d %p %p: %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); + if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) { + *(uint32_t *) data = VK_SUBPASS_EXTERNAL; + } else { + char *end; + unsigned long val = strtoul (valstr, &end, 0); + if (*valstr && !*end && val <= 0xffffffff) { + *(uint32_t *) data = val; + } else if (val > 0xffffffff) { + PL_Message (messages, item, "%lu bigger than 32 bits", val); + ret = 0; + } else { + PL_Message (messages, item, "invalid char at %d in '%s'\n", + (int) (end - valstr), valstr); + ret = 0; + } + } + + return ret; } static int parse_enum (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages) { - return 0; + int ret = 1; + int val; + const char *valstr = PL_String (item); + __auto_type enumval = (enumval_t *) field->data; + //Sys_Printf ("parse_enum: %s %zd %d %p %p %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); + if (find_enum (valstr, enumval, &val)) { + *(int *) data = val; + } else { + PL_Message (messages, item, "invalid enum: %s", valstr); + ret = 0; + } + return ret; } static int parse_flags (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages) { - return 0; + int ret = 1; + int val; + const char *valstr = PL_String (item); + __auto_type enumval = (enumval_t *) field->data; + //Sys_Printf ("parse_flags: %s %zd %d %p %p %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); + if (find_enum (valstr, enumval, &val)) { + *(int *) data = val; + } else if (strcmp (valstr, "0") == 0) { + *(int *) data = 0; + } else { + PL_Message (messages, item, "invalid enum: %s", valstr); + ret = 0; + } + return ret; } static int parse_single (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages) { - return 0; + __auto_type single = (parse_single_t *) field->data; + void *flddata = (byte *)data + single->value_offset; + + //Sys_Printf ("parse_single: %s %zd %d %p %p\n", field->name, field->offset, + // field->type, field->parser, field->data); + + if (PL_Type (item) != single->type) { + PL_Message (messages, item, "error: wrong type"); + return 0; + } + + plfield_t f = { 0, 0, single->type, single->parser, 0 }; + void *value = calloc (1, single->stride); + if (!single->parser (&f, item, value, messages)) { + free (value); + return 0; + } + + *(void **) flddata = value; + return 1; } static int parse_array (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages) { - return 0; + __auto_type array = (parse_array_t *) field->data; + __auto_type value = (void **) ((byte *)data + array->value_offset); + __auto_type size = (uint32_t *) ((byte *)data + array->size_offset); + + plelement_t element = { + array->type, + array->stride, + malloc, + array->parser, + 0, + }; + plfield_t f = { 0, 0, 0, 0, &element }; + + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr; + + //Sys_Printf ("parse_array: %s %zd %d %p %p %p\n", + // field->name, field->offset, field->type, field->parser, + // field->data, data); + //Sys_Printf (" %d %zd %p %zd %zd\n", array->type, array->stride, + // array->parser, array->value_offset, array->size_offset); + if (!PL_ParseArray (&f, item, &arr, messages)) { + return 0; + } + *value = malloc (array->stride * arr->size); + memcpy (*value, arr->a, array->stride * arr->size); + if ((void *) size > data) { + *size = arr->size; + } + free (arr); + return 1; } #include "libs/video/renderer/vulkan/vkparse.inc" @@ -144,11 +259,11 @@ static plelement_t parse_qfv_renderpass_dependencies_data = { static plfield_t renderpass_fields[] = { { "attachments", field_offset (qfv_renderpass_t, attachments), QFArray, - parse_array, &parse_qfv_renderpass_attachments_data }, + PL_ParseArray, &parse_qfv_renderpass_attachments_data }, { "subpasses", field_offset (qfv_renderpass_t, subpasses), QFArray, - parse_array, &parse_qfv_renderpass_subpasses_data }, + PL_ParseArray, &parse_qfv_renderpass_subpasses_data }, { "dependencies", field_offset (qfv_renderpass_t, dependencies), QFArray, - parse_array, &parse_qfv_renderpass_dependencies_data }, + PL_ParseArray, &parse_qfv_renderpass_dependencies_data }, {} }; From 91ff15ca7c306eb4f0659f2befd2570fa7630c9d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Jul 2020 00:33:00 +0900 Subject: [PATCH 1088/3664] [vulkan] Correct some plist errors in the renderpass Typos and incorrect attachment array reference. --- libs/video/renderer/vulkan/qfpipeline.plist | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 059405ceb..1c594aee0 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -37,20 +37,20 @@ ); subpasses = ( { - inputAttachments = ( + colorAttachments = ( { - attachmeht = 0; + attachment = 0; layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } ); resolveAttachments = ( { - attachmeht = 2; + attachment = 2; layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } ); depthStencilAttachment = { - attachmeht = 1; + attachment = 1; layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; }; preserveAttachments = (); From 900728169e647b01877184eb512c8fe0416b371c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Jul 2020 01:20:02 +0900 Subject: [PATCH 1089/3664] [build] Support silent rules for sed --- libs/video/renderer/Makemodule.am | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 0b68d0b41..1077ef6ca 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -73,12 +73,19 @@ libs_video_renderer_vid_render_gl_la_SOURCES=\ shader_src= libs/video/renderer/glsl/quakeforge.glsl shader_gen= libs/video/renderer/glsl/quakeforge.slc +V_SED = $(V_SED_@AM_V@) +V_SED_ = $(V_SED_@AM_DEFAULT_V@) +V_SED_0 = @echo " SED " $@; +V_SED_1 = + SUFFICES=.frag .vert .fc .vc .slc .glsl .plist .plc .glsl.slc: - sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ + $(V_SED)sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\ + $(am__mv) $@.t $@ .plist.plc: - sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $< > $@ + $(V_SED)sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\ + $(am__mv) $@.t $@ video_renderer_glsl_libs= \ libs/models/libmodels_glsl.la @@ -249,6 +256,7 @@ CLEANFILES += \ libs/video/renderer/glsl/*.fc \ libs/video/renderer/glsl/*.slc \ libs/video/renderer/vulkan/*.plc \ + libs/video/renderer/vulkan/vkgen.sym \ $(vkparse_src) BUILT_SOURCES += $(shader_gen) From 3413947e0cc6d50fb103feda206cec15159f569d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Jul 2020 20:11:44 +0900 Subject: [PATCH 1090/3664] [qfmap] Update script.py from io_object_mu While not necessary for qf (at this stage), this brings in support for optionally not parsing strings and better utf-8 and wide char handling. --- tools/io_qfmap/script.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/io_qfmap/script.py b/tools/io_qfmap/script.py index 9e34934f9..fc030e3e5 100644 --- a/tools/io_qfmap/script.py +++ b/tools/io_qfmap/script.py @@ -25,10 +25,15 @@ class ScriptError(Exception): self.line = line class Script: - def __init__(self, filename, text, single="{}()':"): + def __init__(self, filename, text, single="{}()':", quotes=True): self.filename = filename + if text[0:3] == "\xef\xbb\xbf": + text = text[3:] + elif text[0] == u"\ufeff": + text = text[1:] self.text = text self.single = single + self.quotes = quotes self.pos = 0 self.line = 1 self.unget = False @@ -87,7 +92,7 @@ class Script: if not crossline: self.error("line is incomplete") return None - if self.text[self.pos] == "\"": + if self.quotes and self.text[self.pos] == "\"": self.pos += 1 start = self.pos if self.text[self.pos] == len(self.text): From 92aa94d776380513f1c8898aab8e3df2df78db73 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Aug 2020 11:30:53 +0900 Subject: [PATCH 1091/3664] [ruamoko] Fix incorrect clearing of dtables The problem was caused by passing the index into the dtables array to dtable_get which expects a handle. A handle is the ones-compliment negative of the index which means that handle 0 is invalid (but 0 was being passed... oops). Fixes the segfault when qw-client-x11 connects to a server. --- libs/ruamoko/rua_obj.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 7ecc8ef28..baa8fe73b 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -2192,7 +2192,10 @@ rua_obj_cleanup (progs_t *pr, void *data) } for (i = 0; i < probj->dtables._size; i++) { - dtable_t *dtable = dtable_get (probj, i); + /* dtable_get expects a handle, but a handle is the ones-compliment + * negative of the index. + */ + dtable_t *dtable = dtable_get (probj, ~i); if (!dtable->imp) { break; } From fdcdbefc05dbb0ad6e90523c6f6e21cf570fc84c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Aug 2020 13:07:21 +0900 Subject: [PATCH 1092/3664] [sizebuf] Add function to dump contents of a buffer The usual 8-bit hex + chars (with chars wrapped into 7-bits) with addresses block. --- include/QF/sizebuf.h | 1 + libs/util/sizebuf.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/QF/sizebuf.h b/include/QF/sizebuf.h index 08436b1b8..a6fc39411 100644 --- a/include/QF/sizebuf.h +++ b/include/QF/sizebuf.h @@ -50,6 +50,7 @@ void SZ_Clear (sizebuf_t *buf); void *SZ_GetSpace (sizebuf_t *buf, int length); void SZ_Write (sizebuf_t *buf, const void *data, int length); void SZ_Print (sizebuf_t *buf, const char *data); // strcats onto the sizebuf +void SZ_Dump (sizebuf_t *buf); ///@} diff --git a/libs/util/sizebuf.c b/libs/util/sizebuf.c index 757672367..785287d0c 100644 --- a/libs/util/sizebuf.c +++ b/libs/util/sizebuf.c @@ -99,3 +99,34 @@ SZ_Print (sizebuf_t *buf, const char *data) memcpy (SZ_GetSpace (buf, len), data, len); } + +VISIBLE void +SZ_Dump (sizebuf_t *buf) +{ + int i; + char chars[17], c; + + chars[16] = 0; + for (i = 0; i < buf->cursize; i++) { + if (i % 16 == 0) { + Sys_Printf ("%04x:", i); + } else if (i % 16 == 8) { + Sys_Printf (" "); + } + Sys_Printf (" %02x", buf->data[i]); + c = buf->data[i] & 0x7f; + if (c < ' ') { + c = '.'; + } + chars[i % 16] = c; + if (i % 16 == 15) { + Sys_Printf (" %s\n", chars); + } + } + i %= 16; + if (i) { + chars[i] = 0; + i = 16 - i; + Sys_Printf ("%*s %s\n", i * 3 + (i > 7), "", chars); + } +} From 09384eb70388b1113417d2df01f6e2b73ab644df Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Aug 2020 13:08:49 +0900 Subject: [PATCH 1093/3664] [netchan] Optionally dump the contents of packets --- libs/net/net_chan.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libs/net/net_chan.c b/libs/net/net_chan.c index 88f7ad08e..61f125117 100644 --- a/libs/net/net_chan.c +++ b/libs/net/net_chan.c @@ -257,12 +257,16 @@ Netchan_Transmit (netchan_t *chan, int length, byte *data) if (net_nochoke) chan->cleartime = *net_realtime; - if (showpackets->int_val & 1) + if (showpackets->int_val & 1) { Sys_Printf ("--> s=%i(%i) a=%i(%i) %-4i %i\n", chan->outgoing_sequence, send_reliable, chan->incoming_sequence, chan->incoming_reliable_sequence, send.cursize, chan->outgoing_sequence - chan->incoming_sequence); + if (showpackets->int_val & 4) { + SZ_Dump (&send); + } + } } qboolean @@ -289,9 +293,13 @@ Netchan_Process (netchan_t *chan) sequence &= ~(1 << 31); sequence_ack &= ~(1 << 31); - if (showpackets->int_val & 2) + if (showpackets->int_val & 2) { Sys_Printf ("<-- s=%i(%i) a=%i(%i) %i\n", sequence, reliable_message, sequence_ack, reliable_ack, net_message->message->cursize); + if (showpackets->int_val & 8) { + SZ_Dump (net_message->message); + } + } // get a rate estimation #if 0 // FIXME: Dead code From 62c20aa4abe6a68e1082471908241a3ad7db5ae6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Aug 2020 11:30:53 +0900 Subject: [PATCH 1094/3664] [ruamoko] Fix incorrect clearing of dtables The problem was caused by passing the index into the dtables array to dtable_get which expects a handle. A handle is the ones-compliment negative of the index which means that handle 0 is invalid (but 0 was being passed... oops). Fixes the segfault when qw-client-x11 connects to a server. --- libs/ruamoko/rua_obj.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 7ecc8ef28..baa8fe73b 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -2192,7 +2192,10 @@ rua_obj_cleanup (progs_t *pr, void *data) } for (i = 0; i < probj->dtables._size; i++) { - dtable_t *dtable = dtable_get (probj, i); + /* dtable_get expects a handle, but a handle is the ones-compliment + * negative of the index. + */ + dtable_t *dtable = dtable_get (probj, ~i); if (!dtable->imp) { break; } From 550b9c3bb2bdedc7ffcafd7f0f8cbad290122df3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Aug 2020 14:35:20 +0900 Subject: [PATCH 1095/3664] [qfcc] Fix silent make rules flex and bison --- tools/qfcc/source/Makemodule.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index d8db07b5c..dacfd3448 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -80,13 +80,13 @@ BUILT_SOURCES += \ tools/qfcc/source/qp-lex.c tools/qfcc/source/qc-parse.c: tools/qfcc/source/qc-parse.y - $(YACC) $(YFLAGS) -Dapi.prefix={qc_yy} $< -o $@ + $(AM_V_YACC)$(YACCCOMPILE) -Dapi.prefix={qc_yy} $< -o $@ tools/qfcc/source/qc-lex.c: tools/qfcc/source/qc-lex.l tools/qfcc/source/qc-parse.h - $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqc_yy -o$@ $< + $(AM_V_LEX)$(LEXCOMPILE) -Pqc_yy -o$@ $< tools/qfcc/source/qp-parse.c: tools/qfcc/source/qp-parse.y - $(YACC) $(YFLAGS) -Dapi.prefix={qp_yy} $< -o $@ + $(AM_V_YACC)$(YACCCOMPILE) -Dapi.prefix={qp_yy} $< -o $@ tools/qfcc/source/qp-lex.c: tools/qfcc/source/qp-lex.l tools/qfcc/source/qp-parse.h - $(LEX) $(LFLAGS) $(AM_LFLAGS) -Pqp_yy -o$@ $< + $(AM_V_LEX)$(LEXCOMPILE) -Pqp_yy -o$@ $< EXTRA_DIST += \ tools/qfcc/source/qfpreqcc From 4a8818f0b6d3d8bc1b5303a0e3f954fa9a6f3ee7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Aug 2020 14:36:08 +0900 Subject: [PATCH 1096/3664] [qfcc] Clean up some excess includes --- tools/qfcc/source/defspace.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index 72537f2d0..1cfe572c3 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -44,15 +44,9 @@ #include "QF/sys.h" #include "QF/va.h" -#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/def.h" #include "tools/qfcc/include/defspace.h" #include "tools/qfcc/include/diagnostic.h" -#include "tools/qfcc/include/expr.h" -#include "tools/qfcc/include/options.h" -#include "tools/qfcc/include/reloc.h" -#include "tools/qfcc/include/strpool.h" -#include "tools/qfcc/include/struct.h" -#include "tools/qfcc/include/type.h" typedef struct locref_s { struct locref_s *next; From e991c44232cf1a1ca19946374536bb88ed687fbc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Dec 2020 13:36:28 +0900 Subject: [PATCH 1097/3664] [util] Make a minor improvement to QuatMultVec Switch from using addition to multiplication for doubling the value. Also, fix lib/util/test Makemodule to actually work (too much c&p coding). --- libs/util/mathlib.c | 2 +- libs/util/test/Makemodule.am | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 842f96df1..1267df2ad 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -268,7 +268,7 @@ QuatMultVec (const quat_t q, const vec3_t v, vec3_t out) dqq = DotProduct (q, q); VectorScale (tv, s, tv); VectorMultAdd (tv, dqv, q, tv); - VectorAdd (tv, tv, tv); + VectorScale (tv, 2, tv); VectorMultAdd (tv, s * s - dqq, v, out); } diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index cf35f885c..8bbb671ad 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -14,9 +14,10 @@ libs_util_tests = \ libs/util/test/test-set \ libs/util/test/test-txtbuffer \ libs/util/test/test-vrect -check_PROGRAMS += $(libs_util_tests) -TESTS += $(libs_model_tests) +TESTS += $(libs_util_tests) + +check_PROGRAMS += $(libs_util_tests) libs_util_test_test_bary_SOURCES=libs/util/test/test-bary.c libs_util_test_test_bary_LDADD=libs/util/libQFutil.la From 62f3e1f428406d3d5a0a7e3c87821111c7e922d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Dec 2020 17:29:08 +0900 Subject: [PATCH 1098/3664] [util] Calculate quaternion to rotate between two vectors The calculation fails (produces NaN) if the vectors are anti-parallel, but works for all other combinations. I came up with this implementation when I discovered Unity's Quaternion.FromToRotation could did not work with very small angles. This implementation will produce a usable quaternion below 0.00255 degrees (though it will be slightly larger than unit). Unity's failed such that I could see KSP's skybox snap while it rotated around my test vessel. --- include/QF/math/quaternion.h | 1 + libs/util/mathlib.c | 18 +++++++ libs/util/test/test-quat.c | 102 +++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) diff --git a/include/QF/math/quaternion.h b/include/QF/math/quaternion.h index d6e34814a..da39b7734 100644 --- a/include/QF/math/quaternion.h +++ b/include/QF/math/quaternion.h @@ -164,6 +164,7 @@ extern const vec_t *const quat_origin; void QuatMult (const quat_t q1, const quat_t q2, quat_t out); void QuatMultVec (const quat_t q, const vec3_t v, vec3_t out); +void QuatRotation (const vec3_t a, const vec3_t b, quat_t out); void QuatInverse (const quat_t in, quat_t out); void QuatExp (const quat_t a, quat_t b); void QuatToMatrix (const quat_t q, vec_t *m, int homogenous, int vertical); diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 1267df2ad..2d547f756 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -272,6 +272,24 @@ QuatMultVec (const quat_t q, const vec3_t v, vec3_t out) VectorMultAdd (tv, s * s - dqq, v, out); } +VISIBLE void +QuatRotation(const vec3_t a, const vec3_t b, quat_t out) +{ + vec_t ma, mb; + vec_t den, mba_mab; + vec3_t t; + + ma = VectorLength(a); + mb = VectorLength(b); + den = 2 * ma * mb; + VectorScale (a, mb, t); + VectorMultAdd(t, ma, b, t); + mba_mab = VectorLength(t); + CrossProduct (a, b, t); + VectorScale(t, 1 / mba_mab, out); + out[3] = mba_mab / den; +} + VISIBLE void QuatInverse (const quat_t in, quat_t out) { diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index 44c8923b3..11cc5b617 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -29,6 +29,45 @@ static vec3_t test_angles[] = { }; #define num_angle_tests (sizeof (test_angles) / sizeof (test_angles[0])) +static struct { + vec3_t a; + vec3_t b; + quat_t expect; +} quat_vector_rotation_tests[] = { + {{1, 0, 0}, {1, 0, 0}, {0, 0, 0, 1}}, + {{0, 1, 0}, {0, 1, 0}, {0, 0, 0, 1}}, + {{0, 0, 1}, {0, 0, 1}, {0, 0, 0, 1}}, + {{1, 0, 0}, {8, 0, 0}, {0, 0, 0, 1}}, + {{0, 8, 0}, {0, 1, 0}, {0, 0, 0, 1}}, + {{0, 0, 8}, {0, 0, 8}, {0, 0, 0, 1}}, + {{1, 0, 0}, {-1, 0, 0}, {0, 0, 0, 0}}, // x, y, z = NaN + {{0, -1, 0}, {0, 1, 0}, {0, 0, 0, 0}}, // x, y, z = NaN + {{0, 0, 1}, {0, 0, -1}, {0, 0, 0, 0}}, // x, y, z = NaN + {{-1, 0, 0}, {8, 0, 0}, {0, 0, 0, 0}}, // x, y, z = NaN + {{0, 8, 0}, {0, -1, 0}, {0, 0, 0, 0}}, // x, y, z = NaN + {{0, 0, -8}, {0, 0, 8}, {0, 0, 0, 0}}, // x, y, z = NaN + // excessive for float, but if vec_t becomes double... + // 1/50 second orbiting JNSQ Kerbin at 120km altitude. While this has + // nothing to do with quakeforge (yet?), it came up when testing camera + // rotation in KSP and Unity failed miserably. I don't remember the exact + // details, but I could see significant snapping in the rotation (I thought + // it was a few times per second, but these numbers indicate it must have + // been every few seconds). + // The quaternion is unit to 9 sigfigs (a little larger) + {{1720000, 0, 0}, {1719999.9983028059, 76.409082595828366, 0}, {0, 0, 2.22119434e-5, 1}}, + // 1/20 second, same situation + {{1720000, 0, 0}, {1719999.9893925365, 191.02270615971355, 0}, {0, 0, 5.55298575e-5, 1}}, + // 1/5 second, same situation + {{1720000, 0, 0}, {1719999.8302805868, 764.09080107761736, 0}, {0, 0, 2.2211943e-4, 1}}, + // 1/4 second, same situation + {{1720000, 0, 0}, {1719999.7348134194, 955.11348367609469, 0}, {0, 0, 2.77649262e-4, 1}}, + // 1/3 second, same situation. This is (float) 1 ulp in w: about 0.0424 + // degrees. + // The quaternion is unit to 9 sigfigs (a little larger) + {{1720000, 0, 0}, {1719999.5285571995, 1273.4845939975546, 0}, {0, 0, 3.70199094e-4, 0.99999994}}, +}; +#define num_quat_vector_rotation_tests (sizeof (quat_vector_rotation_tests) / sizeof (quat_vector_rotation_tests[0])) + // return true if a and b are close enough (yay, floats) static int compare (vec_t a, vec_t b) @@ -200,6 +239,60 @@ fail: return 0; } +static int +test_rotation4 (const vec3_t a, const vec3_t b, const quat_t expect) +{ + int i; + quat_t quat; + vec3_t t; + vec_t d = 0; + + VectorZero (t); + + // find the rotation vector between a and b + QuatRotation (a, b, quat); + + if (quat[3] == 0) { + if (expect[3] != 0) { + goto fail; + } + // expect NaN for the vector components because the vectors are + // anti-parallel and thus the rotation axis is undefined + if (!(isnan(quat[0]) && isnan(quat[1]) && isnan(quat[2]))) { + goto fail; + } + } else { + // the vectors are not anti-parallel and thus the rotation axis is + // defined, so NaN is invalid + if (isnan(quat[0]) || isnan(quat[1]) || isnan(quat[2])) { + goto fail; + } + for (i = 0; i < 4; i++) { + // yes, float precision will make it difficult to set up expect + // but it is at least consistent (ie, the "errors" are not at all + // random and thus will be the same from run to run) + if (quat[i] != expect[i]) { + goto fail; + } + } + QuatMultVec(quat, a, t); + + d = DotProduct (t, b) / (VectorLength (t) * VectorLength (b)) - 1; + if (d * d > 1e-8) { + goto fail; + } + } + return 1; +fail: + printf ("\ntest_rotation4\n"); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand(a)); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand(b)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand(quat)); + printf ("%11.9g %11.9g %11.9g\n", VectorExpand(t)); + printf ("%11.9g\n", d); + return 0; +} + #define s05 0.70710678118654757 static struct { @@ -285,6 +378,15 @@ main (int argc, const char **argv) res = 1; } + for (i = 0; i < num_quat_vector_rotation_tests; i++) { + vec_t *a = quat_vector_rotation_tests[i].a; + vec_t *b = quat_vector_rotation_tests[i].b; + vec_t *expect = quat_vector_rotation_tests[i].expect; + if (!test_rotation4 (a, b, expect)) { + res = 1; + } + } + for (i = 0; i < num_quat_mat_tests; i ++) { vec_t *q = quat_mat_tests[i].q; vec_t *expect = quat_mat_tests[i].expect; From af814ff9a80fb57ba52866a0dc5c2e89a4169320 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Dec 2020 17:37:22 +0900 Subject: [PATCH 1099/3664] [util] Add a cache-line aligned memory allocator This was inspired by Hoard: A Scalable Memory Allocator for Multithreaded Applications Emery D. Berger, Kathryn S. McKinley, Robert D. Blumofe, Paul R. Wilson, It's not anywhere near the same implementation, but it did take a few basic concepts. The idea is twofold: 1) A pool of memory from which blocks can be allocated and then freed en-mass and is fairly efficient for small (4-16 byte) blocks 2) Tread safety for use with the Vulkan renderer (and any other multi-threaded tasks). However, based on the Hoard paper, small allocations are cache-line aligned. On top of that, larger allocations are page aligned. I suspect it would help qfvis somewhat if I ever get around to tweaking qfvis to use cmem. --- include/QF/cmem.h | 96 ++++++++++ libs/util/Makemodule.am | 1 + libs/util/cmem.c | 327 +++++++++++++++++++++++++++++++++ libs/util/test/Makemodule.am | 5 + libs/util/test/test-cmem.c | 346 +++++++++++++++++++++++++++++++++++ 5 files changed, 775 insertions(+) create mode 100644 include/QF/cmem.h create mode 100644 libs/util/cmem.c create mode 100644 libs/util/test/test-cmem.c diff --git a/include/QF/cmem.h b/include/QF/cmem.h new file mode 100644 index 000000000..966696d6c --- /dev/null +++ b/include/QF/cmem.h @@ -0,0 +1,96 @@ +/* + cmem.h + + Cache-line aligned memory allocator + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __cmem_h +#define __cmem_h + +#include "QF/qtypes.h" + +#define MEM_LINE_SIZE 64 + +typedef struct memline_s { + struct memline_s *next; + size_t size; + size_t pad[6]; +} memline_t; + +typedef struct memsline_s { + struct memsline_s *next; + size_t size:2; + size_t list:4; + size_t prev:58; // memsline_t ** +} memsline_t; + +typedef struct memblock_s { + struct memblock_s *next; + struct memblock_s **prev; + /* The pointer to pass to free() + */ + void *mem; + memline_t *free_lines; + /* Size of memory region before block "header". + * + * Since large blocks are allocated with page-size alignment, odds are + * high that the there will be many cache lines "wasted" in the space + * between the address returned from aligned_alloc (to cache-line + * alignment) and the block itself. Setting them up as a pool makes the + * lines available for smaller allocations, thus reducing waste. + */ + size_t pre_size; + /* Size of memory region after block "header". + * + * Will be 0 for blocks that were allocated exclusively for small + * allocations, otherwise indicates the size of the allocated block. + */ + size_t post_size; + /* True if the post-header block is free to be reused. + */ + int post_free; + int pad; + size_t pre_allocated; +} memblock_t; + +typedef struct memsuper_s { + size_t page_size; + size_t page_mask; + memblock_t *memblocks; + /* Allocated cache lines from which smaller blocks can be allocated. + * + * The index is the base-2 log minus 2 of the size of the elements in the + * cache line from which an element was last freed. Only 4-32 bytes are of + * interest because nothing smaller than 4 bytes (int/float) will be + * allocated, and 64 bytes and up consume entire cache lines. + */ + memsline_t *last_freed[4]; + size_t pad; +} memsuper_t; + +memsuper_t *new_memsuper (void); +void delete_memsuper (memsuper_t *super); +void *cmemalloc (memsuper_t *super, size_t size); +void cmemfree (memsuper_t *super, void *mem); + +#endif//__cmem_h diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am index 272459d4d..af99b15d3 100644 --- a/libs/util/Makemodule.am +++ b/libs/util/Makemodule.am @@ -45,6 +45,7 @@ libs_util_libQFutil_la_SOURCES= \ libs/util/cbuf.c \ libs/util/checksum.c \ libs/util/cmd.c \ + libs/util/cmem.c \ libs/util/crc.c \ libs/util/cvar.c \ libs/util/dstring.c \ diff --git a/libs/util/cmem.c b/libs/util/cmem.c new file mode 100644 index 000000000..b446e58f0 --- /dev/null +++ b/libs/util/cmem.c @@ -0,0 +1,327 @@ +/* + cmem.c + + Cache-line aligned memory allocator + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#include + +#include "QF/alloc.h" +#include "QF/cmem.h" + + +memsuper_t * +new_memsuper (void) +{ + memsuper_t *super = aligned_alloc (MEM_LINE_SIZE, sizeof (*super)); + memset (super, 0, sizeof (*super)); + super->page_size = sysconf (_SC_PAGESIZE); + super->page_mask = (super->page_size - 1); + return super; +} + +void +delete_memsuper (memsuper_t *super) +{ + while (super->memblocks) { + memblock_t *t = super->memblocks; + super->memblocks = super->memblocks->next; + free (t->mem); + } + free (super); +} + +static memblock_t * +init_block (memsuper_t *super, void *mem, size_t alloc_size) +{ + size_t size = super->page_size; + size_t mask = super->page_mask; + size_t ptr = (size_t) mem; + memblock_t *block; + + block = (memblock_t *) (((ptr + size) & ~mask) - sizeof (memblock_t)); + memset (block, 0, sizeof (memblock_t)); + + if (super->memblocks) { + super->memblocks->prev = &block->next; + } + block->next = super->memblocks; + block->prev = &super->memblocks; + super->memblocks = block; + + block->mem = mem; + block->pre_size = (size_t) block - (size_t) mem; + block->post_size = alloc_size - block->pre_size - sizeof (memblock_t); + if (!((size_t) mem & mask) && block->pre_size) { + // can't use the first cache line of the page as it would be + // indistinguishable from a large block + block->pre_size -= MEM_LINE_SIZE; + } + if (block->pre_size) { + block->free_lines = (memline_t *) ((size_t) block - block->pre_size); + block->free_lines->next = 0; + block->free_lines->size = block->pre_size; + } + return block; +} + +static memblock_t * +block_alloc (memsuper_t *super, size_t size) +{ + memblock_t *block; + memblock_t *best = 0; + size_t best_size = ~0u; + + for (block = super->memblocks; block; block = block->next) { + if (block->post_free && block->post_size >= size + && block->post_size < best_size) { + best = block; + best_size = block->post_size; + } + } + if (best) { + best->post_free = 0; + return best; + } + + size_t page_size = super->page_size; + size_t alloc_size = sizeof (memblock_t) + page_size + size; + void *mem = aligned_alloc (MEM_LINE_SIZE, alloc_size); + block = init_block (super, mem, alloc_size); + return block; +} + +static void * +line_alloc (memblock_t *block, size_t size) +{ + memline_t **line = &block->free_lines; + memline_t **best = 0; + memline_t *mem; + size_t best_size = ~0u; + + while (*line) { + if ((*line)->size >= size && (*line)->size < best_size) { + best_size = (*line)->size; + best = line; + } + line = &(*line)->next; + } + if (!best) { + return 0; + } + mem = *best; + if (size < best_size) { + *best = (memline_t *)((size_t) mem + size); + (*best)->next = mem->next; + (*best)->size = mem->size - size; + } else { + *best = (*best)->next; + } + block->pre_allocated += size; + return mem; +} + +static void +line_free (memblock_t *block, void *mem) +{ + //FIXME right now, can free only single lines (need allocated lines to + // have a control block) + size_t size = MEM_LINE_SIZE; + memline_t **l; + memline_t *line = 0; + + block->pre_allocated -= size; + + for (l = &block->free_lines; *l; l = &(*l)->next) { + line = *l; + + if ((size_t) mem + size < (size_t) line) { + // line to be freed is below the free line + break; + } + if ((size_t) mem + size == (size_t) line) { + // line to be freed is immediately below the free line + // merge with the free line + size += line->size; + line = line->next; + break; + } + if ((size_t) line + line->size == (size_t) mem) { + // line to be freed is immediately above the free line + // merge with the free line + line->size += size; + if (line->next && (size_t) line->next == (size_t) mem + size) { + line->size += line->next->size; + line->next = line->next->next; + } + return; + } + } + ((memline_t *) mem)->next = line; + ((memline_t *) mem)->size = size; + *l = mem; +} + +static memsline_t * +sline_new (memsuper_t *super, size_t size_ind) +{ + size_t size = 4 << size_ind; + size_t free_loc = (sizeof (memsline_t) + size - 1) & ~(size - 1); + memsline_t *sline = cmemalloc (super, MEM_LINE_SIZE); + sline->size = size_ind; + sline->list = free_loc >> 2; + while (free_loc + size < MEM_LINE_SIZE) { + *(uint16_t *)((size_t) sline + free_loc) = free_loc + size; + free_loc += size; + } + *(uint16_t *)((size_t) sline + free_loc) = 0; + if (super->last_freed[size_ind]) { + super->last_freed[size_ind]->prev = (size_t) &sline->next >> 6; + } + sline->next = super->last_freed[size_ind]; + sline->prev = (size_t) &super->last_freed[size_ind] >> 6; + super->last_freed[size_ind] = sline; + return sline; +} + +void * +cmemalloc (memsuper_t *super, size_t size) +{ + size_t ind = 0; + // allocation sizes start at 4 (sizeof(float)) and go up in powers of two + while ((4u << ind) < size) { + ind++; + } + // round size up + if (size > MEM_LINE_SIZE * 8 || size > super->page_size / 8) { + // the object is large enough it could cause excessive fragmentation, + memblock_t *block = block_alloc (super, 4 << ind); + if (!block) { + return 0; + } + return block + 1; + } else { + size = 4 << ind; + if (size >= MEM_LINE_SIZE) { + // whole cache lines are required for this object + // FIXME slow + memblock_t *block = super->memblocks; + void *mem; + + while (block) { + if ((mem = line_alloc (block, size))) { + return mem; + } + block = block->next; + } + /* The cache-line pool is page aligned for two reasons: + * 1) so it fits exactly within a page + * 2) the control block can be found easily + * And the reason the pool is exactly one page large is so no + * allocated line is ever page-aligned as that would make the line + * indistinguishable from a large block. + */ + mem = aligned_alloc (super->page_size, super->page_size); + block = init_block (super, mem, super->page_size); + return line_alloc (block, size); + } else { + void *mem = 0; + memsline_t **sline = &super->last_freed[ind]; + if (!*sline) { + *sline = sline_new (super, ind); + } + if (*sline) { + size_t list = (*sline)->list << 2; + mem = (void *) ((size_t) *sline + list); + (*sline)->list = *(uint16_t *) mem >> 2; + if (!(*sline)->list) { + // the sub-line is full, so remove it from the free + // list. Freeing a block from the line will add it back + // to the list + memsline_t *s = *sline; + if ((*sline)->next) { + (*sline)->next->prev = (*sline)->prev; + } + *sline = (*sline)->next; + s->next = 0; + s->prev = 0; + } + } + return mem; + } + } + return 0; +} + +static void +unlink_block (memblock_t *block) +{ + if (block->next) { + block->next->prev = block->prev; + } + *block->prev = block->next; +} + +void +cmemfree (memsuper_t *super, void *mem) +{ + memsline_t **super_sline; + memsline_t *sline; + memblock_t *block; + + if ((size_t) mem & (MEM_LINE_SIZE - 1)) { + // sub line block + sline = (memsline_t *) ((size_t) mem & ~(MEM_LINE_SIZE - 1)); + *(uint16_t *) mem = sline->list << 2; + sline->list = (size_t) mem & (MEM_LINE_SIZE - 1); + super_sline = &super->last_freed[sline->size]; + if (*super_sline != sline) { + if (sline->next) { + sline->next->prev = sline->prev; + } + if (sline->prev) { + *(memsline_t **) (size_t)(sline->prev << 6) = sline->next; + } + + (*super_sline)->prev = (size_t) &sline->next >> 6; + sline->next = *super_sline; + sline->prev = (size_t) super_sline >> 6; + (*super_sline) = sline; + } + return; + } else if ((size_t) mem & super->page_mask) { + // cache line + size_t page_size = super->page_size; + size_t page_mask = super->page_mask; + block = (memblock_t *) (((size_t) mem + page_size) & ~page_mask) - 1; + line_free (block, mem); + } else { + // large block + block = (memblock_t *) mem - 1; + block->post_free = 1; + } + if (!block->pre_allocated && (!block->post_size || block->post_free)) { + unlink_block (block); + free (block->mem); + } +} diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 8bbb671ad..39140bee7 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -1,5 +1,6 @@ libs_util_tests = \ libs/util/test/test-bary \ + libs/util/test/test-cmem \ libs/util/test/test-cs \ libs/util/test/test-darray \ libs/util/test/test-dq \ @@ -23,6 +24,10 @@ libs_util_test_test_bary_SOURCES=libs/util/test/test-bary.c libs_util_test_test_bary_LDADD=libs/util/libQFutil.la libs_util_test_test_bary_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_cmem_SOURCES=libs/util/test/test-cmem.c +libs_util_test_test_cmem_LDADD=libs/util/libQFutil.la +libs_util_test_test_cmem_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_cs_SOURCES=libs/util/test/test-cs.c libs_util_test_test_cs_LDADD=libs/util/libQFutil.la libs_util_test_test_cs_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-cmem.c b/libs/util/test/test-cmem.c new file mode 100644 index 000000000..c8c2ee7e3 --- /dev/null +++ b/libs/util/test/test-cmem.c @@ -0,0 +1,346 @@ +#include +#include +#include +#include + +#include "QF/cmem.h" + +static int +test_block (memsuper_t *super) +{ + size_t size = super->page_size; + void *mem = cmemalloc (super, size); + memblock_t *block; + + if (!mem) { + fprintf (stderr, "could not allocate %zd byte block\n", + super->page_size); + return 0; + } + if ((size_t) mem & super->page_mask) { + fprintf (stderr, "mem not page aligned: %p %zd\n", + mem, super->page_size); + return 0; + } + block = super->memblocks; + if (mem != block + 1) { + fprintf (stderr, "super does not point to mem\n"); + return 0; + } + if (block->post_size < size) { + fprintf (stderr, "block post_size too small: %zd < %zd\n", + block->post_size, size); + return 0; + } + if (block->post_size - size >= super->page_size) { + fprintf (stderr, "block post_size too big: %zd < %zd\n", + block->post_size - size, super->page_size); + return 0; + } + memset (mem, 0, size); // valgrind check + cmemfree (super, mem); + if (super->memblocks) { + fprintf (stderr, "super still points to mem\n"); + return 0; + } + return 1; +} + +static int +test_line (memsuper_t *super) +{ + memline_t *line1 = cmemalloc (super, MEM_LINE_SIZE); + memline_t *line2 = cmemalloc (super, MEM_LINE_SIZE); + memline_t *line3 = cmemalloc (super, MEM_LINE_SIZE); + memblock_t *block = super->memblocks; + + if (block->next) { + fprintf (stderr, "too many memblocks\n"); + return 0; + } + if (line1 < (memline_t *) block->mem || line1 >= (memline_t *) block) { + fprintf (stderr, "line1 outside block line pool\n"); + return 0; + } + if (line2 < (memline_t *) block->mem || line2 >= (memline_t *) block) { + fprintf (stderr, "line2 outside block line pool\n"); + return 0; + } + if (line3 < (memline_t *) block->mem || line3 >= (memline_t *) block) { + fprintf (stderr, "line3 outside block line pool\n"); + return 0; + } + if (!((size_t) line1 & super->page_mask)) { + fprintf (stderr, "line1 is page aligned\n"); + return 0; + } + if (!((size_t) line2 & super->page_mask)) { + fprintf (stderr, "line2 is page aligned\n"); + return 0; + } + if (!((size_t) line3 & super->page_mask)) { + fprintf (stderr, "line3 is page aligned\n"); + return 0; + } + if (line1 + 1 != line2 || line2 + 1 != line3) { + fprintf (stderr, "lines not contiguous\n"); + return 0; + } + if (line3 + 1 != block->free_lines) { + fprintf (stderr, "line3 not contiguous with free lines\n"); + return 0; + } + if (block->free_lines->next) { + fprintf (stderr, "multiple free line blocks\n"); + return 0; + } + if (block->pre_allocated != 3 * MEM_LINE_SIZE) { + fprintf (stderr, "pre_allocated wrong size: %zd != %d\n", + block->pre_allocated, 3 * MEM_LINE_SIZE); + return 0; + } + if (block->free_lines->size != block->pre_size - block->pre_allocated) { + fprintf (stderr, "free lines wrong size: %zd != %zd\n", + block->free_lines->size, + block->pre_size - block->pre_allocated); + return 0; + } + size_t old_size = block->free_lines->size; + memline_t *old_line = block->free_lines; + cmemfree (super, line2); + if (block->pre_allocated != 2 * MEM_LINE_SIZE) { + fprintf (stderr, "pre_allocated wrong size: %zd != %d\n", + block->pre_allocated, 2 * MEM_LINE_SIZE); + return 0; + } + if (block->free_lines != line2) { + fprintf (stderr, "free lines not pointing to line2\n"); + return 0; + } + if (!block->free_lines->next || block->free_lines->next->next) { + fprintf (stderr, "incorrect number of free blocks\n"); + return 0; + } + if (line2->next != old_line || old_line->size != old_size) { + fprintf (stderr, "free line blocks corrupted\n"); + return 0; + } + if (block->free_lines->size != MEM_LINE_SIZE) { + fprintf (stderr, "free line block wrong size: %zd != %d\n", + block->free_lines->size, MEM_LINE_SIZE); + return 0; + } + cmemfree (super, line3); + if (block->free_lines != line2) { + fprintf (stderr, "free lines not pointing to line2 2\n"); + return 0; + } + if (block->pre_allocated != MEM_LINE_SIZE) { + fprintf (stderr, "pre_allocated wrong size: %zd != %d\n", + block->pre_allocated, MEM_LINE_SIZE); + return 0; + } + if (block->free_lines->size != block->pre_size - block->pre_allocated) { + fprintf (stderr, "free lines wrong size: %zd != %zd\n", + block->free_lines->size, + block->pre_size - block->pre_allocated); + return 0; + } + cmemfree (super, line1); + if (super->memblocks) { + fprintf (stderr, "line pool not freed\n"); + return 0; + } + return 1; +} + +static int +test_sline (memsuper_t *super) +{ + void *mem[] = { + //cmemalloc (super, 2), // smaller than min size + cmemalloc (super, 4), + cmemalloc (super, 4), + cmemalloc (super, 8), + cmemalloc (super, 8), + cmemalloc (super, 16), + cmemalloc (super, 16), + cmemalloc (super, 32), + cmemalloc (super, 32), + }; +#define mem_size (sizeof (mem) / sizeof (mem[0])) + int fail = 0; + for (size_t i = 0; i < mem_size; i++) { + printf("%p\n", mem[i]); + if (!mem[i]) { + fprintf (stderr, "mem[%zd] is null\n", i); + fail = 1; + } + for (size_t j = i + 1; j < mem_size; j++) { + if (mem[i] == mem[j]) { + fprintf (stderr, "mem[%zd] is dupped with %zd\n", i, j); + fail = 1; + } + } + } + if (fail) { + return 0; + } +#undef mem_size + return 1; +} + +static int +test_block_line (memsuper_t *super) +{ + void *mem = cmemalloc (super, 2 * super->page_size); + void *line; + memblock_t *block = super->memblocks; + + if (block + 1 != (memblock_t *) mem) { + fprintf (stderr, "super memblocks do not point to mem\n"); + return 0; + } + if (block->pre_size < MEM_LINE_SIZE) { + // need to figure out a way to guarantee a shared block + fprintf (stderr, "can't allocate line from block\n"); + return 0; + } + if (block->next) { + fprintf (stderr, "excess blocks in super\n"); + return 0; + } + line = cmemalloc (super, MEM_LINE_SIZE); + if (!((size_t) line & super->page_mask)) { + fprintf (stderr, "line is page aligned\n"); + return 0; + } + if (super->memblocks->next) { + // need to figure out a way to guarantee a shared block + fprintf (stderr, "mem and line not in same block\n"); + return 0; + } + cmemfree (super, mem); + if (!super->memblocks) { + fprintf (stderr, "shared block freed\n"); + return 0; + } + if (cmemalloc (super, super->page_size) != mem) { + fprintf (stderr, "block not reused for mem\n"); + return 0; + } + if (super->memblocks != block || super->memblocks->next) { + // need to figure out a way to guarantee a shared block + fprintf (stderr, "blocks corrupt\n"); + return 0; + } + cmemfree (super, line); + if (!super->memblocks) { + fprintf (stderr, "shared block freed 2\n"); + return 0; + } + cmemfree (super, mem); + if (super->memblocks) { + fprintf (stderr, "shared block not freed\n"); + return 0; + } + return 1; +} + +int +main (void) +{ + memsuper_t *super = new_memsuper (); + + if (sizeof (memsuper_t) != MEM_LINE_SIZE) { + fprintf (stderr, "memsuper_t not cache size: %zd\n", + sizeof (memline_t)); + return 1; + } + if (sizeof (memline_t) != MEM_LINE_SIZE) { + fprintf (stderr, "memline_t not cache size: %zd\n", + sizeof (memline_t)); + return 1; + } + if (sizeof (memsline_t) != 2 * sizeof (void *)) { + fprintf (stderr, "memsline_t not two pointers: %zd\n", + sizeof (memsline_t)); + return 1; + } + if (sizeof (memblock_t) != MEM_LINE_SIZE) { + fprintf (stderr, "memblock_t not cache size: %zd\n", + sizeof (memblock_t)); + return 1; + } + if ((size_t) super & (MEM_LINE_SIZE - 1)) { + fprintf (stderr, "super block not cache aligned: %p\n", super); + return 1; + } + if (super->page_size != (size_t) sysconf (_SC_PAGESIZE)) { + fprintf (stderr, "page size not equal to system page size: %zd, %zd\n", + super->page_size, sysconf (_SC_PAGESIZE)); + return 1; + } + if (!super->page_size || (super->page_size & (super->page_size - 1))) { + fprintf (stderr, "page size not power of two: %zd\n", + super->page_size); + return 1; + } + if (super->page_mask + 1 != super->page_size) { + fprintf (stderr, "page mask not page size - 1: %zx %zx\n", + super->page_mask, super->page_size); + return 1; + } + if (!super->page_mask || (super->page_mask & (super->page_mask + 1))) { + fprintf (stderr, "page mask not all 1s: %zx\n", + super->page_mask); + return 1; + } + if (super->memblocks) { + fprintf (stderr, "super block list not null\n"); + return 1; + } + if (!test_block (super)) { + fprintf (stderr, "block tests failed\n"); + } + if (super->memblocks) { + fprintf (stderr, "super block list not null 2\n"); + return 1; + } + if (!test_line (super)) { + fprintf (stderr, "line tests failed\n"); + return 1; + } + if (super->memblocks) { + fprintf (stderr, "super block list not null 2\n"); + return 1; + } + if (!test_block_line (super)) { + fprintf (stderr, "block-line tests failed\n"); + return 1; + } + for (size_t i = 0; i < 2 * super->page_size / MEM_LINE_SIZE; i++) { + void *line = cmemalloc (super, MEM_LINE_SIZE); + if (!line) { + fprintf (stderr, "could not allocate %d byte line\n", + MEM_LINE_SIZE); + return 1; + } + if ((size_t) line % MEM_LINE_SIZE) { + fprintf (stderr, "line not cache-line aligned: %p %d\n", + line, MEM_LINE_SIZE); + return 1; + } + if (!((size_t) line & super->page_mask)) { + fprintf (stderr, "line is page aligned: %p %zd\n", + line, super->page_size); + return 1; + } + } + if (!test_sline (super)) { + fprintf (stderr, "sub-line tests failed\n"); + return 1; + } + delete_memsuper (super); + return 0; +} From ab04a1915ed45646a7111b43371b451626ea6d2c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 02:12:51 +0900 Subject: [PATCH 1100/3664] [build] Fix a pile of gcc 10 issues gcc got stricter about array accesses, complicating progs macros, and much better at detecting buffer overflows. --- include/QF/math/vector.h | 7 +- include/QF/pr_comp.h | 4 +- include/QF/progs.h | 14 ++-- libs/console/bi_inputline.c | 2 +- libs/gamecode/pr_debug.c | 8 +- libs/gamecode/pr_exec.c | 89 +++++++++++---------- libs/gamecode/pr_parse.c | 6 +- libs/models/alias/model_alias.c | 2 +- libs/ruamoko/rua_hash.c | 2 +- libs/ruamoko/rua_msgbuf.c | 5 +- libs/ruamoko/rua_obj.c | 2 +- libs/ruamoko/rua_plist.c | 2 +- libs/ruamoko/rua_qfile.c | 2 +- libs/ruamoko/rua_script.c | 2 +- libs/ruamoko/rua_set.c | 4 +- libs/util/zone.c | 3 +- libs/video/renderer/r_progs.c | 2 +- libs/video/renderer/vulkan/vkgen/vkstruct.r | 39 +++++---- nq/include/sv_progs.h | 2 +- qw/include/sv_progs.h | 2 +- qw/source/pmove.c | 2 +- qw/source/sv_progs.c | 4 +- ruamoko/qwaq/builtins/curses.c | 4 +- ruamoko/qwaq/builtins/debug.c | 2 +- ruamoko/qwaq/builtins/editbuffer.c | 2 +- ruamoko/qwaq/builtins/main.c | 1 + tools/qfbsp/source/outside.c | 2 + tools/qfcc/include/qfcc.h | 4 +- tools/qflight/include/noise.h | 2 +- tools/qfmodelgen/source/modelgen.c | 10 ++- 30 files changed, 125 insertions(+), 107 deletions(-) diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 6a8b80809..993cbaf08 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -142,7 +142,12 @@ extern const vec_t *const vec3_origin; } while (0) #define VectorIsZero(a) (!(a)[0] && !(a)[1] && !(a)[2]) -#define VectorZero(a) ((a)[2] = (a)[1] = (a)[0] = 0); +#define VectorZero(a) \ + do { \ + (a)[0] = 0; \ + (a)[1] = 0; \ + (a)[2] = 0; \ + } while (0) #define VectorSet(a,b,c,d) \ do { \ (d)[0] = a; \ diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index a84e56953..0cd65d7e5 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -474,8 +474,8 @@ typedef union pr_type_u { string_t string_var; func_t func_var; pr_int_t entity_var; - float vector_var[0]; // really 3, but this structure must be 32 bits - float quat_var[0]; // really 4, but this structure must be 32 bits + float vector_var; // really [3], but this structure must be 32 bits + float quat_var; // really [4], but this structure must be 32 bits pr_int_t integer_var; pointer_t pointer_var; pr_uint_t uinteger_var; diff --git a/include/QF/progs.h b/include/QF/progs.h index 8a78926bf..64a9d20bb 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -445,7 +445,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_VECTOR(p,o) G_var (p, o, vector) +#define G_VECTOR(p,o) (&G_var (p, o, vector)) /** Access a quaternion global. Can be assigned to. @@ -457,7 +457,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_QUAT(p,o) G_var (p, o, quat) +#define G_QUAT(p,o) (&G_var (p, o, quat)) /** Access a string index global. Can be assigned to. @@ -661,7 +661,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_VECTOR(p,n) P_var (p, n, vector) +#define P_VECTOR(p,n) (&P_var (p, n, vector)) /** Access a quaterion parameter. Can be used any way a quat_t variable can. @@ -673,7 +673,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_QUAT(p,n) P_var (p, n, quat) +#define P_QUAT(p,n) (&P_var (p, n, quat)) /** Access a string index parameter. Can be assigned to. @@ -873,7 +873,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_VECTOR(p) R_var (p, vector) +#define R_VECTOR(p) (&R_var (p, vector)) /** Access the VM function return value as a \c ::quat_t quaternion. @@ -884,7 +884,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_QUAT(p) R_var (p, quat) +#define R_QUAT(p) (&R_var (p, quat)) /** Access the VM function return value as a ::string_t (a VM string reference). @@ -1054,7 +1054,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_VECTOR(e,o) E_var (e, o, vector) +#define E_VECTOR(e,o) (&E_var (e, o, vector)) /** Access a quaternion entity field. Can be used any way a quat_t variable can. diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index f48a4551e..7e4e743a2 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -83,7 +83,7 @@ il_data_get (il_resources_t *res, unsigned index) PR_RESGET (res->line_map, index); } -static inline int +static inline int __attribute__((pure)) il_data_index (il_resources_t *res, il_data_t *line) { PR_RESINDEX (res->line_map, line); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 3d99da30a..d8105c5f6 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1133,9 +1133,7 @@ pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%.9g %.9g %.9g'", - value->vector_var[0], value->vector_var[1], - value->vector_var[2]); + dasprintf (dstr, "'%.9g %.9g %.9g'", VectorExpand (&value->vector_var)); } static void @@ -1213,9 +1211,7 @@ pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%.9g %.9g %.9g %.9g'", - value->vector_var[0], value->vector_var[1], - value->vector_var[2], value->vector_var[3]); + dasprintf (dstr, "'%.9g %.9g %.9g %.9g'", QuatExpand (&value->quat_var)); } static void diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 4a79f8173..9a9d03893 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -512,10 +512,10 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.float_var = OPA.float_var + OPB.float_var; break; case OP_ADD_V: - VectorAdd (OPA.vector_var, OPB.vector_var, OPC.vector_var); + VectorAdd (&OPA.vector_var, &OPB.vector_var, &OPC.vector_var); break; case OP_ADD_Q: - QuatAdd (OPA.quat_var, OPB.quat_var, OPC.quat_var); + QuatAdd (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); break; case OP_ADD_S: OPC.string_var = PR_CatStrings (pr, @@ -531,10 +531,11 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.float_var = OPA.float_var - OPB.float_var; break; case OP_SUB_V: - VectorSubtract (OPA.vector_var, OPB.vector_var, OPC.vector_var); + VectorSubtract (&OPA.vector_var, &OPB.vector_var, + &OPC.vector_var); break; case OP_SUB_Q: - QuatSubtract (OPA.quat_var, OPB.quat_var, OPC.quat_var); + QuatSubtract (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); break; case OP_MUL_D: OPC_double_var = OPA_double_var * OPB_double_var; @@ -543,14 +544,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.float_var = OPA.float_var * OPB.float_var; break; case OP_MUL_V: - OPC.float_var = DotProduct (OPA.vector_var, OPB.vector_var); + OPC.float_var = DotProduct (&OPA.vector_var, &OPB.vector_var); break; case OP_MUL_DV: { // avoid issues with the likes of x = x.x * x; // makes for faster code, too double scale = OPA_double_var; - VectorScale (OPB.vector_var, scale, OPC.vector_var); + VectorScale (&OPB.vector_var, scale, &OPC.vector_var); } break; case OP_MUL_VD: @@ -558,7 +559,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x * x.x; // makes for faster code, too double scale = OPB_double_var; - VectorScale (OPA.vector_var, scale, OPC.vector_var); + VectorScale (&OPA.vector_var, scale, &OPC.vector_var); } break; case OP_MUL_FV: @@ -566,7 +567,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x.x * x; // makes for faster code, too float scale = OPA.float_var; - VectorScale (OPB.vector_var, scale, OPC.vector_var); + VectorScale (&OPB.vector_var, scale, &OPC.vector_var); } break; case OP_MUL_VF: @@ -574,21 +575,21 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x * x.x; // makes for faster code, too float scale = OPB.float_var; - VectorScale (OPA.vector_var, scale, OPC.vector_var); + VectorScale (&OPA.vector_var, scale, &OPC.vector_var); } break; case OP_MUL_Q: - QuatMult (OPA.quat_var, OPB.quat_var, OPC.quat_var); + QuatMult (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); break; case OP_MUL_QV: - QuatMultVec (OPA.quat_var, OPB.vector_var, OPC.vector_var); + QuatMultVec (&OPA.quat_var, &OPB.vector_var, &OPC.vector_var); break; case OP_MUL_DQ: { // avoid issues with the likes of x = x.s * x; // makes for faster code, too double scale = OPA_double_var; - QuatScale (OPB.quat_var, scale, OPC.quat_var); + QuatScale (&OPB.quat_var, scale, &OPC.quat_var); } break; case OP_MUL_QD: @@ -596,7 +597,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x * x.s; // makes for faster code, too double scale = OPB_double_var; - QuatScale (OPA.quat_var, scale, OPC.quat_var); + QuatScale (&OPA.quat_var, scale, &OPC.quat_var); } break; case OP_MUL_FQ: @@ -604,7 +605,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x.s * x; // makes for faster code, too float scale = OPA.float_var; - QuatScale (OPB.quat_var, scale, OPC.quat_var); + QuatScale (&OPB.quat_var, scale, &OPC.quat_var); } break; case OP_MUL_QF: @@ -612,11 +613,11 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x * x.s; // makes for faster code, too float scale = OPB.float_var; - QuatScale (OPA.quat_var, scale, OPC.quat_var); + QuatScale (&OPA.quat_var, scale, &OPC.quat_var); } break; case OP_CONJ_Q: - QuatConj (OPA.quat_var, OPC.quat_var); + QuatConj (&OPA.quat_var, &OPC.quat_var); break; case OP_DIV_D: OPC_double_var = OPA_double_var / OPB_double_var; @@ -673,10 +674,10 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.integer_var = !FNZ (OPA); break; case OP_NOT_V: - OPC.integer_var = VectorIsZero (OPA.vector_var); + OPC.integer_var = VectorIsZero (&OPA.vector_var); break; case OP_NOT_Q: - OPC.integer_var = QuatIsZero (OPA.quat_var); + OPC.integer_var = QuatIsZero (&OPA.quat_var); break; case OP_NOT_S: OPC.integer_var = !OPA.string_var || @@ -692,11 +693,11 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.integer_var = OPA.float_var == OPB.float_var; break; case OP_EQ_V: - OPC.integer_var = VectorCompare (OPA.vector_var, - OPB.vector_var); + OPC.integer_var = VectorCompare (&OPA.vector_var, + &OPB.vector_var); break; case OP_EQ_Q: - OPC.integer_var = QuatCompare (OPA.quat_var, OPB.quat_var); + OPC.integer_var = QuatCompare (&OPA.quat_var, &OPB.quat_var); break; case OP_EQ_E: OPC.integer_var = OPA.integer_var == OPB.integer_var; @@ -708,11 +709,11 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.integer_var = OPA.float_var != OPB.float_var; break; case OP_NE_V: - OPC.integer_var = !VectorCompare (OPA.vector_var, - OPB.vector_var); + OPC.integer_var = !VectorCompare (&OPA.vector_var, + &OPB.vector_var); break; case OP_NE_Q: - OPC.integer_var = !QuatCompare (OPA.quat_var, OPB.quat_var); + OPC.integer_var = !QuatCompare (&OPA.quat_var, &OPB.quat_var); break; case OP_LE_S: case OP_GE_S: @@ -753,10 +754,10 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPB.integer_var = OPA.integer_var; break; case OP_STORE_V: - VectorCopy (OPA.vector_var, OPB.vector_var); + VectorCopy (&OPA.vector_var, &OPB.vector_var); break; case OP_STORE_Q: - QuatCopy (OPA.quat_var, OPB.quat_var); + QuatCopy (&OPA.quat_var, &OPB.quat_var); break; case OP_STORE_D: OPB_double_var = OPA_double_var; @@ -782,7 +783,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (OPA.vector_var, ptr->vector_var); + VectorCopy (&OPA.vector_var, &ptr->vector_var); break; case OP_STOREP_Q: pointer = OPB.integer_var; @@ -790,7 +791,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (OPA.quat_var, ptr->quat_var); + QuatCopy (&OPA.quat_var, &ptr->quat_var); break; case OP_STOREP_D: pointer = OPB.integer_var; @@ -909,7 +910,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (ptr->vector_var, OPC.vector_var); + VectorCopy (&ptr->vector_var, &OPC.vector_var); break; case OP_LOADB_Q: pointer = OPA.integer_var + OPB.integer_var; @@ -917,7 +918,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (ptr->quat_var, OPC.quat_var); + QuatCopy (&ptr->quat_var, &OPC.quat_var); break; case OP_LOADB_D: pointer = OPA.integer_var + OPB.integer_var; @@ -948,7 +949,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (ptr->vector_var, OPC.vector_var); + VectorCopy (&ptr->vector_var, &OPC.vector_var); break; case OP_LOADBI_Q: pointer = OPA.integer_var + (short) st->b; @@ -956,7 +957,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (ptr->quat_var, OPC.quat_var); + QuatCopy (&ptr->quat_var, &OPC.quat_var); break; case OP_LOADBI_D: pointer = OPA.integer_var + (short) st->b; @@ -997,7 +998,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (OPA.vector_var, ptr->vector_var); + VectorCopy (&OPA.vector_var, &ptr->vector_var); break; case OP_STOREB_Q: pointer = OPB.integer_var + OPC.integer_var; @@ -1005,7 +1006,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (OPA.quat_var, ptr->quat_var); + QuatCopy (&OPA.quat_var, &ptr->quat_var); break; case OP_STOREB_D: pointer = OPB.integer_var + OPC.integer_var; @@ -1036,7 +1037,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (OPA.vector_var, ptr->vector_var); + VectorCopy (&OPA.vector_var, &ptr->vector_var); break; case OP_STOREBI_Q: pointer = OPB.integer_var + (short) st->c; @@ -1044,7 +1045,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (OPA.quat_var, ptr->quat_var); + QuatCopy (&OPA.quat_var, &ptr->quat_var); break; case OP_STOREBI_D: pointer = OPB.integer_var + (short) st->c; @@ -1131,7 +1132,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (ptr->vector_var, stk->vector_var); + VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack; } break; @@ -1148,7 +1149,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (ptr->quat_var, stk->quat_var); + QuatCopy (&ptr->quat_var, &stk->quat_var); *pr->globals.stack = stack; } break; @@ -1189,7 +1190,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (ptr->vector_var, stk->vector_var); + VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack; } break; @@ -1206,7 +1207,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (ptr->quat_var, stk->quat_var); + QuatCopy (&ptr->quat_var, &stk->quat_var); *pr->globals.stack = stack; } break; @@ -1287,7 +1288,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (ptr->vector_var, stk->vector_var); + VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack + 3; } break; @@ -1304,7 +1305,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (ptr->quat_var, stk->quat_var); + QuatCopy (&ptr->quat_var, &stk->quat_var); *pr->globals.stack = stack + 4; } break; @@ -1345,7 +1346,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (ptr->vector_var, stk->vector_var); + VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack + 3; } break; @@ -1362,7 +1363,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (ptr->quat_var, stk->quat_var); + QuatCopy (&ptr->quat_var, &stk->quat_var); *pr->globals.stack = stack + 4; } break; diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 2652694e8..6471a44bb 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -92,10 +92,10 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) dsprintf (line, "%d", val->integer_var); break; case ev_vector: - dsprintf (line, "%.9g %.9g %.9g", VectorExpand (val->vector_var)); + dsprintf (line, "%.9g %.9g %.9g", VectorExpand (&val->vector_var)); break; case ev_quat: - dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (val->quat_var)); + dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (&val->quat_var)); break; default: dsprintf (line, "bad type %i", type); @@ -241,7 +241,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) while (*v && *v != ' ') v++; *v = 0; - d->vector_var[i] = atof (w); + (&d->vector_var)[i] = atof (w); w = v = v + 1; } free (string); diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index af2731d71..8a4784b2d 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -138,7 +138,7 @@ Mod_LoadAliasFrame (void *pin, int *posenum, maliasframedesc_t *frame, pdaliasframe = (daliasframe_t *) pin; - strncpy (frame->name, pdaliasframe->name, sizeof (frame->name)); + memcpy (frame->name, pdaliasframe->name, sizeof (frame->name)); frame->name[sizeof (frame->name) - 1] = 0; frame->firstpose = (*posenum); frame->numposes = 1; diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index cff92eb4e..98d9722ba 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -85,7 +85,7 @@ table_get (hash_resources_t *res, int index) PR_RESGET(res->table_map, index); } -static inline int +static inline int __attribute__((pure)) table_index (hash_resources_t *res, bi_hashtab_t *table) { PR_RESINDEX(res->table_map, table); diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index 9b026c90f..51c7bcf16 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -80,7 +80,7 @@ msgbuf_get (msgbuf_resources_t *res, int index) PR_RESGET(res->msgbuf_map, index); } -static inline int +static inline int __attribute__((pure)) msgbuf_index (msgbuf_resources_t *res, msgbuf_t *msgbuf) { PR_RESINDEX(res->msgbuf_map, msgbuf); @@ -358,8 +358,7 @@ static void bi_MsgBuf_ReadCoordAngleV (progs_t *pr) { msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); - MSG_ReadCoordAngleV (&mb->msg, P_GPOINTER (pr, 1)->vector_var, - P_GPOINTER (pr, 2)->vector_var); + MSG_ReadCoordAngleV (&mb->msg, P_VECTOR (pr, 1), P_VECTOR (pr, 2)); } static void diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index baa8fe73b..155124b9f 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -108,7 +108,7 @@ dtable_get (probj_t *probj, int index) PR_RESGET (probj->dtables, index); } -static inline int +static inline int __attribute__((pure)) dtable_index (probj_t *probj, dtable_t *dtable) { PR_RESINDEX (probj->dtables, dtable); diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 9732b75c3..b71af2ead 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -84,7 +84,7 @@ plist_get (plist_resources_t *res, unsigned index) PR_RESGET(res->plist_map, index); } -static inline int +static inline int __attribute__((pure)) plist_index (plist_resources_t *res, bi_plist_t *plist) { PR_RESINDEX(res->plist_map, plist); diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index d96c433a2..2f625a949 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -77,7 +77,7 @@ handle_get (qfile_resources_t *res, int index) PR_RESGET(res->handle_map, index); } -static inline int +static inline int __attribute__((pure)) handle_index (qfile_resources_t *res, qfile_t *handle) { PR_RESINDEX(res->handle_map, handle); diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index ff5b2ab0a..7c2cd6666 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -78,7 +78,7 @@ script_get (script_resources_t *res, int index) PR_RESGET(res->scripts, index); } -static inline int +static inline int __attribute__((pure)) script_index (script_resources_t *res, rua_script_t *script) { PR_RESINDEX(res->scripts, script); diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 0fdd964e7..4e3ea732d 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -98,7 +98,7 @@ res_set_get (set_resources_t *res, int index) PR_RESGET(res->set_map, index); } -static inline int +static inline int __attribute__((pure)) res_set_index (set_resources_t *res, bi_set_t *set) { PR_RESINDEX(res->set_map, set); @@ -128,7 +128,7 @@ res_set_iter_get (set_resources_t *res, int index) PR_RESGET(res->set_iter_map, index); } -static inline int +static inline int __attribute__((pure)) res_set_iter_index (set_resources_t *res, bi_set_iter_t *set_iter) { PR_RESINDEX(res->set_iter_map, set_iter); diff --git a/libs/util/zone.c b/libs/util/zone.c index 40af412ba..f52226d55 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -577,7 +577,8 @@ Hunk_AllocName (int size, const char *name) h->size = size; h->sentinal = HUNK_SENTINAL; - strncpy (h->name, name, 8); + memcpy (h->name, name, 8); + h->name[7] = 0; return (void *) (h + 1); } diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index aba1de6ea..3f2925fba 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -101,7 +101,7 @@ qpic_get (draw_resources_t *res, int index) PR_RESGET (res->qpic_map, index); } -static inline int +static inline int __attribute__((pure)) qpic_index (draw_resources_t *res, qpic_res_t *qp) { PR_RESINDEX (res->qpic_map, qp); diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index dc6aa39d6..b1bf22960 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -48,9 +48,15 @@ -(void) writeTable: (PLItem *) parse { - PLItem *field_dict = [parse getObjectForKey:[self name]]; + string name = [self name]; + PLItem *field_dict = [parse getObjectForKey:name]; PLItem *field_defs = [field_dict allKeys]; Type *field_type; + PLItem *new_name = [field_dict getObjectForKey:".name"]; + + if (new_name) { + name = [new_name string]; + } if (field_defs) { PLItem *field_def; @@ -65,7 +71,7 @@ string size_field = nil; string value_field = nil; - if (!type_desc) { + if (!type_desc || str_mid(field_name, 0, 1) == ".") { continue; } type_record = [[type_desc getObjectAtIndex:0] string]; @@ -73,22 +79,22 @@ field_type = [[Type lookup: type_type] dereference]; fprintf (output_file, "static parse_%s_t parse_%s_%s_data = {\n", - type_record, [self name], field_name); + type_record, name, field_name); fprintf (output_file, "\t%s,\n", [field_type parseType]); fprintf (output_file, "\tsizeof (%s),\n", type_type); fprintf (output_file, "\tparse_%s,\n", type_type); if (type_record == "single") { value_field = [[field_def getObjectForKey:"value"] string]; fprintf (output_file, "\tfield_offset (%s, %s),\n", - [self name], value_field); + name, value_field); } else { value_field = [[field_def getObjectForKey:"values"] string]; size_field = [[field_def getObjectForKey:"size"] string]; fprintf (output_file, "\tfield_offset (%s, %s),\n", - [self name], value_field); + name, value_field); if (size_field) { fprintf (output_file, "\tfield_offset (%s, %s),\n", - [self name], size_field); + name, size_field); } else { fprintf (output_file, "\t-1,\n"); } @@ -96,13 +102,16 @@ fprintf (output_file, "};\n"); } } - fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self name]); + fprintf (output_file, "static plfield_t %s_fields[] = {\n", name); if (field_defs) { PLItem *field_def; qfot_var_t *field; for (int i = [field_defs count]; i-- > 0; ) { string field_name = [[field_defs getObjectAtIndex:i] string]; + if (str_mid(field_name, 0, 1) == ".") { + continue; + } field_def = [field_dict getObjectForKey:field_name]; if ([field_def string] == "auto") { field = [self findField:field_name]; @@ -112,7 +121,7 @@ field_type = [Type findType: field.type]; fprintf (output_file, "\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n", - field_name, [self name], field_name, + field_name, name, field_name, [field_type parseType], [field_type parseFunc], [field_type parseData]); } else { @@ -133,7 +142,7 @@ fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", field_name, parseType, type_record, - [self name], field_name); + name, field_name); } } } else { @@ -145,7 +154,7 @@ field_type = [Type findType: field.type]; fprintf (output_file, "\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n", - field.name, [self name], field.name, + field.name, name, field.name, [field_type parseType], [field_type parseFunc], [field_type parseData]); } @@ -154,12 +163,14 @@ fprintf (output_file, "};\n"); fprintf (output_file, "static int parse_%s (const plfield_t *field," - " const plitem_t *item, void *data, plitem_t *messages)\n", - [self name]); + " const plitem_t *item, void *data, plitem_t *messages," + " void *context)\n", + name); fprintf (output_file, "{\n"); fprintf (output_file, - "\treturn PL_ParseDictionary (%s_fields, item, data, messages);\n", - [self name]); + "\treturn PL_ParseDictionary (%s_fields, item, data, messages," + " context);\n", + name); fprintf (output_file, "}\n"); } diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 07a8c8f7c..3d798ac16 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -208,7 +208,7 @@ extern progs_t sv_pr_state; #define SVstring(e,f) SVFIELD (e, f, string) #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) -#define SVvector(e,f) SVFIELD (e, f, vector) +#define SVvector(e,f) (&SVFIELD (e, f, vector)) #define SVinteger(e,f) SVFIELD (e, f, integer) #if TYPECHECK_PROGS #define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index 18bdde503..88fe18c24 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -193,7 +193,7 @@ extern progs_t sv_pr_state; #define SVstring(e,f) SVFIELD (e, f, string) #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) -#define SVvector(e,f) SVFIELD (e, f, vector) +#define SVvector(e,f) (&SVFIELD (e, f, vector)) #define SVinteger(e,f) SVFIELD (e, f, integer) #if TYPECHECK_PROGS #define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) diff --git a/qw/source/pmove.c b/qw/source/pmove.c index 637528afa..358409bc5 100644 --- a/qw/source/pmove.c +++ b/qw/source/pmove.c @@ -738,7 +738,7 @@ SpectatorMove (void) // friction speed = DotProduct (pmove.velocity, pmove.velocity); if (speed < 1) { - VectorZero (pmove.velocity) + VectorZero (pmove.velocity); } else { speed = sqrt (speed); drop = 0; diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 276ee2875..7ef651a15 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -101,8 +101,8 @@ free_edict (progs_t *pr, edict_t *ent) ent->v[sv_fields.frame].float_var = 0; ent->v[sv_fields.nextthink].float_var = -1; ent->v[sv_fields.solid].float_var = 0; - memset (ent->v[sv_fields.origin].vector_var, 0, 3*sizeof (float)); - memset (ent->v[sv_fields.angles].vector_var, 0, 3*sizeof (float)); + memset (&ent->v[sv_fields.origin].vector_var, 0, 3*sizeof (float)); + memset (&ent->v[sv_fields.angles].vector_var, 0, 3*sizeof (float)); } else { ED_ClearEdict (pr, ent, 0); } diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 8f543f493..4f2044cf7 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -148,7 +148,7 @@ window_get (qwaq_resources_t *res, unsigned index) PR_RESGET(res->window_map, index); } -static inline int +static inline int __attribute__((pure)) window_index (qwaq_resources_t *res, window_t *win) { PR_RESINDEX (res->window_map, win); @@ -194,7 +194,7 @@ panel_get (qwaq_resources_t *res, unsigned index) PR_RESGET(res->panel_map, index); } -static inline int +static inline int __attribute__((pure)) panel_index (qwaq_resources_t *res, panel_t *win) { PR_RESINDEX (res->panel_map, win); diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index d16ac6f97..19b215e38 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -94,7 +94,7 @@ target_get (qwaq_debug_t *debug, unsigned index) PR_RESGET (debug->targets, index); } -static inline int +static inline int __attribute__((pure)) target_index (qwaq_debug_t *debug, qwaq_target_t *target) { PR_RESINDEX (debug->targets, target); diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index 12cde52ab..d687103d3 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -52,7 +52,7 @@ editbuffer_get (qwaq_ebresources_t *res, unsigned index) PR_RESGET (res->buffers, index); } -static inline int +static inline int __attribute__((pure)) editbuffer_index (qwaq_ebresources_t *res, editbuffer_t *buffer) { PR_RESINDEX (res->buffers, buffer); diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 0a4faf28b..f493e8528 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -86,6 +86,7 @@ open_file (const char *path, int *len) if (!file) { strerror_r(errno, errbuff, sizeof (errbuff)); Sys_Printf ("%s\n", errbuff); + *len = 0; return 0; } *len = Qfilesize (file); diff --git a/tools/qfbsp/source/outside.c b/tools/qfbsp/source/outside.c index 15da18dba..d7ba0d142 100644 --- a/tools/qfbsp/source/outside.c +++ b/tools/qfbsp/source/outside.c @@ -180,6 +180,8 @@ MarkLeakTrail2 (void) vec3_t wc, pwc; const vec_t *v; + VectorZero (wc); + leakfile = fopen (options.pointfile, "w"); if (!leakfile) Sys_Error ("Couldn't open %s\n", options.pointfile); diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 6fac011ce..9d552ab3e 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -101,8 +101,8 @@ extern pr_info_t pr; #define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset)) #define D_FLOAT(d) D_var (float, d) #define D_INT(d) D_var (integer, d) -#define D_VECTOR(d) D_var (vector, d) -#define D_QUAT(d) D_var (quat, d) +#define D_VECTOR(d) (&D_var (vector, d)) +#define D_QUAT(d) (&D_var (quat, d)) #define D_STRING(d) D_var (string, d) #define D_GETSTR(d) GETSTR (D_STRING (d)) #define D_FUNCTION(d) D_var (func, d) diff --git a/tools/qflight/include/noise.h b/tools/qflight/include/noise.h index be63d9de1..0b118d17a 100644 --- a/tools/qflight/include/noise.h +++ b/tools/qflight/include/noise.h @@ -34,7 +34,7 @@ ///@{ float noise3d (vec3_t v, int num) __attribute__((pure)); -float noiseXYZ (float x, float y, float z, int num) __attribute__((pure)); +float noiseXYZ (float x, float y, float z, int num) __attribute__((const)); float noise_scaled (vec3_t v, float s, int num) __attribute__((pure)); float noise_perlin (vec3_t v, float p, int num) __attribute__((pure)); void snap_vector (vec3_t v_old, vec3_t v_new, float scale); diff --git a/tools/qfmodelgen/source/modelgen.c b/tools/qfmodelgen/source/modelgen.c index 5d3eee4d0..a4b18b1ac 100644 --- a/tools/qfmodelgen/source/modelgen.c +++ b/tools/qfmodelgen/source/modelgen.c @@ -178,15 +178,17 @@ SetQdirFromPath (char *path) static const char * ExpandPath (const char *path) { - static char full[1024]; + static dstring_t *full; - //FIXME buffer overflow central + if (!full) { + full = dstring_new(); + } //if (!qdir) // Sys_Error ("ExpandPath called without qdir set"); if (path[0] == '/' || path[0] == '\\' || path[1] == ':') return path; - sprintf (full, "%s%s", qdir, path); - return full; + dsprintf (full, "%s%s", qdir, path); + return full->str; } static void From ebcef5c8a46b7d199df88ac9d4f3f1ae5b5b6cbd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 02:32:29 +0900 Subject: [PATCH 1101/3664] [util] Deal with gcc optimizing out isnan checks This occurs because of -ffast-math, but I need to investigate how much of an impact disabling it has on QF's performance. --- libs/util/test/test-quat.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index 11cc5b617..8e4738449 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -239,11 +239,16 @@ fail: return 0; } +// XXX FIXME see usage in test_rotation4. need to investigate whether +// -ffast-math is any real benefit +#define ISNAN(x) (((x) & 0x7f800000) == 0x7f800000 && ((x) & 0x7fffff)) + static int test_rotation4 (const vec3_t a, const vec3_t b, const quat_t expect) { int i; - quat_t quat; + union { int x[4]; vec_t q[4]; } q; + vec_t *quat = q.q; vec3_t t; vec_t d = 0; @@ -258,13 +263,19 @@ test_rotation4 (const vec3_t a, const vec3_t b, const quat_t expect) } // expect NaN for the vector components because the vectors are // anti-parallel and thus the rotation axis is undefined - if (!(isnan(quat[0]) && isnan(quat[1]) && isnan(quat[2]))) { + //XXX FIXME(?) still using -ffast-math which implies + // -ffinite-math-only which in turn disables nan/inf checks, so have + // to do it by hand + // if (!(isnan(quat[0]) && isnan(quat[1]) && isnan(quat[2]))) { + if (!(ISNAN(q.x[0]) && ISNAN(q.x[1]) && ISNAN(q.x[2]))) { goto fail; } } else { // the vectors are not anti-parallel and thus the rotation axis is // defined, so NaN is invalid - if (isnan(quat[0]) || isnan(quat[1]) || isnan(quat[2])) { + // XXX FIXME see above + //if (isnan(quat[0]) || isnan(quat[1]) || isnan(quat[2])) { + if (ISNAN(q.x[0]) || ISNAN(q.x[1]) || ISNAN(q.x[2])) { goto fail; } for (i = 0; i < 4; i++) { @@ -288,6 +299,7 @@ fail: printf ("%11.9g %11.9g %11.9g\n", VectorExpand(a)); printf ("%11.9g %11.9g %11.9g\n", VectorExpand(b)); printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand(quat)); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand(expect)); printf ("%11.9g %11.9g %11.9g\n", VectorExpand(t)); printf ("%11.9g\n", d); return 0; From 591667c36dbcd71f31269ed78285ced5a191c549 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 13:55:54 +0900 Subject: [PATCH 1102/3664] [util] Add a context parameter to the plist parsers Not used by the dict/array parsers themselves, but is passed on to any value parser callbacks for their own use. --- include/QF/qfplist.h | 9 ++++++--- libs/util/qfplist.c | 10 +++++----- libs/video/renderer/vulkan/vkparse.c | 16 ++++++++-------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 3fdfa7825..70a1b8302 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -80,12 +80,14 @@ struct plfield_s; error messages. Messages should be strings, but no checking is done: it is up to the top-level caller to parse out the messages. + \param context Additional context data passed to the parser. \return 0 for error, 1 for success. See \a PL_ParseDictionary. */ typedef int (*plparser_t) (const struct plfield_s *field, const struct plitem_s *item, void *data, - struct plitem_s *messages); + struct plitem_s *messages, + void *context); /** A field to be parsed from a dictionary item. @@ -320,12 +322,13 @@ void PL_Free (plitem_t *item); message format is "[line number]: [message]". If the line number is 0, then the actual line is unknown (due to the source item not being parsed from a file or string). + \param context Additional context data passed to the parser. \return 0 if there are any errors, 1 if there are no errors. */ int PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, - void *data, plitem_t *messages); + void *data, plitem_t *messages, void *context); int PL_ParseArray (const plfield_t *fields, const plitem_t *dict, - void *data, plitem_t *messages); + void *data, plitem_t *messages, void *context); void __attribute__((format(printf,3,4))) PL_Message (plitem_t *messages, const plitem_t *item, const char *fmt, ...); diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 8eb7e867c..2f71d42bc 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1086,7 +1086,7 @@ PL_Message (plitem_t *messages, const plitem_t *item, const char *fmt, ...) static int pl_default_parser (const plfield_t *field, const plitem_t *item, void *data, - plitem_t *messages) + plitem_t *messages, void *context) { switch (field->type) { case QFDictionary: @@ -1125,7 +1125,7 @@ pl_default_parser (const plfield_t *field, const plitem_t *item, void *data, VISIBLE int PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, - plitem_t *messages) + plitem_t *messages, void *context) { void **list, **l; dictkey_t *current; @@ -1161,7 +1161,7 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, pl_types[item->type]); result = 0; } else { - if (!parser (f, item, flddata, messages)) { + if (!parser (f, item, flddata, messages, context)) { result = 0; } } @@ -1180,7 +1180,7 @@ PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, VISIBLE int PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, - plitem_t *messages) + plitem_t *messages, void *context) { int result = 1; plparser_t parser; @@ -1219,7 +1219,7 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, pl_types[item->type]); result = 0; } else { - if (!parser (&f, item, eledata, messages)) { + if (!parser (&f, item, eledata, messages, context)) { result = 0; } } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 7fb137b29..a4b037202 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -97,7 +97,7 @@ static int find_enum (const char *valstr, enumval_t *enumval, int *val) } static int parse_uint32_t (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages) + void *data, plitem_t *messages, void *ctx) { int ret = 1; const char *valstr = PL_String (item); @@ -125,7 +125,7 @@ static int parse_uint32_t (const plfield_t *field, const plitem_t *item, } static int parse_enum (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages) + void *data, plitem_t *messages, void *ctx) { int ret = 1; int val; @@ -144,7 +144,7 @@ static int parse_enum (const plfield_t *field, const plitem_t *item, } static int parse_flags (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages) + void *data, plitem_t *messages, void *ctx) { int ret = 1; int val; @@ -165,7 +165,7 @@ static int parse_flags (const plfield_t *field, const plitem_t *item, } static int parse_single (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages) + void *data, plitem_t *messages, void *ctx) { __auto_type single = (parse_single_t *) field->data; void *flddata = (byte *)data + single->value_offset; @@ -180,7 +180,7 @@ static int parse_single (const plfield_t *field, const plitem_t *item, plfield_t f = { 0, 0, single->type, single->parser, 0 }; void *value = calloc (1, single->stride); - if (!single->parser (&f, item, value, messages)) { + if (!single->parser (&f, item, value, messages, ctx)) { free (value); return 0; } @@ -190,7 +190,7 @@ static int parse_single (const plfield_t *field, const plitem_t *item, } static int parse_array (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages) + void *data, plitem_t *messages, void *ctx) { __auto_type array = (parse_array_t *) field->data; __auto_type value = (void **) ((byte *)data + array->value_offset); @@ -213,7 +213,7 @@ static int parse_array (const plfield_t *field, const plitem_t *item, // field->data, data); //Sys_Printf (" %d %zd %p %zd %zd\n", array->type, array->stride, // array->parser, array->value_offset, array->size_offset); - if (!PL_ParseArray (&f, item, &arr, messages)) { + if (!PL_ParseArray (&f, item, &arr, messages, ctx)) { return 0; } *value = malloc (array->stride * arr->size); @@ -275,7 +275,7 @@ QFV_ParseRenderPass (qfv_device_t *device, plitem_t *plist) VkRenderPass renderpass; if (!PL_ParseDictionary (renderpass_fields, plist, - &renderpass_data, messages)) { + &renderpass_data, messages, 0)) { for (int i = 0; i < PL_A_NumObjects (messages); i++) { Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } From f3682638d4757b7b34a5c005a16110a2c9aabfb5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 14:06:21 +0900 Subject: [PATCH 1103/3664] [util] Add a mini expression parser It is capable of parsing single expressions with fairly simple operations. It current supports ints, enums, cvars and (external) data structs. It is also thread-safe (in theory, needs proper testing) and the memory it uses can be mass-freed. --- include/QF/cexpr.h | 118 +++++++++++++ libs/util/Makemodule.am | 13 ++ libs/util/cexpr-lex.l | 281 +++++++++++++++++++++++++++++++ libs/util/cexpr-parse.y | 219 ++++++++++++++++++++++++ libs/util/cexpr-type.c | 314 +++++++++++++++++++++++++++++++++++ libs/util/cexpr-vars.c | 154 +++++++++++++++++ libs/util/test/Makemodule.am | 5 + libs/util/test/test-cexpr.c | 81 +++++++++ 8 files changed, 1185 insertions(+) create mode 100644 include/QF/cexpr.h create mode 100644 libs/util/cexpr-lex.l create mode 100644 libs/util/cexpr-parse.y create mode 100644 libs/util/cexpr-type.c create mode 100644 libs/util/cexpr-vars.c create mode 100644 libs/util/test/test-cexpr.c diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h new file mode 100644 index 000000000..fcdeaad57 --- /dev/null +++ b/include/QF/cexpr.h @@ -0,0 +1,118 @@ +/* + cexpr.h + + Config expression parser. Or concurrent. + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __expr_h +#define __expr_h + +#include + +struct exprval_s; +struct exprctx_s; + +typedef struct binop_s { + int op; + struct exprtype_s *other; + struct exprtype_s *result; + void (*func) (const struct exprval_s *val1, + const struct exprval_s *val2, + struct exprval_s *result, + struct exprctx_s *context); +} binop_t; + +typedef struct unop_s { + int op; + struct exprtype_s *result; + void (*func) (const struct exprval_s *val, struct exprval_s *result, + struct exprctx_s *context); +} unop_t; + +typedef struct exprtype_s { + const char *name; + size_t size; + binop_t *binops; + unop_t *unops; + void *data; +} exprtype_t; + +typedef struct exprval_s { + exprtype_t *type; + void *value; +} exprval_t; + +typedef struct exprsym_s { + const char *name; + exprtype_t *type; + void *value; + struct exprsym_s *next; +} exprsym_t; + +typedef struct exprtab_s { + exprsym_t *symbols; + struct hashtab_s *tab; +} exprtab_t; + +typedef struct exprctx_s { + exprval_t *result; + exprtab_t *symtab; // directly accessible symbols + exprtab_t *external_variables; // accessible via $id + struct memsuper_s *memsuper; + const struct plitem_s *item; + struct plitem_s *messages; + struct hashlink_s *hashlinks; +} exprctx_t; + +typedef struct exprenum_s { + exprtype_t *type; + exprtab_t *symtab; +} exprenum_t; + +int cexpr_parse_enum (exprenum_t *enm, const char *str, + const exprctx_t *context, void *data); +binop_t *cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) __attribute__((pure)); +exprval_t *cexpr_value (exprtype_t *type, exprctx_t *ctx); +exprval_t *cexpr_value_reference (exprtype_t *type, void *data, exprctx_t *ctx); +int cexpr_eval_string (const char *str, exprctx_t *context); +void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(printf,2,3))); + +void cexpr_struct_getfield (const exprval_t *a, const exprval_t *b, + exprval_t *c, exprctx_t *ctx); +exprval_t *cexpr_cvar (const char *name, exprctx_t *ctx); +exprval_t *cexpr_cvar_struct (exprctx_t *ctx); + +void cexpr_init_symtab (exprtab_t *symtab, exprctx_t *ctx); + +char *cexpr_yyget_text (void *scanner); + +extern exprtype_t cexpr_int; +extern exprtype_t cexpr_uint; +extern exprtype_t cexpr_float; +extern exprtype_t cexpr_double; +extern exprtype_t cexpr_exprval; +extern exprtype_t cexpr_field; + +extern binop_t cexpr_struct_binops[]; + +#endif diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am index af99b15d3..f554289be 100644 --- a/libs/util/Makemodule.am +++ b/libs/util/Makemodule.am @@ -43,6 +43,10 @@ libs_util_libQFutil_la_SOURCES= \ libs/util/bspfile.c \ libs/util/buildnum.c \ libs/util/cbuf.c \ + libs/util/cexpr-lex.l \ + libs/util/cexpr-parse.y \ + libs/util/cexpr-type.c \ + libs/util/cexpr-vars.c \ libs/util/checksum.c \ libs/util/cmd.c \ libs/util/cmem.c \ @@ -82,4 +86,13 @@ libs_util_libQFutil_la_SOURCES= \ libs/util/zone.c \ $(dirent) $(fnmatch) $(getopt) +BUILT_SOURCES += \ + libs/util/cexpr-lex.c \ + libs/util/cexpr-parse.c + +libs/util/cexpr-parse.c: libs/util/cexpr-parse.y + $(AM_V_YACC)$(YACCCOMPILE) $< -o $@ +libs/util/cexpr-lex.c: libs/util/cexpr-lex.l libs/util/cexpr-parse.h + $(AM_V_LEX)$(LEXCOMPILE) -o$@ $< + EXTRA_DIST += $(fnmatch_src) $(getopt_src) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l new file mode 100644 index 000000000..cfb1b99c6 --- /dev/null +++ b/libs/util/cexpr-lex.l @@ -0,0 +1,281 @@ +/* + cexpr-lex.l + + Config expression parser. Or concurrent. + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +%option bison-bridge +%option reentrant +%option prefix="cexpr_yy" +%option noyywrap + +%{ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include +#include + +#include "QF/cmem.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/qfplist.h" +#include "QF/sys.h" + +#include "QF/cexpr.h" +#include "libs/util/cexpr-parse.h" + +#define YY_NO_INPUT +#define YY_NO_UNPUT + +#define YYSTYPE CEXPR_YYSTYPE +#define YY_EXTRA_TYPE exprctx_t * + +exprctx_t *cexpr_yyget_extra (yyscan_t yyscanner) __attribute__((pure)); +int cexpr_yyget_lineno (yyscan_t yyscanner) __attribute__((pure)); +int cexpr_yyget_column (yyscan_t yyscanner) __attribute__((pure)); +YYSTYPE *cexpr_yyget_lval (yyscan_t yyscanner) __attribute__((pure)); +int cexpr_yyget_debug (yyscan_t yyscanner) __attribute__((pure)); +char *cexpr_yyget_text (yyscan_t yyscanner) __attribute__((pure)); +int cexpr_yyget_leng (yyscan_t yyscanner) __attribute__((pure)); +FILE *cexpr_yyget_out (yyscan_t yyscanner) __attribute__((pure)); +FILE *cexpr_yyget_in (yyscan_t yyscanner) __attribute__((pure)); + +static exprval_t *parse_int (const char *str, exprctx_t *context); +static exprval_t *parse_uint (const char *str, exprctx_t *context); +static exprval_t *parse_float (const char *str, exprctx_t *context); +static exprval_t *parse_double (const char *str, exprctx_t *context); +static exprsym_t *parse_name (const char *str, exprctx_t *context); +static exprval_t *parse_variable (const char *str, exprctx_t *context); + +VISIBLE void +cexpr_error(exprctx_t *ctx, const char *fmt, ...) +{ + va_list args; + dstring_t *string; + + string = dstring_new (); + + va_start (args, fmt); + dvsprintf (string, fmt, args); + va_end (args); + + if (ctx->messages) { + PL_Message (ctx->messages, ctx->item, "%s", string->str); + } else { + Sys_Printf ("%s\n", string->str); + } + dstring_delete (string); +} + +%} + +s [ \t] +m [\-+] +D [0-9] +B [01] +X [0-9a-fA-F] +ID [a-zA-Z_][a-zA-Z_0-9]* +FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)? +FLOATf {FLOAT}[fF] +FLOATd {FLOAT}[dD] +INT ({D}+|0[xX]{X}+|0[bB]{B}) +STRING \"(\\.|[^"\\])*\" + +%% +%{ + __auto_type context = yyget_extra (yyscanner); +%} + +{INT}+ { + yylval->value = parse_int (yytext, context); + return VALUE; + } + +{INT}+[uU] { + yylval->value = parse_uint (yytext, context); + return VALUE; + } + +{FLOAT} { + yylval->value = parse_double (yytext, context); + return VALUE; + } +{FLOATf} { + yylval->value = parse_float (yytext, context); + return VALUE; + } +{FLOATd} { + yylval->value = parse_double (yytext, context); + return VALUE; + } + +{ID} { + yylval->symbol = parse_name (yytext, context); + return NAME; + } + +\${ID} { + yylval->value = parse_variable (yytext + 1, context); + return VALUE; + } + +{STRING} { + } +@ return '@'; + +'(\\[^xX0-7\r\n]|[^'\r\n]|\\[xX][0-9A-Fa-f]+|\\[0-7]+)*' { + } + +[+\-*/&|^%]= { + } + +"%%=" { + } + +"<<=" { + } + +">>=" { + } + +[!(){}.*/&|^~+\-=\[\];,#%?:] { + return yytext[0]; + } + +"%%" { + } + +"<<" return SHL; +">>" return SHR; + +"&&" return AND; +"||" return OR; +"==" return EQ; +"!=" return NE; +"<=" return LE; +">=" return GE; +"<" return LT; +">" return GT; + +"++" { + } + +"--" { + } + +<*>\r*\n { + } + +<*>{s}* /* skip */ + +<*>. cexpr_error (context, "all your typo are belong to us"); + +%% + +VISIBLE int +cexpr_eval_string (const char *str, exprctx_t *context) +{ + int status; + yyscan_t scanner; + cexpr_yypstate *ps = cexpr_yypstate_new (); + + yylex_init_extra (context, &scanner); + yy_scan_string (str, scanner); + + do { + CEXPR_YYSTYPE lval; + int token = yylex (&lval, scanner); + status = cexpr_yypush_parse (ps, token, &lval, scanner, context); + } while (status == YYPUSH_MORE); + + yylex_destroy (scanner); + cexpr_yypstate_delete (ps); + return status; +} + +static exprval_t *parse_int (const char *str, exprctx_t *context) +{ + exprval_t *val = cexpr_value (&cexpr_int, context); + *(int *) val->value = strtoimax (str, 0, 0); + return val; +} + +static exprval_t *parse_uint (const char *str, exprctx_t *context) +{ + exprval_t *val = cexpr_value (&cexpr_uint, context); + *(unsigned *) val->value = strtoumax (str, 0, 0); + return val; +} + +static exprval_t *parse_float (const char *str, exprctx_t *context) +{ + exprval_t *val = cexpr_value (&cexpr_int, context); + *(float *) val->value = strtof (str, 0); + return val; +} + +static exprval_t *parse_double (const char *str, exprctx_t *context) +{ + exprval_t *val = cexpr_value (&cexpr_int, context); + *(double *) val->value = strtod (str, 0); + return val; +} + +static exprsym_t * +parse_name (const char *name, exprctx_t *context) +{ + exprtab_t *symtab = context->symtab; + + __auto_type sym = (exprsym_t *) Hash_Find (symtab->tab, name); + return sym; +} + +static exprval_t * +parse_variable (const char *name, exprctx_t *context) +{ + exprval_t *val = 0; + if (strcmp (name, "cvars") == 0) { + val = cexpr_cvar_struct (context); + } else { + exprtab_t *symtab = context->external_variables; + __auto_type sym = (exprsym_t *) Hash_Find (symtab->tab, name); + if (sym) { + val = cexpr_value_reference (sym->type, sym->value, context); + } else { + val = cexpr_cvar (name, context); + } + } + if (!val) { + cexpr_error (context, "undefined variable %s", name); + } + return val; +} diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y new file mode 100644 index 000000000..ac41c549c --- /dev/null +++ b/libs/util/cexpr-parse.y @@ -0,0 +1,219 @@ +/* + cexpr-parse.y + + Config expression parser. Or concurrent. + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +%define api.prefix {cexpr_yy} +%define api.pure full +%define api.push-pull push +%parse-param {void *scanner} {exprctx_t *context} + +%{ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/cmem.h" +#include "QF/hash.h" +#include "QF/qfplist.h" +#include "QF/sys.h" + +#include "QF/cexpr.h" + +static void assign_expr (exprval_t *dst, const exprval_t *src, + exprctx_t *context); +static exprval_t *binary_expr (int op, const exprval_t *a, const exprval_t *b, + exprctx_t *context); +static exprval_t *field_expr (const exprval_t *a, const exprval_t *b, + exprctx_t *context); + +static void +yyerror (void *scanner, exprctx_t *context, const char *s) +{ + cexpr_error (context, "%s before %s\n", s, cexpr_yyget_text (scanner)); +} + +%} + +%left COMMA +%right '=' ASX +%right '?' ':' +%left OR +%left AND +%left '|' +%left '^' +%left '&' +%left EQ NE +%left LE GE LT GT + +%left SHL SHR +%left '+' '-' +%left '*' '/' '%' MOD +%right SIZEOF UNARY INCOP +%left HYPERUNARY +%left '.' '(' '[' + +%token NAME +%token VALUE + +%type expr field + +%union { + int op; + exprsym_t *symbol; + exprval_t *value; + const char *string; +} + +%% + +start + : expr { assign_expr (context->result, $1, context); } + ; + +expr + : expr SHL expr { $$ = binary_expr (SHL, $1, $3, context); } + | expr SHR expr { $$ = binary_expr (SHR, $1, $3, context); } + | expr '+' expr { $$ = binary_expr ('+', $1, $3, context); } + | expr '-' expr { $$ = binary_expr ('-', $1, $3, context); } + | expr '*' expr { $$ = binary_expr ('*', $1, $3, context); } + | expr '/' expr { $$ = binary_expr ('/', $1, $3, context); } + | expr '&' expr { $$ = binary_expr ('&', $1, $3, context); } + | expr '|' expr { $$ = binary_expr ('|', $1, $3, context); } + | expr '^' expr { $$ = binary_expr ('^', $1, $3, context); } + | expr '%' expr { $$ = binary_expr ('%', $1, $3, context); } + | expr '.' field { $$ = field_expr ($1, $3, context); } + | expr MOD expr { $$ = binary_expr (MOD, $1, $3, context); } + | NAME + { + if ($1) { + $$ = (exprval_t *) cmemalloc (context->memsuper, sizeof (*$$)); + $$->type = $1->type; + $$->value = $1->value; + } else { + cexpr_error (context, "undefined identifier %s", + cexpr_yyget_text (scanner)); + } + } + | VALUE + ; + +field + : NAME + { + exprctx_t *ctx = context; + const char *name = cexpr_yyget_text (scanner); + size_t size = strlen (name) + 1; + //FIXME reuse strings + $$ = (exprval_t *) cmemalloc (ctx->memsuper, sizeof (exprval_t)); + $$->type = &cexpr_field; + $$->value = cmemalloc (ctx->memsuper, size); + memcpy ($$->value, name, size); + } + ; + +%% + +static void +assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context) +{ + binop_t *binop; + if (!src) { + return; + } + for (binop = dst->type->binops; binop && binop->op; binop++) { + if (binop->op == '=' && binop->other == src->type) { + break; + } + } + if (binop && binop->op) { + binop->func (dst, src, dst, context); + } else { + if (dst->type != src->type) { + cexpr_error (context, + "type mismatch in expression result: %s = %s\n", + dst->type->name, src->type->name); + return; + } + memcpy (dst->value, src->value, dst->type->size); + } +} + +static exprval_t * +binary_expr (int op, const exprval_t *a, const exprval_t *b, + exprctx_t *context) +{ + binop_t *binop; + + for (binop = a->type->binops; binop->op; binop++) { + exprtype_t *otype = binop->other; + if (!otype) { + otype = a->type; + } + if (binop->op == op && binop->other == b->type) { + break; + } + } + exprtype_t *rtype = binop->result; + if (!rtype) { + rtype = a->type; + } + exprval_t *result = cexpr_value (rtype, context); + if (!binop->op) { + cexpr_error (context, "invalid binary expression: %s %c %s\n", + a->type->name, op, b->type->name); + } else { + binop->func (a, b, result, context); + } + return result; +} + +static exprval_t * +field_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context) +{ + binop_t *binop; + exprval_t *result = 0; + + for (binop = a->type->binops; binop->op; binop++) { + if (binop->op == '.' && binop->other == b->type) { + break; + } + } + if (!binop->op) { + cexpr_error (context, "invalid binary expression: %s.%s\n", + a->type->name, b->type->name); + } else { + exprval_t c = { 0, &result }; + binop->func (a, b, &c, context); + } + return result; +} diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c new file mode 100644 index 000000000..35c62ee85 --- /dev/null +++ b/libs/util/cexpr-type.c @@ -0,0 +1,314 @@ +/* + cexpr-type.c + + Config expression parser. Or concurrent. + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/cexpr.h" + +#include "libs/util/cexpr-parse.h" + +#define BINOP(pre, opname, type, op) \ +static void \ +pre##_##opname (const exprval_t *a, const exprval_t *b, exprval_t *c, \ + exprctx_t *ctx) \ +{ \ + (*(type *) c->value) = (*(type *) a->value) op (*(type *) b->value); \ +} + +#define UNOP(pre, opname, type, op) \ +static void \ +pre##_##opname (const exprval_t *a, exprval_t *b, exprctx_t *ctx) \ +{ \ + (*(type *) b->value) = op (*(type *) a->value); \ +} + +BINOP(int, shl, int, <<) +BINOP(int, shr, int, >>) +BINOP(int, add, int, +) +BINOP(int, sub, int, -) +BINOP(int, mul, int, *) +BINOP(int, div, int, /) +BINOP(int, band, int, &) +BINOP(int, bor, int, |) +BINOP(int, xor, int, ^) +BINOP(int, rem, int, %) + +UNOP(int, pos, int, +) +UNOP(int, neg, int, -) +UNOP(int, tnot, int, !) +UNOP(int, bnot, int, ~) + +static void +int_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, + exprctx_t *ctx) +{ + // implement true modulo for integers: + // 5 mod 3 = 2 + // -5 mod 3 = 1 + // 5 mod -3 = -1 + // -5 mod -3 = -2 + int a = *(int *) val1->value; + int b = *(int *) val2->value; + int c = a % b; + // % is really remainder and so has the same sign rules + // as division: -5 % 3 = -2, so need to add b (3 here) + // if c's sign is incorrect, but only if c is non-zero + int mask = (a ^ b) >> 31; + mask &= ~(!!c + 0) + 1; // +0 to convert bool to int (gcc) + *(int *) result->value = c + (mask & b); +} + +binop_t int_binops[] = { + { SHL, &cexpr_int, &cexpr_int, int_shl }, + { SHR, &cexpr_int, &cexpr_int, int_shr }, + { '+', &cexpr_int, &cexpr_int, int_add }, + { '-', &cexpr_int, &cexpr_int, int_sub }, + { '*', &cexpr_int, &cexpr_int, int_mul }, + { '/', &cexpr_int, &cexpr_int, int_div }, + { '&', &cexpr_int, &cexpr_int, int_band }, + { '|', &cexpr_int, &cexpr_int, int_bor }, + { '^', &cexpr_int, &cexpr_int, int_xor }, + { '%', &cexpr_int, &cexpr_int, int_rem }, + { MOD, &cexpr_int, &cexpr_int, int_mod }, + {} +}; + +unop_t int_unops[] = { + { '+', &cexpr_int, int_pos }, + { '-', &cexpr_int, int_neg }, + { '!', &cexpr_int, int_tnot }, + { '~', &cexpr_int, int_bnot }, + {} +}; + +exprtype_t cexpr_int = { + "int", + sizeof (int), + int_binops, + int_unops, +}; + +BINOP(uint, shl, unsigned, <<) +BINOP(uint, shr, unsigned, >>) +BINOP(uint, add, unsigned, +) +BINOP(uint, sub, unsigned, -) +BINOP(uint, mul, unsigned, *) +BINOP(uint, div, unsigned, /) +BINOP(uint, band, unsigned, &) +BINOP(uint, bor, unsigned, |) +BINOP(uint, xor, unsigned, ^) +BINOP(uint, rem, unsigned, %) + +UNOP(uint, pos, unsigned, +) +UNOP(uint, neg, unsigned, -) +UNOP(uint, tnot, unsigned, !) +UNOP(uint, bnot, unsigned, ~) + +binop_t uint_binops[] = { + { SHL, &cexpr_uint, &cexpr_uint, uint_shl }, + { SHR, &cexpr_uint, &cexpr_uint, uint_shr }, + { '+', &cexpr_uint, &cexpr_uint, uint_add }, + { '-', &cexpr_uint, &cexpr_uint, uint_sub }, + { '*', &cexpr_uint, &cexpr_uint, uint_mul }, + { '/', &cexpr_uint, &cexpr_uint, uint_div }, + { '&', &cexpr_uint, &cexpr_uint, uint_band }, + { '|', &cexpr_uint, &cexpr_uint, uint_bor }, + { '^', &cexpr_uint, &cexpr_uint, uint_xor }, + { '%', &cexpr_uint, &cexpr_uint, uint_rem }, + { MOD, &cexpr_uint, &cexpr_uint, uint_rem }, + {} +}; + +unop_t uint_unops[] = { + { '+', &cexpr_uint, uint_pos }, + { '-', &cexpr_uint, uint_neg }, + { '!', &cexpr_uint, uint_tnot }, + { '~', &cexpr_uint, uint_bnot }, + {} +}; + +exprtype_t cexpr_uint = { + "uint", + sizeof (unsigned), + uint_binops, + uint_unops, +}; + +BINOP(float, add, float, +) +BINOP(float, sub, float, -) +BINOP(float, mul, float, *) +BINOP(float, div, float, /) + +static void +float_rem (const exprval_t *val1, const exprval_t *val2, exprval_t *result, + exprctx_t *ctx) +{ + float a = *(float *) val1->value; + float b = *(float *) val2->value; + *(float *) result->value = a - b * truncf (a / b); +} + +static void +float_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, + exprctx_t *ctx) +{ + // implement true modulo for integers: + // 5 mod 3 = 2 + // -5 mod 3 = 1 + // 5 mod -3 = -1 + // -5 mod -3 = -2 + float a = *(float *) val1->value; + float b = *(float *) val2->value; + *(float *) result->value = a - b * floorf (a / b); +} + +UNOP(float, pos, float, +) +UNOP(float, neg, float, -) +UNOP(float, tnot, float, !) + +binop_t float_binops[] = { + { '+', &cexpr_float, &cexpr_float, float_add }, + { '-', &cexpr_float, &cexpr_float, float_sub }, + { '*', &cexpr_float, &cexpr_float, float_mul }, + { '/', &cexpr_float, &cexpr_float, float_div }, + { '%', &cexpr_float, &cexpr_float, float_rem }, + { MOD, &cexpr_float, &cexpr_float, float_mod }, + {} +}; + +unop_t float_unops[] = { + { '+', &cexpr_float, float_pos }, + { '-', &cexpr_float, float_neg }, + { '!', &cexpr_float, float_tnot }, + {} +}; + +exprtype_t cexpr_float = { + "float", + sizeof (float), + float_binops, + float_unops, +}; + +BINOP(double, add, double, +) +BINOP(double, sub, double, -) +BINOP(double, mul, double, *) +BINOP(double, div, double, /) + +static void +double_rem (const exprval_t *val1, const exprval_t *val2, exprval_t *result, + exprctx_t *ctx) +{ + double a = *(double *) val1->value; + double b = *(double *) val2->value; + *(double *) result->value = a - b * truncf (a / b); +} + +static void +double_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, + exprctx_t *ctx) +{ + // implement true modulo for integers: + // 5 mod 3 = 2 + // -5 mod 3 = 1 + // 5 mod -3 = -1 + // -5 mod -3 = -2 + double a = *(double *) val1->value; + double b = *(double *) val2->value; + *(double *) result->value = a - b * floorf (a / b); +} + +UNOP(double, pos, double, +) +UNOP(double, neg, double, -) +UNOP(double, tnot, double, !) + +binop_t double_binops[] = { + { '+', &cexpr_double, &cexpr_double, double_add }, + { '-', &cexpr_double, &cexpr_double, double_sub }, + { '*', &cexpr_double, &cexpr_double, double_mul }, + { '/', &cexpr_double, &cexpr_double, double_div }, + { '%', &cexpr_double, &cexpr_double, double_rem }, + { MOD, &cexpr_double, &cexpr_double, double_mod }, + {} +}; + +unop_t double_unops[] = { + { '+', &cexpr_double, double_pos }, + { '-', &cexpr_double, double_neg }, + { '!', &cexpr_double, double_tnot }, + {} +}; + +exprtype_t cexpr_double = { + "double", + sizeof (double), + double_binops, + double_unops, +}; + +exprtype_t cexpr_exprval = { + "exprval", + sizeof (exprval_t *), + 0, // can't actually do anything with an exprval + 0, +}; + +exprtype_t cexpr_field = { + "field", + 0, // has no size of its own, rather, it's the length of the name + 0, // can't actually do anything with a field + 0, +}; + +VISIBLE binop_t * +cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) +{ + binop_t *binop = 0; + + for (binop = dst_type->binops; binop && binop->op; binop++) { + if (binop->op == '=' && binop->other == src_type) { + break; + } + } + if (binop && binop->op) { + return binop; + } + return 0; +} + +VISIBLE int +cexpr_parse_enum (exprenum_t *enm, const char *str, const exprctx_t *ctx, + void *data) +{ + exprval_t result = { enm->type, data }; + exprctx_t context = *ctx; + context.symtab = enm->symtab; + context.result = &result; + return cexpr_eval_string (str, &context); +} diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c new file mode 100644 index 000000000..9f01e3134 --- /dev/null +++ b/libs/util/cexpr-vars.c @@ -0,0 +1,154 @@ +/* + cexpr-vars.c + + Config expression parser. Or concurrent. + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include + +#include "QF/cexpr.h" +#include "QF/cmem.h" +#include "QF/cvar.h" +#include "QF/hash.h" +#include "QF/qfplist.h" + +#include "libs/util/cexpr-parse.h" + +VISIBLE void +cexpr_struct_getfield (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + __auto_type symtab = (exprtab_t *) a->type->data; + __auto_type name = (const char *) b->value; + __auto_type field = (exprsym_t *) Hash_Find (symtab->tab, name); + exprval_t *val = 0; + if (field) { + val = cmemalloc (ctx->memsuper, sizeof (exprval_t)); + val->type = field->type; + val->value = a->value + (ptrdiff_t) field->value; + } + *(exprval_t **) c->value = val; +} + +VISIBLE binop_t cexpr_struct_binops[] = { + { '.', &cexpr_field, &cexpr_exprval, cexpr_struct_getfield }, + {} +}; + +static void +cvar_get (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx) +{ + __auto_type name = (const char *) b->value; + exprval_t *var = cexpr_cvar (name, ctx); + if (!var) { + PL_Message (ctx->messages, ctx->item, "unknown cvar %s", name); + } + *(exprval_t **) c->value = var; +} + +static binop_t cvar_binops[] = { + { '.', &cexpr_field, &cexpr_exprval, cvar_get }, + {} +}; + +static exprtype_t cvar_type = { + "cvar", + sizeof (void *), // ref to struct (will always be 0) + cvar_binops, + 0, +}; + +VISIBLE exprval_t * +cexpr_cvar (const char *name, exprctx_t *ctx) +{ + cvar_t *var = Cvar_FindVar (name); + if (!var) { + var = Cvar_FindAlias (name); + } + if (!var) { + return 0; + } + + exprtype_t *type = ctx->result->type; + binop_t *cast = cexpr_find_cast (type, &cexpr_int); + + exprval_t *val = 0; + if (cast || val->type == &cexpr_int || val->type == &cexpr_uint) { + val = cexpr_value (type, ctx); + *(int *) val->value = var->int_val; + } else if (val->type == &cexpr_float) { + val = cexpr_value (type, ctx); + *(float *) val->value = var->value; + } else if (val->type == &cexpr_double) { + val = cexpr_value (type, ctx); + //FIXME cvars need to support double values + *(double *) val->value = var->value; + } + return val; +} + +VISIBLE exprval_t * +cexpr_cvar_struct (exprctx_t *ctx) +{ + exprval_t *cvars = cexpr_value (&cvar_type, ctx); + *(void **) cvars->value = 0; + return cvars; +} + +static const char *expr_getkey (const void *s, void *unused) +{ + __auto_type sym = (exprsym_t *) s; + return sym->name; +} + +void cexpr_init_symtab (exprtab_t *symtab, exprctx_t *ctx) +{ + exprsym_t *sym; + + symtab->tab = Hash_NewTable (61, expr_getkey, 0, 0, &ctx->hashlinks); + for (sym = symtab->symbols; sym->name; sym++) { + Hash_Add (symtab->tab, sym); + } +} + +VISIBLE exprval_t * +cexpr_value_reference (exprtype_t *type, void *data, exprctx_t *ctx) +{ + __auto_type ref = (exprval_t *) cmemalloc (ctx->memsuper, + sizeof (exprval_t)); + ref->type = type; + ref->value = data; + return ref; +} + +VISIBLE exprval_t * +cexpr_value (exprtype_t *type, exprctx_t *ctx) +{ + exprval_t *val = cexpr_value_reference (type, 0, ctx); + val->value = cmemalloc (ctx->memsuper, type->size); + return val; +} diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 39140bee7..9447a7807 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -1,5 +1,6 @@ libs_util_tests = \ libs/util/test/test-bary \ + libs/util/test/test-cexpr \ libs/util/test/test-cmem \ libs/util/test/test-cs \ libs/util/test/test-darray \ @@ -24,6 +25,10 @@ libs_util_test_test_bary_SOURCES=libs/util/test/test-bary.c libs_util_test_test_bary_LDADD=libs/util/libQFutil.la libs_util_test_test_bary_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_cexpr_SOURCES=libs/util/test/test-cexpr.c +libs_util_test_test_cexpr_LDADD=libs/util/libQFutil.la +libs_util_test_test_cexpr_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_cmem_SOURCES=libs/util/test/test-cmem.c libs_util_test_test_cmem_LDADD=libs/util/libQFutil.la libs_util_test_test_cmem_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-cexpr.c b/libs/util/test/test-cexpr.c new file mode 100644 index 000000000..095316222 --- /dev/null +++ b/libs/util/test/test-cexpr.c @@ -0,0 +1,81 @@ +/* + test-cexpr.c + + Config expression parser. Or concurrent. + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#include "QF/cexpr.h" +#include "QF/cmem.h" +#include "QF/hash.h" + +int a = 5; +int b = 6; +int c; + +exprsym_t symbols[] = { + { "a", &cexpr_int, &a }, + { "b", &cexpr_int, &b }, + {} +}; +exprval_t result = { &cexpr_int, &c }; + +exprtab_t symtab = { + symbols, + 0 +}; + +exprctx_t context = { &result, &symtab }; + +#define TEST_BINOP(op) \ + do { \ + c = -4096; \ + cexpr_eval_string ("a " #op " b", &context); \ + printf ("c = a %s b -> %d = %d %s %d\n", #op, c, a, #op, b); \ + if (c != (a op b)) { \ + ret |= 1; \ + } \ + } while (0) + +int +main(int argc, const char **argv) +{ + int ret = 0; + + cexpr_init_symtab (&symtab, &context); + context.memsuper = new_memsuper(); + + TEST_BINOP (<<); + TEST_BINOP (>>); + TEST_BINOP (+); + TEST_BINOP (-); + TEST_BINOP (*); + TEST_BINOP (/); + TEST_BINOP (&); + TEST_BINOP (|); + TEST_BINOP (^); + TEST_BINOP (%); + + Hash_DelTable (symtab.tab); + delete_memsuper (context.memsuper); + return ret; +} From 4649294a275b9777e81b0852a26e9fa004a5fbf6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 14:47:15 +0900 Subject: [PATCH 1104/3664] [util] Fix inferred binary operator type checking The problem is that I needed to support dynamic types on operators (for bit-field enums), had things working, but a bad edit messed things up and I had to rebuild that bit of code. Missed one bit :P --- libs/util/cexpr-parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index ac41c549c..e789a40e9 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -179,7 +179,7 @@ binary_expr (int op, const exprval_t *a, const exprval_t *b, if (!otype) { otype = a->type; } - if (binop->op == op && binop->other == b->type) { + if (binop->op == op && otype == b->type) { break; } } From 96df447c45481a9698402f136061b41deb331ed3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 18:38:31 +0900 Subject: [PATCH 1105/3664] [vulkan] Hook up the expression parser The pipeline parser still isn't hooked up yet as something isn't quite right, but it seems all the parsing works. --- include/vid_vulkan.h | 1 + libs/video/renderer/Makemodule.am | 17 ++- libs/video/renderer/vulkan/qfpipeline.plist | 13 +- libs/video/renderer/vulkan/vkgen/vkalias.r | 18 +++ libs/video/renderer/vulkan/vkgen/vkenum.h | 3 + libs/video/renderer/vulkan/vkgen/vkenum.r | 74 ++++++++-- libs/video/renderer/vulkan/vkgen/vkgen.h | 1 + libs/video/renderer/vulkan/vkgen/vkgen.r | 21 ++- libs/video/renderer/vulkan/vkgen/vkstruct.h | 1 + libs/video/renderer/vulkan/vkgen/vkstruct.r | 95 +++++++++++- libs/video/renderer/vulkan/vkgen/vktype.h | 1 + libs/video/renderer/vulkan/vkgen/vktype.r | 5 + libs/video/renderer/vulkan/vkgen/vulkan.r | 1 + libs/video/renderer/vulkan/vkparse.c | 137 ++++++++++-------- libs/video/renderer/vulkan/vkparse.h | 6 +- libs/video/renderer/vulkan/vkparse.plist | 5 + .../video/renderer/vulkan/vulkan_vid_common.c | 22 ++- 17 files changed, 332 insertions(+), 89 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 2675d3036..411fcf4db 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -41,6 +41,7 @@ typedef struct vulkan_ctx_s { struct qfv_instance_s *instance; struct qfv_device_s *device; struct qfv_swapchain_s *swapchain; + struct hashlink_s *hashlinks; //FIXME want per thread VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain VkCommandPool cmdpool; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 1077ef6ca..e2b71bf07 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -233,12 +233,15 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vkparse_src) -libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(pipeline_gen) +libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c ${vkparse_src} $(pipeline_gen) qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) +vkparse_cinc = libs/video/renderer/vulkan/vkparse.cinc +vkparse_hinc = libs/video/renderer/vulkan/vkparse.hinc vkparse_src = \ - libs/video/renderer/vulkan/vkparse.inc + ${vkparse_cinc} \ + ${vkparse_hinc} vkparse_plist = \ $(srcdir)/libs/video/renderer/vulkan/vkparse.plist @@ -247,9 +250,13 @@ V_VKGEN_ = $(V_VKGEN_@AM_DEFAULT_V@) V_VKGEN_0 = @echo " VKGEN " $@; V_VKGEN_1 = -libs/video/renderer/vulkan/vkparse.inc: $(vkgen) $(qwaq_curses) $(vkparse_plist) - $(V_VKGEN)$(qwaq_curses) $(vkgen) -- $(vkparse_plist) $@.t &&\ - $(am__mv) $@.t $@ +${vkparse_cinc}: $(vkgen) $(qwaq_curses) $(vkparse_plist) + $(V_VKGEN)$(qwaq_curses) $(vkgen) -- $(vkparse_plist) ${vkparse_cinc}.t ${vkparse_hinc}.t &&\ + $(am__mv) ${vkparse_cinc}.t ${vkparse_cinc} &&\ + $(am__mv) ${vkparse_hinc}.t ${vkparse_hinc} + +${vkparse_hinc}: ${vkparse_cinc} +# do nothing: hinc generated at the same time as cinc CLEANFILES += \ libs/video/renderer/glsl/*.vc \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 1c594aee0..a8e1c36c9 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -14,18 +14,18 @@ }, { flags = 0; - format = $swapchain.format; - samples = $msaaSamples; + format = VK_FORMAT_D32_SFLOAT; + samples = $cvars.msaaSamples; loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - storeOp = VK_ATTACHMENT_STORE_OP_STORE; + storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; }, { flags = 0; - format = VK_FORMAT_D32_SFLOAT; + format = $swapchain.format; samples = VK_SAMPLE_COUNT_1_BIT; loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -37,6 +37,7 @@ ); subpasses = ( { + pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; colorAttachments = ( { attachment = 0; @@ -51,7 +52,7 @@ ); depthStencilAttachment = { attachment = 1; - layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; }; preserveAttachments = (); }, diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index 6228ac230..132e6291a 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -50,6 +50,24 @@ } } +-(string) cexprType +{ + Type *alias = [Type findType:type.alias.full_type]; + string name = [self name]; + + if ([alias name] == "VkFlags") { + if (str_mid (name, -5) == "Flags") { + string tag = str_mid (name, 0, -1) + "Bits"; + id enumObj = [(id) Hash_Find (available_types, tag) resolveType]; + return [enumObj cexprType]; + } + } + if (name == "uint32_t") { + return "cexpr_uint"; + } + return [alias cexprType]; +} + -(string) parseType { Type *alias = [Type findType:type.alias.full_type]; diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.h b/libs/video/renderer/vulkan/vkgen/vkenum.h index 5deb7ff6f..6694c24cb 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.h +++ b/libs/video/renderer/vulkan/vkgen/vkenum.h @@ -3,11 +3,14 @@ #include "vktype.h" +@class PLItem; + @interface Enum: Type { int prefix_length; } -(void) writeTable; +-(void) writeSymtabInit:(PLItem *) parse; @end #endif//__renderer_vulkan_vkgen_vkenum_h diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 768e4b8d4..e3894902a 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -50,6 +50,15 @@ } } +static int +skip_value(string name) +{ + return (str_str (name, "_MAX_ENUM") >= 0 + || str_str (name, "_BEGIN_RANGE") >= 0 + || str_str (name, "_END_RANGE") >= 0 + || str_str (name, "_RANGE_SIZE") >= 0); +} + -(void) writeTable { int strip_bit = 0; @@ -57,16 +66,37 @@ strip_bit = 1; } - fprintf (output_file, "enumval_t %s_values[] = {\n", [self name]); - for (int i = 0; i < type.strct.num_fields; i++) { + fprintf (output_file, "static exprtype_t %s_type = {\n", [self name]); + fprintf (output_file, "\t\"%s\",\n", [self name]); + fprintf (output_file, "\tsizeof (int),\n"); + if (strip_bit) { + fprintf (output_file, "\tflag_binops,\n"); + fprintf (output_file, "\tflag_unops,\n"); + } else { + fprintf (output_file, "\t0,\n"); + fprintf (output_file, "\t0,\n"); + } + fprintf (output_file, "};\n"); + + fprintf (output_file, "static %s %s_values[] = {\n", [self name], [self name]); + for (int i = 0, index = 0; i < type.strct.num_fields; i++) { qfot_var_t *var = &type.strct.fields[i]; - if (str_str (var.name, "_MAX_ENUM") >= 0 - || str_str (var.name, "_BEGIN_RANGE") >= 0 - || str_str (var.name, "_END_RANGE") >= 0 - || str_str (var.name, "_RANGE_SIZE") >= 0) { + if (skip_value (var.name)) { continue; } - fprintf (output_file, "\t{\"%s\", %d},\n", var.name, var.offset); + fprintf (output_file, "\t%s, // %d 0x%x\n", + var.name, var.offset, var.offset); + index++; + } + fprintf (output_file, "};\n"); + fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self name]); + for (int i = 0, index = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (skip_value (var.name)) { + continue; + } + fprintf (output_file, "\t{\"%s\", &%s_type, %s_values + %d},\n", + var.name, [self name], [self name], index); if (prefix_length) { string shortname = str_mid (var.name, prefix_length); if (strip_bit) { @@ -75,12 +105,33 @@ shortname = str_mid (shortname, 0, bit_pos); } } - fprintf (output_file, "\t{\"%s\", %d},\n", str_lower(shortname), - var.offset); + fprintf (output_file, "\t{\"%s\", &%s_type, %s_values + %d},\n", + str_lower(shortname), [self name], [self name], index); } + index++; } fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); + fprintf (output_file, "static exprtab_t %s_symtab = {\n", [self name]); + fprintf (output_file, "\t%s_symbols,\n", [self name]); + fprintf (output_file, "};\n"); + fprintf (output_file, "exprenum_t %s_enum = {\n", [self name]); + fprintf (output_file, "\t&%s_type,\n", [self name]); + fprintf (output_file, "\t&%s_symtab,\n", [self name]); + fprintf (output_file, "};\n"); + + fprintf (header_file, "extern exprenum_t %s_enum;\n", [self name]); +} + +-(void) writeSymtabInit:(PLItem *) parse +{ + fprintf (output_file, "\tcexpr_init_symtab (&%s_symtab, context);\n", + [self name]); +} + +-(string) cexprType +{ + return [self name] + "_type"; } -(string) parseType @@ -90,14 +141,11 @@ -(string) parseFunc { - if (str_mid([self name], -8) == "FlagBits") { - return "parse_flags"; - } return "parse_enum"; } -(string) parseData { - return [self name] + "_values"; + return "&" + [self name] + "_enum"; } @end diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.h b/libs/video/renderer/vulkan/vkgen/vkgen.h index 0d488abe8..e60499f25 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.h +++ b/libs/video/renderer/vulkan/vkgen/vkgen.h @@ -13,6 +13,7 @@ void fprintf (QFile file, string format, ...); extern Array *queue; extern Array *output_types; extern QFile output_file; +extern QFile header_file; extern hashtab_t *processed_types; extern hashtab_t *available_types; diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 7744d0cdc..025e3d2cc 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -25,7 +25,6 @@ arp_end (void) autorelease_pool = nil; } - void printf (string fmt, ...) = #0; void fprintf (QFile file, string format, ...) @@ -39,6 +38,7 @@ Array *queue; Array *output_types; QFile output_file; +QFile header_file; qfot_type_encodings_t *encodings; @@ -135,7 +135,7 @@ get_object_key (void *obj, void *unused) void usage (string name) { - printf ("%s [plist file] [output file]\n", name); + printf ("%s [plist file] [output file] [header file]\n", name); } int @@ -151,7 +151,7 @@ main(int argc, string *argv) arp_start (); - if (argc != 3) { + if (argc != 4) { usage (argv[0]); return 1; } @@ -211,6 +211,7 @@ main(int argc, string *argv) arp_end (); output_file = Qopen (argv[2], "wt"); + header_file = Qopen (argv[3], "wt"); for (int i = [output_types count]; i-- > 0; ) { id obj = [output_types objectAtIndex:i]; if ([obj name] == "VkStructureType") { @@ -237,6 +238,20 @@ main(int argc, string *argv) [obj writeTable:parse]; arp_end (); } + fprintf (output_file, "static void\n"); + fprintf (output_file, "vkgen_init_symtabs (exprctx_t *context)\n"); + fprintf (output_file, "{\n"); + for (int i = [output_types count]; i-- > 0; ) { + id obj = [output_types objectAtIndex:i]; + if ([obj name] == "VkStructureType") { + continue; + } + arp_start (); + [obj writeSymtabInit:parse]; + arp_end (); + } + fprintf (output_file, "}\n"); Qclose (output_file); + Qclose (header_file); return 0; } diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index 246d23070..c251cb4c0 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -13,6 +13,7 @@ } -(void) forEachFieldCall: (varfunc) func; -(void) writeTable: (PLItem *) parse; +-(void) writeSymtabInit:(PLItem *) parse; @end #endif//__renderer_vulkan_vkgen_vkstruct_h diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index b1bf22960..4c9040cb6 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -162,7 +162,11 @@ fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); - fprintf (output_file, "static int parse_%s (const plfield_t *field," + fprintf (header_file, "int parse_%s (const plfield_t *field," + " const plitem_t *item, void *data, plitem_t *messages," + " void *context);\n", + name); + fprintf (output_file, "int parse_%s (const plfield_t *field," " const plitem_t *item, void *data, plitem_t *messages," " void *context)\n", name); @@ -172,6 +176,95 @@ " context);\n", name); fprintf (output_file, "}\n"); + + fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", name); + if (field_defs) { + PLItem *field_def; + qfot_var_t *field; + + for (int i = [field_defs count]; i-- > 0; ) { + string field_name = [[field_defs getObjectAtIndex:i] string]; + field_def = [field_dict getObjectForKey:field_name]; + PLItem *type_desc = [field_def getObjectForKey:"type"]; + string type_record; + string type_type; + string size_field = nil; + string value_field = nil; + + if (str_mid(field_name, 0, 1) == ".") { + continue; + } + field_def = [field_dict getObjectForKey:field_name]; + if ([field_def string] == "auto") { + field = [self findField:field_name]; + if (!field) { + continue; + } + field_type = [Type findType: field.type]; + fprintf (output_file, + "\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n", + field_name, [field_type cexprType], name, field_name); + } else { + type_record = [[type_desc getObjectAtIndex:0] string]; + if (type_record == "single") { + value_field = [[field_def getObjectForKey:"value"] string]; + } else { + value_field = [[field_def getObjectForKey:"values"] string]; + } + if (!value_field) { + value_field = field_name; + } + fprintf (output_file, + "\t{\"%s\", 0/*FIXME*/," + " (void *) field_offset (%s, %s)},\n", + field_name, name, value_field); + } + } + } else { + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *field = &type.strct.fields[i]; + if (field.name == "sType" || field.name == "pNext") { + continue; + } + field_type = [Type findType: field.type]; + fprintf (output_file, + "\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n", + field.name, [field_type cexprType], name, field.name); + } + } + fprintf (output_file, "\t{ }\n"); + fprintf (output_file, "};\n"); + + fprintf (output_file, "static exprtab_t %s_symtab = {\n", name); + fprintf (output_file, "\t%s_symbols,\n", name); + fprintf (output_file, "};\n"); + + fprintf (output_file, "exprtype_t %s_type = {\n", name); + fprintf (output_file, "\t\"%s\",\n", name); + fprintf (output_file, "\tsizeof (%s),\n", name); + fprintf (output_file, "\tcexpr_struct_binops,\n"); + fprintf (output_file, "\t0,\n"); + fprintf (output_file, "\t&%s_symtab,\n", name); + fprintf (output_file, "};\n"); + fprintf (header_file, "extern exprtype_t %s_type;\n", name); +} + +-(void) writeSymtabInit:(PLItem *) parse +{ + string name = [self name]; + PLItem *field_dict = [parse getObjectForKey:name]; + PLItem *new_name = [field_dict getObjectForKey:".name"]; + + if (new_name) { + name = [new_name string]; + } + + fprintf (output_file, "\tcexpr_init_symtab (&%s_symtab, context);\n", name); +} + +-(string) cexprType +{ + return [self name] + "_type"; } -(string) parseType diff --git a/libs/video/renderer/vulkan/vkgen/vktype.h b/libs/video/renderer/vulkan/vkgen/vktype.h index fc5a53c84..0008c83ab 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.h +++ b/libs/video/renderer/vulkan/vkgen/vktype.h @@ -19,6 +19,7 @@ -(Type *) resolveType; +(Type *) findType: (qfot_type_t *) type; +(Type *) lookup: (string) name; +-(string) cexprType; -(string) parseType; -(string) parseFunc; -(string) parseData; diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index caa7ac057..5d6c1b7ae 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -91,6 +91,11 @@ static string get_type_key (void *type, void *unused) return self; } +-(string) cexprType +{ + return "cexpr_" + [self name]; +} + -(string) parseType { return "no parse"; diff --git a/libs/video/renderer/vulkan/vkgen/vulkan.r b/libs/video/renderer/vulkan/vkgen/vulkan.r index 46b720d0c..a2a53be7c 100644 --- a/libs/video/renderer/vulkan/vkgen/vulkan.r +++ b/libs/video/renderer/vulkan/vkgen/vulkan.r @@ -1,2 +1,3 @@ #define __x86_64__ #include +#include "QF/Vulkan/swapchain.h" diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index a4b037202..55798c185 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -38,6 +38,8 @@ # include #endif +#include "QF/cexpr.h" +#include "QF/cmem.h" #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/input.h" @@ -64,10 +66,41 @@ #include "util.h" #include "vkparse.h" -typedef struct enumval_s { - const char *name; - int value; -} enumval_t; +static void flag_or (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + *(int *) (result->value) = *(int *) (val1->value) | *(int *) (val2->value); +} + +static void flag_and (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + *(int *) (result->value) = *(int *) (val1->value) & *(int *) (val2->value); +} + +static void flag_cast_int (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + // FIXME should check value is valid + *(int *) (result->value) = *(int *) (val2->value); +} + +static void flag_not (const exprval_t *val, exprval_t *result, exprctx_t *ctx) +{ + *(int *) (result->value) = ~(*(int *) (val->value)); +} + +binop_t flag_binops[] = { + { '|', 0, 0, flag_or }, + { '&', 0, 0, flag_and }, + { '=', &cexpr_int, 0, flag_cast_int }, + {} +}; + +unop_t flag_unops[] = { + { '~', 0, flag_not }, + {} +}; typedef struct parse_single_s { pltype_t type; @@ -84,20 +117,8 @@ typedef struct parse_array_s { size_t size_offset; } parse_array_t; -static int find_enum (const char *valstr, enumval_t *enumval, int *val) -{ - while (enumval->name && strcmp (enumval->name, valstr) != 0) { - enumval++; - } - if (enumval->name) { - *val = enumval->value; - return 1; - } - return 0; -} - static int parse_uint32_t (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *ctx) + void *data, plitem_t *messages, void *context) { int ret = 1; const char *valstr = PL_String (item); @@ -125,47 +146,25 @@ static int parse_uint32_t (const plfield_t *field, const plitem_t *item, } static int parse_enum (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *ctx) + void *data, plitem_t *messages, void *context) { int ret = 1; - int val; + __auto_type enm = (exprenum_t *) field->data; + exprctx_t ectx = *(exprctx_t *)context; + exprval_t result = { enm->type, data }; + ectx.symtab = enm->symtab; + ectx.result = &result; const char *valstr = PL_String (item); - __auto_type enumval = (enumval_t *) field->data; - //Sys_Printf ("parse_enum: %s %zd %d %p %p %s\n", - // field->name, field->offset, field->type, field->parser, - // field->data, valstr); - if (find_enum (valstr, enumval, &val)) { - *(int *) data = val; - } else { - PL_Message (messages, item, "invalid enum: %s", valstr); - ret = 0; - } - return ret; -} - -static int parse_flags (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *ctx) -{ - int ret = 1; - int val; - const char *valstr = PL_String (item); - __auto_type enumval = (enumval_t *) field->data; - //Sys_Printf ("parse_flags: %s %zd %d %p %p %s\n", - // field->name, field->offset, field->type, field->parser, - // field->data, valstr); - if (find_enum (valstr, enumval, &val)) { - *(int *) data = val; - } else if (strcmp (valstr, "0") == 0) { - *(int *) data = 0; - } else { - PL_Message (messages, item, "invalid enum: %s", valstr); - ret = 0; - } + Sys_Printf ("parse_enum: %s %zd %d %p %p %s\n", + field->name, field->offset, field->type, field->parser, + field->data, valstr); + ret = !cexpr_parse_enum (enm, valstr, &ectx, data); + Sys_Printf (" %d\n", *(int *)data); return ret; } static int parse_single (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *ctx) + void *data, plitem_t *messages, void *context) { __auto_type single = (parse_single_t *) field->data; void *flddata = (byte *)data + single->value_offset; @@ -180,7 +179,7 @@ static int parse_single (const plfield_t *field, const plitem_t *item, plfield_t f = { 0, 0, single->type, single->parser, 0 }; void *value = calloc (1, single->stride); - if (!single->parser (&f, item, value, messages, ctx)) { + if (!single->parser (&f, item, value, messages, context)) { free (value); return 0; } @@ -190,7 +189,7 @@ static int parse_single (const plfield_t *field, const plitem_t *item, } static int parse_array (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *ctx) + void *data, plitem_t *messages, void *context) { __auto_type array = (parse_array_t *) field->data; __auto_type value = (void **) ((byte *)data + array->value_offset); @@ -213,7 +212,7 @@ static int parse_array (const plfield_t *field, const plitem_t *item, // field->data, data); //Sys_Printf (" %d %zd %p %zd %zd\n", array->type, array->stride, // array->parser, array->value_offset, array->size_offset); - if (!PL_ParseArray (&f, item, &arr, messages, ctx)) { + if (!PL_ParseArray (&f, item, &arr, messages, context)) { return 0; } *value = malloc (array->stride * arr->size); @@ -225,7 +224,7 @@ static int parse_array (const plfield_t *field, const plitem_t *item, return 1; } -#include "libs/video/renderer/vulkan/vkparse.inc" +#include "libs/video/renderer/vulkan/vkparse.cinc" typedef struct qfv_renderpass_s { qfv_attachmentdescription_t *attachments; @@ -268,20 +267,37 @@ static plfield_t renderpass_fields[] = { }; VkRenderPass -QFV_ParseRenderPass (qfv_device_t *device, plitem_t *plist) +QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) { + qfv_device_t *device = ctx->device; qfv_renderpass_t renderpass_data = {}; plitem_t *messages = PL_NewArray (); VkRenderPass renderpass; + exprsym_t var_syms[] = { + {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {} + }; + exprtab_t vars_tab = { var_syms, 0 }; + exprctx_t exprctx = {}; + + exprctx.external_variables = &vars_tab; + exprctx.memsuper = new_memsuper (); + exprctx.messages = messages; + exprctx.hashlinks = ctx->hashlinks; + + cexpr_init_symtab (&vars_tab, &exprctx); if (!PL_ParseDictionary (renderpass_fields, plist, - &renderpass_data, messages, 0)) { + &renderpass_data, messages, &exprctx)) { for (int i = 0; i < PL_A_NumObjects (messages); i++) { Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } return 0; } PL_Free (messages); + delete_memsuper (exprctx.memsuper); + ctx->hashlinks = exprctx.hashlinks; + renderpass = QFV_CreateRenderPass (device, renderpass_data.attachments, renderpass_data.subpasses, @@ -299,3 +315,10 @@ QFV_ParseRenderPass (qfv_device_t *device, plitem_t *plist) free (renderpass_data.dependencies); return renderpass; } + +void +QFV_InitParse (void) +{ + exprctx_t context = {}; + vkgen_init_symtabs (&context); +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 0d14eecbe..ae8a30af9 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -2,9 +2,9 @@ #define __vkparse_h #include "QF/Vulkan/renderpass.h" +#include "libs/video/renderer/vulkan/vkparse.hinc" -VkRenderPass -QFV_ParseRenderPass (qfv_device_t *device, plitem_t *plist); - +VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); +void QFV_InitParse (void); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 017025426..1441a0267 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -3,8 +3,13 @@ VkAttachmentDescription, VkSubpassDescription, VkSubpassDependency, + qfv_swapchain_t, ); parse = { + qfv_swapchain_s = { + .name = qfv_swapchain_t; + format = auto; + }; VkSubpassDescription = { flags = auto; pipelineBindPoint = auto; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 6f0ba9892..b0d285ed6 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -39,6 +39,8 @@ # include #endif +#include "QF/cexpr.h" +#include "QF/cmem.h" #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/input.h" @@ -63,12 +65,14 @@ #include "vid_vulkan.h" #include "util.h" +#include "vkparse.h" static const char quakeforge_pipeline[] = #include "libs/video/renderer/vulkan/qfpipeline.plc" ; cvar_t *vulkan_presentation_mode; +cvar_t *msaaSamples; static void vulkan_presentation_mode_f (cvar_t *var) @@ -87,6 +91,19 @@ vulkan_presentation_mode_f (cvar_t *var) } } +static void +msaaSamples_f (cvar_t *var) +{ + exprctx_t context = {}; + context.memsuper = new_memsuper(); + + if (cexpr_parse_enum (&VkSampleCountFlagBits_enum, var->string, &context, + &var->int_val)) { + Sys_Printf ("Invalid MSAA samples, using 1\n"); + var->int_val = VK_SAMPLE_COUNT_1_BIT; + } +} + static void Vulkan_Init_Cvars (void) { @@ -100,6 +117,9 @@ Vulkan_Init_Cvars (void) CVAR_NONE, vulkan_presentation_mode_f, "desired presentation mode (may fall " "back to fifo)."); + msaaSamples = Cvar_Get ("msaaSamples", "VK_SAMPLE_COUNT_1_BIT", + CVAR_NONE, msaaSamples_f, + "desired MSAA sample size."); } static const char *instance_extensions[] = { @@ -116,8 +136,8 @@ void Vulkan_Init_Common (vulkan_ctx_t *ctx) { Sys_Printf ("Vulkan_Init_Common\n"); + QFV_InitParse (); Vulkan_Init_Cvars (); - ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version } From ac8206555ee145ad4a690432b6df1d5b6ffb638e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 19:30:00 +0900 Subject: [PATCH 1106/3664] [vulkan] Get the parsed pipeline working It turned out the msaa setting defaulting to 1 instead of 8 was the problem no idea why at this stage (need to read up on just how that setting works). Once I understand just how it works, I'll rework the msaa handling. --- libs/video/renderer/vulkan/instance.c | 2 +- libs/video/renderer/vulkan/renderpass.c | 61 ++++++++++++++++ libs/video/renderer/vulkan/vkparse.c | 8 +-- .../video/renderer/vulkan/vulkan_vid_common.c | 69 +------------------ 4 files changed, 68 insertions(+), 72 deletions(-) diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index 4d23b5a75..b228df2fe 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -296,6 +296,6 @@ QFV_GetMaxSampleCount (qfv_physdev_t *physdev) while (maxSamples && maxSamples > counts) { maxSamples >>= 1; } - Sys_MaskPrintf (SYS_VULKAN, "Max samples: %x\n", maxSamples); + Sys_MaskPrintf (SYS_VULKAN, "Max samples: %x (%d)\n", maxSamples, counts); return maxSamples; } diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 40bc095ad..78cc46563 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -71,6 +71,67 @@ QFV_CreateRenderPass (qfv_device_t *device, VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; + if (developer->int_val & SYS_VULKAN) { + Sys_Printf ("attachments: %ld\n", attachments->size); + for (size_t i = 0; i < attachments->size; i++) { + Sys_Printf (" flags: %x\n", attachments->a[i].flags); + Sys_Printf (" format: %d\n", attachments->a[i].format); + Sys_Printf (" samples: %x\n", attachments->a[i].samples); + Sys_Printf (" loadOp: %d\n", attachments->a[i].loadOp); + Sys_Printf (" storeOp: %d\n", attachments->a[i].storeOp); + Sys_Printf (" stencilLoadOp: %d\n", + attachments->a[i].stencilLoadOp); + Sys_Printf (" stencilStoreOp: %d\n", + attachments->a[i].stencilStoreOp); + Sys_Printf (" initialLayout: %d\n", + attachments->a[i].initialLayout); + Sys_Printf (" finalLayout: %d\n", + attachments->a[i].finalLayout); + } + Sys_Printf ("subpassparams: %ld\n", subpassparams->size); + for (size_t i = 0; i < subpassparams->size; i++) { + VkSubpassDescription *sp = &subpassparams->a[i]; + Sys_Printf (" flags: %x\n", sp->flags); + Sys_Printf (" piplineBindPoint: %d\n", sp->pipelineBindPoint); + Sys_Printf (" inputAttachmentCount: %d\n", + sp->inputAttachmentCount); + for (size_t j = 0; j < sp->inputAttachmentCount; j++) { + const VkAttachmentReference *ref = &sp->pInputAttachments[j]; + Sys_Printf (" c %d %d\n", ref->attachment, ref->layout); + } + Sys_Printf (" colorAttachmentCount: %d\n", + sp->colorAttachmentCount); + for (size_t j = 0; j < sp->colorAttachmentCount; j++) { + const VkAttachmentReference *ref = &sp->pColorAttachments[j]; + Sys_Printf (" c %d %d\n", ref->attachment, ref->layout); + } + for (size_t j = 0; j < sp->colorAttachmentCount; j++) { + const VkAttachmentReference *ref = &sp->pResolveAttachments[j]; + Sys_Printf (" r %d %d\n", ref->attachment, ref->layout); + } + Sys_Printf (" pDepthStencilAttachment: %p\n", + sp->pDepthStencilAttachment); + if (sp->pDepthStencilAttachment) { + const VkAttachmentReference *ref = sp->pDepthStencilAttachment; + Sys_Printf (" %d %d\n", ref->attachment, ref->layout); + } + Sys_Printf (" preserveAttachmentCount: %d\n", + sp->preserveAttachmentCount); + for (size_t j = 0; j < sp->preserveAttachmentCount; j++) { + Sys_Printf (" %d\n", sp->pPreserveAttachments[j]); + } + } + Sys_Printf ("dependencies: %ld\n", dependencies->size); + for (size_t i = 0; i < dependencies->size; i++) { + Sys_Printf (" srcSubpass: %d\n", dependencies->a[i].srcSubpass); + Sys_Printf (" dstSubpass: %d\n", dependencies->a[i].dstSubpass); + Sys_Printf (" srcStageMask: %x\n", dependencies->a[i].srcStageMask); + Sys_Printf (" dstStageMask: %x\n", dependencies->a[i].dstStageMask); + Sys_Printf (" srcAccessMask: %x\n", dependencies->a[i].srcAccessMask); + Sys_Printf (" dstAccessMask: %x\n", dependencies->a[i].dstAccessMask); + Sys_Printf (" dependencyFlags: %x\n", dependencies->a[i].dependencyFlags); + } + } VkRenderPassCreateInfo createInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 0, 0, attachments->size, attachments->a, diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 55798c185..b6512d041 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -155,11 +155,11 @@ static int parse_enum (const plfield_t *field, const plitem_t *item, ectx.symtab = enm->symtab; ectx.result = &result; const char *valstr = PL_String (item); - Sys_Printf ("parse_enum: %s %zd %d %p %p %s\n", - field->name, field->offset, field->type, field->parser, - field->data, valstr); + //Sys_Printf ("parse_enum: %s %zd %d %p %p %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); ret = !cexpr_parse_enum (enm, valstr, &ectx, data); - Sys_Printf (" %d\n", *(int *)data); + //Sys_Printf (" %d\n", *(int *)data); return ret; } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index b0d285ed6..ee0a209a1 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -117,7 +117,7 @@ Vulkan_Init_Cvars (void) CVAR_NONE, vulkan_presentation_mode_f, "desired presentation mode (may fall " "back to fifo)."); - msaaSamples = Cvar_Get ("msaaSamples", "VK_SAMPLE_COUNT_1_BIT", + msaaSamples = Cvar_Get ("msaaSamples", "VK_SAMPLE_COUNT_8_BIT", CVAR_NONE, msaaSamples_f, "desired MSAA sample size."); } @@ -366,72 +366,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) ctx->renderpass.colorImage = colorImage; ctx->renderpass.depthImage = depthImage; - - __auto_type attachments = QFV_AllocAttachmentDescription (3, alloca); - __auto_type attachmentRefs = QFV_AllocAttachmentReference (3, alloca); - - // color attachment - attachments->a[0].flags = 0; - attachments->a[0].format = sc->format; - attachments->a[0].samples = msaaSamples; - attachments->a[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments->a[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments->a[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments->a[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments->a[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments->a[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - attachmentRefs->a[0].attachment = 0; - attachmentRefs->a[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - // depth attachment - attachments->a[1].flags = 0; - attachments->a[1].format = depthFormat; - attachments->a[1].samples = msaaSamples; - attachments->a[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments->a[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments->a[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments->a[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments->a[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments->a[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attachmentRefs->a[1].attachment = 1; - attachmentRefs->a[1].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - // resolve attachment - attachments->a[2].flags = 0; - attachments->a[2].format = sc->format; - attachments->a[2].samples = VK_SAMPLE_COUNT_1_BIT; - attachments->a[2].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments->a[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments->a[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments->a[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments->a[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - attachments->a[2].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - attachmentRefs->a[2].attachment = 2; - attachmentRefs->a[2].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - __auto_type subpasses = QFV_AllocSubpassParametersSet (1, alloca); - subpasses->a[0].flags = 0; - subpasses->a[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpasses->a[0].inputAttachmentCount = 0; - subpasses->a[0].pInputAttachments = 0; - subpasses->a[0].colorAttachmentCount = 1; - subpasses->a[0].pColorAttachments = &attachmentRefs->a[0]; - subpasses->a[0].pResolveAttachments = &attachmentRefs->a[2]; - subpasses->a[0].pDepthStencilAttachment = &attachmentRefs->a[1]; - subpasses->a[0].preserveAttachmentCount = 0; - subpasses->a[0].pPreserveAttachments = 0; - - __auto_type depenencies = QFV_AllocSubpassDependencies (1, alloca); - depenencies->a[0].srcSubpass = VK_SUBPASS_EXTERNAL; - depenencies->a[0].dstSubpass = 0; - depenencies->a[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - depenencies->a[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - depenencies->a[0].srcAccessMask = 0; - depenencies->a[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - depenencies->a[0].dependencyFlags = 0; - - ctx->renderpass.renderpass = QFV_CreateRenderPass (device, attachments, - subpasses, depenencies); + ctx->renderpass.renderpass = QFV_ParseRenderPass (ctx, item); } void From 79f22ffebfb6c698624100b4383fab8ef285e454 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 20:15:43 +0900 Subject: [PATCH 1107/3664] [util] Propagate cexpr errors back to the caller Not much point in error detection when it's ignored. --- include/QF/cexpr.h | 1 + libs/util/cexpr-lex.l | 7 +++++-- libs/util/cexpr-vars.c | 3 +-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index fcdeaad57..7524dec0c 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -82,6 +82,7 @@ typedef struct exprctx_s { const struct plitem_s *item; struct plitem_s *messages; struct hashlink_s *hashlinks; + int errors; } exprctx_t; typedef struct exprenum_s { diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index cfb1b99c6..cdae1ee04 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -82,6 +82,8 @@ cexpr_error(exprctx_t *ctx, const char *fmt, ...) va_list args; dstring_t *string; + ctx->errors++; + string = dstring_new (); va_start (args, fmt); @@ -211,6 +213,7 @@ cexpr_eval_string (const char *str, exprctx_t *context) yylex_init_extra (context, &scanner); yy_scan_string (str, scanner); + context->errors = 0; do { CEXPR_YYSTYPE lval; int token = yylex (&lval, scanner); @@ -219,7 +222,7 @@ cexpr_eval_string (const char *str, exprctx_t *context) yylex_destroy (scanner); cexpr_yypstate_delete (ps); - return status; + return status || context->errors; } static exprval_t *parse_int (const char *str, exprctx_t *context) @@ -271,7 +274,7 @@ parse_variable (const char *name, exprctx_t *context) if (sym) { val = cexpr_value_reference (sym->type, sym->value, context); } else { - val = cexpr_cvar (name, context); + //val = cexpr_cvar (name, context); } } if (!val) { diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c index 9f01e3134..6ec8ce3d9 100644 --- a/libs/util/cexpr-vars.c +++ b/libs/util/cexpr-vars.c @@ -34,7 +34,6 @@ #include "QF/cmem.h" #include "QF/cvar.h" #include "QF/hash.h" -#include "QF/qfplist.h" #include "libs/util/cexpr-parse.h" @@ -65,7 +64,7 @@ cvar_get (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx) __auto_type name = (const char *) b->value; exprval_t *var = cexpr_cvar (name, ctx); if (!var) { - PL_Message (ctx->messages, ctx->item, "unknown cvar %s", name); + cexpr_error (ctx, "unknown cvar %s", name); } *(exprval_t **) c->value = var; } From 80aec45e35b5f7704dd65f7b39104ef80b1e48ca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 20:17:27 +0900 Subject: [PATCH 1108/3664] [vulkan] Ensure msaa settings are consistent I had forgotten that msaa samples was governed by the driver (as a max) and the renderpass setup code simply took the max. Thus why 1 vs 8 caused the display to render incorrectly. --- include/vid_vulkan.h | 1 + libs/video/renderer/vulkan/qfpipeline.plist | 2 +- libs/video/renderer/vulkan/vkparse.c | 1 + libs/video/renderer/vulkan/vulkan_vid_common.c | 10 +++++----- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 411fcf4db..1886730c6 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -41,6 +41,7 @@ typedef struct vulkan_ctx_s { struct qfv_instance_s *instance; struct qfv_device_s *device; struct qfv_swapchain_s *swapchain; + VkSampleCountFlagBits msaaSamples; // FIXME not here? struct hashlink_s *hashlinks; //FIXME want per thread VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index a8e1c36c9..66c9e0adb 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -15,7 +15,7 @@ { flags = 0; format = VK_FORMAT_D32_SFLOAT; - samples = $cvars.msaaSamples; + samples = $msaaSamples; loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index b6512d041..b62637796 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -275,6 +275,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) VkRenderPass renderpass; exprsym_t var_syms[] = { {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {} }; exprtab_t vars_tab = { var_syms, 0 }; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index ee0a209a1..9c2b021f4 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -117,7 +117,7 @@ Vulkan_Init_Cvars (void) CVAR_NONE, vulkan_presentation_mode_f, "desired presentation mode (may fall " "back to fifo)."); - msaaSamples = Cvar_Get ("msaaSamples", "VK_SAMPLE_COUNT_8_BIT", + msaaSamples = Cvar_Get ("msaaSamples", "VK_SAMPLE_COUNT_1_BIT", CVAR_NONE, msaaSamples_f, "desired MSAA sample size."); } @@ -284,13 +284,13 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) VkExtent3D extent = {sc->extent.width, sc->extent.height, 1}; - VkSampleCountFlagBits msaaSamples - = QFV_GetMaxSampleCount (device->physDev); + //FIXME incorporate cvar setting + ctx->msaaSamples = QFV_GetMaxSampleCount (device->physDev); Sys_MaskPrintf (SYS_VULKAN, "color resource\n"); colorImage->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - sc->format, extent, 1, 1, msaaSamples, + sc->format, extent, 1, 1, ctx->msaaSamples, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); colorImage->object @@ -308,7 +308,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) VkFormat depthFormat = VK_FORMAT_D32_SFLOAT; depthImage->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - depthFormat, extent, 1, 1, msaaSamples, + depthFormat, extent, 1, 1, ctx->msaaSamples, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); depthImage->object = QFV_AllocImageMemory (device, depthImage->image, From 91c5baa7089741c9a9e7746004058f2572ee5fd6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 23 Dec 2020 14:06:20 +0900 Subject: [PATCH 1109/3664] [util] Add size_t support to cexpr --- include/QF/cexpr.h | 1 + libs/util/cexpr-type.c | 46 ++++++++++++++++++++++ libs/video/renderer/vulkan/vkgen/vkalias.r | 7 +++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 7524dec0c..0d2b4a8a4 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -109,6 +109,7 @@ char *cexpr_yyget_text (void *scanner); extern exprtype_t cexpr_int; extern exprtype_t cexpr_uint; +extern exprtype_t cexpr_size_t; extern exprtype_t cexpr_float; extern exprtype_t cexpr_double; extern exprtype_t cexpr_exprval; diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 35c62ee85..c0610b13d 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -160,6 +160,52 @@ exprtype_t cexpr_uint = { uint_unops, }; +BINOP(size_t, shl, unsigned, <<) +BINOP(size_t, shr, unsigned, >>) +BINOP(size_t, add, unsigned, +) +BINOP(size_t, sub, unsigned, -) +BINOP(size_t, mul, unsigned, *) +BINOP(size_t, div, unsigned, /) +BINOP(size_t, band, unsigned, &) +BINOP(size_t, bor, unsigned, |) +BINOP(size_t, xor, unsigned, ^) +BINOP(size_t, rem, unsigned, %) + +UNOP(size_t, pos, unsigned, +) +UNOP(size_t, neg, unsigned, -) +UNOP(size_t, tnot, unsigned, !) +UNOP(size_t, bnot, unsigned, ~) + +binop_t size_t_binops[] = { + { SHL, &cexpr_size_t, &cexpr_size_t, size_t_shl }, + { SHR, &cexpr_size_t, &cexpr_size_t, size_t_shr }, + { '+', &cexpr_size_t, &cexpr_size_t, size_t_add }, + { '-', &cexpr_size_t, &cexpr_size_t, size_t_sub }, + { '*', &cexpr_size_t, &cexpr_size_t, size_t_mul }, + { '/', &cexpr_size_t, &cexpr_size_t, size_t_div }, + { '&', &cexpr_size_t, &cexpr_size_t, size_t_band }, + { '|', &cexpr_size_t, &cexpr_size_t, size_t_bor }, + { '^', &cexpr_size_t, &cexpr_size_t, size_t_xor }, + { '%', &cexpr_size_t, &cexpr_size_t, size_t_rem }, + { MOD, &cexpr_size_t, &cexpr_size_t, size_t_rem }, + {} +}; + +unop_t size_t_unops[] = { + { '+', &cexpr_size_t, size_t_pos }, + { '-', &cexpr_size_t, size_t_neg }, + { '!', &cexpr_size_t, size_t_tnot }, + { '~', &cexpr_size_t, size_t_bnot }, + {} +}; + +exprtype_t cexpr_size_t = { + "size_t", + sizeof (size_t), + size_t_binops, + size_t_unops, +}; + BINOP(float, add, float, +) BINOP(float, sub, float, -) BINOP(float, mul, float, *) diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index 132e6291a..be783b207 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -65,6 +65,9 @@ if (name == "uint32_t") { return "cexpr_uint"; } + if (name == "size_t") { + return "cexpr_size_t"; + } return [alias cexprType]; } @@ -80,7 +83,7 @@ return [enumObj parseType]; } } - if (name == "uint32_t") { + if (name == "uint32_t" || name == "size_t") { return "QFString"; } return [alias parseType]; @@ -116,7 +119,7 @@ return [enumObj parseData]; } } - if (name == "uint32_t") { + if (name == "uint32_t" || name == "size_t") { return "0"; } return [alias parseData]; From 5864b553ef95cdff5c3e038d32ff7441b9982f17 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 23 Dec 2020 14:07:30 +0900 Subject: [PATCH 1110/3664] [util] Add accessors for binary plist objects --- include/QF/qfplist.h | 17 +++++++++++++++++ libs/util/qfplist.c | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 70a1b8302..1d45426d2 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -141,6 +141,23 @@ pltype_t PL_Type (const plitem_t *item) __attribute__((pure)); */ int PL_Line (const plitem_t *item) __attribute__((pure)); +/** Retrieve the data size from a binary object. + + \param binary The binary object + \return the size in bytes of the binary object 0 if binary isn't a binary + object. +*/ +size_t PL_BinarySize (const plitem_t *item) __attribute__((pure)); + +/** Retrieve the data from a binary object. + + \param binary The binary object + \return pointer to the actual data or NULL if binary isn't a binary object. + \note You are NOT responsible for freeing the returned object. It will + be destroyed when its container is. +*/ +const void *PL_BinaryData (const plitem_t *binary) __attribute__((pure)); + /** Retrieve a string from a string object. \param string The string object diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 2f71d42bc..b33d22084 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -231,6 +231,26 @@ PL_Free (plitem_t *item) free (item); } +VISIBLE size_t +PL_BinarySize (const plitem_t *binary) +{ + plbinary_t *bin = (plbinary_t *) binary->data; + + if (binary->type != QFBinary) + return 0; + return bin->size; +} + +VISIBLE const void * +PL_BinaryData (const plitem_t *binary) +{ + plbinary_t *bin = (plbinary_t *) binary->data; + + if (binary->type != QFBinary) + return 0; + return bin->data; +} + VISIBLE const char * PL_String (const plitem_t *string) { From f1848bb5b77299bdbf487fb86122ea520616d397 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 23 Dec 2020 14:08:53 +0900 Subject: [PATCH 1111/3664] [vulkan] Add support for parsing binary data --- libs/video/renderer/vulkan/vkgen/vkstruct.r | 34 ++++++++++++++++----- libs/video/renderer/vulkan/vkparse.c | 29 ++++++++++++++++++ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 4c9040cb6..6e6908bb8 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -80,14 +80,17 @@ field_type = [[Type lookup: type_type] dereference]; fprintf (output_file, "static parse_%s_t parse_%s_%s_data = {\n", type_record, name, field_name); - fprintf (output_file, "\t%s,\n", [field_type parseType]); - fprintf (output_file, "\tsizeof (%s),\n", type_type); - fprintf (output_file, "\tparse_%s,\n", type_type); if (type_record == "single") { + fprintf (output_file, "\t%s,\n", [field_type parseType]); + fprintf (output_file, "\tsizeof (%s),\n", type_type); + fprintf (output_file, "\tparse_%s,\n", type_type); value_field = [[field_def getObjectForKey:"value"] string]; fprintf (output_file, "\tfield_offset (%s, %s),\n", name, value_field); - } else { + } else if (type_record == "array") { + fprintf (output_file, "\t%s,\n", [field_type parseType]); + fprintf (output_file, "\tsizeof (%s),\n", type_type); + fprintf (output_file, "\tparse_%s,\n", type_type); value_field = [[field_def getObjectForKey:"values"] string]; size_field = [[field_def getObjectForKey:"size"] string]; fprintf (output_file, "\tfield_offset (%s, %s),\n", @@ -98,6 +101,19 @@ } else { fprintf (output_file, "\t-1,\n"); } + } else if (type_record == "data") { + value_field = [[field_def getObjectForKey:"data"] string]; + size_field = [[field_def getObjectForKey:"size"] string]; + fprintf (output_file, "\tfield_offset (%s, %s),\n", + name, value_field); + if (size_field) { + fprintf (output_file, "\tfield_offset (%s, %s),\n", + name, size_field); + } else { + fprintf (output_file, "\t-1,\n"); + } + } else { + fprintf (output_file, "\tno type,\n"); } fprintf (output_file, "};\n"); } @@ -128,7 +144,7 @@ PLItem *type_desc = [field_def getObjectForKey:"type"]; string type_record; string type_type; - string parseType; + string parseType = "no type"; type_record = [[type_desc getObjectAtIndex:0] string]; type_type = [[type_desc getObjectAtIndex:1] string]; @@ -136,8 +152,10 @@ field_type = [[Type lookup: type_type] dereference]; if (type_record == "single") { parseType = [field_type parseType]; - } else { + } else if (type_record == "array") { parseType = "QFArray"; + } else if (type_record == "data") { + parseType = "QFBinary"; } fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", @@ -208,8 +226,10 @@ type_record = [[type_desc getObjectAtIndex:0] string]; if (type_record == "single") { value_field = [[field_def getObjectForKey:"value"] string]; - } else { + } else if (type_record == "array") { value_field = [[field_def getObjectForKey:"values"] string]; + } else if (type_record == "data") { + value_field = [[field_def getObjectForKey:"data"] string]; } if (!value_field) { value_field = field_name; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index b62637796..fbe46d512 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -117,6 +117,11 @@ typedef struct parse_array_s { size_t size_offset; } parse_array_t; +typedef struct parse_data_s { + size_t value_offset; + size_t size_offset; +} parse_data_t; + static int parse_uint32_t (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { @@ -224,6 +229,30 @@ static int parse_array (const plfield_t *field, const plitem_t *item, return 1; } +static int parse_data (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + __auto_type datad = (parse_data_t *) field->data; + __auto_type value = (void **) ((byte *)data + datad->value_offset); + __auto_type size = (size_t *) ((byte *)data + datad->size_offset); + + const void *bindata = PL_BinaryData (item); + size_t binsize = PL_BinarySize (item); + + Sys_Printf ("parse_array: %s %zd %d %p %p %p\n", + field->name, field->offset, field->type, field->parser, + field->data, data); + Sys_Printf (" %zd %zd\n", datad->value_offset, datad->size_offset); + Sys_Printf (" %zd %p\n", binsize, bindata); + + *value = malloc (binsize); + memcpy (*value, bindata, binsize); + if ((void *) size > data) { + *size = binsize; + } + return 1; +} + #include "libs/video/renderer/vulkan/vkparse.cinc" typedef struct qfv_renderpass_s { From 7fb335a21559f3944b259111521e0470a2ea2677 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 23 Dec 2020 14:32:29 +0900 Subject: [PATCH 1112/3664] [vulkan] Add support for building and loading shaders Shaders can be built as spv files and installed into $libdir/quakeforge/shaders or as spvc files and compiled into the engine. Loading supports $builtin/name to access builtin shaders, $shader/path to access external standard shaders and quake filesystem access for all other paths. --- Makefile.am | 22 +++ config.d/paths.m4 | 13 ++ config.d/vulkan.m4 | 1 + include/QF/Vulkan/shader.h | 13 ++ include/vid_vulkan.h | 2 + libs/video/renderer/Makemodule.am | 42 ++++- libs/video/renderer/vulkan/passthrough.vert | 8 + libs/video/renderer/vulkan/pushcolor.frag | 12 ++ libs/video/renderer/vulkan/shader.c | 192 ++++++++++++++++++++ 9 files changed, 296 insertions(+), 9 deletions(-) create mode 100644 include/QF/Vulkan/shader.h create mode 100644 libs/video/renderer/vulkan/passthrough.vert create mode 100644 libs/video/renderer/vulkan/pushcolor.frag create mode 100644 libs/video/renderer/vulkan/shader.c diff --git a/Makefile.am b/Makefile.am index 71e429956..b59b21eb7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -107,6 +107,27 @@ qcautodep = $(join $(addsuffix $(DEPDIR)/,$(dir $(basename $(1)))),$(addsuffix . r_depfiles_remade= pas_depfiles_remade= +V_GLSLANG = $(V_GLSLANG_@AM_V@) +V_GLSLANG_ = $(V_GLSLANG_@AM_DEFAULT_V@) +V_GLSLANG_0 = @echo " GLSLANG " $@; +V_GLSLANG_1 = + +V_XXD = $(V_XXD_@AM_V@) +V_XXD_ = $(V_XXD_@AM_DEFAULT_V@) +V_XXD_0 = @echo " XXD " $@; +V_XXD_1 = + +%.spv: % + @$(mkdir_p) $(builddir)/`dirname $@` + $(V_GLSLANG)$(GLSLANGVALIDATOR) -V $< -o $@ > /dev/null + +%.spvc: % + @$(mkdir_p) $(builddir)/`dirname $@` + $(V_GLSLANG)$(GLSLANGVALIDATOR) --vn `basename $< | tr . _` -V $< -o $@ > /dev/null + +shaderdir = @shaderdir@ +shader_DATA = + include doc/Makemodule.am include RPM/Makemodule.am include debian/Makemodule.am @@ -122,6 +143,7 @@ include tools/Makemodule.am include ruamoko/Makemodule.am DISTCLEANFILES += $(r_depfiles_remade) $(pas_depfiles_remade) +CLEANFILES += $(shader_DATA) $(r_depfiles_remade): $(MKDIR_P) $(@D) diff --git a/config.d/paths.m4 b/config.d/paths.m4 index f340eda78..c5ce432ce 100644 --- a/config.d/paths.m4 +++ b/config.d/paths.m4 @@ -98,6 +98,19 @@ eval expanded_plugindir="$expanded_plugindir" AC_DEFINE_UNQUOTED(FS_PLUGINPATH, "$expanded_plugindir", [Define this to the path from which to load plugins]) AC_SUBST(plugindir) +SHADERDIR="\${libdir}/quakeforge/shaders" +if test "x$shaderdir" = "xauto" -o "x$shaderdir" = "xyes" -o "x$shaderdir" = "x"; then + shaderdir="$SHADERDIR" +elif test "x$shaderdir" = xno; then + shaderdir="." +else + SHADERDIR="$shaderdir" +fi +eval expanded_shaderdir="$shaderdir" +eval expanded_shaderdir="$expanded_shaderdir" +AC_DEFINE_UNQUOTED(FS_SHADERPATH, "$expanded_shaderdir", [Define this to the path from which to load shaders]) +AC_SUBST(plugindir) + AC_ARG_WITH(gl-driver, [ --with-gl-driver=NAME Name of OpenGL driver DLL/DSO], gl_driver=$withval, diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index 4c9df43f4..0c780e98a 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -16,5 +16,6 @@ if test "x$HAVE_VULKAN" = xyes; then AC_DEFINE([HAVE_VULKAN], [1], [Define if yhou have the Vulkan libs]) fi AC_SUBST(VULKAN_LIBS) +AC_SUBST(GLSLANGVALIDATOR, [$glslangvalidator]) AM_CONDITIONAL(X11_VULKAN, test "x$HAVE_VULKAN" = "xyes") diff --git a/include/QF/Vulkan/shader.h b/include/QF/Vulkan/shader.h new file mode 100644 index 000000000..6b8321cdd --- /dev/null +++ b/include/QF/Vulkan/shader.h @@ -0,0 +1,13 @@ +#ifndef __QF_Vulkan_shader_h +#define __QF_Vulkan_shader_h + +struct qfv_device_s; +struct vulkan_ctx_s; + +VkShaderModule QFV_CreateShaderModule (struct qfv_device_s *device, + const char *path); +void QFV_RegisterShaderModule (struct vulkan_ctx_s *ctx, const char *name, + VkShaderModule module); +void QFV_DeregisterShaderModule (struct vulkan_ctx_s *ctx, const char *name); + +#endif//__QF_Vulkan_shader_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 1886730c6..5eb2dd157 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -44,6 +44,8 @@ typedef struct vulkan_ctx_s { VkSampleCountFlagBits msaaSamples; // FIXME not here? struct hashlink_s *hashlinks; //FIXME want per thread VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain + struct hashtab_s *shadermodules; + struct shadermodule_s *shadermodule_freelist; VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index e2b71bf07..b5ca83cf5 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -78,7 +78,7 @@ V_SED_ = $(V_SED_@AM_DEFAULT_V@) V_SED_0 = @echo " SED " $@; V_SED_1 = -SUFFICES=.frag .vert .fc .vc .slc .glsl .plist .plc +SUFFICES=.frag .vert .spv .spvc .fc .vc .slc .glsl .plist .plc .glsl.slc: $(V_SED)sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\ $(am__mv) $@.t $@ @@ -224,6 +224,7 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/namehack.h \ libs/video/renderer/vulkan/pipeline.c \ libs/video/renderer/vulkan/renderpass.c \ + libs/video/renderer/vulkan/shader.c \ libs/video/renderer/vulkan/swapchain.c \ libs/video/renderer/vulkan/util.c \ libs/video/renderer/vulkan/util.h \ @@ -233,29 +234,44 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vkparse_src) -libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c ${vkparse_src} $(pipeline_gen) +libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c) + +libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) vkparse_cinc = libs/video/renderer/vulkan/vkparse.cinc vkparse_hinc = libs/video/renderer/vulkan/vkparse.hinc vkparse_src = \ - ${vkparse_cinc} \ - ${vkparse_hinc} + $(vkparse_cinc) \ + $(vkparse_hinc) vkparse_plist = \ $(srcdir)/libs/video/renderer/vulkan/vkparse.plist +passthrough_src = libs/video/renderer/vulkan/passthrough.vert +passthrough_c = libs/video/renderer/vulkan/passthrough.vert.spvc +pushcolor_src = libs/video/renderer/vulkan/pushcolor.frag +pushcolor_c = libs/video/renderer/vulkan/pushcolor.frag.spvc + +$(passthrough_c): $(passthrough_src) + +$(pushcolor_c): $(pushcolor_src) + +vkshader_c = \ + $(passthrough_c) \ + $(pushcolor_c) + V_VKGEN = $(V_VKGEN_@AM_V@) V_VKGEN_ = $(V_VKGEN_@AM_DEFAULT_V@) V_VKGEN_0 = @echo " VKGEN " $@; V_VKGEN_1 = -${vkparse_cinc}: $(vkgen) $(qwaq_curses) $(vkparse_plist) - $(V_VKGEN)$(qwaq_curses) $(vkgen) -- $(vkparse_plist) ${vkparse_cinc}.t ${vkparse_hinc}.t &&\ - $(am__mv) ${vkparse_cinc}.t ${vkparse_cinc} &&\ - $(am__mv) ${vkparse_hinc}.t ${vkparse_hinc} +$(vkparse_cinc): $(vkgen) $(qwaq_curses) $(vkparse_plist) + $(V_VKGEN)$(qwaq_curses) $(vkgen) -- $(vkparse_plist) $(vkparse_cinc).t $(vkparse_hinc).t &&\ + $(am__mv) $(vkparse_cinc).t $(vkparse_cinc) &&\ + $(am__mv) $(vkparse_hinc).t $(vkparse_hinc) -${vkparse_hinc}: ${vkparse_cinc} +$(vkparse_hinc): $(vkparse_cinc) # do nothing: hinc generated at the same time as cinc CLEANFILES += \ @@ -263,7 +279,15 @@ CLEANFILES += \ libs/video/renderer/glsl/*.fc \ libs/video/renderer/glsl/*.slc \ libs/video/renderer/vulkan/*.plc \ + libs/video/renderer/vulkan/*.spv \ + libs/video/renderer/vulkan/*.spvc \ libs/video/renderer/vulkan/vkgen.sym \ $(vkparse_src) BUILT_SOURCES += $(shader_gen) + +#shader_DATA += \ +# libs/video/renderer/vulkan/passthrough.vert.spv \ +# libs/video/renderer/vulkan/pushcolor.frag.spv + +EXTRA_DIST += $(shader_DATA:.spv=) diff --git a/libs/video/renderer/vulkan/passthrough.vert b/libs/video/renderer/vulkan/passthrough.vert new file mode 100644 index 000000000..0283a53b3 --- /dev/null +++ b/libs/video/renderer/vulkan/passthrough.vert @@ -0,0 +1,8 @@ +#version 450 + +layout (location = 0) in vec4 app_position; + +void main() +{ + gl_Position = app_position; +} diff --git a/libs/video/renderer/vulkan/pushcolor.frag b/libs/video/renderer/vulkan/pushcolor.frag new file mode 100644 index 000000000..d19413fe1 --- /dev/null +++ b/libs/video/renderer/vulkan/pushcolor.frag @@ -0,0 +1,12 @@ +#version 450 + +layout (location = 0) out vec4 frag_color; + +layout (push_constant) uniform ColorBlock { + vec4 Color; +} PushConstant; + +void main() +{ + frag_color = PushConstant.Color; +} diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c new file mode 100644 index 000000000..704e01996 --- /dev/null +++ b/libs/video/renderer/vulkan/shader.c @@ -0,0 +1,192 @@ +/* + shader.c + + Vulkan shader manager + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/alloc.h" +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/renderpass.h" +#include "QF/Vulkan/shader.h" + +#include "vid_vulkan.h" + +static +#include "libs/video/renderer/vulkan/passthrough.vert.spvc" +static +#include "libs/video/renderer/vulkan/pushcolor.frag.spvc" + +typedef struct shaderdata_s { + const char *name; + const uint32_t *data; + size_t size; +} shaderdata_t; + +typedef struct shadermodule_s { + char *name; + union { + VkShaderModule module; + struct shadermodule_s *next; + }; +} shadermodule_t; + +static shaderdata_t builtin_shaders[] = { + { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, + { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, + {} +}; + +#define BUILTIN "$builtin/" +#define BUILTIN_SIZE (sizeof (BUILTIN) - 1) +#define SHADER "$shader/" +#define SHADER_SIZE (sizeof (SHADER) - 1) + +VkShaderModule +QFV_CreateShaderModule (qfv_device_t *device, const char *shader_path) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + shaderdata_t _data = {}; + shaderdata_t *data = 0; + dstring_t *path = 0; + QFile *file; + VkShaderModule shader = 0; + + if (strncmp (shader_path, BUILTIN, BUILTIN_SIZE) == 0) { + const char *name = shader_path + BUILTIN_SIZE; + + for (int i = 0; builtin_shaders[i].name; i++) { + if (strcmp (builtin_shaders[i].name, name) == 0) { + data = &builtin_shaders[i]; + break; + } + } + } else if (strncmp (shader_path, SHADER, SHADER_SIZE)) { + path = dstring_new (); + dsprintf (path, "%s/%s", FS_SHADERPATH, shader_path + SHADER_SIZE); + file = Qopen (path->str, "rbz"); + } else { + file = QFS_FOpenFile (shader_path); + } + + if (file) { + _data.size = Qfilesize (file); + _data.data = malloc (_data.size); + Qread (file, (void *) _data.data, _data.size); + Qclose (file); + data = &_data; + } + + if (data) { + VkShaderModuleCreateInfo createInfo = { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 0, + 0, data->size, data->data + }; + + dfunc->vkCreateShaderModule (dev, &createInfo, 0, &shader); + } else { + Sys_MaskPrintf (SYS_VULKAN, + "QFV_CreateShaderModule: could not find shader %s\n", + shader_path); + } + + if (path) { + dstring_delete (path); + } + if (_data.data) { + free ((void *) _data.data); + } + return shader; +} + +static shadermodule_t * +new_module (vulkan_ctx_t *ctx) +{ + shadermodule_t *shadermodule; + ALLOC (128, shadermodule_t, ctx->shadermodule, shadermodule); + return shadermodule; +} + +static void +del_module (shadermodule_t *shadermodule, vulkan_ctx_t *ctx) +{ + free (shadermodule->name); + FREE (ctx->shadermodule, shadermodule); +} + +static const char * +sm_getkey (const void *sm, void *unused) +{ + return ((shadermodule_t *) sm)->name; +} + +static void +sm_free (void *sm, void *ctx) +{ + del_module (sm, ctx); +} + +void +QFV_RegisterShaderModule (vulkan_ctx_t *ctx, const char *name, + VkShaderModule module) +{ + if (!ctx->shadermodules) { + ctx->shadermodules = Hash_NewTable (127, sm_getkey, sm_free, ctx, 0); + } + shadermodule_t *shadermodule = new_module (ctx); + shadermodule->name = strdup (name); + shadermodule->module = module; + Hash_Add (ctx->shadermodules, shadermodule); +} + +void +QFV_DeregisterShaderModule (vulkan_ctx_t *ctx, const char *name) +{ + if (!ctx->shadermodules) { + return; + } + Hash_Free (ctx->shadermodules, Hash_Del (ctx->shadermodules, name)); +} From e1e2a0e71263022def45eba305a312ba98fe6912 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 23 Dec 2020 21:52:42 +0900 Subject: [PATCH 1113/3664] [ruamoko] Add a wrapper for PL_Line Makes error reporting in rua code easier. --- libs/ruamoko/rua_plist.c | 10 ++++++++++ ruamoko/include/PropertyList.h | 1 + ruamoko/include/plist.h | 1 + ruamoko/lib/PropertyList.r | 5 +++++ ruamoko/lib/plist.r | 1 + 5 files changed, 18 insertions(+) diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index b71af2ead..d45ee1b8d 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -229,6 +229,15 @@ bi_PL_Type (progs_t *pr) R_INT (pr) = PL_Type (plist->plitem); } +static void +bi_PL_Line (progs_t *pr) +{ + int handle = P_INT (pr, 0); + bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + + R_INT (pr) = PL_Line (plist->plitem); +} + static void bi_PL_String (progs_t *pr) { @@ -432,6 +441,7 @@ static builtin_t builtins[] = { {"PL_GetPropertyList", bi_PL_GetPropertyList, -1}, {"PL_WritePropertyList", bi_PL_WritePropertyList, -1}, {"PL_Type", bi_PL_Type, -1}, + {"PL_Line", bi_PL_Line, -1}, {"PL_String", bi_PL_String, -1}, {"PL_ObjectForKey", bi_PL_ObjectForKey, -1}, {"PL_RemoveObjectForKey", bi_PL_RemoveObjectForKey, -1}, diff --git a/ruamoko/include/PropertyList.h b/ruamoko/include/PropertyList.h index c0c4bed35..d2494a94a 100644 --- a/ruamoko/include/PropertyList.h +++ b/ruamoko/include/PropertyList.h @@ -42,6 +42,7 @@ - initWithOwnItem:(plitem_t) item; - (string) write; - (pltype_t) type; +- (int) line; @end @interface PLDictionary: PLItem diff --git a/ruamoko/include/plist.h b/ruamoko/include/plist.h index 4544e00ff..bfaa25516 100644 --- a/ruamoko/include/plist.h +++ b/ruamoko/include/plist.h @@ -10,6 +10,7 @@ typedef enum {QFDictionary, QFArray, QFBinary, QFString} pltype_t; // possible t @extern plitem_t PL_GetPropertyList (string str); @extern string PL_WritePropertyList (plitem_t pl); @extern pltype_t PL_Type (plitem_t str); +@extern int PL_Line (plitem_t str); @extern string PL_String (plitem_t str); @extern plitem_t PL_ObjectForKey (plitem_t item, string key); @extern plitem_t PL_RemoveObjectForKey (plitem_t item, string key); diff --git a/ruamoko/lib/PropertyList.r b/ruamoko/lib/PropertyList.r index b8469e473..c6df13070 100644 --- a/ruamoko/lib/PropertyList.r +++ b/ruamoko/lib/PropertyList.r @@ -94,6 +94,11 @@ return PL_Type (item); } +- (int) line +{ + return PL_Line (item); +} + - (int) count { if ([self class] == [PLDictionary class]) { diff --git a/ruamoko/lib/plist.r b/ruamoko/lib/plist.r index 40ab2e1fc..34f0ce6c1 100644 --- a/ruamoko/lib/plist.r +++ b/ruamoko/lib/plist.r @@ -4,6 +4,7 @@ plitem_t PL_GetFromFile (QFile file) = #0; plitem_t PL_GetPropertyList (string str) = #0; string PL_WritePropertyList (plitem_t pl) = #0; pltype_t PL_Type (plitem_t str) = #0; +int PL_Line (plitem_t str) = #0; string PL_String (plitem_t str) = #0; plitem_t PL_ObjectForKey (plitem_t item, string key) = #0; plitem_t PL_RemoveObjectForKey (plitem_t item, string key) = #0; From 017d2c1f4453daa7802e031958fab96a9ef7316d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 23 Dec 2020 22:13:50 +0900 Subject: [PATCH 1114/3664] [vulkan] Refactor vkgen struct generation The addition of data an then string support made keeping track of things in struct's writeTable a nightmare. --- .../video/renderer/vulkan/vkgen/Makemodule.am | 6 + libs/video/renderer/vulkan/vkgen/vkenum.h | 2 +- libs/video/renderer/vulkan/vkgen/vkenum.r | 2 +- .../renderer/vulkan/vkgen/vkfieldarray.h | 12 + .../renderer/vulkan/vkgen/vkfieldarray.r | 52 ++++ .../video/renderer/vulkan/vkgen/vkfieldauto.h | 9 + .../video/renderer/vulkan/vkgen/vkfieldauto.r | 43 ++++ .../video/renderer/vulkan/vkgen/vkfielddata.h | 9 + .../video/renderer/vulkan/vkgen/vkfielddata.r | 45 ++++ libs/video/renderer/vulkan/vkgen/vkfielddef.h | 28 +++ libs/video/renderer/vulkan/vkgen/vkfielddef.r | 95 ++++++++ .../renderer/vulkan/vkgen/vkfieldsingle.h | 12 + .../renderer/vulkan/vkgen/vkfieldsingle.r | 46 ++++ .../renderer/vulkan/vkgen/vkfieldstring.h | 9 + .../renderer/vulkan/vkgen/vkfieldstring.r | 36 +++ libs/video/renderer/vulkan/vkgen/vkgen.h | 1 + libs/video/renderer/vulkan/vkgen/vkgen.r | 9 +- libs/video/renderer/vulkan/vkgen/vkstruct.h | 7 +- libs/video/renderer/vulkan/vkgen/vkstruct.r | 229 +++++------------- libs/video/renderer/vulkan/vkparse.c | 24 +- 20 files changed, 499 insertions(+), 177 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldarray.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldarray.r create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldauto.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldauto.r create mode 100644 libs/video/renderer/vulkan/vkgen/vkfielddata.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfielddata.r create mode 100644 libs/video/renderer/vulkan/vkgen/vkfielddef.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfielddef.r create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldsingle.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldsingle.r create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldstring.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldstring.r diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 66971a2c3..31c22d936 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -4,6 +4,12 @@ noinst_PROGRAMS += $(vkgen) vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkalias.r \ libs/video/renderer/vulkan/vkgen/vkenum.r \ + libs/video/renderer/vulkan/vkgen/vkfieldarray.r \ + libs/video/renderer/vulkan/vkgen/vkfieldauto.r \ + libs/video/renderer/vulkan/vkgen/vkfielddata.r \ + libs/video/renderer/vulkan/vkgen/vkfielddef.r \ + libs/video/renderer/vulkan/vkgen/vkfieldsingle.r \ + libs/video/renderer/vulkan/vkgen/vkfieldstring.r \ libs/video/renderer/vulkan/vkgen/vkgen.r \ libs/video/renderer/vulkan/vkgen/vkstruct.r \ libs/video/renderer/vulkan/vkgen/vktype.r \ diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.h b/libs/video/renderer/vulkan/vkgen/vkenum.h index 6694c24cb..4df770b92 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.h +++ b/libs/video/renderer/vulkan/vkgen/vkenum.h @@ -10,7 +10,7 @@ int prefix_length; } -(void) writeTable; --(void) writeSymtabInit:(PLItem *) parse; +-(void) writeSymtabInit; @end #endif//__renderer_vulkan_vkgen_vkenum_h diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index e3894902a..234c99b61 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -123,7 +123,7 @@ skip_value(string name) fprintf (header_file, "extern exprenum_t %s_enum;\n", [self name]); } --(void) writeSymtabInit:(PLItem *) parse +-(void) writeSymtabInit { fprintf (output_file, "\tcexpr_init_symtab (&%s_symtab, context);\n", [self name]); diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldarray.h b/libs/video/renderer/vulkan/vkgen/vkfieldarray.h new file mode 100644 index 000000000..5cf31880b --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldarray.h @@ -0,0 +1,12 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldarray_h +#define __renderer_vulkan_vkgen_vkfieldarray_h + +#include "vkfielddef.h" + +@interface ArrayField: FieldDef +{ + string type; +} +@end + +#endif//__renderer_vulkan_vkgen_vkfieldarray_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldarray.r b/libs/video/renderer/vulkan/vkgen/vkfieldarray.r new file mode 100644 index 000000000..dd81dd9f4 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldarray.r @@ -0,0 +1,52 @@ +#include + +#include "vkfieldarray.h" +#include "vkgen.h" +#include "vktype.h" + +@implementation ArrayField + +-init:(PLItem *) item struct:(Struct *)strct field:(string)fname +{ + self = [super init:item struct:strct field:fname]; + if (!self) { + return self; + } + + PLItem *desc = [item getObjectForKey:"type"]; + type = [[desc getObjectAtIndex:1] string]; + + value_field = [[item getObjectForKey:"values"] string]; + size_field = [[item getObjectForKey:"size"] string]; + return self; +} + +-writeParseData +{ + Type *field_type = [[Type lookup: type] dereference]; + + fprintf (output_file, "static parse_array_t parse_%s_%s_data = {\n", + struct_name, field_name); + fprintf (output_file, "\t%s,\n", [field_type parseType]); + fprintf (output_file, "\tsizeof (%s),\n", type); + fprintf (output_file, "\tparse_%s,\n", type); + fprintf (output_file, "\tfield_offset (%s, %s),\n", + struct_name, value_field); + if (size_field) { + fprintf (output_file, "\tfield_offset (%s, %s),\n", + struct_name, size_field); + } else { + fprintf (output_file, "\t-1,\n"); + } + fprintf (output_file, "};\n"); + return self; +} + +-writeField +{ + fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", + field_name, "QFArray", "array", struct_name, field_name); + return self; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldauto.h b/libs/video/renderer/vulkan/vkgen/vkfieldauto.h new file mode 100644 index 000000000..a2e05deb8 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldauto.h @@ -0,0 +1,9 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldauto_h +#define __renderer_vulkan_vkgen_vkfieldauto_h + +#include "vkfielddef.h" + +@interface AutoField: FieldDef +@end + +#endif//__renderer_vulkan_vkgen_vkfieldauto_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldauto.r b/libs/video/renderer/vulkan/vkgen/vkfieldauto.r new file mode 100644 index 000000000..dab844c92 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldauto.r @@ -0,0 +1,43 @@ +#include "vkfieldauto.h" +#include "vkgen.h" +#include "vkstruct.h" + +@implementation AutoField + +-init:(PLItem *) item struct:(Struct *)strct field:(string)fname +{ + self = [super init:item struct:strct field:fname]; + if (!self) { + return self; + } + field = [strct findField:field_name]; + + return self; +} + +-writeParseData +{ + printf("FieldDef: '%s' '%s'\n", struct_name, field_name); + return self; +} + +-writeField +{ + Type *field_type = [Type findType: field.type]; + fprintf (output_file, "\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n", + field_name, struct_name, field_name, + [field_type parseType], [field_type parseFunc], + [field_type parseData]); + return self; +} + +-writeSymbol +{ + Type *field_type = [Type findType: field.type]; + fprintf (output_file, + "\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n", + field_name, [field_type cexprType], struct_name, field_name); + return self; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddata.h b/libs/video/renderer/vulkan/vkgen/vkfielddata.h new file mode 100644 index 000000000..cf8356262 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfielddata.h @@ -0,0 +1,9 @@ +#ifndef __renderer_vulkan_vkgen_vkfielddata_h +#define __renderer_vulkan_vkgen_vkfielddata_h + +#include "vkfielddef.h" + +@interface DataField: FieldDef +@end + +#endif//__renderer_vulkan_vkgen_vkfielddata_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddata.r b/libs/video/renderer/vulkan/vkgen/vkfielddata.r new file mode 100644 index 000000000..d13ff8965 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfielddata.r @@ -0,0 +1,45 @@ +#include + +#include "vkfielddata.h" +#include "vkgen.h" +#include "vkstruct.h" +#include "vktype.h" + +@implementation DataField + +-init:(PLItem *) item struct:(Struct *)strct field:(string)fname +{ + self = [super init:item struct:strct field:fname]; + if (!self) { + return self; + } + + value_field = [[item getObjectForKey:"data"] string]; + size_field = [[item getObjectForKey:"size"] string]; + return self; +} + +-writeParseData +{ + fprintf (output_file, "static parse_data_t parse_%s_%s_data = {\n", + struct_name, field_name); + fprintf (output_file, "\tfield_offset (%s, %s),\n", + struct_name, value_field); + if (size_field) { + fprintf (output_file, "\tfield_offset (%s, %s),\n", + struct_name, size_field); + } else { + fprintf (output_file, "\tt-1,\n"); + } + fprintf (output_file, "};\n"); + return self; +} + +-writeField +{ + fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", + field_name, "QFBinary", "data", struct_name, field_name); + return self; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.h b/libs/video/renderer/vulkan/vkgen/vkfielddef.h new file mode 100644 index 000000000..0363a9e7f --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.h @@ -0,0 +1,28 @@ +#ifndef __renderer_vulkan_vkgen_vkfielddef_h +#define __renderer_vulkan_vkgen_vkfielddef_h + +#include +#include + +@class PLItem; +@class Struct; +@class Type; + +@interface FieldDef: Object +{ + int line; + qfot_var_t *field; + string struct_name; + string field_name; + string value_field; + string size_field; +} ++fielddef:(PLItem *)item struct:(Struct *)strct field:(string)fname; +-init:(PLItem *)item struct:(Struct *)strct field:(string)fname; +-writeParseData; +-writeField; +-writeSymbol; +-(string) name; +@end + +#endif//__renderer_vulkan_vkgen_vkfielddef_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.r b/libs/video/renderer/vulkan/vkgen/vkfielddef.r new file mode 100644 index 000000000..9cc35c13a --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.r @@ -0,0 +1,95 @@ +#include +#include + +#include "vkfieldarray.h" +#include "vkfieldauto.h" +#include "vkfielddata.h" +#include "vkfielddef.h" +#include "vkfieldsingle.h" +#include "vkfieldstring.h" +#include "vkstruct.h" + +@implementation FieldDef + ++fielddef:(PLItem *)item struct:(Struct *)strct field:(string)fname +{ + string record = [item string]; + PLItem *type_desc = [item getObjectForKey:"type"]; + + if (!item) { + record = "auto"; + } + if (!record) { + if (item && !type_desc) { + return nil; + } + record = [type_desc string]; + if (!record) { + record = [[type_desc getObjectAtIndex:0] string]; + } + } + switch (record) { + case "auto": + return [[[AutoField alloc] init:item struct:strct field:fname] autorelease]; + case "string": + return [[[StringField alloc] init:item struct:strct field:fname] autorelease]; + case "data": + return [[[DataField alloc] init:item struct:strct field:fname] autorelease]; + case "single": + return [[[SingleField alloc] init:item struct:strct field:fname] autorelease]; + case "array": + return [[[ArrayField alloc] init:item struct:strct field:fname] autorelease]; + } + return nil; +} + +-init:(PLItem *)item struct:(Struct *)strct field:(string)fname +{ + self = [super init]; + if (!self) { + return self; + } + + line = [item line]; + struct_name = str_hold ([strct outname]); + field_name = str_hold (fname); + return self; +} + +-fromField:(qfot_var_t *)field struct:(Struct *)strct +{ + return self; +} + +-(void)dealloc +{ + str_free (struct_name); + str_free (field_name); +} + +-writeParseData +{ + fprintf (output_file, "undefined record type parse: %d\n", line); + return self; +} + +-writeField +{ + fprintf (output_file, "undefined record type field: %d\n", line); + return self; +} + +-writeSymbol +{ + fprintf (output_file, + "\t{\"%s\", 0/*FIXME*/, (void *) field_offset (%s, %s)},\n", + field_name, struct_name, value_field); + return self; +} + +-(string) name +{ + return field_name; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldsingle.h b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.h new file mode 100644 index 000000000..2fcd312c4 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.h @@ -0,0 +1,12 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldsingle_h +#define __renderer_vulkan_vkgen_vkfieldsingle_h + +#include "vkfielddef.h" + +@interface SingleField: FieldDef +{ + string type; +} +@end + +#endif//__renderer_vulkan_vkgen_vkfieldsingle_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r new file mode 100644 index 000000000..e30ced3dd --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r @@ -0,0 +1,46 @@ +#include + +#include "vkfieldsingle.h" +#include "vkgen.h" +#include "vktype.h" + +@implementation SingleField + +-init:(PLItem *) item struct:(Struct *)strct field:(string)fname +{ + self = [super init:item struct:strct field:fname]; + if (!self) { + return self; + } + + PLItem *desc = [item getObjectForKey:"type"]; + type = [[desc getObjectAtIndex:1] string]; + + value_field = [[item getObjectForKey:"value"] string]; + return self; +} + +-writeParseData +{ + Type *field_type = [[Type lookup: type] dereference]; + + fprintf (output_file, "static parse_single_t parse_%s_%s_data = {\n", + struct_name, field_name); + fprintf (output_file, "\t%s,\n", [field_type parseType]); + fprintf (output_file, "\tsizeof (%s),\n", type); + fprintf (output_file, "\tparse_%s,\n", type); + fprintf (output_file, "\tfield_offset (%s, %s),\n", + struct_name, value_field); + fprintf (output_file, "};\n"); + return self; +} + +-writeField +{ + string parse_type = [[[Type lookup: type] dereference] parseType]; + fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", + field_name, parse_type, "single", struct_name, field_name); + return self; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldstring.h b/libs/video/renderer/vulkan/vkgen/vkfieldstring.h new file mode 100644 index 000000000..fead71504 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldstring.h @@ -0,0 +1,9 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldstring_h +#define __renderer_vulkan_vkgen_vkfieldstring_h + +#include "vkfielddef.h" + +@interface StringField: FieldDef +@end + +#endif//__renderer_vulkan_vkgen_vkfieldstring_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldstring.r b/libs/video/renderer/vulkan/vkgen/vkfieldstring.r new file mode 100644 index 000000000..ff0ba525d --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldstring.r @@ -0,0 +1,36 @@ +#include + +#include "vkfieldstring.h" +#include "vkgen.h" + +@implementation StringField + +-init:(PLItem *) item struct:(Struct *)strct field:(string)fname +{ + self = [super init:item struct:strct field:fname]; + if (!self) { + return self; + } + + value_field = [[item getObjectForKey:"string"] string]; + return self; +} + +-writeParseData +{ + fprintf (output_file, "static parse_string_t parse_%s_%s_data = {\n", + struct_name, field_name); + fprintf (output_file, "\tfield_offset (%s, %s),\n", + struct_name, value_field); + fprintf (output_file, "};\n"); + return self; +} + +-writeField +{ + fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", + field_name, "QFString", "string", struct_name, field_name); + return self; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.h b/libs/video/renderer/vulkan/vkgen/vkgen.h index e60499f25..8f9cd5c93 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.h +++ b/libs/video/renderer/vulkan/vkgen/vkgen.h @@ -12,6 +12,7 @@ void printf (string fmt, ...); void fprintf (QFile file, string format, ...); extern Array *queue; extern Array *output_types; +extern PLItem *parse; extern QFile output_file; extern QFile header_file; extern hashtab_t *processed_types; diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 025e3d2cc..7a1edab8a 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -37,6 +37,7 @@ hashtab_t *processed_types; Array *queue; Array *output_types; +PLItem *parse; QFile output_file; QFile header_file; @@ -147,7 +148,6 @@ main(int argc, string *argv) QFile plist_file; PLItem *plist; PLItem *search; - PLItem *parse; arp_start (); @@ -199,6 +199,9 @@ main(int argc, string *argv) id obj = [queue objectAtIndex:0]; [queue removeObjectAtIndex:0]; if ([obj class] == [Struct class]) { + if ([[parse getObjectForKey:[obj name]] string] == "skip") { + continue; + } [obj forEachFieldCall:struct_func]; } [output_types addObject:obj]; @@ -235,7 +238,7 @@ main(int argc, string *argv) } arp_start (); - [obj writeTable:parse]; + [obj writeTable]; arp_end (); } fprintf (output_file, "static void\n"); @@ -247,7 +250,7 @@ main(int argc, string *argv) continue; } arp_start (); - [obj writeSymtabInit:parse]; + [obj writeSymtabInit]; arp_end (); } fprintf (output_file, "}\n"); diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index c251cb4c0..048b3332f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -10,10 +10,13 @@ @interface Struct: Type { + string outname; } -(void) forEachFieldCall: (varfunc) func; --(void) writeTable: (PLItem *) parse; --(void) writeSymtabInit:(PLItem *) parse; +-(qfot_var_t *)findField:(string) fieldName; +-(void) writeTable; +-(void) writeSymtabInit; +-(string) outname; @end #endif//__renderer_vulkan_vkgen_vkstruct_h diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 6e6908bb8..6a8b21caa 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -6,6 +6,7 @@ #include #include +#include "vkfielddef.h" #include "vkgen.h" #include "vkstruct.h" @@ -46,122 +47,33 @@ return nil; } --(void) writeTable: (PLItem *) parse +-(void) writeTable { - string name = [self name]; - PLItem *field_dict = [parse getObjectForKey:name]; - PLItem *field_defs = [field_dict allKeys]; - Type *field_type; + PLItem *field_dict = [parse getObjectForKey:[self name]]; PLItem *new_name = [field_dict getObjectForKey:".name"]; + Array *field_defs = [Array array]; + if ([parse string] == "skip") { + return; + } if (new_name) { - name = [new_name string]; + outname = str_hold ([new_name string]); } - if (field_defs) { - PLItem *field_def; - qfot_var_t *field; + if (field_dict) { + PLItem *field_keys = [field_dict allKeys]; - for (int i = [field_defs count]; i-- > 0; ) { - string field_name = [[field_defs getObjectAtIndex:i] string]; - field_def = [field_dict getObjectForKey:field_name]; - PLItem *type_desc = [field_def getObjectForKey:"type"]; - string type_record; - string type_type; - string size_field = nil; - string value_field = nil; + for (int i = [field_keys count]; i-- > 0; ) { + string field_name = [[field_keys getObjectAtIndex:i] string]; - if (!type_desc || str_mid(field_name, 0, 1) == ".") { - continue; - } - type_record = [[type_desc getObjectAtIndex:0] string]; - type_type = [[type_desc getObjectAtIndex:1] string]; - - field_type = [[Type lookup: type_type] dereference]; - fprintf (output_file, "static parse_%s_t parse_%s_%s_data = {\n", - type_record, name, field_name); - if (type_record == "single") { - fprintf (output_file, "\t%s,\n", [field_type parseType]); - fprintf (output_file, "\tsizeof (%s),\n", type_type); - fprintf (output_file, "\tparse_%s,\n", type_type); - value_field = [[field_def getObjectForKey:"value"] string]; - fprintf (output_file, "\tfield_offset (%s, %s),\n", - name, value_field); - } else if (type_record == "array") { - fprintf (output_file, "\t%s,\n", [field_type parseType]); - fprintf (output_file, "\tsizeof (%s),\n", type_type); - fprintf (output_file, "\tparse_%s,\n", type_type); - value_field = [[field_def getObjectForKey:"values"] string]; - size_field = [[field_def getObjectForKey:"size"] string]; - fprintf (output_file, "\tfield_offset (%s, %s),\n", - name, value_field); - if (size_field) { - fprintf (output_file, "\tfield_offset (%s, %s),\n", - name, size_field); - } else { - fprintf (output_file, "\t-1,\n"); - } - } else if (type_record == "data") { - value_field = [[field_def getObjectForKey:"data"] string]; - size_field = [[field_def getObjectForKey:"size"] string]; - fprintf (output_file, "\tfield_offset (%s, %s),\n", - name, value_field); - if (size_field) { - fprintf (output_file, "\tfield_offset (%s, %s),\n", - name, size_field); - } else { - fprintf (output_file, "\t-1,\n"); - } - } else { - fprintf (output_file, "\tno type,\n"); - } - fprintf (output_file, "};\n"); - } - } - fprintf (output_file, "static plfield_t %s_fields[] = {\n", name); - if (field_defs) { - PLItem *field_def; - qfot_var_t *field; - - for (int i = [field_defs count]; i-- > 0; ) { - string field_name = [[field_defs getObjectAtIndex:i] string]; if (str_mid(field_name, 0, 1) == ".") { continue; } - field_def = [field_dict getObjectForKey:field_name]; - if ([field_def string] == "auto") { - field = [self findField:field_name]; - if (!field) { - continue; - } - field_type = [Type findType: field.type]; - fprintf (output_file, - "\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n", - field_name, name, field_name, - [field_type parseType], [field_type parseFunc], - [field_type parseData]); - } else { - PLItem *type_desc = [field_def getObjectForKey:"type"]; - string type_record; - string type_type; - string parseType = "no type"; - - type_record = [[type_desc getObjectAtIndex:0] string]; - type_type = [[type_desc getObjectAtIndex:1] string]; - - field_type = [[Type lookup: type_type] dereference]; - if (type_record == "single") { - parseType = [field_type parseType]; - } else if (type_record == "array") { - parseType = "QFArray"; - } else if (type_record == "data") { - parseType = "QFBinary"; - } - fprintf (output_file, - "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", - field_name, parseType, type_record, - name, field_name); - } + PLItem *field_item = [field_dict getObjectForKey:field_name]; + FieldDef *field_def = [FieldDef fielddef:field_item + struct:self + field:field_name]; + [field_defs addObject: field_def]; } } else { for (int i = 0; i < type.strct.num_fields; i++) { @@ -169,76 +81,47 @@ if (field.name == "sType" || field.name == "pNext") { continue; } - field_type = [Type findType: field.type]; - fprintf (output_file, - "\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n", - field.name, name, field.name, - [field_type parseType], [field_type parseFunc], - [field_type parseData]); + FieldDef *field_def = [FieldDef fielddef:nil + struct:self + field:field.name]; + [field_defs addObject: field_def]; } } + for (int i = [field_defs count]; i-- > 0; ) { + FieldDef *field_def = [field_defs objectAtIndex:i]; + [field_def writeParseData]; + } + fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self outname]); + for (int i = [field_defs count]; i-- > 0; ) { + FieldDef *field_def = [field_defs objectAtIndex:i]; + [field_def writeField]; + } fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); fprintf (header_file, "int parse_%s (const plfield_t *field," " const plitem_t *item, void *data, plitem_t *messages," " void *context);\n", - name); + [self outname]); fprintf (output_file, "int parse_%s (const plfield_t *field," " const plitem_t *item, void *data, plitem_t *messages," " void *context)\n", - name); + [self outname]); fprintf (output_file, "{\n"); fprintf (output_file, "\treturn PL_ParseDictionary (%s_fields, item, data, messages," " context);\n", - name); + [self outname]); fprintf (output_file, "}\n"); - fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", name); + fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self outname]); if (field_defs) { PLItem *field_def; qfot_var_t *field; for (int i = [field_defs count]; i-- > 0; ) { - string field_name = [[field_defs getObjectAtIndex:i] string]; - field_def = [field_dict getObjectForKey:field_name]; - PLItem *type_desc = [field_def getObjectForKey:"type"]; - string type_record; - string type_type; - string size_field = nil; - string value_field = nil; - - if (str_mid(field_name, 0, 1) == ".") { - continue; - } - field_def = [field_dict getObjectForKey:field_name]; - if ([field_def string] == "auto") { - field = [self findField:field_name]; - if (!field) { - continue; - } - field_type = [Type findType: field.type]; - fprintf (output_file, - "\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n", - field_name, [field_type cexprType], name, field_name); - } else { - type_record = [[type_desc getObjectAtIndex:0] string]; - if (type_record == "single") { - value_field = [[field_def getObjectForKey:"value"] string]; - } else if (type_record == "array") { - value_field = [[field_def getObjectForKey:"values"] string]; - } else if (type_record == "data") { - value_field = [[field_def getObjectForKey:"data"] string]; - } - if (!value_field) { - value_field = field_name; - } - fprintf (output_file, - "\t{\"%s\", 0/*FIXME*/," - " (void *) field_offset (%s, %s)},\n", - field_name, name, value_field); - } + FieldDef *field_def = [field_defs objectAtIndex:i]; + [field_def writeSymbol]; } } else { for (int i = 0; i < type.strct.num_fields; i++) { @@ -246,40 +129,48 @@ if (field.name == "sType" || field.name == "pNext") { continue; } - field_type = [Type findType: field.type]; + Type *field_type = [Type findType: field.type]; fprintf (output_file, "\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n", - field.name, [field_type cexprType], name, field.name); + field.name, [field_type cexprType], [self outname], field.name); } } fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); - fprintf (output_file, "static exprtab_t %s_symtab = {\n", name); - fprintf (output_file, "\t%s_symbols,\n", name); + fprintf (output_file, "static exprtab_t %s_symtab = {\n", [self outname]); + fprintf (output_file, "\t%s_symbols,\n", [self outname]); fprintf (output_file, "};\n"); - fprintf (output_file, "exprtype_t %s_type = {\n", name); - fprintf (output_file, "\t\"%s\",\n", name); - fprintf (output_file, "\tsizeof (%s),\n", name); + fprintf (output_file, "exprtype_t %s_type = {\n", [self outname]); + fprintf (output_file, "\t\"%s\",\n", [self outname]); + fprintf (output_file, "\tsizeof (%s),\n", [self outname]); fprintf (output_file, "\tcexpr_struct_binops,\n"); fprintf (output_file, "\t0,\n"); - fprintf (output_file, "\t&%s_symtab,\n", name); + fprintf (output_file, "\t&%s_symtab,\n", [self outname]); fprintf (output_file, "};\n"); - fprintf (header_file, "extern exprtype_t %s_type;\n", name); + fprintf (output_file, "\n"); + fprintf (header_file, "extern exprtype_t %s_type;\n", [self outname]); } --(void) writeSymtabInit:(PLItem *) parse +-(void) writeSymtabInit { - string name = [self name]; - PLItem *field_dict = [parse getObjectForKey:name]; - PLItem *new_name = [field_dict getObjectForKey:".name"]; + PLItem *field_dict = [parse getObjectForKey:[self outname]]; - if (new_name) { - name = [new_name string]; + if ([parse string] == "skip") { + return; } - fprintf (output_file, "\tcexpr_init_symtab (&%s_symtab, context);\n", name); + fprintf (output_file, "\tcexpr_init_symtab (&%s_symtab, context);\n", + [self outname]); +} + +-(string) outname +{ + if (outname) { + return outname; + } + return [self name]; } -(string) cexprType diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index fbe46d512..fbfbdf226 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -122,6 +122,10 @@ typedef struct parse_data_s { size_t size_offset; } parse_data_t; +typedef struct parse_string_s { + size_t value_offset; +} parse_string_t; + static int parse_uint32_t (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { @@ -239,7 +243,7 @@ static int parse_data (const plfield_t *field, const plitem_t *item, const void *bindata = PL_BinaryData (item); size_t binsize = PL_BinarySize (item); - Sys_Printf ("parse_array: %s %zd %d %p %p %p\n", + Sys_Printf ("parse_data: %s %zd %d %p %p %p\n", field->name, field->offset, field->type, field->parser, field->data, data); Sys_Printf (" %zd %zd\n", datad->value_offset, datad->size_offset); @@ -253,6 +257,24 @@ static int parse_data (const plfield_t *field, const plitem_t *item, return 1; } +static int parse_string (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + __auto_type string = (parse_string_t *) field->data; + __auto_type value = (char **) ((byte *)data + string->value_offset); + + const char *str = PL_BinaryData (item); + + Sys_Printf ("parse_string: %s %zd %d %p %p %p\n", + field->name, field->offset, field->type, field->parser, + field->data, data); + Sys_Printf (" %zd\n", string->value_offset); + Sys_Printf (" %s\n", str); + + *value = strdup (str); + return 1; +} + #include "libs/video/renderer/vulkan/vkparse.cinc" typedef struct qfv_renderpass_s { From 25ade4c0f3ab289f4b04946dc2701fbee4f81b84 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Dec 2020 01:36:17 +0900 Subject: [PATCH 1115/3664] [vulkan] Add support for custom parsers And provisionally parse shader stage defs. --- include/QF/Vulkan/pipeline.h | 3 - include/QF/Vulkan/qf_vid.h | 3 +- include/QF/Vulkan/shader.h | 9 +++ libs/video/renderer/vid_render_vulkan.c | 3 + libs/video/renderer/vulkan/pipeline.c | 17 ------ libs/video/renderer/vulkan/qfpipeline.plist | 15 +++++ libs/video/renderer/vulkan/shader.c | 39 +++++++++++- .../video/renderer/vulkan/vkgen/Makemodule.am | 1 + .../renderer/vulkan/vkgen/vkfieldcustom.h | 14 +++++ .../renderer/vulkan/vkgen/vkfieldcustom.r | 60 +++++++++++++++++++ libs/video/renderer/vulkan/vkgen/vkfielddef.r | 3 + libs/video/renderer/vulkan/vkparse.c | 55 ++++++++++++----- libs/video/renderer/vulkan/vkparse.h | 6 ++ libs/video/renderer/vulkan/vkparse.plist | 33 +++++++++- .../video/renderer/vulkan/vulkan_vid_common.c | 40 ++++++++++++- 15 files changed, 261 insertions(+), 40 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldcustom.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldcustom.r diff --git a/include/QF/Vulkan/pipeline.h b/include/QF/Vulkan/pipeline.h index f77585217..c7d5013de 100644 --- a/include/QF/Vulkan/pipeline.h +++ b/include/QF/Vulkan/pipeline.h @@ -128,9 +128,6 @@ typedef struct qfv_pipelinecacheset_s #define QFV_AllocPipelineCacheSet(num, allocator) \ DARRAY_ALLOCFIXED (qfv_pipelinecacheset_t, num, allocator) -VkShaderModule QFV_CreateShaderModule (struct qfv_device_s *device, - size_t size, const uint32_t *code); - struct dstring_s; VkPipelineCache QFV_CreatePipelineCache (struct qfv_device_s *device, struct dstring_s *cacheData); diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index d7ef64a97..d380d1236 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -38,8 +38,9 @@ struct vulkan_ctx_s; void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); -void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); +void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); +void Vulkan_CreatePipelines (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/shader.h b/include/QF/Vulkan/shader.h index 6b8321cdd..b13f6a618 100644 --- a/include/QF/Vulkan/shader.h +++ b/include/QF/Vulkan/shader.h @@ -3,11 +3,20 @@ struct qfv_device_s; struct vulkan_ctx_s; +struct plitem_s; +struct parsectx_s; VkShaderModule QFV_CreateShaderModule (struct qfv_device_s *device, const char *path); +void QFV_DestroyShaderModule (struct qfv_device_s *device, + VkShaderModule module); +VkShaderModule QFV_FindShaderModule (struct vulkan_ctx_s *ctx, + const char *name); void QFV_RegisterShaderModule (struct vulkan_ctx_s *ctx, const char *name, VkShaderModule module); void QFV_DeregisterShaderModule (struct vulkan_ctx_s *ctx, const char *name); +int parse_VkShaderModule (const struct plitem_s *item, void **data, + struct plitem_s *messages, + struct parsectx_s *context); #endif//__QF_Vulkan_shader_h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 85181547c..52246162b 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -64,6 +64,9 @@ vulkan_R_Init (void) Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_CreateFramebuffers (vulkan_ctx); + // FIXME this should be staged so screen updates can begin while pipelines + // are being built + Vulkan_CreatePipelines (vulkan_ctx); qfv_swapchain_t *sc = vulkan_ctx->swapchain; diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c index 119fbf303..bfe48ce9f 100644 --- a/libs/video/renderer/vulkan/pipeline.c +++ b/libs/video/renderer/vulkan/pipeline.c @@ -64,23 +64,6 @@ #include "util.h" -VkShaderModule -QFV_CreateShaderModule (qfv_device_t *device, - size_t size, const uint32_t *code) -{ - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - VkShaderModuleCreateInfo createInfo = { - VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 0, 0, - size, code, - }; - - VkShaderModule module; - dfunc->vkCreateShaderModule (dev, &createInfo, 0, &module); - return module; -} - VkPipelineCache QFV_CreatePipelineCache (qfv_device_t *device, dstring_t *cacheData) { diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 66c9e0adb..7af624b99 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -1,4 +1,19 @@ { + modules = ( + // specify shader modules to load into memory + { + // the name of the module for referecy by the pipeline + name = passthrough; + // the path to the spv file to load + // $shader refers to the shader install path + // $builtin refers to compiled-in shaders + file = $builtin/passthrough.vert; + }, + { + name = pushcolor; + file = $builtin/pushcolor.frag; + }, + ); renderpass = { attachments = ( { diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 704e01996..5ee89ca25 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -42,6 +42,7 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/Vulkan/qf_vid.h" @@ -52,6 +53,7 @@ #include "QF/Vulkan/shader.h" #include "vid_vulkan.h" +#include "vkparse.h" static #include "libs/video/renderer/vulkan/passthrough.vert.spvc" @@ -92,7 +94,7 @@ QFV_CreateShaderModule (qfv_device_t *device, const char *shader_path) shaderdata_t _data = {}; shaderdata_t *data = 0; dstring_t *path = 0; - QFile *file; + QFile *file = 0; VkShaderModule shader = 0; if (strncmp (shader_path, BUILTIN, BUILTIN_SIZE) == 0) { @@ -142,6 +144,15 @@ QFV_CreateShaderModule (qfv_device_t *device, const char *shader_path) return shader; } +void +QFV_DestroyShaderModule (qfv_device_t *device, VkShaderModule module) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyShaderModule (dev, module, 0); +} + static shadermodule_t * new_module (vulkan_ctx_t *ctx) { @@ -169,10 +180,21 @@ sm_free (void *sm, void *ctx) del_module (sm, ctx); } +VkShaderModule +QFV_FindShaderModule (vulkan_ctx_t *ctx, const char *name) +{ + //FIXME + if (!ctx->shadermodules) { + ctx->shadermodules = Hash_NewTable (127, sm_getkey, sm_free, ctx, 0); + } + return Hash_Find (ctx->shadermodules, name); +} + void QFV_RegisterShaderModule (vulkan_ctx_t *ctx, const char *name, VkShaderModule module) { + //FIXME if (!ctx->shadermodules) { ctx->shadermodules = Hash_NewTable (127, sm_getkey, sm_free, ctx, 0); } @@ -190,3 +212,18 @@ QFV_DeregisterShaderModule (vulkan_ctx_t *ctx, const char *name) } Hash_Free (ctx->shadermodules, Hash_Del (ctx->shadermodules, name)); } + +int +parse_VkShaderModule (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context) +{ + vulkan_ctx_t *ctx = context->vctx; + const char *name = PL_String (item); + __auto_type mptr = (VkShaderModule *)data[0]; + VkShaderModule module = QFV_FindShaderModule (ctx, name); + if (module) { + *mptr = module; + return 1; + } + return 0; +} diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 31c22d936..4847bf6fd 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -6,6 +6,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkenum.r \ libs/video/renderer/vulkan/vkgen/vkfieldarray.r \ libs/video/renderer/vulkan/vkgen/vkfieldauto.r \ + libs/video/renderer/vulkan/vkgen/vkfieldcustom.r \ libs/video/renderer/vulkan/vkgen/vkfielddata.r \ libs/video/renderer/vulkan/vkgen/vkfielddef.r \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.r \ diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.h b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.h new file mode 100644 index 000000000..4b7672a9e --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.h @@ -0,0 +1,14 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldcustom_h +#define __renderer_vulkan_vkgen_vkfieldcustom_h + +#include "vkfielddef.h" + +@interface CustomField: FieldDef +{ + string pltype; + string parser; + PLItem *fields; +} +@end + +#endif//__renderer_vulkan_vkgen_vkfieldcustom_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r new file mode 100644 index 000000000..e00085ac1 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r @@ -0,0 +1,60 @@ +#include + +#include "vkfieldcustom.h" +#include "vkgen.h" +#include "vktype.h" + +@implementation CustomField + +-init:(PLItem *) item struct:(Struct *)strct field:(string)fname +{ + self = [super init:item struct:strct field:fname]; + if (!self) { + return self; + } + + PLItem *desc = [item getObjectForKey:"type"]; + pltype = [[desc getObjectAtIndex:1] string]; + parser = [[desc getObjectAtIndex:2] string]; + + fields = [item getObjectForKey:"fields"]; + return self; +} + +-writeParseData +{ + fprintf (output_file, "static size_t parse_%s_%s_offsets = {\n", + struct_name, field_name); + for (int i = 0, count = [fields count]; i < count; i++) { + string field = [[fields getObjectAtIndex:i] string]; + fprintf (output_file, "\tfield_offset (%s, %s),\n", + struct_name, field); + } + fprintf (output_file, "};\n"); + + fprintf (output_file, "static parse_custom_t parse_%s_%s_data = {\n", + struct_name, field_name); + fprintf (output_file, "\t%s,\n", parser); + fprintf (output_file, "\t&parse_%s_%s_offsets,\n", + struct_name, field_name); + fprintf (output_file, "\t%d,\n", [fields count]); + fprintf (output_file, "};\n"); + return self; +} + +-writeField +{ + fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", + field_name, pltype, "custom", struct_name, field_name); + return self; +} + +-writeSymbol +{ + fprintf (output_file, + "\t{\"%s\", 0/*FIXME*/, 0/*(void *) field_offset (%s, %s)*/},\n", + field_name, struct_name, "FIXME"); + return self; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.r b/libs/video/renderer/vulkan/vkgen/vkfielddef.r index 9cc35c13a..6aba1df05 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfielddef.r +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.r @@ -3,6 +3,7 @@ #include "vkfieldarray.h" #include "vkfieldauto.h" +#include "vkfieldcustom.h" #include "vkfielddata.h" #include "vkfielddef.h" #include "vkfieldsingle.h" @@ -31,6 +32,8 @@ switch (record) { case "auto": return [[[AutoField alloc] init:item struct:strct field:fname] autorelease]; + case "custom": + return [[[CustomField alloc] init:item struct:strct field:fname] autorelease]; case "string": return [[[StringField alloc] init:item struct:strct field:fname] autorelease]; case "data": diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index fbfbdf226..5b198a807 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -56,6 +56,7 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/renderpass.h" +#include "QF/Vulkan/shader.h" #include "QF/Vulkan/swapchain.h" #include "compat.h" @@ -126,8 +127,16 @@ typedef struct parse_string_s { size_t value_offset; } parse_string_t; -static int parse_uint32_t (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) +typedef struct parse_custom_s { + int (*parse) (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context); + size_t *offsets; + size_t num_offsets; +} parse_custom_t; + +static int +parse_uint32_t (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) { int ret = 1; const char *valstr = PL_String (item); @@ -154,12 +163,13 @@ static int parse_uint32_t (const plfield_t *field, const plitem_t *item, return ret; } -static int parse_enum (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) +static int +parse_enum (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) { int ret = 1; __auto_type enm = (exprenum_t *) field->data; - exprctx_t ectx = *(exprctx_t *)context; + exprctx_t ectx = *((parsectx_t *)context)->ectx; exprval_t result = { enm->type, data }; ectx.symtab = enm->symtab; ectx.result = &result; @@ -172,8 +182,9 @@ static int parse_enum (const plfield_t *field, const plitem_t *item, return ret; } -static int parse_single (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) +static int +parse_single (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) { __auto_type single = (parse_single_t *) field->data; void *flddata = (byte *)data + single->value_offset; @@ -197,8 +208,9 @@ static int parse_single (const plfield_t *field, const plitem_t *item, return 1; } -static int parse_array (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) +static int +parse_array (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) { __auto_type array = (parse_array_t *) field->data; __auto_type value = (void **) ((byte *)data + array->value_offset); @@ -233,8 +245,9 @@ static int parse_array (const plfield_t *field, const plitem_t *item, return 1; } -static int parse_data (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) +static int +parse_data (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) { __auto_type datad = (parse_data_t *) field->data; __auto_type value = (void **) ((byte *)data + datad->value_offset); @@ -257,8 +270,9 @@ static int parse_data (const plfield_t *field, const plitem_t *item, return 1; } -static int parse_string (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) +static int +parse_string (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) { __auto_type string = (parse_string_t *) field->data; __auto_type value = (char **) ((byte *)data + string->value_offset); @@ -275,6 +289,18 @@ static int parse_string (const plfield_t *field, const plitem_t *item, return 1; } +static int +parse_custom (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + __auto_type custom = (parse_custom_t *) field->data; + void **offsets = alloca (custom->num_offsets * sizeof (void *)); + for (size_t i = 0; i < custom->num_offsets; i++) { + offsets[i] = data + custom->offsets[i]; + } + return custom->parse (item, offsets, messages, context); +} + #include "libs/video/renderer/vulkan/vkparse.cinc" typedef struct qfv_renderpass_s { @@ -331,6 +357,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) }; exprtab_t vars_tab = { var_syms, 0 }; exprctx_t exprctx = {}; + parsectx_t parsectx = { &exprctx, ctx }; exprctx.external_variables = &vars_tab; exprctx.memsuper = new_memsuper (); @@ -340,7 +367,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) cexpr_init_symtab (&vars_tab, &exprctx); if (!PL_ParseDictionary (renderpass_fields, plist, - &renderpass_data, messages, &exprctx)) { + &renderpass_data, messages, &parsectx)) { for (int i = 0; i < PL_A_NumObjects (messages); i++) { Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index ae8a30af9..b95475bda 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -1,9 +1,15 @@ #ifndef __vkparse_h #define __vkparse_h +#include "QF/cexpr.h" #include "QF/Vulkan/renderpass.h" #include "libs/video/renderer/vulkan/vkparse.hinc" +typedef struct parsectx_s { + struct exprctx_s *ectx; + struct vulkan_ctx_s *vctx; +} parsectx_t; + VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); void QFV_InitParse (void); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 1441a0267..1ba7e8bb4 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -3,6 +3,8 @@ VkAttachmentDescription, VkSubpassDescription, VkSubpassDependency, + VkSpecializationInfo, + VkPipelineShaderStageCreateInfo, qfv_swapchain_t, ); parse = { @@ -37,6 +39,35 @@ size = preserveAttachmentCount; values = pPreserveAttachments; }; - } + }; + VkSpecializationInfo = { + mapEntries = { + type = (array, VkSpecializationMapEntry); + size = mapEntryCount; + values = pMapEntries; + }; + data = { + type = data; + size = dataSize; + data = pData; + }; + }; + VkPipelineShaderStageCreateInfo = { + flags = auto; + stage = auto; + name = { + type = string; + string = pName; + }; + module = { + type = (custom, QFString, parse_VkShaderModule); + fields = (module); + }; + specializationInfo = { + type = (single, VkSpecializationInfo); + value = pSpecializationInfo; + }; + }; + VkShaderModuleCreateInfo = skip; } } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 9c2b021f4..78c4e9add 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -57,6 +57,7 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/renderpass.h" +#include "QF/Vulkan/shader.h" #include "QF/Vulkan/swapchain.h" #include "compat.h" @@ -260,7 +261,12 @@ static qfv_pipelinestagepair_t imageLayoutTransitionStages[] = { static plitem_t * qfv_load_pipeline (void) { - return PL_GetPropertyList (quakeforge_pipeline); + static plitem_t *pipeline; + + if (!pipeline) { + pipeline = PL_GetPropertyList (quakeforge_pipeline); + } + return pipeline; } void @@ -269,9 +275,9 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) plitem_t *item = qfv_load_pipeline (); if (!item || !(item = PL_ObjectForKey (item, "renderpass"))) { - Sys_Printf ("error loading pipeline\n"); + Sys_Printf ("error loading renderpass\n"); } else { - Sys_Printf ("Found renderer def\n"); + Sys_Printf ("Found renderpass def\n"); } qfv_device_t *device = ctx->device; VkDevice dev = device->dev; @@ -391,6 +397,34 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) ctx->renderpass.depthImage = 0; } +void +Vulkan_CreatePipelines (vulkan_ctx_t *ctx) +{ + plitem_t *item = qfv_load_pipeline (); + + if (!item || !(item = PL_ObjectForKey (item, "modules"))) { + Sys_Printf ("error loading modules\n"); + } else { + Sys_Printf ("Found modules def\n"); + } + for (int i = PL_A_NumObjects (item); i-- > 0; ) { + plitem_t *mod = PL_ObjectAtIndex (item, i); + const char *name = PL_String (PL_ObjectForKey (mod, "name")); + const char *file = PL_String (PL_ObjectForKey (mod, "file")); + if (!name || !file) { + continue; + } + if (QFV_FindShaderModule (ctx, name)) { + continue; + } + VkShaderModule module = QFV_CreateShaderModule (ctx->device, file); + if (module) { + Sys_Printf ("registering shader %s %p\n", name, module); + QFV_RegisterShaderModule (ctx, name, module); + } + } +} + void Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) { From 5b0da2b14ce2402a102875a3d7209f7a31774271 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Dec 2020 09:57:24 +0900 Subject: [PATCH 1116/3664] [util] Add an int to uint cast for cexpr --- libs/util/cexpr-parse.y | 6 +----- libs/util/cexpr-type.c | 8 ++++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index e789a40e9..eb56ed588 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -150,11 +150,7 @@ assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context) if (!src) { return; } - for (binop = dst->type->binops; binop && binop->op; binop++) { - if (binop->op == '=' && binop->other == src->type) { - break; - } - } + binop = cexpr_find_cast (dst->type, src->type); if (binop && binop->op) { binop->func (dst, src, dst, context); } else { diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index c0610b13d..c1dbbafb0 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -125,6 +125,13 @@ BINOP(uint, bor, unsigned, |) BINOP(uint, xor, unsigned, ^) BINOP(uint, rem, unsigned, %) +static void +uint_cast_int (const exprval_t *val1, const exprval_t *src, exprval_t *result, + exprctx_t *ctx) +{ + *(unsigned *) result->value = *(int *) src->value; +} + UNOP(uint, pos, unsigned, +) UNOP(uint, neg, unsigned, -) UNOP(uint, tnot, unsigned, !) @@ -142,6 +149,7 @@ binop_t uint_binops[] = { { '^', &cexpr_uint, &cexpr_uint, uint_xor }, { '%', &cexpr_uint, &cexpr_uint, uint_rem }, { MOD, &cexpr_uint, &cexpr_uint, uint_rem }, + { '=', &cexpr_int, &cexpr_uint, uint_cast_int }, {} }; From 2430f44d7b0330d49db79c32726f8dbbe76d9cb3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Dec 2020 09:58:27 +0900 Subject: [PATCH 1117/3664] [vulkan] Support parsing numeric types --- libs/video/renderer/vulkan/vkgen/vktype.r | 12 +++++ libs/video/renderer/vulkan/vkparse.c | 54 +++++++++++++++++------ 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index 5d6c1b7ae..fbe44e350 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -74,6 +74,9 @@ static string get_type_key (void *type, void *unused) -(string) name { + if (type.meta == ty_basic) { + return pr_type_name[type.type]; + } //FIXME extract alias name and return proper type name return type.encoding; } @@ -98,16 +101,25 @@ static string get_type_key (void *type, void *unused) -(string) parseType { + if (type.meta == ty_basic) { + return "QFString"; + } return "no parse"; } -(string) parseFunc { + if (type.meta == ty_basic) { + return "parse_basic"; + } return "0"; } -(string) parseData { + if (type.meta == ty_basic) { + return "&cexpr_" + pr_type_name[type.type]; + } return "0"; } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 5b198a807..ac198e756 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -135,29 +135,55 @@ typedef struct parse_custom_s { } parse_custom_t; static int -parse_uint32_t (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) +parse_basic (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) { int ret = 1; + __auto_type etype = (exprtype_t *) field->data; + exprctx_t ectx = *((parsectx_t *) context)->ectx; + exprval_t result = { etype, data }; + ectx.symtab = 0; + ectx.result = &result; const char *valstr = PL_String (item); //Sys_Printf ("parse_uint32_t: %s %zd %d %p %p: %s\n", // field->name, field->offset, field->type, field->parser, // field->data, valstr); if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) { + //FIXME handle subpass in a separate parser? *(uint32_t *) data = VK_SUBPASS_EXTERNAL; } else { - char *end; - unsigned long val = strtoul (valstr, &end, 0); - if (*valstr && !*end && val <= 0xffffffff) { - *(uint32_t *) data = val; - } else if (val > 0xffffffff) { - PL_Message (messages, item, "%lu bigger than 32 bits", val); - ret = 0; - } else { - PL_Message (messages, item, "invalid char at %d in '%s'\n", - (int) (end - valstr), valstr); - ret = 0; - } + Sys_Printf ("parse_uint32_t: %s %zd %d %p %p %s\n", + field->name, field->offset, field->type, field->parser, + field->data, valstr); + ret = !cexpr_eval_string (valstr, &ectx); + Sys_Printf (" %x\n", *(uint32_t *)data); + } + + return ret; +} + +static int +parse_uint32_t (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + int ret = 1; + exprctx_t ectx = *((parsectx_t *) context)->ectx; + exprval_t result = { &cexpr_uint, data }; + ectx.symtab = 0; + ectx.result = &result; + const char *valstr = PL_String (item); + //Sys_Printf ("parse_uint32_t: %s %zd %d %p %p: %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); + if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) { + //FIXME handle subpass in a separate parser? + *(uint32_t *) data = VK_SUBPASS_EXTERNAL; + } else { + Sys_Printf ("parse_uint32_t: %s %zd %d %p %p %s\n", + field->name, field->offset, field->type, field->parser, + field->data, valstr); + ret = !cexpr_eval_string (valstr, &ectx); + Sys_Printf (" %d\n", *(uint32_t *)data); } return ret; From 5c0ce2c414527e8bac3a84f79bb18e6312ccc3df Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Dec 2020 11:50:52 +0900 Subject: [PATCH 1118/3664] [vulkan] Correct the usage of custom field offsets I had missed the array declaration and thus initialized the pointer to the offset array incorrectly. Didn't show up until I tried using multiple offsets. --- libs/video/renderer/vulkan/vkgen/vkfieldcustom.r | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r index e00085ac1..3e9e56c74 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r @@ -23,7 +23,7 @@ -writeParseData { - fprintf (output_file, "static size_t parse_%s_%s_offsets = {\n", + fprintf (output_file, "static size_t parse_%s_%s_offsets[] = {\n", struct_name, field_name); for (int i = 0, count = [fields count]; i < count; i++) { string field = [[fields getObjectAtIndex:i] string]; @@ -35,7 +35,7 @@ fprintf (output_file, "static parse_custom_t parse_%s_%s_data = {\n", struct_name, field_name); fprintf (output_file, "\t%s,\n", parser); - fprintf (output_file, "\t&parse_%s_%s_offsets,\n", + fprintf (output_file, "\tparse_%s_%s_offsets,\n", struct_name, field_name); fprintf (output_file, "\t%d,\n", [fields count]); fprintf (output_file, "};\n"); From cb2bdb0224c915b8f8dcd2e59781a9ecb6bb57de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Dec 2020 13:33:37 +0900 Subject: [PATCH 1119/3664] [util] Rename PL_ParseDictionary to PL_ParseStruct Struct is far more appropriate for its function, and I need to parse a dictionary into a hash table. --- include/QF/qfplist.h | 4 ++-- libs/util/qfplist.c | 4 ++-- libs/video/renderer/vulkan/vkgen/vkstruct.r | 2 +- libs/video/renderer/vulkan/vkparse.c | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 1d45426d2..e8a64f054 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -342,8 +342,8 @@ void PL_Free (plitem_t *item); \param context Additional context data passed to the parser. \return 0 if there are any errors, 1 if there are no errors. */ -int PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, - void *data, plitem_t *messages, void *context); +int PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, + void *data, plitem_t *messages, void *context); int PL_ParseArray (const plfield_t *fields, const plitem_t *dict, void *data, plitem_t *messages, void *context); void __attribute__((format(printf,3,4))) diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index b33d22084..d8338a332 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1144,8 +1144,8 @@ pl_default_parser (const plfield_t *field, const plitem_t *item, void *data, } VISIBLE int -PL_ParseDictionary (const plfield_t *fields, const plitem_t *dict, void *data, - plitem_t *messages, void *context) +PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, void *data, + plitem_t *messages, void *context) { void **list, **l; dictkey_t *current; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 6a8b21caa..761cbdade 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -109,7 +109,7 @@ [self outname]); fprintf (output_file, "{\n"); fprintf (output_file, - "\treturn PL_ParseDictionary (%s_fields, item, data, messages," + "\treturn PL_ParseStruct (%s_fields, item, data, messages," " context);\n", [self outname]); fprintf (output_file, "}\n"); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index ac198e756..d2ae12949 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -392,8 +392,8 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) cexpr_init_symtab (&vars_tab, &exprctx); - if (!PL_ParseDictionary (renderpass_fields, plist, - &renderpass_data, messages, &parsectx)) { + if (!PL_ParseStruct (renderpass_fields, plist, &renderpass_data, + messages, &parsectx)) { for (int i = 0; i < PL_A_NumObjects (messages); i++) { Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } From 55c1ed124df99fec8737c8e4d1f5cd6fc0232409 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Dec 2020 15:52:32 +0900 Subject: [PATCH 1120/3664] [doxygen] Fix some missed issues for doc building --- doc/Makemodule.am | 3 ++- doc/quakeforge.dox.conf.in | 13 +++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/doc/Makemodule.am b/doc/Makemodule.am index b26d57841..91d9270b7 100644 --- a/doc/Makemodule.am +++ b/doc/Makemodule.am @@ -76,5 +76,6 @@ doc/progs/vm-mem.eps: doc/progs/vm-mem.fig doc/qtv/qwtv.svg: doc/qtv/qwtv.fig doc/qtv/qwtv.eps: doc/qtv/qwtv.fig -doc: doc/quakeforge.dox.conf doc/progs/vm-mem.svg doc/progs/vm-mem.eps doc/qtv/qwtv.svg qtv/qwtv.eps ${DOX} +.PHONY: doc +doc: doc/quakeforge.dox.conf doc/progs/vm-mem.svg doc/progs/vm-mem.eps doc/qtv/qwtv.svg doc/qtv/qwtv.eps ${DOX} doxygen doc/quakeforge.dox.conf diff --git a/doc/quakeforge.dox.conf.in b/doc/quakeforge.dox.conf.in index a235a895d..1e925e354 100644 --- a/doc/quakeforge.dox.conf.in +++ b/doc/quakeforge.dox.conf.in @@ -253,12 +253,6 @@ TAB_SIZE = 4 ALIASES = QF=QuakeForge -# This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding "class=itcl::class" -# will allow you to use the command class in the itcl::class meaning. - -TCL_SUBST = - # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all @@ -937,8 +931,8 @@ EXAMPLE_RECURSIVE = NO # \image command). IMAGE_PATH = @TOPSRC@/doc \ - @builddir@/progs \ - @builddir@/qtv + @builddir@/doc/progs \ + @builddir@/doc/qtv # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -1756,7 +1750,7 @@ COMPACT_LATEX = YES # The default value is: a4. # This tag requires that the tag GENERATE_LATEX is set to YES. -PAPER_TYPE = a4wide +PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names # that should be included in the LaTeX output. The package can be specified just @@ -2144,7 +2138,6 @@ SEARCH_INCLUDES = YES # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = @TOPSRC@/include \ - @TOPSRC@/hw/include \ @TOPSRC@/nq/include \ @TOPSRC@/qw/include \ @TOPSRC@/qtv/include From fefb32bf13bd4d553465c5599403d190cf9f5262 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Dec 2020 15:59:33 +0900 Subject: [PATCH 1121/3664] [util] Add a PL dictionary to hash table parser --- include/QF/qfplist.h | 88 ++++++++++++++++++++++++++++++++++++++++++-- libs/util/qfplist.c | 62 +++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 3 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index e8a64f054..972f69dc3 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -147,7 +147,7 @@ int PL_Line (const plitem_t *item) __attribute__((pure)); \return the size in bytes of the binary object 0 if binary isn't a binary object. */ -size_t PL_BinarySize (const plitem_t *item) __attribute__((pure)); +size_t PL_BinarySize (const plitem_t *binary) __attribute__((pure)); /** Retrieve the data from a binary object. @@ -323,9 +323,9 @@ void PL_Free (plitem_t *item); Can be used recursively to parse deep hierarchies. - \param dict The dictionary object to parse \param fields Array of field items describing the structure. Terminated by a field item with a null \a name pointer. + \param dict The dictionary object to parse \param data Pointer to the structure into which the data will be parsed. \param messages Array object supplied by the caller used for storing @@ -344,8 +344,90 @@ void PL_Free (plitem_t *item); */ int PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, void *data, plitem_t *messages, void *context); -int PL_ParseArray (const plfield_t *fields, const plitem_t *dict, + +/** Parse an array object into a dynamic arrah (see darray.h). + + For each object in the array, the field item is used to determine how to + parse the object. If the array is empty, the destination will be + initialized to an empty array. + + When an error occurs (incorrect item type (item type does not match the + type specified in the element object) or the element object's \a parser + returns 0), processing continues but the error result is returned. + + Can be used recursively to parse deep hierarchies. + + \param field Pointer to a single field that has the field data pointer + set to reference a plelement_t object used to describe + the contents of the array. + \param array The array object to parse + \param data Pointer to the pointer to which the dynamic array will + be written. The dynamic array is allocated using + DARRAY_ALLOCFIXED(). + \param messages Array object supplied by the caller used for storing + messages. The messages may or may not indicate errors (its + contents are not checked). This function itself will add + only string objects. + If there are any errors, suitable messages will be found in + the \a messages object. However, just because there are no + errors doesn't mean that \a messages will remain empty as + a field's \a parser may add other messages. The standard + message format is "[line number]: [message]". If the line + number is 0, then the actual line is unknown (due to the + source item not being parsed from a file or string). + \param context Additional context data passed to the parser. + \return 0 if there are any errors, 1 if there are no errors. +*/ +int PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, plitem_t *messages, void *context); + +/** Parse a dictionary object into a hash table. + + For each key in the dictionary, the element object is used to determine + how to parse the object associated with that key. Duplicate keys are an + error: they must be unique. A suitable message is added to the + \a messages object. If the dictionary object is empty, the destination + table is left unmodified. + + When an error occurs (duplicate keys, incorrect type, or the element + object's \a parser returns 0), processing continues but the error + result is returned. + + Can be used recursively to parse deep hierarchies. + + Hash_Add() is used to add objects to the hash table, and Hash_Find() is + used to check for duplicates. Hash_Free() is used to free unused + objects. The means that the hash table is expected to use standard + objects with embedded keys (the parser is expected to put the key in the + object) and to have a free function. + + The parser's data paramenter points to a pre-allocated block of memory + of the sized indicated by the element object's size field, using the + element object's alloc callback. The name field in the field paramenter + is set to the object's key and remains owned by the dictionary. + + \param field Pointer to a single field that has the field data pointer + set to reference a plelement_t object used to describe + the contents of the dictionary. + \param dict The dictionary object to parse + \param data Pointer to the structure into which the data will be + parsed. + \param messages Array object supplied by the caller used for storing + messages. The messages may or may not indicate errors (its + contents are not checked). This function itself will add + only string objects. + If there are any errors, suitable messages will be found in + the \a messages object. However, just because there are no + errors doesn't mean that \a messages will remain empty as + a field's \a parser may add other messages. The standard + message format is "[line number]: [message]". If the line + number is 0, then the actual line is unknown (due to the + source item not being parsed from a file or string). + \param context Additional context data passed to the parser. + \return 0 if there are any errors, 1 if there are no errors. +*/ +int PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, + void *data, plitem_t *messages, void *context); void __attribute__((format(printf,3,4))) PL_Message (plitem_t *messages, const plitem_t *item, const char *fmt, ...); diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index d8338a332..e789435ef 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1247,3 +1247,65 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, *(arr_t **) data = arr; return result; } + +VISIBLE int +PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, + plitem_t *messages, void *context) +{ + void **list, **l; + dictkey_t *current; + int result = 1; + plparser_t parser; + __auto_type tab = (hashtab_t *) data; + + plelement_t *element = (plelement_t *) field->data; + plfield_t f = { 0, 0, element->type, element->parser, element->data }; + + if (dict->type != QFDictionary) { + PL_Message (messages, dict, "error: not a dictionary object"); + return 0; + } + + if (f.parser) { + parser = f.parser; + } else { + PL_Message (messages, dict, "no parser set"); + return 0; + } + + if (!(l = list = Hash_GetList ((hashtab_t *) dict->data))) { + // empty struct: leave as default + return 1; + } + + void *obj = element->alloc (element->stride); + while ((current = (dictkey_t *) *l++)) { + const char *key = current->key; + plitem_t *item = current->value; + + if (item->type != element->type) { + PL_Message (messages, item, + "error: element %s is the wrong type" + " Got %s, expected %s", key, + pl_types[element->type], + pl_types[item->type]); + result = 0; + continue; + } + f.name = key; + if (Hash_Find (tab, key)) { + PL_Message (messages, item, "duplicate name"); + result = 0; + } else { + if (!parser (&f, item, obj, messages, context)) { + result = 0; + } else { + Hash_Add (tab, obj); + obj = element->alloc (element->stride); + } + } + } + Hash_Free (tab, obj); + free (list); + return result; +} From 9db80259d1c75f937f08677f729563fc17488590 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Dec 2020 16:39:05 +0900 Subject: [PATCH 1122/3664] [gl,glsl] Copy fog color rather than return pointer The static variable meant that Fog_GetColor was not thread-safe (though multiple calls in the one thread look to be ok for now). However, this change takes it one step closer to being more generally usable. Patch found in an old stash. --- include/r_internal.h | 2 +- libs/video/renderer/gl/gl_fog.c | 37 ++++++++++++----------- libs/video/renderer/glsl/glsl_alias.c | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 8 ++--- libs/video/renderer/glsl/glsl_fog.c | 25 +++++++-------- libs/video/renderer/glsl/glsl_iqm.c | 2 +- libs/video/renderer/glsl/glsl_particles.c | 4 +-- libs/video/renderer/glsl/glsl_sprite.c | 2 +- 8 files changed, 41 insertions(+), 41 deletions(-) diff --git a/include/r_internal.h b/include/r_internal.h index 31272a5a8..547d4d1bf 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -31,7 +31,7 @@ void Fog_Update (float density, float red, float green, float blue, struct plitem_s; void Fog_ParseWorldspawn (struct plitem_s *worldspawn); -float *Fog_GetColor (void); +void Fog_GetColor (quat_t fogcolor); float Fog_GetDensity (void) __attribute__((pure)); void Fog_SetupFrame (void); void Fog_EnableGFog (void); diff --git a/libs/video/renderer/gl/gl_fog.c b/libs/video/renderer/gl/gl_fog.c index fe63419b5..b8747e37b 100644 --- a/libs/video/renderer/gl/gl_fog.c +++ b/libs/video/renderer/gl/gl_fog.c @@ -189,32 +189,29 @@ gl_Fog_ParseWorldspawn (plitem_t *worldspawn) calculates fog color for this frame, taking into account fade times */ -float * -gl_Fog_GetColor (void) +void +gl_Fog_GetColor (quat_t fogcolor) { - static float c[4]; float f; int i; if (fade_done > vr_data.realtime) { f = (fade_done - vr_data.realtime) / fade_time; - c[0] = f * old_red + (1.0 - f) * fog_red; - c[1] = f * old_green + (1.0 - f) * fog_green; - c[2] = f * old_blue + (1.0 - f) * fog_blue; - c[3] = 1.0; + fogcolor[0] = f * old_red + (1.0 - f) * fog_red; + fogcolor[1] = f * old_green + (1.0 - f) * fog_green; + fogcolor[2] = f * old_blue + (1.0 - f) * fog_blue; + fogcolor[3] = 1.0; } else { - c[0] = fog_red; - c[1] = fog_green; - c[2] = fog_blue; - c[3] = 1.0; + fogcolor[0] = fog_red; + fogcolor[1] = fog_green; + fogcolor[2] = fog_blue; + fogcolor[3] = 1.0; } //find closest 24-bit RGB value, so solid-colored sky can match the fog //perfectly for (i = 0; i < 3; i++) - c[i] = (float) (rint (c[i] * 255)) / 255.0f; - - return c; + fogcolor[i] = (float) (rint (fogcolor[i] * 255)) / 255.0f; } /* @@ -243,7 +240,10 @@ gl_Fog_GetDensity (void) void gl_Fog_SetupFrame (void) { - qfglFogfv (GL_FOG_COLOR, gl_Fog_GetColor ()); + quat_t fogcolor; + + gl_Fog_GetColor (fogcolor); + qfglFogfv (GL_FOG_COLOR, fogcolor); qfglFogf (GL_FOG_DENSITY, gl_Fog_GetDensity () / 64.0); } @@ -294,8 +294,11 @@ gl_Fog_StartAdditive (void) void gl_Fog_StopAdditive (void) { - if (gl_Fog_GetDensity () > 0) - qfglFogfv (GL_FOG_COLOR, gl_Fog_GetColor ()); + if (gl_Fog_GetDensity () > 0) { + quat_t fogcolor; + gl_Fog_GetColor (fogcolor); + qfglFogfv (GL_FOG_COLOR, fogcolor); + } } //============================================================================== diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 3fdd50b66..155845450 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -333,7 +333,7 @@ glsl_R_AliasBegin (void) qfeglDisableVertexAttribArray (quake_mdl.colora.location); qfeglDisableVertexAttribArray (quake_mdl.colorb.location); - VectorCopy (glsl_Fog_GetColor (), fog); + glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_mdl.fog.location, 1, fog); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 682ffb628..767000b12 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -360,7 +360,7 @@ static void update_lightmap (msurface_t *surf) { int maps; - +return; for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) if (d_lightstylevalue[surf->styles[maps]] != surf->cached_light[maps]) goto dynamic; @@ -871,7 +871,7 @@ bsp_begin (void) qfeglVertexAttrib4fv (quake_bsp.color.location, default_color); - VectorCopy (glsl_Fog_GetColor (), fog); + glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_bsp.fog.location, 1, fog); @@ -926,7 +926,7 @@ turb_begin (void) qfeglVertexAttrib4fv (quake_turb.color.location, default_color); - VectorCopy (glsl_Fog_GetColor (), fog); + glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_turb.fog.location, 1, fog); @@ -1030,7 +1030,7 @@ sky_begin (void) qfeglEnable (GL_TEXTURE_2D); } - VectorCopy (glsl_Fog_GetColor (), fog); + glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; qfeglUniform4fv (sky_params.fog->location, 1, fog); diff --git a/libs/video/renderer/glsl/glsl_fog.c b/libs/video/renderer/glsl/glsl_fog.c index 8e246b6b7..8118b8497 100644 --- a/libs/video/renderer/glsl/glsl_fog.c +++ b/libs/video/renderer/glsl/glsl_fog.c @@ -189,32 +189,29 @@ glsl_Fog_ParseWorldspawn (plitem_t *worldspawn) calculates fog color for this frame, taking into account fade times */ -float * -glsl_Fog_GetColor (void) +void +glsl_Fog_GetColor (quat_t fogcolor) { - static float c[4]; float f; int i; if (fade_done > vr_data.realtime) { f = (fade_done - vr_data.realtime) / fade_time; - c[0] = f * old_red + (1.0 - f) * fog_red; - c[1] = f * old_green + (1.0 - f) * fog_green; - c[2] = f * old_blue + (1.0 - f) * fog_blue; - c[3] = 1.0; + fogcolor[0] = f * old_red + (1.0 - f) * fog_red; + fogcolor[1] = f * old_green + (1.0 - f) * fog_green; + fogcolor[2] = f * old_blue + (1.0 - f) * fog_blue; + fogcolor[3] = 1.0; } else { - c[0] = fog_red; - c[1] = fog_green; - c[2] = fog_blue; - c[3] = 1.0; + fogcolor[0] = fog_red; + fogcolor[1] = fog_green; + fogcolor[2] = fog_blue; + fogcolor[3] = 1.0; } //find closest 24-bit RGB value, so solid-colored sky can match the fog //perfectly for (i = 0; i < 3; i++) - c[i] = (float) (rint (c[i] * 255)) / 255.0f; - - return c; + fogcolor[i] = (float) (rint (fogcolor[i] * 255)) / 255.0f; } /* diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index d189a4cbe..e757cf087 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -278,7 +278,7 @@ glsl_R_IQMBegin (void) qfeglUseProgram (iqm_shader.program); - VectorCopy (glsl_Fog_GetColor (), fog); + glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; qfeglUniform4fv (iqm_shader.fog.location, 1, fog); diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index c4e214c50..b1461f208 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -1579,7 +1579,7 @@ draw_qf_particles (void) qfeglEnableVertexAttribArray (quake_part.color.location); qfeglEnableVertexAttribArray (quake_part.st.location); - VectorCopy (glsl_Fog_GetColor (), fog); + glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_part.fog.location, 1, fog); @@ -1725,7 +1725,7 @@ draw_id_particles (void) qfeglUniformMatrix4fv (quake_point.mvp_matrix.location, 1, false, vp_mat); - VectorCopy (glsl_Fog_GetColor (), fog); + glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_point.fog.location, 1, fog); diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 69c67335a..c0acdc078 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -335,7 +335,7 @@ R_SpriteBegin (void) qfeglDisableVertexAttribArray (quake_sprite.colorb.location); qfeglDisableVertexAttribArray (quake_sprite.blend.location); - VectorCopy (glsl_Fog_GetColor (), fog); + glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_sprite.fog.location, 1, fog); From c0c728b188c6c0a7c44f18ec8b0b9ea878137669 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Dec 2020 00:17:20 +0900 Subject: [PATCH 1123/3664] [vulkan] Fix a few code generation issues QC's int type is named "integer" (didn't feel like changing that right now), so special case it to be "int". Output the parse func name (instead of "fix me"). Output a parse func for enums (needed for arrays of enums (VkDynamicState)). --- libs/video/renderer/vulkan/vkgen/vkenum.r | 18 ++++++++++++++++++ libs/video/renderer/vulkan/vkgen/vkstruct.r | 4 ++-- libs/video/renderer/vulkan/vkgen/vktype.r | 6 ++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 234c99b61..9f12c013e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -120,6 +120,24 @@ skip_value(string name) fprintf (output_file, "\t&%s_symtab,\n", [self name]); fprintf (output_file, "};\n"); + fprintf (output_file, "static plfield_t %s_field = { 0, 0, QFString," + " parse_enum, &%s_enum};\n", + [self name], [self name]); + fprintf (output_file, "int parse_%s (const plfield_t *field," + " const plitem_t *item, void *data, plitem_t *messages," + " void *context)\n", + [self name]); + fprintf (output_file, "{\n"); + fprintf (output_file, + "\treturn parse_enum (&%s_field, item, data, messages," + " context);\n", + [self name]); + fprintf (output_file, "}\n"); + + fprintf (header_file, "int parse_%s (const plfield_t *field," + " const plitem_t *item, void *data, plitem_t *messages," + " void *context);\n", + [self name]); fprintf (header_file, "extern exprenum_t %s_enum;\n", [self name]); } diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 761cbdade..ac03d8f41 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -175,7 +175,7 @@ -(string) cexprType { - return [self name] + "_type"; + return [self outname] + "_type"; } -(string) parseType @@ -185,7 +185,7 @@ -(string) parseFunc { - return "fix me"; + return "parse_" + [self outname]; } -(string) parseData diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index fbe44e350..735e88339 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -75,6 +75,9 @@ static string get_type_key (void *type, void *unused) -(string) name { if (type.meta == ty_basic) { + if (type.type == ev_integer) { + return "int"; + } return pr_type_name[type.type]; } //FIXME extract alias name and return proper type name @@ -118,6 +121,9 @@ static string get_type_key (void *type, void *unused) -(string) parseData { if (type.meta == ty_basic) { + if (type.type == ev_integer) { + return "&cexpr_int"; + } return "&cexpr_" + pr_type_name[type.type]; } return "0"; From d824db68a5df60bafd7359032d2ec9e9bbd623d4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Dec 2020 00:28:26 +0900 Subject: [PATCH 1124/3664] [util] Zero plist symtabl object memory --- libs/util/qfplist.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index e789435ef..3e64e3c3e 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1279,6 +1279,7 @@ PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, } void *obj = element->alloc (element->stride); + memset (obj, 0, element->stride); while ((current = (dictkey_t *) *l++)) { const char *key = current->key; plitem_t *item = current->value; @@ -1302,6 +1303,7 @@ PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, } else { Hash_Add (tab, obj); obj = element->alloc (element->stride); + memset (obj, 0, element->stride); } } } From 4f8a06ddd3052f5e66e2ed8e1838524fc589c18f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Dec 2020 02:12:51 +0900 Subject: [PATCH 1125/3664] [build] Fix a pile of gcc 10 issues gcc got stricter about array accesses, complicating progs macros, and much better at detecting buffer overflows. --- include/QF/math/vector.h | 7 ++- include/QF/pr_comp.h | 4 +- include/QF/progs.h | 14 ++--- libs/console/bi_inputline.c | 2 +- libs/gamecode/pr_debug.c | 8 +-- libs/gamecode/pr_exec.c | 89 +++++++++++++++--------------- libs/gamecode/pr_parse.c | 6 +- libs/models/alias/model_alias.c | 2 +- libs/ruamoko/rua_hash.c | 2 +- libs/ruamoko/rua_msgbuf.c | 5 +- libs/ruamoko/rua_obj.c | 2 +- libs/ruamoko/rua_plist.c | 2 +- libs/ruamoko/rua_qfile.c | 2 +- libs/ruamoko/rua_script.c | 2 +- libs/ruamoko/rua_set.c | 4 +- libs/util/zone.c | 3 +- libs/video/renderer/r_progs.c | 2 +- nq/include/sv_progs.h | 2 +- qw/include/sv_progs.h | 2 +- qw/source/pmove.c | 2 +- qw/source/sv_progs.c | 4 +- ruamoko/qwaq/builtins/curses.c | 4 +- ruamoko/qwaq/builtins/debug.c | 2 +- ruamoko/qwaq/builtins/editbuffer.c | 2 +- ruamoko/qwaq/builtins/main.c | 1 + tools/qfbsp/source/outside.c | 2 + tools/qfcc/include/qfcc.h | 4 +- tools/qflight/include/noise.h | 2 +- tools/qfmodelgen/source/modelgen.c | 10 ++-- 29 files changed, 100 insertions(+), 93 deletions(-) diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 6a8b80809..993cbaf08 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -142,7 +142,12 @@ extern const vec_t *const vec3_origin; } while (0) #define VectorIsZero(a) (!(a)[0] && !(a)[1] && !(a)[2]) -#define VectorZero(a) ((a)[2] = (a)[1] = (a)[0] = 0); +#define VectorZero(a) \ + do { \ + (a)[0] = 0; \ + (a)[1] = 0; \ + (a)[2] = 0; \ + } while (0) #define VectorSet(a,b,c,d) \ do { \ (d)[0] = a; \ diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index a84e56953..0cd65d7e5 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -474,8 +474,8 @@ typedef union pr_type_u { string_t string_var; func_t func_var; pr_int_t entity_var; - float vector_var[0]; // really 3, but this structure must be 32 bits - float quat_var[0]; // really 4, but this structure must be 32 bits + float vector_var; // really [3], but this structure must be 32 bits + float quat_var; // really [4], but this structure must be 32 bits pr_int_t integer_var; pointer_t pointer_var; pr_uint_t uinteger_var; diff --git a/include/QF/progs.h b/include/QF/progs.h index 8a78926bf..64a9d20bb 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -445,7 +445,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_VECTOR(p,o) G_var (p, o, vector) +#define G_VECTOR(p,o) (&G_var (p, o, vector)) /** Access a quaternion global. Can be assigned to. @@ -457,7 +457,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_QUAT(p,o) G_var (p, o, quat) +#define G_QUAT(p,o) (&G_var (p, o, quat)) /** Access a string index global. Can be assigned to. @@ -661,7 +661,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_VECTOR(p,n) P_var (p, n, vector) +#define P_VECTOR(p,n) (&P_var (p, n, vector)) /** Access a quaterion parameter. Can be used any way a quat_t variable can. @@ -673,7 +673,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_QUAT(p,n) P_var (p, n, quat) +#define P_QUAT(p,n) (&P_var (p, n, quat)) /** Access a string index parameter. Can be assigned to. @@ -873,7 +873,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_VECTOR(p) R_var (p, vector) +#define R_VECTOR(p) (&R_var (p, vector)) /** Access the VM function return value as a \c ::quat_t quaternion. @@ -884,7 +884,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_QUAT(p) R_var (p, quat) +#define R_QUAT(p) (&R_var (p, quat)) /** Access the VM function return value as a ::string_t (a VM string reference). @@ -1054,7 +1054,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_VECTOR(e,o) E_var (e, o, vector) +#define E_VECTOR(e,o) (&E_var (e, o, vector)) /** Access a quaternion entity field. Can be used any way a quat_t variable can. diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index f48a4551e..7e4e743a2 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -83,7 +83,7 @@ il_data_get (il_resources_t *res, unsigned index) PR_RESGET (res->line_map, index); } -static inline int +static inline int __attribute__((pure)) il_data_index (il_resources_t *res, il_data_t *line) { PR_RESINDEX (res->line_map, line); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 3d99da30a..d8105c5f6 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1133,9 +1133,7 @@ pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%.9g %.9g %.9g'", - value->vector_var[0], value->vector_var[1], - value->vector_var[2]); + dasprintf (dstr, "'%.9g %.9g %.9g'", VectorExpand (&value->vector_var)); } static void @@ -1213,9 +1211,7 @@ pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%.9g %.9g %.9g %.9g'", - value->vector_var[0], value->vector_var[1], - value->vector_var[2], value->vector_var[3]); + dasprintf (dstr, "'%.9g %.9g %.9g %.9g'", QuatExpand (&value->quat_var)); } static void diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 4a79f8173..9a9d03893 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -512,10 +512,10 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.float_var = OPA.float_var + OPB.float_var; break; case OP_ADD_V: - VectorAdd (OPA.vector_var, OPB.vector_var, OPC.vector_var); + VectorAdd (&OPA.vector_var, &OPB.vector_var, &OPC.vector_var); break; case OP_ADD_Q: - QuatAdd (OPA.quat_var, OPB.quat_var, OPC.quat_var); + QuatAdd (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); break; case OP_ADD_S: OPC.string_var = PR_CatStrings (pr, @@ -531,10 +531,11 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.float_var = OPA.float_var - OPB.float_var; break; case OP_SUB_V: - VectorSubtract (OPA.vector_var, OPB.vector_var, OPC.vector_var); + VectorSubtract (&OPA.vector_var, &OPB.vector_var, + &OPC.vector_var); break; case OP_SUB_Q: - QuatSubtract (OPA.quat_var, OPB.quat_var, OPC.quat_var); + QuatSubtract (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); break; case OP_MUL_D: OPC_double_var = OPA_double_var * OPB_double_var; @@ -543,14 +544,14 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.float_var = OPA.float_var * OPB.float_var; break; case OP_MUL_V: - OPC.float_var = DotProduct (OPA.vector_var, OPB.vector_var); + OPC.float_var = DotProduct (&OPA.vector_var, &OPB.vector_var); break; case OP_MUL_DV: { // avoid issues with the likes of x = x.x * x; // makes for faster code, too double scale = OPA_double_var; - VectorScale (OPB.vector_var, scale, OPC.vector_var); + VectorScale (&OPB.vector_var, scale, &OPC.vector_var); } break; case OP_MUL_VD: @@ -558,7 +559,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x * x.x; // makes for faster code, too double scale = OPB_double_var; - VectorScale (OPA.vector_var, scale, OPC.vector_var); + VectorScale (&OPA.vector_var, scale, &OPC.vector_var); } break; case OP_MUL_FV: @@ -566,7 +567,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x.x * x; // makes for faster code, too float scale = OPA.float_var; - VectorScale (OPB.vector_var, scale, OPC.vector_var); + VectorScale (&OPB.vector_var, scale, &OPC.vector_var); } break; case OP_MUL_VF: @@ -574,21 +575,21 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x * x.x; // makes for faster code, too float scale = OPB.float_var; - VectorScale (OPA.vector_var, scale, OPC.vector_var); + VectorScale (&OPA.vector_var, scale, &OPC.vector_var); } break; case OP_MUL_Q: - QuatMult (OPA.quat_var, OPB.quat_var, OPC.quat_var); + QuatMult (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); break; case OP_MUL_QV: - QuatMultVec (OPA.quat_var, OPB.vector_var, OPC.vector_var); + QuatMultVec (&OPA.quat_var, &OPB.vector_var, &OPC.vector_var); break; case OP_MUL_DQ: { // avoid issues with the likes of x = x.s * x; // makes for faster code, too double scale = OPA_double_var; - QuatScale (OPB.quat_var, scale, OPC.quat_var); + QuatScale (&OPB.quat_var, scale, &OPC.quat_var); } break; case OP_MUL_QD: @@ -596,7 +597,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x * x.s; // makes for faster code, too double scale = OPB_double_var; - QuatScale (OPA.quat_var, scale, OPC.quat_var); + QuatScale (&OPA.quat_var, scale, &OPC.quat_var); } break; case OP_MUL_FQ: @@ -604,7 +605,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x.s * x; // makes for faster code, too float scale = OPA.float_var; - QuatScale (OPB.quat_var, scale, OPC.quat_var); + QuatScale (&OPB.quat_var, scale, &OPC.quat_var); } break; case OP_MUL_QF: @@ -612,11 +613,11 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // avoid issues with the likes of x = x * x.s; // makes for faster code, too float scale = OPB.float_var; - QuatScale (OPA.quat_var, scale, OPC.quat_var); + QuatScale (&OPA.quat_var, scale, &OPC.quat_var); } break; case OP_CONJ_Q: - QuatConj (OPA.quat_var, OPC.quat_var); + QuatConj (&OPA.quat_var, &OPC.quat_var); break; case OP_DIV_D: OPC_double_var = OPA_double_var / OPB_double_var; @@ -673,10 +674,10 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.integer_var = !FNZ (OPA); break; case OP_NOT_V: - OPC.integer_var = VectorIsZero (OPA.vector_var); + OPC.integer_var = VectorIsZero (&OPA.vector_var); break; case OP_NOT_Q: - OPC.integer_var = QuatIsZero (OPA.quat_var); + OPC.integer_var = QuatIsZero (&OPA.quat_var); break; case OP_NOT_S: OPC.integer_var = !OPA.string_var || @@ -692,11 +693,11 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.integer_var = OPA.float_var == OPB.float_var; break; case OP_EQ_V: - OPC.integer_var = VectorCompare (OPA.vector_var, - OPB.vector_var); + OPC.integer_var = VectorCompare (&OPA.vector_var, + &OPB.vector_var); break; case OP_EQ_Q: - OPC.integer_var = QuatCompare (OPA.quat_var, OPB.quat_var); + OPC.integer_var = QuatCompare (&OPA.quat_var, &OPB.quat_var); break; case OP_EQ_E: OPC.integer_var = OPA.integer_var == OPB.integer_var; @@ -708,11 +709,11 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPC.integer_var = OPA.float_var != OPB.float_var; break; case OP_NE_V: - OPC.integer_var = !VectorCompare (OPA.vector_var, - OPB.vector_var); + OPC.integer_var = !VectorCompare (&OPA.vector_var, + &OPB.vector_var); break; case OP_NE_Q: - OPC.integer_var = !QuatCompare (OPA.quat_var, OPB.quat_var); + OPC.integer_var = !QuatCompare (&OPA.quat_var, &OPB.quat_var); break; case OP_LE_S: case OP_GE_S: @@ -753,10 +754,10 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) OPB.integer_var = OPA.integer_var; break; case OP_STORE_V: - VectorCopy (OPA.vector_var, OPB.vector_var); + VectorCopy (&OPA.vector_var, &OPB.vector_var); break; case OP_STORE_Q: - QuatCopy (OPA.quat_var, OPB.quat_var); + QuatCopy (&OPA.quat_var, &OPB.quat_var); break; case OP_STORE_D: OPB_double_var = OPA_double_var; @@ -782,7 +783,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (OPA.vector_var, ptr->vector_var); + VectorCopy (&OPA.vector_var, &ptr->vector_var); break; case OP_STOREP_Q: pointer = OPB.integer_var; @@ -790,7 +791,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (OPA.quat_var, ptr->quat_var); + QuatCopy (&OPA.quat_var, &ptr->quat_var); break; case OP_STOREP_D: pointer = OPB.integer_var; @@ -909,7 +910,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (ptr->vector_var, OPC.vector_var); + VectorCopy (&ptr->vector_var, &OPC.vector_var); break; case OP_LOADB_Q: pointer = OPA.integer_var + OPB.integer_var; @@ -917,7 +918,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (ptr->quat_var, OPC.quat_var); + QuatCopy (&ptr->quat_var, &OPC.quat_var); break; case OP_LOADB_D: pointer = OPA.integer_var + OPB.integer_var; @@ -948,7 +949,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (ptr->vector_var, OPC.vector_var); + VectorCopy (&ptr->vector_var, &OPC.vector_var); break; case OP_LOADBI_Q: pointer = OPA.integer_var + (short) st->b; @@ -956,7 +957,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (ptr->quat_var, OPC.quat_var); + QuatCopy (&ptr->quat_var, &OPC.quat_var); break; case OP_LOADBI_D: pointer = OPA.integer_var + (short) st->b; @@ -997,7 +998,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (OPA.vector_var, ptr->vector_var); + VectorCopy (&OPA.vector_var, &ptr->vector_var); break; case OP_STOREB_Q: pointer = OPB.integer_var + OPC.integer_var; @@ -1005,7 +1006,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (OPA.quat_var, ptr->quat_var); + QuatCopy (&OPA.quat_var, &ptr->quat_var); break; case OP_STOREB_D: pointer = OPB.integer_var + OPC.integer_var; @@ -1036,7 +1037,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (OPA.vector_var, ptr->vector_var); + VectorCopy (&OPA.vector_var, &ptr->vector_var); break; case OP_STOREBI_Q: pointer = OPB.integer_var + (short) st->c; @@ -1044,7 +1045,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (OPA.quat_var, ptr->quat_var); + QuatCopy (&OPA.quat_var, &ptr->quat_var); break; case OP_STOREBI_D: pointer = OPB.integer_var + (short) st->c; @@ -1131,7 +1132,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (ptr->vector_var, stk->vector_var); + VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack; } break; @@ -1148,7 +1149,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (ptr->quat_var, stk->quat_var); + QuatCopy (&ptr->quat_var, &stk->quat_var); *pr->globals.stack = stack; } break; @@ -1189,7 +1190,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (ptr->vector_var, stk->vector_var); + VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack; } break; @@ -1206,7 +1207,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (ptr->quat_var, stk->quat_var); + QuatCopy (&ptr->quat_var, &stk->quat_var); *pr->globals.stack = stack; } break; @@ -1287,7 +1288,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (ptr->vector_var, stk->vector_var); + VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack + 3; } break; @@ -1304,7 +1305,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (ptr->quat_var, stk->quat_var); + QuatCopy (&ptr->quat_var, &stk->quat_var); *pr->globals.stack = stack + 4; } break; @@ -1345,7 +1346,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (ptr->vector_var, stk->vector_var); + VectorCopy (&ptr->vector_var, &stk->vector_var); *pr->globals.stack = stack + 3; } break; @@ -1362,7 +1363,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (ptr->quat_var, stk->quat_var); + QuatCopy (&ptr->quat_var, &stk->quat_var); *pr->globals.stack = stack + 4; } break; diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 2652694e8..6471a44bb 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -92,10 +92,10 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) dsprintf (line, "%d", val->integer_var); break; case ev_vector: - dsprintf (line, "%.9g %.9g %.9g", VectorExpand (val->vector_var)); + dsprintf (line, "%.9g %.9g %.9g", VectorExpand (&val->vector_var)); break; case ev_quat: - dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (val->quat_var)); + dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (&val->quat_var)); break; default: dsprintf (line, "bad type %i", type); @@ -241,7 +241,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) while (*v && *v != ' ') v++; *v = 0; - d->vector_var[i] = atof (w); + (&d->vector_var)[i] = atof (w); w = v = v + 1; } free (string); diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index af2731d71..8a4784b2d 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -138,7 +138,7 @@ Mod_LoadAliasFrame (void *pin, int *posenum, maliasframedesc_t *frame, pdaliasframe = (daliasframe_t *) pin; - strncpy (frame->name, pdaliasframe->name, sizeof (frame->name)); + memcpy (frame->name, pdaliasframe->name, sizeof (frame->name)); frame->name[sizeof (frame->name) - 1] = 0; frame->firstpose = (*posenum); frame->numposes = 1; diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index cff92eb4e..98d9722ba 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -85,7 +85,7 @@ table_get (hash_resources_t *res, int index) PR_RESGET(res->table_map, index); } -static inline int +static inline int __attribute__((pure)) table_index (hash_resources_t *res, bi_hashtab_t *table) { PR_RESINDEX(res->table_map, table); diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index 9b026c90f..51c7bcf16 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -80,7 +80,7 @@ msgbuf_get (msgbuf_resources_t *res, int index) PR_RESGET(res->msgbuf_map, index); } -static inline int +static inline int __attribute__((pure)) msgbuf_index (msgbuf_resources_t *res, msgbuf_t *msgbuf) { PR_RESINDEX(res->msgbuf_map, msgbuf); @@ -358,8 +358,7 @@ static void bi_MsgBuf_ReadCoordAngleV (progs_t *pr) { msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); - MSG_ReadCoordAngleV (&mb->msg, P_GPOINTER (pr, 1)->vector_var, - P_GPOINTER (pr, 2)->vector_var); + MSG_ReadCoordAngleV (&mb->msg, P_VECTOR (pr, 1), P_VECTOR (pr, 2)); } static void diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index baa8fe73b..155124b9f 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -108,7 +108,7 @@ dtable_get (probj_t *probj, int index) PR_RESGET (probj->dtables, index); } -static inline int +static inline int __attribute__((pure)) dtable_index (probj_t *probj, dtable_t *dtable) { PR_RESINDEX (probj->dtables, dtable); diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 9732b75c3..b71af2ead 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -84,7 +84,7 @@ plist_get (plist_resources_t *res, unsigned index) PR_RESGET(res->plist_map, index); } -static inline int +static inline int __attribute__((pure)) plist_index (plist_resources_t *res, bi_plist_t *plist) { PR_RESINDEX(res->plist_map, plist); diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index d96c433a2..2f625a949 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -77,7 +77,7 @@ handle_get (qfile_resources_t *res, int index) PR_RESGET(res->handle_map, index); } -static inline int +static inline int __attribute__((pure)) handle_index (qfile_resources_t *res, qfile_t *handle) { PR_RESINDEX(res->handle_map, handle); diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index ff5b2ab0a..7c2cd6666 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -78,7 +78,7 @@ script_get (script_resources_t *res, int index) PR_RESGET(res->scripts, index); } -static inline int +static inline int __attribute__((pure)) script_index (script_resources_t *res, rua_script_t *script) { PR_RESINDEX(res->scripts, script); diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 0fdd964e7..4e3ea732d 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -98,7 +98,7 @@ res_set_get (set_resources_t *res, int index) PR_RESGET(res->set_map, index); } -static inline int +static inline int __attribute__((pure)) res_set_index (set_resources_t *res, bi_set_t *set) { PR_RESINDEX(res->set_map, set); @@ -128,7 +128,7 @@ res_set_iter_get (set_resources_t *res, int index) PR_RESGET(res->set_iter_map, index); } -static inline int +static inline int __attribute__((pure)) res_set_iter_index (set_resources_t *res, bi_set_iter_t *set_iter) { PR_RESINDEX(res->set_iter_map, set_iter); diff --git a/libs/util/zone.c b/libs/util/zone.c index 40af412ba..f52226d55 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -577,7 +577,8 @@ Hunk_AllocName (int size, const char *name) h->size = size; h->sentinal = HUNK_SENTINAL; - strncpy (h->name, name, 8); + memcpy (h->name, name, 8); + h->name[7] = 0; return (void *) (h + 1); } diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index aba1de6ea..3f2925fba 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -101,7 +101,7 @@ qpic_get (draw_resources_t *res, int index) PR_RESGET (res->qpic_map, index); } -static inline int +static inline int __attribute__((pure)) qpic_index (draw_resources_t *res, qpic_res_t *qp) { PR_RESINDEX (res->qpic_map, qp); diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 07a8c8f7c..3d798ac16 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -208,7 +208,7 @@ extern progs_t sv_pr_state; #define SVstring(e,f) SVFIELD (e, f, string) #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) -#define SVvector(e,f) SVFIELD (e, f, vector) +#define SVvector(e,f) (&SVFIELD (e, f, vector)) #define SVinteger(e,f) SVFIELD (e, f, integer) #if TYPECHECK_PROGS #define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index 18bdde503..88fe18c24 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -193,7 +193,7 @@ extern progs_t sv_pr_state; #define SVstring(e,f) SVFIELD (e, f, string) #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) -#define SVvector(e,f) SVFIELD (e, f, vector) +#define SVvector(e,f) (&SVFIELD (e, f, vector)) #define SVinteger(e,f) SVFIELD (e, f, integer) #if TYPECHECK_PROGS #define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) diff --git a/qw/source/pmove.c b/qw/source/pmove.c index 637528afa..358409bc5 100644 --- a/qw/source/pmove.c +++ b/qw/source/pmove.c @@ -738,7 +738,7 @@ SpectatorMove (void) // friction speed = DotProduct (pmove.velocity, pmove.velocity); if (speed < 1) { - VectorZero (pmove.velocity) + VectorZero (pmove.velocity); } else { speed = sqrt (speed); drop = 0; diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 276ee2875..7ef651a15 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -101,8 +101,8 @@ free_edict (progs_t *pr, edict_t *ent) ent->v[sv_fields.frame].float_var = 0; ent->v[sv_fields.nextthink].float_var = -1; ent->v[sv_fields.solid].float_var = 0; - memset (ent->v[sv_fields.origin].vector_var, 0, 3*sizeof (float)); - memset (ent->v[sv_fields.angles].vector_var, 0, 3*sizeof (float)); + memset (&ent->v[sv_fields.origin].vector_var, 0, 3*sizeof (float)); + memset (&ent->v[sv_fields.angles].vector_var, 0, 3*sizeof (float)); } else { ED_ClearEdict (pr, ent, 0); } diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 8f543f493..4f2044cf7 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -148,7 +148,7 @@ window_get (qwaq_resources_t *res, unsigned index) PR_RESGET(res->window_map, index); } -static inline int +static inline int __attribute__((pure)) window_index (qwaq_resources_t *res, window_t *win) { PR_RESINDEX (res->window_map, win); @@ -194,7 +194,7 @@ panel_get (qwaq_resources_t *res, unsigned index) PR_RESGET(res->panel_map, index); } -static inline int +static inline int __attribute__((pure)) panel_index (qwaq_resources_t *res, panel_t *win) { PR_RESINDEX (res->panel_map, win); diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index bb22d35e2..f0414649c 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -93,7 +93,7 @@ target_get (qwaq_debug_t *debug, unsigned index) PR_RESGET (debug->targets, index); } -static inline int +static inline int __attribute__((pure)) target_index (qwaq_debug_t *debug, qwaq_target_t *target) { PR_RESINDEX (debug->targets, target); diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index 12cde52ab..d687103d3 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -52,7 +52,7 @@ editbuffer_get (qwaq_ebresources_t *res, unsigned index) PR_RESGET (res->buffers, index); } -static inline int +static inline int __attribute__((pure)) editbuffer_index (qwaq_ebresources_t *res, editbuffer_t *buffer) { PR_RESINDEX (res->buffers, buffer); diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index c4c426166..8a1104b22 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -86,6 +86,7 @@ open_file (const char *path, int *len) if (!file) { strerror_r(errno, errbuff, sizeof (errbuff)); Sys_Printf ("%s\n", errbuff); + *len = 0; return 0; } *len = Qfilesize (file); diff --git a/tools/qfbsp/source/outside.c b/tools/qfbsp/source/outside.c index 15da18dba..d7ba0d142 100644 --- a/tools/qfbsp/source/outside.c +++ b/tools/qfbsp/source/outside.c @@ -180,6 +180,8 @@ MarkLeakTrail2 (void) vec3_t wc, pwc; const vec_t *v; + VectorZero (wc); + leakfile = fopen (options.pointfile, "w"); if (!leakfile) Sys_Error ("Couldn't open %s\n", options.pointfile); diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 6fac011ce..9d552ab3e 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -101,8 +101,8 @@ extern pr_info_t pr; #define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset)) #define D_FLOAT(d) D_var (float, d) #define D_INT(d) D_var (integer, d) -#define D_VECTOR(d) D_var (vector, d) -#define D_QUAT(d) D_var (quat, d) +#define D_VECTOR(d) (&D_var (vector, d)) +#define D_QUAT(d) (&D_var (quat, d)) #define D_STRING(d) D_var (string, d) #define D_GETSTR(d) GETSTR (D_STRING (d)) #define D_FUNCTION(d) D_var (func, d) diff --git a/tools/qflight/include/noise.h b/tools/qflight/include/noise.h index be63d9de1..0b118d17a 100644 --- a/tools/qflight/include/noise.h +++ b/tools/qflight/include/noise.h @@ -34,7 +34,7 @@ ///@{ float noise3d (vec3_t v, int num) __attribute__((pure)); -float noiseXYZ (float x, float y, float z, int num) __attribute__((pure)); +float noiseXYZ (float x, float y, float z, int num) __attribute__((const)); float noise_scaled (vec3_t v, float s, int num) __attribute__((pure)); float noise_perlin (vec3_t v, float p, int num) __attribute__((pure)); void snap_vector (vec3_t v_old, vec3_t v_new, float scale); diff --git a/tools/qfmodelgen/source/modelgen.c b/tools/qfmodelgen/source/modelgen.c index 5d3eee4d0..a4b18b1ac 100644 --- a/tools/qfmodelgen/source/modelgen.c +++ b/tools/qfmodelgen/source/modelgen.c @@ -178,15 +178,17 @@ SetQdirFromPath (char *path) static const char * ExpandPath (const char *path) { - static char full[1024]; + static dstring_t *full; - //FIXME buffer overflow central + if (!full) { + full = dstring_new(); + } //if (!qdir) // Sys_Error ("ExpandPath called without qdir set"); if (path[0] == '/' || path[0] == '\\' || path[1] == ':') return path; - sprintf (full, "%s%s", qdir, path); - return full; + dsprintf (full, "%s%s", qdir, path); + return full->str; } static void From 09a10f80e1a5ec8111dd28745aabec459cd52f84 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Dec 2020 12:29:04 +0900 Subject: [PATCH 1126/3664] [util] Add basic SIMD implemented vector functions They take advantage of gcc's vector_size attribute and so only cross, dot, qmul, qvmul and qrot (create rotation quaternion from two vectors) are needed at this stage as basic (per-component) math is supported natively by gcc. The provided functions work on horizontal (array-of-structs) data, ie a vec4d_t or vec4f_t represents a single vector, or traditional vector layout. Vertical layout (struct-of-arrays) does not need any special functions as the regular math can be used to operate on four vectors at a time. Functions are provided for loading a vec4 from a vec3 (4th element set to 0) and storing a vec4 into a vec3 (discarding the 4th element). With this, QF will require AVX2 support (needed for vec4d_t). Without support for doubles, SSE is possible, but may not be worthwhile for horizontal data. Fused-multiply-add is NOT used because it alters the results between unoptimized and optimized code, resulting in -mfma really meaning -mfast-math-anyway. I really do not want to have to debug issues that occur only in optimized code. --- config.d/compiling.m4 | 5 + include/QF/simd/types.h | 85 +++++++++++ include/QF/simd/vec4d.h | 156 +++++++++++++++++++ include/QF/simd/vec4f.h | 159 +++++++++++++++++++ libs/util/test/Makemodule.am | 5 + libs/util/test/test-simd.c | 289 +++++++++++++++++++++++++++++++++++ 6 files changed, 699 insertions(+) create mode 100644 include/QF/simd/types.h create mode 100644 include/QF/simd/vec4d.h create mode 100644 include/QF/simd/vec4f.h create mode 100644 libs/util/test/test-simd.c diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 343218d35..d9ba92887 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -82,6 +82,11 @@ AC_ARG_ENABLE(optimize, optimize=yes ) +QF_CC_OPTION(-mavx2) +dnl fma is not used as it is the equivalent of turning on +dnl -funsafe-math-optimizations +dnl QF_CC_OPTION(-mfma) + AC_MSG_CHECKING(for optimization) if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then AC_MSG_RESULT(yes) diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h new file mode 100644 index 000000000..cd8b0da9d --- /dev/null +++ b/include/QF/simd/types.h @@ -0,0 +1,85 @@ +/* + QF/simd/types.h + + Type definitions for QF SIMD values + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_types_h +#define __QF_simd_types_h + +#define VEC_TYPE(t,n) typedef t n __attribute__ ((vector_size (4*sizeof (t)))) + +/** Three element vector type for interfacing with compact data. + * + * This cannot be used directly by SIMD code and must be loaded and stored + * using load_vec3d() and store_vec3d() respectively. + */ +typedef double vec3d_t[3]; + +#ifdef __AVX__ +/** Four element vector type for horizontal (AOS) vector data. + * + * This is used for both vectors (3D and 4D) and quaternions. 3D vectors + * are simply vec4d_t values with 0 in the 4th element. + * + * Also usable with vertical (SOA) code, in which case each vec4d_t represents + * a single component from four vectors, or a single row/column (depending on + * context) of an Nx4 or 4xN matrix. + */ +VEC_TYPE (double, vec4d_t); + +/** Used mostly for __builtin_shuffle. + */ +VEC_TYPE (long, vec4l_t); +#endif + +/** Three element vector type for interfacing with compact data. + * + * This cannot be used directly by SIMD code and must be loaded and stored + * using load_vec3f() and store_vec3f() respectively. + */ +typedef float vec3f_t[3]; + +/** Four element vector type for horizontal (AOS) vector data. + * + * This is used for both vectors (3D and 4D) and quaternions. 3D vectors + * are simply vec4f_t values with 0 in the 4th element. + * + * Also usable with vertical (SOA) code, in which case each vec4f_t represents + * a single component from four vectors, or a single row/column (depending on + * context) of an Nx4 or 4xN matrix. + */ +VEC_TYPE (float, vec4f_t); + +/** Used mostly for __builtin_shuffle. + */ +VEC_TYPE (int, vec4i_t); + +#define VEC4D_FMT "[%.17g, %.17g, %.17g, %.17g]" +#define VEC4L_FMT "[%ld, %ld, %ld, %ld]" +#define VEC4F_FMT "[%.9g, %.9g, %.9g, %.9g]" +#define VEC4I_FMT "[%d, %d, %d, %d]" +#define VEC4_EXP(v) (v)[0], (v)[1], (v)[2], (v)[3] + +#endif//__QF_simd_types_h diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h new file mode 100644 index 000000000..d608933f5 --- /dev/null +++ b/include/QF/simd/vec4d.h @@ -0,0 +1,156 @@ +/* + QF/simd/vec4d.h + + Vector functions for vec4d_t (ie, double precision) + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec4d_h +#define __QF_simd_vec4d_h + +#include + +#include "QF/simd/types.h" + +/** 3D vector cross product. + * + * The w (4th) component can be any value on input, and is guaranteed to be 0 + * in the result. The result is not affected in any way by either vector's w + * componemnt + */ +vec4d_t crossd (vec4d_t a, vec4d_t b) __attribute__((const)); +vec4d_t +crossd (vec4d_t a, vec4d_t b) +{ + static const vec4l_t A = {1, 2, 0, 3}; + vec4d_t c = a * __builtin_shuffle (b, A); + vec4d_t d = __builtin_shuffle (a, A) * b; + c = c - d; + return __builtin_shuffle(c, A); +} + +/** 4D vector dot product. + * + * The w component *IS* significant, but if it is 0 in either vector, then + * the result will be as for a 3D dot product. + * + * Note that the dot product is in all 4 of the return value's elements. This + * helps optimize vector math as the scalar is already pre-spread. If just the + * scalar is required, use result[0]. + */ +vec4d_t dotd (vec4d_t a, vec4d_t b) __attribute__((const)); +vec4d_t +dotd (vec4d_t a, vec4d_t b) +{ + vec4d_t c = a * b; + c = _mm256_hadd_pd (c, c); + static const vec4l_t A = {2, 3, 0, 1}; + c += __builtin_shuffle(c, A); + return c; +} + +/** Quaternion product. + * + * The vector is interpreted as a quaternion instead of a regular 4D vector. + * The quaternion may be of any magnitude, so this is more generally useful. + * than if the quaternion was required to be unit length. + */ +vec4d_t qmuld (vec4d_t a, vec4d_t b) __attribute__((const)); +vec4d_t +qmuld (vec4d_t a, vec4d_t b) +{ + // results in [2*as*bs, as*b + bs*a + a x b] ([scalar, vector] notation) + // doesn't seem to adversly affect precision + vec4d_t c = crossd (a, b) + a * b[3] + a[3] * b; + vec4d_t d = dotd (a, b); + // zero out the vector component of dot product so only the scalar remains + d = _mm256_permute2f128_pd (d, d, 0x18); + d = _mm256_permute4x64_pd (d, 0xc0); + return c - d; +} + +/** Optimized quaterion-vector multiplication for vector rotation. + * + * If the vector's w component is not zero, then the result's w component + * is the cosine of the full rotation angle scaled by the vector's w component. + * The quaternion is assumed to be unit. If the quaternion is not unit, the + * vector will be scaled by the square of the quaternion's magnitude. + */ +vec4d_t qvmuld (vec4d_t q, vec4d_t v) __attribute__((const)); +vec4d_t +qvmuld (vec4d_t q, vec4d_t v) +{ + double s = q[3]; + // zero the scalar of the quaternion. Results in an extra operation, but + // avoids adding precision issues. + vec4d_t z = {}; + q = _mm256_blend_pd (q, z, 0x08); + vec4d_t c = crossd (q, v); + vec4d_t qv = dotd (q, v); // q.w is 0 so v.w is irrelevant + vec4d_t qq = dotd (q, q); + + return (s * s - qq) * v + 2 * (qv * q + s * c); +} + +/** Create the quaternion representing the shortest rotation from a to b. + * + * Both a and b are assumed to be 3D vectors (w components 0), but a resonable + * (but incorrect) result will still be produced if either a or b is a 4D + * vector. The rotation axis will be the same as if both vectors were 3D, but + * the magnitude of the rotation will be different. + */ +vec4d_t qrotd (vec4d_t a, vec4d_t b) __attribute__((const)); +vec4d_t +qrotd (vec4d_t a, vec4d_t b) +{ + vec4d_t ma = _mm256_sqrt_pd (dotd (a, a)); + vec4d_t mb = _mm256_sqrt_pd (dotd (b, b)); + vec4d_t den = 2 * ma * mb; + vec4d_t t = mb * a + ma * b; + vec4d_t mba_mab = _mm256_sqrt_pd (dotd (t, t)); + vec4d_t q = crossd (a, b) / mba_mab; + q[3] = (mba_mab / den)[0]; + return q; +} + +vec4d_t loadvec3d (const double v3[]) __attribute__((pure, access(read_only, 1))); +vec4d_t +loadvec3d (const double v3[]) +{ + vec4d_t v4 = {}; + + v4[0] = v3[0]; + v4[1] = v3[1]; + v4[2] = v3[2]; + return v4; +} + +void storevec3d (double v3[3], vec4d_t v4) __attribute__((access (write_only, 1))); +void storevec3d (double v3[3], vec4d_t v4) +{ + v3[0] = v4[0]; + v3[1] = v4[1]; + v3[2] = v4[2]; +} + +#endif//__QF_simd_vec4d_h diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h new file mode 100644 index 000000000..ea92b81d9 --- /dev/null +++ b/include/QF/simd/vec4f.h @@ -0,0 +1,159 @@ +/* + QF/simd/vec4f.h + + Vector functions for vec4f_t (ie, float precision) + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec4f_h +#define __QF_simd_vec4f_h + +#include + +#include "QF/simd/types.h" + +/** 3D vector cross product. + * + * The w (4th) component can be any value on input, and is guaranteed to be 0 + * in the result. The result is not affected in any way by either vector's w + * componemnt + */ +vec4f_t crossf (vec4f_t a, vec4f_t b) __attribute__((const)); +vec4f_t +crossf (vec4f_t a, vec4f_t b) +{ + static const vec4i_t A = {1, 2, 0, 3}; + vec4f_t c = a * __builtin_shuffle (b, A) - __builtin_shuffle (a, A) * b; + return __builtin_shuffle(c, A); +} + +/** 4D vector dot product. + * + * The w component *IS* significant, but if it is 0 in either vector, then + * the result will be as for a 3D dot product. + * + * Note that the dot product is in all 4 of the return value's elements. This + * helps optimize vector math as the scalar is already pre-spread. If just the + * scalar is required, use result[0]. + */ +vec4f_t dotf (vec4f_t a, vec4f_t b) __attribute__((const)); +vec4f_t +dotf (vec4f_t a, vec4f_t b) +{ + vec4f_t c = a * b; + c = _mm_hadd_ps (c, c); + c = _mm_hadd_ps (c, c); + return c; +} + +/** Quaternion product. + * + * The vector is interpreted as a quaternion instead of a regular 4D vector. + * The quaternion may be of any magnitude, so this is more generally useful. + * than if the quaternion was required to be unit length. + */ +vec4f_t qmulf (vec4f_t a, vec4f_t b) __attribute__((const)); +vec4f_t +qmulf (vec4f_t a, vec4f_t b) +{ + // results in [2*as*bs, as*b + bs*a + a x b] ([scalar, vector] notation) + // doesn't seem to adversly affect precision + vec4f_t c = crossf (a, b) + a * b[3] + a[3] * b; + vec4f_t d = dotf (a, b); + // zero out the vector component of dot product so only the scalar remains + d = _mm_insert_ps (d, d, 0xf7); + return c - d; +} + +/** Optimized quaterion-vector multiplication for vector rotation. + * + * If the vector's w component is not zero, then the result's w component + * is the cosine of the full rotation angle scaled by the vector's w component. + * The quaternion is assumed to be unit. + */ +vec4f_t qvmulf (vec4f_t q, vec4f_t v) __attribute__((const)); +vec4f_t +qvmulf (vec4f_t q, vec4f_t v) +{ + float s = q[3]; + // zero the scalar of the quaternion. Results in an extra operation, but + // avoids adding precision issues. + q = _mm_insert_ps (q, q, 0xf8); + vec4f_t c = crossf (q, v); // q.w is 0 so v.w is irrelevant + vec4f_t qv = dotf (q, v); + vec4f_t qq = dotf (q, q); + + return (s * s - qq) * v + 2 * (qv * q + s * c); +} + +/** Create the quaternion representing the shortest rotation from a to b. + * + * Both a and b are assumed to be 3D vectors (w components 0), but a resonable + * (but incorrect) result will still be produced if either a or b is a 4D + * vector. The rotation axis will be the same as if both vectors were 3D, but + * the magnitude of the rotation will be different. + */ +vec4f_t qrotf (vec4f_t a, vec4f_t b) __attribute__((const)); +vec4f_t +qrotf (vec4f_t a, vec4f_t b) +{ + vec4f_t ma = _mm_sqrt_ps (dotf (a, a)); + vec4f_t mb = _mm_sqrt_ps (dotf (b, b)); + vec4f_t den = 2 * ma * mb; + vec4f_t t = mb * a + ma * b; + vec4f_t mba_mab = _mm_sqrt_ps (dotf (t, t)); + vec4f_t q = crossf (a, b) / mba_mab; + q[3] = (mba_mab / den)[0]; + return q; +} + +vec4f_t loadvec3f (const float v3[3]) __attribute__((pure, access(read_only, 1))); +vec4f_t +loadvec3f (const float v3[3]) +{ + vec4f_t v4; + + // this had to be in asm otherwise gcc thinks v4 is only partially + // initialized, and gcc 10 does not use the zero flags when generating + // the code, resulting in a memory access to load a 0 into v4[3] + // + // The first instruction zeros v4[3] while loading v4[0] + asm ("\n\ + vinsertps $0x08, %1, %0, %0 \n\ + vinsertps $0x10, %2, %0, %0 \n\ + vinsertps $0x20, %3, %0, %0 \n\ + " + : "=v"(v4) + : "m"(v3[0]), "m"(v3[1]), "m"(v3[2])); + return v4; +} + +void storevec3f (float v3[3], vec4f_t v4) __attribute__((access (write_only, 1))); +void storevec3f (float v3[3], vec4f_t v4) +{ + v3[0] = v4[0]; + v3[1] = v4[1]; + v3[2] = v4[2]; +} + +#endif//__QF_simd_vec4f_h diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 9447a7807..ca777f864 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -14,6 +14,7 @@ libs_util_tests = \ libs/util/test/test-seb \ libs/util/test/test-seg \ libs/util/test/test-set \ + libs/util/test/test-simd \ libs/util/test/test-txtbuffer \ libs/util/test/test-vrect @@ -81,6 +82,10 @@ libs_util_test_test_set_SOURCES=libs/util/test/test-set.c libs_util_test_test_set_LDADD=libs/util/libQFutil.la libs_util_test_test_set_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_simd_SOURCES=libs/util/test/test-simd.c +libs_util_test_test_simd_LDADD=libs/util/libQFutil.la +libs_util_test_test_simd_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_txtbuffer_SOURCES=libs/util/test/test-txtbuffer.c libs_util_test_test_txtbuffer_LDADD=libs/util/libQFutil.la libs_util_test_test_txtbuffer_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c new file mode 100644 index 000000000..ec1b145ac --- /dev/null +++ b/libs/util/test/test-simd.c @@ -0,0 +1,289 @@ +#include +#include +#include +#include + +#include "QF/simd/vec4d.h" +#include "QF/simd/vec4f.h" + +#define right { 1, 0, 0 } +#define forward { 0, 1, 0 } +#define up { 0, 0, 1 } +#define one { 1, 1, 1, 1 } +#define half { 0.5, 0.5, 0.5, 0.5 } +#define zero { 0, 0, 0, 0 } +#define qident { 0, 0, 0, 1 } +#define qtest { 0.64, 0.48, 0, 0.6 } + +#define nright { -1, 0, 0 } +#define nforward { 0, -1, 0 } +#define nup { 0, 0, -1 } +#define none { -1, -1, -1, -1 } +#define nqident { 0, 0, 0, -1 } + +#define s05 0.70710678118654757 + +typedef struct { + vec4d_t (*op) (vec4d_t a, vec4d_t b); + vec4d_t a; + vec4d_t b; + vec4d_t expect; + vec4d_t ulp_errors; +} vec4d_test_t; + +typedef struct { + vec4f_t (*op) (vec4f_t a, vec4f_t b); + vec4f_t a; + vec4f_t b; + vec4f_t expect; + vec4f_t ulp_errors; +} vec4f_test_t; + +static vec4d_test_t vec4d_tests[] = { + // 3D dot products + { dotd, right, right, one }, + { dotd, right, forward, zero }, + { dotd, right, up, zero }, + { dotd, forward, right, zero }, + { dotd, forward, forward, one }, + { dotd, forward, up, zero }, + { dotd, up, right, zero }, + { dotd, up, forward, zero }, + { dotd, up, up, one }, + + // one is 4D, so its self dot product is 4 + { dotd, one, one, { 4, 4, 4, 4} }, + { dotd, one, none, {-4, -4, -4, -4} }, + + // 3D cross products + { crossd, right, right, zero }, + { crossd, right, forward, up }, + { crossd, right, up, nforward }, + { crossd, forward, right, nup }, + { crossd, forward, forward, zero }, + { crossd, forward, up, right }, + { crossd, up, right, forward }, + { crossd, up, forward, nright }, + { crossd, up, up, zero }, + // double whammy tests: cross product with an angled vector and + // ensuring that a 4d vector (non-zero w component) does not affect + // the result, including the result's w component remaining zero. + { crossd, right, one, { 0, -1, 1} }, + { crossd, forward, one, { 1, 0, -1} }, + { crossd, up, one, {-1, 1, 0} }, + { crossd, one, right, { 0, 1, -1} }, + { crossd, one, forward, {-1, 0, 1} }, + { crossd, one, up, { 1, -1, 0} }, + // This one fails when optimizing with -mfma (which is why fma is not + // used): ulp errors in z and w + { crossd, qtest, qtest, {0, 0, 0, 0} }, + + { qmuld, qident, qident, qident }, + { qmuld, qident, right, right }, + { qmuld, qident, forward, forward }, + { qmuld, qident, up, up }, + { qmuld, right, qident, right }, + { qmuld, forward, qident, forward }, + { qmuld, up, qident, up }, + { qmuld, right, right, nqident }, + { qmuld, right, forward, up }, + { qmuld, right, up, nforward }, + { qmuld, forward, right, nup }, + { qmuld, forward, forward, nqident }, + { qmuld, forward, up, right }, + { qmuld, up, right, forward }, + { qmuld, up, forward, nright }, + { qmuld, up, up, nqident }, + { qmuld, one, one, { 2, 2, 2, -2 } }, + { qmuld, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } }, + // This one fails when optimizing with -mfma (which is why fma is not + // used): ulp error in z + { qmuld, qtest, qtest, {0.768, 0.576, 0, -0.28} }, + + // The one vector is not unit (magnitude 2), so using it as a rotation + // quaternion results in scaling by 4. However, it still has the effect + // of rotating 120 degrees around the axis equidistant from the three + // orthogonal axes such that x->y->z->x + { qvmuld, one, right, { 0, 4, 0, 0 } }, + { qvmuld, one, forward, { 0, 0, 4, 0 } }, + { qvmuld, one, up, { 4, 0, 0, 0 } }, + { qvmuld, one, {1,1,1,0}, { 4, 4, 4, 0 } }, + { qvmuld, one, one, { 4, 4, 4, -2 } }, + // The half vector is unit. + { qvmuld, half, right, forward }, + { qvmuld, half, forward, up }, + { qvmuld, half, up, right }, + { qvmuld, half, {1,1,1,0}, { 1, 1, 1, 0 } }, + // one is a 4D vector and qvmuld is meant for 3D vectors. However, it + // seems that the vector's w has no effect on the 3d portion of the + // result, but the result's w is cosine of the full rotation angle + // scaled by quaternion magnitude and vector w + { qvmuld, half, one, { 1, 1, 1, -0.5 } }, + { qvmuld, half, {2,2,2,2}, { 2, 2, 2, -1 } }, + { qvmuld, qtest, right, {0.5392, 0.6144, -0.576, 0} }, + { qvmuld, qtest, forward, {0.6144, 0.1808, 0.768, 0}, + {0, -2.7e-17, 0, 0} }, + { qvmuld, qtest, up, {0.576, -0.768, -0.28, 0} }, + + { qrotd, right, right, qident }, + { qrotd, right, forward, { 0, 0, s05, s05 }, + {0, 0, -1.1e-16, 0} }, + { qrotd, right, up, { 0, -s05, 0, s05 }, + {0, 1.1e-16, 0, 0} }, + { qrotd, forward, right, { 0, 0, -s05, s05 }, + {0, 0, 1.1e-16, 0} }, + { qrotd, forward, forward, qident }, + { qrotd, forward, up, { s05, 0, 0, s05 }, + {-1.1e-16, 0, 0, 0} }, + { qrotd, up, right, { 0, s05, 0, s05 }, + {0, -1.1e-16, 0, 0} }, + { qrotd, up, forward, { -s05, 0, 0, s05 }, + { 1.1e-16, 0, 0, 0} }, + { qrotd, up, up, qident }, +}; +#define num_vec4d_tests (sizeof (vec4d_tests) / (sizeof (vec4d_tests[0]))) + +static vec4f_test_t vec4f_tests[] = { + // 3D dot products + { dotf, right, right, one }, + { dotf, right, forward, zero }, + { dotf, right, up, zero }, + { dotf, forward, right, zero }, + { dotf, forward, forward, one }, + { dotf, forward, up, zero }, + { dotf, up, right, zero }, + { dotf, up, forward, zero }, + { dotf, up, up, one }, + + // one is 4D, so its self dot product is 4 + { dotf, one, one, { 4, 4, 4, 4} }, + { dotf, one, none, {-4, -4, -4, -4} }, + + // 3D cross products + { crossf, right, right, zero }, + { crossf, right, forward, up }, + { crossf, right, up, nforward }, + { crossf, forward, right, nup }, + { crossf, forward, forward, zero }, + { crossf, forward, up, right }, + { crossf, up, right, forward }, + { crossf, up, forward, nright }, + { crossf, up, up, zero }, + // double whammy tests: cross product with an angled vector and + // ensuring that a 4d vector (non-zero w component) does not affect + // the result, including the result's w component remaining zero. + { crossf, right, one, { 0, -1, 1} }, + { crossf, forward, one, { 1, 0, -1} }, + { crossf, up, one, {-1, 1, 0} }, + { crossf, one, right, { 0, 1, -1} }, + { crossf, one, forward, {-1, 0, 1} }, + { crossf, one, up, { 1, -1, 0} }, + { crossf, qtest, qtest, {0, 0, 0, 0} }, + + { qmulf, qident, qident, qident }, + { qmulf, qident, right, right }, + { qmulf, qident, forward, forward }, + { qmulf, qident, up, up }, + { qmulf, right, qident, right }, + { qmulf, forward, qident, forward }, + { qmulf, up, qident, up }, + { qmulf, right, right, nqident }, + { qmulf, right, forward, up }, + { qmulf, right, up, nforward }, + { qmulf, forward, right, nup }, + { qmulf, forward, forward, nqident }, + { qmulf, forward, up, right }, + { qmulf, up, right, forward }, + { qmulf, up, forward, nright }, + { qmulf, up, up, nqident }, + { qmulf, one, one, { 2, 2, 2, -2 } }, + { qmulf, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } }, + { qmulf, qtest, qtest, {0.768, 0.576, 0, -0.28}, + {0, 6e-8, 0, 3e-8} }, + + // The one vector is not unit (magnitude 2), so using it as a rotation + // quaternion results in scaling by 4. However, it still has the effect + // of rotating 120 degrees around the axis equidistant from the three + // orthogonal axes such that x->y->z->x + { qvmulf, one, right, { 0, 4, 0, 0 } }, + { qvmulf, one, forward, { 0, 0, 4, 0 } }, + { qvmulf, one, up, { 4, 0, 0, 0 } }, + { qvmulf, one, {1,1,1,0}, { 4, 4, 4, 0 } }, + { qvmulf, one, one, { 4, 4, 4, -2 } }, + { qvmulf, qtest, right, {0.5392, 0.6144, -0.576, 0}, + {0, -5.9e-08, -6e-8, 0} }, + { qvmulf, qtest, forward, {0.6144, 0.1808, 0.768, 0}, + {-5.9e-08, 1.5e-08, 0, 0} }, + { qvmulf, qtest, up, {0.576, -0.768, -0.28, 0}, + {6e-8, 0, 3e-8, 0} }, + + { qrotf, right, right, qident }, + { qrotf, right, forward, { 0, 0, s05, s05 } }, + { qrotf, right, up, { 0, -s05, 0, s05 } }, + { qrotf, forward, right, { 0, 0, -s05, s05 } }, + { qrotf, forward, forward, qident }, + { qrotf, forward, up, { s05, 0, 0, s05 } }, + { qrotf, up, right, { 0, s05, 0, s05 } }, + { qrotf, up, forward, { -s05, 0, 0, s05 } }, + { qrotf, up, up, qident }, +}; +#define num_vec4f_tests (sizeof (vec4f_tests) / (sizeof (vec4f_tests[0]))) + +static int +run_vec4d_tests (void) +{ + int ret = 0; + + for (size_t i = 0; i < num_vec4d_tests; i++) { + __auto_type test = &vec4d_tests[i]; + vec4d_t result = test->op (test->a, test->b); + vec4d_t expect = test->expect + test->ulp_errors; + vec4l_t res = result != expect; + if (res[0] || res[1] || res[2] || res[3]) { + ret |= 1; + printf ("\nrun_vec4d_tests\n"); + printf ("a: " VEC4D_FMT "\n", VEC4_EXP(test->a)); + printf ("b: " VEC4D_FMT "\n", VEC4_EXP(test->b)); + printf ("r: " VEC4D_FMT "\n", VEC4_EXP(result)); + printf ("t: " VEC4L_FMT "\n", VEC4_EXP(res)); + printf ("E: " VEC4D_FMT "\n", VEC4_EXP(expect)); + printf ("e: " VEC4D_FMT "\n", VEC4_EXP(test->expect)); + printf ("u: " VEC4D_FMT "\n", VEC4_EXP(test->ulp_errors)); + } + } + return ret; +} + +static int +run_vec4f_tests (void) +{ + int ret = 0; + + for (size_t i = 0; i < num_vec4f_tests; i++) { + __auto_type test = &vec4f_tests[i]; + vec4f_t result = test->op (test->a, test->b); + vec4f_t expect = test->expect + test->ulp_errors; + vec4i_t res = result != expect; + if (res[0] || res[1] || res[2] || res[3]) { + ret |= 1; + printf ("\nrun_vec4f_tests\n"); + printf ("a: " VEC4F_FMT "\n", VEC4_EXP(test->a)); + printf ("b: " VEC4F_FMT "\n", VEC4_EXP(test->b)); + printf ("r: " VEC4F_FMT "\n", VEC4_EXP(result)); + printf ("t: " VEC4I_FMT "\n", VEC4_EXP(res)); + printf ("E: " VEC4F_FMT "\n", VEC4_EXP(expect)); + printf ("e: " VEC4F_FMT "\n", VEC4_EXP(test->expect)); + printf ("u: " VEC4F_FMT "\n", VEC4_EXP(test->ulp_errors)); + } + } + return ret; +} + +int +main (void) +{ + int ret = 0; + ret |= run_vec4d_tests (); + ret |= run_vec4f_tests (); + return ret; +} From 03fcb530c71a7a107839598bba55f3a07b7a3953 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Dec 2020 12:45:25 +0900 Subject: [PATCH 1127/3664] [util] Make quat test failure prints clearer --- libs/util/test/test-quat.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index 8e4738449..9144f56be 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -296,12 +296,12 @@ test_rotation4 (const vec3_t a, const vec3_t b, const quat_t expect) return 1; fail: printf ("\ntest_rotation4\n"); - printf ("%11.9g %11.9g %11.9g\n", VectorExpand(a)); - printf ("%11.9g %11.9g %11.9g\n", VectorExpand(b)); - printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand(quat)); - printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand(expect)); - printf ("%11.9g %11.9g %11.9g\n", VectorExpand(t)); - printf ("%11.9g\n", d); + printf ("a: %11.9g %11.9g %11.9g\n", VectorExpand(a)); + printf ("b: %11.9g %11.9g %11.9g\n", VectorExpand(b)); + printf ("q: %11.9g %11.9g %11.9g %11.9g\n", QuatExpand(quat)); + printf ("e: %11.9g %11.9g %11.9g %11.9g\n", QuatExpand(expect)); + printf ("t: %11.9g %11.9g %11.9g\n", VectorExpand(t)); + printf ("d: %11.9g\n", d); return 0; } @@ -351,6 +351,7 @@ test_quat_mat(const quat_t q, const quat_t expect) goto fail; return 1; fail: + printf ("\ntest_quat_mat\n"); printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (q)); printf ("%11.9g %11.9g %11.9g %11.9g %11.9g %11.9g\n", VectorExpand (m + 0), VectorExpand (expect + 0)); From 1ddd57b09ecdac19a7be6f322dd957541b0eda6f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Dec 2020 14:52:36 +0900 Subject: [PATCH 1128/3664] [util] Add qconj, vtrunc, vceil and vfloor functions I had forgotten these rather critical functions. Both double and float versions are included. --- include/QF/simd/vec4d.h | 26 ++++++++++++++++++++ include/QF/simd/vec4f.h | 30 +++++++++++++++++++++++ libs/util/test/test-simd.c | 50 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index d608933f5..11e173eff 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -133,6 +133,14 @@ qrotd (vec4d_t a, vec4d_t b) return q; } +vec4d_t qconjd (vec4d_t q) __attribute__((const)); +vec4d_t +qconjd (vec4d_t q) +{ + const vec4l_t neg = { 1lu << 63, 1lu << 63, 1lu << 63, 0 }; + return _mm256_xor_pd (q, (__m256d) neg); +} + vec4d_t loadvec3d (const double v3[]) __attribute__((pure, access(read_only, 1))); vec4d_t loadvec3d (const double v3[]) @@ -153,4 +161,22 @@ void storevec3d (double v3[3], vec4d_t v4) v3[2] = v4[2]; } +vec4d_t vceild (vec4d_t v) __attribute__((const)); +vec4d_t vceild (vec4d_t v) +{ + return _mm256_ceil_pd (v); +} + +vec4d_t vfloord (vec4d_t v) __attribute__((const)); +vec4d_t vfloord (vec4d_t v) +{ + return _mm256_floor_pd (v); +} + +vec4d_t vtruncd (vec4d_t v) __attribute__((const)); +vec4d_t vtruncd (vec4d_t v) +{ + return _mm256_round_pd (v, _MM_FROUND_TRUNC); +} + #endif//__QF_simd_vec4d_h diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index ea92b81d9..e2e09c341 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -127,6 +127,18 @@ qrotf (vec4f_t a, vec4f_t b) return q; } +/** Return the conjugate of the quaternion. + * + * That is, [-x, -y, -z, w]. + */ +vec4f_t qconjf (vec4f_t q) __attribute__((const)); +vec4f_t +qconjf (vec4f_t q) +{ + const vec4i_t neg = { 1u << 31, 1u << 31, 1u << 31, 0 }; + return _mm_xor_ps (q, (__m128) neg); +} + vec4f_t loadvec3f (const float v3[3]) __attribute__((pure, access(read_only, 1))); vec4f_t loadvec3f (const float v3[3]) @@ -156,4 +168,22 @@ void storevec3f (float v3[3], vec4f_t v4) v3[2] = v4[2]; } +vec4f_t vceilf (vec4f_t v) __attribute__((const)); +vec4f_t vceilf (vec4f_t v) +{ + return _mm_ceil_ps (v); +} + +vec4f_t vfloorf (vec4f_t v) __attribute__((const)); +vec4f_t vfloorf (vec4f_t v) +{ + return _mm_floor_ps (v); +} + +vec4f_t vtruncf (vec4f_t v) __attribute__((const)); +vec4f_t vtruncf (vec4f_t v) +{ + return _mm_round_ps (v, _MM_FROUND_TRUNC); +} + #endif//__QF_simd_vec4f_h diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index ec1b145ac..8fcc6935c 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -39,6 +39,46 @@ typedef struct { vec4f_t ulp_errors; } vec4f_test_t; +static vec4d_t tvtruncd (vec4d_t v, vec4d_t ignore) +{ + return vtruncd (v); +} + +static vec4d_t tvceild (vec4d_t v, vec4d_t ignore) +{ + return vceild (v); +} + +static vec4d_t tvfloord (vec4d_t v, vec4d_t ignore) +{ + return vfloord (v); +} + +static vec4d_t tqconjd (vec4d_t v, vec4d_t ignore) +{ + return qconjd (v); +} + +static vec4f_t tvtruncf (vec4f_t v, vec4f_t ignore) +{ + return vtruncf (v); +} + +static vec4f_t tvceilf (vec4f_t v, vec4f_t ignore) +{ + return vceilf (v); +} + +static vec4f_t tvfloorf (vec4f_t v, vec4f_t ignore) +{ + return vfloorf (v); +} + +static vec4f_t tqconjf (vec4f_t v, vec4f_t ignore) +{ + return qconjf (v); +} + static vec4d_test_t vec4d_tests[] = { // 3D dot products { dotd, right, right, one }, @@ -140,6 +180,11 @@ static vec4d_test_t vec4d_tests[] = { { qrotd, up, forward, { -s05, 0, 0, s05 }, { 1.1e-16, 0, 0, 0} }, { qrotd, up, up, qident }, + + { tvtruncd, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -1, -2 } }, + { tvceild, { 1.1, 2.9, -1.1, -2.9 }, {}, { 2, 3, -1, -2 } }, + { tvfloord, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -2, -3 } }, + { tqconjd, one, {}, { -1, -1, -1, 1 } }, }; #define num_vec4d_tests (sizeof (vec4d_tests) / (sizeof (vec4d_tests[0]))) @@ -226,6 +271,11 @@ static vec4f_test_t vec4f_tests[] = { { qrotf, up, right, { 0, s05, 0, s05 } }, { qrotf, up, forward, { -s05, 0, 0, s05 } }, { qrotf, up, up, qident }, + + { tvtruncf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -1, -2 } }, + { tvceilf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 2, 3, -1, -2 } }, + { tvfloorf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -2, -3 } }, + { tqconjf, one, {}, { -1, -1, -1, 1 } }, }; #define num_vec4f_tests (sizeof (vec4f_tests) / (sizeof (vec4f_tests[0]))) From 3125009a7c7779de7434deca6913b17ef5eb7eab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Dec 2020 14:56:59 +0900 Subject: [PATCH 1129/3664] [util] Add vector and quaternion types to cexpr Although there's no distinction between the two at the C level, I think it's probably best to separate them in a scripting language. --- include/QF/cexpr.h | 2 + include/QF/simd/vec4f.h | 4 +- libs/util/cexpr-type.c | 125 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 127 insertions(+), 4 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 0d2b4a8a4..e257412d6 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -112,6 +112,8 @@ extern exprtype_t cexpr_uint; extern exprtype_t cexpr_size_t; extern exprtype_t cexpr_float; extern exprtype_t cexpr_double; +extern exprtype_t cexpr_vector; +extern exprtype_t cexpr_quaternion; extern exprtype_t cexpr_exprval; extern exprtype_t cexpr_field; diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index e2e09c341..997127a94 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -99,8 +99,8 @@ qvmulf (vec4f_t q, vec4f_t v) // zero the scalar of the quaternion. Results in an extra operation, but // avoids adding precision issues. q = _mm_insert_ps (q, q, 0xf8); - vec4f_t c = crossf (q, v); // q.w is 0 so v.w is irrelevant - vec4f_t qv = dotf (q, v); + vec4f_t c = crossf (q, v); + vec4f_t qv = dotf (q, v); // q.w is 0 so v.w is irrelevant vec4f_t qq = dotf (q, q); return (s * s - qq) * v + 2 * (qv * q + s * c); diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index c1dbbafb0..81fc212cd 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -30,6 +30,8 @@ #include #include "QF/cexpr.h" +#include "QF/mathlib.h" +#include "QF/simd/vec4f.h" #include "libs/util/cexpr-parse.h" @@ -232,7 +234,7 @@ static void float_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, exprctx_t *ctx) { - // implement true modulo for integers: + // implement true modulo for floats: // 5 mod 3 = 2 // -5 mod 3 = 1 // 5 mod -3 = -1 @@ -242,6 +244,26 @@ float_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, *(float *) result->value = a - b * floorf (a / b); } +static void +float_mul_vec4f (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + float s = *(float *) val1->value; + __auto_type v = (vec4f_t *) val2->value; + __auto_type r = (vec4f_t *) result->value; + *r = s * *v; +} + +static void +float_div_quat (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + float a = *(float *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = a * qconjf (b) / dotf (b, b); +} + UNOP(float, pos, float, +) UNOP(float, neg, float, -) UNOP(float, tnot, float, !) @@ -250,7 +272,10 @@ binop_t float_binops[] = { { '+', &cexpr_float, &cexpr_float, float_add }, { '-', &cexpr_float, &cexpr_float, float_sub }, { '*', &cexpr_float, &cexpr_float, float_mul }, + { '*', &cexpr_vector, &cexpr_vector, float_mul_vec4f }, + { '*', &cexpr_quaternion, &cexpr_quaternion, float_mul_vec4f }, { '/', &cexpr_float, &cexpr_float, float_div }, + { '/', &cexpr_quaternion, &cexpr_quaternion, float_div_quat }, { '%', &cexpr_float, &cexpr_float, float_rem }, { MOD, &cexpr_float, &cexpr_float, float_mod }, {} @@ -288,7 +313,7 @@ static void double_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, exprctx_t *ctx) { - // implement true modulo for integers: + // implement true modulo for doubles: // 5 mod 3 = 2 // -5 mod 3 = 1 // 5 mod -3 = -1 @@ -326,6 +351,102 @@ exprtype_t cexpr_double = { double_unops, }; +BINOP(vector, add, vec4f_t, +) +BINOP(vector, sub, vec4f_t, -) +BINOP(vector, mul, vec4f_t, *) +BINOP(vector, div, vec4f_t, /) + +static void +vector_rem (const exprval_t *val1, const exprval_t *val2, exprval_t *result, + exprctx_t *ctx) +{ + vec4f_t a = *(vec4f_t *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = a - b * vtruncf (a / b); +} + +static void +vector_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, + exprctx_t *ctx) +{ + // implement true modulo for doubles: + // 5 mod 3 = 2 + // -5 mod 3 = 1 + // 5 mod -3 = -1 + // -5 mod -3 = -2 + vec4f_t a = *(vec4f_t *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = a - b * vfloorf (a / b); +} + +UNOP(vector, pos, vec4f_t, +) +UNOP(vector, neg, vec4f_t, -) + +static void +vector_tnot (const exprval_t *val, exprval_t *result, exprctx_t *ctx) +{ + vec4f_t v = *(vec4f_t *) val->value; + __auto_type c = (vec4i_t *) result->value; + *c = v != 0; +} + +binop_t vector_binops[] = { + { '+', &cexpr_vector, &cexpr_vector, vector_add }, + { '-', &cexpr_vector, &cexpr_vector, vector_sub }, + { '*', &cexpr_vector, &cexpr_vector, vector_mul }, + { '/', &cexpr_vector, &cexpr_vector, vector_div }, + { '%', &cexpr_vector, &cexpr_vector, vector_rem }, + { MOD, &cexpr_vector, &cexpr_vector, vector_mod }, + {} +}; + +unop_t vector_unops[] = { + { '+', &cexpr_vector, vector_pos }, + { '-', &cexpr_vector, vector_neg }, + { '!', &cexpr_vector, vector_tnot }, + {} +}; + +exprtype_t cexpr_vector = { + "vector", + sizeof (vec4f_t), + vector_binops, + vector_unops, +}; + +static void +quaternion_mul (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + vec4f_t a = *(vec4f_t *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = qmulf (a, b); +} + +binop_t quaternion_binops[] = { + { '+', &cexpr_quaternion, &cexpr_quaternion, vector_add }, + { '-', &cexpr_quaternion, &cexpr_quaternion, vector_sub }, + { '*', &cexpr_quaternion, &cexpr_quaternion, quaternion_mul }, + {} +}; + +unop_t quaternion_unops[] = { + { '+', &cexpr_vector, vector_pos }, + { '-', &cexpr_vector, vector_neg }, + { '!', &cexpr_vector, vector_tnot }, + {} +}; + +exprtype_t cexpr_quaternion = { + "quaterion", + sizeof (vec4f_t), + quaternion_binops, + quaternion_unops, +}; + exprtype_t cexpr_exprval = { "exprval", sizeof (exprval_t *), From 4039075f41dacb15a4a4f368bc433587f18b71b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Dec 2020 18:19:43 +0900 Subject: [PATCH 1130/3664] [util] Use a linked list of free cache lines The idea is to not search through blocks for an available allocation. While the goal was to speed up allocation of cache lines of varying cluster sizes, it's not enough due to fragmentation. --- include/QF/cmem.h | 18 +++- libs/util/cmem.c | 187 ++++++++++++++++++++++++------------- libs/util/test/test-cmem.c | 9 +- 3 files changed, 144 insertions(+), 70 deletions(-) diff --git a/include/QF/cmem.h b/include/QF/cmem.h index 966696d6c..dafdd97f9 100644 --- a/include/QF/cmem.h +++ b/include/QF/cmem.h @@ -32,9 +32,21 @@ #define MEM_LINE_SIZE 64 typedef struct memline_s { - struct memline_s *next; + /* chain of free line blocks for fast allocation + * chain begins in memsuper_t + */ + struct memline_s *free_next; + struct memline_s **free_prev; + /* chain of free line blocks within a membock for merging + * chain begins in memblock_t + */ + struct memline_s *block_next; + struct memline_s **block_prev; size_t size; - size_t pad[6]; + /* owning block + */ + struct memblock_s *block; + size_t pad[2]; } memline_t; typedef struct memsline_s { @@ -85,7 +97,7 @@ typedef struct memsuper_s { * allocated, and 64 bytes and up consume entire cache lines. */ memsline_t *last_freed[4]; - size_t pad; + memline_t *free_lines; } memsuper_t; memsuper_t *new_memsuper (void); diff --git a/libs/util/cmem.c b/libs/util/cmem.c index b446e58f0..d395eb78f 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -51,7 +51,32 @@ delete_memsuper (memsuper_t *super) free (super); } -static memblock_t * +static void +link_free_line (memsuper_t *super, memline_t *line) +{ + if (super->free_lines) { + super->free_lines->free_prev = &line->free_next; + } + line->free_next = super->free_lines; + line->free_prev = &super->free_lines; + super->free_lines = line; +} + +static void +unlink_line (memline_t *line) +{ + if (line->block_next) { + line->block_next->block_prev = line->block_prev; + } + *line->block_prev = line->block_next; + + if (line->free_next) { + line->free_next->free_prev = line->free_prev; + } + *line->free_prev = line->free_next; +} + +static memblock_t * __attribute__((noinline)) init_block (memsuper_t *super, void *mem, size_t alloc_size) { size_t size = super->page_size; @@ -78,14 +103,20 @@ init_block (memsuper_t *super, void *mem, size_t alloc_size) block->pre_size -= MEM_LINE_SIZE; } if (block->pre_size) { - block->free_lines = (memline_t *) ((size_t) block - block->pre_size); - block->free_lines->next = 0; - block->free_lines->size = block->pre_size; + memline_t *line = (memline_t *) ((size_t) block - block->pre_size); + + link_free_line (super, line); + + line->block = block; + line->block_next = 0; + line->block_prev = &block->free_lines; + block->free_lines = line; + line->size = block->pre_size; } return block; } -static memblock_t * +static memblock_t * __attribute__((noinline)) block_alloc (memsuper_t *super, size_t size) { memblock_t *block; @@ -111,38 +142,39 @@ block_alloc (memsuper_t *super, size_t size) return block; } -static void * -line_alloc (memblock_t *block, size_t size) +static void * __attribute__((noinline)) +alloc_line (memline_t *line, size_t size) { - memline_t **line = &block->free_lines; - memline_t **best = 0; - memline_t *mem; - size_t best_size = ~0u; + void *mem = line; - while (*line) { - if ((*line)->size >= size && (*line)->size < best_size) { - best_size = (*line)->size; - best = line; + if (line->size > size) { + // split the line block and insert the new block into the list + memline_t *split = (memline_t *)((size_t) line + size); + split->block = line->block; + split->size = line->size - size; + line->size = size; + + split->block_next = line->block_next; + if (split->block_next) { + split->block_next->block_prev = &split->block_next; } - line = &(*line)->next; + line->block_next = split; + split->block_prev = &line->block_next; + + split->free_next = line->free_next; + if (split->free_next) { + split->free_next->free_prev = &split->free_next; + } + line->free_next = split; + split->free_prev = &line->free_next; } - if (!best) { - return 0; - } - mem = *best; - if (size < best_size) { - *best = (memline_t *)((size_t) mem + size); - (*best)->next = mem->next; - (*best)->size = mem->size - size; - } else { - *best = (*best)->next; - } - block->pre_allocated += size; + line->block->pre_allocated += line->size; + unlink_line (line); return mem; } -static void -line_free (memblock_t *block, void *mem) +static void __attribute__((noinline)) +line_free (memsuper_t *super, memblock_t *block, void *mem) { //FIXME right now, can free only single lines (need allocated lines to // have a control block) @@ -152,37 +184,55 @@ line_free (memblock_t *block, void *mem) block->pre_allocated -= size; - for (l = &block->free_lines; *l; l = &(*l)->next) { + for (l = &block->free_lines; *l; l = &(*l)->block_next) { line = *l; - + if (line->block_next && line->block_next < line) { + *(int *)0 = 0; + } if ((size_t) mem + size < (size_t) line) { // line to be freed is below the free line break; } if ((size_t) mem + size == (size_t) line) { // line to be freed is immediately below the free line - // merge with the free line + // merge with the free line by "allocating" the line and then + // "freeing" it with the line to be freed size += line->size; - line = line->next; + unlink_line (line); // does not modify line->block_next + line = line->block_next; break; } if ((size_t) line + line->size == (size_t) mem) { // line to be freed is immediately above the free line - // merge with the free line + // merge with the free line by growing the line line->size += size; - if (line->next && (size_t) line->next == (size_t) mem + size) { - line->size += line->next->size; - line->next = line->next->next; + if (line->block_next + && (size_t) line->block_next == (size_t) mem + size) { + // the line to be freed connects two free lines + line->size += line->block_next->size; + unlink_line (line->block_next); } return; } + if ((size_t) mem >= (size_t) line + && (size_t) mem < (size_t) line + line->size) { + *(int *) 0 = 0; + } + line = 0; } - ((memline_t *) mem)->next = line; - ((memline_t *) mem)->size = size; - *l = mem; + memline_t *memline = (memline_t *) mem; + memline->block_next = line; + if (memline->block_next) { + memline->block_next->block_prev = &memline->block_next; + } + memline->block_prev = l; + memline->size = size; + memline->block = block; + *l = memline; + link_free_line (super, memline); } -static memsline_t * +static memsline_t * __attribute__((noinline)) sline_new (memsuper_t *super, size_t size_ind) { size_t size = 4 << size_ind; @@ -224,26 +274,29 @@ cmemalloc (memsuper_t *super, size_t size) size = 4 << ind; if (size >= MEM_LINE_SIZE) { // whole cache lines are required for this object - // FIXME slow - memblock_t *block = super->memblocks; - void *mem; + memline_t *line = super->free_lines; - while (block) { - if ((mem = line_alloc (block, size))) { - return mem; - } - block = block->next; + while (line && line->size < size) { + line = line->free_next; } - /* The cache-line pool is page aligned for two reasons: - * 1) so it fits exactly within a page - * 2) the control block can be found easily - * And the reason the pool is exactly one page large is so no - * allocated line is ever page-aligned as that would make the line - * indistinguishable from a large block. - */ - mem = aligned_alloc (super->page_size, super->page_size); - block = init_block (super, mem, super->page_size); - return line_alloc (block, size); + if (!line) { + // need a new line, one that doesn't make me fe... wrong song + void *mem; + /* The cache-line pool is page aligned for two reasons: + * 1) so it fits exactly within a page + * 2) the control block can be found easily + * And the reason the pool is exactly one page large is so no + * allocated line is ever page-aligned as that would make the + * line indistinguishable from a large block. + */ + mem = aligned_alloc (super->page_size, super->page_size); + // sets super->free_lines, the block is guarnateed to be big + // enough to hold the requested allocation as otherwise a full + // block allocation would have been used + init_block (super, mem, super->page_size); + line = super->free_lines; + } + return alloc_line (line, size);; } else { void *mem = 0; memsline_t **sline = &super->last_freed[ind]; @@ -273,9 +326,15 @@ cmemalloc (memsuper_t *super, size_t size) return 0; } -static void +static void __attribute__((noinline)) unlink_block (memblock_t *block) { + if (block->pre_size) { + if (!block->free_lines || block->free_lines->block_next) { + *(int *) 0 = 0; + } + unlink_line (block->free_lines); + } if (block->next) { block->next->prev = block->prev; } @@ -303,7 +362,9 @@ cmemfree (memsuper_t *super, void *mem) *(memsline_t **) (size_t)(sline->prev << 6) = sline->next; } - (*super_sline)->prev = (size_t) &sline->next >> 6; + if (*super_sline) { + (*super_sline)->prev = (size_t) &sline->next >> 6; + } sline->next = *super_sline; sline->prev = (size_t) super_sline >> 6; (*super_sline) = sline; @@ -314,7 +375,7 @@ cmemfree (memsuper_t *super, void *mem) size_t page_size = super->page_size; size_t page_mask = super->page_mask; block = (memblock_t *) (((size_t) mem + page_size) & ~page_mask) - 1; - line_free (block, mem); + line_free (super, block, mem); } else { // large block block = (memblock_t *) mem - 1; diff --git a/libs/util/test/test-cmem.c b/libs/util/test/test-cmem.c index c8c2ee7e3..6acd76c33 100644 --- a/libs/util/test/test-cmem.c +++ b/libs/util/test/test-cmem.c @@ -90,7 +90,7 @@ test_line (memsuper_t *super) fprintf (stderr, "line3 not contiguous with free lines\n"); return 0; } - if (block->free_lines->next) { + if (block->free_lines->block_next) { fprintf (stderr, "multiple free line blocks\n"); return 0; } @@ -117,11 +117,12 @@ test_line (memsuper_t *super) fprintf (stderr, "free lines not pointing to line2\n"); return 0; } - if (!block->free_lines->next || block->free_lines->next->next) { + if (!block->free_lines->block_next + || block->free_lines->block_next->block_next) { fprintf (stderr, "incorrect number of free blocks\n"); return 0; } - if (line2->next != old_line || old_line->size != old_size) { + if (line2->block_next != old_line || old_line->size != old_size) { fprintf (stderr, "free line blocks corrupted\n"); return 0; } @@ -254,7 +255,7 @@ main (void) if (sizeof (memsuper_t) != MEM_LINE_SIZE) { fprintf (stderr, "memsuper_t not cache size: %zd\n", - sizeof (memline_t)); + sizeof (memsuper_t)); return 1; } if (sizeof (memline_t) != MEM_LINE_SIZE) { From 73544f07908e18a29f12dd7261fe381d2e0a7160 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Dec 2020 20:42:39 +0900 Subject: [PATCH 1131/3664] [util] Split cmem's free cache-line over size bins They're binned by powers of two (with in between sizes going to the smaller bin should I make cache-line allocations NPOT (which I think might be worthwhile). However, there seems to still be a bug somewhere causing a nasty leak as now my hacked qfvis consumes 40G in less than a minute. --- include/QF/cmem.h | 12 +++++++++++- libs/util/cmem.c | 38 +++++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/include/QF/cmem.h b/include/QF/cmem.h index dafdd97f9..5f0d733ea 100644 --- a/include/QF/cmem.h +++ b/include/QF/cmem.h @@ -30,6 +30,7 @@ #include "QF/qtypes.h" #define MEM_LINE_SIZE 64 +#define MAX_CACHE_LINES 9 typedef struct memline_s { /* chain of free line blocks for fast allocation @@ -97,7 +98,16 @@ typedef struct memsuper_s { * allocated, and 64 bytes and up consume entire cache lines. */ memsline_t *last_freed[4]; - memline_t *free_lines; + /* Free chache lines grouped by size. + * + * The index is the base-2 log of the MINIMUM number of cache lines + * available in each block. ie, blocks with 4, 5, 6 and 7 lines will all + * be in the third list (index 2). For 4k page sizes, only 6 lists are + * needed (32-63 lines) because a page can hold only 62 lines (1 for the + * control block and one to avoid a cache-line being on a page boundary). + * Having 9 (MAX_CACHE_LINES) lists allows page sizes up to 16kB. + */ + memline_t *free_lines[MAX_CACHE_LINES]; } memsuper_t; memsuper_t *new_memsuper (void); diff --git a/libs/util/cmem.c b/libs/util/cmem.c index d395eb78f..c98eeb389 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -29,6 +29,15 @@ #include "QF/alloc.h" #include "QF/cmem.h" +static size_t __attribute__((const)) +ilog2 (size_t x) +{ + size_t l = 0; + while (x >>= 1) { + l++; + } + return l; +} memsuper_t * new_memsuper (void) @@ -54,12 +63,13 @@ delete_memsuper (memsuper_t *super) static void link_free_line (memsuper_t *super, memline_t *line) { - if (super->free_lines) { - super->free_lines->free_prev = &line->free_next; + size_t ind = ilog2 (line->size) - 6; + if (super->free_lines[ind]) { + super->free_lines[ind]->free_prev = &line->free_next; } - line->free_next = super->free_lines; - line->free_prev = &super->free_lines; - super->free_lines = line; + line->free_next = super->free_lines[ind]; + line->free_prev = &super->free_lines[ind]; + super->free_lines[ind] = line; } static void @@ -105,13 +115,14 @@ init_block (memsuper_t *super, void *mem, size_t alloc_size) if (block->pre_size) { memline_t *line = (memline_t *) ((size_t) block - block->pre_size); - link_free_line (super, line); - line->block = block; + line->size = block->pre_size; + line->block_next = 0; line->block_prev = &block->free_lines; block->free_lines = line; - line->size = block->pre_size; + + link_free_line (super, line); } return block; } @@ -274,8 +285,13 @@ cmemalloc (memsuper_t *super, size_t size) size = 4 << ind; if (size >= MEM_LINE_SIZE) { // whole cache lines are required for this object - memline_t *line = super->free_lines; + // convert from byte log2 to cache-line log2 + ind -= 4; + memline_t *line = 0; + while (!line && ind < MAX_CACHE_LINES) { + line = super->free_lines[ind++]; + } while (line && line->size < size) { line = line->free_next; } @@ -293,8 +309,8 @@ cmemalloc (memsuper_t *super, size_t size) // sets super->free_lines, the block is guarnateed to be big // enough to hold the requested allocation as otherwise a full // block allocation would have been used - init_block (super, mem, super->page_size); - line = super->free_lines; + memblock_t *block = init_block (super, mem, super->page_size); + line = block->free_lines; } return alloc_line (line, size);; } else { From d12abc513259b88898a933456a2fbbfcb9c51d4f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Dec 2020 01:47:53 +0900 Subject: [PATCH 1132/3664] [util] Relink grown free line block This fixes one source of memory leaks, but it seems some are still lurking as qfvis still leaks like a sieve. --- libs/util/cmem.c | 17 +- libs/util/test/test-cmem.c | 337 ++++++++++++++++++++++++++++++++----- 2 files changed, 307 insertions(+), 47 deletions(-) diff --git a/libs/util/cmem.c b/libs/util/cmem.c index c98eeb389..cc55ef01a 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -72,6 +72,15 @@ link_free_line (memsuper_t *super, memline_t *line) super->free_lines[ind] = line; } +static void +unlink_free_line (memline_t *line) +{ + if (line->free_next) { + line->free_next->free_prev = line->free_prev; + } + *line->free_prev = line->free_next; +} + static void unlink_line (memline_t *line) { @@ -80,10 +89,7 @@ unlink_line (memline_t *line) } *line->block_prev = line->block_next; - if (line->free_next) { - line->free_next->free_prev = line->free_prev; - } - *line->free_prev = line->free_next; + unlink_free_line (line); } static memblock_t * __attribute__((noinline)) @@ -223,6 +229,9 @@ line_free (memsuper_t *super, memblock_t *block, void *mem) line->size += line->block_next->size; unlink_line (line->block_next); } + // the line changed size so needs to be relinked in the super + unlink_free_line (line); + link_free_line (super, line); return; } if ((size_t) mem >= (size_t) line diff --git a/libs/util/test/test-cmem.c b/libs/util/test/test-cmem.c index 6acd76c33..107c20ad4 100644 --- a/libs/util/test/test-cmem.c +++ b/libs/util/test/test-cmem.c @@ -1,9 +1,10 @@ #include -#include +#include #include #include #include "QF/cmem.h" +#include "QF/set.h" static int test_block (memsuper_t *super) @@ -46,6 +47,133 @@ test_block (memsuper_t *super) return 1; } +static int +check_block (memblock_t *block, int line_count, int allocated) +{ + set_t *visited = set_new (); + size_t free_bytes = 0; + int ret = 1; + int count = 0; + + for (memline_t **l = &block->free_lines; *l; l = &(*l)->block_next) { + memline_t *line = *l; + ptrdiff_t ind = (memline_t *) block - line; + if (ind < 1 || (size_t ) ind > block->pre_size / MEM_LINE_SIZE) { + fprintf (stderr, "line outside of block\n"); + return 0; + } + if (set_is_member (visited, ind)) { + fprintf (stderr, "loop in block free_lines\n"); + return 0; + } + count++; + set_add (visited, ind); + if (!line->size) { + fprintf (stderr, "line with size 0\n"); + ret = 0; + } + if (line->block_next && line->block_next < line) { + fprintf (stderr, "line link in wrong direction\n"); + ret = 0; + } + if ((size_t) line + line->size == (size_t) line->block_next) { + fprintf (stderr, "adjacant free line blocks\n"); + ret = 0; + } + if (line->block_prev != l) { + fprintf (stderr, "line block_prev link incorrect\n"); + ret = 0; + } + if (line->size > block->pre_size) { + fprintf (stderr, "line size too large: %zd / %zd\n", + line->size, block->pre_size); + ret = 0; + } + if (line->size % MEM_LINE_SIZE) { + fprintf (stderr, "bad line size: %zd / %zd\n", + line->size, line->size % MEM_LINE_SIZE); + ret = 0; + } + if (ret) { + free_bytes += line->size; + } + } + if (ret) { + if (free_bytes + block->pre_allocated != block->pre_size) { + fprintf (stderr, "block space mismatch: s: %zd a: %zd f: %zd\n", + block->pre_size, block->pre_allocated, free_bytes); + ret = 0; + } + if (line_count >= 0 && line_count != count) { + fprintf (stderr, "incorrect number of lines: e: %d g: %d\n", + line_count, count); + ret = 0; + } + if (allocated >= 0 && (size_t) allocated != block->pre_allocated) { + fprintf (stderr, "pre_allocated wrong size: %zd != %d\n", + block->pre_allocated, allocated); + } + } + set_delete (visited); + return ret; +} + +static int +check_for_loop (memline_t *line, memline_t **stop) +{ + memline_t *next = line->free_next; + + for (memline_t **l = line->free_prev; l != stop; + l = line->free_prev) { + line = (memline_t *) l; + if (line == next) { + return 1; + } + } + return 0; +} + +static int +check_bins (memsuper_t *super, int mask) +{ + int ret = 1; + for (int i = MAX_CACHE_LINES; i-- > 0; ) { + if (mask >= 0) { + if (mask & (1 << i)) { + if (!super->free_lines[i]) { + fprintf (stderr, "super free_lines[%d] is empty\n", i); + ret = 0; + } + } else { + if (super->free_lines[i]) { + fprintf (stderr, "super free_lines[%d] is occupied\n", i); + ret = 0; + } + } + } + for (memline_t **l = &super->free_lines[i]; *l; l = &(*l)->free_next) { + memline_t *line = *l; + if (line->free_prev != l) { + fprintf (stderr, "super free_lines[%d] has bad prev\n", i); + ret = 0; + break; + } + if (check_for_loop (line, &super->free_lines[i])) { + fprintf (stderr, "super free_lines[%d] loop detected\n", i); + ret = 0; + break; + } + if ((MEM_LINE_SIZE << i) > (int) line->size + || (MEM_LINE_SIZE << (i + 1)) <= (int) line->size) { + fprintf (stderr, "line in wrong i: %d %d %zd\n", + i, MEM_LINE_SIZE << i, line->size); + ret = 0; + } + } + } + return ret; +} + static int test_line (memsuper_t *super) { @@ -90,68 +218,153 @@ test_line (memsuper_t *super) fprintf (stderr, "line3 not contiguous with free lines\n"); return 0; } - if (block->free_lines->block_next) { - fprintf (stderr, "multiple free line blocks\n"); + + if (!check_block (block, 1, 3 * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 1 failed\n"); return 0; } - if (block->pre_allocated != 3 * MEM_LINE_SIZE) { - fprintf (stderr, "pre_allocated wrong size: %zd != %d\n", - block->pre_allocated, 3 * MEM_LINE_SIZE); + if (!check_bins (super, 0x20)) { + fprintf (stderr, "bin check 1 failed\n"); return 0; } - if (block->free_lines->size != block->pre_size - block->pre_allocated) { - fprintf (stderr, "free lines wrong size: %zd != %zd\n", - block->free_lines->size, - block->pre_size - block->pre_allocated); - return 0; - } - size_t old_size = block->free_lines->size; - memline_t *old_line = block->free_lines; + cmemfree (super, line2); - if (block->pre_allocated != 2 * MEM_LINE_SIZE) { - fprintf (stderr, "pre_allocated wrong size: %zd != %d\n", - block->pre_allocated, 2 * MEM_LINE_SIZE); + + if (!check_block (block, 2, 2 * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 2 failed\n"); return 0; } + if (!check_bins (super, 0x21)) { + fprintf (stderr, "bin check 2 failed\n"); + return 0; + } + if (block->free_lines != line2) { - fprintf (stderr, "free lines not pointing to line2\n"); + fprintf (stderr, "block free_lines not pointing to line2\n"); return 0; } - if (!block->free_lines->block_next - || block->free_lines->block_next->block_next) { - fprintf (stderr, "incorrect number of free blocks\n"); - return 0; - } - if (line2->block_next != old_line || old_line->size != old_size) { - fprintf (stderr, "free line blocks corrupted\n"); - return 0; - } - if (block->free_lines->size != MEM_LINE_SIZE) { - fprintf (stderr, "free line block wrong size: %zd != %d\n", - block->free_lines->size, MEM_LINE_SIZE); + if (super->free_lines[0] != line2) { + fprintf (stderr, "super free_lines[0] not pointing to line2\n"); return 0; } + cmemfree (super, line3); + if (!check_block (block, 1, 1 * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 3 failed\n"); + return 0; + } + if (!check_bins (super, 0x20)) { + fprintf (stderr, "bin check 3 failed\n"); + return 0; + } + if (block->free_lines != line2) { fprintf (stderr, "free lines not pointing to line2 2\n"); return 0; } - if (block->pre_allocated != MEM_LINE_SIZE) { - fprintf (stderr, "pre_allocated wrong size: %zd != %d\n", - block->pre_allocated, MEM_LINE_SIZE); - return 0; - } - if (block->free_lines->size != block->pre_size - block->pre_allocated) { - fprintf (stderr, "free lines wrong size: %zd != %zd\n", - block->free_lines->size, - block->pre_size - block->pre_allocated); - return 0; - } + cmemfree (super, line1); if (super->memblocks) { fprintf (stderr, "line pool not freed\n"); return 0; } + if (!check_bins (super, 0x00)) { + fprintf (stderr, "bins not cleared\n"); + return 0; + } + + line1 = cmemalloc (super, MEM_LINE_SIZE); + line2 = cmemalloc (super, MEM_LINE_SIZE); + line3 = cmemalloc (super, MEM_LINE_SIZE); + block = super->memblocks; + + if (!check_block (block, 1, 3 * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 4 failed\n"); + return 0; + } + if (!check_bins (super, 0x20)) { + fprintf (stderr, "bin check 4 failed\n"); + return 0; + } + + cmemfree (super, line1); + + if (!check_block (block, 2, 2 * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 5 failed\n"); + return 0; + } + if (!check_bins (super, 0x21)) { + fprintf (stderr, "bin check 5 failed\n"); + return 0; + } + + cmemfree (super, line2); + + if (!check_block (block, 2, 1 * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 6 failed\n"); + return 0; + } + if (!check_bins (super, 0x22)) { + fprintf (stderr, "bin check 6 failed\n"); + return 0; + } + + cmemfree (super, line3); + if (super->memblocks) { + fprintf (stderr, "line pool not freed 2\n"); + return 0; + } + if (!check_bins (super, 0x00)) { + fprintf (stderr, "bins not cleared 2\n"); + return 0; + } + + line1 = cmemalloc (super, MEM_LINE_SIZE); + line2 = cmemalloc (super, MEM_LINE_SIZE); + line3 = cmemalloc (super, MEM_LINE_SIZE); + block = super->memblocks; + + if (!check_block (block, 1, 3 * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 7 failed\n"); + return 0; + } + if (!check_bins (super, 0x20)) { + fprintf (stderr, "bin check 7 failed\n"); + return 0; + } + + cmemfree (super, line3); + + if (!check_block (block, 1, 2 * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 8 failed\n"); + return 0; + } + if (!check_bins (super, 0x20)) { + fprintf (stderr, "bin check 8 failed\n"); + return 0; + } + + cmemfree (super, line2); + + if (!check_block (block, 1, 1 * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 9 failed\n"); + return 0; + } + if (!check_bins (super, 0x20)) { + fprintf (stderr, "bin check 9 failed\n"); + return 0; + } + + cmemfree (super, line1); + if (super->memblocks) { + fprintf (stderr, "line pool not freed 3\n"); + return 0; + } + if (!check_bins (super, 0x00)) { + fprintf (stderr, "bins not cleared 3\n"); + return 0; + } + return 1; } @@ -252,9 +465,10 @@ int main (void) { memsuper_t *super = new_memsuper (); + int i; - if (sizeof (memsuper_t) != MEM_LINE_SIZE) { - fprintf (stderr, "memsuper_t not cache size: %zd\n", + if (sizeof (memsuper_t) != 2 * MEM_LINE_SIZE) { + fprintf (stderr, "memsuper_t not 2 * cache size: %zd\n", sizeof (memsuper_t)); return 1; } @@ -301,13 +515,50 @@ main (void) fprintf (stderr, "super block list not null\n"); return 1; } + for (i = 4; i-- > 0; ) { + if (super->last_freed[i]) { + break; + } + } + if (i >= 0) { + fprintf (stderr, "super last_freed not all null\n"); + return 1; + } + for (i = MAX_CACHE_LINES; i-- > 0; ) { + if (super->free_lines[i]) { + break; + } + } + if (i >= 0) { + fprintf (stderr, "super free_lines not all null\n"); + return 1; + } if (!test_block (super)) { fprintf (stderr, "block tests failed\n"); + return 1; } if (super->memblocks) { fprintf (stderr, "super block list not null 2\n"); return 1; } + for (i = 4; i-- > 0; ) { + if (super->last_freed[i]) { + break; + } + } + if (i >= 0) { + fprintf (stderr, "super last_freed not all null 2\n"); + return 1; + } + for (i = MAX_CACHE_LINES; i-- > 0; ) { + if (super->free_lines[i]) { + break; + } + } + if (i >= 0) { + fprintf (stderr, "super free_lines not all null 2\n"); + return 1; + } if (!test_line (super)) { fprintf (stderr, "line tests failed\n"); return 1; From 9090c535192c7318f681e39787e9c10b79f8b8c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Dec 2020 11:07:12 +0900 Subject: [PATCH 1133/3664] [util] Add failing sub-line allocator tests I think the sub-line allocator falling over is the final source of qfvis's leaks. It certainly causes a mess of the sub-lines. But having some tests to get working sure beats scratching my head over qfvis :) --- libs/util/test/test-cmem.c | 109 +++++++++++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 22 deletions(-) diff --git a/libs/util/test/test-cmem.c b/libs/util/test/test-cmem.c index 107c20ad4..3d995ba42 100644 --- a/libs/util/test/test-cmem.c +++ b/libs/util/test/test-cmem.c @@ -368,40 +368,105 @@ test_line (memsuper_t *super) return 1; } +typedef struct { + size_t size; + int group_id; +} sline_block_t; + +static sline_block_t group_tests[] = { + { 2, 4}, + { 4, 4}, + { 5, 8}, + { 3, 4}, + { 1, 4}, + { 6, 8}, + { 9, 16}, + { 4, 4}, + { 4, 4}, + { 7, 8}, + { 2, 4}, + { 4, 4}, + { 8, 8}, + {13, 16}, + { 3, 4}, + { 1, 4}, + { 8, 8}, + { 8, 8}, + { 4, 4}, + { 4, 4}, + {16, 16}, + {32, 32}, + {32, 33}, +}; +#define num_group_tests (sizeof (group_tests) / sizeof (group_tests[0])) +#define mask(x) (((size_t) (x)) & ~(MEM_LINE_SIZE - 1)) +#define pagemask(x,o,s) (((size_t) (x)) & (o (s)->page_mask)) + static int test_sline (memsuper_t *super) { - void *mem[] = { - //cmemalloc (super, 2), // smaller than min size - cmemalloc (super, 4), - cmemalloc (super, 4), - cmemalloc (super, 8), - cmemalloc (super, 8), - cmemalloc (super, 16), - cmemalloc (super, 16), - cmemalloc (super, 32), - cmemalloc (super, 32), - }; -#define mem_size (sizeof (mem) / sizeof (mem[0])) - int fail = 0; - for (size_t i = 0; i < mem_size; i++) { - printf("%p\n", mem[i]); + void *mem[num_group_tests]; + int ret = 1; + + for (size_t i = 0; i < num_group_tests; i++) { + mem[i] = cmemalloc (super, group_tests[i].size); if (!mem[i]) { fprintf (stderr, "mem[%zd] is null\n", i); - fail = 1; + return 0; } - for (size_t j = i + 1; j < mem_size; j++) { + if (!((size_t) mem[i] % MEM_LINE_SIZE)) { + fprintf (stderr, "mem[%zd] is aligned with chache line\n", i); + ret = 0; + } + } + for (size_t i = 0; i < num_group_tests; i++) { + for (size_t j = i + 1; j < num_group_tests; j++) { if (mem[i] == mem[j]) { fprintf (stderr, "mem[%zd] is dupped with %zd\n", i, j); - fail = 1; + ret = 0; + } + if (mask (mem[i]) == mask (mem[j])) { + if (group_tests[i].group_id != group_tests[j].group_id) { + fprintf (stderr, "mem[%zd](%d) is grouped with %zd(%d)\n", + i, group_tests[i].group_id, + j, group_tests[j].group_id); + ret = 0; + } + } else { + if (group_tests[i].group_id == group_tests[j].group_id) { + fprintf (stderr, + "mem[%zd](%d) is not grouped with %zd(%d)\n", + i, group_tests[i].group_id, + j, group_tests[j].group_id); + ret = 0; + } + } + if (pagemask (mem[i], ~, super) != pagemask (mem[j], ~, super)) { + fprintf (stderr, + "mem[%zd](%d) is not block grouped with %zd(%d)\n", + i, group_tests[i].group_id, + j, group_tests[j].group_id); } } } - if (fail) { - return 0; + for (size_t i = 0; i < num_group_tests; i++) { + cmemfree (super, mem[i]); + void *newmem = cmemalloc (super, group_tests[i].size); + if (newmem != mem[i]) { + fprintf (stderr, + "%2zd bytes not recycled (%2zd,%2d) (%06zx %06zx)\n", + group_tests[i].size, i, group_tests[i].group_id, + pagemask (mem[i], ~~, super), + pagemask (newmem, ~~, super)); + ret = 0; + } + if (!((size_t) newmem % MEM_LINE_SIZE)) { + fprintf (stderr, "newmem is aligned with chache line %p\n", + newmem); + ret = 0; + } } -#undef mem_size - return 1; + return ret; } static int From efdbd59909202933706e3b7a139a1fdde84c2fed Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Dec 2020 18:12:28 +0900 Subject: [PATCH 1134/3664] [util] Fix handling of sline's list 'pointer' I forgot to right-shift the value so offsets were becoming 0 or 8 instead of 0-15. This fixes the management of small objects. It turns out that after this fix, qfvis's problems were caused by fragmentation in the windings. Need to revisit line allocation and use POT-specialized pools. --- libs/util/cmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/cmem.c b/libs/util/cmem.c index cc55ef01a..77060f8f8 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -377,7 +377,7 @@ cmemfree (memsuper_t *super, void *mem) // sub line block sline = (memsline_t *) ((size_t) mem & ~(MEM_LINE_SIZE - 1)); *(uint16_t *) mem = sline->list << 2; - sline->list = (size_t) mem & (MEM_LINE_SIZE - 1); + sline->list = ((size_t) mem & (MEM_LINE_SIZE - 1)) >> 2; super_sline = &super->last_freed[sline->size]; if (*super_sline != sline) { if (sline->next) { From 1fd02322f45d0e0bc5f57ff70e2f23c3732554bb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Jan 2021 19:53:39 +0900 Subject: [PATCH 1135/3664] [util] Clean up some minor issues in cmem I forgot to remove the noinline attribute and do a check with optimization (to catch the "pure" recommendation). --- libs/util/cmem.c | 12 ++++++------ libs/util/test/test-cmem.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/util/cmem.c b/libs/util/cmem.c index 77060f8f8..9dc461b87 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -92,7 +92,7 @@ unlink_line (memline_t *line) unlink_free_line (line); } -static memblock_t * __attribute__((noinline)) +static memblock_t * init_block (memsuper_t *super, void *mem, size_t alloc_size) { size_t size = super->page_size; @@ -133,7 +133,7 @@ init_block (memsuper_t *super, void *mem, size_t alloc_size) return block; } -static memblock_t * __attribute__((noinline)) +static memblock_t * block_alloc (memsuper_t *super, size_t size) { memblock_t *block; @@ -159,7 +159,7 @@ block_alloc (memsuper_t *super, size_t size) return block; } -static void * __attribute__((noinline)) +static void * alloc_line (memline_t *line, size_t size) { void *mem = line; @@ -190,7 +190,7 @@ alloc_line (memline_t *line, size_t size) return mem; } -static void __attribute__((noinline)) +static void line_free (memsuper_t *super, memblock_t *block, void *mem) { //FIXME right now, can free only single lines (need allocated lines to @@ -252,7 +252,7 @@ line_free (memsuper_t *super, memblock_t *block, void *mem) link_free_line (super, memline); } -static memsline_t * __attribute__((noinline)) +static memsline_t * sline_new (memsuper_t *super, size_t size_ind) { size_t size = 4 << size_ind; @@ -351,7 +351,7 @@ cmemalloc (memsuper_t *super, size_t size) return 0; } -static void __attribute__((noinline)) +static void unlink_block (memblock_t *block) { if (block->pre_size) { diff --git a/libs/util/test/test-cmem.c b/libs/util/test/test-cmem.c index 3d995ba42..4f146ccc7 100644 --- a/libs/util/test/test-cmem.c +++ b/libs/util/test/test-cmem.c @@ -118,7 +118,7 @@ check_block (memblock_t *block, int line_count, int allocated) return ret; } -static int +static int __attribute__ ((pure)) check_for_loop (memline_t *line, memline_t **stop) { memline_t *next = line->free_next; From 7bf90e5f4a8659da87af15c50b2580988ad36405 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Jan 2021 19:49:20 +0900 Subject: [PATCH 1136/3664] [util] Sort out implementation issues for simd --- include/QF/simd/vec4d.h | 192 ++++++++++++++++++++++++++----------- include/QF/simd/vec4f.h | 192 +++++++++++++++++++++++++------------ libs/util/Makemodule.am | 1 + libs/util/simd.c | 37 +++++++ libs/util/test/test-simd.c | 4 + 5 files changed, 308 insertions(+), 118 deletions(-) create mode 100644 libs/util/simd.c diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 11e173eff..6bd984357 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -32,13 +32,107 @@ #include "QF/simd/types.h" +GNU89INLINE inline vec4d_t vsqrtd (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vceild (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vfloord (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vtruncd (vec4d_t v) __attribute__((const)); /** 3D vector cross product. * * The w (4th) component can be any value on input, and is guaranteed to be 0 * in the result. The result is not affected in any way by either vector's w * componemnt */ -vec4d_t crossd (vec4d_t a, vec4d_t b) __attribute__((const)); +GNU89INLINE inline vec4d_t crossd (vec4d_t a, vec4d_t b) __attribute__((const)); +/** 4D vector dot product. + * + * The w component *IS* significant, but if it is 0 in either vector, then + * the result will be as for a 3D dot product. + * + * Note that the dot product is in all 4 of the return value's elements. This + * helps optimize vector math as the scalar is already pre-spread. If just the + * scalar is required, use result[0]. + */ +GNU89INLINE inline vec4d_t dotd (vec4d_t a, vec4d_t b) __attribute__((const)); +/** Quaternion product. + * + * The vector is interpreted as a quaternion instead of a regular 4D vector. + * The quaternion may be of any magnitude, so this is more generally useful. + * than if the quaternion was required to be unit length. + */ +GNU89INLINE inline vec4d_t qmuld (vec4d_t a, vec4d_t b) __attribute__((const)); +/** Optimized quaterion-vector multiplication for vector rotation. + * + * If the vector's w component is not zero, then the result's w component + * is the cosine of the full rotation angle scaled by the vector's w component. + * The quaternion is assumed to be unit. If the quaternion is not unit, the + * vector will be scaled by the square of the quaternion's magnitude. + */ +GNU89INLINE inline vec4d_t qvmuld (vec4d_t q, vec4d_t v) __attribute__((const)); +/** Create the quaternion representing the shortest rotation from a to b. + * + * Both a and b are assumed to be 3D vectors (w components 0), but a resonable + * (but incorrect) result will still be produced if either a or b is a 4D + * vector. The rotation axis will be the same as if both vectors were 3D, but + * the magnitude of the rotation will be different. + */ +GNU89INLINE inline vec4d_t qrotd (vec4d_t a, vec4d_t b) __attribute__((const)); +/** Return the conjugate of the quaternion. + * + * That is, [-x, -y, -z, w]. + */ +GNU89INLINE inline vec4d_t qconjd (vec4d_t q) __attribute__((const)); +GNU89INLINE inline vec4d_t loadvec3d (const double v3[]) __attribute__((pure, access(read_only, 1))); +GNU89INLINE inline void storevec3d (double v3[3], vec4d_t v4) __attribute__((access (write_only, 1))); + +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4d_t +vsqrtd (vec4d_t v) +{ + return _mm256_sqrt_pd (v); +} + +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4d_t +vceild (vec4d_t v) +{ + return _mm256_ceil_pd (v); +} + +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4d_t +vfloord (vec4d_t v) +{ + return _mm256_floor_pd (v); +} + +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4d_t +vtruncd (vec4d_t v) +{ + return _mm256_round_pd (v, _MM_FROUND_TRUNC); +} + +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4d_t crossd (vec4d_t a, vec4d_t b) { @@ -49,16 +143,11 @@ crossd (vec4d_t a, vec4d_t b) return __builtin_shuffle(c, A); } -/** 4D vector dot product. - * - * The w component *IS* significant, but if it is 0 in either vector, then - * the result will be as for a 3D dot product. - * - * Note that the dot product is in all 4 of the return value's elements. This - * helps optimize vector math as the scalar is already pre-spread. If just the - * scalar is required, use result[0]. - */ -vec4d_t dotd (vec4d_t a, vec4d_t b) __attribute__((const)); +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4d_t dotd (vec4d_t a, vec4d_t b) { @@ -69,13 +158,11 @@ dotd (vec4d_t a, vec4d_t b) return c; } -/** Quaternion product. - * - * The vector is interpreted as a quaternion instead of a regular 4D vector. - * The quaternion may be of any magnitude, so this is more generally useful. - * than if the quaternion was required to be unit length. - */ -vec4d_t qmuld (vec4d_t a, vec4d_t b) __attribute__((const)); +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4d_t qmuld (vec4d_t a, vec4d_t b) { @@ -89,14 +176,11 @@ qmuld (vec4d_t a, vec4d_t b) return c - d; } -/** Optimized quaterion-vector multiplication for vector rotation. - * - * If the vector's w component is not zero, then the result's w component - * is the cosine of the full rotation angle scaled by the vector's w component. - * The quaternion is assumed to be unit. If the quaternion is not unit, the - * vector will be scaled by the square of the quaternion's magnitude. - */ -vec4d_t qvmuld (vec4d_t q, vec4d_t v) __attribute__((const)); +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4d_t qvmuld (vec4d_t q, vec4d_t v) { @@ -112,19 +196,16 @@ qvmuld (vec4d_t q, vec4d_t v) return (s * s - qq) * v + 2 * (qv * q + s * c); } -/** Create the quaternion representing the shortest rotation from a to b. - * - * Both a and b are assumed to be 3D vectors (w components 0), but a resonable - * (but incorrect) result will still be produced if either a or b is a 4D - * vector. The rotation axis will be the same as if both vectors were 3D, but - * the magnitude of the rotation will be different. - */ -vec4d_t qrotd (vec4d_t a, vec4d_t b) __attribute__((const)); +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4d_t qrotd (vec4d_t a, vec4d_t b) { - vec4d_t ma = _mm256_sqrt_pd (dotd (a, a)); - vec4d_t mb = _mm256_sqrt_pd (dotd (b, b)); + vec4d_t ma = vsqrtd (dotd (a, a)); + vec4d_t mb = vsqrtd (dotd (b, b)); vec4d_t den = 2 * ma * mb; vec4d_t t = mb * a + ma * b; vec4d_t mba_mab = _mm256_sqrt_pd (dotd (t, t)); @@ -133,7 +214,11 @@ qrotd (vec4d_t a, vec4d_t b) return q; } -vec4d_t qconjd (vec4d_t q) __attribute__((const)); +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4d_t qconjd (vec4d_t q) { @@ -141,7 +226,11 @@ qconjd (vec4d_t q) return _mm256_xor_pd (q, (__m256d) neg); } -vec4d_t loadvec3d (const double v3[]) __attribute__((pure, access(read_only, 1))); +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4d_t loadvec3d (const double v3[]) { @@ -153,30 +242,17 @@ loadvec3d (const double v3[]) return v4; } -void storevec3d (double v3[3], vec4d_t v4) __attribute__((access (write_only, 1))); -void storevec3d (double v3[3], vec4d_t v4) +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +storevec3d (double v3[3], vec4d_t v4) { v3[0] = v4[0]; v3[1] = v4[1]; v3[2] = v4[2]; } -vec4d_t vceild (vec4d_t v) __attribute__((const)); -vec4d_t vceild (vec4d_t v) -{ - return _mm256_ceil_pd (v); -} - -vec4d_t vfloord (vec4d_t v) __attribute__((const)); -vec4d_t vfloord (vec4d_t v) -{ - return _mm256_floor_pd (v); -} - -vec4d_t vtruncd (vec4d_t v) __attribute__((const)); -vec4d_t vtruncd (vec4d_t v) -{ - return _mm256_round_pd (v, _MM_FROUND_TRUNC); -} - #endif//__QF_simd_vec4d_h diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 997127a94..5c0b4cc3d 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -32,21 +32,17 @@ #include "QF/simd/types.h" +GNU89INLINE inline vec4f_t vsqrtf (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vceilf (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vfloorf (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vtruncf (vec4f_t v) __attribute__((const)); /** 3D vector cross product. * * The w (4th) component can be any value on input, and is guaranteed to be 0 * in the result. The result is not affected in any way by either vector's w * componemnt */ -vec4f_t crossf (vec4f_t a, vec4f_t b) __attribute__((const)); -vec4f_t -crossf (vec4f_t a, vec4f_t b) -{ - static const vec4i_t A = {1, 2, 0, 3}; - vec4f_t c = a * __builtin_shuffle (b, A) - __builtin_shuffle (a, A) * b; - return __builtin_shuffle(c, A); -} - +GNU89INLINE inline vec4f_t crossf (vec4f_t a, vec4f_t b) __attribute__((const)); /** 4D vector dot product. * * The w component *IS* significant, but if it is 0 in either vector, then @@ -56,7 +52,99 @@ crossf (vec4f_t a, vec4f_t b) * helps optimize vector math as the scalar is already pre-spread. If just the * scalar is required, use result[0]. */ -vec4f_t dotf (vec4f_t a, vec4f_t b) __attribute__((const)); +GNU89INLINE inline vec4f_t dotf (vec4f_t a, vec4f_t b) __attribute__((const)); +/** Quaternion product. + * + * The vector is interpreted as a quaternion instead of a regular 4D vector. + * The quaternion may be of any magnitude, so this is more generally useful. + * than if the quaternion was required to be unit length. + */ +GNU89INLINE inline vec4f_t qmulf (vec4f_t a, vec4f_t b) __attribute__((const)); +/** Optimized quaterion-vector multiplication for vector rotation. + * + * If the vector's w component is not zero, then the result's w component + * is the cosine of the full rotation angle scaled by the vector's w component. + * The quaternion is assumed to be unit. + */ +GNU89INLINE inline vec4f_t qvmulf (vec4f_t q, vec4f_t v) __attribute__((const)); +/** Create the quaternion representing the shortest rotation from a to b. + * + * Both a and b are assumed to be 3D vectors (w components 0), but a resonable + * (but incorrect) result will still be produced if either a or b is a 4D + * vector. The rotation axis will be the same as if both vectors were 3D, but + * the magnitude of the rotation will be different. + */ +GNU89INLINE inline vec4f_t qrotf (vec4f_t a, vec4f_t b) __attribute__((const)); +/** Return the conjugate of the quaternion. + * + * That is, [-x, -y, -z, w]. + */ +GNU89INLINE inline vec4f_t qconjf (vec4f_t q) __attribute__((const)); +GNU89INLINE inline vec4f_t loadvec3f (const float v3[3]) __attribute__((pure, access(read_only, 1))); +GNU89INLINE inline void storevec3f (float v3[3], vec4f_t v4) __attribute__((access (write_only, 1))); + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +vsqrtf (vec4f_t v) +{ + return _mm_sqrt_ps (v); +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +vceilf (vec4f_t v) +{ + return _mm_ceil_ps (v); +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +vfloorf (vec4f_t v) +{ + return _mm_floor_ps (v); +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +vtruncf (vec4f_t v) +{ + return _mm_round_ps (v, _MM_FROUND_TRUNC); +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +crossf (vec4f_t a, vec4f_t b) +{ + static const vec4i_t A = {1, 2, 0, 3}; + vec4f_t c = a * __builtin_shuffle (b, A) - __builtin_shuffle (a, A) * b; + return __builtin_shuffle(c, A); +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4f_t dotf (vec4f_t a, vec4f_t b) { @@ -66,13 +154,11 @@ dotf (vec4f_t a, vec4f_t b) return c; } -/** Quaternion product. - * - * The vector is interpreted as a quaternion instead of a regular 4D vector. - * The quaternion may be of any magnitude, so this is more generally useful. - * than if the quaternion was required to be unit length. - */ -vec4f_t qmulf (vec4f_t a, vec4f_t b) __attribute__((const)); +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4f_t qmulf (vec4f_t a, vec4f_t b) { @@ -85,13 +171,11 @@ qmulf (vec4f_t a, vec4f_t b) return c - d; } -/** Optimized quaterion-vector multiplication for vector rotation. - * - * If the vector's w component is not zero, then the result's w component - * is the cosine of the full rotation angle scaled by the vector's w component. - * The quaternion is assumed to be unit. - */ -vec4f_t qvmulf (vec4f_t q, vec4f_t v) __attribute__((const)); +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4f_t qvmulf (vec4f_t q, vec4f_t v) { @@ -106,19 +190,16 @@ qvmulf (vec4f_t q, vec4f_t v) return (s * s - qq) * v + 2 * (qv * q + s * c); } -/** Create the quaternion representing the shortest rotation from a to b. - * - * Both a and b are assumed to be 3D vectors (w components 0), but a resonable - * (but incorrect) result will still be produced if either a or b is a 4D - * vector. The rotation axis will be the same as if both vectors were 3D, but - * the magnitude of the rotation will be different. - */ -vec4f_t qrotf (vec4f_t a, vec4f_t b) __attribute__((const)); +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4f_t qrotf (vec4f_t a, vec4f_t b) { - vec4f_t ma = _mm_sqrt_ps (dotf (a, a)); - vec4f_t mb = _mm_sqrt_ps (dotf (b, b)); + vec4f_t ma = vsqrtf (dotf (a, a)); + vec4f_t mb = vsqrtf (dotf (b, b)); vec4f_t den = 2 * ma * mb; vec4f_t t = mb * a + ma * b; vec4f_t mba_mab = _mm_sqrt_ps (dotf (t, t)); @@ -127,11 +208,11 @@ qrotf (vec4f_t a, vec4f_t b) return q; } -/** Return the conjugate of the quaternion. - * - * That is, [-x, -y, -z, w]. - */ -vec4f_t qconjf (vec4f_t q) __attribute__((const)); +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4f_t qconjf (vec4f_t q) { @@ -139,7 +220,11 @@ qconjf (vec4f_t q) return _mm_xor_ps (q, (__m128) neg); } -vec4f_t loadvec3f (const float v3[3]) __attribute__((pure, access(read_only, 1))); +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif vec4f_t loadvec3f (const float v3[3]) { @@ -160,30 +245,17 @@ loadvec3f (const float v3[3]) return v4; } -void storevec3f (float v3[3], vec4f_t v4) __attribute__((access (write_only, 1))); -void storevec3f (float v3[3], vec4f_t v4) +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +storevec3f (float v3[3], vec4f_t v4) { v3[0] = v4[0]; v3[1] = v4[1]; v3[2] = v4[2]; } -vec4f_t vceilf (vec4f_t v) __attribute__((const)); -vec4f_t vceilf (vec4f_t v) -{ - return _mm_ceil_ps (v); -} - -vec4f_t vfloorf (vec4f_t v) __attribute__((const)); -vec4f_t vfloorf (vec4f_t v) -{ - return _mm_floor_ps (v); -} - -vec4f_t vtruncf (vec4f_t v) __attribute__((const)); -vec4f_t vtruncf (vec4f_t v) -{ - return _mm_round_ps (v, _MM_FROUND_TRUNC); -} - #endif//__QF_simd_vec4f_h diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am index f554289be..d2ad47b0c 100644 --- a/libs/util/Makemodule.am +++ b/libs/util/Makemodule.am @@ -74,6 +74,7 @@ libs_util_libQFutil_la_SOURCES= \ libs/util/script.c \ libs/util/segtext.c \ libs/util/set.c \ + libs/util/simd.c \ libs/util/sizebuf.c \ libs/util/string.c \ libs/util/sys.c \ diff --git a/libs/util/simd.c b/libs/util/simd.c new file mode 100644 index 000000000..f5a0fcd35 --- /dev/null +++ b/libs/util/simd.c @@ -0,0 +1,37 @@ +/* + simd.c + + SIMD math support + + Copyright (C) 2020 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#define IMPLEMENT_VEC4F_Funcs +#define IMPLEMENT_VEC4D_Funcs + +#include "QF/simd/vec4d.h" +#include "QF/simd/vec4f.h" diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index 8fcc6935c..006e57526 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include From 015cee7b6f37c95451b0ad3b26405c6bad14d9b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Jan 2021 10:44:45 +0900 Subject: [PATCH 1137/3664] [util] Add vector-quaternion shortcut functions Care needs to be taken to ensure the right function is used with the right arguments, but with these, the need to use qconj(d|f) for a one-off inverse rotation is removed. --- include/QF/simd/vec4d.h | 36 ++++++++++++++++++++++++++++++++++++ include/QF/simd/vec4f.h | 30 ++++++++++++++++++++++++++++++ libs/util/test/test-simd.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 2 deletions(-) diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 6bd984357..1b8adbdfc 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -61,6 +61,8 @@ GNU89INLINE inline vec4d_t dotd (vec4d_t a, vec4d_t b) __attribute__((const)); */ GNU89INLINE inline vec4d_t qmuld (vec4d_t a, vec4d_t b) __attribute__((const)); /** Optimized quaterion-vector multiplication for vector rotation. + * + * \note This is the inverse of vqmulf * * If the vector's w component is not zero, then the result's w component * is the cosine of the full rotation angle scaled by the vector's w component. @@ -68,6 +70,16 @@ GNU89INLINE inline vec4d_t qmuld (vec4d_t a, vec4d_t b) __attribute__((const)); * vector will be scaled by the square of the quaternion's magnitude. */ GNU89INLINE inline vec4d_t qvmuld (vec4d_t q, vec4d_t v) __attribute__((const)); +/** Optimized vector-quaterion multiplication for vector rotation. + * + * \note This is the inverse of qvmulf + * + * If the vector's w component is not zero, then the result's w component + * is the cosine of the full rotation angle scaled by the vector's w component. + * The quaternion is assumed to be unit. If the quaternion is not unit, the + * vector will be scaled by the square of the quaternion's magnitude. + */ +GNU89INLINE inline vec4d_t vqmuld (vec4d_t v, vec4d_t q) __attribute__((const)); /** Create the quaternion representing the shortest rotation from a to b. * * Both a and b are assumed to be 3D vectors (w components 0), but a resonable @@ -183,6 +195,7 @@ VISIBLE #endif vec4d_t qvmuld (vec4d_t q, vec4d_t v) +// ^^^ ^^^ { double s = q[3]; // zero the scalar of the quaternion. Results in an extra operation, but @@ -193,9 +206,32 @@ qvmuld (vec4d_t q, vec4d_t v) vec4d_t qv = dotd (q, v); // q.w is 0 so v.w is irrelevant vec4d_t qq = dotd (q, q); + // vvv return (s * s - qq) * v + 2 * (qv * q + s * c); } +#ifndef IMPLEMENT_VEC4D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4d_t +vqmuld (vec4d_t v, vec4d_t q) +// ^^^ ^^^ +{ + double s = q[3]; + // zero the scalar of the quaternion. Results in an extra operation, but + // avoids adding precision issues. + vec4d_t z = {}; + q = _mm256_blend_pd (q, z, 0x08); + vec4d_t c = crossd (q, v); + vec4d_t qv = dotd (q, v); // q.w is 0 so v.w is irrelevant + vec4d_t qq = dotd (q, q); + + // vvv + return (s * s - qq) * v + 2 * (qv * q - s * c); +} + #ifndef IMPLEMENT_VEC4D_Funcs GNU89INLINE inline #else diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 5c0b4cc3d..f3ea3b22f 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -61,12 +61,23 @@ GNU89INLINE inline vec4f_t dotf (vec4f_t a, vec4f_t b) __attribute__((const)); */ GNU89INLINE inline vec4f_t qmulf (vec4f_t a, vec4f_t b) __attribute__((const)); /** Optimized quaterion-vector multiplication for vector rotation. + * + * \note This is the inverse of vqmulf * * If the vector's w component is not zero, then the result's w component * is the cosine of the full rotation angle scaled by the vector's w component. * The quaternion is assumed to be unit. */ GNU89INLINE inline vec4f_t qvmulf (vec4f_t q, vec4f_t v) __attribute__((const)); +/** Optimized vector-quaterion multiplication for vector rotation. + * + * \note This is the inverse of qvmulf + * + * If the vector's w component is not zero, then the result's w component + * is the cosine of the full rotation angle scaled by the vector's w component. + * The quaternion is assumed to be unit. + */ +GNU89INLINE inline vec4f_t vqmulf (vec4f_t v, vec4f_t q) __attribute__((const)); /** Create the quaternion representing the shortest rotation from a to b. * * Both a and b are assumed to be 3D vectors (w components 0), but a resonable @@ -190,6 +201,25 @@ qvmulf (vec4f_t q, vec4f_t v) return (s * s - qq) * v + 2 * (qv * q + s * c); } +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +vqmulf (vec4f_t v, vec4f_t q) +{ + float s = q[3]; + // zero the scalar of the quaternion. Results in an extra operation, but + // avoids adding precision issues. + q = _mm_insert_ps (q, q, 0xf8); + vec4f_t c = crossf (q, v); + vec4f_t qv = dotf (q, v); // q.w is 0 so v.w is irrelevant + vec4f_t qq = dotf (q, q); + + return (s * s - qq) * v + 2 * (qv * q - s * c); +} + #ifndef IMPLEMENT_VEC4F_Funcs GNU89INLINE inline #else diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index 006e57526..40a7276de 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -153,11 +153,22 @@ static vec4d_test_t vec4d_tests[] = { { qvmuld, one, up, { 4, 0, 0, 0 } }, { qvmuld, one, {1,1,1,0}, { 4, 4, 4, 0 } }, { qvmuld, one, one, { 4, 4, 4, -2 } }, + // inverse rotation, so x->z->y->x + { vqmuld, right, one, { 0, 0, 4, 0 } }, + { vqmuld, forward, one, { 4, 0, 0, 0 } }, + { vqmuld, up, one, { 0, 4, 0, 0 } }, + { vqmuld, {1,1,1,0}, one, { 4, 4, 4, 0 } }, + { vqmuld, one, one, { 4, 4, 4, -2 } }, // The half vector is unit. { qvmuld, half, right, forward }, { qvmuld, half, forward, up }, { qvmuld, half, up, right }, { qvmuld, half, {1,1,1,0}, { 1, 1, 1, 0 } }, + // inverse + { vqmuld, right, half, up }, + { vqmuld, forward, half, right }, + { vqmuld, up, half, forward }, + { vqmuld, {1,1,1,0}, half, { 1, 1, 1, 0 } }, // one is a 4D vector and qvmuld is meant for 3D vectors. However, it // seems that the vector's w has no effect on the 3d portion of the // result, but the result's w is cosine of the full rotation angle @@ -168,6 +179,13 @@ static vec4d_test_t vec4d_tests[] = { { qvmuld, qtest, forward, {0.6144, 0.1808, 0.768, 0}, {0, -2.7e-17, 0, 0} }, { qvmuld, qtest, up, {0.576, -0.768, -0.28, 0} }, + // inverse + { vqmuld, one, half, { 1, 1, 1, -0.5 } }, + { vqmuld, {2,2,2,2}, half, { 2, 2, 2, -1 } }, + { vqmuld, right, qtest, {0.5392, 0.6144, 0.576, 0} }, + { vqmuld, forward, qtest, {0.6144, 0.1808, -0.768, 0}, + {0, -2.7e-17, 0, 0} }, + { vqmuld, up, qtest, {-0.576, 0.768, -0.28, 0} }, { qrotd, right, right, qident }, { qrotd, right, forward, { 0, 0, s05, s05 }, @@ -259,12 +277,25 @@ static vec4f_test_t vec4f_tests[] = { { qvmulf, one, up, { 4, 0, 0, 0 } }, { qvmulf, one, {1,1,1,0}, { 4, 4, 4, 0 } }, { qvmulf, one, one, { 4, 4, 4, -2 } }, + // inverse rotation, so x->z->y->x + { vqmulf, right, one, { 0, 0, 4, 0 } }, + { vqmulf, forward, one, { 4, 0, 0, 0 } }, + { vqmulf, up, one, { 0, 4, 0, 0 } }, + { vqmulf, {1,1,1,0}, one, { 4, 4, 4, 0 } }, + { vqmulf, one, one, { 4, 4, 4, -2 } }, + // { qvmulf, qtest, right, {0.5392, 0.6144, -0.576, 0}, - {0, -5.9e-08, -6e-8, 0} }, + {0, -5.9e-8, -6e-8, 0} }, { qvmulf, qtest, forward, {0.6144, 0.1808, 0.768, 0}, - {-5.9e-08, 1.5e-08, 0, 0} }, + {-5.9e-8, 1.5e-8, 0, 0} }, { qvmulf, qtest, up, {0.576, -0.768, -0.28, 0}, {6e-8, 0, 3e-8, 0} }, + { vqmulf, right, qtest, {0.5392, 0.6144, 0.576, 0}, + {0, -5.9e-8, 5.9e-8, 0} }, + { vqmulf, forward, qtest, {0.6144, 0.1808, -0.768, 0}, + {-5.9e-8, 1.5e-8, 0, 0} }, + { vqmulf, up, qtest, {-0.576, 0.768, -0.28, 0}, + {-5.9e-8, 0, 3e-8, 0} }, { qrotf, right, right, qident }, { qrotf, right, forward, { 0, 0, s05, s05 } }, From eb52d366c8f12d8b07a16834c9c96c995a4259a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Jan 2021 12:10:58 +0900 Subject: [PATCH 1138/3664] [util] Add q-v and v-q multiplication to cexpr --- libs/util/cexpr-type.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 81fc212cd..04eef6d70 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -356,6 +356,16 @@ BINOP(vector, sub, vec4f_t, -) BINOP(vector, mul, vec4f_t, *) BINOP(vector, div, vec4f_t, /) +static void +vector_quaternion_mul (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + vec4f_t a = *(vec4f_t *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = vqmulf (a, b); +} + static void vector_rem (const exprval_t *val1, const exprval_t *val2, exprval_t *result, exprctx_t *ctx) @@ -396,6 +406,7 @@ binop_t vector_binops[] = { { '+', &cexpr_vector, &cexpr_vector, vector_add }, { '-', &cexpr_vector, &cexpr_vector, vector_sub }, { '*', &cexpr_vector, &cexpr_vector, vector_mul }, + { '*', &cexpr_quaternion, &cexpr_vector, vector_quaternion_mul }, { '/', &cexpr_vector, &cexpr_vector, vector_div }, { '%', &cexpr_vector, &cexpr_vector, vector_rem }, { MOD, &cexpr_vector, &cexpr_vector, vector_mod }, @@ -426,10 +437,21 @@ quaternion_mul (const exprval_t *val1, const exprval_t *val2, *c = qmulf (a, b); } +static void +quaternion_vector_mul (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ + vec4f_t a = *(vec4f_t *) val1->value; + vec4f_t b = *(vec4f_t *) val2->value; + __auto_type c = (vec4f_t *) result->value; + *c = qvmulf (a, b); +} + binop_t quaternion_binops[] = { { '+', &cexpr_quaternion, &cexpr_quaternion, vector_add }, { '-', &cexpr_quaternion, &cexpr_quaternion, vector_sub }, { '*', &cexpr_quaternion, &cexpr_quaternion, quaternion_mul }, + { '*', &cexpr_vector, &cexpr_vector, quaternion_vector_mul }, {} }; From 81300f89f8ca473a90840a0dfce5998fe037852d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Jan 2021 14:02:33 +0900 Subject: [PATCH 1139/3664] [util] Allow multiple types for pl fields I want to be able to use name references, but that requires string items, so anything that would normally be dictionary or array (or binary, even) would also need to accept string. This seemed to be the cleanest solution. Any custom parser would then need to check the type and act appropriately, but any inappropriate types have already been pre-filtered by the standard parsers. --- include/QF/qfplist.h | 5 +++- libs/util/qfplist.c | 66 ++++++++++++++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 972f69dc3..20c7671bb 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -44,7 +44,10 @@ typedef enum { QFArray, ///< The property list item represents an array. QFBinary, ///< The property list item represents arbitrary binary ///< data. - QFString ///< The property list item represents a C string. + QFString, ///< The property list item represents a C string. + + QFMultiType = (1 << 31) ///< if bit 31 is set, the type indicates a mask + ///< of allowed types for plfield_t } pltype_t; /** Generic property list item. diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 3e64e3c3e..c3fc5a756 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -227,6 +227,8 @@ PL_Free (plitem_t *item) case QFString: free (item->data); break; + case QFMultiType: + break; } free (item); } @@ -1138,11 +1140,48 @@ pl_default_parser (const plfield_t *field, const plitem_t *item, void *data, case QFString: *(char **)data = (char *)item->data; return 1; + case QFMultiType: + break; } PL_Message (messages, 0, "invalid item type: %d", field->type); return 0; } +static int +types_match (pltype_t field_type, pltype_t item_type) +{ + if (field_type & QFMultiType) { + // field_type is a mask of allowed types + return field_type & (1 << item_type); + } else { + // exact match + return field_type == item_type; + } +} + +static void +type_mismatch (plitem_t *messages, const plitem_t *item, const char *name, + pltype_t field_type, pltype_t item_type) +{ + const int num_types = sizeof (pl_types) / sizeof (pl_types[0]); + if (field_type & QFMultiType) { + PL_Message (messages, item, + "error: %s is the wrong type. Got %s, expected on of:", + name, pl_types[item_type]); + field_type &= ~QFMultiType; + for (int type = 0; field_type && type < num_types; + type++, field_type >>= 1) { + if (field_type & 1) { + PL_Message (messages, item, " %s", pl_types[type]); + } + } + } else { + PL_Message (messages, item, + "error: %s is the wrong type. Got %s, expected %s", name, + pl_types[item_type], pl_types[field_type]); + } +} + VISIBLE int PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, void *data, plitem_t *messages, void *context) @@ -1174,11 +1213,9 @@ PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, void *data, } else { parser = pl_default_parser; } - if (item->type != f->type) { - PL_Message (messages, item, "error: %s is the wrong type" - " Got %s, expected %s",current->key, - pl_types[f->type], - pl_types[item->type]); + if (!types_match (f->type, item->type)) { + type_mismatch (messages, item, current->key, + f->type, item->type); result = 0; } else { if (!parser (f, item, flddata, messages, context)) { @@ -1231,12 +1268,11 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, plitem_t *item = plarray->values[i]; void *eledata = &arr->a[i * element->stride]; - if (item->type != element->type) { - PL_Message (messages, item, - "error: element %d is the wrong type" - " Got %s, expected %s", i, - pl_types[element->type], - pl_types[item->type]); + if (!types_match (element->type, item->type)) { + char index[16]; + snprintf (index, sizeof(index) - 1, "%d", i); + index[15] = 0; + type_mismatch (messages, item, index, element->type, item->type); result = 0; } else { if (!parser (&f, item, eledata, messages, context)) { @@ -1284,12 +1320,8 @@ PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, const char *key = current->key; plitem_t *item = current->value; - if (item->type != element->type) { - PL_Message (messages, item, - "error: element %s is the wrong type" - " Got %s, expected %s", key, - pl_types[element->type], - pl_types[item->type]); + if (!types_match (element->type, item->type)) { + type_mismatch (messages, item, key, element->type, item->type); result = 0; continue; } From 4562e0b8760447438b543d2a098838a74d81b3c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 00:11:52 +0900 Subject: [PATCH 1140/3664] [util] Implement more of cexpr This adds unary, vector and function expressions. --- include/QF/cexpr.h | 14 +++ libs/util/cexpr-parse.y | 193 +++++++++++++++++++++++++++++++++++----- libs/util/cexpr-type.c | 7 ++ 3 files changed, 194 insertions(+), 20 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index e257412d6..77e5b0463 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -62,6 +62,11 @@ typedef struct exprval_s { void *value; } exprval_t; +typedef struct exprlist_s { + struct exprlist_s *next; + exprval_t *value; +} exprlist_t; + typedef struct exprsym_s { const char *name; exprtype_t *type; @@ -69,6 +74,14 @@ typedef struct exprsym_s { struct exprsym_s *next; } exprsym_t; +typedef struct exprfunc_s { + exprtype_t *result; + int num_params; + exprtype_t **param_types; + void (*func) (const exprval_t **params, exprval_t *result, + struct exprctx_s *context); +} exprfunc_t; + typedef struct exprtab_s { exprsym_t *symbols; struct hashtab_s *tab; @@ -116,6 +129,7 @@ extern exprtype_t cexpr_vector; extern exprtype_t cexpr_quaternion; extern exprtype_t cexpr_exprval; extern exprtype_t cexpr_field; +extern exprtype_t cexpr_function; extern binop_t cexpr_struct_binops[]; diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index eb56ed588..f208f4680 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -43,6 +43,7 @@ #include #include "QF/cmem.h" +#include "QF/dstring.h" #include "QF/hash.h" #include "QF/qfplist.h" #include "QF/sys.h" @@ -55,11 +56,17 @@ static exprval_t *binary_expr (int op, const exprval_t *a, const exprval_t *b, exprctx_t *context); static exprval_t *field_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context); +static exprval_t *unary_expr (int op, const exprval_t *val, + exprctx_t *context); +static exprval_t *vector_expr (exprlist_t *list, exprctx_t *context); +static exprval_t *function_expr (exprsym_t *fsym, exprlist_t *list, + exprctx_t *context); +static exprlist_t *expr_item (exprval_t *val, exprctx_t *context); static void yyerror (void *scanner, exprctx_t *context, const char *s) { - cexpr_error (context, "%s before %s\n", s, cexpr_yyget_text (scanner)); + cexpr_error (context, "%s before %s", s, cexpr_yyget_text (scanner)); } %} @@ -78,19 +85,21 @@ yyerror (void *scanner, exprctx_t *context, const char *s) %left SHL SHR %left '+' '-' %left '*' '/' '%' MOD -%right SIZEOF UNARY INCOP +%right SIZEOF UNARY INCOP %left HYPERUNARY %left '.' '(' '[' %token NAME %token VALUE -%type expr field +%type expr field uexpr +%type opt_arg_list arg_list arg_expr %union { int op; exprsym_t *symbol; exprval_t *value; + exprlist_t *list; const char *string; } @@ -100,20 +109,8 @@ start : expr { assign_expr (context->result, $1, context); } ; -expr - : expr SHL expr { $$ = binary_expr (SHL, $1, $3, context); } - | expr SHR expr { $$ = binary_expr (SHR, $1, $3, context); } - | expr '+' expr { $$ = binary_expr ('+', $1, $3, context); } - | expr '-' expr { $$ = binary_expr ('-', $1, $3, context); } - | expr '*' expr { $$ = binary_expr ('*', $1, $3, context); } - | expr '/' expr { $$ = binary_expr ('/', $1, $3, context); } - | expr '&' expr { $$ = binary_expr ('&', $1, $3, context); } - | expr '|' expr { $$ = binary_expr ('|', $1, $3, context); } - | expr '^' expr { $$ = binary_expr ('^', $1, $3, context); } - | expr '%' expr { $$ = binary_expr ('%', $1, $3, context); } - | expr '.' field { $$ = field_expr ($1, $3, context); } - | expr MOD expr { $$ = binary_expr (MOD, $1, $3, context); } - | NAME +uexpr + : NAME { if ($1) { $$ = (exprval_t *) cmemalloc (context->memsuper, sizeof (*$$)); @@ -125,6 +122,29 @@ expr } } | VALUE + | '[' arg_list ']' { $$ = vector_expr ($2, context); } + | '(' expr ')' { $$ = $2; } + | NAME '(' opt_arg_list ')' { $$ = function_expr ($1, $3, context); } + | uexpr '.' field { $$ = field_expr ($1, $3, context); } + | '+' uexpr %prec UNARY { $$ = $2; } + | '-' uexpr %prec UNARY { $$ = unary_expr ('-', $2, context); } + | '!' uexpr %prec UNARY { $$ = unary_expr ('!', $2, context); } + | '~' uexpr %prec UNARY { $$ = unary_expr ('~', $2, context); } + ; + +expr + : uexpr + | expr SHL expr { $$ = binary_expr (SHL, $1, $3, context); } + | expr SHR expr { $$ = binary_expr (SHR, $1, $3, context); } + | expr '+' expr { $$ = binary_expr ('+', $1, $3, context); } + | expr '-' expr { $$ = binary_expr ('-', $1, $3, context); } + | expr '*' expr { $$ = binary_expr ('*', $1, $3, context); } + | expr '/' expr { $$ = binary_expr ('/', $1, $3, context); } + | expr '&' expr { $$ = binary_expr ('&', $1, $3, context); } + | expr '|' expr { $$ = binary_expr ('|', $1, $3, context); } + | expr '^' expr { $$ = binary_expr ('^', $1, $3, context); } + | expr '%' expr { $$ = binary_expr ('%', $1, $3, context); } + | expr MOD expr { $$ = binary_expr (MOD, $1, $3, context); } ; field @@ -141,6 +161,23 @@ field } ; +opt_arg_list + : { $$ = 0; } + | arg_list { $$ = $1; } + ; + +arg_list + : arg_expr + | arg_list ',' arg_expr + { + $3-> next = $1; + $$ = $3; + } + +arg_expr + : expr { $$ = expr_item ($1, context); } + ; + %% static void @@ -156,7 +193,7 @@ assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context) } else { if (dst->type != src->type) { cexpr_error (context, - "type mismatch in expression result: %s = %s\n", + "type mismatch in expression result: %s = %s", dst->type->name, src->type->name); return; } @@ -185,8 +222,9 @@ binary_expr (int op, const exprval_t *a, const exprval_t *b, } exprval_t *result = cexpr_value (rtype, context); if (!binop->op) { - cexpr_error (context, "invalid binary expression: %s %c %s\n", + cexpr_error (context, "invalid binary expression: %s %c %s", a->type->name, op, b->type->name); + memset (result->value, 0, rtype->size); } else { binop->func (a, b, result, context); } @@ -205,11 +243,126 @@ field_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context) } } if (!binop->op) { - cexpr_error (context, "invalid binary expression: %s.%s\n", + cexpr_error (context, "invalid binary expression: %s.%s", a->type->name, b->type->name); + result = cexpr_value (&cexpr_int, context); + *(int *) result->value = 0; } else { exprval_t c = { 0, &result }; binop->func (a, b, &c, context); } return result; } + +static exprval_t * +unary_expr (int op, const exprval_t *val, exprctx_t *context) +{ + unop_t *unop; + + for (unop = val->type->unops; unop->op; unop++) { + if (unop->op == op) { + break; + } + } + exprtype_t *rtype = unop->result; + if (!rtype) { + rtype = val->type; + } + exprval_t *result = cexpr_value (rtype, context); + if (!unop->op) { + cexpr_error (context, "invalid unary expression: %c %s", + op, val->type->name); + } else { + unop->func (val, result, context); + } + return result; +} + +exprval_t * +vector_expr (exprlist_t *list, exprctx_t *context) +{ + exprlist_t *l; + exprval_t *val = cexpr_value (&cexpr_vector, context); + int i; + for (i = 0; i < 4 && list; i++, list = l) { + exprval_t dst = { &cexpr_float, ((float *) val->value) + i }; + exprval_t *src = list->value; + binop_t *cast = cexpr_find_cast (&cexpr_float, src->type); + if (cast) { + cast->func (&dst, src, &dst, context); + } else { + cexpr_error (context, "invalid vector expression type: [%d] %s", + i, val->type->name); + } + l = list->next; + cmemfree (context->memsuper, list); + } + for ( ; i < 4; i++) { + ((float *) val->value)[i] = 0; + } + if (i == 4 && list) { + cexpr_error (context, "excess elements in vector expression"); + } + return val; +} + +static exprval_t *function_expr (exprsym_t *fsym, exprlist_t *list, + exprctx_t *context) +{ + exprlist_t *l; + int num_args = 0; + exprfunc_t *func = 0; + exprval_t *result; + + for (l = list; l; l = l->next) { + num_args++; + } + __auto_type args = (const exprval_t **) alloca (num_args * sizeof (exprval_t *)); + __auto_type types = (exprtype_t **) alloca (num_args * sizeof (exprtype_t *)); + for (num_args = 0; list; list = l, num_args++) { + args[num_args] = list->value; + types[num_args] = list->value->type; + l = list->next; + cmemfree (context->memsuper, list); + } + if (fsym->type != &cexpr_function) { + cexpr_error (context, "invalid function %s", fsym->name); + result = cexpr_value (&cexpr_int, context); + *(int *) result->value = 0; + return result; + } + for (exprfunc_t *f = fsym->value; f->result; f++) { + if (f->num_params == num_args + && memcmp (f->param_types, types, + num_args * sizeof (exprtype_t *)) == 0) { + func = f; + break; + } + } + if (!func) { + dstring_t *argstr = dstring_newstr(); + for (int i = 0; i < num_args; i++) { + dasprintf (argstr, "%s%s", types[i]->name, + i + 1 < num_args ? ", ": ""); + } + cexpr_error (context, "no overload for %s(%s)", fsym->name, + argstr->str); + dstring_delete (argstr); + result = cexpr_value (&cexpr_int, context); + *(int *) result->value = 0; + return result; + } + result = cexpr_value (func->result, context); + func->func (args, result, context); + return result; +} + +static exprlist_t * +expr_item (exprval_t *val, exprctx_t *context) +{ + __auto_type item = (exprlist_t *) cmemalloc (context->memsuper, + sizeof (exprlist_t)); + item->next = 0; + item->value = val; + return item; +} diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 04eef6d70..1a68728de 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -483,6 +483,13 @@ exprtype_t cexpr_field = { 0, }; +exprtype_t cexpr_function = { + "function", + 0, // has no size of its own + 0, // can't actually do anything with a function other than call + 0, +}; + VISIBLE binop_t * cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) { From 619fe1536784727fc99ff8bb58824e08f73f4093 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 00:15:22 +0900 Subject: [PATCH 1141/3664] [util] Add vector swizzles to cexpr That turned out to be a lot easier than expected: needed only 4 ifs per vector "type" (xyzw vs rgba) instead of 340. --- libs/util/cexpr-type.c | 73 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 1a68728de..6b02be01d 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -391,6 +391,78 @@ vector_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, *c = a - b * vfloorf (a / b); } +static void +vector_swizzle (const exprval_t *val1, const exprval_t *val2, + exprval_t *result, exprctx_t *ctx) +{ +#define m(x) (1 << ((x) - 'a')) +#define v(x, mask) (((x) & 0x60) == 0x60 && (m(x) & (mask))) +#define vind(x) ((x) & 3) +#define cind(x) (-(((x) >> 3) ^ (x)) & 3) + const int color = m('r') | m('g') | m('b') | m('a'); + const int vector = m('x') | m('y') | m('z') | m('w'); + float *vec = val1->value; + const char *name = val2->value; + exprval_t *val = 0; + + if (v (name[0], vector) && v (name[1], vector) + && v (name[2], vector) && v (name[3], vector) && !name[4]) { + val = cexpr_value (&cexpr_vector, ctx); + float *res = val->value; + res[0] = vec[vind (name[0])]; + res[1] = vec[vind (name[1])]; + res[2] = vec[vind (name[2])]; + res[3] = vec[vind (name[3])]; + } else if (v (name[0], color) && v (name[1], color) + && v (name[2], color) && v (name[3], color) && !name[4]) { + val = cexpr_value (&cexpr_vector, ctx); + float *res = val->value; + res[0] = vec[cind (name[0])]; + res[1] = vec[cind (name[1])]; + res[2] = vec[cind (name[2])]; + res[3] = vec[cind (name[3])]; + } else if (v (name[0], vector) && v (name[1], vector) + && v (name[2], vector) && !name[3]) { + val = cexpr_value (&cexpr_vector, ctx); + float *res = val->value; + res[0] = vec[vind (name[0])]; + res[1] = vec[vind (name[1])]; + res[2] = vec[vind (name[2])]; + res[3] = 0; + } else if (v (name[0], color) && v (name[1], color) + && v (name[2], color) && !name[3]) { + val = cexpr_value (&cexpr_vector, ctx); + float *res = val->value; + res[0] = vec[cind (name[0])]; + res[1] = vec[cind (name[1])]; + res[2] = vec[cind (name[2])]; + res[3] = 0; + } else if (v (name[0], vector) && v (name[1], vector) && !name[2]) { + val = cexpr_value (&cexpr_vector, ctx); + float *res = val->value; + res[0] = vec[vind (name[0])]; + res[1] = vec[vind (name[1])]; + res[2] = 0; + res[3] = 0; + } else if (v (name[0], color) && v (name[1], color) && !name[2]) { + val = cexpr_value (&cexpr_vector, ctx); + float *res = val->value; + res[0] = vec[cind (name[0])]; + res[1] = vec[cind (name[1])]; + res[2] = 0; + res[3] = 0; + } else if (v (name[0], vector) && !name[1]) { + val = cexpr_value (&cexpr_float, ctx); + float *res = val->value; + res[0] = vec[vind (name[0])]; + } else if (v (name[0], color) && !name[1]) { + val = cexpr_value (&cexpr_float, ctx); + float *res = val->value; + res[0] = vec[cind (name[0])]; + } + *(exprval_t **) result->value = val; +} + UNOP(vector, pos, vec4f_t, +) UNOP(vector, neg, vec4f_t, -) @@ -410,6 +482,7 @@ binop_t vector_binops[] = { { '/', &cexpr_vector, &cexpr_vector, vector_div }, { '%', &cexpr_vector, &cexpr_vector, vector_rem }, { MOD, &cexpr_vector, &cexpr_vector, vector_mod }, + { '.', &cexpr_field, &cexpr_exprval, vector_swizzle }, {} }; From 55445a25f2438ddccf9aa4864086d3201b634e44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 00:18:35 +0900 Subject: [PATCH 1142/3664] [util] Add some tests for the new cexpr work --- libs/util/test/test-cexpr.c | 141 +++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 2 deletions(-) diff --git a/libs/util/test/test-cexpr.c b/libs/util/test/test-cexpr.c index 095316222..338e71bbc 100644 --- a/libs/util/test/test-cexpr.c +++ b/libs/util/test/test-cexpr.c @@ -24,27 +24,125 @@ Boston, MA 02111-1307, USA */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "QF/cexpr.h" #include "QF/cmem.h" #include "QF/hash.h" +#include "QF/mathlib.h" +#include "QF/simd/vec4f.h" int a = 5; int b = 6; int c; +float point[4] = { 2, 3, 4, 1 }; // a point, so w = 1 +float normal[4] = { 1, 2, 3, 0 }; // a vector, so w = 0 +float direction[4] = { 4, 5, 6, 0 }; // a vector, so w = 0 +float plane[4]; +float intercept[4]; + +exprtype_t *vector_params[] = { + &cexpr_vector, + &cexpr_vector, +}; + +exprtype_t *int_params[] = { + &cexpr_int, + &cexpr_int, +}; + +exprtype_t *float_params[] = { + &cexpr_float, + &cexpr_float, +}; + +exprtype_t *double_params[] = { + &cexpr_double, + &cexpr_double, +}; + +static void +float_dot (const exprval_t **params, exprval_t *result, exprctx_t *context) +{ + // parameters are reversed! + vec4f_t *a = params[1]->value; + vec4f_t *b = params[0]->value; + vec4f_t *d = result->value; + *d = dotf (*a, *b); +} + +exprfunc_t dot_func[] = { + { &cexpr_vector, 2, vector_params, float_dot}, + {} +}; + +exprfunc_t sin_func[] = { + { &cexpr_float, 1, float_params }, + { &cexpr_double, 1, double_params }, + {} +}; + +exprfunc_t cos_func[] = { + { &cexpr_float, 1, float_params }, + { &cexpr_double, 1, double_params }, + {} +}; + +exprfunc_t atan2_func[] = { + { &cexpr_float, 2, float_params }, + { &cexpr_double, 2, double_params }, + {} +}; + +exprfunc_t int_func[] = { + { &cexpr_int, 1, float_params }, + { &cexpr_int, 1, double_params }, + {} +}; + +exprfunc_t float_func[] = { + { &cexpr_float, 1, int_params }, + { &cexpr_float, 1, double_params }, + {} +}; + +exprfunc_t double_func[] = { + { &cexpr_double, 1, float_params }, + { &cexpr_double, 1, double_params }, + {} +}; exprsym_t symbols[] = { { "a", &cexpr_int, &a }, { "b", &cexpr_int, &b }, + { "point", &cexpr_vector, &point }, + { "normal", &cexpr_vector, &normal }, + { "plane", &cexpr_vector, &plane }, + { "direction", &cexpr_vector, &direction }, + { "intercept", &cexpr_vector, &intercept }, + { "dot", &cexpr_function, dot_func }, + { "sin", &cexpr_function, sin_func }, + { "cos", &cexpr_function, cos_func }, + { "atan2", &cexpr_function, atan2_func }, + { "float", &cexpr_function, float_func }, + { "double", &cexpr_function, double_func }, + { "int", &cexpr_function, int_func }, {} }; -exprval_t result = { &cexpr_int, &c }; +exprval_t test_result = { &cexpr_int, &c }; +exprval_t plane_result = { &cexpr_vector, &plane }; +// a bit hacky, but no l-values +exprval_t dist_result = { &cexpr_float, &plane[3] }; +exprval_t intercept_result = { &cexpr_vector, &intercept }; exprtab_t symtab = { symbols, 0 }; -exprctx_t context = { &result, &symtab }; +exprctx_t context = { &test_result, &symtab }; #define TEST_BINOP(op) \ do { \ @@ -75,6 +173,45 @@ main(int argc, const char **argv) TEST_BINOP (^); TEST_BINOP (%); + context.result = &plane_result; + cexpr_eval_string ("point.wzyx", &context); + if (plane[0] != point[3] || plane[1] != point[2] + || plane[2] != point[1] || plane[3] != point[0]) { + printf ("point.wzyx [%.9g, %.9g, %.9g] %.9g\n", + VectorExpand (plane), plane[3]); + ret |= 1; + } + cexpr_eval_string ("point.zyx", &context); + if (plane[0] != point[2] || plane[1] != point[1] + || plane[2] != point[0] || plane[3] != 0) { + printf ("point.zyx [%.9g, %.9g, %.9g] %.9g\n", + VectorExpand (plane), plane[3]); + ret |= 1; + } + cexpr_eval_string ("point.yx", &context); + if (plane[0] != point[1] || plane[1] != point[0] + || plane[2] != 0 || plane[3] != 0) { + printf ("point.yx [%.9g, %.9g, %.9g] %.9g\n", + VectorExpand (plane), plane[3]); + ret |= 1; + } + cexpr_eval_string ("normal", &context); + context.result = &dist_result; + cexpr_eval_string ("-dot(point, normal).x / 2f", &context); + if (!VectorCompare (normal, plane) + || plane[3] != -DotProduct (normal, point) / 2) { + printf ("plane [%.9g, %.9g, %.9g] %.9g\n", + VectorExpand (plane), plane[3]); + ret |= 1; + } + context.result = &intercept_result; + cexpr_eval_string ("point - direction * dot(point, plane)/dot(direction,plane)", &context); + if (intercept[0] != 0.75 || intercept[1] != 1.4375 + || intercept[2] != 2.125 || intercept[3] != 1) { + printf ("[%.9g, %.9g, %.9g] %.9g\n", VectorExpand (intercept), intercept[3]); + ret |= 1; + } + Hash_DelTable (symtab.tab); delete_memsuper (context.memsuper); return ret; From 5b842da394beaca4e8f2b45261bc10e88454c322 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 00:21:48 +0900 Subject: [PATCH 1143/3664] [util] Fix types for double and float constants --- libs/util/cexpr-lex.l | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index cdae1ee04..2cbbdaa79 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -241,14 +241,14 @@ static exprval_t *parse_uint (const char *str, exprctx_t *context) static exprval_t *parse_float (const char *str, exprctx_t *context) { - exprval_t *val = cexpr_value (&cexpr_int, context); + exprval_t *val = cexpr_value (&cexpr_float, context); *(float *) val->value = strtof (str, 0); return val; } static exprval_t *parse_double (const char *str, exprctx_t *context) { - exprval_t *val = cexpr_value (&cexpr_int, context); + exprval_t *val = cexpr_value (&cexpr_double, context); *(double *) val->value = strtod (str, 0); return val; } From 0426879bf60119f3b7cc6dbe4ca701fc32268bcf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 14:54:04 +0900 Subject: [PATCH 1144/3664] [qfcc] Check returned type instead of expr type Block expressions hide ex_error, but get_type() always returns null when it finds one (which it does by recursing into block expression), so just check the type itself. --- tools/qfcc/source/expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 9ecf0ad15..a8684a83b 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2075,7 +2075,7 @@ return_expr (function_t *f, expr_t *e) t = get_type (e); - if (e->type == ex_error) { + if (!t) { return e; } if (is_void(ret_type)) { From a6a3d4c6b52ceb0cd735ed019f749497c9b3de86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 15:30:27 +0900 Subject: [PATCH 1145/3664] [vulkan] Make array and single parsing smarter Array and single type overrides now allow the parsing of the items themselves to be customized. This makes it easy to handle arrays and pointers to single items while also using custom specifications, rather than relying entirely on the custom override. --- .../video/renderer/vulkan/vkgen/Makemodule.am | 1 + .../renderer/vulkan/vkgen/vkfieldarray.h | 4 +- .../renderer/vulkan/vkgen/vkfieldarray.r | 9 +-- .../renderer/vulkan/vkgen/vkfieldsingle.h | 4 +- .../renderer/vulkan/vkgen/vkfieldsingle.r | 11 ++- .../video/renderer/vulkan/vkgen/vkfieldtype.h | 20 ++++++ .../video/renderer/vulkan/vkgen/vkfieldtype.r | 69 +++++++++++++++++++ 7 files changed, 103 insertions(+), 15 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldtype.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldtype.r diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 4847bf6fd..b60e97f1d 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -11,6 +11,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkfielddef.r \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.r \ libs/video/renderer/vulkan/vkgen/vkfieldstring.r \ + libs/video/renderer/vulkan/vkgen/vkfieldtype.r \ libs/video/renderer/vulkan/vkgen/vkgen.r \ libs/video/renderer/vulkan/vkgen/vkstruct.r \ libs/video/renderer/vulkan/vkgen/vktype.r \ diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldarray.h b/libs/video/renderer/vulkan/vkgen/vkfieldarray.h index 5cf31880b..6f97f0aa7 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldarray.h +++ b/libs/video/renderer/vulkan/vkgen/vkfieldarray.h @@ -3,9 +3,11 @@ #include "vkfielddef.h" +@class FieldType; + @interface ArrayField: FieldDef { - string type; + FieldType *type; } @end diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldarray.r b/libs/video/renderer/vulkan/vkgen/vkfieldarray.r index dd81dd9f4..159a41ba3 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldarray.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldarray.r @@ -1,6 +1,7 @@ #include #include "vkfieldarray.h" +#include "vkfieldtype.h" #include "vkgen.h" #include "vktype.h" @@ -14,7 +15,7 @@ } PLItem *desc = [item getObjectForKey:"type"]; - type = [[desc getObjectAtIndex:1] string]; + type = [[FieldType fieldType:[desc getObjectAtIndex:1]] retain]; value_field = [[item getObjectForKey:"values"] string]; size_field = [[item getObjectForKey:"size"] string]; @@ -23,13 +24,9 @@ -writeParseData { - Type *field_type = [[Type lookup: type] dereference]; - fprintf (output_file, "static parse_array_t parse_%s_%s_data = {\n", struct_name, field_name); - fprintf (output_file, "\t%s,\n", [field_type parseType]); - fprintf (output_file, "\tsizeof (%s),\n", type); - fprintf (output_file, "\tparse_%s,\n", type); + [type writeParseData]; fprintf (output_file, "\tfield_offset (%s, %s),\n", struct_name, value_field); if (size_field) { diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldsingle.h b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.h index 2fcd312c4..83a3dad77 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldsingle.h +++ b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.h @@ -3,9 +3,11 @@ #include "vkfielddef.h" +@class FieldType; + @interface SingleField: FieldDef { - string type; + FieldType *type; } @end diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r index e30ced3dd..f1c4b4977 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r @@ -1,6 +1,7 @@ #include #include "vkfieldsingle.h" +#include "vkfieldtype.h" #include "vkgen.h" #include "vktype.h" @@ -14,7 +15,7 @@ } PLItem *desc = [item getObjectForKey:"type"]; - type = [[desc getObjectAtIndex:1] string]; + type = [[FieldType fieldType:[desc getObjectAtIndex:1]] retain]; value_field = [[item getObjectForKey:"value"] string]; return self; @@ -22,13 +23,9 @@ -writeParseData { - Type *field_type = [[Type lookup: type] dereference]; - fprintf (output_file, "static parse_single_t parse_%s_%s_data = {\n", struct_name, field_name); - fprintf (output_file, "\t%s,\n", [field_type parseType]); - fprintf (output_file, "\tsizeof (%s),\n", type); - fprintf (output_file, "\tparse_%s,\n", type); + [type writeParseData]; fprintf (output_file, "\tfield_offset (%s, %s),\n", struct_name, value_field); fprintf (output_file, "};\n"); @@ -37,7 +34,7 @@ -writeField { - string parse_type = [[[Type lookup: type] dereference] parseType]; + string parse_type = [type parseType]; fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", field_name, parse_type, "single", struct_name, field_name); return self; diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.h b/libs/video/renderer/vulkan/vkgen/vkfieldtype.h new file mode 100644 index 000000000..fa27c7d8e --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.h @@ -0,0 +1,20 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldtype_h +#define __renderer_vulkan_vkgen_vkfieldtype_h + +#include + +@class PLItem; + +@interface FieldType: Object +{ + string parse_type; + string type; + string parser; +} ++fieldType:(PLItem *)item; +-initWithItem:(PLItem *)item; +-writeParseData; +-(string)parseType; +@end + +#endif//__renderer_vulkan_vkgen_vkfieldtype_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r new file mode 100644 index 000000000..e3d7cf59d --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r @@ -0,0 +1,69 @@ +#include +#include + +#include "vkfieldtype.h" +#include "vkgen.h" +#include "vktype.h" + +@implementation FieldType + ++fieldType:(PLItem *)item +{ + return [[[self alloc] initWithItem:item] autorelease]; +} + +-(void)dealloc +{ + str_free (parser); + str_free (parse_type); +} + +static string +parseItemType (PLItem *item) +{ + string str = [item string]; + if (str) { + return str; + } + string mask = "QFMultiType"; + for (int i = [item count]; i-- > 0; ) { + str = [[item getObjectAtIndex:i] string]; + mask = mask + " | (1 << " + str + ")"; + } + return str_hold (mask); +} + +-initWithItem:(PLItem *)item +{ + if (!(self = [super init])) { + return nil; + } + + type = [item string]; + if (type) { + Type *field_type = [[Type lookup:type] dereference]; + parse_type = [field_type parseType]; + parser = str_hold ("parse_" + type); + } else { + parse_type = parseItemType([item getObjectForKey:"parse_type"]); + type = [[item getObjectForKey:"type"] string]; + parser = [[item getObjectForKey:"parser"] string]; + } + + return self; +} + +-writeParseData +{ + fprintf (output_file, "\t%s,\n", parse_type); + fprintf (output_file, "\tsizeof (%s),\n", type); + fprintf (output_file, "\t%s,\n", parser); + return self; +} + +-(string) parseType +{ + return parse_type; +} + +@end From e4f75791ce273bc74a03828e2207fed1891736f2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 17:26:39 +0900 Subject: [PATCH 1146/3664] [vulkan] Clean up some tangled dependencies Dependencies on vkparse.hinc were spreading through the code which I didn't want as that removes a lot of the automation from the automake files. This keeps all parser code internal to vkparse.c's scope, and any accesses required for enum and struct (not yet) definitions can be fetched by name. --- include/QF/Vulkan/shader.h | 3 -- libs/video/renderer/vulkan/descriptor.c | 1 - libs/video/renderer/vulkan/shader.c | 16 ------ libs/video/renderer/vulkan/vkgen/vkenum.h | 1 + libs/video/renderer/vulkan/vkgen/vkenum.r | 6 +++ libs/video/renderer/vulkan/vkgen/vkgen.r | 1 + libs/video/renderer/vulkan/vkgen/vkstruct.h | 1 + libs/video/renderer/vulkan/vkgen/vkstruct.r | 4 ++ libs/video/renderer/vulkan/vkparse.c | 52 +++++++++++++++---- libs/video/renderer/vulkan/vkparse.h | 3 ++ .../video/renderer/vulkan/vulkan_vid_common.c | 5 +- 11 files changed, 62 insertions(+), 31 deletions(-) diff --git a/include/QF/Vulkan/shader.h b/include/QF/Vulkan/shader.h index b13f6a618..41b38a862 100644 --- a/include/QF/Vulkan/shader.h +++ b/include/QF/Vulkan/shader.h @@ -15,8 +15,5 @@ VkShaderModule QFV_FindShaderModule (struct vulkan_ctx_s *ctx, void QFV_RegisterShaderModule (struct vulkan_ctx_s *ctx, const char *name, VkShaderModule module); void QFV_DeregisterShaderModule (struct vulkan_ctx_s *ctx, const char *name); -int parse_VkShaderModule (const struct plitem_s *item, void **data, - struct plitem_s *messages, - struct parsectx_s *context); #endif//__QF_Vulkan_shader_h diff --git a/libs/video/renderer/vulkan/descriptor.c b/libs/video/renderer/vulkan/descriptor.c index 23c1a0d50..dc7cc6fa4 100644 --- a/libs/video/renderer/vulkan/descriptor.c +++ b/libs/video/renderer/vulkan/descriptor.c @@ -44,7 +44,6 @@ #include "QF/hash.h" #include "QF/input.h" #include "QF/mathlib.h" -#include "QF/qargs.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/va.h" diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 5ee89ca25..e55833782 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -53,7 +53,6 @@ #include "QF/Vulkan/shader.h" #include "vid_vulkan.h" -#include "vkparse.h" static #include "libs/video/renderer/vulkan/passthrough.vert.spvc" @@ -212,18 +211,3 @@ QFV_DeregisterShaderModule (vulkan_ctx_t *ctx, const char *name) } Hash_Free (ctx->shadermodules, Hash_Del (ctx->shadermodules, name)); } - -int -parse_VkShaderModule (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *context) -{ - vulkan_ctx_t *ctx = context->vctx; - const char *name = PL_String (item); - __auto_type mptr = (VkShaderModule *)data[0]; - VkShaderModule module = QFV_FindShaderModule (ctx, name); - if (module) { - *mptr = module; - return 1; - } - return 0; -} diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.h b/libs/video/renderer/vulkan/vkgen/vkenum.h index 4df770b92..5577b8a23 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.h +++ b/libs/video/renderer/vulkan/vkgen/vkenum.h @@ -11,6 +11,7 @@ } -(void) writeTable; -(void) writeSymtabInit; +-(void) writeSymtabEntry; @end #endif//__renderer_vulkan_vkgen_vkenum_h diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 9f12c013e..22342cb1c 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -147,6 +147,12 @@ skip_value(string name) [self name]); } +-(void) writeSymtabEntry +{ + fprintf (output_file, "\tHash_Add (enum_symtab, &%s_enum);\n", + [self name]); +} + -(string) cexprType { return [self name] + "_type"; diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 7a1edab8a..d47873ad2 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -251,6 +251,7 @@ main(int argc, string *argv) } arp_start (); [obj writeSymtabInit]; + [obj writeSymtabEntry]; arp_end (); } fprintf (output_file, "}\n"); diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index 048b3332f..08b489592 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -16,6 +16,7 @@ -(qfot_var_t *)findField:(string) fieldName; -(void) writeTable; -(void) writeSymtabInit; +-(void) writeSymtabEntry; -(string) outname; @end diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index ac03d8f41..6d5c2cfc2 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -165,6 +165,10 @@ [self outname]); } +-(void) writeSymtabEntry +{ +} + -(string) outname { if (outname) { diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index d2ae12949..21e7bdf72 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -42,6 +42,7 @@ #include "QF/cmem.h" #include "QF/cvar.h" #include "QF/dstring.h" +#include "QF/hash.h" #include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" @@ -50,6 +51,7 @@ #include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" +#include "QF/simd/vec4f.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/command.h" @@ -65,7 +67,10 @@ #include "vid_vulkan.h" #include "util.h" + +#define vkparse_internal #include "vkparse.h" +#undef vkparse_internal static void flag_or (const exprval_t *val1, const exprval_t *val2, exprval_t *result, exprctx_t *ctx) @@ -145,19 +150,16 @@ parse_basic (const plfield_t *field, const plitem_t *item, ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); - //Sys_Printf ("parse_uint32_t: %s %zd %d %p %p: %s\n", + //Sys_Printf ("parse_basic: %s %zd %d %p %p: %s\n", // field->name, field->offset, field->type, field->parser, // field->data, valstr); if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) { //FIXME handle subpass in a separate parser? *(uint32_t *) data = VK_SUBPASS_EXTERNAL; } else { - Sys_Printf ("parse_uint32_t: %s %zd %d %p %p %s\n", - field->name, field->offset, field->type, field->parser, - field->data, valstr); ret = !cexpr_eval_string (valstr, &ectx); - Sys_Printf (" %x\n", *(uint32_t *)data); } + //Sys_Printf (" %x\n", *(uint32_t *)data); return ret; } @@ -179,11 +181,11 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, //FIXME handle subpass in a separate parser? *(uint32_t *) data = VK_SUBPASS_EXTERNAL; } else { - Sys_Printf ("parse_uint32_t: %s %zd %d %p %p %s\n", - field->name, field->offset, field->type, field->parser, - field->data, valstr); + //Sys_Printf ("parse_uint32_t: %s %zd %d %p %p %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); ret = !cexpr_eval_string (valstr, &ectx); - Sys_Printf (" %d\n", *(uint32_t *)data); + //Sys_Printf (" %d\n", *(uint32_t *)data); } return ret; @@ -327,6 +329,23 @@ parse_custom (const plfield_t *field, const plitem_t *item, return custom->parse (item, offsets, messages, context); } + +static int +parse_VkShaderModule (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context) +{ + vulkan_ctx_t *ctx = context->vctx; + const char *name = PL_String (item); + __auto_type mptr = (VkShaderModule *)data[0]; + VkShaderModule module = QFV_FindShaderModule (ctx, name); + if (module) { + *mptr = module; + return 1; + } + return 0; +} +static hashtab_t *enum_symtab; + #include "libs/video/renderer/vulkan/vkparse.cinc" typedef struct qfv_renderpass_s { @@ -421,9 +440,24 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) return renderpass; } +static const char * +enum_symtab_getkey (const void *e, void *unused) +{ + __auto_type enm = (const exprenum_t *) e; + return enm->type->name; +} + void QFV_InitParse (void) { exprctx_t context = {}; + enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, + &context.hashlinks); vkgen_init_symtabs (&context); } + +exprenum_t * +QFV_GetEnum (const char *name) +{ + return Hash_Find (enum_symtab, name); +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index b95475bda..e34624dab 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -3,7 +3,9 @@ #include "QF/cexpr.h" #include "QF/Vulkan/renderpass.h" +#ifdef vkparse_internal #include "libs/video/renderer/vulkan/vkparse.hinc" +#endif typedef struct parsectx_s { struct exprctx_s *ectx; @@ -12,5 +14,6 @@ typedef struct parsectx_s { VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); void QFV_InitParse (void); +exprenum_t *QFV_GetEnum (const char *name); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 78c4e9add..7647db9ff 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -98,11 +98,12 @@ msaaSamples_f (cvar_t *var) exprctx_t context = {}; context.memsuper = new_memsuper(); - if (cexpr_parse_enum (&VkSampleCountFlagBits_enum, var->string, &context, - &var->int_val)) { + if (cexpr_parse_enum (QFV_GetEnum ("VkSampleCountFlagBits"), var->string, + &context, &var->int_val)) { Sys_Printf ("Invalid MSAA samples, using 1\n"); var->int_val = VK_SAMPLE_COUNT_1_BIT; } + delete_memsuper (context.memsuper); } static void From d919a85c8e63cd7757f6b9be49cb0fc59d5124d3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 17:36:11 +0900 Subject: [PATCH 1147/3664] [vulkan] Implement pipeline layout creation It seems to work when parsing the layouts. They can be created in-line (in theory) or in a "setLayouts" node and then referenced by name. --- include/vid_vulkan.h | 1 + libs/video/renderer/vulkan/qfpipeline.plist | 31 ++++ libs/video/renderer/vulkan/vkparse.c | 116 +++++++++++++++ libs/video/renderer/vulkan/vkparse.h | 2 + libs/video/renderer/vulkan/vkparse.plist | 132 ++++++++++++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 21 ++- 6 files changed, 302 insertions(+), 1 deletion(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 5eb2dd157..29cbc8ff1 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -45,6 +45,7 @@ typedef struct vulkan_ctx_s { struct hashlink_s *hashlinks; //FIXME want per thread VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain struct hashtab_s *shadermodules; + struct hashtab_s *setLayouts; struct shadermodule_s *shadermodule_freelist; VkCommandPool cmdpool; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 7af624b99..d619b8406 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -14,6 +14,37 @@ file = $builtin/pushcolor.frag; }, ); + setLayouts = { + something = { + flags = 0; + bindings = ( + { + binding = 0; + descriptorType = sampled_image; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 1; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; + }; + pipelineLayouts = { + something = { + setLayouts = (something); + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "4 * 4"; + }, + ); + }; + }; renderpass = { attachments = ( { diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 21e7bdf72..0931ee755 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -53,6 +53,7 @@ #include "QF/vid.h" #include "QF/simd/vec4f.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/instance.h" @@ -329,6 +330,21 @@ parse_custom (const plfield_t *field, const plitem_t *item, return custom->parse (item, offsets, messages, context); } +static int +parse_RGBA (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context) +{ + int ret = 1; + exprctx_t ectx = *context->ectx; + exprval_t result = { &cexpr_vector, data[0] }; + ectx.symtab = 0; + ectx.result = &result; + const char *valstr = PL_String (item); + Sys_Printf ("parse_RGBA: %s\n", valstr); + ret = !cexpr_eval_string (valstr, &ectx); + Sys_Printf (" "VEC4F_FMT"\n", VEC4_EXP (*(vec4f_t *)data[0])); + return ret; +} static int parse_VkShaderModule (const plitem_t *item, void **data, @@ -344,6 +360,79 @@ parse_VkShaderModule (const plitem_t *item, void **data, } return 0; } + +typedef struct setlayout_s { + char *name; + VkDescriptorSetLayout layout; +} setlayout_t; + +static const char * +setLayout_getkey (const void *sl, void *unused) +{ + return ((setlayout_t *)sl)->name; +} + +static void +setLayout_free (void *sl, void *_ctx) +{ + __auto_type setLayout = (setlayout_t *) sl; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyDescriptorSetLayout (device->dev, setLayout->layout, 0); + free (setLayout->name); + free (setLayout); +} + +static int +parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + __auto_type layout = (setlayout_t *) data; + vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (PL_Type (item) == QFString) { + // accessing a named set layout + const char *name = PL_String (item); + setlayout_t *l = Hash_Find (ctx->setLayouts, name); + if (!l) { + PL_Message (messages, item, "undefined set layout %s", name); + return 0; + } + *layout = *l; + return 1; + } + + VkDescriptorSetLayoutCreateInfo createInfo = {}; + + if (!parse_VkDescriptorSetLayoutCreateInfo (0, item, &createInfo, + messages, context)) { + return 0; + } + layout->name = strdup (field->name); + VkResult res; + res = dfunc->vkCreateDescriptorSetLayout (device->dev, &createInfo, 0, + &layout->layout); + if (res != VK_SUCCESS) { + PL_Message (messages, item, "could not create set layout"); + return 0; + } + return 1; +} + +static plelement_t setLayout_data = { + QFDictionary, + sizeof (setlayout_t), + malloc, + parse_VkDescriptorSetLayout, + 0, +}; + +static plfield_t setLayout_field = { 0, 0, QFDictionary, 0, &setLayout_data }; + static hashtab_t *enum_symtab; #include "libs/video/renderer/vulkan/vkparse.cinc" @@ -440,6 +529,33 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) return renderpass; } +void +QFV_ParseDescriptorSetLayouts (vulkan_ctx_t *ctx, plitem_t *sets) +{ + plitem_t *messages = PL_NewArray (); + exprctx_t exprctx = {}; + parsectx_t parsectx = { &exprctx, ctx }; + + exprctx.memsuper = new_memsuper (); + exprctx.messages = messages; + exprctx.hashlinks = ctx->hashlinks; + + if (!ctx->setLayouts) { + ctx->setLayouts = Hash_NewTable (23, setLayout_getkey, setLayout_free, + ctx, &exprctx.hashlinks); + } + int res = PL_ParseSymtab (&setLayout_field, sets, ctx->setLayouts, + messages, &parsectx); + if (!res || developer->int_val & SYS_VULKAN) { + for (int i = 0; i < PL_A_NumObjects (messages); i++) { + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + } + } + PL_Free (messages); + delete_memsuper (exprctx.memsuper); + ctx->hashlinks = exprctx.hashlinks; +} + static const char * enum_symtab_getkey (const void *e, void *unused) { diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index e34624dab..0f47ac16a 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -12,6 +12,8 @@ typedef struct parsectx_s { struct vulkan_ctx_s *vctx; } parsectx_t; + +void QFV_ParseDescriptorSetLayouts (vulkan_ctx_t *ctx, plitem_t *sets); VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); void QFV_InitParse (void); exprenum_t *QFV_GetEnum (const char *name); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 1ba7e8bb4..95ad4368e 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -5,6 +5,18 @@ VkSubpassDependency, VkSpecializationInfo, VkPipelineShaderStageCreateInfo, + VkPipelineVertexInputStateCreateInfo, + VkPipelineInputAssemblyStateCreateInfo, + VkPipelineViewportStateCreateInfo, + VkPipelineRasterizationStateCreateInfo, + VkPipelineMultisampleStateCreateInfo, + VkPipelineDepthStencilStateCreateInfo, + VkPipelineColorBlendStateCreateInfo, + VkPipelineDynamicStateCreateInfo, + VkDescriptorSetLayoutBinding, + VkDescriptorSetLayoutCreateInfo, + VkPushConstantRange, + VkPipelineLayoutCreateInfo, qfv_swapchain_t, ); parse = { @@ -69,5 +81,125 @@ }; }; VkShaderModuleCreateInfo = skip; + VkDescriptorSetLayoutBinding = { + binding = auto; + descriptorType = auto; + descriptorCount = auto; + stageFlags = auto; + // skip pImmutableSamplers (default to 0) until I know how it works + }; + VkDescriptorSetLayoutCreateInfo = { + flags = auto; + bindings = { + type = (array, VkDescriptorSetLayoutBinding); + size = bindingCount; + values = pBindings; + }; + }; + VkPipelineVertexInputStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + bindings = { + type = (array, VkVertexInputBindingDescription); + size = vertexBindingDescriptionCount; + values = pVertexBindingDescriptions; + }; + attributes = { + type = (array, VkVertexInputAttributeDescription); + size = vertexAttributeDescriptionCount; + values = pVertexAttributeDescriptions; + }; + }; + VkPipelineInputAssemblyStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + topology = auto; + primitiveRestartEnable = auto; + }; + VkPipelineViewportStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + //FIXME redo as one array + viewports = { + type = (array, VkViewport); + size = viewportCount; + values = pViewports; + }; + scissors = { + type = (array, VkRect2D); + size = scissorCount; + values = pScissors; + }; + }; + VkPipelineRasterizationStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + depthClampEnable = auto; + rasterizerDiscardEnable = auto; + polygonMode = auto; + cullMode = auto; + frontFace = auto; + depthBiasEnable = auto; + depthBiasConstantFactor = auto; + depthBiasClamp = auto; + depthBiasSlopeFactor = auto; + lineWidth = auto; + }; + VkPipelineMultisampleStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + rasterizationSamples = auto; + sampleShadingEnable = auto; + minSampleShading = auto; + //pSampleMask = auto; FIXME disabled until correct size is known + alphaToCoverageEnable = auto; + alphaToOneEnable = auto; + }; + VkPipelineDepthStencilStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + depthTestEnable = auto; + depthWriteEnable = auto; + depthCompareOp = auto; + depthBoundsTestEnable = auto; + stencilTestEnable = auto; + front = auto; + back = auto; + minDepthBounds = auto; + maxDepthBounds = auto; + }; + VkPipelineColorBlendStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + logicOpEnable = auto; + logicOp = auto; + attachments = { + type = (array, VkPipelineColorBlendAttachmentState); + size = attachmentCount; + values = pAttachments; + }; + blendConstants = { + type = (custom, QFString, parse_RGBA); + fields = (blendConstants); + }; + }; + VkPipelineDynamicStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + dynamicState = { + type = (array, VkDynamicState); + size = dynamicStateCount; + values = pDynamicStates; + }; + }; + VkPipelineLayoutCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + setLayouts = { + type = (array, { + parse_type = (QFDictionary, QFString); + type = VkDescriptorSetLayout; + parser = parse_VkDescriptorSetLayout; + }); + size = setLayoutCount; + values = pSetLayouts; + }; + pushConstantRanges = { + type = (array, VkPushConstantRange); + size = pushConstantRangeCount; + values = pPushConstantRanges; + }; + } } } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 7647db9ff..f515abd83 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -52,6 +52,7 @@ #include "QF/va.h" #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/instance.h" @@ -401,8 +402,10 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) void Vulkan_CreatePipelines (vulkan_ctx_t *ctx) { - plitem_t *item = qfv_load_pipeline (); + plitem_t *pipeline_def = qfv_load_pipeline (); + plitem_t *item; + item = pipeline_def; if (!item || !(item = PL_ObjectForKey (item, "modules"))) { Sys_Printf ("error loading modules\n"); } else { @@ -424,6 +427,22 @@ Vulkan_CreatePipelines (vulkan_ctx_t *ctx) QFV_RegisterShaderModule (ctx, name, module); } } + + item = pipeline_def; + if (!item || !(item = PL_ObjectForKey (item, "setLayouts"))) { + Sys_Printf ("error loading setLayouts\n"); + } else { + Sys_Printf ("Found setLayouts\n"); + QFV_ParseDescriptorSetLayouts (ctx, item); + } + + /*item = pipeline_def; + if (!item || !(item = PL_ObjectForKey (item, "pipelineLayouts"))) { + Sys_Printf ("error loading pipelineLayouts\n"); + } else { + Sys_Printf ("Found pipelineLayouts\n"); + QFV_ParsePipelineLayouts (ctx, item); + }*/ } void From 7e726545b86e81eb329fe3d853bd0ade0bacef63 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 19:28:27 +0900 Subject: [PATCH 1148/3664] [vulkan] Fix some string retention issues I really need to come up with a better solution for managing strings in quakec. --- libs/video/renderer/vulkan/vkgen/vkfieldcustom.r | 11 +++++++++-- libs/video/renderer/vulkan/vkgen/vkfieldtype.r | 6 ++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r index 3e9e56c74..7c7843414 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r @@ -1,4 +1,5 @@ #include +#include #include "vkfieldcustom.h" #include "vkgen.h" @@ -14,13 +15,19 @@ } PLItem *desc = [item getObjectForKey:"type"]; - pltype = [[desc getObjectAtIndex:1] string]; - parser = [[desc getObjectAtIndex:2] string]; + pltype = str_hold ([[desc getObjectAtIndex:1] string]); + parser = str_hold ([[desc getObjectAtIndex:2] string]); fields = [item getObjectForKey:"fields"]; return self; } +-(void)dealloc +{ + str_free (pltype); + str_free (parser); +} + -writeParseData { fprintf (output_file, "static size_t parse_%s_%s_offsets[] = {\n", diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r index e3d7cf59d..cb1a04508 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r @@ -14,6 +14,7 @@ -(void)dealloc { + str_free (type); str_free (parser); str_free (parse_type); } @@ -42,12 +43,13 @@ parseItemType (PLItem *item) type = [item string]; if (type) { Type *field_type = [[Type lookup:type] dereference]; + type = str_hold (type); parse_type = [field_type parseType]; parser = str_hold ("parse_" + type); } else { parse_type = parseItemType([item getObjectForKey:"parse_type"]); - type = [[item getObjectForKey:"type"] string]; - parser = [[item getObjectForKey:"parser"] string]; + type = str_hold ([[item getObjectForKey:"type"] string]); + parser = str_hold ([[item getObjectForKey:"parser"] string]); } return self; From 1b8b7c04cbe1259af47106a87c22c3e1daf56acd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 23:42:10 +0900 Subject: [PATCH 1149/3664] [gamecode] Disconnect held strings from return slot Fixes an internal string error when a return string has been freed. --- libs/gamecode/pr_strings.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index e8e1dff85..7efd2265c 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -344,7 +344,7 @@ get_string (progs_t *pr, string_t num) case str_free: break; } - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); } else { if (num >= pr->pr_stringsize) return 0; @@ -469,17 +469,17 @@ PR_SetReturnString (progs_t *pr, const char *s) requeue_strref (res, sr); } else if ((sr->type == str_return && !sr->rs_slot) || (sr->type != str_return && sr->rs_slot)) { - PR_Error (pr, "internal string error: %d %d %p", __LINE__, + PR_Error (pr, "internal string error: line:%d %d %p", __LINE__, sr->type, sr->rs_slot); } return string_index (res, sr); } // grab the string ref from the oldest slot, or make a new one if the - // slot is empty or the string has been held - if ((sr = res->rs_slot->strref) && sr->type != str_dynamic) { + // slot is empty + if ((sr = res->rs_slot->strref)) { if (sr->type != str_return || sr->rs_slot != res->rs_slot) { - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); } pr_strfree (pr, sr->s.string); } else { @@ -629,7 +629,10 @@ PR_HoldString (progs_t *pr, string_t str) if (sr) { switch (sr->type) { case str_temp: + break; case str_return: + sr->rs_slot->strref = 0; + sr->rs_slot = 0; break; case str_static: case str_mutable: @@ -637,7 +640,7 @@ PR_HoldString (progs_t *pr, string_t str) // non-ephemeral string, no-op return; default: - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); } sr->type = str_dynamic; return; @@ -666,7 +669,7 @@ PR_FreeString (progs_t *pr, string_t str) pr_strfree (pr, sr->s.string); break; default: - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); } free_string_ref (res, sr); return; @@ -690,7 +693,7 @@ PR_FreeTempStrings (progs_t *pr) continue; } if (sr->type != str_temp) - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); if (R_STRING (pr) < 0 && string_index (res, sr) == R_STRING (pr) && pr->pr_depth) { // It looks like the temp string is being returned. While this From ec7d974dc104668bb02e4380f9ddafe095614f9f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 00:07:58 +0900 Subject: [PATCH 1150/3664] [gamecode] Move % handling to the flags state % is effectively a format flag that cancels the format and outputs a % single %. Fixes % not getting output for %%. --- libs/gamecode/pr_strings.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 7efd2265c..7cb295284 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -868,6 +868,7 @@ fmt_append_item (fmt_state_t *state) * \dot * digraph PR_Sprintf_fmt_state_machine { * format -> flags [label="{%}"]; + * flogs -> format [label="{%}"]; * flags -> flags [label="{#+0 -}"]; * flags -> var_field_width [label="{*}"]; * flags -> precision [label="{.}"]; @@ -906,6 +907,17 @@ fmt_state_flags (fmt_state_t *state) state->c++; // skip over % while (1) { switch (*state->c) { + case '%': + state->c++; + (*state->fi)->flags = 0; + (*state->fi)->precision = 1; + (*state->fi)->minFieldWidth = 0; + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = "%"; + + fmt_append_item (state); + state->state = fmt_state_format; + return; case '0': (*state->fi)->flags |= FMT_ZEROPAD; break; @@ -1111,15 +1123,6 @@ fmt_state_conversion (fmt_state_t *state) (*state->fi)->data.string_var = "'"; state->fmt_count++; - fmt_append_item (state); - break; - case '%': - (*state->fi)->flags = 0; - (*state->fi)->precision = 0; - (*state->fi)->minFieldWidth = 0; - (*state->fi)->type = 's'; - (*state->fi)->data.string_var = "%"; - fmt_append_item (state); break; case 'x': From 9039c6975a461d44f6f1719aa1646eaae6fe4f29 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 08:35:53 +0900 Subject: [PATCH 1151/3664] [util] Clean up some missed vsqrt changes --- include/QF/simd/vec4d.h | 2 +- include/QF/simd/vec4f.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 1b8adbdfc..e73873bc0 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -244,7 +244,7 @@ qrotd (vec4d_t a, vec4d_t b) vec4d_t mb = vsqrtd (dotd (b, b)); vec4d_t den = 2 * ma * mb; vec4d_t t = mb * a + ma * b; - vec4d_t mba_mab = _mm256_sqrt_pd (dotd (t, t)); + vec4d_t mba_mab = vsqrtd (dotd (t, t)); vec4d_t q = crossd (a, b) / mba_mab; q[3] = (mba_mab / den)[0]; return q; diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index f3ea3b22f..85eb252eb 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -232,7 +232,7 @@ qrotf (vec4f_t a, vec4f_t b) vec4f_t mb = vsqrtf (dotf (b, b)); vec4f_t den = 2 * ma * mb; vec4f_t t = mb * a + ma * b; - vec4f_t mba_mab = _mm_sqrt_ps (dotf (t, t)); + vec4f_t mba_mab = vsqrtf (dotf (t, t)); vec4f_t q = crossf (a, b) / mba_mab; q[3] = (mba_mab / den)[0]; return q; From d8261ade9e1350fc713800e311892e6a01240b73 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 08:38:35 +0900 Subject: [PATCH 1152/3664] [vulkan] Generate code for vulkan handles The handles can be created in place or in resource blocks and referred to by name (resource block code gen next). --- include/vid_vulkan.h | 2 + .../video/renderer/vulkan/vkgen/Makemodule.am | 1 + libs/video/renderer/vulkan/vkgen/vkenum.r | 3 +- libs/video/renderer/vulkan/vkgen/vkgen.r | 18 +++ libs/video/renderer/vulkan/vkgen/vkhandle.h | 8 ++ libs/video/renderer/vulkan/vkgen/vkhandle.r | 56 ++++++++++ libs/video/renderer/vulkan/vkparse.c | 81 +++++--------- libs/video/renderer/vulkan/vkparse.plist | 105 ++++++++++++++++++ 8 files changed, 221 insertions(+), 53 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkhandle.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkhandle.r diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 29cbc8ff1..d35c0139d 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -46,6 +46,8 @@ typedef struct vulkan_ctx_s { VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain struct hashtab_s *shadermodules; struct hashtab_s *setLayouts; + struct hashtab_s *pipelineLayouts; + struct hashtab_s *renderPasses; struct shadermodule_s *shadermodule_freelist; VkCommandPool cmdpool; diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index b60e97f1d..21c2ae97e 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -13,6 +13,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkfieldstring.r \ libs/video/renderer/vulkan/vkgen/vkfieldtype.r \ libs/video/renderer/vulkan/vkgen/vkgen.r \ + libs/video/renderer/vulkan/vkgen/vkhandle.r \ libs/video/renderer/vulkan/vkgen/vkstruct.r \ libs/video/renderer/vulkan/vkgen/vktype.r \ libs/video/renderer/vulkan/vkgen/vulkan.r diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 22342cb1c..537916800 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -115,7 +115,7 @@ skip_value(string name) fprintf (output_file, "static exprtab_t %s_symtab = {\n", [self name]); fprintf (output_file, "\t%s_symbols,\n", [self name]); fprintf (output_file, "};\n"); - fprintf (output_file, "exprenum_t %s_enum = {\n", [self name]); + fprintf (output_file, "static exprenum_t %s_enum = {\n", [self name]); fprintf (output_file, "\t&%s_type,\n", [self name]); fprintf (output_file, "\t&%s_symtab,\n", [self name]); fprintf (output_file, "};\n"); @@ -138,7 +138,6 @@ skip_value(string name) " const plitem_t *item, void *data, plitem_t *messages," " void *context);\n", [self name]); - fprintf (header_file, "extern exprenum_t %s_enum;\n", [self name]); } -(void) writeSymtabInit diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index d47873ad2..3d4837744 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -10,6 +10,7 @@ #include "vkgen.h" #include "vkstruct.h" #include "vkenum.h" +#include "vkhandle.h" static AutoreleasePool *autorelease_pool; static void @@ -148,6 +149,7 @@ main(int argc, string *argv) QFile plist_file; PLItem *plist; PLItem *search; + PLItem *handles; arp_start (); @@ -171,6 +173,7 @@ main(int argc, string *argv) printf ("%s not a dictionary\n", plist_filename); } search = [[plist getObjectForKey: "search"] retain]; + handles = [[plist getObjectForKey: "handles"] retain]; parse = [[plist getObjectForKey: "parse"] retain]; encodings = PR_FindGlobal (".type_encodings"); @@ -195,6 +198,17 @@ main(int argc, string *argv) } } + PLItem *handle_keys = [handles allKeys]; + for (int i = [handle_keys count]; i-- > 0; ) { + string search_name = [[handle_keys getObjectAtIndex:i] string]; + id obj = (id) Hash_Find (available_types, search_name); + obj = [obj resolveType]; + printf("handle: %d %s\n", obj, class_get_class_name([obj class])); + if (obj && [obj class] == [Struct class]) { + [obj addToQueue]; + } + } + while ([queue count]) { id obj = [queue objectAtIndex:0]; [queue removeObjectAtIndex:0]; @@ -241,6 +255,10 @@ main(int argc, string *argv) [obj writeTable]; arp_end (); } + for (int i = [handle_keys count]; i-- > 0; ) { + string key = [[handle_keys getObjectAtIndex:i] string]; + output_handle (key, [handles getObjectForKey: key]); + } fprintf (output_file, "static void\n"); fprintf (output_file, "vkgen_init_symtabs (exprctx_t *context)\n"); fprintf (output_file, "{\n"); diff --git a/libs/video/renderer/vulkan/vkgen/vkhandle.h b/libs/video/renderer/vulkan/vkgen/vkhandle.h new file mode 100644 index 000000000..47a68798b --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkhandle.h @@ -0,0 +1,8 @@ +#ifndef __renderer_vulkan_vkgen_vkhandle_h +#define __renderer_vulkan_vkgen_vkhandle_h + +@class PLItem; + +void output_handle (string name, PLItem *handle); + +#endif//__renderer_vulkan_vkgen_vkhandle_h diff --git a/libs/video/renderer/vulkan/vkgen/vkhandle.r b/libs/video/renderer/vulkan/vkgen/vkhandle.r new file mode 100644 index 000000000..d6e9a7f52 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkhandle.r @@ -0,0 +1,56 @@ +#include +#include + +#include "vkgen.h" +#include "vkhandle.h" + +void +output_handle (string name, PLItem *handle) +{ + string symtab = str_hold ([[handle getObjectForKey:"symtab"] string]); + string class = str_hold ([[handle getObjectForKey:"class"] string]); + string create = str_hold ([[handle getObjectForKey:"create"] string]); + fprintf (output_file, "static int parse_%s (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name); + fprintf (output_file, "{\n"); + fprintf (output_file, "\t__auto_type handle = (%s *) data;\n", name); + fprintf (output_file, "\tvulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;\n"); + fprintf (output_file, "\tqfv_device_t *device = ctx->device;\n"); + fprintf (output_file, "\tqfv_devfuncs_t *dfunc = device->funcs;\n"); + fprintf (output_file, "\tif (PL_Type (item) == QFString) {\n"); + fprintf (output_file, "\t\tconst char *name = PL_String (item);\n"); + fprintf (output_file, "\t\thandleref_t *hr = Hash_Find (ctx->%s, name);\n", symtab); + fprintf (output_file, "\t\tif (!hr) {\n"); + fprintf (output_file, "\t\t\tPL_Message (messages, item, \"undefined %s %%s\", name);\n", class); + fprintf (output_file, "\t\t\treturn 0;\n"); + fprintf (output_file, "\t\t}\n"); + fprintf (output_file, "\t\t*handle = (%s) hr->handle;\n", name); + fprintf (output_file, "\t\treturn 1;\n"); + fprintf (output_file, "\t}\n"); + + fprintf (output_file, "\t%sCreateInfo createInfo = {};\n", name); + + fprintf (output_file, "\tif (!parse_%sCreateInfo (0, item, &createInfo, messages, context)) {\n", name); + fprintf (output_file, "\t\treturn 0;\n"); + fprintf (output_file, "\t}\n"); + fprintf (output_file, "\tVkResult res;\n"); + fprintf (output_file, "\tres = dfunc->%s (device->dev, &createInfo, 0, handle);\n", create); + fprintf (output_file, "\tif (res != VK_SUCCESS) {\n"); + fprintf (output_file, "\t\tPL_Message (messages, item, \"could not create %s\");\n", class); + fprintf (output_file, "\t\treturn 0;\n"); + fprintf (output_file, "\t}\n"); + fprintf (output_file, "\treturn 1;\n"); + fprintf (output_file, "}\n"); + + fprintf (output_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name); + fprintf (output_file, "{\n"); + fprintf (output_file, "\thandleref_t *handleref = data;\n"); + fprintf (output_file, "\thandleref->name = strdup (field->name);\n"); + fprintf (output_file, "\treturn parse_%s (field, item, &handleref->handle, messages, context);\n", name); + fprintf (output_file, "}\n"); + + fprintf (header_file, "static int parse_%s (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name); + fprintf (header_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name); + str_free (symtab); + str_free (class); + str_free (create); +} diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 0931ee755..af22a1dc0 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -361,82 +361,61 @@ parse_VkShaderModule (const plitem_t *item, void **data, return 0; } -typedef struct setlayout_s { +typedef struct handleref_s { char *name; - VkDescriptorSetLayout layout; -} setlayout_t; + uint64_t handle; +} handleref_t; static const char * -setLayout_getkey (const void *sl, void *unused) +handleref_getkey (const void *hr, void *unused) { - return ((setlayout_t *)sl)->name; + return ((handleref_t *)hr)->name; } static void -setLayout_free (void *sl, void *_ctx) +handleref_free (void *hr, void *_ctx) { - __auto_type setLayout = (setlayout_t *) sl; + __auto_type handleref = (handleref_t *) hr; + free (handleref->name); + free (handleref); +} + +static void +setLayout_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type layout = (VkDescriptorSetLayout) handleref->handle; __auto_type ctx = (vulkan_ctx_t *) _ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkDestroyDescriptorSetLayout (device->dev, setLayout->layout, 0); - free (setLayout->name); - free (setLayout); + dfunc->vkDestroyDescriptorSetLayout (device->dev, layout, 0); + handleref_free (handleref, ctx); } +static hashtab_t *enum_symtab; + static int -parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) +parse_BasePipeline (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context) { - __auto_type layout = (setlayout_t *) data; - vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - if (PL_Type (item) == QFString) { - // accessing a named set layout - const char *name = PL_String (item); - setlayout_t *l = Hash_Find (ctx->setLayouts, name); - if (!l) { - PL_Message (messages, item, "undefined set layout %s", name); - return 0; - } - *layout = *l; - return 1; - } - - VkDescriptorSetLayoutCreateInfo createInfo = {}; - - if (!parse_VkDescriptorSetLayoutCreateInfo (0, item, &createInfo, - messages, context)) { - return 0; - } - layout->name = strdup (field->name); - VkResult res; - res = dfunc->vkCreateDescriptorSetLayout (device->dev, &createInfo, 0, - &layout->layout); - if (res != VK_SUCCESS) { - PL_Message (messages, item, "could not create set layout"); - return 0; - } - return 1; + *(VkPipeline *) data = 0; + PL_Message (messages, item, "not implemented"); + return 0; } +#include "libs/video/renderer/vulkan/vkparse.cinc" + static plelement_t setLayout_data = { QFDictionary, - sizeof (setlayout_t), + sizeof (handleref_t), malloc, - parse_VkDescriptorSetLayout, + parse_VkDescriptorSetLayout_handleref, 0, }; static plfield_t setLayout_field = { 0, 0, QFDictionary, 0, &setLayout_data }; -static hashtab_t *enum_symtab; - -#include "libs/video/renderer/vulkan/vkparse.cinc" - typedef struct qfv_renderpass_s { qfv_attachmentdescription_t *attachments; qfv_subpassparametersset_t *subpasses; @@ -541,7 +520,7 @@ QFV_ParseDescriptorSetLayouts (vulkan_ctx_t *ctx, plitem_t *sets) exprctx.hashlinks = ctx->hashlinks; if (!ctx->setLayouts) { - ctx->setLayouts = Hash_NewTable (23, setLayout_getkey, setLayout_free, + ctx->setLayouts = Hash_NewTable (23, handleref_getkey, setLayout_free, ctx, &exprctx.hashlinks); } int res = PL_ParseSymtab (&setLayout_field, sets, ctx->setLayouts, diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 95ad4368e..c816b32c4 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -17,8 +17,26 @@ VkDescriptorSetLayoutCreateInfo, VkPushConstantRange, VkPipelineLayoutCreateInfo, + VkGraphicsPipelineCreateInfo, qfv_swapchain_t, ); + handles = { + VkDescriptorSetLayout = { + symtab = setLayouts; + class = "set layout"; + create = vkCreateDescriptorSetLayout; + }; + VkRenderPass = { + symtab = renderPasses; + class = "render pass"; + create = vkCreateRenderPass; + }; + VkPipelineLayout = { + symtab = pipelineLayouts; + class = "pipeline layout"; + create = vkCreatePipelineLayout; + }; + }; parse = { qfv_swapchain_s = { .name = qfv_swapchain_t; @@ -52,6 +70,24 @@ values = pPreserveAttachments; }; }; + VkRenderPassCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + attachments = { + type = (array, VkAttachmentDescription); + size = attachmentCount; + values = pAttachments; + }; + subpasses = { + type = (array, VkSubpassDescription); + size = subpassCount; + values = pSubpasses; + }; + dependencies = { + type = (array, VkSubpassDependency); + size = dependencyCount; + values = pDependencies; + }; + }; VkSpecializationInfo = { mapEntries = { type = (array, VkSpecializationMapEntry); @@ -200,6 +236,75 @@ size = pushConstantRangeCount; values = pPushConstantRanges; }; + }; + VkPipelineTessellationStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + patchControlPoints = auto; + }; + VkGraphicsPipelineCreateInfo = { + flags = auto; + stages = { + type = (array, VkPipelineShaderStageCreateInfo); + size = stageCount; + values = pStages; + }; + vertexInput = { + type = (single, VkPipelineVertexInputStateCreateInfo); + value = pVertexInputState; + }; + inputAssembly = { + type = (single, VkPipelineInputAssemblyStateCreateInfo); + value = pInputAssemblyState; + }; + tessellation = { + type = (single, VkPipelineTessellationStateCreateInfo); + value = pTessellationState; + }; + viewport = { + type = (single, VkPipelineViewportStateCreateInfo); + value = pViewportState; + }; + rasterization = { + type = (single, VkPipelineRasterizationStateCreateInfo); + value = pRasterizationState; + }; + multisample = { + type = (single, VkPipelineMultisampleStateCreateInfo); + value = pMultisampleState; + }; + depthStencil = { + type = (single, VkPipelineDepthStencilStateCreateInfo); + value = pDepthStencilState; + }; + colorBlend = { + type = (single, VkPipelineColorBlendStateCreateInfo); + value = pColorBlendState; + }; + dynamic = { + type = (single, VkPipelineDynamicStateCreateInfo); + value = pDynamicState; + }; + layout = { + type = (single, { + parse_type = (QFDictionary, QFString); + type = VkPipelineLayout; + parser = parse_VkPipelineLayout; + }); + value = layout; + }; + renderPass = { + type = (single, { + parse_type = (QFDictionary, QFString); + type = VkRenderPass; + parser = parse_VkRenderPass; + }); + value = renderPass; + }; + basePipelineHandle = { + type = (custom, QFString, parse_BasePipeline); + fields = (basePipelineHandle); + }; + basePipelineIndex = auto; } } } From e5708100bbf8b65a9578c472a2be68d36c1b4e99 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 14:15:35 +0900 Subject: [PATCH 1153/3664] [vulkan] Generate code for resource nodes This makes it easy to add resource nodes defining contextually named resources. It is already used for shaders, set layouts, and pipeline layouts. --- include/QF/Vulkan/shader.h | 5 - include/vid_vulkan.h | 3 +- libs/video/renderer/vulkan/qfpipeline.plist | 22 ++-- libs/video/renderer/vulkan/shader.c | 71 +---------- .../video/renderer/vulkan/vkgen/Makemodule.am | 1 + libs/video/renderer/vulkan/vkgen/vkgen.r | 16 +++ libs/video/renderer/vulkan/vkgen/vkhandle.r | 66 +++++----- libs/video/renderer/vulkan/vkgen/vkresource.h | 9 ++ libs/video/renderer/vulkan/vkgen/vkresource.r | 44 +++++++ libs/video/renderer/vulkan/vkparse.c | 118 ++++++++++++++---- libs/video/renderer/vulkan/vkparse.h | 12 +- libs/video/renderer/vulkan/vkparse.plist | 36 +++++- .../video/renderer/vulkan/vulkan_vid_common.c | 40 +----- 13 files changed, 257 insertions(+), 186 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkresource.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkresource.r diff --git a/include/QF/Vulkan/shader.h b/include/QF/Vulkan/shader.h index 41b38a862..f44189978 100644 --- a/include/QF/Vulkan/shader.h +++ b/include/QF/Vulkan/shader.h @@ -10,10 +10,5 @@ VkShaderModule QFV_CreateShaderModule (struct qfv_device_s *device, const char *path); void QFV_DestroyShaderModule (struct qfv_device_s *device, VkShaderModule module); -VkShaderModule QFV_FindShaderModule (struct vulkan_ctx_s *ctx, - const char *name); -void QFV_RegisterShaderModule (struct vulkan_ctx_s *ctx, const char *name, - VkShaderModule module); -void QFV_DeregisterShaderModule (struct vulkan_ctx_s *ctx, const char *name); #endif//__QF_Vulkan_shader_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index d35c0139d..1741165ee 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -44,11 +44,10 @@ typedef struct vulkan_ctx_s { VkSampleCountFlagBits msaaSamples; // FIXME not here? struct hashlink_s *hashlinks; //FIXME want per thread VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain - struct hashtab_s *shadermodules; + struct hashtab_s *shaderModules; struct hashtab_s *setLayouts; struct hashtab_s *pipelineLayouts; struct hashtab_s *renderPasses; - struct shadermodule_s *shadermodule_freelist; VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index d619b8406..ed74f689a 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -1,19 +1,13 @@ { - modules = ( + shaderModules = { // specify shader modules to load into memory - { - // the name of the module for referecy by the pipeline - name = passthrough; - // the path to the spv file to load - // $shader refers to the shader install path - // $builtin refers to compiled-in shaders - file = $builtin/passthrough.vert; - }, - { - name = pushcolor; - file = $builtin/pushcolor.frag; - }, - ); + // key is the name of the module for referecy by the pipeline + // value the path to the spv file to load + // $shader refers to the shader install path + // $builtin refers to compiled-in shaders + passthrough = $builtin/passthrough.vert; + pushcolor = $builtin/pushcolor.frag; + }; setLayouts = { something = { flags = 0; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index e55833782..f0064bb35 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -65,14 +65,6 @@ typedef struct shaderdata_s { size_t size; } shaderdata_t; -typedef struct shadermodule_s { - char *name; - union { - VkShaderModule module; - struct shadermodule_s *next; - }; -} shadermodule_t; - static shaderdata_t builtin_shaders[] = { { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, @@ -122,6 +114,9 @@ QFV_CreateShaderModule (qfv_device_t *device, const char *shader_path) } if (data) { + Sys_MaskPrintf (SYS_VULKAN, + "QFV_CreateShaderModule: creating shader module %s\n", + shader_path); VkShaderModuleCreateInfo createInfo = { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, 0, 0, data->size, data->data @@ -151,63 +146,3 @@ QFV_DestroyShaderModule (qfv_device_t *device, VkShaderModule module) dfunc->vkDestroyShaderModule (dev, module, 0); } - -static shadermodule_t * -new_module (vulkan_ctx_t *ctx) -{ - shadermodule_t *shadermodule; - ALLOC (128, shadermodule_t, ctx->shadermodule, shadermodule); - return shadermodule; -} - -static void -del_module (shadermodule_t *shadermodule, vulkan_ctx_t *ctx) -{ - free (shadermodule->name); - FREE (ctx->shadermodule, shadermodule); -} - -static const char * -sm_getkey (const void *sm, void *unused) -{ - return ((shadermodule_t *) sm)->name; -} - -static void -sm_free (void *sm, void *ctx) -{ - del_module (sm, ctx); -} - -VkShaderModule -QFV_FindShaderModule (vulkan_ctx_t *ctx, const char *name) -{ - //FIXME - if (!ctx->shadermodules) { - ctx->shadermodules = Hash_NewTable (127, sm_getkey, sm_free, ctx, 0); - } - return Hash_Find (ctx->shadermodules, name); -} - -void -QFV_RegisterShaderModule (vulkan_ctx_t *ctx, const char *name, - VkShaderModule module) -{ - //FIXME - if (!ctx->shadermodules) { - ctx->shadermodules = Hash_NewTable (127, sm_getkey, sm_free, ctx, 0); - } - shadermodule_t *shadermodule = new_module (ctx); - shadermodule->name = strdup (name); - shadermodule->module = module; - Hash_Add (ctx->shadermodules, shadermodule); -} - -void -QFV_DeregisterShaderModule (vulkan_ctx_t *ctx, const char *name) -{ - if (!ctx->shadermodules) { - return; - } - Hash_Free (ctx->shadermodules, Hash_Del (ctx->shadermodules, name)); -} diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 21c2ae97e..2fba61b0b 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -14,6 +14,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkfieldtype.r \ libs/video/renderer/vulkan/vkgen/vkgen.r \ libs/video/renderer/vulkan/vkgen/vkhandle.r \ + libs/video/renderer/vulkan/vkgen/vkresource.r \ libs/video/renderer/vulkan/vkgen/vkstruct.r \ libs/video/renderer/vulkan/vkgen/vktype.r \ libs/video/renderer/vulkan/vkgen/vulkan.r diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 3d4837744..4636df52f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -11,6 +11,7 @@ #include "vkstruct.h" #include "vkenum.h" #include "vkhandle.h" +#include "vkresource.h" static AutoreleasePool *autorelease_pool; static void @@ -150,6 +151,7 @@ main(int argc, string *argv) PLItem *plist; PLItem *search; PLItem *handles; + PLItem *resources; arp_start (); @@ -174,6 +176,7 @@ main(int argc, string *argv) } search = [[plist getObjectForKey: "search"] retain]; handles = [[plist getObjectForKey: "handles"] retain]; + resources = [[plist getObjectForKey: "resources"] retain]; parse = [[plist getObjectForKey: "parse"] retain]; encodings = PR_FindGlobal (".type_encodings"); @@ -259,6 +262,19 @@ main(int argc, string *argv) string key = [[handle_keys getObjectAtIndex:i] string]; output_handle (key, [handles getObjectForKey: key]); } + for (int i = [resources count]; i-- > 0; ) { + PLItem *res = [resources getObjectAtIndex:i]; + output_resource_data (res); + } + // keep the order intuitive (since it matters) + fprintf (output_file, "static parseres_t parse_resources[] = {\n"); + for (int i = 0; i < [resources count]; i++) { + PLItem *res = [resources getObjectAtIndex:i]; + output_resource_entry (res); + } + fprintf (output_file, "\t{}\n"); + fprintf (output_file, "};\n"); + fprintf (output_file, "static void\n"); fprintf (output_file, "vkgen_init_symtabs (exprctx_t *context)\n"); fprintf (output_file, "{\n"); diff --git a/libs/video/renderer/vulkan/vkgen/vkhandle.r b/libs/video/renderer/vulkan/vkgen/vkhandle.r index d6e9a7f52..da4a4fbcc 100644 --- a/libs/video/renderer/vulkan/vkgen/vkhandle.r +++ b/libs/video/renderer/vulkan/vkgen/vkhandle.r @@ -10,46 +10,54 @@ output_handle (string name, PLItem *handle) string symtab = str_hold ([[handle getObjectForKey:"symtab"] string]); string class = str_hold ([[handle getObjectForKey:"class"] string]); string create = str_hold ([[handle getObjectForKey:"create"] string]); - fprintf (output_file, "static int parse_%s (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name); - fprintf (output_file, "{\n"); - fprintf (output_file, "\t__auto_type handle = (%s *) data;\n", name); - fprintf (output_file, "\tvulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;\n"); - fprintf (output_file, "\tqfv_device_t *device = ctx->device;\n"); - fprintf (output_file, "\tqfv_devfuncs_t *dfunc = device->funcs;\n"); - fprintf (output_file, "\tif (PL_Type (item) == QFString) {\n"); - fprintf (output_file, "\t\tconst char *name = PL_String (item);\n"); - fprintf (output_file, "\t\thandleref_t *hr = Hash_Find (ctx->%s, name);\n", symtab); - fprintf (output_file, "\t\tif (!hr) {\n"); - fprintf (output_file, "\t\t\tPL_Message (messages, item, \"undefined %s %%s\", name);\n", class); - fprintf (output_file, "\t\t\treturn 0;\n"); - fprintf (output_file, "\t\t}\n"); - fprintf (output_file, "\t\t*handle = (%s) hr->handle;\n", name); - fprintf (output_file, "\t\treturn 1;\n"); - fprintf (output_file, "\t}\n"); + string custom = str_hold ([[handle getObjectForKey:"custom"] string]); + if (!custom) { + fprintf (output_file, "static int parse_%s (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name); + fprintf (output_file, "{\n"); + fprintf (output_file, "\t__auto_type handle = (%s *) data;\n", name); + fprintf (output_file, "\tvulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;\n"); + fprintf (output_file, "\tqfv_device_t *device = ctx->device;\n"); + fprintf (output_file, "\tqfv_devfuncs_t *dfunc = device->funcs;\n"); + fprintf (output_file, "\tif (PL_Type (item) == QFString) {\n"); + fprintf (output_file, "\t\tconst char *name = PL_String (item);\n"); + fprintf (output_file, "\t\thandleref_t *hr = Hash_Find (ctx->%s, name);\n", symtab); + fprintf (output_file, "\t\tif (!hr) {\n"); + fprintf (output_file, "\t\t\tPL_Message (messages, item, \"undefined %s %%s\", name);\n", class); + fprintf (output_file, "\t\t\treturn 0;\n"); + fprintf (output_file, "\t\t}\n"); + fprintf (output_file, "\t\t*handle = (%s) hr->handle;\n", name); + fprintf (output_file, "\t\treturn 1;\n"); + fprintf (output_file, "\t}\n"); - fprintf (output_file, "\t%sCreateInfo createInfo = {};\n", name); + fprintf (output_file, "\t%sCreateInfo createInfo = {};\n", name); - fprintf (output_file, "\tif (!parse_%sCreateInfo (0, item, &createInfo, messages, context)) {\n", name); - fprintf (output_file, "\t\treturn 0;\n"); - fprintf (output_file, "\t}\n"); - fprintf (output_file, "\tVkResult res;\n"); - fprintf (output_file, "\tres = dfunc->%s (device->dev, &createInfo, 0, handle);\n", create); - fprintf (output_file, "\tif (res != VK_SUCCESS) {\n"); - fprintf (output_file, "\t\tPL_Message (messages, item, \"could not create %s\");\n", class); - fprintf (output_file, "\t\treturn 0;\n"); - fprintf (output_file, "\t}\n"); - fprintf (output_file, "\treturn 1;\n"); - fprintf (output_file, "}\n"); + fprintf (output_file, "\tif (!parse_%sCreateInfo (0, item, &createInfo, messages, context)) {\n", name); + fprintf (output_file, "\t\treturn 0;\n"); + fprintf (output_file, "\t}\n"); + fprintf (output_file, "\tVkResult res;\n"); + fprintf (output_file, "\tres = dfunc->%s (device->dev, &createInfo, 0, handle);\n", create); + fprintf (output_file, "\tif (res != VK_SUCCESS) {\n"); + fprintf (output_file, "\t\tPL_Message (messages, item, \"could not create %s\");\n", class); + fprintf (output_file, "\t\treturn 0;\n"); + fprintf (output_file, "\t}\n"); + fprintf (output_file, "\treturn 1;\n"); + fprintf (output_file, "}\n"); + } fprintf (output_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name); fprintf (output_file, "{\n"); fprintf (output_file, "\thandleref_t *handleref = data;\n"); fprintf (output_file, "\thandleref->name = strdup (field->name);\n"); - fprintf (output_file, "\treturn parse_%s (field, item, &handleref->handle, messages, context);\n", name); + if (custom) { + fprintf (output_file, "\treturn %s (field, item, &handleref->handle, messages, context);\n", custom); + } else { + fprintf (output_file, "\treturn parse_%s (field, item, &handleref->handle, messages, context);\n", name); + } fprintf (output_file, "}\n"); fprintf (header_file, "static int parse_%s (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name); fprintf (header_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name); + str_free (custom); str_free (symtab); str_free (class); str_free (create); diff --git a/libs/video/renderer/vulkan/vkgen/vkresource.h b/libs/video/renderer/vulkan/vkgen/vkresource.h new file mode 100644 index 000000000..e72042c3e --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkresource.h @@ -0,0 +1,9 @@ +#ifndef __renderer_vulkan_vkgen_vkresource_h +#define __renderer_vulkan_vkgen_vkresource_h + +@class PLItem; + +void output_resource_data (PLItem *resource); +void output_resource_entry (PLItem *resource); + +#endif//__renderer_vulkan_vkgen_vkresource_h diff --git a/libs/video/renderer/vulkan/vkgen/vkresource.r b/libs/video/renderer/vulkan/vkgen/vkresource.r new file mode 100644 index 000000000..47478d9f8 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkresource.r @@ -0,0 +1,44 @@ +#include +#include + +#include "vkgen.h" +#include "vkresource.h" + +void +output_resource_data (PLItem *resource) +{ + string name = str_hold ([[resource getObjectForKey:"name"] string]); + string parse_type = str_hold ([[resource getObjectForKey:"parse_type"] string]); + string parser = str_hold ([[resource getObjectForKey:"parser"] string]); + string type = str_hold ([[resource getObjectForKey:"type"] string]); + + fprintf (output_file, "static plelement_t resource_%s_data = {\n", name); + fprintf (output_file, "\t%s,\n", parse_type); + fprintf (output_file, "\tsizeof (%s),\n", type); + fprintf (output_file, "\tmalloc,\n"); + fprintf (output_file, "\t%s,\n", parser); + fprintf (output_file, "\t0,\n"); + fprintf (output_file, "};\n"); + + fprintf (output_file, "static plfield_t resource_%s_field = {\n", name); + fprintf (output_file, "\t0, 0, %s, 0, &resource_%s_data\n", + parse_type, name); + fprintf (output_file, "};\n"); + + str_free (name); + str_free (parse_type); + str_free (parser); + str_free (type); +} + +void +output_resource_entry (PLItem *resource) +{ + string name = str_hold ([[resource getObjectForKey:"name"] string]); + string table = str_hold ([[resource getObjectForKey:"table"] string]); + fprintf (output_file, + "\t{\"%s\", &resource_%s_field, field_offset (vulkan_ctx_t, %s) },\n", + name, name, table); + str_free (name); + str_free (table); +} diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index af22a1dc0..418ef707d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -207,6 +207,9 @@ parse_enum (const plfield_t *field, const plitem_t *item, // field->name, field->offset, field->type, field->parser, // field->data, valstr); ret = !cexpr_parse_enum (enm, valstr, &ectx, data); + if (!ret) { + PL_Message (messages, item, "error parsing enum: %s", valstr); + } //Sys_Printf (" %d\n", *(int *)data); return ret; } @@ -347,24 +350,37 @@ parse_RGBA (const plitem_t *item, void **data, } static int -parse_VkShaderModule (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *context) +parse_VkShaderModule (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages, void *context) { - vulkan_ctx_t *ctx = context->vctx; + __auto_type handle = (VkShaderModule *) data; + vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; + const char *name = PL_String (item); - __auto_type mptr = (VkShaderModule *)data[0]; - VkShaderModule module = QFV_FindShaderModule (ctx, name); - if (module) { - *mptr = module; - return 1; + handleref_t *hr = Hash_Find (ctx->shaderModules, name); + if (!hr) { + PL_Message (messages, item, "undefined shader module %s", name); + return 0; } - return 0; + *handle = (VkShaderModule) hr->handle; + return 1; } -typedef struct handleref_s { - char *name; - uint64_t handle; -} handleref_t; +static int +parse_VkShaderModule_resource (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + __auto_type handle = (VkShaderModule *) data; + vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; + qfv_device_t *device = ctx->device; + + const char *shader_path = PL_String (item); + if (!(*handle = QFV_CreateShaderModule (device, shader_path))) { + PL_Message (messages, item, "could not find shader %s", shader_path); + return 0; + } + return 1; +} static const char * handleref_getkey (const void *hr, void *unused) @@ -393,6 +409,45 @@ setLayout_free (void *hr, void *_ctx) handleref_free (handleref, ctx); } +static void +shaderModule_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type module = (VkShaderModule) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyShaderModule (device->dev, module, 0); + handleref_free (handleref, ctx); +} + +static void +pipelineLayout_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type layout = (VkPipelineLayout) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyPipelineLayout (device->dev, layout, 0); + handleref_free (handleref, ctx); +} + +static void +renderPass_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type renderPass = (VkRenderPass) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyRenderPass (device->dev, renderPass, 0); + handleref_free (handleref, ctx); +} + static hashtab_t *enum_symtab; static int @@ -406,16 +461,6 @@ parse_BasePipeline (const plitem_t *item, void **data, #include "libs/video/renderer/vulkan/vkparse.cinc" -static plelement_t setLayout_data = { - QFDictionary, - sizeof (handleref_t), - malloc, - parse_VkDescriptorSetLayout_handleref, - 0, -}; - -static plfield_t setLayout_field = { 0, 0, QFDictionary, 0, &setLayout_data }; - typedef struct qfv_renderpass_s { qfv_attachmentdescription_t *attachments; qfv_subpassparametersset_t *subpasses; @@ -509,27 +554,46 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) } void -QFV_ParseDescriptorSetLayouts (vulkan_ctx_t *ctx, plitem_t *sets) +QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) { plitem_t *messages = PL_NewArray (); exprctx_t exprctx = {}; parsectx_t parsectx = { &exprctx, ctx }; + int ret = 1; exprctx.memsuper = new_memsuper (); exprctx.messages = messages; exprctx.hashlinks = ctx->hashlinks; if (!ctx->setLayouts) { + ctx->shaderModules = Hash_NewTable (23, handleref_getkey, + shaderModule_free, + ctx, &exprctx.hashlinks); ctx->setLayouts = Hash_NewTable (23, handleref_getkey, setLayout_free, ctx, &exprctx.hashlinks); + ctx->pipelineLayouts = Hash_NewTable (23, handleref_getkey, + pipelineLayout_free, + ctx, &exprctx.hashlinks); + ctx->renderPasses = Hash_NewTable (23, handleref_getkey, + renderPass_free, + ctx, &exprctx.hashlinks); } - int res = PL_ParseSymtab (&setLayout_field, sets, ctx->setLayouts, - messages, &parsectx); - if (!res || developer->int_val & SYS_VULKAN) { + + for (parseres_t *res = parse_resources; res->name; res++) { + plitem_t *item = PL_ObjectForKey (pipelinedef, res->name); + if (item) { + __auto_type table = *(hashtab_t **) ((size_t) ctx + res->offset); + Sys_Printf ("found %s\n", res->name); + ret &= PL_ParseSymtab (res->field, item, table, messages, + &parsectx); + } + } + if (!ret || developer->int_val & SYS_VULKAN) { for (int i = 0; i < PL_A_NumObjects (messages); i++) { Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } } + PL_Free (messages); delete_memsuper (exprctx.memsuper); ctx->hashlinks = exprctx.hashlinks; diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 0f47ac16a..e63bb44e2 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -12,9 +12,19 @@ typedef struct parsectx_s { struct vulkan_ctx_s *vctx; } parsectx_t; +typedef struct parseres_s { + const char *name; + plfield_t *field; + size_t offset; +} parseres_t; + +typedef struct handleref_s { + char *name; + uint64_t handle; +} handleref_t; -void QFV_ParseDescriptorSetLayouts (vulkan_ctx_t *ctx, plitem_t *sets); VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); +void QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *plist); void QFV_InitParse (void); exprenum_t *QFV_GetEnum (const char *name); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index c816b32c4..844b471f9 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -21,6 +21,11 @@ qfv_swapchain_t, ); handles = { + VkShaderModule = { + symtab = shaderModules; + class = "shader module"; + custom = parse_VkShaderModule_resource; + }; VkDescriptorSetLayout = { symtab = setLayouts; class = "set layout"; @@ -37,6 +42,29 @@ create = vkCreatePipelineLayout; }; }; + resources = ( + { + name = shaderModules; + parse_type = QFString; + parser = parse_VkShaderModule_handleref; + type = handleref_t; + table = shaderModules; + }, + { + name = setLayouts; + parse_type = QFDictionary; + parser = parse_VkDescriptorSetLayout_handleref; + type = handleref_t; + table = setLayouts; + }, + { + name = pipelineLayouts; + parse_type = QFDictionary; + parser = parse_VkPipelineLayout_handleref; + type = handleref_t; + table = pipelineLayouts; + }, + ); parse = { qfv_swapchain_s = { .name = qfv_swapchain_t; @@ -108,8 +136,12 @@ string = pName; }; module = { - type = (custom, QFString, parse_VkShaderModule); - fields = (module); + type = (single, { + parse_type = QFString; + type = VkShaderModule; + parser = parse_VkShaderModule; + }); + value = module; }; specializationInfo = { type = (single, VkSpecializationInfo); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index f515abd83..12c9a463b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -403,46 +403,10 @@ void Vulkan_CreatePipelines (vulkan_ctx_t *ctx) { plitem_t *pipeline_def = qfv_load_pipeline (); - plitem_t *item; - item = pipeline_def; - if (!item || !(item = PL_ObjectForKey (item, "modules"))) { - Sys_Printf ("error loading modules\n"); - } else { - Sys_Printf ("Found modules def\n"); + if (pipeline_def) { + QFV_ParseResources (ctx, pipeline_def); } - for (int i = PL_A_NumObjects (item); i-- > 0; ) { - plitem_t *mod = PL_ObjectAtIndex (item, i); - const char *name = PL_String (PL_ObjectForKey (mod, "name")); - const char *file = PL_String (PL_ObjectForKey (mod, "file")); - if (!name || !file) { - continue; - } - if (QFV_FindShaderModule (ctx, name)) { - continue; - } - VkShaderModule module = QFV_CreateShaderModule (ctx->device, file); - if (module) { - Sys_Printf ("registering shader %s %p\n", name, module); - QFV_RegisterShaderModule (ctx, name, module); - } - } - - item = pipeline_def; - if (!item || !(item = PL_ObjectForKey (item, "setLayouts"))) { - Sys_Printf ("error loading setLayouts\n"); - } else { - Sys_Printf ("Found setLayouts\n"); - QFV_ParseDescriptorSetLayouts (ctx, item); - } - - /*item = pipeline_def; - if (!item || !(item = PL_ObjectForKey (item, "pipelineLayouts"))) { - Sys_Printf ("error loading pipelineLayouts\n"); - } else { - Sys_Printf ("Found pipelineLayouts\n"); - QFV_ParsePipelineLayouts (ctx, item); - }*/ } void From 518befdaed3a8aad617baeca7b633cc3c493aa6b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 17:40:07 +0900 Subject: [PATCH 1154/3664] [util] FIx an "only" in a comment --- include/QF/hash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/hash.h b/include/QF/hash.h index fde2eed97..f96682fd9 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -46,7 +46,7 @@ typedef struct hashlink_s hashlink_t; inserting or finding the element. First parameter is a pointer to the element from which to extract the key, the second is the user data pointer. - \param f a function to free the element. Only ever called from + \param f a function to free the element. Called from only Hash_FlushTable and Hash_DelTable. The first parameter is the element to be freed and the second is the user data pointer. \param ud user data pointer. set to whatever you want, it will be passed From 7c661e7cc51d51839e7c6e7451c93800831c7485 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 17:43:26 +0900 Subject: [PATCH 1155/3664] [vulkan] Remove renderpass from generated code The creation of a render pass seems to need special handling. --- include/vid_vulkan.h | 2 +- libs/video/renderer/vulkan/qfpipeline.plist | 77 ++++++++++++++++++++- libs/video/renderer/vulkan/vkparse.c | 16 ----- libs/video/renderer/vulkan/vkparse.plist | 15 +--- 4 files changed, 78 insertions(+), 32 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 1741165ee..74a1ef51a 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -44,10 +44,10 @@ typedef struct vulkan_ctx_s { VkSampleCountFlagBits msaaSamples; // FIXME not here? struct hashlink_s *hashlinks; //FIXME want per thread VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain + struct plitem_s *pipelineDef; struct hashtab_s *shaderModules; struct hashtab_s *setLayouts; struct hashtab_s *pipelineLayouts; - struct hashtab_s *renderPasses; VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index ed74f689a..198604466 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -39,6 +39,81 @@ ); }; }; + pipelines = { + something = { + stages = ( + { stage = vertex; name = main; module = passthrough; }, + { stage = fragment; name = main; module = pushcolor; }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "4 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + ); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = 0; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1000; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = 1; + rasterizerDiscardEnable = 0; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = 0; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = 0; + minSampleShading = 0.5; + alphaToCoverageEnable = 0; + alphaToOneEnable = 0; + }; + depthStencil = { + depthTestEnable = 1; + depthWriteEnable = 1; + depthCompareOp = less; + depthBoundsTestEnable = 0; + stencilTestEnable = 0; + }; + colorBlend = { + logicOpEnable = 0; + }; + dymamic = { + dymamicState = ( viewport, scissor ); + }; + layout = something; + renderPass = renderpass; + }; + }; renderpass = { attachments = ( { @@ -108,5 +183,5 @@ dependencyFlags = 0; } ); - } + }; } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 418ef707d..08ab9acfb 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -435,19 +435,6 @@ pipelineLayout_free (void *hr, void *_ctx) handleref_free (handleref, ctx); } -static void -renderPass_free (void *hr, void *_ctx) -{ - __auto_type handleref = (handleref_t *) hr; - __auto_type renderPass = (VkRenderPass) handleref->handle; - __auto_type ctx = (vulkan_ctx_t *) _ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - dfunc->vkDestroyRenderPass (device->dev, renderPass, 0); - handleref_free (handleref, ctx); -} - static hashtab_t *enum_symtab; static int @@ -574,9 +561,6 @@ QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) ctx->pipelineLayouts = Hash_NewTable (23, handleref_getkey, pipelineLayout_free, ctx, &exprctx.hashlinks); - ctx->renderPasses = Hash_NewTable (23, handleref_getkey, - renderPass_free, - ctx, &exprctx.hashlinks); } for (parseres_t *res = parse_resources; res->name; res++) { diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 844b471f9..e270fb9be 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -31,11 +31,6 @@ class = "set layout"; create = vkCreateDescriptorSetLayout; }; - VkRenderPass = { - symtab = renderPasses; - class = "render pass"; - create = vkCreateRenderPass; - }; VkPipelineLayout = { symtab = pipelineLayouts; class = "pipeline layout"; @@ -129,7 +124,7 @@ }; }; VkPipelineShaderStageCreateInfo = { - flags = auto; + //flags = auto; reserved for future use (Bits enum does not exist) stage = auto; name = { type = string; @@ -324,14 +319,6 @@ }); value = layout; }; - renderPass = { - type = (single, { - parse_type = (QFDictionary, QFString); - type = VkRenderPass; - parser = parse_VkRenderPass; - }); - value = renderPass; - }; basePipelineHandle = { type = (custom, QFString, parse_BasePipeline); fields = (basePipelineHandle); From d22be09ae339ed7628283fccbed0f0c690b8a053 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 17:45:02 +0900 Subject: [PATCH 1156/3664] [vulkan] Clean up pipeline def loading --- .../video/renderer/vulkan/vulkan_vid_common.c | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 12c9a463b..486e078e4 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -260,22 +260,23 @@ static qfv_pipelinestagepair_t imageLayoutTransitionStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }, }; -static plitem_t * -qfv_load_pipeline (void) +static void +qfv_load_pipeline (vulkan_ctx_t *ctx) { - static plitem_t *pipeline; - - if (!pipeline) { - pipeline = PL_GetPropertyList (quakeforge_pipeline); + if (!ctx->pipelineDef) { + ctx->pipelineDef = PL_GetPropertyList (quakeforge_pipeline); + if (ctx->pipelineDef) { + QFV_ParseResources (ctx, ctx->pipelineDef); + } } - return pipeline; } void Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) { - plitem_t *item = qfv_load_pipeline (); + qfv_load_pipeline (ctx); + plitem_t *item = ctx->pipelineDef; if (!item || !(item = PL_ObjectForKey (item, "renderpass"))) { Sys_Printf ("error loading renderpass\n"); } else { @@ -402,11 +403,6 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) void Vulkan_CreatePipelines (vulkan_ctx_t *ctx) { - plitem_t *pipeline_def = qfv_load_pipeline (); - - if (pipeline_def) { - QFV_ParseResources (ctx, pipeline_def); - } } void From dc704a9384a23ecdc5f327eb161507dcf3825e52 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 17:46:03 +0900 Subject: [PATCH 1157/3664] [vulkan] Update the validation layer request It's now Kronos as LunarG has been deprecated (explains why I got no help with some of my debugging). --- libs/video/renderer/vulkan/instance.c | 2 +- libs/video/renderer/vulkan/vulkan_vid_common.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index b228df2fe..617d792e8 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -59,7 +59,7 @@ static VkExtensionProperties *instanceExtensionProperties; static strset_t *instanceExtensions; const char * const vulkanValidationLayers[] = { - "VK_LAYER_LUNARG_standard_validation", + "VK_LAYER_KHRONOS_validation", 0, }; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 486e078e4..23d5ca4cc 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -112,8 +112,8 @@ Vulkan_Init_Cvars (void) { vulkan_use_validation = Cvar_Get ("vulkan_use_validation", "1", CVAR_NONE, 0, - "enable LunarG Standard Validation " - "Layer if available (requires instance " + "enable KRONOS Validation Layer if " + "available (requires instance " "restart)."); // FIXME implement fallback choices (instead of just fifo) vulkan_presentation_mode = Cvar_Get ("vulkan_presentation_mode", "mailbox", From 3cf8a336a81f627c21573deaa2a232b1c1b7fe29 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 17:48:00 +0900 Subject: [PATCH 1158/3664] [vulkan] Clear out the resource tables on shutdown This would take care of undestroyed resources if there wasn't a problem with invalid memory use. Not sure what's going on just yet. --- libs/video/renderer/vulkan/vkparse.c | 12 +++++++++--- libs/video/renderer/vulkan/vulkan_vid_common.c | 13 +++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 08ab9acfb..55192ad36 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -405,7 +405,9 @@ setLayout_free (void *hr, void *_ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkDestroyDescriptorSetLayout (device->dev, layout, 0); + if (layout) { + dfunc->vkDestroyDescriptorSetLayout (device->dev, layout, 0); + } handleref_free (handleref, ctx); } @@ -418,7 +420,9 @@ shaderModule_free (void *hr, void *_ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkDestroyShaderModule (device->dev, module, 0); + if (module) { + dfunc->vkDestroyShaderModule (device->dev, module, 0); + } handleref_free (handleref, ctx); } @@ -431,7 +435,9 @@ pipelineLayout_free (void *hr, void *_ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkDestroyPipelineLayout (device->dev, layout, 0); + if (layout) { + dfunc->vkDestroyPipelineLayout (device->dev, layout, 0); + }; handleref_free (handleref, ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 23d5ca4cc..fc0a97edf 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -43,6 +43,7 @@ #include "QF/cmem.h" #include "QF/cvar.h" #include "QF/dstring.h" +#include "QF/hash.h" #include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" @@ -144,6 +145,15 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version } +static void +clear_table (hashtab_t **table) +{ + if (*table) { + Hash_DelTable (*table); + *table = 0; + } +} + void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { @@ -156,6 +166,9 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } + clear_table (&ctx->pipelineLayouts); + clear_table (&ctx->setLayouts); + clear_table (&ctx->shaderModules); ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, ctx->surface, 0); if (ctx->device) { From 37b6d11c01d5a7aba766d28bd9185918c81be7dc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 18:24:18 +0900 Subject: [PATCH 1159/3664] [ruamoko] Add binding for str_upper I can't believe I didn't do that when I did str_lower. --- libs/ruamoko/rua_string.c | 17 +++++++++++++++++ ruamoko/include/string.h | 1 + ruamoko/lib/string.r | 1 + 3 files changed, 19 insertions(+) diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 31b717273..754d1627e 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -265,6 +265,22 @@ bi_str_lower (progs_t *pr) RETURN_STRING (pr, lower); } +static void +bi_str_upper (progs_t *pr) +{ + const char *str = P_GSTRING (pr, 0); + char *upper = alloca (strlen (str) + 1); + char *l = upper; + byte c; + + while ((c = *str++)) { + *l++ = toupper (c); + } + *l++ = 0; + + RETURN_STRING (pr, upper); +} + static builtin_t builtins[] = { {"strlen", bi_strlen, -1}, {"sprintf", bi_sprintf, -1}, @@ -283,6 +299,7 @@ static builtin_t builtins[] = { {"str_char", bi_str_char, -1}, {"str_quote", bi_str_quote, -1}, {"str_lower", bi_str_lower, -1}, + {"str_upper", bi_str_upper, -1}, {0} }; diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index 8087ef67e..3d978cfd5 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -18,5 +18,6 @@ int str_str (string haystack, string needle); @extern int str_char (string str, int ind); string str_quote (string str); string str_lower (string str); +string str_upper (string str); #endif//__ruamoko_string_h diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index 3858ef7d6..5169296a0 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -17,3 +17,4 @@ int str_str (string haystack, string needle) = #0; int str_char (string str, int ind) = #0; string str_quote (string str) = #0; string str_lower (string str) = #0; +string str_upper (string str) = #0; From d8b389d2b61cc58870e0e94d9bf088d46080a049 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 18:26:01 +0900 Subject: [PATCH 1160/3664] [vulkan] Initialize sType in parsed structures This fixes a lot of validation issues, but still some fun with uninitialized memory and bad accesses. --- libs/video/renderer/vulkan/vkgen/vkstruct.r | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 6d5c2cfc2..108af71ef 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -47,11 +47,31 @@ return nil; } +-(string)sTypeName +{ + string s = "VK_STRUCTURE_TYPE"; + string name = str_hold ([self outname]); + int length = strlen (name); + int start, end, c; + for (start = 2; start < length; start = end) { + for (end = start + 1; end < length; end++) { + c = str_char (name, end); + if (c >= 'A' && c <= 'Z') { + break; + } + } + s += "_" + str_mid (name, start, end); + } + str_free (name); + return str_upper (s); +} + -(void) writeTable { PLItem *field_dict = [parse getObjectForKey:[self name]]; PLItem *new_name = [field_dict getObjectForKey:".name"]; Array *field_defs = [Array array]; + int have_sType = 0; if ([parse string] == "skip") { return; @@ -60,6 +80,12 @@ outname = str_hold ([new_name string]); } + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *field = &type.strct.fields[i]; + if (field.name == "sType") { + have_sType = 1; + } + } if (field_dict) { PLItem *field_keys = [field_dict allKeys]; @@ -108,6 +134,10 @@ " void *context)\n", [self outname]); fprintf (output_file, "{\n"); + if (have_sType) { + fprintf (output_file, "\t((%s *) data)->sType", [self outname]); + fprintf (output_file, " = %s;\n", [self sTypeName]); + } fprintf (output_file, "\treturn PL_ParseStruct (%s_fields, item, data, messages," " context);\n", From a45f8f98b6e001dd068c1c42c8d714c128437061 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 19:55:17 +0900 Subject: [PATCH 1161/3664] [util] Make exprctx hashlinks double pointer The way I wound up using the field meant that exprctx should not "own" the hashlinks chain, but rather just point to it. This fixes the nasty access errors I had. --- include/QF/cexpr.h | 2 +- libs/util/cexpr-vars.c | 2 +- libs/video/renderer/vulkan/vkparse.c | 17 ++++++++--------- libs/video/renderer/vulkan/vkparse.h | 2 +- libs/video/renderer/vulkan/vulkan_vid_common.c | 9 +++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 77e5b0463..ac6eef683 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -94,7 +94,7 @@ typedef struct exprctx_s { struct memsuper_s *memsuper; const struct plitem_s *item; struct plitem_s *messages; - struct hashlink_s *hashlinks; + struct hashlink_s **hashlinks; int errors; } exprctx_t; diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c index 6ec8ce3d9..115f0ba64 100644 --- a/libs/util/cexpr-vars.c +++ b/libs/util/cexpr-vars.c @@ -128,7 +128,7 @@ void cexpr_init_symtab (exprtab_t *symtab, exprctx_t *ctx) { exprsym_t *sym; - symtab->tab = Hash_NewTable (61, expr_getkey, 0, 0, &ctx->hashlinks); + symtab->tab = Hash_NewTable (61, expr_getkey, 0, 0, ctx->hashlinks); for (sym = symtab->symbols; sym->name; sym++) { Hash_Add (symtab->tab, sym); } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 55192ad36..394a402d9 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -513,7 +513,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) exprctx.external_variables = &vars_tab; exprctx.memsuper = new_memsuper (); exprctx.messages = messages; - exprctx.hashlinks = ctx->hashlinks; + exprctx.hashlinks = &ctx->hashlinks; cexpr_init_symtab (&vars_tab, &exprctx); @@ -526,7 +526,6 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) } PL_Free (messages); delete_memsuper (exprctx.memsuper); - ctx->hashlinks = exprctx.hashlinks; renderpass = QFV_CreateRenderPass (device, renderpass_data.attachments, @@ -556,17 +555,17 @@ QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) exprctx.memsuper = new_memsuper (); exprctx.messages = messages; - exprctx.hashlinks = ctx->hashlinks; + exprctx.hashlinks = &ctx->hashlinks; if (!ctx->setLayouts) { ctx->shaderModules = Hash_NewTable (23, handleref_getkey, shaderModule_free, - ctx, &exprctx.hashlinks); + ctx, &ctx->hashlinks); ctx->setLayouts = Hash_NewTable (23, handleref_getkey, setLayout_free, - ctx, &exprctx.hashlinks); + ctx, &ctx->hashlinks); ctx->pipelineLayouts = Hash_NewTable (23, handleref_getkey, pipelineLayout_free, - ctx, &exprctx.hashlinks); + ctx, &ctx->hashlinks); } for (parseres_t *res = parse_resources; res->name; res++) { @@ -586,7 +585,6 @@ QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) PL_Free (messages); delete_memsuper (exprctx.memsuper); - ctx->hashlinks = exprctx.hashlinks; } static const char * @@ -597,11 +595,12 @@ enum_symtab_getkey (const void *e, void *unused) } void -QFV_InitParse (void) +QFV_InitParse (vulkan_ctx_t *ctx) { exprctx_t context = {}; enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, - &context.hashlinks); + &ctx->hashlinks); + context.hashlinks = &ctx->hashlinks; vkgen_init_symtabs (&context); } diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index e63bb44e2..e4fe36774 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -25,7 +25,7 @@ typedef struct handleref_s { VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); void QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *plist); -void QFV_InitParse (void); +void QFV_InitParse (vulkan_ctx_t *ctx); exprenum_t *QFV_GetEnum (const char *name); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index fc0a97edf..af24c78eb 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -140,7 +140,7 @@ void Vulkan_Init_Common (vulkan_ctx_t *ctx) { Sys_Printf ("Vulkan_Init_Common\n"); - QFV_InitParse (); + QFV_InitParse (ctx); Vulkan_Init_Cvars (); ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version } @@ -149,8 +149,9 @@ static void clear_table (hashtab_t **table) { if (*table) { - Hash_DelTable (*table); + hashtab_t *tab = *table; *table = 0; + Hash_DelTable (tab); } } @@ -166,11 +167,11 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } + ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, + ctx->surface, 0); clear_table (&ctx->pipelineLayouts); clear_table (&ctx->setLayouts); clear_table (&ctx->shaderModules); - ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, - ctx->surface, 0); if (ctx->device) { QFV_DestroyDevice (ctx->device); } From b493e6ac324c7414f2fc8a902565f7da88214d7a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 23:39:52 +0900 Subject: [PATCH 1162/3664] [util] Expose plist type check support functions --- include/QF/qfplist.h | 5 +++++ libs/util/qfplist.c | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 20c7671bb..3f22a9e16 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -310,6 +310,11 @@ plitem_t *PL_NewString (const char *str); */ void PL_Free (plitem_t *item); +int PL_CheckType (pltype_t field_type, pltype_t item_type); +void PL_TypeMismatch (plitem_t *messages, const plitem_t *item, + const char *name, pltype_t field_type, + pltype_t item_type); + /** Parse a dictionary object into a structure. For each key in the dictionary, the corresponding field item is used to diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index c3fc5a756..273148657 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1147,8 +1147,8 @@ pl_default_parser (const plfield_t *field, const plitem_t *item, void *data, return 0; } -static int -types_match (pltype_t field_type, pltype_t item_type) +VISIBLE int +PL_CheckType (pltype_t field_type, pltype_t item_type) { if (field_type & QFMultiType) { // field_type is a mask of allowed types @@ -1159,9 +1159,9 @@ types_match (pltype_t field_type, pltype_t item_type) } } -static void -type_mismatch (plitem_t *messages, const plitem_t *item, const char *name, - pltype_t field_type, pltype_t item_type) +VISIBLE void +PL_TypeMismatch (plitem_t *messages, const plitem_t *item, const char *name, + pltype_t field_type, pltype_t item_type) { const int num_types = sizeof (pl_types) / sizeof (pl_types[0]); if (field_type & QFMultiType) { @@ -1213,9 +1213,9 @@ PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, void *data, } else { parser = pl_default_parser; } - if (!types_match (f->type, item->type)) { - type_mismatch (messages, item, current->key, - f->type, item->type); + if (!PL_CheckType (f->type, item->type)) { + PL_TypeMismatch (messages, item, current->key, + f->type, item->type); result = 0; } else { if (!parser (f, item, flddata, messages, context)) { @@ -1268,11 +1268,11 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, plitem_t *item = plarray->values[i]; void *eledata = &arr->a[i * element->stride]; - if (!types_match (element->type, item->type)) { + if (!PL_CheckType (element->type, item->type)) { char index[16]; snprintf (index, sizeof(index) - 1, "%d", i); index[15] = 0; - type_mismatch (messages, item, index, element->type, item->type); + PL_TypeMismatch (messages, item, index, element->type, item->type); result = 0; } else { if (!parser (&f, item, eledata, messages, context)) { @@ -1320,8 +1320,8 @@ PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, const char *key = current->key; plitem_t *item = current->value; - if (!types_match (element->type, item->type)) { - type_mismatch (messages, item, key, element->type, item->type); + if (!PL_CheckType (element->type, item->type)) { + PL_TypeMismatch (messages, item, key, element->type, item->type); result = 0; continue; } From 0da99bc59ce90e1a9e59f0325151c037a3e43f43 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 23:41:13 +0900 Subject: [PATCH 1163/3664] [util] Add promotion from float to int to cexpr I won't go the other way nor will I add double to float. --- libs/util/cexpr-type.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 6b02be01d..f400803cb 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -264,6 +264,13 @@ float_div_quat (const exprval_t *val1, const exprval_t *val2, *c = a * qconjf (b) / dotf (b, b); } +static void +float_cast_int (const exprval_t *val1, const exprval_t *src, exprval_t *result, + exprctx_t *ctx) +{ + *(float *) result->value = *(int *) src->value; +} + UNOP(float, pos, float, +) UNOP(float, neg, float, -) UNOP(float, tnot, float, !) @@ -278,6 +285,7 @@ binop_t float_binops[] = { { '/', &cexpr_quaternion, &cexpr_quaternion, float_div_quat }, { '%', &cexpr_float, &cexpr_float, float_rem }, { MOD, &cexpr_float, &cexpr_float, float_mod }, + { '=', &cexpr_int, &cexpr_float, float_cast_int }, {} }; From 5eb1afdcb363c6dd5d47c396bee031bdfc372a33 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 23:42:30 +0900 Subject: [PATCH 1164/3664] [vulkan] Implement pipeline creation The prototypes for handle parsers needed to be changes because it turned out "single" was inappropriate for handles as "single" allocates memory for the parsed object, but handles must be written directly. --- include/vid_vulkan.h | 1 + libs/video/renderer/vulkan/qfpipeline.plist | 152 +++++++------- .../renderer/vulkan/vkgen/vkfieldcustom.r | 3 +- .../video/renderer/vulkan/vkgen/vkfieldtype.h | 2 + .../video/renderer/vulkan/vkgen/vkfieldtype.r | 33 +-- libs/video/renderer/vulkan/vkgen/vkhandle.r | 15 +- libs/video/renderer/vulkan/vkparse.c | 188 ++++++++++++------ libs/video/renderer/vulkan/vkparse.h | 14 +- libs/video/renderer/vulkan/vkparse.plist | 19 +- .../video/renderer/vulkan/vulkan_vid_common.c | 9 + 10 files changed, 256 insertions(+), 180 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 74a1ef51a..d34e067fe 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -53,6 +53,7 @@ typedef struct vulkan_ctx_s { VkCommandBuffer cmdbuffer; VkFence fence; // for ctx->cmdbuffer only vulkan_renderpass_t renderpass; + VkPipeline pipeline; size_t curFrame; vulkan_framebufferset_t framebuffers; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 198604466..1f9c6de46 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -39,80 +39,88 @@ ); }; }; - pipelines = { - something = { - stages = ( - { stage = vertex; name = main; module = passthrough; }, - { stage = fragment; name = main; module = pushcolor; }, + pipeline = { + stages = ( + { stage = vertex; name = main; module = passthrough; }, + { stage = fragment; name = main; module = pushcolor; }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "4 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "4 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 0; - }, - ); - }; - inputAssembly = { - topology = triangle_list; - primitiveRestartEnable = 0; - }; - viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1000; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); - }; - rasterization = { - depthClampEnable = 1; - rasterizerDiscardEnable = 0; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = 0; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = 0; - minSampleShading = 0.5; - alphaToCoverageEnable = 0; - alphaToOneEnable = 0; - }; - depthStencil = { - depthTestEnable = 1; - depthWriteEnable = 1; - depthCompareOp = less; - depthBoundsTestEnable = 0; - stencilTestEnable = 0; - }; - colorBlend = { - logicOpEnable = 0; - }; - dymamic = { - dymamicState = ( viewport, scissor ); - }; - layout = something; - renderPass = renderpass; }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = 0; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = 0; + rasterizerDiscardEnable = 0; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = 0; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = 0; + minSampleShading = 0.5f; + alphaToCoverageEnable = 0; + alphaToOneEnable = 0; + }; + depthStencil = { + depthTestEnable = 1; + depthWriteEnable = 1; + depthCompareOp = less; + depthBoundsTestEnable = 0; + stencilTestEnable = 0; + }; + colorBlend = { + logicOpEnable = 0; + attachments = ({ + blendEnable = 0; + srcColorBlendFactor = src_color; + dstColorBlendFactor = zero; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = zero; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = something; + //renderPass = renderpass; }; renderpass = { attachments = ( diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r index 7c7843414..611cd7a9b 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r @@ -2,6 +2,7 @@ #include #include "vkfieldcustom.h" +#include "vkfieldtype.h" #include "vkgen.h" #include "vktype.h" @@ -15,7 +16,7 @@ } PLItem *desc = [item getObjectForKey:"type"]; - pltype = str_hold ([[desc getObjectAtIndex:1] string]); + pltype = str_hold (parseItemType ([desc getObjectAtIndex:1])); parser = str_hold ([[desc getObjectAtIndex:2] string]); fields = [item getObjectForKey:"fields"]; diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.h b/libs/video/renderer/vulkan/vkgen/vkfieldtype.h index fa27c7d8e..8e5d26bf8 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldtype.h +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.h @@ -17,4 +17,6 @@ -(string)parseType; @end +string parseItemType (PLItem *item); + #endif//__renderer_vulkan_vkgen_vkfieldtype_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r index cb1a04508..5f9429a20 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r @@ -5,6 +5,21 @@ #include "vkgen.h" #include "vktype.h" +string +parseItemType (PLItem *item) +{ + string str = [item string]; + if (str) { + return str; + } + string mask = "QFMultiType"; + for (int i = [item count]; i-- > 0; ) { + str = [[item getObjectAtIndex:i] string]; + mask = mask + " | (1 << " + str + ")"; + } + return mask; +} + @implementation FieldType +fieldType:(PLItem *)item @@ -19,21 +34,6 @@ str_free (parse_type); } -static string -parseItemType (PLItem *item) -{ - string str = [item string]; - if (str) { - return str; - } - string mask = "QFMultiType"; - for (int i = [item count]; i-- > 0; ) { - str = [[item getObjectAtIndex:i] string]; - mask = mask + " | (1 << " + str + ")"; - } - return str_hold (mask); -} - -initWithItem:(PLItem *)item { if (!(self = [super init])) { @@ -47,7 +47,8 @@ parseItemType (PLItem *item) parse_type = [field_type parseType]; parser = str_hold ("parse_" + type); } else { - parse_type = parseItemType([item getObjectForKey:"parse_type"]); + PLItem *typeItem = [item getObjectForKey:"parse_type"]; + parse_type = str_hold (parseItemType(typeItem)); type = str_hold ([[item getObjectForKey:"type"] string]); parser = str_hold ([[item getObjectForKey:"parser"] string]); } diff --git a/libs/video/renderer/vulkan/vkgen/vkhandle.r b/libs/video/renderer/vulkan/vkgen/vkhandle.r index da4a4fbcc..b76d99af4 100644 --- a/libs/video/renderer/vulkan/vkgen/vkhandle.r +++ b/libs/video/renderer/vulkan/vkgen/vkhandle.r @@ -12,10 +12,10 @@ output_handle (string name, PLItem *handle) string create = str_hold ([[handle getObjectForKey:"create"] string]); string custom = str_hold ([[handle getObjectForKey:"custom"] string]); if (!custom) { - fprintf (output_file, "static int parse_%s (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name); + fprintf (output_file, "static int parse_%s (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context)\n", name); fprintf (output_file, "{\n"); - fprintf (output_file, "\t__auto_type handle = (%s *) data;\n", name); - fprintf (output_file, "\tvulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx;\n"); + fprintf (output_file, "\t__auto_type handle = (%s *) data[0];\n", name); + fprintf (output_file, "\tvulkan_ctx_t *ctx = context->vctx;\n"); fprintf (output_file, "\tqfv_device_t *device = ctx->device;\n"); fprintf (output_file, "\tqfv_devfuncs_t *dfunc = device->funcs;\n"); fprintf (output_file, "\tif (PL_Type (item) == QFString) {\n"); @@ -47,15 +47,18 @@ output_handle (string name, PLItem *handle) fprintf (output_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name); fprintf (output_file, "{\n"); fprintf (output_file, "\thandleref_t *handleref = data;\n"); + fprintf (output_file, "\tvoid *hrdata[] = { &handleref->handle };\n"); fprintf (output_file, "\thandleref->name = strdup (field->name);\n"); if (custom) { - fprintf (output_file, "\treturn %s (field, item, &handleref->handle, messages, context);\n", custom); + fprintf (output_file, "\treturn %s (item, hrdata, messages, context);\n", custom); } else { - fprintf (output_file, "\treturn parse_%s (field, item, &handleref->handle, messages, context);\n", name); + fprintf (output_file, "\treturn parse_%s (item, hrdata, messages, context);\n", name); } fprintf (output_file, "}\n"); - fprintf (header_file, "static int parse_%s (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name); + if (!custom) { + fprintf (header_file, "static int parse_%s (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context);\n", name); + } fprintf (header_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name); str_free (custom); str_free (symtab); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 394a402d9..45236c7ff 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -58,6 +58,7 @@ #include "QF/Vulkan/command.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/shader.h" #include "QF/Vulkan/swapchain.h" @@ -159,6 +160,10 @@ parse_basic (const plfield_t *field, const plitem_t *item, *(uint32_t *) data = VK_SUBPASS_EXTERNAL; } else { ret = !cexpr_eval_string (valstr, &ectx); + if (!ret) { + PL_Message (messages, item, "error parsing %s: %s", + field->name, valstr); + } } //Sys_Printf (" %x\n", *(uint32_t *)data); @@ -224,8 +229,9 @@ parse_single (const plfield_t *field, const plitem_t *item, //Sys_Printf ("parse_single: %s %zd %d %p %p\n", field->name, field->offset, // field->type, field->parser, field->data); - if (PL_Type (item) != single->type) { - PL_Message (messages, item, "error: wrong type"); + if (!PL_CheckType (single->type, PL_Type (item))) { + PL_TypeMismatch (messages, item, field->name, single->type, + PL_Type (item)); return 0; } @@ -309,13 +315,13 @@ parse_string (const plfield_t *field, const plitem_t *item, __auto_type string = (parse_string_t *) field->data; __auto_type value = (char **) ((byte *)data + string->value_offset); - const char *str = PL_BinaryData (item); + const char *str = PL_String (item); - Sys_Printf ("parse_string: %s %zd %d %p %p %p\n", - field->name, field->offset, field->type, field->parser, - field->data, data); - Sys_Printf (" %zd\n", string->value_offset); - Sys_Printf (" %s\n", str); + //Sys_Printf ("parse_string: %s %zd %d %p %p %p\n", + // field->name, field->offset, field->type, field->parser, + // field->data, data); + //Sys_Printf (" %zd\n", string->value_offset); + //Sys_Printf (" %s\n", str); *value = strdup (str); return 1; @@ -350,11 +356,11 @@ parse_RGBA (const plitem_t *item, void **data, } static int -parse_VkShaderModule (const plfield_t *field, const plitem_t *item, void *data, - plitem_t *messages, void *context) +parse_VkShaderModule (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context) { - __auto_type handle = (VkShaderModule *) data; - vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; + __auto_type handle = (VkShaderModule *) data[0]; + vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); handleref_t *hr = Hash_Find (ctx->shaderModules, name); @@ -367,10 +373,10 @@ parse_VkShaderModule (const plfield_t *field, const plitem_t *item, void *data, } static int -parse_VkShaderModule_resource (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) +parse_VkShaderModule_resource (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context) { - __auto_type handle = (VkShaderModule *) data; + __auto_type handle = (VkShaderModule *) data[0]; vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; qfv_device_t *device = ctx->device; @@ -382,6 +388,15 @@ parse_VkShaderModule_resource (const plfield_t *field, const plitem_t *item, return 1; } +static int +parse_VkDescriptorSetLayout_array (const plfield_t *field, + const plitem_t *item, void *data, + plitem_t *messages, void *context) +{ + void *layout[] = { data }; + return parse_VkDescriptorSetLayout (item, layout, messages, context); +} + static const char * handleref_getkey (const void *hr, void *unused) { @@ -494,57 +509,6 @@ static plfield_t renderpass_fields[] = { {} }; -VkRenderPass -QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) -{ - qfv_device_t *device = ctx->device; - qfv_renderpass_t renderpass_data = {}; - plitem_t *messages = PL_NewArray (); - VkRenderPass renderpass; - exprsym_t var_syms[] = { - {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, - {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {} - }; - exprtab_t vars_tab = { var_syms, 0 }; - exprctx_t exprctx = {}; - parsectx_t parsectx = { &exprctx, ctx }; - - exprctx.external_variables = &vars_tab; - exprctx.memsuper = new_memsuper (); - exprctx.messages = messages; - exprctx.hashlinks = &ctx->hashlinks; - - cexpr_init_symtab (&vars_tab, &exprctx); - - if (!PL_ParseStruct (renderpass_fields, plist, &renderpass_data, - messages, &parsectx)) { - for (int i = 0; i < PL_A_NumObjects (messages); i++) { - Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); - } - return 0; - } - PL_Free (messages); - delete_memsuper (exprctx.memsuper); - - renderpass = QFV_CreateRenderPass (device, - renderpass_data.attachments, - renderpass_data.subpasses, - renderpass_data.dependencies); - - free (renderpass_data.attachments); - for (size_t i = 0; i < renderpass_data.subpasses->size; i++) { - free ((void *) renderpass_data.subpasses->a[i].pInputAttachments); - free ((void *) renderpass_data.subpasses->a[i].pColorAttachments); - free ((void *) renderpass_data.subpasses->a[i].pResolveAttachments); - free ((void *) renderpass_data.subpasses->a[i].pDepthStencilAttachment); - free ((void *) renderpass_data.subpasses->a[i].pPreserveAttachments); - } - free (renderpass_data.subpasses); - free (renderpass_data.dependencies); - return renderpass; -} - void QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) { @@ -609,3 +573,95 @@ QFV_GetEnum (const char *name) { return Hash_Find (enum_symtab, name); } + +VkRenderPass +QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) +{ + qfv_device_t *device = ctx->device; + qfv_renderpass_t renderpass_data = {}; + plitem_t *messages = PL_NewArray (); + VkRenderPass renderpass; + exprsym_t var_syms[] = { + {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, + {} + }; + exprtab_t vars_tab = { var_syms, 0 }; + exprctx_t exprctx = {}; + parsectx_t parsectx = { &exprctx, ctx }; + + exprctx.external_variables = &vars_tab; + exprctx.memsuper = new_memsuper (); + exprctx.messages = messages; + exprctx.hashlinks = &ctx->hashlinks; + + cexpr_init_symtab (&vars_tab, &exprctx); + + if (!PL_ParseStruct (renderpass_fields, plist, &renderpass_data, + messages, &parsectx)) { + for (int i = 0; i < PL_A_NumObjects (messages); i++) { + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + } + return 0; + } + PL_Free (messages); + delete_memsuper (exprctx.memsuper); + + renderpass = QFV_CreateRenderPass (device, + renderpass_data.attachments, + renderpass_data.subpasses, + renderpass_data.dependencies); + + free (renderpass_data.attachments); + for (size_t i = 0; i < renderpass_data.subpasses->size; i++) { + free ((void *) renderpass_data.subpasses->a[i].pInputAttachments); + free ((void *) renderpass_data.subpasses->a[i].pColorAttachments); + free ((void *) renderpass_data.subpasses->a[i].pResolveAttachments); + free ((void *) renderpass_data.subpasses->a[i].pDepthStencilAttachment); + free ((void *) renderpass_data.subpasses->a[i].pPreserveAttachments); + } + free (renderpass_data.subpasses); + free (renderpass_data.dependencies); + return renderpass; +} + +VkPipeline +QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) +{ + qfv_device_t *device = ctx->device; + + plitem_t *messages = PL_NewArray (); + exprctx_t exprctx = {}; + parsectx_t parsectx = { &exprctx, ctx }; + exprsym_t var_syms[] = { + {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, + {} + }; + exprtab_t vars_tab = { var_syms, 0 }; + + exprctx.external_variables = &vars_tab; + exprctx.memsuper = new_memsuper (); + exprctx.messages = messages; + exprctx.hashlinks = &ctx->hashlinks; + + cexpr_init_symtab (&vars_tab, &exprctx); + + __auto_type cInfo = QFV_AllocGraphicsPipelineCreateInfoSet (1, alloca); + memset (&cInfo->a[0], 0, sizeof (cInfo->a[0])); + + if (!parse_VkGraphicsPipelineCreateInfo (0, plist, &cInfo->a[0], + messages, &parsectx)) { + for (int i = 0; i < PL_A_NumObjects (messages); i++) { + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + } + return 0; + } + PL_Free (messages); + delete_memsuper (exprctx.memsuper); + + cInfo->a[0].renderPass = ctx->renderpass.renderpass; + __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); + VkPipeline pipeline = plSet->a[0]; + free (plSet); + return pipeline; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index e4fe36774..394cd296d 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -1,17 +1,17 @@ #ifndef __vkparse_h #define __vkparse_h +typedef struct parsectx_s { + struct exprctx_s *ectx; + struct vulkan_ctx_s *vctx; +} parsectx_t; + #include "QF/cexpr.h" #include "QF/Vulkan/renderpass.h" #ifdef vkparse_internal #include "libs/video/renderer/vulkan/vkparse.hinc" #endif -typedef struct parsectx_s { - struct exprctx_s *ectx; - struct vulkan_ctx_s *vctx; -} parsectx_t; - typedef struct parseres_s { const char *name; plfield_t *field; @@ -23,9 +23,11 @@ typedef struct handleref_s { uint64_t handle; } handleref_t; -VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); void QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *plist); void QFV_InitParse (vulkan_ctx_t *ctx); exprenum_t *QFV_GetEnum (const char *name); +VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); +VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist); + #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index e270fb9be..97e767676 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -131,12 +131,8 @@ string = pName; }; module = { - type = (single, { - parse_type = QFString; - type = VkShaderModule; - parser = parse_VkShaderModule; - }); - value = module; + type = (custom, QFString, parse_VkShaderModule); + fields = (module); }; specializationInfo = { type = (single, VkSpecializationInfo); @@ -253,7 +249,7 @@ type = (array, { parse_type = (QFDictionary, QFString); type = VkDescriptorSetLayout; - parser = parse_VkDescriptorSetLayout; + parser = parse_VkDescriptorSetLayout_array; }); size = setLayoutCount; values = pSetLayouts; @@ -312,12 +308,9 @@ value = pDynamicState; }; layout = { - type = (single, { - parse_type = (QFDictionary, QFString); - type = VkPipelineLayout; - parser = parse_VkPipelineLayout; - }); - value = layout; + type = (custom, (QFDictionary, QFString), + parse_VkPipelineLayout); + fields = (layout); }; basePipelineHandle = { type = (custom, QFString, parse_BasePipeline); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index af24c78eb..179748dfe 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -417,6 +417,15 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) void Vulkan_CreatePipelines (vulkan_ctx_t *ctx) { + qfv_load_pipeline (ctx); + + plitem_t *item = ctx->pipelineDef; + if (!item || !(item = PL_ObjectForKey (item, "pipeline"))) { + Sys_Printf ("error loading pipeline\n"); + } else { + Sys_Printf ("Found pipeline def\n"); + } + ctx->pipeline = QFV_ParsePipeline (ctx, item); } void From 3b06ca01afe61f9c2fe334f8011c9be9e82597e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 23:54:22 +0900 Subject: [PATCH 1165/3664] [vulkan] Destroy pipeline on shutdown --- include/QF/Vulkan/pipeline.h | 2 ++ libs/video/renderer/vulkan/pipeline.c | 9 +++++++++ libs/video/renderer/vulkan/vulkan_vid_common.c | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/include/QF/Vulkan/pipeline.h b/include/QF/Vulkan/pipeline.h index c7d5013de..bd6e292a9 100644 --- a/include/QF/Vulkan/pipeline.h +++ b/include/QF/Vulkan/pipeline.h @@ -150,5 +150,7 @@ qfv_pipelineset_t * QFV_CreateComputePipelines (struct qfv_device_s *device, VkPipelineCache cache, qfv_computepipelinecreateinfoset_t *cpciSet); +void +QFV_DestroyPipeline (struct qfv_device_s *device, VkPipeline pipeline); #endif//__QF_Vulkan_pipeline_h diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c index bfe48ce9f..2db39812c 100644 --- a/libs/video/renderer/vulkan/pipeline.c +++ b/libs/video/renderer/vulkan/pipeline.c @@ -153,3 +153,12 @@ QFV_CreateComputePipelines (qfv_device_t *device, pipelines->a); return pipelines; } + +void +QFV_DestroyPipeline (qfv_device_t *device, VkPipeline pipeline) +{ + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyPipeline (dev, pipeline, 0); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 179748dfe..38288c81b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -58,6 +58,7 @@ #include "QF/Vulkan/command.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/shader.h" #include "QF/Vulkan/swapchain.h" @@ -158,6 +159,9 @@ clear_table (hashtab_t **table) void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { + if (ctx->pipeline) { + QFV_DestroyPipeline (ctx->device, ctx->pipeline); + } if (ctx->framebuffers.size) { Vulkan_DestroyFramebuffers (ctx); } From d4277ef130af9bdc051a3cfa7edb298c33247f27 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 7 Jan 2021 01:10:25 +0900 Subject: [PATCH 1166/3664] [util] Mark PL_CheckType as const I keep forgetting to do optimized builds :( --- include/QF/qfplist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 3f22a9e16..8f8db669f 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -310,7 +310,7 @@ plitem_t *PL_NewString (const char *str); */ void PL_Free (plitem_t *item); -int PL_CheckType (pltype_t field_type, pltype_t item_type); +int PL_CheckType (pltype_t field_type, pltype_t item_type) __attribute__((const)); void PL_TypeMismatch (plitem_t *messages, const plitem_t *item, const char *name, pltype_t field_type, pltype_t item_type); From 90428db3d5185b2bd1fad986e82c8a82a678da88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 7 Jan 2021 22:47:58 +0900 Subject: [PATCH 1167/3664] [glsl] Remove stray return statement I have no idea why that was in that patch and certainly does not seem to be correct. --- libs/video/renderer/glsl/glsl_bsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 767000b12..acdaf22c6 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -360,7 +360,7 @@ static void update_lightmap (msurface_t *surf) { int maps; -return; + for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) if (d_lightstylevalue[surf->styles[maps]] != surf->cached_light[maps]) goto dynamic; From b6d2c630591e1d21725bab9f72cc0d296585b233 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 7 Jan 2021 22:49:43 +0900 Subject: [PATCH 1168/3664] [vulkan] Fix some formtatting Both code and developer output. --- libs/video/renderer/vid_render_vulkan.c | 4 +--- libs/video/renderer/vulkan/renderpass.c | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 52246162b..a2ab54024 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -124,9 +124,7 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 1, - &framebuffer->imageAvailableSemaphore, - &waitStage, + 1, &framebuffer->imageAvailableSemaphore, &waitStage, 1, &framebuffer->cmdBuffer, 1, &framebuffer->renderDoneSemaphore, }; diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 78cc46563..65134ffd7 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -74,6 +74,7 @@ QFV_CreateRenderPass (qfv_device_t *device, if (developer->int_val & SYS_VULKAN) { Sys_Printf ("attachments: %ld\n", attachments->size); for (size_t i = 0; i < attachments->size; i++) { + Sys_Printf (" attachment: %zd\n", i); Sys_Printf (" flags: %x\n", attachments->a[i].flags); Sys_Printf (" format: %d\n", attachments->a[i].format); Sys_Printf (" samples: %x\n", attachments->a[i].samples); From 5aa74df922fbc56117954aaafa02d5312a667a6d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 8 Jan 2021 14:37:52 +0900 Subject: [PATCH 1169/3664] [renderer] Add a default 8x8 font It is not compatible with the quake charset (it's the IBM charset). The data is a simple bitmap but a converter to quake pic format is provided. --- include/r_local.h | 5 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/font8x8.c | 336 ++++++++++++++++++++++++++++++ 3 files changed, 342 insertions(+) create mode 100644 libs/video/renderer/font8x8.c diff --git a/include/r_local.h b/include/r_local.h index 189d38d38..ebf1a9dd6 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -346,7 +346,12 @@ extern byte crosshair_data[]; #define CROSSHAIR_TILEY 2 #define CROSSHAIR_COUNT (CROSSHAIR_TILEX * CROSSHAIR_TILEY) +//NOTE: This is packed 8x8 bitmap data, one byte per scanline, 8 scanlines +////per character. Also, it is NOT the quake font, but the IBM charset. +extern byte font8x8_data[]; + struct qpic_s *Draw_CrosshairPic (void); +struct qpic_s *Draw_Font8x8Pic (void); struct tex_s *R_DotParticleTexture (void); struct tex_s *R_SparkParticleTexture (void); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index b5ca83cf5..990d17d88 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -13,6 +13,7 @@ EXTRA_LTLIBRARIES += \ video_renderer_common_sources = \ libs/video/renderer/crosshair.c \ + libs/video/renderer/font8x8.c \ libs/video/renderer/noisetextures.c \ libs/video/renderer/r_alias.c \ libs/video/renderer/r_bsp.c \ diff --git a/libs/video/renderer/font8x8.c b/libs/video/renderer/font8x8.c new file mode 100644 index 000000000..ab78882a5 --- /dev/null +++ b/libs/video/renderer/font8x8.c @@ -0,0 +1,336 @@ +/* + r_font8x8.c + + 8x8 bitmap font data. + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/1/8 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/qtypes.h" +#include "QF/wadfile.h" + +#include "r_internal.h" + +//NOTE: This is packed 8x8 bitmap data, one byte per scanline, 8 scanlines +//per character. Also, it is NOT the quake font, but the IBM charset. +byte font8x8_data[] = { + 0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xff, + 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E, + 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E, + 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, + 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x92, 0x10, 0x7C, + 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C, + 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, + 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, + 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, + 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, + 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78, + 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, + 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0, + 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0, + 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99, + 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00, + 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00, + 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00, + 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0x86, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00, + 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF, + 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, + 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, + 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, + 0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00, + 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00, + 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00, + 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, + 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, + 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, + 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, + 0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00, + 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00, + 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00, + 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00, + 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00, + 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00, + 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00, + 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, + 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00, + 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00, + 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, + 0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, + 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, + 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00, + 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, + 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00, + 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00, + 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00, + 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00, + 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00, + 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00, + 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, + 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00, + 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00, + 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, + 0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00, + 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00, + 0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00, + 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, + 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, + 0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00, + 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00, + 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00, + 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00, + 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00, + 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00, + 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, + 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00, + 0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, + 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0, + 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E, + 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00, + 0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00, + 0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00, + 0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00, + 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00, + 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00, + 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, + 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00, + 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00, + 0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C, + 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0x7E, 0x81, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0x00, + 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0x78, 0x0C, 0x38, + 0x7E, 0x81, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, + 0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00, + 0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7C, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00, + 0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xC6, 0x10, 0x7C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00, + 0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00, + 0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00, + 0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00, + 0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00, + 0x78, 0x84, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x78, 0x84, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8, + 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00, + 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, + 0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18, + 0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00, + 0xCC, 0xCC, 0x78, 0x30, 0xFC, 0x30, 0xFC, 0x30, + 0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC3, + 0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70, + 0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00, + 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00, + 0x00, 0xF8, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0x00, + 0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00, + 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, + 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, + 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3C, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00, + 0xC6, 0xCC, 0xD8, 0x36, 0x6B, 0xC2, 0x84, 0x0F, + 0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6D, 0xCF, 0x03, + 0x18, 0x00, 0x18, 0x18, 0x3C, 0x3C, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, + 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, + 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0xDB, 0xF6, 0xDB, 0x6F, 0xDB, 0x7E, 0xD7, 0xED, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00, + 0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xCC, 0xF8, 0xC0, + 0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, + 0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, + 0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00, + 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0, + 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC, + 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00, + 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00, + 0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00, + 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00, + 0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0, + 0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00, + 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00, + 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, + 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00, + 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00, + 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70, + 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, + 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, + 0x58, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, + 0x70, 0x98, 0x30, 0x60, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, + 0xff, 0x99, 0x99, 0xff, 0xff, 0x99, 0x99, 0xff, +}; +#define FONT_WIDTH 8 +#define FONT_HEIGHT 8 +#define FONT_HCHARS 16 +#define FONT_VCHARS 16 +#define FONT_BYTES ((FONT_VCHARS)*(FONT_HCHARS)*(FONT_HEIGHT)*(FONT_WIDTH)) + +qpic_t * +Draw_Font8x8Pic (void) +{ + qpic_t *pic; + byte *data; + byte *out; + int i, j, x, y, ind; + + pic = calloc (1, field_offset (qpic_t, data[FONT_BYTES])); + pic->width = FONT_HCHARS * FONT_WIDTH; + pic->height = FONT_VCHARS * FONT_HEIGHT; + // convert the bitmap data to pixel data in a 16x16 character "image" + // assumes the quake palette where 254 is white, and 255 is transparent + data = font8x8_data; + for (j = 0; j < FONT_VCHARS; j++) { + for (i = 0; i < FONT_HCHARS; i++) { + for (y = 0; y < FONT_HEIGHT; y++) { + byte scanline = *data++; + ind = (j * FONT_HEIGHT + y) * FONT_WIDTH * FONT_HCHARS; + ind += i * FONT_WIDTH; + out = pic->data + ind; + for (x = 0; x < FONT_WIDTH; x++) { + *out++ = 0xff - ((scanline & 0x80) >> 7); + scanline <<= 1; + } + } + } + } + return pic; +} From 06d45cff0d23b0a0de9c89ad001f56fc2e335e3c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 9 Jan 2021 11:36:19 +0900 Subject: [PATCH 1170/3664] [build] Keep error messages from glslangValidator The tool is horrible as a built tool due to it not being silent when all is good (it outputs the input file name) and sends its error messages to stdout instead of stderr. Then filtering causes the error code to be lost. This uses a solution found on stack-exchange. --- Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index b59b21eb7..c869a6f3a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -119,11 +119,11 @@ V_XXD_1 = %.spv: % @$(mkdir_p) $(builddir)/`dirname $@` - $(V_GLSLANG)$(GLSLANGVALIDATOR) -V $< -o $@ > /dev/null + $(V_GLSLANG)(((($(GLSLANGVALIDATOR) -V $< -o $@; echo $$? >&3) | sed -e '1d' 1>&2) 3>&1) | (read xs; exit $$xs)) %.spvc: % @$(mkdir_p) $(builddir)/`dirname $@` - $(V_GLSLANG)$(GLSLANGVALIDATOR) --vn `basename $< | tr . _` -V $< -o $@ > /dev/null + $(V_GLSLANG)(((($(GLSLANGVALIDATOR) --vn `basename $< | tr . _` -V $< -o $@; echo $$? >&3) | sed -e '1d' 1>&2) 3>&1) | (read xs; exit $$xs)) shaderdir = @shaderdir@ shader_DATA = From 0c1699fdbb76da34d6463e631c94f34392430895 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 9 Jan 2021 20:42:23 +0900 Subject: [PATCH 1171/3664] Fix a pile of double semicolons --- libs/ruamoko/rua_set.c | 2 +- libs/util/cmem.c | 2 +- libs/util/qendian.c | 4 ++-- libs/video/renderer/gl/gl_mod_alias.c | 2 +- libs/video/renderer/glsl/glsl_textures.c | 2 +- libs/video/renderer/r_efrag.c | 2 +- libs/video/renderer/vulkan/swapchain.c | 2 +- qtv/source/sv_parse.c | 2 +- tools/bsp2img/bsp2img.c | 4 ++-- tools/qfcc/include/dags.h | 2 +- tools/qfcc/source/class.c | 2 +- tools/qfcc/source/dags.c | 2 +- tools/qfcc/source/qfcc.c | 2 +- tools/qfcc/test/old/linkdef2.r | 2 +- tools/qflight/source/entities.c | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 4e3ea732d..3bc36c06b 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -392,7 +392,7 @@ bi_set_first (progs_t *pr) res->set_iters->prev = &set_iter->next; res->set_iters = set_iter; - set_iter->iter = iter;; + set_iter->iter = iter; R_INT (pr) = res_set_iter_index (res, set_iter); } diff --git a/libs/util/cmem.c b/libs/util/cmem.c index 9dc461b87..1879f7ea3 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -321,7 +321,7 @@ cmemalloc (memsuper_t *super, size_t size) memblock_t *block = init_block (super, mem, super->page_size); line = block->free_lines; } - return alloc_line (line, size);; + return alloc_line (line, size); } else { void *mem = 0; memsline_t **sline = &super->last_freed[ind]; diff --git a/libs/util/qendian.c b/libs/util/qendian.c index 12873af9f..9858823be 100644 --- a/libs/util/qendian.c +++ b/libs/util/qendian.c @@ -41,9 +41,9 @@ */ #ifndef WORDS_BIGENDIAN -VISIBLE qboolean bigendien = false;; +VISIBLE qboolean bigendien = false; #else -VISIBLE qboolean bigendien = true;; +VISIBLE qboolean bigendien = true; #endif diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index c74e1815c..44a114ff5 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -190,7 +190,7 @@ GL_DrawAliasFrameMulti (vert_order_t *vo) static void GL_DrawAliasShadowTri (const aliashdr_t *paliashdr, const vert_order_t *vo) { - int count = vo->count;; + int count = vo->count; const blended_vert_t *verts = vo->verts; float height, lheight; vec3_t point; diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index 62b331662..4e6303093 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -519,7 +519,7 @@ GLSL_SubpicUpdate (subpic_t *subpic, byte *data, int batch) void GLSL_ScrapFlush (scrap_t *scrap) { - vrect_t *rect = scrap->batch;; + vrect_t *rect = scrap->batch; if (!rect) return; diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 74592fa30..870c01fc1 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -89,7 +89,7 @@ R_ClearEfrags (void) if (!efrag_list) efrag_list = calloc (1, sizeof (t_efrag_list)); - r_free_efrags = efrag_list->efrags;; + r_free_efrags = efrag_list->efrags; for (efl = efrag_list; efl; efl = efl->next) { init_efrag_list (efl); if (efl->next) diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index b2007953a..478700e83 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -43,7 +43,7 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) uint32_t numModes; VkPresentModeKHR *modes; - VkPresentModeKHR useMode = VK_PRESENT_MODE_FIFO_KHR;; + VkPresentModeKHR useMode = VK_PRESENT_MODE_FIFO_KHR; ifuncs->vkGetPhysicalDeviceSurfacePresentModesKHR (physDev, ctx->surface, &numModes, 0); diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index c179d125e..1b6ca5841 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -531,7 +531,7 @@ parse_player_delta (qmsg_t *msg, plent_state_t *from, plent_state_t *to) if (flags & PF_SKINNUM) to->skinnum = MSG_ReadByte (msg); if (flags & PF_EFFECTS) - to->effects = (to->effects & 0xff00) | MSG_ReadByte (msg);; + to->effects = (to->effects & 0xff00) | MSG_ReadByte (msg); if (flags & PF_WEAPONFRAME) to->weaponframe = MSG_ReadByte (msg); if (flags & PF_QF) { diff --git a/tools/bsp2img/bsp2img.c b/tools/bsp2img/bsp2img.c index 649fe1427..7b95c35a6 100644 --- a/tools/bsp2img/bsp2img.c +++ b/tools/bsp2img/bsp2img.c @@ -672,14 +672,14 @@ render_map (bsp_t *bsp) vertexlist[i].X = -vertexlist[i].X; tempf = vertexlist[i].Z; vertexlist[i].Z = vertexlist[i].Y; - vertexlist[i].Y = tempf;; + vertexlist[i].Y = tempf; break; case 2: /* +Y -- (-x <--> +x; +y out of screen, +z up) */ tempf = vertexlist[i].Z; vertexlist[i].Z = -vertexlist[i].Y; - vertexlist[i].Y = tempf;; + vertexlist[i].Y = tempf; break; case -3: /* -Z -- negate X and Z (ie. 180 rotate diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index 534e58511..2c677a972 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -89,7 +89,7 @@ typedef struct dag_s { int num_topo; ///< number of nodes in topo (may be < ///< num_nodes after dead node removal) daglabel_t **labels; ///< array of all daglabels in this dag - int num_labels;; + int num_labels; struct set_s *roots; ///< set of root nodes struct flownode_s *flownode;///< flow node this dag represents } dag_t; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 52a3e194a..9203e9fbf 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1563,7 +1563,7 @@ class_finish_module (void) save_storage = current_storage; current_storage = sc_static; current_func = begin_function (init_sym, 0, current_symtab, 1); - build_code_function (init_sym, 0, init_expr);; + build_code_function (init_sym, 0, init_expr); current_func = 0; current_storage = save_storage; } diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 8dec15fa2..1d98df411 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -500,7 +500,7 @@ static int dag_def_kill_aliases_visit (def_t *def, void *_l) { daglabel_t *l = (daglabel_t *) _l; - dagnode_t *node = l->dagnode;; + dagnode_t *node = l->dagnode; daglabel_t *label; if (def == l->op->o.def) diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 96c26e4b0..e6c3b7946 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -189,7 +189,7 @@ InitData (void) pr.entity_data = defspace_new (ds_virtual); pr.entity_fields = new_symtab (0, stab_global); - pr.entity_fields->space = pr.entity_data;; + pr.entity_fields->space = pr.entity_data; clear_functions (); clear_frame_macros (); diff --git a/tools/qfcc/test/old/linkdef2.r b/tools/qfcc/test/old/linkdef2.r index 133235f69..20a72fa3a 100644 --- a/tools/qfcc/test/old/linkdef2.r +++ b/tools/qfcc/test/old/linkdef2.r @@ -5,5 +5,5 @@ id obj; integer foo (void) { [obj message]; - return bar () + baz ();; + return bar () + baz (); } diff --git a/tools/qflight/source/entities.c b/tools/qflight/source/entities.c index c9d262356..d2bd2711c 100644 --- a/tools/qflight/source/entities.c +++ b/tools/qflight/source/entities.c @@ -183,7 +183,7 @@ LoadEntities (void) // start parsing num_entities = PL_A_NumObjects (entity_list); - entities = malloc (num_entities * sizeof (entity_t));; + entities = malloc (num_entities * sizeof (entity_t)); // go through all the entities for (i = 0; i < num_entities; i++) { From 16334158bded47847201bcf6b6a6f6f26838ea87 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 01:35:39 +0900 Subject: [PATCH 1172/3664] [util] Support struct pointer accesses in cexpr --- include/QF/cexpr.h | 3 +++ libs/util/cexpr-vars.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index ac6eef683..53fc159e7 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -113,6 +113,8 @@ void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(pri void cexpr_struct_getfield (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx); +void cexpr_struct_pointer_getfield (const exprval_t *a, const exprval_t *b, + exprval_t *c, exprctx_t *ctx); exprval_t *cexpr_cvar (const char *name, exprctx_t *ctx); exprval_t *cexpr_cvar_struct (exprctx_t *ctx); @@ -132,5 +134,6 @@ extern exprtype_t cexpr_field; extern exprtype_t cexpr_function; extern binop_t cexpr_struct_binops[]; +extern binop_t cexpr_struct_pointer_binops[]; #endif diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c index 115f0ba64..04c6871ad 100644 --- a/libs/util/cexpr-vars.c +++ b/libs/util/cexpr-vars.c @@ -58,6 +58,20 @@ VISIBLE binop_t cexpr_struct_binops[] = { {} }; +VISIBLE void +cexpr_struct_pointer_getfield (const exprval_t *a, const exprval_t *b, + exprval_t *c, exprctx_t *ctx) +{ + // "dereference" the pointer + exprval_t struct_val = { a->type, *(void **) a->value }; + cexpr_struct_getfield (&struct_val, b, c, ctx); +} + +VISIBLE binop_t cexpr_struct_pointer_binops[] = { + { '.', &cexpr_field, &cexpr_exprval, cexpr_struct_pointer_getfield }, + {} +}; + static void cvar_get (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx) { From e281b608e1bc3dbf972a2fa2d2022c2c39dc7a35 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 01:38:31 +0900 Subject: [PATCH 1173/3664] [vulkan] Provide access to swapchain image count This necessitated hand-writing qfv_swapchain_t's descriptors as I don't feel like getting that complicated with vkgen at this stage and it's not really appropriate anyway? qfv_swapchain_t is meant to be read-only and not parsed from a plist. --- libs/video/renderer/vulkan/vkparse.c | 32 ++++++++++++++++++++++++ libs/video/renderer/vulkan/vkparse.plist | 5 ---- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 45236c7ff..b74d9af7d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -469,6 +469,36 @@ parse_BasePipeline (const plitem_t *item, void **data, #include "libs/video/renderer/vulkan/vkparse.cinc" +static exprsym_t imageset_symbols[] = { + {"size", &cexpr_size_t, (void *)field_offset (qfv_imageset_t, size)}, + { } +}; +static exprtab_t imageset_symtab = { + imageset_symbols, +}; +exprtype_t imageset_type = { + "imageset", + sizeof (qfv_imageset_t *), + cexpr_struct_pointer_binops, + 0, + &imageset_symtab, +}; +static exprsym_t qfv_swapchain_t_symbols[] = { + {"format", &VkFormat_type, (void *)field_offset (qfv_swapchain_t, format)}, + {"images", &imageset_type, (void *)field_offset (qfv_swapchain_t, images)}, + { } +}; +static exprtab_t qfv_swapchain_t_symtab = { + qfv_swapchain_t_symbols, +}; +exprtype_t qfv_swapchain_t_type = { + "qfv_swapchain_t", + sizeof (qfv_swapchain_t), + cexpr_struct_binops, + 0, + &qfv_swapchain_t_symtab, +}; + typedef struct qfv_renderpass_s { qfv_attachmentdescription_t *attachments; qfv_subpassparametersset_t *subpasses; @@ -566,6 +596,8 @@ QFV_InitParse (vulkan_ctx_t *ctx) &ctx->hashlinks); context.hashlinks = &ctx->hashlinks; vkgen_init_symtabs (&context); + cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); + cexpr_init_symtab (&imageset_symtab, &context); } exprenum_t * diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 97e767676..f6c92e110 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -18,7 +18,6 @@ VkPushConstantRange, VkPipelineLayoutCreateInfo, VkGraphicsPipelineCreateInfo, - qfv_swapchain_t, ); handles = { VkShaderModule = { @@ -61,10 +60,6 @@ }, ); parse = { - qfv_swapchain_s = { - .name = qfv_swapchain_t; - format = auto; - }; VkSubpassDescription = { flags = auto; pipelineBindPoint = auto; From 01b9c9bf7870c42e1f49ccaf29462965e89bb3b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 01:53:15 +0900 Subject: [PATCH 1174/3664] [vulkan] Parse descriptor pools --- include/vid_vulkan.h | 1 + libs/video/renderer/vulkan/vkparse.c | 18 ++++++++++++++++++ libs/video/renderer/vulkan/vkparse.plist | 15 +++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index d34e067fe..6aff7ea32 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -48,6 +48,7 @@ typedef struct vulkan_ctx_s { struct hashtab_s *shaderModules; struct hashtab_s *setLayouts; struct hashtab_s *pipelineLayouts; + struct hashtab_s *descriptorPools; VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index b74d9af7d..d7060d237 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -456,6 +456,21 @@ pipelineLayout_free (void *hr, void *_ctx) handleref_free (handleref, ctx); } +static void +descriptorPool_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type pool = (VkDescriptorPool) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (pool) { + dfunc->vkDestroyDescriptorPool (device->dev, pool, 0); + }; + handleref_free (handleref, ctx); +} + static hashtab_t *enum_symtab; static int @@ -560,6 +575,9 @@ QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) ctx->pipelineLayouts = Hash_NewTable (23, handleref_getkey, pipelineLayout_free, ctx, &ctx->hashlinks); + ctx->descriptorPools = Hash_NewTable (23, handleref_getkey, + descriptorPool_free, + ctx, &ctx->hashlinks); } for (parseres_t *res = parse_resources; res->name; res++) { diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index f6c92e110..fc406b4c4 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -18,6 +18,7 @@ VkPushConstantRange, VkPipelineLayoutCreateInfo, VkGraphicsPipelineCreateInfo, + VkDescriptorPoolCreateInfo, ); handles = { VkShaderModule = { @@ -25,6 +26,11 @@ class = "shader module"; custom = parse_VkShaderModule_resource; }; + VkDescriptorPool = { + symtab = descriptorPools; + class = "descriptor pool"; + create = vkCreateDescriptorPool; + }; VkDescriptorSetLayout = { symtab = setLayouts; class = "set layout"; @@ -150,6 +156,15 @@ values = pBindings; }; }; + VkDescriptorPoolCreateInfo = { + flags = auto; + maxSets = auto; + bindings = { + type = (array, VkDescriptorPoolSize); + size = poolSizeCount; + values = pPoolSizes; + }; + }; VkPipelineVertexInputStateCreateInfo = { //flags = auto; reserved for future use (Bits enum does not exist) bindings = { From a35eec387792384a07f2bd94272576c1b684df21 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 15:02:24 +0900 Subject: [PATCH 1175/3664] [util] Fail gracefully when no symtab is present --- libs/util/cexpr-lex.l | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index 2cbbdaa79..9c9377beb 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -258,6 +258,9 @@ parse_name (const char *name, exprctx_t *context) { exprtab_t *symtab = context->symtab; + if (!symtab) { + return 0; + } __auto_type sym = (exprsym_t *) Hash_Find (symtab->tab, name); return sym; } From e7106cce9eacad81cac5b1d42da1aa256188431e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 15:22:39 +0900 Subject: [PATCH 1176/3664] [plugin] Remove Draw_Init from draw funcs It's never called outside the renderers. --- include/QF/plugin/vid_render.h | 1 - libs/video/renderer/vid_render_gl.c | 1 - libs/video/renderer/vid_render_glsl.c | 1 - libs/video/renderer/vid_render_sw.c | 1 - libs/video/renderer/vid_render_sw32.c | 1 - libs/video/renderer/vid_render_vulkan.c | 1 - 6 files changed, 6 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index bdec285d1..6de6e9af7 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -108,7 +108,6 @@ typedef struct vid_model_funcs_s { } vid_model_funcs_t; typedef struct vid_render_funcs_s { - void (*Draw_Init) (void); void (*Draw_Character) (int x, int y, unsigned ch); void (*Draw_String) (int x, int y, const char *str); void (*Draw_nString) (int x, int y, const char *str, int count); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 9085e751d..434588894 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -72,7 +72,6 @@ static vid_model_funcs_t model_funcs = { }; vid_render_funcs_t gl_vid_render_funcs = { - gl_Draw_Init, gl_Draw_Character, gl_Draw_String, gl_Draw_nString, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 22de04ea3..f8ca47174 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -72,7 +72,6 @@ static vid_model_funcs_t model_funcs = { }; vid_render_funcs_t glsl_vid_render_funcs = { - glsl_Draw_Init, glsl_Draw_Character, glsl_Draw_String, glsl_Draw_nString, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index dcfb4abc7..a418d200c 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -65,7 +65,6 @@ static vid_model_funcs_t model_funcs = { }; vid_render_funcs_t sw_vid_render_funcs = { - Draw_Init, Draw_Character, Draw_String, Draw_nString, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index ed7414a85..9fffb0298 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -70,7 +70,6 @@ static vid_model_funcs_t model_funcs = { }; vid_render_funcs_t sw32_vid_render_funcs = { - sw32_Draw_Init, sw32_Draw_Character, sw32_Draw_String, sw32_Draw_nString, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a2ab54024..a4299d827 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -194,7 +194,6 @@ static vid_model_funcs_t model_funcs = { }; vid_render_funcs_t vulkan_vid_render_funcs = { - 0,//vulkan_Draw_Init, 0,//vulkan_Draw_Character, 0,//vulkan_Draw_String, 0,//vulkan_Draw_nString, From ef817a5cbf51dabc0e501944b6960e4c38f91c2c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 15:26:09 +0900 Subject: [PATCH 1177/3664] [vulkan] Allow images to be created initialized Needed for loaded textures. --- include/QF/Vulkan/image.h | 3 ++- libs/video/renderer/vulkan/image.c | 8 +++++--- libs/video/renderer/vulkan/vulkan_vid_common.c | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index edb5e025e..dc6bc5eea 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -37,7 +37,8 @@ VkImage QFV_CreateImage (struct qfv_device_s *device, int cubemap, uint32_t num_mipmaps, uint32_t num_layers, VkSampleCountFlagBits samples, - VkImageUsageFlags usage_scenarios); + VkImageUsageFlags usage_scenarios, + int initialized); VkDeviceMemory QFV_AllocImageMemory (struct qfv_device_s *device, VkImage image, diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 68decb94a..a60435a9d 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -69,7 +69,8 @@ QFV_CreateImage (qfv_device_t *device, int cubemap, uint32_t num_mipmaps, uint32_t num_layers, VkSampleCountFlagBits samples, - VkImageUsageFlags usage_scenarios) + VkImageUsageFlags usage_scenarios, + int initialized) { VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; @@ -79,11 +80,12 @@ QFV_CreateImage (qfv_device_t *device, int cubemap, type, format, size, num_mipmaps, cubemap ? 6 * num_layers : num_layers, samples, - VK_IMAGE_TILING_OPTIMAL, + initialized ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL, usage_scenarios, VK_SHARING_MODE_EXCLUSIVE, 0, 0, - VK_IMAGE_LAYOUT_UNDEFINED, + initialized ? VK_IMAGE_LAYOUT_PREINITIALIZED + : VK_IMAGE_LAYOUT_UNDEFINED, }; VkImage image; dfunc->vkCreateImage (dev, &createInfo, 0, &image); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 38288c81b..8d0aa4870 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -319,7 +319,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, sc->format, extent, 1, 1, ctx->msaaSamples, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT - | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0); colorImage->object = QFV_AllocImageMemory (device, colorImage->image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); @@ -336,7 +336,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) depthImage->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, depthFormat, extent, 1, 1, ctx->msaaSamples, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0); depthImage->object = QFV_AllocImageMemory (device, depthImage->image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); From fd07169a80607f4be4e030ee154c776ea8727c41 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 15:27:39 +0900 Subject: [PATCH 1178/3664] [util] Support casts from int/uint to size_t I don't want to do implicit down casts (size_t to uint) but I needed to be able to reference swapchain array size. --- libs/util/cexpr-type.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index f400803cb..57c7a945b 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -31,6 +31,7 @@ #include "QF/cexpr.h" #include "QF/mathlib.h" +#include "QF/qfplist.h" #include "QF/simd/vec4f.h" #include "libs/util/cexpr-parse.h" @@ -181,6 +182,26 @@ BINOP(size_t, bor, unsigned, |) BINOP(size_t, xor, unsigned, ^) BINOP(size_t, rem, unsigned, %) +static void +size_t_cast_int (const exprval_t *val1, const exprval_t *src, + exprval_t *result, exprctx_t *ctx) +{ + int val = *(int *) src->value; + if (val < 0) { + PL_Message (ctx->messages, ctx->item, "int value clamped to 0: %d", + val); + val = 0; + } + *(size_t *) result->value = val; +} + +static void +size_t_cast_uint (const exprval_t *val1, const exprval_t *src, + exprval_t *result, exprctx_t *ctx) +{ + *(size_t *) result->value = *(unsigned *) src->value; +} + UNOP(size_t, pos, unsigned, +) UNOP(size_t, neg, unsigned, -) UNOP(size_t, tnot, unsigned, !) @@ -198,6 +219,8 @@ binop_t size_t_binops[] = { { '^', &cexpr_size_t, &cexpr_size_t, size_t_xor }, { '%', &cexpr_size_t, &cexpr_size_t, size_t_rem }, { MOD, &cexpr_size_t, &cexpr_size_t, size_t_rem }, + { '=', &cexpr_int, &cexpr_size_t, size_t_cast_int }, + { '=', &cexpr_uint, &cexpr_size_t, size_t_cast_uint }, {} }; From b40b3cff1c32d8c1bbdd69f4f8629f019c864215 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 15:29:47 +0900 Subject: [PATCH 1179/3664] [vulkan] Use a size_t temp to parse uint32 values Needed for swapbuffer frame count --- libs/video/renderer/vulkan/vkparse.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index d7060d237..fbba8238b 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -175,8 +175,9 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { int ret = 1; + size_t val = 0; exprctx_t ectx = *((parsectx_t *) context)->ectx; - exprval_t result = { &cexpr_uint, data }; + exprval_t result = { &cexpr_size_t, &val }; ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); @@ -191,6 +192,11 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, // field->name, field->offset, field->type, field->parser, // field->data, valstr); ret = !cexpr_eval_string (valstr, &ectx); + if (!ret) { + PL_Message (messages, item, "error parsing %s: %s", + field->name, valstr); + } + *(uint32_t *) data = val; //Sys_Printf (" %d\n", *(uint32_t *)data); } From fed7149508c887d0d3abffe68099b009b71a6360 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 15:50:24 +0900 Subject: [PATCH 1180/3664] [vulkan] Parse sampler definitions --- libs/video/renderer/vulkan/vkparse.c | 49 ++++++++++++++----- libs/video/renderer/vulkan/vkparse.h | 1 + libs/video/renderer/vulkan/vkparse.plist | 20 ++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 2 + 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index fbba8238b..cd5e98502 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -477,6 +477,21 @@ descriptorPool_free (void *hr, void *_ctx) handleref_free (handleref, ctx); } +static void +sampler_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type sampler = (VkSampler) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (sampler) { + dfunc->vkDestroySampler (device->dev, sampler, 0); + }; + handleref_free (handleref, ctx); +} + static hashtab_t *enum_symtab; static int @@ -560,10 +575,23 @@ static plfield_t renderpass_fields[] = { {} }; +static hashtab_t * +handlref_symtab (void (*free_func)(void*,void*), vulkan_ctx_t *ctx) +{ + return Hash_NewTable (23, handleref_getkey, free_func, + ctx, &ctx->hashlinks); +} + void QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) { plitem_t *messages = PL_NewArray (); + exprsym_t var_syms[] = { + {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, + {} + }; + exprtab_t vars_tab = { var_syms, 0 }; exprctx_t exprctx = {}; parsectx_t parsectx = { &exprctx, ctx }; int ret = 1; @@ -571,19 +599,15 @@ QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) exprctx.memsuper = new_memsuper (); exprctx.messages = messages; exprctx.hashlinks = &ctx->hashlinks; + exprctx.external_variables = &vars_tab; + cexpr_init_symtab (&vars_tab, &exprctx); if (!ctx->setLayouts) { - ctx->shaderModules = Hash_NewTable (23, handleref_getkey, - shaderModule_free, - ctx, &ctx->hashlinks); - ctx->setLayouts = Hash_NewTable (23, handleref_getkey, setLayout_free, - ctx, &ctx->hashlinks); - ctx->pipelineLayouts = Hash_NewTable (23, handleref_getkey, - pipelineLayout_free, - ctx, &ctx->hashlinks); - ctx->descriptorPools = Hash_NewTable (23, handleref_getkey, - descriptorPool_free, - ctx, &ctx->hashlinks); + ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); + ctx->setLayouts = handlref_symtab (setLayout_free, ctx); + ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx); + ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx); + ctx->samplers = handlref_symtab (sampler_free, ctx); } for (parseres_t *res = parse_resources; res->name; res++) { @@ -646,11 +670,10 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) exprctx_t exprctx = {}; parsectx_t parsectx = { &exprctx, ctx }; - exprctx.external_variables = &vars_tab; exprctx.memsuper = new_memsuper (); exprctx.messages = messages; exprctx.hashlinks = &ctx->hashlinks; - + exprctx.external_variables = &vars_tab; cexpr_init_symtab (&vars_tab, &exprctx); if (!PL_ParseStruct (renderpass_fields, plist, &renderpass_data, diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 394cd296d..75dd8fe9d 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -7,6 +7,7 @@ typedef struct parsectx_s { } parsectx_t; #include "QF/cexpr.h" +#include "QF/qfplist.h" #include "QF/Vulkan/renderpass.h" #ifdef vkparse_internal #include "libs/video/renderer/vulkan/vkparse.hinc" diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index fc406b4c4..edf68541e 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -19,6 +19,7 @@ VkPipelineLayoutCreateInfo, VkGraphicsPipelineCreateInfo, VkDescriptorPoolCreateInfo, + VkSamplerCreateInfo, ); handles = { VkShaderModule = { @@ -41,6 +42,11 @@ class = "pipeline layout"; create = vkCreatePipelineLayout; }; + VkSampler = { + symtab = samplers; + class = "sampler"; + create = vkCreateSampler; + }; }; resources = ( { @@ -64,6 +70,20 @@ type = handleref_t; table = pipelineLayouts; }, + { + name = descriptorPools; + parse_type = QFDictionary; + parser = parse_VkDescriptorPool_handleref; + type = handleref_t; + table = descriptorPools; + }, + { + name = samplers; + parse_type = QFDictionary; + parser = parse_VkSampler_handleref; + type = handleref_t; + table = samplers; + }, ); parse = { VkSubpassDescription = { diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 8d0aa4870..3f701e27a 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -176,6 +176,8 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) clear_table (&ctx->pipelineLayouts); clear_table (&ctx->setLayouts); clear_table (&ctx->shaderModules); + clear_table (&ctx->descriptorPools); + clear_table (&ctx->samplers); if (ctx->device) { QFV_DestroyDevice (ctx->device); } From ba6450d0b4630abca73d6b0a9dd46140495aad92 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 10 Jan 2021 15:52:27 +0900 Subject: [PATCH 1181/3664] [vulkan] Make a start on the 2D pipeline Short wrappers for Draw functins are in vid_render_vulkan.c so the vulkan context can be passed on to the actual functions. The 2D shaders are set up similar to those in glsl, but with full 32-bit color (rgba) support instead of paletted. However, the textures are not loaded yet, nor is anything bound. --- include/QF/Vulkan/draw.h | 237 ++++++++++++++++++ include/QF/Vulkan/qf_draw.h | 52 +++- include/QF/Vulkan/qf_vid.h | 2 +- include/vid_vulkan.h | 3 + libs/video/renderer/Makemodule.am | 12 +- libs/video/renderer/vid_render_vulkan.c | 154 ++++++++++-- libs/video/renderer/vulkan/device.c | 3 +- libs/video/renderer/vulkan/qfpipeline.plist | 224 +++++++++++------ libs/video/renderer/vulkan/shader.c | 6 + libs/video/renderer/vulkan/twod.frag | 19 ++ libs/video/renderer/vulkan/twod.vert | 27 ++ libs/video/renderer/vulkan/vulkan_draw.c | 142 ++++++++--- .../video/renderer/vulkan/vulkan_vid_common.c | 19 +- 13 files changed, 742 insertions(+), 158 deletions(-) create mode 100644 include/QF/Vulkan/draw.h create mode 100644 libs/video/renderer/vulkan/twod.frag create mode 100644 libs/video/renderer/vulkan/twod.vert diff --git a/include/QF/Vulkan/draw.h b/include/QF/Vulkan/draw.h new file mode 100644 index 000000000..8f6b78889 --- /dev/null +++ b/include/QF/Vulkan/draw.h @@ -0,0 +1,237 @@ +/* + draw.h + + Video buffer handling definitions and prototypes + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_draw_h +#define __QF_draw_h + +/** \defgroup video Video Sub-sytem */ + +/** \defgroup video_renderer Renderer Sub-system + \ingroup video +*/ + +/** \defgroup video_renderer_draw Generic draw functions + \ingroup video_renderer +*/ +///@{ + +#include "QF/wad.h" + +extern byte *draw_chars; + +/** Initialize the draw stuff. +*/ +void Draw_Init (void); + +/** Draws one 8*8 graphics character with 0 being transparent. + It can be clipped to the top of the screen to allow the console to be + smoothly scrolled off. + \param x horizontal location of the top left corner of the character. + \param y vertical location of the top left corner of the character. + \param ch 8 bit character to draw. + \note The character drawn is from the quake character set, which is + (by default) standard ascii for 0x20-0x7e (white). 0xa0-0xfe is + also standard ascii (brown). 0x01-0x1f and 0x80-0x9f are + various drawing characters, and 0x7f is a backwards arrow. +*/ +void Draw_Character (int x, int y, unsigned ch); + +/** Draws a character string to the screen. + No line wrapping is performed. + \param x horizontal location of the top left corner of the character. + \param y vertical location of the top left corner of the character. + \param str 8 bit character string to draw. + \note See Draw_Character() for character set description. + String is normal nul terminated C string. +*/ +void Draw_String (int x, int y, const char *str); + +/** Draws a character sub-string to the screen. + No line wrapping is performed. + \param x horizontal location of the top left corner of the character. + \param y vertical location of the top left corner of the character. + \param str 8 bit character string to draw. + \param count Maximum characters of the string to draw. + \note See Draw_Character() for character set description. + Draws up to \p count characters, or stops at the first nul + character. +*/ +void Draw_nString (int x, int y, const char *str, int count); + +/** Draws a character string to the screen. + No line wrapping is performed. + \param x horizontal location of the top left corner of the character. + \param y vertical location of the top left corner of the character. + \param str 8 bit character string to draw. + \note See Draw_Character() for character set description. + String is normal nul terminated C string. + Characters of the string are forced to have their high bit set + (ie, they will be in the range 0x80-0xff). +*/ +void Draw_AltString (int x, int y, const char *str); + +/** Draw the console background with various optional effects. + \param lines Vertical size in pixels of the console. + \param alpha Console transparency level (255 = opaque). + \note \p alpha is effective only in the OpenGL renderer. Effectively + 255 (opaque) for the software renderer. + + \c gl_conspin causes the background to spin. + + \c gl_constretch causes the background to stretch rather than slide. +*/ +void Draw_ConsoleBackground (int lines, byte alpha); + +/** Draw a crosshair at the center of the screen. + \c crosshair specifies which crosshair (1 = '+', 2 = large 'x' shape, + 3 = fancy '+' shape) + \c cl_crossx and \c cl_crossy offset the crosshair from the center of the + screen. +*/ +void Draw_Crosshair (void); + +/** Draw the specified crosshair on the screen. + \param ch crosshair to draw + \param x horizontal position of the center of the crosshair. + \param y vertical position of the center of the crosshair. + + See Draw_Crosshair() for description of crosshair values. +*/ +void Draw_CrosshairAt (int ch, int x, int y); + +/** Clear a rectangle with a tiled background. + \param x horizontal position of the upper left corner of the rectangle + \param y horizontal position of the upper left corner of the rectangle + \param w width of the rectangle + \param h height of the rectangle + + The background used is the "backtile" WAD lump. +*/ +void Draw_TileClear (int x, int y, int w, int h); + +/** Clear a rectangle with a solid color. + \param x horizontal position of the upper left corner of the rectangle + \param y horizontal position of the upper left corner of the rectangle + \param w width of the rectangle + \param h height of the rectangle + \param c 8 bit color index. + + The color comes from the quake palette. +*/ +void Draw_Fill (int x, int y, int w, int h, int c); + +/** Draw a text box on the screen + \param x horizontal location of the upper left corner of the box + \param y vertical location of the upper left corner of the box + \param width horizontal size in character cells of the region + \param lines vertical size in character cells of the region + \param alpha transparency of the box +*/ +void Draw_TextBox (int x, int y, int width, int lines, byte alpha); + +/** Darken the screen. +*/ +void Draw_FadeScreen (void); + +/** Shift the screen colors. +*/ +void Draw_BlendScreen (quat_t color); +///@} + +/** \defgroup video_renderer_draw_qpic QPic functions + \ingroup video_renderer_draw +*/ +///@{ +/** Load a qpic from the filesystem. + \param path path of the file within the quake filesystem + \param alpha transparency level of the pic. + \return pointer qpic data. + \note Up to MAX_CACHED_PICS qpics can be loaded at a time this way +*/ +qpic_t *Draw_CachePic (const char *path, qboolean alpha); + +/** Remove a qpic from the qpic cache. + + This affects only those qpics that were loaded via Draw_CachePic. + + \param path path of the file within the quake filesystem +*/ +void Draw_UncachePic (const char *path); + +/** Create a qpic from raw data. + + \param width The width of the pic. + \param height The height of the pic. + \param data The raw data bytes. The system palette will be used for + colors. + \return pointer qpic data. +*/ +qpic_t *Draw_MakePic (int width, int height, const byte *data); + +/** Destroy a qpic created by Draw_MakePic. + + \param pic The qpic to destory. +*/ +void Draw_DestroyPic (qpic_t *pic); + +/** Load a qpic from gfx.wad. + \param name name of the was lump to load + \return pointer qpic data. +*/ +qpic_t *Draw_PicFromWad (const char *name); + +/** Draw a qpic to the screen + \param x horizontal location of the upper left corner of the qpic + \param y vertical location of the upper left corner of the qpic + \param pic qpic to draw +*/ +void Draw_Pic (int x, int y, qpic_t *pic); + +/** Draw a qpic to the screen + \param x horizontal location of the upper left corner of the qpic + \param y vertical location of the upper left corner of the qpic + \param pic qpic to draw +*/ +void Draw_Picf (float x, float y, qpic_t *pic); + +/** Draw a sub-region of a qpic to the screan + \param x horizontal screen location of the upper left corner of the + sub-region + \param y vertical screen location of the upper left corner of the + sub-region + \param pic qpic to draw + \param srcx horizontal qpic location of the upper left corner of the + sub-region + \param srcy vertical qpic location of the upper left corner of the + sub-region + \param width horizontal size of the sub-region to be drawn + \param height vertical size of the sub-region to be drawn +*/ +void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); +///@} + +#endif//__QF_draw_h diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index e4716f7ed..b0297c2d0 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -25,13 +25,49 @@ */ -#ifndef __gl_draw_h -#define __gl_draw_h +#ifndef __QF_Vulkan_qf_draw_h +#define __QF_Vulkan_qf_draw_h -void Vulkan_Set2D (void); -void Vulkan_Set2DScaled (void); -void Vulkan_End2D (void); -void Vulkan_DrawReset (void); -void Vulkan_FlushText (void); +struct vulkan_ctx_s; -#endif//__gl_draw_h +void Vulkan_Draw_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Character (int x, int y, unsigned ch, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_String (int x, int y, const char *str, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_nString (int x, int y, const char *str, int count, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_AltString (int x, int y, const char *str, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_ConsoleBackground (int lines, byte alpha, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Crosshair (struct vulkan_ctx_s *ctx); +void Vulkan_Draw_CrosshairAt (int ch, int x, int y, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_TileClear (int x, int y, int w, int h, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Fill (int x, int y, int w, int h, int c, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_FadeScreen (struct vulkan_ctx_s *ctx); +void Vulkan_Draw_BlendScreen (quat_t color, struct vulkan_ctx_s *ctx); +qpic_t *Vulkan_Draw_CachePic (const char *path, qboolean alpha, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_UncachePic (const char *path, struct vulkan_ctx_s *ctx); +qpic_t *Vulkan_Draw_MakePic (int width, int height, const byte *data, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_DestroyPic (qpic_t *pic, struct vulkan_ctx_s *ctx); +qpic_t *Vulkan_Draw_PicFromWad (const char *name, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Pic (int x, int y, qpic_t *pic, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Picf (float x, float y, qpic_t *pic, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_SubPic(int x, int y, qpic_t *pic, + int srcx, int srcy, int width, int height, + struct vulkan_ctx_s *ctx); + +void Vulkan_Set2D (struct vulkan_ctx_s *ctx); +void Vulkan_Set2DScaled (struct vulkan_ctx_s *ctx); +void Vulkan_End2D (struct vulkan_ctx_s *ctx); +void Vulkan_DrawReset (struct vulkan_ctx_s *ctx); +void Vulkan_FlushText (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_draw_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index d380d1236..f859d93f2 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -40,7 +40,7 @@ void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); -void Vulkan_CreatePipelines (struct vulkan_ctx_s *ctx); +VkPipeline Vulkan_CreatePipeline (struct vulkan_ctx_s *ctx, const char *name); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 6aff7ea32..0bc8d629d 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -20,6 +20,8 @@ typedef struct vulkan_framebuffer_s { VkSemaphore imageAvailableSemaphore; VkSemaphore renderDoneSemaphore; VkCommandBuffer cmdBuffer; + + VkDescriptorSet twodDescriptors; } vulkan_framebuffer_t; typedef struct vulkan_framebufferset_s @@ -49,6 +51,7 @@ typedef struct vulkan_ctx_s { struct hashtab_s *setLayouts; struct hashtab_s *pipelineLayouts; struct hashtab_s *descriptorPools; + struct hashtab_s *samplers; VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 990d17d88..1d6c5eaea 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -213,7 +213,7 @@ libs_video_renderer_vid_render_vulkan_la_LDFLAGS= $(plugin_ldflags) libs_video_renderer_vid_render_vulkan_la_LIBADD= $(vulkan_libs) libs_video_renderer_vid_render_vulkan_la_DEPENDENCIES=$(vulkan_libs) libs_video_renderer_vid_render_vulkan_la_SOURCES = \ - $(common_sources) \ + $(video_renderer_common_sources) \ libs/video/renderer/vid_render_vulkan.c \ libs/video/renderer/vulkan/buffer.c \ libs/video/renderer/vulkan/command.c \ @@ -249,16 +249,26 @@ vkparse_src = \ vkparse_plist = \ $(srcdir)/libs/video/renderer/vulkan/vkparse.plist +twodv_src = libs/video/renderer/vulkan/twod.vert +twodv_c = libs/video/renderer/vulkan/twod.vert.spvc +twodf_src = libs/video/renderer/vulkan/twod.frag +twodf_c = libs/video/renderer/vulkan/twod.frag.spvc passthrough_src = libs/video/renderer/vulkan/passthrough.vert passthrough_c = libs/video/renderer/vulkan/passthrough.vert.spvc pushcolor_src = libs/video/renderer/vulkan/pushcolor.frag pushcolor_c = libs/video/renderer/vulkan/pushcolor.frag.spvc +$(twodv_c): $(twodv_src) + +$(twodf_c): $(twodf_src) + $(passthrough_c): $(passthrough_src) $(pushcolor_c): $(pushcolor_src) vkshader_c = \ + $(twodv_c) \ + $(twodf_c) \ $(passthrough_c) \ $(pushcolor_c) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a4299d827..f84f9eb84 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -39,6 +39,7 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" @@ -66,7 +67,8 @@ vulkan_R_Init (void) Vulkan_CreateFramebuffers (vulkan_ctx); // FIXME this should be staged so screen updates can begin while pipelines // are being built - Vulkan_CreatePipelines (vulkan_ctx); + vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); + Vulkan_Draw_Init (vulkan_ctx); qfv_swapchain_t *sc = vulkan_ctx->swapchain; @@ -81,7 +83,7 @@ vulkan_R_Init (void) VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, vulkan_ctx->renderpass.renderpass, 0, { {0, 0}, sc->extent }, - 2, clearValues + 2, clearValues + 2 }; for (size_t i = 0; i < vulkan_ctx->framebuffers.size; i++) { __auto_type framebuffer = &vulkan_ctx->framebuffers.a[i]; @@ -153,18 +155,124 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) } } +static void +vulkan_Draw_Character (int x, int y, unsigned ch) +{ + Vulkan_Draw_Character (x, y, ch, vulkan_ctx); +} + +static void +vulkan_Draw_String (int x, int y, const char *str) +{ + Vulkan_Draw_String (x, y, str, vulkan_ctx); +} + +static void +vulkan_Draw_nString (int x, int y, const char *str, int count) +{ + Vulkan_Draw_nString (x, y, str, count, vulkan_ctx); +} + +static void +vulkan_Draw_AltString (int x, int y, const char *str) +{ + Vulkan_Draw_AltString (x, y, str, vulkan_ctx); +} + +static void +vulkan_Draw_ConsoleBackground (int lines, byte alpha) +{ + Vulkan_Draw_ConsoleBackground (lines, alpha, vulkan_ctx); +} + +static void +vulkan_Draw_Crosshair (void) +{ + Vulkan_Draw_Crosshair (vulkan_ctx); +} + +static void +vulkan_Draw_CrosshairAt (int ch, int x, int y) +{ + Vulkan_Draw_CrosshairAt (ch, x, y, vulkan_ctx); +} + +static void +vulkan_Draw_TileClear (int x, int y, int w, int h) +{ + Vulkan_Draw_TileClear (x, y, w, h, vulkan_ctx); +} + +static void +vulkan_Draw_Fill (int x, int y, int w, int h, int c) +{ + Vulkan_Draw_Fill (x, y, w, h, c, vulkan_ctx); +} + +static void +vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha) +{ + Vulkan_Draw_TextBox (x, y, width, lines, alpha, vulkan_ctx); +} + +static void +vulkan_Draw_FadeScreen (void) +{ + Vulkan_Draw_FadeScreen (vulkan_ctx); +} + +static void +vulkan_Draw_BlendScreen (quat_t color) +{ + Vulkan_Draw_BlendScreen (color, vulkan_ctx); +} + static qpic_t * vulkan_Draw_CachePic (const char *path, qboolean alpha) { - return 0; + return Vulkan_Draw_CachePic (path, alpha, vulkan_ctx); } -static qpic_t qpic = { 1, 1, {0} }; +static void +vulkan_Draw_UncachePic (const char *path) +{ + Vulkan_Draw_UncachePic (path, vulkan_ctx); +} static qpic_t * vulkan_Draw_MakePic (int width, int height, const byte *data) { - return &qpic; + return Vulkan_Draw_MakePic (width, height, data, vulkan_ctx); +} + +static void +vulkan_Draw_DestroyPic (qpic_t *pic) +{ + Vulkan_Draw_DestroyPic (pic, vulkan_ctx); +} + +static qpic_t * +vulkan_Draw_PicFromWad (const char *name) +{ + return Vulkan_Draw_PicFromWad (name, vulkan_ctx); +} + +static void +vulkan_Draw_Pic (int x, int y, qpic_t *pic) +{ + Vulkan_Draw_Pic (x, y, pic, vulkan_ctx); +} + +static void +vulkan_Draw_Picf (float x, float y, qpic_t *pic) +{ + Vulkan_Draw_Picf (x, y, pic, vulkan_ctx); +} + +static void +vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height) +{ + Vulkan_Draw_SubPic (x, y, pic, srcx, srcy, width, height, vulkan_ctx); } static vid_model_funcs_t model_funcs = { @@ -194,26 +302,26 @@ static vid_model_funcs_t model_funcs = { }; vid_render_funcs_t vulkan_vid_render_funcs = { - 0,//vulkan_Draw_Character, - 0,//vulkan_Draw_String, - 0,//vulkan_Draw_nString, - 0,//vulkan_Draw_AltString, - 0,//vulkan_Draw_ConsoleBackground, - 0,//vulkan_Draw_Crosshair, - 0,//vulkan_Draw_CrosshairAt, - 0,//vulkan_Draw_TileClear, - 0,//vulkan_Draw_Fill, - 0,//vulkan_Draw_TextBox, - 0,//vulkan_Draw_FadeScreen, - 0,//vulkan_Draw_BlendScreen, + vulkan_Draw_Character, + vulkan_Draw_String, + vulkan_Draw_nString, + vulkan_Draw_AltString, + vulkan_Draw_ConsoleBackground, + vulkan_Draw_Crosshair, + vulkan_Draw_CrosshairAt, + vulkan_Draw_TileClear, + vulkan_Draw_Fill, + vulkan_Draw_TextBox, + vulkan_Draw_FadeScreen, + vulkan_Draw_BlendScreen, vulkan_Draw_CachePic, - 0,//vulkan_Draw_UncachePic, + vulkan_Draw_UncachePic, vulkan_Draw_MakePic, - 0,//vulkan_Draw_DestroyPic, - 0,//vulkan_Draw_PicFromWad, - 0,//vulkan_Draw_Pic, - 0,//vulkan_Draw_Picf, - 0,//vulkan_Draw_SubPic, + vulkan_Draw_DestroyPic, + vulkan_Draw_PicFromWad, + vulkan_Draw_Pic, + vulkan_Draw_Picf, + vulkan_Draw_SubPic, vulkan_SCR_UpdateScreen, SCR_DrawRam, diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 0457d0570..86ba71f73 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -165,7 +165,7 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, family, 1, &priority }; - VkPhysicalDeviceFeatures features; + VkPhysicalDeviceFeatures features = {}; VkDeviceCreateInfo dCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0, 1, &qCreateInfo, @@ -173,7 +173,6 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) next, ext, &features }; - memset (&features, 0, sizeof (features)); qfv_device_t *device = calloc (1, sizeof (qfv_device_t) + sizeof (qfv_devfuncs_t)); device->funcs = (qfv_devfuncs_t *) (device + 1); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 1f9c6de46..03a4243b2 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -7,8 +7,61 @@ // $builtin refers to compiled-in shaders passthrough = $builtin/passthrough.vert; pushcolor = $builtin/pushcolor.frag; + twodv = $builtin/twod.vert; + twodf = $builtin/twod.frag; + }; + samplers = { + quakepic = { + magFilter = nearest; + minFilter = nearest; + mipmapMode = nearest; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = 0;//FIXME false!!! + maxAnisotropy = 0; + compareEnable = 0;//FIXME false!!! + compareOp = always; + minLod = 0; + maxLod = 0.25f; + borderColor = float_transparent_black; + unnormalizedCoordinates = 0;//FIXME false!!! + }; + }; + descriptorPools = { + twod = { + flags = 0; + maxSets = $swapchain.images.size; + bindings = ( + { + type = uniform_buffer; + descriptorCount = $swapchain.images.size; + }, + { + type = combined_image_sampler; + descriptorCount = $swapchain.images.size; + }, + ); + }; }; setLayouts = { + twod = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + binding = 1; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; something = { flags = 0; bindings = ( @@ -28,6 +81,9 @@ }; }; pipelineLayouts = { + twod = { + setLayouts = (twod); + }; something = { setLayouts = (something); pushConstantRanges = ( @@ -39,88 +95,96 @@ ); }; }; - pipeline = { - stages = ( - { stage = vertex; name = main; module = passthrough; }, - { stage = fragment; name = main; module = pushcolor; }, - ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "4 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 0; - }, + pipelines = { + twod = { + stages = ( + { stage = vertex; name = main; module = twodv; }, + { stage = fragment; name = main; module = twodf; }, ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "2 * 4 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + { + location = 1; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 4; + }, + ); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = 0; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = 0; + rasterizerDiscardEnable = 0; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = 0; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = 0; + minSampleShading = 0.5f; + alphaToCoverageEnable = 0; + alphaToOneEnable = 0; + }; + depthStencil = { + depthTestEnable = 1; + depthWriteEnable = 1; + depthCompareOp = less; + depthBoundsTestEnable = 0; + stencilTestEnable = 0; + }; + colorBlend = { + logicOpEnable = 0; + attachments = ({ + blendEnable = 0; + srcColorBlendFactor = src_color; + dstColorBlendFactor = zero; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = zero; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = twod; + //renderPass = renderpass; }; - inputAssembly = { - topology = triangle_list; - primitiveRestartEnable = 0; - }; - viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); - }; - rasterization = { - depthClampEnable = 0; - rasterizerDiscardEnable = 0; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = 0; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = 0; - minSampleShading = 0.5f; - alphaToCoverageEnable = 0; - alphaToOneEnable = 0; - }; - depthStencil = { - depthTestEnable = 1; - depthWriteEnable = 1; - depthCompareOp = less; - depthBoundsTestEnable = 0; - stencilTestEnable = 0; - }; - colorBlend = { - logicOpEnable = 0; - attachments = ({ - blendEnable = 0; - srcColorBlendFactor = src_color; - dstColorBlendFactor = zero; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = zero; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }); - }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - layout = something; - //renderPass = renderpass; }; renderpass = { attachments = ( diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index f0064bb35..25e1049ea 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -54,6 +54,10 @@ #include "vid_vulkan.h" +static +#include "libs/video/renderer/vulkan/twod.vert.spvc" +static +#include "libs/video/renderer/vulkan/twod.frag.spvc" static #include "libs/video/renderer/vulkan/passthrough.vert.spvc" static @@ -66,6 +70,8 @@ typedef struct shaderdata_s { } shaderdata_t; static shaderdata_t builtin_shaders[] = { + { "twod.vert", twod_vert, sizeof (twod_vert) }, + { "twod.frag", twod_frag, sizeof (twod_frag) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, {} diff --git a/libs/video/renderer/vulkan/twod.frag b/libs/video/renderer/vulkan/twod.frag new file mode 100644 index 000000000..83bda0874 --- /dev/null +++ b/libs/video/renderer/vulkan/twod.frag @@ -0,0 +1,19 @@ +#version 450 + +layout (set = 0, binding = 1) uniform sampler2D Texture; + +layout (location = 0) in vec2 st; +layout (location = 1) in vec4 color; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + vec4 pix; + + pix = texture (Texture, st); + if (pix.a < 0.5) + discard; + frag_color = pix * color; +} diff --git a/libs/video/renderer/vulkan/twod.vert b/libs/video/renderer/vulkan/twod.vert new file mode 100644 index 000000000..83655d6a7 --- /dev/null +++ b/libs/video/renderer/vulkan/twod.vert @@ -0,0 +1,27 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection; + mat4 View; + mat4 Model; +}; +/** Vertex position. + + x, y, s, t + + \a vertex provides the onscreen location at which to draw the icon + (\a x, \a y) and texture coordinate for the icon (\a s=z, \a t=w). +*/ +layout (location = 0) in vec4 vertex; +layout (location = 1) in vec4 vcolor; + +layout (location = 0) out vec2 st; +layout (location = 1) out vec4 color; + +void +main (void) +{ + gl_Position = Projection * vec4 (vertex.xy, 0.0, 1.0); + st = vertex.zw; + color = vcolor; +} diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 628306044..7f5e11111 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -3,10 +3,10 @@ 2D drawing support for Vulkan - Copyright (C) 2011 Bill Currie + Copyright (C) 2021 Bill Currie Author: Bill Currie - Date: 2011/12/23 + Date: 2021/1/10 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -49,10 +49,24 @@ #include "QF/sys.h" #include "QF/vid.h" +#include "compat.h" #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" #include "r_internal.h" +#include "vid_vulkan.h" +#include "vkparse.h" + +//FIXME move into a context struct +VkImage conchars_image; +VkDeviceMemory conchars_memory; +VkImageView conchars_view; +VkSampler conchars_sampler; + +VkPipeline twod; static qpic_t * pic_data (const char *name, int w, int h, const byte *data) @@ -67,135 +81,189 @@ pic_data (const char *name, int w, int h, const byte *data) } qpic_t * -vulkan_Draw_MakePic (int width, int height, const byte *data) +Vulkan_Draw_MakePic (int width, int height, const byte *data, + vulkan_ctx_t *ctx) { return pic_data (0, width, height, data); } void -vulkan_Draw_DestroyPic (qpic_t *pic) +Vulkan_Draw_DestroyPic (qpic_t *pic, vulkan_ctx_t *ctx) { } qpic_t * -vulkan_Draw_PicFromWad (const char *name) +Vulkan_Draw_PicFromWad (const char *name, vulkan_ctx_t *ctx) { return pic_data (0, 1, 1, (const byte *)""); } qpic_t * -vulkan_Draw_CachePic (const char *path, qboolean alpha) +Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) { return pic_data (0, 1, 1, (const byte *)""); } void -vulkan_Draw_UncachePic (const char *path) +Vulkan_Draw_UncachePic (const char *path, vulkan_ctx_t *ctx) { } void -vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha) +Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, + vulkan_ctx_t *ctx) +{ +} + +static void +Vulkan_Draw_Shutdown (void *data) +{ + vulkan_ctx_t *ctx = data; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyPipeline (device->dev, twod, 0); + dfunc->vkDestroyImageView (device->dev, conchars_view, 0); + dfunc->vkFreeMemory (device->dev, conchars_memory, 0); + dfunc->vkDestroyImage (device->dev, conchars_image, 0); +} + +void +Vulkan_Draw_Init (vulkan_ctx_t *ctx) +{ + Sys_RegisterShutdown (Vulkan_Draw_Shutdown, ctx); + + qfv_device_t *device = ctx->device; + qpic_t *charspic = Draw_Font8x8Pic (); + VkExtent3D extent = { charspic->width, charspic->height, 1 }; + conchars_image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, + VK_FORMAT_A8B8G8R8_UNORM_PACK32, + extent, 1, 1, + VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT, + 1); + conchars_memory = QFV_AllocImageMemory (device, conchars_image, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + 0, 0); + QFV_BindImageMemory (device, conchars_image, conchars_memory, 0); + conchars_view = QFV_CreateImageView (device, conchars_image, + VK_IMAGE_VIEW_TYPE_2D, + VK_FORMAT_A8B8G8R8_UNORM_PACK32, + VK_IMAGE_ASPECT_COLOR_BIT); + conchars_sampler = Hash_Find (ctx->samplers, "quakepic"); + + twod = Vulkan_CreatePipeline (ctx, "twod"); + + handleref_t *h; + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (ctx->framebuffers.size, alloca); + for (size_t i = 0; i < layouts->size; i++) { + h = Hash_Find (ctx->setLayouts, "twod"); + layouts->a[i] = (VkDescriptorSetLayout) h->handle; + } + h = Hash_Find (ctx->descriptorPools, "twod"); + __auto_type pool = (VkDescriptorPool) h->handle; + __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); + for (size_t i = 0; i < ctx->framebuffers.size; i++) { + ctx->framebuffers.a[i].twodDescriptors = sets->a[i]; + } +} + +void +Vulkan_Draw_Character (int x, int y, unsigned int chr, vulkan_ctx_t *ctx) { } void -vulkan_Draw_Init (void) +Vulkan_Draw_String (int x, int y, const char *str, vulkan_ctx_t *ctx) { } void -vulkan_Draw_Character (int x, int y, unsigned int chr) +Vulkan_Draw_nString (int x, int y, const char *str, int count, + vulkan_ctx_t *ctx) { } void -vulkan_Draw_String (int x, int y, const char *str) +Vulkan_Draw_AltString (int x, int y, const char *str, vulkan_ctx_t *ctx) { } void -vulkan_Draw_nString (int x, int y, const char *str, int count) +Vulkan_Draw_CrosshairAt (int ch, int x, int y, vulkan_ctx_t *ctx) { } void -vulkan_Draw_AltString (int x, int y, const char *str) +Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx) { } void -vulkan_Draw_CrosshairAt (int ch, int x, int y) +Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) { } void -vulkan_Draw_Crosshair (void) +Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) { } void -vulkan_Draw_Pic (int x, int y, qpic_t *pic) +Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, + int srcx, int srcy, int width, int height, + vulkan_ctx_t *ctx) { } void -vulkan_Draw_Picf (float x, float y, qpic_t *pic) +Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) { } void -vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, - int height) +Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) { } void -vulkan_Draw_ConsoleBackground (int lines, byte alpha) +Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) { } void -vulkan_Draw_TileClear (int x, int y, int w, int h) +Vulkan_Draw_FadeScreen (vulkan_ctx_t *ctx) { } void -vulkan_Draw_Fill (int x, int y, int w, int h, int c) +Vulkan_Set2D (vulkan_ctx_t *ctx) { } void -vulkan_Draw_FadeScreen (void) +Vulkan_Set2DScaled (vulkan_ctx_t *ctx) { } void -Vulkan_Set2D (void) +Vulkan_End2D (vulkan_ctx_t *ctx) { } void -Vulkan_Set2DScaled (void) +Vulkan_DrawReset (vulkan_ctx_t *ctx) { } void -Vulkan_End2D (void) +Vulkan_FlushText (vulkan_ctx_t *ctx) { } void -Vulkan_DrawReset (void) -{ -} - -void -Vulkan_FlushText (void) -{ -} - -void -vulkan_Draw_BlendScreen (quat_t color) +Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) { } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 3f701e27a..c2b17d0fe 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -420,18 +420,25 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) ctx->renderpass.depthImage = 0; } -void -Vulkan_CreatePipelines (vulkan_ctx_t *ctx) +VkPipeline +Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) { qfv_load_pipeline (ctx); plitem_t *item = ctx->pipelineDef; - if (!item || !(item = PL_ObjectForKey (item, "pipeline"))) { - Sys_Printf ("error loading pipeline\n"); + if (!item || !(item = PL_ObjectForKey (item, "pipelines"))) { + Sys_Printf ("error loading pipelines\n"); + return 0; } else { - Sys_Printf ("Found pipeline def\n"); + Sys_Printf ("Found pipelines def\n"); } - ctx->pipeline = QFV_ParsePipeline (ctx, item); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading pipeline %s\n", name); + return 0; + } else { + Sys_Printf ("Found pipeline def %s\n", name); + } + return QFV_ParsePipeline (ctx, item); } void From 23db917ec4efea4b2964009c95579b1ed766cd4e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 11 Jan 2021 01:24:15 +0900 Subject: [PATCH 1182/3664] [vulkan] Create a staging buffer struct And move the barrier prefabs into a more convenient place. --- include/QF/Vulkan/barrier.h | 21 ++++ include/QF/Vulkan/qf_vid.h | 1 + include/QF/Vulkan/staging.h | 18 ++++ include/vid_vulkan.h | 1 + libs/video/renderer/Makemodule.am | 2 + libs/video/renderer/vid_render_vulkan.c | 1 + libs/video/renderer/vulkan/barrier.c | 92 ++++++++++++++++++ libs/video/renderer/vulkan/staging.c | 96 +++++++++++++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 82 +++------------- 9 files changed, 243 insertions(+), 71 deletions(-) create mode 100644 include/QF/Vulkan/barrier.h create mode 100644 include/QF/Vulkan/staging.h create mode 100644 libs/video/renderer/vulkan/barrier.c create mode 100644 libs/video/renderer/vulkan/staging.c diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h new file mode 100644 index 000000000..12cea49ab --- /dev/null +++ b/include/QF/Vulkan/barrier.h @@ -0,0 +1,21 @@ +#ifndef __QF_Vulkan_barrier_h +#define __QF_Vulkan_barrier_h + +typedef struct { + VkPipelineStageFlags src; + VkPipelineStageFlags dst; +} qfv_pipelinestagepair_t; + +//XXX Note: imageLayoutTransitionBarriers, imageLayoutTransitionStages and +// the enum must be kept in sync +enum { + qfv_LT_Undefined_to_TransferDst, + qfv_LT_TransferDst_to_ShaderReadOnly, + qfv_LT_Undefined_to_DepthStencil, + qfv_LT_Undefined_to_Color, +}; + +extern const VkImageMemoryBarrier imageLayoutTransitionBarriers[]; +extern const qfv_pipelinestagepair_t imageLayoutTransitionStages[]; + +#endif//__QF_Vulkan_barrier_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index f859d93f2..d5f59cc84 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -45,5 +45,6 @@ void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); void Vulkan_Shutdown_Common (struct vulkan_ctx_s *ctx); +void Vulkan_CreateStagingBuffers (struct vulkan_ctx_s *ctx); #endif // __QF_Vulkan_vid_h diff --git a/include/QF/Vulkan/staging.h b/include/QF/Vulkan/staging.h new file mode 100644 index 000000000..d281f1854 --- /dev/null +++ b/include/QF/Vulkan/staging.h @@ -0,0 +1,18 @@ +#ifndef __QF_Vulkan_staging_h +#define __QF_Vulkan_staging_h + +typedef struct qfv_stagebuf_s { + struct qfv_device_s *device; + VkBuffer buffer; + VkDeviceMemory memory; + size_t size; + void *data; +} qfv_stagebuf_t; + + +qfv_stagebuf_t *QFV_CreateStagingBuffer (struct qfv_device_s *device, + size_t size); +void QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage); +void QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size); + +#endif//__QF_Vulkan_staging_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 0bc8d629d..05e127825 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -57,6 +57,7 @@ typedef struct vulkan_ctx_s { VkCommandBuffer cmdbuffer; VkFence fence; // for ctx->cmdbuffer only vulkan_renderpass_t renderpass; + struct qfv_stagebuf_s *staging[2]; VkPipeline pipeline; size_t curFrame; vulkan_framebufferset_t framebuffers; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 1d6c5eaea..36b013d97 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -215,6 +215,7 @@ libs_video_renderer_vid_render_vulkan_la_DEPENDENCIES=$(vulkan_libs) libs_video_renderer_vid_render_vulkan_la_SOURCES = \ $(video_renderer_common_sources) \ libs/video/renderer/vid_render_vulkan.c \ + libs/video/renderer/vulkan/barrier.c \ libs/video/renderer/vulkan/buffer.c \ libs/video/renderer/vulkan/command.c \ libs/video/renderer/vulkan/descriptor.c \ @@ -226,6 +227,7 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/pipeline.c \ libs/video/renderer/vulkan/renderpass.c \ libs/video/renderer/vulkan/shader.c \ + libs/video/renderer/vulkan/staging.c \ libs/video/renderer/vulkan/swapchain.c \ libs/video/renderer/vulkan/util.c \ libs/video/renderer/vulkan/util.h \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index f84f9eb84..64d8f3766 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -62,6 +62,7 @@ vulkan_R_Init (void) qfv_device_t *device = vulkan_ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_CreateFramebuffers (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c new file mode 100644 index 000000000..c7c1f21a3 --- /dev/null +++ b/libs/video/renderer/vulkan/barrier.c @@ -0,0 +1,92 @@ +/* + barrier.c + + Memory barrier helpers + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/barrier.h" + +const VkImageMemoryBarrier imageLayoutTransitionBarriers[] = { + // undefined -> transfer dst optimal + { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + // transfer dst optimal -> shader read only optimal + { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + // undefined -> depth stencil attachment optimal + { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 } + }, + // undefined -> color attachment optimal + { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + { /* end of transition barriers */ } +}; + +const qfv_pipelinestagepair_t imageLayoutTransitionStages[] = { + // undefined -> transfer dst optimal + { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT }, + // preinitialized -> shader read only optimal + { VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, + // transfer dst optimal -> shader read only optimal + { VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, + // undefined -> depth stencil attachment optimal + { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT }, + // undefined -> color attachment optimal + { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }, +}; diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c new file mode 100644 index 000000000..de791239c --- /dev/null +++ b/libs/video/renderer/vulkan/staging.c @@ -0,0 +1,96 @@ +/* + shader.c + + Vulkan shader manager + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/alloc.h" +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/qfplist.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/staging.h" + +#include "vid_vulkan.h" + +qfv_stagebuf_t * +QFV_CreateStagingBuffer (qfv_device_t *device, size_t size) +{ + qfv_devfuncs_t *dfunc = device->funcs; + + qfv_stagebuf_t *stage = malloc (sizeof (qfv_stagebuf_t)); + stage->device = device; + stage->buffer = QFV_CreateBuffer (device, size, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + stage->memory = QFV_AllocBufferMemory (device, stage->buffer, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + size, 0); + QFV_BindBufferMemory (device, stage->buffer, stage->memory, 0); + dfunc->vkMapMemory (device->dev, stage->memory, 0, size, 0, &stage->data); + return stage; +} + +void +QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage) +{ + qfv_device_t *device = stage->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkUnmapMemory (device->dev, stage->memory); + dfunc->vkFreeMemory (device->dev, stage->memory, 0); + dfunc->vkDestroyBuffer (device->dev, stage->buffer, 0); + free (stage); +} + +void +QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size) +{ + qfv_device_t *device = stage->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + stage->memory, offset, size + }; + dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index c2b17d0fe..c230955dc 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -53,6 +53,7 @@ #include "QF/va.h" #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/barrier.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/command.h" @@ -61,6 +62,7 @@ #include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/shader.h" +#include "QF/Vulkan/staging.h" #include "QF/Vulkan/swapchain.h" #include "compat.h" @@ -171,6 +173,8 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } + QFV_DestroyStagingBuffer (ctx->staging[0]); + QFV_DestroyStagingBuffer (ctx->staging[1]); ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, ctx->surface, 0); clear_table (&ctx->pipelineLayouts); @@ -194,6 +198,13 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) ctx->device = QFV_CreateDevice (ctx, device_extensions); } +void +Vulkan_CreateStagingBuffers (vulkan_ctx_t *ctx) +{ + ctx->staging[0] = QFV_CreateStagingBuffer (ctx->device, 1024*1024); + ctx->staging[1] = QFV_CreateStagingBuffer (ctx->device, 1024*1024); +} + void Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) { @@ -209,77 +220,6 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) } } -typedef struct { - VkPipelineStageFlags src; - VkPipelineStageFlags dst; -} qfv_pipelinestagepair_t; - -//XXX Note: imageLayoutTransitionBarriers, imageLayoutTransitionStages and -// the enum be kept in sync -enum { - qfv_LT_Undefined_to_TransferDst, - qfv_LT_TransferDst_to_ShaderReadOnly, - qfv_LT_Undefined_to_DepthStencil, - qfv_LT_Undefined_to_Color, -}; - -static VkImageMemoryBarrier imageLayoutTransitionBarriers[] = { - // undefined -> transfer dst optimal - { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - }, - // transfer dst optimal -> shader read only optimal - { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - }, - // undefined -> depth stencil attachment optimal - { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - 0, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT - | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, - { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 } - }, - // undefined -> color attachment optimal - { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - 0, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT - | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - }, - { /* end of transition barriers */ } -}; - -static qfv_pipelinestagepair_t imageLayoutTransitionStages[] = { - // undefined -> transfer dst optimal - { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT }, - // transfer dst optimal -> shader read only optimal - { VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, - // undefined -> depth stencil attachment optimal - { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT }, - // undefined -> color attachment optimal - { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }, -}; - static void qfv_load_pipeline (vulkan_ctx_t *ctx) { From b584d6f40381c6e223cef113aef7893dbf0abc01 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 11 Jan 2021 01:25:55 +0900 Subject: [PATCH 1183/3664] [vulkan] Abandon image "preinitialized" layout Turn's out it's not useful for transfers. I might bring it back when I figure out how to use it. --- include/QF/Vulkan/image.h | 3 +-- libs/video/renderer/vulkan/image.c | 8 +++----- libs/video/renderer/vulkan/qfpipeline.plist | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 3 +-- libs/video/renderer/vulkan/vulkan_vid_common.c | 4 ++-- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index dc6bc5eea..edb5e025e 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -37,8 +37,7 @@ VkImage QFV_CreateImage (struct qfv_device_s *device, int cubemap, uint32_t num_mipmaps, uint32_t num_layers, VkSampleCountFlagBits samples, - VkImageUsageFlags usage_scenarios, - int initialized); + VkImageUsageFlags usage_scenarios); VkDeviceMemory QFV_AllocImageMemory (struct qfv_device_s *device, VkImage image, diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index a60435a9d..68decb94a 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -69,8 +69,7 @@ QFV_CreateImage (qfv_device_t *device, int cubemap, uint32_t num_mipmaps, uint32_t num_layers, VkSampleCountFlagBits samples, - VkImageUsageFlags usage_scenarios, - int initialized) + VkImageUsageFlags usage_scenarios) { VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; @@ -80,12 +79,11 @@ QFV_CreateImage (qfv_device_t *device, int cubemap, type, format, size, num_mipmaps, cubemap ? 6 * num_layers : num_layers, samples, - initialized ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_TILING_OPTIMAL, usage_scenarios, VK_SHARING_MODE_EXCLUSIVE, 0, 0, - initialized ? VK_IMAGE_LAYOUT_PREINITIALIZED - : VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_UNDEFINED, }; VkImage image; dfunc->vkCreateImage (dev, &createInfo, 0, &image); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 03a4243b2..819492c93 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -26,7 +26,7 @@ minLod = 0; maxLod = 0.25f; borderColor = float_transparent_black; - unnormalizedCoordinates = 0;//FIXME false!!! + unnormalizedCoordinates = 1;//FIXME true!!! }; }; descriptorPools = { diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 7f5e11111..634e401eb 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -142,8 +142,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT, - 1); + | VK_IMAGE_USAGE_SAMPLED_BIT); conchars_memory = QFV_AllocImageMemory (device, conchars_image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index c230955dc..e35d5765c 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -261,7 +261,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, sc->format, extent, 1, 1, ctx->msaaSamples, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT - | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0); + | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); colorImage->object = QFV_AllocImageMemory (device, colorImage->image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); @@ -278,7 +278,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) depthImage->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, depthFormat, extent, 1, 1, ctx->msaaSamples, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0); + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); depthImage->object = QFV_AllocImageMemory (device, depthImage->image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); From 88d48944cb7791f96bd568ac6619a3a382e24d51 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 11 Jan 2021 01:27:40 +0900 Subject: [PATCH 1184/3664] [vulkan] Upload the default character set Nothing's shown yet, and the code is a tad messy, but it's serving as a proof of concept for now. --- libs/video/renderer/vulkan/vulkan_draw.c | 65 +++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 634e401eb..a7459bd4c 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -52,9 +52,11 @@ #include "compat.h" #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/barrier.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/staging.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -134,10 +136,13 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) Sys_RegisterShutdown (Vulkan_Draw_Shutdown, ctx); qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkCommandBuffer cmd = ctx->cmdbuffer; + qpic_t *charspic = Draw_Font8x8Pic (); VkExtent3D extent = { charspic->width, charspic->height, 1 }; conchars_image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - VK_FORMAT_A8B8G8R8_UNORM_PACK32, + VK_FORMAT_A1R5G5B5_UNORM_PACK16, extent, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT @@ -149,10 +154,66 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) QFV_BindImageMemory (device, conchars_image, conchars_memory, 0); conchars_view = QFV_CreateImageView (device, conchars_image, VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_A8B8G8R8_UNORM_PACK32, + VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT); conchars_sampler = Hash_Find (ctx->samplers, "quakepic"); + uint16_t *chars_data = ctx->staging[0]->data; + size_t size = charspic->width * charspic->height; + for (size_t i = 0; i < size; i++) { + // convert 0xff = transparent, 0xfe = white to 0x0000 and 0xffff + // for a1r5g5b5 + uint16_t pix = (charspic->data[i] & 1) - 1; + chars_data[i] = ~pix; + } + QFV_FlushStagingBuffer (ctx->staging[0], 0, size); + VkImageMemoryBarrier barrier; + qfv_pipelinestagepair_t stages; + dfunc->vkWaitForFences (device->dev, 1, &ctx->fence, VK_TRUE, ~0ull); + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; + barrier=imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + barrier.image = conchars_image; + dfunc->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, + 0, 0, + 0, 0, + 1, &barrier); + + VkBufferImageCopy region = { + 0, 0, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, + { 0, 0, 0 }, + { charspic->width, charspic->height, 1 }, + }; + dfunc->vkCmdCopyBufferToImage (cmd, + ctx->staging[0]->buffer, conchars_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ®ion); + + stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier.image = conchars_image; + dfunc->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, + 0, 0, + 0, 0, + 1, &barrier); + dfunc->vkEndCommandBuffer (cmd); + + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + 0, 0, 0, + 1, &cmd, + 0, 0, + }; + dfunc->vkResetFences (device->dev, 1, &ctx->fence); + dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, ctx->fence); + twod = Vulkan_CreatePipeline (ctx, "twod"); handleref_t *h; From 6e636a27d06e8aef530af862eeb29c732a178a42 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 11 Jan 2021 16:57:31 +0900 Subject: [PATCH 1185/3664] [renderer] Continue the job of merging SCR_UpdateScreen I think this is probably as merged as it will get (though the update callbacks can probably do with some merging). --- include/QF/plugin/vid_render.h | 4 +-- include/QF/screen.h | 3 +++ include/r_internal.h | 2 +- libs/video/renderer/gl/gl_screen.c | 34 +++++-------------------- libs/video/renderer/gl/namehack.h | 4 +-- libs/video/renderer/glsl/glsl_screen.c | 18 +++---------- libs/video/renderer/glsl/namehack.h | 4 +-- libs/video/renderer/r_screen.c | 31 ++++++++++++++++++++++ libs/video/renderer/sw/screen.c | 30 +--------------------- libs/video/renderer/sw32/namehack.h | 4 +-- libs/video/renderer/sw32/screen.c | 30 +--------------------- libs/video/renderer/vid_render_gl.c | 2 +- libs/video/renderer/vid_render_glsl.c | 2 +- libs/video/renderer/vid_render_sw.c | 2 +- libs/video/renderer/vid_render_sw32.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 4 +-- libs/video/renderer/vulkan/namehack.h | 2 -- nq/source/cl_screen.c | 2 +- qw/source/cl_screen.c | 2 +- ruamoko/qwaq/builtins/qwaq-bi.c | 2 +- 20 files changed, 63 insertions(+), 121 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 6de6e9af7..fc011a8b6 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -130,9 +130,6 @@ typedef struct vid_render_funcs_s { void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); - // scr_funcs is a null terminated array - void (*SCR_UpdateScreen) (double realtime, SCR_Func scr_3dfunc, - SCR_Func *scr_funcs); void (*SCR_DrawRam) (void); void (*SCR_DrawTurtle) (void); void (*SCR_DrawPause) (void); @@ -146,6 +143,7 @@ typedef struct vid_render_funcs_s { void (*Fog_ParseWorldspawn) (struct plitem_s *worldspawn); void (*R_Init) (void); + void (*R_RenderFrame) (SCR_Func scr_3dfunc, SCR_Func *scr_funcs); void (*R_ClearState) (void); void (*R_LoadSkys) (const char *); void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); diff --git a/include/QF/screen.h b/include/QF/screen.h index 8dda2deb4..b904f1c7c 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -35,6 +35,9 @@ void SCR_Init_Cvars (void); void SCR_Init (void); typedef void (*SCR_Func)(void); +// scr_funcs is a null terminated array +void SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, + SCR_Func *scr_funcs); void SCR_SizeUp (void); void SCR_SizeDown (void); diff --git a/include/r_internal.h b/include/r_internal.h index 547d4d1bf..de11978fa 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -44,7 +44,7 @@ void gl_R_Init (void); void glsl_R_Init (void); void sw_R_Init (void); void sw32_R_Init (void); - +void R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs); void R_Init_Cvars (void); void R_InitEfrags (void); void R_ClearState (void); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index fbe47106f..5758b5941 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -188,37 +188,23 @@ SCR_TileClear (void) } } -/* - SCR_UpdateScreen - - This is called every frame, and can also be called explicitly to flush - text to the screen. - - WARNING: be very careful calling this from elsewhere, because the refresh - needs almost the entire 256k of stack space! -*/ void -gl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +gl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) { double time1 = 0, time2; static int begun = 0; - if (scr_skipupdate) - return; - - if (begun) + if (begun) { gl_ctx->end_rendering (); - - vr_data.realtime = realtime; + begun = 0; + } vid.numpages = 2 + gl_triplebuffer->int_val; - scr_copytop = 0; + //FIXME forces the status bar to redraw. needed because it does not fully + //update in sw modes but must in gl mode vr_data.scr_copyeverything = 1; - if (!scr_initialized) - return; // not initialized yet - begun = 1; if (r_speeds->int_val) { @@ -227,14 +213,6 @@ gl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) gl_c_alias_polys = 0; } - if (oldfov != scr_fov->value) { // determine size of refresh window - oldfov = scr_fov->value; - vid.recalc_refdef = true; - } - - if (vid.recalc_refdef) - SCR_CalcRefdef (); - // do 3D refresh drawing, and then update the screen scr_3dfunc (); diff --git a/libs/video/renderer/gl/namehack.h b/libs/video/renderer/gl/namehack.h index 075e31836..e33d0aef6 100644 --- a/libs/video/renderer/gl/namehack.h +++ b/libs/video/renderer/gl/namehack.h @@ -69,7 +69,7 @@ #define SCR_CaptureBGR gl_SCR_CaptureBGR #define SCR_ScreenShot gl_SCR_ScreenShot #define SCR_ScreenShot_f gl_SCR_ScreenShot_f -#define SCR_UpdateScreen gl_SCR_UpdateScreen +#define R_RenderFrame gl_R_RenderFrame #define c_alias_polys gl_c_alias_polys #define c_brush_polys gl_c_brush_polys #define r_easter_eggs_f gl_r_easter_eggs_f @@ -125,7 +125,7 @@ #undef SCR_CaptureBGR #undef SCR_ScreenShot #undef SCR_ScreenShot_f -#undef SCR_UpdateScreen +#undef R_RenderFrame #undef c_alias_polys #undef c_brush_polys #undef r_easter_eggs_f diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index 89276999d..098f6a816 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -155,8 +155,7 @@ SCR_TileClear (void) } void -glsl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, - SCR_Func *scr_funcs) +glsl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) { static int begun = 0; @@ -169,23 +168,14 @@ glsl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, glsl_ctx->end_rendering (); } - vr_data.realtime = realtime; - vr_data.scr_copyeverything = 1; //FIXME useless cvar? vid.numpages = 2 + gl_triplebuffer->int_val; - if (!scr_initialized) - return; - qfeglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); begun = 1; - - if (oldfov != scr_fov->value) { - oldfov = scr_fov->value; - vid.recalc_refdef = true; - } - if (vid.recalc_refdef) - SCR_CalcRefdef (); + //FIXME forces the status bar to redraw. needed because it does not fully + //update in sw modes but must in glsl mode + vr_data.scr_copyeverything = 1; scr_3dfunc (); diff --git a/libs/video/renderer/glsl/namehack.h b/libs/video/renderer/glsl/namehack.h index 7edaed944..aed6d2e21 100644 --- a/libs/video/renderer/glsl/namehack.h +++ b/libs/video/renderer/glsl/namehack.h @@ -72,7 +72,7 @@ #define SCR_CaptureBGR glsl_SCR_CaptureBGR #define SCR_ScreenShot glsl_SCR_ScreenShot #define SCR_ScreenShot_f glsl_SCR_ScreenShot_f -#define SCR_UpdateScreen glsl_SCR_UpdateScreen +#define R_RenderFrame glsl_R_RenderFrame #define c_alias_polys glsl_c_alias_polys #define c_brush_polys glsl_c_brush_polys #define r_easter_eggs_f glsl_r_easter_eggs_f @@ -128,7 +128,7 @@ #undef SCR_CaptureBGR #undef SCR_ScreenShot #undef SCR_ScreenShot_f -#undef SCR_UpdateScreen +#undef R_RenderFrame #undef c_alias_polys #undef c_brush_polys #undef r_easter_eggs_f diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 6eb307229..db6dcbcf7 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -170,6 +170,37 @@ SCR_CalcRefdef (void) vr_funcs->R_ViewChanged (vid.aspect); } +/* + SCR_UpdateScreen + + This is called every frame, and can also be called explicitly to flush + text to the screen. + + WARNING: be very careful calling this from elsewhere, because the refresh + needs almost the entire 256k of stack space! +*/ +void +SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +{ + if (scr_skipupdate || !scr_initialized) { + return; + } + + vr_data.realtime = realtime; + scr_copytop = vr_data.scr_copyeverything = 0; + + if (oldfov != scr_fov->value) { + oldfov = scr_fov->value; + vid.recalc_refdef = true; + } + + if (vid.recalc_refdef) { + SCR_CalcRefdef (); + } + + vr_funcs->R_RenderFrame (scr_3dfunc, scr_funcs); +} + float CalcFov (float fov_x, float width, float height) { diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 5b69e7a0d..4ab9302c1 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -178,39 +178,11 @@ SCR_ScreenShot_f (void) dstring_delete (pcxname); } -/* - SCR_UpdateScreen - - This is called every frame, and can also be called explicitly to flush - text to the screen. - - WARNING: be very careful calling this from elsewhere, because the refresh - needs almost the entire 256k of stack space! -*/ void -SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) { vrect_t vrect; - if (scr_skipupdate) - return; - - vr_data.realtime = realtime; - - scr_copytop = 0; - vr_data.scr_copyeverything = 0; - - if (!scr_initialized) - return; // not initialized yet - - if (oldfov != scr_fov->value) { // determine size of refresh window - oldfov = scr_fov->value; - vid.recalc_refdef = true; - } - - if (vid.recalc_refdef) - SCR_CalcRefdef (); - // do 3D refresh drawing, and then update the screen D_EnableBackBufferAccess (); // of all overlay stuff if drawing // directly diff --git a/libs/video/renderer/sw32/namehack.h b/libs/video/renderer/sw32/namehack.h index cbdb673ce..6642d2d54 100644 --- a/libs/video/renderer/sw32/namehack.h +++ b/libs/video/renderer/sw32/namehack.h @@ -110,7 +110,7 @@ #define SCR_CaptureBGR sw32_SCR_CaptureBGR #define SCR_ScreenShot sw32_SCR_ScreenShot #define SCR_ScreenShot_f sw32_SCR_ScreenShot_f -#define SCR_UpdateScreen sw32_SCR_UpdateScreen +#define R_RenderFrame sw32_R_RenderFrame #define TransformVector sw32_TransformVector #define Turbulent sw32_Turbulent #define acolormap sw32_acolormap @@ -351,7 +351,7 @@ extern struct surf_s *sw32_surfaces; #undef SCR_CaptureBGR #undef SCR_ScreenShot #undef SCR_ScreenShot_f -#undef SCR_UpdateScreen +#undef R_RenderFrame #undef TransformVector #undef Turbulent #undef VID_InitBuffers diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index e4779d8da..543c8602a 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -136,39 +136,11 @@ sw32_SCR_ScreenShot_f (void) dstring_delete (pcxname); } -/* - SCR_UpdateScreen - - This is called every frame, and can also be called explicitly to flush - text to the screen. - - WARNING: be very careful calling this from elsewhere, because the refresh - needs almost the entire 256k of stack space! -*/ void -sw32_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +sw32_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) { vrect_t vrect; - if (scr_skipupdate) - return; - - vr_data.realtime = realtime; - - scr_copytop = 0; - vr_data.scr_copyeverything = 0; - - if (!scr_initialized) - return; // not initialized yet - - if (oldfov != scr_fov->value) { // determine size of refresh window - oldfov = scr_fov->value; - vid.recalc_refdef = true; - } - - if (vid.recalc_refdef) - SCR_CalcRefdef (); - // do 3D refresh drawing, and then update the screen sw32_D_EnableBackBufferAccess (); // of all overlay stuff if drawing // directly diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 434588894..c27b5d4ac 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -93,7 +93,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_Picf, gl_Draw_SubPic, - gl_SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, SCR_DrawPause, @@ -105,6 +104,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Fog_ParseWorldspawn, gl_R_Init, + gl_R_RenderFrame, gl_R_ClearState, gl_R_LoadSkys, gl_R_NewMap, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index f8ca47174..e3b549e35 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -93,7 +93,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_Picf, glsl_Draw_SubPic, - glsl_SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, SCR_DrawPause, @@ -105,6 +104,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Fog_ParseWorldspawn, glsl_R_Init, + glsl_R_RenderFrame, glsl_R_ClearState, glsl_R_LoadSkys, glsl_R_NewMap, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index a418d200c..5c9264381 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -86,7 +86,6 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_Picf, Draw_SubPic, - SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, SCR_DrawPause, @@ -98,6 +97,7 @@ vid_render_funcs_t sw_vid_render_funcs = { 0, sw_R_Init, + R_RenderFrame, R_ClearState, R_LoadSkys, R_NewMap, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 9fffb0298..be727c8a9 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -91,7 +91,6 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_Draw_Picf, sw32_Draw_SubPic, - sw32_SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, SCR_DrawPause, @@ -103,6 +102,7 @@ vid_render_funcs_t sw32_vid_render_funcs = { 0, sw32_R_Init, + sw32_R_RenderFrame, sw32_R_ClearState, sw32_R_LoadSkys, sw32_R_NewMap, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 64d8f3766..a61a911a2 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -105,7 +105,7 @@ vulkan_R_Init (void) } static void -vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void)) +vulkan_R_RenderFrame (void (*f)(void), void (**g)(void)) { static int count = 0; static double startTime; @@ -324,7 +324,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_Picf, vulkan_Draw_SubPic, - vulkan_SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, SCR_DrawPause, @@ -336,6 +335,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { 0,//vulkan_Fog_ParseWorldspawn, vulkan_R_Init, + vulkan_R_RenderFrame, 0,//vulkan_R_ClearState, 0,//vulkan_R_LoadSkys, 0,//vulkan_R_NewMap, diff --git a/libs/video/renderer/vulkan/namehack.h b/libs/video/renderer/vulkan/namehack.h index 7289995f2..17f107080 100644 --- a/libs/video/renderer/vulkan/namehack.h +++ b/libs/video/renderer/vulkan/namehack.h @@ -72,7 +72,6 @@ #define SCR_CaptureBGR vulkan_SCR_CaptureBGR #define SCR_ScreenShot vulkan_SCR_ScreenShot #define SCR_ScreenShot_f vulkan_SCR_ScreenShot_f -#define SCR_UpdateScreen vulkan_SCR_UpdateScreen #define c_alias_polys vulkan_c_alias_polys #define c_brush_polys vulkan_c_brush_polys #define r_easter_eggs_f vulkan_r_easter_eggs_f @@ -128,7 +127,6 @@ #undef SCR_CaptureBGR #undef SCR_ScreenShot #undef SCR_ScreenShot_f -#undef SCR_UpdateScreen #undef c_alias_polys #undef c_brush_polys #undef r_easter_eggs_f diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index c7940e305..509352a1c 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -146,5 +146,5 @@ CL_UpdateScreen (double realtime) scr_funcs_normal[3] = r_funcs->SCR_DrawPause; V_PrepBlend (); - r_funcs->SCR_UpdateScreen (realtime, V_RenderView, scr_funcs[index]); + SCR_UpdateScreen (realtime, V_RenderView, scr_funcs[index]); } diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 5b81f65a7..7827c30db 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -147,5 +147,5 @@ CL_UpdateScreen (double realtime) scr_funcs_normal[3] = r_funcs->SCR_DrawPause; V_PrepBlend (); - r_funcs->SCR_UpdateScreen (realtime, V_RenderView, scr_funcs[index]); + SCR_UpdateScreen (realtime, V_RenderView, scr_funcs[index]); } diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c index 27a7ae04f..a78dd7763 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/qwaq-bi.c @@ -127,7 +127,7 @@ bi_refresh (progs_t *pr) IN_ProcessEvents (); //GIB_Thread_Execute (); Cbuf_Execute_Stack (qwaq_cbuf); - r_funcs->SCR_UpdateScreen (con_realtime, bi_3d, bi_2dfuncs); + SCR_UpdateScreen (con_realtime, bi_3d, bi_2dfuncs); R_FLOAT (pr) = con_frametime; } From bf4613acd5b2e57b01c2081ea49a93e6da25cbbd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 10:43:05 +0900 Subject: [PATCH 1186/3664] [vulkan] Remove missed preinitialized stages --- libs/video/renderer/vulkan/barrier.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c index c7c1f21a3..e257eb990 100644 --- a/libs/video/renderer/vulkan/barrier.c +++ b/libs/video/renderer/vulkan/barrier.c @@ -77,9 +77,6 @@ const qfv_pipelinestagepair_t imageLayoutTransitionStages[] = { // undefined -> transfer dst optimal { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT }, - // preinitialized -> shader read only optimal - { VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, // transfer dst optimal -> shader read only optimal { VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, From 8f6f32981c0d9b7034ebfd00585fa2722f2541ac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 11:26:20 +0900 Subject: [PATCH 1187/3664] [vulkan] Add some matrix buffers It seems they could all be in the one buffer: there are indications that uniform binding can be fairly fine-grained. I need to investigate that. --- include/QF/Vulkan/qf_vid.h | 4 + include/vid_vulkan.h | 12 ++ libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vid_render_vulkan.c | 9 +- libs/video/renderer/vulkan/vulkan_matrices.c | 204 ++++++++++++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 1 + 6 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 libs/video/renderer/vulkan/vulkan_matrices.c diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index d5f59cc84..7e30a3a57 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -41,6 +41,10 @@ void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); VkPipeline Vulkan_CreatePipeline (struct vulkan_ctx_s *ctx, const char *name); +void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx); +void Vulkan_DestroyMatrices (struct vulkan_ctx_s *ctx); +void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx, float aspect); +void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 05e127825..3ffa0052c 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -24,6 +24,15 @@ typedef struct vulkan_framebuffer_s { VkDescriptorSet twodDescriptors; } vulkan_framebuffer_t; +typedef struct vulkan_matrices_s { + VkBuffer buffer_2d; + VkBuffer buffer_3d; + VkDeviceMemory memory; + float *projection_2d; + float *projection_3d; + float *view_3d; +} vulkan_matrices_t; + typedef struct vulkan_framebufferset_s DARRAY_TYPE (vulkan_framebuffer_t) vulkan_framebufferset_t; @@ -62,6 +71,9 @@ typedef struct vulkan_ctx_s { size_t curFrame; vulkan_framebufferset_t framebuffers; + // projection and view matrices (model is push constant) + vulkan_matrices_t matrices; + #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 36b013d97..d6187a93a 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -233,6 +233,7 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/util.h \ libs/video/renderer/vulkan/vkparse.c \ libs/video/renderer/vulkan/vulkan_draw.c \ + libs/video/renderer/vulkan/vulkan_matrices.c \ libs/video/renderer/vulkan/vulkan_vid_common.c libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vkparse_src) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a61a911a2..77368d093 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -63,6 +63,7 @@ vulkan_R_Init (void) qfv_devfuncs_t *dfunc = device->funcs; Vulkan_CreateStagingBuffers (vulkan_ctx); + Vulkan_CreateMatrices (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_CreateFramebuffers (vulkan_ctx); @@ -276,6 +277,12 @@ vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, in Vulkan_Draw_SubPic (x, y, pic, srcx, srcy, width, height, vulkan_ctx); } +static void +vulkan_R_ViewChanged (float aspect) +{ + Vulkan_CalcProjectionMatrices (vulkan_ctx, aspect); +} + static vid_model_funcs_t model_funcs = { 0,//vulkan_Mod_LoadExternalTextures, 0,//vulkan_Mod_LoadLighting, @@ -347,7 +354,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { R_AllocEntity, 0,//vulkan_R_RenderView, R_DecayLights, - 0,//vulkan_R_ViewChanged, + vulkan_R_ViewChanged, 0,//vulkan_R_ClearParticles, 0,//vulkan_R_InitParticles, 0,//vulkan_SCR_ScreenShot_f, diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c new file mode 100644 index 000000000..c734f82d0 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -0,0 +1,204 @@ +/* + vid_common_vulkan.c + + Common Vulkan video driver functions + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/mathlib.h" +#include "QF/sys.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/device.h" + +#include "compat.h" +#include "d_iface.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#include "util.h" + +#define MAT_SIZE (16 * sizeof (float)) + +static void +ortho_mat (float *proj, float xmin, float xmax, float ymin, float ymax, + float znear, float zfar) +{ + proj[0] = 2 / (xmax - xmin); + proj[4] = 0; + proj[8] = 0; + proj[12] = -(xmax + xmin) / (xmax - xmin); + + proj[1] = 0; + proj[5] = 2 / (ymax - ymin); + proj[9] = 0; + proj[13] = -(ymax + ymin) / (ymax - ymin); + + proj[2] = 0; + proj[6] = 0; + proj[10] = -2 / (zfar - znear); + proj[14] = -(zfar + znear) / (zfar - znear); + + proj[3] = 0; + proj[7] = 0; + proj[11] = 0; + proj[15] = 1; +} + +static void +persp_mat (float *proj, float xmin, float xmax, float ymin, float ymax, + float aspect) +{ + float fovx, fovy, neard, fard; + + fovx = r_refdef.fov_x; + fovy = r_refdef.fov_y; + neard = r_nearclip->value; + fard = r_farclip->value; + + ymax = neard * tan (fovy * M_PI / 360); // fov_2 / 2 + ymin = -ymax; + xmax = neard * tan (fovx * M_PI / 360); // fov_2 / 2 + xmin = -xmax; + + proj[0] = (2 * neard) / (xmax - xmin); + proj[4] = 0; + proj[8] = (xmax + xmin) / (xmax - xmin); + proj[12] = 0; + + proj[1] = 0; + proj[5] = (2 * neard) / (ymax - ymin); + proj[9] = (ymax + ymin) / (ymax - ymin); + proj[13] = 0; + + proj[2] = 0; + proj[6] = 0; + proj[10] = (fard + neard) / (neard - fard); + proj[14] = (2 * fard * neard) / (neard - fard); + + proj[3] = 0; + proj[7] = 0; + proj[11] = -1; + proj[15] = 0; +} + +void +Vulkan_DestroyMatrices (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + __auto_type mat = &ctx->matrices; + + dfunc->vkUnmapMemory (device->dev, mat->memory); + dfunc->vkFreeMemory (device->dev, mat->memory, 0); + dfunc->vkDestroyBuffer (device->dev, mat->buffer_2d, 0); + dfunc->vkDestroyBuffer (device->dev, mat->buffer_3d, 0); +} + +void +Vulkan_CreateMatrices (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + __auto_type mat = &ctx->matrices; + mat->buffer_2d = QFV_CreateBuffer (device, 1 * MAT_SIZE, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + mat->buffer_3d = QFV_CreateBuffer (device, 2 * MAT_SIZE, + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + size_t size = 0; + size_t offset; + VkMemoryRequirements req; + + dfunc->vkGetBufferMemoryRequirements (device->dev, mat->buffer_2d, &req); + size += req.size; + offset = size; + + dfunc->vkGetBufferMemoryRequirements (device->dev, mat->buffer_3d, &req); + offset = (offset + req.alignment - 1) & ~(req.alignment - 1); + size += req.size; + + mat->memory = QFV_AllocBufferMemory (device, mat->buffer_2d, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + size, 0); + QFV_BindBufferMemory (device, mat->buffer_2d, mat->memory, 0); + QFV_BindBufferMemory (device, mat->buffer_3d, mat->memory, offset); + void *data; + dfunc->vkMapMemory (device->dev, mat->memory, 0, size, 0, &data); + mat->projection_2d = data; + mat->projection_3d = mat->projection_2d + offset / sizeof (float); + mat->view_3d = mat->projection_3d + 16; +} + +void +Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx, float aspect) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + __auto_type mat = &ctx->matrices; + + int width = vid.conwidth; + int height = vid.conheight; + + ortho_mat (mat->projection_2d, 0, width, 0, height, -99999, 99999); + persp_mat (mat->projection_3d, 0, width, 0, height, aspect); + + Sys_MaskPrintf (SYS_VULKAN, "ortho:\n"); + Sys_MaskPrintf (SYS_VULKAN, " [[%g, %g, %g, %g],\n", + QuatExpand (mat->projection_2d + 0)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + QuatExpand (mat->projection_2d + 4)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + QuatExpand (mat->projection_2d + 8)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g]]\n", + QuatExpand (mat->projection_2d + 12)); + Sys_MaskPrintf (SYS_VULKAN, "presp:\n"); + Sys_MaskPrintf (SYS_VULKAN, " [[%g, %g, %g, %g],\n", + QuatExpand (mat->projection_3d + 0)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + QuatExpand (mat->projection_3d + 4)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + QuatExpand (mat->projection_3d + 8)); + Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g]]\n", + QuatExpand (mat->projection_3d + 12)); + + VkMappedMemoryRange ranges[] = { + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, 0, MAT_SIZE }, + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, + (mat->projection_3d - mat->projection_2d) * sizeof (float), + MAT_SIZE}, + }; + dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index e35d5765c..c166c239b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -175,6 +175,7 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) } QFV_DestroyStagingBuffer (ctx->staging[0]); QFV_DestroyStagingBuffer (ctx->staging[1]); + Vulkan_DestroyMatrices (ctx); ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, ctx->surface, 0); clear_table (&ctx->pipelineLayouts); From bb4ca7683ee028a107d5cebae98f93186491f0ef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 11:27:41 +0900 Subject: [PATCH 1188/3664] [vulkan] Get the 2D pipeline up and running First pixels! This was a nightmare of little issues that the validation layers couldn't help with: incorrect input assembly, incorrect vertex attribute specs. Though the layers did help with getting the queues working. Still, lots of work to go but this is a major breakthrough as I now have access to visual debugging for textures and the like. --- include/QF/Vulkan/funclist.h | 8 + include/QF/Vulkan/qf_draw.h | 1 + include/vid_vulkan.h | 2 + libs/video/renderer/vid_render_vulkan.c | 67 ++-- libs/video/renderer/vulkan/qfpipeline.plist | 16 +- libs/video/renderer/vulkan/twod.vert | 9 +- libs/video/renderer/vulkan/vulkan_draw.c | 286 +++++++++++++++++- .../video/renderer/vulkan/vulkan_vid_common.c | 7 +- 8 files changed, 343 insertions(+), 53 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 8ab62852a..534097b5d 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -166,6 +166,14 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdClearColorImage) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdExecuteCommands) + +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetViewport) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindVertexBuffers) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindIndexBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindDescriptorSets) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDrawIndexed) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index b0297c2d0..c9e8b20ad 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -31,6 +31,7 @@ struct vulkan_ctx_s; void Vulkan_Draw_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Draw_Character (int x, int y, unsigned ch, struct vulkan_ctx_s *ctx); void Vulkan_Draw_String (int x, int y, const char *str, diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 3ffa0052c..784c74312 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -21,6 +21,8 @@ typedef struct vulkan_framebuffer_s { VkSemaphore renderDoneSemaphore; VkCommandBuffer cmdBuffer; + struct qfv_cmdbufferset_s *subCommand; + VkDescriptorSet twodDescriptors; } vulkan_framebuffer_t; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 77368d093..431f6e0b4 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -59,9 +59,6 @@ static vulkan_ctx_t *vulkan_ctx; static void vulkan_R_Init (void) { - qfv_device_t *device = vulkan_ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateMatrices (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); @@ -72,41 +69,18 @@ vulkan_R_Init (void) vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); Vulkan_Draw_Init (vulkan_ctx); - qfv_swapchain_t *sc = vulkan_ctx->swapchain; - - VkCommandBufferBeginInfo beginInfo - = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - VkClearValue clearValues[3] = { - { { {0.7294, 0.8549, 0.3333, 1.0} } }, - { { {1.0, 0.0} } }, - { { {0, 0, 0, 0} } }, - }; - VkRenderPassBeginInfo renderPassInfo = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, - vulkan_ctx->renderpass.renderpass, 0, - { {0, 0}, sc->extent }, - 2, clearValues + 2 - }; - for (size_t i = 0; i < vulkan_ctx->framebuffers.size; i++) { - __auto_type framebuffer = &vulkan_ctx->framebuffers.a[i]; - dfunc->vkBeginCommandBuffer (framebuffer->cmdBuffer, &beginInfo); - renderPassInfo.framebuffer = framebuffer->framebuffer; - dfunc->vkCmdBeginRenderPass (framebuffer->cmdBuffer, &renderPassInfo, - VK_SUBPASS_CONTENTS_INLINE); - - dfunc->vkCmdEndRenderPass (framebuffer->cmdBuffer); - dfunc->vkEndCommandBuffer (framebuffer->cmdBuffer); - } Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, vulkan_ctx->swapchain->numImages); for (int32_t i = 0; i < vulkan_ctx->swapchain->numImages; i++) { Sys_Printf (" %p", vulkan_ctx->swapchain->images->a[i]); } Sys_Printf ("\n"); + + SCR_Init (); } static void -vulkan_R_RenderFrame (void (*f)(void), void (**g)(void)) +vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) { static int count = 0; static double startTime; @@ -116,6 +90,12 @@ vulkan_R_RenderFrame (void (*f)(void), void (**g)(void)) VkDevice dev = device->dev; qfv_queue_t *queue = &vulkan_ctx->device->queue; + scr_3dfunc (); + while (*scr_funcs) { + (*scr_funcs) (); + scr_funcs++; + } + __auto_type framebuffer = &vulkan_ctx->framebuffers.a[vulkan_ctx->curFrame]; @@ -124,6 +104,34 @@ vulkan_R_RenderFrame (void (*f)(void), void (**g)(void)) framebuffer->imageAvailableSemaphore, 0, &imageIndex); + Vulkan_FlushText (vulkan_ctx); + + qfv_swapchain_t *sc = vulkan_ctx->swapchain; + VkCommandBufferBeginInfo beginInfo + = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + VkClearValue clearValues[2] = { + { { {0.0, 0.0, 0.0, 1.0} } }, + { { {1.0, 0.0} } }, + }; + VkRenderPassBeginInfo renderPassInfo = { + VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, + vulkan_ctx->renderpass.renderpass, 0, + { {0, 0}, sc->extent }, + 2, clearValues + }; + + dfunc->vkBeginCommandBuffer (framebuffer->cmdBuffer, &beginInfo); + renderPassInfo.framebuffer = framebuffer->framebuffer; + dfunc->vkCmdBeginRenderPass (framebuffer->cmdBuffer, &renderPassInfo, + VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); + + dfunc->vkCmdExecuteCommands (framebuffer->cmdBuffer, + framebuffer->subCommand->size, + framebuffer->subCommand->a); + + dfunc->vkCmdEndRenderPass (framebuffer->cmdBuffer); + dfunc->vkEndCommandBuffer (framebuffer->cmdBuffer); + VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submitInfo = { @@ -425,6 +433,7 @@ vulkan_vid_render_shutdown (void) QFV_DeviceWaitIdle (device); df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); + Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Shutdown_Common (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 819492c93..3d7ec1f10 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -24,7 +24,7 @@ compareEnable = 0;//FIXME false!!! compareOp = always; minLod = 0; - maxLod = 0.25f; + maxLod = 0; borderColor = float_transparent_black; unnormalizedCoordinates = 1;//FIXME true!!! }; @@ -113,20 +113,26 @@ { location = 0; binding = 0; - format = r32g32b32a32_sfloat; + format = r32g32_sfloat; offset = 0; }, { location = 1; binding = 0; + format = r32g32_sint; + offset = 8; + }, + { + location = 2; + binding = 0; format = r32g32b32a32_sfloat; - offset = 4; + offset = 16; }, ); }; inputAssembly = { - topology = triangle_list; - primitiveRestartEnable = 0; + topology = triangle_strip; + primitiveRestartEnable = 1; }; viewport = { viewports = ( diff --git a/libs/video/renderer/vulkan/twod.vert b/libs/video/renderer/vulkan/twod.vert index 83655d6a7..5db2990db 100644 --- a/libs/video/renderer/vulkan/twod.vert +++ b/libs/video/renderer/vulkan/twod.vert @@ -2,8 +2,6 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 Projection; - mat4 View; - mat4 Model; }; /** Vertex position. @@ -12,8 +10,9 @@ layout (set = 0, binding = 0) uniform Matrices { \a vertex provides the onscreen location at which to draw the icon (\a x, \a y) and texture coordinate for the icon (\a s=z, \a t=w). */ -layout (location = 0) in vec4 vertex; -layout (location = 1) in vec4 vcolor; +layout (location = 0) in vec2 vertex; +layout (location = 1) in ivec2 uv; +layout (location = 2) in vec4 vcolor; layout (location = 0) out vec2 st; layout (location = 1) out vec4 color; @@ -22,6 +21,6 @@ void main (void) { gl_Position = Projection * vec4 (vertex.xy, 0.0, 1.0); - st = vertex.zw; + st = vec2(uv); color = vcolor; } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index a7459bd4c..76cbb0c82 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -53,6 +53,8 @@ #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/command.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" @@ -62,13 +64,86 @@ #include "vid_vulkan.h" #include "vkparse.h" +typedef struct { + float xy[2]; + int st[2]; + float color[4]; +} drawvert_t; + +#define MAX_QUADS (65536) +#define VERTS_PER_QUAD (4) +#define INDS_PER_QUAD (5) // one per vert plus primitive reset + //FIXME move into a context struct VkImage conchars_image; VkDeviceMemory conchars_memory; VkImageView conchars_view; VkSampler conchars_sampler; -VkPipeline twod; +VkBuffer quad_vert_buffer; +VkBuffer quad_ind_buffer; +VkDeviceMemory quad_memory; +drawvert_t *quad_verts; +uint32_t *quad_inds; +uint32_t num_quads; + +VkPipeline twod_pipeline; +VkPipelineLayout twod_layout; +size_t draw_cmdBuffer; + +static void +create_quad_buffers (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + //FIXME quad_inds can be a completely separate buffer that is + //pre-initialized to draw 2-tri triangle strips as the actual indices will + //never change + size_t vert_size = MAX_QUADS * VERTS_PER_QUAD * sizeof (drawvert_t); + size_t ind_size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t); + + quad_vert_buffer = QFV_CreateBuffer (device, vert_size, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + quad_ind_buffer = QFV_CreateBuffer (device, ind_size, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + quad_memory = QFV_AllocBufferMemory (device, quad_vert_buffer, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + vert_size + ind_size, 0); + QFV_BindBufferMemory (device, quad_vert_buffer, quad_memory, 0); + QFV_BindBufferMemory (device, quad_ind_buffer, quad_memory, vert_size); + void *data; + dfunc->vkMapMemory (device->dev, quad_memory, 0, vert_size + ind_size, + 0, &data); + quad_verts = data; + quad_inds = (uint32_t *) (quad_verts + MAX_QUADS * VERTS_PER_QUAD); + // pre-initialize quad_inds as the indices will never change + uint32_t *ind = quad_inds; + for (int i = 0; i < MAX_QUADS; i++) { + for (int j = 0; j < VERTS_PER_QUAD; j++) { + *ind++ = i * VERTS_PER_QUAD + j; + } + // mark end of primitive + *ind++ = -1; + } + VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + quad_memory, vert_size, ind_size, + }; + dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); +} + +static void +destroy_quad_buffers (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkUnmapMemory (device->dev, quad_memory); + dfunc->vkFreeMemory (device->dev, quad_memory, 0); + dfunc->vkDestroyBuffer (device->dev, quad_vert_buffer, 0); + dfunc->vkDestroyBuffer (device->dev, quad_ind_buffer, 0); +} static qpic_t * pic_data (const char *name, int w, int h, const byte *data) @@ -117,14 +192,15 @@ Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, { } -static void -Vulkan_Draw_Shutdown (void *data) +void +Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) { - vulkan_ctx_t *ctx = data; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkDestroyPipeline (device->dev, twod, 0); + destroy_quad_buffers (ctx); + + dfunc->vkDestroyPipeline (device->dev, twod_pipeline, 0); dfunc->vkDestroyImageView (device->dev, conchars_view, 0); dfunc->vkFreeMemory (device->dev, conchars_memory, 0); dfunc->vkDestroyImage (device->dev, conchars_image, 0); @@ -133,12 +209,12 @@ Vulkan_Draw_Shutdown (void *data) void Vulkan_Draw_Init (vulkan_ctx_t *ctx) { - Sys_RegisterShutdown (Vulkan_Draw_Shutdown, ctx); - qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; VkCommandBuffer cmd = ctx->cmdbuffer; + create_quad_buffers (ctx); + qpic_t *charspic = Draw_Font8x8Pic (); VkExtent3D extent = { charspic->width, charspic->height, 1 }; conchars_image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, @@ -156,7 +232,9 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT); - conchars_sampler = Hash_Find (ctx->samplers, "quakepic"); + handleref_t *h; + h = Hash_Find (ctx->samplers, "quakepic"); + conchars_sampler = (VkSampler) h->handle; uint16_t *chars_data = ctx->staging[0]->data; size_t size = charspic->width * charspic->height; @@ -164,9 +242,9 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) // convert 0xff = transparent, 0xfe = white to 0x0000 and 0xffff // for a1r5g5b5 uint16_t pix = (charspic->data[i] & 1) - 1; - chars_data[i] = ~pix; + chars_data[i] = pix; } - QFV_FlushStagingBuffer (ctx->staging[0], 0, size); + QFV_FlushStagingBuffer (ctx->staging[0], 0, size * sizeof (uint16_t)); VkImageMemoryBarrier barrier; qfv_pipelinestagepair_t stages; dfunc->vkWaitForFences (device->dev, 1, &ctx->fence, VK_TRUE, ~0ull); @@ -214,9 +292,11 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dfunc->vkResetFences (device->dev, 1, &ctx->fence); dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, ctx->fence); - twod = Vulkan_CreatePipeline (ctx, "twod"); + twod_pipeline = Vulkan_CreatePipeline (ctx, "twod"); + + h = Hash_Find (ctx->pipelineLayouts, "twod"); + twod_layout = (VkPipelineLayout) h->handle; - handleref_t *h; __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (ctx->framebuffers.size, alloca); for (size_t i = 0; i < layouts->size; i++) { h = Hash_Find (ctx->setLayouts, "twod"); @@ -224,31 +304,167 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) } h = Hash_Find (ctx->descriptorPools, "twod"); __auto_type pool = (VkDescriptorPool) h->handle; + + VkDescriptorBufferInfo bufferInfo = { + ctx->matrices.buffer_2d, 0, VK_WHOLE_SIZE + }; + VkDescriptorImageInfo imageInfo = { + conchars_sampler, + conchars_view, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + __auto_type cmdBuffers + = QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, + ctx->framebuffers.size); + __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < ctx->framebuffers.size; i++) { - ctx->framebuffers.a[i].twodDescriptors = sets->a[i]; + __auto_type frame = &ctx->framebuffers.a[i]; + frame->twodDescriptors = sets->a[i]; + + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + frame->twodDescriptors, 0, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, &bufferInfo, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + frame->twodDescriptors, 1, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo, 0, 0 }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + draw_cmdBuffer = frame->subCommand->size; + DARRAY_APPEND (frame->subCommand, cmdBuffers->a[i]); } + free (sets); + free (cmdBuffers); +} + +static inline void +draw_pic (float x, float y, int w, int h, qpic_t *pic, + int srcx, int srcy, int srcw, int srch, + float *color) +{ + if (num_quads + VERTS_PER_QUAD > MAX_QUADS) { + return; + } + + drawvert_t *verts = quad_verts + num_quads * VERTS_PER_QUAD; + num_quads += VERTS_PER_QUAD; + + float sl = (srcx); + float sr = (srcx + srcw); + float st = (srcy); + float sb = (srcy + srch); + + verts[0].xy[0] = x; + verts[0].xy[1] = y; + verts[0].st[0] = sl; + verts[0].st[1] = st; + QuatCopy (color, verts[0].color); + + verts[1].xy[0] = x; + verts[1].xy[1] = y + h; + verts[1].st[0] = sl; + verts[1].st[1] = sb; + QuatCopy (color, verts[1].color); + + verts[2].xy[0] = x + w; + verts[2].xy[1] = y; + verts[2].st[0] = sr; + verts[2].st[1] = st; + QuatCopy (color, verts[2].color); + + verts[3].xy[0] = x + w; + verts[3].xy[1] = y + h; + verts[3].st[0] = sr; + verts[3].st[1] = sb; + QuatCopy (color, verts[3].color); +} + +static inline void +queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx) +{ + quat_t color = {1, 1, 1, 1}; + int cx, cy; + cx = chr % 16; + cy = chr / 16; + + draw_pic (x, y, 8, 8, 0/*FIXME*/, cx * 8, cy * 8, 8, 8, color); } void Vulkan_Draw_Character (int x, int y, unsigned int chr, vulkan_ctx_t *ctx) { + if (chr == ' ') { + return; + } + if (y <= -8 || y >= vid.conheight) { + return; + } + if (x <= -8 || x >= vid.conwidth) { + return; + } + queue_character (x, y, chr, ctx); } void Vulkan_Draw_String (int x, int y, const char *str, vulkan_ctx_t *ctx) { + byte chr; + + if (!str || !str[0]) { + return; + } + if (y <= -8 || y >= vid.conheight) { + return; + } + while (*str) { + if ((chr = *str++) != ' ' && x >= -8 && x < vid.conwidth) { + queue_character (x, y, chr, ctx); + } + x += 8; + } } void Vulkan_Draw_nString (int x, int y, const char *str, int count, vulkan_ctx_t *ctx) { + byte chr; + + if (!str || !str[0]) { + return; + } + if (y <= -8 || y >= vid.conheight) { + return; + } + while (count-- > 0 && *str) { + if ((chr = *str++) != ' ' && x >= -8 && x < vid.conwidth) { + queue_character (x, y, chr, ctx); + } + x += 8; + } } void Vulkan_Draw_AltString (int x, int y, const char *str, vulkan_ctx_t *ctx) { + byte chr; + + if (!str || !str[0]) { + return; + } + if (y <= -8 || y >= vid.conheight) { + return; + } + while (*str) { + if ((chr = *str++ | 0x80) != (' ' | 0x80) + && x >= -8 && x < vid.conwidth) { + queue_character (x, y, chr, ctx); + } + x += 8; + } } void @@ -321,6 +537,50 @@ Vulkan_DrawReset (vulkan_ctx_t *ctx) void Vulkan_FlushText (vulkan_ctx_t *ctx) { + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type frame = &ctx->framebuffers.a[ctx->curFrame]; + VkCommandBuffer cmd = frame->subCommand->a[draw_cmdBuffer]; + + VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + quad_memory, 0, num_quads * VERTS_PER_QUAD * sizeof (drawvert_t), + }; + dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + ctx->renderpass.renderpass, 0, + frame->framebuffer, + 0, 0, 0 + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + twod_pipeline); + VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; + VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; + dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &quad_vert_buffer, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, quad_ind_buffer, 0, + VK_INDEX_TYPE_UINT32); + VkDescriptorSet set = frame->twodDescriptors; + VkPipelineLayout layout = twod_layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 1, &set, 0, 0); + dfunc->vkCmdDrawIndexed (cmd, num_quads * INDS_PER_QUAD, 1, 0, 0, 0); + + dfunc->vkEndCommandBuffer (cmd); + + num_quads = 0; } void diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index c166c239b..126d602fd 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -3,7 +3,6 @@ Common Vulkan video driver functions - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2019 Bill Currie This program is free software; you can redistribute it and/or @@ -54,6 +53,7 @@ #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" +#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/command.h" @@ -127,6 +127,7 @@ Vulkan_Init_Cvars (void) msaaSamples = Cvar_Get ("msaaSamples", "VK_SAMPLE_COUNT_1_BIT", CVAR_NONE, msaaSamples_f, "desired MSAA sample size."); + R_Init_Cvars (); } static const char *instance_extensions[] = { @@ -415,7 +416,11 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); frame->renderDoneSemaphore = QFV_CreateSemaphore (device); frame->cmdBuffer = cmdBuffers->a[i]; + + frame->subCommand = malloc (sizeof (qfv_cmdbufferset_t)); + DARRAY_INIT (frame->subCommand, 4); } + free (cmdBuffers); } void From 03f614ccb90bd99243c83674c7a05fb7ff7fd129 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 13:07:51 +0900 Subject: [PATCH 1189/3664] [vulkan] Parse VkBool32 correctly as bool type This makes it much clearer whether something is just a flag or an index of some sort. --- libs/video/renderer/vulkan/qfpipeline.plist | 32 ++++++++++----------- libs/video/renderer/vulkan/vkgen/vkalias.r | 22 ++++++++++++-- libs/video/renderer/vulkan/vkgen/vkenum.r | 6 ++++ libs/video/renderer/vulkan/vkgen/vkgen.r | 5 +++- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 3d7ec1f10..437ab5854 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -19,14 +19,14 @@ addressModeV = clamp_to_edge; addressModeW = clamp_to_edge; mipLodBias = 0; - anisotropyEnable = 0;//FIXME false!!! + anisotropyEnable = false; maxAnisotropy = 0; - compareEnable = 0;//FIXME false!!! + compareEnable = false; compareOp = always; minLod = 0; maxLod = 0; borderColor = float_transparent_black; - unnormalizedCoordinates = 1;//FIXME true!!! + unnormalizedCoordinates = true; }; }; descriptorPools = { @@ -132,7 +132,7 @@ }; inputAssembly = { topology = triangle_strip; - primitiveRestartEnable = 1; + primitiveRestartEnable = true; }; viewport = { viewports = ( @@ -150,32 +150,32 @@ ); }; rasterization = { - depthClampEnable = 0; - rasterizerDiscardEnable = 0; + depthClampEnable = false; + rasterizerDiscardEnable = false; polygonMode = fill; cullMode = back; frontFace = counter_clockwise; - depthBiasEnable = 0; + depthBiasEnable = false; lineWidth = 1; }; multisample = { rasterizationSamples = $msaaSamples; - sampleShadingEnable = 0; + sampleShadingEnable = false; minSampleShading = 0.5f; - alphaToCoverageEnable = 0; - alphaToOneEnable = 0; + alphaToCoverageEnable = false; + alphaToOneEnable = false; }; depthStencil = { - depthTestEnable = 1; - depthWriteEnable = 1; + depthTestEnable = true; + depthWriteEnable = true; depthCompareOp = less; - depthBoundsTestEnable = 0; - stencilTestEnable = 0; + depthBoundsTestEnable = false; + stencilTestEnable = false; }; colorBlend = { - logicOpEnable = 0; + logicOpEnable = false; attachments = ({ - blendEnable = 0; + blendEnable = false; srcColorBlendFactor = src_color; dstColorBlendFactor = zero; colorBlendOp = add; diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index be783b207..cde6eb270 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -28,14 +28,16 @@ [enumObj addToQueue]; } } else if (name == "VkBool32") { - // drop + id enumObj = [(id) Hash_Find (available_types, name) resolveType]; + [enumObj addToQueue]; } else if ([alias class] == [Enum class] || [alias class] == [Struct class]) { [alias addToQueue]; } else if (alias.type.meta == ty_basic && alias.type.type == ev_pointer) { Type *type = [Type findType:alias.type.fldptr.aux_type]; if (!type) { - // pointer to opaque struct. Probably VK_DEFINE_NON_DISPATCHABLE_HANDLE or VK_DEFINE_HANDLE + // pointer to opaque struct. Probably + // VK_DEFINE_NON_DISPATCHABLE_HANDLE or VK_DEFINE_HANDLE string createInfo = name + "CreateInfo"; id structObj = (id) Hash_Find (available_types, createInfo); if (structObj) { @@ -62,6 +64,10 @@ return [enumObj cexprType]; } } + if (name == "VkBool32") { + id enumObj = [(id) Hash_Find (available_types, name) resolveType]; + return [enumObj cexprType]; + } if (name == "uint32_t") { return "cexpr_uint"; } @@ -83,6 +89,10 @@ return [enumObj parseType]; } } + if (name == "VkBool32") { + id enumObj = [(id) Hash_Find (available_types, name) resolveType]; + return [enumObj parseType]; + } if (name == "uint32_t" || name == "size_t") { return "QFString"; } @@ -101,6 +111,10 @@ return [enumObj parseFunc]; } } + if (name == "VkBool32") { + id enumObj = [(id) Hash_Find (available_types, name) resolveType]; + return [enumObj parseFunc]; + } if (name == "uint32_t") { return "parse_uint32_t"; } @@ -119,6 +133,10 @@ return [enumObj parseData]; } } + if (name == "VkBool32") { + id enumObj = [(id) Hash_Find (available_types, name) resolveType]; + return [enumObj parseData]; + } if (name == "uint32_t" || name == "size_t") { return "0"; } diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 537916800..7c974f6fb 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -3,6 +3,12 @@ #include "vkenum.h" #include "vkgen.h" +typedef enum VkBool32 { + VK_FALSE, + VK_TRUE, + VK_MAX_ENUM = VK_TRUE +} VkBool32; + @implementation Enum -(void)process { diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 4636df52f..01637c54a 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -117,7 +117,10 @@ scan_types (void) string tag = str_mid(type.strct.tag, 4); Type *avail_type = [Type fromType: type]; if (avail_type) { - Hash_Add (available_types, avail_type); + if (!Hash_Find (available_types, [avail_type name])) { + printf ("scan: %s %s\n", tag, [avail_type name]); + Hash_Add (available_types, avail_type); + } } } } From 8a85b5c610b5c3d475bae6b3c51a3ce0f3b76690 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 13:51:41 +0900 Subject: [PATCH 1190/3664] [vulkan] Switch to float/normalized for pics It gives better results when pics are squished or expanded. --- libs/video/renderer/vulkan/qfpipeline.plist | 4 ++-- libs/video/renderer/vulkan/twod.vert | 4 ++-- libs/video/renderer/vulkan/vulkan_draw.c | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 437ab5854..a291ddf09 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -26,7 +26,7 @@ minLod = 0; maxLod = 0; borderColor = float_transparent_black; - unnormalizedCoordinates = true; + unnormalizedCoordinates = false; }; }; descriptorPools = { @@ -119,7 +119,7 @@ { location = 1; binding = 0; - format = r32g32_sint; + format = r32g32_sfloat; offset = 8; }, { diff --git a/libs/video/renderer/vulkan/twod.vert b/libs/video/renderer/vulkan/twod.vert index 5db2990db..c5dc5063a 100644 --- a/libs/video/renderer/vulkan/twod.vert +++ b/libs/video/renderer/vulkan/twod.vert @@ -11,7 +11,7 @@ layout (set = 0, binding = 0) uniform Matrices { (\a x, \a y) and texture coordinate for the icon (\a s=z, \a t=w). */ layout (location = 0) in vec2 vertex; -layout (location = 1) in ivec2 uv; +layout (location = 1) in vec2 uv; layout (location = 2) in vec4 vcolor; layout (location = 0) out vec2 st; @@ -21,6 +21,6 @@ void main (void) { gl_Position = Projection * vec4 (vertex.xy, 0.0, 1.0); - st = vec2(uv); + st = uv; color = vcolor; } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 76cbb0c82..5dca3b98e 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -66,7 +66,7 @@ typedef struct { float xy[2]; - int st[2]; + float st[2]; float color[4]; } drawvert_t; @@ -352,10 +352,10 @@ draw_pic (float x, float y, int w, int h, qpic_t *pic, drawvert_t *verts = quad_verts + num_quads * VERTS_PER_QUAD; num_quads += VERTS_PER_QUAD; - float sl = (srcx); - float sr = (srcx + srcw); - float st = (srcy); - float sb = (srcy + srch); + float sl = (srcx + 0.03125) / 128.0; + float sr = (srcx + srcw - 0.03125) / 128.0; + float st = (srcy + 0.03125) / 128.0; + float sb = (srcy + srch - 0.03125) / 128.0; verts[0].xy[0] = x; verts[0].xy[1] = y; From 93aa038d9e8511a5857109c4468ce8bd027436a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 14:56:02 +0900 Subject: [PATCH 1191/3664] [vulkan] Generate handle get functions Cleans up (hides) the casting when fetching a handle. --- libs/video/renderer/vulkan/vkgen/vkhandle.r | 7 +++++++ libs/video/renderer/vulkan/vkparse.h | 7 +++++++ libs/video/renderer/vulkan/vulkan_draw.c | 13 ++++--------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkhandle.r b/libs/video/renderer/vulkan/vkgen/vkhandle.r index b76d99af4..ec78c22ba 100644 --- a/libs/video/renderer/vulkan/vkgen/vkhandle.r +++ b/libs/video/renderer/vulkan/vkgen/vkhandle.r @@ -56,10 +56,17 @@ output_handle (string name, PLItem *handle) } fprintf (output_file, "}\n"); + fprintf (output_file, "%s QFV_Get%s (vulkan_ctx_t *ctx, const char *name)\n", name, str_mid (name, 2)); + fprintf (output_file, "{\n"); + fprintf (output_file, "\thandleref_t *handleref = Hash_Find (ctx->%s, name);\n", symtab); + fprintf (output_file, "\treturn handleref ? (%s) handleref->handle : 0;\n", name); + fprintf (output_file, "}\n"); + if (!custom) { fprintf (header_file, "static int parse_%s (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context);\n", name); } fprintf (header_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name); + fprintf (output_file, "%s QFV_Get%s (vulkan_ctx_t *ctx, const char *name);\n", name, str_mid (name, 2)); str_free (custom); str_free (symtab); str_free (class); diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 75dd8fe9d..459c0f6a2 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -24,6 +24,13 @@ typedef struct handleref_s { uint64_t handle; } handleref_t; +VkShaderModule QFV_GetShaderModule (vulkan_ctx_t *ctx, const char *name); +VkDescriptorPool QFV_GetDescriptorPool (vulkan_ctx_t *ctx, const char *name); +VkDescriptorSetLayout QFV_GetDescriptorSetLayout (vulkan_ctx_t *ctx, + const char *name); +VkPipelineLayout QFV_GetPipelineLayout (vulkan_ctx_t *ctx, const char *name); +VkSampler QFV_GetSampler (vulkan_ctx_t *ctx, const char *name); + void QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *plist); void QFV_InitParse (vulkan_ctx_t *ctx); exprenum_t *QFV_GetEnum (const char *name); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 5dca3b98e..89ead5380 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -232,9 +232,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT); - handleref_t *h; - h = Hash_Find (ctx->samplers, "quakepic"); - conchars_sampler = (VkSampler) h->handle; + conchars_sampler = QFV_GetSampler (ctx, "quakepic"); uint16_t *chars_data = ctx->staging[0]->data; size_t size = charspic->width * charspic->height; @@ -294,16 +292,13 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) twod_pipeline = Vulkan_CreatePipeline (ctx, "twod"); - h = Hash_Find (ctx->pipelineLayouts, "twod"); - twod_layout = (VkPipelineLayout) h->handle; + twod_layout = QFV_GetPipelineLayout (ctx, "twod"); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (ctx->framebuffers.size, alloca); for (size_t i = 0; i < layouts->size; i++) { - h = Hash_Find (ctx->setLayouts, "twod"); - layouts->a[i] = (VkDescriptorSetLayout) h->handle; + layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "twod"); } - h = Hash_Find (ctx->descriptorPools, "twod"); - __auto_type pool = (VkDescriptorPool) h->handle; + __auto_type pool = QFV_GetDescriptorPool (ctx, "twod"); VkDescriptorBufferInfo bufferInfo = { ctx->matrices.buffer_2d, 0, VK_WHOLE_SIZE From 858ac1932726a239e272a0aa1449149588ba141f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 16:14:46 +0900 Subject: [PATCH 1192/3664] [renderer] Move r_screen and r_cvar into main bin r_screen because of SCR_UpdateScreen, and r_cvar because the cvars really should never have been in a plugin in the first place (and r_screen needed access). --- include/QF/plugin/vid_render.h | 1 + libs/video/renderer/Makemodule.am | 4 +- libs/video/renderer/r_cvar.c | 22 ++++++---- libs/video/renderer/r_main.c | 2 - libs/video/renderer/r_screen.c | 56 +++++++++++++------------ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_sw32.c | 1 + libs/video/renderer/vid_render_vulkan.c | 1 + 10 files changed, 51 insertions(+), 39 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index fc011a8b6..462aaabf4 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -153,6 +153,7 @@ typedef struct vid_render_funcs_s { void (*R_LineGraph) (int x, int y, int *h_vals, int count); dlight_t *(*R_AllocDlight) (int key); entity_t *(*R_AllocEntity) (void); + void (*R_MaxDlightsCheck) (struct cvar_s *var); void (*R_RenderView) (void); void (*R_DecayLights) (double frametime); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index d6187a93a..3e5dd4f70 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -17,7 +17,6 @@ video_renderer_common_sources = \ libs/video/renderer/noisetextures.c \ libs/video/renderer/r_alias.c \ libs/video/renderer/r_bsp.c \ - libs/video/renderer/r_cvar.c \ libs/video/renderer/r_dyn_textures.c \ libs/video/renderer/r_efrag.c \ libs/video/renderer/r_ent.c \ @@ -26,7 +25,6 @@ video_renderer_common_sources = \ libs/video/renderer/r_light.c \ libs/video/renderer/r_main.c \ libs/video/renderer/r_part.c \ - libs/video/renderer/r_screen.c \ libs/video/renderer/vid_common.c renderer_libs= \ @@ -37,7 +35,9 @@ libs_video_renderer_libQFrenderer_la_LDFLAGS= @STATIC@ libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libs) libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs) libs_video_renderer_libQFrenderer_la_SOURCES=\ + libs/video/renderer/r_cvar.c \ libs/video/renderer/r_init.c \ + libs/video/renderer/r_screen.c \ libs/video/renderer/r_progs.c video_renderer_gl_libs= \ diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index d9f3e14d2..98cd22858 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -138,7 +138,7 @@ r_farclip_f (cvar_t *var) Cvar_SetValue (r_particles_nearclip, bound (r_nearclip->value, r_particles_nearclip->value, r_farclip->value)); - vid.recalc_refdef = true; + r_data->vid->recalc_refdef = true; } static void @@ -149,7 +149,7 @@ r_nearclip_f (cvar_t *var) Cvar_SetValue (r_particles_nearclip, bound (r_nearclip->value, r_particles_nearclip->value, r_farclip->value)); - vid.recalc_refdef = true; + r_data->vid->recalc_refdef = true; } static void @@ -176,13 +176,19 @@ viewsize_f (cvar_t *var) if (var->int_val < 30 || var->int_val > 120) { Cvar_SetValue (var, bound (30, var->int_val, 120)); } else { - vid.recalc_refdef = true; + r_data->vid->recalc_refdef = true; r_viewsize = bound (0, var->int_val, 100); - if (vr_data.viewsize_callback) - vr_data.viewsize_callback (var); + if (r_data->viewsize_callback) + r_data->viewsize_callback (var); } } +static void +r_dlight_max_f (cvar_t *var) +{ + r_funcs->R_MaxDlightsCheck (var); +} + void R_Init_Cvars (void) { @@ -218,7 +224,7 @@ R_Init_Cvars (void) NULL, "Set to 1 for high quality dynamic " "lighting."); r_dlight_max = Cvar_Get ("r_dlight_max", "32", CVAR_ARCHIVE, - R_MaxDlightsCheck, "Number of dynamic lights."); + r_dlight_max_f, "Number of dynamic lights."); r_drawentities = Cvar_Get ("r_drawentities", "1", CVAR_NONE, NULL, "Toggles drawing of entities (almost " "everything but the world)"); @@ -309,6 +315,6 @@ R_Init_Cvars (void) scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE, viewsize_f, "Set the screen size 30 minimum, 120 maximum"); - vr_data.graphheight = r_graphheight; - vr_data.scr_viewsize = scr_viewsize; + r_data->graphheight = r_graphheight; + r_data->scr_viewsize = scr_viewsize; } diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index 0d38123d3..bc1590dd0 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -70,8 +70,6 @@ vec3_t r_entorigin; // the currently rendering entity in world entity_t *currententity; entity_t r_worldentity; -qboolean r_cache_thrash; // set if surface cache is thrashing - // view origin vec3_t vup, base_vup; vec3_t vpn, base_vpn; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index db6dcbcf7..5e4e3ba61 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -97,6 +97,8 @@ byte *draw_chars; // 8*8 graphic characters FIXME location float oldfov; int oldsbar; +qboolean r_cache_thrash; // set if surface cache is thrashing + qboolean scr_initialized; // ready to draw qpic_t *scr_ram; @@ -117,7 +119,7 @@ R_SetVrect (vrect_t *vrectin, vrect_t *vrect, int lineadj) // intermission is always full screen size = min (r_viewsize, 100); - if (vr_data.force_fullscreen) { + if (r_data->force_fullscreen) { size = 100.0; lineadj = 0; } @@ -148,18 +150,18 @@ SCR_CalcRefdef (void) refdef_t *refdef = r_data->refdef; // force a background redraw - vr_data.scr_fullupdate = 0; - vid.recalc_refdef = 0; + r_data->scr_fullupdate = 0; + r_data->vid->recalc_refdef = 0; // bound field of view Cvar_SetValue (scr_fov, bound (1, scr_fov->value, 170)); vrect.x = 0; vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; + vrect.width = r_data->vid->width; + vrect.height = r_data->vid->height; - R_SetVrect (&vrect, &scr_vrect, vr_data.lineadj); + R_SetVrect (&vrect, &scr_vrect, r_data->lineadj); refdef->vrect = scr_vrect; refdef->fov_x = scr_fov->value; @@ -167,7 +169,7 @@ SCR_CalcRefdef (void) CalcFov (refdef->fov_x, refdef->vrect.width, refdef->vrect.height); // notify the refresh of the change - vr_funcs->R_ViewChanged (vid.aspect); + r_funcs->R_ViewChanged (r_data->vid->aspect); } /* @@ -186,19 +188,19 @@ SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) return; } - vr_data.realtime = realtime; - scr_copytop = vr_data.scr_copyeverything = 0; + r_data->realtime = realtime; + scr_copytop = r_data->scr_copyeverything = 0; if (oldfov != scr_fov->value) { oldfov = scr_fov->value; - vid.recalc_refdef = true; + r_data->vid->recalc_refdef = true; } - if (vid.recalc_refdef) { + if (r_data->vid->recalc_refdef) { SCR_CalcRefdef (); } - vr_funcs->R_RenderFrame (scr_3dfunc, scr_funcs); + r_funcs->R_RenderFrame (scr_3dfunc, scr_funcs); } float @@ -221,7 +223,7 @@ CalcFov (float fov_x, float width, float height) static void ScreenShot_f (void) { - vr_funcs->SCR_ScreenShot_f (); + r_funcs->SCR_ScreenShot_f (); } /* @@ -234,7 +236,7 @@ SCR_SizeUp_f (void) { if (scr_viewsize->int_val < 120) { Cvar_SetValue (scr_viewsize, scr_viewsize->int_val + 10); - vid.recalc_refdef = 1; + r_data->vid->recalc_refdef = 1; } } @@ -247,7 +249,7 @@ static void SCR_SizeDown_f (void) { Cvar_SetValue (scr_viewsize, scr_viewsize->int_val - 10); - vid.recalc_refdef = 1; + r_data->vid->recalc_refdef = 1; } void @@ -259,7 +261,7 @@ SCR_DrawRam (void) if (!r_cache_thrash) return; - vr_funcs->Draw_Pic (scr_vrect.x + 32, scr_vrect.y, scr_ram); + r_funcs->Draw_Pic (scr_vrect.x + 32, scr_vrect.y, scr_ram); } void @@ -270,7 +272,7 @@ SCR_DrawTurtle (void) if (!scr_showturtle->int_val) return; - if (vr_data.frametime < 0.1) { + if (r_data->frametime < 0.1) { count = 0; return; } @@ -279,7 +281,7 @@ SCR_DrawTurtle (void) if (count < 3) return; - vr_funcs->Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); + r_funcs->Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); } void @@ -290,12 +292,12 @@ SCR_DrawPause (void) if (!scr_showpause->int_val) // turn off for screenshots return; - if (!vr_data.paused) + if (!r_data->paused) return; - pic = vr_funcs->Draw_CachePic ("gfx/pause.lmp", true); - vr_funcs->Draw_Pic ((vid.conwidth - pic->width) / 2, - (vid.conheight - 48 - pic->height) / 2, pic); + pic = r_funcs->Draw_CachePic ("gfx/pause.lmp", true); + r_funcs->Draw_Pic ((r_data->vid->conwidth - pic->width) / 2, + (r_data->vid->conheight - 48 - pic->height) / 2, pic); } void @@ -323,9 +325,9 @@ MipColor (int r, int g, int b) for (i = 0; i < 256; i++) { int j; j = i * 3; - r1 = vid.palette[j] - r; - g1 = vid.palette[j + 1] - g; - b1 = vid.palette[j + 2] - b; + r1 = r_data->vid->palette[j] - r; + g1 = r_data->vid->palette[j + 1] - g; + b1 = r_data->vid->palette[j + 2] - b; dist = r1 * r1 + g1 * g1 + b1 * b1; if (dist < bestdist) { bestdist = dist; @@ -391,8 +393,8 @@ SCR_Init (void) Cmd_AddCommand ("sizeup", SCR_SizeUp_f, "Increases the screen size"); Cmd_AddCommand ("sizedown", SCR_SizeDown_f, "Decreases the screen size"); - scr_ram = vr_funcs->Draw_PicFromWad ("ram"); - scr_turtle = vr_funcs->Draw_PicFromWad ("turtle"); + scr_ram = r_funcs->Draw_PicFromWad ("ram"); + scr_turtle = r_funcs->Draw_PicFromWad ("turtle"); scr_initialized = true; } diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index c27b5d4ac..852a0a423 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -114,6 +114,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_LineGraph, R_AllocDlight, R_AllocEntity, + R_MaxDlightsCheck, gl_R_RenderView, R_DecayLights, gl_R_ViewChanged, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index e3b549e35..25bdb9224 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -114,6 +114,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_LineGraph, R_AllocDlight, R_AllocEntity, + R_MaxDlightsCheck, glsl_R_RenderView, R_DecayLights, glsl_R_ViewChanged, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 5c9264381..02ff562e6 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -107,6 +107,7 @@ vid_render_funcs_t sw_vid_render_funcs = { R_LineGraph, R_AllocDlight, R_AllocEntity, + R_MaxDlightsCheck, R_RenderView, R_DecayLights, R_ViewChanged, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index be727c8a9..97097e2ad 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -112,6 +112,7 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_R_LineGraph, R_AllocDlight, R_AllocEntity, + R_MaxDlightsCheck, sw32_R_RenderView, R_DecayLights, sw32_R_ViewChanged, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 431f6e0b4..995763baf 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -360,6 +360,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { 0,//vulkan_R_LineGraph, R_AllocDlight, R_AllocEntity, + R_MaxDlightsCheck, 0,//vulkan_R_RenderView, R_DecayLights, vulkan_R_ViewChanged, From db14025935b79ae2a87b42281307647ce42b4a2e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 17:34:57 +0900 Subject: [PATCH 1193/3664] [gamecode] Put strings and debug back in load funcs It turns out they're required to be initialized before most of the rest of the system. --- libs/gamecode/pr_debug.c | 1 - libs/gamecode/pr_load.c | 2 ++ libs/gamecode/pr_strings.c | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index d8105c5f6..a272babf8 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1702,7 +1702,6 @@ PR_Debug_Init (progs_t *pr) pr->hashlink_freelist); PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); - PR_AddLoadFunc (pr, PR_LoadDebug); } void diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 6ef18cc15..32033ae90 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -378,7 +378,9 @@ pr_run_ctors (progs_t *pr) } static int (*load_funcs_1[])(progs_t *) = { + PR_LoadStrings, PR_RelocateBuiltins, + PR_LoadDebug, 0, }; diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 7cb295284..82e9540da 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -1222,5 +1222,4 @@ PR_Strings_Init (progs_t *pr) res->print_str = dstring_new (); PR_Resources_Register (pr, "Strings", res, pr_strings_clear); - PR_AddLoadFunc (pr, PR_LoadStrings); } From bf62929f06abb232d9c594490ece29901af7ca31 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jul 2020 21:40:40 +0900 Subject: [PATCH 1194/3664] [gamecode] Add a comment about returning temp strings --- libs/gamecode/pr_strings.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 89d5ee60f..e8e1dff85 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -693,6 +693,11 @@ PR_FreeTempStrings (progs_t *pr) PR_Error (pr, "internal string error: %d", __LINE__); if (R_STRING (pr) < 0 && string_index (res, sr) == R_STRING (pr) && pr->pr_depth) { + // It looks like the temp string is being returned. While this + // may be a false positive (just a random integer with the same + // value), it is better to hold onto the temp string a little + // longer than to remove it prematurely. This allows functions + // to return the result of "str a" + "str b" prstack_t *frame = pr->pr_stack + pr->pr_depth - 1; sr->next = frame->tstr; frame->tstr = sr; From a88f8213426cbf650bf521780cb9707a6496aafa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Jan 2021 23:42:10 +0900 Subject: [PATCH 1195/3664] [gamecode] Disconnect held strings from return slot Fixes an internal string error when a return string has been freed. --- libs/gamecode/pr_strings.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index e8e1dff85..7efd2265c 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -344,7 +344,7 @@ get_string (progs_t *pr, string_t num) case str_free: break; } - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); } else { if (num >= pr->pr_stringsize) return 0; @@ -469,17 +469,17 @@ PR_SetReturnString (progs_t *pr, const char *s) requeue_strref (res, sr); } else if ((sr->type == str_return && !sr->rs_slot) || (sr->type != str_return && sr->rs_slot)) { - PR_Error (pr, "internal string error: %d %d %p", __LINE__, + PR_Error (pr, "internal string error: line:%d %d %p", __LINE__, sr->type, sr->rs_slot); } return string_index (res, sr); } // grab the string ref from the oldest slot, or make a new one if the - // slot is empty or the string has been held - if ((sr = res->rs_slot->strref) && sr->type != str_dynamic) { + // slot is empty + if ((sr = res->rs_slot->strref)) { if (sr->type != str_return || sr->rs_slot != res->rs_slot) { - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); } pr_strfree (pr, sr->s.string); } else { @@ -629,7 +629,10 @@ PR_HoldString (progs_t *pr, string_t str) if (sr) { switch (sr->type) { case str_temp: + break; case str_return: + sr->rs_slot->strref = 0; + sr->rs_slot = 0; break; case str_static: case str_mutable: @@ -637,7 +640,7 @@ PR_HoldString (progs_t *pr, string_t str) // non-ephemeral string, no-op return; default: - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); } sr->type = str_dynamic; return; @@ -666,7 +669,7 @@ PR_FreeString (progs_t *pr, string_t str) pr_strfree (pr, sr->s.string); break; default: - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); } free_string_ref (res, sr); return; @@ -690,7 +693,7 @@ PR_FreeTempStrings (progs_t *pr) continue; } if (sr->type != str_temp) - PR_Error (pr, "internal string error: %d", __LINE__); + PR_Error (pr, "internal string error: line:%d", __LINE__); if (R_STRING (pr) < 0 && string_index (res, sr) == R_STRING (pr) && pr->pr_depth) { // It looks like the temp string is being returned. While this From 1c5454cf6b9055f4357e9cc93c5c1c41af5f8874 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 5 Jan 2021 00:07:58 +0900 Subject: [PATCH 1196/3664] [gamecode] Move % handling to the flags state % is effectively a format flag that cancels the format and outputs a % single %. Fixes % not getting output for %%. --- libs/gamecode/pr_strings.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 7efd2265c..7cb295284 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -868,6 +868,7 @@ fmt_append_item (fmt_state_t *state) * \dot * digraph PR_Sprintf_fmt_state_machine { * format -> flags [label="{%}"]; + * flogs -> format [label="{%}"]; * flags -> flags [label="{#+0 -}"]; * flags -> var_field_width [label="{*}"]; * flags -> precision [label="{.}"]; @@ -906,6 +907,17 @@ fmt_state_flags (fmt_state_t *state) state->c++; // skip over % while (1) { switch (*state->c) { + case '%': + state->c++; + (*state->fi)->flags = 0; + (*state->fi)->precision = 1; + (*state->fi)->minFieldWidth = 0; + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = "%"; + + fmt_append_item (state); + state->state = fmt_state_format; + return; case '0': (*state->fi)->flags |= FMT_ZEROPAD; break; @@ -1111,15 +1123,6 @@ fmt_state_conversion (fmt_state_t *state) (*state->fi)->data.string_var = "'"; state->fmt_count++; - fmt_append_item (state); - break; - case '%': - (*state->fi)->flags = 0; - (*state->fi)->precision = 0; - (*state->fi)->minFieldWidth = 0; - (*state->fi)->type = 's'; - (*state->fi)->data.string_var = "%"; - fmt_append_item (state); break; case 'x': From 40d62e06c7ba470985b76d253a724e2431196636 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 17:34:57 +0900 Subject: [PATCH 1197/3664] [gamecode] Put strings and debug back in load funcs It turns out they're required to be initialized before most of the rest of the system. --- libs/gamecode/pr_debug.c | 1 - libs/gamecode/pr_load.c | 2 ++ libs/gamecode/pr_strings.c | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index d8105c5f6..a272babf8 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1702,7 +1702,6 @@ PR_Debug_Init (progs_t *pr) pr->hashlink_freelist); PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); - PR_AddLoadFunc (pr, PR_LoadDebug); } void diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 6ef18cc15..32033ae90 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -378,7 +378,9 @@ pr_run_ctors (progs_t *pr) } static int (*load_funcs_1[])(progs_t *) = { + PR_LoadStrings, PR_RelocateBuiltins, + PR_LoadDebug, 0, }; diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 7cb295284..82e9540da 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -1222,5 +1222,4 @@ PR_Strings_Init (progs_t *pr) res->print_str = dstring_new (); PR_Resources_Register (pr, "Strings", res, pr_strings_clear); - PR_AddLoadFunc (pr, PR_LoadStrings); } From bfbfd7af61d0bed1f921ec9786c5cb9abcf74f72 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 18:45:44 +0900 Subject: [PATCH 1198/3664] [glsl] Remove subpic_t's tnum It's never actually used (the texture can be fetched using GLSL_ScrapTexture) and gets in the way of sharing the scrap system with the vulkan renderer. --- include/QF/GLSL/qf_textures.h | 1 - libs/video/renderer/glsl/glsl_textures.c | 1 - 2 files changed, 2 deletions(-) diff --git a/include/QF/GLSL/qf_textures.h b/include/QF/GLSL/qf_textures.h index 5f30fbf68..0a6e3ba6d 100644 --- a/include/QF/GLSL/qf_textures.h +++ b/include/QF/GLSL/qf_textures.h @@ -35,7 +35,6 @@ typedef struct subpic_s { const struct subpic_s * const next; const scrap_t * const scrap; const struct vrect_s * const rect; - const int tnum; ///< texture number const int width; ///< requested width const int height; ///< requested height const float size; ///< size factor for tex coords (mult) diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index 4e6303093..8130dfdf5 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -437,7 +437,6 @@ GLSL_ScrapSubpic (scrap_t *scrap, int width, int height) scrap->subpics = subpic; *((scrap_t **) &subpic->scrap) = scrap; *((vrect_t **) &subpic->rect) = rect; - *((int *) &subpic->tnum) = scrap->tnum; *((int *) &subpic->width) = width; *((int *) &subpic->height) = height; *((float *) &subpic->size) = 1.0 / scrap->size; From b6bc8ed5537ca99171ac6bf728e46092d7fa8c0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Jan 2021 21:10:22 +0900 Subject: [PATCH 1199/3664] [renderer] Move core of scrap into shared code The actual 2d area management code is now shared, with the actual definition for scrap_t being left to the renderer specific implementation. --- include/QF/GLSL/qf_textures.h | 16 +- include/QF/render.h | 9 ++ include/r_scrap.h | 49 ++++++ libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/glsl/glsl_textures.c | 120 +++------------ libs/video/renderer/r_init.c | 2 + libs/video/renderer/r_scrap.c | 183 +++++++++++++++++++++++ 7 files changed, 273 insertions(+), 107 deletions(-) create mode 100644 include/r_scrap.h create mode 100644 libs/video/renderer/r_scrap.c diff --git a/include/QF/GLSL/qf_textures.h b/include/QF/GLSL/qf_textures.h index 0a6e3ba6d..2298c3e16 100644 --- a/include/QF/GLSL/qf_textures.h +++ b/include/QF/GLSL/qf_textures.h @@ -31,14 +31,6 @@ #include "QF/qtypes.h" typedef struct scrap_s scrap_t; -typedef struct subpic_s { - const struct subpic_s * const next; - const scrap_t * const scrap; - const struct vrect_s * const rect; - const int width; ///< requested width - const int height; ///< requested height - const float size; ///< size factor for tex coords (mult) -} subpic_t; int GLSL_LoadQuakeTexture (const char *identifier, int width, int height, byte *data); @@ -55,9 +47,11 @@ scrap_t *GLSL_CreateScrap (int size, int format, int linear); void GLSL_DestroyScrap (scrap_t *scrap); void GLSL_ScrapClear (scrap_t *scrap); int GLSL_ScrapTexture (scrap_t *scrap) __attribute__((pure)); -subpic_t *GLSL_ScrapSubpic (scrap_t *scrap, int width, int height); //XXX slow! -void GLSL_SubpicDelete (subpic_t *subpic); //XXX slow! -void GLSL_SubpicUpdate (subpic_t *subpic, byte *data, int batch); +//XXX slow! +struct subpic_s *GLSL_ScrapSubpic (scrap_t *scrap, int width, int height); +//XXX slow! +void GLSL_SubpicDelete (struct subpic_s *subpic); +void GLSL_SubpicUpdate (struct subpic_s *subpic, byte *data, int batch); void GLSL_ScrapFlush (scrap_t *scrap); #endif//__QF_GLSL_textures_h diff --git a/include/QF/render.h b/include/QF/render.h index 7f02672e2..607b8b800 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -55,6 +55,15 @@ typedef enum { extern struct vid_render_funcs_s *r_funcs; extern struct vid_render_data_s *r_data; +typedef struct subpic_s { + const struct subpic_s *const next; + const struct scrap_s *const scrap; ///< renderer specific type + const struct vrect_s *const rect; + const int width; ///< requested width + const int height; ///< requested height + const float size; ///< size factor for tex coords (mult) +} subpic_t; + // dynamic lights =========================================================== typedef struct dlight_s diff --git a/include/r_scrap.h b/include/r_scrap.h new file mode 100644 index 000000000..5539d7480 --- /dev/null +++ b/include/r_scrap.h @@ -0,0 +1,49 @@ +/* + r_scrap.h + + Renderer agnostic scrap management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/1/12 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __r_scrap_h +#define __r_scrap_h + +typedef struct rscrap_s { + struct vrect_s *free_rects; ///< linked list of free areas + struct vrect_s *rects; ///< linked list of allocated rects + int width; ///< overall width of scrap + int height; ///< overall height of scrap +} rscrap_t; + +void R_ScrapInit (rscrap_t *scrap, int width, int height); +void R_ScrapDelete (rscrap_t *scrap); +struct vrect_s *R_ScrapAlloc (rscrap_t *scrap, int width, int height); +void R_ScrapFree (rscrap_t *scrap, struct vrect_s *rect); +void R_ScrapClear (rscrap_t *scrap); +size_t R_ScrapArea (rscrap_t *scrap) __attribute__((pure)); +void R_ScrapDump (rscrap_t *scrap); + +#endif//__r_scrap_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 3e5dd4f70..05740af60 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -37,6 +37,7 @@ libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs) libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_cvar.c \ libs/video/renderer/r_init.c \ + libs/video/renderer/r_scrap.c \ libs/video/renderer/r_screen.c \ libs/video/renderer/r_progs.c diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index 8130dfdf5..1edd77b71 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -44,6 +44,7 @@ #include "QF/cmd.h" #include "QF/mathlib.h" #include "QF/model.h" +#include "QF/render.h" #include "QF/sys.h" #include "QF/vrect.h" @@ -51,15 +52,15 @@ #include "QF/GLSL/funcs.h" #include "QF/GLSL/qf_textures.h" +#include "r_scrap.h" + struct scrap_s { + rscrap_t rscrap; GLuint tnum; - int size; // in pixels, for now, always square, power of 2 int format; int bpp; byte *data; // local copy of the texture so updates can be batched vrect_t *batch; - vrect_t *free_rects; - vrect_t *rects; subpic_t *subpics; struct scrap_s *next; }; @@ -248,23 +249,22 @@ static void glsl_scraps_f (void) { scrap_t *scrap; - vrect_t *rect; int area; + int size; if (!scrap_list) { Sys_Printf ("No scraps\n"); return; } for (scrap = scrap_list; scrap; scrap = scrap->next) { - for (rect = scrap->free_rects, area = 0; rect; rect = rect->next) - area += rect->width * rect->height; + area = R_ScrapArea (&scrap->rscrap); + // always square + size = scrap->rscrap.width; Sys_Printf ("tnum=%u size=%d format=%04x bpp=%d free=%d%%\n", - scrap->tnum, scrap->size, scrap->format, scrap->bpp, - area * 100 / (scrap->size * scrap->size)); + scrap->tnum, size, scrap->format, scrap->bpp, + area * 100 / (size * size)); if (Cmd_Argc () > 1) { - for (rect = scrap->rects, area = 0; rect; rect = rect->next) - Sys_Printf ("%d %d %d %d\n", rect->x, rect->y, - rect->width, rect->height); + R_ScrapDump (&scrap->rscrap); } } } @@ -309,11 +309,9 @@ GLSL_CreateScrap (int size, int format, int linear) } scrap = malloc (sizeof (scrap_t)); qfeglGenTextures (1, &scrap->tnum); - scrap->size = size; + R_ScrapInit (&scrap->rscrap, size, size); scrap->format = format; scrap->bpp = bpp; - scrap->free_rects = VRect_New (0, 0, size, size); - scrap->rects = 0; scrap->subpics = 0; scrap->next = scrap_list; scrap_list = scrap; @@ -341,26 +339,13 @@ GLSL_CreateScrap (int size, int format, int linear) void GLSL_ScrapClear (scrap_t *scrap) { - vrect_t *t; subpic_t *sp; - - while (scrap->free_rects) { - t = scrap->free_rects; - scrap->free_rects = t->next; - VRect_Delete (t); - } - while (scrap->rects) { - t = scrap->rects; - scrap->rects = t->next; - VRect_Delete (t); - } while (scrap->subpics) { sp = scrap->subpics; scrap->subpics = (subpic_t *) sp->next; free (sp); } - - scrap->free_rects = VRect_New (0, 0, scrap->size, scrap->size); + R_ScrapClear (&scrap->rscrap); } void @@ -375,7 +360,7 @@ GLSL_DestroyScrap (scrap_t *scrap) } } GLSL_ScrapClear (scrap); - VRect_Delete (scrap->free_rects); + R_ScrapDelete (&scrap->rscrap); GLSL_ReleaseTexture (scrap->tnum); free (scrap->data); free (scrap); @@ -390,47 +375,13 @@ GLSL_ScrapTexture (scrap_t *scrap) subpic_t * GLSL_ScrapSubpic (scrap_t *scrap, int width, int height) { - int i, w, h; - vrect_t **t, **best; - vrect_t *old, *frags, *rect; + vrect_t *rect; subpic_t *subpic; - for (i = 0; i < 16; i++) - if (width <= (1 << i)) - break; - w = 1 << i; - for (i = 0; i < 16; i++) - if (height <= (1 << i)) - break; - h = 1 << i; - - best = 0; - for (t = &scrap->free_rects; *t; t = &(*t)->next) { - if ((*t)->width < w || (*t)->height < h) - continue; // won't fit - if (!best) { - best = t; - continue; - } - if ((*t)->width <= (*best)->width || (*t)->height <= (*best)->height) - best = t; + rect = R_ScrapAlloc (&scrap->rscrap, width, height); + if (!rect) { + return 0; } - if (!best) - return 0; // couldn't find a spot - old = *best; - *best = old->next; - rect = VRect_New (old->x, old->y, w, h); - frags = VRect_Difference (old, rect); - VRect_Delete (old); - if (frags) { - // old was bigger than the requested size - for (old = frags; old->next; old = old->next) - ; - old->next = scrap->free_rects; - scrap->free_rects = frags; - } - rect->next = scrap->rects; - scrap->rects = rect; subpic = malloc (sizeof (subpic_t)); *((subpic_t **) &subpic->next) = scrap->subpics; @@ -439,7 +390,7 @@ GLSL_ScrapSubpic (scrap_t *scrap, int width, int height) *((vrect_t **) &subpic->rect) = rect; *((int *) &subpic->width) = width; *((int *) &subpic->height) = height; - *((float *) &subpic->size) = 1.0 / scrap->size; + *((float *) &subpic->size) = 1.0 / scrap->rscrap.width; return subpic; } @@ -448,8 +399,6 @@ GLSL_SubpicDelete (subpic_t *subpic) { scrap_t *scrap = (scrap_t *) subpic->scrap; vrect_t *rect = (vrect_t *) subpic->rect; - vrect_t *old, *merge; - vrect_t **t; subpic_t **sp; for (sp = &scrap->subpics; *sp; sp = (subpic_t **) &(*sp)->next) @@ -459,29 +408,7 @@ GLSL_SubpicDelete (subpic_t *subpic) Sys_Error ("GLSL_ScrapDelSubpic: broken subpic"); *sp = (subpic_t *) subpic->next; free (subpic); - for (t = &scrap->rects; *t; t = &(*t)->next) - if (*t == rect) - break; - if (*t != rect) - Sys_Error ("GLSL_ScrapDelSubpic: broken subpic"); - *t = rect->next; - - do { - merge = 0; - for (t = &scrap->free_rects; *t; t = &(*t)->next) { - merge = VRect_Merge (*t, rect); - if (merge) { - old = *t; - *t = (*t)->next; - VRect_Delete (old); - VRect_Delete (rect); - rect = merge; - break; - } - } - } while (merge); - rect->next = scrap->free_rects; - scrap->free_rects = rect; + R_ScrapFree (&scrap->rscrap, rect); } void @@ -502,7 +429,7 @@ GLSL_SubpicUpdate (subpic_t *subpic, byte *data, int batch) scrap->batch = VRect_New (rect->x, rect->y, rect->width, rect->height); } - step = scrap->size * scrap->bpp; + step = scrap->rscrap.width * scrap->bpp; sbytes = subpic->width * scrap->bpp; dest = scrap->data + rect->y * step + rect->x * scrap->bpp; for (i = 0; i < subpic->height; i++, dest += step, data += sbytes) @@ -519,6 +446,7 @@ void GLSL_ScrapFlush (scrap_t *scrap) { vrect_t *rect = scrap->batch; + int size = scrap->rscrap.width; if (!rect) return; @@ -526,9 +454,9 @@ GLSL_ScrapFlush (scrap_t *scrap) //should update to not update the entire horizontal block qfeglBindTexture (GL_TEXTURE_2D, scrap->tnum); qfeglTexSubImage2D (GL_TEXTURE_2D, 0, 0, rect->y, - scrap->size, rect->height, scrap->format, + size, rect->height, scrap->format, GL_UNSIGNED_BYTE, - scrap->data + rect->y * scrap->size * scrap->bpp); + scrap->data + rect->y * size * scrap->bpp); VRect_Delete (rect); scrap->batch = 0; } diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index f298538ba..733004a21 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -46,6 +46,7 @@ #include "QF/plugin/general.h" #include "r_internal.h" +#include "r_scrap.h" #include "vid_internal.h" cvar_t *vidrend_plugin; @@ -61,6 +62,7 @@ vid_render_funcs_t *r_funcs; #define U __attribute__ ((used)) static U void (*const r_progs_init)(struct progs_s *) = R_Progs_Init; +static U void (*const r_scrapdelete)(rscrap_t *) = R_ScrapDelete; #undef U static void diff --git a/libs/video/renderer/r_scrap.c b/libs/video/renderer/r_scrap.c new file mode 100644 index 000000000..86a4ca0a6 --- /dev/null +++ b/libs/video/renderer/r_scrap.c @@ -0,0 +1,183 @@ +/* + r_scrap.c + + Renderer agnostic scrap management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/1/12 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/sys.h" +#include "QF/vrect.h" + +#include "compat.h" +#include "r_scrap.h" + +static unsigned +pow2rup (unsigned x) +{ + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + return x; +} + +VISIBLE void +R_ScrapInit (rscrap_t *scrap, int width, int height) +{ + width = pow2rup (width); + height = pow2rup (height); + scrap->width = width; + scrap->height = height; + scrap->rects = 0; + scrap->free_rects = VRect_New (0, 0, width, height); +} + +VISIBLE void +R_ScrapDelete (rscrap_t *scrap) +{ + R_ScrapClear (scrap); + VRect_Delete (scrap->free_rects); +} + +VISIBLE vrect_t * +R_ScrapAlloc (rscrap_t *scrap, int width, int height) +{ + int w, h; + vrect_t **t, **best; + vrect_t *old, *frags, *rect; + + w = pow2rup (width); + h = pow2rup (height); + + best = 0; + for (t = &scrap->free_rects; *t; t = &(*t)->next) { + if ((*t)->width < w || (*t)->height < h) + continue; // won't fit + if (!best) { + best = t; + continue; + } + if ((*t)->width <= (*best)->width || (*t)->height <= (*best)->height) + best = t; + } + if (!best) + return 0; // couldn't find a spot + old = *best; + *best = old->next; + rect = VRect_New (old->x, old->y, w, h); + frags = VRect_Difference (old, rect); + VRect_Delete (old); + if (frags) { + // old was bigger than the requested size + for (old = frags; old->next; old = old->next) + ; + old->next = scrap->free_rects; + scrap->free_rects = frags; + } + rect->next = scrap->rects; + scrap->rects = rect; + + return rect; +} + +VISIBLE void +R_ScrapFree (rscrap_t *scrap, vrect_t *rect) +{ + vrect_t *old, *merge; + vrect_t **t; + + for (t = &scrap->rects; *t; t = &(*t)->next) + if (*t == rect) + break; + if (*t != rect) + Sys_Error ("R_ScrapFree: broken rect"); + *t = rect->next; + + do { + merge = 0; + for (t = &scrap->free_rects; *t; t = &(*t)->next) { + merge = VRect_Merge (*t, rect); + if (merge) { + old = *t; + *t = (*t)->next; + VRect_Delete (old); + VRect_Delete (rect); + rect = merge; + break; + } + } + } while (merge); + rect->next = scrap->free_rects; + scrap->free_rects = rect; +} + +VISIBLE void +R_ScrapClear (rscrap_t *scrap) +{ + vrect_t *t; + + while (scrap->free_rects) { + t = scrap->free_rects; + scrap->free_rects = t->next; + VRect_Delete (t); + } + while (scrap->rects) { + t = scrap->rects; + scrap->rects = t->next; + VRect_Delete (t); + } + + scrap->free_rects = VRect_New (0, 0, scrap->width, scrap->height); +} + +VISIBLE size_t +R_ScrapArea (rscrap_t *scrap) +{ + vrect_t *rect; + size_t area; + + for (rect = scrap->free_rects, area = 0; rect; rect = rect->next) { + area += rect->width * rect->height; + } + return area; +} + +VISIBLE void +R_ScrapDump (rscrap_t *scrap) +{ + vrect_t *rect; + + for (rect = scrap->rects; rect; rect = rect->next) { + Sys_Printf ("%d %d %d %d\n", rect->x, rect->y, + rect->width, rect->height); + } +} From a7ac188d1d1808c34f58be980bf9804659f24e30 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Jan 2021 10:43:23 +0900 Subject: [PATCH 1200/3664] [vulkan] Use a scrap texture for draw The scrap texture did very good things for the glsl renderer and the better control over data copying might help it do even better things for vulkan, especially with lots of little icons. --- include/QF/Vulkan/command.h | 6 + include/QF/Vulkan/staging.h | 2 + include/QF/Vulkan/texture.h | 43 ++++ libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vulkan/staging.c | 13 + libs/video/renderer/vulkan/texture.c | 299 +++++++++++++++++++++++ libs/video/renderer/vulkan/vulkan_draw.c | 90 ++----- 7 files changed, 390 insertions(+), 64 deletions(-) create mode 100644 include/QF/Vulkan/texture.h create mode 100644 libs/video/renderer/vulkan/texture.c diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 046c8b2b3..925a63781 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -12,6 +12,12 @@ typedef struct qfv_semaphoreset_s typedef struct qfv_fenceset_s DARRAY_TYPE (VkFence) qfv_fenceset_t; +typedef struct qfv_bufferimagecopy_s + DARRAY_TYPE (VkBufferImageCopy) qfv_bufferimagecopy_t; + +#define QFV_AllocBufferImageCopy(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_bufferimagecopy_t, num, allocator) + struct qfv_queue_s; struct qfv_device_s; VkCommandPool QFV_CreateCommandPool (struct qfv_device_s *device, diff --git a/include/QF/Vulkan/staging.h b/include/QF/Vulkan/staging.h index d281f1854..9a90edd6e 100644 --- a/include/QF/Vulkan/staging.h +++ b/include/QF/Vulkan/staging.h @@ -6,6 +6,7 @@ typedef struct qfv_stagebuf_s { VkBuffer buffer; VkDeviceMemory memory; size_t size; + size_t offset; ///< for batching building void *data; } qfv_stagebuf_t; @@ -14,5 +15,6 @@ qfv_stagebuf_t *QFV_CreateStagingBuffer (struct qfv_device_s *device, size_t size); void QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage); void QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size); +void *QFV_ClaimStagingBuffer (qfv_stagebuf_t *stage, size_t size); #endif//__QF_Vulkan_staging_h diff --git a/include/QF/Vulkan/texture.h b/include/QF/Vulkan/texture.h new file mode 100644 index 000000000..6a55815f6 --- /dev/null +++ b/include/QF/Vulkan/texture.h @@ -0,0 +1,43 @@ +#ifndef __QF_Vulkan_texture_h +#define __QF_Vulkan_texture_h + +typedef enum { + QFV_LUMINANCE, + QFV_LUMINANCE_ALPHA, + QFV_RGB, + QFV_RGBA, +} QFVFormat; + +typedef struct scrap_s scrap_t; + +scrap_t *QFV_CreateScrap (struct qfv_device_s *device, int size, + QFVFormat format); +void QFV_ScrapClear (scrap_t *scrap); +void QFV_DestroyScrap (scrap_t *scrap); +VkImageView QFV_ScrapImageView (scrap_t *scrap) __attribute__((pure)); +subpic_t *QFV_ScrapSubpic (scrap_t *scrap, int width, int height); +void QFV_SubpicDelete (subpic_t *subpic); + +/** Add an update region to the batch queue. + * + * The region to be updated is recorded in the batch queue, space allocated + * in the staging buffer, and a pointer to the allocated space is returned. + * + * \note No data is stransfered. This facilitates writing generated data + * directly to the staging buffer. + */ +void *QFV_SubpicBatch (subpic_t *subpic, struct qfv_stagebuf_s *stage); + +/** Flush all batched subpic updates. + * + * The offset in the staging bufffer \a stage is reset to 0. The command + * buffer is populated with the appropriate image layout barriers and the + * necessary copy commands. + * + * \note The command buffer is neither begun nor ended, nor is it submitted + * to a queue. This is to maximize flexibility in command buffer usage. + */ +void QFV_ScrapFlush (scrap_t *scrap, struct qfv_stagebuf_s *stage, + VkCommandBuffer cmd); + +#endif//__QF_Vulkan_texture_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 05740af60..6f306ffe5 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -230,6 +230,7 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/shader.c \ libs/video/renderer/vulkan/staging.c \ libs/video/renderer/vulkan/swapchain.c \ + libs/video/renderer/vulkan/texture.c \ libs/video/renderer/vulkan/util.c \ libs/video/renderer/vulkan/util.h \ libs/video/renderer/vulkan/vkparse.c \ diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index de791239c..04e3897db 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -59,6 +59,8 @@ QFV_CreateStagingBuffer (qfv_device_t *device, size_t size) qfv_devfuncs_t *dfunc = device->funcs; qfv_stagebuf_t *stage = malloc (sizeof (qfv_stagebuf_t)); + stage->size = size; + stage->offset = 0; stage->device = device; stage->buffer = QFV_CreateBuffer (device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); @@ -94,3 +96,14 @@ QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size) }; dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); } + +void * +QFV_ClaimStagingBuffer (qfv_stagebuf_t *stage, size_t size) +{ + if (stage->offset + size > stage->size) { + return 0; + } + void *data = (byte *) stage->data + stage->offset; + stage->offset += (size + 3) & ~3; + return data; +} diff --git a/libs/video/renderer/vulkan/texture.c b/libs/video/renderer/vulkan/texture.c new file mode 100644 index 000000000..6529800b1 --- /dev/null +++ b/libs/video/renderer/vulkan/texture.c @@ -0,0 +1,299 @@ +/* + texuture.c + + Vulkan texuture manager + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/alloc.h" +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/qfplist.h" +#include "QF/quakefs.h" +#include "QF/render.h" +#include "QF/sys.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/barrier.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/staging.h" +#include "QF/Vulkan/texture.h" + +#include "r_scrap.h" +#include "vid_vulkan.h" + +struct scrap_s { + rscrap_t rscrap; + VkImage image; + VkDeviceMemory memory; + VkImageView view; + size_t bpp; + vrect_t *batch; + vrect_t **batch_tail; + vrect_t *batch_free; + size_t batch_count; + subpic_t *subpics; + qfv_device_t *device; +}; + +scrap_t * +QFV_CreateScrap (qfv_device_t *device, int size, QFVFormat format) +{ + int bpp = 0; + VkFormat fmt = VK_FORMAT_UNDEFINED; + + switch (format) { + case QFV_LUMINANCE: + bpp = 1; + fmt = VK_FORMAT_R8_UNORM; + break; + case QFV_LUMINANCE_ALPHA: + bpp = 2; + fmt = VK_FORMAT_R8G8_UNORM; + break; + case QFV_RGB: + bpp = 3; + fmt = VK_FORMAT_R8G8B8_UNORM; + break; + case QFV_RGBA: + bpp = 4; + fmt = VK_FORMAT_R8G8B8A8_UNORM; + break; + } + + scrap_t *scrap = malloc (sizeof (scrap_t)); + + R_ScrapInit (&scrap->rscrap, size, size); + + // R_ScrapInit rounds sizes up to next power of 2 + size = scrap->rscrap.width; + VkExtent3D extent = { size, size, 1 }; + scrap->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, fmt, + extent, 1, 1, VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT); + scrap->memory = QFV_AllocImageMemory (device, scrap->image, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + 0, 0); + QFV_BindImageMemory (device, scrap->image, scrap->memory, 0); + scrap->view = QFV_CreateImageView (device, scrap->image, + VK_IMAGE_VIEW_TYPE_2D, fmt, + VK_IMAGE_ASPECT_COLOR_BIT); + scrap->bpp = bpp; + scrap->subpics = 0; + scrap->device = device; + scrap->batch = 0; + scrap->batch_tail = &scrap->batch; + scrap->batch_free = 0; + scrap->batch_count = 0; + return scrap; +} + +void +QFV_ScrapClear (scrap_t *scrap) +{ + subpic_t *sp; + while (scrap->subpics) { + sp = scrap->subpics; + scrap->subpics = (subpic_t *) sp->next; + free (sp); + } + R_ScrapClear (&scrap->rscrap); +} + +void +QFV_DestroyScrap (scrap_t *scrap) +{ + qfv_device_t *device = scrap->device; + qfv_devfuncs_t *dfunc = device->funcs; + + QFV_ScrapClear (scrap); + R_ScrapDelete (&scrap->rscrap); + dfunc->vkDestroyImageView (device->dev, scrap->view, 0); + dfunc->vkDestroyImage (device->dev, scrap->image, 0); + dfunc->vkFreeMemory (device->dev, scrap->memory, 0); + + while (scrap->batch_free) { + vrect_t *b = scrap->batch_free; + scrap->batch_free = b->next; + VRect_Delete (b); + } + free (scrap); +} + +VkImageView +QFV_ScrapImageView (scrap_t *scrap) +{ + return scrap->view; +} + +subpic_t * +QFV_ScrapSubpic (scrap_t *scrap, int width, int height) +{ + vrect_t *rect; + subpic_t *subpic; + + rect = R_ScrapAlloc (&scrap->rscrap, width, height); + if (!rect) { + return 0; + } + + subpic = malloc (sizeof (subpic_t)); + *((subpic_t **) &subpic->next) = scrap->subpics; + scrap->subpics = subpic; + *((scrap_t **) &subpic->scrap) = scrap; + *((vrect_t **) &subpic->rect) = rect; + *((int *) &subpic->width) = width; + *((int *) &subpic->height) = height; + *((float *) &subpic->size) = 1.0 / scrap->rscrap.width; + return subpic; +} + +void +QFV_SubpicDelete (subpic_t *subpic) +{ + scrap_t *scrap = (scrap_t *) subpic->scrap; + vrect_t *rect = (vrect_t *) subpic->rect; + subpic_t **sp; + + for (sp = &scrap->subpics; *sp; sp = (subpic_t **) &(*sp)->next) { + if (*sp == subpic) { + break; + } + } + if (*sp != subpic) { + Sys_Error ("QFV_SubpicDelete: broken subpic"); + } + *sp = (subpic_t *) subpic->next; + free (subpic); + R_ScrapFree (&scrap->rscrap, rect); +} + +void * +QFV_SubpicBatch (subpic_t *subpic, qfv_stagebuf_t *stage) +{ + scrap_t *scrap = (scrap_t *) subpic->scrap; + vrect_t *rect = (vrect_t *) subpic->rect; + vrect_t *batch; + byte *dest; + size_t size; + + size = subpic->width * subpic->height * scrap->bpp; + if (!(dest = QFV_ClaimStagingBuffer (stage, size))) { + return 0; + } + + if (scrap->batch_free) { + batch = scrap->batch_free; + scrap->batch_free = batch->next; + } else { + batch = VRect_New (rect->x, rect->y, subpic->width, subpic->height); + } + *scrap->batch_tail = batch; + scrap->batch_tail = &batch->next; + batch->next = 0; + scrap->batch_count++; + return dest; +} + +void +QFV_ScrapFlush (scrap_t *scrap, qfv_stagebuf_t *stage, VkCommandBuffer cmd) +{ + qfv_device_t *device = scrap->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (!scrap->batch_count) { + return; + } + + size_t i; + __auto_type copy = QFV_AllocBufferImageCopy (128, alloca); + memset (copy->a, 0, 128 * sizeof (copy->a[0])); + + for (i = 0; i < scrap->batch_count && i < 128; i++) { + copy->a[i].imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy->a[i].imageSubresource.layerCount = 1; + copy->a[i].imageExtent.depth = 1; + } + + QFV_FlushStagingBuffer (stage, 0, stage->offset); + + VkImageMemoryBarrier barrier; + qfv_pipelinestagepair_t stages; + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + barrier.image = scrap->image; + dfunc->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, + 1, &barrier); + + size_t offset = 0, size; + vrect_t *batch = scrap->batch; + while (scrap->batch_count) { + for (i = 0; i < scrap->batch_count && i < 128; i++) { + size = batch->width * batch->height * scrap->bpp; + + copy->a[i].bufferOffset = offset; + copy->a[i].imageOffset.x = batch->x; + copy->a[i].imageOffset.y = batch->y; + copy->a[i].imageExtent.width = batch->width; + copy->a[i].imageExtent.height = batch->height; + + offset += (size + 3) & ~3; + batch = batch->next; + } + dfunc->vkCmdCopyBufferToImage (cmd, stage->buffer, scrap->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + i, copy->a); + scrap->batch_count -= i; + } + + stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier.image = scrap->image; + dfunc->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, + 1, &barrier); + + *scrap->batch_tail = scrap->batch_free; + scrap->batch_free = scrap->batch; + scrap->batch = 0; + scrap->batch_tail = &scrap->batch; + stage->offset = 0; +} diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 89ead5380..badc01332 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -46,6 +46,7 @@ #include "QF/dstring.h" #include "QF/hash.h" #include "QF/quakefs.h" +#include "QF/render.h" #include "QF/sys.h" #include "QF/vid.h" @@ -59,6 +60,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/staging.h" +#include "QF/Vulkan/texture.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -75,10 +77,9 @@ typedef struct { #define INDS_PER_QUAD (5) // one per vert plus primitive reset //FIXME move into a context struct -VkImage conchars_image; -VkDeviceMemory conchars_memory; -VkImageView conchars_view; VkSampler conchars_sampler; +scrap_t *draw_scrap; +subpic_t *conchars; VkBuffer quad_vert_buffer; VkBuffer quad_ind_buffer; @@ -201,9 +202,7 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) destroy_quad_buffers (ctx); dfunc->vkDestroyPipeline (device->dev, twod_pipeline, 0); - dfunc->vkDestroyImageView (device->dev, conchars_view, 0); - dfunc->vkFreeMemory (device->dev, conchars_memory, 0); - dfunc->vkDestroyImage (device->dev, conchars_image, 0); + QFV_DestroyScrap (draw_scrap); } void @@ -214,37 +213,24 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) VkCommandBuffer cmd = ctx->cmdbuffer; create_quad_buffers (ctx); - - qpic_t *charspic = Draw_Font8x8Pic (); - VkExtent3D extent = { charspic->width, charspic->height, 1 }; - conchars_image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - VK_FORMAT_A1R5G5B5_UNORM_PACK16, - extent, 1, 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_USAGE_TRANSFER_DST_BIT - | VK_IMAGE_USAGE_TRANSFER_SRC_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT); - conchars_memory = QFV_AllocImageMemory (device, conchars_image, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - 0, 0); - QFV_BindImageMemory (device, conchars_image, conchars_memory, 0); - conchars_view = QFV_CreateImageView (device, conchars_image, - VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_A1R5G5B5_UNORM_PACK16, - VK_IMAGE_ASPECT_COLOR_BIT); + draw_scrap = QFV_CreateScrap (device, 2048, QFV_RGBA); conchars_sampler = QFV_GetSampler (ctx, "quakepic"); - uint16_t *chars_data = ctx->staging[0]->data; + qpic_t *charspic = Draw_Font8x8Pic (); + + conchars = QFV_ScrapSubpic (draw_scrap, charspic->width, charspic->height); + + byte *chars_data = QFV_SubpicBatch (conchars, ctx->staging[0]); size_t size = charspic->width * charspic->height; for (size_t i = 0; i < size; i++) { - // convert 0xff = transparent, 0xfe = white to 0x0000 and 0xffff - // for a1r5g5b5 - uint16_t pix = (charspic->data[i] & 1) - 1; - chars_data[i] = pix; + byte pix = charspic->data[i]; + byte *col = vid.palette + pix * 3; + *chars_data++ = *col++; + *chars_data++ = *col++; + *chars_data++ = *col++; + *chars_data++ = (pix == 255) - 1; } - QFV_FlushStagingBuffer (ctx->staging[0], 0, size * sizeof (uint16_t)); - VkImageMemoryBarrier barrier; - qfv_pipelinestagepair_t stages; + dfunc->vkWaitForFences (device->dev, 1, &ctx->fence, VK_TRUE, ~0ull); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferBeginInfo beginInfo = { @@ -252,33 +238,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0, }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; - barrier=imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; - barrier.image = conchars_image; - dfunc->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, - 0, 0, - 0, 0, - 1, &barrier); - - VkBufferImageCopy region = { - 0, 0, 0, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, - { 0, 0, 0 }, - { charspic->width, charspic->height, 1 }, - }; - dfunc->vkCmdCopyBufferToImage (cmd, - ctx->staging[0]->buffer, conchars_image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ®ion); - - stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier.image = conchars_image; - dfunc->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, - 0, 0, - 0, 0, - 1, &barrier); + QFV_ScrapFlush (draw_scrap, ctx->staging[0], cmd); dfunc->vkEndCommandBuffer (cmd); VkSubmitInfo submitInfo = { @@ -305,7 +265,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) }; VkDescriptorImageInfo imageInfo = { conchars_sampler, - conchars_view, + QFV_ScrapImageView (draw_scrap), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; __auto_type cmdBuffers @@ -347,10 +307,12 @@ draw_pic (float x, float y, int w, int h, qpic_t *pic, drawvert_t *verts = quad_verts + num_quads * VERTS_PER_QUAD; num_quads += VERTS_PER_QUAD; - float sl = (srcx + 0.03125) / 128.0; - float sr = (srcx + srcw - 0.03125) / 128.0; - float st = (srcy + 0.03125) / 128.0; - float sb = (srcy + srch - 0.03125) / 128.0; + //FIXME extract subpic from pic + float size = conchars->size; + float sl = (srcx + 0.03125) * size; + float sr = (srcx + srcw - 0.03125) * size; + float st = (srcy + 0.03125) * size; + float sb = (srcy + srch - 0.03125) * size; verts[0].xy[0] = x; verts[0].xy[1] = y; From eebf3158facf24b268e07be68e764aa69290cd45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Jan 2021 15:24:50 +0900 Subject: [PATCH 1201/3664] [ruamoko] Check for null when allocating objects It's difficult for progs to check for errors when the engine crashes out from underneath them :P --- libs/ruamoko/rua_obj.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 155124b9f..8612cd6f0 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1700,12 +1700,14 @@ class_create_instance (progs_t *pr, pr_class_t *class) { int size = (class->instance_size + 1) * sizeof (pr_type_t); pr_type_t *mem; - pr_id_t *id; + pr_id_t *id = 0; mem = PR_Zone_TagMalloc (pr, size, class->name); - memset (mem, 0, size); - id = (pr_id_t *) (mem + 1); - id->class_pointer = PR_SetPointer (pr, class); + if (mem) { + memset (mem, 0, size); + id = (pr_id_t *) (mem + 1); + id->class_pointer = PR_SetPointer (pr, class); + } return id; } @@ -1832,9 +1834,11 @@ rua_object_copy (progs_t *pr) pr_id_t *id; id = class_create_instance (pr, class); - memcpy (id, object, sizeof (pr_type_t) * class->instance_size); - // copy the retain count - ((pr_type_t *) id)[-1] = ((pr_type_t *) object)[-1]; + if (id) { + memcpy (id, object, sizeof (pr_type_t) * class->instance_size); + // copy the retain count + ((pr_type_t *) id)[-1] = ((pr_type_t *) object)[-1]; + } RETURN_POINTER (pr, id); } From 41b366186966ae986637f82b44c172c855954f4b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Jan 2021 15:28:56 +0900 Subject: [PATCH 1202/3664] [vulkan] Use the scrap for draw Draw now has its own staging buffer to use with its scrap. Also, a few fixes were needed for the staging buffer and scrap flush routines. Other than some synchronization issues with draw scrap flushing (currently worked around with a fence-wait) things seem to be working nicely. --- libs/video/renderer/vulkan/staging.c | 3 + libs/video/renderer/vulkan/texture.c | 4 + libs/video/renderer/vulkan/vulkan_draw.c | 116 +++++++++++++++-------- 3 files changed, 82 insertions(+), 41 deletions(-) diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 04e3897db..be181d00b 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -90,6 +90,9 @@ QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size) qfv_device_t *device = stage->device; qfv_devfuncs_t *dfunc = device->funcs; + size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + offset &= ~(atom - 1); + size = (size + atom - 1) & ~ (atom - 1); VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, stage->memory, offset, size diff --git a/libs/video/renderer/vulkan/texture.c b/libs/video/renderer/vulkan/texture.c index 6529800b1..12fba3932 100644 --- a/libs/video/renderer/vulkan/texture.c +++ b/libs/video/renderer/vulkan/texture.c @@ -223,6 +223,10 @@ QFV_SubpicBatch (subpic_t *subpic, qfv_stagebuf_t *stage) if (scrap->batch_free) { batch = scrap->batch_free; scrap->batch_free = batch->next; + batch->x = rect->x; + batch->y = rect->y; + batch->width = subpic->width; + batch->height = subpic->height; } else { batch = VRect_New (rect->x, rect->y, subpic->width, subpic->height); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index badc01332..ba2d7c24c 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -79,7 +79,8 @@ typedef struct { //FIXME move into a context struct VkSampler conchars_sampler; scrap_t *draw_scrap; -subpic_t *conchars; +qfv_stagebuf_t *draw_stage; +qpic_t *conchars; VkBuffer quad_vert_buffer; VkBuffer quad_ind_buffer; @@ -146,15 +147,58 @@ destroy_quad_buffers (vulkan_ctx_t *ctx) dfunc->vkDestroyBuffer (device->dev, quad_ind_buffer, 0); } +static void +flush_draw_scrap (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkCommandBuffer cmd = ctx->cmdbuffer; + + dfunc->vkWaitForFences (device->dev, 1, &ctx->fence, VK_TRUE, ~0ull); + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + QFV_ScrapFlush (draw_scrap, draw_stage, cmd); + dfunc->vkEndCommandBuffer (cmd); + + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + 0, 0, 0, + 1, &cmd, + 0, 0, + }; + dfunc->vkResetFences (device->dev, 1, &ctx->fence); + dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, ctx->fence); + dfunc->vkWaitForFences (device->dev, 1, &ctx->fence, VK_TRUE, ~0ull);//FIXME +} + static qpic_t * -pic_data (const char *name, int w, int h, const byte *data) +pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) { qpic_t *pic; + subpic_t *subpic; + byte *picdata; - pic = malloc (field_offset (qpic_t, data[w * h])); + pic = malloc (field_offset (qpic_t, data[sizeof (subpic_t)])); pic->width = w; pic->height = h; - memcpy (pic->data, data, pic->width * pic->height); + + subpic = QFV_ScrapSubpic (draw_scrap, w, h); + *(subpic_t **) pic->data = subpic; + + picdata = QFV_SubpicBatch (subpic, draw_stage); + size_t size = w * h; + for (size_t i = 0; i < size; i++) { + byte pix = *data++; + byte *col = vid.palette + pix * 3; + *picdata++ = *col++; + *picdata++ = *col++; + *picdata++ = *col++; + *picdata++ = (pix == 255) - 1; + } return pic; } @@ -162,7 +206,7 @@ qpic_t * Vulkan_Draw_MakePic (int width, int height, const byte *data, vulkan_ctx_t *ctx) { - return pic_data (0, width, height, data); + return pic_data (0, width, height, data, ctx); } void @@ -173,13 +217,18 @@ Vulkan_Draw_DestroyPic (qpic_t *pic, vulkan_ctx_t *ctx) qpic_t * Vulkan_Draw_PicFromWad (const char *name, vulkan_ctx_t *ctx) { - return pic_data (0, 1, 1, (const byte *)""); + qpic_t *wadpic = W_GetLumpName (name); + + if (!wadpic) { + return 0; + } + return pic_data (name, wadpic->width, wadpic->height, wadpic->data, ctx); } qpic_t * Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) { - return pic_data (0, 1, 1, (const byte *)""); + return pic_data (0, 1, 1, (const byte *)"", ctx); } void @@ -203,6 +252,7 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) dfunc->vkDestroyPipeline (device->dev, twod_pipeline, 0); QFV_DestroyScrap (draw_scrap); + QFV_DestroyStagingBuffer (draw_stage); } void @@ -210,45 +260,17 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - VkCommandBuffer cmd = ctx->cmdbuffer; create_quad_buffers (ctx); draw_scrap = QFV_CreateScrap (device, 2048, QFV_RGBA); + draw_stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024); conchars_sampler = QFV_GetSampler (ctx, "quakepic"); qpic_t *charspic = Draw_Font8x8Pic (); - conchars = QFV_ScrapSubpic (draw_scrap, charspic->width, charspic->height); + conchars = pic_data (0, charspic->width, charspic->height, charspic->data, ctx); - byte *chars_data = QFV_SubpicBatch (conchars, ctx->staging[0]); - size_t size = charspic->width * charspic->height; - for (size_t i = 0; i < size; i++) { - byte pix = charspic->data[i]; - byte *col = vid.palette + pix * 3; - *chars_data++ = *col++; - *chars_data++ = *col++; - *chars_data++ = *col++; - *chars_data++ = (pix == 255) - 1; - } - - dfunc->vkWaitForFences (device->dev, 1, &ctx->fence, VK_TRUE, ~0ull); - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - QFV_ScrapFlush (draw_scrap, ctx->staging[0], cmd); - dfunc->vkEndCommandBuffer (cmd); - - VkSubmitInfo submitInfo = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 0, 0, 0, - 1, &cmd, - 0, 0, - }; - dfunc->vkResetFences (device->dev, 1, &ctx->fence); - dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, ctx->fence); + flush_draw_scrap (ctx); twod_pipeline = Vulkan_CreatePipeline (ctx, "twod"); @@ -307,8 +329,11 @@ draw_pic (float x, float y, int w, int h, qpic_t *pic, drawvert_t *verts = quad_verts + num_quads * VERTS_PER_QUAD; num_quads += VERTS_PER_QUAD; - //FIXME extract subpic from pic - float size = conchars->size; + subpic_t *subpic = *(subpic_t **) pic->data; + srcx += subpic->rect->x; + srcy += subpic->rect->y; + + float size = subpic->size; float sl = (srcx + 0.03125) * size; float sr = (srcx + srcw - 0.03125) * size; float st = (srcy + 0.03125) * size; @@ -347,7 +372,7 @@ queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx) cx = chr % 16; cy = chr / 16; - draw_pic (x, y, 8, 8, 0/*FIXME*/, cx * 8, cy * 8, 8, 8, color); + draw_pic (x, y, 8, 8, conchars, cx * 8, cy * 8, 8, 8, color); } void @@ -437,11 +462,17 @@ Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx) void Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) { + static quat_t color = { 1, 1, 1, 1}; + draw_pic (x, y, pic->width, pic->height, pic, + 0, 0, pic->width, pic->height, color); } void Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) { + static quat_t color = { 1, 1, 1, 1}; + draw_pic (x, y, pic->width, pic->height, pic, + 0, 0, pic->width, pic->height, color); } void @@ -494,6 +525,9 @@ Vulkan_DrawReset (vulkan_ctx_t *ctx) void Vulkan_FlushText (vulkan_ctx_t *ctx) { + if (draw_stage->offset) { + flush_draw_scrap (ctx); + } qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type frame = &ctx->framebuffers.a[ctx->curFrame]; From 1205c935d00329ae5ae4f3f1e6373a74eaea8ce0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Jan 2021 16:47:49 +0900 Subject: [PATCH 1203/3664] [qfcc] Add failing test for static init The function local static init is being treated as a non-static init (ie, initialized each call). --- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/static-init.r | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tools/qfcc/test/static-init.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 3eb33892b..f328fcb6e 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -36,6 +36,7 @@ test_progs_dat=\ tools/qfcc/test/return-ivar.dat \ tools/qfcc/test/sendv.dat \ tools/qfcc/test/state.dat \ + tools/qfcc/test/static-init.dat \ tools/qfcc/test/struct-init-param.dat \ tools/qfcc/test/struct-nil-init.dat \ tools/qfcc/test/structarray.dat \ @@ -411,6 +412,16 @@ tools/qfcc/test/state.run: $(qfcc_test_run_deps) include $(state_dep) # am--include-marker r_depfiles_remade += $(state_dep) +tools_qfcc_test_static_init_dat_SOURCES=tools/qfcc/test/static-init.r +static_init_obj=$(tools_qfcc_test_static_init_dat_SOURCES:.r=.o) +static_init_dep=$(call qcautodep,$(tools_qfcc_test_static_init_dat_SOURCES)) +tools/qfcc/test/static-init.dat$(EXEEXT): $(static_init_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(static_init_obj) +tools/qfcc/test/static-init.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(static_init_dep) # am--include-marker +r_depfiles_remade += $(static_init_dep) + tools_qfcc_test_struct_init_param_dat_SOURCES=tools/qfcc/test/struct-init-param.r struct_init_param_obj=$(tools_qfcc_test_struct_init_param_dat_SOURCES:.r=.o) struct_init_param_dep=$(call qcautodep,$(tools_qfcc_test_struct_init_param_dat_SOURCES)) diff --git a/tools/qfcc/test/static-init.r b/tools/qfcc/test/static-init.r new file mode 100644 index 000000000..bbbe3f9a7 --- /dev/null +++ b/tools/qfcc/test/static-init.r @@ -0,0 +1,19 @@ +#include "test-harness.h" + +int count_down () +{ + static int count = 2; + count--; + return count > 0; +} + +int main() +{ + int ret = 0; + count_down (); + if (count_down ()) { + printf ("did not reach 0\n"); + ret |= 1; + } + return ret; +} From c7da999b6a956c24b3df8173c2fc4c8b974be6ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Jan 2021 18:08:30 +0900 Subject: [PATCH 1204/3664] [qfcc] Use local_expr only for local variables ie, not function-scope static variables. --- tools/qfcc/source/def.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 1fb204a67..d3299a0ab 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -597,7 +597,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, error (init, "type mismatch in initializer"); return; } - if (local_expr) { + if (storage == sc_local && local_expr) { sym->s.def->initialized = 1; init = assign_expr (new_symbol_expr (sym), init); // fold_constants takes care of int/float conversions From 1fcb16d8cfcd15ae8cecdb2a578b321af4101c1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Jan 2021 16:47:49 +0900 Subject: [PATCH 1205/3664] [qfcc] Add failing test for static init The function local static init is being treated as a non-static init (ie, initialized each call). --- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/static-init.r | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tools/qfcc/test/static-init.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 3eb33892b..f328fcb6e 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -36,6 +36,7 @@ test_progs_dat=\ tools/qfcc/test/return-ivar.dat \ tools/qfcc/test/sendv.dat \ tools/qfcc/test/state.dat \ + tools/qfcc/test/static-init.dat \ tools/qfcc/test/struct-init-param.dat \ tools/qfcc/test/struct-nil-init.dat \ tools/qfcc/test/structarray.dat \ @@ -411,6 +412,16 @@ tools/qfcc/test/state.run: $(qfcc_test_run_deps) include $(state_dep) # am--include-marker r_depfiles_remade += $(state_dep) +tools_qfcc_test_static_init_dat_SOURCES=tools/qfcc/test/static-init.r +static_init_obj=$(tools_qfcc_test_static_init_dat_SOURCES:.r=.o) +static_init_dep=$(call qcautodep,$(tools_qfcc_test_static_init_dat_SOURCES)) +tools/qfcc/test/static-init.dat$(EXEEXT): $(static_init_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(static_init_obj) +tools/qfcc/test/static-init.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(static_init_dep) # am--include-marker +r_depfiles_remade += $(static_init_dep) + tools_qfcc_test_struct_init_param_dat_SOURCES=tools/qfcc/test/struct-init-param.r struct_init_param_obj=$(tools_qfcc_test_struct_init_param_dat_SOURCES:.r=.o) struct_init_param_dep=$(call qcautodep,$(tools_qfcc_test_struct_init_param_dat_SOURCES)) diff --git a/tools/qfcc/test/static-init.r b/tools/qfcc/test/static-init.r new file mode 100644 index 000000000..bbbe3f9a7 --- /dev/null +++ b/tools/qfcc/test/static-init.r @@ -0,0 +1,19 @@ +#include "test-harness.h" + +int count_down () +{ + static int count = 2; + count--; + return count > 0; +} + +int main() +{ + int ret = 0; + count_down (); + if (count_down ()) { + printf ("did not reach 0\n"); + ret |= 1; + } + return ret; +} From 64c7efdc0c734abefe9665373eb8d2247e9937d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Jan 2021 18:08:30 +0900 Subject: [PATCH 1206/3664] [qfcc] Use local_expr only for local variables ie, not function-scope static variables. --- tools/qfcc/source/def.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 1fb204a67..d3299a0ab 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -597,7 +597,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, error (init, "type mismatch in initializer"); return; } - if (local_expr) { + if (storage == sc_local && local_expr) { sym->s.def->initialized = 1; init = assign_expr (new_symbol_expr (sym), init); // fold_constants takes care of int/float conversions From cef81741ebd1d0d3be9997d41998ba5c08fcf3b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 14 Jan 2021 00:44:34 +0900 Subject: [PATCH 1207/3664] [vulkan] Implement most of the 2D renderer The console background is missing, and scaled vs unscaled (currently always scaled) 2d, but otherwise everything seems to work. Lots of places to clean up, though. --- libs/video/renderer/vulkan/qfpipeline.plist | 10 +-- libs/video/renderer/vulkan/twod.frag | 2 - libs/video/renderer/vulkan/vulkan_draw.c | 85 ++++++++++++++++++++- 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index a291ddf09..385713c80 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -168,19 +168,19 @@ depthStencil = { depthTestEnable = true; depthWriteEnable = true; - depthCompareOp = less; + depthCompareOp = less_or_equal; depthBoundsTestEnable = false; stencilTestEnable = false; }; colorBlend = { logicOpEnable = false; attachments = ({ - blendEnable = false; - srcColorBlendFactor = src_color; - dstColorBlendFactor = zero; + blendEnable = true; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; colorBlendOp = add; srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = zero; + dstAlphaBlendFactor = one_minus_src_alpha; alphaBlendOp = add; colorWriteMask = r|g|b|a; }); diff --git a/libs/video/renderer/vulkan/twod.frag b/libs/video/renderer/vulkan/twod.frag index 83bda0874..a6a40212d 100644 --- a/libs/video/renderer/vulkan/twod.frag +++ b/libs/video/renderer/vulkan/twod.frag @@ -13,7 +13,5 @@ main (void) vec4 pix; pix = texture (Texture, st); - if (pix.a < 0.5) - discard; frag_color = pix * color; } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index ba2d7c24c..0262e1802 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -72,6 +72,12 @@ typedef struct { float color[4]; } drawvert_t; +typedef struct cachepic_s { + struct cachepic_s *next; + char *name; + qpic_t *pic; +} cachepic_t; + #define MAX_QUADS (65536) #define VERTS_PER_QUAD (4) #define INDS_PER_QUAD (5) // one per vert plus primitive reset @@ -81,6 +87,8 @@ VkSampler conchars_sampler; scrap_t *draw_scrap; qfv_stagebuf_t *draw_stage; qpic_t *conchars; +qpic_t *white_pic; +static hashtab_t *pic_cache; VkBuffer quad_vert_buffer; VkBuffer quad_ind_buffer; @@ -175,6 +183,41 @@ flush_draw_scrap (vulkan_ctx_t *ctx) dfunc->vkWaitForFences (device->dev, 1, &ctx->fence, VK_TRUE, ~0ull);//FIXME } +static void +pic_free (qpic_t *pic) +{ + subpic_t *subpic = *(subpic_t **) pic->data; + QFV_SubpicDelete (subpic); + free (pic); +} + +//FIXME use cmem? +static cachepic_t * +new_cachepic (const char *name, qpic_t *pic) +{ + cachepic_t *cp; + + cp = malloc (sizeof (cachepic_t)); + cp->name = strdup (name); + cp->pic = pic; + return cp; +} + +static void +cachepic_free (void *_cp, void *unused) +{ + cachepic_t *cp = (cachepic_t *) _cp; + pic_free (cp->pic); + free (cp->name); + free (cp); +} + +static const char * +cachepic_getkey (const void *_cp, void *unused) +{ + return ((cachepic_t *) _cp)->name; +} + static qpic_t * pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) { @@ -228,12 +271,29 @@ Vulkan_Draw_PicFromWad (const char *name, vulkan_ctx_t *ctx) qpic_t * Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) { - return pic_data (0, 1, 1, (const byte *)"", ctx); + qpic_t *p; + qpic_t *pic; + cachepic_t *cpic; + + if ((cpic = Hash_Find (pic_cache, path))) { + return cpic->pic; + } + if (strlen (path) < 4 || strcmp (path + strlen (path) - 4, ".lmp") + || !(p = (qpic_t *) QFS_LoadFile (QFS_FOpenFile (path), 0))) { + return 0; + } + + pic = pic_data (path, p->width, p->height, p->data, ctx); + free (p); + cpic = new_cachepic (path, pic); + Hash_Add (pic_cache, cpic); + return pic; } void Vulkan_Draw_UncachePic (const char *path, vulkan_ctx_t *ctx) { + Hash_Free (pic_cache, Hash_Del (pic_cache, path)); } void @@ -261,6 +321,9 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + //FIXME move into struct + pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, 0, 0); + create_quad_buffers (ctx); draw_scrap = QFV_CreateScrap (device, 2048, QFV_RGBA); draw_stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024); @@ -269,6 +332,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) qpic_t *charspic = Draw_Font8x8Pic (); conchars = pic_data (0, charspic->width, charspic->height, charspic->data, ctx); + byte white_block = 0xfe; + white_pic = pic_data (0, 1, 1, &white_block, ctx); flush_draw_scrap (ctx); @@ -480,6 +545,8 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height, vulkan_ctx_t *ctx) { + static quat_t color = { 1, 1, 1, 1}; + draw_pic (x, y, width, height, pic, srcx, srcy, width, height, color); } void @@ -495,11 +562,24 @@ Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) void Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) { + quat_t color; + + VectorScale (vid.palette + c * 3, 1.0f/255.0f, color); + color[3] = 1; + draw_pic (x, y, w, h, white_pic, 0, 0, 1, 1, color); +} + +static inline void +draw_blendscreen (quat_t color) +{ + draw_pic (0, 0, vid.conwidth, vid.conheight, white_pic, 0, 0, 1, 1, color); } void Vulkan_Draw_FadeScreen (vulkan_ctx_t *ctx) { + static quat_t color = { 0, 0, 0, 0.7 }; + draw_blendscreen (color); } void @@ -577,4 +657,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) void Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) { + if (color[3]) { + draw_blendscreen (color); + } } From ad9c3193faa5230c665ac4e215f6d3e58af6eced Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 15 Jan 2021 22:45:49 +0900 Subject: [PATCH 1208/3664] [vulkan] Use darray size to control cmd buffer count This allows the array in which the command buffers are allocated to be allocated on the stack using alloca and thus remove the need to malloc/free of relatively small chunks. --- include/QF/Vulkan/command.h | 11 ++++++++--- libs/video/renderer/vid_render_vulkan.c | 7 +++---- libs/video/renderer/vulkan/command.c | 12 +++++------- libs/video/renderer/vulkan/vulkan_draw.c | 9 ++++----- libs/video/renderer/vulkan/vulkan_vid_common.c | 7 +++---- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 925a63781..47418db1a 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -6,6 +6,9 @@ typedef struct qfv_cmdbufferset_s DARRAY_TYPE (VkCommandBuffer) qfv_cmdbufferset_t; +#define QFV_AllocCommandBufferSet(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_cmdbufferset_t, num, allocator) + typedef struct qfv_semaphoreset_s DARRAY_TYPE (VkSemaphore) qfv_semaphoreset_t; @@ -23,9 +26,11 @@ struct qfv_device_s; VkCommandPool QFV_CreateCommandPool (struct qfv_device_s *device, uint32_t queueFamily, int transient, int reset); -qfv_cmdbufferset_t *QFV_AllocateCommandBuffers (struct qfv_device_s *device, - VkCommandPool pool, - int secondary, int count); +/** Allocate bufferset->size command buffers + */ +int QFV_AllocateCommandBuffers (struct qfv_device_s *device, + VkCommandPool pool, int secondary, + qfv_cmdbufferset_t *bufferset); VkSemaphore QFV_CreateSemaphore (struct qfv_device_s *device); VkFence QFV_CreateFence (struct qfv_device_s *device, int signaled); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 995763baf..f68e8c182 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -389,11 +389,10 @@ vulkan_vid_render_choose_visual (void) vulkan_ctx->cmdpool = QFV_CreateCommandPool (vulkan_ctx->device, vulkan_ctx->device->queue.queueFamily, 0, 1); - __auto_type cmdset = QFV_AllocateCommandBuffers (vulkan_ctx->device, - vulkan_ctx->cmdpool, - 0, 1); + __auto_type cmdset = QFV_AllocCommandBufferSet (1, alloca); + QFV_AllocateCommandBuffers (vulkan_ctx->device, vulkan_ctx->cmdpool, 0, + cmdset); vulkan_ctx->cmdbuffer = cmdset->a[0]; - free (cmdset); vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1); Sys_Printf ("vk choose visual %p %p %d %p\n", vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue, diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 8ba60ab32..10f0cc559 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -87,9 +87,9 @@ QFV_CreateCommandPool (qfv_device_t *device, uint32_t queueFamily, return pool; } -qfv_cmdbufferset_t * +int QFV_AllocateCommandBuffers (qfv_device_t *device, VkCommandPool pool, - int secondary, int count) + int secondary, qfv_cmdbufferset_t *bufferset) { VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; @@ -99,12 +99,10 @@ QFV_AllocateCommandBuffers (qfv_device_t *device, VkCommandPool pool, } VkCommandBufferAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 0, - pool, level, count + pool, level, bufferset->size }; - qfv_cmdbufferset_t *cmdbufferset; - cmdbufferset = DARRAY_ALLOCFIXED (*cmdbufferset, count, malloc); - dfunc->vkAllocateCommandBuffers (dev, &allocInfo, cmdbufferset->a); - return cmdbufferset; + int ret = dfunc->vkAllocateCommandBuffers (dev, &allocInfo, bufferset->a); + return ret == VK_SUCCESS; } VkSemaphore diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 0262e1802..61b85d3e1 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -355,12 +355,12 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) QFV_ScrapImageView (draw_scrap), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; - __auto_type cmdBuffers - = QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, - ctx->framebuffers.size); + size_t frames = ctx->framebuffers.size; + __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); - for (size_t i = 0; i < ctx->framebuffers.size; i++) { + for (size_t i = 0; i < frames; i++) { __auto_type frame = &ctx->framebuffers.a[i]; frame->twodDescriptors = sets->a[i]; @@ -379,7 +379,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) DARRAY_APPEND (frame->subCommand, cmdBuffers->a[i]); } free (sets); - free (cmdBuffers); } static inline void diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 126d602fd..16e60e5c1 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -402,9 +402,9 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) attachments->a[0] = ctx->renderpass.colorImage->view; attachments->a[1] = ctx->renderpass.depthImage->view; - __auto_type cmdBuffers - = QFV_AllocateCommandBuffers (device, cmdpool, 0, - ctx->framebuffers.size); + __auto_type cmdBuffers = QFV_AllocCommandBufferSet (ctx->framebuffers.size, + alloca); + QFV_AllocateCommandBuffers (device, cmdpool, 0, cmdBuffers); for (size_t i = 0; i < ctx->framebuffers.size; i++) { attachments->a[2] = sc->imageViews->a[i]; @@ -420,7 +420,6 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) frame->subCommand = malloc (sizeof (qfv_cmdbufferset_t)); DARRAY_INIT (frame->subCommand, 4); } - free (cmdBuffers); } void From 92afe9f265ef74243138cb12508bf3317c9487cf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 15 Jan 2021 22:50:04 +0900 Subject: [PATCH 1209/3664] [vulkan] Convert stagebuf to a ring buffer I should have known this would be necessary, but it fixes the corruption when updating the scrap. --- include/QF/Vulkan/funclist.h | 1 + include/QF/Vulkan/staging.h | 24 +- include/QF/Vulkan/texture.h | 20 +- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vulkan/staging.c | 180 ++++++- libs/video/renderer/vulkan/test/Makemodule.am | 19 + .../video/renderer/vulkan/test/test-staging.c | 438 ++++++++++++++++++ libs/video/renderer/vulkan/texture.c | 39 +- libs/video/renderer/vulkan/vulkan_draw.c | 32 +- .../video/renderer/vulkan/vulkan_vid_common.c | 6 +- 10 files changed, 688 insertions(+), 72 deletions(-) create mode 100644 libs/video/renderer/vulkan/test/Makemodule.am create mode 100644 libs/video/renderer/vulkan/test/test-staging.c diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 534097b5d..63c5bde29 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -101,6 +101,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateFence) DEVICE_LEVEL_VULKAN_FUNCTION (vkWaitForFences) DEVICE_LEVEL_VULKAN_FUNCTION (vkResetFences) +DEVICE_LEVEL_VULKAN_FUNCTION (vkGetFenceStatus) DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueSubmit) DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueWaitIdle) DEVICE_LEVEL_VULKAN_FUNCTION (vkDeviceWaitIdle) diff --git a/include/QF/Vulkan/staging.h b/include/QF/Vulkan/staging.h index 9a90edd6e..aaac5d749 100644 --- a/include/QF/Vulkan/staging.h +++ b/include/QF/Vulkan/staging.h @@ -1,20 +1,36 @@ #ifndef __QF_Vulkan_staging_h #define __QF_Vulkan_staging_h +typedef struct qfv_packet_s { + struct qfv_stagebuf_s *stage; ///< staging buffer that owns this packet + VkCommandBuffer cmd; + VkFence fence; + size_t offset; + size_t length; +} qfv_packet_t; + typedef struct qfv_stagebuf_s { struct qfv_device_s *device; VkBuffer buffer; VkDeviceMemory memory; - size_t size; - size_t offset; ///< for batching building + qfv_packet_t *packet; ///< array of packets for controlling access + size_t num_packets;///< number of packets in array + size_t next_packet;///< index of the next packet to be used + size_t size; ///< actual size of the buffer + size_t end; ///< effective end of the buffer due to early wrap + size_t head; + size_t tail; void *data; } qfv_stagebuf_t; qfv_stagebuf_t *QFV_CreateStagingBuffer (struct qfv_device_s *device, - size_t size); + size_t size, int num_packets, + VkCommandPool cmdPool); void QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage); void QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size); -void *QFV_ClaimStagingBuffer (qfv_stagebuf_t *stage, size_t size); +qfv_packet_t *QFV_PacketAcquire (qfv_stagebuf_t *stage); +void *QFV_PacketExtend (qfv_packet_t *packet, size_t size); +void QFV_PacketSubmit (qfv_packet_t *packet); #endif//__QF_Vulkan_staging_h diff --git a/include/QF/Vulkan/texture.h b/include/QF/Vulkan/texture.h index 6a55815f6..e24fa0eb1 100644 --- a/include/QF/Vulkan/texture.h +++ b/include/QF/Vulkan/texture.h @@ -18,26 +18,8 @@ VkImageView QFV_ScrapImageView (scrap_t *scrap) __attribute__((pure)); subpic_t *QFV_ScrapSubpic (scrap_t *scrap, int width, int height); void QFV_SubpicDelete (subpic_t *subpic); -/** Add an update region to the batch queue. - * - * The region to be updated is recorded in the batch queue, space allocated - * in the staging buffer, and a pointer to the allocated space is returned. - * - * \note No data is stransfered. This facilitates writing generated data - * directly to the staging buffer. - */ void *QFV_SubpicBatch (subpic_t *subpic, struct qfv_stagebuf_s *stage); -/** Flush all batched subpic updates. - * - * The offset in the staging bufffer \a stage is reset to 0. The command - * buffer is populated with the appropriate image layout barriers and the - * necessary copy commands. - * - * \note The command buffer is neither begun nor ended, nor is it submitted - * to a queue. This is to maximize flexibility in command buffer usage. - */ -void QFV_ScrapFlush (scrap_t *scrap, struct qfv_stagebuf_s *stage, - VkCommandBuffer cmd); +void QFV_ScrapFlush (scrap_t *scrap); #endif//__QF_Vulkan_texture_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 6f306ffe5..7a323f118 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -1,3 +1,4 @@ +include libs/video/renderer/vulkan/test/Makemodule.am include libs/video/renderer/vulkan/vkgen/Makemodule.am #lib_LTLIBRARIES += @VID_REND_TARGETS@ diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index be181d00b..40ad459a6 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -47,6 +47,7 @@ #include "QF/sys.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/staging.h" @@ -54,21 +55,39 @@ #include "vid_vulkan.h" qfv_stagebuf_t * -QFV_CreateStagingBuffer (qfv_device_t *device, size_t size) +QFV_CreateStagingBuffer (qfv_device_t *device, size_t size, int num_packets, + VkCommandPool cmdPool) { qfv_devfuncs_t *dfunc = device->funcs; - qfv_stagebuf_t *stage = malloc (sizeof (qfv_stagebuf_t)); - stage->size = size; - stage->offset = 0; + qfv_stagebuf_t *stage = malloc (sizeof (qfv_stagebuf_t) + + num_packets * sizeof (qfv_packet_t)); stage->device = device; stage->buffer = QFV_CreateBuffer (device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); stage->memory = QFV_AllocBufferMemory (device, stage->buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, size, 0); - QFV_BindBufferMemory (device, stage->buffer, stage->memory, 0); + stage->packet = (qfv_packet_t *) (stage + 1); + stage->num_packets = num_packets; + stage->next_packet = 0; + stage->size = size; + stage->end = size; + stage->head = 0; + stage->tail = 0; + dfunc->vkMapMemory (device->dev, stage->memory, 0, size, 0, &stage->data); + QFV_BindBufferMemory (device, stage->buffer, stage->memory, 0); + + __auto_type bufferset = QFV_AllocCommandBufferSet (num_packets, alloca); + QFV_AllocateCommandBuffers (device, cmdPool, 0, bufferset); + for (int i = 0; i < num_packets; i++) { + stage->packet[i].stage = stage; + stage->packet[i].cmd = bufferset->a[i]; + stage->packet[i].fence = QFV_CreateFence (device, 1); + stage->packet[i].offset = 0; + stage->packet[i].length = 0; + } return stage; } @@ -78,6 +97,10 @@ QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage) qfv_device_t *device = stage->device; qfv_devfuncs_t *dfunc = device->funcs; + for (size_t i = 0; i < stage->num_packets; i++) { + dfunc->vkDestroyFence (device->dev, stage->packet[i].fence, 0); + } + dfunc->vkUnmapMemory (device->dev, stage->memory); dfunc->vkFreeMemory (device->dev, stage->memory, 0); dfunc->vkDestroyBuffer (device->dev, stage->buffer, 0); @@ -100,13 +123,150 @@ QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size) dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); } -void * -QFV_ClaimStagingBuffer (qfv_stagebuf_t *stage, size_t size) +static void +advance_tail (qfv_stagebuf_t *stage, qfv_packet_t *packet) { - if (stage->offset + size > stage->size) { + qfv_device_t *device = stage->device; + qfv_devfuncs_t *dfunc = device->funcs; + + qfv_packet_t *start = packet; + + while (1) { + if ((size_t) (++packet - stage->packet) >= stage->num_packets) { + packet = stage->packet; + } + if (packet != start + && (dfunc->vkGetFenceStatus (device->dev, packet->fence) + == VK_SUCCESS)) { + if (packet->length == 0) { + continue; + } + if ((stage->tail == stage->end && packet->offset == 0) + || stage->tail == packet->offset) { + stage->tail = packet->offset + packet->length; + packet->length = 0; + if (stage->tail >= stage->end) { + stage->end = stage->size; + stage->tail = stage->size; + } + } + continue; + } + // Packets are always aquired in sequence and thus the first busy + // packet after the start packet marks the end of available space. + // Alternatively, there is only one packet and we've looped around + // back to the start packet. Must ensure the tail is updated + if (stage->tail >= stage->end && packet->offset == 0) { + stage->end = stage->size; + stage->tail = packet->offset; + } + break; + } +} + +qfv_packet_t * +QFV_PacketAcquire (qfv_stagebuf_t *stage) +{ + qfv_device_t *device = stage->device; + qfv_devfuncs_t *dfunc = device->funcs; + qfv_packet_t *packet = &stage->packet[stage->next_packet++]; + stage->next_packet %= stage->num_packets; + + dfunc->vkWaitForFences (device->dev, 1, &packet->fence, VK_TRUE, ~0ull); + + advance_tail (stage, packet); + if (stage->head == stage->size) { + stage->head = 0; + } + packet->offset = stage->head; + packet->length = 0; + + dfunc->vkResetFences (device->dev, 1, &packet->fence); + dfunc->vkResetCommandBuffer (packet->cmd, 0); + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0, + }; + dfunc->vkBeginCommandBuffer (packet->cmd, &beginInfo); + + return packet; +} + +void * +QFV_PacketExtend (qfv_packet_t *packet, size_t size) +{ + qfv_stagebuf_t *stage = packet->stage; + if (!size || size > stage->size) { return 0; } - void *data = (byte *) stage->data + stage->offset; - stage->offset += (size + 3) & ~3; + + //FIXME extra logic may be needed to wait wait for space to become + //available when the requested size should fit but can't due to in-flight + //packets + advance_tail (stage, packet); + + size_t head = stage->head; + size_t end = stage->end; + if (head + size > stage->end) { + if (packet->length) { + // packets cannot wrap around the buffer (must use separate + // packets) + return 0; + } + if (stage->tail == 0) { + // the beginning of the the staging buffer is occupied + return 0; + } + packet->offset = 0; + head = 0; + end = stage->head; + } + if (head < stage->tail && head + size > stage->tail) { + // not enough room for the sub-packet + return 0; + } + void *data = (byte *) stage->data + head; + stage->end = end; + stage->head = head + size; + packet->length += size; return data; } + +void +QFV_PacketSubmit (qfv_packet_t *packet) +{ + qfv_stagebuf_t *stage = packet->stage; + qfv_device_t *device = stage->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (!packet->length) { + // XXX at this stage, this looks the same as below, I think a queue + // completing is the only way to set a fence (other than creation), + // so submit the (hopefully) empty command buffer so the fence becomes + // set, but without waiting on or triggering any semaphores. + dfunc->vkEndCommandBuffer (packet->cmd); + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + 0, 0, 0, + 1, &packet->cmd, + 0, 0, + }; + dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, + packet->fence); + return; + } + + QFV_FlushStagingBuffer (stage, packet->offset, packet->length); + + dfunc->vkEndCommandBuffer (packet->cmd); + //XXX it may become necessary to pass in semaphores etc (maybe add to + //packet?) + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + 0, 0, 0, + 1, &packet->cmd, + 0, 0, + }; + // The fence was reset when the packet was acquired + dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, packet->fence); +} diff --git a/libs/video/renderer/vulkan/test/Makemodule.am b/libs/video/renderer/vulkan/test/Makemodule.am new file mode 100644 index 000000000..cacb206f3 --- /dev/null +++ b/libs/video/renderer/vulkan/test/Makemodule.am @@ -0,0 +1,19 @@ +libs_video_renderer_vulkan_tests = \ + libs/video/renderer/vulkan/test/test-staging \ + $e + +TESTS += $(libs_video_renderer_vulkan_tests) + +check_PROGRAMS += $(libs_video_renderer_vulkan_tests) + +libs_video_renderer_vulkan_test_libs= \ + libs/video/renderer/vid_render_vulkan.la \ + libs/util/libQFutil.la + +libs_video_renderer_vulkan_test_test_staging_SOURCES= \ + libs/video/renderer/vulkan/test/test-staging.c \ + $e +libs_video_renderer_vulkan_test_test_staging_LDADD= \ + $(libs_video_renderer_vulkan_test_libs) +libs_video_renderer_vulkan_test_test_staging_DEPENDENCIES= \ + $(libs_video_renderer_vulkan_test_libs) diff --git a/libs/video/renderer/vulkan/test/test-staging.c b/libs/video/renderer/vulkan/test/test-staging.c new file mode 100644 index 000000000..bb5361cec --- /dev/null +++ b/libs/video/renderer/vulkan/test/test-staging.c @@ -0,0 +1,438 @@ +#include +#include +#include +#include + +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/staging.h" + +void *stage_memory; + +static VkResult +vkMapMemory (VkDevice device, VkDeviceMemory memory, + VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, + void **data) +{ + char *buf = calloc (1, size); + stage_memory = buf; + *data = buf; + return VK_SUCCESS; +} + +static VkResult +vkBindBufferMemory (VkDevice device, VkBuffer buffer, VkDeviceMemory memory, + VkDeviceSize offset) +{ + return VK_SUCCESS; +} + +static VkResult +vkCreateBuffer (VkDevice device, const VkBufferCreateInfo *cinfo, + const VkAllocationCallbacks *allocator, VkBuffer *buffer) +{ + *buffer = 0; + return VK_SUCCESS; +} + +static void +vkGetBufferMemoryRequirements (VkDevice device, VkBuffer buffer, + VkMemoryRequirements *requirements) +{ + memset (requirements, 0, sizeof (*requirements)); +} + +static VkResult +vkAllocateCommandBuffers (VkDevice device, + const VkCommandBufferAllocateInfo *info, + VkCommandBuffer *buffers) +{ + static size_t cmdBuffer = 0; + + for (uint32_t i = 0; i < info->commandBufferCount; i++) { + buffers[i] = (VkCommandBuffer) ++cmdBuffer; + } + return VK_SUCCESS; +} + +static VkResult +vkCreateFence (VkDevice device, const VkFenceCreateInfo *info, + const VkAllocationCallbacks *allocator, VkFence *fence) +{ + int *f = malloc (sizeof (int)); + *f = info->flags & VK_FENCE_CREATE_SIGNALED_BIT ? 1 : 0; + *(int **)fence = f; + return VK_SUCCESS; +} + +static VkResult +vkWaitForFences (VkDevice device, uint32_t fenceCount, const VkFence *fences, + VkBool32 waitAll, uint64_t timeout) +{ + for (uint32_t i = 0; i < fenceCount; i++) { + int *f = (int *)fences[i]; + *f = 0; + } + return VK_SUCCESS; +} + +static VkResult +vkResetFences (VkDevice device, uint32_t fenceCount, const VkFence *fences) +{ + for (uint32_t i = 0; i < fenceCount; i++) { + int *f = (int *)fences[i]; + *f = 0; + } + return VK_SUCCESS; +} + +static VkResult +vkGetFenceStatus (VkDevice device, VkFence fence) +{ + int *f = (int *)fence; + return *f ? VK_SUCCESS : VK_NOT_READY; +} + +static VkResult +vkResetCommandBuffer (VkCommandBuffer buffer, VkCommandBufferResetFlags flags) +{ + return VK_SUCCESS; +} + +static VkResult +vkBeginCommandBuffer (VkCommandBuffer buffer, + const VkCommandBufferBeginInfo *info) +{ + return VK_SUCCESS; +} + +static VkResult +vkEndCommandBuffer (VkCommandBuffer buffer) +{ + return VK_SUCCESS; +} + +static VkResult +vkFlushMappedMemoryRanges (VkDevice device, uint32_t count, + const VkMappedMemoryRange *ranges) +{ + return VK_SUCCESS; +} + +static VkResult +vkQueueSubmit (VkQueue queue, uint32_t count, const VkSubmitInfo *submits, + VkFence fence) +{ + int *f = (int *)fence; + *f = 1; + return VK_SUCCESS; +} + +qfv_devfuncs_t dfuncs = { + vkCreateBuffer:vkCreateBuffer, + vkGetBufferMemoryRequirements:vkGetBufferMemoryRequirements, + vkMapMemory:vkMapMemory, + vkBindBufferMemory:vkBindBufferMemory, + vkAllocateCommandBuffers:vkAllocateCommandBuffers, + vkCreateFence:vkCreateFence, + vkWaitForFences:vkWaitForFences, + vkResetFences:vkResetFences, + vkGetFenceStatus:vkGetFenceStatus, + vkResetCommandBuffer:vkResetCommandBuffer, + vkBeginCommandBuffer:vkBeginCommandBuffer, + vkEndCommandBuffer:vkEndCommandBuffer, + vkFlushMappedMemoryRanges:vkFlushMappedMemoryRanges, + vkQueueSubmit:vkQueueSubmit, +}; +qfv_physdev_t physDev; +qfv_device_t device = { + physDev:&physDev, + funcs:&dfuncs, +}; + +static void __attribute__ ((format (printf, 2, 3), noreturn)) +_error (int line, const char *fmt, ...) +{ + va_list args; + + va_start (args, fmt); + fprintf (stderr, "%d: ", line); + vfprintf (stderr, fmt, args); + fprintf (stderr, "\n"); + va_end (args); + exit(1); +} +#define error(fmt...) _error(__LINE__, fmt) + +int +main (void) +{ + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (&device, 1024, 4, 0); + + if (stage->num_packets != 4) { + error ("stage has incorrect packet count: %zd\n", stage->num_packets); + } + if (stage->next_packet != 0) { + error ("stage has incorrect next_packet: %zd\n", stage->next_packet); + } + if (stage->size != 1024) { + error ("stage has incorrect size: %zd\n", stage->size); + } + if (stage->end != stage->size) { + error ("stage has incorrect end: %zd\n", stage->end); + } + if (stage->head || stage->tail != stage->head) { + error ("stage ring buffer not initialized: h:%zd t:%zd\n", + stage->head, stage->tail); + } + if (!stage->data || stage->data != stage_memory) { + error ("stage memory not mapped: d:%p, m:%p\n", + stage->data, stage_memory); + } + + for (size_t i = 0; i < stage->num_packets; i++) { + qfv_packet_t *p = &stage->packet[i]; + if (p->stage != stage) { + error ("packet[%zd] stage not set: ps:%p s:%p\n", i, + p->stage, stage); + } + if (!p->cmd) { + error ("packet[%zd] has no command buffer\n", i); + } + if (!p->fence) { + error ("packet[%zd] has no fence\n", i); + } + for (size_t j = 0; j < i; j++) { + qfv_packet_t *q = &stage->packet[j]; + if (q->cmd == p->cmd || q->fence == p->fence) { + error ("packet[%zd] has dup fence or cmd buf\n", i); + } + } + if (vkGetFenceStatus (device.dev, p->fence) != VK_SUCCESS) { + error ("packet[%zd].fence is not signaled\n", i); + } + if (p->offset || p->length) { + error ("packet[%zd] size/length not initialized: o:%zd l:%zd\n", + i, p->offset, p->length); + } + } + + qfv_packet_t *packet = QFV_PacketAcquire (stage); + if (vkGetFenceStatus (device.dev, packet->fence) != VK_NOT_READY) { + error ("packet.fence is signaled\n"); + } + + void *data; + size_t old_head, old_tail; + + old_head = stage->head; + old_tail = stage->tail; + data = QFV_PacketExtend (packet, 0); + if (data) { + error ("0 byte extend did not return null\n"); + } + if (stage->head != old_head || stage->tail != old_tail) { + error ("0 byte extend moved head or tail\n"); + } + + data = QFV_PacketExtend (packet, 2048); + if (data) { + error ("2048 byte extend did not return null\n"); + } + if (stage->head != old_head || stage->tail != old_tail) { + error ("2048 byte extend moved head or tail\n"); + } + + data = QFV_PacketExtend (packet, 1024); + if (!data) { + error ("1024 byte extend failed\n"); + } + if (stage->head == old_head) { + error ("1024 byte extend did not move head\n"); + } + if (stage->tail != old_tail) { + error ("1024 byte extend moved tail\n"); + } + if (stage->head > stage->size) { + error ("stage head out of bounds: %zd\n", stage->head); + } + if (packet->offset != old_head || packet->length != 1024) { + error ("packet offset/size incorrect: p:%zd,%zd h:%zd\n", + packet->offset, packet->length, old_head); + } + if (stage->head < packet->offset + packet->length) { + error ("stage head before end of packet: %zd, pe:%zd\n", + stage->head, packet->offset + packet->length); + } + + old_head = stage->head; + old_tail = stage->tail; + data = QFV_PacketExtend (packet, 16); + if (data) { + error ("16 byte extend in full stage did not return null\n"); + } + if (stage->head != old_head || stage->tail != old_tail) { + error ("16 byte extend moved head or tail\n"); + } + QFV_PacketSubmit (packet); + if (vkGetFenceStatus (device.dev, packet->fence) != VK_SUCCESS) { + error ("packet.fence is not signaled\n"); + } + + if (stage->head != 1024 || stage->tail != 0) { + error ("stage head or tail not as expected: h: %zd t:%zd\n", + stage->head, stage->tail); + } + + qfv_packet_t *packet2 = QFV_PacketAcquire (stage); + if (!packet2 || packet2 == packet) { + error ("did not get new packet: n:%p o:%p\n", packet2, packet); + } + packet = packet2; + if (packet->offset != 0 || stage->head != 0 || stage->tail != 0) { + error ("new packet did not wrap: p:%zd h:%zd t:%zd\n", + packet2->offset, stage->head, stage->tail); + } + + old_head = stage->head; + old_tail = stage->tail; + data = QFV_PacketExtend (packet, 768); + if (!data) { + error ("768 byte extend failed\n"); + } + if (stage->head == old_head) { + error ("768 byte extend did not move head\n"); + } + if (stage->tail != 0) { + error ("768 byte extend dit not wrap tail: %zd\n", stage->tail); + } + if (stage->head > stage->size) { + error ("stage head out of bounds: %zd\n", stage->head); + } + if (packet->offset != old_head || packet->length != 768) { + error ("packet offset/size incorrect: p:%zd,%zd h:%zd\n", + packet->offset, packet->length, old_head); + } + if (stage->head < packet->offset + packet->length) { + error ("stage head before end of packet: %zd, pe:%zd\n", + stage->head, packet->offset + packet->length); + } + + // test attempting to wrap the packet (without needed space) + old_head = stage->head; + old_tail = stage->tail; + data = QFV_PacketExtend (packet, 512); + if (data) { + error ("512 byte extend in partially full stage succeeded\n"); + } + if (stage->head != old_head || stage->tail != old_tail) { + error ("512 byte extend moved head or tail\n"); + } + QFV_PacketSubmit (packet); + + if (stage->head != 768 || stage->tail != 0) { + error ("stage head or tail not as expected: h: %zd t:%zd\n", + stage->head, stage->tail); + } + + packet = QFV_PacketAcquire (stage); + + // test wrapping a new packet + data = QFV_PacketExtend (packet, 512); + if (!data) { + error ("512 byte extend failed\n"); + } + if (packet->offset != 0 || packet->length != 512) { + error ("packet offset/size incorrect: p:%zd,%zd\n", + packet->offset, packet->length); + } + if (stage->head != 512 || stage->tail != stage->end || stage->end !=768) { + error ("stage head or tail not as expected: h: %zd t:%zd\n", + stage->head, stage->tail); + } + data = QFV_PacketExtend (packet, 512); + if (!data) { + error ("second 512 byte extend failed\n"); + } + if (packet->offset != 0 || packet->length != 1024) { + error ("packet offset/size incorrect: p:%zd,%zd\n", + packet->offset, packet->length); + } + if (stage->head != 1024 || stage->tail != 0 || stage->end != 1024) { + error ("stage head or tail not as expected: h: %zd t:%zd\n", + stage->head, stage->tail); + } + QFV_PacketSubmit (packet); + + packet = QFV_PacketAcquire (stage); + data = QFV_PacketExtend (packet, 512); + if (!data) { + error ("512 byte extend failed\n"); + } + if (packet->offset != 0 || packet->length != 512) { + error ("packet offset/size incorrect: p:%zd,%zd\n", + packet->offset, packet->length); + } + QFV_PacketSubmit (packet); + + if (stage->head != 512 || stage->tail != 0 || stage->end != 1024) { + error ("stage head or tail not as expected: h: %zd t:%zd\n", + stage->head, stage->tail); + } + + packet = QFV_PacketAcquire (stage); + data = QFV_PacketExtend (packet, 256); + if (!data) { + error ("256 byte extend failed\n"); + } + if (packet->offset != 512 || packet->length != 256) { + error ("packet offset/size incorrect: p:%zd,%zd\n", + packet->offset, packet->length); + } + if (stage->head != 768 || stage->tail != 512 || stage->end != 1024) { + error ("stage head or tail not as expected: h: %zd t:%zd\n", + stage->head, stage->tail); + } + // don't submit yet. Normally, it would be an error, but the test harness + // needs to keep the packet on hand for the following tests to work + packet2 = QFV_PacketAcquire (stage); + old_head = stage->head; + old_tail = stage->tail; + data = QFV_PacketExtend (packet2, 768); + if (data) { + error ("768 byte extend did not return null\n"); + } + if (stage->head != old_head || stage->tail != old_tail) { + error ("768 byte extend moved head or tail\n"); + } + + //should wrap + data = QFV_PacketExtend (packet2, 512); + if (!data) { + error ("512 byte extend failed\n"); + } + if (packet2->offset != 0 || packet2->length != 512) { + error ("packet offset/size incorrect: p:%zd,%zd\n", + packet2->offset, packet2->length); + } + if (stage->head != 512 || stage->tail != 512 || stage->end != 768) { + error ("stage head or tail not as expected: h: %zd t:%zd\n", + stage->head, stage->tail); + } + + //submit the first packet + QFV_PacketSubmit (packet); + + packet = QFV_PacketAcquire (stage); + old_head = stage->head; + old_tail = stage->tail; + data = QFV_PacketExtend (packet, 768); + if (data) { + error ("768 byte extend did not return null\n"); + } + if (stage->head != old_head || stage->tail != old_tail) { + error ("768 byte extend moved head or tail\n"); + } + return 0; +} diff --git a/libs/video/renderer/vulkan/texture.c b/libs/video/renderer/vulkan/texture.c index 12fba3932..f23e1297a 100644 --- a/libs/video/renderer/vulkan/texture.c +++ b/libs/video/renderer/vulkan/texture.c @@ -65,6 +65,7 @@ struct scrap_s { VkDeviceMemory memory; VkImageView view; size_t bpp; + qfv_packet_t *packet; vrect_t *batch; vrect_t **batch_tail; vrect_t *batch_free; @@ -119,6 +120,7 @@ QFV_CreateScrap (qfv_device_t *device, int size, QFVFormat format) scrap->bpp = bpp; scrap->subpics = 0; scrap->device = device; + scrap->packet = 0; scrap->batch = 0; scrap->batch_tail = &scrap->batch; scrap->batch_free = 0; @@ -215,9 +217,21 @@ QFV_SubpicBatch (subpic_t *subpic, qfv_stagebuf_t *stage) byte *dest; size_t size; - size = subpic->width * subpic->height * scrap->bpp; - if (!(dest = QFV_ClaimStagingBuffer (stage, size))) { - return 0; + if (!scrap->packet) { + scrap->packet = QFV_PacketAcquire (stage); + } + size = (subpic->width * subpic->height * scrap->bpp + 3) & ~3; + if (!(dest = QFV_PacketExtend (scrap->packet, size))) { + if (scrap->packet->length) { + QFV_ScrapFlush (scrap); + + scrap->packet = QFV_PacketAcquire (stage); + dest = QFV_PacketExtend (scrap->packet, size); + } + if (!dest) { + printf ("could not get space for update\n"); + return 0; + } } if (scrap->batch_free) { @@ -238,7 +252,7 @@ QFV_SubpicBatch (subpic_t *subpic, qfv_stagebuf_t *stage) } void -QFV_ScrapFlush (scrap_t *scrap, qfv_stagebuf_t *stage, VkCommandBuffer cmd) +QFV_ScrapFlush (scrap_t *scrap) { qfv_device_t *device = scrap->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -247,6 +261,8 @@ QFV_ScrapFlush (scrap_t *scrap, qfv_stagebuf_t *stage, VkCommandBuffer cmd) return; } + qfv_packet_t *packet = scrap->packet; + qfv_stagebuf_t *stage = packet->stage; size_t i; __auto_type copy = QFV_AllocBufferImageCopy (128, alloca); memset (copy->a, 0, 128 * sizeof (copy->a[0])); @@ -257,7 +273,6 @@ QFV_ScrapFlush (scrap_t *scrap, qfv_stagebuf_t *stage, VkCommandBuffer cmd) copy->a[i].imageExtent.depth = 1; } - QFV_FlushStagingBuffer (stage, 0, stage->offset); VkImageMemoryBarrier barrier; qfv_pipelinestagepair_t stages; @@ -265,10 +280,11 @@ QFV_ScrapFlush (scrap_t *scrap, qfv_stagebuf_t *stage, VkCommandBuffer cmd) stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; barrier.image = scrap->image; - dfunc->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, 1, &barrier); - size_t offset = 0, size; + size_t offset = packet->offset, size; vrect_t *batch = scrap->batch; while (scrap->batch_count) { for (i = 0; i < scrap->batch_count && i < 128; i++) { @@ -283,7 +299,7 @@ QFV_ScrapFlush (scrap_t *scrap, qfv_stagebuf_t *stage, VkCommandBuffer cmd) offset += (size + 3) & ~3; batch = batch->next; } - dfunc->vkCmdCopyBufferToImage (cmd, stage->buffer, scrap->image, + dfunc->vkCmdCopyBufferToImage (packet->cmd, stage->buffer, scrap->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, i, copy->a); scrap->batch_count -= i; @@ -292,12 +308,15 @@ QFV_ScrapFlush (scrap_t *scrap, qfv_stagebuf_t *stage, VkCommandBuffer cmd) stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; barrier.image = scrap->image; - dfunc->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, 1, &barrier); *scrap->batch_tail = scrap->batch_free; scrap->batch_free = scrap->batch; scrap->batch = 0; scrap->batch_tail = &scrap->batch; - stage->offset = 0; + + QFV_PacketSubmit (scrap->packet); + scrap->packet = 0; } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 61b85d3e1..24202a8c3 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -158,29 +158,7 @@ destroy_quad_buffers (vulkan_ctx_t *ctx) static void flush_draw_scrap (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkCommandBuffer cmd = ctx->cmdbuffer; - - dfunc->vkWaitForFences (device->dev, 1, &ctx->fence, VK_TRUE, ~0ull); - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - QFV_ScrapFlush (draw_scrap, draw_stage, cmd); - dfunc->vkEndCommandBuffer (cmd); - - VkSubmitInfo submitInfo = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 0, 0, 0, - 1, &cmd, - 0, 0, - }; - dfunc->vkResetFences (device->dev, 1, &ctx->fence); - dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, ctx->fence); - dfunc->vkWaitForFences (device->dev, 1, &ctx->fence, VK_TRUE, ~0ull);//FIXME + QFV_ScrapFlush (draw_scrap); } static void @@ -326,7 +304,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) create_quad_buffers (ctx); draw_scrap = QFV_CreateScrap (device, 2048, QFV_RGBA); - draw_stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024); + draw_stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024, 4, + ctx->cmdpool); conchars_sampler = QFV_GetSampler (ctx, "quakepic"); qpic_t *charspic = Draw_Font8x8Pic (); @@ -604,9 +583,8 @@ Vulkan_DrawReset (vulkan_ctx_t *ctx) void Vulkan_FlushText (vulkan_ctx_t *ctx) { - if (draw_stage->offset) { - flush_draw_scrap (ctx); - } + flush_draw_scrap (ctx); + qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type frame = &ctx->framebuffers.a[ctx->curFrame]; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 16e60e5c1..02b9a0c07 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -203,8 +203,10 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) void Vulkan_CreateStagingBuffers (vulkan_ctx_t *ctx) { - ctx->staging[0] = QFV_CreateStagingBuffer (ctx->device, 1024*1024); - ctx->staging[1] = QFV_CreateStagingBuffer (ctx->device, 1024*1024); + ctx->staging[0] = QFV_CreateStagingBuffer (ctx->device, 1024*1024, 1, + ctx->cmdpool); + ctx->staging[1] = QFV_CreateStagingBuffer (ctx->device, 1024*1024, 1, + ctx->cmdpool); } void From 904a91c0b759757e0d388464afa1d8cfd743e691 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 16 Jan 2021 14:37:16 +0900 Subject: [PATCH 1210/3664] [vulkan] Use only one global staging buffer I think I did two as a bit of a ring buffer, but the new ring buffer system used inside a staging buffer makes it less necessary. Also, the staging buffer is now a fair bit bigger (4M is probably not really enough) --- include/vid_vulkan.h | 2 +- libs/video/renderer/vulkan/vulkan_vid_common.c | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 784c74312..223412999 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -68,7 +68,7 @@ typedef struct vulkan_ctx_s { VkCommandBuffer cmdbuffer; VkFence fence; // for ctx->cmdbuffer only vulkan_renderpass_t renderpass; - struct qfv_stagebuf_s *staging[2]; + struct qfv_stagebuf_s *staging; VkPipeline pipeline; size_t curFrame; vulkan_framebufferset_t framebuffers; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 02b9a0c07..a40e38c52 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -174,8 +174,7 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } - QFV_DestroyStagingBuffer (ctx->staging[0]); - QFV_DestroyStagingBuffer (ctx->staging[1]); + QFV_DestroyStagingBuffer (ctx->staging); Vulkan_DestroyMatrices (ctx); ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, ctx->surface, 0); @@ -203,10 +202,8 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) void Vulkan_CreateStagingBuffers (vulkan_ctx_t *ctx) { - ctx->staging[0] = QFV_CreateStagingBuffer (ctx->device, 1024*1024, 1, - ctx->cmdpool); - ctx->staging[1] = QFV_CreateStagingBuffer (ctx->device, 1024*1024, 1, - ctx->cmdpool); + ctx->staging = QFV_CreateStagingBuffer (ctx->device, 4*1024*1024, 1, + ctx->cmdpool); } void From 5186d3ae49cb60ec8f8268ccc67d80455eeadce2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 16 Jan 2021 14:42:25 +0900 Subject: [PATCH 1211/3664] [vulkan] Rework draw to use a context struct Cleans up global space and makes it usable in multiple contexts. Also, max quads dropped to 32k as each frame now has its own vertex buffer to avoid issues with vertex overwrites (which I have seen). However, all vertex buffers are in the one memory/buffer object (using offsets) and the index buffer has been moved into a device-local memory object. --- include/vid_vulkan.h | 4 +- libs/video/renderer/vulkan/vulkan_draw.c | 282 ++++++++++++++--------- 2 files changed, 178 insertions(+), 108 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 223412999..c8d318a99 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -22,8 +22,6 @@ typedef struct vulkan_framebuffer_s { VkCommandBuffer cmdBuffer; struct qfv_cmdbufferset_s *subCommand; - - VkDescriptorSet twodDescriptors; } vulkan_framebuffer_t; typedef struct vulkan_matrices_s { @@ -64,6 +62,8 @@ typedef struct vulkan_ctx_s { struct hashtab_s *descriptorPools; struct hashtab_s *samplers; + struct drawctx_s *draw_context; + VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; VkFence fence; // for ctx->cmdbuffer only diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 24202a8c3..43068ae52 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -78,57 +78,89 @@ typedef struct cachepic_s { qpic_t *pic; } cachepic_t; -#define MAX_QUADS (65536) +typedef struct drawframe_s { + size_t vert_offset; + drawvert_t *verts; + uint32_t num_quads; + VkCommandBuffer cmd; + VkDescriptorSet descriptors; +} drawframe_t; + +typedef struct drawframeset_s + DARRAY_TYPE (drawframe_t) drawframeset_t; + +typedef struct drawctx_s { + VkSampler sampler; + scrap_t *scrap; + qfv_stagebuf_t *stage; + qpic_t *conchars; + qpic_t *conback; + qpic_t *white_pic; + hashtab_t *pic_cache; + VkBuffer vert_buffer; + VkDeviceMemory vert_memory; + VkBuffer ind_buffer; + VkDeviceMemory ind_memory; + VkPipeline pipeline; + VkPipelineLayout layout; + drawframeset_t frames; +} drawctx_t; + +// enough for a full screen of 8x8 chars at 1920x1080 plus some extras (368) +#define MAX_QUADS (32768) #define VERTS_PER_QUAD (4) #define INDS_PER_QUAD (5) // one per vert plus primitive reset -//FIXME move into a context struct -VkSampler conchars_sampler; -scrap_t *draw_scrap; -qfv_stagebuf_t *draw_stage; -qpic_t *conchars; -qpic_t *white_pic; -static hashtab_t *pic_cache; - -VkBuffer quad_vert_buffer; -VkBuffer quad_ind_buffer; -VkDeviceMemory quad_memory; -drawvert_t *quad_verts; -uint32_t *quad_inds; -uint32_t num_quads; - -VkPipeline twod_pipeline; -VkPipelineLayout twod_layout; -size_t draw_cmdBuffer; - static void create_quad_buffers (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - //FIXME quad_inds can be a completely separate buffer that is - //pre-initialized to draw 2-tri triangle strips as the actual indices will - //never change - size_t vert_size = MAX_QUADS * VERTS_PER_QUAD * sizeof (drawvert_t); - size_t ind_size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t); + drawctx_t *dctx = ctx->draw_context; + + size_t vert_size; + size_t ind_size; + size_t frames = ctx->framebuffers.size; + VkBuffer vbuf, ibuf; + VkDeviceMemory vmem, imem; + + vert_size = frames * MAX_QUADS * VERTS_PER_QUAD * sizeof (drawvert_t); + ind_size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t); + + vbuf = QFV_CreateBuffer (device, vert_size, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + ibuf = QFV_CreateBuffer (device, ind_size, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + vmem = QFV_AllocBufferMemory (device, vbuf, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + vert_size, 0); + imem = QFV_AllocBufferMemory (device, ibuf, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + ind_size, 0); + QFV_BindBufferMemory (device, vbuf, vmem, 0); + QFV_BindBufferMemory (device, ibuf, imem, 0); + + dctx->vert_buffer = vbuf; + dctx->vert_memory = vmem; + dctx->ind_buffer = ibuf; + dctx->ind_memory = imem; - quad_vert_buffer = QFV_CreateBuffer (device, vert_size, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - quad_ind_buffer = QFV_CreateBuffer (device, ind_size, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT); - quad_memory = QFV_AllocBufferMemory (device, quad_vert_buffer, - VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - vert_size + ind_size, 0); - QFV_BindBufferMemory (device, quad_vert_buffer, quad_memory, 0); - QFV_BindBufferMemory (device, quad_ind_buffer, quad_memory, vert_size); void *data; - dfunc->vkMapMemory (device->dev, quad_memory, 0, vert_size + ind_size, - 0, &data); - quad_verts = data; - quad_inds = (uint32_t *) (quad_verts + MAX_QUADS * VERTS_PER_QUAD); - // pre-initialize quad_inds as the indices will never change - uint32_t *ind = quad_inds; + dfunc->vkMapMemory (device->dev, vmem, 0, vert_size, 0, &data); + drawvert_t *vert_data = data; + + for (size_t f = 0; f < frames; f++) { + drawframe_t *frame = &dctx->frames.a[f]; + size_t ind = f * MAX_QUADS * VERTS_PER_QUAD; + frame->vert_offset = ind * sizeof (drawvert_t); + frame->verts = vert_data + ind; + frame->num_quads = 0; + } + + // The indices will never change so pre-generate and stash them + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + uint32_t *ind = QFV_PacketExtend (packet, ind_size); for (int i = 0; i < MAX_QUADS; i++) { for (int j = 0; j < VERTS_PER_QUAD; j++) { *ind++ = i * VERTS_PER_QUAD + j; @@ -136,11 +168,10 @@ create_quad_buffers (vulkan_ctx_t *ctx) // mark end of primitive *ind++ = -1; } - VkMappedMemoryRange range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - quad_memory, vert_size, ind_size, - }; - dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); + VkBufferCopy copy_region = { packet->offset, 0, ind_size }; + dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, ibuf, + 1, ©_region); + QFV_PacketSubmit (packet); } static void @@ -148,17 +179,19 @@ destroy_quad_buffers (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + drawctx_t *dctx = ctx->draw_context; - dfunc->vkUnmapMemory (device->dev, quad_memory); - dfunc->vkFreeMemory (device->dev, quad_memory, 0); - dfunc->vkDestroyBuffer (device->dev, quad_vert_buffer, 0); - dfunc->vkDestroyBuffer (device->dev, quad_ind_buffer, 0); + dfunc->vkUnmapMemory (device->dev, dctx->vert_memory); + dfunc->vkFreeMemory (device->dev, dctx->vert_memory, 0); + dfunc->vkFreeMemory (device->dev, dctx->ind_memory, 0); + dfunc->vkDestroyBuffer (device->dev, dctx->vert_buffer, 0); + dfunc->vkDestroyBuffer (device->dev, dctx->ind_buffer, 0); } static void flush_draw_scrap (vulkan_ctx_t *ctx) { - QFV_ScrapFlush (draw_scrap); + QFV_ScrapFlush (ctx->draw_context->scrap); } static void @@ -197,7 +230,7 @@ cachepic_getkey (const void *_cp, void *unused) } static qpic_t * -pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) +pic_data (const char *name, int w, int h, const byte *data, drawctx_t *dctx) { qpic_t *pic; subpic_t *subpic; @@ -207,10 +240,10 @@ pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) pic->width = w; pic->height = h; - subpic = QFV_ScrapSubpic (draw_scrap, w, h); + subpic = QFV_ScrapSubpic (dctx->scrap, w, h); *(subpic_t **) pic->data = subpic; - picdata = QFV_SubpicBatch (subpic, draw_stage); + picdata = QFV_SubpicBatch (subpic, dctx->stage); size_t size = w * h; for (size_t i = 0; i < size; i++) { byte pix = *data++; @@ -227,7 +260,7 @@ qpic_t * Vulkan_Draw_MakePic (int width, int height, const byte *data, vulkan_ctx_t *ctx) { - return pic_data (0, width, height, data, ctx); + return pic_data (0, width, height, data, ctx->draw_context); } void @@ -243,7 +276,7 @@ Vulkan_Draw_PicFromWad (const char *name, vulkan_ctx_t *ctx) if (!wadpic) { return 0; } - return pic_data (name, wadpic->width, wadpic->height, wadpic->data, ctx); + return pic_data (name, wadpic->width, wadpic->height, wadpic->data, ctx->draw_context); } qpic_t * @@ -252,8 +285,9 @@ Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) qpic_t *p; qpic_t *pic; cachepic_t *cpic; + drawctx_t *dctx = ctx->draw_context; - if ((cpic = Hash_Find (pic_cache, path))) { + if ((cpic = Hash_Find (dctx->pic_cache, path))) { return cpic->pic; } if (strlen (path) < 4 || strcmp (path + strlen (path) - 4, ".lmp") @@ -261,17 +295,18 @@ Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) return 0; } - pic = pic_data (path, p->width, p->height, p->data, ctx); + pic = pic_data (path, p->width, p->height, p->data, dctx); free (p); cpic = new_cachepic (path, pic); - Hash_Add (pic_cache, cpic); + Hash_Add (dctx->pic_cache, cpic); return pic; } void Vulkan_Draw_UncachePic (const char *path, vulkan_ctx_t *ctx) { - Hash_Free (pic_cache, Hash_Del (pic_cache, path)); + drawctx_t *dctx = ctx->draw_context; + Hash_Free (dctx->pic_cache, Hash_Del (dctx->pic_cache, path)); } void @@ -285,12 +320,13 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + drawctx_t *dctx = ctx->draw_context; destroy_quad_buffers (ctx); - dfunc->vkDestroyPipeline (device->dev, twod_pipeline, 0); - QFV_DestroyScrap (draw_scrap); - QFV_DestroyStagingBuffer (draw_stage); + dfunc->vkDestroyPipeline (device->dev, dctx->pipeline, 0); + QFV_DestroyScrap (dctx->scrap); + QFV_DestroyStagingBuffer (dctx->stage); } void @@ -299,26 +335,35 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - //FIXME move into struct - pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, 0, 0); + drawctx_t *dctx = calloc (1, sizeof (drawctx_t)); + ctx->draw_context = dctx; + + size_t frames = ctx->framebuffers.size; + DARRAY_INIT (&dctx->frames, frames); + DARRAY_RESIZE (&dctx->frames, frames); + dctx->frames.grow = 0; + + dctx->pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, + 0, 0); create_quad_buffers (ctx); - draw_scrap = QFV_CreateScrap (device, 2048, QFV_RGBA); - draw_stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024, 4, - ctx->cmdpool); - conchars_sampler = QFV_GetSampler (ctx, "quakepic"); + dctx->scrap = QFV_CreateScrap (device, 2048, QFV_RGBA); + dctx->stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024, 4, + ctx->cmdpool); + dctx->sampler = QFV_GetSampler (ctx, "quakepic"); qpic_t *charspic = Draw_Font8x8Pic (); - conchars = pic_data (0, charspic->width, charspic->height, charspic->data, ctx); + dctx->conchars = pic_data ("conchars", charspic->width, charspic->height, + charspic->data, dctx); byte white_block = 0xfe; - white_pic = pic_data (0, 1, 1, &white_block, ctx); + dctx->white_pic = pic_data ("white", 1, 1, &white_block, dctx); flush_draw_scrap (ctx); - twod_pipeline = Vulkan_CreatePipeline (ctx, "twod"); + dctx->pipeline = Vulkan_CreatePipeline (ctx, "twod"); - twod_layout = QFV_GetPipelineLayout (ctx, "twod"); + dctx->layout = QFV_GetPipelineLayout (ctx, "twod"); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (ctx->framebuffers.size, alloca); for (size_t i = 0; i < layouts->size; i++) { @@ -330,32 +375,32 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) ctx->matrices.buffer_2d, 0, VK_WHOLE_SIZE }; VkDescriptorImageInfo imageInfo = { - conchars_sampler, - QFV_ScrapImageView (draw_scrap), + dctx->sampler, + QFV_ScrapImageView (dctx->scrap), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; - size_t frames = ctx->framebuffers.size; __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < frames; i++) { - __auto_type frame = &ctx->framebuffers.a[i]; - frame->twodDescriptors = sets->a[i]; + __auto_type cframe = &ctx->framebuffers.a[i]; + __auto_type dframe = &dctx->frames.a[i]; + dframe->descriptors = sets->a[i]; VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - frame->twodDescriptors, 0, 0, 1, + dframe->descriptors, 0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &bufferInfo, 0 }, { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - frame->twodDescriptors, 1, 0, 1, + dframe->descriptors, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo, 0, 0 }, }; dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); - draw_cmdBuffer = frame->subCommand->size; - DARRAY_APPEND (frame->subCommand, cmdBuffers->a[i]); + dframe->cmd = cmdBuffers->a[i]; + DARRAY_APPEND (cframe->subCommand, cmdBuffers->a[i]); } free (sets); } @@ -363,14 +408,14 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) static inline void draw_pic (float x, float y, int w, int h, qpic_t *pic, int srcx, int srcy, int srcw, int srch, - float *color) + float *color, drawframe_t *frame) { - if (num_quads + VERTS_PER_QUAD > MAX_QUADS) { + if (frame->num_quads + VERTS_PER_QUAD > MAX_QUADS) { return; } - drawvert_t *verts = quad_verts + num_quads * VERTS_PER_QUAD; - num_quads += VERTS_PER_QUAD; + drawvert_t *verts = frame->verts + frame->num_quads * VERTS_PER_QUAD; + frame->num_quads += VERTS_PER_QUAD; subpic_t *subpic = *(subpic_t **) pic->data; srcx += subpic->rect->x; @@ -410,12 +455,15 @@ draw_pic (float x, float y, int w, int h, qpic_t *pic, static inline void queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + quat_t color = {1, 1, 1, 1}; int cx, cy; cx = chr % 16; cy = chr / 16; - draw_pic (x, y, 8, 8, conchars, cx * 8, cy * 8, 8, 8, color); + draw_pic (x, y, 8, 8, dctx->conchars, cx * 8, cy * 8, 8, 8, color, frame); } void @@ -505,17 +553,23 @@ Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx) void Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + static quat_t color = { 1, 1, 1, 1}; draw_pic (x, y, pic->width, pic->height, pic, - 0, 0, pic->width, pic->height, color); + 0, 0, pic->width, pic->height, color, frame); } void Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + static quat_t color = { 1, 1, 1, 1}; draw_pic (x, y, pic->width, pic->height, pic, - 0, 0, pic->width, pic->height, color); + 0, 0, pic->width, pic->height, color, frame); } void @@ -523,8 +577,12 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + static quat_t color = { 1, 1, 1, 1}; - draw_pic (x, y, width, height, pic, srcx, srcy, width, height, color); + draw_pic (x, y, width, height, pic, srcx, srcy, width, height, + color, frame); } void @@ -540,24 +598,31 @@ Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) void Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + quat_t color; VectorScale (vid.palette + c * 3, 1.0f/255.0f, color); color[3] = 1; - draw_pic (x, y, w, h, white_pic, 0, 0, 1, 1, color); + draw_pic (x, y, w, h, dctx->white_pic, 0, 0, 1, 1, color, frame); } static inline void -draw_blendscreen (quat_t color) +draw_blendscreen (quat_t color, vulkan_ctx_t *ctx) { - draw_pic (0, 0, vid.conwidth, vid.conheight, white_pic, 0, 0, 1, 1, color); + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + + draw_pic (0, 0, vid.conwidth, vid.conheight, dctx->white_pic, 0, 0, 1, 1, + color, frame); } void Vulkan_Draw_FadeScreen (vulkan_ctx_t *ctx) { static quat_t color = { 0, 0, 0, 0.7 }; - draw_blendscreen (color); + draw_blendscreen (color, ctx); } void @@ -587,12 +652,16 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - __auto_type frame = &ctx->framebuffers.a[ctx->curFrame]; - VkCommandBuffer cmd = frame->subCommand->a[draw_cmdBuffer]; + __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; + drawctx_t *dctx = ctx->draw_context; + drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + + VkCommandBuffer cmd = dframe->cmd; VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - quad_memory, 0, num_quads * VERTS_PER_QUAD * sizeof (drawvert_t), + dctx->vert_memory, dframe->vert_offset, + dframe->num_quads * VERTS_PER_QUAD * sizeof (drawvert_t), }; dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); @@ -600,7 +669,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, ctx->renderpass.renderpass, 0, - frame->framebuffer, + cframe->framebuffer, 0, 0, 0 }; VkCommandBufferBeginInfo beginInfo = { @@ -611,30 +680,31 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) dfunc->vkBeginCommandBuffer (cmd, &beginInfo); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - twod_pipeline); + dctx->pipeline); VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); - VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &quad_vert_buffer, offsets); - dfunc->vkCmdBindIndexBuffer (cmd, quad_ind_buffer, 0, + VkDeviceSize offsets[] = {dframe->vert_offset}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, VK_INDEX_TYPE_UINT32); - VkDescriptorSet set = frame->twodDescriptors; - VkPipelineLayout layout = twod_layout; + VkDescriptorSet set = dframe->descriptors; + VkPipelineLayout layout = dctx->layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 1, &set, 0, 0); - dfunc->vkCmdDrawIndexed (cmd, num_quads * INDS_PER_QUAD, 1, 0, 0, 0); + dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD, + 1, 0, 0, 0); dfunc->vkEndCommandBuffer (cmd); - num_quads = 0; + dframe->num_quads = 0; } void Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) { if (color[3]) { - draw_blendscreen (color); + draw_blendscreen (color, ctx); } } From 0150fc0487c93a26a901d2cce6cdfac36ba09002 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 16 Jan 2021 15:09:39 +0900 Subject: [PATCH 1212/3664] [vulkan] Use pipeline barriers for index buffer And set the usage correctly. --- libs/video/renderer/vulkan/vulkan_draw.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 43068ae52..2b9642554 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -131,7 +131,8 @@ create_quad_buffers (vulkan_ctx_t *ctx) vbuf = QFV_CreateBuffer (device, vert_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); ibuf = QFV_CreateBuffer (device, ind_size, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + VK_BUFFER_USAGE_INDEX_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT); vmem = QFV_AllocBufferMemory (device, vbuf, VK_MEMORY_PROPERTY_HOST_CACHED_BIT, vert_size, 0); @@ -168,9 +169,28 @@ create_quad_buffers (vulkan_ctx_t *ctx) // mark end of primitive *ind++ = -1; } + + VkBufferMemoryBarrier wr_barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, ibuf, 0, ind_size + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, 0, 1, &wr_barrier, 0, 0); VkBufferCopy copy_region = { packet->offset, 0, ind_size }; dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, ibuf, 1, ©_region); + VkBufferMemoryBarrier rd_barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, ibuf, 0, ind_size + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + 0, 0, 0, 1, &rd_barrier, 0, 0); QFV_PacketSubmit (packet); } From fa6ff04c5ae5cc7b611abd69ffae15a62ecdd2ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 16 Jan 2021 15:39:16 +0900 Subject: [PATCH 1213/3664] [image] Use an enum for tex_t formats --- include/QF/image.h | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/include/QF/image.h b/include/QF/image.h index 106379bb7..396547f42 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -29,23 +29,26 @@ #ifndef __QF_image_h #define __QF_image_h -#include "QF/quakeio.h" +#include "QF/qtypes.h" + +typedef enum QFFormat { + tex_palette = 0, + tex_l = 0x1909, //GL_LUMINANCE + tex_a = 0x1906, //GL_ALPHA + tex_la = 2, + tex_rgb = 3, + tex_rgba = 4, +} QFFormat; // could not use texture_t as that is used for models. typedef struct tex_s { - int width; - int height; - int format; - unsigned char *palette; // 0 = 32 bit, otherwise 8 - unsigned char data[4]; // variable length + int width; + int height; + QFFormat format; + byte *palette; // 0 = 32 bit, otherwise 8 + byte data[4]; // variable length } tex_t; -#define tex_palette 0 -#define tex_l 0x1909 //GL_LUMINANCE -#define tex_a 0x1906 //GL_ALPHA -#define tex_la 2 -#define tex_rgb 3 -#define tex_rgba 4 tex_t *LoadImage (const char *imageFile); From f3695ec3dd93e446b70040a9fa44b4d03c28ca67 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 16 Jan 2021 15:39:36 +0900 Subject: [PATCH 1214/3664] [vulkan] Use the previously existing tex_t formats I'd forgotten we had these (though direct GL_* was used). --- include/QF/Vulkan/texture.h | 9 ++------- libs/video/renderer/vulkan/texture.c | 13 ++++++++----- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/QF/Vulkan/texture.h b/include/QF/Vulkan/texture.h index e24fa0eb1..39f5b07f2 100644 --- a/include/QF/Vulkan/texture.h +++ b/include/QF/Vulkan/texture.h @@ -1,17 +1,12 @@ #ifndef __QF_Vulkan_texture_h #define __QF_Vulkan_texture_h -typedef enum { - QFV_LUMINANCE, - QFV_LUMINANCE_ALPHA, - QFV_RGB, - QFV_RGBA, -} QFVFormat; +#include "QF/image.h" typedef struct scrap_s scrap_t; scrap_t *QFV_CreateScrap (struct qfv_device_s *device, int size, - QFVFormat format); + QFFormat format); void QFV_ScrapClear (scrap_t *scrap); void QFV_DestroyScrap (scrap_t *scrap); VkImageView QFV_ScrapImageView (scrap_t *scrap) __attribute__((pure)); diff --git a/libs/video/renderer/vulkan/texture.c b/libs/video/renderer/vulkan/texture.c index f23e1297a..b4eacf0e6 100644 --- a/libs/video/renderer/vulkan/texture.c +++ b/libs/video/renderer/vulkan/texture.c @@ -42,6 +42,7 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/image.h" #include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/render.h" @@ -75,25 +76,27 @@ struct scrap_s { }; scrap_t * -QFV_CreateScrap (qfv_device_t *device, int size, QFVFormat format) +QFV_CreateScrap (qfv_device_t *device, int size, QFFormat format) { int bpp = 0; VkFormat fmt = VK_FORMAT_UNDEFINED; switch (format) { - case QFV_LUMINANCE: + case tex_l: + case tex_a: + case tex_palette: bpp = 1; fmt = VK_FORMAT_R8_UNORM; break; - case QFV_LUMINANCE_ALPHA: + case tex_la: bpp = 2; fmt = VK_FORMAT_R8G8_UNORM; break; - case QFV_RGB: + case tex_rgb: bpp = 3; fmt = VK_FORMAT_R8G8B8_UNORM; break; - case QFV_RGBA: + case tex_rgba: bpp = 4; fmt = VK_FORMAT_R8G8B8A8_UNORM; break; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 2b9642554..e94f971f0 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -367,7 +367,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) 0, 0); create_quad_buffers (ctx); - dctx->scrap = QFV_CreateScrap (device, 2048, QFV_RGBA); + dctx->scrap = QFV_CreateScrap (device, 2048, tex_rgba); dctx->stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024, 4, ctx->cmdpool); dctx->sampler = QFV_GetSampler (ctx, "quakepic"); From 7282d2addea795de15a81b5d762e39735cd4a219 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 16 Jan 2021 20:27:48 +0900 Subject: [PATCH 1215/3664] [vulkan] Make renderpass dependencies more explicit Doesn't seem to adversely affect anything and is more correct from what I can tell reading some other documentation. --- libs/video/renderer/vulkan/qfpipeline.plist | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 385713c80..2f3ef7445 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -254,12 +254,21 @@ { srcSubpass = VK_SUBPASS_EXTERNAL; dstSubpass = 0; - srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - srcAccessMask = 0; - dstAccessMask = "VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT"; - dependencyFlags = 0; - } + srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + }, + { + srcSubpass = 0; + dstSubpass = VK_SUBPASS_EXTERNAL; + srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + }, ); }; } From fd8521da76d2d32dcef064297747c3da8b9f78c8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 16 Jan 2021 21:03:36 +0900 Subject: [PATCH 1216/3664] [vulkan] Make frame-buffer count available to It turns out I made a bit of a mistake in tying the frame-buffer count to the number of swapchain images. This is the first step in sorting that out. --- libs/video/renderer/vulkan/vkparse.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index cd5e98502..0fc00b835 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -535,6 +535,21 @@ exprtype_t qfv_swapchain_t_type = { &qfv_swapchain_t_symtab, }; +static exprsym_t vulkan_framebufferset_t_symbols[] = { + {"size", &cexpr_size_t, (void *)field_offset (vulkan_framebufferset_t, size)}, + { } +}; +static exprtab_t vulkan_framebufferset_t_symtab = { + vulkan_framebufferset_t_symbols, +}; +exprtype_t vulkan_framebufferset_t_type = { + "framebufferset", + sizeof (vulkan_framebufferset_t *), + cexpr_struct_binops, + 0, + &vulkan_framebufferset_t_symtab, +}; + typedef struct qfv_renderpass_s { qfv_attachmentdescription_t *attachments; qfv_subpassparametersset_t *subpasses; @@ -588,6 +603,7 @@ QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) plitem_t *messages = PL_NewArray (); exprsym_t var_syms[] = { {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {} }; @@ -645,6 +661,7 @@ QFV_InitParse (vulkan_ctx_t *ctx) context.hashlinks = &ctx->hashlinks; vkgen_init_symtabs (&context); cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); + cexpr_init_symtab (&vulkan_framebufferset_t_symtab, &context); cexpr_init_symtab (&imageset_symtab, &context); } @@ -663,6 +680,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) VkRenderPass renderpass; exprsym_t var_syms[] = { {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {} }; From 8078e10ea18e3326a5fb79f5f79086cd794d9fcd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 16 Jan 2021 21:24:42 +0900 Subject: [PATCH 1217/3664] [vulkan] Make frame-buffers independent of swapchain This is more correct as the environment (X11 etc) might provide more swapchain images than we want: 3 frames in flight is generally considered a good balance between saturating the hardware and latency. --- libs/video/renderer/vid_render_vulkan.c | 19 +++++++++++++++++-- libs/video/renderer/vulkan/qfpipeline.plist | 6 +++--- .../video/renderer/vulkan/vulkan_vid_common.c | 14 ++------------ 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index f68e8c182..646a3b740 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -45,6 +45,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/swapchain.h" #include "mod_internal.h" @@ -62,8 +63,8 @@ vulkan_R_Init (void) Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateMatrices (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); - Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_CreateFramebuffers (vulkan_ctx); + Vulkan_CreateRenderPass (vulkan_ctx); // FIXME this should be staged so screen updates can begin while pipelines // are being built vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); @@ -100,13 +101,27 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) = &vulkan_ctx->framebuffers.a[vulkan_ctx->curFrame]; dfunc->vkWaitForFences (dev, 1, &framebuffer->fence, VK_TRUE, 2000000000); + if (framebuffer->framebuffer) { + dfunc->vkDestroyFramebuffer (dev, framebuffer->framebuffer, 0); + } QFV_AcquireNextImage (vulkan_ctx->swapchain, framebuffer->imageAvailableSemaphore, 0, &imageIndex); + __auto_type attachments = DARRAY_ALLOCFIXED (qfv_imageviewset_t, 3, + alloca); + qfv_swapchain_t *sc = vulkan_ctx->swapchain; + attachments->a[0] = vulkan_ctx->renderpass.colorImage->view; + attachments->a[1] = vulkan_ctx->renderpass.depthImage->view; + attachments->a[2] = sc->imageViews->a[imageIndex]; + + VkRenderPass renderpass = vulkan_ctx->renderpass.renderpass; + framebuffer->framebuffer = QFV_CreateFramebuffer (device, renderpass, + attachments, + sc->extent, 1); + Vulkan_FlushText (vulkan_ctx); - qfv_swapchain_t *sc = vulkan_ctx->swapchain; VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; VkClearValue clearValues[2] = { diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 2f3ef7445..4bc6017e9 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -32,15 +32,15 @@ descriptorPools = { twod = { flags = 0; - maxSets = $swapchain.images.size; + maxSets = $framebuffers.size; bindings = ( { type = uniform_buffer; - descriptorCount = $swapchain.images.size; + descriptorCount = $framebuffers.size; }, { type = combined_image_sampler; - descriptorCount = $swapchain.images.size; + descriptorCount = $framebuffers.size; }, ); }; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a40e38c52..3d317f52c 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -387,30 +387,20 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; VkCommandPool cmdpool = ctx->cmdpool; - qfv_swapchain_t *sc = ctx->swapchain; - VkRenderPass renderpass = ctx->renderpass.renderpass; if (!ctx->framebuffers.grow) { DARRAY_INIT (&ctx->framebuffers, 4); } - DARRAY_RESIZE (&ctx->framebuffers, sc->numImages); - - __auto_type attachments = DARRAY_ALLOCFIXED (qfv_imageviewset_t, 3, - alloca); - attachments->a[0] = ctx->renderpass.colorImage->view; - attachments->a[1] = ctx->renderpass.depthImage->view; + DARRAY_RESIZE (&ctx->framebuffers, 3);//FIXME cvar __auto_type cmdBuffers = QFV_AllocCommandBufferSet (ctx->framebuffers.size, alloca); QFV_AllocateCommandBuffers (device, cmdpool, 0, cmdBuffers); for (size_t i = 0; i < ctx->framebuffers.size; i++) { - attachments->a[2] = sc->imageViews->a[i]; __auto_type frame = &ctx->framebuffers.a[i]; - frame->framebuffer = QFV_CreateFramebuffer (device, renderpass, - attachments, - sc->extent, 1); + frame->framebuffer = 0; frame->fence = QFV_CreateFence (device, 1); frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); frame->renderDoneSemaphore = QFV_CreateSemaphore (device); From debaffcb97f8bd968bb716b531d791faf87517e4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 17 Jan 2021 22:26:48 +0900 Subject: [PATCH 1218/3664] [vulkan] Retain handle_keys item Ugh, need to come up with valgrind for ruamoko :P --- libs/video/renderer/vulkan/vkgen/vkgen.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 01637c54a..a336a861c 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -204,7 +204,7 @@ main(int argc, string *argv) } } - PLItem *handle_keys = [handles allKeys]; + PLItem *handle_keys = [[handles allKeys] retain]; for (int i = [handle_keys count]; i-- > 0; ) { string search_name = [[handle_keys getObjectAtIndex:i] string]; id obj = (id) Hash_Find (available_types, search_name); From 1e163fd2d73beca39f3729a95dcef51c3dab13e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 18 Jan 2021 02:08:55 +0900 Subject: [PATCH 1219/3664] [vulkan] Correct QFV_CreateImage samples type Not sure why I though FlagBits was correct instead of Flags. --- include/QF/Vulkan/image.h | 2 +- libs/video/renderer/vulkan/image.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index edb5e025e..501a5025e 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -36,7 +36,7 @@ VkImage QFV_CreateImage (struct qfv_device_s *device, int cubemap, VkExtent3D size, uint32_t num_mipmaps, uint32_t num_layers, - VkSampleCountFlagBits samples, + VkSampleCountFlags samples, VkImageUsageFlags usage_scenarios); VkDeviceMemory QFV_AllocImageMemory (struct qfv_device_s *device, diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 68decb94a..bd71cc162 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -68,7 +68,7 @@ QFV_CreateImage (qfv_device_t *device, int cubemap, VkExtent3D size, uint32_t num_mipmaps, uint32_t num_layers, - VkSampleCountFlagBits samples, + VkSampleCountFlags samples, VkImageUsageFlags usage_scenarios) { VkDevice dev = device->dev; From aa7ff9d6188b579c5169380c6b9afcf1d686eb25 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 18 Jan 2021 02:10:10 +0900 Subject: [PATCH 1220/3664] [vulkan] Implement console background drawing That went better than expected after deciding to put the conback in the scrap. --- libs/video/renderer/vulkan/vulkan_draw.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index e94f971f0..7aadd6692 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -608,6 +608,15 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, void Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + + quat_t color = { 1, 1, 1, bound (0, alpha, 255) / 255.0}; + qpic_t *cpic; + cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx); + int ofs = max (0, cpic->height - lines); + draw_pic (0, 0, vid.conwidth, lines, cpic, + 0, ofs, cpic->width, lines, color, frame); } void From abd3b900044ba9863978a524a355e8223908fa35 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 18 Jan 2021 02:10:56 +0900 Subject: [PATCH 1221/3664] [vulkan] Implement basic quake texture loading It optionally generates mipmaps, and supports the main texture types (especially for texture packs), including palettes, but is otherwise rather unsophisticated code. Needs a lot of work, but testing first. --- include/QF/Vulkan/funclist.h | 1 + include/QF/Vulkan/qf_texture.h | 13 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vulkan/vulkan_texture.c | 249 ++++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 include/QF/Vulkan/qf_texture.h create mode 100644 libs/video/renderer/vulkan/vulkan_texture.c diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 63c5bde29..209ee0561 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -162,6 +162,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBufferToImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyImageToBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBlitImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBeginRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass) diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h new file mode 100644 index 000000000..a1750682d --- /dev/null +++ b/include/QF/Vulkan/qf_texture.h @@ -0,0 +1,13 @@ +#ifndef __QF_Vulkan_qf_texture_h +#define __QF_Vulkan_qf_texture_h + +#include "QF/image.h" + +typedef struct qfv_tex_s qfv_tex_t; +struct vulkan_ctx_s; + +qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip); +VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure)); +void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex); + +#endif//__QF_Vulkan_qf_texture_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 7a323f118..d44139a22 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -237,6 +237,7 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vkparse.c \ libs/video/renderer/vulkan/vulkan_draw.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ + libs/video/renderer/vulkan/vulkan_texture.c \ libs/video/renderer/vulkan/vulkan_vid_common.c libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vkparse_src) diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c new file mode 100644 index 000000000..0b2c2e102 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -0,0 +1,249 @@ +/* + vulkan_texuture.c + + Quake specific Vulkan texuture manager + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/alloc.h" +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/hash.h" +#include "QF/image.h" +#include "QF/mathlib.h" +#include "QF/qfplist.h" +#include "QF/quakefs.h" +#include "QF/render.h" +#include "QF/sys.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/barrier.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/staging.h" +#include "QF/Vulkan/texture.h" + +#include "r_scrap.h" +#include "vid_vulkan.h" + +struct qfv_tex_s { // qfv_tex_t + VkDeviceMemory memory; + size_t offset; + VkImage image; + VkImageView view; +}; + +static int +ilog2 (unsigned x) +{ + if (x > 0x7fffffff) { + // avoid overflow + return 31; + } + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + int y = 0; + y |= ((x & 0xffff0000) != 0) << 4; + y |= ((x & 0xff00ff00) != 0) << 3; + y |= ((x & 0xf0f0f0f0) != 0) << 2; + y |= ((x & 0xcccccccc) != 0) << 1; + y |= ((x & 0xaaaaaaaa) != 0) << 0; + return y; +} + +qfv_tex_t * +Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + int bpp = 0; + VkFormat format = VK_FORMAT_UNDEFINED; + + switch (tex->format) { + case tex_l: + case tex_a: + format = VK_FORMAT_R8_UNORM; + bpp = 1; + break; + case tex_la: + format = VK_FORMAT_R8G8_UNORM; + bpp = 2; + break; + case tex_palette: + if (!tex->palette) { + return 0; + } + format = VK_FORMAT_R8G8B8_UNORM; + bpp = 3; + break; + case tex_rgb: + format = VK_FORMAT_R8G8B8_UNORM; + bpp = 3; + break; + case tex_rgba: + format = VK_FORMAT_R8G8B8A8_UNORM; + bpp = 4; + break; + } + if (format == VK_FORMAT_UNDEFINED) { + return 0; + } + + if (mip) { + mip = ilog2 (max (tex->width, tex->height)) + 1; + } else { + mip = 1; + } + + //qfv_devfuncs_t *dfunc = device->funcs; + //FIXME this whole thing is ineffiecient, especially for small textures + qfv_tex_t *qtex = malloc (sizeof (qfv_tex_t)); + + VkExtent3D extent = { tex->width, tex->height, 1 }; + qtex->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, format, extent, + mip, 1, VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT); + qtex->memory = QFV_AllocImageMemory (device, qtex->image, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + 0, 0); + QFV_BindImageMemory (device, qtex->image, qtex->memory, 0); + + size_t bytes = bpp * tex->width * tex->height; + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + byte *tex_data = QFV_PacketExtend (packet, bytes); + + if (tex->format == tex_palette) { + byte *data = tex->data; + for (size_t count = tex->width * tex->height; count-- > 0; ) { + byte pix = *data++; + byte *col = tex->palette + pix; + *tex_data++ = *col++; + *tex_data++ = *col++; + *tex_data++ = *col++; + } + } else { + memcpy (tex_data, tex->data, bytes); + } + + VkImageMemoryBarrier barrier; + qfv_pipelinestagepair_t stages; + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + barrier.image = qtex->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + VkBufferImageCopy copy = { + packet->offset, 0, 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, {tex->width, tex->height, 1}, + }; + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + qtex->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©); + barrier.subresourceRange.baseMipLevel = 0; + stages.src = VK_PIPELINE_STAGE_TRANSFER_BIT; + stages.dst = VK_PIPELINE_STAGE_TRANSFER_BIT; + VkImageBlit blit = { + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {{0, 0, 0}, {tex->width, tex->height, 1}}, + {VK_IMAGE_ASPECT_COLOR_BIT, 1, 0, 1}, + {{0, 0, 0}, {(tex->width + 1) >> 1, (tex->height + 1) >> 1, 1}}, + }; + while (--mip > 0) { + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, + 0, 0, 0, 0, + 1, &barrier); + + dfunc->vkCmdBlitImage (packet->cmd, + qtex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + qtex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &blit, VK_FILTER_LINEAR); + + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, + 0, 0, 0, 0, + 1, &barrier); + + blit.srcSubresource.mipLevel++; + blit.srcOffsets[1].x = blit.dstOffsets[1].x; + blit.srcOffsets[1].y = blit.dstOffsets[1].y; + blit.dstSubresource.mipLevel++; + blit.dstOffsets[1].x = (blit.dstOffsets[1].x + 1) >> 1; + blit.dstOffsets[1].y = (blit.dstOffsets[1].y + 1) >> 1; + barrier.subresourceRange.baseMipLevel++; + } + QFV_PacketSubmit (packet); + return 0; +} + +VkImageView +Vulkan_TexImageView (qfv_tex_t *tex) +{ + return tex->view; +} + +void +Vulkan_UnloadTex (vulkan_ctx_t *ctx, qfv_tex_t *tex) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyImageView (device->dev, tex->view, 0); + dfunc->vkDestroyImage (device->dev, tex->image, 0); + dfunc->vkFreeMemory (device->dev, tex->memory, 0); + free (tex); +} From dacda501300b0b72a1b3a2a3d719916ba9b88384 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 18 Jan 2021 12:46:06 +0900 Subject: [PATCH 1222/3664] [renderer] Stub out all the vulkan functions nq-x11 now gets through all three demos without crashing (but without rendering anything useful, though). --- include/QF/Vulkan/qf_particles.h | 15 + include/r_dynamic.h | 6 - include/r_internal.h | 1 + libs/models/alias/gl_model_alias.c | 2 +- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/gl/gl_dyn_part.c | 42 +-- libs/video/renderer/glsl/glsl_particles.c | 42 +-- libs/video/renderer/r_efrag.c | 2 +- libs/video/renderer/sw/sw_rpart.c | 92 +++--- libs/video/renderer/sw32/sw32_rpart.c | 94 +++--- libs/video/renderer/vid_render_vulkan.c | 201 +++++++++++-- libs/video/renderer/vulkan/vulkan_particles.c | 268 ++++++++++++++++++ 12 files changed, 596 insertions(+), 170 deletions(-) create mode 100644 include/QF/Vulkan/qf_particles.h create mode 100644 libs/video/renderer/vulkan/vulkan_particles.c diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h new file mode 100644 index 000000000..3ac71ac71 --- /dev/null +++ b/include/QF/Vulkan/qf_particles.h @@ -0,0 +1,15 @@ +#ifndef __QF_Vulkan_qf_particles_h +#define __QF_Vulkan_qf_particles_h + +#include "QF/image.h" + +struct cvar_s; +struct vulkan_ctx_s;; + +void Vulkan_R_ClearParticles (struct vulkan_ctx_s *ctx); +void Vulkan_R_InitParticles (struct vulkan_ctx_s *ctx); +void Vulkan_r_easter_eggs_f (struct cvar_s *var, struct vulkan_ctx_s *ctx); +void Vulkan_r_particles_style_f (struct cvar_s *var, struct vulkan_ctx_s *ctx); +void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_particles_h diff --git a/include/r_dynamic.h b/include/r_dynamic.h index 1dd54fc11..8968cfa1c 100644 --- a/include/r_dynamic.h +++ b/include/r_dynamic.h @@ -49,12 +49,6 @@ void R_PushDlights (const vec3_t entorigin); struct cvar_s; void R_MaxDlightsCheck (struct cvar_s *var); void R_Particles_Init_Cvars (void); -void R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, - float ramp); -void R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, float die, - int color, float alpha, float ramp); void R_InitBubble (void); void R_InitParticles (void); diff --git a/include/r_internal.h b/include/r_internal.h index de11978fa..b38f1706c 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -16,6 +16,7 @@ extern vid_render_funcs_t gl_vid_render_funcs; extern vid_render_funcs_t glsl_vid_render_funcs; extern vid_render_funcs_t sw_vid_render_funcs; extern vid_render_funcs_t sw32_vid_render_funcs; +extern vid_render_funcs_t vulkan_vid_render_funcs; extern vid_render_funcs_t *vid_render_funcs; #define vr_data vid_render_data diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index 63618451e..5d09f93b7 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -53,7 +53,7 @@ #include "compat.h" void * -gl_Mod_LoadSkin (byte * skin, int skinsize, int snum, int gnum, qboolean group, +gl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) { byte *pskin; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index d44139a22..b58aaf3af 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -237,6 +237,7 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vkparse.c \ libs/video/renderer/vulkan/vulkan_draw.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ + libs/video/renderer/vulkan/vulkan_particles.c \ libs/video/renderer/vulkan/vulkan_texture.c \ libs/video/renderer/vulkan/vulkan_vid_common.c diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 5b7f1a63a..0572efec0 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -1591,6 +1591,27 @@ gl_R_DrawParticles (void) qfglDepthMask (GL_TRUE); } +static void +gl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, + const vec3_t vel, float die, int color, float alpha, + float ramp) +{ + if (numparticles >= r_maxparticles) + return; + particle_new (type, texnum, org, scale, vel, die, color, alpha, ramp); +} + +static void +gl_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, + int org_fuzz, float scale, int vel_fuzz, float die, + int color, float alpha, float ramp) +{ + if (numparticles >= r_maxparticles) + return; + particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, die, + color, alpha, ramp); +} + static vid_particle_funcs_t particles_QF = { R_RocketTrail_QF, R_GrenadeTrail_QF, @@ -1775,24 +1796,3 @@ gl_R_Particles_Init_Cvars (void) "0 for Id, 1 for QF."); R_ParticleFunctionInit (); } - -void -gl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, - float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_new (type, texnum, org, scale, vel, die, color, alpha, ramp); -} - -void -gl_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, float die, - int color, float alpha, float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, die, - color, alpha, ramp); -} diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index b1461f208..cb956188c 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -1800,6 +1800,27 @@ glsl_R_DrawParticles (void) } } +static void +glsl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, + const vec3_t vel, float die, int color, float alpha, + float ramp) +{ + if (numparticles >= r_maxparticles) + return; + particle_new (type, texnum, org, scale, vel, die, color, alpha, ramp); +} + +static void +glsl_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, + int org_fuzz, float scale, int vel_fuzz, float die, + int color, float alpha, float ramp) +{ + if (numparticles >= r_maxparticles) + return; + particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, die, + color, alpha, ramp); +} + static vid_particle_funcs_t particles_QF = { R_RocketTrail_QF, R_GrenadeTrail_QF, @@ -1984,24 +2005,3 @@ glsl_R_Particles_Init_Cvars (void) "0 for Id, 1 for QF."); R_ParticleFunctionInit (); } - -void -glsl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, - float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_new (type, texnum, org, scale, vel, die, color, alpha, ramp); -} - -void -glsl_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, float die, - int color, float alpha, float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, die, - color, alpha, ramp); -} diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 870c01fc1..ae5e1fd8a 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -199,7 +199,7 @@ R_AddEfrags (entity_t *ent) { model_t *entmodel; - if (!ent->model) + if (!ent->model || !r_worldentity.model) return; if (ent == &r_worldentity) diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index 601a003c9..d7039504f 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -801,6 +801,52 @@ r_particles_style_f (cvar_t *var) { } +static void +R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, + const vec3_t vel, float die, int color, float alpha, float ramp) +{ + particle_t *p; + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + VectorCopy (org, p->org); + p->color = color; + p->tex = texnum; + p->scale = scale; + p->alpha = alpha; + VectorCopy (vel, p->vel); + p->type = type; + p->phys = R_ParticlePhysics (p->type); + p->die = die; + p->ramp = ramp; +} + +static void +R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, int org_fuzz, + float scale, int vel_fuzz, float die, int color, + float alpha, float ramp) +{ + float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; + int rnd; + vec3_t porg, pvel; + + rnd = mtwist_rand (&mt); + porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; + porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; + porg[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; + rnd = mtwist_rand (&mt); + pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; + pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; + pvel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; + + R_Particle_New (type, texnum, porg, scale, pvel, die, color, alpha, ramp); +} + static vid_particle_funcs_t particles_QF = { R_RocketTrail_QF, R_GrenadeTrail_QF, @@ -874,49 +920,3 @@ R_Particles_Init_Cvars (void) "0 for Id, 1 for QF."); R_ParticleFunctionInit (); } - -void -R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, float ramp) -{ - particle_t *p; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorCopy (org, p->org); - p->color = color; - p->tex = texnum; - p->scale = scale; - p->alpha = alpha; - VectorCopy (vel, p->vel); - p->type = type; - p->phys = R_ParticlePhysics (p->type); - p->die = die; - p->ramp = ramp; -} - -void -R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, int org_fuzz, - float scale, int vel_fuzz, float die, int color, - float alpha, float ramp) -{ - float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; - int rnd; - vec3_t porg, pvel; - - rnd = mtwist_rand (&mt); - porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; - porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; - porg[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; - rnd = mtwist_rand (&mt); - pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; - pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; - pvel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; - - R_Particle_New (type, texnum, porg, scale, pvel, die, color, alpha, ramp); -} diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 7b910005d..fe2e39601 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -814,6 +814,53 @@ sw32_r_particles_style_f (cvar_t *var) { } +static void +sw32_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, + const vec3_t vel, float die, int color, float alpha, + float ramp) +{ + particle_t *p; + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + VectorCopy (org, p->org); + p->color = color; + p->tex = texnum; + p->scale = scale; + p->alpha = alpha; + VectorCopy (vel, p->vel); + p->type = type; + p->phys = R_ParticlePhysics (p->type); + p->die = die; + p->ramp = ramp; +} + +static void +sw32_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, + int org_fuzz, float scale, int vel_fuzz, float die, + int color, float alpha, float ramp) +{ + float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; + int rnd; + vec3_t porg, pvel; + + rnd = mtwist_rand (&mt); + porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; + porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; + porg[2] = o_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0 + org[2]; + rnd = mtwist_rand (&mt); + pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; + pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; + pvel[2] = v_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0; + + sw32_R_Particle_New (type, texnum, porg, scale, pvel, die, color, alpha, ramp); +} + static vid_particle_funcs_t particles_QF = { R_RocketTrail_QF, R_GrenadeTrail_QF, @@ -887,50 +934,3 @@ sw32_R_Particles_Init_Cvars (void) "0 for Id, 1 for QF."); R_ParticleFunctionInit (); } - -void -sw32_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, - float ramp) -{ - particle_t *p; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorCopy (org, p->org); - p->color = color; - p->tex = texnum; - p->scale = scale; - p->alpha = alpha; - VectorCopy (vel, p->vel); - p->type = type; - p->phys = R_ParticlePhysics (p->type); - p->die = die; - p->ramp = ramp; -} - -void -sw32_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, float die, - int color, float alpha, float ramp) -{ - float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; - int rnd; - vec3_t porg, pvel; - - rnd = mtwist_rand (&mt); - porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; - porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; - porg[2] = o_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0 + org[2]; - rnd = mtwist_rand (&mt); - pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; - pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; - pvel[2] = v_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0; - - sw32_R_Particle_New (type, texnum, porg, scale, pvel, die, color, alpha, ramp); -} diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 646a3b740..80ccf0127 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -40,6 +40,7 @@ #include "QF/plugin/vid_render.h" #include "QF/Vulkan/qf_draw.h" +#include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" @@ -57,6 +58,29 @@ static vulkan_ctx_t *vulkan_ctx; +static tex_t * +vulkan_SCR_CaptureBGR (void) +{ + return 0; +} + +static tex_t * +vulkan_SCR_ScreenShot (int width, int height) +{ + return 0; +} + +static void +vulkan_Fog_Update (float density, float red, float green, float blue, + float time) +{ +} + +static void +vulkan_Fog_ParseWorldspawn (struct plitem_s *worldspawn) +{ +} + static void vulkan_R_Init (void) { @@ -69,6 +93,7 @@ vulkan_R_Init (void) // are being built vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); Vulkan_Draw_Init (vulkan_ctx); + Vulkan_Particles_Init (vulkan_ctx); Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, vulkan_ctx->swapchain->numImages); @@ -180,6 +205,31 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) } } +static void +vulkan_R_ClearState (void) +{ +} + +static void +vulkan_R_LoadSkys (const char *skyname) +{ +} + +static void +vulkan_R_NewMap (model_t *worldmodel, model_t **models, int num_models) +{ +} + +static void +vulkan_R_LineGraph (int x, int y, int *h_vals, int count) +{ +} + +static void +vulkan_R_RenderView (void) +{ +} + static void vulkan_Draw_Character (int x, int y, unsigned ch) { @@ -306,30 +356,127 @@ vulkan_R_ViewChanged (float aspect) Vulkan_CalcProjectionMatrices (vulkan_ctx, aspect); } +static void +vulkan_R_ClearParticles (void) +{ + Vulkan_R_ClearParticles (vulkan_ctx); +} + +static void +vulkan_R_InitParticles (void) +{ + Vulkan_R_InitParticles (vulkan_ctx); +} + +static void +vulkan_SCR_ScreenShot_f (void) +{ +} + +static void +vulkan_r_easter_eggs_f (struct cvar_s *var) +{ + Vulkan_r_easter_eggs_f (var, vulkan_ctx); +} + +static void +vulkan_r_particles_style_f (struct cvar_s *var) +{ + Vulkan_r_particles_style_f (var, vulkan_ctx); +} + +static void +vulkan_Mod_LoadExternalTextures (model_t *mod) +{ +} + +static void +vulkan_Mod_LoadLighting (bsp_t *bsp) +{ +} + +static void +vulkan_Mod_SubdivideSurface (msurface_t *fa) +{ +} + +static void +vulkan_Mod_ProcessTexture (texture_t *tx) +{ +} + +static void +vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, + void *_m, int _s, int extra) +{ +} + +static void * +vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, + qboolean group, maliasskindesc_t *skindesc) +{ + return skin + skinsize; +} + +static void +vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr) +{ +} + +static void +vulkan_Mod_LoadExternalSkins (model_t *mod) +{ +} + +static void +vulkan_Mod_IQMFinish (model_t *mod) +{ +} + +static void +vulkan_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum) +{ +} + +static void +vulkan_Skin_SetupSkin (struct skin_s *skin, int cmap) +{ +} + +static void +vulkan_Skin_ProcessTranslation (int cmap, const byte *translation) +{ +} + +static void +vulkan_Skin_InitTranslations (void) +{ +} + static vid_model_funcs_t model_funcs = { - 0,//vulkan_Mod_LoadExternalTextures, - 0,//vulkan_Mod_LoadLighting, - 0,//vulkan_Mod_SubdivideSurface, - 0,//vulkan_Mod_ProcessTexture, + vulkan_Mod_LoadExternalTextures, + vulkan_Mod_LoadLighting, + vulkan_Mod_SubdivideSurface, + vulkan_Mod_ProcessTexture, Mod_LoadIQM, Mod_LoadAliasModel, Mod_LoadSpriteModel, - 0,//vulkan_Mod_MakeAliasModelDisplayLists, - 0,//vulkan_Mod_LoadSkin, - 0,//vulkan_Mod_FinalizeAliasModel, - 0,//vulkan_Mod_LoadExternalSkins, - 0,//vulkan_Mod_IQMFinish, + vulkan_Mod_MakeAliasModelDisplayLists, + vulkan_Mod_LoadSkin, + vulkan_Mod_FinalizeAliasModel, + vulkan_Mod_LoadExternalSkins, + vulkan_Mod_IQMFinish, 0, - 0,//vulkan_Mod_SpriteLoadTexture, + vulkan_Mod_SpriteLoadTexture, Skin_SetColormap, Skin_SetSkin, - 0,//vulkan_Skin_SetupSkin, + vulkan_Skin_SetupSkin, Skin_SetTranslation, - 0,//vulkan_Skin_ProcessTranslation, - 0,//vulkan_Skin_InitTranslations, + vulkan_Skin_ProcessTranslation, + vulkan_Skin_InitTranslations, }; vid_render_funcs_t vulkan_vid_render_funcs = { @@ -357,33 +504,33 @@ vid_render_funcs_t vulkan_vid_render_funcs = { SCR_DrawRam, SCR_DrawTurtle, SCR_DrawPause, - 0,//vulkan_SCR_CaptureBGR, - 0,//vulkan_SCR_ScreenShot, + vulkan_SCR_CaptureBGR, + vulkan_SCR_ScreenShot, SCR_DrawStringToSnap, - 0,//vulkan_Fog_Update, - 0,//vulkan_Fog_ParseWorldspawn, + vulkan_Fog_Update, + vulkan_Fog_ParseWorldspawn, vulkan_R_Init, vulkan_R_RenderFrame, - 0,//vulkan_R_ClearState, - 0,//vulkan_R_LoadSkys, - 0,//vulkan_R_NewMap, + vulkan_R_ClearState, + vulkan_R_LoadSkys, + vulkan_R_NewMap, R_AddEfrags, R_RemoveEfrags, R_EnqueueEntity, - 0,//vulkan_R_LineGraph, + vulkan_R_LineGraph, R_AllocDlight, R_AllocEntity, R_MaxDlightsCheck, - 0,//vulkan_R_RenderView, + vulkan_R_RenderView, R_DecayLights, vulkan_R_ViewChanged, - 0,//vulkan_R_ClearParticles, - 0,//vulkan_R_InitParticles, - 0,//vulkan_SCR_ScreenShot_f, - 0,//vulkan_r_easter_eggs_f, - 0,//vulkan_r_particles_style_f, + vulkan_R_ClearParticles, + vulkan_R_InitParticles, + vulkan_SCR_ScreenShot_f, + vulkan_r_easter_eggs_f, + vulkan_r_particles_style_f, 0, &model_funcs }; diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c new file mode 100644 index 000000000..282bfaf8a --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -0,0 +1,268 @@ +/* + vulkan_particles.c + + Quake specific Vulkan particle manager + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/render.h" +#include "QF/plugin/vid_render.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/qf_particles.h" + +#include "r_internal.h" +#include "vid_vulkan.h" + +void +Vulkan_R_ClearParticles (struct vulkan_ctx_s *ctx) +{ +} + +void +Vulkan_R_InitParticles (struct vulkan_ctx_s *ctx) +{ +} + +static void +R_RocketTrail_QF (const entity_t *ent) +{ +} + +static void +R_GrenadeTrail_QF (const entity_t *ent) +{ +} + +static void +R_BloodTrail_QF (const entity_t *ent) +{ +} + +static void +R_SlightBloodTrail_QF (const entity_t *ent) +{ +} + +static void +R_WizTrail_QF (const entity_t *ent) +{ +} + +static void +R_FlameTrail_QF (const entity_t *ent) +{ +} + +static void +R_VoorTrail_QF (const entity_t *ent) +{ +} + +static void +R_GlowTrail_QF (const entity_t *ent, int glow_color) +{ +} + +static void +R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, + int count) +{ +} + +static void +R_BloodPuffEffect_QF (const vec3_t org, int count) +{ +} + +static void +R_GunshotEffect_QF (const vec3_t org, int count) +{ +} + +static void +R_LightningBloodEffect_QF (const vec3_t org) +{ +} + +static void +R_SpikeEffect_QF (const vec3_t org) +{ +} + +static void +R_KnightSpikeEffect_QF (const vec3_t org) +{ +} + +static void +R_SuperSpikeEffect_QF (const vec3_t org) +{ +} + +static void +R_WizSpikeEffect_QF (const vec3_t org) +{ +} + +static void +R_BlobExplosion_QF (const vec3_t org) +{ +} + +static void +R_ParticleExplosion_QF (const vec3_t org) +{ +} + +static void +R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) +{ +} + +static void +R_LavaSplash_QF (const vec3_t org) +{ +} + +static void +R_TeleportSplash_QF (const vec3_t org) +{ +} + +static void +R_DarkFieldParticles_ID (const entity_t *ent) +{ +} + +static void +R_EntityParticles_ID (const entity_t *ent) +{ +} + +static void +R_Particle_New (ptype_t type, int texnum, const vec3_t org, + float scale, const vec3_t vel, float die, + int color, float alpha, float ramp) +{ +} + +static void +R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, + int org_fuzz, float scale, int vel_fuzz, + float die, int color, float alpha, + float ramp) +{ +} + +static vid_particle_funcs_t vulkan_particles_QF = { + R_RocketTrail_QF, + R_GrenadeTrail_QF, + R_BloodTrail_QF, + R_SlightBloodTrail_QF, + R_WizTrail_QF, + R_FlameTrail_QF, + R_VoorTrail_QF, + R_GlowTrail_QF, + R_RunParticleEffect_QF, + R_BloodPuffEffect_QF, + R_GunshotEffect_QF, + R_LightningBloodEffect_QF, + R_SpikeEffect_QF, + R_KnightSpikeEffect_QF, + R_SuperSpikeEffect_QF, + R_WizSpikeEffect_QF, + R_BlobExplosion_QF, + R_ParticleExplosion_QF, + R_ParticleExplosion2_QF, + R_LavaSplash_QF, + R_TeleportSplash_QF, + R_DarkFieldParticles_ID, + R_EntityParticles_ID, + R_Particle_New, + R_Particle_NewRandom, +}; + +void +Vulkan_r_easter_eggs_f (cvar_t *var, struct vulkan_ctx_s *ctx) +{ + if (!easter_eggs || !r_particles_style) { + return; + } + if (easter_eggs->int_val) { + if (r_particles_style->int_val) { + //vulkan_vid_render_funcs.particles = &vulkan_particles_QF_egg; + } else { + //vulkan_vid_render_funcs.particles = &vulkan_particles_ID_egg; + } + } else { + if (r_particles_style->int_val) { + //vulkan_vid_render_funcs.particles = &vulkan_particles_QF; + } else { + //vulkan_vid_render_funcs.particles = &vulkan_particles_ID; + } + } + vulkan_vid_render_funcs.particles = &vulkan_particles_QF; +} + +void +Vulkan_r_particles_style_f (cvar_t *var, struct vulkan_ctx_s *ctx) +{ + Vulkan_r_particles_style_f (var, ctx); +} + +void +Vulkan_Particles_Init (struct vulkan_ctx_s *ctx) +{ + /* + easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, r_easter_eggs_f, + "Enables easter eggs."); + r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, + "Toggles drawing of particles."); + r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, + r_particles_max_f, "Maximum amount of " + "particles to display. No maximum, minimum " + "is 0."); + r_particles_nearclip = Cvar_Get ("r_particles_nearclip", "32", + CVAR_ARCHIVE, r_particles_nearclip_f, + "Distance of the particle near clipping " + "plane from the player."); + r_particles_style = Cvar_Get ("r_particles_style", "1", CVAR_ARCHIVE, + r_particles_style_f, "Sets particle style. " + "0 for Id, 1 for QF."); + */ + vulkan_vid_render_funcs.particles = &vulkan_particles_QF; +} From c7b2843c0e6fc6ed88345268def633ee491dd0a6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 18 Jan 2021 17:13:52 +0900 Subject: [PATCH 1223/3664] [vulkan] Create shanders for brush models The fragment shader is a bit of a mini mega-shader, but I do want to try out specializations. --- include/vid_vulkan.h | 1 + libs/video/renderer/Makemodule.am | 10 ++ libs/video/renderer/vulkan/quakebsp.frag | 122 +++++++++++++++++++ libs/video/renderer/vulkan/quakebsp.vert | 28 +++++ libs/video/renderer/vulkan/shader.c | 6 + libs/video/renderer/vulkan/vulkan_matrices.c | 3 +- 6 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 libs/video/renderer/vulkan/quakebsp.frag create mode 100644 libs/video/renderer/vulkan/quakebsp.vert diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index c8d318a99..90d4908f2 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -31,6 +31,7 @@ typedef struct vulkan_matrices_s { float *projection_2d; float *projection_3d; float *view_3d; + float *sky_3d; } vulkan_matrices_t; typedef struct vulkan_framebufferset_s diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index b58aaf3af..bfe8cb5e3 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -261,6 +261,10 @@ twodv_src = libs/video/renderer/vulkan/twod.vert twodv_c = libs/video/renderer/vulkan/twod.vert.spvc twodf_src = libs/video/renderer/vulkan/twod.frag twodf_c = libs/video/renderer/vulkan/twod.frag.spvc +quakebspv_src = libs/video/renderer/vulkan/quakebsp.vert +quakebspv_c = libs/video/renderer/vulkan/quakebsp.vert.spvc +quakebspf_src = libs/video/renderer/vulkan/quakebsp.frag +quakebspf_c = libs/video/renderer/vulkan/quakebsp.frag.spvc passthrough_src = libs/video/renderer/vulkan/passthrough.vert passthrough_c = libs/video/renderer/vulkan/passthrough.vert.spvc pushcolor_src = libs/video/renderer/vulkan/pushcolor.frag @@ -270,6 +274,10 @@ $(twodv_c): $(twodv_src) $(twodf_c): $(twodf_src) +$(quakebspv_c): $(quakebspv_src) + +$(quakebspf_c): $(quakebspf_src) + $(passthrough_c): $(passthrough_src) $(pushcolor_c): $(pushcolor_src) @@ -277,6 +285,8 @@ $(pushcolor_c): $(pushcolor_src) vkshader_c = \ $(twodv_c) \ $(twodf_c) \ + $(quakebspv_c) \ + $(quakebspf_c) \ $(passthrough_c) \ $(pushcolor_c) diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag new file mode 100644 index 000000000..151243249 --- /dev/null +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -0,0 +1,122 @@ +#version 450 + +layout (set = 0, binding = 1) uniform sampler2D Texture; +layout (set = 0, binding = 2) uniform sampler2D Glowmap; +layout (set = 0, binding = 3) uniform sampler2D Lightmap; +layout (set = 0, binding = 4) uniform samplerCube SkyCube; +layout (set = 0, binding = 5) uniform sampler2DArray SkySheet; + +layout (push_constant) uniform PushConstants { + float time; + vec4 fog; +}; + +layout (location = 0) in vec4 tl_st; +layout (location = 1) in vec4 color; +layout (location = 2) out vec3 direction; + +layout (location = 0) out vec4 frag_color; + +layout (constant_id = 0) const bool doWarp = false; +layout (constant_id = 1) const bool doLight = true; +layout (constant_id = 2) const bool doSkyCube = false; +layout (constant_id = 3) const bool doSkySheet = false; + +const float PI = 3.14159265; +const float SPEED = 20.0; +const float CYCLE = 128.0; +const float FACTOR = PI * 2.0 / CYCLE; +const vec2 BIAS = vec2 (1.0, 1.0); +const float SCALE = 8.0; + +vec2 +warp_st (vec2 st, float time) +{ + vec2 angle = st.ts * CYCLE / 2.0; + vec2 phase = vec2 (time, time) * SPEED; + return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; +} + +vec4 +fogBlend (vec4 color) +{ + float az = fog.a * gl_FragCoord.z / gl_FragCoord.w; + vec3 fog_color = fog.rgb; + float fog_factor = exp (-az * az); + + return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); +} + +vec4 +sky_sheet (vec3 dir, float time) +{ + float len; + vec2 flow = vec2 (1.0, 1.0); + vec2 base; + vec3 st1, st2; + vec4 c1, c2, c; + + dir.z *= 3.0; + len = dot (dir, dir); + len = SCALE * inversesqrt (len); + base = dir.yx * vec2(1.0, -1.0) * len; + + st1 = vec3 (base + flow * time / 8.0, 0); + st2 = vec3 (base + flow * time / 16.0, 1); + + c1 = texture (SkySheet, st1); + c2 = texture (SkySheet, st2); + + c = vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); + + return c; +} + +vec4 +sky_cube (vec3 dir, float time) +{ + // NOTE: quake's world is right-handed with Z up and X forward, but + // Vulkan's cube maps are left-handed with Y up and Z forward. The + // rotation to X foward is done by the Sky matrix so all that's left + // to do here is swizzle the Y and Z coordinates + return texture (SkyCube, dir.xzy); +} + +vec4 +sky_color (vec3 dir, float time) +{ + if (!doSkySheet) { + return sky_cube (dir, time); + } if (!doSkyCube) { + return sky_sheet (dir, time); + } else { + // can see through the sheet (may look funny when looking down) + // maybe have 4 sheet layers instead of 2? + vec4 c1 = sky_sheet (dir, time); + vec4 c2 = sky_cube (dir, time); + return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); + } +} + +void +main (void) +{ + vec4 c; + vec2 t_st = tl_st.xy; + vec2 l_st = tl_st.zw; + + if (doWarp) { + t_st = warp_st (t_st, time); + } + if (doSkyCube || doSkySheet) { + c = sky_color (direction, time); + } else { + c = texture (Texture, t_st) * color; + } + if (doLight) { + c *= texture (Lightmap, l_st); + } + c += texture (Glowmap, t_st); + + frag_color = fogBlend (c); +} diff --git a/libs/video/renderer/vulkan/quakebsp.vert b/libs/video/renderer/vulkan/quakebsp.vert new file mode 100644 index 000000000..11ae0c90a --- /dev/null +++ b/libs/video/renderer/vulkan/quakebsp.vert @@ -0,0 +1,28 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection; + mat4 View; + mat4 Sky; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; +}; + +layout (location = 0) in vec4 vertex; +layout (location = 1) in vec4 tl_uv; +layout (location = 2) in vec4 vcolor; + +layout (location = 0) out vec4 tl_st; +layout (location = 1) out vec4 color; +layout (location = 2) out vec3 direction; + +void +main (void) +{ + gl_Position = Projection * (View * (Model * vertex)); + direction = (Sky * vertex).xyz; + tl_st = tl_uv; + color = vcolor; +} diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 25e1049ea..4b0fed532 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -59,6 +59,10 @@ static static #include "libs/video/renderer/vulkan/twod.frag.spvc" static +#include "libs/video/renderer/vulkan/quakebsp.vert.spvc" +static +#include "libs/video/renderer/vulkan/quakebsp.frag.spvc" +static #include "libs/video/renderer/vulkan/passthrough.vert.spvc" static #include "libs/video/renderer/vulkan/pushcolor.frag.spvc" @@ -72,6 +76,8 @@ typedef struct shaderdata_s { static shaderdata_t builtin_shaders[] = { { "twod.vert", twod_vert, sizeof (twod_vert) }, { "twod.frag", twod_frag, sizeof (twod_frag) }, + { "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) }, + { "quakebsp.frag", quakebsp_frag, sizeof (quakebsp_frag) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, {} diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index c734f82d0..62eb16c1d 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -134,7 +134,7 @@ Vulkan_CreateMatrices (vulkan_ctx_t *ctx) __auto_type mat = &ctx->matrices; mat->buffer_2d = QFV_CreateBuffer (device, 1 * MAT_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - mat->buffer_3d = QFV_CreateBuffer (device, 2 * MAT_SIZE, + mat->buffer_3d = QFV_CreateBuffer (device, 3 * MAT_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); size_t size = 0; @@ -159,6 +159,7 @@ Vulkan_CreateMatrices (vulkan_ctx_t *ctx) mat->projection_2d = data; mat->projection_3d = mat->projection_2d + offset / sizeof (float); mat->view_3d = mat->projection_3d + 16; + mat->sky_3d = mat->view_3d + 16; } void From 9b53d7d4e288e2a4763c808754ba405c0222b477 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 19 Jan 2021 08:26:53 +0900 Subject: [PATCH 1224/3664] [model] Remove empty brush model functions It seems better to check for a null pointer and just not call. --- libs/models/brush/glsl_model_brush.c | 10 ---------- libs/models/brush/model_brush.c | 11 +++++++---- libs/models/brush/sw_model_brush.c | 16 ---------------- libs/models/null_model.c | 15 --------------- libs/video/renderer/vid_render_glsl.c | 4 ++-- libs/video/renderer/vid_render_sw.c | 6 +++--- libs/video/renderer/vid_render_sw32.c | 6 +++--- 7 files changed, 15 insertions(+), 53 deletions(-) diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index 8827844da..e840e0b29 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -132,11 +132,6 @@ glsl_Mod_ProcessTexture (texture_t *tx) } } -void -glsl_Mod_LoadExternalTextures (model_t *mod) -{ -} - void glsl_Mod_LoadLighting (bsp_t *bsp) { @@ -150,8 +145,3 @@ glsl_Mod_LoadLighting (bsp_t *bsp) loadmodel->lightdata = Hunk_AllocName (bsp->lightdatasize, loadname); memcpy (loadmodel->lightdata, bsp->lightdata, bsp->lightdatasize); } - -void -glsl_Mod_SubdivideSurface (msurface_t *fa) -{ -} diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index c81fbabe9..19d28a8c6 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -204,7 +204,7 @@ Mod_LoadTextures (bsp_t *bsp) if (!strncmp (mt->name, "sky", 3)) loadmodel->skytexture = tx; - if (mod_funcs) + if (mod_funcs && mod_funcs->Mod_ProcessTexture) mod_funcs->Mod_ProcessTexture (tx); } @@ -539,7 +539,7 @@ Mod_LoadFaces (bsp_t *bsp) if (!strncmp (out->texinfo->texture->name, "sky", 3)) { // sky out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); if (gl_sky_divide && gl_sky_divide->int_val) - if (mod_funcs) + if (mod_funcs && mod_funcs->Mod_SubdivideSurface) mod_funcs->Mod_SubdivideSurface (out); continue; } @@ -552,8 +552,10 @@ Mod_LoadFaces (bsp_t *bsp) out->extents[i] = 16384; out->texturemins[i] = -8192; } - if (mod_funcs) // cut up polygon for warps + if (mod_funcs && mod_funcs->Mod_SubdivideSurface) { + // cut up polygon for warps mod_funcs->Mod_SubdivideSurface (out); + } continue; } } @@ -915,8 +917,9 @@ Mod_LoadBrushModel (model_t *mod, void *buffer) Mod_LoadEdges (bsp); Mod_LoadSurfedges (bsp); Mod_LoadTextures (bsp); - if (mod_funcs) + if (mod_funcs && mod_funcs->Mod_LoadLighting) { mod_funcs->Mod_LoadLighting (bsp); + } Mod_LoadPlanes (bsp); Mod_LoadTexinfo (bsp); Mod_LoadFaces (bsp); diff --git a/libs/models/brush/sw_model_brush.c b/libs/models/brush/sw_model_brush.c index c78cd12b4..1f179bab2 100644 --- a/libs/models/brush/sw_model_brush.c +++ b/libs/models/brush/sw_model_brush.c @@ -40,22 +40,6 @@ #include "mod_internal.h" - -void -sw_Mod_SubdivideSurface (msurface_t *fa) -{ -} - -void -sw_Mod_ProcessTexture (texture_t *tx) -{ -} - -void -sw_Mod_LoadExternalTextures (model_t *mod) -{ -} - void sw_Mod_LoadLighting (bsp_t *bsp) { diff --git a/libs/models/null_model.c b/libs/models/null_model.c index 18cb987c1..6f482cc01 100644 --- a/libs/models/null_model.c +++ b/libs/models/null_model.c @@ -48,26 +48,11 @@ Mod_LoadSpriteModel (model_t *mod, void *buf) { } -void -Mod_ProcessTexture (texture_t *tx) -{ -} - void Mod_LoadExternalSkins (model_t *mod) { } -void -Mod_LoadExternalTextures (model_t *mod) -{ -} - -void -Mod_SubdivideSurface (msurface_t *fa) -{ -} - viddef_t vid; VISIBLE void diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 25bdb9224..6d6c87b3a 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -46,9 +46,9 @@ gl_ctx_t *glsl_ctx; static vid_model_funcs_t model_funcs = { - glsl_Mod_LoadExternalTextures, + 0,//Mod_LoadExternalTextures, glsl_Mod_LoadLighting, - glsl_Mod_SubdivideSurface, + 0,//Mod_SubdivideSurface, glsl_Mod_ProcessTexture, Mod_LoadIQM, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 02ff562e6..8c5360701 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -39,10 +39,10 @@ sw_ctx_t *sw_ctx; static vid_model_funcs_t model_funcs = { - sw_Mod_LoadExternalTextures, + 0,//Mod_LoadExternalTextures, sw_Mod_LoadLighting, - sw_Mod_SubdivideSurface, - sw_Mod_ProcessTexture, + 0,//Mod_SubdivideSurface, + 0,//Mod_ProcessTexture, Mod_LoadIQM, Mod_LoadAliasModel, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 97097e2ad..af72bc0df 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -44,10 +44,10 @@ sw_ctx_t *sw32_ctx; static vid_model_funcs_t model_funcs = { - sw_Mod_LoadExternalTextures, + 0,//Mod_LoadExternalTextures, sw_Mod_LoadLighting, - sw_Mod_SubdivideSurface, - sw_Mod_ProcessTexture, + 0,//Mod_SubdivideSurface, + 0,//Mod_ProcessTexture, Mod_LoadIQM, Mod_LoadAliasModel, From e50430e00cf44c41a60b9241ee5858abc86e5550 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 19 Jan 2021 10:15:57 +0900 Subject: [PATCH 1225/3664] [image] Add parameter to load only the header I want to be able to calculate texture sizes without actually loading the images. --- include/QF/image.h | 8 ++-- include/QF/pcx.h | 3 +- include/QF/png.h | 2 +- include/QF/tga.h | 2 +- libs/image/image.c | 11 ++--- libs/image/pcx.c | 18 +++++++-- libs/image/png.c | 60 ++++++++++++++++------------ libs/image/tga.c | 31 +++++++++----- libs/models/alias/gl_model_alias.c | 12 +++--- libs/models/brush/gl_model_brush.c | 13 +++--- libs/models/brush/glsl_model_brush.c | 2 +- libs/models/iqm/gl_model_iqm.c | 2 +- libs/models/iqm/glsl_model_iqm.c | 4 +- libs/models/iqm/sw_model_iqm.c | 4 +- libs/models/skin.c | 2 +- libs/models/sprite/gl_model_sprite.c | 2 +- libs/video/renderer/gl/gl_draw.c | 6 +-- libs/video/renderer/gl/gl_sky.c | 4 +- libs/video/renderer/glsl/glsl_bsp.c | 6 +-- tools/qflmp/lmp.c | 2 +- tools/qfspritegen/spritegen.c | 2 +- tools/wad/script.c | 2 +- 22 files changed, 116 insertions(+), 82 deletions(-) diff --git a/include/QF/image.h b/include/QF/image.h index 396547f42..cd649c42e 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -45,11 +45,11 @@ typedef struct tex_s { int width; int height; QFFormat format; - byte *palette; // 0 = 32 bit, otherwise 8 - byte data[4]; // variable length + int loaded; // 0 if size info only, otherwise data loaded + byte *palette; // 0 = 32 bit, otherwise 8 + byte data[4]; // variable length } tex_t; - -tex_t *LoadImage (const char *imageFile); +tex_t *LoadImage (const char *imageFile, int load); #endif//__QF_image_h diff --git a/include/QF/pcx.h b/include/QF/pcx.h index 8536b9f69..8ae83a156 100644 --- a/include/QF/pcx.h +++ b/include/QF/pcx.h @@ -71,10 +71,11 @@ pcx_t *EncodePCX (byte *data, int width, int height, int rowbytes, \param f The file to read the texture from \param convert If true, the texture is converted to RGB on load \param pal The palette to apply during conversion + \param load If false, only the format and size info is loaded \return A pointer to the texture. \warning Uses Hunk_TempAlloc() to allocate the texture. */ -struct tex_s *LoadPCX (QFile *f, qboolean convert, byte *pal); +struct tex_s *LoadPCX (QFile *f, qboolean convert, byte *pal, int load); #endif//__QF_pcx_h diff --git a/include/QF/png.h b/include/QF/png.h index c3e2ed562..b322a93f0 100644 --- a/include/QF/png.h +++ b/include/QF/png.h @@ -33,7 +33,7 @@ #include "QF/quakefs.h" -struct tex_s *LoadPNG (QFile *infile); +struct tex_s *LoadPNG (QFile *infile, int load); void WritePNG (const char *fileName, const byte *data, int width, int height); void WritePNGqfs (const char *fileName, const byte *data, int width, int height); diff --git a/include/QF/tga.h b/include/QF/tga.h index 365f5d366..08d610d95 100644 --- a/include/QF/tga.h +++ b/include/QF/tga.h @@ -67,7 +67,7 @@ typedef struct _TargaHeader { # endif #endif -struct tex_s *LoadTGA (QFile *fin); +struct tex_s *LoadTGA (QFile *fin, int load); void WriteTGAfile (const char *tganame, byte *data, int width, int height); #endif//__QF_tga_h diff --git a/libs/image/image.c b/libs/image/image.c index 7df5d9bb2..4da1e5827 100644 --- a/libs/image/image.c +++ b/libs/image/image.c @@ -43,7 +43,7 @@ #include "QF/tga.h" VISIBLE tex_t * -LoadImage (const char *imageFile) +LoadImage (const char *imageFile, int load) { int tmp; dstring_t *tmpFile; @@ -64,7 +64,7 @@ LoadImage (const char *imageFile) dstring_replace (tmpFile, tmp, tmpFile->size, ".png", 5); fp = QFS_FOpenFile (tmpFile->str); if (fp) { - tex = LoadPNG (fp); + tex = LoadPNG (fp, load); Qclose (fp); dstring_delete (tmpFile); return (tex); @@ -74,7 +74,7 @@ LoadImage (const char *imageFile) dstring_replace (tmpFile, tmp, tmpFile->size, ".tga", 5); fp = QFS_FOpenFile (tmpFile->str); if (fp) { - tex = LoadTGA (fp); + tex = LoadTGA (fp, load); Qclose (fp); dstring_delete (tmpFile); return (tex); @@ -85,7 +85,7 @@ LoadImage (const char *imageFile) dstring_replace (tmpFile, tmp, tmpFile->size, ".jpg", 5); fp = QFS_FOpenFile (tmpFile->str); if (fp) { - tex = LoadJPG (fp); + tex = LoadJPG (fp, load); Qclose (fp); dstring_delete (tmpFile); return (tex); @@ -96,7 +96,8 @@ LoadImage (const char *imageFile) dstring_replace (tmpFile, tmp, tmpFile->size, ".pcx", 5); fp = QFS_FOpenFile (tmpFile->str); if (fp) { - tex = LoadPCX (fp, 1, NULL); // Convert, some users don't grok paletted + // Convert, some users don't grok paletted + tex = LoadPCX (fp, 1, NULL, load); Qclose (fp); dstring_delete (tmpFile); return (tex); diff --git a/libs/image/pcx.c b/libs/image/pcx.c index 9ca47bc34..495b1b1d5 100644 --- a/libs/image/pcx.c +++ b/libs/image/pcx.c @@ -47,7 +47,7 @@ VISIBLE tex_t * -LoadPCX (QFile *f, qboolean convert, byte *pal) +LoadPCX (QFile *f, qboolean convert, byte *pal, int load) { pcx_t *pcx; int pcx_mark; @@ -58,8 +58,11 @@ LoadPCX (QFile *f, qboolean convert, byte *pal) int runLength = 1; int count; tex_t *tex; - int fsize = Qfilesize(f); + int fsize = sizeof (pcx_t); + if (load) { + fsize = Qfilesize(f); + } // parse the PCX file pcx_mark = Hunk_LowMark (); pcx = Hunk_AllocName (fsize, "PCX"); @@ -79,14 +82,16 @@ LoadPCX (QFile *f, qboolean convert, byte *pal) || pcx->encoding != 1 || pcx->bits_per_pixel != 8) { Sys_Printf ("Bad pcx file: %x %d %d %d\n", - pcx->manufacturer, pcx->version, pcx->encoding, pcx->bits_per_pixel); + pcx->manufacturer, pcx->version, pcx->encoding, + pcx->bits_per_pixel); + Hunk_FreeToLowMark (pcx_mark); return 0; } end = palette = ((byte *) pcx) + fsize - 768; dataByte = (byte *) &pcx[1]; - count = (pcx->xmax + 1) * (pcx->ymax + 1); + count = load ? (pcx->xmax + 1) * (pcx->ymax + 1) : 0; if (convert) { tex = Hunk_TempAlloc (field_offset (tex_t, data[count * 3])); tex->format = tex_rgb; @@ -101,6 +106,11 @@ LoadPCX (QFile *f, qboolean convert, byte *pal) } tex->width = pcx->xmax + 1; tex->height = pcx->ymax + 1; + tex->loaded = load; + if (!load) { + Hunk_FreeToLowMark (pcx_mark); + return tex; + } pix = tex->data; while (count) { diff --git a/libs/image/png.c b/libs/image/png.c index 62d9977df..9e81ca138 100644 --- a/libs/image/png.c +++ b/libs/image/png.c @@ -115,7 +115,7 @@ readpng_init (QFile *infile, png_structp *png_ptr, png_infop *info_ptr) /* Load the png file and return a texture */ VISIBLE tex_t * -LoadPNG (QFile *infile) +LoadPNG (QFile *infile, int load) { double gamma; png_structp png_ptr = NULL; @@ -131,37 +131,41 @@ LoadPNG (QFile *infile) png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); - if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_expand (png_ptr); + if (load) { + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand (png_ptr); - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - png_set_expand (png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand (png_ptr); - if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_expand (png_ptr); + if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand (png_ptr); - if (bit_depth == 16) - png_set_strip_16 (png_ptr); + if (bit_depth == 16) + png_set_strip_16 (png_ptr); - if (color_type == PNG_COLOR_TYPE_GRAY - || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb (png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb (png_ptr); - /* NOTE: gamma support? */ - /* unlike the example in the libpng documentation, we have *no* idea where - * this file may have come from--so if it doesn't have a file gamma, don't - * do any correction ("do no harm") - */ - if (png_get_gAMA(png_ptr, info_ptr, &gamma)) - png_set_gamma (png_ptr, 1.0, gamma); + /* NOTE: gamma support? */ + /* unlike the example in the libpng documentation, we have *no* idea + * wherethis file may have come from--so if it doesn't have a file + * gamma, don't do any correction ("do no harm") + */ + if (png_get_gAMA(png_ptr, info_ptr, &gamma)) + png_set_gamma (png_ptr, 1.0, gamma); - /* All transformations have been registered, now update the info_ptr - * structure */ - png_read_update_info (png_ptr, info_ptr); + /* All transformations have been registered, now update the info_ptr + * structure */ + png_read_update_info (png_ptr, info_ptr); - /* Allocate tex_t structure */ - rowbytes = png_get_rowbytes(png_ptr, info_ptr); - tex = Hunk_TempAlloc (field_offset (tex_t, data[height * rowbytes])); + /* Allocate tex_t structure */ + rowbytes = png_get_rowbytes(png_ptr, info_ptr); + tex = Hunk_TempAlloc (field_offset (tex_t, data[height * rowbytes])); + } else { + tex = Hunk_TempAlloc (field_offset (tex_t, data[0])); + } tex->width = width; tex->height = height; @@ -170,6 +174,12 @@ LoadPNG (QFile *infile) else tex->format = tex_rgb; tex->palette = NULL; + tex->loaded = load; + + if (!load) { + png_read_end (png_ptr, NULL); + return tex; + } if ((row_pointers = (png_bytepp) malloc (height * sizeof (png_bytep))) == NULL) { diff --git a/libs/image/tga.c b/libs/image/tga.c index 323a05d04..1a4dad133 100644 --- a/libs/image/tga.c +++ b/libs/image/tga.c @@ -620,15 +620,18 @@ static decoder_t decoder_functions[] = { / sizeof (decoder_functions[0])) struct tex_s * -LoadTGA (QFile *fin) +LoadTGA (QFile *fin, int load) { byte *dataByte; decoder_t decode; - int fsize = Qfilesize (fin); + int fsize = sizeof (TargaHeader); int numPixels, targa_mark; TargaHeader *targa; tex_t *tex; + if (load) { + fsize = Qfilesize (fin); + } targa_mark = Hunk_LowMark (); targa = Hunk_AllocName (fsize, "TGA"); Qread (fin, targa, fsize); @@ -641,20 +644,30 @@ LoadTGA (QFile *fin) targa->height = LittleShort (targa->height); if (targa->image_type >= NUM_DECODERS - || !(decode = decoder_functions[targa->image_type])) - Sys_Error ("LoadTGA: Unsupported targa type"); + || !(decode = decoder_functions[targa->image_type])) { + Sys_Printf ("LoadTGA: Unsupported targa type"); + Hunk_FreeToLowMark (targa_mark); + return 0; + } - numPixels = targa->width * targa->height; + if (load) { + numPixels = targa->width * targa->height; + } else { + numPixels = 0; + } tex = Hunk_TempAlloc (field_offset (tex_t, data[numPixels * 4])); tex->width = targa->width; tex->height = targa->height; tex->palette = 0; + tex->loaded = load; - // skip TARGA image comment - dataByte = (byte *) (targa + 1); - dataByte += targa->id_length; + if (load) { + // skip TARGA image comment + dataByte = (byte *) (targa + 1); + dataByte += targa->id_length; - decode (targa, tex, dataByte); + decode (targa, tex, dataByte); + } Hunk_FreeToLowMark (targa_mark); return tex; diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index 5d09f93b7..82919aad4 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -120,9 +120,9 @@ Mod_LoadExternalSkin (maliasskindesc_t *pskindesc, char *filename) if (!ptr) ptr = filename; - tex = LoadImage (filename); + tex = LoadImage (filename, 1); if (!tex) - tex = LoadImage (va ("textures/%s", ptr + 1)); + tex = LoadImage (va ("textures/%s", ptr + 1), 1); if (tex) { pskindesc->texnum = GL_LoadTexture (filename, tex->width, tex->height, tex->data, true, false, @@ -130,13 +130,13 @@ Mod_LoadExternalSkin (maliasskindesc_t *pskindesc, char *filename) pskindesc->fb_texnum = 0; - glow = LoadImage (va ("%s_luma", filename)); + glow = LoadImage (va ("%s_luma", filename), 1); if (!glow) - glow = LoadImage (va ("%s_glow", filename)); + glow = LoadImage (va ("%s_glow", filename), 1); if (!glow) - glow = LoadImage (va ("textures/%s_luma", ptr + 1)); + glow = LoadImage (va ("textures/%s_luma", ptr + 1), 1); if (!glow) - glow = LoadImage (va ("textures/%s_glow", ptr + 1)); + glow = LoadImage (va ("textures/%s_glow", ptr + 1), 1); if (glow) pskindesc->fb_texnum = GL_LoadTexture (va ("fb_%s", filename), glow->width, diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 7b7e171ac..9c1057226 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -68,7 +68,7 @@ gl_Mod_ProcessTexture (texture_t *tx) } static tex_t * -Mod_LoadAnExternalTexture (char * tname, char *mname) +Mod_LoadAnExternalTexture (char *tname, char *mname) { char rname[32]; tex_t *image; @@ -78,17 +78,16 @@ Mod_LoadAnExternalTexture (char * tname, char *mname) if (rname[0] == '*') rname[0] = '#'; image = LoadImage (va ("textures/%.*s/%s", (int) strlen (mname + 5) - 4, - mname + 5, rname)); + mname + 5, rname), 1); if (!image) - image = LoadImage (va ("maps/%.*s/%s", - (int) strlen (mname + 5) - 4, - mname + 5, rname)); + image = LoadImage (va ("maps/%.*s/%s", (int) strlen (mname + 5) - 4, + mname + 5, rname), 1); // if (!image) // image = LoadImage (va ("textures/bmodels/%s", rname)); if (!image) - image = LoadImage (va ("textures/%s", rname)); + image = LoadImage (va ("textures/%s", rname), 1); if (!image) - image = LoadImage (va ("maps/%s", rname)); + image = LoadImage (va ("maps/%s", rname), 1); return image; } diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index e840e0b29..67fff7b44 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -135,7 +135,7 @@ glsl_Mod_ProcessTexture (texture_t *tx) void glsl_Mod_LoadLighting (bsp_t *bsp) { - // a big hacky, but it's as good a place as any + // a bit hacky, but it's as good a place as any loadmodel->clear = glsl_brush_clear; mod_lightmap_bytes = 1; if (!bsp->lightdatasize) { diff --git a/libs/models/iqm/gl_model_iqm.c b/libs/models/iqm/gl_model_iqm.c index e2e877d1d..f57b18637 100644 --- a/libs/models/iqm/gl_model_iqm.c +++ b/libs/models/iqm/gl_model_iqm.c @@ -80,7 +80,7 @@ gl_iqm_load_textures (iqm_t *iqm) for (i = 0; i < iqm->num_meshes; i++) { dstring_copystr (str, iqm->text + iqm->meshes[i].material); QFS_StripExtension (str->str, str->str); - if ((tex = LoadImage (va ("textures/%s", str->str)))) + if ((tex = LoadImage (va ("textures/%s", str->str), 1))) gl->textures[i] = GL_LoadTexture (str->str, tex->width, tex->height, tex->data, true, false, diff --git a/libs/models/iqm/glsl_model_iqm.c b/libs/models/iqm/glsl_model_iqm.c index 5e1a26030..6a79eede7 100644 --- a/libs/models/iqm/glsl_model_iqm.c +++ b/libs/models/iqm/glsl_model_iqm.c @@ -102,12 +102,12 @@ glsl_iqm_load_textures (iqm_t *iqm) for (i = 0; i < iqm->num_meshes; i++) { dstring_copystr (str, iqm->text + iqm->meshes[i].material); QFS_StripExtension (str->str, str->str); - if ((tex = LoadImage (va ("textures/%s", str->str)))) + if ((tex = LoadImage (va ("textures/%s", str->str), 1))) glsl->textures[i] = GLSL_LoadRGBATexture (str->str, tex->width, tex->height, tex->data); else glsl->textures[i] = GLSL_LoadRGBATexture ("", 2, 2, null_texture); - if ((tex = LoadImage (va ("textures/%s_norm", str->str)))) + if ((tex = LoadImage (va ("textures/%s_norm", str->str), 1))) glsl->normmaps[i] = GLSL_LoadRGBATexture (str->str, tex->width, tex->height, tex->data); else diff --git a/libs/models/iqm/sw_model_iqm.c b/libs/models/iqm/sw_model_iqm.c index 5b609ca75..4bc8fedb9 100644 --- a/libs/models/iqm/sw_model_iqm.c +++ b/libs/models/iqm/sw_model_iqm.c @@ -54,7 +54,7 @@ #include "r_internal.h" static tex_t null_texture = { - 2, 2, tex_palette, 0, {15, 15, 15, 15} + 2, 2, tex_palette, 1, 0, {15, 15, 15, 15} }; static void @@ -165,7 +165,7 @@ sw_iqm_load_textures (iqm_t *iqm) continue; dstring_copystr (str, iqm->text + iqm->meshes[i].material); QFS_StripExtension (str->str, str->str); - if ((tex = LoadImage (va ("textures/%s", str->str)))) + if ((tex = LoadImage (va ("textures/%s", str->str), 1))) tex = sw->skins[i] = convert_tex (tex); else tex = sw->skins[i] = &null_texture; diff --git a/libs/models/skin.c b/libs/models/skin.c index 9583383cc..5e1fe0d85 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -184,7 +184,7 @@ Skin_SetSkin (skin_t *skin, int cmap, const char *skinname) name = 0; break; } - tex = LoadPCX (file, 0, r_data->vid->palette); + tex = LoadPCX (file, 0, r_data->vid->palette, 1); Qclose (file); if (!tex || tex->width > 320 || tex->height > 200) { Sys_Printf ("Bad skin %s\n", name); diff --git a/libs/models/sprite/gl_model_sprite.c b/libs/models/sprite/gl_model_sprite.c index 647b5f687..f050e9bdb 100644 --- a/libs/models/sprite/gl_model_sprite.c +++ b/libs/models/sprite/gl_model_sprite.c @@ -49,7 +49,7 @@ gl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum) tex_t *targa; const char *name; - targa = LoadImage (name = va ("%s_%i", loadmodel->name, framenum)); + targa = LoadImage (name = va ("%s_%i", loadmodel->name, framenum), 1); if (targa) { if (targa->format < 4) pspriteframe->gl_texturenum = GL_LoadTexture (name, diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 6cebda1fb..d84e8f17e 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -175,7 +175,7 @@ gl_Draw_PicFromWad (const char *name) tex_t *targa; pic = W_GetLumpName (name); - targa = LoadImage (name); + targa = LoadImage (name, 1); if (targa) { p = malloc (sizeof (qpic_t) + sizeof (glpic_t)); p->width = pic->width; @@ -236,7 +236,7 @@ gl_Draw_CachePic (const char *path, qboolean alpha) // Adjust for endian.. SwapPic (dat); // Check for a .tga first - targa = LoadImage (path); + targa = LoadImage (path, 1); if (targa) { if (targa->format < 4) { gl->texnum = GL_LoadTexture ("", targa->width, targa->height, @@ -353,7 +353,7 @@ gl_Draw_Init (void) // write the version string into the background before turning it into a // texture - image = LoadImage ("gfx/conchars"); + image = LoadImage ("gfx/conchars", 1); if (image) { if (image->format < 4) { char_texture = GL_LoadTexture ("charset", image->width, diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index a4d325f09..4f69ef8b7 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -131,11 +131,11 @@ gl_R_LoadSkys (const char *skyname) qfglBindTexture (GL_TEXTURE_2D, SKY_TEX + i); - targa = LoadImage (name = va ("env/%s%s", skyname, suf[i])); + targa = LoadImage (name = va ("env/%s%s", skyname, suf[i]), 1); if (!targa || targa->format < 3) { // FIXME Can't do PCX right now Sys_MaskPrintf (SYS_DEV, "Couldn't load %s\n", name); // also look in gfx/env, where Darkplaces looks for skies - targa = LoadImage (name = va ("gfx/env/%s%s", skyname, suf[i])); + targa = LoadImage (name = va ("gfx/env/%s%s", skyname, suf[i]), 1); if (!targa) { Sys_MaskPrintf (SYS_DEV, "Couldn't load %s\n", name); gl_skyloaded = false; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index acdaf22c6..0dc19103e 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -1399,7 +1399,7 @@ glsl_R_LoadSkys (const char *sky) //blender envmap // bk rt ft // dn up lt - tex = LoadImage (name = va ("env/%s_map", sky)); + tex = LoadImage (name = va ("env/%s_map", sky), 1); if (tex && tex->format >= 3 && tex->height * 3 == tex->width * 2 && is_pow2 (tex->height)) { tex_t *sub; @@ -1426,12 +1426,12 @@ glsl_R_LoadSkys (const char *sky) } else { skybox_loaded = true; for (i = 0; i < 6; i++) { - tex = LoadImage (name = va ("env/%s%s", sky, sky_suffix[i])); + tex = LoadImage (name = va ("env/%s%s", sky, sky_suffix[i]), 1); if (!tex || tex->format < 3) { // FIXME pcx support Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); // also look in gfx/env, where Darkplaces looks for skies tex = LoadImage (name = va ("gfx/env/%s%s", sky, - sky_suffix[i])); + sky_suffix[i]), 1); if (!tex || tex->format < 3) { // FIXME pcx support Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); skybox_loaded = false; diff --git a/tools/qflmp/lmp.c b/tools/qflmp/lmp.c index b8021166c..1840ce328 100644 --- a/tools/qflmp/lmp.c +++ b/tools/qflmp/lmp.c @@ -213,7 +213,7 @@ importFile (const char *inpath) if (options.verbosity > 1) Sys_Printf ("PCX file size: %d\n", fsize); - lmp = LoadPCX (infile, false, NULL); + lmp = LoadPCX (infile, false, NULL, 1); if (!lmp) { Sys_Printf ("%s: Failed to load %s as texture.\n", diff --git a/tools/qfspritegen/spritegen.c b/tools/qfspritegen/spritegen.c index 5234adc0c..08ddc86f1 100644 --- a/tools/qfspritegen/spritegen.c +++ b/tools/qfspritegen/spritegen.c @@ -190,7 +190,7 @@ LoadScreen (const char *name) file = Qopen (name, "rb"); if (!file) Sys_Error ("could not open"); - image = LoadPCX (file, false, 0); + image = LoadPCX (file, false, 0, 1); } diff --git a/tools/wad/script.c b/tools/wad/script.c index eef6a90e9..b4eaeeeff 100644 --- a/tools/wad/script.c +++ b/tools/wad/script.c @@ -92,7 +92,7 @@ load_image (const char *name) if (!(file = Qopen (name, "rb"))) Sys_Error ("couldn't open %s. %s", name, strerror(errno)); - if (!(tex = LoadPNG (file))) + if (!(tex = LoadPNG (file, 1))) Sys_Error ("couldn't read %s as PNG", name); pixels = tex->width * tex->height; From 40fc9f00005eb163181ce4922d29c93f9ff6bd48 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 19 Jan 2021 10:30:37 +0900 Subject: [PATCH 1226/3664] [model] Make Mod_LoadExternalTextures private It never really needed to be externally accessible as it has always been gl-specific and can be called by Mod_ProcessTexture anyway. --- include/QF/plugin/vid_render.h | 1 - include/mod_internal.h | 3 - libs/models/brush/gl_model_brush.c | 91 ++++++++++++------------- libs/models/model.c | 4 -- libs/video/renderer/vid_render_gl.c | 1 - libs/video/renderer/vid_render_glsl.c | 1 - libs/video/renderer/vid_render_sw.c | 1 - libs/video/renderer/vid_render_sw32.c | 1 - libs/video/renderer/vid_render_vulkan.c | 6 -- 9 files changed, 45 insertions(+), 64 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 462aaabf4..447bc8ce6 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -80,7 +80,6 @@ typedef struct vid_particle_funcs_s { } vid_particle_funcs_t; typedef struct vid_model_funcs_s { - void (*Mod_LoadExternalTextures) (model_t *mod); void (*Mod_LoadLighting) (bsp_t *bsp); void (*Mod_SubdivideSurface) (msurface_t *fa); void (*Mod_ProcessTexture) (texture_t *tx); diff --git a/include/mod_internal.h b/include/mod_internal.h index 7f6be3e4e..2dbf624bf 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -32,17 +32,14 @@ void sw_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr); void sw_Mod_LoadExternalSkins (model_t *mod); void sw_Mod_IQMFinish (model_t *mod); -void gl_Mod_LoadExternalTextures (model_t *mod); void gl_Mod_LoadLighting (bsp_t *bsp); void gl_Mod_SubdivideSurface (msurface_t *fa); void gl_Mod_ProcessTexture(texture_t *tx); -void glsl_Mod_LoadExternalTextures (model_t *mod); void glsl_Mod_LoadLighting (bsp_t *bsp); void glsl_Mod_SubdivideSurface (msurface_t *fa); void glsl_Mod_ProcessTexture(texture_t *tx); -void sw_Mod_LoadExternalTextures (model_t *mod); void sw_Mod_LoadLighting (bsp_t *bsp); void sw_Mod_SubdivideSurface (msurface_t *fa); void sw_Mod_ProcessTexture(texture_t *tx); diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 9c1057226..2c95cbe64 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -51,22 +51,6 @@ #include "mod_internal.h" #include "r_internal.h" - -void -gl_Mod_ProcessTexture (texture_t *tx) -{ - const char *name; - - if (!strncmp (tx->name, "sky", 3)) - return; - name = va ("fb_%s", tx->name); - tx->gl_fb_texturenum = - Mod_Fullbright ((byte *) (tx + 1), tx->width, tx->height, name); - tx->gl_texturenum = - GL_LoadTexture (tx->name, tx->width, tx->height, (byte *) (tx + 1), - true, false, 1); -} - static tex_t * Mod_LoadAnExternalTexture (char *tname, char *mname) { @@ -92,44 +76,59 @@ Mod_LoadAnExternalTexture (char *tname, char *mname) return image; } -void -gl_Mod_LoadExternalTextures (model_t *mod) +static int +Mod_LoadExternalTextures (model_t *mod, texture_t *tx) { - int i; tex_t *base, *luma; - texture_t *tx; + int external = 0; + if ((base = Mod_LoadAnExternalTexture (tx->name, mod->name))) { + external = 1; + tx->gl_texturenum = + GL_LoadTexture (tx->name, base->width, base->height, + base->data, true, false, + base->format > 2 ? base->format : 1); - for (i = 0; i < mod->numtextures; i++) { - tx = mod->textures[i]; - if (!tx) - continue; - - if ((base = Mod_LoadAnExternalTexture (tx->name, mod->name))) { - tx->gl_texturenum = - GL_LoadTexture (tx->name, base->width, base->height, - base->data, true, false, - base->format > 2 ? base->format : 1); - - luma = Mod_LoadAnExternalTexture (va ("%s_luma", tx->name), + luma = Mod_LoadAnExternalTexture (va ("%s_luma", tx->name), + mod->name); + if (!luma) + luma = Mod_LoadAnExternalTexture (va ("%s_glow", tx->name), mod->name); - if (!luma) - luma = Mod_LoadAnExternalTexture (va ("%s_glow", tx->name), - mod->name); - tx->gl_fb_texturenum = 0; + tx->gl_fb_texturenum = 0; - if (luma) { - tx->gl_fb_texturenum = - GL_LoadTexture (va ("fb_%s", tx->name), luma->width, - luma->height, luma->data, true, true, - luma->format > 2 ? luma->format : 1); - } else if (base->format < 3) { - tx->gl_fb_texturenum = - Mod_Fullbright (base->data, base->width, base->height, - va ("fb_%s", tx->name)); - } + if (luma) { + tx->gl_fb_texturenum = + GL_LoadTexture (va ("fb_%s", tx->name), luma->width, + luma->height, luma->data, true, true, + luma->format > 2 ? luma->format : 1); + } else if (base->format < 3) { + tx->gl_fb_texturenum = + Mod_Fullbright (base->data, base->width, base->height, + va ("fb_%s", tx->name)); } } + return external; +} + +void +gl_Mod_ProcessTexture (texture_t *tx) +{ + const char *name; + + if (gl_textures_external && gl_textures_external->int_val) { + if (Mod_LoadExternalTextures (loadmodel, tx)) { + return; + } + } + if (strncmp (tx->name, "sky", 3) == 0) { + return; + } + name = va ("fb_%s", tx->name); + tx->gl_fb_texturenum = + Mod_Fullbright ((byte *) (tx + 1), tx->width, tx->height, name); + tx->gl_texturenum = + GL_LoadTexture (tx->name, tx->width, tx->height, (byte *) (tx + 1), + true, false, 1); } void diff --git a/libs/models/model.c b/libs/models/model.c index bac0223de..d8ce5df03 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -231,10 +231,6 @@ Mod_RealLoadModel (model_t *mod, qboolean crash, cache_allocator_t allocator) default: // Version 29: Quake 1 .bsp // Version 38: Quake 2 .bsp Mod_LoadBrushModel (mod, buf); - - if (gl_textures_external && gl_textures_external->int_val - && mod_funcs && mod_funcs->Mod_LoadExternalTextures) - mod_funcs->Mod_LoadExternalTextures (mod); break; } free (buf); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 852a0a423..8e12a67ec 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -46,7 +46,6 @@ gl_ctx_t *gl_ctx; static vid_model_funcs_t model_funcs = { - gl_Mod_LoadExternalTextures, gl_Mod_LoadLighting, gl_Mod_SubdivideSurface, gl_Mod_ProcessTexture, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 6d6c87b3a..be427f3ca 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -46,7 +46,6 @@ gl_ctx_t *glsl_ctx; static vid_model_funcs_t model_funcs = { - 0,//Mod_LoadExternalTextures, glsl_Mod_LoadLighting, 0,//Mod_SubdivideSurface, glsl_Mod_ProcessTexture, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 8c5360701..e30ef9e2e 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -39,7 +39,6 @@ sw_ctx_t *sw_ctx; static vid_model_funcs_t model_funcs = { - 0,//Mod_LoadExternalTextures, sw_Mod_LoadLighting, 0,//Mod_SubdivideSurface, 0,//Mod_ProcessTexture, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index af72bc0df..895098065 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -44,7 +44,6 @@ sw_ctx_t *sw32_ctx; static vid_model_funcs_t model_funcs = { - 0,//Mod_LoadExternalTextures, sw_Mod_LoadLighting, 0,//Mod_SubdivideSurface, 0,//Mod_ProcessTexture, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 80ccf0127..8cfb7926a 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -385,11 +385,6 @@ vulkan_r_particles_style_f (struct cvar_s *var) Vulkan_r_particles_style_f (var, vulkan_ctx); } -static void -vulkan_Mod_LoadExternalTextures (model_t *mod) -{ -} - static void vulkan_Mod_LoadLighting (bsp_t *bsp) { @@ -454,7 +449,6 @@ vulkan_Skin_InitTranslations (void) } static vid_model_funcs_t model_funcs = { - vulkan_Mod_LoadExternalTextures, vulkan_Mod_LoadLighting, vulkan_Mod_SubdivideSurface, vulkan_Mod_ProcessTexture, From 6e0cb7b917c951b2d42555156160bbf8de3152c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 19 Jan 2021 13:05:39 +0900 Subject: [PATCH 1227/3664] [model] Isolate renderer specific texture data This cleans up texture_t and possibly even improves locality of reference when running through texture chains (not profiled, and not actually the goal). --- include/QF/model.h | 12 ++----- include/QF/plugin/vid_render.h | 1 + include/mod_internal.h | 3 -- include/r_internal.h | 27 +++++++++++++++ libs/models/brush/gl_model_brush.c | 22 ++++++++---- libs/models/brush/glsl_model_brush.c | 32 ++++++++++++------ libs/models/brush/model_brush.c | 16 ++++++++- libs/video/renderer/gl/gl_rsurf.c | 29 +++++++++------- libs/video/renderer/glsl/glsl_bsp.c | 45 +++++++++++++------------ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_sw32.c | 1 + libs/video/renderer/vid_render_vulkan.c | 1 + 14 files changed, 130 insertions(+), 62 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index d4b243241..e8cb22367 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -91,19 +91,13 @@ typedef struct instsurf_s { typedef struct texture_s { char *name; - unsigned int width, height; - int gl_texturenum; - int gl_fb_texturenum; - int sky_tex[2]; - instsurf_t *tex_chain; // for gl_texsort drawing - instsurf_t **tex_chain_tail; - struct elechain_s *elechain; - struct elechain_s **elechain_tail; + unsigned width, height; + void *render; // renderer specific data int anim_total; // total tenths in sequence ( 0 = no) int anim_min, anim_max; // time for this frame min <=time< max struct texture_s *anim_next; // in the animation sequence struct texture_s *alternate_anims; // bmodels in frmae 1 use these - unsigned int offsets[MIPLEVELS]; // four mip maps stored + unsigned offsets[MIPLEVELS]; // four mip maps stored } texture_t; diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 447bc8ce6..b2ea3d224 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -80,6 +80,7 @@ typedef struct vid_particle_funcs_s { } vid_particle_funcs_t; typedef struct vid_model_funcs_s { + size_t texture_render_size;// size of renderer specific texture data void (*Mod_LoadLighting) (bsp_t *bsp); void (*Mod_SubdivideSurface) (msurface_t *fa); void (*Mod_ProcessTexture) (texture_t *tx); diff --git a/include/mod_internal.h b/include/mod_internal.h index 2dbf624bf..125da1065 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -37,12 +37,9 @@ void gl_Mod_SubdivideSurface (msurface_t *fa); void gl_Mod_ProcessTexture(texture_t *tx); void glsl_Mod_LoadLighting (bsp_t *bsp); -void glsl_Mod_SubdivideSurface (msurface_t *fa); void glsl_Mod_ProcessTexture(texture_t *tx); void sw_Mod_LoadLighting (bsp_t *bsp); -void sw_Mod_SubdivideSurface (msurface_t *fa); -void sw_Mod_ProcessTexture(texture_t *tx); void gl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum); void glsl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum); diff --git a/include/r_internal.h b/include/r_internal.h index b38f1706c..37edbbdd2 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -9,6 +9,33 @@ #include "r_screen.h" #include "r_shared.h" +typedef struct gltex_s { + texture_t *texture; + int gl_texturenum; + int gl_fb_texturenum; + instsurf_t *tex_chain; // for gl_texsort drawing + instsurf_t **tex_chain_tail; +} gltex_t; + +typedef struct glsltex_s { + texture_t *texture; + int gl_texturenum; + int sky_tex[2]; + instsurf_t *tex_chain; // for gl_texsort drawing + instsurf_t **tex_chain_tail; + struct elechain_s *elechain; + struct elechain_s **elechain_tail; +} glsltex_t; + +typedef struct vulktex_s { + texture_t *texture; + struct qfv_tex_s *tex; + instsurf_t *tex_chain; // for gl_texsort drawing + instsurf_t **tex_chain_tail; + struct elechain_s *elechain; + struct elechain_s **elechain_tail; +} vulktex_t; + extern viddef_t vid; // global video state extern vid_render_data_t vid_render_data; diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 2c95cbe64..1d7d04634 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -51,6 +51,8 @@ #include "mod_internal.h" #include "r_internal.h" +static gltex_t gl_notexture = { }; + static tex_t * Mod_LoadAnExternalTexture (char *tname, char *mname) { @@ -80,10 +82,13 @@ static int Mod_LoadExternalTextures (model_t *mod, texture_t *tx) { tex_t *base, *luma; + gltex_t *gltx; int external = 0; + + gltx = tx->render; if ((base = Mod_LoadAnExternalTexture (tx->name, mod->name))) { external = 1; - tx->gl_texturenum = + gltx->gl_texturenum = GL_LoadTexture (tx->name, base->width, base->height, base->data, true, false, base->format > 2 ? base->format : 1); @@ -94,15 +99,15 @@ Mod_LoadExternalTextures (model_t *mod, texture_t *tx) luma = Mod_LoadAnExternalTexture (va ("%s_glow", tx->name), mod->name); - tx->gl_fb_texturenum = 0; + gltx->gl_fb_texturenum = 0; if (luma) { - tx->gl_fb_texturenum = + gltx->gl_fb_texturenum = GL_LoadTexture (va ("fb_%s", tx->name), luma->width, luma->height, luma->data, true, true, luma->format > 2 ? luma->format : 1); } else if (base->format < 3) { - tx->gl_fb_texturenum = + gltx->gl_fb_texturenum = Mod_Fullbright (base->data, base->width, base->height, va ("fb_%s", tx->name)); } @@ -115,6 +120,10 @@ gl_Mod_ProcessTexture (texture_t *tx) { const char *name; + if (!tx) { + r_notexture_mip->render = &gl_notexture; + return; + } if (gl_textures_external && gl_textures_external->int_val) { if (Mod_LoadExternalTextures (loadmodel, tx)) { return; @@ -123,10 +132,11 @@ gl_Mod_ProcessTexture (texture_t *tx) if (strncmp (tx->name, "sky", 3) == 0) { return; } + gltex_t *gltex = tx->render; name = va ("fb_%s", tx->name); - tx->gl_fb_texturenum = + gltex->gl_fb_texturenum = Mod_Fullbright ((byte *) (tx + 1), tx->width, tx->height, name); - tx->gl_texturenum = + gltex->gl_texturenum = GL_LoadTexture (tx->name, tx->width, tx->height, (byte *) (tx + 1), true, false, 1); } diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index 67fff7b44..e839f5317 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -57,6 +57,9 @@ #include "compat.h" #include "mod_internal.h" +#include "r_internal.h" + +static glsltex_t glsl_notexture = { }; static void glsl_brush_clear (model_t *m) @@ -66,11 +69,15 @@ glsl_brush_clear (model_t *m) m->needload = true; for (i = 0; i < m->numtextures; i++) { // NOTE: some maps (eg e1m2) have empty texture slots - if (m->textures[i] && m->textures[i]->gl_texturenum) { - GLSL_ReleaseTexture (m->textures[i]->gl_texturenum); - GLSL_ReleaseTexture (m->textures[i]->sky_tex[0]); - GLSL_ReleaseTexture (m->textures[i]->sky_tex[1]); - m->textures[i]->gl_texturenum = 0; + glsltex_t *tex = 0; + if (m->textures[i]) { + tex = m->textures[i]->render; + } + if (tex && tex->gl_texturenum) { + GLSL_ReleaseTexture (tex->gl_texturenum); + GLSL_ReleaseTexture (tex->sky_tex[0]); + GLSL_ReleaseTexture (tex->sky_tex[1]); + tex->gl_texturenum = 0; } } for (i = 0; i < m->numsurfaces; i++) { @@ -96,6 +103,11 @@ load_skytex (texture_t *tx, byte *data) void glsl_Mod_ProcessTexture (texture_t *tx) { + if (!tx) { + r_notexture_mip->render = &glsl_notexture; + return; + } + glsltex_t *tex = tx->render; if (!strncmp (tx->name, "sky", 3)) { // sky textures need to be loaded as two separate textures to allow // wrapping on both sky layers. @@ -112,23 +124,23 @@ glsl_Mod_ProcessTexture (texture_t *tx) // a square sky texture probably means it's black, but just in // case some other magic is being done, duplicate the square to // both sky layers. - tx->sky_tex[0] = load_skytex (tx, tx_data); - tx->sky_tex[1] = tx->sky_tex[0]; + tex->sky_tex[0] = load_skytex (tx, tx_data); + tex->sky_tex[1] = tex->sky_tex[0]; } else if (tx_w == 2 * tx_h) { data = alloca (tx_h * tx_h); for (i = 0; i < 2; i++) { for (j = 0; j < tx_h; j++) memcpy (&data[j * tx_h], &tx_data[j * tx_w + i * tx_h], tx_h); - tx->sky_tex[i] = load_skytex (tx, data); + tex->sky_tex[i] = load_skytex (tx, data); } - tx->gl_texturenum = 0; + tex->gl_texturenum = 0; } else { Sys_Error ("Mod_ProcessTexture: invalid sky texture: %dx%d\n", tx_w, tx_h); } } else { - tx->gl_texturenum = GLSL_LoadQuakeMipTex (tx); + tex->gl_texturenum = GLSL_LoadQuakeMipTex (tx); } } diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 19d28a8c6..f3ab08689 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -204,8 +204,22 @@ Mod_LoadTextures (bsp_t *bsp) if (!strncmp (mt->name, "sky", 3)) loadmodel->skytexture = tx; - if (mod_funcs && mod_funcs->Mod_ProcessTexture) + } + if (mod_funcs && mod_funcs->Mod_ProcessTexture) { + size_t render_size = mod_funcs->texture_render_size; + byte *render_data = 0; + if (render_size) { + render_data = Hunk_AllocName (m->nummiptex * render_size, + loadname); + } + for (i = 0; i < m->nummiptex; i++) { + tx = loadmodel->textures[i]; + tx->render = render_data; + render_data += render_size; mod_funcs->Mod_ProcessTexture (tx); + } + // signal the end of the textures + mod_funcs->Mod_ProcessTexture (0); } // sequence the animations diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 3cfb3c49b..f673e4cc4 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -85,7 +85,7 @@ static instsurf_t **sky_chain_tail; (chain) = inst; \ } while (0) -static texture_t **r_texture_chains; +static gltex_t **r_texture_chains; static int r_num_texture_chains; static int max_texture_chains; @@ -129,16 +129,17 @@ release_instsurfs (void) } void -gl_R_AddTexture (texture_t *tex) +gl_R_AddTexture (texture_t *tx) { int i; if (r_num_texture_chains == max_texture_chains) { max_texture_chains += 64; r_texture_chains = realloc (r_texture_chains, - max_texture_chains * sizeof (texture_t *)); + max_texture_chains * sizeof (gltex_t *)); for (i = r_num_texture_chains; i < max_texture_chains; i++) r_texture_chains[i] = 0; } + gltex_t *tex = tx->render; r_texture_chains[r_num_texture_chains++] = tex; tex->tex_chain = NULL; tex->tex_chain_tail = &tex->tex_chain; @@ -174,7 +175,7 @@ R_RenderFullbrights (void) int i, j; glpoly_t *p; instsurf_t *sc; - texture_t *tex; + gltex_t *tex; for (i = 0; i < r_num_texture_chains; i++) { if (!(tex = r_texture_chains[i]) || !tex->gl_fb_texturenum) @@ -332,13 +333,15 @@ gl_R_DrawWaterSurfaces (void) i = -1; for (s = waterchain; s; s = s->tex_chain) { + gltex_t *tex; fa = s->surface; if (s->transform) qfglLoadMatrixf (s->transform); else qfglLoadMatrixf (gl_r_world_matrix); - if (i != fa->texinfo->texture->gl_texturenum) { - i = fa->texinfo->texture->gl_texturenum; + tex = fa->texinfo->texture->render; + if (i != tex->gl_texturenum) { + i = tex->gl_texturenum; qfglBindTexture (GL_TEXTURE_2D, i); } GL_EmitWaterPolys (fa); @@ -360,7 +363,7 @@ DrawTextureChains (int disable_blend, int do_bind) int i; instsurf_t *s; msurface_t *fa; - texture_t *tex; + gltex_t *tex; if (gl_mtex_active_tmus >= 2) { // Lightmaps @@ -469,7 +472,7 @@ static void clear_texture_chains (void) { int i; - texture_t *tex; + gltex_t *tex; for (i = 0; i < r_num_texture_chains; i++) { tex = r_texture_chains[i]; @@ -478,7 +481,7 @@ clear_texture_chains (void) tex->tex_chain = NULL; tex->tex_chain_tail = &tex->tex_chain; } - tex = r_notexture_mip; + tex = r_notexture_mip->render; tex->tex_chain = NULL; tex->tex_chain_tail = &tex->tex_chain; release_instsurfs (); @@ -496,12 +499,14 @@ chain_surface (msurface_t *surf, vec_t *transform, float *color) } else if (surf->flags & SURF_DRAWSKY) { CHAIN_SURF_F2B (surf, sky_chain); } else { - texture_t *tex; + texture_t *tx; + gltex_t *tex; if (!surf->texinfo->texture->anim_total) - tex = surf->texinfo->texture; + tx = surf->texinfo->texture; else - tex = R_TextureAnimation (surf); + tx = R_TextureAnimation (surf); + tex = tx->render; CHAIN_SURF_F2B (surf, tex->tex_chain); R_AddToLightmapChain (surf); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 0dc19103e..409450901 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -73,7 +73,7 @@ static instsurf_t **waterchain_tail = &waterchain; static instsurf_t *sky_chain; static instsurf_t **sky_chain_tail = &sky_chain; -static texture_t **r_texture_chains; +static glsltex_t **r_texture_chains; static int r_num_texture_chains; static int max_texture_chains; @@ -293,16 +293,17 @@ GET_RELEASE (instsurf_t, static_instsurf) GET_RELEASE (instsurf_t, instsurf) void -glsl_R_AddTexture (texture_t *tex) +glsl_R_AddTexture (texture_t *tx) { int i; if (r_num_texture_chains == max_texture_chains) { max_texture_chains += 64; r_texture_chains = realloc (r_texture_chains, - max_texture_chains * sizeof (texture_t *)); + max_texture_chains * sizeof (glsltex_t *)); for (i = r_num_texture_chains; i < max_texture_chains; i++) r_texture_chains[i] = 0; } + glsltex_t *tex = tx->render; r_texture_chains[r_num_texture_chains++] = tex; tex->tex_chain = 0; tex->tex_chain_tail = &tex->tex_chain; @@ -325,7 +326,7 @@ glsl_R_InitSurfaceChains (model_t *model) } static inline void -clear_tex_chain (texture_t *tex) +clear_tex_chain (glsltex_t *tex) { tex->tex_chain = 0; tex->tex_chain_tail = &tex->tex_chain; @@ -343,7 +344,7 @@ clear_texture_chains (void) continue; clear_tex_chain (r_texture_chains[i]); } - clear_tex_chain (r_notexture_mip); + clear_tex_chain (r_notexture_mip->render); release_elechains (); release_elementss (); release_instsurfs (); @@ -382,12 +383,14 @@ chain_surface (msurface_t *surf, vec_t *transform, float *color) } else if ((surf->flags & SURF_DRAWTURB) || (color && color[3] < 1.0)) { CHAIN_SURF_B2F (surf, waterchain); } else { - texture_t *tex; + texture_t *tx; + glsltex_t *tex; if (!surf->texinfo->texture->anim_total) - tex = surf->texinfo->texture; + tx = surf->texinfo->texture; else - tex = R_TextureAnimation (surf); + tx = R_TextureAnimation (surf); + tex = tx->render; CHAIN_SURF_F2B (surf, tex->tex_chain); update_lightmap (surf); @@ -444,7 +447,7 @@ glsl_R_RegisterTextures (model_t **models, int num_models) } static elechain_t * -add_elechain (texture_t *tex, int ec_index) +add_elechain (glsltex_t *tex, int ec_index) { elechain_t *ec; @@ -563,7 +566,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) // non-bsp models don't have surfaces. dm = m->submodels; for (j = 0; j < m->numsurfaces; j++) { - texture_t *tex; + glsltex_t *tex; if (j == dm->firstface + dm->numfaces) { dm++; if (dm - m->submodels == m->numsubmodels) { @@ -578,7 +581,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) surf->ec_index = dm - m->submodels; if (!surf->ec_index && m != r_worldentity.model) surf->ec_index = -1 - i; // instanced model - tex = surf->texinfo->texture; + tex = surf->texinfo->texture->render; CHAIN_SURF_F2B (surf, tex->tex_chain); } } @@ -590,7 +593,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) // For animated textures, if a surface is on one texture of the group, it // will be on all. for (i = 0; i < r_num_texture_chains; i++) { - texture_t *tex; + glsltex_t *tex; instsurf_t *is; elechain_t *ec = 0; elements_t *el = 0; @@ -1057,7 +1060,7 @@ sky_end (void) } static inline void -add_surf_elements (texture_t *tex, instsurf_t *is, +add_surf_elements (glsltex_t *tex, instsurf_t *is, elechain_t **ec, elements_t **el) { msurface_t *surf = is->surface; @@ -1096,7 +1099,7 @@ add_surf_elements (texture_t *tex, instsurf_t *is, } static void -build_tex_elechain (texture_t *tex) +build_tex_elechain (glsltex_t *tex) { instsurf_t *is; elechain_t *ec = 0; @@ -1136,7 +1139,7 @@ glsl_R_DrawWorld (void) bsp_begin (); qfeglActiveTexture (GL_TEXTURE0 + 0); for (i = 0; i < r_num_texture_chains; i++) { - texture_t *tex; + glsltex_t *tex; elechain_t *ec = 0; tex = r_texture_chains[i]; @@ -1163,7 +1166,7 @@ glsl_R_DrawWaterSurfaces () { instsurf_t *is; msurface_t *surf; - texture_t *tex = 0; + glsltex_t *tex = 0; elechain_t *ec = 0; elements_t *el = 0; @@ -1173,7 +1176,7 @@ glsl_R_DrawWaterSurfaces () turb_begin (); for (is = waterchain; is; is = is->tex_chain) { surf = is->surface; - if (tex != surf->texinfo->texture) { + if (tex != surf->texinfo->texture->render) { if (tex) { qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); for (ec = tex->elechain; ec; ec = ec->next) @@ -1184,7 +1187,7 @@ glsl_R_DrawWaterSurfaces () tex->elechain = 0; tex->elechain_tail = &tex->elechain; } - tex = surf->texinfo->texture; + tex = surf->texinfo->texture->render; } add_surf_elements (tex, is, &ec, &el); } @@ -1209,7 +1212,7 @@ glsl_R_DrawSky (void) { instsurf_t *is; msurface_t *surf; - texture_t *tex = 0; + glsltex_t *tex = 0; elechain_t *ec = 0; elements_t *el = 0; @@ -1219,7 +1222,7 @@ glsl_R_DrawSky (void) sky_begin (); for (is = sky_chain; is; is = is->tex_chain) { surf = is->surface; - if (tex != surf->texinfo->texture) { + if (tex != surf->texinfo->texture->render) { if (tex) { if (!skybox_loaded) { qfeglActiveTexture (GL_TEXTURE0 + 0); @@ -1233,7 +1236,7 @@ glsl_R_DrawSky (void) tex->elechain = 0; tex->elechain_tail = &tex->elechain; } - tex = surf->texinfo->texture; + tex = surf->texinfo->texture->render; } add_surf_elements (tex, is, &ec, &el); } diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 8e12a67ec..584f03ada 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -46,6 +46,7 @@ gl_ctx_t *gl_ctx; static vid_model_funcs_t model_funcs = { + sizeof (gltex_t), gl_Mod_LoadLighting, gl_Mod_SubdivideSurface, gl_Mod_ProcessTexture, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index be427f3ca..d8abed43e 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -46,6 +46,7 @@ gl_ctx_t *glsl_ctx; static vid_model_funcs_t model_funcs = { + sizeof (glsltex_t), glsl_Mod_LoadLighting, 0,//Mod_SubdivideSurface, glsl_Mod_ProcessTexture, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index e30ef9e2e..0ef7a0108 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -39,6 +39,7 @@ sw_ctx_t *sw_ctx; static vid_model_funcs_t model_funcs = { + 0, sw_Mod_LoadLighting, 0,//Mod_SubdivideSurface, 0,//Mod_ProcessTexture, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 895098065..a3fe10d97 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -44,6 +44,7 @@ sw_ctx_t *sw32_ctx; static vid_model_funcs_t model_funcs = { + 0, sw_Mod_LoadLighting, 0,//Mod_SubdivideSurface, 0,//Mod_ProcessTexture, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 8cfb7926a..717809012 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -449,6 +449,7 @@ vulkan_Skin_InitTranslations (void) } static vid_model_funcs_t model_funcs = { + sizeof (vulktex_t), vulkan_Mod_LoadLighting, vulkan_Mod_SubdivideSurface, vulkan_Mod_ProcessTexture, From 7a353d5aeeecee59f42b1ac9ffd04d3d2b96b3d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 19 Jan 2021 13:53:08 +0900 Subject: [PATCH 1228/3664] [model] Build vulkan model libs The contents are currently empty (required .c files), but this gets the build system updated. --- config.d/build_control.m4 | 29 +++++++++++++++--------- libs/models/Makemodule.am | 17 +++++++++++++- libs/models/alias/Makemodule.am | 15 ++++++++++-- libs/models/alias/vulkan_model_alias.c | 0 libs/models/brush/Makemodule.am | 16 +++++++++++-- libs/models/brush/vulkan_model_brush.c | 0 libs/models/iqm/Makemodule.am | 16 +++++++++++-- libs/models/iqm/vulkan_model_iqm.c | 0 libs/models/sprite/Makemodule.am | 16 +++++++++++-- libs/models/sprite/vulkan_model_sprite.c | 0 libs/models/vulkan_skin.c | 0 libs/video/renderer/Makemodule.am | 7 +++--- 12 files changed, 93 insertions(+), 23 deletions(-) create mode 100644 libs/models/alias/vulkan_model_alias.c create mode 100644 libs/models/brush/vulkan_model_brush.c create mode 100644 libs/models/iqm/vulkan_model_iqm.c create mode 100644 libs/models/sprite/vulkan_model_sprite.c create mode 100644 libs/models/vulkan_skin.c diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index d67d50033..be71d59f4 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -72,10 +72,14 @@ if test "x$HAVE_X" = xyes; then CL_TARGETS="$CL_TARGETS X11" VID_TARGETS="$VID_TARGETS libs/video/targets/libQFx11.la" if test "$HAVE_VULKAN" = "yes"; then - QF_NEED(vid_render, [sw sw32 gl glsl vulkan]) - else - QF_NEED(vid_render, [sw sw32 gl glsl]) + QF_NEED(vid_render, [vulkan]) + QF_NEED(models, [vulkan]) + QF_NEED(alias, [vulkan]) + QF_NEED(brush, [vulkan]) + QF_NEED(iqm, [vulkan]) + QF_NEED(sprite, [vulkan]) fi + QF_NEED(vid_render, [sw sw32 gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -100,10 +104,13 @@ if test "x$HAVE_SDL" = xyes; then CL_TARGETS="$CL_TARGETS SDL" VID_TARGETS="$VID_TARGETS libs/video/targets/libQFsdl.la" if test "$HAVE_VULKAN" = "yes"; then - QF_NEED(vid_render, [sw sw32 gl glsl vulkan]) - else - QF_NEED(vid_render, [sw sw32 gl glsl]) + QF_NEED(vid_render, [vulkan]) + QF_NEED(alias, [vulkan]) + QF_NEED(brush, [vulkan]) + QF_NEED(iqm, [vulkan]) + QF_NEED(sprite, [vulkan]) fi + QF_NEED(vid_render, [sw sw32 gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -291,11 +298,11 @@ QF_PROCESS_NEED_DIRS(top, [libs hw nq qtv qw tools ruamoko]) QF_PROCESS_NEED_LIBS(swrend, [asm]) QF_PROCESS_NEED_DIRS(vid_render, [gl glsl sw sw32 vulkan]) -QF_PROCESS_NEED_LIBS(models, [gl glsl sw], [libs/models]) -QF_PROCESS_NEED_LIBS(alias, [gl glsl sw], [libs/models/alias]) -QF_PROCESS_NEED_LIBS(brush, [gl glsl sw], [libs/models/brush]) -QF_PROCESS_NEED_LIBS(iqm, [gl glsl sw], [libs/models/iqm]) -QF_PROCESS_NEED_LIBS(sprite, [gl glsl sw], [libs/models/sprite]) +QF_PROCESS_NEED_LIBS(models, [gl glsl sw vulkan], [libs/models]) +QF_PROCESS_NEED_LIBS(alias, [gl glsl sw vulkan], [libs/models/alias]) +QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush]) +QF_PROCESS_NEED_LIBS(iqm, [gl glsl sw vulkan], [libs/models/iqm]) +QF_PROCESS_NEED_LIBS(sprite, [gl glsl sw vulkan], [libs/models/sprite]) QF_PROCESS_NEED_LIBS(vid, [common sdl svga x11], [libs/video/targets]) QF_PROCESS_NEED_LIBS(qw, [client common sdl server], [qw/source], a) diff --git a/libs/models/Makemodule.am b/libs/models/Makemodule.am index 2fbc7380d..24e5a3ca3 100644 --- a/libs/models/Makemodule.am +++ b/libs/models/Makemodule.am @@ -6,7 +6,11 @@ include libs/models/test/Makemodule.am lib_LTLIBRARIES += libs/models/libQFmodels.la noinst_LTLIBRARIES += @models_libs@ -EXTRA_LTLIBRARIES += libs/models/libmodels_gl.la libs/models/libmodels_glsl.la libs/models/libmodels_sw.la +EXTRA_LTLIBRARIES += \ + libs/models/libmodels_gl.la \ + libs/models/libmodels_glsl.la \ + libs/models/libmodels_sw.la \ + libs/models/libmodels_vulkan.la models_sources = libs/models/clip_hull.c libs/models/model.c libs/models/portal.c libs/models/trace.c libs/models/winding.c @@ -53,3 +57,14 @@ libs_models_libmodels_sw_la_LDFLAGS= libs_models_libmodels_sw_la_LIBADD= $(sw_libs) libs_models_libmodels_sw_la_DEPENDENCIES= $(sw_libs) libs_models_libmodels_sw_la_SOURCES= libs/models/sw_skin.c libs/models/skin.c + +vulkan_libs= \ + libs/models/alias/libalias_vulkan.la \ + libs/models/brush/libbrush_vulkan.la \ + libs/models/iqm/libiqm_vulkan.la \ + libs/models/sprite/libsprite_vulkan.la \ + libs/image/libQFimage.la +libs_models_libmodels_vulkan_la_LDFLAGS= +libs_models_libmodels_vulkan_la_LIBADD= $(vulkan_libs) +libs_models_libmodels_vulkan_la_DEPENDENCIES= $(vulkan_libs) +libs_models_libmodels_vulkan_la_SOURCES= libs/models/vulkan_skin.c libs/models/skin.c diff --git a/libs/models/alias/Makemodule.am b/libs/models/alias/Makemodule.am index 42f2c5a73..cac8d4a09 100644 --- a/libs/models/alias/Makemodule.am +++ b/libs/models/alias/Makemodule.am @@ -1,15 +1,26 @@ noinst_LTLIBRARIES += @alias_libs@ -EXTRA_LTLIBRARIES += libs/models/alias/libalias_gl.la libs/models/alias/libalias_glsl.la libs/models/alias/libalias_sw.la +EXTRA_LTLIBRARIES += \ + libs/models/alias/libalias_gl.la \ + libs/models/alias/libalias_glsl.la \ + libs/models/alias/libalias_sw.la \ + libs/models/alias/libalias_vulkan.la alias_src= libs/models/alias/model_alias.c alias_gl_src= libs/models/alias/gl_mesh.c libs/models/alias/gl_model_alias.c libs/models/alias/floodfill.c alias_glsl_src= libs/models/alias/glsl_model_alias.c libs/models/alias/floodfill.c alias_sw_src= libs/models/alias/sw_model_alias.c +alias_vulkan_src= libs/models/alias/vulkan_model_alias.c libs_models_alias_libalias_gl_la_SOURCES= $(alias_gl_src) $(alias_src) libs_models_alias_libalias_glsl_la_SOURCES= $(alias_glsl_src) $(alias_src) libs_models_alias_libalias_sw_la_SOURCES= $(alias_sw_src) $(alias_src) +libs_models_alias_libalias_vulkan_la_SOURCES= $(alias_vulkan_src) $(alias_src) -EXTRA_DIST += $(alias_gl_src) $(alias_glsl_src) $(alias_sw_src) $(alias_src) +EXTRA_DIST += \ + $(alias_gl_src) \ + $(alias_glsl_src) \ + $(alias_sw_src) \ + $(alias_vulkan_src) \ + $(alias_src) diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c new file mode 100644 index 000000000..e69de29bb diff --git a/libs/models/brush/Makemodule.am b/libs/models/brush/Makemodule.am index a07ce0726..4a6f03a1f 100644 --- a/libs/models/brush/Makemodule.am +++ b/libs/models/brush/Makemodule.am @@ -1,10 +1,15 @@ noinst_LTLIBRARIES += libs/models/brush/libbrush.la @brush_libs@ -EXTRA_LTLIBRARIES += libs/models/brush/libbrush_gl.la libs/models/brush/libbrush_glsl.la libs/models/brush/libbrush_sw.la +EXTRA_LTLIBRARIES += \ + libs/models/brush/libbrush_gl.la \ + libs/models/brush/libbrush_glsl.la \ + libs/models/brush/libbrush_sw.la \ + libs/models/brush/libbrush_vulkan.la brush_src= libs/models/brush/model_brush.c brush_gl_src= libs/models/brush/gl_model_brush.c brush_glsl_src= libs/models/brush/glsl_model_brush.c brush_sw_src= libs/models/brush/sw_model_brush.c +brush_vulkan_src= libs/models/brush/vulkan_model_brush.c libs_models_brush_libbrush_la_SOURCES= $(brush_src) @@ -14,4 +19,11 @@ libs_models_brush_libbrush_glsl_la_SOURCES= $(brush_glsl_src) $(brush_src) libs_models_brush_libbrush_sw_la_SOURCES= $(brush_sw_src) $(brush_src) -EXTRA_DIST += $(brush_gl_src) $(brush_glsl_src) $(brush_sw_src) $(brush_src) +libs_models_brush_libbrush_vulkan_la_SOURCES= $(brush_vulkan_src) $(brush_src) + +EXTRA_DIST += \ + $(brush_gl_src) \ + $(brush_glsl_src) \ + $(brush_sw_src) \ + ${brush_vulkan_src} \ + $(brush_src) diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c new file mode 100644 index 000000000..e69de29bb diff --git a/libs/models/iqm/Makemodule.am b/libs/models/iqm/Makemodule.am index 20c29548b..cc362050d 100644 --- a/libs/models/iqm/Makemodule.am +++ b/libs/models/iqm/Makemodule.am @@ -1,10 +1,15 @@ noinst_LTLIBRARIES += @iqm_libs@ -EXTRA_LTLIBRARIES += libs/models/iqm/libiqm_gl.la libs/models/iqm/libiqm_glsl.la libs/models/iqm/libiqm_sw.la +EXTRA_LTLIBRARIES += \ + libs/models/iqm/libiqm_gl.la \ + libs/models/iqm/libiqm_glsl.la \ + libs/models/iqm/libiqm_sw.la \ + libs/models/iqm/libiqm_vulkan.la iqm_src= libs/models/iqm/model_iqm.c iqm_gl_src= libs/models/iqm/gl_model_iqm.c iqm_glsl_src= libs/models/iqm/glsl_model_iqm.c iqm_sw_src= libs/models/iqm/sw_model_iqm.c +iqm_vulkan_src= libs/models/iqm/vulkan_model_iqm.c libs_models_iqm_libiqm_gl_la_SOURCES= $(iqm_gl_src) $(iqm_src) @@ -12,4 +17,11 @@ libs_models_iqm_libiqm_glsl_la_SOURCES= $(iqm_glsl_src) $(iqm_src) libs_models_iqm_libiqm_sw_la_SOURCES= $(iqm_sw_src) $(iqm_src) -EXTRA_DIST += $(iqm_gl_src) $(iqm_glsl_src) $(iqm_sw_src) $(iqm_src) +libs_models_iqm_libiqm_vulkan_la_SOURCES= $(iqm_vulkan_src) $(iqm_src) + +EXTRA_DIST += \ + $(iqm_gl_src) \ + $(iqm_glsl_src) \ + $(iqm_sw_src) \ + $(iqm_vulkan_src) \ + $(iqm_src) diff --git a/libs/models/iqm/vulkan_model_iqm.c b/libs/models/iqm/vulkan_model_iqm.c new file mode 100644 index 000000000..e69de29bb diff --git a/libs/models/sprite/Makemodule.am b/libs/models/sprite/Makemodule.am index 76b9fa714..2021eb370 100644 --- a/libs/models/sprite/Makemodule.am +++ b/libs/models/sprite/Makemodule.am @@ -1,10 +1,15 @@ noinst_LTLIBRARIES += @sprite_libs@ -EXTRA_LTLIBRARIES += libs/models/sprite/libsprite_gl.la libs/models/sprite/libsprite_glsl.la libs/models/sprite/libsprite_sw.la +EXTRA_LTLIBRARIES += \ + libs/models/sprite/libsprite_gl.la \ + libs/models/sprite/libsprite_glsl.la \ + libs/models/sprite/libsprite_sw.la \ + libs/models/sprite/libsprite_vulkan.la sprite_src= libs/models/sprite/model_sprite.c sprite_gl_src= libs/models/sprite/gl_model_sprite.c sprite_glsl_src= libs/models/sprite/glsl_model_sprite.c sprite_sw_src= libs/models/sprite/sw_model_sprite.c +sprite_vulkan_src= libs/models/sprite/vulkan_model_sprite.c libs_models_sprite_libsprite_gl_la_SOURCES= $(sprite_gl_src) $(sprite_src) @@ -12,4 +17,11 @@ libs_models_sprite_libsprite_glsl_la_SOURCES= $(sprite_glsl_src) $(sprite_src) libs_models_sprite_libsprite_sw_la_SOURCES= $(sprite_sw_src) $(sprite_src) -EXTRA_DIST += $(sprite_gl_src) $(sprite_glsl_src) $(sprite_sw_src) $(sprite_src) +libs_models_sprite_libsprite_vulkan_la_SOURCES= $(sprite_vulkan_src) $(sprite_src) + +EXTRA_DIST += \ + $(sprite_gl_src) \ + $(sprite_glsl_src) \ + $(sprite_sw_src) \ + $(sprite_vulkan_src) \ + $(sprite_src) diff --git a/libs/models/sprite/vulkan_model_sprite.c b/libs/models/sprite/vulkan_model_sprite.c new file mode 100644 index 000000000..e69de29bb diff --git a/libs/models/vulkan_skin.c b/libs/models/vulkan_skin.c new file mode 100644 index 000000000..e69de29bb diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index bfe8cb5e3..b149d528c 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -210,10 +210,11 @@ libs_video_renderer_vid_render_sw32_la_SOURCES=\ pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc -vulkan_libs = +video_renderer_vulkan_libs = \ + libs/models/libmodels_vulkan.la libs_video_renderer_vid_render_vulkan_la_LDFLAGS= $(plugin_ldflags) -libs_video_renderer_vid_render_vulkan_la_LIBADD= $(vulkan_libs) -libs_video_renderer_vid_render_vulkan_la_DEPENDENCIES=$(vulkan_libs) +libs_video_renderer_vid_render_vulkan_la_LIBADD= $(video_renderer_vulkan_libs) +libs_video_renderer_vid_render_vulkan_la_DEPENDENCIES=$(video_renderer_vulkan_libs) libs_video_renderer_vid_render_vulkan_la_SOURCES = \ $(video_renderer_common_sources) \ libs/video/renderer/vid_render_vulkan.c \ From ba5e86d9274751748968493952bb406bef9b59a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 19 Jan 2021 14:54:39 +0900 Subject: [PATCH 1229/3664] [model] Move Mod_CalcFullbright to its own file This allows it to be shared between renderers. --- libs/models/Makemodule.am | 8 ++++- libs/models/fullbright.c | 49 +++++++++++++++++++++++++++++++ libs/models/gl_model_fullbright.c | 18 ------------ 3 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 libs/models/fullbright.c diff --git a/libs/models/Makemodule.am b/libs/models/Makemodule.am index 24e5a3ca3..982e96a3a 100644 --- a/libs/models/Makemodule.am +++ b/libs/models/Makemodule.am @@ -12,7 +12,13 @@ EXTRA_LTLIBRARIES += \ libs/models/libmodels_sw.la \ libs/models/libmodels_vulkan.la -models_sources = libs/models/clip_hull.c libs/models/model.c libs/models/portal.c libs/models/trace.c libs/models/winding.c +models_sources = \ + libs/models/clip_hull.c \ + libs/models/fullbright.c \ + libs/models/model.c \ + libs/models/portal.c \ + libs/models/trace.c \ + libs/models/winding.c common_libs = \ libs/util/libQFutil.la diff --git a/libs/models/fullbright.c b/libs/models/fullbright.c new file mode 100644 index 000000000..79c32ede9 --- /dev/null +++ b/libs/models/fullbright.c @@ -0,0 +1,49 @@ +/* + fullbright.c + + fullbright skin handling + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +// models are the only shared resource between a client and server running +// on the same machine. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "r_local.h" + + +VISIBLE int +Mod_CalcFullbright (byte *in, byte *out, int pixels) +{ + byte fb = 0; + + while (pixels--) { + byte pix = *in++; + byte mask = (pix >= 256 - 32) - 1; + fb |= mask + 1; + *out++ = pix | mask; + } + return fb; +} diff --git a/libs/models/gl_model_fullbright.c b/libs/models/gl_model_fullbright.c index 3417b6646..f319581ae 100644 --- a/libs/models/gl_model_fullbright.c +++ b/libs/models/gl_model_fullbright.c @@ -40,24 +40,6 @@ #include "r_local.h" - -VISIBLE int -Mod_CalcFullbright (byte *in, byte *out, int pixels) -{ - int fb = 0; - - while (pixels--) { - if (*in >= 256 - 32) { - fb = 1; - *out++ = *in++; - } else { - *out++ = 255; - in++; - } - } - return fb; -} - int Mod_Fullbright (byte *skin, int width, int height, const char *name) { From 0f81432090c3e6a968de5fef52908b2983e25364 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 19 Jan 2021 18:15:05 +0900 Subject: [PATCH 1230/3664] [model] Load bsp textures into vulkan The textures for an entire model are loaded into a single memory object with shared between multiple images. --- include/QF/Vulkan/qf_texture.h | 9 +- include/QF/model.h | 3 +- include/mod_internal.h | 6 + include/r_internal.h | 3 +- libs/models/alias/glsl_model_alias.c | 2 +- libs/models/brush/glsl_model_brush.c | 2 +- libs/models/brush/model_brush.c | 11 +- libs/models/brush/vulkan_model_brush.c | 212 ++++++++++++++++++++ libs/models/iqm/gl_model_iqm.c | 2 +- libs/models/iqm/glsl_model_iqm.c | 2 +- libs/models/iqm/sw_model_iqm.c | 2 +- libs/models/model.c | 2 +- libs/models/sprite/glsl_model_sprite.c | 2 +- libs/video/renderer/r_init.c | 1 + libs/video/renderer/vid_render_vulkan.c | 4 +- libs/video/renderer/vulkan/vulkan_texture.c | 7 - 16 files changed, 247 insertions(+), 23 deletions(-) diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index a1750682d..90906873c 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -2,9 +2,14 @@ #define __QF_Vulkan_qf_texture_h #include "QF/image.h" +#include "QF/Vulkan/qf_vid.h" -typedef struct qfv_tex_s qfv_tex_t; -struct vulkan_ctx_s; +typedef struct qfv_tex_s { + VkDeviceMemory memory; + size_t offset; + VkImage image; + VkImageView view; +} qfv_tex_t; qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip); VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure)); diff --git a/include/QF/model.h b/include/QF/model.h index e8cb22367..1dbfe1b6f 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -422,7 +422,8 @@ typedef struct model_s { // additional model data cache_user_t cache; - void (*clear) (struct model_s *m); + void (*clear) (struct model_s *m, void *data); + void *data; } model_t; // ============================================================================ diff --git a/include/mod_internal.h b/include/mod_internal.h index 125da1065..632411785 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -6,6 +6,8 @@ #include "QF/skin.h" #include "QF/plugin/vid_render.h" +struct vulkan_ctx_s; + extern vid_model_funcs_t *m_funcs; void gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, @@ -41,6 +43,10 @@ void glsl_Mod_ProcessTexture(texture_t *tx); void sw_Mod_LoadLighting (bsp_t *bsp); +void Vulkan_Mod_LoadLighting (bsp_t *bsp, struct vulkan_ctx_s *ctx); +void Vulkan_Mod_SubdivideSurface (msurface_t *fa, struct vulkan_ctx_s *ctx); +void Vulkan_Mod_ProcessTexture(texture_t *tx, struct vulkan_ctx_s *ctx); + void gl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum); void glsl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum); void sw_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum); diff --git a/include/r_internal.h b/include/r_internal.h index 37edbbdd2..01c9af001 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -29,11 +29,12 @@ typedef struct glsltex_s { typedef struct vulktex_s { texture_t *texture; - struct qfv_tex_s *tex; instsurf_t *tex_chain; // for gl_texsort drawing instsurf_t **tex_chain_tail; struct elechain_s *elechain; struct elechain_s **elechain_tail; + struct qfv_tex_s *tex; + struct qfv_tex_s *glow; } vulktex_t; extern viddef_t vid; // global video state diff --git a/libs/models/alias/glsl_model_alias.c b/libs/models/alias/glsl_model_alias.c index 5e80ccbb8..215c9d400 100644 --- a/libs/models/alias/glsl_model_alias.c +++ b/libs/models/alias/glsl_model_alias.c @@ -55,7 +55,7 @@ static vec3_t vertex_normals[NUMVERTEXNORMALS] = { }; static void -glsl_alias_clear (model_t *m) +glsl_alias_clear (model_t *m, void *data) { int i, j; aliashdr_t *hdr; diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index e839f5317..23bb683ad 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -62,7 +62,7 @@ static glsltex_t glsl_notexture = { }; static void -glsl_brush_clear (model_t *m) +glsl_brush_clear (model_t *m, void *data) { int i; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index f3ab08689..24af26c95 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -982,10 +982,13 @@ Mod_LoadBrushModel (model_t *mod, void *buffer) char name[12]; snprintf (name, sizeof (name), "*%i", i + 1); - loadmodel = Mod_FindName (name); - *loadmodel = *mod; - strcpy (loadmodel->name, name); - mod = loadmodel; + model_t *m = Mod_FindName (name); + *m = *mod; + strcpy (m->name, name); + mod = m; + // make sure clear is called only for the main model + m->clear = 0; + m->data = 0; } } } diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index e69de29bb..5cc5f2984 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -0,0 +1,212 @@ +/* + vulkan_model_brush.c + + Vulkan support routines for model loading and caching + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +// models are the only shared resource between a client and server running +// on the same machine. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/image.h" +#include "QF/qendian.h" +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/Vulkan/qf_bsp.h" +#include "QF/Vulkan/qf_model.h" +#include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" + +#include "compat.h" +#include "mod_internal.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +static vulktex_t vulkan_notexture = { }; + +static void vulkan_brush_clear (model_t *model, void *data) +{ + modelctx_t *mctx = data; + vulkan_ctx_t *ctx = mctx->ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + for (int i = 0; i < model->numtextures; i++) { + texture_t *tx = model->textures[i]; + if (!tx) { + continue; + } + vulktex_t *tex = tx->render; + dfunc->vkDestroyImage (device->dev, tex->tex->image, 0); + if (tex->glow) { + dfunc->vkDestroyImage (device->dev, tex->glow->image, 0); + } + } + dfunc->vkFreeMemory (device->dev, mctx->texture_memory, 0); +} + +static size_t +get_image_size (VkImage image, qfv_device_t *device) +{ + qfv_devfuncs_t *dfunc = device->funcs; + size_t size; + size_t align; + + VkMemoryRequirements requirements; + dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements); + size = requirements.size; + align = requirements.alignment - 1; + size = (size + align) & ~(align); + return size; +} + +static void +load_textures (model_t *model, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + modelctx_t *mctx = model->data; + VkImage image = 0; + + size_t memsize = 0; + for (int i = 0; i < model->numtextures; i++) { + texture_t *tx = model->textures[i]; + if (!tx) { + continue; + } + vulktex_t *tex = tx->render; + tex->tex->offset = memsize; + memsize += get_image_size (tex->tex->image, device); + // just so we have one in the end + image = tex->tex->image; + if (tex->glow) { + tex->glow->offset = memsize; + memsize += get_image_size (tex->glow->image, device); + } + } + VkDeviceMemory mem; + mem = QFV_AllocImageMemory (device, image, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + memsize, 0); + mctx->texture_memory = mem; + + for (int i = 0; i < model->numtextures; i++) { + texture_t *tx = model->textures[i]; + if (!tx) { + continue; + } + vulktex_t *tex = tx->render; + + dfunc->vkBindImageMemory (device->dev, tex->tex->image, mem, + tex->tex->offset); + if (tex->glow) { + dfunc->vkBindImageMemory (device->dev, tex->glow->image, mem, + tex->glow->offset); + } + } +} + +void +Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + if (!tx) { + modelctx_t *mctx = Hunk_AllocName (sizeof (modelctx_t), + loadmodel->name); + mctx->ctx = ctx; + loadmodel->clear = vulkan_brush_clear; + loadmodel->data = mctx; + + r_notexture_mip->render = &vulkan_notexture; + load_textures (loadmodel, ctx); + return; + } + + vulktex_t *tex = tx->render; + tex->tex = (qfv_tex_t *) (tx + 1); + VkExtent3D extent = { tx->width, tx->height, 1 }; + + int layers = 1; + if (strncmp (tx->name, "sky", 3) == 0) { + layers = 2; + } + + tex->tex->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, + VK_FORMAT_R8G8B8A8_UNORM, + extent, 4, layers, + VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT); + if (layers > 1) { + // skys are unlit, so no fullbrights + return; + } + + const char *name = va ("fb_%s", tx->name); + int size = (tx->width * tx->height * 85) / 64; + int fullbright_mark = Hunk_LowMark (); + byte *pixels = Hunk_AllocName (size, name); + + if (!Mod_CalcFullbright ((byte *) (tx + 1), pixels, size)) { + Hunk_FreeToLowMark (fullbright_mark); + return; + } + tex->glow = tex->tex + 1; + tex->glow->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, + VK_FORMAT_R8G8B8A8_UNORM, + extent, 4, 1, + VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT); + // store the pointer to the fullbright data: memory will never be set to + // actual device memory because all of the textures will be loaded in one + // big buffer + tex->glow->memory = (VkDeviceMemory) pixels; +} + +void +Vulkan_Mod_LoadLighting (bsp_t *bsp, vulkan_ctx_t *ctx) +{ + mod_lightmap_bytes = 1; + if (!bsp->lightdatasize) { + loadmodel->lightdata = NULL; + return; + } + loadmodel->lightdata = Hunk_AllocName (bsp->lightdatasize, loadname); + memcpy (loadmodel->lightdata, bsp->lightdata, bsp->lightdatasize); +} diff --git a/libs/models/iqm/gl_model_iqm.c b/libs/models/iqm/gl_model_iqm.c index f57b18637..93a1e9992 100644 --- a/libs/models/iqm/gl_model_iqm.c +++ b/libs/models/iqm/gl_model_iqm.c @@ -56,7 +56,7 @@ static byte null_texture[] = { }; static void -gl_iqm_clear (model_t *mod) +gl_iqm_clear (model_t *mod, void *data) { iqm_t *iqm = (iqm_t *) mod->aliashdr; gliqm_t *gl = (gliqm_t *) iqm->extra_data; diff --git a/libs/models/iqm/glsl_model_iqm.c b/libs/models/iqm/glsl_model_iqm.c index 6a79eede7..5b37e0fd2 100644 --- a/libs/models/iqm/glsl_model_iqm.c +++ b/libs/models/iqm/glsl_model_iqm.c @@ -68,7 +68,7 @@ static byte null_normmap[] = { }; static void -glsl_iqm_clear (model_t *mod) +glsl_iqm_clear (model_t *mod, void *data) { iqm_t *iqm = (iqm_t *) mod->aliashdr; glsliqm_t *glsl = (glsliqm_t *) iqm->extra_data; diff --git a/libs/models/iqm/sw_model_iqm.c b/libs/models/iqm/sw_model_iqm.c index 4bc8fedb9..b15422090 100644 --- a/libs/models/iqm/sw_model_iqm.c +++ b/libs/models/iqm/sw_model_iqm.c @@ -58,7 +58,7 @@ static tex_t null_texture = { }; static void -sw_iqm_clear (model_t *mod) +sw_iqm_clear (model_t *mod, void *data) { iqm_t *iqm = (iqm_t *) mod->aliashdr; swiqm_t *sw = (swiqm_t *) iqm->extra_data; diff --git a/libs/models/model.c b/libs/models/model.c index d8ce5df03..198a69f7c 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -123,7 +123,7 @@ Mod_ClearAll (void) for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) { if (!(*mod)->needload && (*mod)->clear) { - (*mod)->clear (*mod); + (*mod)->clear (*mod, (*mod)->data); } else { if ((*mod)->type != mod_alias) (*mod)->needload = true; diff --git a/libs/models/sprite/glsl_model_sprite.c b/libs/models/sprite/glsl_model_sprite.c index 66e1318e2..bbef94e02 100644 --- a/libs/models/sprite/glsl_model_sprite.c +++ b/libs/models/sprite/glsl_model_sprite.c @@ -47,7 +47,7 @@ #include "mod_internal.h" static void -glsl_sprite_clear (model_t *m) +glsl_sprite_clear (model_t *m, void *data) { int i, j; msprite_t *sprite = (msprite_t *) m->cache.data; diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 733004a21..94385e1c2 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -68,6 +68,7 @@ static U void (*const r_scrapdelete)(rscrap_t *) = R_ScrapDelete; static void R_shutdown (void *data) { + Mod_ClearAll (); if (vidrendmodule->functions->general->p_Shutdown) { vidrendmodule->functions->general->p_Shutdown (); } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 717809012..4d2744089 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -388,6 +388,7 @@ vulkan_r_particles_style_f (struct cvar_s *var) static void vulkan_Mod_LoadLighting (bsp_t *bsp) { + Vulkan_Mod_LoadLighting (bsp, vulkan_ctx); } static void @@ -398,6 +399,7 @@ vulkan_Mod_SubdivideSurface (msurface_t *fa) static void vulkan_Mod_ProcessTexture (texture_t *tx) { + Vulkan_Mod_ProcessTexture (tx, vulkan_ctx); } static void @@ -449,7 +451,7 @@ vulkan_Skin_InitTranslations (void) } static vid_model_funcs_t model_funcs = { - sizeof (vulktex_t), + sizeof (vulktex_t) + 2 * sizeof (struct qfv_tex_s *), vulkan_Mod_LoadLighting, vulkan_Mod_SubdivideSurface, vulkan_Mod_ProcessTexture, diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 0b2c2e102..c9dc0d60f 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -62,13 +62,6 @@ #include "r_scrap.h" #include "vid_vulkan.h" -struct qfv_tex_s { // qfv_tex_t - VkDeviceMemory memory; - size_t offset; - VkImage image; - VkImageView view; -}; - static int ilog2 (unsigned x) { From 82889a2c52d77117f8b5e0d063afd43b9da5c4d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 19 Jan 2021 18:25:30 +0900 Subject: [PATCH 1231/3664] [model] Create and destroy the bsp image views --- libs/models/brush/vulkan_model_brush.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 5cc5f2984..fe5fbfce5 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -72,8 +72,10 @@ static void vulkan_brush_clear (model_t *model, void *data) } vulktex_t *tex = tx->render; dfunc->vkDestroyImage (device->dev, tex->tex->image, 0); + dfunc->vkDestroyImageView (device->dev, tex->tex->view, 0); if (tex->glow) { dfunc->vkDestroyImage (device->dev, tex->glow->image, 0); + dfunc->vkDestroyImageView (device->dev, tex->glow->view, 0); } } dfunc->vkFreeMemory (device->dev, mctx->texture_memory, 0); @@ -133,9 +135,22 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) dfunc->vkBindImageMemory (device->dev, tex->tex->image, mem, tex->tex->offset); + VkImageViewType type = VK_IMAGE_VIEW_TYPE_2D; + if (strncmp (tx->name, "sky", 3) == 0) { + type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + } + tex->tex->view = QFV_CreateImageView (device, tex->tex->image, + type, VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_ASPECT_COLOR_BIT); if (tex->glow) { dfunc->vkBindImageMemory (device->dev, tex->glow->image, mem, tex->glow->offset); + // skys are unlit so never have a glow texture thus glow + // textures are always simple 2D + tex->glow->view = QFV_CreateImageView (device, tex->tex->image, + VK_IMAGE_VIEW_TYPE_2D, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_ASPECT_COLOR_BIT); } } } From 2de1c02f61eb69701efac1e61e5410ac6a1a5d51 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 20 Jan 2021 01:18:47 +0900 Subject: [PATCH 1232/3664] [image] Add support for float rgba for vulkan --- include/QF/image.h | 1 + libs/models/iqm/sw_model_iqm.c | 9 +++++++++ libs/video/renderer/vulkan/texture.c | 4 ++++ libs/video/renderer/vulkan/vulkan_texture.c | 4 ++++ 4 files changed, 18 insertions(+) diff --git a/include/QF/image.h b/include/QF/image.h index cd649c42e..62d57dd35 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -38,6 +38,7 @@ typedef enum QFFormat { tex_la = 2, tex_rgb = 3, tex_rgba = 4, + tex_frgba = 5, } QFFormat; // could not use texture_t as that is used for models. diff --git a/libs/models/iqm/sw_model_iqm.c b/libs/models/iqm/sw_model_iqm.c index b15422090..582109a73 100644 --- a/libs/models/iqm/sw_model_iqm.c +++ b/libs/models/iqm/sw_model_iqm.c @@ -130,6 +130,15 @@ convert_tex (tex_t *tex) for (i = 0; i < pixels; i++) new->data[i] = convert_color (tex->data + i * bpp); break; + case tex_frgba: + for (i = 0; i < pixels; i++) { + byte col[3]; + col[0] = ((float *)tex->data)[i * 4 + 0] * 255; + col[1] = ((float *)tex->data)[i * 4 + 1] * 255; + col[2] = ((float *)tex->data)[i * 4 + 2] * 255; + new->data[i] = convert_color (col); + } + break; } return new; } diff --git a/libs/video/renderer/vulkan/texture.c b/libs/video/renderer/vulkan/texture.c index b4eacf0e6..d926632a7 100644 --- a/libs/video/renderer/vulkan/texture.c +++ b/libs/video/renderer/vulkan/texture.c @@ -100,6 +100,10 @@ QFV_CreateScrap (qfv_device_t *device, int size, QFFormat format) bpp = 4; fmt = VK_FORMAT_R8G8B8A8_UNORM; break; + case tex_frgba: + bpp = 16; + fmt = VK_FORMAT_R32G32B32A32_SFLOAT; + break; } scrap_t *scrap = malloc (sizeof (scrap_t)); diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index c9dc0d60f..05d602d63 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -118,6 +118,10 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) format = VK_FORMAT_R8G8B8A8_UNORM; bpp = 4; break; + case tex_frgba: + format = VK_FORMAT_R32G32B32A32_SFLOAT; + bpp = 16; + break; } if (format == VK_FORMAT_UNDEFINED) { return 0; From df82cb88eec5f6b8573515ea09cd2110591da7d7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 20 Jan 2021 01:23:24 +0900 Subject: [PATCH 1233/3664] [vulkan] Make some little cleanups --- include/QF/Vulkan/qf_particles.h | 5 +++-- libs/video/renderer/glsl/glsl_lightmap.c | 3 --- libs/video/renderer/vulkan/vulkan_draw.c | 4 ++-- libs/video/renderer/vulkan/vulkan_particles.c | 11 ++++++++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index 3ac71ac71..c256a9610 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -6,10 +6,11 @@ struct cvar_s; struct vulkan_ctx_s;; -void Vulkan_R_ClearParticles (struct vulkan_ctx_s *ctx); -void Vulkan_R_InitParticles (struct vulkan_ctx_s *ctx); +void Vulkan_ClearParticles (struct vulkan_ctx_s *ctx); +void Vulkan_InitParticles (struct vulkan_ctx_s *ctx); void Vulkan_r_easter_eggs_f (struct cvar_s *var, struct vulkan_ctx_s *ctx); void Vulkan_r_particles_style_f (struct cvar_s *var, struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); +void Vulkan_DrawParticles (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_particles_h diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index 11ae46ca8..b6f37142b 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -58,7 +58,6 @@ #define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT) static scrap_t *light_scrap; -static byte *light_data; static unsigned *blocklights; static int bl_extents[2]; @@ -201,10 +200,8 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) //FIXME RGB support if (!light_scrap) { light_scrap = GLSL_CreateScrap (2048, GL_LUMINANCE, 1); - light_data = malloc (BLOCK_SIZE * MAX_LIGHTMAPS); } else { GLSL_ScrapClear (light_scrap); - memset (light_data, 0, BLOCK_SIZE * MAX_LIGHTMAPS); } glsl_R_BuildLightMap = R_BuildLightMap_1; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 7aadd6692..5cb213b16 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -369,7 +369,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) create_quad_buffers (ctx); dctx->scrap = QFV_CreateScrap (device, 2048, tex_rgba); dctx->stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024, 4, - ctx->cmdpool); + ctx->cmdpool); dctx->sampler = QFV_GetSampler (ctx, "quakepic"); qpic_t *charspic = Draw_Font8x8Pic (); @@ -385,7 +385,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->layout = QFV_GetPipelineLayout (ctx, "twod"); - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (ctx->framebuffers.size, alloca); + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); for (size_t i = 0; i < layouts->size; i++) { layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "twod"); } diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 282bfaf8a..abb24924b 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -48,12 +48,12 @@ #include "vid_vulkan.h" void -Vulkan_R_ClearParticles (struct vulkan_ctx_s *ctx) +Vulkan_ClearParticles (struct vulkan_ctx_s *ctx) { } void -Vulkan_R_InitParticles (struct vulkan_ctx_s *ctx) +Vulkan_InitParticles (struct vulkan_ctx_s *ctx) { } @@ -241,7 +241,12 @@ Vulkan_r_easter_eggs_f (cvar_t *var, struct vulkan_ctx_s *ctx) void Vulkan_r_particles_style_f (cvar_t *var, struct vulkan_ctx_s *ctx) { - Vulkan_r_particles_style_f (var, ctx); + Vulkan_r_easter_eggs_f (var, ctx); +} + +void +Vulkan_DrawParticles (struct vulkan_ctx_s *ctx) +{ } void From 0622a24380d96359c71356cff09a30e4a89ee651 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 20 Jan 2021 01:24:32 +0900 Subject: [PATCH 1234/3664] [util] Support size_t constants Much like 1u and 1l, 1z is for size_t. --- libs/util/cexpr-lex.l | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index 9c9377beb..d34cd250a 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -71,6 +71,7 @@ FILE *cexpr_yyget_in (yyscan_t yyscanner) __attribute__((pure)); static exprval_t *parse_int (const char *str, exprctx_t *context); static exprval_t *parse_uint (const char *str, exprctx_t *context); +static exprval_t *parse_size_t (const char *str, exprctx_t *context); static exprval_t *parse_float (const char *str, exprctx_t *context); static exprval_t *parse_double (const char *str, exprctx_t *context); static exprsym_t *parse_name (const char *str, exprctx_t *context); @@ -127,6 +128,11 @@ STRING \"(\\.|[^"\\])*\" return VALUE; } +{INT}+[zZ] { + yylval->value = parse_size_t (yytext, context); + return VALUE; + } + {FLOAT} { yylval->value = parse_double (yytext, context); return VALUE; @@ -239,6 +245,13 @@ static exprval_t *parse_uint (const char *str, exprctx_t *context) return val; } +static exprval_t *parse_size_t (const char *str, exprctx_t *context) +{ + exprval_t *val = cexpr_value (&cexpr_size_t, context); + *(unsigned *) val->value = strtoumax (str, 0, 0); + return val; +} + static exprval_t *parse_float (const char *str, exprctx_t *context) { exprval_t *val = cexpr_value (&cexpr_float, context); From d33f5b8d0d6e693d17acce115b55c2c42882e4bd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 20 Jan 2021 01:25:54 +0900 Subject: [PATCH 1235/3664] [vulkan] Make a lot of progress for brush models Light maps are maybe updating, but as nothing is actually rendered yet, it's hard to tell. --- include/QF/Vulkan/qf_bsp.h | 134 ++ include/QF/Vulkan/qf_lightmap.h | 48 + include/QF/Vulkan/qf_main.h | 37 + include/QF/Vulkan/qf_model.h | 44 + include/QF/Vulkan/texture.h | 4 + include/r_local.h | 2 + include/vid_vulkan.h | 1 + libs/models/brush/vulkan_model_brush.c | 52 +- libs/video/renderer/Makemodule.am | 3 + libs/video/renderer/vid_render_vulkan.c | 28 +- libs/video/renderer/vulkan/qfpipeline.plist | 160 +++ libs/video/renderer/vulkan/quakebsp.frag | 9 +- libs/video/renderer/vulkan/quakebsp.vert | 5 +- libs/video/renderer/vulkan/texture.c | 6 + libs/video/renderer/vulkan/vulkan_bsp.c | 1286 ++++++++++++++++++ libs/video/renderer/vulkan/vulkan_draw.c | 3 +- libs/video/renderer/vulkan/vulkan_lightmap.c | 279 ++++ libs/video/renderer/vulkan/vulkan_main.c | 250 ++++ 18 files changed, 2329 insertions(+), 22 deletions(-) create mode 100644 include/QF/Vulkan/qf_bsp.h create mode 100644 include/QF/Vulkan/qf_lightmap.h create mode 100644 include/QF/Vulkan/qf_main.h create mode 100644 include/QF/Vulkan/qf_model.h create mode 100644 libs/video/renderer/vulkan/vulkan_bsp.c create mode 100644 libs/video/renderer/vulkan/vulkan_lightmap.c create mode 100644 libs/video/renderer/vulkan/vulkan_main.c diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h new file mode 100644 index 000000000..dec2fe085 --- /dev/null +++ b/include/QF/Vulkan/qf_bsp.h @@ -0,0 +1,134 @@ +/* + qf_bsp.h + + Vulkan specific brush model stuff + + Copyright (C) 2012 Bill Currie + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2012/1/7 + Date: 2021/1/18 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_bsp_h +#define __QF_Vulkan_qf_bsp_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/Vulkan/qf_vid.h" + +typedef struct bspvert_s { + quat_t vertex; + quat_t tlst; +} bspvert_t; + +typedef struct elements_s { + struct elements_s *_next; + struct elements_s *next; + byte *base; + struct dstring_s *list; +} elements_t; + +typedef struct elechain_s { + struct elechain_s *_next; + struct elechain_s *next; + int index; + elements_t *elements; + vec_t *transform; + float *color; +} elechain_t; + +typedef struct bspframe_s { + uint32_t *indeces; + VkCommandBuffer bsp_cmd; + VkCommandBuffer turb_cmd; + VkCommandBuffer sky_cmd; + VkDescriptorSet descriptors; +} bspframe_t; + +typedef struct bspframeset_s + DARRAY_TYPE (bspframe_t) bspframeset_t; + +typedef struct texchainset_s + DARRAY_TYPE (struct vulktex_s *) texchainset_t; + +typedef struct bspctx_s { + instsurf_t *waterchain; + instsurf_t **waterchain_tail; + instsurf_t *sky_chain; + instsurf_t **sky_chain_tail; + + texchainset_t texture_chains; + + // for world and non-instance models + instsurf_t *static_instsurfs; + instsurf_t **static_instsurfs_tail; + instsurf_t *free_static_instsurfs; + + // for instance models + elechain_t *elechains; + elechain_t **elechains_tail; + elechain_t *free_elechains; + elements_t *elementss; + elements_t **elementss_tail; + elements_t *free_elementss; + instsurf_t *instsurfs; + instsurf_t **instsurfs_tail; + instsurf_t *free_instsurfs; + + struct qfv_tex_s *skybox_tex; + quat_t sky_rotation[2]; + quat_t sky_velocity; + quat_t sky_fix; + double sky_time; + + quat_t default_color; + quat_t last_color; + + struct scrap_s *light_scrap; + struct qfv_stagebuf_s *light_stage; + + VkDeviceMemory texture_memory; + VkPipeline main; + VkPipelineLayout layout; + size_t vertex_buffer_size; + size_t index_buffer_size; + VkBuffer vertex_buffer; + VkDeviceMemory vertex_memory; + VkBuffer index_buffer; + VkDeviceMemory index_memory; + bspframeset_t frames; +} bspctx_t; + +struct vulkan_ctx_s; +void Vulkan_ClearElements (struct vulkan_ctx_s *ctx); +void Vulkan_DrawWorld (struct vulkan_ctx_s *ctx); +void Vulkan_DrawSky (struct vulkan_ctx_s *ctx); +void Vulkan_RegisterTextures (model_t **models, int num_models, + struct vulkan_ctx_s *ctx); +void Vulkan_BuildDisplayLists (model_t **models, int num_models, + struct vulkan_ctx_s *ctx); +void Vulkan_Bsp_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx); +void Vulkan_DrawWaterSurfaces (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_bsp_h diff --git a/include/QF/Vulkan/qf_lightmap.h b/include/QF/Vulkan/qf_lightmap.h new file mode 100644 index 000000000..649a5b139 --- /dev/null +++ b/include/QF/Vulkan/qf_lightmap.h @@ -0,0 +1,48 @@ +/* + qf_lightmap.h + + Vulkan lightmap stuff from the renderer. + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_Vulkan_qf_lightmap_h +#define __QF_Vulkan_qf_lightmap_h + +#define MAX_LIGHTMAPS 1024 +#define BLOCK_WIDTH 64 +#define BLOCK_HEIGHT 64 + +#include "QF/Vulkan/qf_vid.h" + +struct vulkan_ctx_s; +struct model_s; +struct msurface_s; + +void Vulkan_lightmap_init (struct vulkan_ctx_s *ctx); +void Vulkan_BuildLightmaps (struct model_s **models, int num_models, struct vulkan_ctx_s *ctx); +void Vulkan_CalcLightmaps (struct vulkan_ctx_s *ctx); +void Vulkan_BuildLightMap (struct msurface_s *surf, struct vulkan_ctx_s *ctx); +VkImageView Vulkan_LightmapImageView (struct vulkan_ctx_s *ctx) __attribute__((pure)); +void Vulkan_FlushLightmaps (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_lightmap_h diff --git a/include/QF/Vulkan/qf_main.h b/include/QF/Vulkan/qf_main.h new file mode 100644 index 000000000..4b487da5e --- /dev/null +++ b/include/QF/Vulkan/qf_main.h @@ -0,0 +1,37 @@ +/* + qf_main.h + + Vulkan main stuff from the renderer. + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_Vulkan_qf_main_h +#define __QF_Vulkan_qf_main_h + +struct vulkan_ctx_s; + +void Vulkan_NewMap (model_t *worldmodel, struct model_s **models, + int num_models, struct vulkan_ctx_s *ctx); +void Vulkan_RenderView (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_main_h diff --git a/include/QF/Vulkan/qf_model.h b/include/QF/Vulkan/qf_model.h new file mode 100644 index 000000000..3a42e131d --- /dev/null +++ b/include/QF/Vulkan/qf_model.h @@ -0,0 +1,44 @@ +/* + qf_model.h + + Vulkan specific model stuff + + Copyright (C) 2012 Bill Currie + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2012/1/7 + Date: 2021/1/19 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_model_h +#define __QF_Vulkan_qf_model_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/Vulkan/qf_vid.h" + +typedef struct modelctx_s { + struct vulkan_ctx_s *ctx; + VkDeviceMemory texture_memory; +} modelctx_t; + +#endif//__QF_Vulkan_qf_model_h diff --git a/include/QF/Vulkan/texture.h b/include/QF/Vulkan/texture.h index 39f5b07f2..35aaf5bb5 100644 --- a/include/QF/Vulkan/texture.h +++ b/include/QF/Vulkan/texture.h @@ -5,8 +5,12 @@ typedef struct scrap_s scrap_t; +struct qfv_stagebuf_s; +struct qfv_device_s; + scrap_t *QFV_CreateScrap (struct qfv_device_s *device, int size, QFFormat format); +size_t QFV_ScrapSize (scrap_t *scrap); void QFV_ScrapClear (scrap_t *scrap); void QFV_DestroyScrap (scrap_t *scrap); VkImageView QFV_ScrapImageView (scrap_t *scrap) __attribute__((pure)); diff --git a/include/r_local.h b/include/r_local.h index ebf1a9dd6..4a3645ded 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -180,6 +180,7 @@ void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist); void R_StepActiveU (edge_t *pedge); void R_RemoveEdges (edge_t *pedge); void R_AddTexture (texture_t *tex); +struct vulkan_ctx_s; void R_ClearTextures (void); void R_InitSurfaceChains (model_t *model); @@ -313,6 +314,7 @@ void R_MarkLights (const vec3_t lightorigin, struct dlight_s *light, int bit, model_t *model); void R_LoadSkys (const char *); +//void Vulkan_R_LoadSkys (const char *, struct vulkan_ctx_s *ctx); void R_LowFPPrecision (void); void R_HighFPPrecision (void); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 90d4908f2..92208425e 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -63,6 +63,7 @@ typedef struct vulkan_ctx_s { struct hashtab_s *descriptorPools; struct hashtab_s *samplers; + struct bspctx_s *bsp_context; struct drawctx_s *draw_context; VkCommandPool cmdpool; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index fe5fbfce5..52826d280 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -217,11 +217,57 @@ Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) void Vulkan_Mod_LoadLighting (bsp_t *bsp, vulkan_ctx_t *ctx) { - mod_lightmap_bytes = 1; + mod_lightmap_bytes = 3; if (!bsp->lightdatasize) { loadmodel->lightdata = NULL; return; } - loadmodel->lightdata = Hunk_AllocName (bsp->lightdatasize, loadname); - memcpy (loadmodel->lightdata, bsp->lightdata, bsp->lightdatasize); + + byte d; + byte *in, *out, *data; + size_t i; + int ver; + QFile *lit_file; + + loadmodel->lightdata = 0; + if (mod_lightmap_bytes > 1) { + // LordHavoc: check for a .lit file to load + dstring_t *litfilename = dstring_new (); + dstring_copystr (litfilename, loadmodel->name); + QFS_StripExtension (litfilename->str, litfilename->str); + dstring_appendstr (litfilename, ".lit"); + lit_file = QFS_VOpenFile (litfilename->str, 0, loadmodel->vpath); + data = (byte *) QFS_LoadHunkFile (lit_file); + if (data) { + if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' + && data[3] == 'T') { + ver = LittleLong (((int32_t *) data)[1]); + if (ver == 1) { + Sys_MaskPrintf (SYS_DEV, "%s loaded", litfilename->str); + loadmodel->lightdata = data + 8; + } else { + Sys_MaskPrintf (SYS_DEV, + "Unknown .lit file version (%d)\n", ver); + } + } else { + Sys_MaskPrintf (SYS_DEV, "Corrupt .lit file (old version?)\n"); + } + } + dstring_delete (litfilename); + } + if (loadmodel->lightdata || !bsp->lightdatasize) { + return; + } + // LordHavoc: oh well, expand the white lighting data + loadmodel->lightdata = Hunk_AllocName (bsp->lightdatasize * 3, + loadmodel->name); + in = bsp->lightdata; + out = loadmodel->lightdata; + + for (i = 0; i < bsp->lightdatasize ; i++) { + d = *in++; + *out++ = d; + *out++ = d; + *out++ = d; + } } diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index b149d528c..a200747ff 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -236,7 +236,10 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/util.c \ libs/video/renderer/vulkan/util.h \ libs/video/renderer/vulkan/vkparse.c \ + libs/video/renderer/vulkan/vulkan_bsp.c \ libs/video/renderer/vulkan/vulkan_draw.c \ + libs/video/renderer/vulkan/vulkan_lightmap.c \ + libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ libs/video/renderer/vulkan/vulkan_particles.c \ libs/video/renderer/vulkan/vulkan_texture.c \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 4d2744089..e6f993b38 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -39,7 +39,10 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_draw.h" +#include "QF/Vulkan/qf_lightmap.h" +#include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" @@ -92,6 +95,7 @@ vulkan_R_Init (void) // FIXME this should be staged so screen updates can begin while pipelines // are being built vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); + Vulkan_Bsp_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); Vulkan_Particles_Init (vulkan_ctx); @@ -116,12 +120,6 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) VkDevice dev = device->dev; qfv_queue_t *queue = &vulkan_ctx->device->queue; - scr_3dfunc (); - while (*scr_funcs) { - (*scr_funcs) (); - scr_funcs++; - } - __auto_type framebuffer = &vulkan_ctx->framebuffers.a[vulkan_ctx->curFrame]; @@ -145,6 +143,12 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) attachments, sc->extent, 1); + scr_3dfunc (); + while (*scr_funcs) { + (*scr_funcs) (); + scr_funcs++; + } + Vulkan_FlushText (vulkan_ctx); VkCommandBufferBeginInfo beginInfo @@ -168,6 +172,8 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) dfunc->vkCmdExecuteCommands (framebuffer->cmdBuffer, framebuffer->subCommand->size, framebuffer->subCommand->a); + // reset for next time around + framebuffer->subCommand->size = 0; dfunc->vkCmdEndRenderPass (framebuffer->cmdBuffer); dfunc->vkEndCommandBuffer (framebuffer->cmdBuffer); @@ -208,6 +214,9 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) static void vulkan_R_ClearState (void) { + R_ClearEfrags (); + R_ClearDlights (); + Vulkan_ClearParticles (vulkan_ctx); } static void @@ -218,6 +227,7 @@ vulkan_R_LoadSkys (const char *skyname) static void vulkan_R_NewMap (model_t *worldmodel, model_t **models, int num_models) { + Vulkan_NewMap (worldmodel, models, num_models, vulkan_ctx); } static void @@ -228,6 +238,7 @@ vulkan_R_LineGraph (int x, int y, int *h_vals, int count) static void vulkan_R_RenderView (void) { + Vulkan_RenderView (vulkan_ctx); } static void @@ -359,13 +370,13 @@ vulkan_R_ViewChanged (float aspect) static void vulkan_R_ClearParticles (void) { - Vulkan_R_ClearParticles (vulkan_ctx); + Vulkan_ClearParticles (vulkan_ctx); } static void vulkan_R_InitParticles (void) { - Vulkan_R_InitParticles (vulkan_ctx); + Vulkan_InitParticles (vulkan_ctx); } static void @@ -593,6 +604,7 @@ vulkan_vid_render_shutdown (void) df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); Vulkan_Draw_Shutdown (vulkan_ctx); + Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Shutdown_Common (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 4bc6017e9..822e187a5 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -9,6 +9,8 @@ pushcolor = $builtin/pushcolor.frag; twodv = $builtin/twod.vert; twodf = $builtin/twod.frag; + quakebspv = $builtin/quakebsp.vert; + quakebspf = $builtin/quakebsp.frag; }; samplers = { quakepic = { @@ -44,6 +46,20 @@ }, ); }; + quakebsp = { + flags = 0; + maxSets = $framebuffers.size; + bindings = ( + { + type = uniform_buffer; + descriptorCount = $framebuffers.size; + }, + { + type = combined_image_sampler; + descriptorCount = "5z * $framebuffers.size"; + }, + ); + }; }; setLayouts = { twod = { @@ -62,6 +78,46 @@ }, ); }; + quakebsp = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + binding = 1; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 3; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 4; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 5; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; something = { flags = 0; bindings = ( @@ -84,6 +140,21 @@ twod = { setLayouts = (twod); }; + quakebsp = { + setLayouts = (quakebsp); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4"; + }, + { + stageFlags = fragment; + offset = 0; + size = 32; + }, + ); + }; something = { setLayouts = (something); pushConstantRanges = ( @@ -96,6 +167,95 @@ }; }; pipelines = { + quakebsp.main = { + stages = ( + { stage = vertex; name = main; module = quakebspv; }, + { stage = fragment; name = main; module = quakebspf; }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "3 * 4 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + { + location = 1; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 8; + }, + ); + }; + inputAssembly = { + topology = triangle_fan; + primitiveRestartEnable = true; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + depthStencil = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ({ + blendEnable = true; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }); + }; + dynamic = { + dynamicState = ( viewport, scissor, blend_constants ); + }; + layout = quakebsp; + //renderPass = renderpass; + }; twod = { stages = ( { stage = vertex; name = main; module = twodv; }, diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag index 151243249..219ce9212 100644 --- a/libs/video/renderer/vulkan/quakebsp.frag +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -3,8 +3,8 @@ layout (set = 0, binding = 1) uniform sampler2D Texture; layout (set = 0, binding = 2) uniform sampler2D Glowmap; layout (set = 0, binding = 3) uniform sampler2D Lightmap; -layout (set = 0, binding = 4) uniform samplerCube SkyCube; -layout (set = 0, binding = 5) uniform sampler2DArray SkySheet; +layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; +layout (set = 0, binding = 5) uniform samplerCube SkyCube; layout (push_constant) uniform PushConstants { float time; @@ -12,8 +12,7 @@ layout (push_constant) uniform PushConstants { }; layout (location = 0) in vec4 tl_st; -layout (location = 1) in vec4 color; -layout (location = 2) out vec3 direction; +layout (location = 1) in vec3 direction; layout (location = 0) out vec4 frag_color; @@ -111,7 +110,7 @@ main (void) if (doSkyCube || doSkySheet) { c = sky_color (direction, time); } else { - c = texture (Texture, t_st) * color; + c = texture (Texture, t_st); } if (doLight) { c *= texture (Lightmap, l_st); diff --git a/libs/video/renderer/vulkan/quakebsp.vert b/libs/video/renderer/vulkan/quakebsp.vert index 11ae0c90a..bb9e87e4a 100644 --- a/libs/video/renderer/vulkan/quakebsp.vert +++ b/libs/video/renderer/vulkan/quakebsp.vert @@ -12,11 +12,9 @@ layout (push_constant) uniform PushConstants { layout (location = 0) in vec4 vertex; layout (location = 1) in vec4 tl_uv; -layout (location = 2) in vec4 vcolor; layout (location = 0) out vec4 tl_st; -layout (location = 1) out vec4 color; -layout (location = 2) out vec3 direction; +layout (location = 1) out vec3 direction; void main (void) @@ -24,5 +22,4 @@ main (void) gl_Position = Projection * (View * (Model * vertex)); direction = (Sky * vertex).xyz; tl_st = tl_uv; - color = vcolor; } diff --git a/libs/video/renderer/vulkan/texture.c b/libs/video/renderer/vulkan/texture.c index d926632a7..112c71a92 100644 --- a/libs/video/renderer/vulkan/texture.c +++ b/libs/video/renderer/vulkan/texture.c @@ -135,6 +135,12 @@ QFV_CreateScrap (qfv_device_t *device, int size, QFFormat format) return scrap; } +size_t +QFV_ScrapSize (scrap_t *scrap) +{ + return scrap->rscrap.width * scrap->rscrap.height * scrap->bpp; +} + void QFV_ScrapClear (scrap_t *scrap) { diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c new file mode 100644 index 000000000..466d6bbd7 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -0,0 +1,1286 @@ +/* + vulkan_bsp.c + + Vulkan bsp + + Copyright (C) 2012 Bill Currie + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2012/1/7 + Date: 2021/1/18 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define NH_DEFINE +//#include "namehack.h" + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "qfalloca.h" + +#include "QF/cvar.h" +#include "QF/darray.h" +#include "QF/dstring.h" +#include "QF/image.h" +#include "QF/render.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vrect.h" + +#include "QF/Vulkan/qf_bsp.h" +#include "QF/Vulkan/qf_lightmap.h" +#include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/staging.h" +#include "QF/Vulkan/texture.h" + +#include "r_internal.h" +#include "vid_vulkan.h" +#include "vkparse.h" + +#define ALLOC_CHUNK 64 + +typedef struct { + uint32_t count; + uint32_t indices[1]; +} glslpoly_t; + +#define CHAIN_SURF_F2B(surf,chain) \ + do { \ + instsurf_t *inst = (surf)->instsurf; \ + if (__builtin_expect(!inst, 1)) \ + (surf)->tinst = inst = get_instsurf (bctx); \ + inst->surface = (surf); \ + *(chain##_tail) = inst; \ + (chain##_tail) = &inst->tex_chain; \ + *(chain##_tail) = 0; \ + } while (0) + +#define CHAIN_SURF_B2F(surf,chain) \ + do { \ + instsurf_t *inst = (surf)->instsurf; \ + if (__builtin_expect(!inst, 1)) \ + (surf)->tinst = inst = get_instsurf (bctx); \ + inst->surface = (surf); \ + inst->tex_chain = (chain); \ + (chain) = inst; \ + } while (0) + +#define GET_RELEASE(type,name) \ +static inline type * \ +get_##name (bspctx_t *bctx) \ +{ \ + type *ele; \ + if (!bctx->free_##name##s) { \ + int i; \ + bctx->free_##name##s = calloc (ALLOC_CHUNK, sizeof (type)); \ + for (i = 0; i < ALLOC_CHUNK - 1; i++) \ + bctx->free_##name##s[i]._next = &bctx->free_##name##s[i + 1]; \ + } \ + ele = bctx->free_##name##s; \ + bctx->free_##name##s = ele->_next; \ + ele->_next = 0; \ + *bctx->name##s_tail = ele; \ + bctx->name##s_tail = &ele->_next; \ + return ele; \ +} \ +static inline void \ +release_##name##s (bspctx_t *bctx) \ +{ \ + if (bctx->name##s) { \ + *bctx->name##s_tail = bctx->free_##name##s; \ + bctx->free_##name##s = bctx->name##s; \ + bctx->name##s = 0; \ + bctx->name##s_tail = &bctx->name##s; \ + } \ +} + +GET_RELEASE (elechain_t, elechain) +GET_RELEASE (elements_t, elements) +GET_RELEASE (instsurf_t, static_instsurf) +GET_RELEASE (instsurf_t, instsurf) + +static void +add_texture (texture_t *tx, vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + + vulktex_t *tex = tx->render; + DARRAY_APPEND (&bctx->texture_chains, tex); + tex->tex_chain = 0; + tex->tex_chain_tail = &tex->tex_chain; + tex->elechain = 0; + tex->elechain_tail = &tex->elechain; +} + +static void +init_surface_chains (model_t *model, vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + int i; + + release_static_instsurfs (bctx); + release_instsurfs (bctx); + + for (i = 0; i < model->nummodelsurfaces; i++) { + model->surfaces[i].instsurf = get_static_instsurf (bctx); + model->surfaces[i].instsurf->surface = &model->surfaces[i]; + } +} + +static inline void +clear_tex_chain (vulktex_t *tex) +{ + tex->tex_chain = 0; + tex->tex_chain_tail = &tex->tex_chain; + tex->elechain = 0; + tex->elechain_tail = &tex->elechain; +} + +static void +clear_texture_chains (bspctx_t *bctx) +{ + for (size_t i = 0; i < bctx->texture_chains.size; i++) { + if (!bctx->texture_chains.a[i]) + continue; + clear_tex_chain (bctx->texture_chains.a[i]); + } + clear_tex_chain (r_notexture_mip->render); + release_elechains (bctx); + release_elementss (bctx); + release_instsurfs (bctx); +} + +void +Vulkan_ClearElements (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + release_elechains (bctx); + release_elementss (bctx); +} + +static void +update_lightmap (msurface_t *surf, vulkan_ctx_t *ctx) +{ + int maps; + + for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) + if (d_lightstylevalue[surf->styles[maps]] != surf->cached_light[maps]) + goto dynamic; + + if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { +dynamic: + if (r_dynamic->int_val) + Vulkan_BuildLightMap (surf, ctx); + } +} + +static inline void +chain_surface (msurface_t *surf, vec_t *transform, float *color, + vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + instsurf_t *is; + + if (surf->flags & SURF_DRAWSKY) { + CHAIN_SURF_F2B (surf, bctx->sky_chain); + } else if ((surf->flags & SURF_DRAWTURB) || (color && color[3] < 1.0)) { + CHAIN_SURF_B2F (surf, bctx->waterchain); + } else { + texture_t *tx; + vulktex_t *tex; + + if (!surf->texinfo->texture->anim_total) + tx = surf->texinfo->texture; + else + tx = R_TextureAnimation (surf); + tex = tx->render; + CHAIN_SURF_F2B (surf, tex->tex_chain); + + update_lightmap (surf, ctx); + } + if (!(is = surf->instsurf)) + is = surf->tinst; + is->transform = transform; + is->color = color; +} + +static void +register_textures (model_t *model, vulkan_ctx_t *ctx) +{ + int i; + texture_t *tex; + + for (i = 0; i < model->numtextures; i++) { + tex = model->textures[i]; + if (!tex) + continue; + add_texture (tex, ctx); + } +} + +static void +clear_textures (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + bctx->texture_chains.size = 0; +} + +void +Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) +{ + int i; + model_t *m; + + clear_textures (ctx); + init_surface_chains (r_worldentity.model, ctx); + add_texture (r_notexture_mip, ctx); + register_textures (r_worldentity.model, ctx); + for (i = 0; i < num_models; i++) { + m = models[i]; + if (!m) + continue; + // sub-models are done as part of the main model + if (*m->name == '*') + continue; + // world has already been done, not interested in non-brush models + if (m == r_worldentity.model || m->type != mod_brush) + continue; + m->numsubmodels = 1; // no support for submodels in non-world model + register_textures (m, ctx); + } +} + +static elechain_t * +add_elechain (vulktex_t *tex, int ec_index, bspctx_t *bctx) +{ + elechain_t *ec; + + ec = get_elechain (bctx); + ec->elements = get_elements (bctx); + ec->index = ec_index; + ec->transform = 0; + ec->color = 0; + *tex->elechain_tail = ec; + tex->elechain_tail = &ec->next; + return ec; +} + +static void +build_surf_displist (model_t **models, msurface_t *fa, int base, + dstring_t *vert_list) +{ + int numverts; + int numtris; + int numindices; + int i; + vec_t *vec; + mvertex_t *vertices; + medge_t *edges; + int *surfedges; + int index; + bspvert_t *verts; + glslpoly_t *poly; + uint32_t *ind; + float s, t; + + if (fa->ec_index < 0) { + vertices = models[-fa->ec_index - 1]->vertexes; + edges = models[-fa->ec_index - 1]->edges; + surfedges = models[-fa->ec_index - 1]->surfedges; + } else { + vertices = r_worldentity.model->vertexes; + edges = r_worldentity.model->edges; + surfedges = r_worldentity.model->surfedges; + } + numverts = fa->numedges; + numtris = numverts - 2; + numindices = numtris * 3; + verts = alloca (numverts * sizeof (bspvert_t)); + poly = malloc (field_offset (glslpoly_t, indices[numindices])); + poly->count = numindices; + for (i = 0, ind = poly->indices; i < numtris; i++) { + *ind++ = base; + *ind++ = base + i + 1; + *ind++ = base + i + 2; + } + fa->polys = (glpoly_t *) poly; + + for (i = 0; i < numverts; i++) { + index = surfedges[fa->firstedge + i]; + if (index > 0) + vec = vertices[edges[index].v[0]].position; + else + vec = vertices[edges[-index].v[1]].position; + + s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; + t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; + VectorCopy (vec, verts[i].vertex); + verts[i].vertex[3] = 1; + verts[i].tlst[0] = s / fa->texinfo->texture->width; + verts[i].tlst[1] = t / fa->texinfo->texture->height; + + //lightmap texture coordinates + if (!fa->lightpic) { + // sky and water textures don't have lightmaps + verts[i].tlst[2] = 0; + verts[i].tlst[3] = 0; + continue; + } + s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; + t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; + s -= fa->texturemins[0]; + t -= fa->texturemins[1]; + s += fa->lightpic->rect->x * 16 + 8; + t += fa->lightpic->rect->y * 16 + 8; + s /= 16; + t /= 16; + verts[i].tlst[2] = s * fa->lightpic->size; + verts[i].tlst[3] = t * fa->lightpic->size; + } + dstring_append (vert_list, (char *) verts, numverts * sizeof (bspvert_t)); +} + +void +Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + int i, j; + int vertex_index_base; + model_t *m; + dmodel_t *dm; + msurface_t *surf; + dstring_t *vertices; + + QuatSet (0, 0, sqrt(0.5), sqrt(0.5), bctx->sky_fix); // proper skies + QuatSet (0, 0, 0, 1, bctx->sky_rotation[0]); + QuatCopy (bctx->sky_rotation[0], bctx->sky_rotation[1]); + QuatSet (0, 0, 0, 0, bctx->sky_velocity); + QuatExp (bctx->sky_velocity, bctx->sky_velocity); + bctx->sky_time = vr_data.realtime; + + // now run through all surfaces, chaining them to their textures, thus + // effectively sorting the surfaces by texture (without worrying about + // surface order on the same texture chain). + for (i = 0; i < num_models; i++) { + m = models[i]; + if (!m) + continue; + // sub-models are done as part of the main model + if (*m->name == '*') + continue; + // non-bsp models don't have surfaces. + dm = m->submodels; + for (j = 0; j < m->numsurfaces; j++) { + vulktex_t *tex; + if (j == dm->firstface + dm->numfaces) { + dm++; + if (dm - m->submodels == m->numsubmodels) { + // limit the surfaces + // probably never hit + Sys_Printf ("R_BuildDisplayLists: too many surfaces\n"); + m->numsurfaces = j; + break; + } + } + surf = m->surfaces + j; + surf->ec_index = dm - m->submodels; + if (!surf->ec_index && m != r_worldentity.model) + surf->ec_index = -1 - i; // instanced model + tex = surf->texinfo->texture->render; + CHAIN_SURF_F2B (surf, tex->tex_chain); + } + } + // All vertices from all brush models go into one giant vbo. + vertices = dstring_new (); + vertex_index_base = 0; + // All usable surfaces have been chained to the (base) texture they use. + // Run through the textures, using their chains to build display maps. + // For animated textures, if a surface is on one texture of the group, it + // will be on all. + for (size_t i = 0; i < bctx->texture_chains.size; i++) { + vulktex_t *tex; + instsurf_t *is; + elechain_t *ec = 0; + elements_t *el = 0; + + tex = bctx->texture_chains.a[i]; + + for (is = tex->tex_chain; is; is = is->tex_chain) { + msurface_t *surf = is->surface; + if (!tex->elechain) { + ec = add_elechain (tex, surf->ec_index, bctx); + el = ec->elements; + el->base = (byte *) (intptr_t) vertices->size; + vertex_index_base = 0; + } + if (surf->ec_index != ec->index) { // next sub-model + ec = add_elechain (tex, surf->ec_index, bctx); + el = ec->elements; + el->base = (byte *) (intptr_t) vertices->size; + vertex_index_base = 0; + } + if (vertex_index_base + surf->numedges > 65535) { + // elements index overflow + el->next = get_elements (bctx); + el = el->next; + el->base = (byte *) (intptr_t) vertices->size; + vertex_index_base = 0; + } + // we don't use it now, but pre-initializing the list won't hurt + if (!el->list) + el->list = dstring_new (); + dstring_clear (el->list); + + surf->base = el->base; + build_surf_displist (models, surf, vertex_index_base, vertices); + vertex_index_base += surf->numedges; + } + } + clear_texture_chains (bctx); + Sys_MaskPrintf (SYS_GLSL, "R_BuildDisplayLists: %ld verts total\n", + (long) (vertices->size / sizeof (bspvert_t))); + /*XXX if (!bsp_vbo) + qfeglGenBuffers (1, &bsp_vbo); + qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo); + qfeglBufferData (GL_ARRAY_BUFFER, vertices->size, vertices->str, + GL_STATIC_DRAW); + qfeglBindBuffer (GL_ARRAY_BUFFER, 0);*/ + dstring_delete (vertices); +} + +static void +R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) +{ + float dot, radius; + int i; + unsigned k; + model_t *model; + plane_t *plane; + msurface_t *surf; + qboolean rotated; + vec3_t mins, maxs, org; + + model = e->model; + if (e->transform[0] != 1 || e->transform[5] != 1 || e->transform[10] != 1) { + rotated = true; + radius = model->radius; + if (R_CullSphere (e->origin, radius)) + return; + } else { + rotated = false; + VectorAdd (e->origin, model->mins, mins); + VectorAdd (e->origin, model->maxs, maxs); + if (R_CullBox (mins, maxs)) + return; + } + + VectorSubtract (r_refdef.vieworg, e->origin, org); + if (rotated) { + vec3_t temp; + + VectorCopy (org, temp); + org[0] = DotProduct (temp, e->transform + 0); + org[1] = DotProduct (temp, e->transform + 4); + org[2] = DotProduct (temp, e->transform + 8); + } + + // calculate dynamic lighting for bmodel if it's not an instanced model + if (model->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { + vec3_t lightorigin; + + for (k = 0; k < r_maxdlights; k++) { + if ((r_dlights[k].die < vr_data.realtime) + || (!r_dlights[k].radius)) + continue; + + VectorSubtract (r_dlights[k].origin, e->origin, lightorigin); + R_RecursiveMarkLights (lightorigin, &r_dlights[k], k, + model->nodes + model->hulls[0].firstclipnode); + } + } + + surf = &model->surfaces[model->firstmodelsurface]; + + for (i = 0; i < model->nummodelsurfaces; i++, surf++) { + // find the node side on which we are + plane = surf->plane; + + dot = PlaneDiff (org, plane); + + // enqueue the polygon + if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) + || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { + chain_surface (surf, e->transform, e->colormod, ctx); + } + } +} + +static inline void +visit_leaf (mleaf_t *leaf) +{ + // deal with model fragments in this leaf + if (leaf->efrags) + R_StoreEfrags (leaf->efrags); +} + +static inline int +get_side (mnode_t *node) +{ + // find the node side on which we are + plane_t *plane = node->plane; + + if (plane->type < 3) + return (r_origin[plane->type] - plane->dist) < 0; + return (DotProduct (r_origin, plane->normal) - plane->dist) < 0; +} + +static inline void +visit_node (mnode_t *node, int side, vulkan_ctx_t *ctx) +{ + int c; + msurface_t *surf; + + // sneaky hack for side = side ? SURF_PLANEBACK : 0; + side = (~side + 1) & SURF_PLANEBACK; + // draw stuff + if ((c = node->numsurfaces)) { + surf = r_worldentity.model->surfaces + node->firstsurface; + for (; c; c--, surf++) { + if (surf->visframe != r_visframecount) + continue; + + // side is either 0 or SURF_PLANEBACK + if (side ^ (surf->flags & SURF_PLANEBACK)) + continue; // wrong side + + chain_surface (surf, 0, 0, ctx); + } + } +} + +static inline int +test_node (mnode_t *node) +{ + if (node->contents < 0) + return 0; + if (node->visframe != r_visframecount) + return 0; + if (R_CullBox (node->minmaxs, node->minmaxs + 3)) + return 0; + return 1; +} + +static void +R_VisitWorldNodes (model_t *model, vulkan_ctx_t *ctx) +{ + typedef struct { + mnode_t *node; + int side; + } rstack_t; + rstack_t *node_ptr; + rstack_t *node_stack; + mnode_t *node; + mnode_t *front; + int side; + + node = model->nodes; + // +2 for paranoia + node_stack = alloca ((model->depth + 2) * sizeof (rstack_t)); + node_ptr = node_stack; + + while (1) { + while (test_node (node)) { + side = get_side (node); + front = node->children[side]; + if (test_node (front)) { + node_ptr->node = node; + node_ptr->side = side; + node_ptr++; + node = front; + continue; + } + if (front->contents < 0 && front->contents != CONTENTS_SOLID) + visit_leaf ((mleaf_t *) front); + visit_node (node, side, ctx); + node = node->children[!side]; + } + if (node->contents < 0 && node->contents != CONTENTS_SOLID) + visit_leaf ((mleaf_t *) node); + if (node_ptr != node_stack) { + node_ptr--; + node = node_ptr->node; + side = node_ptr->side; + visit_node (node, side, ctx); + node = node->children[!side]; + continue; + } + break; + } + if (node->contents < 0 && node->contents != CONTENTS_SOLID) + visit_leaf ((mleaf_t *) node); +} + +/*static void +draw_elechain (elechain_t *ec, int matloc, int vertloc, int tlstloc, + int colloc, bspctx_t *bctx) +{ + mat4_t mat; + elements_t *el; + int count; + float *color; + + if (colloc >= 0) { + color = ec->color; + if (!color) + color = bctx->default_color; + if (!QuatCompare (color, bctx->last_color)) { + QuatCopy (color, bctx->last_color); + qfeglVertexAttrib4fv (quake_bsp.color.location, color); + } + } + if (ec->transform) { + Mat4Mult (bsp_vp, ec->transform, mat); + qfeglUniformMatrix4fv (matloc, 1, false, mat); + } else { + qfeglUniformMatrix4fv (matloc, 1, false, bsp_vp); + } + for (el = ec->elements; el; el = el->next) { + if (!el->list->size) + continue; + count = el->list->size / sizeof (GLushort); + qfeglVertexAttribPointer (vertloc, 4, GL_FLOAT, + 0, sizeof (bspvert_t), + el->base + field_offset (bspvert_t, vertex)); + if (tlstloc >= 0) + qfeglVertexAttribPointer (tlstloc, 4, GL_FLOAT, + 0, sizeof (bspvert_t), + el->base + field_offset (bspvert_t,tlst)); + qfeglDrawElements (GL_TRIANGLES, count, + GL_UNSIGNED_SHORT, el->list->str); + dstring_clear (el->list); + } +}*/ + +static void +bsp_begin (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; + //XXX quat_t fog; + + bctx->default_color[3] = 1; + QuatCopy (bctx->default_color, bctx->last_color); + + __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; + DARRAY_APPEND (cframe->subCommand, bframe->bsp_cmd); + + dfunc->vkResetCommandBuffer (bframe->bsp_cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + ctx->renderpass.renderpass, 0, + cframe->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (bframe->bsp_cmd, &beginInfo); + + //XXX glsl_Fog_GetColor (fog); + //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; +} + +static void +bsp_end (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; + + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; + dfunc->vkEndCommandBuffer (bframe->bsp_cmd); +} + +/*static void +turb_begin (bspctx_t *bctx) +{ + quat_t fog; + + bctx->default_color[3] = bound (0, r_wateralpha->value, 1); + QuatCopy (bctx->default_color, bctx->last_color); + qfeglVertexAttrib4fv (quake_bsp.color.location, default_color); + + Mat4Mult (glsl_projection, glsl_view, bsp_vp); + + qfeglUseProgram (quake_turb.program); + qfeglEnableVertexAttribArray (quake_turb.vertex.location); + qfeglEnableVertexAttribArray (quake_turb.tlst.location); + qfeglDisableVertexAttribArray (quake_turb.color.location); + + qfeglVertexAttrib4fv (quake_turb.color.location, default_color); + + glsl_Fog_GetColor (fog); + fog[3] = glsl_Fog_GetDensity () / 64.0; + qfeglUniform4fv (quake_turb.fog.location, 1, fog); + + qfeglUniform1i (quake_turb.palette.location, 1); + qfeglActiveTexture (GL_TEXTURE0 + 1); + qfeglEnable (GL_TEXTURE_2D); + qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); + + qfeglUniform1f (quake_turb.time.location, vr_data.realtime); + + qfeglUniform1i (quake_turb.texture.location, 0); + qfeglActiveTexture (GL_TEXTURE0 + 0); + qfeglEnable (GL_TEXTURE_2D); + + qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo); +}*/ + +/*static void +turb_end (bspctx_t *bctx) +{ + qfeglDisableVertexAttribArray (quake_turb.vertex.location); + qfeglDisableVertexAttribArray (quake_turb.tlst.location); + + qfeglActiveTexture (GL_TEXTURE0 + 0); + qfeglDisable (GL_TEXTURE_2D); + qfeglActiveTexture (GL_TEXTURE0 + 1); + qfeglDisable (GL_TEXTURE_2D); + + qfeglBindBuffer (GL_ARRAY_BUFFER, 0); +}*/ + +/*XXX static void +spin (mat4_t mat, bspctx_t *bctx) +{ + quat_t q; + mat4_t m; + float blend; + + while (vr_data.realtime - bctx->sky_time > 1) { + QuatCopy (bctx->sky_rotation[1], bctx->sky_rotation[0]); + QuatMult (bctx->sky_velocity, bctx->sky_rotation[0], + bctx->sky_rotation[1]); + bctx->sky_time += 1; + } + blend = bound (0, (vr_data.realtime - bctx->sky_time), 1); + + QuatBlend (bctx->sky_rotation[0], bctx->sky_rotation[1], blend, q); + QuatMult (bctx->sky_fix, q, q); + Mat4Identity (mat); + VectorNegate (r_origin, mat + 12); + QuatToMatrix (q, m, 1, 1); + Mat4Mult (m, mat, mat); +}*/ + +static void +sky_begin (bspctx_t *bctx) +{ + //XXX mat4_t mat; + //XXX quat_t fog; + + bctx->default_color[3] = 1; + QuatCopy (bctx->default_color, bctx->last_color); +/* qfeglVertexAttrib4fv (quake_bsp.color.location, bctx->default_color); + + Mat4Mult (glsl_projection, glsl_view, bsp_vp); + + if (bctx->skybox_tex) { + sky_params.mvp_matrix = &quake_skybox.mvp_matrix; + sky_params.vertex = &quake_skybox.vertex; + sky_params.sky_matrix = &quake_skybox.sky_matrix; + sky_params.fog = &quake_skybox.fog; + + qfeglUseProgram (quake_skybox.program); + qfeglEnableVertexAttribArray (quake_skybox.vertex.location); + + qfeglUniform1i (quake_skybox.sky.location, 0); + qfeglActiveTexture (GL_TEXTURE0 + 0); + qfeglEnable (GL_TEXTURE_CUBE_MAP); + qfeglBindTexture (GL_TEXTURE_CUBE_MAP, skybox_tex); + } else { + sky_params.mvp_matrix = &quake_skyid.mvp_matrix; + sky_params.sky_matrix = &quake_skyid.sky_matrix; + sky_params.vertex = &quake_skyid.vertex; + sky_params.fog = &quake_skyid.fog; + + qfeglUseProgram (quake_skyid.program); + qfeglEnableVertexAttribArray (quake_skyid.vertex.location); + + qfeglUniform1i (quake_skyid.palette.location, 2); + qfeglActiveTexture (GL_TEXTURE0 + 2); + qfeglEnable (GL_TEXTURE_2D); + qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); + + qfeglUniform1f (quake_skyid.time.location, vr_data.realtime); + + qfeglUniform1i (quake_skyid.trans.location, 0); + qfeglActiveTexture (GL_TEXTURE0 + 0); + qfeglEnable (GL_TEXTURE_2D); + + qfeglUniform1i (quake_skyid.solid.location, 1); + qfeglActiveTexture (GL_TEXTURE0 + 1); + qfeglEnable (GL_TEXTURE_2D); + } + + glsl_Fog_GetColor (fog); + fog[3] = glsl_Fog_GetDensity () / 64.0; + qfeglUniform4fv (sky_params.fog->location, 1, fog); + + spin (mat); + qfeglUniformMatrix4fv (sky_params.sky_matrix->location, 1, false, mat); + + qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo);*/ +} + +static void +sky_end (bspctx_t *bctx) +{ + /*XXX qfeglDisableVertexAttribArray (sky_params.vertex->location); + + qfeglActiveTexture (GL_TEXTURE0 + 0); + qfeglDisable (GL_TEXTURE_2D); + qfeglDisable (GL_TEXTURE_CUBE_MAP); + qfeglActiveTexture (GL_TEXTURE0 + 1); + qfeglDisable (GL_TEXTURE_2D); + qfeglActiveTexture (GL_TEXTURE0 + 2); + qfeglDisable (GL_TEXTURE_2D); + + qfeglBindBuffer (GL_ARRAY_BUFFER, 0);*/ +} + +static inline void +add_surf_elements (vulktex_t *tex, instsurf_t *is, + elechain_t **ec, elements_t **el, bspctx_t *bctx) +{ + msurface_t *surf = is->surface; + glslpoly_t *poly = (glslpoly_t *) surf->polys; + + if (!tex->elechain) { + (*ec) = add_elechain (tex, surf->ec_index, bctx); + (*ec)->transform = is->transform; + (*ec)->color = is->color; + (*el) = (*ec)->elements; + (*el)->base = surf->base; + if (!(*el)->list) + (*el)->list = dstring_new (); + dstring_clear ((*el)->list); + } + if (is->transform != (*ec)->transform || is->color != (*ec)->color) { + (*ec) = add_elechain (tex, surf->ec_index, bctx); + (*ec)->transform = is->transform; + (*ec)->color = is->color; + (*el) = (*ec)->elements; + (*el)->base = surf->base; + if (!(*el)->list) + (*el)->list = dstring_new (); + dstring_clear ((*el)->list); + } + if (surf->base != (*el)->base) { + (*el)->next = get_elements (bctx); + (*el) = (*el)->next; + (*el)->base = surf->base; + if (!(*el)->list) + (*el)->list = dstring_new (); + dstring_clear ((*el)->list); + } + dstring_append ((*el)->list, (char *) poly->indices, + poly->count * sizeof (poly->indices[0])); +} + +static void +build_tex_elechain (vulktex_t *tex, bspctx_t *bctx) +{ + instsurf_t *is; + elechain_t *ec = 0; + elements_t *el = 0; + + for (is = tex->tex_chain; is; is = is->tex_chain) { + add_surf_elements (tex, is, &ec, &el, bctx); + } +} + +void +Vulkan_DrawWorld (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + entity_t worldent; + + clear_texture_chains (bctx); // do this first for water and skys + + memset (&worldent, 0, sizeof (worldent)); + worldent.model = r_worldentity.model; + + currententity = &worldent; + + R_VisitWorldNodes (worldent.model, ctx); + if (r_drawentities->int_val) { + entity_t *ent; + for (ent = r_ent_queue; ent; ent = ent->next) { + if (ent->model->type != mod_brush) + continue; + currententity = ent; + + R_DrawBrushModel (ent, ctx); + } + } + + Vulkan_FlushLightmaps (ctx); + bsp_begin (ctx); + //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); + for (size_t i = 0; i < bctx->texture_chains.size; i++) { + vulktex_t *tex; + //XXX elechain_t *ec = 0; + + tex = bctx->texture_chains.a[i]; + + build_tex_elechain (tex, bctx); + + //XXX if (tex->elechain) + //XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); + + /*XXX for (ec = tex->elechain; ec; ec = ec->next) { + draw_elechain (ec, quake_bsp.mvp_matrix.location, + quake_bsp.vertex.location, + quake_bsp.tlst.location, + quake_bsp.color.location); + }*/ + tex->elechain = 0; + tex->elechain_tail = &tex->elechain; + } + bsp_end (ctx); +} + +void +Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) +{ +/* bspctx_t *bctx = ctx->bsp_context; + instsurf_t *is; + msurface_t *surf; + vulktex_t *tex = 0; + elechain_t *ec = 0; + elements_t *el = 0; + + if (!bctx->waterchain) + return; + + turb_begin (bctx); + for (is = bctx->waterchain; is; is = is->tex_chain) { + surf = is->surface; + if (tex != surf->texinfo->texture) { + if (tex) { + //XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); + //for (ec = tex->elechain; ec; ec = ec->next) + // draw_elechain (ec, quake_turb.mvp_matrix.location, + // quake_turb.vertex.location, + // quake_turb.tlst.location, + // quake_turb.color.location); + tex->elechain = 0; + tex->elechain_tail = &tex->elechain; + } + tex = surf->texinfo->texture; + } + add_surf_elements (tex, is, &ec, &el, bctx); + } + if (tex) { + //XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); + //for (ec = tex->elechain; ec; ec = ec->next) + // draw_elechain (ec, quake_turb.mvp_matrix.location, + // quake_turb.vertex.location, + // quake_turb.tlst.location, + // quake_turb.color.location); + tex->elechain = 0; + tex->elechain_tail = &tex->elechain; + } + turb_end (bctx); + + bctx->waterchain = 0; + bctx->waterchain_tail = &bctx->waterchain;*/ +} + +void +Vulkan_DrawSky (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + instsurf_t *is; + msurface_t *surf; + vulktex_t *tex = 0; + elechain_t *ec = 0; + elements_t *el = 0; + + if (!bctx->sky_chain) + return; + + sky_begin (bctx); + for (is = bctx->sky_chain; is; is = is->tex_chain) { + surf = is->surface; + if (tex != surf->texinfo->texture->render) { + if (tex) { + if (!bctx->skybox_tex) { + //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); + //qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[0]); + //qfeglActiveTexture (GL_TEXTURE0 + 1); + //qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[1]); + } + //for (ec = tex->elechain; ec; ec = ec->next) + // draw_elechain (ec, sky_params.mvp_matrix->location, + // sky_params.vertex->location, -1, -1); + tex->elechain = 0; + tex->elechain_tail = &tex->elechain; + } + tex = surf->texinfo->texture->render; + } + add_surf_elements (tex, is, &ec, &el, bctx); + } + if (tex) { + if (!bctx->skybox_tex) { + //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); + //qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[0]); + //qfeglActiveTexture (GL_TEXTURE0 + 1); + //qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[1]); + } + //for (ec = tex->elechain; ec; ec = ec->next) + // draw_elechain (ec, sky_params.mvp_matrix->location, + // sky_params.vertex->location, -1, -1); + tex->elechain = 0; + tex->elechain_tail = &tex->elechain; + } + sky_end (bctx); + + bctx->sky_chain = 0; + bctx->sky_chain_tail = &bctx->sky_chain; +} + +void +Vulkan_Bsp_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + bspctx_t *bctx = calloc (1, sizeof (bspctx_t)); + ctx->bsp_context = bctx; + + bctx->waterchain_tail = &bctx->waterchain; + bctx->sky_chain_tail = &bctx->sky_chain; + bctx->static_instsurfs_tail = &bctx->static_instsurfs; + bctx->elechains_tail = &bctx->elechains; + bctx->elementss_tail = &bctx->elementss; + bctx->instsurfs_tail = &bctx->instsurfs; + + bctx->light_scrap = QFV_CreateScrap (device, 2048, tex_frgba); + size_t size = QFV_ScrapSize (bctx->light_scrap); + bctx->light_stage = QFV_CreateStagingBuffer (device, size, 3, + ctx->cmdpool); + + DARRAY_INIT (&bctx->texture_chains, 64); + + size_t frames = ctx->framebuffers.size; + DARRAY_INIT (&bctx->frames, frames); + DARRAY_RESIZE (&bctx->frames, frames); + bctx->frames.grow = 0; + + bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp.main"); + bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp"); + + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "quakebsp"); + } + __auto_type pool = QFV_GetDescriptorPool (ctx, "quakebsp"); + + __auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca); + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); + + __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); + for (size_t i = 0; i < frames; i++) { + __auto_type bframe = &bctx->frames.a[i]; + bframe->descriptors = sets->a[i]; + bframe->bsp_cmd = cmdBuffers->a[i]; + bframe->turb_cmd = cmdBuffers->a[i]; + bframe->sky_cmd = cmdBuffers->a[i]; + } + free (sets); +} + +void +Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; + + dfunc->vkDestroyPipeline (device->dev, bctx->main, 0); + DARRAY_CLEAR (&bctx->texture_chains); + DARRAY_CLEAR (&bctx->frames); + QFV_DestroyStagingBuffer (bctx->light_stage); + QFV_DestroyScrap (bctx->light_scrap); +} + +static inline __attribute__((const)) int +is_pow2 (unsigned x) +{ + int count; + + for (count = 0; x; x >>= 1) + if (x & 1) + count++; + return count == 1; +} + +// NOTE: this expects the destination tex_t to be set up: memory allocated +// and dimentions/format etc already set. the size of the rect to be copied +// is taken from dst. Also, dst->format and src->format must be the same, and +// either 3 or 4, or bad things will happen. Also, no clipping is done, so if +// x < 0 or y < 0 or x + dst->width > src->width +// or y + dst->height > src->height, bad things will happen. +/*XXX static void +copy_sub_tex (tex_t *src, int x, int y, tex_t *dst) +{ + int dstbytes; + int srcbytes; + int i; + + srcbytes = src->width * src->format; + dstbytes = dst->width * dst->format; + + x *= src->format; + for (i = 0; i < dst->height; i++) + memcpy (dst->data + i * dstbytes, src->data + (i + y) * srcbytes + x, + dstbytes); +}*/ + +/*XXX void +Vulkan_R_LoadSkys (const char *sky, vulkan_ctx_t *ctx) +{ +const char *name; + int i; + tex_t *tex; + // NOTE: quake's world and GL's world are rotated relative to each other + // quake has x right, y in, z up. gl has x right, y up, z out + // quake order: +x -x +z -z +y -y + // gl order: +x -x +y -y +z -z + // fizquake orger: -y +y +z -z +x -x + // to get from quake order to fitzquake order, all that's needed is + // a -90 degree rotation on the (quake) z-axis. This is taken care of in + // the sky_matrix setup code. + // However, from the player's perspective, skymaps have lf and rt + // swapped, but everythink makes sense if looking at the cube from outside + // along the positive y axis, with the front of the cube being the nearest + // face. This matches nicely with Blender's default cube in front (num-1) + // view. + static const char *sky_suffix[] = { "ft", "bk", "up", "dn", "rt", "lf"}; + static int sky_coords[][2] = { + {2, 0}, // front + {0, 0}, // back + {1, 1}, // up + {0, 1}, // down + {2, 1}, // left + {1, 0}, // right + }; + + if (!sky || !*sky) + sky = r_skyname->string; + + if (!*sky || !strcasecmp (sky, "none")) { + skybox_loaded = false; + return; + } + + if (!skybox_tex) + qfeglGenTextures (1, &skybox_tex); + + qfeglBindTexture (GL_TEXTURE_CUBE_MAP, skybox_tex); + + //blender envmap + // bk rt ft + // dn up lt + tex = LoadImage (name = va ("env/%s_map", sky)); + if (tex && tex->format >= 3 && tex->height * 3 == tex->width * 2 + && is_pow2 (tex->height)) { + tex_t *sub; + int size = tex->height / 2; + + skybox_loaded = true; + sub = malloc (field_offset (tex_t, data[size * size * tex->format])); + sub->width = size; + sub->height = size; + sub->format = tex->format; + sub->palette = tex->palette; + for (i = 0; i < 6; i++) { + int x, y; + x = sky_coords[i][0] * size; + y = sky_coords[i][1] * size; + copy_sub_tex (tex, x, y, sub); + qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, + sub->format == 3 ? GL_RGB : GL_RGBA, + sub->width, sub->height, 0, + sub->format == 3 ? GL_RGB : GL_RGBA, + GL_UNSIGNED_BYTE, sub->data); + } + free (sub); + } else { + skybox_loaded = true; + for (i = 0; i < 6; i++) { + tex = LoadImage (name = va ("env/%s%s", sky, sky_suffix[i])); + if (!tex || tex->format < 3) { // FIXME pcx support + Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); + // also look in gfx/env, where Darkplaces looks for skies + tex = LoadImage (name = va ("gfx/env/%s%s", sky, + sky_suffix[i])); + if (!tex || tex->format < 3) { // FIXME pcx support + Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); + skybox_loaded = false; + continue; + } + } + Sys_MaskPrintf (SYS_GLSL, "Loaded %s\n", name); + qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, + tex->format == 3 ? GL_RGB : GL_RGBA, + tex->width, tex->height, 0, + tex->format == 3 ? GL_RGB : GL_RGBA, + GL_UNSIGNED_BYTE, tex->data); + } + } + qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + qfeglGenerateMipmap (GL_TEXTURE_CUBE_MAP); +}*/ diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 5cb213b16..cca17f727 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -404,7 +404,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < frames; i++) { - __auto_type cframe = &ctx->framebuffers.a[i]; __auto_type dframe = &dctx->frames.a[i]; dframe->descriptors = sets->a[i]; @@ -420,7 +419,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) }; dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); dframe->cmd = cmdBuffers->a[i]; - DARRAY_APPEND (cframe->subCommand, cmdBuffers->a[i]); } free (sets); } @@ -686,6 +684,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = dframe->cmd; + DARRAY_APPEND (cframe->subCommand, cmd); VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c new file mode 100644 index 000000000..495864d9f --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -0,0 +1,279 @@ +/* + vulkan_lightmap.c + + surface-related refresh code + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2000 Joseph Carter + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define NH_DEFINE +#include "namehack.h" + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include + +#include "QF/cvar.h" +#include "QF/render.h" +#include "QF/sys.h" +#include "QF/Vulkan/qf_bsp.h" +#include "QF/Vulkan/qf_lightmap.h" +#include "QF/Vulkan/qf_main.h" +#include "QF/Vulkan/texture.h" + +#include "compat.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +#define LUXEL_SIZE 4 + +static inline void +add_dynamic_lights (msurface_t *surf, float *block) +{ + unsigned lnum; + int sd, td; + float dist, rad, minlight; + vec3_t impact, local, lightorigin; + int smax, tmax; + int s, t; + mtexinfo_t *tex; + plane_t *plane; + + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + tex = surf->texinfo; + plane = surf->plane; + + for (lnum = 0; lnum < r_maxdlights; lnum++) { + if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32)))) + continue; // not lit by this light + + dlight_t *light = &r_dlights[lnum]; + + VectorSubtract (light->origin, currententity->origin, lightorigin); + rad = light->radius; + dist = DotProduct (lightorigin, plane->normal) - plane->dist; + rad -= fabs (dist); + + minlight = light->minlight; + if (rad < minlight) { + continue; + } + VectorMultSub (light->origin, dist, plane->normal, impact); + + local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]; + local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]; + + local[0] -= surf->texturemins[0]; + local[1] -= surf->texturemins[1]; + + for (t = 0; t < tmax; t++) { + td = local[1] - t * 16; + if (td < 0) { + td = -td; + } + for (s = 0; s < smax; s++) { + sd = local[0] - s * 16; + if (sd < 0) { + sd = -sd; + } + if (sd > td) { + dist = sd + (td >> 1); + } else { + dist = td + (sd >> 1); + } + if (dist < minlight) { + float *out = block + (t * smax + s) * LUXEL_SIZE; + float l = (rad - dist) * 256; + VectorMultAdd (out, l, light->color, out); + out[3] = 1; + out += LUXEL_SIZE; + } + } + } + } +} + +void +Vulkan_BuildLightMap (msurface_t *surf, vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + int smax, tmax, size; + unsigned scale; + int i; + float *out, *block; + + surf->cached_dlight = (surf->dlightframe == r_framecount); + + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + size = smax * tmax * LUXEL_SIZE; + + block = QFV_SubpicBatch (surf->lightpic, bctx->light_stage); + + // set to full bright if no light data + if (!r_worldentity.model->lightdata) { + out = block; + while (size-- > 0) { + *out++ = 1; + } + return; + } + + // clear to no light + memset (block, 0, size * sizeof(float)); + + // add all the lightmaps + if (surf->samples) { + byte *lightmap; + + lightmap = surf->samples; + for (int maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; + maps++) { + scale = d_lightstylevalue[surf->styles[maps]]; + surf->cached_light[maps] = scale; // 8.8 fraction + out = block; + for (i = 0; i < smax * tmax; i++) { + *out++ += *lightmap++ * scale / 256.0; + *out++ += *lightmap++ * scale / 256.0; + *out++ += *lightmap++ * scale / 256.0; + } + } + } + // add all the dynamic lights + if (surf->dlightframe == r_framecount) { + add_dynamic_lights (surf, block); + } +} + +void +Vulkan_CalcLightmaps (vulkan_ctx_t *ctx) +{ +/* int i; + + for (i = 0; i < MAX_LIGHTMAPS; i++) { + if (!gl_lightmap_polys[i]) + continue; + if (gl_lightmap_modified[i]) { + qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + i); + GL_UploadLightmap (i); + gl_lightmap_modified[i] = false; + } + }*/ +} + +static void +vulkan_create_surf_lightmap (msurface_t *surf, vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + int smax, tmax; + + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + + surf->lightpic = QFV_ScrapSubpic (bctx->light_scrap, smax, tmax); + if (!surf->lightpic) { + Sys_Error ("FIXME taniwha is being lazy"); + } +} + +/* + GL_BuildLightmaps + + Builds the lightmap texture with all the surfaces from all brush models +*/ +void +Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + int i, j; + model_t *m; + + QFV_ScrapClear (bctx->light_scrap); + + r_framecount = 1; // no dlightcache + + for (j = 1; j < num_models; j++) { + m = models[j]; + if (!m) + break; + if (m->name[0] == '*') { + // sub model surfaces are processed as part of the main model + continue; + } + // non-bsp models don't have surfaces. + for (i = 0; i < m->numsurfaces; i++) { + msurface_t *surf = m->surfaces + i; + surf->lightpic = 0; // paranoia + if (surf->flags & SURF_DRAWTURB) { + continue; + } + if (surf->flags & SURF_DRAWSKY) { + continue; + } + vulkan_create_surf_lightmap (surf, ctx); + } + } + + for (j = 1; j < num_models; j++) { + m = models[j]; + if (!m) { + break; + } + if (m->name[0] == '*') { + // sub model surfaces are processed as part of the main model + continue; + } + // non-bsp models don't have surfaces. + for (i = 0; i < m->numsurfaces; i++) { + msurface_t *surf = m->surfaces + i; + if (surf->lightpic) { + Vulkan_BuildLightMap (surf, ctx); + } + } + } +} + +VkImageView +Vulkan_LightmapImageView (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + return QFV_ScrapImageView (bctx->light_scrap); +} + +void +Vulkan_FlushLightmaps (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + QFV_ScrapFlush (bctx->light_scrap); +} diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c new file mode 100644 index 000000000..1e1913de9 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -0,0 +1,250 @@ +/* + vulkan_main.c + + Vulkan rendering + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/1/19 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define NH_DEFINE +#include "namehack.h" + +#ifdef HAVE_STRING_H +# include "string.h" +#endif +#ifdef HAVE_STRINGS_H +# include "strings.h" +#endif + +#include "QF/cmd.h" +#include "QF/cvar.h" +#include "QF/image.h" +#include "QF/render.h" +#include "QF/screen.h" +#include "QF/sys.h" + +#include "QF/Vulkan/qf_vid.h" +//#include "QF/Vulkan/qf_alias.h" +#include "QF/Vulkan/qf_bsp.h" +//#include "QF/Vulkan/qf_iqm.h" +#include "QF/Vulkan/qf_lightmap.h" +#include "QF/Vulkan/qf_main.h" +#include "QF/Vulkan/qf_particles.h" +//#include "QF/Vulkan/qf_textures.h" + +#include "mod_internal.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +static void +setup_frame (vulkan_ctx_t *ctx) +{ + R_AnimateLight (); + R_ClearEnts (); + r_framecount++; + + VectorCopy (r_refdef.vieworg, r_origin); + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + R_SetFrustum (); + + r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.model); +} + +static void +setup_view (vulkan_ctx_t *ctx) +{ + float *mat = ctx->matrices.view_3d; + static mat4_t z_up = { + 0, 0, -1, 0, + -1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 1, + }; + + /*x = r_refdef.vrect.x; + y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); + w = r_refdef.vrect.width; + h = r_refdef.vrect.height; + qfeglViewport (x, y, w, h);*/ + + Mat4Zero (mat); + VectorCopy (vpn, mat + 0); + VectorNegate (vright, mat + 4); // we want vleft + VectorCopy (vup, mat + 8); + mat[15] = 1; + Mat4Transpose (mat, mat);//AngleVectors gives the transpose of what we want + Mat4Mult (z_up, mat, glsl_view); + + Mat4Identity (mat); + VectorNegate (r_refdef.vieworg, mat + 12); + Mat4Mult (glsl_view, mat, glsl_view); +} + +static void +R_RenderEntities (vulkan_ctx_t *ctx) +{ + //entity_t *ent; + //int begun; + + if (!r_drawentities->int_val) + return; +#define RE_LOOP(type_name, Type) \ + do { \ + begun = 0; \ + for (ent = r_ent_queue; ent; ent = ent->next) { \ + if (ent->model->type != mod_##type_name) \ + continue; \ + if (!begun) { \ + glsl_R_##Type##Begin (); \ + begun = 1; \ + } \ + currententity = ent; \ + glsl_R_Draw##Type (); \ + } \ + if (begun) \ + glsl_R_##Type##End (); \ + } while (0) + + //RE_LOOP (alias, Alias); + //RE_LOOP (iqm, IQM); + //RE_LOOP (sprite, Sprite); +} + +static void +R_DrawViewModel (void) +{ + currententity = vr_data.view_model; + if (vr_data.inhibit_viewmodel + || !r_drawviewmodel->int_val + || !r_drawentities->int_val + || !currententity->model) + return; + + // hack the depth range to prevent view model from poking into walls + //qfeglDepthRangef (0, 0.3); + //glsl_R_AliasBegin (); + //glsl_R_DrawAlias (); + //glsl_R_AliasEnd (); + //qfeglDepthRangef (0, 1); +} + +void +Vulkan_RenderView (vulkan_ctx_t *ctx) +{ + double t[10] = {}; + int speeds = r_speeds->int_val; + + if (speeds) + t[0] = Sys_DoubleTime (); + setup_frame (ctx); + setup_view (ctx); + if (speeds) + t[1] = Sys_DoubleTime (); + R_MarkLeaves (); + if (speeds) + t[2] = Sys_DoubleTime (); + R_PushDlights (vec3_origin); + if (speeds) + t[3] = Sys_DoubleTime (); + Vulkan_DrawWorld (ctx); + if (speeds) + t[4] = Sys_DoubleTime (); + Vulkan_DrawSky (ctx); + if (speeds) + t[5] = Sys_DoubleTime (); + R_RenderEntities (ctx); + if (speeds) + t[6] = Sys_DoubleTime (); + Vulkan_DrawWaterSurfaces (ctx); + if (speeds) + t[7] = Sys_DoubleTime (); + Vulkan_DrawParticles (ctx); + if (speeds) + t[8] = Sys_DoubleTime (); + R_DrawViewModel (); + if (speeds) + t[9] = Sys_DoubleTime (); + if (speeds) { + Sys_Printf ("frame: %g, setup: %g, mark: %g, pushdl: %g, world: %g," + " sky: %g, ents: %g, water: %g, part: %g, view: %g\n", + (t[9] - t[0]) * 1000, (t[1] - t[0]) * 1000, + (t[2] - t[1]) * 1000, (t[3] - t[2]) * 1000, + (t[4] - t[3]) * 1000, (t[5] - t[4]) * 1000, + (t[6] - t[5]) * 1000, (t[7] - t[6]) * 1000, + (t[8] - t[7]) * 1000, (t[9] - t[8]) * 1000); + } +} + +void +Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, + vulkan_ctx_t *ctx) +{ + int i; + + for (i = 0; i < 256; i++) { + d_lightstylevalue[i] = 264; // normal light value + } + + memset (&r_worldentity, 0, sizeof (r_worldentity)); + r_worldentity.model = worldmodel; + + // Force a vis update + r_viewleaf = NULL; + R_MarkLeaves (); + + R_FreeAllEntities (); + Vulkan_ClearParticles (ctx); + Vulkan_RegisterTextures (models, num_models, ctx); + Vulkan_BuildLightmaps (models, num_models, ctx); + Vulkan_BuildDisplayLists (models, num_models, ctx); +} + +/*void +glsl_R_LineGraph (int x, int y, int *h_vals, int count) +{ +}*/ + +/*void +glsl_R_TimeRefresh_f (void) +{ + double start, stop, time; + int i; + + glsl_ctx->end_rendering (); + + start = Sys_DoubleTime (); + for (i = 0; i < 128; i++) { + r_refdef.viewangles[1] = i * (360.0 / 128.0); + Vulkan_RenderView (ctx); + glsl_ctx->end_rendering (); + } + + stop = Sys_DoubleTime (); + time = stop - start; + Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); +}*/ From 7d9ef9a47e8391b078ae6192f0cb5c2288ad8bff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 20 Jan 2021 13:55:50 +0900 Subject: [PATCH 1236/3664] [model] Mark all cleared models as cleared This fixes a nine year old bug that I discovered only today thanks to the vulkan renderer. The problem was that when a model had a clear callback, it was not getting marked as needing to be reloaded, and thus the model would be "reused" after being trampled on by another model loading over it. Also, plug a potential string buffer overflow (strcpy just will not die!). --- libs/models/model.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libs/models/model.c b/libs/models/model.c index 198a69f7c..8c5036278 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -122,14 +122,15 @@ Mod_ClearAll (void) model_t **mod; for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) { + //FIXME this seems to be correct but need to double check the behavior + //with alias models if (!(*mod)->needload && (*mod)->clear) { (*mod)->clear (*mod, (*mod)->data); - } else { - if ((*mod)->type != mod_alias) - (*mod)->needload = true; - if ((*mod)->type == mod_sprite) - (*mod)->cache.data = 0; } + if ((*mod)->type != mod_alias) + (*mod)->needload = true; + if ((*mod)->type == mod_sprite) + (*mod)->cache.data = 0; } } @@ -156,7 +157,8 @@ Mod_FindName (const char *name) for (i = 1; i < MOD_BLOCK; i++) mod[i] = mod[0] + i; } - strcpy ((*mod)->name, name); + memset ((*mod), 0, sizeof (model_t)); + strncpy ((*mod)->name, name, sizeof (*mod)->name - 1); (*mod)->needload = true; mod_numknown++; Cache_Add (&(*mod)->cache, *mod, Mod_CallbackLoad); From 9eef805b7db232c5784af82a3493121cef04ec58 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 20 Jan 2021 15:11:50 +0900 Subject: [PATCH 1237/3664] [vulkan] Generate triangle fans for bsp models They're not uploaded to the card yet, but the basics seem to be working. --- include/QF/Vulkan/qf_bsp.h | 3 +- include/QF/model.h | 2 +- libs/video/renderer/vid_render_vulkan.c | 3 +- libs/video/renderer/vulkan/vulkan_bsp.c | 133 ++++++++++++++---------- 4 files changed, 85 insertions(+), 56 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index dec2fe085..0dae9450a 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -45,7 +45,6 @@ typedef struct elements_s { struct elements_s *_next; struct elements_s *next; byte *base; - struct dstring_s *list; } elements_t; typedef struct elechain_s { @@ -107,6 +106,8 @@ typedef struct bspctx_s { struct scrap_s *light_scrap; struct qfv_stagebuf_s *light_stage; + struct bsppoly_s *polys; + VkDeviceMemory texture_memory; VkPipeline main; VkPipelineLayout layout; diff --git a/include/QF/model.h b/include/QF/model.h index 1dbfe1b6f..8d0129721 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -153,7 +153,7 @@ typedef struct msurface_s { int light_s, light_t; // gl lightmap coordinates - glpoly_t *polys; // multiple if warped + glpoly_t *polys; // multiple if warped instsurf_t *instsurf; ///< null if not part of world model/sub-model instsurf_t *tinst; ///< for instance models diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index e6f993b38..9e6dc90fd 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -44,6 +44,7 @@ #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_particles.h" +#include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" @@ -462,7 +463,7 @@ vulkan_Skin_InitTranslations (void) } static vid_model_funcs_t model_funcs = { - sizeof (vulktex_t) + 2 * sizeof (struct qfv_tex_s *), + sizeof (vulktex_t) + 2 * sizeof (qfv_tex_t), vulkan_Mod_LoadLighting, vulkan_Mod_SubdivideSurface, vulkan_Mod_ProcessTexture, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 466d6bbd7..a755f3d86 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -70,10 +70,10 @@ #define ALLOC_CHUNK 64 -typedef struct { +typedef struct bsppoly_s { uint32_t count; uint32_t indices[1]; -} glslpoly_t; +} bsppoly_t; #define CHAIN_SURF_F2B(surf,chain) \ do { \ @@ -297,11 +297,18 @@ add_elechain (vulktex_t *tex, int ec_index, bspctx_t *bctx) } static void +count_verts_inds (model_t **models, msurface_t *fa, + uint32_t *verts, uint32_t *inds) +{ + *verts = fa->numedges; + *inds = fa->numedges + 1; +} + +static bsppoly_t * build_surf_displist (model_t **models, msurface_t *fa, int base, - dstring_t *vert_list) + bspvert_t **vert_list) { int numverts; - int numtris; int numindices; int i; vec_t *vec; @@ -310,38 +317,41 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, int *surfedges; int index; bspvert_t *verts; - glslpoly_t *poly; + bsppoly_t *poly; uint32_t *ind; float s, t; if (fa->ec_index < 0) { - vertices = models[-fa->ec_index - 1]->vertexes; - edges = models[-fa->ec_index - 1]->edges; - surfedges = models[-fa->ec_index - 1]->surfedges; + // instance model + vertices = models[~fa->ec_index]->vertexes; + edges = models[~fa->ec_index]->edges; + surfedges = models[~fa->ec_index]->surfedges; } else { - vertices = r_worldentity.model->vertexes; - edges = r_worldentity.model->edges; + // main or sub model + vertices = r_worldentity.model->vertexes; + edges = r_worldentity.model->edges; surfedges = r_worldentity.model->surfedges; } + // create a triangle fan numverts = fa->numedges; - numtris = numverts - 2; - numindices = numtris * 3; - verts = alloca (numverts * sizeof (bspvert_t)); - poly = malloc (field_offset (glslpoly_t, indices[numindices])); + numindices = numverts + 1; + verts = *vert_list; + // surf->polys is set to the next slow before the call + poly = (bsppoly_t *) fa->polys; poly->count = numindices; - for (i = 0, ind = poly->indices; i < numtris; i++) { - *ind++ = base; - *ind++ = base + i + 1; - *ind++ = base + i + 2; + for (i = 0, ind = poly->indices; i < numverts; i++) { + *ind++ = base + i; } + *ind++ = -1; // end of primitive fa->polys = (glpoly_t *) poly; for (i = 0; i < numverts; i++) { index = surfedges[fa->firstedge + i]; - if (index > 0) + if (index > 0) { vec = vertices[edges[index].v[0]].position; - else + } else { vec = vertices[edges[-index].v[1]].position; + } s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; @@ -368,19 +378,23 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, verts[i].tlst[2] = s * fa->lightpic->size; verts[i].tlst[3] = t * fa->lightpic->size; } - dstring_append (vert_list, (char *) verts, numverts * sizeof (bspvert_t)); + *vert_list += numverts; + return (bsppoly_t *) &poly->indices[numindices]; } void Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) { + qfv_device_t *device = ctx->device; bspctx_t *bctx = ctx->bsp_context; int i, j; int vertex_index_base; model_t *m; dmodel_t *dm; msurface_t *surf; - dstring_t *vertices; + qfv_stagebuf_t *stage; + bspvert_t *vertices; + bsppoly_t *poly; QuatSet (0, 0, sqrt(0.5), sqrt(0.5), bctx->sky_fix); // proper skies QuatSet (0, 0, 0, 1, bctx->sky_rotation[0]); @@ -418,16 +432,38 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!surf->ec_index && m != r_worldentity.model) surf->ec_index = -1 - i; // instanced model tex = surf->texinfo->texture->render; + // append surf to the texture chain CHAIN_SURF_F2B (surf, tex->tex_chain); } } // All vertices from all brush models go into one giant vbo. - vertices = dstring_new (); + uint32_t vertex_count = 0; + uint32_t index_count = 0; + uint32_t poly_count = 0; + for (size_t i = 0; i < bctx->texture_chains.size; i++) { + vulktex_t *tex = bctx->texture_chains.a[i]; + for (instsurf_t *is = tex->tex_chain; is; is = is->tex_chain) { + uint32_t verts, inds; + count_verts_inds (models, is->surface, &verts, &inds); + vertex_count += verts; + index_count += inds; + poly_count++; + } + } + stage = QFV_CreateStagingBuffer (device, + vertex_count * sizeof (bspvert_t), 1, + ctx->cmdpool); + vertices = stage->data; vertex_index_base = 0; + // holds all the polygon definitions (count + indices) + bctx->polys = malloc ((index_count + poly_count) * sizeof (uint32_t)); + // All usable surfaces have been chained to the (base) texture they use. // Run through the textures, using their chains to build display maps. // For animated textures, if a surface is on one texture of the group, it // will be on all. + poly = bctx->polys; + int count = 0; for (size_t i = 0; i < bctx->texture_chains.size; i++) { vulktex_t *tex; instsurf_t *is; @@ -441,42 +477,43 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!tex->elechain) { ec = add_elechain (tex, surf->ec_index, bctx); el = ec->elements; - el->base = (byte *) (intptr_t) vertices->size; vertex_index_base = 0; } if (surf->ec_index != ec->index) { // next sub-model ec = add_elechain (tex, surf->ec_index, bctx); el = ec->elements; - el->base = (byte *) (intptr_t) vertices->size; vertex_index_base = 0; } if (vertex_index_base + surf->numedges > 65535) { // elements index overflow el->next = get_elements (bctx); el = el->next; - el->base = (byte *) (intptr_t) vertices->size; vertex_index_base = 0; } // we don't use it now, but pre-initializing the list won't hurt - if (!el->list) - el->list = dstring_new (); - dstring_clear (el->list); + //XXX if (!el->list) + //XXX el->list = dstring_new (); + //XXX dstring_clear (el->list); - surf->base = el->base; - build_surf_displist (models, surf, vertex_index_base, vertices); + surf->polys = (glpoly_t *) poly; + poly = build_surf_displist (models, surf, vertex_index_base, + &vertices); vertex_index_base += surf->numedges; + count++; } } clear_texture_chains (bctx); - Sys_MaskPrintf (SYS_GLSL, "R_BuildDisplayLists: %ld verts total\n", - (long) (vertices->size / sizeof (bspvert_t))); + Sys_MaskPrintf (SYS_VULKAN, + "R_BuildDisplayLists: verts:%u, inds:%u, polys:%u (%d) %zd\n", + vertex_count, index_count, poly_count, count, + ((size_t) poly - (size_t) bctx->polys)/sizeof(uint32_t)); /*XXX if (!bsp_vbo) qfeglGenBuffers (1, &bsp_vbo); qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo); qfeglBufferData (GL_ARRAY_BUFFER, vertices->size, vertices->str, GL_STATIC_DRAW); qfeglBindBuffer (GL_ARRAY_BUFFER, 0);*/ - dstring_delete (vertices); + QFV_DestroyStagingBuffer (stage); } static void @@ -890,38 +927,28 @@ add_surf_elements (vulktex_t *tex, instsurf_t *is, elechain_t **ec, elements_t **el, bspctx_t *bctx) { msurface_t *surf = is->surface; - glslpoly_t *poly = (glslpoly_t *) surf->polys; + //XXX bsppoly_t *poly = (bsppoly_t *) surf->polys; if (!tex->elechain) { (*ec) = add_elechain (tex, surf->ec_index, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; - (*el)->base = surf->base; - if (!(*el)->list) - (*el)->list = dstring_new (); - dstring_clear ((*el)->list); + //XXX if (!(*el)->list) + //XXX (*el)->list = dstring_new (); + //XXX dstring_clear ((*el)->list); } if (is->transform != (*ec)->transform || is->color != (*ec)->color) { (*ec) = add_elechain (tex, surf->ec_index, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; - (*el)->base = surf->base; - if (!(*el)->list) - (*el)->list = dstring_new (); - dstring_clear ((*el)->list); + //XXX if (!(*el)->list) + //XXX (*el)->list = dstring_new (); + //XXX dstring_clear ((*el)->list); } - if (surf->base != (*el)->base) { - (*el)->next = get_elements (bctx); - (*el) = (*el)->next; - (*el)->base = surf->base; - if (!(*el)->list) - (*el)->list = dstring_new (); - dstring_clear ((*el)->list); - } - dstring_append ((*el)->list, (char *) poly->indices, - poly->count * sizeof (poly->indices[0])); + //XXX dstring_append ((*el)->list, (char *) poly->indices, + //XXX poly->count * sizeof (poly->indices[0])); } static void From 6f73a7388b16c4e80f5b732208253ccf8128e8c8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 20 Jan 2021 16:25:26 +0900 Subject: [PATCH 1238/3664] [vulkan] Ensure staging buffer is idle before free I never actually tested what would happen, but I suspect destroying a staging buffer before it is finished its job would lead to unpleasant issues. --- include/QF/Vulkan/command.h | 3 +++ libs/video/renderer/vulkan/staging.c | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 47418db1a..c9ed3021e 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -15,6 +15,9 @@ typedef struct qfv_semaphoreset_s typedef struct qfv_fenceset_s DARRAY_TYPE (VkFence) qfv_fenceset_t; +#define QFV_AllocFenceSet(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_fenceset_t, num, allocator) + typedef struct qfv_bufferimagecopy_s DARRAY_TYPE (VkBufferImageCopy) qfv_bufferimagecopy_t; diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 40ad459a6..68bf6a9aa 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -1,7 +1,7 @@ /* - shader.c + staging.c - Vulkan shader manager + Vulkan staging buffer manager Copyright (C) 2021 Bill Currie @@ -97,6 +97,12 @@ QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage) qfv_device_t *device = stage->device; qfv_devfuncs_t *dfunc = device->funcs; + __auto_type fences = QFV_AllocFenceSet (stage->num_packets, alloca); + for (size_t i = 0; i < stage->num_packets; i++) { + fences->a[i] = stage->packet[i].fence; + } + dfunc->vkWaitForFences (device->dev, fences->size, fences->a, VK_TRUE, + ~0ull); for (size_t i = 0; i < stage->num_packets; i++) { dfunc->vkDestroyFence (device->dev, stage->packet[i].fence, 0); } From 9ebecf08bb2ccc86730dfb4946ff2abdcc07fe2d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 20 Jan 2021 16:28:04 +0900 Subject: [PATCH 1239/3664] [vulkan] Create a populate the vertex buffer And create/map the index buffer. --- include/QF/Vulkan/qf_bsp.h | 3 +- libs/video/renderer/vulkan/vulkan_bsp.c | 103 ++++++++++++++++++++---- 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 0dae9450a..c5a74c76e 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -57,7 +57,8 @@ typedef struct elechain_s { } elechain_t; typedef struct bspframe_s { - uint32_t *indeces; + uint32_t *index_data; + uint32_t index_count; VkCommandBuffer bsp_cmd; VkCommandBuffer turb_cmd; VkCommandBuffer sky_cmd; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a755f3d86..eb1ccacc4 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -58,6 +58,7 @@ #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" @@ -386,6 +387,7 @@ void Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; int i, j; int vertex_index_base; @@ -450,10 +452,14 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) poly_count++; } } - stage = QFV_CreateStagingBuffer (device, - vertex_count * sizeof (bspvert_t), 1, + + size_t frames = bctx->frames.size; + size_t index_buffer_size = index_count * frames * sizeof (uint32_t); + size_t vertex_buffer_size = vertex_count * sizeof (bspvert_t); + stage = QFV_CreateStagingBuffer (device, vertex_buffer_size, 1, ctx->cmdpool); - vertices = stage->data; + qfv_packet_t *packet = QFV_PacketAcquire (stage); + vertices = QFV_PacketExtend (packet, vertex_buffer_size); vertex_index_base = 0; // holds all the polygon definitions (count + indices) bctx->polys = malloc ((index_count + poly_count) * sizeof (uint32_t)); @@ -468,7 +474,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) vulktex_t *tex; instsurf_t *is; elechain_t *ec = 0; - elements_t *el = 0; + //elements_t *el = 0; tex = bctx->texture_chains.a[i]; @@ -476,20 +482,20 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) msurface_t *surf = is->surface; if (!tex->elechain) { ec = add_elechain (tex, surf->ec_index, bctx); - el = ec->elements; + //el = ec->elements; vertex_index_base = 0; } if (surf->ec_index != ec->index) { // next sub-model ec = add_elechain (tex, surf->ec_index, bctx); - el = ec->elements; + //el = ec->elements; vertex_index_base = 0; } - if (vertex_index_base + surf->numedges > 65535) { + /*if (vertex_index_base + surf->numedges > 65535) { // elements index overflow el->next = get_elements (bctx); el = el->next; vertex_index_base = 0; - } + }*/ // we don't use it now, but pre-initializing the list won't hurt //XXX if (!el->list) //XXX el->list = dstring_new (); @@ -507,12 +513,73 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) "R_BuildDisplayLists: verts:%u, inds:%u, polys:%u (%d) %zd\n", vertex_count, index_count, poly_count, count, ((size_t) poly - (size_t) bctx->polys)/sizeof(uint32_t)); - /*XXX if (!bsp_vbo) - qfeglGenBuffers (1, &bsp_vbo); - qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo); - qfeglBufferData (GL_ARRAY_BUFFER, vertices->size, vertices->str, - GL_STATIC_DRAW); - qfeglBindBuffer (GL_ARRAY_BUFFER, 0);*/ + if (index_buffer_size > bctx->index_buffer_size) { + if (bctx->index_buffer) { + dfunc->vkUnmapMemory (device->dev, bctx->index_memory); + dfunc->vkDestroyBuffer (device->dev, bctx->index_buffer, 0); + dfunc->vkFreeMemory (device->dev, bctx->index_memory, 0); + } + bctx->index_buffer + = QFV_CreateBuffer (device, index_buffer_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + bctx->index_memory + = QFV_AllocBufferMemory (device, bctx->index_buffer, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + index_buffer_size, 0); + QFV_BindBufferMemory (device, + bctx->index_buffer, bctx->index_memory, 0); + bctx->index_buffer_size = index_buffer_size; + void *data; + dfunc->vkMapMemory (device->dev, bctx->index_memory, 0, + index_buffer_size, 0, &data); + uint32_t *index_data = data; + for (size_t i = 0; i < frames; i++) { + bctx->frames.a[i].index_data = index_data + index_count * i; + } + } + if (vertex_buffer_size > bctx->vertex_buffer_size) { + if (bctx->vertex_buffer) { + dfunc->vkDestroyBuffer (device->dev, bctx->vertex_buffer, 0); + dfunc->vkFreeMemory (device->dev, bctx->vertex_memory, 0); + } + bctx->vertex_buffer + = QFV_CreateBuffer (device, vertex_buffer_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + bctx->vertex_memory + = QFV_AllocBufferMemory (device, bctx->vertex_buffer, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + vertex_buffer_size, 0); + QFV_BindBufferMemory (device, + bctx->vertex_buffer, bctx->vertex_memory, 0); + bctx->vertex_buffer_size = vertex_buffer_size; + } + + VkBufferMemoryBarrier wr_barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + bctx->vertex_buffer, 0, vertex_buffer_size, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, 0, 1, &wr_barrier, 0, 0); + VkBufferCopy copy_region = { packet->offset, 0, vertex_buffer_size }; + dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, + bctx->vertex_buffer, 1, ©_region); + VkBufferMemoryBarrier rd_barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + bctx->vertex_buffer, 0, vertex_buffer_size, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + 0, 0, 0, 1, &rd_barrier, 0, 0); + QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); } @@ -1176,6 +1243,14 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) DARRAY_CLEAR (&bctx->frames); QFV_DestroyStagingBuffer (bctx->light_stage); QFV_DestroyScrap (bctx->light_scrap); + if (bctx->vertex_buffer) { + dfunc->vkDestroyBuffer (device->dev, bctx->vertex_buffer, 0); + dfunc->vkFreeMemory (device->dev, bctx->vertex_memory, 0); + } + if (bctx->index_buffer) { + dfunc->vkDestroyBuffer (device->dev, bctx->index_buffer, 0); + dfunc->vkFreeMemory (device->dev, bctx->index_memory, 0); + } } static inline __attribute__((const)) int From 1080c89a268de9bb5650068bcd207068c104ff1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 20 Jan 2021 16:51:35 +0900 Subject: [PATCH 1240/3664] [vulkan] Bind the bsp main pipeline No drawing commands are issued yet, but vulkan seems to be happy with the state. --- include/QF/Vulkan/qf_bsp.h | 1 + libs/video/renderer/vulkan/vulkan_bsp.c | 30 ++++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index c5a74c76e..6d4440bd6 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -59,6 +59,7 @@ typedef struct elechain_s { typedef struct bspframe_s { uint32_t *index_data; uint32_t index_count; + uint32_t index_offset; VkCommandBuffer bsp_cmd; VkCommandBuffer turb_cmd; VkCommandBuffer sky_cmd; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index eb1ccacc4..aba44c043 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -522,7 +522,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) bctx->index_buffer = QFV_CreateBuffer (device, index_buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT - | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); bctx->index_memory = QFV_AllocBufferMemory (device, bctx->index_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, @@ -535,7 +535,9 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) index_buffer_size, 0, &data); uint32_t *index_data = data; for (size_t i = 0; i < frames; i++) { - bctx->frames.a[i].index_data = index_data + index_count * i; + uint32_t offset = index_count * i; + bctx->frames.a[i].index_data = index_data + offset; + bctx->frames.a[i].index_offset = offset * sizeof (uint32_t); } } if (vertex_buffer_size > bctx->vertex_buffer_size) { @@ -809,9 +811,10 @@ bsp_begin (vulkan_ctx_t *ctx) __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - DARRAY_APPEND (cframe->subCommand, bframe->bsp_cmd); + VkCommandBuffer cmd = bframe->bsp_cmd; + DARRAY_APPEND (cframe->subCommand, cmd); - dfunc->vkResetCommandBuffer (bframe->bsp_cmd, 0); + dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, ctx->renderpass.renderpass, 0, @@ -823,7 +826,24 @@ bsp_begin (vulkan_ctx_t *ctx) VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, }; - dfunc->vkBeginCommandBuffer (bframe->bsp_cmd, &beginInfo); + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + bctx->main); + VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; + VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; + dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + + VkDeviceSize offsets[] = { 0 }; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &bctx->vertex_buffer, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, + VK_INDEX_TYPE_UINT32); + + VkDescriptorSet set = bframe->descriptors; + VkPipelineLayout layout = bctx->layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 1, &set, 0, 0); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; From e0e6677bd337143412549cb2cb21564db563d1d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 21 Jan 2021 00:40:22 +0900 Subject: [PATCH 1241/3664] [vulkan] Upload brush model textures Things aren't quite right with them (sky texture is very wrong), but the heavy lifting is done. --- include/QF/Vulkan/image.h | 2 + include/QF/Vulkan/qf_texture.h | 2 + libs/models/brush/vulkan_model_brush.c | 154 ++++++++++++++++++++ libs/video/renderer/vulkan/vulkan_texture.c | 34 ++++- 4 files changed, 184 insertions(+), 8 deletions(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 501a5025e..489c86e40 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -28,6 +28,8 @@ typedef struct qfv_imagetransitionset_s DARRAY_TYPE (qfv_imagetransition_t) qfv_imagetransitionset_t; typedef struct qfv_imagebarrierset_s DARRAY_TYPE (VkImageMemoryBarrier) qfv_imagebarrierset_t; +#define QFV_AllocImageBarrierSet(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_imagebarrierset_t, num, allocator) struct qfv_device_s; VkImage QFV_CreateImage (struct qfv_device_s *device, int cubemap, diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index 90906873c..a2ffbd38e 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -11,6 +11,8 @@ typedef struct qfv_tex_s { VkImageView view; } qfv_tex_t; +void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, + int alpha, int count); qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip); VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure)); void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex); diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 52826d280..2b5ed2021 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -48,9 +48,13 @@ #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_model.h" #include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/barrier.h" +#include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/staging.h" +#include "qfalloca.h" #include "compat.h" #include "mod_internal.h" #include "r_internal.h" @@ -96,6 +100,75 @@ get_image_size (VkImage image, qfv_device_t *device) return size; } +static void +transfer_mips (byte *dst, const void *_src, const texture_t *tx) +{ + const byte *src = _src; + unsigned width = tx->width; + unsigned height = tx->height; + unsigned count, offset; + + for (int i = 0; i < MIPLEVELS; i++) { + // mip offsets are relative to the texture pointer rather than the + // end of the texture struct + offset = tx->offsets[i] - sizeof (texture_t); + count = width * height; + Vulkan_ExpandPalette (dst, src + offset, vid.palette, 1, count); + dst += count; + width >>= 1; + height >>= 1; + } +} + +static void +copy_mips (qfv_packet_t *packet, texture_t *tx, qfv_tex_t *tex, + qfv_devfuncs_t *dfunc) +{ + // base copy + VkBufferImageCopy copy = { + tex->offset, tx->width, 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, {tx->width, tx->height, 1}, + }; + int is_sky = 0; + int sky_offset = 0; + size_t size = tx->width * tx->height * 4; + int copy_count = MIPLEVELS; + + if (strncmp (tx->name, "sky", 3) == 0) { + if (tx->width == 2 * tx->height) { + copy.imageExtent.width /= 2; + sky_offset = tx->width * 4 / 2; + } + is_sky = 1; + copy_count *= 2; + } + + __auto_type copies = QFV_AllocBufferImageCopy (copy_count, alloca); + copies->size = 0; + + for (int i = 0; i < MIPLEVELS; i++) { + __auto_type c = &copies->a[copies->size++]; + *c = copy; + if (is_sky) { + __auto_type c = &copies->a[copies->size++]; + *c = copy; + c->bufferOffset += sky_offset * 4; + c->imageSubresource.baseArrayLayer = 1; + } + copy.bufferOffset += size; + size >>= 2; + copy.bufferRowLength >>= 1; + copy.imageExtent.width >>= 1; + copy.imageExtent.height >>= 1; + sky_offset >>= 1; + } + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + tex->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + copies->size, copies->a); +} + static void load_textures (model_t *model, vulkan_ctx_t *ctx) { @@ -103,7 +176,10 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; modelctx_t *mctx = model->data; VkImage image = 0; + byte *buffer; + size_t image_count = 0; + size_t copy_count = 0; size_t memsize = 0; for (int i = 0; i < model->numtextures; i++) { texture_t *tx = model->textures[i]; @@ -113,11 +189,18 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) vulktex_t *tex = tx->render; tex->tex->offset = memsize; memsize += get_image_size (tex->tex->image, device); + image_count++; + copy_count += MIPLEVELS; + if (strncmp (tx->name, "sky", 3) == 0) { + copy_count += MIPLEVELS; + } // just so we have one in the end image = tex->tex->image; if (tex->glow) { + copy_count += MIPLEVELS; tex->glow->offset = memsize; memsize += get_image_size (tex->glow->image, device); + image_count++; } } VkDeviceMemory mem; @@ -126,6 +209,11 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) memsize, 0); mctx->texture_memory = mem; + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, memsize, 1, + ctx->cmdpool); + qfv_packet_t *packet = QFV_PacketAcquire (stage); + buffer = QFV_PacketExtend (packet, memsize); + for (int i = 0; i < model->numtextures; i++) { texture_t *tx = model->textures[i]; if (!tx) { @@ -142,6 +230,7 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) tex->tex->view = QFV_CreateImageView (device, tex->tex->image, type, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + transfer_mips (buffer + tex->tex->offset, tx + 1, tx); if (tex->glow) { dfunc->vkBindImageMemory (device->dev, tex->glow->image, mem, tex->glow->offset); @@ -151,8 +240,67 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + transfer_mips (buffer + tex->glow->offset, tex->glow->memory, tx); } } + + // base barrier + VkImageMemoryBarrier barrier; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + + __auto_type barriers = QFV_AllocImageBarrierSet (image_count, malloc); + barriers->size = 0; + for (int i = 0; i < model->numtextures; i++) { + texture_t *tx = model->textures[i]; + if (!tx) { + continue; + } + vulktex_t *tex = tx->render; + __auto_type b = &barriers->a[barriers->size++]; + *b = barrier; + b->image = tex->tex->image; + if (tex->glow) { + b = &barriers->a[barriers->size++]; + *b = barrier; + b->image = tex->glow->image; + } + } + qfv_pipelinestagepair_t stages; + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + barriers->size, barriers->a); + for (int i = 0, j = 0; i < model->numtextures; i++) { + texture_t *tx = model->textures[i]; + if (!tx) { + continue; + } + vulktex_t *tex = tx->render; + __auto_type b = &barriers->a[j++]; + b->oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + b->newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + b->srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + b->dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + copy_mips (packet, tx, tex->tex, dfunc); + if (tex->glow) { + b = &barriers->a[j++]; + b->oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + b->newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + b->srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + b->dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + copy_mips (packet, tx, tex->glow, dfunc); + } + } + + stages=imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + barriers->size, barriers->a); + QFV_PacketSubmit (packet); + QFV_DestroyStagingBuffer (stage); } void @@ -173,12 +321,18 @@ Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) } vulktex_t *tex = tx->render; + tex->texture = tx; tex->tex = (qfv_tex_t *) (tx + 1); VkExtent3D extent = { tx->width, tx->height, 1 }; int layers = 1; if (strncmp (tx->name, "sky", 3) == 0) { layers = 2; + // the sky texture is normally 2 side-by-side squares, but + // some maps have just a single square + if (tx->width == 2 * tx->height) { + extent.width /= 2; + } } tex->tex->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 05d602d63..bc95431b0 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -85,6 +85,30 @@ ilog2 (unsigned x) return y; } +void +Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, + int alpha, int count) +{ + if (alpha) { + while (count-- > 0) { + byte pix = *src++; + const byte *col = palette + pix; + *dst++ = *col++; + *dst++ = *col++; + *dst++ = *col++; + *dst++ = 0xff; + } + } else { + while (count-- > 0) { + byte pix = *src++; + const byte *col = palette + pix; + *dst++ = *col++; + *dst++ = *col++; + *dst++ = *col++; + } + } +} + qfv_tex_t * Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) { @@ -152,14 +176,8 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) byte *tex_data = QFV_PacketExtend (packet, bytes); if (tex->format == tex_palette) { - byte *data = tex->data; - for (size_t count = tex->width * tex->height; count-- > 0; ) { - byte pix = *data++; - byte *col = tex->palette + pix; - *tex_data++ = *col++; - *tex_data++ = *col++; - *tex_data++ = *col++; - } + Vulkan_ExpandPalette (tex_data, tex->data, tex->palette, + 0, tex->width * tex->height); } else { memcpy (tex_data, tex->data, bytes); } From 9e03096da6d116461a06bce1c35df4498094ebab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 21 Jan 2021 02:13:40 +0900 Subject: [PATCH 1242/3664] [vulkan] Build brush model display lists Not working particularly well yet, but no errors out of validation. --- include/QF/Vulkan/funclist.h | 1 + include/QF/Vulkan/qf_bsp.h | 11 +- libs/video/renderer/r_init.c | 1 - libs/video/renderer/vid_render_vulkan.c | 1 + libs/video/renderer/vulkan/qfpipeline.plist | 25 ++- libs/video/renderer/vulkan/quakebsp.frag | 17 ++- libs/video/renderer/vulkan/vulkan_bsp.c | 161 ++++++++++++++------ 7 files changed, 151 insertions(+), 66 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 209ee0561..b0fe394d9 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -169,6 +169,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdClearColorImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdExecuteCommands) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPushConstants) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetViewport) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 6d4440bd6..95f128e5b 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -44,7 +44,8 @@ typedef struct bspvert_s { typedef struct elements_s { struct elements_s *_next; struct elements_s *next; - byte *base; + uint32_t first_index; + uint32_t index_count; } elements_t; typedef struct elechain_s { @@ -57,9 +58,9 @@ typedef struct elechain_s { } elechain_t; typedef struct bspframe_s { - uint32_t *index_data; - uint32_t index_count; - uint32_t index_offset; + uint32_t *index_data; // pointer into mega-buffer for this frame (c) + uint32_t index_offset; // offset of index_data within mega-buffer (c) + uint32_t index_count; // number if indices queued (d) VkCommandBuffer bsp_cmd; VkCommandBuffer turb_cmd; VkCommandBuffer sky_cmd; @@ -96,6 +97,7 @@ typedef struct bspctx_s { instsurf_t **instsurfs_tail; instsurf_t *free_instsurfs; + struct qfv_tex_s *skysheet_tex; struct qfv_tex_s *skybox_tex; quat_t sky_rotation[2]; quat_t sky_velocity; @@ -110,6 +112,7 @@ typedef struct bspctx_s { struct bsppoly_s *polys; + VkSampler sampler; VkDeviceMemory texture_memory; VkPipeline main; VkPipelineLayout layout; diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 94385e1c2..733004a21 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -68,7 +68,6 @@ static U void (*const r_scrapdelete)(rscrap_t *) = R_ScrapDelete; static void R_shutdown (void *data) { - Mod_ClearAll (); if (vidrendmodule->functions->general->p_Shutdown) { vidrendmodule->functions->general->p_Shutdown (); } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 9e6dc90fd..85d090b37 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -606,6 +606,7 @@ vulkan_vid_render_shutdown (void) df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); + Mod_ClearAll (); Vulkan_Shutdown_Common (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 822e187a5..aa60ec958 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -30,6 +30,23 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; + quakebsp = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = repeat; + addressModeV = repeat; + addressModeW = repeat; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 1; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; }; descriptorPools = { twod = { @@ -110,12 +127,12 @@ descriptorCount = 1; stageFlags = fragment; }, - { + /*{ binding = 5; descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; - }, + },*/ ); }; something = { @@ -150,7 +167,7 @@ }, { stageFlags = fragment; - offset = 0; + offset = 64; size = 32; }, ); @@ -176,7 +193,7 @@ bindings = ( { binding = 0; - stride = "3 * 4 * 4"; + stride = "2 * 4 * 4"; inputRate = vertex; }, ); diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag index 219ce9212..24745fba0 100644 --- a/libs/video/renderer/vulkan/quakebsp.frag +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -4,9 +4,10 @@ layout (set = 0, binding = 1) uniform sampler2D Texture; layout (set = 0, binding = 2) uniform sampler2D Glowmap; layout (set = 0, binding = 3) uniform sampler2D Lightmap; layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; -layout (set = 0, binding = 5) uniform samplerCube SkyCube; +//layout (set = 0, binding = 5) uniform samplerCube SkyCube; layout (push_constant) uniform PushConstants { + layout (offset = 64) float time; vec4 fog; }; @@ -70,7 +71,7 @@ sky_sheet (vec3 dir, float time) return c; } - +/* vec4 sky_cube (vec3 dir, float time) { @@ -80,20 +81,22 @@ sky_cube (vec3 dir, float time) // to do here is swizzle the Y and Z coordinates return texture (SkyCube, dir.xzy); } - +*/ vec4 sky_color (vec3 dir, float time) { if (!doSkySheet) { - return sky_cube (dir, time); + return vec4 (1, 0, 1, 1); + //return sky_cube (dir, time); } if (!doSkyCube) { return sky_sheet (dir, time); } else { - // can see through the sheet (may look funny when looking down) + /*// can see through the sheet (may look funny when looking down) // maybe have 4 sheet layers instead of 2? vec4 c1 = sky_sheet (dir, time); vec4 c2 = sky_cube (dir, time); - return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); + return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a));*/ + return vec4 (1, 0, 1, 1); } } @@ -117,5 +120,5 @@ main (void) } c += texture (Glowmap, t_st); - frag_color = fogBlend (c); + frag_color = vec4(t_st, 1, 1);//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index aba44c043..d60f95bb5 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -496,10 +496,6 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) el = el->next; vertex_index_base = 0; }*/ - // we don't use it now, but pre-initializing the list won't hurt - //XXX if (!el->list) - //XXX el->list = dstring_new (); - //XXX dstring_clear (el->list); surf->polys = (glpoly_t *) poly; poly = build_surf_displist (models, surf, vertex_index_base, @@ -757,16 +753,14 @@ R_VisitWorldNodes (model_t *model, vulkan_ctx_t *ctx) visit_leaf ((mleaf_t *) node); } -/*static void -draw_elechain (elechain_t *ec, int matloc, int vertloc, int tlstloc, - int colloc, bspctx_t *bctx) +static void +draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, + VkCommandBuffer cmd) { - mat4_t mat; elements_t *el; - int count; - float *color; - if (colloc >= 0) { + /*if (colloc >= 0) { + float *color; color = ec->color; if (!color) color = bctx->default_color; @@ -774,29 +768,31 @@ draw_elechain (elechain_t *ec, int matloc, int vertloc, int tlstloc, QuatCopy (color, bctx->last_color); qfeglVertexAttrib4fv (quake_bsp.color.location, color); } - } + }*/ if (ec->transform) { - Mat4Mult (bsp_vp, ec->transform, mat); - qfeglUniformMatrix4fv (matloc, 1, false, mat); - } else { - qfeglUniformMatrix4fv (matloc, 1, false, bsp_vp); + dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, 16 * sizeof (float), ec->transform); } for (el = ec->elements; el; el = el->next) { - if (!el->list->size) + //FIXME check if these are contiguous and if so merge into one + //command + if (!el->index_count) continue; - count = el->list->size / sizeof (GLushort); - qfeglVertexAttribPointer (vertloc, 4, GL_FLOAT, - 0, sizeof (bspvert_t), - el->base + field_offset (bspvert_t, vertex)); - if (tlstloc >= 0) - qfeglVertexAttribPointer (tlstloc, 4, GL_FLOAT, - 0, sizeof (bspvert_t), - el->base + field_offset (bspvert_t,tlst)); - qfeglDrawElements (GL_TRIANGLES, count, - GL_UNSIGNED_SHORT, el->list->str); - dstring_clear (el->list); + dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index, + 0, 0); + el->first_index = 0; + el->index_count = 0; } -}*/ +} + +static VkImageView +get_view (qfv_tex_t *tex) +{ + if (tex) { + return tex->view; + } + return 0; +} static void bsp_begin (vulkan_ctx_t *ctx) @@ -814,6 +810,54 @@ bsp_begin (vulkan_ctx_t *ctx) VkCommandBuffer cmd = bframe->bsp_cmd; DARRAY_APPEND (cframe->subCommand, cmd); + VkDescriptorBufferInfo bufferInfo = { + ctx->matrices.buffer_3d, 0, VK_WHOLE_SIZE + }; + VkDescriptorImageInfo imageInfo[] = { + { bctx->sampler, + QFV_ScrapImageView (bctx->light_scrap), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, + { bctx->sampler, + QFV_ScrapImageView (bctx->light_scrap), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, + { bctx->sampler, + QFV_ScrapImageView (bctx->light_scrap), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, + { bctx->sampler, + get_view (bctx->skysheet_tex), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, + { bctx->sampler, + get_view (bctx->skybox_tex), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + bframe->descriptors, 0, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, &bufferInfo, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + bframe->descriptors, 1, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo[0], 0, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + bframe->descriptors, 2, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo[1], 0, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + bframe->descriptors, 3, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo[2], 0, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + bframe->descriptors, 4, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo[3], 0, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + bframe->descriptors, 5, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo[4], 0, 0 }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 5, write, 0, 0); + dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, @@ -1011,49 +1055,56 @@ sky_end (bspctx_t *bctx) static inline void add_surf_elements (vulktex_t *tex, instsurf_t *is, - elechain_t **ec, elements_t **el, bspctx_t *bctx) + elechain_t **ec, elements_t **el, + bspctx_t *bctx, bspframe_t *bframe) { msurface_t *surf = is->surface; - //XXX bsppoly_t *poly = (bsppoly_t *) surf->polys; + bsppoly_t *poly = (bsppoly_t *) surf->polys; if (!tex->elechain) { (*ec) = add_elechain (tex, surf->ec_index, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; - //XXX if (!(*el)->list) - //XXX (*el)->list = dstring_new (); - //XXX dstring_clear ((*el)->list); + (*el)-> first_index = bframe->index_count; } if (is->transform != (*ec)->transform || is->color != (*ec)->color) { (*ec) = add_elechain (tex, surf->ec_index, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; - //XXX if (!(*el)->list) - //XXX (*el)->list = dstring_new (); - //XXX dstring_clear ((*el)->list); + (*el)-> first_index = bframe->index_count; } - //XXX dstring_append ((*el)->list, (char *) poly->indices, - //XXX poly->count * sizeof (poly->indices[0])); + memcpy (bframe->index_data + bframe->index_count, + poly->indices, poly->count * sizeof (poly->indices[0])); + (*el)->index_count += poly->count; } static void -build_tex_elechain (vulktex_t *tex, bspctx_t *bctx) +build_tex_elechain (vulktex_t *tex, bspctx_t *bctx, bspframe_t *bframe) { instsurf_t *is; elechain_t *ec = 0; elements_t *el = 0; for (is = tex->tex_chain; is; is = is->tex_chain) { - add_surf_elements (tex, is, &ec, &el, bctx); + add_surf_elements (tex, is, &ec, &el, bctx, bframe); } } void Vulkan_DrawWorld (vulkan_ctx_t *ctx) { + static float identity[] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; entity_t worldent; clear_texture_chains (bctx); // do this first for water and skys @@ -1061,6 +1112,9 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) memset (&worldent, 0, sizeof (worldent)); worldent.model = r_worldentity.model; + vulktex_t *tex = r_worldentity.model->skytexture->render; + bctx->skysheet_tex = tex->tex; + currententity = &worldent; R_VisitWorldNodes (worldent.model, ctx); @@ -1077,24 +1131,29 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) Vulkan_FlushLightmaps (ctx); bsp_begin (ctx); + + dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, + VK_SHADER_STAGE_VERTEX_BIT, + 0, 16 * sizeof (float), identity); + float frag_pc[8] = { }; + dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, + VK_SHADER_STAGE_FRAGMENT_BIT, + 64, 8 * sizeof (float), &frag_pc); //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); for (size_t i = 0; i < bctx->texture_chains.size; i++) { vulktex_t *tex; - //XXX elechain_t *ec = 0; + elechain_t *ec = 0; tex = bctx->texture_chains.a[i]; - build_tex_elechain (tex, bctx); + build_tex_elechain (tex, bctx, bframe); //XXX if (tex->elechain) //XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); - /*XXX for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, quake_bsp.mvp_matrix.location, - quake_bsp.vertex.location, - quake_bsp.tlst.location, - quake_bsp.color.location); - }*/ + for (ec = tex->elechain; ec; ec = ec->next) { + draw_elechain (ec, bctx->layout, dfunc, bframe->bsp_cmd); + } tex->elechain = 0; tex->elechain_tail = &tex->elechain; } @@ -1152,6 +1211,7 @@ void Vulkan_DrawSky (vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; instsurf_t *is; msurface_t *surf; vulktex_t *tex = 0; @@ -1180,7 +1240,7 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) } tex = surf->texinfo->texture->render; } - add_surf_elements (tex, is, &ec, &el, bctx); + add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { if (!bctx->skybox_tex) { @@ -1230,6 +1290,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp.main"); bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp"); + bctx->sampler = QFV_GetSampler (ctx, "quakebsp"); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); for (size_t i = 0; i < layouts->size; i++) { From 2c1a335715a9531b50266b802af44e1d9a423cfb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 21 Jan 2021 12:39:08 +0900 Subject: [PATCH 1243/3664] [vulkan] Use vkCmdPushDescriptorSetKHR for bsp This makes switching textures on the fly much easier. --- include/QF/Vulkan/funclist.h | 1 + include/QF/Vulkan/qf_bsp.h | 1 - libs/video/renderer/vulkan/qfpipeline.plist | 15 +------- libs/video/renderer/vulkan/vulkan_bsp.c | 35 ++++++++----------- .../video/renderer/vulkan/vulkan_vid_common.c | 2 ++ 5 files changed, 18 insertions(+), 36 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index b0fe394d9..90c3a51d2 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -170,6 +170,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdClearColorImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdExecuteCommands) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPushConstants) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPushDescriptorSetKHR) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetViewport) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 95f128e5b..5b01da407 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -64,7 +64,6 @@ typedef struct bspframe_s { VkCommandBuffer bsp_cmd; VkCommandBuffer turb_cmd; VkCommandBuffer sky_cmd; - VkDescriptorSet descriptors; } bspframe_t; typedef struct bspframeset_s diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index aa60ec958..fee54e446 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -63,20 +63,6 @@ }, ); }; - quakebsp = { - flags = 0; - maxSets = $framebuffers.size; - bindings = ( - { - type = uniform_buffer; - descriptorCount = $framebuffers.size; - }, - { - type = combined_image_sampler; - descriptorCount = "5z * $framebuffers.size"; - }, - ); - }; }; setLayouts = { twod = { @@ -96,6 +82,7 @@ ); }; quakebsp = { + flags = push_descriptor; bindings = ( { binding = 0; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index d60f95bb5..5d7c9efc2 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -831,32 +831,31 @@ bsp_begin (vulkan_ctx_t *ctx) VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, }; VkWriteDescriptorSet write[] = { - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - bframe->descriptors, 0, 0, 1, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &bufferInfo, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - bframe->descriptors, 1, 0, 1, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo[0], 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - bframe->descriptors, 2, 0, 1, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 2, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo[1], 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - bframe->descriptors, 3, 0, 1, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 3, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo[2], 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - bframe->descriptors, 4, 0, 1, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 4, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo[3], 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - bframe->descriptors, 5, 0, 1, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 5, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo[4], 0, 0 }, }; - dfunc->vkUpdateDescriptorSets (device->dev, 5, write, 0, 0); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { @@ -884,10 +883,8 @@ bsp_begin (vulkan_ctx_t *ctx) dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, VK_INDEX_TYPE_UINT32); - VkDescriptorSet set = bframe->descriptors; - VkPipelineLayout layout = bctx->layout; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 1, &set, 0, 0); + dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + bctx->layout, 0, 5, write); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -1296,20 +1293,16 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) for (size_t i = 0; i < layouts->size; i++) { layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "quakebsp"); } - __auto_type pool = QFV_GetDescriptorPool (ctx, "quakebsp"); __auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); - __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < frames; i++) { __auto_type bframe = &bctx->frames.a[i]; - bframe->descriptors = sets->a[i]; bframe->bsp_cmd = cmdBuffers->a[i]; bframe->turb_cmd = cmdBuffers->a[i]; bframe->sky_cmd = cmdBuffers->a[i]; } - free (sets); } void diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 3d317f52c..d9220307b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -132,11 +132,13 @@ Vulkan_Init_Cvars (void) static const char *instance_extensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, + VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 0, }; static const char *device_extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, 0, }; From eb9807576dedd70cc64396e31ee427007200176a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 21 Jan 2021 14:37:39 +0900 Subject: [PATCH 1244/3664] [vulkan] Fix the bsp vertex index list creation There's still a problem with the vertex data itself not getting sent to the GPU properly, but vulkan is now happy with my tiny test map (which required disabling skies entirely until I get null textures working). --- libs/video/renderer/vulkan/qfpipeline.plist | 4 +-- libs/video/renderer/vulkan/quakebsp.frag | 18 ++++++------- libs/video/renderer/vulkan/vulkan_bsp.c | 29 +++++++-------------- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index fee54e446..26c3965ac 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -108,13 +108,13 @@ descriptorCount = 1; stageFlags = fragment; }, - { + /*{ binding = 4; descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; }, - /*{ + { binding = 5; descriptorType = combined_image_sampler; descriptorCount = 1; diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag index 24745fba0..21c26dfaa 100644 --- a/libs/video/renderer/vulkan/quakebsp.frag +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -3,7 +3,7 @@ layout (set = 0, binding = 1) uniform sampler2D Texture; layout (set = 0, binding = 2) uniform sampler2D Glowmap; layout (set = 0, binding = 3) uniform sampler2D Lightmap; -layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; +//layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; //layout (set = 0, binding = 5) uniform samplerCube SkyCube; layout (push_constant) uniform PushConstants { @@ -46,7 +46,7 @@ fogBlend (vec4 color) return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); } - +/* vec4 sky_sheet (vec3 dir, float time) { @@ -71,7 +71,7 @@ sky_sheet (vec3 dir, float time) return c; } -/* + vec4 sky_cube (vec3 dir, float time) { @@ -81,7 +81,7 @@ sky_cube (vec3 dir, float time) // to do here is swizzle the Y and Z coordinates return texture (SkyCube, dir.xzy); } -*/ + vec4 sky_color (vec3 dir, float time) { @@ -91,15 +91,15 @@ sky_color (vec3 dir, float time) } if (!doSkyCube) { return sky_sheet (dir, time); } else { - /*// can see through the sheet (may look funny when looking down) + // can see through the sheet (may look funny when looking down) // maybe have 4 sheet layers instead of 2? vec4 c1 = sky_sheet (dir, time); vec4 c2 = sky_cube (dir, time); - return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a));*/ + return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); return vec4 (1, 0, 1, 1); } } - +*/ void main (void) { @@ -110,11 +110,11 @@ main (void) if (doWarp) { t_st = warp_st (t_st, time); } - if (doSkyCube || doSkySheet) { + /*if (doSkyCube || doSkySheet) { c = sky_color (direction, time); } else { c = texture (Texture, t_st); - } + }*/ if (doLight) { c *= texture (Lightmap, l_st); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 5d7c9efc2..cf6e6dda2 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -33,9 +33,6 @@ # include "config.h" #endif -#define NH_DEFINE -//#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -337,7 +334,7 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, numverts = fa->numedges; numindices = numverts + 1; verts = *vert_list; - // surf->polys is set to the next slow before the call + // surf->polys is set to the next slot before the call poly = (bsppoly_t *) fa->polys; poly->count = numindices; for (i = 0, ind = poly->indices; i < numverts; i++) { @@ -474,7 +471,6 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) vulktex_t *tex; instsurf_t *is; elechain_t *ec = 0; - //elements_t *el = 0; tex = bctx->texture_chains.a[i]; @@ -482,20 +478,10 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) msurface_t *surf = is->surface; if (!tex->elechain) { ec = add_elechain (tex, surf->ec_index, bctx); - //el = ec->elements; - vertex_index_base = 0; } if (surf->ec_index != ec->index) { // next sub-model ec = add_elechain (tex, surf->ec_index, bctx); - //el = ec->elements; - vertex_index_base = 0; } - /*if (vertex_index_base + surf->numedges > 65535) { - // elements index overflow - el->next = get_elements (bctx); - el = el->next; - vertex_index_base = 0; - }*/ surf->polys = (glpoly_t *) poly; poly = build_surf_displist (models, surf, vertex_index_base, @@ -534,6 +520,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) uint32_t offset = index_count * i; bctx->frames.a[i].index_data = index_data + offset; bctx->frames.a[i].index_offset = offset * sizeof (uint32_t); + bctx->frames.a[i].index_count = 0; } } if (vertex_buffer_size > bctx->vertex_buffer_size) { @@ -884,7 +871,7 @@ bsp_begin (vulkan_ctx_t *ctx) VK_INDEX_TYPE_UINT32); dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, 0, 5, write); + bctx->layout, 0, 4, write); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -1063,18 +1050,19 @@ add_surf_elements (vulktex_t *tex, instsurf_t *is, (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; - (*el)-> first_index = bframe->index_count; + (*el)->first_index = bframe->index_count; } if (is->transform != (*ec)->transform || is->color != (*ec)->color) { (*ec) = add_elechain (tex, surf->ec_index, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; - (*el)-> first_index = bframe->index_count; + (*el)->first_index = bframe->index_count; } memcpy (bframe->index_data + bframe->index_count, poly->indices, poly->count * sizeof (poly->indices[0])); (*el)->index_count += poly->count; + bframe->index_count += poly->count; } static void @@ -1105,12 +1093,13 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) entity_t worldent; clear_texture_chains (bctx); // do this first for water and skys + bframe->index_count = 0; memset (&worldent, 0, sizeof (worldent)); worldent.model = r_worldentity.model; - vulktex_t *tex = r_worldentity.model->skytexture->render; - bctx->skysheet_tex = tex->tex; + //vulktex_t *tex = r_worldentity.model->skytexture->render; + //bctx->skysheet_tex = tex->tex; currententity = &worldent; From 94b589567b7ec36c94a1ba40ab0307481424ec62 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 21 Jan 2021 16:39:11 +0900 Subject: [PATCH 1245/3664] [vulkan] Rename texture.c to scrap.c I had originally planned on mixing the stage management with general texture support code like I did in glsl, but I think that was a mistake and I did keep looking for scrap.[ch] when I wanted to edit something to do with the scrap... --- include/QF/Vulkan/{texture.h => scrap.h} | 6 +++--- libs/video/renderer/Makemodule.am | 2 +- libs/video/renderer/vulkan/{texture.c => scrap.c} | 6 +++--- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- libs/video/renderer/vulkan/vulkan_lightmap.c | 2 +- libs/video/renderer/vulkan/vulkan_texture.c | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) rename include/QF/Vulkan/{texture.h => scrap.h} (87%) rename libs/video/renderer/vulkan/{texture.c => scrap.c} (99%) diff --git a/include/QF/Vulkan/texture.h b/include/QF/Vulkan/scrap.h similarity index 87% rename from include/QF/Vulkan/texture.h rename to include/QF/Vulkan/scrap.h index 35aaf5bb5..563a46cc2 100644 --- a/include/QF/Vulkan/texture.h +++ b/include/QF/Vulkan/scrap.h @@ -1,5 +1,5 @@ -#ifndef __QF_Vulkan_texture_h -#define __QF_Vulkan_texture_h +#ifndef __QF_Vulkan_scrap_h +#define __QF_Vulkan_scrap_h #include "QF/image.h" @@ -21,4 +21,4 @@ void *QFV_SubpicBatch (subpic_t *subpic, struct qfv_stagebuf_s *stage); void QFV_ScrapFlush (scrap_t *scrap); -#endif//__QF_Vulkan_texture_h +#endif//__QF_Vulkan_scrap_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index a200747ff..5a30c9f0c 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -229,10 +229,10 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/namehack.h \ libs/video/renderer/vulkan/pipeline.c \ libs/video/renderer/vulkan/renderpass.c \ + libs/video/renderer/vulkan/scrap.c \ libs/video/renderer/vulkan/shader.c \ libs/video/renderer/vulkan/staging.c \ libs/video/renderer/vulkan/swapchain.c \ - libs/video/renderer/vulkan/texture.c \ libs/video/renderer/vulkan/util.c \ libs/video/renderer/vulkan/util.h \ libs/video/renderer/vulkan/vkparse.c \ diff --git a/libs/video/renderer/vulkan/texture.c b/libs/video/renderer/vulkan/scrap.c similarity index 99% rename from libs/video/renderer/vulkan/texture.c rename to libs/video/renderer/vulkan/scrap.c index 112c71a92..6e17e786c 100644 --- a/libs/video/renderer/vulkan/texture.c +++ b/libs/video/renderer/vulkan/scrap.c @@ -1,7 +1,7 @@ /* - texuture.c + scrap.c - Vulkan texuture manager + Vulkan scrap manager Copyright (C) 2021 Bill Currie @@ -54,8 +54,8 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" -#include "QF/Vulkan/texture.h" #include "r_scrap.h" #include "vid_vulkan.h" diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index cf6e6dda2..d8c45d556 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -59,8 +59,8 @@ #include "QF/Vulkan/command.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" -#include "QF/Vulkan/texture.h" #include "r_internal.h" #include "vid_vulkan.h" diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index cca17f727..7345fccd5 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -59,8 +59,8 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" -#include "QF/Vulkan/texture.h" #include "r_internal.h" #include "vid_vulkan.h" diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 495864d9f..01025e110 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -49,7 +49,7 @@ #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" -#include "QF/Vulkan/texture.h" +#include "QF/Vulkan/scrap.h" #include "compat.h" #include "r_internal.h" diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index bc95431b0..a35498fef 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -56,8 +56,8 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" -#include "QF/Vulkan/texture.h" #include "r_scrap.h" #include "vid_vulkan.h" From dc79a8a935cfb3d2fffe2705a379b7fa82f70892 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 21 Jan 2021 17:13:17 +0900 Subject: [PATCH 1246/3664] [vulkan] Clear scrap image on creation And fix the transitions in ScrapFlush. --- include/QF/Vulkan/barrier.h | 1 + include/QF/Vulkan/scrap.h | 2 +- libs/video/renderer/vulkan/barrier.c | 12 ++++++++ libs/video/renderer/vulkan/scrap.c | 35 +++++++++++++++++++++--- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h index 12cea49ab..56438aeba 100644 --- a/include/QF/Vulkan/barrier.h +++ b/include/QF/Vulkan/barrier.h @@ -11,6 +11,7 @@ typedef struct { enum { qfv_LT_Undefined_to_TransferDst, qfv_LT_TransferDst_to_ShaderReadOnly, + qfv_LT_ShaderReadOnly_to_TransferDst, qfv_LT_Undefined_to_DepthStencil, qfv_LT_Undefined_to_Color, }; diff --git a/include/QF/Vulkan/scrap.h b/include/QF/Vulkan/scrap.h index 563a46cc2..80c95bd96 100644 --- a/include/QF/Vulkan/scrap.h +++ b/include/QF/Vulkan/scrap.h @@ -9,7 +9,7 @@ struct qfv_stagebuf_s; struct qfv_device_s; scrap_t *QFV_CreateScrap (struct qfv_device_s *device, int size, - QFFormat format); + QFFormat format, struct qfv_stagebuf_s *stage); size_t QFV_ScrapSize (scrap_t *scrap); void QFV_ScrapClear (scrap_t *scrap); void QFV_DestroyScrap (scrap_t *scrap); diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c index e257eb990..935b370e0 100644 --- a/libs/video/renderer/vulkan/barrier.c +++ b/libs/video/renderer/vulkan/barrier.c @@ -50,6 +50,15 @@ const VkImageMemoryBarrier imageLayoutTransitionBarriers[] = { VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } }, + // shader read only optimal -> transfer dst optimal + { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, // undefined -> depth stencil attachment optimal { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, 0, @@ -80,6 +89,9 @@ const qfv_pipelinestagepair_t imageLayoutTransitionStages[] = { // transfer dst optimal -> shader read only optimal { VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, + // shader read only optimal -> transfer dst optimal + { VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT }, // undefined -> depth stencil attachment optimal { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT }, diff --git a/libs/video/renderer/vulkan/scrap.c b/libs/video/renderer/vulkan/scrap.c index 6e17e786c..bc5efeda5 100644 --- a/libs/video/renderer/vulkan/scrap.c +++ b/libs/video/renderer/vulkan/scrap.c @@ -76,8 +76,10 @@ struct scrap_s { }; scrap_t * -QFV_CreateScrap (qfv_device_t *device, int size, QFFormat format) +QFV_CreateScrap (qfv_device_t *device, int size, QFFormat format, + qfv_stagebuf_t *stage) { + qfv_devfuncs_t *dfunc = device->funcs; int bpp = 0; VkFormat fmt = VK_FORMAT_UNDEFINED; @@ -132,6 +134,32 @@ QFV_CreateScrap (qfv_device_t *device, int size, QFFormat format) scrap->batch_tail = &scrap->batch; scrap->batch_free = 0; scrap->batch_count = 0; + + VkImageMemoryBarrier barrier; + qfv_pipelinestagepair_t stages; + + qfv_packet_t *packet = QFV_PacketAcquire (stage); + // no data for the packet + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + barrier.image = scrap->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + VkClearColorValue color = { + float32:{0xde/255.0, 0xad/255.0, 0xbe/255.0, 0xef/255.0}, + }; + VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + dfunc->vkCmdClearColorImage (packet->cmd, scrap->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &color, 1, &range); + stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier.image = scrap->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + QFV_PacketSubmit (packet); return scrap; } @@ -286,12 +314,11 @@ QFV_ScrapFlush (scrap_t *scrap) copy->a[i].imageExtent.depth = 1; } - VkImageMemoryBarrier barrier; qfv_pipelinestagepair_t stages; - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + stages = imageLayoutTransitionStages[qfv_LT_ShaderReadOnly_to_TransferDst]; + barrier=imageLayoutTransitionBarriers[qfv_LT_ShaderReadOnly_to_TransferDst]; barrier.image = scrap->image; dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index d8c45d556..f485b0259 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1262,7 +1262,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->elementss_tail = &bctx->elementss; bctx->instsurfs_tail = &bctx->instsurfs; - bctx->light_scrap = QFV_CreateScrap (device, 2048, tex_frgba); + bctx->light_scrap = QFV_CreateScrap (device, 2048, tex_frgba, ctx->staging); size_t size = QFV_ScrapSize (bctx->light_scrap); bctx->light_stage = QFV_CreateStagingBuffer (device, size, 3, ctx->cmdpool); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 7345fccd5..2e41e2252 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -367,9 +367,9 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) 0, 0); create_quad_buffers (ctx); - dctx->scrap = QFV_CreateScrap (device, 2048, tex_rgba); dctx->stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024, 4, ctx->cmdpool); + dctx->scrap = QFV_CreateScrap (device, 2048, tex_rgba, dctx->stage); dctx->sampler = QFV_GetSampler (ctx, "quakepic"); qpic_t *charspic = Draw_Font8x8Pic (); From 2acdaa02525f3c13dcf93d32540f3e7ebb618806 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 21 Jan 2021 21:24:54 +0900 Subject: [PATCH 1247/3664] [vulkan] Fix a pile of data upload issues Copying data from the wrong buffer was the cause of the corrupted brush model vertices, and then lots of little errors (mostly forgetting to multiply by bpp) for textures. --- libs/models/brush/vulkan_model_brush.c | 10 ++++++---- libs/video/renderer/vulkan/qfpipeline.plist | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- libs/video/renderer/vulkan/vulkan_lightmap.c | 7 ++++--- libs/video/renderer/vulkan/vulkan_texture.c | 4 ++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 2b5ed2021..e40a76e28 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -114,7 +114,7 @@ transfer_mips (byte *dst, const void *_src, const texture_t *tx) offset = tx->offsets[i] - sizeof (texture_t); count = width * height; Vulkan_ExpandPalette (dst, src + offset, vid.palette, 1, count); - dst += count; + dst += count * 4; width >>= 1; height >>= 1; } @@ -126,7 +126,7 @@ copy_mips (qfv_packet_t *packet, texture_t *tx, qfv_tex_t *tex, { // base copy VkBufferImageCopy copy = { - tex->offset, tx->width, 0, + tex->offset, tx->width, tx->height, {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, {0, 0, 0}, {tx->width, tx->height, 1}, }; @@ -153,14 +153,16 @@ copy_mips (qfv_packet_t *packet, texture_t *tx, qfv_tex_t *tex, if (is_sky) { __auto_type c = &copies->a[copies->size++]; *c = copy; - c->bufferOffset += sky_offset * 4; + c->bufferOffset += sky_offset; c->imageSubresource.baseArrayLayer = 1; } copy.bufferOffset += size; size >>= 2; copy.bufferRowLength >>= 1; + copy.bufferImageHeight >>= 1; copy.imageExtent.width >>= 1; copy.imageExtent.height >>= 1; + copy.imageSubresource.mipLevel++; sky_offset >>= 1; } dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, @@ -322,7 +324,7 @@ Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) vulktex_t *tex = tx->render; tex->texture = tx; - tex->tex = (qfv_tex_t *) (tx + 1); + tex->tex = (qfv_tex_t *) (tex + 1); VkExtent3D extent = { tx->width, tx->height, 1 }; int layers = 1; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 26c3965ac..094f49948 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -43,7 +43,7 @@ compareEnable = false; compareOp = always; minLod = 0; - maxLod = 1; + maxLod = 4; borderColor = float_transparent_black; unnormalizedCoordinates = false; }; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index f485b0259..b0b4c2162 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -552,7 +552,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, 0, 1, &wr_barrier, 0, 0); VkBufferCopy copy_region = { packet->offset, 0, vertex_buffer_size }; - dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, + dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, bctx->vertex_buffer, 1, ©_region); VkBufferMemoryBarrier rd_barrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 01025e110..30118e484 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -164,9 +164,10 @@ Vulkan_BuildLightMap (msurface_t *surf, vulkan_ctx_t *ctx) surf->cached_light[maps] = scale; // 8.8 fraction out = block; for (i = 0; i < smax * tmax; i++) { - *out++ += *lightmap++ * scale / 256.0; - *out++ += *lightmap++ * scale / 256.0; - *out++ += *lightmap++ * scale / 256.0; + *out++ += *lightmap++ * scale / 65536.0; + *out++ += *lightmap++ * scale / 65536.0; + *out++ += *lightmap++ * scale / 65536.0; + *out++ = 1; } } } diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index a35498fef..295d1a89d 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -92,7 +92,7 @@ Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, if (alpha) { while (count-- > 0) { byte pix = *src++; - const byte *col = palette + pix; + const byte *col = palette + pix * 3; *dst++ = *col++; *dst++ = *col++; *dst++ = *col++; @@ -101,7 +101,7 @@ Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, } else { while (count-- > 0) { byte pix = *src++; - const byte *col = palette + pix; + const byte *col = palette + pix * 3; *dst++ = *col++; *dst++ = *col++; *dst++ = *col++; From f96d7109af39e5b1f5bf0becd197d70ccc9c3dbc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 22 Jan 2021 02:13:58 +0900 Subject: [PATCH 1248/3664] [vulkan] Fix a pure warning Need to do more testing with optimized builds, but... --- include/QF/Vulkan/scrap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/Vulkan/scrap.h b/include/QF/Vulkan/scrap.h index 80c95bd96..b4818d558 100644 --- a/include/QF/Vulkan/scrap.h +++ b/include/QF/Vulkan/scrap.h @@ -10,7 +10,7 @@ struct qfv_device_s; scrap_t *QFV_CreateScrap (struct qfv_device_s *device, int size, QFFormat format, struct qfv_stagebuf_s *stage); -size_t QFV_ScrapSize (scrap_t *scrap); +size_t QFV_ScrapSize (scrap_t *scrap) __attribute__((pure)); void QFV_ScrapClear (scrap_t *scrap); void QFV_DestroyScrap (scrap_t *scrap); VkImageView QFV_ScrapImageView (scrap_t *scrap) __attribute__((pure)); From 7e7b82086cf6384bebec038f9a8d7cacdd688b6c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 22 Jan 2021 02:18:39 +0900 Subject: [PATCH 1249/3664] [vulkan] Round up the staging buffer size Vulkan validation (quite rightly) doesn't like it when the flush range goes past the end of the buffer, but also doesn't like it when the flush range isn't cache-line aligned, so align the size of the buffer, too. --- include/QF/Vulkan/staging.h | 1 + libs/video/renderer/vulkan/staging.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/QF/Vulkan/staging.h b/include/QF/Vulkan/staging.h index aaac5d749..e8cf18ae7 100644 --- a/include/QF/Vulkan/staging.h +++ b/include/QF/Vulkan/staging.h @@ -17,6 +17,7 @@ typedef struct qfv_stagebuf_s { size_t num_packets;///< number of packets in array size_t next_packet;///< index of the next packet to be used size_t size; ///< actual size of the buffer + size_t atom_mask; ///< for flush size rounding size_t end; ///< effective end of the buffer due to early wrap size_t head; size_t tail; diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 68bf6a9aa..613422b2b 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -58,10 +58,13 @@ qfv_stagebuf_t * QFV_CreateStagingBuffer (qfv_device_t *device, size_t size, int num_packets, VkCommandPool cmdPool) { + size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; qfv_devfuncs_t *dfunc = device->funcs; qfv_stagebuf_t *stage = malloc (sizeof (qfv_stagebuf_t) + num_packets * sizeof (qfv_packet_t)); + stage->atom_mask = atom - 1; + size = (size + stage->atom_mask) & ~stage->atom_mask; stage->device = device; stage->buffer = QFV_CreateBuffer (device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); @@ -119,9 +122,8 @@ QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size) qfv_device_t *device = stage->device; qfv_devfuncs_t *dfunc = device->funcs; - size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; - offset &= ~(atom - 1); - size = (size + atom - 1) & ~ (atom - 1); + offset &= ~stage->atom_mask; + size = (size + stage->atom_mask) & ~stage->atom_mask; VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, stage->memory, offset, size From c75568c1cf11c9c1ea457bf95c72cdbb5fb0ba47 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 22 Jan 2021 02:20:32 +0900 Subject: [PATCH 1250/3664] [vulkan] Get wall rendering partially working Many surfaces are missing (I suspect it's due to transform stage management in the index emitter), and currently only the light maps are rendered (still not binding the correct textures), but the basics are working. --- libs/video/renderer/vulkan/qfpipeline.plist | 2 +- libs/video/renderer/vulkan/quakebsp.frag | 5 +++-- libs/video/renderer/vulkan/quakebsp.vert | 2 +- libs/video/renderer/vulkan/scrap.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 20 ++++++++++++++++++++ libs/video/renderer/vulkan/vulkan_main.c | 7 ++++--- libs/video/renderer/vulkan/vulkan_matrices.c | 6 +++--- 7 files changed, 33 insertions(+), 11 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 094f49948..9b0a6a1d7 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -195,7 +195,7 @@ location = 1; binding = 0; format = r32g32b32a32_sfloat; - offset = 8; + offset = 16; }, ); }; diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag index 21c26dfaa..d79408bf9 100644 --- a/libs/video/renderer/vulkan/quakebsp.frag +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -115,10 +115,11 @@ main (void) } else { c = texture (Texture, t_st); }*/ + c = texture (Texture, t_st); if (doLight) { c *= texture (Lightmap, l_st); } c += texture (Glowmap, t_st); - - frag_color = vec4(t_st, 1, 1);//fogBlend (c); + c = texture (Lightmap, l_st); + frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/quakebsp.vert b/libs/video/renderer/vulkan/quakebsp.vert index bb9e87e4a..efc03bac8 100644 --- a/libs/video/renderer/vulkan/quakebsp.vert +++ b/libs/video/renderer/vulkan/quakebsp.vert @@ -20,6 +20,6 @@ void main (void) { gl_Position = Projection * (View * (Model * vertex)); - direction = (Sky * vertex).xyz; + direction = vertex.xyz;//(Sky * vertex).xyz; tl_st = tl_uv; } diff --git a/libs/video/renderer/vulkan/scrap.c b/libs/video/renderer/vulkan/scrap.c index bc5efeda5..27c2ea3bd 100644 --- a/libs/video/renderer/vulkan/scrap.c +++ b/libs/video/renderer/vulkan/scrap.c @@ -270,7 +270,7 @@ QFV_SubpicBatch (subpic_t *subpic, qfv_stagebuf_t *stage) dest = QFV_PacketExtend (scrap->packet, size); } if (!dest) { - printf ("could not get space for update\n"); + printf ("scrap: could not get space for update\n"); return 0; } } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index b0b4c2162..18e7d2c49 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -59,6 +59,7 @@ #include "QF/Vulkan/command.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" @@ -450,9 +451,13 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } } + size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + size_t atom_mask = atom - 1; size_t frames = bctx->frames.size; size_t index_buffer_size = index_count * frames * sizeof (uint32_t); size_t vertex_buffer_size = vertex_count * sizeof (bspvert_t); + + index_buffer_size = (index_buffer_size + atom_mask) & ~atom_mask; stage = QFV_CreateStagingBuffer (device, vertex_buffer_size, 1, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); @@ -1144,6 +1149,21 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) tex->elechain_tail = &tex->elechain; } bsp_end (ctx); + + size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + size_t atom_mask = atom - 1; + size_t offset = bframe->index_offset; + size_t size = bframe->index_count * sizeof (uint32_t); + + offset &= ~atom_mask; + size = (size + atom_mask) & ~atom_mask; + + //FIXME this needs to come at the end of the frame after all passes + VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + bctx->index_memory, offset, size + }; + dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); } void diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 1e1913de9..f31558e7b 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -78,7 +78,8 @@ setup_frame (vulkan_ctx_t *ctx) static void setup_view (vulkan_ctx_t *ctx) { - float *mat = ctx->matrices.view_3d; + mat4_t mat; + float *view = ctx->matrices.view_3d; static mat4_t z_up = { 0, 0, -1, 0, -1, 0, 0, 0, @@ -98,11 +99,11 @@ setup_view (vulkan_ctx_t *ctx) VectorCopy (vup, mat + 8); mat[15] = 1; Mat4Transpose (mat, mat);//AngleVectors gives the transpose of what we want - Mat4Mult (z_up, mat, glsl_view); + Mat4Mult (z_up, mat, view); Mat4Identity (mat); VectorNegate (r_refdef.vieworg, mat + 12); - Mat4Mult (glsl_view, mat, glsl_view); + Mat4Mult (view, mat, view); } static void diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 62eb16c1d..e1a1dd13e 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -96,14 +96,14 @@ persp_mat (float *proj, float xmin, float xmax, float ymin, float ymax, proj[12] = 0; proj[1] = 0; - proj[5] = (2 * neard) / (ymax - ymin); + proj[5] = -(2 * neard) / (ymax - ymin); proj[9] = (ymax + ymin) / (ymax - ymin); proj[13] = 0; proj[2] = 0; proj[6] = 0; - proj[10] = (fard + neard) / (neard - fard); - proj[14] = (2 * fard * neard) / (neard - fard); + proj[10] = (fard) / (neard - fard); + proj[14] = (fard * neard) / (neard - fard); proj[3] = 0; proj[7] = 0; From 55badea1aedc30a1ae3a1b1cde45dad7fe9260bd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 22 Jan 2021 02:42:58 +0900 Subject: [PATCH 1251/3664] [vulkan] Reset model transform for world surfaces Fixes the misplaced walls. --- libs/video/renderer/vulkan/vulkan_bsp.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 18e7d2c49..fe7c001f4 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -67,6 +67,13 @@ #include "vid_vulkan.h" #include "vkparse.h" +static float identity[] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, +}; + #define ALLOC_CHUNK 64 typedef struct bsppoly_s { @@ -764,6 +771,10 @@ draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, if (ec->transform) { dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 16 * sizeof (float), ec->transform); + } else { + //FIXME should cache current transform + dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, 16 * sizeof (float), identity); } for (el = ec->elements; el; el = el->next) { //FIXME check if these are contiguous and if so merge into one @@ -1085,12 +1096,6 @@ build_tex_elechain (vulktex_t *tex, bspctx_t *bctx, bspframe_t *bframe) void Vulkan_DrawWorld (vulkan_ctx_t *ctx) { - static float identity[] = { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - }; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; From c016ad9f5586d520e01546709047c5cbff5559cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 22 Jan 2021 13:08:33 +0900 Subject: [PATCH 1252/3664] [vulkan] Ignore light map alpha Needed to use an rgba format to use floats (and optimal layout), but having to set the alpha to 1 even for full-dark luxels is not very efficient. Better to just ignore the alpha in the shader. Fixes the occasional transparent surface in shadowed areas. --- libs/video/renderer/vulkan/quakebsp.frag | 4 ++-- libs/video/renderer/vulkan/vulkan_lightmap.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag index d79408bf9..916581292 100644 --- a/libs/video/renderer/vulkan/quakebsp.frag +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -117,9 +117,9 @@ main (void) }*/ c = texture (Texture, t_st); if (doLight) { - c *= texture (Lightmap, l_st); + c *= vec4 (texture (Lightmap, l_st).xyz, 1); } c += texture (Glowmap, t_st); - c = texture (Lightmap, l_st); + c = vec4(texture (Lightmap, l_st).xyz, 1); frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 30118e484..6c74ab802 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -167,7 +167,7 @@ Vulkan_BuildLightMap (msurface_t *surf, vulkan_ctx_t *ctx) *out++ += *lightmap++ * scale / 65536.0; *out++ += *lightmap++ * scale / 65536.0; *out++ += *lightmap++ * scale / 65536.0; - *out++ = 1; + out++; } } } From baf25f089107292f707b6357be91e4aa7640a3b0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 22 Jan 2021 15:22:04 +0900 Subject: [PATCH 1253/3664] Document the ring buffer macros --- include/QF/ringbuffer.h | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/include/QF/ringbuffer.h b/include/QF/ringbuffer.h index cc289640e..3ec4a3407 100644 --- a/include/QF/ringbuffer.h +++ b/include/QF/ringbuffer.h @@ -28,6 +28,16 @@ #ifndef __QF_ringbuffer_h #define __QF_ringbuffer_h +/** Type declaration for a type-safe ring buffer. + * + * While not in itself thread-safe, the buffer is designed (and tested) to be + * used in a threaded environment using sutable locking mechanisms. + * + * \param type The type of data element stored in the ring buffer. + * \param size The number of objects in the ring buffer. Note that the + * actual capacity of the buffer is `size - 1` due to the + * way ring buffers work. + */ #define RING_BUFFER(type, size) \ struct { \ type buffer[size]; \ @@ -40,16 +50,46 @@ sizeof (rb->buffer) / sizeof (rb->buffer[0]); \ }) +/** Return the amount of space available for writing in the ring buffer. + * + * Use this to know how much data can be written (RB_WRITE_DATA()), or just + * to see if any space is available. + * + * \note Does NOT affect buffer state. + * + * \param ring_buffer The ring buffer to check for available space. + */ #define RB_SPACE_AVAILABLE(ring_buffer) \ ({ __auto_type rb = &(ring_buffer); \ (rb->tail + RB_buffer_size(rb) - rb->head - 1) % RB_buffer_size(rb);\ }) +/** Return the number of objects available in the ring buffer. + * + * Use this to know how much data can be read (RB_READ_DATA()) or discarded + * (RB_DROP_DATA()), or just to see if any data is available. + * + * \note Does NOT affect buffer state. + * + * \param ring_buffer The ring buffer to check for available data. + */ #define RB_DATA_AVAILABLE(ring_buffer) \ ({ __auto_type rb = &(ring_buffer); \ (rb->head + RB_buffer_size (rb) - rb->tail) % RB_buffer_size (rb); \ }) +/** Write \a count objects from \a data to the buffer, wrapping if necessary. + * + * \note Affects buffer state (advances the head). + * + * \note Does NOT check that the space is available. It is the caller's + * responsitiblity to do so using RB_SPACE_AVAILABLE(). + * + * \param ring_buffer The ring buffer to which the data will be written. + * \param data Pointer to the data to be copied into the ring buffer. + * \param count unsigned int. The number of objects to copy from + * \a data + */ #define RB_WRITE_DATA(ring_buffer, data, count) \ ({ __auto_type rb = &(ring_buffer); \ const typeof (rb->buffer[0]) *d = (data); \ @@ -66,6 +106,19 @@ memcpy (rb->buffer + h, d, c * sizeof (rb->buffer[0])); \ }) +/** Read \a count objects from the buffer to \a data, wrapping if necessary. + * + * \note Affects buffer state (advances the tail). + * + * \note Does NOT check that the data is available. It is the caller's + * responsitiblity to do so using RB_DATA_AVAILABLE(). + * + * \param ring_buffer The ring buffer from which the data will be read. + * \param data Pointer to the location into which data will be copied + * from the ring buffer. + * \param count unsigned int. The number of objects to copy from + * the buffer into \a data + */ #define RB_READ_DATA(ring_buffer, data, count) \ ({ __auto_type rb = &(ring_buffer); \ typeof (&rb->buffer[0]) d = (data); \ @@ -83,6 +136,17 @@ rb->tail = (t + oc) % RB_buffer_size (rb); \ }) +/** Discard \a count objects from the ring buffer. + * + * \note Affects buffer state (advances the tail). + * + * \note Does NOT check that the data is available. It is the caller's + * responsitiblity to do so using RB_DATA_AVAILABLE(). + * + * \param ring_buffer The ring buffer from which the objects will be + * discarded. + * \param count The number of objects to discard. + */ #define RB_DROP_DATA(ring_buffer, count) \ ({ __auto_type rb = &(ring_buffer); \ unsigned c = (count); \ @@ -90,11 +154,35 @@ rb->tail = (t + c) % RB_buffer_size (rb); \ }) +/** Read a single item from the buffer without affecting buffer state. + * + * \note Does NOT affect buffer state. + * + * \note Does NOT check that the data is available. It is the caller's + * responsitiblity to do so using RB_DATA_AVAILABLE(). + * + * \param ring_buffer The ring buffer from which to read the object. + * \param ahead The tail-relative index of the object to read from + * the buffer. Valid range is 0 to + * `RB_DATA_AVAILABLE() - 1` + */ #define RB_PEEK_DATA(ring_buffer, ahead) \ ({ __auto_type rb = &(ring_buffer); \ rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)]; \ }) +/** WRite a single item to the buffer without affecting buffer state. + * + * \note Does NOT affect buffer state. + * + * \note Does NOT check that the data is available. It is the caller's + * responsitiblity to do so using RB_DATA_AVAILABLE(). + * + * \param ring_buffer The ring buffer from which to read the object. + * \param ahead The tail-relative index of the buffer object to write. + * Valid range is 0 to `RB_DATA_AVAILABLE() - 1` + * \param data The data to write to the buffer. + */ #define RB_POKE_DATA(ring_buffer, ahead, data) \ ({ __auto_type rb = &(ring_buffer); \ rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)] = (data); \ From 07b869d1bfb12d8127ae1f0cb867de9e035d30c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 22 Jan 2021 15:23:04 +0900 Subject: [PATCH 1254/3664] Fix some doxygen warnings --- doc/quakeforge.dox.conf.in | 7 ------- include/snd_internal.h | 3 ++- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/doc/quakeforge.dox.conf.in b/doc/quakeforge.dox.conf.in index 1e925e354..3d22be413 100644 --- a/doc/quakeforge.dox.conf.in +++ b/doc/quakeforge.dox.conf.in @@ -1116,13 +1116,6 @@ CLANG_DATABASE_PATH = ALPHABETICAL_INDEX = YES -# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in -# which the alphabetical index list will be split. -# Minimum value: 1, maximum value: 20, default value: 5. -# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. - -COLS_IN_ALPHA_INDEX = 4 - # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored diff --git a/include/snd_internal.h b/include/snd_internal.h index ca4dc76c6..7978c4307 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -58,7 +58,8 @@ typedef struct sfxstream_s sfxstream_t; \param buffer sound data \param count number of frames to paint */ -typedef void sfxpaint_t (int, channel_t *, float *, unsigned); +typedef void sfxpaint_t (int offset, channel_t *ch, float *buffer, + unsigned count); /** Represent a sound sample in the mixer. */ From e6704b85e107fc00457759b04e67032c0c2ab64e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 22 Jan 2021 18:29:35 +0900 Subject: [PATCH 1255/3664] Make RB_PEEK_DATA return the address of the data This makes it a little more generally useful. --- include/QF/ringbuffer.h | 9 +- ruamoko/qwaq/builtins/curses.c | 154 ++++++++++++++++----------------- ruamoko/qwaq/builtins/input.c | 2 +- 3 files changed, 83 insertions(+), 82 deletions(-) diff --git a/include/QF/ringbuffer.h b/include/QF/ringbuffer.h index 3ec4a3407..4c7e95e74 100644 --- a/include/QF/ringbuffer.h +++ b/include/QF/ringbuffer.h @@ -154,21 +154,22 @@ rb->tail = (t + c) % RB_buffer_size (rb); \ }) -/** Read a single item from the buffer without affecting buffer state. +/** Access a single item from the buffer without affecting buffer state. * * \note Does NOT affect buffer state. * * \note Does NOT check that the data is available. It is the caller's * responsitiblity to do so using RB_DATA_AVAILABLE(). * - * \param ring_buffer The ring buffer from which to read the object. - * \param ahead The tail-relative index of the object to read from + * \param ring_buffer The ring buffer from which to access the object. + * \param ahead The tail-relative index of the object to access from * the buffer. Valid range is 0 to * `RB_DATA_AVAILABLE() - 1` + * \return Address of the accessed element */ #define RB_PEEK_DATA(ring_buffer, ahead) \ ({ __auto_type rb = &(ring_buffer); \ - rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)]; \ + &rb->buffer[(rb->tail + ahead) % RB_buffer_size (rb)]; \ }) /** WRite a single item to the buffer without affecting buffer state. diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 4f2044cf7..c54721bca 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -273,7 +273,7 @@ qwaq_wait_result (qwaq_resources_t *res, int *result, int cmd, unsigned len) { pthread_mutex_lock (&res->results_cond.mut); while (RB_DATA_AVAILABLE (res->results) < len - || RB_PEEK_DATA (res->results, 0) != cmd) { + || *RB_PEEK_DATA (res->results, 0) != cmd) { pthread_cond_wait (&res->results_cond.rcond, &res->results_cond.mut); } @@ -285,7 +285,7 @@ qwaq_wait_result (qwaq_resources_t *res, int *result, int cmd, unsigned len) static void cmd_syncprint (qwaq_resources_t *res) { - int string_id = RB_PEEK_DATA (res->command_queue, 2); + int string_id = *RB_PEEK_DATA (res->command_queue, 2); Sys_Printf ("%s\n", res->strings[string_id].str); release_string (res, string_id); @@ -294,10 +294,10 @@ cmd_syncprint (qwaq_resources_t *res) static void cmd_newwin (qwaq_resources_t *res) { - int xpos = RB_PEEK_DATA (res->command_queue, 2); - int ypos = RB_PEEK_DATA (res->command_queue, 3); - int xlen = RB_PEEK_DATA (res->command_queue, 4); - int ylen = RB_PEEK_DATA (res->command_queue, 5); + int xpos = *RB_PEEK_DATA (res->command_queue, 2); + int ypos = *RB_PEEK_DATA (res->command_queue, 3); + int xlen = *RB_PEEK_DATA (res->command_queue, 4); + int ylen = *RB_PEEK_DATA (res->command_queue, 5); window_t *window = window_new (res); window->win = newwin (ylen, xlen, ypos, xpos); @@ -311,7 +311,7 @@ cmd_newwin (qwaq_resources_t *res) static void cmd_delwin (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); window_t *window = get_window (res, __FUNCTION__, window_id); delwin (window->win); @@ -321,7 +321,7 @@ cmd_delwin (qwaq_resources_t *res) static void cmd_getwrect (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); int xpos, ypos; int xlen, ylen; @@ -339,7 +339,7 @@ cmd_getwrect (qwaq_resources_t *res) static void cmd_new_panel (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); window_t *window = get_window (res, __FUNCTION__, window_id); panel_t *panel = panel_new (res); @@ -354,7 +354,7 @@ cmd_new_panel (qwaq_resources_t *res) static void cmd_del_panel (qwaq_resources_t *res) { - int panel_id = RB_PEEK_DATA (res->command_queue, 2); + int panel_id = *RB_PEEK_DATA (res->command_queue, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); del_panel (panel->panel); @@ -364,7 +364,7 @@ cmd_del_panel (qwaq_resources_t *res) static void cmd_hide_panel (qwaq_resources_t *res) { - int panel_id = RB_PEEK_DATA (res->command_queue, 2); + int panel_id = *RB_PEEK_DATA (res->command_queue, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); hide_panel (panel->panel); @@ -373,7 +373,7 @@ cmd_hide_panel (qwaq_resources_t *res) static void cmd_show_panel (qwaq_resources_t *res) { - int panel_id = RB_PEEK_DATA (res->command_queue, 2); + int panel_id = *RB_PEEK_DATA (res->command_queue, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); show_panel (panel->panel); @@ -382,7 +382,7 @@ cmd_show_panel (qwaq_resources_t *res) static void cmd_top_panel (qwaq_resources_t *res) { - int panel_id = RB_PEEK_DATA (res->command_queue, 2); + int panel_id = *RB_PEEK_DATA (res->command_queue, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); top_panel (panel->panel); @@ -391,7 +391,7 @@ cmd_top_panel (qwaq_resources_t *res) static void cmd_bottom_panel (qwaq_resources_t *res) { - int panel_id = RB_PEEK_DATA (res->command_queue, 2); + int panel_id = *RB_PEEK_DATA (res->command_queue, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); bottom_panel (panel->panel); @@ -400,9 +400,9 @@ cmd_bottom_panel (qwaq_resources_t *res) static void cmd_move_panel (qwaq_resources_t *res) { - int panel_id = RB_PEEK_DATA (res->command_queue, 2); - int x = RB_PEEK_DATA (res->command_queue, 3); - int y = RB_PEEK_DATA (res->command_queue, 4); + int panel_id = *RB_PEEK_DATA (res->command_queue, 2); + int x = *RB_PEEK_DATA (res->command_queue, 3); + int y = *RB_PEEK_DATA (res->command_queue, 4); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); move_panel (panel->panel, y, x); @@ -411,7 +411,7 @@ cmd_move_panel (qwaq_resources_t *res) static void cmd_panel_window (qwaq_resources_t *res) { - int panel_id = RB_PEEK_DATA (res->command_queue, 2); + int panel_id = *RB_PEEK_DATA (res->command_queue, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); @@ -423,8 +423,8 @@ cmd_panel_window (qwaq_resources_t *res) static void cmd_replace_panel (qwaq_resources_t *res) { - int panel_id = RB_PEEK_DATA (res->command_queue, 2); - int window_id = RB_PEEK_DATA (res->command_queue, 3); + int panel_id = *RB_PEEK_DATA (res->command_queue, 2); + int window_id = *RB_PEEK_DATA (res->command_queue, 3); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); window_t *window = get_window (res, __FUNCTION__, window_id); @@ -447,10 +447,10 @@ cmd_doupdate (qwaq_resources_t *res) static void cmd_mvwaddstr (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int x = RB_PEEK_DATA (res->command_queue, 3); - int y = RB_PEEK_DATA (res->command_queue, 4); - int string_id = RB_PEEK_DATA (res->command_queue, 5); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int x = *RB_PEEK_DATA (res->command_queue, 3); + int y = *RB_PEEK_DATA (res->command_queue, 4); + int string_id = *RB_PEEK_DATA (res->command_queue, 5); window_t *window = get_window (res, __FUNCTION__, window_id); mvwaddstr (window->win, y, x, res->strings[string_id].str); @@ -460,8 +460,8 @@ cmd_mvwaddstr (qwaq_resources_t *res) static void cmd_waddstr (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int string_id = RB_PEEK_DATA (res->command_queue, 3); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int string_id = *RB_PEEK_DATA (res->command_queue, 3); window_t *window = get_window (res, __FUNCTION__, window_id); waddstr (window->win, res->strings[string_id].str); @@ -471,10 +471,10 @@ cmd_waddstr (qwaq_resources_t *res) static void cmd_mvwaddch (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int x = RB_PEEK_DATA (res->command_queue, 3); - int y = RB_PEEK_DATA (res->command_queue, 4); - int ch = RB_PEEK_DATA (res->command_queue, 5); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int x = *RB_PEEK_DATA (res->command_queue, 3); + int y = *RB_PEEK_DATA (res->command_queue, 4); + int ch = *RB_PEEK_DATA (res->command_queue, 5); window_t *window = get_window (res, __FUNCTION__, window_id); mvwaddch (window->win, y, x, ch); @@ -483,8 +483,8 @@ cmd_mvwaddch (qwaq_resources_t *res) static void cmd_waddch (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int ch = RB_PEEK_DATA (res->command_queue, 3); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int ch = *RB_PEEK_DATA (res->command_queue, 3); window_t *window = get_window (res, __FUNCTION__, window_id); waddch (window->win, ch); @@ -493,7 +493,7 @@ cmd_waddch (qwaq_resources_t *res) static void cmd_wrefresh (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); window_t *window = get_window (res, __FUNCTION__, window_id); wrefresh (window->win); @@ -502,9 +502,9 @@ cmd_wrefresh (qwaq_resources_t *res) static void cmd_init_pair (qwaq_resources_t *res) { - int pair = RB_PEEK_DATA (res->command_queue, 2); - int f = RB_PEEK_DATA (res->command_queue, 3); - int b = RB_PEEK_DATA (res->command_queue, 4); + int pair = *RB_PEEK_DATA (res->command_queue, 2); + int f = *RB_PEEK_DATA (res->command_queue, 3); + int b = *RB_PEEK_DATA (res->command_queue, 4); init_pair (pair, f, b); } @@ -512,8 +512,8 @@ cmd_init_pair (qwaq_resources_t *res) static void cmd_wbkgd (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int ch = RB_PEEK_DATA (res->command_queue, 3); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int ch = *RB_PEEK_DATA (res->command_queue, 3); window_t *window = get_window (res, __FUNCTION__, window_id); wbkgd (window->win, ch); @@ -522,7 +522,7 @@ cmd_wbkgd (qwaq_resources_t *res) static void cmd_werase (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); window_t *window = get_window (res, __FUNCTION__, window_id); werase (window->win); @@ -531,8 +531,8 @@ cmd_werase (qwaq_resources_t *res) static void cmd_scrollok (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int flag = RB_PEEK_DATA (res->command_queue, 3); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int flag = *RB_PEEK_DATA (res->command_queue, 3); window_t *window = get_window (res, __FUNCTION__, window_id); scrollok (window->win, flag); @@ -541,8 +541,8 @@ cmd_scrollok (qwaq_resources_t *res) static void cmd_move (qwaq_resources_t *res) { - int x = RB_PEEK_DATA (res->command_queue, 2); - int y = RB_PEEK_DATA (res->command_queue, 3); + int x = *RB_PEEK_DATA (res->command_queue, 2); + int y = *RB_PEEK_DATA (res->command_queue, 3); move (y, x); } @@ -550,7 +550,7 @@ cmd_move (qwaq_resources_t *res) static void cmd_curs_set (qwaq_resources_t *res) { - int visibility = RB_PEEK_DATA (res->command_queue, 2); + int visibility = *RB_PEEK_DATA (res->command_queue, 2); curs_set (visibility); } @@ -558,15 +558,15 @@ cmd_curs_set (qwaq_resources_t *res) static void cmd_wborder (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int ls = RB_PEEK_DATA (res->command_queue, 3); - int rs = RB_PEEK_DATA (res->command_queue, 4); - int ts = RB_PEEK_DATA (res->command_queue, 5); - int bs = RB_PEEK_DATA (res->command_queue, 6); - int tl = RB_PEEK_DATA (res->command_queue, 7); - int tr = RB_PEEK_DATA (res->command_queue, 8); - int bl = RB_PEEK_DATA (res->command_queue, 9); - int br = RB_PEEK_DATA (res->command_queue, 10); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int ls = *RB_PEEK_DATA (res->command_queue, 3); + int rs = *RB_PEEK_DATA (res->command_queue, 4); + int ts = *RB_PEEK_DATA (res->command_queue, 5); + int bs = *RB_PEEK_DATA (res->command_queue, 6); + int tl = *RB_PEEK_DATA (res->command_queue, 7); + int tr = *RB_PEEK_DATA (res->command_queue, 8); + int bl = *RB_PEEK_DATA (res->command_queue, 9); + int br = *RB_PEEK_DATA (res->command_queue, 10); window_t *window = get_window (res, __FUNCTION__, window_id); wborder (window->win, ls, rs, ts, bs, tl, tr, bl, br); @@ -575,11 +575,11 @@ cmd_wborder (qwaq_resources_t *res) static void cmd_mvwblit_line (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int x = RB_PEEK_DATA (res->command_queue, 3); - int y = RB_PEEK_DATA (res->command_queue, 4); - int chs_id = RB_PEEK_DATA (res->command_queue, 5); - int len = RB_PEEK_DATA (res->command_queue, 6); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int x = *RB_PEEK_DATA (res->command_queue, 3); + int y = *RB_PEEK_DATA (res->command_queue, 4); + int chs_id = *RB_PEEK_DATA (res->command_queue, 5); + int len = *RB_PEEK_DATA (res->command_queue, 6); int *chs = (int *) res->strings[chs_id].str; int save_x; int save_y; @@ -598,9 +598,9 @@ cmd_mvwblit_line (qwaq_resources_t *res) static void cmd_wresize (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int width = RB_PEEK_DATA (res->command_queue, 3); - int height = RB_PEEK_DATA (res->command_queue, 4); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int width = *RB_PEEK_DATA (res->command_queue, 3); + int height = *RB_PEEK_DATA (res->command_queue, 4); window_t *window = get_window (res, __FUNCTION__, window_id); wresize (window->win, height, width); @@ -609,8 +609,8 @@ cmd_wresize (qwaq_resources_t *res) static void cmd_resizeterm (qwaq_resources_t *res) { - int width = RB_PEEK_DATA (res->command_queue, 2); - int height = RB_PEEK_DATA (res->command_queue, 3); + int width = *RB_PEEK_DATA (res->command_queue, 2); + int height = *RB_PEEK_DATA (res->command_queue, 3); resizeterm (height, width); } @@ -618,11 +618,11 @@ cmd_resizeterm (qwaq_resources_t *res) static void cmd_mvwhline (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int x = RB_PEEK_DATA (res->command_queue, 3); - int y = RB_PEEK_DATA (res->command_queue, 4); - int ch = RB_PEEK_DATA (res->command_queue, 5); - int n = RB_PEEK_DATA (res->command_queue, 6); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int x = *RB_PEEK_DATA (res->command_queue, 3); + int y = *RB_PEEK_DATA (res->command_queue, 4); + int ch = *RB_PEEK_DATA (res->command_queue, 5); + int n = *RB_PEEK_DATA (res->command_queue, 6); window_t *window = get_window (res, __FUNCTION__, window_id); mvwhline (window->win, y, x, ch, n); @@ -631,11 +631,11 @@ cmd_mvwhline (qwaq_resources_t *res) static void cmd_mvwvline (qwaq_resources_t *res) { - int window_id = RB_PEEK_DATA (res->command_queue, 2); - int x = RB_PEEK_DATA (res->command_queue, 3); - int y = RB_PEEK_DATA (res->command_queue, 4); - int ch = RB_PEEK_DATA (res->command_queue, 5); - int n = RB_PEEK_DATA (res->command_queue, 6); + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int x = *RB_PEEK_DATA (res->command_queue, 3); + int y = *RB_PEEK_DATA (res->command_queue, 4); + int ch = *RB_PEEK_DATA (res->command_queue, 5); + int n = *RB_PEEK_DATA (res->command_queue, 6); window_t *window = get_window (res, __FUNCTION__, window_id); mvwvline (window->win, y, x, ch, n); @@ -645,13 +645,13 @@ static void dump_command (qwaq_resources_t *res, int len) { if (0) { - qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); + qwaq_commands cmd = *RB_PEEK_DATA (res->command_queue, 0); Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); if (cmd == qwaq_cmd_syncprint) { Sys_Printf (" "); } else { for (int i = 2; i < len; i++) { - Sys_Printf (" %d", RB_PEEK_DATA (res->command_queue, i)); + Sys_Printf (" %d", *RB_PEEK_DATA (res->command_queue, i)); } Sys_Printf ("\n"); } @@ -692,10 +692,10 @@ process_commands (qwaq_resources_t *res) // as the mutex is not released until after the data has been written to // the buffer. while ((avail = RB_DATA_AVAILABLE (res->command_queue)) >= 2 - && avail >= (len = RB_PEEK_DATA (res->command_queue, 1))) { + && avail >= (len = *RB_PEEK_DATA (res->command_queue, 1))) { pthread_mutex_unlock (&res->command_cond.mut); dump_command (res, len); - qwaq_commands cmd = RB_PEEK_DATA (res->command_queue, 0); + qwaq_commands cmd = *RB_PEEK_DATA (res->command_queue, 0); switch (cmd) { case qwaq_cmd_syncprint: cmd_syncprint (res); diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index ce2caec46..ce47b1914 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -185,7 +185,7 @@ qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event) pthread_mutex_lock (&res->event_cond.mut); unsigned last = RB_DATA_AVAILABLE (res->event_queue); if (event->what == qe_mousemove && last > 1 - && RB_PEEK_DATA(res->event_queue, last - 1).what == qe_mousemove) { + && RB_PEEK_DATA(res->event_queue, last - 1)->what == qe_mousemove) { RB_POKE_DATA(res->event_queue, last - 1, *event); merged = 1; pthread_cond_broadcast (&res->event_cond.rcond); From 328a529a94d8153e6cd85e2126c627c34f06477d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 11:56:45 +0900 Subject: [PATCH 1256/3664] Create RB_ACQUIRE and RB_RELEASE RB_RELEASE is actually RB_DROP_DATA renamed, but RB_ACQUIRE and RB_RELEASE work well when working with more structured ring buffer contents. --- include/QF/ringbuffer.h | 28 ++++++++++++++++++++++++---- ruamoko/qwaq/builtins/curses.c | 2 +- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/include/QF/ringbuffer.h b/include/QF/ringbuffer.h index 4c7e95e74..ac339ea70 100644 --- a/include/QF/ringbuffer.h +++ b/include/QF/ringbuffer.h @@ -52,8 +52,8 @@ /** Return the amount of space available for writing in the ring buffer. * - * Use this to know how much data can be written (RB_WRITE_DATA()), or just - * to see if any space is available. + * Use this to know how much data can be written (RB_WRITE_DATA()) or acquired + * (RB_ACQUIRE()), or just to see if any space is available. * * \note Does NOT affect buffer state. * @@ -67,7 +67,7 @@ /** Return the number of objects available in the ring buffer. * * Use this to know how much data can be read (RB_READ_DATA()) or discarded - * (RB_DROP_DATA()), or just to see if any data is available. + * (RB_RELEASE()), or just to see if any data is available. * * \note Does NOT affect buffer state. * @@ -106,6 +106,26 @@ memcpy (rb->buffer + h, d, c * sizeof (rb->buffer[0])); \ }) +/** Acquire \a count objects from the buffer, wrapping if necessary. + * + * \note Affects buffer state (advances the head). + * + * \note Does NOT check that the space is available. It is the caller's + * responsitiblity to do so using RB_SPACE_AVAILABLE(). + * + * \param ring_buffer The ring buffer to which the data will be written. + * \param count unsigned int. The number of objects to copy from + * \a data. + * \return Address of the first object acquired. + */ +#define RB_ACQUIRE(ring_buffer, count) \ + ({ __auto_type rb = &(ring_buffer); \ + unsigned c = (count); \ + unsigned h = rb->head; \ + rb->head = (h + c) % RB_buffer_size (rb); \ + &rb->buffer[h]; \ + }) + /** Read \a count objects from the buffer to \a data, wrapping if necessary. * * \note Affects buffer state (advances the tail). @@ -147,7 +167,7 @@ * discarded. * \param count The number of objects to discard. */ -#define RB_DROP_DATA(ring_buffer, count) \ +#define RB_RELEASE(ring_buffer, count) \ ({ __auto_type rb = &(ring_buffer); \ unsigned c = (count); \ unsigned t = rb->tail; \ diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index c54721bca..0848158f7 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -795,7 +795,7 @@ process_commands (qwaq_resources_t *res) break; } pthread_mutex_lock (&res->command_cond.mut); - RB_DROP_DATA (res->command_queue, len); + RB_RELEASE (res->command_queue, len); pthread_cond_broadcast (&res->command_cond.wcond); // unlocked at top of top if there's more data, otherwise just after // the loop From c989c8a6b631bec3cb9440f7723938b710cd8a3e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 12:01:52 +0900 Subject: [PATCH 1257/3664] [vulkan] Rewrite staging buffer packet handling It now uses the ring buffer code I wrote for qwaq (and forgot about, oops) to handle the packets themselves, and the logic for allocating and freeing space from the buffer is a bit simpler and seems to be more reliable. The automated test is a bit of a joke now, though, but coming up with good tests for it... However, nq now cycles through the demos without obvious issue under the same conditions that caused the light map update code to segfault. --- include/QF/Vulkan/staging.h | 15 +- libs/models/brush/vulkan_model_brush.c | 2 +- libs/video/renderer/vulkan/staging.c | 202 +++++++------ .../video/renderer/vulkan/test/test-staging.c | 279 +++--------------- libs/video/renderer/vulkan/vulkan_bsp.c | 6 +- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- .../video/renderer/vulkan/vulkan_vid_common.c | 2 +- 7 files changed, 159 insertions(+), 349 deletions(-) diff --git a/include/QF/Vulkan/staging.h b/include/QF/Vulkan/staging.h index e8cf18ae7..ee3678625 100644 --- a/include/QF/Vulkan/staging.h +++ b/include/QF/Vulkan/staging.h @@ -1,6 +1,8 @@ #ifndef __QF_Vulkan_staging_h #define __QF_Vulkan_staging_h +#include "QF/ringbuffer.h" + typedef struct qfv_packet_s { struct qfv_stagebuf_s *stage; ///< staging buffer that owns this packet VkCommandBuffer cmd; @@ -13,21 +15,18 @@ typedef struct qfv_stagebuf_s { struct qfv_device_s *device; VkBuffer buffer; VkDeviceMemory memory; - qfv_packet_t *packet; ///< array of packets for controlling access - size_t num_packets;///< number of packets in array - size_t next_packet;///< index of the next packet to be used - size_t size; ///< actual size of the buffer + RING_BUFFER(qfv_packet_t, 4) packets; ///< packets for controlling access size_t atom_mask; ///< for flush size rounding + size_t size; ///< actual size of the buffer size_t end; ///< effective end of the buffer due to early wrap - size_t head; - size_t tail; + size_t space_start;///< beginning of available space + size_t space_end; ///< end of available space void *data; } qfv_stagebuf_t; qfv_stagebuf_t *QFV_CreateStagingBuffer (struct qfv_device_s *device, - size_t size, int num_packets, - VkCommandPool cmdPool); + size_t size, VkCommandPool cmdPool); void QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage); void QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size); qfv_packet_t *QFV_PacketAcquire (qfv_stagebuf_t *stage); diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index e40a76e28..b64e8c11f 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -211,7 +211,7 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) memsize, 0); mctx->texture_memory = mem; - qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, memsize, 1, + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, memsize, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); buffer = QFV_PacketExtend (packet, memsize); diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 613422b2b..836a08e5e 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -55,14 +55,13 @@ #include "vid_vulkan.h" qfv_stagebuf_t * -QFV_CreateStagingBuffer (qfv_device_t *device, size_t size, int num_packets, +QFV_CreateStagingBuffer (qfv_device_t *device, size_t size, VkCommandPool cmdPool) { size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; qfv_devfuncs_t *dfunc = device->funcs; - qfv_stagebuf_t *stage = malloc (sizeof (qfv_stagebuf_t) - + num_packets * sizeof (qfv_packet_t)); + qfv_stagebuf_t *stage = calloc (1, sizeof (qfv_stagebuf_t)); stage->atom_mask = atom - 1; size = (size + stage->atom_mask) & ~stage->atom_mask; stage->device = device; @@ -71,25 +70,23 @@ QFV_CreateStagingBuffer (qfv_device_t *device, size_t size, int num_packets, stage->memory = QFV_AllocBufferMemory (device, stage->buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, size, 0); - stage->packet = (qfv_packet_t *) (stage + 1); - stage->num_packets = num_packets; - stage->next_packet = 0; stage->size = size; stage->end = size; - stage->head = 0; - stage->tail = 0; dfunc->vkMapMemory (device->dev, stage->memory, 0, size, 0, &stage->data); QFV_BindBufferMemory (device, stage->buffer, stage->memory, 0); - __auto_type bufferset = QFV_AllocCommandBufferSet (num_packets, alloca); + int count = RB_buffer_size (&stage->packets); + + __auto_type bufferset = QFV_AllocCommandBufferSet (count, alloca); QFV_AllocateCommandBuffers (device, cmdPool, 0, bufferset); - for (int i = 0; i < num_packets; i++) { - stage->packet[i].stage = stage; - stage->packet[i].cmd = bufferset->a[i]; - stage->packet[i].fence = QFV_CreateFence (device, 1); - stage->packet[i].offset = 0; - stage->packet[i].length = 0; + for (int i = 0; i < count; i++) { + qfv_packet_t *packet = &stage->packets.buffer[i]; + packet->stage = stage; + packet->cmd = bufferset->a[i]; + packet->fence = QFV_CreateFence (device, 1); + packet->offset = 0; + packet->length = 0; } return stage; } @@ -100,14 +97,15 @@ QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage) qfv_device_t *device = stage->device; qfv_devfuncs_t *dfunc = device->funcs; - __auto_type fences = QFV_AllocFenceSet (stage->num_packets, alloca); - for (size_t i = 0; i < stage->num_packets; i++) { - fences->a[i] = stage->packet[i].fence; + int count = RB_buffer_size (&stage->packets); + __auto_type fences = QFV_AllocFenceSet (count, alloca); + for (int i = 0; i < count; i++) { + fences->a[i] = stage->packets.buffer[i].fence; } dfunc->vkWaitForFences (device->dev, fences->size, fences->a, VK_TRUE, - ~0ull); - for (size_t i = 0; i < stage->num_packets; i++) { - dfunc->vkDestroyFence (device->dev, stage->packet[i].fence, 0); + 500000000ull); + for (int i = 0; i < count; i++) { + dfunc->vkDestroyFence (device->dev, fences->a[i], 0); } dfunc->vkUnmapMemory (device->dev, stage->memory); @@ -132,44 +130,87 @@ QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size) } static void -advance_tail (qfv_stagebuf_t *stage, qfv_packet_t *packet) +release_space (qfv_stagebuf_t *stage, size_t offset, size_t length) { + if (stage->space_end != offset + && offset != 0 + && stage->space_end != stage->end) { + Sys_Error ("staging: out of sequence packet release"); + } + if (stage->space_end == stage->end) { + stage->space_end = 0; + stage->end = stage->size; + } + stage->space_end += length; +} + +static void * +acquire_space (qfv_packet_t *packet, size_t size) +{ + qfv_stagebuf_t *stage = packet->stage; qfv_device_t *device = stage->device; qfv_devfuncs_t *dfunc = device->funcs; - qfv_packet_t *start = packet; - - while (1) { - if ((size_t) (++packet - stage->packet) >= stage->num_packets) { - packet = stage->packet; + // clean up after any completed packets + while (RB_DATA_AVAILABLE (stage->packets) > 1) { + qfv_packet_t *p = RB_PEEK_DATA (stage->packets, 0); + if (dfunc->vkGetFenceStatus (device->dev, p->fence) != VK_SUCCESS) { + break; } - if (packet != start - && (dfunc->vkGetFenceStatus (device->dev, packet->fence) - == VK_SUCCESS)) { - if (packet->length == 0) { - continue; - } - if ((stage->tail == stage->end && packet->offset == 0) - || stage->tail == packet->offset) { - stage->tail = packet->offset + packet->length; - packet->length = 0; - if (stage->tail >= stage->end) { - stage->end = stage->size; - stage->tail = stage->size; - } - } - continue; - } - // Packets are always aquired in sequence and thus the first busy - // packet after the start packet marks the end of available space. - // Alternatively, there is only one packet and we've looped around - // back to the start packet. Must ensure the tail is updated - if (stage->tail >= stage->end && packet->offset == 0) { - stage->end = stage->size; - stage->tail = packet->offset; - } - break; + release_space (stage, p->offset, p->length); + RB_RELEASE (stage->packets, 1); } + + if (size > stage->size) { + // utterly impossible allocation + return 0; + } + + // if the staging buffer has been freed up and no data is assigned to the + // single existing packet, then ensure the packet starts at the beginning + // of the staging buffer in order to maximize the space available to it + // (some of the tests are redundant since if any space is assigned to a + // packet, the buffer cannot be fully freed up) + if (stage->space_end == stage->space_start + && RB_DATA_AVAILABLE (stage->packets) == 1 + && packet->length == 0) { + stage->space_end = 0; + stage->space_start = 0; + packet->offset = 0; + } + if (stage->space_start >= stage->space_end) { + // all the space to the actual end of the buffer is free + if (stage->space_start + size <= stage->size) { + void *data = (byte *) stage->data + stage->space_start; + stage->space_start += size; + return data; + } + // doesn't fit at the end of the buffer, try the beginning but only + // if the packet can be moved (no spaced has been allocated to it yet) + if (packet->length > 0) { + // can't move it + return 0; + } + // mark the unused end of the buffer such that it gets reclaimed + // properly when the preceeding packet is freed + stage->end = stage->space_start; + stage->space_start = 0; + packet->offset = 0; + } + while (stage->space_start + size > stage->space_end + && RB_DATA_AVAILABLE (stage->packets) > 1) { + packet = RB_PEEK_DATA (stage->packets, 0); + dfunc->vkWaitForFences (device->dev, 1, &packet->fence, VK_TRUE, + ~0ull); + release_space (stage, packet->offset, packet->length); + RB_RELEASE (stage->packets, 1); + } + if (stage->space_start + size > stage->space_end) { + return 0; + } + void *data = (byte *) stage->data + stage->space_start; + stage->space_start += size; + return data; } qfv_packet_t * @@ -177,16 +218,19 @@ QFV_PacketAcquire (qfv_stagebuf_t *stage) { qfv_device_t *device = stage->device; qfv_devfuncs_t *dfunc = device->funcs; - qfv_packet_t *packet = &stage->packet[stage->next_packet++]; - stage->next_packet %= stage->num_packets; - dfunc->vkWaitForFences (device->dev, 1, &packet->fence, VK_TRUE, ~0ull); - - advance_tail (stage, packet); - if (stage->head == stage->size) { - stage->head = 0; + qfv_packet_t *packet = 0; + if (!RB_SPACE_AVAILABLE (stage->packets)) { + // need to wait for a packet to become available + packet = RB_PEEK_DATA (stage->packets, 0); + dfunc->vkWaitForFences (device->dev, 1, &packet->fence, VK_TRUE, + ~0ull); + release_space (stage, packet->offset, packet->length); + RB_RELEASE (stage->packets, 1); } - packet->offset = stage->head; + packet = RB_ACQUIRE (stage->packets, 1); + + packet->offset = stage->space_start; packet->length = 0; dfunc->vkResetFences (device->dev, 1, &packet->fence); @@ -203,40 +247,10 @@ QFV_PacketAcquire (qfv_stagebuf_t *stage) void * QFV_PacketExtend (qfv_packet_t *packet, size_t size) { - qfv_stagebuf_t *stage = packet->stage; - if (!size || size > stage->size) { - return 0; + void *data = acquire_space (packet, size); + if (data) { + packet->length += size; } - - //FIXME extra logic may be needed to wait wait for space to become - //available when the requested size should fit but can't due to in-flight - //packets - advance_tail (stage, packet); - - size_t head = stage->head; - size_t end = stage->end; - if (head + size > stage->end) { - if (packet->length) { - // packets cannot wrap around the buffer (must use separate - // packets) - return 0; - } - if (stage->tail == 0) { - // the beginning of the the staging buffer is occupied - return 0; - } - packet->offset = 0; - head = 0; - end = stage->head; - } - if (head < stage->tail && head + size > stage->tail) { - // not enough room for the sub-packet - return 0; - } - void *data = (byte *) stage->data + head; - stage->end = end; - stage->head = head + size; - packet->length += size; return data; } diff --git a/libs/video/renderer/vulkan/test/test-staging.c b/libs/video/renderer/vulkan/test/test-staging.c index bb5361cec..020af9ab2 100644 --- a/libs/video/renderer/vulkan/test/test-staging.c +++ b/libs/video/renderer/vulkan/test/test-staging.c @@ -66,12 +66,17 @@ vkCreateFence (VkDevice device, const VkFenceCreateInfo *info, return VK_SUCCESS; } +int wait_count = 0; + static VkResult vkWaitForFences (VkDevice device, uint32_t fenceCount, const VkFence *fences, VkBool32 waitAll, uint64_t timeout) { for (uint32_t i = 0; i < fenceCount; i++) { int *f = (int *)fences[i]; + if (*f) { + wait_count++; + } *f = 0; } return VK_SUCCESS; @@ -145,7 +150,13 @@ qfv_devfuncs_t dfuncs = { vkFlushMappedMemoryRanges:vkFlushMappedMemoryRanges, vkQueueSubmit:vkQueueSubmit, }; -qfv_physdev_t physDev; +qfv_physdev_t physDev = { + properties:{ + limits:{ + nonCoherentAtomSize:256, + }, + }, +}; qfv_device_t device = { physDev:&physDev, funcs:&dfuncs, @@ -168,271 +179,59 @@ _error (int line, const char *fmt, ...) int main (void) { - qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (&device, 1024, 4, 0); + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (&device, 1024, 0); - if (stage->num_packets != 4) { - error ("stage has incorrect packet count: %zd\n", stage->num_packets); - } - if (stage->next_packet != 0) { - error ("stage has incorrect next_packet: %zd\n", stage->next_packet); - } if (stage->size != 1024) { - error ("stage has incorrect size: %zd\n", stage->size); + error ("stage has incorrect size: %zd", stage->size); } if (stage->end != stage->size) { - error ("stage has incorrect end: %zd\n", stage->end); - } - if (stage->head || stage->tail != stage->head) { - error ("stage ring buffer not initialized: h:%zd t:%zd\n", - stage->head, stage->tail); + error ("stage has incorrect end: %zd", stage->end); } if (!stage->data || stage->data != stage_memory) { - error ("stage memory not mapped: d:%p, m:%p\n", + error ("stage memory not mapped: d:%p, m:%p", stage->data, stage_memory); } - for (size_t i = 0; i < stage->num_packets; i++) { - qfv_packet_t *p = &stage->packet[i]; + for (size_t i = 0; i < RB_buffer_size (&stage->packets); i++) { + qfv_packet_t *p = &stage->packets.buffer[i]; if (p->stage != stage) { - error ("packet[%zd] stage not set: ps:%p s:%p\n", i, + error ("packet[%zd] stage not set: ps:%p s:%p", i, p->stage, stage); } if (!p->cmd) { - error ("packet[%zd] has no command buffer\n", i); + error ("packet[%zd] has no command buffer", i); } if (!p->fence) { - error ("packet[%zd] has no fence\n", i); - } - for (size_t j = 0; j < i; j++) { - qfv_packet_t *q = &stage->packet[j]; - if (q->cmd == p->cmd || q->fence == p->fence) { - error ("packet[%zd] has dup fence or cmd buf\n", i); - } + error ("packet[%zd] has no fence", i); } if (vkGetFenceStatus (device.dev, p->fence) != VK_SUCCESS) { - error ("packet[%zd].fence is not signaled\n", i); + error ("packet[%zd].fence is not signaled", i); } if (p->offset || p->length) { - error ("packet[%zd] size/length not initialized: o:%zd l:%zd\n", + error ("packet[%zd] size/length not initialized: o:%zd l:%zd", i, p->offset, p->length); } } qfv_packet_t *packet = QFV_PacketAcquire (stage); + if (!packet) { + error ("could not get a packet"); + } + if (RB_DATA_AVAILABLE (stage->packets) != 1) { + error ("in flight packet count incorrect"); + } if (vkGetFenceStatus (device.dev, packet->fence) != VK_NOT_READY) { - error ("packet.fence is signaled\n"); + error ("packet.fence is signaled"); + } + if (QFV_PacketExtend (packet, 2048)) { + error ("2048 byte request did not return null"); + } + if (!QFV_PacketExtend (packet, 1024)) { + error ("1024 byte request returned null"); + } + if (QFV_PacketExtend (packet, 1)) { + error ("1 byte request did not return null"); } - void *data; - size_t old_head, old_tail; - - old_head = stage->head; - old_tail = stage->tail; - data = QFV_PacketExtend (packet, 0); - if (data) { - error ("0 byte extend did not return null\n"); - } - if (stage->head != old_head || stage->tail != old_tail) { - error ("0 byte extend moved head or tail\n"); - } - - data = QFV_PacketExtend (packet, 2048); - if (data) { - error ("2048 byte extend did not return null\n"); - } - if (stage->head != old_head || stage->tail != old_tail) { - error ("2048 byte extend moved head or tail\n"); - } - - data = QFV_PacketExtend (packet, 1024); - if (!data) { - error ("1024 byte extend failed\n"); - } - if (stage->head == old_head) { - error ("1024 byte extend did not move head\n"); - } - if (stage->tail != old_tail) { - error ("1024 byte extend moved tail\n"); - } - if (stage->head > stage->size) { - error ("stage head out of bounds: %zd\n", stage->head); - } - if (packet->offset != old_head || packet->length != 1024) { - error ("packet offset/size incorrect: p:%zd,%zd h:%zd\n", - packet->offset, packet->length, old_head); - } - if (stage->head < packet->offset + packet->length) { - error ("stage head before end of packet: %zd, pe:%zd\n", - stage->head, packet->offset + packet->length); - } - - old_head = stage->head; - old_tail = stage->tail; - data = QFV_PacketExtend (packet, 16); - if (data) { - error ("16 byte extend in full stage did not return null\n"); - } - if (stage->head != old_head || stage->tail != old_tail) { - error ("16 byte extend moved head or tail\n"); - } - QFV_PacketSubmit (packet); - if (vkGetFenceStatus (device.dev, packet->fence) != VK_SUCCESS) { - error ("packet.fence is not signaled\n"); - } - - if (stage->head != 1024 || stage->tail != 0) { - error ("stage head or tail not as expected: h: %zd t:%zd\n", - stage->head, stage->tail); - } - - qfv_packet_t *packet2 = QFV_PacketAcquire (stage); - if (!packet2 || packet2 == packet) { - error ("did not get new packet: n:%p o:%p\n", packet2, packet); - } - packet = packet2; - if (packet->offset != 0 || stage->head != 0 || stage->tail != 0) { - error ("new packet did not wrap: p:%zd h:%zd t:%zd\n", - packet2->offset, stage->head, stage->tail); - } - - old_head = stage->head; - old_tail = stage->tail; - data = QFV_PacketExtend (packet, 768); - if (!data) { - error ("768 byte extend failed\n"); - } - if (stage->head == old_head) { - error ("768 byte extend did not move head\n"); - } - if (stage->tail != 0) { - error ("768 byte extend dit not wrap tail: %zd\n", stage->tail); - } - if (stage->head > stage->size) { - error ("stage head out of bounds: %zd\n", stage->head); - } - if (packet->offset != old_head || packet->length != 768) { - error ("packet offset/size incorrect: p:%zd,%zd h:%zd\n", - packet->offset, packet->length, old_head); - } - if (stage->head < packet->offset + packet->length) { - error ("stage head before end of packet: %zd, pe:%zd\n", - stage->head, packet->offset + packet->length); - } - - // test attempting to wrap the packet (without needed space) - old_head = stage->head; - old_tail = stage->tail; - data = QFV_PacketExtend (packet, 512); - if (data) { - error ("512 byte extend in partially full stage succeeded\n"); - } - if (stage->head != old_head || stage->tail != old_tail) { - error ("512 byte extend moved head or tail\n"); - } - QFV_PacketSubmit (packet); - - if (stage->head != 768 || stage->tail != 0) { - error ("stage head or tail not as expected: h: %zd t:%zd\n", - stage->head, stage->tail); - } - - packet = QFV_PacketAcquire (stage); - - // test wrapping a new packet - data = QFV_PacketExtend (packet, 512); - if (!data) { - error ("512 byte extend failed\n"); - } - if (packet->offset != 0 || packet->length != 512) { - error ("packet offset/size incorrect: p:%zd,%zd\n", - packet->offset, packet->length); - } - if (stage->head != 512 || stage->tail != stage->end || stage->end !=768) { - error ("stage head or tail not as expected: h: %zd t:%zd\n", - stage->head, stage->tail); - } - data = QFV_PacketExtend (packet, 512); - if (!data) { - error ("second 512 byte extend failed\n"); - } - if (packet->offset != 0 || packet->length != 1024) { - error ("packet offset/size incorrect: p:%zd,%zd\n", - packet->offset, packet->length); - } - if (stage->head != 1024 || stage->tail != 0 || stage->end != 1024) { - error ("stage head or tail not as expected: h: %zd t:%zd\n", - stage->head, stage->tail); - } - QFV_PacketSubmit (packet); - - packet = QFV_PacketAcquire (stage); - data = QFV_PacketExtend (packet, 512); - if (!data) { - error ("512 byte extend failed\n"); - } - if (packet->offset != 0 || packet->length != 512) { - error ("packet offset/size incorrect: p:%zd,%zd\n", - packet->offset, packet->length); - } - QFV_PacketSubmit (packet); - - if (stage->head != 512 || stage->tail != 0 || stage->end != 1024) { - error ("stage head or tail not as expected: h: %zd t:%zd\n", - stage->head, stage->tail); - } - - packet = QFV_PacketAcquire (stage); - data = QFV_PacketExtend (packet, 256); - if (!data) { - error ("256 byte extend failed\n"); - } - if (packet->offset != 512 || packet->length != 256) { - error ("packet offset/size incorrect: p:%zd,%zd\n", - packet->offset, packet->length); - } - if (stage->head != 768 || stage->tail != 512 || stage->end != 1024) { - error ("stage head or tail not as expected: h: %zd t:%zd\n", - stage->head, stage->tail); - } - // don't submit yet. Normally, it would be an error, but the test harness - // needs to keep the packet on hand for the following tests to work - packet2 = QFV_PacketAcquire (stage); - old_head = stage->head; - old_tail = stage->tail; - data = QFV_PacketExtend (packet2, 768); - if (data) { - error ("768 byte extend did not return null\n"); - } - if (stage->head != old_head || stage->tail != old_tail) { - error ("768 byte extend moved head or tail\n"); - } - - //should wrap - data = QFV_PacketExtend (packet2, 512); - if (!data) { - error ("512 byte extend failed\n"); - } - if (packet2->offset != 0 || packet2->length != 512) { - error ("packet offset/size incorrect: p:%zd,%zd\n", - packet2->offset, packet2->length); - } - if (stage->head != 512 || stage->tail != 512 || stage->end != 768) { - error ("stage head or tail not as expected: h: %zd t:%zd\n", - stage->head, stage->tail); - } - - //submit the first packet - QFV_PacketSubmit (packet); - - packet = QFV_PacketAcquire (stage); - old_head = stage->head; - old_tail = stage->tail; - data = QFV_PacketExtend (packet, 768); - if (data) { - error ("768 byte extend did not return null\n"); - } - if (stage->head != old_head || stage->tail != old_tail) { - error ("768 byte extend moved head or tail\n"); - } return 0; } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index fe7c001f4..27c2b724a 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -465,8 +465,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) size_t vertex_buffer_size = vertex_count * sizeof (bspvert_t); index_buffer_size = (index_buffer_size + atom_mask) & ~atom_mask; - stage = QFV_CreateStagingBuffer (device, vertex_buffer_size, 1, - ctx->cmdpool); + stage = QFV_CreateStagingBuffer (device, vertex_buffer_size, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); vertices = QFV_PacketExtend (packet, vertex_buffer_size); vertex_index_base = 0; @@ -1289,8 +1288,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->light_scrap = QFV_CreateScrap (device, 2048, tex_frgba, ctx->staging); size_t size = QFV_ScrapSize (bctx->light_scrap); - bctx->light_stage = QFV_CreateStagingBuffer (device, size, 3, - ctx->cmdpool); + bctx->light_stage = QFV_CreateStagingBuffer (device, size, ctx->cmdpool); DARRAY_INIT (&bctx->texture_chains, 64); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 2e41e2252..6ec67b227 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -367,7 +367,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) 0, 0); create_quad_buffers (ctx); - dctx->stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024, 4, + dctx->stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024, ctx->cmdpool); dctx->scrap = QFV_CreateScrap (device, 2048, tex_rgba, dctx->stage); dctx->sampler = QFV_GetSampler (ctx, "quakepic"); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index d9220307b..4e5f338cc 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -204,7 +204,7 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) void Vulkan_CreateStagingBuffers (vulkan_ctx_t *ctx) { - ctx->staging = QFV_CreateStagingBuffer (ctx->device, 4*1024*1024, 1, + ctx->staging = QFV_CreateStagingBuffer (ctx->device, 4*1024*1024, ctx->cmdpool); } From 68b734142990aa5be9246e35e9b89610a2a9f226 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 13:51:09 +0900 Subject: [PATCH 1258/3664] [vulkan] Set main texture image view Glow map and sky sheet and cube need to wait until I can get some default textures going, but the world is rendering correctly otherwise (though a tad dark: need to do a gamma setting). --- include/QF/Vulkan/qf_bsp.h | 8 ++ libs/video/renderer/vulkan/quakebsp.frag | 11 ++- libs/video/renderer/vulkan/vulkan_bsp.c | 111 +++++++++++++---------- 3 files changed, 76 insertions(+), 54 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 5b01da407..92c63b034 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -57,6 +57,11 @@ typedef struct elechain_s { float *color; } elechain_t; +// view matrix +#define BSP_BUFFER_INFOS 1 +// Texture, GlowMap, LightMap, SkySheet, SkyCube +#define BSP_IMAGE_INFOS 5 + typedef struct bspframe_s { uint32_t *index_data; // pointer into mega-buffer for this frame (c) uint32_t index_offset; // offset of index_data within mega-buffer (c) @@ -64,6 +69,9 @@ typedef struct bspframe_s { VkCommandBuffer bsp_cmd; VkCommandBuffer turb_cmd; VkCommandBuffer sky_cmd; + VkDescriptorBufferInfo bufferInfo[BSP_BUFFER_INFOS]; + VkDescriptorImageInfo imageInfo[BSP_IMAGE_INFOS]; + VkWriteDescriptorSet descriptors[BSP_BUFFER_INFOS + BSP_IMAGE_INFOS]; } bspframe_t; typedef struct bspframeset_s diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag index 916581292..73270557e 100644 --- a/libs/video/renderer/vulkan/quakebsp.frag +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -1,8 +1,8 @@ #version 450 layout (set = 0, binding = 1) uniform sampler2D Texture; -layout (set = 0, binding = 2) uniform sampler2D Glowmap; -layout (set = 0, binding = 3) uniform sampler2D Lightmap; +layout (set = 0, binding = 2) uniform sampler2D GlowMap; +layout (set = 0, binding = 3) uniform sampler2D LightMap; //layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; //layout (set = 0, binding = 5) uniform samplerCube SkyCube; @@ -117,9 +117,10 @@ main (void) }*/ c = texture (Texture, t_st); if (doLight) { - c *= vec4 (texture (Lightmap, l_st).xyz, 1); + c *= vec4 (texture (LightMap, l_st).xyz, 1); } - c += texture (Glowmap, t_st); - c = vec4(texture (Lightmap, l_st).xyz, 1); + //c += texture (GlowMap, t_st); + //c = vec4(texture (LightMap, l_st).xyz, 1); + //c = vec4(texture (Texture, t_st).xyz, 1); frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 27c2b724a..a7fab14ab 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -788,12 +788,12 @@ draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, } static VkImageView -get_view (qfv_tex_t *tex) +get_view (qfv_tex_t *tex, VkImageView default_view) { if (tex) { return tex->view; } - return 0; + return default_view; } static void @@ -812,52 +812,13 @@ bsp_begin (vulkan_ctx_t *ctx) VkCommandBuffer cmd = bframe->bsp_cmd; DARRAY_APPEND (cframe->subCommand, cmd); - VkDescriptorBufferInfo bufferInfo = { - ctx->matrices.buffer_3d, 0, VK_WHOLE_SIZE - }; - VkDescriptorImageInfo imageInfo[] = { - { bctx->sampler, - QFV_ScrapImageView (bctx->light_scrap), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, - { bctx->sampler, - QFV_ScrapImageView (bctx->light_scrap), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, - { bctx->sampler, - QFV_ScrapImageView (bctx->light_scrap), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, - { bctx->sampler, - get_view (bctx->skysheet_tex), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, - { bctx->sampler, - get_view (bctx->skybox_tex), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, - }; - VkWriteDescriptorSet write[] = { - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 0, 0, 1, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - 0, &bufferInfo, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 1, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &imageInfo[0], 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 2, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &imageInfo[1], 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 3, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &imageInfo[2], 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 4, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &imageInfo[3], 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 5, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &imageInfo[4], 0, 0 }, - }; + //FIXME need per frame matrices + bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + bframe->imageInfo[0].imageView = 0; // set by tex chain loop + bframe->imageInfo[1].imageView = 0; // set by tex chain loop + bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); + bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, 0); + bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, 0); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { @@ -885,8 +846,15 @@ bsp_begin (vulkan_ctx_t *ctx) dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, VK_INDEX_TYPE_UINT32); + // push VP matrices dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, 0, 4, write); + bctx->layout, + 0, 1, bframe->descriptors + 0); + // push static images + // XXX sky sheet and box not pushed yet + dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + bctx->layout, + 0, 1, bframe->descriptors + 3); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -1140,11 +1108,22 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) elechain_t *ec = 0; tex = bctx->texture_chains.a[i]; + if (!tex->tex) { + //FIXME bind to whit + continue; + } build_tex_elechain (tex, bctx, bframe); //XXX if (tex->elechain) //XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); + bframe->imageInfo[0].imageView = get_view (tex->tex, 0); + bframe->imageInfo[1].imageView = get_view (tex->glow, 0); + //XXX glow map + dfunc->vkCmdPushDescriptorSetKHR (bframe->bsp_cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + bctx->layout, + 0, 1, bframe->descriptors + 1); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->bsp_cmd); @@ -1271,6 +1250,25 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) bctx->sky_chain_tail = &bctx->sky_chain; } +static VkDescriptorBufferInfo base_buffer_info = { + 0, 0, VK_WHOLE_SIZE +}; +static VkDescriptorImageInfo base_image_info = { + 0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL +}; +static VkWriteDescriptorSet base_buffer_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, 0, 0 +}; +static VkWriteDescriptorSet base_image_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 0, 0, 0 +}; + void Vulkan_Bsp_Init (vulkan_ctx_t *ctx) { @@ -1314,6 +1312,21 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bframe->bsp_cmd = cmdBuffers->a[i]; bframe->turb_cmd = cmdBuffers->a[i]; bframe->sky_cmd = cmdBuffers->a[i]; + + for (int j = 0; j < BSP_BUFFER_INFOS; j++) { + bframe->bufferInfo[j] = base_buffer_info; + bframe->descriptors[j] = base_buffer_write; + bframe->descriptors[j].dstBinding = j; + bframe->descriptors[j].pBufferInfo = &bframe->bufferInfo[j]; + } + for (int j = 0; j < BSP_IMAGE_INFOS; j++) { + bframe->imageInfo[j] = base_image_info; + bframe->imageInfo[j].sampler = bctx->sampler; + int k = j + BSP_BUFFER_INFOS; + bframe->descriptors[k] = base_image_write; + bframe->descriptors[k].dstBinding = k; + bframe->descriptors[k].pImageInfo = &bframe->imageInfo[j]; + } } } From 93e9f89bd38b9a900eae83da8d2f67f3deb512e3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 15:40:31 +0900 Subject: [PATCH 1259/3664] [vulkan] Create some default textures Black, white and magenta. This gets glow (full bright) maps working. --- include/QF/Vulkan/qf_texture.h | 2 ++ include/vid_vulkan.h | 6 ++++ libs/video/renderer/vid_render_vulkan.c | 2 ++ libs/video/renderer/vulkan/quakebsp.frag | 4 +-- libs/video/renderer/vulkan/vulkan_bsp.c | 28 +++++++++--------- libs/video/renderer/vulkan/vulkan_texture.c | 32 ++++++++++++++++++++- 6 files changed, 56 insertions(+), 18 deletions(-) diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index a2ffbd38e..d08fc0a46 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -16,5 +16,7 @@ void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip); VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure)); void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex); +void Vulkan_Texture_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Texture_Shutdown (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_texture_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 92208425e..3a234c0d2 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -75,6 +75,12 @@ typedef struct vulkan_ctx_s { size_t curFrame; vulkan_framebufferset_t framebuffers; + struct qfv_tex_s *default_black; + struct qfv_tex_s *default_white; + struct qfv_tex_s *default_magenta; + struct qfv_tex_s *default_skysheet; + struct qfv_tex_s *default_skybox; + // projection and view matrices (model is push constant) vulkan_matrices_t matrices; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 85d090b37..a54962b52 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -96,6 +96,7 @@ vulkan_R_Init (void) // FIXME this should be staged so screen updates can begin while pipelines // are being built vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); + Vulkan_Texture_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); Vulkan_Particles_Init (vulkan_ctx); @@ -607,6 +608,7 @@ vulkan_vid_render_shutdown (void) Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Mod_ClearAll (); + Vulkan_Texture_Shutdown (vulkan_ctx); Vulkan_Shutdown_Common (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag index 73270557e..872c97893 100644 --- a/libs/video/renderer/vulkan/quakebsp.frag +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -119,8 +119,6 @@ main (void) if (doLight) { c *= vec4 (texture (LightMap, l_st).xyz, 1); } - //c += texture (GlowMap, t_st); - //c = vec4(texture (LightMap, l_st).xyz, 1); - //c = vec4(texture (Texture, t_st).xyz, 1); + c += texture (GlowMap, t_st); frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a7fab14ab..552ea075f 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -788,12 +788,15 @@ draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, } static VkImageView -get_view (qfv_tex_t *tex, VkImageView default_view) +get_view (qfv_tex_t *tex, qfv_tex_t *default_tex) { if (tex) { return tex->view; } - return default_view; + if (default_tex) { + return default_tex->view; + } + return 0; } static void @@ -817,8 +820,10 @@ bsp_begin (vulkan_ctx_t *ctx) bframe->imageInfo[0].imageView = 0; // set by tex chain loop bframe->imageInfo[1].imageView = 0; // set by tex chain loop bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); - bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, 0); - bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, 0); + bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, + ctx->default_skysheet); + bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, + ctx->default_skybox); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { @@ -1108,22 +1113,17 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) elechain_t *ec = 0; tex = bctx->texture_chains.a[i]; - if (!tex->tex) { - //FIXME bind to whit - continue; - } build_tex_elechain (tex, bctx, bframe); - //XXX if (tex->elechain) - //XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); - bframe->imageInfo[0].imageView = get_view (tex->tex, 0); - bframe->imageInfo[1].imageView = get_view (tex->glow, 0); - //XXX glow map + bframe->imageInfo[0].imageView = get_view (tex->tex, + ctx->default_white); + bframe->imageInfo[1].imageView = get_view (tex->glow, + ctx->default_black); dfunc->vkCmdPushDescriptorSetKHR (bframe->bsp_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, bctx->layout, - 0, 1, bframe->descriptors + 1); + 0, 2, bframe->descriptors + 1); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->bsp_cmd); diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 295d1a89d..86bd890ab 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -170,6 +170,10 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); QFV_BindImageMemory (device, qtex->image, qtex->memory, 0); + qtex->view = QFV_CreateImageView (device, qtex->image, + VK_IMAGE_VIEW_TYPE_2D, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_ASPECT_COLOR_BIT); size_t bytes = bpp * tex->width * tex->height; qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); @@ -241,8 +245,14 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) blit.dstOffsets[1].y = (blit.dstOffsets[1].y + 1) >> 1; barrier.subresourceRange.baseMipLevel++; } + stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier.image = qtex->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); QFV_PacketSubmit (packet); - return 0; + return qtex; } VkImageView @@ -262,3 +272,23 @@ Vulkan_UnloadTex (vulkan_ctx_t *ctx, qfv_tex_t *tex) dfunc->vkFreeMemory (device->dev, tex->memory, 0); free (tex); } + +static tex_t default_black_tex = {1, 1, tex_rgba, 1, 0, {0, 0, 0, 0 }}; +static tex_t default_white_tex = {1, 1, tex_rgba, 1, 0, {255, 255, 255, 255 }}; +static tex_t default_magenta_tex = {1, 1, tex_rgba, 1, 0, {255, 0, 255, 255 }}; + +void +Vulkan_Texture_Init (vulkan_ctx_t *ctx) +{ + ctx->default_black = Vulkan_LoadTex (ctx, &default_black_tex, 1); + ctx->default_white = Vulkan_LoadTex (ctx, &default_white_tex, 1); + ctx->default_magenta = Vulkan_LoadTex (ctx, &default_magenta_tex, 1); +} + +void +Vulkan_Texture_Shutdown (vulkan_ctx_t *ctx) +{ + Vulkan_UnloadTex (ctx, ctx->default_black); + Vulkan_UnloadTex (ctx, ctx->default_white); + Vulkan_UnloadTex (ctx, ctx->default_magenta); +} From 82241693947ef9a271f65e1ddb36f73cec495411 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 18:56:15 +0900 Subject: [PATCH 1260/3664] [util] Make plist parse errors a little more useful Particularly the "unexpected character" ones. --- libs/util/qfplist.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 273148657..3fa64b9d0 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -85,11 +85,11 @@ struct plbinary_s { typedef struct plbinary_s plbinary_t; typedef struct pldata_s { // Unparsed property list string - const char *ptr; - unsigned int end; - unsigned int pos; - unsigned int line; - const char *error; + const char *ptr; + unsigned end; + unsigned pos; + unsigned line; + plitem_t *error; } pldata_t; // Ugly defines for fast checking and conversion from char to number @@ -454,7 +454,7 @@ PL_SkipSpace (pldata_t *pl) pl->pos++; } if (pl->pos >= pl->end) { - pl->error = "Reached end of string in comment"; + pl->error = PL_NewString ("Reached end of string in comment"); return false; } } else if (pl->ptr[pl->pos + 1] == '*') { // "/*" comments @@ -473,7 +473,7 @@ PL_SkipSpace (pldata_t *pl) pl->pos++; } if (pl->pos >= pl->end) { - pl->error = "Reached end of string in comment"; + pl->error = PL_NewString ("Reached end of string in comment"); return false; } } else { @@ -488,7 +488,7 @@ PL_SkipSpace (pldata_t *pl) } pl->pos++; } - pl->error = "Reached end of string"; + pl->error = PL_NewString ("Reached end of string"); return false; } @@ -523,7 +523,7 @@ PL_ParseData (pldata_t *pl, int *len) } if (c == '>') { if (nibbles & 1) { - pl->error = "invalid data, missing nibble"; + pl->error = PL_NewString ("invalid data, missing nibble"); return NULL; } *len = nibbles / 2; @@ -533,10 +533,10 @@ PL_ParseData (pldata_t *pl, int *len) pl->ptr[start + i * 2 + 1]); return str; } - pl->error = "invalid character in data"; + pl->error = PL_NewString (va ("invalid character in data: %02x", c)); return NULL; } - pl->error = "Reached end of string while parsing data"; + pl->error = PL_NewString ("Reached end of string while parsing data"); return NULL; } @@ -603,7 +603,7 @@ PL_ParseQuotedString (pldata_t *pl) } if (pl->pos >= pl->end) { - pl->error = "Reached end of string while parsing quoted string"; + pl->error = PL_NewString ("Reached end of string while parsing quoted string"); return NULL; } @@ -741,14 +741,14 @@ PL_ParsePropertyListItem (pldata_t *pl) } if (key->type != QFString) { - pl->error = "Key is not a string"; + pl->error = PL_NewString ("Key is not a string"); PL_Free (key); PL_Free (item); return NULL; } if (pl->ptr[pl->pos] != '=') { - pl->error = "Unexpected character (expected '=')"; + pl->error = PL_NewString (va ("Unexpected character %c (expected '=')", pl->ptr[pl->pos])); PL_Free (key); PL_Free (item); return NULL; @@ -772,7 +772,7 @@ PL_ParsePropertyListItem (pldata_t *pl) if (pl->ptr[pl->pos] == ';') { pl->pos++; } else if (pl->ptr[pl->pos] != '}') { - pl->error = "Unexpected character (wanted ';' or '}')"; + pl->error = PL_NewString (va ("Unexpected character %c (wanted ';' or '}')", pl->ptr[pl->pos])); PL_Free (key); PL_Free (value); PL_Free (item); @@ -790,7 +790,7 @@ PL_ParsePropertyListItem (pldata_t *pl) } if (pl->pos >= pl->end) { // Catch the error - pl->error = "Unexpected end of string when parsing dictionary"; + pl->error = PL_NewString ("Unexpected end of string when parsing dictionary"); PL_Free (item); return NULL; } @@ -822,14 +822,14 @@ PL_ParsePropertyListItem (pldata_t *pl) if (pl->ptr[pl->pos] == ',') { pl->pos++; } else if (pl->ptr[pl->pos] != ')') { - pl->error = "Unexpected character (wanted ',' or ')')"; + pl->error = PL_NewString (va ("Unexpected character %c (wanted ',' or ')')", pl->ptr[pl->pos])); PL_Free (value); PL_Free (item); return NULL; } if (!PL_A_AddObject (item, value)) { - pl->error = "Unexpected character (too many items in array)"; + pl->error = PL_NewString ("Unexpected character (too many items in array)"); PL_Free (value); PL_Free (item); return NULL; @@ -896,8 +896,13 @@ PL_GetPropertyList (const char *string) free (pl); return newpl; } else { - if (pl && pl->error && pl->error[0]) - Sys_Printf ("plist: %d,%d: %s", pl->line, pl->pos, pl->error); + if (pl && pl->error) { + const char *error = PL_String (pl->error); + if (error[0]) { + Sys_Printf ("plist: %d,%d: %s", pl->line, pl->pos, error); + } + PL_Free (pl->error); + } free (pl); return NULL; } From 4283d690ad892cb36ba682aaf9e3e3c6d8933bcc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 20:39:09 +0900 Subject: [PATCH 1261/3664] [vulkan] Generate correct parse data for size_t Fixes a segfault when parsing specialization map data. --- libs/video/renderer/vulkan/vkgen/vkalias.r | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index cde6eb270..e0aad2943 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -137,9 +137,12 @@ id enumObj = [(id) Hash_Find (available_types, name) resolveType]; return [enumObj parseData]; } - if (name == "uint32_t" || name == "size_t") { + if (name == "uint32_t") { return "0"; } + if (name == "size_t") { + return "&cexpr_size_t"; + } return [alias parseData]; } @end From 77a8f901133a35e7dfd6e527cae0b4c347407dff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 20:40:11 +0900 Subject: [PATCH 1262/3664] [vulkan] Fix array parsing size error The size was not getting written if it was the first value in the structure. --- libs/video/renderer/vulkan/vkparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 0fc00b835..3c2447702 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -282,7 +282,7 @@ parse_array (const plfield_t *field, const plitem_t *item, } *value = malloc (array->stride * arr->size); memcpy (*value, arr->a, array->stride * arr->size); - if ((void *) size > data) { + if ((void *) size >= data) { *size = arr->size; } free (arr); From 49408c695dcfa063691ad1437cc83addb512723d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 20:42:53 +0900 Subject: [PATCH 1263/3664] [vulkan] Get sky sheets mostly working They render (incorrectly because the images weren't translated correctly), but aren't animated (haven't pushed the time constant) --- include/QF/Vulkan/qf_bsp.h | 11 + include/vid_vulkan.h | 2 - libs/video/renderer/vulkan/qfpipeline.plist | 106 ++++++- libs/video/renderer/vulkan/quakebsp.frag | 19 +- libs/video/renderer/vulkan/quakebsp.vert | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 297 ++++++++++++++------ 6 files changed, 341 insertions(+), 96 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 92c63b034..969fdd92c 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -57,6 +57,13 @@ typedef struct elechain_s { float *color; } elechain_t; +typedef enum { + qfv_bsp_texture, + qfv_bsp_glowmap, + qfv_bsp_lightmap, + qfv_bsp_skysheet, + qfv_bsp_skycube, +} qfv_bsp_tex; // view matrix #define BSP_BUFFER_INFOS 1 // Texture, GlowMap, LightMap, SkySheet, SkyCube @@ -104,7 +111,10 @@ typedef struct bspctx_s { instsurf_t **instsurfs_tail; instsurf_t *free_instsurfs; + struct qfv_tex_s *default_skysheet; struct qfv_tex_s *skysheet_tex; + + struct qfv_tex_s *default_skybox; struct qfv_tex_s *skybox_tex; quat_t sky_rotation[2]; quat_t sky_velocity; @@ -122,6 +132,7 @@ typedef struct bspctx_s { VkSampler sampler; VkDeviceMemory texture_memory; VkPipeline main; + VkPipeline sky; VkPipelineLayout layout; size_t vertex_buffer_size; size_t index_buffer_size; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 3a234c0d2..f4642afb1 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -78,8 +78,6 @@ typedef struct vulkan_ctx_s { struct qfv_tex_s *default_black; struct qfv_tex_s *default_white; struct qfv_tex_s *default_magenta; - struct qfv_tex_s *default_skysheet; - struct qfv_tex_s *default_skybox; // projection and view matrices (model is push constant) vulkan_matrices_t matrices; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 9b0a6a1d7..b5f5cd6cb 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -108,7 +108,7 @@ descriptorCount = 1; stageFlags = fragment; }, - /*{ + { binding = 4; descriptorType = combined_image_sampler; descriptorCount = 1; @@ -119,7 +119,7 @@ descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; - },*/ + }, ); }; something = { @@ -260,6 +260,108 @@ layout = quakebsp; //renderPass = renderpass; }; + quakebsp.skysheet = { + stages = ( + { stage = vertex; name = main; module = quakebspv; }, + { + stage = fragment; + name = main; + module = quakebspf; + specializationInfo = { + mapEntries = ( + { size = 4; offset = 0; constantID = 0; }, + { size = 4; offset = 0; constantID = 1; }, + { size = 4; offset = 0; constantID = 2; }, + { size = 4; offset = 4; constantID = 3; }, + ); + data = <00000000ffffffff>; + }; + }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "2 * 4 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + { + location = 1; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 16; + }, + ); + }; + inputAssembly = { + topology = triangle_fan; + primitiveRestartEnable = true; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + depthStencil = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ({ + blendEnable = true; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }); + }; + dynamic = { + dynamicState = ( viewport, scissor, blend_constants ); + }; + layout = quakebsp; + //renderPass = renderpass; + }; twod = { stages = ( { stage = vertex; name = main; module = twodv; }, diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag index 872c97893..483a3887e 100644 --- a/libs/video/renderer/vulkan/quakebsp.frag +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -3,8 +3,8 @@ layout (set = 0, binding = 1) uniform sampler2D Texture; layout (set = 0, binding = 2) uniform sampler2D GlowMap; layout (set = 0, binding = 3) uniform sampler2D LightMap; -//layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; -//layout (set = 0, binding = 5) uniform samplerCube SkyCube; +layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; +layout (set = 0, binding = 5) uniform samplerCube SkyCube; layout (push_constant) uniform PushConstants { layout (offset = 64) @@ -46,7 +46,7 @@ fogBlend (vec4 color) return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); } -/* + vec4 sky_sheet (vec3 dir, float time) { @@ -99,7 +99,7 @@ sky_color (vec3 dir, float time) return vec4 (1, 0, 1, 1); } } -*/ + void main (void) { @@ -110,15 +110,14 @@ main (void) if (doWarp) { t_st = warp_st (t_st, time); } - /*if (doSkyCube || doSkySheet) { + if (doSkyCube || doSkySheet) { c = sky_color (direction, time); } else { c = texture (Texture, t_st); - }*/ - c = texture (Texture, t_st); - if (doLight) { - c *= vec4 (texture (LightMap, l_st).xyz, 1); + if (doLight) { + c *= vec4 (texture (LightMap, l_st).xyz, 1); + } + c += texture (GlowMap, t_st); } - c += texture (GlowMap, t_st); frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/quakebsp.vert b/libs/video/renderer/vulkan/quakebsp.vert index efc03bac8..bb9e87e4a 100644 --- a/libs/video/renderer/vulkan/quakebsp.vert +++ b/libs/video/renderer/vulkan/quakebsp.vert @@ -20,6 +20,6 @@ void main (void) { gl_Position = Projection * (View * (Model * vertex)); - direction = vertex.xyz;//(Sky * vertex).xyz; + direction = (Sky * vertex).xyz; tl_st = tl_uv; } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 552ea075f..bfd54f9e8 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -56,9 +56,11 @@ #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/barrier.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" @@ -751,6 +753,17 @@ R_VisitWorldNodes (model_t *model, vulkan_ctx_t *ctx) visit_leaf ((mleaf_t *) node); } +static void +bind_view (qfv_bsp_tex tex, VkImageView view, bspframe_t *bframe, + VkCommandBuffer cmd, VkPipelineLayout layout, qfv_devfuncs_t *dfunc) +{ + bframe->imageInfo[tex].imageView = view; + dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 1, + bframe->descriptors + tex + + BSP_BUFFER_INFOS); +} + static void draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) @@ -821,9 +834,9 @@ bsp_begin (vulkan_ctx_t *ctx) bframe->imageInfo[1].imageView = 0; // set by tex chain loop bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, - ctx->default_skysheet); + bctx->default_skysheet); bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, - ctx->default_skybox); + bctx->default_skybox); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { @@ -856,10 +869,9 @@ bsp_begin (vulkan_ctx_t *ctx) bctx->layout, 0, 1, bframe->descriptors + 0); // push static images - // XXX sky sheet and box not pushed yet dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, bctx->layout, - 0, 1, bframe->descriptors + 3); + 0, 3, bframe->descriptors + 3); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -926,7 +938,7 @@ turb_end (bspctx_t *bctx) qfeglBindBuffer (GL_ARRAY_BUFFER, 0); }*/ -/*XXX static void +static void spin (mat4_t mat, bspctx_t *bctx) { quat_t q; @@ -947,82 +959,88 @@ spin (mat4_t mat, bspctx_t *bctx) VectorNegate (r_origin, mat + 12); QuatToMatrix (q, m, 1, 1); Mat4Mult (m, mat, mat); -}*/ +} static void -sky_begin (bspctx_t *bctx) +sky_begin (vulkan_ctx_t *ctx) { - //XXX mat4_t mat; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; //XXX quat_t fog; bctx->default_color[3] = 1; QuatCopy (bctx->default_color, bctx->last_color); -/* qfeglVertexAttrib4fv (quake_bsp.color.location, bctx->default_color); - Mat4Mult (glsl_projection, glsl_view, bsp_vp); + //XXX glsl_Fog_GetColor (fog); + //fog[3] = glsl_Fog_GetDensity () / 64.0; + //qfeglUniform4fv (sky_params.fog->location, 1, fog); - if (bctx->skybox_tex) { - sky_params.mvp_matrix = &quake_skybox.mvp_matrix; - sky_params.vertex = &quake_skybox.vertex; - sky_params.sky_matrix = &quake_skybox.sky_matrix; - sky_params.fog = &quake_skybox.fog; + spin (ctx->matrices.sky_3d, bctx); - qfeglUseProgram (quake_skybox.program); - qfeglEnableVertexAttribArray (quake_skybox.vertex.location); + __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = bframe->sky_cmd; + DARRAY_APPEND (cframe->subCommand, cmd); - qfeglUniform1i (quake_skybox.sky.location, 0); - qfeglActiveTexture (GL_TEXTURE0 + 0); - qfeglEnable (GL_TEXTURE_CUBE_MAP); - qfeglBindTexture (GL_TEXTURE_CUBE_MAP, skybox_tex); - } else { - sky_params.mvp_matrix = &quake_skyid.mvp_matrix; - sky_params.sky_matrix = &quake_skyid.sky_matrix; - sky_params.vertex = &quake_skyid.vertex; - sky_params.fog = &quake_skyid.fog; + //FIXME need per frame matrices + bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + bframe->imageInfo[0].imageView = ctx->default_magenta->view; + bframe->imageInfo[1].imageView = ctx->default_magenta->view; + bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); + bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, + bctx->default_skysheet); + bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, + bctx->default_skybox); - qfeglUseProgram (quake_skyid.program); - qfeglEnableVertexAttribArray (quake_skyid.vertex.location); + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + ctx->renderpass.renderpass, 0, + cframe->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - qfeglUniform1i (quake_skyid.palette.location, 2); - qfeglActiveTexture (GL_TEXTURE0 + 2); - qfeglEnable (GL_TEXTURE_2D); - qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + bctx->sky); + VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; + VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; + dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); - qfeglUniform1f (quake_skyid.time.location, vr_data.realtime); + VkDeviceSize offsets[] = { 0 }; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &bctx->vertex_buffer, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, + VK_INDEX_TYPE_UINT32); - qfeglUniform1i (quake_skyid.trans.location, 0); - qfeglActiveTexture (GL_TEXTURE0 + 0); - qfeglEnable (GL_TEXTURE_2D); + // push VP matrices + dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + bctx->layout, + 0, 1, bframe->descriptors + 0); + // push static images + dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + bctx->layout, + 0, 5, bframe->descriptors + 1); - qfeglUniform1i (quake_skyid.solid.location, 1); - qfeglActiveTexture (GL_TEXTURE0 + 1); - qfeglEnable (GL_TEXTURE_2D); - } - - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; - qfeglUniform4fv (sky_params.fog->location, 1, fog); - - spin (mat); - qfeglUniformMatrix4fv (sky_params.sky_matrix->location, 1, false, mat); - - qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo);*/ + //XXX glsl_Fog_GetColor (fog); + //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; } static void -sky_end (bspctx_t *bctx) +sky_end (vulkan_ctx_t *ctx) { - /*XXX qfeglDisableVertexAttribArray (sky_params.vertex->location); + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; - qfeglActiveTexture (GL_TEXTURE0 + 0); - qfeglDisable (GL_TEXTURE_2D); - qfeglDisable (GL_TEXTURE_CUBE_MAP); - qfeglActiveTexture (GL_TEXTURE0 + 1); - qfeglDisable (GL_TEXTURE_2D); - qfeglActiveTexture (GL_TEXTURE0 + 2); - qfeglDisable (GL_TEXTURE_2D); - - qfeglBindBuffer (GL_ARRAY_BUFFER, 0);*/ + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; + dfunc->vkEndCommandBuffer (bframe->sky_cmd); } static inline void @@ -1199,6 +1217,8 @@ Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) void Vulkan_DrawSky (vulkan_ctx_t *ctx) { + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; instsurf_t *is; @@ -1210,20 +1230,24 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) if (!bctx->sky_chain) return; - sky_begin (bctx); + sky_begin (ctx); + dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, + VK_SHADER_STAGE_VERTEX_BIT, + 0, 16 * sizeof (float), identity); + float frag_pc[8] = { }; + dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, + VK_SHADER_STAGE_FRAGMENT_BIT, + 64, 8 * sizeof (float), &frag_pc); for (is = bctx->sky_chain; is; is = is->tex_chain) { surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { - if (!bctx->skybox_tex) { - //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); - //qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[0]); - //qfeglActiveTexture (GL_TEXTURE0 + 1); - //qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[1]); + bind_view (qfv_bsp_skysheet, + get_view (tex->tex, ctx->default_black), + bframe, bframe->sky_cmd, bctx->layout, dfunc); + for (ec = tex->elechain; ec; ec = ec->next) { + draw_elechain (ec, bctx->layout, dfunc, bframe->sky_cmd); } - //for (ec = tex->elechain; ec; ec = ec->next) - // draw_elechain (ec, sky_params.mvp_matrix->location, - // sky_params.vertex->location, -1, -1); tex->elechain = 0; tex->elechain_tail = &tex->elechain; } @@ -1232,24 +1256,123 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - if (!bctx->skybox_tex) { - //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); - //qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[0]); - //qfeglActiveTexture (GL_TEXTURE0 + 1); - //qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[1]); + bind_view (qfv_bsp_skysheet, + get_view (tex->tex, ctx->default_black), + bframe, bframe->sky_cmd, bctx->layout, dfunc); + for (ec = tex->elechain; ec; ec = ec->next) { + draw_elechain (ec, bctx->layout, dfunc, bframe->sky_cmd); } - //for (ec = tex->elechain; ec; ec = ec->next) - // draw_elechain (ec, sky_params.mvp_matrix->location, - // sky_params.vertex->location, -1, -1); tex->elechain = 0; tex->elechain_tail = &tex->elechain; } - sky_end (bctx); + sky_end (ctx); bctx->sky_chain = 0; bctx->sky_chain_tail = &bctx->sky_chain; } +static void +create_default_skys (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; + VkImage skybox; + VkImage skysheet; + VkDeviceMemory memory; + VkImageView boxview; + VkImageView sheetview; + + bctx->default_skybox = calloc (2, sizeof (qfv_tex_t)); + bctx->default_skysheet = bctx->default_skybox + 1; + + VkExtent3D extents = { 1, 1, 1 }; + skybox = QFV_CreateImage (device, 1, VK_IMAGE_TYPE_2D, + VK_FORMAT_B8G8R8A8_UNORM, extents, 1, 1, + VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + + skysheet = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, + VK_FORMAT_B8G8R8A8_UNORM, extents, 1, 2, + VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + VkMemoryRequirements requirements; + dfunc->vkGetImageMemoryRequirements (device->dev, skybox, &requirements); + size_t boxsize = requirements.size; + dfunc->vkGetImageMemoryRequirements (device->dev, skysheet, &requirements); + size_t sheetsize = requirements.size; + + memory = QFV_AllocImageMemory (device, skybox, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + boxsize + sheetsize, + VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT); + + QFV_BindImageMemory (device, skybox, memory, 0); + QFV_BindImageMemory (device, skysheet, memory, boxsize); + + boxview = QFV_CreateImageView (device, skybox, VK_IMAGE_VIEW_TYPE_CUBE, + VK_FORMAT_B8G8R8A8_UNORM, + VK_IMAGE_ASPECT_COLOR_BIT); + + sheetview = QFV_CreateImageView (device, skysheet, + VK_IMAGE_VIEW_TYPE_2D_ARRAY, + VK_FORMAT_B8G8R8A8_UNORM, + VK_IMAGE_ASPECT_COLOR_BIT); + + bctx->default_skybox->image = skybox; + bctx->default_skybox->view = boxview; + bctx->default_skybox->memory = memory; + bctx->default_skysheet->image = skysheet; + bctx->default_skysheet->view = sheetview; + + // temporarily commandeer the light map's staging buffer + qfv_packet_t *packet = QFV_PacketAcquire (bctx->light_stage); + VkImageMemoryBarrier barrier; + VkImageMemoryBarrier barriers[2]; + qfv_pipelinestagepair_t stages; + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + barriers[0] = barrier; + barriers[1] = barrier; + barriers[0].image = skybox; + barriers[1].image = skysheet; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 2, barriers); + + VkClearColorValue color = {}; + VkImageSubresourceRange range = { + VK_IMAGE_ASPECT_COLOR_BIT, + 0, VK_REMAINING_MIP_LEVELS, + 0, VK_REMAINING_ARRAY_LAYERS + }; + dfunc->vkCmdClearColorImage (packet->cmd, skybox, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &color, 1, &range); + dfunc->vkCmdClearColorImage (packet->cmd, skysheet, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + &color, 1, &range); + + stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + barriers[0] = barrier; + barriers[1] = barrier; + barriers[0].image = skybox; + barriers[1].image = skysheet; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 2, barriers); + QFV_PacketSubmit (packet); +} + static VkDescriptorBufferInfo base_buffer_info = { 0, 0, VK_WHOLE_SIZE }; @@ -1288,6 +1411,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) size_t size = QFV_ScrapSize (bctx->light_scrap); bctx->light_stage = QFV_CreateStagingBuffer (device, size, ctx->cmdpool); + create_default_skys (ctx); + DARRAY_INIT (&bctx->texture_chains, 64); size_t frames = ctx->framebuffers.size; @@ -1296,6 +1421,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->frames.grow = 0; bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp.main"); + bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp.skysheet"); bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp"); bctx->sampler = QFV_GetSampler (ctx, "quakebsp"); @@ -1309,9 +1435,9 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) for (size_t i = 0; i < frames; i++) { __auto_type bframe = &bctx->frames.a[i]; - bframe->bsp_cmd = cmdBuffers->a[i]; - bframe->turb_cmd = cmdBuffers->a[i]; - bframe->sky_cmd = cmdBuffers->a[i]; + bframe->bsp_cmd = cmdBuffers->a[i * 3 + 0]; + bframe->turb_cmd = cmdBuffers->a[i * 3 + 1]; + bframe->sky_cmd = cmdBuffers->a[i * 3 + 2]; for (int j = 0; j < BSP_BUFFER_INFOS; j++) { bframe->bufferInfo[j] = base_buffer_info; @@ -1338,6 +1464,7 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) bspctx_t *bctx = ctx->bsp_context; dfunc->vkDestroyPipeline (device->dev, bctx->main, 0); + dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0); DARRAY_CLEAR (&bctx->texture_chains); DARRAY_CLEAR (&bctx->frames); QFV_DestroyStagingBuffer (bctx->light_stage); @@ -1350,6 +1477,14 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) dfunc->vkDestroyBuffer (device->dev, bctx->index_buffer, 0); dfunc->vkFreeMemory (device->dev, bctx->index_memory, 0); } + + dfunc->vkDestroyImageView (device->dev, bctx->default_skysheet->view, 0); + dfunc->vkDestroyImage (device->dev, bctx->default_skysheet->image, 0); + + dfunc->vkDestroyImageView (device->dev, bctx->default_skybox->view, 0); + dfunc->vkDestroyImage (device->dev, bctx->default_skybox->image, 0); + dfunc->vkFreeMemory (device->dev, bctx->default_skybox->memory, 0); + free (bctx->default_skybox); } static inline __attribute__((const)) int From 145e7478a748e6df680403bbdbdcb15b24c83c93 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 23:56:33 +0900 Subject: [PATCH 1264/3664] [vid] Create a 32-bit version of the palette The 32-bit palette includes the alpha channel, with color 255's alpha set to 0. --- include/QF/vid.h | 1 + libs/video/targets/vid.c | 29 +++++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/include/QF/vid.h b/include/QF/vid.h index 19618f66c..430e775ab 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -43,6 +43,7 @@ typedef struct { byte *gammatable; // 256 byte *basepal; // 256 * 3 byte *palette; // 256 * 3 + byte *palette32; // 256 * 4 includes alpha byte *colormap8; // 256 * VID_GRADES size unsigned short *colormap16; // 256 * VID_GRADES size unsigned int *colormap32; // 256 * VID_GRADES size diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 651101539..b656b5a22 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -200,6 +200,10 @@ void VID_UpdateGamma (cvar_t *vid_gamma) { double gamma = bound (0.1, vid_gamma->value, 9.9); + byte *p24; + byte *p32; + byte *col; + int i; viddef.recalc_refdef = 1; // force a surface cache flush @@ -207,13 +211,29 @@ VID_UpdateGamma (cvar_t *vid_gamma) Sys_MaskPrintf (SYS_VID, "Setting hardware gamma to %g\n", gamma); VID_BuildGammaTable (1.0); // hardware gamma wants a linear palette VID_SetGamma (gamma); - memcpy (viddef.palette, viddef.basepal, 256 * 3); + p24 = viddef.palette; + p32 = viddef.palette32; + col = viddef.basepal; + for (i = 0; i < 256; i++) { + *p32++ = *p24++ = *col++; + *p32++ = *p24++ = *col++; + *p32++ = *p24++ = *col++; + *p32++ = 255; + } + p32[-1] = 0; // color 255 is transparent } else { // We have to hack the palette - int i; Sys_MaskPrintf (SYS_VID, "Setting software gamma to %g\n", gamma); VID_BuildGammaTable (gamma); - for (i = 0; i < 256 * 3; i++) - viddef.palette[i] = viddef.gammatable[viddef.basepal[i]]; + p24 = viddef.palette; + p32 = viddef.palette32; + col = viddef.basepal; + for (i = 0; i < 256; i++) { + *p32++ = *p24++ = viddef.gammatable[*col++]; + *p32++ = *p24++ = viddef.gammatable[*col++]; + *p32++ = *p24++ = viddef.gammatable[*col++]; + *p32++ = 255; + } + p32[-1] = 0; // color 255 is transparent viddef.vid_internal->set_palette (viddef.palette); // update with the new palette } } @@ -232,6 +252,7 @@ VID_InitGamma (unsigned char *pal) viddef.gammatable = malloc (256); viddef.basepal = pal; viddef.palette = malloc (256 * 3); + viddef.palette32 = malloc (256 * 4); if ((i = COM_CheckParm ("-gamma"))) { gamma = atof (com_argv[i + 1]); } From 3132aa91a82f4d205cc38cb7b0f357077e6fa498 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Jan 2021 23:58:34 +0900 Subject: [PATCH 1265/3664] [vulkan] Get sky sheets working The sky texture is loaded with black's alpha set to 0. While this does hit both layers, the screen is cleared to black so it shouldn't be a problem (and will allow having a skybox behind the sheets). --- include/QF/Vulkan/qf_bsp.h | 5 +++++ libs/models/brush/vulkan_model_brush.c | 16 ++++++++++++---- libs/video/renderer/vulkan/quakebsp.frag | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 16 +++++++--------- libs/video/renderer/vulkan/vulkan_texture.c | 11 ++++++++++- 5 files changed, 35 insertions(+), 15 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 969fdd92c..151e6e7be 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -81,6 +81,11 @@ typedef struct bspframe_s { VkWriteDescriptorSet descriptors[BSP_BUFFER_INFOS + BSP_IMAGE_INFOS]; } bspframe_t; +typedef struct fragconst_s { + quat_t fog; + float time; +} fragconst_t; + typedef struct bspframeset_s DARRAY_TYPE (bspframe_t) bspframeset_t; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index b64e8c11f..c9b336f0f 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -101,7 +101,7 @@ get_image_size (VkImage image, qfv_device_t *device) } static void -transfer_mips (byte *dst, const void *_src, const texture_t *tx) +transfer_mips (byte *dst, const void *_src, const texture_t *tx, byte *palette) { const byte *src = _src; unsigned width = tx->width; @@ -113,7 +113,7 @@ transfer_mips (byte *dst, const void *_src, const texture_t *tx) // end of the texture struct offset = tx->offsets[i] - sizeof (texture_t); count = width * height; - Vulkan_ExpandPalette (dst, src + offset, vid.palette, 1, count); + Vulkan_ExpandPalette (dst, src + offset, palette, 2, count); dst += count * 4; width >>= 1; height >>= 1; @@ -218,6 +218,7 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) for (int i = 0; i < model->numtextures; i++) { texture_t *tx = model->textures[i]; + byte *palette = vid.palette32; if (!tx) { continue; } @@ -227,12 +228,18 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) tex->tex->offset); VkImageViewType type = VK_IMAGE_VIEW_TYPE_2D; if (strncmp (tx->name, "sky", 3) == 0) { + palette = alloca (256 * 4); + memcpy (palette, vid.palette32, 256 * 4); + // sky's black is transparent + // this hits both layers, but so long as the screen is cleared + // to black, no one should notice :) + palette[3] = 0; type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; } tex->tex->view = QFV_CreateImageView (device, tex->tex->image, type, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); - transfer_mips (buffer + tex->tex->offset, tx + 1, tx); + transfer_mips (buffer + tex->tex->offset, tx + 1, tx, palette); if (tex->glow) { dfunc->vkBindImageMemory (device->dev, tex->glow->image, mem, tex->glow->offset); @@ -242,7 +249,8 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); - transfer_mips (buffer + tex->glow->offset, tex->glow->memory, tx); + transfer_mips (buffer + tex->glow->offset, tex->glow->memory, tx, + palette); } } diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/quakebsp.frag index 483a3887e..fe596246e 100644 --- a/libs/video/renderer/vulkan/quakebsp.frag +++ b/libs/video/renderer/vulkan/quakebsp.frag @@ -8,8 +8,8 @@ layout (set = 0, binding = 5) uniform samplerCube SkyCube; layout (push_constant) uniform PushConstants { layout (offset = 64) - float time; vec4 fog; + float time; }; layout (location = 0) in vec4 tl_st; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index bfd54f9e8..6da253bea 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -908,6 +908,9 @@ turb_begin (bspctx_t *bctx) glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; + fragconst_t frag_constants = { time: vr_data.realtime }; + dfunc->vkCmdPushConstants (cmd, bctx->layout, VK_SHADER_STAGE_FRAGMENT_BIT, + 64, sizeof (fragconst_t), &frag_constants); qfeglUniform4fv (quake_turb.fog.location, 1, fog); qfeglUniform1i (quake_turb.palette.location, 1); @@ -967,15 +970,10 @@ sky_begin (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; - //XXX quat_t fog; bctx->default_color[3] = 1; QuatCopy (bctx->default_color, bctx->last_color); - //XXX glsl_Fog_GetColor (fog); - //fog[3] = glsl_Fog_GetDensity () / 64.0; - //qfeglUniform4fv (sky_params.fog->location, 1, fog); - spin (ctx->matrices.sky_3d, bctx); __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; @@ -1121,10 +1119,10 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 16 * sizeof (float), identity); - float frag_pc[8] = { }; + fragconst_t frag_constants = { time: vr_data.realtime }; dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, VK_SHADER_STAGE_FRAGMENT_BIT, - 64, 8 * sizeof (float), &frag_pc); + 64, sizeof (fragconst_t), &frag_constants); //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); for (size_t i = 0; i < bctx->texture_chains.size; i++) { vulktex_t *tex; @@ -1234,10 +1232,10 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, VK_SHADER_STAGE_VERTEX_BIT, 0, 16 * sizeof (float), identity); - float frag_pc[8] = { }; + fragconst_t frag_constants = { time: vr_data.realtime }; dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, VK_SHADER_STAGE_FRAGMENT_BIT, - 64, 8 * sizeof (float), &frag_pc); + 64, sizeof (fragconst_t), &frag_constants); for (is = bctx->sky_chain; is; is = is->tex_chain) { surf = is->surface; if (tex != surf->texinfo->texture->render) { diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 86bd890ab..c1a4e28f0 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -89,7 +89,16 @@ void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, int alpha, int count) { - if (alpha) { + if (alpha > 1) { + while (count-- > 0) { + int pix = *src++; + const byte *col = palette + pix * 4; + *dst++ = *col++; + *dst++ = *col++; + *dst++ = *col++; + *dst++ = *col++; + } + } else if (alpha) { while (count-- > 0) { byte pix = *src++; const byte *col = palette + pix * 3; From ada4f37b9d574d67e015b614d8149a68cf3a3395 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Jan 2021 00:26:38 +0900 Subject: [PATCH 1266/3664] [vulkan] Fix the over-bright dynamic lights I doubt they're anywhere near right, but they're much better. At least they're not just solid blocks of white. --- libs/video/renderer/vulkan/vulkan_lightmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 6c74ab802..0eeed8546 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -114,7 +114,7 @@ add_dynamic_lights (msurface_t *surf, float *block) } if (dist < minlight) { float *out = block + (t * smax + s) * LUXEL_SIZE; - float l = (rad - dist) * 256; + float l = (rad - dist); VectorMultAdd (out, l, light->color, out); out[3] = 1; out += LUXEL_SIZE; From af5415010afeb1ed34f0a44f1ece1136e36c9c68 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Jan 2021 00:54:26 +0900 Subject: [PATCH 1267/3664] [vulkan] Clamp the conback lines to the texture height Fixes the bad background (with deadbeef scrap) --- libs/video/renderer/vulkan/vulkan_draw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 6ec67b227..f4bf8c19e 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -613,6 +613,7 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) qpic_t *cpic; cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx); int ofs = max (0, cpic->height - lines); + lines = min (lines, cpic->height); draw_pic (0, 0, vid.conwidth, lines, cpic, 0, ofs, cpic->width, lines, color, frame); } From 7a19be7265f7396f26c3ecdcc198fff28fe52aaa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 25 Jan 2021 00:54:41 +0900 Subject: [PATCH 1268/3664] [image] Change tex_t data from array to pointer This makes tex_t more generally useable and probably more portable. The goal was to be able to use tex_t with data that is in a separate chunk of memory. --- include/QF/image.h | 2 +- libs/image/pcx.c | 6 ++++-- libs/image/png.c | 6 ++++-- libs/image/tga.c | 3 ++- libs/models/gl_skin.c | 6 ++++-- libs/models/iqm/sw_model_iqm.c | 8 ++++---- libs/models/skin.c | 3 ++- libs/video/renderer/gl/gl_screen.c | 6 ++++-- libs/video/renderer/glsl/glsl_bsp.c | 3 ++- libs/video/renderer/glsl/glsl_screen.c | 3 ++- libs/video/renderer/r_dyn_textures.c | 9 ++++++--- libs/video/renderer/sw/screen.c | 6 ++++-- libs/video/renderer/sw32/screen.c | 3 ++- libs/video/renderer/vulkan/vulkan_texture.c | 9 ++++++--- 14 files changed, 47 insertions(+), 26 deletions(-) diff --git a/include/QF/image.h b/include/QF/image.h index 62d57dd35..c7830c832 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -48,7 +48,7 @@ typedef struct tex_s { QFFormat format; int loaded; // 0 if size info only, otherwise data loaded byte *palette; // 0 = 32 bit, otherwise 8 - byte data[4]; // variable length + byte *data; } tex_t; tex_t *LoadImage (const char *imageFile, int load); diff --git a/libs/image/pcx.c b/libs/image/pcx.c index 495b1b1d5..bfa4fc88d 100644 --- a/libs/image/pcx.c +++ b/libs/image/pcx.c @@ -93,11 +93,13 @@ LoadPCX (QFile *f, qboolean convert, byte *pal, int load) count = load ? (pcx->xmax + 1) * (pcx->ymax + 1) : 0; if (convert) { - tex = Hunk_TempAlloc (field_offset (tex_t, data[count * 3])); + tex = Hunk_TempAlloc (sizeof (tex_t) + count * 3); + tex->data = (byte *) (tex + 1); tex->format = tex_rgb; tex->palette = 0; } else { - tex = Hunk_TempAlloc (field_offset (tex_t, data[count])); + tex = Hunk_TempAlloc (sizeof (tex_t) + count); + tex->data = (byte *) (tex + 1); tex->format = tex_palette; if (pal) tex->palette = pal; diff --git a/libs/image/png.c b/libs/image/png.c index 9e81ca138..ddf9066a9 100644 --- a/libs/image/png.c +++ b/libs/image/png.c @@ -162,9 +162,11 @@ LoadPNG (QFile *infile, int load) /* Allocate tex_t structure */ rowbytes = png_get_rowbytes(png_ptr, info_ptr); - tex = Hunk_TempAlloc (field_offset (tex_t, data[height * rowbytes])); + tex = Hunk_TempAlloc (sizeof (tex_t) + height * rowbytes); + tex->data = (byte *) (tex + 1); } else { - tex = Hunk_TempAlloc (field_offset (tex_t, data[0])); + tex = Hunk_TempAlloc (sizeof (tex_t)); + tex->data = 0; } tex->width = width; diff --git a/libs/image/tga.c b/libs/image/tga.c index 1a4dad133..1f72e2687 100644 --- a/libs/image/tga.c +++ b/libs/image/tga.c @@ -655,7 +655,8 @@ LoadTGA (QFile *fin, int load) } else { numPixels = 0; } - tex = Hunk_TempAlloc (field_offset (tex_t, data[numPixels * 4])); + tex = Hunk_TempAlloc (sizeof (tex_t) + numPixels * 4); + tex->data = (byte *) (tex + 1); tex->width = targa->width; tex->height = targa->height; tex->palette = 0; diff --git a/libs/models/gl_skin.c b/libs/models/gl_skin.c index 442def004..e88fbf2d6 100644 --- a/libs/models/gl_skin.c +++ b/libs/models/gl_skin.c @@ -72,7 +72,8 @@ do_fb_skin (glskin_t *s) { int size = s->tex->width * s->tex->height; - s->fb_tex = realloc (s->fb_tex, field_offset(tex_t, data[size])); + s->fb_tex = realloc (s->fb_tex, sizeof (tex_t) + size); + s->fb_tex->data = (byte *) (s->fb_tex + 1); s->fb_tex->width = s->tex->width; s->fb_tex->height = s->tex->height; s->fb_tex->format = tex_palette; @@ -87,7 +88,8 @@ gl_Skin_SetPlayerSkin (int width, int height, const byte *data) glskin_t *s; s = &player_skin; - s->tex = realloc (s->tex, field_offset(tex_t, data[size])); + s->tex = realloc (s->tex, sizeof (tex_t) + size); + s->tex->data = (byte *) (s->tex + 1); s->tex->width = width; s->tex->height = height; s->tex->format = tex_palette; diff --git a/libs/models/iqm/sw_model_iqm.c b/libs/models/iqm/sw_model_iqm.c index 582109a73..274a6f0a9 100644 --- a/libs/models/iqm/sw_model_iqm.c +++ b/libs/models/iqm/sw_model_iqm.c @@ -53,9 +53,8 @@ #include "mod_internal.h" #include "r_internal.h" -static tex_t null_texture = { - 2, 2, tex_palette, 1, 0, {15, 15, 15, 15} -}; +static byte null_data[] = {15, 15, 15, 15}; +static tex_t null_texture = { 2, 2, tex_palette, 1, 0, null_data }; static void sw_iqm_clear (model_t *mod, void *data) @@ -109,7 +108,8 @@ convert_tex (tex_t *tex) int i; pixels = tex->width * tex->height; - new = malloc (field_offset (tex_t, data[pixels])); + new = malloc (sizeof (tex_t) + pixels); + new->data = (byte *) (new + 1); new->width = tex->width; new->height = tex->height; new->format = tex_palette; diff --git a/libs/models/skin.c b/libs/models/skin.c index 5e1fe0d85..9897a4143 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -193,7 +193,8 @@ Skin_SetSkin (skin_t *skin, int cmap, const char *skinname) tex = 0; break; } - out = malloc (field_offset (tex_t, data[PLAYER_WIDTH*PLAYER_HEIGHT])); + out = malloc (sizeof (tex_t) + PLAYER_WIDTH*PLAYER_HEIGHT); + out->data = (byte *) (out + 1); out->width = PLAYER_WIDTH; out->height = PLAYER_HEIGHT; out->format = tex_palette; diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 5758b5941..f8b0e6546 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -70,7 +70,8 @@ gl_SCR_CaptureBGR (void) tex_t *tex; count = vid.width * vid.height; - tex = malloc (field_offset (tex_t, data[count * 3])); + tex = malloc (sizeof (tex_t) + count * 3); + tex->data = (byte *) (tex + 1); SYS_CHECKMEM (tex); tex->width = vid.width; tex->height = vid.height; @@ -100,7 +101,8 @@ gl_SCR_ScreenShot (int width, int height) fracw = (float) vid.width / (float) w; frach = (float) vid.height / (float) h; - tex = malloc (field_offset (tex_t, data[w * h])); + tex = malloc (sizeof (tex_t) + w * h); + tex->data = (byte *) (tex + 1); if (!tex) return 0; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 409450901..144f8094c 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -1409,7 +1409,8 @@ glsl_R_LoadSkys (const char *sky) int size = tex->height / 2; skybox_loaded = true; - sub = malloc (field_offset (tex_t, data[size * size * tex->format])); + sub = malloc (sizeof (tex_t) + size * size * tex->format); + sub->data = (byte *) (sub + 1); sub->width = size; sub->height = size; sub->format = tex->format; diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index 098f6a816..a19d3205a 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -201,7 +201,8 @@ glsl_SCR_CaptureBGR (void) tex_t *tex; count = vid.width * vid.height; - tex = malloc (field_offset (tex_t, data[count * 3])); + tex = malloc (sizeof (tex_t) + count * 3); + tex->data = (byte *) (tex + 1); SYS_CHECKMEM (tex); tex->width = vid.width; tex->height = vid.height; diff --git a/libs/video/renderer/r_dyn_textures.c b/libs/video/renderer/r_dyn_textures.c index 167027fad..67b0862c6 100644 --- a/libs/video/renderer/r_dyn_textures.c +++ b/libs/video/renderer/r_dyn_textures.c @@ -50,7 +50,8 @@ R_DotParticleTexture (void) int x, y, dx2, dy, d; tex_t *tex; - tex = malloc (field_offset (tex_t, data[sizeof (*data)])); + tex = malloc (sizeof (tex_t) + sizeof (*data)); + tex->data = (byte *) (tex + 1); tex->width = 32; tex->height = 32; tex->format = tex_la; @@ -79,7 +80,8 @@ R_SparkParticleTexture (void) int x, y, dx2, dy, d; tex_t *tex; - tex = malloc (field_offset (tex_t, data[sizeof (*data)])); + tex = malloc (sizeof (tex_t) + sizeof (*data)); + tex->data = (byte*) (tex + 1); tex->width = 32; tex->height = 32; tex->format = tex_la; @@ -113,7 +115,8 @@ R_SmokeParticleTexture (void) int x, y, c; tex_t *tex; - tex = malloc (field_offset (tex_t, data[sizeof (*data)])); + tex = malloc (sizeof (tex_t) + sizeof (*data)); + tex->data = (byte *) (tex + 1); tex->width = 32; tex->height = 32; tex->format = tex_la; diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 4ab9302c1..125d8648f 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -64,7 +64,8 @@ SCR_CaptureBGR (void) byte *dst; count = vid.width * vid.height; - tex = malloc (field_offset (tex_t, data[count * 3])); + tex = malloc (sizeof (tex_t) + count * 3); + tex->data = (byte *) (tex + 1); SYS_CHECKMEM (tex); tex->width = vid.width; tex->height = vid.height; @@ -102,7 +103,8 @@ SCR_ScreenShot (int width, int height) fracw = (float) vid.width / (float) w; frach = (float) vid.height / (float) h; - tex = malloc (field_offset (tex_t, data[w * h])); + tex = malloc (sizeof (tex_t) + w * h); + tex->data = (byte *) (tex + 1); if (!tex) return 0; diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index 543c8602a..ce84cb08c 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -67,7 +67,8 @@ sw32_SCR_CaptureBGR (void) byte *dst; count = vid.width * vid.height; - tex = malloc (field_offset (tex_t, data[count * 3])); + tex = malloc (sizeof (tex_t) + count * 3); + tex->data = (byte *) (tex + 1); SYS_CHECKMEM (tex); tex->width = vid.width; tex->height = vid.height; diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index c1a4e28f0..07bcc7f0a 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -282,9 +282,12 @@ Vulkan_UnloadTex (vulkan_ctx_t *ctx, qfv_tex_t *tex) free (tex); } -static tex_t default_black_tex = {1, 1, tex_rgba, 1, 0, {0, 0, 0, 0 }}; -static tex_t default_white_tex = {1, 1, tex_rgba, 1, 0, {255, 255, 255, 255 }}; -static tex_t default_magenta_tex = {1, 1, tex_rgba, 1, 0, {255, 0, 255, 255 }}; +static byte black_data[] = {0, 0, 0, 0}; +static byte white_data[] = {255, 255, 255, 255}; +static byte magenta_data[] = {255, 0, 255, 255}; +static tex_t default_black_tex = {1, 1, tex_rgba, 1, 0, black_data}; +static tex_t default_white_tex = {1, 1, tex_rgba, 1, 0, white_data}; +static tex_t default_magenta_tex = {1, 1, tex_rgba, 1, 0, magenta_data}; void Vulkan_Texture_Init (vulkan_ctx_t *ctx) From d8b81e86787ec19a6d4dc1e92cecb5fb5768fbea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 25 Jan 2021 13:31:41 +0900 Subject: [PATCH 1269/3664] [models] Remove MAXALIASFRAMES The dynamic array macros made this much easier than last time I looked at it, especially when it came to figuring out the bad memory accesses that I seem to remember from my last attempt 9 years ago. --- include/QF/model.h | 11 +++++---- libs/models/alias/gl_mesh.c | 32 ++++++++++++------------- libs/models/alias/glsl_model_alias.c | 6 ++--- libs/models/alias/model_alias.c | 36 ++++++++++------------------ libs/models/alias/sw_model_alias.c | 12 +++++----- 5 files changed, 44 insertions(+), 53 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 8d0129721..703d11227 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -28,6 +28,7 @@ #ifndef __QF_model_h #define __QF_model_h +#include "QF/darray.h" #include "QF/qtypes.h" #include "QF/bspfile.h" #include "QF/spritegn.h" @@ -320,11 +321,13 @@ typedef struct { maliasframedesc_t frames[1]; } aliashdr_t; -#define MAXALIASFRAMES 256 +typedef struct stvertset_s DARRAY_TYPE (stvert_t) stvertset_t; +typedef struct mtriangleset_s DARRAY_TYPE (mtriangle_t) mtriangleset_t; +typedef struct trivertxset_s DARRAY_TYPE (trivertx_t *) trivertxset_t; extern aliashdr_t *pheader; -extern stvert_t *stverts; -extern mtriangle_t *triangles; -extern trivertx_t *poseverts[MAXALIASFRAMES]; +extern stvertset_t stverts; +extern mtriangleset_t triangles; +extern trivertxset_t poseverts; extern int aliasbboxmins[3]; extern int aliasbboxmaxs[3]; diff --git a/libs/models/alias/gl_mesh.c b/libs/models/alias/gl_mesh.c index 22498ddea..c55225057 100644 --- a/libs/models/alias/gl_mesh.c +++ b/libs/models/alias/gl_mesh.c @@ -133,7 +133,7 @@ StripLength (int starttri, int startv) used[starttri] = 2; - last = &triangles[starttri]; + last = &triangles.a[starttri]; stripcount = 0; add_strip (last->vertindex[(startv) % 3], starttri); @@ -145,7 +145,7 @@ StripLength (int starttri, int startv) // look for a matching triangle nexttri: - for (j = starttri + 1, check = &triangles[starttri + 1]; + for (j = starttri + 1, check = &triangles.a[starttri + 1]; j < pheader->mdl.numtris; j++, check++) { if (check->facesfront != last->facesfront) continue; @@ -191,7 +191,7 @@ FanLength (int starttri, int startv) used[starttri] = 2; - last = &triangles[starttri]; + last = &triangles.a[starttri]; stripcount = 0; add_strip (last->vertindex[(startv) % 3], starttri); @@ -204,7 +204,7 @@ FanLength (int starttri, int startv) // look for a matching triangle nexttri: - for (j = starttri + 1, check = &triangles[starttri + 1]; + for (j = starttri + 1, check = &triangles.a[starttri + 1]; j < pheader->mdl.numtris; j++, check++) { if (check->facesfront != last->facesfront) continue; @@ -304,9 +304,9 @@ BuildTris (void) add_vertex (k); // emit s/t coords into the commands stream - s = stverts[k].s; - t = stverts[k].t; - if (!triangles[besttris[0]].facesfront && stverts[k].onseam) + s = stverts.a[k].s; + t = stverts.a[k].t; + if (!triangles.a[besttris[0]].facesfront && stverts.a[k].onseam) s += pheader->mdl.skinwidth / 2; // on back side s = (s + 0.5) / pheader->mdl.skinwidth; t = (t + 0.5) / pheader->mdl.skinheight; @@ -485,9 +485,9 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, numorder = 0; for (i=0; i < pheader->mdl.numtris; i++) { - add_vertex(triangles[i].vertindex[0]); - add_vertex(triangles[i].vertindex[1]); - add_vertex(triangles[i].vertindex[2]); + add_vertex(triangles.a[i].vertindex[0]); + add_vertex(triangles.a[i].vertindex[1]); + add_vertex(triangles.a[i].vertindex[2]); } paliashdr->poseverts = numorder; @@ -497,9 +497,9 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, float s, t; int k; k = vertexorder[i]; - s = stverts[k].s; - t = stverts[k].t; - if (!triangles[i/3].facesfront && stverts[k].onseam) + s = stverts.a[k].s; + t = stverts.a[k].t; + if (!triangles.a[i/3].facesfront && stverts.a[k].onseam) s += pheader->mdl.skinwidth / 2; // on back side s = (s + 0.5) / pheader->mdl.skinwidth; t = (t + 0.5) / pheader->mdl.skinheight; @@ -514,7 +514,7 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, * sizeof (trivertx16_t)); paliashdr->posedata = (byte *) verts - (byte *) paliashdr; for (i = 0; i < paliashdr->numposes; i++) { - trivertx_t *pv = poseverts[i]; + trivertx_t *pv = poseverts.a[i]; for (j = 0; j < numorder; j++) { trivertx16_t v; // convert MD16's split coordinates into something a little @@ -526,7 +526,7 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, VectorMultAdd (pv[vertexorder[j] + hdr->mdl.numverts].v, 256, pv[vertexorder[j]].v, v.v); v.lightnormalindex = - poseverts[i][vertexorder[j]].lightnormalindex; + poseverts.a[i][vertexorder[j]].lightnormalindex; *verts++ = v; } } @@ -537,7 +537,7 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, paliashdr->posedata = (byte *) verts - (byte *) paliashdr; for (i = 0; i < paliashdr->numposes; i++) { for (j = 0; j < numorder; j++) - *verts++ = poseverts[i][vertexorder[j]]; + *verts++ = poseverts.a[i][vertexorder[j]]; } } dstring_delete (cache); diff --git a/libs/models/alias/glsl_model_alias.c b/libs/models/alias/glsl_model_alias.c index 215c9d400..cb612e962 100644 --- a/libs/models/alias/glsl_model_alias.c +++ b/libs/models/alias/glsl_model_alias.c @@ -147,7 +147,7 @@ glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, // copy triangles before editing them tris = malloc (numtris * sizeof (mtriangle_t)); - memcpy (tris, triangles, numtris * sizeof (mtriangle_t)); + memcpy (tris, triangles.a, numtris * sizeof (mtriangle_t)); // initialize indexmap to -1 (unduplicated). any other value indicates // both that the vertex has been duplicated and the index of the @@ -157,7 +157,7 @@ glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, // copy stverts. need space for duplicates st = malloc (2 * numverts * sizeof (stvert_t)); - memcpy (st, stverts, numverts * sizeof (stvert_t)); + memcpy (st, stverts.a, numverts * sizeof (stvert_t)); // check for onseam verts, and duplicate any that are associated with // back-facing triangles. the s coordinate is shifted right by half @@ -182,7 +182,7 @@ glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, verts = malloc (vertexsize); for (i = 0, pose = 0; i < hdr->numposes; i++, pose += numverts) { for (j = 0; j < hdr->mdl.numverts; j++) { - pv = &poseverts[i][j]; + pv = &poseverts.a[i][j]; if (extra) { VectorMultAdd (pv[hdr->mdl.numverts].v, 256, pv->v, verts[pose + j].vertex); diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index 8a4784b2d..c5018f929 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -51,14 +51,12 @@ aliashdr_t *pheader; -stvert_t *stverts; -mtriangle_t *triangles; -int stverts_size = 0; -int triangles_size = 0; +stvertset_t stverts = { 0, 0, 256 }; +mtriangleset_t triangles = { 0, 0, 256 }; // a pose is a single set of vertexes. a frame may be an animating // sequence of poses -trivertx_t *poseverts[MAXALIASFRAMES]; +trivertxset_t poseverts = { 0, 0, 256 };; int posenum = 0; int aliasbboxmins[3], aliasbboxmaxs[3]; @@ -151,7 +149,7 @@ Mod_LoadAliasFrame (void *pin, int *posenum, maliasframedesc_t *frame, pinframe = (trivertx_t *) (pdaliasframe + 1); - poseverts[(*posenum)] = pinframe; + DARRAY_APPEND (&poseverts, pinframe); (*posenum)++; pinframe += pheader->mdl.numverts; @@ -264,30 +262,20 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) Sys_Error ("model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT); + DARRAY_RESIZE (&poseverts, 0); pmodel->numverts = LittleLong (pinmodel->numverts); if (pmodel->numverts <= 0) Sys_Error ("model %s has no vertices", mod->name); - if (pmodel->numverts > stverts_size) { - stverts = realloc (stverts, pmodel->numverts * sizeof (stvert_t)); - if (!stverts) - Sys_Error ("model_alias: out of memory"); - stverts_size = pmodel->numverts; - } + DARRAY_RESIZE (&stverts, pmodel->numverts); pmodel->numtris = LittleLong (pinmodel->numtris); if (pmodel->numtris <= 0) Sys_Error ("model %s has no triangles", mod->name); - if (pmodel->numtris > triangles_size) { - triangles = realloc (triangles, - pmodel->numtris * sizeof (mtriangle_t)); - if (!triangles) - Sys_Error ("model_alias: out of memory"); - triangles_size = pmodel->numtris; - } + DARRAY_RESIZE (&triangles, pmodel->numtris); pmodel->numframes = LittleLong (pinmodel->numframes); numframes = pmodel->numframes; @@ -313,19 +301,19 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) pinstverts = (stvert_t *) pskintype; for (i = 0; i < pheader->mdl.numverts; i++) { - stverts[i].onseam = LittleLong (pinstverts[i].onseam); - stverts[i].s = LittleLong (pinstverts[i].s); - stverts[i].t = LittleLong (pinstverts[i].t); + stverts.a[i].onseam = LittleLong (pinstverts[i].onseam); + stverts.a[i].s = LittleLong (pinstverts[i].s); + stverts.a[i].t = LittleLong (pinstverts[i].t); } // load triangle lists pintriangles = (dtriangle_t *) &pinstverts[pheader->mdl.numverts]; for (i = 0; i < pheader->mdl.numtris; i++) { - triangles[i].facesfront = LittleLong (pintriangles[i].facesfront); + triangles.a[i].facesfront = LittleLong (pintriangles[i].facesfront); for (j = 0; j < 3; j++) { - triangles[i].vertindex[j] = + triangles.a[i].vertindex[j] = LittleLong (pintriangles[i].vertindex[j]); } } diff --git a/libs/models/alias/sw_model_alias.c b/libs/models/alias/sw_model_alias.c index b252ad474..e021278a4 100644 --- a/libs/models/alias/sw_model_alias.c +++ b/libs/models/alias/sw_model_alias.c @@ -79,7 +79,7 @@ process_frame (maliasframedesc_t *frame, int posenum, int extra) // from the high-order bits (see R_AliasTransformFinalVert16 in // sw_ralias.c), but in adjacant arrays. This means we can get away with // just one memcpy as there are no endian issues. - memcpy (frame_verts, poseverts[posenum], size); + memcpy (frame_verts, poseverts.a[posenum], size); } void @@ -101,14 +101,14 @@ sw_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, hdr->triangles = (byte *) ptri - (byte *) hdr; for (i = 0; i < numv; i++) { - pstverts[i].onseam = stverts[i].onseam; - pstverts[i].s = stverts[i].s << 16; - pstverts[i].t = stverts[i].t << 16; + pstverts[i].onseam = stverts.a[i].onseam; + pstverts[i].s = stverts.a[i].s << 16; + pstverts[i].t = stverts.a[i].t << 16; } for (i = 0; i < numt; i++) { - ptri[i].facesfront = triangles[i].facesfront; - VectorCopy (triangles[i].vertindex, ptri[i].vertindex); + ptri[i].facesfront = triangles.a[i].facesfront; + VectorCopy (triangles.a[i].vertindex, ptri[i].vertindex); } for (i = 0; i < pheader->mdl.numframes; i++) { From 3bbe33844ae76876aa7026be05566a8d365ef130 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jan 2021 00:39:34 +0900 Subject: [PATCH 1270/3664] [util] Add component-wise vector mult-add/sub macros --- include/QF/math/vector.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 993cbaf08..630332907 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -74,6 +74,18 @@ extern const vec_t *const vec3_origin; (c)[1] = (a)[1] - (s) * (b)[1]; \ (c)[2] = (a)[2] - (s) * (b)[2]; \ } while (0) +#define VectorCompMultAdd(a,b,c,d) \ + do { \ + (d)[0] = (a)[0] + (b)[0] * (c)[0]; \ + (d)[1] = (a)[1] + (b)[1] * (c)[1]; \ + (d)[2] = (a)[2] + (b)[2] * (c)[2]; \ + } while (0) +#define VectorCompMultSub(a,b,c,d) \ + do { \ + (d)[0] = (a)[0] - (b)[0] * (c)[0]; \ + (d)[1] = (a)[1] - (b)[1] * (c)[1]; \ + (d)[2] = (a)[2] - (b)[2] * (c)[2]; \ + } while (0) #define VectorLength(a) sqrt(DotProduct(a, a)) #define VectorScale(a,b,c) \ From 57968249feb6ec0c8394148d75272909e54e967e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jan 2021 00:55:45 +0900 Subject: [PATCH 1271/3664] [vulkan] Start work on the alias pipeline --- include/QF/Vulkan/qf_alias.h | 84 ++++++ include/QF/model.h | 13 +- libs/models/alias/vulkan_model_alias.c | 291 ++++++++++++++++++++ libs/video/renderer/Makemodule.am | 10 + libs/video/renderer/vid_render_vulkan.c | 6 +- libs/video/renderer/vulkan/alias.frag | 55 ++++ libs/video/renderer/vulkan/alias.vert | 38 +++ libs/video/renderer/vulkan/qfpipeline.plist | 201 +++++++++++++- libs/video/renderer/vulkan/shader.c | 6 + libs/video/renderer/vulkan/vulkan_bsp.c | 9 +- 10 files changed, 695 insertions(+), 18 deletions(-) create mode 100644 include/QF/Vulkan/qf_alias.h create mode 100644 libs/video/renderer/vulkan/alias.frag create mode 100644 libs/video/renderer/vulkan/alias.vert diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h new file mode 100644 index 000000000..efe3dd0dc --- /dev/null +++ b/include/QF/Vulkan/qf_alias.h @@ -0,0 +1,84 @@ +/* + qf_alias.h + + Vulkan specific brush model stuff + + Copyright (C) 2012 Bill Currie + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2012/1/7 + Date: 2021/1/18 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_alias_h +#define __QF_Vulkan_qf_alias_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/modelgen.h" +#include "QF/Vulkan/qf_vid.h" + +typedef struct aliasvrt_s { + float vertex[4]; + float normal[4]; +} aliasvrt_t; + +typedef struct aliasuv_s { + float u, v; +} aliasuv_t; + +typedef struct qfv_alias_mesh_s { + VkBuffer vertex_buffer; + VkBuffer uv_buffer; + VkBuffer index_buffer; + VkDeviceMemory memory; +} qfv_alias_mesh_t; + +typedef struct qfv_light_s { + vec3_t color; + float dist; + vec3_t position; + int type; + vec3_t direction; + float cone; +} qfv_light_t; + +typedef struct qfv_light_buffer_s { + int light_count; + qfv_light_t lights[] __attribute__((aligned(16))); +} qfv_light_buffer_t; + +typedef struct alias_ctx_s { +} alias_ctx_t; + +struct vulkan_ctx_s; +void *Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, + qboolean group, maliasskindesc_t *skindesc, + struct vulkan_ctx_s *ctx); +void Vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr, + struct vulkan_ctx_s *ctx); +void Vulkan_Mod_LoadExternalSkins (model_t *mod, struct vulkan_ctx_s *ctx); +void Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, + void *_m, int _s, int extra, + struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_alias_h diff --git a/include/QF/model.h b/include/QF/model.h index 703d11227..d1129bfce 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -277,10 +277,15 @@ typedef struct { } maliasframedesc_t; typedef struct { - aliasskintype_t type; - int skin; - int texnum; - int fb_texnum; + aliasskintype_t type; + int skin; + union { + struct { + int texnum; + int fb_texnum; + }; + void *tex; + }; } maliasskindesc_t; typedef struct { diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index e69de29bb..97801febc 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -0,0 +1,291 @@ +/* + vulkan_model_alais.c + + Alias model processing for Vulkan + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/1/24 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include "QF/va.h" + +#include "QF/modelgen.h" +#include "QF/vid.h" +#include "QF/Vulkan/qf_alias.h" +#include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/staging.h" + +#include "mod_internal.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +static vec3_t vertex_normals[NUMVERTEXNORMALS] = { +#include "anorms.h" +}; + +static void +vulkan_alias_clear (model_t *m, void *data) +{ +} + +void * +Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, + qboolean group, maliasskindesc_t *skindesc, + vulkan_ctx_t *ctx) +{ + byte *tskin; + int w, h; + + w = pheader->mdl.skinwidth; + h = pheader->mdl.skinheight; + tskin = malloc (skinsize); + memcpy (tskin, skin, skinsize); + Mod_FloodFillSkin (tskin, w, h); + tex_t skin_tex = {w, h, tex_palette, 1, vid.palette, tskin}; + skindesc->tex = Vulkan_LoadTex (ctx, &skin_tex, 1); + free (tskin); + return skin + skinsize; +} + +void +Vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr, vulkan_ctx_t *ctx) +{ + if (hdr->mdl.ident == HEADER_MDL16) + VectorScale (hdr->mdl.scale, 1/256.0, hdr->mdl.scale); + m->clear = vulkan_alias_clear; +} + +void +Vulkan_Mod_LoadExternalSkins (model_t *mod, vulkan_ctx_t *ctx) +{ +} + +void +Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, + int _s, int extra, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliasvrt_t *verts; + aliasuv_t *uv; + trivertx_t *pv; + int *indexmap; + uint32_t *indices; + int numverts; + int numtris; + int i, j; + int pose; + vec3_t pos; + + numverts = hdr->mdl.numverts; + numtris = hdr->mdl.numtris; + + // initialize indexmap to -1 (unduplicated). any other value indicates + // both that the vertex has been duplicated and the index of the + // duplicate vertex. + indexmap = malloc (numverts * sizeof (int)); + memset (indexmap, -1, numverts * sizeof (int)); + + // check for onseam verts, and duplicate any that are associated with + // back-facing triangles + for (i = 0; i < numtris; i++) { + for (j = 0; j < 3; j++) { + int vind = triangles.a[i].vertindex[j]; + if (stverts.a[vind].onseam && !triangles.a[i].facesfront) { + // duplicate the vertex if it has not alreaddy been + // duplicated + if (indexmap[vind] == -1) { + indexmap[vind] = numverts++; + } + } + } + } + + // we now know exactly how many vertices we need, so built the vertex + // and index data arrays + // The layout is: + // vbuf:{vertex, normal} * (numposes * numverts) + // uvbuf:{uv} * (numverts) + // ibuf:{index} * (numtris * 3) + // numverts includes the duplicated seam vertices. + // The vertex buffer will be bound with various offsets based on the + // current and previous pose, uvbuff "statically" bound as uvs are not + // animated by pose, and the same for ibuf: indices will never change for + // the mesh + size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + size_t atom_mask = atom - 1; + size_t vert_count = numverts * hdr->numposes; + size_t vert_size = vert_count * sizeof (aliasvrt_t); + size_t uv_size = numverts * sizeof (aliasuv_t); + size_t ind_size = numverts * sizeof (uint32_t); + vert_size = (vert_size + atom_mask) & ~atom_mask; + uv_size = (uv_size + atom_mask) & ~atom_mask; + ind_size = (ind_size + atom_mask) & ~atom_mask; + size_t buff_size = vert_size + ind_size + uv_size; + + VkBuffer vbuff = QFV_CreateBuffer (device, buff_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + VkBuffer uvbuff = QFV_CreateBuffer (device, buff_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + VkBuffer ibuff = QFV_CreateBuffer (device, buff_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + VkDeviceMemory mem; + mem = QFV_AllocBufferMemory (device, vbuff, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + buff_size, 0); + QFV_BindBufferMemory (device, vbuff, mem, 0); + QFV_BindBufferMemory (device, uvbuff, mem, vert_size); + QFV_BindBufferMemory (device, ibuff, mem, vert_size + uv_size); + + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, buff_size, + ctx->cmdpool); + qfv_packet_t *packet = QFV_PacketAcquire (stage); + verts = QFV_PacketExtend (packet, vert_size); + uv = QFV_PacketExtend (packet, uv_size); + indices = QFV_PacketExtend (packet, ind_size); + + // populate the uvs, duplicating and shifting any that are on the seam + // and associated with back-facing triangles (marked by non-negative + // indexmap entry). + // the s coordinate is shifted right by half the skin width. + for (i = 0; i < hdr->mdl.numverts; i++) { + int vind = indexmap[i]; + uv[i].u = (float) stverts.a[i].s / hdr->mdl.skinwidth; + uv[i].v = (float) stverts.a[i].t / hdr->mdl.skinheight; + if (vind != -1) { + uv[vind] = uv[i]; + uv[vind].u += 0.5; + } + } + + // poputlate the vertex position and normal data, duplicating for + // back-facing on-seam verts (indicated by non-negative indexmap entry) + for (i = 0, pose = 0; i < hdr->numposes; i++, pose += numverts) { + for (j = 0; j < hdr->mdl.numverts; j++) { + pv = &poseverts.a[i][j]; + if (extra) { + VectorMultAdd (pv[hdr->mdl.numverts].v, 256, pv->v, pos); + } else { + VectorCopy (pv->v, pos); + } + VectorCompMultAdd (hdr->mdl.scale_origin, hdr->mdl.scale, + pos, verts[pose + j].vertex); + VectorCopy (vertex_normals[pv->lightnormalindex], + verts[pose + j].normal); + // duplicate on-seam vert associated with back-facing triangle + if (indexmap[j] != -1) { + verts[pose + indexmap[j]] = verts[pose + j]; + } + } + } + + // now build the indices for DrawElements + for (i = 0; i < numverts; i++) { + indexmap[i] = indexmap[i] != -1 ? indexmap[i] : i; + } + for (i = 0; i < numtris; i++) { + for (j = 0; j < 3; j++) { + indices[3 * i + j] = indexmap[triangles.a[i].vertindex[j]]; + } + } + // finished with indexmap + free (indexmap); + + hdr->poseverts = numverts; + + VkBufferMemoryBarrier wr_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + vbuff, 0, vert_size}, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + uvbuff, 0, uv_size}, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + ibuff, 0, ind_size}, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, 0, 3, wr_barriers, 0, 0); + VkBufferCopy copy_region[] = { + { packet->offset, 0, vert_size }, + { packet->offset + vert_size, 0, uv_size }, + { packet->offset + vert_size + uv_size, 0, ind_size }, + }; + dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, + vbuff, 1, ©_region[0]); + dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, + uvbuff, 1, ©_region[1]); + dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, + ibuff, 1, ©_region[2]); + VkBufferMemoryBarrier rd_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + vbuff, 0, vert_size }, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + uvbuff, 0, uv_size }, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + ibuff, 0, ind_size }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + 0, 0, 0, 1, rd_barriers, 0, 0); + QFV_PacketSubmit (packet); + QFV_DestroyStagingBuffer (stage); + + qfv_alias_mesh_t *mesh = Hunk_Alloc (sizeof (qfv_alias_mesh_t)); + mesh->vertex_buffer = vbuff; + mesh->uv_buffer = uvbuff; + mesh->index_buffer = ibuff; + mesh->memory = mem; + hdr->commands = (byte *) mesh - (byte *) hdr; +} diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 5a30c9f0c..e3b154541 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -269,6 +269,10 @@ quakebspv_src = libs/video/renderer/vulkan/quakebsp.vert quakebspv_c = libs/video/renderer/vulkan/quakebsp.vert.spvc quakebspf_src = libs/video/renderer/vulkan/quakebsp.frag quakebspf_c = libs/video/renderer/vulkan/quakebsp.frag.spvc +aliasv_src = libs/video/renderer/vulkan/alias.vert +aliasv_c = libs/video/renderer/vulkan/alias.vert.spvc +aliasf_src = libs/video/renderer/vulkan/alias.frag +aliasf_c = libs/video/renderer/vulkan/alias.frag.spvc passthrough_src = libs/video/renderer/vulkan/passthrough.vert passthrough_c = libs/video/renderer/vulkan/passthrough.vert.spvc pushcolor_src = libs/video/renderer/vulkan/pushcolor.frag @@ -282,6 +286,10 @@ $(quakebspv_c): $(quakebspv_src) $(quakebspf_c): $(quakebspf_src) +$(aliasv_c): $(aliasv_src) + +$(aliasf_c): $(aliasf_src) + $(passthrough_c): $(passthrough_src) $(pushcolor_c): $(pushcolor_src) @@ -291,6 +299,8 @@ vkshader_c = \ $(twodf_c) \ $(quakebspv_c) \ $(quakebspf_c) \ + $(aliasv_c) \ + $(aliasf_c) \ $(passthrough_c) \ $(pushcolor_c) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a54962b52..2b001bcd3 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -39,6 +39,7 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_lightmap.h" @@ -419,18 +420,21 @@ static void vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra) { + Vulkan_Mod_MakeAliasModelDisplayLists (m, hdr, _m, _s, extra, vulkan_ctx); } static void * vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) { - return skin + skinsize; + return Vulkan_Mod_LoadSkin (skin, skinsize, snum, gnum, group, skindesc, + vulkan_ctx); } static void vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr) { + Vulkan_Mod_FinalizeAliasModel (m, hdr, vulkan_ctx); } static void diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/alias.frag new file mode 100644 index 000000000..935fa06b4 --- /dev/null +++ b/libs/video/renderer/vulkan/alias.frag @@ -0,0 +1,55 @@ +#version 450 + +layout (set = 0, binding = 1) uniform sampler2D Texture; +layout (set = 0, binding = 2) uniform sampler2D GlowMap; +layout (set = 0, binding = 3) uniform sampler2D ColorA; +layout (set = 0, binding = 4) uniform sampler2D ColorB; + +struct LightData { + vec3 color; + float dist; + vec3 position; + int type; + vec3 direction; + float cone; +}; + +layout (constant_id = 0) const int MaxLights = 8; +layout (set = 1, binding = 0) uniform Lights { + int light_count; + LightData lights[MaxLights]; +}; + +layout (push_constant) uniform PushConstants { + layout (offset = 80) + vec4 fog; + vec4 color; +}; + +layout (location = 0) in vec2 st; +layout (location = 1) in vec3 position; +layout (location = 2) in vec3 normal; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + vec4 c; + int i; + vec3 light = vec3 (0); + + c = texture (Texture, st); + c += texture (ColorA, st); + c += texture (ColorB, st); + c += texture (GlowMap, st); + if (MaxLights > 0) { + for (i = 0; i < light_count; i++) { + vec3 dist = lights[i].position - position; + float dd = dot (dist, dist); + float mag = max (0.0, dot (dist, normal)); + light += lights[i].color * mag * lights[i].dist / dd; + } + } + frag_color = c * vec4(light, 1);//fogBlend (c); +} diff --git a/libs/video/renderer/vulkan/alias.vert b/libs/video/renderer/vulkan/alias.vert new file mode 100644 index 000000000..871c3a0c0 --- /dev/null +++ b/libs/video/renderer/vulkan/alias.vert @@ -0,0 +1,38 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection; + mat4 View; + mat4 Sky; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; + float blend; +}; + +layout (location = 0) in vec4 vertexa; +layout (location = 1) in vec3 normala; +layout (location = 2) in vec4 vertexb; +layout (location = 3) in vec3 normalb; +layout (location = 4) in vec2 uv; + +layout (location = 0) out vec2 st; +layout (location = 1) out vec3 position; +layout (location = 2) out vec3 normal; + +void +main (void) +{ + vec4 vertex; + vec3 norm; + vec4 pos; + + vertex = mix (vertexa, vertexb, blend); + norm = mix (normala, normalb, blend); + pos = (Model * vertex); + gl_Position = Projection * (View * pos); + position = pos.xyz; + normal = mat3 (Model) * norm; + st = uv; +} diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index b5f5cd6cb..5fd0680af 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -11,6 +11,8 @@ twodf = $builtin/twod.frag; quakebspv = $builtin/quakebsp.vert; quakebspf = $builtin/quakebsp.frag; + aliasv = $builtin/alias.vert; + aliasf = $builtin/alias.frag; }; samplers = { quakepic = { @@ -30,7 +32,7 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; - quakebsp = { + quakebsp.sampler = { magFilter = linear; minFilter = linear; mipmapMode = linear; @@ -81,7 +83,7 @@ }, ); }; - quakebsp = { + quakebsp.textures = { flags = push_descriptor; bindings = ( { @@ -122,6 +124,51 @@ }, ); }; + alias.textures = { + flags = push_descriptor; + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + binding = 1; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 3; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 4; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + alias.lights = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; something = { flags = 0; bindings = ( @@ -144,8 +191,8 @@ twod = { setLayouts = (twod); }; - quakebsp = { - setLayouts = (quakebsp); + quakebsp.layout = { + setLayouts = (quakebsp.textures); pushConstantRanges = ( { stageFlags = vertex; @@ -159,6 +206,21 @@ }, ); }; + alias.layout = { + setLayouts = (alias.textures, alias.lights); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 80; + size = "2 * 4 * 4"; + }, + ); + }; something = { setLayouts = (something); pushConstantRanges = ( @@ -171,6 +233,133 @@ }; }; pipelines = { + alias = { + stages = ( + { stage = vertex; name = main; module = aliasv; }, + { + stage = fragment; + name = main; + module = aliasf; + specializationInfo = { + mapEntries = ( + { size = 4; offset = 0; constantID = 0; }, + ); + data = <00000000>; + }; + }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "2 * 4 * 4"; + inputRate = vertex; + }, + { + binding = 1; + stride = "2 * 4 * 4"; + inputRate = vertex; + }, + { + binding = 2; + stride = "2 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + { + location = 1; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 16; + }, + { + location = 2; + binding = 1; + format = r32g32b32a32_sfloat; + offset = 0; + }, + { + location = 3; + binding = 1; + format = r32g32b32a32_sfloat; + offset = 16; + }, + { + location = 4; + binding = 2; + format = r32g32_sfloat; + offset = 0; + }, + ); + }; + inputAssembly = { + topology = triangle; + primitiveRestartEnable = false; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + depthStencil = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ({ + blendEnable = true; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }); + }; + dynamic = { + dynamicState = ( viewport, scissor, blend_constants ); + }; + layout = alias; + //renderPass = renderpass; + }; quakebsp.main = { stages = ( { stage = vertex; name = main; module = quakebspv; }, @@ -257,7 +446,7 @@ dynamic = { dynamicState = ( viewport, scissor, blend_constants ); }; - layout = quakebsp; + layout = quakebsp.layout; //renderPass = renderpass; }; quakebsp.skysheet = { @@ -359,7 +548,7 @@ dynamic = { dynamicState = ( viewport, scissor, blend_constants ); }; - layout = quakebsp; + layout = quakebsp.layout; //renderPass = renderpass; }; twod = { diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 4b0fed532..a3cc9e3f0 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -63,6 +63,10 @@ static static #include "libs/video/renderer/vulkan/quakebsp.frag.spvc" static +#include "libs/video/renderer/vulkan/alias.vert.spvc" +static +#include "libs/video/renderer/vulkan/alias.frag.spvc" +static #include "libs/video/renderer/vulkan/passthrough.vert.spvc" static #include "libs/video/renderer/vulkan/pushcolor.frag.spvc" @@ -78,6 +82,8 @@ static shaderdata_t builtin_shaders[] = { { "twod.frag", twod_frag, sizeof (twod_frag) }, { "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) }, { "quakebsp.frag", quakebsp_frag, sizeof (quakebsp_frag) }, + { "alias.vert", alias_vert, sizeof (alias_vert) }, + { "alias.frag", alias_frag, sizeof (alias_frag) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, {} diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 6da253bea..c95a14c97 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1420,13 +1420,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp.main"); bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp.skysheet"); - bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp"); - bctx->sampler = QFV_GetSampler (ctx, "quakebsp"); - - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "quakebsp"); - } + bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp.layout"); + bctx->sampler = QFV_GetSampler (ctx, "quakebsp.sampler"); __auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); From 56573d09e4795c3ec176d270fa3ee826cefb3500 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jan 2021 10:22:06 +0900 Subject: [PATCH 1272/3664] [vulkan] Get Vulkan_LoadTex working Finally managed to actually use and thus sort out its issues. --- libs/video/renderer/vulkan/vulkan_texture.c | 34 +++++++++++++-------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 07bcc7f0a..d5723ad3f 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -65,6 +65,7 @@ static int ilog2 (unsigned x) { + unsigned o = x; if (x > 0x7fffffff) { // avoid overflow return 31; @@ -82,7 +83,7 @@ ilog2 (unsigned x) y |= ((x & 0xf0f0f0f0) != 0) << 2; y |= ((x & 0xcccccccc) != 0) << 1; y |= ((x & 0xaaaaaaaa) != 0) << 0; - return y; + return y - ((o & (x - 1)) != 0); } void @@ -140,8 +141,8 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) if (!tex->palette) { return 0; } - format = VK_FORMAT_R8G8B8_UNORM; - bpp = 3; + format = VK_FORMAT_R8G8B8A8_UNORM; + bpp = 4; break; case tex_rgb: format = VK_FORMAT_R8G8B8_UNORM; @@ -174,6 +175,7 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) qtex->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, format, extent, mip, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); qtex->memory = QFV_AllocImageMemory (device, qtex->image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, @@ -190,7 +192,7 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) if (tex->format == tex_palette) { Vulkan_ExpandPalette (tex_data, tex->data, tex->palette, - 0, tex->width * tex->height); + 1, tex->width * tex->height); } else { memcpy (tex_data, tex->data, bytes); } @@ -201,6 +203,7 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; barrier.image = qtex->image; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, 1, &barrier); @@ -214,19 +217,29 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; stages.src = VK_PIPELINE_STAGE_TRANSFER_BIT; stages.dst = VK_PIPELINE_STAGE_TRANSFER_BIT; VkImageBlit blit = { {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, {{0, 0, 0}, {tex->width, tex->height, 1}}, {VK_IMAGE_ASPECT_COLOR_BIT, 1, 0, 1}, - {{0, 0, 0}, {(tex->width + 1) >> 1, (tex->height + 1) >> 1, 1}}, + {{0, 0, 0}, {max (tex->width >> 1, 1), max (tex->height >> 1, 1), 1}}, }; + if (mip == 1) { + stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier.image = qtex->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + } while (--mip > 0) { barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + stages.dst = VK_PIPELINE_STAGE_TRANSFER_BIT; dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, @@ -242,6 +255,7 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + stages.dst = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, 1, &barrier); @@ -250,16 +264,10 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) blit.srcOffsets[1].x = blit.dstOffsets[1].x; blit.srcOffsets[1].y = blit.dstOffsets[1].y; blit.dstSubresource.mipLevel++; - blit.dstOffsets[1].x = (blit.dstOffsets[1].x + 1) >> 1; - blit.dstOffsets[1].y = (blit.dstOffsets[1].y + 1) >> 1; + blit.dstOffsets[1].x = max (blit.dstOffsets[1].x >> 1, 1); + blit.dstOffsets[1].y = max (blit.dstOffsets[1].y >> 1, 1); barrier.subresourceRange.baseMipLevel++; } - stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier.image = qtex->image; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, - 0, 0, 0, 0, 0, - 1, &barrier); QFV_PacketSubmit (packet); return qtex; } From 69a8b984a52a9ba9058438d45d1c660c5b5f68a1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jan 2021 13:46:33 +0900 Subject: [PATCH 1273/3664] [vulkan] Sort out alias model load and unload --- libs/models/alias/vulkan_model_alias.c | 77 ++++++++++++++++++++------ 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 97801febc..88e2ced29 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -62,6 +62,34 @@ static vec3_t vertex_normals[NUMVERTEXNORMALS] = { static void vulkan_alias_clear (model_t *m, void *data) { + vulkan_ctx_t *ctx = data; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliashdr_t *hdr; + qfv_alias_mesh_t *mesh; + + m->needload = true; //FIXME is this right? + if (!(hdr = m->aliashdr)) { + hdr = Cache_Get (&m->cache); + } + mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); + dfunc->vkDestroyBuffer (device->dev, mesh->vertex_buffer, 0); + dfunc->vkDestroyBuffer (device->dev, mesh->uv_buffer, 0); + dfunc->vkDestroyBuffer (device->dev, mesh->index_buffer, 0); + dfunc->vkFreeMemory (device->dev, mesh->memory, 0); + + __auto_type skins = (maliasskindesc_t *) ((byte *) hdr + hdr->skindesc); + for (int i = 0; i < hdr->mdl.numskins; i++) { + if (skins[i].type == ALIAS_SKIN_GROUP) { + __auto_type group = (maliasskingroup_t *) + ((byte *) hdr + skins[i].skin); + for (int j = 0; j < group->numskins; j++) { + Vulkan_UnloadTex (ctx, group->skindescs[j].tex); + } + } else { + Vulkan_UnloadTex (ctx, skins[i].tex); + } + } } void * @@ -72,6 +100,8 @@ Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, byte *tskin; int w, h; + //FIXME move all skins into arrays(?) + //FIXME fullbrights w = pheader->mdl.skinwidth; h = pheader->mdl.skinheight; tskin = malloc (skinsize); @@ -86,9 +116,8 @@ Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, void Vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr, vulkan_ctx_t *ctx) { - if (hdr->mdl.ident == HEADER_MDL16) - VectorScale (hdr->mdl.scale, 1/256.0, hdr->mdl.scale); m->clear = vulkan_alias_clear; + m->data = ctx; } void @@ -96,6 +125,21 @@ Vulkan_Mod_LoadExternalSkins (model_t *mod, vulkan_ctx_t *ctx) { } +static size_t +get_buffer_size (qfv_device_t *device, VkBuffer buffer) +{ + qfv_devfuncs_t *dfunc = device->funcs; + size_t size; + size_t align; + + VkMemoryRequirements requirements; + dfunc->vkGetBufferMemoryRequirements (device->dev, buffer, &requirements); + size = requirements.size; + align = requirements.alignment - 1; + size = (size + align) & ~(align); + return size; +} + void Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra, vulkan_ctx_t *ctx) @@ -113,6 +157,9 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int pose; vec3_t pos; + if (hdr->mdl.ident == HEADER_MDL16) + VectorScale (hdr->mdl.scale, 1/256.0, hdr->mdl.scale); + numverts = hdr->mdl.numverts; numtris = hdr->mdl.numtris; @@ -148,33 +195,31 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, // current and previous pose, uvbuff "statically" bound as uvs are not // animated by pose, and the same for ibuf: indices will never change for // the mesh - size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; - size_t atom_mask = atom - 1; size_t vert_count = numverts * hdr->numposes; size_t vert_size = vert_count * sizeof (aliasvrt_t); size_t uv_size = numverts * sizeof (aliasuv_t); - size_t ind_size = numverts * sizeof (uint32_t); - vert_size = (vert_size + atom_mask) & ~atom_mask; - uv_size = (uv_size + atom_mask) & ~atom_mask; - ind_size = (ind_size + atom_mask) & ~atom_mask; - size_t buff_size = vert_size + ind_size + uv_size; + size_t ind_size = 3 * numtris * sizeof (uint32_t); - VkBuffer vbuff = QFV_CreateBuffer (device, buff_size, + VkBuffer vbuff = QFV_CreateBuffer (device, vert_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - VkBuffer uvbuff = QFV_CreateBuffer (device, buff_size, + VkBuffer uvbuff = QFV_CreateBuffer (device, uv_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - VkBuffer ibuff = QFV_CreateBuffer (device, buff_size, + VkBuffer ibuff = QFV_CreateBuffer (device, ind_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + size_t voffs = 0; + size_t uvoffs = voffs + get_buffer_size (device, vbuff); + size_t ioffs = uvoffs + get_buffer_size (device, uvbuff); + size_t buff_size = ioffs + get_buffer_size (device, ibuff); VkDeviceMemory mem; mem = QFV_AllocBufferMemory (device, vbuff, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buff_size, 0); - QFV_BindBufferMemory (device, vbuff, mem, 0); - QFV_BindBufferMemory (device, uvbuff, mem, vert_size); - QFV_BindBufferMemory (device, ibuff, mem, vert_size + uv_size); + QFV_BindBufferMemory (device, vbuff, mem, voffs); + QFV_BindBufferMemory (device, uvbuff, mem, uvoffs); + QFV_BindBufferMemory (device, ibuff, mem, ioffs); qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, buff_size, ctx->cmdpool); @@ -219,7 +264,7 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, } // now build the indices for DrawElements - for (i = 0; i < numverts; i++) { + for (i = 0; i < hdr->mdl.numverts; i++) { indexmap[i] = indexmap[i] != -1 ? indexmap[i] : i; } for (i = 0; i < numtris; i++) { From 826e650c273e466caf325a220dcdd664ce182e11 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jan 2021 20:33:51 +0900 Subject: [PATCH 1274/3664] [models] Do full alias skin loading This includes base, glow and two color maps (pants and shorts). --- include/QF/Vulkan/qf_alias.h | 6 +++ include/QF/model.h | 16 +++---- include/mod_internal.h | 4 ++ libs/models/alias/vulkan_model_alias.c | 48 ++++++++++++++++++--- libs/models/fullbright.c | 17 ++++++-- libs/models/skin.c | 60 ++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 20 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index efe3dd0dc..006bd8672 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -37,6 +37,12 @@ #include "QF/modelgen.h" #include "QF/Vulkan/qf_vid.h" +typedef struct aliasskin_s { + struct qfv_tex_s *tex; + struct qfv_tex_s *glow; + struct qfv_tex_s *colora; + struct qfv_tex_s *colorb; +} aliasskin_t; typedef struct aliasvrt_s { float vertex[4]; float normal[4]; diff --git a/include/QF/model.h b/include/QF/model.h index d1129bfce..5512506f3 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -278,14 +278,9 @@ typedef struct { typedef struct { aliasskintype_t type; - int skin; - union { - struct { - int texnum; - int fb_texnum; - }; - void *tex; - }; + int skin; + int texnum; + int fb_texnum; } maliasskindesc_t; typedef struct { @@ -447,7 +442,8 @@ void Mod_TouchModel (const char *name); mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure)); byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); model_t *Mod_FindName (const char *name); -int Mod_CalcFullbright (byte *in, byte *out, int pixels); +int Mod_CalcFullbright (const byte *in, byte *out, int pixels); +void Mod_ClearFullbright (const byte *in, byte *out, int pixels); int Mod_Fullbright (byte * skin, int width, int height, const char *name); void *Mod_LoadAliasFrame (void *pin, int *posenum, maliasframedesc_t *frame, @@ -457,7 +453,7 @@ void *Mod_LoadAliasGroup (void *pin, int *posenum, maliasframedesc_t *frame, void Mod_FindClipDepth (hull_t *hull); void Mod_LoadBrushModel (model_t *mod, void *buffer); -void Mod_FloodFillSkin (byte * skin, int skinwidth, int skinheight); +void Mod_FloodFillSkin (byte *skin, int skinwidth, int skinheight); void Mod_Print (void); diff --git a/include/mod_internal.h b/include/mod_internal.h index 632411785..382a8985f 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -62,6 +62,10 @@ void Skin_Init (void); skin_t *Skin_SetColormap (skin_t *skin, int cmap); skin_t *Skin_SetSkin (skin_t *skin, int cmap, const char *skinname); void Skin_SetTranslation (int cmap, int top, int bottom); +int Skin_CalcTopColors (const byte *in, byte *out, int pixels); +int Skin_CalcBottomColors (const byte *in, byte *out, int pixels); +void Skin_ClearTopColors (const byte *in, byte *out, int pixels); +void Skin_ClearBottomColors (const byte *in, byte *out, int pixels); void sw_Skin_SetupSkin (skin_t *skin, int cmap); void sw_Skin_ProcessTranslation (int cmap, const byte *translation); diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 88e2ced29..3a7ad4705 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -59,6 +59,22 @@ static vec3_t vertex_normals[NUMVERTEXNORMALS] = { #include "anorms.h" }; +static void +skin_clear (int skin_offset, aliashdr_t *hdr, vulkan_ctx_t *ctx) +{ + aliasskin_t *skin = (aliasskin_t *) ((byte *) hdr + skin_offset); + Vulkan_UnloadTex (ctx, skin->tex); + if (skin->glow) { + Vulkan_UnloadTex (ctx, skin->glow); + } + if (skin->colora) { + Vulkan_UnloadTex (ctx, skin->colora); + } + if (skin->colorb) { + Vulkan_UnloadTex (ctx, skin->colorb); + } +} + static void vulkan_alias_clear (model_t *m, void *data) { @@ -84,32 +100,50 @@ vulkan_alias_clear (model_t *m, void *data) __auto_type group = (maliasskingroup_t *) ((byte *) hdr + skins[i].skin); for (int j = 0; j < group->numskins; j++) { - Vulkan_UnloadTex (ctx, group->skindescs[j].tex); + skin_clear (group->skindescs[j].skin, hdr, ctx); } } else { - Vulkan_UnloadTex (ctx, skins[i].tex); + skin_clear (skins[i].skin, hdr, ctx); } } } void * -Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, +Vulkan_Mod_LoadSkin (byte *skinpix, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc, vulkan_ctx_t *ctx) { + aliasskin_t *skin; byte *tskin; int w, h; + skin = Hunk_Alloc (sizeof (aliasskin_t)); + skindesc->skin = (byte *) skin - (byte *) pheader;//FIXME pheader global //FIXME move all skins into arrays(?) - //FIXME fullbrights w = pheader->mdl.skinwidth; h = pheader->mdl.skinheight; - tskin = malloc (skinsize); + tskin = malloc (2 * skinsize); memcpy (tskin, skin, skinsize); Mod_FloodFillSkin (tskin, w, h); - tex_t skin_tex = {w, h, tex_palette, 1, vid.palette, tskin}; - skindesc->tex = Vulkan_LoadTex (ctx, &skin_tex, 1); + + tex_t skin_tex = {w, h, tex_palette, 1, vid.palette, tskin + skinsize}; + if (Mod_CalcFullbright (tskin, tskin + skinsize, skinsize)) { + skin->glow = Vulkan_LoadTex (ctx, &skin_tex, 1); + Mod_ClearFullbright (tskin, tskin, skinsize); + } + if (Skin_CalcTopColors (tskin, tskin + skinsize, skinsize)) { + skin->colora = Vulkan_LoadTex (ctx, &skin_tex, 1); + Skin_ClearTopColors (tskin, tskin, skinsize); + } + if (Skin_CalcBottomColors (tskin, tskin + skinsize, skinsize)) { + skin->colorb = Vulkan_LoadTex (ctx, &skin_tex, 1); + Skin_ClearBottomColors (tskin, tskin, skinsize); + } + skin_tex.data = tskin; + skin->tex = Vulkan_LoadTex (ctx, &skin_tex, 1); + free (tskin); + return skin + skinsize; } diff --git a/libs/models/fullbright.c b/libs/models/fullbright.c index 79c32ede9..62f9ccee5 100644 --- a/libs/models/fullbright.c +++ b/libs/models/fullbright.c @@ -33,17 +33,28 @@ #include "r_local.h" - VISIBLE int -Mod_CalcFullbright (byte *in, byte *out, int pixels) +Mod_CalcFullbright (const byte *in, byte *out, int pixels) { byte fb = 0; - while (pixels--) { + while (pixels-- > 0) { byte pix = *in++; byte mask = (pix >= 256 - 32) - 1; fb |= mask + 1; + // mask is 0 for fullbright, otherwise 0xff *out++ = pix | mask; } return fb; } + +VISIBLE void +Mod_ClearFullbright (const byte *in, byte *out, int pixels) +{ + while (pixels-- > 0) { + byte pix = *in++; + byte mask = ~((pix >= 256 - 32) - 1); + // mask is 0xff for fullbright, otherwise 0 + *out++ = pix | mask; + } +} diff --git a/libs/models/skin.c b/libs/models/skin.c index 9897a4143..88d53cea6 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -246,3 +246,63 @@ Skin_Init (void) skin_cache = Hash_NewTable (127, skin_getkey, skin_free, 0, 0); m_funcs->Skin_InitTranslations (); } + +VISIBLE int +Skin_CalcTopColors (const byte *in, byte *out, int pixels) +{ + byte tc = 0; + + while (pixels-- > 0) { + byte pix = *in++; + byte a = (pix < TOP_RANGE) - 1; + byte b = (pix > TOP_RANGE + 15) - 1; + byte mask = ~(a & b); + tc |= mask; + // mask is 0 for top color otherwise 0xff + *out++ = (pix - TOP_RANGE) | mask; + } + return tc; +} + +VISIBLE int +Skin_CalcBottomColors (const byte *in, byte *out, int pixels) +{ + byte bc = 0; + + while (pixels-- > 0) { + byte pix = *in++; + byte a = (pix < BOTTOM_RANGE) - 1; + byte b = (pix > BOTTOM_RANGE + 15) - 1; + byte mask = ~(a & b); + bc |= mask; + // mask is 0 for bottom color otherwise 0xff + *out++ = (pix - BOTTOM_RANGE) | mask; + } + return bc; +} + +VISIBLE void +Skin_ClearTopColors (const byte *in, byte *out, int pixels) +{ + while (pixels-- > 0) { + byte pix = *in++; + byte a = (pix < TOP_RANGE) - 1; + byte b = (pix > TOP_RANGE + 15) - 1; + byte mask = (a & b); + // mask is 0xff for top color otherwise 0 + *out++ = (pix - TOP_RANGE) | mask; + } +} + +VISIBLE void +Skin_ClearBottomColors (const byte *in, byte *out, int pixels) +{ + while (pixels-- > 0) { + byte pix = *in++; + byte a = (pix < BOTTOM_RANGE) - 1; + byte b = (pix > BOTTOM_RANGE + 15) - 1; + byte mask = (a & b); + // mask is 0xff for bottom color otherwise 0 + *out++ = (pix - BOTTOM_RANGE) | mask; + } +} From 12ec6c5c296a416e7fbc2a07526fd917aee66cbc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jan 2021 20:45:07 +0900 Subject: [PATCH 1275/3664] [util] Add eol to plist parse errors I suspect it got lost when I made the error message a string item. --- libs/util/qfplist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 3fa64b9d0..fe0fc3268 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -899,7 +899,7 @@ PL_GetPropertyList (const char *string) if (pl && pl->error) { const char *error = PL_String (pl->error); if (error[0]) { - Sys_Printf ("plist: %d,%d: %s", pl->line, pl->pos, error); + Sys_Printf ("plist: %d,%d: %s\n", pl->line, pl->pos, error); } PL_Free (pl->error); } From 748217b43833fcb0cc24f32d76115b1ead2312b4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jan 2021 20:58:24 +0900 Subject: [PATCH 1276/3664] [vulkan] Start work on alias model rendering --- include/QF/Vulkan/qf_alias.h | 38 ++- include/vid_vulkan.h | 1 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vid_render_vulkan.c | 2 + libs/video/renderer/vulkan/alias.frag | 8 +- libs/video/renderer/vulkan/qfpipeline.plist | 65 +++-- libs/video/renderer/vulkan/vulkan_alias.c | 276 ++++++++++++++++++ libs/video/renderer/vulkan/vulkan_draw.c | 6 +- libs/video/renderer/vulkan/vulkan_main.c | 15 +- .../video/renderer/vulkan/vulkan_vid_common.c | 1 + 10 files changed, 378 insertions(+), 35 deletions(-) create mode 100644 libs/video/renderer/vulkan/vulkan_alias.c diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 006bd8672..bcc5be337 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -43,6 +43,7 @@ typedef struct aliasskin_s { struct qfv_tex_s *colora; struct qfv_tex_s *colorb; } aliasskin_t; + typedef struct aliasvrt_s { float vertex[4]; float normal[4]; @@ -68,15 +69,39 @@ typedef struct qfv_light_s { float cone; } qfv_light_t; +#define ALIAS_LIGHTS 8 + typedef struct qfv_light_buffer_s { int light_count; - qfv_light_t lights[] __attribute__((aligned(16))); + qfv_light_t lights[ALIAS_LIGHTS] __attribute__((aligned(16))); } qfv_light_buffer_t; -typedef struct alias_ctx_s { -} alias_ctx_t; +#define ALIAS_BUFFER_INFOS 2 +#define ALIAS_IMAGE_INFOS 4 + +typedef struct aliasframe_s { + VkCommandBuffer cmd; + VkDescriptorBufferInfo bufferInfo[ALIAS_BUFFER_INFOS]; + VkDescriptorImageInfo imageInfo[ALIAS_IMAGE_INFOS]; + VkWriteDescriptorSet descriptors[ALIAS_BUFFER_INFOS + ALIAS_IMAGE_INFOS]; + qfv_light_buffer_t *lights; + VkBuffer light_buffer; +} aliasframe_t; + +typedef struct aliasframeset_s + DARRAY_TYPE (aliasframe_t) aliasframeset_t; + +typedef struct aliasctx_s { + aliasframeset_t frames; + VkPipeline pipeline; + VkPipelineLayout layout; + VkSampler sampler; + + VkDeviceMemory light_memory; +} aliasctx_t; struct vulkan_ctx_s; +struct entity_s; void *Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc, struct vulkan_ctx_s *ctx); @@ -87,4 +112,11 @@ void Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra, struct vulkan_ctx_s *ctx); +void Vulkan_AliasBegin (struct vulkan_ctx_s *ctx); +void Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx); +void Vulkan_AliasEnd (struct vulkan_ctx_s *ctx); + +void Vulkan_Alias_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx); + #endif//__QF_Vulkan_qf_alias_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index f4642afb1..8a60707fe 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -63,6 +63,7 @@ typedef struct vulkan_ctx_s { struct hashtab_s *descriptorPools; struct hashtab_s *samplers; + struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; struct drawctx_s *draw_context; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index e3b154541..b322a7ca4 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -236,6 +236,7 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/util.c \ libs/video/renderer/vulkan/util.h \ libs/video/renderer/vulkan/vkparse.c \ + libs/video/renderer/vulkan/vulkan_alias.c \ libs/video/renderer/vulkan/vulkan_bsp.c \ libs/video/renderer/vulkan/vulkan_draw.c \ libs/video/renderer/vulkan/vulkan_lightmap.c \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 2b001bcd3..fc8aebc11 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -98,6 +98,7 @@ vulkan_R_Init (void) // are being built vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); Vulkan_Texture_Init (vulkan_ctx); + Vulkan_Alias_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); Vulkan_Particles_Init (vulkan_ctx); @@ -611,6 +612,7 @@ vulkan_vid_render_shutdown (void) df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); + Vulkan_Alias_Shutdown (vulkan_ctx); Mod_ClearAll (); Vulkan_Texture_Shutdown (vulkan_ctx); Vulkan_Shutdown_Common (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/alias.frag index 935fa06b4..d1ad194bb 100644 --- a/libs/video/renderer/vulkan/alias.frag +++ b/libs/video/renderer/vulkan/alias.frag @@ -1,9 +1,9 @@ #version 450 -layout (set = 0, binding = 1) uniform sampler2D Texture; -layout (set = 0, binding = 2) uniform sampler2D GlowMap; -layout (set = 0, binding = 3) uniform sampler2D ColorA; -layout (set = 0, binding = 4) uniform sampler2D ColorB; +layout (set = 2, binding = 0) uniform sampler2D Texture; +layout (set = 2, binding = 1) uniform sampler2D GlowMap; +layout (set = 2, binding = 2) uniform sampler2D ColorA; +layout (set = 2, binding = 3) uniform sampler2D ColorB; struct LightData { vec3 color; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 5fd0680af..b6823707c 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -49,9 +49,26 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; + alias.sampler = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 1000; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; }; descriptorPools = { - twod = { + twod.pool = { flags = 0; maxSets = $framebuffers.size; bindings = ( @@ -65,9 +82,19 @@ }, ); }; + alias.pool = { + flags = 0; + maxSets = "2z * $framebuffers.size"; + bindings = ( + { + type = uniform_buffer; + descriptorCount = "2z * $framebuffers.size"; + }, + ); + }; }; setLayouts = { - twod = { + twod.set = { bindings = ( { binding = 0; @@ -124,8 +151,7 @@ }, ); }; - alias.textures = { - flags = push_descriptor; + alias.matrices = { bindings = ( { binding = 0; @@ -133,6 +159,17 @@ descriptorCount = 1; stageFlags = vertex; }, + ); + }; + alias.textures = { + flags = push_descriptor; + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, { binding = 1; descriptorType = combined_image_sampler; @@ -151,12 +188,6 @@ descriptorCount = 1; stageFlags = fragment; }, - { - binding = 4; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, ); }; alias.lights = { @@ -188,8 +219,8 @@ }; }; pipelineLayouts = { - twod = { - setLayouts = (twod); + twod.layout = { + setLayouts = (twod.set); }; quakebsp.layout = { setLayouts = (quakebsp.textures); @@ -207,7 +238,7 @@ ); }; alias.layout = { - setLayouts = (alias.textures, alias.lights); + setLayouts = (alias.matrices, alias.lights, alias.textures); pushConstantRanges = ( { stageFlags = vertex; @@ -244,7 +275,7 @@ mapEntries = ( { size = 4; offset = 0; constantID = 0; }, ); - data = <00000000>; + data = <00000008>; }; }, ); @@ -300,7 +331,7 @@ ); }; inputAssembly = { - topology = triangle; + topology = triangle_list; primitiveRestartEnable = false; }; viewport = { @@ -357,7 +388,7 @@ dynamic = { dynamicState = ( viewport, scissor, blend_constants ); }; - layout = alias; + layout = alias.layout; //renderPass = renderpass; }; quakebsp.main = { @@ -643,7 +674,7 @@ dynamic = { dynamicState = ( viewport, scissor ); }; - layout = twod; + layout = twod.layout; //renderPass = renderpass; }; }; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c new file mode 100644 index 000000000..3fa9d7c52 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -0,0 +1,276 @@ +/* + vulkan_alias.c + + Vulkan alias model pipeline + + Copyright (C) 2012 Bill Currie + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2012/1/7 + Date: 2021/1/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "qfalloca.h" + +#include "QF/cvar.h" +#include "QF/darray.h" +#include "QF/dstring.h" +#include "QF/image.h" +#include "QF/render.h" +#include "QF/skin.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vrect.h" + +#include "QF/Vulkan/qf_alias.h" +#include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" + +#include "r_internal.h" +#include "vid_vulkan.h" +#include "vkparse.h" + +static VkImageView +get_view (qfv_tex_t *tex, qfv_tex_t *default_tex) +{ + if (tex) { + return tex->view; + } + if (default_tex) { + return default_tex->view; + } + return 0; +} + +void +Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliasctx_t *actx = ctx->alias_context; + aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + model_t *model = ent->model; + aliashdr_t *hdr; + qfv_alias_mesh_t *mesh; + float blend; + aliasskin_t *skin; + + if (!(hdr = model->aliashdr)) { + hdr = Cache_Get (&model->cache); + } + mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); + + blend = R_AliasGetLerpedFrames (ent, hdr); + + if (0/*XXX ent->skin && ent->skin->tex*/) { + //skin = ent->skin->tex; + } else { + maliasskindesc_t *skindesc; + skindesc = R_AliasGetSkindesc (ent->skinnum, hdr); + skin = (aliasskin_t *) ((byte *) hdr + skindesc->skin); + } + + VkDeviceSize offsets[] = { + ent->pose1 * hdr->poseverts, + ent->pose2 * hdr->poseverts, + 0, + }; + VkBuffer buffers[] = { + mesh->vertex_buffer, + mesh->vertex_buffer, + mesh->uv_buffer, + }; + dfunc->vkCmdBindVertexBuffers (aframe->cmd, 0, 3, buffers, offsets); + dfunc->vkCmdBindIndexBuffer (aframe->cmd, mesh->index_buffer, 0, + VK_INDEX_TYPE_UINT32); + dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, + VK_SHADER_STAGE_VERTEX_BIT, + 0, 16 * sizeof (float), ent->transform); + dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, + VK_SHADER_STAGE_VERTEX_BIT, + 64, sizeof (float), &blend); + aframe->imageInfo[0].imageView = get_view (skin->tex, ctx->default_white); + aframe->imageInfo[1].imageView = get_view (skin->glow, ctx->default_black); + aframe->imageInfo[2].imageView = get_view (skin->colora, + ctx->default_black); + aframe->imageInfo[3].imageView = get_view (skin->colorb, + ctx->default_black); + dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + actx->layout, + 0, 2, aframe->descriptors + + ALIAS_BUFFER_INFOS); + dfunc->vkCmdDrawIndexed (aframe->cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); +} + +void +Vulkan_AliasBegin (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliasctx_t *actx = ctx->alias_context; + //XXX quat_t fog; + + __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; + aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = aframe->cmd; + DARRAY_APPEND (cframe->subCommand, cmd); + + //FIXME need per frame matrices + aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + aframe->bufferInfo[1].buffer = aframe->light_buffer; + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + ctx->renderpass.renderpass, 0, + cframe->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + actx->pipeline); + VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; + VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; + dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + + dfunc->vkUpdateDescriptorSets (device->dev, 2, aframe->descriptors, 0, 0); + + //XXX glsl_Fog_GetColor (fog); + //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; +} + +void +Vulkan_AliasEnd (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliasctx_t *actx = ctx->alias_context; + + aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + dfunc->vkEndCommandBuffer (aframe->cmd); +} + +static VkDescriptorBufferInfo base_buffer_info = { + 0, 0, VK_WHOLE_SIZE +}; +static VkDescriptorImageInfo base_image_info = { + 0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL +}; +static VkWriteDescriptorSet base_buffer_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, 0, 0 +}; +static VkWriteDescriptorSet base_image_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 0, 0, 0 +}; + +void +Vulkan_Alias_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); + ctx->alias_context = actx; + + size_t frames = ctx->framebuffers.size; + DARRAY_INIT (&actx->frames, frames); + DARRAY_RESIZE (&actx->frames, frames); + actx->frames.grow = 0; + + actx->pipeline = Vulkan_CreatePipeline (ctx, "alias"); + actx->layout = QFV_GetPipelineLayout (ctx, "alias.layout"); + actx->sampler = QFV_GetSampler (ctx, "alias.sampler"); + + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (2 * frames, alloca); + for (size_t i = 0; i < layouts->size / 2; i++) { + __auto_type mats = QFV_GetDescriptorSetLayout (ctx, "alias.matrices"); + __auto_type lights = QFV_GetDescriptorSetLayout (ctx, "alias.lights"); + layouts->a[2 * i + 0] = mats; + layouts->a[2 * i + 1] = lights; + } + __auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool"); + + __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); + + __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); + for (size_t i = 0; i < frames; i++) { + __auto_type aframe = &actx->frames.a[i]; + aframe->cmd = cmdBuffers->a[i]; + + for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) { + aframe->bufferInfo[j] = base_buffer_info; + aframe->descriptors[j] = base_buffer_write; + aframe->descriptors[j].dstSet = sets->a[2 * i + j]; + aframe->descriptors[j].dstBinding = 0; + aframe->descriptors[j].pBufferInfo = &aframe->bufferInfo[j]; + } + for (int j = 0; j < ALIAS_IMAGE_INFOS; j++) { + aframe->imageInfo[j] = base_image_info; + aframe->imageInfo[j].sampler = actx->sampler; + int k = j + ALIAS_BUFFER_INFOS; + aframe->descriptors[k] = base_image_write; + aframe->descriptors[k].dstBinding = j; + aframe->descriptors[k].pImageInfo = &aframe->imageInfo[j]; + } + } + free (sets); +} + +void +Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliasctx_t *actx = ctx->alias_context; + + dfunc->vkDestroyPipeline (device->dev, actx->pipeline, 0); + DARRAY_CLEAR (&actx->frames); + free (actx); +} diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index f4bf8c19e..3fc563cb2 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -383,13 +383,13 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->pipeline = Vulkan_CreatePipeline (ctx, "twod"); - dctx->layout = QFV_GetPipelineLayout (ctx, "twod"); + dctx->layout = QFV_GetPipelineLayout (ctx, "twod.layout"); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "twod"); + layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "twod.set"); } - __auto_type pool = QFV_GetDescriptorPool (ctx, "twod"); + __auto_type pool = QFV_GetDescriptorPool (ctx, "twod.pool"); VkDescriptorBufferInfo bufferInfo = { ctx->matrices.buffer_2d, 0, VK_WHOLE_SIZE diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index f31558e7b..95fcd02ab 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -49,7 +49,7 @@ #include "QF/sys.h" #include "QF/Vulkan/qf_vid.h" -//#include "QF/Vulkan/qf_alias.h" +#include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" //#include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_lightmap.h" @@ -109,8 +109,8 @@ setup_view (vulkan_ctx_t *ctx) static void R_RenderEntities (vulkan_ctx_t *ctx) { - //entity_t *ent; - //int begun; + entity_t *ent; + int begun; if (!r_drawentities->int_val) return; @@ -121,17 +121,16 @@ R_RenderEntities (vulkan_ctx_t *ctx) if (ent->model->type != mod_##type_name) \ continue; \ if (!begun) { \ - glsl_R_##Type##Begin (); \ + Vulkan_##Type##Begin (ctx); \ begun = 1; \ } \ - currententity = ent; \ - glsl_R_Draw##Type (); \ + Vulkan_Draw##Type (ent, ctx); \ } \ if (begun) \ - glsl_R_##Type##End (); \ + Vulkan_##Type##End (ctx); \ } while (0) - //RE_LOOP (alias, Alias); + RE_LOOP (alias, Alias); //RE_LOOP (iqm, IQM); //RE_LOOP (sprite, Sprite); } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 4e5f338cc..2ab5fc166 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -242,6 +242,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) plitem_t *item = ctx->pipelineDef; if (!item || !(item = PL_ObjectForKey (item, "renderpass"))) { Sys_Printf ("error loading renderpass\n"); + return; } else { Sys_Printf ("Found renderpass def\n"); } From a64f477796b1b6fcd023e94fe2397722613fc8b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Jan 2021 12:15:45 +0900 Subject: [PATCH 1277/3664] [vulkan] Get alias texture loading working That was a mess, partly premature optimizations, and some silly mistakes. --- libs/models/alias/vulkan_model_alias.c | 2 +- libs/models/fullbright.c | 18 +-- libs/models/skin.c | 44 +++---- libs/video/renderer/vulkan/vulkan_texture.c | 125 +++++++++++++------- 4 files changed, 115 insertions(+), 74 deletions(-) diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 3a7ad4705..e3e5f0701 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -123,7 +123,7 @@ Vulkan_Mod_LoadSkin (byte *skinpix, int skinsize, int snum, int gnum, w = pheader->mdl.skinwidth; h = pheader->mdl.skinheight; tskin = malloc (2 * skinsize); - memcpy (tskin, skin, skinsize); + memcpy (tskin, skinpix, skinsize); Mod_FloodFillSkin (tskin, w, h); tex_t skin_tex = {w, h, tex_palette, 1, vid.palette, tskin + skinsize}; diff --git a/libs/models/fullbright.c b/libs/models/fullbright.c index 62f9ccee5..22cef6a83 100644 --- a/libs/models/fullbright.c +++ b/libs/models/fullbright.c @@ -40,10 +40,12 @@ Mod_CalcFullbright (const byte *in, byte *out, int pixels) while (pixels-- > 0) { byte pix = *in++; - byte mask = (pix >= 256 - 32) - 1; - fb |= mask + 1; - // mask is 0 for fullbright, otherwise 0xff - *out++ = pix | mask; + if (pix >= 256 - 32) { + fb = 1; + *out++ = pix; + } else { + *out++ = 0; + } } return fb; } @@ -53,8 +55,10 @@ Mod_ClearFullbright (const byte *in, byte *out, int pixels) { while (pixels-- > 0) { byte pix = *in++; - byte mask = ~((pix >= 256 - 32) - 1); - // mask is 0xff for fullbright, otherwise 0 - *out++ = pix | mask; + if (pix >= 256 - 32) { + *out++ = 0; + } else { + *out++ = pix; + } } } diff --git a/libs/models/skin.c b/libs/models/skin.c index 88d53cea6..fd561143d 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -254,12 +254,12 @@ Skin_CalcTopColors (const byte *in, byte *out, int pixels) while (pixels-- > 0) { byte pix = *in++; - byte a = (pix < TOP_RANGE) - 1; - byte b = (pix > TOP_RANGE + 15) - 1; - byte mask = ~(a & b); - tc |= mask; - // mask is 0 for top color otherwise 0xff - *out++ = (pix - TOP_RANGE) | mask; + if (pix >= TOP_RANGE && pix < TOP_RANGE + 16) { + tc = 1; + *out++ = pix - TOP_RANGE; + } else { + *out++ = 0; + } } return tc; } @@ -271,12 +271,12 @@ Skin_CalcBottomColors (const byte *in, byte *out, int pixels) while (pixels-- > 0) { byte pix = *in++; - byte a = (pix < BOTTOM_RANGE) - 1; - byte b = (pix > BOTTOM_RANGE + 15) - 1; - byte mask = ~(a & b); - bc |= mask; - // mask is 0 for bottom color otherwise 0xff - *out++ = (pix - BOTTOM_RANGE) | mask; + if (pix >= BOTTOM_RANGE && pix < BOTTOM_RANGE + 16) { + bc = 1; + *out++ = pix - BOTTOM_RANGE; + } else { + *out++ = 0; + } } return bc; } @@ -286,11 +286,11 @@ Skin_ClearTopColors (const byte *in, byte *out, int pixels) { while (pixels-- > 0) { byte pix = *in++; - byte a = (pix < TOP_RANGE) - 1; - byte b = (pix > TOP_RANGE + 15) - 1; - byte mask = (a & b); - // mask is 0xff for top color otherwise 0 - *out++ = (pix - TOP_RANGE) | mask; + if (pix >= TOP_RANGE && pix < TOP_RANGE + 16) { + *out++ = 0; + } else { + *out++ = pix; + } } } @@ -299,10 +299,10 @@ Skin_ClearBottomColors (const byte *in, byte *out, int pixels) { while (pixels-- > 0) { byte pix = *in++; - byte a = (pix < BOTTOM_RANGE) - 1; - byte b = (pix > BOTTOM_RANGE + 15) - 1; - byte mask = (a & b); - // mask is 0xff for bottom color otherwise 0 - *out++ = (pix - BOTTOM_RANGE) | mask; + if (pix >= BOTTOM_RANGE && pix < BOTTOM_RANGE + 16) { + *out++ = 0; + } else { + *out++ = pix; + } } } diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index d5723ad3f..0129f886c 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -119,6 +119,85 @@ Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, } } +static void +blit_mips (int mips, VkImage image, tex_t *tex, + qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) +{ + qfv_pipelinestagepair_t pre_stages = { + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + }; + qfv_pipelinestagepair_t post_stages = { + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + }; + qfv_pipelinestagepair_t final_stages = { + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + }; + VkImageMemoryBarrier pre_barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + image, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }; + VkImageMemoryBarrier post_barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + image, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }; + VkImageMemoryBarrier final_barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + image, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }; + + VkImageBlit blit = { + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {{0, 0, 0}, {tex->width, tex->height, 1}}, + {VK_IMAGE_ASPECT_COLOR_BIT, 1, 0, 1}, + {{0, 0, 0}, {max (tex->width >> 1, 1), max (tex->height >> 1, 1), 1}}, + }; + + while (--mips > 0) { + dfunc->vkCmdPipelineBarrier (cmd, pre_stages.src, pre_stages.dst, 0, + 0, 0, 0, 0, + 1, &pre_barrier); + dfunc->vkCmdBlitImage (cmd, + image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &blit, VK_FILTER_LINEAR); + + dfunc->vkCmdPipelineBarrier (cmd, post_stages.src, post_stages.dst, 0, + 0, 0, 0, 0, + 1, &post_barrier); + + blit.srcSubresource.mipLevel++; + blit.srcOffsets[1].x = blit.dstOffsets[1].x; + blit.srcOffsets[1].y = blit.dstOffsets[1].y; + blit.dstSubresource.mipLevel++; + blit.dstOffsets[1].x = max (blit.dstOffsets[1].x >> 1, 1); + blit.dstOffsets[1].y = max (blit.dstOffsets[1].y >> 1, 1); + pre_barrier.subresourceRange.baseMipLevel++; + post_barrier.subresourceRange.baseMipLevel++; + final_barrier.subresourceRange.baseMipLevel++; + } + dfunc->vkCmdPipelineBarrier (cmd, final_stages.src, final_stages.dst, 0, + 0, 0, 0, 0, + 1, &final_barrier); +} + qfv_tex_t * Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) { @@ -216,16 +295,6 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) qtex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); - barrier.subresourceRange.baseMipLevel = 0; - barrier.subresourceRange.levelCount = 1; - stages.src = VK_PIPELINE_STAGE_TRANSFER_BIT; - stages.dst = VK_PIPELINE_STAGE_TRANSFER_BIT; - VkImageBlit blit = { - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, - {{0, 0, 0}, {tex->width, tex->height, 1}}, - {VK_IMAGE_ASPECT_COLOR_BIT, 1, 0, 1}, - {{0, 0, 0}, {max (tex->width >> 1, 1), max (tex->height >> 1, 1), 1}}, - }; if (mip == 1) { stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; @@ -233,40 +302,8 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, 1, &barrier); - } - while (--mip > 0) { - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - stages.dst = VK_PIPELINE_STAGE_TRANSFER_BIT; - - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, - 0, 0, 0, 0, - 1, &barrier); - - dfunc->vkCmdBlitImage (packet->cmd, - qtex->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - qtex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, &blit, VK_FILTER_LINEAR); - - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - stages.dst = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, - 0, 0, 0, 0, - 1, &barrier); - - blit.srcSubresource.mipLevel++; - blit.srcOffsets[1].x = blit.dstOffsets[1].x; - blit.srcOffsets[1].y = blit.dstOffsets[1].y; - blit.dstSubresource.mipLevel++; - blit.dstOffsets[1].x = max (blit.dstOffsets[1].x >> 1, 1); - blit.dstOffsets[1].y = max (blit.dstOffsets[1].y >> 1, 1); - barrier.subresourceRange.baseMipLevel++; + } else { + blit_mips (mip, qtex->image, tex, dfunc, packet->cmd); } QFV_PacketSubmit (packet); return qtex; From 97febc0888681dbae463c948841cdd8d665e7be9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Jan 2021 12:51:22 +0900 Subject: [PATCH 1278/3664] [tools/misc] Update mdl.py for python 3 --- tools/misc/mdl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/misc/mdl.py b/tools/misc/mdl.py index 00c788316..f9b6698c4 100644 --- a/tools/misc/mdl.py +++ b/tools/misc/mdl.py @@ -22,8 +22,8 @@ for i in range(m[6]): else: n = unpack ("i", model[:4])[0] model = model [4:] - print n - k = (n, unpack (`n`+"f", model[:n*4]), []) + print (n) + k = (n, unpack (("%df" % n), model[:n*4]), []) model = model [n*4:] for j in range (n): k[2].append (model[:s]) @@ -67,7 +67,7 @@ for i in range (m[11]): g = (t, unpack ("i 3B B 3B B", model[:12])) model = model[12:] n = g[1][0] - g = g + (unpack (`n`+"f", model[:n*4]), []) + g = g + (unpack (("%df" % n), model[:n*4]), []) model = model[n*4:] for k in range (g[1][0]): f = (unpack ("3B B 3B B 16s", model[:24]), []) From 4da8feca360d786e4c3adc1dda1cb4a28df53fce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Jan 2021 16:13:37 +0900 Subject: [PATCH 1279/3664] [models] Fix some vulkan alias upload errors Fixes the bogus vertex/index data and does barriers for all three buffers. --- libs/models/alias/vulkan_model_alias.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index e3e5f0701..a5520217c 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -144,7 +144,7 @@ Vulkan_Mod_LoadSkin (byte *skinpix, int skinsize, int snum, int gnum, free (tskin); - return skin + skinsize; + return skinpix + skinsize; } void @@ -288,8 +288,10 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, } VectorCompMultAdd (hdr->mdl.scale_origin, hdr->mdl.scale, pos, verts[pose + j].vertex); + verts[pose + j].vertex[3] = 1; VectorCopy (vertex_normals[pv->lightnormalindex], verts[pose + j].normal); + verts[pose + j].normal[3] = 0; // duplicate on-seam vert associated with back-facing triangle if (indexmap[j] != -1) { verts[pose + indexmap[j]] = verts[pose + j]; @@ -357,7 +359,7 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, dfunc->vkCmdPipelineBarrier (packet->cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, 0, 0, 1, rd_barriers, 0, 0); + 0, 0, 0, 3, rd_barriers, 0, 0); QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); From 9f6441684611a432521b770130173c929084a90a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Jan 2021 16:16:28 +0900 Subject: [PATCH 1280/3664] [vulkan] Create the lights buffer It's a tad bogus as it's the lights close to the camera, but it should at least be a good start once things are working. There's currently something very wrong with the state of things. --- include/QF/Vulkan/buffer.h | 5 +++ libs/video/renderer/vulkan/instance.c | 9 ++++- libs/video/renderer/vulkan/vulkan_alias.c | 46 ++++++++++++++++++++++- libs/video/renderer/vulkan/vulkan_main.c | 6 +-- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h index 9346d0466..712b14a96 100644 --- a/include/QF/Vulkan/buffer.h +++ b/include/QF/Vulkan/buffer.h @@ -18,6 +18,11 @@ typedef struct qfv_buffertransitionset_s typedef struct qfv_bufferbarrierset_s DARRAY_TYPE (VkBufferMemoryBarrier) qfv_bufferbarrierset_t; +typedef struct qfv_bufferset_s + DARRAY_TYPE (VkBuffer) qfv_bufferset_t; +#define QFV_AllocBufferSet(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_bufferset_t, num, allocator) + struct qfv_device_s; VkBuffer QFV_CreateBuffer (struct qfv_device_s *device, VkDeviceSize size, diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index 617d792e8..d1c845c6b 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -125,6 +125,11 @@ static int message_types = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; +static void +debug_breakpoint (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity) +{ +} + static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -144,7 +149,9 @@ debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { msgSev = "error: "; } - fprintf (stderr, "validation layer: %s%s\n", msgSev, callbackData->pMessage); + fprintf (stderr, "validation layer: %s%s\n", msgSev, + callbackData->pMessage); + debug_breakpoint (messageSeverity); return VK_FALSE; } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 3fa9d7c52..4ba872a1a 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -55,6 +55,7 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" @@ -131,8 +132,9 @@ Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx) dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->layout, - 0, 2, aframe->descriptors - + ALIAS_BUFFER_INFOS); + ALIAS_BUFFER_INFOS, ALIAS_IMAGE_INFOS, + aframe->descriptors + + ALIAS_BUFFER_INFOS); dfunc->vkCmdDrawIndexed (aframe->cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); } @@ -142,6 +144,8 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; + + dlight_t *lights[ALIAS_LIGHTS]; //XXX quat_t fog; __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; @@ -149,6 +153,18 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) VkCommandBuffer cmd = aframe->cmd; DARRAY_APPEND (cframe->subCommand, cmd); + R_FindNearLights (r_origin, ALIAS_LIGHTS, lights); + aframe->lights->light_count = 0; + for (int i = 0; i < ALIAS_LIGHTS; i++) { + if (!lights[i]) { + break; + } + aframe->lights->light_count++; + VectorCopy (lights[i]->color, aframe->lights->lights[i].color); + VectorCopy (lights[i]->origin, aframe->lights->lights[i].position); + aframe->lights->lights[i].dist = lights[i]->radius; + } + //FIXME need per frame matrices aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; aframe->bufferInfo[1].buffer = aframe->light_buffer; @@ -169,6 +185,12 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->pipeline); + VkDescriptorSet sets[] = { + aframe->descriptors[0].dstSet, + aframe->descriptors[1].dstSet, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + actx->layout, 0, 2, sets, 0, 0); VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); @@ -214,6 +236,7 @@ void Vulkan_Alias_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); ctx->alias_context = actx; @@ -239,10 +262,29 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); + __auto_type lbuffers = QFV_AllocBufferSet (frames, alloca); + for (size_t i = 0; i < frames; i++) { + lbuffers->a[i] = QFV_CreateBuffer (device, sizeof (qfv_light_buffer_t), + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + } + VkMemoryRequirements requirements; + dfunc->vkGetBufferMemoryRequirements (device->dev, lbuffers->a[0], + &requirements); + actx->light_memory = QFV_AllocBufferMemory (device, lbuffers->a[0], + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + frames * requirements.size, 0); + byte *light_data; + dfunc->vkMapMemory (device->dev, actx->light_memory, 0, + frames * requirements.size, 0, (void **) &light_data); + __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < frames; i++) { __auto_type aframe = &actx->frames.a[i]; aframe->cmd = cmdBuffers->a[i]; + aframe->light_buffer = lbuffers->a[i]; + aframe->lights = (qfv_light_buffer_t *) (light_data + i * requirements.size); + QFV_BindBufferMemory (device, lbuffers->a[i], actx->light_memory, + i * requirements.size); for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) { aframe->bufferInfo[j] = base_buffer_info; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 95fcd02ab..8df89eaa1 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -109,14 +109,12 @@ setup_view (vulkan_ctx_t *ctx) static void R_RenderEntities (vulkan_ctx_t *ctx) { - entity_t *ent; - int begun; - if (!r_drawentities->int_val) return; #define RE_LOOP(type_name, Type) \ do { \ - begun = 0; \ + entity_t *ent; \ + int begun = 0; \ for (ent = r_ent_queue; ent; ent = ent->next) { \ if (ent->model->type != mod_##type_name) \ continue; \ From caa7623a353943070b2d871ca9f2fe5a9a8daa70 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Jan 2021 17:59:09 +0900 Subject: [PATCH 1281/3664] [vulkan] Clean up alias light buffer Still wedging, but it seems to be something to do with the matrix buffer. --- libs/video/renderer/vulkan/vulkan_alias.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 4ba872a1a..0a74c0582 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -105,8 +105,8 @@ Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx) } VkDeviceSize offsets[] = { - ent->pose1 * hdr->poseverts, - ent->pose2 * hdr->poseverts, + ent->pose1 * hdr->poseverts * sizeof (aliasvrt_t), + ent->pose2 * hdr->poseverts * sizeof (aliasvrt_t), 0, }; VkBuffer buffers[] = { @@ -289,7 +289,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) { aframe->bufferInfo[j] = base_buffer_info; aframe->descriptors[j] = base_buffer_write; - aframe->descriptors[j].dstSet = sets->a[2 * i + j]; + aframe->descriptors[j].dstSet = sets->a[ALIAS_BUFFER_INFOS*i + j]; aframe->descriptors[j].dstBinding = 0; aframe->descriptors[j].pBufferInfo = &aframe->bufferInfo[j]; } @@ -312,6 +312,12 @@ Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx) qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; + for (size_t i = 0; i < actx->frames.size; i++) { + __auto_type aframe = &actx->frames.a[i]; + dfunc->vkDestroyBuffer (device->dev, aframe->light_buffer, 0); + } + dfunc->vkFreeMemory (device->dev, actx->light_memory, 0); + dfunc->vkDestroyPipeline (device->dev, actx->pipeline, 0); DARRAY_CLEAR (&actx->frames); free (actx); From 64904e2b2766e605e150facc50b50d0decb430be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 28 Jan 2021 10:49:23 +0900 Subject: [PATCH 1282/3664] [vulkan] Switch over to pushed descriptors I don't really know why (I need to do some research), but this fixes the lockups when accessing the matrices UBO. It has made a mess of my carefully designed uniform binding layout, so I hope I can get bound descriptor sets working the way I want, but I really need to progress on the rest of the project. --- libs/video/renderer/vulkan/alias.frag | 8 ++-- libs/video/renderer/vulkan/qfpipeline.plist | 48 +++++++++++++++++++-- libs/video/renderer/vulkan/vulkan_alias.c | 27 +++++++----- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/alias.frag index d1ad194bb..8fb794f47 100644 --- a/libs/video/renderer/vulkan/alias.frag +++ b/libs/video/renderer/vulkan/alias.frag @@ -1,5 +1,5 @@ #version 450 - +/* layout (set = 2, binding = 0) uniform sampler2D Texture; layout (set = 2, binding = 1) uniform sampler2D GlowMap; layout (set = 2, binding = 2) uniform sampler2D ColorA; @@ -19,7 +19,7 @@ layout (set = 1, binding = 0) uniform Lights { int light_count; LightData lights[MaxLights]; }; - +*/ layout (push_constant) uniform PushConstants { layout (offset = 80) vec4 fog; @@ -38,7 +38,7 @@ main (void) vec4 c; int i; vec3 light = vec3 (0); - +/* c = texture (Texture, st); c += texture (ColorA, st); c += texture (ColorB, st); @@ -52,4 +52,6 @@ main (void) } } frag_color = c * vec4(light, 1);//fogBlend (c); +*/ + frag_color = vec4((normal + 1)/2, 1); } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index b6823707c..3cbf8db5e 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -110,7 +110,7 @@ }, ); }; - quakebsp.textures = { + quakebsp.set = { flags = push_descriptor; bindings = ( { @@ -151,6 +151,47 @@ }, ); }; + alias.set = { + flags = push_descriptor; + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + binding = 1; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 3; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 4; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 5; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; alias.matrices = { bindings = ( { @@ -223,7 +264,7 @@ setLayouts = (twod.set); }; quakebsp.layout = { - setLayouts = (quakebsp.textures); + setLayouts = (quakebsp.set); pushConstantRanges = ( { stageFlags = vertex; @@ -238,7 +279,8 @@ ); }; alias.layout = { - setLayouts = (alias.matrices, alias.lights, alias.textures); + //setLayouts = (alias.matrices, alias.lights, alias.textures); + setLayouts = (alias.set); pushConstantRanges = ( { stageFlags = vertex; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 0a74c0582..3fd17c0b1 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -123,6 +123,7 @@ Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx) dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, VK_SHADER_STAGE_VERTEX_BIT, 64, sizeof (float), &blend); + if (0) { aframe->imageInfo[0].imageView = get_view (skin->tex, ctx->default_white); aframe->imageInfo[1].imageView = get_view (skin->glow, ctx->default_black); aframe->imageInfo[2].imageView = get_view (skin->colora, @@ -135,6 +136,7 @@ Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx) ALIAS_BUFFER_INFOS, ALIAS_IMAGE_INFOS, aframe->descriptors + ALIAS_BUFFER_INFOS); + } dfunc->vkCmdDrawIndexed (aframe->cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); } @@ -185,18 +187,21 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->pipeline); - VkDescriptorSet sets[] = { - aframe->descriptors[0].dstSet, - aframe->descriptors[1].dstSet, - }; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, 0, 2, sets, 0, 0); + //VkDescriptorSet sets[] = { + // aframe->descriptors[0].dstSet, + // aframe->descriptors[1].dstSet, + //}; + //dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + // actx->layout, 0, 2, sets, 0, 0); + dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + actx->layout, + 0, 1, aframe->descriptors + 0); VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); - dfunc->vkUpdateDescriptorSets (device->dev, 2, aframe->descriptors, 0, 0); + //dfunc->vkUpdateDescriptorSets (device->dev, 2, aframe->descriptors, 0, 0); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -257,7 +262,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) layouts->a[2 * i + 0] = mats; layouts->a[2 * i + 1] = lights; } - __auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool"); + //__auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool"); __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); @@ -277,7 +282,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) dfunc->vkMapMemory (device->dev, actx->light_memory, 0, frames * requirements.size, 0, (void **) &light_data); - __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); + //__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < frames; i++) { __auto_type aframe = &actx->frames.a[i]; aframe->cmd = cmdBuffers->a[i]; @@ -289,7 +294,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) { aframe->bufferInfo[j] = base_buffer_info; aframe->descriptors[j] = base_buffer_write; - aframe->descriptors[j].dstSet = sets->a[ALIAS_BUFFER_INFOS*i + j]; + //aframe->descriptors[j].dstSet = sets->a[ALIAS_BUFFER_INFOS*i + j]; aframe->descriptors[j].dstBinding = 0; aframe->descriptors[j].pBufferInfo = &aframe->bufferInfo[j]; } @@ -302,7 +307,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) aframe->descriptors[k].pImageInfo = &aframe->imageInfo[j]; } } - free (sets); + //free (sets); } void From 28652c4d59134443dc8a4910fdc90f5dec829ac2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 28 Jan 2021 14:14:21 +0900 Subject: [PATCH 1283/3664] [vulkan] Implement alias model texturing I had messed up my index array creation, but once that was fixed the textures worked well other than a lot of pixels are shades of grey due to being in the top or bottom color map range. --- libs/models/alias/vulkan_model_alias.c | 9 +++++---- libs/video/renderer/vulkan/alias.frag | 13 +++++++++---- libs/video/renderer/vulkan/vulkan_alias.c | 6 ++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index a5520217c..832541071 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -300,12 +300,13 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, } // now build the indices for DrawElements - for (i = 0; i < hdr->mdl.numverts; i++) { - indexmap[i] = indexmap[i] != -1 ? indexmap[i] : i; - } for (i = 0; i < numtris; i++) { for (j = 0; j < 3; j++) { - indices[3 * i + j] = indexmap[triangles.a[i].vertindex[j]]; + int vind = triangles.a[i].vertindex[j]; + if (stverts.a[vind].onseam && !triangles.a[i].facesfront) { + vind = indexmap[vind]; + } + indices[3 * i + j] = vind; } } // finished with indexmap diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/alias.frag index 8fb794f47..513b92d2a 100644 --- a/libs/video/renderer/vulkan/alias.frag +++ b/libs/video/renderer/vulkan/alias.frag @@ -1,4 +1,8 @@ #version 450 +layout (set = 0, binding = 2) uniform sampler2D Texture; +layout (set = 0, binding = 3) uniform sampler2D GlowMap; +layout (set = 0, binding = 4) uniform sampler2D ColorA; +layout (set = 0, binding = 5) uniform sampler2D ColorB; /* layout (set = 2, binding = 0) uniform sampler2D Texture; layout (set = 2, binding = 1) uniform sampler2D GlowMap; @@ -38,11 +42,10 @@ main (void) vec4 c; int i; vec3 light = vec3 (0); -/* c = texture (Texture, st); c += texture (ColorA, st); c += texture (ColorB, st); - c += texture (GlowMap, st); +/* if (MaxLights > 0) { for (i = 0; i < light_count; i++) { vec3 dist = lights[i].position - position; @@ -51,7 +54,9 @@ main (void) light += lights[i].color * mag * lights[i].dist / dd; } } - frag_color = c * vec4(light, 1);//fogBlend (c); + c *= vec4 (light, 1); */ - frag_color = vec4((normal + 1)/2, 1); + c += texture (GlowMap, st); + //frag_color = vec4((normal + 1)/2, 1); + frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 3fd17c0b1..6d1628bc0 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -123,7 +123,6 @@ Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx) dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, VK_SHADER_STAGE_VERTEX_BIT, 64, sizeof (float), &blend); - if (0) { aframe->imageInfo[0].imageView = get_view (skin->tex, ctx->default_white); aframe->imageInfo[1].imageView = get_view (skin->glow, ctx->default_black); aframe->imageInfo[2].imageView = get_view (skin->colora, @@ -133,10 +132,9 @@ Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx) dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->layout, - ALIAS_BUFFER_INFOS, ALIAS_IMAGE_INFOS, + 0, ALIAS_IMAGE_INFOS, aframe->descriptors + ALIAS_BUFFER_INFOS); - } dfunc->vkCmdDrawIndexed (aframe->cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); } @@ -303,7 +301,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) aframe->imageInfo[j].sampler = actx->sampler; int k = j + ALIAS_BUFFER_INFOS; aframe->descriptors[k] = base_image_write; - aframe->descriptors[k].dstBinding = j; + aframe->descriptors[k].dstBinding = k; aframe->descriptors[k].pImageInfo = &aframe->imageInfo[j]; } } From 206c63181141b37dec4cda716053928289dd15a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 28 Jan 2021 15:20:24 +0900 Subject: [PATCH 1284/3664] [vulkan] Get alias lighting mostly working It's not so much that parts aren't working, but rather there's no base-level lighting so everything is black until a dlight is in the vicinity --- libs/video/renderer/vulkan/alias.frag | 11 ++++++----- libs/video/renderer/vulkan/vulkan_alias.c | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/alias.frag index 513b92d2a..aa0deafdb 100644 --- a/libs/video/renderer/vulkan/alias.frag +++ b/libs/video/renderer/vulkan/alias.frag @@ -8,7 +8,7 @@ layout (set = 2, binding = 0) uniform sampler2D Texture; layout (set = 2, binding = 1) uniform sampler2D GlowMap; layout (set = 2, binding = 2) uniform sampler2D ColorA; layout (set = 2, binding = 3) uniform sampler2D ColorB; - +*/ struct LightData { vec3 color; float dist; @@ -19,11 +19,12 @@ struct LightData { }; layout (constant_id = 0) const int MaxLights = 8; -layout (set = 1, binding = 0) uniform Lights { +//layout (set = 1, binding = 0) uniform Lights { +layout (set = 0, binding = 1) uniform Lights { int light_count; LightData lights[MaxLights]; }; -*/ + layout (push_constant) uniform PushConstants { layout (offset = 80) vec4 fog; @@ -45,7 +46,7 @@ main (void) c = texture (Texture, st); c += texture (ColorA, st); c += texture (ColorB, st); -/* + if (MaxLights > 0) { for (i = 0; i < light_count; i++) { vec3 dist = lights[i].position - position; @@ -55,7 +56,7 @@ main (void) } } c *= vec4 (light, 1); -*/ + c += texture (GlowMap, st); //frag_color = vec4((normal + 1)/2, 1); frag_color = c;//fogBlend (c); diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 6d1628bc0..a71e0629e 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -193,7 +193,7 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) // actx->layout, 0, 2, sets, 0, 0); dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->layout, - 0, 1, aframe->descriptors + 0); + 0, 2, aframe->descriptors + 0); VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); @@ -293,7 +293,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) aframe->bufferInfo[j] = base_buffer_info; aframe->descriptors[j] = base_buffer_write; //aframe->descriptors[j].dstSet = sets->a[ALIAS_BUFFER_INFOS*i + j]; - aframe->descriptors[j].dstBinding = 0; + aframe->descriptors[j].dstBinding = j; aframe->descriptors[j].pBufferInfo = &aframe->bufferInfo[j]; } for (int j = 0; j < ALIAS_IMAGE_INFOS; j++) { From 7ee02f39653e952101c73b8b67bc6dadf240e952 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 28 Jan 2021 19:17:40 +0900 Subject: [PATCH 1285/3664] [vulkan] Sort of implement ambient lighting It works, but as it uses the camera position rather than the lit entity's position, it is incorrect. I have some interim ideas to handle it, though. --- libs/video/renderer/vulkan/alias.frag | 21 ++++++++++++--- libs/video/renderer/vulkan/vulkan_alias.c | 33 ++++++++++++++++++----- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/alias.frag index aa0deafdb..eff6ff10a 100644 --- a/libs/video/renderer/vulkan/alias.frag +++ b/libs/video/renderer/vulkan/alias.frag @@ -37,6 +37,22 @@ layout (location = 2) in vec3 normal; layout (location = 0) out vec4 frag_color; +vec3 +calc_light (LightData light) +{ + if (light.type == 0) { + vec3 dist = light.position - position; + float dd = dot (dist, dist); + float mag = max (0.0, dot (dist, normal)); + return light.color * mag * light.dist / dd; + } else if (light.type == 1) { + } else if (light.type == 2) { + float mag = max (0.0, -dot (light.direction, normal)); + // position is ambient light + return light.color * dot (light.direction, normal) + light.position; + } +} + void main (void) { @@ -49,10 +65,7 @@ main (void) if (MaxLights > 0) { for (i = 0; i < light_count; i++) { - vec3 dist = lights[i].position - position; - float dd = dot (dist, dist); - float mag = max (0.0, dot (dist, normal)); - light += lights[i].color * mag * lights[i].dist / dd; + light += calc_light (lights[i]); } } c *= vec4 (light, 1); diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index a71e0629e..a31267cfb 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -77,7 +77,7 @@ get_view (qfv_tex_t *tex, qfv_tex_t *default_tex) } void -Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx) +Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -138,6 +138,22 @@ Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx) dfunc->vkCmdDrawIndexed (aframe->cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); } +static void +calc_lighting (qfv_light_t *light, entity_t *ent) +{ + vec3_t ambient_color; + //FIXME should be ent->position + float l = R_LightPoint (r_origin) / 128.0; + + //XXX l = max (light, max (ent->model->min_light, ent->min_light)); + light->type = 2; + VectorSet (1, 1, 1, ambient_color); //FIXME + // position doubles as ambient light + VectorScale (ambient_color, l, light->position); + VectorSet (-1, 0, 0, light->direction); //FIXME + VectorCopy (light->position, light->color); +} + void Vulkan_AliasBegin (vulkan_ctx_t *ctx) { @@ -153,16 +169,19 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) VkCommandBuffer cmd = aframe->cmd; DARRAY_APPEND (cframe->subCommand, cmd); - R_FindNearLights (r_origin, ALIAS_LIGHTS, lights); - aframe->lights->light_count = 0; - for (int i = 0; i < ALIAS_LIGHTS; i++) { + //FIXME ambient needs to be per entity + aframe->lights->light_count = 1; + calc_lighting (&aframe->lights->lights[0], 0); + R_FindNearLights (r_origin, ALIAS_LIGHTS - 1, lights); + for (int i = 0; i < ALIAS_LIGHTS - 1; i++) { if (!lights[i]) { break; } aframe->lights->light_count++; - VectorCopy (lights[i]->color, aframe->lights->lights[i].color); - VectorCopy (lights[i]->origin, aframe->lights->lights[i].position); - aframe->lights->lights[i].dist = lights[i]->radius; + VectorCopy (lights[i]->color, aframe->lights->lights[i + 1].color); + VectorCopy (lights[i]->origin, aframe->lights->lights[i + 1].position); + aframe->lights->lights[i + 1].dist = lights[i]->radius; + aframe->lights->lights[i + 1].type = 0; } //FIXME need per frame matrices From cad1eb42fdc1f3e72feb0db3ce346fca41391b2f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 30 Jan 2021 14:45:47 +0900 Subject: [PATCH 1286/3664] [qwaq] Put my qdb script in a safe place The paths are generally wrong, and it's not overly complicated, but having a reference helps me remember how to use the thing. --- ruamoko/qwaq/qdb | 3 +++ 1 file changed, 3 insertions(+) create mode 100755 ruamoko/qwaq/qdb diff --git a/ruamoko/qwaq/qdb b/ruamoko/qwaq/qdb new file mode 100755 index 000000000..7f1ed27e2 --- /dev/null +++ b/ruamoko/qwaq/qdb @@ -0,0 +1,3 @@ +#! /bin/bash -x + +./qwaq-curses qwaq-app.dat $1 From f523f6ba80eeb7efdc0095c2c27a23e39439cc4d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 30 Jan 2021 14:49:42 +0900 Subject: [PATCH 1287/3664] [vid] Disable X11 repeat control For now, at least. It is a royal pain in the neck when doing a lot of development work and I'm not sure it's worthwhile on modern CPUs. --- libs/video/targets/in_x11.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 8ef111ec2..2787771c6 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -599,11 +599,11 @@ XLateKey (XKeyEvent * ev, int *k, int *u) static void x11_keydest_callback (keydest_t key_dest) { - if (key_dest == key_game) { - XAutoRepeatOff (x_disp); - } else { - XAutoRepeatOn (x_disp); - } +// if (key_dest == key_game) { +// XAutoRepeatOff (x_disp); +// } else { +// XAutoRepeatOn (x_disp); +// } } static void @@ -792,7 +792,7 @@ IN_LL_Shutdown (void) Sys_MaskPrintf (SYS_VID, "IN_LL_Shutdown\n"); in_mouse_avail = 0; if (x_disp) { - XAutoRepeatOn (x_disp); +// XAutoRepeatOn (x_disp); dga_off (); } if (in_mouse_accel && !in_mouse_accel->int_val) From 7970525ef4fac3a3ea11e9ee85ff83d81dc853eb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 31 Jan 2021 16:01:20 +0900 Subject: [PATCH 1288/3664] [util] Make va thread-safe It now takes a context pointer (opaque data) that holds the buffers it uses for the temporary strings. If the context pointer is null, a static context is used (making those uses of va NOT thread-safe). Most calls to va use the static context, but all such calls have been formatted consistently so they are easy to find when it comes time to do a full audit. --- include/QF/va.h | 57 ++++++++++++++++++++-- include/vid_vulkan.h | 1 + libs/audio/cd_file.c | 4 +- libs/audio/renderer/snd_jack.c | 2 +- libs/audio/renderer/snd_sfx.c | 2 +- libs/console/client.c | 4 +- libs/console/complete.c | 2 +- libs/console/filelist.c | 2 +- libs/gib/exp.c | 16 +++--- libs/gib/gib_builtin.c | 2 +- libs/gib/gib_classes.c | 4 +- libs/gib/gib_object.c | 2 +- libs/gib/gib_parse.c | 6 ++- libs/gib/gib_vars.c | 2 +- libs/models/alias/gl_model_alias.c | 14 +++--- libs/models/alias/glsl_model_alias.c | 4 +- libs/models/alias/vulkan_model_alias.c | 17 +++++-- libs/models/brush/gl_model_brush.c | 20 ++++---- libs/models/brush/vulkan_model_brush.c | 2 +- libs/models/iqm/gl_model_iqm.c | 2 +- libs/models/iqm/glsl_model_iqm.c | 4 +- libs/models/iqm/sw_model_iqm.c | 2 +- libs/models/skin.c | 2 +- libs/models/sprite/gl_model_sprite.c | 2 +- libs/models/sprite/glsl_model_sprite.c | 2 +- libs/ruamoko/rua_cvar.c | 6 +-- libs/ruamoko/rua_qfs.c | 3 +- libs/util/cvar.c | 4 +- libs/util/qfplist.c | 32 +++++++----- libs/util/quakefs.c | 18 +++---- libs/util/va.c | 53 ++++++++++++++------ libs/video/renderer/gl/gl_dyn_part.c | 2 +- libs/video/renderer/gl/gl_screen.c | 2 +- libs/video/renderer/gl/gl_sky.c | 5 +- libs/video/renderer/glsl/glsl_bsp.c | 6 +-- libs/video/renderer/glsl/glsl_particles.c | 2 +- libs/video/renderer/glsl/glsl_screen.c | 4 +- libs/video/renderer/glsl/vid_common_glsl.c | 2 +- libs/video/renderer/sw/screen.c | 2 +- libs/video/renderer/sw/sw_rpart.c | 2 +- libs/video/renderer/sw32/screen.c | 4 +- libs/video/renderer/sw32/sw32_rpart.c | 2 +- libs/video/targets/context_sdl.c | 4 +- libs/video/targets/context_x11.c | 2 +- libs/video/targets/joy.c | 2 +- libs/video/targets/vid.c | 16 +++--- libs/video/targets/vid_x11.c | 4 +- libs/video/targets/vid_x11_vulkan.c | 2 + nq/source/cl_demo.c | 2 +- nq/source/cl_main.c | 10 ++-- nq/source/cl_parse.c | 2 +- nq/source/host.c | 6 +-- nq/source/host_cmd.c | 22 ++++----- nq/source/sbar.c | 28 +++++------ nq/source/sv_main.c | 2 +- nq/source/sv_pr_cmds.c | 2 +- qtv/source/client.c | 6 +-- qtv/source/qtv.c | 2 +- qtv/source/sbar.c | 4 +- qtv/source/server.c | 5 +- qtv/source/sv_parse.c | 12 ++--- qw/source/cl_chat.c | 2 +- qw/source/cl_cvar.c | 2 +- qw/source/cl_demo.c | 6 +-- qw/source/cl_main.c | 12 ++--- qw/source/cl_parse.c | 35 +++++++------ qw/source/cl_skin.c | 5 +- qw/source/cl_slist.c | 2 +- qw/source/crudefile.c | 2 +- qw/source/locs.c | 4 +- qw/source/sbar.c | 29 ++++++----- qw/source/sv_ccmds.c | 32 ++++++------ qw/source/sv_demo.c | 10 ++-- qw/source/sv_init.c | 4 +- qw/source/sv_main.c | 6 +-- qw/source/sv_pr_cmds.c | 10 ++-- qw/source/sv_pr_qwe.c | 2 +- qw/source/sv_qtv.c | 8 +-- qw/source/sv_sbar.c | 4 +- qw/source/sv_user.c | 16 +++--- qw/source/teamplay.c | 8 +-- ruamoko/qwaq/builtins/main.c | 2 +- ruamoko/qwaq/builtins/qwaq.c | 2 +- tools/qfbsp/source/brush.c | 2 +- tools/qfbsp/source/map.c | 2 +- tools/qfbsp/source/readbsp.c | 4 +- tools/qfbsp/source/writebsp.c | 2 +- tools/qfcc/source/class.c | 55 +++++++++++---------- tools/qfcc/source/def.c | 6 +-- tools/qfcc/source/dot_expr.c | 31 ++++++------ tools/qfcc/source/dot_flow.c | 2 +- tools/qfcc/source/dot_type.c | 2 +- tools/qfcc/source/dump_globals.c | 30 ++++++------ tools/qfcc/source/expr.c | 7 +-- tools/qfcc/source/flow.c | 2 +- tools/qfcc/source/function.c | 6 +-- tools/qfcc/source/linker.c | 2 +- tools/qfcc/source/method.c | 4 +- tools/qfcc/source/obj_file.c | 4 +- tools/qfcc/source/options.c | 2 +- tools/qfcc/source/qc-parse.y | 6 ++- tools/qfcc/source/qfcc.c | 4 +- tools/qfcc/source/qfprogs.c | 4 +- tools/qfcc/source/statements.c | 43 ++++++++-------- tools/qfcc/source/struct.c | 6 +-- tools/qflight/source/entities.c | 3 +- tools/qflight/source/qflight.c | 2 +- tools/wad/script.c | 2 +- 108 files changed, 505 insertions(+), 390 deletions(-) diff --git a/include/QF/va.h b/include/QF/va.h index 1bf0eadaf..74a28aba7 100644 --- a/include/QF/va.h +++ b/include/QF/va.h @@ -34,9 +34,60 @@ */ ///@{ -// does a varargs printf into a temp buffer -char *va(const char *format, ...) __attribute__((format(printf,1,2))); -// does a varargs printf into a malloced buffer +/** Opaque context for va so it can have per-thread data. + */ +typedef struct va_ctx_s va_ctx_t; + +/** Create a va context with the specified number of buffers. + * + * Having multiple buffers allows va to be used in short chains. + * + * \param buffers The number of buffers to create in the context. va() will + * cycle through the buffers for each call. + * \return Pointer to the context. Pass to va() for thread-safe usage. + */ +va_ctx_t *va_create_context (int buffers); + +/** Destroy a va context. + * + * \param ctx The context to be destroyed. Must have been created by + * va_create_context(). + * \note Any pointers to strings returned by va() using the context + * referenced by \a ctx will become invalid as the backing + * memory for the strings will have been freed. + */ +void va_destroy_context (va_ctx_t *ctx); + +/** Does a varargs printf into a private buffer. + * + * \param ctx Context used for storing the private buffer such that va + * can be used in a multi-threaded environment. If null then + * a static context is used, in which case va is NOT + * thread-safe. + * \param format Standard printf() format string. + * \return Pointer to the beginning of the output string. The memory + * for the returned string is owned by the context pointed to + * by \a ctx. + * \note The static context is created with 4 buffers, so va (0,...) + * can be used to produce mildly complex output (eg, 3 calls + * to va sent to a 4th) with a reduced risk of strings being + * trampled. + */ +char *va(va_ctx_t *ctx, const char *format, ...) __attribute__((format(printf,2,3))); + +/** Does a varargs printf into a malloced buffer. + * + * Combines the effect of strdup and sprintf, but in a safe manner. Essentially + * the equivalent of strdup (va (ctx, format, ...)); + * + * \param format Standard printf() format string. + * \return Pointer to the beginning of the output string. The caller + * is responsible for freeing the memory holding the string. + * \note As nva() creates a new buffer every time it is called, it + * is thread-safe and there is no risk of the string being + * trampled. In addition, it does not use va(), so combining + * nva() with va() is safe. + */ char *nva(const char *format, ...) __attribute__((format(printf,1,2))); ///@} diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 8a60707fe..a213c7ac5 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -50,6 +50,7 @@ typedef struct vulkan_ctx_s { void (*create_window) (struct vulkan_ctx_s *ctx); VkSurfaceKHR (*create_surface) (struct vulkan_ctx_s *ctx); + struct va_ctx_s *va_ctx; struct qfv_instance_s *instance; struct qfv_device_s *device; struct qfv_swapchain_s *swapchain; diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index 94d394154..ef9979bd9 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -189,7 +189,7 @@ Load_Tracklist (void) static void I_OGGMus_SetPlayList (int track) { - const char *trackstring = va ("%i", track); + const char *trackstring = va (0, "%i", track); int i; play_list = PL_ObjectForKey (tracklist, trackstring); @@ -327,7 +327,7 @@ I_OGGMus_Info (void) /* loop, and count up the Highest key number. */ for (iter = 1, count = 0; count < keycount && iter <= 99 ; iter++) { - trackstring = va ("%i", iter); + trackstring = va (0, "%i", iter); if (!(currenttrack = PL_ObjectForKey (tracklist, trackstring))) { continue; } diff --git a/libs/audio/renderer/snd_jack.c b/libs/audio/renderer/snd_jack.c index f37ef3dc8..e35d61e50 100644 --- a/libs/audio/renderer/snd_jack.c +++ b/libs/audio/renderer/snd_jack.c @@ -329,7 +329,7 @@ s_jack_connect (void) jack_set_process_callback (jack_handle, snd_jack_process, 0); jack_on_shutdown (jack_handle, snd_jack_shutdown, 0); for (i = 0; i < 2; i++) - jack_out[i] = jack_port_register (jack_handle, va ("out_%d", i + 1), + jack_out[i] = jack_port_register (jack_handle, va (0, "out_%d", i + 1), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); snd_shm->speed = jack_get_sample_rate (jack_handle); diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 4dc57ee90..8152213a6 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -199,7 +199,7 @@ SND_PrecacheSound (const char *name) if (!name) Sys_Error ("SND_PrecacheSound: NULL"); - sfx = SND_LoadSound (va ("sound/%s", name)); + sfx = SND_LoadSound (va (0, "sound/%s", name)); if (sfx && precache->int_val) { if (sfx->retain (sfx)) sfx->release (sfx); diff --git a/libs/console/client.c b/libs/console/client.c index 582113703..3370a7614 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -251,7 +251,7 @@ Condump_f (void) Sys_Printf ("invalid character in filename\n"); return; } - name = va ("%s/%s.txt", qfs_gamedir->dir.def, Cmd_Argv (1)); + name = va (0, "%s/%s.txt", qfs_gamedir->dir.def, Cmd_Argv (1));//FIXME if (!(file = QFS_WOpen (name, 0))) { Sys_Printf ("could not open %s for writing: %s\n", name, @@ -375,7 +375,7 @@ C_Print (const char *fmt, va_list args) // log all messages to file if (con_debuglog) - Sys_DebugLog (va ("%s/%s/qconsole.log", qfs_userpath, + Sys_DebugLog (va (0, "%s/%s/qconsole.log", qfs_userpath,//FIXME qfs_gamedir->dir.def), "%s", buffer->str); if (!con_initialized) diff --git a/libs/console/complete.c b/libs/console/complete.c index 83dedc7a1..220906473 100644 --- a/libs/console/complete.c +++ b/libs/console/complete.c @@ -157,7 +157,7 @@ Con_BasicCompleteCommandLine (inputline_t *il) && strncmp (s + bound, cmd, strlen (s + bound))) bound++; - overwrite = va("%.*s%.*s", bound, s, cmd_len, cmd); + overwrite = va (0, "%.*s%.*s", bound, s, cmd_len, cmd); il->lines[il->edit_line][1] = '/'; strncpy (il->lines[il->edit_line] + 2, overwrite, il->line_size - 3); diff --git a/libs/console/filelist.c b/libs/console/filelist.c index dd979743a..b2942c593 100644 --- a/libs/console/filelist.c +++ b/libs/console/filelist.c @@ -167,7 +167,7 @@ Con_Skyboxlist_f (void) for (j = 1; sb_endings[j]; j++) { b = 0; for (k = 0; k < skyboxlist->count; k++) { - if (strcmp(va("%s%s", basename->str, sb_endings[j]), + if (strcmp(va (0, "%s%s", basename->str, sb_endings[j]), skyboxlist->list[k]) == 0) { b = 1; *skyboxlist->list[k] = 0; diff --git a/libs/gib/exp.c b/libs/gib/exp.c index f56159e71..3ca5b19b8 100644 --- a/libs/gib/exp.c +++ b/libs/gib/exp.c @@ -311,7 +311,7 @@ EXP_ParseString (char *str) } else { EXP_DestroyTokens (chain); EXP_Error (EXP_E_INVOP, - va ("Unknown operator or function '%s'.", buf)); + va (0, "Unknown operator or function '%s'.", buf)); return 0; } } @@ -347,8 +347,7 @@ EXP_SimplifyTokens (token * chain) cur = cur->generic.prev; if (EXP_DoFunction (cur)) return EXP_Error (EXP_E_SYNTAX, - va - ("Invalid number of arguments to function '%s'.", + va (0, "Invalid number of arguments to function '%s'.", cur->func.func->str)); } else { if (EXP_ContainsCommas (cur)) @@ -374,8 +373,7 @@ EXP_SimplifyTokens (token * chain) if (cur->generic.next->generic.type == TOKEN_OP) if (EXP_DoUnary (cur->generic.next)) return EXP_Error (EXP_E_SYNTAX, - va - ("Unary operator '%s' not followed by a unary operator or numerical value.", + va (0, "Unary operator '%s' not followed by a unary operator or numerical value.", cur->generic.next->op.op->str)); if (optable[i].operands == 1 && cur->generic.next->generic.type == TOKEN_NUM) { @@ -482,14 +480,12 @@ EXP_Validate (token * chain) cur->generic.next->op.op = EXP_FindOpByStr ("neg"); else if (cur->generic.next->op.op->operands == 2) return EXP_Error (EXP_E_SYNTAX, - va - ("Operator '%s' does not follow a number or numerical value.", + va (0, "Operator '%s' does not follow a number or numerical value.", cur->generic.next->op.op->str)); } else if (cur->generic.type == TOKEN_FUNC && cur->generic.next->generic.type != TOKEN_OPAREN) return EXP_Error (EXP_E_SYNTAX, - va - ("Function '%s' called without an argument list.", + va (0, "Function '%s' called without an argument list.", cur->func.func->str)); else if (cur->generic.type == TOKEN_COMMA && @@ -501,7 +497,7 @@ EXP_Validate (token * chain) else if (cur->generic.type == TOKEN_OP && cur->generic.next->generic.type == TOKEN_CPAREN) return EXP_Error (EXP_E_SYNTAX, - va ("Operator '%s' is missing an operand.", + va (0, "Operator '%s' is missing an operand.", cur->op.op->str)); else if (cur->generic.type == TOKEN_NUM && cur->generic.next->generic.type == TOKEN_NUM) diff --git a/libs/gib/gib_builtin.c b/libs/gib/gib_builtin.c index b7f571458..190ec8373 100644 --- a/libs/gib/gib_builtin.c +++ b/libs/gib/gib_builtin.c @@ -823,7 +823,7 @@ GIB_File_Write_f (void) } path = GIB_Argv (1); - QFS_WriteFile (va ("%s/%s", qfs_gamedir->dir.def, path), + QFS_WriteFile (va (0, "%s/%s", qfs_gamedir->dir.def, path), GIB_Argv(2), GIB_Argd(2)->size-1); } diff --git a/libs/gib/gib_classes.c b/libs/gib/gib_classes.c index 88922af50..55087dcdf 100644 --- a/libs/gib/gib_classes.c +++ b/libs/gib/gib_classes.c @@ -612,9 +612,9 @@ static const char *g_gcbs_name; static const char *gcbs_fname (const char *str) { if (g_gcbs_mode == INSTANCE) - return va ("__%s_%s__", g_gcbs_name, str); + return va (0, "__%s_%s__", g_gcbs_name, str); else - return va ("%s::%s", g_gcbs_name, str); + return va (0, "%s::%s", g_gcbs_name, str); } void diff --git a/libs/gib/gib_object.c b/libs/gib/gib_object.c index 3d69b887e..b9fbf66a9 100644 --- a/libs/gib/gib_object.c +++ b/libs/gib/gib_object.c @@ -205,7 +205,7 @@ GIB_Object_Create (const char *classname, qboolean classobj) obj->data = malloc (sizeof (void *) * (class->depth+1)); obj->methods = classobj ? class->class_methods : class->methods; obj->handle = classobj ? 0 : GIB_Handle_New (obj); - obj->handstr = strdup (va ("%lu", obj->handle)); + obj->handstr = strdup (va (0, "%lu", obj->handle)); obj->refs = 1; obj->signals = Hash_NewTable (128, GIB_Signal_Get_Key, GIB_Signal_Free, NULL, 0); diff --git a/libs/gib/gib_parse.c b/libs/gib/gib_parse.c index 0ace51571..c0afaa8d5 100644 --- a/libs/gib/gib_parse.c +++ b/libs/gib/gib_parse.c @@ -333,7 +333,8 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs) return nodes; ERROR: if (c) - GIB_Parse_Error (va ("Could not find match for '%c'.", c), *i + pofs); + GIB_Parse_Error (va (0, "Could not find match for '%c'.", c), + *i + pofs); if (nodes) GIB_Tree_Unref (&nodes); return 0; @@ -496,7 +497,8 @@ GIB_Parse_Embedded (gib_tree_t *token) return lines; ERROR: if (c) - GIB_Parse_Error (va ("Could not find match for '%c'.", c), i + token->start); + GIB_Parse_Error (va (0, "Could not find match for '%c'.", c), + i + token->start); if (lines) GIB_Tree_Unref (&lines); return 0; diff --git a/libs/gib/gib_vars.c b/libs/gib/gib_vars.c index 31d7b3c6a..2d40141e1 100644 --- a/libs/gib/gib_vars.c +++ b/libs/gib/gib_vars.c @@ -210,7 +210,7 @@ GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *ke key->str[i] = 0; if ((var = GIB_Var_Get_Very_Complex (&one, &two, key, n+1+varstartskip, &index2, create))) { if (key->str[n] == '#') - str = va("%u", var->size); + str = va (0, "%u", var->size); else str = var->array[index2].value->str; key->str[i] = c; diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index 82919aad4..ff5d62347 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -122,7 +122,7 @@ Mod_LoadExternalSkin (maliasskindesc_t *pskindesc, char *filename) tex = LoadImage (filename, 1); if (!tex) - tex = LoadImage (va ("textures/%s", ptr + 1), 1); + tex = LoadImage (va (0, "textures/%s", ptr + 1), 1); if (tex) { pskindesc->texnum = GL_LoadTexture (filename, tex->width, tex->height, tex->data, true, false, @@ -130,22 +130,22 @@ Mod_LoadExternalSkin (maliasskindesc_t *pskindesc, char *filename) pskindesc->fb_texnum = 0; - glow = LoadImage (va ("%s_luma", filename), 1); + glow = LoadImage (va (0, "%s_luma", filename), 1); if (!glow) - glow = LoadImage (va ("%s_glow", filename), 1); + glow = LoadImage (va (0, "%s_glow", filename), 1); if (!glow) - glow = LoadImage (va ("textures/%s_luma", ptr + 1), 1); + glow = LoadImage (va (0, "textures/%s_luma", ptr + 1), 1); if (!glow) - glow = LoadImage (va ("textures/%s_glow", ptr + 1), 1); + glow = LoadImage (va (0, "textures/%s_glow", ptr + 1), 1); if (glow) pskindesc->fb_texnum = - GL_LoadTexture (va ("fb_%s", filename), glow->width, + GL_LoadTexture (va (0, "fb_%s", filename), glow->width, glow->height, glow->data, true, true, glow->format > 2 ? glow->format : 1); else if (tex->format < 3) pskindesc->fb_texnum = Mod_Fullbright (tex->data, tex->width, tex->height, - va ("fb_%s", filename)); + va (0, "fb_%s", filename)); } } diff --git a/libs/models/alias/glsl_model_alias.c b/libs/models/alias/glsl_model_alias.c index cb612e962..796b3f346 100644 --- a/libs/models/alias/glsl_model_alias.c +++ b/libs/models/alias/glsl_model_alias.c @@ -104,9 +104,9 @@ glsl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, memcpy (tskin, skin, skinsize); Mod_FloodFillSkin (tskin, w, h); if (group) - name = va ("%s_%i_%i", loadmodel->name, snum, gnum); + name = va (0, "%s_%i_%i", loadmodel->name, snum, gnum); else - name = va ("%s_%i", loadmodel->name, snum); + name = va (0, "%s_%i", loadmodel->name, snum); skindesc->texnum = GLSL_LoadQuakeTexture (name, w, h, tskin); free (tskin); return skin + skinsize; diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 832541071..91ae665d0 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -128,19 +128,28 @@ Vulkan_Mod_LoadSkin (byte *skinpix, int skinsize, int snum, int gnum, tex_t skin_tex = {w, h, tex_palette, 1, vid.palette, tskin + skinsize}; if (Mod_CalcFullbright (tskin, tskin + skinsize, skinsize)) { - skin->glow = Vulkan_LoadTex (ctx, &skin_tex, 1); + skin->glow = Vulkan_LoadTex (ctx, &skin_tex, 1, + va (ctx->va_ctx, "%s:%d:%d:glow", + loadmodel->name, snum, gnum)); Mod_ClearFullbright (tskin, tskin, skinsize); } if (Skin_CalcTopColors (tskin, tskin + skinsize, skinsize)) { - skin->colora = Vulkan_LoadTex (ctx, &skin_tex, 1); + skin->colora = Vulkan_LoadTex (ctx, &skin_tex, 1, + va (ctx->va_ctx, "%s:%d:%d:colora", + loadmodel->name, snum, gnum)); Skin_ClearTopColors (tskin, tskin, skinsize); } if (Skin_CalcBottomColors (tskin, tskin + skinsize, skinsize)) { - skin->colorb = Vulkan_LoadTex (ctx, &skin_tex, 1); + skin->colorb = Vulkan_LoadTex (ctx, &skin_tex, 1, + va (ctx->va_ctx, "%s:%d:%d:colorb", + loadmodel->name, snum, gnum)); Skin_ClearBottomColors (tskin, tskin, skinsize); } skin_tex.data = tskin; - skin->tex = Vulkan_LoadTex (ctx, &skin_tex, 1); + skin->tex = Vulkan_LoadTex (ctx, &skin_tex, 1, + va (ctx->va_ctx, "%s:%d:%d:tex", + loadmodel->name, + snum, gnum)); free (tskin); diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 1d7d04634..878d2c344 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -63,17 +63,17 @@ Mod_LoadAnExternalTexture (char *tname, char *mname) if (rname[0] == '*') rname[0] = '#'; - image = LoadImage (va ("textures/%.*s/%s", (int) strlen (mname + 5) - 4, + image = LoadImage (va (0, "textures/%.*s/%s", (int) strlen (mname + 5) - 4, mname + 5, rname), 1); if (!image) - image = LoadImage (va ("maps/%.*s/%s", (int) strlen (mname + 5) - 4, + image = LoadImage (va (0, "maps/%.*s/%s", (int) strlen (mname + 5) - 4, mname + 5, rname), 1); // if (!image) -// image = LoadImage (va ("textures/bmodels/%s", rname)); +// image = LoadImage (va (0, "textures/bmodels/%s", rname)); if (!image) - image = LoadImage (va ("textures/%s", rname), 1); + image = LoadImage (va (0, "textures/%s", rname), 1); if (!image) - image = LoadImage (va ("maps/%s", rname), 1); + image = LoadImage (va (0, "maps/%s", rname), 1); return image; } @@ -93,23 +93,23 @@ Mod_LoadExternalTextures (model_t *mod, texture_t *tx) base->data, true, false, base->format > 2 ? base->format : 1); - luma = Mod_LoadAnExternalTexture (va ("%s_luma", tx->name), + luma = Mod_LoadAnExternalTexture (va (0, "%s_luma", tx->name), mod->name); if (!luma) - luma = Mod_LoadAnExternalTexture (va ("%s_glow", tx->name), + luma = Mod_LoadAnExternalTexture (va (0, "%s_glow", tx->name), mod->name); gltx->gl_fb_texturenum = 0; if (luma) { gltx->gl_fb_texturenum = - GL_LoadTexture (va ("fb_%s", tx->name), luma->width, + GL_LoadTexture (va (0, "fb_%s", tx->name), luma->width, luma->height, luma->data, true, true, luma->format > 2 ? luma->format : 1); } else if (base->format < 3) { gltx->gl_fb_texturenum = Mod_Fullbright (base->data, base->width, base->height, - va ("fb_%s", tx->name)); + va (0, "fb_%s", tx->name)); } } return external; @@ -133,7 +133,7 @@ gl_Mod_ProcessTexture (texture_t *tx) return; } gltex_t *gltex = tx->render; - name = va ("fb_%s", tx->name); + name = va (0, "fb_%s", tx->name); gltex->gl_fb_texturenum = Mod_Fullbright ((byte *) (tx + 1), tx->width, tx->height, name); gltex->gl_texturenum = diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index c9b336f0f..3d45dd63c 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -356,7 +356,7 @@ Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) return; } - const char *name = va ("fb_%s", tx->name); + const char *name = va (ctx->va_ctx, "fb_%s", tx->name); int size = (tx->width * tx->height * 85) / 64; int fullbright_mark = Hunk_LowMark (); byte *pixels = Hunk_AllocName (size, name); diff --git a/libs/models/iqm/gl_model_iqm.c b/libs/models/iqm/gl_model_iqm.c index 93a1e9992..fc9c50f1a 100644 --- a/libs/models/iqm/gl_model_iqm.c +++ b/libs/models/iqm/gl_model_iqm.c @@ -80,7 +80,7 @@ gl_iqm_load_textures (iqm_t *iqm) for (i = 0; i < iqm->num_meshes; i++) { dstring_copystr (str, iqm->text + iqm->meshes[i].material); QFS_StripExtension (str->str, str->str); - if ((tex = LoadImage (va ("textures/%s", str->str), 1))) + if ((tex = LoadImage (va (0, "textures/%s", str->str), 1))) gl->textures[i] = GL_LoadTexture (str->str, tex->width, tex->height, tex->data, true, false, diff --git a/libs/models/iqm/glsl_model_iqm.c b/libs/models/iqm/glsl_model_iqm.c index 5b37e0fd2..c8a82a112 100644 --- a/libs/models/iqm/glsl_model_iqm.c +++ b/libs/models/iqm/glsl_model_iqm.c @@ -102,12 +102,12 @@ glsl_iqm_load_textures (iqm_t *iqm) for (i = 0; i < iqm->num_meshes; i++) { dstring_copystr (str, iqm->text + iqm->meshes[i].material); QFS_StripExtension (str->str, str->str); - if ((tex = LoadImage (va ("textures/%s", str->str), 1))) + if ((tex = LoadImage (va (0, "textures/%s", str->str), 1))) glsl->textures[i] = GLSL_LoadRGBATexture (str->str, tex->width, tex->height, tex->data); else glsl->textures[i] = GLSL_LoadRGBATexture ("", 2, 2, null_texture); - if ((tex = LoadImage (va ("textures/%s_norm", str->str), 1))) + if ((tex = LoadImage (va (0, "textures/%s_norm", str->str), 1))) glsl->normmaps[i] = GLSL_LoadRGBATexture (str->str, tex->width, tex->height, tex->data); else diff --git a/libs/models/iqm/sw_model_iqm.c b/libs/models/iqm/sw_model_iqm.c index 274a6f0a9..f48867ae1 100644 --- a/libs/models/iqm/sw_model_iqm.c +++ b/libs/models/iqm/sw_model_iqm.c @@ -174,7 +174,7 @@ sw_iqm_load_textures (iqm_t *iqm) continue; dstring_copystr (str, iqm->text + iqm->meshes[i].material); QFS_StripExtension (str->str, str->str); - if ((tex = LoadImage (va ("textures/%s", str->str), 1))) + if ((tex = LoadImage (va (0, "textures/%s", str->str), 1))) tex = sw->skins[i] = convert_tex (tex); else tex = sw->skins[i] = &null_texture; diff --git a/libs/models/skin.c b/libs/models/skin.c index fd561143d..e5a0353f5 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -177,7 +177,7 @@ Skin_SetSkin (skin_t *skin, int cmap, const char *skinname) break; } - file = QFS_FOpenFile (va ("skins/%s.pcx", name)); + file = QFS_FOpenFile (va (0, "skins/%s.pcx", name)); if (!file) { Sys_Printf ("Couldn't load skin %s\n", name); free (name); diff --git a/libs/models/sprite/gl_model_sprite.c b/libs/models/sprite/gl_model_sprite.c index f050e9bdb..1d5d1597c 100644 --- a/libs/models/sprite/gl_model_sprite.c +++ b/libs/models/sprite/gl_model_sprite.c @@ -49,7 +49,7 @@ gl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum) tex_t *targa; const char *name; - targa = LoadImage (name = va ("%s_%i", loadmodel->name, framenum), 1); + targa = LoadImage (name = va (0, "%s_%i", loadmodel->name, framenum), 1); if (targa) { if (targa->format < 4) pspriteframe->gl_texturenum = GL_LoadTexture (name, diff --git a/libs/models/sprite/glsl_model_sprite.c b/libs/models/sprite/glsl_model_sprite.c index bbef94e02..138b3d0d0 100644 --- a/libs/models/sprite/glsl_model_sprite.c +++ b/libs/models/sprite/glsl_model_sprite.c @@ -76,7 +76,7 @@ glsl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum) const char *name; loadmodel->clear = glsl_sprite_clear; - name = va ("%s_%i", loadmodel->name, framenum); + name = va (0, "%s_%i", loadmodel->name, framenum); pspriteframe->gl_texturenum = GLSL_LoadQuakeTexture (name, pspriteframe->width, pspriteframe->height, pspriteframe->pixels); diff --git a/libs/ruamoko/rua_cvar.c b/libs/ruamoko/rua_cvar.c index 18275988e..dbb652817 100644 --- a/libs/ruamoko/rua_cvar.c +++ b/libs/ruamoko/rua_cvar.c @@ -140,7 +140,7 @@ bi_Cvar_SetInteger (progs_t *pr) if (!var) var = Cvar_FindAlias (varname); if (var) - Cvar_Set (var, va ("%d", val)); + Cvar_Set (var, va (0, "%d", val)); } static void @@ -153,7 +153,7 @@ bi_Cvar_SetFloat (progs_t *pr) if (!var) var = Cvar_FindAlias (varname); if (var) - Cvar_Set (var, va ("%g", val)); + Cvar_Set (var, va (0, "%g", val)); } static void @@ -166,7 +166,7 @@ bi_Cvar_SetVector (progs_t *pr) if (!var) var = Cvar_FindAlias (varname); if (var) - Cvar_Set (var, va ("%g %g %g", val[0], val[1], val[2])); + Cvar_Set (var, va (0, "%g %g %g", val[0], val[1], val[2])); } static void diff --git a/libs/ruamoko/rua_qfs.c b/libs/ruamoko/rua_qfs.c index 87b2c5add..4a3eebb59 100644 --- a/libs/ruamoko/rua_qfs.c +++ b/libs/ruamoko/rua_qfs.c @@ -146,7 +146,8 @@ bi_QFS_WriteFile (progs_t *pr) int count = P_INT (pr, 2); check_buffer (pr, buf, count, "QFS_WriteFile"); - QFS_WriteFile (va ("%s/%s", qfs_gamedir->dir.def, filename), buf, count); + QFS_WriteFile (va (0, "%s/%s", qfs_gamedir->dir.def, filename), buf, + count); } static void diff --git a/libs/util/cvar.c b/libs/util/cvar.c index dc4485828..afcfeef33 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -284,7 +284,7 @@ Cvar_Set (cvar_t *var, const char *value) VISIBLE void Cvar_SetValue (cvar_t *var, float value) { - Cvar_Set (var, va ("%g", value)); + Cvar_Set (var, va (0, "%g", value)); } /* @@ -608,7 +608,7 @@ Cvar_CvarList_f (void) showhelp++; } for (var = cvar_vars, i = 0; var; var = var->next, i++) { - flags = va ("%c%c%c%c", + flags = va (0, "%c%c%c%c", var->flags & CVAR_ROM ? 'r' : ' ', var->flags & CVAR_ARCHIVE ? '*' : ' ', var->flags & CVAR_USERINFO ? 'u' : ' ', diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index fe0fc3268..f36b6552e 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -90,6 +90,7 @@ typedef struct pldata_s { // Unparsed property list string unsigned pos; unsigned line; plitem_t *error; + va_ctx_t *va_ctx; } pldata_t; // Ugly defines for fast checking and conversion from char to number @@ -533,7 +534,8 @@ PL_ParseData (pldata_t *pl, int *len) pl->ptr[start + i * 2 + 1]); return str; } - pl->error = PL_NewString (va ("invalid character in data: %02x", c)); + pl->error = PL_NewString (va (pl->va_ctx, + "invalid character in data: %02x", c)); return NULL; } pl->error = PL_NewString ("Reached end of string while parsing data"); @@ -748,7 +750,7 @@ PL_ParsePropertyListItem (pldata_t *pl) } if (pl->ptr[pl->pos] != '=') { - pl->error = PL_NewString (va ("Unexpected character %c (expected '=')", pl->ptr[pl->pos])); + pl->error = PL_NewString (va (pl->va_ctx, "Unexpected character %c (expected '=')", pl->ptr[pl->pos])); PL_Free (key); PL_Free (item); return NULL; @@ -772,7 +774,7 @@ PL_ParsePropertyListItem (pldata_t *pl) if (pl->ptr[pl->pos] == ';') { pl->pos++; } else if (pl->ptr[pl->pos] != '}') { - pl->error = PL_NewString (va ("Unexpected character %c (wanted ';' or '}')", pl->ptr[pl->pos])); + pl->error = PL_NewString (va (pl->va_ctx, "Unexpected character %c (wanted ';' or '}')", pl->ptr[pl->pos])); PL_Free (key); PL_Free (value); PL_Free (item); @@ -822,7 +824,7 @@ PL_ParsePropertyListItem (pldata_t *pl) if (pl->ptr[pl->pos] == ',') { pl->pos++; } else if (pl->ptr[pl->pos] != ')') { - pl->error = PL_NewString (va ("Unexpected character %c (wanted ',' or ')')", pl->ptr[pl->pos])); + pl->error = PL_NewString (va (pl->va_ctx, "Unexpected character %c (wanted ',' or ')')", pl->ptr[pl->pos])); PL_Free (value); PL_Free (item); return NULL; @@ -891,8 +893,10 @@ PL_GetPropertyList (const char *string) pl->end = strlen (string); pl->error = NULL; pl->line = 1; + pl->va_ctx = va_create_context (4); if ((newpl = PL_ParsePropertyListItem (pl))) { + va_destroy_context (pl->va_ctx); free (pl); return newpl; } else { @@ -903,6 +907,7 @@ PL_GetPropertyList (const char *string) } PL_Free (pl->error); } + va_destroy_context (pl->va_ctx); free (pl); return NULL; } @@ -1093,22 +1098,25 @@ VISIBLE void PL_Message (plitem_t *messages, const plitem_t *item, const char *fmt, ...) { va_list args; - dstring_t *string; + dstring_t *va_str; + dstring_t *msg_str; + char *msg; - string = dstring_new (); + va_str = dstring_new (); + msg_str = dstring_new (); va_start (args, fmt); - dvsprintf (string, fmt, args); + dvsprintf (va_str, fmt, args); va_end (args); if (item) { - PL_A_AddObject (messages, - PL_NewString (va ("%d: %s", item->line, string->str))); + msg = dsprintf (msg_str, "%d: %s", item->line, va_str->str); } else { - PL_A_AddObject (messages, - PL_NewString (va ("internal: %s", string->str))); + msg = dsprintf (msg_str, "internal: %s", va_str->str); } - dstring_delete (string); + PL_A_AddObject (messages, PL_NewString (msg)); + dstring_delete (va_str); + dstring_delete (msg_str); } static int diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 039548130..683378904 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -359,7 +359,7 @@ qfs_var_subst (const char *string, hashtab_t *vars) dstring_appendsubstr (new, s, (e - s)); break; } - var = va ("%.*s", (int) (e - s) - 1, s + 1); + var = va (0, "%.*s", (int) (e - s) - 1, s + 1); sub = Hash_Find (vars, var); if (sub) dstring_appendstr (new, sub->val); @@ -370,7 +370,7 @@ qfs_var_subst (const char *string, hashtab_t *vars) s = e; while (qfs_isident (*e)) e++; - var = va ("%.*s", (int) (e - s), s); + var = va (0, "%.*s", (int) (e - s), s); sub = Hash_Find (vars, var); if (sub) dstring_appendstr (new, sub->val); @@ -588,7 +588,7 @@ qfs_build_gamedir (const char **list) gamedir = calloc (1, sizeof (gamedir_t)); path = dstring_newstr (); while (j--) { - const char *name = va ("%s:%s", qfs_game, dir = list[j]); + const char *name = va (0, "%s:%s", qfs_game, dir = list[j]); if (Hash_Find (dirs, name)) continue; gdpl = qfs_find_gamedir (name, dirs); @@ -1661,7 +1661,7 @@ QFS_FilelistAdd (filelist_t *filelist, const char *fname, const char *ext) } str = strdup (fname); - if (ext && (s = strstr(str, va(".%s", ext)))) + if (ext && (s = strstr(str, va (0, ".%s", ext)))) *s = 0; filelist->list[filelist->count++] = str; } @@ -1680,9 +1680,9 @@ qfs_filelistfill_do (filelist_t *list, const searchpath_t *search, const char *c for (i = 0; i < pak->numfiles; i++) { char *name = pak->files[i].name; - if (!fnmatch (va("%s%s*.%s", cp, separator, ext), name, + if (!fnmatch (va (0, "%s%s*.%s", cp, separator, ext), name, FNM_PATHNAME) - || !fnmatch (va("%s%s*.%s.gz", cp, separator, ext), name, + || !fnmatch (va (0, "%s%s*.%s.gz", cp, separator, ext), name, FNM_PATHNAME)) QFS_FilelistAdd (list, name, strip ? ext : 0); } @@ -1690,12 +1690,12 @@ qfs_filelistfill_do (filelist_t *list, const searchpath_t *search, const char *c DIR *dir_ptr; struct dirent *dirent; - dir_ptr = opendir (va ("%s/%s", search->filename, cp)); + dir_ptr = opendir (va (0, "%s/%s", search->filename, cp)); if (!dir_ptr) return; while ((dirent = readdir (dir_ptr))) - if (!fnmatch (va("*.%s", ext), dirent->d_name, 0) - || !fnmatch (va("*.%s.gz", ext), dirent->d_name, 0)) + if (!fnmatch (va (0, "*.%s", ext), dirent->d_name, 0) + || !fnmatch (va (0, "*.%s.gz", ext), dirent->d_name, 0)) QFS_FilelistAdd (list, dirent->d_name, strip ? ext : 0); closedir (dir_ptr); } diff --git a/libs/util/va.c b/libs/util/va.c index dd24c05d1..c4b83aebb 100644 --- a/libs/util/va.c +++ b/libs/util/va.c @@ -40,28 +40,51 @@ #include "QF/dstring.h" #include "QF/va.h" +struct va_ctx_s { + dstring_t **strings; + int num_strings; + int str_index; +}; -/* - va - - does a varargs printf into a temp buffer, so I don't need to have - varargs versions of all text functions. -*/ -VISIBLE char * -va (const char *fmt, ...) +VISIBLE va_ctx_t * +va_create_context (int buffers) { + va_ctx_t *ctx; + + ctx = malloc (sizeof (va_ctx_t) + buffers * sizeof (dstring_t *)); + ctx->strings = (dstring_t **) (ctx + 1); + ctx->num_strings = buffers; + ctx->str_index = 0; + + for (int i = 0; i < buffers; i++) { + ctx->strings[i] = dstring_new (); + } + return ctx; +} + +VISIBLE void +va_destroy_context (va_ctx_t *ctx) +{ + for (int i = 0; i < ctx->num_strings; i++) { + dstring_delete (ctx->strings[i]); + } + free (ctx); +} + +VISIBLE char * +va (va_ctx_t *ctx, const char *fmt, ...) +{ + static va_ctx_t *_ctx; va_list args; - static dstring_t *string[4]; -#define NUM_STRINGS (sizeof (string) / sizeof (string[0])) - static int str_index; dstring_t *dstr; - if (!string[0]) { - for (size_t i = 0; i < NUM_STRINGS; i++) { - string[i] = dstring_new (); + if (!ctx) { + if (!_ctx) { + _ctx = va_create_context (4); } + ctx = _ctx; } - dstr = string[str_index++ % NUM_STRINGS]; + dstr = ctx->strings[ctx->str_index++ % ctx->num_strings]; va_start (args, fmt); dvsprintf (dstr, fmt, args); diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 0572efec0..c3b0ddf68 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -210,7 +210,7 @@ gl_R_ReadPointFile_f (void) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); - name = va ("%s.pts", mapname); + name = va (0, "%s.pts", mapname); free (mapname); f = QFS_FOpenFile (name); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index f8b0e6546..96738d58e 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -152,7 +152,7 @@ gl_SCR_ScreenShot_f (void) // find a file name to save it to if (!QFS_NextFilename (pcxname, - va ("%s/qf", qfs_gamedir->dir.shots), ".tga")) { + va (0, "%s/qf", qfs_gamedir->dir.shots), ".tga")) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); } else { tex_t *tex; diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index 4f69ef8b7..cb3258246 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -131,11 +131,12 @@ gl_R_LoadSkys (const char *skyname) qfglBindTexture (GL_TEXTURE_2D, SKY_TEX + i); - targa = LoadImage (name = va ("env/%s%s", skyname, suf[i]), 1); + targa = LoadImage (name = va (0, "env/%s%s", skyname, suf[i]), 1); if (!targa || targa->format < 3) { // FIXME Can't do PCX right now Sys_MaskPrintf (SYS_DEV, "Couldn't load %s\n", name); // also look in gfx/env, where Darkplaces looks for skies - targa = LoadImage (name = va ("gfx/env/%s%s", skyname, suf[i]), 1); + targa = LoadImage (name = va (0, "gfx/env/%s%s", skyname, + suf[i]), 1); if (!targa) { Sys_MaskPrintf (SYS_DEV, "Couldn't load %s\n", name); gl_skyloaded = false; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 144f8094c..480c647a9 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -1402,7 +1402,7 @@ glsl_R_LoadSkys (const char *sky) //blender envmap // bk rt ft // dn up lt - tex = LoadImage (name = va ("env/%s_map", sky), 1); + tex = LoadImage (name = va (0, "env/%s_map", sky), 1); if (tex && tex->format >= 3 && tex->height * 3 == tex->width * 2 && is_pow2 (tex->height)) { tex_t *sub; @@ -1430,11 +1430,11 @@ glsl_R_LoadSkys (const char *sky) } else { skybox_loaded = true; for (i = 0; i < 6; i++) { - tex = LoadImage (name = va ("env/%s%s", sky, sky_suffix[i]), 1); + tex = LoadImage (name = va (0, "env/%s%s", sky, sky_suffix[i]), 1); if (!tex || tex->format < 3) { // FIXME pcx support Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); // also look in gfx/env, where Darkplaces looks for skies - tex = LoadImage (name = va ("gfx/env/%s%s", sky, + tex = LoadImage (name = va (0, "gfx/env/%s%s", sky, sky_suffix[i]), 1); if (!tex || tex->format < 3) { // FIXME pcx support Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index cb956188c..5a0dcd43a 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -318,7 +318,7 @@ glsl_R_ReadPointFile_f (void) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); - name = va ("%s.pts", mapname); + name = va (0, "%s.pts", mapname); free (mapname); f = QFS_FOpenFile (name); diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index a19d3205a..16063c7c5 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -231,8 +231,8 @@ glsl_SCR_ScreenShot_f (void) dstring_t *name = dstring_new (); // find a file name to save it to - if (!QFS_NextFilename (name, - va ("%s/qf", qfs_gamedir->dir.shots), ".png")) { + if (!QFS_NextFilename (name, va (0, "%s/qf", + qfs_gamedir->dir.shots), ".png")) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file\n"); } else { tex_t *tex; diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index a437fd96e..7fabdd6d2 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -268,7 +268,7 @@ type_name (GLenum type) case GL_FIXED: return "fixed"; } - return va("%x", type); + return va (0, "%x", type); } static void diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 125d8648f..12b7116de 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -159,7 +159,7 @@ SCR_ScreenShot_f (void) // find a file name to save it to if (!QFS_NextFilename (pcxname, - va ("%s/qf", qfs_gamedir->dir.shots), ".pcx")) { + va (0, "%s/qf", qfs_gamedir->dir.shots), ".pcx")) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); } else { // enable direct drawing of console to back buffer diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index d7039504f..c05281863 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -88,7 +88,7 @@ R_ReadPointFile_f (void) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); - name = va ("maps/%s.pts", mapname); + name = va (0, "maps/%s.pts", mapname); free (mapname); f = QFS_FOpenFile (name); diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index ce84cb08c..f1e9e1380 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -103,8 +103,8 @@ sw32_SCR_ScreenShot_f (void) int pcx_len; // find a file name to save it to - if (!QFS_NextFilename (pcxname, - va ("%s/qf", qfs_gamedir->dir.shots), ".pcx")) { + if (!QFS_NextFilename (pcxname, va (0, "%s/qf", + qfs_gamedir->dir.shots), ".pcx")) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); } else { // enable direct drawing of console to back buffer diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index fe2e39601..655467525 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -93,7 +93,7 @@ sw32_R_ReadPointFile_f (void) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); - name = va ("maps/%s.pts", mapname); + name = va (0, "maps/%s.pts", mapname); free (mapname); f = QFS_FOpenFile (name); diff --git a/libs/video/targets/context_sdl.c b/libs/video/targets/context_sdl.c index 7a764553a..21fde4b06 100644 --- a/libs/video/targets/context_sdl.c +++ b/libs/video/targets/context_sdl.c @@ -40,10 +40,10 @@ VID_SetCaption (const char *text) if (text && *text) { char *temp = strdup (text); - SDL_WM_SetCaption (va ("%s: %s", PACKAGE_STRING, temp), NULL); + SDL_WM_SetCaption (va (0, "%s: %s", PACKAGE_STRING, temp), NULL); free (temp); } else { - SDL_WM_SetCaption (va ("%s", PACKAGE_STRING), NULL); + SDL_WM_SetCaption (va (0, "%s", PACKAGE_STRING), NULL); } } diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 7f952aa99..c118feab2 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -566,7 +566,7 @@ X11_CreateWindow (int width, int height) XFree (SizeHints); } // Set window title - X11_SetCaption (va ("%s", PACKAGE_STRING)); + X11_SetCaption (va (0, "%s", PACKAGE_STRING)); // Set icon name XSetIconName (x_disp, x_win, PACKAGE_NAME); diff --git a/libs/video/targets/joy.c b/libs/video/targets/joy.c index 0a209cdfe..da25db1f4 100644 --- a/libs/video/targets/joy.c +++ b/libs/video/targets/joy.c @@ -183,7 +183,7 @@ JOY_Init (void) static void joyamp_f (cvar_t *var) { - Cvar_Set (var, va ("%g", max (0.0001, var->value))); + Cvar_Set (var, va (0, "%g", max (0.0001, var->value))); } typedef struct { diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index b656b5a22..49f33c004 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -90,9 +90,9 @@ VID_GetWindowSize (int def_w, int def_h) { int pnum, conheight; - vid_width = Cvar_Get ("vid_width", va ("%d", def_w), CVAR_NONE, NULL, + vid_width = Cvar_Get ("vid_width", va (0, "%d", def_w), CVAR_NONE, NULL, "screen width"); - vid_height = Cvar_Get ("vid_height", va ("%d", def_h), CVAR_NONE, NULL, + vid_height = Cvar_Get ("vid_height", va (0, "%d", def_h), CVAR_NONE, NULL, "screen height"); vid_aspect = Cvar_Get ("vid_aspect", "4:3", CVAR_ROM, vid_aspect_f, "Physical screen aspect ratio in \"width:height\" format. " @@ -140,7 +140,7 @@ VID_GetWindowSize (int def_w, int def_h) viddef.aspect = ((vid_aspect->vec[0] * viddef.height) / (vid_aspect->vec[1] * viddef.width)); - con_width = Cvar_Get ("con_width", va ("%d", viddef.width), CVAR_NONE, + con_width = Cvar_Get ("con_width", va (0, "%d", viddef.width), CVAR_NONE, NULL, "console effective width (GL only)"); if ((pnum = COM_CheckParm ("-conwidth"))) { if (pnum >= com_argc - 1) @@ -148,20 +148,20 @@ VID_GetWindowSize (int def_w, int def_h) Cvar_Set (con_width, com_argv[pnum + 1]); } // make con_width a multiple of 8 and >= 320 - Cvar_Set (con_width, va ("%d", max (con_width->int_val & ~7, 320))); + Cvar_Set (con_width, va (0, "%d", max (con_width->int_val & ~7, 320))); Cvar_SetFlags (con_width, con_width->flags | CVAR_ROM); viddef.conwidth = con_width->int_val; conheight = (viddef.conwidth * vid_aspect->vec[1]) / vid_aspect->vec[0]; - con_height = Cvar_Get ("con_height", va ("%d", conheight), CVAR_NONE, NULL, - "console effective height (GL only)"); + con_height = Cvar_Get ("con_height", va (0, "%d", conheight), CVAR_NONE, + NULL, "console effective height (GL only)"); if ((pnum = COM_CheckParm ("-conheight"))) { if (pnum >= com_argc - 1) Sys_Error ("VID: -conheight "); Cvar_Set (con_height, com_argv[pnum + 1]); } // make con_height >= 200 - Cvar_Set (con_height, va ("%d", max (con_height->int_val, 200))); + Cvar_Set (con_height, va (0, "%d", max (con_height->int_val, 200))); Cvar_SetFlags (con_height, con_height->flags | CVAR_ROM); viddef.conheight = con_height->int_val; @@ -258,7 +258,7 @@ VID_InitGamma (unsigned char *pal) } gamma = bound (0.1, gamma, 9.9); - vid_gamma = Cvar_Get ("vid_gamma", va ("%f", gamma), CVAR_ARCHIVE, + vid_gamma = Cvar_Get ("vid_gamma", va (0, "%f", gamma), CVAR_ARCHIVE, VID_UpdateGamma, "Gamma correction"); VID_BuildGammaTable (vid_gamma->value); diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 58183ba8f..b29b64b1f 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -182,10 +182,10 @@ VID_SetCaption (const char *text) if (text && *text) { char *temp = strdup (text); - X11_SetCaption (va ("%s: %s", PACKAGE_STRING, temp)); + X11_SetCaption (va (0, "%s: %s", PACKAGE_STRING, temp)); free (temp); } else { - X11_SetCaption (va ("%s", PACKAGE_STRING)); + X11_SetCaption (va (0, "%s", PACKAGE_STRING)); } } diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index cd228b051..d64bed09f 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -53,6 +53,7 @@ #include "QF/cvar.h" #include "QF/set.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/Vulkan/instance.h" @@ -211,6 +212,7 @@ X11_Vulkan_Context (void) ctx->create_window = x11_vulkan_create_window; ctx->create_surface = x11_vulkan_create_surface; ctx->required_extensions = required_extensions; + ctx->va_ctx = va_create_context (4); return ctx; } diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 55a10af26..2b264d850 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -312,7 +312,7 @@ CL_Record_f (void) // start up the map if (c > 2) - Cmd_ExecuteString (va ("map %s", Cmd_Argv (2)), src_command); + Cmd_ExecuteString (va (0, "map %s", Cmd_Argv (2)), src_command); CL_Record (Cmd_Argv (1), track); } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index f93b924d6..9424a670e 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -106,7 +106,7 @@ CL_WriteConfiguration (void) // dedicated servers initialize the host but don't parse and set the // config.cfg cvars if (host_initialized && !isDedicated && cl_writecfg->int_val) { - char *path = va ("%s/config.cfg", qfs_gamedir->dir.def); + char *path = va (0, "%s/config.cfg", qfs_gamedir->dir.def); f = QFS_WOpen (path, 0); if (!f) { Sys_Printf ("Couldn't write config.cfg.\n"); @@ -344,10 +344,11 @@ CL_SignonReply (void) case so_spawn: MSG_WriteByte (&cls.message, clc_stringcmd); - MSG_WriteString (&cls.message, va ("name \"%s\"\n", cl_name->string)); + MSG_WriteString (&cls.message, va (0, "name \"%s\"\n", + cl_name->string)); MSG_WriteByte (&cls.message, clc_stringcmd); MSG_WriteString (&cls.message, - va ("color %i %i\n", (cl_color->int_val) >> 4, + va (0, "color %i %i\n", (cl_color->int_val) >> 4, (cl_color->int_val) & 15)); MSG_WriteByte (&cls.message, clc_stringcmd); MSG_WriteString (&cls.message, "spawn"); @@ -389,7 +390,8 @@ CL_NextDemo (void) } } - Cbuf_InsertText (host_cbuf, va ("playdemo %s\n", cls.demos[cls.demonum])); + Cbuf_InsertText (host_cbuf, va (0, "playdemo %s\n", + cls.demos[cls.demonum])); cls.demonum++; } diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index bf9ce6418..981f72714 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -866,7 +866,7 @@ CL_ParseServerMessage (void) continue; } - SHOWNET (va ("%s(%d)", svc_strings[cmd], cmd)); + SHOWNET (va (0, "%s(%d)", svc_strings[cmd], cmd)); // other commands switch (cmd) { diff --git a/nq/source/host.c b/nq/source/host.c index c852311be..861e9d06b 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -529,7 +529,7 @@ Host_FilterTime (float time) //FIXME not having the framerate cap is nice, but it breaks net play timedifference = (timescale / 72.0) - (realtime - oldrealtime); - if (!cls.timedemo && (timedifference > 0)) + if (0 && !cls.timedemo && (timedifference > 0)) return timedifference; // framerate is too high host_frametime = realtime - oldrealtime; @@ -541,7 +541,7 @@ Host_FilterTime (float time) if (host_framerate->value > 0) host_frametime = host_framerate->value; else // don't allow really long or short frames - host_frametime = bound (0.001, host_frametime, 0.1); + host_frametime = bound (0.000, host_frametime, 0.1); return 0; } @@ -696,7 +696,7 @@ _Host_Frame (float time) if (cls.demo_capture) { tex_t *tex = r_funcs->SCR_CaptureBGR (); - WritePNGqfs (va ("%s/qfmv%06d.png", qfs_gamedir->dir.shots, + WritePNGqfs (va (0, "%s/qfmv%06d.png", qfs_gamedir->dir.shots, cls.demo_capture++), tex->data, tex->width, tex->height); free (tex); diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index ce79f1212..76529838e 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -239,13 +239,13 @@ nice_time (float time) int t = time + 0.5; if (t < 60) { - return va ("%ds", t); + return va (0, "%ds", t); } else if (t < 3600) { - return va ("%dm%02ds", t / 60, t % 60); + return va (0, "%dm%02ds", t / 60, t % 60); } else if (t < 86400) { - return va ("%dh%02dm%02ds", t / 3600, (t / 60) % 60, t % 60); + return va (0, "%dh%02dm%02ds", t / 3600, (t / 60) % 60, t % 60); } else { - return va ("%dd%02dh%02dm%02ds", + return va (0, "%dd%02dh%02dm%02ds", t / 86400, (t / 3600) % 24, (t / 60) % 60, t % 60); } } @@ -279,7 +279,7 @@ Host_Map_f (void) } // check to make sure the level exists - expanded = va ("maps/%s.bsp", Cmd_Argv (1)); + expanded = va (0, "maps/%s.bsp", Cmd_Argv (1)); f = QFS_FOpenFile (expanded); if (!f) { Sys_Printf ("Can't find %s\n", expanded); @@ -395,7 +395,7 @@ spawn_parms_array (void) const char *parm; for (i = 0; i < NUM_SPAWN_PARMS; i++) { - parm = va ("%.9g", svs.clients->spawn_parms[i]); + parm = va (0, "%.9g", svs.clients->spawn_parms[i]); PL_A_AddObject (parms, PL_NewString (parm)); } return parms; @@ -437,15 +437,15 @@ game_dict (void) plitem_t *game = PL_NewDictionary (); PL_D_AddObject (game, "comment", - PL_NewString (va ("%-21s kills:%3i/%3i", cl.levelname, + PL_NewString (va (0, "%-21s kills:%3i/%3i", cl.levelname, cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]))); PL_D_AddObject (game, "spawn_parms", spawn_parms_array ()); PL_D_AddObject (game, "current_skill", - PL_NewString (va ("%d", current_skill))); + PL_NewString (va (0, "%d", current_skill))); PL_D_AddObject (game, "name", PL_NewString (sv.name)); // sv.time is a double, so it gets 17 digits - PL_D_AddObject (game, "time", PL_NewString (va ("%.17g", sv.time))); + PL_D_AddObject (game, "time", PL_NewString (va (0, "%.17g", sv.time))); PL_D_AddObject (game, "lightstyles", lightstyles_array ()); PL_D_AddObject (game, "globals", ED_GlobalsDict (&sv_pr_state)); PL_D_AddObject (game, "entities", entities_array ()); @@ -478,7 +478,7 @@ convert_to_game_dict (script_t *script) // values Script_GetToken (script, 1); skill = (int) (atof (script->token->str) + 0.1); - PL_D_AddObject (game, "current_skill", PL_NewString (va ("%d", skill))); + PL_D_AddObject (game, "current_skill", PL_NewString (va (0, "%d", skill))); Script_GetToken (script, 1); PL_D_AddObject (game, "name", PL_NewString (script->token->str)); @@ -752,7 +752,7 @@ Host_Name_f (void) if (cmd_source == src_command) { if (strcmp (cl_name->string, newName) == 0) return; - Cvar_Set (cl_name, va ("%.15s", newName)); + Cvar_Set (cl_name, va (0, "%.15s", newName)); if (cls.state >= ca_connected) CL_Cmd_ForwardToServer (); return; diff --git a/nq/source/sbar.c b/nq/source/sbar.c index dd8c9adef..fe7e3264a 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1648,8 +1648,8 @@ Sbar_Init (void) Key_KeydestCallback (sbar_keydest_callback); for (i = 0; i < 10; i++) { - sb_nums[0][i] = r_funcs->Draw_PicFromWad (va ("num_%i", i)); - sb_nums[1][i] = r_funcs->Draw_PicFromWad (va ("anum_%i", i)); + sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); + sb_nums[1][i] = r_funcs->Draw_PicFromWad (va (0, "anum_%i", i)); } sb_nums[0][10] = r_funcs->Draw_PicFromWad ("num_minus"); @@ -1676,19 +1676,19 @@ Sbar_Init (void) for (i = 0; i < 5; i++) { sb_weapons[2 + i][0] = - r_funcs->Draw_PicFromWad (va ("inva%i_shotgun", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_shotgun", i + 1)); sb_weapons[2 + i][1] = - r_funcs->Draw_PicFromWad (va ("inva%i_sshotgun", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_sshotgun", i + 1)); sb_weapons[2 + i][2] = - r_funcs->Draw_PicFromWad (va ("inva%i_nailgun", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_nailgun", i + 1)); sb_weapons[2 + i][3] = - r_funcs->Draw_PicFromWad (va ("inva%i_snailgun", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_snailgun", i + 1)); sb_weapons[2 + i][4] = - r_funcs->Draw_PicFromWad (va ("inva%i_rlaunch", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_rlaunch", i + 1)); sb_weapons[2 + i][5] = - r_funcs->Draw_PicFromWad (va ("inva%i_srlaunch", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_srlaunch", i + 1)); sb_weapons[2 + i][6] = - r_funcs->Draw_PicFromWad (va ("inva%i_lightng", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_lightng", i + 1)); } sb_ammo[0] = r_funcs->Draw_PicFromWad ("sb_shells"); @@ -1753,15 +1753,15 @@ Sbar_Init (void) for (i = 0; i < 5; i++) { hsb_weapons[2 + i][0] = - r_funcs->Draw_PicFromWad (va ("inva%i_laser", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_laser", i + 1)); hsb_weapons[2 + i][1] = - r_funcs->Draw_PicFromWad (va ("inva%i_mjolnir", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_mjolnir", i + 1)); hsb_weapons[2 + i][2] = - r_funcs->Draw_PicFromWad (va ("inva%i_gren_prox", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_gren_prox", i + 1)); hsb_weapons[2 + i][3] = - r_funcs->Draw_PicFromWad (va ("inva%i_prox_gren", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_prox_gren", i + 1)); hsb_weapons[2 + i][4] = - r_funcs->Draw_PicFromWad (va ("inva%i_prox", i + 1)); + r_funcs->Draw_PicFromWad (va (0, "inva%i_prox", i + 1)); } hsb_items[0] = r_funcs->Draw_PicFromWad ("sb_wsuit"); diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 70b3d91f4..60ede5d87 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1214,7 +1214,7 @@ SV_SpawnServer (const char *server) *sv_globals.serverflags = svs.serverflags; *sv_globals.time = sv.time; - ent_file = QFS_VOpenFile (va ("maps/%s.ent", server), 0, + ent_file = QFS_VOpenFile (va (0, "maps/%s.ent", server), 0, sv.worldmodel->vpath); if ((buf = QFS_LoadFile (ent_file, 0))) { ED_LoadFromFile (&sv_pr_state, (char *) buf); diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index d5dcc4bb4..0084b3b99 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -1280,7 +1280,7 @@ PF_changelevel (progs_t *pr) svs.changelevel_issued = true; s = P_GSTRING (pr, 0); - Cbuf_AddText (host_cbuf, va ("changelevel %s\n", s)); + Cbuf_AddText (host_cbuf, va (0, "changelevel %s\n", s)); } // entity (entity ent) testentitypos diff --git a/qtv/source/client.c b/qtv/source/client.c index 06955b12f..c55e57bd2 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -177,9 +177,9 @@ cl_prespawn_f (client_t *cl, void *unused) if (buf >= sv->num_signon_buffers) buf = 0; if (buf == sv->num_signon_buffers - 1) - cmd = va ("cmd spawn %i 0\n", cl->server->spawncount); + cmd = va (0, "cmd spawn %i 0\n", cl->server->spawncount); else - cmd = va ("cmd prespawn %i %i\n", cl->server->spawncount, buf + 1); + cmd = va (0, "cmd prespawn %i %i\n", cl->server->spawncount, buf + 1); size = sv->signon_buffer_size[buf] + 1 + strlen (cmd) + 1; msg = MSG_ReliableCheckBlock (&cl->backbuf, size); SZ_Write (msg, sv->signon_buffers[buf], sv->signon_buffer_size[buf]); @@ -1234,7 +1234,7 @@ Client_New (client_t *cl) MSG_WriteByte (&cl->netchan.message, sv->cdtrack); MSG_WriteByte (&cl->netchan.message, svc_stufftext); MSG_WriteString (&cl->netchan.message, - va ("fullserverinfo \"%s\"\n", + va (0, "fullserverinfo \"%s\"\n", Info_MakeString (sv->info, 0))); } diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index a227bfc31..513bb069e 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -237,7 +237,7 @@ qtv_quit_f (void) static void qtv_net_init (void) { - qtv_port = Cvar_Get ("qtv_port", va ("%d", PORT_QTV), 0, 0, + qtv_port = Cvar_Get ("qtv_port", va (0, "%d", PORT_QTV), 0, 0, "udp port to use"); sv_timeout = Cvar_Get ("sv_timeout", "60", 0, 0, "server timeout"); NET_Init (qtv_port->int_val); diff --git a/qtv/source/sbar.c b/qtv/source/sbar.c index 092c85ea1..c6e9ead8a 100644 --- a/qtv/source/sbar.c +++ b/qtv/source/sbar.c @@ -52,7 +52,7 @@ draw_clients (view_t *view) const char *s; char *d; - str = va ("[CL: %3d]", client_count); + str = va (0, "[CL: %3d]", client_count); for (s = str, d = sb->text + view->xrel; *s; s++) *d++ = *s; } @@ -66,7 +66,7 @@ draw_servers (view_t *view) const char *s; char *d; - str = va ("[SV: %2d]", server_count); + str = va (0, "[SV: %2d]", server_count); for (s = str, d = sb->text + view->xrel; *s; s++) *d++ = *s; } diff --git a/qtv/source/server.c b/qtv/source/server.c index c376905d2..00778acea 100644 --- a/qtv/source/server.c +++ b/qtv/source/server.c @@ -452,7 +452,8 @@ sv_new_f (void) sv->qport = qport->int_val; sv->info = Info_ParseString ("", MAX_INFO_STRING, 0); Info_SetValueForStarKey (sv->info, "*ver", - va ("%s QTV %s", QW_VERSION, PACKAGE_VERSION), 0); + va (0, "%s QTV %s", QW_VERSION, PACKAGE_VERSION), + 0); Info_SetValueForStarKey (sv->info, "*qsg_version", QW_QSG_VERSION, 0); Info_SetValueForKey (sv->info, "name", "QTV Proxy", 0); Hash_Add (server_hash, sv); @@ -628,7 +629,7 @@ Server_Broadcast (server_t *sv, int reliable, int all, const byte *msg, void Server_BroadcastCommand (server_t *sv, const char *cmd) { - const char *msg = va ("%c%s", svc_stufftext, cmd); + const char *msg = va (0, "%c%s", svc_stufftext, cmd); int len = strlen (msg) + 1; Server_Broadcast (sv, 1, 1, (const byte *) msg, len); } diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index 1b6ca5841..493aa613a 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -118,7 +118,7 @@ sv_serverdata (server_t *sv, qmsg_t *msg) MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); MSG_WriteString (&sv->netchan.message, - va ("soundlist %i %i", sv->spawncount, 0)); + va (0, "soundlist %i %i", sv->spawncount, 0)); sv->next_run = realtime; } @@ -147,11 +147,11 @@ sv_soundlist (server_t *sv, qmsg_t *msg) if (n) { MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); MSG_WriteString (&sv->netchan.message, - va ("soundlist %d %d", sv->spawncount, n)); + va (0, "soundlist %d %d", sv->spawncount, n)); } else { MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); MSG_WriteString (&sv->netchan.message, - va ("modellist %d %d", sv->spawncount, 0)); + va (0, "modellist %d %d", sv->spawncount, 0)); } sv->next_run = realtime; } @@ -183,11 +183,11 @@ sv_modellist (server_t *sv, qmsg_t *msg) if (n) { MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); MSG_WriteString (&sv->netchan.message, - va ("modellist %d %d", sv->spawncount, n)); + va (0, "modellist %d %d", sv->spawncount, n)); } else { MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); MSG_WriteString (&sv->netchan.message, - va ("prespawn %d 0 0", sv->spawncount)); + va (0, "prespawn %d 0 0", sv->spawncount)); sv->signon = 1; } sv->next_run = realtime; @@ -213,7 +213,7 @@ sv_skins_f (server_t *sv) // to get everything ready at the last miniute before we start getting // actual in-game update messages MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); - MSG_WriteString (&sv->netchan.message, va ("begin %d", sv->spawncount)); + MSG_WriteString (&sv->netchan.message, va (0, "begin %d", sv->spawncount)); sv->next_run = realtime; sv->connected = 2; sv->delta = -1; diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index 7a3dcb186..b2099d22d 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -233,7 +233,7 @@ CL_ChatInfo (int val) val = 0; if (cls.chat != val) { cls.chat = val; - Cbuf_AddText(cl_cbuf, va ("setinfo chat \"%d\"\n", val)); + Cbuf_AddText(cl_cbuf, va (0, "setinfo chat \"%d\"\n", val)); } } diff --git a/qw/source/cl_cvar.c b/qw/source/cl_cvar.c index ebd569ba8..f9e116ae9 100644 --- a/qw/source/cl_cvar.c +++ b/qw/source/cl_cvar.c @@ -53,7 +53,7 @@ Cvar_Info (cvar_t *var) if (cls.state >= ca_connected && !cls.demoplayback) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va ("setinfo \"%s\" \"%s\"\n", var->name, + va (0, "setinfo \"%s\" \"%s\"\n", var->name, var->string)); } } diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 51c709adc..b6e0049e7 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -697,7 +697,7 @@ demo_start_recording (int track) // send server info string MSG_WriteByte (&buf, svc_stufftext); - MSG_WriteString (&buf, va ("fullserverinfo \"%s\"\n", + MSG_WriteString (&buf, va (0, "fullserverinfo \"%s\"\n", Info_MakeString (cl.serverinfo, 0))); // flush packet @@ -803,7 +803,7 @@ demo_start_recording (int track) } MSG_WriteByte (&buf, svc_stufftext); - MSG_WriteString (&buf, va ("cmd spawn %i 0\n", cl.servercount)); + MSG_WriteString (&buf, va (0, "cmd spawn %i 0\n", cl.servercount)); if (buf.cursize) { CL_WriteRecordDemoMessage (&buf, seq++); @@ -863,7 +863,7 @@ demo_start_recording (int track) // get the client to check and download skins // when that is completed, a begin command will be issued MSG_WriteByte (&buf, svc_stufftext); - MSG_WriteString (&buf, va ("skins\n")); + MSG_WriteString (&buf, va (0, "skins\n")); CL_WriteRecordDemoMessage (&buf, seq++); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index e1c305c2b..d9ee07b56 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -321,7 +321,7 @@ CL_CheckForResend (void) connect_time = realtime + t2 - t1; // for retransmit requests - VID_SetCaption (va ("Connecting to %s", cls.servername->str)); + VID_SetCaption (va (0, "Connecting to %s", cls.servername->str)); Sys_Printf ("Connecting to %s...\n", cls.servername->str); Netchan_SendPacket (strlen (getchallenge), (void *) getchallenge, cls.server_addr); @@ -785,7 +785,7 @@ CL_NextDemo (void) } } - Cbuf_InsertText (cl_cbuf, va ("playdemo %s\n", cls.demos[cls.demonum])); + Cbuf_InsertText (cl_cbuf, va (0, "playdemo %s\n", cls.demos[cls.demonum])); cls.demonum++; } @@ -1089,7 +1089,7 @@ CL_Download_f (void) cls.downloadtype = dl_single; MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, va ("download %s\n", Cmd_Argv (1))); + SZ_Print (&cls.netchan.message, va (0, "download %s\n", Cmd_Argv (1))); } else { Sys_Printf ("error downloading %s: %s\n", Cmd_Argv (1), strerror (errno)); @@ -1515,7 +1515,7 @@ Host_WriteConfiguration (void) QFile *f; if (host_initialized && cl_writecfg->int_val) { - char *path = va ("%s/config.cfg", qfs_gamedir->dir.def); + char *path = va (0, "%s/config.cfg", qfs_gamedir->dir.def); f = QFS_WOpen (path, 0); if (!f) { @@ -1700,7 +1700,7 @@ Host_Frame (float time) if (cls.demo_capture) { tex_t *tex = r_funcs->SCR_CaptureBGR (); - WritePNGqfs (va ("%s/qfmv%06d.png", qfs_gamedir->dir.shots, + WritePNGqfs (va (0, "%s/qfmv%06d.png", qfs_gamedir->dir.shots, cls.demo_capture++), tex->data, tex->width, tex->height); free (tex); @@ -1782,7 +1782,7 @@ CL_Autoexec (int phase) Cbuf_AddText (cl_cbuf, "exec autoexec.cfg\n"); } - Cbuf_AddText (cl_cbuf, va ("cmd_warncmd %d\n", cmd_warncmd_val)); + Cbuf_AddText (cl_cbuf, va (0, "cmd_warncmd %d\n", cmd_warncmd_val)); } void diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 2446413d6..21c7dabd2 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -265,7 +265,7 @@ CL_CheckOrDownloadFile (const char *filename) MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va ("download \"%s\"", cls.downloadname->str)); + va (0, "download \"%s\"", cls.downloadname->str)); cls.downloadnumber++; @@ -373,12 +373,13 @@ Model_NextDownload (void) aliashdr_t *ahdr = cl.model_precache[i]->aliashdr; if (!ahdr) ahdr = Cache_Get (&cl.model_precache[i]->cache); - Info_SetValueForKey (cls.userinfo, info_key, va ("%d", ahdr->crc), + Info_SetValueForKey (cls.userinfo, info_key, va (0, "%d", + ahdr->crc), 0); if (!cls.demoplayback) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, va ("setinfo %s %d", info_key, - ahdr->crc)); + SZ_Print (&cls.netchan.message, va (0, "setinfo %s %d", + info_key, ahdr->crc)); } if (!cl.model_precache[i]->aliashdr) Cache_Release (&cl.model_precache[i]->cache); @@ -402,7 +403,7 @@ Model_NextDownload (void) if (!cls.demoplayback) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va (prespawn_name, cl.servercount, + va (0, prespawn_name, cl.servercount, cl.worldmodel->checksum2)); } } @@ -423,7 +424,7 @@ Sound_NextDownload (void) for (; cl.sound_name[cls.downloadnumber][0]; cls.downloadnumber++) { s = cl.sound_name[cls.downloadnumber]; - if (!CL_CheckOrDownloadFile (va ("sound/%s", s))) + if (!CL_CheckOrDownloadFile (va (0, "sound/%s", s))) return; // started a download } @@ -443,7 +444,7 @@ Sound_NextDownload (void) if (!cls.demoplayback) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va (modellist_name, cl.servercount, 0)); + va (0, modellist_name, cl.servercount, 0)); } } @@ -472,7 +473,7 @@ void CL_FinishDownload (void) { Qclose (cls.download); - VID_SetCaption (va ("Connecting to %s", cls.servername->str)); + VID_SetCaption (va (0, "Connecting to %s", cls.servername->str)); // rename the temp file to it's final name if (strcmp (cls.downloadtempname->str, cls.downloadname->str)) { @@ -662,8 +663,8 @@ CL_ParseDownload (void) if (percent != 100) { // request next block if (percent != cls.downloadpercent) - VID_SetCaption (va ("Downloading %s %d%%", cls.downloadname->str, - percent)); + VID_SetCaption (va (0, "Downloading %s %d%%", + cls.downloadname->str, percent)); cls.downloadpercent = percent; MSG_WriteByte (&cls.netchan.message, clc_stringcmd); @@ -842,7 +843,7 @@ CL_ParseServerData (void) if (!cls.demoplayback) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va (soundlist_name, cl.servercount, 0)); + va (0, soundlist_name, cl.servercount, 0)); } // now waiting for downloads, etc @@ -878,7 +879,7 @@ CL_ParseSoundlist (void) if (n && !cls.demoplayback) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va (soundlist_name, cl.servercount, n)); + va (0, soundlist_name, cl.servercount, n)); return; } @@ -929,7 +930,7 @@ CL_ParseModellist (void) if (!cls.demoplayback) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va (modellist_name, cl.servercount, n)); + va (0, modellist_name, cl.servercount, n)); } return; } @@ -1095,7 +1096,8 @@ CL_ProcessUserInfo (int slot, player_info_t *player) while (!(player->name = Info_Key (player->userinfo, "name"))) { if (player->userid) Info_SetValueForKey (player->userinfo, "name", - va ("user-%i [exploit]", player->userid), 1); + va (0, "user-%i [exploit]", + player->userid), 1); else Info_SetValueForKey (player->userinfo, "name", "", 1); } @@ -1248,7 +1250,8 @@ CL_SetStat (int stat, int value) break; case STAT_HEALTH: if (cl_player_health_e->func) - GIB_Event_Callback (cl_player_health_e, 1, va ("%i", value)); + GIB_Event_Callback (cl_player_health_e, 1, + va (0, "%i", value)); if (value <= 0) Team_Dead (); break; @@ -1331,7 +1334,7 @@ CL_ParseServerMessage (void) break; // end of message } - SHOWNET (va ("%s(%d)", svc_strings[cmd], cmd)); + SHOWNET (va (0, "%s(%d)", svc_strings[cmd], cmd)); // other commands switch (cmd) { diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index 21a9afea7..491d12652 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -78,7 +78,8 @@ Skin_NextDownload (void) //XXX Skin_Find (sc); if (noskins->int_val) //XXX FIXME continue; - //XXX if (!CL_CheckOrDownloadFile (va ("skins/%s.pcx", sc->skin->name))) + //XXX if (!CL_CheckOrDownloadFile (va (0, "skins/%s.pcx", + // sc->skin->name))) //XXX return; // started a download } @@ -99,7 +100,7 @@ Skin_NextDownload (void) // get next signon phase MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va ("begin %i", cl.servercount)); + va (0, "begin %i", cl.servercount)); Cache_Report (); // print remaining memory } CL_SetState (ca_active); diff --git a/qw/source/cl_slist.c b/qw/source/cl_slist.c index 4b5ea16b8..ded6445c8 100644 --- a/qw/source/cl_slist.c +++ b/qw/source/cl_slist.c @@ -575,7 +575,7 @@ MSL_ParseServerList (const char *msl_data) unsigned int msl_ptr; for (msl_ptr = 0; msl_ptr < strlen (msl_data); msl_ptr = msl_ptr + 6) { - slist = SL_Add (slist, va ("%i.%i.%i.%i:%i", + slist = SL_Add (slist, va (0, "%i.%i.%i.%i:%i", (byte) msl_data[msl_ptr], (byte) msl_data[msl_ptr+1], (byte) msl_data[msl_ptr+2], diff --git a/qw/source/crudefile.c b/qw/source/crudefile.c index 3050a6efc..a02bc81bc 100644 --- a/qw/source/crudefile.c +++ b/qw/source/crudefile.c @@ -150,7 +150,7 @@ CF_BuildQuota (void) cf_cursize = 0; while ((i = readdir (dir))) { - cf_cursize += CF_GetFileSize (va ("%s/%s", path->str, i->d_name)); + cf_cursize += CF_GetFileSize (va (0, "%s/%s", path->str, i->d_name)); } closedir (dir); } diff --git a/qw/source/locs.c b/qw/source/locs.c index c30080dd7..ab92ec4c2 100644 --- a/qw/source/locs.c +++ b/qw/source/locs.c @@ -136,7 +136,7 @@ locs_load (const char *filename) vec3_t loc; QFile *file; - tmp = va ("maps/%s", filename); + tmp = va (0, "maps/%s", filename); file = QFS_FOpenFile (tmp); if (!file) { Sys_Printf ("Couldn't load %s\n", tmp); @@ -196,7 +196,7 @@ locs_save (const char *filename, qboolean gz) if (gz) { if (strcmp (QFS_FileExtension (filename), ".gz") != 0) - filename = va ("%s.gz", filename); + filename = va (0, "%s.gz", filename); locfd = QFS_Open (filename, "z9w+"); } else locfd = QFS_Open (filename, "w+"); diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 3a6e97778..a7b3ab415 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -1605,7 +1605,7 @@ draw_net (view_t *view) int ping = cl.players[cl.playernum].ping; ping = bound (0, ping, 999); - draw_string (view, 0, 0, va ("%3d ms ", ping)); + draw_string (view, 0, 0, va (0, "%3d ms ", ping)); } if (hud_ping->int_val && hud_pl->int_val) @@ -1615,7 +1615,7 @@ draw_net (view_t *view) int lost = CL_CalcNet (); lost = bound (0, lost, 999); - draw_string (view, 56, 0, va ("%3d pl", lost)); + draw_string (view, 56, 0, va (0, "%3d pl", lost)); } } @@ -1950,8 +1950,8 @@ Sbar_Init (void) Key_KeydestCallback (sbar_keydest_callback); for (i = 0; i < 10; i++) { - sb_nums[0][i] = r_funcs->Draw_PicFromWad (va ("num_%i", i)); - sb_nums[1][i] = r_funcs->Draw_PicFromWad (va ("anum_%i", i)); + sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); + sb_nums[1][i] = r_funcs->Draw_PicFromWad (va (0, "anum_%i", i)); } sb_nums[0][10] = r_funcs->Draw_PicFromWad ("num_minus"); @@ -1977,19 +1977,26 @@ Sbar_Init (void) sb_weapons[1][6] = r_funcs->Draw_PicFromWad ("inv2_lightng"); for (i = 0; i < 5; i++) { - sb_weapons[2 + i][0] = r_funcs->Draw_PicFromWad (va ("inva%i_shotgun", + sb_weapons[2 + i][0] = r_funcs->Draw_PicFromWad (va (0, + "inva%i_shotgun", i + 1)); - sb_weapons[2 + i][1] = r_funcs->Draw_PicFromWad (va ("inva%i_sshotgun", + sb_weapons[2 + i][1] = r_funcs->Draw_PicFromWad (va (0, + "inva%i_sshotgun", i + 1)); - sb_weapons[2 + i][2] = r_funcs->Draw_PicFromWad (va ("inva%i_nailgun", + sb_weapons[2 + i][2] = r_funcs->Draw_PicFromWad (va (0, + "inva%i_nailgun", i + 1)); - sb_weapons[2 + i][3] = r_funcs->Draw_PicFromWad (va ("inva%i_snailgun", + sb_weapons[2 + i][3] = r_funcs->Draw_PicFromWad (va (0, + "inva%i_snailgun", i + 1)); - sb_weapons[2 + i][4] = r_funcs->Draw_PicFromWad (va ("inva%i_rlaunch", + sb_weapons[2 + i][4] = r_funcs->Draw_PicFromWad (va (0, + "inva%i_rlaunch", i + 1)); - sb_weapons[2 + i][5] = r_funcs->Draw_PicFromWad (va ("inva%i_srlaunch", + sb_weapons[2 + i][5] = r_funcs->Draw_PicFromWad (va (0, + "inva%i_srlaunch", i + 1)); - sb_weapons[2 + i][6] = r_funcs->Draw_PicFromWad (va ("inva%i_lightng", + sb_weapons[2 + i][6] = r_funcs->Draw_PicFromWad (va (0, + "inva%i_lightng", i + 1)); } diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index aef14bea6..22604df69 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -250,7 +250,7 @@ SV_Fraglogfile_f (void) } name = dstring_new (); if (!QFS_NextFilename (name, - va ("%s/frag_", qfs_gamedir->dir.def), ".log")) { + va (0, "%s/frag_", qfs_gamedir->dir.def), ".log")) { SV_Printf ("Can't open any logfiles.\n"); sv_fraglogfile = NULL; } else { @@ -396,29 +396,29 @@ nice_time (float time) #if 0 //FIXME ditch or cvar? if (t < 60) { - return va ("%ds", t); + return va (0, "%ds", t); } else if (t < 600) { - return va ("%dm%02ds", t / 60, t % 60); + return va (0, "%dm%02ds", t / 60, t % 60); } else if (t < 3600) { - return va ("%dm", t / 60); + return va (0, "%dm", t / 60); } else if (t < 36000) { t /= 60; - return va ("%dh%02dm", t / 60, t % 60); + return va (0, "%dh%02dm", t / 60, t % 60); } else if (t < 86400) { - return va ("%dh", t / 3600); + return va (0, "%dh", t / 3600); } else { t /= 3600; - return va ("%dd%02dh", t / 24, t % 24); + return va (0, "%dd%02dh", t / 24, t % 24); } #endif if (t < 60) { - return va ("%ds", t); + return va (0, "%ds", t); } else if (t < 3600) { - return va ("%dm%02ds", t / 60, t % 60); + return va (0, "%dm%02ds", t / 60, t % 60); } else if (t < 86400) { - return va ("%dh%02dm%02ds", t / 3600, (t / 60) % 60, t % 60); + return va (0, "%dh%02dm%02ds", t / 3600, (t / 60) % 60, t % 60); } else { - return va ("%dd%02dh%02dm%02ds", + return va (0, "%dd%02dh%02dm%02ds", t / 86400, (t / 3600) % 24, (t / 60) % 60, t % 60); } } @@ -742,15 +742,15 @@ SV_Ban_f (void) if (argc > argr) { reason = Cmd_Args (argr); SV_BroadcastPrintf (PRINT_HIGH, "Admin Banned user %s %s: %s\n", - cl->name, mins ? va ("for %.1f minutes", mins) + cl->name, mins ? va (0, "for %.1f minutes", mins) : "permanently", reason); } else { SV_BroadcastPrintf (PRINT_HIGH, "Admin Banned user %s %s\n", - cl->name, mins ? va ("for %.1f minutes", mins) + cl->name, mins ? va (0, "for %.1f minutes", mins) : "permanently"); } SV_DropClient (cl); - Cmd_ExecuteString (va ("addip %s %f", + Cmd_ExecuteString (va (0, "addip %s %f", NET_BaseAdrToString (cl->netchan.remote_address), mins), src_command); } @@ -812,7 +812,7 @@ SV_ConSay (const char *prefix, client_t *client) dbuf = SVR_WriteBegin (dem_all, 0, strlen (text->str) + 7); MSG_WriteByte (dbuf, svc_print); MSG_WriteByte (dbuf, PRINT_HIGH); - MSG_WriteString (dbuf, va ("%s\n", text->str)); + MSG_WriteString (dbuf, va (0, "%s\n", text->str)); MSG_WriteByte (dbuf, svc_print); MSG_WriteByte (dbuf, PRINT_CHAT); MSG_WriteString (dbuf, ""); @@ -1136,7 +1136,7 @@ SV_Snap (int uid) cl->uploadfn = dstring_new (); if (!QFS_NextFilename (cl->uploadfn, - va ("%s/snap/%d-", qfs_gamedir->dir.def, uid), + va (0, "%s/snap/%d-", qfs_gamedir->dir.def, uid), ".pcx")) { SV_Printf ("Snap: Couldn't create a file, clean some out.\n"); dstring_delete (cl->uploadfn); diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index cc53372a8..b13135c93 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -191,7 +191,7 @@ SV_Stop (int reason) sv_redirected = RD_NONE; // onrecord script is called always // from the console - Cmd_TokenizeString (va ("script %s \"%s\" \"%s\" \"%s\" %s", + Cmd_TokenizeString (va (0, "script %s \"%s\" \"%s\" \"%s\" %s", sv_onrecordfinish->string, demo.path->str, serverdemo->string, path, p != NULL ? p + 1 : "")); @@ -454,7 +454,7 @@ SV_Record (char *name) // send server info string MSG_WriteByte (&buf, svc_stufftext); - MSG_WriteString (&buf, va ("fullserverinfo \"%s\"\n", + MSG_WriteString (&buf, va (0, "fullserverinfo \"%s\"\n", Info_MakeString (svs.info, 0))); // flush packet @@ -524,7 +524,7 @@ SV_Record (char *name) } MSG_WriteByte (&buf, svc_stufftext); - MSG_WriteString (&buf, va ("cmd spawn %i 0\n", svs.spawncount)); + MSG_WriteString (&buf, va (0, "cmd spawn %i 0\n", svs.spawncount)); if (buf.cursize) { SV_WriteRecordDemoMessage (&buf); @@ -576,7 +576,7 @@ SV_Record (char *name) // get the client to check and download skins // when that is completed, a begin command will be issued MSG_WriteByte (&buf, svc_stufftext); - MSG_WriteString (&buf, va ("skins\n")); + MSG_WriteString (&buf, va (0, "skins\n")); SV_WriteRecordDemoMessage (&buf); @@ -797,7 +797,7 @@ Demo_Init (void) sv_demoPings = Cvar_Get ("sv_demoPings", "3", CVAR_NONE, 0, "FIXME"); sv_demoNoVis = Cvar_Get ("sv_demoNoVis", "1", CVAR_NONE, 0, "FIXME"); sv_demoUseCache = Cvar_Get ("sv_demoUseCache", "0", CVAR_NONE, 0, "FIXME"); - sv_demoCacheSize = Cvar_Get ("sv_demoCacheSize", va ("%d", size / 1024), + sv_demoCacheSize = Cvar_Get ("sv_demoCacheSize", va (0, "%d", size / 1024), CVAR_ROM, 0, "FIXME"); sv_demoMaxSize = Cvar_Get ("sv_demoMaxSize", "20480", CVAR_NONE, 0, "FIXME"); diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index d5b6d0d2c..6e8b7bae5 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -374,7 +374,7 @@ SV_SpawnServer (const char *server) SV_LoadProgs (); SV_FreeAllEdictLeafs (); SV_SetupUserCommands (); - Info_SetValueForStarKey (svs.info, "*progs", va ("%i", sv_pr_state.crc), + Info_SetValueForStarKey (svs.info, "*progs", va (0, "%i", sv_pr_state.crc), !sv_highchars->int_val); // leave slots at start for only clients @@ -437,7 +437,7 @@ SV_SpawnServer (const char *server) // load and spawn all other entities *sv_globals.time = sv.time; - ent_file = QFS_VOpenFile (va ("maps/%s.ent", server), 0, + ent_file = QFS_VOpenFile (va (0, "maps/%s.ent", server), 0, sv.worldmodel->vpath); if ((buf = QFS_LoadFile (ent_file, 0))) { ED_LoadFromFile (&sv_pr_state, (char *) buf); diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index ffc1a5db4..0156d689a 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -368,7 +368,7 @@ SV_DropClient (client_t *drop) // Trigger GIB event if (sv_client_disconnect_e->func) GIB_Event_Callback (sv_client_disconnect_e, 1, - va ("%u", drop->userid)); + va (0, "%u", drop->userid)); } int @@ -1459,7 +1459,7 @@ SV_AddIP_f (void) bantime / 60); else strncpy (timestr, "permanently", sizeof (timestr)); - text = va ("You are %s %s\n%s", + text = va (0, "You are %s %s\n%s", typestr, timestr, type == ft_ban ? "" : "\nReconnecting won't help..."); MSG_ReliableWrite_Begin (&cl->backbuf, svc_centerprint, @@ -1884,7 +1884,7 @@ SV_CheckVars (void) Info_SetValueForKey (svs.info, "needpass", "", !sv_highchars->int_val); else - Info_SetValueForKey (svs.info, "needpass", va ("%i", v), + Info_SetValueForKey (svs.info, "needpass", va (0, "%i", v), !sv_highchars->int_val); } diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 49f0cc332..7298dc74a 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -1411,7 +1411,7 @@ PF_changelevel (progs_t *pr) last_spawncount = svs.spawncount; s = P_GSTRING (pr, 0); - Cbuf_AddText (sv_cbuf, va ("map %s\n", s)); + Cbuf_AddText (sv_cbuf, va (0, "map %s\n", s)); } /* @@ -1460,13 +1460,13 @@ PF_logfrag (progs_t *pr) snprintf(buf, sizeof(buf), "%d", u2); - GIB_Event_Callback (sv_frag_e, 4, type1, va ("%d", u1), type2, buf); + GIB_Event_Callback (sv_frag_e, 4, type1, va (0, "%d", u1), type2, buf); } if (e1 < 1 || e1 > MAX_CLIENTS || e2 < 1 || e2 > MAX_CLIENTS) return; - s = va ("\\%s\\%s\\\n", svs.clients[e1 - 1].name, + s = va (0, "\\%s\\%s\\\n", svs.clients[e1 - 1].name, svs.clients[e2 - 1].name); SZ_Print (&svs.log[svs.logsequence & 1], s); @@ -1511,7 +1511,7 @@ PF_infokey (progs_t *pr) else if (!strcmp (key, "ping")) { int ping = SV_CalcPing (&svs.clients[e1 - 1]); - value = va ("%d", ping); + value = va (0, "%d", ping); } else value = Info_ValueForKey (svs.clients[e1 - 1].userinfo, key); } else @@ -1862,7 +1862,7 @@ PF_SV_FreeClient (progs_t *pr) cl->state = cs_free; //if (sv_client_disconnect_e->func) - // GIB_Event_Callback (sv_client_disconnect_e, 2, va ("%u", cl->userid), + // GIB_Event_Callback (sv_client_disconnect_e, 2, va (0, "%u", cl->userid), // "server"); } diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index 010c8a5a6..ea4d533f4 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -451,7 +451,7 @@ PF_log (progs_t *pr) char *text; QFile *file; - name = va ("%s/%s.log", qfs_gamedir->dir.def, P_GSTRING (pr, 0)); + name = va (0, "%s/%s.log", qfs_gamedir->dir.def, P_GSTRING (pr, 0)); file = QFS_Open (name, "a"); text = PF_VarString (pr, 2); diff --git a/qw/source/sv_qtv.c b/qw/source/sv_qtv.c index 6804a51e3..366c2d687 100644 --- a/qw/source/sv_qtv.c +++ b/qw/source/sv_qtv.c @@ -194,9 +194,9 @@ qtv_prespawn_f (sv_qtv_t *proxy) buf = 0; if (buf == sv.num_signon_buffers - 1) - command = va ("cmd spawn %i 0\n", svs.spawncount); + command = va (0, "cmd spawn %i 0\n", svs.spawncount); else - command = va ("cmd prespawn %i %i\n", svs.spawncount, buf + 1); + command = va (0, "cmd prespawn %i %i\n", svs.spawncount, buf + 1); size = (3 + sv.signon_buffer_size[buf]) + (1 + strlen (command) + 1); msg = MSG_ReliableCheckBlock (&proxy->backbuf, size); @@ -534,7 +534,7 @@ SV_qtvChanging (void) int i, len; const char *msg; - msg = va ("%cchanging", qtv_stringcmd); + msg = va (0, "%cchanging", qtv_stringcmd); len = strlen (msg) + 1; for (i = 0; i < MAX_PROXIES; i++) { proxy = proxies + i; @@ -555,7 +555,7 @@ SV_qtvReconnect (void) int i, len; const char *msg; - msg = va ("%creconnect", qtv_stringcmd); + msg = va (0, "%creconnect", qtv_stringcmd); len = strlen (msg) + 1; for (i = 0; i < MAX_PROXIES; i++) { proxy = proxies + i; diff --git a/qw/source/sv_sbar.c b/qw/source/sv_sbar.c index 012a38835..12aa9115a 100644 --- a/qw/source/sv_sbar.c +++ b/qw/source/sv_sbar.c @@ -55,7 +55,7 @@ draw_cpu (view_t *view) cpu = (svs.stats.latched_active + svs.stats.latched_idle); cpu = 100 * svs.stats.latched_active / cpu; - cpu_str = va ("[CPU: %3d%%]", (int) cpu); + cpu_str = va (0, "[CPU: %3d%%]", (int) cpu); for (s = cpu_str, d = sb->text + view->xrel; *s; s++) *d++ = *s; if (cpu > 70.0) { @@ -74,7 +74,7 @@ draw_rec (view_t *view) const char *s; char *d; - str = va ("[REC: %d]", SVR_NumRecorders ()); + str = va (0, "[REC: %d]", SVR_NumRecorders ()); for (s = str, d = sb->text + view->xrel; *s; s++) *d++ = *s; } diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index f9c44f48f..3fba2c17f 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -141,7 +141,7 @@ SV_WriteWorldVars (netchan_t *netchan) // send server info string MSG_WriteByte (&netchan->message, svc_stufftext); MSG_WriteString (&netchan->message, - va ("fullserverinfo \"%s\"\n", + va (0, "fullserverinfo \"%s\"\n", Info_MakeString (svs.info, 0))); } @@ -194,7 +194,7 @@ SV_New_f (void *unused) // Trigger GIB connection event if (sv_client_connect_e->func) GIB_Event_Callback (sv_client_connect_e, 1, - va ("%u", host_client->userid)); + va (0, "%u", host_client->userid)); } void @@ -351,9 +351,9 @@ SV_PreSpawn_f (void *unused) host_client->prespawned = true; if (buf == sv.num_signon_buffers - 1) - command = va ("cmd spawn %i 0\n", svs.spawncount); + command = va (0, "cmd spawn %i 0\n", svs.spawncount); else - command = va ("cmd prespawn %i %i\n", svs.spawncount, buf + 1); + command = va (0, "cmd prespawn %i %i\n", svs.spawncount, buf + 1); size = sv.signon_buffer_size[buf] + 1 + strlen (command) + 1; @@ -605,7 +605,7 @@ SV_Begin_f (void *unused) // Trigger GIB events if (sv_client_spawn_e->func) - GIB_Event_Callback (sv_client_spawn_e, 1, va ("%u", + GIB_Event_Callback (sv_client_spawn_e, 1, va (0, "%u", host_client->userid)); } @@ -787,7 +787,7 @@ SV_BeginDownload_f (void *unused) MSG_ReliableWrite_Short (&host_client->backbuf, DL_HTTP); MSG_ReliableWrite_Byte (&host_client->backbuf, 0); MSG_ReliableWrite_String (&host_client->backbuf, - va ("%s/%s", sv_http_url_base->string, + va (0, "%s/%s", sv_http_url_base->string, ren ? qfs_foundfile.realname : name)); MSG_ReliableWrite_String (&host_client->backbuf, ren ? qfs_foundfile.realname : ""); @@ -914,7 +914,7 @@ SV_Say (qboolean team) dsprintf (text, fmt, host_client->name); if (sv_chat_e->func) - GIB_Event_Callback (sv_chat_e, 2, va ("%i", host_client->userid), p, + GIB_Event_Callback (sv_chat_e, 2, va (0, "%i", host_client->userid), p, type); dstring_appendstr (text, p); @@ -1201,7 +1201,7 @@ SV_SetUserinfo (client_t *client, const char *key, const char *value) // trigger a GIB event if (sv_setinfo_e->func) - GIB_Event_Callback (sv_setinfo_e, 4, va("%d", client->userid), + GIB_Event_Callback (sv_setinfo_e, 4, va (0, "%d", client->userid), key, oldvalue, value); if (sv_funcs.UserInfoChanged) { diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index c5df33cd3..b8158cbdb 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -424,7 +424,7 @@ Locs_Init (void) static const char * Team_F_Version (char *args) { - return va ("say %s", PACKAGE_STRING); + return va (0, "say %s", PACKAGE_STRING); } static const char * @@ -446,7 +446,7 @@ Team_F_Skins (char *args) if (l == 0) { //XXXtotalfb = Skin_FbPercent (0); totalfb = 0; - return va ("say Player models have %f%% brightness\n" + return va (0, "say Player models have %f%% brightness\n" "say Average percent fullbright for all loaded skins is " "%d.%d%%", allfb * 100, totalfb / 10, totalfb % 10); } @@ -455,8 +455,8 @@ Team_F_Skins (char *args) totalfb = 0; if (totalfb >= 0) - return va ("say \"Skin %s is %d.%d%% fullbright\"", args, totalfb / 10, - totalfb % 10); + return va (0, "say \"Skin %s is %d.%d%% fullbright\"", + args, totalfb / 10, totalfb % 10); else return ("say \"Skin not currently loaded.\""); } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index f493e8528..dbafed33f 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -102,7 +102,7 @@ load_file (progs_t *pr, const char *name, off_t *_size) file = open_file (name, &size); if (!file) { - file = open_file (va ("%s.gz", name), &size); + file = open_file (va (0, "%s.gz", name), &size); if (!file) { return 0; } diff --git a/ruamoko/qwaq/builtins/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c index 0a8070825..f74b429cf 100644 --- a/ruamoko/qwaq/builtins/qwaq.c +++ b/ruamoko/qwaq/builtins/qwaq.c @@ -79,7 +79,7 @@ load_file (progs_t *pr, const char *name, off_t *_size) file = open_file (name, &size); if (!file) { - file = open_file (va ("%s.gz", name), &size); + file = open_file (va (0, "%s.gz", name), &size); if (!file) { return 0; } diff --git a/tools/qfbsp/source/brush.c b/tools/qfbsp/source/brush.c index 97ddbfd4d..e0b05f2d9 100644 --- a/tools/qfbsp/source/brush.c +++ b/tools/qfbsp/source/brush.c @@ -347,7 +347,7 @@ CreateBrushFaces (void) GetVectorForKey (FoundEntity, "origin", offset); SetKeyValue (CurrentEntity, "origin", - va ("%g %g %g", VectorExpand (offset))); + va (0, "%g %g %g", VectorExpand (offset))); } for (i = 0; i < numbrushfaces; i++) { diff --git a/tools/qfbsp/source/map.c b/tools/qfbsp/source/map.c index d8bb6c893..870fb7c07 100644 --- a/tools/qfbsp/source/map.c +++ b/tools/qfbsp/source/map.c @@ -620,7 +620,7 @@ WriteEntitiesToString (void) dstring_appendstr (buf, "{\n"); for (ep = entities[i].epairs; ep; ep = ep->next) { - dstring_appendstr (buf, va ("\"%s\" \"%s\"\n", + dstring_appendstr (buf, va (0, "\"%s\" \"%s\"\n", ep->key, ep->value)); } dstring_appendstr (buf, "}\n"); diff --git a/tools/qfbsp/source/readbsp.c b/tools/qfbsp/source/readbsp.c index caf69255b..c554755c5 100644 --- a/tools/qfbsp/source/readbsp.c +++ b/tools/qfbsp/source/readbsp.c @@ -359,13 +359,13 @@ unique_name (wad_t *wad, const char *name) do { strncpy (uname, name, MIPTEXNAME); uname[(MIPTEXNAME - 1)] = 0; - tag = va ("~%x", i++); + tag = va (0, "~%x", i++); if (strlen (uname) + strlen (tag) <= (MIPTEXNAME - 1)) strcat (uname, tag); else strcpy (uname + (MIPTEXNAME - 1) - strlen (tag), tag); } while (wad_find_lump (wad, uname)); - return va ("%s", uname); // just to make a safe returnable that doesn't + return va (0, "%s", uname); // just to make a safe returnable that doesn't // need to be freed } diff --git a/tools/qfbsp/source/writebsp.c b/tools/qfbsp/source/writebsp.c index 94f679313..dd7d0fa99 100644 --- a/tools/qfbsp/source/writebsp.c +++ b/tools/qfbsp/source/writebsp.c @@ -301,7 +301,7 @@ TEX_InitFromWad (const char *path) wad = wad_open (path); #ifdef HAVE_ZLIB if (!wad) - wad = wad_open (path = va ("%s.gz", path)); + wad = wad_open (path = va (0, "%s.gz", path)); #endif if (!wad) return -1; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 9203e9fbf..ddef199fa 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -258,7 +258,8 @@ emit_static_instances (const char *classname) } instances_struct[1].type = array_type (&type_pointer, data.num_instances + 1); - instances_def = emit_structure (va ("_OBJ_STATIC_INSTANCES_%s", classname), + instances_def = emit_structure (va (0, "_OBJ_STATIC_INSTANCES_%s", + classname), 's', instances_struct, 0, &data, 0, sc_static); free (data.instances); @@ -538,16 +539,16 @@ get_class_name (class_type_t *class_type, int pretty) if (pretty) return class_type->c.class->name; else - return va ("%s_", class_type->c.class->name); + return va (0, "%s_", class_type->c.class->name); case ct_category: if (pretty) - return va ("%s (%s)", class_type->c.category->class->name, + return va (0, "%s (%s)", class_type->c.category->class->name, class_type->c.category->name); else - return va ("%s_%s", class_type->c.category->class->name, + return va (0, "%s_%s", class_type->c.category->class->name, class_type->c.category->name); case ct_protocol: - return va ("<%s>", class_type->c.protocol->name); + return va (0, "<%s>", class_type->c.protocol->name); } return "???"; } @@ -561,13 +562,13 @@ class_symbol (class_type_t *class_type, int external) switch (class_type->type) { case ct_category: - name = va ("_OBJ_CATEGORY_%s_%s", + name = va (0, "_OBJ_CATEGORY_%s_%s", class_type->c.category->class->name, class_type->c.category->name); type = &type_category; break; case ct_class: - name = va ("_OBJ_CLASS_%s", class_type->c.class->name); + name = va (0, "_OBJ_CLASS_%s", class_type->c.class->name); type = &type_class; break; case ct_protocol: @@ -710,7 +711,8 @@ begin_category (category_t *category) EMIT_STRING (space, pr_category->class_name, class->name); EMIT_DEF (space, pr_category->protocols, emit_protocol_list (category->protocols, - va ("%s_%s", class->name, category->name))); + va (0, "%s_%s", class->name, + category->name))); } typedef struct { @@ -786,7 +788,7 @@ emit_ivars (symtab_t *ivars, const char *name) } ivar_list_struct[1].type = array_type (&type_ivar, ivar_data.count); - def = emit_structure (va ("_OBJ_INSTANCE_VARIABLES_%s", name), 's', + def = emit_structure (va (0, "_OBJ_INSTANCE_VARIABLES_%s", name), 's', ivar_list_struct, 0, &ivar_data, 0, sc_static); dstring_delete (ivar_data.encoding); @@ -803,7 +805,7 @@ begin_class (class_t *class) def_t *def; defspace_t *space; - sym = make_symbol (va ("_OBJ_METACLASS_%s", class->name), + sym = make_symbol (va (0, "_OBJ_METACLASS_%s", class->name), &type_class, pr.far_data, sc_static); meta_def = sym->s.def; meta_def->initialized = meta_def->constant = meta_def->nosave = 1; @@ -872,15 +874,15 @@ emit_class_ref (const char *class_name) def_t *ref_def; def_t *name_def; - ref_sym = make_symbol (va (".obj_class_ref_%s", class_name), &type_pointer, - pr.far_data, sc_static); + ref_sym = make_symbol (va (0, ".obj_class_ref_%s", class_name), + &type_pointer, pr.far_data, sc_static); if (!ref_sym->table) symtab_addsymbol (pr.symtab, ref_sym); ref_def = ref_sym->s.def; if (ref_def->initialized) return; ref_def->initialized = ref_def->constant = ref_def->nosave = 1; - name_sym = make_symbol (va (".obj_class_name_%s", class_name), + name_sym = make_symbol (va (0, ".obj_class_name_%s", class_name), &type_pointer, pr.far_data, sc_extern); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); @@ -896,7 +898,7 @@ emit_class_name (const char *class_name) symbol_t *name_sym; def_t *name_def; - name_sym = make_symbol (va (".obj_class_name_%s", class_name), + name_sym = make_symbol (va (0, ".obj_class_name_%s", class_name), &type_pointer, pr.far_data, sc_global); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); @@ -916,9 +918,9 @@ emit_category_ref (const char *class_name, const char *category_name) def_t *ref_def; def_t *name_def; - ref_sym = make_symbol (va (".obj_category_ref_%s_%s", - class_name, category_name), - &type_pointer, pr.far_data, sc_static); + ref_sym = make_symbol (va (0, ".obj_category_ref_%s_%s", + class_name, category_name), + &type_pointer, pr.far_data, sc_static); if (!ref_sym->table) symtab_addsymbol (pr.symtab, ref_sym); ref_def = ref_sym->s.def; @@ -926,9 +928,9 @@ emit_category_ref (const char *class_name, const char *category_name) return; ref_def->initialized = ref_def->constant = 1; ref_def->nosave = 1; - name_sym = make_symbol (va (".obj_category_name_%s_%s", - class_name, category_name), - &type_pointer, pr.far_data, sc_extern); + name_sym = make_symbol (va (0, ".obj_category_name_%s_%s", + class_name, category_name), + &type_pointer, pr.far_data, sc_extern); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); name_def = name_sym->s.def; @@ -943,7 +945,7 @@ emit_category_name (const char *class_name, const char *category_name) symbol_t *name_sym; def_t *name_def; - name_sym = make_symbol (va (".obj_category_name_%s_%s", + name_sym = make_symbol (va (0, ".obj_category_name_%s_%s", class_name, category_name), &type_pointer, pr.far_data, sc_global); if (!name_sym->table) @@ -1374,9 +1376,8 @@ class_pointer_symbol (class_t *class) class_type.c.class = class; - sym = make_symbol (va ("_OBJ_CLASS_POINTER_%s", class->name), - &type_Class, - pr.near_data, sc_static); + sym = make_symbol (va (0, "_OBJ_CLASS_POINTER_%s", class->name), + &type_Class, pr.near_data, sc_static); if (!sym->table) symtab_addsymbol (pr.symtab, sym); def = sym->s.def; @@ -1716,7 +1717,7 @@ emit_protocol (protocol_t *protocol) pr_protocol_t *proto; defspace_t *space; - proto_def = make_symbol (va ("_OBJ_PROTOCOL_%s", protocol->name), + proto_def = make_symbol (va (0, "_OBJ_PROTOCOL_%s", protocol->name), &type_protocol, pr.far_data, sc_static)->s.def; if (proto_def->initialized) return proto_def; @@ -1728,7 +1729,7 @@ emit_protocol (protocol_t *protocol) EMIT_STRING (space, proto->protocol_name, protocol->name); EMIT_DEF (space, proto->protocol_list, emit_protocol_list (protocol->protocols, - va ("PROTOCOL_%s", protocol->name))); + va (0, "PROTOCOL_%s", protocol->name))); EMIT_DEF (space, proto->instance_methods, emit_method_descriptions (protocol->methods, protocol->name, 1)); EMIT_DEF (space, proto->class_methods, @@ -1786,7 +1787,7 @@ emit_protocol_list (protocollist_t *protocols, const char *name) if (!protocols) return 0; proto_list_struct[2].type = array_type (&type_pointer, protocols->count); - return emit_structure (va ("_OBJ_PROTOCOLS_%s", name), 's', + return emit_structure (va (0, "_OBJ_PROTOCOLS_%s", name), 's', proto_list_struct, 0, protocols, 0, sc_static); } diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index d3299a0ab..7ac1d0822 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -187,7 +187,7 @@ alias_def (def_t *def, type_t *type, int offset) return alias; } ALLOC (16384, def_t, defs, alias); - alias->name = save_string (va ("[%s:%d]", def->name, offset)); + alias->name = save_string (va (0, "[%s:%d]", def->name, offset)); alias->return_addr = __builtin_return_address (0); alias->offset = offset; alias->offset_reloc = 1; @@ -222,7 +222,7 @@ temp_def (type_t *type) temp->offset = defspace_alloc_aligned_loc (space, size, alignment); *space->def_tail = temp; space->def_tail = &temp->next; - temp->name = save_string (va (".tmp%d", current_func->temp_num++)); + temp->name = save_string (va (0, ".tmp%d", current_func->temp_num++)); } temp->return_addr = __builtin_return_address (0); temp->type = type; @@ -424,7 +424,7 @@ init_vector_components (symbol_t *vector_sym, int is_field) symbol_t *sym; const char *name; - name = va ("%s_%s", vector_sym->name, fields[i]); + name = va (0, "%s_%s", vector_sym->name, fields[i]); sym = symtab_lookup (current_symtab, name); if (sym) { if (sym->table == current_symtab) { diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 4db09bc39..84bae7aa2 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -180,13 +180,13 @@ print_bool (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) for ( ; i < tl_count; i++) dasprintf (dstr, "%*st%s\n", indent, "", i, - i == count ? va ("", + i == count ? va (0, "", bool->true_list->size - count) : ""); for ( ; i < fl_count; i++) dasprintf (dstr, "%*s%sf\n", indent, "", - i == count ? va ("", + i == count ? va (0, "", bool->false_list->size - count) : "", i); @@ -449,22 +449,23 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) switch (e->e.value->lltype) { case ev_string: - label = va ("\\\"%s\\\"", quote_string (e->e.value->v.string_val)); + label = va (0, "\\\"%s\\\"", + quote_string (e->e.value->v.string_val)); break; case ev_double: - label = va ("f %g", e->e.value->v.double_val); + label = va (0, "f %g", e->e.value->v.double_val); break; case ev_float: - label = va ("f %g", e->e.value->v.float_val); + label = va (0, "f %g", e->e.value->v.float_val); break; case ev_vector: - label = va ("'%g %g %g'", + label = va (0, "'%g %g %g'", e->e.value->v.vector_val[0], e->e.value->v.vector_val[1], e->e.value->v.vector_val[2]); break; case ev_quat: - label = va ("'%g %g %g %g'", + label = va (0, "'%g %g %g %g'", e->e.value->v.quaternion_val[0], e->e.value->v.quaternion_val[1], e->e.value->v.quaternion_val[2], @@ -477,32 +478,32 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) print_type_str (type_str, type); } if (e->e.value->v.pointer.def) - label = va ("(*%s)[%d]<%s>", + label = va (0, "(*%s)[%d]<%s>", type ? type_str->str : "???", e->e.value->v.pointer.val, e->e.value->v.pointer.def->name); else - label = va ("(*%s)[%d]", + label = va (0, "(*%s)[%d]", type ? type_str->str : "???", e->e.value->v.pointer.val); break; case ev_field: - label = va ("field %d", e->e.value->v.pointer.val); + label = va (0, "field %d", e->e.value->v.pointer.val); break; case ev_entity: - label = va ("ent %d", e->e.value->v.integer_val); + label = va (0, "ent %d", e->e.value->v.integer_val); break; case ev_func: - label = va ("func %d", e->e.value->v.integer_val); + label = va (0, "func %d", e->e.value->v.integer_val); break; case ev_integer: - label = va ("i %d", e->e.value->v.integer_val); + label = va (0, "i %d", e->e.value->v.integer_val); break; case ev_uinteger: - label = va ("u %u", e->e.value->v.uinteger_val); + label = va (0, "u %u", e->e.value->v.uinteger_val); break; case ev_short: - label = va ("s %d", e->e.value->v.short_val); + label = va (0, "s %d", e->e.value->v.short_val); break; case ev_void: label = ""; diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 0320ebb2d..ecfbcc01f 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -114,7 +114,7 @@ print_flow_node_dag (dstring_t *dstr, flowgraph_t *graph, flownode_t *node, int level) { if (node->dag) - print_dag (dstr, node->dag, va ("%d (%d)", node->id, node->dfn)); + print_dag (dstr, node->dag, va (0, "%d (%d)", node->id, node->dfn)); else print_flow_node (dstr, graph, node, level); } diff --git a/tools/qfcc/source/dot_type.c b/tools/qfcc/source/dot_type.c index ae58552b4..522fa91fb 100644 --- a/tools/qfcc/source/dot_type.c +++ b/tools/qfcc/source/dot_type.c @@ -175,7 +175,7 @@ print_struct (dstring_t *dstr, type_t *t, int level, int id) continue; } val = sym->s.offset; - port = va (" port=\"f%d\"", pnum++); + port = va (0, " port=\"f%d\"", pnum++); } dasprintf (dstr, "%*s%s%d\n", indent + 4, "", diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index fe166885c..317e70c03 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -93,20 +93,20 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) if (string < 0 || (pr_uint_t) string >= pr->progs->numstrings) { str = "invalid string offset"; - comment = va (" %d %s", string, str); + comment = va (0, " %d %s", string, str); } else { str = quote_string (pr->pr_strings + G_INT (pr, offset)); - comment = va (" %d \"%s\"", string, str); + comment = va (0, " %d \"%s\"", string, str); } break; case ev_float: - comment = va (" %g", G_FLOAT (pr, offset)); + comment = va (0, " %g", G_FLOAT (pr, offset)); break; case ev_double: - comment = va (" %.17g", G_DOUBLE (pr, offset)); + comment = va (0, " %.17g", G_DOUBLE (pr, offset)); break; case ev_vector: - comment = va (" '%g %g %g'", + comment = va (0, " '%g %g %g'", G_VECTOR (pr, offset)[0], G_VECTOR (pr, offset)[1], G_VECTOR (pr, offset)[2]); @@ -114,7 +114,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) case ev_entity: break; case ev_field: - comment = va (" %x", G_INT (pr, offset)); + comment = va (0, " %x", G_INT (pr, offset)); break; case ev_func: { @@ -123,26 +123,26 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) if (func < pr->progs->numfunctions) { start = pr->pr_functions[func].first_statement; if (start > 0) - comment = va (" %d @ %x", func, start); + comment = va (0, " %d @ %x", func, start); else - comment = va (" %d = #%d", func, -start); + comment = va (0, " %d = #%d", func, -start); } else { - comment = va (" %d = illegal function", func); + comment = va (0, " %d = illegal function", func); } } break; case ev_pointer: - comment = va (" %x", G_INT (pr, offset)); + comment = va (0, " %x", G_INT (pr, offset)); break; case ev_quat: - comment = va (" '%g %g %g %g'", + comment = va (0, " '%g %g %g %g'", G_QUAT (pr, offset)[0], G_QUAT (pr, offset)[1], G_QUAT (pr, offset)[2], G_QUAT (pr, offset)[3]); break; case ev_integer: - comment = va (" %d", G_INT (pr, offset)); + comment = va (0, " %d", G_INT (pr, offset)); break; case ev_short: break; @@ -255,9 +255,9 @@ dump_functions (progs_t *pr) start = func->first_statement; if (start > 0) - comment = va (" @ %x", start); + comment = va (0, " @ %x", start); else - comment = va (" = #%d", -start); + comment = va (0, " = #%d", -start); printf ("%-5d %s%s: %d (", i, name, comment, func->numparms); if (func->numparms < 0) @@ -537,7 +537,7 @@ dump_qfo_types (qfo_t *qfo, int base_address) continue; } if (type->meta < 0 || type->meta >= NUM_META) - meta = va ("invalid meta: %d", type->meta); + meta = va (0, "invalid meta: %d", type->meta); else meta = ty_meta_names[type->meta]; printf ("%-5x %-9s %-20s", type_ptr + base_address, meta, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index a8684a83b..f86e9dece 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -479,7 +479,7 @@ new_label_name (void) const char *fname = current_func->sym->name; const char *lname; - lname = save_string (va ("$%s_%d", fname, lnum)); + lname = save_string (va (0, "$%s_%d", fname, lnum)); return lname; } @@ -543,7 +543,8 @@ named_label_expr (symbol_t *label) return sym->s.expr; } l = new_label_expr (); - l->e.label.name = save_string (va ("%s_%s", l->e.label.name, label->name)); + l->e.label.name = save_string (va (0, "%s_%s", l->e.label.name, + label->name)); l->e.label.symbol = label; label->sy_type = sy_expr; label->s.expr = l; @@ -1268,7 +1269,7 @@ new_ret_expr (type_t *type) expr_t * new_param_expr (type_t *type, int num) { - return param_expr (va (".param_%d", num), type); + return param_expr (va (0, ".param_%d", num), type); } expr_t * diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 86f6dc9d5..3a1bb54c1 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1607,7 +1607,7 @@ flow_build_graph (function_t *func) flow_make_edges (graph); flow_build_dfst (graph); if (options.block_dot.flow) - dump_dot (va ("flow-%d", pass), graph, dump_dot_flow); + dump_dot (va (0, "flow-%d", pass), graph, dump_dot_flow); pass++; } while (flow_remove_unreachable_nodes (graph)); flow_find_predecessors (graph); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 940abf11e..4e7ef61f3 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -249,7 +249,7 @@ get_function (const char *name, const type_t *type, int overload, int create) name = save_string (name); - full_name = save_string (va ("%s|%s", name, encode_params (type))); + full_name = save_string (va (0, "%s|%s", name, encode_params (type))); func = Hash_Find (overloaded_functions, full_name); if (func) { @@ -382,7 +382,7 @@ find_function (expr_t *fexpr, expr_t *params) dummy.type = find_type (&type); qsort (funcs, func_count, sizeof (void *), func_compare); - dummy.full_name = save_string (va ("%s|%s", fexpr->e.symbol->name, + dummy.full_name = save_string (va (0, "%s|%s", fexpr->e.symbol->name, encode_params (&type))); dummy_p = bsearch (&dummy_p, funcs, func_count, sizeof (void *), func_compare); @@ -526,7 +526,7 @@ build_scope (symbol_t *fsym, symtab_t *parent) if (args) { while (i < MAX_PARMS) { - param = new_symbol_type (va (".par%d", i), &type_param); + param = new_symbol_type (va (0, ".par%d", i), &type_param); initialize_def (param, 0, symtab->space, sc_param); i++; } diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 2f6e4a565..eb5aeb2bb 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -1106,7 +1106,7 @@ linker_add_lib (const char *libname) if (strncmp (libname, "-l", 2) == 0) { while (path) { - path_name = va ("%s/lib%s.a", path->path, libname + 2); + path_name = va (0, "%s/lib%s.a", path->path, libname + 2); pack = pack_open (path_name); if (pack) break; diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 1c461af85..a1d05ce9d 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -609,7 +609,7 @@ emit_methods (methodlist_t *methods, const char *name, int instance) methods->instance = instance; methods_struct[2].type = array_type (&type_method, count); - return emit_structure (va ("_OBJ_%s_METHODS_%s", type, name), 's', + return emit_structure (va (0, "_OBJ_%s_METHODS_%s", type, name), 's', methods_struct, 0, methods, 0, sc_static); } @@ -677,7 +677,7 @@ emit_method_descriptions (methodlist_t *methods, const char *name, methods->instance = instance; method_list_struct[1].type = array_type (&type_method_description, count); - return emit_structure (va ("_OBJ_%s_METHODS_%s", type, name), 's', + return emit_structure (va (0, "_OBJ_%s_METHODS_%s", type, name), 's', method_list_struct, 0, methods, 0, sc_static); } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 76a5219d4..a8e6ae5fb 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -455,7 +455,7 @@ qfo_write (qfo_t *qfo, const char *filename) file = Qopen (filename, options.gzip ? "wbz9" : "wb"); if (!file) { - perror (va ("failed to open %s for writing", filename)); + perror (va (0, "failed to open %s for writing", filename)); return -1; } @@ -1168,7 +1168,7 @@ qfo_to_progs (qfo_t *qfo, int *size) if (options.verbosity >= 0) { const char *big_function = ""; if (big_func) - big_function = va (" (%s)", strings + qfo->funcs[big_func].name); + big_function = va (0, " (%s)", strings + qfo->funcs[big_func].name); printf ("%6i strofs\n", progs->numstrings); printf ("%6i statements\n", progs->numstatements); printf ("%6i functions\n", progs->numfunctions); diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 758e388a3..09989684c 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -341,7 +341,7 @@ DecodeArgs (int argc, char **argv) } break; case 'l': // lib file - add_file (va ("-l%s", NORMALIZE (optarg))); + add_file (va (0, "-l%s", NORMALIZE (optarg))); break; case 'L': linker_add_path (NORMALIZE (optarg)); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index b08884b92..32161c4b7 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -741,7 +741,8 @@ struct_def } else if (is_anonymous_struct ($1)) { // anonymous struct/union // type->name always begins with "tag " - $1.sym = new_symbol (va (".anonymous.%s", $1.type->name + 4)); + $1.sym = new_symbol (va (0, ".anonymous.%s", + $1.type->name + 4)); $1.sym->type = $1.type; $1.sym->sy_type = sy_var; $1.sym->visibility = vis_anonymous; @@ -1924,7 +1925,8 @@ ivar_decl if (is_anonymous_struct ($1)) { // anonymous struct/union // type->name always begins with "tag " - $1.sym = new_symbol (va (".anonymous.%s", $1.type->name + 4)); + $1.sym = new_symbol (va (0, ".anonymous.%s", + $1.type->name + 4)); $1.sym->type = $1.type; $1.sym->sy_type = sy_var; $1.sym->visibility = vis_anonymous; diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index e6c3b7946..1a8406186 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -411,7 +411,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) } } if (options.frames_files) { - write_frame_macros (va ("%s.frame", file_basename (file, 0))); + write_frame_macros (va (0, "%s.frame", file_basename (file, 0))); } if (!err) { qfo_t *qfo; @@ -777,7 +777,7 @@ progs_src_compile (void) if (compile_file (qc_filename->str)) return 1; if (options.frames_files) { - write_frame_macros (va ("%s.frame", + write_frame_macros (va (0, "%s.frame", file_basename (qc_filename->str, 0))); } diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 03d09123d..54b98b62a 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -183,7 +183,7 @@ load_file (progs_t *pr, const char *name, off_t *_size) file = open_file (name, &size); if (!file) { - file = open_file (va ("%s.gz", name), &size); + file = open_file (va (0, "%s.gz", name), &size); if (!file) return 0; } @@ -233,7 +233,7 @@ init_qf (void) { Sys_Init (); - Cvar_Get ("pr_debug", va ("%d", 1+verbosity), 0, 0, ""); + Cvar_Get ("pr_debug", va (0, "%d", 1+verbosity), 0, 0, ""); Cvar_Get ("pr_source_path", source_path, 0, 0, ""); PR_Init_Cvars (); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 2383dcc84..0743c5c40 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -97,14 +97,14 @@ tempop_string (operand_t *tmpop) { tempop_t *tempop = &tmpop->o.tempop; if (tempop->alias) { - return va ("", + return va (0, "", pr_type_name[tempop->type->type], tmpop, tempop->users, tempop->alias, tempop->offset, tempop->alias->o.tempop.users); } - return va ("", pr_type_name[tempop->type->type], + return va (0, "", pr_type_name[tempop->type->type], tmpop, tempop->users); } @@ -119,47 +119,47 @@ operand_string (operand_t *op) case op_value: switch (op->o.value->lltype) { case ev_string: - return va ("\"%s\"", + return va (0, "\"%s\"", quote_string (op->o.value->v.string_val)); case ev_double: - return va ("%g", op->o.value->v.double_val); + return va (0, "%g", op->o.value->v.double_val); case ev_float: - return va ("%g", op->o.value->v.float_val); + return va (0, "%g", op->o.value->v.float_val); case ev_vector: - return va ("'%g %g %g'", + return va (0, "'%g %g %g'", op->o.value->v.vector_val[0], op->o.value->v.vector_val[1], op->o.value->v.vector_val[2]); case ev_quat: - return va ("'%g %g %g %g'", + return va (0, "'%g %g %g %g'", op->o.value->v.quaternion_val[0], op->o.value->v.quaternion_val[1], op->o.value->v.quaternion_val[2], op->o.value->v.quaternion_val[3]); case ev_pointer: if (op->o.value->v.pointer.def) { - return va ("ptr %s+%d", + return va (0, "ptr %s+%d", op->o.value->v.pointer.def->name, op->o.value->v.pointer.val); } else if(op->o.value->v.pointer.tempop) { operand_t *tempop = op->o.value->v.pointer.tempop; - return va ("ptr %s+%d", tempop_string (tempop), + return va (0, "ptr %s+%d", tempop_string (tempop), op->o.value->v.pointer.val); } else { - return va ("ptr %d", op->o.value->v.pointer.val); + return va (0, "ptr %d", op->o.value->v.pointer.val); } case ev_field: - return va ("field %d", op->o.value->v.pointer.val); + return va (0, "field %d", op->o.value->v.pointer.val); case ev_entity: - return va ("ent %d", op->o.value->v.integer_val); + return va (0, "ent %d", op->o.value->v.integer_val); case ev_func: - return va ("func %d", op->o.value->v.integer_val); + return va (0, "func %d", op->o.value->v.integer_val); case ev_integer: - return va ("int %d", op->o.value->v.integer_val); + return va (0, "int %d", op->o.value->v.integer_val); case ev_uinteger: - return va ("uint %u", op->o.value->v.uinteger_val); + return va (0, "uint %u", op->o.value->v.uinteger_val); case ev_short: - return va ("short %d", op->o.value->v.short_val); + return va (0, "short %d", op->o.value->v.short_val); case ev_void: return "(void)"; case ev_invalid: @@ -177,10 +177,11 @@ operand_string (operand_t *op) const char *alias = operand_string (op->o.alias); char *buf = alloca (strlen (alias) + 1); strcpy (buf, alias); - return va ("alias(%s,%s)", pr_type_name[op->type->type], buf); + return va (0, "alias(%s,%s)", pr_type_name[op->type->type], + buf); } case op_nil: - return va ("nil"); + return va (0, "nil"); } return ("??"); } @@ -1036,7 +1037,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) } } } - opcode = va ("<%sCALL%d>", pref, count); + opcode = va (0, "<%sCALL%d>", pref, count); s = new_statement (st_func, opcode, call); sblock = statement_subexpr (sblock, func, &s->opa); s->opb = arguments[0]; @@ -2076,11 +2077,11 @@ make_statements (expr_t *e) do { did_something = thread_jumps (sblock); if (options.block_dot.thread) - dump_dot (va ("thread-%d", pass), sblock, dump_dot_sblock); + dump_dot (va (0, "thread-%d", pass), sblock, dump_dot_sblock); did_something |= remove_dead_blocks (sblock); sblock = merge_blocks (sblock); if (options.block_dot.dead) - dump_dot (va ("dead-%d", pass), sblock, dump_dot_sblock); + dump_dot (va (0, "dead-%d", pass), sblock, dump_dot_sblock); pass++; } while (did_something); check_final_block (sblock); diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index c42935dd2..ef9bd7389 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -70,13 +70,13 @@ find_tag (ty_meta_e meta, symbol_t *tag, type_t *type) symbol_t *sym; if (tag) { - tag_name = va ("tag %s", tag->name); + tag_name = va (0, "tag %s", tag->name); } else { const char *path = GETSTR (pr.source_file); const char *file = strrchr (path, '/'); if (!file++) file = path; - tag_name = va ("tag .%s.%d", file, pr.source_line); + tag_name = va (0, "tag .%s.%d", file, pr.source_line); } sym = symtab_lookup (current_symtab, tag_name); if (sym) { @@ -355,7 +355,7 @@ emit_structure (const char *name, int su, struct_def_t *defs, type_t *type, for (i = 0, field_sym = type->t.symtab->symbols; field_sym; i++, field_sym = field_sym->next) { field_def.type = field_sym->type; - field_def.name = save_string (va ("%s.%s", name, field_sym->name)); + field_def.name = save_string (va (0, "%s.%s", name, field_sym->name)); field_def.space = struct_def->space; field_def.offset = struct_def->offset + field_sym->s.offset; if (!defs[i].emit) { diff --git a/tools/qflight/source/entities.c b/tools/qflight/source/entities.c index d2bd2711c..1383004df 100644 --- a/tools/qflight/source/entities.c +++ b/tools/qflight/source/entities.c @@ -125,7 +125,8 @@ MatchTargets (void) // set the style on the source ent for switchable lights if (entities[j].style) { entities[i].style = entities[j].style; - SetKeyValue (&entities[i], "style", va ("%i", entities[i].style)); + SetKeyValue (&entities[i], "style", va (0, "%i", + entities[i].style)); } if (entities[i].spotcone >= 0) { diff --git a/tools/qflight/source/qflight.c b/tools/qflight/source/qflight.c index 4d2acfb73..75b9941d7 100644 --- a/tools/qflight/source/qflight.c +++ b/tools/qflight/source/qflight.c @@ -150,7 +150,7 @@ FindFaceOffsets (void) surfaceorgs = (vec3_t *) calloc (bsp->numfaces, sizeof (vec3_t)); for (i = 1; i < bsp->nummodels; i++) { - ent = FindEntityWithKeyPair ("model", name = va ("*%d", i)); + ent = FindEntityWithKeyPair ("model", name = va (0, "*%d", i)); VectorZero (org); if (!ent) Sys_Error ("FindFaceOffsets: Couldn't find entity for model %s.\n", diff --git a/tools/wad/script.c b/tools/wad/script.c index b4eaeeeff..e93efe0ac 100644 --- a/tools/wad/script.c +++ b/tools/wad/script.c @@ -159,7 +159,7 @@ write_file (void) QFile *file; const char *name; - name = va ("%s/%s.lmp", destfile.str, lumpname->str); + name = va (0, "%s/%s.lmp", destfile.str, lumpname->str); if (!(file = Qopen (name, "wb"))) Sys_Error ("couldn't open %s. %s", name, strerror(errno)); Qwrite (file, lumpbuffer, lump_p - lumpbuffer); From eeda04e3c95475b25308841dde1bcb77415d5b85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 31 Jan 2021 19:58:55 +0900 Subject: [PATCH 1289/3664] [vulkan] Name most resources This makes debugging with renderdoc and validation messages much easier (no more "what buffer is that?"). --- include/QF/Vulkan/debug.h | 115 ++++++++++++++++++ include/QF/Vulkan/funclist.h | 19 +++ include/QF/Vulkan/qf_texture.h | 3 +- include/QF/Vulkan/scrap.h | 5 +- include/QF/Vulkan/staging.h | 3 +- libs/models/alias/vulkan_model_alias.c | 20 ++- libs/models/brush/vulkan_model_brush.c | 28 ++++- libs/video/renderer/vulkan/device.c | 4 +- libs/video/renderer/vulkan/scrap.c | 13 +- libs/video/renderer/vulkan/staging.c | 17 ++- libs/video/renderer/vulkan/vkparse.c | 3 + libs/video/renderer/vulkan/vulkan_alias.c | 25 +++- libs/video/renderer/vulkan/vulkan_bsp.c | 42 ++++++- libs/video/renderer/vulkan/vulkan_draw.c | 5 +- libs/video/renderer/vulkan/vulkan_texture.c | 19 ++- .../video/renderer/vulkan/vulkan_vid_common.c | 16 ++- 16 files changed, 310 insertions(+), 27 deletions(-) create mode 100644 include/QF/Vulkan/debug.h diff --git a/include/QF/Vulkan/debug.h b/include/QF/Vulkan/debug.h new file mode 100644 index 000000000..3250d5aca --- /dev/null +++ b/include/QF/Vulkan/debug.h @@ -0,0 +1,115 @@ +#ifndef __QF_Vulkan_debug_h +#define __QF_Vulkan_debug_h + +#define QFV_duCmdBeginLabel(device, cmd, name...)\ + do { \ + qfv_devfuncs_t *dfunc = device->funcs; \ + if (dfunc->vkCmdBeginDebugUtilsLabelEXT) { \ + VkDebugUtilsLabelEXT label = { \ + VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, name \ + }; \ + dfunc->vkCmdBeginDebugUtilsLabelEXT (cmd, &label); \ + } \ + } while (0) + +#define QFV_duCmdEndLabel(device, cmd) \ + do { \ + qfv_devfuncs_t *dfunc = device->funcs; \ + if (dfunc->vkCmdEndDebugUtilsLabelEXT) { \ + dfunc->vkCmdEndDebugUtilsLabelEXT (cmd); \ + } \ + } while (0) + +#define QFV_duCmdInsertLabel(device, cmd, name...) \ + do { \ + qfv_devfuncs_t *dfunc = device->funcs; \ + if (dfunc->vkCmdInsertDebugUtilsLabelEXT) { \ + VkDebugUtilsLabelEXT label = { \ + VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, name \ + }; \ + dfunc->vkCmdInsertDebugUtilsLabelEXT (cmd, &label); \ + } \ + } while (0) + +#define QFV_duCreateMessenger(inst, severity, type, callback, data, messenger)\ + do { \ + if (inst->funcs->vkCreateDebugUtilsMessengerEXT) { \ + VkDebugUtilsMessengerCreateInfoEXT createInfo = { \ + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, 0, 0,\ + severity, type, callback, data \ + }; \ + inst->funcs->vkCreateDebugUtilsMessengerEXT (inst, &createInfo, 0,\ + messenger); \ + } \ + } while (0) + +#define QFV_duDestroyMessenger(inst, messenger) \ + do { \ + if (inst->funcs->vkDestroyDebugUtilsMessengerEXT) { \ + inst->funcs->vkDestroyDebugUtilsMessengerEXT (inst, messenger, 0);\ + } \ + } while (0) + +#define QFV_duQueueBeginLabel(device, queue, name...) \ + do { \ + qfv_devfuncs_t *dfunc = device->funcs; \ + if (dfunc->vkQueueBeginDebugUtilsLabelEXT) { \ + VkDebugUtilsLabelEXT label = { \ + VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, name \ + }; \ + dfunc->vkQueueBeginDebugUtilsLabelEXT (queue, &label); \ + } \ + } while (0) + +#define QFV_duQueueEndLabel(device, queue) \ + do { \ + qfv_devfuncs_t *dfunc = device->funcs; \ + if (dfunc->vkQueueEndDebugUtilsLabelEXT) { \ + dfunc->vkQueueEndDebugUtilsLabelEXT (queue); \ + } \ + } while (0) + +#define QFV_duQueueInsertLabel(device, queue, name...) \ + do { \ + qfv_devfuncs_t *dfunc = device->funcs; \ + if (dfunc->vkQueueInsertDebugUtilsLabelEXT) { \ + VkDebugUtilsLabelEXT label = { \ + VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, name \ + }; \ + dfunc->vkQueueInsertDebugUtilsLabelEXT (queue, &label); \ + } \ + } while (0) + +#define QFV_duSetObjectName(device, type, handle, name) \ + do { \ + qfv_devfuncs_t *dfunc = device->funcs; \ + if (dfunc->vkSetDebugUtilsObjectNameEXT) { \ + VkDebugUtilsObjectNameInfoEXT nameInfo = { \ + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 0, \ + type, (uint64_t) handle, name \ + }; \ + dfunc->vkSetDebugUtilsObjectNameEXT (device->dev, &nameInfo); \ + } \ + } while (0) + +#define QFV_duSetObjectTag(device, type, handle, name, size, tag) \ + do { \ + qfv_devfuncs_t *dfunc = device->funcs; \ + if (dfunc->vkSetDebugUtilsObjectTagEXT) { \ + VkDebugUtilsObjectTagInfoEXT tagInfo = { \ + VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT, 0, \ + type, handle, name, size, tag \ + }; \ + dfunc->vkSetDebugUtilsObjectTagEXT (device->dev, &tagInfo); \ + } \ + } while (0) + +#define QFV_duSubmitMessage(inst, severity, types, data) \ + do { \ + if (inst->funcs->vkSubmitDebugUtilsMessageEXT) { \ + inst->funcs->vkSubmitDebugUtilsMessageEXT (inst, severity, types, \ + data); \ + } \ + } while (0) + +#endif//__QF_Vulkan_debug_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 90c3a51d2..a1601f814 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -43,6 +43,8 @@ INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkCreateDebugUtilsMessengerEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkDestroyDebugUtilsMessengerEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) +INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkSubmitDebugUtilsMessageEXT, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkGetPhysicalDeviceSurfaceSupportKHR, VK_KHR_SURFACE_EXTENSION_NAME) INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION @@ -196,4 +198,21 @@ DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkQueuePresentKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkCmdBeginDebugUtilsLabelEXT, 0) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkCmdEndDebugUtilsLabelEXT, 0) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkCmdInsertDebugUtilsLabelEXT, 0) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkQueueBeginDebugUtilsLabelEXT, 0) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkQueueEndDebugUtilsLabelEXT, 0) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkQueueInsertDebugUtilsLabelEXT, 0) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkSetDebugUtilsObjectNameEXT, 0) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkSetDebugUtilsObjectTagEXT, 0) + #undef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index d08fc0a46..a70ba1116 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -13,7 +13,8 @@ typedef struct qfv_tex_s { void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, int alpha, int count); -qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip); +qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip, + const char *name); VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure)); void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex); void Vulkan_Texture_Init (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/scrap.h b/include/QF/Vulkan/scrap.h index b4818d558..31ceba506 100644 --- a/include/QF/Vulkan/scrap.h +++ b/include/QF/Vulkan/scrap.h @@ -8,8 +8,9 @@ typedef struct scrap_s scrap_t; struct qfv_stagebuf_s; struct qfv_device_s; -scrap_t *QFV_CreateScrap (struct qfv_device_s *device, int size, - QFFormat format, struct qfv_stagebuf_s *stage); +scrap_t *QFV_CreateScrap (struct qfv_device_s *device, const char *name, + int size, QFFormat format, + struct qfv_stagebuf_s *stage); size_t QFV_ScrapSize (scrap_t *scrap) __attribute__((pure)); void QFV_ScrapClear (scrap_t *scrap); void QFV_DestroyScrap (scrap_t *scrap); diff --git a/include/QF/Vulkan/staging.h b/include/QF/Vulkan/staging.h index ee3678625..9058e3c9a 100644 --- a/include/QF/Vulkan/staging.h +++ b/include/QF/Vulkan/staging.h @@ -26,7 +26,8 @@ typedef struct qfv_stagebuf_s { qfv_stagebuf_t *QFV_CreateStagingBuffer (struct qfv_device_s *device, - size_t size, VkCommandPool cmdPool); + const char *name, size_t size, + VkCommandPool cmdPool); void QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage); void QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size); qfv_packet_t *QFV_PacketAcquire (qfv_stagebuf_t *stage); diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 91ae665d0..07c63bee1 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -48,6 +48,7 @@ #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/staging.h" @@ -252,6 +253,15 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, VkBuffer ibuff = QFV_CreateBuffer (device, ind_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, vbuff, + va (ctx->va_ctx, "buffer:alias:vertex:%s", + loadmodel->name)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, uvbuff, + va (ctx->va_ctx, "buffer:alias:uv:%s", + loadmodel->name)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, ibuff, + va (ctx->va_ctx, "buffer:alias:index:%s", + loadmodel->name)); size_t voffs = 0; size_t uvoffs = voffs + get_buffer_size (device, vbuff); size_t ioffs = uvoffs + get_buffer_size (device, uvbuff); @@ -260,12 +270,18 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, mem = QFV_AllocBufferMemory (device, vbuff, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buff_size, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, mem, + va (ctx->va_ctx, "memory:alias:vuvi:%s", + loadmodel->name)); QFV_BindBufferMemory (device, vbuff, mem, voffs); QFV_BindBufferMemory (device, uvbuff, mem, uvoffs); QFV_BindBufferMemory (device, ibuff, mem, ioffs); - qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, buff_size, - ctx->cmdpool); + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, + va (ctx->va_ctx, + "alias:%s", + loadmodel->name), + buff_size, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); verts = QFV_PacketExtend (packet, vert_size); uv = QFV_PacketExtend (packet, uv_size); diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 3d45dd63c..ea08a25a4 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -50,6 +50,7 @@ #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/staging.h" @@ -209,10 +210,16 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) mem = QFV_AllocImageMemory (device, image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, memsize, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + mem, va (ctx->va_ctx, "memory:%s:texture", + loadmodel->name)); mctx->texture_memory = mem; - qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, memsize, - ctx->cmdpool); + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, + va (ctx->va_ctx, + "brush:%s", + loadmodel->name), + memsize, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); buffer = QFV_PacketExtend (packet, memsize); @@ -239,6 +246,10 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) tex->tex->view = QFV_CreateImageView (device, tex->tex->image, type, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, + tex->tex->view, + va (ctx->va_ctx, "iview:%s:%s:tex", + loadmodel->name, tx->name)); transfer_mips (buffer + tex->tex->offset, tx + 1, tx, palette); if (tex->glow) { dfunc->vkBindImageMemory (device->dev, tex->glow->image, mem, @@ -249,6 +260,11 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, + tex->glow->view, + va (ctx->va_ctx, "iview:%s:%s:glow", + loadmodel->name, + tx->name)); transfer_mips (buffer + tex->glow->offset, tex->glow->memory, tx, palette); } @@ -351,6 +367,10 @@ Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, + tex->tex->image, + va (ctx->va_ctx, "image:%s:%s:tex", loadmodel->name, + tx->name)); if (layers > 1) { // skys are unlit, so no fullbrights return; @@ -372,6 +392,10 @@ Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, + tex->glow->image, + va (ctx->va_ctx, "image:%s:%s:glow", loadmodel->name, + tx->name)); // store the pointer to the fullbright data: memory will never be set to // actual device memory because all of the textures will be loaded in one // big buffer diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 86ba71f73..4cfceb999 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -112,10 +112,12 @@ load_device_funcs (qfv_instance_t *inst, qfv_device_t *dev) } #define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ - if (dev->extension_enabled (dev, ext)) { \ + if (!ext || dev->extension_enabled (dev, ext)) { \ dfunc->name = (PFN_##name) ifunc->vkGetDeviceProcAddr (device, #name); \ if (!dfunc->name) { \ Sys_Printf ("Couldn't find device level function %s", #name); \ + } else { \ + Sys_Printf ("Found device level function %s\n", #name); \ } \ } diff --git a/libs/video/renderer/vulkan/scrap.c b/libs/video/renderer/vulkan/scrap.c index 27c2ea3bd..01eed4bf8 100644 --- a/libs/video/renderer/vulkan/scrap.c +++ b/libs/video/renderer/vulkan/scrap.c @@ -51,6 +51,7 @@ #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" @@ -76,12 +77,13 @@ struct scrap_s { }; scrap_t * -QFV_CreateScrap (qfv_device_t *device, int size, QFFormat format, - qfv_stagebuf_t *stage) +QFV_CreateScrap (qfv_device_t *device, const char *name, int size, + QFFormat format, qfv_stagebuf_t *stage) { qfv_devfuncs_t *dfunc = device->funcs; int bpp = 0; VkFormat fmt = VK_FORMAT_UNDEFINED; + dstring_t *str = dstring_new (); switch (format) { case tex_l: @@ -119,13 +121,20 @@ QFV_CreateScrap (qfv_device_t *device, int size, QFFormat format, extent, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, scrap->image, + dsprintf (str, "image:scrap:%s", name)); scrap->memory = QFV_AllocImageMemory (device, scrap->image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, scrap->memory, + dsprintf (str, "memory:scrap:%s", name)); QFV_BindImageMemory (device, scrap->image, scrap->memory, 0); scrap->view = QFV_CreateImageView (device, scrap->image, VK_IMAGE_VIEW_TYPE_2D, fmt, VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, scrap->view, + dsprintf (str, "iview:scrap:%s", name)); + dstring_delete (str); scrap->bpp = bpp; scrap->subpics = 0; scrap->device = device; diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 836a08e5e..cb3bb8ad0 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -48,6 +48,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/staging.h" @@ -55,11 +56,12 @@ #include "vid_vulkan.h" qfv_stagebuf_t * -QFV_CreateStagingBuffer (qfv_device_t *device, size_t size, +QFV_CreateStagingBuffer (qfv_device_t *device, const char * name, size_t size, VkCommandPool cmdPool) { size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; qfv_devfuncs_t *dfunc = device->funcs; + dstring_t *str = dstring_new (); qfv_stagebuf_t *stage = calloc (1, sizeof (qfv_stagebuf_t)); stage->atom_mask = atom - 1; @@ -67,9 +69,13 @@ QFV_CreateStagingBuffer (qfv_device_t *device, size_t size, stage->device = device; stage->buffer = QFV_CreateBuffer (device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, stage->buffer, + dsprintf (str, "staging:buffer:%s", name)); stage->memory = QFV_AllocBufferMemory (device, stage->buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, size, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, stage->memory, + dsprintf (str, "staging:memory:%s", name)); stage->size = size; stage->end = size; @@ -85,9 +91,18 @@ QFV_CreateStagingBuffer (qfv_device_t *device, size_t size, packet->stage = stage; packet->cmd = bufferset->a[i]; packet->fence = QFV_CreateFence (device, 1); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + packet->cmd, + dsprintf (str, "staging:packet:cmd:%s:%d", + name, i)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_FENCE, + packet->fence, + dsprintf (str, "staging:packet:fence:%s:%d", + name, i)); packet->offset = 0; packet->length = 0; } + dstring_delete (str); return stage; } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 3c2447702..4108a75f5 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -54,6 +54,7 @@ #include "QF/simd/vec4f.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/instance.h" @@ -391,6 +392,8 @@ parse_VkShaderModule_resource (const plitem_t *item, void **data, PL_Message (messages, item, "could not find shader %s", shader_path); return 0; } + QFV_duSetObjectName (device, VK_OBJECT_TYPE_SHADER_MODULE, *handle, + va (ctx->va_ctx, "shader:%s", shader_path)); return 1; } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index a31267cfb..65fa232cc 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -57,6 +57,7 @@ #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" @@ -270,15 +271,25 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) actx->pipeline = Vulkan_CreatePipeline (ctx, "alias"); actx->layout = QFV_GetPipelineLayout (ctx, "alias.layout"); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, actx->layout, + va (ctx->va_ctx, "layout:%s", "alias.layout")); actx->sampler = QFV_GetSampler (ctx, "alias.sampler"); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_SAMPLER, actx->sampler, + va (ctx->va_ctx, "sampler:%s", "alias.sampler")); - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (2 * frames, alloca); + /*__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (2 * frames, alloca); for (size_t i = 0; i < layouts->size / 2; i++) { __auto_type mats = QFV_GetDescriptorSetLayout (ctx, "alias.matrices"); __auto_type lights = QFV_GetDescriptorSetLayout (ctx, "alias.lights"); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, + mats, va (ctx->va_ctx, "set_layout:%s:%d", + "alias.matrices", i)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, + lights, va (ctx->va_ctx, "set_layout:%s:%d", + "alias.lights", i)); layouts->a[2 * i + 0] = mats; layouts->a[2 * i + 1] = lights; - } + }*/ //__auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool"); __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); @@ -288,6 +299,10 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) for (size_t i = 0; i < frames; i++) { lbuffers->a[i] = QFV_CreateBuffer (device, sizeof (qfv_light_buffer_t), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, + lbuffers->a[i], + va (ctx->va_ctx, "buffer:alias:%s:%zd", + "lights", i)); } VkMemoryRequirements requirements; dfunc->vkGetBufferMemoryRequirements (device->dev, lbuffers->a[0], @@ -295,6 +310,9 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) actx->light_memory = QFV_AllocBufferMemory (device, lbuffers->a[0], VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, frames * requirements.size, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + actx->light_memory, va (ctx->va_ctx, + "memory:alias:%s", "lights")); byte *light_data; dfunc->vkMapMemory (device->dev, actx->light_memory, 0, frames * requirements.size, 0, (void **) &light_data); @@ -303,6 +321,9 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) for (size_t i = 0; i < frames; i++) { __auto_type aframe = &actx->frames.a[i]; aframe->cmd = cmdBuffers->a[i]; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + aframe->cmd, + va (ctx->va_ctx, "cmd:alias:%zd", i)); aframe->light_buffer = lbuffers->a[i]; aframe->lights = (qfv_light_buffer_t *) (light_data + i * requirements.size); QFV_BindBufferMemory (device, lbuffers->a[i], actx->light_memory, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index c95a14c97..a923f854a 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -58,6 +58,7 @@ #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" @@ -467,7 +468,8 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) size_t vertex_buffer_size = vertex_count * sizeof (bspvert_t); index_buffer_size = (index_buffer_size + atom_mask) & ~atom_mask; - stage = QFV_CreateStagingBuffer (device, vertex_buffer_size, ctx->cmdpool); + stage = QFV_CreateStagingBuffer (device, "bsp", vertex_buffer_size, + ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); vertices = QFV_PacketExtend (packet, vertex_buffer_size); vertex_index_base = 0; @@ -518,10 +520,14 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) = QFV_CreateBuffer (device, index_buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, bctx->index_buffer, + "buffer:bsp:index"); bctx->index_memory = QFV_AllocBufferMemory (device, bctx->index_buffer, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, index_buffer_size, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + bctx->index_memory, "memory:bsp:index"); QFV_BindBufferMemory (device, bctx->index_buffer, bctx->index_memory, 0); bctx->index_buffer_size = index_buffer_size; @@ -545,10 +551,14 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) = QFV_CreateBuffer (device, vertex_buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, + bctx->vertex_buffer, "buffer:bsp:vertex"); bctx->vertex_memory = QFV_AllocBufferMemory (device, bctx->vertex_buffer, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertex_buffer_size, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + bctx->vertex_memory, "memory:bsp:vertex"); QFV_BindBufferMemory (device, bctx->vertex_buffer, bctx->vertex_memory, 0); bctx->vertex_buffer_size = vertex_buffer_size; @@ -1290,12 +1300,17 @@ create_default_skys (vulkan_ctx_t *ctx) VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, skybox, + "bsp:image:default_skybox"); skysheet = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, VK_FORMAT_B8G8R8A8_UNORM, extents, 1, 2, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, skysheet, + "bsp:image:default_skysheet"); + VkMemoryRequirements requirements; dfunc->vkGetImageMemoryRequirements (device->dev, skybox, &requirements); size_t boxsize = requirements.size; @@ -1307,6 +1322,8 @@ create_default_skys (vulkan_ctx_t *ctx) boxsize + sheetsize, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, memory, + "bsp:memory:default_skys"); QFV_BindImageMemory (device, skybox, memory, 0); QFV_BindImageMemory (device, skysheet, memory, boxsize); @@ -1314,11 +1331,15 @@ create_default_skys (vulkan_ctx_t *ctx) boxview = QFV_CreateImageView (device, skybox, VK_IMAGE_VIEW_TYPE_CUBE, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, boxview, + "bsp:iview:default_skysheet"); sheetview = QFV_CreateImageView (device, skysheet, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, sheetview, + "bsp:iview:default_skysheet"); bctx->default_skybox->image = skybox; bctx->default_skybox->view = boxview; @@ -1405,9 +1426,11 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->elementss_tail = &bctx->elementss; bctx->instsurfs_tail = &bctx->instsurfs; - bctx->light_scrap = QFV_CreateScrap (device, 2048, tex_frgba, ctx->staging); + bctx->light_scrap = QFV_CreateScrap (device, "lightmap_atlas", 2048, + tex_frgba, ctx->staging); size_t size = QFV_ScrapSize (bctx->light_scrap); - bctx->light_stage = QFV_CreateStagingBuffer (device, size, ctx->cmdpool); + bctx->light_stage = QFV_CreateStagingBuffer (device, "lightmap", size, + ctx->cmdpool); create_default_skys (ctx); @@ -1421,7 +1444,11 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp.main"); bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp.skysheet"); bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp.layout"); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, bctx->layout, + va (ctx->va_ctx, "layout:%s", "quakebsp.layout")); bctx->sampler = QFV_GetSampler (ctx, "quakebsp.sampler"); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_SAMPLER, bctx->sampler, + va (ctx->va_ctx, "sampler:%s", "quakebsp.sampler")); __auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); @@ -1431,6 +1458,15 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bframe->bsp_cmd = cmdBuffers->a[i * 3 + 0]; bframe->turb_cmd = cmdBuffers->a[i * 3 + 1]; bframe->sky_cmd = cmdBuffers->a[i * 3 + 2]; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + bframe->bsp_cmd, + va (ctx->va_ctx, "cmd:bsp:%zd", i)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + bframe->turb_cmd, + va (ctx->va_ctx, "cmd:turb:%zd", i)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + bframe->sky_cmd, + va (ctx->va_ctx, "cmd:sky:%zd", i)); for (int j = 0; j < BSP_BUFFER_INFOS; j++) { bframe->bufferInfo[j] = base_buffer_info; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 3fc563cb2..16b563600 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -367,9 +367,10 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) 0, 0); create_quad_buffers (ctx); - dctx->stage = QFV_CreateStagingBuffer (device, 4 * 1024 * 1024, + dctx->stage = QFV_CreateStagingBuffer (device, "draw", 4 * 1024 * 1024, ctx->cmdpool); - dctx->scrap = QFV_CreateScrap (device, 2048, tex_rgba, dctx->stage); + dctx->scrap = QFV_CreateScrap (device, "draw_atlas", 2048, tex_rgba, + dctx->stage); dctx->sampler = QFV_GetSampler (ctx, "quakepic"); qpic_t *charspic = Draw_Font8x8Pic (); diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 0129f886c..9bff6e72b 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -48,11 +48,13 @@ #include "QF/quakefs.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" @@ -199,7 +201,7 @@ blit_mips (int mips, VkImage image, tex_t *tex, } qfv_tex_t * -Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) +Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -256,14 +258,20 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip) VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, qtex->image, + va (ctx->va_ctx, "image:%s", name)); qtex->memory = QFV_AllocImageMemory (device, qtex->image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, qtex->memory, + va (ctx->va_ctx, "memory:%s", name)); QFV_BindImageMemory (device, qtex->image, qtex->memory, 0); qtex->view = QFV_CreateImageView (device, qtex->image, VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, qtex->view, + va (ctx->va_ctx, "iview:%s", name)); size_t bytes = bpp * tex->width * tex->height; qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); @@ -337,9 +345,12 @@ static tex_t default_magenta_tex = {1, 1, tex_rgba, 1, 0, magenta_data}; void Vulkan_Texture_Init (vulkan_ctx_t *ctx) { - ctx->default_black = Vulkan_LoadTex (ctx, &default_black_tex, 1); - ctx->default_white = Vulkan_LoadTex (ctx, &default_white_tex, 1); - ctx->default_magenta = Vulkan_LoadTex (ctx, &default_magenta_tex, 1); + ctx->default_black = Vulkan_LoadTex (ctx, &default_black_tex, 1, + "default_black"); + ctx->default_white = Vulkan_LoadTex (ctx, &default_white_tex, 1, + "default_white"); + ctx->default_magenta = Vulkan_LoadTex (ctx, &default_magenta_tex, 1, + "default_magenta"); } void diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 2ab5fc166..ddd20e82c 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -54,6 +54,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/command.h" @@ -204,8 +205,8 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) void Vulkan_CreateStagingBuffers (vulkan_ctx_t *ctx) { - ctx->staging = QFV_CreateStagingBuffer (ctx->device, 4*1024*1024, - ctx->cmdpool); + ctx->staging = QFV_CreateStagingBuffer (ctx->device, "vulkan_ctx", + 4*1024*1024, ctx->cmdpool); } void @@ -238,9 +239,10 @@ void Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) { qfv_load_pipeline (ctx); + const char *name = "renderpass";//FIXME plitem_t *item = ctx->pipelineDef; - if (!item || !(item = PL_ObjectForKey (item, "renderpass"))) { + if (!item || !(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading renderpass\n"); return; } else { @@ -340,6 +342,9 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) ctx->renderpass.colorImage = colorImage; ctx->renderpass.depthImage = depthImage; ctx->renderpass.renderpass = QFV_ParseRenderPass (ctx, item); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, + ctx->renderpass.renderpass, + va (ctx->va_ctx, "pipeline:%s", name)); } void @@ -382,7 +387,10 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found pipeline def %s\n", name); } - return QFV_ParsePipeline (ctx, item); + VkPipeline pipeline = QFV_ParsePipeline (ctx, item); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, + va (ctx->va_ctx, "pipeline:%s", name)); + return pipeline; } void From 08b1d75582b37e245299b39ca2f34b804e34b6d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Feb 2021 10:54:49 +0900 Subject: [PATCH 1290/3664] [nq] Put the fps lock back in That wasn't meant to be removed yet as there are physics problems, but it's useful for renderer testing. It snuck in with the va patch. --- nq/source/host.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nq/source/host.c b/nq/source/host.c index 861e9d06b..65266f801 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -529,7 +529,7 @@ Host_FilterTime (float time) //FIXME not having the framerate cap is nice, but it breaks net play timedifference = (timescale / 72.0) - (realtime - oldrealtime); - if (0 && !cls.timedemo && (timedifference > 0)) + if (!cls.timedemo && (timedifference > 0)) return timedifference; // framerate is too high host_frametime = realtime - oldrealtime; @@ -541,7 +541,7 @@ Host_FilterTime (float time) if (host_framerate->value > 0) host_frametime = host_framerate->value; else // don't allow really long or short frames - host_frametime = bound (0.000, host_frametime, 0.1); + host_frametime = bound (0.001, host_frametime, 0.1); return 0; } From c7eafd92547591b1f9e1e4e0607c5ccf88841177 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Feb 2021 12:16:05 +0900 Subject: [PATCH 1291/3664] [vulkan] Make the mip map generation public I've decided that alias model skins should be in a single four-level array texture rather than spread over four textures, but there's no way I want to write that code again: getting it right was hard enough the first time :P --- include/QF/Vulkan/image.h | 26 +++++++ libs/video/renderer/vulkan/image.c | 83 +++++++++++++++++++++ libs/video/renderer/vulkan/vulkan_texture.c | 82 +------------------- 3 files changed, 111 insertions(+), 80 deletions(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 489c86e40..71ca57389 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -57,4 +57,30 @@ VkImageView QFV_CreateImageView (struct qfv_device_s *device, VkImage image, VkImageViewType type, VkFormat format, VkImageAspectFlags aspect); +/** Generate all mipmaps for a given texture down to a 1x1 pixel. + * + * Uses the GPU blit command from one mip level to the next, thus the base mip + * level data must have already been transfered to the image and the image is + * expected to be in VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. This includes any + * array levels. + * + * \param device The device owning the command buffer. + * \param cmd The command buffer to which the barrier and blit commands + * will be written. + * \param image The image to be processed. All array layers of the base mip + * level must be initialized and in "transfer dst optimal" + * layout. All remaining mip levels must be in "undefined" + * oayout. + * \param mips The total number of mip levels of the processed image. + * \param width The pixel width of the base image. + * \param height The pixel height of the base image. + * \param layers The number of array layers in the mbase image. + * + * \note The processed image will be in "shader read only optimal" layout on + * completion. + */ +void QFV_GenerateMipMaps (struct qfv_device_s *device, VkCommandBuffer cmd, + VkImage image, unsigned mips, + unsigned width, unsigned height, unsigned layers); + #endif//__QF_Vulkan_image_h diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index bd71cc162..92d584f80 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -49,6 +49,7 @@ #include "QF/va.h" #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/barrier.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" @@ -192,3 +193,85 @@ QFV_CreateImageView (qfv_device_t *device, VkImage image, dfunc->vkCreateImageView (dev, &createInfo, 0, &view); return view; } + +void +QFV_GenerateMipMaps (qfv_device_t *device, VkCommandBuffer cmd, + VkImage image, unsigned mips, + unsigned width, unsigned height, unsigned layers) +{ + qfv_devfuncs_t *dfunc = device->funcs; + + qfv_pipelinestagepair_t pre_stages = { + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + }; + qfv_pipelinestagepair_t post_stages = { + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + }; + qfv_pipelinestagepair_t final_stages = { + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + }; + VkImageMemoryBarrier pre_barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + image, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, layers } + }; + VkImageMemoryBarrier post_barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + image, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, layers } + }; + VkImageMemoryBarrier final_barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + image, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, layers } + }; + + VkImageBlit blit = { + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, layers}, + {{0, 0, 0}, {width, height, 1}}, + {VK_IMAGE_ASPECT_COLOR_BIT, 1, 0, layers}, + {{0, 0, 0}, {max (width >> 1, 1), max (height >> 1, 1), 1}}, + }; + + while (--mips > 0) { + dfunc->vkCmdPipelineBarrier (cmd, pre_stages.src, pre_stages.dst, 0, + 0, 0, 0, 0, + 1, &pre_barrier); + dfunc->vkCmdBlitImage (cmd, + image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &blit, VK_FILTER_LINEAR); + + dfunc->vkCmdPipelineBarrier (cmd, post_stages.src, post_stages.dst, 0, + 0, 0, 0, 0, + 1, &post_barrier); + + blit.srcSubresource.mipLevel++; + blit.srcOffsets[1].x = blit.dstOffsets[1].x; + blit.srcOffsets[1].y = blit.dstOffsets[1].y; + blit.dstSubresource.mipLevel++; + blit.dstOffsets[1].x = max (blit.dstOffsets[1].x >> 1, 1); + blit.dstOffsets[1].y = max (blit.dstOffsets[1].y >> 1, 1); + pre_barrier.subresourceRange.baseMipLevel++; + post_barrier.subresourceRange.baseMipLevel++; + final_barrier.subresourceRange.baseMipLevel++; + } + dfunc->vkCmdPipelineBarrier (cmd, final_stages.src, final_stages.dst, 0, + 0, 0, 0, 0, + 1, &final_barrier); +} diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 9bff6e72b..4a1e2d2ab 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -121,85 +121,6 @@ Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, } } -static void -blit_mips (int mips, VkImage image, tex_t *tex, - qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) -{ - qfv_pipelinestagepair_t pre_stages = { - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - }; - qfv_pipelinestagepair_t post_stages = { - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - }; - qfv_pipelinestagepair_t final_stages = { - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - }; - VkImageMemoryBarrier pre_barrier = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - image, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - }; - VkImageMemoryBarrier post_barrier = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - image, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - }; - VkImageMemoryBarrier final_barrier = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - image, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } - }; - - VkImageBlit blit = { - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, - {{0, 0, 0}, {tex->width, tex->height, 1}}, - {VK_IMAGE_ASPECT_COLOR_BIT, 1, 0, 1}, - {{0, 0, 0}, {max (tex->width >> 1, 1), max (tex->height >> 1, 1), 1}}, - }; - - while (--mips > 0) { - dfunc->vkCmdPipelineBarrier (cmd, pre_stages.src, pre_stages.dst, 0, - 0, 0, 0, 0, - 1, &pre_barrier); - dfunc->vkCmdBlitImage (cmd, - image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, &blit, VK_FILTER_LINEAR); - - dfunc->vkCmdPipelineBarrier (cmd, post_stages.src, post_stages.dst, 0, - 0, 0, 0, 0, - 1, &post_barrier); - - blit.srcSubresource.mipLevel++; - blit.srcOffsets[1].x = blit.dstOffsets[1].x; - blit.srcOffsets[1].y = blit.dstOffsets[1].y; - blit.dstSubresource.mipLevel++; - blit.dstOffsets[1].x = max (blit.dstOffsets[1].x >> 1, 1); - blit.dstOffsets[1].y = max (blit.dstOffsets[1].y >> 1, 1); - pre_barrier.subresourceRange.baseMipLevel++; - post_barrier.subresourceRange.baseMipLevel++; - final_barrier.subresourceRange.baseMipLevel++; - } - dfunc->vkCmdPipelineBarrier (cmd, final_stages.src, final_stages.dst, 0, - 0, 0, 0, 0, - 1, &final_barrier); -} - qfv_tex_t * Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) { @@ -311,7 +232,8 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) 0, 0, 0, 0, 0, 1, &barrier); } else { - blit_mips (mip, qtex->image, tex, dfunc, packet->cmd); + QFV_GenerateMipMaps (device, packet->cmd, qtex->image, + mip, tex->width, tex->height, 1); } QFV_PacketSubmit (packet); return qtex; From afe8e9633e3c38e8d3a6ebf168d2f737015a0544 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Feb 2021 12:24:27 +0900 Subject: [PATCH 1292/3664] [vulkan] Silence the matrix dump It got annoying and has served its purpose. However, the code is still there (#if 0) in case it's needed again. --- libs/video/renderer/vulkan/vulkan_matrices.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index e1a1dd13e..ffd36219a 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -175,7 +175,7 @@ Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx, float aspect) ortho_mat (mat->projection_2d, 0, width, 0, height, -99999, 99999); persp_mat (mat->projection_3d, 0, width, 0, height, aspect); - +#if 0 Sys_MaskPrintf (SYS_VULKAN, "ortho:\n"); Sys_MaskPrintf (SYS_VULKAN, " [[%g, %g, %g, %g],\n", QuatExpand (mat->projection_2d + 0)); @@ -194,7 +194,7 @@ Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx, float aspect) QuatExpand (mat->projection_3d + 8)); Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g]]\n", QuatExpand (mat->projection_3d + 12)); - +#endif VkMappedMemoryRange ranges[] = { { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, 0, MAT_SIZE }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, From bb6c6963d2b6cb45f42a0b3cc0e841183a76603d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Feb 2021 14:39:00 +0900 Subject: [PATCH 1293/3664] [model] Clean up the globals around model loading Covers only the generic load code (alias etc to follow), but this should take care of a lot of issues in the future. --- include/QF/Vulkan/qf_alias.h | 7 +- include/QF/model.h | 36 +-- include/QF/plugin/vid_render.h | 12 +- include/mod_internal.h | 54 ++-- libs/models/alias/gl_mesh.c | 6 +- libs/models/alias/gl_model_alias.c | 18 +- libs/models/alias/glsl_model_alias.c | 6 +- libs/models/alias/model_alias.c | 44 +-- libs/models/alias/sw_model_alias.c | 20 +- libs/models/alias/vulkan_model_alias.c | 24 +- libs/models/brush/gl_model_brush.c | 35 ++- libs/models/brush/glsl_model_brush.c | 12 +- libs/models/brush/model_brush.c | 285 ++++++++++--------- libs/models/brush/sw_model_brush.c | 8 +- libs/models/brush/vulkan_model_brush.c | 71 +++-- libs/models/clip_hull.c | 1 + libs/models/fullbright.c | 2 +- libs/models/gl_model_fullbright.c | 2 +- libs/models/iqm/model_iqm.c | 10 +- libs/models/model.c | 33 +-- libs/models/sprite/gl_model_sprite.c | 5 +- libs/models/sprite/glsl_model_sprite.c | 7 +- libs/models/sprite/model_sprite.c | 27 +- libs/models/sprite/sw_model_sprite.c | 3 +- libs/video/renderer/gl/gl_dyn_part.c | 2 +- libs/video/renderer/gl/gl_lightmap.c | 4 +- libs/video/renderer/gl/gl_rmisc.c | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 4 +- libs/video/renderer/glsl/glsl_lightmap.c | 4 +- libs/video/renderer/glsl/glsl_particles.c | 2 +- libs/video/renderer/sw/sw_ralias.c | 2 +- libs/video/renderer/sw/sw_rpart.c | 2 +- libs/video/renderer/sw32/sw32_ralias.c | 2 +- libs/video/renderer/sw32/sw32_rpart.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 25 +- libs/video/renderer/vulkan/vulkan_bsp.c | 4 +- libs/video/renderer/vulkan/vulkan_lightmap.c | 4 +- nq/source/cl_demo.c | 2 +- nq/source/cl_main.c | 2 +- nq/source/sv_main.c | 2 +- qw/source/cl_demo.c | 2 +- qw/source/sbar.c | 2 +- qw/source/sv_init.c | 2 +- qw/source/teamplay.c | 8 +- 44 files changed, 408 insertions(+), 399 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index bcc5be337..dac8f4ca7 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -102,13 +102,14 @@ typedef struct aliasctx_s { struct vulkan_ctx_s; struct entity_s; -void *Vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc, +void *Vulkan_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, + int gnum, qboolean group, + maliasskindesc_t *skindesc, struct vulkan_ctx_s *ctx); void Vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr, struct vulkan_ctx_s *ctx); void Vulkan_Mod_LoadExternalSkins (model_t *mod, struct vulkan_ctx_s *ctx); -void Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, +void Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, int _s, int extra, struct vulkan_ctx_s *ctx); diff --git a/include/QF/model.h b/include/QF/model.h index 5512506f3..c7fc9190f 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -346,6 +346,8 @@ typedef enum {mod_brush, mod_sprite, mod_alias, mod_iqm} modtype_t; #define EF_GLOWTRAIL 4096 // glowcolor particle trail typedef struct model_s { + //FIXME use pointers. needs care in bsp submodel loading + char path[MAX_QPATH]; char name[MAX_QPATH]; const struct vpath_s *vpath;// virtual path where this model was found qboolean needload; // bmodels and sprites don't cache normally @@ -431,40 +433,20 @@ typedef struct model_s { // ============================================================================ -extern float RadiusFromBounds (const vec3_t mins, const vec3_t maxs) __attribute__((pure)); -void Mod_Init (void); -void Mod_Init_Cvars (void); -void Mod_ClearAll (void); +void Mod_Init (void); +void Mod_Init_Cvars (void); +void Mod_ClearAll (void); model_t *Mod_ForName (const char *name, qboolean crash); -void *Mod_Extradata (model_t *mod); // handles caching -void Mod_TouchModel (const char *name); - +void Mod_TouchModel (const char *name); +// brush specific mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure)); -byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); -model_t *Mod_FindName (const char *name); -int Mod_CalcFullbright (const byte *in, byte *out, int pixels); -void Mod_ClearFullbright (const byte *in, byte *out, int pixels); -int Mod_Fullbright (byte * skin, int width, int height, const char *name); - -void *Mod_LoadAliasFrame (void *pin, int *posenum, maliasframedesc_t *frame, - int extra); -void *Mod_LoadAliasGroup (void *pin, int *posenum, maliasframedesc_t *frame, - int extra); - -void Mod_FindClipDepth (hull_t *hull); -void Mod_LoadBrushModel (model_t *mod, void *buffer); -void Mod_FloodFillSkin (byte *skin, int skinwidth, int skinheight); - -void Mod_Print (void); +byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); +void Mod_Print (void); extern struct cvar_s *gl_mesh_cache; extern struct cvar_s *gl_subdivide_size; extern struct cvar_s *gl_alias_render_tri; extern struct cvar_s *gl_textures_external; -extern model_t *loadmodel; -extern char *loadname; -extern byte *mod_base; -extern byte mod_novis[MAX_MAP_LEAFS / 8]; extern int mod_lightmap_bytes; #endif//__QF_model_h diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index b2ea3d224..cc634e562 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -81,22 +81,24 @@ typedef struct vid_particle_funcs_s { typedef struct vid_model_funcs_s { size_t texture_render_size;// size of renderer specific texture data - void (*Mod_LoadLighting) (bsp_t *bsp); - void (*Mod_SubdivideSurface) (msurface_t *fa); - void (*Mod_ProcessTexture) (texture_t *tx); + void (*Mod_LoadLighting) (model_t *mod, bsp_t *bsp); + void (*Mod_SubdivideSurface) (model_t *mod, msurface_t *fa); + void (*Mod_ProcessTexture) (model_t *mod, texture_t *tx); void (*Mod_LoadIQM) (model_t *mod, void *buffer); void (*Mod_LoadAliasModel) (model_t *mod, void *buffer, cache_allocator_t allocator); void (*Mod_LoadSpriteModel) (model_t *mod, void *buffer); void (*Mod_MakeAliasModelDisplayLists) (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra); - void *(*Mod_LoadSkin) (byte *skin, int skinsize, int snum, int gnum, + void *(*Mod_LoadSkin) (model_t *mod, byte *skin, int skinsize, int snum, + int gnum, qboolean group, maliasskindesc_t *skindesc); void (*Mod_FinalizeAliasModel) (model_t *m, aliashdr_t *hdr); void (*Mod_LoadExternalSkins) (model_t *mod); void (*Mod_IQMFinish) (model_t *mod); int alias_cache; - void (*Mod_SpriteLoadTexture) (mspriteframe_t *pspriteframe, int framenum); + void (*Mod_SpriteLoadTexture) (model_t *mod, mspriteframe_t *pspriteframe, + int framenum); struct skin_s *(*Skin_SetColormap) (struct skin_s *skin, int cmap); struct skin_s *(*Skin_SetSkin) (struct skin_s *skin, int cmap, diff --git a/include/mod_internal.h b/include/mod_internal.h index 382a8985f..f459bbeaa 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -6,50 +6,68 @@ #include "QF/skin.h" #include "QF/plugin/vid_render.h" +int Mod_CalcFullbright (const byte *in, byte *out, int pixels); +void Mod_ClearFullbright (const byte *in, byte *out, int pixels); +void Mod_FloodFillSkin (byte *skin, int skinwidth, int skinheight); +//FIXME gl specific. rewrite to use above +int Mod_Fullbright (byte * skin, int width, int height, const char *name); + +void Mod_LoadBrushModel (model_t *mod, void *buffer); +void Mod_FindClipDepth (hull_t *hull); + +model_t *Mod_FindName (const char *name); +float RadiusFromBounds (const vec3_t mins, const vec3_t maxs) __attribute__((pure)); + struct vulkan_ctx_s; extern vid_model_funcs_t *m_funcs; void gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra); -void *gl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc); +void *gl_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, + int gnum, qboolean group, maliasskindesc_t *skindesc); void gl_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr); void gl_Mod_LoadExternalSkins (model_t *mod); void gl_Mod_IQMFinish (model_t *mod); void glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra); -void *glsl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc); +void *glsl_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, + int gnum, qboolean group, maliasskindesc_t *skindesc); void glsl_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr); void glsl_Mod_LoadExternalSkins (model_t *mod); void glsl_Mod_IQMFinish (model_t *mod); void sw_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s, int extra); -void *sw_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc); +void *sw_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, + int gnum, qboolean group, maliasskindesc_t *skindesc); void sw_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr); void sw_Mod_LoadExternalSkins (model_t *mod); void sw_Mod_IQMFinish (model_t *mod); -void gl_Mod_LoadLighting (bsp_t *bsp); -void gl_Mod_SubdivideSurface (msurface_t *fa); -void gl_Mod_ProcessTexture(texture_t *tx); +void gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp); +void gl_Mod_SubdivideSurface (model_t *mod, msurface_t *fa); +void gl_Mod_ProcessTexture (model_t *mod, texture_t *tx); -void glsl_Mod_LoadLighting (bsp_t *bsp); -void glsl_Mod_ProcessTexture(texture_t *tx); +void glsl_Mod_LoadLighting (model_t *mod, bsp_t *bsp); +void glsl_Mod_ProcessTexture (model_t *mod, texture_t *tx); -void sw_Mod_LoadLighting (bsp_t *bsp); +void sw_Mod_LoadLighting (model_t *mod, bsp_t *bsp); -void Vulkan_Mod_LoadLighting (bsp_t *bsp, struct vulkan_ctx_s *ctx); -void Vulkan_Mod_SubdivideSurface (msurface_t *fa, struct vulkan_ctx_s *ctx); -void Vulkan_Mod_ProcessTexture(texture_t *tx, struct vulkan_ctx_s *ctx); +void Vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp, + struct vulkan_ctx_s *ctx); +void Vulkan_Mod_SubdivideSurface (model_t *mod, msurface_t *fa, + struct vulkan_ctx_s *ctx); +void Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, + struct vulkan_ctx_s *ctx); -void gl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum); -void glsl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum); -void sw_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum); +void gl_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, + int framenum); +void glsl_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, + int framenum); +void sw_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, + int framenum); void Mod_LoadIQM (model_t *mod, void *buffer); void Mod_FreeIQM (iqm_t *iqm); diff --git a/libs/models/alias/gl_mesh.c b/libs/models/alias/gl_mesh.c index c55225057..6820000cf 100644 --- a/libs/models/alias/gl_mesh.c +++ b/libs/models/alias/gl_mesh.c @@ -361,8 +361,8 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, // look for a cached version dstring_copystr (cache, "glquake/"); - dstring_appendstr (cache, m->name); - QFS_StripExtension (m->name + strlen ("progs/"), + dstring_appendstr (cache, m->path); + QFS_StripExtension (m->path + strlen ("progs/"), cache->str + strlen ("glquake/")); dstring_appendstr (cache, ".qfms"); @@ -433,7 +433,7 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, } if (remesh) { // build it from scratch - Sys_MaskPrintf (SYS_DEV, "meshing %s...\n", m->name); + Sys_MaskPrintf (SYS_DEV, "meshing %s...\n", m->path); BuildTris (); // trifans or lists diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index ff5d62347..dec3a6e98 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -53,15 +53,15 @@ #include "compat.h" void * -gl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, qboolean group, - maliasskindesc_t *skindesc) +gl_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, int gnum, + qboolean group, maliasskindesc_t *skindesc) { byte *pskin; char modname[MAX_QPATH + 4]; int fb_texnum = 0, texnum = 0; dstring_t *name = dstring_new (); - pskin = Hunk_AllocName (skinsize, loadname); + pskin = Hunk_AllocName (skinsize, mod->name); skindesc->skin = (byte *) pskin - (byte *) pheader; memcpy (pskin, skin, skinsize); @@ -69,13 +69,13 @@ gl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, qboolean group, Mod_FloodFillSkin (pskin, pheader->mdl.skinwidth, pheader->mdl.skinheight); // save 8 bit texels for the player model to remap // FIXME remove model restriction - if (strequal (loadmodel->name, "progs/player.mdl")) + if (strequal (mod->path, "progs/player.mdl")) gl_Skin_SetPlayerSkin (pheader->mdl.skinwidth, pheader->mdl.skinheight, pskin); - QFS_StripExtension (loadmodel->name, modname); + QFS_StripExtension (mod->path, modname); - if (!loadmodel->fullbright) { + if (!mod->fullbright) { if (group) { dsprintf (name, "fb_%s_%i_%i", modname, snum, gnum); } else { @@ -95,7 +95,7 @@ gl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, qboolean group, Sys_MaskPrintf (SYS_GLT, "%s %d\n", name->str, texnum); skindesc->texnum = texnum; skindesc->fb_texnum = fb_texnum; - loadmodel->hasfullbrights = fb_texnum; + mod->hasfullbrights = fb_texnum; dstring_delete (name); // alpha param was true for non group skins return skin + skinsize; @@ -104,7 +104,7 @@ gl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, qboolean group, void gl_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr) { - if (strequal (m->name, "progs/eyes.mdl")) { + if (strequal (m->path, "progs/eyes.mdl")) { hdr->mdl.scale_origin[2] -= (22 + 8); VectorScale (hdr->mdl.scale, 2, hdr->mdl.scale); } @@ -158,7 +158,7 @@ gl_Mod_LoadExternalSkins (model_t *mod) maliasskingroup_t *pskingroup; dstring_t *filename = dstring_new (); - QFS_StripExtension (mod->name, modname); + QFS_StripExtension (mod->path, modname); for (i = 0; i < pheader->mdl.numskins; i++) { pskindesc = ((maliasskindesc_t *) diff --git a/libs/models/alias/glsl_model_alias.c b/libs/models/alias/glsl_model_alias.c index 796b3f346..609fa01b7 100644 --- a/libs/models/alias/glsl_model_alias.c +++ b/libs/models/alias/glsl_model_alias.c @@ -91,7 +91,7 @@ glsl_alias_clear (model_t *m, void *data) } void * -glsl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, +glsl_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) { byte *tskin; @@ -104,9 +104,9 @@ glsl_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, memcpy (tskin, skin, skinsize); Mod_FloodFillSkin (tskin, w, h); if (group) - name = va (0, "%s_%i_%i", loadmodel->name, snum, gnum); + name = va (0, "%s_%i_%i", mod->path, snum, gnum); else - name = va (0, "%s_%i", loadmodel->name, snum); + name = va (0, "%s_%i", mod->path, snum); skindesc->texnum = GLSL_LoadQuakeTexture (name, w, h, tskin); free (tskin); return skin + skinsize; diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index c5018f929..e4225daea 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -62,7 +62,8 @@ int aliasbboxmins[3], aliasbboxmaxs[3]; static void * -Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) +Mod_LoadAllSkins (model_t *mod, int numskins, daliasskintype_t *pskintype, + int *pskinindex) { byte *skin; float *poutskinintervals; @@ -77,7 +78,7 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) skinsize = pheader->mdl.skinwidth * pheader->mdl.skinheight; pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), - loadname); + mod->name); *pskinindex = (byte *) pskindesc - (byte *) pheader; @@ -85,7 +86,7 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) pskindesc[snum].type = pskintype->type; if (pskintype->type == ALIAS_SKIN_SINGLE) { skin = (byte *) (pskintype + 1); - skin = m_funcs->Mod_LoadSkin (skin, skinsize, snum, 0, false, + skin = m_funcs->Mod_LoadSkin (mod, skin, skinsize, snum, 0, false, &pskindesc[snum]); } else { pskintype++; @@ -93,14 +94,14 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) groupskins = LittleLong (pinskingroup->numskins); t = field_offset (maliasskingroup_t, skindescs[groupskins]); - paliasskingroup = Hunk_AllocName (t, loadname); + paliasskingroup = Hunk_AllocName (t, mod->name); paliasskingroup->numskins = groupskins; pskindesc[snum].skin = (byte *) paliasskingroup - (byte *) pheader; pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1); poutskinintervals = Hunk_AllocName (groupskins * sizeof (float), - loadname); + mod->name); paliasskingroup->intervals = (byte *) poutskinintervals - (byte *) pheader; for (gnum = 0; gnum < groupskins; gnum++) { @@ -117,8 +118,9 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) for (gnum = 0; gnum < groupskins; gnum++) { paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE; - skin = mod_funcs->Mod_LoadSkin (skin, skinsize, snum, gnum, - true, &paliasskingroup->skindescs[gnum]); + skin = mod_funcs->Mod_LoadSkin (mod, skin, skinsize, snum, + gnum, true, + &paliasskingroup->skindescs[gnum]); } } pskintype = (daliasskintype_t *) skin; @@ -127,9 +129,9 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) return pskintype; } -void * -Mod_LoadAliasFrame (void *pin, int *posenum, maliasframedesc_t *frame, - int extra) +static void * +Mod_LoadAliasFrame (model_t *mod, void *pin, int *posenum, + maliasframedesc_t *frame, int extra) { daliasframe_t *pdaliasframe; trivertx_t *pinframe; @@ -159,9 +161,9 @@ Mod_LoadAliasFrame (void *pin, int *posenum, maliasframedesc_t *frame, return pinframe; } -void * -Mod_LoadAliasGroup (void *pin, int *posenum, maliasframedesc_t *frame, - int extra) +static void * +Mod_LoadAliasGroup (model_t *mod, void *pin, int *posenum, + maliasframedesc_t *frame, int extra) { daliasgroup_t *pingroup; daliasinterval_t *pin_intervals; @@ -178,7 +180,7 @@ Mod_LoadAliasGroup (void *pin, int *posenum, maliasframedesc_t *frame, frame->numposes = numframes; paliasgroup = Hunk_AllocName (field_offset (maliasgroup_t, - frames[numframes]), loadname); + frames[numframes]), mod->name); paliasgroup->numframes = numframes; frame->frame = (byte *) paliasgroup - (byte *) pheader; @@ -189,7 +191,7 @@ Mod_LoadAliasGroup (void *pin, int *posenum, maliasframedesc_t *frame, VectorCompMax (frame->bboxmax.v, aliasbboxmaxs, aliasbboxmaxs); pin_intervals = (daliasinterval_t *) (pingroup + 1); - poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); + poutintervals = Hunk_AllocName (numframes * sizeof (float), mod->name); paliasgroup->intervals = (byte *) poutintervals - (byte *) pheader; frame->interval = LittleFloat (pin_intervals->interval); for (i = 0; i < numframes; i++) { @@ -203,7 +205,7 @@ Mod_LoadAliasGroup (void *pin, int *posenum, maliasframedesc_t *frame, ptemp = (void *) pin_intervals; for (i = 0; i < numframes; i++) { maliasframedesc_t temp_frame; - ptemp = Mod_LoadAliasFrame (ptemp, posenum, &temp_frame, extra); + ptemp = Mod_LoadAliasFrame (mod, ptemp, posenum, &temp_frame, extra); memcpy (&paliasgroup->frames[i], &temp_frame, sizeof (paliasgroup->frames[i])); } @@ -242,7 +244,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) // allocate space for a working header, plus all the data except the // frames, skin and group info size = field_offset (aliashdr_t, frames[LittleLong (pinmodel->numframes)]); - pheader = Hunk_AllocName (size, loadname); + pheader = Hunk_AllocName (size, mod->name); memset (pheader, 0, size); pmodel = &pheader->mdl; pheader->model = (byte *) pmodel - (byte *) pheader; @@ -294,7 +296,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) // load the skins pskintype = (daliasskintype_t *) &pinmodel[1]; - pskintype = Mod_LoadAllSkins (pheader->mdl.numskins, pskintype, + pskintype = Mod_LoadAllSkins (mod, pheader->mdl.numskins, pskintype, &pheader->skindesc); // load base s and t vertices @@ -332,11 +334,11 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) if (frametype == ALIAS_SINGLE) { pframetype = (daliasframetype_t *) - Mod_LoadAliasFrame (pframetype + 1, &posenum, + Mod_LoadAliasFrame (mod, pframetype + 1, &posenum, &pheader->frames[i], extra); } else { pframetype = (daliasframetype_t *) - Mod_LoadAliasGroup (pframetype + 1, &posenum, + Mod_LoadAliasGroup (mod, pframetype + 1, &posenum, &pheader->frames[i], extra); } } @@ -367,7 +369,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) end = Hunk_LowMark (); total = end - start; - mem = allocator (&mod->cache, total, loadname); + mem = allocator (&mod->cache, total, mod->name); if (mem) memcpy (mem, pheader, total); diff --git a/libs/models/alias/sw_model_alias.c b/libs/models/alias/sw_model_alias.c index e021278a4..61122298b 100644 --- a/libs/models/alias/sw_model_alias.c +++ b/libs/models/alias/sw_model_alias.c @@ -50,12 +50,12 @@ void * -sw_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, +sw_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) { byte *pskin; - pskin = Hunk_AllocName (skinsize, loadname); + pskin = Hunk_AllocName (skinsize, mod->name); skindesc->skin = (byte *) pskin - (byte *) pheader; memcpy (pskin, skin, skinsize); @@ -64,7 +64,7 @@ sw_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, } static void -process_frame (maliasframedesc_t *frame, int posenum, int extra) +process_frame (model_t *mod, maliasframedesc_t *frame, int posenum, int extra) { int size = pheader->mdl.numverts * sizeof (trivertx_t); trivertx_t *frame_verts; @@ -72,7 +72,7 @@ process_frame (maliasframedesc_t *frame, int posenum, int extra) if (extra) size *= 2; - frame_verts = Hunk_AllocName (size, loadname); + frame_verts = Hunk_AllocName (size, mod->name); frame->frame = (byte *) frame_verts - (byte *) pheader; // The low-order 8 bits (actually, fractional) are completely separate @@ -83,7 +83,7 @@ process_frame (maliasframedesc_t *frame, int posenum, int extra) } void -sw_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, +sw_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, int _s, int extra) { int i, j; @@ -93,9 +93,9 @@ sw_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, mtriangle_t *ptri; pstverts = (stvert_t *) Hunk_AllocName (numv * sizeof (stvert_t), - loadname); + mod->name); ptri = (mtriangle_t *) Hunk_AllocName (numt * sizeof (mtriangle_t), - loadname); + mod->name); hdr->stverts = (byte *) pstverts - (byte *) hdr; hdr->triangles = (byte *) ptri - (byte *) hdr; @@ -117,16 +117,16 @@ sw_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, maliasgroup_t *group; group = (maliasgroup_t *) ((byte *) pheader + frame->frame); for (j = 0; j < group->numframes; j++) - process_frame ((maliasframedesc_t *) &group->frames[j], + process_frame (mod, (maliasframedesc_t *) &group->frames[j], posenum++, extra); } else { - process_frame (frame, posenum++, extra); + process_frame (mod, frame, posenum++, extra); } } } void -sw_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr) +sw_Mod_FinalizeAliasModel (model_t *mod, aliashdr_t *hdr) { } diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 07c63bee1..97e8a63d0 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -110,8 +110,8 @@ vulkan_alias_clear (model_t *m, void *data) } void * -Vulkan_Mod_LoadSkin (byte *skinpix, int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc, +Vulkan_Mod_LoadSkin (model_t *mod, byte *skinpix, int skinsize, int snum, + int gnum, qboolean group, maliasskindesc_t *skindesc, vulkan_ctx_t *ctx) { aliasskin_t *skin; @@ -131,25 +131,25 @@ Vulkan_Mod_LoadSkin (byte *skinpix, int skinsize, int snum, int gnum, if (Mod_CalcFullbright (tskin, tskin + skinsize, skinsize)) { skin->glow = Vulkan_LoadTex (ctx, &skin_tex, 1, va (ctx->va_ctx, "%s:%d:%d:glow", - loadmodel->name, snum, gnum)); + mod->name, snum, gnum)); Mod_ClearFullbright (tskin, tskin, skinsize); } if (Skin_CalcTopColors (tskin, tskin + skinsize, skinsize)) { skin->colora = Vulkan_LoadTex (ctx, &skin_tex, 1, va (ctx->va_ctx, "%s:%d:%d:colora", - loadmodel->name, snum, gnum)); + mod->name, snum, gnum)); Skin_ClearTopColors (tskin, tskin, skinsize); } if (Skin_CalcBottomColors (tskin, tskin + skinsize, skinsize)) { skin->colorb = Vulkan_LoadTex (ctx, &skin_tex, 1, va (ctx->va_ctx, "%s:%d:%d:colorb", - loadmodel->name, snum, gnum)); + mod->name, snum, gnum)); Skin_ClearBottomColors (tskin, tskin, skinsize); } skin_tex.data = tskin; skin->tex = Vulkan_LoadTex (ctx, &skin_tex, 1, va (ctx->va_ctx, "%s:%d:%d:tex", - loadmodel->name, + mod->name, snum, gnum)); free (tskin); @@ -185,7 +185,7 @@ get_buffer_size (qfv_device_t *device, VkBuffer buffer) } void -Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, +Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, int _s, int extra, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; @@ -255,13 +255,13 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, vbuff, va (ctx->va_ctx, "buffer:alias:vertex:%s", - loadmodel->name)); + mod->name)); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, uvbuff, va (ctx->va_ctx, "buffer:alias:uv:%s", - loadmodel->name)); + mod->name)); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, ibuff, va (ctx->va_ctx, "buffer:alias:index:%s", - loadmodel->name)); + mod->name)); size_t voffs = 0; size_t uvoffs = voffs + get_buffer_size (device, vbuff); size_t ioffs = uvoffs + get_buffer_size (device, uvbuff); @@ -272,7 +272,7 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, buff_size, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, mem, va (ctx->va_ctx, "memory:alias:vuvi:%s", - loadmodel->name)); + mod->name)); QFV_BindBufferMemory (device, vbuff, mem, voffs); QFV_BindBufferMemory (device, uvbuff, mem, uvoffs); QFV_BindBufferMemory (device, ibuff, mem, ioffs); @@ -280,7 +280,7 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, va (ctx->va_ctx, "alias:%s", - loadmodel->name), + mod->name), buff_size, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); verts = QFV_PacketExtend (packet, vert_size); diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 878d2c344..05b3c0b94 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -86,7 +86,7 @@ Mod_LoadExternalTextures (model_t *mod, texture_t *tx) int external = 0; gltx = tx->render; - if ((base = Mod_LoadAnExternalTexture (tx->name, mod->name))) { + if ((base = Mod_LoadAnExternalTexture (tx->name, mod->path))) { external = 1; gltx->gl_texturenum = GL_LoadTexture (tx->name, base->width, base->height, @@ -94,10 +94,10 @@ Mod_LoadExternalTextures (model_t *mod, texture_t *tx) base->format > 2 ? base->format : 1); luma = Mod_LoadAnExternalTexture (va (0, "%s_luma", tx->name), - mod->name); + mod->path); if (!luma) luma = Mod_LoadAnExternalTexture (va (0, "%s_glow", tx->name), - mod->name); + mod->path); gltx->gl_fb_texturenum = 0; @@ -116,7 +116,7 @@ Mod_LoadExternalTextures (model_t *mod, texture_t *tx) } void -gl_Mod_ProcessTexture (texture_t *tx) +gl_Mod_ProcessTexture (model_t *mod, texture_t *tx) { const char *name; @@ -125,7 +125,7 @@ gl_Mod_ProcessTexture (texture_t *tx) return; } if (gl_textures_external && gl_textures_external->int_val) { - if (Mod_LoadExternalTextures (loadmodel, tx)) { + if (Mod_LoadExternalTextures (mod, tx)) { return; } } @@ -142,7 +142,7 @@ gl_Mod_ProcessTexture (texture_t *tx) } void -gl_Mod_LoadLighting (bsp_t *bsp) +gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp) { byte d; byte *in, *out, *data; @@ -151,13 +151,13 @@ gl_Mod_LoadLighting (bsp_t *bsp) int ver; QFile *lit_file; - dstring_copystr (litfilename, loadmodel->name); - loadmodel->lightdata = NULL; + dstring_copystr (litfilename, mod->path); + mod->lightdata = NULL; if (mod_lightmap_bytes > 1) { // LordHavoc: check for a .lit file to load QFS_StripExtension (litfilename->str, litfilename->str); dstring_appendstr (litfilename, ".lit"); - lit_file = QFS_VOpenFile (litfilename->str, 0, loadmodel->vpath); + lit_file = QFS_VOpenFile (litfilename->str, 0, mod->vpath); data = (byte *) QFS_LoadHunkFile (lit_file); if (data) { if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' @@ -165,7 +165,7 @@ gl_Mod_LoadLighting (bsp_t *bsp) ver = LittleLong (((int32_t *) data)[1]); if (ver == 1) { Sys_MaskPrintf (SYS_DEV, "%s loaded", litfilename->str); - loadmodel->lightdata = data + 8; + mod->lightdata = data + 8; return; } else Sys_MaskPrintf (SYS_DEV, @@ -179,11 +179,10 @@ gl_Mod_LoadLighting (bsp_t *bsp) dstring_delete (litfilename); return; } - loadmodel->lightdata = Hunk_AllocName (bsp->lightdatasize - * mod_lightmap_bytes, - litfilename->str); + mod->lightdata = Hunk_AllocName (bsp->lightdatasize * mod_lightmap_bytes, + litfilename->str); in = bsp->lightdata; - out = loadmodel->lightdata; + out = mod->lightdata; if (mod_lightmap_bytes > 1) for (i = 0; i < bsp->lightdatasize ; i++) { @@ -304,7 +303,7 @@ SubdividePolygon (int numverts, float *verts) can be done reasonably. */ void -gl_Mod_SubdivideSurface (msurface_t *fa) +gl_Mod_SubdivideSurface (model_t *mod, msurface_t *fa) { float *vec; int lindex, numverts, i; @@ -315,12 +314,12 @@ gl_Mod_SubdivideSurface (msurface_t *fa) // convert edges back to a normal polygon numverts = 0; for (i = 0; i < fa->numedges; i++) { - lindex = loadmodel->surfedges[fa->firstedge + i]; + lindex = mod->surfedges[fa->firstedge + i]; if (lindex > 0) - vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; + vec = mod->vertexes[mod->edges[lindex].v[0]].position; else - vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position; + vec = mod->vertexes[mod->edges[-lindex].v[1]].position; VectorCopy (vec, verts[numverts]); numverts++; } diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index 23bb683ad..3a2717f57 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -101,7 +101,7 @@ load_skytex (texture_t *tx, byte *data) } void -glsl_Mod_ProcessTexture (texture_t *tx) +glsl_Mod_ProcessTexture (model_t *mod, texture_t *tx) { if (!tx) { r_notexture_mip->render = &glsl_notexture; @@ -145,15 +145,15 @@ glsl_Mod_ProcessTexture (texture_t *tx) } void -glsl_Mod_LoadLighting (bsp_t *bsp) +glsl_Mod_LoadLighting (model_t *mod, bsp_t *bsp) { // a bit hacky, but it's as good a place as any - loadmodel->clear = glsl_brush_clear; + mod->clear = glsl_brush_clear; mod_lightmap_bytes = 1; if (!bsp->lightdatasize) { - loadmodel->lightdata = NULL; + mod->lightdata = NULL; return; } - loadmodel->lightdata = Hunk_AllocName (bsp->lightdatasize, loadname); - memcpy (loadmodel->lightdata, bsp->lightdata, bsp->lightdatasize); + mod->lightdata = Hunk_AllocName (bsp->lightdatasize, mod->name); + memcpy (mod->lightdata, bsp->lightdata, bsp->lightdatasize); } diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 24af26c95..38a33c893 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -53,8 +53,9 @@ #include "QF/plugin/vid_render.h" #include "compat.h" +#include "mod_internal.h" -byte mod_novis[MAX_MAP_LEAFS / 8]; +static byte mod_novis[MAX_MAP_LEAFS / 8]; VISIBLE cvar_t *gl_sky_divide; //FIXME visibility? VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible? @@ -122,8 +123,12 @@ Mod_DecompressVis (byte * in, model_t *model) VISIBLE byte * Mod_LeafPVS (mleaf_t *leaf, model_t *model) { - if (leaf == model->leafs) + if (leaf == model->leafs) { + if (!mod_novis[0]) { + memset (mod_novis, 0xff, sizeof (mod_novis)); + } return mod_novis; + } return Mod_DecompressVis (leaf->compressed_vis, model); } @@ -158,7 +163,7 @@ mod_unique_miptex_name (texture_t **textures, texture_t *tx, int ind) } static void -Mod_LoadTextures (bsp_t *bsp) +Mod_LoadTextures (model_t *mod, bsp_t *bsp) { dmiptexlump_t *m; int i, j, pixels, num, max, altmax; @@ -167,14 +172,14 @@ Mod_LoadTextures (bsp_t *bsp) texture_t *anims[10], *altanims[10]; if (!bsp->texdatasize) { - loadmodel->textures = NULL; + mod->textures = NULL; return; } m = (dmiptexlump_t *) bsp->texdata; - loadmodel->numtextures = m->nummiptex; - loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof - (*loadmodel->textures), loadname); + mod->numtextures = m->nummiptex; + mod->textures = Hunk_AllocName (m->nummiptex * sizeof (*mod->textures), + mod->name); for (i = 0; i < m->nummiptex; i++) { if (m->dataofs[i] == -1) @@ -188,12 +193,12 @@ Mod_LoadTextures (bsp_t *bsp) if ((mt->width & 15) || (mt->height & 15)) Sys_Error ("Texture %s is not 16 aligned", mt->name); pixels = mt->width * mt->height / 64 * 85; - tx = Hunk_AllocName (sizeof (texture_t) + pixels, loadname); + tx = Hunk_AllocName (sizeof (texture_t) + pixels, mod->name); - loadmodel->textures[i] = tx; + mod->textures[i] = tx; tx->name = strndup(mt->name, sizeof (mt->name)); - mod_unique_miptex_name (loadmodel->textures, tx, i); + mod_unique_miptex_name (mod->textures, tx, i); tx->width = mt->width; tx->height = mt->height; for (j = 0; j < MIPLEVELS; j++) @@ -203,28 +208,28 @@ Mod_LoadTextures (bsp_t *bsp) memcpy (tx + 1, mt + 1, pixels); if (!strncmp (mt->name, "sky", 3)) - loadmodel->skytexture = tx; + mod->skytexture = tx; } if (mod_funcs && mod_funcs->Mod_ProcessTexture) { size_t render_size = mod_funcs->texture_render_size; byte *render_data = 0; if (render_size) { render_data = Hunk_AllocName (m->nummiptex * render_size, - loadname); + mod->name); } for (i = 0; i < m->nummiptex; i++) { - tx = loadmodel->textures[i]; + tx = mod->textures[i]; tx->render = render_data; render_data += render_size; - mod_funcs->Mod_ProcessTexture (tx); + mod_funcs->Mod_ProcessTexture (mod, tx); } // signal the end of the textures - mod_funcs->Mod_ProcessTexture (0); + mod_funcs->Mod_ProcessTexture (mod, 0); } // sequence the animations for (i = 0; i < m->nummiptex; i++) { - tx = loadmodel->textures[i]; + tx = mod->textures[i]; if (!tx || tx->name[0] != '+') continue; if (tx->anim_next) @@ -251,7 +256,7 @@ Mod_LoadTextures (bsp_t *bsp) Sys_Error ("Bad animating texture %s", tx->name); for (j = i + 1; j < m->nummiptex; j++) { - tx2 = loadmodel->textures[j]; + tx2 = mod->textures[j]; if (!tx2 || tx2->name[0] != '+') continue; if (strcmp (tx2->name + 2, tx->name + 2)) @@ -302,29 +307,29 @@ Mod_LoadTextures (bsp_t *bsp) } static void -Mod_LoadVisibility (bsp_t *bsp) +Mod_LoadVisibility (model_t *mod, bsp_t *bsp) { if (!bsp->visdatasize) { - loadmodel->visdata = NULL; + mod->visdata = NULL; return; } - loadmodel->visdata = Hunk_AllocName (bsp->visdatasize, loadname); - memcpy (loadmodel->visdata, bsp->visdata, bsp->visdatasize); + mod->visdata = Hunk_AllocName (bsp->visdatasize, mod->name); + memcpy (mod->visdata, bsp->visdata, bsp->visdatasize); } static void -Mod_LoadEntities (bsp_t *bsp) +Mod_LoadEntities (model_t *mod, bsp_t *bsp) { if (!bsp->entdatasize) { - loadmodel->entities = NULL; + mod->entities = NULL; return; } - loadmodel->entities = Hunk_AllocName (bsp->entdatasize, loadname); - memcpy (loadmodel->entities, bsp->entdata, bsp->entdatasize); + mod->entities = Hunk_AllocName (bsp->entdatasize, mod->name); + memcpy (mod->entities, bsp->entdata, bsp->entdatasize); } static void -Mod_LoadVertexes (bsp_t *bsp) +Mod_LoadVertexes (model_t *mod, bsp_t *bsp) { dvertex_t *in; int count, i; @@ -332,27 +337,27 @@ Mod_LoadVertexes (bsp_t *bsp) in = bsp->vertexes; count = bsp->numvertexes; - out = Hunk_AllocName (count * sizeof (*out), loadname); + out = Hunk_AllocName (count * sizeof (*out), mod->name); - loadmodel->vertexes = out; - loadmodel->numvertexes = count; + mod->vertexes = out; + mod->numvertexes = count; for (i = 0; i < count; i++, in++, out++) VectorCopy (in->point, out->position); } static void -Mod_LoadSubmodels (bsp_t *bsp) +Mod_LoadSubmodels (model_t *mod, bsp_t *bsp) { dmodel_t *in, *out; int count, i, j; in = bsp->models; count = bsp->nummodels; - out = Hunk_AllocName (count * sizeof (*out), loadname); + out = Hunk_AllocName (count * sizeof (*out), mod->name); - loadmodel->submodels = out; - loadmodel->numsubmodels = count; + mod->submodels = out; + mod->numsubmodels = count; for (i = 0; i < count; i++, in++, out++) { static vec3_t offset = {1, 1, 1}; @@ -367,11 +372,11 @@ Mod_LoadSubmodels (bsp_t *bsp) out->numfaces = in->numfaces; } - out = loadmodel->submodels; + out = mod->submodels; if (out->visleafs > MAX_MAP_LEAFS) { Sys_Error ("Mod_LoadSubmodels: too many visleafs (%d, max = %d) in %s", - out->visleafs, MAX_MAP_LEAFS, loadmodel->name); + out->visleafs, MAX_MAP_LEAFS, mod->path); } if (out->visleafs > 8192) @@ -381,7 +386,7 @@ Mod_LoadSubmodels (bsp_t *bsp) } static void -Mod_LoadEdges (bsp_t *bsp) +Mod_LoadEdges (model_t *mod, bsp_t *bsp) { dedge_t *in; int count, i; @@ -389,10 +394,10 @@ Mod_LoadEdges (bsp_t *bsp) in = bsp->edges; count = bsp->numedges; - out = Hunk_AllocName ((count + 1) * sizeof (*out), loadname); + out = Hunk_AllocName ((count + 1) * sizeof (*out), mod->name); - loadmodel->edges = out; - loadmodel->numedges = count; + mod->edges = out; + mod->numedges = count; for (i = 0; i < count; i++, in++, out++) { out->v[0] = in->v[0]; @@ -401,7 +406,7 @@ Mod_LoadEdges (bsp_t *bsp) } static void -Mod_LoadTexinfo (bsp_t *bsp) +Mod_LoadTexinfo (model_t *mod, bsp_t *bsp) { float len1, len2; int count, miptex, i, j; @@ -410,10 +415,10 @@ Mod_LoadTexinfo (bsp_t *bsp) in = bsp->texinfo; count = bsp->numtexinfo; - out = Hunk_AllocName (count * sizeof (*out), loadname); + out = Hunk_AllocName (count * sizeof (*out), mod->name); - loadmodel->texinfo = out; - loadmodel->numtexinfo = count; + mod->texinfo = out; + mod->numtexinfo = count; for (i = 0; i < count; i++, in++, out++) { for (j = 0; j < 4; j++) { @@ -436,13 +441,13 @@ Mod_LoadTexinfo (bsp_t *bsp) miptex = in->miptex; out->flags = in->flags; - if (!loadmodel->textures) { + if (!mod->textures) { out->texture = r_notexture_mip; // checkerboard texture out->flags = 0; } else { - if (miptex >= loadmodel->numtextures) - Sys_Error ("miptex >= loadmodel->numtextures"); - out->texture = loadmodel->textures[miptex]; + if (miptex >= mod->numtextures) + Sys_Error ("miptex >= mod->numtextures"); + out->texture = mod->textures[miptex]; if (!out->texture) { out->texture = r_notexture_mip; // texture not found out->flags = 0; @@ -457,7 +462,7 @@ Mod_LoadTexinfo (bsp_t *bsp) Fills in s->texturemins[] and s->extents[] */ static void -CalcSurfaceExtents (msurface_t *s) +CalcSurfaceExtents (model_t *mod, msurface_t *s) { float mins[2], maxs[2], val; int e, i, j; @@ -471,11 +476,11 @@ CalcSurfaceExtents (msurface_t *s) tex = s->texinfo; for (i = 0; i < s->numedges; i++) { - e = loadmodel->surfedges[s->firstedge + i]; + e = mod->surfedges[s->firstedge + i]; if (e >= 0) - v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; + v = &mod->vertexes[mod->edges[e].v[0]]; else - v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; + v = &mod->vertexes[mod->edges[-e].v[1]]; for (j = 0; j < 2; j++) { val = v->position[0] * tex->vecs[j][0] + @@ -502,7 +507,7 @@ CalcSurfaceExtents (msurface_t *s) } static void -Mod_LoadFaces (bsp_t *bsp) +Mod_LoadFaces (model_t *mod, bsp_t *bsp) { dface_t *in; int count, planenum, side, surfnum, i; @@ -510,15 +515,15 @@ Mod_LoadFaces (bsp_t *bsp) in = bsp->faces; count = bsp->numfaces; - out = Hunk_AllocName (count * sizeof (*out), loadname); + out = Hunk_AllocName (count * sizeof (*out), mod->name); if (count > 32767) { Sys_MaskPrintf (SYS_WARN, "%i faces exceeds standard limit of 32767.\n", count); } - loadmodel->surfaces = out; - loadmodel->numsurfaces = count; + mod->surfaces = out; + mod->numsurfaces = count; for (surfnum = 0; surfnum < count; surfnum++, in++, out++) { out->firstedge = in->firstedge; @@ -530,11 +535,11 @@ Mod_LoadFaces (bsp_t *bsp) if (side) out->flags |= SURF_PLANEBACK; - out->plane = loadmodel->planes + planenum; + out->plane = mod->planes + planenum; - out->texinfo = loadmodel->texinfo + in->texinfo; + out->texinfo = mod->texinfo + in->texinfo; - CalcSurfaceExtents (out); + CalcSurfaceExtents (mod, out); // lighting info @@ -544,7 +549,7 @@ Mod_LoadFaces (bsp_t *bsp) if (i == -1) out->samples = NULL; else - out->samples = loadmodel->lightdata + (i * mod_lightmap_bytes); + out->samples = mod->lightdata + (i * mod_lightmap_bytes); // set the drawing flags flag if (!out->texinfo->texture || !out->texinfo->texture->name) @@ -554,7 +559,7 @@ Mod_LoadFaces (bsp_t *bsp) out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); if (gl_sky_divide && gl_sky_divide->int_val) if (mod_funcs && mod_funcs->Mod_SubdivideSurface) - mod_funcs->Mod_SubdivideSurface (out); + mod_funcs->Mod_SubdivideSurface (mod, out); continue; } @@ -568,7 +573,7 @@ Mod_LoadFaces (bsp_t *bsp) } if (mod_funcs && mod_funcs->Mod_SubdivideSurface) { // cut up polygon for warps - mod_funcs->Mod_SubdivideSurface (out); + mod_funcs->Mod_SubdivideSurface (mod, out); } continue; } @@ -586,7 +591,7 @@ Mod_SetParent (mnode_t *node, mnode_t *parent) } static void -Mod_LoadNodes (bsp_t *bsp) +Mod_LoadNodes (model_t *mod, bsp_t *bsp) { dnode_t *in; int count, i, j, p; @@ -594,15 +599,15 @@ Mod_LoadNodes (bsp_t *bsp) in = bsp->nodes; count = bsp->numnodes; - out = Hunk_AllocName (count * sizeof (*out), loadname); + out = Hunk_AllocName (count * sizeof (*out), mod->name); if (count > 32767) { Sys_MaskPrintf (SYS_WARN, "%i nodes exceeds standard limit of 32767.\n", count); } - loadmodel->nodes = out; - loadmodel->numnodes = count; + mod->nodes = out; + mod->numnodes = count; for (i = 0; i < count; i++, in++, out++) { for (j = 0; j < 3; j++) { @@ -611,7 +616,7 @@ Mod_LoadNodes (bsp_t *bsp) } p = in->planenum; - out->plane = loadmodel->planes + p; + out->plane = mod->planes + p; out->firstsurface = in->firstface; out->numsurfaces = in->numfaces; @@ -620,27 +625,27 @@ Mod_LoadNodes (bsp_t *bsp) p = in->children[j]; // this check is for extended bsp 29 files if (p >= 0) { - out->children[j] = loadmodel->nodes + p; + out->children[j] = mod->nodes + p; } else { p = ~p; - if (p < loadmodel->numleafs) { - out->children[j] = (mnode_t *) (loadmodel->leafs + p); + if (p < mod->numleafs) { + out->children[j] = (mnode_t *) (mod->leafs + p); } else { Sys_Printf ("Mod_LoadNodes: invalid leaf index %i " "(file has only %i leafs)\n", p, - loadmodel->numleafs); + mod->numleafs); //map it to the solid leaf - out->children[j] = (mnode_t *)(loadmodel->leafs); + out->children[j] = (mnode_t *)(mod->leafs); } } } } - Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs + Mod_SetParent (mod->nodes, NULL); // sets nodes and leafs } static void -Mod_LoadLeafs (bsp_t *bsp) +Mod_LoadLeafs (model_t *mod, bsp_t *bsp) { dleaf_t *in; int count, i, j, p; @@ -649,13 +654,13 @@ Mod_LoadLeafs (bsp_t *bsp) in = bsp->leafs; count = bsp->numleafs; - out = Hunk_AllocName (count * sizeof (*out), loadname); + out = Hunk_AllocName (count * sizeof (*out), mod->name); - loadmodel->leafs = out; - loadmodel->numleafs = count; + mod->leafs = out; + mod->numleafs = count; // snprintf(s, sizeof (s), "maps/%s.bsp", // Info_ValueForKey(cl.serverinfo,"map")); - if (!strncmp ("maps/", loadmodel->name, 5)) + if (!strncmp ("maps/", mod->path, 5)) isnotmap = false; for (i = 0; i < count; i++, in++, out++) { for (j = 0; j < 3; j++) { @@ -666,14 +671,14 @@ Mod_LoadLeafs (bsp_t *bsp) p = in->contents; out->contents = p; - out->firstmarksurface = loadmodel->marksurfaces + in->firstmarksurface; + out->firstmarksurface = mod->marksurfaces + in->firstmarksurface; out->nummarksurfaces = in->nummarksurfaces; p = in->visofs; if (p == -1) out->compressed_vis = NULL; else - out->compressed_vis = loadmodel->visdata + p; + out->compressed_vis = mod->visdata + p; out->efrags = NULL; for (j = 0; j < 4; j++) @@ -692,7 +697,7 @@ Mod_LoadLeafs (bsp_t *bsp) } static void -Mod_LoadClipnodes (bsp_t *bsp) +Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) { dclipnode_t *in; mclipnode_t *out; @@ -701,7 +706,7 @@ Mod_LoadClipnodes (bsp_t *bsp) in = bsp->clipnodes; count = bsp->numclipnodes; - out = Hunk_AllocName (count * sizeof (*out), loadname); + out = Hunk_AllocName (count * sizeof (*out), mod->name); if (count > 32767) { Sys_MaskPrintf (SYS_WARN, @@ -709,15 +714,15 @@ Mod_LoadClipnodes (bsp_t *bsp) count); } - loadmodel->clipnodes = out; - loadmodel->numclipnodes = count; + mod->clipnodes = out; + mod->numclipnodes = count; - hull = &loadmodel->hulls[1]; - loadmodel->hull_list[1] = hull; + hull = &mod->hulls[1]; + mod->hull_list[1] = hull; hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count - 1; - hull->planes = loadmodel->planes; + hull->planes = mod->planes; hull->clip_mins[0] = -16; hull->clip_mins[1] = -16; hull->clip_mins[2] = -24; @@ -725,12 +730,12 @@ Mod_LoadClipnodes (bsp_t *bsp) hull->clip_maxs[1] = 16; hull->clip_maxs[2] = 32; - hull = &loadmodel->hulls[2]; - loadmodel->hull_list[2] = hull; + hull = &mod->hulls[2]; + mod->hull_list[2] = hull; hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count - 1; - hull->planes = loadmodel->planes; + hull->planes = mod->planes; hull->clip_mins[0] = -32; hull->clip_mins[1] = -32; hull->clip_mins[2] = -24; @@ -740,7 +745,7 @@ Mod_LoadClipnodes (bsp_t *bsp) for (i = 0; i < count; i++, out++, in++) { out->planenum = in->planenum; - if (out->planenum < 0 || out->planenum >= loadmodel->numplanes) + if (out->planenum < 0 || out->planenum >= mod->numplanes) Sys_Error ("Mod_LoadClipnodes: planenum out of bounds"); out->children[0] = in->children[0]; out->children[1] = in->children[1]; @@ -765,39 +770,39 @@ Mod_LoadClipnodes (bsp_t *bsp) Replicate the drawing hull structure as a clipping hull */ static void -Mod_MakeHull0 (void) +Mod_MakeHull0 (model_t *mod) { mclipnode_t *out; hull_t *hull; int count, i, j; mnode_t *in, *child; - hull = &loadmodel->hulls[0]; - loadmodel->hull_list[0] = hull; + hull = &mod->hulls[0]; + mod->hull_list[0] = hull; - in = loadmodel->nodes; - count = loadmodel->numnodes; - out = Hunk_AllocName (count * sizeof (*out), loadname); + in = mod->nodes; + count = mod->numnodes; + out = Hunk_AllocName (count * sizeof (*out), mod->name); hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count - 1; - hull->planes = loadmodel->planes; + hull->planes = mod->planes; for (i = 0; i < count; i++, out++, in++) { - out->planenum = in->plane - loadmodel->planes; + out->planenum = in->plane - mod->planes; for (j = 0; j < 2; j++) { child = in->children[j]; if (child->contents < 0) out->children[j] = child->contents; else - out->children[j] = child - loadmodel->nodes; + out->children[j] = child - mod->nodes; } } } static void -Mod_LoadMarksurfaces (bsp_t *bsp) +Mod_LoadMarksurfaces (model_t *mod, bsp_t *bsp) { int count, i, j; msurface_t **out; @@ -805,7 +810,7 @@ Mod_LoadMarksurfaces (bsp_t *bsp) in = bsp->marksurfaces; count = bsp->nummarksurfaces; - out = Hunk_AllocName (count * sizeof (*out), loadname); + out = Hunk_AllocName (count * sizeof (*out), mod->name); if (count > 32767) { Sys_MaskPrintf (SYS_WARN, @@ -813,19 +818,19 @@ Mod_LoadMarksurfaces (bsp_t *bsp) count); } - loadmodel->marksurfaces = out; - loadmodel->nummarksurfaces = count; + mod->marksurfaces = out; + mod->nummarksurfaces = count; for (i = 0; i < count; i++) { j = in[i]; - if (j >= loadmodel->numsurfaces) + if (j >= mod->numsurfaces) Sys_Error ("Mod_ParseMarksurfaces: bad surface number"); - out[i] = loadmodel->surfaces + j; + out[i] = mod->surfaces + j; } } static void -Mod_LoadSurfedges (bsp_t *bsp) +Mod_LoadSurfedges (model_t *mod, bsp_t *bsp) { int count, i; int32_t *in; @@ -833,17 +838,17 @@ Mod_LoadSurfedges (bsp_t *bsp) in = bsp->surfedges; count = bsp->numsurfedges; - out = Hunk_AllocName (count * sizeof (*out), loadname); + out = Hunk_AllocName (count * sizeof (*out), mod->name); - loadmodel->surfedges = out; - loadmodel->numsurfedges = count; + mod->surfedges = out; + mod->numsurfedges = count; for (i = 0; i < count; i++) out[i] = in[i]; } static void -Mod_LoadPlanes (bsp_t *bsp) +Mod_LoadPlanes (model_t *mod, bsp_t *bsp) { dplane_t *in; int bits, count, i, j; @@ -851,10 +856,10 @@ Mod_LoadPlanes (bsp_t *bsp) in = bsp->planes; count = bsp->numplanes; - out = Hunk_AllocName (count * 2 * sizeof (*out), loadname); + out = Hunk_AllocName (count * 2 * sizeof (*out), mod->name); - loadmodel->planes = out; - loadmodel->numplanes = count; + mod->planes = out; + mod->numplanes = count; for (i = 0; i < count; i++, in++, out++) { bits = 0; @@ -897,22 +902,22 @@ do_checksums (const bsp_t *bsp, void *_mod) } static void -recurse_draw_tree (mnode_t *node, int depth) +recurse_draw_tree (model_t *mod, mnode_t *node, int depth) { if (!node || node->contents < 0) { - if (depth > loadmodel->depth) - loadmodel->depth = depth; + if (depth > mod->depth) + mod->depth = depth; return; } - recurse_draw_tree (node->children[0], depth + 1); - recurse_draw_tree (node->children[1], depth + 1); + recurse_draw_tree (mod, node->children[0], depth + 1); + recurse_draw_tree (mod, node->children[1], depth + 1); } static void -Mod_FindDrawDepth (void) +Mod_FindDrawDepth (model_t *mod) { - loadmodel->depth = 0; - recurse_draw_tree (loadmodel->nodes, 1); + mod->depth = 0; + recurse_draw_tree (mod, mod->nodes, 1); } void @@ -922,34 +927,34 @@ Mod_LoadBrushModel (model_t *mod, void *buffer) int i, j; bsp_t *bsp; - loadmodel->type = mod_brush; + mod->type = mod_brush; bsp = LoadBSPMem (buffer, qfs_filesize, do_checksums, mod); // load into heap - Mod_LoadVertexes (bsp); - Mod_LoadEdges (bsp); - Mod_LoadSurfedges (bsp); - Mod_LoadTextures (bsp); + Mod_LoadVertexes (mod, bsp); + Mod_LoadEdges (mod, bsp); + Mod_LoadSurfedges (mod, bsp); + Mod_LoadTextures (mod, bsp); if (mod_funcs && mod_funcs->Mod_LoadLighting) { - mod_funcs->Mod_LoadLighting (bsp); + mod_funcs->Mod_LoadLighting (mod, bsp); } - Mod_LoadPlanes (bsp); - Mod_LoadTexinfo (bsp); - Mod_LoadFaces (bsp); - Mod_LoadMarksurfaces (bsp); - Mod_LoadVisibility (bsp); - Mod_LoadLeafs (bsp); - Mod_LoadNodes (bsp); - Mod_LoadClipnodes (bsp); - Mod_LoadEntities (bsp); - Mod_LoadSubmodels (bsp); + Mod_LoadPlanes (mod, bsp); + Mod_LoadTexinfo (mod, bsp); + Mod_LoadFaces (mod, bsp); + Mod_LoadMarksurfaces (mod, bsp); + Mod_LoadVisibility (mod, bsp); + Mod_LoadLeafs (mod, bsp); + Mod_LoadNodes (mod, bsp); + Mod_LoadClipnodes (mod, bsp); + Mod_LoadEntities (mod, bsp); + Mod_LoadSubmodels (mod, bsp); BSP_Free(bsp); - Mod_MakeHull0 (); + Mod_MakeHull0 (mod); - Mod_FindDrawDepth (); + Mod_FindDrawDepth (mod); for (i = 0; i < MAX_MAP_HULLS; i++) Mod_FindClipDepth (&mod->hulls[i]); @@ -984,7 +989,7 @@ Mod_LoadBrushModel (model_t *mod, void *buffer) snprintf (name, sizeof (name), "*%i", i + 1); model_t *m = Mod_FindName (name); *m = *mod; - strcpy (m->name, name); + strcpy (m->path, name); mod = m; // make sure clear is called only for the main model m->clear = 0; diff --git a/libs/models/brush/sw_model_brush.c b/libs/models/brush/sw_model_brush.c index 1f179bab2..65a0e4e48 100644 --- a/libs/models/brush/sw_model_brush.c +++ b/libs/models/brush/sw_model_brush.c @@ -41,13 +41,13 @@ #include "mod_internal.h" void -sw_Mod_LoadLighting (bsp_t *bsp) +sw_Mod_LoadLighting (model_t *mod, bsp_t *bsp) { mod_lightmap_bytes = 1; if (!bsp->lightdatasize) { - loadmodel->lightdata = NULL; + mod->lightdata = NULL; return; } - loadmodel->lightdata = Hunk_AllocName (bsp->lightdatasize, loadname); - memcpy (loadmodel->lightdata, bsp->lightdata, bsp->lightdatasize); + mod->lightdata = Hunk_AllocName (bsp->lightdatasize, mod->name); + memcpy (mod->lightdata, bsp->lightdata, bsp->lightdatasize); } diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index ea08a25a4..ce9fd1e7e 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -63,15 +63,15 @@ static vulktex_t vulkan_notexture = { }; -static void vulkan_brush_clear (model_t *model, void *data) +static void vulkan_brush_clear (model_t *mod, void *data) { modelctx_t *mctx = data; vulkan_ctx_t *ctx = mctx->ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - for (int i = 0; i < model->numtextures; i++) { - texture_t *tx = model->textures[i]; + for (int i = 0; i < mod->numtextures; i++) { + texture_t *tx = mod->textures[i]; if (!tx) { continue; } @@ -173,19 +173,19 @@ copy_mips (qfv_packet_t *packet, texture_t *tx, qfv_tex_t *tex, } static void -load_textures (model_t *model, vulkan_ctx_t *ctx) +load_textures (model_t *mod, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - modelctx_t *mctx = model->data; + modelctx_t *mctx = mod->data; VkImage image = 0; byte *buffer; size_t image_count = 0; size_t copy_count = 0; size_t memsize = 0; - for (int i = 0; i < model->numtextures; i++) { - texture_t *tx = model->textures[i]; + for (int i = 0; i < mod->numtextures; i++) { + texture_t *tx = mod->textures[i]; if (!tx) { continue; } @@ -211,20 +211,18 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, memsize, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - mem, va (ctx->va_ctx, "memory:%s:texture", - loadmodel->name)); + mem, va (ctx->va_ctx, "memory:%s:texture", mod->name)); mctx->texture_memory = mem; qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, va (ctx->va_ctx, - "brush:%s", - loadmodel->name), + "brush:%s", mod->name), memsize, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); buffer = QFV_PacketExtend (packet, memsize); - for (int i = 0; i < model->numtextures; i++) { - texture_t *tx = model->textures[i]; + for (int i = 0; i < mod->numtextures; i++) { + texture_t *tx = mod->textures[i]; byte *palette = vid.palette32; if (!tx) { continue; @@ -249,7 +247,7 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, tex->tex->view, va (ctx->va_ctx, "iview:%s:%s:tex", - loadmodel->name, tx->name)); + mod->name, tx->name)); transfer_mips (buffer + tex->tex->offset, tx + 1, tx, palette); if (tex->glow) { dfunc->vkBindImageMemory (device->dev, tex->glow->image, mem, @@ -263,8 +261,7 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, tex->glow->view, va (ctx->va_ctx, "iview:%s:%s:glow", - loadmodel->name, - tx->name)); + mod->name, tx->name)); transfer_mips (buffer + tex->glow->offset, tex->glow->memory, tx, palette); } @@ -278,8 +275,8 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) __auto_type barriers = QFV_AllocImageBarrierSet (image_count, malloc); barriers->size = 0; - for (int i = 0; i < model->numtextures; i++) { - texture_t *tx = model->textures[i]; + for (int i = 0; i < mod->numtextures; i++) { + texture_t *tx = mod->textures[i]; if (!tx) { continue; } @@ -299,8 +296,8 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, barriers->size, barriers->a); - for (int i = 0, j = 0; i < model->numtextures; i++) { - texture_t *tx = model->textures[i]; + for (int i = 0, j = 0; i < mod->numtextures; i++) { + texture_t *tx = mod->textures[i]; if (!tx) { continue; } @@ -330,19 +327,18 @@ load_textures (model_t *model, vulkan_ctx_t *ctx) } void -Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) +Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; if (!tx) { - modelctx_t *mctx = Hunk_AllocName (sizeof (modelctx_t), - loadmodel->name); + modelctx_t *mctx = Hunk_AllocName (sizeof (modelctx_t), mod->name); mctx->ctx = ctx; - loadmodel->clear = vulkan_brush_clear; - loadmodel->data = mctx; + mod->clear = vulkan_brush_clear; + mod->data = mctx; r_notexture_mip->render = &vulkan_notexture; - load_textures (loadmodel, ctx); + load_textures (mod, ctx); return; } @@ -369,7 +365,7 @@ Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) | VK_IMAGE_USAGE_SAMPLED_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, tex->tex->image, - va (ctx->va_ctx, "image:%s:%s:tex", loadmodel->name, + va (ctx->va_ctx, "image:%s:%s:tex", mod->name, tx->name)); if (layers > 1) { // skys are unlit, so no fullbrights @@ -394,7 +390,7 @@ Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) | VK_IMAGE_USAGE_SAMPLED_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, tex->glow->image, - va (ctx->va_ctx, "image:%s:%s:glow", loadmodel->name, + va (ctx->va_ctx, "image:%s:%s:glow", mod->name, tx->name)); // store the pointer to the fullbright data: memory will never be set to // actual device memory because all of the textures will be loaded in one @@ -403,11 +399,11 @@ Vulkan_Mod_ProcessTexture (texture_t *tx, vulkan_ctx_t *ctx) } void -Vulkan_Mod_LoadLighting (bsp_t *bsp, vulkan_ctx_t *ctx) +Vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp, vulkan_ctx_t *ctx) { mod_lightmap_bytes = 3; if (!bsp->lightdatasize) { - loadmodel->lightdata = NULL; + mod->lightdata = NULL; return; } @@ -417,14 +413,14 @@ Vulkan_Mod_LoadLighting (bsp_t *bsp, vulkan_ctx_t *ctx) int ver; QFile *lit_file; - loadmodel->lightdata = 0; + mod->lightdata = 0; if (mod_lightmap_bytes > 1) { // LordHavoc: check for a .lit file to load dstring_t *litfilename = dstring_new (); - dstring_copystr (litfilename, loadmodel->name); + dstring_copystr (litfilename, mod->name); QFS_StripExtension (litfilename->str, litfilename->str); dstring_appendstr (litfilename, ".lit"); - lit_file = QFS_VOpenFile (litfilename->str, 0, loadmodel->vpath); + lit_file = QFS_VOpenFile (litfilename->str, 0, mod->vpath); data = (byte *) QFS_LoadHunkFile (lit_file); if (data) { if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' @@ -432,7 +428,7 @@ Vulkan_Mod_LoadLighting (bsp_t *bsp, vulkan_ctx_t *ctx) ver = LittleLong (((int32_t *) data)[1]); if (ver == 1) { Sys_MaskPrintf (SYS_DEV, "%s loaded", litfilename->str); - loadmodel->lightdata = data + 8; + mod->lightdata = data + 8; } else { Sys_MaskPrintf (SYS_DEV, "Unknown .lit file version (%d)\n", ver); @@ -443,14 +439,13 @@ Vulkan_Mod_LoadLighting (bsp_t *bsp, vulkan_ctx_t *ctx) } dstring_delete (litfilename); } - if (loadmodel->lightdata || !bsp->lightdatasize) { + if (mod->lightdata || !bsp->lightdatasize) { return; } // LordHavoc: oh well, expand the white lighting data - loadmodel->lightdata = Hunk_AllocName (bsp->lightdatasize * 3, - loadmodel->name); + mod->lightdata = Hunk_AllocName (bsp->lightdatasize * 3, mod->name); in = bsp->lightdata; - out = loadmodel->lightdata; + out = mod->lightdata; for (i = 0; i < bsp->lightdatasize ; i++) { d = *in++; diff --git a/libs/models/clip_hull.c b/libs/models/clip_hull.c index f47c1886d..0a01b62f1 100644 --- a/libs/models/clip_hull.c +++ b/libs/models/clip_hull.c @@ -36,6 +36,7 @@ #include "QF/clip_hull.h" #include "QF/model.h" +#include "mod_internal.h" VISIBLE clip_hull_t * MOD_Alloc_Hull (int nodes, int planes) diff --git a/libs/models/fullbright.c b/libs/models/fullbright.c index 22cef6a83..8d76b9db4 100644 --- a/libs/models/fullbright.c +++ b/libs/models/fullbright.c @@ -31,7 +31,7 @@ # include "config.h" #endif -#include "r_local.h" +#include "mod_internal.h" VISIBLE int Mod_CalcFullbright (const byte *in, byte *out, int pixels) diff --git a/libs/models/gl_model_fullbright.c b/libs/models/gl_model_fullbright.c index f319581ae..ef94e59ca 100644 --- a/libs/models/gl_model_fullbright.c +++ b/libs/models/gl_model_fullbright.c @@ -38,7 +38,7 @@ #include "QF/qendian.h" #include "QF/sys.h" -#include "r_local.h" +#include "mod_internal.h" int Mod_Fullbright (byte *skin, int width, int height, const char *name) diff --git a/libs/models/iqm/model_iqm.c b/libs/models/iqm/model_iqm.c index 4940da557..1091ee7d9 100644 --- a/libs/models/iqm/model_iqm.c +++ b/libs/models/iqm/model_iqm.c @@ -497,25 +497,25 @@ Mod_LoadIQM (model_t *mod, void *buffer) uint32_t *swap; if (!strequal (hdr->magic, IQM_MAGIC)) - Sys_Error ("%s: not an IQM", loadname); + Sys_Error ("%s: not an IQM", mod->path); // Byte swap the header. Everything is the same type, so no problem :) for (swap = &hdr->version; swap <= &hdr->ofs_extensions; swap++) *swap = LittleLong (*swap); //if (hdr->version < 1 || hdr->version > IQM_VERSION) if (hdr->version != IQM_VERSION) - Sys_Error ("%s: unable to handle iqm version %d", loadname, + Sys_Error ("%s: unable to handle iqm version %d", mod->path, hdr->version); if (hdr->filesize != (uint32_t) qfs_filesize) - Sys_Error ("%s: invalid filesize", loadname); + Sys_Error ("%s: invalid filesize", mod->path); iqm = calloc (1, sizeof (iqm_t)); iqm->text = malloc (hdr->num_text); memcpy (iqm->text, (byte *) buffer + hdr->ofs_text, hdr->num_text); mod->aliashdr = (aliashdr_t *) iqm; mod->type = mod_iqm; if (hdr->num_meshes && !load_iqm_meshes (mod, hdr, (byte *) buffer)) - Sys_Error ("%s: error loading meshes", loadname); + Sys_Error ("%s: error loading meshes", mod->path); if (hdr->num_anims && !load_iqm_anims (mod, hdr, (byte *) buffer)) - Sys_Error ("%s: error loading anims", loadname); + Sys_Error ("%s: error loading anims", mod->path); m_funcs->Mod_IQMFinish (mod); } diff --git a/libs/models/model.c b/libs/models/model.c index 8c5036278..7eb606930 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -48,12 +48,10 @@ #include "QF/plugin/vid_render.h" #include "compat.h" +#include "mod_internal.h" vid_model_funcs_t *mod_funcs; -model_t *loadmodel; -char *loadname; // for hunk tags - #define MOD_BLOCK 16 // allocate 16 models at a time model_t **mod_known; int mod_numknown; @@ -75,7 +73,6 @@ Mod_Init (void) int m, x, y; int mip0size = 16*16, mip1size = 8*8, mip2size = 4*4, mip3size = 2*2; - memset (mod_novis, 0xff, sizeof (mod_novis)); r_notexture_mip = Hunk_AllocName (sizeof (texture_t) + mip0size + mip1size + mip2size + mip3size, "notexture"); @@ -145,7 +142,7 @@ Mod_FindName (const char *name) // search the currently loaded models for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) - if (!strcmp ((*mod)->name, name)) + if (!strcmp ((*mod)->path, name)) break; if (i == mod_numknown) { @@ -158,7 +155,7 @@ Mod_FindName (const char *name) mod[i] = mod[0] + i; } memset ((*mod), 0, sizeof (model_t)); - strncpy ((*mod)->name, name, sizeof (*mod)->name - 1); + strncpy ((*mod)->path, name, sizeof (*mod)->path - 1); (*mod)->needload = true; mod_numknown++; Cache_Add (&(*mod)->cache, *mod, Mod_CallbackLoad); @@ -173,17 +170,17 @@ Mod_RealLoadModel (model_t *mod, qboolean crash, cache_allocator_t allocator) uint32_t *buf; // load the file - buf = (uint32_t *) QFS_LoadFile (QFS_FOpenFile (mod->name), 0); + buf = (uint32_t *) QFS_LoadFile (QFS_FOpenFile (mod->path), 0); if (!buf) { if (crash) - Sys_Error ("Mod_LoadModel: %s not found", mod->name); + Sys_Error ("Mod_LoadModel: %s not found", mod->path); return NULL; } - if (loadname) - free (loadname); - loadname = QFS_FileBase (mod->name); - loadmodel = mod; + char *name = QFS_FileBase (mod->path); + strncpy (mod->name, name, sizeof (mod->name - 1)); + mod->name[sizeof (mod->name) - 1] = 0; + free (name); // fill it in mod->vpath = qfs_foundfile.vpath; @@ -204,17 +201,17 @@ Mod_RealLoadModel (model_t *mod, qboolean crash, cache_allocator_t allocator) break; case IDHEADER_MDL: // Type 6: Quake 1 .mdl case HEADER_MDL16: // QF Type 6 extended for 16bit precision - if (strequal (mod->name, "progs/grenade.mdl")) { + if (strequal (mod->path, "progs/grenade.mdl")) { mod->fullbright = 0; mod->shadow_alpha = 255; - } else if (strnequal (mod->name, "progs/flame", 11) - || strnequal (mod->name, "progs/bolt", 10)) { + } else if (strnequal (mod->path, "progs/flame", 11) + || strnequal (mod->path, "progs/bolt", 10)) { mod->fullbright = 1; mod->shadow_alpha = 0; } - if (strnequal (mod->name, "progs/v_", 8)) { + if (strnequal (mod->path, "progs/v_", 8)) { mod->min_light = 0.12; - } else if (strequal (mod->name, "progs/player.mdl")) { + } else if (strequal (mod->path, "progs/player.mdl")) { mod->min_light = 0.04; } if (mod_funcs) @@ -309,7 +306,7 @@ Mod_Print (void) Sys_Printf ("Cached models:\n"); for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) { - Sys_Printf ("%8p : %s\n", (*mod)->cache.data, (*mod)->name); + Sys_Printf ("%8p : %s\n", (*mod)->cache.data, (*mod)->path); } } diff --git a/libs/models/sprite/gl_model_sprite.c b/libs/models/sprite/gl_model_sprite.c index 1d5d1597c..2abef1dfc 100644 --- a/libs/models/sprite/gl_model_sprite.c +++ b/libs/models/sprite/gl_model_sprite.c @@ -44,12 +44,13 @@ #include "mod_internal.h" void -gl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum) +gl_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, + int framenum) { tex_t *targa; const char *name; - targa = LoadImage (name = va (0, "%s_%i", loadmodel->name, framenum), 1); + targa = LoadImage (name = va (0, "%s_%i", mod->path, framenum), 1); if (targa) { if (targa->format < 4) pspriteframe->gl_texturenum = GL_LoadTexture (name, diff --git a/libs/models/sprite/glsl_model_sprite.c b/libs/models/sprite/glsl_model_sprite.c index 138b3d0d0..b5781124f 100644 --- a/libs/models/sprite/glsl_model_sprite.c +++ b/libs/models/sprite/glsl_model_sprite.c @@ -71,12 +71,13 @@ glsl_sprite_clear (model_t *m, void *data) } void -glsl_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum) +glsl_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, + int framenum) { const char *name; - loadmodel->clear = glsl_sprite_clear; - name = va (0, "%s_%i", loadmodel->name, framenum); + mod->clear = glsl_sprite_clear; + name = va (0, "%s_%i", mod->path, framenum); pspriteframe->gl_texturenum = GLSL_LoadQuakeTexture (name, pspriteframe->width, pspriteframe->height, pspriteframe->pixels); diff --git a/libs/models/sprite/model_sprite.c b/libs/models/sprite/model_sprite.c index ce962fec4..e4806bf6e 100644 --- a/libs/models/sprite/model_sprite.c +++ b/libs/models/sprite/model_sprite.c @@ -42,7 +42,8 @@ #include "mod_internal.h" static void * -Mod_LoadSpriteFrame (void *pin, mspriteframe_t **ppframe, int framenum) +Mod_LoadSpriteFrame (model_t *mod, void *pin, mspriteframe_t **ppframe, + int framenum) { dspriteframe_t *pinframe; int width, height, size, origin[2]; @@ -54,7 +55,7 @@ Mod_LoadSpriteFrame (void *pin, mspriteframe_t **ppframe, int framenum) height = LittleLong (pinframe->height); size = width * height; - pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size, loadname); + pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size, mod->name); memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); @@ -72,13 +73,14 @@ Mod_LoadSpriteFrame (void *pin, mspriteframe_t **ppframe, int framenum) memcpy (pspriteframe->pixels, (byte *) (pinframe + 1), size); - m_funcs->Mod_SpriteLoadTexture (pspriteframe, framenum); + m_funcs->Mod_SpriteLoadTexture (mod, pspriteframe, framenum); return (void *) ((byte *) pinframe + sizeof (dspriteframe_t) + size); } static void * -Mod_LoadSpriteGroup (void *pin, mspriteframe_t **ppframe, int framenum) +Mod_LoadSpriteGroup (model_t *mod, void *pin, mspriteframe_t **ppframe, + int framenum) { dspritegroup_t *pingroup; dspriteinterval_t *pin_intervals; @@ -92,7 +94,8 @@ Mod_LoadSpriteGroup (void *pin, mspriteframe_t **ppframe, int framenum) numframes = LittleLong (pingroup->numframes); pspritegroup = Hunk_AllocName (field_offset (mspritegroup_t, - frames[numframes]), loadname); + frames[numframes]), + mod->name); pspritegroup->numframes = numframes; @@ -100,7 +103,7 @@ Mod_LoadSpriteGroup (void *pin, mspriteframe_t **ppframe, int framenum) pin_intervals = (dspriteinterval_t *) (pingroup + 1); - poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); + poutintervals = Hunk_AllocName (numframes * sizeof (float), mod->name); pspritegroup->intervals = poutintervals; @@ -117,7 +120,7 @@ Mod_LoadSpriteGroup (void *pin, mspriteframe_t **ppframe, int framenum) for (i = 0; i < numframes; i++) { ptemp = - Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], + Mod_LoadSpriteFrame (mod, ptemp, &pspritegroup->frames[i], framenum * 100 + i); } @@ -136,14 +139,14 @@ Mod_LoadSpriteModel (model_t *mod, void *buffer) version = LittleLong (pin->version); if (version != SPR_VERSION) - Sys_Error ("%s has wrong version number " - "(%i should be %i)", mod->name, version, SPR_VERSION); + Sys_Error ("%s has wrong version number (%i should be %i)", + mod->path, version, SPR_VERSION); numframes = LittleLong (pin->numframes); size = field_offset (msprite_t, frames[numframes]); - psprite = Hunk_AllocName (size, loadname); + psprite = Hunk_AllocName (size, mod->name); mod->cache.data = psprite; @@ -175,11 +178,11 @@ Mod_LoadSpriteModel (model_t *mod, void *buffer) if (frametype == SPR_SINGLE) { pframetype = (dspriteframetype_t *) - Mod_LoadSpriteFrame (pframetype + 1, + Mod_LoadSpriteFrame (mod, pframetype + 1, &psprite->frames[i].frameptr, i); } else { pframetype = (dspriteframetype_t *) - Mod_LoadSpriteGroup (pframetype + 1, + Mod_LoadSpriteGroup (mod, pframetype + 1, &psprite->frames[i].frameptr, i); } } diff --git a/libs/models/sprite/sw_model_sprite.c b/libs/models/sprite/sw_model_sprite.c index 9d3f25bd2..8dc5a5461 100644 --- a/libs/models/sprite/sw_model_sprite.c +++ b/libs/models/sprite/sw_model_sprite.c @@ -31,6 +31,7 @@ #include "mod_internal.h" void -sw_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum) +sw_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, + int framenum) { } diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index c3b0ddf68..5f510b26c 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -205,7 +205,7 @@ gl_R_ReadPointFile_f (void) vec3_t org; QFile *f; - mapname = strdup (r_worldentity.model->name); + mapname = strdup (r_worldentity.model->path); if (!mapname) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 9dfa3df92..6eed72124 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -585,7 +585,7 @@ gl_overbright_f (cvar_t *var) if (m->type != mod_brush) continue; - if (m->name[0] == '*') + if (m->path[0] == '*') continue; for (j = 0, fa = m->surfaces; j < m->numsurfaces; j++, fa++) { @@ -732,7 +732,7 @@ GL_BuildLightmaps (model_t **models, int num_models) m = models[j]; if (!m) break; - if (m->name[0] == '*') { + if (m->path[0] == '*') { // sub model surfaces are processed as part of the main model continue; } diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index a47e6ba42..5946c98bd 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -226,7 +226,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) for (i = 0; i < num_models; i++) { if (!models[i]) continue; - if (*models[i]->name == '*') + if (*models[i]->path == '*') continue; if (models[i] != r_worldentity.model && models[i]->type == mod_brush) register_textures (models[i]); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 480c647a9..8a6ee73f5 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -436,7 +436,7 @@ glsl_R_RegisterTextures (model_t **models, int num_models) if (!m) continue; // sub-models are done as part of the main model - if (*m->name == '*') + if (*m->path == '*') continue; // world has already been done, not interested in non-brush models if (m == r_worldentity.model || m->type != mod_brush) @@ -561,7 +561,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) if (!m) continue; // sub-models are done as part of the main model - if (*m->name == '*') + if (*m->path == '*') continue; // non-bsp models don't have surfaces. dm = m->submodels; diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index b6f37142b..0776e015e 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -210,7 +210,7 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) m = models[j]; if (!m) break; - if (m->name[0] == '*') { + if (m->path[0] == '*') { // sub model surfaces are processed as part of the main model continue; } @@ -231,7 +231,7 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) m = models[j]; if (!m) break; - if (m->name[0] == '*') { + if (m->path[0] == '*') { // sub model surfaces are processed as part of the main model continue; } diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 5a0dcd43a..139423bb7 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -313,7 +313,7 @@ glsl_R_ReadPointFile_f (void) vec3_t org; QFile *f; - mapname = strdup (r_worldentity.model->name); + mapname = strdup (r_worldentity.model->path); if (!mapname) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index a275873d3..d28e41b04 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -106,7 +106,7 @@ R_AliasCheckBBox (void) frame = currententity->frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { - Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->name); + Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->path); frame = 0; } diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index c05281863..a5be06453 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -83,7 +83,7 @@ R_ReadPointFile_f (void) const char *name; char *mapname; - mapname = strdup (r_worldentity.model->name); + mapname = strdup (r_worldentity.model->path); if (!mapname) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); diff --git a/libs/video/renderer/sw32/sw32_ralias.c b/libs/video/renderer/sw32/sw32_ralias.c index 167730ab1..4ead8055a 100644 --- a/libs/video/renderer/sw32/sw32_ralias.c +++ b/libs/video/renderer/sw32/sw32_ralias.c @@ -109,7 +109,7 @@ sw32_R_AliasCheckBBox (void) frame = currententity->frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { - Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->name); + Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->path); frame = 0; } diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 655467525..1364f5d1b 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -88,7 +88,7 @@ sw32_R_ReadPointFile_f (void) const char *name; char *mapname; - mapname = strdup (r_worldentity.model->name); + mapname = strdup (r_worldentity.model->path); if (!mapname) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index fc8aebc11..3473a92cf 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -401,35 +401,35 @@ vulkan_r_particles_style_f (struct cvar_s *var) } static void -vulkan_Mod_LoadLighting (bsp_t *bsp) +vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp) { - Vulkan_Mod_LoadLighting (bsp, vulkan_ctx); + Vulkan_Mod_LoadLighting (mod, bsp, vulkan_ctx); } static void -vulkan_Mod_SubdivideSurface (msurface_t *fa) +vulkan_Mod_SubdivideSurface (model_t *mod, msurface_t *fa) { } static void -vulkan_Mod_ProcessTexture (texture_t *tx) +vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx) { - Vulkan_Mod_ProcessTexture (tx, vulkan_ctx); + Vulkan_Mod_ProcessTexture (mod, tx, vulkan_ctx); } static void -vulkan_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, +vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, int _s, int extra) { - Vulkan_Mod_MakeAliasModelDisplayLists (m, hdr, _m, _s, extra, vulkan_ctx); + Vulkan_Mod_MakeAliasModelDisplayLists (mod, hdr, _m, _s, extra, vulkan_ctx); } static void * -vulkan_Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc) +vulkan_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, + int gnum, qboolean group, maliasskindesc_t *skindesc) { - return Vulkan_Mod_LoadSkin (skin, skinsize, snum, gnum, group, skindesc, - vulkan_ctx); + return Vulkan_Mod_LoadSkin (mod, skin, skinsize, snum, gnum, group, + skindesc, vulkan_ctx); } static void @@ -449,7 +449,8 @@ vulkan_Mod_IQMFinish (model_t *mod) } static void -vulkan_Mod_SpriteLoadTexture (mspriteframe_t *pspriteframe, int framenum) +vulkan_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, + int framenum) { } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a923f854a..ff64990ee 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -280,7 +280,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!m) continue; // sub-models are done as part of the main model - if (*m->name == '*') + if (*m->path == '*') continue; // world has already been done, not interested in non-brush models if (m == r_worldentity.model || m->type != mod_brush) @@ -421,7 +421,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!m) continue; // sub-models are done as part of the main model - if (*m->name == '*') + if (*m->path == '*') continue; // non-bsp models don't have surfaces. dm = m->submodels; diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 0eeed8546..623bd9d94 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -228,7 +228,7 @@ Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) m = models[j]; if (!m) break; - if (m->name[0] == '*') { + if (m->path[0] == '*') { // sub model surfaces are processed as part of the main model continue; } @@ -251,7 +251,7 @@ Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!m) { break; } - if (m->name[0] == '*') { + if (m->path[0] == '*') { // sub model surfaces are processed as part of the main model continue; } diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 2b264d850..772778b92 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -338,7 +338,7 @@ demo_default_name (const char *argv1) strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim)); // the leading path-name is to be removed from cl.worldmodel->name - mapname = QFS_SkipPath (cl.worldmodel->name); + mapname = QFS_SkipPath (cl.worldmodel->path); // the map name is cut off after any "." because this would prevent // an extension being appended diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 9424a670e..739e4a61c 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -408,7 +408,7 @@ CL_PrintEntities_f (void) continue; } Sys_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n", - ent->model->name, ent->frame, VectorExpand (ent->origin), + ent->model->path, ent->frame, VectorExpand (ent->origin), VectorExpand (ent->angles)); } } diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 60ede5d87..9ee006e3b 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1198,7 +1198,7 @@ SV_SpawnServer (const char *server) ent = EDICT_NUM (&sv_pr_state, 0); memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); ent->free = false; - SVstring (ent, model) = PR_SetString (&sv_pr_state, sv.worldmodel->name); + SVstring (ent, model) = PR_SetString (&sv_pr_state, sv.worldmodel->path); SVfloat (ent, modelindex) = 1; // world model SVfloat (ent, solid) = SOLID_BSP; SVfloat (ent, movetype) = MOVETYPE_PUSH; diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index b6e0049e7..6151b6bd0 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -634,7 +634,7 @@ demo_default_name (const char *argv1) strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim)); // the leading path-name is to be removed from cl.worldmodel->name - mapname = QFS_SkipPath (cl.worldmodel->name); + mapname = QFS_SkipPath (cl.worldmodel->path); // the map name is cut off after any "." because this would prevent // an extension being appended diff --git a/qw/source/sbar.c b/qw/source/sbar.c index a7b3ab415..4a517887e 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -1108,7 +1108,7 @@ Sbar_LogFrags (void) if (t) Qwrite (file, t, strlen (t)); - Qprintf (file, "%s\n%s %s\n", cls.servername->str, cl.worldmodel->name, + Qprintf (file, "%s\n%s %s\n", cls.servername->str, cl.worldmodel->path, cl.levelname); // scores diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 6e8b7bae5..8535dacb6 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -420,7 +420,7 @@ SV_SpawnServer (const char *server) ent = EDICT_NUM (&sv_pr_state, 0); ent->free = false; - SVstring (ent, model) = PR_SetString (&sv_pr_state, sv.worldmodel->name); + SVstring (ent, model) = PR_SetString (&sv_pr_state, sv.worldmodel->path); SVfloat (ent, modelindex) = 1; // world model SVfloat (ent, solid) = SOLID_BSP; SVfloat (ent, movetype) = MOVETYPE_PUSH; diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index b8158cbdb..e8a38606d 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -288,8 +288,8 @@ Team_NewMap (void) died = false; recorded_location = false; - mapname = strdup (cl.worldmodel->name); - t2 = malloc (sizeof (cl.worldmodel->name)); + mapname = strdup (cl.worldmodel->path); + t2 = malloc (sizeof (cl.worldmodel->path)); if (!mapname || !t2) Sys_Error ("Can't duplicate mapname!"); map_to_loc (mapname,t2); @@ -345,10 +345,10 @@ locs_loc (void) } if (Cmd_Argc () >= 3) desc = Cmd_Args (2); - mapname = malloc (sizeof (cl.worldmodel->name)); + mapname = malloc (sizeof (cl.worldmodel->path)); if (!mapname) Sys_Error ("Can't duplicate mapname!"); - map_to_loc (cl.worldmodel->name, mapname); + map_to_loc (cl.worldmodel->path, mapname); snprintf (locfile, sizeof (locfile), "%s/%s", qfs_gamedir->dir.def, mapname); free (mapname); From f02b35a20cfbbd26472600e77fcfd004a30e0e80 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Feb 2021 15:02:42 +0900 Subject: [PATCH 1294/3664] [model] Clean up the model array a little Probably not really necessary, but I think I found a small opportunity for a buffer overflow in there while I was modifying the code, so this is probably better anyway. --- libs/models/model.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/libs/models/model.c b/libs/models/model.c index 7eb606930..4c2d4ac30 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -39,6 +39,7 @@ #endif #include "QF/cvar.h" +#include "QF/darray.h" #include "QF/iqm.h" #include "QF/model.h" #include "QF/qendian.h" @@ -53,9 +54,8 @@ vid_model_funcs_t *mod_funcs; #define MOD_BLOCK 16 // allocate 16 models at a time -model_t **mod_known; -int mod_numknown; -int mod_maxknown; +static struct DARRAY_TYPE (model_t *) mod_known = {0, 0, MOD_BLOCK}; +static size_t mod_numknown; VISIBLE texture_t *r_notexture_mip; @@ -115,10 +115,10 @@ Mod_Init_Cvars (void) VISIBLE void Mod_ClearAll (void) { - int i; + size_t i; model_t **mod; - for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) { + for (i = 0, mod = mod_known.a; i < mod_numknown; i++, mod++) { //FIXME this seems to be correct but need to double check the behavior //with alias models if (!(*mod)->needload && (*mod)->clear) { @@ -134,25 +134,24 @@ Mod_ClearAll (void) model_t * Mod_FindName (const char *name) { - int i; + size_t i; model_t **mod; if (!name[0]) Sys_Error ("Mod_FindName: empty name"); // search the currently loaded models - for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) + for (i = 0, mod = mod_known.a; i < mod_numknown; i++, mod++) if (!strcmp ((*mod)->path, name)) break; if (i == mod_numknown) { - if (mod_numknown == mod_maxknown) { - mod_maxknown += MOD_BLOCK; - mod_known = realloc (mod_known, mod_maxknown * sizeof (model_t *)); - mod = mod_known + mod_numknown; - *mod = calloc (MOD_BLOCK, sizeof (model_t)); - for (i = 1; i < MOD_BLOCK; i++) - mod[i] = mod[0] + i; + if (mod_numknown == mod_known.size) { + model_t *block = calloc (MOD_BLOCK, sizeof (model_t)); + for (i = 0; i < MOD_BLOCK; i++) { + DARRAY_APPEND (&mod_known, &block[i]); + } + mod = &mod_known.a[mod_numknown]; } memset ((*mod), 0, sizeof (model_t)); strncpy ((*mod)->path, name, sizeof (*mod)->path - 1); @@ -301,11 +300,11 @@ Mod_TouchModel (const char *name) VISIBLE void Mod_Print (void) { - int i; + size_t i; model_t **mod; Sys_Printf ("Cached models:\n"); - for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) { + for (i = 0, mod = mod_known.a; i < mod_numknown; i++, mod++) { Sys_Printf ("%8p : %s\n", (*mod)->cache.data, (*mod)->path); } } From 6969adf02c6a7209f70f91d0c8cdd6b73af2b8cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Feb 2021 19:19:18 +0900 Subject: [PATCH 1295/3664] [models] Fix black models with fullbrights in GL I had missed the breakage when I got vulkan alias model skins working. --- libs/models/gl_model_fullbright.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libs/models/gl_model_fullbright.c b/libs/models/gl_model_fullbright.c index ef94e59ca..60df0d50c 100644 --- a/libs/models/gl_model_fullbright.c +++ b/libs/models/gl_model_fullbright.c @@ -55,6 +55,13 @@ Mod_Fullbright (byte *skin, int width, int height, const char *name) // Check for fullbright pixels if (Mod_CalcFullbright (skin, ptexels, pixels)) { + //FIXME black should be transparent for fullbrights (or just fix + //fullbright rendering in gl) + for (int i = 0; i < pixels; i++) { + if (!ptexels[i]) { + ptexels[i] = 255; + } + } Sys_MaskPrintf (SYS_DEV, "FB Model ID: '%s'\n", name); texnum = GL_LoadTexture (name, width, height, ptexels, true, true, 1); } From 34dc7cf2df3253459c951508e61f6a5294b6dca0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Feb 2021 19:31:11 +0900 Subject: [PATCH 1296/3664] [models] Move brush data into its own struct This is a big step towards a cleaner api. The struct reference in model_t really should be a pointer, but bsp submodel(?) loading messed that up, though that's just a matter of taking more care in the loading code. It seems sensible to make that a separate step. --- include/QF/GL/qf_lightmap.h | 2 +- include/QF/GLSL/qf_lightmap.h | 2 +- include/QF/Vulkan/qf_lightmap.h | 3 +- include/QF/model.h | 104 ++++----- include/QF/plugin/vid_render.h | 2 +- include/r_internal.h | 2 +- include/r_local.h | 8 +- libs/models/brush/gl_model_brush.c | 18 +- libs/models/brush/glsl_model_brush.c | 21 +- libs/models/brush/model_brush.c | 222 ++++++++++--------- libs/models/brush/sw_model_brush.c | 6 +- libs/models/brush/vulkan_model_brush.c | 36 +-- libs/video/renderer/gl/gl_lightmap.c | 46 ++-- libs/video/renderer/gl/gl_mod_alias.c | 2 +- libs/video/renderer/gl/gl_rmisc.c | 22 +- libs/video/renderer/gl/gl_rsurf.c | 53 ++--- libs/video/renderer/glsl/glsl_alias.c | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 96 ++++---- libs/video/renderer/glsl/glsl_iqm.c | 2 +- libs/video/renderer/glsl/glsl_lightmap.c | 23 +- libs/video/renderer/glsl/namehack.h | 1 - libs/video/renderer/r_bsp.c | 6 +- libs/video/renderer/r_efrag.c | 4 +- libs/video/renderer/r_light.c | 34 +-- libs/video/renderer/sw/sw_rbsp.c | 40 ++-- libs/video/renderer/sw/sw_rdraw.c | 17 +- libs/video/renderer/sw/sw_rmain.c | 27 ++- libs/video/renderer/sw/sw_rsurf.c | 2 +- libs/video/renderer/sw32/sw32_rbsp.c | 40 ++-- libs/video/renderer/sw32/sw32_rdraw.c | 17 +- libs/video/renderer/sw32/sw32_rmain.c | 28 ++- libs/video/renderer/sw32/sw32_rsurf.c | 2 +- libs/video/renderer/vulkan/vulkan_alias.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 96 ++++---- libs/video/renderer/vulkan/vulkan_lightmap.c | 21 +- nq/source/cl_chase.c | 2 +- nq/source/cl_ents.c | 6 +- nq/source/cl_parse.c | 6 +- nq/source/cl_tent.c | 4 +- nq/source/sv_main.c | 8 +- nq/source/sv_pr_cmds.c | 4 +- nq/source/world.c | 12 +- qw/source/cl_chase.c | 2 +- qw/source/cl_entparse.c | 2 +- qw/source/cl_ents.c | 10 +- qw/source/cl_parse.c | 8 +- qw/source/cl_tent.c | 6 +- qw/source/pmovetst.c | 6 +- qw/source/sv_ents.c | 6 +- qw/source/sv_init.c | 9 +- qw/source/sv_pr_cmds.c | 4 +- qw/source/sv_send.c | 9 +- qw/source/sv_user.c | 9 +- qw/source/world.c | 12 +- 54 files changed, 607 insertions(+), 527 deletions(-) diff --git a/include/QF/GL/qf_lightmap.h b/include/QF/GL/qf_lightmap.h index c048b181a..e0a05d4dd 100644 --- a/include/QF/GL/qf_lightmap.h +++ b/include/QF/GL/qf_lightmap.h @@ -50,6 +50,6 @@ void gl_lightmap_init (void); void GL_BuildLightmaps (struct model_s **models, int num_models); void R_BlendLightmaps (void); void R_CalcLightmaps (void); -extern void (*R_BuildLightMap) (msurface_t *surf); +extern void (*R_BuildLightMap) (mod_brush_t *brush, msurface_t *surf); #endif // __QF_GL_lightmap_h diff --git a/include/QF/GLSL/qf_lightmap.h b/include/QF/GLSL/qf_lightmap.h index 7619ed890..507eaeae6 100644 --- a/include/QF/GLSL/qf_lightmap.h +++ b/include/QF/GLSL/qf_lightmap.h @@ -36,7 +36,7 @@ void glsl_lightmap_init (void); void glsl_R_BuildLightmaps (struct model_s **models, int num_models); void glsl_R_CalcLightmaps (void); -extern void (*glsl_R_BuildLightMap) (msurface_t *surf); +extern void (*glsl_R_BuildLightMap) (mod_brush_t *brush, msurface_t *surf); int glsl_R_LightmapTexture (void) __attribute__((pure)); void glsl_R_FlushLightmaps (void); diff --git a/include/QF/Vulkan/qf_lightmap.h b/include/QF/Vulkan/qf_lightmap.h index 649a5b139..eaca4e35f 100644 --- a/include/QF/Vulkan/qf_lightmap.h +++ b/include/QF/Vulkan/qf_lightmap.h @@ -36,12 +36,13 @@ struct vulkan_ctx_s; struct model_s; +struct mod_brush_s; struct msurface_s; void Vulkan_lightmap_init (struct vulkan_ctx_s *ctx); void Vulkan_BuildLightmaps (struct model_s **models, int num_models, struct vulkan_ctx_s *ctx); void Vulkan_CalcLightmaps (struct vulkan_ctx_s *ctx); -void Vulkan_BuildLightMap (struct msurface_s *surf, struct vulkan_ctx_s *ctx); +void Vulkan_BuildLightMap (struct mod_brush_s *brush, struct msurface_s *surf, struct vulkan_ctx_s *ctx); VkImageView Vulkan_LightmapImageView (struct vulkan_ctx_s *ctx) __attribute__((pure)); void Vulkan_FlushLightmaps (struct vulkan_ctx_s *ctx); diff --git a/include/QF/model.h b/include/QF/model.h index c7fc9190f..6d7dfe61d 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -62,7 +62,6 @@ typedef struct efrag_s { struct efrag_s *entnext; } efrag_t; - // in memory representation =================================================== // !!! if this is changed, it must be changed in asm_draw.h too !!! @@ -228,6 +227,58 @@ typedef struct hull_s { int depth; ///< maximum depth of the tree } hull_t; +typedef struct mod_brush_s { + int firstmodelsurface, nummodelsurfaces; + + int numsubmodels; + dmodel_t *submodels; + + int numplanes; + plane_t *planes; + + int numleafs; // number of visible leafs, not counting 0 + mleaf_t *leafs; + + int numvertexes; + mvertex_t *vertexes; + + int numedges; + medge_t *edges; + + int numnodes; + mnode_t *nodes; + int depth; ///< maximum depth of the tree + + int numtexinfo; + mtexinfo_t *texinfo; + + int numsurfaces; + msurface_t *surfaces; + + int numsurfedges; + int *surfedges; + + int numclipnodes; + mclipnode_t *clipnodes; + + int nummarksurfaces; + msurface_t **marksurfaces; + + hull_t hulls[MAX_MAP_HULLS]; + hull_t *hull_list[MAX_MAP_HULLS]; + + int numtextures; + texture_t **textures; + texture_t *skytexture; + + byte *visdata; + byte *lightdata; + char *entities; //FIXME should not be here + + unsigned int checksum; + unsigned int checksum2; +} mod_brush_t; + // SPRITE MODELS ============================================================== // FIXME: shorten these? @@ -375,55 +426,8 @@ typedef struct model_s { vec3_t clipmins, clipmaxs; // brush model - int firstmodelsurface, nummodelsurfaces; - - int numsubmodels; - dmodel_t *submodels; - - int numplanes; - plane_t *planes; - - int numleafs; // number of visible leafs, not counting 0 - mleaf_t *leafs; - - int numvertexes; - mvertex_t *vertexes; - - int numedges; - medge_t *edges; - - int numnodes; - mnode_t *nodes; - int depth; ///< maximum depth of the tree - - int numtexinfo; - mtexinfo_t *texinfo; - - int numsurfaces; - msurface_t *surfaces; - - int numsurfedges; - int *surfedges; - - int numclipnodes; - mclipnode_t *clipnodes; - - int nummarksurfaces; - msurface_t **marksurfaces; - - hull_t hulls[MAX_MAP_HULLS]; - hull_t *hull_list[MAX_MAP_HULLS]; - - int numtextures; - texture_t **textures; - texture_t *skytexture; - - byte *visdata; - byte *lightdata; - char *entities; - - unsigned int checksum; - unsigned int checksum2; + //FIXME should be a pointer (submodels make things tricky) + mod_brush_t brush; // additional model data cache_user_t cache; diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index cc634e562..bc80780e4 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -149,7 +149,7 @@ typedef struct vid_render_funcs_s { void (*R_ClearState) (void); void (*R_LoadSkys) (const char *); void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); - void (*R_AddEfrags) (entity_t *ent); + void (*R_AddEfrags) (mod_brush_t *brush, entity_t *ent); void (*R_RemoveEfrags) (entity_t *ent); void (*R_EnqueueEntity) (struct entity_s *ent); //FIXME should not be here void (*R_LineGraph) (int x, int y, int *h_vals, int count); diff --git a/include/r_internal.h b/include/r_internal.h index 01c9af001..651946140 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -83,7 +83,7 @@ void R_RenderView (void); // must set r_refdef first void R_ViewChanged (float aspect); // must set r_refdef first // called whenever r_refdef or vid change -void R_AddEfrags (entity_t *ent); +void R_AddEfrags (mod_brush_t *, entity_t *ent); void R_RemoveEfrags (entity_t *ent); void R_NewMap (model_t *worldmodel, model_t **models, int num_models); diff --git a/include/r_local.h b/include/r_local.h index 4a3645ded..9e56b7343 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -182,7 +182,7 @@ void R_RemoveEdges (edge_t *pedge); void R_AddTexture (texture_t *tex); struct vulkan_ctx_s; void R_ClearTextures (void); -void R_InitSurfaceChains (model_t *model); +void R_InitSurfaceChains (mod_brush_t *brush); extern void R_Surf8Start (void); extern void R_Surf8End (void); @@ -303,13 +303,13 @@ void R_ZGraph (void); void R_PrintAliasStats (void); void R_PrintTimes (void); void R_AnimateLight (void); -int R_LightPoint (const vec3_t p); +int R_LightPoint (mod_brush_t *brush, const vec3_t p); void R_SetupFrame (void); void R_cshift_f (void); void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1); void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip); -void R_RecursiveMarkLights (const vec3_t lightorigin, struct dlight_s *light, - int bit, mnode_t *node); +void R_RecursiveMarkLights (mod_brush_t *brush, const vec3_t lightorigin, + struct dlight_s *light, int bit, mnode_t *node); void R_MarkLights (const vec3_t lightorigin, struct dlight_s *light, int bit, model_t *model); diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 05b3c0b94..9585bb108 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -150,9 +150,10 @@ gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp) size_t i; int ver; QFile *lit_file; + mod_brush_t *brush = &mod->brush; dstring_copystr (litfilename, mod->path); - mod->lightdata = NULL; + brush->lightdata = NULL; if (mod_lightmap_bytes > 1) { // LordHavoc: check for a .lit file to load QFS_StripExtension (litfilename->str, litfilename->str); @@ -165,7 +166,7 @@ gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp) ver = LittleLong (((int32_t *) data)[1]); if (ver == 1) { Sys_MaskPrintf (SYS_DEV, "%s loaded", litfilename->str); - mod->lightdata = data + 8; + brush->lightdata = data + 8; return; } else Sys_MaskPrintf (SYS_DEV, @@ -179,10 +180,10 @@ gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp) dstring_delete (litfilename); return; } - mod->lightdata = Hunk_AllocName (bsp->lightdatasize * mod_lightmap_bytes, - litfilename->str); + brush->lightdata = Hunk_AllocName (bsp->lightdatasize * mod_lightmap_bytes, + litfilename->str); in = bsp->lightdata; - out = mod->lightdata; + out = brush->lightdata; if (mod_lightmap_bytes > 1) for (i = 0; i < bsp->lightdatasize ; i++) { @@ -308,18 +309,19 @@ gl_Mod_SubdivideSurface (model_t *mod, msurface_t *fa) float *vec; int lindex, numverts, i; vec3_t verts[64]; + mod_brush_t *brush = &mod->brush; warpface = fa; // convert edges back to a normal polygon numverts = 0; for (i = 0; i < fa->numedges; i++) { - lindex = mod->surfedges[fa->firstedge + i]; + lindex = brush->surfedges[fa->firstedge + i]; if (lindex > 0) - vec = mod->vertexes[mod->edges[lindex].v[0]].position; + vec = brush->vertexes[brush->edges[lindex].v[0]].position; else - vec = mod->vertexes[mod->edges[-lindex].v[1]].position; + vec = brush->vertexes[brush->edges[-lindex].v[1]].position; VectorCopy (vec, verts[numverts]); numverts++; } diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index 3a2717f57..f44327acd 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -65,13 +65,14 @@ static void glsl_brush_clear (model_t *m, void *data) { int i; + mod_brush_t *brush = &m->brush; m->needload = true; - for (i = 0; i < m->numtextures; i++) { + for (i = 0; i < brush->numtextures; i++) { // NOTE: some maps (eg e1m2) have empty texture slots glsltex_t *tex = 0; - if (m->textures[i]) { - tex = m->textures[i]->render; + if (brush->textures[i]) { + tex = brush->textures[i]->render; } if (tex && tex->gl_texturenum) { GLSL_ReleaseTexture (tex->gl_texturenum); @@ -80,10 +81,10 @@ glsl_brush_clear (model_t *m, void *data) tex->gl_texturenum = 0; } } - for (i = 0; i < m->numsurfaces; i++) { - if (m->surfaces[i].polys) { - free (m->surfaces[i].polys); - m->surfaces[i].polys = 0; + for (i = 0; i < brush->numsurfaces; i++) { + if (brush->surfaces[i].polys) { + free (brush->surfaces[i].polys); + brush->surfaces[i].polys = 0; } } } @@ -151,9 +152,9 @@ glsl_Mod_LoadLighting (model_t *mod, bsp_t *bsp) mod->clear = glsl_brush_clear; mod_lightmap_bytes = 1; if (!bsp->lightdatasize) { - mod->lightdata = NULL; + mod->brush.lightdata = NULL; return; } - mod->lightdata = Hunk_AllocName (bsp->lightdatasize, mod->name); - memcpy (mod->lightdata, bsp->lightdata, bsp->lightdatasize); + mod->brush.lightdata = Hunk_AllocName (bsp->lightdatasize, mod->name); + memcpy (mod->brush.lightdata, bsp->lightdata, bsp->lightdatasize); } diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 38a33c893..8a703050d 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -67,10 +67,10 @@ Mod_PointInLeaf (const vec3_t p, model_t *model) mnode_t *node; plane_t *plane; - if (!model || !model->nodes) + if (!model || !model->brush.nodes) Sys_Error ("Mod_PointInLeaf: bad model"); - node = model->nodes; + node = model->brush.nodes; while (1) { if (node->contents < 0) return (mleaf_t *) node; @@ -86,13 +86,13 @@ Mod_PointInLeaf (const vec3_t p, model_t *model) } static inline byte * -Mod_DecompressVis (byte * in, model_t *model) +Mod_DecompressVis (byte * in, mod_brush_t *brush) { static byte decompressed[MAX_MAP_LEAFS / 8]; byte *out; int row, c; - row = (model->numleafs + 7) >> 3; + row = (brush->numleafs + 7) >> 3; out = decompressed; if (!in) { // no vis info, so make all visible @@ -123,13 +123,13 @@ Mod_DecompressVis (byte * in, model_t *model) VISIBLE byte * Mod_LeafPVS (mleaf_t *leaf, model_t *model) { - if (leaf == model->leafs) { + if (leaf == model->brush.leafs) { if (!mod_novis[0]) { memset (mod_novis, 0xff, sizeof (mod_novis)); } return mod_novis; } - return Mod_DecompressVis (leaf->compressed_vis, model); + return Mod_DecompressVis (leaf->compressed_vis, &model->brush); } // BRUSHMODEL LOADING ========================================================= @@ -170,16 +170,17 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) miptex_t *mt; texture_t *tx, *tx2; texture_t *anims[10], *altanims[10]; + mod_brush_t *brush = &mod->brush; if (!bsp->texdatasize) { - mod->textures = NULL; + brush->textures = NULL; return; } m = (dmiptexlump_t *) bsp->texdata; - mod->numtextures = m->nummiptex; - mod->textures = Hunk_AllocName (m->nummiptex * sizeof (*mod->textures), - mod->name); + brush->numtextures = m->nummiptex; + brush->textures = Hunk_AllocName (m->nummiptex * sizeof (*brush->textures), + mod->name); for (i = 0; i < m->nummiptex; i++) { if (m->dataofs[i] == -1) @@ -195,10 +196,10 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) pixels = mt->width * mt->height / 64 * 85; tx = Hunk_AllocName (sizeof (texture_t) + pixels, mod->name); - mod->textures[i] = tx; + brush->textures[i] = tx; tx->name = strndup(mt->name, sizeof (mt->name)); - mod_unique_miptex_name (mod->textures, tx, i); + mod_unique_miptex_name (brush->textures, tx, i); tx->width = mt->width; tx->height = mt->height; for (j = 0; j < MIPLEVELS; j++) @@ -208,7 +209,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) memcpy (tx + 1, mt + 1, pixels); if (!strncmp (mt->name, "sky", 3)) - mod->skytexture = tx; + brush->skytexture = tx; } if (mod_funcs && mod_funcs->Mod_ProcessTexture) { size_t render_size = mod_funcs->texture_render_size; @@ -218,7 +219,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) mod->name); } for (i = 0; i < m->nummiptex; i++) { - tx = mod->textures[i]; + tx = brush->textures[i]; tx->render = render_data; render_data += render_size; mod_funcs->Mod_ProcessTexture (mod, tx); @@ -229,7 +230,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) // sequence the animations for (i = 0; i < m->nummiptex; i++) { - tx = mod->textures[i]; + tx = brush->textures[i]; if (!tx || tx->name[0] != '+') continue; if (tx->anim_next) @@ -256,7 +257,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) Sys_Error ("Bad animating texture %s", tx->name); for (j = i + 1; j < m->nummiptex; j++) { - tx2 = mod->textures[j]; + tx2 = brush->textures[j]; if (!tx2 || tx2->name[0] != '+') continue; if (strcmp (tx2->name + 2, tx->name + 2)) @@ -310,22 +311,22 @@ static void Mod_LoadVisibility (model_t *mod, bsp_t *bsp) { if (!bsp->visdatasize) { - mod->visdata = NULL; + mod->brush.visdata = NULL; return; } - mod->visdata = Hunk_AllocName (bsp->visdatasize, mod->name); - memcpy (mod->visdata, bsp->visdata, bsp->visdatasize); + mod->brush.visdata = Hunk_AllocName (bsp->visdatasize, mod->name); + memcpy (mod->brush.visdata, bsp->visdata, bsp->visdatasize); } static void Mod_LoadEntities (model_t *mod, bsp_t *bsp) { if (!bsp->entdatasize) { - mod->entities = NULL; + mod->brush.entities = NULL; return; } - mod->entities = Hunk_AllocName (bsp->entdatasize, mod->name); - memcpy (mod->entities, bsp->entdata, bsp->entdatasize); + mod->brush.entities = Hunk_AllocName (bsp->entdatasize, mod->name); + memcpy (mod->brush.entities, bsp->entdata, bsp->entdatasize); } static void @@ -339,8 +340,8 @@ Mod_LoadVertexes (model_t *mod, bsp_t *bsp) count = bsp->numvertexes; out = Hunk_AllocName (count * sizeof (*out), mod->name); - mod->vertexes = out; - mod->numvertexes = count; + mod->brush.vertexes = out; + mod->brush.numvertexes = count; for (i = 0; i < count; i++, in++, out++) VectorCopy (in->point, out->position); @@ -351,13 +352,14 @@ Mod_LoadSubmodels (model_t *mod, bsp_t *bsp) { dmodel_t *in, *out; int count, i, j; + mod_brush_t *brush = &mod->brush; in = bsp->models; count = bsp->nummodels; out = Hunk_AllocName (count * sizeof (*out), mod->name); - mod->submodels = out; - mod->numsubmodels = count; + brush->submodels = out; + brush->numsubmodels = count; for (i = 0; i < count; i++, in++, out++) { static vec3_t offset = {1, 1, 1}; @@ -372,7 +374,7 @@ Mod_LoadSubmodels (model_t *mod, bsp_t *bsp) out->numfaces = in->numfaces; } - out = mod->submodels; + out = brush->submodels; if (out->visleafs > MAX_MAP_LEAFS) { Sys_Error ("Mod_LoadSubmodels: too many visleafs (%d, max = %d) in %s", @@ -396,8 +398,8 @@ Mod_LoadEdges (model_t *mod, bsp_t *bsp) count = bsp->numedges; out = Hunk_AllocName ((count + 1) * sizeof (*out), mod->name); - mod->edges = out; - mod->numedges = count; + mod->brush.edges = out; + mod->brush.numedges = count; for (i = 0; i < count; i++, in++, out++) { out->v[0] = in->v[0]; @@ -417,8 +419,8 @@ Mod_LoadTexinfo (model_t *mod, bsp_t *bsp) count = bsp->numtexinfo; out = Hunk_AllocName (count * sizeof (*out), mod->name); - mod->texinfo = out; - mod->numtexinfo = count; + mod->brush.texinfo = out; + mod->brush.numtexinfo = count; for (i = 0; i < count; i++, in++, out++) { for (j = 0; j < 4; j++) { @@ -441,13 +443,13 @@ Mod_LoadTexinfo (model_t *mod, bsp_t *bsp) miptex = in->miptex; out->flags = in->flags; - if (!mod->textures) { + if (!mod->brush.textures) { out->texture = r_notexture_mip; // checkerboard texture out->flags = 0; } else { - if (miptex >= mod->numtextures) - Sys_Error ("miptex >= mod->numtextures"); - out->texture = mod->textures[miptex]; + if (miptex >= mod->brush.numtextures) + Sys_Error ("miptex >= mod->brush.numtextures"); + out->texture = mod->brush.textures[miptex]; if (!out->texture) { out->texture = r_notexture_mip; // texture not found out->flags = 0; @@ -469,6 +471,7 @@ CalcSurfaceExtents (model_t *mod, msurface_t *s) int bmins[2], bmaxs[2]; mtexinfo_t *tex; mvertex_t *v; + mod_brush_t *brush = &mod->brush; mins[0] = mins[1] = 999999; maxs[0] = maxs[1] = -99999; @@ -476,11 +479,11 @@ CalcSurfaceExtents (model_t *mod, msurface_t *s) tex = s->texinfo; for (i = 0; i < s->numedges; i++) { - e = mod->surfedges[s->firstedge + i]; + e = brush->surfedges[s->firstedge + i]; if (e >= 0) - v = &mod->vertexes[mod->edges[e].v[0]]; + v = &brush->vertexes[brush->edges[e].v[0]]; else - v = &mod->vertexes[mod->edges[-e].v[1]]; + v = &brush->vertexes[brush->edges[-e].v[1]]; for (j = 0; j < 2; j++) { val = v->position[0] * tex->vecs[j][0] + @@ -512,6 +515,7 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) dface_t *in; int count, planenum, side, surfnum, i; msurface_t *out; + mod_brush_t *brush = &mod->brush; in = bsp->faces; count = bsp->numfaces; @@ -522,8 +526,8 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) "%i faces exceeds standard limit of 32767.\n", count); } - mod->surfaces = out; - mod->numsurfaces = count; + brush->surfaces = out; + brush->numsurfaces = count; for (surfnum = 0; surfnum < count; surfnum++, in++, out++) { out->firstedge = in->firstedge; @@ -535,9 +539,9 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) if (side) out->flags |= SURF_PLANEBACK; - out->plane = mod->planes + planenum; + out->plane = brush->planes + planenum; - out->texinfo = mod->texinfo + in->texinfo; + out->texinfo = brush->texinfo + in->texinfo; CalcSurfaceExtents (mod, out); @@ -549,7 +553,7 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) if (i == -1) out->samples = NULL; else - out->samples = mod->lightdata + (i * mod_lightmap_bytes); + out->samples = brush->lightdata + (i * mod_lightmap_bytes); // set the drawing flags flag if (!out->texinfo->texture || !out->texinfo->texture->name) @@ -596,6 +600,7 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) dnode_t *in; int count, i, j, p; mnode_t *out; + mod_brush_t *brush = &mod->brush; in = bsp->nodes; count = bsp->numnodes; @@ -606,8 +611,8 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) "%i nodes exceeds standard limit of 32767.\n", count); } - mod->nodes = out; - mod->numnodes = count; + brush->nodes = out; + brush->numnodes = count; for (i = 0; i < count; i++, in++, out++) { for (j = 0; j < 3; j++) { @@ -616,7 +621,7 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) } p = in->planenum; - out->plane = mod->planes + p; + out->plane = brush->planes + p; out->firstsurface = in->firstface; out->numsurfaces = in->numfaces; @@ -625,23 +630,23 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) p = in->children[j]; // this check is for extended bsp 29 files if (p >= 0) { - out->children[j] = mod->nodes + p; + out->children[j] = brush->nodes + p; } else { p = ~p; - if (p < mod->numleafs) { - out->children[j] = (mnode_t *) (mod->leafs + p); + if (p < brush->numleafs) { + out->children[j] = (mnode_t *) (brush->leafs + p); } else { Sys_Printf ("Mod_LoadNodes: invalid leaf index %i " "(file has only %i leafs)\n", p, - mod->numleafs); + brush->numleafs); //map it to the solid leaf - out->children[j] = (mnode_t *)(mod->leafs); + out->children[j] = (mnode_t *)(brush->leafs); } } } } - Mod_SetParent (mod->nodes, NULL); // sets nodes and leafs + Mod_SetParent (brush->nodes, NULL); // sets nodes and leafs } static void @@ -651,13 +656,14 @@ Mod_LoadLeafs (model_t *mod, bsp_t *bsp) int count, i, j, p; mleaf_t *out; qboolean isnotmap = true; + mod_brush_t *brush = &mod->brush; in = bsp->leafs; count = bsp->numleafs; out = Hunk_AllocName (count * sizeof (*out), mod->name); - mod->leafs = out; - mod->numleafs = count; + brush->leafs = out; + brush->numleafs = count; // snprintf(s, sizeof (s), "maps/%s.bsp", // Info_ValueForKey(cl.serverinfo,"map")); if (!strncmp ("maps/", mod->path, 5)) @@ -671,14 +677,14 @@ Mod_LoadLeafs (model_t *mod, bsp_t *bsp) p = in->contents; out->contents = p; - out->firstmarksurface = mod->marksurfaces + in->firstmarksurface; + out->firstmarksurface = brush->marksurfaces + in->firstmarksurface; out->nummarksurfaces = in->nummarksurfaces; p = in->visofs; if (p == -1) out->compressed_vis = NULL; else - out->compressed_vis = mod->visdata + p; + out->compressed_vis = brush->visdata + p; out->efrags = NULL; for (j = 0; j < 4; j++) @@ -703,6 +709,7 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) mclipnode_t *out; hull_t *hull; int count, i; + mod_brush_t *brush = &mod->brush; in = bsp->clipnodes; count = bsp->numclipnodes; @@ -714,15 +721,15 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) count); } - mod->clipnodes = out; - mod->numclipnodes = count; + brush->clipnodes = out; + brush->numclipnodes = count; - hull = &mod->hulls[1]; - mod->hull_list[1] = hull; + hull = &brush->hulls[1]; + brush->hull_list[1] = hull; hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count - 1; - hull->planes = mod->planes; + hull->planes = brush->planes; hull->clip_mins[0] = -16; hull->clip_mins[1] = -16; hull->clip_mins[2] = -24; @@ -730,12 +737,12 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) hull->clip_maxs[1] = 16; hull->clip_maxs[2] = 32; - hull = &mod->hulls[2]; - mod->hull_list[2] = hull; + hull = &brush->hulls[2]; + brush->hull_list[2] = hull; hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count - 1; - hull->planes = mod->planes; + hull->planes = brush->planes; hull->clip_mins[0] = -32; hull->clip_mins[1] = -32; hull->clip_mins[2] = -24; @@ -745,7 +752,7 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) for (i = 0; i < count; i++, out++, in++) { out->planenum = in->planenum; - if (out->planenum < 0 || out->planenum >= mod->numplanes) + if (out->planenum < 0 || out->planenum >= brush->numplanes) Sys_Error ("Mod_LoadClipnodes: planenum out of bounds"); out->children[0] = in->children[0]; out->children[1] = in->children[1]; @@ -776,27 +783,28 @@ Mod_MakeHull0 (model_t *mod) hull_t *hull; int count, i, j; mnode_t *in, *child; + mod_brush_t *brush = &mod->brush; - hull = &mod->hulls[0]; - mod->hull_list[0] = hull; + hull = &brush->hulls[0]; + brush->hull_list[0] = hull; - in = mod->nodes; - count = mod->numnodes; + in = brush->nodes; + count = brush->numnodes; out = Hunk_AllocName (count * sizeof (*out), mod->name); hull->clipnodes = out; hull->firstclipnode = 0; hull->lastclipnode = count - 1; - hull->planes = mod->planes; + hull->planes = brush->planes; for (i = 0; i < count; i++, out++, in++) { - out->planenum = in->plane - mod->planes; + out->planenum = in->plane - brush->planes; for (j = 0; j < 2; j++) { child = in->children[j]; if (child->contents < 0) out->children[j] = child->contents; else - out->children[j] = child - mod->nodes; + out->children[j] = child - brush->nodes; } } } @@ -807,6 +815,7 @@ Mod_LoadMarksurfaces (model_t *mod, bsp_t *bsp) int count, i, j; msurface_t **out; uint32_t *in; + mod_brush_t *brush = &mod->brush; in = bsp->marksurfaces; count = bsp->nummarksurfaces; @@ -818,14 +827,14 @@ Mod_LoadMarksurfaces (model_t *mod, bsp_t *bsp) count); } - mod->marksurfaces = out; - mod->nummarksurfaces = count; + brush->marksurfaces = out; + brush->nummarksurfaces = count; for (i = 0; i < count; i++) { j = in[i]; - if (j >= mod->numsurfaces) + if (j >= brush->numsurfaces) Sys_Error ("Mod_ParseMarksurfaces: bad surface number"); - out[i] = mod->surfaces + j; + out[i] = brush->surfaces + j; } } @@ -835,13 +844,14 @@ Mod_LoadSurfedges (model_t *mod, bsp_t *bsp) int count, i; int32_t *in; int *out; + mod_brush_t *brush = &mod->brush; in = bsp->surfedges; count = bsp->numsurfedges; out = Hunk_AllocName (count * sizeof (*out), mod->name); - mod->surfedges = out; - mod->numsurfedges = count; + brush->surfedges = out; + brush->numsurfedges = count; for (i = 0; i < count; i++) out[i] = in[i]; @@ -853,13 +863,14 @@ Mod_LoadPlanes (model_t *mod, bsp_t *bsp) dplane_t *in; int bits, count, i, j; plane_t *out; + mod_brush_t *brush = &mod->brush; in = bsp->planes; count = bsp->numplanes; out = Hunk_AllocName (count * 2 * sizeof (*out), mod->name); - mod->planes = out; - mod->numplanes = count; + brush->planes = out; + brush->numplanes = count; for (i = 0; i < count; i++, in++, out++) { bits = 0; @@ -881,12 +892,13 @@ do_checksums (const bsp_t *bsp, void *_mod) int i; model_t *mod = (model_t *) _mod; byte *base; + mod_brush_t *brush = &mod->brush; base = (byte *) bsp->header; // checksum all of the map, except for entities - mod->checksum = 0; - mod->checksum2 = 0; + brush->checksum = 0; + brush->checksum2 = 0; for (i = 0; i < HEADER_LUMPS; i++) { lump_t *lump = bsp->header->lumps + i; int csum; @@ -894,30 +906,30 @@ do_checksums (const bsp_t *bsp, void *_mod) if (i == LUMP_ENTITIES) continue; csum = Com_BlockChecksum (base + lump->fileofs, lump->filelen); - mod->checksum ^= csum; + brush->checksum ^= csum; if (i != LUMP_VISIBILITY && i != LUMP_LEAFS && i != LUMP_NODES) - mod->checksum2 ^= csum; + brush->checksum2 ^= csum; } } static void -recurse_draw_tree (model_t *mod, mnode_t *node, int depth) +recurse_draw_tree (mod_brush_t *brush, mnode_t *node, int depth) { if (!node || node->contents < 0) { - if (depth > mod->depth) - mod->depth = depth; + if (depth > brush->depth) + brush->depth = depth; return; } - recurse_draw_tree (mod, node->children[0], depth + 1); - recurse_draw_tree (mod, node->children[1], depth + 1); + recurse_draw_tree (brush, node->children[0], depth + 1); + recurse_draw_tree (brush, node->children[1], depth + 1); } static void -Mod_FindDrawDepth (model_t *mod) +Mod_FindDrawDepth (mod_brush_t *brush) { - mod->depth = 0; - recurse_draw_tree (mod, mod->nodes, 1); + brush->depth = 0; + recurse_draw_tree (brush, brush->nodes, 1); } void @@ -954,35 +966,35 @@ Mod_LoadBrushModel (model_t *mod, void *buffer) Mod_MakeHull0 (mod); - Mod_FindDrawDepth (mod); + Mod_FindDrawDepth (&mod->brush); for (i = 0; i < MAX_MAP_HULLS; i++) - Mod_FindClipDepth (&mod->hulls[i]); + Mod_FindClipDepth (&mod->brush.hulls[i]); mod->numframes = 2; // regular and alternate animation // set up the submodels (FIXME: this is confusing) - for (i = 0; i < mod->numsubmodels; i++) { - bm = &mod->submodels[i]; + for (i = 0; i < mod->brush.numsubmodels; i++) { + bm = &mod->brush.submodels[i]; - mod->hulls[0].firstclipnode = bm->headnode[0]; - mod->hull_list[0] = &mod->hulls[0]; + mod->brush.hulls[0].firstclipnode = bm->headnode[0]; + mod->brush.hull_list[0] = &mod->brush.hulls[0]; for (j = 1; j < MAX_MAP_HULLS; j++) { - mod->hulls[j].firstclipnode = bm->headnode[j]; - mod->hulls[j].lastclipnode = mod->numclipnodes - 1; - mod->hull_list[j] = &mod->hulls[j]; + mod->brush.hulls[j].firstclipnode = bm->headnode[j]; + mod->brush.hulls[j].lastclipnode = mod->brush.numclipnodes - 1; + mod->brush.hull_list[j] = &mod->brush.hulls[j]; } - mod->firstmodelsurface = bm->firstface; - mod->nummodelsurfaces = bm->numfaces; + mod->brush.firstmodelsurface = bm->firstface; + mod->brush.nummodelsurfaces = bm->numfaces; VectorCopy (bm->maxs, mod->maxs); VectorCopy (bm->mins, mod->mins); mod->radius = RadiusFromBounds (mod->mins, mod->maxs); - mod->numleafs = bm->visleafs; + mod->brush.numleafs = bm->visleafs; - if (i < mod->numsubmodels - 1) { + if (i < mod->brush.numsubmodels - 1) { // duplicate the basic information char name[12]; diff --git a/libs/models/brush/sw_model_brush.c b/libs/models/brush/sw_model_brush.c index 65a0e4e48..84080d49d 100644 --- a/libs/models/brush/sw_model_brush.c +++ b/libs/models/brush/sw_model_brush.c @@ -45,9 +45,9 @@ sw_Mod_LoadLighting (model_t *mod, bsp_t *bsp) { mod_lightmap_bytes = 1; if (!bsp->lightdatasize) { - mod->lightdata = NULL; + mod->brush.lightdata = NULL; return; } - mod->lightdata = Hunk_AllocName (bsp->lightdatasize, mod->name); - memcpy (mod->lightdata, bsp->lightdata, bsp->lightdatasize); + mod->brush.lightdata = Hunk_AllocName (bsp->lightdatasize, mod->name); + memcpy (mod->brush.lightdata, bsp->lightdata, bsp->lightdatasize); } diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index ce9fd1e7e..55eacb90b 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -69,9 +69,10 @@ static void vulkan_brush_clear (model_t *mod, void *data) vulkan_ctx_t *ctx = mctx->ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + mod_brush_t *brush = &mod->brush; - for (int i = 0; i < mod->numtextures; i++) { - texture_t *tx = mod->textures[i]; + for (int i = 0; i < brush->numtextures; i++) { + texture_t *tx = brush->textures[i]; if (!tx) { continue; } @@ -180,12 +181,13 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) modelctx_t *mctx = mod->data; VkImage image = 0; byte *buffer; + mod_brush_t *brush = &mod->brush; size_t image_count = 0; size_t copy_count = 0; size_t memsize = 0; - for (int i = 0; i < mod->numtextures; i++) { - texture_t *tx = mod->textures[i]; + for (int i = 0; i < brush->numtextures; i++) { + texture_t *tx = brush->textures[i]; if (!tx) { continue; } @@ -221,8 +223,8 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) qfv_packet_t *packet = QFV_PacketAcquire (stage); buffer = QFV_PacketExtend (packet, memsize); - for (int i = 0; i < mod->numtextures; i++) { - texture_t *tx = mod->textures[i]; + for (int i = 0; i < brush->numtextures; i++) { + texture_t *tx = brush->textures[i]; byte *palette = vid.palette32; if (!tx) { continue; @@ -275,8 +277,8 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) __auto_type barriers = QFV_AllocImageBarrierSet (image_count, malloc); barriers->size = 0; - for (int i = 0; i < mod->numtextures; i++) { - texture_t *tx = mod->textures[i]; + for (int i = 0; i < brush->numtextures; i++) { + texture_t *tx = brush->textures[i]; if (!tx) { continue; } @@ -296,8 +298,8 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, barriers->size, barriers->a); - for (int i = 0, j = 0; i < mod->numtextures; i++) { - texture_t *tx = mod->textures[i]; + for (int i = 0, j = 0; i < brush->numtextures; i++) { + texture_t *tx = brush->textures[i]; if (!tx) { continue; } @@ -401,9 +403,11 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) void Vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp, vulkan_ctx_t *ctx) { + mod_brush_t *brush = &mod->brush; + mod_lightmap_bytes = 3; if (!bsp->lightdatasize) { - mod->lightdata = NULL; + brush->lightdata = NULL; return; } @@ -413,7 +417,7 @@ Vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp, vulkan_ctx_t *ctx) int ver; QFile *lit_file; - mod->lightdata = 0; + brush->lightdata = 0; if (mod_lightmap_bytes > 1) { // LordHavoc: check for a .lit file to load dstring_t *litfilename = dstring_new (); @@ -428,7 +432,7 @@ Vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp, vulkan_ctx_t *ctx) ver = LittleLong (((int32_t *) data)[1]); if (ver == 1) { Sys_MaskPrintf (SYS_DEV, "%s loaded", litfilename->str); - mod->lightdata = data + 8; + brush->lightdata = data + 8; } else { Sys_MaskPrintf (SYS_DEV, "Unknown .lit file version (%d)\n", ver); @@ -439,13 +443,13 @@ Vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp, vulkan_ctx_t *ctx) } dstring_delete (litfilename); } - if (mod->lightdata || !bsp->lightdatasize) { + if (brush->lightdata || !bsp->lightdatasize) { return; } // LordHavoc: oh well, expand the white lighting data - mod->lightdata = Hunk_AllocName (bsp->lightdatasize * 3, mod->name); + brush->lightdata = Hunk_AllocName (bsp->lightdatasize * 3, mod->name); in = bsp->lightdata; - out = mod->lightdata; + out = brush->lightdata; for (i = 0; i < bsp->lightdatasize ; i++) { d = *in++; diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 6eed72124..c6270f5d4 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -74,7 +74,7 @@ glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; static int lmshift = 7; -void (*gl_R_BuildLightMap) (msurface_t *surf); +void (*gl_R_BuildLightMap) (mod_brush_t *brush, msurface_t *surf); extern void gl_multitexture_f (cvar_t *var); @@ -240,7 +240,7 @@ R_AddDynamicLights_3 (msurface_t *surf) } static void -R_BuildLightMap_1 (msurface_t *surf) +R_BuildLightMap_1 (mod_brush_t *brush, msurface_t *surf) { byte *dest; int maps, size, stride, smax, tmax, i, j; @@ -254,7 +254,7 @@ R_BuildLightMap_1 (msurface_t *surf) size = smax * tmax * gl_internalformat; // set to full bright if no light data - if (!r_worldentity.model->lightdata) { + if (!brush->lightdata) { memset (&blocklights[0], 0xff, size * sizeof(int)); goto store; } @@ -300,7 +300,7 @@ R_BuildLightMap_1 (msurface_t *surf) } static void -R_BuildLightMap_3 (msurface_t *surf) +R_BuildLightMap_3 (mod_brush_t *brush, msurface_t *surf) { byte *dest; int maps, size, stride, smax, tmax, i, j; @@ -314,7 +314,7 @@ R_BuildLightMap_3 (msurface_t *surf) size = smax * tmax * gl_internalformat; // set to full bright if no light data - if (!r_worldentity.model->lightdata) { + if (!brush->lightdata) { memset (&blocklights[0], 0xff, size * sizeof(int)); goto store; } @@ -365,7 +365,7 @@ R_BuildLightMap_3 (msurface_t *surf) } static void -R_BuildLightMap_4 (msurface_t *surf) +R_BuildLightMap_4 (mod_brush_t *brush, msurface_t *surf) { byte *dest; int maps, size, smax, tmax, i, j, stride; @@ -379,7 +379,7 @@ R_BuildLightMap_4 (msurface_t *surf) size = smax * tmax * gl_internalformat; // set to full bright if no light data - if (!r_worldentity.model->lightdata) { + if (!brush->lightdata) { memset (&blocklights[0], 0xff, size * sizeof(int)); goto store; } @@ -535,6 +535,7 @@ gl_overbright_f (cvar_t *var) model_t *m; msurface_t *fa; entity_t *ent; + mod_brush_t *brush; if (!var) return; @@ -588,7 +589,8 @@ gl_overbright_f (cvar_t *var) if (m->path[0] == '*') continue; - for (j = 0, fa = m->surfaces; j < m->numsurfaces; j++, fa++) { + brush = &m->brush; + for (j = 0, fa = brush->surfaces; j < brush->numsurfaces; j++, fa++) { if (fa->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) continue; @@ -599,13 +601,13 @@ gl_overbright_f (cvar_t *var) gl_lightmap_rectchange[num].w = BLOCK_WIDTH; gl_lightmap_rectchange[num].h = BLOCK_HEIGHT; - gl_R_BuildLightMap (fa); + gl_R_BuildLightMap (brush, fa); } } - m = r_worldentity.model; + brush = &r_worldentity.model->brush; - for (i = 0, fa = m->surfaces; i < m->numsurfaces; i++, fa++) { + for (i = 0, fa = brush->surfaces; i < brush->numsurfaces; i++, fa++) { if (fa->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) continue; @@ -616,7 +618,7 @@ gl_overbright_f (cvar_t *var) gl_lightmap_rectchange[num].w = BLOCK_WIDTH; gl_lightmap_rectchange[num].h = BLOCK_HEIGHT; - gl_R_BuildLightMap (fa); + gl_R_BuildLightMap (brush, fa); } } @@ -665,7 +667,7 @@ AllocBlock (int w, int h, int *x, int *y) } static void -GL_CreateSurfaceLightmap (msurface_t *surf) +GL_CreateSurfaceLightmap (mod_brush_t *brush, msurface_t *surf) { int smax, tmax; @@ -677,7 +679,7 @@ GL_CreateSurfaceLightmap (msurface_t *surf) surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t); - gl_R_BuildLightMap (surf); + gl_R_BuildLightMap (brush, surf); } /* @@ -690,6 +692,7 @@ GL_BuildLightmaps (model_t **models, int num_models) { int i, j; model_t *m; + mod_brush_t *brush; memset (allocated, 0, sizeof (allocated)); @@ -732,21 +735,22 @@ GL_BuildLightmaps (model_t **models, int num_models) m = models[j]; if (!m) break; - if (m->path[0] == '*') { + if (m->path[0] == '*' || m->type != mod_brush) { // sub model surfaces are processed as part of the main model continue; } - r_pcurrentvertbase = m->vertexes; + brush = &m->brush; + r_pcurrentvertbase = brush->vertexes; gl_currentmodel = m; // non-bsp models don't have surfaces. - for (i = 0; i < m->numsurfaces; i++) { - if (m->surfaces[i].flags & SURF_DRAWTURB) + for (i = 0; i < brush->numsurfaces; i++) { + if (brush->surfaces[i].flags & SURF_DRAWTURB) continue; - if (gl_sky_divide->int_val && (m->surfaces[i].flags & + if (gl_sky_divide->int_val && (brush->surfaces[i].flags & SURF_DRAWSKY)) continue; - GL_CreateSurfaceLightmap (m->surfaces + i); - GL_BuildSurfaceDisplayList (m->surfaces + i); + GL_CreateSurfaceLightmap (brush, brush->surfaces + i); + GL_BuildSurfaceDisplayList (brush->surfaces + i); } } diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 44a114ff5..d47a1504f 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -436,7 +436,7 @@ gl_R_DrawAliasModel (entity_t *e) float lightadj; // get lighting information - R_LightPoint (e->origin); + R_LightPoint (&r_worldentity.model->brush, e->origin); lightadj = (ambientcolor[0] + ambientcolor[1] + ambientcolor[2]) / 765.0; diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 5946c98bd..5c61fd70d 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -167,13 +167,13 @@ gl_R_Init (void) } static void -register_textures (model_t *model) +register_textures (mod_brush_t *brush) { int i; texture_t *tex; - for (i = 0; i < model->numtextures; i++) { - tex = model->textures[i]; + for (i = 0; i < brush->numtextures; i++) { + tex = brush->textures[i]; if (!tex) continue; gl_R_AddTexture (tex); @@ -185,18 +185,20 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) { int i; texture_t *tex; + mod_brush_t *brush; for (i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value memset (&r_worldentity, 0, sizeof (r_worldentity)); r_worldentity.model = worldmodel; + brush = &worldmodel->brush; R_FreeAllEntities (); // clear out efrags in case the level hasn't been reloaded - for (i = 0; i < r_worldentity.model->numleafs; i++) - r_worldentity.model->leafs[i].efrags = NULL; + for (i = 0; i < brush->numleafs; i++) + brush->leafs[i].efrags = NULL; // Force a vis update r_viewleaf = NULL; @@ -209,8 +211,8 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) // identify sky texture gl_mirrortexturenum = -1; gl_R_ClearTextures (); - for (i = 0; i < r_worldentity.model->numtextures; i++) { - tex = r_worldentity.model->textures[i]; + for (i = 0; i < brush->numtextures; i++) { + tex = brush->textures[i]; if (!tex) continue; if (!strncmp (tex->name, "sky", 3)) { @@ -220,16 +222,16 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) gl_mirrortexturenum = i; } - gl_R_InitSurfaceChains (r_worldentity.model); + gl_R_InitSurfaceChains (brush); gl_R_AddTexture (r_notexture_mip); - register_textures (r_worldentity.model); + register_textures (brush); for (i = 0; i < num_models; i++) { if (!models[i]) continue; if (*models[i]->path == '*') continue; if (models[i] != r_worldentity.model && models[i]->type == mod_brush) - register_textures (models[i]); + register_textures (&models[i]->brush); } } diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index f673e4cc4..acd9f4ad3 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -146,15 +146,15 @@ gl_R_AddTexture (texture_t *tx) } void -gl_R_InitSurfaceChains (model_t *model) +gl_R_InitSurfaceChains (mod_brush_t *brush) { int i; if (static_chains) free (static_chains); - static_chains = calloc (model->nummodelsurfaces, sizeof (instsurf_t)); - for (i = 0; i < model->nummodelsurfaces; i++) - model->surfaces[i].instsurf = static_chains + i; + static_chains = calloc (brush->nummodelsurfaces, sizeof (instsurf_t)); + for (i = 0; i < brush->nummodelsurfaces; i++) + brush->surfaces[i].instsurf = static_chains + i; release_instsurfs (); } @@ -267,7 +267,7 @@ R_RenderBrushPoly_1 (msurface_t *fa) } static inline void -R_AddToLightmapChain (msurface_t *fa) +R_AddToLightmapChain (mod_brush_t *brush, msurface_t *fa) { int maps, smax, tmax; glRect_t *theRect; @@ -306,7 +306,7 @@ R_AddToLightmapChain (msurface_t *fa) theRect->w = (fa->light_s - theRect->l) + smax; if ((theRect->h + theRect->t) < (fa->light_t + tmax)) theRect->h = (fa->light_t - theRect->t) + tmax; - gl_R_BuildLightMap (fa); + gl_R_BuildLightMap (brush, fa); } } } @@ -490,7 +490,8 @@ clear_texture_chains (void) } static inline void -chain_surface (msurface_t *surf, vec_t *transform, float *color) +chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, + float *color) { instsurf_t *sc; @@ -509,7 +510,7 @@ chain_surface (msurface_t *surf, vec_t *transform, float *color) tex = tx->render; CHAIN_SURF_F2B (surf, tex->tex_chain); - R_AddToLightmapChain (surf); + R_AddToLightmapChain (brush, surf); } if (!(sc = surf->instsurf)) sc = surf->tinst; @@ -528,8 +529,10 @@ gl_R_DrawBrushModel (entity_t *e) msurface_t *psurf; qboolean rotated; vec3_t mins, maxs; + mod_brush_t *brush; model = e->model; + brush = &model->brush; if (e->transform[0] != 1 || e->transform[5] != 1 || e->transform[10] != 1) { rotated = true; @@ -565,7 +568,7 @@ gl_R_DrawBrushModel (entity_t *e) } // calculate dynamic lighting for bmodel if it's not an instanced model - if (model->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { + if (brush->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { vec3_t lightorigin; for (k = 0; k < r_maxdlights; k++) { @@ -574,8 +577,8 @@ gl_R_DrawBrushModel (entity_t *e) continue; VectorSubtract (r_dlights[k].origin, e->origin, lightorigin); - R_RecursiveMarkLights (lightorigin, &r_dlights[k], k, - model->nodes + model->hulls[0].firstclipnode); + R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, + brush->nodes + brush->hulls[0].firstclipnode); } } @@ -584,10 +587,10 @@ gl_R_DrawBrushModel (entity_t *e) qfglGetFloatv (GL_MODELVIEW_MATRIX, e->full_transform); qfglPopMatrix (); - psurf = &model->surfaces[model->firstmodelsurface]; + psurf = &brush->surfaces[brush->firstmodelsurface]; // draw texture - for (i = 0; i < model->nummodelsurfaces; i++, psurf++) { + for (i = 0; i < brush->nummodelsurfaces; i++, psurf++) { // find which side of the node we are on pplane = psurf->plane; @@ -596,7 +599,7 @@ gl_R_DrawBrushModel (entity_t *e) // draw the polygon if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (psurf, e->full_transform, e->colormod); + chain_surface (brush, psurf, e->full_transform, e->colormod); } } } @@ -623,7 +626,7 @@ get_side (mnode_t *node) } static inline void -visit_node (mnode_t *node, int side) +visit_node (mod_brush_t *brush, mnode_t *node, int side) { int c; msurface_t *surf; @@ -632,7 +635,7 @@ visit_node (mnode_t *node, int side) side = (~side + 1) & SURF_PLANEBACK; // draw stuff if ((c = node->numsurfaces)) { - surf = r_worldentity.model->surfaces + node->firstsurface; + surf = brush->surfaces + node->firstsurface; for (; c; c--, surf++) { if (surf->visframe != r_visframecount) continue; @@ -641,7 +644,7 @@ visit_node (mnode_t *node, int side) if (side ^ (surf->flags & SURF_PLANEBACK)) continue; // wrong side - chain_surface (surf, 0, 0); + chain_surface (brush, surf, 0, 0); } } } @@ -659,7 +662,7 @@ test_node (mnode_t *node) } static void -R_VisitWorldNodes (model_t *model) +R_VisitWorldNodes (mod_brush_t *brush) { typedef struct { mnode_t *node; @@ -671,9 +674,9 @@ R_VisitWorldNodes (model_t *model) mnode_t *front; int side; - node = model->nodes; + node = brush->nodes; // +2 for paranoia - node_stack = alloca ((model->depth + 2) * sizeof (rstack_t)); + node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_ptr = node_stack; while (1) { @@ -689,7 +692,7 @@ R_VisitWorldNodes (model_t *model) } if (front->contents < 0 && front->contents != CONTENTS_SOLID) visit_leaf ((mleaf_t *) front); - visit_node (node, side); + visit_node (brush, node, side); node = node->children[!side]; } if (node->contents < 0 && node->contents != CONTENTS_SOLID) @@ -698,7 +701,7 @@ R_VisitWorldNodes (model_t *model) node_ptr--; node = node_ptr->node; side = node_ptr->side; - visit_node (node, side); + visit_node (brush, node, side); node = node->children[!side]; continue; } @@ -726,7 +729,7 @@ gl_R_DrawWorld (void) gl_R_DrawSky (); } - R_VisitWorldNodes (r_worldentity.model); + R_VisitWorldNodes (&r_worldentity.model->brush); if (r_drawentities->int_val) { entity_t *ent; for (ent = r_ent_queue; ent; ent = ent->next) { @@ -821,7 +824,7 @@ GL_BuildSurfaceDisplayList (msurface_t *fa) medge_t *pedges, *r_pedge; // reconstruct the polygon - pedges = gl_currentmodel->edges; + pedges = gl_currentmodel->brush.edges; lnumverts = fa->numedges; // draw texture @@ -833,7 +836,7 @@ GL_BuildSurfaceDisplayList (msurface_t *fa) poly->numverts = lnumverts; for (i = 0; i < lnumverts; i++) { - lindex = gl_currentmodel->surfedges[fa->firstedge + i]; + lindex = gl_currentmodel->brush.surfedges[fa->firstedge + i]; if (lindex > 0) { r_pedge = &pedges[lindex]; diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 155845450..3cbf4f89d 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -159,7 +159,7 @@ calc_lighting (entity_t *ent, float *ambient, float *shadelight, int light; VectorSet ( -1, 0, 0, lightvec); //FIXME - light = R_LightPoint (ent->origin); + light = R_LightPoint (&r_worldentity.model->brush, ent->origin); *ambient = max (light, max (ent->model->min_light, ent->min_light) * 128); *shadelight = *ambient; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 8a6ee73f5..3b5ed0cd4 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -311,17 +311,17 @@ glsl_R_AddTexture (texture_t *tx) tex->elechain_tail = &tex->elechain; } -void -glsl_R_InitSurfaceChains (model_t *model) +static void +glsl_R_InitSurfaceChains (mod_brush_t *brush) { int i; release_static_instsurfs (); release_instsurfs (); - for (i = 0; i < model->nummodelsurfaces; i++) { - model->surfaces[i].instsurf = get_static_instsurf (); - model->surfaces[i].instsurf->surface = &model->surfaces[i]; + for (i = 0; i < brush->nummodelsurfaces; i++) { + brush->surfaces[i].instsurf = get_static_instsurf (); + brush->surfaces[i].instsurf->surface = &brush->surfaces[i]; } } @@ -358,7 +358,7 @@ glsl_R_ClearElements (void) } static void -update_lightmap (msurface_t *surf) +update_lightmap (mod_brush_t *brush, msurface_t *surf) { int maps; @@ -369,12 +369,13 @@ update_lightmap (msurface_t *surf) if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { dynamic: if (r_dynamic->int_val) - glsl_R_BuildLightMap (surf); + glsl_R_BuildLightMap (brush, surf); } } static inline void -chain_surface (msurface_t *surf, vec_t *transform, float *color) +chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, + float *color) { instsurf_t *is; @@ -393,7 +394,7 @@ chain_surface (msurface_t *surf, vec_t *transform, float *color) tex = tx->render; CHAIN_SURF_F2B (surf, tex->tex_chain); - update_lightmap (surf); + update_lightmap (brush, surf); } if (!(is = surf->instsurf)) is = surf->tinst; @@ -402,13 +403,13 @@ chain_surface (msurface_t *surf, vec_t *transform, float *color) } static void -register_textures (model_t *model) +register_textures (mod_brush_t *brush) { int i; texture_t *tex; - for (i = 0; i < model->numtextures; i++) { - tex = model->textures[i]; + for (i = 0; i < brush->numtextures; i++) { + tex = brush->textures[i]; if (!tex) continue; glsl_R_AddTexture (tex); @@ -426,11 +427,12 @@ glsl_R_RegisterTextures (model_t **models, int num_models) { int i; model_t *m; + mod_brush_t *brush; glsl_R_ClearTextures (); - glsl_R_InitSurfaceChains (r_worldentity.model); + glsl_R_InitSurfaceChains (&r_worldentity.model->brush); glsl_R_AddTexture (r_notexture_mip); - register_textures (r_worldentity.model); + register_textures (&r_worldentity.model->brush); for (i = 0; i < num_models; i++) { m = models[i]; if (!m) @@ -441,8 +443,9 @@ glsl_R_RegisterTextures (model_t **models, int num_models) // world has already been done, not interested in non-brush models if (m == r_worldentity.model || m->type != mod_brush) continue; - m->numsubmodels = 1; // no support for submodels in non-world model - register_textures (m); + brush = &m->brush; + brush->numsubmodels = 1; // no support for submodels in non-world model + register_textures (brush); } } @@ -478,16 +481,17 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, glslpoly_t *poly; GLushort *ind; float s, t; + mod_brush_t *brush; if (fa->ec_index < 0) { - vertices = models[-fa->ec_index - 1]->vertexes; - edges = models[-fa->ec_index - 1]->edges; - surfedges = models[-fa->ec_index - 1]->surfedges; + brush = &models[-fa->ec_index - 1]->brush; } else { - vertices = r_worldentity.model->vertexes; - edges = r_worldentity.model->edges; - surfedges = r_worldentity.model->surfedges; + brush = &r_worldentity.model->brush; } + vertices = brush->vertexes; + edges = brush->edges; + surfedges = brush->surfedges; + numverts = fa->numedges; numtris = numverts - 2; numindices = numtris * 3; @@ -545,6 +549,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) dmodel_t *dm; msurface_t *surf; dstring_t *vertices; + mod_brush_t *brush; QuatSet (0, 0, sqrt(0.5), sqrt(0.5), sky_fix); // proper skies QuatSet (0, 0, 0, 1, sky_rotation[0]); @@ -561,24 +566,25 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) if (!m) continue; // sub-models are done as part of the main model - if (*m->path == '*') + if (*m->path == '*' || m->type != mod_brush) continue; + brush = &m->brush; // non-bsp models don't have surfaces. - dm = m->submodels; - for (j = 0; j < m->numsurfaces; j++) { + dm = brush->submodels; + for (j = 0; j < brush->numsurfaces; j++) { glsltex_t *tex; if (j == dm->firstface + dm->numfaces) { dm++; - if (dm - m->submodels == m->numsubmodels) { + if (dm - brush->submodels == brush->numsubmodels) { // limit the surfaces // probably never hit Sys_Printf ("R_BuildDisplayLists: too many surfaces\n"); - m->numsurfaces = j; + brush->numsurfaces = j; break; } } - surf = m->surfaces + j; - surf->ec_index = dm - m->submodels; + surf = brush->surfaces + j; + surf->ec_index = dm - brush->submodels; if (!surf->ec_index && m != r_worldentity.model) surf->ec_index = -1 - i; // instanced model tex = surf->texinfo->texture->render; @@ -654,8 +660,10 @@ R_DrawBrushModel (entity_t *e) msurface_t *surf; qboolean rotated; vec3_t mins, maxs, org; + mod_brush_t *brush; model = e->model; + brush = &model->brush; if (e->transform[0] != 1 || e->transform[5] != 1 || e->transform[10] != 1) { rotated = true; radius = model->radius; @@ -680,7 +688,7 @@ R_DrawBrushModel (entity_t *e) } // calculate dynamic lighting for bmodel if it's not an instanced model - if (model->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { + if (brush->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { vec3_t lightorigin; for (k = 0; k < r_maxdlights; k++) { @@ -689,14 +697,14 @@ R_DrawBrushModel (entity_t *e) continue; VectorSubtract (r_dlights[k].origin, e->origin, lightorigin); - R_RecursiveMarkLights (lightorigin, &r_dlights[k], k, - model->nodes + model->hulls[0].firstclipnode); + R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, + brush->nodes + brush->hulls[0].firstclipnode); } } - surf = &model->surfaces[model->firstmodelsurface]; + surf = &brush->surfaces[brush->firstmodelsurface]; - for (i = 0; i < model->nummodelsurfaces; i++, surf++) { + for (i = 0; i < brush->nummodelsurfaces; i++, surf++) { // find the node side on which we are plane = surf->plane; @@ -705,7 +713,7 @@ R_DrawBrushModel (entity_t *e) // enqueue the polygon if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (surf, e->transform, e->colormod); + chain_surface (brush, surf, e->transform, e->colormod); } } } @@ -730,7 +738,7 @@ get_side (mnode_t *node) } static inline void -visit_node (mnode_t *node, int side) +visit_node (mod_brush_t *brush, mnode_t *node, int side) { int c; msurface_t *surf; @@ -739,7 +747,7 @@ visit_node (mnode_t *node, int side) side = (~side + 1) & SURF_PLANEBACK; // draw stuff if ((c = node->numsurfaces)) { - surf = r_worldentity.model->surfaces + node->firstsurface; + surf = brush->surfaces + node->firstsurface; for (; c; c--, surf++) { if (surf->visframe != r_visframecount) continue; @@ -748,7 +756,7 @@ visit_node (mnode_t *node, int side) if (side ^ (surf->flags & SURF_PLANEBACK)) continue; // wrong side - chain_surface (surf, 0, 0); + chain_surface (brush, surf, 0, 0); } } } @@ -766,7 +774,7 @@ test_node (mnode_t *node) } static void -R_VisitWorldNodes (model_t *model) +R_VisitWorldNodes (mod_brush_t *brush) { typedef struct { mnode_t *node; @@ -778,9 +786,9 @@ R_VisitWorldNodes (model_t *model) mnode_t *front; int side; - node = model->nodes; + node = brush->nodes; // +2 for paranoia - node_stack = alloca ((model->depth + 2) * sizeof (rstack_t)); + node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_ptr = node_stack; while (1) { @@ -796,7 +804,7 @@ R_VisitWorldNodes (model_t *model) } if (front->contents < 0 && front->contents != CONTENTS_SOLID) visit_leaf ((mleaf_t *) front); - visit_node (node, side); + visit_node (brush, node, side); node = node->children[!side]; } if (node->contents < 0 && node->contents != CONTENTS_SOLID) @@ -805,7 +813,7 @@ R_VisitWorldNodes (model_t *model) node_ptr--; node = node_ptr->node; side = node_ptr->side; - visit_node (node, side); + visit_node (brush, node, side); node = node->children[!side]; continue; } @@ -1123,7 +1131,7 @@ glsl_R_DrawWorld (void) currententity = &worldent; - R_VisitWorldNodes (worldent.model); + R_VisitWorldNodes (&worldent.model->brush); if (r_drawentities->int_val) { entity_t *ent; for (ent = r_ent_queue; ent; ent = ent->next) { diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index e757cf087..ce2c2f31d 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -217,7 +217,7 @@ glsl_R_DrawIQM (void) float blend; iqmframe_t *frame; - R_LightPoint (ent->origin); //FIXME min_light? + R_LightPoint (&r_worldentity.model->brush, ent->origin);//FIXME min_light? VectorScale (ambientcolor, 1/255.0, ambientcolor); R_FindNearLights (ent->origin, MAX_IQM_LIGHTS, lights); diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index 0776e015e..65af9d238 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -61,7 +61,7 @@ static scrap_t *light_scrap; static unsigned *blocklights; static int bl_extents[2]; -void (*glsl_R_BuildLightMap) (msurface_t *surf); +void (*glsl_R_BuildLightMap) (mod_brush_t *brush, msurface_t *surf); static void R_AddDynamicLights_1 (msurface_t *surf) @@ -121,7 +121,7 @@ R_AddDynamicLights_1 (msurface_t *surf) } static void -R_BuildLightMap_1 (msurface_t *surf) +R_BuildLightMap_1 (mod_brush_t *brush, msurface_t *surf) { int smax, tmax, size; unsigned scale; @@ -138,7 +138,7 @@ R_BuildLightMap_1 (msurface_t *surf) // clear to no light memset (blocklights, 0, size * sizeof (blocklights[0])); - if (!r_worldentity.model->lightdata) { + if (!brush->lightdata) { // because we by-pass the inversion, "no light" = "full bright" GLSL_SubpicUpdate (surf->lightpic, (byte *) blocklights, 1); return; @@ -196,6 +196,7 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) { int i, j, size; model_t *m; + mod_brush_t *brush; //FIXME RGB support if (!light_scrap) { @@ -210,13 +211,14 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) m = models[j]; if (!m) break; - if (m->path[0] == '*') { + if (m->path[0] == '*' || m->type != mod_brush) { // sub model surfaces are processed as part of the main model continue; } + brush = &m->brush; // non-bsp models don't have surfaces. - for (i = 0; i < m->numsurfaces; i++) { - msurface_t *surf = m->surfaces + i; + for (i = 0; i < brush->numsurfaces; i++) { + msurface_t *surf = brush->surfaces + i; surf->lightpic = 0; // paranoia if (surf->flags & SURF_DRAWTURB) continue; @@ -231,15 +233,16 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) m = models[j]; if (!m) break; - if (m->path[0] == '*') { + if (m->path[0] == '*' || m->type != mod_brush) { // sub model surfaces are processed as part of the main model continue; } + brush = &m->brush; // non-bsp models don't have surfaces. - for (i = 0; i < m->numsurfaces; i++) { - msurface_t *surf = m->surfaces + i; + for (i = 0; i < brush->numsurfaces; i++) { + msurface_t *surf = brush->surfaces + i; if (surf->lightpic) - glsl_R_BuildLightMap (surf); + glsl_R_BuildLightMap (brush, surf); } } } diff --git a/libs/video/renderer/glsl/namehack.h b/libs/video/renderer/glsl/namehack.h index aed6d2e21..a6f62e701 100644 --- a/libs/video/renderer/glsl/namehack.h +++ b/libs/video/renderer/glsl/namehack.h @@ -52,7 +52,6 @@ #define R_InitParticles glsl_R_InitParticles #define R_InitSky glsl_R_InitSky #define R_InitSprites glsl_R_InitSprites -#define R_InitSurfaceChains glsl_R_InitSurfaceChains #define R_LineGraph glsl_R_LineGraph #define R_LoadSky_f glsl_R_LoadSky_f #define R_LoadSkys glsl_R_LoadSkys diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index a6fdc961d..2475873a5 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -67,13 +67,13 @@ R_MarkLeaves (void) r_oldviewleaf = 0; // so vis will be recalcualted when novis gets // turned off vis = solid; - memset (solid, 0xff, (r_worldentity.model->numleafs + 7) >> 3); + memset (solid, 0xff, (r_worldentity.model->brush.numleafs + 7) >> 3); } else vis = Mod_LeafPVS (r_viewleaf, r_worldentity.model); - for (i = 0; (int) i < r_worldentity.model->numleafs; i++) { + for (i = 0; (int) i < r_worldentity.model->brush.numleafs; i++) { if (vis[i >> 3] & (1 << (i & 7))) { - leaf = &r_worldentity.model->leafs[i + 1]; + leaf = &r_worldentity.model->brush.leafs[i + 1]; if ((c = leaf->nummarksurfaces)) { mark = leaf->firstmarksurface; do { diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index ae5e1fd8a..8785d3d7d 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -195,7 +195,7 @@ R_SplitEntityOnNode (mnode_t *node) } void -R_AddEfrags (entity_t *ent) +R_AddEfrags (mod_brush_t *brush, entity_t *ent) { model_t *entmodel; @@ -215,7 +215,7 @@ R_AddEfrags (entity_t *ent) VectorAdd (ent->origin, entmodel->mins, r_emins); VectorAdd (ent->origin, entmodel->maxs, r_emaxs); - R_SplitEntityOnNode (r_worldentity.model->nodes); + R_SplitEntityOnNode (brush->nodes); ent->topnode = r_pefragtopnode; } diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index bd242e7bc..8d3294c37 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -203,8 +203,8 @@ mark_surfaces (msurface_t *surf, const vec3_t lightorigin, dlight_t *light, // LordHavoc: heavily modified, to eliminate unnecessary texture uploads, // and support bmodel lighting better void -R_RecursiveMarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, - mnode_t *node) +R_RecursiveMarkLights (mod_brush_t *brush, const vec3_t lightorigin, + dlight_t *light, int lightnum, mnode_t *node) { unsigned i; float ndist, maxdist; @@ -240,14 +240,14 @@ loc0: } // mark the polygons - surf = r_worldentity.model->surfaces + node->firstsurface; + surf = brush->surfaces + node->firstsurface; for (i = 0; i < node->numsurfaces; i++, surf++) { mark_surfaces (surf, lightorigin, light, lightnum); } if (node->children[0]->contents >= 0) { if (node->children[1]->contents >= 0) - R_RecursiveMarkLights (lightorigin, light, lightnum, + R_RecursiveMarkLights (brush, lightorigin, light, lightnum, node->children[1]); node = node->children[0]; goto loc0; @@ -262,11 +262,12 @@ void R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, model_t *model) { + mod_brush_t *brush = &model->brush; mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model); if (!pvsleaf->compressed_vis) { - mnode_t *node = model->nodes + model->hulls[0].firstclipnode; - R_RecursiveMarkLights (lightorigin, light, lightnum, node); + mnode_t *node = brush->nodes + brush->hulls[0].firstclipnode; + R_RecursiveMarkLights (brush, lightorigin, light, lightnum, node); } else { float radius = light->radius; vec3_t mins, maxs; @@ -280,16 +281,16 @@ R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, maxs[0] = lightorigin[0] + radius; maxs[1] = lightorigin[1] + radius; maxs[2] = lightorigin[2] + radius; - while (leafnum < model->numleafs) { + while (leafnum < brush->numleafs) { int b; if (!(vis_bits = *in++)) { leafnum += (*in++) * 8; continue; } - for (b = 1; b < 256 && leafnum < model->numleafs; + for (b = 1; b < 256 && leafnum < brush->numleafs; b <<= 1, leafnum++) { int m; - mleaf_t *leaf = &model->leafs[leafnum + 1]; + mleaf_t *leaf = &brush->leafs[leafnum + 1]; if (!(vis_bits & b)) continue; if (leaf->visframe != r_visframecount) @@ -400,7 +401,8 @@ calc_lighting_3 (msurface_t *surf, int ds, int dt) } static int -RecursiveLightPoint (mnode_t *node, const vec3_t start, const vec3_t end) +RecursiveLightPoint (mod_brush_t *brush, mnode_t *node, const vec3_t start, + const vec3_t end) { unsigned i; int r, s, t, ds, dt, side; @@ -430,7 +432,7 @@ loop: mid[2] = start[2] + (end[2] - start[2]) * frac; // go down front side - r = RecursiveLightPoint (node->children[side], start, mid); + r = RecursiveLightPoint (brush, node->children[side], start, mid); if (r >= 0) return r; // hit something @@ -441,7 +443,7 @@ loop: VectorCopy (mid, lightspot); lightplane = plane; - surf = r_worldentity.model->surfaces + node->firstsurface; + surf = brush->surfaces + node->firstsurface; for (i = 0; i < node->numsurfaces; i++, surf++) { if (surf->flags & SURF_DRAWTILED) continue; // no lightmaps @@ -472,16 +474,16 @@ loop: } // go down back side - return RecursiveLightPoint (node->children[!side], mid, end); + return RecursiveLightPoint (brush, node->children[!side], mid, end); } int -R_LightPoint (const vec3_t p) +R_LightPoint (mod_brush_t *brush, const vec3_t p) { vec3_t end; int r; - if (!r_worldentity.model->lightdata) { + if (!brush->lightdata) { // allow dlights to have some effect, so don't go /quite/ fullbright ambientcolor[2] = ambientcolor[1] = ambientcolor[0] = 200; return 200; @@ -491,7 +493,7 @@ R_LightPoint (const vec3_t p) end[1] = p[1]; end[2] = p[2] - 2048; - r = RecursiveLightPoint (r_worldentity.model->nodes, p, end); + r = RecursiveLightPoint (brush, brush->nodes, p, end); if (r == -1) r = 0; diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 17fcbf5bb..7cf001b87 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -237,7 +237,7 @@ R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) void -R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) +R_DrawSolidClippedSubmodelPolygons (model_t *model) { int i, j, lindex; vec_t dot; @@ -247,12 +247,13 @@ R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) mvertex_t bverts[MAX_BMODEL_VERTS]; bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; medge_t *pedge, *pedges; + mod_brush_t *brush = &model->brush; // FIXME: use bounding-box-based frustum clipping info? - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; - pedges = pmodel->edges; + psurf = &brush->surfaces[brush->firstmodelsurface]; + numsurfaces = brush->nummodelsurfaces; + pedges = brush->edges; for (i = 0; i < numsurfaces; i++, psurf++) { // find which side of the node we are on @@ -278,7 +279,7 @@ R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) numbedges += psurf->numedges; for (j = 0; j < psurf->numedges; j++) { - lindex = pmodel->surfedges[psurf->firstedge + j]; + lindex = brush->surfedges[psurf->firstedge + j]; if (lindex > 0) { pedge = &pedges[lindex]; @@ -306,18 +307,19 @@ R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) void -R_DrawSubmodelPolygons (model_t *pmodel, int clipflags) +R_DrawSubmodelPolygons (model_t *model, int clipflags) { int i; vec_t dot; msurface_t *psurf; int numsurfaces; plane_t *pplane; + mod_brush_t *brush = &model->brush; // FIXME: use bounding-box-based frustum clipping info? - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; + psurf = &brush->surfaces[brush->firstmodelsurface]; + numsurfaces = brush->nummodelsurfaces; for (i = 0; i < numsurfaces; i++, psurf++) { // find which side of the node we are on @@ -358,7 +360,7 @@ get_side (mnode_t *node) } static void -visit_node (mnode_t *node, int side, int clipflags) +visit_node (mod_brush_t *brush, mnode_t *node, int side, int clipflags) { int c; msurface_t *surf; @@ -367,7 +369,7 @@ visit_node (mnode_t *node, int side, int clipflags) side = (~side + 1) & SURF_PLANEBACK; // draw stuff if ((c = node->numsurfaces)) { - surf = r_worldentity.model->surfaces + node->firstsurface; + surf = brush->surfaces + node->firstsurface; for (; c; c--, surf++) { if (surf->visframe != r_visframecount) continue; @@ -444,7 +446,7 @@ test_node (mnode_t *node, int *clipflags) } static void -R_VisitWorldNodes (model_t *model, int clipflags) +R_VisitWorldNodes (mod_brush_t *brush, int clipflags) { typedef struct { mnode_t *node; @@ -456,9 +458,9 @@ R_VisitWorldNodes (model_t *model, int clipflags) mnode_t *front; int side, cf; - node = model->nodes; + node = brush->nodes; // +2 for paranoia - node_stack = alloca ((model->depth + 2) * sizeof (rstack_t)); + node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_ptr = node_stack; cf = clipflags; @@ -478,7 +480,7 @@ R_VisitWorldNodes (model_t *model, int clipflags) } if (front->contents < 0 && front->contents != CONTENTS_SOLID) visit_leaf ((mleaf_t *) front); - visit_node (node, side, clipflags); + visit_node (brush, node, side, clipflags); node = node->children[!side]; } if (node->contents < 0 && node->contents != CONTENTS_SOLID) @@ -488,7 +490,7 @@ R_VisitWorldNodes (model_t *model, int clipflags) node = node_ptr->node; side = node_ptr->side; clipflags = node_ptr->clipflags; - visit_node (node, side, clipflags); + visit_node (brush, node, side, clipflags); node = node->children[!side]; continue; } @@ -502,17 +504,17 @@ void R_RenderWorld (void) { int i; - model_t *clmodel; btofpoly_t btofpolys[MAX_BTOFPOLYS]; + mod_brush_t *brush; pbtofpolys = btofpolys; currententity = &r_worldentity; VectorCopy (r_origin, modelorg); - clmodel = currententity->model; - r_pcurrentvertbase = clmodel->vertexes; + brush = ¤tentity->model->brush; + r_pcurrentvertbase = brush->vertexes; - R_VisitWorldNodes (clmodel, 15); + R_VisitWorldNodes (brush, 15); // if the driver wants the polygons back to front, play the visible ones // back in that order diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index c5c943fd5..3f460643d 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -353,6 +353,7 @@ R_RenderFace (msurface_t *fa, int clipflags) vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; + mod_brush_t *brush = ¤tentity->model->brush; // skip out if no more surfs if ((surface_p) >= surf_max) { @@ -382,11 +383,11 @@ R_RenderFace (msurface_t *fa, int clipflags) r_nearzi = 0; r_nearzionly = false; makeleftedge = makerightedge = false; - pedges = currententity->model->edges; + pedges = brush->edges; r_lastvertvalid = false; for (i = 0; i < fa->numedges; i++) { - lindex = currententity->model->surfedges[fa->firstedge + i]; + lindex = brush->surfedges[fa->firstedge + i]; if (lindex > 0) { r_pedge = &pedges[lindex]; @@ -623,6 +624,7 @@ R_RenderPoly (msurface_t *fa, int clipflags) polyvert_t pverts[100]; // FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; qboolean visible; + mod_brush_t *brush = ¤tentity->model->brush; // FIXME: clean this up and make it faster // FIXME: guard against running out of vertices @@ -641,12 +643,12 @@ R_RenderPoly (msurface_t *fa, int clipflags) // reconstruct the polygon // FIXME: these should be precalculated and loaded off disk - pedges = currententity->model->edges; + pedges = brush->edges; lnumverts = fa->numedges; vertpage = 0; for (i = 0; i < lnumverts; i++) { - lindex = currententity->model->surfedges[fa->firstedge + i]; + lindex = brush->surfedges[fa->firstedge + i]; if (lindex > 0) { r_pedge = &pedges[lindex]; @@ -777,15 +779,16 @@ R_RenderPoly (msurface_t *fa, int clipflags) void -R_ZDrawSubmodelPolys (model_t *pmodel) +R_ZDrawSubmodelPolys (model_t *model) { int i, numsurfaces; msurface_t *psurf; float dot; plane_t *pplane; + mod_brush_t *brush = &model->brush; - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; + psurf = &brush->surfaces[brush->firstmodelsurface]; + numsurfaces = brush->nummodelsurfaces; for (i = 0; i < numsurfaces; i++, psurf++) { // find which side of the node we are on diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 5d38ae04d..573827bda 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -164,6 +164,7 @@ void R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) { int i; + mod_brush_t *brush = &worldmodel->brush; memset (&r_worldentity, 0, sizeof (r_worldentity)); r_worldentity.model = worldmodel; @@ -172,11 +173,11 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) // clear out efrags in case the level hasn't been reloaded // FIXME: is this one short? - for (i = 0; i < r_worldentity.model->numleafs; i++) - r_worldentity.model->leafs[i].efrags = NULL; + for (i = 0; i < brush->numleafs; i++) + brush->leafs[i].efrags = NULL; - if (worldmodel->skytexture) - R_InitSky (worldmodel->skytexture); + if (brush->skytexture) + R_InitSky (brush->skytexture); // Force a vis update r_viewleaf = NULL; @@ -381,7 +382,8 @@ R_DrawEntitiesOnList (void) if (currententity->model->type == mod_iqm//FIXME || R_AliasCheckBBox ()) { // 128 instead of 255 due to clamping below - j = max (R_LightPoint (currententity->origin), minlight * 128); + j = max (R_LightPoint (&r_worldentity.model->brush, + currententity->origin), minlight * 128); lighting.ambientlight = j; lighting.shadelight = j; @@ -448,7 +450,8 @@ R_DrawViewModel (void) minlight = max (currententity->min_light, currententity->model->min_light); - j = max (R_LightPoint (currententity->origin), minlight * 128); + j = max (R_LightPoint (&r_worldentity.model->brush, + currententity->origin), minlight * 128); r_viewlighting.ambientlight = j; r_viewlighting.shadelight = j; @@ -568,19 +571,20 @@ R_DrawBEntitiesOnList (void) clipflags = R_BmodelCheckBBox (clmodel, minmaxs); if (clipflags != BMODEL_FULLY_CLIPPED) { + mod_brush_t *brush = &clmodel->brush; VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); // FIXME: is this needed? VectorCopy (modelorg, r_worldmodelorg); - r_pcurrentvertbase = clmodel->vertexes; + r_pcurrentvertbase = brush->vertexes; // FIXME: stop transforming twice R_RotateBmodel (); // calculate dynamic lighting for bmodel if it's not an // instanced model - if (clmodel->firstmodelsurface != 0) { + if (brush->firstmodelsurface != 0) { vec3_t lightorigin; for (k = 0; k < r_maxdlights; k++) { @@ -590,9 +594,10 @@ R_DrawBEntitiesOnList (void) VectorSubtract (r_dlights[k].origin, currententity->origin, lightorigin); - R_RecursiveMarkLights (lightorigin, &r_dlights[k], - k, clmodel->nodes + - clmodel->hulls[0].firstclipnode); + R_RecursiveMarkLights (brush, lightorigin, + &r_dlights[k], k, + brush->nodes + + brush->hulls[0].firstclipnode); } } // if the driver wants polygons, deliver those. diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index e4d3fa853..5133118cb 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -154,7 +154,7 @@ R_BuildLightMap (void) size = smax * tmax; lightmap = surf->samples; - if (!r_worldentity.model->lightdata) { + if (!r_worldentity.model->brush.lightdata) { for (i = 0; i < size; i++) blocklights[i] = 0; return; diff --git a/libs/video/renderer/sw32/sw32_rbsp.c b/libs/video/renderer/sw32/sw32_rbsp.c index 017268dbb..521e70cd5 100644 --- a/libs/video/renderer/sw32/sw32_rbsp.c +++ b/libs/video/renderer/sw32/sw32_rbsp.c @@ -240,7 +240,7 @@ R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) void -sw32_R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) +sw32_R_DrawSolidClippedSubmodelPolygons (model_t *model) { int i, j, lindex; vec_t dot; @@ -250,12 +250,13 @@ sw32_R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) mvertex_t bverts[MAX_BMODEL_VERTS]; bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; medge_t *pedge, *pedges; + mod_brush_t *brush = &model->brush; // FIXME: use bounding-box-based frustum clipping info? - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; - pedges = pmodel->edges; + psurf = &brush->surfaces[brush->firstmodelsurface]; + numsurfaces = brush->nummodelsurfaces; + pedges = brush->edges; for (i = 0; i < numsurfaces; i++, psurf++) { // find which side of the node we are on @@ -281,7 +282,7 @@ sw32_R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) numbedges += psurf->numedges; for (j = 0; j < psurf->numedges; j++) { - lindex = pmodel->surfedges[psurf->firstedge + j]; + lindex = brush->surfedges[psurf->firstedge + j]; if (lindex > 0) { pedge = &pedges[lindex]; @@ -309,18 +310,19 @@ sw32_R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) void -sw32_R_DrawSubmodelPolygons (model_t *pmodel, int clipflags) +sw32_R_DrawSubmodelPolygons (model_t *model, int clipflags) { int i; vec_t dot; msurface_t *psurf; int numsurfaces; plane_t *pplane; + mod_brush_t *brush = &model->brush; // FIXME: use bounding-box-based frustum clipping info? - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; + psurf = &brush->surfaces[brush->firstmodelsurface]; + numsurfaces = brush->nummodelsurfaces; for (i = 0; i < numsurfaces; i++, psurf++) { // find which side of the node we are on @@ -361,7 +363,7 @@ get_side (mnode_t *node) } static void -visit_node (mnode_t *node, int side, int clipflags) +visit_node (mod_brush_t *brush, mnode_t *node, int side, int clipflags) { int c; msurface_t *surf; @@ -370,7 +372,7 @@ visit_node (mnode_t *node, int side, int clipflags) side = (~side + 1) & SURF_PLANEBACK; // draw stuff if ((c = node->numsurfaces)) { - surf = r_worldentity.model->surfaces + node->firstsurface; + surf = brush->surfaces + node->firstsurface; for (; c; c--, surf++) { if (surf->visframe != r_visframecount) continue; @@ -447,7 +449,7 @@ test_node (mnode_t *node, int *clipflags) } static void -R_VisitWorldNodes (model_t *model, int clipflags) +R_VisitWorldNodes (mod_brush_t *brush, int clipflags) { typedef struct { mnode_t *node; @@ -459,9 +461,9 @@ R_VisitWorldNodes (model_t *model, int clipflags) mnode_t *front; int side, cf; - node = model->nodes; + node = brush->nodes; // +2 for paranoia - node_stack = alloca ((model->depth + 2) * sizeof (rstack_t)); + node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_ptr = node_stack; cf = clipflags; @@ -481,7 +483,7 @@ R_VisitWorldNodes (model_t *model, int clipflags) } if (front->contents < 0 && front->contents != CONTENTS_SOLID) visit_leaf ((mleaf_t *) front); - visit_node (node, side, clipflags); + visit_node (brush, node, side, clipflags); node = node->children[!side]; } if (node->contents < 0 && node->contents != CONTENTS_SOLID) @@ -491,7 +493,7 @@ R_VisitWorldNodes (model_t *model, int clipflags) node = node_ptr->node; side = node_ptr->side; clipflags = node_ptr->clipflags; - visit_node (node, side, clipflags); + visit_node (brush, node, side, clipflags); node = node->children[!side]; continue; } @@ -505,17 +507,17 @@ void sw32_R_RenderWorld (void) { int i; - model_t *clmodel; btofpoly_t btofpolys[MAX_BTOFPOLYS]; + mod_brush_t *brush; pbtofpolys = btofpolys; currententity = &r_worldentity; VectorCopy (r_origin, modelorg); - clmodel = currententity->model; - r_pcurrentvertbase = clmodel->vertexes; + brush = ¤tentity->model->brush; + r_pcurrentvertbase = brush->vertexes; - R_VisitWorldNodes (clmodel, 15); + R_VisitWorldNodes (brush, 15); // if the driver wants the polygons back to front, play the visible ones // back in that order diff --git a/libs/video/renderer/sw32/sw32_rdraw.c b/libs/video/renderer/sw32/sw32_rdraw.c index 6624917a7..b106ab63a 100644 --- a/libs/video/renderer/sw32/sw32_rdraw.c +++ b/libs/video/renderer/sw32/sw32_rdraw.c @@ -349,6 +349,7 @@ sw32_R_RenderFace (msurface_t *fa, int clipflags) vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; + mod_brush_t *brush = ¤tentity->model->brush; // skip out if no more surfs if ((sw32_surface_p) >= sw32_surf_max) { @@ -378,11 +379,11 @@ sw32_R_RenderFace (msurface_t *fa, int clipflags) sw32_r_nearzi = 0; sw32_r_nearzionly = false; makeleftedge = makerightedge = false; - pedges = currententity->model->edges; + pedges = brush->edges; sw32_r_lastvertvalid = false; for (i = 0; i < fa->numedges; i++) { - lindex = currententity->model->surfedges[fa->firstedge + i]; + lindex = brush->surfedges[fa->firstedge + i]; if (lindex > 0) { sw32_r_pedge = &pedges[lindex]; @@ -621,6 +622,7 @@ sw32_R_RenderPoly (msurface_t *fa, int clipflags) polyvert_t pverts[100]; // FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; qboolean visible; + mod_brush_t *brush = ¤tentity->model->brush; // FIXME: clean this up and make it faster // FIXME: guard against running out of vertices @@ -639,12 +641,12 @@ sw32_R_RenderPoly (msurface_t *fa, int clipflags) // reconstruct the polygon // FIXME: these should be precalculated and loaded off disk - pedges = currententity->model->edges; + pedges = brush->edges; lnumverts = fa->numedges; vertpage = 0; for (i = 0; i < lnumverts; i++) { - lindex = currententity->model->surfedges[fa->firstedge + i]; + lindex = brush->surfedges[fa->firstedge + i]; if (lindex > 0) { sw32_r_pedge = &pedges[lindex]; @@ -775,15 +777,16 @@ sw32_R_RenderPoly (msurface_t *fa, int clipflags) void -sw32_R_ZDrawSubmodelPolys (model_t *pmodel) +sw32_R_ZDrawSubmodelPolys (model_t *model) { int i, numsurfaces; msurface_t *psurf; float dot; plane_t *pplane; + mod_brush_t *brush = &model->brush; - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; + psurf = &brush->surfaces[brush->firstmodelsurface]; + numsurfaces = brush->nummodelsurfaces; for (i = 0; i < numsurfaces; i++, psurf++) { // find which side of the node we are on diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index fd204e587..67c59e2f9 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -180,6 +180,7 @@ void sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) { int i; + mod_brush_t *brush = &worldmodel->brush; memset (&r_worldentity, 0, sizeof (r_worldentity)); r_worldentity.model = worldmodel; @@ -188,11 +189,11 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) // clear out efrags in case the level hasn't been reloaded // FIXME: is this one short? - for (i = 0; i < r_worldentity.model->numleafs; i++) - r_worldentity.model->leafs[i].efrags = NULL; + for (i = 0; i < brush->numleafs; i++) + brush->leafs[i].efrags = NULL; - if (worldmodel->skytexture) - sw32_R_InitSky (worldmodel->skytexture); + if (brush->skytexture) + sw32_R_InitSky (brush->skytexture); // Force a vis update r_viewleaf = NULL; @@ -388,7 +389,9 @@ R_DrawEntitiesOnList (void) if (currententity->model->type == mod_iqm//FIXME || sw32_R_AliasCheckBBox ()) { // 128 instead of 255 due to clamping below - j = max (R_LightPoint (currententity->origin), minlight * 128); + j = max (R_LightPoint (&r_worldentity.model->brush, + currententity->origin), + minlight * 128); lighting.ambientlight = j; lighting.shadelight = j; @@ -454,7 +457,8 @@ R_DrawViewModel (void) minlight = max (currententity->min_light, currententity->model->min_light); - j = max (R_LightPoint (currententity->origin), minlight * 128); + j = max (R_LightPoint (&r_worldentity.model->brush, + currententity->origin), minlight * 128); r_viewlighting.ambientlight = j; r_viewlighting.shadelight = j; @@ -574,19 +578,20 @@ R_DrawBEntitiesOnList (void) clipflags = R_BmodelCheckBBox (clmodel, minmaxs); if (clipflags != BMODEL_FULLY_CLIPPED) { + mod_brush_t *brush = &clmodel->brush; VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); // FIXME: is this needed? VectorCopy (modelorg, sw32_r_worldmodelorg); - r_pcurrentvertbase = clmodel->vertexes; + r_pcurrentvertbase = brush->vertexes; // FIXME: stop transforming twice sw32_R_RotateBmodel (); // calculate dynamic lighting for bmodel if it's not an // instanced model - if (clmodel->firstmodelsurface != 0) { + if (brush->firstmodelsurface != 0) { vec3_t lightorigin; for (k = 0; k < r_maxdlights; k++) { @@ -596,9 +601,10 @@ R_DrawBEntitiesOnList (void) VectorSubtract (r_dlights[k].origin, currententity->origin, lightorigin); - R_RecursiveMarkLights (lightorigin, &r_dlights[k], - k, clmodel->nodes + - clmodel->hulls[0].firstclipnode); + R_RecursiveMarkLights (brush, lightorigin, + &r_dlights[k], k, + brush->nodes + + brush->hulls[0].firstclipnode); } } // if the driver wants polygons, deliver those. diff --git a/libs/video/renderer/sw32/sw32_rsurf.c b/libs/video/renderer/sw32/sw32_rsurf.c index 9badf0c96..decd8c3a7 100644 --- a/libs/video/renderer/sw32/sw32_rsurf.c +++ b/libs/video/renderer/sw32/sw32_rsurf.c @@ -172,7 +172,7 @@ R_BuildLightMap (void) size = smax * tmax; lightmap = surf->samples; - if (!r_worldentity.model->lightdata) { + if (!r_worldentity.model->brush.lightdata) { for (i = 0; i < size; i++) blocklights[i] = 0; return; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 65fa232cc..fec2d2cd6 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -144,7 +144,7 @@ calc_lighting (qfv_light_t *light, entity_t *ent) { vec3_t ambient_color; //FIXME should be ent->position - float l = R_LightPoint (r_origin) / 128.0; + float l = R_LightPoint (&r_worldentity.model->brush, r_origin) / 128.0; //XXX l = max (light, max (ent->model->min_light, ent->min_light)); light->type = 2; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index ff64990ee..a0dcd9134 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -153,7 +153,7 @@ add_texture (texture_t *tx, vulkan_ctx_t *ctx) } static void -init_surface_chains (model_t *model, vulkan_ctx_t *ctx) +init_surface_chains (mod_brush_t *brush, vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; int i; @@ -161,9 +161,9 @@ init_surface_chains (model_t *model, vulkan_ctx_t *ctx) release_static_instsurfs (bctx); release_instsurfs (bctx); - for (i = 0; i < model->nummodelsurfaces; i++) { - model->surfaces[i].instsurf = get_static_instsurf (bctx); - model->surfaces[i].instsurf->surface = &model->surfaces[i]; + for (i = 0; i < brush->nummodelsurfaces; i++) { + brush->surfaces[i].instsurf = get_static_instsurf (bctx); + brush->surfaces[i].instsurf->surface = &brush->surfaces[i]; } } @@ -199,7 +199,7 @@ Vulkan_ClearElements (vulkan_ctx_t *ctx) } static void -update_lightmap (msurface_t *surf, vulkan_ctx_t *ctx) +update_lightmap (mod_brush_t *brush, msurface_t *surf, vulkan_ctx_t *ctx) { int maps; @@ -210,13 +210,13 @@ update_lightmap (msurface_t *surf, vulkan_ctx_t *ctx) if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { dynamic: if (r_dynamic->int_val) - Vulkan_BuildLightMap (surf, ctx); + Vulkan_BuildLightMap (brush, surf, ctx); } } static inline void -chain_surface (msurface_t *surf, vec_t *transform, float *color, - vulkan_ctx_t *ctx) +chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, + float *color, vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; instsurf_t *is; @@ -236,7 +236,7 @@ chain_surface (msurface_t *surf, vec_t *transform, float *color, tex = tx->render; CHAIN_SURF_F2B (surf, tex->tex_chain); - update_lightmap (surf, ctx); + update_lightmap (brush, surf, ctx); } if (!(is = surf->instsurf)) is = surf->tinst; @@ -245,13 +245,13 @@ chain_surface (msurface_t *surf, vec_t *transform, float *color, } static void -register_textures (model_t *model, vulkan_ctx_t *ctx) +register_textures (mod_brush_t *brush, vulkan_ctx_t *ctx) { int i; texture_t *tex; - for (i = 0; i < model->numtextures; i++) { - tex = model->textures[i]; + for (i = 0; i < brush->numtextures; i++) { + tex = brush->textures[i]; if (!tex) continue; add_texture (tex, ctx); @@ -270,11 +270,12 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) { int i; model_t *m; + mod_brush_t *brush = &r_worldentity.model->brush; clear_textures (ctx); - init_surface_chains (r_worldentity.model, ctx); + init_surface_chains (brush, ctx); add_texture (r_notexture_mip, ctx); - register_textures (r_worldentity.model, ctx); + register_textures (brush, ctx); for (i = 0; i < num_models; i++) { m = models[i]; if (!m) @@ -285,8 +286,9 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) // world has already been done, not interested in non-brush models if (m == r_worldentity.model || m->type != mod_brush) continue; - m->numsubmodels = 1; // no support for submodels in non-world model - register_textures (m, ctx); + brush = &m->brush; + brush->numsubmodels = 1; // no support for submodels in non-world model + register_textures (brush, ctx); } } @@ -329,18 +331,18 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, bsppoly_t *poly; uint32_t *ind; float s, t; + mod_brush_t *brush; if (fa->ec_index < 0) { // instance model - vertices = models[~fa->ec_index]->vertexes; - edges = models[~fa->ec_index]->edges; - surfedges = models[~fa->ec_index]->surfedges; + brush = &models[~fa->ec_index]->brush; } else { // main or sub model - vertices = r_worldentity.model->vertexes; - edges = r_worldentity.model->edges; - surfedges = r_worldentity.model->surfedges; + brush = &r_worldentity.model->brush; } + vertices = brush->vertexes; + edges = brush->edges; + surfedges = brush->surfedges; // create a triangle fan numverts = fa->numedges; numindices = numverts + 1; @@ -405,6 +407,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) qfv_stagebuf_t *stage; bspvert_t *vertices; bsppoly_t *poly; + mod_brush_t *brush; QuatSet (0, 0, sqrt(0.5), sqrt(0.5), bctx->sky_fix); // proper skies QuatSet (0, 0, 0, 1, bctx->sky_rotation[0]); @@ -421,24 +424,25 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!m) continue; // sub-models are done as part of the main model - if (*m->path == '*') + if (*m->path == '*' || m->type != mod_brush) continue; + brush = &m->brush; // non-bsp models don't have surfaces. - dm = m->submodels; - for (j = 0; j < m->numsurfaces; j++) { + dm = brush->submodels; + for (j = 0; j < brush->numsurfaces; j++) { vulktex_t *tex; if (j == dm->firstface + dm->numfaces) { dm++; - if (dm - m->submodels == m->numsubmodels) { + if (dm - brush->submodels == brush->numsubmodels) { // limit the surfaces // probably never hit Sys_Printf ("R_BuildDisplayLists: too many surfaces\n"); - m->numsurfaces = j; + brush->numsurfaces = j; break; } } - surf = m->surfaces + j; - surf->ec_index = dm - m->submodels; + surf = brush->surfaces + j; + surf->ec_index = dm - brush->submodels; if (!surf->ec_index && m != r_worldentity.model) surf->ec_index = -1 - i; // instanced model tex = surf->texinfo->texture->render; @@ -602,8 +606,10 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) msurface_t *surf; qboolean rotated; vec3_t mins, maxs, org; + mod_brush_t *brush; model = e->model; + brush = &model->brush; if (e->transform[0] != 1 || e->transform[5] != 1 || e->transform[10] != 1) { rotated = true; radius = model->radius; @@ -628,7 +634,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) } // calculate dynamic lighting for bmodel if it's not an instanced model - if (model->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { + if (brush->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { vec3_t lightorigin; for (k = 0; k < r_maxdlights; k++) { @@ -637,14 +643,14 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) continue; VectorSubtract (r_dlights[k].origin, e->origin, lightorigin); - R_RecursiveMarkLights (lightorigin, &r_dlights[k], k, - model->nodes + model->hulls[0].firstclipnode); + R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, + brush->nodes + brush->hulls[0].firstclipnode); } } - surf = &model->surfaces[model->firstmodelsurface]; + surf = &brush->surfaces[brush->firstmodelsurface]; - for (i = 0; i < model->nummodelsurfaces; i++, surf++) { + for (i = 0; i < brush->nummodelsurfaces; i++, surf++) { // find the node side on which we are plane = surf->plane; @@ -653,7 +659,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) // enqueue the polygon if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (surf, e->transform, e->colormod, ctx); + chain_surface (brush, surf, e->transform, e->colormod, ctx); } } } @@ -678,7 +684,7 @@ get_side (mnode_t *node) } static inline void -visit_node (mnode_t *node, int side, vulkan_ctx_t *ctx) +visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) { int c; msurface_t *surf; @@ -687,7 +693,7 @@ visit_node (mnode_t *node, int side, vulkan_ctx_t *ctx) side = (~side + 1) & SURF_PLANEBACK; // draw stuff if ((c = node->numsurfaces)) { - surf = r_worldentity.model->surfaces + node->firstsurface; + surf = brush->surfaces + node->firstsurface; for (; c; c--, surf++) { if (surf->visframe != r_visframecount) continue; @@ -696,7 +702,7 @@ visit_node (mnode_t *node, int side, vulkan_ctx_t *ctx) if (side ^ (surf->flags & SURF_PLANEBACK)) continue; // wrong side - chain_surface (surf, 0, 0, ctx); + chain_surface (brush, surf, 0, 0, ctx); } } } @@ -714,7 +720,7 @@ test_node (mnode_t *node) } static void -R_VisitWorldNodes (model_t *model, vulkan_ctx_t *ctx) +R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) { typedef struct { mnode_t *node; @@ -726,9 +732,9 @@ R_VisitWorldNodes (model_t *model, vulkan_ctx_t *ctx) mnode_t *front; int side; - node = model->nodes; + node = brush->nodes; // +2 for paranoia - node_stack = alloca ((model->depth + 2) * sizeof (rstack_t)); + node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_ptr = node_stack; while (1) { @@ -744,7 +750,7 @@ R_VisitWorldNodes (model_t *model, vulkan_ctx_t *ctx) } if (front->contents < 0 && front->contents != CONTENTS_SOLID) visit_leaf ((mleaf_t *) front); - visit_node (node, side, ctx); + visit_node (brush, node, side, ctx); node = node->children[!side]; } if (node->contents < 0 && node->contents != CONTENTS_SOLID) @@ -753,7 +759,7 @@ R_VisitWorldNodes (model_t *model, vulkan_ctx_t *ctx) node_ptr--; node = node_ptr->node; side = node_ptr->side; - visit_node (node, side, ctx); + visit_node (brush, node, side, ctx); node = node->children[!side]; continue; } @@ -1099,19 +1105,21 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; entity_t worldent; + mod_brush_t *brush; clear_texture_chains (bctx); // do this first for water and skys bframe->index_count = 0; memset (&worldent, 0, sizeof (worldent)); worldent.model = r_worldentity.model; + brush = &r_worldentity.model->brush; //vulktex_t *tex = r_worldentity.model->skytexture->render; //bctx->skysheet_tex = tex->tex; currententity = &worldent; - R_VisitWorldNodes (worldent.model, ctx); + R_VisitWorldNodes (brush, ctx); if (r_drawentities->int_val) { entity_t *ent; for (ent = r_ent_queue; ent; ent = ent->next) { diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 623bd9d94..ca5d433e8 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -125,7 +125,7 @@ add_dynamic_lights (msurface_t *surf, float *block) } void -Vulkan_BuildLightMap (msurface_t *surf, vulkan_ctx_t *ctx) +Vulkan_BuildLightMap (mod_brush_t *brush, msurface_t *surf, vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; int smax, tmax, size; @@ -142,7 +142,7 @@ Vulkan_BuildLightMap (msurface_t *surf, vulkan_ctx_t *ctx) block = QFV_SubpicBatch (surf->lightpic, bctx->light_stage); // set to full bright if no light data - if (!r_worldentity.model->lightdata) { + if (!brush->lightdata) { out = block; while (size-- > 0) { *out++ = 1; @@ -219,6 +219,7 @@ Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) bspctx_t *bctx = ctx->bsp_context; int i, j; model_t *m; + mod_brush_t *brush; QFV_ScrapClear (bctx->light_scrap); @@ -228,13 +229,14 @@ Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) m = models[j]; if (!m) break; - if (m->path[0] == '*') { + if (m->path[0] == '*' || m->type != mod_brush) { // sub model surfaces are processed as part of the main model continue; } + brush = &m->brush; // non-bsp models don't have surfaces. - for (i = 0; i < m->numsurfaces; i++) { - msurface_t *surf = m->surfaces + i; + for (i = 0; i < brush->numsurfaces; i++) { + msurface_t *surf = brush->surfaces + i; surf->lightpic = 0; // paranoia if (surf->flags & SURF_DRAWTURB) { continue; @@ -251,15 +253,16 @@ Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!m) { break; } - if (m->path[0] == '*') { + if (m->path[0] == '*' || m->type != mod_brush) { // sub model surfaces are processed as part of the main model continue; } + brush = &m->brush; // non-bsp models don't have surfaces. - for (i = 0; i < m->numsurfaces; i++) { - msurface_t *surf = m->surfaces + i; + for (i = 0; i < brush->numsurfaces; i++) { + msurface_t *surf = brush->surfaces + i; if (surf->lightpic) { - Vulkan_BuildLightMap (surf, ctx); + Vulkan_BuildLightMap (brush, surf, ctx); } } } diff --git a/nq/source/cl_chase.c b/nq/source/cl_chase.c index 92903bbfc..5d23817cd 100644 --- a/nq/source/cl_chase.c +++ b/nq/source/cl_chase.c @@ -86,7 +86,7 @@ TraceLine (vec3_t start, vec3_t end, vec3_t impact) memset (&trace, 0, sizeof (trace)); trace.fraction = 1; - MOD_TraceLine (cl.worldmodel->hulls, 0, start, end, &trace); + MOD_TraceLine (cl.worldmodel->brush.hulls, 0, start, end, &trace); VectorCopy (trace.endpos, impact); } diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 6f6e90e29..ce76ebf71 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -381,7 +381,7 @@ CL_RelinkEntities (void) if (i != cl.viewentity || chase_active->int_val) { if (ent->efrag) r_funcs->R_RemoveEfrags (ent); - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } VectorCopy (ent->origin, ent->old_origin); } else { @@ -416,10 +416,10 @@ CL_RelinkEntities (void) if (ent->efrag) { if (!VectorCompare (ent->origin, ent->old_origin)) { r_funcs->R_RemoveEfrags (ent); - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } } else { - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } } } diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 981f72714..3b076b43f 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -301,7 +301,7 @@ map_ent (const char *mapname) edicts = ED_Parse (&edpr, buf); free (buf); } else { - edicts = ED_Parse (&edpr, cl.model_precache[1]->entities); + edicts = ED_Parse (&edpr, cl.model_precache[1]->brush.entities); } free (name); return edicts; @@ -315,7 +315,7 @@ CL_NewMap (const char *mapname) Hunk_Check (); // make sure nothing is hurt Sbar_CenterPrint (0); - if (cl.model_precache[1] && cl.model_precache[1]->entities) { + if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) { cl.edicts = map_ent (mapname); if (cl.edicts) { cl.worldspawn = PL_ObjectAtIndex (cl.edicts, 0); @@ -795,7 +795,7 @@ CL_ParseStatic (int version) VectorCopy (baseline.origin, ent->origin); CL_TransformEntity (ent, baseline.angles, true); - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } static void diff --git a/nq/source/cl_tent.c b/nq/source/cl_tent.c index 89f05ee74..2286d829a 100644 --- a/nq/source/cl_tent.c +++ b/nq/source/cl_tent.c @@ -294,7 +294,7 @@ beam_setup (beam_t *b, qboolean transform) CL_TransformEntity (&tent->ent, ang, true); } VectorCopy (ang, tent->ent.angles); - r_funcs->R_AddEfrags (&tent->ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, &tent->ent); } } @@ -588,7 +588,7 @@ CL_UpdateExplosions (void) ent->frame = f; if (!ent->efrag) - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } } diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 9ee006e3b..38604e66c 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -432,9 +432,9 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node) static byte * SV_FatPVS (vec3_t org) { - fatbytes = (sv.worldmodel->numleafs + 31) >> 3; + fatbytes = (sv.worldmodel->brush.numleafs + 31) >> 3; memset (fatpvs, 0, fatbytes); - SV_AddToFatPVS (org, sv.worldmodel->nodes); + SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); return fatpvs; } @@ -1189,7 +1189,7 @@ SV_SpawnServer (const char *server) sv.model_precache[0] = sv_pr_state.pr_strings; sv.model_precache[1] = sv.modelname; - for (i = 1; i < sv.worldmodel->numsubmodels; i++) { + for (i = 1; i < sv.worldmodel->brush.numsubmodels; i++) { sv.model_precache[1 + i] = localmodels[i]; sv.models[i + 1] = Mod_ForName (localmodels[i], false); } @@ -1220,7 +1220,7 @@ SV_SpawnServer (const char *server) ED_LoadFromFile (&sv_pr_state, (char *) buf); free (buf); } else { - ED_LoadFromFile (&sv_pr_state, sv.worldmodel->entities); + ED_LoadFromFile (&sv_pr_state, sv.worldmodel->brush.entities); } sv.active = true; diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 0084b3b99..096010f77 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -585,7 +585,7 @@ PF_newcheckclient (progs_t *pr, int check) VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); leaf = Mod_PointInLeaf (org, sv.worldmodel); pvs = Mod_LeafPVS (leaf, sv.worldmodel); - memcpy (checkpvs, pvs, (sv.worldmodel->numleafs + 7) >> 3); + memcpy (checkpvs, pvs, (sv.worldmodel->brush.numleafs + 7) >> 3); return i; } @@ -630,7 +630,7 @@ PF_checkclient (progs_t *pr) self = PROG_TO_EDICT (pr, *sv_globals.self); VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view); leaf = Mod_PointInLeaf (view, sv.worldmodel); - l = (leaf - sv.worldmodel->leafs) - 1; + l = (leaf - sv.worldmodel->brush.leafs) - 1; if ((l < 0) || !(checkpvs[l >> 3] & (1 << (l & 7)))) { c_notvis++; RETURN_EDICT (pr, sv.edicts); diff --git a/nq/source/world.c b/nq/source/world.c index f7d379a2d..5f8bce898 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -245,7 +245,7 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, PR_GetString (&sv_pr_state, SVstring (ent, classname))); - hull_list = model->hull_list; + hull_list = model->brush.hull_list; } if (hull_list) { // decide which clipping hull to use, based on the size @@ -425,7 +425,7 @@ SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) leaf = (mleaf_t *) node; edict_leaf = alloc_edict_leaf (); - edict_leaf->leafnum = leaf - sv.worldmodel->leafs - 1; + edict_leaf->leafnum = leaf - sv.worldmodel->brush.leafs - 1; edict_leaf->next = SVdata (ent)->leafs; SVdata (ent)->leafs = edict_leaf; return; @@ -497,7 +497,7 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers) // link to PVS leafs free_edict_leafs (&SVdata (ent)->leafs); if (SVfloat (ent, modelindex)) - SV_FindTouchedLeafs (ent, sv.worldmodel->nodes); + SV_FindTouchedLeafs (ent, sv.worldmodel->brush.nodes); if (SVfloat (ent, solid) == SOLID_NOT) return; @@ -560,7 +560,7 @@ SV_PointContents (const vec3_t p) { int cont; - cont = SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); + cont = SV_HullPointContents (&sv.worldmodel->brush.hulls[0], 0, p); if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN) cont = CONTENTS_WATER; return cont; @@ -569,7 +569,7 @@ SV_PointContents (const vec3_t p) int SV_TruePointContents (const vec3_t p) { - return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); + return SV_HullPointContents (&sv.worldmodel->brush.hulls[0], 0, p); } /* @@ -903,7 +903,7 @@ SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) vec3_t boxmins, boxmaxs, offset; // check world first - hull = &sv.worldmodel->hulls[1]; + hull = &sv.worldmodel->brush.hulls[1]; if (SV_HullPointContents (hull, hull->firstclipnode, origin) != CONTENTS_EMPTY) return sv.edicts; diff --git a/qw/source/cl_chase.c b/qw/source/cl_chase.c index 2e5583429..8a3d6419d 100644 --- a/qw/source/cl_chase.c +++ b/qw/source/cl_chase.c @@ -86,7 +86,7 @@ TraceLine (vec3_t start, vec3_t end, vec3_t impact) memset (&trace, 0, sizeof (trace)); trace.fraction = 1; - MOD_TraceLine (cl.worldmodel->hulls, 0, start, end, &trace); + MOD_TraceLine (cl.worldmodel->brush.hulls, 0, start, end, &trace); VectorCopy (trace.endpos, impact); } diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 3fdeda901..6fc04a4c4 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -542,7 +542,7 @@ CL_SetSolidEntities (void) continue; if (!cl.model_precache[state->modelindex]) continue; - if (cl.model_precache[state->modelindex]->hulls[1].firstclipnode + if (cl.model_precache[state->modelindex]->brush.hulls[1].firstclipnode || cl.model_precache[state->modelindex]->clipbox) { if (pmove.numphysent == MAX_PHYSENTS) { Sys_Printf ("WARNING: entity physent overflow, email " diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 24f14933b..7c95040ed 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -335,7 +335,7 @@ CL_LinkPacketEntities (void) if (i != cl.viewentity || chase_active->int_val) { if (ent->efrag) r_funcs->R_RemoveEfrags (ent); - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } VectorCopy (ent->origin, ent->old_origin); } else { @@ -370,15 +370,15 @@ CL_LinkPacketEntities (void) if (ent->efrag) { if (!VectorCompare (ent->origin, ent->old_origin)) { r_funcs->R_RemoveEfrags (ent); - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } } else { - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } } } if (!ent->efrag) - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); // rotate binary objects locally if (ent->model->flags & EF_ROTATE) { @@ -567,7 +567,7 @@ CL_LinkPlayers (void) } // stuff entity in map - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); if (state->pls.effects & EF_FLAG1) CL_AddFlagModels (ent, 0, j); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 21c7dabd2..f38b30537 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -288,7 +288,7 @@ map_ent (const char *mapname) edicts = ED_Parse (&edpr, buf); free (buf); } else { - edicts = ED_Parse (&edpr, cl.model_precache[1]->entities); + edicts = ED_Parse (&edpr, cl.model_precache[1]->brush.entities); } free (name); return edicts; @@ -305,7 +305,7 @@ CL_NewMap (const char *mapname) Hunk_Check (); // make sure nothing is hurt Sbar_CenterPrint (0); - if (cl.model_precache[1] && cl.model_precache[1]->entities) { + if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) { cl.edicts = map_ent (mapname); if (cl.edicts) { cl.worldspawn = PL_ObjectAtIndex (cl.edicts, 0); @@ -404,7 +404,7 @@ Model_NextDownload (void) MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va (0, prespawn_name, cl.servercount, - cl.worldmodel->checksum2)); + cl.worldmodel->brush.checksum2)); } } @@ -986,7 +986,7 @@ CL_ParseStatic (void) VectorCopy (es.origin, ent->origin); CL_TransformEntity (ent, es.angles, true); - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } static void diff --git a/qw/source/cl_tent.c b/qw/source/cl_tent.c index 950734bea..c24f1f0bc 100644 --- a/qw/source/cl_tent.c +++ b/qw/source/cl_tent.c @@ -298,7 +298,7 @@ beam_setup (beam_t *b, qboolean transform) CL_TransformEntity (&tent->ent, ang, true); } VectorCopy (ang, tent->ent.angles); - r_funcs->R_AddEfrags (&tent->ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, &tent->ent); } } @@ -595,7 +595,7 @@ CL_UpdateExplosions (void) ent->frame = f; if (!ent->efrag) - r_funcs->R_AddEfrags (ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } } @@ -658,7 +658,7 @@ CL_ParseProjectiles (qboolean nail2) pr->angles[2] = 0; CL_TransformEntity (&tent->ent, tent->ent.angles, true); - r_funcs->R_AddEfrags (&tent->ent); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, &tent->ent); } *tail = cl_projectiles; diff --git a/qw/source/pmovetst.c b/qw/source/pmovetst.c index 6b3857feb..b79e860e0 100644 --- a/qw/source/pmovetst.c +++ b/qw/source/pmovetst.c @@ -136,7 +136,7 @@ PM_PointContents (const vec3_t p) hull_t *hull; plane_t *plane; - hull = &pmove.physents[0].model->hulls[0]; + hull = &pmove.physents[0].model->brush.hulls[0]; num = hull->firstclipnode; @@ -174,7 +174,7 @@ PM_TestPlayerPosition (const vec3_t pos) pe = &pmove.physents[i]; // get the clipping hull if (pe->model) - hull = &pmove.physents[i].model->hulls[1]; + hull = &pmove.physents[i].model->brush.hulls[1]; else { VectorSubtract (pe->mins, player_maxs, mins); VectorSubtract (pe->maxs, player_mins, maxs); @@ -235,7 +235,7 @@ PM_PlayerMove (const vec3_t start, const vec3_t end) } else { check_box = 1; if (pe->model) { - hull = &pe->model->hulls[1]; + hull = &pe->model->brush.hulls[1]; VectorSubtract (pe->model->mins, player_maxs, mins); VectorSubtract (pe->model->maxs, player_mins, maxs); } else { diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index 09e19ba83..a5d6b4db9 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -99,9 +99,9 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node) static byte * SV_FatPVS (vec3_t org) { - fatbytes = (sv.worldmodel->numleafs + 31) >> 3; + fatbytes = (sv.worldmodel->brush.numleafs + 31) >> 3; memset (fatpvs, 0, fatbytes); - SV_AddToFatPVS (org, sv.worldmodel->nodes); + SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); return fatpvs; } @@ -738,7 +738,7 @@ calc_pvs (delta_t *delta) if (pvs == NULL) { pvs = SV_FatPVS (org); } else { - SV_AddToFatPVS (org, sv.worldmodel->nodes); + SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); } } } diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 8535dacb6..e0a370f92 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -229,7 +229,7 @@ SV_CalcPHS (void) SV_Printf ("Building PHS...\n"); - num = sv.worldmodel->numleafs; + num = sv.worldmodel->brush.numleafs; rowwords = (num + 31) >> 5; rowbytes = rowwords * 4; @@ -237,7 +237,8 @@ SV_CalcPHS (void) scan = sv.pvs; vcount = 0; for (i = 0; i < num; i++, scan += rowbytes) { - memcpy (scan, Mod_LeafPVS (sv.worldmodel->leafs + i, sv.worldmodel), + memcpy (scan, Mod_LeafPVS (sv.worldmodel->brush.leafs + i, + sv.worldmodel), rowbytes); if (i == 0) continue; @@ -402,7 +403,7 @@ SV_SpawnServer (const char *server) sv.model_precache[0] = sv_pr_state.pr_strings; sv.model_precache[1] = sv.modelname; sv.models[1] = sv.worldmodel; - for (i = 1; i < sv.worldmodel->numsubmodels; i++) { + for (i = 1; i < sv.worldmodel->brush.numsubmodels; i++) { sv.model_precache[1 + i] = localmodels[i]; sv.models[i + 1] = Mod_ForName (localmodels[i], false); } @@ -443,7 +444,7 @@ SV_SpawnServer (const char *server) ED_LoadFromFile (&sv_pr_state, (char *) buf); free (buf); } else { - ED_LoadFromFile (&sv_pr_state, sv.worldmodel->entities); + ED_LoadFromFile (&sv_pr_state, sv.worldmodel->brush.entities); } // look up some model indexes for specialized message compression diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 7298dc74a..b8dc58de0 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -506,7 +506,7 @@ PF_newcheckclient (progs_t *pr, int check) VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); leaf = Mod_PointInLeaf (org, sv.worldmodel); pvs = Mod_LeafPVS (leaf, sv.worldmodel); - memcpy (checkpvs, pvs, (sv.worldmodel->numleafs + 7) >> 3); + memcpy (checkpvs, pvs, (sv.worldmodel->brush.numleafs + 7) >> 3); return i; } @@ -551,7 +551,7 @@ PF_checkclient (progs_t *pr) self = PROG_TO_EDICT (pr, *sv_globals.self); VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view); leaf = Mod_PointInLeaf (view, sv.worldmodel); - l = (leaf - sv.worldmodel->leafs) - 1; + l = (leaf - sv.worldmodel->brush.leafs) - 1; if ((l < 0) || !(checkpvs[l >> 3] & (1 << (l & 7)))) { c_notvis++; RETURN_EDICT (pr, sv.edicts); diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index 400b9484e..0948e6f18 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -297,12 +297,13 @@ SV_Multicast (const vec3_t origin, int to) int leafnum, j; mleaf_t *leaf; qboolean reliable; + mod_brush_t *brush = &sv.worldmodel->brush; leaf = Mod_PointInLeaf (origin, sv.worldmodel); if (!leaf) leafnum = 0; else - leafnum = leaf - sv.worldmodel->leafs; + leafnum = leaf - sv.worldmodel->brush.leafs; reliable = false; @@ -316,13 +317,13 @@ SV_Multicast (const vec3_t origin, int to) case MULTICAST_PHS_R: reliable = true; // intentional fallthrough case MULTICAST_PHS: - mask = sv.phs + leafnum * 4 * ((sv.worldmodel->numleafs + 31) >> 5); + mask = sv.phs + leafnum * 4 * ((brush->numleafs + 31) >> 5); break; case MULTICAST_PVS_R: reliable = true; // intentional fallthrough case MULTICAST_PVS: - mask = sv.pvs + leafnum * 4 * ((sv.worldmodel->numleafs + 31) >> 5); + mask = sv.pvs + leafnum * 4 * ((brush->numleafs + 31) >> 5); break; default: @@ -347,7 +348,7 @@ SV_Multicast (const vec3_t origin, int to) sv.worldmodel); if (leaf) { // -1 is because pvs rows are 1 based, not 0 based like leafs - leafnum = leaf - sv.worldmodel->leafs - 1; + leafnum = leaf - brush->leafs - 1; if (!(mask[leafnum >> 3] & (1 << (leafnum & 7)))) { // SV_Printf ("supressed multicast\n"); continue; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 3fba2c17f..12c3de010 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -335,14 +335,15 @@ SV_PreSpawn_f (void *unused) // Sys_MaskPrintf (SYS_DEV, , "Client check = %d\n", check); - if (sv_mapcheck->int_val && check != sv.worldmodel->checksum && - check != sv.worldmodel->checksum2) { + if (sv_mapcheck->int_val && check != sv.worldmodel->brush.checksum && + check != sv.worldmodel->brush.checksum2) { SV_ClientPrintf (1, host_client, PRINT_HIGH, "Map model file does " "not match (%s), %i != %i/%i.\n" "You may need a new version of the map, or the " "proper install files.\n", - sv.modelname, check, sv.worldmodel->checksum, - sv.worldmodel->checksum2); + sv.modelname, check, + sv.worldmodel->brush.checksum, + sv.worldmodel->brush.checksum2); SV_DropClient (host_client); return; } diff --git a/qw/source/world.c b/qw/source/world.c index bbf4d930e..393daaf6f 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -245,7 +245,7 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, PR_GetString (&sv_pr_state, SVstring (ent, classname))); - hull_list = model->hull_list; + hull_list = model->brush.hull_list; } if (hull_list) { // decide which clipping hull to use, based on the size @@ -425,7 +425,7 @@ SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) leaf = (mleaf_t *) node; edict_leaf = alloc_edict_leaf (); - edict_leaf->leafnum = leaf - sv.worldmodel->leafs - 1; + edict_leaf->leafnum = leaf - sv.worldmodel->brush.leafs - 1; edict_leaf->next = SVdata (ent)->leafs; SVdata (ent)->leafs = edict_leaf; return; @@ -497,7 +497,7 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers) // link to PVS leafs free_edict_leafs (&SVdata (ent)->leafs); if (SVfloat (ent, modelindex)) - SV_FindTouchedLeafs (ent, sv.worldmodel->nodes); + SV_FindTouchedLeafs (ent, sv.worldmodel->brush.nodes); if (SVfloat (ent, solid) == SOLID_NOT) return; @@ -560,7 +560,7 @@ SV_PointContents (const vec3_t p) { int cont; - cont = SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); + cont = SV_HullPointContents (&sv.worldmodel->brush.hulls[0], 0, p); if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN) cont = CONTENTS_WATER; return cont; @@ -569,7 +569,7 @@ SV_PointContents (const vec3_t p) int SV_TruePointContents (const vec3_t p) { - return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); + return SV_HullPointContents (&sv.worldmodel->brush.hulls[0], 0, p); } /* @@ -991,7 +991,7 @@ SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) vec3_t boxmins, boxmaxs, offset; // check world first - hull = &sv.worldmodel->hulls[1]; + hull = &sv.worldmodel->brush.hulls[1]; if (SV_HullPointContents (hull, hull->firstclipnode, origin) != CONTENTS_EMPTY) return sv.edicts; From ea72d0c60e9e2ead63fbfdaa96a62d16c52cde86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Feb 2021 21:11:45 +0900 Subject: [PATCH 1297/3664] [model] Clean up the globals for alias models --- include/QF/Vulkan/qf_alias.h | 12 +- include/QF/model.h | 11 -- include/QF/plugin/vid_render.h | 12 +- include/mod_internal.h | 47 ++++--- libs/models/alias/gl_mesh.c | 118 ++++++++--------- libs/models/alias/gl_model_alias.c | 51 ++++---- libs/models/alias/glsl_model_alias.c | 75 +++++------ libs/models/alias/model_alias.c | 161 +++++++++++++----------- libs/models/alias/sw_model_alias.c | 75 ++++++----- libs/models/alias/vulkan_model_alias.c | 82 ++++++------ libs/video/renderer/vid_render_sw.c | 4 +- libs/video/renderer/vid_render_sw32.c | 4 +- libs/video/renderer/vid_render_vulkan.c | 18 +-- 13 files changed, 350 insertions(+), 320 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index dac8f4ca7..ebf4f6996 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -102,14 +102,16 @@ typedef struct aliasctx_s { struct vulkan_ctx_s; struct entity_s; -void *Vulkan_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, - int gnum, qboolean group, +struct mod_alias_ctx_s; +void *Vulkan_Mod_LoadSkin (struct mod_alias_ctx_s *alias_ctx, byte *skin, + int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc, struct vulkan_ctx_s *ctx); -void Vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr, +void Vulkan_Mod_FinalizeAliasModel (struct mod_alias_ctx_s *alias_ctx, struct vulkan_ctx_s *ctx); -void Vulkan_Mod_LoadExternalSkins (model_t *mod, struct vulkan_ctx_s *ctx); -void Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, +void Vulkan_Mod_LoadExternalSkins (struct mod_alias_ctx_s *alias_ctx, + struct vulkan_ctx_s *ctx); +void Vulkan_Mod_MakeAliasModelDisplayLists (struct mod_alias_ctx_s *alias_ctx, void *_m, int _s, int extra, struct vulkan_ctx_s *ctx); diff --git a/include/QF/model.h b/include/QF/model.h index 6d7dfe61d..a05d489a4 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -28,7 +28,6 @@ #ifndef __QF_model_h #define __QF_model_h -#include "QF/darray.h" #include "QF/qtypes.h" #include "QF/bspfile.h" #include "QF/spritegn.h" @@ -372,16 +371,6 @@ typedef struct { maliasframedesc_t frames[1]; } aliashdr_t; -typedef struct stvertset_s DARRAY_TYPE (stvert_t) stvertset_t; -typedef struct mtriangleset_s DARRAY_TYPE (mtriangle_t) mtriangleset_t; -typedef struct trivertxset_s DARRAY_TYPE (trivertx_t *) trivertxset_t; -extern aliashdr_t *pheader; -extern stvertset_t stverts; -extern mtriangleset_t triangles; -extern trivertxset_t poseverts; -extern int aliasbboxmins[3]; -extern int aliasbboxmaxs[3]; - // Whole model ================================================================ typedef enum {mod_brush, mod_sprite, mod_alias, mod_iqm} modtype_t; diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index bc80780e4..5d2ed3d18 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -37,6 +37,8 @@ struct plitem_s; struct cvar_s; struct skin_s; +struct mod_alias_ctx_s; + /* All video plugins must export these functions */ @@ -88,13 +90,13 @@ typedef struct vid_model_funcs_s { void (*Mod_LoadAliasModel) (model_t *mod, void *buffer, cache_allocator_t allocator); void (*Mod_LoadSpriteModel) (model_t *mod, void *buffer); - void (*Mod_MakeAliasModelDisplayLists) (model_t *m, aliashdr_t *hdr, + void (*Mod_MakeAliasModelDisplayLists) (struct mod_alias_ctx_s *alias_ctx, void *_m, int _s, int extra); - void *(*Mod_LoadSkin) (model_t *mod, byte *skin, int skinsize, int snum, - int gnum, + void *(*Mod_LoadSkin) (struct mod_alias_ctx_s *alias_ctx, byte *skin, + int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc); - void (*Mod_FinalizeAliasModel) (model_t *m, aliashdr_t *hdr); - void (*Mod_LoadExternalSkins) (model_t *mod); + void (*Mod_FinalizeAliasModel) (struct mod_alias_ctx_s *alias_ctx); + void (*Mod_LoadExternalSkins) (struct mod_alias_ctx_s *alias_ctx); void (*Mod_IQMFinish) (model_t *mod); int alias_cache; void (*Mod_SpriteLoadTexture) (model_t *mod, mspriteframe_t *pspriteframe, diff --git a/include/mod_internal.h b/include/mod_internal.h index f459bbeaa..d498ee9ce 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -1,11 +1,27 @@ #ifndef __mod_internal_h #define __mod_internal_h +#include "QF/darray.h" #include "QF/iqm.h" #include "QF/model.h" #include "QF/skin.h" #include "QF/plugin/vid_render.h" +typedef struct stvertset_s DARRAY_TYPE (stvert_t) stvertset_t; +typedef struct mtriangleset_s DARRAY_TYPE (mtriangle_t) mtriangleset_t; +typedef struct trivertxset_s DARRAY_TYPE (trivertx_t *) trivertxset_t; + +typedef struct mod_alias_ctx_s { + aliashdr_t *header; + model_t *mod; + stvertset_t stverts; + mtriangleset_t triangles; + trivertxset_t poseverts; + int aliasbboxmins[3]; + int aliasbboxmaxs[3]; + +} mod_alias_ctx_t; + int Mod_CalcFullbright (const byte *in, byte *out, int pixels); void Mod_ClearFullbright (const byte *in, byte *out, int pixels); void Mod_FloodFillSkin (byte *skin, int skinwidth, int skinheight); @@ -22,28 +38,29 @@ struct vulkan_ctx_s; extern vid_model_funcs_t *m_funcs; -void gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, +void gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra); -void *gl_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, - int gnum, qboolean group, maliasskindesc_t *skindesc); -void gl_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr); -void gl_Mod_LoadExternalSkins (model_t *mod); +void *gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, + int snum, int gnum, qboolean group, + maliasskindesc_t *skindesc); +void gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx); +void gl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx); void gl_Mod_IQMFinish (model_t *mod); -void glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, +void glsl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra); -void *glsl_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, - int gnum, qboolean group, maliasskindesc_t *skindesc); -void glsl_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr); -void glsl_Mod_LoadExternalSkins (model_t *mod); +void *glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, + int snum, int gnum, qboolean group, + maliasskindesc_t *skindesc); +void glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx); +void glsl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx); void glsl_Mod_IQMFinish (model_t *mod); -void sw_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, +void sw_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra); -void *sw_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, - int gnum, qboolean group, maliasskindesc_t *skindesc); -void sw_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr); -void sw_Mod_LoadExternalSkins (model_t *mod); +void *sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, + int snum, int gnum, qboolean group, + maliasskindesc_t *skindesc); void sw_Mod_IQMFinish (model_t *mod); void gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp); diff --git a/libs/models/alias/gl_mesh.c b/libs/models/alias/gl_mesh.c index 6820000cf..73c65b56d 100644 --- a/libs/models/alias/gl_mesh.c +++ b/libs/models/alias/gl_mesh.c @@ -49,9 +49,6 @@ // ALIAS MODEL DISPLAY LIST GENERATION ======================================== -static model_t *aliasmodel; -static aliashdr_t *paliashdr; - static qboolean *used; static int used_size; @@ -126,14 +123,15 @@ add_strip (int vert, int tri) } static int -StripLength (int starttri, int startv) +StripLength (mod_alias_ctx_t *alias_ctx, int starttri, int startv) { + aliashdr_t *header = alias_ctx->header; int m1, m2, j, k; mtriangle_t *last, *check; used[starttri] = 2; - last = &triangles.a[starttri]; + last = &alias_ctx->triangles.a[starttri]; stripcount = 0; add_strip (last->vertindex[(startv) % 3], starttri); @@ -145,8 +143,8 @@ StripLength (int starttri, int startv) // look for a matching triangle nexttri: - for (j = starttri + 1, check = &triangles.a[starttri + 1]; - j < pheader->mdl.numtris; j++, check++) { + for (j = starttri + 1, check = &alias_ctx->triangles.a[starttri + 1]; + j < header->mdl.numtris; j++, check++) { if (check->facesfront != last->facesfront) continue; for (k = 0; k < 3; k++) { @@ -176,7 +174,7 @@ nexttri: done: // clear the temp used flags - for (j = starttri + 1; j < pheader->mdl.numtris; j++) + for (j = starttri + 1; j < header->mdl.numtris; j++) if (used[j] == 2) used[j] = 0; @@ -184,14 +182,15 @@ done: } static int -FanLength (int starttri, int startv) +FanLength (mod_alias_ctx_t *alias_ctx, int starttri, int startv) { + aliashdr_t *header = alias_ctx->header; int m1, m2, j, k; mtriangle_t *last, *check; used[starttri] = 2; - last = &triangles.a[starttri]; + last = &alias_ctx->triangles.a[starttri]; stripcount = 0; add_strip (last->vertindex[(startv) % 3], starttri); @@ -204,8 +203,8 @@ FanLength (int starttri, int startv) // look for a matching triangle nexttri: - for (j = starttri + 1, check = &triangles.a[starttri + 1]; - j < pheader->mdl.numtris; j++, check++) { + for (j = starttri + 1, check = &alias_ctx->triangles.a[starttri + 1]; + j < header->mdl.numtris; j++, check++) { if (check->facesfront != last->facesfront) continue; for (k = 0; k < 3; k++) { @@ -232,7 +231,7 @@ FanLength (int starttri, int startv) done: // clear the temp used flags - for (j = starttri + 1; j < pheader->mdl.numtris; j++) + for (j = starttri + 1; j < header->mdl.numtris; j++) if (used[j] == 2) used[j] = 0; @@ -246,8 +245,9 @@ FanLength (int starttri, int startv) for the model, which holds for all frames */ static void -BuildTris (void) +BuildTris (mod_alias_ctx_t *alias_ctx) { + aliashdr_t *header = alias_ctx->header; float s, t; int bestlen, len, startv, type, i, j, k; int besttype = 0; @@ -257,10 +257,10 @@ BuildTris (void) numorder = 0; numcommands = 0; stripcount = 0; - alloc_used (pheader->mdl.numtris); + alloc_used (header->mdl.numtris); memset (used, 0, used_size * sizeof (used[0])); - for (i = 0; i < pheader->mdl.numtris; i++) { + for (i = 0; i < header->mdl.numtris; i++) { // pick an unused triangle and start the trifan if (used[i]) continue; @@ -270,9 +270,9 @@ BuildTris (void) // type = 1; for (startv = 0; startv < 3; startv++) { if (type == 1) - len = StripLength (i, startv); + len = StripLength (alias_ctx, i, startv); else - len = FanLength (i, startv); + len = FanLength (alias_ctx, i, startv); if (len > bestlen) { besttype = type; bestlen = len; @@ -304,12 +304,13 @@ BuildTris (void) add_vertex (k); // emit s/t coords into the commands stream - s = stverts.a[k].s; - t = stverts.a[k].t; - if (!triangles.a[besttris[0]].facesfront && stverts.a[k].onseam) - s += pheader->mdl.skinwidth / 2; // on back side - s = (s + 0.5) / pheader->mdl.skinwidth; - t = (t + 0.5) / pheader->mdl.skinheight; + s = alias_ctx->stverts.a[k].s; + t = alias_ctx->stverts.a[k].t; + if (!alias_ctx->triangles.a[besttris[0]].facesfront + && alias_ctx->stverts.a[k].onseam) + s += header->mdl.skinwidth / 2; // on back side + s = (s + 0.5) / header->mdl.skinwidth; + t = (t + 0.5) / header->mdl.skinheight; memcpy (&tmp, &s, 4); add_command (tmp); @@ -321,10 +322,10 @@ BuildTris (void) add_command (0); // end of list marker Sys_MaskPrintf (SYS_DEV, "%3i tri %3i vert %3i cmd\n", - pheader->mdl.numtris, numorder, numcommands); + header->mdl.numtris, numorder, numcommands); allverts += numorder; - alltris += pheader->mdl.numtris; + alltris += header->mdl.numtris; if (bestverts) free (bestverts); @@ -333,9 +334,10 @@ BuildTris (void) } void -gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, +gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra) { + aliashdr_t *header = alias_ctx->header; dstring_t *cache, *fullpath; unsigned char model_digest[MDFOUR_DIGEST_BYTES]; unsigned char mesh_digest[MDFOUR_DIGEST_BYTES]; @@ -345,24 +347,21 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, qboolean remesh = true; qboolean do_cache = false; - aliasmodel = m; - paliashdr = hdr; - cache = dstring_new (); fullpath = dstring_new (); if (!gl_alias_render_tri->int_val) { if (gl_mesh_cache->int_val - && gl_mesh_cache->int_val <= paliashdr->mdl.numtris) { + && gl_mesh_cache->int_val <= header->mdl.numtris) { do_cache = true; mdfour (model_digest, (unsigned char *) _m, _s); // look for a cached version dstring_copystr (cache, "glquake/"); - dstring_appendstr (cache, m->path); - QFS_StripExtension (m->path + strlen ("progs/"), + dstring_appendstr (cache, alias_ctx->mod->path); + QFS_StripExtension (alias_ctx->mod->path + strlen ("progs/"), cache->str + strlen ("glquake/")); dstring_appendstr (cache, ".qfms"); @@ -433,9 +432,9 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, } if (remesh) { // build it from scratch - Sys_MaskPrintf (SYS_DEV, "meshing %s...\n", m->path); + Sys_MaskPrintf (SYS_DEV, "meshing %s...\n", alias_ctx->mod->path); - BuildTris (); // trifans or lists + BuildTris (alias_ctx); // trifans or lists if (do_cache) { // save out the cached version @@ -474,35 +473,36 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, } // save the data out - paliashdr->poseverts = numorder; + header->poseverts = numorder; cmds = Hunk_Alloc (numcommands * sizeof (int)); - paliashdr->commands = (byte *) cmds - (byte *) paliashdr; + header->commands = (byte *) cmds - (byte *) header; memcpy (cmds, commands, numcommands * sizeof (int)); } else { tex_coord_t *tex_coord; numorder = 0; - for (i=0; i < pheader->mdl.numtris; i++) { - add_vertex(triangles.a[i].vertindex[0]); - add_vertex(triangles.a[i].vertindex[1]); - add_vertex(triangles.a[i].vertindex[2]); + for (i=0; i < header->mdl.numtris; i++) { + add_vertex(alias_ctx->triangles.a[i].vertindex[0]); + add_vertex(alias_ctx->triangles.a[i].vertindex[1]); + add_vertex(alias_ctx->triangles.a[i].vertindex[2]); } - paliashdr->poseverts = numorder; + header->poseverts = numorder; tex_coord = Hunk_Alloc (numorder * sizeof(tex_coord_t)); - paliashdr->tex_coord = (byte *) tex_coord - (byte *) paliashdr; + header->tex_coord = (byte *) tex_coord - (byte *) header; for (i=0; i < numorder; i++) { float s, t; int k; k = vertexorder[i]; - s = stverts.a[k].s; - t = stverts.a[k].t; - if (!triangles.a[i/3].facesfront && stverts.a[k].onseam) - s += pheader->mdl.skinwidth / 2; // on back side - s = (s + 0.5) / pheader->mdl.skinwidth; - t = (t + 0.5) / pheader->mdl.skinheight; + s = alias_ctx->stverts.a[k].s; + t = alias_ctx->stverts.a[k].t; + if (!alias_ctx->triangles.a[i/3].facesfront + && alias_ctx->stverts.a[k].onseam) + s += header->mdl.skinwidth / 2; // on back side + s = (s + 0.5) / header->mdl.skinwidth; + t = (t + 0.5) / header->mdl.skinheight; tex_coord[i].st[0] = s; tex_coord[i].st[1] = t; } @@ -510,11 +510,11 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, if (extra) { trivertx16_t *verts; - verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts + verts = Hunk_Alloc (header->numposes * header->poseverts * sizeof (trivertx16_t)); - paliashdr->posedata = (byte *) verts - (byte *) paliashdr; - for (i = 0; i < paliashdr->numposes; i++) { - trivertx_t *pv = poseverts.a[i]; + header->posedata = (byte *) verts - (byte *) header; + for (i = 0; i < header->numposes; i++) { + trivertx_t *pv = alias_ctx->poseverts.a[i]; for (j = 0; j < numorder; j++) { trivertx16_t v; // convert MD16's split coordinates into something a little @@ -523,21 +523,21 @@ gl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, // fractional bits of the vertex, giving 8.8. However, it's // easier for us to multiply everything by 256 and adjust the // model scale appropriately - VectorMultAdd (pv[vertexorder[j] + hdr->mdl.numverts].v, + VectorMultAdd (pv[vertexorder[j] + header->mdl.numverts].v, 256, pv[vertexorder[j]].v, v.v); v.lightnormalindex = - poseverts.a[i][vertexorder[j]].lightnormalindex; + alias_ctx->poseverts.a[i][vertexorder[j]].lightnormalindex; *verts++ = v; } } } else { trivertx_t *verts; - verts = Hunk_Alloc (paliashdr->numposes * paliashdr->poseverts + verts = Hunk_Alloc (header->numposes * header->poseverts * sizeof (trivertx_t)); - paliashdr->posedata = (byte *) verts - (byte *) paliashdr; - for (i = 0; i < paliashdr->numposes; i++) { + header->posedata = (byte *) verts - (byte *) header; + for (i = 0; i < header->numposes; i++) { for (j = 0; j < numorder; j++) - *verts++ = poseverts.a[i][vertexorder[j]]; + *verts++ = alias_ctx->poseverts.a[i][vertexorder[j]]; } } dstring_delete (cache); diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index dec3a6e98..4b8d6ccb7 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -53,36 +53,38 @@ #include "compat.h" void * -gl_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc) +gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, + int snum, int gnum, qboolean group, + maliasskindesc_t *skindesc) { + aliashdr_t *header = alias_ctx->header; byte *pskin; char modname[MAX_QPATH + 4]; int fb_texnum = 0, texnum = 0; dstring_t *name = dstring_new (); - pskin = Hunk_AllocName (skinsize, mod->name); - skindesc->skin = (byte *) pskin - (byte *) pheader; + pskin = Hunk_AllocName (skinsize, alias_ctx->mod->name); + skindesc->skin = (byte *) pskin - (byte *) header; memcpy (pskin, skin, skinsize); - Mod_FloodFillSkin (pskin, pheader->mdl.skinwidth, pheader->mdl.skinheight); + Mod_FloodFillSkin (pskin, header->mdl.skinwidth, header->mdl.skinheight); // save 8 bit texels for the player model to remap // FIXME remove model restriction - if (strequal (mod->path, "progs/player.mdl")) - gl_Skin_SetPlayerSkin (pheader->mdl.skinwidth, pheader->mdl.skinheight, + if (strequal (alias_ctx->mod->path, "progs/player.mdl")) + gl_Skin_SetPlayerSkin (header->mdl.skinwidth, header->mdl.skinheight, pskin); - QFS_StripExtension (mod->path, modname); + QFS_StripExtension (alias_ctx->mod->path, modname); - if (!mod->fullbright) { + if (!alias_ctx->mod->fullbright) { if (group) { dsprintf (name, "fb_%s_%i_%i", modname, snum, gnum); } else { dsprintf (name, "fb_%s_%i", modname, snum); } - fb_texnum = Mod_Fullbright (pskin, pheader->mdl.skinwidth, - pheader->mdl.skinheight, name->str); + fb_texnum = Mod_Fullbright (pskin, header->mdl.skinwidth, + header->mdl.skinheight, name->str); Sys_MaskPrintf (SYS_GLT, "%s %d\n", name->str, fb_texnum); } if (group) { @@ -90,23 +92,25 @@ gl_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, int gnum, } else { dsprintf (name, "%s_%i", modname, snum); } - texnum = GL_LoadTexture (name->str, pheader->mdl.skinwidth, - pheader->mdl.skinheight, pskin, true, false, 1); + texnum = GL_LoadTexture (name->str, header->mdl.skinwidth, + header->mdl.skinheight, pskin, true, false, 1); Sys_MaskPrintf (SYS_GLT, "%s %d\n", name->str, texnum); skindesc->texnum = texnum; skindesc->fb_texnum = fb_texnum; - mod->hasfullbrights = fb_texnum; + alias_ctx->mod->hasfullbrights = fb_texnum; dstring_delete (name); // alpha param was true for non group skins return skin + skinsize; } void -gl_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr) +gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx) { - if (strequal (m->path, "progs/eyes.mdl")) { - hdr->mdl.scale_origin[2] -= (22 + 8); - VectorScale (hdr->mdl.scale, 2, hdr->mdl.scale); + aliashdr_t *header = alias_ctx->header; + + if (strequal (alias_ctx->mod->path, "progs/eyes.mdl")) { + header->mdl.scale_origin[2] -= (22 + 8); + VectorScale (header->mdl.scale, 2, header->mdl.scale); } } @@ -150,25 +154,26 @@ Mod_LoadExternalSkin (maliasskindesc_t *pskindesc, char *filename) } void -gl_Mod_LoadExternalSkins (model_t *mod) +gl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx) { + aliashdr_t *header = alias_ctx->header; char modname[MAX_QPATH + 4]; int i, j; maliasskindesc_t *pskindesc; maliasskingroup_t *pskingroup; dstring_t *filename = dstring_new (); - QFS_StripExtension (mod->path, modname); + QFS_StripExtension (alias_ctx->mod->path, modname); - for (i = 0; i < pheader->mdl.numskins; i++) { + for (i = 0; i < header->mdl.numskins; i++) { pskindesc = ((maliasskindesc_t *) - ((byte *) pheader + pheader->skindesc)) + i; + ((byte *) header + header->skindesc)) + i; if (pskindesc->type == ALIAS_SKIN_SINGLE) { dsprintf (filename, "%s_%i", modname, i); Mod_LoadExternalSkin (pskindesc, filename->str); } else { pskingroup = (maliasskingroup_t *) - ((byte *) pheader + pskindesc->skin); + ((byte *) header + pskindesc->skin); for (j = 0; j < pskingroup->numskins; j++) { dsprintf (filename, "%s_%i_%i", modname, i, j); diff --git a/libs/models/alias/glsl_model_alias.c b/libs/models/alias/glsl_model_alias.c index 609fa01b7..c48500ad7 100644 --- a/libs/models/alias/glsl_model_alias.c +++ b/libs/models/alias/glsl_model_alias.c @@ -58,24 +58,24 @@ static void glsl_alias_clear (model_t *m, void *data) { int i, j; - aliashdr_t *hdr; + aliashdr_t *header; GLuint bufs[2]; maliasskindesc_t *skins; maliasskingroup_t *group; m->needload = true; - if (!(hdr = m->aliashdr)) - hdr = Cache_Get (&m->cache); + if (!(header = m->aliashdr)) + header = Cache_Get (&m->cache); - bufs[0] = hdr->posedata; - bufs[1] = hdr->commands; + bufs[0] = header->posedata; + bufs[1] = header->commands; qfeglDeleteBuffers (2, bufs); - skins = ((maliasskindesc_t *) ((byte *) hdr + hdr->skindesc)); - for (i = 0; i < hdr->mdl.numskins; i++) { + skins = ((maliasskindesc_t *) ((byte *) header + header->skindesc)); + for (i = 0; i < header->mdl.numskins; i++) { if (skins[i].type == ALIAS_SKIN_GROUP) { - group = (maliasskingroup_t *) ((byte *) hdr + skins[i].skin); + group = (maliasskingroup_t *) ((byte *) header + skins[i].skin); for (j = 0; j < group->numskins; j++) { GLSL_ReleaseTexture (group->skindescs[j].texnum); } @@ -91,44 +91,49 @@ glsl_alias_clear (model_t *m, void *data) } void * -glsl_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc) +glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, + int snum, int gnum, qboolean group, + maliasskindesc_t *skindesc) { + aliashdr_t *header = alias_ctx->header; byte *tskin; const char *name; int w, h; - w = pheader->mdl.skinwidth; - h = pheader->mdl.skinheight; + w = header->mdl.skinwidth; + h = header->mdl.skinheight; tskin = malloc (skinsize); memcpy (tskin, skin, skinsize); Mod_FloodFillSkin (tskin, w, h); if (group) - name = va (0, "%s_%i_%i", mod->path, snum, gnum); + name = va (0, "%s_%i_%i", alias_ctx->mod->path, snum, gnum); else - name = va (0, "%s_%i", mod->path, snum); + name = va (0, "%s_%i", alias_ctx->mod->path, snum); skindesc->texnum = GLSL_LoadQuakeTexture (name, w, h, tskin); free (tskin); return skin + skinsize; } void -glsl_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr) +glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx) { - if (hdr->mdl.ident == HEADER_MDL16) - VectorScale (hdr->mdl.scale, 1/256.0, hdr->mdl.scale); - m->clear = glsl_alias_clear; + aliashdr_t *header = alias_ctx->header; + + if (header->mdl.ident == HEADER_MDL16) + VectorScale (header->mdl.scale, 1/256.0, header->mdl.scale); + alias_ctx->mod->clear = glsl_alias_clear; } void -glsl_Mod_LoadExternalSkins (model_t *mod) +glsl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx) { } void -glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, +glsl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra) { + aliashdr_t *header = alias_ctx->header; mtriangle_t *tris; stvert_t *st; aliasvrt_t *verts; @@ -142,12 +147,12 @@ glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int i, j; int pose; - numverts = hdr->mdl.numverts; - numtris = hdr->mdl.numtris; + numverts = header->mdl.numverts; + numtris = header->mdl.numtris; // copy triangles before editing them tris = malloc (numtris * sizeof (mtriangle_t)); - memcpy (tris, triangles.a, numtris * sizeof (mtriangle_t)); + memcpy (tris, alias_ctx->triangles.a, numtris * sizeof (mtriangle_t)); // initialize indexmap to -1 (unduplicated). any other value indicates // both that the vertex has been duplicated and the index of the @@ -157,7 +162,7 @@ glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, // copy stverts. need space for duplicates st = malloc (2 * numverts * sizeof (stvert_t)); - memcpy (st, stverts.a, numverts * sizeof (stvert_t)); + memcpy (st, alias_ctx->stverts.a, numverts * sizeof (stvert_t)); // check for onseam verts, and duplicate any that are associated with // back-facing triangles. the s coordinate is shifted right by half @@ -168,7 +173,7 @@ glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, if (st[vind].onseam && !tris[i].facesfront) { if (indexmap[vind] == -1) { st[numverts] = st[vind]; - st[numverts].s += hdr->mdl.skinwidth / 2; + st[numverts].s += header->mdl.skinwidth / 2; indexmap[vind] = numverts++; } tris[i].vertindex[j] = indexmap[vind]; @@ -178,13 +183,13 @@ glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, // we now know exactly how many vertices we need, so built the vertex // array - vertexsize = hdr->numposes * numverts * sizeof (aliasvrt_t); + vertexsize = header->numposes * numverts * sizeof (aliasvrt_t); verts = malloc (vertexsize); - for (i = 0, pose = 0; i < hdr->numposes; i++, pose += numverts) { - for (j = 0; j < hdr->mdl.numverts; j++) { - pv = &poseverts.a[i][j]; + for (i = 0, pose = 0; i < header->numposes; i++, pose += numverts) { + for (j = 0; j < header->mdl.numverts; j++) { + pv = &alias_ctx->poseverts.a[i][j]; if (extra) { - VectorMultAdd (pv[hdr->mdl.numverts].v, 256, pv->v, + VectorMultAdd (pv[header->mdl.numverts].v, 256, pv->v, verts[pose + j].vertex); } else { VectorCopy (pv->v, verts[pose + j].vertex); @@ -218,14 +223,14 @@ glsl_Mod_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, // finished with tris free (tris); - hdr->poseverts = numverts; + header->poseverts = numverts; // load the vertex data and indices into GL qfeglGenBuffers (2, bnum); - hdr->posedata = bnum[0]; - hdr->commands = bnum[1]; - qfeglBindBuffer (GL_ARRAY_BUFFER, hdr->posedata); - qfeglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, hdr->commands); + header->posedata = bnum[0]; + header->commands = bnum[1]; + qfeglBindBuffer (GL_ARRAY_BUFFER, header->posedata); + qfeglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, header->commands); qfeglBufferData (GL_ARRAY_BUFFER, vertexsize, verts, GL_STATIC_DRAW); qfeglBufferData (GL_ELEMENT_ARRAY_BUFFER, indexsize, indices, GL_STATIC_DRAW); diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index e4225daea..727957fe5 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -49,22 +49,11 @@ #include "mod_internal.h" #include "r_local.h" -aliashdr_t *pheader; - -stvertset_t stverts = { 0, 0, 256 }; -mtriangleset_t triangles = { 0, 0, 256 }; - -// a pose is a single set of vertexes. a frame may be an animating -// sequence of poses -trivertxset_t poseverts = { 0, 0, 256 };; -int posenum = 0; -int aliasbboxmins[3], aliasbboxmaxs[3]; - - static void * -Mod_LoadAllSkins (model_t *mod, int numskins, daliasskintype_t *pskintype, - int *pskinindex) +Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins, + daliasskintype_t *pskintype, int *pskinindex) { + aliashdr_t *header = alias_ctx->header; byte *skin; float *poutskinintervals; int groupskins, skinsize, gnum, snum, t; @@ -76,34 +65,34 @@ Mod_LoadAllSkins (model_t *mod, int numskins, daliasskintype_t *pskintype, if (numskins < 1 || numskins > MAX_SKINS) Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d", numskins); - skinsize = pheader->mdl.skinwidth * pheader->mdl.skinheight; + skinsize = header->mdl.skinwidth * header->mdl.skinheight; pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), - mod->name); + alias_ctx->mod->name); - *pskinindex = (byte *) pskindesc - (byte *) pheader; + *pskinindex = (byte *) pskindesc - (byte *) header; for (snum = 0; snum < numskins; snum++) { pskindesc[snum].type = pskintype->type; if (pskintype->type == ALIAS_SKIN_SINGLE) { skin = (byte *) (pskintype + 1); - skin = m_funcs->Mod_LoadSkin (mod, skin, skinsize, snum, 0, false, - &pskindesc[snum]); + skin = m_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize, snum, 0, + false, &pskindesc[snum]); } else { pskintype++; pinskingroup = (daliasskingroup_t *) pskintype; groupskins = LittleLong (pinskingroup->numskins); t = field_offset (maliasskingroup_t, skindescs[groupskins]); - paliasskingroup = Hunk_AllocName (t, mod->name); + paliasskingroup = Hunk_AllocName (t, alias_ctx->mod->name); paliasskingroup->numskins = groupskins; - pskindesc[snum].skin = (byte *) paliasskingroup - (byte *) pheader; + pskindesc[snum].skin = (byte *) paliasskingroup - (byte *) header; pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1); poutskinintervals = Hunk_AllocName (groupskins * sizeof (float), - mod->name); + alias_ctx->mod->name); paliasskingroup->intervals = - (byte *) poutskinintervals - (byte *) pheader; + (byte *) poutskinintervals - (byte *) header; for (gnum = 0; gnum < groupskins; gnum++) { *poutskinintervals = LittleFloat (pinskinintervals->interval); if (*poutskinintervals <= 0) @@ -118,8 +107,8 @@ Mod_LoadAllSkins (model_t *mod, int numskins, daliasskintype_t *pskintype, for (gnum = 0; gnum < groupskins; gnum++) { paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE; - skin = mod_funcs->Mod_LoadSkin (mod, skin, skinsize, snum, - gnum, true, + skin = mod_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize, + snum, gnum, true, &paliasskingroup->skindescs[gnum]); } } @@ -130,9 +119,10 @@ Mod_LoadAllSkins (model_t *mod, int numskins, daliasskintype_t *pskintype, } static void * -Mod_LoadAliasFrame (model_t *mod, void *pin, int *posenum, +Mod_LoadAliasFrame (mod_alias_ctx_t *alias_ctx, void *pin, int *posenum, maliasframedesc_t *frame, int extra) { + aliashdr_t *header = alias_ctx->header; daliasframe_t *pdaliasframe; trivertx_t *pinframe; @@ -146,25 +136,29 @@ Mod_LoadAliasFrame (model_t *mod, void *pin, int *posenum, // byte values, don't worry about endianness VectorCopy (pdaliasframe->bboxmin.v, frame->bboxmin.v); VectorCopy (pdaliasframe->bboxmax.v, frame->bboxmax.v); - VectorCompMin (frame->bboxmin.v, aliasbboxmins, aliasbboxmins); - VectorCompMax (frame->bboxmax.v, aliasbboxmaxs, aliasbboxmaxs); + VectorCompMin (frame->bboxmin.v, alias_ctx->aliasbboxmins, + alias_ctx->aliasbboxmins); + VectorCompMax (frame->bboxmax.v, alias_ctx->aliasbboxmaxs, + alias_ctx->aliasbboxmaxs); pinframe = (trivertx_t *) (pdaliasframe + 1); - DARRAY_APPEND (&poseverts, pinframe); + DARRAY_APPEND (&alias_ctx->poseverts, pinframe); (*posenum)++; - pinframe += pheader->mdl.numverts; + pinframe += header->mdl.numverts; if (extra) - pinframe += pheader->mdl.numverts; + pinframe += header->mdl.numverts; return pinframe; } static void * -Mod_LoadAliasGroup (model_t *mod, void *pin, int *posenum, +Mod_LoadAliasGroup (mod_alias_ctx_t *alias_ctx, void *pin, int *posenum, maliasframedesc_t *frame, int extra) { + aliashdr_t *header = alias_ctx->header; + model_t *mod = alias_ctx->mod; daliasgroup_t *pingroup; daliasinterval_t *pin_intervals; float *poutintervals; @@ -182,17 +176,19 @@ Mod_LoadAliasGroup (model_t *mod, void *pin, int *posenum, paliasgroup = Hunk_AllocName (field_offset (maliasgroup_t, frames[numframes]), mod->name); paliasgroup->numframes = numframes; - frame->frame = (byte *) paliasgroup - (byte *) pheader; + frame->frame = (byte *) paliasgroup - (byte *) header; // these are byte values, so we don't have to worry about endianness VectorCopy (pingroup->bboxmin.v, frame->bboxmin.v); VectorCopy (pingroup->bboxmax.v, frame->bboxmax.v); - VectorCompMin (frame->bboxmin.v, aliasbboxmins, aliasbboxmins); - VectorCompMax (frame->bboxmax.v, aliasbboxmaxs, aliasbboxmaxs); + VectorCompMin (frame->bboxmin.v, alias_ctx->aliasbboxmins, + alias_ctx->aliasbboxmins); + VectorCompMax (frame->bboxmax.v, alias_ctx->aliasbboxmaxs, + alias_ctx->aliasbboxmaxs); pin_intervals = (daliasinterval_t *) (pingroup + 1); poutintervals = Hunk_AllocName (numframes * sizeof (float), mod->name); - paliasgroup->intervals = (byte *) poutintervals - (byte *) pheader; + paliasgroup->intervals = (byte *) poutintervals - (byte *) header; frame->interval = LittleFloat (pin_intervals->interval); for (i = 0; i < numframes; i++) { *poutintervals = LittleFloat (pin_intervals->interval); @@ -205,7 +201,8 @@ Mod_LoadAliasGroup (model_t *mod, void *pin, int *posenum, ptemp = (void *) pin_intervals; for (i = 0; i < numframes; i++) { maliasframedesc_t temp_frame; - ptemp = Mod_LoadAliasFrame (mod, ptemp, posenum, &temp_frame, extra); + ptemp = Mod_LoadAliasFrame (alias_ctx, ptemp, posenum, &temp_frame, + extra); memcpy (&paliasgroup->frames[i], &temp_frame, sizeof (paliasgroup->frames[i])); } @@ -225,6 +222,14 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) mdl_t *pinmodel, *pmodel; unsigned short crc; stvert_t *pinstverts; + mod_alias_ctx_t alias_ctx = {}; + aliashdr_t *header; + + alias_ctx.mod = mod; + //FIXME should be per batch rather than per model + DARRAY_INIT (&alias_ctx.poseverts, 256); + DARRAY_INIT (&alias_ctx.stverts, 256); + DARRAY_INIT (&alias_ctx.triangles, 256); if (LittleLong (* (unsigned int *) buffer) == HEADER_MDL16) extra = 1; // extra precision bytes @@ -244,12 +249,13 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) // allocate space for a working header, plus all the data except the // frames, skin and group info size = field_offset (aliashdr_t, frames[LittleLong (pinmodel->numframes)]); - pheader = Hunk_AllocName (size, mod->name); - memset (pheader, 0, size); - pmodel = &pheader->mdl; - pheader->model = (byte *) pmodel - (byte *) pheader; + header = Hunk_AllocName (size, mod->name); + memset (header, 0, size); + alias_ctx.header = header; + pmodel = &header->mdl; + header->model = (byte *) pmodel - (byte *) header; - pheader->crc = crc; + header->crc = crc; mod->flags = LittleLong (pinmodel->flags); @@ -264,20 +270,20 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) Sys_Error ("model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT); - DARRAY_RESIZE (&poseverts, 0); + DARRAY_RESIZE (&alias_ctx.poseverts, 0); pmodel->numverts = LittleLong (pinmodel->numverts); if (pmodel->numverts <= 0) Sys_Error ("model %s has no vertices", mod->name); - DARRAY_RESIZE (&stverts, pmodel->numverts); + DARRAY_RESIZE (&alias_ctx.stverts, pmodel->numverts); pmodel->numtris = LittleLong (pinmodel->numtris); if (pmodel->numtris <= 0) Sys_Error ("model %s has no triangles", mod->name); - DARRAY_RESIZE (&triangles, pmodel->numtris); + DARRAY_RESIZE (&alias_ctx.triangles, pmodel->numtris); pmodel->numframes = LittleLong (pinmodel->numframes); numframes = pmodel->numframes; @@ -296,73 +302,76 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) // load the skins pskintype = (daliasskintype_t *) &pinmodel[1]; - pskintype = Mod_LoadAllSkins (mod, pheader->mdl.numskins, pskintype, - &pheader->skindesc); + pskintype = Mod_LoadAllSkins (&alias_ctx, header->mdl.numskins, pskintype, + &header->skindesc); // load base s and t vertices pinstverts = (stvert_t *) pskintype; - for (i = 0; i < pheader->mdl.numverts; i++) { - stverts.a[i].onseam = LittleLong (pinstverts[i].onseam); - stverts.a[i].s = LittleLong (pinstverts[i].s); - stverts.a[i].t = LittleLong (pinstverts[i].t); + for (i = 0; i < header->mdl.numverts; i++) { + alias_ctx.stverts.a[i].onseam = LittleLong (pinstverts[i].onseam); + alias_ctx.stverts.a[i].s = LittleLong (pinstverts[i].s); + alias_ctx.stverts.a[i].t = LittleLong (pinstverts[i].t); } // load triangle lists - pintriangles = (dtriangle_t *) &pinstverts[pheader->mdl.numverts]; + pintriangles = (dtriangle_t *) &pinstverts[header->mdl.numverts]; - for (i = 0; i < pheader->mdl.numtris; i++) { - triangles.a[i].facesfront = LittleLong (pintriangles[i].facesfront); + for (i = 0; i < header->mdl.numtris; i++) { + alias_ctx.triangles.a[i].facesfront = + LittleLong (pintriangles[i].facesfront); for (j = 0; j < 3; j++) { - triangles.a[i].vertindex[j] = + alias_ctx.triangles.a[i].vertindex[j] = LittleLong (pintriangles[i].vertindex[j]); } } // load the frames - posenum = 0; - pframetype = (daliasframetype_t *) &pintriangles[pheader->mdl.numtris]; - aliasbboxmins[0] = aliasbboxmins[1] = aliasbboxmins[2] = 99999; - aliasbboxmaxs[0] = aliasbboxmaxs[1] = aliasbboxmaxs[2] = -99999; + int posenum = 0; + pframetype = (daliasframetype_t *) &pintriangles[header->mdl.numtris]; + VectorSet (99999, 99999, 99999, alias_ctx.aliasbboxmins); + VectorSet (-99999, -99999, -99999, alias_ctx.aliasbboxmaxs); for (i = 0; i < numframes; i++) { aliasframetype_t frametype; frametype = LittleLong (pframetype->type); - pheader->frames[i].type = frametype; + header->frames[i].type = frametype; if (frametype == ALIAS_SINGLE) { pframetype = (daliasframetype_t *) - Mod_LoadAliasFrame (mod, pframetype + 1, &posenum, - &pheader->frames[i], extra); + Mod_LoadAliasFrame (&alias_ctx, pframetype + 1, &posenum, + &header->frames[i], extra); } else { pframetype = (daliasframetype_t *) - Mod_LoadAliasGroup (mod, pframetype + 1, &posenum, - &pheader->frames[i], extra); + Mod_LoadAliasGroup (&alias_ctx, pframetype + 1, &posenum, + &header->frames[i], extra); } } - pheader->numposes = posenum; + header->numposes = posenum; mod->type = mod_alias; - for (i = 0; i < 3; i++) { - mod->mins[i] = aliasbboxmins[i] * pheader->mdl.scale[i] + - pheader->mdl.scale_origin[i]; - mod->maxs[i] = aliasbboxmaxs[i] * pheader->mdl.scale[i] + - pheader->mdl.scale_origin[i]; - } + VectorCompMultAdd (header->mdl.scale_origin, header->mdl.scale, + alias_ctx.aliasbboxmins, mod->mins); + VectorCompMultAdd (header->mdl.scale_origin, header->mdl.scale, + alias_ctx.aliasbboxmaxs, mod->maxs); mod->radius = RadiusFromBounds (mod->mins, mod->maxs); // build the draw lists - m_funcs->Mod_MakeAliasModelDisplayLists (mod, pheader, buffer, + m_funcs->Mod_MakeAliasModelDisplayLists (&alias_ctx, buffer, qfs_filesize, extra); - m_funcs->Mod_FinalizeAliasModel (mod, pheader); + if (m_funcs->Mod_FinalizeAliasModel) { + m_funcs->Mod_FinalizeAliasModel (&alias_ctx); + } - m_funcs->Mod_LoadExternalSkins (mod); + if (m_funcs->Mod_LoadExternalSkins) { + m_funcs->Mod_LoadExternalSkins (&alias_ctx); + } // move the complete, relocatable alias model to the cache if (m_funcs->alias_cache) { @@ -371,11 +380,11 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) mem = allocator (&mod->cache, total, mod->name); if (mem) - memcpy (mem, pheader, total); + memcpy (mem, header, total); Hunk_FreeToLowMark (start); mod->aliashdr = 0; } else { - mod->aliashdr = pheader; + mod->aliashdr = header; } } diff --git a/libs/models/alias/sw_model_alias.c b/libs/models/alias/sw_model_alias.c index 61122298b..0bd57d5ce 100644 --- a/libs/models/alias/sw_model_alias.c +++ b/libs/models/alias/sw_model_alias.c @@ -50,13 +50,14 @@ void * -sw_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, int gnum, +sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, + int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) { byte *pskin; - pskin = Hunk_AllocName (skinsize, mod->name); - skindesc->skin = (byte *) pskin - (byte *) pheader; + pskin = Hunk_AllocName (skinsize, alias_ctx->mod->name); + skindesc->skin = (byte *) pskin - (byte *) alias_ctx->header; memcpy (pskin, skin, skinsize); @@ -64,73 +65,67 @@ sw_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, int gnum, } static void -process_frame (model_t *mod, maliasframedesc_t *frame, int posenum, int extra) +process_frame (mod_alias_ctx_t *alias_ctx, maliasframedesc_t *frame, + int posenum, int extra) { - int size = pheader->mdl.numverts * sizeof (trivertx_t); + aliashdr_t *header = alias_ctx->header; + int size = header->mdl.numverts * sizeof (trivertx_t); trivertx_t *frame_verts; if (extra) size *= 2; - frame_verts = Hunk_AllocName (size, mod->name); - frame->frame = (byte *) frame_verts - (byte *) pheader; + frame_verts = Hunk_AllocName (size, alias_ctx->mod->name); + frame->frame = (byte *) frame_verts - (byte *) header; // The low-order 8 bits (actually, fractional) are completely separate // from the high-order bits (see R_AliasTransformFinalVert16 in // sw_ralias.c), but in adjacant arrays. This means we can get away with // just one memcpy as there are no endian issues. - memcpy (frame_verts, poseverts.a[posenum], size); + memcpy (frame_verts, alias_ctx->poseverts.a[posenum], size); } void -sw_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, +sw_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra) { + aliashdr_t *header = alias_ctx->header; int i, j; int posenum = 0; - int numv = hdr->mdl.numverts, numt = hdr->mdl.numtris; - stvert_t *pstverts; - mtriangle_t *ptri; + int numv = header->mdl.numverts, numt = header->mdl.numtris; + stvert_t *stverts; + mtriangle_t *tris; - pstverts = (stvert_t *) Hunk_AllocName (numv * sizeof (stvert_t), - mod->name); - ptri = (mtriangle_t *) Hunk_AllocName (numt * sizeof (mtriangle_t), - mod->name); + stverts = (stvert_t *) Hunk_AllocName (numv * sizeof (stvert_t), + alias_ctx->mod->name); + tris = (mtriangle_t *) Hunk_AllocName (numt * sizeof (mtriangle_t), + alias_ctx->mod->name); - hdr->stverts = (byte *) pstverts - (byte *) hdr; - hdr->triangles = (byte *) ptri - (byte *) hdr; + header->stverts = (byte *) stverts - (byte *) header; + header->triangles = (byte *) tris - (byte *) header; for (i = 0; i < numv; i++) { - pstverts[i].onseam = stverts.a[i].onseam; - pstverts[i].s = stverts.a[i].s << 16; - pstverts[i].t = stverts.a[i].t << 16; + stverts[i].onseam = alias_ctx->stverts.a[i].onseam; + stverts[i].s = alias_ctx->stverts.a[i].s << 16; + stverts[i].t = alias_ctx->stverts.a[i].t << 16; } for (i = 0; i < numt; i++) { - ptri[i].facesfront = triangles.a[i].facesfront; - VectorCopy (triangles.a[i].vertindex, ptri[i].vertindex); + tris[i].facesfront = alias_ctx->triangles.a[i].facesfront; + VectorCopy (alias_ctx->triangles.a[i].vertindex, tris[i].vertindex); } - for (i = 0; i < pheader->mdl.numframes; i++) { - maliasframedesc_t *frame = pheader->frames + i; + for (i = 0; i < header->mdl.numframes; i++) { + maliasframedesc_t *frame = header->frames + i; if (frame->type) { maliasgroup_t *group; - group = (maliasgroup_t *) ((byte *) pheader + frame->frame); - for (j = 0; j < group->numframes; j++) - process_frame (mod, (maliasframedesc_t *) &group->frames[j], - posenum++, extra); + group = (maliasgroup_t *) ((byte *) header + frame->frame); + for (j = 0; j < group->numframes; j++) { + __auto_type frame = (maliasframedesc_t *) &group->frames[j]; + process_frame (alias_ctx, frame, posenum++, extra); + } } else { - process_frame (mod, frame, posenum++, extra); + process_frame (alias_ctx, frame, posenum++, extra); } } } - -void -sw_Mod_FinalizeAliasModel (model_t *mod, aliashdr_t *hdr) -{ -} - -void -sw_Mod_LoadExternalSkins (model_t *mod) -{ -} diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 97e8a63d0..c6493c750 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -110,19 +110,20 @@ vulkan_alias_clear (model_t *m, void *data) } void * -Vulkan_Mod_LoadSkin (model_t *mod, byte *skinpix, int skinsize, int snum, - int gnum, qboolean group, maliasskindesc_t *skindesc, - vulkan_ctx_t *ctx) +Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, + int snum, int gnum, qboolean group, + maliasskindesc_t *skindesc, vulkan_ctx_t *ctx) { + aliashdr_t *header = alias_ctx->header; aliasskin_t *skin; byte *tskin; int w, h; skin = Hunk_Alloc (sizeof (aliasskin_t)); - skindesc->skin = (byte *) skin - (byte *) pheader;//FIXME pheader global + skindesc->skin = (byte *) skin - (byte *) header; //FIXME move all skins into arrays(?) - w = pheader->mdl.skinwidth; - h = pheader->mdl.skinheight; + w = header->mdl.skinwidth; + h = header->mdl.skinheight; tskin = malloc (2 * skinsize); memcpy (tskin, skinpix, skinsize); Mod_FloodFillSkin (tskin, w, h); @@ -131,25 +132,25 @@ Vulkan_Mod_LoadSkin (model_t *mod, byte *skinpix, int skinsize, int snum, if (Mod_CalcFullbright (tskin, tskin + skinsize, skinsize)) { skin->glow = Vulkan_LoadTex (ctx, &skin_tex, 1, va (ctx->va_ctx, "%s:%d:%d:glow", - mod->name, snum, gnum)); + alias_ctx->mod->name, snum, gnum)); Mod_ClearFullbright (tskin, tskin, skinsize); } if (Skin_CalcTopColors (tskin, tskin + skinsize, skinsize)) { skin->colora = Vulkan_LoadTex (ctx, &skin_tex, 1, va (ctx->va_ctx, "%s:%d:%d:colora", - mod->name, snum, gnum)); + alias_ctx->mod->name, snum, gnum)); Skin_ClearTopColors (tskin, tskin, skinsize); } if (Skin_CalcBottomColors (tskin, tskin + skinsize, skinsize)) { skin->colorb = Vulkan_LoadTex (ctx, &skin_tex, 1, va (ctx->va_ctx, "%s:%d:%d:colorb", - mod->name, snum, gnum)); + alias_ctx->mod->name, snum, gnum)); Skin_ClearBottomColors (tskin, tskin, skinsize); } skin_tex.data = tskin; skin->tex = Vulkan_LoadTex (ctx, &skin_tex, 1, va (ctx->va_ctx, "%s:%d:%d:tex", - mod->name, + alias_ctx->mod->name, snum, gnum)); free (tskin); @@ -158,14 +159,14 @@ Vulkan_Mod_LoadSkin (model_t *mod, byte *skinpix, int skinsize, int snum, } void -Vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr, vulkan_ctx_t *ctx) +Vulkan_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx) { - m->clear = vulkan_alias_clear; - m->data = ctx; + alias_ctx->mod->clear = vulkan_alias_clear; + alias_ctx->mod->data = ctx; } void -Vulkan_Mod_LoadExternalSkins (model_t *mod, vulkan_ctx_t *ctx) +Vulkan_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx) { } @@ -185,9 +186,10 @@ get_buffer_size (qfv_device_t *device, VkBuffer buffer) } void -Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, +Vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra, vulkan_ctx_t *ctx) { + aliashdr_t *header = alias_ctx->header; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasvrt_t *verts; @@ -201,11 +203,11 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, int pose; vec3_t pos; - if (hdr->mdl.ident == HEADER_MDL16) - VectorScale (hdr->mdl.scale, 1/256.0, hdr->mdl.scale); + if (header->mdl.ident == HEADER_MDL16) + VectorScale (header->mdl.scale, 1/256.0, header->mdl.scale); - numverts = hdr->mdl.numverts; - numtris = hdr->mdl.numtris; + numverts = header->mdl.numverts; + numtris = header->mdl.numtris; // initialize indexmap to -1 (unduplicated). any other value indicates // both that the vertex has been duplicated and the index of the @@ -217,8 +219,9 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, // back-facing triangles for (i = 0; i < numtris; i++) { for (j = 0; j < 3; j++) { - int vind = triangles.a[i].vertindex[j]; - if (stverts.a[vind].onseam && !triangles.a[i].facesfront) { + int vind = alias_ctx->triangles.a[i].vertindex[j]; + if (alias_ctx->stverts.a[vind].onseam + && !alias_ctx->triangles.a[i].facesfront) { // duplicate the vertex if it has not alreaddy been // duplicated if (indexmap[vind] == -1) { @@ -239,7 +242,7 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, // current and previous pose, uvbuff "statically" bound as uvs are not // animated by pose, and the same for ibuf: indices will never change for // the mesh - size_t vert_count = numverts * hdr->numposes; + size_t vert_count = numverts * header->numposes; size_t vert_size = vert_count * sizeof (aliasvrt_t); size_t uv_size = numverts * sizeof (aliasuv_t); size_t ind_size = 3 * numtris * sizeof (uint32_t); @@ -255,13 +258,13 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, | VK_BUFFER_USAGE_INDEX_BUFFER_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, vbuff, va (ctx->va_ctx, "buffer:alias:vertex:%s", - mod->name)); + alias_ctx->mod->name)); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, uvbuff, va (ctx->va_ctx, "buffer:alias:uv:%s", - mod->name)); + alias_ctx->mod->name)); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, ibuff, va (ctx->va_ctx, "buffer:alias:index:%s", - mod->name)); + alias_ctx->mod->name)); size_t voffs = 0; size_t uvoffs = voffs + get_buffer_size (device, vbuff); size_t ioffs = uvoffs + get_buffer_size (device, uvbuff); @@ -272,7 +275,7 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, buff_size, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, mem, va (ctx->va_ctx, "memory:alias:vuvi:%s", - mod->name)); + alias_ctx->mod->name)); QFV_BindBufferMemory (device, vbuff, mem, voffs); QFV_BindBufferMemory (device, uvbuff, mem, uvoffs); QFV_BindBufferMemory (device, ibuff, mem, ioffs); @@ -280,7 +283,7 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, va (ctx->va_ctx, "alias:%s", - mod->name), + alias_ctx->mod->name), buff_size, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); verts = QFV_PacketExtend (packet, vert_size); @@ -291,10 +294,10 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, // and associated with back-facing triangles (marked by non-negative // indexmap entry). // the s coordinate is shifted right by half the skin width. - for (i = 0; i < hdr->mdl.numverts; i++) { + for (i = 0; i < header->mdl.numverts; i++) { int vind = indexmap[i]; - uv[i].u = (float) stverts.a[i].s / hdr->mdl.skinwidth; - uv[i].v = (float) stverts.a[i].t / hdr->mdl.skinheight; + uv[i].u = (float) alias_ctx->stverts.a[i].s / header->mdl.skinwidth; + uv[i].v = (float) alias_ctx->stverts.a[i].t / header->mdl.skinheight; if (vind != -1) { uv[vind] = uv[i]; uv[vind].u += 0.5; @@ -303,15 +306,15 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, // poputlate the vertex position and normal data, duplicating for // back-facing on-seam verts (indicated by non-negative indexmap entry) - for (i = 0, pose = 0; i < hdr->numposes; i++, pose += numverts) { - for (j = 0; j < hdr->mdl.numverts; j++) { - pv = &poseverts.a[i][j]; + for (i = 0, pose = 0; i < header->numposes; i++, pose += numverts) { + for (j = 0; j < header->mdl.numverts; j++) { + pv = &alias_ctx->poseverts.a[i][j]; if (extra) { - VectorMultAdd (pv[hdr->mdl.numverts].v, 256, pv->v, pos); + VectorMultAdd (pv[header->mdl.numverts].v, 256, pv->v, pos); } else { VectorCopy (pv->v, pos); } - VectorCompMultAdd (hdr->mdl.scale_origin, hdr->mdl.scale, + VectorCompMultAdd (header->mdl.scale_origin, header->mdl.scale, pos, verts[pose + j].vertex); verts[pose + j].vertex[3] = 1; VectorCopy (vertex_normals[pv->lightnormalindex], @@ -327,8 +330,9 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, // now build the indices for DrawElements for (i = 0; i < numtris; i++) { for (j = 0; j < 3; j++) { - int vind = triangles.a[i].vertindex[j]; - if (stverts.a[vind].onseam && !triangles.a[i].facesfront) { + int vind = alias_ctx->triangles.a[i].vertindex[j]; + if (alias_ctx->stverts.a[vind].onseam + && !alias_ctx->triangles.a[i].facesfront) { vind = indexmap[vind]; } indices[3 * i + j] = vind; @@ -337,7 +341,7 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, // finished with indexmap free (indexmap); - hdr->poseverts = numverts; + header->poseverts = numverts; VkBufferMemoryBarrier wr_barriers[] = { { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, @@ -394,5 +398,5 @@ Vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, void *_m, mesh->uv_buffer = uvbuff; mesh->index_buffer = ibuff; mesh->memory = mem; - hdr->commands = (byte *) mesh - (byte *) hdr; + header->commands = (byte *) mesh - (byte *) header; } diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 0ef7a0108..2f790d847 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -50,8 +50,8 @@ static vid_model_funcs_t model_funcs = { sw_Mod_MakeAliasModelDisplayLists, sw_Mod_LoadSkin, - sw_Mod_FinalizeAliasModel, - sw_Mod_LoadExternalSkins, + 0, + 0, sw_Mod_IQMFinish, 1, sw_Mod_SpriteLoadTexture, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index a3fe10d97..db94b291d 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -55,8 +55,8 @@ static vid_model_funcs_t model_funcs = { sw_Mod_MakeAliasModelDisplayLists, sw_Mod_LoadSkin, - sw_Mod_FinalizeAliasModel, - sw_Mod_LoadExternalSkins, + 0, + 0, sw_Mod_IQMFinish, 1, sw_Mod_SpriteLoadTexture, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 3473a92cf..8441795c1 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -418,28 +418,30 @@ vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx) } static void -vulkan_Mod_MakeAliasModelDisplayLists (model_t *mod, aliashdr_t *hdr, +vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra) { - Vulkan_Mod_MakeAliasModelDisplayLists (mod, hdr, _m, _s, extra, vulkan_ctx); + Vulkan_Mod_MakeAliasModelDisplayLists (alias_ctx, _m, _s, extra, + vulkan_ctx); } static void * -vulkan_Mod_LoadSkin (model_t *mod, byte *skin, int skinsize, int snum, - int gnum, qboolean group, maliasskindesc_t *skindesc) +vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, + int snum, int gnum, qboolean group, + maliasskindesc_t *skindesc) { - return Vulkan_Mod_LoadSkin (mod, skin, skinsize, snum, gnum, group, + return Vulkan_Mod_LoadSkin (alias_ctx, skin, skinsize, snum, gnum, group, skindesc, vulkan_ctx); } static void -vulkan_Mod_FinalizeAliasModel (model_t *m, aliashdr_t *hdr) +vulkan_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx) { - Vulkan_Mod_FinalizeAliasModel (m, hdr, vulkan_ctx); + Vulkan_Mod_FinalizeAliasModel (alias_ctx, vulkan_ctx); } static void -vulkan_Mod_LoadExternalSkins (model_t *mod) +vulkan_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx) { } From 0d4ca46923d77c88a74f0fe8e8b95cbc06671652 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 2 Feb 2021 00:04:45 +0900 Subject: [PATCH 1298/3664] [vulkan] Move mip map generation commands to image --- include/QF/Vulkan/image.h | 1 + libs/video/renderer/vulkan/image.c | 30 +++++++++++++++++++++ libs/video/renderer/vulkan/vulkan_texture.c | 26 +----------------- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 71ca57389..9942562b2 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -82,5 +82,6 @@ VkImageView QFV_CreateImageView (struct qfv_device_s *device, void QFV_GenerateMipMaps (struct qfv_device_s *device, VkCommandBuffer cmd, VkImage image, unsigned mips, unsigned width, unsigned height, unsigned layers); +int QFV_MipLevels (int width, int height) __attribute__((const)); #endif//__QF_Vulkan_image_h diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 92d584f80..41b4586f0 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -275,3 +275,33 @@ QFV_GenerateMipMaps (qfv_device_t *device, VkCommandBuffer cmd, 0, 0, 0, 0, 1, &final_barrier); } + +static int +ilog2 (unsigned x) +{ + unsigned o = x; + if (x > 0x7fffffff) { + // avoid overflow + return 31; + } + x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + int y = 0; + y |= ((x & 0xffff0000) != 0) << 4; + y |= ((x & 0xff00ff00) != 0) << 3; + y |= ((x & 0xf0f0f0f0) != 0) << 2; + y |= ((x & 0xcccccccc) != 0) << 1; + y |= ((x & 0xaaaaaaaa) != 0) << 0; + return y - ((o & (x - 1)) != 0); +} + +int +QFV_MipLevels (int width, int height) +{ + return ilog2 (max (width, height)) + 1; +} diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 4a1e2d2ab..7d8b13155 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -64,30 +64,6 @@ #include "r_scrap.h" #include "vid_vulkan.h" -static int -ilog2 (unsigned x) -{ - unsigned o = x; - if (x > 0x7fffffff) { - // avoid overflow - return 31; - } - x--; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - x++; - int y = 0; - y |= ((x & 0xffff0000) != 0) << 4; - y |= ((x & 0xff00ff00) != 0) << 3; - y |= ((x & 0xf0f0f0f0) != 0) << 2; - y |= ((x & 0xcccccccc) != 0) << 1; - y |= ((x & 0xaaaaaaaa) != 0) << 0; - return y - ((o & (x - 1)) != 0); -} - void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, int alpha, int count) @@ -164,7 +140,7 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) } if (mip) { - mip = ilog2 (max (tex->width, tex->height)) + 1; + mip = QFV_MipLevels (tex->width, tex->height); } else { mip = 1; } From 8e63ab9f94b8d028cb38b2c1918abde127d39e3c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 2 Feb 2021 00:11:47 +0900 Subject: [PATCH 1299/3664] [vulkan] Use 4 layer arrays for alias skins Doesn't seem to make much difference performance-wise, but speed does seem to be fill-rate limited due to the 8x msaa. Still, it does mean fewer bindings to worry about. --- include/QF/Vulkan/qf_alias.h | 9 +- libs/models/alias/vulkan_model_alias.c | 139 +++++++++++++++----- libs/video/renderer/vulkan/alias.frag | 13 +- libs/video/renderer/vulkan/qfpipeline.plist | 18 --- libs/video/renderer/vulkan/vulkan_alias.c | 11 +- 5 files changed, 112 insertions(+), 78 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index ebf4f6996..6f96e0fa0 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -37,13 +37,6 @@ #include "QF/modelgen.h" #include "QF/Vulkan/qf_vid.h" -typedef struct aliasskin_s { - struct qfv_tex_s *tex; - struct qfv_tex_s *glow; - struct qfv_tex_s *colora; - struct qfv_tex_s *colorb; -} aliasskin_t; - typedef struct aliasvrt_s { float vertex[4]; float normal[4]; @@ -77,7 +70,7 @@ typedef struct qfv_light_buffer_s { } qfv_light_buffer_t; #define ALIAS_BUFFER_INFOS 2 -#define ALIAS_IMAGE_INFOS 4 +#define ALIAS_IMAGE_INFOS 1 typedef struct aliasframe_s { VkCommandBuffer cmd; diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index c6493c750..5b3ce995c 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -46,9 +46,11 @@ #include "QF/vid.h" #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/debug.h" +#include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/staging.h" @@ -63,17 +65,13 @@ static vec3_t vertex_normals[NUMVERTEXNORMALS] = { static void skin_clear (int skin_offset, aliashdr_t *hdr, vulkan_ctx_t *ctx) { - aliasskin_t *skin = (aliasskin_t *) ((byte *) hdr + skin_offset); - Vulkan_UnloadTex (ctx, skin->tex); - if (skin->glow) { - Vulkan_UnloadTex (ctx, skin->glow); - } - if (skin->colora) { - Vulkan_UnloadTex (ctx, skin->colora); - } - if (skin->colorb) { - Vulkan_UnloadTex (ctx, skin->colorb); - } + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + qfv_tex_t *skin = (qfv_tex_t *) ((byte *) hdr + skin_offset); + + dfunc->vkDestroyImageView (device->dev, skin->view, 0); + dfunc->vkDestroyImage (device->dev, skin->image, 0); + dfunc->vkFreeMemory (device->dev, skin->memory, 0); } static void @@ -114,12 +112,14 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc, vulkan_ctx_t *ctx) { + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; aliashdr_t *header = alias_ctx->header; - aliasskin_t *skin; + qfv_tex_t *skin; byte *tskin; int w, h; - skin = Hunk_Alloc (sizeof (aliasskin_t)); + skin = Hunk_Alloc (sizeof (qfv_tex_t)); skindesc->skin = (byte *) skin - (byte *) header; //FIXME move all skins into arrays(?) w = header->mdl.skinwidth; @@ -128,30 +128,97 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, memcpy (tskin, skinpix, skinsize); Mod_FloodFillSkin (tskin, w, h); - tex_t skin_tex = {w, h, tex_palette, 1, vid.palette, tskin + skinsize}; - if (Mod_CalcFullbright (tskin, tskin + skinsize, skinsize)) { - skin->glow = Vulkan_LoadTex (ctx, &skin_tex, 1, - va (ctx->va_ctx, "%s:%d:%d:glow", - alias_ctx->mod->name, snum, gnum)); - Mod_ClearFullbright (tskin, tskin, skinsize); + int mipLevels = QFV_MipLevels (w, h); + VkExtent3D extent = { w, h, 1 }; + skin->offset = 0; + skin->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, + VK_FORMAT_R8G8B8A8_UNORM, extent, + mipLevels, 4, VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, skin->image, + va (ctx->va_ctx, "image:%s:%d:%d", + alias_ctx->mod->name, snum, gnum)); + skin->memory = QFV_AllocImageMemory (device, skin->image, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + 0, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, skin->memory, + va (ctx->va_ctx, "memory:%s:%d:%d", + alias_ctx->mod->name, snum, gnum)); + QFV_BindImageMemory (device, skin->image, skin->memory, 0); + skin->view = QFV_CreateImageView (device, skin->image, + VK_IMAGE_VIEW_TYPE_2D_ARRAY, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, skin->view, + va (ctx->va_ctx, "iview:%s:%d:%d", + alias_ctx->mod->name, snum, gnum)); + + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, "alias stage", + 4 * skinsize * 4, + ctx->cmdpool); + qfv_packet_t *packet = QFV_PacketAcquire (stage); + byte *base_data = QFV_PacketExtend (packet, skinsize * 4); + byte *cola_data = QFV_PacketExtend (packet, skinsize * 4); + byte *colb_data = QFV_PacketExtend (packet, skinsize * 4); + byte *glow_data = QFV_PacketExtend (packet, skinsize * 4); + + Mod_CalcFullbright (tskin, tskin + skinsize, skinsize); + Vulkan_ExpandPalette (glow_data, tskin + skinsize, vid.palette, 1, + skinsize); + Mod_ClearFullbright (tskin, tskin, skinsize); + + Skin_CalcTopColors (tskin, tskin + skinsize, skinsize); + Vulkan_ExpandPalette (cola_data, tskin + skinsize, vid.palette, 1, + skinsize); + Skin_ClearTopColors (tskin, tskin, skinsize); + + Skin_CalcBottomColors (tskin, tskin + skinsize, skinsize); + Vulkan_ExpandPalette (colb_data, tskin + skinsize, vid.palette, 1, + skinsize); + Skin_ClearBottomColors (tskin, tskin, skinsize); + + Vulkan_ExpandPalette (base_data, tskin, vid.palette, 1, skinsize); + + VkImageMemoryBarrier barrier; + qfv_pipelinestagepair_t stages; + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + barrier.image = skin->image; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + + VkBufferImageCopy copy = { + packet->offset, 0, 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 4}, + {0, 0, 0}, {w, h, 1}, + }; + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + skin->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©); + + if (mipLevels == 1) { + stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier.image = skin->image; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + + } else { + QFV_GenerateMipMaps (device, packet->cmd, skin->image, + mipLevels, w, h, 4); } - if (Skin_CalcTopColors (tskin, tskin + skinsize, skinsize)) { - skin->colora = Vulkan_LoadTex (ctx, &skin_tex, 1, - va (ctx->va_ctx, "%s:%d:%d:colora", - alias_ctx->mod->name, snum, gnum)); - Skin_ClearTopColors (tskin, tskin, skinsize); - } - if (Skin_CalcBottomColors (tskin, tskin + skinsize, skinsize)) { - skin->colorb = Vulkan_LoadTex (ctx, &skin_tex, 1, - va (ctx->va_ctx, "%s:%d:%d:colorb", - alias_ctx->mod->name, snum, gnum)); - Skin_ClearBottomColors (tskin, tskin, skinsize); - } - skin_tex.data = tskin; - skin->tex = Vulkan_LoadTex (ctx, &skin_tex, 1, - va (ctx->va_ctx, "%s:%d:%d:tex", - alias_ctx->mod->name, - snum, gnum)); + QFV_PacketSubmit (packet); + QFV_DestroyStagingBuffer (stage); free (tskin); diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/alias.frag index eff6ff10a..bff1b87dd 100644 --- a/libs/video/renderer/vulkan/alias.frag +++ b/libs/video/renderer/vulkan/alias.frag @@ -1,8 +1,5 @@ #version 450 -layout (set = 0, binding = 2) uniform sampler2D Texture; -layout (set = 0, binding = 3) uniform sampler2D GlowMap; -layout (set = 0, binding = 4) uniform sampler2D ColorA; -layout (set = 0, binding = 5) uniform sampler2D ColorB; +layout (set = 0, binding = 2) uniform sampler2DArray Skin; /* layout (set = 2, binding = 0) uniform sampler2D Texture; layout (set = 2, binding = 1) uniform sampler2D GlowMap; @@ -59,9 +56,9 @@ main (void) vec4 c; int i; vec3 light = vec3 (0); - c = texture (Texture, st); - c += texture (ColorA, st); - c += texture (ColorB, st); + c = texture (Skin, vec3 (st, 0)); + c += texture (Skin, vec3 (st, 1)); + c += texture (Skin, vec3 (st, 2)); if (MaxLights > 0) { for (i = 0; i < light_count; i++) { @@ -70,7 +67,7 @@ main (void) } c *= vec4 (light, 1); - c += texture (GlowMap, st); + c += texture (Skin, vec3 (st, 3)); //frag_color = vec4((normal + 1)/2, 1); frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 3cbf8db5e..5d44ec6ff 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -172,24 +172,6 @@ descriptorCount = 1; stageFlags = fragment; }, - { - binding = 3; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 4; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 5; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, ); }; alias.matrices = { diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index fec2d2cd6..d7f933cb9 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -88,7 +88,7 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) aliashdr_t *hdr; qfv_alias_mesh_t *mesh; float blend; - aliasskin_t *skin; + qfv_tex_t *skin; if (!(hdr = model->aliashdr)) { hdr = Cache_Get (&model->cache); @@ -102,7 +102,7 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) } else { maliasskindesc_t *skindesc; skindesc = R_AliasGetSkindesc (ent->skinnum, hdr); - skin = (aliasskin_t *) ((byte *) hdr + skindesc->skin); + skin = (qfv_tex_t *) ((byte *) hdr + skindesc->skin); } VkDeviceSize offsets[] = { @@ -124,12 +124,7 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, VK_SHADER_STAGE_VERTEX_BIT, 64, sizeof (float), &blend); - aframe->imageInfo[0].imageView = get_view (skin->tex, ctx->default_white); - aframe->imageInfo[1].imageView = get_view (skin->glow, ctx->default_black); - aframe->imageInfo[2].imageView = get_view (skin->colora, - ctx->default_black); - aframe->imageInfo[3].imageView = get_view (skin->colorb, - ctx->default_black); + aframe->imageInfo[0].imageView = get_view (skin, 0); dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->layout, From d6b678ac78785f8df92fabee0dbf3993e5c77769 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 2 Feb 2021 19:53:36 +0900 Subject: [PATCH 1300/3664] [vulkan] Implement team colors It's not quite as expected, but that may be due to one of msaa, the 0-15 range in the palette not being all the way to white, the color gradients being not quite linear (haven't checked yet) or some combination of the above. However, it's that what should be yellow is more green. At least the zombies are no longer white and the ogres don't look like they're wearing skeleton suits. --- include/QF/Vulkan/qf_alias.h | 8 +++++ libs/models/alias/vulkan_model_alias.c | 10 +++--- libs/video/renderer/vulkan/alias.frag | 11 ++++--- libs/video/renderer/vulkan/qfpipeline.plist | 4 +-- libs/video/renderer/vulkan/vulkan_alias.c | 34 +++++++++------------ 5 files changed, 36 insertions(+), 31 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 6f96e0fa0..714cb06b3 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -53,6 +53,14 @@ typedef struct qfv_alias_mesh_s { VkDeviceMemory memory; } qfv_alias_mesh_t; +typedef struct qfv_alias_skin_s { + VkDeviceMemory memory; + VkImage image; + VkImageView view; + byte colora[4]; + byte colorb[4]; +} qfv_alias_skin_t; + typedef struct qfv_light_s { vec3_t color; float dist; diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 5b3ce995c..fd1f8c731 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -67,7 +67,7 @@ skin_clear (int skin_offset, aliashdr_t *hdr, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - qfv_tex_t *skin = (qfv_tex_t *) ((byte *) hdr + skin_offset); + qfv_alias_skin_t *skin = (qfv_alias_skin_t *) ((byte *) hdr + skin_offset); dfunc->vkDestroyImageView (device->dev, skin->view, 0); dfunc->vkDestroyImage (device->dev, skin->image, 0); @@ -115,11 +115,13 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliashdr_t *header = alias_ctx->header; - qfv_tex_t *skin; + qfv_alias_skin_t *skin; byte *tskin; int w, h; - skin = Hunk_Alloc (sizeof (qfv_tex_t)); + skin = Hunk_Alloc (sizeof (qfv_alias_skin_t)); + QuatCopy (vid.palette32 + (TOP_RANGE + 15) * 4, skin->colora); + QuatCopy (vid.palette32 + (BOTTOM_RANGE + 15) * 4, skin->colorb); skindesc->skin = (byte *) skin - (byte *) header; //FIXME move all skins into arrays(?) w = header->mdl.skinwidth; @@ -130,7 +132,6 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, int mipLevels = QFV_MipLevels (w, h); VkExtent3D extent = { w, h, 1 }; - skin->offset = 0; skin->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, extent, mipLevels, 4, VK_SAMPLE_COUNT_1_BIT, @@ -212,7 +213,6 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, 0, 0, 0, 0, 0, 1, &barrier); - } else { QFV_GenerateMipMaps (device, packet->cmd, skin->image, mipLevels, w, h, 4); diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/alias.frag index bff1b87dd..3b5c9fddd 100644 --- a/libs/video/renderer/vulkan/alias.frag +++ b/libs/video/renderer/vulkan/alias.frag @@ -23,7 +23,10 @@ layout (set = 0, binding = 1) uniform Lights { }; layout (push_constant) uniform PushConstants { - layout (offset = 80) + layout (offset = 68) + uint base_color; + uint colorA; + uint colorB; vec4 fog; vec4 color; }; @@ -56,9 +59,9 @@ main (void) vec4 c; int i; vec3 light = vec3 (0); - c = texture (Skin, vec3 (st, 0)); - c += texture (Skin, vec3 (st, 1)); - c += texture (Skin, vec3 (st, 2)); + c = texture (Skin, vec3 (st, 0)) * unpackUnorm4x8(base_color); + c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA); + c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB); if (MaxLights > 0) { for (i = 0; i < light_count; i++) { diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 5d44ec6ff..33bc11b27 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -271,8 +271,8 @@ }, { stageFlags = fragment; - offset = 80; - size = "2 * 4 * 4"; + offset = 68; + size = "3 * 4 + 2 * 4 * 4"; }, ); }; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index d7f933cb9..76f4ac7b5 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -65,18 +65,6 @@ #include "vid_vulkan.h" #include "vkparse.h" -static VkImageView -get_view (qfv_tex_t *tex, qfv_tex_t *default_tex) -{ - if (tex) { - return tex->view; - } - if (default_tex) { - return default_tex->view; - } - return 0; -} - void Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) { @@ -87,23 +75,28 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) model_t *model = ent->model; aliashdr_t *hdr; qfv_alias_mesh_t *mesh; - float blend; - qfv_tex_t *skin; + qfv_alias_skin_t *skin; + float vertex_constants[17]; + byte fragment_constants[3][4]; if (!(hdr = model->aliashdr)) { hdr = Cache_Get (&model->cache); } mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); - blend = R_AliasGetLerpedFrames (ent, hdr); + memcpy (vertex_constants, ent->transform, sizeof (ent->transform)); + vertex_constants[16] = R_AliasGetLerpedFrames (ent, hdr); if (0/*XXX ent->skin && ent->skin->tex*/) { //skin = ent->skin->tex; } else { maliasskindesc_t *skindesc; skindesc = R_AliasGetSkindesc (ent->skinnum, hdr); - skin = (qfv_tex_t *) ((byte *) hdr + skindesc->skin); + skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } + QuatScale (ent->colormod, 255, fragment_constants[0]); + QuatCopy (skin->colora, fragment_constants[1]); + QuatCopy (skin->colorb, fragment_constants[2]); VkDeviceSize offsets[] = { ent->pose1 * hdr->poseverts * sizeof (aliasvrt_t), @@ -120,11 +113,12 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) VK_INDEX_TYPE_UINT32); dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), ent->transform); + 0, sizeof (vertex_constants), vertex_constants); dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, - VK_SHADER_STAGE_VERTEX_BIT, - 64, sizeof (float), &blend); - aframe->imageInfo[0].imageView = get_view (skin, 0); + VK_SHADER_STAGE_FRAGMENT_BIT, + 68, sizeof (fragment_constants), + fragment_constants); + aframe->imageInfo[0].imageView = skin->view; dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->layout, From 22fe49d0ef9fe3fa2f036cb795cc7322594f4dfb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 18 Feb 2013 15:26:28 +0900 Subject: [PATCH 1301/3664] Add support for loading an alternative palette. Sort of at the request of leileilol (a utility to create quakepal.py was asked for, but this seems to be better approach). However, the feature is not used yet (needs hooks in the import and export modules). --- tools/io_mesh_qfmdl/quakepal.py | 45 ++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/tools/io_mesh_qfmdl/quakepal.py b/tools/io_mesh_qfmdl/quakepal.py index da7e4adec..7c2a6678f 100644 --- a/tools/io_mesh_qfmdl/quakepal.py +++ b/tools/io_mesh_qfmdl/quakepal.py @@ -1,4 +1,27 @@ -palette = ( +# vim:ts=4:et +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# 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 2 +# 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, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# + +from struct import unpack + +default_palette = ( (0x00, 0x00, 0x00), (0x0f, 0x0f, 0x0f), (0x1f, 0x1f, 0x1f), @@ -256,3 +279,23 @@ palette = ( (0xff, 0xff, 0xff), (0x9f, 0x5b, 0x53), ) + +palette = default_palette + +def load_palette(filepath): + if not filepath: + palette = default_palette + else: + try: + f = open(filepath, "rb") + pal = f.read(768) + if len(pal) < 768: + pal = pal + b'\0' * (768 - len(pal)) + palette = [] + for i in range(256): + palette.append(unpack("<3B", pal[i * 3 : i * 3 + 3])) + palette = tuple(palette) + except IOError: + palette = default_palette + return None + return palette From ebb73e19b2309e0e5025215d99a7a267d4880c16 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Feb 2021 00:08:33 +0900 Subject: [PATCH 1302/3664] [vulkan] Use the msaaSamples cvar That took a bit of fiddling with the render pass to get things working for both sampling and no sampling (ie, msaaSamples = 1). --- libs/video/renderer/vid_render_vulkan.c | 16 ++-- libs/video/renderer/vulkan/qfpipeline.plist | 76 +++++++++++++++++-- libs/video/renderer/vulkan/renderpass.c | 10 ++- .../video/renderer/vulkan/vulkan_vid_common.c | 25 +++--- 4 files changed, 100 insertions(+), 27 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 8441795c1..ebca7b9b0 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -135,12 +135,15 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) framebuffer->imageAvailableSemaphore, 0, &imageIndex); - __auto_type attachments = DARRAY_ALLOCFIXED (qfv_imageviewset_t, 3, - alloca); + int attachCount = vulkan_ctx->msaaSamples > 1 ? 3 : 2; + __auto_type attachments = DARRAY_ALLOCFIXED (qfv_imageviewset_t, + attachCount, alloca); qfv_swapchain_t *sc = vulkan_ctx->swapchain; - attachments->a[0] = vulkan_ctx->renderpass.colorImage->view; + attachments->a[0] = sc->imageViews->a[imageIndex]; attachments->a[1] = vulkan_ctx->renderpass.depthImage->view; - attachments->a[2] = sc->imageViews->a[imageIndex]; + if (attachCount > 2) { + attachments->a[2] = vulkan_ctx->renderpass.colorImage->view; + } VkRenderPass renderpass = vulkan_ctx->renderpass.renderpass; framebuffer->framebuffer = QFV_CreateFramebuffer (device, renderpass, @@ -157,15 +160,16 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - VkClearValue clearValues[2] = { + VkClearValue clearValues[3] = { { { {0.0, 0.0, 0.0, 1.0} } }, { { {1.0, 0.0} } }, + { { {0.0, 0.0, 0.0, 1.0} } }, }; VkRenderPassBeginInfo renderPassInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, vulkan_ctx->renderpass.renderpass, 0, { {0, 0}, sc->extent }, - 2, clearValues + 3, clearValues }; dfunc->vkBeginCommandBuffer (framebuffer->cmdBuffer, &beginInfo); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 33bc11b27..96de769c9 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -707,13 +707,75 @@ { flags = 0; format = $swapchain.format; - samples = $msaaSamples; + samples = 1; loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; storeOp = VK_ATTACHMENT_STORE_OP_STORE; stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + }, + { + flags = 0; + format = VK_FORMAT_D32_SFLOAT; + samples = 1; + loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + }, + ); + subpasses = ( + { + pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + colorAttachments = ( + { + attachment = 0; + layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + ); + depthStencilAttachment = { + attachment = 1; + layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + }; + preserveAttachments = (); + }, + ); + dependencies = ( + { + srcSubpass = VK_SUBPASS_EXTERNAL; + dstSubpass = 0; + srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + }, + { + srcSubpass = 0; + dstSubpass = VK_SUBPASS_EXTERNAL; + srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + }, + ); + }; + renderpass.msaa = { + attachments = ( + { + flags = 0; + format = $swapchain.format; + samples = VK_SAMPLE_COUNT_1_BIT; + loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + storeOp = VK_ATTACHMENT_STORE_OP_STORE; + stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; }, { flags = 0; @@ -729,13 +791,13 @@ { flags = 0; format = $swapchain.format; - samples = VK_SAMPLE_COUNT_1_BIT; - loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + samples = $msaaSamples; + loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; storeOp = VK_ATTACHMENT_STORE_OP_STORE; stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; }, ); subpasses = ( @@ -743,13 +805,13 @@ pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; colorAttachments = ( { - attachment = 0; + attachment = 2; layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } ); resolveAttachments = ( { - attachment = 2; + attachment = 0; layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } ); diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 65134ffd7..4970b050b 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -106,9 +106,13 @@ QFV_CreateRenderPass (qfv_device_t *device, const VkAttachmentReference *ref = &sp->pColorAttachments[j]; Sys_Printf (" c %d %d\n", ref->attachment, ref->layout); } - for (size_t j = 0; j < sp->colorAttachmentCount; j++) { - const VkAttachmentReference *ref = &sp->pResolveAttachments[j]; - Sys_Printf (" r %d %d\n", ref->attachment, ref->layout); + if (sp->pResolveAttachments) { + for (size_t j = 0; j < sp->colorAttachmentCount; j++) { + const VkAttachmentReference *ref + = &sp->pResolveAttachments[j]; + Sys_Printf (" r %d %d\n", ref->attachment, + ref->layout); + } } Sys_Printf (" pDepthStencilAttachment: %p\n", sp->pDepthStencilAttachment); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index ddd20e82c..ff026331a 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -240,28 +240,31 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) { qfv_load_pipeline (ctx); const char *name = "renderpass";//FIXME - - plitem_t *item = ctx->pipelineDef; - if (!item || !(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading renderpass\n"); - return; - } else { - Sys_Printf ("Found renderpass def\n"); - } qfv_device_t *device = ctx->device; VkDevice dev = device->dev; qfv_devfuncs_t *df = device->funcs; VkCommandBuffer cmd = ctx->cmdbuffer; qfv_swapchain_t *sc = ctx->swapchain; + ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val, + QFV_GetMaxSampleCount (device->physDev)); + if (ctx->msaaSamples > 1) { + name = "renderpass.msaa"; + } + + plitem_t *item = ctx->pipelineDef; + if (!item || !(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading renderpass: %s\n", name); + return; + } else { + Sys_Printf ("Found renderpass def: %s\n", name); + } + qfv_imageresource_t *colorImage = malloc (sizeof (*colorImage)); qfv_imageresource_t *depthImage = malloc (sizeof (*depthImage)); VkExtent3D extent = {sc->extent.width, sc->extent.height, 1}; - //FIXME incorporate cvar setting - ctx->msaaSamples = QFV_GetMaxSampleCount (device->physDev); - Sys_MaskPrintf (SYS_VULKAN, "color resource\n"); colorImage->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, From bc7858bb87b7150077a77c8da2a562bd74bbc0f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Feb 2021 11:41:38 +0900 Subject: [PATCH 1303/3664] [model] Move parent pointer out of leaf/node struct The node struct was 72 bytes thus two cache line. Moving the pointer into the brush model data block allows nodes to fit in a single cache line (not that they're aligned yet, but that's next). It doesn't seem to have made any difference to performance (at least in the vulkan renderer), but it hasn't hurt, either, as the only place that needed the parent pointer was R_MarkLeaves. --- include/QF/model.h | 7 +++---- libs/models/brush/model_brush.c | 17 +++++++++++------ libs/video/renderer/r_bsp.c | 16 +++++++++------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index a05d489a4..b65a5ad18 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -179,8 +179,6 @@ typedef struct mnode_s { float minmaxs[6]; // for bounding box culling - struct mnode_s *parent; - // node specific plane_t *plane; struct mnode_s *children[2]; @@ -198,8 +196,6 @@ typedef struct mleaf_s { float mins[3]; float maxs[3]; - struct mnode_s *parent; - // leaf specific byte *compressed_vis; efrag_t *efrags; @@ -274,6 +270,9 @@ typedef struct mod_brush_s { byte *lightdata; char *entities; //FIXME should not be here + mnode_t **node_parents; + mnode_t **leaf_parents; + unsigned int checksum; unsigned int checksum2; } mod_brush_t; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 8a703050d..b18de9076 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -585,13 +585,15 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) } static void -Mod_SetParent (mnode_t *node, mnode_t *parent) +Mod_SetParent (mod_brush_t *brush, mnode_t *node, mnode_t *parent) { - node->parent = parent; - if (node->contents < 0) + if (node->contents < 0) { + brush->leaf_parents[(mleaf_t *)node - brush->leafs] = parent; return; - Mod_SetParent (node->children[0], node); - Mod_SetParent (node->children[1], node); + } + brush->node_parents[node - brush->nodes] = parent; + Mod_SetParent (brush, node->children[0], node); + Mod_SetParent (brush, node->children[1], node); } static void @@ -646,7 +648,10 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) } } - Mod_SetParent (brush->nodes, NULL); // sets nodes and leafs + size_t size = (brush->numleafs + brush->numnodes) * sizeof (mnode_t *); + brush->node_parents = Hunk_AllocName (size, mod->name); + brush->leaf_parents = brush->node_parents + brush->numnodes; + Mod_SetParent (brush, brush->nodes, NULL); // sets nodes and leafs } static void diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 2475873a5..47b78a643 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -54,6 +54,7 @@ R_MarkLeaves (void) mleaf_t *leaf; mnode_t *node; msurface_t **mark; + mod_brush_t *brush = &r_worldentity.model->brush; if (r_oldviewleaf == r_viewleaf && !r_novis->int_val) return; @@ -67,13 +68,13 @@ R_MarkLeaves (void) r_oldviewleaf = 0; // so vis will be recalcualted when novis gets // turned off vis = solid; - memset (solid, 0xff, (r_worldentity.model->brush.numleafs + 7) >> 3); + memset (solid, 0xff, (brush->numleafs + 7) >> 3); } else vis = Mod_LeafPVS (r_viewleaf, r_worldentity.model); - for (i = 0; (int) i < r_worldentity.model->brush.numleafs; i++) { + for (i = 0; (int) i < brush->numleafs; i++) { if (vis[i >> 3] & (1 << (i & 7))) { - leaf = &r_worldentity.model->brush.leafs[i + 1]; + leaf = &brush->leafs[i + 1]; if ((c = leaf->nummarksurfaces)) { mark = leaf->firstmarksurface; do { @@ -81,13 +82,14 @@ R_MarkLeaves (void) mark++; } while (--c); } - node = (mnode_t *) leaf; - do { + leaf->visframe = r_visframecount; + node = brush->leaf_parents[leaf - brush->leafs]; + while (node) { if (node->visframe == r_visframecount) break; node->visframe = r_visframecount; - node = node->parent; - } while (node); + node = brush->node_parents[node - brush->nodes]; + } } } } From 0bfb60775e204a5dedf3a1df8699d212f5c602ac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Feb 2021 13:19:19 +0900 Subject: [PATCH 1304/3664] [util] Ensure hunk allocs are cache alligned This doesn't seem to make much difference in the vulkan renderer, but it certainly doesn't hurt. --- include/QF/sys.h | 3 ++- libs/audio/test/testsound.c | 2 +- libs/util/sys.c | 14 ++++++++++++-- libs/util/zone.c | 10 ++++++---- nq/source/host.c | 2 +- qtv/source/qtv.c | 2 +- qw/source/cl_main.c | 2 +- qw/source/sv_demo.c | 2 +- qw/source/sv_main.c | 2 +- ruamoko/qwaq/builtins/main.c | 2 +- ruamoko/qwaq/builtins/qwaq.c | 2 +- tools/bsp2img/bsp2img.c | 2 +- tools/qfcc/test/test-harness.c | 2 +- tools/qflmp/lmp.c | 2 +- tools/wad/wad.c | 2 +- 15 files changed, 32 insertions(+), 19 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 8d32d14e2..58aa08b76 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -122,7 +122,8 @@ void Sys_Init_Cvars (void); // memory protection // void Sys_MakeCodeWriteable (uintptr_t startaddr, size_t length); -void Sys_PageIn (void *ptr, int size); +void Sys_PageIn (void *ptr, size_t size); +void *Sys_Alloc (size_t size); // // system IO diff --git a/libs/audio/test/testsound.c b/libs/audio/test/testsound.c index f4518d7ac..698fc40ec 100644 --- a/libs/audio/test/testsound.c +++ b/libs/audio/test/testsound.c @@ -68,7 +68,7 @@ init (void) COM_ParseConfig (); Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); - Memory_Init (malloc (MEMSIZE), MEMSIZE); + Memory_Init (Sys_Alloc (MEMSIZE), MEMSIZE); QFS_Init ("qw"); PI_Init (); diff --git a/libs/util/sys.c b/libs/util/sys.c index 7e09b4f91..db0777f07 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -612,11 +612,11 @@ Sys_TimeID (void) //FIXME I need a new name, one that doesn't make me feel 3 fee } VISIBLE void -Sys_PageIn (void *ptr, int size) +Sys_PageIn (void *ptr, size_t size) { //may or may not be useful in linux #ifdef _WIN32 byte *x; - int m, n; + size_t m, n; // touch all the memory to make sure it's there. The 16-page skip is to // keep Win 95 from thinking we're trying to page ourselves in (we are @@ -632,6 +632,16 @@ Sys_PageIn (void *ptr, int size) //#endif } +VISIBLE void * +Sys_Alloc (size_t size) +{ + size_t page_size = sysconf (_SC_PAGESIZE); + size_t page_mask = page_size - 1; + size = (size + page_mask) & ~page_mask; + return mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); +} + VISIBLE void Sys_DebugLog (const char *file, const char *fmt, ...) { diff --git a/libs/util/zone.c b/libs/util/zone.c index f52226d55..fdd440764 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -56,6 +56,7 @@ static qboolean Cache_FreeLRU (void); #define HUNK_SENTINAL 0x1df001ed #define MINFRAGMENT 64 +#define HUNK_ALIGN 64 /* ZONE MEMORY ALLOCATION @@ -413,6 +414,7 @@ typedef struct { int sentinal; int size; // including sizeof(hunk_t), -1 = not allocated char name[8]; + char fill[48]; // pad out to 64 bytes } hunk_t; byte *hunk_base; @@ -551,7 +553,7 @@ Hunk_AllocName (int size, const char *name) if (size < 0) Sys_Error ("Hunk_Alloc: bad size: %i", size); - size = sizeof (hunk_t) + ((size + 15) & ~15); + size = sizeof (hunk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); if (hunk_size - hunk_low_used - hunk_high_used < size) { Hunk_HighMark(); @@ -618,7 +620,7 @@ Hunk_HighAlloc (int size) Hunk_Check (); #endif - size = ((size + 15) & ~15); + size = ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); if (hunk_size - hunk_low_used - hunk_high_used < size) { Sys_Printf ("Hunk_HighAlloc: failed on %i bytes\n", size); @@ -640,7 +642,7 @@ Hunk_TempAlloc (int size) { void *buf; - size = (size + 15) & ~15; + size = (size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1); if (hunk_tempactive) { if (hunk_high_used - hunk_tempmark >= size + (int) sizeof (hunk_t)) { @@ -1009,7 +1011,7 @@ Cache_Alloc (cache_user_t *c, int size, const char *name) if (size <= 0) Sys_Error ("Cache_Alloc: size %i", size); - size = (size + sizeof (cache_system_t) + 15) & ~15; + size = (size + sizeof (cache_system_t) + HUNK_ALIGN - 1) & ~(HUNK_ALIGN-1); // find memory for it while (1) { diff --git a/nq/source/host.c b/nq/source/host.c index 65266f801..dba8202e4 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -859,7 +859,7 @@ Host_Init_Memory (void) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", mem_size / (float) 0x100000); - mem_base = malloc (mem_size); + mem_base = Sys_Alloc (mem_size); if (!mem_base) Sys_Error ("Can't allocate %d", mem_size); diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 513bb069e..049f0a568 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -214,7 +214,7 @@ qtv_memory_init (void) Cvar_SetFlags (qtv_mem_size, qtv_mem_size->flags | CVAR_ROM); mem_size = (int) (qtv_mem_size->value * 1024 * 1024); - mem_base = malloc (mem_size); + mem_base = Sys_Alloc (mem_size); if (!mem_base) Sys_Error ("Can't allocate %d", mem_size); Memory_Init (mem_base, mem_size); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index d9ee07b56..5fcf0364e 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1756,7 +1756,7 @@ CL_Init_Memory (void) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", mem_size / (float) 0x100000); - mem_base = malloc (mem_size); + mem_base = Sys_Alloc (mem_size); if (!mem_base) Sys_Error ("Can't allocate %d", mem_size); diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index b13135c93..1018ecb6c 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -774,7 +774,7 @@ Demo_Init (void) if (p < com_argc - 1) size = atoi (com_argv[p + 1]) * 1024; else - Sys_Error ("Memory_Init: you must specify a size in KB after " + Sys_Error ("Demo_Init: you must specify a size in KB after " "-democache"); } diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 0156d689a..d91a24832 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2470,7 +2470,7 @@ SV_Init_Memory (void) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", mem_size / (float) 0x100000); - mem_base = malloc (mem_size); + mem_base = Sys_Alloc (mem_size); if (!mem_base) Sys_Error ("Can't allocate %d", mem_size); diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index dbafed33f..f8800df93 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -136,7 +136,7 @@ init_qf (void) //Cvar_Set (developer, "1"); - Memory_Init (malloc (8 * 1024 * 1024), 8 * 1024 * 1024); + Memory_Init (Sys_Alloc (8 * 1024 * 1024), 8 * 1024 * 1024); Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); diff --git a/ruamoko/qwaq/builtins/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c index f74b429cf..c1733ae0e 100644 --- a/ruamoko/qwaq/builtins/qwaq.c +++ b/ruamoko/qwaq/builtins/qwaq.c @@ -114,7 +114,7 @@ init_qf (void) //Cvar_Set (developer, "1"); - Memory_Init (malloc (8 * 1024 * 1024), 8 * 1024 * 1024); + Memory_Init (Sys_Alloc (8 * 1024 * 1024), 8 * 1024 * 1024); Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); diff --git a/tools/bsp2img/bsp2img.c b/tools/bsp2img/bsp2img.c index 7b95c35a6..bf99eea67 100644 --- a/tools/bsp2img/bsp2img.c +++ b/tools/bsp2img/bsp2img.c @@ -925,7 +925,7 @@ write_pcx (image_t *image) Sys_Init (); - Memory_Init (malloc (MEMSIZE), MEMSIZE); + Memory_Init (Sys_Alloc (MEMSIZE), MEMSIZE); pcx = EncodePCX (image->image, image->width, image->height, image->width, palette, false, &pcx_len); if (Qwrite (outfile, pcx, pcx_len) != pcx_len) { diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index ba9759c19..69de8c47b 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -134,7 +134,7 @@ init_qf (void) Sys_Init (); Cvar_Get ("developer", va ("%d", options.developer), 0, 0, 0); - Memory_Init (malloc (1024 * 1024), 1024 * 1024); + Memory_Init (Sys_Alloc (1024 * 1024), 1024 * 1024); cvar_t *debug = Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "2", 0, 0, 0); diff --git a/tools/qflmp/lmp.c b/tools/qflmp/lmp.c index 1840ce328..06a77e370 100644 --- a/tools/qflmp/lmp.c +++ b/tools/qflmp/lmp.c @@ -334,7 +334,7 @@ main (int argc, char **argv) this_program = argv[0]; Sys_Init (); - Memory_Init (malloc (MEMSIZE), MEMSIZE); + Memory_Init (Sys_Alloc (MEMSIZE), MEMSIZE); decode_args (argc, argv); diff --git a/tools/wad/wad.c b/tools/wad/wad.c index a1caf6fc9..08abf6d81 100644 --- a/tools/wad/wad.c +++ b/tools/wad/wad.c @@ -396,7 +396,7 @@ main (int argc, char **argv) lumpinfo_t *pf; Sys_Init (); - Memory_Init (malloc (MEMSIZE), MEMSIZE); + Memory_Init (Sys_Alloc (MEMSIZE), MEMSIZE); this_program = argv[0]; From 5d1d85f72e09f1ee385559b1c6f32b167e46a705 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Feb 2021 13:21:08 +0900 Subject: [PATCH 1305/3664] [util] Resurrect Hunk_Print and fix some errors It turned out that Hunk_HighAlloc was not creating a hunk header (ancient bug by me), and I cleaned up a bunch of name-size issues, along the way. --- include/QF/zone.h | 1 + libs/util/zone.c | 42 +++++++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/include/QF/zone.h b/include/QF/zone.h index 10063b2cc..023ff07d6 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -105,6 +105,7 @@ void Z_SetError (memzone_t *zone, void (*err) (void *data, const char *msg), void *data); void Z_CheckPointer (const memzone_t *zone, const void *ptr, int size); +void Hunk_Print (qboolean all); void *Hunk_Alloc (int size); // returns 0 filled memory void *Hunk_AllocName (int size, const char *name); int Hunk_LowMark (void) __attribute__((pure)); diff --git a/libs/util/zone.c b/libs/util/zone.c index fdd440764..14ef0b503 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -438,7 +438,8 @@ Hunk_Check (void) for (h = (hunk_t *) hunk_base; (byte *) h != hunk_base + hunk_low_used;) { if (h->sentinal != HUNK_SENTINAL) Sys_Error ("Hunk_Check: trashed sentinal"); - if (h->size < 16 || h->size + (byte *) h - hunk_base > hunk_size) + if (h->size < (int) sizeof (hunk_t) + || h->size + (byte *) h - hunk_base > hunk_size) Sys_Error ("Hunk_Check: bad size"); h = (hunk_t *) ((byte *) h + h->size); } @@ -451,15 +452,13 @@ Hunk_Check (void) Otherwise, allocations with the same name will be totaled up before printing. */ -/* -static void + +VISIBLE void Hunk_Print (qboolean all) { - char name[9]; hunk_t *h, *next, *endlow, *starthigh, *endhigh; int count, sum, totalblocks; - name[8] = 0; count = 0; sum = 0; totalblocks = 0; @@ -488,7 +487,8 @@ Hunk_Print (qboolean all) // run consistancy checks if (h->sentinal != HUNK_SENTINAL) Sys_Error ("Hunk_Check: trahsed sentinal"); - if (h->size < 16 || h->size + (byte *) h - hunk_base > hunk_size) + if (h->size < (int) sizeof (hunk_t) + || h->size + (byte *) h - hunk_base > hunk_size) Sys_Error ("Hunk_Check: bad size"); next = (hunk_t *) ((byte *) h + h->size); @@ -497,15 +497,14 @@ Hunk_Print (qboolean all) sum += h->size; // print the single block - memcpy (name, h->name, 8); if (all) - Sys_Printf ("%8p :%8i %8s\n", h, h->size, name); + Sys_Printf ("%8p :%8i %8.8s\n", h, h->size, h->name); // print the total if (next == endlow || next == endhigh || strncmp (h->name, next->name, 8)) { if (!all) - Sys_Printf (" :%8i %8s (TOTAL)\n", sum, name); + Sys_Printf (" :%8i %8.8s (TOTAL)\n", sum, h->name); count = 0; sum = 0; } @@ -516,7 +515,7 @@ Hunk_Print (qboolean all) Sys_Printf ("-------------------------\n"); Sys_Printf ("%8i total blocks\n", totalblocks); } -*/ + static void Hunk_FreeToHighMark (int mark) { @@ -579,8 +578,7 @@ Hunk_AllocName (int size, const char *name) h->size = size; h->sentinal = HUNK_SENTINAL; - memcpy (h->name, name, 8); - h->name[7] = 0; + memcpy (h->name, name, sizeof (h->name)); return (void *) (h + 1); } @@ -609,6 +607,8 @@ Hunk_FreeToLowMark (int mark) static void * Hunk_HighAlloc (int size) { + hunk_t *h; + if (size < 0) Sys_Error ("Hunk_HighAlloc: bad size: %i", size); @@ -620,7 +620,7 @@ Hunk_HighAlloc (int size) Hunk_Check (); #endif - size = ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); + size = sizeof (hunk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); if (hunk_size - hunk_low_used - hunk_high_used < size) { Sys_Printf ("Hunk_HighAlloc: failed on %i bytes\n", size); @@ -629,7 +629,11 @@ Hunk_HighAlloc (int size) hunk_high_used += size; - return (void *) (hunk_base + hunk_size - hunk_high_used); + h = (void *) (hunk_base + hunk_size - hunk_high_used); + h->sentinal = HUNK_SENTINAL; + h->size = size; + h->name[0] = 0; + return h + 1; } /* @@ -744,7 +748,7 @@ static inline void Cache_UnlinkLRU (cache_system_t * cs) { if (!cs->lru_next || !cs->lru_prev) - Sys_Error ("Cache_UnlinkLRU: NULL link: %s %p %p", + Sys_Error ("Cache_UnlinkLRU: NULL link: %.16s %p %p", cs->name, cs->lru_next, cs->lru_prev); cs->lru_next->lru_prev = cs->lru_prev; @@ -757,7 +761,7 @@ static void Cache_MakeLRU (cache_system_t * cs) { if (cs->lru_next || cs->lru_prev) - Sys_Error ("Cache_MakeLRU: active link: %s %p %p", + Sys_Error ("Cache_MakeLRU: active link: %.16s %p %p", cs->name, cs->lru_next, cs->lru_prev); cache_head.lru_next->lru_prev = cs; @@ -896,7 +900,7 @@ Cache_Print (void) cache_system_t *cd; for (cd = cache_head.next; cd != &cache_head; cd = cd->next) { - Sys_Printf ("%8d : %s\n", (int) cd->size, cd->name); + Sys_Printf ("%8d : %.16s\n", (int) cd->size, cd->name); } } @@ -929,7 +933,7 @@ Cache_Flush (void) while (cache_head.prev != &cache_head) { if (!cache_head.prev->user->data) Sys_Error ("Cache_Flush: user/system out of sync for " - "'%s' with %d size", + "'%.16s' with %d size", cache_head.prev->name, (int) cache_head.prev->size); Cache_Free (cache_head.prev->user); // reclaim the space } @@ -970,7 +974,7 @@ Cache_Free (cache_user_t *c) if (cs->readlock) Sys_Error ("Cache_Free: attempt to free locked block"); - Sys_MaskPrintf (SYS_DEV, "Cache_Free: freeing '%s' %p\n", cs->name, cs); + Sys_MaskPrintf (SYS_DEV, "Cache_Free: freeing '%.16s' %p\n", cs->name, cs); Cache_UnlinkLRU (cs); From 846fcc276c68a6d6a01ff0b3697746e8b76c86e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Feb 2021 18:24:15 +0900 Subject: [PATCH 1306/3664] [nq] Allow free-fps for demo playback I still need to look into making physics (and network, I imagine) work with unlimited frame rates, but this gets in what I need for now. --- nq/source/host.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nq/source/host.c b/nq/source/host.c index dba8202e4..bb4721677 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -529,7 +529,7 @@ Host_FilterTime (float time) //FIXME not having the framerate cap is nice, but it breaks net play timedifference = (timescale / 72.0) - (realtime - oldrealtime); - if (!cls.timedemo && (timedifference > 0)) + if (!cls.demoplayback && (timedifference > 0)) return timedifference; // framerate is too high host_frametime = realtime - oldrealtime; @@ -541,7 +541,7 @@ Host_FilterTime (float time) if (host_framerate->value > 0) host_frametime = host_framerate->value; else // don't allow really long or short frames - host_frametime = bound (0.001, host_frametime, 0.1); + host_frametime = bound (0.000, host_frametime, 0.1); return 0; } From d2536e584f112bdbfaf3e23002678c16832eab96 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 4 Feb 2021 16:58:13 +0900 Subject: [PATCH 1307/3664] [util] Add plist support to cexpr This allows plist objects to be accessed directly from cexpr expressions using struct.field syntax for dictionary objects and array[index] syntax for array objects. --- include/QF/cexpr.h | 1 + libs/util/cexpr-parse.y | 30 +++++++++++++++ libs/util/cexpr-type.c | 83 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 53fc159e7..f511b6a9c 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -132,6 +132,7 @@ extern exprtype_t cexpr_quaternion; extern exprtype_t cexpr_exprval; extern exprtype_t cexpr_field; extern exprtype_t cexpr_function; +extern exprtype_t cexpr_plitem; extern binop_t cexpr_struct_binops[]; extern binop_t cexpr_struct_pointer_binops[]; diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index f208f4680..07993af9b 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -56,6 +56,8 @@ static exprval_t *binary_expr (int op, const exprval_t *a, const exprval_t *b, exprctx_t *context); static exprval_t *field_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context); +static exprval_t *index_expr (const exprval_t *a, const exprval_t *b, + exprctx_t *context); static exprval_t *unary_expr (int op, const exprval_t *val, exprctx_t *context); static exprval_t *vector_expr (exprlist_t *list, exprctx_t *context); @@ -126,6 +128,7 @@ uexpr | '(' expr ')' { $$ = $2; } | NAME '(' opt_arg_list ')' { $$ = function_expr ($1, $3, context); } | uexpr '.' field { $$ = field_expr ($1, $3, context); } + | uexpr '[' field ']' { $$ = index_expr ($1, $3, context); } | '+' uexpr %prec UNARY { $$ = $2; } | '-' uexpr %prec UNARY { $$ = unary_expr ('-', $2, context); } | '!' uexpr %prec UNARY { $$ = unary_expr ('!', $2, context); } @@ -237,6 +240,10 @@ field_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context) binop_t *binop; exprval_t *result = 0; + if (!a) { + return 0; + } + for (binop = a->type->binops; binop->op; binop++) { if (binop->op == '.' && binop->other == b->type) { break; @@ -254,6 +261,29 @@ field_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context) return result; } +static exprval_t * +index_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context) +{ + binop_t *binop; + exprval_t *result = 0; + + for (binop = a->type->binops; binop->op; binop++) { + if (binop->op == '[' && binop->other == b->type) { + break; + } + } + if (!binop->op) { + cexpr_error (context, "invalid index expression: %s.%s", + a->type->name, b->type->name); + result = cexpr_value (&cexpr_int, context); + *(int *) result->value = 0; + } else { + exprval_t c = { 0, &result }; + binop->func (a, b, &c, context); + } + return result; +} + static exprval_t * unary_expr (int op, const exprval_t *val, exprctx_t *context) { diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 57c7a945b..c01e0cac0 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -30,6 +30,7 @@ #include #include "QF/cexpr.h" +#include "QF/cmem.h" #include "QF/mathlib.h" #include "QF/qfplist.h" #include "QF/simd/vec4f.h" @@ -594,6 +595,88 @@ exprtype_t cexpr_function = { 0, }; +static void +plitem_field (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + __auto_type dict = *(plitem_t **) a->value; + __auto_type key = (const char *) b->value; + + if (PL_Type (dict) != QFDictionary) { + cexpr_error(ctx, "not a dictionary object"); + return; + } + plitem_t *item = PL_ObjectForKey (dict, key); + exprval_t *val = 0; + if (!item) { + cexpr_error (ctx, "key not found: %s", key); + } else { + val = cexpr_value (&cexpr_plitem, ctx); + *(plitem_t **) val->value = item; + } + *(exprval_t **) c->value = val; +} + +static void +plitem_index (const exprval_t *a, int index, exprval_t *c, + exprctx_t *ctx) +{ + __auto_type array = *(plitem_t **) a->type->data; + + if (PL_Type (array) != QFArray) { + cexpr_error(ctx, "not an array object"); + return; + } + plitem_t *item = PL_ObjectAtIndex (array, index); + exprval_t *val = 0; + if (!item) { + cexpr_error (ctx, "invalid index: %d", index); + } else { + val = cexpr_value (&cexpr_plitem, ctx); + *(plitem_t **) val->value = item; + } + *(exprval_t **) c->value = val; +} + +static void +plitem_int (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + int index = *(int *) a->value; + plitem_index (a, index, c, ctx); +} + +static void +plitem_uint (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + int index = *(int *) a->value; + plitem_index (a, index, c, ctx); +} + +static void +plitem_size_t (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + int index = *(int *) a->value; + plitem_index (a, index, c, ctx); +} + +binop_t plitem_binops[] = { + { '.', &cexpr_field, &cexpr_plitem, plitem_field }, + { '[', &cexpr_int, &cexpr_plitem, plitem_int }, + { '[', &cexpr_uint, &cexpr_plitem, plitem_uint }, + { '[', &cexpr_size_t, &cexpr_plitem, plitem_size_t }, + {} +}; + +exprtype_t cexpr_plitem = { + "plitem", + sizeof (plitem_t *), + plitem_binops, + 0, +}; + VISIBLE binop_t * cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) { From 8179c44042c60ef4db469e1302cc1b029f7a616d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 4 Feb 2021 17:03:49 +0900 Subject: [PATCH 1308/3664] [vulkan] Rework pipeline parsing for better reuse It's not entirely there yet, but the basics are working. Work is still needed for avoiding duplication of objects (different threads will have different contexts and thus different tables, so necessary per-thread duplication should not become a problem) and general access to arbitrary fields (mostly just parsing the strings) --- include/QF/Vulkan/qf_vid.h | 10 +- include/vid_vulkan.h | 1 + libs/video/renderer/vulkan/qfpipeline.plist | 103 +++--- .../video/renderer/vulkan/vkgen/Makemodule.am | 2 - libs/video/renderer/vulkan/vkgen/vkgen.r | 32 -- libs/video/renderer/vulkan/vkgen/vkhandle.h | 8 - libs/video/renderer/vulkan/vkgen/vkhandle.r | 74 ---- libs/video/renderer/vulkan/vkgen/vkresource.h | 9 - libs/video/renderer/vulkan/vkgen/vkresource.r | 44 --- libs/video/renderer/vulkan/vkparse.c | 323 ++++++++++++------ libs/video/renderer/vulkan/vkparse.h | 13 +- libs/video/renderer/vulkan/vkparse.plist | 69 +--- libs/video/renderer/vulkan/vulkan_alias.c | 9 +- libs/video/renderer/vulkan/vulkan_bsp.c | 13 +- libs/video/renderer/vulkan/vulkan_draw.c | 9 +- .../video/renderer/vulkan/vulkan_vid_common.c | 100 ++++-- 16 files changed, 388 insertions(+), 431 deletions(-) delete mode 100644 libs/video/renderer/vulkan/vkgen/vkhandle.h delete mode 100644 libs/video/renderer/vulkan/vkgen/vkhandle.r delete mode 100644 libs/video/renderer/vulkan/vkgen/vkresource.h delete mode 100644 libs/video/renderer/vulkan/vkgen/vkresource.r diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 7e30a3a57..1102845b5 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -40,7 +40,6 @@ void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); -VkPipeline Vulkan_CreatePipeline (struct vulkan_ctx_s *ctx, const char *name); void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx); void Vulkan_DestroyMatrices (struct vulkan_ctx_s *ctx); void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx, float aspect); @@ -51,4 +50,13 @@ void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); void Vulkan_Shutdown_Common (struct vulkan_ctx_s *ctx); void Vulkan_CreateStagingBuffers (struct vulkan_ctx_s *ctx); +VkPipeline Vulkan_CreatePipeline (struct vulkan_ctx_s *ctx, const char *name); +VkDescriptorPool Vulkan_CreateDescriptorPool (struct vulkan_ctx_s *ctx, + const char *name); +VkPipelineLayout Vulkan_CreatePipelineLayout (struct vulkan_ctx_s *ctx, + const char *name); +VkSampler Vulkan_CreateSampler (struct vulkan_ctx_s *ctx, const char *name); +VkDescriptorSetLayout Vulkan_CreateDescriptorSetLayout(struct vulkan_ctx_s*ctx, + const char *name); + #endif // __QF_Vulkan_vid_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index a213c7ac5..38aa4b69f 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -58,6 +58,7 @@ typedef struct vulkan_ctx_s { struct hashlink_s *hashlinks; //FIXME want per thread VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain struct plitem_s *pipelineDef; + struct hashtab_s *shaderModules; struct hashtab_s *setLayouts; struct hashtab_s *pipelineLayouts; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 96de769c9..8ba2937c2 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -1,19 +1,4 @@ { - shaderModules = { - // specify shader modules to load into memory - // key is the name of the module for referecy by the pipeline - // value the path to the spv file to load - // $shader refers to the shader install path - // $builtin refers to compiled-in shaders - passthrough = $builtin/passthrough.vert; - pushcolor = $builtin/pushcolor.frag; - twodv = $builtin/twod.vert; - twodf = $builtin/twod.frag; - quakebspv = $builtin/quakebsp.vert; - quakebspf = $builtin/quakebsp.frag; - aliasv = $builtin/alias.vert; - aliasf = $builtin/alias.frag; - }; samplers = { quakepic = { magFilter = nearest; @@ -32,7 +17,7 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; - quakebsp.sampler = { + quakebsp_sampler = { magFilter = linear; minFilter = linear; mipmapMode = linear; @@ -49,7 +34,7 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; - alias.sampler = { + alias_sampler = { magFilter = linear; minFilter = linear; mipmapMode = linear; @@ -68,7 +53,7 @@ }; }; descriptorPools = { - twod.pool = { + twod_pool = { flags = 0; maxSets = $framebuffers.size; bindings = ( @@ -82,7 +67,7 @@ }, ); }; - alias.pool = { + alias_pool = { flags = 0; maxSets = "2z * $framebuffers.size"; bindings = ( @@ -94,7 +79,7 @@ }; }; setLayouts = { - twod.set = { + twod_set = { bindings = ( { binding = 0; @@ -110,7 +95,7 @@ }, ); }; - quakebsp.set = { + quakebsp_set = { flags = push_descriptor; bindings = ( { @@ -151,7 +136,7 @@ }, ); }; - alias.set = { + alias_set = { flags = push_descriptor; bindings = ( { @@ -174,7 +159,7 @@ }, ); }; - alias.matrices = { + alias_matrices = { bindings = ( { binding = 0; @@ -184,7 +169,7 @@ }, ); }; - alias.textures = { + alias_textures = { flags = push_descriptor; bindings = ( { @@ -213,7 +198,7 @@ }, ); }; - alias.lights = { + alias_lights = { bindings = ( { binding = 0; @@ -242,11 +227,11 @@ }; }; pipelineLayouts = { - twod.layout = { - setLayouts = (twod.set); + twod_layout = { + setLayouts = (twod_set); }; - quakebsp.layout = { - setLayouts = (quakebsp.set); + quakebsp_layout = { + setLayouts = (quakebsp_set); pushConstantRanges = ( { stageFlags = vertex; @@ -260,9 +245,9 @@ }, ); }; - alias.layout = { - //setLayouts = (alias.matrices, alias.lights, alias.textures); - setLayouts = (alias.set); + alias_layout = { + //setLayouts = (alias_matrices, alias_lights, alias_textures); + setLayouts = (alias_set); pushConstantRanges = ( { stageFlags = vertex; @@ -290,11 +275,15 @@ pipelines = { alias = { stages = ( - { stage = vertex; name = main; module = aliasv; }, + { + stage = vertex; + name = main; + module = $builtin/alias.vert; + }, { stage = fragment; name = main; - module = aliasf; + module = $builtin/alias.frag; specializationInfo = { mapEntries = ( { size = 4; offset = 0; constantID = 0; }, @@ -412,13 +401,21 @@ dynamic = { dynamicState = ( viewport, scissor, blend_constants ); }; - layout = alias.layout; + layout = alias_layout; //renderPass = renderpass; }; - quakebsp.main = { + quakebsp_main = { stages = ( - { stage = vertex; name = main; module = quakebspv; }, - { stage = fragment; name = main; module = quakebspf; }, + { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/quakebsp.frag; + }, ); vertexInput = { bindings = ( @@ -501,16 +498,20 @@ dynamic = { dynamicState = ( viewport, scissor, blend_constants ); }; - layout = quakebsp.layout; + layout = quakebsp_layout; //renderPass = renderpass; }; - quakebsp.skysheet = { + quakebsp_skysheet = { stages = ( - { stage = vertex; name = main; module = quakebspv; }, + { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }, { stage = fragment; name = main; - module = quakebspf; + module = $builtin/quakebsp.frag; specializationInfo = { mapEntries = ( { size = 4; offset = 0; constantID = 0; }, @@ -603,13 +604,21 @@ dynamic = { dynamicState = ( viewport, scissor, blend_constants ); }; - layout = quakebsp.layout; + layout = quakebsp_layout; //renderPass = renderpass; }; twod = { stages = ( - { stage = vertex; name = main; module = twodv; }, - { stage = fragment; name = main; module = twodf; }, + { + stage = vertex; + name = main; + module = $builtin/twod.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/twod.frag; + }, ); vertexInput = { bindings = ( @@ -698,7 +707,7 @@ dynamic = { dynamicState = ( viewport, scissor ); }; - layout = twod.layout; + layout = twod_layout; //renderPass = renderpass; }; }; @@ -764,7 +773,7 @@ }, ); }; - renderpass.msaa = { + renderpass_msaa = { attachments = ( { flags = 0; diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 2fba61b0b..b60e97f1d 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -13,8 +13,6 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkfieldstring.r \ libs/video/renderer/vulkan/vkgen/vkfieldtype.r \ libs/video/renderer/vulkan/vkgen/vkgen.r \ - libs/video/renderer/vulkan/vkgen/vkhandle.r \ - libs/video/renderer/vulkan/vkgen/vkresource.r \ libs/video/renderer/vulkan/vkgen/vkstruct.r \ libs/video/renderer/vulkan/vkgen/vktype.r \ libs/video/renderer/vulkan/vkgen/vulkan.r diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index a336a861c..25bcbaf69 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -10,8 +10,6 @@ #include "vkgen.h" #include "vkstruct.h" #include "vkenum.h" -#include "vkhandle.h" -#include "vkresource.h" static AutoreleasePool *autorelease_pool; static void @@ -154,7 +152,6 @@ main(int argc, string *argv) PLItem *plist; PLItem *search; PLItem *handles; - PLItem *resources; arp_start (); @@ -179,7 +176,6 @@ main(int argc, string *argv) } search = [[plist getObjectForKey: "search"] retain]; handles = [[plist getObjectForKey: "handles"] retain]; - resources = [[plist getObjectForKey: "resources"] retain]; parse = [[plist getObjectForKey: "parse"] retain]; encodings = PR_FindGlobal (".type_encodings"); @@ -204,17 +200,6 @@ main(int argc, string *argv) } } - PLItem *handle_keys = [[handles allKeys] retain]; - for (int i = [handle_keys count]; i-- > 0; ) { - string search_name = [[handle_keys getObjectAtIndex:i] string]; - id obj = (id) Hash_Find (available_types, search_name); - obj = [obj resolveType]; - printf("handle: %d %s\n", obj, class_get_class_name([obj class])); - if (obj && [obj class] == [Struct class]) { - [obj addToQueue]; - } - } - while ([queue count]) { id obj = [queue objectAtIndex:0]; [queue removeObjectAtIndex:0]; @@ -261,23 +246,6 @@ main(int argc, string *argv) [obj writeTable]; arp_end (); } - for (int i = [handle_keys count]; i-- > 0; ) { - string key = [[handle_keys getObjectAtIndex:i] string]; - output_handle (key, [handles getObjectForKey: key]); - } - for (int i = [resources count]; i-- > 0; ) { - PLItem *res = [resources getObjectAtIndex:i]; - output_resource_data (res); - } - // keep the order intuitive (since it matters) - fprintf (output_file, "static parseres_t parse_resources[] = {\n"); - for (int i = 0; i < [resources count]; i++) { - PLItem *res = [resources getObjectAtIndex:i]; - output_resource_entry (res); - } - fprintf (output_file, "\t{}\n"); - fprintf (output_file, "};\n"); - fprintf (output_file, "static void\n"); fprintf (output_file, "vkgen_init_symtabs (exprctx_t *context)\n"); fprintf (output_file, "{\n"); diff --git a/libs/video/renderer/vulkan/vkgen/vkhandle.h b/libs/video/renderer/vulkan/vkgen/vkhandle.h deleted file mode 100644 index 47a68798b..000000000 --- a/libs/video/renderer/vulkan/vkgen/vkhandle.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __renderer_vulkan_vkgen_vkhandle_h -#define __renderer_vulkan_vkgen_vkhandle_h - -@class PLItem; - -void output_handle (string name, PLItem *handle); - -#endif//__renderer_vulkan_vkgen_vkhandle_h diff --git a/libs/video/renderer/vulkan/vkgen/vkhandle.r b/libs/video/renderer/vulkan/vkgen/vkhandle.r deleted file mode 100644 index ec78c22ba..000000000 --- a/libs/video/renderer/vulkan/vkgen/vkhandle.r +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include - -#include "vkgen.h" -#include "vkhandle.h" - -void -output_handle (string name, PLItem *handle) -{ - string symtab = str_hold ([[handle getObjectForKey:"symtab"] string]); - string class = str_hold ([[handle getObjectForKey:"class"] string]); - string create = str_hold ([[handle getObjectForKey:"create"] string]); - string custom = str_hold ([[handle getObjectForKey:"custom"] string]); - if (!custom) { - fprintf (output_file, "static int parse_%s (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context)\n", name); - fprintf (output_file, "{\n"); - fprintf (output_file, "\t__auto_type handle = (%s *) data[0];\n", name); - fprintf (output_file, "\tvulkan_ctx_t *ctx = context->vctx;\n"); - fprintf (output_file, "\tqfv_device_t *device = ctx->device;\n"); - fprintf (output_file, "\tqfv_devfuncs_t *dfunc = device->funcs;\n"); - fprintf (output_file, "\tif (PL_Type (item) == QFString) {\n"); - fprintf (output_file, "\t\tconst char *name = PL_String (item);\n"); - fprintf (output_file, "\t\thandleref_t *hr = Hash_Find (ctx->%s, name);\n", symtab); - fprintf (output_file, "\t\tif (!hr) {\n"); - fprintf (output_file, "\t\t\tPL_Message (messages, item, \"undefined %s %%s\", name);\n", class); - fprintf (output_file, "\t\t\treturn 0;\n"); - fprintf (output_file, "\t\t}\n"); - fprintf (output_file, "\t\t*handle = (%s) hr->handle;\n", name); - fprintf (output_file, "\t\treturn 1;\n"); - fprintf (output_file, "\t}\n"); - - fprintf (output_file, "\t%sCreateInfo createInfo = {};\n", name); - - fprintf (output_file, "\tif (!parse_%sCreateInfo (0, item, &createInfo, messages, context)) {\n", name); - fprintf (output_file, "\t\treturn 0;\n"); - fprintf (output_file, "\t}\n"); - fprintf (output_file, "\tVkResult res;\n"); - fprintf (output_file, "\tres = dfunc->%s (device->dev, &createInfo, 0, handle);\n", create); - fprintf (output_file, "\tif (res != VK_SUCCESS) {\n"); - fprintf (output_file, "\t\tPL_Message (messages, item, \"could not create %s\");\n", class); - fprintf (output_file, "\t\treturn 0;\n"); - fprintf (output_file, "\t}\n"); - fprintf (output_file, "\treturn 1;\n"); - fprintf (output_file, "}\n"); - } - - fprintf (output_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context)\n", name); - fprintf (output_file, "{\n"); - fprintf (output_file, "\thandleref_t *handleref = data;\n"); - fprintf (output_file, "\tvoid *hrdata[] = { &handleref->handle };\n"); - fprintf (output_file, "\thandleref->name = strdup (field->name);\n"); - if (custom) { - fprintf (output_file, "\treturn %s (item, hrdata, messages, context);\n", custom); - } else { - fprintf (output_file, "\treturn parse_%s (item, hrdata, messages, context);\n", name); - } - fprintf (output_file, "}\n"); - - fprintf (output_file, "%s QFV_Get%s (vulkan_ctx_t *ctx, const char *name)\n", name, str_mid (name, 2)); - fprintf (output_file, "{\n"); - fprintf (output_file, "\thandleref_t *handleref = Hash_Find (ctx->%s, name);\n", symtab); - fprintf (output_file, "\treturn handleref ? (%s) handleref->handle : 0;\n", name); - fprintf (output_file, "}\n"); - - if (!custom) { - fprintf (header_file, "static int parse_%s (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context);\n", name); - } - fprintf (header_file, "int parse_%s_handleref (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context);\n", name); - fprintf (output_file, "%s QFV_Get%s (vulkan_ctx_t *ctx, const char *name);\n", name, str_mid (name, 2)); - str_free (custom); - str_free (symtab); - str_free (class); - str_free (create); -} diff --git a/libs/video/renderer/vulkan/vkgen/vkresource.h b/libs/video/renderer/vulkan/vkgen/vkresource.h deleted file mode 100644 index e72042c3e..000000000 --- a/libs/video/renderer/vulkan/vkgen/vkresource.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __renderer_vulkan_vkgen_vkresource_h -#define __renderer_vulkan_vkgen_vkresource_h - -@class PLItem; - -void output_resource_data (PLItem *resource); -void output_resource_entry (PLItem *resource); - -#endif//__renderer_vulkan_vkgen_vkresource_h diff --git a/libs/video/renderer/vulkan/vkgen/vkresource.r b/libs/video/renderer/vulkan/vkgen/vkresource.r deleted file mode 100644 index 47478d9f8..000000000 --- a/libs/video/renderer/vulkan/vkgen/vkresource.r +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include - -#include "vkgen.h" -#include "vkresource.h" - -void -output_resource_data (PLItem *resource) -{ - string name = str_hold ([[resource getObjectForKey:"name"] string]); - string parse_type = str_hold ([[resource getObjectForKey:"parse_type"] string]); - string parser = str_hold ([[resource getObjectForKey:"parser"] string]); - string type = str_hold ([[resource getObjectForKey:"type"] string]); - - fprintf (output_file, "static plelement_t resource_%s_data = {\n", name); - fprintf (output_file, "\t%s,\n", parse_type); - fprintf (output_file, "\tsizeof (%s),\n", type); - fprintf (output_file, "\tmalloc,\n"); - fprintf (output_file, "\t%s,\n", parser); - fprintf (output_file, "\t0,\n"); - fprintf (output_file, "};\n"); - - fprintf (output_file, "static plfield_t resource_%s_field = {\n", name); - fprintf (output_file, "\t0, 0, %s, 0, &resource_%s_data\n", - parse_type, name); - fprintf (output_file, "};\n"); - - str_free (name); - str_free (parse_type); - str_free (parser); - str_free (type); -} - -void -output_resource_entry (PLItem *resource) -{ - string name = str_hold ([[resource getObjectForKey:"name"] string]); - string table = str_hold ([[resource getObjectForKey:"table"] string]); - fprintf (output_file, - "\t{\"%s\", &resource_%s_field, field_offset (vulkan_ctx_t, %s) },\n", - name, name, table); - str_free (name); - str_free (table); -} diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 4108a75f5..88c580506 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -362,48 +362,103 @@ parse_RGBA (const plitem_t *item, void **data, return ret; } +static void +add_handle (hashtab_t *tab, const char *name, uint64_t handle) +{ + handleref_t *hr = malloc (sizeof (handleref_t)); + hr->name = strdup (name); + hr->handle = handle; + Hash_Add (tab, hr); +} + static int parse_VkShaderModule (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context) { __auto_type handle = (VkShaderModule *) data[0]; vulkan_ctx_t *ctx = context->vctx; + qfv_device_t *device = ctx->device; const char *name = PL_String (item); handleref_t *hr = Hash_Find (ctx->shaderModules, name); - if (!hr) { - PL_Message (messages, item, "undefined shader module %s", name); + if (hr) { + *handle = (VkShaderModule) hr->handle; + return 1; + } + if (!(*handle = QFV_CreateShaderModule (device, name))) { + PL_Message (messages, item, "could not find shader %s", name); return 0; } - *handle = (VkShaderModule) hr->handle; + add_handle (ctx->shaderModules, name, (uint64_t) *handle); return 1; } static int -parse_VkShaderModule_resource (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *context) +parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) { - __auto_type handle = (VkShaderModule *) data[0]; + __auto_type handle = (VkDescriptorSetLayout *) data; + int ret = 1; + exprctx_t ectx = *((parsectx_t *) context)->ectx; vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; - qfv_device_t *device = ctx->device; - const char *shader_path = PL_String (item); - if (!(*handle = QFV_CreateShaderModule (device, shader_path))) { - PL_Message (messages, item, "could not find shader %s", shader_path); - return 0; + const char *name = PL_String (item); + Sys_Printf ("parse_VkDescriptorSetLayout: %s\n", name); + name = va (ctx->va_ctx, "$properties.setLayouts.%s", name); + + handleref_t *hr = Hash_Find (ctx->setLayouts, name); + if (hr) { + *handle = (VkDescriptorSetLayout) hr->handle; + return 1; } - QFV_duSetObjectName (device, VK_OBJECT_TYPE_SHADER_MODULE, *handle, - va (ctx->va_ctx, "shader:%s", shader_path)); - return 1; + + plitem_t *setItem = 0; + exprval_t result = { &cexpr_plitem, &setItem }; + ectx.symtab = 0; + ectx.result = &result; + ret = !cexpr_eval_string (name, &ectx); + if (ret) { + VkDescriptorSetLayout setLayout; + setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem); + *handle = (VkDescriptorSetLayout) setLayout; + + add_handle (ctx->setLayouts, name, (uint64_t) setLayout); + } + return ret; } static int -parse_VkDescriptorSetLayout_array (const plfield_t *field, - const plitem_t *item, void *data, - plitem_t *messages, void *context) +parse_VkPipelineLayout (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context) { - void *layout[] = { data }; - return parse_VkDescriptorSetLayout (item, layout, messages, context); + __auto_type handle = (VkPipelineLayout *) data[0]; + int ret = 1; + exprctx_t ectx = *((parsectx_t *) context)->ectx; + vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; + + const char *name = PL_String (item); + Sys_Printf ("parse_VkPipelineLayout: %s\n", name); + name = va (ctx->va_ctx, "$properties.pipelineLayouts.%s", name); + + handleref_t *hr = Hash_Find (ctx->pipelineLayouts, name); + if (hr) { + *handle = (VkPipelineLayout) hr->handle; + return 1; + } + + plitem_t *setItem = 0; + exprval_t result = { &cexpr_plitem, &setItem }; + ectx.symtab = 0; + ectx.result = &result; + ret = !cexpr_eval_string (name, &ectx); + if (ret) { + VkPipelineLayout layout; + layout = QFV_ParsePipelineLayout (ctx, setItem); + *handle = (VkPipelineLayout) layout; + + add_handle (ctx->pipelineLayouts, name, (uint64_t) layout); + } + return ret; } static const char * @@ -600,54 +655,6 @@ handlref_symtab (void (*free_func)(void*,void*), vulkan_ctx_t *ctx) ctx, &ctx->hashlinks); } -void -QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *pipelinedef) -{ - plitem_t *messages = PL_NewArray (); - exprsym_t var_syms[] = { - {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, - {"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers}, - {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {} - }; - exprtab_t vars_tab = { var_syms, 0 }; - exprctx_t exprctx = {}; - parsectx_t parsectx = { &exprctx, ctx }; - int ret = 1; - - exprctx.memsuper = new_memsuper (); - exprctx.messages = messages; - exprctx.hashlinks = &ctx->hashlinks; - exprctx.external_variables = &vars_tab; - cexpr_init_symtab (&vars_tab, &exprctx); - - if (!ctx->setLayouts) { - ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); - ctx->setLayouts = handlref_symtab (setLayout_free, ctx); - ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx); - ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx); - ctx->samplers = handlref_symtab (sampler_free, ctx); - } - - for (parseres_t *res = parse_resources; res->name; res++) { - plitem_t *item = PL_ObjectForKey (pipelinedef, res->name); - if (item) { - __auto_type table = *(hashtab_t **) ((size_t) ctx + res->offset); - Sys_Printf ("found %s\n", res->name); - ret &= PL_ParseSymtab (res->field, item, table, messages, - &parsectx); - } - } - if (!ret || developer->int_val & SYS_VULKAN) { - for (int i = 0; i < PL_A_NumObjects (messages); i++) { - Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); - } - } - - PL_Free (messages); - delete_memsuper (exprctx.memsuper); -} - static const char * enum_symtab_getkey (const void *e, void *unused) { @@ -666,6 +673,14 @@ QFV_InitParse (vulkan_ctx_t *ctx) cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); cexpr_init_symtab (&vulkan_framebufferset_t_symtab, &context); cexpr_init_symtab (&imageset_symtab, &context); + + if (!ctx->setLayouts) { + ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); + ctx->setLayouts = handlref_symtab (setLayout_free, ctx); + ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx); + ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx); + ctx->samplers = handlref_symtab (sampler_free, ctx); + } } exprenum_t * @@ -674,13 +689,79 @@ QFV_GetEnum (const char *name) return Hash_Find (enum_symtab, name); } +static int +parse_object (vulkan_ctx_t *ctx, plitem_t *plist, + plparser_t parser, void *object) +{ + plitem_t *messages = PL_NewArray (); + exprctx_t exprctx = {}; + parsectx_t parsectx = { &exprctx, ctx }; + exprsym_t var_syms[] = { + {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers}, + {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, + {"properties", &cexpr_plitem, &ctx->pipelineDef}, + {} + }; + exprtab_t vars_tab = { var_syms, 0 }; + + exprctx.external_variables = &vars_tab; + exprctx.memsuper = new_memsuper (); + exprctx.messages = messages; + exprctx.hashlinks = &ctx->hashlinks; + + cexpr_init_symtab (&vars_tab, &exprctx); + + + if (!parser (0, plist, object, messages, &parsectx)) { + for (int i = 0; i < PL_A_NumObjects (messages); i++) { + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + } + return 0; + } + PL_Free (messages); + delete_memsuper (exprctx.memsuper); + + return 1; +} + +static int +parse_qfv_renderpass (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages, void *context) +{ + return PL_ParseStruct (renderpass_fields, item, data, messages, context); +} + VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) { qfv_device_t *device = ctx->device; + qfv_renderpass_t renderpass_data = {}; - plitem_t *messages = PL_NewArray (); + + if (!parse_object (ctx, plist, parse_qfv_renderpass, &renderpass_data)) { + return 0; + } + VkRenderPass renderpass; + renderpass = QFV_CreateRenderPass (device, + renderpass_data.attachments, + renderpass_data.subpasses, + renderpass_data.dependencies); + + free (renderpass_data.attachments); + for (size_t i = 0; i < renderpass_data.subpasses->size; i++) { + free ((void *) renderpass_data.subpasses->a[i].pInputAttachments); + free ((void *) renderpass_data.subpasses->a[i].pColorAttachments); + free ((void *) renderpass_data.subpasses->a[i].pResolveAttachments); + free ((void *) renderpass_data.subpasses->a[i].pDepthStencilAttachment); + free ((void *) renderpass_data.subpasses->a[i].pPreserveAttachments); + } + free (renderpass_data.subpasses); + free (renderpass_data.dependencies); + return renderpass; + +/* plitem_t *messages = PL_NewArray (); exprsym_t var_syms[] = { {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, {"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers}, @@ -707,11 +788,6 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) PL_Free (messages); delete_memsuper (exprctx.memsuper); - renderpass = QFV_CreateRenderPass (device, - renderpass_data.attachments, - renderpass_data.subpasses, - renderpass_data.dependencies); - free (renderpass_data.attachments); for (size_t i = 0; i < renderpass_data.subpasses->size; i++) { free ((void *) renderpass_data.subpasses->a[i].pInputAttachments); @@ -722,7 +798,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) } free (renderpass_data.subpasses); free (renderpass_data.dependencies); - return renderpass; + return renderpass;*/ } VkPipeline @@ -730,34 +806,13 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) { qfv_device_t *device = ctx->device; - plitem_t *messages = PL_NewArray (); - exprctx_t exprctx = {}; - parsectx_t parsectx = { &exprctx, ctx }; - exprsym_t var_syms[] = { - {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {} - }; - exprtab_t vars_tab = { var_syms, 0 }; - - exprctx.external_variables = &vars_tab; - exprctx.memsuper = new_memsuper (); - exprctx.messages = messages; - exprctx.hashlinks = &ctx->hashlinks; - - cexpr_init_symtab (&vars_tab, &exprctx); - __auto_type cInfo = QFV_AllocGraphicsPipelineCreateInfoSet (1, alloca); memset (&cInfo->a[0], 0, sizeof (cInfo->a[0])); - if (!parse_VkGraphicsPipelineCreateInfo (0, plist, &cInfo->a[0], - messages, &parsectx)) { - for (int i = 0; i < PL_A_NumObjects (messages); i++) { - Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); - } + if (!parse_object (ctx, plist, parse_VkGraphicsPipelineCreateInfo, + &cInfo->a[0])) { return 0; } - PL_Free (messages); - delete_memsuper (exprctx.memsuper); cInfo->a[0].renderPass = ctx->renderpass.renderpass; __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); @@ -765,3 +820,77 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) free (plSet); return pipeline; } + +VkDescriptorPool +QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkDescriptorPoolCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkDescriptorPoolCreateInfo, &cInfo)) { + return 0; + } + + VkDescriptorPool pool; + dfunc->vkCreateDescriptorPool (device->dev, &cInfo, 0, &pool); + + return pool; +} + +VkDescriptorSetLayout +QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkDescriptorSetLayoutCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkDescriptorSetLayoutCreateInfo, + &cInfo)) { + return 0; + } + + VkDescriptorSetLayout setLayout; + dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, &setLayout); + + return setLayout; +} + +VkPipelineLayout +QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkPipelineLayoutCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkPipelineLayoutCreateInfo, + &cInfo)) { + return 0; + } + + VkPipelineLayout layout; + dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &layout); + + return layout; +} + +VkSampler +QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkSamplerCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkSamplerCreateInfo, &cInfo)) { + return 0; + } + + VkSampler sampler; + dfunc->vkCreateSampler (device->dev, &cInfo, 0, &sampler); + + return sampler; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 459c0f6a2..480c8bc99 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -24,18 +24,15 @@ typedef struct handleref_s { uint64_t handle; } handleref_t; -VkShaderModule QFV_GetShaderModule (vulkan_ctx_t *ctx, const char *name); -VkDescriptorPool QFV_GetDescriptorPool (vulkan_ctx_t *ctx, const char *name); -VkDescriptorSetLayout QFV_GetDescriptorSetLayout (vulkan_ctx_t *ctx, - const char *name); -VkPipelineLayout QFV_GetPipelineLayout (vulkan_ctx_t *ctx, const char *name); -VkSampler QFV_GetSampler (vulkan_ctx_t *ctx, const char *name); - -void QFV_ParseResources (vulkan_ctx_t *ctx, plitem_t *plist); void QFV_InitParse (vulkan_ctx_t *ctx); exprenum_t *QFV_GetEnum (const char *name); VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist); +VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist); +VkDescriptorSetLayout QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, + plitem_t *plist); +VkPipelineLayout QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist); +VkSampler QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index edf68541e..c3a0bfdd9 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -21,70 +21,6 @@ VkDescriptorPoolCreateInfo, VkSamplerCreateInfo, ); - handles = { - VkShaderModule = { - symtab = shaderModules; - class = "shader module"; - custom = parse_VkShaderModule_resource; - }; - VkDescriptorPool = { - symtab = descriptorPools; - class = "descriptor pool"; - create = vkCreateDescriptorPool; - }; - VkDescriptorSetLayout = { - symtab = setLayouts; - class = "set layout"; - create = vkCreateDescriptorSetLayout; - }; - VkPipelineLayout = { - symtab = pipelineLayouts; - class = "pipeline layout"; - create = vkCreatePipelineLayout; - }; - VkSampler = { - symtab = samplers; - class = "sampler"; - create = vkCreateSampler; - }; - }; - resources = ( - { - name = shaderModules; - parse_type = QFString; - parser = parse_VkShaderModule_handleref; - type = handleref_t; - table = shaderModules; - }, - { - name = setLayouts; - parse_type = QFDictionary; - parser = parse_VkDescriptorSetLayout_handleref; - type = handleref_t; - table = setLayouts; - }, - { - name = pipelineLayouts; - parse_type = QFDictionary; - parser = parse_VkPipelineLayout_handleref; - type = handleref_t; - table = pipelineLayouts; - }, - { - name = descriptorPools; - parse_type = QFDictionary; - parser = parse_VkDescriptorPool_handleref; - type = handleref_t; - table = descriptorPools; - }, - { - name = samplers; - parse_type = QFDictionary; - parser = parse_VkSampler_handleref; - type = handleref_t; - table = samplers; - }, - ); parse = { VkSubpassDescription = { flags = auto; @@ -279,7 +215,7 @@ type = (array, { parse_type = (QFDictionary, QFString); type = VkDescriptorSetLayout; - parser = parse_VkDescriptorSetLayout_array; + parser = parse_VkDescriptorSetLayout; }); size = setLayoutCount; values = pSetLayouts; @@ -338,8 +274,7 @@ value = pDynamicState; }; layout = { - type = (custom, (QFDictionary, QFString), - parse_VkPipelineLayout); + type = (custom, QFString, parse_VkPipelineLayout); fields = (layout); }; basePipelineHandle = { diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 76f4ac7b5..ad42daed4 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -63,7 +63,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -#include "vkparse.h" void Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) @@ -259,12 +258,8 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) actx->frames.grow = 0; actx->pipeline = Vulkan_CreatePipeline (ctx, "alias"); - actx->layout = QFV_GetPipelineLayout (ctx, "alias.layout"); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, actx->layout, - va (ctx->va_ctx, "layout:%s", "alias.layout")); - actx->sampler = QFV_GetSampler (ctx, "alias.sampler"); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_SAMPLER, actx->sampler, - va (ctx->va_ctx, "sampler:%s", "alias.sampler")); + actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); + actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); /*__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (2 * frames, alloca); for (size_t i = 0; i < layouts->size / 2; i++) { diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a0dcd9134..5ae835897 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -68,7 +68,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -#include "vkparse.h" static float identity[] = { 1, 0, 0, 0, @@ -1449,14 +1448,10 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&bctx->frames, frames); bctx->frames.grow = 0; - bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp.main"); - bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp.skysheet"); - bctx->layout = QFV_GetPipelineLayout (ctx, "quakebsp.layout"); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, bctx->layout, - va (ctx->va_ctx, "layout:%s", "quakebsp.layout")); - bctx->sampler = QFV_GetSampler (ctx, "quakebsp.sampler"); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_SAMPLER, bctx->sampler, - va (ctx->va_ctx, "sampler:%s", "quakebsp.sampler")); + bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp_main"); + bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp_skysheet"); + bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); + bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); __auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 16b563600..ff7e6ed15 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -64,7 +64,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -#include "vkparse.h" typedef struct { float xy[2]; @@ -371,7 +370,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) ctx->cmdpool); dctx->scrap = QFV_CreateScrap (device, "draw_atlas", 2048, tex_rgba, dctx->stage); - dctx->sampler = QFV_GetSampler (ctx, "quakepic"); + dctx->sampler = Vulkan_CreateSampler (ctx, "quakepic"); qpic_t *charspic = Draw_Font8x8Pic (); @@ -384,13 +383,13 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->pipeline = Vulkan_CreatePipeline (ctx, "twod"); - dctx->layout = QFV_GetPipelineLayout (ctx, "twod.layout"); + dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout"); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = QFV_GetDescriptorSetLayout (ctx, "twod.set"); + layouts->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "twod_set"); } - __auto_type pool = QFV_GetDescriptorPool (ctx, "twod.pool"); + __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "twod_pool"); VkDescriptorBufferInfo bufferInfo = { ctx->matrices.buffer_2d, 0, VK_WHOLE_SIZE diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index ff026331a..979d30a7c 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -224,21 +224,25 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) } } -static void -qfv_load_pipeline (vulkan_ctx_t *ctx) +static plitem_t * +qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) { if (!ctx->pipelineDef) { ctx->pipelineDef = PL_GetPropertyList (quakeforge_pipeline); - if (ctx->pipelineDef) { - QFV_ParseResources (ctx, ctx->pipelineDef); - } } + + plitem_t *item = ctx->pipelineDef; + if (!item || !(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading %s\n", name); + } else { + Sys_Printf ("Found %s def\n", name); + } + return item; } void Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) { - qfv_load_pipeline (ctx); const char *name = "renderpass";//FIXME qfv_device_t *device = ctx->device; VkDevice dev = device->dev; @@ -249,15 +253,13 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val, QFV_GetMaxSampleCount (device->physDev)); if (ctx->msaaSamples > 1) { - name = "renderpass.msaa"; + name = "renderpass_msaa"; } - plitem_t *item = ctx->pipelineDef; - if (!item || !(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading renderpass: %s\n", name); + //FIXME a tad inconsistent + plitem_t *item = qfv_load_pipeline (ctx, name); + if (!item) { return; - } else { - Sys_Printf ("Found renderpass def: %s\n", name); } qfv_imageresource_t *colorImage = malloc (sizeof (*colorImage)); @@ -375,15 +377,7 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) VkPipeline Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) { - qfv_load_pipeline (ctx); - - plitem_t *item = ctx->pipelineDef; - if (!item || !(item = PL_ObjectForKey (item, "pipelines"))) { - Sys_Printf ("error loading pipelines\n"); - return 0; - } else { - Sys_Printf ("Found pipelines def\n"); - } + plitem_t *item = qfv_load_pipeline (ctx, "pipelines"); if (!(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading pipeline %s\n", name); return 0; @@ -396,6 +390,70 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) return pipeline; } +VkDescriptorPool +Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) +{ + plitem_t *item = qfv_load_pipeline (ctx, "descriptorPools"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading descriptor pool %s\n", name); + return 0; + } else { + Sys_Printf ("Found descriptor pool def %s\n", name); + } + VkDescriptorPool pool = QFV_ParseDescriptorPool (ctx, item); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool, + va (ctx->va_ctx, "descriptor_pool:%s", name)); + return pool; +} + +VkPipelineLayout +Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) +{ + plitem_t *item = qfv_load_pipeline (ctx, "pipelineLayouts"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading pipeline layout %s\n", name); + return 0; + } else { + Sys_Printf ("Found pipeline layout def %s\n", name); + } + VkPipelineLayout layout = QFV_ParsePipelineLayout (ctx, item); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, + va (ctx->va_ctx, "pipeline_layout:%s", name)); + return layout; +} + +VkSampler +Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) +{ + plitem_t *item = qfv_load_pipeline (ctx, "samplers"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading sampler %s\n", name); + return 0; + } else { + Sys_Printf ("Found sampler def %s\n", name); + } + VkSampler sampler = QFV_ParseSampler (ctx, item); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler, + va (ctx->va_ctx, "sampler:%s", name)); + return sampler; +} + +VkDescriptorSetLayout +Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) +{ + plitem_t *item = qfv_load_pipeline (ctx, "setLayouts"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading descriptor set %s\n", name); + return 0; + } else { + Sys_Printf ("Found descriptor set def %s\n", name); + } + VkDescriptorSetLayout set = QFV_ParseDescriptorSetLayout (ctx, item); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, + set, va (ctx->va_ctx, "descriptor_set:%s", name)); + return set; +} + void Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) { From a54de63feedcbd44962139153dca1345b1829b54 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 4 Feb 2021 20:40:28 +0900 Subject: [PATCH 1309/3664] [vulkan] Take care of the duplicate handles --- libs/video/renderer/vulkan/vkparse.c | 41 ++++++++++------- libs/video/renderer/vulkan/vkparse.h | 5 +++ .../video/renderer/vulkan/vulkan_vid_common.c | 44 +++++++++++++++++-- 3 files changed, 69 insertions(+), 21 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 88c580506..aa6c88325 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -362,8 +362,18 @@ parse_RGBA (const plitem_t *item, void **data, return ret; } -static void -add_handle (hashtab_t *tab, const char *name, uint64_t handle) +uint64_t +QFV_GetHandle (hashtab_t *tab, const char *name) +{ + handleref_t *hr = Hash_Find (tab, name); + if (hr) { + return hr->handle; + } + return 0; +} + +void +QFV_AddHandle (hashtab_t *tab, const char *name, uint64_t handle) { handleref_t *hr = malloc (sizeof (handleref_t)); hr->name = strdup (name); @@ -380,16 +390,15 @@ parse_VkShaderModule (const plitem_t *item, void **data, qfv_device_t *device = ctx->device; const char *name = PL_String (item); - handleref_t *hr = Hash_Find (ctx->shaderModules, name); - if (hr) { - *handle = (VkShaderModule) hr->handle; + *handle = (VkShaderModule) QFV_GetHandle (ctx->shaderModules, name); + if (*handle) { return 1; } if (!(*handle = QFV_CreateShaderModule (device, name))) { PL_Message (messages, item, "could not find shader %s", name); return 0; } - add_handle (ctx->shaderModules, name, (uint64_t) *handle); + QFV_AddHandle (ctx->shaderModules, name, (uint64_t) *handle); return 1; } @@ -404,11 +413,10 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, const char *name = PL_String (item); Sys_Printf ("parse_VkDescriptorSetLayout: %s\n", name); - name = va (ctx->va_ctx, "$properties.setLayouts.%s", name); + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); - handleref_t *hr = Hash_Find (ctx->setLayouts, name); - if (hr) { - *handle = (VkDescriptorSetLayout) hr->handle; + *handle = (VkDescriptorSetLayout) QFV_GetHandle (ctx->setLayouts, name); + if (*handle) { return 1; } @@ -422,7 +430,7 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem); *handle = (VkDescriptorSetLayout) setLayout; - add_handle (ctx->setLayouts, name, (uint64_t) setLayout); + QFV_AddHandle (ctx->setLayouts, name, (uint64_t) setLayout); } return ret; } @@ -438,11 +446,10 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, const char *name = PL_String (item); Sys_Printf ("parse_VkPipelineLayout: %s\n", name); - name = va (ctx->va_ctx, "$properties.pipelineLayouts.%s", name); + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); - handleref_t *hr = Hash_Find (ctx->pipelineLayouts, name); - if (hr) { - *handle = (VkPipelineLayout) hr->handle; + *handle = (VkPipelineLayout) QFV_GetHandle (ctx->pipelineLayouts, name); + if (*handle) { return 1; } @@ -456,7 +463,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, layout = QFV_ParsePipelineLayout (ctx, setItem); *handle = (VkPipelineLayout) layout; - add_handle (ctx->pipelineLayouts, name, (uint64_t) layout); + QFV_AddHandle (ctx->pipelineLayouts, name, (uint64_t) layout); } return ret; } @@ -700,7 +707,7 @@ parse_object (vulkan_ctx_t *ctx, plitem_t *plist, {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, {"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {"properties", &cexpr_plitem, &ctx->pipelineDef}, + {QFV_PROPERTIES, &cexpr_plitem, &ctx->pipelineDef}, {} }; exprtab_t vars_tab = { var_syms, 0 }; diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 480c8bc99..c443e98e3 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -13,6 +13,8 @@ typedef struct parsectx_s { #include "libs/video/renderer/vulkan/vkparse.hinc" #endif +#define QFV_PROPERTIES "properties" + typedef struct parseres_s { const char *name; plfield_t *field; @@ -27,6 +29,9 @@ typedef struct handleref_s { void QFV_InitParse (vulkan_ctx_t *ctx); exprenum_t *QFV_GetEnum (const char *name); +uint64_t QFV_GetHandle (struct hashtab_s *tab, const char *name); +void QFV_AddHandle (struct hashtab_s *tab, const char *name, uint64_t handle); + VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist); VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 979d30a7c..21c21b085 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -393,6 +393,14 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) VkDescriptorPool Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) { + hashtab_t *tab = ctx->descriptorPools; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".descriptorPools.%s", name); + __auto_type pool = (VkDescriptorPool) QFV_GetHandle (tab, path); + if (pool) { + return pool; + } + plitem_t *item = qfv_load_pipeline (ctx, "descriptorPools"); if (!(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading descriptor pool %s\n", name); @@ -400,7 +408,8 @@ Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found descriptor pool def %s\n", name); } - VkDescriptorPool pool = QFV_ParseDescriptorPool (ctx, item); + pool = QFV_ParseDescriptorPool (ctx, item); + QFV_AddHandle (tab, path, (uint64_t) pool); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool, va (ctx->va_ctx, "descriptor_pool:%s", name)); return pool; @@ -409,6 +418,14 @@ Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) VkPipelineLayout Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) { + hashtab_t *tab = ctx->pipelineLayouts; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); + __auto_type layout = (VkPipelineLayout) QFV_GetHandle (tab, path); + if (layout) { + return layout; + } + plitem_t *item = qfv_load_pipeline (ctx, "pipelineLayouts"); if (!(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading pipeline layout %s\n", name); @@ -416,7 +433,8 @@ Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found pipeline layout def %s\n", name); } - VkPipelineLayout layout = QFV_ParsePipelineLayout (ctx, item); + layout = QFV_ParsePipelineLayout (ctx, item); + QFV_AddHandle (tab, path, (uint64_t) layout); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, va (ctx->va_ctx, "pipeline_layout:%s", name)); return layout; @@ -425,6 +443,14 @@ Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) VkSampler Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) { + hashtab_t *tab = ctx->samplers; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".samplers.%s", name); + __auto_type sampler = (VkSampler) QFV_GetHandle (tab, path); + if (sampler) { + return sampler; + } + plitem_t *item = qfv_load_pipeline (ctx, "samplers"); if (!(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading sampler %s\n", name); @@ -432,7 +458,8 @@ Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found sampler def %s\n", name); } - VkSampler sampler = QFV_ParseSampler (ctx, item); + sampler = QFV_ParseSampler (ctx, item); + QFV_AddHandle (tab, path, (uint64_t) sampler); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler, va (ctx->va_ctx, "sampler:%s", name)); return sampler; @@ -441,6 +468,14 @@ Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) VkDescriptorSetLayout Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) { + hashtab_t *tab = ctx->setLayouts; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); + __auto_type set = (VkDescriptorSetLayout) QFV_GetHandle (tab, path); + if (set) { + return set; + } + plitem_t *item = qfv_load_pipeline (ctx, "setLayouts"); if (!(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading descriptor set %s\n", name); @@ -448,7 +483,8 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found descriptor set def %s\n", name); } - VkDescriptorSetLayout set = QFV_ParseDescriptorSetLayout (ctx, item); + set = QFV_ParseDescriptorSetLayout (ctx, item); + QFV_AddHandle (tab, path, (uint64_t) set); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, set, va (ctx->va_ctx, "descriptor_set:%s", name)); return set; From e929dca3006b1b549994056386f1f32ac4bf5916 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 4 Feb 2021 22:37:20 +0900 Subject: [PATCH 1310/3664] [util] Auto-cast plist string items The casting uses a recursive call to the expression parser, so the expressions are type-checked automatically. --- include/QF/cexpr.h | 3 +++ libs/util/cexpr-type.c | 25 +++++++++++++++++++++++ libs/video/renderer/vulkan/vkgen/vkenum.r | 2 +- libs/video/renderer/vulkan/vkparse.c | 6 ++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index f511b6a9c..4e2dd3bcb 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -118,6 +118,9 @@ void cexpr_struct_pointer_getfield (const exprval_t *a, const exprval_t *b, exprval_t *cexpr_cvar (const char *name, exprctx_t *ctx); exprval_t *cexpr_cvar_struct (exprctx_t *ctx); +void cexpr_cast_plitem (const exprval_t *val1, const exprval_t *src, + exprval_t *result, exprctx_t *ctx); + void cexpr_init_symtab (exprtab_t *symtab, exprctx_t *ctx); char *cexpr_yyget_text (void *scanner); diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index c01e0cac0..1ba3b3f0f 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -100,6 +100,7 @@ binop_t int_binops[] = { { '^', &cexpr_int, &cexpr_int, int_xor }, { '%', &cexpr_int, &cexpr_int, int_rem }, { MOD, &cexpr_int, &cexpr_int, int_mod }, + { '=', &cexpr_plitem, &cexpr_int, cexpr_cast_plitem }, {} }; @@ -154,6 +155,7 @@ binop_t uint_binops[] = { { '%', &cexpr_uint, &cexpr_uint, uint_rem }, { MOD, &cexpr_uint, &cexpr_uint, uint_rem }, { '=', &cexpr_int, &cexpr_uint, uint_cast_int }, + { '=', &cexpr_plitem, &cexpr_uint, cexpr_cast_plitem }, {} }; @@ -222,6 +224,7 @@ binop_t size_t_binops[] = { { MOD, &cexpr_size_t, &cexpr_size_t, size_t_rem }, { '=', &cexpr_int, &cexpr_size_t, size_t_cast_int }, { '=', &cexpr_uint, &cexpr_size_t, size_t_cast_uint }, + { '=', &cexpr_plitem, &cexpr_size_t, cexpr_cast_plitem }, {} }; @@ -310,6 +313,7 @@ binop_t float_binops[] = { { '%', &cexpr_float, &cexpr_float, float_rem }, { MOD, &cexpr_float, &cexpr_float, float_mod }, { '=', &cexpr_int, &cexpr_float, float_cast_int }, + { '=', &cexpr_plitem, &cexpr_float, cexpr_cast_plitem }, {} }; @@ -366,6 +370,7 @@ binop_t double_binops[] = { { '/', &cexpr_double, &cexpr_double, double_div }, { '%', &cexpr_double, &cexpr_double, double_rem }, { MOD, &cexpr_double, &cexpr_double, double_mod }, + { '=', &cexpr_plitem, &cexpr_double, cexpr_cast_plitem }, {} }; @@ -595,6 +600,26 @@ exprtype_t cexpr_function = { 0, }; +void +cexpr_cast_plitem (const exprval_t *val1, const exprval_t *src, + exprval_t *result, exprctx_t *ctx) +{ + plitem_t *item = *(plitem_t **) src->value; + const char *str = PL_String (item); + if (!str) { + cexpr_error (ctx, "not a string object: %d", PL_Line (item)); + return; + } + + exprctx_t ectx = *ctx; + ectx.result = result; + cexpr_eval_string (str, &ectx); + ctx->errors += ectx.errors; + if (ectx.errors) { + cexpr_error (ctx, "could not convert: %d", PL_Line (item)); + } +} + static void plitem_field (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx) diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 7c974f6fb..b4dc8b79f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -79,7 +79,7 @@ skip_value(string name) fprintf (output_file, "\tflag_binops,\n"); fprintf (output_file, "\tflag_unops,\n"); } else { - fprintf (output_file, "\t0,\n"); + fprintf (output_file, "\tenum_binops,\n"); fprintf (output_file, "\t0,\n"); } fprintf (output_file, "};\n"); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index aa6c88325..90e8d5d5e 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -103,6 +103,12 @@ binop_t flag_binops[] = { { '|', 0, 0, flag_or }, { '&', 0, 0, flag_and }, { '=', &cexpr_int, 0, flag_cast_int }, + { '=', &cexpr_plitem, 0, cexpr_cast_plitem }, + {} +}; + +binop_t enum_binops[] = { + { '=', &cexpr_plitem, 0, cexpr_cast_plitem }, {} }; From 7ffe197564c20d990741ce7b1234f78dc7442596 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Feb 2021 10:19:57 +0900 Subject: [PATCH 1311/3664] [vulkan] Remove some dead code I forgot to delete that block of code after getting the new code working. --- libs/video/renderer/vulkan/vkparse.c | 39 ---------------------------- 1 file changed, 39 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 90e8d5d5e..1155e3242 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -773,45 +773,6 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) free (renderpass_data.subpasses); free (renderpass_data.dependencies); return renderpass; - -/* plitem_t *messages = PL_NewArray (); - exprsym_t var_syms[] = { - {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, - {"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers}, - {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {} - }; - exprtab_t vars_tab = { var_syms, 0 }; - exprctx_t exprctx = {}; - parsectx_t parsectx = { &exprctx, ctx }; - - exprctx.memsuper = new_memsuper (); - exprctx.messages = messages; - exprctx.hashlinks = &ctx->hashlinks; - exprctx.external_variables = &vars_tab; - cexpr_init_symtab (&vars_tab, &exprctx); - - if (!PL_ParseStruct (renderpass_fields, plist, &renderpass_data, - messages, &parsectx)) { - for (int i = 0; i < PL_A_NumObjects (messages); i++) { - Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); - } - return 0; - } - PL_Free (messages); - delete_memsuper (exprctx.memsuper); - - free (renderpass_data.attachments); - for (size_t i = 0; i < renderpass_data.subpasses->size; i++) { - free ((void *) renderpass_data.subpasses->a[i].pInputAttachments); - free ((void *) renderpass_data.subpasses->a[i].pColorAttachments); - free ((void *) renderpass_data.subpasses->a[i].pResolveAttachments); - free ((void *) renderpass_data.subpasses->a[i].pDepthStencilAttachment); - free ((void *) renderpass_data.subpasses->a[i].pPreserveAttachments); - } - free (renderpass_data.subpasses); - free (renderpass_data.dependencies); - return renderpass;*/ } VkPipeline From 1275067655b0f083be5a0d25a7c6608ec2889a16 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Feb 2021 10:22:32 +0900 Subject: [PATCH 1312/3664] [vulkan] Rename vulkan_framebuffer_t It turns out I had conflated frame buffers with frames and wound up making a minor mess when separating the number of frames the renderer could have in flight from the number of swap-chain images. This is the first step towards correcting that mistake. --- include/vid_vulkan.h | 8 +-- libs/video/renderer/vid_render_vulkan.c | 49 +++++++++---------- libs/video/renderer/vulkan/qfpipeline.plist | 10 ++-- libs/video/renderer/vulkan/vkparse.c | 20 ++++---- libs/video/renderer/vulkan/vulkan_alias.c | 4 +- libs/video/renderer/vulkan/vulkan_bsp.c | 6 +-- libs/video/renderer/vulkan/vulkan_draw.c | 6 +-- .../video/renderer/vulkan/vulkan_vid_common.c | 20 ++++---- 8 files changed, 60 insertions(+), 63 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 38aa4b69f..4ddab99e3 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -22,7 +22,7 @@ typedef struct vulkan_framebuffer_s { VkCommandBuffer cmdBuffer; struct qfv_cmdbufferset_s *subCommand; -} vulkan_framebuffer_t; +} vulkan_frame_t; typedef struct vulkan_matrices_s { VkBuffer buffer_2d; @@ -34,8 +34,8 @@ typedef struct vulkan_matrices_s { float *sky_3d; } vulkan_matrices_t; -typedef struct vulkan_framebufferset_s - DARRAY_TYPE (vulkan_framebuffer_t) vulkan_framebufferset_t; +typedef struct vulkan_frameset_s + DARRAY_TYPE (vulkan_frame_t) vulkan_frameset_t; typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); @@ -76,7 +76,7 @@ typedef struct vulkan_ctx_s { struct qfv_stagebuf_s *staging; VkPipeline pipeline; size_t curFrame; - vulkan_framebufferset_t framebuffers; + vulkan_frameset_t frames; struct qfv_tex_s *default_black; struct qfv_tex_s *default_white; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index ebca7b9b0..92e68b0a2 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -124,15 +124,14 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) VkDevice dev = device->dev; qfv_queue_t *queue = &vulkan_ctx->device->queue; - __auto_type framebuffer - = &vulkan_ctx->framebuffers.a[vulkan_ctx->curFrame]; + __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; - dfunc->vkWaitForFences (dev, 1, &framebuffer->fence, VK_TRUE, 2000000000); - if (framebuffer->framebuffer) { - dfunc->vkDestroyFramebuffer (dev, framebuffer->framebuffer, 0); + dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); + if (frame->framebuffer) { + dfunc->vkDestroyFramebuffer (dev, frame->framebuffer, 0); } QFV_AcquireNextImage (vulkan_ctx->swapchain, - framebuffer->imageAvailableSemaphore, + frame->imageAvailableSemaphore, 0, &imageIndex); int attachCount = vulkan_ctx->msaaSamples > 1 ? 3 : 2; @@ -146,9 +145,8 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) } VkRenderPass renderpass = vulkan_ctx->renderpass.renderpass; - framebuffer->framebuffer = QFV_CreateFramebuffer (device, renderpass, - attachments, - sc->extent, 1); + frame->framebuffer = QFV_CreateFramebuffer (device, renderpass, + attachments, sc->extent, 1); scr_3dfunc (); while (*scr_funcs) { @@ -172,41 +170,40 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) 3, clearValues }; - dfunc->vkBeginCommandBuffer (framebuffer->cmdBuffer, &beginInfo); - renderPassInfo.framebuffer = framebuffer->framebuffer; - dfunc->vkCmdBeginRenderPass (framebuffer->cmdBuffer, &renderPassInfo, - VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); + dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); + renderPassInfo.framebuffer = frame->framebuffer; + dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, + VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); - dfunc->vkCmdExecuteCommands (framebuffer->cmdBuffer, - framebuffer->subCommand->size, - framebuffer->subCommand->a); + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, frame->subCommand->size, + frame->subCommand->a); // reset for next time around - framebuffer->subCommand->size = 0; + frame->subCommand->size = 0; - dfunc->vkCmdEndRenderPass (framebuffer->cmdBuffer); - dfunc->vkEndCommandBuffer (framebuffer->cmdBuffer); + dfunc->vkCmdEndRenderPass (frame->cmdBuffer); + dfunc->vkEndCommandBuffer (frame->cmdBuffer); VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 1, &framebuffer->imageAvailableSemaphore, &waitStage, - 1, &framebuffer->cmdBuffer, - 1, &framebuffer->renderDoneSemaphore, + 1, &frame->imageAvailableSemaphore, &waitStage, + 1, &frame->cmdBuffer, + 1, &frame->renderDoneSemaphore, }; - dfunc->vkResetFences (dev, 1, &framebuffer->fence); - dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, framebuffer->fence); + dfunc->vkResetFences (dev, 1, &frame->fence); + dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, - 1, &framebuffer->renderDoneSemaphore, + 1, &frame->renderDoneSemaphore, 1, &vulkan_ctx->swapchain->swapchain, &imageIndex, 0 }; dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); vulkan_ctx->curFrame++; - vulkan_ctx->curFrame %= vulkan_ctx->framebuffers.size; + vulkan_ctx->curFrame %= vulkan_ctx->frames.size; if (++count >= 100) { double currenTime = Sys_DoubleTime (); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 8ba2937c2..324e08e7c 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -55,25 +55,25 @@ descriptorPools = { twod_pool = { flags = 0; - maxSets = $framebuffers.size; + maxSets = $frames.size; bindings = ( { type = uniform_buffer; - descriptorCount = $framebuffers.size; + descriptorCount = $frames.size; }, { type = combined_image_sampler; - descriptorCount = $framebuffers.size; + descriptorCount = $frames.size; }, ); }; alias_pool = { flags = 0; - maxSets = "2z * $framebuffers.size"; + maxSets = "2z * $frames.size"; bindings = ( { type = uniform_buffer; - descriptorCount = "2z * $framebuffers.size"; + descriptorCount = "2z * $frames.size"; }, ); }; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 1155e3242..7e336a167 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -606,19 +606,19 @@ exprtype_t qfv_swapchain_t_type = { &qfv_swapchain_t_symtab, }; -static exprsym_t vulkan_framebufferset_t_symbols[] = { - {"size", &cexpr_size_t, (void *)field_offset (vulkan_framebufferset_t, size)}, +static exprsym_t vulkan_frameset_t_symbols[] = { + {"size", &cexpr_size_t, (void *)field_offset (vulkan_frameset_t, size)}, { } }; -static exprtab_t vulkan_framebufferset_t_symtab = { - vulkan_framebufferset_t_symbols, +static exprtab_t vulkan_frameset_t_symtab = { + vulkan_frameset_t_symbols, }; -exprtype_t vulkan_framebufferset_t_type = { - "framebufferset", - sizeof (vulkan_framebufferset_t *), +exprtype_t vulkan_frameset_t_type = { + "frameset", + sizeof (vulkan_frameset_t *), cexpr_struct_binops, 0, - &vulkan_framebufferset_t_symtab, + &vulkan_frameset_t_symtab, }; typedef struct qfv_renderpass_s { @@ -684,7 +684,7 @@ QFV_InitParse (vulkan_ctx_t *ctx) context.hashlinks = &ctx->hashlinks; vkgen_init_symtabs (&context); cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); - cexpr_init_symtab (&vulkan_framebufferset_t_symtab, &context); + cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); cexpr_init_symtab (&imageset_symtab, &context); if (!ctx->setLayouts) { @@ -711,7 +711,7 @@ parse_object (vulkan_ctx_t *ctx, plitem_t *plist, parsectx_t parsectx = { &exprctx, ctx }; exprsym_t var_syms[] = { {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, - {"framebuffers", &vulkan_framebufferset_t_type, &ctx->framebuffers}, + {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {QFV_PROPERTIES, &cexpr_plitem, &ctx->pipelineDef}, {} diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index ad42daed4..67598dc96 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -153,7 +153,7 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) dlight_t *lights[ALIAS_LIGHTS]; //XXX quat_t fog; - __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = aframe->cmd; DARRAY_APPEND (cframe->subCommand, cmd); @@ -252,7 +252,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); ctx->alias_context = actx; - size_t frames = ctx->framebuffers.size; + size_t frames = ctx->frames.size; DARRAY_INIT (&actx->frames, frames); DARRAY_RESIZE (&actx->frames, frames); actx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 5ae835897..7028aa754 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -838,7 +838,7 @@ bsp_begin (vulkan_ctx_t *ctx) bctx->default_color[3] = 1; QuatCopy (bctx->default_color, bctx->last_color); - __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = bframe->bsp_cmd; DARRAY_APPEND (cframe->subCommand, cmd); @@ -991,7 +991,7 @@ sky_begin (vulkan_ctx_t *ctx) spin (ctx->matrices.sky_3d, bctx); - __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = bframe->sky_cmd; DARRAY_APPEND (cframe->subCommand, cmd); @@ -1443,7 +1443,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&bctx->texture_chains, 64); - size_t frames = ctx->framebuffers.size; + size_t frames = ctx->frames.size; DARRAY_INIT (&bctx->frames, frames); DARRAY_RESIZE (&bctx->frames, frames); bctx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index ff7e6ed15..249ff933e 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -120,7 +120,7 @@ create_quad_buffers (vulkan_ctx_t *ctx) size_t vert_size; size_t ind_size; - size_t frames = ctx->framebuffers.size; + size_t frames = ctx->frames.size; VkBuffer vbuf, ibuf; VkDeviceMemory vmem, imem; @@ -357,7 +357,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) drawctx_t *dctx = calloc (1, sizeof (drawctx_t)); ctx->draw_context = dctx; - size_t frames = ctx->framebuffers.size; + size_t frames = ctx->frames.size; DARRAY_INIT (&dctx->frames, frames); DARRAY_RESIZE (&dctx->frames, frames); dctx->frames.grow = 0; @@ -680,7 +680,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - __auto_type cframe = &ctx->framebuffers.a[ctx->curFrame]; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 21c21b085..54879cdbb 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -168,7 +168,7 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) if (ctx->pipeline) { QFV_DestroyPipeline (ctx->device, ctx->pipeline); } - if (ctx->framebuffers.size) { + if (ctx->frames.size) { Vulkan_DestroyFramebuffers (ctx); } if (ctx->renderpass.colorImage) { @@ -496,18 +496,18 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; VkCommandPool cmdpool = ctx->cmdpool; - if (!ctx->framebuffers.grow) { - DARRAY_INIT (&ctx->framebuffers, 4); + if (!ctx->frames.grow) { + DARRAY_INIT (&ctx->frames, 4); } - DARRAY_RESIZE (&ctx->framebuffers, 3);//FIXME cvar + DARRAY_RESIZE (&ctx->frames, 3);//FIXME cvar - __auto_type cmdBuffers = QFV_AllocCommandBufferSet (ctx->framebuffers.size, + __auto_type cmdBuffers = QFV_AllocCommandBufferSet (ctx->frames.size, alloca); QFV_AllocateCommandBuffers (device, cmdpool, 0, cmdBuffers); - for (size_t i = 0; i < ctx->framebuffers.size; i++) { - __auto_type frame = &ctx->framebuffers.a[i]; + for (size_t i = 0; i < ctx->frames.size; i++) { + __auto_type frame = &ctx->frames.a[i]; frame->framebuffer = 0; frame->fence = QFV_CreateFence (device, 1); frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); @@ -526,13 +526,13 @@ Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) qfv_devfuncs_t *df = device->funcs; VkDevice dev = device->dev; - for (size_t i = 0; i < ctx->framebuffers.size; i++) { - __auto_type frame = &ctx->framebuffers.a[i]; + for (size_t i = 0; i < ctx->frames.size; i++) { + __auto_type frame = &ctx->frames.a[i]; df->vkDestroyFence (dev, frame->fence, 0); df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0); df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); df->vkDestroyFramebuffer (dev, frame->framebuffer, 0); } - DARRAY_CLEAR (&ctx->framebuffers); + DARRAY_CLEAR (&ctx->frames); } From f633a846a123e2f9390e85bab53ee176dac0e9d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Feb 2021 11:06:18 +0900 Subject: [PATCH 1313/3664] [vulkan] Make the frames in flight configurable --- include/QF/Vulkan/cvars.h | 1 + libs/video/renderer/vulkan/vulkan_vid_common.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/QF/Vulkan/cvars.h b/include/QF/Vulkan/cvars.h index 706bc44de..54a34048b 100644 --- a/include/QF/Vulkan/cvars.h +++ b/include/QF/Vulkan/cvars.h @@ -3,5 +3,6 @@ extern struct cvar_s *vulkan_use_validation; extern struct cvar_s *vulkan_presentation_mode; +extern struct cvar_s *vulkan_frame_count; #endif//__QF_Vulkan_cvars_h diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 54879cdbb..4dcda5d86 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -78,6 +78,7 @@ static const char quakeforge_pipeline[] = #include "libs/video/renderer/vulkan/qfpipeline.plc" ; +cvar_t *vulkan_frame_count; cvar_t *vulkan_presentation_mode; cvar_t *msaaSamples; @@ -98,6 +99,15 @@ vulkan_presentation_mode_f (cvar_t *var) } } +static void +vulkan_frame_count_f (cvar_t *var) +{ + if (var->int_val < 1) { + Sys_Printf ("Invalid frame count: %d. Setting to 1\n", var->int_val); + Cvar_Set (var, "1"); + } +} + static void msaaSamples_f (cvar_t *var) { @@ -125,6 +135,12 @@ Vulkan_Init_Cvars (void) CVAR_NONE, vulkan_presentation_mode_f, "desired presentation mode (may fall " "back to fifo)."); + vulkan_frame_count = Cvar_Get ("vulkan_frame_count", "3", CVAR_NONE, + vulkan_frame_count_f, + "Number of frames to render in the" + " background. More frames can increase" + " performance, but at the cost of latency." + " The default of 3 is recommended."); msaaSamples = Cvar_Get ("msaaSamples", "VK_SAMPLE_COUNT_1_BIT", CVAR_NONE, msaaSamples_f, "desired MSAA sample size."); @@ -500,7 +516,7 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) DARRAY_INIT (&ctx->frames, 4); } - DARRAY_RESIZE (&ctx->frames, 3);//FIXME cvar + DARRAY_RESIZE (&ctx->frames, vulkan_frame_count->int_val); __auto_type cmdBuffers = QFV_AllocCommandBufferSet (ctx->frames.size, alloca); From c536a363ecd902634195ff702d7cb2907340e130 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Feb 2021 11:10:43 +0900 Subject: [PATCH 1314/3664] [vulkan] Remove namehack.h Never really wanted in the first place (back when I did the plugin renderers), but I didn't feel like doing the required work to avoid it at the time. At least with Vulkan being a fresh start in an environment that's already plugin-friendly, there was no real work involved. I'll get to the other renderers eventually (especially now that I know gdb does the right thing when there are multiple functions with the same name). --- libs/video/renderer/vid_render_vulkan.c | 5 - libs/video/renderer/vulkan/namehack.h | 135 ------------------- libs/video/renderer/vulkan/vulkan_draw.c | 3 - libs/video/renderer/vulkan/vulkan_lightmap.c | 3 - libs/video/renderer/vulkan/vulkan_main.c | 3 - 5 files changed, 149 deletions(-) delete mode 100644 libs/video/renderer/vulkan/namehack.h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 92e68b0a2..a41a1d960 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -30,9 +30,6 @@ #include -//#define NH_DEFINE -//#include "vulkan/namehack.h" - #include "QF/darray.h" #include "QF/sys.h" @@ -59,8 +56,6 @@ #include "vid_internal.h" #include "vid_vulkan.h" -#include "vulkan/namehack.h" - static vulkan_ctx_t *vulkan_ctx; static tex_t * diff --git a/libs/video/renderer/vulkan/namehack.h b/libs/video/renderer/vulkan/namehack.h deleted file mode 100644 index 17f107080..000000000 --- a/libs/video/renderer/vulkan/namehack.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifdef NH_DEFINE -#undef NH_DEFINE -#define Draw_Init vulkan_Draw_Init -#define Draw_Character vulkan_Draw_Character -#define Draw_String vulkan_Draw_String -#define Draw_nString vulkan_Draw_nString -#define Draw_AltString vulkan_Draw_AltString -#define Draw_ConsoleBackground vulkan_Draw_ConsoleBackground -#define Draw_Crosshair vulkan_Draw_Crosshair -#define Draw_CrosshairAt vulkan_Draw_CrosshairAt -#define Draw_TileClear vulkan_Draw_TileClear -#define Draw_Fill vulkan_Draw_Fill -#define Draw_TextBox vulkan_Draw_TextBox -#define Draw_FadeScreen vulkan_Draw_FadeScreen -#define Draw_BlendScreen vulkan_Draw_BlendScreen -#define Draw_CachePic vulkan_Draw_CachePic -#define Draw_UncachePic vulkan_Draw_UncachePic -#define Draw_MakePic vulkan_Draw_MakePic -#define Draw_DestroyPic vulkan_Draw_DestroyPic -#define Draw_PicFromWad vulkan_Draw_PicFromWad -#define Draw_Pic vulkan_Draw_Pic -#define Draw_Picf vulkan_Draw_Picf -#define Draw_SubPic vulkan_Draw_SubPic -#define Fog_DisableGFog vulkan_Fog_DisableGFog -#define Fog_EnableGFog vulkan_Fog_EnableGFog -#define Fog_GetColor vulkan_Fog_GetColor -#define Fog_GetDensity vulkan_Fog_GetDensity -#define Fog_Init vulkan_Fog_Init -#define Fog_ParseWorldspawn vulkan_Fog_ParseWorldspawn -#define Fog_SetupFrame vulkan_Fog_SetupFrame -#define Fog_StartAdditive vulkan_Fog_StartAdditive -#define Fog_StopAdditive vulkan_Fog_StopAdditive -#define Fog_Update vulkan_Fog_Update -#define R_AddTexture vulkan_R_AddTexture -#define R_BlendLightmaps vulkan_R_BlendLightmaps -#define R_BuildLightMap vulkan_R_BuildLightMap -#define R_CalcLightmaps vulkan_R_CalcLightmaps -#define R_ClearParticles vulkan_R_ClearParticles -#define R_ClearState vulkan_R_ClearState -#define R_ClearTextures vulkan_R_ClearTextures -#define R_DrawAliasModel vulkan_R_DrawAliasModel -#define R_DrawBrushModel vulkan_R_DrawBrushModel -#define R_DrawParticles vulkan_R_DrawParticles -#define R_DrawSky vulkan_R_DrawSky -#define R_DrawSkyChain vulkan_R_DrawSkyChain -#define R_DrawSprite vulkan_R_DrawSprite -#define R_DrawSpriteModel vulkan_R_DrawSpriteModel -#define R_DrawWaterSurfaces vulkan_R_DrawWaterSurfaces -#define R_DrawWorld vulkan_R_DrawWorld -#define R_InitBubble vulkan_R_InitBubble -#define R_InitGraphTextures vulkan_R_InitGraphTextures -#define R_InitParticles vulkan_R_InitParticles -#define R_InitSky vulkan_R_InitSky -#define R_InitSprites vulkan_R_InitSprites -#define R_InitSurfaceChains vulkan_R_InitSurfaceChains -#define R_LineGraph vulkan_R_LineGraph -#define R_LoadSky_f vulkan_R_LoadSky_f -#define R_LoadSkys vulkan_R_LoadSkys -#define R_NewMap vulkan_R_NewMap -#define R_Particle_New vulkan_R_Particle_New -#define R_Particle_NewRandom vulkan_R_Particle_NewRandom -#define R_Particles_Init_Cvars vulkan_R_Particles_Init_Cvars -#define R_ReadPointFile_f vulkan_R_ReadPointFile_f -#define R_RenderDlights vulkan_R_RenderDlights -#define R_RenderView vulkan_R_RenderView -#define R_RotateForEntity vulkan_R_RotateForEntity -#define R_SetupFrame vulkan_R_SetupFrame -#define R_SpriteBegin vulkan_R_SpriteBegin -#define R_SpriteEnd vulkan_R_SpriteEnd -#define R_TimeRefresh_f vulkan_R_TimeRefresh_f -#define R_ViewChanged vulkan_R_ViewChanged -#define SCR_CaptureBGR vulkan_SCR_CaptureBGR -#define SCR_ScreenShot vulkan_SCR_ScreenShot -#define SCR_ScreenShot_f vulkan_SCR_ScreenShot_f -#define c_alias_polys vulkan_c_alias_polys -#define c_brush_polys vulkan_c_brush_polys -#define r_easter_eggs_f vulkan_r_easter_eggs_f -#define r_particles_style_f vulkan_r_particles_style_f -#define r_world_matrix vulkan_r_world_matrix -#else -#undef Fog_DisableGFog -#undef Fog_EnableGFog -#undef Fog_GetColor -#undef Fog_GetDensity -#undef Fog_Init -#undef Fog_ParseWorldspawn -#undef Fog_SetupFrame -#undef Fog_StartAdditive -#undef Fog_StopAdditive -#undef Fog_Update -#undef R_AddTexture -#undef R_BlendLightmaps -#undef R_BuildLightMap -#undef R_CalcLightmaps -#undef R_ClearParticles -#undef R_ClearState -#undef R_ClearTextures -#undef R_DrawAliasModel -#undef R_DrawBrushModel -#undef R_DrawParticles -#undef R_DrawSky -#undef R_DrawSkyChain -#undef R_DrawSpriteModel -#undef R_DrawWaterSurfaces -#undef R_DrawWorld -#undef R_Init -#undef R_InitBubble -#undef R_InitGraphTextures -#undef R_InitParticles -#undef R_InitSky -#undef R_InitSprites -#undef R_InitSurfaceChains -#undef R_LineGraph -#undef R_LoadSky_f -#undef R_LoadSkys -#undef R_NewMap -#undef R_Particle_New -#undef R_Particle_NewRandom -#undef R_Particles_Init_Cvars -#undef R_ReadPointFile_f -#undef R_RenderDlights -#undef R_RenderView -#undef R_RotateForEntity -#undef R_SetupFrame -#undef R_TimeRefresh_f -#undef R_ViewChanged -#undef SCR_CaptureBGR -#undef SCR_ScreenShot -#undef SCR_ScreenShot_f -#undef c_alias_polys -#undef c_brush_polys -#undef r_easter_eggs_f -#undef r_particles_style_f -#undef r_world_matrix -#endif diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 249ff933e..b03cb9e38 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -31,9 +31,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index ca5d433e8..97c30c667 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -30,9 +30,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 8df89eaa1..b4bdc8872 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -31,9 +31,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include "string.h" #endif From f023675f8c205d78c0de6202edf0a8a483406f52 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Feb 2021 16:25:08 +0900 Subject: [PATCH 1315/3664] [vulkan] Clean up draw's memory handling a little Use cmem for pic and cachpic name allocations. If nothing else, it at least keeps memory a little less fragmented. --- libs/video/renderer/vulkan/vulkan_draw.c | 44 ++++++++++++++++-------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index b03cb9e38..93b73d7b3 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -38,6 +38,7 @@ # include #endif +#include "QF/cmem.h" #include "QF/cvar.h" #include "QF/draw.h" #include "QF/dstring.h" @@ -69,7 +70,6 @@ typedef struct { } drawvert_t; typedef struct cachepic_s { - struct cachepic_s *next; char *name; qpic_t *pic; } cachepic_t; @@ -92,6 +92,11 @@ typedef struct drawctx_s { qpic_t *conchars; qpic_t *conback; qpic_t *white_pic; + // use two separate cmem blocks for pics and strings (cachepic names) + // to ensure the names are never in the same cacheline as a pic since the + // names are used only for lookup + memsuper_t *pic_memsuper; + memsuper_t *string_memsuper; hashtab_t *pic_cache; VkBuffer vert_buffer; VkDeviceMemory vert_memory; @@ -211,32 +216,34 @@ flush_draw_scrap (vulkan_ctx_t *ctx) } static void -pic_free (qpic_t *pic) +pic_free (drawctx_t *dctx, qpic_t *pic) { subpic_t *subpic = *(subpic_t **) pic->data; QFV_SubpicDelete (subpic); - free (pic); + cmemfree (dctx->pic_memsuper, pic); } -//FIXME use cmem? static cachepic_t * -new_cachepic (const char *name, qpic_t *pic) +new_cachepic (drawctx_t *dctx, const char *name, qpic_t *pic) { cachepic_t *cp; + size_t size = strlen (name) + 1; - cp = malloc (sizeof (cachepic_t)); - cp->name = strdup (name); + cp = cmemalloc (dctx->pic_memsuper, sizeof (cachepic_t)); + cp->name = cmemalloc (dctx->string_memsuper, size); + memcpy (cp->name, name, size); cp->pic = pic; return cp; } static void -cachepic_free (void *_cp, void *unused) +cachepic_free (void *_cp, void *_dctx) { + drawctx_t *dctx = _dctx; cachepic_t *cp = (cachepic_t *) _cp; - pic_free (cp->pic); - free (cp->name); - free (cp); + pic_free (dctx, cp->pic); + cmemfree (dctx->string_memsuper, cp->name); + cmemfree (dctx->pic_memsuper, cp); } static const char * @@ -252,7 +259,8 @@ pic_data (const char *name, int w, int h, const byte *data, drawctx_t *dctx) subpic_t *subpic; byte *picdata; - pic = malloc (field_offset (qpic_t, data[sizeof (subpic_t)])); + pic = cmemalloc (dctx->pic_memsuper, + field_offset (qpic_t, data[sizeof (subpic_t *)])); pic->width = w; pic->height = h; @@ -292,7 +300,8 @@ Vulkan_Draw_PicFromWad (const char *name, vulkan_ctx_t *ctx) if (!wadpic) { return 0; } - return pic_data (name, wadpic->width, wadpic->height, wadpic->data, ctx->draw_context); + return pic_data (name, wadpic->width, wadpic->height, wadpic->data, + ctx->draw_context); } qpic_t * @@ -313,7 +322,7 @@ Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) pic = pic_data (path, p->width, p->height, p->data, dctx); free (p); - cpic = new_cachepic (path, pic); + cpic = new_cachepic (dctx, path, pic); Hash_Add (dctx->pic_cache, cpic); return pic; } @@ -341,6 +350,9 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) destroy_quad_buffers (ctx); dfunc->vkDestroyPipeline (device->dev, dctx->pipeline, 0); + Hash_DelTable (dctx->pic_cache); + delete_memsuper (dctx->pic_memsuper); + delete_memsuper (dctx->string_memsuper); QFV_DestroyScrap (dctx->scrap); QFV_DestroyStagingBuffer (dctx->stage); } @@ -359,8 +371,10 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&dctx->frames, frames); dctx->frames.grow = 0; + dctx->pic_memsuper = new_memsuper (); + dctx->string_memsuper = new_memsuper (); dctx->pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, - 0, 0); + dctx, 0); create_quad_buffers (ctx); dctx->stage = QFV_CreateStagingBuffer (device, "draw", 4 * 1024 * 1024, From 84dc73da2c0cad9e469610aac169d4120cd44bb6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Feb 2021 21:42:35 +0900 Subject: [PATCH 1316/3664] [test] Get the tests building again They happen to all pass, which is nice :) --- libs/models/test/testclip.c | 5 +++-- libs/models/test/testcontents.c | 4 ++-- libs/models/test/testportals.c | 4 ++-- libs/video/renderer/vulkan/staging.c | 2 +- libs/video/renderer/vulkan/test/test-staging.c | 2 +- tools/qfcc/test/test-harness.c | 4 ++-- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/libs/models/test/testclip.c b/libs/models/test/testclip.c index 6b6672e4b..f0f774c1e 100644 --- a/libs/models/test/testclip.c +++ b/libs/models/test/testclip.c @@ -6,6 +6,7 @@ #include "QF/va.h" #include "getopt.h" +#include "mod_internal.h" #include "world.h" #include "hulls.h" @@ -323,9 +324,9 @@ run_test (test_t *test) err = 1; if (test->desc) - desc = va ("(%d) %s", (int)(long)(test - tests), test->desc); + desc = va (0, "(%d) %s", (int)(long)(test - tests), test->desc); else - desc = va ("test #%d", (int)(long)(test - tests)); + desc = va (0, "test #%d", (int)(long)(test - tests)); if (verbose >= 0 || err) { if (output) puts(""); diff --git a/libs/models/test/testcontents.c b/libs/models/test/testcontents.c index 605ed7a6c..17b20f3ae 100644 --- a/libs/models/test/testcontents.c +++ b/libs/models/test/testcontents.c @@ -145,9 +145,9 @@ run_test (test_t *test) res = 1; if (test->desc) - desc = va ("(%d) %s", (int)(long)(test - tests), test->desc); + desc = va (0, "(%d) %s", (int)(long)(test - tests), test->desc); else - desc = va ("test #%d", (int)(long)(test - tests)); + desc = va (0, "test #%d", (int)(long)(test - tests)); if (verbose >= 0 || !res) { if (output) puts(""); diff --git a/libs/models/test/testportals.c b/libs/models/test/testportals.c index 1cc2f50ec..facfa2914 100644 --- a/libs/models/test/testportals.c +++ b/libs/models/test/testportals.c @@ -170,9 +170,9 @@ nodeleaf_bail: MOD_FreeBrushes (test->hull); if (test->desc) - desc = va ("(%d) %s", (int)(long)(test - tests), test->desc); + desc = va (0, "(%d) %s", (int)(long)(test - tests), test->desc); else - desc = va ("test #%d", (int)(long)(test - tests)); + desc = va (0, "test #%d", (int)(long)(test - tests)); if (verbose >= 0 || err) { if (output) puts(""); diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index cb3bb8ad0..759962c4d 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -56,7 +56,7 @@ #include "vid_vulkan.h" qfv_stagebuf_t * -QFV_CreateStagingBuffer (qfv_device_t *device, const char * name, size_t size, +QFV_CreateStagingBuffer (qfv_device_t *device, const char *name, size_t size, VkCommandPool cmdPool) { size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; diff --git a/libs/video/renderer/vulkan/test/test-staging.c b/libs/video/renderer/vulkan/test/test-staging.c index 020af9ab2..fcfa4b8a9 100644 --- a/libs/video/renderer/vulkan/test/test-staging.c +++ b/libs/video/renderer/vulkan/test/test-staging.c @@ -179,7 +179,7 @@ _error (int line, const char *fmt, ...) int main (void) { - qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (&device, 1024, 0); + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (&device, "", 1024, 0); if (stage->size != 1024) { error ("stage has incorrect size: %zd", stage->size); diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 69de8c47b..822df9f41 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -104,7 +104,7 @@ load_file (progs_t *pr, const char *name, off_t *_size) file = open_file (name, &size); if (!file) { - file = open_file (va ("%s.gz", name), &size); + file = open_file (va (0, "%s.gz", name), &size); if (!file) { return 0; } @@ -132,7 +132,7 @@ static void init_qf (void) { Sys_Init (); - Cvar_Get ("developer", va ("%d", options.developer), 0, 0, 0); + Cvar_Get ("developer", va (0, "%d", options.developer), 0, 0, 0); Memory_Init (Sys_Alloc (1024 * 1024), 1024 * 1024); From dfa7af03c6d4b96c3e2339bf23a695f5d97203cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 09:57:07 +0900 Subject: [PATCH 1317/3664] [util] Plug a thread-safety hole in plists --- include/QF/progs.h | 4 +++- include/QF/qfplist.h | 11 +++++++++-- libs/audio/cd_file.c | 2 +- libs/gamecode/pr_parse.c | 12 ++++++------ libs/ruamoko/rua_plist.c | 7 ++++--- libs/util/qfplist.c | 12 +++++++----- libs/util/quakefs.c | 4 ++-- libs/video/renderer/vulkan/vulkan_vid_common.c | 3 ++- nq/source/host_cmd.c | 8 ++++---- tools/qflight/source/entities.c | 4 ++-- tools/qflight/source/properties.c | 2 +- 11 files changed, 41 insertions(+), 28 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 64a9d20bb..89fa5d181 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -298,13 +298,15 @@ void ED_PrintNum (progs_t *pr, pr_int_t ent); // pr_parse.c struct script_s; struct plitem_s; +struct hashlink_s; qboolean ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s); struct plitem_s *ED_EntityDict (progs_t *pr, edict_t *ed); struct plitem_s *ED_GlobalsDict (progs_t *pr); void ED_InitGlobals (progs_t *pr, struct plitem_s *globals); void ED_InitEntity (progs_t *pr, struct plitem_s *entity, edict_t *ent); -struct plitem_s *ED_ConvertToPlist (struct script_s *script, int nohack); +struct plitem_s *ED_ConvertToPlist (struct script_s *script, int nohack, + struct hashlink_s **hashlinks); struct plitem_s *ED_Parse (progs_t *pr, const char *data); void ED_LoadFromFile (progs_t *pr, const char *data); void ED_EntityParseFunction (progs_t *pr); diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 8f8db669f..5de86d05f 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -28,6 +28,8 @@ #ifndef __QF_qfplist_h #define __QF_qfplist_h +struct hashlink_s; + /** \defgroup qfplist Property lists \ingroup utils */ @@ -115,11 +117,14 @@ typedef struct plelement_s { /** Create an in-memory representation of the contents of a property list. \param string the saved plist, as read from a file. + \param hashlinks Hashlink chain to use when creating dictionaries (see + Hash_NewTable()). May be null. \return Returns an object equivalent to the passed-in string. \note You are responsible for freeing the returned object. */ -plitem_t *PL_GetPropertyList (const char *string); +plitem_t *PL_GetPropertyList (const char *string, + struct hashlink_s **hashlinks); /** Create a property list string from the in-memory representation. @@ -275,9 +280,11 @@ plitem_t *PL_RemoveObjectAtIndex (plitem_t *array, int index); /** Create a new dictionary object. The dictionary will be empty. + \param hashlinks Hashlink chain to use when creating dictionaries (see + Hash_NewTable()). May be null. \return the new dictionary object */ -plitem_t *PL_NewDictionary (void); +plitem_t *PL_NewDictionary (struct hashlink_s **hashlinks); /** Create a new array object. The array will be empty. diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index ef9979bd9..5ffe88290 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -172,7 +172,7 @@ Load_Tracklist (void) buffile = calloc (size+10, sizeof (char)); Qread (oggfile, buffile, size); - tracklist = PL_GetPropertyList (buffile); + tracklist = PL_GetPropertyList (buffile, 0); if (!tracklist || PL_Type (tracklist) != QFDictionary) { Sys_Printf ("Malformed or empty tracklist file. check mus_ogglist\n"); return -1; diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 6471a44bb..0f0a3dea5 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -109,7 +109,7 @@ VISIBLE plitem_t * ED_EntityDict (progs_t *pr, edict_t *ed) { dstring_t *dstr = dstring_newstr (); - plitem_t *entity = PL_NewDictionary (); + plitem_t *entity = PL_NewDictionary (pr->hashlink_freelist); pr_uint_t i; int j; int type; @@ -155,7 +155,7 @@ VISIBLE plitem_t * ED_GlobalsDict (progs_t *pr) { dstring_t *dstr = dstring_newstr (); - plitem_t *globals = PL_NewDictionary (); + plitem_t *globals = PL_NewDictionary (pr->hashlink_freelist); pr_uint_t i; const char *name; const char *value; @@ -290,7 +290,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) */ VISIBLE plitem_t * -ED_ConvertToPlist (script_t *script, int nohack) +ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks) { dstring_t *dstr = dstring_newstr (); plitem_t *plist = PL_NewArray (); @@ -304,7 +304,7 @@ ED_ConvertToPlist (script_t *script, int nohack) token = script->token->str; if (!strequal (token, "{")) Sys_Error ("ED_ConvertToPlist: EOF without closing brace"); - ent = PL_NewDictionary (); + ent = PL_NewDictionary (hashlinks); while (1) { int n; @@ -499,11 +499,11 @@ ED_Parse (progs_t *pr, const char *data) if (Script_GetToken (script, 1)) { if (strequal (script->token->str, "(")) { // new style (plist) entity data - entity_list = PL_GetPropertyList (data); + entity_list = PL_GetPropertyList (data, pr->hashlink_freelist); } else { // oldstyle entity data Script_UngetToken (script); - entity_list = ED_ConvertToPlist (script, 0); + entity_list = ED_ConvertToPlist (script, 0, pr->hashlink_freelist); } } Script_Delete (script); diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index d45ee1b8d..ce5030e5c 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -195,7 +195,7 @@ bi_PL_GetFromFile (progs_t *pr) Qread (file, buf, len); buf[len] = 0; - plitem = PL_GetPropertyList (buf); + plitem = PL_GetPropertyList (buf, pr->hashlink_freelist); R_INT (pr) = plist_retain (res, plitem); } @@ -204,7 +204,8 @@ static void bi_PL_GetPropertyList (progs_t *pr) { plist_resources_t *res = PR_Resources_Find (pr, "plist"); - plitem_t *plitem = PL_GetPropertyList (P_GSTRING (pr, 0)); + plitem_t *plitem = PL_GetPropertyList (P_GSTRING (pr, 0), + pr->hashlink_freelist); R_INT (pr) = plist_retain (res, plitem); } @@ -373,7 +374,7 @@ static void bi_PL_NewDictionary (progs_t *pr) { plist_resources_t *res = PR_Resources_Find (pr, "plist"); - plitem_t *plitem = PL_NewDictionary (); + plitem_t *plitem = PL_NewDictionary (pr->hashlink_freelist); R_INT (pr) = plist_retain (res, plitem); } diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index f36b6552e..9d4a7b2bf 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -91,6 +91,7 @@ typedef struct pldata_s { // Unparsed property list string unsigned line; plitem_t *error; va_ctx_t *va_ctx; + hashlink_t **hashlinks; } pldata_t; // Ugly defines for fast checking and conversion from char to number @@ -157,11 +158,11 @@ PL_NewItem (pltype_t type) } VISIBLE plitem_t * -PL_NewDictionary (void) +PL_NewDictionary (hashlink_t **hashlinks) { plitem_t *item = PL_NewItem (QFDictionary); - //FIXME need a per-thread hashlink freelist for plist to be thread-safe - hashtab_t *dict = Hash_NewTable (1021, dict_get_key, dict_free, NULL, 0); + hashtab_t *dict = Hash_NewTable (1021, dict_get_key, dict_free, NULL, + hashlinks); item->data = dict; return item; } @@ -722,7 +723,7 @@ PL_ParsePropertyListItem (pldata_t *pl) switch (pl->ptr[pl->pos]) { case '{': { - item = PL_NewDictionary (); + item = PL_NewDictionary (pl->hashlinks); item->line = pl->line; pl->pos++; @@ -880,7 +881,7 @@ PL_ParsePropertyListItem (pldata_t *pl) } VISIBLE plitem_t * -PL_GetPropertyList (const char *string) +PL_GetPropertyList (const char *string, hashlink_t **hashlinks) { pldata_t *pl = calloc (1, sizeof (pldata_t)); plitem_t *newpl = NULL; @@ -894,6 +895,7 @@ PL_GetPropertyList (const char *string) pl->error = NULL; pl->line = 1; pl->va_ctx = va_create_context (4); + pl->hashlinks = hashlinks; if ((newpl = PL_ParsePropertyListItem (pl))) { va_destroy_context (pl->va_ctx); diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 683378904..569fab341 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -672,7 +672,7 @@ qfs_load_config (void) buf[len + 2] = 0; if (qfs_gd_plist) PL_Free (qfs_gd_plist); - qfs_gd_plist = PL_GetPropertyList (buf); + qfs_gd_plist = PL_GetPropertyList (buf, 0); free (buf); if (qfs_gd_plist && PL_Type (qfs_gd_plist) == QFDictionary) return; // done @@ -680,7 +680,7 @@ qfs_load_config (void) no_config: if (qfs_gd_plist) PL_Free (qfs_gd_plist); - qfs_gd_plist = PL_GetPropertyList (qfs_default_dirconf); + qfs_gd_plist = PL_GetPropertyList (qfs_default_dirconf, 0); } /* diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 4dcda5d86..0132bf6d0 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -244,7 +244,8 @@ static plitem_t * qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) { if (!ctx->pipelineDef) { - ctx->pipelineDef = PL_GetPropertyList (quakeforge_pipeline); + ctx->pipelineDef = PL_GetPropertyList (quakeforge_pipeline, + &ctx->hashlinks); } plitem_t *item = ctx->pipelineDef; diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 76529838e..c7e138f23 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -434,7 +434,7 @@ entities_array (void) static plitem_t * game_dict (void) { - plitem_t *game = PL_NewDictionary (); + plitem_t *game = PL_NewDictionary (0); PL_D_AddObject (game, "comment", PL_NewString (va (0, "%-21s kills:%3i/%3i", cl.levelname, @@ -455,7 +455,7 @@ game_dict (void) static plitem_t * convert_to_game_dict (script_t *script) { - plitem_t *game = PL_NewDictionary (); + plitem_t *game = PL_NewDictionary (0); plitem_t *item; plitem_t *list; int skill; @@ -500,7 +500,7 @@ convert_to_game_dict (script_t *script) PL_D_AddObject (game, "lightstyles", item); // load the edicts out of the savegame file - list = ED_ConvertToPlist (script, 0); + list = ED_ConvertToPlist (script, 0, 0); item = PL_RemoveObjectAtIndex (list, 0); PL_D_AddObject (game, "globals", item); PL_D_AddObject (game, "entities", list); @@ -647,7 +647,7 @@ Host_Loadgame_f (void) Sys_Printf ("Unexpected EOF reading %s\n", name->str); goto end; } - game = PL_GetPropertyList (script->p); + game = PL_GetPropertyList (script->p, 0); } else { sscanf (script->token->str, "%i", &version); if (version != SAVEGAME_VERSION) { diff --git a/tools/qflight/source/entities.c b/tools/qflight/source/entities.c index 1383004df..d3c608f6f 100644 --- a/tools/qflight/source/entities.c +++ b/tools/qflight/source/entities.c @@ -179,7 +179,7 @@ LoadEntities (void) script = Script_New (); Script_Start (script, "ent data", bsp->entdata); - entity_list = ED_ConvertToPlist (script, 1); + entity_list = ED_ConvertToPlist (script, 1, 0); Script_Delete (script); // start parsing @@ -208,7 +208,7 @@ LoadEntities (void) } entity->dict = PL_ObjectAtIndex (entity_list, i); - dict = PL_NewDictionary (); + dict = PL_NewDictionary (0); // go through all the keys in this entity keys = PL_D_AllKeys (entity->dict); diff --git a/tools/qflight/source/properties.c b/tools/qflight/source/properties.c index e7774f6d4..c9297984b 100644 --- a/tools/qflight/source/properties.c +++ b/tools/qflight/source/properties.c @@ -334,6 +334,6 @@ LoadProperties (const char *filename) Qread (f, buf, len); Qclose (f); buf[len] = 0; - properties = PL_GetPropertyList (buf); + properties = PL_GetPropertyList (buf, 0); free (buf); } From 8664a5b969a8f9f78a22bab9c55d9d38210f43a1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 10:02:04 +0900 Subject: [PATCH 1318/3664] [util] Enable parser debugging for cexpr Not actually turned on in the code, but cexpr_yydebug is present. --- libs/util/cexpr-lex.l | 2 ++ libs/util/cexpr-parse.y | 1 + 2 files changed, 3 insertions(+) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index d34cd250a..46fbcdd55 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -50,6 +50,8 @@ #include "QF/qfplist.h" #include "QF/sys.h" +#define CEXPR_YYDEBUG 1 + #include "QF/cexpr.h" #include "libs/util/cexpr-parse.h" diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index 07993af9b..599955afd 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -27,6 +27,7 @@ %define api.prefix {cexpr_yy} %define api.pure full %define api.push-pull push +%define parse.trace %parse-param {void *scanner} {exprctx_t *context} %{ From fdba8228099c2a547c530228b9861e31f80d8a45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 14:43:45 +0900 Subject: [PATCH 1319/3664] [util] Fix a code-comment disagreement And the comment was correct :P --- include/QF/darray.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/darray.h b/include/QF/darray.h index 2b8689726..f79403283 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -121,9 +121,9 @@ #define DARRAY_CLEAR(array) \ do { \ __auto_type ar = (array); \ - free (ar->a); \ ar->size = 0; \ if (ar->grow) { \ + free (ar->a); \ ar->maxSize = 0; \ ar->a = 0; \ } \ From c8afbdf0f5a0f1e07ebfdb8fa8bb62f3e83137e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 14:56:11 +0900 Subject: [PATCH 1320/3664] [util] Add an object-based fixed array allocator --- include/QF/darray.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/include/QF/darray.h b/include/QF/darray.h index f79403283..50dc6c348 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -88,6 +88,30 @@ ar; \ }) +/** Allocate a fixed-size array using the given allocator + + The allocated array is initilized to be ungrowable, and with both size + and maxSize set to the given size. + + \param array_type Expression acceptable by typeof for determining the + type of the array. + \param array_size The size of the array. + \param alloc Allocator taking (obj, size) where obj is allocator + specific data (eg, a memory pool). + \param data Additional data for the allocator. +*/ +#define DARRAY_ALLOCFIXED_OBJ(array_type, array_size, alloc, obj) \ + ({ \ + __auto_type s = (array_size); \ + typeof (array_type) *ar = alloc ((obj), \ + sizeof(*ar) \ + + s * sizeof (*ar->a)); \ + ar->size = ar->maxSize = s; \ + ar->grow = 0; \ + ar->a = (typeof (ar->a)) (ar + 1); \ + ar; \ + }) + /** Initialized the array. The array will be initialized to be empty but with grow set to the From a408fd40daacb4b15cfc2ee7d67defde3951c199 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 14:56:48 +0900 Subject: [PATCH 1321/3664] [util] Make plist more const-correct --- include/QF/qfplist.h | 8 ++++---- libs/util/qfplist.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 5de86d05f..89cb00a85 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -185,7 +185,7 @@ const char *PL_String (const plitem_t *string) __attribute__((pure)); \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ -plitem_t *PL_ObjectForKey (plitem_t *dict, const char *key); +plitem_t *PL_ObjectForKey (const plitem_t *dict, const char *key); /** Remove a value from a dictionary object. @@ -195,7 +195,7 @@ plitem_t *PL_ObjectForKey (plitem_t *dict, const char *key); isn't a dictionary. \note You are responsible for freeing the returned object. */ -plitem_t *PL_RemoveObjectForKey (plitem_t *dict, const char *key); +plitem_t *PL_RemoveObjectForKey (const plitem_t *dict, const char *key); /** Retrieve a value from an array object. @@ -206,7 +206,7 @@ plitem_t *PL_RemoveObjectForKey (plitem_t *dict, const char *key); \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ -plitem_t *PL_ObjectAtIndex (plitem_t *array, int index) __attribute__((pure)); +plitem_t *PL_ObjectAtIndex (const plitem_t *array, int index) __attribute__((pure)); /** Retrieve a list of all keys in a dictionary. @@ -222,7 +222,7 @@ plitem_t *PL_D_AllKeys (plitem_t *dict); \return Returns the number of keys in the dictionary. */ -int PL_D_NumKeys (plitem_t *dict) __attribute__((pure)); +int PL_D_NumKeys (const plitem_t *dict) __attribute__((pure)); /** Add a key/value pair to a dictionary. diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 9d4a7b2bf..b40fec69a 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -264,7 +264,7 @@ PL_String (const plitem_t *string) } VISIBLE plitem_t * -PL_ObjectForKey (plitem_t *dict, const char *key) +PL_ObjectForKey (const plitem_t *dict, const char *key) { hashtab_t *table = (hashtab_t *) dict->data; dictkey_t *k; @@ -277,7 +277,7 @@ PL_ObjectForKey (plitem_t *dict, const char *key) } VISIBLE plitem_t * -PL_RemoveObjectForKey (plitem_t *dict, const char *key) +PL_RemoveObjectForKey (const plitem_t *dict, const char *key) { hashtab_t *table = (hashtab_t *) dict->data; dictkey_t *k; @@ -320,7 +320,7 @@ PL_D_AllKeys (plitem_t *dict) } VISIBLE int -PL_D_NumKeys (plitem_t *dict) +PL_D_NumKeys (const plitem_t *dict) { if (dict->type != QFDictionary) return 0; @@ -328,7 +328,7 @@ PL_D_NumKeys (plitem_t *dict) } VISIBLE plitem_t * -PL_ObjectAtIndex (plitem_t *array, int index) +PL_ObjectAtIndex (const plitem_t *array, int index) { plarray_t *arr = (plarray_t *) array->data; From 14e4fd9f6a4a8403bead6e1c3dd62a7ea97039ae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 15:01:55 +0900 Subject: [PATCH 1322/3664] [util] Pass context to the plist array/symtab parser allocator --- include/QF/qfplist.h | 10 +++++----- libs/util/qfplist.c | 8 ++++---- libs/video/renderer/vulkan/vkparse.c | 14 ++++++++++---- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 89cb00a85..67eb68588 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -109,7 +109,7 @@ typedef struct plfield_s { typedef struct plelement_s { pltype_t type; ///< the required type of the array elements size_t stride; ///< the size of each element - void *(*alloc) (size_t size); ///< allocator for array memory + void *(*alloc) (void *ctx, size_t size);///< allocator for array memory plparser_t parser; ///< custom parser function void *data; ///< additional data for \a parser } plelement_t; @@ -360,7 +360,7 @@ void PL_TypeMismatch (plitem_t *messages, const plitem_t *item, int PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, void *data, plitem_t *messages, void *context); -/** Parse an array object into a dynamic arrah (see darray.h). +/** Parse an array object into a dynamic array (see darray.h). For each object in the array, the field item is used to determine how to parse the object. If the array is empty, the destination will be @@ -378,7 +378,7 @@ int PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, \param array The array object to parse \param data Pointer to the pointer to which the dynamic array will be written. The dynamic array is allocated using - DARRAY_ALLOCFIXED(). + DARRAY_ALLOCFIXED_OBJ(). \param messages Array object supplied by the caller used for storing messages. The messages may or may not indicate errors (its contents are not checked). This function itself will add @@ -390,7 +390,7 @@ int PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, message format is "[line number]: [message]". If the line number is 0, then the actual line is unknown (due to the source item not being parsed from a file or string). - \param context Additional context data passed to the parser. + \param context Additional context data passed to the parser and allocator. \return 0 if there are any errors, 1 if there are no errors. */ int PL_ParseArray (const plfield_t *field, const plitem_t *array, @@ -438,7 +438,7 @@ int PL_ParseArray (const plfield_t *field, const plitem_t *array, message format is "[line number]: [message]". If the line number is 0, then the actual line is unknown (due to the source item not being parsed from a file or string). - \param context Additional context data passed to the parser. + \param context Additional context data passed to the parser and allocator. \return 0 if there are any errors, 1 if there are no errors. */ int PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index b40fec69a..4b7e34e7a 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1272,8 +1272,8 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, parser = pl_default_parser; } - arr = DARRAY_ALLOCFIXED (arr_t, plarray->numvals * element->stride, - element->alloc); + arr = DARRAY_ALLOCFIXED_OBJ (arr_t, plarray->numvals * element->stride, + element->alloc, context); memset (arr->a, 0, arr->size); // the array is allocated using bytes, but need the actual number of // elements in the array @@ -1329,7 +1329,7 @@ PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, return 1; } - void *obj = element->alloc (element->stride); + void *obj = element->alloc (context, element->stride); memset (obj, 0, element->stride); while ((current = (dictkey_t *) *l++)) { const char *key = current->key; @@ -1349,7 +1349,7 @@ PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, result = 0; } else { Hash_Add (tab, obj); - obj = element->alloc (element->stride); + obj = element->alloc (context, element->stride); memset (obj, 0, element->stride); } } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 7e336a167..3f02b8022 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -259,6 +259,12 @@ parse_single (const plfield_t *field, const plitem_t *item, return 1; } +static void * +array_alloc (void *context, size_t size) +{ + return malloc (size); +} + static int parse_array (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -270,7 +276,7 @@ parse_array (const plfield_t *field, const plitem_t *item, plelement_t element = { array->type, array->stride, - malloc, + array_alloc, array->parser, 0, }; @@ -630,7 +636,7 @@ typedef struct qfv_renderpass_s { static plelement_t parse_qfv_renderpass_attachments_data = { QFDictionary, sizeof (VkAttachmentDescription), - malloc, + array_alloc, parse_VkAttachmentDescription, 0, }; @@ -638,7 +644,7 @@ static plelement_t parse_qfv_renderpass_attachments_data = { static plelement_t parse_qfv_renderpass_subpasses_data = { QFDictionary, sizeof (VkSubpassDescription), - malloc, + array_alloc, parse_VkSubpassDescription, 0, }; @@ -646,7 +652,7 @@ static plelement_t parse_qfv_renderpass_subpasses_data = { static plelement_t parse_qfv_renderpass_dependencies_data = { QFDictionary, sizeof (VkSubpassDependency), - malloc, + array_alloc, parse_VkSubpassDependency, 0, }; From bc763da9f696ac020358925216ed0d52f0b4777f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 15:02:22 +0900 Subject: [PATCH 1323/3664] [qfcc] Fix a typo in the man page --- tools/qfcc/doc/man/qfcc.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index 4105eaa1d..045aa8963 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -100,7 +100,7 @@ For each source file (listed either on the command line, or in \fBprogs.src\fP, write a file whose name is the base name of the source file with an extension of \fB.frame\fP, and contains a list of frame macro names with their associated frame numbers. Eg, \fBplayer.qc\fP will produce -\fBplayer.frame\fPa. Note that files that do not create frame macros will +\fBplayer.frame\fP. Note that files that do not create frame macros will not generate a frame file. At this time, the file is always written to the current directory. From 0dcd946063e1b602c4b30850feab0407094c2e85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 15:24:28 +0900 Subject: [PATCH 1324/3664] [util] Add plist parser for dictionary -> array PL_ParseLabeledArray works the same way as PL_ParseArray, but instead takes a dictionary object. The keys of the items are ignored, and the order is not preserved (at this stage), but this is a cleaner solution to getting an array of objects when the definitions of those objects need to be accessible by name as well. --- include/QF/qfplist.h | 39 +++++++++++++++++++++++++++ libs/util/qfplist.c | 63 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 67eb68588..3e1086be0 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -396,6 +396,45 @@ int PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, int PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, plitem_t *messages, void *context); +/** Parse a dictionary object into a dynamic array (see darray.h). + + This is useful when the dictionary object is meant to be a labeled list + rather than a representation of a structure. + + For each object in the array, the field item is used to determine how to + parse the object. If the array is empty, the destination will be + initialized to an empty array. + + When an error occurs (incorrect item type (item type does not match the + type specified in the element object) or the element object's \a parser + returns 0), processing continues but the error result is returned. + + Can be used recursively to parse deep hierarchies. + + \param field Pointer to a single field that has the field data pointer + set to reference a plelement_t object used to describe + the contents of the array. + \param dict The dict object to parse + \param data Pointer to the pointer to which the dynamic array will + be written. The dynamic array is allocated using + DARRAY_ALLOCFIXED_OBJ(). + \param messages Array object supplied by the caller used for storing + messages. The messages may or may not indicate errors (its + contents are not checked). This function itself will add + only string objects. + If there are any errors, suitable messages will be found in + the \a messages object. However, just because there are no + errors doesn't mean that \a messages will remain empty as + a field's \a parser may add other messages. The standard + message format is "[line number]: [message]". If the line + number is 0, then the actual line is unknown (due to the + source item not being parsed from a file or string). + \param context Additional context data passed to the parser and allocator. + \return 0 if there are any errors, 1 if there are no errors. +*/ +int PL_ParseLabeledArray (const plfield_t *field, const plitem_t *dict, + void *data, plitem_t *messages, void *context); + /** Parse a dictionary object into a hash table. For each key in the dictionary, the element object is used to determine diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 4b7e34e7a..6bee78c3f 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -1211,10 +1211,7 @@ PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, void *data, return 0; } - if (!(l = list = Hash_GetList ((hashtab_t *) dict->data))) { - // empty struct: leave as default - return 1; - } + l = list = Hash_GetList ((hashtab_t *) dict->data); while ((current = (dictkey_t *) *l++)) { const plfield_t *f; @@ -1299,6 +1296,64 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, return result; } +VISIBLE int +PL_ParseLabeledArray (const plfield_t *field, const plitem_t *dict, + void *data, plitem_t *messages, void *context) +{ + void **list, **l; + dictkey_t *current; + int result = 1; + plparser_t parser; + plelement_t *element = (plelement_t *) field->data; + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr; + plfield_t f = { 0, 0, element->type, element->parser, element->data }; + + if (dict->type != QFDictionary) { + PL_Message (messages, dict, "error: not a dictionary object"); + return 0; + } + if (f.parser) { + parser = f.parser; + } else { + parser = pl_default_parser; + } + + list = Hash_GetList ((hashtab_t *) dict->data); + + int numvals = 0; + for (l = list; *l; l++) { + numvals++; + } + + arr = DARRAY_ALLOCFIXED_OBJ (arr_t, numvals * element->stride, + element->alloc, context); + memset (arr->a, 0, arr->size); + // the array is allocated using bytes, but need the actual number of + // elements in the array + arr->size = arr->maxSize = numvals; + + for (int i = 0; i < numvals; i++) { + current = list[i]; + plitem_t *item = current->value; + void *eledata = &arr->a[i * element->stride]; + + if (!PL_CheckType (element->type, item->type)) { + char index[16]; + snprintf (index, sizeof(index) - 1, "%d", i); + index[15] = 0; + PL_TypeMismatch (messages, item, index, element->type, item->type); + result = 0; + } else { + if (!parser (&f, item, eledata, messages, context)) { + result = 0; + } + } + } + *(arr_t **) data = arr; + return result; +} + VISIBLE int PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, plitem_t *messages, void *context) From 5535d1f8e6f32cc7817dce3c2b624ea90ff8eeb1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 16:53:21 +0900 Subject: [PATCH 1325/3664] [util] Keep track of plist dictionary key order The order in which keys are added to the dictionary object is maintained. Adding a key after removing an old key adds the new key to the end of the list rather than reusing the old key's spot. --- include/QF/qfplist.h | 16 +++- libs/util/qfplist.c | 169 ++++++++++++++++++++++++------------------- 2 files changed, 109 insertions(+), 76 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index 3e1086be0..f1cc95b8a 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -197,12 +197,24 @@ plitem_t *PL_ObjectForKey (const plitem_t *dict, const char *key); */ plitem_t *PL_RemoveObjectForKey (const plitem_t *dict, const char *key); +/** Retrieve a key from a dictionary object. + + \param dict The dictionary to get the key from + \param index The index of the key + \return the key at the specified index, or NULL if index is out of range or + dict is not a dictionaly + isn't an array. + \note You are NOT responsible for freeing the returned object. It will + be destroyed when its container is. +*/ +const char *PL_KeyAtIndex (const plitem_t *array, int index) __attribute__((pure)); + /** Retrieve a value from an array object. \param array The array to get the value from \param index The index within the array to retrieve - \return the value associated with the key, or NULL if not found or array - isn't an array. + \return the value at the specified index, or NULL if index is out of range + or array is not an array. \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 6bee78c3f..6e4726c95 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -64,6 +64,12 @@ struct dictkey_s { }; typedef struct dictkey_s dictkey_t; +struct pldict_s { + hashtab_t *tab; + struct DARRAY_TYPE (dictkey_t *) keys; +}; +typedef struct pldict_s pldict_t; + /* Arrays */ @@ -161,8 +167,9 @@ VISIBLE plitem_t * PL_NewDictionary (hashlink_t **hashlinks) { plitem_t *item = PL_NewItem (QFDictionary); - hashtab_t *dict = Hash_NewTable (1021, dict_get_key, dict_free, NULL, - hashlinks); + pldict_t *dict = malloc (sizeof (pldict_t)); + dict->tab = Hash_NewTable (1021, dict_get_key, dict_free, NULL, hashlinks); + DARRAY_INIT (&dict->keys, 8); item->data = dict; return item; } @@ -205,18 +212,25 @@ PL_NewString (const char *str) VISIBLE void PL_Free (plitem_t *item) { + pldict_t *dict; + plarray_t *array; + switch (item->type) { case QFDictionary: - Hash_DelTable (item->data); + dict = item->data; + Hash_DelTable (dict->tab); + DARRAY_CLEAR (&dict->keys); break; - case QFArray: { - int i = ((plarray_t *) item->data)->numvals; + case QFArray: + { + array = item->data; + int i = array->numvals; while (i-- > 0) { - PL_Free (((plarray_t *) item->data)->values[i]); + PL_Free (array->values[i]); } - free (((plarray_t *) item->data)->values); + free (array->values); free (item->data); } break; @@ -264,67 +278,85 @@ PL_String (const plitem_t *string) } VISIBLE plitem_t * -PL_ObjectForKey (const plitem_t *dict, const char *key) +PL_ObjectForKey (const plitem_t *item, const char *key) { - hashtab_t *table = (hashtab_t *) dict->data; + pldict_t *dict = (pldict_t *) item->data; dictkey_t *k; - if (dict->type != QFDictionary) + if (item->type != QFDictionary) return NULL; - k = (dictkey_t *) Hash_Find (table, key); + k = (dictkey_t *) Hash_Find (dict->tab, key); return k ? k->value : NULL; } -VISIBLE plitem_t * -PL_RemoveObjectForKey (const plitem_t *dict, const char *key) +VISIBLE const char * +PL_KeyAtIndex (const plitem_t *item, int index) { - hashtab_t *table = (hashtab_t *) dict->data; + pldict_t *dict = (pldict_t *) item->data; + + if (item->type != QFDictionary) + return NULL; + if (index < 0 || (size_t) index >= dict->keys.size) { + return NULL; + } + + return dict->keys.a[index]->key; +} + +VISIBLE plitem_t * +PL_RemoveObjectForKey (const plitem_t *item, const char *key) +{ + pldict_t *dict = (pldict_t *) item->data; dictkey_t *k; plitem_t *value; - if (dict->type != QFDictionary) + if (item->type != QFDictionary) return NULL; - k = (dictkey_t *) Hash_Del (table, key); + k = (dictkey_t *) Hash_Del (dict->tab, key); if (!k) return NULL; value = k->value; k->value = 0; + for (size_t i = 0; i < dict->keys.size; i++) { + if (dict->keys.a[i] == k) { + DARRAY_REMOVE_AT (&dict->keys, i); + break; + } + } dict_free (k, 0); return value; } VISIBLE plitem_t * -PL_D_AllKeys (plitem_t *dict) +PL_D_AllKeys (plitem_t *item) { - void **list, **l; - dictkey_t *current; - plitem_t *array; + pldict_t *dict = (pldict_t *) item->data; + dictkey_t *current; + plitem_t *array; - if (dict->type != QFDictionary) - return NULL; - - if (!(l = list = Hash_GetList ((hashtab_t *) dict->data))) + if (item->type != QFDictionary) return NULL; if (!(array = PL_NewArray ())) return NULL; - while ((current = (dictkey_t *) *l++)) { + for (size_t i = 0; i < dict->keys.size; i++) { + current = dict->keys.a[i]; PL_A_AddObject (array, PL_NewString (current->key)); } - free (list); return array; } VISIBLE int -PL_D_NumKeys (const plitem_t *dict) +PL_D_NumKeys (const plitem_t *item) { - if (dict->type != QFDictionary) + pldict_t *dict = (pldict_t *) item->data; + if (item->type != QFDictionary) return 0; - return Hash_NumElements ((hashtab_t *) dict->data); + return Hash_NumElements (dict->tab); } VISIBLE plitem_t * @@ -339,14 +371,15 @@ PL_ObjectAtIndex (const plitem_t *array, int index) } VISIBLE qboolean -PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value) +PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) { + pldict_t *dict = (pldict_t *) item->data; dictkey_t *k; - if (dict->type != QFDictionary) + if (item->type != QFDictionary) return false; - if ((k = Hash_Find ((hashtab_t *)dict->data, key))) { + if ((k = Hash_Find (dict->tab, key))) { PL_Free ((plitem_t *) k->value); k->value = value; } else { @@ -358,7 +391,8 @@ PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value) k->key = strdup (key); k->value = value; - Hash_Add ((hashtab_t *)dict->data, k); + Hash_Add (dict->tab, k); + DARRAY_APPEND (&dict->keys, k); } return true; } @@ -1024,24 +1058,24 @@ write_string (dstring_t *dstr, const char *str) static void write_item (dstring_t *dstr, plitem_t *item, int level) { - void **list, **l; dictkey_t *current; plarray_t *array; + pldict_t *dict; plbinary_t *binary; int i; switch (item->type) { case QFDictionary: write_string_len (dstr, "{\n", 2); - l = list = Hash_GetList ((hashtab_t *) item->data); - while ((current = (dictkey_t *) *l++)) { + dict = (pldict_t *) item->data; + for (size_t i = 0; i < dict->keys.size; i++) { + current = dict->keys.a[i]; write_tabs (dstr, level + 1); write_string (dstr, current->key); write_string_len (dstr, " = ", 3); write_item (dstr, current->value, level + 1); write_string_len (dstr, ";\n", 2); } - free (list); write_tabs (dstr, level); write_string_len (dstr, "}", 1); break; @@ -1128,7 +1162,7 @@ pl_default_parser (const plfield_t *field, const plitem_t *item, void *data, switch (field->type) { case QFDictionary: { - *(hashtab_t **)data = (hashtab_t *)item->data; + *(hashtab_t **)data = ((pldict_t *)item->data)->tab; } return 1; case QFArray: @@ -1198,23 +1232,23 @@ PL_TypeMismatch (plitem_t *messages, const plitem_t *item, const char *name, } VISIBLE int -PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, void *data, +PL_ParseStruct (const plfield_t *fields, const plitem_t *item, void *data, plitem_t *messages, void *context) { - void **list, **l; + pldict_t *dict = item->data; dictkey_t *current; int result = 1; plparser_t parser; - if (dict->type != QFDictionary) { - PL_Message (messages, dict, "error: not a dictionary object"); + if (item->type != QFDictionary) { + PL_Message (messages, item, "error: not a dictionary object"); return 0; } - l = list = Hash_GetList ((hashtab_t *) dict->data); - while ((current = (dictkey_t *) *l++)) { + for (size_t i = 0; i < dict->keys.size; i++) { const plfield_t *f; + current = dict->keys.a[i]; for (f = fields; f->name; f++) { if (strcmp (f->name, current->key) == 0) { plitem_t *item = current->value; @@ -1238,12 +1272,11 @@ PL_ParseStruct (const plfield_t *fields, const plitem_t *dict, void *data, } } if (!f->name) { - PL_Message (messages, dict, "error: unknown field %s", + PL_Message (messages, item, "error: unknown field %s", current->key); result = 0; } } - free (list); return result; } @@ -1297,10 +1330,10 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, } VISIBLE int -PL_ParseLabeledArray (const plfield_t *field, const plitem_t *dict, +PL_ParseLabeledArray (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { - void **list, **l; + pldict_t *dict = item->data; dictkey_t *current; int result = 1; plparser_t parser; @@ -1309,8 +1342,8 @@ PL_ParseLabeledArray (const plfield_t *field, const plitem_t *dict, arr_t *arr; plfield_t f = { 0, 0, element->type, element->parser, element->data }; - if (dict->type != QFDictionary) { - PL_Message (messages, dict, "error: not a dictionary object"); + if (item->type != QFDictionary) { + PL_Message (messages, item, "error: not a dictionary object"); return 0; } if (f.parser) { @@ -1319,28 +1352,21 @@ PL_ParseLabeledArray (const plfield_t *field, const plitem_t *dict, parser = pl_default_parser; } - list = Hash_GetList ((hashtab_t *) dict->data); - - int numvals = 0; - for (l = list; *l; l++) { - numvals++; - } - - arr = DARRAY_ALLOCFIXED_OBJ (arr_t, numvals * element->stride, + arr = DARRAY_ALLOCFIXED_OBJ (arr_t, dict->keys.size * element->stride, element->alloc, context); memset (arr->a, 0, arr->size); // the array is allocated using bytes, but need the actual number of // elements in the array - arr->size = arr->maxSize = numvals; + arr->size = arr->maxSize = dict->keys.size; - for (int i = 0; i < numvals; i++) { - current = list[i]; + for (size_t i = 0; i < dict->keys.size; i++) { + current = dict->keys.a[i]; plitem_t *item = current->value; void *eledata = &arr->a[i * element->stride]; if (!PL_CheckType (element->type, item->type)) { char index[16]; - snprintf (index, sizeof(index) - 1, "%d", i); + snprintf (index, sizeof(index) - 1, "%zd", i); index[15] = 0; PL_TypeMismatch (messages, item, index, element->type, item->type); result = 0; @@ -1355,10 +1381,10 @@ PL_ParseLabeledArray (const plfield_t *field, const plitem_t *dict, } VISIBLE int -PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, +PL_ParseSymtab (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { - void **list, **l; + pldict_t *dict = item->data; dictkey_t *current; int result = 1; plparser_t parser; @@ -1367,26 +1393,22 @@ PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, plelement_t *element = (plelement_t *) field->data; plfield_t f = { 0, 0, element->type, element->parser, element->data }; - if (dict->type != QFDictionary) { - PL_Message (messages, dict, "error: not a dictionary object"); + if (item->type != QFDictionary) { + PL_Message (messages, item, "error: not a dictionary object"); return 0; } if (f.parser) { parser = f.parser; } else { - PL_Message (messages, dict, "no parser set"); + PL_Message (messages, item, "no parser set"); return 0; } - if (!(l = list = Hash_GetList ((hashtab_t *) dict->data))) { - // empty struct: leave as default - return 1; - } - void *obj = element->alloc (context, element->stride); memset (obj, 0, element->stride); - while ((current = (dictkey_t *) *l++)) { + for (size_t i = 0; i < dict->keys.size; i++) { + current = dict->keys.a[i]; const char *key = current->key; plitem_t *item = current->value; @@ -1410,6 +1432,5 @@ PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, } } Hash_Free (tab, obj); - free (list); return result; } From 35f12c36ff631b3d9ef31c0f373e83a11c3d1508 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 19:29:48 +0900 Subject: [PATCH 1326/3664] [util] Catch some more cexpr errors --- libs/util/cexpr-parse.y | 5 ++++- libs/util/cexpr-type.c | 10 +++++----- libs/util/cexpr-vars.c | 2 ++ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index 599955afd..8ccf0b20b 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -129,7 +129,7 @@ uexpr | '(' expr ')' { $$ = $2; } | NAME '(' opt_arg_list ')' { $$ = function_expr ($1, $3, context); } | uexpr '.' field { $$ = field_expr ($1, $3, context); } - | uexpr '[' field ']' { $$ = index_expr ($1, $3, context); } + | uexpr '[' expr ']' { $$ = index_expr ($1, $3, context); } | '+' uexpr %prec UNARY { $$ = $2; } | '-' uexpr %prec UNARY { $$ = unary_expr ('-', $2, context); } | '!' uexpr %prec UNARY { $$ = unary_expr ('!', $2, context); } @@ -268,6 +268,9 @@ index_expr (const exprval_t *a, const exprval_t *b, exprctx_t *context) binop_t *binop; exprval_t *result = 0; + if (!a || !b) { + return 0; + } for (binop = a->type->binops; binop->op; binop++) { if (binop->op == '[' && binop->other == b->type) { break; diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 1ba3b3f0f..2aff20006 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -646,14 +646,14 @@ static void plitem_index (const exprval_t *a, int index, exprval_t *c, exprctx_t *ctx) { - __auto_type array = *(plitem_t **) a->type->data; + __auto_type array = *(plitem_t **) a->value; if (PL_Type (array) != QFArray) { cexpr_error(ctx, "not an array object"); return; } plitem_t *item = PL_ObjectAtIndex (array, index); - exprval_t *val = 0; + exprval_t *val = 0; if (!item) { cexpr_error (ctx, "invalid index: %d", index); } else { @@ -667,7 +667,7 @@ static void plitem_int (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx) { - int index = *(int *) a->value; + int index = *(int *) b->value; plitem_index (a, index, c, ctx); } @@ -675,7 +675,7 @@ static void plitem_uint (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx) { - int index = *(int *) a->value; + int index = *(unsigned *) b->value; plitem_index (a, index, c, ctx); } @@ -683,7 +683,7 @@ static void plitem_size_t (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx) { - int index = *(int *) a->value; + int index = *(size_t *) b->value; plitem_index (a, index, c, ctx); } diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c index 04c6871ad..9b390b523 100644 --- a/libs/util/cexpr-vars.c +++ b/libs/util/cexpr-vars.c @@ -49,6 +49,8 @@ cexpr_struct_getfield (const exprval_t *a, const exprval_t *b, exprval_t *c, val = cmemalloc (ctx->memsuper, sizeof (exprval_t)); val->type = field->type; val->value = a->value + (ptrdiff_t) field->value; + } else { + cexpr_error (ctx, "%s has no field %s", a->type->name, name); } *(exprval_t **) c->value = val; } From 55104ac430bed00caf6b5a9fb9c0861ca2eecb68 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Feb 2021 19:30:30 +0900 Subject: [PATCH 1327/3664] [util] Allow "any type" results for cexpr Setting the result type cexpr_exprval tells cexpr to simply return whoe exprval object rather than the referenced value, thus allowing the caller to check the type when the expression is context sensitive. --- libs/util/cexpr-parse.y | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index 8ccf0b20b..ad734def7 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -191,6 +191,10 @@ assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context) if (!src) { return; } + if (dst->type == &cexpr_exprval) { + *(exprval_t **) dst->value = (exprval_t *) src; + return; + } binop = cexpr_find_cast (dst->type, src->type); if (binop && binop->op) { binop->func (dst, src, dst, context); From cffd48434ca28b86ba0131ec872b6715a88a064e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Feb 2021 17:43:11 +0900 Subject: [PATCH 1328/3664] [vulkan] Move the shaders into their own directory --- libs/video/renderer/Makemodule.am | 34 ++++++++++--------- libs/video/renderer/vulkan/shader.c | 16 ++++----- .../renderer/vulkan/{ => shader}/alias.frag | 0 .../renderer/vulkan/{ => shader}/alias.vert | 0 .../vulkan/{ => shader}/passthrough.vert | 0 .../vulkan/{ => shader}/pushcolor.frag | 0 .../vulkan/{ => shader}/quakebsp.frag | 0 .../vulkan/{ => shader}/quakebsp.vert | 0 .../renderer/vulkan/{ => shader}/twod.frag | 0 .../renderer/vulkan/{ => shader}/twod.vert | 0 10 files changed, 26 insertions(+), 24 deletions(-) rename libs/video/renderer/vulkan/{ => shader}/alias.frag (100%) rename libs/video/renderer/vulkan/{ => shader}/alias.vert (100%) rename libs/video/renderer/vulkan/{ => shader}/passthrough.vert (100%) rename libs/video/renderer/vulkan/{ => shader}/pushcolor.frag (100%) rename libs/video/renderer/vulkan/{ => shader}/quakebsp.frag (100%) rename libs/video/renderer/vulkan/{ => shader}/quakebsp.vert (100%) rename libs/video/renderer/vulkan/{ => shader}/twod.frag (100%) rename libs/video/renderer/vulkan/{ => shader}/twod.vert (100%) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index b322a7ca4..cb0eec6d1 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -262,22 +262,24 @@ vkparse_src = \ vkparse_plist = \ $(srcdir)/libs/video/renderer/vulkan/vkparse.plist -twodv_src = libs/video/renderer/vulkan/twod.vert -twodv_c = libs/video/renderer/vulkan/twod.vert.spvc -twodf_src = libs/video/renderer/vulkan/twod.frag -twodf_c = libs/video/renderer/vulkan/twod.frag.spvc -quakebspv_src = libs/video/renderer/vulkan/quakebsp.vert -quakebspv_c = libs/video/renderer/vulkan/quakebsp.vert.spvc -quakebspf_src = libs/video/renderer/vulkan/quakebsp.frag -quakebspf_c = libs/video/renderer/vulkan/quakebsp.frag.spvc -aliasv_src = libs/video/renderer/vulkan/alias.vert -aliasv_c = libs/video/renderer/vulkan/alias.vert.spvc -aliasf_src = libs/video/renderer/vulkan/alias.frag -aliasf_c = libs/video/renderer/vulkan/alias.frag.spvc -passthrough_src = libs/video/renderer/vulkan/passthrough.vert -passthrough_c = libs/video/renderer/vulkan/passthrough.vert.spvc -pushcolor_src = libs/video/renderer/vulkan/pushcolor.frag -pushcolor_c = libs/video/renderer/vulkan/pushcolor.frag.spvc +vkshaderpath = libs/video/renderer/vulkan/shader + +twodv_src = $(vkshaderpath)/twod.vert +twodv_c = $(vkshaderpath)/twod.vert.spvc +twodf_src = $(vkshaderpath)/twod.frag +twodf_c = $(vkshaderpath)/twod.frag.spvc +quakebspv_src = $(vkshaderpath)/quakebsp.vert +quakebspv_c = $(vkshaderpath)/quakebsp.vert.spvc +quakebspf_src = $(vkshaderpath)/quakebsp.frag +quakebspf_c = $(vkshaderpath)/quakebsp.frag.spvc +aliasv_src = $(vkshaderpath)/alias.vert +aliasv_c = $(vkshaderpath)/alias.vert.spvc +aliasf_src = $(vkshaderpath)/alias.frag +aliasf_c = $(vkshaderpath)/alias.frag.spvc +passthrough_src = $(vkshaderpath)/passthrough.vert +passthrough_c = $(vkshaderpath)/passthrough.vert.spvc +pushcolor_src = $(vkshaderpath)/pushcolor.frag +pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc $(twodv_c): $(twodv_src) diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index a3cc9e3f0..90a93684b 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -55,21 +55,21 @@ #include "vid_vulkan.h" static -#include "libs/video/renderer/vulkan/twod.vert.spvc" +#include "libs/video/renderer/vulkan/shader/twod.vert.spvc" static -#include "libs/video/renderer/vulkan/twod.frag.spvc" +#include "libs/video/renderer/vulkan/shader/twod.frag.spvc" static -#include "libs/video/renderer/vulkan/quakebsp.vert.spvc" +#include "libs/video/renderer/vulkan/shader/quakebsp.vert.spvc" static -#include "libs/video/renderer/vulkan/quakebsp.frag.spvc" +#include "libs/video/renderer/vulkan/shader/quakebsp.frag.spvc" static -#include "libs/video/renderer/vulkan/alias.vert.spvc" +#include "libs/video/renderer/vulkan/shader/alias.vert.spvc" static -#include "libs/video/renderer/vulkan/alias.frag.spvc" +#include "libs/video/renderer/vulkan/shader/alias.frag.spvc" static -#include "libs/video/renderer/vulkan/passthrough.vert.spvc" +#include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc" static -#include "libs/video/renderer/vulkan/pushcolor.frag.spvc" +#include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc" typedef struct shaderdata_s { const char *name; diff --git a/libs/video/renderer/vulkan/alias.frag b/libs/video/renderer/vulkan/shader/alias.frag similarity index 100% rename from libs/video/renderer/vulkan/alias.frag rename to libs/video/renderer/vulkan/shader/alias.frag diff --git a/libs/video/renderer/vulkan/alias.vert b/libs/video/renderer/vulkan/shader/alias.vert similarity index 100% rename from libs/video/renderer/vulkan/alias.vert rename to libs/video/renderer/vulkan/shader/alias.vert diff --git a/libs/video/renderer/vulkan/passthrough.vert b/libs/video/renderer/vulkan/shader/passthrough.vert similarity index 100% rename from libs/video/renderer/vulkan/passthrough.vert rename to libs/video/renderer/vulkan/shader/passthrough.vert diff --git a/libs/video/renderer/vulkan/pushcolor.frag b/libs/video/renderer/vulkan/shader/pushcolor.frag similarity index 100% rename from libs/video/renderer/vulkan/pushcolor.frag rename to libs/video/renderer/vulkan/shader/pushcolor.frag diff --git a/libs/video/renderer/vulkan/quakebsp.frag b/libs/video/renderer/vulkan/shader/quakebsp.frag similarity index 100% rename from libs/video/renderer/vulkan/quakebsp.frag rename to libs/video/renderer/vulkan/shader/quakebsp.frag diff --git a/libs/video/renderer/vulkan/quakebsp.vert b/libs/video/renderer/vulkan/shader/quakebsp.vert similarity index 100% rename from libs/video/renderer/vulkan/quakebsp.vert rename to libs/video/renderer/vulkan/shader/quakebsp.vert diff --git a/libs/video/renderer/vulkan/twod.frag b/libs/video/renderer/vulkan/shader/twod.frag similarity index 100% rename from libs/video/renderer/vulkan/twod.frag rename to libs/video/renderer/vulkan/shader/twod.frag diff --git a/libs/video/renderer/vulkan/twod.vert b/libs/video/renderer/vulkan/shader/twod.vert similarity index 100% rename from libs/video/renderer/vulkan/twod.vert rename to libs/video/renderer/vulkan/shader/twod.vert From 121425a75bba7056a931c3b9494e438f20e558de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 Feb 2021 11:20:54 +0900 Subject: [PATCH 1329/3664] [vulkan] Allow all struct objects to be referenced --- libs/video/renderer/vulkan/vkgen/vkstruct.r | 8 +++-- libs/video/renderer/vulkan/vkparse.c | 35 +++++++++++++++++---- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 108af71ef..77b11fad5 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -139,9 +139,13 @@ fprintf (output_file, " = %s;\n", [self sTypeName]); } fprintf (output_file, + "\tif (PL_Type (item) == QFString\n" + "\t\t&& !(item = parse_reference (item, \"%s\", messages, context))) {\n" + "\t\treturn 0;\n" + "\t}\n" "\treturn PL_ParseStruct (%s_fields, item, data, messages," " context);\n", - [self outname]); + [self outname], [self outname]); fprintf (output_file, "}\n"); fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self outname]); @@ -214,7 +218,7 @@ -(string) parseType { - return "QFDictionary"; + return "QFMultiType | (1 << QFString) | (1 << QFDictionary)"; } -(string) parseFunc diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 3f02b8022..ad2696c8f 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -232,6 +232,24 @@ parse_enum (const plfield_t *field, const plitem_t *item, return ret; } +static const plitem_t * +parse_reference (const plitem_t *item, const char *type, plitem_t *messages, + parsectx_t *pctx) +{ + exprctx_t ectx = *pctx->ectx; + vulkan_ctx_t *ctx = pctx->vctx; + plitem_t *refItem = 0; + exprval_t result = { &cexpr_plitem, &refItem }; + ectx.symtab = 0; + ectx.result = &result; + const char *name = PL_String (item); + if (cexpr_eval_string (name, &ectx)) { + PL_Message (messages, item, va (ctx->va_ctx, "not a %s reference", type)); + return 0; + } + return refItem; +} + static int parse_single (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -420,12 +438,15 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, { __auto_type handle = (VkDescriptorSetLayout *) data; int ret = 1; - exprctx_t ectx = *((parsectx_t *) context)->ectx; - vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; + parsectx_t *pctx = context; + exprctx_t ectx = *pctx->ectx; + vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); Sys_Printf ("parse_VkDescriptorSetLayout: %s\n", name); - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); + if (name[0] != '$') { + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); + } *handle = (VkDescriptorSetLayout) QFV_GetHandle (ctx->setLayouts, name); if (*handle) { @@ -453,12 +474,14 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, { __auto_type handle = (VkPipelineLayout *) data[0]; int ret = 1; - exprctx_t ectx = *((parsectx_t *) context)->ectx; - vulkan_ctx_t *ctx = ((parsectx_t *) context)->vctx; + exprctx_t ectx = *context->ectx; + vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); Sys_Printf ("parse_VkPipelineLayout: %s\n", name); - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); + if (name[0] != '$') { + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); + } *handle = (VkPipelineLayout) QFV_GetHandle (ctx->pipelineLayouts, name); if (*handle) { From a94949c00928a9be998bf226412558dbb25b9932 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 Feb 2021 11:35:06 +0900 Subject: [PATCH 1330/3664] [vulkan] Start moving towards a deferred renderer After getting lights even vaguely working for alias models, I realized that it just wasn't going to be feasible to do nice lighting with forward rendering. This gets the bulk of the work done for deferred rendering, but still need to sort out the shaders before any real testing can be done. --- include/QF/Vulkan/image.h | 13 +- include/QF/Vulkan/qf_alias.h | 36 +- include/QF/Vulkan/qf_bsp.h | 13 +- include/QF/Vulkan/qf_vid.h | 15 +- include/QF/Vulkan/renderpass.h | 6 + include/vid_vulkan.h | 23 +- libs/video/renderer/Makemodule.am | 4 +- libs/video/renderer/vid_render_vulkan.c | 40 +- libs/video/renderer/vulkan/deferred.plist | 342 ++++++++++++++ libs/video/renderer/vulkan/qfpipeline.plist | 163 +++---- libs/video/renderer/vulkan/vkparse.c | 424 ++++++++++++++++-- libs/video/renderer/vulkan/vkparse.h | 31 +- libs/video/renderer/vulkan/vkparse.plist | 45 ++ libs/video/renderer/vulkan/vulkan_alias.c | 231 +++++----- libs/video/renderer/vulkan/vulkan_bsp.c | 256 ++++++----- libs/video/renderer/vulkan/vulkan_draw.c | 5 +- .../video/renderer/vulkan/vulkan_vid_common.c | 251 +++++------ 17 files changed, 1347 insertions(+), 551 deletions(-) create mode 100644 libs/video/renderer/vulkan/deferred.plist diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 9942562b2..5e5623137 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -3,8 +3,17 @@ #include "QF/darray.h" -typedef struct qfv_imageset_s DARRAY_TYPE (VkImage) qfv_imageset_t; -typedef struct qfv_imageviewset_s DARRAY_TYPE (VkImageView) qfv_imageviewset_t; +typedef struct qfv_imageset_s + DARRAY_TYPE (VkImage) qfv_imageset_t; + +#define QFV_AllocImages(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_imageset_t, num, allocator) + +typedef struct qfv_imageviewset_s + DARRAY_TYPE (VkImageView) qfv_imageviewset_t; + +#define QFV_AllocImageViews(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_imageviewset_t, num, allocator) typedef struct qfv_imageresource_s { struct qfv_device_s *device; diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 714cb06b3..597888a4d 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -36,6 +36,7 @@ #include "QF/model.h" #include "QF/modelgen.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" typedef struct aliasvrt_s { float vertex[4]; @@ -61,32 +62,22 @@ typedef struct qfv_alias_skin_s { byte colorb[4]; } qfv_alias_skin_t; -typedef struct qfv_light_s { - vec3_t color; - float dist; - vec3_t position; - int type; - vec3_t direction; - float cone; -} qfv_light_t; - -#define ALIAS_LIGHTS 8 - -typedef struct qfv_light_buffer_s { - int light_count; - qfv_light_t lights[ALIAS_LIGHTS] __attribute__((aligned(16))); -} qfv_light_buffer_t; - -#define ALIAS_BUFFER_INFOS 2 +#define ALIAS_BUFFER_INFOS 1 #define ALIAS_IMAGE_INFOS 1 +enum { + QFV_aliasDepth, + QFV_aliasGBuffer, + //QFV_aliasTranslucent, + + QFV_aliasNumPasses +}; + typedef struct aliasframe_s { - VkCommandBuffer cmd; + qfv_cmdbufferset_t cmdSet; VkDescriptorBufferInfo bufferInfo[ALIAS_BUFFER_INFOS]; VkDescriptorImageInfo imageInfo[ALIAS_IMAGE_INFOS]; VkWriteDescriptorSet descriptors[ALIAS_BUFFER_INFOS + ALIAS_IMAGE_INFOS]; - qfv_light_buffer_t *lights; - VkBuffer light_buffer; } aliasframe_t; typedef struct aliasframeset_s @@ -94,11 +85,10 @@ typedef struct aliasframeset_s typedef struct aliasctx_s { aliasframeset_t frames; - VkPipeline pipeline; + VkPipeline depth; + VkPipeline gbuf; VkPipelineLayout layout; VkSampler sampler; - - VkDeviceMemory light_memory; } aliasctx_t; struct vulkan_ctx_s; diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 151e6e7be..b78aaf643 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -35,6 +35,7 @@ #include "QF/darray.h" #include "QF/model.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" typedef struct bspvert_s { quat_t vertex; @@ -69,13 +70,19 @@ typedef enum { // Texture, GlowMap, LightMap, SkySheet, SkyCube #define BSP_IMAGE_INFOS 5 +enum { + QFV_bspDepth, + QFV_bspGBuffer, + QFV_bspTranslucent, + + QFV_bspNumPasses +}; + typedef struct bspframe_s { uint32_t *index_data; // pointer into mega-buffer for this frame (c) uint32_t index_offset; // offset of index_data within mega-buffer (c) uint32_t index_count; // number if indices queued (d) - VkCommandBuffer bsp_cmd; - VkCommandBuffer turb_cmd; - VkCommandBuffer sky_cmd; + qfv_cmdbufferset_t cmdSet; VkDescriptorBufferInfo bufferInfo[BSP_BUFFER_INFOS]; VkDescriptorImageInfo imageInfo[BSP_IMAGE_INFOS]; VkWriteDescriptorSet descriptors[BSP_BUFFER_INFOS + BSP_IMAGE_INFOS]; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 1102845b5..f81e934a1 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -35,9 +35,22 @@ #endif #include +//FIXME location +enum { + QFV_passDepth, // geometry + QFV_passGBuffer, // geometry + QFV_passTranslucent, // geometry + QFV_passLighting, // single quad + QFV_passCompose, // single quad + + QFV_NumPasses +}; + struct vulkan_ctx_s; -void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); +void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); +void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); +void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index 49134c730..a584d476d 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -27,6 +27,12 @@ typedef struct qfv_subpassdependency_s #define QFV_AllocSubpassDependencies(num, allocator) \ DARRAY_ALLOCFIXED (qfv_subpassdependency_t, num, allocator) +typedef struct qfv_framebufferset_s + DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t; + +#define QFV_AllocFrameBuffers(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_framebufferset_t, num, allocator) + struct qfv_device_s; struct qfv_imageviewset_s; VkRenderPass diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 4ddab99e3..dcf4f624b 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -8,20 +8,15 @@ #include "QF/darray.h" -typedef struct vulkan_renderpass_s { - VkRenderPass renderpass; - struct qfv_imageresource_s *colorImage; - struct qfv_imageresource_s *depthImage; -} vulkan_renderpass_t; - -typedef struct vulkan_framebuffer_s { +typedef struct vulkan_frame_s { VkFramebuffer framebuffer; VkFence fence; VkSemaphore imageAvailableSemaphore; VkSemaphore renderDoneSemaphore; VkCommandBuffer cmdBuffer; - struct qfv_cmdbufferset_s *subCommand; + int cmdSetCount; + struct qfv_cmdbufferset_s *cmdSets; } vulkan_frame_t; typedef struct vulkan_matrices_s { @@ -59,11 +54,22 @@ typedef struct vulkan_ctx_s { VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain struct plitem_s *pipelineDef; + struct plitem_s *renderpassDef; + VkRenderPass renderpass; + struct qfv_imageset_s *attachment_images; + struct qfv_imageviewset_s *attachment_views; + VkDeviceMemory attachmentMemory; + + uint32_t swapImageIndex; + struct qfv_framebufferset_s *framebuffers; + struct hashtab_s *shaderModules; struct hashtab_s *setLayouts; struct hashtab_s *pipelineLayouts; struct hashtab_s *descriptorPools; struct hashtab_s *samplers; + struct hashtab_s *images; + struct hashtab_s *imageViews; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; @@ -72,7 +78,6 @@ typedef struct vulkan_ctx_s { VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; VkFence fence; // for ctx->cmdbuffer only - vulkan_renderpass_t renderpass; struct qfv_stagebuf_s *staging; VkPipeline pipeline; size_t curFrame; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index cb0eec6d1..66db70d11 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -209,6 +209,8 @@ libs_video_renderer_vid_render_sw32_la_SOURCES=\ pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc +renderpass_src = libs/video/renderer/vulkan/deferred.plist +renderpass_gen = libs/video/renderer/vulkan/deferred.plc video_renderer_vulkan_libs = \ libs/models/libmodels_vulkan.la @@ -250,7 +252,7 @@ libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vk libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c) -libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) +libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${renderpass_gen} qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a41a1d960..b8f9dc718 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -87,8 +87,9 @@ vulkan_R_Init (void) Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateMatrices (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); - Vulkan_CreateFramebuffers (vulkan_ctx); + Vulkan_CreateFrames (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); + Vulkan_CreateFramebuffers (vulkan_ctx); // FIXME this should be staged so screen updates can begin while pipelines // are being built vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); @@ -111,6 +112,8 @@ vulkan_R_Init (void) static void vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) { + const VkSubpassContents subpassContents + = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; static int count = 0; static double startTime; uint32_t imageIndex = 0; @@ -128,20 +131,9 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) QFV_AcquireNextImage (vulkan_ctx->swapchain, frame->imageAvailableSemaphore, 0, &imageIndex); + vulkan_ctx->swapImageIndex = imageIndex; - int attachCount = vulkan_ctx->msaaSamples > 1 ? 3 : 2; - __auto_type attachments = DARRAY_ALLOCFIXED (qfv_imageviewset_t, - attachCount, alloca); - qfv_swapchain_t *sc = vulkan_ctx->swapchain; - attachments->a[0] = sc->imageViews->a[imageIndex]; - attachments->a[1] = vulkan_ctx->renderpass.depthImage->view; - if (attachCount > 2) { - attachments->a[2] = vulkan_ctx->renderpass.colorImage->view; - } - - VkRenderPass renderpass = vulkan_ctx->renderpass.renderpass; - frame->framebuffer = QFV_CreateFramebuffer (device, renderpass, - attachments, sc->extent, 1); + frame->framebuffer = vulkan_ctx->framebuffers->a[imageIndex]; scr_3dfunc (); while (*scr_funcs) { @@ -160,20 +152,26 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) }; VkRenderPassBeginInfo renderPassInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, - vulkan_ctx->renderpass.renderpass, 0, - { {0, 0}, sc->extent }, + vulkan_ctx->renderpass, 0, + { {0, 0}, vulkan_ctx->swapchain->extent }, 3, clearValues }; dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); renderPassInfo.framebuffer = frame->framebuffer; dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, - VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); + subpassContents); - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, frame->subCommand->size, - frame->subCommand->a); - // reset for next time around - frame->subCommand->size = 0; + for (int i = 0; i < frame->cmdSetCount; i++) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, frame->cmdSets[i].size, + frame->cmdSets[i].a); + // reset for next time around + frame->cmdSets[i].size = 0; + + if (i < frame->cmdSetCount) { + dfunc->vkCmdNextSubpass (frame->cmdBuffer, subpassContents); + } + } dfunc->vkCmdEndRenderPass (frame->cmdBuffer); dfunc->vkEndCommandBuffer (frame->cmdBuffer); diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist new file mode 100644 index 000000000..e7e7e1f12 --- /dev/null +++ b/libs/video/renderer/vulkan/deferred.plist @@ -0,0 +1,342 @@ +{ + images = { + depth = { + imageType = VK_IMAGE_TYPE_2D; //FIXME short form is 2d... + format = x8_d24_unorm_pack32; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = depth_stencil_attachment|input_attachment; + }; + color = { + imageType = VK_IMAGE_TYPE_2D; + format = r8g8b8a8_unorm; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment; + }; + normals = { + imageType = VK_IMAGE_TYPE_2D; + format = r16g16b16a16_sfloat; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment; + }; + opaque = { + imageType = VK_IMAGE_TYPE_2D; + format = r8g8b8a8_unorm; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment; + }; + translucent = { + imageType = VK_IMAGE_TYPE_2D; + format = r8g8b8a8_unorm; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment; + }; + }; + imageViews = { + depth = { + image = depth; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.depth.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = depth; + levelCount = 1; + layerCount = 1; + }; + }; + color = { + image = color; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.color.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + normals = { + image = normals; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.normals.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + opaque = { + image = opaque; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.opaque.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + translucent = { + image = translucent; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.translucent.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + }; + framebuffer = { + renderPass = renderpass; + attachments = (depth, color, normals, opaque, translucent, + "$swapchain.views[$swapImageIndex]"); + width = $swapchain.extent.width; + height = $swapchain.extent.height; + }; + renderpass = { + attachments = ( + { + format = $properties.images.depth.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = depth_stencil_attachment_optimal; + }, + { + format = $properties.images.color.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, + { + format = $properties.images.normals.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, + { + format = $properties.images.opaque.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, + { + format = $properties.images.translucent.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, + { + format = $swapchain.format; + samples = 1; + loadOp = clear; + storeOp = store; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = present_src_khr; + }, + ); + subpasses = ( + { // depth + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_attachment_optimal; + }; + }, + { // g-buffer generation + pipelineBindPoint = graphics; + colorAttachments = ( + { // color + attachment = 1; + layout = color_attachment_optimal; + }, + { // normals + attachment = 2; + layout = color_attachment_optimal; + }, + ); + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_attachment_optimal; + }; + }, + { // lighting + pipelineBindPoint = graphics; + inputAttachments = ( + { // depth + attachment = 0; + layout = shader_read_only_optimal; + }, + { // color + attachment = 1; + layout = shader_read_only_optimal; + }, + { // normals + attachment = 2; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // opaque + attachment = 3; + layout = color_attachment_optimal; + }, + ); + }, + { // translucent + pipelineBindPoint = graphics; + colorAttachments = ( + { // translucent + attachment = 4; + layout = color_attachment_optimal; + }, + ); + }, + { // compose + pipelineBindPoint = graphics; + inputAttachments = ( + { // opaque + attachment = 3; + layout = shader_read_only_optimal; + }, + { // translucent + attachment = 4; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // swapchain + attachment = 5; + layout = color_attachment_optimal; + }, + ); + }, + ); + dependencies = ( + { + srcSubpass = 0; + dstSubpass = 1; + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = shader_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 1; + dstSubpass = 2; + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = shader_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 2; + dstSubpass = 4; + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = shader_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 3; + dstSubpass = 4; + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = shader_read; + dependencyFlags = by_region; + }, + ); + }; +} diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 324e08e7c..2cd110385 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -273,7 +273,45 @@ }; }; pipelines = { - alias = { + alias_depth = { + stages = ( + { + stage = vertex; + name = main; + module = $builtin/alias.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.pipelines.alias_gbuf.vertexInput.bindings[0]", + "$properties.pipelines.alias_gbuf.vertexInput.bindings[1]", + ); + attributes = ( + "$properties.pipelines.alias_gbuf.vertexInput.attributes[0]", + "$properties.pipelines.alias_gbuf.vertexInput.attributes[1]", + "$properties.pipelines.alias_gbuf.vertexInput.attributes[2]", + "$properties.pipelines.alias_gbuf.vertexInput.attributes[3]", + ); + }; + inputAssembly = $properties.pipelines.alias_gbuf.inputAssembly; + viewport = $properties.pipelines.alias_gbuf.viewport; + rasterization = $properties.pipelines.alias_gbuf.rasterization; + multisample = $properties.pipelines.alias_gbuf.multisample; + depthStencil = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = $properties.pipelines.alias_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = alias_layout; + //renderPass = renderpass; + }; + alias_gbuf = { stages = ( { stage = vertex; @@ -404,7 +442,41 @@ layout = alias_layout; //renderPass = renderpass; }; - quakebsp_main = { + bsp_depth = { + stages = ( + { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.pipelines.bsp_gbuf.vertexInput.bindings[0]", + ); + attributes = ( + "$properties.pipelines.bsp_gbuf.vertexInput.attributes[0]", + ); + }; + inputAssembly = $properties.pipelines.bsp_main.inputAssembly; + viewport = $properties.pipelines.bsp_main.viewport; + rasterization = $properties.pipelines.bsp_main.rasterization; + multisample = $properties.pipelines.bsp_main.multisample; + depthStencil = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = quakebsp_layout; + //renderPass = renderpass; + }; + bsp_gbuf = { stages = ( { stage = vertex; @@ -523,86 +595,15 @@ }; }, ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "2 * 4 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 0; - }, - { - location = 1; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 16; - }, - ); - }; - inputAssembly = { - topology = triangle_fan; - primitiveRestartEnable = true; - }; - viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); - }; - rasterization = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - depthStencil = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - colorBlend = { - logicOpEnable = false; - attachments = ({ - blendEnable = true; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }); - }; + vertexInput = $properties.pipelines.bsp_gbuf.vertexInput; + inputAssembly = $properties.pipelines.bsp_gbuf.inputAssembly; + viewport = $properties.pipelines.bsp_gbuf.viewport; + rasterization = $properties.pipelines.bsp_gbuf.rasterization; + multisample = $properties.pipelines.bsp_gbuf.multisample; + depthStencil = $properties.pipelines.bsp_gbuf.depthStencil; + colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; dynamic = { - dynamicState = ( viewport, scissor, blend_constants ); + dynamicState = ( viewport, scissor ); }; layout = quakebsp_layout; //renderPass = renderpass; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index ad2696c8f..2d9b3c806 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -460,7 +460,8 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, ret = !cexpr_eval_string (name, &ectx); if (ret) { VkDescriptorSetLayout setLayout; - setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem); + setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem, + pctx->properties); *handle = (VkDescriptorSetLayout) setLayout; QFV_AddHandle (ctx->setLayouts, name, (uint64_t) setLayout); @@ -495,7 +496,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, ret = !cexpr_eval_string (name, &ectx); if (ret) { VkPipelineLayout layout; - layout = QFV_ParsePipelineLayout (ctx, setItem); + layout = QFV_ParsePipelineLayout (ctx, setItem, context->properties); *handle = (VkPipelineLayout) layout; QFV_AddHandle (ctx->pipelineLayouts, name, (uint64_t) layout); @@ -503,6 +504,92 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, return ret; } +static int +parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, + parsectx_t *context) +{ + __auto_type handle = (VkImage *) data[0]; + int ret = 1; + exprctx_t ectx = *context->ectx; + vulkan_ctx_t *ctx = context->vctx; + + const char *name = PL_String (item); + Sys_Printf ("parse_VkImage: %s\n", name); + if (name[0] != '$') { + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); + } + + *handle = (VkImage) QFV_GetHandle (ctx->images, name); + if (*handle) { + return 1; + } + + plitem_t *imageItem = 0; + exprval_t result = { &cexpr_plitem, &imageItem }; + ectx.symtab = 0; + ectx.result = &result; + ret = !cexpr_eval_string (name, &ectx); + if (ret) { + VkImage image; + image = QFV_ParseImage (ctx, imageItem, context->properties); + *handle = (VkImage) image; + + QFV_AddHandle (ctx->images, name, (uint64_t) image); + } + return ret; +} + +static exprtype_t imageview_type = { + "VkImageView", + sizeof (VkImageView), + 0, 0, 0 +}; + +static int +parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages, void *_context) +{ + parsectx_t *context = _context; + __auto_type handle = (VkImageView *) data; + int ret = 1; + exprctx_t ectx = *context->ectx; + vulkan_ctx_t *ctx = context->vctx; + + const char *name = PL_String (item); + Sys_Printf ("parse_VkImageView: %s\n", name); + if (name[0] != '$') { + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name); + } + + *handle = (VkImageView) QFV_GetHandle (ctx->imageViews, name); + if (*handle) { + return 1; + } + + exprval_t *value = 0; + exprval_t result = { &cexpr_exprval, &value }; + ectx.symtab = 0; + ectx.result = &result; + ret = !cexpr_eval_string (name, &ectx); + + plitem_t *imageViewItem = 0; + if (ret) { + VkImageView imageView; + if (value->type == &imageview_type) { + imageView = *(VkImageView *) value->value; + } else if (value->type == &cexpr_plitem) { + imageView = QFV_ParseImageView (ctx, imageViewItem, + context->properties); + QFV_AddHandle (ctx->imageViews, name, (uint64_t) imageView); + } else { + PL_Message (messages, item, "not a VkImageView"); + return 0; + } + *handle = (VkImageView) imageView; + } + return ret; +} + static const char * handleref_getkey (const void *hr, void *unused) { @@ -592,6 +679,36 @@ sampler_free (void *hr, void *_ctx) handleref_free (handleref, ctx); } +static void +image_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type image = (VkImage) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (image) { + dfunc->vkDestroyImage (device->dev, image, 0); + }; + handleref_free (handleref, ctx); +} + +static void +imageView_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type imageView = (VkImageView) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (imageView) { + dfunc->vkDestroyImageView (device->dev, imageView, 0); + }; + handleref_free (handleref, ctx); +} + static hashtab_t *enum_symtab; static int @@ -605,23 +722,71 @@ parse_BasePipeline (const plitem_t *item, void **data, #include "libs/video/renderer/vulkan/vkparse.cinc" -static exprsym_t imageset_symbols[] = { - {"size", &cexpr_size_t, (void *)field_offset (qfv_imageset_t, size)}, +static void +imageviewset_index (const exprval_t *a, size_t index, exprval_t *c, + exprctx_t *ctx) +{ + __auto_type set = *(qfv_imageviewset_t **) a->value; + exprval_t *val = 0; + if (index >= set->size) { + cexpr_error (ctx, "invalid index: %zd", index); + } else { + val = cexpr_value (&imageview_type, ctx); + *(VkImageView *) val->value = set->a[index]; + } + *(exprval_t **) c->value = val; +} + +static void +imageviewset_int (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + size_t index = *(int *) b->value; + imageviewset_index (a, index, c, ctx); +} + +static void +imageviewset_uint (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + size_t index = *(unsigned *) b->value; + imageviewset_index (a, index, c, ctx); +} + +static void +imageviewset_size_t (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + size_t index = *(size_t *) b->value; + imageviewset_index (a, index, c, ctx); +} + +binop_t imageviewset_binops[] = { + { '.', &cexpr_field, &cexpr_exprval, cexpr_struct_pointer_getfield }, + { '[', &cexpr_int, &imageview_type, imageviewset_int }, + { '[', &cexpr_uint, &imageview_type, imageviewset_uint }, + { '[', &cexpr_size_t, &imageview_type, imageviewset_size_t }, + {} +}; + +static exprsym_t imageviewset_symbols[] = { + {"size", &cexpr_size_t, (void *)field_offset (qfv_imageviewset_t, size)}, { } }; -static exprtab_t imageset_symtab = { - imageset_symbols, +static exprtab_t imageviewset_symtab = { + imageviewset_symbols, }; -exprtype_t imageset_type = { - "imageset", - sizeof (qfv_imageset_t *), - cexpr_struct_pointer_binops, +exprtype_t imageviewset_type = { + "imageviewset", + sizeof (qfv_imageviewset_t *), + imageviewset_binops, 0, - &imageset_symtab, + &imageviewset_symtab, }; static exprsym_t qfv_swapchain_t_symbols[] = { {"format", &VkFormat_type, (void *)field_offset (qfv_swapchain_t, format)}, - {"images", &imageset_type, (void *)field_offset (qfv_swapchain_t, images)}, + {"extent", &VkExtent2D_type, (void *)field_offset (qfv_swapchain_t, extent)}, + {"views", &imageviewset_type, (void *)field_offset (qfv_swapchain_t, imageViews)}, { } }; static exprtab_t qfv_swapchain_t_symtab = { @@ -714,7 +879,7 @@ QFV_InitParse (vulkan_ctx_t *ctx) vkgen_init_symtabs (&context); cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); - cexpr_init_symtab (&imageset_symtab, &context); + cexpr_init_symtab (&imageviewset_symtab, &context); if (!ctx->setLayouts) { ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); @@ -722,6 +887,8 @@ QFV_InitParse (vulkan_ctx_t *ctx) ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx); ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx); ctx->samplers = handlref_symtab (sampler_free, ctx); + ctx->images = handlref_symtab (image_free, ctx); + ctx->imageViews = handlref_symtab (imageView_free, ctx); } } @@ -733,16 +900,17 @@ QFV_GetEnum (const char *name) static int parse_object (vulkan_ctx_t *ctx, plitem_t *plist, - plparser_t parser, void *object) + plparser_t parser, void *object, plitem_t *properties) { plitem_t *messages = PL_NewArray (); exprctx_t exprctx = {}; - parsectx_t parsectx = { &exprctx, ctx }; + parsectx_t parsectx = { &exprctx, ctx, properties }; exprsym_t var_syms[] = { {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {QFV_PROPERTIES, &cexpr_plitem, &ctx->pipelineDef}, + {"swapImageIndex", &cexpr_uint, &ctx->swapImageIndex}, + {QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties}, {} }; exprtab_t vars_tab = { var_syms, 0 }; @@ -775,13 +943,14 @@ parse_qfv_renderpass (const plfield_t *field, const plitem_t *item, void *data, } VkRenderPass -QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_renderpass_t renderpass_data = {}; - if (!parse_object (ctx, plist, parse_qfv_renderpass, &renderpass_data)) { + if (!parse_object (ctx, plist, parse_qfv_renderpass, &renderpass_data, + properties)) { return 0; } @@ -805,7 +974,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) } VkPipeline -QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; @@ -813,11 +982,11 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) memset (&cInfo->a[0], 0, sizeof (cInfo->a[0])); if (!parse_object (ctx, plist, parse_VkGraphicsPipelineCreateInfo, - &cInfo->a[0])) { + &cInfo->a[0], properties)) { return 0; } - cInfo->a[0].renderPass = ctx->renderpass.renderpass; + cInfo->a[0].renderPass = ctx->renderpass; __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); VkPipeline pipeline = plSet->a[0]; free (plSet); @@ -825,14 +994,16 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) } VkDescriptorPool -QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; VkDescriptorPoolCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkDescriptorPoolCreateInfo, &cInfo)) { + if (!parse_object (ctx, plist, parse_VkDescriptorPoolCreateInfo, &cInfo, + properties)) { return 0; } @@ -843,7 +1014,8 @@ QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist) } VkDescriptorSetLayout -QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -851,7 +1023,7 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist) VkDescriptorSetLayoutCreateInfo cInfo = {}; if (!parse_object (ctx, plist, parse_VkDescriptorSetLayoutCreateInfo, - &cInfo)) { + &cInfo, properties)) { return 0; } @@ -862,7 +1034,8 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist) } VkPipelineLayout -QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -870,7 +1043,7 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist) VkPipelineLayoutCreateInfo cInfo = {}; if (!parse_object (ctx, plist, parse_VkPipelineLayoutCreateInfo, - &cInfo)) { + &cInfo, properties)) { return 0; } @@ -881,14 +1054,15 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist) } VkSampler -QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist) +QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; VkSamplerCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkSamplerCreateInfo, &cInfo)) { + if (!parse_object (ctx, plist, parse_VkSamplerCreateInfo, &cInfo, + properties)) { return 0; } @@ -897,3 +1071,195 @@ QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist) return sampler; } + +VkImage +QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkImageCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkImageCreateInfo, &cInfo, + properties)) { + return 0; + } + + VkImage image; + dfunc->vkCreateImage (device->dev, &cInfo, 0, &image); + + return image; +} + +VkImageView +QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkImageViewCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkImageViewCreateInfo, &cInfo, + properties)) { + return 0; + } + + VkImageView imageView; + dfunc->vkCreateImageView (device->dev, &cInfo, 0, &imageView); + + return imageView; +} + +typedef struct { + uint32_t count; + VkImageCreateInfo *info; +} imagecreate_t; + +typedef struct { + uint32_t count; + VkImageViewCreateInfo *info; +} imageviewcreate_t; + +static plelement_t qfv_imagecreate_dict = { + QFDictionary, + sizeof (VkImageCreateInfo), + array_alloc, + parse_VkImageCreateInfo, +}; + +static plelement_t qfv_imageviewcreate_dict = { + QFDictionary, + sizeof (VkImageViewCreateInfo), + array_alloc, + parse_VkImageViewCreateInfo, +}; + +static int +parse_imagecreate_dict (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + plfield_t f = { "images", 0, QFArray, parse_array, + &qfv_imagecreate_dict }; + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr = 0; + int ret; + + if ((ret = PL_ParseLabeledArray (&f, item, &arr, messages, context))) { + imagecreate_t *imagecreate = data; + imagecreate->count = arr->size; + imagecreate->info = (VkImageCreateInfo *) arr->a; + } else { + //FIXME leaky boat when succeeds + if (arr) { + free (arr); + } + } + return ret; +} + +static int +parse_imageviewcreate_dict (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + plfield_t f = { "images", 0, QFArray, parse_array, + &qfv_imageviewcreate_dict }; + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr = 0; + int ret; + + if ((ret = PL_ParseLabeledArray (&f, item, &arr, messages, context))) { + imageviewcreate_t *imageviewcreate = data; + imageviewcreate->count = arr->size; + imageviewcreate->info = (VkImageViewCreateInfo *) arr->a; + } else { + //FIXME leaky boat when succeeds + if (arr) { + free (arr); + } + } + return ret; +} + +qfv_imageset_t * +QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + imagecreate_t create = {}; + + pltype_t type = PL_Type (item); + + if (type == QFDictionary) { + if (!parse_object (ctx, item, parse_imagecreate_dict, &create, + properties)) { + return 0; + } + } else { + Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item)); + return 0; + } + + __auto_type set = QFV_AllocImages (create.count, malloc); + for (uint32_t i = 0; i < create.count; i++) { + dfunc->vkCreateImage (device->dev, &create.info[i], 0, &set->a[i]); + + const char *name = PL_KeyAtIndex (item, i); + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); + QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]); + } + + return set; +} + +qfv_imageviewset_t * +QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, + plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + imageviewcreate_t create = {}; + + pltype_t type = PL_Type (item); + + if (type == QFDictionary) { + if (!parse_object (ctx, item, parse_imageviewcreate_dict, &create, + properties)) { + return 0; + } + } else { + Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item)); + return 0; + } + + __auto_type set = QFV_AllocImageViews (create.count, malloc); + for (uint32_t i = 0; i < create.count; i++) { + dfunc->vkCreateImageView (device->dev, &create.info[i], 0, &set->a[i]); + + const char *name = PL_KeyAtIndex (item, i); + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name); + QFV_AddHandle (ctx->imageViews, name, (uint64_t) set->a[i]); + } + + return set; +} + +VkFramebuffer +QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkFramebufferCreateInfo cInfo = {}; + + if (!parse_object (ctx, plist, parse_VkFramebufferCreateInfo, &cInfo, + properties)) { + return 0; + } + + VkFramebuffer framebuffer; + dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); + + return framebuffer; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index c443e98e3..f8aea8a7f 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -4,6 +4,8 @@ typedef struct parsectx_s { struct exprctx_s *ectx; struct vulkan_ctx_s *vctx; + struct plitem_s *properties; + void *data; } parsectx_t; #include "QF/cexpr.h" @@ -32,12 +34,29 @@ exprenum_t *QFV_GetEnum (const char *name); uint64_t QFV_GetHandle (struct hashtab_s *tab, const char *name); void QFV_AddHandle (struct hashtab_s *tab, const char *name, uint64_t handle); -VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); -VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist); -VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist); +VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); VkDescriptorSetLayout QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, - plitem_t *plist); -VkPipelineLayout QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist); -VkSampler QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist); + plitem_t *plist, + plitem_t *properties); +VkPipelineLayout QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkSampler QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkImage QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkImageView QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +struct qfv_imageset_s *QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +struct qfv_imageviewset_s *QFV_ParseImageViewSet (vulkan_ctx_t *ctx, + plitem_t *plist, + plitem_t *properties); +VkFramebuffer QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index c3a0bfdd9..ced50835a 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -20,6 +20,9 @@ VkGraphicsPipelineCreateInfo, VkDescriptorPoolCreateInfo, VkSamplerCreateInfo, + VkImageCreateInfo, + VkImageViewCreateInfo, + VkFramebufferCreateInfo, ); parse = { VkSubpassDescription = { @@ -282,6 +285,48 @@ fields = (basePipelineHandle); }; basePipelineIndex = auto; + }; + VkImageCreateInfo = { + flags = auto; + imageType = auto; + format = auto; + extent = auto; + mipLevels = auto; + arrayLayers = auto; + samples = auto; + tiling = auto; + usage = auto; + sharingMode = skip; // FIXME for now + queueFamilyIndexCount = skip; // FIXME for now + pQueueFamilyIndices = skip; // FIXME for now + initialLayout = auto; + }; + VkImageViewCreateInfo = { + flags = auto; + image = { + type = (custom, (QFDictionary, QFString), + parse_VkImage); + fields = (image); + }; + viewType = auto; + format = auto; + components = auto; + subresourceRange = auto; + }; + VkFramebufferCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + renderPass = { + type = (custom, QFString, parse_VkShaderModule); + fields = (renderPass); + }; + attachments = { + type = (array, VkImageView); + size = attachmentCount; + values = pAttachments; + }; + width = auto; + height = auto; + layers = auto; } } } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 67598dc96..973e5445b 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -64,16 +64,65 @@ #include "r_internal.h" #include "vid_vulkan.h" -void -Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) +static const char *alias_pass_names[] = { + "depth", + "g-buffer", + "translucent", +}; + +static void +emit_commands (VkCommandBuffer cmd, int pose1, int pose2, + qfv_alias_skin_t *skin, + void *vert_constants, int vert_size, + void *frag_constants, int frag_size, + aliashdr_t *hdr, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + + __auto_type mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); + + VkDeviceSize offsets[] = { + pose1 * hdr->poseverts * sizeof (aliasvrt_t), + pose2 * hdr->poseverts * sizeof (aliasvrt_t), + 0, + }; + VkBuffer buffers[] = { + mesh->vertex_buffer, + mesh->vertex_buffer, + mesh->uv_buffer, + }; + int bindingCount = skin ? 3 : 2; + + dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, + VK_INDEX_TYPE_UINT32); + dfunc->vkCmdPushConstants (cmd, actx->layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, vert_size, vert_constants); + if (skin) { + dfunc->vkCmdPushConstants (cmd, actx->layout, + VK_SHADER_STAGE_FRAGMENT_BIT, + 68, frag_size, frag_constants); + aframe->imageInfo[0].imageView = skin->view; + dfunc->vkCmdPushDescriptorSetKHR (cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + actx->layout, + 0, ALIAS_IMAGE_INFOS, + aframe->descriptors + + ALIAS_BUFFER_INFOS); + } + dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); +} + +void +Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx) +{ + aliasctx_t *actx = ctx->alias_context; + aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; model_t *model = ent->model; aliashdr_t *hdr; - qfv_alias_mesh_t *mesh; qfv_alias_skin_t *skin; float vertex_constants[17]; byte fragment_constants[3][4]; @@ -81,7 +130,6 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) if (!(hdr = model->aliashdr)) { hdr = Cache_Get (&model->cache); } - mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); memcpy (vertex_constants, ent->transform, sizeof (ent->transform)); vertex_constants[16] = R_AliasGetLerpedFrames (ent, hdr); @@ -97,90 +145,26 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) QuatCopy (skin->colora, fragment_constants[1]); QuatCopy (skin->colorb, fragment_constants[2]); - VkDeviceSize offsets[] = { - ent->pose1 * hdr->poseverts * sizeof (aliasvrt_t), - ent->pose2 * hdr->poseverts * sizeof (aliasvrt_t), - 0, - }; - VkBuffer buffers[] = { - mesh->vertex_buffer, - mesh->vertex_buffer, - mesh->uv_buffer, - }; - dfunc->vkCmdBindVertexBuffers (aframe->cmd, 0, 3, buffers, offsets); - dfunc->vkCmdBindIndexBuffer (aframe->cmd, mesh->index_buffer, 0, - VK_INDEX_TYPE_UINT32); - dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, - VK_SHADER_STAGE_VERTEX_BIT, - 0, sizeof (vertex_constants), vertex_constants); - dfunc->vkCmdPushConstants (aframe->cmd, actx->layout, - VK_SHADER_STAGE_FRAGMENT_BIT, - 68, sizeof (fragment_constants), - fragment_constants); - aframe->imageInfo[0].imageView = skin->view; - dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, - 0, ALIAS_IMAGE_INFOS, - aframe->descriptors - + ALIAS_BUFFER_INFOS); - dfunc->vkCmdDrawIndexed (aframe->cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); + emit_commands (aframe->cmdSet.a[QFV_aliasDepth], ent->pose1, ent->pose2, + 0, vertex_constants, sizeof (vertex_constants), + fragment_constants, sizeof (fragment_constants), + hdr, ctx); } static void -calc_lighting (qfv_light_t *light, entity_t *ent) -{ - vec3_t ambient_color; - //FIXME should be ent->position - float l = R_LightPoint (&r_worldentity.model->brush, r_origin) / 128.0; - - //XXX l = max (light, max (ent->model->min_light, ent->min_light)); - light->type = 2; - VectorSet (1, 1, 1, ambient_color); //FIXME - // position doubles as ambient light - VectorScale (ambient_color, l, light->position); - VectorSet (-1, 0, 0, light->direction); //FIXME - VectorCopy (light->position, light->color); -} - -void -Vulkan_AliasBegin (vulkan_ctx_t *ctx) +alias_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline, + vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; - - dlight_t *lights[ALIAS_LIGHTS]; - //XXX quat_t fog; - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = aframe->cmd; - DARRAY_APPEND (cframe->subCommand, cmd); - - //FIXME ambient needs to be per entity - aframe->lights->light_count = 1; - calc_lighting (&aframe->lights->lights[0], 0); - R_FindNearLights (r_origin, ALIAS_LIGHTS - 1, lights); - for (int i = 0; i < ALIAS_LIGHTS - 1; i++) { - if (!lights[i]) { - break; - } - aframe->lights->light_count++; - VectorCopy (lights[i]->color, aframe->lights->lights[i + 1].color); - VectorCopy (lights[i]->origin, aframe->lights->lights[i + 1].position); - aframe->lights->lights[i + 1].dist = lights[i]->radius; - aframe->lights->lights[i + 1].type = 0; - } - - //FIXME need per frame matrices - aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - aframe->bufferInfo[1].buffer = aframe->light_buffer; dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass.renderpass, 0, + ctx->renderpass, 0, cframe->framebuffer, 0, 0, 0, }; @@ -192,7 +176,7 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) dfunc->vkBeginCommandBuffer (cmd, &beginInfo); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->pipeline); + pipeline); //VkDescriptorSet sets[] = { // aframe->descriptors[0].dstSet, // aframe->descriptors[1].dstSet, @@ -213,15 +197,43 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; } -void -Vulkan_AliasEnd (vulkan_ctx_t *ctx) +static void +alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - aliasctx_t *actx = ctx->alias_context; + dfunc->vkEndCommandBuffer (cmd); +} + +void +Vulkan_AliasBegin (vulkan_ctx_t *ctx) +{ + aliasctx_t *actx = ctx->alias_context; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - dfunc->vkEndCommandBuffer (aframe->cmd); + + //XXX quat_t fog; + DARRAY_APPEND (&cframe->cmdSets[QFV_passDepth], + aframe->cmdSet.a[QFV_aliasDepth]); + DARRAY_APPEND (&cframe->cmdSets[QFV_passGBuffer], + aframe->cmdSet.a[QFV_aliasGBuffer]); + + //FIXME need per frame matrices + aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + + alias_begin_subpass (aframe->cmdSet.a[QFV_aliasDepth], actx->depth, ctx); + alias_begin_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], actx->gbuf, ctx); +} + +void +Vulkan_AliasEnd (vulkan_ctx_t *ctx) +{ + aliasctx_t *actx = ctx->alias_context; + aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + + alias_end_subpass (aframe->cmdSet.a[QFV_aliasDepth], ctx); + alias_end_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], ctx); } static VkDescriptorBufferInfo base_buffer_info = { @@ -247,7 +259,6 @@ void Vulkan_Alias_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); ctx->alias_context = actx; @@ -257,7 +268,8 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&actx->frames, frames); actx->frames.grow = 0; - actx->pipeline = Vulkan_CreatePipeline (ctx, "alias"); + actx->depth = Vulkan_CreatePipeline (ctx, "alias_depth"); + actx->gbuf = Vulkan_CreatePipeline (ctx, "alias_gbuf"); actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); @@ -276,43 +288,22 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) }*/ //__auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool"); - __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); - - __auto_type lbuffers = QFV_AllocBufferSet (frames, alloca); - for (size_t i = 0; i < frames; i++) { - lbuffers->a[i] = QFV_CreateBuffer (device, sizeof (qfv_light_buffer_t), - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, - lbuffers->a[i], - va (ctx->va_ctx, "buffer:alias:%s:%zd", - "lights", i)); - } - VkMemoryRequirements requirements; - dfunc->vkGetBufferMemoryRequirements (device->dev, lbuffers->a[0], - &requirements); - actx->light_memory = QFV_AllocBufferMemory (device, lbuffers->a[0], - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - frames * requirements.size, 0); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - actx->light_memory, va (ctx->va_ctx, - "memory:alias:%s", "lights")); - byte *light_data; - dfunc->vkMapMemory (device->dev, actx->light_memory, 0, - frames * requirements.size, 0, (void **) &light_data); - //__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < frames; i++) { __auto_type aframe = &actx->frames.a[i]; - aframe->cmd = cmdBuffers->a[i]; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - aframe->cmd, - va (ctx->va_ctx, "cmd:alias:%zd", i)); - aframe->light_buffer = lbuffers->a[i]; - aframe->lights = (qfv_light_buffer_t *) (light_data + i * requirements.size); - QFV_BindBufferMemory (device, lbuffers->a[i], actx->light_memory, - i * requirements.size); + DARRAY_INIT (&aframe->cmdSet, QFV_aliasNumPasses); + DARRAY_RESIZE (&aframe->cmdSet, QFV_aliasNumPasses); + aframe->cmdSet.grow = 0; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &aframe->cmdSet); + + for (int j = 0; j < QFV_aliasNumPasses; j++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + aframe->cmdSet.a[j], + va (ctx->va_ctx, "cmd:alias:%zd:%s", i, + alias_pass_names[j])); + } for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) { aframe->bufferInfo[j] = base_buffer_info; aframe->descriptors[j] = base_buffer_write; @@ -333,7 +324,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) } void -Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx) +Vulkan_Alias_Shutdown (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -341,11 +332,11 @@ Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx) for (size_t i = 0; i < actx->frames.size; i++) { __auto_type aframe = &actx->frames.a[i]; - dfunc->vkDestroyBuffer (device->dev, aframe->light_buffer, 0); + free (aframe->cmdSet.a); } - dfunc->vkFreeMemory (device->dev, actx->light_memory, 0); - dfunc->vkDestroyPipeline (device->dev, actx->pipeline, 0); - DARRAY_CLEAR (&actx->frames); + dfunc->vkDestroyPipeline (device->dev, actx->depth, 0); + dfunc->vkDestroyPipeline (device->dev, actx->gbuf, 0); + free (actx->frames.a); free (actx); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 7028aa754..895caed49 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -69,6 +69,12 @@ #include "r_internal.h" #include "vid_vulkan.h" +static const char *bsp_pass_names[] = { + "depth", + "g-buffer", + "translucent", +}; + static float identity[] = { 1, 0, 0, 0, 0, 1, 0, 0, @@ -779,33 +785,44 @@ bind_view (qfv_bsp_tex tex, VkImageView view, bspframe_t *bframe, + BSP_BUFFER_INFOS); } +static void +push_transform (vec_t *transform, VkPipelineLayout layout, + qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) +{ + dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, + 0, 16 * sizeof (float), transform); +} + +static void +push_fragconst (fragconst_t *fragconst, VkPipelineLayout layout, + qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) +{ + dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, + 0, sizeof (fragconst_t), fragconst); +} + +static void +push_descriptors (int count, VkWriteDescriptorSet *descriptors, + VkPipelineLayout layout, qfv_devfuncs_t *dfunc, + VkCommandBuffer cmd) +{ + dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, count, descriptors); +} + static void draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) { elements_t *el; - /*if (colloc >= 0) { - float *color; - color = ec->color; - if (!color) - color = bctx->default_color; - if (!QuatCompare (color, bctx->last_color)) { - QuatCopy (color, bctx->last_color); - qfeglVertexAttrib4fv (quake_bsp.color.location, color); - } - }*/ if (ec->transform) { - dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), ec->transform); + push_transform (ec->transform, layout, dfunc, cmd); } else { //FIXME should cache current transform - dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), identity); + push_transform (identity, layout, dfunc, cmd); } for (el = ec->elements; el; el = el->next) { - //FIXME check if these are contiguous and if so merge into one - //command if (!el->index_count) continue; dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index, @@ -828,35 +845,18 @@ get_view (qfv_tex_t *tex, qfv_tex_t *default_tex) } static void -bsp_begin (vulkan_ctx_t *ctx) +bsp_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; - //XXX quat_t fog; - - bctx->default_color[3] = 1; - QuatCopy (bctx->default_color, bctx->last_color); - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = bframe->bsp_cmd; - DARRAY_APPEND (cframe->subCommand, cmd); - - //FIXME need per frame matrices - bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - bframe->imageInfo[0].imageView = 0; // set by tex chain loop - bframe->imageInfo[1].imageView = 0; // set by tex chain loop - bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); - bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, - bctx->default_skysheet); - bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, - bctx->default_skybox); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass.renderpass, 0, + ctx->renderpass, 0, cframe->framebuffer, 0, 0, 0, }; @@ -868,7 +868,7 @@ bsp_begin (vulkan_ctx_t *ctx) dfunc->vkBeginCommandBuffer (cmd, &beginInfo); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->main); + pipeline); VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); @@ -893,14 +893,54 @@ bsp_begin (vulkan_ctx_t *ctx) } static void -bsp_end (vulkan_ctx_t *ctx) +bsp_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - bspctx_t *bctx = ctx->bsp_context; + dfunc->vkEndCommandBuffer (cmd); +} + +static void +bsp_begin (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + //XXX quat_t fog; + + bctx->default_color[3] = 1; + QuatCopy (bctx->default_color, bctx->last_color); + + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - dfunc->vkEndCommandBuffer (bframe->bsp_cmd); + + DARRAY_APPEND (&cframe->cmdSets[QFV_passDepth], + bframe->cmdSet.a[QFV_bspDepth]); + DARRAY_APPEND (&cframe->cmdSets[QFV_passGBuffer], + bframe->cmdSet.a[QFV_bspGBuffer]); + + //FIXME need per frame matrices + bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + bframe->imageInfo[0].imageView = 0; // set by tex chain loop + bframe->imageInfo[1].imageView = 0; // set by tex chain loop + bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); + bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, + bctx->default_skysheet); + bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, + bctx->default_skybox); + + //FIXME pipeline + bsp_begin_subpass (bframe->cmdSet.a[QFV_bspDepth], bctx->main, ctx); + bsp_begin_subpass (bframe->cmdSet.a[QFV_bspGBuffer], bctx->main, ctx); +} + +static void +bsp_end (vulkan_ctx_t *ctx) +{ + bspctx_t *bctx = ctx->bsp_context; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; + + bsp_end_subpass (bframe->cmdSet.a[QFV_bspDepth], ctx); + bsp_end_subpass (bframe->cmdSet.a[QFV_bspGBuffer], ctx); } /*static void @@ -982,8 +1022,6 @@ spin (mat4_t mat, bspctx_t *bctx) static void sky_begin (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; bctx->default_color[3] = 1; @@ -993,8 +1031,10 @@ sky_begin (vulkan_ctx_t *ctx) __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = bframe->sky_cmd; - DARRAY_APPEND (cframe->subCommand, cmd); + + //FIXME where should skys go? g-buffer is overkill. Translucent pre-pass? + DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], + bframe->cmdSet.a[QFV_bspTranslucent]); //FIXME need per frame matrices bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; @@ -1006,54 +1046,18 @@ sky_begin (vulkan_ctx_t *ctx) bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, bctx->default_skybox); - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass.renderpass, 0, - cframe->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->sky); - VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; - VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; - dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); - - VkDeviceSize offsets[] = { 0 }; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &bctx->vertex_buffer, offsets); - dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, - VK_INDEX_TYPE_UINT32); - - // push VP matrices - dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, - 0, 1, bframe->descriptors + 0); - // push static images - dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, - 0, 5, bframe->descriptors + 1); - - //XXX glsl_Fog_GetColor (fog); - //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; + //FIXME sky pass + bsp_begin_subpass (bframe->cmdSet.a[QFV_bspTranslucent], bctx->sky, ctx); } static void sky_end (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - dfunc->vkEndCommandBuffer (bframe->sky_cmd); + + //FIXME sky pass + bsp_end_subpass (bframe->cmdSet.a[QFV_bspTranslucent], ctx); } static inline void @@ -1133,13 +1137,13 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) Vulkan_FlushLightmaps (ctx); bsp_begin (ctx); - dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, - VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), identity); + push_transform (identity, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspDepth]); + push_transform (identity, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); fragconst_t frag_constants = { time: vr_data.realtime }; - dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, - VK_SHADER_STAGE_FRAGMENT_BIT, - 64, sizeof (fragconst_t), &frag_constants); + push_fragconst (&frag_constants, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); for (size_t i = 0; i < bctx->texture_chains.size; i++) { vulktex_t *tex; @@ -1153,13 +1157,15 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) ctx->default_white); bframe->imageInfo[1].imageView = get_view (tex->glow, ctx->default_black); - dfunc->vkCmdPushDescriptorSetKHR (bframe->bsp_cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, - 0, 2, bframe->descriptors + 1); + + push_descriptors (2, bframe->descriptors + 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, bframe->bsp_cmd); + draw_elechain (ec, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspDepth]); + draw_elechain (ec, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1246,22 +1252,24 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) return; sky_begin (ctx); - dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, - VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), identity); + //FIXME sky pass + push_transform (identity, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTranslucent]); fragconst_t frag_constants = { time: vr_data.realtime }; - dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, - VK_SHADER_STAGE_FRAGMENT_BIT, - 64, sizeof (fragconst_t), &frag_constants); + push_fragconst (&frag_constants, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTranslucent]); for (is = bctx->sky_chain; is; is = is->tex_chain) { surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black), - bframe, bframe->sky_cmd, bctx->layout, dfunc); + bframe, + bframe->cmdSet.a[QFV_bspTranslucent],//FIXME + bctx->layout, dfunc); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, bframe->sky_cmd); + draw_elechain (ec, bctx->layout, dfunc,//FIXME + bframe->cmdSet.a[QFV_bspTranslucent]); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1271,11 +1279,12 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - bind_view (qfv_bsp_skysheet, - get_view (tex->tex, ctx->default_black), - bframe, bframe->sky_cmd, bctx->layout, dfunc); + bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black), + bframe, bframe->cmdSet.a[QFV_bspTranslucent],//FIXME + bctx->layout, dfunc); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, bframe->sky_cmd); + draw_elechain (ec, bctx->layout, dfunc,//FIXME + bframe->cmdSet.a[QFV_bspTranslucent]); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1453,23 +1462,21 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); - __auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca); - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); - for (size_t i = 0; i < frames; i++) { __auto_type bframe = &bctx->frames.a[i]; - bframe->bsp_cmd = cmdBuffers->a[i * 3 + 0]; - bframe->turb_cmd = cmdBuffers->a[i * 3 + 1]; - bframe->sky_cmd = cmdBuffers->a[i * 3 + 2]; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - bframe->bsp_cmd, - va (ctx->va_ctx, "cmd:bsp:%zd", i)); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - bframe->turb_cmd, - va (ctx->va_ctx, "cmd:turb:%zd", i)); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - bframe->sky_cmd, - va (ctx->va_ctx, "cmd:sky:%zd", i)); + + DARRAY_INIT (&bframe->cmdSet, QFV_bspNumPasses); + DARRAY_RESIZE (&bframe->cmdSet, QFV_bspNumPasses); + bframe->cmdSet.grow = 0; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &bframe->cmdSet); + + for (int j = 0; j < QFV_bspNumPasses; j++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + bframe->cmdSet.a[i], + va (ctx->va_ctx, "cmd:bsp:%zd:%s", i, + bsp_pass_names[j])); + } for (int j = 0; j < BSP_BUFFER_INFOS; j++) { bframe->bufferInfo[j] = base_buffer_info; @@ -1495,6 +1502,11 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; + for (size_t i = 0; i < bctx->frames.size; i++) { + __auto_type bframe = &bctx->frames.a[i]; + free (bframe->cmdSet.a); + } + dfunc->vkDestroyPipeline (device->dev, bctx->main, 0); dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0); DARRAY_CLEAR (&bctx->texture_chains); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 93b73d7b3..43b246273 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -696,7 +696,8 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = dframe->cmd; - DARRAY_APPEND (cframe->subCommand, cmd); + //FIXME which pass? + DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], cmd); VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, @@ -708,7 +709,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass.renderpass, 0, + ctx->renderpass, 0, cframe->framebuffer, 0, 0, 0 }; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 0132bf6d0..a6f444798 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -78,6 +78,10 @@ static const char quakeforge_pipeline[] = #include "libs/video/renderer/vulkan/qfpipeline.plc" ; +static const char quakeforge_renderpass[] = +#include "libs/video/renderer/vulkan/deferred.plc" +; + cvar_t *vulkan_frame_count; cvar_t *vulkan_presentation_mode; cvar_t *msaaSamples; @@ -163,6 +167,7 @@ void Vulkan_Init_Common (vulkan_ctx_t *ctx) { Sys_Printf ("Vulkan_Init_Common\n"); + QFV_InitParse (ctx); Vulkan_Init_Cvars (); ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version @@ -185,9 +190,9 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) QFV_DestroyPipeline (ctx->device, ctx->pipeline); } if (ctx->frames.size) { - Vulkan_DestroyFramebuffers (ctx); + Vulkan_DestroyFrames (ctx); } - if (ctx->renderpass.colorImage) { + if (ctx->renderpass) { Vulkan_DestroyRenderPass (ctx); } if (ctx->swapchain) { @@ -216,6 +221,15 @@ void Vulkan_CreateDevice (vulkan_ctx_t *ctx) { ctx->device = QFV_CreateDevice (ctx, device_extensions); + + //FIXME msaa and deferred rendering... + //also, location + ctx->msaaSamples = 1; + /*ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val, + QFV_GetMaxSampleCount (device->physDev)); + if (ctx->msaaSamples > 1) { + name = "renderpass_msaa"; + }*/ } void @@ -257,138 +271,54 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) return item; } +static plitem_t * +qfv_load_renderpass (vulkan_ctx_t *ctx, const char *name) +{ + if (!ctx->renderpassDef) { + ctx->renderpassDef = PL_GetPropertyList (quakeforge_renderpass, + &ctx->hashlinks); + } + + plitem_t *item = ctx->renderpassDef; + if (!item || !(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading %s\n", name); + } else { + Sys_Printf ("Found %s def\n", name); + } + return item; +} + +static size_t +get_image_size (VkImage image, qfv_device_t *device) +{ + qfv_devfuncs_t *dfunc = device->funcs; + size_t size; + size_t align; + + VkMemoryRequirements requirements; + dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements); + size = requirements.size; + align = requirements.alignment - 1; + size = (size + align) & ~(align); + return size; +} + void Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) { const char *name = "renderpass";//FIXME - qfv_device_t *device = ctx->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *df = device->funcs; - VkCommandBuffer cmd = ctx->cmdbuffer; - qfv_swapchain_t *sc = ctx->swapchain; - ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val, - QFV_GetMaxSampleCount (device->physDev)); - if (ctx->msaaSamples > 1) { - name = "renderpass_msaa"; - } + plitem_t *item = qfv_load_renderpass (ctx, name); - //FIXME a tad inconsistent - plitem_t *item = qfv_load_pipeline (ctx, name); - if (!item) { - return; - } - - qfv_imageresource_t *colorImage = malloc (sizeof (*colorImage)); - qfv_imageresource_t *depthImage = malloc (sizeof (*depthImage)); - - VkExtent3D extent = {sc->extent.width, sc->extent.height, 1}; - - Sys_MaskPrintf (SYS_VULKAN, "color resource\n"); - colorImage->image - = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - sc->format, extent, 1, 1, ctx->msaaSamples, - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT - | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - colorImage->object - = QFV_AllocImageMemory (device, colorImage->image, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); - QFV_BindImageMemory (device, colorImage->image, colorImage->object, 0); - colorImage->view - = QFV_CreateImageView (device, colorImage->image, - VK_IMAGE_VIEW_TYPE_2D, - sc->format, VK_IMAGE_ASPECT_COLOR_BIT); - Sys_MaskPrintf (SYS_VULKAN, " image: %p object: %p view:%p\n", - colorImage->image, colorImage->object, colorImage->view); - - Sys_MaskPrintf (SYS_VULKAN, "depth resource\n"); - VkFormat depthFormat = VK_FORMAT_D32_SFLOAT; - depthImage->image - = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - depthFormat, extent, 1, 1, ctx->msaaSamples, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); - depthImage->object - = QFV_AllocImageMemory (device, depthImage->image, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0); - QFV_BindImageMemory (device, depthImage->image, depthImage->object, 0); - depthImage->view - = QFV_CreateImageView (device, depthImage->image, - VK_IMAGE_VIEW_TYPE_2D, - depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); - Sys_MaskPrintf (SYS_VULKAN, " image: %p object: %p view:%p\n", - depthImage->image, depthImage->object, depthImage->view); - - VkImageMemoryBarrier barrier; - qfv_pipelinestagepair_t stages; - - df->vkWaitForFences (dev, 1, &ctx->fence, VK_TRUE, ~0ull); - df->vkResetCommandBuffer (cmd, 0); - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0, - }; - df->vkBeginCommandBuffer (cmd, &beginInfo); - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_Color]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_Color]; - barrier.image = colorImage->image; - - df->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, - 0, 0, - 0, 0, - 1, &barrier); - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_DepthStencil]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_DepthStencil]; - barrier.image = depthImage->image; - if (depthFormat == VK_FORMAT_D32_SFLOAT_S8_UINT - || depthFormat == VK_FORMAT_D24_UNORM_S8_UINT) { - barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - - df->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0, - 0, 0, - 0, 0, - 1, &barrier); - df->vkEndCommandBuffer (cmd); - - VkSubmitInfo submitInfo = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 0, 0, 0, - 1, &cmd, - 0, 0 - }; - df->vkResetFences (dev, 1, &ctx->fence); - df->vkQueueSubmit (device->queue.queue, 1, &submitInfo, ctx->fence); - - ctx->renderpass.colorImage = colorImage; - ctx->renderpass.depthImage = depthImage; - ctx->renderpass.renderpass = QFV_ParseRenderPass (ctx, item); + ctx->renderpass = QFV_ParseRenderPass (ctx, item, ctx->renderpassDef); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, - ctx->renderpass.renderpass, - va (ctx->va_ctx, "pipeline:%s", name)); + ctx->renderpass, va (ctx->va_ctx, "renderpass:%s", + name)); } void Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *df = device->funcs; - - df->vkDestroyRenderPass (dev, ctx->renderpass.renderpass, 0); - - df->vkDestroyImageView (dev, ctx->renderpass.colorImage->view, 0); - df->vkDestroyImage (dev, ctx->renderpass.colorImage->image, 0); - df->vkFreeMemory (dev, ctx->renderpass.colorImage->object, 0); - free (ctx->renderpass.colorImage); - ctx->renderpass.colorImage = 0; - - df->vkDestroyImageView (dev, ctx->renderpass.depthImage->view, 0); - df->vkDestroyImage (dev, ctx->renderpass.depthImage->image, 0); - df->vkFreeMemory (dev, ctx->renderpass.depthImage->object, 0); - free (ctx->renderpass.depthImage); - ctx->renderpass.depthImage = 0; } VkPipeline @@ -401,7 +331,7 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found pipeline def %s\n", name); } - VkPipeline pipeline = QFV_ParsePipeline (ctx, item); + VkPipeline pipeline = QFV_ParsePipeline (ctx, item, ctx->pipelineDef); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, va (ctx->va_ctx, "pipeline:%s", name)); return pipeline; @@ -425,7 +355,7 @@ Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found descriptor pool def %s\n", name); } - pool = QFV_ParseDescriptorPool (ctx, item); + pool = QFV_ParseDescriptorPool (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) pool); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool, va (ctx->va_ctx, "descriptor_pool:%s", name)); @@ -450,7 +380,7 @@ Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found pipeline layout def %s\n", name); } - layout = QFV_ParsePipelineLayout (ctx, item); + layout = QFV_ParsePipelineLayout (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) layout); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, va (ctx->va_ctx, "pipeline_layout:%s", name)); @@ -475,7 +405,7 @@ Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found sampler def %s\n", name); } - sampler = QFV_ParseSampler (ctx, item); + sampler = QFV_ParseSampler (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) sampler); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler, va (ctx->va_ctx, "sampler:%s", name)); @@ -500,7 +430,7 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) } else { Sys_Printf ("Found descriptor set def %s\n", name); } - set = QFV_ParseDescriptorSetLayout (ctx, item); + set = QFV_ParseDescriptorSetLayout (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) set); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, set, va (ctx->va_ctx, "descriptor_set:%s", name)); @@ -508,7 +438,7 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) } void -Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) +Vulkan_CreateFrames (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; VkCommandPool cmdpool = ctx->cmdpool; @@ -531,13 +461,16 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) frame->renderDoneSemaphore = QFV_CreateSemaphore (device); frame->cmdBuffer = cmdBuffers->a[i]; - frame->subCommand = malloc (sizeof (qfv_cmdbufferset_t)); - DARRAY_INIT (frame->subCommand, 4); + frame->cmdSetCount = QFV_NumPasses; + frame->cmdSets = malloc (QFV_NumPasses * sizeof (qfv_cmdbufferset_t)); + for (int j = 0; j < QFV_NumPasses; j++) { + DARRAY_INIT (&frame->cmdSets[j], 4); + } } } void -Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) +Vulkan_DestroyFrames (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *df = device->funcs; @@ -553,3 +486,59 @@ Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) DARRAY_CLEAR (&ctx->frames); } + +void +Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + plitem_t *item = qfv_load_renderpass (ctx, "images"); + if (!item) { + return; + } + + __auto_type images = QFV_ParseImageSet (ctx, item, ctx->renderpassDef); + ctx->attachment_images = images; + size_t memSize = 0; + for (size_t i = 0; i < images->size; i++) { + memSize += get_image_size (images->a[i], device); + } + VkDeviceMemory mem; + mem = QFV_AllocImageMemory (device, images->a[0], + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + memSize, 0); + ctx->attachmentMemory = mem; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + mem, "memory:framebuffers"); + size_t offset = 0; + for (size_t i = 0; i < images->size; i++) { + QFV_BindImageMemory (device, images->a[i], mem, offset); + offset += get_image_size (images->a[i], device); + } + + item = qfv_load_renderpass (ctx, "imageViews"); + if (!item) { + return; + } + + __auto_type views = QFV_ParseImageViewSet (ctx, item, ctx->renderpassDef); + ctx->attachment_views = views; + + item = qfv_load_renderpass (ctx, "framebuffer"); + if (!item) { + return; + } + + ctx->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, + malloc); + for (size_t i = 0; i < ctx->framebuffers->size; i++) { + ctx->swapImageIndex = i; + ctx->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, + ctx->renderpassDef); + } +} + +void +Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) +{ +} From 4bda49d79867d3139093994cb4e20d5085348bbd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 17 Feb 2021 13:29:53 +0900 Subject: [PATCH 1331/3664] [util] Correct the lex priority for int constants The actual need to specify unsigned int constant is a bit of a pain, but not being able to do so due to lex priority errors is even more of a pain. --- libs/util/cexpr-lex.l | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index 46fbcdd55..b82724af4 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -120,13 +120,13 @@ STRING \"(\\.|[^"\\])*\" __auto_type context = yyget_extra (yyscanner); %} -{INT}+ { - yylval->value = parse_int (yytext, context); +{INT}+[uU] { + yylval->value = parse_uint (yytext, context); return VALUE; } -{INT}+[uU] { - yylval->value = parse_uint (yytext, context); +{INT}+ { + yylval->value = parse_int (yytext, context); return VALUE; } From b08c3881b9988876e71e722b8d7afe9e953504c0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 17 Feb 2021 13:32:04 +0900 Subject: [PATCH 1332/3664] [vulkan] Add a comment about using size_t Due to wanting to access array sizes when parsing uint32_t type values, parse_uint32_t needs to handle size_t values even though it throws out any excess bits. --- libs/video/renderer/vulkan/vkparse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 2d9b3c806..ee8efb8a4 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -182,9 +182,11 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { int ret = 1; + // use size_t (and cexpr_size_t) for val so references to array sizes + // can be used size_t val = 0; - exprctx_t ectx = *((parsectx_t *) context)->ectx; exprval_t result = { &cexpr_size_t, &val }; + exprctx_t ectx = *((parsectx_t *) context)->ectx; ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); From 64740b0f730257255892bb7160761ef60a813a88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 17 Feb 2021 13:35:19 +0900 Subject: [PATCH 1333/3664] [vulkan] Create shaders for alias deferred rendering A simple (no uv output) vertex shader that still blends the two frames, and the relevant g-buffer fragment shader. --- libs/video/renderer/Makemodule.am | 10 ++++++ libs/video/renderer/vulkan/qfpipeline.plist | 10 +++--- libs/video/renderer/vulkan/shader.c | 6 ++++ .../renderer/vulkan/shader/alias_depth.vert | 28 ++++++++++++++++ .../renderer/vulkan/shader/alias_gbuf.frag | 32 +++++++++++++++++++ 5 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/alias_depth.vert create mode 100644 libs/video/renderer/vulkan/shader/alias_gbuf.frag diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 66db70d11..4194b1f8b 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -278,6 +278,10 @@ aliasv_src = $(vkshaderpath)/alias.vert aliasv_c = $(vkshaderpath)/alias.vert.spvc aliasf_src = $(vkshaderpath)/alias.frag aliasf_c = $(vkshaderpath)/alias.frag.spvc +alias_depth_src = $(vkshaderpath)/alias_depth.vert +alias_depth_c = $(vkshaderpath)/alias_depth.vert.spvc +alias_gbuf_src = $(vkshaderpath)/alias_gbuf.frag +alias_gbuf_c = $(vkshaderpath)/alias_gbuf.frag.spvc passthrough_src = $(vkshaderpath)/passthrough.vert passthrough_c = $(vkshaderpath)/passthrough.vert.spvc pushcolor_src = $(vkshaderpath)/pushcolor.frag @@ -293,8 +297,12 @@ $(quakebspf_c): $(quakebspf_src) $(aliasv_c): $(aliasv_src) +$(alias_depth_c): $(alias_depth_src) + $(aliasf_c): $(aliasf_src) +$(alias_gbuf_c): $(alias_gbuf_src) + $(passthrough_c): $(passthrough_src) $(pushcolor_c): $(pushcolor_src) @@ -305,7 +313,9 @@ vkshader_c = \ $(quakebspv_c) \ $(quakebspf_c) \ $(aliasv_c) \ + $(alias_depth_c) \ $(aliasf_c) \ + $(alias_gbuf_c) \ $(passthrough_c) \ $(pushcolor_c) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 2cd110385..faf35b779 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -278,7 +278,7 @@ { stage = vertex; name = main; - module = $builtin/alias.vert; + module = $builtin/alias_depth.vert; }, ); vertexInput = { @@ -321,7 +321,7 @@ { stage = fragment; name = main; - module = $builtin/alias.frag; + module = $builtin/alias_gbuf.frag; specializationInfo = { mapEntries = ( { size = 4; offset = 0; constantID = 0; }, @@ -447,7 +447,7 @@ { stage = vertex; name = main; - module = $builtin/quakebsp.vert; + module = $builtin/bsp_depth.vert; }, ); vertexInput = { @@ -481,12 +481,12 @@ { stage = vertex; name = main; - module = $builtin/quakebsp.vert; + module = $builtin/bsp_gbuf.vert; }, { stage = fragment; name = main; - module = $builtin/quakebsp.frag; + module = $builtin/bsp_gbuf.frag; }, ); vertexInput = { diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 90a93684b..857d457d4 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -65,8 +65,12 @@ static static #include "libs/video/renderer/vulkan/shader/alias.vert.spvc" static +#include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc" +static #include "libs/video/renderer/vulkan/shader/alias.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/alias_gbuf.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc" static #include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc" @@ -83,7 +87,9 @@ static shaderdata_t builtin_shaders[] = { { "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) }, { "quakebsp.frag", quakebsp_frag, sizeof (quakebsp_frag) }, { "alias.vert", alias_vert, sizeof (alias_vert) }, + { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, { "alias.frag", alias_frag, sizeof (alias_frag) }, + { "alias_gbuf.frag", alias_gbuf_frag, sizeof (alias_gbuf_frag) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, {} diff --git a/libs/video/renderer/vulkan/shader/alias_depth.vert b/libs/video/renderer/vulkan/shader/alias_depth.vert new file mode 100644 index 000000000..44437788e --- /dev/null +++ b/libs/video/renderer/vulkan/shader/alias_depth.vert @@ -0,0 +1,28 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection; + mat4 View; + mat4 Sky; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; + float blend; +}; + +layout (location = 0) in vec4 vertexa; +layout (location = 1) in vec3 normala; +layout (location = 2) in vec4 vertexb; +layout (location = 3) in vec3 normalb; + +void +main (void) +{ + vec4 vertex; + vec4 pos; + + vertex = mix (vertexa, vertexb, blend); + pos = (Model * vertex); + gl_Position = Projection * (View * pos); +} diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag new file mode 100644 index 000000000..e8b14a305 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -0,0 +1,32 @@ +#version 450 +layout (set = 0, binding = 2) uniform sampler2DArray Skin; + +layout (push_constant) uniform PushConstants { + layout (offset = 68) + uint base_color; + uint colorA; + uint colorB; + vec4 fog; + vec4 color; +}; + +layout (location = 0) in vec2 st; +layout (location = 1) in vec3 position; +layout (location = 2) in vec3 normal; + +layout (location = 0) out vec4 frag_color; +layout (location = 1) out vec4 frag_normal; + +void +main (void) +{ + vec4 c; + int i; + vec3 light = vec3 (0); + c = texture (Skin, vec3 (st, 0)) * unpackUnorm4x8(base_color); + c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA); + c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB); + + frag_color = c; + frag_normal = vec4(normal, 0); +} From 4245c6ad3bcc0f460dbe34a23df28d3a1dcd5008 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 17 Feb 2021 13:50:36 +0900 Subject: [PATCH 1334/3664] [vulkan] Specify subpass number in pipeline def This gets the alias model render pass and pipeline passing validation. I don't know why I didn't add the subpass field to the VkGraphicsPipelineCreateInfo parser def, though it could be I simply missed it, or I thought I wouldn't need it at the time. --- libs/video/renderer/vulkan/qfpipeline.plist | 34 +++++++++++++++------ libs/video/renderer/vulkan/vkparse.plist | 1 + 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index faf35b779..2892f5fec 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -274,6 +274,7 @@ }; pipelines = { alias_depth = { + subpass = 0; stages = ( { stage = vertex; @@ -312,6 +313,7 @@ //renderPass = renderpass; }; alias_gbuf = { + subpass = 1; stages = ( { stage = vertex; @@ -425,16 +427,28 @@ }; colorBlend = { logicOpEnable = false; - attachments = ({ - blendEnable = true; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }); + attachments = ( + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, + ); }; dynamic = { dynamicState = ( viewport, scissor, blend_constants ); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index ced50835a..9eb5e7e04 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -280,6 +280,7 @@ type = (custom, QFString, parse_VkPipelineLayout); fields = (layout); }; + subpass = auto; basePipelineHandle = { type = (custom, QFString, parse_BasePipeline); fields = (basePipelineHandle); From cbc8ad271ab50e842e18c0aefa021de45b73a674 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Feb 2021 11:14:54 +0900 Subject: [PATCH 1335/3664] [vulkan] Convert bsp and draw to deferred This has bsp and draw passing muster with the validation layers. --- include/QF/Vulkan/qf_alias.h | 6 +- include/QF/Vulkan/qf_bsp.h | 7 +- include/QF/Vulkan/qf_vid.h | 2 +- libs/video/renderer/Makemodule.am | 21 +++ libs/video/renderer/vulkan/device.c | 4 +- libs/video/renderer/vulkan/qfpipeline.plist | 60 ++++++--- libs/video/renderer/vulkan/shader.c | 12 ++ .../renderer/vulkan/shader/bsp_depth.vert | 19 +++ .../renderer/vulkan/shader/bsp_gbuf.frag | 126 ++++++++++++++++++ .../renderer/vulkan/shader/bsp_gbuf.geom | 29 ++++ .../renderer/vulkan/shader/bsp_gbuf.vert | 25 ++++ libs/video/renderer/vulkan/vulkan_alias.c | 9 +- libs/video/renderer/vulkan/vulkan_bsp.c | 21 +-- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- 14 files changed, 304 insertions(+), 39 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/bsp_depth.vert create mode 100644 libs/video/renderer/vulkan/shader/bsp_gbuf.frag create mode 100644 libs/video/renderer/vulkan/shader/bsp_gbuf.geom create mode 100644 libs/video/renderer/vulkan/shader/bsp_gbuf.vert diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 597888a4d..5f3964a2b 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -65,13 +65,13 @@ typedef struct qfv_alias_skin_s { #define ALIAS_BUFFER_INFOS 1 #define ALIAS_IMAGE_INFOS 1 -enum { +typedef enum { QFV_aliasDepth, QFV_aliasGBuffer, - //QFV_aliasTranslucent, + QFV_aliasTranslucent, QFV_aliasNumPasses -}; +} QFV_AliasSubpass; typedef struct aliasframe_s { qfv_cmdbufferset_t cmdSet; diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index b78aaf643..ff3f6612a 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -70,13 +70,13 @@ typedef enum { // Texture, GlowMap, LightMap, SkySheet, SkyCube #define BSP_IMAGE_INFOS 5 -enum { +typedef enum { QFV_bspDepth, QFV_bspGBuffer, QFV_bspTranslucent, QFV_bspNumPasses -}; +} QFV_BspSubpass; typedef struct bspframe_s { uint32_t *index_data; // pointer into mega-buffer for this frame (c) @@ -143,7 +143,8 @@ typedef struct bspctx_s { VkSampler sampler; VkDeviceMemory texture_memory; - VkPipeline main; + VkPipeline depth; + VkPipeline gbuf; VkPipeline sky; VkPipelineLayout layout; size_t vertex_buffer_size; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index f81e934a1..db423d014 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -39,8 +39,8 @@ enum { QFV_passDepth, // geometry QFV_passGBuffer, // geometry - QFV_passTranslucent, // geometry QFV_passLighting, // single quad + QFV_passTranslucent, // geometry QFV_passCompose, // single quad QFV_NumPasses diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 4194b1f8b..a5c3fc1a0 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -274,6 +274,15 @@ quakebspv_src = $(vkshaderpath)/quakebsp.vert quakebspv_c = $(vkshaderpath)/quakebsp.vert.spvc quakebspf_src = $(vkshaderpath)/quakebsp.frag quakebspf_c = $(vkshaderpath)/quakebsp.frag.spvc + +bsp_depth_src = $(vkshaderpath)/bsp_depth.vert +bsp_depth_c = $(vkshaderpath)/bsp_depth.vert.spvc +bsp_gbufv_src = $(vkshaderpath)/bsp_gbuf.vert +bsp_gbufv_c = $(vkshaderpath)/bsp_gbuf.vert.spvc +bsp_gbufg_src = $(vkshaderpath)/bsp_gbuf.geom +bsp_gbufg_c = $(vkshaderpath)/bsp_gbuf.geom.spvc +bsp_gbuff_src = $(vkshaderpath)/bsp_gbuf.frag +bsp_gbuff_c = $(vkshaderpath)/bsp_gbuf.frag.spvc aliasv_src = $(vkshaderpath)/alias.vert aliasv_c = $(vkshaderpath)/alias.vert.spvc aliasf_src = $(vkshaderpath)/alias.frag @@ -295,6 +304,14 @@ $(quakebspv_c): $(quakebspv_src) $(quakebspf_c): $(quakebspf_src) +$(bsp_depth_c): $(bsp_depth_src) + +$(bsp_gbufv_c): $(bsp_gbufv_src) + +$(bsp_gbufg_c): $(bsp_gbufg_src) + +$(bsp_gbuff_c): $(bsp_gbuff_src) + $(aliasv_c): $(aliasv_src) $(alias_depth_c): $(alias_depth_src) @@ -312,6 +329,10 @@ vkshader_c = \ $(twodf_c) \ $(quakebspv_c) \ $(quakebspf_c) \ + $(bsp_depth_c) \ + $(bsp_gbufv_c) \ + $(bsp_gbufg_c) \ + $(bsp_gbuff_c) \ $(aliasv_c) \ $(alias_depth_c) \ $(aliasf_c) \ diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 4cfceb999..58e04c110 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -167,7 +167,9 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, family, 1, &priority }; - VkPhysicalDeviceFeatures features = {}; + VkPhysicalDeviceFeatures features = { + .geometryShader = 1, + }; VkDeviceCreateInfo dCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0, 1, &qCreateInfo, diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 2892f5fec..d71ce6037 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -457,6 +457,7 @@ //renderPass = renderpass; }; bsp_depth = { + subpass = 0; stages = ( { stage = vertex; @@ -472,10 +473,10 @@ "$properties.pipelines.bsp_gbuf.vertexInput.attributes[0]", ); }; - inputAssembly = $properties.pipelines.bsp_main.inputAssembly; - viewport = $properties.pipelines.bsp_main.viewport; - rasterization = $properties.pipelines.bsp_main.rasterization; - multisample = $properties.pipelines.bsp_main.multisample; + inputAssembly = $properties.pipelines.bsp_gbuf.inputAssembly; + viewport = $properties.pipelines.bsp_gbuf.viewport; + rasterization = $properties.pipelines.bsp_gbuf.rasterization; + multisample = $properties.pipelines.bsp_gbuf.multisample; depthStencil = { depthTestEnable = true; depthWriteEnable = true; @@ -491,12 +492,18 @@ //renderPass = renderpass; }; bsp_gbuf = { + subpass = 1; stages = ( { stage = vertex; name = main; module = $builtin/bsp_gbuf.vert; }, + { + stage = geometry; + name = main; + module = $builtin/bsp_gbuf.geom; + }, { stage = fragment; name = main; @@ -570,16 +577,28 @@ }; colorBlend = { logicOpEnable = false; - attachments = ({ - blendEnable = true; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }); + attachments = ( + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + } + ); }; dynamic = { dynamicState = ( viewport, scissor, blend_constants ); @@ -587,17 +606,23 @@ layout = quakebsp_layout; //renderPass = renderpass; }; - quakebsp_skysheet = { + bsp_skysheet = { + subpass = 1; stages = ( { stage = vertex; name = main; - module = $builtin/quakebsp.vert; + module = $builtin/bsp_gbuf.vert; + }, + { + stage = geometry; + name = main; + module = $builtin/bsp_gbuf.geom; }, { stage = fragment; name = main; - module = $builtin/quakebsp.frag; + module = $builtin/bsp_gbuf.frag; specializationInfo = { mapEntries = ( { size = 4; offset = 0; constantID = 0; }, @@ -623,6 +648,7 @@ //renderPass = renderpass; }; twod = { + subpass = 3; stages = ( { stage = vertex; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 857d457d4..64c0954cb 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -63,6 +63,14 @@ static static #include "libs/video/renderer/vulkan/shader/quakebsp.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/bsp_depth.vert.spvc" +static +#include "libs/video/renderer/vulkan/shader/bsp_gbuf.vert.spvc" +static +#include "libs/video/renderer/vulkan/shader/bsp_gbuf.geom.spvc" +static +#include "libs/video/renderer/vulkan/shader/bsp_gbuf.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/alias.vert.spvc" static #include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc" @@ -86,6 +94,10 @@ static shaderdata_t builtin_shaders[] = { { "twod.frag", twod_frag, sizeof (twod_frag) }, { "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) }, { "quakebsp.frag", quakebsp_frag, sizeof (quakebsp_frag) }, + { "bsp_depth.vert", bsp_depth_vert, sizeof (bsp_depth_vert) }, + { "bsp_gbuf.vert", bsp_gbuf_vert, sizeof (bsp_gbuf_vert) }, + { "bsp_gbuf.geom", bsp_gbuf_geom, sizeof (bsp_gbuf_geom) }, + { "bsp_gbuf.frag", bsp_gbuf_frag, sizeof (bsp_gbuf_frag) }, { "alias.vert", alias_vert, sizeof (alias_vert) }, { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, { "alias.frag", alias_frag, sizeof (alias_frag) }, diff --git a/libs/video/renderer/vulkan/shader/bsp_depth.vert b/libs/video/renderer/vulkan/shader/bsp_depth.vert new file mode 100644 index 000000000..02a4fed80 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/bsp_depth.vert @@ -0,0 +1,19 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection; + mat4 View; + mat4 Sky; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; +}; + +layout (location = 0) in vec4 vertex; + +void +main (void) +{ + gl_Position = Projection * (View * (Model * vertex)); +} diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag new file mode 100644 index 000000000..272499efa --- /dev/null +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -0,0 +1,126 @@ +#version 450 + +layout (set = 0, binding = 1) uniform sampler2D Texture; +layout (set = 0, binding = 2) uniform sampler2D GlowMap; +layout (set = 0, binding = 3) uniform sampler2D LightMap; +layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; +layout (set = 0, binding = 5) uniform samplerCube SkyCube; + +layout (push_constant) uniform PushConstants { + layout (offset = 64) + vec4 fog; + float time; +}; + +layout (location = 0) in vec4 tl_st; +layout (location = 1) in vec3 direction; +layout (location = 2) in vec3 normal; + +layout (location = 0) out vec4 frag_color; +layout (location = 1) out vec4 frag_normal; + +layout (constant_id = 0) const bool doWarp = false; +layout (constant_id = 1) const bool doLight = true; +layout (constant_id = 2) const bool doSkyCube = false; +layout (constant_id = 3) const bool doSkySheet = false; + +const float PI = 3.14159265; +const float SPEED = 20.0; +const float CYCLE = 128.0; +const float FACTOR = PI * 2.0 / CYCLE; +const vec2 BIAS = vec2 (1.0, 1.0); +const float SCALE = 8.0; + +vec2 +warp_st (vec2 st, float time) +{ + vec2 angle = st.ts * CYCLE / 2.0; + vec2 phase = vec2 (time, time) * SPEED; + return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; +} + +vec4 +fogBlend (vec4 color) +{ + float az = fog.a * gl_FragCoord.z / gl_FragCoord.w; + vec3 fog_color = fog.rgb; + float fog_factor = exp (-az * az); + + return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); +} + +vec4 +sky_sheet (vec3 dir, float time) +{ + float len; + vec2 flow = vec2 (1.0, 1.0); + vec2 base; + vec3 st1, st2; + vec4 c1, c2, c; + + dir.z *= 3.0; + len = dot (dir, dir); + len = SCALE * inversesqrt (len); + base = dir.yx * vec2(1.0, -1.0) * len; + + st1 = vec3 (base + flow * time / 8.0, 0); + st2 = vec3 (base + flow * time / 16.0, 1); + + c1 = texture (SkySheet, st1); + c2 = texture (SkySheet, st2); + + c = vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); + + return c; +} + +vec4 +sky_cube (vec3 dir, float time) +{ + // NOTE: quake's world is right-handed with Z up and X forward, but + // Vulkan's cube maps are left-handed with Y up and Z forward. The + // rotation to X foward is done by the Sky matrix so all that's left + // to do here is swizzle the Y and Z coordinates + return texture (SkyCube, dir.xzy); +} + +vec4 +sky_color (vec3 dir, float time) +{ + if (!doSkySheet) { + return vec4 (1, 0, 1, 1); + //return sky_cube (dir, time); + } if (!doSkyCube) { + return sky_sheet (dir, time); + } else { + // can see through the sheet (may look funny when looking down) + // maybe have 4 sheet layers instead of 2? + vec4 c1 = sky_sheet (dir, time); + vec4 c2 = sky_cube (dir, time); + return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); + return vec4 (1, 0, 1, 1); + } +} + +void +main (void) +{ + vec4 c; + vec2 t_st = tl_st.xy; + vec2 l_st = tl_st.zw; + + if (doWarp) { + t_st = warp_st (t_st, time); + } + if (doSkyCube || doSkySheet) { + c = sky_color (direction, time); + } else { + c = texture (Texture, t_st); + if (doLight) { + c *= vec4 (texture (LightMap, l_st).xyz, 1); + } + c += texture (GlowMap, t_st); + } + frag_color = c;//fogBlend (c); + frag_normal = vec4 (normal, 0); +} diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom new file mode 100644 index 000000000..f1107f759 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom @@ -0,0 +1,29 @@ +#version 450 + +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; +layout (location = 0) in vec4 v_tl_st[]; +layout (location = 1) in vec3 v_direction[]; + +layout (location = 0) out vec4 tl_st; +layout (location = 1) out vec3 direction; +layout (location = 2) out vec3 normal; + +void +main() +{ + vec3 a = gl_in[0].gl_Position.xyz; + vec3 b = gl_in[1].gl_Position.xyz; + vec3 c = gl_in[2].gl_Position.xyz; + + vec3 n = normalize (cross (b - a, c - a)); + + for (int vert = 0; vert < 3; vert++) { + gl_Position = gl_in[vert].gl_Position; + tl_st = v_tl_st[vert]; + direction = v_direction[vert]; + normal = n; + EmitVertex (); + } + EndPrimitive (); +} diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert new file mode 100644 index 000000000..bb9e87e4a --- /dev/null +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert @@ -0,0 +1,25 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection; + mat4 View; + mat4 Sky; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; +}; + +layout (location = 0) in vec4 vertex; +layout (location = 1) in vec4 tl_uv; + +layout (location = 0) out vec4 tl_st; +layout (location = 1) out vec3 direction; + +void +main (void) +{ + gl_Position = Projection * (View * (Model * vertex)); + direction = (Sky * vertex).xyz; + tl_st = tl_uv; +} diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 973e5445b..f7d9b2f0b 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -152,7 +152,7 @@ Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx) } static void -alias_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline, +alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; @@ -160,11 +160,12 @@ alias_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline, aliasctx_t *actx = ctx->alias_context; __auto_type cframe = &ctx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = aframe->cmdSet.a[subpass]; dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, 0, + ctx->renderpass, subpass, cframe->framebuffer, 0, 0, 0, }; @@ -222,8 +223,8 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx) //FIXME need per frame matrices aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - alias_begin_subpass (aframe->cmdSet.a[QFV_aliasDepth], actx->depth, ctx); - alias_begin_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], actx->gbuf, ctx); + alias_begin_subpass (QFV_aliasDepth, actx->depth, ctx); + alias_begin_subpass (QFV_aliasGBuffer, actx->gbuf, ctx); } void diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 895caed49..dfd58b1f5 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -845,18 +845,20 @@ get_view (qfv_tex_t *tex, qfv_tex_t *default_tex) } static void -bsp_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline, vulkan_ctx_t *ctx) +bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, + vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = bframe->cmdSet.a[subpass]; dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, 0, + ctx->renderpass, subpass, cframe->framebuffer, 0, 0, 0, }; @@ -928,9 +930,8 @@ bsp_begin (vulkan_ctx_t *ctx) bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, bctx->default_skybox); - //FIXME pipeline - bsp_begin_subpass (bframe->cmdSet.a[QFV_bspDepth], bctx->main, ctx); - bsp_begin_subpass (bframe->cmdSet.a[QFV_bspGBuffer], bctx->main, ctx); + bsp_begin_subpass (QFV_bspDepth, bctx->depth, ctx); + bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, ctx); } static void @@ -1047,7 +1048,7 @@ sky_begin (vulkan_ctx_t *ctx) bctx->default_skybox); //FIXME sky pass - bsp_begin_subpass (bframe->cmdSet.a[QFV_bspTranslucent], bctx->sky, ctx); + bsp_begin_subpass (QFV_bspTranslucent, bctx->sky, ctx); } static void @@ -1457,8 +1458,9 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&bctx->frames, frames); bctx->frames.grow = 0; - bctx->main = Vulkan_CreatePipeline (ctx, "quakebsp_main"); - bctx->sky = Vulkan_CreatePipeline (ctx, "quakebsp_skysheet"); + bctx->depth = Vulkan_CreatePipeline (ctx, "bsp_depth"); + bctx->gbuf = Vulkan_CreatePipeline (ctx, "bsp_gbuf"); + bctx->sky = Vulkan_CreatePipeline (ctx, "bsp_skysheet"); bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); @@ -1507,7 +1509,8 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) free (bframe->cmdSet.a); } - dfunc->vkDestroyPipeline (device->dev, bctx->main, 0); + dfunc->vkDestroyPipeline (device->dev, bctx->depth, 0); + dfunc->vkDestroyPipeline (device->dev, bctx->gbuf, 0); dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0); DARRAY_CLEAR (&bctx->texture_chains); DARRAY_CLEAR (&bctx->frames); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 43b246273..4b962edd6 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -709,7 +709,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, 0, + ctx->renderpass, QFV_passTranslucent, cframe->framebuffer, 0, 0, 0 }; From 0cd2ece38e4ae951e3d61512437ccf953971eab3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Feb 2021 14:37:13 +0900 Subject: [PATCH 1336/3664] [util] Correct element order for vector expressions --- libs/util/cexpr-parse.y | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index ad734def7..4c57c98c0 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -321,9 +321,22 @@ vector_expr (exprlist_t *list, exprctx_t *context) { exprlist_t *l; exprval_t *val = cexpr_value (&cexpr_vector, context); + float *vector = val->value; int i; + exprlist_t *rlist = 0; + + // list is built in reverse order, so need to reverse it to make converting + // to an array easier + while (list) { + exprlist_t *t = list->next; + list->next = rlist; + rlist = list; + list = t; + } + list = rlist; + for (i = 0; i < 4 && list; i++, list = l) { - exprval_t dst = { &cexpr_float, ((float *) val->value) + i }; + exprval_t dst = { &cexpr_float, &vector[i] }; exprval_t *src = list->value; binop_t *cast = cexpr_find_cast (&cexpr_float, src->type); if (cast) { @@ -335,12 +348,12 @@ vector_expr (exprlist_t *list, exprctx_t *context) l = list->next; cmemfree (context->memsuper, list); } - for ( ; i < 4; i++) { - ((float *) val->value)[i] = 0; - } if (i == 4 && list) { cexpr_error (context, "excess elements in vector expression"); } + for ( ; i < 4; i++) { + vector[i] = 0; + } return val; } From 82eabb5ca2acf4053fa3ed08ff2a2fbc84c2a9f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Feb 2021 14:37:48 +0900 Subject: [PATCH 1337/3664] [vulkan] Parse clear values And get the render pass working in general. Note that this is only the render pass and frame buffers: actual commands still have problems. --- include/vid_vulkan.h | 5 ++ libs/video/renderer/vid_render_vulkan.c | 19 ++--- libs/video/renderer/vulkan/deferred.plist | 16 +++- libs/video/renderer/vulkan/vkparse.c | 85 +++++++++++++++++++ libs/video/renderer/vulkan/vkparse.h | 3 + libs/video/renderer/vulkan/vkparse.plist | 13 ++- libs/video/renderer/vulkan/vulkan_draw.c | 1 + .../video/renderer/vulkan/vulkan_vid_common.c | 13 +++ 8 files changed, 140 insertions(+), 15 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index dcf4f624b..a672f02d1 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -32,6 +32,9 @@ typedef struct vulkan_matrices_s { typedef struct vulkan_frameset_s DARRAY_TYPE (vulkan_frame_t) vulkan_frameset_t; +typedef struct clearvalueset_s + DARRAY_TYPE (VkClearValue) clearvalueset_t; + typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); void (*unload_vulkan) (struct vulkan_ctx_s *ctx); @@ -56,6 +59,7 @@ typedef struct vulkan_ctx_s { struct plitem_s *renderpassDef; VkRenderPass renderpass; + clearvalueset_t *clearValues; struct qfv_imageset_s *attachment_images; struct qfv_imageviewset_s *attachment_views; VkDeviceMemory attachmentMemory; @@ -70,6 +74,7 @@ typedef struct vulkan_ctx_s { struct hashtab_s *samplers; struct hashtab_s *images; struct hashtab_s *imageViews; + struct hashtab_s *renderpasses; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index b8f9dc718..84f7b41f9 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -125,9 +125,6 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); - if (frame->framebuffer) { - dfunc->vkDestroyFramebuffer (dev, frame->framebuffer, 0); - } QFV_AcquireNextImage (vulkan_ctx->swapchain, frame->imageAvailableSemaphore, 0, &imageIndex); @@ -145,16 +142,11 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - VkClearValue clearValues[3] = { - { { {0.0, 0.0, 0.0, 1.0} } }, - { { {1.0, 0.0} } }, - { { {0.0, 0.0, 0.0, 1.0} } }, - }; VkRenderPassBeginInfo renderPassInfo = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, vulkan_ctx->renderpass, 0, { {0, 0}, vulkan_ctx->swapchain->extent }, - 3, clearValues + vulkan_ctx->clearValues->size, vulkan_ctx->clearValues->a }; dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); @@ -163,12 +155,15 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) subpassContents); for (int i = 0; i < frame->cmdSetCount; i++) { - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, frame->cmdSets[i].size, - frame->cmdSets[i].a); + if (frame->cmdSets[i].size) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, + frame->cmdSets[i].size, + frame->cmdSets[i].a); + } // reset for next time around frame->cmdSets[i].size = 0; - if (i < frame->cmdSetCount) { + if (i < frame->cmdSetCount - 1) { dfunc->vkCmdNextSubpass (frame->cmdBuffer, subpassContents); } } diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index e7e7e1f12..c03c30625 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -13,6 +13,7 @@ arrayLayers = 1; tiling = optimal; usage = depth_stencil_attachment|input_attachment; + initialLayout = undefined; }; color = { imageType = VK_IMAGE_TYPE_2D; @@ -27,6 +28,7 @@ arrayLayers = 1; tiling = optimal; usage = color_attachment|input_attachment; + initialLayout = undefined; }; normals = { imageType = VK_IMAGE_TYPE_2D; @@ -41,6 +43,7 @@ arrayLayers = 1; tiling = optimal; usage = color_attachment|input_attachment; + initialLayout = undefined; }; opaque = { imageType = VK_IMAGE_TYPE_2D; @@ -55,6 +58,7 @@ arrayLayers = 1; tiling = optimal; usage = color_attachment|input_attachment; + initialLayout = undefined; }; translucent = { imageType = VK_IMAGE_TYPE_2D; @@ -69,6 +73,7 @@ arrayLayers = 1; tiling = optimal; usage = color_attachment|input_attachment; + initialLayout = undefined; }; }; imageViews = { @@ -154,12 +159,21 @@ }; }; framebuffer = { - renderPass = renderpass; + renderPass = $properties.renderpass; attachments = (depth, color, normals, opaque, translucent, "$swapchain.views[$swapImageIndex]"); width = $swapchain.extent.width; height = $swapchain.extent.height; + layers = 1; }; + clearValues = ( + { depthStencil = { depth = 1; stencil = 0; }; }, + { color = "[0, 0, 0, 1]"; }, // color + { color = "[0, 0, 0, 1]"; }, // normals + { color = "[0, 0, 0, 1]"; }, // opaque + { color = "[0, 0, 0, 0]"; }, // translucent + { color = "[0, 0, 0, 1]"; }, // swapchain + ); renderpass = { attachments = ( { diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index ee8efb8a4..72ec5abbb 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -413,6 +413,42 @@ QFV_AddHandle (hashtab_t *tab, const char *name, uint64_t handle) Hash_Add (tab, hr); } +static int +parse_VkRenderPass (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context) +{ + __auto_type handle = (VkRenderPass *) data[0]; + int ret = 1; + parsectx_t *pctx = context; + exprctx_t ectx = *pctx->ectx; + vulkan_ctx_t *ctx = pctx->vctx; + + const char *name = PL_String (item); + Sys_Printf ("parse_VkRenderPass: %s\n", name); + if (name[0] != '$') { + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); + } + + *handle = (VkRenderPass) QFV_GetHandle (ctx->renderpasses, name); + if (*handle) { + return 1; + } + + plitem_t *setItem = 0; + exprval_t result = { &cexpr_plitem, &setItem }; + ectx.symtab = 0; + ectx.result = &result; + ret = !cexpr_eval_string (name, &ectx); + if (ret) { + VkRenderPass setLayout; + setLayout = QFV_ParseRenderPass (ctx, setItem, pctx->properties); + *handle = (VkRenderPass) setLayout; + + QFV_AddHandle (ctx->setLayouts, name, (uint64_t) setLayout); + } + return ret; +} + static int parse_VkShaderModule (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context) @@ -711,6 +747,21 @@ imageView_free (void *hr, void *_ctx) handleref_free (handleref, ctx); } +static void +renderpass_free (void *hr, void *_ctx) +{ + __auto_type handleref = (handleref_t *) hr; + __auto_type renderpass = (VkRenderPass) handleref->handle; + __auto_type ctx = (vulkan_ctx_t *) _ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (renderpass) { + dfunc->vkDestroyRenderPass (device->dev, renderpass, 0); + }; + handleref_free (handleref, ctx); +} + static hashtab_t *enum_symtab; static int @@ -891,6 +942,7 @@ QFV_InitParse (vulkan_ctx_t *ctx) ctx->samplers = handlref_symtab (sampler_free, ctx); ctx->images = handlref_symtab (image_free, ctx); ctx->imageViews = handlref_symtab (imageView_free, ctx); + ctx->renderpasses = handlref_symtab (renderpass_free, ctx); } } @@ -1262,6 +1314,39 @@ QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) VkFramebuffer framebuffer; dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); + printf ("framebuffer, renderPass: %p, %p\n", framebuffer, cInfo.renderPass); return framebuffer; } + +static int +parse_clearvalueset (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages, void *context) +{ + parsectx_t *parsectx = context; + vulkan_ctx_t *ctx = parsectx->vctx; + + plelement_t element = { + QFDictionary, + sizeof (VkClearValue), + array_alloc, + parse_VkClearValue, + 0, + }; + plfield_t f = { 0, 0, 0, 0, &element }; + + if (!PL_ParseArray (&f, item, &ctx->clearValues, messages, context)) { + return 0; + } + return 1; +} + +int +QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) +{ + if (!parse_object (ctx, plist, parse_clearvalueset, &ctx->clearValues, + properties)) { + return 0; + } + return 1; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index f8aea8a7f..2550e1b17 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -58,5 +58,8 @@ struct qfv_imageviewset_s *QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *properties); VkFramebuffer QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties); +int QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); + #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 9eb5e7e04..22d9173dc 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -23,6 +23,7 @@ VkImageCreateInfo, VkImageViewCreateInfo, VkFramebufferCreateInfo, + VkClearValue, ); parse = { VkSubpassDescription = { @@ -317,7 +318,7 @@ VkFramebufferCreateInfo = { //flags = auto; reserved for future use (Bits enum does not exist) renderPass = { - type = (custom, QFString, parse_VkShaderModule); + type = (custom, QFString, parse_VkRenderPass); fields = (renderPass); }; attachments = { @@ -328,6 +329,14 @@ width = auto; height = auto; layers = auto; - } + }; + VkClearColorValue = skip; + VkClearValue = { + color = { + type = (custom, QFString, parse_RGBA); + fields = (color); + }; + depthStencil = auto; + }; } } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 4b962edd6..2ab8bd05a 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -718,6 +718,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, }; + printf ("Vulkan_FlushText: %p %p\n", inherit.renderPass, inherit.framebuffer); dfunc->vkBeginCommandBuffer (cmd, &beginInfo); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a6f444798..903dc8d19 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -308,12 +308,25 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) { const char *name = "renderpass";//FIXME + hashtab_t *tab = ctx->renderpasses; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); + __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); + if (renderpass) { + ctx->renderpass = renderpass; + return; + } + plitem_t *item = qfv_load_renderpass (ctx, name); ctx->renderpass = QFV_ParseRenderPass (ctx, item, ctx->renderpassDef); + QFV_AddHandle (tab, path, (uint64_t) ctx->renderpass); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, ctx->renderpass, va (ctx->va_ctx, "renderpass:%s", name)); + item = qfv_load_renderpass (ctx, "clearValues"); + QFV_ParseClearValues (ctx, item, ctx->renderpassDef); + printf ("renderpass: %p\n", ctx->renderpass); } void From e6ecf5e8559b1e99038fe39614522392313332ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Feb 2021 15:43:02 +0900 Subject: [PATCH 1338/3664] [vulkan] Fix up commands for deferred rendering Nothing gets output yet (lighting and composite passes not implemented), but everything passes validation until exit (not destroying everything). --- libs/video/renderer/Makemodule.am | 5 + libs/video/renderer/vulkan/qfpipeline.plist | 29 +++--- libs/video/renderer/vulkan/shader.c | 3 + .../video/renderer/vulkan/shader/bsp_sky.frag | 96 +++++++++++++++++++ libs/video/renderer/vulkan/vulkan_alias.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 11 ++- 6 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/bsp_sky.frag diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index a5c3fc1a0..93f6a51b4 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -283,6 +283,8 @@ bsp_gbufg_src = $(vkshaderpath)/bsp_gbuf.geom bsp_gbufg_c = $(vkshaderpath)/bsp_gbuf.geom.spvc bsp_gbuff_src = $(vkshaderpath)/bsp_gbuf.frag bsp_gbuff_c = $(vkshaderpath)/bsp_gbuf.frag.spvc +bsp_skyf_src = $(vkshaderpath)/bsp_sky.frag +bsp_skyf_c = $(vkshaderpath)/bsp_sky.frag.spvc aliasv_src = $(vkshaderpath)/alias.vert aliasv_c = $(vkshaderpath)/alias.vert.spvc aliasf_src = $(vkshaderpath)/alias.frag @@ -312,6 +314,8 @@ $(bsp_gbufg_c): $(bsp_gbufg_src) $(bsp_gbuff_c): $(bsp_gbuff_src) +$(bsp_skyf_c): $(bsp_skyf_src) + $(aliasv_c): $(aliasv_src) $(alias_depth_c): $(alias_depth_src) @@ -333,6 +337,7 @@ vkshader_c = \ $(bsp_gbufv_c) \ $(bsp_gbufg_c) \ $(bsp_gbuff_c) \ + $(bsp_skyf_c) \ $(aliasv_c) \ $(alias_depth_c) \ $(aliasf_c) \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index d71ce6037..03e200fc7 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -607,28 +607,21 @@ //renderPass = renderpass; }; bsp_skysheet = { - subpass = 1; + subpass = 2; stages = ( { stage = vertex; name = main; module = $builtin/bsp_gbuf.vert; }, - { - stage = geometry; - name = main; - module = $builtin/bsp_gbuf.geom; - }, { stage = fragment; name = main; - module = $builtin/bsp_gbuf.frag; + module = $builtin/bsp_sky.frag; specializationInfo = { mapEntries = ( { size = 4; offset = 0; constantID = 0; }, - { size = 4; offset = 0; constantID = 1; }, - { size = 4; offset = 0; constantID = 2; }, - { size = 4; offset = 4; constantID = 3; }, + { size = 4; offset = 4; constantID = 1; }, ); data = <00000000ffffffff>; }; @@ -640,7 +633,21 @@ rasterization = $properties.pipelines.bsp_gbuf.rasterization; multisample = $properties.pipelines.bsp_gbuf.multisample; depthStencil = $properties.pipelines.bsp_gbuf.depthStencil; - colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; + colorBlend = { + logicOpEnable = false; + attachments = ( + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, + ); + }; dynamic = { dynamicState = ( viewport, scissor ); }; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 64c0954cb..4063e6f33 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -71,6 +71,8 @@ static static #include "libs/video/renderer/vulkan/shader/bsp_gbuf.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/bsp_sky.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/alias.vert.spvc" static #include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc" @@ -98,6 +100,7 @@ static shaderdata_t builtin_shaders[] = { { "bsp_gbuf.vert", bsp_gbuf_vert, sizeof (bsp_gbuf_vert) }, { "bsp_gbuf.geom", bsp_gbuf_geom, sizeof (bsp_gbuf_geom) }, { "bsp_gbuf.frag", bsp_gbuf_frag, sizeof (bsp_gbuf_frag) }, + { "bsp_sky.frag", bsp_sky_frag, sizeof (bsp_sky_frag) }, { "alias.vert", alias_vert, sizeof (alias_vert) }, { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, { "alias.frag", alias_frag, sizeof (alias_frag) }, diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag new file mode 100644 index 000000000..28ce41421 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -0,0 +1,96 @@ +#version 450 + +layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; +layout (set = 0, binding = 5) uniform samplerCube SkyCube; + +layout (push_constant) uniform PushConstants { + layout (offset = 64) + vec4 fog; + float time; +}; + +layout (location = 0) in vec4 tl_st; +layout (location = 1) in vec3 direction; + +layout (location = 0) out vec4 frag_color; + +layout (constant_id = 0) const bool doSkyCube = false; +layout (constant_id = 1) const bool doSkySheet = false; + +const float SCALE = 8.0; + +vec4 +fogBlend (vec4 color) +{ + float az = fog.a * gl_FragCoord.z / gl_FragCoord.w; + vec3 fog_color = fog.rgb; + float fog_factor = exp (-az * az); + + return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); +} + +vec4 +sky_sheet (vec3 dir, float time) +{ + float len; + vec2 flow = vec2 (1.0, 1.0); + vec2 base; + vec3 st1, st2; + vec4 c1, c2, c; + + dir.z *= 3.0; + len = dot (dir, dir); + len = SCALE * inversesqrt (len); + base = dir.yx * vec2(1.0, -1.0) * len; + + st1 = vec3 (base + flow * time / 8.0, 0); + st2 = vec3 (base + flow * time / 16.0, 1); + + c1 = texture (SkySheet, st1); + c2 = texture (SkySheet, st2); + + c = vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); + + return c; +} + +vec4 +sky_cube (vec3 dir, float time) +{ + // NOTE: quake's world is right-handed with Z up and X forward, but + // Vulkan's cube maps are left-handed with Y up and Z forward. The + // rotation to X foward is done by the Sky matrix so all that's left + // to do here is swizzle the Y and Z coordinates + return texture (SkyCube, dir.xzy); +} + +vec4 +sky_color (vec3 dir, float time) +{ + if (!doSkySheet) { + return vec4 (1, 0, 1, 1); + //return sky_cube (dir, time); + } if (!doSkyCube) { + return sky_sheet (dir, time); + } else { + // can see through the sheet (may look funny when looking down) + // maybe have 4 sheet layers instead of 2? + vec4 c1 = sky_sheet (dir, time); + vec4 c2 = sky_cube (dir, time); + return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); + return vec4 (1, 0, 1, 1); + } +} + +void +main (void) +{ + vec4 c; + + if (doSkyCube || doSkySheet) { + c = sky_color (direction, time); + } else { + c = vec4 (0, 0, 0, 1); + } + frag_color = c;//fogBlend (c); +} diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index f7d9b2f0b..8468335c1 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -186,7 +186,7 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, // actx->layout, 0, 2, sets, 0, 0); dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->layout, - 0, 2, aframe->descriptors + 0); + 0, 1, aframe->descriptors + 0); VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index dfd58b1f5..8b33cebb3 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -798,7 +798,7 @@ push_fragconst (fragconst_t *fragconst, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) { dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, - 0, sizeof (fragconst_t), fragconst); + 64, sizeof (fragconst_t), fragconst);//FIXME 64 } static void @@ -1259,6 +1259,15 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) fragconst_t frag_constants = { time: vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTranslucent]); + bind_view (qfv_bsp_texture, ctx->default_black->view, bframe, + bframe->cmdSet.a[QFV_bspTranslucent],//FIXME + bctx->layout, dfunc); + bind_view (qfv_bsp_glowmap, ctx->default_black->view, bframe, + bframe->cmdSet.a[QFV_bspTranslucent],//FIXME + bctx->layout, dfunc); + bind_view (qfv_bsp_lightmap, ctx->default_black->view, bframe, + bframe->cmdSet.a[QFV_bspTranslucent],//FIXME + bctx->layout, dfunc); for (is = bctx->sky_chain; is; is = is->tex_chain) { surf = is->surface; if (tex != surf->texinfo->texture->render) { From 9229b67633cf2308a78d211c0547f9b926dcbaf4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 Feb 2021 16:27:56 +0900 Subject: [PATCH 1339/3664] [vulkan] Clean up the new render pass and framebuffers --- include/QF/Vulkan/qf_alias.h | 2 +- libs/video/renderer/vid_render_vulkan.c | 2 ++ libs/video/renderer/vulkan/vulkan_draw.c | 1 - libs/video/renderer/vulkan/vulkan_vid_common.c | 17 ++++++++++++++--- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 5f3964a2b..7cd5b5bad 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -1,7 +1,7 @@ /* qf_alias.h - Vulkan specific brush model stuff + Vulkan specific alias model stuff Copyright (C) 2012 Bill Currie Copyright (C) 2021 Bill Currie diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 84f7b41f9..9893c08da 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -607,6 +607,8 @@ vulkan_vid_render_shutdown (void) Vulkan_Alias_Shutdown (vulkan_ctx); Mod_ClearAll (); Vulkan_Texture_Shutdown (vulkan_ctx); + Vulkan_DestroyFramebuffers (vulkan_ctx); + Vulkan_DestroyRenderPass (vulkan_ctx); Vulkan_Shutdown_Common (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 2ab8bd05a..4b962edd6 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -718,7 +718,6 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, }; - printf ("Vulkan_FlushText: %p %p\n", inherit.renderPass, inherit.framebuffer); dfunc->vkBeginCommandBuffer (cmd, &beginInfo); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 903dc8d19..98fec5945 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -192,9 +192,6 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) if (ctx->frames.size) { Vulkan_DestroyFrames (ctx); } - if (ctx->renderpass) { - Vulkan_DestroyRenderPass (ctx); - } if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } @@ -332,6 +329,10 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) void Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) { + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + dfunc->vkDestroyRenderPass (device->dev, ctx->renderpass, 0); } VkPipeline @@ -554,4 +555,14 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) void Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) { + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + for (size_t i = 0; i < ctx->attachment_views->size; i++) { + dfunc->vkDestroyImageView (device->dev, ctx->attachment_views->a[i], 0); + } + for (size_t i = 0; i < ctx->attachment_images->size; i++) { + dfunc->vkDestroyImage (device->dev, ctx->attachment_images->a[i], 0); + } + dfunc->vkFreeMemory (device->dev, ctx->attachmentMemory, 0); } From 10a1b99a92a9d83caee473e188d16b71a4f8ba9e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 Feb 2021 19:58:31 +0900 Subject: [PATCH 1340/3664] [vulkan] Implement lighting and compose passes Lighting doesn't actually do lights yet, but it's producing pixels. Translucent seems to be working (2d draw uses it), and compose seems to be working. --- include/QF/Vulkan/funclist.h | 1 + include/QF/Vulkan/qf_compose.h | 62 ++++ include/QF/Vulkan/qf_lighting.h | 65 +++++ include/vid_vulkan.h | 5 + libs/video/renderer/Makemodule.am | 12 + libs/video/renderer/vid_render_vulkan.c | 9 + libs/video/renderer/vulkan/deferred.plist | 32 ++- libs/video/renderer/vulkan/qfpipeline.plist | 271 +++++++++++++++++- libs/video/renderer/vulkan/shader.c | 6 + .../video/renderer/vulkan/shader/compose.frag | 19 ++ .../renderer/vulkan/shader/lighting.frag | 33 +++ libs/video/renderer/vulkan/vkparse.c | 2 + libs/video/renderer/vulkan/vulkan_alias.c | 3 +- libs/video/renderer/vulkan/vulkan_bsp.c | 12 + libs/video/renderer/vulkan/vulkan_compose.c | 175 +++++++++++ libs/video/renderer/vulkan/vulkan_lighting.c | 202 +++++++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 50 ++++ 17 files changed, 930 insertions(+), 29 deletions(-) create mode 100644 include/QF/Vulkan/qf_compose.h create mode 100644 include/QF/Vulkan/qf_lighting.h create mode 100644 libs/video/renderer/vulkan/shader/compose.frag create mode 100644 libs/video/renderer/vulkan/shader/lighting.frag create mode 100644 libs/video/renderer/vulkan/vulkan_compose.c create mode 100644 libs/video/renderer/vulkan/vulkan_lighting.c diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index a1601f814..e4a21d52a 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -179,6 +179,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindVertexBuffers) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindIndexBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindDescriptorSets) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDraw) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDrawIndexed) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h new file mode 100644 index 000000000..f8fd497a1 --- /dev/null +++ b/include/QF/Vulkan/qf_compose.h @@ -0,0 +1,62 @@ +/* + qf_compose.h + + Vulkan compose pass + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/2/24 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_compose_h +#define __QF_Vulkan_qf_compose_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/modelgen.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" + +#define COMPOSE_IMAGE_INFOS 2 + +typedef struct composeframe_s { + VkCommandBuffer cmd; + VkDescriptorImageInfo imageInfo[COMPOSE_IMAGE_INFOS]; + VkWriteDescriptorSet descriptors[COMPOSE_IMAGE_INFOS]; +} composeframe_t; + +typedef struct composeframeset_s + DARRAY_TYPE (composeframe_t) composeframeset_t; + +typedef struct composectx_s { + composeframeset_t frames; + VkPipeline pipeline; + VkPipelineLayout layout; +} composectx_t; + +struct vulkan_ctx_s; + +void Vulkan_Compose_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Compose_Shutdown (struct vulkan_ctx_s *ctx); +void Vulkan_Compose_Draw (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_compose_h diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h new file mode 100644 index 000000000..d2cee31ac --- /dev/null +++ b/include/QF/Vulkan/qf_lighting.h @@ -0,0 +1,65 @@ +/* + qf_lighting.h + + Vulkan lighting pass + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/2/23 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_lighting_h +#define __QF_Vulkan_qf_lighting_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/modelgen.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" + +#define LIGHTING_BUFFER_INFOS 1 +#define LIGHTING_IMAGE_INFOS 3 + +typedef struct lightingframe_s { + VkCommandBuffer cmd; + VkDescriptorBufferInfo bufferInfo[LIGHTING_BUFFER_INFOS]; + VkDescriptorImageInfo imageInfo[LIGHTING_IMAGE_INFOS]; + VkWriteDescriptorSet descriptors[LIGHTING_BUFFER_INFOS + + LIGHTING_IMAGE_INFOS]; +} lightingframe_t; + +typedef struct lightingframeset_s + DARRAY_TYPE (lightingframe_t) lightingframeset_t; + +typedef struct lightingctx_s { + lightingframeset_t frames; + VkPipeline pipeline; + VkPipelineLayout layout; +} lightingctx_t; + +struct vulkan_ctx_s; + +void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); +void Vulkan_Lighting_Draw (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_lighting_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index a672f02d1..080b8079f 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -79,6 +79,11 @@ typedef struct vulkan_ctx_s { struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; struct drawctx_s *draw_context; + struct lightingctx_s *lighting_context; + struct composectx_s *compose_context; + + VkBuffer quad_buffer; + VkDeviceMemory quad_memory; VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 93f6a51b4..8789de037 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -240,7 +240,9 @@ libs_video_renderer_vid_render_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vkparse.c \ libs/video/renderer/vulkan/vulkan_alias.c \ libs/video/renderer/vulkan/vulkan_bsp.c \ + libs/video/renderer/vulkan/vulkan_compose.c \ libs/video/renderer/vulkan/vulkan_draw.c \ + libs/video/renderer/vulkan/vulkan_lighting.c \ libs/video/renderer/vulkan/vulkan_lightmap.c \ libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ @@ -285,6 +287,10 @@ bsp_gbuff_src = $(vkshaderpath)/bsp_gbuf.frag bsp_gbuff_c = $(vkshaderpath)/bsp_gbuf.frag.spvc bsp_skyf_src = $(vkshaderpath)/bsp_sky.frag bsp_skyf_c = $(vkshaderpath)/bsp_sky.frag.spvc +lightingf_src = $(vkshaderpath)/lighting.frag +lightingf_c = $(vkshaderpath)/lighting.frag.spvc +composef_src = $(vkshaderpath)/compose.frag +composef_c = $(vkshaderpath)/compose.frag.spvc aliasv_src = $(vkshaderpath)/alias.vert aliasv_c = $(vkshaderpath)/alias.vert.spvc aliasf_src = $(vkshaderpath)/alias.frag @@ -316,6 +322,10 @@ $(bsp_gbuff_c): $(bsp_gbuff_src) $(bsp_skyf_c): $(bsp_skyf_src) +$(lightingf_c): $(lightingf_src) + +$(composef_c): $(composef_src) + $(aliasv_c): $(aliasv_src) $(alias_depth_c): $(alias_depth_src) @@ -338,6 +348,8 @@ vkshader_c = \ $(bsp_gbufg_c) \ $(bsp_gbuff_c) \ $(bsp_skyf_c) \ + $(lightingf_c) \ + $(composef_c) \ $(aliasv_c) \ $(alias_depth_c) \ $(aliasf_c) \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 9893c08da..059250fff 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -38,7 +38,9 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" +#include "QF/Vulkan/qf_compose.h" #include "QF/Vulkan/qf_draw.h" +#include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_particles.h" @@ -98,6 +100,8 @@ vulkan_R_Init (void) Vulkan_Bsp_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); Vulkan_Particles_Init (vulkan_ctx); + Vulkan_Lighting_Init (vulkan_ctx); + Vulkan_Compose_Init (vulkan_ctx); Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, vulkan_ctx->swapchain->numImages); @@ -140,6 +144,9 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) Vulkan_FlushText (vulkan_ctx); + Vulkan_Lighting_Draw (vulkan_ctx); + Vulkan_Compose_Draw (vulkan_ctx); + VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; VkRenderPassBeginInfo renderPassInfo = { @@ -602,6 +609,8 @@ vulkan_vid_render_shutdown (void) QFV_DeviceWaitIdle (device); df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); + Vulkan_Compose_Shutdown (vulkan_ctx); + Vulkan_Lighting_Shutdown (vulkan_ctx); Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Alias_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index c03c30625..0245906da 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -179,7 +179,7 @@ { format = $properties.images.depth.format; samples = 1; - loadOp = dont_care; + loadOp = clear; storeOp = dont_care; stencilLoadOp = dont_care; stencilStoreOp = dont_care; @@ -238,14 +238,14 @@ }, ); subpasses = ( - { // depth + { // 0 depth pipelineBindPoint = graphics; depthStencilAttachment = { attachment = 0; layout = depth_stencil_attachment_optimal; }; }, - { // g-buffer generation + { // 1 g-buffer generation pipelineBindPoint = graphics; colorAttachments = ( { // color @@ -261,8 +261,9 @@ attachment = 0; layout = depth_stencil_attachment_optimal; }; + preserveAttachments = (4); }, - { // lighting + { // 2 lighting pipelineBindPoint = graphics; inputAttachments = ( { // depth @@ -284,8 +285,9 @@ layout = color_attachment_optimal; }, ); + preserveAttachments = (4); }, - { // translucent + { // 3 translucent pipelineBindPoint = graphics; colorAttachments = ( { // translucent @@ -293,8 +295,9 @@ layout = color_attachment_optimal; }, ); + preserveAttachments = (0, 1, 2, 3); }, - { // compose + { // 4 compose pipelineBindPoint = graphics; inputAttachments = ( { // opaque @@ -312,12 +315,13 @@ layout = color_attachment_optimal; }, ); + preserveAttachments = (0, 1, 2); }, ); dependencies = ( { - srcSubpass = 0; - dstSubpass = 1; + srcSubpass = 0; // depth + dstSubpass = 1; // g-buffer srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -325,8 +329,8 @@ dependencyFlags = by_region; }, { - srcSubpass = 1; - dstSubpass = 2; + srcSubpass = 1; // g-buffer + dstSubpass = 2; // lighting srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -334,8 +338,8 @@ dependencyFlags = by_region; }, { - srcSubpass = 2; - dstSubpass = 4; + srcSubpass = 2; // lighting + dstSubpass = 4; // compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -343,8 +347,8 @@ dependencyFlags = by_region; }, { - srcSubpass = 3; - dstSubpass = 4; + srcSubpass = 3; // translucent + dstSubpass = 4; // compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 03e200fc7..825f71a59 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -77,6 +77,36 @@ }, ); }; + lighting_attach_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = input_attachment; + descriptorCount = "3z * $frames.size"; + }, + ); + }; + lighting_lights_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = uniform_buffer; + descriptorCount = $frames.size; + }, + ); + }; + compose_attach_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = input_attachment; + descriptorCount = "2z * $frames.size"; + }, + ); + }; }; setLayouts = { twod_set = { @@ -208,20 +238,51 @@ }, ); }; - something = { - flags = 0; + lighting_attach = { bindings = ( { binding = 0; - descriptorType = sampled_image; + descriptorType = input_attachment; descriptorCount = 1; stageFlags = fragment; }, { binding = 1; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + lighting_lights = { + bindings = ( + { + binding = 0; descriptorType = uniform_buffer; descriptorCount = 1; - stageFlags = vertex; + stageFlags = fragment; + }, + ); + }; + compose_attach = { + bindings = ( + { + binding = 0; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 1; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; }, ); }; @@ -261,15 +322,11 @@ }, ); }; - something = { - setLayouts = (something); - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "4 * 4"; - }, - ); + lighting_layout = { + setLayouts = (lighting_attach, lighting_lights); + }; + compose_layout = { + setLayouts = (compose_attach); }; }; pipelines = { @@ -758,6 +815,194 @@ layout = twod_layout; //renderPass = renderpass; }; + lighting = { + subpass = 2; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/passthrough.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/lighting.frag; + }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "4 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + ); + }; + inputAssembly = { + topology = triangle_strip; + primitiveRestartEnable = false; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + depthStencil = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ( + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, + ); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = lighting_layout; + //renderPass = renderpass; + }; + compose = { + subpass = 4; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/passthrough.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/compose.frag; + }, + ); + vertexInput = { + bindings = ( + { + binding = 0; + stride = "4 * 4"; + inputRate = vertex; + }, + ); + attributes = ( + { + location = 0; + binding = 0; + format = r32g32b32a32_sfloat; + offset = 0; + }, + ); + }; + inputAssembly = { + topology = triangle_strip; + primitiveRestartEnable = false; + }; + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + depthStencil = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ( + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, + ); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = compose_layout; + //renderPass = renderpass; + }; }; renderpass = { attachments = ( diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 4063e6f33..4168d9b63 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -73,6 +73,10 @@ static static #include "libs/video/renderer/vulkan/shader/bsp_sky.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/lighting.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/compose.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/alias.vert.spvc" static #include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc" @@ -101,6 +105,8 @@ static shaderdata_t builtin_shaders[] = { { "bsp_gbuf.geom", bsp_gbuf_geom, sizeof (bsp_gbuf_geom) }, { "bsp_gbuf.frag", bsp_gbuf_frag, sizeof (bsp_gbuf_frag) }, { "bsp_sky.frag", bsp_sky_frag, sizeof (bsp_sky_frag) }, + { "lighting.frag", lighting_frag, sizeof (lighting_frag) }, + { "compose.frag", compose_frag, sizeof (compose_frag) }, { "alias.vert", alias_vert, sizeof (alias_vert) }, { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, { "alias.frag", alias_frag, sizeof (alias_frag) }, diff --git a/libs/video/renderer/vulkan/shader/compose.frag b/libs/video/renderer/vulkan/shader/compose.frag new file mode 100644 index 000000000..39ac94845 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/compose.frag @@ -0,0 +1,19 @@ +#version 450 + +layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput opaque; +layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput translucent; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + vec3 o; + vec4 t; + vec3 c; + + o = subpassLoad (opaque).rgb; + t = subpassLoad (translucent); + c = mix (o, t.rgb, t.a); + frag_color = vec4 (c, 1); +} diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag new file mode 100644 index 000000000..555682645 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -0,0 +1,33 @@ +#version 450 + +layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput depth; +layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput color; +layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput normal; + +struct LightData { + vec3 color; + float dist; + vec3 position; + int type; + vec3 direction; + float cone; +}; + +layout (constant_id = 0) const int MaxLights = 8; +/*layout (set = 1, binding = 0) uniform Lights { + int lightCount; + LightData lights[MaxLights]; +};*/ + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + float d = subpassLoad (depth).r; + vec4 c; + + //c = vec4 (d, d, d, 1); + c = vec4 (subpassLoad (color).rgb, 1); + frag_color = c; +} diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 72ec5abbb..de12d60c0 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1259,6 +1259,8 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) dfunc->vkCreateImage (device->dev, &create.info[i], 0, &set->a[i]); const char *name = PL_KeyAtIndex (item, i); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, set->a[i], + va (ctx->va_ctx, "image:%s", name)); name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]); } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 8468335c1..d3663d0df 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -176,8 +176,7 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); //VkDescriptorSet sets[] = { // aframe->descriptors[0].dstSet, // aframe->descriptors[1].dstSet, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 8b33cebb3..046ba6c0a 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -827,6 +827,15 @@ draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, continue; dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index, 0, 0); + } +} + +static void +reset_elechain (elechain_t *ec) +{ + elements_t *el; + + for (el = ec->elements; el; el = el->next) { el->first_index = 0; el->index_count = 0; } @@ -1167,6 +1176,7 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) bframe->cmdSet.a[QFV_bspDepth]); draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspGBuffer]); + reset_elechain (ec); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1280,6 +1290,7 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc,//FIXME bframe->cmdSet.a[QFV_bspTranslucent]); + reset_elechain (ec); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; @@ -1295,6 +1306,7 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc,//FIXME bframe->cmdSet.a[QFV_bspTranslucent]); + reset_elechain (ec); } tex->elechain = 0; tex->elechain_tail = &tex->elechain; diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c new file mode 100644 index 000000000..e2748dcb3 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -0,0 +1,175 @@ +/* + vulkan_compose.c + + Vulkan compose pass pipeline + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/2/23 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "qfalloca.h" + +#include "QF/sys.h" + +#include "QF/Vulkan/qf_compose.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" + +#include "r_internal.h" +#include "vid_vulkan.h" + +void +Vulkan_Compose_Draw (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + composectx_t *cctx = ctx->compose_context; + __auto_type frame = &ctx->frames.a[ctx->curFrame]; + composeframe_t *cframe = &cctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = cframe->cmd; + + DARRAY_APPEND (&frame->cmdSets[QFV_passCompose], cmd); + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + ctx->renderpass, QFV_passCompose, + frame->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + cctx->pipeline); + + cframe->imageInfo[0].imageView = ctx->attachment_views->a[3]; + cframe->imageInfo[1].imageView = ctx->attachment_views->a[4]; + dfunc->vkUpdateDescriptorSets (device->dev, 2, cframe->descriptors, 0, 0); + + VkDescriptorSet sets[] = { + cframe->descriptors[0].dstSet, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + cctx->layout, 0, 1, sets, 0, 0); + + VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; + VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; + dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + + VkDeviceSize offset = 0; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); + dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); + + dfunc->vkEndCommandBuffer (cmd); +} + +static VkDescriptorImageInfo base_image_info = { + 0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL +}; +static VkWriteDescriptorSet base_image_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + 0, 0, 0 +}; + +void +Vulkan_Compose_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + composectx_t *cctx = calloc (1, sizeof (composectx_t)); + ctx->compose_context = cctx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&cctx->frames, frames); + DARRAY_RESIZE (&cctx->frames, frames); + cctx->frames.grow = 0; + + cctx->pipeline = Vulkan_CreatePipeline (ctx, "compose"); + cctx->layout = Vulkan_CreatePipelineLayout (ctx, "compose_layout"); + + __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); + + __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + for (size_t i = 0; i < frames; i++) { + attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, + "compose_attach"); + } + __auto_type attach_pool = Vulkan_CreateDescriptorPool (ctx, + "compose_attach_pool"); + + __auto_type attach_set = QFV_AllocateDescriptorSet (device, attach_pool, + attach); + for (size_t i = 0; i < frames; i++) { + __auto_type cframe = &cctx->frames.a[i]; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); + cframe->cmd = cmdSet->a[0]; + + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + cframe->cmd, "cmd:compose"); + for (int j = 0; j < COMPOSE_IMAGE_INFOS; j++) { + cframe->imageInfo[j] = base_image_info; + cframe->imageInfo[j].sampler = 0; + cframe->descriptors[j] = base_image_write; + cframe->descriptors[j].dstSet = attach_set->a[i]; + cframe->descriptors[j].dstBinding = j; + cframe->descriptors[j].pImageInfo = &cframe->imageInfo[j]; + } + } + free (attach_set); +} + +void +Vulkan_Compose_Shutdown (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + composectx_t *cctx = ctx->compose_context; + + dfunc->vkDestroyPipeline (device->dev, cctx->pipeline, 0); + free (cctx->frames.a); + free (cctx); +} diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c new file mode 100644 index 000000000..604e7ff94 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -0,0 +1,202 @@ +/* + vulkan_lighting.c + + Vulkan lighting pass pipeline + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/2/23 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "qfalloca.h" + +#include "QF/sys.h" + +#include "QF/Vulkan/qf_lighting.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" + +#include "r_internal.h" +#include "vid_vulkan.h" + +void +Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + lightingctx_t *lctx = ctx->lighting_context; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; + lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = lframe->cmd; + + DARRAY_APPEND (&cframe->cmdSets[QFV_passLighting], cmd); + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + ctx->renderpass, QFV_passLighting, + cframe->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + lctx->pipeline); + + lframe->imageInfo[0].imageView = ctx->attachment_views->a[0]; + lframe->imageInfo[1].imageView = ctx->attachment_views->a[1]; + lframe->imageInfo[2].imageView = ctx->attachment_views->a[2]; + dfunc->vkUpdateDescriptorSets (device->dev, 3, lframe->descriptors+1, 0, 0); + + VkDescriptorSet sets[] = { + lframe->descriptors[1].dstSet, + lframe->descriptors[0].dstSet, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + lctx->layout, 0, 2, sets, 0, 0); + + VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; + VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; + dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + + VkDeviceSize offset = 0; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); + dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); + + dfunc->vkEndCommandBuffer (cmd); +} + +static VkDescriptorBufferInfo base_buffer_info = { + 0, 0, VK_WHOLE_SIZE +}; +static VkDescriptorImageInfo base_image_info = { + 0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL +}; +static VkWriteDescriptorSet base_buffer_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, 0, 0 +}; +static VkWriteDescriptorSet base_image_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + 0, 0, 0 +}; + +void +Vulkan_Lighting_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); + ctx->lighting_context = lctx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&lctx->frames, frames); + DARRAY_RESIZE (&lctx->frames, frames); + lctx->frames.grow = 0; + + lctx->pipeline = Vulkan_CreatePipeline (ctx, "lighting"); + lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout"); + + __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); + + __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + __auto_type lights = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + for (size_t i = 0; i < frames; i++) { + attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, + "lighting_attach"); + lights->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, + "lighting_lights"); + } + __auto_type attach_pool = Vulkan_CreateDescriptorPool (ctx, + "lighting_attach_pool"); + __auto_type lights_pool = Vulkan_CreateDescriptorPool (ctx, + "lighting_lights_pool"); + + __auto_type attach_set = QFV_AllocateDescriptorSet (device, attach_pool, + attach); + __auto_type lights_set = QFV_AllocateDescriptorSet (device, lights_pool, + lights); + for (size_t i = 0; i < frames; i++) { + __auto_type lframe = &lctx->frames.a[i]; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); + lframe->cmd = cmdSet->a[0]; + + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + lframe->cmd, "cmd:lighting"); + for (int j = 0; j < LIGHTING_BUFFER_INFOS; j++) { + lframe->bufferInfo[j] = base_buffer_info; + lframe->descriptors[j] = base_buffer_write; + lframe->descriptors[j].dstSet = lights_set->a[i]; + lframe->descriptors[j].dstBinding = j; + lframe->descriptors[j].pBufferInfo = &lframe->bufferInfo[j]; + } + for (int j = 0; j < LIGHTING_IMAGE_INFOS; j++) { + lframe->imageInfo[j] = base_image_info; + lframe->imageInfo[j].sampler = 0; + int k = j + LIGHTING_BUFFER_INFOS; + lframe->descriptors[k] = base_image_write; + lframe->descriptors[k].dstSet = attach_set->a[i]; + lframe->descriptors[k].dstBinding = j; + lframe->descriptors[k].pImageInfo = &lframe->imageInfo[j]; + } + } + free (attach_set); + free (lights_set); +} + +void +Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + lightingctx_t *lctx = ctx->lighting_context; + + dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0); + free (lctx->frames.a); + free (lctx); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 98fec5945..909f26236 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -324,6 +324,53 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) item = qfv_load_renderpass (ctx, "clearValues"); QFV_ParseClearValues (ctx, item, ctx->renderpassDef); printf ("renderpass: %p\n", ctx->renderpass); + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + static float quad_vertices[] = { + -1, -1, 0, 1, + -1, 1, 0, 1, + 1, -1, 0, 1, + 1, 1, 0, 1, + }; + ctx->quad_buffer = QFV_CreateBuffer (device, sizeof (quad_vertices), + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT); + ctx->quad_memory = QFV_AllocBufferMemory (device, ctx->quad_buffer, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + 0, 0); + QFV_BindBufferMemory (device, ctx->quad_buffer, ctx->quad_memory, 0); + + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + float *verts = QFV_PacketExtend (packet, sizeof (quad_vertices)); + memcpy (verts, quad_vertices, sizeof (quad_vertices)); + + VkBufferMemoryBarrier wr_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + ctx->quad_buffer, 0, sizeof (quad_vertices) }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, 0, 1, wr_barriers, 0, 0); + VkBufferCopy copy_region[] = { + { packet->offset, 0, sizeof (quad_vertices) }, + }; + dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, + ctx->quad_buffer, 1, ©_region[0]); + VkBufferMemoryBarrier rd_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + ctx->quad_buffer, 0, sizeof (quad_vertices) }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + 0, 0, 0, 1, rd_barriers, 0, 0); + QFV_PacketSubmit (packet); } void @@ -333,6 +380,9 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkDestroyRenderPass (device->dev, ctx->renderpass, 0); + + dfunc->vkFreeMemory (device->dev, ctx->quad_memory, 0); + dfunc->vkDestroyBuffer (device->dev, ctx->quad_buffer, 0); } VkPipeline From 6c1d6666b410596212a045284e77047b397bc201 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 Feb 2021 20:24:46 +0900 Subject: [PATCH 1341/3664] [vulkan] Actually write the alias g-buffer commands It seems to help for some reason. --- libs/video/renderer/vulkan/qfpipeline.plist | 6 ------ libs/video/renderer/vulkan/shader/alias_gbuf.frag | 4 ++-- libs/video/renderer/vulkan/vulkan_alias.c | 4 ++++ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 825f71a59..cb7cf82f9 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -177,12 +177,6 @@ }, { binding = 1; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 2; descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index e8b14a305..6ef33dd43 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -1,5 +1,5 @@ #version 450 -layout (set = 0, binding = 2) uniform sampler2DArray Skin; +layout (set = 0, binding = 1) uniform sampler2DArray Skin; layout (push_constant) uniform PushConstants { layout (offset = 68) @@ -28,5 +28,5 @@ main (void) c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB); frag_color = c; - frag_normal = vec4(normal, 0); + frag_normal = vec4(normal, 1); } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index d3663d0df..cc1905c4a 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -149,6 +149,10 @@ Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx) 0, vertex_constants, sizeof (vertex_constants), fragment_constants, sizeof (fragment_constants), hdr, ctx); + emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], ent->pose1, ent->pose2, + skin, vertex_constants, sizeof (vertex_constants), + fragment_constants, sizeof (fragment_constants), + hdr, ctx); } static void From f8961e43767128b9d825640aa22e33327a8067be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Feb 2021 10:12:19 +0900 Subject: [PATCH 1342/3664] [qflight] Fix some typos in comments --- tools/qflight/include/properties.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qflight/include/properties.h b/tools/qflight/include/properties.h index d5e73db7f..8d39361b7 100644 --- a/tools/qflight/include/properties.h +++ b/tools/qflight/include/properties.h @@ -76,7 +76,7 @@ void parse_color (const char *str, vec3_t color); \arg HalfLife "R G B i" where R G & B are 0-255 and i is the same as for normal id lights. The RGB values will be scaled by 1/255 such that 255 becomes 1.0. - \arg RGB "R B B" where R G & B are left as-is and the intensity + \arg RGB "R G B" where R G & B are left as-is and the intensity is set to 1.0. \arg id Standard quake single value light intensity. The color is set to white ([1.0 1.0 1.0]). @@ -124,7 +124,7 @@ int parse_noise (const char *arg); The database is loaded via LoadProperties(). - If a set of properties named "worldspawn" is in the database, the it + If a set of properties named "worldspawn" is in the database, then it will be used for default values, otherwise the database will be ignored. @@ -163,7 +163,7 @@ void set_sun_properties (entity_t *ent, struct plitem_s *dict); Supported properties: \arg \c light see \ref parse_light \arg \c style light style: 0-254 - \arg \c angle spotlight con angle in degress. defaults to 20 + \arg \c angle spotlight cone angle in degress. defaults to 20 \arg \c wait light "falloff". defaults to 1.0 \arg \c lightradius size of light. interacts with falloff for distance clipping (?). defaults to 0 From 4eb07220cd7eca8cdd9696cddb10a7515e5d3366 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Feb 2021 11:55:25 +0900 Subject: [PATCH 1343/3664] [util] Make plists more const-correct --- include/QF/qfplist.h | 6 +++--- libs/gamecode/pr_parse.c | 2 +- libs/util/qfplist.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index f1cc95b8a..cef305086 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -132,7 +132,7 @@ plitem_t *PL_GetPropertyList (const char *string, \return the text representation of the property list \note You are responsible for freeing the returned string. */ -char *PL_WritePropertyList (plitem_t *pl); +char *PL_WritePropertyList (const plitem_t *pl); /** Retrieve the type of an object. @@ -226,7 +226,7 @@ plitem_t *PL_ObjectAtIndex (const plitem_t *array, int index) __attribute__((pur \return an Array containing Strings or NULL if dict isn't a dictionary \note You are responsible for freeing this array. */ -plitem_t *PL_D_AllKeys (plitem_t *dict); +plitem_t *PL_D_AllKeys (const plitem_t *dict); /** Retrieve the number of keys in a dictionary. @@ -265,7 +265,7 @@ qboolean PL_A_AddObject (plitem_t *array, plitem_t *item); \return number of objects in the array */ -int PL_A_NumObjects (plitem_t *array) __attribute__((pure)); +int PL_A_NumObjects (const plitem_t *array) __attribute__((pure)); /** Insert an item into an array before the specified location. diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 0f0a3dea5..b33d14e6c 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -501,7 +501,7 @@ ED_Parse (progs_t *pr, const char *data) // new style (plist) entity data entity_list = PL_GetPropertyList (data, pr->hashlink_freelist); } else { - // oldstyle entity data + // old style entity data Script_UngetToken (script); entity_list = ED_ConvertToPlist (script, 0, pr->hashlink_freelist); } diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 6e4726c95..56c168168 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -330,7 +330,7 @@ PL_RemoveObjectForKey (const plitem_t *item, const char *key) } VISIBLE plitem_t * -PL_D_AllKeys (plitem_t *item) +PL_D_AllKeys (const plitem_t *item) { pldict_t *dict = (pldict_t *) item->data; dictkey_t *current; @@ -440,7 +440,7 @@ PL_A_AddObject (plitem_t *array, plitem_t *item) } VISIBLE int -PL_A_NumObjects (plitem_t *array) +PL_A_NumObjects (const plitem_t *array) { if (array->type != QFArray) return 0; @@ -1056,7 +1056,7 @@ write_string (dstring_t *dstr, const char *str) } static void -write_item (dstring_t *dstr, plitem_t *item, int level) +write_item (dstring_t *dstr, const plitem_t *item, int level) { dictkey_t *current; plarray_t *array; @@ -1107,7 +1107,7 @@ write_item (dstring_t *dstr, plitem_t *item, int level) } VISIBLE char * -PL_WritePropertyList (plitem_t *pl) +PL_WritePropertyList (const plitem_t *pl) { dstring_t *dstr = dstring_newstr (); From 918c3af095a4e840689f5092d864b5d9ec1c5efd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Feb 2021 13:46:33 +0900 Subject: [PATCH 1344/3664] [vulkan] Add a position buffer to the g-buffer While I could reconstruct the position from the screen coords and depth, this is easier and good enough for now. Reconstruction is an optimization thing. --- include/QF/Vulkan/qf_lighting.h | 2 +- include/QF/Vulkan/qf_vid.h | 10 ++ libs/video/renderer/vulkan/deferred.plist | 96 ++++++++++++++----- libs/video/renderer/vulkan/qfpipeline.plist | 30 +++++- libs/video/renderer/vulkan/shader/alias.vert | 4 +- .../renderer/vulkan/shader/alias_gbuf.frag | 4 +- .../renderer/vulkan/shader/bsp_gbuf.frag | 3 + .../renderer/vulkan/shader/bsp_gbuf.geom | 13 ++- .../renderer/vulkan/shader/bsp_gbuf.vert | 3 +- .../renderer/vulkan/shader/lighting.frag | 12 ++- libs/video/renderer/vulkan/vulkan_compose.c | 6 +- libs/video/renderer/vulkan/vulkan_lighting.c | 13 ++- 12 files changed, 154 insertions(+), 42 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index d2cee31ac..fab2ffc3d 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -37,7 +37,7 @@ #include "QF/Vulkan/command.h" #define LIGHTING_BUFFER_INFOS 1 -#define LIGHTING_IMAGE_INFOS 3 +#define LIGHTING_IMAGE_INFOS 4 typedef struct lightingframe_s { VkCommandBuffer cmd; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index db423d014..5ac5dddd4 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -46,6 +46,16 @@ enum { QFV_NumPasses }; +enum { + QFV_attachDepth, + QFV_attachColor, + QFV_attachNormal, + QFV_attachPosition, + QFV_attachOpaque, + QFV_attachTranslucent, + QFV_attachSwapchain, +}; + struct vulkan_ctx_s; void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 0245906da..6eded7acb 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -12,7 +12,7 @@ mipLevels = 1; arrayLayers = 1; tiling = optimal; - usage = depth_stencil_attachment|input_attachment; + usage = depth_stencil_attachment|input_attachment|transient_attachment; initialLayout = undefined; }; color = { @@ -27,10 +27,10 @@ mipLevels = 1; arrayLayers = 1; tiling = optimal; - usage = color_attachment|input_attachment; + usage = color_attachment|input_attachment|transient_attachment; initialLayout = undefined; }; - normals = { + normal = { imageType = VK_IMAGE_TYPE_2D; format = r16g16b16a16_sfloat; samples = 1; @@ -42,7 +42,22 @@ mipLevels = 1; arrayLayers = 1; tiling = optimal; - usage = color_attachment|input_attachment; + usage = color_attachment|input_attachment|transient_attachment; + initialLayout = undefined; + }; + position = { + imageType = VK_IMAGE_TYPE_2D; + format = r32g32b32a32_sfloat; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment|transient_attachment; initialLayout = undefined; }; opaque = { @@ -57,7 +72,7 @@ mipLevels = 1; arrayLayers = 1; tiling = optimal; - usage = color_attachment|input_attachment; + usage = color_attachment|input_attachment|transient_attachment; initialLayout = undefined; }; translucent = { @@ -72,7 +87,7 @@ mipLevels = 1; arrayLayers = 1; tiling = optimal; - usage = color_attachment|input_attachment; + usage = color_attachment|input_attachment|transient_attachment; initialLayout = undefined; }; }; @@ -109,10 +124,26 @@ layerCount = 1; }; }; - normals = { - image = normals; + normal = { + image = normal; viewType = VK_IMAGE_VIEW_TYPE_2D; - format = $properties.images.normals.format; + format = $properties.images.normal.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + position = { + image = position; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.position.format; components = { r = identity; g = identity; @@ -160,7 +191,7 @@ }; framebuffer = { renderPass = $properties.renderpass; - attachments = (depth, color, normals, opaque, translucent, + attachments = (depth, color, normal, position, opaque, translucent, "$swapchain.views[$swapImageIndex]"); width = $swapchain.extent.width; height = $swapchain.extent.height; @@ -169,7 +200,8 @@ clearValues = ( { depthStencil = { depth = 1; stencil = 0; }; }, { color = "[0, 0, 0, 1]"; }, // color - { color = "[0, 0, 0, 1]"; }, // normals + { color = "[0, 0, 0, 1]"; }, // normal + { color = "[0, 0, 0, 1]"; }, // position { color = "[0, 0, 0, 1]"; }, // opaque { color = "[0, 0, 0, 0]"; }, // translucent { color = "[0, 0, 0, 1]"; }, // swapchain @@ -197,7 +229,17 @@ finalLayout = color_attachment_optimal; }, { - format = $properties.images.normals.format; + format = $properties.images.normal.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, + { + format = $properties.images.position.format; samples = 1; loadOp = dont_care; storeOp = dont_care; @@ -252,16 +294,20 @@ attachment = 1; layout = color_attachment_optimal; }, - { // normals + { // normal attachment = 2; layout = color_attachment_optimal; }, + { // position + attachment = 3; + layout = color_attachment_optimal; + }, ); depthStencilAttachment = { attachment = 0; layout = depth_stencil_attachment_optimal; }; - preserveAttachments = (4); + preserveAttachments = (5); }, { // 2 lighting pipelineBindPoint = graphics; @@ -274,48 +320,52 @@ attachment = 1; layout = shader_read_only_optimal; }, - { // normals + { // normal attachment = 2; layout = shader_read_only_optimal; }, + { // position + attachment = 3; + layout = shader_read_only_optimal; + }, ); colorAttachments = ( { // opaque - attachment = 3; + attachment = 4; layout = color_attachment_optimal; }, ); - preserveAttachments = (4); + preserveAttachments = (5); }, { // 3 translucent pipelineBindPoint = graphics; colorAttachments = ( { // translucent - attachment = 4; + attachment = 5; layout = color_attachment_optimal; }, ); - preserveAttachments = (0, 1, 2, 3); + preserveAttachments = (0, 1, 2, 3, 4); }, { // 4 compose pipelineBindPoint = graphics; inputAttachments = ( { // opaque - attachment = 3; + attachment = 4; layout = shader_read_only_optimal; }, { // translucent - attachment = 4; + attachment = 5; layout = shader_read_only_optimal; }, ); colorAttachments = ( { // swapchain - attachment = 5; + attachment = 6; layout = color_attachment_optimal; }, ); - preserveAttachments = (0, 1, 2); + preserveAttachments = (0, 1, 2, 3); }, ); dependencies = ( diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index cb7cf82f9..446ed30c6 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -83,7 +83,7 @@ bindings = ( { type = input_attachment; - descriptorCount = "3z * $frames.size"; + descriptorCount = "4z * $frames.size"; }, ); }; @@ -132,7 +132,7 @@ binding = 0; descriptorType = uniform_buffer; descriptorCount = 1; - stageFlags = vertex; + stageFlags = vertex|geometry; }, { binding = 1; @@ -252,6 +252,12 @@ descriptorCount = 1; stageFlags = fragment; }, + { + binding = 3; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, ); }; lighting_lights = { @@ -499,6 +505,16 @@ alphaBlendOp = add; colorWriteMask = r|g|b|a; }, + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, ); }; dynamic = { @@ -639,6 +655,16 @@ alphaBlendOp = add; colorWriteMask = r|g|b|a; }, + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, { blendEnable = false; srcColorBlendFactor = src_alpha; diff --git a/libs/video/renderer/vulkan/shader/alias.vert b/libs/video/renderer/vulkan/shader/alias.vert index 871c3a0c0..a54b43674 100644 --- a/libs/video/renderer/vulkan/shader/alias.vert +++ b/libs/video/renderer/vulkan/shader/alias.vert @@ -18,7 +18,7 @@ layout (location = 3) in vec3 normalb; layout (location = 4) in vec2 uv; layout (location = 0) out vec2 st; -layout (location = 1) out vec3 position; +layout (location = 1) out vec4 position; layout (location = 2) out vec3 normal; void @@ -32,7 +32,7 @@ main (void) norm = mix (normala, normalb, blend); pos = (Model * vertex); gl_Position = Projection * (View * pos); - position = pos.xyz; + position = pos; normal = mat3 (Model) * norm; st = uv; } diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index 6ef33dd43..0808b87f7 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -11,11 +11,12 @@ layout (push_constant) uniform PushConstants { }; layout (location = 0) in vec2 st; -layout (location = 1) in vec3 position; +layout (location = 1) in vec4 position; layout (location = 2) in vec3 normal; layout (location = 0) out vec4 frag_color; layout (location = 1) out vec4 frag_normal; +layout (location = 2) out vec4 frag_position; void main (void) @@ -29,4 +30,5 @@ main (void) frag_color = c; frag_normal = vec4(normal, 1); + frag_position = position; } diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index 272499efa..e4578ce5e 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -15,9 +15,11 @@ layout (push_constant) uniform PushConstants { layout (location = 0) in vec4 tl_st; layout (location = 1) in vec3 direction; layout (location = 2) in vec3 normal; +layout (location = 3) in vec4 position; layout (location = 0) out vec4 frag_color; layout (location = 1) out vec4 frag_normal; +layout (location = 2) out vec4 frag_position; layout (constant_id = 0) const bool doWarp = false; layout (constant_id = 1) const bool doLight = true; @@ -123,4 +125,5 @@ main (void) } frag_color = c;//fogBlend (c); frag_normal = vec4 (normal, 0); + frag_position = position; } diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom index f1107f759..bb46ae43a 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom @@ -1,5 +1,11 @@ #version 450 +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection; + mat4 View; + mat4 Sky; +}; + layout (triangles) in; layout (triangle_strip, max_vertices = 3) out; layout (location = 0) in vec4 v_tl_st[]; @@ -8,6 +14,7 @@ layout (location = 1) in vec3 v_direction[]; layout (location = 0) out vec4 tl_st; layout (location = 1) out vec3 direction; layout (location = 2) out vec3 normal; +layout (location = 3) out vec4 position; void main() @@ -16,13 +23,15 @@ main() vec3 b = gl_in[1].gl_Position.xyz; vec3 c = gl_in[2].gl_Position.xyz; - vec3 n = normalize (cross (b - a, c - a)); + vec3 n = normalize (cross (c - a, b - a)); for (int vert = 0; vert < 3; vert++) { - gl_Position = gl_in[vert].gl_Position; + vec4 p = gl_in[vert].gl_Position; + gl_Position = Projection * (View * (p)); tl_st = v_tl_st[vert]; direction = v_direction[vert]; normal = n; + position = p; EmitVertex (); } EndPrimitive (); diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert index bb9e87e4a..abfb6c4e6 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert @@ -19,7 +19,8 @@ layout (location = 1) out vec3 direction; void main (void) { - gl_Position = Projection * (View * (Model * vertex)); + // geometry shader will take care of Projection and View + gl_Position = Model * vertex; direction = (Sky * vertex).xyz; tl_st = tl_uv; } diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 555682645..89ea7940d 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -3,6 +3,7 @@ layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput depth; layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput color; layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput normal; +layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput position; struct LightData { vec3 color; @@ -25,9 +26,12 @@ void main (void) { float d = subpassLoad (depth).r; - vec4 c; + vec3 c = subpassLoad (color).rgb; + vec3 n = subpassLoad (normal).rgb; + vec3 p = subpassLoad (position).rgb; - //c = vec4 (d, d, d, 1); - c = vec4 (subpassLoad (color).rgb, 1); - frag_color = c; + c = vec3 (d, d, d); + c = (n + 1)/2; + c = (p / 1024 + 1) / 2; + frag_color = vec4 (c, 1); } diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index e2748dcb3..fc7316ede 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -82,8 +82,10 @@ Vulkan_Compose_Draw (vulkan_ctx_t *ctx) dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, cctx->pipeline); - cframe->imageInfo[0].imageView = ctx->attachment_views->a[3]; - cframe->imageInfo[1].imageView = ctx->attachment_views->a[4]; + cframe->imageInfo[0].imageView + = ctx->attachment_views->a[QFV_attachOpaque]; + cframe->imageInfo[1].imageView + = ctx->attachment_views->a[QFV_attachTranslucent]; dfunc->vkUpdateDescriptorSets (device->dev, 2, cframe->descriptors, 0, 0); VkDescriptorSet sets[] = { diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 604e7ff94..84c756cdc 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -82,10 +82,15 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, lctx->pipeline); - lframe->imageInfo[0].imageView = ctx->attachment_views->a[0]; - lframe->imageInfo[1].imageView = ctx->attachment_views->a[1]; - lframe->imageInfo[2].imageView = ctx->attachment_views->a[2]; - dfunc->vkUpdateDescriptorSets (device->dev, 3, lframe->descriptors+1, 0, 0); + lframe->imageInfo[0].imageView = ctx->attachment_views->a[QFV_attachDepth]; + lframe->imageInfo[1].imageView = ctx->attachment_views->a[QFV_attachColor]; + lframe->imageInfo[2].imageView + = ctx->attachment_views->a[QFV_attachNormal]; + lframe->imageInfo[3].imageView + = ctx->attachment_views->a[QFV_attachPosition]; + dfunc->vkUpdateDescriptorSets (device->dev, LIGHTING_IMAGE_INFOS, + lframe->descriptors + LIGHTING_BUFFER_INFOS, + 0, 0); VkDescriptorSet sets[] = { lframe->descriptors[1].dstSet, From 33575f93d59b2d9f3415e6399f8e0c345ebeb4a7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Feb 2021 15:51:54 +0900 Subject: [PATCH 1345/3664] [vulkan] Implement deferred lighting for dlights Static lights are yet to come (so the screen is black most of the time), but dynamic lights work very nicely (and look very good) despite the falloff being incorrect. --- include/QF/Vulkan/qf_lighting.h | 19 ++++ libs/video/renderer/vulkan/qfpipeline.plist | 9 ++ .../renderer/vulkan/shader/lighting.frag | 38 +++++-- libs/video/renderer/vulkan/vulkan_lighting.c | 99 ++++++++++++++++++- 4 files changed, 152 insertions(+), 13 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index fab2ffc3d..8eaa53a6f 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -36,11 +36,29 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" +typedef struct qfv_light_s { + vec3_t color; + float intensity; + vec3_t position; + int radius; + vec3_t direction; + float cone; +} qfv_light_t; + +#define NUM_LIGHTS 128 + +typedef struct qfv_light_buffer_s { + int lightCount; + qfv_light_t lights[NUM_LIGHTS] __attribute__((aligned(16))); +} qfv_light_buffer_t; + + #define LIGHTING_BUFFER_INFOS 1 #define LIGHTING_IMAGE_INFOS 4 typedef struct lightingframe_s { VkCommandBuffer cmd; + VkBuffer light_buffer; VkDescriptorBufferInfo bufferInfo[LIGHTING_BUFFER_INFOS]; VkDescriptorImageInfo imageInfo[LIGHTING_IMAGE_INFOS]; VkWriteDescriptorSet descriptors[LIGHTING_BUFFER_INFOS @@ -54,6 +72,7 @@ typedef struct lightingctx_s { lightingframeset_t frames; VkPipeline pipeline; VkPipelineLayout layout; + VkDeviceMemory light_memory; } lightingctx_t; struct vulkan_ctx_s; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 446ed30c6..536c98a05 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -575,6 +575,15 @@ stage = fragment; name = main; module = $builtin/bsp_gbuf.frag; + specializationInfo = { + mapEntries = ( + { size = 4; offset = 0; constantID = 0; }, + { size = 4; offset = 0; constantID = 1; }, + { size = 4; offset = 0; constantID = 2; }, + { size = 4; offset = 4; constantID = 1; }, + ); + data = <00000000ffffffff>; + }; }, ); vertexInput = { diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 89ea7940d..9eef7c8bd 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -7,31 +7,49 @@ layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput p struct LightData { vec3 color; - float dist; + float intensity; vec3 position; - int type; + int radius; vec3 direction; float cone; }; -layout (constant_id = 0) const int MaxLights = 8; -/*layout (set = 1, binding = 0) uniform Lights { +layout (constant_id = 0) const int MaxLights = 128; +layout (set = 1, binding = 0) uniform Lights { int lightCount; LightData lights[MaxLights]; -};*/ +}; layout (location = 0) out vec4 frag_color; +vec3 +calc_light (LightData light, vec3 position, vec3 normal) +{ + vec3 dist = light.position - position; + vec3 incoming = normalize (dist); + float spotdot = -dot (incoming, light.direction); + float lightdot = dot (incoming, normal); + float d = dot (dist, dist); + float r = light.radius; + + float intensity = light.intensity * step (d, r * r); + intensity *= step (spotdot, light.cone) * clamp (lightdot, 0, 1); + return light.color * intensity; +} + void main (void) { - float d = subpassLoad (depth).r; + //float d = subpassLoad (depth).r; vec3 c = subpassLoad (color).rgb; vec3 n = subpassLoad (normal).rgb; vec3 p = subpassLoad (position).rgb; + vec3 light = vec3 (0); - c = vec3 (d, d, d); - c = (n + 1)/2; - c = (p / 1024 + 1) / 2; - frag_color = vec4 (c, 1); + if (MaxLights > 0) { + for (int i = 0; i < lightCount; i++) { + light += calc_light (lights[i], p, n); + } + } + frag_color = vec4 (c * light, 1); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 84c756cdc..8e41cf312 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -42,22 +42,85 @@ #include "qfalloca.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/Vulkan/qf_lighting.h" +#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/staging.h" + +#include "compat.h" #include "r_internal.h" #include "vid_vulkan.h" +static void +update_lights (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + lightingctx_t *lctx = ctx->lighting_context; + lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; + + dlight_t *lights[NUM_LIGHTS]; + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + qfv_light_buffer_t *light_data = QFV_PacketExtend (packet, + sizeof (*light_data)); + + light_data->lightCount = 0; + R_FindNearLights (r_origin, NUM_LIGHTS - 1, lights); + for (int i = 0; i < NUM_LIGHTS - 1; i++) { + if (!lights[i]) { + break; + } + light_data->lightCount++; + VectorCopy (lights[i]->color, light_data->lights[i].color); + VectorCopy (lights[i]->origin, light_data->lights[i].position); + light_data->lights[i].radius = lights[i]->radius; + light_data->lights[i].intensity = 1; + VectorZero (light_data->lights[i].direction); + light_data->lights[i].cone = 1; + } + + VkBufferMemoryBarrier wr_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + lframe->light_buffer, 0, sizeof (qfv_light_buffer_t) }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, 0, 1, wr_barriers, 0, 0); + VkBufferCopy copy_region[] = { + { packet->offset, 0, sizeof (qfv_light_buffer_t) }, + }; + dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, + lframe->light_buffer, 1, ©_region[0]); + VkBufferMemoryBarrier rd_barriers[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + lframe->light_buffer, 0, sizeof (qfv_light_buffer_t) }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + 0, 0, 0, 1, rd_barriers, 0, 0); + QFV_PacketSubmit (packet); +} + void Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + update_lights (ctx); + lightingctx_t *lctx = ctx->lighting_context; __auto_type cframe = &ctx->frames.a[ctx->curFrame]; lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; @@ -82,15 +145,16 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, lctx->pipeline); + lframe->bufferInfo[0].buffer = lframe->light_buffer; lframe->imageInfo[0].imageView = ctx->attachment_views->a[QFV_attachDepth]; lframe->imageInfo[1].imageView = ctx->attachment_views->a[QFV_attachColor]; lframe->imageInfo[2].imageView = ctx->attachment_views->a[QFV_attachNormal]; lframe->imageInfo[3].imageView = ctx->attachment_views->a[QFV_attachPosition]; - dfunc->vkUpdateDescriptorSets (device->dev, LIGHTING_IMAGE_INFOS, - lframe->descriptors + LIGHTING_BUFFER_INFOS, - 0, 0); + dfunc->vkUpdateDescriptorSets (device->dev, + LIGHTING_BUFFER_INFOS + LIGHTING_IMAGE_INFOS, + lframe->descriptors, 0, 0); VkDescriptorSet sets[] = { lframe->descriptors[1].dstSet, @@ -134,6 +198,7 @@ void Vulkan_Lighting_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); ctx->lighting_context = lctx; @@ -146,6 +211,25 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lctx->pipeline = Vulkan_CreatePipeline (ctx, "lighting"); lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout"); + __auto_type lbuffers = QFV_AllocBufferSet (frames, alloca); + for (size_t i = 0; i < frames; i++) { + lbuffers->a[i] = QFV_CreateBuffer (device, sizeof (qfv_light_buffer_t), + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, + lbuffers->a[i], + va (ctx->va_ctx, "buffer:lighting:%zd", i)); + } + VkMemoryRequirements requirements; + dfunc->vkGetBufferMemoryRequirements (device->dev, lbuffers->a[0], + &requirements); + lctx->light_memory = QFV_AllocBufferMemory (device, lbuffers->a[0], + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + frames * requirements.size, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + lctx->light_memory, "memory:lighting"); + + __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); @@ -171,6 +255,10 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); lframe->cmd = cmdSet->a[0]; + lframe->light_buffer = lbuffers->a[i]; + QFV_BindBufferMemory (device, lbuffers->a[i], lctx->light_memory, + i * requirements.size); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, lframe->cmd, "cmd:lighting"); for (int j = 0; j < LIGHTING_BUFFER_INFOS; j++) { @@ -201,6 +289,11 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; lightingctx_t *lctx = ctx->lighting_context; + for (size_t i = 0; i < lctx->frames.size; i++) { + lightingframe_t *lframe = &lctx->frames.a[i]; + dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0); + } + dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0); dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0); free (lctx->frames.a); free (lctx); From fd97bb145674f55a85b9e395e626794d066a9129 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Feb 2021 16:11:47 +0900 Subject: [PATCH 1346/3664] [vulkan] Implement linear falloff It's possibly too bright, but it might be the lights themselves. Still, it looks better than the no-falloff implementation. --- libs/video/renderer/vulkan/shader/lighting.frag | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 9eef7c8bd..3dfb755be 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -29,12 +29,12 @@ calc_light (LightData light, vec3 position, vec3 normal) vec3 incoming = normalize (dist); float spotdot = -dot (incoming, light.direction); float lightdot = dot (incoming, normal); - float d = dot (dist, dist); + float d = sqrt (dot (dist, dist)); float r = light.radius; - float intensity = light.intensity * step (d, r * r); + float intensity = light.intensity * step (d, r); intensity *= step (spotdot, light.cone) * clamp (lightdot, 0, 1); - return light.color * intensity; + return light.color * intensity * (r - d); } void From 407ea15e35260aba8f159402a3ab23798eb96a52 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 2 Mar 2021 15:05:19 +0900 Subject: [PATCH 1347/3664] [util] Fix some test bitrot --- libs/util/test/test-plist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/test/test-plist.c b/libs/util/test/test-plist.c index 0335493f2..bc8e0457a 100644 --- a/libs/util/test/test-plist.c +++ b/libs/util/test/test-plist.c @@ -29,7 +29,7 @@ test_string_io (const char *str) item = PL_NewString (str); saved = PL_WritePropertyList (item); PL_Free (item); - item = PL_GetPropertyList (saved); + item = PL_GetPropertyList (saved, 0); res = PL_String (item); if (!strcmp (str, res)) return 1; From 22c0bec03a9017529e63467d8769cb32612fe6ae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 13:02:35 +0900 Subject: [PATCH 1348/3664] [build] Clean up obsolete QF_PROCESS_NEED_DIRS Its need went away with the shift to non-recursive make. The macro is still available just in case. --- config.d/build_control.m4 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index be71d59f4..09e4a10c0 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -260,13 +260,8 @@ fi QF_NEED(top, [libs hw nq qtv qw]) -QF_PROCESS_NEED_DIRS(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav]) QF_PROCESS_NEED_FUNC(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav], QF_NEED(top,tools)) -QF_PROCESS_NEED_DIRS(libs,[util gamecode ruamoko gib audio image models video console net qw client]) - -QF_PROCESS_NEED_DIRS(ruamoko,[qwaq]) - if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) qfac_qfcc_include_qf="\$(qfcc_include_qf)" @@ -294,10 +289,7 @@ if test "$HAVE_ZLIB" = "yes"; then fi QF_SUBST(progs_gz) -QF_PROCESS_NEED_DIRS(top, [libs hw nq qtv qw tools ruamoko]) - QF_PROCESS_NEED_LIBS(swrend, [asm]) -QF_PROCESS_NEED_DIRS(vid_render, [gl glsl sw sw32 vulkan]) QF_PROCESS_NEED_LIBS(models, [gl glsl sw vulkan], [libs/models]) QF_PROCESS_NEED_LIBS(alias, [gl glsl sw vulkan], [libs/models/alias]) QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush]) From 9617bbef97be221895953c426d847b365005574e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 13:04:26 +0900 Subject: [PATCH 1349/3664] [build] Create static libs for render targets The static libs are used to build the plugins, but make it easy to use only those modules needed for tests. Fixes the link error when running "make check" with non-static plugins. --- config.d/build_control.m4 | 8 ++++ libs/video/renderer/Makemodule.am | 39 ++++++++++++++++--- libs/video/renderer/vulkan/test/Makemodule.am | 2 +- .../video/renderer/vulkan/vkgen/Makemodule.am | 2 + 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 09e4a10c0..a5fc7bc51 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -41,6 +41,7 @@ if test "x$HAVE_FBDEV" = xyes; then CL_TARGETS="$CL_TARGETS FBDEV" VID_TARGETS="$VID_TARGETS libs/video/targets/libQFfbdev.la" QF_NEED(vid_render, [sw]) + QF_NEED(render, [sw]) QF_NEED(models, [sw]) QF_NEED(alias, [sw]) QF_NEED(brush, [sw]) @@ -73,6 +74,7 @@ if test "x$HAVE_X" = xyes; then VID_TARGETS="$VID_TARGETS libs/video/targets/libQFx11.la" if test "$HAVE_VULKAN" = "yes"; then QF_NEED(vid_render, [vulkan]) + QF_NEED(render, [vulkan]) QF_NEED(models, [vulkan]) QF_NEED(alias, [vulkan]) QF_NEED(brush, [vulkan]) @@ -80,6 +82,7 @@ if test "x$HAVE_X" = xyes; then QF_NEED(sprite, [vulkan]) fi QF_NEED(vid_render, [sw sw32 gl glsl]) + QF_NEED(render, [sw sw32 gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -105,12 +108,14 @@ if test "x$HAVE_SDL" = xyes; then VID_TARGETS="$VID_TARGETS libs/video/targets/libQFsdl.la" if test "$HAVE_VULKAN" = "yes"; then QF_NEED(vid_render, [vulkan]) + QF_NEED(render, [vulkan]) QF_NEED(alias, [vulkan]) QF_NEED(brush, [vulkan]) QF_NEED(iqm, [vulkan]) QF_NEED(sprite, [vulkan]) fi QF_NEED(vid_render, [sw sw32 gl glsl]) + QF_NEED(render, [sw sw32 gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -133,6 +138,7 @@ if test "x$HAVE_SVGA" = xyes; then CL_TARGETS="$CL_TARGETS SVGAlib" VID_TARGETS="$VID_TARGETS libs/video/targets/libQFsvga.la" QF_NEED(vid_render, [sw]) + QF_NEED(render, [sw]) QF_NEED(models, [sw]) QF_NEED(alias, [sw]) QF_NEED(brush, [sw]) @@ -155,6 +161,7 @@ fi # CL_TARGETS="$CL_TARGETS WGL" # VID_TARGETS="$VID_TARGETS libs/video/targets/libQFwgl.la" # QF_NEED(vid_render, [gl]) +# QF_NEED(render, [gl]) # QF_NEED(models, [gl]) # QF_NEED(alias, [gl]) # QF_NEED(brush, [gl]) @@ -290,6 +297,7 @@ fi QF_SUBST(progs_gz) QF_PROCESS_NEED_LIBS(swrend, [asm]) +QF_PROCESS_NEED_LIBS(render, [gl glsl sw sw32 vulkan], [libs/video/renderer]) QF_PROCESS_NEED_LIBS(models, [gl glsl sw vulkan], [libs/models]) QF_PROCESS_NEED_LIBS(alias, [gl glsl sw vulkan], [libs/models/alias]) QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush]) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 8789de037..9eb2c2354 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -3,8 +3,12 @@ include libs/video/renderer/vulkan/vkgen/Makemodule.am #lib_LTLIBRARIES += @VID_REND_TARGETS@ plugin_LTLIBRARIES += @vid_render_plugins@ -noinst_LTLIBRARIES += libs/video/renderer/libQFrenderer.la @vid_render_static_plugins@ +noinst_LTLIBRARIES += \ + libs/video/renderer/libQFrenderer.la \ + @render_libs@ \ + @vid_render_static_plugins@ +#plugins EXTRA_LTLIBRARIES += \ libs/video/renderer/vid_render_sw.la \ libs/video/renderer/vid_render_sw32.la \ @@ -12,6 +16,14 @@ EXTRA_LTLIBRARIES += \ libs/video/renderer/vid_render_glsl.la \ libs/video/renderer/vid_render_vulkan.la +#helper libraries +EXTRA_LTLIBRARIES += \ + libs/video/renderer/librender_sw.la \ + libs/video/renderer/librender_sw32.la \ + libs/video/renderer/librender_gl.la \ + libs/video/renderer/librender_glsl.la \ + libs/video/renderer/librender_vulkan.la + video_renderer_common_sources = \ libs/video/renderer/crosshair.c \ libs/video/renderer/font8x8.c \ @@ -43,13 +55,16 @@ libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_progs.c video_renderer_gl_libs= \ + libs/video/renderer/librender_gl.la \ libs/models/libmodels_gl.la libs_video_renderer_vid_render_gl_la_LDFLAGS= $(plugin_ldflags) libs_video_renderer_vid_render_gl_la_LIBADD= $(video_renderer_gl_libs) libs_video_renderer_vid_render_gl_la_DEPENDENCIES= $(video_renderer_gl_libs) libs_video_renderer_vid_render_gl_la_SOURCES=\ $(video_renderer_common_sources) \ - libs/video/renderer/vid_render_gl.c \ + libs/video/renderer/vid_render_gl.c + +libs_video_renderer_librender_gl_la_SOURCES = \ libs/video/renderer/gl/gl_draw.c \ libs/video/renderer/gl/gl_dyn_lights.c \ libs/video/renderer/gl/gl_dyn_part.c \ @@ -91,13 +106,16 @@ SUFFICES=.frag .vert .spv .spvc .fc .vc .slc .glsl .plist .plc $(am__mv) $@.t $@ video_renderer_glsl_libs= \ + libs/video/renderer/librender_glsl.la \ libs/models/libmodels_glsl.la libs_video_renderer_vid_render_glsl_la_LDFLAGS= $(plugin_ldflags) libs_video_renderer_vid_render_glsl_la_LIBADD= $(video_renderer_glsl_libs) libs_video_renderer_vid_render_glsl_la_DEPENDENCIES=$(video_renderer_glsl_libs) libs_video_renderer_vid_render_glsl_la_SOURCES=\ $(video_renderer_common_sources) \ - libs/video/renderer/vid_render_glsl.c \ + libs/video/renderer/vid_render_glsl.c + +libs_video_renderer_librender_glsl_la_SOURCES = \ libs/video/renderer/glsl/glsl_alias.c \ libs/video/renderer/glsl/glsl_bsp.c \ libs/video/renderer/glsl/glsl_draw.c \ @@ -116,13 +134,16 @@ libs_video_renderer_vid_render_glsl_la_SOURCES=\ libs/video/renderer/glsl/vid_common_glsl.c video_renderer_sw_libs= \ + libs/video/renderer/librender_sw.la \ libs/models/libmodels_sw.la libs_video_renderer_vid_render_sw_la_LDFLAGS= $(plugin_ldflags) libs_video_renderer_vid_render_sw_la_LIBADD= $(video_renderer_sw_libs) libs_video_renderer_vid_render_sw_la_DEPENDENCIES= $(video_renderer_sw_libs) libs_video_renderer_vid_render_sw_la_SOURCES=\ $(video_renderer_common_sources) \ - libs/video/renderer/vid_render_sw.c \ + libs/video/renderer/vid_render_sw.c + +libs_video_renderer_librender_sw_la_SOURCES = \ libs/video/renderer/sw/d_copy.S \ libs/video/renderer/sw/d_draw.S \ libs/video/renderer/sw/d_edge.c \ @@ -170,13 +191,16 @@ libs_video_renderer_vid_render_sw_la_SOURCES=\ libs/video/renderer/sw/vid_common_sw.c video_renderer_sw32_libs= \ + libs/video/renderer/librender_sw32.la \ libs/models/libmodels_sw.la libs_video_renderer_vid_render_sw32_la_LDFLAGS= $(plugin_ldflags) libs_video_renderer_vid_render_sw32_la_LIBADD= $(video_renderer_sw32_libs) libs_video_renderer_vid_render_sw32_la_DEPENDENCIES=$(video_renderer_sw32_libs) libs_video_renderer_vid_render_sw32_la_SOURCES=\ $(video_renderer_common_sources) \ - libs/video/renderer/vid_render_sw32.c \ + libs/video/renderer/vid_render_sw32.c + +libs_video_renderer_librender_sw32_la_SOURCES = \ libs/video/renderer/sw32/d_edge.c \ libs/video/renderer/sw32/d_fill.c \ libs/video/renderer/sw32/d_init.c \ @@ -213,13 +237,16 @@ renderpass_src = libs/video/renderer/vulkan/deferred.plist renderpass_gen = libs/video/renderer/vulkan/deferred.plc video_renderer_vulkan_libs = \ + libs/video/renderer/librender_vulkan.la \ libs/models/libmodels_vulkan.la libs_video_renderer_vid_render_vulkan_la_LDFLAGS= $(plugin_ldflags) libs_video_renderer_vid_render_vulkan_la_LIBADD= $(video_renderer_vulkan_libs) libs_video_renderer_vid_render_vulkan_la_DEPENDENCIES=$(video_renderer_vulkan_libs) libs_video_renderer_vid_render_vulkan_la_SOURCES = \ $(video_renderer_common_sources) \ - libs/video/renderer/vid_render_vulkan.c \ + libs/video/renderer/vid_render_vulkan.c + +libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/barrier.c \ libs/video/renderer/vulkan/buffer.c \ libs/video/renderer/vulkan/command.c \ diff --git a/libs/video/renderer/vulkan/test/Makemodule.am b/libs/video/renderer/vulkan/test/Makemodule.am index cacb206f3..84c5ff136 100644 --- a/libs/video/renderer/vulkan/test/Makemodule.am +++ b/libs/video/renderer/vulkan/test/Makemodule.am @@ -7,7 +7,7 @@ TESTS += $(libs_video_renderer_vulkan_tests) check_PROGRAMS += $(libs_video_renderer_vulkan_tests) libs_video_renderer_vulkan_test_libs= \ - libs/video/renderer/vid_render_vulkan.la \ + libs/video/renderer/librender_vulkan.la \ libs/util/libQFutil.la libs_video_renderer_vulkan_test_test_staging_SOURCES= \ diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index b60e97f1d..ecb5853ee 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -47,5 +47,7 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/vkgen/vkgen.h \ libs/video/renderer/vulkan/vkgen/vkstruct.h \ libs/video/renderer/vulkan/vkgen/vktype.h \ + $e + CLEANFILES += \ libs/video/renderer/vkgen/*.sym From 45c02556439763bc517875026e56907fe618ea86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 16:17:15 +0900 Subject: [PATCH 1350/3664] [util] Add simd 4x4 matrix functions Currently just add, subtract, multiply (m m and m v). --- include/QF/simd/mat4f.h | 123 +++++++++++++++++++++++++++++++ include/QF/simd/types.h | 4 ++ libs/util/simd.c | 2 + libs/util/test/test-simd.c | 143 ++++++++++++++++++++++++++++++++++++- 4 files changed, 270 insertions(+), 2 deletions(-) create mode 100644 include/QF/simd/mat4f.h diff --git a/include/QF/simd/mat4f.h b/include/QF/simd/mat4f.h new file mode 100644 index 000000000..3e1880ad6 --- /dev/null +++ b/include/QF/simd/mat4f.h @@ -0,0 +1,123 @@ +/* + QF/simd/mat4f.h + + Matrix functions for mat4f_t (ie, float precision) + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_mat4f_h +#define __QF_simd_mat4f_h + +#include + +#include "QF/simd/types.h" + +GNU89INLINE inline void maddf (mat4f_t c, const mat4f_t a, const mat4f_t b); +GNU89INLINE inline void msubf (mat4f_t c, const mat4f_t a, const mat4f_t b); +GNU89INLINE inline void mmulf (mat4f_t c, const mat4f_t a, const mat4f_t b); +GNU89INLINE inline vec4f_t mvmulf (const mat4f_t m, vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t m3vmulf (const mat4f_t m, vec4f_t v) __attribute__((const)); +GNU89INLINE inline void mat4fidentity (mat4f_t m); + +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +maddf (mat4f_t c, const mat4f_t a, const mat4f_t b) +{ + c[0] = a[0] + b[0]; + c[1] = a[1] + b[1]; + c[2] = a[2] + b[2]; + c[3] = a[3] + b[3]; +} + +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +msubf (mat4f_t c, const mat4f_t a, const mat4f_t b) +{ + c[0] = a[0] - b[0]; + c[1] = a[1] - b[1]; + c[2] = a[2] - b[2]; + c[3] = a[3] - b[3]; +} + +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +mmulf (mat4f_t c, const mat4f_t a, const mat4f_t b) +{ + c[0] = a[0] * b[0][0] + a[1] * b[0][1] + a[2] * b[0][2] + a[3] * b[0][3]; + c[1] = a[0] * b[1][0] + a[1] * b[1][1] + a[2] * b[1][2] + a[3] * b[1][3]; + c[2] = a[0] * b[2][0] + a[1] * b[2][1] + a[2] * b[2][2] + a[3] * b[2][3]; + c[3] = a[0] * b[3][0] + a[1] * b[3][1] + a[2] * b[3][2] + a[3] * b[3][3]; +} + +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +mvmulf (const mat4f_t m, vec4f_t v) +{ + return m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * v[3]; +} + +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +m3vmulf (const mat4f_t m, vec4f_t v) +{ + vec4f_t w; + w = m[0] * v[0] + m[1] * v[1] + m[2] * v[2]; + w[3] = 1; + return w; +} + +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +mat4fidentity (mat4f_t m) +{ + m[0] = (vec4f_t) { 1, 0, 0, 0 }; + m[1] = (vec4f_t) { 0, 1, 0, 0 }; + m[2] = (vec4f_t) { 0, 0, 1, 0 }; + m[3] = (vec4f_t) { 0, 0, 0, 1 }; +} + +#endif//__QF_simd_mat4f_h diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index cd8b0da9d..e056abfac 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -82,4 +82,8 @@ VEC_TYPE (int, vec4i_t); #define VEC4I_FMT "[%d, %d, %d, %d]" #define VEC4_EXP(v) (v)[0], (v)[1], (v)[2], (v)[3] +#define MAT4_ROW(m, r) (m)[0][r], (m)[1][r], (m)[2][r], (m)[3][r] + +typedef vec4f_t mat4f_t[4]; +typedef vec4i_t mat4i_t[4]; #endif//__QF_simd_types_h diff --git a/libs/util/simd.c b/libs/util/simd.c index f5a0fcd35..84acc8798 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -32,6 +32,8 @@ #define IMPLEMENT_VEC4F_Funcs #define IMPLEMENT_VEC4D_Funcs +#define IMPLEMENT_MAT4F_Funcs #include "QF/simd/vec4d.h" #include "QF/simd/vec4f.h" +#include "QF/simd/mat4f.h" diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index 40a7276de..6fe524852 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -9,6 +9,7 @@ #include "QF/simd/vec4d.h" #include "QF/simd/vec4f.h" +#include "QF/simd/mat4f.h" #define right { 1, 0, 0 } #define forward { 0, 1, 0 } @@ -25,6 +26,22 @@ #define none { -1, -1, -1, -1 } #define nqident { 0, 0, 0, -1 } +#define identity \ + { { 1, 0, 0, 0 }, \ + { 0, 1, 0, 0 }, \ + { 0, 0, 1, 0 }, \ + { 0, 0, 0, 1 } } +#define rotate120 \ + { { 0, 1, 0, 0 }, \ + { 0, 0, 1, 0 }, \ + { 1, 0, 0, 0 }, \ + { 0, 0, 0, 1 } } +#define rotate240 \ + { { 0, 0, 1, 0 }, \ + { 1, 0, 0, 0 }, \ + { 0, 1, 0, 0 }, \ + { 0, 0, 0, 1 } } + #define s05 0.70710678118654757 typedef struct { @@ -43,6 +60,22 @@ typedef struct { vec4f_t ulp_errors; } vec4f_test_t; +typedef struct { + void (*op) (mat4f_t c, const mat4f_t a, const mat4f_t b); + mat4f_t a; + mat4f_t b; + mat4f_t expect; + mat4f_t ulp_errors; +} mat4f_test_t; + +typedef struct { + vec4f_t (*op) (const mat4f_t a, vec4f_t b); + mat4f_t a; + vec4f_t b; + vec4f_t expect; + vec4f_t ulp_errors; +} mv4f_test_t; + static vec4d_t tvtruncd (vec4d_t v, vec4d_t ignore) { return vtruncd (v); @@ -314,6 +347,26 @@ static vec4f_test_t vec4f_tests[] = { }; #define num_vec4f_tests (sizeof (vec4f_tests) / (sizeof (vec4f_tests[0]))) +static mat4f_test_t mat4f_tests[] = { + { mmulf, identity, identity, identity }, + { mmulf, rotate120, identity, rotate120 }, + { mmulf, identity, rotate120, rotate120 }, + { mmulf, rotate120, rotate120, rotate240 }, + { mmulf, rotate120, rotate240, identity }, + { mmulf, rotate240, rotate120, identity }, +}; +#define num_mat4f_tests (sizeof (mat4f_tests) / (sizeof (mat4f_tests[0]))) + +static mv4f_test_t mv4f_tests[] = { + { mvmulf, identity, { 1, 0, 0, 0 }, { 1, 0, 0, 0 } }, + { mvmulf, identity, { 0, 1, 0, 0 }, { 0, 1, 0, 0 } }, + { mvmulf, identity, { 0, 0, 1, 0 }, { 0, 0, 1, 0 } }, + { mvmulf, identity, { 0, 0, 0, 1 }, { 0, 0, 0, 1 } }, + { mvmulf, rotate120, { 1, 2, 3, 4 }, { 3, 1, 2, 4 } }, + { mvmulf, rotate240, { 1, 2, 3, 4 }, { 2, 3, 1, 4 } }, +}; +#define num_mv4f_tests (sizeof (mv4f_tests) / (sizeof (mv4f_tests[0]))) + static int run_vec4d_tests (void) { @@ -326,7 +379,7 @@ run_vec4d_tests (void) vec4l_t res = result != expect; if (res[0] || res[1] || res[2] || res[3]) { ret |= 1; - printf ("\nrun_vec4d_tests\n"); + printf ("\nrun_vec4d_tests %zd\n", i); printf ("a: " VEC4D_FMT "\n", VEC4_EXP(test->a)); printf ("b: " VEC4D_FMT "\n", VEC4_EXP(test->b)); printf ("r: " VEC4D_FMT "\n", VEC4_EXP(result)); @@ -351,7 +404,7 @@ run_vec4f_tests (void) vec4i_t res = result != expect; if (res[0] || res[1] || res[2] || res[3]) { ret |= 1; - printf ("\nrun_vec4f_tests\n"); + printf ("\nrun_vec4f_tests %zd\n", i); printf ("a: " VEC4F_FMT "\n", VEC4_EXP(test->a)); printf ("b: " VEC4F_FMT "\n", VEC4_EXP(test->b)); printf ("r: " VEC4F_FMT "\n", VEC4_EXP(result)); @@ -364,11 +417,97 @@ run_vec4f_tests (void) return ret; } +static int +run_mat4f_tests (void) +{ + int ret = 0; + + for (size_t i = 0; i < num_mat4f_tests; i++) { + __auto_type test = &mat4f_tests[i]; + mat4f_t result; + mat4f_t expect; + mat4i_t res = {}; + + test->op (result, test->a, test->b); + maddf (expect, test->expect, test->ulp_errors); + + int fail = 0; + for (int j = 0; j < 4; j++) { + res[j] = result[j] != expect[j]; + fail |= res[j][0] || res[j][1] || res[j][2] || res[j][3]; + } + if (fail) { + ret |= 1; + printf ("\nrun_mat4f_tests %zd\n", i); + printf ("a: " VEC4F_FMT "\n", MAT4_ROW(test->a, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 3)); + printf ("b: " VEC4F_FMT "\n", MAT4_ROW(test->b, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->b, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->b, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->b, 3)); + printf ("r: " VEC4F_FMT "\n", MAT4_ROW(result, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(result, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(result, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(result, 3)); + printf ("t: " VEC4I_FMT "\n", MAT4_ROW(res, 0)); + printf (" " VEC4I_FMT "\n", MAT4_ROW(res, 1)); + printf (" " VEC4I_FMT "\n", MAT4_ROW(res, 2)); + printf (" " VEC4I_FMT "\n", MAT4_ROW(res, 3)); + printf ("E: " VEC4F_FMT "\n", MAT4_ROW(expect, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(expect, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(expect, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(expect, 3)); + printf ("e: " VEC4F_FMT "\n", MAT4_ROW(test->expect, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->expect, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->expect, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->expect, 3)); + printf ("u: " VEC4F_FMT "\n", MAT4_ROW(test->ulp_errors, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->ulp_errors, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->ulp_errors, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->ulp_errors, 3)); + } + } + return ret; +} + +static int +run_mv4f_tests (void) +{ + int ret = 0; + + for (size_t i = 0; i < num_mv4f_tests; i++) { + __auto_type test = &mv4f_tests[i]; + vec4f_t result = test->op (test->a, test->b); + vec4f_t expect = test->expect + test->ulp_errors; + vec4i_t res = result != expect; + + if (res[0] || res[1] || res[2] || res[3]) { + ret |= 1; + printf ("\nrun_mat4f_tests %zd\n", i); + printf ("a: " VEC4F_FMT "\n", MAT4_ROW(test->a, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 3)); + printf ("b: " VEC4F_FMT "\n", VEC4_EXP(test->b)); + printf ("r: " VEC4F_FMT "\n", VEC4_EXP(result)); + printf ("t: " VEC4I_FMT "\n", VEC4_EXP(res)); + printf ("E: " VEC4F_FMT "\n", VEC4_EXP(expect)); + printf ("e: " VEC4F_FMT "\n", VEC4_EXP(test->expect)); + printf ("u: " VEC4F_FMT "\n", VEC4_EXP(test->ulp_errors)); + } + } + return ret; +} + int main (void) { int ret = 0; ret |= run_vec4d_tests (); ret |= run_vec4f_tests (); + ret |= run_mat4f_tests (); + ret |= run_mv4f_tests (); return ret; } From eb0aa2dceaa63ccab8d025135dcf7ac8f9221064 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 16:21:37 +0900 Subject: [PATCH 1351/3664] [renderer] Clean up most globals in efrags There's still the memory management itself to clean up, but the main code no longer uses any static/global variables (holdover from when the function was recursive rather). --- libs/video/renderer/r_efrag.c | 61 +++++++++++++++++------------------ 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 8785d3d7d..4c93c935c 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -33,11 +33,9 @@ #include "QF/render.h" #include "QF/sys.h" +#include "qfalloca.h" #include "r_internal.h" -static mnode_t *r_pefragtopnode; -static vec3_t r_emins, r_emaxs; - typedef struct s_efrag_list { struct s_efrag_list *next; efrag_t efrags[MAX_EFRAGS]; @@ -48,10 +46,6 @@ static t_efrag_list *efrag_list; /* ENTITY FRAGMENT FUNCTIONS */ -static efrag_t **lastlink; -static entity_t *r_addent; - - static inline void init_efrag_list (t_efrag_list *efl) { @@ -133,32 +127,39 @@ R_RemoveEfrags (entity_t *ent) ent->efrag = 0; } -#define NODE_STACK_SIZE 1024 -static mnode_t *node_stack[NODE_STACK_SIZE]; -static mnode_t **node_ptr = node_stack + NODE_STACK_SIZE; - static void -R_SplitEntityOnNode (mnode_t *node) +R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, + vec3_t emins, vec3_t emaxs) { efrag_t *ef; plane_t *splitplane; mleaf_t *leaf; int sides; + efrag_t **lastlink; + mnode_t **node_stack; + mnode_t **node_ptr; + mnode_t *node = brush->nodes; - *--node_ptr = 0; + node_stack = alloca ((brush->depth + 2) * sizeof (mnode_t *)); + node_ptr = node_stack; + + lastlink = &ent->efrag; + + *node_ptr++ = 0; while (node) { // add an efrag if the node is a leaf if (__builtin_expect (node->contents < 0, 0)) { - if (!r_pefragtopnode) - r_pefragtopnode = node; + if (!ent->topnode) { + ent->topnode = node; + } leaf = (mleaf_t *) node; ef = new_efrag (); // ensures ef->entnext is 0 // add the link to the chain of links on the entity - ef->entity = r_addent; + ef->entity = ent; *lastlink = ef; lastlink = &ef->entnext; @@ -167,28 +168,29 @@ R_SplitEntityOnNode (mnode_t *node) ef->leafnext = leaf->efrags; leaf->efrags = ef; - node = *node_ptr++; + node = *--node_ptr; } else { // NODE_MIXED splitplane = node->plane; - sides = BOX_ON_PLANE_SIDE (r_emins, r_emaxs, splitplane); + sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane); if (sides == 3) { // split on this plane // if this is the first splitter of this bmodel, remember it - if (!r_pefragtopnode) - r_pefragtopnode = node; + if (!ent->topnode) { + ent->topnode = node; + } } // recurse down the contacted sides if (sides & 1 && node->children[0]->contents != CONTENTS_SOLID) { if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID) - *--node_ptr = node->children[1]; + *node_ptr++ = node->children[1]; node = node->children[0]; } else { if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID) node = node->children[1]; else - node = *node_ptr++; + node = *--node_ptr; } } } @@ -198,6 +200,7 @@ void R_AddEfrags (mod_brush_t *brush, entity_t *ent) { model_t *entmodel; + vec3_t emins, emaxs; if (!ent->model || !r_worldentity.model) return; @@ -205,19 +208,13 @@ R_AddEfrags (mod_brush_t *brush, entity_t *ent) if (ent == &r_worldentity) return; // never add the world - r_addent = ent; - - lastlink = &ent->efrag; - r_pefragtopnode = 0; - entmodel = ent->model; - VectorAdd (ent->origin, entmodel->mins, r_emins); - VectorAdd (ent->origin, entmodel->maxs, r_emaxs); + VectorAdd (ent->origin, entmodel->mins, emins); + VectorAdd (ent->origin, entmodel->maxs, emaxs); - R_SplitEntityOnNode (brush->nodes); - - ent->topnode = r_pefragtopnode; + ent->topnode = 0; + R_SplitEntityOnNode (brush, ent, emins, emaxs); } void From 60348ab458561afb26409e1d83fe0067d806f046 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 16:34:44 +0900 Subject: [PATCH 1352/3664] [headers] Fix some inconsistent include guards --- include/QF/cexpr.h | 6 +++--- include/QF/cmem.h | 6 +++--- include/QF/darray.h | 8 +++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 4e2dd3bcb..9a79690a6 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __expr_h -#define __expr_h +#ifndef __QF_expr_h +#define __QF_expr_h #include @@ -140,4 +140,4 @@ extern exprtype_t cexpr_plitem; extern binop_t cexpr_struct_binops[]; extern binop_t cexpr_struct_pointer_binops[]; -#endif +#endif//__QF_expr_h diff --git a/include/QF/cmem.h b/include/QF/cmem.h index 5f0d733ea..f9c47d4c1 100644 --- a/include/QF/cmem.h +++ b/include/QF/cmem.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __cmem_h -#define __cmem_h +#ifndef __QF_cmem_h +#define __QF_cmem_h #include "QF/qtypes.h" @@ -115,4 +115,4 @@ void delete_memsuper (memsuper_t *super); void *cmemalloc (memsuper_t *super, size_t size); void cmemfree (memsuper_t *super, void *mem); -#endif//__cmem_h +#endif//__QF_cmem_h diff --git a/include/QF/darray.h b/include/QF/darray.h index 50dc6c348..c2e21d7e1 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -28,8 +28,10 @@ */ -#ifndef __darray_h -#define __darray_h +#ifndef __QF_darray_h +#define __QF_darray_h + +#include "QF/sys.h" /** \defgroup darray Dynamic Arrays \ingroup utils @@ -363,4 +365,4 @@ ///@} -#endif//__darray_h +#endif//__QF_darray_h From e3762d8f38dec6a7617c49deb4b619ff69f9c314 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 18:01:35 +0900 Subject: [PATCH 1353/3664] [util] Make plist mostly null-safe The main purpose is to allow fluent-style: const char *targetname = PL_String (PL_ObjectForKey (entity, "targetname")); if (targetname && !PL_ObjectForKey (targets, targetname)) { PL_D_AddObject (targets, targetname, entity); } [note: the above is iffy due to ownership of entity, but the code from which the above comes works around the issue] --- include/QF/qfplist.h | 52 ++++++++------- libs/util/qfplist.c | 152 ++++++++++++++++++++++++------------------- 2 files changed, 113 insertions(+), 91 deletions(-) diff --git a/include/QF/qfplist.h b/include/QF/qfplist.h index cef305086..a4994476d 100644 --- a/include/QF/qfplist.h +++ b/include/QF/qfplist.h @@ -136,14 +136,14 @@ char *PL_WritePropertyList (const plitem_t *pl); /** Retrieve the type of an object. - \param item The object + \param item The object. Must not be null. \return the type of the object */ pltype_t PL_Type (const plitem_t *item) __attribute__((pure)); /** Retrieve the line number of an object. - \param item The object + \param item The object. Must not be null. \return the line number on which the object began, or 0 if not from a string */ @@ -152,15 +152,16 @@ int PL_Line (const plitem_t *item) __attribute__((pure)); /** Retrieve the data size from a binary object. \param binary The binary object - \return the size in bytes of the binary object 0 if binary isn't a binary - object. + \return the size in bytes of the binary object 0 if \a binary isn't a + binary object (includes if \a binary is null). */ size_t PL_BinarySize (const plitem_t *binary) __attribute__((pure)); /** Retrieve the data from a binary object. \param binary The binary object - \return pointer to the actual data or NULL if binary isn't a binary object. + \return pointer to the actual data or NULL if \b binary isn't a binary + object (includes if \a binary is null). \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ @@ -170,7 +171,7 @@ const void *PL_BinaryData (const plitem_t *binary) __attribute__((pure)); \param string The string object \return pointer to the actual string value or NULL if string isn't a - string. + string (includes if \a string is null). \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ @@ -180,8 +181,8 @@ const char *PL_String (const plitem_t *string) __attribute__((pure)); \param dict The dictionary to retrieve a value from \param key The unique key associated with the value - \return the value associated with the key, or NULL if not found or dict - isn't a dictionary. + \return the value associated with the key, or NULL if not found or \a dict + isn't a dictionary (includes if \a dict is null). \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ @@ -191,8 +192,8 @@ plitem_t *PL_ObjectForKey (const plitem_t *dict, const char *key); \param dict The Dictionary to remove the value from \param key The unique key associated with the value to be removed - \return the value associated with the key, or NULL if not found or dict - isn't a dictionary. + \return the value associated with the key, or NULL if not found or \a dict + isn't a dictionary (includes if \a dict is null). \note You are responsible for freeing the returned object. */ plitem_t *PL_RemoveObjectForKey (const plitem_t *dict, const char *key); @@ -202,19 +203,18 @@ plitem_t *PL_RemoveObjectForKey (const plitem_t *dict, const char *key); \param dict The dictionary to get the key from \param index The index of the key \return the key at the specified index, or NULL if index is out of range or - dict is not a dictionaly - isn't an array. + dict is not a dictionary (includes if \a dict is null). \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ -const char *PL_KeyAtIndex (const plitem_t *array, int index) __attribute__((pure)); +const char *PL_KeyAtIndex (const plitem_t *dict, int index) __attribute__((pure)); /** Retrieve a value from an array object. \param array The array to get the value from \param index The index within the array to retrieve - \return the value at the specified index, or NULL if index is out of range - or array is not an array. + \return the value at the specified index, or NULL if \a index is out of + range or \a array is not an array (includes in \a array is null). \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ @@ -223,7 +223,8 @@ plitem_t *PL_ObjectAtIndex (const plitem_t *array, int index) __attribute__((pur /** Retrieve a list of all keys in a dictionary. \param dict The dictionary to list - \return an Array containing Strings or NULL if dict isn't a dictionary + \return an Array containing Strings or NULL if \a dict isn't a dictionary + (includes if \a dict is null). \note You are responsible for freeing this array. */ plitem_t *PL_D_AllKeys (const plitem_t *dict); @@ -232,7 +233,8 @@ plitem_t *PL_D_AllKeys (const plitem_t *dict); \param dict The dictionary to get the number of keys of. - \return Returns the number of keys in the dictionary. + \return Returns the number of keys in the dictionary or 0 if \a dict isn't + a dictionary (includes if \a dict is null). */ int PL_D_NumKeys (const plitem_t *dict) __attribute__((pure)); @@ -242,7 +244,8 @@ int PL_D_NumKeys (const plitem_t *dict) __attribute__((pure)); \param key The key of the key/value pair to be added to the dictionary \param value The value of the key/value pair to be added to the dictionary - \return true on success, false on failure + \return true on success, false on failure (\a dict is null or not a + dictionary) \note the dictionary becomes the owner of the value. */ @@ -253,7 +256,8 @@ qboolean PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value); \param array The array to which the item will be added \param item The item to be added to the array - \return true on success, false on failure + \return true on success, false on failure (\a array is null or not an + array) \note the array becomes the owner of the added item. */ @@ -263,7 +267,8 @@ qboolean PL_A_AddObject (plitem_t *array, plitem_t *item); \param array The array from which to get the number of objects - \return number of objects in the array + \return number of objects in the array or 0 if \a array is null or not + an array. */ int PL_A_NumObjects (const plitem_t *array) __attribute__((pure)); @@ -273,7 +278,8 @@ int PL_A_NumObjects (const plitem_t *array) __attribute__((pure)); \param item The item to be added to the array \param index The location at which to insert the item into the array - \return true on success, false on failure + \return true on success, false on failure (\a array is null or not an + array). \note the array becomes the owner of the added item. */ @@ -285,7 +291,7 @@ qboolean PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index); \param array The array from which to remove the value \param index The index within the array to remove \return the value associated with the index, or NULL if not found or array - isn't an array. + is noll or an array. \note You are responsible for freeing the returned object. */ plitem_t *PL_RemoveObjectAtIndex (plitem_t *array, int index); @@ -323,7 +329,7 @@ plitem_t *PL_NewString (const char *str); /** Free a property list object. This function takes care of freeing any referenced property list data, so - call it only on top-level objects. + call it only on top-level objects. Safe to call with a null argument. \param item the property list object to be freed */ diff --git a/libs/util/qfplist.c b/libs/util/qfplist.c index 56c168168..454c549f7 100644 --- a/libs/util/qfplist.c +++ b/libs/util/qfplist.c @@ -132,11 +132,11 @@ init_quotables (void) quotable_bitmap[*c / 8] &= ~(1 << (*c % 8)); } -static plitem_t *PL_ParsePropertyListItem (pldata_t *); -static qboolean PL_SkipSpace (pldata_t *); -static char *PL_ParseQuotedString (pldata_t *); -static char *PL_ParseUnquotedString (pldata_t *); -static char *PL_ParseData (pldata_t *, int *); +static plitem_t *pl_parsepropertylistitem (pldata_t *); +static qboolean pl_skipspace (pldata_t *); +static char *pl_parsequotedstring (pldata_t *); +static char *pl_parseunquotedstring (pldata_t *); +static char *pl_parsedata (pldata_t *, int *); static const char * dict_get_key (const void *i, void *unused) @@ -156,7 +156,7 @@ dict_free (void *i, void *unused) } static plitem_t * -PL_NewItem (pltype_t type) +pl_newitem (pltype_t type) { plitem_t *item = calloc (1, sizeof (plitem_t)); item->type = type; @@ -166,7 +166,7 @@ PL_NewItem (pltype_t type) VISIBLE plitem_t * PL_NewDictionary (hashlink_t **hashlinks) { - plitem_t *item = PL_NewItem (QFDictionary); + plitem_t *item = pl_newitem (QFDictionary); pldict_t *dict = malloc (sizeof (pldict_t)); dict->tab = Hash_NewTable (1021, dict_get_key, dict_free, NULL, hashlinks); DARRAY_INIT (&dict->keys, 8); @@ -177,7 +177,7 @@ PL_NewDictionary (hashlink_t **hashlinks) VISIBLE plitem_t * PL_NewArray (void) { - plitem_t *item = PL_NewItem (QFArray); + plitem_t *item = pl_newitem (QFArray); plarray_t *array = calloc (1, sizeof (plarray_t)); item->data = array; return item; @@ -186,7 +186,7 @@ PL_NewArray (void) VISIBLE plitem_t * PL_NewData (void *data, size_t size) { - plitem_t *item = PL_NewItem (QFBinary); + plitem_t *item = pl_newitem (QFBinary); plbinary_t *bin = malloc (sizeof (plbinary_t)); item->data = bin; bin->data = data; @@ -197,7 +197,7 @@ PL_NewData (void *data, size_t size) static plitem_t * new_string (char *str, int line) { - plitem_t *item = PL_NewItem (QFString); + plitem_t *item = pl_newitem (QFString); item->data = str; item->line = line; return item; @@ -215,6 +215,9 @@ PL_Free (plitem_t *item) pldict_t *dict; plarray_t *array; + if (!item) { + return; + } switch (item->type) { case QFDictionary: dict = item->data; @@ -252,51 +255,54 @@ PL_Free (plitem_t *item) VISIBLE size_t PL_BinarySize (const plitem_t *binary) { - plbinary_t *bin = (plbinary_t *) binary->data; - - if (binary->type != QFBinary) + if (!binary || binary->type != QFBinary) { return 0; + } + + plbinary_t *bin = (plbinary_t *) binary->data; return bin->size; } VISIBLE const void * PL_BinaryData (const plitem_t *binary) { - plbinary_t *bin = (plbinary_t *) binary->data; - - if (binary->type != QFBinary) + if (!binary || binary->type != QFBinary) { return 0; + } + + plbinary_t *bin = (plbinary_t *) binary->data; return bin->data; } VISIBLE const char * PL_String (const plitem_t *string) { - if (string->type != QFString) + if (!string || string->type != QFString) { return NULL; + } return string->data; } VISIBLE plitem_t * PL_ObjectForKey (const plitem_t *item, const char *key) { - pldict_t *dict = (pldict_t *) item->data; - dictkey_t *k; - - if (item->type != QFDictionary) + if (!item || item->type != QFDictionary) { return NULL; + } - k = (dictkey_t *) Hash_Find (dict->tab, key); + pldict_t *dict = (pldict_t *) item->data; + dictkey_t *k = (dictkey_t *) Hash_Find (dict->tab, key); return k ? k->value : NULL; } VISIBLE const char * PL_KeyAtIndex (const plitem_t *item, int index) { - pldict_t *dict = (pldict_t *) item->data; - - if (item->type != QFDictionary) + if (!item || item->type != QFDictionary) { return NULL; + } + + pldict_t *dict = (pldict_t *) item->data; if (index < 0 || (size_t) index >= dict->keys.size) { return NULL; } @@ -307,13 +313,14 @@ PL_KeyAtIndex (const plitem_t *item, int index) VISIBLE plitem_t * PL_RemoveObjectForKey (const plitem_t *item, const char *key) { + if (!item || item->type != QFDictionary) { + return NULL; + } + pldict_t *dict = (pldict_t *) item->data; dictkey_t *k; plitem_t *value; - if (item->type != QFDictionary) - return NULL; - k = (dictkey_t *) Hash_Del (dict->tab, key); if (!k) return NULL; @@ -332,13 +339,14 @@ PL_RemoveObjectForKey (const plitem_t *item, const char *key) VISIBLE plitem_t * PL_D_AllKeys (const plitem_t *item) { + if (!item || item->type != QFDictionary) { + return NULL; + } + pldict_t *dict = (pldict_t *) item->data; dictkey_t *current; plitem_t *array; - if (item->type != QFDictionary) - return NULL; - if (!(array = PL_NewArray ())) return NULL; @@ -353,32 +361,35 @@ PL_D_AllKeys (const plitem_t *item) VISIBLE int PL_D_NumKeys (const plitem_t *item) { - pldict_t *dict = (pldict_t *) item->data; - if (item->type != QFDictionary) + if (!item || item->type != QFDictionary) { return 0; + } + + pldict_t *dict = (pldict_t *) item->data; return Hash_NumElements (dict->tab); } VISIBLE plitem_t * PL_ObjectAtIndex (const plitem_t *array, int index) { - plarray_t *arr = (plarray_t *) array->data; - - if (array->type != QFArray) + if (!array || array->type != QFArray) { return NULL; + } + plarray_t *arr = (plarray_t *) array->data; return index >= 0 && index < arr->numvals ? arr->values[index] : NULL; } VISIBLE qboolean PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) { + if (!item || item->type != QFDictionary || !value) { + return false; + } + pldict_t *dict = (pldict_t *) item->data; dictkey_t *k; - if (item->type != QFDictionary) - return false; - if ((k = Hash_Find (dict->tab, key))) { PL_Free ((plitem_t *) k->value); k->value = value; @@ -400,10 +411,11 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) VISIBLE qboolean PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index) { - plarray_t *arr; - - if (array->type != QFArray) + if (!array || array->type != QFArray || !item) { return false; + } + + plarray_t *arr; arr = (plarray_t *)array->data; @@ -442,20 +454,22 @@ PL_A_AddObject (plitem_t *array, plitem_t *item) VISIBLE int PL_A_NumObjects (const plitem_t *array) { - if (array->type != QFArray) + if (!array || array->type != QFArray) { return 0; + } return ((plarray_t *) array->data)->numvals; } VISIBLE plitem_t * PL_RemoveObjectAtIndex (plitem_t *array, int index) { + if (!array || array->type != QFArray) { + return 0; + } + plarray_t *arr; plitem_t *item; - if (array->type != QFArray) - return 0; - arr = (plarray_t *)array->data; if (index < 0 || index >= arr->numvals) @@ -472,7 +486,7 @@ PL_RemoveObjectAtIndex (plitem_t *array, int index) } static qboolean -PL_SkipSpace (pldata_t *pl) +pl_skipspace (pldata_t *pl) { while (pl->pos < pl->end) { char c = pl->ptr[pl->pos]; @@ -545,7 +559,7 @@ make_byte (byte h, byte l) } static char * -PL_ParseData (pldata_t *pl, int *len) +pl_parsedata (pldata_t *pl, int *len) { unsigned start = ++pl->pos; int nibbles = 0, i; @@ -578,7 +592,7 @@ PL_ParseData (pldata_t *pl, int *len) } static char * -PL_ParseQuotedString (pldata_t *pl) +pl_parsequotedstring (pldata_t *pl) { unsigned int start = ++pl->pos; unsigned int escaped = 0; @@ -731,7 +745,7 @@ PL_ParseQuotedString (pldata_t *pl) } static char * -PL_ParseUnquotedString (pldata_t *pl) +pl_parseunquotedstring (pldata_t *pl) { unsigned int start = pl->pos; char *str; @@ -747,11 +761,11 @@ PL_ParseUnquotedString (pldata_t *pl) } static plitem_t * -PL_ParsePropertyListItem (pldata_t *pl) +pl_parsepropertylistitem (pldata_t *pl) { plitem_t *item = NULL; - if (!PL_SkipSpace (pl)) + if (!pl_skipspace (pl)) return NULL; switch (pl->ptr[pl->pos]) { @@ -762,16 +776,16 @@ PL_ParsePropertyListItem (pldata_t *pl) pl->pos++; - while (PL_SkipSpace (pl) && pl->ptr[pl->pos] != '}') { + while (pl_skipspace (pl) && pl->ptr[pl->pos] != '}') { plitem_t *key; plitem_t *value; - if (!(key = PL_ParsePropertyListItem (pl))) { + if (!(key = pl_parsepropertylistitem (pl))) { PL_Free (item); return NULL; } - if (!(PL_SkipSpace (pl))) { + if (!(pl_skipspace (pl))) { PL_Free (key); PL_Free (item); return NULL; @@ -793,13 +807,13 @@ PL_ParsePropertyListItem (pldata_t *pl) pl->pos++; // If there is no value, lose the key - if (!(value = PL_ParsePropertyListItem (pl))) { + if (!(value = pl_parsepropertylistitem (pl))) { PL_Free (key); PL_Free (item); return NULL; } - if (!(PL_SkipSpace (pl))) { + if (!(pl_skipspace (pl))) { PL_Free (key); PL_Free (value); PL_Free (item); @@ -842,15 +856,15 @@ PL_ParsePropertyListItem (pldata_t *pl) pl->pos++; - while (PL_SkipSpace (pl) && pl->ptr[pl->pos] != ')') { + while (pl_skipspace (pl) && pl->ptr[pl->pos] != ')') { plitem_t *value; - if (!(value = PL_ParsePropertyListItem (pl))) { + if (!(value = pl_parsepropertylistitem (pl))) { PL_Free (item); return NULL; } - if (!(PL_SkipSpace (pl))) { + if (!(pl_skipspace (pl))) { PL_Free (value); PL_Free (item); return NULL; @@ -879,7 +893,7 @@ PL_ParsePropertyListItem (pldata_t *pl) case '<': { int len; - char *str = PL_ParseData (pl, &len); + char *str = pl_parsedata (pl, &len); if (!str) { return NULL; @@ -892,7 +906,7 @@ PL_ParsePropertyListItem (pldata_t *pl) case '"': { int line = pl->line; - char *str = PL_ParseQuotedString (pl); + char *str = pl_parsequotedstring (pl); if (!str) { return NULL; @@ -903,7 +917,7 @@ PL_ParsePropertyListItem (pldata_t *pl) default: { int line = pl->line; - char *str = PL_ParseUnquotedString (pl); + char *str = pl_parseunquotedstring (pl); if (!str) { return NULL; @@ -931,7 +945,7 @@ PL_GetPropertyList (const char *string, hashlink_t **hashlinks) pl->va_ctx = va_create_context (4); pl->hashlinks = hashlinks; - if ((newpl = PL_ParsePropertyListItem (pl))) { + if ((newpl = pl_parsepropertylistitem (pl))) { va_destroy_context (pl->va_ctx); free (pl); return newpl; @@ -1111,10 +1125,12 @@ PL_WritePropertyList (const plitem_t *pl) { dstring_t *dstr = dstring_newstr (); - if (!quotable_bitmap[0]) - init_quotables (); - write_item (dstr, pl, 0); - write_string_len (dstr, "\n", 1); + if (pl) { + if (!quotable_bitmap[0]) + init_quotables (); + write_item (dstr, pl, 0); + write_string_len (dstr, "\n", 1); + } return dstring_freeze (dstr); } From 2cc30f9dfdf897fccdc61e30c99103e04cac67d7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 18:10:58 +0900 Subject: [PATCH 1354/3664] [headers] Fix a doxygen warning --- include/QF/darray.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/darray.h b/include/QF/darray.h index c2e21d7e1..0ea0a26d6 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -100,7 +100,7 @@ \param array_size The size of the array. \param alloc Allocator taking (obj, size) where obj is allocator specific data (eg, a memory pool). - \param data Additional data for the allocator. + \param obj Additional data for the allocator. */ #define DARRAY_ALLOCFIXED_OBJ(array_type, array_size, alloc, obj) \ ({ \ From 0da3b35ef566f451617d5b3866c8c449e7678c4a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 18:11:59 +0900 Subject: [PATCH 1355/3664] [util] Add macro for using vectors with scanf --- include/QF/math/vector.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 630332907..6189d002c 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -176,6 +176,8 @@ extern const vec_t *const vec3_origin; //For printf etc #define VectorExpand(v) (v)[0], (v)[1], (v)[2] +//For scanf etc +#define VectorExpandAddr(v) &(v)[0], &(v)[1], &(v)[2] /* * VectorDistance, the distance between two points. From 4d8ce22c17e67df9ed1d6fb5ce0faaddb4d97d5d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 18:14:16 +0900 Subject: [PATCH 1356/3664] [vulkan] Load the map's lights into an array It's not used yet as work needs to be done to better support generic entities, but this is the next step to real-time lighting (though, to be honest, I expect it will be too slow to be usable). --- include/QF/Vulkan/qf_lighting.h | 7 +- .../renderer/vulkan/shader/lighting.frag | 2 +- libs/video/renderer/vulkan/vulkan_lighting.c | 108 ++++++++++++++++++ libs/video/renderer/vulkan/vulkan_main.c | 2 + 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 8eaa53a6f..cd9e7d46c 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -40,11 +40,13 @@ typedef struct qfv_light_s { vec3_t color; float intensity; vec3_t position; - int radius; + float radius; vec3_t direction; float cone; } qfv_light_t; +typedef struct qfv_lightset_s DARRAY_TYPE (qfv_light_t) qfv_lightset_t; + #define NUM_LIGHTS 128 typedef struct qfv_light_buffer_s { @@ -52,7 +54,6 @@ typedef struct qfv_light_buffer_s { qfv_light_t lights[NUM_LIGHTS] __attribute__((aligned(16))); } qfv_light_buffer_t; - #define LIGHTING_BUFFER_INFOS 1 #define LIGHTING_IMAGE_INFOS 4 @@ -73,6 +74,7 @@ typedef struct lightingctx_s { VkPipeline pipeline; VkPipelineLayout layout; VkDeviceMemory light_memory; + qfv_lightset_t lights; } lightingctx_t; struct vulkan_ctx_s; @@ -80,5 +82,6 @@ struct vulkan_ctx_s; void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Draw (struct vulkan_ctx_s *ctx); +void Vulkan_LoadLights (const char *entity_data, struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_lighting_h diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 3dfb755be..e2db7cc78 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -9,7 +9,7 @@ struct LightData { vec3 color; float intensity; vec3 position; - int radius; + float radius; vec3 direction; float cone; }; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 8e41cf312..07f0f9927 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -41,6 +41,10 @@ #include "qfalloca.h" +#include "QF/dstring.h" +#include "QF/progs.h" +#include "QF/qfplist.h" +#include "QF/script.h" #include "QF/sys.h" #include "QF/va.h" @@ -203,6 +207,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); ctx->lighting_context = lctx; + DARRAY_INIT (&lctx->lights, 16); + size_t frames = ctx->frames.size; DARRAY_INIT (&lctx->frames, frames); DARRAY_RESIZE (&lctx->frames, frames); @@ -295,6 +301,108 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) } dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0); dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0); + DARRAY_CLEAR (&lctx->lights); free (lctx->frames.a); free (lctx); } + +static void +parse_light (qfv_light_t *light, const plitem_t *entity, + const plitem_t *targets) +{ + const char *str; + + if ((str = PL_String (PL_ObjectForKey (entity, "origin")))) { + sscanf (str, "%f %f %f", VectorExpandAddr (light->position)); + } + + light->cone = 1; + if ((str = PL_String (PL_ObjectForKey (entity, "target")))) { + vec3_t position = {}; + plitem_t *target = PL_ObjectForKey (targets, str); + if (target) { + if ((str = PL_String (PL_ObjectForKey (target, "origin")))) { + sscanf (str, "%f %f %f", VectorExpandAddr (position)); + } + VectorSubtract (position, light->position, light->direction); + VectorNormalize (light->direction); + } + + float angle = 40; + if ((str = PL_String (PL_ObjectForKey (entity, "angle")))) { + angle = atof (str); + } + light->cone = -cos (angle * M_PI / 360); // half angle + } + + light->intensity = 1; + if ((str = PL_String (PL_ObjectForKey (entity, "light"))) + || (str = PL_String (PL_ObjectForKey (entity, "_light")))) { + light->radius = atof (str); + } + + VectorSet (1, 1, 1, light->color); +} + +void +Vulkan_LoadLights (const char *entity_data, vulkan_ctx_t *ctx) +{ + lightingctx_t *lctx = ctx->lighting_context; + plitem_t *entities = 0; + + lctx->lights.size = 0; + + script_t *script = Script_New (); + Script_Start (script, "ent data", entity_data); + + if (Script_GetToken (script, 1)) { + if (strequal (script->token->str, "(")) { + // new style (plist) entity data + entities = PL_GetPropertyList (entity_data, &ctx->hashlinks); + } else { + // old style entity data + Script_UngetToken (script); + // FIXME ED_ConvertToPlist aborts if an error is encountered. + entities = ED_ConvertToPlist (script, 0, &ctx->hashlinks); + } + } + Script_Delete (script); + + if (entities) { + plitem_t *targets = PL_NewDictionary (&ctx->hashlinks); + + // find all the targets so spotlights can be aimed + for (int i = 1; i < PL_A_NumObjects (entities); i++) { + plitem_t *entity = PL_ObjectAtIndex (entities, i); + const char *targetname = PL_String (PL_ObjectForKey (entity, + "targetname")); + if (targetname && !PL_ObjectForKey (targets, targetname)) { + PL_D_AddObject (targets, targetname, entity); + } + } + + for (int i = 1; i < PL_A_NumObjects (entities); i++) { + plitem_t *entity = PL_ObjectAtIndex (entities, i); + const char *classname = PL_String (PL_ObjectForKey (entity, + "classname")); + if (classname && strnequal (classname, "light", 5)) { + qfv_light_t light = {}; + + parse_light (&light, entity, targets); + printf ("[%g, %g, %g] %g, [%g %g %g] %g, [%g %g %g] %g\n", + VectorExpand (light.color), light.intensity, + VectorExpand (light.position), light.radius, + VectorExpand (light.direction), light.cone); + DARRAY_APPEND (&lctx->lights, light); + } + } + // targets does not own the objects, so need to remove them before + // freeing targets + for (int i = PL_D_NumKeys (targets); i-- > 0; ) { + PL_RemoveObjectForKey (targets, PL_KeyAtIndex (targets, i)); + } + PL_Free (targets); + PL_Free (entities); + } + printf ("loaded %zd lights\n", lctx->lights.size); +} diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index b4bdc8872..69916682e 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -49,6 +49,7 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" //#include "QF/Vulkan/qf_iqm.h" +#include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_particles.h" @@ -217,6 +218,7 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, Vulkan_RegisterTextures (models, num_models, ctx); Vulkan_BuildLightmaps (models, num_models, ctx); Vulkan_BuildDisplayLists (models, num_models, ctx); + Vulkan_LoadLights (worldmodel->brush.entities, ctx); } /*void From 0366b72d4a3e17a32008db4d1a60d11fd40fbac3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Mar 2021 18:16:27 +0900 Subject: [PATCH 1357/3664] [vulkan] remove the fps printing Now that pixels are rendered, there's no need to print the fps separately as the in-game display works quite nicely. --- libs/video/renderer/vid_render_vulkan.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 059250fff..00c307dbc 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -118,8 +118,6 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) { const VkSubpassContents subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; - static int count = 0; - static double startTime; uint32_t imageIndex = 0; qfv_device_t *device = vulkan_ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -199,16 +197,6 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) vulkan_ctx->curFrame++; vulkan_ctx->curFrame %= vulkan_ctx->frames.size; - - if (++count >= 100) { - double currenTime = Sys_DoubleTime (); - double time = currenTime - startTime; - startTime = currenTime; - printf ("%d frames in %g s: %g fps \r", - count, time, count / time); - fflush (stdout); - count = 0; - } } static void From 4a97bc3ba549ee2abe0ed3033051f6265fe03a35 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 4 Mar 2021 17:39:05 +0900 Subject: [PATCH 1358/3664] [util] Create simd quaternion to matrix function This seems to be pretty close to as fast as it gets (might be able to do better with some shuffles of the negation constants instead of loading separate constants). --- include/QF/simd/mat4f.h | 50 +++++++++++++++++++++++ libs/util/test/test-quat.c | 32 +++++++++++++++ libs/util/test/test-simd.c | 82 +++++++++++++++++++++++++++++++++++++- 3 files changed, 163 insertions(+), 1 deletion(-) diff --git a/include/QF/simd/mat4f.h b/include/QF/simd/mat4f.h index 3e1880ad6..24773da87 100644 --- a/include/QF/simd/mat4f.h +++ b/include/QF/simd/mat4f.h @@ -38,6 +38,7 @@ GNU89INLINE inline void mmulf (mat4f_t c, const mat4f_t a, const mat4f_t b); GNU89INLINE inline vec4f_t mvmulf (const mat4f_t m, vec4f_t v) __attribute__((const)); GNU89INLINE inline vec4f_t m3vmulf (const mat4f_t m, vec4f_t v) __attribute__((const)); GNU89INLINE inline void mat4fidentity (mat4f_t m); +GNU89INLINE inline void mat4fquat (mat4f_t m, vec4f_t q); #ifndef IMPLEMENT_MAT4F_Funcs GNU89INLINE inline @@ -120,4 +121,53 @@ mat4fidentity (mat4f_t m) m[3] = (vec4f_t) { 0, 0, 0, 1 }; } +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +mat4fquat (mat4f_t m, vec4f_t q) +{ + vec4f_t xq = q[0] * q; + vec4f_t yq = q[1] * q; + vec4f_t zq = q[2] * q; + vec4f_t wq = q[3] * q; + + static const vec4i_t shuff103 = { 1, 0, 3, 2 }; + static const vec4i_t shuff230 = { 2, 3, 0, 1 }; + static const vec4i_t shuff321 = { 3, 2, 1, 0 }; +#define p (0) +#define m (1u << 31) + static const vec4i_t mpm = { m, p, m, 0 }; + static const vec4i_t pmm = { p, m, m, 0 }; + static const vec4i_t mmp = { m, m, p, 0 }; + static const vec4i_t mask = { ~0u, ~0u, ~0u, 0 }; +#undef p +#undef m + { + vec4f_t a = xq; + vec4f_t b = _mm_xor_ps (__builtin_shuffle (yq, shuff103), (__m128) mpm); + vec4f_t c = _mm_xor_ps (__builtin_shuffle (zq, shuff230), (__m128) pmm); + vec4f_t d = _mm_xor_ps (__builtin_shuffle (wq, shuff321), (__m128) mmp); + + m[0] = _mm_and_ps (a + b - c - d, (__m128) mask); + } + { + vec4f_t a = _mm_xor_ps (__builtin_shuffle (xq, shuff103), (__m128) mpm); + vec4f_t b = yq; + vec4f_t c = _mm_xor_ps (__builtin_shuffle (zq, shuff321), (__m128) mmp); + vec4f_t d = _mm_xor_ps (__builtin_shuffle (wq, shuff230), (__m128) pmm); + m[1] = _mm_and_ps (b + c - a - d, (__m128) mask); + } + { + vec4f_t a = _mm_xor_ps (__builtin_shuffle (xq, shuff230), (__m128) pmm); + vec4f_t b = _mm_xor_ps (__builtin_shuffle (yq, shuff321), (__m128) mmp); + vec4f_t c = zq; + vec4f_t d = _mm_xor_ps (__builtin_shuffle (wq, shuff103), (__m128) mpm); + m[2] = _mm_and_ps (a - b + c - d, (__m128) mask); + } + m[3] = (vec4f_t) { 0, 0, 0, 1 }; +} + #endif//__QF_simd_mat4f_h diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index 9144f56be..cafceb2c8 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -362,6 +362,31 @@ fail: return 0; } +static int +test_quat_mat2(const quat_t q, const quat_t expect) +{ + int i; + vec_t m[9]; + + QuatToMatrix (q, m, 0, 1); + Mat3Transpose (m, m); + + for (i = 0; i < 9; i++) + if (m[i] != expect[i]) // exact tests here + goto fail; + return 1; +fail: + printf ("\ntest_quat_mat\n"); + printf ("%11.9g %11.9g %11.9g %11.9g\n", QuatExpand (q)); + printf ("%11.9g %11.9g %11.9g %11.9g %11.9g %11.9g\n", + VectorExpand (m + 0), VectorExpand (expect + 0)); + printf ("%11.9g %11.9g %11.9g %11.9g %11.9g %11.9g\n", + VectorExpand (m + 3), VectorExpand (expect + 3)); + printf ("%11.9g %11.9g %11.9g %11.9g %11.9g %11.9g\n", + VectorExpand (m + 6), VectorExpand (expect + 6)); + return 0; +} + int main (int argc, const char **argv) { @@ -407,5 +432,12 @@ main (int argc, const char **argv) res = 1; } + for (i = 0; i < num_quat_mat_tests; i ++) { + vec_t *q = quat_mat_tests[i].q; + vec_t *expect = quat_mat_tests[i].expect; + if (!test_quat_mat2 (q, expect)) + res = 1; + } + return res; } diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index 6fe524852..b14a1be9c 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -7,6 +7,7 @@ #include #include +#include "QF/mathlib.h" #include "QF/simd/vec4d.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" @@ -76,6 +77,13 @@ typedef struct { vec4f_t ulp_errors; } mv4f_test_t; +typedef struct { + void (*op) (mat4f_t m, vec4f_t q); + vec4f_t q; + mat4f_t expect; + mat4f_t ulp_errors; +} mq4f_test_t; + static vec4d_t tvtruncd (vec4d_t v, vec4d_t ignore) { return vtruncd (v); @@ -367,6 +375,20 @@ static mv4f_test_t mv4f_tests[] = { }; #define num_mv4f_tests (sizeof (mv4f_tests) / (sizeof (mv4f_tests[0]))) +// expect filled in using non-simd QuatToMatrix (has its own tests) +static mq4f_test_t mq4f_tests[] = { + { mat4fquat, { 0, 0, 0, 1 } }, + { mat4fquat, { 0.5, 0.5, 0.5, 0.5 } }, + { mat4fquat, { 0.5, 0.5, -0.5, 0.5 } }, + { mat4fquat, { 0.5, -0.5, 0.5, 0.5 } }, + { mat4fquat, { 0.5, -0.5, -0.5, 0.5 } }, + { mat4fquat, { -0.5, 0.5, 0.5, 0.5 } }, + { mat4fquat, { -0.5, 0.5, -0.5, 0.5 } }, + { mat4fquat, { -0.5, -0.5, 0.5, 0.5 } }, + { mat4fquat, { -0.5, -0.5, -0.5, 0.5 } }, +}; +#define num_mq4f_tests (sizeof (mq4f_tests) / (sizeof (mq4f_tests[0]))) + static int run_vec4d_tests (void) { @@ -485,7 +507,7 @@ run_mv4f_tests (void) if (res[0] || res[1] || res[2] || res[3]) { ret |= 1; - printf ("\nrun_mat4f_tests %zd\n", i); + printf ("\nrun_mv4f_tests %zd\n", i); printf ("a: " VEC4F_FMT "\n", MAT4_ROW(test->a, 0)); printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 1)); printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 2)); @@ -501,6 +523,63 @@ run_mv4f_tests (void) return ret; } +static int +run_mq4f_tests (void) +{ + int ret = 0; + + for (size_t i = 0; i < num_mq4f_tests; i++) { + __auto_type test = &mq4f_tests[i]; + quat_t q; + vec_t m[16]; + memcpy (q, &test->q, sizeof (quat_t)); + QuatToMatrix (q, m, 1, 1); + memcpy (&test->expect, m, sizeof (mat4f_t)); + } + for (size_t i = 0; i < num_mq4f_tests; i++) { + __auto_type test = &mq4f_tests[i]; + mat4f_t result; + mat4f_t expect; + mat4i_t res = {}; + + test->op (result, test->q); + maddf (expect, test->expect, test->ulp_errors); + memcpy (expect, (void *) &test->expect, sizeof (mat4f_t)); + + int fail = 0; + for (int j = 0; j < 4; j++) { + res[j] = result[j] != expect[j]; + fail |= res[j][0] || res[j][1] || res[j][2] || res[j][3]; + } + if (fail) { + ret |= 1; + printf ("\nrun_mq4f_tests %zd\n", i); + printf ("q: " VEC4F_FMT "\n", VEC4_EXP(test->q)); + printf ("r: " VEC4F_FMT "\n", MAT4_ROW(result, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(result, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(result, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(result, 3)); + printf ("t: " VEC4I_FMT "\n", MAT4_ROW(res, 0)); + printf (" " VEC4I_FMT "\n", MAT4_ROW(res, 1)); + printf (" " VEC4I_FMT "\n", MAT4_ROW(res, 2)); + printf (" " VEC4I_FMT "\n", MAT4_ROW(res, 3)); + printf ("E: " VEC4F_FMT "\n", MAT4_ROW(expect, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(expect, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(expect, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(expect, 3)); + printf ("e: " VEC4F_FMT "\n", MAT4_ROW(test->expect, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->expect, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->expect, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->expect, 3)); + printf ("u: " VEC4F_FMT "\n", MAT4_ROW(test->ulp_errors, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->ulp_errors, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->ulp_errors, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(test->ulp_errors, 3)); + } + } + return ret; +} + int main (void) { @@ -509,5 +588,6 @@ main (void) ret |= run_vec4f_tests (); ret |= run_mat4f_tests (); ret |= run_mv4f_tests (); + ret |= run_mq4f_tests (); return ret; } From 14bc560624cbaac5fcff6ab2e1f3975edcc92847 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 7 Mar 2021 17:39:22 +0900 Subject: [PATCH 1359/3664] [build] Add option to enable gcov data generation Nice to be able to check how good the tests are (or aren't, as the case may be). --- config.d/compiling.m4 | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index d9ba92887..7a4908efa 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -223,6 +223,12 @@ QF_CC_OPTION(-Wsuggest-attribute=const) QF_CC_OPTION(-Wsuggest-attribute=noreturn) QF_CC_OPTION(-Wsuggest-attribute=format) +AC_ARG_ENABLE(coverage, +[ --enable-coverage Enable generation of data for gcov]) +if test "x$enable_coverage" = xyes; then + QF_CC_OPTION(-fprofile-arcs -ftest-coverage) +fi + dnl QuakeForge uses lots of BCPL-style (//) comments, which can cause problems dnl with many compilers that do not support the latest ISO standards. Well, dnl that is our cover story -- the reality is that we like them and do not want @@ -250,8 +256,7 @@ if test "x$GCC" != xyes; then fi AC_ARG_ENABLE(Werror, -[ --disable-Werror Do not treat warnings as errors] -) +[ --disable-Werror Do not treat warnings as errors]) dnl We want warnings, lots of warnings... dnl The help text should be INVERTED before release! dnl when in git, this test defaults to ENABLED. From 941a1267bcbb341f7c8d2612bb54384f5f81dee3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Mar 2021 11:35:18 +0900 Subject: [PATCH 1360/3664] [util] Fix a count error when resizing darrays Turns out I had never fully tested inserts. --- include/QF/darray.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/darray.h b/include/QF/darray.h index 0ea0a26d6..61500256a 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -253,7 +253,7 @@ } \ DARRAY_RESIZE (ar, ar->size + sp); \ memmove (&ar->a[po + sp], &ar->a[po], \ - (ar->size - po) * sizeof (*ar->a)); \ + (ar->size - po - sp) * sizeof (*ar->a)); \ &ar->a[po]; \ }) From 2c5742a0765eb7017ba9e9cc40ab74f7674e193f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Mar 2021 11:37:47 +0900 Subject: [PATCH 1361/3664] [renderer] Remove some variable warts Ugh, Hungarian notation is still lurking... --- libs/video/renderer/r_efrag.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 4c93c935c..cbfd0d2c8 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -218,26 +218,26 @@ R_AddEfrags (mod_brush_t *brush, entity_t *ent) } void -R_StoreEfrags (const efrag_t *pefrag) +R_StoreEfrags (const efrag_t *efrag) { - entity_t *pent; + entity_t *ent; model_t *model; - while (pefrag) { - pent = pefrag->entity; - model = pent->model; + while (efrag) { + ent = efrag->entity; + model = ent->model; switch (model->type) { case mod_alias: case mod_brush: case mod_sprite: case mod_iqm: - if (pent->visframe != r_framecount) { - R_EnqueueEntity (pent); + if (ent->visframe != r_framecount) { + R_EnqueueEntity (ent); // mark that we've recorded this entity for this frame - pent->visframe = r_framecount; + ent->visframe = r_framecount; } - pefrag = pefrag->leafnext; + efrag = efrag->leafnext; break; default: From 3230270ae3046ce010f34aaee35389351913bd86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Mar 2021 11:39:41 +0900 Subject: [PATCH 1362/3664] [entity] Start work on a new entity library The plan is to have a fully component based entity system. This adds hierarchical transforms. Not particularly useful for quake itself at this stage, but it will allow for much more flexibility later on, especially when QuakeForge becomes more general-purpose. --- include/QF/entity.h | 122 ++++++ libs/Makemodule.am | 1 + libs/entity/Makemodule.am | 13 + libs/entity/hierarchy.c | 444 +++++++++++++++++++ libs/entity/test/Makemodule.am | 19 + libs/entity/test/test-hierarchy.c | 707 ++++++++++++++++++++++++++++++ libs/entity/transform.c | 317 ++++++++++++++ 7 files changed, 1623 insertions(+) create mode 100644 include/QF/entity.h create mode 100644 libs/entity/Makemodule.am create mode 100644 libs/entity/hierarchy.c create mode 100644 libs/entity/test/Makemodule.am create mode 100644 libs/entity/test/test-hierarchy.c create mode 100644 libs/entity/transform.c diff --git a/include/QF/entity.h b/include/QF/entity.h new file mode 100644 index 000000000..9bf676190 --- /dev/null +++ b/include/QF/entity.h @@ -0,0 +1,122 @@ +/* + entity.h + + Entity management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/02/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_entity_h +#define __QF_entity_h + +#include "QF/darray.h" +#include "QF/mathlib.h" +#include "QF/simd/vec4f.h" +#include "QF/simd/mat4f.h" + +/** \defgroup entity Entity management + \ingroup utils +*/ +///@{ + +typedef struct mat4fset_s DARRAY_TYPE (mat4f_t) mat4fset_t; +typedef struct vec4fset_s DARRAY_TYPE (vec4f_t) vec4fset_t; +typedef struct uint32set_s DARRAY_TYPE (uint32_t) uint32set_t; +typedef struct byteset_s DARRAY_TYPE (byte) byteset_t; +typedef struct stringset_s DARRAY_TYPE (char *) stringset_t; +typedef struct xformset_s DARRAY_TYPE (struct transform_s *) xformset_t; +typedef struct entityset_s DARRAY_TYPE (struct entity_s *) entityset_t; + +#define null_transform (~0u) + +typedef struct hierarchy_s { + xformset_t transform; + entityset_t entity; + uint32set_t childCount; + uint32set_t childIndex; + uint32set_t parentIndex; + stringset_t name; + uint32set_t tag; + byteset_t modified; + mat4fset_t localMatrix; + mat4fset_t localInverse; + mat4fset_t worldMatrix; + mat4fset_t worldInverse; + vec4fset_t localRotation; + vec4fset_t localScale; + vec4fset_t worldRotation; + vec4fset_t worldScale; +} hierarchy_t; + +typedef struct transform_s { + hierarchy_t *hierarchy; + uint32_t index; +} transform_t; + +transform_t *Transform_New (transform_t *parent); +void Transform_Delete (transform_t *transform); +transform_t *Transform_NewNamed (transform_t *parent, const char *name); +uint32_t Transform_ChildCount (const transform_t *transform) __attribute__((pure)); +transform_t *Transform_GetChild (const transform_t *transform, + uint32_t childIndex) __attribute__((pure)); +void Transform_SetParent (transform_t *transform, transform_t *parent); +transform_t *Transform_GetParent (const transform_t *transform) __attribute__((pure)); +void Transform_SetName (transform_t *transform, const char *name); +const char *Transform_GetName (const transform_t *transform) __attribute__((pure)); +void Transform_SetTag (transform_t *transform, uint32_t tag); +uint32_t Transform_GetTag (const transform_t *transform) __attribute__((pure)); +void Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat); +void Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat); +void Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat); +void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat); +vec4f_t Transform_GetLocalPosition (const transform_t *transform) __attribute__((pure)); +void Transform_SetLocalPosition (transform_t *transform_t, vec4f_t position); +vec4f_t Transform_GetLocalRotation (const transform_t *transform) __attribute__((pure)); +void Transform_SetLocalRotation (transform_t *transform_t, vec4f_t rotation); +vec4f_t Transform_GetLocalScale (const transform_t *transform) __attribute__((pure)); +void Transform_SetLocalScale (transform_t *transform_t, vec4f_t scale); +vec4f_t Transform_GetWorldPosition (const transform_t *transform) __attribute__((pure)); +void Transform_SetWorldPosition (transform_t *transform_t, vec4f_t position); +vec4f_t Transform_GetWorldRotation (const transform_t *transform) __attribute__((pure)); +void Transform_SetWorldRotation (transform_t *transform_t, vec4f_t rotation); +vec4f_t Transform_GetWorldScale (const transform_t *transform) __attribute__((pure)); +// NOTE: these use X: right, Y: forward, Z:up +// aslo, not guaranteed to be normalized or even orthogonal +vec4f_t Transform_Forward (const transform_t *transform) __attribute__((pure)); +vec4f_t Transform_Right (const transform_t *transform) __attribute__((pure)); +vec4f_t Transform_Up (const transform_t *transform) __attribute__((pure)); +// no SetWorldScale because after rotations, non uniform scale becomes shear + +hierarchy_t *Hierarchy_New (size_t grow, int createRoot); +hierarchy_t *Hierarchy_Copy (hierarchy_t *src); +void Hierarchy_Delete (hierarchy_t *hierarchy); + +void Hierarchy_UpdateMatrices (hierarchy_t *hierarchy); +uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstParent, uint32_t srcRoot); +void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); +///@} + +#endif//__QF_entity_h diff --git a/libs/Makemodule.am b/libs/Makemodule.am index 5a68c67ba..86fcac7df 100644 --- a/libs/Makemodule.am +++ b/libs/Makemodule.am @@ -7,6 +7,7 @@ include libs/image/Makemodule.am include libs/models/Makemodule.am include libs/video/Makemodule.am include libs/console/Makemodule.am +include libs/entity/Makemodule.am include libs/net/Makemodule.am include libs/client/Makemodule.am diff --git a/libs/entity/Makemodule.am b/libs/entity/Makemodule.am new file mode 100644 index 000000000..d8ac9a7e1 --- /dev/null +++ b/libs/entity/Makemodule.am @@ -0,0 +1,13 @@ +include libs/entity/test/Makemodule.am + +entity_deps=libs/util/libQFutil.la + +lib_LTLIBRARIES += libs/entity/libQFentity.la + +libs_entity_libQFentity_la_LDFLAGS= $(lib_ldflags) +libs_entity_libQFentity_la_LIBADD= $(entity_deps) +libs_entity_libQFentity_la_DEPENDENCIES= $(entity_deps) +libs_entity_libQFentity_la_SOURCES= \ + libs/entity/hierarchy.c \ + libs/entity/transform.c \ + $e diff --git a/libs/entity/hierarchy.c b/libs/entity/hierarchy.c new file mode 100644 index 000000000..cadb3771c --- /dev/null +++ b/libs/entity/hierarchy.c @@ -0,0 +1,444 @@ +/* + hierarchy.c + + General hierarchy handling + + Copyright (C) 2021 Bill Currke + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/entity.h" + +static void +hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, + int offset) +{ + for (size_t i = start; i < hierarchy->transform.size; i++) { + if (hierarchy->transform.a[i]) { + hierarchy->transform.a[i]->index += offset; + } + } +} + +static void +hierarchy_UpdateChildIndices (hierarchy_t *hierarchy, uint32_t start, + int offset) +{ + for (size_t i = start; i < hierarchy->childIndex.size; i++) { + hierarchy->childIndex.a[i] += offset; + } +} + +static void +hierarchy_UpdateParentIndices (hierarchy_t *hierarchy, uint32_t start, + int offset) +{ + for (size_t i = start; i < hierarchy->parentIndex.size; i++) { + hierarchy->parentIndex.a[i] += offset; + } +} + +static void +hierarchy_calcLocalInverse (hierarchy_t *h, uint32_t index) +{ + // This takes advantage of the fact that localMatrix is a simple + // homogenous scale/rotate/translate matrix with no shear + vec4f_t x = h->localMatrix.a[index][0]; + vec4f_t y = h->localMatrix.a[index][1]; + vec4f_t z = h->localMatrix.a[index][2]; + vec4f_t t = h->localMatrix.a[index][3]; + + // "one" is to ensure both the scalar and translation have 1 in their + // forth components + vec4f_t one = { 0, 0, 0, 1 }; + vec4f_t nx = { x[0], y[0], z[0], 0 }; + vec4f_t ny = { x[1], y[1], z[1], 0 }; + vec4f_t nz = { x[2], y[2], z[2], 0 }; + vec4f_t nt = one - t[0] * nx - t[1] * ny - t[2] * nz; + // vertical dot product!!! + vec4f_t s = 1 / (nx * nx + ny * ny + nz * nz + one); + h->localInverse.a[index][0] = nx * s; + h->localInverse.a[index][1] = ny * s; + h->localInverse.a[index][2] = nz * s; + h->localInverse.a[index][3] = nt * s; +} + +void +Hierarchy_UpdateMatrices (hierarchy_t *h) +{ + for (size_t i = 0; i < h->localInverse.size; i++) { + if (h->modified.a[i]) { + hierarchy_calcLocalInverse (h, i); + } + } + if (h->modified.a[0]) { + memcpy (h->worldMatrix.a[0], + h->localMatrix.a[0], sizeof (mat4_t)); + memcpy (h->worldInverse.a[0], + h->localInverse.a[0], sizeof (mat4_t)); + h->worldRotation.a[0] = h->localRotation.a[0]; + h->worldScale.a[0] = h->localScale.a[0]; + } + for (size_t i = 1; i < h->worldMatrix.size; i++) { + uint32_t parent = h->parentIndex.a[i]; + + if (h->modified.a[i] || h->modified.a[parent]) { + mmulf (h->worldMatrix.a[i], + h->worldMatrix.a[parent], h->localMatrix.a[i]); + h->modified.a[i] = 1; + } + } + for (size_t i = 1; i < h->worldInverse.size; i++) { + uint32_t parent = h->parentIndex.a[i]; + + if (h->modified.a[i] || h->modified.a[parent]) { + mmulf (h->worldInverse.a[i], + h->localInverse.a[i], h->worldInverse.a[parent]); + } + } + for (size_t i = 1; i < h->worldRotation.size; i++) { + uint32_t parent = h->parentIndex.a[i]; + if (h->modified.a[i] || h->modified.a[parent]) { + h->worldRotation.a[i] = qmulf (h->worldRotation.a[parent], + h->localRotation.a[i]); + } + } + for (size_t i = 1; i < h->worldScale.size; i++) { + uint32_t parent = h->parentIndex.a[i]; + if (h->modified.a[i] || h->modified.a[parent]) { + h->worldScale.a[i] = m3vmulf (h->worldMatrix.a[parent], + h->localScale.a[i]); + } + } + memset (h->modified.a, 0, h->modified.size); +} + +static void +hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t count) +{ + DARRAY_OPEN_AT (&hierarchy->transform, index, count); + DARRAY_OPEN_AT (&hierarchy->entity, index, count); + DARRAY_OPEN_AT (&hierarchy->childCount, index, count); + DARRAY_OPEN_AT (&hierarchy->childIndex, index, count); + DARRAY_OPEN_AT (&hierarchy->parentIndex, index, count); + DARRAY_OPEN_AT (&hierarchy->name, index, count); + DARRAY_OPEN_AT (&hierarchy->tag, index, count); + DARRAY_OPEN_AT (&hierarchy->modified, index, count); + DARRAY_OPEN_AT (&hierarchy->localMatrix, index, count); + DARRAY_OPEN_AT (&hierarchy->localInverse, index, count); + DARRAY_OPEN_AT (&hierarchy->worldMatrix, index, count); + DARRAY_OPEN_AT (&hierarchy->worldInverse, index, count); + DARRAY_OPEN_AT (&hierarchy->localRotation, index, count); + DARRAY_OPEN_AT (&hierarchy->localScale, index, count); + DARRAY_OPEN_AT (&hierarchy->worldRotation, index, count); + DARRAY_OPEN_AT (&hierarchy->worldScale, index, count); +} + +static void +hierarchy_close (hierarchy_t *hierarchy, uint32_t index, uint32_t count) +{ + if (count) { + DARRAY_CLOSE_AT (&hierarchy->transform, index, count); + DARRAY_CLOSE_AT (&hierarchy->entity, index, count); + DARRAY_CLOSE_AT (&hierarchy->childCount, index, count); + DARRAY_CLOSE_AT (&hierarchy->childIndex, index, count); + DARRAY_CLOSE_AT (&hierarchy->parentIndex, index, count); + DARRAY_CLOSE_AT (&hierarchy->name, index, count); + DARRAY_CLOSE_AT (&hierarchy->tag, index, count); + DARRAY_CLOSE_AT (&hierarchy->modified, index, count); + DARRAY_CLOSE_AT (&hierarchy->localMatrix, index, count); + DARRAY_CLOSE_AT (&hierarchy->localInverse, index, count); + DARRAY_CLOSE_AT (&hierarchy->worldMatrix, index, count); + DARRAY_CLOSE_AT (&hierarchy->worldInverse, index, count); + DARRAY_CLOSE_AT (&hierarchy->localRotation, index, count); + DARRAY_CLOSE_AT (&hierarchy->localScale, index, count); + DARRAY_CLOSE_AT (&hierarchy->worldRotation, index, count); + DARRAY_CLOSE_AT (&hierarchy->worldScale, index, count); + } +} + +static void +hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstIndex, uint32_t srcIndex, uint32_t count) +{ + memcpy (&dst->transform.a[dstIndex], &src->transform.a[srcIndex], + count * sizeof(dst->transform.a[0])); + memset (&src->transform.a[srcIndex], 0, + count * sizeof(dst->transform.a[0])); + memcpy (&dst->entity.a[dstIndex], &src->entity.a[srcIndex], + count * sizeof(dst->entity.a[0])); + memcpy (&dst->name.a[dstIndex], &src->name.a[srcIndex], + count * sizeof(dst->name.a[0])); + memcpy (&dst->tag.a[dstIndex], &src->tag.a[srcIndex], + count * sizeof(dst->tag.a[0])); + memset (&dst->modified.a[dstIndex], 1, count * sizeof(dst->modified.a[0])); + memcpy (&dst->localMatrix.a[dstIndex], &src->localMatrix.a[srcIndex], + count * sizeof(dst->localMatrix.a[0])); + memcpy (&dst->localInverse.a[dstIndex], &src->localInverse.a[srcIndex], + count * sizeof(dst->localInverse.a[0])); + memcpy (&dst->localRotation.a[dstIndex], &src->localRotation.a[srcIndex], + count * sizeof(dst->localRotation.a[0])); + memcpy (&dst->localScale.a[dstIndex], &src->localScale.a[srcIndex], + count * sizeof(dst->localScale.a[0])); + + for (uint32_t i = 0; i < count; i++) { + dst->transform.a[dstIndex + i]->hierarchy = dst; + dst->transform.a[dstIndex + i]->index = dstIndex + i; + } +} + +static void +hierarchy_init (hierarchy_t *dst, uint32_t index, + uint32_t parentIndex, uint32_t childIndex, uint32_t count) +{ + memset (&dst->transform.a[index], 0, + count * sizeof(dst->transform.a[0])); + memset (&dst->entity.a[index], 0, count * sizeof(dst->entity.a[0])); + memset (&dst->name.a[index], 0, count * sizeof(dst->name.a[0])); + memset (&dst->tag.a[index], 0, count * sizeof(dst->tag.a[0])); + memset (&dst->modified.a[index], 1, count * sizeof(dst->modified.a[0])); + + for (uint32_t i = 0; i < count; i++) { + mat4fidentity (dst->localMatrix.a[index]); + mat4fidentity (dst->localInverse.a[index]); + dst->localRotation.a[index] = (vec4f_t) { 0, 0, 0, 1 }; + dst->localScale.a[index] = (vec4f_t) { 1, 1, 1, 1 }; + + dst->parentIndex.a[index + i] = parentIndex; + dst->childCount.a[index + i] = 0; + dst->childIndex.a[index + i] = childIndex; + } +} + +static uint32_t +hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstParent, uint32_t srcRoot, uint32_t count) +{ + uint32_t insertIndex; // where the transforms will be inserted + uint32_t childIndex; // where the transforms' children will inserted + + // The newly added transforms are always last children of the parent + // transform + insertIndex = dst->childIndex.a[dstParent] + dst->childCount.a[dstParent]; + + // By design, all of a transform's children are in one contiguous block, + // and the blocks of children for each transform are ordered by their + // parents. Thus the child index of each transform increases monotonically + // for each child index in the array, regardless of the level of the owning + // transform (higher levels always come before lower levels). + uint32_t neighbor = insertIndex - 1; // insertIndex never zero + childIndex = dst->childIndex.a[neighbor] + dst->childCount.a[neighbor]; + + // Any transforms that come after the inserted transforms need to have + // thier indices adjusted. + hierarchy_UpdateTransformIndices (dst, insertIndex, count); + // The parent transform's child index is not affected, but the child + // indices of all transforms immediately after the parent transform are. + hierarchy_UpdateChildIndices (dst, dstParent + 1, count); + hierarchy_UpdateParentIndices (dst, childIndex, count); + + // The beginning of the block of children for the new transforms was + // computed from the pre-insert indices of the related transforms, thus + // the index must be updated by the number of transforms being inserted + // (it would have been updated thusly if the insert was done before + // updating the indices of the other transforms). + childIndex += count; + + hierarchy_open (dst, insertIndex, count); + if (src) { + hierarchy_move (dst, src, insertIndex, srcRoot, count); + } else { + hierarchy_init (dst, insertIndex, dstParent, childIndex, count); + } + for (uint32_t i = 0; i < count; i++) { + dst->parentIndex.a[insertIndex + i] = dstParent; + dst->childIndex.a[insertIndex + i] = childIndex; + dst->childCount.a[insertIndex + i] = 0; + } + + dst->childCount.a[dstParent] += count; + return insertIndex; +} + +static void +hierarchy_insert_children (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstParent, uint32_t srcRoot) +{ + uint32_t insertIndex; + uint32_t childIndex = src->childIndex.a[srcRoot]; + uint32_t childCount = src->childCount.a[srcRoot]; + + if (childCount) { + insertIndex = hierarchy_insert (dst, src, dstParent, + childIndex, childCount); + for (uint32_t i = 0; i < childCount; i++) { + hierarchy_insert_children (dst, src, insertIndex + i, + childIndex + i); + } + } +} + +uint32_t +Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstParent, uint32_t srcRoot) +{ + uint32_t insertIndex; + + if (dstParent == null_transform) { + if (dst->transform.size) { + Sys_Error ("attempt to insert root in non-empty hierarchy"); + } + hierarchy_open (dst, 0, 1); + hierarchy_move (dst, src, 0, srcRoot, 1); + dst->parentIndex.a[0] = null_transform; + dst->childIndex.a[0] = 1; + dst->childCount.a[0] = 0; + insertIndex = 0; + } else { + if (!dst->transform.size) { + Sys_Error ("attempt to insert non-root in empty hierarchy"); + } + insertIndex = hierarchy_insert (dst, src, dstParent, srcRoot, 1); + } + // if src is null, then inserting a new transform which has no children + if (src) { + hierarchy_insert_children (dst, src, insertIndex, srcRoot); + } + Hierarchy_UpdateMatrices (dst); + return insertIndex; +} + +static void +hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) +{ + uint32_t childIndex = hierarchy->childIndex.a[index]; + uint32_t childCount = hierarchy->childCount.a[index]; + uint32_t parentIndex = hierarchy->parentIndex.a[index]; + uint32_t nieceIndex = null_transform; + + if (parentIndex != null_transform) { + uint32_t siblingIndex = hierarchy->childIndex.a[parentIndex]; + siblingIndex += hierarchy->childCount.a[parentIndex] - 1; + nieceIndex = hierarchy->childIndex.a[siblingIndex]; + } + for (uint32_t i = childCount; i-- > 0; ) { + hierarchy_remove_children (hierarchy, childIndex + i); + } + hierarchy_close (hierarchy, childIndex, childCount); + hierarchy->childCount.a[index] = 0; + + if (childCount) { + hierarchy_UpdateTransformIndices (hierarchy, childIndex, -childCount); + hierarchy_UpdateChildIndices (hierarchy, index, -childCount); + if (nieceIndex != null_transform) { + hierarchy_UpdateParentIndices (hierarchy, nieceIndex, -childCount); + } + } +} + +void +Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) +{ + uint32_t parentIndex = hierarchy->parentIndex.a[index]; + uint32_t childIndex = hierarchy->childIndex.a[index]; + uint32_t siblingIndex = null_transform; + if (parentIndex != null_transform) { + siblingIndex = hierarchy->childIndex.a[parentIndex]; + } + hierarchy_remove_children (hierarchy, index); + hierarchy_close (hierarchy, index, 1); + if (siblingIndex != null_transform) { + hierarchy_UpdateTransformIndices (hierarchy, index, -1); + hierarchy_UpdateChildIndices (hierarchy, siblingIndex, -1); + hierarchy_UpdateParentIndices (hierarchy, childIndex - 1, -1); + } +} + +hierarchy_t * +Hierarchy_New (size_t grow, int createRoot) +{ + if (!grow) { + grow = 16; + } + hierarchy_t *hierarchy = malloc (sizeof (hierarchy_t)); + + DARRAY_INIT (&hierarchy->transform, grow); + DARRAY_INIT (&hierarchy->entity, grow); + DARRAY_INIT (&hierarchy->childCount, grow); + DARRAY_INIT (&hierarchy->childIndex, grow); + DARRAY_INIT (&hierarchy->parentIndex, grow); + DARRAY_INIT (&hierarchy->name, grow); + DARRAY_INIT (&hierarchy->tag, grow); + DARRAY_INIT (&hierarchy->modified, grow); + DARRAY_INIT (&hierarchy->localMatrix, grow); + DARRAY_INIT (&hierarchy->localInverse, grow); + DARRAY_INIT (&hierarchy->worldMatrix, grow); + DARRAY_INIT (&hierarchy->worldInverse, grow); + DARRAY_INIT (&hierarchy->localRotation, grow); + DARRAY_INIT (&hierarchy->localScale, grow); + DARRAY_INIT (&hierarchy->worldRotation, grow); + DARRAY_INIT (&hierarchy->worldScale, grow); + + if (createRoot) { + hierarchy_open (hierarchy, 0, 1); + hierarchy_init (hierarchy, 0, null_transform, 1, 1); + } + + return hierarchy; +} + +void +Hierarchy_Delete (hierarchy_t *hierarchy) +{ + for (size_t i = 0; i < hierarchy->transform.size; i++) { + free (hierarchy->transform.a[i]); + } + for (size_t i = 0; i < hierarchy->name.size; i++) { + free (hierarchy->name.a[i]); + } + DARRAY_CLEAR (&hierarchy->transform); + DARRAY_CLEAR (&hierarchy->entity); + DARRAY_CLEAR (&hierarchy->childCount); + DARRAY_CLEAR (&hierarchy->childIndex); + DARRAY_CLEAR (&hierarchy->parentIndex); + DARRAY_CLEAR (&hierarchy->name); + DARRAY_CLEAR (&hierarchy->tag); + DARRAY_CLEAR (&hierarchy->modified); + DARRAY_CLEAR (&hierarchy->localMatrix); + DARRAY_CLEAR (&hierarchy->localInverse); + DARRAY_CLEAR (&hierarchy->worldMatrix); + DARRAY_CLEAR (&hierarchy->worldInverse); + DARRAY_CLEAR (&hierarchy->localRotation); + DARRAY_CLEAR (&hierarchy->localScale); + DARRAY_CLEAR (&hierarchy->worldRotation); + DARRAY_CLEAR (&hierarchy->worldScale); + free (hierarchy); +} diff --git a/libs/entity/test/Makemodule.am b/libs/entity/test/Makemodule.am new file mode 100644 index 000000000..b0f98ae2b --- /dev/null +++ b/libs/entity/test/Makemodule.am @@ -0,0 +1,19 @@ +libs_entity_tests = \ + libs/entity/test/test-hierarchy \ + $e + +TESTS += $(libs_entity_tests) + +check_PROGRAMS += $(libs_entity_tests) + +libs_entity_test_libs= \ + libs/entity/libQFentity.la \ + libs/util/libQFutil.la + +libs_entity_test_test_hierarchy_SOURCES= \ + libs/entity/test/test-hierarchy.c \ + $e +libs_entity_test_test_hierarchy_LDADD= \ + $(libs_entity_test_libs) +libs_entity_test_test_hierarchy_DEPENDENCIES= \ + $(libs_entity_test_libs) diff --git a/libs/entity/test/test-hierarchy.c b/libs/entity/test/test-hierarchy.c new file mode 100644 index 000000000..513f33fca --- /dev/null +++ b/libs/entity/test/test-hierarchy.c @@ -0,0 +1,707 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "QF/entity.h" + +// NOTE: these are the columns of the matrix! (not that it matters for a +// symmetrical matrix, but...) +mat4f_t identity = { + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 }, +}; +vec4f_t one = { 1, 1, 1, 1 }; + +static int +vec4_equal (vec4f_t a, vec4f_t b) +{ + vec4i_t res = a != b; + return !(res[0] || res[1] || res[2] || res[3]); +} + +static int +mat4_equal (const mat4f_t a, const mat4f_t b) +{ + vec4i_t res = {}; + + for (int i = 0; i < 4; i++) { + res |= a[i] != b[i]; + } + return !(res[0] || res[1] || res[2] || res[3]); +} + +static int +check_hierarchy_size (hierarchy_t *h, uint32_t size) +{ + if (h->transform.size != size + || h->entity.size != size + || h->childCount.size != size + || h->childIndex.size != size + || h->parentIndex.size != size + || h->name.size != size + || h->tag.size != size + || h->modified.size != size + || h->localMatrix.size != size + || h->localInverse.size != size + || h->worldMatrix.size != size + || h->worldInverse.size != size + || h->localRotation.size != size + || h->localScale.size != size + || h->worldRotation.size != size + || h->worldScale.size != size) { + printf ("hierarchy does not have exactly %u" + " transform or array sizes are inconsistent\n", size); + return 0; + } + for (size_t i = 0; i < h->transform.size; i++) { + if (h->transform.a[i]->hierarchy != h) { + printf ("transform %zd (%s) does not point to hierarchy\n", + i, h->name.a[i]); + } + } + return 1; +} + +static void +dump_hierarchy (hierarchy_t *h) +{ + for (size_t i = 0; i < h->transform.size; i++) { + printf ("%2zd: %5s %2u %2u %2u %2u\n", i, h->name.a[i], + h->transform.a[i]->index, h->parentIndex.a[i], + h->childIndex.a[i], h->childCount.a[i]); + } + puts (""); +} + +static int +check_indices (transform_t *transform, uint32_t index, uint32_t parentIndex, + uint32_t childIndex, uint32_t childCount) +{ + hierarchy_t *h = transform->hierarchy; + if (transform->index != index) { + printf ("%s/%s index incorrect: expect %u got %u\n", + h->name.a[transform->index], h->name.a[index], + index, transform->index); + return 0; + } + if (h->parentIndex.a[index] != parentIndex) { + printf ("%s parent index incorrect: expect %u got %u\n", + h->name.a[index], parentIndex, h->parentIndex.a[index]); + return 0; + } + if (h->childIndex.a[index] != childIndex) { + printf ("%s child index incorrect: expect %u got %u\n", + h->name.a[index], childIndex, h->childIndex.a[index]); + return 0; + } + if (h->childCount.a[index] != childCount) { + printf ("%s child count incorrect: expect %u got %u\n", + h->name.a[index], childCount, h->childCount.a[index]); + return 0; + } + return 1; +} + +static int +test_single_transform (void) +{ + transform_t *transform = Transform_New (0); + hierarchy_t *h; + + if (!transform) { + printf ("Transform_New returned null\n"); + return 1; + } + if (!(h = transform->hierarchy)) { + printf ("New transform has no hierarchy\n"); + return 1; + } + if (!check_hierarchy_size (h, 1)) { return 1; } + if (!check_indices (transform, 0, null_transform, 1, 0)) { return 1; } + + if (!mat4_equal (h->localMatrix.a[0], identity) + || !mat4_equal (h->localInverse.a[0], identity) + || !mat4_equal (h->worldMatrix.a[0], identity) + || !mat4_equal (h->worldInverse.a[0], identity)) { + printf ("New transform matrices not identity\n"); + return 1; + } + + if (!vec4_equal (h->localRotation.a[0], identity[3]) + || !vec4_equal (h->localScale.a[0], one)) { + printf ("New transform rotation or scale not identity\n"); + return 1; + } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (transform->hierarchy); + + return 0; +} + +static int +test_parent_child_init (void) +{ + transform_t *parent = Transform_New (0); + transform_t *child = Transform_New (parent); + + if (parent->hierarchy != child->hierarchy) { + printf ("parent and child transforms have separate hierarchies\n"); + return 1; + } + + if (!check_hierarchy_size (parent->hierarchy, 2)) { return 1; } + + if (!check_indices (parent, 0, null_transform, 1, 1)) { return 1; } + if (!check_indices (child, 1, 0, 2, 0)) { return 1; } + + hierarchy_t *h = parent->hierarchy; + if (!mat4_equal (h->localMatrix.a[0], identity) + || !mat4_equal (h->localInverse.a[0], identity) + || !mat4_equal (h->worldMatrix.a[0], identity) + || !mat4_equal (h->worldInverse.a[0], identity)) { + printf ("Parent transform matrices not identity\n"); + return 1; + } + + if (!vec4_equal (h->localRotation.a[0], identity[3]) + || !vec4_equal (h->localScale.a[0], one)) { + printf ("Parent transform rotation or scale not identity\n"); + return 1; + } + + if (!mat4_equal (h->localMatrix.a[1], identity) + || !mat4_equal (h->localInverse.a[1], identity) + || !mat4_equal (h->worldMatrix.a[1], identity) + || !mat4_equal (h->worldInverse.a[1], identity)) { + printf ("Child transform matrices not identity\n"); + return 1; + } + + if (!vec4_equal (h->localRotation.a[1], identity[3]) + || !vec4_equal (h->localScale.a[1], one)) { + printf ("Child transform rotation or scale not identity\n"); + return 1; + } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (parent->hierarchy); + + return 0; +} + +static int +test_parent_child_setparent (void) +{ + transform_t *parent = Transform_New (0); + transform_t *child = Transform_New (0); + + Transform_SetName (parent, "parent"); + Transform_SetName (child, "child"); + + if (!check_indices (parent, 0, null_transform, 1, 0)) { return 1; } + if (!check_indices (child, 0, null_transform, 1, 0)) { return 1; } + + if (parent->hierarchy == child->hierarchy) { + printf ("parent and child transforms have same hierarchy before" + " set paret\n"); + return 1; + } + + Transform_SetParent (child, parent); + + if (parent->hierarchy != child->hierarchy) { + printf ("parent and child transforms have separate hierarchies\n"); + return 1; + } + + if (!check_hierarchy_size (parent->hierarchy, 2)) { return 1; } + + if (!check_indices (parent, 0, null_transform, 1, 1)) { return 1; } + if (!check_indices (child, 1, 0, 2, 0)) { return 1; } + + hierarchy_t *h = parent->hierarchy; + if (!mat4_equal (h->localMatrix.a[0], identity) + || !mat4_equal (h->localInverse.a[0], identity) + || !mat4_equal (h->worldMatrix.a[0], identity) + || !mat4_equal (h->worldInverse.a[0], identity)) { + printf ("Parent transform matrices not identity\n"); + return 1; + } + + if (!vec4_equal (h->localRotation.a[0], identity[3]) + || !vec4_equal (h->localScale.a[0], one)) { + printf ("Parent transform rotation or scale not identity\n"); + return 1; + } + + if (!mat4_equal (h->localMatrix.a[1], identity) + || !mat4_equal (h->localInverse.a[1], identity) + || !mat4_equal (h->worldMatrix.a[1], identity) + || !mat4_equal (h->worldInverse.a[1], identity)) { + printf ("Child transform matrices not identity\n"); + return 1; + } + + if (!vec4_equal (h->localRotation.a[1], identity[3]) + || !vec4_equal (h->localScale.a[1], one)) { + printf ("Child transform rotation or scale not identity\n"); + return 1; + } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (parent->hierarchy); + + return 0; +} + +static int +test_build_hierarchy (void) +{ + printf ("test_build_hierarchy\n"); + + transform_t *root = Transform_NewNamed (0, "root"); + transform_t *A = Transform_NewNamed (root, "A"); + transform_t *B = Transform_NewNamed (root, "B"); + transform_t *C = Transform_NewNamed (root, "C"); + + if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices (A, 1, 0, 4, 0)) { return 1; } + if (!check_indices (B, 2, 0, 4, 0)) { return 1; } + if (!check_indices (C, 3, 0, 4, 0)) { return 1; } + + transform_t *B1 = Transform_NewNamed (B, "B1"); + + if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices ( A, 1, 0, 4, 0)) { return 1; } + if (!check_indices ( B, 2, 0, 4, 1)) { return 1; } + if (!check_indices ( C, 3, 0, 5, 0)) { return 1; } + if (!check_indices (B1, 4, 2, 5, 0)) { return 1; } + + transform_t *A1 = Transform_NewNamed (A, "A1"); + + if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices ( A, 1, 0, 4, 1)) { return 1; } + if (!check_indices ( B, 2, 0, 5, 1)) { return 1; } + if (!check_indices ( C, 3, 0, 6, 0)) { return 1; } + if (!check_indices (A1, 4, 1, 6, 0)) { return 1; } + if (!check_indices (B1, 5, 2, 6, 0)) { return 1; } + transform_t *A1a = Transform_NewNamed (A1, "A1a"); + transform_t *B2 = Transform_NewNamed (B, "B2"); + transform_t *A2 = Transform_NewNamed (A, "A2"); + transform_t *B3 = Transform_NewNamed (B, "B3"); + transform_t *B2a = Transform_NewNamed (B2, "B2a"); + + if (!check_hierarchy_size (root->hierarchy, 11)) { return 1; } + + if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices ( A, 1, 0, 4, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 6, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 9, 0)) { return 1; } + if (!check_indices ( A1, 4, 1, 9, 1)) { return 1; } + if (!check_indices ( A2, 5, 1, 10, 0)) { return 1; } + if (!check_indices ( B1, 6, 2, 10, 0)) { return 1; } + if (!check_indices ( B2, 7, 2, 10, 1)) { return 1; } + if (!check_indices ( B3, 8, 2, 11, 0)) { return 1; } + if (!check_indices (A1a, 9, 4, 11, 0)) { return 1; } + if (!check_indices (B2a, 10, 7, 11, 0)) { return 1; } + + transform_t *D = Transform_NewNamed (root, "D"); + + if (!check_hierarchy_size (root->hierarchy, 12)) { return 1; } + + if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 10, 0)) { return 1; } + if (!check_indices ( D, 4, 0, 10, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 10, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 11, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 11, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 11, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 12, 0)) { return 1; } + if (!check_indices (A1a, 10, 5, 12, 0)) { return 1; } + if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; } + + dump_hierarchy (root->hierarchy); + transform_t *C1 = Transform_NewNamed (C, "C1"); + dump_hierarchy (root->hierarchy); + if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; } + + if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 12, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 13, 0)) { return 1; } + if (!check_indices ( C1, 10, 3, 13, 0)) { return 1; } + if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } + if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (root->hierarchy); + + return 0; +} + +static int +test_build_hierarchy2 (void) +{ + printf ("test_build_hierarchy2\n"); + + transform_t *root = Transform_NewNamed (0, "root"); + transform_t *A = Transform_NewNamed (root, "A"); + transform_t *B = Transform_NewNamed (root, "B"); + transform_t *C = Transform_NewNamed (root, "C"); + transform_t *B1 = Transform_NewNamed (B, "B1"); + transform_t *A1 = Transform_NewNamed (A, "A1"); + transform_t *A1a = Transform_NewNamed (A1, "A1a"); + transform_t *B2 = Transform_NewNamed (B, "B2"); + transform_t *A2 = Transform_NewNamed (A, "A2"); + transform_t *B3 = Transform_NewNamed (B, "B3"); + transform_t *B2a = Transform_NewNamed (B2, "B2a"); + transform_t *D = Transform_NewNamed (root, "D"); + transform_t *C1 = Transform_NewNamed (C, "C1"); + + if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; } + + if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 12, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 13, 0)) { return 1; } + if (!check_indices ( C1, 10, 3, 13, 0)) { return 1; } + if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } + if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } + + transform_t *T = Transform_NewNamed (0, "T"); + transform_t *X = Transform_NewNamed (T, "X"); + transform_t *Y = Transform_NewNamed (T, "Y"); + transform_t *Z = Transform_NewNamed (T, "Z"); + transform_t *Y1 = Transform_NewNamed (Y, "Y1"); + transform_t *X1 = Transform_NewNamed (X, "X1"); + transform_t *X1a = Transform_NewNamed (X1, "X1a"); + transform_t *Y2 = Transform_NewNamed (Y, "Y2"); + transform_t *X2 = Transform_NewNamed (X, "X2"); + transform_t *Y3 = Transform_NewNamed (Y, "Y3"); + transform_t *Y2a = Transform_NewNamed (Y2, "Y2a"); + transform_t *Z1 = Transform_NewNamed (Z, "Z1"); + + dump_hierarchy (T->hierarchy); + if (!check_hierarchy_size (T->hierarchy, 12)) { return 1; } + + if (!check_indices ( T, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices ( X, 1, 0, 4, 2)) { return 1; } + if (!check_indices ( Y, 2, 0, 6, 3)) { return 1; } + if (!check_indices ( Z, 3, 0, 9, 1)) { return 1; } + if (!check_indices ( X1, 4, 1, 10, 1)) { return 1; } + if (!check_indices ( X2, 5, 1, 11, 0)) { return 1; } + if (!check_indices ( Y1, 6, 2, 11, 0)) { return 1; } + if (!check_indices ( Y2, 7, 2, 11, 1)) { return 1; } + if (!check_indices ( Y3, 8, 2, 12, 0)) { return 1; } + if (!check_indices ( Z1, 9, 3, 12, 0)) { return 1; } + if (!check_indices (X1a, 10, 4, 12, 0)) { return 1; } + if (!check_indices (Y2a, 11, 7, 12, 0)) { return 1; } + + Transform_SetParent (T, B); + + dump_hierarchy (root->hierarchy); + + if (!check_hierarchy_size (root->hierarchy, 25)) { return 1; } + + if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 4)) { return 1; } + if (!check_indices ( C, 3, 0, 11, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 12, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 12, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 13, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 13, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 13, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 14, 0)) { return 1; } + if (!check_indices ( T, 10, 2, 14, 3)) { return 1; } + if (!check_indices ( C1, 11, 3, 17, 0)) { return 1; } + if (!check_indices (A1a, 12, 5, 17, 0)) { return 1; } + if (!check_indices (B2a, 13, 8, 17, 0)) { return 1; } + if (!check_indices ( X, 14, 10, 17, 2)) { return 1; } + if (!check_indices ( Y, 15, 10, 19, 3)) { return 1; } + if (!check_indices ( Z, 16, 10, 22, 1)) { return 1; } + if (!check_indices ( X1, 17, 14, 23, 1)) { return 1; } + if (!check_indices ( X2, 18, 14, 24, 0)) { return 1; } + if (!check_indices ( Y1, 19, 15, 24, 0)) { return 1; } + if (!check_indices ( Y2, 20, 15, 24, 1)) { return 1; } + if (!check_indices ( Y3, 21, 15, 25, 0)) { return 1; } + if (!check_indices ( Z1, 22, 16, 25, 0)) { return 1; } + if (!check_indices (X1a, 23, 17, 25, 0)) { return 1; } + if (!check_indices (Y2a, 24, 20, 25, 0)) { return 1; } + + Transform_SetParent (Y, 0); + + dump_hierarchy (root->hierarchy); + dump_hierarchy (Y->hierarchy); + if (!check_hierarchy_size (root->hierarchy, 20)) { return 1; } + if (!check_hierarchy_size (Y->hierarchy, 5)) { return 1; } + + if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 4)) { return 1; } + if (!check_indices ( C, 3, 0, 11, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 12, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 12, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 13, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 13, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 13, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 14, 0)) { return 1; } + if (!check_indices ( T, 10, 2, 14, 3)) { return 1; } + if (!check_indices ( C1, 11, 3, 17, 0)) { return 1; } + if (!check_indices (A1a, 12, 5, 17, 0)) { return 1; } + if (!check_indices (B2a, 13, 8, 17, 0)) { return 1; } + if (!check_indices ( X, 14, 10, 16, 2)) { return 1; } + if (!check_indices ( Z, 15, 10, 18, 1)) { return 1; } + if (!check_indices ( X1, 16, 14, 19, 1)) { return 1; } + if (!check_indices ( X2, 17, 14, 20, 0)) { return 1; } + if (!check_indices ( Z1, 18, 15, 20, 0)) { return 1; } + if (!check_indices (X1a, 19, 16, 20, 0)) { return 1; } + + if (!check_indices ( Y, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices ( Y1, 1, 0, 4, 0)) { return 1; } + if (!check_indices ( Y2, 2, 0, 4, 1)) { return 1; } + if (!check_indices ( Y3, 3, 0, 5, 0)) { return 1; } + if (!check_indices (Y2a, 4, 2, 5, 0)) { return 1; } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (root->hierarchy); + Hierarchy_Delete (Y->hierarchy); + + return 0; +} + +static int +check_vector (const transform_t *transform, + vec4f_t (*func) (const transform_t *t), + vec4f_t expect, const char *msg) +{ + vec4f_t res = func(transform); + if (!vec4_equal (res, expect)) { + printf ("%s %s: expected "VEC4F_FMT" got "VEC4F_FMT"\n", + Transform_GetName (transform), msg, + VEC4_EXP (expect), VEC4_EXP (res)); + return 0; + } + return 1; +} + +static int +test_frames (void) +{ + transform_t *root = Transform_NewNamed (0, "root"); + transform_t *A = Transform_NewNamed (root, "A"); + transform_t *B = Transform_NewNamed (root, "B"); + transform_t *A1 = Transform_NewNamed (A, "A1"); + transform_t *B1 = Transform_NewNamed (B, "B1"); + + Transform_SetLocalPosition (root, (vec4f_t) { 0, 0, 1, 1 }); + Transform_SetLocalPosition (A, (vec4f_t) { 1, 0, 0, 1 }); + Transform_SetLocalRotation (A, (vec4f_t) { 0.5, 0.5, 0.5, 0.5 }); + Transform_SetLocalPosition (B, (vec4f_t) { 0, 1, 0, 1 }); + Transform_SetLocalRotation (B, (vec4f_t) { 0.5, -0.5, 0.5, 0.5 }); + Transform_SetLocalPosition (A1, (vec4f_t) { 1, 0, 0, 1 }); + Transform_SetLocalRotation (A1, (vec4f_t) { -0.5, -0.5, -0.5, 0.5 }); + Transform_SetLocalPosition (B1, (vec4f_t) { 0, 1, 0, 1 }); + Transform_SetLocalRotation (B1, (vec4f_t) { -0.5, 0.5, -0.5, 0.5 }); + + hierarchy_t *h = root->hierarchy; + for (size_t i = 0; i < h->transform.size; i++) { + mat4f_t res; + mmulf (res, h->localMatrix.a[i], h->localInverse.a[i]); + if (!mat4_equal (res, identity)) { + printf ("%s: localInverse not inverse of localMatrix\n", + h->name.a[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 3)); + printf ("r: " VEC4F_FMT "\n", MAT4_ROW(res, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 3)); + return 1; + } + puts (h->name.a[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 3)); + } + for (size_t i = 0; i < h->transform.size; i++) { + mat4f_t res; + mmulf (res, h->worldMatrix.a[i], h->worldInverse.a[i]); + if (!mat4_equal (res, identity)) { + printf ("%s: worldInverse not inverse of worldMatrix\n", + h->name.a[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 3)); + printf ("r: " VEC4F_FMT "\n", MAT4_ROW(res, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 3)); + return 1; + } + puts (h->name.a[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 3)); + } + + if (!check_vector (root, Transform_GetLocalPosition, + (vec4f_t) { 0, 0, 1, 1 }, "local position")) { + return 1; + } + if (!check_vector (root, Transform_GetWorldPosition, + (vec4f_t) { 0, 0, 1, 1 }, "world position")) { + return 1; + } + if (!check_vector (root, Transform_Right, (vec4f_t) { 1, 0, 0, 0 }, + "right")) { + return 1; + } + if (!check_vector (root, Transform_Forward, (vec4f_t) { 0, 1, 0, 0 }, + "right")) { + return 1; + } + if (!check_vector (root, Transform_Up, (vec4f_t) { 0, 0, 1, 0 }, + "up")) { + return 1; + } + + if (!check_vector (A, Transform_GetLocalPosition, (vec4f_t) { 1, 0, 0, 1 }, + "local position")) { + return 1; + } + if (!check_vector (A, Transform_GetWorldPosition, (vec4f_t) { 1, 0, 1, 1 }, + "world position")) { + return 1; + } + if (!check_vector (A, Transform_Right, (vec4f_t) { 0, 1, 0, 0 }, + "right")) { + return 1; + } + if (!check_vector (A, Transform_Forward, (vec4f_t) { 0, 0, 1, 0 }, + "forward")) { + return 1; + } + if (!check_vector (A, Transform_Up, (vec4f_t) { 1, 0, 0, 0 }, + "up")) { + return 1; + } + if (!check_vector (A1, Transform_GetLocalPosition, (vec4f_t) { 1, 0, 0, 1 }, + "local position")) { + return 1; + } + if (!check_vector (A1, Transform_GetWorldPosition, (vec4f_t) { 1, 1, 1, 1 }, + "world position")) { + return 1; + } + if (!check_vector (A1, Transform_Right, (vec4f_t) { 1, 0, 0, 0 }, + "right")) { + return 1; + } + if (!check_vector (A1, Transform_Forward, (vec4f_t) { 0, 1, 0, 0 }, + "forward")) { + return 1; + } + if (!check_vector (A1, Transform_Up, (vec4f_t) { 0, 0, 1, 0 }, + "up")) { + return 1; + } + + if (!check_vector (B, Transform_GetLocalPosition, (vec4f_t) { 0, 1, 0, 1 }, + "local position")) { + return 1; + } + if (!check_vector (B, Transform_GetWorldPosition, (vec4f_t) { 0, 1, 1, 1 }, + "world position")) { + return 1; + } + if (!check_vector (B, Transform_Right, (vec4f_t) { 0, 0, 1, 0 }, + "right")) { + return 1; + } + if (!check_vector (B, Transform_Forward, (vec4f_t) {-1, 0, 0, 0 }, + "forward")) { + return 1; + } + if (!check_vector (B, Transform_Up, (vec4f_t) { 0,-1, 0, 0 }, + "up")) { + return 1; + } + if (!check_vector (B1, Transform_GetLocalPosition, (vec4f_t) { 0, 1, 0, 1 }, + "local position")) { + return 1; + } + if (!check_vector (B1, Transform_GetWorldPosition, (vec4f_t) {-1, 1, 1, 1 }, + "world position")) { + return 1; + } + if (!check_vector (B1, Transform_Right, (vec4f_t) { 1, 0, 0, 0 }, + "right")) { + return 1; + } + if (!check_vector (B1, Transform_Forward, (vec4f_t) { 0, 1, 0, 0 }, + "forward")) { + return 1; + } + if (!check_vector (B1, Transform_Up, (vec4f_t) { 0, 0, 1, 0 }, + "up")) { + return 1; + } + + return 0; +} + +int +main (void) +{ + if (test_single_transform ()) { return 1; } + if (test_parent_child_init ()) { return 1; } + if (test_parent_child_setparent ()) { return 1; } + if (test_build_hierarchy ()) { return 1; } + if (test_build_hierarchy2 ()) { return 1; } + if (test_frames ()) { return 1; } + + return 0; +} diff --git a/libs/entity/transform.c b/libs/entity/transform.c new file mode 100644 index 000000000..18382e56c --- /dev/null +++ b/libs/entity/transform.c @@ -0,0 +1,317 @@ +/* + transform.c + + General transform handling + + Copyright (C) 2021 Bill Currke + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/entity.h" +#include "QF/render.h" + +transform_t * +Transform_New (transform_t *parent) +{ + transform_t *transform = malloc (sizeof (transform_t)); + + if (parent) { + transform->hierarchy = parent->hierarchy; + transform->index = Hierarchy_InsertHierarchy (parent->hierarchy, 0, + parent->index, 0); + } else { + transform->hierarchy = Hierarchy_New (16, 1);//FIXME should be config + transform->index = 0; + } + transform->hierarchy->transform.a[transform->index] = transform; + Hierarchy_UpdateMatrices (transform->hierarchy); + return transform; +} + +void +Transform_Delete (transform_t *transform) +{ + if (transform->index != 0) { + // The transform is not the root, so pull it out of its current + // hierarchy so deleting it is easier + Transform_SetParent (transform, 0); + } + Hierarchy_Delete (transform->hierarchy); +} + +transform_t * +Transform_NewNamed (transform_t *parent, const char *name) +{ + transform_t *transform = Transform_New (parent); + Transform_SetName (transform, name); + return transform; +} + +uint32_t +Transform_ChildCount (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->childCount.a[transform->index]; +} + +transform_t * +Transform_GetChild (const transform_t *transform, uint32_t childIndex) +{ + hierarchy_t *h = transform->hierarchy; + if (childIndex >= h->childCount.a[transform->index]) { + return 0; + } + return h->transform.a[h->childIndex.a[transform->index] + childIndex]; +} + +void +Transform_SetParent (transform_t *transform, transform_t *parent) +{ + if (parent) { + hierarchy_t *hierarchy = transform->hierarchy; + uint32_t index = transform->index; + Hierarchy_InsertHierarchy (parent->hierarchy, hierarchy, + parent->index, index); + Hierarchy_RemoveHierarchy (hierarchy, index); + if (!hierarchy->name.size) { + Hierarchy_Delete (hierarchy); + } + } else { + // null parent -> make transform root + if (!transform->index) { + // already root + return; + } + hierarchy_t *hierarchy = transform->hierarchy; + uint32_t index = transform->index; + + hierarchy_t *new_hierarchy = Hierarchy_New (16, 0); + Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, null_transform, + index); + Hierarchy_RemoveHierarchy (hierarchy, index); + } +} + +transform_t * +Transform_GetParent (const transform_t *transform) +{ + if (transform->index == 0) { + return 0; + } + hierarchy_t *h = transform->hierarchy; + return h->transform.a[h->parentIndex.a[transform->index]]; +} + +void +Transform_SetName (transform_t *transform, const char *name) +{ + hierarchy_t *h = transform->hierarchy; + //FIXME create a string pool (similar to qfcc's, or even move that to util) + if (h->name.a[transform->index]) { + free (h->name.a[transform->index]); + } + h->name.a[transform->index] = strdup (name); +} + +const char * +Transform_GetName (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->name.a[transform->index]; +} + +void +Transform_SetTag (transform_t *transform, uint32_t tag) +{ + hierarchy_t *h = transform->hierarchy; + h->tag.a[transform->index] = tag; +} + +uint32_t +Transform_GetTag (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->tag.a[transform->index]; +} + +void +Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat) +{ + hierarchy_t *h = transform->hierarchy; + memcpy (mat, h->localMatrix.a[transform->index], sizeof (mat4f_t)); +} + +void +Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat) +{ + hierarchy_t *h = transform->hierarchy; + memcpy (mat, h->localInverse.a[transform->index], sizeof (mat4f_t)); +} + +void +Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat) +{ + hierarchy_t *h = transform->hierarchy; + memcpy (mat, h->worldMatrix.a[transform->index], sizeof (mat4f_t)); +} + +void +Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat) +{ + hierarchy_t *h = transform->hierarchy; + memcpy (mat, h->worldInverse.a[transform->index], sizeof (mat4f_t)); +} + +vec4f_t +Transform_GetLocalPosition (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->localMatrix.a[transform->index][3]; +} + +void +Transform_SetLocalPosition (transform_t *transform, vec4f_t position) +{ + hierarchy_t *h = transform->hierarchy; + h->localMatrix.a[transform->index][3] = position; + h->modified.a[transform->index] = 1; + Hierarchy_UpdateMatrices (h); +} + +vec4f_t +Transform_GetLocalRotation (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->localRotation.a[transform->index]; +} + +void +Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation) +{ + hierarchy_t *h = transform->hierarchy; + vec4f_t scale = h->localScale.a[transform->index]; + + mat4f_t mat; + mat4fquat (mat, rotation); + + h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; + h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; + h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; + h->modified.a[transform->index] = 1; + Hierarchy_UpdateMatrices (h); +} + +vec4f_t +Transform_GetLocalScale (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->localScale.a[transform->index]; +} + +void +Transform_SetLocalScale (transform_t *transform, vec4f_t scale) +{ + hierarchy_t *h = transform->hierarchy; + vec4f_t rotation = h->localRotation.a[transform->index]; + + mat4f_t mat; + mat4fquat (mat, rotation); + + h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; + h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; + h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; + h->modified.a[transform->index] = 1; + Hierarchy_UpdateMatrices (h); +} + +vec4f_t +Transform_GetWorldPosition (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldMatrix.a[transform->index][3]; +} + +void +Transform_SetWorldPosition (transform_t *transform, vec4f_t position) +{ + if (transform->index) { + hierarchy_t *h = transform->hierarchy; + uint32_t parent = h->parentIndex.a[transform->index]; + position = mvmulf (h->worldInverse.a[parent], position); + } + Transform_SetLocalPosition (transform, position); +} + +vec4f_t +Transform_GetWorldRotation (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldRotation.a[transform->index]; +} + +void +Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation) +{ + if (transform->index) { + hierarchy_t *h = transform->hierarchy; + uint32_t parent = h->parentIndex.a[transform->index]; + rotation = qmulf (qconjf (h->worldRotation.a[parent]), rotation); + } + Transform_SetLocalRotation (transform, rotation); +} + +vec4f_t +Transform_GetWorldScale (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldScale.a[transform->index]; +} + +vec4f_t +Transform_Forward (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldMatrix.a[transform->index][1]; +} + +vec4f_t +Transform_Right (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldMatrix.a[transform->index][0]; +} + +vec4f_t +Transform_Up (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldMatrix.a[transform->index][2]; +} From 09e1a63470f2bd38f37895003d7fde1c96fde130 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Mar 2021 23:50:32 +0900 Subject: [PATCH 1363/3664] [util] Add a simd mat4 transpose function --- include/QF/simd/mat4f.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/QF/simd/mat4f.h b/include/QF/simd/mat4f.h index 24773da87..719e4c561 100644 --- a/include/QF/simd/mat4f.h +++ b/include/QF/simd/mat4f.h @@ -38,6 +38,7 @@ GNU89INLINE inline void mmulf (mat4f_t c, const mat4f_t a, const mat4f_t b); GNU89INLINE inline vec4f_t mvmulf (const mat4f_t m, vec4f_t v) __attribute__((const)); GNU89INLINE inline vec4f_t m3vmulf (const mat4f_t m, vec4f_t v) __attribute__((const)); GNU89INLINE inline void mat4fidentity (mat4f_t m); +GNU89INLINE inline void mat4ftranspose (mat4f_t t, const mat4f_t m); GNU89INLINE inline void mat4fquat (mat4f_t m, vec4f_t q); #ifndef IMPLEMENT_MAT4F_Funcs @@ -121,6 +122,24 @@ mat4fidentity (mat4f_t m) m[3] = (vec4f_t) { 0, 0, 0, 1 }; } +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +mat4ftranspose (mat4f_t t, const mat4f_t m) +{ + vec4f_t a = m[0]; + vec4f_t b = m[1]; + vec4f_t c = m[2]; + vec4f_t d = m[3]; + t[0] = (vec4f_t) { a[0], b[0], c[0], d[0] }; + t[1] = (vec4f_t) { a[1], b[1], c[1], d[1] }; + t[2] = (vec4f_t) { a[2], b[2], c[2], d[2] }; + t[3] = (vec4f_t) { a[3], b[3], c[3], d[3] }; +} + #ifndef IMPLEMENT_MAT4F_Funcs GNU89INLINE inline #else From fbc1bd9f6ef834a1ccf7e6bdd33c551277c39794 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Mar 2021 23:52:40 +0900 Subject: [PATCH 1364/3664] [renderer] Clean up entity_t to a certain extent This is the first step towards component-based entities. There's still some transform-related stuff in the struct that needs to be moved, but it's all entirely client related (rather than renderer) and will probably go into a "client" component. Also, the current components are directly included structs rather than references as I didn't want to deal with the object management at this stage. As part of the process (because transforms use simd) this also starts the process of moving QF to using simd for vectors and matrices. There's now a mess of simd and sisd code mixed together, but it works surprisingly well together. --- include/QF/entity.h | 12 +- include/QF/render.h | 71 ++++---- include/r_local.h | 6 +- libs/entity/transform.c | 21 ++- libs/video/renderer/gl/gl_dyn_part.c | 2 +- libs/video/renderer/gl/gl_lightmap.c | 4 +- libs/video/renderer/gl/gl_mod_alias.c | 76 +++++---- libs/video/renderer/gl/gl_mod_iqm.c | 6 +- libs/video/renderer/gl/gl_mod_sprite.c | 109 ++++++------ libs/video/renderer/gl/gl_rmain.c | 23 ++- libs/video/renderer/gl/gl_rmisc.c | 5 +- libs/video/renderer/gl/gl_rsurf.c | 29 ++-- libs/video/renderer/glsl/glsl_alias.c | 55 +++--- libs/video/renderer/glsl/glsl_bsp.c | 48 +++--- libs/video/renderer/glsl/glsl_iqm.c | 27 +-- libs/video/renderer/glsl/glsl_main.c | 88 +++++----- libs/video/renderer/glsl/glsl_particles.c | 16 +- libs/video/renderer/glsl/glsl_sprite.c | 37 ++-- libs/video/renderer/r_alias.c | 6 +- libs/video/renderer/r_bsp.c | 6 +- libs/video/renderer/r_efrag.c | 26 +-- libs/video/renderer/r_ent.c | 44 +++-- libs/video/renderer/r_iqm.c | 4 +- libs/video/renderer/r_light.c | 2 +- libs/video/renderer/sw/sw_ralias.c | 52 +++--- libs/video/renderer/sw/sw_rbsp.c | 16 +- libs/video/renderer/sw/sw_rdraw.c | 4 +- libs/video/renderer/sw/sw_riqm.c | 31 ++-- libs/video/renderer/sw/sw_rmain.c | 39 +++-- libs/video/renderer/sw/sw_rmisc.c | 2 +- libs/video/renderer/sw/sw_rpart.c | 2 +- libs/video/renderer/sw/sw_rsprite.c | 15 +- libs/video/renderer/sw/sw_rsurf.c | 2 +- libs/video/renderer/sw32/sw32_ralias.c | 47 ++--- libs/video/renderer/sw32/sw32_rbsp.c | 18 +- libs/video/renderer/sw32/sw32_rdraw.c | 4 +- libs/video/renderer/sw32/sw32_riqm.c | 27 +-- libs/video/renderer/sw32/sw32_rmain.c | 39 +++-- libs/video/renderer/sw32/sw32_rmisc.c | 2 +- libs/video/renderer/sw32/sw32_rpart.c | 2 +- libs/video/renderer/sw32/sw32_rsprite.c | 15 +- libs/video/renderer/sw32/sw32_rsurf.c | 2 +- libs/video/renderer/vulkan/vulkan_alias.c | 27 +-- libs/video/renderer/vulkan/vulkan_bsp.c | 34 ++-- libs/video/renderer/vulkan/vulkan_main.c | 8 +- nq/source/Makemodule.am | 1 + nq/source/cl_ents.c | 106 +++++++----- nq/source/cl_main.c | 5 +- nq/source/cl_parse.c | 22 +-- nq/source/cl_tent.c | 31 ++-- nq/source/cl_view.c | 8 +- qw/source/Makemodule.am | 1 + qw/source/cl_demo.c | 10 +- qw/source/cl_entparse.c | 4 +- qw/source/cl_ents.c | 198 ++++++++++++---------- qw/source/cl_parse.c | 6 +- qw/source/cl_tent.c | 44 +++-- qw/source/cl_view.c | 15 +- ruamoko/qwaq/Makemodule.am | 1 + 59 files changed, 881 insertions(+), 682 deletions(-) diff --git a/include/QF/entity.h b/include/QF/entity.h index 9bf676190..032db67a2 100644 --- a/include/QF/entity.h +++ b/include/QF/entity.h @@ -92,16 +92,18 @@ void Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat); void Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat); void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat); vec4f_t Transform_GetLocalPosition (const transform_t *transform) __attribute__((pure)); -void Transform_SetLocalPosition (transform_t *transform_t, vec4f_t position); +void Transform_SetLocalPosition (transform_t *transform, vec4f_t position); vec4f_t Transform_GetLocalRotation (const transform_t *transform) __attribute__((pure)); -void Transform_SetLocalRotation (transform_t *transform_t, vec4f_t rotation); +void Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation); vec4f_t Transform_GetLocalScale (const transform_t *transform) __attribute__((pure)); -void Transform_SetLocalScale (transform_t *transform_t, vec4f_t scale); +void Transform_SetLocalScale (transform_t *transform, vec4f_t scale); vec4f_t Transform_GetWorldPosition (const transform_t *transform) __attribute__((pure)); -void Transform_SetWorldPosition (transform_t *transform_t, vec4f_t position); +void Transform_SetWorldPosition (transform_t *transform, vec4f_t position); vec4f_t Transform_GetWorldRotation (const transform_t *transform) __attribute__((pure)); -void Transform_SetWorldRotation (transform_t *transform_t, vec4f_t rotation); +void Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation); vec4f_t Transform_GetWorldScale (const transform_t *transform) __attribute__((pure)); +void Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, + vec4f_t rotation, vec4f_t position); // NOTE: these use X: right, Y: forward, Z:up // aslo, not guaranteed to be normalized or even orthogonal vec4f_t Transform_Forward (const transform_t *transform) __attribute__((pure)); diff --git a/include/QF/render.h b/include/QF/render.h index 607b8b800..d6a871865 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -90,47 +90,56 @@ typedef struct //=============== +typedef struct animation_s { + int frame; + float syncbase; // randomize time base for local animations + float frame_start_time; + float frame_interval; + int pose1; + int pose2; + float blend; + int nolerp; // don't lerp this frame (pose data invalid) +} animation_t; + +typedef struct visibility_s { + struct entity_s *entity; // owning entity + struct efrag_s *efrag; // linked list of efrags + struct mnode_s *topnode; // bmodels, first world node that + // splits bmodel, or NULL if not split + // applies to other models, too + int visframe; // last frame this entity was + // found in an active leaf + int trivial_accept; // view clipping (frustum and depth) +} visibility_t; + +typedef struct renderer_s { + struct model_s *model; // NULL = no model + struct skin_s *skin; + float colormod[4]; // color tint and alpha for model + int skinnum; // for Alias models + int fullbright; + float min_light; + mat4_t full_transform; +} renderer_t; + typedef struct entity_s { struct entity_s *next; struct entity_s *unext; //FIXME this shouldn't be here. for qw demos + struct transform_s *transform; + animation_t animation; + visibility_t visibility; + renderer_t renderer; + int active; + //XXX FIXME XXX should not be here + float scale; vec3_t origin; vec3_t old_origin; vec3_t angles; - vec_t transform[4 * 4]; - vec_t full_transform[4 * 4]; - struct model_s *model; // NULL = no model - int frame; - int skinnum; // for Alias models - struct skin_s *skin; - - float syncbase; // for client-side animations - - struct efrag_s *efrag; // linked list of efrags - int visframe; // last frame this entity was - // found in an active leaf - float colormod[4]; // color tint and alpha for model - float scale; // size scaler of the model - - int fullbright; - float min_light; - - // FIXME: could turn these into a union - int trivial_accept; - struct mnode_s *topnode; // for bmodels, first world node that - // splits bmodel, or NULL if not split - - // Animation interpolation - float frame_start_time; - float frame_interval; - int pose1; - int pose2; - struct model_s *pose_model; // no lerp if not the same as model } entity_t; // !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct -{ +typedef struct { vrect_t vrect; // subwindow in video for refresh // FIXME: not need vrect next field here? vrect_t aliasvrect; // scaled Alias version diff --git a/include/r_local.h b/include/r_local.h index 9e56b7343..37d5308c1 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -33,6 +33,8 @@ #include "QF/model.h" #include "QF/render.h" #include "QF/vid.h" +#include "QF/simd/mat4f.h" +#include "QF/simd/vec4f.h" #include "r_shared.h" #define ALIAS_BASE_SIZE_RATIO (1.0 / 11.0) @@ -136,8 +138,8 @@ extern qboolean r_cache_thrash; // set if thrashing the surface cache extern qboolean insubmodel; extern vec3_t r_worldmodelorg; -extern mat4_t glsl_projection; -extern mat4_t glsl_view; +extern mat4f_t glsl_projection; +extern mat4f_t glsl_view; void R_SetFrustum (void); diff --git a/libs/entity/transform.c b/libs/entity/transform.c index 18382e56c..0e274f83a 100644 --- a/libs/entity/transform.c +++ b/libs/entity/transform.c @@ -295,18 +295,35 @@ Transform_GetWorldScale (const transform_t *transform) return h->worldScale.a[transform->index]; } +void +Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, + vec4f_t rotation, vec4f_t position) +{ + hierarchy_t *h = transform->hierarchy; + mat4f_t mat; + mat4fquat (mat, rotation); + + position[3] = 1; + h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; + h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; + h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; + h->localMatrix.a[transform->index][3] = position; + h->modified.a[transform->index] = 1; + Hierarchy_UpdateMatrices (h); +} + vec4f_t Transform_Forward (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][1]; + return h->worldMatrix.a[transform->index][0]; } vec4f_t Transform_Right (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][0]; + return -h->worldMatrix.a[transform->index][1]; } vec4f_t diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 5f510b26c..5aa093813 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -205,7 +205,7 @@ gl_R_ReadPointFile_f (void) vec3_t org; QFile *f; - mapname = strdup (r_worldentity.model->path); + mapname = strdup (r_worldentity.renderer.model->path); if (!mapname) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index c6270f5d4..d46c35014 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -582,7 +582,7 @@ gl_overbright_f (cvar_t *var) return; for (ent = r_ent_queue; ent; ent = ent->next) { - m = ent->model; + m = ent->renderer.model; if (m->type != mod_brush) continue; @@ -605,7 +605,7 @@ gl_overbright_f (cvar_t *var) } } - brush = &r_worldentity.model->brush; + brush = &r_worldentity.renderer.model->brush; for (i = 0, fa = brush->surfaces; i < brush->numsurfaces; i++, fa++) { if (fa->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index d47a1504f..4b90ba54a 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -43,6 +43,7 @@ #include #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/locs.h" #include "QF/mathlib.h" #include "QF/qargs.h" @@ -299,14 +300,14 @@ GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t *e) if (blend == 0.0) { - verts = verts + e->pose1 * count; + verts = verts + e->animation.pose1 * count; } else if (blend == 1.0) { - verts = verts + e->pose2 * count; + verts = verts + e->animation.pose2 * count; } else { trivertx16_t *verts1, *verts2; - verts1 = verts + e->pose1 * count; - verts2 = verts + e->pose2 * count; + verts1 = verts + e->animation.pose1 * count; + verts2 = verts + e->animation.pose2 * count; for (i = 0, vo_v = vo->verts; i < count; i++, vo_v++, verts1++, verts2++) { @@ -362,14 +363,14 @@ GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t *e) blend = 1.0; if (blend == 0.0) { - verts = verts + e->pose1 * count; + verts = verts + e->animation.pose1 * count; } else if (blend == 1.0) { - verts = verts + e->pose2 * count; + verts = verts + e->animation.pose2 * count; } else { trivertx_t *verts1, *verts2; - verts1 = verts + e->pose1 * count; - verts2 = verts + e->pose2 * count; + verts1 = verts + e->animation.pose1 * count; + verts2 = verts + e->animation.pose2 * count; for (i = 0, vo_v = vo->verts; i < count; i++, vo_v++, verts1++, verts2++) { @@ -415,7 +416,7 @@ gl_R_DrawAliasModel (entity_t *e) vec3_t dist, scale; vert_order_t *vo; - model = e->model; + model = e->renderer.model; radius = model->radius; if (e->scale != 1.0) @@ -425,18 +426,18 @@ gl_R_DrawAliasModel (entity_t *e) VectorSubtract (r_origin, e->origin, modelorg); - gl_modelalpha = e->colormod[3]; + gl_modelalpha = e->renderer.colormod[3]; - is_fullbright = (model->fullbright || e->fullbright); - minlight = max (model->min_light, e->min_light); + is_fullbright = (model->fullbright || e->renderer.fullbright); + minlight = max (model->min_light, e->renderer.min_light); - qfglColor4fv (e->colormod); + qfglColor4fv (e->renderer.colormod); if (!is_fullbright) { float lightadj; // get lighting information - R_LightPoint (&r_worldentity.model->brush, e->origin); + R_LightPoint (&r_worldentity.renderer.model->brush, e->origin); lightadj = (ambientcolor[0] + ambientcolor[1] + ambientcolor[2]) / 765.0; @@ -530,24 +531,25 @@ gl_R_DrawAliasModel (entity_t *e) VectorScale (emission, 1.5 / d, emission); } - emission[0] *= e->colormod[0]; - emission[1] *= e->colormod[1]; - emission[2] *= e->colormod[2]; - emission[3] *= e->colormod[3]; + emission[0] *= e->renderer.colormod[0]; + emission[1] *= e->renderer.colormod[1]; + emission[2] *= e->renderer.colormod[2]; + emission[3] *= e->renderer.colormod[3]; qfglColor4fv (emission); } } // locate the proper data - if (!(paliashdr = e->model->aliashdr)) - paliashdr = Cache_Get (&e->model->cache); + if (!(paliashdr = e->renderer.model->aliashdr)) { + paliashdr = Cache_Get (&e->renderer.model->cache); + } gl_c_alias_polys += paliashdr->mdl.numtris; // if the model has a colorised/external skin, use it, otherwise use // the skin embedded in the model data - if (e->skin && e->skin->texnum && !gl_nocolors->int_val) { - skin_t *skin = e->skin; + if (e->renderer.skin && e->renderer.skin->texnum && !gl_nocolors->int_val) { + skin_t *skin = e->renderer.skin; texture = skin->texnum; if (gl_fb_models->int_val) { @@ -556,10 +558,11 @@ gl_R_DrawAliasModel (entity_t *e) } else { maliasskindesc_t *skindesc; - skindesc = R_AliasGetSkindesc (e->skinnum, paliashdr); + skindesc = R_AliasGetSkindesc (e->renderer.skinnum, paliashdr); texture = skindesc->texnum; - if (gl_fb_models->int_val && !is_fullbright) + if (gl_fb_models->int_val && !is_fullbright) { fb_texture = skindesc->fb_texnum; + } } if (paliashdr->mdl.ident == HEADER_MDL16) { @@ -640,7 +643,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglDisable (GL_NORMALIZE); } - qfglColor4fv (e->colormod); + qfglColor4fv (e->renderer.colormod); qfglBindTexture (GL_TEXTURE_2D, fb_texture); GL_DrawAliasFrameTri (vo); @@ -660,7 +663,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglDisable (GL_NORMALIZE); } - qfglColor4fv (e->colormod); + qfglColor4fv (e->renderer.colormod); qfglBindTexture (GL_TEXTURE_2D, fb_texture); GL_DrawAliasFrame (vo); @@ -678,7 +681,7 @@ gl_R_DrawAliasModel (entity_t *e) // torches, grenades, and lightning bolts do not have shadows if (r_shadows->int_val && model->shadow_alpha) { - mat4_t shadow_mat; + mat4f_t shadow_mat; qfglPushMatrix (); gl_R_RotateForEntity (e); @@ -690,19 +693,19 @@ gl_R_DrawAliasModel (entity_t *e) qfglDepthMask (GL_FALSE); if (gl_modelalpha < 1.0) { - VectorBlend (e->colormod, dark, 0.5, color); + VectorBlend (e->renderer.colormod, dark, 0.5, color); color[3] = gl_modelalpha * (model->shadow_alpha / 255.0); qfglColor4fv (color); } else { color_black[3] = model->shadow_alpha; qfglColor4ubv (color_black); } - shadevector[0] = 1; - shadevector[1] = 0; - shadevector[2] = 1; - VectorNormalize (shadevector); - Mat4Transpose (e->transform, shadow_mat); - Mat4as3MultVec (shadow_mat, shadevector, shadevector); + //FIXME fully vectorize + vec4f_t vec = { 707106781, 0, 707106781, 0 }; + Transform_GetWorldMatrix (e->transform, shadow_mat); + mat4ftranspose (shadow_mat, shadow_mat); + vec = mvmulf (shadow_mat, vec); + VectorCopy (vec, shadevector); if (vo->tex_coord) GL_DrawAliasShadowTri (paliashdr, vo); else @@ -722,6 +725,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglDisable (GL_LIGHT0 + used_lights); } - if (!e->model->aliashdr) - Cache_Release (&e->model->cache); + if (!e->renderer.model->aliashdr) { + Cache_Release (&e->renderer.model->cache); + } } diff --git a/libs/video/renderer/gl/gl_mod_iqm.c b/libs/video/renderer/gl/gl_mod_iqm.c index 4c50795b7..601a76fbf 100644 --- a/libs/video/renderer/gl/gl_mod_iqm.c +++ b/libs/video/renderer/gl/gl_mod_iqm.c @@ -90,7 +90,7 @@ gl_draw_iqm_frame (iqm_t *iqm, gliqm_t *gl, iqmframe_t *frame, iqmmesh *mesh) void gl_R_DrawIQMModel (entity_t *ent) { - model_t *model = ent->model; + model_t *model = ent->renderer.model; iqm_t *iqm = (iqm_t *) model->aliashdr; gliqm_t *gl = (gliqm_t *) iqm->extra_data; float blend; @@ -98,8 +98,8 @@ gl_R_DrawIQMModel (entity_t *ent) int i; blend = R_IQMGetLerpedFrames (ent, iqm); - frame = R_IQMBlendPalette (iqm, ent->pose1, ent->pose2, blend, 0, - gl->blend_palette, gl->palette_size); + frame = R_IQMBlendPalette (iqm, ent->animation.pose1, ent->animation.pose2, + blend, 0, gl->blend_palette, gl->palette_size); qfglPushMatrix (); gl_R_RotateForEntity (ent); diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index c5b484ed7..b6ce25f22 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -41,6 +41,7 @@ #include "QF/GL/defines.h" #include "QF/GL/funcs.h" +#include "QF/entity.h" #include "QF/model.h" #include "QF/render.h" #include "QF/sys.h" @@ -66,8 +67,8 @@ R_GetSpriteFrame (entity_t *currententity) mspriteframe_t *pspriteframe; mspritegroup_t *pspritegroup; - psprite = currententity->model->cache.data; - frame = currententity->frame; + psprite = currententity->renderer.model->cache.data; + frame = currententity->animation.frame; if ((frame >= psprite->numframes) || (frame < 0)) { Sys_MaskPrintf (SYS_DEV, "R_DrawSprite: no such frame %d\n", frame); @@ -82,7 +83,7 @@ R_GetSpriteFrame (entity_t *currententity) numframes = pspritegroup->numframes; fullinterval = pintervals[numframes - 1]; - time = vr_data.realtime + currententity->syncbase; + time = vr_data.realtime + currententity->animation.syncbase; // when loading in Mod_LoadSpriteGroup, we guaranteed all interval // values are positive, so we don't have to worry about division by 0 @@ -103,35 +104,32 @@ static void R_DrawSpriteModel_f (entity_t *e) { float modelalpha, color[4]; - float *up, *right; + vec4f_t up = {}, right = {}; + vec4f_t origin, point1, point2; msprite_t *psprite; mspriteframe_t *frame; - vec3_t point, point1, point2, v_up; // don't bother culling, it's just a single polygon without a surface cache frame = R_GetSpriteFrame (e); - psprite = e->model->cache.data; + psprite = e->renderer.model->cache.data; if (psprite->type == SPR_ORIENTED) { // bullet marks on walls - up = e->transform + 2 * 4; - right = e->transform + 1 * 4; + up = Transform_Up (e->transform); + right = Transform_Right (e->transform); } else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) { - v_up[0] = 0; - v_up[1] = 0; - v_up[2] = 1; - up = v_up; - right = vright; + up = (vec4f_t) { 0, 0, 1, 0 }; + VectorCopy (vright, right); } else { // normal sprite - up = vup; - right = vright; + VectorCopy (vup, up); + VectorCopy (vright, right); } if (e->scale != 1.0) { - VectorScale (up, e->scale, up); - VectorScale (right, e->scale, right); + up *= e->scale; + right *= e->scale; } - VectorCopy (e->colormod, color); - modelalpha = color[3] = e->colormod[3]; + VectorCopy (e->renderer.colormod, color); + modelalpha = color[3] = e->renderer.colormod[3]; if (modelalpha < 1.0) qfglDepthMask (GL_FALSE); @@ -141,23 +139,24 @@ R_DrawSpriteModel_f (entity_t *e) qfglColor4fv (color); + origin = Transform_GetWorldPosition (e->transform); + point1 = origin + frame->down * up + frame->left * right; + point2 = origin + frame->up * up + frame->left * right; + qfglTexCoord2f (0, 1); - VectorMultAdd (e->origin, frame->down, up, point1); - VectorMultAdd (point1, frame->left, right, point); - qfglVertex3fv (point); + qfglVertex3fv (&point1[0]); qfglTexCoord2f (0, 0); - VectorMultAdd (e->origin, frame->up, up, point2); - VectorMultAdd (point2, frame->left, right, point); - qfglVertex3fv (point); + qfglVertex3fv (&point2[0]); + + point2 += frame->right * right; + point1 += frame->right * right; qfglTexCoord2f (1, 0); - VectorMultAdd (point2, frame->right, right, point); - qfglVertex3fv (point); + qfglVertex3fv (&point2[0]); qfglTexCoord2f (1, 1); - VectorMultAdd (point1, frame->right, right, point); - qfglVertex3fv (point); + qfglVertex3fv (&point1[0]); qfglEnd (); @@ -169,60 +168,60 @@ static void R_DrawSpriteModel_VA_f (entity_t *e) { unsigned char modelalpha, color[4]; - float *up, *right; + vec4f_t up = {}, right = {}; + vec4f_t origin, point1, point2; int i; // unsigned int vacount; msprite_t *psprite; mspriteframe_t *frame; - vec3_t point1, point2, v_up; varray_t2f_c4ub_v3f_t *VA; VA = gl_spriteVertexArray; // FIXME: Despair // don't bother culling, it's just a single polygon without a surface cache frame = R_GetSpriteFrame (e); - psprite = e->model->cache.data; + psprite = e->renderer.model->cache.data; qfglBindTexture (GL_TEXTURE_2D, frame->gl_texturenum); // FIXME: DESPAIR if (psprite->type == SPR_ORIENTED) { // bullet marks on walls - up = e->transform + 2 * 4; - right = e->transform + 1 * 4; + up = Transform_Up (e->transform); + right = Transform_Right (e->transform); } else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) { - v_up[0] = 0; - v_up[1] = 0; - v_up[2] = 1; - up = v_up; - right = vright; + up = (vec4f_t) { 0, 0, 1, 0 }; + VectorCopy (vright, right); } else { // normal sprite - up = vup; - right = vright; + VectorCopy (vup, up); + VectorCopy (vright, right); } if (e->scale != 1.0) { - VectorScale (up, e->scale, up); - VectorScale (right, e->scale, right); + up *= e->scale; + right *= e->scale; } - for (i = 0; i < 4; i++) - color[i] = e->colormod[i] * 255; + for (i = 0; i < 4; i++) { + color[i] = e->renderer.colormod[i] * 255; + } memcpy (VA[0].color, color, 4); + memcpy (VA[1].color, color, 4); + memcpy (VA[2].color, color, 4); + memcpy (VA[3].color, color, 4); modelalpha = color[3]; if (modelalpha < 255) qfglDepthMask (GL_FALSE); - VectorMultAdd (e->origin, frame->down, up, point1); - VectorMultAdd (point1, frame->left, right, VA[0].vertex); + origin = Transform_GetWorldPosition (e->transform); + point1 = origin + frame->down * up + frame->left * right; + VectorCopy (point1, VA[0].vertex); - memcpy (VA[1].color, color, 4); - VectorMultAdd (e->origin, frame->up, up, point2); - VectorMultAdd (point2, frame->left, right, VA[1].vertex); + point2 = origin + frame->up * up + frame->left * right; + VectorCopy (point2, VA[1].vertex); - memcpy (VA[2].color, color, 4); - VectorMultAdd (point2, frame->right, right, VA[2].vertex); - - memcpy (VA[3].color, color, 4); - VectorMultAdd (point1, frame->right, right, VA[3].vertex); + point2 += frame->right * right; + point1 += frame->right * right; + VectorCopy (point2, VA[2].vertex); + VectorCopy (point1, VA[3].vertex); // VA += 4; // vacount += 4; diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 1f9b30696..23d7f7be4 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -44,6 +44,7 @@ #include "QF/cvar.h" #include "QF/draw.h" +#include "QF/entity.h" #include "QF/locs.h" #include "QF/mathlib.h" #include "QF/qargs.h" @@ -178,7 +179,9 @@ glrmain_init (void) void gl_R_RotateForEntity (entity_t *e) { - qfglMultMatrixf (e->transform); + mat4f_t mat; + Transform_GetWorldMatrix (e->transform, mat); + qfglMultMatrixf (&mat[0][0]); } /* @@ -217,7 +220,7 @@ R_DrawEntitiesOnList (void) } for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->model->type != mod_alias) + if (ent->renderer.model->type != mod_alias) continue; currententity = ent; @@ -249,7 +252,7 @@ R_DrawEntitiesOnList (void) } for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->model->type != mod_iqm) + if (ent->renderer.model->type != mod_iqm) continue; currententity = ent; @@ -262,7 +265,7 @@ R_DrawEntitiesOnList (void) if (gl_va_capable) qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray); for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->model->type != mod_sprite) + if (ent->renderer.model->type != mod_sprite) continue; currententity = ent; @@ -279,7 +282,7 @@ R_DrawViewModel (void) || !r_drawviewmodel->int_val || gl_envmap || !r_drawentities->int_val - || !currententity->model) + || !currententity->renderer.model) return; // hack the depth range to prevent view model from poking into walls @@ -349,7 +352,7 @@ gl_R_SetupFrame (void) R_SetFrustum (); // current viewleaf - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.model); + r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); r_cache_thrash = false; @@ -559,10 +562,12 @@ R_Mirror (void) static void R_RenderView_ (void) { - if (r_norefresh->int_val) + if (r_norefresh->int_val) { return; - if (!r_worldentity.model) + } + if (!r_worldentity.renderer.model) { Sys_Error ("R_RenderView: NULL worldmodel"); + } gl_mirror = false; @@ -892,7 +897,7 @@ R_RenderViewFishEye (void) void gl_R_ClearState (void) { - r_worldentity.model = 0; + r_worldentity.renderer.model = 0; R_ClearEfrags (); R_ClearDlights (); gl_R_ClearParticles (); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 5c61fd70d..d9a1c6797 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -191,7 +191,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) d_lightstylevalue[i] = 264; // normal light value memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.model = worldmodel; + r_worldentity.renderer.model = worldmodel; brush = &worldmodel->brush; R_FreeAllEntities (); @@ -230,7 +230,8 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) continue; if (*models[i]->path == '*') continue; - if (models[i] != r_worldentity.model && models[i]->type == mod_brush) + if (models[i] != r_worldentity.renderer.model + && models[i]->type == mod_brush) register_textures (&models[i]->brush); } } diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index acd9f4ad3..b954fc066 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -45,6 +45,7 @@ #include #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" #include "QF/GL/defines.h" @@ -530,11 +531,14 @@ gl_R_DrawBrushModel (entity_t *e) qboolean rotated; vec3_t mins, maxs; mod_brush_t *brush; + mat4f_t worldMatrix; - model = e->model; + model = e->renderer.model; brush = &model->brush; - if (e->transform[0] != 1 || e->transform[5] != 1 || e->transform[10] != 1) { + Transform_GetWorldMatrix (e->transform, worldMatrix); + if (worldMatrix[0][0] != 1 || worldMatrix[1][1] != 1 + || worldMatrix[2][2] != 1) { rotated = true; radius = model->radius; #if 0 //QSG FIXME @@ -559,12 +563,11 @@ gl_R_DrawBrushModel (entity_t *e) VectorSubtract (r_refdef.vieworg, e->origin, modelorg); if (rotated) { - vec3_t temp; + vec4f_t temp = { modelorg[0], modelorg[1], modelorg[2], 0 }; - VectorCopy (modelorg, temp); - modelorg[0] = DotProduct (temp, e->transform + 0); - modelorg[1] = DotProduct (temp, e->transform + 4); - modelorg[2] = DotProduct (temp, e->transform + 8); + modelorg[0] = dotf (temp, worldMatrix[0])[0]; + modelorg[1] = dotf (temp, worldMatrix[1])[0]; + modelorg[2] = dotf (temp, worldMatrix[2])[0]; } // calculate dynamic lighting for bmodel if it's not an instanced model @@ -584,7 +587,7 @@ gl_R_DrawBrushModel (entity_t *e) qfglPushMatrix (); gl_R_RotateForEntity (e); - qfglGetFloatv (GL_MODELVIEW_MATRIX, e->full_transform); + qfglGetFloatv (GL_MODELVIEW_MATRIX, e->renderer.full_transform); qfglPopMatrix (); psurf = &brush->surfaces[brush->firstmodelsurface]; @@ -599,7 +602,8 @@ gl_R_DrawBrushModel (entity_t *e) // draw the polygon if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (brush, psurf, e->full_transform, e->colormod); + chain_surface (brush, psurf, e->renderer.full_transform, + e->renderer.colormod); } } } @@ -717,7 +721,7 @@ gl_R_DrawWorld (void) entity_t worldent; memset (&worldent, 0, sizeof (worldent)); - worldent.model = r_worldentity.model; + worldent.renderer.model = r_worldentity.renderer.model; VectorCopy (r_refdef.vieworg, modelorg); @@ -729,12 +733,13 @@ gl_R_DrawWorld (void) gl_R_DrawSky (); } - R_VisitWorldNodes (&r_worldentity.model->brush); + R_VisitWorldNodes (&r_worldentity.renderer.model->brush); if (r_drawentities->int_val) { entity_t *ent; for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->model->type != mod_brush) + if (ent->renderer.model->type != mod_brush) { continue; + } currententity = ent; gl_R_DrawBrushModel (currententity); diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 3cbf4f89d..e0c29cfe4 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -43,6 +43,7 @@ #include #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" @@ -111,7 +112,7 @@ static struct { {"fog", 1}, }; -static mat4_t alias_vp; +static mat4f_t alias_vp; void glsl_R_InitAlias (void) @@ -159,8 +160,9 @@ calc_lighting (entity_t *ent, float *ambient, float *shadelight, int light; VectorSet ( -1, 0, 0, lightvec); //FIXME - light = R_LightPoint (&r_worldentity.model->brush, ent->origin); - *ambient = max (light, max (ent->model->min_light, ent->min_light) * 128); + light = R_LightPoint (&r_worldentity.renderer.model->brush, ent->origin); + *ambient = max (light, max (ent->renderer.model->min_light, + ent->renderer.min_light) * 128); *shadelight = *ambient; for (i = 0; i < r_maxdlights; i++) { @@ -228,50 +230,52 @@ glsl_R_DrawAlias (void) float skin_size[2]; float blend; entity_t *ent = currententity; - model_t *model = ent->model; + model_t *model = ent->renderer.model; aliashdr_t *hdr; vec_t norm_mat[9]; - mat4_t mvp_mat; int skin_tex; int colormap; aliasvrt_t *pose1 = 0; // VBO's are null based aliasvrt_t *pose2 = 0; // VBO's are null based + mat4f_t worldMatrix; if (!(hdr = model->aliashdr)) hdr = Cache_Get (&model->cache); calc_lighting (ent, &ambient, &shadelight, lightvec); + Transform_GetWorldMatrix (ent->transform, worldMatrix); // we need only the rotation for normals. - VectorCopy (ent->transform + 0, norm_mat + 0); - VectorCopy (ent->transform + 4, norm_mat + 3); - VectorCopy (ent->transform + 8, norm_mat + 6); + VectorCopy (worldMatrix[0], norm_mat + 0); + VectorCopy (worldMatrix[1], norm_mat + 3); + VectorCopy (worldMatrix[2], norm_mat + 6); // ent model scaling and offset - Mat4Zero (mvp_mat); - mvp_mat[0] = hdr->mdl.scale[0]; - mvp_mat[5] = hdr->mdl.scale[1]; - mvp_mat[10] = hdr->mdl.scale[2]; - mvp_mat[15] = 1; - VectorCopy (hdr->mdl.scale_origin, mvp_mat + 12); - Mat4Mult (ent->transform, mvp_mat, mvp_mat); - Mat4Mult (alias_vp, mvp_mat, mvp_mat); + mat4f_t mvp_mat = { + { hdr->mdl.scale[0], 0, 0, 0 }, + { 0, hdr->mdl.scale[1], 0, 0 }, + { 0, 0, hdr->mdl.scale[2], 0 }, + { hdr->mdl.scale_origin[0], hdr->mdl.scale_origin[1], + hdr->mdl.scale_origin[2], 1 }, + }; + mmulf (mvp_mat, worldMatrix, mvp_mat); + mmulf (mvp_mat, alias_vp, mvp_mat); colormap = glsl_colormap; - if (ent->skin && ent->skin->auxtex) - colormap = ent->skin->auxtex; - if (ent->skin && ent->skin->texnum) { - skin_t *skin = ent->skin; + if (ent->renderer.skin && ent->renderer.skin->auxtex) + colormap = ent->renderer.skin->auxtex; + if (ent->renderer.skin && ent->renderer.skin->texnum) { + skin_t *skin = ent->renderer.skin; skin_tex = skin->texnum; } else { maliasskindesc_t *skindesc; - skindesc = R_AliasGetSkindesc (ent->skinnum, hdr); + skindesc = R_AliasGetSkindesc (ent->renderer.skinnum, hdr); skin_tex = skindesc->texnum; } blend = R_AliasGetLerpedFrames (ent, hdr); - pose1 += ent->pose1 * hdr->poseverts; - pose2 += ent->pose2 * hdr->poseverts; + pose1 += ent->animation.pose1 * hdr->poseverts; + pose2 += ent->animation.pose2 * hdr->poseverts; skin_size[0] = hdr->mdl.skinwidth; skin_size[1] = hdr->mdl.skinheight; @@ -293,7 +297,8 @@ glsl_R_DrawAlias (void) qfeglUniform1f (quake_mdl.shadelight.location, shadelight); qfeglUniform3fv (quake_mdl.lightvec.location, 1, lightvec); qfeglUniform2fv (quake_mdl.skin_size.location, 1, skin_size); - qfeglUniformMatrix4fv (quake_mdl.mvp_matrix.location, 1, false, mvp_mat); + qfeglUniformMatrix4fv (quake_mdl.mvp_matrix.location, 1, false, + &mvp_mat[0][0]); qfeglUniformMatrix3fv (quake_mdl.norm_matrix.location, 1, false, norm_mat); #ifndef TETRAHEDRON @@ -321,7 +326,7 @@ glsl_R_AliasBegin (void) quat_t fog; // pre-multiply the view and projection matricies - Mat4Mult (glsl_projection, glsl_view, alias_vp); + mmulf (alias_vp, glsl_projection, glsl_view); qfeglUseProgram (quake_mdl.program); qfeglEnableVertexAttribArray (quake_mdl.vertexa.location); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 3b5ed0cd4..3fc716cf8 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -46,6 +46,7 @@ #include "QF/cvar.h" #include "QF/dstring.h" +#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/sys.h" @@ -94,7 +95,7 @@ static instsurf_t **instsurfs_tail = &instsurfs; static instsurf_t *free_instsurfs; static GLuint bsp_vbo; -static mat4_t bsp_vp; +static mat4f_t bsp_vp; static GLuint skybox_tex; static qboolean skybox_loaded; @@ -430,9 +431,9 @@ glsl_R_RegisterTextures (model_t **models, int num_models) mod_brush_t *brush; glsl_R_ClearTextures (); - glsl_R_InitSurfaceChains (&r_worldentity.model->brush); + glsl_R_InitSurfaceChains (&r_worldentity.renderer.model->brush); glsl_R_AddTexture (r_notexture_mip); - register_textures (&r_worldentity.model->brush); + register_textures (&r_worldentity.renderer.model->brush); for (i = 0; i < num_models; i++) { m = models[i]; if (!m) @@ -441,7 +442,7 @@ glsl_R_RegisterTextures (model_t **models, int num_models) if (*m->path == '*') continue; // world has already been done, not interested in non-brush models - if (m == r_worldentity.model || m->type != mod_brush) + if (m == r_worldentity.renderer.model || m->type != mod_brush) continue; brush = &m->brush; brush->numsubmodels = 1; // no support for submodels in non-world model @@ -486,7 +487,7 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, if (fa->ec_index < 0) { brush = &models[-fa->ec_index - 1]->brush; } else { - brush = &r_worldentity.model->brush; + brush = &r_worldentity.renderer.model->brush; } vertices = brush->vertexes; edges = brush->edges; @@ -585,7 +586,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) } surf = brush->surfaces + j; surf->ec_index = dm - brush->submodels; - if (!surf->ec_index && m != r_worldentity.model) + if (!surf->ec_index && m != r_worldentity.renderer.model) surf->ec_index = -1 - i; // instanced model tex = surf->texinfo->texture->render; CHAIN_SURF_F2B (surf, tex->tex_chain); @@ -662,9 +663,12 @@ R_DrawBrushModel (entity_t *e) vec3_t mins, maxs, org; mod_brush_t *brush; - model = e->model; + model = e->renderer.model; brush = &model->brush; - if (e->transform[0] != 1 || e->transform[5] != 1 || e->transform[10] != 1) { + mat4f_t mat; + Transform_GetWorldMatrix (e->transform, mat); + memcpy (e->renderer.full_transform, mat, sizeof (mat));//FIXME + if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; if (R_CullSphere (e->origin, radius)) @@ -679,12 +683,11 @@ R_DrawBrushModel (entity_t *e) VectorSubtract (r_refdef.vieworg, e->origin, org); if (rotated) { - vec3_t temp; + vec4f_t temp = { org[0], org[1], org[2], 0 }; - VectorCopy (org, temp); - org[0] = DotProduct (temp, e->transform + 0); - org[1] = DotProduct (temp, e->transform + 4); - org[2] = DotProduct (temp, e->transform + 8); + org[0] = dotf (temp, mat[0])[0]; + org[1] = dotf (temp, mat[1])[0]; + org[2] = dotf (temp, mat[2])[0]; } // calculate dynamic lighting for bmodel if it's not an instanced model @@ -713,7 +716,8 @@ R_DrawBrushModel (entity_t *e) // enqueue the polygon if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (brush, surf, e->transform, e->colormod); + chain_surface (brush, surf, e->renderer.full_transform, + e->renderer.colormod); } } } @@ -842,10 +846,10 @@ draw_elechain (elechain_t *ec, int matloc, int vertloc, int tlstloc, } } if (ec->transform) { - Mat4Mult (bsp_vp, ec->transform, mat); + Mat4Mult (&bsp_vp[0][0], ec->transform, mat);//FIXME qfeglUniformMatrix4fv (matloc, 1, false, mat); } else { - qfeglUniformMatrix4fv (matloc, 1, false, bsp_vp); + qfeglUniformMatrix4fv (matloc, 1, false, &bsp_vp[0][0]); } for (el = ec->elements; el; el = el->next) { if (!el->list->size) @@ -873,7 +877,7 @@ bsp_begin (void) QuatCopy (default_color, last_color); qfeglVertexAttrib4fv (quake_bsp.color.location, default_color); - Mat4Mult (glsl_projection, glsl_view, bsp_vp); + mmulf (bsp_vp, glsl_projection, glsl_view); qfeglUseProgram (quake_bsp.program); qfeglEnableVertexAttribArray (quake_bsp.vertex.location); @@ -928,7 +932,7 @@ turb_begin (void) QuatCopy (default_color, last_color); qfeglVertexAttrib4fv (quake_bsp.color.location, default_color); - Mat4Mult (glsl_projection, glsl_view, bsp_vp); + mmulf (bsp_vp, glsl_projection, glsl_view); qfeglUseProgram (quake_turb.program); qfeglEnableVertexAttribArray (quake_turb.vertex.location); @@ -1001,7 +1005,7 @@ sky_begin (void) QuatCopy (default_color, last_color); qfeglVertexAttrib4fv (quake_bsp.color.location, default_color); - Mat4Mult (glsl_projection, glsl_view, bsp_vp); + mmulf (bsp_vp, glsl_projection, glsl_view); if (skybox_loaded) { sky_params.mvp_matrix = &quake_skybox.mvp_matrix; @@ -1127,15 +1131,15 @@ glsl_R_DrawWorld (void) clear_texture_chains (); // do this first for water and skys memset (&worldent, 0, sizeof (worldent)); - worldent.model = r_worldentity.model; + worldent.renderer.model = r_worldentity.renderer.model; currententity = &worldent; - R_VisitWorldNodes (&worldent.model->brush); + R_VisitWorldNodes (&worldent.renderer.model->brush); if (r_drawentities->int_val) { entity_t *ent; for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->model->type != mod_brush) + if (ent->renderer.model->type != mod_brush) continue; currententity = ent; diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index ce2c2f31d..76a9ae85e 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -43,6 +43,7 @@ #include #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" @@ -137,7 +138,7 @@ static struct va_attr_s { {&iqm_shader.vcolor, 4, GL_UNSIGNED_BYTE, 1}, }; -static mat4_t iqm_vp; +static mat4f_t iqm_vp; void glsl_R_InitIQM (void) @@ -207,28 +208,31 @@ glsl_R_DrawIQM (void) { static quat_t color = { 1, 1, 1, 1}; entity_t *ent = currententity; - model_t *model = ent->model; + model_t *model = ent->renderer.model; iqm_t *iqm = (iqm_t *) model->aliashdr; glsliqm_t *glsl = (glsliqm_t *) iqm->extra_data; dlight_t *lights[MAX_IQM_LIGHTS]; int i; vec_t norm_mat[9]; - mat4_t mvp_mat; + mat4f_t mvp_mat; float blend; iqmframe_t *frame; - R_LightPoint (&r_worldentity.model->brush, ent->origin);//FIXME min_light? + R_LightPoint (&r_worldentity.renderer.model->brush, ent->origin);//FIXME min_light? VectorScale (ambientcolor, 1/255.0, ambientcolor); R_FindNearLights (ent->origin, MAX_IQM_LIGHTS, lights); // we need only the rotation for normals. - VectorCopy (ent->transform + 0, norm_mat + 0); - VectorCopy (ent->transform + 4, norm_mat + 3); - VectorCopy (ent->transform + 8, norm_mat + 6); - Mat4Mult (iqm_vp, ent->transform, mvp_mat); + mat4f_t mat; + Transform_GetWorldMatrix (ent->transform, mat); + VectorCopy (mat[0], norm_mat + 0); + VectorCopy (mat[1], norm_mat + 3); + VectorCopy (mat[2], norm_mat + 6); + mmulf (mvp_mat, iqm_vp, mat); blend = R_IQMGetLerpedFrames (ent, iqm); - frame = R_IQMBlendFrames (iqm, ent->pose1, ent->pose2, blend, 0); + frame = R_IQMBlendFrames (iqm, ent->animation.pose1, ent->animation.pose2, + blend, 0); qfeglUniform3fv (iqm_shader.ambient.location, 1, ambientcolor); for (i = 0; i < MAX_IQM_LIGHTS; i++) { @@ -249,7 +253,8 @@ glsl_R_DrawIQM (void) qfeglBindBuffer (GL_ARRAY_BUFFER, glsl->vertex_array); qfeglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, glsl->element_array); - qfeglUniformMatrix4fv (iqm_shader.mvp_matrix.location, 1, false, mvp_mat); + qfeglUniformMatrix4fv (iqm_shader.mvp_matrix.location, 1, false, + &mvp_mat[0][0]); qfeglUniformMatrix3fv (iqm_shader.norm_matrix.location, 1, false, norm_mat); qfeglUniformMatrix4fv (iqm_shader.bonemats.location, iqm->num_joints, @@ -274,7 +279,7 @@ glsl_R_IQMBegin (void) quat_t fog; // pre-multiply the view and projection matricies - Mat4Mult (glsl_projection, glsl_view, iqm_vp); + mmulf (iqm_vp, glsl_projection, glsl_view); qfeglUseProgram (iqm_shader.program); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 32688b2ae..ba8c2dce7 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -60,15 +60,15 @@ #include "r_internal.h" #include "vid_gl.h" -mat4_t glsl_projection; -mat4_t glsl_view; +mat4f_t glsl_projection; +mat4f_t glsl_view; void glsl_R_ViewChanged (float aspect) { double xmin, xmax, ymin, ymax; float fovx, fovy, neard, fard; - vec_t *proj = glsl_projection; + vec4f_t *proj = glsl_projection; fovx = r_refdef.fov_x; fovy = r_refdef.fov_y; @@ -80,25 +80,30 @@ glsl_R_ViewChanged (float aspect) xmax = neard * tan (fovx * M_PI / 360); // fov_2 / 2 xmin = -xmax; - proj[0] = (2 * neard) / (xmax - xmin); - proj[4] = 0; - proj[8] = (xmax + xmin) / (xmax - xmin); - proj[12] = 0; - - proj[1] = 0; - proj[5] = (2 * neard) / (ymax - ymin); - proj[9] = (ymax + ymin) / (ymax - ymin); - proj[13] = 0; - - proj[2] = 0; - proj[6] = 0; - proj[10] = (fard + neard) / (neard - fard); - proj[14] = (2 * fard * neard) / (neard - fard); - - proj[3] = 0; - proj[7] = 0; - proj[11] = -1; - proj[15] = 0; + proj[0] = (vec4f_t) { + (2 * neard) / (xmax - xmin), + 0, + 0, + 0 + }; + proj[1] = (vec4f_t) { + 0, + (2 * neard) / (ymax - ymin), + 0, + 0 + }; + proj[2] = (vec4f_t) { + (xmax + xmin) / (xmax - xmin), + (ymax + ymin) / (ymax - ymin), + (fard + neard) / (neard - fard), + -1 + }; + proj[3] = (vec4f_t) { + 0, + 0, + (2 * fard * neard) / (neard - fard), + 0 + }; } void @@ -110,22 +115,24 @@ glsl_R_SetupFrame (void) VectorCopy (r_refdef.vieworg, r_origin); AngleVectors (r_refdef.viewangles, vpn, vright, vup); + R_SetFrustum (); - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.model); + r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); } static void R_SetupView (void) { float x, y, w, h; - mat4_t mat; - static mat4_t z_up = { - 0, 0, -1, 0, - -1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 1, + static mat4f_t z_up = { + { 0, 0, -1, 0}, + {-1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 0, 1}, }; + vec4f_t rotation; + vec4f_t offset = { 0, 0, 0, 1 }; x = r_refdef.vrect.x; y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); @@ -133,17 +140,12 @@ R_SetupView (void) h = r_refdef.vrect.height; qfeglViewport (x, y, w, h); - Mat4Zero (mat); - VectorCopy (vpn, mat + 0); - VectorNegate (vright, mat + 4); // we want vleft - VectorCopy (vup, mat + 8); - mat[15] = 1; - Mat4Transpose (mat, mat);//AngleVectors gives the transpose of what we want - Mat4Mult (z_up, mat, glsl_view); - - Mat4Identity (mat); - VectorNegate (r_refdef.vieworg, mat + 12); - Mat4Mult (glsl_view, mat, glsl_view); + AngleQuat (r_refdef.viewangles, &rotation[0]); + rotation = qconjf (rotation); + mat4fquat (glsl_view, rotation); + mmulf (glsl_view, z_up, glsl_view); + VectorNegate (r_refdef.vieworg, offset); + glsl_view[3] = mvmulf (glsl_view, offset); qfeglEnable (GL_CULL_FACE); qfeglEnable (GL_DEPTH_TEST); @@ -161,7 +163,7 @@ R_RenderEntities (void) do { \ begun = 0; \ for (ent = r_ent_queue; ent; ent = ent->next) { \ - if (ent->model->type != mod_##type_name) \ + if (ent->renderer.model->type != mod_##type_name) \ continue; \ if (!begun) { \ glsl_R_##Type##Begin (); \ @@ -186,7 +188,7 @@ R_DrawViewModel (void) if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val || !r_drawentities->int_val - || !currententity->model) + || !currententity->renderer.model) return; // hack the depth range to prevent view model from poking into walls @@ -273,7 +275,7 @@ glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) d_lightstylevalue[i] = 264; // normal light value memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.model = worldmodel; + r_worldentity.renderer.model = worldmodel; // Force a vis update r_viewleaf = NULL; diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 139423bb7..eb7eccb6d 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -313,7 +313,7 @@ glsl_R_ReadPointFile_f (void) vec3_t org; QFile *f; - mapname = strdup (r_worldentity.model->path); + mapname = strdup (r_worldentity.renderer.model->path); if (!mapname) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); @@ -1568,10 +1568,10 @@ draw_qf_particles (void) particle_t *part; vec3_t up_scale, right_scale, up_right_scale, down_right_scale; partvert_t *VA; - mat4_t vp_mat; + mat4f_t vp_mat; quat_t fog; - Mat4Mult (glsl_projection, glsl_view, vp_mat); + mmulf (vp_mat, glsl_projection, glsl_view); qfeglDepthMask (GL_FALSE); qfeglUseProgram (quake_part.program); @@ -1583,7 +1583,8 @@ draw_qf_particles (void) fog[3] = glsl_Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_part.fog.location, 1, fog); - qfeglUniformMatrix4fv (quake_part.mvp_matrix.location, 1, false, vp_mat); + qfeglUniformMatrix4fv (quake_part.mvp_matrix.location, 1, false, + &vp_mat[0][0]); qfeglUniform1i (quake_part.texture.location, 0); qfeglActiveTexture (GL_TEXTURE0 + 0); @@ -1712,10 +1713,10 @@ draw_id_particles (void) float minparticledist; particle_t *part; partvert_t *VA; - mat4_t vp_mat; + mat4f_t vp_mat; quat_t fog; - Mat4Mult (glsl_projection, glsl_view, vp_mat); + mmulf (vp_mat, glsl_projection, glsl_view); // LordHavoc: particles should not affect zbuffer qfeglDepthMask (GL_FALSE); @@ -1723,7 +1724,8 @@ draw_id_particles (void) qfeglEnableVertexAttribArray (quake_point.vertex.location); qfeglEnableVertexAttribArray (quake_point.color.location); - qfeglUniformMatrix4fv (quake_point.mvp_matrix.location, 1, false, vp_mat); + qfeglUniformMatrix4fv (quake_point.mvp_matrix.location, 1, false, + &vp_mat[0][0]); glsl_Fog_GetColor (fog); fog[3] = glsl_Fog_GetDensity () / 64.0; diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index c0acdc078..7582e9db3 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -42,6 +42,7 @@ #endif #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/draw.h" #include "QF/dstring.h" #include "QF/quakefs.h" @@ -131,7 +132,7 @@ static void R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, mspriteframe_t **frame2, float *blend) { - int framenum = currententity->frame; + int framenum = currententity->animation.frame; int pose; int i, numframes; float *intervals; @@ -153,7 +154,7 @@ R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, numframes = group->numframes; fullinterval = intervals[numframes - 1]; - time = vr_data.realtime + currententity->syncbase; + time = vr_data.realtime + currententity->animation.syncbase; targettime = time - ((int) (time / fullinterval)) * fullinterval; for (i = 0; i < numframes - 1; i++) { @@ -170,17 +171,17 @@ R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, //group frames. *blend = R_EntityBlend (ent, pose, frame_interval); if (group) { - *frame1 = group->frames[ent->pose1]; - *frame2 = group->frames[ent->pose2]; + *frame1 = group->frames[ent->animation.pose1]; + *frame2 = group->frames[ent->animation.pose2]; } else { - *frame1 = sprite->frames[ent->pose1].frameptr; - *frame2 = sprite->frames[ent->pose2].frameptr; + *frame1 = sprite->frames[ent->animation.pose1].frameptr; + *frame2 = sprite->frames[ent->animation.pose2].frameptr; } } static void -make_quad (mspriteframe_t *frame, const vec3_t vpn, const vec3_t vright, - const vec3_t vup, float verts[6][3]) +make_quad (mspriteframe_t *frame, vec4f_t vpn, vec4f_t vright, + vec4f_t vup, float verts[6][3]) { vec3_t left, up, right, down; vec3_t ul, ur, ll, lr; @@ -209,11 +210,11 @@ void R_DrawSprite (void) { entity_t *ent = currententity; - msprite_t *sprite = (msprite_t *) ent->model->cache.data; + msprite_t *sprite = (msprite_t *) ent->renderer.model->cache.data; mspriteframe_t *frame1, *frame2; float blend, sr, cr, dot, angle; vec3_t tvec; - vec3_t svpn, svright, svup; + vec4f_t svpn = {}, svright = {}, svup = {}; static quat_t color = { 1, 1, 1, 1}; float vertsa[6][3], vertsb[6][3]; static float uvab[6][4] = { @@ -242,7 +243,7 @@ R_DrawSprite (void) VectorSet (0, 0, 1, svup); // CrossProduct (svup, -r_origin, svright) VectorSet (tvec[1], -tvec[0], 0, svright); - VectorNormalize (svright); + svright /= vsqrtf (dotf (svright, svright)); // CrossProduct (svright, svup, svpn); VectorSet (-svright[1], svright[0], 0, svpn); break; @@ -267,16 +268,16 @@ R_DrawSprite (void) VectorSet (0, 0, 1, svup); // CrossProduct (svup, -r_origin, svright) VectorSet (vpn[1], -vpn[0], 0, svright); - VectorNormalize (svright); + svright /= vsqrtf (dotf (svright, svright)); // CrossProduct (svright, svup, svpn); VectorSet (-svright[1], svright[0], 0, svpn); break; case SPR_ORIENTED: // generate the prite's axes according to the sprite's world // orientation - VectorCopy (currententity->transform + 0, svpn); - VectorNegate (currententity->transform + 4, svright); - VectorCopy (currententity->transform + 8, svup); + svup = Transform_Up (currententity->transform); + svright = Transform_Right (currententity->transform); + svpn = Transform_Forward (currententity->transform); break; case SPR_VP_PARALLEL_ORIENTED: // generate the sprite's axes parallel to the viewplane, but @@ -324,7 +325,7 @@ R_DrawSprite (void) void R_SpriteBegin (void) { - mat4_t mat; + mat4f_t mat; quat_t fog; qfeglUseProgram (quake_sprite.program); @@ -352,8 +353,8 @@ R_SpriteBegin (void) qfeglEnable (GL_TEXTURE_2D); qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); - Mat4Mult (glsl_projection, glsl_view, mat); - qfeglUniformMatrix4fv (quake_sprite.matrix.location, 1, false, mat); + mmulf (mat, glsl_projection, glsl_view); + qfeglUniformMatrix4fv (quake_sprite.matrix.location, 1, false, &mat[0][0]); } void diff --git a/libs/video/renderer/r_alias.c b/libs/video/renderer/r_alias.c index aa1541ca2..b956f0500 100644 --- a/libs/video/renderer/r_alias.c +++ b/libs/video/renderer/r_alias.c @@ -63,7 +63,7 @@ R_AliasGetSkindesc (int skinnum, aliashdr_t *ahdr) numskins = paliasskingroup->numskins; fullskininterval = pskinintervals[numskins - 1]; - skintime = vr_data.realtime + currententity->syncbase; + skintime = vr_data.realtime + currententity->animation.syncbase; // when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval // values are positive, so we don't have to worry about division by 0 @@ -118,7 +118,7 @@ alias_get_frame (int framenum, aliashdr_t *hdr, float *frame_interval) numframes = group->numframes; fullinterval = intervals[numframes - 1]; - time = vr_data.realtime + currententity->syncbase; + time = vr_data.realtime + currententity->animation.syncbase; // when loading in Mod_LoadAliasGroup, we guaranteed all interval values // are positive, so we don't have to worry about division by 0 @@ -148,6 +148,6 @@ R_AliasGetLerpedFrames (entity_t *ent, aliashdr_t *hdr) maliasframedesc_t *frame; float interval; - frame = alias_get_frame (ent->frame, hdr, &interval); + frame = alias_get_frame (ent->animation.frame, hdr, &interval); return R_EntityBlend (ent, frame->firstpose, interval); } diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 47b78a643..03af6696b 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -54,7 +54,7 @@ R_MarkLeaves (void) mleaf_t *leaf; mnode_t *node; msurface_t **mark; - mod_brush_t *brush = &r_worldentity.model->brush; + mod_brush_t *brush = &r_worldentity.renderer.model->brush; if (r_oldviewleaf == r_viewleaf && !r_novis->int_val) return; @@ -70,7 +70,7 @@ R_MarkLeaves (void) vis = solid; memset (solid, 0xff, (brush->numleafs + 7) >> 3); } else - vis = Mod_LeafPVS (r_viewleaf, r_worldentity.model); + vis = Mod_LeafPVS (r_viewleaf, r_worldentity.renderer.model); for (i = 0; (int) i < brush->numleafs; i++) { if (vis[i >> 3] & (1 << (i & 7))) { @@ -105,7 +105,7 @@ R_TextureAnimation (msurface_t *surf) texture_t *base = surf->texinfo->texture; int count, relative; - if (currententity->frame) { + if (currententity->animation.frame) { if (base->alternate_anims) base = base->alternate_anims; } diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index cbfd0d2c8..86d494b6d 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -101,7 +101,7 @@ R_RemoveEfrags (entity_t *ent) { efrag_t *ef, *old, *walk, **prev; - ef = ent->efrag; + ef = ent->visibility.efrag; while (ef) { prev = &ef->leaf->efrags; @@ -124,7 +124,7 @@ R_RemoveEfrags (entity_t *ent) r_free_efrags = old; } - ent->efrag = 0; + ent->visibility.efrag = 0; } static void @@ -143,15 +143,15 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, node_stack = alloca ((brush->depth + 2) * sizeof (mnode_t *)); node_ptr = node_stack; - lastlink = &ent->efrag; + lastlink = &ent->visibility.efrag; *node_ptr++ = 0; while (node) { // add an efrag if the node is a leaf if (__builtin_expect (node->contents < 0, 0)) { - if (!ent->topnode) { - ent->topnode = node; + if (!ent->visibility.topnode) { + ent->visibility.topnode = node; } leaf = (mleaf_t *) node; @@ -177,8 +177,8 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, if (sides == 3) { // split on this plane // if this is the first splitter of this bmodel, remember it - if (!ent->topnode) { - ent->topnode = node; + if (!ent->visibility.topnode) { + ent->visibility.topnode = node; } } // recurse down the contacted sides @@ -202,18 +202,18 @@ R_AddEfrags (mod_brush_t *brush, entity_t *ent) model_t *entmodel; vec3_t emins, emaxs; - if (!ent->model || !r_worldentity.model) + if (!ent->renderer.model || !r_worldentity.renderer.model) return; if (ent == &r_worldentity) return; // never add the world - entmodel = ent->model; + entmodel = ent->renderer.model; VectorAdd (ent->origin, entmodel->mins, emins); VectorAdd (ent->origin, entmodel->maxs, emaxs); - ent->topnode = 0; + ent->visibility.topnode = 0; R_SplitEntityOnNode (brush, ent, emins, emaxs); } @@ -225,17 +225,17 @@ R_StoreEfrags (const efrag_t *efrag) while (efrag) { ent = efrag->entity; - model = ent->model; + model = ent->renderer.model; switch (model->type) { case mod_alias: case mod_brush: case mod_sprite: case mod_iqm: - if (ent->visframe != r_framecount) { + if (ent->visibility.visframe != r_framecount) { R_EnqueueEntity (ent); // mark that we've recorded this entity for this frame - ent->visframe = r_framecount; + ent->visibility.visframe = r_framecount; } efrag = efrag->leafnext; break; diff --git a/libs/video/renderer/r_ent.c b/libs/video/renderer/r_ent.c index e72d10399..5a20bcb1f 100644 --- a/libs/video/renderer/r_ent.c +++ b/libs/video/renderer/r_ent.c @@ -38,6 +38,7 @@ #include #include +#include "QF/entity.h" #include "QF/model.h" #include "QF/msg.h" #include "QF/render.h" @@ -70,6 +71,7 @@ R_AllocEntity (void) if ((ent = free_entities)) { free_entities = ent->next; ent->next = 0; + ent->transform = 0; return ent; } @@ -78,9 +80,12 @@ R_AllocEntity (void) *entpool_tail = pool; entpool_tail = &pool->next; - for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) + for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) { ent->next = ent + 1; + ent->transform = 0; + } ent->next = 0; + ent->transform = 0; free_entities = pool->entities; return R_AllocEntity (); @@ -94,9 +99,18 @@ R_FreeAllEntities (void) int i; for (pool = entity_pools; pool; pool = pool->next) { - for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) + for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) { ent->next = ent + 1; + if (ent->transform) { + Transform_Delete (ent->transform); + ent->transform = 0; + } + } ent->next = pool->next ? pool->next->entities : 0; + if (ent->transform) { + Transform_Delete (ent->transform); + ent->transform = 0; + } } free_entities = entity_pools ? entity_pools->entities : 0; } @@ -121,27 +135,27 @@ R_EntityBlend (entity_t *ent, int pose, float interval) { float blend; - if (ent->pose_model != ent->model) { - ent->pose_model = ent->model; - ent->pose1 = pose; - ent->pose2 = pose; + if (ent->animation.nolerp) { + ent->animation.nolerp = 0; + ent->animation.pose1 = pose; + ent->animation.pose2 = pose; return 0.0; } - ent->frame_interval = interval; - if (ent->pose2 != pose) { - ent->frame_start_time = vr_data.realtime; - if (ent->pose2 == -1) { - ent->pose1 = pose; + ent->animation.frame_interval = interval; + if (ent->animation.pose2 != pose) { + ent->animation.frame_start_time = vr_data.realtime; + if (ent->animation.pose2 == -1) { + ent->animation.pose1 = pose; } else { - ent->pose1 = ent->pose2; + ent->animation.pose1 = ent->animation.pose2; } - ent->pose2 = pose; + ent->animation.pose2 = pose; blend = 0.0; } else if (vr_data.paused) { blend = 1.0; } else { - blend = (vr_data.realtime - ent->frame_start_time) - / ent->frame_interval; + blend = (vr_data.realtime - ent->animation.frame_start_time) + / ent->animation.frame_interval; blend = min (blend, 1.0); } return blend; diff --git a/libs/video/renderer/r_iqm.c b/libs/video/renderer/r_iqm.c index 224182a79..71dc47b3a 100644 --- a/libs/video/renderer/r_iqm.c +++ b/libs/video/renderer/r_iqm.c @@ -49,7 +49,7 @@ float R_IQMGetLerpedFrames (entity_t *ent, iqm_t *iqm) { - int frame = ent->frame; + int frame = ent->animation.frame; float time, fullinterval; iqmanim *anim; @@ -62,7 +62,7 @@ R_IQMGetLerpedFrames (entity_t *ent, iqm_t *iqm) } anim = &iqm->anims[frame]; fullinterval = anim->num_frames / anim->framerate; - time = vr_data.realtime + currententity->syncbase; + time = vr_data.realtime + currententity->animation.syncbase; time -= ((int) (time / fullinterval)) * fullinterval; frame = (int) (time * anim->framerate) + anim->first_frame; return R_EntityBlend (ent, frame, 1.0 / anim->framerate); diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 8d3294c37..96899621e 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -328,7 +328,7 @@ R_PushDlights (const vec3_t entorigin) if (l->die < vr_data.realtime || !l->radius) continue; VectorSubtract (l->origin, entorigin, lightorigin); - R_MarkLights (lightorigin, l, i, r_worldentity.model); + R_MarkLights (lightorigin, l, i, r_worldentity.renderer.model); } } diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index d28e41b04..1fcd1ce12 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -30,6 +30,7 @@ #include +#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" @@ -94,8 +95,8 @@ R_AliasCheckBBox (void) int minz; // expand, rotate, and translate points into worldspace - currententity->trivial_accept = 0; - pmodel = currententity->model; + currententity->visibility.trivial_accept = 0; + pmodel = currententity->renderer.model; if (!(pahdr = pmodel->aliashdr)) pahdr = Cache_Get (&pmodel->cache); pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model); @@ -103,7 +104,7 @@ R_AliasCheckBBox (void) R_AliasSetUpTransform (0); // construct the base bounding box for this frame - frame = currententity->frame; + frame = currententity->animation.frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->path); @@ -218,11 +219,11 @@ R_AliasCheckBBox (void) return false; // trivial reject off one side } - currententity->trivial_accept = !anyclip & !zclipped; + currententity->visibility.trivial_accept = !anyclip & !zclipped; - if (currententity->trivial_accept) { + if (currententity->visibility.trivial_accept) { if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) { - currententity->trivial_accept |= 2; + currententity->visibility.trivial_accept |= 2; } } @@ -355,10 +356,12 @@ R_AliasSetUpTransform (int trivial_accept) float rotationmatrix[3][4], t2matrix[3][4]; static float tmatrix[3][4]; static float viewmatrix[3][4]; + mat4f_t mat; - VectorCopy (currententity->transform + 0, alias_forward); - VectorNegate (currententity->transform + 4, alias_right); - VectorCopy (currententity->transform + 8, alias_up); + Transform_GetWorldMatrix (currententity->transform, mat); + VectorCopy (mat[0], alias_forward); + VectorNegate (mat[1], alias_right); + VectorCopy (mat[2], alias_up); tmatrix[0][0] = pmdl->scale[0]; tmatrix[1][1] = pmdl->scale[1]; @@ -542,7 +545,7 @@ R_AliasSetupSkin (void) { int skinnum; - skinnum = currententity->skinnum; + skinnum = currententity->renderer.skinnum; if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { Sys_MaskPrintf (SYS_DEV, "R_AliasSetupSkin: no such skin # %d\n", skinnum); @@ -559,16 +562,16 @@ R_AliasSetupSkin (void) r_affinetridesc.skinheight = pmdl->skinheight; acolormap = vid.colormap8; - if (currententity->skin) { + if (currententity->renderer.skin) { tex_t *base; - base = currententity->skin->texels; + base = currententity->renderer.skin->texels; if (base) { r_affinetridesc.pskin = base->data; r_affinetridesc.skinwidth = base->width; r_affinetridesc.skinheight = base->height; } - acolormap = currententity->skin->colormap; + acolormap = currententity->renderer.skin->colormap; } } @@ -611,7 +614,7 @@ R_AliasSetupFrame (void) { maliasframedesc_t *frame; - frame = R_AliasGetFramedesc (currententity->frame, paliashdr); + frame = R_AliasGetFramedesc (currententity->animation.frame, paliashdr); r_apverts = (trivertx_t *) ((byte *) paliashdr + frame->frame); } @@ -624,8 +627,8 @@ R_AliasDrawModel (alight_t *plighting) r_amodels_drawn++; - if (!(paliashdr = currententity->model->aliashdr)) - paliashdr = Cache_Get (¤tentity->model->cache); + if (!(paliashdr = currententity->renderer.model->aliashdr)) + paliashdr = Cache_Get (¤tentity->renderer.model->cache); pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model); size = (CACHE_SIZE - 1) @@ -641,12 +644,12 @@ R_AliasDrawModel (alight_t *plighting) pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1]; R_AliasSetupSkin (); - R_AliasSetUpTransform (currententity->trivial_accept); + R_AliasSetUpTransform (currententity->visibility.trivial_accept); R_AliasSetupLighting (plighting); R_AliasSetupFrame (); - r_affinetridesc.drawtype = (currententity->trivial_accept == 3) && - r_recursiveaffinetriangles; + r_affinetridesc.drawtype = ((currententity->visibility.trivial_accept == 3) + && r_recursiveaffinetriangles); if (!acolormap) acolormap = vid.colormap8; @@ -664,11 +667,14 @@ R_AliasDrawModel (alight_t *plighting) else ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - if (currententity->trivial_accept && pmdl->ident != HEADER_MDL16) + if (currententity->visibility.trivial_accept + && pmdl->ident != HEADER_MDL16) { R_AliasPrepareUnclippedPoints (); - else + } else { R_AliasPreparePoints (); + } - if (!currententity->model->aliashdr) - Cache_Release (¤tentity->model->cache); + if (!currententity->renderer.model->aliashdr) { + Cache_Release (¤tentity->renderer.model->cache); + } } diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 7cf001b87..e9b3fde8a 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -33,6 +33,7 @@ #include "qfalloca.h" +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" @@ -77,9 +78,11 @@ R_EntityRotate (vec3_t vec) void R_RotateBmodel (void) { - VectorCopy (currententity->transform + 0, entity_rotation[0]); - VectorCopy (currententity->transform + 4, entity_rotation[1]); - VectorCopy (currententity->transform + 8, entity_rotation[2]); + mat4f_t mat; + Transform_GetWorldMatrix (currententity->transform, mat); + VectorCopy (mat[0], entity_rotation[0]); + VectorCopy (mat[1], entity_rotation[1]); + VectorCopy (mat[2], entity_rotation[2]); // rotate modelorg and the transformation matrix R_EntityRotate (modelorg); @@ -297,7 +300,8 @@ R_DrawSolidClippedSubmodelPolygons (model_t *model) pbedge[j - 1].pnext = NULL; // mark end of edges - R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf); + R_RecursiveClipBPoly (pbedge, + currententity->visibility.topnode, psurf); } else { Sys_Error ("no edges in bmodel"); } @@ -330,7 +334,7 @@ R_DrawSubmodelPolygons (model_t *model, int clipflags) // draw the polygon if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - r_currentkey = ((mleaf_t *) currententity->topnode)->key; + r_currentkey = ((mleaf_t *) currententity->visibility.topnode)->key; // FIXME: use bounding-box-based frustum clipping info? R_RenderFace (psurf, clipflags); @@ -511,7 +515,7 @@ R_RenderWorld (void) currententity = &r_worldentity; VectorCopy (r_origin, modelorg); - brush = ¤tentity->model->brush; + brush = ¤tentity->renderer.model->brush; r_pcurrentvertbase = brush->vertexes; R_VisitWorldNodes (brush, 15); diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index 3f460643d..67c298187 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -353,7 +353,7 @@ R_RenderFace (msurface_t *fa, int clipflags) vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; - mod_brush_t *brush = ¤tentity->model->brush; + mod_brush_t *brush = ¤tentity->renderer.model->brush; // skip out if no more surfs if ((surface_p) >= surf_max) { @@ -624,7 +624,7 @@ R_RenderPoly (msurface_t *fa, int clipflags) polyvert_t pverts[100]; // FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; qboolean visible; - mod_brush_t *brush = ¤tentity->model->brush; + mod_brush_t *brush = ¤tentity->renderer.model->brush; // FIXME: clean this up and make it faster // FIXME: guard against running out of vertices diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index 285342b3f..8674e3ca6 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -40,6 +40,7 @@ #include #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" @@ -231,9 +232,12 @@ R_IQMSetupLighting (entity_t *ent, alight_t *plighting) r_shadelight *= VID_GRADES; // rotate the lighting vector into the model's frame of reference - r_plightvec[0] = DotProduct (plighting->plightvec, ent->transform + 0); - r_plightvec[1] = DotProduct (plighting->plightvec, ent->transform + 4); - r_plightvec[2] = DotProduct (plighting->plightvec, ent->transform + 8); + mat4f_t mat; + Transform_GetWorldMatrix (ent->transform, mat); + //FIXME vectorize + r_plightvec[0] = DotProduct (plighting->plightvec, mat[0]); + r_plightvec[1] = DotProduct (plighting->plightvec, mat[1]); + r_plightvec[2] = DotProduct (plighting->plightvec, mat[2]); } static void @@ -244,9 +248,11 @@ R_IQMSetUpTransform (int trivial_accept) static float viewmatrix[3][4]; vec3_t forward, left, up; - VectorCopy (currententity->transform + 0, forward); - VectorCopy (currententity->transform + 4, left); - VectorCopy (currententity->transform + 8, up); + mat4f_t mat; + Transform_GetWorldMatrix (currententity->transform, mat); + VectorCopy (mat[0], forward); + VectorCopy (mat[1], left); + VectorCopy (mat[2], up); // TODO: can do this with simple matrix rearrangement @@ -293,7 +299,7 @@ void R_IQMDrawModel (alight_t *plighting) { entity_t *ent = currententity; - model_t *model = ent->model; + model_t *model = ent->renderer.model; iqm_t *iqm = (iqm_t *) model->aliashdr; swiqm_t *sw = (swiqm_t *) iqm->extra_data; int size; @@ -304,18 +310,19 @@ R_IQMDrawModel (alight_t *plighting) + sizeof (finalvert_t) * (iqm->num_verts + 1) + sizeof (auxvert_t) * iqm->num_verts; blend = R_IQMGetLerpedFrames (ent, iqm); - frame = R_IQMBlendPalette (iqm, ent->pose1, ent->pose2, blend, size, - sw->blend_palette, sw->palette_size); + frame = R_IQMBlendPalette (iqm, ent->animation.pose1, ent->animation.pose2, + blend, size, sw->blend_palette, + sw->palette_size); pfinalverts = (finalvert_t *) &frame[sw->palette_size]; pfinalverts = (finalvert_t *) (((intptr_t) &pfinalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); pauxverts = (auxvert_t *) &pfinalverts[iqm->num_verts + 1]; - R_IQMSetUpTransform (ent->trivial_accept); + R_IQMSetUpTransform (ent->visibility.trivial_accept); R_IQMSetupLighting (ent, plighting); - r_affinetridesc.drawtype = (ent->trivial_accept == 3) && + r_affinetridesc.drawtype = (ent->visibility.trivial_accept == 3) && r_recursiveaffinetriangles; //if (!acolormap) @@ -326,7 +333,7 @@ R_IQMDrawModel (alight_t *plighting) else ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - if (ent->trivial_accept) + if (ent->visibility.trivial_accept) R_IQMPrepareUnclippedPoints (iqm, sw, frame); else R_IQMPreparePoints (iqm, sw, frame); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 573827bda..7cf5416c0 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -42,6 +42,7 @@ #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/locs.h" #include "QF/mathlib.h" #include "QF/render.h" @@ -167,7 +168,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) mod_brush_t *brush = &worldmodel->brush; memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.model = worldmodel; + r_worldentity.renderer.model = worldmodel; R_FreeAllEntities (); @@ -362,7 +363,7 @@ R_DrawEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { currententity = ent; - switch (currententity->model->type) { + switch (currententity->renderer.model->type) { case mod_sprite: VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); @@ -374,15 +375,16 @@ R_DrawEntitiesOnList (void) VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); - minlight = max (currententity->model->min_light, currententity->min_light); + minlight = max (currententity->renderer.model->min_light, + currententity->renderer.min_light); // see if the bounding box lets us trivially reject, also // sets trivial accept status - currententity->trivial_accept = 0; //FIXME - if (currententity->model->type == mod_iqm//FIXME + currententity->visibility.trivial_accept = 0; //FIXME + if (currententity->renderer.model->type == mod_iqm//FIXME || R_AliasCheckBBox ()) { // 128 instead of 255 due to clamping below - j = max (R_LightPoint (&r_worldentity.model->brush, + j = max (R_LightPoint (&r_worldentity.renderer.model->brush, currententity->origin), minlight * 128); lighting.ambientlight = j; @@ -407,7 +409,7 @@ R_DrawEntitiesOnList (void) if (lighting.ambientlight + lighting.shadelight > 192) lighting.shadelight = 192 - lighting.ambientlight; - if (currententity->model->type == mod_iqm) + if (currententity->renderer.model->type == mod_iqm) R_IQMDrawModel (&lighting); else R_AliasDrawModel (&lighting); @@ -439,7 +441,7 @@ R_DrawViewModel (void) return; currententity = vr_data.view_model; - if (!currententity->model) + if (!currententity->renderer.model) return; VectorCopy (currententity->origin, r_entorigin); @@ -448,9 +450,10 @@ R_DrawViewModel (void) VectorCopy (vup, viewlightvec); VectorNegate (viewlightvec, viewlightvec); - minlight = max (currententity->min_light, currententity->model->min_light); + minlight = max (currententity->renderer.min_light, + currententity->renderer.model->min_light); - j = max (R_LightPoint (&r_worldentity.model->brush, + j = max (R_LightPoint (&r_worldentity.renderer.model->brush, currententity->origin), minlight * 128); r_viewlighting.ambientlight = j; @@ -489,11 +492,12 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) int i, *pindex, clipflags; vec3_t acceptpt, rejectpt; double d; + mat4f_t mat; clipflags = 0; - if (currententity->transform[0] != 1 || currententity->transform[5] != 1 - || currententity->transform[10] != 1) { + Transform_GetWorldMatrix (currententity->transform, mat); + if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { for (i = 0; i < 4; i++) { d = DotProduct (currententity->origin, view_clipplanes[i].normal); d -= view_clipplanes[i].dist; @@ -556,9 +560,9 @@ R_DrawBEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { currententity = ent; - switch (currententity->model->type) { + switch (currententity->renderer.model->type) { case mod_brush: - clmodel = currententity->model; + clmodel = currententity->renderer.model; // see if the bounding box lets us trivially reject, also // sets trivial accept status @@ -606,8 +610,9 @@ R_DrawBEntitiesOnList (void) if (r_drawpolys | r_drawculledpolys) { R_ZDrawSubmodelPolys (clmodel); } else { - if (currententity->topnode) { - mnode_t *topnode = currententity->topnode; + if (currententity->visibility.topnode) { + mnode_t *topnode + = currententity->visibility.topnode; if (topnode->contents >= 0) { // not a leaf; has to be clipped to the world @@ -756,7 +761,7 @@ R_RenderView_ (void) // done in screen.c R_LowFPPrecision (); - if (!r_worldentity.model) + if (!r_worldentity.renderer.model) Sys_Error ("R_RenderView: NULL worldmodel"); if (!r_dspeeds->int_val) { diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index b2272ff14..dee5c780e 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -244,7 +244,7 @@ R_SetupFrame (void) R_SetFrustum (); // current viewleaf - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.model); + r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); r_dowarpold = r_dowarp; r_dowarp = r_waterwarp->int_val && (r_viewleaf->contents <= diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index a5be06453..d154ad739 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -83,7 +83,7 @@ R_ReadPointFile_f (void) const char *name; char *mapname; - mapname = strdup (r_worldentity.model->path); + mapname = strdup (r_worldentity.renderer.model->path); if (!mapname) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 4ee5d74c3..8eb4151e7 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -37,6 +37,7 @@ #include +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" @@ -246,7 +247,7 @@ R_GetSpriteframe (msprite_t *psprite) int i, numframes, frame; float *pintervals, fullinterval, targettime, time; - frame = currententity->frame; + frame = currententity->animation.frame; if ((frame >= psprite->numframes) || (frame < 0)) { Sys_Printf ("R_DrawSprite: no such frame %d\n", frame); @@ -261,7 +262,7 @@ R_GetSpriteframe (msprite_t *psprite) numframes = pspritegroup->numframes; fullinterval = pintervals[numframes - 1]; - time = vr_data.realtime + currententity->syncbase; + time = vr_data.realtime + currententity->animation.syncbase; // when loading in Mod_LoadSpriteGroup, we guaranteed all interval // values are positive, so we don't have to worry about division by 0 @@ -287,7 +288,7 @@ R_DrawSprite (void) vec3_t tvec; float dot, angle, sr, cr; - psprite = currententity->model->cache.data; + psprite = currententity->renderer.model->cache.data; r_spritedesc.pspriteframe = R_GetSpriteframe (psprite); @@ -361,9 +362,11 @@ R_DrawSprite (void) } else if (psprite->type == SPR_ORIENTED) { // generate the sprite's axes, according to the sprite's world // orientation - VectorCopy (currententity->transform + 0, r_spritedesc.vpn); - VectorNegate (currententity->transform + 4, r_spritedesc.vright); - VectorCopy (currententity->transform + 8, r_spritedesc.vup); + mat4f_t mat; + Transform_GetWorldMatrix (currententity->transform, mat); + VectorCopy (mat[0], r_spritedesc.vpn); + VectorNegate (mat[1], r_spritedesc.vright); + VectorCopy (mat[2], r_spritedesc.vup); } else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) { // generate the sprite's axes, parallel to the viewplane, but rotated // in that plane around the center according to the sprite entity's diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 5133118cb..1dded8c00 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -154,7 +154,7 @@ R_BuildLightMap (void) size = smax * tmax; lightmap = surf->samples; - if (!r_worldentity.model->brush.lightdata) { + if (!r_worldentity.renderer.model->brush.lightdata) { for (i = 0; i < size; i++) blocklights[i] = 0; return; diff --git a/libs/video/renderer/sw32/sw32_ralias.c b/libs/video/renderer/sw32/sw32_ralias.c index 4ead8055a..1dacb5bc7 100644 --- a/libs/video/renderer/sw32/sw32_ralias.c +++ b/libs/video/renderer/sw32/sw32_ralias.c @@ -31,6 +31,7 @@ #define NH_DEFINE #include "namehack.h" +#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" @@ -97,8 +98,8 @@ sw32_R_AliasCheckBBox (void) int minz; // expand, rotate, and translate points into worldspace - currententity->trivial_accept = 0; - pmodel = currententity->model; + currententity->visibility.trivial_accept = 0; + pmodel = currententity->renderer.model; if (!(pahdr = pmodel->aliashdr)) pahdr = Cache_Get (&pmodel->cache); pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model); @@ -106,7 +107,7 @@ sw32_R_AliasCheckBBox (void) sw32_R_AliasSetUpTransform (0); // construct the base bounding box for this frame - frame = currententity->frame; + frame = currententity->animation.frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->path); @@ -221,11 +222,11 @@ sw32_R_AliasCheckBBox (void) return false; // trivial reject off one side } - currententity->trivial_accept = !anyclip & !zclipped; + currententity->visibility.trivial_accept = !anyclip & !zclipped; - if (currententity->trivial_accept) { + if (currententity->visibility.trivial_accept) { if (minz > (sw32_r_aliastransition + (pmdl->size * sw32_r_resfudge))) { - currententity->trivial_accept |= 2; + currententity->visibility.trivial_accept |= 2; } } @@ -366,9 +367,11 @@ sw32_R_AliasSetUpTransform (int trivial_accept) static float tmatrix[3][4]; static float viewmatrix[3][4]; - VectorCopy (currententity->transform + 0, alias_forward); - VectorNegate (currententity->transform + 4, alias_right); - VectorCopy (currententity->transform + 8, alias_up); + mat4f_t mat; + Transform_GetWorldMatrix (currententity->transform, mat); + VectorCopy (mat[0], alias_forward); + VectorNegate (mat[1], alias_right); + VectorCopy (mat[2], alias_up); tmatrix[0][0] = pmdl->scale[0]; tmatrix[1][1] = pmdl->scale[1]; @@ -543,7 +546,7 @@ R_AliasSetupSkin (void) { int skinnum; - skinnum = currententity->skinnum; + skinnum = currententity->renderer.skinnum; if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { Sys_MaskPrintf (SYS_DEV, "R_AliasSetupSkin: no such skin # %d\n", skinnum); @@ -559,16 +562,16 @@ R_AliasSetupSkin (void) sw32_r_affinetridesc.skinheight = pmdl->skinheight; sw32_acolormap = vid.colormap8; - if (currententity->skin) { + if (currententity->renderer.skin) { tex_t *base; - base = currententity->skin->texels; + base = currententity->renderer.skin->texels; if (base) { sw32_r_affinetridesc.pskin = base->data; sw32_r_affinetridesc.skinwidth = base->width; sw32_r_affinetridesc.skinheight = base->height; } - sw32_acolormap = currententity->skin->colormap; + sw32_acolormap = currententity->renderer.skin->colormap; } } @@ -611,7 +614,7 @@ R_AliasSetupFrame (void) { maliasframedesc_t *frame; - frame = R_AliasGetFramedesc (currententity->frame, paliashdr); + frame = R_AliasGetFramedesc (currententity->animation.frame, paliashdr); sw32_r_apverts = (trivertx_t *) ((byte *) paliashdr + frame->frame); } @@ -624,8 +627,8 @@ sw32_R_AliasDrawModel (alight_t *plighting) sw32_r_amodels_drawn++; - if (!(paliashdr = currententity->model->aliashdr)) - paliashdr = Cache_Get (¤tentity->model->cache); + if (!(paliashdr = currententity->renderer.model->aliashdr)) + paliashdr = Cache_Get (¤tentity->renderer.model->cache); pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model); size = (CACHE_SIZE - 1) @@ -641,7 +644,7 @@ sw32_R_AliasDrawModel (alight_t *plighting) sw32_pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1]; R_AliasSetupSkin (); - sw32_R_AliasSetUpTransform (currententity->trivial_accept); + sw32_R_AliasSetUpTransform (currententity->visibility.trivial_accept); R_AliasSetupLighting (plighting); R_AliasSetupFrame (); @@ -663,11 +666,13 @@ sw32_R_AliasDrawModel (alight_t *plighting) else sw32_ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - if (currententity->trivial_accept) + if (currententity->visibility.trivial_accept) { R_AliasPrepareUnclippedPoints (); - else + } else { R_AliasPreparePoints (); + } - if (!currententity->model->aliashdr) - Cache_Release (¤tentity->model->cache); + if (!currententity->renderer.model->aliashdr) { + Cache_Release (¤tentity->renderer.model->cache); + } } diff --git a/libs/video/renderer/sw32/sw32_rbsp.c b/libs/video/renderer/sw32/sw32_rbsp.c index 521e70cd5..1f62b381e 100644 --- a/libs/video/renderer/sw32/sw32_rbsp.c +++ b/libs/video/renderer/sw32/sw32_rbsp.c @@ -36,6 +36,7 @@ #include "qfalloca.h" +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" @@ -80,9 +81,11 @@ R_EntityRotate (vec3_t vec) void sw32_R_RotateBmodel (void) { - VectorCopy (currententity->transform + 0, entity_rotation[0]); - VectorCopy (currententity->transform + 4, entity_rotation[1]); - VectorCopy (currententity->transform + 8, entity_rotation[2]); + mat4f_t mat; + Transform_GetWorldMatrix (currententity->transform, mat); + VectorCopy (mat[0], entity_rotation[0]); + VectorCopy (mat[1], entity_rotation[1]); + VectorCopy (mat[2], entity_rotation[2]); // rotate modelorg and the transformation matrix R_EntityRotate (modelorg); @@ -300,7 +303,9 @@ sw32_R_DrawSolidClippedSubmodelPolygons (model_t *model) pbedge[j - 1].pnext = NULL; // mark end of edges - R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf); + R_RecursiveClipBPoly (pbedge, + currententity->visibility.topnode, + psurf); } else { Sys_Error ("no edges in bmodel"); } @@ -333,7 +338,8 @@ sw32_R_DrawSubmodelPolygons (model_t *model, int clipflags) // draw the polygon if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - sw32_r_currentkey = ((mleaf_t *) currententity->topnode)->key; + sw32_r_currentkey + = ((mleaf_t *) currententity->visibility.topnode)->key; // FIXME: use bounding-box-based frustum clipping info? sw32_R_RenderFace (psurf, clipflags); @@ -514,7 +520,7 @@ sw32_R_RenderWorld (void) currententity = &r_worldentity; VectorCopy (r_origin, modelorg); - brush = ¤tentity->model->brush; + brush = ¤tentity->renderer.model->brush; r_pcurrentvertbase = brush->vertexes; R_VisitWorldNodes (brush, 15); diff --git a/libs/video/renderer/sw32/sw32_rdraw.c b/libs/video/renderer/sw32/sw32_rdraw.c index b106ab63a..7c1e696be 100644 --- a/libs/video/renderer/sw32/sw32_rdraw.c +++ b/libs/video/renderer/sw32/sw32_rdraw.c @@ -349,7 +349,7 @@ sw32_R_RenderFace (msurface_t *fa, int clipflags) vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; - mod_brush_t *brush = ¤tentity->model->brush; + mod_brush_t *brush = ¤tentity->renderer.model->brush; // skip out if no more surfs if ((sw32_surface_p) >= sw32_surf_max) { @@ -622,7 +622,7 @@ sw32_R_RenderPoly (msurface_t *fa, int clipflags) polyvert_t pverts[100]; // FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; qboolean visible; - mod_brush_t *brush = ¤tentity->model->brush; + mod_brush_t *brush = ¤tentity->renderer.model->brush; // FIXME: clean this up and make it faster // FIXME: guard against running out of vertices diff --git a/libs/video/renderer/sw32/sw32_riqm.c b/libs/video/renderer/sw32/sw32_riqm.c index b53186bd9..1db5fbbdc 100644 --- a/libs/video/renderer/sw32/sw32_riqm.c +++ b/libs/video/renderer/sw32/sw32_riqm.c @@ -43,6 +43,7 @@ #include "namehack.h" #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" @@ -222,9 +223,12 @@ R_IQMSetupLighting (entity_t *ent, alight_t *plighting) r_shadelight *= VID_GRADES; // rotate the lighting vector into the model's frame of reference - r_plightvec[0] = DotProduct (plighting->plightvec, ent->transform + 0); - r_plightvec[1] = DotProduct (plighting->plightvec, ent->transform + 4); - r_plightvec[2] = DotProduct (plighting->plightvec, ent->transform + 8); + mat4f_t mat; + Transform_GetWorldMatrix (ent->transform, mat); + //FIXME vectorize + r_plightvec[0] = DotProduct (plighting->plightvec, mat[0]); + r_plightvec[1] = DotProduct (plighting->plightvec, mat[1]); + r_plightvec[2] = DotProduct (plighting->plightvec, mat[2]); } static void @@ -235,9 +239,11 @@ R_IQMSetUpTransform (int trivial_accept) static float viewmatrix[3][4]; vec3_t forward, left, up; - VectorCopy (currententity->transform + 0, forward); - VectorCopy (currententity->transform + 4, left); - VectorCopy (currententity->transform + 8, up); + mat4f_t mat; + Transform_GetWorldMatrix (currententity->transform, mat); + VectorCopy (mat[0], forward); + VectorCopy (mat[1], left); + VectorCopy (mat[2], up); // TODO: can do this with simple matrix rearrangement @@ -284,7 +290,7 @@ void sw32_R_IQMDrawModel (alight_t *plighting) { entity_t *ent = currententity; - model_t *model = ent->model; + model_t *model = ent->renderer.model; iqm_t *iqm = (iqm_t *) model->aliashdr; swiqm_t *sw = (swiqm_t *) iqm->extra_data; int size; @@ -295,7 +301,8 @@ sw32_R_IQMDrawModel (alight_t *plighting) + sizeof (finalvert_t) * (iqm->num_verts + 1) + sizeof (auxvert_t) * iqm->num_verts; blend = R_IQMGetLerpedFrames (ent, iqm); - frame = R_IQMBlendPalette (iqm, ent->pose1, ent->pose2, blend, size, + frame = R_IQMBlendPalette (iqm, ent->animation.pose1, ent->animation.pose2, + blend, size, sw->blend_palette, sw->palette_size); pfinalverts = (finalvert_t *) &frame[sw->palette_size]; @@ -303,7 +310,7 @@ sw32_R_IQMDrawModel (alight_t *plighting) (((intptr_t) &pfinalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); pauxverts = (auxvert_t *) &pfinalverts[iqm->num_verts + 1]; - R_IQMSetUpTransform (ent->trivial_accept); + R_IQMSetUpTransform (ent->visibility.trivial_accept); R_IQMSetupLighting (ent, plighting); @@ -315,7 +322,7 @@ sw32_R_IQMDrawModel (alight_t *plighting) else sw32_ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - if (ent->trivial_accept) + if (ent->visibility.trivial_accept) R_IQMPrepareUnclippedPoints (iqm, sw, frame); else R_IQMPreparePoints (iqm, sw, frame); diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 67c59e2f9..812a43205 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -42,6 +42,7 @@ #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/locs.h" #include "QF/mathlib.h" #include "QF/render.h" @@ -183,7 +184,7 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) mod_brush_t *brush = &worldmodel->brush; memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.model = worldmodel; + r_worldentity.renderer.model = worldmodel; R_FreeAllEntities (); @@ -369,7 +370,7 @@ R_DrawEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { currententity = ent; - switch (currententity->model->type) { + switch (currententity->renderer.model->type) { case mod_sprite: VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); @@ -381,15 +382,16 @@ R_DrawEntitiesOnList (void) VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); - minlight = max (currententity->min_light, currententity->model->min_light); + minlight = max (currententity->renderer.min_light, + currententity->renderer.model->min_light); // see if the bounding box lets us trivially reject, also // sets trivial accept status - currententity->trivial_accept = 0; //FIXME - if (currententity->model->type == mod_iqm//FIXME + currententity->visibility.trivial_accept = 0; //FIXME + if (currententity->renderer.model->type == mod_iqm//FIXME || sw32_R_AliasCheckBBox ()) { // 128 instead of 255 due to clamping below - j = max (R_LightPoint (&r_worldentity.model->brush, + j = max (R_LightPoint (&r_worldentity.renderer.model->brush, currententity->origin), minlight * 128); @@ -415,7 +417,7 @@ R_DrawEntitiesOnList (void) if (lighting.ambientlight + lighting.shadelight > 192) lighting.shadelight = 192 - lighting.ambientlight; - if (currententity->model->type == mod_iqm) + if (currententity->renderer.model->type == mod_iqm) sw32_R_IQMDrawModel (&lighting); else sw32_R_AliasDrawModel (&lighting); @@ -446,7 +448,7 @@ R_DrawViewModel (void) return; currententity = vr_data.view_model; - if (!currententity->model) + if (!currententity->renderer.model) return; VectorCopy (currententity->origin, r_entorigin); @@ -455,9 +457,10 @@ R_DrawViewModel (void) VectorCopy (vup, viewlightvec); VectorNegate (viewlightvec, viewlightvec); - minlight = max (currententity->min_light, currententity->model->min_light); + minlight = max (currententity->renderer.min_light, + currententity->renderer.model->min_light); - j = max (R_LightPoint (&r_worldentity.model->brush, + j = max (R_LightPoint (&r_worldentity.renderer.model->brush, currententity->origin), minlight * 128); r_viewlighting.ambientlight = j; @@ -496,11 +499,12 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) int i, *pindex, clipflags; vec3_t acceptpt, rejectpt; double d; + mat4f_t mat; clipflags = 0; - if (currententity->transform[0] != 1 || currententity->transform[5] != 1 - || currententity->transform[10] != 1) { + Transform_GetWorldMatrix (currententity->transform, mat); + if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { for (i = 0; i < 4; i++) { d = DotProduct (currententity->origin, sw32_view_clipplanes[i].normal); d -= sw32_view_clipplanes[i].dist; @@ -563,9 +567,9 @@ R_DrawBEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { currententity = ent; - switch (currententity->model->type) { + switch (currententity->renderer.model->type) { case mod_brush: - clmodel = currententity->model; + clmodel = currententity->renderer.model; // see if the bounding box lets us trivially reject, also // sets trivial accept status @@ -613,8 +617,9 @@ R_DrawBEntitiesOnList (void) if (sw32_r_drawpolys | sw32_r_drawculledpolys) { sw32_R_ZDrawSubmodelPolys (clmodel); } else { - if (currententity->topnode) { - mnode_t *topnode = currententity->topnode; + if (currententity->visibility.topnode) { + mnode_t *topnode + = currententity->visibility.topnode; if (topnode->contents >= 0) { // not a leaf; has to be clipped to the world @@ -759,7 +764,7 @@ R_RenderView_ (void) #endif R_PushDlights (vec3_origin); - if (!r_worldentity.model) + if (!r_worldentity.renderer.model) Sys_Error ("R_RenderView: NULL worldmodel"); if (!r_dspeeds->int_val) { diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c index 1b329b54f..753268993 100644 --- a/libs/video/renderer/sw32/sw32_rmisc.c +++ b/libs/video/renderer/sw32/sw32_rmisc.c @@ -240,7 +240,7 @@ sw32_R_SetupFrame (void) R_SetFrustum (); // current viewleaf - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.model); + r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); sw32_r_dowarpold = sw32_r_dowarp; sw32_r_dowarp = r_waterwarp->int_val && (r_viewleaf->contents <= diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 1364f5d1b..fc640bc8e 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -88,7 +88,7 @@ sw32_R_ReadPointFile_f (void) const char *name; char *mapname; - mapname = strdup (r_worldentity.model->path); + mapname = strdup (r_worldentity.renderer.model->path); if (!mapname) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); diff --git a/libs/video/renderer/sw32/sw32_rsprite.c b/libs/video/renderer/sw32/sw32_rsprite.c index 92be9b51e..9c6cb7221 100644 --- a/libs/video/renderer/sw32/sw32_rsprite.c +++ b/libs/video/renderer/sw32/sw32_rsprite.c @@ -40,6 +40,7 @@ #include +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" @@ -242,7 +243,7 @@ R_GetSpriteframe (msprite_t *psprite) int i, numframes, frame; float *pintervals, fullinterval, targettime, time; - frame = currententity->frame; + frame = currententity->animation.frame; if ((frame >= psprite->numframes) || (frame < 0)) { Sys_Printf ("R_DrawSprite: no such frame %d\n", frame); @@ -257,7 +258,7 @@ R_GetSpriteframe (msprite_t *psprite) numframes = pspritegroup->numframes; fullinterval = pintervals[numframes - 1]; - time = vr_data.realtime + currententity->syncbase; + time = vr_data.realtime + currententity->animation.syncbase; // when loading in Mod_LoadSpriteGroup, we guaranteed all interval // values are positive, so we don't have to worry about division by 0 @@ -283,7 +284,7 @@ sw32_R_DrawSprite (void) vec3_t tvec; float dot, angle, sr, cr; - psprite = currententity->model->cache.data; + psprite = currententity->renderer.model->cache.data; sw32_r_spritedesc.pspriteframe = R_GetSpriteframe (psprite); @@ -357,9 +358,11 @@ sw32_R_DrawSprite (void) } else if (psprite->type == SPR_ORIENTED) { // generate the sprite's axes, according to the sprite's world // orientation - VectorCopy (currententity->transform + 0, sw32_r_spritedesc.vpn); - VectorNegate (currententity->transform + 4, sw32_r_spritedesc.vright); - VectorCopy (currententity->transform + 8, sw32_r_spritedesc.vup); + mat4f_t mat; + Transform_GetWorldMatrix (currententity->transform, mat); + VectorCopy (mat[0], r_spritedesc.vpn); + VectorNegate (mat[1], r_spritedesc.vright); + VectorCopy (mat[2], r_spritedesc.vup); } else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) { // generate the sprite's axes, parallel to the viewplane, but rotated // in that plane around the center according to the sprite entity's diff --git a/libs/video/renderer/sw32/sw32_rsurf.c b/libs/video/renderer/sw32/sw32_rsurf.c index decd8c3a7..dfc9c31cc 100644 --- a/libs/video/renderer/sw32/sw32_rsurf.c +++ b/libs/video/renderer/sw32/sw32_rsurf.c @@ -172,7 +172,7 @@ R_BuildLightMap (void) size = smax * tmax; lightmap = surf->samples; - if (!r_worldentity.model->brush.lightdata) { + if (!r_worldentity.renderer.model->brush.lightdata) { for (i = 0; i < size; i++) blocklights[i] = 0; return; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index cc1905c4a..25a2d9d13 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -45,7 +45,7 @@ #include "QF/cvar.h" #include "QF/darray.h" -#include "QF/dstring.h" +#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" @@ -121,36 +121,41 @@ Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx) { aliasctx_t *actx = ctx->alias_context; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - model_t *model = ent->model; + model_t *model = ent->renderer.model; aliashdr_t *hdr; qfv_alias_skin_t *skin; - float vertex_constants[17]; + struct { + mat4f_t mat; + float blend; + } vertex_constants; byte fragment_constants[3][4]; if (!(hdr = model->aliashdr)) { hdr = Cache_Get (&model->cache); } - memcpy (vertex_constants, ent->transform, sizeof (ent->transform)); - vertex_constants[16] = R_AliasGetLerpedFrames (ent, hdr); + Transform_GetWorldMatrix (ent->transform, vertex_constants.mat); + vertex_constants.blend = R_AliasGetLerpedFrames (ent, hdr); if (0/*XXX ent->skin && ent->skin->tex*/) { //skin = ent->skin->tex; } else { maliasskindesc_t *skindesc; - skindesc = R_AliasGetSkindesc (ent->skinnum, hdr); + skindesc = R_AliasGetSkindesc (ent->renderer.skinnum, hdr); skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } - QuatScale (ent->colormod, 255, fragment_constants[0]); + QuatScale (ent->renderer.colormod, 255, fragment_constants[0]); QuatCopy (skin->colora, fragment_constants[1]); QuatCopy (skin->colorb, fragment_constants[2]); - emit_commands (aframe->cmdSet.a[QFV_aliasDepth], ent->pose1, ent->pose2, - 0, vertex_constants, sizeof (vertex_constants), + emit_commands (aframe->cmdSet.a[QFV_aliasDepth], + ent->animation.pose1, ent->animation.pose2, + 0, &vertex_constants, 17 * sizeof (float), fragment_constants, sizeof (fragment_constants), hdr, ctx); - emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], ent->pose1, ent->pose2, - skin, vertex_constants, sizeof (vertex_constants), + emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], + ent->animation.pose1, ent->animation.pose2, + skin, &vertex_constants, 17 * sizeof (float), fragment_constants, sizeof (fragment_constants), hdr, ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 046ba6c0a..38aa57ee9 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -45,7 +45,7 @@ #include "QF/cvar.h" #include "QF/darray.h" -#include "QF/dstring.h" +#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/sys.h" @@ -275,7 +275,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) { int i; model_t *m; - mod_brush_t *brush = &r_worldentity.model->brush; + mod_brush_t *brush = &r_worldentity.renderer.model->brush; clear_textures (ctx); init_surface_chains (brush, ctx); @@ -289,7 +289,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) if (*m->path == '*') continue; // world has already been done, not interested in non-brush models - if (m == r_worldentity.model || m->type != mod_brush) + if (m == r_worldentity.renderer.model || m->type != mod_brush) continue; brush = &m->brush; brush->numsubmodels = 1; // no support for submodels in non-world model @@ -343,7 +343,7 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, brush = &models[~fa->ec_index]->brush; } else { // main or sub model - brush = &r_worldentity.model->brush; + brush = &r_worldentity.renderer.model->brush; } vertices = brush->vertexes; edges = brush->edges; @@ -448,7 +448,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } surf = brush->surfaces + j; surf->ec_index = dm - brush->submodels; - if (!surf->ec_index && m != r_worldentity.model) + if (!surf->ec_index && m != r_worldentity.renderer.model) surf->ec_index = -1 - i; // instanced model tex = surf->texinfo->texture->render; // append surf to the texture chain @@ -613,9 +613,12 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) vec3_t mins, maxs, org; mod_brush_t *brush; - model = e->model; + model = e->renderer.model; brush = &model->brush; - if (e->transform[0] != 1 || e->transform[5] != 1 || e->transform[10] != 1) { + mat4f_t mat; + Transform_GetWorldMatrix (e->transform, mat); + memcpy (e->renderer.full_transform, mat, sizeof (mat));//FIXME + if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; if (R_CullSphere (e->origin, radius)) @@ -633,9 +636,9 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) vec3_t temp; VectorCopy (org, temp); - org[0] = DotProduct (temp, e->transform + 0); - org[1] = DotProduct (temp, e->transform + 4); - org[2] = DotProduct (temp, e->transform + 8); + org[0] = DotProduct (temp, mat[0]); + org[1] = DotProduct (temp, mat[1]); + org[2] = DotProduct (temp, mat[2]); } // calculate dynamic lighting for bmodel if it's not an instanced model @@ -664,7 +667,8 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) // enqueue the polygon if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (brush, surf, e->transform, e->colormod, ctx); + chain_surface (brush, surf, e->renderer.full_transform, + e->renderer.colormod, ctx); } } } @@ -1124,10 +1128,10 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) bframe->index_count = 0; memset (&worldent, 0, sizeof (worldent)); - worldent.model = r_worldentity.model; - brush = &r_worldentity.model->brush; + worldent.renderer.model = r_worldentity.renderer.model; + brush = &r_worldentity.renderer.model->brush; - //vulktex_t *tex = r_worldentity.model->skytexture->render; + //vulktex_t *tex = r_worldentity.renderer.model->skytexture->render; //bctx->skysheet_tex = tex->tex; currententity = &worldent; @@ -1136,7 +1140,7 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) if (r_drawentities->int_val) { entity_t *ent; for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->model->type != mod_brush) + if (ent->renderer.model->type != mod_brush) continue; currententity = ent; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 69916682e..e63ff0b03 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -70,7 +70,7 @@ setup_frame (vulkan_ctx_t *ctx) AngleVectors (r_refdef.viewangles, vpn, vright, vup); R_SetFrustum (); - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.model); + r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); } static void @@ -114,7 +114,7 @@ R_RenderEntities (vulkan_ctx_t *ctx) entity_t *ent; \ int begun = 0; \ for (ent = r_ent_queue; ent; ent = ent->next) { \ - if (ent->model->type != mod_##type_name) \ + if (ent->renderer.model->type != mod_##type_name) \ continue; \ if (!begun) { \ Vulkan_##Type##Begin (ctx); \ @@ -138,7 +138,7 @@ R_DrawViewModel (void) if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val || !r_drawentities->int_val - || !currententity->model) + || !currententity->renderer.model) return; // hack the depth range to prevent view model from poking into walls @@ -207,7 +207,7 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, } memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.model = worldmodel; + r_worldentity.renderer.model = worldmodel; // Force a vis update r_viewleaf = NULL; diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 2157cd42b..2da0c7fb4 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -45,6 +45,7 @@ nq_cl_plugin_LIBS= \ @client_static_plugin_libs@ nq_client_LIBFILES= \ + libs/entity/libQFentity.la \ libs/video/targets/libQFjs.la \ libs/audio/libQFcd.la \ libs/audio/libQFsound.la diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index ce76ebf71..933097913 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -32,6 +32,7 @@ #include "QF/cmd.h" #include "QF/console.h" #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/input.h" #include "QF/keys.h" #include "QF/msg.h" @@ -179,41 +180,40 @@ CL_LerpPoint (void) void CL_TransformEntity (entity_t *ent, const vec3_t angles, qboolean force) { - vec3_t ang; - vec_t *forward, *left, *up; + union { + quat_t q; + vec4f_t v; + } rotation; + vec4f_t position; + vec4f_t scale; + VectorCopy (ent->origin, position); + position[3] = 1; + VectorSet (ent->scale, ent->scale, ent->scale, scale); + scale[3] = 1; if (VectorIsZero (angles)) { - VectorSet (1, 0, 0, ent->transform + 0); - VectorSet (0, 1, 0, ent->transform + 4); - VectorSet (0, 0, 1, ent->transform + 8); - } else if (force || !VectorCompare (angles, ent->angles)) { - forward = ent->transform + 0; - left = ent->transform + 4; - up = ent->transform + 8; + QuatSet (0, 0, 0, 1, rotation.q); + } else { + vec3_t ang; VectorCopy (angles, ang); - if (ent->model && ent->model->type == mod_alias) { + if (ent->renderer.model && ent->renderer.model->type == mod_alias) { // stupid quake bug // why, oh, why, do alias models pitch in the opposite direction // to everything else? ang[PITCH] = -ang[PITCH]; } - AngleVectors (ang, forward, left, up); - VectorNegate (left, left); // AngleVectors is right-handed + AngleQuat (ang, rotation.q); } - VectorCopy (angles, ent->angles); - ent->transform[3] = 0; - ent->transform[7] = 0; - ent->transform[11] = 0; - VectorCopy (ent->origin, ent->transform + 12); - ent->transform[15] = 1; + Transform_SetLocalTransform (ent->transform, scale, rotation.v, position); } static void CL_ModelEffects (entity_t *ent, int num, int glow_color) { dlight_t *dl; - model_t *model = ent->model; + model_t *model = ent->renderer.model; + // add automatic particle trails if (model->flags & EF_ROCKET) { dl = r_funcs->R_AllocDlight (num); if (dl) { @@ -250,11 +250,12 @@ CL_EntityEffects (int num, entity_t *ent, entity_state_t *state) if (state->effects & EF_BRIGHTFIELD) r_funcs->particles->R_EntityParticles (ent); if (state->effects & EF_MUZZLEFLASH) { - vec_t *fv = ent->transform; - dl = r_funcs->R_AllocDlight (num); if (dl) { - VectorMultAdd (ent->origin, 18, fv, dl->origin); + vec4f_t position = Transform_GetWorldPosition (ent->transform); + vec4f_t fv = Transform_Forward (ent->transform); + position += 18 * fv; + VectorCopy (position, dl->origin); dl->origin[2] += 16; dl->radius = 200 + (rand () & 31); dl->die = cl.time + 0.1; @@ -271,19 +272,24 @@ static void set_entity_model (entity_t *ent, int modelindex) { int i = ent - cl_entities; - ent->model = cl.model_precache[modelindex]; + renderer_t *renderer = &ent->renderer; + animation_t *animation = &ent->animation; + renderer->model = cl.model_precache[modelindex]; // automatic animation (torches, etc) can be either all together // or randomized - if (ent->model) { - if (ent->model->synctype == ST_RAND) - ent->syncbase = (float) (rand () & 0x7fff) / 0x7fff; - else - ent->syncbase = 0.0; + if (renderer->model) { + if (renderer->model->synctype == ST_RAND) { + animation->syncbase = (float) (rand () & 0x7fff) / 0x7fff; + } else { + animation->syncbase = 0.0; + } } else { cl_forcelink[i] = true; // hack to make null model players work } - if (i <= cl.maxclients) - ent->skin = mod_funcs->Skin_SetColormap (ent->skin, i); + animation->nolerp = 1; // don't try to lerp when the model has changed + if (i <= cl.maxclients) { + renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, i); + } } void @@ -291,6 +297,8 @@ CL_RelinkEntities (void) { entity_t *ent; entity_state_t *new, *old; + renderer_t *renderer; + animation_t *animation; float bobjrotate, frac, f, d; int i, j; int entvalid; @@ -326,6 +334,9 @@ CL_RelinkEntities (void) new = &nq_entstates.frame[0 + cl.mindex][i]; old = &nq_entstates.frame[1 - cl.mindex][i]; ent = &cl_entities[i]; + renderer = &ent->renderer; + animation = &ent->animation; + // if the object wasn't included in the last packet, remove it entvalid = cl_msgtime[i] == cl.mtime[0]; if (entvalid && !new->modelindex) { @@ -334,10 +345,11 @@ CL_RelinkEntities (void) entvalid = 0; } if (!entvalid) { - ent->model = NULL; - ent->pose1 = ent->pose2 = -1; - if (ent->efrag) + renderer->model = NULL; + animation->pose1 = animation->pose2 = -1; + if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); // just became empty + } continue; } @@ -348,39 +360,43 @@ CL_RelinkEntities (void) old->modelindex = new->modelindex; set_entity_model (ent, new->modelindex); } - ent->frame = new->frame; + animation->frame = new->frame; if (cl_forcelink[i] || new->colormap != old->colormap) { old->colormap = new->colormap; - ent->skin = mod_funcs->Skin_SetColormap (ent->skin, new->colormap); + renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, + new->colormap); } if (cl_forcelink[i] || new->skinnum != old->skinnum) { old->skinnum = new->skinnum; - ent->skinnum = new->skinnum; + renderer->skinnum = new->skinnum; if (i <= cl.maxclients) { - ent->skin = mod_funcs->Skin_SetColormap (ent->skin, i); + renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, + i); mod_funcs->Skin_SetTranslation (i, cl.scores[i - 1].topcolor, cl.scores[i - 1].bottomcolor); } } ent->scale = new->scale / 16.0; - VectorCopy (ent_colormod[new->colormod], ent->colormod); - ent->colormod[3] = ENTALPHA_DECODE (new->alpha); + VectorCopy (ent_colormod[new->colormod], renderer->colormod); + renderer->colormod[3] = ENTALPHA_DECODE (new->alpha); model_flags = 0; - if (ent->model) - model_flags = ent->model->flags; + if (renderer->model) { + model_flags = renderer->model->flags; + } if (cl_forcelink[i]) { // The entity was not updated in the last message so move to the // final spot - ent->pose1 = ent->pose2 = -1; + animation->pose1 = animation->pose2 = -1; VectorCopy (new->origin, ent->origin); if (!(model_flags & EF_ROTATE)) CL_TransformEntity (ent, new->angles, true); if (i != cl.viewentity || chase_active->int_val) { - if (ent->efrag) + if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); + } r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } VectorCopy (ent->origin, ent->old_origin); @@ -395,7 +411,7 @@ CL_RelinkEntities (void) VectorCopy (new->origin, ent->origin); if (!(model_flags & EF_ROTATE)) CL_TransformEntity (ent, new->angles, true); - ent->pose1 = ent->pose2 = -1; + animation->pose1 = animation->pose2 = -1; } else { vec3_t angles, d; // interpolate the origin and angles @@ -413,7 +429,7 @@ CL_RelinkEntities (void) } } if (i != cl.viewentity || chase_active->int_val) { - if (ent->efrag) { + if (ent->visibility.efrag) { if (!VectorCompare (ent->origin, ent->old_origin)) { r_funcs->R_RemoveEfrags (ent); r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 739e4a61c..f31256138 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -403,12 +403,13 @@ CL_PrintEntities_f (void) for (i = 0, ent = cl_entities; i < cl.num_entities; i++, ent++) { Sys_Printf ("%3i:", i); - if (!ent->model) { + if (!ent->renderer.model) { Sys_Printf ("EMPTY\n"); continue; } Sys_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n", - ent->model->path, ent->frame, VectorExpand (ent->origin), + ent->renderer.model->path, ent->animation.frame, + VectorExpand (ent->origin), VectorExpand (ent->angles)); } } diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 3b076b43f..10ac2d4f5 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -433,7 +433,7 @@ CL_ParseServerInfo (void) } // local state - cl_entities[0].model = cl.worldmodel = cl.model_precache[1]; + cl_entities[0].renderer.model = cl.worldmodel = cl.model_precache[1]; if (!centerprint) centerprint = dstring_newstr (); else @@ -766,9 +766,9 @@ CL_ParseClientdata (void) cl.stats[STAT_WEAPONFRAME] |= MSG_ReadByte (net_message) << 8; if (bits & SU_WEAPONALPHA) { byte alpha = MSG_ReadByte (net_message); - cl.viewent.colormod[3] = ENTALPHA_DECODE (alpha); + cl.viewent.renderer.colormod[3] = ENTALPHA_DECODE (alpha); } else { - cl.viewent.colormod[3] = 1.0; + cl.viewent.renderer.colormod[3] = 1.0; } } @@ -785,12 +785,12 @@ CL_ParseStatic (int version) // copy it to the current state //FIXME alpha & lerp - ent->model = cl.model_precache[baseline.modelindex]; - ent->frame = baseline.frame; - ent->skin = 0; - ent->skinnum = baseline.skinnum; - VectorCopy (ent_colormod[baseline.colormod], ent->colormod); - ent->colormod[3] = ENTALPHA_DECODE (baseline.alpha); + ent->renderer.model = cl.model_precache[baseline.modelindex]; + ent->animation.frame = baseline.frame; + ent->renderer.skin = 0; + ent->renderer.skinnum = baseline.skinnum; + VectorCopy (ent_colormod[baseline.colormod], ent->renderer.colormod); + ent->renderer.colormod[3] = ENTALPHA_DECODE (baseline.alpha); ent->scale = baseline.scale / 16.0; VectorCopy (baseline.origin, ent->origin); CL_TransformEntity (ent, baseline.angles, true); @@ -1024,7 +1024,9 @@ CL_ParseServerMessage (void) mod_funcs->Skin_SetTranslation (i + 1, top, bot); cl.scores[i].topcolor = top; cl.scores[i].bottomcolor = bot; - ent->skin = mod_funcs->Skin_SetColormap (ent->skin, i + 1); + ent->renderer.skin + = mod_funcs->Skin_SetColormap (ent->renderer.skin, + i + 1); } break; diff --git a/nq/source/cl_tent.c b/nq/source/cl_tent.c index 2286d829a..3a8a1b899 100644 --- a/nq/source/cl_tent.c +++ b/nq/source/cl_tent.c @@ -38,6 +38,7 @@ #include #include +#include "QF/entity.h" #include "QF/model.h" #include "QF/msg.h" #include "QF/sound.h" @@ -132,12 +133,16 @@ CL_TEnts_Init (void) void CL_Init_Entity (entity_t *ent) { + if (ent->transform) { + Transform_Delete (ent->transform); + } memset (ent, 0, sizeof (*ent)); - ent->skin = 0; - QuatSet (1.0, 1.0, 1.0, 1.0, ent->colormod); + ent->transform = Transform_New (0); + ent->renderer.skin = 0; + QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); ent->scale = 1.0; - ent->pose1 = ent->pose2 = -1; + ent->animation.pose1 = ent->animation.pose2 = -1; } static tent_t * @@ -150,8 +155,10 @@ new_temp_entity (void) temp_entities = malloc (TEMP_BATCH * sizeof (tent_t)); for (i = 0; i < TEMP_BATCH - 1; i++) { temp_entities[i].next = &temp_entities[i + 1]; + temp_entities[i].ent.transform = 0; } temp_entities[i].next = 0; + temp_entities[i].ent.transform = 0; } tent = temp_entities; temp_entities = tent->next; @@ -208,7 +215,7 @@ CL_ClearTEnts (void) for (to = cl_beams; to; to = to->next) { for (t = to->to.beam.tents; t; t = t->next) - t->ent.efrag = 0; + t->ent.visibility.efrag = 0; free_temp_entities (to->to.beam.tents); } free_tent_objects (cl_beams); @@ -216,7 +223,7 @@ CL_ClearTEnts (void) for (to = cl_explosions; to; to = to->next) { for (t = to->to.ex.tent; t; t = t->next) - t->ent.efrag = 0; + t->ent.visibility.efrag = 0; free_temp_entities (to->to.ex.tent); } free_tent_objects (cl_explosions); @@ -231,7 +238,7 @@ beam_clear (beam_t *b) for (t = b->tents; t; t = t->next) { r_funcs->R_RemoveEfrags (&t->ent); - t->ent.efrag = 0; + t->ent.visibility.efrag = 0; } free_temp_entities (b->tents); b->tents = 0; @@ -285,7 +292,7 @@ beam_setup (beam_t *b, qboolean transform) VectorMultAdd (org, d, dist, tent->ent.origin); d += 1.0; - tent->ent.model = b->model; + tent->ent.renderer.model = b->model; ang[PITCH] = pitch; ang[YAW] = yaw; if (transform) { @@ -428,7 +435,7 @@ CL_ParseTEnt (void) //FIXME need better model management if (!cl_spr_explod->cache.data) cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); - ex->tent->ent.model = cl_spr_explod; + ex->tent->ent.renderer.model = cl_spr_explod; CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true); break; @@ -573,10 +580,10 @@ CL_UpdateExplosions (void) ex = &(*to)->to.ex; ent = &ex->tent->ent; f = 10 * (cl.time - ex->start); - if (f >= ent->model->numframes) { + if (f >= ent->renderer.model->numframes) { tent_obj_t *_to; r_funcs->R_RemoveEfrags (ent); - ent->efrag = 0; + ent->visibility.efrag = 0; free_temp_entities (ex->tent); _to = *to; *to = _to->next; @@ -586,8 +593,8 @@ CL_UpdateExplosions (void) } to = &(*to)->next; - ent->frame = f; - if (!ent->efrag) + ent->animation.frame = f; + if (!ent->visibility.efrag) r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } } diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index 71383ff08..132df122f 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -614,7 +614,7 @@ V_CalcIntermissionRefdef (void) VectorCopy (origin, r_data->refdef->vieworg); VectorCopy (angles, r_data->refdef->viewangles); - view->model = NULL; + view->renderer.model = NULL; // always idle in intermission old = v_idlescale->value; @@ -699,9 +699,9 @@ V_CalcRefdef (void) else if (r_data->scr_viewsize->int_val == 80) view->origin[2] += 0.5; - view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; - view->frame = cl.stats[STAT_WEAPONFRAME]; - view->skin = 0; + view->renderer.model = cl.model_precache[cl.stats[STAT_WEAPON]]; + view->animation.frame = cl.stats[STAT_WEAPONFRAME]; + view->renderer.skin = 0; // set up the refresh position VectorAdd (r_data->refdef->viewangles, cl.punchangle, diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 553a32f65..739789020 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -87,6 +87,7 @@ qw_cl_plugin_LIBS= \ qw_client_LIBS= \ libs/qw/libqw.a \ libs/net/libnet_chan.la \ + libs/entity/libQFentity.la \ libs/console/libQFconsole.la \ libs/video/targets/libQFjs.la \ libs/audio/libQFcd.la \ diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 6151b6bd0..d063211d4 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -758,17 +758,19 @@ demo_start_recording (int track) for (ent = cl_static_entities; ent; ent = ent->unext) { MSG_WriteByte (&buf, svc_spawnstatic); - for (j = 1; j < cl.nummodels; j++) - if (ent->model == cl.model_precache[j]) + for (j = 1; j < cl.nummodels; j++) { + if (ent->renderer.model == cl.model_precache[j]) { break; + } + } if (j == cl.nummodels) MSG_WriteByte (&buf, 0); else MSG_WriteByte (&buf, j); - MSG_WriteByte (&buf, ent->frame); + MSG_WriteByte (&buf, ent->animation.frame); MSG_WriteByte (&buf, 0); - MSG_WriteByte (&buf, ent->skinnum); + MSG_WriteByte (&buf, ent->renderer.skinnum); MSG_WriteCoordAngleV (&buf, ent->origin, ent->angles); if (buf.cursize > MAX_MSGLEN / 2) { diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 6fc04a4c4..2d130574d 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -482,7 +482,7 @@ CL_ParsePlayerinfo (void) bits = MSG_ReadByte (net_message); if (bits & PF_ALPHA) { val = MSG_ReadByte (net_message); - ent->colormod[3] = val / 255.0; + ent->renderer.colormod[3] = val / 255.0; } if (bits & PF_SCALE) { val = MSG_ReadByte (net_message); @@ -505,7 +505,7 @@ CL_ParsePlayerinfo (void) g = (float) ((val >> 2) & 7) * (1.0 / 7.0); b = (float) (val & 3) * (1.0 / 3.0); } - VectorSet (r, g, b, ent->colormod); + VectorSet (r, g, b, ent->renderer.colormod); } if (bits & PF_FRAME2) { state->pls.frame |= MSG_ReadByte (net_message) << 8; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 7c95040ed..d294f9981 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -36,6 +36,7 @@ #endif #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/locs.h" #include "QF/msg.h" #include "QF/render.h" @@ -172,40 +173,38 @@ is_gib (entity_state_t *s1) void CL_TransformEntity (entity_t *ent, const vec3_t angles, qboolean force) { - vec3_t ang; - vec_t *forward, *left, *up; + union { + quat_t q; + vec4f_t v; + } rotation; + vec4f_t position; + vec4f_t scale; + VectorCopy (ent->origin, position); + position[3] = 1; + VectorSet (ent->scale, ent->scale, ent->scale, scale); + scale[3] = 1; if (VectorIsZero (angles)) { - VectorSet (1, 0, 0, ent->transform + 0); - VectorSet (0, 1, 0, ent->transform + 4); - VectorSet (0, 0, 1, ent->transform + 8); - } else if (force || !VectorCompare (angles, ent->angles)) { - forward = ent->transform + 0; - left = ent->transform + 4; - up = ent->transform + 8; + QuatSet (0, 0, 0, 1, rotation.q); + } else { + vec3_t ang; VectorCopy (angles, ang); - if (ent->model && ent->model->type == mod_alias) { + if (ent->renderer.model && ent->renderer.model->type == mod_alias) { // stupid quake bug // why, oh, why, do alias models pitch in the opposite direction // to everything else? ang[PITCH] = -ang[PITCH]; } - AngleVectors (ang, forward, left, up); - VectorNegate (left, left); // AngleVectors is right-handed + AngleQuat (ang, rotation.q); } - VectorCopy (angles, ent->angles); - ent->transform[3] = 0; - ent->transform[7] = 0; - ent->transform[11] = 0; - VectorCopy (ent->origin, ent->transform + 12); - ent->transform[15] = 1; + Transform_SetLocalTransform (ent->transform, scale, rotation.v, position); } static void CL_ModelEffects (entity_t *ent, int num, int glow_color) { dlight_t *dl; - model_t *model = ent->model; + model_t *model = ent->renderer.model; // add automatic particle trails if (model->flags & EF_ROCKET) { @@ -239,14 +238,17 @@ CL_ModelEffects (entity_t *ent, int num, int glow_color) static void set_entity_model (entity_t *ent, int modelindex) { - ent->model = cl.model_precache[modelindex]; + renderer_t *renderer = &ent->renderer; + animation_t *animation = &ent->animation; + renderer->model = cl.model_precache[modelindex]; // automatic animation (torches, etc) can be either all together // or randomized - if (ent->model) { - if (ent->model->synctype == ST_RAND) - ent->syncbase = (float) (rand () & 0x7fff) / 0x7fff; - else - ent->syncbase = 0.0; + if (renderer->model) { + if (renderer->model->synctype == ST_RAND) { + animation->syncbase = (float) (rand () & 0x7fff) / 0x7fff; + } else { + animation->syncbase = 0.0; + } } } @@ -257,6 +259,8 @@ CL_LinkPacketEntities (void) float frac, f; entity_t *ent; entity_state_t *new, *old; + renderer_t *renderer; + animation_t *animation; vec3_t delta; frac = 1; @@ -264,14 +268,17 @@ CL_LinkPacketEntities (void) new = &qw_entstates.frame[cl.link_sequence & UPDATE_MASK][i]; old = &qw_entstates.frame[cl.prev_sequence & UPDATE_MASK][i]; ent = &cl_entities[i]; + renderer = &ent->renderer; + animation = &ent->animation; forcelink = cl_entity_valid[0][i] != cl_entity_valid[1][i]; cl_entity_valid[1][i] = cl_entity_valid[0][i]; // if the object wasn't included in the last packet, remove it if (!cl_entity_valid[0][i]) { - ent->model = NULL; - ent->pose1 = ent->pose2 = -1; - if (ent->efrag) + renderer->model = NULL; + animation->pose1 = animation->pose2 = -1; + if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); // just became empty + } continue; } @@ -283,8 +290,9 @@ CL_LinkPacketEntities (void) if (!new->modelindex || (cl_deadbodyfilter->int_val && is_dead_body (new)) || (cl_gibfilter->int_val && is_gib (new))) { - if (ent->efrag) + if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); + } continue; } @@ -295,46 +303,50 @@ CL_LinkPacketEntities (void) old->modelindex = new->modelindex; set_entity_model (ent, new->modelindex); } - ent->frame = new->frame; + animation->frame = new->frame; if (forcelink || new->colormap != old->colormap || new->skinnum != old->skinnum) { old->skinnum = new->skinnum; - ent->skinnum = new->skinnum; + renderer->skinnum = new->skinnum; old->colormap = new->colormap; if (new->colormap && (new->colormap <= MAX_CLIENTS) && cl.players[new->colormap - 1].name && cl.players[new->colormap - 1].name->value[0] && new->modelindex == cl_playerindex) { player_info_t *player = &cl.players[new->colormap - 1]; - ent->skin = mod_funcs->Skin_SetSkin (ent->skin, new->colormap, - player->skinname->value); - ent->skin = mod_funcs->Skin_SetColormap (ent->skin, - new->colormap); + renderer->skin + = mod_funcs->Skin_SetSkin (renderer->skin, new->colormap, + player->skinname->value); + renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, + new->colormap); } else { - ent->skin = mod_funcs->Skin_SetColormap (ent->skin, 0); + renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, + 0); } } ent->scale = new->scale / 16.0; - VectorCopy (ent_colormod[new->colormod], ent->colormod); - ent->colormod[3] = new->alpha / 255.0; + VectorCopy (ent_colormod[new->colormod], renderer->colormod); + renderer->colormod[3] = new->alpha / 255.0; - ent->min_light = 0; - ent->fullbright = 0; + renderer->min_light = 0; + renderer->fullbright = 0; if (new->modelindex == cl_playerindex) { - ent->min_light = min (cl.fbskins, cl_fb_players->value); - if (ent->min_light >= 1.0) - ent->fullbright = 1; + renderer->min_light = min (cl.fbskins, cl_fb_players->value); + if (renderer->min_light >= 1.0) { + renderer->fullbright = 1; + } } if (forcelink) { - ent->pose1 = ent->pose2 = -1; + animation->pose1 = animation->pose2 = -1; VectorCopy (new->origin, ent->origin); - if (!(ent->model->flags & EF_ROTATE)) + if (!(renderer->model->flags & EF_ROTATE)) CL_TransformEntity (ent, new->angles, true); if (i != cl.viewentity || chase_active->int_val) { - if (ent->efrag) + if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); + } r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } VectorCopy (ent->origin, ent->old_origin); @@ -347,14 +359,15 @@ CL_LinkPacketEntities (void) || fabs (delta[2]) > 100) { // assume a teleportation, not a motion VectorCopy (new->origin, ent->origin); - if (!(ent->model->flags & EF_ROTATE)) + if (!(renderer->model->flags & EF_ROTATE)) { CL_TransformEntity (ent, new->angles, true); - ent->pose1 = ent->pose2 = -1; + } + animation->pose1 = animation->pose2 = -1; } else { vec3_t angles, d; // interpolate the origin and angles VectorMultAdd (old->origin, f, delta, ent->origin); - if (!(ent->model->flags & EF_ROTATE)) { + if (!(renderer->model->flags & EF_ROTATE)) { VectorSubtract (new->angles, old->angles, d); for (j = 0; j < 3; j++) { if (d[j] > 180) @@ -367,7 +380,7 @@ CL_LinkPacketEntities (void) } } if (i != cl.viewentity || chase_active->int_val) { - if (ent->efrag) { + if (ent->visibility.efrag) { if (!VectorCompare (ent->origin, ent->old_origin)) { r_funcs->R_RemoveEfrags (ent); r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); @@ -377,11 +390,12 @@ CL_LinkPacketEntities (void) } } } - if (!ent->efrag) + if (!ent->visibility.efrag) { r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + } // rotate binary objects locally - if (ent->model->flags & EF_ROTATE) { + if (renderer->model->flags & EF_ROTATE) { vec3_t angles; angles[PITCH] = 0; angles[YAW] = anglemod (100 * cl.time); @@ -392,8 +406,9 @@ CL_LinkPacketEntities (void) //CL_NewDlight (i, ent->origin, new->effects, 0, 0); if (VectorDistance_fast (old->origin, ent->origin) > (256 * 256)) VectorCopy (ent->origin, old->origin); - if (ent->model->flags & ~EF_ROTATE) + if (renderer->model->flags & ~EF_ROTATE) { CL_ModelEffects (ent, -new->number, new->glow_color); + } } } @@ -414,36 +429,40 @@ CL_AddFlagModels (entity_t *ent, int team, int key) }; float f; entity_t *fent; - vec_t *v_forward, *v_left; - vec3_t ang; - - if (cl_flagindex == -1) - return; - - f = 14.0; - if (ent->frame >= 29 && ent->frame <= 40) { - f = flag_offsets[ent->frame - 29]; - } else if (ent->frame >= 103 && ent->frame <= 118) { - if (ent->frame <= 106) // 103-104 nailattack - f = 20.0; // 105-106 light - else // 107-112 rocketattack - f = 21.0; // 112-118 shotattack - } fent = &cl_flag_ents[key]; - fent->model = cl.model_precache[cl_flagindex]; - fent->skinnum = team; - v_forward = ent->transform + 0; - v_left = ent->transform + 4; + if (cl_flagindex == -1) { + fent->active = 0; + return; + } - VectorMultAdd (ent->origin, -f, v_forward, fent->origin); - VectorMultAdd (fent->origin, -22, v_left, fent->origin); - fent->origin[2] -= 16.0; + fent->active = 1; + f = 14.0; + if (ent->animation.frame >= 29 && ent->animation.frame <= 40) { + f = flag_offsets[ent->animation.frame - 29]; + } else if (ent->animation.frame >= 103 && ent->animation.frame <= 118) { + if (ent->animation.frame <= 106) { // 103-104 nailattack + f = 20.0; // 105-106 light + } else { // 107-112 rocketattack + f = 21.0; // 112-118 shotattack + } + } - VectorCopy (ent->angles, ang); - ang[2] -= 45.0; - CL_TransformEntity (fent, ang, false); + vec4f_t position = { 22, -f, -16, 1}; + + if (!Transform_GetParent (fent->transform)) { + vec4f_t scale = { 1, 1, 1, 1 }; + // -45 degree roll (x is forward) + vec4f_t rotation = { -0.382683432, 0, 0, 0.923879533 }; + Transform_SetParent (fent->transform, ent->transform); + Transform_SetLocalTransform (fent->transform, scale, rotation, + position); + } else { + Transform_SetLocalPosition (fent->transform, position); + } + fent->renderer.model = cl.model_precache[cl_flagindex]; + fent->renderer.skinnum = team; r_funcs->R_EnqueueEntity (fent);//FIXME should use efrag (needs smarter // handling //in the player code) @@ -477,7 +496,7 @@ CL_LinkPlayers (void) for (j = 0, info = cl.players, state = frame->playerstate; j < MAX_CLIENTS; j++, info++, state++) { ent = &cl_player_ents[j]; - if (ent->efrag) + if (ent->visibility.efrag) r_funcs->R_RemoveEfrags (ent); if (state->messagenum != cl.parsecount) continue; // not present this frame @@ -544,26 +563,27 @@ CL_LinkPlayers (void) } ang[ROLL] = V_CalcRoll (ang, state->pls.velocity) * 4.0; - ent->model = cl.model_precache[state->pls.modelindex]; - ent->frame = state->pls.frame; - ent->skinnum = state->pls.skinnum; + ent->renderer.model = cl.model_precache[state->pls.modelindex]; + ent->animation.frame = state->pls.frame; + ent->renderer.skinnum = state->pls.skinnum; CL_TransformEntity (ent, ang, false); - ent->min_light = 0; - ent->fullbright = 0; + ent->renderer.min_light = 0; + ent->renderer.fullbright = 0; if (state->pls.modelindex == cl_playerindex) { //XXX // use custom skin - ent->skin = info->skin; + ent->renderer.skin = info->skin; - ent->min_light = min (cl.fbskins, cl_fb_players->value); + ent->renderer.min_light = min (cl.fbskins, cl_fb_players->value); - if (ent->min_light >= 1.0) - ent->fullbright = 1; + if (ent->renderer.min_light >= 1.0) { + ent->renderer.fullbright = 1; + } } else { // FIXME no team colors on nonstandard player models - ent->skin = 0; + ent->renderer.skin = 0; } // stuff entity in map diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index f38b30537..2523f8feb 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -979,9 +979,9 @@ CL_ParseStatic (void) cl_static_tail = &ent->unext; // copy it to the current state - ent->model = cl.model_precache[es.modelindex]; - ent->frame = es.frame; - ent->skinnum = es.skinnum; + ent->renderer.model = cl.model_precache[es.modelindex]; + ent->animation.frame = es.frame; + ent->renderer.skinnum = es.skinnum; VectorCopy (es.origin, ent->origin); CL_TransformEntity (ent, es.angles, true); diff --git a/qw/source/cl_tent.c b/qw/source/cl_tent.c index c24f1f0bc..e44ec9b3a 100644 --- a/qw/source/cl_tent.c +++ b/qw/source/cl_tent.c @@ -39,6 +39,7 @@ #include #include "QF/console.h" +#include "QF/entity.h" #include "QF/model.h" #include "QF/msg.h" #include "QF/sound.h" @@ -136,12 +137,16 @@ CL_TEnts_Init (void) void CL_Init_Entity (entity_t *ent) { + if (ent->transform) { + Transform_Delete (ent->transform); + } memset (ent, 0, sizeof (*ent)); - ent->skin = 0; - QuatSet (1.0, 1.0, 1.0, 1.0, ent->colormod); + ent->transform = Transform_New (0); + ent->renderer.skin = 0; + QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); ent->scale = 1.0; - ent->pose1 = ent->pose2 = -1; + ent->animation.pose1 = ent->animation.pose2 = -1; } static tent_t * @@ -154,8 +159,10 @@ new_temp_entity (void) temp_entities = malloc (TEMP_BATCH * sizeof (tent_t)); for (i = 0; i < TEMP_BATCH - 1; i++) { temp_entities[i].next = &temp_entities[i + 1]; + temp_entities[i].ent.transform = 0; } temp_entities[i].next = 0; + temp_entities[i].ent.transform = 0; } tent = temp_entities; temp_entities = tent->next; @@ -211,16 +218,18 @@ CL_ClearTEnts (void) tent_obj_t *to; for (to = cl_beams; to; to = to->next) { - for (t = to->to.beam.tents; t; t = t->next) - t->ent.efrag = 0; + for (t = to->to.beam.tents; t; t = t->next) { + t->ent.visibility.efrag = 0; + } free_temp_entities (to->to.beam.tents); } free_tent_objects (cl_beams); cl_beams = 0; for (to = cl_explosions; to; to = to->next) { - for (t = to->to.ex.tent; t; t = t->next) - t->ent.efrag = 0; + for (t = to->to.ex.tent; t; t = t->next) { + t->ent.visibility.efrag = 0; + } free_temp_entities (to->to.ex.tent); } free_tent_objects (cl_explosions); @@ -235,7 +244,7 @@ beam_clear (beam_t *b) for (t = b->tents; t; t = t->next) { r_funcs->R_RemoveEfrags (&t->ent); - t->ent.efrag = 0; + t->ent.visibility.efrag = 0; } free_temp_entities (b->tents); b->tents = 0; @@ -289,7 +298,7 @@ beam_setup (beam_t *b, qboolean transform) VectorMultAdd (org, d, dist, tent->ent.origin); d += 1.0; - tent->ent.model = b->model; + tent->ent.renderer.model = b->model; ang[PITCH] = pitch; ang[YAW] = yaw; if (transform) { @@ -432,7 +441,7 @@ CL_ParseTEnt (void) //FIXME need better model management if (!cl_spr_explod->cache.data) cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); - ex->tent->ent.model = cl_spr_explod; + ex->tent->ent.renderer.model = cl_spr_explod; CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true); break; @@ -580,10 +589,10 @@ CL_UpdateExplosions (void) ex = &(*to)->to.ex; ent = &ex->tent->ent; f = 10 * (cl.time - ex->start); - if (f >= ent->model->numframes) { + if (f >= ent->renderer.model->numframes) { tent_obj_t *_to; r_funcs->R_RemoveEfrags (ent); - ent->efrag = 0; + ent->visibility.efrag = 0; free_temp_entities (ex->tent); _to = *to; *to = _to->next; @@ -593,9 +602,10 @@ CL_UpdateExplosions (void) } to = &(*to)->next; - ent->frame = f; - if (!ent->efrag) + ent->animation.frame = f; + if (!ent->visibility.efrag) { r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + } } } @@ -613,7 +623,7 @@ CL_ClearProjectiles (void) for (tent = cl_projectiles; tent; tent = tent->next) { r_funcs->R_RemoveEfrags (&tent->ent); - tent->ent.efrag = 0; + tent->ent.visibility.efrag = 0; } free_temp_entities (cl_projectiles); cl_projectiles = 0; @@ -648,8 +658,8 @@ CL_ParseProjectiles (qboolean nail2) tail = &tent->next; pr = &tent->ent; - pr->model = cl.model_precache[cl_spikeindex]; - pr->skin = 0; + pr->renderer.model = cl.model_precache[cl_spikeindex]; + pr->renderer.skin = 0; pr->origin[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096; pr->origin[1] = (((bits[1] >> 4) + (bits[2] << 4)) << 1) - 4096; pr->origin[2] = ((bits[3] + ((bits[4] & 15) << 8)) << 1) - 4096; diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 4ad5da14f..59e7920cd 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -617,7 +617,7 @@ V_CalcIntermissionRefdef (void) VectorCopy (origin, r_data->refdef->vieworg); VectorCopy (angles, r_data->refdef->viewangles); - view->model = NULL; + view->renderer.model = NULL; // always idle in intermission old = v_idlescale->value; @@ -700,12 +700,13 @@ V_CalcRefdef (void) else if (r_data->scr_viewsize->int_val == 80) view->origin[2] += 0.5; - if (view_message->pls.flags & (PF_GIB | PF_DEAD)) - view->model = NULL; - else - view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; - view->frame = view_message->pls.weaponframe; - view->skin = 0; + if (view_message->pls.flags & (PF_GIB | PF_DEAD)) { + view->renderer.model = NULL; + } else { + view->renderer.model = cl.model_precache[cl.stats[STAT_WEAPON]]; + } + view->animation.frame = view_message->pls.weaponframe; + view->renderer.skin = 0; // set up the refresh position VectorAdd (r_data->refdef->viewangles, cl.punchangle, diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index bcb97af94..781db5c76 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -65,6 +65,7 @@ qwaq_cl_plugin_libs= \ @client_static_plugin_libs@ qwaq_client_libs= \ + $(top_builddir)/libs/entity/libQFentity.la \ $(top_builddir)/libs/console/libQFconsole.la \ $(top_builddir)/libs/video/targets/libQFjs.la \ $(top_builddir)/libs/audio/libQFcd.la \ From 098ceed5ff6213e515259ddcee3b5e024aab544f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Mar 2021 18:00:16 +0900 Subject: [PATCH 1365/3664] [client] Merge nq and qw temp entity handling This finally gets cl_tent merged away. --- include/client/entities.h | 3 + include/client/temp_entities.h | 119 ++++ libs/client/Makemodule.am | 4 +- libs/client/cl_entities.c | 34 + .../client/cl_temp_entities.c | 448 ++++++++----- nq/include/client.h | 10 - nq/source/Makemodule.am | 2 +- nq/source/cl_ents.c | 40 +- nq/source/cl_main.c | 8 +- nq/source/cl_parse.c | 15 +- nq/source/cl_tent.c | 630 ------------------ nq/source/cl_view.c | 2 +- qw/include/Makemodule.am | 1 - qw/include/cl_ents.h | 4 +- qw/include/cl_parse.h | 1 - qw/include/cl_tent.h | 38 -- qw/source/Makemodule.am | 2 +- qw/source/cl_entparse.c | 3 +- qw/source/cl_ents.c | 49 +- qw/source/cl_main.c | 3 +- qw/source/cl_parse.c | 21 +- qw/source/cl_view.c | 2 +- 22 files changed, 482 insertions(+), 957 deletions(-) create mode 100644 include/client/temp_entities.h rename qw/source/cl_tent.c => libs/client/cl_temp_entities.c (54%) delete mode 100644 nq/source/cl_tent.c delete mode 100644 qw/include/cl_tent.h diff --git a/include/client/entities.h b/include/client/entities.h index ae046b8c4..1dba394d6 100644 --- a/include/client/entities.h +++ b/include/client/entities.h @@ -67,4 +67,7 @@ extern entstates_t qw_entstates; extern vec3_t ent_colormod[256]; +struct entity_s; +void CL_TransformEntity (struct entity_s *ent, const vec3_t angles); + #endif//__client_entities_h diff --git a/include/client/temp_entities.h b/include/client/temp_entities.h new file mode 100644 index 000000000..c4dbc0868 --- /dev/null +++ b/include/client/temp_entities.h @@ -0,0 +1,119 @@ +/* + temp_entities.h + + Temporary entity management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/3/10 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __client_temp_entities_h +#define __client_temp_entities_h + +#include "QF/simd/vec4f.h" + +typedef enum TE_Effect { + TE_NoEffect, // for invalid nq/qw -> qf mapping + TE_Beam, // grappling hook beam + TE_Blood, // bullet hitting body + TE_Explosion, // rocket explosion + TE_Explosion2, // color mapped explosion + TE_Explosion3, // Nehahra colored light explosion + TE_Gunshot1, // NQ gunshot (20 particles) + TE_Gunshot2, // QW gunshot (has particle count) + TE_KnightSpike, // spike hitting wall + TE_LavaSplash, + TE_Lightning1, // lightning bolts + TE_Lightning2, // lightning bolts + TE_Lightning3, // lightning bolts + TE_Lightning4, // Nehahra lightning + TE_LightningBlood, // lightning hitting body + TE_Spike, // spike hitting wall + TE_SuperSpike, // super spike hitting wall + TE_TarExplosion, // tarbaby explosion + TE_Teleport, + TE_WizSpike, // spike hitting wall +} TE_Effect; + +typedef enum TE_nqEffect { + TE_nqSpike, + TE_nqSuperSpike, + TE_nqGunshot, + TE_nqExplosion, + TE_nqTarExplosion, + TE_nqLightning1, + TE_nqLightning2, + TE_nqWizSpike, + TE_nqKnightSpike, + TE_nqLightning3, + TE_nqLavaSplash, + TE_nqTeleport, + TE_nqExplosion2, + TE_nqBeam, + TE_nqExplosion3 = 16, + TE_nqLightning4, +} TE_nqEffect; + +typedef enum TE_qwEffect { + TE_qwSpike, + TE_qwSuperSpike, + TE_qwGunshot, + TE_qwExplosion, + TE_qwTarExplosion, + TE_qwLightning1, + TE_qwLightning2, + TE_qwWizSpike, + TE_qwKnightSpike, + TE_qwLightning3, + TE_qwLavaSplash, + TE_qwTeleport, + TE_qwBlood, + TE_qwLightningBlood, + TE_qwExplosion2 = 16, + TE_qwBeam, +} TE_qwEffect; + +//FIXME find a better way to get this info from the parser +typedef struct TEntContext_s { + vec4f_t simorg; + struct model_s *worldModel; + int playerEntity; +} TEntContext_t; + +struct msg_s; +struct entity_s; + +void CL_TEnts_Init (void); +void CL_Init_Entity (struct entity_s *ent); +void CL_ClearTEnts (void); +void CL_UpdateTEnts (double time, TEntContext_t *ctx); +void CL_ParseTEnt_nq (struct msg_s *net_message, double time, + TEntContext_t *ctx); +void CL_ParseTEnt_qw (struct msg_s *net_message, double time, + TEntContext_t *ctx); +void CL_ParseParticleEffect (struct msg_s *net_message); +void CL_ClearProjectiles (void); +void CL_ParseProjectiles (struct msg_s *net_message, qboolean nail2, + TEntContext_t *ctx); + +#endif//__client_temp_entities_h diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 962430a4b..9129b9dbd 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -3,4 +3,6 @@ noinst_LTLIBRARIES += libs/client/libQFclient.la libs_client_libQFclient_la_LDFLAGS= @STATIC@ libs_client_libQFclient_la_LIBADD= libs/gamecode/libQFgamecode.la libs/util/libQFutil.la libs_client_libQFclient_la_SOURCES= \ - libs/client/cl_entities.c + libs/client/cl_temp_entities.c \ + libs/client/cl_entities.c \ + $e diff --git a/libs/client/cl_entities.c b/libs/client/cl_entities.c index 01397321a..837cfbe60 100644 --- a/libs/client/cl_entities.c +++ b/libs/client/cl_entities.c @@ -31,6 +31,10 @@ # include "config.h" #endif +#include "QF/entity.h" +#include "QF/render.h" //FIXME for entity_t +#include "QF/simd/vec4f.h" + #include "client/entities.h" /* QW has a max of 512 entities and wants 64 frames of data per entity, plus @@ -340,3 +344,33 @@ vec3_t ent_colormod[256] = { {1, 1, 0.666667}, {1, 1, 1} }; + +void +CL_TransformEntity (entity_t *ent, const vec3_t angles) +{ + union { + quat_t q; + vec4f_t v; + } rotation; + vec4f_t position; + vec4f_t scale; + + VectorCopy (ent->origin, position); + position[3] = 1; + VectorSet (ent->scale, ent->scale, ent->scale, scale); + scale[3] = 1; + if (VectorIsZero (angles)) { + QuatSet (0, 0, 0, 1, rotation.q); + } else { + vec3_t ang; + VectorCopy (angles, ang); + if (ent->renderer.model && ent->renderer.model->type == mod_alias) { + // stupid quake bug + // why, oh, why, do alias models pitch in the opposite direction + // to everything else? + ang[PITCH] = -ang[PITCH]; + } + AngleQuat (ang, rotation.q); + } + Transform_SetLocalTransform (ent->transform, scale, rotation.v, position); +} diff --git a/qw/source/cl_tent.c b/libs/client/cl_temp_entities.c similarity index 54% rename from qw/source/cl_tent.c rename to libs/client/cl_temp_entities.c index e44ec9b3a..a0627e42d 100644 --- a/qw/source/cl_tent.c +++ b/libs/client/cl_temp_entities.c @@ -1,9 +1,12 @@ /* - cl_tent.c + cl_temp_entities.c - client side temporary entities + Client side temporary entity management - Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/3/10 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -27,7 +30,6 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif - #ifdef HAVE_STRING_H # include #endif @@ -35,23 +37,16 @@ # include #endif -#include -#include - -#include "QF/console.h" #include "QF/entity.h" -#include "QF/model.h" #include "QF/msg.h" +#include "QF/quakefs.h" +#include "QF/render.h" #include "QF/sound.h" -#include "QF/sys.h" -#include "compat.h" +#include "QF/plugin/vid_render.h" //FIXME -#include "qw/include/cl_ents.h" -#include "qw/include/cl_main.h" -#include "qw/include/cl_parse.h" -#include "qw/include/cl_tent.h" -#include "qw/include/client.h" +#include "client/entities.h" +#include "client/temp_entities.h" typedef struct tent_s { struct tent_s *next; @@ -94,28 +89,29 @@ static tent_t *cl_projectiles; static sfx_t *cl_sfx_wizhit; static sfx_t *cl_sfx_knighthit; static sfx_t *cl_sfx_tink1; -static sfx_t *cl_sfx_ric1; -static sfx_t *cl_sfx_ric2; -static sfx_t *cl_sfx_ric3; static sfx_t *cl_sfx_r_exp3; +static sfx_t *cl_sfx_ric[4]; static model_t *cl_mod_beam; static model_t *cl_mod_bolt; static model_t *cl_mod_bolt2; static model_t *cl_mod_bolt3; static model_t *cl_spr_explod; +static model_t *cl_spike; static void CL_TEnts_Precache (int phase) { - if (!phase) + if (!phase) { return; + } cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav"); cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav"); cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav"); - cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav"); - cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav"); - cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav"); + cl_sfx_ric[3] = S_PrecacheSound ("weapons/ric1.wav"); + cl_sfx_ric[2] = S_PrecacheSound ("weapons/ric2.wav"); + cl_sfx_ric[1] = S_PrecacheSound ("weapons/ric3.wav"); + cl_sfx_ric[0] = cl_sfx_ric[1]; cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav"); cl_mod_bolt = Mod_ForName ("progs/bolt.mdl", true); @@ -123,8 +119,11 @@ CL_TEnts_Precache (int phase) cl_mod_bolt3 = Mod_ForName ("progs/bolt3.mdl", true); cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); cl_mod_beam = Mod_ForName ("progs/beam.mdl", false); - if (!cl_mod_beam) + cl_spike = Mod_ForName ("progs/spike.mdl", false); + + if (!cl_mod_beam) { cl_mod_beam = cl_mod_bolt; + } } void @@ -214,23 +213,23 @@ free_tent_objects (tent_obj_t *tobjs) void CL_ClearTEnts (void) { - tent_t *t; - tent_obj_t *to; + tent_t *tent; + tent_obj_t *tobj; - for (to = cl_beams; to; to = to->next) { - for (t = to->to.beam.tents; t; t = t->next) { - t->ent.visibility.efrag = 0; + for (tobj = cl_beams; tobj; tobj = tobj->next) { + for (tent = tobj->to.beam.tents; tent; tent = tent->next) { + tent->ent.visibility.efrag = 0; } - free_temp_entities (to->to.beam.tents); + free_temp_entities (tobj->to.beam.tents); } free_tent_objects (cl_beams); cl_beams = 0; - for (to = cl_explosions; to; to = to->next) { - for (t = to->to.ex.tent; t; t = t->next) { - t->ent.visibility.efrag = 0; + for (tobj = cl_explosions; tobj; tobj = tobj->next) { + for (tent = tobj->to.ex.tent; tent; tent = tent->next) { + tent->ent.visibility.efrag = 0; } - free_temp_entities (to->to.ex.tent); + free_temp_entities (tobj->to.ex.tent); } free_tent_objects (cl_explosions); cl_explosions = 0; @@ -252,7 +251,7 @@ beam_clear (beam_t *b) } static inline void -beam_setup (beam_t *b, qboolean transform) +beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx) { tent_t *tent; float forward, pitch, yaw, d; @@ -287,8 +286,7 @@ beam_setup (beam_t *b, qboolean transform) ent_count = ceil (d / 30); d = 0; - seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) % - BEAM_SEED_INTERVAL); + seed = b->seed + ((int) (time * BEAM_SEED_INTERVAL) % BEAM_SEED_INTERVAL); ang[ROLL] = 0; while (ent_count--) { @@ -304,15 +302,15 @@ beam_setup (beam_t *b, qboolean transform) if (transform) { seed = seed * BEAM_SEED_PRIME; ang[ROLL] = seed % 360; - CL_TransformEntity (&tent->ent, ang, true); + CL_TransformEntity (&tent->ent, ang); } VectorCopy (ang, tent->ent.angles); - r_funcs->R_AddEfrags (&cl.worldmodel->brush, &tent->ent); + r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent); } } static void -CL_ParseBeam (model_t *m) +CL_ParseBeam (qmsg_t *net_message, model_t *m, double time, TEntContext_t *ctx) { tent_obj_t *to; beam_t *b; @@ -326,9 +324,11 @@ CL_ParseBeam (model_t *m) to = 0; if (ent) { - for (to = cl_beams; to; to = to->next) - if (to->to.beam.entity == ent) + for (to = cl_beams; to; to = to->next) { + if (to->to.beam.entity == ent) { break; + } + } } if (!to) { to = new_tent_object (); @@ -341,93 +341,60 @@ CL_ParseBeam (model_t *m) beam_clear (b); b->model = m; - b->endtime = cl.time + 0.2; + b->endtime = time + 0.2; b->seed = rand (); VectorCopy (end, b->end); - if (b->entity != cl.viewentity) { + if (b->entity != ctx->playerEntity) { // this will be done in CL_UpdateBeams VectorCopy (start, b->start); - beam_setup (b, true); + beam_setup (b, true, time, ctx); } } -void -CL_ParseTEnt (void) +static void +parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, + TE_Effect type) { - byte type; dlight_t *dl; tent_obj_t *to; explosion_t *ex; int colorStart, colorLength; - int cnt = -1; - vec3_t pos; - sfx_t *spike_sound[] = { - cl_sfx_ric3, cl_sfx_ric3, cl_sfx_ric2, cl_sfx_ric1, - }; + quat_t color; + vec3_t position; + int count; + const char *name; - type = MSG_ReadByte (net_message); switch (type) { - case TE_WIZSPIKE: // spike hitting wall - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_WizSpikeEffect (pos); - S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); + case TE_NoEffect: + // invalid mapping, can't do anything break; - - case TE_KNIGHTSPIKE: // spike hitting wall - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_KnightSpikeEffect (pos); - S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); + case TE_Beam: + CL_ParseBeam (net_message, cl_mod_beam, time, ctx); break; - - case TE_SPIKE: // spike hitting wall - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_SpikeEffect (pos); - { - int i; - sfx_t *sound; - - i = (rand () % 20) - 16; - if (i >= 0) - sound = spike_sound[i]; - else - sound = cl_sfx_tink1; - S_StartSound (-1, 0, sound, pos, 1, 1); - } + case TE_Blood: + count = MSG_ReadByte (net_message) * 20; + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_BloodPuffEffect (position, count); break; + case TE_Explosion: + MSG_ReadCoordV (net_message, position); - case TE_SUPERSPIKE: // super spike hitting wall - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_SuperSpikeEffect (pos); - { - int i; - sfx_t *sound; - - i = (rand () % 20) - 16; - if (i >= 0) - sound = spike_sound[i]; - else - sound = cl_sfx_tink1; - S_StartSound (-1, 0, sound, pos, 1, 1); - } - break; - - case TE_EXPLOSION: // rocket explosion // particles - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_ParticleExplosion (pos); + r_funcs->particles->R_ParticleExplosion (position); // light dl = r_funcs->R_AllocDlight (0); if (dl) { - VectorCopy (pos, dl->origin); + VectorCopy (position, dl->origin); dl->radius = 350; - dl->die = cl.time + 0.5; + dl->die = time + 0.5; dl->decay = 300; QuatSet (0.86, 0.31, 0.24, 0.7, dl->color); + //FIXME? nq: QuatSet (1.0, 0.5, 0.25, 0.7, dl->color); } // sound - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); // sprite to = new_tent_object (); @@ -436,105 +403,201 @@ CL_ParseTEnt (void) ex = &to->to.ex; ex->tent = new_temp_entity (); - VectorCopy (pos, ex->tent->ent.origin); - ex->start = cl.time; + VectorCopy (position, ex->tent->ent.origin); + ex->start = time; //FIXME need better model management - if (!cl_spr_explod->cache.data) + if (!cl_spr_explod->cache.data) { cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); + } ex->tent->ent.renderer.model = cl_spr_explod; - CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true); + CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles); break; - - case TE_TAREXPLOSION: // tarbaby explosion - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_BlobExplosion (pos); - - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); - break; - - case TE_LIGHTNING1: // lightning bolts - CL_ParseBeam (cl_mod_bolt); - break; - - case TE_LIGHTNING2: // lightning bolts - CL_ParseBeam (cl_mod_bolt2); - break; - - case TE_LIGHTNING3: // lightning bolts - CL_ParseBeam (cl_mod_bolt3); - break; - - // PGM 01/21/97 - case TE_BEAM: // grappling hook beam - CL_ParseBeam (cl_mod_beam); - break; - // PGM 01/21/97 - - case TE_LAVASPLASH: - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_LavaSplash (pos); - break; - - case TE_TELEPORT: - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_TeleportSplash (pos); - break; - - case TE_EXPLOSION2: // color mapped explosion - MSG_ReadCoordV (net_message, pos); + case TE_Explosion2: + MSG_ReadCoordV (net_message, position); colorStart = MSG_ReadByte (net_message); colorLength = MSG_ReadByte (net_message); - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); - r_funcs->particles->R_ParticleExplosion2 (pos, colorStart, + S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); + r_funcs->particles->R_ParticleExplosion2 (position, colorStart, colorLength); dl = r_funcs->R_AllocDlight (0); if (!dl) break; - VectorCopy (pos, dl->origin); + VectorCopy (position, dl->origin); dl->radius = 350; - dl->die = cl.time + 0.5; + dl->die = time + 0.5; dl->decay = 300; colorStart = (colorStart + (rand () % colorLength)) * 3; VectorScale (&r_data->vid->palette[colorStart], 1.0 / 255.0, dl->color); dl->color[3] = 0.7; break; - - case TE_GUNSHOT: // bullet hitting wall - cnt = MSG_ReadByte (net_message) * 20; - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_GunshotEffect (pos, cnt); + case TE_Explosion3: + MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, color); // OUCH! + color[3] = 0.7; + r_funcs->particles->R_ParticleExplosion (position); + S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); + dl = r_funcs->R_AllocDlight (0); + if (dl) { + VectorCopy (position, dl->origin); + dl->radius = 350; + dl->die = time + 0.5; + dl->decay = 300; + QuatCopy (color, dl->color); + } break; - - case TE_BLOOD: // bullet hitting body - cnt = MSG_ReadByte (net_message) * 20; - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_BloodPuffEffect (pos, cnt); + case TE_Gunshot1: + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_GunshotEffect (position, 20); break; - - case TE_LIGHTNINGBLOOD: // lightning hitting body - MSG_ReadCoordV (net_message, pos); + case TE_Gunshot2: + count = MSG_ReadByte (net_message) * 20; + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_GunshotEffect (position, count); + break; + case TE_KnightSpike: + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_KnightSpikeEffect (position); + S_StartSound (-1, 0, cl_sfx_knighthit, position, 1, 1); + break; + case TE_LavaSplash: + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_LavaSplash (position); + break; + case TE_Lightning1: + CL_ParseBeam (net_message, cl_mod_bolt, time, ctx); + break; + case TE_Lightning2: + CL_ParseBeam (net_message, cl_mod_bolt2, time, ctx); + break; + case TE_Lightning3: + CL_ParseBeam (net_message, cl_mod_bolt3, time, ctx); + break; + case TE_Lightning4: + name = MSG_ReadString (net_message); + CL_ParseBeam (net_message, Mod_ForName (name, true), time, ctx); + break; + case TE_LightningBlood: + MSG_ReadCoordV (net_message, position); // light dl = r_funcs->R_AllocDlight (0); if (dl) { - VectorCopy (pos, dl->origin); + VectorCopy (position, dl->origin); dl->radius = 150; - dl->die = cl.time + 0.1; + dl->die = time + 0.1; dl->decay = 200; QuatSet (0.25, 0.40, 0.65, 1, dl->color); } - r_funcs->particles->R_LightningBloodEffect (pos); + r_funcs->particles->R_LightningBloodEffect (position); break; + case TE_Spike: + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_SpikeEffect (position); + { + int i; + sfx_t *sound; - default: - Sys_Error ("CL_ParseTEnt: bad type %d", type); + i = (rand () % 20) - 16; + if (i >= 0) { + sound = cl_sfx_ric[i]; + } else { + sound = cl_sfx_tink1; + } + S_StartSound (-1, 0, sound, position, 1, 1); + } + break; + case TE_SuperSpike: + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_SuperSpikeEffect (position); + { + int i; + sfx_t *sound; + + i = (rand () % 20) - 16; + if (i >= 0) { + sound = cl_sfx_ric[i]; + } else { + sound = cl_sfx_tink1; + } + S_StartSound (-1, 0, sound, position, 1, 1); + } + break; + case TE_TarExplosion: + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_BlobExplosion (position); + + S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); + break; + case TE_Teleport: + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_TeleportSplash (position); + break; + case TE_WizSpike: + MSG_ReadCoordV (net_message, position); + r_funcs->particles->R_WizSpikeEffect (position); + S_StartSound (-1, 0, cl_sfx_wizhit, position, 1, 1); + break; } } +// the effect type is a byte so a max of 256 values +static const TE_Effect nqEffects[256] = { + [TE_nqSpike] = TE_Spike, + [TE_nqSuperSpike] = TE_SuperSpike, + [TE_nqGunshot] = TE_Gunshot1, + [TE_nqExplosion] = TE_Explosion, + [TE_nqTarExplosion] = TE_TarExplosion, + [TE_nqLightning1] = TE_Lightning1, + [TE_nqLightning2] = TE_Lightning2, + [TE_nqWizSpike] = TE_WizSpike, + [TE_nqKnightSpike] = TE_KnightSpike, + [TE_nqLightning3] = TE_Lightning3, + [TE_nqLavaSplash] = TE_LavaSplash, + [TE_nqTeleport] = TE_Teleport, + [TE_nqExplosion2] = TE_Explosion2, + [TE_nqBeam] = TE_Beam, + [TE_nqExplosion3] = TE_Explosion3, + [TE_nqLightning4] = TE_Lightning4, +}; + +void +CL_ParseTEnt_nq (qmsg_t *net_message, double time, TEntContext_t *ctx) +{ + byte type = MSG_ReadByte (net_message); + parse_tent (net_message, time, ctx, nqEffects[type]); +} + +// the effect type is a byte so a max of 256 values +static const TE_Effect qwEffects[256] = { + [TE_qwSpike] = TE_Spike, + [TE_qwSuperSpike] = TE_SuperSpike, + [TE_qwGunshot] = TE_Gunshot2, + [TE_qwExplosion] = TE_Explosion, + [TE_qwTarExplosion] = TE_TarExplosion, + [TE_qwLightning1] = TE_Lightning1, + [TE_qwLightning2] = TE_Lightning2, + [TE_qwWizSpike] = TE_WizSpike, + [TE_qwKnightSpike] = TE_KnightSpike, + [TE_qwLightning3] = TE_Lightning3, + [TE_qwLavaSplash] = TE_LavaSplash, + [TE_qwTeleport] = TE_Teleport, + [TE_qwBlood] = TE_Blood, + [TE_qwLightningBlood] = TE_LightningBlood, + [TE_qwExplosion2] = TE_Explosion2, + [TE_qwBeam] = TE_Beam, +}; + +void +CL_ParseTEnt_qw (qmsg_t *net_message, double time, TEntContext_t *ctx) +{ + byte type = MSG_ReadByte (net_message); + parse_tent (net_message, time, ctx, qwEffects[type]); +} + static void -CL_UpdateBeams (void) +CL_UpdateBeams (double time, TEntContext_t *ctx) { tent_obj_t **to; beam_t *b; @@ -546,7 +609,7 @@ CL_UpdateBeams (void) b = &(*to)->to.beam; if (!b->endtime) continue; - if (!b->model || b->endtime < cl.time) { + if (!b->model || b->endtime < time) { tent_obj_t *_to; b->endtime = 0; beam_clear (b); @@ -559,26 +622,26 @@ CL_UpdateBeams (void) to = &(*to)->next; // if coming from the player, update the start position - if (b->entity == cl.viewentity) { + if (b->entity == ctx->playerEntity) { beam_clear (b); - VectorCopy (cl.simorg, b->start); - beam_setup (b, false); + VectorCopy (ctx->simorg, b->start); + beam_setup (b, false, time, ctx); } - seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) % + seed = b->seed + ((int) (time * BEAM_SEED_INTERVAL) % BEAM_SEED_INTERVAL); // add new entities for the lightning for (t = b->tents; t; t = t->next) { seed = seed * BEAM_SEED_PRIME; t->ent.angles[ROLL] = seed % 360; - CL_TransformEntity (&t->ent, t->ent.angles, true); + CL_TransformEntity (&t->ent, t->ent.angles); } } } static void -CL_UpdateExplosions (void) +CL_UpdateExplosions (double time, TEntContext_t *ctx) { int f; tent_obj_t **to; @@ -588,7 +651,7 @@ CL_UpdateExplosions (void) for (to = &cl_explosions; *to; ) { ex = &(*to)->to.ex; ent = &ex->tent->ent; - f = 10 * (cl.time - ex->start); + f = 10 * (time - ex->start); if (f >= ent->renderer.model->numframes) { tent_obj_t *_to; r_funcs->R_RemoveEfrags (ent); @@ -604,16 +667,39 @@ CL_UpdateExplosions (void) ent->animation.frame = f; if (!ent->visibility.efrag) { - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + r_funcs->R_AddEfrags (&ctx->worldModel->brush, ent); } } } void -CL_UpdateTEnts (void) +CL_UpdateTEnts (double time, TEntContext_t *ctx) { - CL_UpdateBeams (); - CL_UpdateExplosions (); + CL_UpdateBeams (time, ctx); + CL_UpdateExplosions (time, ctx); +} + +/* + CL_ParseParticleEffect + + Parse an effect out of the server message +*/ +void +CL_ParseParticleEffect (qmsg_t *net_message) +{ + int i, count, color; + vec3_t org, dir; + + MSG_ReadCoordV (net_message, org); + for (i = 0; i < 3; i++) + dir[i] = ((signed char) MSG_ReadByte (net_message)) * (15.0 / 16.0); + count = MSG_ReadByte (net_message); + color = MSG_ReadByte (net_message); + + if (count == 255) + r_funcs->particles->R_ParticleExplosion (org); + else + r_funcs->particles->R_RunParticleEffect (org, dir, color, count); } void @@ -633,7 +719,7 @@ CL_ClearProjectiles (void) Nails are passed as efficient temporary entities */ void -CL_ParseProjectiles (qboolean nail2) +CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) { tent_t *tent; tent_t *head = 0, **tail = &head; @@ -658,7 +744,7 @@ CL_ParseProjectiles (qboolean nail2) tail = &tent->next; pr = &tent->ent; - pr->renderer.model = cl.model_precache[cl_spikeindex]; + pr->renderer.model = cl_spike; pr->renderer.skin = 0; pr->origin[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096; pr->origin[1] = (((bits[1] >> 4) + (bits[2] << 4)) << 1) - 4096; @@ -666,9 +752,9 @@ CL_ParseProjectiles (qboolean nail2) pr->angles[0] = (bits[4] >> 4) * (360.0 / 16.0); pr->angles[1] = bits[5] * (360.0 / 256.0); pr->angles[2] = 0; - CL_TransformEntity (&tent->ent, tent->ent.angles, true); + CL_TransformEntity (&tent->ent, tent->ent.angles); - r_funcs->R_AddEfrags (&cl.worldmodel->brush, &tent->ent); + r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent); } *tail = cl_projectiles; diff --git a/nq/include/client.h b/nq/include/client.h index 817bebaf6..07c43ae87 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -304,10 +304,6 @@ void CL_Input_Init (void); void CL_SendCmd (void); void CL_SendMove (usercmd_t *cmd); -void CL_ParseParticleEffect (void); -void CL_ParseTEnt (void); -void CL_UpdateTEnts (void); - void CL_ClearState (void); int CL_ReadFromServer (void); @@ -344,13 +340,7 @@ void V_SetContentsColor (int contents); void V_PrepBlend (void); // cl_tent -void CL_TEnts_Init (void); -void CL_ClearTEnts (void); -void CL_Init_Entity (struct entity_s *ent); -void CL_ParseTEnt (void); void CL_SignonReply (void); -void CL_TransformEntity (struct entity_s *ent, const vec3_t - angles, qboolean force); void CL_RelinkEntities (void); void CL_ClearEnts (void); diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 2da0c7fb4..6caa9fe32 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -70,7 +70,7 @@ nq_server_LIB_DEPS=$(nq_server_LIBFILES) $(nq_common_LIBFILES) nq_source_libnq_client_a_SOURCES= \ nq/source/cl_chase.c nq/source/cl_cmd.c nq/source/cl_demo.c nq/source/cl_ents.c nq/source/cl_input.c nq/source/cl_main.c \ - nq/source/cl_screen.c nq/source/cl_parse.c nq/source/cl_tent.c nq/source/cl_view.c nq/source/sbar.c + nq/source/cl_screen.c nq/source/cl_parse.c nq/source/cl_view.c nq/source/sbar.c nq_source_libnq_server_a_SOURCES= \ nq/source/host.c nq/source/host_cmd.c nq/source/sv_cl_phys.c nq/source/sv_cvar.c nq/source/sv_main.c \ diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 933097913..3fdd3d0af 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -47,6 +47,8 @@ #include "compat.h" +#include "client/temp_entities.h" + #include "nq/include/chase.h" #include "nq/include/client.h" #include "nq/include/host.h" @@ -177,36 +179,6 @@ CL_LerpPoint (void) return frac; } -void -CL_TransformEntity (entity_t *ent, const vec3_t angles, qboolean force) -{ - union { - quat_t q; - vec4f_t v; - } rotation; - vec4f_t position; - vec4f_t scale; - - VectorCopy (ent->origin, position); - position[3] = 1; - VectorSet (ent->scale, ent->scale, ent->scale, scale); - scale[3] = 1; - if (VectorIsZero (angles)) { - QuatSet (0, 0, 0, 1, rotation.q); - } else { - vec3_t ang; - VectorCopy (angles, ang); - if (ent->renderer.model && ent->renderer.model->type == mod_alias) { - // stupid quake bug - // why, oh, why, do alias models pitch in the opposite direction - // to everything else? - ang[PITCH] = -ang[PITCH]; - } - AngleQuat (ang, rotation.q); - } - Transform_SetLocalTransform (ent->transform, scale, rotation.v, position); -} - static void CL_ModelEffects (entity_t *ent, int num, int glow_color) { @@ -392,7 +364,7 @@ CL_RelinkEntities (void) animation->pose1 = animation->pose2 = -1; VectorCopy (new->origin, ent->origin); if (!(model_flags & EF_ROTATE)) - CL_TransformEntity (ent, new->angles, true); + CL_TransformEntity (ent, new->angles); if (i != cl.viewentity || chase_active->int_val) { if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); @@ -410,7 +382,7 @@ CL_RelinkEntities (void) // assume a teleportation, not a motion VectorCopy (new->origin, ent->origin); if (!(model_flags & EF_ROTATE)) - CL_TransformEntity (ent, new->angles, true); + CL_TransformEntity (ent, new->angles); animation->pose1 = animation->pose2 = -1; } else { vec3_t angles, d; @@ -425,7 +397,7 @@ CL_RelinkEntities (void) d[j] += 360; } VectorMultAdd (old->angles, f, d, angles); - CL_TransformEntity (ent, angles, false); + CL_TransformEntity (ent, angles); } } if (i != cl.viewentity || chase_active->int_val) { @@ -445,7 +417,7 @@ CL_RelinkEntities (void) vec3_t angles; VectorCopy (new->angles, angles); angles[YAW] = bobjrotate; - CL_TransformEntity (ent, angles, false); + CL_TransformEntity (ent, angles); } CL_EntityEffects (i, ent, new); CL_NewDlight (i, ent->origin, new->effects, new->glow_size, diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index f31256138..25ff7bd39 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -52,6 +52,8 @@ #include "clview.h" #include "sbar.h" +#include "client/temp_entities.h" + #include "nq/include/chase.h" #include "nq/include/cl_skin.h" #include "nq/include/client.h" @@ -423,6 +425,10 @@ int CL_ReadFromServer (void) { int ret; + TEntContext_t tentCtx = { + {VectorExpand (cl_entities[cl.viewentity].origin), 1}, + cl.worldmodel, cl.viewentity + }; cl.oldtime = cl.time; cl.time += host_frametime; @@ -442,7 +448,7 @@ CL_ReadFromServer (void) Sys_Printf ("\n"); CL_RelinkEntities (); - CL_UpdateTEnts (); + CL_UpdateTEnts (cl.time, &tentCtx); // bring the links up to date return 0; diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 10ac2d4f5..260920d13 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -53,6 +53,8 @@ #include "QF/plugin/vid_render.h" +#include "client/temp_entities.h" + #include "compat.h" #include "sbar.h" @@ -591,7 +593,7 @@ CL_ParseUpdate (int bits) //VectorCopy (state->msg_origins[0], state->msg_origins[1]); //VectorCopy (state->msg_origins[0], ent->origin); //VectorCopy (state->msg_angles[0], state->msg_angles[1]); - //CL_TransformEntity (ent, state->msg_angles[0], true); + //CL_TransformEntity (ent, state->msg_angles[0]); //state->forcelink = true; cl_forcelink[num] = true; } @@ -793,7 +795,7 @@ CL_ParseStatic (int version) ent->renderer.colormod[3] = ENTALPHA_DECODE (baseline.alpha); ent->scale = baseline.scale / 16.0; VectorCopy (baseline.origin, ent->origin); - CL_TransformEntity (ent, baseline.angles, true); + CL_TransformEntity (ent, baseline.angles); r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } @@ -835,6 +837,11 @@ CL_ParseServerMessage (void) static dstring_t *stuffbuf; signon_t so; + TEntContext_t tentCtx = { + {VectorExpand (cl_entities[cl.viewentity].origin), 1}, + cl.worldmodel, cl.viewentity + }; + // if recording demos, copy the message out if (cl_shownet->int_val == 1) Sys_Printf ("%i ", net_message->message->cursize); @@ -1031,7 +1038,7 @@ CL_ParseServerMessage (void) break; case svc_particle: - CL_ParseParticleEffect (); + CL_ParseParticleEffect (net_message); break; case svc_damage: @@ -1051,7 +1058,7 @@ CL_ParseServerMessage (void) break; case svc_temp_entity: - CL_ParseTEnt (); + CL_ParseTEnt_nq (net_message, cl.time, &tentCtx); break; case svc_setpause: diff --git a/nq/source/cl_tent.c b/nq/source/cl_tent.c deleted file mode 100644 index 3a8a1b899..000000000 --- a/nq/source/cl_tent.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - cl_tent.c - - client side temporary entities - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include -#include - -#include "QF/entity.h" -#include "QF/model.h" -#include "QF/msg.h" -#include "QF/sound.h" -#include "QF/sys.h" - -#include "QF/plugin/vid_render.h" - -#include "compat.h" - -#include "nq/include/client.h" - -typedef struct tent_s { - struct tent_s *next; - entity_t ent; -} tent_t; - -#define TEMP_BATCH 64 -static tent_t *temp_entities = 0; - -typedef struct { - int entity; - struct model_s *model; - float endtime; - vec3_t start, end; - tent_t *tents; - int seed; -} beam_t; - -#define BEAM_SEED_INTERVAL 72 -#define BEAM_SEED_PRIME 3191 - -typedef struct { - float start; - tent_t *tent; -} explosion_t; - -typedef struct tent_obj_s { - struct tent_obj_s *next; - union { - beam_t beam; - explosion_t ex; - } to; -} tent_obj_t; - -static tent_obj_t *tent_objects; -static tent_obj_t *cl_beams; -static tent_obj_t *cl_explosions; - -static sfx_t *cl_sfx_wizhit; -static sfx_t *cl_sfx_knighthit; -static sfx_t *cl_sfx_tink1; -static sfx_t *cl_sfx_ric1; -static sfx_t *cl_sfx_ric2; -static sfx_t *cl_sfx_ric3; -static sfx_t *cl_sfx_r_exp3; - -static model_t *cl_mod_beam; -static model_t *cl_mod_bolt; -static model_t *cl_mod_bolt2; -static model_t *cl_mod_bolt3; -static model_t *cl_spr_explod; - -static void -CL_TEnts_Precache (int phase) -{ - if (!phase) - return; - cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav"); - cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav"); - cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav"); - cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav"); - cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav"); - cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav"); - cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav"); - - cl_mod_bolt = Mod_ForName ("progs/bolt.mdl", true); - cl_mod_bolt2 = Mod_ForName ("progs/bolt2.mdl", true); - cl_mod_bolt3 = Mod_ForName ("progs/bolt3.mdl", true); - cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); - cl_mod_beam = Mod_ForName ("progs/beam.mdl", false); - if (!cl_mod_beam) - cl_mod_beam = cl_mod_bolt; -} - -void -CL_TEnts_Init (void) -{ - QFS_GamedirCallback (CL_TEnts_Precache); - CL_TEnts_Precache (1); -} - -void -CL_Init_Entity (entity_t *ent) -{ - if (ent->transform) { - Transform_Delete (ent->transform); - } - memset (ent, 0, sizeof (*ent)); - - ent->transform = Transform_New (0); - ent->renderer.skin = 0; - QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); - ent->scale = 1.0; - ent->animation.pose1 = ent->animation.pose2 = -1; -} - -static tent_t * -new_temp_entity (void) -{ - tent_t *tent; - if (!temp_entities) { - int i; - - temp_entities = malloc (TEMP_BATCH * sizeof (tent_t)); - for (i = 0; i < TEMP_BATCH - 1; i++) { - temp_entities[i].next = &temp_entities[i + 1]; - temp_entities[i].ent.transform = 0; - } - temp_entities[i].next = 0; - temp_entities[i].ent.transform = 0; - } - tent = temp_entities; - temp_entities = tent->next; - tent->next = 0; - CL_Init_Entity (&tent->ent); - return tent; -} - -static void -free_temp_entities (tent_t *tents) -{ - tent_t **t = &tents; - - while (*t) - t = &(*t)->next; - *t = temp_entities; - temp_entities = tents; -} - -static tent_obj_t * -new_tent_object (void) -{ - tent_obj_t *tobj; - if (!tent_objects) { - int i; - - tent_objects = malloc (TEMP_BATCH * sizeof (tent_obj_t)); - for (i = 0; i < TEMP_BATCH - 1; i++) - tent_objects[i].next = &tent_objects[i + 1]; - tent_objects[i].next = 0; - } - tobj = tent_objects; - tent_objects = tobj->next; - tobj->next = 0; - return tobj; -} - -static void -free_tent_objects (tent_obj_t *tobjs) -{ - tent_obj_t **t = &tobjs; - - while (*t) - t = &(*t)->next; - *t = tent_objects; - tent_objects = tobjs; -} - -void -CL_ClearTEnts (void) -{ - tent_t *t; - tent_obj_t *to; - - for (to = cl_beams; to; to = to->next) { - for (t = to->to.beam.tents; t; t = t->next) - t->ent.visibility.efrag = 0; - free_temp_entities (to->to.beam.tents); - } - free_tent_objects (cl_beams); - cl_beams = 0; - - for (to = cl_explosions; to; to = to->next) { - for (t = to->to.ex.tent; t; t = t->next) - t->ent.visibility.efrag = 0; - free_temp_entities (to->to.ex.tent); - } - free_tent_objects (cl_explosions); - cl_explosions = 0; -} - -static inline void -beam_clear (beam_t *b) -{ - if (b->tents) { - tent_t *t; - - for (t = b->tents; t; t = t->next) { - r_funcs->R_RemoveEfrags (&t->ent); - t->ent.visibility.efrag = 0; - } - free_temp_entities (b->tents); - b->tents = 0; - } -} - -static inline void -beam_setup (beam_t *b, qboolean transform) -{ - tent_t *tent; - float forward, pitch, yaw, d; - int ent_count; - vec3_t dist, org, ang; - unsigned seed; - - // calculate pitch and yaw - VectorSubtract (b->end, b->start, dist); - - if (dist[1] == 0 && dist[0] == 0) { - yaw = 0; - if (dist[2] > 0) - pitch = 90; - else - pitch = 270; - } else { - yaw = (int) (atan2 (dist[1], dist[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - - forward = sqrt (dist[0] * dist[0] + dist[1] * dist[1]); - pitch = (int) (atan2 (dist[2], forward) * 180 / M_PI); - if (pitch < 0) - pitch += 360; - } - - // add new entities for the lightning - VectorCopy (b->start, org); - d = VectorNormalize (dist); - VectorScale (dist, 30, dist); - ent_count = ceil (d / 30); - d = 0; - - seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) % - BEAM_SEED_INTERVAL); - - ang[ROLL] = 0; - while (ent_count--) { - tent = new_temp_entity (); - tent->next = b->tents; - b->tents = tent; - - VectorMultAdd (org, d, dist, tent->ent.origin); - d += 1.0; - tent->ent.renderer.model = b->model; - ang[PITCH] = pitch; - ang[YAW] = yaw; - if (transform) { - seed = seed * BEAM_SEED_PRIME; - ang[ROLL] = seed % 360; - CL_TransformEntity (&tent->ent, ang, true); - } - VectorCopy (ang, tent->ent.angles); - r_funcs->R_AddEfrags (&cl.worldmodel->brush, &tent->ent); - } -} - -static void -CL_ParseBeam (model_t *m) -{ - tent_obj_t *to; - beam_t *b; - int ent; - vec3_t start, end; - - ent = MSG_ReadShort (net_message); - - MSG_ReadCoordV (net_message, start); - MSG_ReadCoordV (net_message, end); - - to = 0; - if (ent) { - for (to = cl_beams; to; to = to->next) - if (to->to.beam.entity == ent) - break; - } - if (!to) { - to = new_tent_object (); - to->next = cl_beams; - cl_beams = to; - to->to.beam.tents = 0; - to->to.beam.entity = ent; - } - b = &to->to.beam; - - beam_clear (b); - b->model = m; - b->endtime = cl.time + 0.2; - b->seed = rand (); - VectorCopy (end, b->end); - if (b->entity != cl.viewentity) { - // this will be done in CL_UpdateBeams - VectorCopy (start, b->start); - beam_setup (b, true); - } -} - -void -CL_ParseTEnt (void) -{ - byte type; - dlight_t *dl; - tent_obj_t *to; - explosion_t *ex; - int colorStart, colorLength; - quat_t col; - vec3_t pos; - sfx_t *spike_sound[] = { - cl_sfx_ric3, cl_sfx_ric3, cl_sfx_ric2, cl_sfx_ric1, - }; - - type = MSG_ReadByte (net_message); - switch (type) { - case TE_WIZSPIKE: // spike hitting wall - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_WizSpikeEffect (pos); - S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); - break; - - case TE_KNIGHTSPIKE: // spike hitting wall - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_KnightSpikeEffect (pos); - S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); - break; - - case TE_SPIKE: // spike hitting wall - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_SpikeEffect (pos); - { - int i; - sfx_t *sound; - - i = (rand () % 20) - 16; - if (i >= 0) - sound = spike_sound[i]; - else - sound = cl_sfx_tink1; - S_StartSound (-1, 0, sound, pos, 1, 1); - } - break; - - case TE_SUPERSPIKE: // super spike hitting wall - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_SuperSpikeEffect (pos); - { - int i; - sfx_t *sound; - - i = (rand () % 20) - 16; - if (i >= 0) - sound = spike_sound[i]; - else - sound = cl_sfx_tink1; - S_StartSound (-1, 0, sound, pos, 1, 1); - } - break; - - case TE_EXPLOSION: // rocket explosion - // particles - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_ParticleExplosion (pos); - - // light - dl = r_funcs->R_AllocDlight (0); - if (dl) { - VectorCopy (pos, dl->origin); - dl->radius = 350; - dl->die = cl.time + 0.5; - dl->decay = 300; - QuatSet (1.0, 0.5, 0.25, 0.7, dl->color); - } - - // sound - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); - - // sprite - to = new_tent_object (); - to->next = cl_explosions; - cl_explosions = to; - ex = &to->to.ex; - ex->tent = new_temp_entity (); - - VectorCopy (pos, ex->tent->ent.origin); - ex->start = cl.time; - //FIXME need better model management - if (!cl_spr_explod->cache.data) - cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); - ex->tent->ent.renderer.model = cl_spr_explod; - CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true); - break; - - case TE_TAREXPLOSION: // tarbaby explosion - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_BlobExplosion (pos); - - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); - break; - - case TE_LIGHTNING1: // lightning bolts - CL_ParseBeam (cl_mod_bolt); - break; - - case TE_LIGHTNING2: // lightning bolts - CL_ParseBeam (cl_mod_bolt2); - break; - - case TE_LIGHTNING3: // lightning bolts - CL_ParseBeam (cl_mod_bolt3); - break; - - case TE_LIGHTNING4NEH: // Nehahra lightning - CL_ParseBeam (Mod_ForName (MSG_ReadString (net_message), true)); - break; - - // PGM 01/21/97 - case TE_BEAM: // grappling hook beam - CL_ParseBeam (cl_mod_beam); - break; - // PGM 01/21/97 - - case TE_LAVASPLASH: - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_LavaSplash (pos); - break; - - case TE_TELEPORT: - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_TeleportSplash (pos); - break; - - case TE_EXPLOSION2: // color mapped explosion - MSG_ReadCoordV (net_message, pos); - colorStart = MSG_ReadByte (net_message); - colorLength = MSG_ReadByte (net_message); - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); - r_funcs->particles->R_ParticleExplosion2 (pos, colorStart, - colorLength); - dl = r_funcs->R_AllocDlight (0); - if (!dl) - break; - VectorCopy (pos, dl->origin); - dl->radius = 350; - dl->die = cl.time + 0.5; - dl->decay = 300; - colorStart = (colorStart + (rand () % colorLength)) * 3; - VectorScale (&r_data->vid->palette[colorStart], 1.0 / 255.0, - dl->color); - dl->color[3] = 0.7; - break; - - case TE_EXPLOSION3: // Nehahra colored light explosion - MSG_ReadCoordV (net_message, pos); - MSG_ReadCoordV (net_message, col); // OUCH! - col[3] = 0.7; - r_funcs->particles->R_ParticleExplosion (pos); - S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); - dl = r_funcs->R_AllocDlight (0); - if (dl) { - VectorCopy (pos, dl->origin); - dl->radius = 350; - dl->die = cl.time + 0.5; - dl->decay = 300; - QuatCopy (col, dl->color); - } - break; - - case TE_GUNSHOT: // bullet hitting wall - MSG_ReadCoordV (net_message, pos); - r_funcs->particles->R_GunshotEffect (pos, 20); - break; - - default: - Sys_Error ("CL_ParseTEnt: bad type %d", type); - } -} - -static void -CL_UpdateBeams (void) -{ - tent_obj_t **to; - beam_t *b; - unsigned seed; - tent_t *t; - - // update lightning - for (to = &cl_beams; *to; ) { - b = &(*to)->to.beam; - if (!b->endtime) - continue; - if (!b->model || b->endtime < cl.time) { - tent_obj_t *_to; - b->endtime = 0; - beam_clear (b); - _to = *to; - *to = _to->next; - _to->next = tent_objects; - tent_objects = _to; - continue; - } - to = &(*to)->next; - - // if coming from the player, update the start position - if (b->entity == cl.viewentity) { - beam_clear (b); - VectorCopy (cl_entities[cl.viewentity].origin, b->start); - beam_setup (b, false); - } - - seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) % - BEAM_SEED_INTERVAL); - - // add new entities for the lightning - for (t = b->tents; t; t = t->next) { - seed = seed * BEAM_SEED_PRIME; - t->ent.angles[ROLL] = seed % 360; - CL_TransformEntity (&t->ent, t->ent.angles, true); - } - } -} - -static void -CL_UpdateExplosions (void) -{ - int f; - tent_obj_t **to; - explosion_t *ex; - entity_t *ent; - - for (to = &cl_explosions; *to; ) { - ex = &(*to)->to.ex; - ent = &ex->tent->ent; - f = 10 * (cl.time - ex->start); - if (f >= ent->renderer.model->numframes) { - tent_obj_t *_to; - r_funcs->R_RemoveEfrags (ent); - ent->visibility.efrag = 0; - free_temp_entities (ex->tent); - _to = *to; - *to = _to->next; - _to->next = tent_objects; - tent_objects = _to; - continue; - } - to = &(*to)->next; - - ent->animation.frame = f; - if (!ent->visibility.efrag) - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); - } -} - -void -CL_UpdateTEnts (void) -{ - CL_UpdateBeams (); - CL_UpdateExplosions (); -} - -/* - CL_ParseParticleEffect - - Parse an effect out of the server message -*/ -void -CL_ParseParticleEffect (void) -{ - int i, count, color; - vec3_t org, dir; - - MSG_ReadCoordV (net_message, org); - for (i = 0; i < 3; i++) - dir[i] = ((signed char) MSG_ReadByte (net_message)) * (15.0 / 16.0); - count = MSG_ReadByte (net_message); - color = MSG_ReadByte (net_message); - - if (count == 255) - r_funcs->particles->R_ParticleExplosion (org); - else - r_funcs->particles->R_RunParticleEffect (org, dir, color, count); -} diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index 132df122f..e6812a263 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -728,7 +728,7 @@ V_CalcRefdef (void) if (cl.chase && chase_active->int_val) Chase_Update (); - CL_TransformEntity (view, view->angles, true); + CL_TransformEntity (view, view->angles); } /* diff --git a/qw/include/Makemodule.am b/qw/include/Makemodule.am index 2f5076b12..c30d5decf 100644 --- a/qw/include/Makemodule.am +++ b/qw/include/Makemodule.am @@ -11,7 +11,6 @@ EXTRA_DIST += \ qw/include/cl_pred.h \ qw/include/cl_skin.h \ qw/include/cl_slist.h \ - qw/include/cl_tent.h \ qw/include/client.h \ qw/include/crudefile.h \ qw/include/game.h \ diff --git a/qw/include/cl_ents.h b/qw/include/cl_ents.h index 275cd04f6..b56e162d9 100644 --- a/qw/include/cl_ents.h +++ b/qw/include/cl_ents.h @@ -34,11 +34,9 @@ void CL_SetSolidPlayers (int playernum); void CL_ClearPredict (void); void CL_SetUpPlayerPrediction(qboolean dopred); -void CL_TransformEntity (struct entity_s * ent, const vec3_t angles, - qboolean force); +void CL_ClearEnts (void); void CL_EmitEntities (void); void CL_ClearProjectiles (void); -void CL_ParseProjectiles (qboolean nail2); void CL_ParsePacketEntities (qboolean delta); void CL_SetSolidEntities (void); void CL_ParsePlayerinfo (void); diff --git a/qw/include/cl_parse.h b/qw/include/cl_parse.h index 4dd3646c6..b624dd0d3 100644 --- a/qw/include/cl_parse.h +++ b/qw/include/cl_parse.h @@ -40,7 +40,6 @@ extern int parsecountmod; extern double parsecounttime; extern int cl_playerindex; extern int cl_flagindex; -extern int cl_spikeindex; extern int viewentity; extern int cl_h_playerindex; extern int cl_gib1index; diff --git a/qw/include/cl_tent.h b/qw/include/cl_tent.h deleted file mode 100644 index 71af54705..000000000 --- a/qw/include/cl_tent.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - client.h - - Client definitions - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ - -#ifndef _CL_TENT_H -#define _CL_TENT_H - -void CL_TEnts_Init (void); -void CL_ClearEnts (void); -void CL_ClearTEnts (void); -void CL_Init_Entity (struct entity_s *ent); -void CL_ParseTEnt (void); -void CL_UpdateTEnts (void); - -#endif diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 739789020..00e30b4bc 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -103,7 +103,7 @@ qw_source_libqw_client_a_SOURCES= \ qw/source/cl_cam.c qw/source/cl_chase.c qw/source/cl_chat.c qw/source/cl_cmd.c qw/source/cl_cvar.c qw/source/cl_demo.c \ qw/source/cl_entparse.c qw/source/cl_ents.c qw/source/cl_http.c qw/source/cl_input.c qw/source/cl_main.c qw/source/cl_ngraph.c \ qw/source/cl_parse.c qw/source/cl_pred.c qw/source/cl_rss.c qw/source/cl_screen.c qw/source/cl_skin.c qw/source/cl_slist.c \ - qw/source/cl_tent.c qw/source/cl_view.c \ + qw/source/cl_view.c \ qw/source/locs.c qw/source/sbar.c qw/source/teamplay.c # Software-rendering clients diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 2d130574d..3a3d67264 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -45,6 +45,8 @@ #include "compat.h" #include "clview.h" +#include "client/temp_entities.h" + #include "qw/msg_ucmd.h" #include "qw/pmove.h" #include "qw/bothdefs.h" @@ -54,7 +56,6 @@ #include "qw/include/cl_main.h" #include "qw/include/cl_parse.h" #include "qw/include/cl_pred.h" -#include "qw/include/cl_tent.h" #include "qw/include/host.h" static struct predicted_player { diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index d294f9981..11acacaf2 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -47,6 +47,8 @@ #include "clview.h" #include "d_iface.h" +#include "client/temp_entities.h" + #include "qw/bothdefs.h" #include "qw/msg_ucmd.h" #include "qw/pmove.h" @@ -57,7 +59,6 @@ #include "qw/include/cl_main.h" #include "qw/include/cl_parse.h" #include "qw/include/cl_pred.h" -#include "qw/include/cl_tent.h" #include "qw/include/host.h" entity_t cl_player_ents[MAX_CLIENTS]; @@ -170,36 +171,6 @@ is_gib (entity_state_t *s1) return 0; } -void -CL_TransformEntity (entity_t *ent, const vec3_t angles, qboolean force) -{ - union { - quat_t q; - vec4f_t v; - } rotation; - vec4f_t position; - vec4f_t scale; - - VectorCopy (ent->origin, position); - position[3] = 1; - VectorSet (ent->scale, ent->scale, ent->scale, scale); - scale[3] = 1; - if (VectorIsZero (angles)) { - QuatSet (0, 0, 0, 1, rotation.q); - } else { - vec3_t ang; - VectorCopy (angles, ang); - if (ent->renderer.model && ent->renderer.model->type == mod_alias) { - // stupid quake bug - // why, oh, why, do alias models pitch in the opposite direction - // to everything else? - ang[PITCH] = -ang[PITCH]; - } - AngleQuat (ang, rotation.q); - } - Transform_SetLocalTransform (ent->transform, scale, rotation.v, position); -} - static void CL_ModelEffects (entity_t *ent, int num, int glow_color) { @@ -342,7 +313,7 @@ CL_LinkPacketEntities (void) animation->pose1 = animation->pose2 = -1; VectorCopy (new->origin, ent->origin); if (!(renderer->model->flags & EF_ROTATE)) - CL_TransformEntity (ent, new->angles, true); + CL_TransformEntity (ent, new->angles); if (i != cl.viewentity || chase_active->int_val) { if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); @@ -360,7 +331,7 @@ CL_LinkPacketEntities (void) // assume a teleportation, not a motion VectorCopy (new->origin, ent->origin); if (!(renderer->model->flags & EF_ROTATE)) { - CL_TransformEntity (ent, new->angles, true); + CL_TransformEntity (ent, new->angles); } animation->pose1 = animation->pose2 = -1; } else { @@ -376,7 +347,7 @@ CL_LinkPacketEntities (void) d[j] += 360; } VectorMultAdd (old->angles, f, d, angles); - CL_TransformEntity (ent, angles, false); + CL_TransformEntity (ent, angles); } } if (i != cl.viewentity || chase_active->int_val) { @@ -400,7 +371,7 @@ CL_LinkPacketEntities (void) angles[PITCH] = 0; angles[YAW] = anglemod (100 * cl.time); angles[ROLL] = 0; - CL_TransformEntity (ent, angles, false); + CL_TransformEntity (ent, angles); } //CL_EntityEffects (i, ent, new); //CL_NewDlight (i, ent->origin, new->effects, 0, 0); @@ -567,7 +538,7 @@ CL_LinkPlayers (void) ent->animation.frame = state->pls.frame; ent->renderer.skinnum = state->pls.skinnum; - CL_TransformEntity (ent, ang, false); + CL_TransformEntity (ent, ang); ent->renderer.min_light = 0; ent->renderer.fullbright = 0; @@ -611,9 +582,13 @@ CL_EmitEntities (void) if (!cl.validsequence) return; + TEntContext_t tentCtx = { + {VectorExpand (cl.simorg), 1}, cl.worldmodel, cl.viewentity + }; + CL_LinkPlayers (); CL_LinkPacketEntities (); - CL_UpdateTEnts (); + CL_UpdateTEnts (cl.time, &tentCtx); if (cl_draw_locs->int_val) { //FIXME custom ent rendering code would be nice dlight_t *dl; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 5fcf0364e..656d6eb57 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -96,6 +96,8 @@ #include "compat.h" #include "sbar.h" +#include "client/temp_entities.h" + #include "qw/bothdefs.h" #include "qw/pmove.h" @@ -110,7 +112,6 @@ #include "qw/include/cl_pred.h" #include "qw/include/cl_skin.h" #include "qw/include/cl_slist.h" -#include "qw/include/cl_tent.h" #include "qw/include/client.h" #include "qw/include/game.h" #include "qw/include/host.h" diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 2523f8feb..2266d1029 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -65,6 +65,8 @@ #include "clview.h" #include "sbar.h" +#include "client/temp_entities.h" + #include "qw/bothdefs.h" #include "qw/pmove.h" #include "qw/protocol.h" @@ -77,7 +79,6 @@ #include "qw/include/cl_main.h" #include "qw/include/cl_parse.h" #include "qw/include/cl_skin.h" -#include "qw/include/cl_tent.h" #include "qw/include/client.h" #include "qw/include/host.h" #include "qw/include/map_cfg.h" @@ -161,7 +162,7 @@ int oldparsecountmod; int parsecountmod; double parsecounttime; -int cl_spikeindex, cl_playerindex, cl_flagindex; +int cl_playerindex, cl_flagindex; int cl_h_playerindex, cl_gib1index, cl_gib2index, cl_gib3index; int packet_latency[NET_TIMINGS]; @@ -437,7 +438,6 @@ Sound_NextDownload (void) // done with sounds, request models now memset (cl.model_precache, 0, sizeof (cl.model_precache)); cl_playerindex = -1; - cl_spikeindex = -1; cl_flagindex = -1; cl_h_playerindex = -1; cl_gib1index = cl_gib2index = cl_gib3index = -1; @@ -906,9 +906,7 @@ CL_ParseModellist (void) Host_Error ("Server sent too many model_precache"); strcpy (cl.model_name[cl.nummodels], str); - if (!strcmp (cl.model_name[cl.nummodels], "progs/spike.mdl")) - cl_spikeindex = cl.nummodels; - else if (!strcmp (cl.model_name[cl.nummodels], "progs/player.mdl")) + if (!strcmp (cl.model_name[cl.nummodels], "progs/player.mdl")) cl_playerindex = cl.nummodels; else if (!strcmp (cl.model_name[cl.nummodels], "progs/flag.mdl")) cl_flagindex = cl.nummodels; @@ -984,7 +982,7 @@ CL_ParseStatic (void) ent->renderer.skinnum = es.skinnum; VectorCopy (es.origin, ent->origin); - CL_TransformEntity (ent, es.angles, true); + CL_TransformEntity (ent, es.angles); r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } @@ -1305,6 +1303,9 @@ CL_ParseServerMessage (void) int cmd = 0, i, j; const char *str; static dstring_t *stuffbuf; + TEntContext_t tentCtx = { + {VectorExpand (cl.simorg), 1}, cl.worldmodel, cl.viewentity + }; received_framecount = host_framecount; cl.last_servermessage = realtime; @@ -1507,7 +1508,7 @@ CL_ParseServerMessage (void) break; case svc_temp_entity: - CL_ParseTEnt (); + CL_ParseTEnt_qw (net_message, cl.time, &tentCtx); break; case svc_setpause: @@ -1639,7 +1640,7 @@ CL_ParseServerMessage (void) break; case svc_nails: - CL_ParseProjectiles (false); + CL_ParseProjectiles (net_message, false, &tentCtx); break; case svc_chokecount: // some preceding packets were choked @@ -1690,7 +1691,7 @@ CL_ParseServerMessage (void) break; case svc_nails2: // FIXME from qwex - CL_ParseProjectiles (true); + CL_ParseProjectiles (net_message, true, &tentCtx); break; } } diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 59e7920cd..08d4dd501 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -731,7 +731,7 @@ V_CalcRefdef (void) if (cl.chase && chase_active->int_val) Chase_Update (); - CL_TransformEntity (view, view->angles, true); + CL_TransformEntity (view, view->angles); } static void From 693225a16fac7d5e99e87db1ff59d80e50bd293b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Mar 2021 18:05:12 +0900 Subject: [PATCH 1366/3664] [util] Add a fixme for a comment The code itself is fine, but the comment is rubbish because it's confusing, though essentially correct. --- libs/util/mathlib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 2d547f756..33eae277d 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -501,6 +501,8 @@ BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, plane_t *p) #endif /* + FIXME these comments are a confused mess (the code is fine) + angles is a left(?) handed system: 'pitch yaw roll' with x (pitch) axis to the right, y (yaw) axis up and z (roll) axis forward. From 56d84ef63ecaf9ae399027e5dad1f680925842b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Mar 2021 18:35:35 +0900 Subject: [PATCH 1367/3664] [gl] Fix the compressed sprites Seems to be an ancient bug. --- libs/video/renderer/gl/gl_mod_sprite.c | 40 ++++++++++++++------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index b6ce25f22..d0dd91444 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -105,7 +105,7 @@ R_DrawSpriteModel_f (entity_t *e) { float modelalpha, color[4]; vec4f_t up = {}, right = {}; - vec4f_t origin, point1, point2; + vec4f_t origin, point; msprite_t *psprite; mspriteframe_t *frame; @@ -140,23 +140,23 @@ R_DrawSpriteModel_f (entity_t *e) qfglColor4fv (color); origin = Transform_GetWorldPosition (e->transform); - point1 = origin + frame->down * up + frame->left * right; - point2 = origin + frame->up * up + frame->left * right; + point = origin + frame->down * up + frame->left * right; qfglTexCoord2f (0, 1); - qfglVertex3fv (&point1[0]); + qfglVertex3fv (&point[0]); + point = origin + frame->up * up + frame->left * right; qfglTexCoord2f (0, 0); - qfglVertex3fv (&point2[0]); + qfglVertex3fv (&point[0]); - point2 += frame->right * right; - point1 += frame->right * right; + point = origin + frame->up * up + frame->right * right; qfglTexCoord2f (1, 0); - qfglVertex3fv (&point2[0]); + qfglVertex3fv (&point[0]); + point = origin + frame->down * up + frame->right * right; qfglTexCoord2f (1, 1); - qfglVertex3fv (&point1[0]); + qfglVertex3fv (&point[0]); qfglEnd (); @@ -169,7 +169,7 @@ R_DrawSpriteModel_VA_f (entity_t *e) { unsigned char modelalpha, color[4]; vec4f_t up = {}, right = {}; - vec4f_t origin, point1, point2; + vec4f_t origin, point; int i; // unsigned int vacount; msprite_t *psprite; @@ -212,16 +212,18 @@ R_DrawSpriteModel_VA_f (entity_t *e) qfglDepthMask (GL_FALSE); origin = Transform_GetWorldPosition (e->transform); - point1 = origin + frame->down * up + frame->left * right; - VectorCopy (point1, VA[0].vertex); - point2 = origin + frame->up * up + frame->left * right; - VectorCopy (point2, VA[1].vertex); + point = origin + frame->down * up + frame->left * right; + VectorCopy (point, VA[0].vertex); - point2 += frame->right * right; - point1 += frame->right * right; - VectorCopy (point2, VA[2].vertex); - VectorCopy (point1, VA[3].vertex); + point = origin + frame->up * up + frame->left * right; + VectorCopy (point, VA[1].vertex); + + point = origin + frame->up * up + frame->right * right; + VectorCopy (point, VA[2].vertex); + + point = origin + frame->down * up + frame->right * right; + VectorCopy (point, VA[3].vertex); // VA += 4; // vacount += 4; @@ -242,7 +244,7 @@ gl_R_InitSprites (void) int i; if (r_init) { - if (gl_va_capable) { // 0 == gl_va_capable + if (gl_va_capable) { gl_R_DrawSpriteModel = R_DrawSpriteModel_VA_f; #if 0 From 169e0192f2f851d4b01044e2a7e460e517c28032 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Mar 2021 19:06:15 +0900 Subject: [PATCH 1368/3664] [gl] Use the correct value for sqrt(0.5) 707106781 looks right, but isn't quite. --- libs/video/renderer/gl/gl_mod_alias.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 4b90ba54a..8e4670a77 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -701,10 +701,10 @@ gl_R_DrawAliasModel (entity_t *e) qfglColor4ubv (color_black); } //FIXME fully vectorize - vec4f_t vec = { 707106781, 0, 707106781, 0 }; + vec4f_t vec = { 0.707106781, 0, 0.707106781, 0 }; Transform_GetWorldMatrix (e->transform, shadow_mat); mat4ftranspose (shadow_mat, shadow_mat); - vec = mvmulf (shadow_mat, vec); + vec = m3vmulf (shadow_mat, vec); VectorCopy (vec, shadevector); if (vo->tex_coord) GL_DrawAliasShadowTri (paliashdr, vo); From 5949753579c32b0d477890bb4bb5e88b6e76fd34 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Mar 2021 19:40:19 +0900 Subject: [PATCH 1369/3664] Make m3vmulf return v[3] unchanged --- include/QF/simd/mat4f.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/simd/mat4f.h b/include/QF/simd/mat4f.h index 719e4c561..658cf582b 100644 --- a/include/QF/simd/mat4f.h +++ b/include/QF/simd/mat4f.h @@ -104,7 +104,7 @@ m3vmulf (const mat4f_t m, vec4f_t v) { vec4f_t w; w = m[0] * v[0] + m[1] * v[1] + m[2] * v[2]; - w[3] = 1; + w[3] = v[3]; return w; } From 62cce7f98c39b41cae345b59afe9f69fee05de7c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Mar 2021 21:15:53 +0900 Subject: [PATCH 1370/3664] [gl] Remove some more warts seeing ptexels and pixels together is very confusing --- libs/models/gl_model_fullbright.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libs/models/gl_model_fullbright.c b/libs/models/gl_model_fullbright.c index 60df0d50c..6635cbef5 100644 --- a/libs/models/gl_model_fullbright.c +++ b/libs/models/gl_model_fullbright.c @@ -43,29 +43,28 @@ int Mod_Fullbright (byte *skin, int width, int height, const char *name) { - byte *ptexels; + byte *texels; int pixels; int texnum = 0; pixels = width * height; -// ptexels = Hunk_Alloc(s); - ptexels = malloc (pixels); - SYS_CHECKMEM (ptexels); + texels = malloc (pixels); + SYS_CHECKMEM (texels); // Check for fullbright pixels - if (Mod_CalcFullbright (skin, ptexels, pixels)) { + if (Mod_CalcFullbright (skin, texels, pixels)) { //FIXME black should be transparent for fullbrights (or just fix //fullbright rendering in gl) + Sys_MaskPrintf (SYS_DEV, "FB Model ID: '%s'\n", name); for (int i = 0; i < pixels; i++) { - if (!ptexels[i]) { - ptexels[i] = 255; + if (!texels[i]) { + texels[i] = 255; } } - Sys_MaskPrintf (SYS_DEV, "FB Model ID: '%s'\n", name); - texnum = GL_LoadTexture (name, width, height, ptexels, true, true, 1); + texnum = GL_LoadTexture (name, width, height, texels, true, true, 1); } - free (ptexels); + free (texels); return texnum; } From c05a15dec5caf897e3fa73a5829be0c133f4fb46 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Mar 2021 21:17:34 +0900 Subject: [PATCH 1371/3664] [glsl] Use vec4f_t in a few more places No idea if it makes a noticeable speed difference, but it makes a huge readability difference. --- libs/video/renderer/glsl/glsl_sprite.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 7582e9db3..63704ebfa 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -183,20 +183,20 @@ static void make_quad (mspriteframe_t *frame, vec4f_t vpn, vec4f_t vright, vec4f_t vup, float verts[6][3]) { - vec3_t left, up, right, down; - vec3_t ul, ur, ll, lr; + vec4f_t left, up, right, down; + vec4f_t ul, ur, ll, lr; // build the sprite poster in worldspace // first, rotate the sprite axes into world space - VectorScale (vright, frame->right, right); - VectorScale (vup, frame->up, up); - VectorScale (vright, frame->left, left); - VectorScale (vup, frame->down, down); + right = frame->right * vright; + up = frame->up * vup; + left = frame->left * vright; + down = frame->down * vup; // next, build the sprite corners from the axes - VectorAdd (up, left, ul); - VectorAdd (up, right, ur); - VectorAdd (down, left, ll); - VectorAdd (down, right, lr); + ul = up + left; + ur = up + right; + ll = down + left; + lr = down + right; // finally, translate the sprite corners, creating two triangles VectorAdd (currententity->origin, ul, verts[0]); // first triangle VectorAdd (currententity->origin, ur, verts[1]); From 51e86941958a763dc555b556ed57d26accda90ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Mar 2021 09:11:08 +0900 Subject: [PATCH 1372/3664] [qw] Use a dynamic array to track static entities This takes care of another fixme in the cleanup of entity_t. --- include/QF/darray.h | 2 ++ include/QF/render.h | 1 - qw/include/client.h | 3 ++- qw/source/cl_demo.c | 4 +++- qw/source/cl_parse.c | 9 +++------ 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/QF/darray.h b/include/QF/darray.h index 61500256a..e41cd5edb 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -69,6 +69,8 @@ ele_type *a; \ } +#define DARRAY_STATIC_INIT(g) { .grow = g } + /** Allocate a fixed-size array using the given allocator The allocated array is initilized to be ungrowable, and with both size diff --git a/include/QF/render.h b/include/QF/render.h index d6a871865..99fb105a9 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -124,7 +124,6 @@ typedef struct renderer_s { typedef struct entity_s { struct entity_s *next; - struct entity_s *unext; //FIXME this shouldn't be here. for qw demos struct transform_s *transform; animation_t animation; diff --git a/qw/include/client.h b/qw/include/client.h index 23d22e893..3c64c128b 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -28,6 +28,7 @@ #ifndef _CLIENT_H #define _CLIENT_H +#include "QF/entity.h" #include "QF/info.h" #include "QF/quakefs.h" #include "QF/vid.h" @@ -341,7 +342,7 @@ extern struct cvar_s *cl_fb_players; extern client_state_t cl; -extern entity_t *cl_static_entities; +extern entityset_t cl_static_entities; extern entity_t cl_entities[512]; extern byte cl_entity_valid[2][512]; diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index d063211d4..31594d51f 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -755,7 +755,9 @@ demo_start_recording (int track) SZ_Clear (&buf); } // spawnstatic - for (ent = cl_static_entities; ent; ent = ent->unext) { + for (size_t staticIndex = 0; staticIndex < cl_static_entities.size; + staticIndex++) { + ent = cl_static_entities.a[staticIndex]; MSG_WriteByte (&buf, svc_spawnstatic); for (j = 1; j < cl.nummodels; j++) { diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 2266d1029..7366b4da0 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -169,8 +169,7 @@ int packet_latency[NET_TIMINGS]; extern cvar_t *hud_scoreboard_uid; -entity_t *cl_static_entities; -static entity_t **cl_static_tail; +entityset_t cl_static_entities = DARRAY_STATIC_INIT (32); static void CL_LoadSky (void) @@ -298,8 +297,7 @@ map_ent (const char *mapname) static void CL_NewMap (const char *mapname) { - cl_static_entities = 0; - cl_static_tail = &cl_static_entities; + cl_static_entities.size = 0; r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels); Team_NewMap (); Con_NewMap (); @@ -973,8 +971,7 @@ CL_ParseStatic (void) ent = r_funcs->R_AllocEntity (); CL_Init_Entity (ent); - *cl_static_tail = ent; - cl_static_tail = &ent->unext; + DARRAY_APPEND (&cl_static_entities, ent); // copy it to the current state ent->renderer.model = cl.model_precache[es.modelindex]; From b8267f2eddbb8e53c72a5c80c67055ee10f149d7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Mar 2021 11:25:04 +0900 Subject: [PATCH 1373/3664] [client] Merge nq/qw entity effects code --- include/client/effects.h | 43 ++++++++ libs/client/Makemodule.am | 3 +- libs/client/cl_effects.c | 175 +++++++++++++++++++++++++++++++++ libs/client/cl_temp_entities.c | 1 + nq/source/cl_ents.c | 135 +------------------------ qw/source/cl_ents.c | 112 ++------------------- 6 files changed, 231 insertions(+), 238 deletions(-) create mode 100644 include/client/effects.h create mode 100644 libs/client/cl_effects.c diff --git a/include/client/effects.h b/include/client/effects.h new file mode 100644 index 000000000..1f1259274 --- /dev/null +++ b/include/client/effects.h @@ -0,0 +1,43 @@ +/* + effects.h + + Effect management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/3/11 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __client_effects_h +#define __client_effects_h + +struct entity_s; +struct entity_state_s; + +void CL_NewDlight (int key, vec3_t org, int effects, byte glow_size, + byte glow_color, double time); +void CL_ModelEffects (struct entity_s *ent, int num, int glow_color, + double time); +void CL_EntityEffects (int num, struct entity_s *ent, + struct entity_state_s *state, double time); + +#endif//__client_effects_h diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 9129b9dbd..943f6bf9e 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES += libs/client/libQFclient.la libs_client_libQFclient_la_LDFLAGS= @STATIC@ libs_client_libQFclient_la_LIBADD= libs/gamecode/libQFgamecode.la libs/util/libQFutil.la libs_client_libQFclient_la_SOURCES= \ - libs/client/cl_temp_entities.c \ + libs/client/cl_effects.c \ libs/client/cl_entities.c \ + libs/client/cl_temp_entities.c \ $e diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c new file mode 100644 index 000000000..3030431a8 --- /dev/null +++ b/libs/client/cl_effects.c @@ -0,0 +1,175 @@ +/* + cl_effect.c + + Client side effect management + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/3/11 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/entity.h" +#include "QF/render.h" + +#include "QF/plugin/vid_render.h" //FIXME + +#include "client/entities.h" +#include "client/effects.h" + +void +CL_NewDlight (int key, vec3_t org, int effects, byte glow_size, + byte glow_color, double time) +{ + float radius; + dlight_t *dl; + static quat_t normal = {0.4, 0.2, 0.05, 0.7}; + static quat_t red = {0.5, 0.05, 0.05, 0.7}; + static quat_t blue = {0.05, 0.05, 0.5, 0.7}; + static quat_t purple = {0.5, 0.05, 0.5, 0.7}; + + effects &= EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT; + if (!effects) { + if (!glow_size) + return; + } + + dl = r_funcs->R_AllocDlight (key); + if (!dl) + return; + VectorCopy (org, dl->origin); + + if (effects & (EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT)) { + radius = 200 + (rand () & 31); + if (effects & EF_BRIGHTLIGHT) { + radius += 200; + dl->origin[2] += 16; + } + if (effects & EF_DIMLIGHT) + if (effects & ~EF_DIMLIGHT) + radius -= 100; + dl->radius = radius; + dl->die = time + 0.1; + + switch (effects & (EF_RED | EF_BLUE)) { + case EF_RED | EF_BLUE: + QuatCopy (purple, dl->color); + break; + case EF_RED: + QuatCopy (red, dl->color); + break; + case EF_BLUE: + QuatCopy (blue, dl->color); + break; + default: + QuatCopy (normal, dl->color); + break; + } + } + + if (glow_size) { + dl->radius += glow_size < 128 ? glow_size * 8.0 : + (glow_size - 256) * 8.0; + dl->die = time + 0.1; + if (glow_color) { + if (glow_color == 255) { + dl->color[0] = dl->color[1] = dl->color[2] = 1.0; + } else { + byte *tempcolor; + + tempcolor = (byte *) &d_8to24table[glow_color]; + VectorScale (tempcolor, 1 / 255.0, dl->color); + } + } + } +} + +void +CL_ModelEffects (entity_t *ent, int num, int glow_color, double time) +{ + dlight_t *dl; + model_t *model = ent->renderer.model; + + // add automatic particle trails + if (model->flags & EF_ROCKET) { + dl = r_funcs->R_AllocDlight (num); + if (dl) { + VectorCopy (ent->origin, dl->origin); + dl->radius = 200.0; + dl->die = time + 0.1; + //FIXME VectorCopy (r_firecolor->vec, dl->color); + VectorSet (0.9, 0.7, 0.0, dl->color); + dl->color[3] = 0.7; + } + r_funcs->particles->R_RocketTrail (ent); + } else if (model->flags & EF_GRENADE) + r_funcs->particles->R_GrenadeTrail (ent); + else if (model->flags & EF_GIB) + r_funcs->particles->R_BloodTrail (ent); + else if (model->flags & EF_ZOMGIB) + r_funcs->particles->R_SlightBloodTrail (ent); + else if (model->flags & EF_TRACER) + r_funcs->particles->R_WizTrail (ent); + else if (model->flags & EF_TRACER2) + r_funcs->particles->R_FlameTrail (ent); + else if (model->flags & EF_TRACER3) + r_funcs->particles->R_VoorTrail (ent); + else if (model->flags & EF_GLOWTRAIL) + if (r_funcs->particles->R_GlowTrail) + r_funcs->particles->R_GlowTrail (ent, glow_color); +} + +void +CL_EntityEffects (int num, entity_t *ent, entity_state_t *state, double time) +{ + dlight_t *dl; + + if (state->effects & EF_BRIGHTFIELD) + r_funcs->particles->R_EntityParticles (ent); + if (state->effects & EF_MUZZLEFLASH) { + dl = r_funcs->R_AllocDlight (num); + if (dl) { + vec4f_t position = Transform_GetWorldPosition (ent->transform); + vec4f_t fv = Transform_Forward (ent->transform); + position += 18 * fv; + VectorCopy (position, dl->origin); + dl->origin[2] += 16; + dl->radius = 200 + (rand () & 31); + dl->die = time + 0.1; + dl->minlight = 32; + dl->color[0] = 0.2; + dl->color[1] = 0.1; + dl->color[2] = 0.05; + dl->color[3] = 0.7; + } + } +} diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index a0627e42d..0b6672f0f 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -3,6 +3,7 @@ Client side temporary entity management + Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2021 Bill Currie Author: Bill Currie diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 3fdd3d0af..957cadb6a 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -47,6 +47,7 @@ #include "compat.h" +#include "client/effects.h" #include "client/temp_entities.h" #include "nq/include/chase.h" @@ -75,73 +76,6 @@ CL_ClearEnts (void) CL_Init_Entity (cl_entities + i); } -static void -CL_NewDlight (int key, vec3_t org, int effects, byte glow_size, - byte glow_color) -{ - float radius; - dlight_t *dl; - static quat_t normal = {0.4, 0.2, 0.05, 0.7}; - static quat_t red = {0.5, 0.05, 0.05, 0.7}; - static quat_t blue = {0.05, 0.05, 0.5, 0.7}; - static quat_t purple = {0.5, 0.05, 0.5, 0.7}; - - effects &= EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT; - if (!effects) { - if (!glow_size) - return; - } - - dl = r_funcs->R_AllocDlight (key); - if (!dl) - return; - VectorCopy (org, dl->origin); - - if (effects & (EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT)) { - radius = 200 + (rand () & 31); - if (effects & EF_BRIGHTLIGHT) { - radius += 200; - dl->origin[2] += 16; - } - if (effects & EF_DIMLIGHT) - if (effects & ~EF_DIMLIGHT) - radius -= 100; - dl->radius = radius; - dl->die = cl.time + 0.1; - - switch (effects & (EF_RED | EF_BLUE)) { - case EF_RED | EF_BLUE: - QuatCopy (purple, dl->color); - break; - case EF_RED: - QuatCopy (red, dl->color); - break; - case EF_BLUE: - QuatCopy (blue, dl->color); - break; - default: - QuatCopy (normal, dl->color); - break; - } - } - - if (glow_size) { - dl->radius += glow_size < 128 ? glow_size * 8.0 : - (glow_size - 256) * 8.0; - dl->die = cl.time + 0.1; - if (glow_color) { - if (glow_color == 255) { - dl->color[0] = dl->color[1] = dl->color[2] = 1.0; - } else { - byte *tempcolor; - - tempcolor = (byte *) &d_8to24table[glow_color]; - VectorScale (tempcolor, 1 / 255.0, dl->color); - } - } - } -} - /* CL_LerpPoint @@ -179,67 +113,6 @@ CL_LerpPoint (void) return frac; } -static void -CL_ModelEffects (entity_t *ent, int num, int glow_color) -{ - dlight_t *dl; - model_t *model = ent->renderer.model; - - // add automatic particle trails - if (model->flags & EF_ROCKET) { - dl = r_funcs->R_AllocDlight (num); - if (dl) { - VectorCopy (ent->origin, dl->origin); - dl->radius = 200.0; - dl->die = cl.time + 0.1; - //FIXME VectorCopy (r_firecolor->vec, dl->color); - VectorSet (0.9, 0.7, 0.0, dl->color); - dl->color[3] = 0.7; - } - r_funcs->particles->R_RocketTrail (ent); - } else if (model->flags & EF_GRENADE) - r_funcs->particles->R_GrenadeTrail (ent); - else if (model->flags & EF_GIB) - r_funcs->particles->R_BloodTrail (ent); - else if (model->flags & EF_ZOMGIB) - r_funcs->particles->R_SlightBloodTrail (ent); - else if (model->flags & EF_TRACER) - r_funcs->particles->R_WizTrail (ent); - else if (model->flags & EF_TRACER2) - r_funcs->particles->R_FlameTrail (ent); - else if (model->flags & EF_TRACER3) - r_funcs->particles->R_VoorTrail (ent); - else if (model->flags & EF_GLOWTRAIL) - if (r_funcs->particles->R_GlowTrail) - r_funcs->particles->R_GlowTrail (ent, glow_color); -} - -static void -CL_EntityEffects (int num, entity_t *ent, entity_state_t *state) -{ - dlight_t *dl; - - if (state->effects & EF_BRIGHTFIELD) - r_funcs->particles->R_EntityParticles (ent); - if (state->effects & EF_MUZZLEFLASH) { - dl = r_funcs->R_AllocDlight (num); - if (dl) { - vec4f_t position = Transform_GetWorldPosition (ent->transform); - vec4f_t fv = Transform_Forward (ent->transform); - position += 18 * fv; - VectorCopy (position, dl->origin); - dl->origin[2] += 16; - dl->radius = 200 + (rand () & 31); - dl->die = cl.time + 0.1; - dl->minlight = 32; - dl->color[0] = 0.2; - dl->color[1] = 0.1; - dl->color[2] = 0.05; - dl->color[3] = 0.7; - } - } -} - static void set_entity_model (entity_t *ent, int modelindex) { @@ -419,13 +292,13 @@ CL_RelinkEntities (void) angles[YAW] = bobjrotate; CL_TransformEntity (ent, angles); } - CL_EntityEffects (i, ent, new); + CL_EntityEffects (i, ent, new, cl.time); CL_NewDlight (i, ent->origin, new->effects, new->glow_size, - new->glow_color); + new->glow_color, cl.time); if (VectorDistance_fast (old->origin, ent->origin) > (256 * 256)) VectorCopy (ent->origin, old->origin); if (model_flags & ~EF_ROTATE) - CL_ModelEffects (ent, i, new->glow_color); + CL_ModelEffects (ent, i, new->glow_color, cl.time); cl_forcelink[i] = false; } diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 11acacaf2..0cf0f835e 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -47,6 +47,7 @@ #include "clview.h" #include "d_iface.h" +#include "client/effects.h" #include "client/temp_entities.h" #include "qw/bothdefs.h" @@ -82,73 +83,6 @@ CL_ClearEnts (void) CL_Init_Entity (&cl_player_ents[i]); } -static void -CL_NewDlight (int key, vec3_t org, int effects, byte glow_size, - byte glow_color) -{ - float radius; - dlight_t *dl; - static quat_t normal = {0.4, 0.2, 0.05, 0.7}; - static quat_t red = {0.5, 0.05, 0.05, 0.7}; - static quat_t blue = {0.05, 0.05, 0.5, 0.7}; - static quat_t purple = {0.5, 0.05, 0.5, 0.7}; - - effects &= EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT; - if (!effects) { - if (!glow_size) - return; - } - - dl = r_funcs->R_AllocDlight (key); - if (!dl) - return; - VectorCopy (org, dl->origin); - - if (effects & (EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT)) { - radius = 200 + (rand () & 31); - if (effects & EF_BRIGHTLIGHT) { - radius += 200; - dl->origin[2] += 16; - } - if (effects & EF_DIMLIGHT) - if (effects & ~EF_DIMLIGHT) - radius -= 100; - dl->radius = radius; - dl->die = cl.time + 0.1; - - switch (effects & (EF_RED | EF_BLUE)) { - case EF_RED | EF_BLUE: - QuatCopy (purple, dl->color); - break; - case EF_RED: - QuatCopy (red, dl->color); - break; - case EF_BLUE: - QuatCopy (blue, dl->color); - break; - default: - QuatCopy (normal, dl->color); - break; - } - } - - if (glow_size) { - dl->radius += glow_size < 128 ? glow_size * 8.0 : - (glow_size - 256) * 8.0; - dl->die = cl.time + 0.1; - if (glow_color) { - if (glow_color == 255) { - dl->color[0] = dl->color[1] = dl->color[2] = 1.0; - } else { - byte *tempcolor; - - tempcolor = (byte *) &d_8to24table[glow_color]; - VectorScale (tempcolor, 1 / 255.0, dl->color); - } - } - } -} - // Hack hack hack static inline int is_dead_body (entity_state_t *s1) @@ -171,41 +105,6 @@ is_gib (entity_state_t *s1) return 0; } -static void -CL_ModelEffects (entity_t *ent, int num, int glow_color) -{ - dlight_t *dl; - model_t *model = ent->renderer.model; - - // add automatic particle trails - if (model->flags & EF_ROCKET) { - dl = r_funcs->R_AllocDlight (num); - if (dl) { - VectorCopy (ent->origin, dl->origin); - dl->radius = 200.0; - dl->die = cl.time + 0.1; - //FIXME VectorCopy (r_firecolor->vec, dl->color); - VectorSet (0.9, 0.7, 0.0, dl->color); - dl->color[3] = 0.7; - } - r_funcs->particles->R_RocketTrail (ent); - } else if (model->flags & EF_GRENADE) - r_funcs->particles->R_GrenadeTrail (ent); - else if (model->flags & EF_GIB) - r_funcs->particles->R_BloodTrail (ent); - else if (model->flags & EF_ZOMGIB) - r_funcs->particles->R_SlightBloodTrail (ent); - else if (model->flags & EF_TRACER) - r_funcs->particles->R_WizTrail (ent); - else if (model->flags & EF_TRACER2) - r_funcs->particles->R_FlameTrail (ent); - else if (model->flags & EF_TRACER3) - r_funcs->particles->R_VoorTrail (ent); - else if (model->flags & EF_GLOWTRAIL) - if (r_funcs->particles->R_GlowTrail) - r_funcs->particles->R_GlowTrail (ent, glow_color); -} - static void set_entity_model (entity_t *ent, int modelindex) { @@ -221,6 +120,7 @@ set_entity_model (entity_t *ent, int modelindex) animation->syncbase = 0.0; } } + animation->nolerp = 1; // don't try to lerp when the model has changed } static void @@ -255,7 +155,7 @@ CL_LinkPacketEntities (void) // spawn light flashes, even ones coming from invisible objects CL_NewDlight (i, new->origin, new->effects, new->glow_size, - new->glow_color); + new->glow_color, cl.time); // if set to invisible, skip if (!new->modelindex @@ -374,11 +274,11 @@ CL_LinkPacketEntities (void) CL_TransformEntity (ent, angles); } //CL_EntityEffects (i, ent, new); - //CL_NewDlight (i, ent->origin, new->effects, 0, 0); + //CL_NewDlight (i, ent->origin, new->effects, 0, 0, cl.time); if (VectorDistance_fast (old->origin, ent->origin) > (256 * 256)) VectorCopy (ent->origin, old->origin); if (renderer->model->flags & ~EF_ROTATE) { - CL_ModelEffects (ent, -new->number, new->glow_color); + CL_ModelEffects (ent, -new->number, new->glow_color, cl.time); } } } @@ -492,7 +392,7 @@ CL_LinkPlayers (void) QuatSet (0.0, 1.0, 0.0, 1.0, dl->color); } else { CL_NewDlight (j + 1, org, state->pls.effects, state->pls.glow_size, - state->pls.glow_color); + state->pls.glow_color, cl.time); } // Draw player? From abaccbec538ae18f9d9eb710c1d4815a9d69e6e1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Mar 2021 11:38:33 +0900 Subject: [PATCH 1374/3664] [client] Move qw's loc code into client This makes the location code available to nq (not used yet) but more importantly moves some definitely client-side code into the right place. --- include/Makemodule.am | 3 ++ include/QF/Makemodule.am | 1 - include/{QF => client}/locs.h | 1 + libs/client/Makemodule.am | 1 + {qw/source => libs/client}/locs.c | 44 +++++++++++++++++++++++++-- libs/video/renderer/gl/gl_mod_alias.c | 1 - libs/video/renderer/gl/gl_rmain.c | 1 - libs/video/renderer/sw/sw_rmain.c | 1 - libs/video/renderer/sw32/sw32_rmain.c | 1 - qw/source/Makemodule.am | 2 +- qw/source/cl_entparse.c | 1 - qw/source/cl_ents.c | 32 ++----------------- qw/source/teamplay.c | 3 +- 13 files changed, 51 insertions(+), 41 deletions(-) rename include/{QF => client}/locs.h (97%) rename {qw/source => libs/client}/locs.c (84%) diff --git a/include/Makemodule.am b/include/Makemodule.am index 9fd003768..645a820bf 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -76,7 +76,10 @@ EXTRA_DIST += \ include/vregset.h \ include/winquake.h \ include/world.h \ + include/client/effects.h \ include/client/entities.h \ + include/client/temp_entities.h \ + include/client/locs.h \ include/qw/bothdefs.h \ include/qw/msg_backbuf.h \ include/qw/msg_ucmd.h \ diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 5282d5230..aefd432f7 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -25,7 +25,6 @@ include_qf = \ include/QF/keys.h \ include/QF/link.h \ include/QF/llist.h \ - include/QF/locs.h \ include/QF/mathlib.h \ include/QF/mdfour.h \ include/QF/mersenne.h \ diff --git a/include/QF/locs.h b/include/client/locs.h similarity index 97% rename from include/QF/locs.h rename to include/client/locs.h index 4f7dc9b5c..8786c6532 100644 --- a/include/QF/locs.h +++ b/include/client/locs.h @@ -46,5 +46,6 @@ int locs_nearest (const vec3_t loc) __attribute__((pure)); void locs_reset (void); void locs_save (const char *filename, qboolean gz); void map_to_loc (const char *mapname, char *filename); +void locs_draw (vec3_t simorg); #endif//__QF_locs_h diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 943f6bf9e..074daea58 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -6,4 +6,5 @@ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_effects.c \ libs/client/cl_entities.c \ libs/client/cl_temp_entities.c \ + libs/client/locs.c \ $e diff --git a/qw/source/locs.c b/libs/client/locs.c similarity index 84% rename from qw/source/locs.c rename to libs/client/locs.c index ab92ec4c2..dd6a17d9f 100644 --- a/qw/source/locs.c +++ b/libs/client/locs.c @@ -41,15 +41,19 @@ #include -#include "QF/locs.h" +#include "QF/mathlib.h" +#include "QF/render.h" #include "QF/qtypes.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/va.h" -#include "compat.h" +#include "QF/plugin/vid_render.h" //FIXME -#include "qw/include/client.h" +#include "compat.h" +#include "d_iface.h" //FIXME part_tex_smoke and part_tex_dot + +#include "client/locs.h" #define LOCATION_BLOCK 128 // 128 locations per block. @@ -276,3 +280,37 @@ map_to_loc (const char *mapname, char *filename) t1++; strcpy (t1, "loc"); } + +void +locs_draw (vec3_t simorg) +{ + //FIXME custom ent rendering code would be nice + dlight_t *dl; + location_t *nearloc; + vec3_t trueloc; + int i; + + nearloc = locs_find (simorg); + if (nearloc) { + dl = r_funcs->R_AllocDlight (4096); + if (dl) { + VectorCopy (nearloc->loc, dl->origin); + dl->radius = 200; + dl->die = r_data->realtime + 0.1; + dl->color[0] = 0; + dl->color[1] = 1; + dl->color[2] = 0; + dl->color[3] = 0.7; + } + VectorCopy (nearloc->loc, trueloc); + r_funcs->particles->R_Particle_New (pt_smokecloud, part_tex_smoke, + trueloc, 2.0, + vec3_origin, r_data->realtime + 9.0, 254, + 0.25 + qfrandom (0.125), 0.0); + for (i = 0; i < 15; i++) + r_funcs->particles->R_Particle_NewRandom (pt_fallfade, + part_tex_dot, trueloc, 12, + 0.7, 96, r_data->realtime + 5.0, + 104 + (rand () & 7), 1.0, 0.0); + } +} diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 8e4670a77..92c67038d 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -44,7 +44,6 @@ #include "QF/cvar.h" #include "QF/entity.h" -#include "QF/locs.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/render.h" diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 23d7f7be4..8079b790b 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -45,7 +45,6 @@ #include "QF/cvar.h" #include "QF/draw.h" #include "QF/entity.h" -#include "QF/locs.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/render.h" diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 7cf5416c0..8ab480bcc 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -43,7 +43,6 @@ #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/entity.h" -#include "QF/locs.h" #include "QF/mathlib.h" #include "QF/render.h" #include "QF/screen.h" diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 812a43205..36d94fd2a 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -43,7 +43,6 @@ #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/entity.h" -#include "QF/locs.h" #include "QF/mathlib.h" #include "QF/render.h" #include "QF/screen.h" diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 00e30b4bc..bad7bd189 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -104,7 +104,7 @@ qw_source_libqw_client_a_SOURCES= \ qw/source/cl_entparse.c qw/source/cl_ents.c qw/source/cl_http.c qw/source/cl_input.c qw/source/cl_main.c qw/source/cl_ngraph.c \ qw/source/cl_parse.c qw/source/cl_pred.c qw/source/cl_rss.c qw/source/cl_screen.c qw/source/cl_skin.c qw/source/cl_slist.c \ qw/source/cl_view.c \ - qw/source/locs.c qw/source/sbar.c qw/source/teamplay.c + qw/source/sbar.c qw/source/teamplay.c # Software-rendering clients diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 3a3d67264..ac7f0ae21 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -36,7 +36,6 @@ #endif #include "QF/cvar.h" -#include "QF/locs.h" #include "QF/msg.h" #include "QF/render.h" #include "QF/skin.h" diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 0cf0f835e..757cc7e56 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -37,7 +37,6 @@ #include "QF/cvar.h" #include "QF/entity.h" -#include "QF/locs.h" #include "QF/msg.h" #include "QF/render.h" #include "QF/skin.h" @@ -48,6 +47,7 @@ #include "d_iface.h" #include "client/effects.h" +#include "client/locs.h" #include "client/temp_entities.h" #include "qw/bothdefs.h" @@ -490,35 +490,7 @@ CL_EmitEntities (void) CL_LinkPacketEntities (); CL_UpdateTEnts (cl.time, &tentCtx); if (cl_draw_locs->int_val) { - //FIXME custom ent rendering code would be nice - dlight_t *dl; - location_t *nearloc; - vec3_t trueloc; - int i; - - nearloc = locs_find (cl.simorg); - if (nearloc) { - dl = r_funcs->R_AllocDlight (4096); - if (dl) { - VectorCopy (nearloc->loc, dl->origin); - dl->radius = 200; - dl->die = r_data->realtime + 0.1; - dl->color[0] = 0; - dl->color[1] = 1; - dl->color[2] = 0; - dl->color[3] = 0.7; - } - VectorCopy (nearloc->loc, trueloc); - r_funcs->particles->R_Particle_New (pt_smokecloud, part_tex_smoke, - trueloc, 2.0, - vec3_origin, r_data->realtime + 9.0, 254, - 0.25 + qfrandom (0.125), 0.0); - for (i = 0; i < 15; i++) - r_funcs->particles->R_Particle_NewRandom (pt_fallfade, - part_tex_dot, trueloc, 12, - 0.7, 96, r_data->realtime + 5.0, - 104 + (rand () & 7), 1.0, 0.0); - } + locs_draw (cl.simorg); } } diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index e8a38606d..75e6aefe3 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -43,7 +43,6 @@ #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/gib.h" -#include "QF/locs.h" #include "QF/model.h" #include "QF/va.h" #include "QF/skin.h" @@ -52,6 +51,8 @@ #include "compat.h" +#include "client/locs.h" + #include "qw/bothdefs.h" #include "qw/include/cl_input.h" #include "qw/include/client.h" From c9bbc2971aea47af43c88b8383607ea38934d6f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Mar 2021 12:47:08 +0900 Subject: [PATCH 1375/3664] [qw] Rename view_message to view_state Makes more sense to me. --- qw/source/cl_view.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 08d4dd501..763de6767 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -82,7 +82,7 @@ cvar_t *v_idlescale; float v_dmg_time, v_dmg_roll, v_dmg_pitch; frame_t *view_frame; -player_state_t *view_message; +player_state_t *view_state; cshift_t cshift_empty = { {130, 80, 50}, 0}; cshift_t cshift_water = { {130, 80, 50}, 128}; @@ -189,7 +189,7 @@ V_DriftPitch (void) int frameno = (cls.netchan.outgoing_sequence - 1) & UPDATE_MASK; usercmd_t *cmd = &cl.frames[frameno].cmd; - if (view_message->onground == -1 || cls.demoplayback) { + if (view_state->onground == -1 || cls.demoplayback) { cl.driftmove = 0; cl.pitchvel = 0; return; @@ -600,7 +600,7 @@ V_CalcViewRoll (void) v_dmg_time -= host_frametime; } - if (view_message->pls.flags & PF_DEAD) // PF_GIB will also set PF_DEAD + if (view_state->pls.flags & PF_DEAD) // PF_GIB will also set PF_DEAD r_data->refdef->viewangles[ROLL] = 80; // dead view angle } @@ -700,12 +700,12 @@ V_CalcRefdef (void) else if (r_data->scr_viewsize->int_val == 80) view->origin[2] += 0.5; - if (view_message->pls.flags & (PF_GIB | PF_DEAD)) { + if (view_state->pls.flags & (PF_GIB | PF_DEAD)) { view->renderer.model = NULL; } else { view->renderer.model = cl.model_precache[cl.stats[STAT_WEAPON]]; } - view->animation.frame = view_message->pls.weaponframe; + view->animation.frame = view_state->pls.weaponframe; view->renderer.skin = 0; // set up the refresh position @@ -755,11 +755,11 @@ V_RenderView (void) return; view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; - view_message = &view_frame->playerstate[cl.playernum]; + view_state = &view_frame->playerstate[cl.playernum]; - if (view_message->pls.flags & PF_GIB) + if (view_state->pls.flags & PF_GIB) cl.viewheight = 8; // gib view height - else if (view_message->pls.flags & PF_DEAD) + else if (view_state->pls.flags & PF_DEAD) cl.viewheight = -16; // corpse view height else { cl.viewheight = DEFAULT_VIEWHEIGHT; // view height From ca38f9b616b802e8b0e783a3860d56cc2a42b7a0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Mar 2021 14:27:36 +0900 Subject: [PATCH 1376/3664] [qw] Use entity_state_t as a base for player_state_t This will, in the long run, help clean up a lot of the differences in the handling of entities in the clients. --- include/client/entities.h | 6 +- include/qw/protocol.h | 19 +---- qtv/source/client.c | 60 +++++++-------- qtv/source/sv_parse.c | 46 ++++++------ qw/source/cl_cam.c | 32 ++++---- qw/source/cl_entparse.c | 61 ++++++++-------- qw/source/cl_ents.c | 34 ++++----- qw/source/cl_main.c | 4 +- qw/source/cl_pred.c | 41 ++++++----- qw/source/cl_view.c | 10 +-- qw/source/sv_ents.c | 150 +++++++++++++++++++------------------- 11 files changed, 225 insertions(+), 238 deletions(-) diff --git a/include/client/entities.h b/include/client/entities.h index 1dba394d6..45420cbb7 100644 --- a/include/client/entities.h +++ b/include/client/entities.h @@ -40,9 +40,11 @@ typedef struct entity_state_s { unsigned flags; // nolerp, etc vec3_t origin; + vec3_t velocity; vec3_t angles; - unsigned short modelindex; - unsigned short frame; + uint16_t modelindex; + uint16_t frame; + int weaponframe; int effects; byte colormap; byte skinnum; diff --git a/include/qw/protocol.h b/include/qw/protocol.h index 76f2c625d..9fb818d37 100644 --- a/include/qw/protocol.h +++ b/include/qw/protocol.h @@ -320,26 +320,9 @@ typedef struct usercmd_s { } usercmd_t; typedef struct plent_state_s { - int number; - - unsigned int flags; - vec3_t origin; + entity_state_t es; usercmd_t cmd; - vec3_t velocity; - int modelindex; - int frame; - int skinnum; - int effects; - int weaponframe; - byte msec; - - // QSG 2 - byte alpha; - byte scale; - byte glow_size; - byte glow_color; - byte colormod; } plent_state_t; typedef struct { diff --git a/qtv/source/client.c b/qtv/source/client.c index c55e57bd2..6da363953 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -446,9 +446,9 @@ spectator_move (client_t *cl, usercmd_t *ucmd) AngleVectors (cl->state.cmd.angles, forward, right, up); - speed = DotProduct (cl->state.velocity, cl->state.velocity); + speed = DotProduct (cl->state.es.velocity, cl->state.es.velocity); if (speed < 1) { - VectorZero (cl->state.velocity); + VectorZero (cl->state.es.velocity); } else { speed = sqrt (speed); drop = 0; @@ -462,7 +462,7 @@ spectator_move (client_t *cl, usercmd_t *ucmd) newspeed = 0; newspeed /= speed; - VectorScale (cl->state.velocity, newspeed, cl->state.velocity); + VectorScale (cl->state.es.velocity, newspeed, cl->state.es.velocity); } fmove = ucmd->forwardmove; @@ -484,7 +484,7 @@ spectator_move (client_t *cl, usercmd_t *ucmd) wishspeed = sv->movevars.spectatormaxspeed; } - currentspeed = DotProduct (cl->state.velocity, wishdir); + currentspeed = DotProduct (cl->state.es.velocity, wishdir); addspeed = wishspeed - currentspeed; if (addspeed <= 0) return; @@ -492,10 +492,10 @@ spectator_move (client_t *cl, usercmd_t *ucmd) if (accelspeed > addspeed) accelspeed = addspeed; - VectorMultAdd (cl->state.velocity, accelspeed, wishdir, - cl->state.velocity); - VectorMultAdd (cl->state.origin, frametime, cl->state.velocity, - cl->state.origin); + VectorMultAdd (cl->state.es.velocity, accelspeed, wishdir, + cl->state.es.velocity); + VectorMultAdd (cl->state.es.origin, frametime, cl->state.es.velocity, + cl->state.es.origin); } static void @@ -612,7 +612,7 @@ client_parse_message (client_t *cl) break; case clc_tmove: MSG_ReadCoordV (net_message, o); - VectorCopy (o, cl->state.origin); + VectorCopy (o, cl->state.es.origin); break; case clc_upload: size = MSG_ReadShort (net_message); @@ -627,18 +627,18 @@ static void write_player (int num, plent_state_t *pl, server_t *sv, sizebuf_t *msg) { int i; - int pflags = (pl->flags & (PF_GIB | PF_DEAD)) + int pflags = (pl->es.flags & (PF_GIB | PF_DEAD)) | PF_MSEC | PF_COMMAND; int qf_bits = 0; - if (pl->modelindex != sv->playermodel) + if (pl->es.modelindex != sv->playermodel) pflags |= PF_MODEL; for (i = 0; i < 3; i++) - if (pl->velocity[i]) + if (pl->es.velocity[i]) pflags |= PF_VELOCITY1 << i; - if (pl->effects & 0xff) + if (pl->es.effects & 0xff) pflags |= PF_EFFECTS; - if (pl->skinnum) + if (pl->es.skinnum) pflags |= PF_SKINNUM; qf_bits = 0; @@ -670,21 +670,21 @@ write_player (int num, plent_state_t *pl, server_t *sv, sizebuf_t *msg) // } else if (ent == clent) { // // don't send a lot of data on personal entity // pflags &= ~(PF_MSEC | PF_COMMAND); -// if (pl->weaponframe) +// if (pl->es.weaponframe) // pflags |= PF_WEAPONFRAME; // } // if (client->spec_track && client->spec_track - 1 == j -// && pl->weaponframe) +// && pl->es.weaponframe) // pflags |= PF_WEAPONFRAME; MSG_WriteByte (msg, svc_playerinfo); MSG_WriteByte (msg, num); MSG_WriteShort (msg, pflags); - MSG_WriteCoordV (msg, pl->origin); + MSG_WriteCoordV (msg, pl->es.origin); - MSG_WriteByte (msg, pl->frame); + MSG_WriteByte (msg, pl->es.frame); if (pflags & PF_MSEC) { //msec = 1000 * (sv.time - cl->localtime); @@ -699,36 +699,36 @@ write_player (int num, plent_state_t *pl, server_t *sv, sizebuf_t *msg) for (i = 0; i < 3; i++) if (pflags & (PF_VELOCITY1 << i)) - MSG_WriteShort (msg, pl->velocity[i]); + MSG_WriteShort (msg, pl->es.velocity[i]); if (pflags & PF_MODEL) - MSG_WriteByte (msg, pl->modelindex); + MSG_WriteByte (msg, pl->es.modelindex); if (pflags & PF_SKINNUM) - MSG_WriteByte (msg, pl->skinnum); + MSG_WriteByte (msg, pl->es.skinnum); if (pflags & PF_EFFECTS) - MSG_WriteByte (msg, pl->effects); + MSG_WriteByte (msg, pl->es.effects); if (pflags & PF_WEAPONFRAME) - MSG_WriteByte (msg, pl->weaponframe); + MSG_WriteByte (msg, pl->es.weaponframe); if (pflags & PF_QF) { MSG_WriteByte (msg, qf_bits); if (qf_bits & PF_ALPHA) - MSG_WriteByte (msg, pl->alpha); + MSG_WriteByte (msg, pl->es.alpha); if (qf_bits & PF_SCALE) - MSG_WriteByte (msg, pl->scale); + MSG_WriteByte (msg, pl->es.scale); if (qf_bits & PF_EFFECTS2) - MSG_WriteByte (msg, pl->effects >> 8); + MSG_WriteByte (msg, pl->es.effects >> 8); if (qf_bits & PF_GLOWSIZE) - MSG_WriteByte (msg, pl->scale); + MSG_WriteByte (msg, pl->es.glow_size); if (qf_bits & PF_GLOWCOLOR) - MSG_WriteByte (msg, pl->glow_color); + MSG_WriteByte (msg, pl->es.glow_color); if (qf_bits & PF_COLORMOD) - MSG_WriteByte (msg, pl->colormod); + MSG_WriteByte (msg, pl->es.colormod); if (qf_bits & PF_FRAME2) - MSG_WriteByte (msg, pl->frame >> 8); + MSG_WriteByte (msg, pl->es.frame >> 8); } } #if 0 diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index 493aa613a..268e9999d 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -514,9 +514,9 @@ parse_player_delta (qmsg_t *msg, plent_state_t *from, plent_state_t *to) int i; int flags; - flags = to->flags = MSG_ReadShort (msg); - MSG_ReadCoordV (msg, to->origin); - to->frame = (to->frame & 0xff00) | MSG_ReadByte (msg); + flags = to->es.flags = MSG_ReadShort (msg); + MSG_ReadCoordV (msg, to->es.origin); + to->es.frame = (to->es.frame & 0xff00) | MSG_ReadByte (msg); if (flags & PF_MSEC) to->msec = MSG_ReadByte (msg); // qtv_printf ("%02x\n", msg->message->data[msg->readcount]); @@ -524,36 +524,36 @@ parse_player_delta (qmsg_t *msg, plent_state_t *from, plent_state_t *to) MSG_ReadDeltaUsercmd (msg, &from->cmd, &to->cmd); for (i = 0; i < 3; i++) { if (flags & (PF_VELOCITY1 << i)) - to->velocity[i] = (short) MSG_ReadShort (msg); + to->es.velocity[i] = (short) MSG_ReadShort (msg); } if (flags & PF_MODEL) - to->modelindex = MSG_ReadByte (msg); + to->es.modelindex = MSG_ReadByte (msg); if (flags & PF_SKINNUM) - to->skinnum = MSG_ReadByte (msg); + to->es.skinnum = MSG_ReadByte (msg); if (flags & PF_EFFECTS) - to->effects = (to->effects & 0xff00) | MSG_ReadByte (msg); + to->es.effects = (to->es.effects & 0xff00) | MSG_ReadByte (msg); if (flags & PF_WEAPONFRAME) - to->weaponframe = MSG_ReadByte (msg); + to->es.weaponframe = MSG_ReadByte (msg); if (flags & PF_QF) { int bits; bits = MSG_ReadByte (msg); if (bits & PF_ALPHA) - to->alpha = MSG_ReadByte (msg); + to->es.alpha = MSG_ReadByte (msg); if (bits & PF_SCALE) - to->scale = MSG_ReadByte (msg); + to->es.scale = MSG_ReadByte (msg); if (bits & PF_EFFECTS2) - to->effects = (to->effects & 0x00ff) - | (MSG_ReadByte (msg) << 8); + to->es.effects = (to->es.effects & 0x00ff) + | (MSG_ReadByte (msg) << 8); if (bits & PF_GLOWSIZE) - to->glow_size = MSG_ReadByte (msg); + to->es.glow_size = MSG_ReadByte (msg); if (bits & PF_GLOWCOLOR) - to->glow_color = MSG_ReadByte (msg); + to->es.glow_color = MSG_ReadByte (msg); if (bits & PF_COLORMOD) - to->colormod = MSG_ReadByte (msg); + to->es.colormod = MSG_ReadByte (msg); if (bits & PF_FRAME2) - to->frame = (to->frame & 0xff) - | (MSG_ReadByte (msg) << 8); + to->es.frame = (to->es.frame & 0xff) + | (MSG_ReadByte (msg) << 8); } } @@ -567,12 +567,12 @@ sv_playerinfo (server_t *sv, qmsg_t *msg) int fromind, toind; static plent_state_t null_player_state; - if (!null_player_state.alpha) { - null_player_state.alpha = 255; - null_player_state.scale = 16; - null_player_state.glow_size = 0; - null_player_state.glow_color = 254; - null_player_state.colormod = 255; + if (!null_player_state.es.alpha) { + null_player_state.es.alpha = 255; + null_player_state.es.scale = 16; + null_player_state.es.glow_size = 0; + null_player_state.es.glow_color = 254; + null_player_state.es.colormod = 255; } fromind = MSG_ReadByte (msg); toind = sv->netchan.incoming_sequence & UPDATE_MASK; diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 5a7f0d486..91e7a44eb 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -218,23 +218,23 @@ Cam_TryFlyby (player_state_t * self, player_state_t * player, vec3_t vec, vectoangles (vec, v); VectorCopy (v, pmove.angles); VectorNormalize (vec); - VectorMultAdd (player->pls.origin, 800, vec, v); + VectorMultAdd (player->pls.es.origin, 800, vec, v); // v is endpos // fake a player move - trace = Cam_DoTrace (player->pls.origin, v); + trace = Cam_DoTrace (player->pls.es.origin, v); if ( /* trace.inopen || */ trace.inwater) return 9999; VectorCopy (trace.endpos, vec); - len = VectorDistance (trace.endpos, player->pls.origin); + len = VectorDistance (trace.endpos, player->pls.es.origin); if (len < 32 || len > 800) return 9999; if (checkvis) { - trace = Cam_DoTrace (self->pls.origin, vec); + trace = Cam_DoTrace (self->pls.es.origin, vec); if (trace.fraction != 1 || trace.inwater) return 9999; - len = VectorDistance (trace.endpos, self->pls.origin); + len = VectorDistance (trace.endpos, self->pls.es.origin); } return len; @@ -248,11 +248,11 @@ Cam_IsVisible (player_state_t * player, vec3_t vec) trace_t trace; vec3_t v; - trace = Cam_DoTrace (player->pls.origin, vec); + trace = Cam_DoTrace (player->pls.es.origin, vec); if (trace.fraction != 1 || /* trace.inopen || */ trace.inwater) return false; // check distance, don't let the player get too far away or too close - VectorSubtract (player->pls.origin, vec, v); + VectorSubtract (player->pls.es.origin, vec, v); d = VectorLength (v); return (d > 16.0); @@ -440,22 +440,22 @@ Cam_Track (usercmd_t *cmd) cmd->forwardmove = cmd->sidemove = cmd->upmove = 0; VectorCopy (player->viewangles, cl.viewangles); - VectorCopy (player->pls.origin, desired_position); - if (memcmp (&desired_position, &self->pls.origin, + VectorCopy (player->pls.es.origin, desired_position); + if (memcmp (&desired_position, &self->pls.es.origin, sizeof (desired_position)) != 0) { if (!cls.demoplayback) { MSG_WriteByte (&cls.netchan.message, clc_tmove); MSG_WriteCoordV (&cls.netchan.message, desired_position); } // move there locally immediately - VectorCopy (desired_position, self->pls.origin); + VectorCopy (desired_position, self->pls.es.origin); } - self->pls.weaponframe = player->pls.weaponframe; + self->pls.es.weaponframe = player->pls.es.weaponframe; } else { // Ok, move to our desired position and set our angles to view // the player - VectorSubtract (desired_position, self->pls.origin, vec); + VectorSubtract (desired_position, self->pls.es.origin, vec); len = VectorLength (vec); cmd->forwardmove = cmd->sidemove = cmd->upmove = 0; if (len > 16) { // close enough? @@ -465,9 +465,9 @@ Cam_Track (usercmd_t *cmd) } } // move there locally immediately - VectorCopy (desired_position, self->pls.origin); + VectorCopy (desired_position, self->pls.es.origin); - VectorSubtract (player->pls.origin, desired_position, vec); + VectorSubtract (player->pls.es.origin, desired_position, vec); vectoangles (vec, cl.viewangles); cl.viewangles[0] = -cl.viewangles[0]; } @@ -520,7 +520,7 @@ Cam_SetView (void) player = frame->playerstate + spec_track; self = frame->playerstate + cl.playernum; - VectorSubtract (player->pls.origin, cl.simorg, vec); + VectorSubtract (player->pls.es.origin, cl.simorg, vec); if (cam_forceview) { cam_forceview = false; vectoangles (vec, cam_viewangles); @@ -560,7 +560,7 @@ Cam_FinishMove (usercmd_t *cmd) player = frame->playerstate + spec_track; self = frame->playerstate + cl.playernum; - VectorSubtract (player->pls.origin, self->pls.origin, vec); + VectorSubtract (player->pls.es.origin, self->pls.es.origin, vec); if (cam_forceview) { cam_forceview = false; vectoangles (vec, cam_viewangles); diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index ac7f0ae21..b1b5d3386 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -360,7 +360,7 @@ CL_ParseDemoPlayerinfo (int num) info = &cl.players[num]; state = &cl.frames[parsecountmod].playerstate[num]; - state->pls.number = num; + state->pls.es.number = num; if (info->prevcount > cl.parsecount || !cl.parsecount) { prevstate = &dummy; @@ -383,25 +383,25 @@ CL_ParseDemoPlayerinfo (int num) memcpy (state, prevstate, sizeof (player_state_t)); flags = MSG_ReadShort (net_message); - state->pls.flags = TranslateFlags (flags); + state->pls.es.flags = TranslateFlags (flags); state->messagenum = cl.parsecount; state->pls.cmd.msec = 0; - state->pls.frame = MSG_ReadByte (net_message); + state->pls.es.frame = MSG_ReadByte (net_message); state->state_time = parsecounttime; for (i=0; i <3; i++) if (flags & (DF_ORIGIN << i)) - state->pls.origin[i] = MSG_ReadCoord (net_message); + state->pls.es.origin[i] = MSG_ReadCoord (net_message); for (i=0; i <3; i++) if (flags & (DF_ANGLES << i)) state->pls.cmd.angles[i] = MSG_ReadAngle16 (net_message); if (flags & DF_MODEL) - state->pls.modelindex = MSG_ReadByte (net_message); + state->pls.es.modelindex = MSG_ReadByte (net_message); if (flags & DF_SKINNUM) - state->pls.skinnum = MSG_ReadByte (net_message); + state->pls.es.skinnum = MSG_ReadByte (net_message); if (flags & DF_EFFECTS) - state->pls.effects = MSG_ReadByte (net_message); + state->pls.es.effects = MSG_ReadByte (net_message); if (flags & DF_WEAPONFRAME) - state->pls.weaponframe = MSG_ReadByte (net_message); + state->pls.es.weaponframe = MSG_ReadByte (net_message); VectorCopy (state->pls.cmd.angles, state->viewangles); } @@ -422,14 +422,14 @@ CL_ParsePlayerinfo (void) state = &cl.frames[parsecountmod].playerstate[num]; - state->pls.number = num; + state->pls.es.number = num; - flags = state->pls.flags = MSG_ReadShort (net_message); + flags = state->pls.es.flags = MSG_ReadShort (net_message); state->messagenum = cl.parsecount; - MSG_ReadCoordV (net_message, state->pls.origin); + MSG_ReadCoordV (net_message, state->pls.es.origin); - state->pls.frame = MSG_ReadByte (net_message); + state->pls.es.frame = MSG_ReadByte (net_message); // the other player's last move was likely some time // before the packet was sent out, so accurately track @@ -445,30 +445,30 @@ CL_ParsePlayerinfo (void) for (i = 0; i < 3; i++) { if (flags & (PF_VELOCITY1 << i)) - state->pls.velocity[i] = (short) MSG_ReadShort (net_message); + state->pls.es.velocity[i] = (short) MSG_ReadShort (net_message); else - state->pls.velocity[i] = 0; + state->pls.es.velocity[i] = 0; } if (flags & PF_MODEL) i = MSG_ReadByte (net_message); else i = cl_playerindex; - state->pls.modelindex = i; + state->pls.es.modelindex = i; if (flags & PF_SKINNUM) - state->pls.skinnum = MSG_ReadByte (net_message); + state->pls.es.skinnum = MSG_ReadByte (net_message); else - state->pls.skinnum = 0; + state->pls.es.skinnum = 0; if (flags & PF_EFFECTS) - state->pls.effects = MSG_ReadByte (net_message); + state->pls.es.effects = MSG_ReadByte (net_message); else - state->pls.effects = 0; + state->pls.es.effects = 0; if (flags & PF_WEAPONFRAME) - state->pls.weaponframe = MSG_ReadByte (net_message); + state->pls.es.weaponframe = MSG_ReadByte (net_message); else - state->pls.weaponframe = 0; + state->pls.es.weaponframe = 0; VectorCopy (state->pls.cmd.angles, state->viewangles); @@ -489,13 +489,13 @@ CL_ParsePlayerinfo (void) ent->scale = val / 16.0; } if (bits & PF_EFFECTS2) { - state->pls.effects |= MSG_ReadByte (net_message) << 8; + state->pls.es.effects |= MSG_ReadByte (net_message) << 8; } if (bits & PF_GLOWSIZE) { - state->pls.glow_size = MSG_ReadByte (net_message); + state->pls.es.glow_size = MSG_ReadByte (net_message); } if (bits & PF_GLOWCOLOR) { - state->pls.glow_color = MSG_ReadByte (net_message); + state->pls.es.glow_color = MSG_ReadByte (net_message); } if (bits & PF_COLORMOD) { float r = 1.0, g = 1.0, b = 1.0; @@ -508,7 +508,7 @@ CL_ParsePlayerinfo (void) VectorSet (r, g, b, ent->renderer.colormod); } if (bits & PF_FRAME2) { - state->pls.frame |= MSG_ReadByte (net_message) << 8; + state->pls.es.frame |= MSG_ReadByte (net_message) << 8; } } } @@ -599,22 +599,23 @@ CL_SetUpPlayerPrediction (qboolean dopred) if (state->messagenum != cl.parsecount) continue; // not present this frame - if (!state->pls.modelindex) + if (!state->pls.es.modelindex) continue; pplayer->active = true; - pplayer->flags = state->pls.flags; + pplayer->flags = state->pls.es.flags; // note that the local player is special, since he moves locally // we use his last predicted postition if (j == cl.playernum) { VectorCopy (cl.frames[cls.netchan.outgoing_sequence & UPDATE_MASK]. - playerstate[cl.playernum].pls.origin, pplayer->origin); + playerstate[cl.playernum].pls.es.origin, + pplayer->origin); } else { // predict only half the move to minimize overruns msec = 500 * (playertime - state->state_time); if (msec <= 0 || !dopred) { - VectorCopy (state->pls.origin, pplayer->origin); + VectorCopy (state->pls.es.origin, pplayer->origin); // Sys_MaskPrintf (SYS_DEV, "nopredict\n"); } else { // predict players movement @@ -622,7 +623,7 @@ CL_SetUpPlayerPrediction (qboolean dopred) // Sys_MaskPrintf (SYS_DEV, "predict: %i\n", msec); CL_PredictUsercmd (state, &exact, &state->pls.cmd, false); - VectorCopy (exact.pls.origin, pplayer->origin); + VectorCopy (exact.pls.es.origin, pplayer->origin); } } } diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 757cc7e56..1e8ab80d9 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -349,7 +349,7 @@ static void CL_LinkPlayers (void) { double playertime; - int msec, oldphysent, i, j; + int msec, oldphysent, j; entity_t *ent; frame_t *frame; player_info_t *info; @@ -381,7 +381,7 @@ CL_LinkPlayers (void) r_data->player_entity = &cl_player_ents[j]; clientplayer = true; } else { - VectorCopy (state->pls.origin, org); + VectorCopy (state->pls.es.origin, org); clientplayer = false; } if (info->chat && info->chat->value[0] != '0') { @@ -391,28 +391,28 @@ CL_LinkPlayers (void) dl->die = cl.time + 0.1; QuatSet (0.0, 1.0, 0.0, 1.0, dl->color); } else { - CL_NewDlight (j + 1, org, state->pls.effects, state->pls.glow_size, - state->pls.glow_color, cl.time); + CL_NewDlight (j + 1, org, state->pls.es.effects, + state->pls.es.glow_size, state->pls.es.glow_color, + cl.time); } // Draw player? if (!Cam_DrawPlayer (j)) continue; - if (!state->pls.modelindex) + if (!state->pls.es.modelindex) continue; // Hack hack hack if (cl_deadbodyfilter->int_val - && state->pls.modelindex == cl_playerindex - && ((i = state->pls.frame) == 49 || i == 60 || i == 69 || i == 84 - || i == 93 || i == 102)) + && state->pls.es.modelindex == cl_playerindex + && is_dead_body (&state->pls.es)) continue; // predict only half the move to minimize overruns msec = 500 * (playertime - state->state_time); if (msec <= 0 || (!cl_predict_players->int_val) || cls.demoplayback2) { - VectorCopy (state->pls.origin, ent->origin); + VectorCopy (state->pls.es.origin, ent->origin); } else { // predict players movement state->pls.cmd.msec = msec = min (msec, 255); @@ -420,7 +420,7 @@ CL_LinkPlayers (void) CL_SetSolidPlayers (j); CL_PredictUsercmd (state, &exact, &state->pls.cmd, clientplayer); pmove.numphysent = oldphysent; - VectorCopy (exact.pls.origin, ent->origin); + VectorCopy (exact.pls.es.origin, ent->origin); } // angles @@ -432,18 +432,18 @@ CL_LinkPlayers (void) ang[PITCH] = -state->viewangles[PITCH] / 3.0; ang[YAW] = state->viewangles[YAW]; } - ang[ROLL] = V_CalcRoll (ang, state->pls.velocity) * 4.0; + ang[ROLL] = V_CalcRoll (ang, state->pls.es.velocity) * 4.0; - ent->renderer.model = cl.model_precache[state->pls.modelindex]; - ent->animation.frame = state->pls.frame; - ent->renderer.skinnum = state->pls.skinnum; + ent->renderer.model = cl.model_precache[state->pls.es.modelindex]; + ent->animation.frame = state->pls.es.frame; + ent->renderer.skinnum = state->pls.es.skinnum; CL_TransformEntity (ent, ang); ent->renderer.min_light = 0; ent->renderer.fullbright = 0; - if (state->pls.modelindex == cl_playerindex) { //XXX + if (state->pls.es.modelindex == cl_playerindex) { //XXX // use custom skin ent->renderer.skin = info->skin; @@ -460,9 +460,9 @@ CL_LinkPlayers (void) // stuff entity in map r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); - if (state->pls.effects & EF_FLAG1) + if (state->pls.es.effects & EF_FLAG1) CL_AddFlagModels (ent, 0, j); - else if (state->pls.effects & EF_FLAG2) + else if (state->pls.es.effects & EF_FLAG2) CL_AddFlagModels (ent, 1, j); } } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 656d6eb57..ea143c9ae 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1631,8 +1631,8 @@ Host_Frame (float time) oldself = &cl.frames[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].playerstate[cl.playernum]; self->messagenum = cl.parsecount; - VectorCopy (oldself->pls.origin, self->pls.origin); - VectorCopy (oldself->pls.velocity, self->pls.velocity); + VectorCopy (oldself->pls.es.origin, self->pls.es.origin); + VectorCopy (oldself->pls.es.velocity, self->pls.es.velocity); VectorCopy (oldself->viewangles, self->viewangles); CL_ParseClientdata (); diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index 1ac6e5ca1..1fe115949 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -51,10 +51,10 @@ CL_PredictUsercmd (player_state_t * from, player_state_t * to, usercmd_t *u, qboolean clientplayer) { if (!clientplayer) { - if (VectorIsZero (from->pls.velocity)) { - VectorCopy (from->pls.origin, to->pls.origin); + if (VectorIsZero (from->pls.es.velocity)) { + VectorCopy (from->pls.es.origin, to->pls.es.origin); VectorCopy (u->angles, to->viewangles); - VectorCopy (from->pls.velocity, to->pls.velocity); + VectorCopy (from->pls.es.velocity, to->pls.es.velocity); return; } } @@ -72,9 +72,9 @@ CL_PredictUsercmd (player_state_t * from, player_state_t * to, usercmd_t *u, return; } - VectorCopy (from->pls.origin, pmove.origin); + VectorCopy (from->pls.es.origin, pmove.origin); VectorCopy (u->angles, pmove.angles); - VectorCopy (from->pls.velocity, pmove.velocity); + VectorCopy (from->pls.es.velocity, pmove.velocity); pmove.oldbuttons = from->oldbuttons; pmove.oldonground = from->oldonground; @@ -92,11 +92,11 @@ CL_PredictUsercmd (player_state_t * from, player_state_t * to, usercmd_t *u, to->waterjumptime = pmove.waterjumptime; to->oldbuttons = pmove.oldbuttons; // Tonik to->oldonground = pmove.oldonground; - VectorCopy (pmove.origin, to->pls.origin); + VectorCopy (pmove.origin, to->pls.es.origin); VectorCopy (pmove.angles, to->viewangles); - VectorCopy (pmove.velocity, to->pls.velocity); + VectorCopy (pmove.velocity, to->pls.es.velocity); to->onground = onground; - to->pls.weaponframe = from->pls.weaponframe; + to->pls.es.weaponframe = from->pls.es.weaponframe; } void @@ -137,8 +137,8 @@ CL_PredictMove (void) from = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; if (!cl_predict->int_val) { - VectorCopy (from->playerstate[cl.playernum].pls.velocity, cl.simvel); - VectorCopy (from->playerstate[cl.playernum].pls.origin, cl.simorg); + VectorCopy (from->playerstate[cl.playernum].pls.es.velocity, cl.simvel); + VectorCopy (from->playerstate[cl.playernum].pls.es.origin, cl.simorg); return; } @@ -175,21 +175,22 @@ CL_PredictMove (void) } for (i = 0; i < 3; i++) - if (fabs (from->playerstate[cl.playernum].pls.origin[i] - - to->playerstate[cl.playernum].pls.origin[i]) > 128) { + if (fabs (from->playerstate[cl.playernum].pls.es.origin[i] - + to->playerstate[cl.playernum].pls.es.origin[i]) > 128) { // teleported, so don't lerp - VectorCopy (to->playerstate[cl.playernum].pls.velocity, cl.simvel); - VectorCopy (to->playerstate[cl.playernum].pls.origin, cl.simorg); + VectorCopy (to->playerstate[cl.playernum].pls.es.velocity, + cl.simvel); + VectorCopy (to->playerstate[cl.playernum].pls.es.origin, cl.simorg); return; } for (i = 0; i < 3; i++) { - cl.simorg[i] = from->playerstate[cl.playernum].pls.origin[i] + - f * (to->playerstate[cl.playernum].pls.origin[i] - - from->playerstate[cl.playernum].pls.origin[i]); - cl.simvel[i] = from->playerstate[cl.playernum].pls.velocity[i] + - f * (to->playerstate[cl.playernum].pls.velocity[i] - - from->playerstate[cl.playernum].pls.velocity[i]); + cl.simorg[i] = from->playerstate[cl.playernum].pls.es.origin[i] + + f * (to->playerstate[cl.playernum].pls.es.origin[i] - + from->playerstate[cl.playernum].pls.es.origin[i]); + cl.simvel[i] = from->playerstate[cl.playernum].pls.es.velocity[i] + + f * (to->playerstate[cl.playernum].pls.es.velocity[i] - + from->playerstate[cl.playernum].pls.es.velocity[i]); } } diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 763de6767..3b1ca0688 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -600,7 +600,7 @@ V_CalcViewRoll (void) v_dmg_time -= host_frametime; } - if (view_state->pls.flags & PF_DEAD) // PF_GIB will also set PF_DEAD + if (view_state->pls.es.flags & PF_DEAD) // PF_GIB will also set PF_DEAD r_data->refdef->viewangles[ROLL] = 80; // dead view angle } @@ -700,12 +700,12 @@ V_CalcRefdef (void) else if (r_data->scr_viewsize->int_val == 80) view->origin[2] += 0.5; - if (view_state->pls.flags & (PF_GIB | PF_DEAD)) { + if (view_state->pls.es.flags & (PF_GIB | PF_DEAD)) { view->renderer.model = NULL; } else { view->renderer.model = cl.model_precache[cl.stats[STAT_WEAPON]]; } - view->animation.frame = view_state->pls.weaponframe; + view->animation.frame = view_state->pls.es.weaponframe; view->renderer.skin = 0; // set up the refresh position @@ -757,9 +757,9 @@ V_RenderView (void) view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; view_state = &view_frame->playerstate[cl.playernum]; - if (view_state->pls.flags & PF_GIB) + if (view_state->pls.es.flags & PF_GIB) cl.viewheight = 8; // gib view height - else if (view_state->pls.flags & PF_DEAD) + else if (view_state->pls.es.flags & PF_DEAD) cl.viewheight = -16; // corpse view height else { cl.viewheight = DEFAULT_VIEWHEIGHT; // view height diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index a5d6b4db9..50c7a3d97 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -400,7 +400,7 @@ write_demoplayer (delta_t *delta, plent_state_t *from, plent_state_t *to, int flags; int j; - flags = to->flags >> 1; // convert PF_(GIB|DEAD) to DF_(GIB|DEAD) + flags = to->es.flags >> 1; // convert PF_(GIB|DEAD) to DF_(GIB|DEAD) flags &= DF_GIB | DF_DEAD; // PF_MSEC and PF_COMMAND aren't wanted if (full) { flags |= DF_ORIGIN | (DF_ORIGIN << 1) | (DF_ORIGIN << 2) @@ -408,55 +408,55 @@ write_demoplayer (delta_t *delta, plent_state_t *from, plent_state_t *to, | DF_EFFECTS | DF_SKINNUM | DF_WEAPONFRAME | DF_MODEL; } else { for (j = 0; j < 3; j++) - if (from->origin[j] != to->origin[j]) + if (from->es.origin[j] != to->es.origin[j]) flags |= DF_ORIGIN << j; for (j = 0; j < 3; j++) if (from->cmd.angles[j] != to->cmd.angles[j]) flags |= DF_ANGLES << j; - if (from->modelindex != to->modelindex) + if (from->es.modelindex != to->es.modelindex) flags |= DF_MODEL; - if ((from->effects & 0xff) != (to->effects & 0xff)) + if ((from->es.effects & 0xff) != (to->es.effects & 0xff)) flags |= DF_EFFECTS; - if (from->skinnum != to->skinnum) + if (from->es.skinnum != to->es.skinnum) flags |= DF_SKINNUM; - if (from->weaponframe != to->weaponframe) + if (from->es.weaponframe != to->es.weaponframe) flags |= DF_WEAPONFRAME; } MSG_WriteByte (msg, svc_playerinfo); - MSG_WriteByte (msg, to->number); + MSG_WriteByte (msg, to->es.number); MSG_WriteShort (msg, flags); - MSG_WriteByte (msg, to->frame); + MSG_WriteByte (msg, to->es.frame); for (j = 0; j < 3; j++) if (flags & (DF_ORIGIN << j)) - MSG_WriteCoord (msg, to->origin[j]); + MSG_WriteCoord (msg, to->es.origin[j]); for (j = 0; j < 3; j++) if (flags & (DF_ANGLES << j)) MSG_WriteAngle16 (msg, to->cmd.angles[j]); if (flags & DF_MODEL) - MSG_WriteByte (msg, to->modelindex); + MSG_WriteByte (msg, to->es.modelindex); if (flags & DF_SKINNUM) - MSG_WriteByte (msg, to->skinnum); + MSG_WriteByte (msg, to->es.skinnum); if (flags & DF_EFFECTS) - MSG_WriteByte (msg, to->effects); + MSG_WriteByte (msg, to->es.effects); if (flags & DF_WEAPONFRAME) - MSG_WriteByte (msg, to->weaponframe); + MSG_WriteByte (msg, to->es.weaponframe); } static void write_player (delta_t *delta, plent_state_t *from, plent_state_t *to, sizebuf_t *msg, int mask, int full) { - int flags = to->flags; + int flags = to->es.flags; int qf_bits = 0; int i; int ds = delta->delta_sequence & 0x7f; @@ -472,30 +472,30 @@ write_player (delta_t *delta, plent_state_t *from, plent_state_t *to, ds = -1; } else { for (i = 0; i < 3; i++) - if (from->velocity[i] != to->velocity[i]) + if (from->es.velocity[i] != to->es.velocity[i]) flags |= PF_VELOCITY1 << i; - if (from->modelindex != to->modelindex) + if (from->es.modelindex != to->es.modelindex) flags |= PF_MODEL; - if (from->skinnum != to->skinnum) + if (from->es.skinnum != to->es.skinnum) flags |= PF_SKINNUM; - if ((from->effects & 0xff) != (to->effects &0xff)) + if ((from->es.effects & 0xff) != (to->es.effects &0xff)) flags |= PF_EFFECTS; - if (from->weaponframe != to->weaponframe) + if (from->es.weaponframe != to->es.weaponframe) flags |= PF_WEAPONFRAME; - if (from->alpha != to->alpha) + if (from->es.alpha != to->es.alpha) qf_bits |= PF_ALPHA; - if (from->scale != to->scale) + if (from->es.scale != to->es.scale) qf_bits |= PF_SCALE; - if ((from->effects & 0xff00) != (to->effects & 0xff00)) + if ((from->es.effects & 0xff00) != (to->es.effects & 0xff00)) qf_bits |= PF_EFFECTS2; - if (from->glow_size != to->glow_size) + if (from->es.glow_size != to->es.glow_size) qf_bits |= PF_GLOWSIZE; - if (from->glow_color != to->glow_color) + if (from->es.glow_color != to->es.glow_color) qf_bits |= PF_GLOWCOLOR; - if (from->colormod != to->colormod) + if (from->es.colormod != to->es.colormod) qf_bits |= PF_COLORMOD; - if ((from->frame & 0xff00) != (to->frame & 0xff00)) + if ((from->es.frame & 0xff00) != (to->es.frame & 0xff00)) qf_bits |= PF_FRAME2; if (qf_bits) flags |= PF_QF; @@ -506,12 +506,12 @@ write_player (delta_t *delta, plent_state_t *from, plent_state_t *to, MSG_WriteByte (msg, svc_playerinfo); if (delta->type == dt_tp_qtv) MSG_WriteByte (msg, ds); - MSG_WriteByte (msg, to->number); + MSG_WriteByte (msg, to->es.number); MSG_WriteShort (msg, flags); - MSG_WriteCoordV (msg, to->origin); + MSG_WriteCoordV (msg, to->es.origin); - MSG_WriteByte (msg, to->frame); + MSG_WriteByte (msg, to->es.frame); if (flags & PF_MSEC) MSG_WriteByte (msg, to->msec); @@ -519,32 +519,32 @@ write_player (delta_t *delta, plent_state_t *from, plent_state_t *to, MSG_WriteDeltaUsercmd (msg, &from->cmd, &to->cmd); for (i = 0; i < 3; i++) if (flags & (PF_VELOCITY1 << i)) - MSG_WriteShort (msg, to->velocity[i]); + MSG_WriteShort (msg, to->es.velocity[i]); if (flags & PF_MODEL) - MSG_WriteByte (msg, to->modelindex); + MSG_WriteByte (msg, to->es.modelindex); if (flags & PF_SKINNUM) - MSG_WriteByte (msg, to->skinnum); + MSG_WriteByte (msg, to->es.skinnum); if (flags & PF_EFFECTS) - MSG_WriteByte (msg, to->effects); + MSG_WriteByte (msg, to->es.effects); if (flags & PF_WEAPONFRAME) - MSG_WriteByte (msg, to->weaponframe); + MSG_WriteByte (msg, to->es.weaponframe); if (flags & PF_QF) { MSG_WriteByte (msg, qf_bits); if (qf_bits & PF_ALPHA) - MSG_WriteByte (msg, to->alpha); + MSG_WriteByte (msg, to->es.alpha); if (qf_bits & PF_SCALE) - MSG_WriteByte (msg, to->scale); + MSG_WriteByte (msg, to->es.scale); if (qf_bits & PF_EFFECTS2) - MSG_WriteByte (msg, to->effects >> 8); + MSG_WriteByte (msg, to->es.effects >> 8); if (qf_bits & PF_GLOWSIZE) - MSG_WriteByte (msg, to->glow_size); + MSG_WriteByte (msg, to->es.glow_size); if (qf_bits & PF_GLOWCOLOR) - MSG_WriteByte (msg, to->glow_color); + MSG_WriteByte (msg, to->es.glow_color); if (qf_bits & PF_COLORMOD) - MSG_WriteByte (msg, to->colormod); + MSG_WriteByte (msg, to->es.colormod); if (qf_bits & PF_FRAME2) - MSG_WriteByte (msg, to->frame); + MSG_WriteByte (msg, to->es.frame); } } @@ -566,19 +566,19 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg) void (*write) (delta_t *, plent_state_t *, plent_state_t *, sizebuf_t *, int, int); - if (!null_player_state.alpha) { - null_player_state.alpha = 255; - null_player_state.scale = 16; - null_player_state.glow_size = 0; - null_player_state.glow_color = 254; - null_player_state.colormod = 255; + if (!null_player_state.es.alpha) { + null_player_state.es.alpha = 255; + null_player_state.es.scale = 16; + null_player_state.es.glow_size = 0; + null_player_state.es.glow_color = 254; + null_player_state.es.colormod = 255; } - null_player_state.modelindex = 0; + null_player_state.es.modelindex = 0; if (delta->client) { clent = delta->client->edict; spec_track = delta->client->spec_track; - null_player_state.modelindex = sv_playermodel; + null_player_state.es.modelindex = sv_playermodel; full = 0; // normal qw clients don't get real deltas on players } @@ -625,9 +625,9 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg) state = &pack->players[pack->num_players]; pack->num_players++; - state->number = j; - state->flags = 0; - VectorCopy (SVvector (ent, origin), state->origin); + state->es.number = j; + state->es.flags = 0; + VectorCopy (SVvector (ent, origin), state->es.origin); state->msec = min (255, 1000 * (sv.time - cl->localtime)); @@ -639,44 +639,44 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg) state->cmd.angles[0] = 0; } - VectorCopy (SVvector (ent, velocity), state->velocity); - state->modelindex = SVfloat (ent, modelindex); - state->frame = SVfloat (ent, frame); - state->skinnum = SVfloat (ent, skin); - state->effects = SVfloat (ent, effects); - state->weaponframe = SVfloat (ent, weaponframe); + VectorCopy (SVvector (ent, velocity), state->es.velocity); + state->es.modelindex = SVfloat (ent, modelindex); + state->es.frame = SVfloat (ent, frame); + state->es.skinnum = SVfloat (ent, skin); + state->es.effects = SVfloat (ent, effects); + state->es.weaponframe = SVfloat (ent, weaponframe); if (SVfloat (ent, health) <= 0) - state->flags |= PF_DEAD; + state->es.flags |= PF_DEAD; if (SVvector (ent, mins)[2] != -24) - state->flags |= PF_GIB; - state->flags |= PF_MSEC | PF_COMMAND; + state->es.flags |= PF_GIB; + state->es.flags |= PF_MSEC | PF_COMMAND; - state->alpha = 255; - state->scale = 16; - state->glow_size = 0; - state->glow_color = 254; - state->colormod = 255; + state->es.alpha = 255; + state->es.scale = 16; + state->es.glow_size = 0; + state->es.glow_color = 254; + state->es.colormod = 255; if (sv_fields.alpha != -1 && SVfloat (ent, alpha)) { float alpha = SVfloat (ent, alpha); - state->alpha = bound (0, alpha, 1) * 255.0; + state->es.alpha = bound (0, alpha, 1) * 255.0; } if (sv_fields.scale != -1 && SVfloat (ent, scale)) { float scale = SVfloat (ent, scale); - state->scale = bound (0, scale, 15.9375) * 16; + state->es.scale = bound (0, scale, 15.9375) * 16; } if (sv_fields.glow_size != -1 && SVfloat (ent, glow_size)) { int glow_size = SVfloat (ent, glow_size); - state->glow_size = bound (-1024, glow_size, 1016) >> 3; + state->es.glow_size = bound (-1024, glow_size, 1016) >> 3; } if (sv_fields.glow_color != -1 && SVfloat (ent, glow_color)) - state->glow_color = SVfloat (ent, glow_color); + state->es.glow_color = SVfloat (ent, glow_color); if (sv_fields.colormod != -1 && !VectorIsZero (SVvector (ent, colormod))) { float *colormod= SVvector (ent, colormod); - state->colormod = ((int) (bound (0, colormod[0], 1) * 7) << 5) | - ((int) (bound (0, colormod[1], 1) * 7) << 2) | - (int) (bound (0, colormod[2], 1) * 3); + state->es.colormod = ((int) (bound (0, colormod[0], 1) * 7) << 5) | + ((int) (bound (0, colormod[1], 1) * 7) << 2) | + (int) (bound (0, colormod[2], 1) * 3); } if (cl->spectator) { @@ -693,10 +693,10 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg) if (from_pack && from_pack->players) { while (k < from_pack->num_players - && from_pack->players[k].number < state->number) + && from_pack->players[k].es.number < state->es.number) k++; if (k < from_pack->num_players - && from_pack->players[k].number == state->number) { + && from_pack->players[k].es.number == state->es.number) { write (delta, &from_pack->players[k], state, msg, mask, full); continue; } From 36761192a6d6ff1f037ee0a49e746b93c01dede9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Mar 2021 15:23:35 +0900 Subject: [PATCH 1377/3664] [qw] Partially clean up muzzle flash handling It needs some more work (see FIXME in the code). --- include/client/effects.h | 4 ++++ libs/client/cl_effects.c | 39 ++++++++++++++++++++++----------------- qw/source/cl_parse.c | 30 ++++++++++++------------------ 3 files changed, 38 insertions(+), 35 deletions(-) diff --git a/include/client/effects.h b/include/client/effects.h index 1f1259274..9fea133d2 100644 --- a/include/client/effects.h +++ b/include/client/effects.h @@ -30,6 +30,8 @@ #ifndef __client_effects_h #define __client_effects_h +#include "QF/simd/types.h" + struct entity_s; struct entity_state_s; @@ -39,5 +41,7 @@ void CL_ModelEffects (struct entity_s *ent, int num, int glow_color, double time); void CL_EntityEffects (int num, struct entity_s *ent, struct entity_state_s *state, double time); +void CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num, + double time); #endif//__client_effects_h diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index 3030431a8..cc702587c 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -148,28 +148,33 @@ CL_ModelEffects (entity_t *ent, int num, int glow_color, double time) r_funcs->particles->R_GlowTrail (ent, glow_color); } +void +CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num, + double time) +{ + dlight_t *dl = r_funcs->R_AllocDlight (num); + if (dl) { + position += 18 * fv; + VectorCopy (position, dl->origin); + dl->origin[2] += zoffset; + dl->radius = 200 + (rand () & 31); + dl->die = time + 0.1; + dl->minlight = 32; + dl->color[0] = 0.2; + dl->color[1] = 0.1; + dl->color[2] = 0.05; + dl->color[3] = 0.7; + } +} + void CL_EntityEffects (int num, entity_t *ent, entity_state_t *state, double time) { - dlight_t *dl; - if (state->effects & EF_BRIGHTFIELD) r_funcs->particles->R_EntityParticles (ent); if (state->effects & EF_MUZZLEFLASH) { - dl = r_funcs->R_AllocDlight (num); - if (dl) { - vec4f_t position = Transform_GetWorldPosition (ent->transform); - vec4f_t fv = Transform_Forward (ent->transform); - position += 18 * fv; - VectorCopy (position, dl->origin); - dl->origin[2] += 16; - dl->radius = 200 + (rand () & 31); - dl->die = time + 0.1; - dl->minlight = 32; - dl->color[0] = 0.2; - dl->color[1] = 0.1; - dl->color[2] = 0.05; - dl->color[3] = 0.7; - } + vec4f_t position = Transform_GetWorldPosition (ent->transform); + vec4f_t fv = Transform_Forward (ent->transform); + CL_MuzzleFlash (position, fv, 16, num, time); } } diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 7366b4da0..095f636bc 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -65,6 +65,7 @@ #include "clview.h" #include "sbar.h" +#include "client/effects.h" #include "client/temp_entities.h" #include "qw/bothdefs.h" @@ -1255,12 +1256,14 @@ CL_SetStat (int stat, int value) } static void -CL_MuzzleFlash (void) +CL_ParseMuzzleFlash (void) { - dlight_t *dl; + //FIXME this should just enable the effect on the relevant entity and + //then automatic entity updates take care of the rest int i; player_state_t *pl; - vec3_t fv, rv, uv; + vec3_t f, r, u; + vec4f_t position = { 0, 0, 0, 1}, fv = {}; i = MSG_ReadShort (net_message); @@ -1269,23 +1272,14 @@ CL_MuzzleFlash (void) pl = &cl.frames[parsecountmod].playerstate[i - 1]; - dl = r_funcs->R_AllocDlight (i); - if (!dl) - return; - if (i - 1 == cl.playernum) - AngleVectors (cl.viewangles, fv, rv, uv); + AngleVectors (cl.viewangles, f, r, u); else - AngleVectors (pl->viewangles, fv, rv, uv); + AngleVectors (pl->viewangles, f, r, u); - VectorMultAdd (pl->pls.origin, 18, fv, dl->origin); - dl->radius = 200 + (rand () & 31); - dl->die = cl.time + 0.1; - dl->minlight = 32; - dl->color[0] = 0.2; - dl->color[1] = 0.1; - dl->color[2] = 0.05; - dl->color[3] = 0.7; + VectorCopy (f, fv); + VectorCopy (pl->pls.es.origin, position); + CL_MuzzleFlash (position, fv, 0, i, cl.time); } #define SHOWNET(x) \ @@ -1621,7 +1615,7 @@ CL_ParseServerMessage (void) break; case svc_muzzleflash: - CL_MuzzleFlash (); + CL_ParseMuzzleFlash (); break; case svc_updateuserinfo: From 8466de2325a874d787b422f84e95d044793cef90 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Mar 2021 16:19:49 +0900 Subject: [PATCH 1378/3664] [client] Use vec4_t in entity_state_t And clean up the mess (sort of:P) --- include/client/effects.h | 2 +- include/client/entities.h | 5 +++-- include/client/locs.h | 19 ++++++++++--------- include/clview.h | 3 ++- libs/client/cl_effects.c | 2 +- libs/client/locs.c | 31 +++++++++++++++++-------------- nq/include/client.h | 8 ++++---- nq/source/cl_demo.c | 4 ++-- nq/source/cl_ents.c | 16 ++++++++-------- nq/source/cl_parse.c | 13 +++++++------ nq/source/cl_view.c | 12 +++++++----- nq/source/sv_main.c | 3 ++- qtv/source/client.c | 3 ++- qtv/source/sv_parse.c | 5 +++-- qw/include/client.h | 4 ++-- qw/source/cl_cam.c | 8 ++++---- qw/source/cl_demo.c | 2 +- qw/source/cl_entparse.c | 2 +- qw/source/cl_ents.c | 7 ++++--- qw/source/cl_parse.c | 6 ++++-- qw/source/cl_pred.c | 11 +++-------- qw/source/cl_view.c | 20 +++++++++++--------- qw/source/sv_ents.c | 2 +- qw/source/sv_init.c | 4 ++-- qw/source/teamplay.c | 8 ++++---- 25 files changed, 106 insertions(+), 94 deletions(-) diff --git a/include/client/effects.h b/include/client/effects.h index 9fea133d2..dbec75769 100644 --- a/include/client/effects.h +++ b/include/client/effects.h @@ -35,7 +35,7 @@ struct entity_s; struct entity_state_s; -void CL_NewDlight (int key, vec3_t org, int effects, byte glow_size, +void CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size, byte glow_color, double time); void CL_ModelEffects (struct entity_s *ent, int num, int glow_color, double time); diff --git a/include/client/entities.h b/include/client/entities.h index 45420cbb7..fda534295 100644 --- a/include/client/entities.h +++ b/include/client/entities.h @@ -32,6 +32,7 @@ #define __client_entities_h #include "QF/qtypes.h" +#include "QF/simd/types.h" // entity_state_t is the information conveyed from the server // in an update message @@ -39,8 +40,8 @@ typedef struct entity_state_s { int number; // edict index unsigned flags; // nolerp, etc - vec3_t origin; - vec3_t velocity; + vec4f_t origin; + vec4f_t velocity; vec3_t angles; uint16_t modelindex; uint16_t frame; diff --git a/include/client/locs.h b/include/client/locs.h index 8786c6532..06817ef5a 100644 --- a/include/client/locs.h +++ b/include/client/locs.h @@ -29,23 +29,24 @@ #define __QF_locs_h #include "QF/qtypes.h" +#include "QF/simd/types.h" typedef struct { - vec3_t loc; - char *name; + vec4f_t loc; + char *name; } location_t; -location_t *locs_find(const vec3_t target) __attribute__((pure)); -void locs_add (const vec3_t location, const char *name); -void locs_del (const vec3_t loc); -void locs_edit (const vec3_t loc, const char *desc); +location_t *locs_find(vec4f_t target) __attribute__((pure)); +void locs_add (vec4f_t location, const char *name); +void locs_del (vec4f_t loc); +void locs_edit (vec4f_t loc, const char *desc); void locs_load(const char *filename); -void locs_mark (const vec3_t loc, const char *desc); -int locs_nearest (const vec3_t loc) __attribute__((pure)); +void locs_mark (vec4f_t loc, const char *desc); +int locs_nearest (vec4f_t loc) __attribute__((pure)); void locs_reset (void); void locs_save (const char *filename, qboolean gz); void map_to_loc (const char *mapname, char *filename); -void locs_draw (vec3_t simorg); +void locs_draw (vec4f_t simorg); #endif//__QF_locs_h diff --git a/include/clview.h b/include/clview.h index 7568ab23b..2b2cbffb2 100644 --- a/include/clview.h +++ b/include/clview.h @@ -30,6 +30,7 @@ #define __clview_h_ #include "QF/mathlib.h" +#include "QF/simd/types.h" #define INFO_CSHIFT_BONUS (1 << 0) #define INFO_CSHIFT_CONTENTS (1 << 1) @@ -39,7 +40,7 @@ void V_Init (void); void V_Init_Cvars (void); void V_RenderView (void); -float V_CalcRoll (const vec3_t angles, const vec3_t velocity); +float V_CalcRoll (const vec3_t angles, vec4f_t velocity); void V_UpdatePalette (void); void V_StartPitchDrift (void); void V_StopPitchDrift (void); diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index cc702587c..af40dc62c 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -47,7 +47,7 @@ #include "client/effects.h" void -CL_NewDlight (int key, vec3_t org, int effects, byte glow_size, +CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size, byte glow_color, double time) { float radius; diff --git a/libs/client/locs.c b/libs/client/locs.c index dd6a17d9f..07deee426 100644 --- a/libs/client/locs.c +++ b/libs/client/locs.c @@ -48,6 +48,8 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/simd/vec4f.h" + #include "QF/plugin/vid_render.h" //FIXME #include "compat.h" @@ -63,7 +65,7 @@ int locations_count = 0; int location_blocks = 0; int -locs_nearest (const vec3_t loc) +locs_nearest (vec4f_t loc) { float best_distance = 9999999, distance; int i, j = -1; @@ -71,7 +73,8 @@ locs_nearest (const vec3_t loc) for (i = 0; i < locations_count; i++) { cur = locations[i]; - distance = VectorDistance_fast (loc, cur->loc); + vec4f_t d = loc - cur->loc; + distance = dotf (d, d)[0]; if ((distance < best_distance)) { best_distance = distance; j = i; @@ -81,7 +84,7 @@ locs_nearest (const vec3_t loc) } location_t * -locs_find (const vec3_t target) +locs_find (vec4f_t target) { int i; @@ -110,7 +113,7 @@ locs_more (void) } void -locs_add (const vec3_t location, const char *name) +locs_add (vec4f_t location, const char *name) { int num; @@ -137,7 +140,7 @@ locs_load (const char *filename) const char *tmp; char *t1, *t2; const char *line; - vec3_t loc; + vec4f_t loc; QFile *file; tmp = va (0, "maps/%s", filename); @@ -216,7 +219,7 @@ locs_save (const char *filename, qboolean gz) } void -locs_mark (const vec3_t loc, const char *desc) +locs_mark (vec4f_t loc, const char *desc) { locs_add (loc, desc); Sys_Printf ("Marked current location: %s\n", desc); @@ -229,14 +232,14 @@ locs_mark (const vec3_t loc, const char *desc) call with NULL description to modify location vectors */ void -locs_edit (const vec3_t loc, const char *desc) +locs_edit (vec4f_t loc, const char *desc) { int i; if (locations_count) { i = locs_nearest (loc); if (!desc) { - VectorCopy (loc, locations[i]->loc); + locations[i]->loc = loc; Sys_Printf ("Moving location marker for %s\n", locations[i]->name); } else { @@ -250,7 +253,7 @@ locs_edit (const vec3_t loc, const char *desc) } void -locs_del (const vec3_t loc) +locs_del (vec4f_t loc) { int i; @@ -282,12 +285,12 @@ map_to_loc (const char *mapname, char *filename) } void -locs_draw (vec3_t simorg) +locs_draw (vec4f_t simorg) { //FIXME custom ent rendering code would be nice dlight_t *dl; location_t *nearloc; - vec3_t trueloc; + vec4f_t trueloc; int i; nearloc = locs_find (simorg); @@ -302,14 +305,14 @@ locs_draw (vec3_t simorg) dl->color[2] = 0; dl->color[3] = 0.7; } - VectorCopy (nearloc->loc, trueloc); + trueloc = nearloc->loc; r_funcs->particles->R_Particle_New (pt_smokecloud, part_tex_smoke, - trueloc, 2.0, + &trueloc[0], 2.0,//FIXME vec3_origin, r_data->realtime + 9.0, 254, 0.25 + qfrandom (0.125), 0.0); for (i = 0; i < 15; i++) r_funcs->particles->R_Particle_NewRandom (pt_fallfade, - part_tex_dot, trueloc, 12, + part_tex_dot, &trueloc[0], 12,//FIXME 0.7, 96, r_data->realtime + 5.0, 104 + (rand () & 7), 1.0, 0.0); } diff --git a/nq/include/client.h b/nq/include/client.h index 07c43ae87..4af07cd24 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -162,13 +162,13 @@ typedef struct { // server each frame. The server sets punchangle when the view is temporarily // offset, and an angle reset commands at the start of each level and after // teleporting. - int mindex; - vec3_t mviewangles[2]; // During demo playback viewangles is lerped + int frameIndex; + vec3_t frameViewAngles[2]; // During demo playback viewangles is lerped // between these vec3_t viewangles; - vec3_t mvelocity[2]; // Update by server, used for lean+bob + vec4f_t frameVelocity[2]; // Update by server, used for lean+bob // (0 is newest) - vec3_t velocity; // Lerped between mvelocity[0] and [1] + vec4f_t velocity; // Lerped between frameVelocity[0] and [1] vec3_t punchangle; // Temporary offset // pitch drifting vars diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 772778b92..39cdf9d24 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -182,14 +182,14 @@ read_demopacket (void) if (net_message->message->cursize > MAX_DEMMSG) Host_Error ("Demo message > MAX_DEMMSG: %d/%d", net_message->message->cursize, MAX_DEMMSG); - VectorCopy (cl.mviewangles[0], cl.mviewangles[1]); + VectorCopy (cl.frameViewAngles[0], cl.frameViewAngles[1]); for (i = 0; i < 3; i++) { r = Qread (cls.demofile, &f, 4); if (r != 4) { CL_StopPlayback (); return 0; } - cl.mviewangles[0][i] = LittleFloat (f); + cl.frameViewAngles[0][i] = LittleFloat (f); } r = Qread (cls.demofile, net_message->message->data, net_message->message->cursize); diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 957cadb6a..e8aecb26c 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -156,19 +156,18 @@ CL_RelinkEntities (void) frac = CL_LerpPoint (); // interpolate player info - for (i = 0; i < 3; i++) - cl.velocity[i] = cl.mvelocity[1][i] + - frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); + cl.velocity = cl.frameVelocity[1] + + frac * (cl.frameVelocity[0] - cl.frameVelocity[1]); if (cls.demoplayback) { // interpolate the angles for (j = 0; j < 3; j++) { - d = cl.mviewangles[0][j] - cl.mviewangles[1][j]; + d = cl.frameViewAngles[0][j] - cl.frameViewAngles[1][j]; if (d > 180) d -= 360; else if (d < -180) d += 360; - cl.viewangles[j] = cl.mviewangles[1][j] + frac * d; + cl.viewangles[j] = cl.frameViewAngles[1][j] + frac * d; } } @@ -176,8 +175,8 @@ CL_RelinkEntities (void) // start on the entity after the world for (i = 1; i < cl.num_entities; i++) { - new = &nq_entstates.frame[0 + cl.mindex][i]; - old = &nq_entstates.frame[1 - cl.mindex][i]; + new = &nq_entstates.frame[0 + cl.frameIndex][i]; + old = &nq_entstates.frame[1 - cl.frameIndex][i]; ent = &cl_entities[i]; renderer = &ent->renderer; animation = &ent->animation; @@ -293,7 +292,8 @@ CL_RelinkEntities (void) CL_TransformEntity (ent, angles); } CL_EntityEffects (i, ent, new, cl.time); - CL_NewDlight (i, ent->origin, new->effects, new->glow_size, + vec4f_t org = { VectorExpand (ent->origin), 1}; //FIXME + CL_NewDlight (i, org, new->effects, new->glow_size, new->glow_color, cl.time); if (VectorDistance_fast (old->origin, ent->origin) > (256 * 256)) VectorCopy (ent->origin, old->origin); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 260920d13..ccf535e18 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -491,7 +491,7 @@ CL_ParseUpdate (int bits) num = MSG_ReadByte (net_message); baseline = CL_EntityNum (num); - state = &nq_entstates.frame[0 + cl.mindex][num]; + state = &nq_entstates.frame[0 + cl.frameIndex][num]; for (i = 0; i < 16; i++) if (bits & (1 << i)) @@ -620,7 +620,8 @@ CL_ParseBaseline (entity_state_t *baseline, int version) baseline->colormap = MSG_ReadByte (net_message); baseline->skinnum = MSG_ReadByte (net_message); - MSG_ReadCoordAngleV (net_message, baseline->origin, baseline->angles); + MSG_ReadCoordAngleV (net_message, &baseline->origin[0], baseline->angles); + baseline->origin[3] = 1;//FIXME if (bits & B_ALPHA) baseline->alpha = MSG_ReadByte (net_message); @@ -659,17 +660,17 @@ CL_ParseClientdata (void) else cl.idealpitch = 0; - VectorCopy (cl.mvelocity[0], cl.mvelocity[1]); + cl.frameVelocity[1] = cl.frameVelocity[0]; for (i = 0; i < 3; i++) { if (bits & (SU_PUNCH1 << i)) cl.punchangle[i] = ((signed char) MSG_ReadByte (net_message)); else cl.punchangle[i] = 0; if (bits & (SU_VELOCITY1 << i)) - cl.mvelocity[0][i] = ((signed char) MSG_ReadByte (net_message)) + cl.frameVelocity[0][i] = ((signed char) MSG_ReadByte (net_message)) * 16; else - cl.mvelocity[0][i] = 0; + cl.frameVelocity[0][i] = 0; } //FIXME @@ -918,7 +919,7 @@ CL_ParseServerMessage (void) case svc_time: cl.mtime[1] = cl.mtime[0]; cl.mtime[0] = MSG_ReadFloat (net_message); - cl.mindex = !cl.mindex; + cl.frameIndex = !cl.frameIndex; break; case svc_print: diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index e6812a263..fa62de0fd 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -33,6 +33,8 @@ #include "QF/msg.h" #include "QF/screen.h" +#include "QF/simd/vec4f.h" + #include "QF/plugin/vid_render.h" #include "compat.h" @@ -87,7 +89,7 @@ cshift_t cshift_bonus = { {215, 186, 60}, 50}; #define sqr(x) ((x) * (x)) float -V_CalcRoll (const vec3_t angles, const vec3_t velocity) +V_CalcRoll (const vec3_t angles, vec4f_t velocity) { float side, sign, value; vec3_t forward, right, up; @@ -110,7 +112,7 @@ V_CalcRoll (const vec3_t angles, const vec3_t velocity) static float V_CalcBob (void) { - vec_t *velocity = cl.velocity; + vec4f_t velocity = cl.velocity; float cycle; static double bobtime; static float bob; @@ -132,8 +134,8 @@ V_CalcBob (void) // bob is proportional to velocity in the xy plane // (don't count Z, or jumping messes it up) - - bob = sqrt (sqr (velocity[0]) + sqr (velocity[1])) * cl_bob->value; + velocity[2] = 0; + bob = sqrt (dotf (velocity, velocity)[0]) * cl_bob->value; bob = bob * 0.3 + bob * 0.7 * sin (cycle * M_PI); if (bob > 4) bob = 4; @@ -582,7 +584,7 @@ V_CalcViewRoll (void) { float side; vec_t *angles = cl_entities[cl.viewentity].angles; - vec_t *velocity = cl.velocity; + vec4f_t velocity = cl.velocity; side = V_CalcRoll (angles, velocity); r_data->refdef->viewangles[ROLL] += side; diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 38604e66c..d8a98b5b4 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1037,7 +1037,8 @@ SV_CreateBaseline (void) MSG_WriteByte (&sv.signon, baseline->colormap); MSG_WriteByte (&sv.signon, baseline->skinnum); - MSG_WriteCoordAngleV (&sv.signon, baseline->origin, baseline->angles); + MSG_WriteCoordAngleV (&sv.signon, &baseline->origin[0],//FIXME + baseline->angles); if (bits & B_ALPHA) MSG_WriteByte (&sv.signon, baseline->alpha); diff --git a/qtv/source/client.c b/qtv/source/client.c index 6da363953..43e3f424f 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -682,7 +682,8 @@ write_player (int num, plent_state_t *pl, server_t *sv, sizebuf_t *msg) MSG_WriteByte (msg, num); MSG_WriteShort (msg, pflags); - MSG_WriteCoordV (msg, pl->es.origin); + MSG_WriteCoordV (msg, &pl->es.origin[0]);//FIXME + pl->es.origin[3] = 1; MSG_WriteByte (msg, pl->es.frame); diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index 268e9999d..fcf5c3616 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -515,7 +515,7 @@ parse_player_delta (qmsg_t *msg, plent_state_t *from, plent_state_t *to) int flags; flags = to->es.flags = MSG_ReadShort (msg); - MSG_ReadCoordV (msg, to->es.origin); + MSG_ReadCoordV (msg, &to->es.origin[0]); to->es.frame = (to->es.frame & 0xff00) | MSG_ReadByte (msg); if (flags & PF_MSEC) to->msec = MSG_ReadByte (msg); @@ -752,7 +752,8 @@ parse_baseline (qmsg_t *msg, entity_state_t *ent) ent->frame = MSG_ReadByte (msg); ent->colormap = MSG_ReadByte (msg); ent->skinnum = MSG_ReadByte (msg); - MSG_ReadCoordAngleV (msg, ent->origin, ent->angles); + MSG_ReadCoordAngleV (msg, &ent->origin[0], ent->angles); //FIXME + ent->origin[3] = 1; ent->colormod = 255; ent->alpha = 255; ent->scale = 16; diff --git a/qw/include/client.h b/qw/include/client.h index 3c64c128b..5389579c4 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -222,8 +222,8 @@ typedef struct { // the client simulates or interpolates movement to get these values double time; // this is the time value that the client // is rendering at. always <= realtime - vec3_t simorg; - vec3_t simvel; + vec4f_t simorg; + vec4f_t simvel; vec3_t simangles; vec3_t punchangle; // temporary view kick from weapon firing diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 91e7a44eb..1b1959f13 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -221,7 +221,7 @@ Cam_TryFlyby (player_state_t * self, player_state_t * player, vec3_t vec, VectorMultAdd (player->pls.es.origin, 800, vec, v); // v is endpos // fake a player move - trace = Cam_DoTrace (player->pls.es.origin, v); + trace = Cam_DoTrace (&player->pls.es.origin[0], v);//FIXME if ( /* trace.inopen || */ trace.inwater) return 9999; VectorCopy (trace.endpos, vec); @@ -230,7 +230,7 @@ Cam_TryFlyby (player_state_t * self, player_state_t * player, vec3_t vec, if (len < 32 || len > 800) return 9999; if (checkvis) { - trace = Cam_DoTrace (self->pls.es.origin, vec); + trace = Cam_DoTrace (&self->pls.es.origin[0], vec);//FIXME if (trace.fraction != 1 || trace.inwater) return 9999; @@ -242,13 +242,13 @@ Cam_TryFlyby (player_state_t * self, player_state_t * player, vec3_t vec, // Is player visible? static qboolean -Cam_IsVisible (player_state_t * player, vec3_t vec) +Cam_IsVisible (player_state_t *player, vec3_t vec) { float d; trace_t trace; vec3_t v; - trace = Cam_DoTrace (player->pls.es.origin, vec); + trace = Cam_DoTrace (&player->pls.es.origin[0], vec);//FIXME if (trace.fraction != 1 || /* trace.inopen || */ trace.inwater) return false; // check distance, don't let the player get too far away or too close diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 31594d51f..0694b5f25 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -797,7 +797,7 @@ demo_start_recording (int track) MSG_WriteByte (&buf, es->frame); MSG_WriteByte (&buf, es->colormap); MSG_WriteByte (&buf, es->skinnum); - MSG_WriteCoordAngleV (&buf, es->origin, es->angles); + MSG_WriteCoordAngleV (&buf, &es->origin[0], es->angles);//FIXME if (buf.cursize > MAX_MSGLEN / 2) { CL_WriteRecordDemoMessage (&buf, seq++); diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index b1b5d3386..a7716b729 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -427,7 +427,7 @@ CL_ParsePlayerinfo (void) flags = state->pls.es.flags = MSG_ReadShort (net_message); state->messagenum = cl.parsecount; - MSG_ReadCoordV (net_message, state->pls.es.origin); + MSG_ReadCoordV (net_message, &state->pls.es.origin[0]);//FIXME state->pls.es.frame = MSG_ReadByte (net_message); diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 1e8ab80d9..606fc1ce8 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -356,7 +356,8 @@ CL_LinkPlayers (void) player_state_t exact; player_state_t *state; qboolean clientplayer; - vec3_t org, ang = {0, 0, 0}; + vec3_t ang = {0, 0, 0}; + vec4f_t org; playertime = realtime - cls.latency + 0.02; if (playertime > realtime) @@ -377,11 +378,11 @@ CL_LinkPlayers (void) // spawn light flashes, even ones coming from invisible objects if (j == cl.playernum) { - VectorCopy (cl.simorg, org); + org = cl.simorg; r_data->player_entity = &cl_player_ents[j]; clientplayer = true; } else { - VectorCopy (state->pls.es.origin, org); + org = state->pls.es.origin; clientplayer = false; } if (info->chat && info->chat->value[0] != '0') { diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 095f636bc..bfd1fa5a2 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -945,7 +945,8 @@ CL_ParseBaseline (entity_state_t *es) es->colormap = MSG_ReadByte (net_message); es->skinnum = MSG_ReadByte (net_message); - MSG_ReadCoordAngleV (net_message, es->origin, es->angles); + MSG_ReadCoordAngleV (net_message, &es->origin[0], es->angles);//FIXME + es->origin[3] = 1; // LordHavoc: set up baseline to for new effects (alpha, colormod, etc) es->colormod = 255; @@ -1541,7 +1542,8 @@ CL_ParseServerMessage (void) cl.completed_time = realtime; r_data->vid->recalc_refdef = true; // go to full screen Sys_MaskPrintf (SYS_DEV, "intermission simorg: "); - MSG_ReadCoordV (net_message, cl.simorg); + MSG_ReadCoordV (net_message, &cl.simorg[0]);//FIXME + cl.simorg[3] = 1; for (i = 0; i < 3; i++) Sys_MaskPrintf (SYS_DEV, "%f ", cl.simorg[i]); Sys_MaskPrintf (SYS_DEV, "\nintermission simangles: "); diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index 1fe115949..f48533673 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -184,14 +184,9 @@ CL_PredictMove (void) return; } - for (i = 0; i < 3; i++) { - cl.simorg[i] = from->playerstate[cl.playernum].pls.es.origin[i] + - f * (to->playerstate[cl.playernum].pls.es.origin[i] - - from->playerstate[cl.playernum].pls.es.origin[i]); - cl.simvel[i] = from->playerstate[cl.playernum].pls.es.velocity[i] + - f * (to->playerstate[cl.playernum].pls.es.velocity[i] - - from->playerstate[cl.playernum].pls.es.velocity[i]); - } + cl.simorg = from->playerstate[cl.playernum].pls.es.origin + + f * (to->playerstate[cl.playernum].pls.es.origin - + from->playerstate[cl.playernum].pls.es.origin); } void diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 3b1ca0688..9497e3ef9 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -33,6 +33,8 @@ #include "QF/msg.h" #include "QF/screen.h" +#include "QF/simd/vec4f.h" + #include "compat.h" #include "clview.h" @@ -93,7 +95,7 @@ cshift_t cshift_bonus = { {215, 186, 60}, 50}; #define sqr(x) ((x) * (x)) float -V_CalcRoll (const vec3_t angles, const vec3_t velocity) +V_CalcRoll (const vec3_t angles, const vec4f_t velocity) { float side, sign, value; vec3_t forward, right, up; @@ -116,7 +118,7 @@ V_CalcRoll (const vec3_t angles, const vec3_t velocity) static float V_CalcBob (void) { - vec_t *velocity = cl.simvel; + vec4f_t velocity = cl.simvel; float cycle; static double bobtime; static float bob; @@ -138,8 +140,8 @@ V_CalcBob (void) // bob is proportional to velocity in the xy plane // (don't count Z, or jumping messes it up) - - bob = sqrt (sqr (velocity[0]) + sqr (velocity[1])) * cl_bob->value; + velocity[2] = 0; + bob = sqrt (dotf (velocity, velocity)[0]) * cl_bob->value; bob = bob * 0.3 + bob * 0.7 * sin (cycle * M_PI); if (bob > 4) bob = 4; @@ -240,7 +242,7 @@ V_ParseDamage (void) { float count, side; int armor, blood; - vec_t *origin = cl.simorg; + vec4f_t origin = cl.simorg; vec_t *angles = cl.simangles; vec3_t from, forward, right, up; @@ -535,7 +537,7 @@ CalcGunAngle (void) static void V_BoundOffsets (void) { - vec_t *origin = cl.simorg; + vec4f_t origin = cl.simorg; // absolutely bound refresh reletive to entity clipping hull // so the view can never be inside a solid wall @@ -587,7 +589,7 @@ V_CalcViewRoll (void) { float side; vec_t *angles = cl.simangles; - vec_t *velocity = cl.simvel; + vec4f_t velocity = cl.simvel; side = V_CalcRoll (angles, velocity); r_data->refdef->viewangles[ROLL] += side; @@ -609,7 +611,7 @@ V_CalcIntermissionRefdef (void) { entity_t *view; float old; - vec_t *origin = cl.simorg; + vec4f_t origin = cl.simorg; vec_t *angles = cl.simangles; // view is the weapon model (visible only from inside body) @@ -635,7 +637,7 @@ V_CalcRefdef (void) static float oldz = 0; int i; vec3_t forward, right, up; - vec_t *origin = cl.simorg; + vec4f_t origin = cl.simorg; vec_t *viewangles = cl.simangles; V_DriftPitch (); diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index 50c7a3d97..ccbf9278b 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -509,7 +509,7 @@ write_player (delta_t *delta, plent_state_t *from, plent_state_t *to, MSG_WriteByte (msg, to->es.number); MSG_WriteShort (msg, flags); - MSG_WriteCoordV (msg, to->es.origin); + MSG_WriteCoordV (msg, &to->es.origin[0]);//FIXME MSG_WriteByte (msg, to->es.frame); diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index e0a370f92..6fbd6cbc7 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -167,8 +167,8 @@ SV_CreateBaseline (void) MSG_WriteByte (&sv.signon, SVdata (svent)->state.colormap); MSG_WriteByte (&sv.signon, SVdata (svent)->state.skinnum); - MSG_WriteCoordAngleV (&sv.signon, SVdata (svent)->state.origin, - SVdata (svent)->state.angles); + MSG_WriteCoordAngleV (&sv.signon, &SVdata (svent)->state.origin[0], + SVdata (svent)->state.angles);//FIXME } } diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index 75e6aefe3..159da95f0 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -58,7 +58,7 @@ #include "qw/include/client.h" static qboolean died = false, recorded_location = false; -static vec3_t death_location, last_recorded_location; +static vec4f_t death_location, last_recorded_location; cvar_t *cl_deadbodyfilter; cvar_t *cl_gibfilter; @@ -165,7 +165,7 @@ Team_ParseSay (dstring_t *buf, const char *s) location = locs_find (death_location); if (location) { recorded_location = true; - VectorCopy (death_location, last_recorded_location); + last_recorded_location = death_location; t1 = location->name; break; } @@ -187,7 +187,7 @@ Team_ParseSay (dstring_t *buf, const char *s) location = locs_find (cl.simorg); if (location) { recorded_location = true; - VectorCopy (cl.simorg, last_recorded_location); + last_recorded_location = cl.simorg; t1 = location->name; } else snprintf (t2, sizeof (t2), "Unknown!"); @@ -279,7 +279,7 @@ void Team_Dead (void) { died = true; - VectorCopy (cl.simorg, death_location); + death_location = cl.simorg; } void From 2015474468ac316b51e2276cc37a055c62cb4fcc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Mar 2021 11:48:53 +0900 Subject: [PATCH 1379/3664] Move and clean up clview.h Redundant or dead prototypes deleted, and the client/view.h seems a good place for the file. --- include/Makemodule.am | 2 +- include/{clview.h => client/view.h} | 13 ++++--------- libs/video/renderer/sw32/draw.c | 3 ++- nq/source/cl_main.c | 2 +- nq/source/cl_view.c | 5 +++-- qw/source/cl_entparse.c | 2 +- qw/source/cl_ents.c | 2 +- qw/source/cl_input.c | 3 ++- qw/source/cl_main.c | 2 +- qw/source/cl_parse.c | 2 +- qw/source/cl_screen.c | 3 ++- qw/source/cl_view.c | 7 ++++--- 12 files changed, 23 insertions(+), 23 deletions(-) rename include/{clview.h => client/view.h} (85%) diff --git a/include/Makemodule.am b/include/Makemodule.am index 645a820bf..0755ed1b5 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -11,7 +11,6 @@ EXTRA_DIST += \ include/block16.h \ include/block8.h \ include/buildnum.h \ - include/clview.h \ include/compat.h \ include/context_sdl.h \ include/context_x11.h \ @@ -80,6 +79,7 @@ EXTRA_DIST += \ include/client/entities.h \ include/client/temp_entities.h \ include/client/locs.h \ + include/client/view.h \ include/qw/bothdefs.h \ include/qw/msg_backbuf.h \ include/qw/msg_ucmd.h \ diff --git a/include/clview.h b/include/client/view.h similarity index 85% rename from include/clview.h rename to include/client/view.h index 2b2cbffb2..756eb1d21 100644 --- a/include/clview.h +++ b/include/client/view.h @@ -1,5 +1,5 @@ /* - clview.h + view.h (description) @@ -26,8 +26,8 @@ */ // view.h -#ifndef __clview_h_ -#define __clview_h_ +#ifndef __client_view_h_ +#define __client_view_h_ #include "QF/mathlib.h" #include "QF/simd/types.h" @@ -41,14 +41,9 @@ void V_Init (void); void V_Init_Cvars (void); void V_RenderView (void); float V_CalcRoll (const vec3_t angles, vec4f_t velocity); -void V_UpdatePalette (void); void V_StartPitchDrift (void); void V_StopPitchDrift (void); -void V_RenderView (void); -void V_UpdatePalette (void); -void V_Register (void); void V_SetContentsColor (int contents); -void V_CalcBlend (void); -#endif // __clview_h_ +#endif // __client_view_h_ diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c index 13454c437..fdb24e2c5 100644 --- a/libs/video/renderer/sw32/draw.c +++ b/libs/video/renderer/sw32/draw.c @@ -1362,6 +1362,7 @@ sw32_Draw_BlendScreen (quat_t color) } break; default: - Sys_Error("V_UpdatePalette: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("sw32_Draw_BlendScreen: unsupported r_pixbytes %i", + sw32_r_pixbytes); } } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 25ff7bd39..e2c222713 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -49,10 +49,10 @@ #include "QF/plugin/vid_render.h" #include "compat.h" -#include "clview.h" #include "sbar.h" #include "client/temp_entities.h" +#include "client/view.h" #include "nq/include/chase.h" #include "nq/include/cl_skin.h" diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index fa62de0fd..1ccf06d98 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -38,7 +38,8 @@ #include "QF/plugin/vid_render.h" #include "compat.h" -#include "clview.h" + +#include "client/view.h" #include "nq/include/chase.h" #include "nq/include/client.h" @@ -393,7 +394,7 @@ V_CalcPowerupCshift (void) LordHavoc made this a real, true alpha blend. Cleaned it up a bit, but otherwise this is his code. --KB */ -void +static void V_CalcBlend (void) { float a2, a3; diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index a7716b729..60c8cf2c4 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -42,9 +42,9 @@ #include "QF/sys.h" #include "compat.h" -#include "clview.h" #include "client/temp_entities.h" +#include "client/view.h" #include "qw/msg_ucmd.h" #include "qw/pmove.h" diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 606fc1ce8..b70b143cc 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -43,12 +43,12 @@ #include "QF/sys.h" #include "compat.h" -#include "clview.h" #include "d_iface.h" #include "client/effects.h" #include "client/locs.h" #include "client/temp_entities.h" +#include "client/view.h" #include "qw/bothdefs.h" #include "qw/msg_ucmd.h" diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 55ef38f5d..5a2fe2b6e 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -46,7 +46,8 @@ #include "QF/va.h" #include "compat.h" -#include "clview.h" + +#include "client/view.h" #include "qw/msg_ucmd.h" diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index ea143c9ae..be73db0e7 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -92,11 +92,11 @@ #include "QF/plugin/console.h" #include "buildnum.h" -#include "clview.h" #include "compat.h" #include "sbar.h" #include "client/temp_entities.h" +#include "client/view.h" #include "qw/bothdefs.h" #include "qw/pmove.h" diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index bfd1fa5a2..b75355fa1 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -62,11 +62,11 @@ #include "QF/va.h" #include "compat.h" -#include "clview.h" #include "sbar.h" #include "client/effects.h" #include "client/temp_entities.h" +#include "client/view.h" #include "qw/bothdefs.h" #include "qw/pmove.h" diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 7827c30db..22c8b5b96 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -44,9 +44,10 @@ #include "QF/pcx.h" #include "QF/screen.h" -#include "clview.h" #include "sbar.h" +#include "client/view.h" + #include "qw/include/client.h" static qpic_t *scr_net; diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 9497e3ef9..f20d5747a 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -36,7 +36,8 @@ #include "QF/simd/vec4f.h" #include "compat.h" -#include "clview.h" + +#include "client/view.h" #include "qw/bothdefs.h" @@ -95,7 +96,7 @@ cshift_t cshift_bonus = { {215, 186, 60}, 50}; #define sqr(x) ((x) * (x)) float -V_CalcRoll (const vec3_t angles, const vec4f_t velocity) +V_CalcRoll (const vec3_t angles, vec4f_t velocity) { float side, sign, value; vec3_t forward, right, up; @@ -399,7 +400,7 @@ V_CalcPowerupCshift (void) LordHavoc made this a real, true alpha blend. Cleaned it up a bit, but otherwise this is his code. --KB */ -void +static void V_CalcBlend (void) { float a2, a3; From 5158cc5527556219fcff0fcf0b63bbc3a9037294 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Mar 2021 11:04:47 +0900 Subject: [PATCH 1380/3664] [util] Add normal and magnitude float vector functions --- include/QF/simd/vec4f.h | 37 ++++++++++++++++++++++++++ libs/video/renderer/glsl/glsl_sprite.c | 4 +-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 85eb252eb..8fe207b74 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -93,6 +93,9 @@ GNU89INLINE inline vec4f_t qrotf (vec4f_t a, vec4f_t b) __attribute__((const)); GNU89INLINE inline vec4f_t qconjf (vec4f_t q) __attribute__((const)); GNU89INLINE inline vec4f_t loadvec3f (const float v3[3]) __attribute__((pure, access(read_only, 1))); GNU89INLINE inline void storevec3f (float v3[3], vec4f_t v4) __attribute__((access (write_only, 1))); +GNU89INLINE inline vec4f_t normalf (vec4f_t v) __attribute__((pure)); +GNU89INLINE inline vec4f_t magnitudef (vec4f_t v) __attribute__((pure)); +GNU89INLINE inline vec4f_t magnitude3f (vec4f_t v) __attribute__((pure)); #ifndef IMPLEMENT_VEC4F_Funcs GNU89INLINE inline @@ -288,4 +291,38 @@ storevec3f (float v3[3], vec4f_t v4) v3[2] = v4[2]; } +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +normalf (vec4f_t v) +{ + return v / vsqrtf (dotf (v, v)); +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +magnitudef (vec4f_t v) +{ + return vsqrtf (dotf (v, v)); +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +magnitude3f (vec4f_t v) +{ + v[3] = 0; + return vsqrtf (dotf (v, v)); +} + #endif//__QF_simd_vec4f_h diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 63704ebfa..4d35bc8d6 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -243,7 +243,7 @@ R_DrawSprite (void) VectorSet (0, 0, 1, svup); // CrossProduct (svup, -r_origin, svright) VectorSet (tvec[1], -tvec[0], 0, svright); - svright /= vsqrtf (dotf (svright, svright)); + svright = normalf (svright); // CrossProduct (svright, svup, svpn); VectorSet (-svright[1], svright[0], 0, svpn); break; @@ -268,7 +268,7 @@ R_DrawSprite (void) VectorSet (0, 0, 1, svup); // CrossProduct (svup, -r_origin, svright) VectorSet (vpn[1], -vpn[0], 0, svright); - svright /= vsqrtf (dotf (svright, svright)); + svright = normalf (svright); // CrossProduct (svright, svup, svpn); VectorSet (-svright[1], svright[0], 0, svpn); break; From 5bf21931c7b40d2becb32377d7183f10753fea47 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Mar 2021 20:18:45 +0900 Subject: [PATCH 1381/3664] [renderer] Remove more old fields from entity_t The only transform related field remaining is old_origin. This also brings the renderer closer to using simd (lots of stuff to fix still, though). --- include/QF/render.h | 11 +- include/client/entities.h | 3 +- include/client/view.h | 15 + libs/client/cl_effects.c | 3 +- libs/client/cl_entities.c | 21 +- libs/client/cl_temp_entities.c | 84 ++--- libs/client/locs.c | 2 +- libs/video/renderer/gl/gl_dyn_part.c | 79 +++-- libs/video/renderer/gl/gl_lightmap.c | 16 +- libs/video/renderer/gl/gl_mod_alias.c | 34 +- libs/video/renderer/gl/gl_mod_iqm.c | 1 - libs/video/renderer/gl/gl_mod_sprite.c | 8 - libs/video/renderer/gl/gl_rmain.c | 59 ++-- libs/video/renderer/gl/gl_rmisc.c | 5 +- libs/video/renderer/gl/gl_rsurf.c | 13 +- libs/video/renderer/gl/gl_sky.c | 20 +- libs/video/renderer/gl/gl_sky_clip.c | 14 +- libs/video/renderer/glsl/glsl_alias.c | 7 +- libs/video/renderer/glsl/glsl_bsp.c | 16 +- libs/video/renderer/glsl/glsl_iqm.c | 12 +- libs/video/renderer/glsl/glsl_lightmap.c | 10 +- libs/video/renderer/glsl/glsl_main.c | 17 +- libs/video/renderer/glsl/glsl_particles.c | 81 +++-- libs/video/renderer/glsl/glsl_sprite.c | 24 +- libs/video/renderer/r_efrag.c | 6 +- libs/video/renderer/sw/d_edge.c | 7 +- libs/video/renderer/sw/sw_rmain.c | 41 +-- libs/video/renderer/sw/sw_rmisc.c | 10 +- libs/video/renderer/sw/sw_rpart.c | 42 ++- libs/video/renderer/sw/sw_rsprite.c | 9 +- libs/video/renderer/sw/sw_rsurf.c | 10 +- libs/video/renderer/sw32/d_edge.c | 7 +- libs/video/renderer/sw32/sw32_rmain.c | 30 +- libs/video/renderer/sw32/sw32_rmisc.c | 10 +- libs/video/renderer/sw32/sw32_rpart.c | 42 ++- libs/video/renderer/sw32/sw32_rsprite.c | 9 +- libs/video/renderer/sw32/sw32_rsurf.c | 10 +- .../renderer/vulkan/shader/lighting.frag | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 17 +- libs/video/renderer/vulkan/vulkan_lightmap.c | 9 +- libs/video/renderer/vulkan/vulkan_main.c | 38 ++- nq/include/client.h | 5 +- nq/source/cl_chase.c | 123 ++++---- nq/source/cl_demo.c | 2 +- nq/source/cl_ents.c | 61 ++-- nq/source/cl_input.c | 45 +-- nq/source/cl_main.c | 14 +- nq/source/cl_parse.c | 20 +- nq/source/cl_screen.c | 4 +- nq/source/cl_view.c | 265 +++++++--------- qw/include/client.h | 12 +- qw/source/cl_chase.c | 123 ++++---- qw/source/cl_demo.c | 22 +- qw/source/cl_entparse.c | 5 +- qw/source/cl_ents.c | 47 ++- qw/source/cl_input.c | 2 + qw/source/cl_main.c | 2 + qw/source/cl_parse.c | 37 ++- qw/source/cl_pred.c | 26 +- qw/source/cl_screen.c | 4 +- qw/source/cl_view.c | 293 ++++++++---------- qw/source/teamplay.c | 16 +- 62 files changed, 1070 insertions(+), 912 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index 99fb105a9..adc5e141e 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -32,6 +32,7 @@ #include "QF/model.h" #include "QF/qdefs.h" // FIXME #include "QF/vid.h" +#include "QF/simd/types.h" typedef enum { pt_static, @@ -131,10 +132,7 @@ typedef struct entity_s { renderer_t renderer; int active; //XXX FIXME XXX should not be here - float scale; - vec3_t origin; - vec3_t old_origin; - vec3_t angles; + vec4f_t old_origin; } entity_t; // !!! if this is changed, it must be changed in asm_draw.h too !!! @@ -159,8 +157,9 @@ typedef struct { float xOrigin; // should probably always be 0.5 float yOrigin; // between be around 0.3 to 0.5 - vec3_t vieworg; - vec3_t viewangles; + //FIXME was vec3_t, need to deal with asm (maybe? is it worth it?) + vec4f_t viewposition; + vec4f_t viewrotation; float fov_x, fov_y; diff --git a/include/client/entities.h b/include/client/entities.h index fda534295..5981d1c9d 100644 --- a/include/client/entities.h +++ b/include/client/entities.h @@ -71,6 +71,7 @@ extern entstates_t qw_entstates; extern vec3_t ent_colormod[256]; struct entity_s; -void CL_TransformEntity (struct entity_s *ent, const vec3_t angles); +void CL_TransformEntity (struct entity_s *ent, float scale, + const vec3_t angles, vec4f_t position); #endif//__client_entities_h diff --git a/include/client/view.h b/include/client/view.h index 756eb1d21..40ad78df3 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -37,6 +37,21 @@ #define INFO_CSHIFT_DAMAGE (1 << 2) #define INFO_CSHIFT_POWERUP (1 << 3) +typedef struct viewstate_s { + vec4f_t movecmd; + vec4f_t velocity; + vec4f_t origin; + vec3_t angles; + int weaponframe; + int onground; + uint32_t flags; + float frametime; + vec4f_t punchangle; +} viewstate_t; + +#define VF_DEAD 1 +#define VF_GIB 2 + void V_Init (void); void V_Init_Cvars (void); void V_RenderView (void); diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index af40dc62c..707699141 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -123,7 +123,8 @@ CL_ModelEffects (entity_t *ent, int num, int glow_color, double time) if (model->flags & EF_ROCKET) { dl = r_funcs->R_AllocDlight (num); if (dl) { - VectorCopy (ent->origin, dl->origin); + VectorCopy (Transform_GetWorldPosition (ent->transform), + dl->origin); dl->radius = 200.0; dl->die = time + 0.1; //FIXME VectorCopy (r_firecolor->vec, dl->color); diff --git a/libs/client/cl_entities.c b/libs/client/cl_entities.c index 837cfbe60..599576863 100644 --- a/libs/client/cl_entities.c +++ b/libs/client/cl_entities.c @@ -346,21 +346,14 @@ vec3_t ent_colormod[256] = { }; void -CL_TransformEntity (entity_t *ent, const vec3_t angles) +CL_TransformEntity (entity_t *ent, float scale, const vec3_t angles, + vec4f_t position) { - union { - quat_t q; - vec4f_t v; - } rotation; - vec4f_t position; - vec4f_t scale; + vec4f_t rotation; + vec4f_t scalevec = { scale, scale, scale, 1}; - VectorCopy (ent->origin, position); - position[3] = 1; - VectorSet (ent->scale, ent->scale, ent->scale, scale); - scale[3] = 1; if (VectorIsZero (angles)) { - QuatSet (0, 0, 0, 1, rotation.q); + rotation = (vec4f_t) { 0, 0, 0, 1 }; } else { vec3_t ang; VectorCopy (angles, ang); @@ -370,7 +363,7 @@ CL_TransformEntity (entity_t *ent, const vec3_t angles) // to everything else? ang[PITCH] = -ang[PITCH]; } - AngleQuat (ang, rotation.q); + AngleQuat (ang, &rotation[0]);//FIXME } - Transform_SetLocalTransform (ent->transform, scale, rotation.v, position); + Transform_SetLocalTransform (ent->transform, scalevec, rotation, position); } diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 0b6672f0f..03fab9b73 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -61,7 +61,8 @@ typedef struct { int entity; struct model_s *model; float endtime; - vec3_t start, end; + vec4f_t start, end; + vec4f_t rotation; tent_t *tents; int seed; } beam_t; @@ -100,6 +101,8 @@ static model_t *cl_mod_bolt3; static model_t *cl_spr_explod; static model_t *cl_spike; +static vec4f_t beam_rolls[360]; + static void CL_TEnts_Precache (int phase) { @@ -132,6 +135,10 @@ CL_TEnts_Init (void) { QFS_GamedirCallback (CL_TEnts_Precache); CL_TEnts_Precache (1); + for (int i = 0; i < 360; i++) { + float ang = i * M_PI / 360; + beam_rolls[i] = (vec4f_t) { sin (ang), 0, 0, cos (ang) }; + } } void @@ -145,7 +152,6 @@ CL_Init_Entity (entity_t *ent) ent->transform = Transform_New (0); ent->renderer.skin = 0; QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); - ent->scale = 1.0; ent->animation.pose1 = ent->animation.pose2 = -1; } @@ -255,57 +261,52 @@ static inline void beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx) { tent_t *tent; - float forward, pitch, yaw, d; + float d; int ent_count; - vec3_t dist, org, ang; + vec4f_t dist, org; + vec4f_t rotation; + vec4f_t scale = { 1, 1, 1, 1 }; unsigned seed; // calculate pitch and yaw - VectorSubtract (b->end, b->start, dist); + dist = b->end - b->start; - if (dist[1] == 0 && dist[0] == 0) { - yaw = 0; - if (dist[2] > 0) - pitch = 90; - else - pitch = 270; + // FIXME interpolation may be off when passing through the -x axis + if (dist[0] < 0 && dist[1] == 0 && dist[2] == 0) { + // anti-parallel with the +x axis, so assome 180 degree rotation around + // the z-axis + rotation = (vec4f_t) { 0, 0, 1, 0 }; } else { - yaw = (int) (atan2 (dist[1], dist[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - - forward = sqrt (dist[0] * dist[0] + dist[1] * dist[1]); - pitch = (int) (atan2 (dist[2], forward) * 180 / M_PI); - if (pitch < 0) - pitch += 360; + rotation = qrotf ((vec4f_t) { 1, 0, 0, 0 }, dist); } + b->rotation = rotation; // add new entities for the lightning - VectorCopy (b->start, org); - d = VectorNormalize (dist); - VectorScale (dist, 30, dist); + org = b->start; + d = magnitudef (dist)[0]; + dist = normalf (dist) * 30; ent_count = ceil (d / 30); d = 0; seed = b->seed + ((int) (time * BEAM_SEED_INTERVAL) % BEAM_SEED_INTERVAL); - ang[ROLL] = 0; while (ent_count--) { tent = new_temp_entity (); tent->next = b->tents; b->tents = tent; - VectorMultAdd (org, d, dist, tent->ent.origin); + vec4f_t position = org + d * dist; d += 1.0; tent->ent.renderer.model = b->model; - ang[PITCH] = pitch; - ang[YAW] = yaw; if (transform) { seed = seed * BEAM_SEED_PRIME; - ang[ROLL] = seed % 360; - CL_TransformEntity (&tent->ent, ang); + Transform_SetLocalTransform (tent->ent.transform, scale, + qmulf (rotation, + beam_rolls[seed % 360]), + position); + } else { + Transform_SetLocalPosition (tent->ent.transform, position); } - VectorCopy (ang, tent->ent.angles); r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent); } } @@ -404,14 +405,14 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, ex = &to->to.ex; ex->tent = new_temp_entity (); - VectorCopy (position, ex->tent->ent.origin); ex->start = time; //FIXME need better model management if (!cl_spr_explod->cache.data) { cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); } ex->tent->ent.renderer.model = cl_spr_explod; - CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles); + Transform_SetLocalPosition (ex->tent->ent.transform,//FIXME + (vec4f_t) {VectorExpand (position), 1}); break; case TE_Explosion2: MSG_ReadCoordV (net_message, position); @@ -635,8 +636,9 @@ CL_UpdateBeams (double time, TEntContext_t *ctx) // add new entities for the lightning for (t = b->tents; t; t = t->next) { seed = seed * BEAM_SEED_PRIME; - t->ent.angles[ROLL] = seed % 360; - CL_TransformEntity (&t->ent, t->ent.angles); + Transform_SetLocalRotation (t->ent.transform, + qmulf (b->rotation, + beam_rolls[seed % 360])); } } } @@ -727,6 +729,8 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) byte bits[6]; int i, c, j, num; entity_t *pr; + vec4f_t position = { 0, 0, 0, 1 }; + vec3_t angles; c = MSG_ReadByte (net_message); @@ -747,13 +751,13 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) pr = &tent->ent; pr->renderer.model = cl_spike; pr->renderer.skin = 0; - pr->origin[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096; - pr->origin[1] = (((bits[1] >> 4) + (bits[2] << 4)) << 1) - 4096; - pr->origin[2] = ((bits[3] + ((bits[4] & 15) << 8)) << 1) - 4096; - pr->angles[0] = (bits[4] >> 4) * (360.0 / 16.0); - pr->angles[1] = bits[5] * (360.0 / 256.0); - pr->angles[2] = 0; - CL_TransformEntity (&tent->ent, tent->ent.angles); + position[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096; + position[1] = (((bits[1] >> 4) + (bits[2] << 4)) << 1) - 4096; + position[2] = ((bits[3] + ((bits[4] & 15) << 8)) << 1) - 4096; + angles[0] = (bits[4] >> 4) * (360.0 / 16.0); + angles[1] = bits[5] * (360.0 / 256.0); + angles[2] = 0; + CL_TransformEntity (&tent->ent, 1, angles, position); r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent); } diff --git a/libs/client/locs.c b/libs/client/locs.c index 07deee426..2ab477921 100644 --- a/libs/client/locs.c +++ b/libs/client/locs.c @@ -140,7 +140,7 @@ locs_load (const char *filename) const char *tmp; char *t1, *t2; const char *line; - vec4f_t loc; + vec4f_t loc = { 0, 0, 0, 1 }; QFile *file; tmp = va (0, "maps/%s", filename); diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 5aa093813..13afc1fe9 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -42,6 +42,7 @@ #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/mersenne.h" #include "QF/qargs.h" #include "QF/quakefs.h" @@ -521,12 +522,14 @@ R_RocketTrail_QF (const entity_t *ent) float dist, maxlen, origlen, percent, pscale, pscalenext; float len = 0.0; vec3_t old_origin, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 1.5 + qfrandom (1.5); @@ -555,12 +558,14 @@ R_GrenadeTrail_QF (const entity_t *ent) float dist, maxlen, origlen, percent, pscale, pscalenext; float len = 0.0; vec3_t old_origin, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 6.0 + qfrandom (7.0); @@ -590,12 +595,14 @@ R_BloodTrail_QF (const entity_t *ent) float len = 0.0; int j; vec3_t old_origin, porg, pvel, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 5.0 + qfrandom (10.0); @@ -630,12 +637,14 @@ R_SlightBloodTrail_QF (const entity_t *ent) float len = 0.0; int j; vec3_t old_origin, porg, pvel, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 1.5 + qfrandom (7.5); @@ -670,12 +679,14 @@ R_WizTrail_QF (const entity_t *ent) float dist = 3.0, len = 0.0; static int tracercount; vec3_t old_origin, pvel, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; VectorScale (vec, maxlen - dist, subtract); @@ -711,12 +722,14 @@ R_FlameTrail_QF (const entity_t *ent) float dist = 3.0, len = 0.0; static int tracercount; vec3_t old_origin, pvel, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; VectorScale (vec, maxlen - dist, subtract); @@ -752,12 +765,14 @@ R_VoorTrail_QF (const entity_t *ent) float dist = 3.0, len = 0.0; int j; vec3_t subtract, old_origin, porg, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; VectorScale (vec, maxlen - dist, subtract); @@ -790,7 +805,8 @@ R_GlowTrail_QF (const entity_t *ent, int glow_color) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; VectorScale (vec, (maxlen - dist), subtract); @@ -869,12 +885,14 @@ R_RocketTrail_EE (const entity_t *ent) float dist, maxlen, origlen, percent, pscale, pscalenext; float len = 0.0; vec3_t old_origin, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 1.5 + qfrandom (1.5); @@ -904,12 +922,14 @@ R_GrenadeTrail_EE (const entity_t *ent) float dist, maxlen, origlen, percent, pscale, pscalenext; float len = 0.0; vec3_t old_origin, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, ent->old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, ent->old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 6.0 + qfrandom (7.0); @@ -1143,7 +1163,7 @@ R_DarkFieldParticles_ID (const entity_t *ent) // l = r_maxparticles - numparticles; // } - VectorCopy (ent->origin, org); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); for (i = -16; i < 16; i += 8) { dir [1] = i * 8; @@ -1177,6 +1197,7 @@ R_EntityParticles_ID (const entity_t *ent) float angle, sp, sy, cp, cy; // cr, sr float beamlength = 16.0, dist = 64.0; vec3_t forward, porg; + vec3_t org; if (numparticles + j >= r_maxparticles) { return; @@ -1184,6 +1205,8 @@ R_EntityParticles_ID (const entity_t *ent) j = r_maxparticles - numparticles; } + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + if (!avelocities[0][0]) { for (i = 0; i < NUMVERTEXNORMALS; i++) { int k; @@ -1209,11 +1232,11 @@ R_EntityParticles_ID (const entity_t *ent) forward[1] = cp * sy; forward[2] = -sp; - porg[0] = ent->origin[0] + r_avertexnormals[i][0] * dist + + porg[0] = org[0] + r_avertexnormals[i][0] * dist + forward[0] * beamlength; - porg[1] = ent->origin[1] + r_avertexnormals[i][1] * dist + + porg[1] = org[1] + r_avertexnormals[i][1] * dist + forward[1] * beamlength; - porg[2] = ent->origin[2] + r_avertexnormals[i][2] * dist + + porg[2] = org[2] + r_avertexnormals[i][2] * dist + forward[2] * beamlength; particle_new (pt_explode, part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 0.01, 0x6f, 1.0, 0); @@ -1232,7 +1255,8 @@ R_RocketTrail_ID (const entity_t *ent) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, ent->old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, ent->old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, (maxlen - dist), subtract); @@ -1264,7 +1288,8 @@ R_GrenadeTrail_ID (const entity_t *ent) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, ent->old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, ent->old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1291,12 +1316,14 @@ R_BloodTrail_ID (const entity_t *ent) float dist = 3.0, len = 0.0; unsigned int rnd; vec3_t old_origin, subtract, vec, porg; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1322,12 +1349,14 @@ R_SlightBloodTrail_ID (const entity_t *ent) float dist = 6.0, len = 0.0; unsigned int rnd; vec3_t old_origin, porg, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1353,12 +1382,14 @@ R_WizTrail_ID (const entity_t *ent) float dist = 3.0, len = 0.0; static int tracercount; vec3_t old_origin, pvel, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1390,12 +1421,14 @@ R_FlameTrail_ID (const entity_t *ent) float dist = 3.0, len = 0.0; static int tracercount; vec3_t old_origin, pvel, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1427,12 +1460,14 @@ R_VoorTrail_ID (const entity_t *ent) float dist = 3.0, len = 0.0; unsigned int rnd; vec3_t old_origin, porg, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1471,7 +1506,7 @@ gl_R_DrawParticles (void) qfglDepthMask (GL_FALSE); qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, particleVertexArray); - minparticledist = DotProduct (r_refdef.vieworg, vpn) + + minparticledist = DotProduct (r_refdef.viewposition, vpn) + r_particles_nearclip->value; activeparticles = 0; diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index d46c35014..2ea33a8c0 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -43,6 +43,7 @@ #include #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" #include "QF/GL/defines.h" @@ -117,16 +118,22 @@ R_AddDynamicLights_1 (msurface_t *surf) unsigned int sdtable[18]; unsigned int *bl; vec3_t impact, local; + vec4f_t entorigin = { 0, 0, 0, 1 }; smax = (surf->extents[0] >> 4) + 1; smax_bytes = smax * gl_internalformat; tmax = (surf->extents[1] >> 4) + 1; + if (currententity->transform) { + //FIXME give world entity a transform + entorigin = Transform_GetWorldPosition (currententity->transform); + } + for (lnum = 0; lnum < r_maxdlights; lnum++) { if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32)))) continue; // not lit by this light - VectorSubtract (r_dlights[lnum].origin, currententity->origin, local); + VectorSubtract (r_dlights[lnum].origin, entorigin, local); dist = DotProduct (local, surf->plane->normal) - surf->plane->dist; VectorMultSub (r_dlights[lnum].origin, dist, surf->plane->normal, impact); @@ -182,16 +189,21 @@ R_AddDynamicLights_3 (msurface_t *surf) unsigned int sdtable[18]; unsigned int *bl; vec3_t impact, local; + vec4f_t entorigin = { 0, 0, 0, 1 }; smax = (surf->extents[0] >> 4) + 1; smax_bytes = smax * gl_internalformat; tmax = (surf->extents[1] >> 4) + 1; + if (currententity->transform) { + entorigin = Transform_GetWorldPosition (currententity->transform); + } + for (lnum = 0; lnum < r_maxdlights; lnum++) { if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32)))) continue; // not lit by this light - VectorSubtract (r_dlights[lnum].origin, currententity->origin, local); + VectorSubtract (r_dlights[lnum].origin, entorigin, local); dist = DotProduct (local, surf->plane->normal) - surf->plane->dist; VectorMultSub (r_dlights[lnum].origin, dist, surf->plane->normal, impact); diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 92c67038d..3f96b4364 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -196,8 +196,10 @@ GL_DrawAliasShadowTri (const aliashdr_t *paliashdr, const vert_order_t *vo) vec3_t point; const vec_t *scale = paliashdr->mdl.scale; const vec_t *scale_origin = paliashdr->mdl.scale_origin; + vec4f_t entorigin; - lheight = currententity->origin[2] - lightspot[2]; + entorigin = Transform_GetWorldPosition (currententity->transform); + lheight = entorigin[2] - lightspot[2]; height = -lheight + 1.0; qfglBegin (GL_TRIANGLES); @@ -232,8 +234,10 @@ GL_DrawAliasShadow (const aliashdr_t *paliashdr, const vert_order_t *vo) const int *order = vo->order; vec3_t point; const blended_vert_t *verts = vo->verts; + vec4f_t entorigin; - lheight = currententity->origin[2] - lightspot[2]; + entorigin = Transform_GetWorldPosition (currententity->transform); + lheight = entorigin[2] - lightspot[2]; height = -lheight + 1.0; while ((count = *order++)) { @@ -413,17 +417,23 @@ gl_R_DrawAliasModel (entity_t *e) dlight_t *l; model_t *model; vec3_t dist, scale; + vec4f_t origin; vert_order_t *vo; model = e->renderer.model; radius = model->radius; - if (e->scale != 1.0) - radius *= e->scale; - if (R_CullSphere (e->origin, radius)) + origin = Transform_GetWorldPosition (e->transform); + VectorCopy (Transform_GetWorldScale (e->transform), scale); + //FIXME assumes uniform scale + if (scale[0] != 1.0) { + radius *= scale[0]; + } + if (R_CullSphere (&origin[0], radius)) {//FIXME return; + } - VectorSubtract (r_origin, e->origin, modelorg); + VectorSubtract (r_origin, origin, modelorg); gl_modelalpha = e->renderer.colormod[3]; @@ -436,7 +446,7 @@ gl_R_DrawAliasModel (entity_t *e) float lightadj; // get lighting information - R_LightPoint (&r_worldentity.renderer.model->brush, e->origin); + R_LightPoint (&r_worldentity.renderer.model->brush, &origin[0]);//FIXME lightadj = (ambientcolor[0] + ambientcolor[1] + ambientcolor[2]) / 765.0; @@ -457,7 +467,7 @@ gl_R_DrawAliasModel (entity_t *e) if (gl_vector_light->int_val) { for (l = r_dlights, lnum = 0; lnum < r_maxdlights; lnum++, l++) { if (l->die >= vr_data.realtime) { - VectorSubtract (l->origin, e->origin, dist); + VectorSubtract (l->origin, origin, dist); if ((d = DotProduct (dist, dist)) > // Out of range ((l->radius + radius) * (l->radius + radius))) { continue; @@ -508,7 +518,7 @@ gl_R_DrawAliasModel (entity_t *e) for (l = r_dlights, lnum = 0; lnum < r_maxdlights; lnum++, l++) { if (l->die >= vr_data.realtime) { - VectorSubtract (l->origin, e->origin, dist); + VectorSubtract (l->origin, origin, dist); if ((d = DotProduct (dist, dist)) > (l->radius + radius) * (l->radius + radius)) { @@ -567,10 +577,12 @@ gl_R_DrawAliasModel (entity_t *e) if (paliashdr->mdl.ident == HEADER_MDL16) { // because we multipled by 256 when we loaded the verts, we have to // scale by 1/256 when drawing. - VectorScale (paliashdr->mdl.scale, e->scale / 256.0, scale); + //FIXME see scaling above + VectorScale (paliashdr->mdl.scale, 1 / 256.0, scale); vo = GL_GetAliasFrameVerts16 (paliashdr, e); } else { - VectorScale (paliashdr->mdl.scale, e->scale, scale); + //FIXME see scaling above + VectorScale (paliashdr->mdl.scale, 1, scale); vo = GL_GetAliasFrameVerts (paliashdr, e); } diff --git a/libs/video/renderer/gl/gl_mod_iqm.c b/libs/video/renderer/gl/gl_mod_iqm.c index 601a76fbf..f66c2c7ca 100644 --- a/libs/video/renderer/gl/gl_mod_iqm.c +++ b/libs/video/renderer/gl/gl_mod_iqm.c @@ -103,7 +103,6 @@ gl_R_DrawIQMModel (entity_t *ent) qfglPushMatrix (); gl_R_RotateForEntity (ent); - qfglScalef (ent->scale, ent->scale, ent->scale); for (i = 0; i < iqm->num_meshes; i++) { qfglBindTexture (GL_TEXTURE_2D, gl->textures[i]); diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index d0dd91444..d4b1c1f86 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -123,10 +123,6 @@ R_DrawSpriteModel_f (entity_t *e) VectorCopy (vup, up); VectorCopy (vright, right); } - if (e->scale != 1.0) { - up *= e->scale; - right *= e->scale; - } VectorCopy (e->renderer.colormod, color); modelalpha = color[3] = e->renderer.colormod[3]; @@ -194,10 +190,6 @@ R_DrawSpriteModel_VA_f (entity_t *e) VectorCopy (vup, up); VectorCopy (vright, right); } - if (e->scale != 1.0) { - up *= e->scale; - right *= e->scale; - } for (i = 0; i < 4; i++) { color[i] = e->renderer.colormod[i] * 255; diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 8079b790b..8bf8ec46a 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -74,7 +74,7 @@ qboolean gl_mirror; plane_t *gl_mirror_plane; float gl_r_world_matrix[16]; -static float r_base_world_matrix[16]; +//FIXME static float r_base_world_matrix[16]; //vec3_t gl_shadecolor; // Ender (Extend) Colormod float gl_modelalpha; // Ender (Extend) Alpha @@ -344,9 +344,12 @@ gl_R_SetupFrame (void) gl_Fog_SetupFrame (); // build the transformation matrix for the given view angles - VectorCopy (r_refdef.vieworg, r_origin); + VectorCopy (r_refdef.viewposition, r_origin); + + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); - AngleVectors (r_refdef.viewangles, vpn, vright, vup); R_SetFrustum (); @@ -419,13 +422,19 @@ R_SetupGL (void) qfglMatrixMode (GL_MODELVIEW); qfglLoadIdentity (); - qfglRotatef (-90, 1, 0, 0); // put Z going up - qfglRotatef (90, 0, 0, 1); // put Z going up - qfglRotatef (-r_refdef.viewangles[ROLL], 1, 0, 0); - qfglRotatef (-r_refdef.viewangles[PITCH], 0, 1, 0); - qfglRotatef (-r_refdef.viewangles[YAW], 0, 0, 1); - qfglTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], - -r_refdef.vieworg[2]); + static mat4f_t z_up = { + { 0, 0, -1, 0}, + {-1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 0, 1}, + }; + mat4f_t view; + mat4fquat (view, qconjf (r_refdef.viewrotation)); + mmulf (view, z_up, view); + vec4f_t offset = -r_refdef.viewposition; + offset[3] = 1; + view[3] = mvmulf (view, offset); + qfglLoadMatrixf (&view[0][0]); qfglGetFloatv (GL_MODELVIEW_MATRIX, gl_r_world_matrix); @@ -480,12 +489,12 @@ R_RenderScene (void) static void R_Mirror (void) { - float d; + //float d; // msurface_t *s; // if (!gl_mirror) // FIXME: Broken return; - +/* memcpy (r_base_world_matrix, gl_r_world_matrix, sizeof (r_base_world_matrix)); @@ -551,6 +560,7 @@ R_Mirror (void) r_worldentity.model->textures[gl_mirrortexturenum]->texturechain = NULL; #endif qfglColor3ubv (color_white); +*/ } /* @@ -584,6 +594,18 @@ R_RenderView_ (void) R_ZGraph (); } +//FIXME static void R_RenderViewFishEye (void); + +void +gl_R_RenderView (void) +{ + R_RenderView_ (); + /*if(!scr_fisheye->int_val) + R_RenderView_ (); + else + R_RenderViewFishEye ();*/ +} +/*FIXME // Algorithm: // Draw up to six views, one in each direction. // Save the picture to cube map texture, use GL_ARB_texture_cube_map. @@ -593,17 +615,6 @@ R_RenderView_ (void) // grid vertices coordinates. // Render view. Fisheye is done. -static void R_RenderViewFishEye (void); - -void -gl_R_RenderView (void) -{ - if(!scr_fisheye->int_val) - R_RenderView_ (); - else - R_RenderViewFishEye (); -} - #define BOX_FRONT 0 #define BOX_RIGHT 1 #define BOX_BEHIND 2 @@ -891,7 +902,7 @@ R_RenderViewFishEye (void) R_SetupGL_Viewport_and_Perspective (); qfglMatrixMode (GL_MODELVIEW); qfglCallList (fisheye_grid); -} +}*/ void gl_R_ClearState (void) diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index d9a1c6797..de34bb203 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -74,6 +74,7 @@ static void R_Envmap_f (void) { + /*FIXME update for simd byte buffer[256 * 256 * 4]; qfglDrawBuffer (GL_FRONT); @@ -122,7 +123,7 @@ R_Envmap_f (void) gl_envmap = false; qfglDrawBuffer (GL_BACK); qfglReadBuffer (GL_BACK); - gl_ctx->end_rendering (); + gl_ctx->end_rendering ();*/ } void @@ -250,6 +251,7 @@ gl_R_ViewChanged (float aspect) void gl_R_TimeRefresh_f (void) { +/*FIXME update for simd double start, stop, time; int i; @@ -265,4 +267,5 @@ gl_R_TimeRefresh_f (void) stop = Sys_DoubleTime (); time = stop - start; Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); +*/ } diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index b954fc066..96d1ec93f 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -545,12 +545,13 @@ gl_R_DrawBrushModel (entity_t *e) if (e->scale != 1.0) radius *= e->scale; #endif - if (R_CullSphere (e->origin, radius)) + if (R_CullSphere (&worldMatrix[3][0], radius)) {//FIXME return; + } } else { rotated = false; - VectorAdd (e->origin, model->mins, mins); - VectorAdd (e->origin, model->maxs, maxs); + VectorAdd (worldMatrix[3], model->mins, mins); + VectorAdd (worldMatrix[3], model->maxs, maxs); #if 0 // QSG FIXME if (e->scale != 1.0) { VectorScale (mins, e->scale, mins); @@ -561,7 +562,7 @@ gl_R_DrawBrushModel (entity_t *e) return; } - VectorSubtract (r_refdef.vieworg, e->origin, modelorg); + VectorSubtract (r_refdef.viewposition, worldMatrix[3], modelorg); if (rotated) { vec4f_t temp = { modelorg[0], modelorg[1], modelorg[2], 0 }; @@ -579,7 +580,7 @@ gl_R_DrawBrushModel (entity_t *e) || (!r_dlights[k].radius)) continue; - VectorSubtract (r_dlights[k].origin, e->origin, lightorigin); + VectorSubtract (r_dlights[k].origin, worldMatrix[3], lightorigin); R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, brush->nodes + brush->hulls[0].firstclipnode); } @@ -723,7 +724,7 @@ gl_R_DrawWorld (void) memset (&worldent, 0, sizeof (worldent)); worldent.renderer.model = r_worldentity.renderer.model; - VectorCopy (r_refdef.vieworg, modelorg); + VectorCopy (r_refdef.viewposition, modelorg); currententity = &worldent; diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index cb3258246..db289326b 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -189,9 +189,9 @@ R_DrawSkyBox (void) float *v = (float *) gl_skyvec[i][j]; qfglTexCoord2fv (v); - qfglVertex3f (r_refdef.vieworg[0] + v[2], - r_refdef.vieworg[1] + v[3], - r_refdef.vieworg[2] + v[4]); + qfglVertex3f (r_refdef.viewposition[0] + v[2], + r_refdef.viewposition[1] + v[3], + r_refdef.viewposition[2] + v[4]); } qfglEnd (); } @@ -219,7 +219,7 @@ skydome_vertex (const vec3_t v, float speedscale) s = speedscale + dir[0]; t = speedscale + dir[1]; - VectorAdd (r_refdef.vieworg, v, point); + VectorAdd (r_refdef.viewposition, v, point); qfglTexCoord2f (s, t); qfglVertex3fv (point); @@ -242,7 +242,7 @@ skydome_debug (void) h = 1; t = 0; - VectorAdd (zenith, r_refdef.vieworg, v[0]); + VectorAdd (zenith, r_refdef.viewposition, v[0]); for (b = 1; b <= 8; b++) { x = gl_bubble_costable[b + 8]; y = -gl_bubble_sintable[b + 8]; @@ -250,7 +250,7 @@ skydome_debug (void) v[h][0] = a1x * x; v[h][1] = a1y * x; v[h][2] = y * domescale[2]; - VectorAdd (v[h], r_refdef.vieworg, v[h]); + VectorAdd (v[h], r_refdef.viewposition, v[h]); for (i = t; i != h; i = (i + 1) % 3) { qfglVertex3fv (v[i]); qfglVertex3fv (v[h]); @@ -262,7 +262,7 @@ skydome_debug (void) v[h][0] = a2x * x; v[h][1] = a2y * x; v[h][2] = y * domescale[2]; - VectorAdd (v[h], r_refdef.vieworg, v[h]); + VectorAdd (v[h], r_refdef.viewposition, v[h]); for (i = t; i != h; i = (i + 1) % 3) { qfglVertex3fv (v[i]); qfglVertex3fv (v[h]); @@ -274,7 +274,7 @@ skydome_debug (void) h = 1; t = 0; - VectorAdd (nadir, r_refdef.vieworg, v[0]); + VectorAdd (nadir, r_refdef.viewposition, v[0]); for (b = 15; b >= 8; b--) { x = gl_bubble_costable[b + 8]; y = -gl_bubble_sintable[b + 8]; @@ -282,7 +282,7 @@ skydome_debug (void) v[h][0] = a2x * x; v[h][1] = a2y * x; v[h][2] = y * domescale[2]; - VectorAdd (v[h], r_refdef.vieworg, v[h]); + VectorAdd (v[h], r_refdef.viewposition, v[h]); for (i = t; i != h; i = (i + 1) % 3) { qfglVertex3fv (v[i]); qfglVertex3fv (v[h]); @@ -294,7 +294,7 @@ skydome_debug (void) v[h][0] = a1x * x; v[h][1] = a1y * x; v[h][2] = y * domescale[2]; - VectorAdd (v[h], r_refdef.vieworg, v[h]); + VectorAdd (v[h], r_refdef.viewposition, v[h]); for (i = t; i != h; i = (i + 1) % 3) { qfglVertex3fv (v[i]); qfglVertex3fv (v[h]); diff --git a/libs/video/renderer/gl/gl_sky_clip.c b/libs/video/renderer/gl/gl_sky_clip.c index 44a560005..697403eb9 100644 --- a/libs/video/renderer/gl/gl_sky_clip.c +++ b/libs/video/renderer/gl/gl_sky_clip.c @@ -220,14 +220,14 @@ find_cube_vertex (int face1, int face2, int face3, vec3_t v) set_vertex add the vertex to the polygon describing the face of the cube. Offsets - the vertex relative to r_refdef.vieworg so the cube is always centered + the vertex relative to r_refdef.viewposition so the cube is always centered on the player and also calculates the texture coordinates of the vertex (wish I could find a cleaner way of calculating s and t). */ static void set_vertex (struct box_def *box, int face, int ind, const vec3_t v) { - VectorAdd (v, r_refdef.vieworg, box->face[face].poly.verts[ind]); + VectorAdd (v, r_refdef.viewposition, box->face[face].poly.verts[ind]); switch (face) { case 0: box->face[face].poly.verts[ind][3] = (1024 - v[1] + 4) / BOX_WIDTH; @@ -601,14 +601,14 @@ R_DrawSkyBoxPoly (const glpoly_t *poly) Sys_Error ("too many verts!"); } - VectorSubtract (poly->verts[poly->numverts - 1], r_refdef.vieworg, last_v); + VectorSubtract (poly->verts[poly->numverts - 1], r_refdef.viewposition, last_v); prev_face = determine_face (last_v); box.visited_faces[0].face = prev_face; box.face_count = 1; for (i = 0; i < poly->numverts; i++) { - VectorSubtract (poly->verts[i], r_refdef.vieworg, v); + VectorSubtract (poly->verts[i], r_refdef.viewposition, v); face = determine_face (v); if (face != prev_face) { if ((face_axis[face]) == (face_axis[prev_face])) { @@ -864,11 +864,11 @@ gl_R_DrawSkyChain (const instsurf_t *sky_chain) vec3_t x, c = { 0, 0, 0 }; for (i = 0; i < p->numverts; i++) { - VectorSubtract (p->verts[i], r_refdef.vieworg, x); + VectorSubtract (p->verts[i], r_refdef.viewposition, x); VectorAdd (x, c, c); } VectorScale (c, 1.0 / p->numverts, c); - VectorAdd (c, r_refdef.vieworg, c); + VectorAdd (c, r_refdef.viewposition, c); qfglVertex3fv (c); p = p->next; } @@ -889,7 +889,7 @@ gl_R_DrawSkyChain (const instsurf_t *sky_chain) qfglBegin (GL_LINE_LOOP); for (j = 0; j < 4; j++) { VectorScale (&gl_skyvec[i][j][2], 1.0 / 128.0, v); - VectorAdd (v, r_refdef.vieworg, v); + VectorAdd (v, r_refdef.viewposition, v); qfglVertex3fv (v); } qfglEnd (); diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index e0c29cfe4..22983ceef 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -157,17 +157,20 @@ calc_lighting (entity_t *ent, float *ambient, float *shadelight, unsigned i; float add; vec3_t dist; + vec4f_t entorigin; int light; + entorigin = Transform_GetWorldPosition (ent->transform); + VectorSet ( -1, 0, 0, lightvec); //FIXME - light = R_LightPoint (&r_worldentity.renderer.model->brush, ent->origin); + light = R_LightPoint (&r_worldentity.renderer.model->brush, &entorigin[0]); *ambient = max (light, max (ent->renderer.model->min_light, ent->renderer.min_light) * 128); *shadelight = *ambient; for (i = 0; i < r_maxdlights; i++) { if (r_dlights[i].die >= vr_data.realtime) { - VectorSubtract (ent->origin, r_dlights[i].origin, dist); + VectorSubtract (entorigin, r_dlights[i].origin, dist); add = r_dlights[i].radius - VectorLength (dist); if (add > 0) *ambient += add; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 3fc716cf8..50a4e98af 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -660,7 +660,8 @@ R_DrawBrushModel (entity_t *e) plane_t *plane; msurface_t *surf; qboolean rotated; - vec3_t mins, maxs, org; + vec3_t mins, maxs; + vec4f_t org; mod_brush_t *brush; model = e->renderer.model; @@ -671,19 +672,20 @@ R_DrawBrushModel (entity_t *e) if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; - if (R_CullSphere (e->origin, radius)) + if (R_CullSphere (&mat[3][0], radius)) { // FIXME return; + } } else { rotated = false; - VectorAdd (e->origin, model->mins, mins); - VectorAdd (e->origin, model->maxs, maxs); + VectorAdd (mat[3], model->mins, mins); + VectorAdd (mat[3], model->maxs, maxs); if (R_CullBox (mins, maxs)) return; } - VectorSubtract (r_refdef.vieworg, e->origin, org); + org = r_refdef.viewposition - mat[3]; if (rotated) { - vec4f_t temp = { org[0], org[1], org[2], 0 }; + vec4f_t temp = org; org[0] = dotf (temp, mat[0])[0]; org[1] = dotf (temp, mat[1])[0]; @@ -699,7 +701,7 @@ R_DrawBrushModel (entity_t *e) || (!r_dlights[k].radius)) continue; - VectorSubtract (r_dlights[k].origin, e->origin, lightorigin); + VectorSubtract (r_dlights[k].origin, mat[3], lightorigin); R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, brush->nodes + brush->hulls[0].firstclipnode); } diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index 76a9ae85e..93a25e982 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -214,22 +214,24 @@ glsl_R_DrawIQM (void) dlight_t *lights[MAX_IQM_LIGHTS]; int i; vec_t norm_mat[9]; + vec4f_t entorigin; mat4f_t mvp_mat; float blend; iqmframe_t *frame; - R_LightPoint (&r_worldentity.renderer.model->brush, ent->origin);//FIXME min_light? - VectorScale (ambientcolor, 1/255.0, ambientcolor); - R_FindNearLights (ent->origin, MAX_IQM_LIGHTS, lights); - // we need only the rotation for normals. mat4f_t mat; Transform_GetWorldMatrix (ent->transform, mat); VectorCopy (mat[0], norm_mat + 0); VectorCopy (mat[1], norm_mat + 3); VectorCopy (mat[2], norm_mat + 6); + entorigin = mat[3]; mmulf (mvp_mat, iqm_vp, mat); + R_LightPoint (&r_worldentity.renderer.model->brush, &entorigin[0]);//FIXME min_light? + VectorScale (ambientcolor, 1/255.0, ambientcolor); + R_FindNearLights (&entorigin[0], MAX_IQM_LIGHTS, lights);//FIXME + blend = R_IQMGetLerpedFrames (ent, iqm); frame = R_IQMBlendFrames (iqm, ent->animation.pose1, ent->animation.pose2, blend, 0); @@ -240,7 +242,7 @@ glsl_R_DrawIQM (void) lightpar_t *l = &iqm_shader.lights[i]; if (!lights[i]) break; - VectorSubtract (lights[i]->origin, ent->origin, val); + VectorSubtract (lights[i]->origin, entorigin, val); val[3] = lights[i]->radius; qfeglUniform4fv (l->position.location, 1, val); qfeglUniform4fv (l->color.location, 1, lights[i]->color); diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index 65af9d238..f34de4692 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -44,6 +44,7 @@ #endif #include +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" @@ -70,6 +71,7 @@ R_AddDynamicLights_1 (msurface_t *surf) int sd, td; float dist, rad, minlight; vec3_t impact, local, lightorigin; + vec4f_t entorigin = { 0, 0, 0, 1}; int s, t; int smax, tmax; mtexinfo_t *tex; @@ -78,12 +80,16 @@ R_AddDynamicLights_1 (msurface_t *surf) tmax = (surf->extents[1] >> 4) + 1; tex = surf->texinfo; + if (currententity->transform) { + //FIXME give world entity a transform + entorigin = Transform_GetWorldPosition (currententity->transform); + } + for (lnum = 0; lnum < r_maxdlights; lnum++) { if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32)))) continue; // not lit by this light - VectorSubtract (r_dlights[lnum].origin, currententity->origin, - lightorigin); + VectorSubtract (r_dlights[lnum].origin, entorigin, lightorigin); rad = r_dlights[lnum].radius; dist = DotProduct (lightorigin, surf->plane->normal) - surf->plane->dist; diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index ba8c2dce7..fed46ed3a 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -113,8 +113,11 @@ glsl_R_SetupFrame (void) R_ClearEnts (); r_framecount++; - VectorCopy (r_refdef.vieworg, r_origin); - AngleVectors (r_refdef.viewangles, vpn, vright, vup); + VectorCopy (r_refdef.viewposition, r_origin); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); + R_SetFrustum (); @@ -131,7 +134,6 @@ R_SetupView (void) { 0, 1, 0, 0}, { 0, 0, 0, 1}, }; - vec4f_t rotation; vec4f_t offset = { 0, 0, 0, 1 }; x = r_refdef.vrect.x; @@ -140,11 +142,10 @@ R_SetupView (void) h = r_refdef.vrect.height; qfeglViewport (x, y, w, h); - AngleQuat (r_refdef.viewangles, &rotation[0]); - rotation = qconjf (rotation); - mat4fquat (glsl_view, rotation); + mat4fquat (glsl_view, qconjf (r_refdef.viewrotation)); mmulf (glsl_view, z_up, glsl_view); - VectorNegate (r_refdef.vieworg, offset); + offset = -r_refdef.viewposition; + offset[3] = 1; glsl_view[3] = mvmulf (glsl_view, offset); qfeglEnable (GL_CULL_FACE); @@ -304,6 +305,7 @@ glsl_R_ClearState (void) void glsl_R_TimeRefresh_f (void) { +/* FIXME update for simd double start, stop, time; int i; @@ -319,4 +321,5 @@ glsl_R_TimeRefresh_f (void) stop = Sys_DoubleTime (); time = stop - start; Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); +*/ } diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index eb7eccb6d..de8c64602 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -42,6 +42,7 @@ #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/image.h" #include "QF/mersenne.h" #include "QF/qargs.h" @@ -629,12 +630,14 @@ R_RocketTrail_QF (const entity_t *ent) float dist, maxlen, origlen, percent, pscale, pscalenext; float len = 0.0; vec3_t old_origin, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 1.5 + qfrandom (1.5); @@ -663,12 +666,14 @@ R_GrenadeTrail_QF (const entity_t *ent) float dist, maxlen, origlen, percent, pscale, pscalenext; float len = 0.0; vec3_t old_origin, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 6.0 + qfrandom (7.0); @@ -698,12 +703,14 @@ R_BloodTrail_QF (const entity_t *ent) float len = 0.0; int j; vec3_t old_origin, porg, pvel, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 5.0 + qfrandom (10.0); @@ -738,12 +745,14 @@ R_SlightBloodTrail_QF (const entity_t *ent) float len = 0.0; int j; vec3_t old_origin, porg, pvel, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 1.5 + qfrandom (7.5); @@ -778,12 +787,14 @@ R_WizTrail_QF (const entity_t *ent) float dist = 3.0, len = 0.0; static int tracercount; vec3_t old_origin, pvel, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; VectorScale (vec, maxlen - dist, subtract); @@ -819,12 +830,14 @@ R_FlameTrail_QF (const entity_t *ent) float dist = 3.0, len = 0.0; static int tracercount; vec3_t old_origin, pvel, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; VectorScale (vec, maxlen - dist, subtract); @@ -860,12 +873,14 @@ R_VoorTrail_QF (const entity_t *ent) float dist = 3.0, len = 0.0; int j; vec3_t subtract, old_origin, porg, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; VectorScale (vec, maxlen - dist, subtract); @@ -898,7 +913,8 @@ R_GlowTrail_QF (const entity_t *ent, int glow_color) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; VectorScale (vec, (maxlen - dist), subtract); @@ -977,12 +993,14 @@ R_RocketTrail_EE (const entity_t *ent) float dist, maxlen, origlen, percent, pscale, pscalenext; float len = 0.0; vec3_t old_origin, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 1.5 + qfrandom (1.5); @@ -1012,12 +1030,14 @@ R_GrenadeTrail_EE (const entity_t *ent) float dist, maxlen, origlen, percent, pscale, pscalenext; float len = 0.0; vec3_t old_origin, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, ent->old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, ent->old_origin, vec); maxlen = VectorNormalize (vec); origlen = vr_data.frametime / maxlen; pscale = 6.0 + qfrandom (7.0); @@ -1251,7 +1271,7 @@ R_DarkFieldParticles_ID (const entity_t *ent) // l = r_maxparticles - numparticles; // } - VectorCopy (ent->origin, org); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); for (i = -16; i < 16; i += 8) { dir [1] = i * 8; @@ -1285,6 +1305,7 @@ R_EntityParticles_ID (const entity_t *ent) float angle, sp, sy, cp, cy; // cr, sr float beamlength = 16.0, dist = 64.0; vec3_t forward, porg; + vec3_t org; if (numparticles + j >= r_maxparticles) { return; @@ -1292,6 +1313,8 @@ R_EntityParticles_ID (const entity_t *ent) j = r_maxparticles - numparticles; } + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + for (i = 0; i < NUMVERTEXNORMALS; i++) { int k; for (k = 0; k < 3; k++) { @@ -1315,11 +1338,11 @@ R_EntityParticles_ID (const entity_t *ent) forward[1] = cp * sy; forward[2] = -sp; - porg[0] = ent->origin[0] + vertex_normals[i][0] * dist + + porg[0] = org[0] + vertex_normals[i][0] * dist + forward[0] * beamlength; - porg[1] = ent->origin[1] + vertex_normals[i][1] * dist + + porg[1] = org[1] + vertex_normals[i][1] * dist + forward[1] * beamlength; - porg[2] = ent->origin[2] + vertex_normals[i][2] * dist + + porg[2] = org[2] + vertex_normals[i][2] * dist + forward[2] * beamlength; particle_new (pt_explode, part_tex_dot, porg, 1.0, vec3_origin, vr_data.realtime + 0.01, 0x6f, 1.0, 0); @@ -1338,7 +1361,8 @@ R_RocketTrail_ID (const entity_t *ent) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, ent->old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, ent->old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, (maxlen - dist), subtract); @@ -1370,7 +1394,8 @@ R_GrenadeTrail_ID (const entity_t *ent) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, ent->old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, ent->old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1397,12 +1422,14 @@ R_BloodTrail_ID (const entity_t *ent) float dist = 3.0, len = 0.0; unsigned int rnd; vec3_t old_origin, subtract, vec, porg; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1428,12 +1455,14 @@ R_SlightBloodTrail_ID (const entity_t *ent) float dist = 6.0, len = 0.0; unsigned int rnd; vec3_t old_origin, porg, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1459,12 +1488,14 @@ R_WizTrail_ID (const entity_t *ent) float dist = 3.0, len = 0.0; static int tracercount; vec3_t old_origin, pvel, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1496,12 +1527,14 @@ R_FlameTrail_ID (const entity_t *ent) float dist = 3.0, len = 0.0; static int tracercount; vec3_t old_origin, pvel, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1533,12 +1566,14 @@ R_VoorTrail_ID (const entity_t *ent) float dist = 3.0, len = 0.0; unsigned int rnd; vec3_t old_origin, porg, subtract, vec; + vec3_t org; if (numparticles >= r_maxparticles) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); maxlen = VectorNormalize (vec); VectorScale (vec, maxlen - dist, subtract); @@ -1594,7 +1629,7 @@ draw_qf_particles (void) // LordHavoc: particles should not affect zbuffer qfeglDepthMask (GL_FALSE); - minparticledist = DotProduct (r_refdef.vieworg, vpn) + + minparticledist = DotProduct (r_refdef.viewposition, vpn) + r_particles_nearclip->value; activeparticles = 0; @@ -1736,7 +1771,7 @@ draw_id_particles (void) qfeglEnable (GL_TEXTURE_2D); qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); - minparticledist = DotProduct (r_refdef.vieworg, vpn) + + minparticledist = DotProduct (r_refdef.viewposition, vpn) + r_particles_nearclip->value; activeparticles = 0; diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 4d35bc8d6..7eecea5dd 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -185,6 +185,7 @@ make_quad (mspriteframe_t *frame, vec4f_t vpn, vec4f_t vright, { vec4f_t left, up, right, down; vec4f_t ul, ur, ll, lr; + vec4f_t origin = Transform_GetWorldPosition (currententity->transform); // build the sprite poster in worldspace // first, rotate the sprite axes into world space @@ -198,12 +199,12 @@ make_quad (mspriteframe_t *frame, vec4f_t vpn, vec4f_t vright, ll = down + left; lr = down + right; // finally, translate the sprite corners, creating two triangles - VectorAdd (currententity->origin, ul, verts[0]); // first triangle - VectorAdd (currententity->origin, ur, verts[1]); - VectorAdd (currententity->origin, lr, verts[2]); - VectorAdd (currententity->origin, ul, verts[3]); // second triangle - VectorAdd (currententity->origin, lr, verts[4]); - VectorAdd (currententity->origin, ll, verts[5]); + VectorAdd (origin, ul, verts[0]); // first triangle + VectorAdd (origin, ur, verts[1]); + VectorAdd (origin, lr, verts[2]); + VectorAdd (origin, ul, verts[3]); // second triangle + VectorAdd (origin, lr, verts[4]); + VectorAdd (origin, ll, verts[5]); } void @@ -212,9 +213,9 @@ R_DrawSprite (void) entity_t *ent = currententity; msprite_t *sprite = (msprite_t *) ent->renderer.model->cache.data; mspriteframe_t *frame1, *frame2; - float blend, sr, cr, dot, angle; + float blend, sr, cr, dot; vec3_t tvec; - vec4f_t svpn = {}, svright = {}, svup = {}; + vec4f_t svpn = {}, svright = {}, svup = {}, rot; static quat_t color = { 1, 1, 1, 1}; float vertsa[6][3], vertsb[6][3]; static float uvab[6][4] = { @@ -284,9 +285,10 @@ R_DrawSprite (void) // rotated in that plane round the center according to the sprite // entity's roll angle. Thus svpn stays the same, but svright and // svup rotate - angle = currententity->angles[ROLL] * (M_PI / 180); - sr = sin (angle); - cr = cos (angle); + rot = Transform_GetLocalRotation (currententity->transform); + //FIXME assumes the entity is only rolled + sr = 2 * rot[0] * rot[3]; + cr = rot[3] * rot[3] - rot[0] * rot[0]; VectorCopy (vpn, svpn); VectorScale (vright, cr, svright); VectorMultAdd (svright, sr, vup, svright); diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 86d494b6d..eb559e9cd 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -30,6 +30,7 @@ #include +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" @@ -210,8 +211,9 @@ R_AddEfrags (mod_brush_t *brush, entity_t *ent) entmodel = ent->renderer.model; - VectorAdd (ent->origin, entmodel->mins, emins); - VectorAdd (ent->origin, entmodel->maxs, emaxs); + vec4f_t org = Transform_GetWorldPosition (ent->transform); + VectorAdd (org, entmodel->mins, emins); + VectorAdd (org, entmodel->maxs, emaxs); ent->visibility.topnode = 0; R_SplitEntityOnNode (brush, ent, emins, emaxs); diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index f510e2063..d1e8a4e29 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -29,6 +29,7 @@ #endif #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/render.h" #include "d_local.h" @@ -207,7 +208,8 @@ D_DrawSurfaces (void) // TODO: store once at start of frame currententity = s->entity; // FIXME: make this passed in // to R_RotateBmodel () - VectorSubtract (r_origin, currententity->origin, + VectorSubtract (r_origin, + Transform_GetWorldPosition (currententity->transform), local_modelorg); TransformVector (local_modelorg, transformed_modelorg); @@ -240,7 +242,8 @@ D_DrawSurfaces (void) // TODO: store once at start of frame currententity = s->entity; // FIXME: make this passed in // to R_RotateBmodel () - VectorSubtract (r_origin, currententity->origin, + VectorSubtract (r_origin, + Transform_GetWorldPosition (currententity->transform), local_modelorg); TransformVector (local_modelorg, transformed_modelorg); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 8ab480bcc..63eecbb60 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -362,16 +362,16 @@ R_DrawEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { currententity = ent; + VectorCopy (Transform_GetWorldPosition (currententity->transform), + r_entorigin); switch (currententity->renderer.model->type) { case mod_sprite: - VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); R_DrawSprite (); break; case mod_alias: case mod_iqm: - VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); minlight = max (currententity->renderer.model->min_light, @@ -384,7 +384,7 @@ R_DrawEntitiesOnList (void) || R_AliasCheckBBox ()) { // 128 instead of 255 due to clamping below j = max (R_LightPoint (&r_worldentity.renderer.model->brush, - currententity->origin), minlight * 128); + r_entorigin), minlight * 128); lighting.ambientlight = j; lighting.shadelight = j; @@ -393,7 +393,7 @@ R_DrawEntitiesOnList (void) for (lnum = 0; lnum < r_maxdlights; lnum++) { if (r_dlights[lnum].die >= vr_data.realtime) { - VectorSubtract (currententity->origin, + VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist); add = r_dlights[lnum].radius - VectorLength (dist); @@ -443,7 +443,8 @@ R_DrawViewModel (void) if (!currententity->renderer.model) return; - VectorCopy (currententity->origin, r_entorigin); + VectorCopy (Transform_GetWorldPosition (currententity->transform), + r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); VectorCopy (vup, viewlightvec); @@ -453,7 +454,7 @@ R_DrawViewModel (void) currententity->renderer.model->min_light); j = max (R_LightPoint (&r_worldentity.renderer.model->brush, - currententity->origin), minlight * 128); + r_entorigin), minlight * 128); r_viewlighting.ambientlight = j; r_viewlighting.shadelight = j; @@ -468,7 +469,7 @@ R_DrawViewModel (void) if (dl->die < vr_data.realtime) continue; - VectorSubtract (currententity->origin, dl->origin, dist); + VectorSubtract (r_entorigin, dl->origin, dist); add = dl->radius - VectorLength (dist); if (add > 0) r_viewlighting.ambientlight += add; @@ -498,7 +499,7 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) Transform_GetWorldMatrix (currententity->transform, mat); if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { for (i = 0; i < 4; i++) { - d = DotProduct (currententity->origin, view_clipplanes[i].normal); + d = DotProduct (mat[3], view_clipplanes[i].normal); d -= view_clipplanes[i].dist; if (d <= -clmodel->radius) @@ -546,6 +547,7 @@ R_DrawBEntitiesOnList (void) int j, clipflags; unsigned int k; vec3_t oldorigin; + vec3_t origin; model_t *clmodel; float minmaxs[6]; entity_t *ent; @@ -559,6 +561,8 @@ R_DrawBEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { currententity = ent; + VectorCopy (Transform_GetWorldPosition (currententity->transform), + origin); switch (currententity->renderer.model->type) { case mod_brush: clmodel = currententity->renderer.model; @@ -566,16 +570,15 @@ R_DrawBEntitiesOnList (void) // see if the bounding box lets us trivially reject, also // sets trivial accept status for (j = 0; j < 3; j++) { - minmaxs[j] = currententity->origin[j] + clmodel->mins[j]; - minmaxs[3 + j] = currententity->origin[j] + - clmodel->maxs[j]; + minmaxs[j] = origin[j] + clmodel->mins[j]; + minmaxs[3 + j] = origin[j] + clmodel->maxs[j]; } clipflags = R_BmodelCheckBBox (clmodel, minmaxs); if (clipflags != BMODEL_FULLY_CLIPPED) { mod_brush_t *brush = &clmodel->brush; - VectorCopy (currententity->origin, r_entorigin); + VectorCopy (origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); // FIXME: is this needed? @@ -594,8 +597,7 @@ R_DrawBEntitiesOnList (void) if ((r_dlights[k].die < vr_data.realtime) || (!r_dlights[k].radius)) continue; - VectorSubtract (r_dlights[k].origin, - currententity->origin, + VectorSubtract (r_dlights[k].origin, origin, lightorigin); R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, @@ -829,7 +831,7 @@ R_RenderView_ (void) R_HighFPPrecision (); } -static void R_RenderViewFishEye (void); +//XXX FIXME static void R_RenderViewFishEye (void); void R_RenderView (void) @@ -849,11 +851,12 @@ R_RenderView (void) if ((intptr_t) (&r_warpbuffer) & 3) Sys_Error ("Globals are missaligned"); - + R_RenderView_ (); +/*XXX FIXME if (!scr_fisheye->int_val) R_RenderView_ (); else - R_RenderViewFishEye (); + R_RenderViewFishEye ();*/ } void @@ -867,7 +870,7 @@ R_InitTurb (void) // AMP2 not 20 } } - +/*XXX FIXME #define BOX_FRONT 0 #define BOX_BEHIND 2 #define BOX_LEFT 3 @@ -1152,7 +1155,7 @@ R_RenderViewFishEye (void) r_refdef.viewangles[PITCH] = pitch; r_refdef.viewangles[ROLL] = roll; renderlookup (offs, scrbufs); -} +}*/ void R_ClearState (void) diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index dee5c780e..2ea74ad4e 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -53,6 +53,7 @@ R_CheckVariables (void) void R_TimeRefresh_f (void) { +/* FIXME update for simd int i; float start, stop, time; int startangle; @@ -82,6 +83,7 @@ R_TimeRefresh_f (void) Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); r_refdef.viewangles[1] = startangle; +*/ } void @@ -237,10 +239,12 @@ R_SetupFrame (void) #endif // build the transformation matrix for the given view angles - VectorCopy (r_refdef.vieworg, modelorg); - VectorCopy (r_refdef.vieworg, r_origin); + VectorCopy (r_refdef.viewposition, modelorg); + VectorCopy (r_refdef.viewposition, r_origin); - AngleVectors (r_refdef.viewangles, vpn, vright, vup); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); R_SetFrustum (); // current viewleaf diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index d154ad739..c429279b2 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -37,6 +37,7 @@ #endif #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/mersenne.h" #include "QF/qargs.h" #include "QF/quakefs.h" @@ -386,9 +387,7 @@ R_DarkFieldParticles_ID (const entity_t *ent) if (!r_particles->int_val) return; - org[0] = ent->origin[0]; - org[1] = ent->origin[1]; - org[2] = ent->origin[2]; + VectorCopy (Transform_GetWorldPosition (ent->transform), org); for (i = -16; i < 16; i += 8) { for (j = -16; j < 16; j += 8) { for (k = 0; k < 32; k += 8) { @@ -431,10 +430,13 @@ R_EntityParticles_ID (const entity_t *ent) float beamlength = 16.0, dist = 64.0; particle_t *p; vec3_t forward; + vec3_t org; if (!r_particles->int_val) return; + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + for (i = 0; i < NUMVERTEXNORMALS; i++) { int k; for (k = 0; k < 3; k++) { @@ -470,11 +472,11 @@ R_EntityParticles_ID (const entity_t *ent) p->type = pt_explode; p->phys = R_ParticlePhysics (p->type); - p->org[0] = ent->origin[0] + r_avertexnormals[i][0] * dist + + p->org[0] = org[0] + r_avertexnormals[i][0] * dist + forward[0] * beamlength; - p->org[1] = ent->origin[1] + r_avertexnormals[i][1] * dist + + p->org[1] = org[1] + r_avertexnormals[i][1] * dist + forward[1] * beamlength; - p->org[2] = ent->origin[2] + r_avertexnormals[i][2] * dist + + p->org[2] = org[2] + r_avertexnormals[i][2] * dist + forward[2] * beamlength; } } @@ -486,12 +488,14 @@ R_RocketTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; + VectorCopy (Transform_GetWorldPosition (ent->transform), org); VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -525,12 +529,14 @@ R_GrenadeTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -564,12 +570,14 @@ R_BloodTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -602,12 +610,14 @@ R_SlightBloodTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -639,12 +649,14 @@ R_WizTrail_QF (const entity_t *ent) float len; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -686,12 +698,14 @@ R_FlameTrail_QF (const entity_t *ent) float len; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -734,12 +748,14 @@ R_VoorTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 8eb4151e7..6a70d2f4f 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -286,7 +286,7 @@ R_DrawSprite (void) int i; msprite_t *psprite; vec3_t tvec; - float dot, angle, sr, cr; + float dot, sr, cr; psprite = currententity->renderer.model->cache.data; @@ -371,9 +371,10 @@ R_DrawSprite (void) // generate the sprite's axes, parallel to the viewplane, but rotated // in that plane around the center according to the sprite entity's // roll angle. So vpn stays the same, but vright and vup rotate - angle = currententity->angles[ROLL] * (M_PI * 2 / 360); - sr = sin (angle); - cr = cos (angle); + vec4f_t rot = Transform_GetLocalRotation (currententity->transform); + //FIXME assumes the entity is only rolled + sr = 2 * rot[0] * rot[3]; + cr = rot[3] * rot[3] - rot[0] * rot[0]; for (i = 0; i < 3; i++) { r_spritedesc.vpn[i] = vpn[i]; diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 1dded8c00..36ea5fe79 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -28,6 +28,7 @@ # include "config.h" #endif +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" @@ -78,6 +79,7 @@ R_AddDynamicLights (void) int sd, td; float dist, rad, minlight; vec3_t impact, local, lightorigin; + vec4f_t entorigin = { 0, 0, 0, 1 }; int s, t; int i; int smax, tmax; @@ -88,12 +90,16 @@ R_AddDynamicLights (void) tmax = (surf->extents[1] >> 4) + 1; tex = surf->texinfo; + if (currententity->transform) { + //FIXME give world entity a transform + entorigin = Transform_GetWorldPosition (currententity->transform); + } + for (lnum = 0; lnum < r_maxdlights; lnum++) { if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32)))) continue; // not lit by this light - VectorSubtract (r_dlights[lnum].origin, currententity->origin, - lightorigin); + VectorSubtract (r_dlights[lnum].origin, entorigin, lightorigin); rad = r_dlights[lnum].radius; dist = DotProduct (lightorigin, surf->plane->normal) - surf->plane->dist; diff --git a/libs/video/renderer/sw32/d_edge.c b/libs/video/renderer/sw32/d_edge.c index 6fa0b131a..6015eaf23 100644 --- a/libs/video/renderer/sw32/d_edge.c +++ b/libs/video/renderer/sw32/d_edge.c @@ -32,6 +32,7 @@ #include "namehack.h" #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" @@ -243,7 +244,8 @@ sw32_D_DrawSurfaces (void) // TODO: store once at start of frame currententity = s->entity; // FIXME: make this passed in // to sw32_R_RotateBmodel () - VectorSubtract (r_origin, currententity->origin, + VectorSubtract (r_origin, + Transform_GetWorldPosition (currententity->transform), local_modelorg); sw32_TransformVector (local_modelorg, transformed_modelorg); @@ -276,7 +278,8 @@ sw32_D_DrawSurfaces (void) // TODO: store once at start of frame currententity = s->entity; // FIXME: make this passed in // to sw32_R_RotateBmodel () - VectorSubtract (r_origin, currententity->origin, + VectorSubtract (r_origin, + Transform_GetWorldPosition (currententity->transform), local_modelorg); sw32_TransformVector (local_modelorg, transformed_modelorg); diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 36d94fd2a..d6dfd7670 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -369,16 +369,16 @@ R_DrawEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { currententity = ent; + VectorCopy (Transform_GetWorldPosition (currententity->transform), + r_entorigin); switch (currententity->renderer.model->type) { case mod_sprite: - VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); sw32_R_DrawSprite (); break; case mod_alias: case mod_iqm: - VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); minlight = max (currententity->renderer.min_light, @@ -391,7 +391,7 @@ R_DrawEntitiesOnList (void) || sw32_R_AliasCheckBBox ()) { // 128 instead of 255 due to clamping below j = max (R_LightPoint (&r_worldentity.renderer.model->brush, - currententity->origin), + r_entorigin), minlight * 128); lighting.ambientlight = j; @@ -401,7 +401,7 @@ R_DrawEntitiesOnList (void) for (lnum = 0; lnum < r_maxdlights; lnum++) { if (r_dlights[lnum].die >= vr_data.realtime) { - VectorSubtract (currententity->origin, + VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist); add = r_dlights[lnum].radius - VectorLength (dist); @@ -450,7 +450,8 @@ R_DrawViewModel (void) if (!currententity->renderer.model) return; - VectorCopy (currententity->origin, r_entorigin); + VectorCopy (Transform_GetWorldPosition (currententity->transform), + r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); VectorCopy (vup, viewlightvec); @@ -460,7 +461,7 @@ R_DrawViewModel (void) currententity->renderer.model->min_light); j = max (R_LightPoint (&r_worldentity.renderer.model->brush, - currententity->origin), minlight * 128); + r_entorigin), minlight * 128); r_viewlighting.ambientlight = j; r_viewlighting.shadelight = j; @@ -475,7 +476,7 @@ R_DrawViewModel (void) if (dl->die < vr_data.realtime) continue; - VectorSubtract (currententity->origin, dl->origin, dist); + VectorSubtract (r_entorigin, dl->origin, dist); add = dl->radius - VectorLength (dist); if (add > 0) r_viewlighting.ambientlight += add; @@ -505,7 +506,7 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) Transform_GetWorldMatrix (currententity->transform, mat); if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { for (i = 0; i < 4; i++) { - d = DotProduct (currententity->origin, sw32_view_clipplanes[i].normal); + d = DotProduct (mat[3], sw32_view_clipplanes[i].normal); d -= sw32_view_clipplanes[i].dist; if (d <= -clmodel->radius) @@ -553,6 +554,7 @@ R_DrawBEntitiesOnList (void) int j, clipflags; unsigned int k; vec3_t oldorigin; + vec3_t origin; model_t *clmodel; float minmaxs[6]; entity_t *ent; @@ -566,6 +568,8 @@ R_DrawBEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { currententity = ent; + VectorCopy (Transform_GetWorldPosition (currententity->transform), + origin); switch (currententity->renderer.model->type) { case mod_brush: clmodel = currententity->renderer.model; @@ -573,16 +577,15 @@ R_DrawBEntitiesOnList (void) // see if the bounding box lets us trivially reject, also // sets trivial accept status for (j = 0; j < 3; j++) { - minmaxs[j] = currententity->origin[j] + clmodel->mins[j]; - minmaxs[3 + j] = currententity->origin[j] + - clmodel->maxs[j]; + minmaxs[j] = origin[j] + clmodel->mins[j]; + minmaxs[3 + j] = origin[j] + clmodel->maxs[j]; } clipflags = R_BmodelCheckBBox (clmodel, minmaxs); if (clipflags != BMODEL_FULLY_CLIPPED) { mod_brush_t *brush = &clmodel->brush; - VectorCopy (currententity->origin, r_entorigin); + VectorCopy (origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); // FIXME: is this needed? @@ -601,8 +604,7 @@ R_DrawBEntitiesOnList (void) if ((r_dlights[k].die < vr_data.realtime) || (!r_dlights[k].radius)) continue; - VectorSubtract (r_dlights[k].origin, - currententity->origin, + VectorSubtract (r_dlights[k].origin, origin, lightorigin); R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c index 753268993..390b13b86 100644 --- a/libs/video/renderer/sw32/sw32_rmisc.c +++ b/libs/video/renderer/sw32/sw32_rmisc.c @@ -55,6 +55,7 @@ R_CheckVariables (void) void sw32_R_TimeRefresh_f (void) { +/* FIXME update for simd int i; float start, stop, time; int startangle; @@ -84,6 +85,7 @@ sw32_R_TimeRefresh_f (void) Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); r_refdef.viewangles[1] = startangle; +*/ } void @@ -233,10 +235,12 @@ sw32_R_SetupFrame (void) #endif // build the transformation matrix for the given view angles - VectorCopy (r_refdef.vieworg, modelorg); - VectorCopy (r_refdef.vieworg, r_origin); + VectorCopy (r_refdef.viewposition, modelorg); + VectorCopy (r_refdef.viewposition, r_origin); - AngleVectors (r_refdef.viewangles, vpn, vright, vup); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); R_SetFrustum (); // current viewleaf diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index fc640bc8e..851618819 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -40,6 +40,7 @@ #endif #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/mersenne.h" #include "QF/qargs.h" #include "QF/quakefs.h" @@ -330,9 +331,7 @@ R_DarkFieldParticles_ID (const entity_t *ent) particle_t *p; vec3_t dir, org; - org[0] = ent->origin[0]; - org[1] = ent->origin[1]; - org[2] = ent->origin[2]; + VectorCopy (Transform_GetWorldPosition (ent->transform), org); for (i = -16; i < 16; i += 8) { for (j = -16; j < 16; j += 8) { for (k = 0; k < 32; k += 8) { @@ -376,6 +375,9 @@ R_EntityParticles_ID (const entity_t *ent) float beamlength = 16.0, dist = 64.0; particle_t *p; vec3_t forward; + vec3_t org; + + VectorCopy (Transform_GetWorldPosition (ent->transform), org); for (i = 0; i < NUMVERTEXNORMALS; i++) { int k; @@ -412,11 +414,11 @@ R_EntityParticles_ID (const entity_t *ent) p->type = pt_explode; p->phys = R_ParticlePhysics (p->type); - p->org[0] = ent->origin[0] + r_avertexnormals[i][0] * dist + + p->org[0] = org[0] + r_avertexnormals[i][0] * dist + forward[0] * beamlength; - p->org[1] = ent->origin[1] + r_avertexnormals[i][1] * dist + + p->org[1] = org[1] + r_avertexnormals[i][1] * dist + forward[1] * beamlength; - p->org[2] = ent->origin[2] + r_avertexnormals[i][2] * dist + + p->org[2] = org[2] + r_avertexnormals[i][2] * dist + forward[2] * beamlength; } } @@ -499,12 +501,14 @@ R_RocketTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, ent->old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, ent->old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -538,12 +542,14 @@ R_GrenadeTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -577,12 +583,14 @@ R_BloodTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -615,12 +623,14 @@ R_SlightBloodTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -652,12 +662,14 @@ R_WizTrail_QF (const entity_t *ent) float len; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -699,12 +711,14 @@ R_FlameTrail_QF (const entity_t *ent) float len; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { @@ -747,12 +761,14 @@ R_VoorTrail_QF (const entity_t *ent) int j; particle_t *p; vec3_t old_origin, vec; + vec3_t org; if (!r_particles->int_val) return; VectorCopy (ent->old_origin, old_origin); - VectorSubtract (ent->origin, old_origin, vec); + VectorCopy (Transform_GetWorldPosition (ent->transform), org); + VectorSubtract (org, old_origin, vec); len = VectorNormalize (vec); while (len > 0) { diff --git a/libs/video/renderer/sw32/sw32_rsprite.c b/libs/video/renderer/sw32/sw32_rsprite.c index 9c6cb7221..bbdc1996f 100644 --- a/libs/video/renderer/sw32/sw32_rsprite.c +++ b/libs/video/renderer/sw32/sw32_rsprite.c @@ -282,7 +282,7 @@ sw32_R_DrawSprite (void) int i; msprite_t *psprite; vec3_t tvec; - float dot, angle, sr, cr; + float dot, sr, cr; psprite = currententity->renderer.model->cache.data; @@ -367,9 +367,10 @@ sw32_R_DrawSprite (void) // generate the sprite's axes, parallel to the viewplane, but rotated // in that plane around the center according to the sprite entity's // roll angle. So vpn stays the same, but vright and vup rotate - angle = currententity->angles[ROLL] * (M_PI * 2 / 360); - sr = sin (angle); - cr = cos (angle); + vec4f_t rot = Transform_GetLocalRotation (currententity->transform); + //FIXME assumes the entity is only rolled + sr = 2 * rot[0] * rot[3]; + cr = rot[3] * rot[3] - rot[0] * rot[0]; for (i = 0; i < 3; i++) { sw32_r_spritedesc.vpn[i] = vpn[i]; diff --git a/libs/video/renderer/sw32/sw32_rsurf.c b/libs/video/renderer/sw32/sw32_rsurf.c index dfc9c31cc..9eba575a9 100644 --- a/libs/video/renderer/sw32/sw32_rsurf.c +++ b/libs/video/renderer/sw32/sw32_rsurf.c @@ -31,6 +31,7 @@ #define NH_DEFINE #include "namehack.h" +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" @@ -96,6 +97,7 @@ R_AddDynamicLights (void) int sd, td; float dist, rad, minlight; vec3_t impact, local, lightorigin; + vec4f_t entorigin = { 0, 0, 0, 1 }; int s, t; int i; int smax, tmax; @@ -106,12 +108,16 @@ R_AddDynamicLights (void) tmax = (surf->extents[1] >> 4) + 1; tex = surf->texinfo; + if (currententity->transform) { + //FIXME give world entity a transform + entorigin = Transform_GetWorldPosition (currententity->transform); + } + for (lnum = 0; lnum < r_maxdlights; lnum++) { if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32)))) continue; // not lit by this light - VectorSubtract (r_dlights[lnum].origin, currententity->origin, - lightorigin); + VectorSubtract (r_dlights[lnum].origin, entorigin, lightorigin); rad = r_dlights[lnum].radius; dist = DotProduct (lightorigin, surf->plane->normal) - surf->plane->dist; diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index e2db7cc78..7468e4dec 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -44,7 +44,7 @@ main (void) vec3 c = subpassLoad (color).rgb; vec3 n = subpassLoad (normal).rgb; vec3 p = subpassLoad (position).rgb; - vec3 light = vec3 (0); + vec3 light = vec3 (0.8); if (MaxLights > 0) { for (int i = 0; i < lightCount; i++) { diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 38aa57ee9..f1ba6e472 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -610,7 +610,8 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) plane_t *plane; msurface_t *surf; qboolean rotated; - vec3_t mins, maxs, org; + vec3_t mins, maxs; + vec4f_t org; mod_brush_t *brush; model = e->renderer.model; @@ -621,21 +622,21 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; - if (R_CullSphere (e->origin, radius)) + if (R_CullSphere (&mat[3][0], radius)) { //FIXME return; + } } else { rotated = false; - VectorAdd (e->origin, model->mins, mins); - VectorAdd (e->origin, model->maxs, maxs); + VectorAdd (mat[3], model->mins, mins); + VectorAdd (mat[3], model->maxs, maxs); if (R_CullBox (mins, maxs)) return; } - VectorSubtract (r_refdef.vieworg, e->origin, org); + org = r_refdef.viewposition - mat[3]; if (rotated) { - vec3_t temp; + vec4f_t temp = org; - VectorCopy (org, temp); org[0] = DotProduct (temp, mat[0]); org[1] = DotProduct (temp, mat[1]); org[2] = DotProduct (temp, mat[2]); @@ -650,7 +651,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) || (!r_dlights[k].radius)) continue; - VectorSubtract (r_dlights[k].origin, e->origin, lightorigin); + VectorSubtract (r_dlights[k].origin, mat[3], lightorigin); R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, brush->nodes + brush->hulls[0].firstclipnode); } diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 97c30c667..3cfbcb7ba 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -41,6 +41,7 @@ #include #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" #include "QF/Vulkan/qf_bsp.h" @@ -61,6 +62,7 @@ add_dynamic_lights (msurface_t *surf, float *block) int sd, td; float dist, rad, minlight; vec3_t impact, local, lightorigin; + vec4f_t entorigin = { 0, 0, 0, 1 }; int smax, tmax; int s, t; mtexinfo_t *tex; @@ -71,13 +73,18 @@ add_dynamic_lights (msurface_t *surf, float *block) tex = surf->texinfo; plane = surf->plane; + if (currententity->transform) { + //FIXME give world entity a transform + entorigin = Transform_GetWorldPosition (currententity->transform); + } + for (lnum = 0; lnum < r_maxdlights; lnum++) { if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32)))) continue; // not lit by this light dlight_t *light = &r_dlights[lnum]; - VectorSubtract (light->origin, currententity->origin, lightorigin); + VectorSubtract (light->origin, entorigin, lightorigin); rad = light->radius; dist = DotProduct (lightorigin, plane->normal) - plane->dist; rad -= fabs (dist); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index e63ff0b03..a7ed49669 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -66,8 +66,11 @@ setup_frame (vulkan_ctx_t *ctx) R_ClearEnts (); r_framecount++; - VectorCopy (r_refdef.vieworg, r_origin); - AngleVectors (r_refdef.viewangles, vpn, vright, vup); + VectorCopy (r_refdef.viewposition, r_origin); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); + VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); + R_SetFrustum (); r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); @@ -76,14 +79,14 @@ setup_frame (vulkan_ctx_t *ctx) static void setup_view (vulkan_ctx_t *ctx) { - mat4_t mat; - float *view = ctx->matrices.view_3d; - static mat4_t z_up = { - 0, 0, -1, 0, - -1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 0, 1, + mat4f_t view; + static mat4f_t z_up = { + { 0, 0, -1, 0}, + {-1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 0, 1}, }; + vec4f_t offset = { 0, 0, 0, 1 }; /*x = r_refdef.vrect.x; y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); @@ -91,17 +94,12 @@ setup_view (vulkan_ctx_t *ctx) h = r_refdef.vrect.height; qfeglViewport (x, y, w, h);*/ - Mat4Zero (mat); - VectorCopy (vpn, mat + 0); - VectorNegate (vright, mat + 4); // we want vleft - VectorCopy (vup, mat + 8); - mat[15] = 1; - Mat4Transpose (mat, mat);//AngleVectors gives the transpose of what we want - Mat4Mult (z_up, mat, view); - - Mat4Identity (mat); - VectorNegate (r_refdef.vieworg, mat + 12); - Mat4Mult (view, mat, view); + mat4fquat (view, qconjf (r_refdef.viewrotation)); + mmulf (view, z_up, view); + offset = -r_refdef.viewposition; + offset[3] = 1; + view[3] = mvmulf (view, offset); + memcpy (ctx->matrices.view_3d, view, sizeof (view)); } static void diff --git a/nq/include/client.h b/nq/include/client.h index 4af07cd24..5d98e437b 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -38,6 +38,7 @@ #include "QF/render.h" #include "client/entities.h" +#include "client/view.h" #include "game.h" #include "netmain.h" @@ -165,11 +166,9 @@ typedef struct { int frameIndex; vec3_t frameViewAngles[2]; // During demo playback viewangles is lerped // between these - vec3_t viewangles; vec4f_t frameVelocity[2]; // Update by server, used for lean+bob // (0 is newest) - vec4f_t velocity; // Lerped between frameVelocity[0] and [1] - vec3_t punchangle; // Temporary offset + viewstate_t viewstate; // pitch drifting vars float idealpitch; diff --git a/nq/source/cl_chase.c b/nq/source/cl_chase.c index 5d23817cd..6f0c430c6 100644 --- a/nq/source/cl_chase.c +++ b/nq/source/cl_chase.c @@ -41,16 +41,19 @@ #include "QF/mathlib.h" #include "QF/plugin/vid_render.h" +#include "QF/simd/vec4f.h" #include "world.h" #include "nq/include/chase.h" #include "nq/include/client.h" -vec3_t camera_origin = {0,0,0}; -vec3_t camera_angles = {0,0,0}; -vec3_t player_origin = {0,0,0}; -vec3_t player_angles = {0,0,0}; + +vec4f_t camera_origin = {0,0,0,1}; +vec4f_t player_origin = {0,0,0,1}; +vec4f_t player_angles = {0,0,0,1}; + +vec3_t camera_angles = {0,0,0}; vec3_t chase_angles; vec3_t chase_dest; @@ -94,19 +97,17 @@ TraceLine (vec3_t start, vec3_t end, vec3_t impact) void Chase_Update (void) { - float pitch, yaw, fwd; - int i; - usercmd_t cmd; // movement direction - vec3_t forward, up, right, stop, dir; + float pitch, yaw, fwd; + usercmd_t cmd; // movement direction + vec4f_t forward = {}, up = {}, right = {}, stop = {}, dir = {}; // lazy camera, look toward player entity if (chase_active->int_val == 2 || chase_active->int_val == 3) { // control camera angles with key/mouse/joy-look - - camera_angles[PITCH] += cl.viewangles[PITCH] - player_angles[PITCH]; - camera_angles[YAW] += cl.viewangles[YAW] - player_angles[YAW]; - camera_angles[ROLL] += cl.viewangles[ROLL] - player_angles[ROLL]; + vec3_t d; + VectorSubtract (cl.viewstate.angles, player_angles, d); + VectorAdd (camera_angles, d, camera_angles); if (chase_active->int_val == 2) { if (camera_angles[PITCH] < -60) @@ -118,48 +119,48 @@ Chase_Update (void) // move camera, it's not enough to just change the angles because // the angles are automatically changed to look toward the player - if (chase_active->int_val == 3) - VectorCopy (r_data->refdef->vieworg, player_origin); + if (chase_active->int_val == 3) { + player_origin = r_data->refdef->viewposition; + } - AngleVectors (camera_angles, forward, right, up); - VectorScale (forward, chase_back->value, forward); - VectorSubtract (player_origin, forward, camera_origin); + AngleVectors (camera_angles, &forward[0], &right[0], &up[0]); + camera_origin = player_origin - chase_back->value * forward; if (chase_active->int_val == 2) { - VectorCopy (r_data->refdef->vieworg, player_origin); + player_origin = r_data->refdef->viewposition; // don't let camera get too low - if (camera_origin[2] < player_origin[2] + chase_up->value) + if (camera_origin[2] < player_origin[2] + chase_up->value) { camera_origin[2] = player_origin[2] + chase_up->value; + } } // don't let camera get too far from player - VectorSubtract (camera_origin, player_origin, dir); - VectorCopy (dir, forward); - VectorNormalize (forward); + dir = camera_origin - player_origin; + forward = normalf (dir); - if (VectorLength (dir) > chase_back->value) { - VectorScale (forward, chase_back->value, dir); - VectorAdd (player_origin, dir, camera_origin); + if (magnitudef (dir)[0] > chase_back->value) { + camera_origin = player_origin + forward * chase_back->value; } // check for walls between player and camera - VectorScale (forward, 8, forward); - VectorAdd (camera_origin, forward, camera_origin); - TraceLine (player_origin, camera_origin, stop); - if (VectorLength (stop) != 0) - VectorSubtract (stop, forward, camera_origin); + camera_origin += 8 * forward; + //FIXME + TraceLine (&player_origin[0], &camera_origin[0], &stop[0]); + stop[3] = 1; + if (magnitude3f (stop)[0] != 0) { + camera_origin = stop - forward; + } - VectorSubtract (camera_origin, r_data->refdef->vieworg, dir); - VectorCopy (dir, forward); - VectorNormalize (forward); + dir = camera_origin - r_data->refdef->viewposition; + forward = normalf (dir); if (chase_active->int_val == 2) { if (dir[1] == 0 && dir[0] == 0) { // look straight up or down -// camera_angles[YAW] = r_data->refdef->viewangles[YAW]; +// camera_angles[YAW] = r_data->refdef->viewstate.angles[YAW]; if (dir[2] > 0) camera_angles[PITCH] = 90; else @@ -182,13 +183,13 @@ Chase_Update (void) } } - VectorCopy (camera_angles, r_data->refdef->viewangles);// rotate camera - VectorCopy (camera_origin, r_data->refdef->vieworg); // move camera + AngleQuat (camera_angles, &r_data->refdef->viewrotation[0]);//FIXME rotate camera + r_data->refdef->viewposition = camera_origin; // move camera // get basic movement from keyboard memset (&cmd, 0, sizeof (cmd)); -// VectorCopy (cl.viewangles, cmd.angles); +// VectorCopy (cl.viewstate.angles, cmd.angles); if (in_strafe.state & 1) { cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_right); @@ -208,54 +209,54 @@ Chase_Update (void) } // mouse and joystick controllers add to movement - VectorSet (0, cl.viewangles[1] - camera_angles[1], 0, dir); - AngleVectors (dir, forward, right, up); - VectorScale (forward, viewdelta.position[2] * m_forward->value, - forward); - VectorScale (right, viewdelta.position[0] * m_side->value, right); - VectorAdd (forward, right, dir); + VectorSet (0, cl.viewstate.angles[1] - camera_angles[1], 0, dir); + AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME + forward *= viewdelta.position[2] * m_forward->value; + right *= viewdelta.position[0] * m_side->value; + dir = forward + right; cmd.forwardmove += dir[0]; cmd.sidemove -= dir[1]; VectorSet (0, camera_angles[1], 0, dir); - AngleVectors (dir, forward, right, up); + AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME VectorScale (forward, cmd.forwardmove, forward); VectorScale (right, cmd.sidemove, right); VectorAdd (forward, right, dir); if (dir[1] || dir[0]) { - cl.viewangles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (cl.viewangles[YAW] < 0) cl.viewangles[YAW] += 360; -// if (cl.viewangles[YAW] < 180) -// cl.viewangles[YAW] += 180; -// else -// cl.viewangles[YAW] -= 180; + cl.viewstate.angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); + if (cl.viewstate.angles[YAW] < 0) { + cl.viewstate.angles[YAW] += 360; + } } - cl.viewangles[PITCH] = 0; + cl.viewstate.angles[PITCH] = 0; // remember the new angle to calculate the difference next frame - VectorCopy (cl.viewangles, player_angles); + VectorCopy (cl.viewstate.angles, player_angles); return; } // regular camera, faces same direction as player - AngleVectors (cl.viewangles, forward, right, up); + //FIXME + AngleVectors (cl.viewstate.angles, &forward[0], &right[0], &up[0]); // calc exact destination - for (i = 0; i < 3; i++) - camera_origin[i] = r_data->refdef->vieworg[i] - - forward[i] * chase_back->value - right[i] * chase_right->value; + camera_origin = r_data->refdef->viewposition + - forward * chase_back->value - right * chase_right->value; + // chase_up is world up camera_origin[2] += chase_up->value; // check for walls between player and camera - TraceLine (r_data->refdef->vieworg, camera_origin, stop); - if (VectorLength (stop) != 0) - for (i = 0; i < 3; i++) - camera_origin[i] = stop[i] + forward[i] * 8; + //FIXME + TraceLine (&r_data->refdef->viewposition[0], &camera_origin[0], &stop[0]); + stop[3] = 1; + if (magnitude3f (stop)[0] != 0) { + camera_origin = stop + forward * 8; + } - VectorCopy (camera_origin, r_data->refdef->vieworg); + r_data->refdef->viewposition = camera_origin; } diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 39cdf9d24..03950998a 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -105,7 +105,7 @@ CL_WriteDemoMessage (sizebuf_t *msg) len = LittleLong (msg->cursize); Qwrite (cls.demofile, &len, 4); for (i = 0; i < 3; i++) { - f = LittleFloat (cl.viewangles[i]); + f = LittleFloat (cl.viewstate.angles[i]); Qwrite (cls.demofile, &f, 4); } Qwrite (cls.demofile, msg->data, msg->cursize); diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index e8aecb26c..2e04ff885 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -144,10 +144,9 @@ CL_RelinkEntities (void) entity_state_t *new, *old; renderer_t *renderer; animation_t *animation; - float bobjrotate, frac, f, d; + float bobjrotate, frac, f; int i, j; int entvalid; - vec3_t delta; int model_flags; r_data->player_entity = &cl_entities[cl.viewentity]; @@ -156,19 +155,21 @@ CL_RelinkEntities (void) frac = CL_LerpPoint (); // interpolate player info - cl.velocity = cl.frameVelocity[1] + cl.viewstate.velocity = cl.frameVelocity[1] + frac * (cl.frameVelocity[0] - cl.frameVelocity[1]); if (cls.demoplayback) { // interpolate the angles + vec3_t d; + VectorSubtract (cl.frameViewAngles[0], cl.frameViewAngles[1], d); for (j = 0; j < 3; j++) { - d = cl.frameViewAngles[0][j] - cl.frameViewAngles[1][j]; - if (d > 180) - d -= 360; - else if (d < -180) - d += 360; - cl.viewangles[j] = cl.frameViewAngles[1][j] + frac * d; + if (d[j] > 180) { + d[j] -= 360; + } else if (d[j] < -180) { + d[j] += 360; + } } + VectorMultAdd (cl.frameViewAngles[1], frac, d, cl.viewstate.angles); } bobjrotate = anglemod (100 * cl.time); @@ -184,8 +185,8 @@ CL_RelinkEntities (void) // if the object wasn't included in the last packet, remove it entvalid = cl_msgtime[i] == cl.mtime[0]; if (entvalid && !new->modelindex) { - VectorCopy (new->origin, ent->origin); - VectorCopy (new->angles, ent->angles); + CL_TransformEntity (ent, new->scale / 16.0, new->angles, + new->origin); entvalid = 0; } if (!entvalid) { @@ -220,7 +221,6 @@ CL_RelinkEntities (void) cl.scores[i - 1].bottomcolor); } } - ent->scale = new->scale / 16.0; VectorCopy (ent_colormod[new->colormod], renderer->colormod); renderer->colormod[3] = ENTALPHA_DECODE (new->alpha); @@ -234,32 +234,30 @@ CL_RelinkEntities (void) // The entity was not updated in the last message so move to the // final spot animation->pose1 = animation->pose2 = -1; - VectorCopy (new->origin, ent->origin); - if (!(model_flags & EF_ROTATE)) - CL_TransformEntity (ent, new->angles); + CL_TransformEntity (ent, new->scale / 16.0, new->angles, + new->origin); if (i != cl.viewentity || chase_active->int_val) { if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); } r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } - VectorCopy (ent->origin, ent->old_origin); + ent->old_origin = new->origin; } else { + vec4f_t delta = new->origin - old->origin; f = frac; - VectorCopy (ent->origin, ent->old_origin); - VectorSubtract (new->origin, old->origin, delta); + ent->old_origin = Transform_GetWorldPosition (ent->transform); // If the delta is large, assume a teleport and don't lerp if (fabs (delta[0]) > 100 || fabs (delta[1] > 100) || fabs (delta[2]) > 100) { // assume a teleportation, not a motion - VectorCopy (new->origin, ent->origin); - if (!(model_flags & EF_ROTATE)) - CL_TransformEntity (ent, new->angles); + CL_TransformEntity (ent, new->scale / 16.0, new->angles, + new->origin); animation->pose1 = animation->pose2 = -1; } else { - vec3_t angles, d; // interpolate the origin and angles - VectorMultAdd (old->origin, f, delta, ent->origin); + vec3_t angles, d; + vec4f_t origin = old->origin + f * delta; if (!(model_flags & EF_ROTATE)) { VectorSubtract (new->angles, old->angles, d); for (j = 0; j < 3; j++) { @@ -269,12 +267,14 @@ CL_RelinkEntities (void) d[j] += 360; } VectorMultAdd (old->angles, f, d, angles); - CL_TransformEntity (ent, angles); } + CL_TransformEntity (ent, new->scale / 16.0, angles, origin); } if (i != cl.viewentity || chase_active->int_val) { if (ent->visibility.efrag) { - if (!VectorCompare (ent->origin, ent->old_origin)) { + vec4f_t org + = Transform_GetWorldPosition (ent->transform); + if (!VectorCompare (org, ent->old_origin)) {//FIXME r_funcs->R_RemoveEfrags (ent); r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } @@ -289,17 +289,20 @@ CL_RelinkEntities (void) vec3_t angles; VectorCopy (new->angles, angles); angles[YAW] = bobjrotate; - CL_TransformEntity (ent, angles); + CL_TransformEntity (ent, new->scale / 16.0, angles, new->origin); } CL_EntityEffects (i, ent, new, cl.time); - vec4f_t org = { VectorExpand (ent->origin), 1}; //FIXME + vec4f_t org = Transform_GetWorldPosition (ent->transform); CL_NewDlight (i, org, new->effects, new->glow_size, new->glow_color, cl.time); - if (VectorDistance_fast (old->origin, ent->origin) > (256 * 256)) - VectorCopy (ent->origin, old->origin); + if (VectorDistance_fast (old->origin, org) > (256 * 256)) { + old->origin = org; + } if (model_flags & ~EF_ROTATE) CL_ModelEffects (ent, i, new->glow_color, cl.time); cl_forcelink[i] = false; } + cl.viewstate.origin + = Transform_GetWorldPosition (cl_entities[cl.viewentity].transform); } diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index dd980e814..291f0ecac 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -438,35 +438,35 @@ CL_AdjustAngles (void) yawspeed *= host_frametime; if (!(in_strafe.state & 1)) { - cl.viewangles[YAW] -= yawspeed * CL_KeyState (&in_right); - cl.viewangles[YAW] += yawspeed * CL_KeyState (&in_left); - cl.viewangles[YAW] = anglemod (cl.viewangles[YAW]); + cl.viewstate.angles[YAW] -= yawspeed * CL_KeyState (&in_right); + cl.viewstate.angles[YAW] += yawspeed * CL_KeyState (&in_left); + cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); } if (in_klook.state & 1) { V_StopPitchDrift (); - cl.viewangles[PITCH] -= pitchspeed * CL_KeyState (&in_forward); - cl.viewangles[PITCH] += pitchspeed * CL_KeyState (&in_back); + cl.viewstate.angles[PITCH] -= pitchspeed * CL_KeyState (&in_forward); + cl.viewstate.angles[PITCH] += pitchspeed * CL_KeyState (&in_back); } up = CL_KeyState (&in_lookup); down = CL_KeyState (&in_lookdown); - cl.viewangles[PITCH] -= pitchspeed * up; - cl.viewangles[PITCH] += pitchspeed * down; + cl.viewstate.angles[PITCH] -= pitchspeed * up; + cl.viewstate.angles[PITCH] += pitchspeed * down; if (up || down) V_StopPitchDrift (); // FIXME: Need to clean up view angle limits - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; + if (cl.viewstate.angles[PITCH] > 80) + cl.viewstate.angles[PITCH] = 80; + if (cl.viewstate.angles[PITCH] < -70) + cl.viewstate.angles[PITCH] = -70; - if (cl.viewangles[ROLL] > 50) - cl.viewangles[ROLL] = 50; - if (cl.viewangles[ROLL] < -50) - cl.viewangles[ROLL] = -50; + if (cl.viewstate.angles[ROLL] > 50) + cl.viewstate.angles[ROLL] = 50; + if (cl.viewstate.angles[ROLL] < -50) + cl.viewstate.angles[ROLL] = -50; } /* @@ -516,12 +516,13 @@ CL_BaseMove (usercmd_t *cmd) IN_Move (); // adjust for chase camera angles + /*FIXME:chase figure out just what this does and get it working if (cl.chase && (chase_active->int_val == 2 || chase_active->int_val == 3)) { vec3_t forward, right, up, f, r; vec3_t dir = {0, 0, 0}; - dir[1] = r_data->refdef->viewangles[1] - cl.viewangles[1]; + dir[1] = r_data->refdef->viewangles[1] - cl.viewstate.angles[1]; AngleVectors (dir, forward, right, up); VectorScale (forward, cmd->forwardmove, f); VectorScale (right, cmd->sidemove, r); @@ -532,16 +533,18 @@ CL_BaseMove (usercmd_t *cmd) viewdelta.position[2] = f[0] + r[0]; viewdelta.position[0] = (f[1] + r[1]) * -1; } + */ cmd->forwardmove += viewdelta.position[2] * m_forward->value; cmd->sidemove += viewdelta.position[0] * m_side->value; cmd->upmove += viewdelta.position[1]; - cl.viewangles[PITCH] += viewdelta.angles[PITCH] * m_pitch->value; - cl.viewangles[YAW] += viewdelta.angles[YAW] * m_yaw->value; - cl.viewangles[ROLL] += viewdelta.angles[ROLL]; + cl.viewstate.angles[PITCH] += viewdelta.angles[PITCH] * m_pitch->value; + cl.viewstate.angles[YAW] += viewdelta.angles[YAW] * m_yaw->value; + cl.viewstate.angles[ROLL] += viewdelta.angles[ROLL]; if (freelook && !(in_strafe.state & 1)) { - cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80); + cl.viewstate.angles[PITCH] + = bound (-70, cl.viewstate.angles[PITCH], 80); } } @@ -564,7 +567,7 @@ CL_SendMove (usercmd_t *cmd) MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times - write_angles (&buf, cl.viewangles); + write_angles (&buf, cl.viewstate.angles); MSG_WriteShort (&buf, cmd->forwardmove); MSG_WriteShort (&buf, cmd->sidemove); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index e2c222713..e52eb5fea 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -34,6 +34,7 @@ #include "QF/console.h" #include "QF/cvar.h" #include "QF/draw.h" +#include "QF/entity.h" #include "QF/input.h" #include "QF/joystick.h" #include "QF/keys.h" @@ -52,7 +53,6 @@ #include "sbar.h" #include "client/temp_entities.h" -#include "client/view.h" #include "nq/include/chase.h" #include "nq/include/cl_skin.h" @@ -409,10 +409,11 @@ CL_PrintEntities_f (void) Sys_Printf ("EMPTY\n"); continue; } - Sys_Printf ("%s:%2i (%5.1f,%5.1f,%5.1f) [%5.1f %5.1f %5.1f]\n", + vec4f_t org = Transform_GetWorldPosition (ent->transform); + vec4f_t rot = Transform_GetWorldRotation (ent->transform); + Sys_Printf ("%s:%2i "VEC4F_FMT" "VEC4F_FMT"\n", ent->renderer.model->path, ent->animation.frame, - VectorExpand (ent->origin), - VectorExpand (ent->angles)); + VEC4_EXP (org), VEC4_EXP (rot)); } } @@ -426,12 +427,13 @@ CL_ReadFromServer (void) { int ret; TEntContext_t tentCtx = { - {VectorExpand (cl_entities[cl.viewentity].origin), 1}, + Transform_GetWorldPosition (cl_entities[cl.viewentity].transform), cl.worldmodel, cl.viewentity }; cl.oldtime = cl.time; cl.time += host_frametime; + cl.viewstate.frametime = host_frametime; do { ret = CL_GetMessage (); @@ -535,7 +537,7 @@ CL_SetState (cactive_t state) static void Force_CenterView_f (void) { - cl.viewangles[PITCH] = 0; + cl.viewstate.angles[PITCH] = 0; } void diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index ccf535e18..e74a65976 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -41,6 +41,7 @@ #include "QF/console.h" #include "QF/cvar.h" #include "QF/dstring.h" +#include "QF/entity.h" #include "QF/idparse.h" #include "QF/input.h" #include "QF/msg.h" @@ -661,17 +662,18 @@ CL_ParseClientdata (void) cl.idealpitch = 0; cl.frameVelocity[1] = cl.frameVelocity[0]; + vec3_t punchangle = { }; for (i = 0; i < 3; i++) { - if (bits & (SU_PUNCH1 << i)) - cl.punchangle[i] = ((signed char) MSG_ReadByte (net_message)); - else - cl.punchangle[i] = 0; + if (bits & (SU_PUNCH1 << i)) { + punchangle[i] = ((signed char) MSG_ReadByte (net_message)); + } if (bits & (SU_VELOCITY1 << i)) cl.frameVelocity[0][i] = ((signed char) MSG_ReadByte (net_message)) * 16; else cl.frameVelocity[0][i] = 0; } + AngleQuat (punchangle, &cl.viewstate.punchangle[0]);//FIXME //FIXME //if (!VectorCompare (v_punchangles[0], cl.punchangle[0])) { @@ -794,9 +796,9 @@ CL_ParseStatic (int version) ent->renderer.skinnum = baseline.skinnum; VectorCopy (ent_colormod[baseline.colormod], ent->renderer.colormod); ent->renderer.colormod[3] = ENTALPHA_DECODE (baseline.alpha); - ent->scale = baseline.scale / 16.0; - VectorCopy (baseline.origin, ent->origin); - CL_TransformEntity (ent, baseline.angles); + + CL_TransformEntity (ent, baseline.scale / 16.0, baseline.angles, + baseline.origin); r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } @@ -839,7 +841,7 @@ CL_ParseServerMessage (void) signon_t so; TEntContext_t tentCtx = { - {VectorExpand (cl_entities[cl.viewentity].origin), 1}, + Transform_GetWorldPosition (cl_entities[cl.viewentity].transform), cl.worldmodel, cl.viewentity }; @@ -948,7 +950,7 @@ CL_ParseServerMessage (void) case svc_setangle: { - vec_t *dest = cl.viewangles; + vec_t *dest = cl.viewstate.angles; MSG_ReadAngleV (net_message, dest); break; diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 509352a1c..78d231953 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -86,7 +86,9 @@ SCR_CShift (void) int contents = CONTENTS_EMPTY; if (cls.state == ca_active && cl.worldmodel) { - leaf = Mod_PointInLeaf (r_data->refdef->vieworg, cl.worldmodel); + //FIXME + leaf = Mod_PointInLeaf (&r_data->refdef->viewposition[0], + cl.worldmodel); contents = leaf->contents; } V_SetContentsColor (contents); diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index 1ccf06d98..f5ba3de8f 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -30,6 +30,7 @@ #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/entity.h" #include "QF/msg.h" #include "QF/screen.h" @@ -39,8 +40,6 @@ #include "compat.h" -#include "client/view.h" - #include "nq/include/chase.h" #include "nq/include/client.h" #include "nq/include/host.h" @@ -81,6 +80,10 @@ cvar_t *v_idlescale; float v_dmg_time, v_dmg_roll, v_dmg_pitch; +vec4f_t v_idle_yaw; +vec4f_t v_idle_roll; +vec4f_t v_idle_pitch; + cshift_t cshift_empty = { {130, 80, 50}, 0}; cshift_t cshift_water = { {130, 80, 50}, 128}; cshift_t cshift_slime = { {0, 25, 5}, 150}; @@ -113,7 +116,7 @@ V_CalcRoll (const vec3_t angles, vec4f_t velocity) static float V_CalcBob (void) { - vec4f_t velocity = cl.velocity; + vec4f_t velocity = cl.viewstate.velocity; float cycle; static double bobtime; static float bob; @@ -124,7 +127,7 @@ V_CalcBob (void) if (cl.onground == -1) return bob; // just use old value - bobtime += host_frametime; + bobtime += cl.viewstate.frametime; cycle = bobtime - (int) (bobtime / cl_bobcycle->value) * cl_bobcycle->value; cycle /= cl_bobcycle->value; @@ -183,9 +186,9 @@ static void V_DriftPitch (void) { float delta, move; - usercmd_t *cmd = &cl.cmd; + float forwardmove = cl.viewstate.movecmd[0]; - if (noclip_anglehack || cl.onground == -1 || cls.demoplayback) { + if (noclip_anglehack || cl.viewstate.onground == -1 || cls.demoplayback) { cl.driftmove = 0; cl.pitchvel = 0; return; @@ -193,10 +196,10 @@ V_DriftPitch (void) // don't count small mouse motion if (cl.nodrift) { - if (fabs (cmd->forwardmove) < cl_forwardspeed->value) + if (fabs (forwardmove) < cl_forwardspeed->value) cl.driftmove = 0; else - cl.driftmove += host_frametime; + cl.driftmove += cl.viewstate.frametime; if (cl.driftmove > v_centermove->value) { V_StartPitchDrift (); @@ -204,28 +207,28 @@ V_DriftPitch (void) return; } - delta = cl.idealpitch - cl.viewangles[PITCH]; + delta = cl.idealpitch - cl.viewstate.angles[PITCH]; if (!delta) { cl.pitchvel = 0; return; } - move = host_frametime * cl.pitchvel; - cl.pitchvel += host_frametime * v_centerspeed->value; + move = cl.viewstate.frametime * cl.pitchvel; + cl.pitchvel += cl.viewstate.frametime * v_centerspeed->value; if (delta > 0) { if (move > delta) { cl.pitchvel = 0; move = delta; } - cl.viewangles[PITCH] += move; + cl.viewstate.angles[PITCH] += move; } else if (delta < 0) { if (move > -delta) { cl.pitchvel = 0; move = -delta; } - cl.viewangles[PITCH] -= move; + cl.viewstate.angles[PITCH] -= move; } } @@ -234,11 +237,10 @@ V_DriftPitch (void) void V_ParseDamage (void) { - entity_t *ent = &cl_entities[cl.viewentity]; float count, side; int armor, blood; - vec_t *origin = ent->origin; - vec_t *angles = ent->angles; + vec4f_t origin = cl.viewstate.origin; + vec_t *angles = cl.viewstate.angles; vec3_t from, forward, right, up; armor = MSG_ReadByte (net_message); @@ -482,74 +484,41 @@ V_PrepBlend (void) /* VIEW RENDERING */ -static float -angledelta (float a) -{ - a = anglemod (a); - if (a > 180) - a -= 360; - return a; -} - static void CalcGunAngle (void) { - float yaw, pitch, move; - static float oldpitch = 0, oldyaw = 0; - - yaw = r_data->refdef->viewangles[YAW]; - pitch = -r_data->refdef->viewangles[PITCH]; - - yaw = angledelta (yaw - r_data->refdef->viewangles[YAW]) * 0.4; - yaw = bound (-10, yaw, 10); - pitch = angledelta (-pitch - r_data->refdef->viewangles[PITCH]) * 0.4; - pitch = bound (-10, pitch, 10); - - move = host_frametime * 20; - if (yaw > oldyaw) { - if (oldyaw + move < yaw) - yaw = oldyaw + move; - } else { - if (oldyaw - move > yaw) - yaw = oldyaw - move; - } - - if (pitch > oldpitch) { - if (oldpitch + move < pitch) - pitch = oldpitch + move; - } else { - if (oldpitch - move > pitch) - pitch = oldpitch - move; - } - - oldyaw = yaw; - oldpitch = pitch; - - cl.viewent.angles[YAW] = r_data->refdef->viewangles[YAW] + yaw; - cl.viewent.angles[PITCH] = -(r_data->refdef->viewangles[PITCH] + pitch); + vec4f_t rotation = r_data->refdef->viewrotation; + //FIXME make child of camera + Transform_SetWorldRotation (cl.viewent.transform, rotation); } static void V_BoundOffsets (void) { - entity_t *ent = &cl_entities[cl.viewentity]; - vec_t *origin = ent->origin; + vec4f_t offset = r_data->refdef->viewposition + - cl.viewstate.origin; // absolutely bound refresh reletive to entity clipping hull // so the view can never be inside a solid wall - if (r_data->refdef->vieworg[0] < origin[0] - 14) - r_data->refdef->vieworg[0] = origin[0] - 14; - else if (r_data->refdef->vieworg[0] > origin[0] + 14) - r_data->refdef->vieworg[0] = origin[0] + 14; - if (r_data->refdef->vieworg[1] < origin[1] - 14) - r_data->refdef->vieworg[1] = origin[1] - 14; - else if (r_data->refdef->vieworg[1] > origin[1] + 14) - r_data->refdef->vieworg[1] = origin[1] + 14; - if (r_data->refdef->vieworg[2] < origin[2] - 22) - r_data->refdef->vieworg[2] = origin[2] - 22; - else if (r_data->refdef->vieworg[2] > origin[2] + 30) - r_data->refdef->vieworg[2] = origin[2] + 30; + offset[0] = bound (-14, offset[0], 14); + offset[1] = bound (-14, offset[1], 14); + offset[2] = bound (-22, offset[2], 30); + r_data->refdef->viewposition = cl.viewstate.origin + offset; +} + +static vec4f_t +idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level) +{ + vec4f_t identity = { 0, 0, 0, 1 }; + if (!level || !cycle) { + return identity; + } + float scale = sin (cl.time * cycle->value); + float ang = scale * level->value * v_idlescale->value; + float c = cos (ang); + float s = sin (ang); + return axis * s + identity * c; } /* @@ -560,19 +529,21 @@ V_BoundOffsets (void) static void V_AddIdle (void) { - r_data->refdef->viewangles[ROLL] += v_idlescale->value * - sin (cl.time * v_iroll_cycle->value) * v_iroll_level->value; - r_data->refdef->viewangles[PITCH] += v_idlescale->value * - sin (cl.time * v_ipitch_cycle->value) * v_ipitch_level->value; - r_data->refdef->viewangles[YAW] += v_idlescale->value * - sin (cl.time * v_iyaw_cycle->value) * v_iyaw_level->value; + vec4f_t roll = idle_quat ((vec4f_t) { 1, 0, 0, 0}, + v_iroll_cycle, v_iroll_level); + vec4f_t pitch = idle_quat ((vec4f_t) { 0, 1, 0, 0}, + v_ipitch_cycle, v_ipitch_level); + vec4f_t yaw = idle_quat ((vec4f_t) { 0, 0, 1, 0}, + v_iyaw_cycle, v_iyaw_level); + vec4f_t rot = normalf (qmulf (yaw, qmulf (pitch, roll))); - cl.viewent.angles[ROLL] -= v_idlescale->value * - sin (cl.time * v_iroll_cycle->value) * v_iroll_level->value; - cl.viewent.angles[PITCH] -= v_idlescale->value * - sin (cl.time * v_ipitch_cycle->value) * v_ipitch_level->value; - cl.viewent.angles[YAW] -= v_idlescale->value * - sin (cl.time * v_iyaw_cycle->value) * v_iyaw_level->value; + // rotate the view + r_data->refdef->viewrotation = qmulf (rot, r_data->refdef->viewrotation); + + // counter-rotate the weapon + rot = qmulf (qconjf (rot), + Transform_GetWorldRotation (cl.viewent.transform)); + Transform_SetWorldRotation (cl.viewent.transform, rot); } /* @@ -583,40 +554,38 @@ V_AddIdle (void) static void V_CalcViewRoll (void) { - float side; - vec_t *angles = cl_entities[cl.viewentity].angles; - vec4f_t velocity = cl.velocity; + vec_t *angles = cl.viewstate.angles; + vec4f_t velocity = cl.viewstate.velocity; + vec3_t ang = { }; - side = V_CalcRoll (angles, velocity); - r_data->refdef->viewangles[ROLL] += side; + ang[ROLL] = V_CalcRoll (angles, velocity); if (v_dmg_time > 0) { - r_data->refdef->viewangles[ROLL] += - v_dmg_time / v_kicktime->value * v_dmg_roll; - r_data->refdef->viewangles[PITCH] += - v_dmg_time / v_kicktime->value * v_dmg_pitch; - v_dmg_time -= host_frametime; + ang[ROLL] += v_dmg_time / v_kicktime->value * v_dmg_roll; + ang[PITCH] += v_dmg_time / v_kicktime->value * v_dmg_pitch; + v_dmg_time -= cl.viewstate.frametime; } - if (cl.stats[STAT_HEALTH] <= 0) - r_data->refdef->viewangles[ROLL] = 80; // dead view angle + if (cl.viewstate.flags & VF_DEAD) { // VF_GIB will also set VF_DEAD + ang[ROLL] = 80; // dead view angle + } + + vec4f_t rot; + AngleQuat (ang, &rot[0]);//FIXME + r_data->refdef->viewrotation = qmulf (r_data->refdef->viewrotation, rot); } static void V_CalcIntermissionRefdef (void) { - // ent is the player model (visible when out of body) - entity_t *ent = &cl_entities[cl.viewentity]; entity_t *view; float old; - vec_t *origin = ent->origin; - vec_t *angles = ent->angles; // view is the weapon model (visible only from inside body) view = &cl.viewent; - VectorCopy (origin, r_data->refdef->vieworg); - VectorCopy (angles, r_data->refdef->viewangles); + r_data->refdef->viewposition = cl.viewstate.origin; + AngleQuat (cl.viewstate.angles, &r_data->refdef->viewrotation[0]);//FIXME view->renderer.model = NULL; // always idle in intermission @@ -629,109 +598,98 @@ V_CalcIntermissionRefdef (void) static void V_CalcRefdef (void) { - // ent is the player model (visible when out of body) - entity_t *ent = &cl_entities[cl.viewentity]; // view is the weapon model (visible only from inside body) entity_t *view = &cl.viewent; float bob; static float oldz = 0; - int i; - vec3_t forward, right, up; - vec_t *origin = ent->origin; - vec_t *viewangles = cl.viewangles; + vec4f_t forward = {}, right = {}, up = {}; + vec4f_t origin = cl.viewstate.origin; + vec_t *viewangles = cl.viewstate.angles; V_DriftPitch (); bob = V_CalcBob (); // refresh position - VectorCopy (origin, r_data->refdef->vieworg); - r_data->refdef->vieworg[2] += cl.viewheight + bob; + r_data->refdef->viewposition = origin; + r_data->refdef->viewposition[2] += cl.viewheight + bob; // never let it sit exactly on a node line, because a water plane can // disappear when viewed with the eye exactly on it. // server protocol specifies to only 1/8 pixel, so add 1/16 in each axis - r_data->refdef->vieworg[0] += 1.0 / 16; - r_data->refdef->vieworg[1] += 1.0 / 16; - r_data->refdef->vieworg[2] += 1.0 / 16; + r_data->refdef->viewposition += (vec4f_t) { 1.0/16, 1.0/16, 1.0/16, 0}; - VectorCopy (viewangles, r_data->refdef->viewangles); + AngleQuat (cl.viewstate.angles, &r_data->refdef->viewrotation[0]);//FIXME V_CalcViewRoll (); V_AddIdle (); // offsets - AngleVectors (viewangles, forward, right, up); + //FIXME semi-duplicates AngleQuat (also, vec3_t vs vec4f_t) + AngleVectors (viewangles, &forward[0], &right[0], &up[0]); // don't allow cheats in multiplayer // FIXME check for dead if (cl.maxclients == 1) { - for (i = 0; i < 3; i++) { - r_data->refdef->vieworg[i] += scr_ofsx->value * forward[i] + - scr_ofsy->value * right[i] + - scr_ofsz->value * up[i]; - } + r_data->refdef->viewposition += scr_ofsx->value * forward + + scr_ofsy->value * right + + scr_ofsz->value * up; } V_BoundOffsets (); // set up gun position - VectorCopy (viewangles, view->angles); - CalcGunAngle (); - VectorCopy (origin, view->origin); - view->origin[2] += cl.viewheight; - - for (i = 0; i < 3; i++) { - view->origin[i] += forward[i] * bob * 0.4; -// view->origin[i] += right[i] * bob * 0.4; -// view->origin[i] += up[i] * bob * 0.8; - } - view->origin[2] += bob; + origin += (vec4f_t) { 0, 0, cl.viewheight, 0 }; + origin += forward * bob * 0.4f + (vec4f_t) { 0, 0, bob, 0 }; // fudge position around to keep amount of weapon visible // roughly equal with different FOV - if (hud_sbar->int_val == 0 && r_data->scr_viewsize->int_val >= 100) + if (hud_sbar->int_val == 0 && r_data->scr_viewsize->int_val >= 100) { ; - else if (r_data->scr_viewsize->int_val == 110) - view->origin[2] += 1; - else if (r_data->scr_viewsize->int_val == 100) - view->origin[2] += 2; - else if (r_data->scr_viewsize->int_val == 90) - view->origin[2] += 1; - else if (r_data->scr_viewsize->int_val == 80) - view->origin[2] += 0.5; + } else if (r_data->scr_viewsize->int_val == 110) { + origin += (vec4f_t) { 0, 0, 1, 0}; + } else if (r_data->scr_viewsize->int_val == 100) { + origin += (vec4f_t) { 0, 0, 2, 0}; + } else if (r_data->scr_viewsize->int_val == 90) { + origin += (vec4f_t) { 0, 0, 1, 0}; + } else if (r_data->scr_viewsize->int_val == 80) { + origin += (vec4f_t) { 0, 0, 0.5, 0}; + } view->renderer.model = cl.model_precache[cl.stats[STAT_WEAPON]]; view->animation.frame = cl.stats[STAT_WEAPONFRAME]; view->renderer.skin = 0; // set up the refresh position - VectorAdd (r_data->refdef->viewangles, cl.punchangle, - r_data->refdef->viewangles); + r_data->refdef->viewrotation = qmulf (cl.viewstate.punchangle, + r_data->refdef->viewrotation); // smooth out stair step ups if ((cl.onground != -1) && (origin[2] - oldz > 0)) { float steptime; - steptime = cl.time - cl.oldtime; - if (steptime < 0) - steptime = 0; + steptime = cl.viewstate.frametime; oldz += steptime * 80; if (oldz > origin[2]) oldz = origin[2]; if (origin[2] - oldz > 12) oldz = origin[2] - 12; - r_data->refdef->vieworg[2] += oldz - origin[2]; - view->origin[2] += oldz - origin[2]; - } else + r_data->refdef->viewposition[2] += oldz - origin[2]; + origin[2] += oldz - origin[2]; + } else { oldz = origin[2]; + } + { + // FIXME sort out the alias model specific negation + vec3_t ang = {-viewangles[0], viewangles[1], viewangles[2]}; + CL_TransformEntity (view, 1, ang, origin); + } - if (cl.chase && chase_active->int_val) + if (cl.chase && chase_active->int_val) { Chase_Update (); - - CL_TransformEntity (view, view->angles); + } } /* @@ -743,8 +701,11 @@ V_CalcRefdef (void) void V_RenderView (void) { - if (cls.state != ca_active) + if (cls.state != ca_active) { + r_data->refdef->viewposition = (vec4f_t) { 0, 0, 0, 1 }; + r_data->refdef->viewrotation = (vec4f_t) { 0, 0, 0, 1 }; return; + } if (cl.intermission) { // intermission / finale rendering V_CalcIntermissionRefdef (); diff --git a/qw/include/client.h b/qw/include/client.h index 5389579c4..8c0369fba 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -37,6 +37,7 @@ #include "QF/plugin/vid_render.h" #include "client/entities.h" +#include "client/view.h" #include "netchan.h" #include "qw/bothdefs.h" @@ -222,12 +223,7 @@ typedef struct { // the client simulates or interpolates movement to get these values double time; // this is the time value that the client // is rendering at. always <= realtime - vec4f_t simorg; - vec4f_t simvel; - vec3_t simangles; - - vec3_t punchangle; // temporary view kick from weapon firing - + viewstate_t viewstate; // pitch drifting vars float idealpitch; float pitchvel; @@ -342,7 +338,9 @@ extern struct cvar_s *cl_fb_players; extern client_state_t cl; -extern entityset_t cl_static_entities; +typedef struct entitystateset_s DARRAY_TYPE (struct entity_state_s) + entitystateset_t; +extern entitystateset_t cl_static_entities; extern entity_t cl_entities[512]; extern byte cl_entity_valid[2][512]; diff --git a/qw/source/cl_chase.c b/qw/source/cl_chase.c index 8a3d6419d..68c9e207a 100644 --- a/qw/source/cl_chase.c +++ b/qw/source/cl_chase.c @@ -41,16 +41,19 @@ #include "QF/mathlib.h" #include "QF/plugin/vid_render.h" +#include "QF/simd/vec4f.h" #include "qw/include/chase.h" #include "qw/include/cl_input.h" #include "qw/include/client.h" #include "world.h" -vec3_t camera_origin = {0,0,0}; -vec3_t camera_angles = {0,0,0}; -vec3_t player_origin = {0,0,0}; -vec3_t player_angles = {0,0,0}; + +vec4f_t camera_origin = {0,0,0,1}; +vec4f_t player_origin = {0,0,0,1}; +vec4f_t player_angles = {0,0,0,1}; + +vec3_t camera_angles = {0,0,0}; vec3_t chase_angles; vec3_t chase_dest; @@ -94,19 +97,17 @@ TraceLine (vec3_t start, vec3_t end, vec3_t impact) void Chase_Update (void) { - float pitch, yaw, fwd; - int i; - usercmd_t cmd; // movement direction - vec3_t forward, up, right, stop, dir; + float pitch, yaw, fwd; + usercmd_t cmd; // movement direction + vec4f_t forward = {}, up = {}, right = {}, stop = {}, dir = {}; // lazy camera, look toward player entity if (chase_active->int_val == 2 || chase_active->int_val == 3) { // control camera angles with key/mouse/joy-look - - camera_angles[PITCH] += cl.viewangles[PITCH] - player_angles[PITCH]; - camera_angles[YAW] += cl.viewangles[YAW] - player_angles[YAW]; - camera_angles[ROLL] += cl.viewangles[ROLL] - player_angles[ROLL]; + vec3_t d; + VectorSubtract (cl.viewstate.angles, player_angles, d); + VectorAdd (camera_angles, d, camera_angles); if (chase_active->int_val == 2) { if (camera_angles[PITCH] < -60) @@ -118,48 +119,48 @@ Chase_Update (void) // move camera, it's not enough to just change the angles because // the angles are automatically changed to look toward the player - if (chase_active->int_val == 3) - VectorCopy (r_data->refdef->vieworg, player_origin); + if (chase_active->int_val == 3) { + player_origin = r_data->refdef->viewposition; + } - AngleVectors (camera_angles, forward, right, up); - VectorScale (forward, chase_back->value, forward); - VectorSubtract (player_origin, forward, camera_origin); + AngleVectors (camera_angles, &forward[0], &right[0], &up[0]); + camera_origin = player_origin - chase_back->value * forward; if (chase_active->int_val == 2) { - VectorCopy (r_data->refdef->vieworg, player_origin); + player_origin = r_data->refdef->viewposition; // don't let camera get too low - if (camera_origin[2] < player_origin[2] + chase_up->value) + if (camera_origin[2] < player_origin[2] + chase_up->value) { camera_origin[2] = player_origin[2] + chase_up->value; + } } // don't let camera get too far from player - VectorSubtract (camera_origin, player_origin, dir); - VectorCopy (dir, forward); - VectorNormalize (forward); + dir = camera_origin - player_origin; + forward = normalf (dir); - if (VectorLength (dir) > chase_back->value) { - VectorScale (forward, chase_back->value, dir); - VectorAdd (player_origin, dir, camera_origin); + if (magnitudef (dir)[0] > chase_back->value) { + camera_origin = player_origin + forward * chase_back->value; } // check for walls between player and camera - VectorScale (forward, 8, forward); - VectorAdd (camera_origin, forward, camera_origin); - TraceLine (player_origin, camera_origin, stop); - if (VectorLength (stop) != 0) - VectorSubtract (stop, forward, camera_origin); + camera_origin += 8 * forward; + //FIXME + TraceLine (&player_origin[0], &camera_origin[0], &stop[0]); + stop[3] = 1; + if (magnitude3f (stop)[0] != 0) { + camera_origin = stop - forward; + } - VectorSubtract (camera_origin, r_data->refdef->vieworg, dir); - VectorCopy (dir, forward); - VectorNormalize (forward); + dir = camera_origin - r_data->refdef->viewposition; + forward = normalf (dir); if (chase_active->int_val == 2) { if (dir[1] == 0 && dir[0] == 0) { // look straight up or down -// camera_angles[YAW] = r_data->refdef->viewangles[YAW]; +// camera_angles[YAW] = r_data->refdef->viewstate.angles[YAW]; if (dir[2] > 0) camera_angles[PITCH] = 90; else @@ -182,13 +183,13 @@ Chase_Update (void) } } - VectorCopy (camera_angles, r_data->refdef->viewangles);// rotate camera - VectorCopy (camera_origin, r_data->refdef->vieworg); // move camera + AngleQuat (camera_angles, &r_data->refdef->viewrotation[0]);//FIXME rotate camera + r_data->refdef->viewposition = camera_origin; // move camera // get basic movement from keyboard memset (&cmd, 0, sizeof (cmd)); -// VectorCopy (cl.viewangles, cmd.angles); +// VectorCopy (cl.viewstate.angles, cmd.angles); if (in_strafe.state & 1) { cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_right); @@ -208,54 +209,54 @@ Chase_Update (void) } // mouse and joystick controllers add to movement - VectorSet (0, cl.viewangles[1] - camera_angles[1], 0, dir); - AngleVectors (dir, forward, right, up); - VectorScale (forward, viewdelta.position[2] * m_forward->value, - forward); - VectorScale (right, viewdelta.position[0] * m_side->value, right); - VectorAdd (forward, right, dir); + VectorSet (0, cl.viewstate.angles[1] - camera_angles[1], 0, dir); + AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME + forward *= viewdelta.position[2] * m_forward->value; + right *= viewdelta.position[0] * m_side->value; + dir = forward + right; cmd.forwardmove += dir[0]; cmd.sidemove -= dir[1]; VectorSet (0, camera_angles[1], 0, dir); - AngleVectors (dir, forward, right, up); + AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME VectorScale (forward, cmd.forwardmove, forward); VectorScale (right, cmd.sidemove, right); VectorAdd (forward, right, dir); if (dir[1] || dir[0]) { - cl.viewangles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (cl.viewangles[YAW] < 0) cl.viewangles[YAW] += 360; -// if (cl.viewangles[YAW] < 180) -// cl.viewangles[YAW] += 180; -// else -// cl.viewangles[YAW] -= 180; + cl.viewstate.angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); + if (cl.viewstate.angles[YAW] < 0) { + cl.viewstate.angles[YAW] += 360; + } } - cl.viewangles[PITCH] = 0; + cl.viewstate.angles[PITCH] = 0; // remember the new angle to calculate the difference next frame - VectorCopy (cl.viewangles, player_angles); + VectorCopy (cl.viewstate.angles, player_angles); return; } // regular camera, faces same direction as player - AngleVectors (cl.viewangles, forward, right, up); + //FIXME + AngleVectors (cl.viewstate.angles, &forward[0], &right[0], &up[0]); // calc exact destination - for (i = 0; i < 3; i++) - camera_origin[i] = r_data->refdef->vieworg[i] - - forward[i] * chase_back->value - right[i] * chase_right->value; + camera_origin = r_data->refdef->viewposition + - forward * chase_back->value - right * chase_right->value; + // chase_up is world up camera_origin[2] += chase_up->value; // check for walls between player and camera - TraceLine (r_data->refdef->vieworg, camera_origin, stop); - if (VectorLength (stop) != 0) - for (i = 0; i < 3; i++) - camera_origin[i] = stop[i] + forward[i] * 8; + //FIXME + TraceLine (&r_data->refdef->viewposition[0], &camera_origin[0], &stop[0]); + stop[3] = 1; + if (magnitude3f (stop)[0] != 0) { + camera_origin = stop + forward * 8; + } - VectorCopy (camera_origin, r_data->refdef->vieworg); + r_data->refdef->viewposition = camera_origin; } diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 0694b5f25..7503f5c2a 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -652,9 +652,8 @@ demo_start_recording (int track) { byte buf_data[MAX_MSGLEN + 10]; // + 10 for header char *s; - int n, i, j; + int n, i; int seq = 1; - entity_t *ent; entity_state_t *es, blankes; player_info_t *player; sizebuf_t buf; @@ -757,23 +756,16 @@ demo_start_recording (int track) // spawnstatic for (size_t staticIndex = 0; staticIndex < cl_static_entities.size; staticIndex++) { - ent = cl_static_entities.a[staticIndex]; + entity_state_t *es = &cl_static_entities.a[staticIndex]; + MSG_WriteByte (&buf, svc_spawnstatic); - for (j = 1; j < cl.nummodels; j++) { - if (ent->renderer.model == cl.model_precache[j]) { - break; - } - } - if (j == cl.nummodels) - MSG_WriteByte (&buf, 0); - else - MSG_WriteByte (&buf, j); + MSG_WriteByte (&buf, es->modelindex); - MSG_WriteByte (&buf, ent->animation.frame); + MSG_WriteByte (&buf, es->frame); MSG_WriteByte (&buf, 0); - MSG_WriteByte (&buf, ent->renderer.skinnum); - MSG_WriteCoordAngleV (&buf, ent->origin, ent->angles); + MSG_WriteByte (&buf, es->skinnum); + MSG_WriteCoordAngleV (&buf, &es->origin[0], &es->angles[0]); if (buf.cursize > MAX_MSGLEN / 2) { CL_WriteRecordDemoMessage (&buf, seq++); diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 60c8cf2c4..7100d2726 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -130,6 +130,8 @@ CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits) if (bits & U_ANGLE3) to->angles[2] = MSG_ReadAngle (net_message); + to->origin[3] = 1; + if (bits & U_SOLID) { // FIXME } @@ -428,6 +430,7 @@ CL_ParsePlayerinfo (void) state->messagenum = cl.parsecount; MSG_ReadCoordV (net_message, &state->pls.es.origin[0]);//FIXME + state->pls.es.origin[3] = 1; state->pls.es.frame = MSG_ReadByte (net_message); @@ -486,7 +489,7 @@ CL_ParsePlayerinfo (void) } if (bits & PF_SCALE) { val = MSG_ReadByte (net_message); - ent->scale = val / 16.0; + state->pls.es.scale = val; } if (bits & PF_EFFECTS2) { state->pls.es.effects |= MSG_ReadByte (net_message) << 8; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index b70b143cc..8ee9440b4 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -132,7 +132,6 @@ CL_LinkPacketEntities (void) entity_state_t *new, *old; renderer_t *renderer; animation_t *animation; - vec3_t delta; frac = 1; for (i = 0; i < 512; i++) { @@ -195,7 +194,6 @@ CL_LinkPacketEntities (void) 0); } } - ent->scale = new->scale / 16.0; VectorCopy (ent_colormod[new->colormod], renderer->colormod); renderer->colormod[3] = new->alpha / 255.0; @@ -209,35 +207,31 @@ CL_LinkPacketEntities (void) } } + ent->old_origin = Transform_GetWorldPosition (ent->transform); if (forcelink) { animation->pose1 = animation->pose2 = -1; - VectorCopy (new->origin, ent->origin); - if (!(renderer->model->flags & EF_ROTATE)) - CL_TransformEntity (ent, new->angles); + CL_TransformEntity (ent, new->scale / 16, new->angles, + new->origin); if (i != cl.viewentity || chase_active->int_val) { if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); } r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } - VectorCopy (ent->origin, ent->old_origin); } else { + vec4f_t delta = new->origin - old->origin; f = frac; - VectorCopy (ent->origin, ent->old_origin); - VectorSubtract (new->origin, old->origin, delta); // If the delta is large, assume a teleport and don't lerp if (fabs (delta[0]) > 100 || fabs (delta[1] > 100) || fabs (delta[2]) > 100) { // assume a teleportation, not a motion - VectorCopy (new->origin, ent->origin); - if (!(renderer->model->flags & EF_ROTATE)) { - CL_TransformEntity (ent, new->angles); - } + CL_TransformEntity (ent, new->scale / 16, new->angles, + new->origin); animation->pose1 = animation->pose2 = -1; } else { vec3_t angles, d; + vec4f_t origin = old->origin + f * delta; // interpolate the origin and angles - VectorMultAdd (old->origin, f, delta, ent->origin); if (!(renderer->model->flags & EF_ROTATE)) { VectorSubtract (new->angles, old->angles, d); for (j = 0; j < 3; j++) { @@ -247,12 +241,14 @@ CL_LinkPacketEntities (void) d[j] += 360; } VectorMultAdd (old->angles, f, d, angles); - CL_TransformEntity (ent, angles); } + CL_TransformEntity (ent, new->scale / 16.0, angles, origin); } if (i != cl.viewentity || chase_active->int_val) { if (ent->visibility.efrag) { - if (!VectorCompare (ent->origin, ent->old_origin)) { + vec4f_t org + = Transform_GetWorldPosition (ent->transform); + if (!VectorCompare (org, ent->old_origin)) {//FIXME r_funcs->R_RemoveEfrags (ent); r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } @@ -271,12 +267,13 @@ CL_LinkPacketEntities (void) angles[PITCH] = 0; angles[YAW] = anglemod (100 * cl.time); angles[ROLL] = 0; - CL_TransformEntity (ent, angles); + CL_TransformEntity (ent, new->scale / 16.0, angles, new->origin); } //CL_EntityEffects (i, ent, new); //CL_NewDlight (i, ent->origin, new->effects, 0, 0, cl.time); - if (VectorDistance_fast (old->origin, ent->origin) > (256 * 256)) - VectorCopy (ent->origin, old->origin); + vec4f_t org = Transform_GetWorldPosition (ent->transform); + if (VectorDistance_fast (old->origin, org) > (256 * 256)) + old->origin = org; if (renderer->model->flags & ~EF_ROTATE) { CL_ModelEffects (ent, -new->number, new->glow_color, cl.time); } @@ -378,7 +375,7 @@ CL_LinkPlayers (void) // spawn light flashes, even ones coming from invisible objects if (j == cl.playernum) { - org = cl.simorg; + org = cl.viewstate.origin; r_data->player_entity = &cl_player_ents[j]; clientplayer = true; } else { @@ -413,15 +410,16 @@ CL_LinkPlayers (void) // predict only half the move to minimize overruns msec = 500 * (playertime - state->state_time); if (msec <= 0 || (!cl_predict_players->int_val) || cls.demoplayback2) { - VectorCopy (state->pls.es.origin, ent->origin); + Sys_Printf("a\n"); + exact.pls.es.origin = state->pls.es.origin; } else { // predict players movement state->pls.cmd.msec = msec = min (msec, 255); oldphysent = pmove.numphysent; CL_SetSolidPlayers (j); + exact.pls.es.origin[3] = 1;//FIXME should be done by prediction CL_PredictUsercmd (state, &exact, &state->pls.cmd, clientplayer); pmove.numphysent = oldphysent; - VectorCopy (exact.pls.es.origin, ent->origin); } // angles @@ -439,7 +437,8 @@ CL_LinkPlayers (void) ent->animation.frame = state->pls.es.frame; ent->renderer.skinnum = state->pls.es.skinnum; - CL_TransformEntity (ent, ang); + //FIXME scale + CL_TransformEntity (ent, 1, ang, exact.pls.es.origin); ent->renderer.min_light = 0; ent->renderer.fullbright = 0; @@ -484,14 +483,14 @@ CL_EmitEntities (void) return; TEntContext_t tentCtx = { - {VectorExpand (cl.simorg), 1}, cl.worldmodel, cl.viewentity + cl.viewstate.origin, cl.worldmodel, cl.viewentity }; CL_LinkPlayers (); CL_LinkPacketEntities (); CL_UpdateTEnts (cl.time, &tentCtx); if (cl_draw_locs->int_val) { - locs_draw (cl.simorg); + locs_draw (cl.viewstate.origin); } } diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 5a2fe2b6e..9b9763d46 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -530,6 +530,7 @@ CL_BaseMove (usercmd_t *cmd) IN_Move (); // adjust for chase camera angles + /*FIXME:chase figure out just what this does and get it working if (cl.chase && (chase_active->int_val == 2 || chase_active->int_val == 3)) { vec3_t forward, right, up, f, r; @@ -546,6 +547,7 @@ CL_BaseMove (usercmd_t *cmd) viewdelta.position[2] = f[0] + r[0]; viewdelta.position[0] = (f[1] + r[1]) * -1; } + */ cmd->forwardmove += viewdelta.position[2] * m_forward->value; cmd->sidemove += viewdelta.position[0] * m_side->value; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index be73db0e7..cef24d6bd 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1605,6 +1605,8 @@ Host_Frame (float time) oldrealtime = realtime; host_frametime = min (host_frametime, 0.2); + cl.viewstate.frametime = host_frametime; + con_frametime = con_realtime - oldcon_realtime; oldcon_realtime = con_realtime; diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index b75355fa1..b53c2beb9 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -170,7 +170,7 @@ int packet_latency[NET_TIMINGS]; extern cvar_t *hud_scoreboard_uid; -entityset_t cl_static_entities = DARRAY_STATIC_INIT (32); +entitystateset_t cl_static_entities = DARRAY_STATIC_INIT (32); static void CL_LoadSky (void) @@ -973,15 +973,14 @@ CL_ParseStatic (void) ent = r_funcs->R_AllocEntity (); CL_Init_Entity (ent); - DARRAY_APPEND (&cl_static_entities, ent); + DARRAY_APPEND (&cl_static_entities, es); // copy it to the current state ent->renderer.model = cl.model_precache[es.modelindex]; ent->animation.frame = es.frame; ent->renderer.skinnum = es.skinnum; - VectorCopy (es.origin, ent->origin); - CL_TransformEntity (ent, es.angles); + CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin); r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); } @@ -1296,7 +1295,7 @@ CL_ParseServerMessage (void) const char *str; static dstring_t *stuffbuf; TEntContext_t tentCtx = { - {VectorExpand (cl.simorg), 1}, cl.worldmodel, cl.viewentity + cl.viewstate.origin, cl.worldmodel, cl.viewentity }; received_framecount = host_framecount; @@ -1542,17 +1541,17 @@ CL_ParseServerMessage (void) cl.completed_time = realtime; r_data->vid->recalc_refdef = true; // go to full screen Sys_MaskPrintf (SYS_DEV, "intermission simorg: "); - MSG_ReadCoordV (net_message, &cl.simorg[0]);//FIXME - cl.simorg[3] = 1; - for (i = 0; i < 3; i++) - Sys_MaskPrintf (SYS_DEV, "%f ", cl.simorg[i]); + MSG_ReadCoordV (net_message, &cl.viewstate.origin[0]);//FIXME + cl.viewstate.origin[3] = 1; + Sys_MaskPrintf (SYS_DEV, VEC4F_FMT, + VEC4_EXP (cl.viewstate.origin)); Sys_MaskPrintf (SYS_DEV, "\nintermission simangles: "); - MSG_ReadAngleV (net_message, cl.simangles); - cl.simangles[ROLL] = 0; // FIXME @@@ - for (i = 0; i < 3; i++) - Sys_MaskPrintf (SYS_DEV, "%f ", cl.simangles[i]); + MSG_ReadAngleV (net_message, cl.viewstate.angles); + cl.viewstate.angles[ROLL] = 0; // FIXME @@@ + Sys_MaskPrintf (SYS_DEV, "%f %f %f", + VectorExpand (cl.viewstate.angles)); Sys_MaskPrintf (SYS_DEV, "\n"); - VectorZero (cl.simvel); + cl.viewstate.velocity = (vec4f_t) { }; // automatic fraglogging (by elmex) // XXX: Should this _really_ called here? @@ -1585,11 +1584,17 @@ CL_ParseServerMessage (void) // svc_cutscene (same value as svc_smallkick) case svc_smallkick: - cl.punchangle[PITCH] = -2; + cl.viewstate.punchangle = (vec4f_t) { + // -2 degrees pitch + 0, -0.0174524064, 0, 0.999847695 + }; break; case svc_bigkick: - cl.punchangle[PITCH] = -4; + cl.viewstate.punchangle = (vec4f_t) { + // -4 degrees pitch + 0, -0.0348994967, 0, 0.999390827 + }; break; case svc_updateping: diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index f48533673..5bf79a163 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -47,7 +47,7 @@ cvar_t *cl_pushlatency; void -CL_PredictUsercmd (player_state_t * from, player_state_t * to, usercmd_t *u, +CL_PredictUsercmd (player_state_t *from, player_state_t *to, usercmd_t *u, qboolean clientplayer) { if (!clientplayer) { @@ -105,6 +105,8 @@ CL_PredictMove (void) float f; int oldphysent, i; frame_t *from, *to = NULL; + entity_state_t *fromes; + entity_state_t *toes; if (cl_pushlatency->value > 0) Cvar_Set (cl_pushlatency, "0"); @@ -130,15 +132,16 @@ CL_PredictMove (void) UPDATE_BACKUP - 1) return; - VectorCopy (cl.viewangles, cl.simangles); - cl.simangles[ROLL] = 0; // FIXME @@@ + VectorCopy (cl.viewangles, cl.viewstate.angles); + cl.viewstate.angles[ROLL] = 0; // FIXME @@@ // this is the last frame received from the server from = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; + fromes = &from->playerstate[cl.playernum].pls.es; if (!cl_predict->int_val) { - VectorCopy (from->playerstate[cl.playernum].pls.es.velocity, cl.simvel); - VectorCopy (from->playerstate[cl.playernum].pls.es.origin, cl.simorg); + cl.viewstate.velocity = fromes->velocity; + cl.viewstate.origin = fromes->origin; return; } @@ -165,6 +168,7 @@ CL_PredictMove (void) if (i == UPDATE_BACKUP - 1 || !to) return; // net hasn't deliver packets in a // long time... + toes = &to->playerstate[cl.playernum].pls.es; // now interpolate some fraction of the final frame if (to->senttime == from->senttime) @@ -175,18 +179,14 @@ CL_PredictMove (void) } for (i = 0; i < 3; i++) - if (fabs (from->playerstate[cl.playernum].pls.es.origin[i] - - to->playerstate[cl.playernum].pls.es.origin[i]) > 128) { + if (fabs (fromes->origin[i] - toes->origin[i]) > 128) { // teleported, so don't lerp - VectorCopy (to->playerstate[cl.playernum].pls.es.velocity, - cl.simvel); - VectorCopy (to->playerstate[cl.playernum].pls.es.origin, cl.simorg); + cl.viewstate.velocity = toes->velocity; + cl.viewstate.origin = toes->origin; return; } - cl.simorg = from->playerstate[cl.playernum].pls.es.origin - + f * (to->playerstate[cl.playernum].pls.es.origin - - from->playerstate[cl.playernum].pls.es.origin); + cl.viewstate.origin = fromes->origin + f * (toes->origin - fromes->origin); } void diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 22c8b5b96..12cfb8441 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -87,7 +87,9 @@ SCR_CShift (void) int contents = CONTENTS_EMPTY; if (cls.state == ca_active && cl.worldmodel) { - leaf = Mod_PointInLeaf (r_data->refdef->vieworg, cl.worldmodel); + //FIXME + leaf = Mod_PointInLeaf (&r_data->refdef->viewposition[0], + cl.worldmodel); contents = leaf->contents; } V_SetContentsColor (contents); diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index f20d5747a..0e9162ca8 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -37,8 +37,6 @@ #include "compat.h" -#include "client/view.h" - #include "qw/bothdefs.h" #include "qw/include/chase.h" @@ -84,8 +82,9 @@ cvar_t *v_idlescale; float v_dmg_time, v_dmg_roll, v_dmg_pitch; -frame_t *view_frame; -player_state_t *view_state; +vec4f_t v_idle_yaw; +vec4f_t v_idle_roll; +vec4f_t v_idle_pitch; cshift_t cshift_empty = { {130, 80, 50}, 0}; cshift_t cshift_water = { {130, 80, 50}, 128}; @@ -119,7 +118,7 @@ V_CalcRoll (const vec3_t angles, vec4f_t velocity) static float V_CalcBob (void) { - vec4f_t velocity = cl.simvel; + vec4f_t velocity = cl.viewstate.velocity; float cycle; static double bobtime; static float bob; @@ -130,7 +129,7 @@ V_CalcBob (void) if (cl.onground == -1) return bob; // just use old value - bobtime += host_frametime; + bobtime += cl.viewstate.frametime; cycle = bobtime - (int) (bobtime / cl_bobcycle->value) * cl_bobcycle->value; cycle /= cl_bobcycle->value; @@ -189,10 +188,9 @@ static void V_DriftPitch (void) { float delta, move; - int frameno = (cls.netchan.outgoing_sequence - 1) & UPDATE_MASK; - usercmd_t *cmd = &cl.frames[frameno].cmd; + float forwardmove = cl.viewstate.movecmd[0]; - if (view_state->onground == -1 || cls.demoplayback) { + if (noclip_anglehack || cl.viewstate.onground == -1 || cls.demoplayback) { cl.driftmove = 0; cl.pitchvel = 0; return; @@ -200,10 +198,10 @@ V_DriftPitch (void) // don't count small mouse motion if (cl.nodrift) { - if (fabs (cmd->forwardmove) < cl_forwardspeed->value) + if (fabs (forwardmove) < cl_forwardspeed->value) cl.driftmove = 0; else - cl.driftmove += host_frametime; + cl.driftmove += cl.viewstate.frametime; if (cl.driftmove > v_centermove->value) { V_StartPitchDrift (); @@ -211,28 +209,28 @@ V_DriftPitch (void) return; } - delta = cl.idealpitch - cl.viewangles[PITCH]; + delta = cl.idealpitch - cl.viewstate.angles[PITCH]; if (!delta) { cl.pitchvel = 0; return; } - move = host_frametime * cl.pitchvel; - cl.pitchvel += host_frametime * v_centerspeed->value; + move = cl.viewstate.frametime * cl.pitchvel; + cl.pitchvel += cl.viewstate.frametime * v_centerspeed->value; if (delta > 0) { if (move > delta) { cl.pitchvel = 0; move = delta; } - cl.viewangles[PITCH] += move; + cl.viewstate.angles[PITCH] += move; } else if (delta < 0) { if (move > -delta) { cl.pitchvel = 0; move = -delta; } - cl.viewangles[PITCH] -= move; + cl.viewstate.angles[PITCH] -= move; } } @@ -243,8 +241,8 @@ V_ParseDamage (void) { float count, side; int armor, blood; - vec4f_t origin = cl.simorg; - vec_t *angles = cl.simangles; + vec4f_t origin = cl.viewstate.origin; + vec_t *angles = cl.viewstate.angles; vec3_t from, forward, right, up; armor = MSG_ReadByte (net_message); @@ -488,73 +486,41 @@ V_PrepBlend (void) /* VIEW RENDERING */ -static float -angledelta (float a) -{ - a = anglemod (a); - if (a > 180) - a -= 360; - return a; -} - static void CalcGunAngle (void) { - float yaw, pitch, move; - static float oldpitch = 0, oldyaw = 0; - - yaw = r_data->refdef->viewangles[YAW]; - pitch = -r_data->refdef->viewangles[PITCH]; - - yaw = angledelta (yaw - r_data->refdef->viewangles[YAW]) * 0.4; - yaw = bound (-10, yaw, 10); - pitch = angledelta (-pitch - r_data->refdef->viewangles[PITCH]) * 0.4; - pitch = bound (-10, pitch, 10); - - move = host_frametime * 20; - if (yaw > oldyaw) { - if (oldyaw + move < yaw) - yaw = oldyaw + move; - } else { - if (oldyaw - move > yaw) - yaw = oldyaw - move; - } - - if (pitch > oldpitch) { - if (oldpitch + move < pitch) - pitch = oldpitch + move; - } else { - if (oldpitch - move > pitch) - pitch = oldpitch - move; - } - - oldyaw = yaw; - oldpitch = pitch; - - cl.viewent.angles[YAW] = r_data->refdef->viewangles[YAW] + yaw; - cl.viewent.angles[PITCH] = -(r_data->refdef->viewangles[PITCH] + pitch); + vec4f_t rotation = r_data->refdef->viewrotation; + //FIXME make child of camera + Transform_SetWorldRotation (cl.viewent.transform, rotation); } static void V_BoundOffsets (void) { - vec4f_t origin = cl.simorg; + vec4f_t offset = r_data->refdef->viewposition + - cl.viewstate.origin; // absolutely bound refresh reletive to entity clipping hull // so the view can never be inside a solid wall - if (r_data->refdef->vieworg[0] < origin[0] - 14) - r_data->refdef->vieworg[0] = origin[0] - 14; - else if (r_data->refdef->vieworg[0] > origin[0] + 14) - r_data->refdef->vieworg[0] = origin[0] + 14; - if (r_data->refdef->vieworg[1] < origin[1] - 14) - r_data->refdef->vieworg[1] = origin[1] - 14; - else if (r_data->refdef->vieworg[1] > origin[1] + 14) - r_data->refdef->vieworg[1] = origin[1] + 14; - if (r_data->refdef->vieworg[2] < origin[2] - 22) - r_data->refdef->vieworg[2] = origin[2] - 22; - else if (r_data->refdef->vieworg[2] > origin[2] + 30) - r_data->refdef->vieworg[2] = origin[2] + 30; + offset[0] = bound (-14, offset[0], 14); + offset[1] = bound (-14, offset[1], 14); + offset[2] = bound (-22, offset[2], 30); + r_data->refdef->viewposition = cl.viewstate.origin + offset; +} + +static vec4f_t +idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level) +{ + vec4f_t identity = { 0, 0, 0, 1 }; + if (!level || !cycle) { + return identity; + } + float scale = sin (cl.time * cycle->value); + float ang = scale * level->value * v_idlescale->value; + float c = cos (ang); + float s = sin (ang); + return axis * s + identity * c; } /* @@ -565,19 +531,21 @@ V_BoundOffsets (void) static void V_AddIdle (void) { - r_data->refdef->viewangles[ROLL] += v_idlescale->value * - sin (cl.time * v_iroll_cycle->value) * v_iroll_level->value; - r_data->refdef->viewangles[PITCH] += v_idlescale->value * - sin (cl.time * v_ipitch_cycle->value) * v_ipitch_level->value; - r_data->refdef->viewangles[YAW] += v_idlescale->value * - sin (cl.time * v_iyaw_cycle->value) * v_iyaw_level->value; + vec4f_t roll = idle_quat ((vec4f_t) { 1, 0, 0, 0}, + v_iroll_cycle, v_iroll_level); + vec4f_t pitch = idle_quat ((vec4f_t) { 0, 1, 0, 0}, + v_ipitch_cycle, v_ipitch_level); + vec4f_t yaw = idle_quat ((vec4f_t) { 0, 0, 1, 0}, + v_iyaw_cycle, v_iyaw_level); + vec4f_t rot = normalf (qmulf (yaw, qmulf (pitch, roll))); - cl.viewent.angles[ROLL] -= v_idlescale->value * - sin (cl.time * v_iroll_cycle->value) * v_iroll_level->value; - cl.viewent.angles[PITCH] -= v_idlescale->value * - sin (cl.time * v_ipitch_cycle->value) * v_ipitch_level->value; - cl.viewent.angles[YAW] -= v_idlescale->value * - sin (cl.time * v_iyaw_cycle->value) * v_iyaw_level->value; + // rotate the view + r_data->refdef->viewrotation = qmulf (rot, r_data->refdef->viewrotation); + + // counter-rotate the weapon + rot = qmulf (qconjf (rot), + Transform_GetWorldRotation (cl.viewent.transform)); + Transform_SetWorldRotation (cl.viewent.transform, rot); } /* @@ -588,23 +556,25 @@ V_AddIdle (void) static void V_CalcViewRoll (void) { - float side; - vec_t *angles = cl.simangles; - vec4f_t velocity = cl.simvel; + vec_t *angles = cl.viewstate.angles; + vec4f_t velocity = cl.viewstate.velocity; + vec3_t ang = { }; - side = V_CalcRoll (angles, velocity); - r_data->refdef->viewangles[ROLL] += side; + ang[ROLL] = V_CalcRoll (angles, velocity); if (v_dmg_time > 0) { - r_data->refdef->viewangles[ROLL] += - v_dmg_time / v_kicktime->value * v_dmg_roll; - r_data->refdef->viewangles[PITCH] += - v_dmg_time / v_kicktime->value * v_dmg_pitch; - v_dmg_time -= host_frametime; + ang[ROLL] += v_dmg_time / v_kicktime->value * v_dmg_roll; + ang[PITCH] += v_dmg_time / v_kicktime->value * v_dmg_pitch; + v_dmg_time -= cl.viewstate.frametime; } - if (view_state->pls.es.flags & PF_DEAD) // PF_GIB will also set PF_DEAD - r_data->refdef->viewangles[ROLL] = 80; // dead view angle + if (cl.viewstate.flags & VF_DEAD) { // VF_GIB will also set VF_DEAD + ang[ROLL] = 80; // dead view angle + } + + vec4f_t rot; + AngleQuat (ang, &rot[0]);//FIXME + r_data->refdef->viewrotation = qmulf (r_data->refdef->viewrotation, rot); } static void @@ -612,14 +582,12 @@ V_CalcIntermissionRefdef (void) { entity_t *view; float old; - vec4f_t origin = cl.simorg; - vec_t *angles = cl.simangles; // view is the weapon model (visible only from inside body) view = &cl.viewent; - VectorCopy (origin, r_data->refdef->vieworg); - VectorCopy (angles, r_data->refdef->viewangles); + r_data->refdef->viewposition = cl.viewstate.origin; + AngleQuat (cl.viewstate.angles, &r_data->refdef->viewrotation[0]);//FIXME view->renderer.model = NULL; // always idle in intermission @@ -636,113 +604,122 @@ V_CalcRefdef (void) entity_t *view = &cl.viewent; float bob; static float oldz = 0; - int i; - vec3_t forward, right, up; - vec4f_t origin = cl.simorg; - vec_t *viewangles = cl.simangles; + vec4f_t forward = {}, right = {}, up = {}; + vec4f_t origin = cl.viewstate.origin; + vec_t *viewangles = cl.viewstate.angles; V_DriftPitch (); bob = V_CalcBob (); // refresh position - VectorCopy (origin, r_data->refdef->vieworg); - r_data->refdef->vieworg[2] += cl.viewheight + bob; + r_data->refdef->viewposition = origin; + r_data->refdef->viewposition[2] += cl.viewheight + bob; // never let it sit exactly on a node line, because a water plane can // disappear when viewed with the eye exactly on it. // server protocol specifies to only 1/8 pixel, so add 1/16 in each axis - r_data->refdef->vieworg[0] += 1.0 / 16; - r_data->refdef->vieworg[1] += 1.0 / 16; - r_data->refdef->vieworg[2] += 1.0 / 16; + r_data->refdef->viewposition += (vec4f_t) { 1.0/16, 1.0/16, 1.0/16, 0}; - VectorCopy (viewangles, r_data->refdef->viewangles); + AngleQuat (cl.viewstate.angles, &r_data->refdef->viewrotation[0]);//FIXME V_CalcViewRoll (); V_AddIdle (); // offsets - AngleVectors (viewangles, forward, right, up); + //FIXME semi-duplicates AngleQuat (also, vec3_t vs vec4f_t) + AngleVectors (viewangles, &forward[0], &right[0], &up[0]); // don't allow cheats in multiplayer // FIXME check for dead if (cl.maxclients == 1) { - for (i = 0; i < 3; i++) { - r_data->refdef->vieworg[i] += scr_ofsx->value * forward[i] + - scr_ofsy->value * right[i] + - scr_ofsz->value * up[i]; - } + r_data->refdef->viewposition += scr_ofsx->value * forward + + scr_ofsy->value * right + + scr_ofsz->value * up; } V_BoundOffsets (); // set up gun position - VectorCopy (viewangles, view->angles); - CalcGunAngle (); - VectorCopy (origin, view->origin); - view->origin[2] += cl.viewheight; - - for (i = 0; i < 3; i++) { - view->origin[i] += forward[i] * bob * 0.4; -// view->origin[i] += right[i] * bob * 0.4; -// view->origin[i] += up[i] * bob * 0.8; - } - view->origin[2] += bob; + origin += (vec4f_t) { 0, 0, cl.viewheight, 0 }; + origin += forward * bob * 0.4f + (vec4f_t) { 0, 0, bob, 0 }; // fudge position around to keep amount of weapon visible // roughly equal with different FOV - if (hud_sbar->int_val == 0 && r_data->scr_viewsize->int_val >= 100) + if (hud_sbar->int_val == 0 && r_data->scr_viewsize->int_val >= 100) { ; - else if (r_data->scr_viewsize->int_val == 110) - view->origin[2] += 1; - else if (r_data->scr_viewsize->int_val == 100) - view->origin[2] += 2; - else if (r_data->scr_viewsize->int_val == 90) - view->origin[2] += 1; - else if (r_data->scr_viewsize->int_val == 80) - view->origin[2] += 0.5; + } else if (r_data->scr_viewsize->int_val == 110) { + origin += (vec4f_t) { 0, 0, 1, 0}; + } else if (r_data->scr_viewsize->int_val == 100) { + origin += (vec4f_t) { 0, 0, 2, 0}; + } else if (r_data->scr_viewsize->int_val == 90) { + origin += (vec4f_t) { 0, 0, 1, 0}; + } else if (r_data->scr_viewsize->int_val == 80) { + origin += (vec4f_t) { 0, 0, 0.5, 0}; + } - if (view_state->pls.es.flags & (PF_GIB | PF_DEAD)) { + if (cl.viewstate.flags & (VF_GIB | VF_DEAD)) { view->renderer.model = NULL; } else { view->renderer.model = cl.model_precache[cl.stats[STAT_WEAPON]]; } - view->animation.frame = view_state->pls.es.weaponframe; + view->animation.frame = cl.viewstate.weaponframe; view->renderer.skin = 0; // set up the refresh position - VectorAdd (r_data->refdef->viewangles, cl.punchangle, - r_data->refdef->viewangles); + r_data->refdef->viewrotation = qmulf (cl.viewstate.punchangle, + r_data->refdef->viewrotation); // smooth out stair step ups if ((cl.onground != -1) && (origin[2] - oldz > 0)) { float steptime; - steptime = host_frametime; + steptime = cl.viewstate.frametime; oldz += steptime * 80; if (oldz > origin[2]) oldz = origin[2]; if (origin[2] - oldz > 12) oldz = origin[2] - 12; - r_data->refdef->vieworg[2] += oldz - origin[2]; - view->origin[2] += oldz - origin[2]; - } else + r_data->refdef->viewposition[2] += oldz - origin[2]; + origin[2] += oldz - origin[2]; + } else { oldz = origin[2]; + } + { + // FIXME sort out the alias model specific negation + vec3_t ang = {-viewangles[0], viewangles[1], viewangles[2]}; + CL_TransformEntity (view, 1, ang, origin); + } - if (cl.chase && chase_active->int_val) + if (cl.chase && chase_active->int_val) { Chase_Update (); - - CL_TransformEntity (view, view->angles); + } } static void DropPunchAngle (void) { - cl.punchangle[PITCH] -= 10 * host_frametime; - if (cl.punchangle[PITCH] < 0) - cl.punchangle[PITCH] = 0; + vec4f_t punch = cl.viewstate.punchangle; + float ps = magnitude3f (punch)[0]; + if (ps < 1e-3) { + // < 0.2 degree rotation, not worth worrying about + //ensure the quaternion is normalized + cl.viewstate.punchangle = (vec4f_t) { 0, 0, 0, 1 }; + return; + } + float pc = punch[3]; + float ds = 0.0871557427 * cl.viewstate.frametime; + float dc = sqrt (1 - ds * ds); + float s = ps * dc - pc * ds; + float c = pc * dc + ps * ds; + if (s <= 0 || c >= 1) { + cl.viewstate.punchangle = (vec4f_t) { 0, 0, 0, 1 }; + } else { + punch *= s / ps; + punch[3] = c; + } } /* @@ -754,17 +731,17 @@ DropPunchAngle (void) void V_RenderView (void) { - if (cls.state != ca_active) + if (cls.state != ca_active) { + r_data->refdef->viewposition = (vec4f_t) { 0, 0, 0, 1 }; + r_data->refdef->viewrotation = (vec4f_t) { 0, 0, 0, 1 }; return; + } - view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; - view_state = &view_frame->playerstate[cl.playernum]; - - if (view_state->pls.es.flags & PF_GIB) + if (cl.viewstate.flags & VF_GIB) { cl.viewheight = 8; // gib view height - else if (view_state->pls.es.flags & PF_DEAD) + } else if (cl.viewstate.flags & VF_DEAD) { cl.viewheight = -16; // corpse view height - else { + } else { cl.viewheight = DEFAULT_VIEWHEIGHT; // view height if (cl.stdver) cl.viewheight = cl.stats[STAT_VIEWHEIGHT]; diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index 159da95f0..c3e2a0424 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -184,10 +184,10 @@ Team_ParseSay (dstring_t *buf, const char *s) case 'l': location: bracket = 0; - location = locs_find (cl.simorg); + location = locs_find (cl.viewstate.origin); if (location) { recorded_location = true; - last_recorded_location = cl.simorg; + last_recorded_location = cl.viewstate.origin; t1 = location->name; } else snprintf (t2, sizeof (t2), "Unknown!"); @@ -279,7 +279,7 @@ void Team_Dead (void) { died = true; - death_location = cl.simorg; + death_location = cl.viewstate.origin; } void @@ -370,7 +370,7 @@ locs_loc (void) if (strcasecmp (Cmd_Argv (1), "add") == 0) { if (Cmd_Argc () >= 3) - locs_mark (cl.simorg, desc); + locs_mark (cl.viewstate.origin, desc); else Sys_Printf ("loc add :marks the current location " "with the description and records the information " @@ -379,7 +379,7 @@ locs_loc (void) if (strcasecmp (Cmd_Argv (1), "rename") == 0) { if (Cmd_Argc () >= 3) - locs_edit (cl.simorg, desc); + locs_edit (cl.viewstate.origin, desc); else Sys_Printf ("loc rename :changes the description of " "the nearest location marker\n"); @@ -387,14 +387,14 @@ locs_loc (void) if (strcasecmp (Cmd_Argv (1),"delete") == 0) { if (Cmd_Argc () == 2) - locs_del (cl.simorg); + locs_del (cl.viewstate.origin); else Sys_Printf ("loc delete :removes nearest location marker\n"); } if (strcasecmp (Cmd_Argv (1),"move") == 0) { if (Cmd_Argc () == 2) - locs_edit (cl.simorg, NULL); + locs_edit (cl.viewstate.origin, NULL); else Sys_Printf ("loc move :moves the nearest location marker to your " "current location\n"); @@ -409,7 +409,7 @@ Locs_Loc_Get (void) if (GIB_Argc () != 1) GIB_USAGE (""); else { - location = locs_find (cl.simorg); + location = locs_find (cl.viewstate.origin); GIB_Return (location ? location->name : "unknown"); } } From 8f7d6b1d02b9057af7e9f93bd69dd1b0ef104403 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Mar 2021 22:53:23 +0900 Subject: [PATCH 1382/3664] [vulkan] Initialize skins This allows the qw client to run with Vulkan. --- libs/video/renderer/vid_render_vulkan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 00c307dbc..b4f84f129 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -102,6 +102,7 @@ vulkan_R_Init (void) Vulkan_Particles_Init (vulkan_ctx); Vulkan_Lighting_Init (vulkan_ctx); Vulkan_Compose_Init (vulkan_ctx); + Skin_Init (); Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, vulkan_ctx->swapchain->numImages); From 82e58dae5f6adcd59df2bbc0390f0346ba8aae17 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Mar 2021 22:54:20 +0900 Subject: [PATCH 1383/3664] [qw] Disable lerping on player model change This seems to be an ancient bug, but may have been exposed by the recent entity changes (was certainly highlighted by Vulkan) --- qw/source/cl_ents.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 8ee9440b4..26e25ad25 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -433,7 +433,11 @@ CL_LinkPlayers (void) } ang[ROLL] = V_CalcRoll (ang, state->pls.es.velocity) * 4.0; - ent->renderer.model = cl.model_precache[state->pls.es.modelindex]; + if (ent->renderer.model + != cl.model_precache[state->pls.es.modelindex]) { + ent->renderer.model = cl.model_precache[state->pls.es.modelindex]; + ent->animation.nolerp = 1; + } ent->animation.frame = state->pls.es.frame; ent->renderer.skinnum = state->pls.es.skinnum; From 5cf1da7c252dcf6b6e9f3a0bd89b66756a2dd249 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 00:58:37 +0900 Subject: [PATCH 1384/3664] [client] Finish moving onground to viewstate Missed this in the entity cleanup (really, should have been separate commits, but oh well). --- include/client/view.h | 2 +- nq/include/client.h | 1 - nq/source/cl_parse.c | 4 ++-- nq/source/cl_view.c | 4 ++-- qw/include/client.h | 1 - qw/source/cl_pred.c | 4 ++-- qw/source/cl_view.c | 4 ++-- 7 files changed, 9 insertions(+), 11 deletions(-) diff --git a/include/client/view.h b/include/client/view.h index 40ad78df3..7a7f8e005 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -43,7 +43,7 @@ typedef struct viewstate_s { vec4f_t origin; vec3_t angles; int weaponframe; - int onground; + int onground; // -1 when in air uint32_t flags; float frametime; vec4f_t punchangle; diff --git a/nq/include/client.h b/nq/include/client.h index 5d98e437b..54cb937f9 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -178,7 +178,6 @@ typedef struct { double laststop; qboolean paused; // Sent over by server - int onground; float viewheight; float crouch; // Local amount for smoothing stepups qboolean inwater; diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index e74a65976..30e48e82a 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -692,7 +692,7 @@ CL_ParseClientdata (void) cl.stats[STAT_ITEMS] = i; } - cl.onground = (bits & SU_ONGROUND) ? 0 : -1; + cl.viewstate.onground = (bits & SU_ONGROUND) ? 0 : -1; cl.inwater = (bits & SU_INWATER) != 0; if (bits & SU_WEAPONFRAME) @@ -851,7 +851,7 @@ CL_ParseServerMessage (void) else if (cl_shownet->int_val == 2) Sys_Printf ("------------------\n"); - cl.onground = -1; // unless the server says otherwise + cl.viewstate.onground = -1; // unless the server says otherwise // parse the message MSG_BeginReading (net_message); diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index f5ba3de8f..d21f267b1 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -124,7 +124,7 @@ V_CalcBob (void) if (cl.spectator) return 0; - if (cl.onground == -1) + if (cl.viewstate.onground == -1) return bob; // just use old value bobtime += cl.viewstate.frametime; @@ -666,7 +666,7 @@ V_CalcRefdef (void) r_data->refdef->viewrotation); // smooth out stair step ups - if ((cl.onground != -1) && (origin[2] - oldz > 0)) { + if ((cl.viewstate.onground != -1) && (origin[2] - oldz > 0)) { float steptime; steptime = cl.viewstate.frametime; diff --git a/qw/include/client.h b/qw/include/client.h index 8c0369fba..f3e12fced 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -232,7 +232,6 @@ typedef struct { double laststop; qboolean paused; // Sent over by server - int onground; // -1 when in air float viewheight; float crouch; // local amount for smoothing stepups diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index 5bf79a163..58ee4a144 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -115,7 +115,7 @@ CL_PredictMove (void) return; // assume on ground unless prediction says different - cl.onground = 0; + cl.viewstate.onground = 0; cl.time = realtime - cls.latency - cl_pushlatency->value * 0.001; if (cl.time > realtime) @@ -157,7 +157,7 @@ CL_PredictMove (void) CL_PredictUsercmd (&from->playerstate[cl.playernum], &to->playerstate[cl.playernum], &to->cmd, true); - cl.onground = onground; + cl.viewstate.onground = onground; if (to->senttime >= cl.time) break; from = to; diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 0e9162ca8..0da8c09cc 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -126,7 +126,7 @@ V_CalcBob (void) if (cl.spectator) return 0; - if (cl.onground == -1) + if (cl.viewstate.onground == -1) return bob; // just use old value bobtime += cl.viewstate.frametime; @@ -672,7 +672,7 @@ V_CalcRefdef (void) r_data->refdef->viewrotation); // smooth out stair step ups - if ((cl.onground != -1) && (origin[2] - oldz > 0)) { + if ((cl.viewstate.onground != -1) && (origin[2] - oldz > 0)) { float steptime; steptime = cl.viewstate.frametime; From dc7cb97481a96319462b2e42bde1dac6eaf32ef1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 01:48:26 +0900 Subject: [PATCH 1385/3664] [qw] Remove viewangles from client state Other than the one line in cl_pred.c, it's redundant, but it looks to be just a redundant copy from ancient times. --- nq/source/cl_input.c | 3 ++- qw/include/client.h | 6 ++---- qw/source/cl_cam.c | 14 ++++++------- qw/source/cl_demo.c | 4 ++-- qw/source/cl_ents.c | 4 ++-- qw/source/cl_input.c | 49 ++++++++++++++++++++++++-------------------- qw/source/cl_main.c | 16 +++++++-------- qw/source/cl_parse.c | 4 ++-- qw/source/cl_pred.c | 2 +- 9 files changed, 53 insertions(+), 49 deletions(-) diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 291f0ecac..5d471afaf 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -477,8 +477,9 @@ CL_AdjustAngles (void) void CL_BaseMove (usercmd_t *cmd) { - if (cls.state != ca_active) + if (cls.state != ca_active) { return; + } CL_AdjustAngles (); diff --git a/qw/include/client.h b/qw/include/client.h index f3e12fced..9f282717c 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -216,13 +216,11 @@ typedef struct { cshift_t cshifts[NUM_CSHIFTS]; // Color shifts for damage, powerups cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types -// the client maintains its own idea of view angles, which are sent to the -// server each frame. And reset only at level change and teleport times - vec3_t viewangles; - // the client simulates or interpolates movement to get these values double time; // this is the time value that the client // is rendering at. always <= realtime +// the client maintains its own idea of view angles, which are sent to the +// server each frame. And reset only at level change and teleport times viewstate_t viewstate; // pitch drifting vars float idealpitch; diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 1b1959f13..383bc313a 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -439,7 +439,7 @@ Cam_Track (usercmd_t *cmd) if (cl_chasecam->int_val) { cmd->forwardmove = cmd->sidemove = cmd->upmove = 0; - VectorCopy (player->viewangles, cl.viewangles); + VectorCopy (player->viewangles, cl.viewstate.angles); VectorCopy (player->pls.es.origin, desired_position); if (memcmp (&desired_position, &self->pls.es.origin, sizeof (desired_position)) != 0) { @@ -468,8 +468,8 @@ Cam_Track (usercmd_t *cmd) VectorCopy (desired_position, self->pls.es.origin); VectorSubtract (player->pls.es.origin, desired_position, vec); - vectoangles (vec, cl.viewangles); - cl.viewangles[0] = -cl.viewangles[0]; + vectoangles (vec, cl.viewstate.angles); + cl.viewstate.angles[0] = -cl.viewstate.angles[0]; } } @@ -536,8 +536,8 @@ Cam_SetView (void) adjustang (cam_viewangles[YAW], vec2[YAW], cl_camera_maxyaw->value); } - VectorCopy (cam_viewangles, cl.viewangles); - VectorCopy (cl.viewangles, cl.simangles); + VectorCopy (cam_viewangles, cl.viewstate.angles); + VectorCopy (cl.viewstate.angles, cl.simangles); cl.simangles[ROLL] = 0; // FIXME @@@ } #endif @@ -576,7 +576,7 @@ Cam_FinishMove (usercmd_t *cmd) adjustang (cam_viewangles[YAW], vec2[YAW], cl_camera_maxyaw->value); } - VectorCopy (cam_viewangles, cl.viewangles); + VectorCopy (cam_viewangles, cl.viewstate.angles); } #endif @@ -587,7 +587,7 @@ Cam_FinishMove (usercmd_t *cmd) if (autocam > CAM_TRACK) { Cam_Unlock (); - VectorCopy (cl.viewangles, cmd->angles); + VectorCopy (cl.viewstate.angles, cmd->angles); return; } } else diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 7503f5c2a..df54decd7 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -333,7 +333,7 @@ nextdemomessage: cls.netchan.outgoing_sequence++; for (i = 0; i < 3; i++) { Qread (cls.demofile, &f, 4); - cl.viewangles[i] = LittleFloat (f); + cl.viewstate.angles[i] = LittleFloat (f); } break; @@ -462,7 +462,7 @@ CL_WriteDemoCmd (usercmd_t *pcmd) Qwrite (cls.demofile, &cmd, sizeof (cmd)); for (i = 0; i < 3; i++) { - fl = LittleFloat (cl.viewangles[i]); + fl = LittleFloat (cl.viewstate.angles[i]); Qwrite (cls.demofile, &fl, 4); } diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 26e25ad25..9da38dc9c 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -425,8 +425,8 @@ CL_LinkPlayers (void) // angles if (j == cl.playernum) { - ang[PITCH] = -cl.viewangles[PITCH] / 3.0; - ang[YAW] = cl.viewangles[YAW]; + ang[PITCH] = -cl.viewstate.angles[PITCH] / 3.0; + ang[YAW] = cl.viewstate.angles[YAW]; } else { ang[PITCH] = -state->viewangles[PITCH] / 3.0; ang[YAW] = state->viewangles[YAW]; diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 9b9763d46..7371c06cc 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -454,35 +454,35 @@ CL_AdjustAngles (void) yawspeed *= host_frametime; if (!(in_strafe.state & 1)) { - cl.viewangles[YAW] -= yawspeed * CL_KeyState (&in_right); - cl.viewangles[YAW] += yawspeed * CL_KeyState (&in_left); - cl.viewangles[YAW] = anglemod (cl.viewangles[YAW]); + cl.viewstate.angles[YAW] -= yawspeed * CL_KeyState (&in_right); + cl.viewstate.angles[YAW] += yawspeed * CL_KeyState (&in_left); + cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); } if (in_klook.state & 1) { V_StopPitchDrift (); - cl.viewangles[PITCH] -= pitchspeed * CL_KeyState (&in_forward); - cl.viewangles[PITCH] += pitchspeed * CL_KeyState (&in_back); + cl.viewstate.angles[PITCH] -= pitchspeed * CL_KeyState (&in_forward); + cl.viewstate.angles[PITCH] += pitchspeed * CL_KeyState (&in_back); } up = CL_KeyState (&in_lookup); down = CL_KeyState (&in_lookdown); - cl.viewangles[PITCH] -= pitchspeed * up; - cl.viewangles[PITCH] += pitchspeed * down; + cl.viewstate.angles[PITCH] -= pitchspeed * up; + cl.viewstate.angles[PITCH] += pitchspeed * down; if (up || down) V_StopPitchDrift (); // FIXME: Need to clean up view angle limits - if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; + if (cl.viewstate.angles[PITCH] > 80) + cl.viewstate.angles[PITCH] = 80; + if (cl.viewstate.angles[PITCH] < -70) + cl.viewstate.angles[PITCH] = -70; - if (cl.viewangles[ROLL] > 50) - cl.viewangles[ROLL] = 50; - if (cl.viewangles[ROLL] < -50) - cl.viewangles[ROLL] = -50; + if (cl.viewstate.angles[ROLL] > 50) + cl.viewstate.angles[ROLL] = 50; + if (cl.viewstate.angles[ROLL] < -50) + cl.viewstate.angles[ROLL] = -50; } /* @@ -493,11 +493,15 @@ CL_AdjustAngles (void) void CL_BaseMove (usercmd_t *cmd) { + if (cls.state != ca_active) { + return; + } + CL_AdjustAngles (); memset (cmd, 0, sizeof (*cmd)); - VectorCopy (cl.viewangles, cmd->angles); + VectorCopy (cl.viewstate.angles, cmd->angles); if (in_strafe.state & 1) { cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right); cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left); @@ -536,7 +540,7 @@ CL_BaseMove (usercmd_t *cmd) vec3_t forward, right, up, f, r; vec3_t dir = {0, 0, 0}; - dir[1] = r_data->refdef->viewangles[1] - cl.viewangles[1]; + dir[1] = r_data->refdef->viewangles[1] - cl.viewstate.angles[1]; AngleVectors (dir, forward, right, up); VectorScale (forward, cmd->forwardmove, f); VectorScale (right, cmd->sidemove, r); @@ -552,12 +556,13 @@ CL_BaseMove (usercmd_t *cmd) cmd->forwardmove += viewdelta.position[2] * m_forward->value; cmd->sidemove += viewdelta.position[0] * m_side->value; cmd->upmove += viewdelta.position[1]; - cl.viewangles[PITCH] += viewdelta.angles[PITCH] * m_pitch->value; - cl.viewangles[YAW] += viewdelta.angles[YAW] * m_yaw->value; - cl.viewangles[ROLL] += viewdelta.angles[ROLL]; + cl.viewstate.angles[PITCH] += viewdelta.angles[PITCH] * m_pitch->value; + cl.viewstate.angles[YAW] += viewdelta.angles[YAW] * m_yaw->value; + cl.viewstate.angles[ROLL] += viewdelta.angles[ROLL]; if (freelook && !(in_strafe.state & 1)) { - cl.viewangles[PITCH] = bound (-70, cl.viewangles[PITCH], 80); + cl.viewstate.angles[PITCH] + = bound (-70, cl.viewstate.angles[PITCH], 80); } } @@ -609,7 +614,7 @@ CL_FinishMove (usercmd_t *cmd) } cmd->msec = ms; - VectorCopy (cl.viewangles, cmd->angles); + VectorCopy (cl.viewstate.angles, cmd->angles); cmd->impulse = in_impulse; in_impulse = 0; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index cef24d6bd..ba7bfe270 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1100,7 +1100,7 @@ CL_Download_f (void) static void Force_CenterView_f (void) { - cl.viewangles[PITCH] = 0; + cl.viewstate.angles[PITCH] = 0; } static void @@ -1109,12 +1109,12 @@ CL_PRotate_f (void) if ((cl.fpd & FPD_LIMIT_PITCH) || Cmd_Argc() < 2) return; - cl.viewangles[PITCH] += atoi (Cmd_Argv (1)); + cl.viewstate.angles[PITCH] += atoi (Cmd_Argv (1)); - if (cl.viewangles[PITCH] < -70) - cl.viewangles[PITCH] = -70; - else if (cl.viewangles[PITCH] > 80) - cl.viewangles[PITCH] = 80; + if (cl.viewstate.angles[PITCH] < -70) + cl.viewstate.angles[PITCH] = -70; + else if (cl.viewstate.angles[PITCH] > 80) + cl.viewstate.angles[PITCH] = 80; } static void @@ -1123,8 +1123,8 @@ CL_Rotate_f (void) if ((cl.fpd & FPD_LIMIT_YAW) || Cmd_Argc() < 2) return; - cl.viewangles[YAW] += atoi (Cmd_Argv (1)); - cl.viewangles[YAW] = anglemod (cl.viewangles[YAW]); + cl.viewstate.angles[YAW] += atoi (Cmd_Argv (1)); + cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); } void diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index b53c2beb9..b7a293f28 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1273,7 +1273,7 @@ CL_ParseMuzzleFlash (void) pl = &cl.frames[parsecountmod].playerstate[i - 1]; if (i - 1 == cl.playernum) - AngleVectors (cl.viewangles, f, r, u); + AngleVectors (cl.viewstate.angles, f, r, u); else AngleVectors (pl->viewangles, f, r, u); @@ -1415,7 +1415,7 @@ CL_ParseServerMessage (void) case svc_setangle: { - vec_t *dest = cl.viewangles; + vec_t *dest = cl.viewstate.angles; vec3_t dummy; if (cls.demoplayback2) { diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index 58ee4a144..40f9f1459 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -132,7 +132,7 @@ CL_PredictMove (void) UPDATE_BACKUP - 1) return; - VectorCopy (cl.viewangles, cl.viewstate.angles); + //VectorCopy (cl.viewstate.angles, cl.viewstate.angles); cl.viewstate.angles[ROLL] = 0; // FIXME @@@ // this is the last frame received from the server From 0ace799b277a16d9269ac8f0fcde60f8b28630a7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 03:56:16 +0900 Subject: [PATCH 1386/3664] [util] Support commands with a data parameter Useful for avoiding a pile of wrapper functions that merely pass on command-specific data to the actual implementation. Used to clean up the wrappers in nq and qw cl_input.c --- include/QF/cmd.h | 8 +- libs/util/cmd.c | 29 +++- nq/source/cl_input.c | 362 +++++++++++-------------------------------- qw/source/cl_input.c | 362 +++++++++++-------------------------------- 4 files changed, 207 insertions(+), 554 deletions(-) diff --git a/include/QF/cmd.h b/include/QF/cmd.h index 35846a063..3cd74432b 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -37,6 +37,7 @@ #include "QF/cbuf.h" typedef void (*xcommand_t) (void); +typedef void (*xdatacmd_t) (void *data); typedef enum { src_client, // came in over a net connection as a clc_stringcmd @@ -48,6 +49,8 @@ typedef struct cmd_function_s { struct cmd_function_s *next; const char *name; xcommand_t function; + xdatacmd_t datafunc; + void *data; const char *description; } cmd_function_t; @@ -56,7 +59,10 @@ extern cmd_source_t cmd_source; void Cmd_Init_Hash (void); void Cmd_Init (void); -int Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *description); +int Cmd_AddCommand (const char *cmd_name, xcommand_t function, + const char *description); +int Cmd_AddDataCommand (const char *cmd_name, xdatacmd_t function, + void *data, const char *description); int Cmd_RemoveCommand (const char *cmd_name); qboolean Cmd_Exists (const char *cmd_name); diff --git a/libs/util/cmd.c b/libs/util/cmd.c index aede64982..812fb55b6 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -118,6 +118,8 @@ Cmd_Command (cbuf_args_t *args) if (cmd) { if (cmd->function) { cmd->function (); + } else if (cmd->datafunc) { + cmd->datafunc (cmd->data); } return 0; } @@ -133,10 +135,9 @@ Cmd_Command (cbuf_args_t *args) return 0; } -/* Registers a command and handler function */ -VISIBLE int -Cmd_AddCommand (const char *cmd_name, xcommand_t function, - const char *description) +static int +add_command (const char *cmd_name, xcommand_t func, xdatacmd_t datafunc, + void *data, const char *description) { cmd_function_t *cmd; cmd_function_t **c; @@ -152,7 +153,9 @@ Cmd_AddCommand (const char *cmd_name, xcommand_t function, cmd = calloc (1, sizeof (cmd_function_t)); SYS_CHECKMEM (cmd); cmd->name = cmd_name; - cmd->function = function; + cmd->function = func; + cmd->datafunc = datafunc; + cmd->data = data; cmd->description = description; Hash_Add (cmd_hash, cmd); for (c = &cmd_functions; *c; c = &(*c)->next) @@ -163,6 +166,22 @@ Cmd_AddCommand (const char *cmd_name, xcommand_t function, return 1; } +/* Registers a command and handler function */ +VISIBLE int +Cmd_AddCommand (const char *cmd_name, xcommand_t function, + const char *description) +{ + return add_command (cmd_name, function, 0, 0, description); +} + +/* Registers a command and handler function with data */ +VISIBLE int +Cmd_AddDataCommand (const char *cmd_name, xdatacmd_t function, + void *data, const char *description) +{ + return add_command (cmd_name, 0, function, data, description); +} + /* Unregisters a command */ VISIBLE int Cmd_RemoveCommand (const char *name) diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 5d471afaf..58787e7e7 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -77,8 +77,9 @@ int in_impulse; void (*write_angles) (sizebuf_t *sb, const vec3_t angles); static void -KeyPress (kbutton_t *b) +KeyPress (void *_b) { + kbutton_t *b = _b; const char *c; int k; @@ -107,8 +108,9 @@ KeyPress (kbutton_t *b) } static void -KeyRelease (kbutton_t *b) +KeyRelease (void *_b) { + kbutton_t *b = _b; const char *c; int k; @@ -141,25 +143,7 @@ KeyRelease (kbutton_t *b) } static void -IN_KLookPress (void) -{ - KeyPress (&in_klook); -} - -static void -IN_KLookRelease (void) -{ - KeyRelease (&in_klook); -} - -static void -IN_MLookPress (void) -{ - KeyPress (&in_mlook); -} - -static void -IN_MLookRelease (void) +IN_MLookRelease (void *data) { KeyRelease (&in_mlook); if (!freelook && lookspring->int_val) @@ -167,187 +151,7 @@ IN_MLookRelease (void) } static void -IN_UpPress (void) -{ - KeyPress (&in_up); -} - -static void -IN_UpRelease (void) -{ - KeyRelease (&in_up); -} - -static void -IN_DownPress (void) -{ - KeyPress (&in_down); -} - -static void -IN_DownRelease (void) -{ - KeyRelease (&in_down); -} - -static void -IN_LeftPress (void) -{ - KeyPress (&in_left); -} - -static void -IN_LeftRelease (void) -{ - KeyRelease (&in_left); -} - -static void -IN_RightPress (void) -{ - KeyPress (&in_right); -} - -static void -IN_RightRelease (void) -{ - KeyRelease (&in_right); -} - -static void -IN_ForwardPress (void) -{ - KeyPress (&in_forward); -} - -static void -IN_ForwardRelease (void) -{ - KeyRelease (&in_forward); -} - -static void -IN_BackPress (void) -{ - KeyPress (&in_back); -} - -static void -IN_BackRelease (void) -{ - KeyRelease (&in_back); -} - -static void -IN_LookupPress (void) -{ - KeyPress (&in_lookup); -} - -static void -IN_LookupRelease (void) -{ - KeyRelease (&in_lookup); -} - -static void -IN_LookdownPress (void) -{ - KeyPress (&in_lookdown); -} - -static void -IN_LookdownRelease (void) -{ - KeyRelease (&in_lookdown); -} - -static void -IN_MoveleftPress (void) -{ - KeyPress (&in_moveleft); -} - -static void -IN_MoveleftRelease (void) -{ - KeyRelease (&in_moveleft); -} - -static void -IN_MoverightPress (void) -{ - KeyPress (&in_moveright); -} - -static void -IN_MoverightRelease (void) -{ - KeyRelease (&in_moveright); -} - -static void -IN_SpeedPress (void) -{ - KeyPress (&in_speed); -} - -static void -IN_SpeedRelease (void) -{ - KeyRelease (&in_speed); -} - -static void -IN_StrafePress (void) -{ - KeyPress (&in_strafe); -} - -static void -IN_StrafeRelease (void) -{ - KeyRelease (&in_strafe); -} - -static void -IN_AttackPress (void) -{ - KeyPress (&in_attack); -} - -static void -IN_AttackRelease (void) -{ - KeyRelease (&in_attack); -} - -static void -IN_UsePress (void) -{ - KeyPress (&in_use); -} - -static void -IN_UseRelease (void) -{ - KeyRelease (&in_use); -} - -static void -IN_JumpPress (void) -{ - KeyPress (&in_jump); -} - -static void -IN_JumpRelease (void) -{ - KeyRelease (&in_jump); -} - -static void -IN_Impulse (void) +IN_Impulse (void *data) { in_impulse = atoi (Cmd_Argv (1)); } @@ -608,76 +412,86 @@ CL_SendMove (usercmd_t *cmd) void CL_Input_Init (void) { - Cmd_AddCommand ("+moveup", IN_UpPress, "When active the player is " - "swimming up in a liquid"); - Cmd_AddCommand ("-moveup", IN_UpRelease, "When active the player is not " - "swimming up in a liquid"); - Cmd_AddCommand ("+movedown", IN_DownPress, "When active the player is " - "swimming down in a liquid"); - Cmd_AddCommand ("-movedown", IN_DownRelease, "When active the player is " - "not swimming down in a liquid"); - Cmd_AddCommand ("+left", IN_LeftPress, "When active the player is turning " - "left"); - Cmd_AddCommand ("-left", IN_LeftRelease, "When active the player is not " - "turning left"); - Cmd_AddCommand ("+right", IN_RightPress, "When active the player is " - "turning right"); - Cmd_AddCommand ("-right", IN_RightRelease, "When active the player is not " - "turning right"); - Cmd_AddCommand ("+forward", IN_ForwardPress, "When active the player is " - "moving forward"); - Cmd_AddCommand ("-forward", IN_ForwardRelease, "When active the player is " - "not moving forward"); - Cmd_AddCommand ("+back", IN_BackPress, "When active the player is moving " - "backwards"); - Cmd_AddCommand ("-back", IN_BackRelease, "When active the player is not " - "moving backwards"); - Cmd_AddCommand ("+lookup", IN_LookupPress, "When active the player's view " - "is looking up"); - Cmd_AddCommand ("-lookup", IN_LookupRelease, "When active the player's " - "view is not looking up"); - Cmd_AddCommand ("+lookdown", IN_LookdownPress, "When active the player's " - "view is looking down"); - Cmd_AddCommand ("-lookdown", IN_LookdownRelease, "When active the " - "player's view is not looking up"); - Cmd_AddCommand ("+strafe", IN_StrafePress, "When active, +left and +right " - "function like +moveleft and +moveright"); - Cmd_AddCommand ("-strafe", IN_StrafeRelease, "When active, +left and " - "+right stop functioning like +moveleft and +moveright"); - Cmd_AddCommand ("+moveleft", IN_MoveleftPress, "When active the player is " - "strafing left"); - Cmd_AddCommand ("-moveleft", IN_MoveleftRelease, "When active the player " - "is not strafing left"); - Cmd_AddCommand ("+moveright", IN_MoverightPress, "When active the player " - "is strafing right"); - Cmd_AddCommand ("-moveright", IN_MoverightRelease, "When active the " - "player is not strafing right"); - Cmd_AddCommand ("+speed", IN_SpeedPress, "When active the player is " - "running"); - Cmd_AddCommand ("-speed", IN_SpeedRelease, "When active the player is not " - "running"); - Cmd_AddCommand ("+attack", IN_AttackPress, "When active player is " - "firing/using current weapon"); - Cmd_AddCommand ("-attack", IN_AttackRelease, "When active player is not " - "firing/using current weapon"); - Cmd_AddCommand ("+use", IN_UsePress, "Non-functional. Left over command " - "for opening doors and triggering switches"); - Cmd_AddCommand ("-use", IN_UseRelease, "Non-functional. Left over command " - "for opening doors and triggering switches"); - Cmd_AddCommand ("+jump", IN_JumpPress, "When active the player is " - "jumping"); - Cmd_AddCommand ("-jump", IN_JumpRelease, "When active the player is not " - "jumping"); - Cmd_AddCommand ("impulse", IN_Impulse, "Call a game function or QuakeC " - "function."); - Cmd_AddCommand ("+klook", IN_KLookPress, "When active, +forward and +back " - "perform +lookup and +lookdown"); - Cmd_AddCommand ("-klook", IN_KLookRelease, "When active, +forward and " - "+back don't perform +lookup and +lookdown"); - Cmd_AddCommand ("+mlook", IN_MLookPress, "When active moving the mouse or " - "joystick forwards and backwards performs +lookup and " - "+lookdown"); - Cmd_AddCommand ("-mlook", IN_MLookRelease, "When active moving the mouse " - "or joystick forwards and backwards doesn't perform " - "+lookup and +lookdown"); + Cmd_AddDataCommand ("+moveup", KeyPress, &in_up, + "When active the player is swimming up in a liquid"); + Cmd_AddDataCommand ("-moveup", KeyRelease, &in_up, + "When active the player is not swimming up in a " + "liquid"); + Cmd_AddDataCommand ("+movedown", KeyPress, &in_down, + "When active the player is swimming down in a liquid"); + Cmd_AddDataCommand ("-movedown", KeyRelease, &in_down, + "When active the player is not swimming down in a " + "liquid"); + Cmd_AddDataCommand ("+left", KeyPress, &in_left, + "When active the player is turning left"); + Cmd_AddDataCommand ("-left", KeyRelease, &in_left, + "When active the player is not turning left"); + Cmd_AddDataCommand ("+right", KeyPress, &in_right, + "When active the player is turning right"); + Cmd_AddDataCommand ("-right", KeyRelease, &in_right, + "When active the player is not turning right"); + Cmd_AddDataCommand ("+forward", KeyPress, &in_forward, + "When active the player is moving forward"); + Cmd_AddDataCommand ("-forward", KeyRelease, &in_forward, + "When active the player is not moving forward"); + Cmd_AddDataCommand ("+back", KeyPress, &in_back, + "When active the player is moving backwards"); + Cmd_AddDataCommand ("-back", KeyRelease, &in_back, + "When active the player is not moving backwards"); + Cmd_AddDataCommand ("+lookup", KeyPress, &in_lookup, + "When active the player's view is looking up"); + Cmd_AddDataCommand ("-lookup", KeyRelease, &in_lookup, + "When active the player's view is not looking up"); + Cmd_AddDataCommand ("+lookdown", KeyPress, &in_lookdown, + "When active the player's view is looking down"); + Cmd_AddDataCommand ("-lookdown", KeyRelease, &in_lookdown, + "When active the player's view is not looking up"); + Cmd_AddDataCommand ("+strafe", KeyPress, &in_strafe, + "When active, +left and +right function like " + "+moveleft and +moveright"); + Cmd_AddDataCommand ("-strafe", KeyRelease, &in_strafe, + "When active, +left and +right stop functioning like " + "+moveleft and +moveright"); + Cmd_AddDataCommand ("+moveleft", KeyPress, &in_moveleft, + "When active the player is strafing left"); + Cmd_AddDataCommand ("-moveleft", KeyRelease, &in_moveleft, + "When active the player is not strafing left"); + Cmd_AddDataCommand ("+moveright", KeyPress, &in_moveright, + "When active the player is strafing right"); + Cmd_AddDataCommand ("-moveright", KeyRelease, &in_moveright, + "When active the player is not strafing right"); + Cmd_AddDataCommand ("+speed", KeyPress, &in_speed, + "When active the player is running"); + Cmd_AddDataCommand ("-speed", KeyRelease, &in_speed, + "When active the player is not running"); + Cmd_AddDataCommand ("+attack", KeyPress, &in_attack, + "When active player is firing/using current weapon"); + Cmd_AddDataCommand ("-attack", KeyRelease, &in_attack, + "When active player is not firing/using current " + "weapon"); + Cmd_AddDataCommand ("+use", KeyPress, &in_use, + "Non-functional. Left over command for opening doors " + "and triggering switches"); + Cmd_AddDataCommand ("-use", KeyRelease, &in_use, + "Non-functional. Left over command for opening doors " + "and triggering switches"); + Cmd_AddDataCommand ("+jump", KeyPress, &in_jump, + "When active the player is jumping"); + Cmd_AddDataCommand ("-jump", KeyRelease, &in_jump, + "When active the player is not jumping"); + Cmd_AddDataCommand ("impulse", IN_Impulse, 0, + "Call a game function or QuakeC function."); + Cmd_AddDataCommand ("+klook", KeyPress, &in_klook, + "When active, +forward and +back perform +lookup and " + "+lookdown"); + Cmd_AddDataCommand ("-klook", KeyRelease, &in_klook, + "When active, +forward and +back don't perform " + "+lookup and +lookdown"); + Cmd_AddDataCommand ("+mlook", KeyPress, &in_mlook, + "When active moving the mouse or joystick forwards " + "and backwards performs +lookup and " + "+lookdown"); + Cmd_AddDataCommand ("-mlook", IN_MLookRelease, &in_mlook, + "When active moving the mouse or joystick forwards " + "and backwards doesn't perform +lookup and +lookdown"); } diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 7371c06cc..770e16358 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -89,8 +89,9 @@ int in_impulse; static void -KeyPress (kbutton_t *b) +KeyPress (void *_b) { + kbutton_t *b = _b; const char *c; int k; @@ -119,8 +120,9 @@ KeyPress (kbutton_t *b) } static void -KeyRelease (kbutton_t *b) +KeyRelease (void *_b) { + kbutton_t *b = _b; const char *c; int k; @@ -153,25 +155,7 @@ KeyRelease (kbutton_t *b) } static void -IN_KLookPress (void) -{ - KeyPress (&in_klook); -} - -static void -IN_KLookRelease (void) -{ - KeyRelease (&in_klook); -} - -static void -IN_MLookPress (void) -{ - KeyPress (&in_mlook); -} - -static void -IN_MLookRelease (void) +IN_MLookRelease (void *data) { KeyRelease (&in_mlook); if (!freelook && lookspring->int_val) @@ -179,187 +163,7 @@ IN_MLookRelease (void) } static void -IN_UpPress (void) -{ - KeyPress (&in_up); -} - -static void -IN_UpRelease (void) -{ - KeyRelease (&in_up); -} - -static void -IN_DownPress (void) -{ - KeyPress (&in_down); -} - -static void -IN_DownRelease (void) -{ - KeyRelease (&in_down); -} - -static void -IN_LeftPress (void) -{ - KeyPress (&in_left); -} - -static void -IN_LeftRelease (void) -{ - KeyRelease (&in_left); -} - -static void -IN_RightPress (void) -{ - KeyPress (&in_right); -} - -static void -IN_RightRelease (void) -{ - KeyRelease (&in_right); -} - -static void -IN_ForwardPress (void) -{ - KeyPress (&in_forward); -} - -static void -IN_ForwardRelease (void) -{ - KeyRelease (&in_forward); -} - -static void -IN_BackPress (void) -{ - KeyPress (&in_back); -} - -static void -IN_BackRelease (void) -{ - KeyRelease (&in_back); -} - -static void -IN_LookupPress (void) -{ - KeyPress (&in_lookup); -} - -static void -IN_LookupRelease (void) -{ - KeyRelease (&in_lookup); -} - -static void -IN_LookdownPress (void) -{ - KeyPress (&in_lookdown); -} - -static void -IN_LookdownRelease (void) -{ - KeyRelease (&in_lookdown); -} - -static void -IN_MoveleftPress (void) -{ - KeyPress (&in_moveleft); -} - -static void -IN_MoveleftRelease (void) -{ - KeyRelease (&in_moveleft); -} - -static void -IN_MoverightPress (void) -{ - KeyPress (&in_moveright); -} - -static void -IN_MoverightRelease (void) -{ - KeyRelease (&in_moveright); -} - -static void -IN_SpeedPress (void) -{ - KeyPress (&in_speed); -} - -static void -IN_SpeedRelease (void) -{ - KeyRelease (&in_speed); -} - -static void -IN_StrafePress (void) -{ - KeyPress (&in_strafe); -} - -static void -IN_StrafeRelease (void) -{ - KeyRelease (&in_strafe); -} - -static void -IN_AttackPress (void) -{ - KeyPress (&in_attack); -} - -static void -IN_AttackRelease (void) -{ - KeyRelease (&in_attack); -} - -static void -IN_UsePress (void) -{ - KeyPress (&in_use); -} - -static void -IN_UseRelease (void) -{ - KeyRelease (&in_use); -} - -static void -IN_JumpPress (void) -{ - KeyPress (&in_jump); -} - -static void -IN_JumpRelease (void) -{ - KeyRelease (&in_jump); -} - -static void -IN_Impulse (void) +IN_Impulse (void *data) { in_impulse = atoi (Cmd_Argv (1)); if (Cmd_Argc () <= 2) @@ -772,78 +576,88 @@ CL_SendCmd (void) void CL_Input_Init (void) { - Cmd_AddCommand ("+moveup", IN_UpPress, "When active the player is " - "swimming up in a liquid"); - Cmd_AddCommand ("-moveup", IN_UpRelease, "When active the player is not " - "swimming up in a liquid"); - Cmd_AddCommand ("+movedown", IN_DownPress, "When active the player is " - "swimming down in a liquid"); - Cmd_AddCommand ("-movedown", IN_DownRelease, "When active the player is " - "not swimming down in a liquid"); - Cmd_AddCommand ("+left", IN_LeftPress, "When active the player is turning " - "left"); - Cmd_AddCommand ("-left", IN_LeftRelease, "When active the player is not " - "turning left"); - Cmd_AddCommand ("+right", IN_RightPress, "When active the player is " - "turning right"); - Cmd_AddCommand ("-right", IN_RightRelease, "When active the player is not " - "turning right"); - Cmd_AddCommand ("+forward", IN_ForwardPress, "When active the player is " - "moving forward"); - Cmd_AddCommand ("-forward", IN_ForwardRelease, "When active the player is " - "not moving forward"); - Cmd_AddCommand ("+back", IN_BackPress, "When active the player is moving " - "backwards"); - Cmd_AddCommand ("-back", IN_BackRelease, "When active the player is not " - "moving backwards"); - Cmd_AddCommand ("+lookup", IN_LookupPress, "When active the player's view " - "is looking up"); - Cmd_AddCommand ("-lookup", IN_LookupRelease, "When active the player's " - "view is not looking up"); - Cmd_AddCommand ("+lookdown", IN_LookdownPress, "When active the player's " - "view is looking down"); - Cmd_AddCommand ("-lookdown", IN_LookdownRelease, "When active the " - "player's view is not looking up"); - Cmd_AddCommand ("+strafe", IN_StrafePress, "When active, +left and +right " - "function like +moveleft and +moveright"); - Cmd_AddCommand ("-strafe", IN_StrafeRelease, "When active, +left and " - "+right stop functioning like +moveleft and +moveright"); - Cmd_AddCommand ("+moveleft", IN_MoveleftPress, "When active the player is " - "strafing left"); - Cmd_AddCommand ("-moveleft", IN_MoveleftRelease, "When active the player " - "is not strafing left"); - Cmd_AddCommand ("+moveright", IN_MoverightPress, "When active the player " - "is strafing right"); - Cmd_AddCommand ("-moveright", IN_MoverightRelease, "When active the " - "player is not strafing right"); - Cmd_AddCommand ("+speed", IN_SpeedPress, "When active the player is " - "running"); - Cmd_AddCommand ("-speed", IN_SpeedRelease, "When active the player is not " - "running"); - Cmd_AddCommand ("+attack", IN_AttackPress, "When active player is " - "firing/using current weapon"); - Cmd_AddCommand ("-attack", IN_AttackRelease, "When active player is not " - "firing/using current weapon"); - Cmd_AddCommand ("+use", IN_UsePress, "Non-functional. Left over command " - "for opening doors and triggering switches"); - Cmd_AddCommand ("-use", IN_UseRelease, "Non-functional. Left over command " - "for opening doors and triggering switches"); - Cmd_AddCommand ("+jump", IN_JumpPress, "When active the player is " - "jumping"); - Cmd_AddCommand ("-jump", IN_JumpRelease, "When active the player is not " - "jumping"); - Cmd_AddCommand ("impulse", IN_Impulse, "Call a game function or QuakeC " - "function."); - Cmd_AddCommand ("+klook", IN_KLookPress, "When active, +forward and +back " - "perform +lookup and +lookdown"); - Cmd_AddCommand ("-klook", IN_KLookRelease, "When active, +forward and " - "+back don't perform +lookup and +lookdown"); - Cmd_AddCommand ("+mlook", IN_MLookPress, "When active moving the mouse or " - "joystick forwards and backwards performs +lookup and " - "+lookdown"); - Cmd_AddCommand ("-mlook", IN_MLookRelease, "When active moving the mouse " - "or joystick forwards and backwards doesn't perform " - "+lookup and +lookdown"); + Cmd_AddDataCommand ("+moveup", KeyPress, &in_up, + "When active the player is swimming up in a liquid"); + Cmd_AddDataCommand ("-moveup", KeyRelease, &in_up, + "When active the player is not swimming up in a " + "liquid"); + Cmd_AddDataCommand ("+movedown", KeyPress, &in_down, + "When active the player is swimming down in a liquid"); + Cmd_AddDataCommand ("-movedown", KeyRelease, &in_down, + "When active the player is not swimming down in a " + "liquid"); + Cmd_AddDataCommand ("+left", KeyPress, &in_left, + "When active the player is turning left"); + Cmd_AddDataCommand ("-left", KeyRelease, &in_left, + "When active the player is not turning left"); + Cmd_AddDataCommand ("+right", KeyPress, &in_right, + "When active the player is turning right"); + Cmd_AddDataCommand ("-right", KeyRelease, &in_right, + "When active the player is not turning right"); + Cmd_AddDataCommand ("+forward", KeyPress, &in_forward, + "When active the player is moving forward"); + Cmd_AddDataCommand ("-forward", KeyRelease, &in_forward, + "When active the player is not moving forward"); + Cmd_AddDataCommand ("+back", KeyPress, &in_back, + "When active the player is moving backwards"); + Cmd_AddDataCommand ("-back", KeyRelease, &in_back, + "When active the player is not moving backwards"); + Cmd_AddDataCommand ("+lookup", KeyPress, &in_lookup, + "When active the player's view is looking up"); + Cmd_AddDataCommand ("-lookup", KeyRelease, &in_lookup, + "When active the player's view is not looking up"); + Cmd_AddDataCommand ("+lookdown", KeyPress, &in_lookdown, + "When active the player's view is looking down"); + Cmd_AddDataCommand ("-lookdown", KeyRelease, &in_lookdown, + "When active the player's view is not looking up"); + Cmd_AddDataCommand ("+strafe", KeyPress, &in_strafe, + "When active, +left and +right function like " + "+moveleft and +moveright"); + Cmd_AddDataCommand ("-strafe", KeyRelease, &in_strafe, + "When active, +left and +right stop functioning like " + "+moveleft and +moveright"); + Cmd_AddDataCommand ("+moveleft", KeyPress, &in_moveleft, + "When active the player is strafing left"); + Cmd_AddDataCommand ("-moveleft", KeyRelease, &in_moveleft, + "When active the player is not strafing left"); + Cmd_AddDataCommand ("+moveright", KeyPress, &in_moveright, + "When active the player is strafing right"); + Cmd_AddDataCommand ("-moveright", KeyRelease, &in_moveright, + "When active the player is not strafing right"); + Cmd_AddDataCommand ("+speed", KeyPress, &in_speed, + "When active the player is running"); + Cmd_AddDataCommand ("-speed", KeyRelease, &in_speed, + "When active the player is not running"); + Cmd_AddDataCommand ("+attack", KeyPress, &in_attack, + "When active player is firing/using current weapon"); + Cmd_AddDataCommand ("-attack", KeyRelease, &in_attack, + "When active player is not firing/using current " + "weapon"); + Cmd_AddDataCommand ("+use", KeyPress, &in_use, + "Non-functional. Left over command for opening doors " + "and triggering switches"); + Cmd_AddDataCommand ("-use", KeyRelease, &in_use, + "Non-functional. Left over command for opening doors " + "and triggering switches"); + Cmd_AddDataCommand ("+jump", KeyPress, &in_jump, + "When active the player is jumping"); + Cmd_AddDataCommand ("-jump", KeyRelease, &in_jump, + "When active the player is not jumping"); + Cmd_AddDataCommand ("impulse", IN_Impulse, 0, + "Call a game function or QuakeC function."); + Cmd_AddDataCommand ("+klook", KeyPress, &in_klook, + "When active, +forward and +back perform +lookup and " + "+lookdown"); + Cmd_AddDataCommand ("-klook", KeyRelease, &in_klook, + "When active, +forward and +back don't perform " + "+lookup and +lookdown"); + Cmd_AddDataCommand ("+mlook", KeyPress, &in_mlook, + "When active moving the mouse or joystick forwards " + "and backwards performs +lookup and " + "+lookdown"); + Cmd_AddDataCommand ("-mlook", IN_MLookRelease, &in_mlook, + "When active moving the mouse or joystick forwards " + "and backwards doesn't perform +lookup and +lookdown"); } void From e3444b726f8f4ecd5320a793481e0c1e653f6c54 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 12:00:40 +0900 Subject: [PATCH 1387/3664] [model] Add a re-entrant Mod_LeafPVS Double benefit, actually: faster when building a fat PVS (don't need to copy as much) and can be used in multiple threads. Also, default visiblity can be set, and the buffer size has its own macro. --- include/QF/bspfile.h | 2 ++ include/QF/model.h | 7 ++++++- libs/models/brush/model_brush.c | 36 +++++++++++++++++++++------------ nq/source/sv_main.c | 2 +- nq/source/sv_pr_cmds.c | 2 +- qw/source/sv_ents.c | 2 +- qw/source/sv_pr_cmds.c | 2 +- tools/qfvis/source/qfvis.c | 2 +- 8 files changed, 36 insertions(+), 19 deletions(-) diff --git a/include/QF/bspfile.h b/include/QF/bspfile.h index 0d32c09e8..27648f297 100644 --- a/include/QF/bspfile.h +++ b/include/QF/bspfile.h @@ -42,6 +42,8 @@ #define MAX_MAP_FACES 65535 // format limit (u16) #define MAX_MAP_MARKSURFACES 65535 // format limit (u16) +#define MAP_PVS_BYTES (MAX_MAP_LEAFS / 8) + //============================================================================= #define BSPVERSION 29 diff --git a/include/QF/model.h b/include/QF/model.h index b65a5ad18..0a7069d3f 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -432,7 +432,12 @@ model_t *Mod_ForName (const char *name, qboolean crash); void Mod_TouchModel (const char *name); // brush specific mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure)); -byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model); +byte *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model); + +// NOTE: the buffer pointed to by out must be at least MAP_PVS_BYTES in size +void Mod_LeafPVS_r (const mleaf_t *leaf, const model_t *model, byte defvis, + byte *out); + void Mod_Print (void); extern struct cvar_s *gl_mesh_cache; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index b18de9076..6270de72b 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -55,7 +55,7 @@ #include "compat.h" #include "mod_internal.h" -static byte mod_novis[MAX_MAP_LEAFS / 8]; +static byte mod_novis[MAP_PVS_BYTES]; VISIBLE cvar_t *gl_sky_divide; //FIXME visibility? VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible? @@ -85,22 +85,21 @@ Mod_PointInLeaf (const vec3_t p, model_t *model) return NULL; // never reached } -static inline byte * -Mod_DecompressVis (byte * in, mod_brush_t *brush) +static inline void +Mod_DecompressVis (const byte *in, const mod_brush_t *brush, byte defvis, + byte *out) { - static byte decompressed[MAX_MAP_LEAFS / 8]; - byte *out; + byte *start = out; int row, c; row = (brush->numleafs + 7) >> 3; - out = decompressed; if (!in) { // no vis info, so make all visible while (row) { - *out++ = 0xff; + *out++ = defvis; row--; } - return decompressed; + return; } do { @@ -115,21 +114,32 @@ Mod_DecompressVis (byte * in, mod_brush_t *brush) *out++ = 0; c--; } - } while (out - decompressed < row); - - return decompressed; + } while (out - start < row); } VISIBLE byte * -Mod_LeafPVS (mleaf_t *leaf, model_t *model) +Mod_LeafPVS (const mleaf_t *leaf, const model_t *model) { + static byte decompressed[MAP_PVS_BYTES]; if (leaf == model->brush.leafs) { if (!mod_novis[0]) { memset (mod_novis, 0xff, sizeof (mod_novis)); } return mod_novis; } - return Mod_DecompressVis (leaf->compressed_vis, &model->brush); + Mod_DecompressVis (leaf->compressed_vis, &model->brush, 0xff, decompressed); + return decompressed; +} + +VISIBLE void +Mod_LeafPVS_r (const mleaf_t *leaf, const model_t *model, byte defvis, + byte *out) +{ + if (leaf == model->brush.leafs) { + memset (out, defvis, sizeof (mod_novis)); + return; + } + return Mod_DecompressVis (leaf->compressed_vis, &model->brush, defvis, out); } // BRUSHMODEL LOADING ========================================================= diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index d8a98b5b4..7d486f24b 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -389,7 +389,7 @@ SV_ClearDatagram (void) */ int fatbytes; -byte fatpvs[MAX_MAP_LEAFS / 8]; +byte fatpvs[MAP_PVS_BYTES]; static void SV_AddToFatPVS (vec3_t org, mnode_t *node) diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 096010f77..0489b4f4c 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -539,7 +539,7 @@ PF_checkpos (progs_t *pr) { } -byte checkpvs[MAX_MAP_LEAFS / 8]; +byte checkpvs[MAP_PVS_BYTES]; static int PF_newcheckclient (progs_t *pr, int check) diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index ccbf9278b..5538de54b 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -54,7 +54,7 @@ when the bob crosses a waterline. */ -byte fatpvs[MAX_MAP_LEAFS / 8]; +byte fatpvs[MAP_PVS_BYTES]; int fatbytes; diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index b8dc58de0..b30664a76 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -460,7 +460,7 @@ PF_checkpos (progs_t *pr) { } -byte checkpvs[MAX_MAP_LEAFS / 8]; +byte checkpvs[MAP_PVS_BYTES]; static int PF_newcheckclient (progs_t *pr, int check) diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 9ffb09e35..c62eabbcc 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -613,7 +613,7 @@ void ClusterFlow (int clusternum) { set_t *visclusters; - byte compressed[MAX_MAP_LEAFS / 8]; + byte compressed[MAP_PVS_BYTES]; byte *outbuffer; int numvis, i; cluster_t *cluster; From e0eacf401451860d86a32c3c54190f65d5adb1e1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 16:06:15 +0900 Subject: [PATCH 1388/3664] [model] Make set and mix versions of Mod_LeafPVS The re-entrant version was a good start, but being able to mix while decompressing saves having to have a temporary buffer somewhere. --- include/QF/model.h | 6 ++-- libs/models/brush/model_brush.c | 57 +++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 0a7069d3f..1c5969820 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -435,8 +435,10 @@ mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure)); byte *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model); // NOTE: the buffer pointed to by out must be at least MAP_PVS_BYTES in size -void Mod_LeafPVS_r (const mleaf_t *leaf, const model_t *model, byte defvis, - byte *out); +void Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, + byte *out); +void Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, + byte *out); void Mod_Print (void); diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 6270de72b..1e2fa81a4 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -86,8 +86,8 @@ Mod_PointInLeaf (const vec3_t p, model_t *model) } static inline void -Mod_DecompressVis (const byte *in, const mod_brush_t *brush, byte defvis, - byte *out) +Mod_DecompressVis_set (const byte *in, const mod_brush_t *brush, byte defvis, + byte *out) { byte *start = out; int row, c; @@ -117,6 +117,35 @@ Mod_DecompressVis (const byte *in, const mod_brush_t *brush, byte defvis, } while (out - start < row); } +static inline void +Mod_DecompressVis_mix (const byte *in, const mod_brush_t *brush, byte defvis, + byte *out) +{ + byte *start = out; + int row, c; + + row = (brush->numleafs + 7) >> 3; + + if (!in) { // no vis info, so make all visible + while (row) { + *out++ |= defvis; + row--; + } + return; + } + + do { + if (*in) { + *out++ |= *in++; + continue; + } + + c = in[1]; + in += 2; + out += c; + } while (out - start < row); +} + VISIBLE byte * Mod_LeafPVS (const mleaf_t *leaf, const model_t *model) { @@ -127,19 +156,35 @@ Mod_LeafPVS (const mleaf_t *leaf, const model_t *model) } return mod_novis; } - Mod_DecompressVis (leaf->compressed_vis, &model->brush, 0xff, decompressed); + Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, 0xff, + decompressed); return decompressed; } VISIBLE void -Mod_LeafPVS_r (const mleaf_t *leaf, const model_t *model, byte defvis, - byte *out) +Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, + byte *out) { if (leaf == model->brush.leafs) { memset (out, defvis, sizeof (mod_novis)); return; } - return Mod_DecompressVis (leaf->compressed_vis, &model->brush, defvis, out); + return Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, defvis, + out); +} + +VISIBLE void +Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, + byte *out) +{ + if (leaf == model->brush.leafs) { + for (int i = MAP_PVS_BYTES; i-- > 0; ) { + *out++ |= defvis; + } + return; + } + return Mod_DecompressVis_mix (leaf->compressed_vis, &model->brush, defvis, + out); } // BRUSHMODEL LOADING ========================================================= From bab3e0720f82be00deb828c4feb8c82b036f90a6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 16:08:44 +0900 Subject: [PATCH 1389/3664] [vulkan] Implement real-time lighting Light styles and shadows aren't implemented yet. The map's entities are used to create the lights, and the PVS used to determine which lights might be visible (ie, the surfaces they light). That could do with some more improvements (eg, checking if a leaf is outside a spotlight's cone), but the concept seems to work. --- include/QF/Vulkan/qf_lighting.h | 13 ++- libs/video/renderer/vulkan/qfpipeline.plist | 6 ++ .../renderer/vulkan/shader/lighting.frag | 10 +-- libs/video/renderer/vulkan/vulkan_lighting.c | 86 +++++++++++++++++-- libs/video/renderer/vulkan/vulkan_main.c | 2 +- 5 files changed, 104 insertions(+), 13 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index cd9e7d46c..c19f6ae80 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -46,8 +46,10 @@ typedef struct qfv_light_s { } qfv_light_t; typedef struct qfv_lightset_s DARRAY_TYPE (qfv_light_t) qfv_lightset_t; +typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightleafset_t; +typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t; -#define NUM_LIGHTS 128 +#define NUM_LIGHTS 256 typedef struct qfv_light_buffer_s { int lightCount; @@ -64,6 +66,11 @@ typedef struct lightingframe_s { VkDescriptorImageInfo imageInfo[LIGHTING_IMAGE_INFOS]; VkWriteDescriptorSet descriptors[LIGHTING_BUFFER_INFOS + LIGHTING_IMAGE_INFOS]; + // A fat PVS of leafs visible from visible leafs so hidden lights can + // illuminate the leafs visible to the player + byte pvs[MAP_PVS_BYTES]; + struct mleaf_s *leaf; // the last leaf used to generate the pvs + qfv_lightleafset_t lightvis; } lightingframe_t; typedef struct lightingframeset_s @@ -75,6 +82,7 @@ typedef struct lightingctx_s { VkPipelineLayout layout; VkDeviceMemory light_memory; qfv_lightset_t lights; + qfv_lightleafset_t lightleafs; } lightingctx_t; struct vulkan_ctx_s; @@ -82,6 +90,7 @@ struct vulkan_ctx_s; void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Draw (struct vulkan_ctx_s *ctx); -void Vulkan_LoadLights (const char *entity_data, struct vulkan_ctx_s *ctx); +void Vulkan_LoadLights (model_t *model, const char *entity_data, + struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_lighting_h diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 536c98a05..523edfbad 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -856,6 +856,12 @@ stage = fragment; name = main; module = $builtin/lighting.frag; + specializationInfo = { + mapEntries = ( + { size = 4; offset = 0; constantID = 0; }, + ); + data = <00000100>; + }; }, ); vertexInput = { diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 7468e4dec..c48f54a2f 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -26,15 +26,15 @@ vec3 calc_light (LightData light, vec3 position, vec3 normal) { vec3 dist = light.position - position; - vec3 incoming = normalize (dist); - float spotdot = -dot (incoming, light.direction); - float lightdot = dot (incoming, normal); float d = sqrt (dot (dist, dist)); + vec3 incoming = dist / d; + float spotdot = dot (incoming, light.direction); + float lightdot = dot (incoming, normal); float r = light.radius; float intensity = light.intensity * step (d, r); intensity *= step (spotdot, light.cone) * clamp (lightdot, 0, 1); - return light.color * intensity * (r - d); + return light.color * intensity * (r - d) / 255.0; } void @@ -44,7 +44,7 @@ main (void) vec3 c = subpassLoad (color).rgb; vec3 n = subpassLoad (normal).rgb; vec3 p = subpassLoad (position).rgb; - vec3 light = vec3 (0.8); + vec3 light = vec3 (0); if (MaxLights > 0) { for (int i = 0; i < lightCount; i++) { diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 07f0f9927..4df8475c7 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -61,6 +61,51 @@ #include "r_internal.h" #include "vid_vulkan.h" +static void +find_visible_lights (vulkan_ctx_t *ctx) +{ + //qfv_device_t *device = ctx->device; + //qfv_devfuncs_t *dfunc = device->funcs; + lightingctx_t *lctx = ctx->lighting_context; + lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; + + mleaf_t *leaf = r_viewleaf; + model_t *model = r_worldentity.renderer.model; + + if (!leaf || !model) { + return; + } + + if (leaf != lframe->leaf) { + double start = Sys_DoubleTime (); + byte pvs[MAP_PVS_BYTES]; + + Mod_LeafPVS_set (leaf, model, 0, pvs); + memcpy (lframe->pvs, pvs, sizeof (pvs)); + for (int i = 0; i < model->brush.numleafs; i++) { + if (pvs[i / 8] & (1 << (i % 8))) { + Mod_LeafPVS_mix (model->brush.leafs + i, model, 0, lframe->pvs); + } + } + lframe->leaf = leaf; + + double end = Sys_DoubleTime (); + Sys_Printf ("find_visible_lights: %.5gus\n", (end - start) * 1e6); + + int visible = 0; + memset (lframe->lightvis.a, 0, lframe->lightvis.size * sizeof (byte)); + for (size_t i = 0; i < lctx->lightleafs.size; i++) { + int l = lctx->lightleafs.a[i]; + if (lframe->pvs[l / 8] & (1 << (l % 8))) { + lframe->lightvis.a[i] = 1; + visible++; + } + } + Sys_Printf ("find_visible_lights: %d / %zd visible\n", visible, + lframe->lightvis.size); + } +} + static void update_lights (vulkan_ctx_t *ctx) { @@ -69,6 +114,8 @@ update_lights (vulkan_ctx_t *ctx) lightingctx_t *lctx = ctx->lighting_context; lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; + find_visible_lights (ctx); + dlight_t *lights[NUM_LIGHTS]; qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); qfv_light_buffer_t *light_data = QFV_PacketExtend (packet, @@ -88,6 +135,12 @@ update_lights (vulkan_ctx_t *ctx) VectorZero (light_data->lights[i].direction); light_data->lights[i].cone = 1; } + for (size_t i = 0; + i < lframe->lightvis.size && light_data->lightCount < NUM_LIGHTS; i++) { + if (lframe->lightvis.a[i]) { + light_data->lights[light_data->lightCount++] = lctx->lights.a[i]; + } + } VkBufferMemoryBarrier wr_barriers[] = { { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, @@ -208,6 +261,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) ctx->lighting_context = lctx; DARRAY_INIT (&lctx->lights, 16); + DARRAY_INIT (&lctx->lightleafs, 16); size_t frames = ctx->frames.size; DARRAY_INIT (&lctx->frames, frames); @@ -258,6 +312,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) for (size_t i = 0; i < frames; i++) { __auto_type lframe = &lctx->frames.a[i]; + DARRAY_INIT (&lframe->lightvis, 16); + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); lframe->cmd = cmdSet->a[0]; @@ -298,10 +354,12 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) for (size_t i = 0; i < lctx->frames.size; i++) { lightingframe_t *lframe = &lctx->frames.a[i]; dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0); + DARRAY_CLEAR (&lframe->lightvis); } dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0); dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0); DARRAY_CLEAR (&lctx->lights); + DARRAY_CLEAR (&lctx->lightleafs); free (lctx->frames.a); free (lctx); } @@ -312,6 +370,14 @@ parse_light (qfv_light_t *light, const plitem_t *entity, { const char *str; + Sys_Printf ("{\n"); + for (int i = PL_D_NumKeys (entity); i-- > 0; ) { + const char *field = PL_KeyAtIndex (entity, i); + const char *value = PL_String (PL_ObjectForKey (entity, field)); + Sys_Printf ("\t%s = %s\n", field, value); + } + Sys_Printf ("}\n"); + if ((str = PL_String (PL_ObjectForKey (entity, "origin")))) { sscanf (str, "%f %f %f", VectorExpandAddr (light->position)); } @@ -336,7 +402,7 @@ parse_light (qfv_light_t *light, const plitem_t *entity, } light->intensity = 1; - if ((str = PL_String (PL_ObjectForKey (entity, "light"))) + if ((str = PL_String (PL_ObjectForKey (entity, "light_lev"))) || (str = PL_String (PL_ObjectForKey (entity, "_light")))) { light->radius = atof (str); } @@ -345,12 +411,13 @@ parse_light (qfv_light_t *light, const plitem_t *entity, } void -Vulkan_LoadLights (const char *entity_data, vulkan_ctx_t *ctx) +Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) { lightingctx_t *lctx = ctx->lighting_context; plitem_t *entities = 0; lctx->lights.size = 0; + lctx->lightleafs.size = 0; script_t *script = Script_New (); Script_Start (script, "ent data", entity_data); @@ -389,13 +456,22 @@ Vulkan_LoadLights (const char *entity_data, vulkan_ctx_t *ctx) qfv_light_t light = {}; parse_light (&light, entity, targets); - printf ("[%g, %g, %g] %g, [%g %g %g] %g, [%g %g %g] %g\n", + DARRAY_APPEND (&lctx->lights, light); + mleaf_t *leaf = Mod_PointInLeaf (&light.position[0], + model); + DARRAY_APPEND (&lctx->lightleafs, leaf - model->brush.leafs); + printf ("[%g, %g, %g] %g, [%g %g %g] %g, [%g %g %g] %g, %zd\n", VectorExpand (light.color), light.intensity, VectorExpand (light.position), light.radius, - VectorExpand (light.direction), light.cone); - DARRAY_APPEND (&lctx->lights, light); + VectorExpand (light.direction), light.cone, + leaf - model->brush.leafs); } } + printf ("%zd frames\n", ctx->frames.size); + for (size_t i = 0; i < ctx->frames.size; i++) { + lightingframe_t *lframe = &lctx->frames.a[i]; + DARRAY_RESIZE (&lframe->lightvis, lctx->lights.size); + } // targets does not own the objects, so need to remove them before // freeing targets for (int i = PL_D_NumKeys (targets); i-- > 0; ) { diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index a7ed49669..bf1cd3ff2 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -216,7 +216,7 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, Vulkan_RegisterTextures (models, num_models, ctx); Vulkan_BuildLightmaps (models, num_models, ctx); Vulkan_BuildDisplayLists (models, num_models, ctx); - Vulkan_LoadLights (worldmodel->brush.entities, ctx); + Vulkan_LoadLights (worldmodel, worldmodel->brush.entities, ctx); } /*void From dccd6989b2d23358ee6b9e054d62ee6cd2d5ac0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 16:49:12 +0900 Subject: [PATCH 1390/3664] [vulkan] Implement gamma correction Currently hard-coded to 0.67 (1/1.5), but it does the job for now. --- libs/video/renderer/vulkan/shader/compose.frag | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vulkan/shader/compose.frag b/libs/video/renderer/vulkan/shader/compose.frag index 39ac94845..631737c67 100644 --- a/libs/video/renderer/vulkan/shader/compose.frag +++ b/libs/video/renderer/vulkan/shader/compose.frag @@ -15,5 +15,6 @@ main (void) o = subpassLoad (opaque).rgb; t = subpassLoad (translucent); c = mix (o, t.rgb, t.a); + c = pow (c, vec3(0.67));//FIXME make gamma correction configurable frag_color = vec4 (c, 1); } From 0246e559832a027344895613508215656a99b515 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 16:50:37 +0900 Subject: [PATCH 1391/3664] [vulkan] Support colored lights Now my dizzy map looks like it used to (more or less, possibly too dark, but I suspect I used some command-line settings to qflight). --- libs/video/renderer/vulkan/vulkan_lighting.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 4df8475c7..a9c50d27b 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -408,6 +408,10 @@ parse_light (qfv_light_t *light, const plitem_t *entity, } VectorSet (1, 1, 1, light->color); + if ((str = PL_String (PL_ObjectForKey (entity, "color"))) + || (str = PL_String (PL_ObjectForKey (entity, "_color")))) { + sscanf (str, "%f %f %f", VectorExpandAddr (light->color)); + } } void From cadea2757706b6d66c3a347030d803c02dabe8c0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 18:02:27 +0900 Subject: [PATCH 1392/3664] [vulkan] Disable lightmap support Hopefully, it won't be needed. --- libs/video/renderer/Makemodule.am | 1 - libs/video/renderer/vulkan/vulkan_bsp.c | 8 ++++---- libs/video/renderer/vulkan/vulkan_main.c | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 9eb2c2354..8c459dd1c 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -270,7 +270,6 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_compose.c \ libs/video/renderer/vulkan/vulkan_draw.c \ libs/video/renderer/vulkan/vulkan_lighting.c \ - libs/video/renderer/vulkan/vulkan_lightmap.c \ libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ libs/video/renderer/vulkan/vulkan_particles.c \ diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index f1ba6e472..937876dc9 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -202,7 +202,7 @@ Vulkan_ClearElements (vulkan_ctx_t *ctx) release_elechains (bctx); release_elementss (bctx); } - +/* static void update_lightmap (mod_brush_t *brush, msurface_t *surf, vulkan_ctx_t *ctx) { @@ -218,7 +218,7 @@ dynamic: Vulkan_BuildLightMap (brush, surf, ctx); } } - +*/ static inline void chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, float *color, vulkan_ctx_t *ctx) @@ -241,7 +241,7 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, tex = tx->render; CHAIN_SURF_F2B (surf, tex->tex_chain); - update_lightmap (brush, surf, ctx); + //update_lightmap (brush, surf, ctx); } if (!(is = surf->instsurf)) is = surf->tinst; @@ -1149,7 +1149,7 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) } } - Vulkan_FlushLightmaps (ctx); + //Vulkan_FlushLightmaps (ctx); bsp_begin (ctx); push_transform (identity, bctx->layout, dfunc, diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index bf1cd3ff2..3474b67ed 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -214,7 +214,7 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, R_FreeAllEntities (); Vulkan_ClearParticles (ctx); Vulkan_RegisterTextures (models, num_models, ctx); - Vulkan_BuildLightmaps (models, num_models, ctx); + //Vulkan_BuildLightmaps (models, num_models, ctx); Vulkan_BuildDisplayLists (models, num_models, ctx); Vulkan_LoadLights (worldmodel, worldmodel->brush.entities, ctx); } From 0a79348ce92eb8995bfc05e1e63c9cc42f75e817 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Mar 2021 19:15:06 +0900 Subject: [PATCH 1393/3664] [vulkan] Tweak the lighting to look a bit better Reduced the gamma correction a bit and increased the intensity of dynamic lights. Not sure the latter is correct, but it looks much better. --- libs/video/renderer/vulkan/shader/compose.frag | 2 +- libs/video/renderer/vulkan/shader/lighting.frag | 6 +++--- libs/video/renderer/vulkan/vulkan_lighting.c | 14 ++++++++------ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/compose.frag b/libs/video/renderer/vulkan/shader/compose.frag index 631737c67..542ba4c1b 100644 --- a/libs/video/renderer/vulkan/shader/compose.frag +++ b/libs/video/renderer/vulkan/shader/compose.frag @@ -15,6 +15,6 @@ main (void) o = subpassLoad (opaque).rgb; t = subpassLoad (translucent); c = mix (o, t.rgb, t.a); - c = pow (c, vec3(0.67));//FIXME make gamma correction configurable + c = pow (c, vec3(0.83));//FIXME make gamma correction configurable frag_color = vec4 (c, 1); } diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index c48f54a2f..b756dd879 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -33,8 +33,8 @@ calc_light (LightData light, vec3 position, vec3 normal) float r = light.radius; float intensity = light.intensity * step (d, r); - intensity *= step (spotdot, light.cone) * clamp (lightdot, 0, 1); - return light.color * intensity * (r - d) / 255.0; + intensity *= smoothstep (spotdot, 1 - (1 - spotdot) * 0.995, light.cone) * clamp (lightdot, 0, 1); + return light.color * intensity * (r - d); } void @@ -51,5 +51,5 @@ main (void) light += calc_light (lights[i], p, n); } } - frag_color = vec4 (c * light, 1); + frag_color = vec4 (c * light / 255.0, 1); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index a9c50d27b..bac1843c7 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -131,7 +131,7 @@ update_lights (vulkan_ctx_t *ctx) VectorCopy (lights[i]->color, light_data->lights[i].color); VectorCopy (lights[i]->origin, light_data->lights[i].position); light_data->lights[i].radius = lights[i]->radius; - light_data->lights[i].intensity = 1; + light_data->lights[i].intensity = 16; VectorZero (light_data->lights[i].direction); light_data->lights[i].cone = 1; } @@ -370,19 +370,23 @@ parse_light (qfv_light_t *light, const plitem_t *entity, { const char *str; - Sys_Printf ("{\n"); + /*Sys_Printf ("{\n"); for (int i = PL_D_NumKeys (entity); i-- > 0; ) { const char *field = PL_KeyAtIndex (entity, i); const char *value = PL_String (PL_ObjectForKey (entity, field)); Sys_Printf ("\t%s = %s\n", field, value); } - Sys_Printf ("}\n"); + Sys_Printf ("}\n");*/ + + light->cone = 1; + light->intensity = 1; + light->radius = 300; + VectorSet (1, 1, 1, light->color); if ((str = PL_String (PL_ObjectForKey (entity, "origin")))) { sscanf (str, "%f %f %f", VectorExpandAddr (light->position)); } - light->cone = 1; if ((str = PL_String (PL_ObjectForKey (entity, "target")))) { vec3_t position = {}; plitem_t *target = PL_ObjectForKey (targets, str); @@ -401,13 +405,11 @@ parse_light (qfv_light_t *light, const plitem_t *entity, light->cone = -cos (angle * M_PI / 360); // half angle } - light->intensity = 1; if ((str = PL_String (PL_ObjectForKey (entity, "light_lev"))) || (str = PL_String (PL_ObjectForKey (entity, "_light")))) { light->radius = atof (str); } - VectorSet (1, 1, 1, light->color); if ((str = PL_String (PL_ObjectForKey (entity, "color"))) || (str = PL_String (PL_ObjectForKey (entity, "_color")))) { sscanf (str, "%f %f %f", VectorExpandAddr (light->color)); From 7650df340018480e52358e5ef456b897bcb73713 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 10:08:44 +0900 Subject: [PATCH 1394/3664] [model] Handle brush models with empty texture slots It seems some maps have some empty texture slots (eg, e1m2). --- libs/models/brush/model_brush.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 1e2fa81a4..a2f02a322 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -274,7 +274,9 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) mod->name); } for (i = 0; i < m->nummiptex; i++) { - tx = brush->textures[i]; + if (!(tx = brush->textures[i])) { + continue; + } tx->render = render_data; render_data += render_size; mod_funcs->Mod_ProcessTexture (mod, tx); From 9e633e7230f1118fe2f60a0c1c07a1468e3b30ef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 10:11:53 +0900 Subject: [PATCH 1395/3664] [qflight] Remove minlights It seems to be have been DOA (even in the original qutils light). --- tools/qflight/include/light.h | 2 -- tools/qflight/source/ltface.c | 34 ---------------------------------- tools/qflight/source/qflight.c | 3 --- 3 files changed, 39 deletions(-) diff --git a/tools/qflight/include/light.h b/tools/qflight/include/light.h index 350b7e442..f558f594d 100644 --- a/tools/qflight/include/light.h +++ b/tools/qflight/include/light.h @@ -97,8 +97,6 @@ extern vec3_t bsp_yvector; extern qboolean extrasamples; -extern float minlights[MAX_MAP_FACES]; - void LoadNodes (const char *file); qboolean TestLine (lightinfo_t *l, const vec3_t start, const vec3_t stop); qboolean TestSky (lightinfo_t *l, const vec3_t start, const vec3_t stop); diff --git a/tools/qflight/source/ltface.c b/tools/qflight/source/ltface.c index 2b8eb1953..de947cfff 100644 --- a/tools/qflight/source/ltface.c +++ b/tools/qflight/source/ltface.c @@ -508,38 +508,6 @@ SkyLightFace (entity_t *ent, int sun, lightinfo_t *l) } } -#if 0 -static void -FixMinlight (lightinfo_t *l) -{ - float minlight; - int i, j; - - minlight = minlights[l->surfnum]; - - // if minlight is set, there must be a style 0 light map - if (!minlight) - return; - - for (i = 0; i < l->numlightstyles; i++) { - if (l->lightstyles[i] == 0) - break; - } - if (i == l->numlightstyles) { - if (l->numlightstyles == MAXLIGHTMAPS) - return; // oh well.. - for (j = 0; j < l->numsurfpt; j++) - l->lightmaps[i][j] = minlight; - l->lightstyles[i] = 0; - l->numlightstyles++; - } else { - for (j = 0; j < l->numsurfpt; j++) - if (l->lightmaps[i][j] < minlight) - l->lightmaps[i][j] = minlight; - } -} -#endif - void LightFace (lightinfo_t *l, int surfnum) { @@ -590,8 +558,6 @@ LightFace (lightinfo_t *l, int surfnum) SkyLightFace (world_entity, i, l); } -// FixMinlight (&l); - for (i = 0; i < MAXLIGHTMAPS; i++) if (l->lightstyles[i] == 255) break; diff --git a/tools/qflight/source/qflight.c b/tools/qflight/source/qflight.c index 75b9941d7..db133a3b4 100644 --- a/tools/qflight/source/qflight.c +++ b/tools/qflight/source/qflight.c @@ -78,9 +78,6 @@ vec3_t bsp_origin; qboolean extrasamples; -float minlights[MAX_MAP_FACES]; - - int GetFileSpace (int size) { From 6e0cc59e8f558157eeda21f0491c7229a95038c0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 11:36:18 +0900 Subject: [PATCH 1396/3664] [util] Make wad lump failure a soft error Can't recover from an error if the program is swept out from underneath you. --- libs/util/wad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/wad.c b/libs/util/wad.c index 3b4355bbb..ffb5414d3 100644 --- a/libs/util/wad.c +++ b/libs/util/wad.c @@ -118,7 +118,7 @@ W_GetLumpinfo (const char *name) return lump_p; } - Sys_Error ("W_GetLumpinfo: %s not found", name); + Sys_MaskPrintf (SYS_WARN, "W_GetLumpinfo: %s not found", name); return NULL; } From 66e66277804bc93cd8efba0415bf9b3decf1ea5a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 11:37:36 +0900 Subject: [PATCH 1397/3664] [vulkan] Use the correct character data I got tired of not being able to read 90% of quake's output :P --- libs/video/renderer/vulkan/vulkan_draw.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 4b962edd6..12b3cd11b 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -383,10 +383,20 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->stage); dctx->sampler = Vulkan_CreateSampler (ctx, "quakepic"); - qpic_t *charspic = Draw_Font8x8Pic (); + draw_chars = W_GetLumpName ("conchars"); + if (draw_chars) { + for (int i = 0; i < 256 * 64; i++) { + if (draw_chars[i] == 0) { + draw_chars[i] = 255; // proper transparent color + } + } + dctx->conchars = pic_data ("conchars", 128, 128, draw_chars, dctx); + } else { + qpic_t *charspic = Draw_Font8x8Pic (); + dctx->conchars = pic_data ("conchars", charspic->width, + charspic->height, charspic->data, dctx); + } - dctx->conchars = pic_data ("conchars", charspic->width, charspic->height, - charspic->data, dctx); byte white_block = 0xfe; dctx->white_pic = pic_data ("white", 1, 1, &white_block, dctx); From a3c1b2e992efbf46fe68025083117d0c0d897587 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 16:13:03 +0900 Subject: [PATCH 1398/3664] [util] Rename qfplist.[ch] The name is a hold-over from before the current quakeforge tree and the QF include directory. --- include/QF/{qfplist.h => plist.h} | 10 +++++----- libs/audio/cd_file.c | 2 +- libs/gamecode/pr_parse.c | 2 +- libs/ruamoko/rua_plist.c | 2 +- libs/util/Makemodule.am | 2 +- libs/util/cexpr-lex.l | 2 +- libs/util/cexpr-parse.y | 2 +- libs/util/cexpr-type.c | 2 +- libs/util/{qfplist.c => plist.c} | 4 ++-- libs/util/quakefs.c | 2 +- libs/util/test/test-plist.c | 2 +- libs/video/renderer/gl/gl_fog.c | 2 +- libs/video/renderer/glsl/glsl_fog.c | 2 +- libs/video/renderer/vulkan/scrap.c | 1 - libs/video/renderer/vulkan/shader.c | 1 - libs/video/renderer/vulkan/staging.c | 1 - libs/video/renderer/vulkan/vkparse.c | 2 +- libs/video/renderer/vulkan/vkparse.h | 2 +- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- libs/video/renderer/vulkan/vulkan_texture.c | 1 - libs/video/renderer/vulkan/vulkan_vid_common.c | 2 +- nq/source/cl_ents.c | 2 +- nq/source/cl_main.c | 2 +- nq/source/cl_parse.c | 2 +- nq/source/host_cmd.c | 2 +- qw/source/cl_parse.c | 2 +- tools/qflight/source/entities.c | 2 +- tools/qflight/source/properties.c | 2 +- 28 files changed, 29 insertions(+), 33 deletions(-) rename include/QF/{qfplist.h => plist.h} (99%) rename libs/util/{qfplist.c => plist.c} (99%) diff --git a/include/QF/qfplist.h b/include/QF/plist.h similarity index 99% rename from include/QF/qfplist.h rename to include/QF/plist.h index a4994476d..b14b5e4aa 100644 --- a/include/QF/qfplist.h +++ b/include/QF/plist.h @@ -1,5 +1,5 @@ /* - qfplist.h + plist.h Property list management types and prototypes @@ -25,12 +25,12 @@ */ -#ifndef __QF_qfplist_h -#define __QF_qfplist_h +#ifndef __QF_plist_h +#define __QF_plist_h struct hashlink_s; -/** \defgroup qfplist Property lists +/** \defgroup plist Property lists \ingroup utils */ ///@{ @@ -505,4 +505,4 @@ PL_Message (plitem_t *messages, const plitem_t *item, const char *fmt, ...); ///@} -#endif//__QF_qfplist_h +#endif//__QF_plist_h diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index 5ffe88290..8f236ec5e 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -53,8 +53,8 @@ #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/dstring.h" +#include "QF/plist.h" #include "QF/qargs.h" -#include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/quakeio.h" #include "QF/sound.h" diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index b33d14e6c..08f394844 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -45,8 +45,8 @@ #include "QF/dstring.h" #include "QF/mathlib.h" +#include "QF/plist.h" #include "QF/progs.h" -#include "QF/qfplist.h" #include "QF/script.h" #include "QF/sys.h" diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index ce5030e5c..d8b3c0da1 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -40,8 +40,8 @@ #include #include "QF/hash.h" +#include "QF/plist.h" #include "QF/progs.h" -#include "QF/qfplist.h" #include "rua_internal.h" diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am index d2ad47b0c..95ce152b9 100644 --- a/libs/util/Makemodule.am +++ b/libs/util/Makemodule.am @@ -64,10 +64,10 @@ libs_util_libQFutil_la_SOURCES= \ libs/util/mersenne.c \ libs/util/msg.c \ libs/util/pakfile.c \ + libs/util/plist.c \ libs/util/plugin.c \ libs/util/qargs.c \ libs/util/qendian.c \ - libs/util/qfplist.c \ libs/util/quakefs.c \ libs/util/quakeio.c \ libs/util/riff.c \ diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index b82724af4..3fafef8e6 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -47,7 +47,7 @@ #include "QF/cmem.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/sys.h" #define CEXPR_YYDEBUG 1 diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index 4c57c98c0..fca9171af 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -46,7 +46,7 @@ #include "QF/cmem.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/sys.h" #include "QF/cexpr.h" diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 2aff20006..7ee34f5c2 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -32,7 +32,7 @@ #include "QF/cexpr.h" #include "QF/cmem.h" #include "QF/mathlib.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/simd/vec4f.h" #include "libs/util/cexpr-parse.h" diff --git a/libs/util/qfplist.c b/libs/util/plist.c similarity index 99% rename from libs/util/qfplist.c rename to libs/util/plist.c index 454c549f7..e41960398 100644 --- a/libs/util/qfplist.c +++ b/libs/util/plist.c @@ -1,5 +1,5 @@ /* - qfplist.c + plist.c Property list management @@ -41,7 +41,7 @@ #include "QF/darray.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/qtypes.h" #include "QF/sys.h" #include "QF/va.h" diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 569fab341..9e7c2dc63 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -82,9 +82,9 @@ #include "QF/mathlib.h" #include "QF/pak.h" #include "QF/pakfile.h" +#include "QF/plist.h" #include "QF/qargs.h" #include "QF/qendian.h" -#include "QF/qfplist.h" #include "QF/qtypes.h" #include "QF/quakefs.h" #include "QF/sys.h" diff --git a/libs/util/test/test-plist.c b/libs/util/test/test-plist.c index bc8e0457a..d3ce32715 100644 --- a/libs/util/test/test-plist.c +++ b/libs/util/test/test-plist.c @@ -2,7 +2,7 @@ # include "config.h" #endif #include -#include "QF/qfplist.h" +#include "QF/plist.h" static const char *test_strings[] = { "Guarding the entrance to the Grendal\n" diff --git a/libs/video/renderer/gl/gl_fog.c b/libs/video/renderer/gl/gl_fog.c index b8747e37b..0b74d0b80 100644 --- a/libs/video/renderer/gl/gl_fog.c +++ b/libs/video/renderer/gl/gl_fog.c @@ -34,7 +34,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #include "QF/cmd.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/render.h" #include "QF/sys.h" diff --git a/libs/video/renderer/glsl/glsl_fog.c b/libs/video/renderer/glsl/glsl_fog.c index 8118b8497..82777061e 100644 --- a/libs/video/renderer/glsl/glsl_fog.c +++ b/libs/video/renderer/glsl/glsl_fog.c @@ -34,7 +34,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #include "QF/cmd.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/render.h" #include "QF/sys.h" diff --git a/libs/video/renderer/vulkan/scrap.c b/libs/video/renderer/vulkan/scrap.c index 01eed4bf8..ab053bf10 100644 --- a/libs/video/renderer/vulkan/scrap.c +++ b/libs/video/renderer/vulkan/scrap.c @@ -43,7 +43,6 @@ #include "QF/dstring.h" #include "QF/hash.h" #include "QF/image.h" -#include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/render.h" #include "QF/sys.h" diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 4168d9b63..d2921faca 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -42,7 +42,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/Vulkan/qf_vid.h" diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 759962c4d..28ea169a7 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -42,7 +42,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/Vulkan/qf_vid.h" diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index de12d60c0..3a9e98411 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -45,8 +45,8 @@ #include "QF/hash.h" #include "QF/input.h" #include "QF/mathlib.h" +#include "QF/plist.h" #include "QF/qargs.h" -#include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/va.h" diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 2550e1b17..4f258a96f 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -9,7 +9,7 @@ typedef struct parsectx_s { } parsectx_t; #include "QF/cexpr.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/Vulkan/renderpass.h" #ifdef vkparse_internal #include "libs/video/renderer/vulkan/vkparse.hinc" diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index bac1843c7..01df24722 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -42,8 +42,8 @@ #include "qfalloca.h" #include "QF/dstring.h" +#include "QF/plist.h" #include "QF/progs.h" -#include "QF/qfplist.h" #include "QF/script.h" #include "QF/sys.h" #include "QF/va.h" diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 7d8b13155..7d975298d 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -44,7 +44,6 @@ #include "QF/hash.h" #include "QF/image.h" #include "QF/mathlib.h" -#include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/render.h" #include "QF/sys.h" diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 909f26236..8c3c975ef 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -45,8 +45,8 @@ #include "QF/hash.h" #include "QF/input.h" #include "QF/mathlib.h" +#include "QF/plist.h" #include "QF/qargs.h" -#include "QF/qfplist.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/va.h" diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 2e04ff885..d2cab9909 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -36,7 +36,7 @@ #include "QF/input.h" #include "QF/keys.h" #include "QF/msg.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/render.h" #include "QF/screen.h" #include "QF/skin.h" diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index e52eb5fea..75b4f72ea 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -39,7 +39,7 @@ #include "QF/joystick.h" #include "QF/keys.h" #include "QF/msg.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/render.h" #include "QF/screen.h" #include "QF/skin.h" diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 30e48e82a..d2b5e0b2b 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -45,7 +45,7 @@ #include "QF/idparse.h" #include "QF/input.h" #include "QF/msg.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/sys.h" #include "QF/screen.h" #include "QF/skin.h" diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index c7e138f23..1ef9fcf41 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -44,7 +44,7 @@ #include "QF/keys.h" #include "QF/model.h" #include "QF/msg.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/screen.h" #include "QF/script.h" #include "QF/sys.h" diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index b7a293f28..4f0c93475 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -52,7 +52,7 @@ #include "QF/idparse.h" #include "QF/msg.h" #include "QF/progs.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/quakeio.h" #include "QF/screen.h" #include "QF/skin.h" diff --git a/tools/qflight/source/entities.c b/tools/qflight/source/entities.c index d3c608f6f..8c2260fcd 100644 --- a/tools/qflight/source/entities.c +++ b/tools/qflight/source/entities.c @@ -47,8 +47,8 @@ #include "QF/bspfile.h" #include "QF/dstring.h" #include "QF/mathlib.h" +#include "QF/plist.h" #include "QF/progs.h" -#include "QF/qfplist.h" #include "QF/qtypes.h" #include "QF/quakefs.h" #include "QF/script.h" diff --git a/tools/qflight/source/properties.c b/tools/qflight/source/properties.c index c9297984b..87229d05d 100644 --- a/tools/qflight/source/properties.c +++ b/tools/qflight/source/properties.c @@ -41,7 +41,7 @@ #include #include "QF/mathlib.h" -#include "QF/qfplist.h" +#include "QF/plist.h" #include "QF/quakeio.h" #include "compat.h" From cc4167668c306fa06b6e742dc3d52ed55c00e3fb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 19:56:17 +0900 Subject: [PATCH 1399/3664] Fix a pile of leaks and uninit errors Still "some" more to go: a pile to do with transforms and temporary entities, and a nasty one with host_cbuf. There's also all the static block-alloc lists :/ --- include/QF/Vulkan/qf_lighting.h | 2 +- include/QF/progs.h | 1 + libs/audio/cd_file.c | 1 + libs/audio/renderer/vorbis.c | 1 + libs/client/cl_temp_entities.c | 13 +- libs/gamecode/pr_builtins.c | 6 + libs/models/alias/model_alias.c | 3 + libs/models/brush/vulkan_model_brush.c | 1 + libs/util/plist.c | 1 + libs/util/quakefs.c | 22 ++- libs/video/renderer/vulkan/instance.c | 3 + libs/video/renderer/vulkan/vkparse.c | 154 +++++++++++------- libs/video/renderer/vulkan/vulkan_lighting.c | 11 +- .../video/renderer/vulkan/vulkan_vid_common.c | 6 + libs/video/targets/context_x11.c | 4 +- libs/video/targets/keys.c | 5 + 16 files changed, 153 insertions(+), 81 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index c19f6ae80..c269feaae 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -70,7 +70,7 @@ typedef struct lightingframe_s { // illuminate the leafs visible to the player byte pvs[MAP_PVS_BYTES]; struct mleaf_s *leaf; // the last leaf used to generate the pvs - qfv_lightleafset_t lightvis; + qfv_lightvisset_t lightvis; } lightingframe_t; typedef struct lightingframeset_s diff --git a/include/QF/progs.h b/include/QF/progs.h index 89fa5d181..498303c25 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1782,6 +1782,7 @@ struct progs_s { ///@{ struct hashtab_s *builtin_hash; struct hashtab_s *builtin_num_hash; + struct biblock_s *builtin_blocks; unsigned bi_next; unsigned (*bi_map) (progs_t *pr, unsigned binum); ///@} diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index 8f236ec5e..0e26a803a 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -172,6 +172,7 @@ Load_Tracklist (void) buffile = calloc (size+10, sizeof (char)); Qread (oggfile, buffile, size); + PL_Free (tracklist); tracklist = PL_GetPropertyList (buffile, 0); if (!tracklist || PL_Type (tracklist) != QFDictionary) { Sys_Printf ("Malformed or empty tracklist file. check mus_ogglist\n"); diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index fd14ec965..1c346a146 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -249,6 +249,7 @@ vorbis_stream_close (sfx_t *sfx) if (vf->data) free (vf->data); ov_clear (vf->vf); + free (vf->vf); free (vf); SND_SFX_StreamClose (sfx); } diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 03fab9b73..11ae7632d 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -317,12 +317,13 @@ CL_ParseBeam (qmsg_t *net_message, model_t *m, double time, TEntContext_t *ctx) tent_obj_t *to; beam_t *b; int ent; - vec3_t start, end; + vec4f_t start, end; ent = MSG_ReadShort (net_message); - MSG_ReadCoordV (net_message, start); - MSG_ReadCoordV (net_message, end); + MSG_ReadCoordV (net_message, &start[0]);//FIXME + MSG_ReadCoordV (net_message, &end[0]);//FIXME + start[3] = end[3] = 1;//FIXME to = 0; if (ent) { @@ -345,10 +346,10 @@ CL_ParseBeam (qmsg_t *net_message, model_t *m, double time, TEntContext_t *ctx) b->model = m; b->endtime = time + 0.2; b->seed = rand (); - VectorCopy (end, b->end); + b->end = end; if (b->entity != ctx->playerEntity) { // this will be done in CL_UpdateBeams - VectorCopy (start, b->start); + b->start = start; beam_setup (b, true, time, ctx); } } @@ -626,7 +627,7 @@ CL_UpdateBeams (double time, TEntContext_t *ctx) // if coming from the player, update the start position if (b->entity == ctx->playerEntity) { beam_clear (b); - VectorCopy (ctx->simorg, b->start); + b->start = ctx->simorg; beam_setup (b, false, time, ctx); } diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index 6d738e6bc..ab159e250 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -40,6 +40,7 @@ #include "QF/cmd.h" #include "QF/crc.h" #include "QF/cvar.h" +#include "QF/darray.h" #include "QF/hash.h" #include "QF/progs.h" #include "QF/qdefs.h" @@ -50,6 +51,8 @@ #include "compat.h" +typedef struct biblock_s DARRAY_TYPE (builtin_t *) biblock_t; + static const char * builtin_get_key (const void *_bi, void *unused) { @@ -92,6 +95,8 @@ PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins) int count; if (!pr->builtin_hash) { + pr->builtin_blocks = malloc (sizeof (biblock_t)); + DARRAY_INIT (pr->builtin_blocks, 16); pr->builtin_hash = Hash_NewTable (1021, builtin_get_key, 0, pr, pr->hashlink_freelist); pr->builtin_num_hash = Hash_NewTable (1021, 0, 0, pr, @@ -104,6 +109,7 @@ PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins) for (bi = builtins, count = 1; bi->name; bi++) count++; bi = malloc (count * sizeof (builtin_t)); + DARRAY_APPEND (pr->builtin_blocks, bi); memcpy (bi, builtins, count * sizeof (builtin_t)); builtins = bi; diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index 727957fe5..583df43fa 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -387,4 +387,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) } else { mod->aliashdr = header; } + DARRAY_CLEAR (&alias_ctx.poseverts); + DARRAY_CLEAR (&alias_ctx.stverts); + DARRAY_CLEAR (&alias_ctx.triangles); } diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 55eacb90b..2248ccdaf 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -326,6 +326,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) barriers->size, barriers->a); QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); + free (barriers); } void diff --git a/libs/util/plist.c b/libs/util/plist.c index e41960398..b731f982f 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -223,6 +223,7 @@ PL_Free (plitem_t *item) dict = item->data; Hash_DelTable (dict->tab); DARRAY_CLEAR (&dict->keys); + free (item->data); break; case QFArray: diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 9e7c2dc63..e209d460a 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -252,12 +252,11 @@ static void delete_searchpath (searchpath_t *searchpath) { if (searchpath->pack) { - Qclose (searchpath->pack->handle); - free (searchpath->pack->files); - free (searchpath->pack); + pack_del (searchpath->pack); } - if (searchpath->filename) + if (searchpath->filename) { free (searchpath->filename); + } FREE (searchpaths, searchpath); } @@ -274,8 +273,9 @@ delete_vpath (vpath_t *vpath) { searchpath_t *next; - if (vpath->name) + if (vpath->name) { free (vpath->name); + } while (vpath->user) { next = vpath->user->next; delete_searchpath (vpath->user); @@ -859,6 +859,7 @@ qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, found.ff.realname = strdup (*fn); found.path = strdup (path->str); found.fname_index = fn - fnames; + dstring_delete (path); return &found; } } @@ -1416,6 +1417,16 @@ qfs_path_cvar (cvar_t *var) free (cpath); } +static void +qfs_shutdown (void *data) +{ + while (qfs_vpaths) { + vpath_t *next = qfs_vpaths->next; + delete_vpath (qfs_vpaths); + qfs_vpaths = next; + } +} + VISIBLE void QFS_Init (const char *game) { @@ -1465,6 +1476,7 @@ QFS_Init (const char *game) } else { QFS_Gamedir (""); } + Sys_RegisterShutdown (qfs_shutdown, 0); } VISIBLE const char * diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index d1c845c6b..f50ec526b 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -285,11 +285,14 @@ void QFV_DestroyInstance (qfv_instance_t *instance) { qfv_instfuncs_t *ifunc = instance->funcs; + if (instance->debug_handle) { ifunc->vkDestroyDebugUtilsMessengerEXT (instance->instance, instance->debug_handle, 0); } instance->funcs->vkDestroyInstance (instance->instance, 0); + del_strset (instance->enabled_extensions); + free (instance->devices); free (instance); } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 3a9e98411..382d04873 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -252,6 +252,13 @@ parse_reference (const plitem_t *item, const char *type, plitem_t *messages, return refItem; } +static void * +vkparse_alloc (void *context, size_t size) +{ + parsectx_t *pctx = context; + return cmemalloc (pctx->ectx->memsuper, size); +} + static int parse_single (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -269,9 +276,9 @@ parse_single (const plfield_t *field, const plitem_t *item, } plfield_t f = { 0, 0, single->type, single->parser, 0 }; - void *value = calloc (1, single->stride); + void *value = vkparse_alloc (context, single->stride); + memset (value, 0, single->stride); if (!single->parser (&f, item, value, messages, context)) { - free (value); return 0; } @@ -279,12 +286,6 @@ parse_single (const plfield_t *field, const plitem_t *item, return 1; } -static void * -array_alloc (void *context, size_t size) -{ - return malloc (size); -} - static int parse_array (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -296,7 +297,7 @@ parse_array (const plfield_t *field, const plitem_t *item, plelement_t element = { array->type, array->stride, - array_alloc, + vkparse_alloc, array->parser, 0, }; @@ -313,12 +314,11 @@ parse_array (const plfield_t *field, const plitem_t *item, if (!PL_ParseArray (&f, item, &arr, messages, context)) { return 0; } - *value = malloc (array->stride * arr->size); + *value = vkparse_alloc (context, array->stride * arr->size); memcpy (*value, arr->a, array->stride * arr->size); if ((void *) size >= data) { *size = arr->size; } - free (arr); return 1; } @@ -339,7 +339,7 @@ parse_data (const plfield_t *field, const plitem_t *item, Sys_Printf (" %zd %zd\n", datad->value_offset, datad->size_offset); Sys_Printf (" %zd %p\n", binsize, bindata); - *value = malloc (binsize); + *value = vkparse_alloc (context, binsize); memcpy (*value, bindata, binsize); if ((void *) size > data) { *size = binsize; @@ -362,7 +362,9 @@ parse_string (const plfield_t *field, const plitem_t *item, //Sys_Printf (" %zd\n", string->value_offset); //Sys_Printf (" %s\n", str); - *value = strdup (str); + size_t len = strlen (str) + 1; + *value = vkparse_alloc (context, len); + memcpy (*value, str, len); return 1; } @@ -877,7 +879,7 @@ typedef struct qfv_renderpass_s { static plelement_t parse_qfv_renderpass_attachments_data = { QFDictionary, sizeof (VkAttachmentDescription), - array_alloc, + vkparse_alloc, parse_VkAttachmentDescription, 0, }; @@ -885,7 +887,7 @@ static plelement_t parse_qfv_renderpass_attachments_data = { static plelement_t parse_qfv_renderpass_subpasses_data = { QFDictionary, sizeof (VkSubpassDescription), - array_alloc, + vkparse_alloc, parse_VkSubpassDescription, 0, }; @@ -893,7 +895,7 @@ static plelement_t parse_qfv_renderpass_subpasses_data = { static plelement_t parse_qfv_renderpass_dependencies_data = { QFDictionary, sizeof (VkSubpassDependency), - array_alloc, + vkparse_alloc, parse_VkSubpassDependency, 0, }; @@ -953,7 +955,7 @@ QFV_GetEnum (const char *name) } static int -parse_object (vulkan_ctx_t *ctx, plitem_t *plist, +parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, plparser_t parser, void *object, plitem_t *properties) { plitem_t *messages = PL_NewArray (); @@ -970,9 +972,9 @@ parse_object (vulkan_ctx_t *ctx, plitem_t *plist, exprtab_t vars_tab = { var_syms, 0 }; exprctx.external_variables = &vars_tab; - exprctx.memsuper = new_memsuper (); exprctx.messages = messages; exprctx.hashlinks = &ctx->hashlinks; + exprctx.memsuper = memsuper; cexpr_init_symtab (&vars_tab, &exprctx); @@ -983,8 +985,8 @@ parse_object (vulkan_ctx_t *ctx, plitem_t *plist, } return 0; } + Hash_DelTable (vars_tab.tab); PL_Free (messages); - delete_memsuper (exprctx.memsuper); return 1; } @@ -999,12 +1001,14 @@ parse_qfv_renderpass (const plfield_t *field, const plitem_t *item, void *data, VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { + memsuper_t *memsuper = new_memsuper (); qfv_device_t *device = ctx->device; qfv_renderpass_t renderpass_data = {}; - if (!parse_object (ctx, plist, parse_qfv_renderpass, &renderpass_data, - properties)) { + if (!parse_object (ctx, memsuper, plist, parse_qfv_renderpass, + &renderpass_data, properties)) { + delete_memsuper (memsuper); return 0; } @@ -1014,29 +1018,22 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) renderpass_data.subpasses, renderpass_data.dependencies); - free (renderpass_data.attachments); - for (size_t i = 0; i < renderpass_data.subpasses->size; i++) { - free ((void *) renderpass_data.subpasses->a[i].pInputAttachments); - free ((void *) renderpass_data.subpasses->a[i].pColorAttachments); - free ((void *) renderpass_data.subpasses->a[i].pResolveAttachments); - free ((void *) renderpass_data.subpasses->a[i].pDepthStencilAttachment); - free ((void *) renderpass_data.subpasses->a[i].pPreserveAttachments); - } - free (renderpass_data.subpasses); - free (renderpass_data.dependencies); + delete_memsuper (memsuper); return renderpass; } VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { + memsuper_t *memsuper = new_memsuper (); qfv_device_t *device = ctx->device; __auto_type cInfo = QFV_AllocGraphicsPipelineCreateInfoSet (1, alloca); memset (&cInfo->a[0], 0, sizeof (cInfo->a[0])); - if (!parse_object (ctx, plist, parse_VkGraphicsPipelineCreateInfo, + if (!parse_object (ctx, memsuper, plist, parse_VkGraphicsPipelineCreateInfo, &cInfo->a[0], properties)) { + delete_memsuper (memsuper); return 0; } @@ -1044,6 +1041,7 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); VkPipeline pipeline = plSet->a[0]; free (plSet); + delete_memsuper (memsuper); return pipeline; } @@ -1053,17 +1051,20 @@ QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + memsuper_t *memsuper = new_memsuper (); VkDescriptorPoolCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkDescriptorPoolCreateInfo, &cInfo, - properties)) { + if (!parse_object (ctx, memsuper, plist, parse_VkDescriptorPoolCreateInfo, + &cInfo, properties)) { + delete_memsuper (memsuper); return 0; } VkDescriptorPool pool; dfunc->vkCreateDescriptorPool (device->dev, &cInfo, 0, &pool); + delete_memsuper (memsuper); return pool; } @@ -1073,17 +1074,21 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist, { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + memsuper_t *memsuper = new_memsuper (); VkDescriptorSetLayoutCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkDescriptorSetLayoutCreateInfo, + if (!parse_object (ctx, memsuper, plist, + parse_VkDescriptorSetLayoutCreateInfo, &cInfo, properties)) { + delete_memsuper (memsuper); return 0; } VkDescriptorSetLayout setLayout; dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, &setLayout); + delete_memsuper (memsuper); return setLayout; } @@ -1093,17 +1098,20 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + memsuper_t *memsuper = new_memsuper (); VkPipelineLayoutCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkPipelineLayoutCreateInfo, + if (!parse_object (ctx, memsuper, plist, parse_VkPipelineLayoutCreateInfo, &cInfo, properties)) { + delete_memsuper (memsuper); return 0; } VkPipelineLayout layout; dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &layout); + delete_memsuper (memsuper); return layout; } @@ -1112,17 +1120,20 @@ QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + memsuper_t *memsuper = new_memsuper (); VkSamplerCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkSamplerCreateInfo, &cInfo, + if (!parse_object (ctx, memsuper, plist, parse_VkSamplerCreateInfo, &cInfo, properties)) { + delete_memsuper (memsuper); return 0; } VkSampler sampler; dfunc->vkCreateSampler (device->dev, &cInfo, 0, &sampler); + delete_memsuper (memsuper); return sampler; } @@ -1131,17 +1142,20 @@ QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + memsuper_t *memsuper = new_memsuper (); VkImageCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkImageCreateInfo, &cInfo, + if (!parse_object (ctx, memsuper, plist, parse_VkImageCreateInfo, &cInfo, properties)) { + delete_memsuper (memsuper); return 0; } VkImage image; dfunc->vkCreateImage (device->dev, &cInfo, 0, &image); + delete_memsuper (memsuper); return image; } @@ -1150,17 +1164,20 @@ QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + memsuper_t *memsuper = new_memsuper (); VkImageViewCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkImageViewCreateInfo, &cInfo, - properties)) { + if (!parse_object (ctx, memsuper, plist, parse_VkImageViewCreateInfo, + &cInfo, properties)) { + delete_memsuper (memsuper); return 0; } VkImageView imageView; dfunc->vkCreateImageView (device->dev, &cInfo, 0, &imageView); + delete_memsuper (memsuper); return imageView; } @@ -1177,14 +1194,14 @@ typedef struct { static plelement_t qfv_imagecreate_dict = { QFDictionary, sizeof (VkImageCreateInfo), - array_alloc, + vkparse_alloc, parse_VkImageCreateInfo, }; static plelement_t qfv_imageviewcreate_dict = { QFDictionary, sizeof (VkImageViewCreateInfo), - array_alloc, + vkparse_alloc, parse_VkImageViewCreateInfo, }; @@ -1202,11 +1219,6 @@ parse_imagecreate_dict (const plfield_t *field, const plitem_t *item, imagecreate_t *imagecreate = data; imagecreate->count = arr->size; imagecreate->info = (VkImageCreateInfo *) arr->a; - } else { - //FIXME leaky boat when succeeds - if (arr) { - free (arr); - } } return ret; } @@ -1239,18 +1251,21 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + memsuper_t *memsuper = new_memsuper (); imagecreate_t create = {}; pltype_t type = PL_Type (item); if (type == QFDictionary) { - if (!parse_object (ctx, item, parse_imagecreate_dict, &create, - properties)) { + if (!parse_object (ctx, memsuper, item, parse_imagecreate_dict, + &create, properties)) { + delete_memsuper (memsuper); return 0; } } else { Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item)); + delete_memsuper (memsuper); return 0; } @@ -1265,6 +1280,7 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]); } + delete_memsuper (memsuper); return set; } @@ -1274,18 +1290,21 @@ QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + memsuper_t *memsuper = new_memsuper (); imageviewcreate_t create = {}; pltype_t type = PL_Type (item); if (type == QFDictionary) { - if (!parse_object (ctx, item, parse_imageviewcreate_dict, &create, - properties)) { + if (!parse_object (ctx, memsuper, item, parse_imageviewcreate_dict, + &create, properties)) { + delete_memsuper (memsuper); return 0; } } else { Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item)); + delete_memsuper (memsuper); return 0; } @@ -1298,6 +1317,7 @@ QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, QFV_AddHandle (ctx->imageViews, name, (uint64_t) set->a[i]); } + delete_memsuper (memsuper); return set; } @@ -1306,11 +1326,13 @@ QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + memsuper_t *memsuper = new_memsuper (); VkFramebufferCreateInfo cInfo = {}; - if (!parse_object (ctx, plist, parse_VkFramebufferCreateInfo, &cInfo, - properties)) { + if (!parse_object (ctx, memsuper, plist, parse_VkFramebufferCreateInfo, + &cInfo, properties)) { + delete_memsuper (memsuper); return 0; } @@ -1318,6 +1340,7 @@ QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); printf ("framebuffer, renderPass: %p, %p\n", framebuffer, cInfo.renderPass); + delete_memsuper (memsuper); return framebuffer; } @@ -1325,19 +1348,16 @@ static int parse_clearvalueset (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { - parsectx_t *parsectx = context; - vulkan_ctx_t *ctx = parsectx->vctx; - plelement_t element = { QFDictionary, sizeof (VkClearValue), - array_alloc, + vkparse_alloc, parse_VkClearValue, 0, }; plfield_t f = { 0, 0, 0, 0, &element }; - if (!PL_ParseArray (&f, item, &ctx->clearValues, messages, context)) { + if (!PL_ParseArray (&f, item, data, messages, context)) { return 0; } return 1; @@ -1346,9 +1366,19 @@ parse_clearvalueset (const plfield_t *field, const plitem_t *item, void *data, int QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { - if (!parse_object (ctx, plist, parse_clearvalueset, &ctx->clearValues, - properties)) { - return 0; + int ret = 0; + memsuper_t *memsuper = new_memsuper (); + clearvalueset_t *clearValues = 0; + + ctx->clearValues = 0; + if (parse_object (ctx, memsuper, plist, parse_clearvalueset, &clearValues, + properties)) { + ret = 1; + ctx->clearValues = DARRAY_ALLOCFIXED (clearvalueset_t, + clearValues->size, malloc); + memcpy (ctx->clearValues->a, clearValues->a, + clearValues->size * sizeof (clearValues->a[0])); } - return 1; + delete_memsuper (memsuper); + return ret; } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 01df24722..b1eecf3d3 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -77,7 +77,7 @@ find_visible_lights (vulkan_ctx_t *ctx) } if (leaf != lframe->leaf) { - double start = Sys_DoubleTime (); + //double start = Sys_DoubleTime (); byte pvs[MAP_PVS_BYTES]; Mod_LeafPVS_set (leaf, model, 0, pvs); @@ -89,8 +89,8 @@ find_visible_lights (vulkan_ctx_t *ctx) } lframe->leaf = leaf; - double end = Sys_DoubleTime (); - Sys_Printf ("find_visible_lights: %.5gus\n", (end - start) * 1e6); + //double end = Sys_DoubleTime (); + //Sys_Printf ("find_visible_lights: %.5gus\n", (end - start) * 1e6); int visible = 0; memset (lframe->lightvis.a, 0, lframe->lightvis.size * sizeof (byte)); @@ -101,8 +101,8 @@ find_visible_lights (vulkan_ctx_t *ctx) visible++; } } - Sys_Printf ("find_visible_lights: %d / %zd visible\n", visible, - lframe->lightvis.size); + //Sys_Printf ("find_visible_lights: %d / %zd visible\n", visible, + // lframe->lightvis.size); } } @@ -313,6 +313,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) __auto_type lframe = &lctx->frames.a[i]; DARRAY_INIT (&lframe->lightvis, 16); + lframe->leaf = 0; QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); lframe->cmd = cmdSet->a[0]; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 8c3c975ef..7c42467de 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -186,6 +186,8 @@ clear_table (hashtab_t **table) void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { + PL_Free (ctx->pipelineDef); + PL_Free (ctx->renderpassDef); if (ctx->pipeline) { QFV_DestroyPipeline (ctx->device, ctx->pipeline); } @@ -546,6 +548,10 @@ Vulkan_DestroyFrames (vulkan_ctx_t *ctx) df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0); df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); df->vkDestroyFramebuffer (dev, frame->framebuffer, 0); + for (int j = 0; j < frame->cmdSetCount; j++) { + DARRAY_CLEAR (&frame->cmdSets[j]); + } + free (frame->cmdSets); } DARRAY_CLEAR (&ctx->frames); diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index c118feab2..68e3645fe 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -311,9 +311,9 @@ void X11_CreateNullCursor (void) { Pixmap cursormask; - XGCValues xgc; + XGCValues xgc = { }; GC gc; - XColor dummycolour; + XColor dummycolour = { }; if (nullcursor != None) return; diff --git a/libs/video/targets/keys.c b/libs/video/targets/keys.c index 5d42aadd0..92ee71fc0 100644 --- a/libs/video/targets/keys.c +++ b/libs/video/targets/keys.c @@ -842,6 +842,11 @@ Key_IMT_Drop_All_f (void) while (key_targets[kd].imts) { imt = key_targets[kd].imts; key_targets[kd].imts = imt->next; + for (int i = 0; i < QFK_LAST; i++) { + if (imt->bindings[i].str) { + free (imt->bindings[i].str); + } + } free ((char *) imt->name); free (imt); } From 1bafd88a27efe26957c055efcb05571aac1bff84 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 20:40:02 +0900 Subject: [PATCH 1400/3664] oops plist --- include/QF/Makemodule.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index aefd432f7..4c190feae 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -36,6 +36,7 @@ include_qf = \ include/QF/pakfile.h \ include/QF/pcx.h \ include/QF/png.h \ + include/QF/plist.h \ include/QF/plugin.h \ include/QF/pr_comp.h \ include/QF/pr_debug.h \ @@ -45,7 +46,6 @@ include_qf = \ include/QF/qargs.h \ include/QF/qdefs.h \ include/QF/qendian.h \ - include/QF/qfplist.h \ include/QF/qtypes.h \ include/QF/quakefs.h \ include/QF/quakeio.h \ From 003910612a75a16c995c1a7cd4e9d6bf7a81e65c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 20:45:43 +0900 Subject: [PATCH 1401/3664] [entity] Fix tests for changed forward/right I had forgotten that Quake has forward as +X and right as -Y (still a right-handed system, just that with X forward, Y points left). --- libs/entity/test/test-hierarchy.c | 38 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/libs/entity/test/test-hierarchy.c b/libs/entity/test/test-hierarchy.c index 513f33fca..7d60f0104 100644 --- a/libs/entity/test/test-hierarchy.c +++ b/libs/entity/test/test-hierarchy.c @@ -595,11 +595,11 @@ test_frames (void) (vec4f_t) { 0, 0, 1, 1 }, "world position")) { return 1; } - if (!check_vector (root, Transform_Right, (vec4f_t) { 1, 0, 0, 0 }, - "right")) { + if (!check_vector (root, Transform_Forward, (vec4f_t) { 1, 0, 0, 0 }, + "forward")) { return 1; } - if (!check_vector (root, Transform_Forward, (vec4f_t) { 0, 1, 0, 0 }, + if (!check_vector (root, Transform_Right, (vec4f_t) { 0, -1, 0, 0 }, "right")) { return 1; } @@ -616,12 +616,12 @@ test_frames (void) "world position")) { return 1; } - if (!check_vector (A, Transform_Right, (vec4f_t) { 0, 1, 0, 0 }, - "right")) { + if (!check_vector (A, Transform_Forward, (vec4f_t) { 0, 1, 0, 0 }, + "forward")) { return 1; } - if (!check_vector (A, Transform_Forward, (vec4f_t) { 0, 0, 1, 0 }, - "forward")) { + if (!check_vector (A, Transform_Right, (vec4f_t) { 0, 0, -1, 0 }, + "right")) { return 1; } if (!check_vector (A, Transform_Up, (vec4f_t) { 1, 0, 0, 0 }, @@ -636,12 +636,12 @@ test_frames (void) "world position")) { return 1; } - if (!check_vector (A1, Transform_Right, (vec4f_t) { 1, 0, 0, 0 }, - "right")) { + if (!check_vector (A1, Transform_Forward, (vec4f_t) { 1, 0, 0, 0 }, + "forward")) { return 1; } - if (!check_vector (A1, Transform_Forward, (vec4f_t) { 0, 1, 0, 0 }, - "forward")) { + if (!check_vector (A1, Transform_Right, (vec4f_t) { 0, -1, 0, 0 }, + "right")) { return 1; } if (!check_vector (A1, Transform_Up, (vec4f_t) { 0, 0, 1, 0 }, @@ -657,12 +657,12 @@ test_frames (void) "world position")) { return 1; } - if (!check_vector (B, Transform_Right, (vec4f_t) { 0, 0, 1, 0 }, - "right")) { + if (!check_vector (B, Transform_Forward, (vec4f_t) { 0, 0, 1, 0 }, + "forward")) { return 1; } - if (!check_vector (B, Transform_Forward, (vec4f_t) {-1, 0, 0, 0 }, - "forward")) { + if (!check_vector (B, Transform_Right, (vec4f_t) { 1, 0, 0, 0 }, + "right")) { return 1; } if (!check_vector (B, Transform_Up, (vec4f_t) { 0,-1, 0, 0 }, @@ -677,12 +677,12 @@ test_frames (void) "world position")) { return 1; } - if (!check_vector (B1, Transform_Right, (vec4f_t) { 1, 0, 0, 0 }, - "right")) { + if (!check_vector (B1, Transform_Forward, (vec4f_t) { 1, 0, 0, 0 }, + "forward")) { return 1; } - if (!check_vector (B1, Transform_Forward, (vec4f_t) { 0, 1, 0, 0 }, - "forward")) { + if (!check_vector (B1, Transform_Right, (vec4f_t) { 0, -1, 0, 0 }, + "right")) { return 1; } if (!check_vector (B1, Transform_Up, (vec4f_t) { 0, 0, 1, 0 }, From 56cf181a1137f4d0412f423adc6c0868901cbb3e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 21:26:36 +0900 Subject: [PATCH 1402/3664] [gamecode] Make PR_RESMAP macros more function-like I never liked that some of the macros needed the type as a parameter (yay typeof and __auto_type) or those that returned a value hid the return statement so they couldn't be used in assignments. --- include/QF/progs.h | 125 +++++++++++++++-------------- libs/console/bi_inputline.c | 10 +-- libs/gamecode/pr_debug.c | 4 +- libs/ruamoko/rua_hash.c | 10 +-- libs/ruamoko/rua_msgbuf.c | 10 +-- libs/ruamoko/rua_obj.c | 8 +- libs/ruamoko/rua_plist.c | 10 +-- libs/ruamoko/rua_qfile.c | 10 +-- libs/ruamoko/rua_script.c | 10 +-- libs/ruamoko/rua_set.c | 20 ++--- libs/video/renderer/r_progs.c | 10 +-- ruamoko/qwaq/builtins/curses.c | 20 ++--- ruamoko/qwaq/builtins/debug.c | 10 +-- ruamoko/qwaq/builtins/editbuffer.c | 10 +-- 14 files changed, 136 insertions(+), 131 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 498303c25..8b1a6e118 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1532,46 +1532,44 @@ void *PR_Resources_Find (progs_t *pr, const char *name); /** Allocate a new resource from the resource map. - \param type The type of the resource. Must match the \c type parameter - used for PR_RESMAP. \param map The resource map. \return A pointer to the new resource, or null if no more could be allocated. */ -#define PR_RESNEW(type,map) \ - type *t; \ - \ - if (!map._free) { \ - int i, size; \ - map._size++; \ - size = map._size * sizeof (type *); \ - map._map = realloc (map._map, size); \ - if (!map._map) \ - return 0; \ - map._free = calloc (1024, sizeof (type)); \ - if (!map._free) \ - return 0; \ - map._map[map._size - 1] = map._free; \ - for (i = 0; i < 1023; i++) \ - *(type **) &map._free[i] = &map._free[i + 1]; \ - *(type **) &map._free[i] = 0; \ - } \ - t = map._free; \ - map._free = *(type **) t; \ - memset (t, 0, sizeof (type)); \ - return t +#define PR_RESNEW(map) \ + ({ \ + if (!map._free) { \ + int i, size; \ + map._size++; \ + size = map._size * sizeof (map._free); \ + map._map = realloc (map._map, size); \ + if (!map._map) \ + return 0; \ + map._free = calloc (1024, sizeof (*map._free)); \ + if (!map._free) \ + return 0; \ + map._map[map._size - 1] = map._free; \ + for (i = 0; i < 1023; i++) \ + *(typeof (map._free) *) &map._free[i] = &map._free[i + 1]; \ + *(typeof (map._free) *) &map._free[i] = 0; \ + } \ + __auto_type t = map._free; \ + map._free = *(typeof (map._free) *) t; \ + memset (t, 0, sizeof (*map._free)); \ + t; \ + }) /** Free a resource returning it to the resource map. - \param type The type of the resource. Must match the \c type parameter - used for PR_RESMAP. \param map The resource map. \param t Pointer to the resource to be freed. */ -#define PR_RESFREE(type,map,t) \ - memset (t, 0, sizeof (type)); \ - *(type **) t = map._free; \ - map._free = t +#define PR_RESFREE(map,t) \ + do { \ + memset (t, 0, sizeof (*map._free)); \ + *(typeof (map._free) *) t = map._free; \ + map._free = t; \ + } while (0) /** Free all resources in the resource map. @@ -1580,24 +1578,24 @@ void *PR_Resources_Find (progs_t *pr, const char *name); A reset resource map is guaranteed to allocate elements sequentially. - \param type The type of the resource. Must match the \c type parameter - used for PR_RESMAP. \param map The resource map. */ -#define PR_RESRESET(type,map) \ - unsigned i, j; \ - if (!map._size) \ - return; \ - for (i = 0; i < map._size; i++) { \ - map._free = map._map[i]; \ - for (j = 0; j < 1023; j++) \ - *(type **) &map._free[j] = &map._free[j + 1]; \ - if (i < map._size - 1) \ - *(type **) &map._free[j] = &map._map[i + 1][0]; \ - else \ - *(type **) &map._free[j] = 0; \ - } \ - map._free = map._map[0]; +#define PR_RESRESET(map) \ + do { \ + unsigned i, j; \ + if (!map._size) \ + return; \ + for (i = 0; i < map._size; i++) { \ + map._free = map._map[i]; \ + for (j = 0; j < 1023; j++) \ + *(typeof (map._free) *) &map._free[j] = &map._free[j + 1]; \ + if (i < map._size - 1) \ + *(typeof (map._free) *) &map._free[j] = &map._map[i + 1][0];\ + else \ + *(typeof (map._free) *) &map._free[j] = 0; \ + } \ + map._free = map._map[0]; \ + } while (0) /** Retrieve a resource from the resource map using a handle. @@ -1606,12 +1604,14 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \return A pointer to the resource, or NULL if the handle is invalid. */ -#define PR_RESGET(map,col) \ - unsigned row = ~col / 1024; \ - col = ~col % 1024; \ - if (row >= map._size) \ - return 0; \ - return &map._map[row][col] +#define PR_RESGET(map,col) \ + ({ \ + unsigned row = ~col / 1024; \ + col = ~col % 1024; \ + if (row >= map._size) \ + return 0; \ + &map._map[row][col]; \ + }) /** Convert a resource pointer to a handle. @@ -1619,14 +1619,19 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \param ptr The resource pointer. \return The handle or 0 if the pointer is invalid. */ -#define PR_RESINDEX(map,ptr) \ - unsigned i; \ - for (i = 0; i < map._size; i++) { \ - long d = ptr - map._map[i]; \ - if (d >= 0 && d < 1024) \ - return ~(i * 1024 + d); \ - } \ - return 0 +#define PR_RESINDEX(map,ptr) \ + ({ \ + unsigned i; \ + unsigned index = 0; \ + for (i = 0; i < map._size; i++) { \ + long d = ptr - map._map[i]; \ + if (d >= 0 && d < 1024) { \ + index = ~(i * 1024 + d); \ + break; \ + } \ + } \ + index; \ + }) ///@} ///@} diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index 7e4e743a2..b55cfa034 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -62,31 +62,31 @@ typedef struct { static il_data_t * il_data_new (il_resources_t *res) { - PR_RESNEW (il_data_t, res->line_map); + return PR_RESNEW (res->line_map); } static void il_data_free (il_resources_t *res, il_data_t *line) { - PR_RESFREE (il_data_t, res->line_map, line); + PR_RESFREE (res->line_map, line); } static void il_data_reset (il_resources_t *res) { - PR_RESRESET (il_data_t, res->line_map); + PR_RESRESET (res->line_map); } static inline il_data_t * il_data_get (il_resources_t *res, unsigned index) { - PR_RESGET (res->line_map, index); + return PR_RESGET (res->line_map, index); } static inline int __attribute__((pure)) il_data_index (il_resources_t *res, il_data_t *line) { - PR_RESINDEX (res->line_map, line); + return PR_RESINDEX (res->line_map, line); } static void diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index a272babf8..e8aa20e66 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -373,7 +373,7 @@ pr_debug_clear (progs_t *pr, void *data) Hash_FlushTable (res->file_hash); Hash_FlushTable (res->debug_syms); Hash_FlushTable (res->compunits); - PR_RESRESET (compunit_t, res->compmap); + PR_RESRESET (res->compmap); res->debug = 0; res->auxfunctions = 0; if (res->auxfunction_map) @@ -461,7 +461,7 @@ byteswap_def (pr_def_t *def) static compunit_t * new_compunit (prdeb_resources_t *res) { - PR_RESNEW (compunit_t, res->compmap); + return PR_RESNEW (res->compmap); } static void diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 98d9722ba..6448e0b1c 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -64,31 +64,31 @@ typedef struct { static bi_hashtab_t * table_new (hash_resources_t *res) { - PR_RESNEW (bi_hashtab_t, res->table_map); + return PR_RESNEW (res->table_map); } static void table_free (hash_resources_t *res, bi_hashtab_t *table) { - PR_RESFREE (bi_hashtab_t, res->table_map, table); + PR_RESFREE (res->table_map, table); } static void table_reset (hash_resources_t *res) { - PR_RESRESET (bi_hashtab_t, res->table_map); + PR_RESRESET (res->table_map); } static inline bi_hashtab_t * table_get (hash_resources_t *res, int index) { - PR_RESGET(res->table_map, index); + return PR_RESGET(res->table_map, index); } static inline int __attribute__((pure)) table_index (hash_resources_t *res, bi_hashtab_t *table) { - PR_RESINDEX(res->table_map, table); + return PR_RESINDEX(res->table_map, table); } static const char * diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index 51c7bcf16..e16525053 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -58,32 +58,32 @@ typedef struct { static msgbuf_t * msgbuf_new (msgbuf_resources_t *res) { - PR_RESNEW (msgbuf_t, res->msgbuf_map); + return PR_RESNEW (res->msgbuf_map); } static void msgbuf_free (progs_t *pr, msgbuf_resources_t *res, msgbuf_t *msgbuf) { PR_Zone_Free (pr, msgbuf->sizebuf.data); - PR_RESFREE (msgbuf_t, res->msgbuf_map, msgbuf); + PR_RESFREE (res->msgbuf_map, msgbuf); } static void msgbuf_reset (msgbuf_resources_t *res) { - PR_RESRESET (msgbuf_t, res->msgbuf_map); + PR_RESRESET (res->msgbuf_map); } static inline msgbuf_t * msgbuf_get (msgbuf_resources_t *res, int index) { - PR_RESGET(res->msgbuf_map, index); + return PR_RESGET(res->msgbuf_map, index); } static inline int __attribute__((pure)) msgbuf_index (msgbuf_resources_t *res, msgbuf_t *msgbuf) { - PR_RESINDEX(res->msgbuf_map, msgbuf); + return PR_RESINDEX(res->msgbuf_map, msgbuf); } static void diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 8612cd6f0..a901823b0 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -93,25 +93,25 @@ typedef struct probj_resources_s { static dtable_t * dtable_new (probj_t *probj) { - PR_RESNEW (dtable_t, probj->dtables); + return PR_RESNEW (probj->dtables); } static void dtable_reset (probj_t *probj) { - PR_RESRESET (dtable_t, probj->dtables); + PR_RESRESET (probj->dtables); } static inline dtable_t * dtable_get (probj_t *probj, int index) { - PR_RESGET (probj->dtables, index); + return PR_RESGET (probj->dtables, index); } static inline int __attribute__((pure)) dtable_index (probj_t *probj, dtable_t *dtable) { - PR_RESINDEX (probj->dtables, dtable); + return PR_RESINDEX (probj->dtables, dtable); } static always_inline dtable_t * __attribute__((pure)) diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index d8b3c0da1..afccba62e 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -63,31 +63,31 @@ typedef struct { static bi_plist_t * plist_new (plist_resources_t *res) { - PR_RESNEW (bi_plist_t, res->plist_map); + return PR_RESNEW (res->plist_map); } static void plist_free (plist_resources_t *res, bi_plist_t *plist) { - PR_RESFREE (bi_plist_t, res->plist_map, plist); + PR_RESFREE (res->plist_map, plist); } static void plist_reset (plist_resources_t *res) { - PR_RESRESET (bi_plist_t, res->plist_map); + PR_RESRESET (res->plist_map); } static inline bi_plist_t * plist_get (plist_resources_t *res, unsigned index) { - PR_RESGET(res->plist_map, index); + return PR_RESGET(res->plist_map, index); } static inline int __attribute__((pure)) plist_index (plist_resources_t *res, bi_plist_t *plist) { - PR_RESINDEX(res->plist_map, plist); + return PR_RESINDEX(res->plist_map, plist); } static void diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index 2f625a949..8c6c45ef1 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -56,31 +56,31 @@ typedef struct { static qfile_t * handle_new (qfile_resources_t *res) { - PR_RESNEW (qfile_t, res->handle_map); + return PR_RESNEW (res->handle_map); } static void handle_free (qfile_resources_t *res, qfile_t *handle) { - PR_RESFREE (qfile_t, res->handle_map, handle); + PR_RESFREE (res->handle_map, handle); } static void handle_reset (qfile_resources_t *res) { - PR_RESRESET (qfile_t, res->handle_map); + PR_RESRESET (res->handle_map); } static inline qfile_t * handle_get (qfile_resources_t *res, int index) { - PR_RESGET(res->handle_map, index); + return PR_RESGET(res->handle_map, index); } static inline int __attribute__((pure)) handle_index (qfile_resources_t *res, qfile_t *handle) { - PR_RESINDEX(res->handle_map, handle); + return PR_RESINDEX(res->handle_map, handle); } static void diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index 7c2cd6666..4723bfcbe 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -57,31 +57,31 @@ typedef struct { static rua_script_t * script_new (script_resources_t *res) { - PR_RESNEW (rua_script_t, res->scripts); + return PR_RESNEW (res->scripts); } static void script_free (script_resources_t *res, rua_script_t *script) { - PR_RESFREE (rua_script_t, res->scripts, script); + PR_RESFREE (res->scripts, script); } static void script_reset (script_resources_t *res) { - PR_RESRESET (rua_script_t, res->scripts); + PR_RESRESET (res->scripts); } static inline rua_script_t * script_get (script_resources_t *res, int index) { - PR_RESGET(res->scripts, index); + return PR_RESGET(res->scripts, index); } static inline int __attribute__((pure)) script_index (script_resources_t *res, rua_script_t *script) { - PR_RESINDEX(res->scripts, script); + return PR_RESINDEX(res->scripts, script); } static void diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 3bc36c06b..343e0ced0 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -77,61 +77,61 @@ typedef struct { static bi_set_t * res_set_new (set_resources_t *res) { - PR_RESNEW (bi_set_t, res->set_map); + return PR_RESNEW (res->set_map); } static void res_set_free (set_resources_t *res, bi_set_t *set) { - PR_RESFREE (bi_set_t, res->set_map, set); + PR_RESFREE (res->set_map, set); } static void res_set_reset (set_resources_t *res) { - PR_RESRESET (bi_set_t, res->set_map); + PR_RESRESET (res->set_map); } static inline bi_set_t * res_set_get (set_resources_t *res, int index) { - PR_RESGET(res->set_map, index); + return PR_RESGET(res->set_map, index); } static inline int __attribute__((pure)) res_set_index (set_resources_t *res, bi_set_t *set) { - PR_RESINDEX(res->set_map, set); + return PR_RESINDEX(res->set_map, set); } static bi_set_iter_t * res_set_iter_new (set_resources_t *res) { - PR_RESNEW (bi_set_iter_t, res->set_iter_map); + return PR_RESNEW (res->set_iter_map); } static void res_set_iter_free (set_resources_t *res, bi_set_iter_t *set_iter) { - PR_RESFREE (bi_set_iter_t, res->set_iter_map, set_iter); + PR_RESFREE (res->set_iter_map, set_iter); } static void res_set_iter_reset (set_resources_t *res) { - PR_RESRESET (bi_set_iter_t, res->set_iter_map); + PR_RESRESET (res->set_iter_map); } static inline bi_set_iter_t * res_set_iter_get (set_resources_t *res, int index) { - PR_RESGET(res->set_iter_map, index); + return PR_RESGET(res->set_iter_map, index); } static inline int __attribute__((pure)) res_set_iter_index (set_resources_t *res, bi_set_iter_t *set_iter) { - PR_RESINDEX(res->set_iter_map, set_iter); + return PR_RESINDEX(res->set_iter_map, set_iter); } static bi_set_t * diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 3f2925fba..c09569c56 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -68,7 +68,7 @@ typedef struct { static qpic_res_t * qpic_new (draw_resources_t *res) { - PR_RESNEW (qpic_res_t, res->qpic_map); + return PR_RESNEW (res->qpic_map); } static void @@ -86,25 +86,25 @@ static void qpic_free (draw_resources_t *res, qpic_res_t *qp) { bi_draw_free_qpic (qp); - PR_RESFREE (qpic_res_t, res->qpic_map, qp); + PR_RESFREE (res->qpic_map, qp); } static void qpic_reset (draw_resources_t *res) { - PR_RESRESET (qpic_res_t, res->qpic_map); + PR_RESRESET (res->qpic_map); } static inline qpic_res_t * qpic_get (draw_resources_t *res, int index) { - PR_RESGET (res->qpic_map, index); + return PR_RESGET (res->qpic_map, index); } static inline int __attribute__((pure)) qpic_index (draw_resources_t *res, qpic_res_t *qp) { - PR_RESINDEX (res->qpic_map, qp); + return PR_RESINDEX (res->qpic_map, qp); } static qpic_res_t * diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 0848158f7..cf4f1ebe3 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -127,31 +127,31 @@ static const char *qwaq_command_names[]= { static window_t * window_new (qwaq_resources_t *res) { - PR_RESNEW (window_t, res->window_map); + return PR_RESNEW (res->window_map); } static void window_free (qwaq_resources_t *res, window_t *win) { - PR_RESFREE (window_t, res->window_map, win); + PR_RESFREE (res->window_map, win); } static void window_reset (qwaq_resources_t *res) { - PR_RESRESET (window_t, res->window_map); + PR_RESRESET (res->window_map); } static inline window_t * window_get (qwaq_resources_t *res, unsigned index) { - PR_RESGET(res->window_map, index); + return PR_RESGET(res->window_map, index); } static inline int __attribute__((pure)) window_index (qwaq_resources_t *res, window_t *win) { - PR_RESINDEX (res->window_map, win); + return PR_RESINDEX (res->window_map, win); } static always_inline window_t * __attribute__((pure)) @@ -173,31 +173,31 @@ get_window (qwaq_resources_t *res, const char *name, int handle) static panel_t * panel_new (qwaq_resources_t *res) { - PR_RESNEW (panel_t, res->panel_map); + return PR_RESNEW (res->panel_map); } static void panel_free (qwaq_resources_t *res, panel_t *win) { - PR_RESFREE (panel_t, res->panel_map, win); + PR_RESFREE (res->panel_map, win); } static void panel_reset (qwaq_resources_t *res) { - PR_RESRESET (panel_t, res->panel_map); + PR_RESRESET (res->panel_map); } static inline panel_t * panel_get (qwaq_resources_t *res, unsigned index) { - PR_RESGET(res->panel_map, index); + return PR_RESGET(res->panel_map, index); } static inline int __attribute__((pure)) panel_index (qwaq_resources_t *res, panel_t *win) { - PR_RESINDEX (res->panel_map, win); + return PR_RESINDEX (res->panel_map, win); } static always_inline panel_t * __attribute__((pure)) diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 19b215e38..a8c56f280 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -73,31 +73,31 @@ typedef struct qwaq_debug_s { static qwaq_target_t * target_new (qwaq_debug_t *debug) { - PR_RESNEW (qwaq_target_t, debug->targets); + return PR_RESNEW (debug->targets); } static void target_free (qwaq_debug_t *debug, qwaq_target_t *target) { - PR_RESFREE (qwaq_target_t, debug->targets, target); + PR_RESFREE (debug->targets, target); } static void target_reset (qwaq_debug_t *debug) { - PR_RESRESET (qwaq_target_t, debug->targets); + PR_RESRESET (debug->targets); } static inline qwaq_target_t * target_get (qwaq_debug_t *debug, unsigned index) { - PR_RESGET (debug->targets, index); + return PR_RESGET (debug->targets, index); } static inline int __attribute__((pure)) target_index (qwaq_debug_t *debug, qwaq_target_t *target) { - PR_RESINDEX (debug->targets, target); + return PR_RESINDEX (debug->targets, target); } static always_inline qwaq_target_t * __attribute__((pure)) diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index d687103d3..666632944 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -31,31 +31,31 @@ typedef struct qwaq_ebresources_s { static editbuffer_t * editbuffer_new (qwaq_ebresources_t *res) { - PR_RESNEW (editbuffer_t, res->buffers); + return PR_RESNEW (res->buffers); } static void editbuffer_free (qwaq_ebresources_t *res, editbuffer_t *buffer) { - PR_RESFREE (editbuffer_t, res->buffers, buffer); + PR_RESFREE (res->buffers, buffer); } static void editbuffer_reset (qwaq_ebresources_t *res) { - PR_RESRESET (editbuffer_t, res->buffers); + PR_RESRESET (res->buffers); } static inline editbuffer_t * editbuffer_get (qwaq_ebresources_t *res, unsigned index) { - PR_RESGET (res->buffers, index); + return PR_RESGET (res->buffers, index); } static inline int __attribute__((pure)) editbuffer_index (qwaq_ebresources_t *res, editbuffer_t *buffer) { - PR_RESINDEX (res->buffers, buffer); + return PR_RESINDEX (res->buffers, buffer); } static always_inline editbuffer_t * __attribute__((pure)) From ce2ffac078df0179f643ae7fe7f54cf753fee7ae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 22:33:57 +0900 Subject: [PATCH 1403/3664] [entity] Free all memory in the unit test Now I know that deleting transforms works properly. --- libs/entity/test/test-hierarchy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/entity/test/test-hierarchy.c b/libs/entity/test/test-hierarchy.c index 7d60f0104..428dfcc5c 100644 --- a/libs/entity/test/test-hierarchy.c +++ b/libs/entity/test/test-hierarchy.c @@ -690,6 +690,8 @@ test_frames (void) return 1; } + Transform_Delete (root); + return 0; } From 1f8c4465a26fe24fe812b19f476baefa9d7bff25 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 23:03:11 +0900 Subject: [PATCH 1404/3664] [gamecode] Make non-clearing version of PR_RESNEW --- include/QF/progs.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 8b1a6e118..52e81d8a4 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -118,7 +118,7 @@ typedef struct pr_stashed_params_s { alloca(). \param pr pointer to ::progs_t VM struct - \return Pointer to a newly allocated and initialized parameter + \return Pointer to a newly allocated and initialized parameter stash that has the current parameters saved to it. \hideinitializer */ @@ -137,7 +137,7 @@ typedef struct pr_stashed_params_s { \param pr pointer to ::progs_t VM struct \param params location to save the parameters, must be of adequade size to hold \a pr_argc * \a pr_param_size words in \a params - \return \a params Allows the likes of: + \return \a params Allows the likes of: __auto_type params = PR_SaveParams (pr); */ pr_stashed_params_t *_PR_SaveParams (progs_t *pr, pr_stashed_params_t *params); @@ -1536,7 +1536,7 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \return A pointer to the new resource, or null if no more could be allocated. */ -#define PR_RESNEW(map) \ +#define PR_RESNEW_NC(map) \ ({ \ if (!map._free) { \ int i, size; \ @@ -1545,7 +1545,7 @@ void *PR_Resources_Find (progs_t *pr, const char *name); map._map = realloc (map._map, size); \ if (!map._map) \ return 0; \ - map._free = calloc (1024, sizeof (*map._free)); \ + map._free = malloc (1024 * sizeof (*map._free)); \ if (!map._free) \ return 0; \ map._map[map._size - 1] = map._free; \ @@ -1555,6 +1555,12 @@ void *PR_Resources_Find (progs_t *pr, const char *name); } \ __auto_type t = map._free; \ map._free = *(typeof (map._free) *) t; \ + t; \ + }) + +#define PR_RESNEW(map) \ + ({ \ + __auto_type t = PR_RESNEW_NC (map); \ memset (t, 0, sizeof (*map._free)); \ t; \ }) From 410fecd67b097184cbcbfab8ae14b01fc774acad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Mar 2021 23:05:13 +0900 Subject: [PATCH 1405/3664] [client] Fix the transform memory leak The transforms aren't actually freed at the end (more work), but at least they aren't lost any more, though one is still lost for the viewent (weapon). The obvious fix didn't work. --- libs/client/cl_temp_entities.c | 80 ++++++++-------------------------- nq/source/cl_ents.c | 8 ++-- 2 files changed, 23 insertions(+), 65 deletions(-) diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 11ae7632d..fdffbf985 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -40,6 +40,7 @@ #include "QF/entity.h" #include "QF/msg.h" +#include "QF/progs.h" // for PR_RESMAP #include "QF/quakefs.h" #include "QF/render.h" #include "QF/sound.h" @@ -54,9 +55,6 @@ typedef struct tent_s { entity_t ent; } tent_t; -#define TEMP_BATCH 64 -static tent_t *temp_entities = 0; - typedef struct { int entity; struct model_s *model; @@ -83,9 +81,11 @@ typedef struct tent_obj_s { } to; } tent_obj_t; -static tent_obj_t *tent_objects; +static PR_RESMAP (tent_t) temp_entities; +static PR_RESMAP (tent_obj_t) tent_objects; static tent_obj_t *cl_beams; static tent_obj_t *cl_explosions; + static tent_t *cl_projectiles; static sfx_t *cl_sfx_wizhit; @@ -158,20 +158,8 @@ CL_Init_Entity (entity_t *ent) static tent_t * new_temp_entity (void) { - tent_t *tent; - if (!temp_entities) { - int i; - - temp_entities = malloc (TEMP_BATCH * sizeof (tent_t)); - for (i = 0; i < TEMP_BATCH - 1; i++) { - temp_entities[i].next = &temp_entities[i + 1]; - temp_entities[i].ent.transform = 0; - } - temp_entities[i].next = 0; - temp_entities[i].ent.transform = 0; - } - tent = temp_entities; - temp_entities = tent->next; + tent_t *tent = PR_RESNEW_NC (temp_entities); + tent->ent.transform = 0; tent->next = 0; CL_Init_Entity (&tent->ent); return tent; @@ -182,63 +170,35 @@ free_temp_entities (tent_t *tents) { tent_t **t = &tents; - while (*t) + while (*t) { + Transform_Delete ((*t)->ent.transform);//FIXME reuse? t = &(*t)->next; - *t = temp_entities; - temp_entities = tents; + } + *t = temp_entities._free; + temp_entities._free = tents; } static tent_obj_t * new_tent_object (void) { - tent_obj_t *tobj; - if (!tent_objects) { - int i; - - tent_objects = malloc (TEMP_BATCH * sizeof (tent_obj_t)); - for (i = 0; i < TEMP_BATCH - 1; i++) - tent_objects[i].next = &tent_objects[i + 1]; - tent_objects[i].next = 0; - } - tobj = tent_objects; - tent_objects = tobj->next; + tent_obj_t *tobj = PR_RESNEW_NC (tent_objects); tobj->next = 0; return tobj; } static void -free_tent_objects (tent_obj_t *tobjs) +free_tent_object (tent_obj_t *tobj) { - tent_obj_t **t = &tobjs; - - while (*t) - t = &(*t)->next; - *t = tent_objects; - tent_objects = tobjs; + tobj->next = tent_objects._free; + tent_objects._free = tobj; } void CL_ClearTEnts (void) { - tent_t *tent; - tent_obj_t *tobj; - - for (tobj = cl_beams; tobj; tobj = tobj->next) { - for (tent = tobj->to.beam.tents; tent; tent = tent->next) { - tent->ent.visibility.efrag = 0; - } - free_temp_entities (tobj->to.beam.tents); - } - free_tent_objects (cl_beams); + PR_RESRESET (temp_entities); + PR_RESRESET (tent_objects); cl_beams = 0; - - for (tobj = cl_explosions; tobj; tobj = tobj->next) { - for (tent = tobj->to.ex.tent; tent; tent = tent->next) { - tent->ent.visibility.efrag = 0; - } - free_temp_entities (tobj->to.ex.tent); - } - free_tent_objects (cl_explosions); cl_explosions = 0; } @@ -618,8 +578,7 @@ CL_UpdateBeams (double time, TEntContext_t *ctx) beam_clear (b); _to = *to; *to = _to->next; - _to->next = tent_objects; - tent_objects = _to; + free_tent_object (_to); continue; } to = &(*to)->next; @@ -663,8 +622,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) free_temp_entities (ex->tent); _to = *to; *to = _to->next; - _to->next = tent_objects; - tent_objects = _to; + free_tent_object (_to); continue; } to = &(*to)->next; diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index d2cab9909..d5c564f28 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -65,15 +65,15 @@ CL_ClearEnts (void) { size_t i; + for (i = 0; i < MAX_EDICTS; i++) { + CL_Init_Entity (cl_entities + i); + } + // clear other arrays - memset (cl_entities, 0, sizeof (cl_entities)); i = nq_entstates.num_frames * nq_entstates.num_entities; memset (nq_entstates.frame[0], 0, i * sizeof (entity_state_t)); memset (cl_msgtime, 0, sizeof (cl_msgtime)); memset (cl_forcelink, 0, sizeof (cl_forcelink)); - - for (i = 0; i < MAX_EDICTS; i++) - CL_Init_Entity (cl_entities + i); } /* From 5173414d97b6093e795a64d24ee9182dad3ca9d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Mar 2021 13:13:26 +0900 Subject: [PATCH 1406/3664] [vulkan] Implement light styles Other than dealing with shader data alignment issues, that went well :). Nicely, the implementation gets the explicit scaling out of the shader, and allows for a directional flag. --- include/QF/Vulkan/qf_lighting.h | 4 +++- .../renderer/vulkan/shader/lighting.frag | 15 +++++++++----- libs/video/renderer/vulkan/vulkan_lighting.c | 20 +++++++++++++++---- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index c269feaae..f6aa67a94 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -38,7 +38,7 @@ typedef struct qfv_light_s { vec3_t color; - float intensity; + int data; vec3_t position; float radius; vec3_t direction; @@ -50,8 +50,10 @@ typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightleafset_t; typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t; #define NUM_LIGHTS 256 +#define NUM_STYLES 64 typedef struct qfv_light_buffer_s { + float intensity[NUM_STYLES + 3]; int lightCount; qfv_light_t lights[NUM_LIGHTS] __attribute__((aligned(16))); } qfv_light_buffer_t; diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index b756dd879..98f5b20a6 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -7,7 +7,7 @@ layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput p struct LightData { vec3 color; - float intensity; + int data;// bits 0-6: intensity key (however, values 0-66) vec3 position; float radius; vec3 direction; @@ -16,6 +16,8 @@ struct LightData { layout (constant_id = 0) const int MaxLights = 128; layout (set = 1, binding = 0) uniform Lights { + vec4 intensity[16]; // 64 floats + vec3 intensity2; int lightCount; LightData lights[MaxLights]; }; @@ -32,9 +34,12 @@ calc_light (LightData light, vec3 position, vec3 normal) float lightdot = dot (incoming, normal); float r = light.radius; - float intensity = light.intensity * step (d, r); - intensity *= smoothstep (spotdot, 1 - (1 - spotdot) * 0.995, light.cone) * clamp (lightdot, 0, 1); - return light.color * intensity * (r - d); + int style = light.data & 0x7f; + // deliberate array index error: access intensity2 as well + float i = intensity[style / 4][style % 4]; + i *= step (d, r) * clamp (lightdot, 0, 1); + i *= smoothstep (spotdot, 1 - (1 - spotdot) * 0.995, light.cone); + return light.color * i * (r - d); } void @@ -51,5 +56,5 @@ main (void) light += calc_light (lights[i], p, n); } } - frag_color = vec4 (c * light / 255.0, 1); + frag_color = vec4 (c * light, 1); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index b1eecf3d3..56c14387a 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -121,6 +121,14 @@ update_lights (vulkan_ctx_t *ctx) qfv_light_buffer_t *light_data = QFV_PacketExtend (packet, sizeof (*light_data)); + for (int i = 0; i < NUM_STYLES; i++) { + light_data->intensity[i] = d_lightstylevalue[i] / 65536.0; + } + // dynamic lights seem a tad fiant, so 16x map lights + light_data->intensity[64] = 1 / 16.0; + light_data->intensity[65] = 1 / 16.0; + light_data->intensity[66] = 1 / 16.0; + light_data->lightCount = 0; R_FindNearLights (r_origin, NUM_LIGHTS - 1, lights); for (int i = 0; i < NUM_LIGHTS - 1; i++) { @@ -131,7 +139,7 @@ update_lights (vulkan_ctx_t *ctx) VectorCopy (lights[i]->color, light_data->lights[i].color); VectorCopy (lights[i]->origin, light_data->lights[i].position); light_data->lights[i].radius = lights[i]->radius; - light_data->lights[i].intensity = 16; + light_data->lights[i].data = 64; // default dynamic light VectorZero (light_data->lights[i].direction); light_data->lights[i].cone = 1; } @@ -380,7 +388,7 @@ parse_light (qfv_light_t *light, const plitem_t *entity, Sys_Printf ("}\n");*/ light->cone = 1; - light->intensity = 1; + light->data = 0; light->radius = 300; VectorSet (1, 1, 1, light->color); @@ -411,6 +419,10 @@ parse_light (qfv_light_t *light, const plitem_t *entity, light->radius = atof (str); } + if ((str = PL_String (PL_ObjectForKey (entity, "style")))) { + light->data = atoi (str) & 0x3f; + } + if ((str = PL_String (PL_ObjectForKey (entity, "color"))) || (str = PL_String (PL_ObjectForKey (entity, "_color")))) { sscanf (str, "%f %f %f", VectorExpandAddr (light->color)); @@ -467,8 +479,8 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) mleaf_t *leaf = Mod_PointInLeaf (&light.position[0], model); DARRAY_APPEND (&lctx->lightleafs, leaf - model->brush.leafs); - printf ("[%g, %g, %g] %g, [%g %g %g] %g, [%g %g %g] %g, %zd\n", - VectorExpand (light.color), light.intensity, + printf ("[%g, %g, %g] %d, [%g %g %g] %g, [%g %g %g] %g, %zd\n", + VectorExpand (light.color), light.data, VectorExpand (light.position), light.radius, VectorExpand (light.direction), light.cone, leaf - model->brush.leafs); From 4eecbe867d8b57afe01b5f8431b22eaaa6bc11b9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Mar 2021 19:08:16 +0900 Subject: [PATCH 1407/3664] [vulkan] Implement deferred emission (fullbrights) That was... easier than expected. A little more tedious that I would have liked, but my scripting system isn't perfect (I suspect it's best suited as the output of a code generator), and the C side could do with a little more automation. --- include/QF/Vulkan/qf_lighting.h | 2 +- include/QF/Vulkan/qf_vid.h | 1 + libs/video/renderer/vulkan/deferred.plist | 80 +++++++++++++++---- libs/video/renderer/vulkan/qfpipeline.plist | 28 ++++++- .../renderer/vulkan/shader/alias_gbuf.frag | 8 +- .../renderer/vulkan/shader/bsp_gbuf.frag | 13 +-- .../renderer/vulkan/shader/lighting.frag | 8 +- libs/video/renderer/vulkan/vulkan_lighting.c | 4 +- 8 files changed, 116 insertions(+), 28 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index f6aa67a94..8541d367e 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -59,7 +59,7 @@ typedef struct qfv_light_buffer_s { } qfv_light_buffer_t; #define LIGHTING_BUFFER_INFOS 1 -#define LIGHTING_IMAGE_INFOS 4 +#define LIGHTING_IMAGE_INFOS 5 typedef struct lightingframe_s { VkCommandBuffer cmd; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 5ac5dddd4..e41d91890 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -49,6 +49,7 @@ enum { enum { QFV_attachDepth, QFV_attachColor, + QFV_attachEmission, QFV_attachNormal, QFV_attachPosition, QFV_attachOpaque, diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 6eded7acb..229c24c10 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -30,6 +30,21 @@ usage = color_attachment|input_attachment|transient_attachment; initialLayout = undefined; }; + emission = { + imageType = VK_IMAGE_TYPE_2D; + format = r16g16b16a16_sfloat; + samples = 1; + extent = { + width = $swapchain.extent.width; + height = $swapchain.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment|transient_attachment; + initialLayout = undefined; + }; normal = { imageType = VK_IMAGE_TYPE_2D; format = r16g16b16a16_sfloat; @@ -124,6 +139,22 @@ layerCount = 1; }; }; + emission = { + image = emission; + viewType = VK_IMAGE_VIEW_TYPE_2D; + format = $properties.images.emission.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; normal = { image = normal; viewType = VK_IMAGE_VIEW_TYPE_2D; @@ -191,8 +222,8 @@ }; framebuffer = { renderPass = $properties.renderpass; - attachments = (depth, color, normal, position, opaque, translucent, - "$swapchain.views[$swapImageIndex]"); + attachments = (depth, color, emission, normal, position, opaque, + translucent, "$swapchain.views[$swapImageIndex]"); width = $swapchain.extent.width; height = $swapchain.extent.height; layers = 1; @@ -200,6 +231,7 @@ clearValues = ( { depthStencil = { depth = 1; stencil = 0; }; }, { color = "[0, 0, 0, 1]"; }, // color + { color = "[0, 0, 0, 1]"; }, // emission { color = "[0, 0, 0, 1]"; }, // normal { color = "[0, 0, 0, 1]"; }, // position { color = "[0, 0, 0, 1]"; }, // opaque @@ -228,6 +260,16 @@ initialLayout = undefined; finalLayout = color_attachment_optimal; }, + { + format = $properties.images.emission.format; + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }, { format = $properties.images.normal.format; samples = 1; @@ -294,20 +336,24 @@ attachment = 1; layout = color_attachment_optimal; }, - { // normal + { // emission attachment = 2; layout = color_attachment_optimal; }, - { // position + { // normal attachment = 3; layout = color_attachment_optimal; }, + { // position + attachment = 4; + layout = color_attachment_optimal; + }, ); depthStencilAttachment = { attachment = 0; layout = depth_stencil_attachment_optimal; }; - preserveAttachments = (5); + preserveAttachments = (6); }, { // 2 lighting pipelineBindPoint = graphics; @@ -320,52 +366,56 @@ attachment = 1; layout = shader_read_only_optimal; }, - { // normal + { // emission attachment = 2; layout = shader_read_only_optimal; }, - { // position + { // normal attachment = 3; layout = shader_read_only_optimal; }, + { // position + attachment = 4; + layout = shader_read_only_optimal; + }, ); colorAttachments = ( { // opaque - attachment = 4; + attachment = 5; layout = color_attachment_optimal; }, ); - preserveAttachments = (5); + preserveAttachments = (6); }, { // 3 translucent pipelineBindPoint = graphics; colorAttachments = ( { // translucent - attachment = 5; + attachment = 6; layout = color_attachment_optimal; }, ); - preserveAttachments = (0, 1, 2, 3, 4); + preserveAttachments = (0, 1, 2, 3, 4, 5); }, { // 4 compose pipelineBindPoint = graphics; inputAttachments = ( { // opaque - attachment = 4; + attachment = 5; layout = shader_read_only_optimal; }, { // translucent - attachment = 5; + attachment = 6; layout = shader_read_only_optimal; }, ); colorAttachments = ( { // swapchain - attachment = 6; + attachment = 7; layout = color_attachment_optimal; }, ); - preserveAttachments = (0, 1, 2, 3); + preserveAttachments = (0, 1, 2, 3, 4); }, ); dependencies = ( diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 523edfbad..3e8f79274 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -83,7 +83,7 @@ bindings = ( { type = input_attachment; - descriptorCount = "4z * $frames.size"; + descriptorCount = "5z * $frames.size"; }, ); }; @@ -258,6 +258,12 @@ descriptorCount = 1; stageFlags = fragment; }, + { + binding = 4; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, ); }; lighting_lights = { @@ -515,6 +521,16 @@ alphaBlendOp = add; colorWriteMask = r|g|b|a; }, + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, ); }; dynamic = { @@ -674,6 +690,16 @@ alphaBlendOp = add; colorWriteMask = r|g|b|a; }, + { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }, { blendEnable = false; srcColorBlendFactor = src_alpha; diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index 0808b87f7..c9cc81db0 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -15,20 +15,24 @@ layout (location = 1) in vec4 position; layout (location = 2) in vec3 normal; layout (location = 0) out vec4 frag_color; -layout (location = 1) out vec4 frag_normal; -layout (location = 2) out vec4 frag_position; +layout (location = 1) out vec4 frag_emission; +layout (location = 2) out vec4 frag_normal; +layout (location = 3) out vec4 frag_position; void main (void) { vec4 c; + vec4 e; int i; vec3 light = vec3 (0); c = texture (Skin, vec3 (st, 0)) * unpackUnorm4x8(base_color); c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA); c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB); + e = texture (Skin, vec3 (st, 3)); frag_color = c; + frag_emission = e; frag_normal = vec4(normal, 1); frag_position = position; } diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index e4578ce5e..c00c0d72d 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -18,8 +18,9 @@ layout (location = 2) in vec3 normal; layout (location = 3) in vec4 position; layout (location = 0) out vec4 frag_color; -layout (location = 1) out vec4 frag_normal; -layout (location = 2) out vec4 frag_position; +layout (location = 1) out vec4 frag_emission; +layout (location = 2) out vec4 frag_normal; +layout (location = 3) out vec4 frag_position; layout (constant_id = 0) const bool doWarp = false; layout (constant_id = 1) const bool doLight = true; @@ -107,7 +108,8 @@ sky_color (vec3 dir, float time) void main (void) { - vec4 c; + vec4 c = vec4 (0); + vec4 e; vec2 t_st = tl_st.xy; vec2 l_st = tl_st.zw; @@ -115,15 +117,16 @@ main (void) t_st = warp_st (t_st, time); } if (doSkyCube || doSkySheet) { - c = sky_color (direction, time); + e = sky_color (direction, time); } else { c = texture (Texture, t_st); if (doLight) { c *= vec4 (texture (LightMap, l_st).xyz, 1); } - c += texture (GlowMap, t_st); + e = texture (GlowMap, t_st); } frag_color = c;//fogBlend (c); + frag_emission = e; frag_normal = vec4 (normal, 0); frag_position = position; } diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 98f5b20a6..86e496991 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -2,8 +2,9 @@ layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput depth; layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput color; -layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput normal; -layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput position; +layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput emission; +layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput normal; +layout (input_attachment_index = 4, set = 0, binding = 4) uniform subpassInput position; struct LightData { vec3 color; @@ -47,6 +48,7 @@ main (void) { //float d = subpassLoad (depth).r; vec3 c = subpassLoad (color).rgb; + vec3 e = subpassLoad (emission).rgb; vec3 n = subpassLoad (normal).rgb; vec3 p = subpassLoad (position).rgb; vec3 light = vec3 (0); @@ -56,5 +58,5 @@ main (void) light += calc_light (lights[i], p, n); } } - frag_color = vec4 (c * light, 1); + frag_color = vec4 (c * light + e, 1); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 56c14387a..69c6faa69 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -214,8 +214,10 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) lframe->imageInfo[0].imageView = ctx->attachment_views->a[QFV_attachDepth]; lframe->imageInfo[1].imageView = ctx->attachment_views->a[QFV_attachColor]; lframe->imageInfo[2].imageView - = ctx->attachment_views->a[QFV_attachNormal]; + = ctx->attachment_views->a[QFV_attachEmission]; lframe->imageInfo[3].imageView + = ctx->attachment_views->a[QFV_attachNormal]; + lframe->imageInfo[4].imageView = ctx->attachment_views->a[QFV_attachPosition]; dfunc->vkUpdateDescriptorSets (device->dev, LIGHTING_BUFFER_INFOS + LIGHTING_IMAGE_INFOS, From de581501fb257bef2b65a9abcf63f51e0d1f5a79 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Mar 2021 20:33:42 +0900 Subject: [PATCH 1408/3664] [vulkan] Early out from lights that are too distant Gives a 43% speed boost to bigass1 timedemo (366 -> 525 fps). --- libs/video/renderer/vulkan/shader/lighting.frag | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 86e496991..3be1485ee 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -28,12 +28,17 @@ layout (location = 0) out vec4 frag_color; vec3 calc_light (LightData light, vec3 position, vec3 normal) { + float r = light.radius; vec3 dist = light.position - position; float d = sqrt (dot (dist, dist)); + if (d > r) { + // the light is too far away + return vec3 (0); + } + vec3 incoming = dist / d; float spotdot = dot (incoming, light.direction); float lightdot = dot (incoming, normal); - float r = light.radius; int style = light.data & 0x7f; // deliberate array index error: access intensity2 as well From 81956095f1e278b2864a3babb2663a37bf48b3d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Mar 2021 08:25:56 +0900 Subject: [PATCH 1409/3664] [vulkan] Use correct vertex shader for skys This gets skys rendering again, but their depth is incorrect. --- include/QF/Vulkan/qf_vid.h | 4 ++-- libs/video/renderer/vulkan/qfpipeline.plist | 4 ++-- libs/video/renderer/vulkan/vulkan_bsp.c | 21 +++++++++++---------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index e41d91890..f2d9bf0ec 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -36,7 +36,7 @@ #include //FIXME location -enum { +typedef enum { QFV_passDepth, // geometry QFV_passGBuffer, // geometry QFV_passLighting, // single quad @@ -44,7 +44,7 @@ enum { QFV_passCompose, // single quad QFV_NumPasses -}; +} QFV_Subpass; enum { QFV_attachDepth, diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 3e8f79274..61687a721 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -719,12 +719,12 @@ //renderPass = renderpass; }; bsp_skysheet = { - subpass = 2; + subpass = 3; stages = ( { stage = vertex; name = main; - module = $builtin/bsp_gbuf.vert; + module = $builtin/quakebsp.vert; }, { stage = fragment; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 937876dc9..cd5b1e022 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -75,6 +75,12 @@ static const char *bsp_pass_names[] = { "translucent", }; +static QFV_Subpass subpass_map[] = { + QFV_passDepth, // QFV_bspDepth + QFV_passGBuffer, // QFV_bspGBuffer + QFV_passTranslucent, // QFV_bspTranslucent +}; + static float identity[] = { 1, 0, 0, 0, 0, 1, 0, 0, @@ -872,7 +878,7 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, subpass, + ctx->renderpass, subpass_map[subpass], cframe->framebuffer, 0, 0, 0, }; @@ -883,6 +889,9 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + QFV_duCmdBeginLabel (device, cmd, bsp_pass_names[subpass], + {0, 0.5, 0.6, 1}); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; @@ -914,6 +923,7 @@ bsp_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); } @@ -1274,15 +1284,6 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) fragconst_t frag_constants = { time: vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTranslucent]); - bind_view (qfv_bsp_texture, ctx->default_black->view, bframe, - bframe->cmdSet.a[QFV_bspTranslucent],//FIXME - bctx->layout, dfunc); - bind_view (qfv_bsp_glowmap, ctx->default_black->view, bframe, - bframe->cmdSet.a[QFV_bspTranslucent],//FIXME - bctx->layout, dfunc); - bind_view (qfv_bsp_lightmap, ctx->default_black->view, bframe, - bframe->cmdSet.a[QFV_bspTranslucent],//FIXME - bctx->layout, dfunc); for (is = bctx->sky_chain; is; is = is->tex_chain) { surf = is->surface; if (tex != surf->texinfo->texture->render) { From d4e1bfb8b82939189dee8c98b491c163a2deebf5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Mar 2021 10:01:13 +0900 Subject: [PATCH 1410/3664] [vulkan] Clean up the pipeline specifications While being able to write pipeline specs like this was the end goal of the parsing sub-project, I didn't realize it was already usable. This sure makes going through the pipeline specs much easier. --- libs/video/renderer/vulkan/qfpipeline.plist | 751 ++++++-------------- 1 file changed, 233 insertions(+), 518 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 61687a721..138d80855 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -335,6 +335,169 @@ setLayouts = (compose_attach); }; }; + + depthStencil = { + test_and_write = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + test_only = { + depthTestEnable = true; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + disable = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + }; + + inputAssembly = { + alias = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + brush = { + topology = triangle_fan; + primitiveRestartEnable = true; + }; + twod = { + topology = triangle_strip; + primitiveRestartEnable = true; + }; + }; + + vertexInput = { + alias = { + bindings = ( + { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 1; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 2; stride = "2 * 4"; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 1; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 3; binding = 1; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 4; binding = 2; format = r32g32_sfloat; offset = 0; }, + ); + }; + brush = { + bindings = ( + { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + ); + }; + twod = { + bindings = ( + { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32_sfloat; offset = 8; }, + { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + ); + }; + }; + + rasterization = { + cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + counter_cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + }; + + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + + attachmentBlendOp = { + disabled = { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + alpha_blend = { + blendEnable = true; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + }; + + fsquad = { + vertexInput = { + bindings = ( + { binding = 0; stride = "4 * 4"; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + ); + }; + inputAssembly = { + topology = triangle_strip; + primitiveRestartEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.disabled); + }; + }; + pipelines = { alias_depth = { subpass = 0; @@ -346,29 +509,24 @@ }, ); vertexInput = { + // depth pass doesn't use UVs bindings = ( - "$properties.pipelines.alias_gbuf.vertexInput.bindings[0]", - "$properties.pipelines.alias_gbuf.vertexInput.bindings[1]", + "$properties.vertexInput.alias.bindings[0]", + "$properties.vertexInput.alias.bindings[1]", ); attributes = ( - "$properties.pipelines.alias_gbuf.vertexInput.attributes[0]", - "$properties.pipelines.alias_gbuf.vertexInput.attributes[1]", - "$properties.pipelines.alias_gbuf.vertexInput.attributes[2]", - "$properties.pipelines.alias_gbuf.vertexInput.attributes[3]", + "$properties.vertexInput.alias.attributes[0]", + "$properties.vertexInput.alias.attributes[1]", + "$properties.vertexInput.alias.attributes[2]", + "$properties.vertexInput.alias.attributes[3]", ); }; - inputAssembly = $properties.pipelines.alias_gbuf.inputAssembly; - viewport = $properties.pipelines.alias_gbuf.viewport; - rasterization = $properties.pipelines.alias_gbuf.rasterization; - multisample = $properties.pipelines.alias_gbuf.multisample; - depthStencil = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - colorBlend = $properties.pipelines.alias_gbuf.colorBlend; + inputAssembly = $properties.inputAssembly.alias; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_and_write; + colorBlend = $properties.pipelines.alias_gbuf.colorBlend; dynamic = { dynamicState = ( viewport, scissor ); }; @@ -395,142 +553,19 @@ }; }, ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "2 * 4 * 4"; - inputRate = vertex; - }, - { - binding = 1; - stride = "2 * 4 * 4"; - inputRate = vertex; - }, - { - binding = 2; - stride = "2 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 0; - }, - { - location = 1; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 16; - }, - { - location = 2; - binding = 1; - format = r32g32b32a32_sfloat; - offset = 0; - }, - { - location = 3; - binding = 1; - format = r32g32b32a32_sfloat; - offset = 16; - }, - { - location = 4; - binding = 2; - format = r32g32_sfloat; - offset = 0; - }, - ); - }; - inputAssembly = { - topology = triangle_list; - primitiveRestartEnable = false; - }; - viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); - }; - rasterization = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - depthStencil = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; + vertexInput = $properties.vertexInput.alias; + inputAssembly = $properties.inputAssembly.alias; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_only; colorBlend = { logicOpEnable = false; attachments = ( - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, ); }; dynamic = { @@ -550,24 +585,18 @@ ); vertexInput = { bindings = ( - "$properties.pipelines.bsp_gbuf.vertexInput.bindings[0]", + "$properties.vertexInput.brush.bindings[0]", ); attributes = ( - "$properties.pipelines.bsp_gbuf.vertexInput.attributes[0]", + "$properties.vertexInput.brush.attributes[0]", ); }; - inputAssembly = $properties.pipelines.bsp_gbuf.inputAssembly; - viewport = $properties.pipelines.bsp_gbuf.viewport; - rasterization = $properties.pipelines.bsp_gbuf.rasterization; - multisample = $properties.pipelines.bsp_gbuf.multisample; - depthStencil = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; + inputAssembly = $properties.inputAssembly.brush; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_and_write; + colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; dynamic = { dynamicState = ( viewport, scissor ); }; @@ -596,120 +625,25 @@ { size = 4; offset = 0; constantID = 0; }, { size = 4; offset = 0; constantID = 1; }, { size = 4; offset = 0; constantID = 2; }, - { size = 4; offset = 4; constantID = 1; }, + { size = 4; offset = 0; constantID = 3; }, ); data = <00000000ffffffff>; }; }, ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "2 * 4 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 0; - }, - { - location = 1; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 16; - }, - ); - }; - inputAssembly = { - topology = triangle_fan; - primitiveRestartEnable = true; - }; - viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); - }; - rasterization = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - depthStencil = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; + vertexInput = $properties.vertexInput.brush; + inputAssembly = $properties.inputAssembly.brush; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_only; colorBlend = { logicOpEnable = false; attachments = ( - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - } + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, ); }; dynamic = { @@ -739,26 +673,15 @@ }; }, ); - vertexInput = $properties.pipelines.bsp_gbuf.vertexInput; - inputAssembly = $properties.pipelines.bsp_gbuf.inputAssembly; - viewport = $properties.pipelines.bsp_gbuf.viewport; - rasterization = $properties.pipelines.bsp_gbuf.rasterization; - multisample = $properties.pipelines.bsp_gbuf.multisample; - depthStencil = $properties.pipelines.bsp_gbuf.depthStencil; + vertexInput = $properties.vertexInput.brush; + inputAssembly = $properties.inputAssembly.brush; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_only; colorBlend = { logicOpEnable = false; - attachments = ( - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, - ); + attachments = ($properties.attachmentBlendOp.disabled); }; dynamic = { dynamicState = ( viewport, scissor ); @@ -780,89 +703,15 @@ module = $builtin/twod.frag; }, ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "2 * 4 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32_sfloat; - offset = 0; - }, - { - location = 1; - binding = 0; - format = r32g32_sfloat; - offset = 8; - }, - { - location = 2; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 16; - }, - ); - }; - inputAssembly = { - topology = triangle_strip; - primitiveRestartEnable = true; - }; - viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); - }; - rasterization = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - depthStencil = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; + vertexInput = $properties.vertexInput.twod; + inputAssembly = $properties.inputAssembly.twod; + viewport = $properties.viewport; + rasterization = $properties.rasterization.counter_cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_and_write; colorBlend = { logicOpEnable = false; - attachments = ({ - blendEnable = true; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }); + attachments = ($properties.attachmentBlendOp.alpha_blend); }; dynamic = { dynamicState = ( viewport, scissor ); @@ -890,80 +739,13 @@ }; }, ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "4 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 0; - }, - ); - }; - inputAssembly = { - topology = triangle_strip; - primitiveRestartEnable = false; - }; - viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); - }; - rasterization = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - depthStencil = { - depthTestEnable = false; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - colorBlend = { - logicOpEnable = false; - attachments = ( - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, - ); - }; + vertexInput = $properties.fsquad.vertexInput; + inputAssembly = $properties.fsquad.inputAssembly; + viewport = $properties.viewport; + rasterization = $properties.rasterization.counter_cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.disable; + colorBlend = $properties.fsquad.colorBlend; dynamic = { dynamicState = ( viewport, scissor ); }; @@ -984,80 +766,13 @@ module = $builtin/compose.frag; }, ); - vertexInput = { - bindings = ( - { - binding = 0; - stride = "4 * 4"; - inputRate = vertex; - }, - ); - attributes = ( - { - location = 0; - binding = 0; - format = r32g32b32a32_sfloat; - offset = 0; - }, - ); - }; - inputAssembly = { - topology = triangle_strip; - primitiveRestartEnable = false; - }; - viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); - }; - rasterization = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - depthStencil = { - depthTestEnable = false; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - colorBlend = { - logicOpEnable = false; - attachments = ( - { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }, - ); - }; + vertexInput = $properties.fsquad.vertexInput; + inputAssembly = $properties.fsquad.inputAssembly; + viewport = $properties.viewport; + rasterization = $properties.rasterization.counter_cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.disable; + colorBlend = $properties.fsquad.colorBlend; dynamic = { dynamicState = ( viewport, scissor ); }; From 5ac807d4b2b9783dcfb4c78aaeafe12071909cfb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Mar 2021 10:12:26 +0900 Subject: [PATCH 1411/3664] [vulkan] Remove the old forward renderpass spec I doubt I'll go back to it, and it was in the wrong place anyway. --- libs/video/renderer/vulkan/qfpipeline.plist | 141 -------------------- 1 file changed, 141 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 138d80855..54bc0f9af 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -780,145 +780,4 @@ //renderPass = renderpass; }; }; - renderpass = { - attachments = ( - { - flags = 0; - format = $swapchain.format; - samples = 1; - loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - storeOp = VK_ATTACHMENT_STORE_OP_STORE; - stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - }, - { - flags = 0; - format = VK_FORMAT_D32_SFLOAT; - samples = 1; - loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - }, - ); - subpasses = ( - { - pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - colorAttachments = ( - { - attachment = 0; - layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - ); - depthStencilAttachment = { - attachment = 1; - layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - }; - preserveAttachments = (); - }, - ); - dependencies = ( - { - srcSubpass = VK_SUBPASS_EXTERNAL; - dstSubpass = 0; - srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - }, - { - srcSubpass = 0; - dstSubpass = VK_SUBPASS_EXTERNAL; - srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - }, - ); - }; - renderpass_msaa = { - attachments = ( - { - flags = 0; - format = $swapchain.format; - samples = VK_SAMPLE_COUNT_1_BIT; - loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - storeOp = VK_ATTACHMENT_STORE_OP_STORE; - stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - }, - { - flags = 0; - format = VK_FORMAT_D32_SFLOAT; - samples = $msaaSamples; - loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - }, - { - flags = 0; - format = $swapchain.format; - samples = $msaaSamples; - loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - storeOp = VK_ATTACHMENT_STORE_OP_STORE; - stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - }, - ); - subpasses = ( - { - pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - colorAttachments = ( - { - attachment = 2; - layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - ); - resolveAttachments = ( - { - attachment = 0; - layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - } - ); - depthStencilAttachment = { - attachment = 1; - layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - }; - preserveAttachments = (); - }, - ); - dependencies = ( - { - srcSubpass = VK_SUBPASS_EXTERNAL; - dstSubpass = 0; - srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - }, - { - srcSubpass = 0; - dstSubpass = VK_SUBPASS_EXTERNAL; - srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; - }, - ); - }; } From 6e0312658d259ecd0a534b679fdf0efcfbb1fcdd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Mar 2021 11:26:24 +0900 Subject: [PATCH 1412/3664] [vulkan] Fix sky depth issues There were actually several problems: translucency wasn't using or depending on the depth buffer, and the depth buffer wasn't marked as read-only in the g-buffer pass. Getting that correct seems to have given bigass1 a 0.5% boost (hard to say, could be the usual noise). --- include/QF/Vulkan/qf_vid.h | 2 +- libs/video/renderer/vulkan/deferred.plist | 49 +++++++++++++-------- libs/video/renderer/vulkan/qfpipeline.plist | 12 ++--- libs/video/renderer/vulkan/vulkan_alias.c | 8 +++- 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index f2d9bf0ec..b01000d06 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -38,9 +38,9 @@ //FIXME location typedef enum { QFV_passDepth, // geometry + QFV_passTranslucent, // geometry QFV_passGBuffer, // geometry QFV_passLighting, // single quad - QFV_passTranslucent, // geometry QFV_passCompose, // single quad QFV_NumPasses diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 229c24c10..d956a5792 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -329,7 +329,21 @@ layout = depth_stencil_attachment_optimal; }; }, - { // 1 g-buffer generation + { // 1 translucent + pipelineBindPoint = graphics; + colorAttachments = ( + { // translucent + attachment = 6; + layout = color_attachment_optimal; + }, + ); + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_read_only_optimal; + }; + preserveAttachments = (1, 2, 3, 4, 5); + }, + { // 2 g-buffer generation pipelineBindPoint = graphics; colorAttachments = ( { // color @@ -351,11 +365,11 @@ ); depthStencilAttachment = { attachment = 0; - layout = depth_stencil_attachment_optimal; + layout = depth_stencil_read_only_optimal; }; preserveAttachments = (6); }, - { // 2 lighting + { // 3 lighting pipelineBindPoint = graphics; inputAttachments = ( { // depth @@ -387,16 +401,6 @@ ); preserveAttachments = (6); }, - { // 3 translucent - pipelineBindPoint = graphics; - colorAttachments = ( - { // translucent - attachment = 6; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (0, 1, 2, 3, 4, 5); - }, { // 4 compose pipelineBindPoint = graphics; inputAttachments = ( @@ -421,7 +425,7 @@ dependencies = ( { srcSubpass = 0; // depth - dstSubpass = 1; // g-buffer + dstSubpass = 1; // translucent srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -429,8 +433,8 @@ dependencyFlags = by_region; }, { - srcSubpass = 1; // g-buffer - dstSubpass = 2; // lighting + srcSubpass = 0; // depth + dstSubpass = 2; // g-buffer srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -438,7 +442,16 @@ dependencyFlags = by_region; }, { - srcSubpass = 2; // lighting + srcSubpass = 2; // g-buffer + dstSubpass = 3; // lighting + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = shader_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 3; // lighting dstSubpass = 4; // compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; @@ -447,7 +460,7 @@ dependencyFlags = by_region; }, { - srcSubpass = 3; // translucent + srcSubpass = 1; // translucent dstSubpass = 4; // compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 54bc0f9af..97bcc9251 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -534,7 +534,7 @@ //renderPass = renderpass; }; alias_gbuf = { - subpass = 1; + subpass = 2; stages = ( { stage = vertex; @@ -604,7 +604,7 @@ //renderPass = renderpass; }; bsp_gbuf = { - subpass = 1; + subpass = 2; stages = ( { stage = vertex; @@ -653,7 +653,7 @@ //renderPass = renderpass; }; bsp_skysheet = { - subpass = 3; + subpass = 1; stages = ( { stage = vertex; @@ -690,7 +690,7 @@ //renderPass = renderpass; }; twod = { - subpass = 3; + subpass = 1; stages = ( { stage = vertex; @@ -708,7 +708,7 @@ viewport = $properties.viewport; rasterization = $properties.rasterization.counter_cw_cull_back; multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; + depthStencil = $properties.depthStencil.test_only; colorBlend = { logicOpEnable = false; attachments = ($properties.attachmentBlendOp.alpha_blend); @@ -720,7 +720,7 @@ //renderPass = renderpass; }; lighting = { - subpass = 2; + subpass = 3; stages = ( { stage = vertex; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 25a2d9d13..c2581e773 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -70,6 +70,12 @@ static const char *alias_pass_names[] = { "translucent", }; +static QFV_Subpass subpass_map[] = { + QFV_passDepth, // QFV_aliasDepth + QFV_passGBuffer, // QFV_aliasGBuffer + QFV_passTranslucent, // QFV_aliasTranslucent +}; + static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_alias_skin_t *skin, @@ -174,7 +180,7 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, subpass, + ctx->renderpass, subpass_map[subpass], cframe->framebuffer, 0, 0, 0, }; From 7e946a4de942e1b3865913ad1e2eff67c067bed7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Mar 2021 12:24:24 +0900 Subject: [PATCH 1413/3664] [vulkan] Implement water surface rendering They're unlit (fullbright, but that's nothing new for quake), but working nicely. As a bonus, sort out the sky pass (forced to due to the way command buffers are used). --- include/QF/Vulkan/qf_bsp.h | 4 +- libs/video/renderer/Makemodule.am | 5 + libs/video/renderer/vulkan/qfpipeline.plist | 37 +++++ libs/video/renderer/vulkan/shader.c | 3 + .../renderer/vulkan/shader/bsp_turb.frag | 52 ++++++ libs/video/renderer/vulkan/vulkan_bsp.c | 150 +++++++++--------- 6 files changed, 173 insertions(+), 78 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/bsp_turb.frag diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index ff3f6612a..7f279ffc2 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -73,7 +73,8 @@ typedef enum { typedef enum { QFV_bspDepth, QFV_bspGBuffer, - QFV_bspTranslucent, + QFV_bspSky, + QFV_bspTurb, QFV_bspNumPasses } QFV_BspSubpass; @@ -146,6 +147,7 @@ typedef struct bspctx_s { VkPipeline depth; VkPipeline gbuf; VkPipeline sky; + VkPipeline turb; VkPipelineLayout layout; size_t vertex_buffer_size; size_t index_buffer_size; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 8c459dd1c..d21a7952d 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -313,6 +313,8 @@ bsp_gbuff_src = $(vkshaderpath)/bsp_gbuf.frag bsp_gbuff_c = $(vkshaderpath)/bsp_gbuf.frag.spvc bsp_skyf_src = $(vkshaderpath)/bsp_sky.frag bsp_skyf_c = $(vkshaderpath)/bsp_sky.frag.spvc +bsp_turbf_src = $(vkshaderpath)/bsp_turb.frag +bsp_turbf_c = $(vkshaderpath)/bsp_turb.frag.spvc lightingf_src = $(vkshaderpath)/lighting.frag lightingf_c = $(vkshaderpath)/lighting.frag.spvc composef_src = $(vkshaderpath)/compose.frag @@ -348,6 +350,8 @@ $(bsp_gbuff_c): $(bsp_gbuff_src) $(bsp_skyf_c): $(bsp_skyf_src) +$(bsp_turbf_c): $(bsp_turbf_src) + $(lightingf_c): $(lightingf_src) $(composef_c): $(composef_src) @@ -374,6 +378,7 @@ vkshader_c = \ $(bsp_gbufg_c) \ $(bsp_gbuff_c) \ $(bsp_skyf_c) \ + $(bsp_turbf_c) \ $(lightingf_c) \ $(composef_c) \ $(aliasv_c) \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 97bcc9251..2d95f06b4 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -689,6 +689,43 @@ layout = quakebsp_layout; //renderPass = renderpass; }; + bsp_turb = { + subpass = 1; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/bsp_turb.frag; + specializationInfo = { + mapEntries = ( + { size = 4; offset = 0; constantID = 0; }, + { size = 4; offset = 4; constantID = 1; }, + ); + data = <00000000ffffffff>; + }; + }, + ); + vertexInput = $properties.vertexInput.brush; + inputAssembly = $properties.inputAssembly.brush; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_only; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.disabled); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = quakebsp_layout; + //renderPass = renderpass; + }; twod = { subpass = 1; stages = ( diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index d2921faca..c10d9a286 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -72,6 +72,8 @@ static static #include "libs/video/renderer/vulkan/shader/bsp_sky.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/bsp_turb.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/lighting.frag.spvc" static #include "libs/video/renderer/vulkan/shader/compose.frag.spvc" @@ -104,6 +106,7 @@ static shaderdata_t builtin_shaders[] = { { "bsp_gbuf.geom", bsp_gbuf_geom, sizeof (bsp_gbuf_geom) }, { "bsp_gbuf.frag", bsp_gbuf_frag, sizeof (bsp_gbuf_frag) }, { "bsp_sky.frag", bsp_sky_frag, sizeof (bsp_sky_frag) }, + { "bsp_turb.frag", bsp_turb_frag, sizeof (bsp_turb_frag) }, { "lighting.frag", lighting_frag, sizeof (lighting_frag) }, { "compose.frag", compose_frag, sizeof (compose_frag) }, { "alias.vert", alias_vert, sizeof (alias_vert) }, diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag new file mode 100644 index 000000000..ab4b04c7d --- /dev/null +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -0,0 +1,52 @@ +#version 450 + +layout (set = 0, binding = 1) uniform sampler2D Texture; + +layout (push_constant) uniform PushConstants { + layout (offset = 64) + vec4 fog; + float time; +}; + +layout (location = 0) in vec4 tl_st; +layout (location = 1) in vec3 direction; + +layout (location = 0) out vec4 frag_color; + +const float PI = 3.14159265; +const float SPEED = 20.0; +const float CYCLE = 128.0; +const float FACTOR = PI * 2.0 / CYCLE; +const vec2 BIAS = vec2 (1.0, 1.0); +const float SCALE = 8.0; + +vec2 +warp_st (vec2 st, float time) +{ + vec2 angle = st.ts * CYCLE / 2.0; + vec2 phase = vec2 (time, time) * SPEED; + return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; +} + +vec4 +fogBlend (vec4 color) +{ + float az = fog.a * gl_FragCoord.z / gl_FragCoord.w; + vec3 fog_color = fog.rgb; + float fog_factor = exp (-az * az); + + return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); +} + +void +main (void) +{ + vec4 c = vec4 (0); + vec4 e; + vec2 t_st = tl_st.xy; + vec2 l_st = tl_st.zw; + + t_st = warp_st (t_st, time); + c = texture (Texture, t_st); + frag_color = c;//fogBlend (c); +} diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index cd5b1e022..a85625440 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -72,13 +72,15 @@ static const char *bsp_pass_names[] = { "depth", "g-buffer", - "translucent", + "sky", + "turb", }; static QFV_Subpass subpass_map[] = { QFV_passDepth, // QFV_bspDepth QFV_passGBuffer, // QFV_bspGBuffer - QFV_passTranslucent, // QFV_bspTranslucent + QFV_passTranslucent, // QFV_bspSky + QFV_passTranslucent, // QFV_bspTurb }; static float identity[] = { @@ -968,58 +970,40 @@ bsp_end (vulkan_ctx_t *ctx) bsp_end_subpass (bframe->cmdSet.a[QFV_bspGBuffer], ctx); } -/*static void -turb_begin (bspctx_t *bctx) +static void +turb_begin (vulkan_ctx_t *ctx) { - quat_t fog; + bspctx_t *bctx = ctx->bsp_context; bctx->default_color[3] = bound (0, r_wateralpha->value, 1); + QuatCopy (bctx->default_color, bctx->last_color); - qfeglVertexAttrib4fv (quake_bsp.color.location, default_color); - Mat4Mult (glsl_projection, glsl_view, bsp_vp); + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - qfeglUseProgram (quake_turb.program); - qfeglEnableVertexAttribArray (quake_turb.vertex.location); - qfeglEnableVertexAttribArray (quake_turb.tlst.location); - qfeglDisableVertexAttribArray (quake_turb.color.location); + DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], + bframe->cmdSet.a[QFV_bspTurb]); - qfeglVertexAttrib4fv (quake_turb.color.location, default_color); + //FIXME need per frame matrices + bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + bframe->imageInfo[0].imageView = ctx->default_magenta->view; + bframe->imageInfo[1].imageView = ctx->default_magenta->view; + bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); + bframe->imageInfo[3].imageView = bctx->default_skysheet->view; + bframe->imageInfo[4].imageView = bctx->default_skybox->view; - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; - fragconst_t frag_constants = { time: vr_data.realtime }; - dfunc->vkCmdPushConstants (cmd, bctx->layout, VK_SHADER_STAGE_FRAGMENT_BIT, - 64, sizeof (fragconst_t), &frag_constants); - qfeglUniform4fv (quake_turb.fog.location, 1, fog); + bsp_begin_subpass (QFV_bspTurb, bctx->turb, ctx); +} - qfeglUniform1i (quake_turb.palette.location, 1); - qfeglActiveTexture (GL_TEXTURE0 + 1); - qfeglEnable (GL_TEXTURE_2D); - qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); - - qfeglUniform1f (quake_turb.time.location, vr_data.realtime); - - qfeglUniform1i (quake_turb.texture.location, 0); - qfeglActiveTexture (GL_TEXTURE0 + 0); - qfeglEnable (GL_TEXTURE_2D); - - qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo); -}*/ - -/*static void -turb_end (bspctx_t *bctx) +static void +turb_end (vulkan_ctx_t *ctx) { - qfeglDisableVertexAttribArray (quake_turb.vertex.location); - qfeglDisableVertexAttribArray (quake_turb.tlst.location); + bspctx_t *bctx = ctx->bsp_context; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - qfeglActiveTexture (GL_TEXTURE0 + 0); - qfeglDisable (GL_TEXTURE_2D); - qfeglActiveTexture (GL_TEXTURE0 + 1); - qfeglDisable (GL_TEXTURE_2D); - - qfeglBindBuffer (GL_ARRAY_BUFFER, 0); -}*/ + bsp_end_subpass (bframe->cmdSet.a[QFV_bspTurb], ctx); +} static void spin (mat4_t mat, bspctx_t *bctx) @@ -1057,9 +1041,8 @@ sky_begin (vulkan_ctx_t *ctx) __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - //FIXME where should skys go? g-buffer is overkill. Translucent pre-pass? DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], - bframe->cmdSet.a[QFV_bspTranslucent]); + bframe->cmdSet.a[QFV_bspSky]); //FIXME need per frame matrices bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; @@ -1071,8 +1054,7 @@ sky_begin (vulkan_ctx_t *ctx) bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, bctx->default_skybox); - //FIXME sky pass - bsp_begin_subpass (QFV_bspTranslucent, bctx->sky, ctx); + bsp_begin_subpass (QFV_bspSky, bctx->sky, ctx); } static void @@ -1081,8 +1063,7 @@ sky_end (vulkan_ctx_t *ctx) bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - //FIXME sky pass - bsp_end_subpass (bframe->cmdSet.a[QFV_bspTranslucent], ctx); + bsp_end_subpass (bframe->cmdSet.a[QFV_bspSky], ctx); } static inline void @@ -1217,7 +1198,10 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) void Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) { -/* bspctx_t *bctx = ctx->bsp_context; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; instsurf_t *is; msurface_t *surf; vulktex_t *tex = 0; @@ -1227,38 +1211,49 @@ Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) if (!bctx->waterchain) return; - turb_begin (bctx); + turb_begin (ctx); + push_transform (identity, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); + fragconst_t frag_constants = { time: vr_data.realtime }; + push_fragconst (&frag_constants, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); for (is = bctx->waterchain; is; is = is->tex_chain) { surf = is->surface; - if (tex != surf->texinfo->texture) { + if (tex != surf->texinfo->texture->render) { if (tex) { - //XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); - //for (ec = tex->elechain; ec; ec = ec->next) - // draw_elechain (ec, quake_turb.mvp_matrix.location, - // quake_turb.vertex.location, - // quake_turb.tlst.location, - // quake_turb.color.location); + bind_view (qfv_bsp_texture, + get_view (tex->tex, ctx->default_black), + bframe, + bframe->cmdSet.a[QFV_bspTurb], + bctx->layout, dfunc); + for (ec = tex->elechain; ec; ec = ec->next) { + draw_elechain (ec, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); + reset_elechain (ec); + } tex->elechain = 0; tex->elechain_tail = &tex->elechain; } - tex = surf->texinfo->texture; + tex = surf->texinfo->texture->render; } - add_surf_elements (tex, is, &ec, &el, bctx); + add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - //XXX qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); - //for (ec = tex->elechain; ec; ec = ec->next) - // draw_elechain (ec, quake_turb.mvp_matrix.location, - // quake_turb.vertex.location, - // quake_turb.tlst.location, - // quake_turb.color.location); + bind_view (qfv_bsp_texture, get_view (tex->tex, ctx->default_black), + bframe, bframe->cmdSet.a[QFV_bspTurb], + bctx->layout, dfunc); + for (ec = tex->elechain; ec; ec = ec->next) { + draw_elechain (ec, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); + reset_elechain (ec); + } tex->elechain = 0; tex->elechain_tail = &tex->elechain; } - turb_end (bctx); + turb_end (ctx); bctx->waterchain = 0; - bctx->waterchain_tail = &bctx->waterchain;*/ + bctx->waterchain_tail = &bctx->waterchain; } void @@ -1278,12 +1273,11 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) return; sky_begin (ctx); - //FIXME sky pass push_transform (identity, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspTranslucent]); + bframe->cmdSet.a[QFV_bspSky]); fragconst_t frag_constants = { time: vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspTranslucent]); + bframe->cmdSet.a[QFV_bspSky]); for (is = bctx->sky_chain; is; is = is->tex_chain) { surf = is->surface; if (tex != surf->texinfo->texture->render) { @@ -1291,11 +1285,11 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black), bframe, - bframe->cmdSet.a[QFV_bspTranslucent],//FIXME + bframe->cmdSet.a[QFV_bspSky], bctx->layout, dfunc); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc,//FIXME - bframe->cmdSet.a[QFV_bspTranslucent]); + draw_elechain (ec, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); reset_elechain (ec); } tex->elechain = 0; @@ -1307,11 +1301,11 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) } if (tex) { bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black), - bframe, bframe->cmdSet.a[QFV_bspTranslucent],//FIXME + bframe, bframe->cmdSet.a[QFV_bspSky], bctx->layout, dfunc); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc,//FIXME - bframe->cmdSet.a[QFV_bspTranslucent]); + draw_elechain (ec, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); reset_elechain (ec); } tex->elechain = 0; @@ -1488,6 +1482,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->depth = Vulkan_CreatePipeline (ctx, "bsp_depth"); bctx->gbuf = Vulkan_CreatePipeline (ctx, "bsp_gbuf"); bctx->sky = Vulkan_CreatePipeline (ctx, "bsp_skysheet"); + bctx->turb = Vulkan_CreatePipeline (ctx, "bsp_turb"); bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); @@ -1539,6 +1534,7 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) dfunc->vkDestroyPipeline (device->dev, bctx->depth, 0); dfunc->vkDestroyPipeline (device->dev, bctx->gbuf, 0); dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0); + dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0); DARRAY_CLEAR (&bctx->texture_chains); DARRAY_CLEAR (&bctx->frames); QFV_DestroyStagingBuffer (bctx->light_stage); From a0d47de4396a2741d7cc5a300ef7c83c7283a5a1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Mar 2021 13:04:22 +0900 Subject: [PATCH 1414/3664] [vulkan] Suppress all the debug output silence is golden --- include/QF/sys.h | 31 ++++--- include/vid_vulkan.h | 1 - libs/audio/renderer/snd_channels.c | 3 +- libs/video/renderer/vid_render_vulkan.c | 20 +--- libs/video/renderer/vulkan/device.c | 6 +- libs/video/renderer/vulkan/vkparse.c | 93 ++++++++++--------- libs/video/renderer/vulkan/vulkan_lighting.c | 15 +-- .../video/renderer/vulkan/vulkan_vid_common.c | 26 +++--- 8 files changed, 99 insertions(+), 96 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 58aa08b76..e54031af2 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -84,21 +84,22 @@ void Sys_TimeOfDay(date_t *date); void Sys_MaskPrintf (int mask, const char *fmt, ...) __attribute__((format(printf,2,3))); // remember to update developer_flags in cvar.c -#define SYS_DEV (1|0) -#define SYS_WARN (1|2) // bit 0 so developer 1 will pick it up -#define SYS_VID (1|4) -#define SYS_FS_NF (1|8) -#define SYS_FS_F (1|16) -#define SYS_FS (1|32) -#define SYS_NET (1|64) -#define SYS_RUA_OBJ (1|128) -#define SYS_RUA_MSG (1|256) -#define SYS_SND (1|512) -#define SYS_GLT (1|1024) -#define SYS_GLSL (1|2048) -#define SYS_SKIN (1|4096) -#define SYS_MODEL (1|8192) -#define SYS_VULKAN (1|16384) +#define SYS_DEV (1|0) +#define SYS_WARN (1|2) // bit 0 so developer 1 will pick it up +#define SYS_VID (1|4) +#define SYS_FS_NF (1|8) +#define SYS_FS_F (1|16) +#define SYS_FS (1|32) +#define SYS_NET (1|64) +#define SYS_RUA_OBJ (1|128) +#define SYS_RUA_MSG (1|256) +#define SYS_SND (1|512) +#define SYS_GLT (1|1024) +#define SYS_GLSL (1|2048) +#define SYS_SKIN (1|4096) +#define SYS_MODEL (1|8192) +#define SYS_VULKAN (1|16384) +#define SYS_VULKAN_PARSE (1|32768) int Sys_CheckInput (int idle, int net_socket); const char *Sys_ConsoleInput (void); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 080b8079f..70deb17f7 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -89,7 +89,6 @@ typedef struct vulkan_ctx_s { VkCommandBuffer cmdbuffer; VkFence fence; // for ctx->cmdbuffer only struct qfv_stagebuf_s *staging; - VkPipeline pipeline; size_t curFrame; vulkan_frameset_t frames; diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index cbf337496..59c068b2c 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -104,7 +104,8 @@ SND_AllocChannel (void) for (free = &free_channels; *free; free = &(*free)->next) { num_free++; } - Sys_Printf ("SND_AllocChannel: out of channels. %d\n", num_free); + Sys_MaskPrintf (SYS_WARN, "SND_AllocChannel: out of channels. %d\n", + num_free); return 0; } chan = *free; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index b4f84f129..83f0d4b51 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -92,9 +92,6 @@ vulkan_R_Init (void) Vulkan_CreateFrames (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_CreateFramebuffers (vulkan_ctx); - // FIXME this should be staged so screen updates can begin while pipelines - // are being built - vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); Vulkan_Texture_Init (vulkan_ctx); Vulkan_Alias_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); @@ -104,13 +101,6 @@ vulkan_R_Init (void) Vulkan_Compose_Init (vulkan_ctx); Skin_Init (); - Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain, - vulkan_ctx->swapchain->numImages); - for (int32_t i = 0; i < vulkan_ctx->swapchain->numImages; i++) { - Sys_Printf (" %p", vulkan_ctx->swapchain->images->a[i]); - } - Sys_Printf ("\n"); - SCR_Init (); } @@ -559,10 +549,10 @@ vulkan_vid_render_choose_visual (void) cmdset); vulkan_ctx->cmdbuffer = cmdset->a[0]; vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1); - Sys_Printf ("vk choose visual %p %p %d %p\n", vulkan_ctx->device->dev, - vulkan_ctx->device->queue.queue, - vulkan_ctx->device->queue.queueFamily, - vulkan_ctx->cmdpool); + Sys_MaskPrintf (SYS_VULKAN, "vk choose visual %p %p %d %p\n", + vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue, + vulkan_ctx->device->queue.queueFamily, + vulkan_ctx->cmdpool); } static void @@ -570,7 +560,7 @@ vulkan_vid_render_create_context (void) { vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); - Sys_Printf ("vk create context %p\n", vulkan_ctx->surface); + Sys_MaskPrintf (SYS_VULKAN, "vk create context %p\n", vulkan_ctx->surface); } static void diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 58e04c110..778c98273 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -115,9 +115,11 @@ load_device_funcs (qfv_instance_t *inst, qfv_device_t *dev) if (!ext || dev->extension_enabled (dev, ext)) { \ dfunc->name = (PFN_##name) ifunc->vkGetDeviceProcAddr (device, #name); \ if (!dfunc->name) { \ - Sys_Printf ("Couldn't find device level function %s", #name); \ + Sys_MaskPrintf (SYS_VULKAN_PARSE, \ + "Couldn't find device level function %s", #name); \ } else { \ - Sys_Printf ("Found device level function %s\n", #name); \ + Sys_MaskPrintf (SYS_VULKAN_PARSE, \ + "Found device level function %s\n", #name); \ } \ } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 382d04873..798cd98f9 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -159,9 +159,9 @@ parse_basic (const plfield_t *field, const plitem_t *item, ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); - //Sys_Printf ("parse_basic: %s %zd %d %p %p: %s\n", - // field->name, field->offset, field->type, field->parser, - // field->data, valstr); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_basic: %s %zd %d %p %p: %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) { //FIXME handle subpass in a separate parser? *(uint32_t *) data = VK_SUBPASS_EXTERNAL; @@ -172,7 +172,7 @@ parse_basic (const plfield_t *field, const plitem_t *item, field->name, valstr); } } - //Sys_Printf (" %x\n", *(uint32_t *)data); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %x\n", *(uint32_t *)data); return ret; } @@ -190,23 +190,24 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); - //Sys_Printf ("parse_uint32_t: %s %zd %d %p %p: %s\n", - // field->name, field->offset, field->type, field->parser, - // field->data, valstr); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_uint32_t: %s %zd %d %p %p: %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) { //FIXME handle subpass in a separate parser? *(uint32_t *) data = VK_SUBPASS_EXTERNAL; } else { - //Sys_Printf ("parse_uint32_t: %s %zd %d %p %p %s\n", - // field->name, field->offset, field->type, field->parser, - // field->data, valstr); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, + // "parse_uint32_t: %s %zd %d %p %p %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); ret = !cexpr_eval_string (valstr, &ectx); if (!ret) { PL_Message (messages, item, "error parsing %s: %s", field->name, valstr); } *(uint32_t *) data = val; - //Sys_Printf (" %d\n", *(uint32_t *)data); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %d\n", *(uint32_t *)data); } return ret; @@ -223,14 +224,14 @@ parse_enum (const plfield_t *field, const plitem_t *item, ectx.symtab = enm->symtab; ectx.result = &result; const char *valstr = PL_String (item); - //Sys_Printf ("parse_enum: %s %zd %d %p %p %s\n", - // field->name, field->offset, field->type, field->parser, - // field->data, valstr); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_enum: %s %zd %d %p %p %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); ret = !cexpr_parse_enum (enm, valstr, &ectx, data); if (!ret) { PL_Message (messages, item, "error parsing enum: %s", valstr); } - //Sys_Printf (" %d\n", *(int *)data); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %d\n", *(int *)data); return ret; } @@ -266,8 +267,9 @@ parse_single (const plfield_t *field, const plitem_t *item, __auto_type single = (parse_single_t *) field->data; void *flddata = (byte *)data + single->value_offset; - //Sys_Printf ("parse_single: %s %zd %d %p %p\n", field->name, field->offset, - // field->type, field->parser, field->data); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_single: %s %zd %d %p %p\n", + // field->name, field->offset, + // field->type, field->parser, field->data); if (!PL_CheckType (single->type, PL_Type (item))) { PL_TypeMismatch (messages, item, field->name, single->type, @@ -306,11 +308,12 @@ parse_array (const plfield_t *field, const plitem_t *item, typedef struct arr_s DARRAY_TYPE(byte) arr_t; arr_t *arr; - //Sys_Printf ("parse_array: %s %zd %d %p %p %p\n", - // field->name, field->offset, field->type, field->parser, - // field->data, data); - //Sys_Printf (" %d %zd %p %zd %zd\n", array->type, array->stride, - // array->parser, array->value_offset, array->size_offset); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_array: %s %zd %d %p %p %p\n", + // field->name, field->offset, field->type, field->parser, + // field->data, data); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %d %zd %p %zd %zd\n", array->type, + // array->stride, array->parser, array->value_offset, + // array->size_offset); if (!PL_ParseArray (&f, item, &arr, messages, context)) { return 0; } @@ -333,11 +336,12 @@ parse_data (const plfield_t *field, const plitem_t *item, const void *bindata = PL_BinaryData (item); size_t binsize = PL_BinarySize (item); - Sys_Printf ("parse_data: %s %zd %d %p %p %p\n", - field->name, field->offset, field->type, field->parser, - field->data, data); - Sys_Printf (" %zd %zd\n", datad->value_offset, datad->size_offset); - Sys_Printf (" %zd %p\n", binsize, bindata); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_data: %s %zd %d %p %p %p\n", + field->name, field->offset, field->type, field->parser, + field->data, data); + Sys_MaskPrintf (SYS_VULKAN_PARSE, " %zd %zd\n", datad->value_offset, + datad->size_offset); + Sys_MaskPrintf (SYS_VULKAN_PARSE, " %zd %p\n", binsize, bindata); *value = vkparse_alloc (context, binsize); memcpy (*value, bindata, binsize); @@ -356,11 +360,11 @@ parse_string (const plfield_t *field, const plitem_t *item, const char *str = PL_String (item); - //Sys_Printf ("parse_string: %s %zd %d %p %p %p\n", - // field->name, field->offset, field->type, field->parser, - // field->data, data); - //Sys_Printf (" %zd\n", string->value_offset); - //Sys_Printf (" %s\n", str); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_string: %s %zd %d %p %p %p\n", + // field->name, field->offset, field->type, field->parser, + // field->data, data); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %zd\n", string->value_offset); + //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %s\n", str); size_t len = strlen (str) + 1; *value = vkparse_alloc (context, len); @@ -390,9 +394,10 @@ parse_RGBA (const plitem_t *item, void **data, ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); - Sys_Printf ("parse_RGBA: %s\n", valstr); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_RGBA: %s\n", valstr); ret = !cexpr_eval_string (valstr, &ectx); - Sys_Printf (" "VEC4F_FMT"\n", VEC4_EXP (*(vec4f_t *)data[0])); + Sys_MaskPrintf (SYS_VULKAN_PARSE, " "VEC4F_FMT"\n", + VEC4_EXP (*(vec4f_t *)data[0])); return ret; } @@ -426,7 +431,7 @@ parse_VkRenderPass (const plitem_t *item, void **data, vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); - Sys_Printf ("parse_VkRenderPass: %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkRenderPass: %s\n", name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); } @@ -483,7 +488,8 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); - Sys_Printf ("parse_VkDescriptorSetLayout: %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkDescriptorSetLayout: %s\n", + name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); } @@ -519,7 +525,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); - Sys_Printf ("parse_VkPipelineLayout: %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkPipelineLayout: %s\n", name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); } @@ -554,7 +560,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); - Sys_Printf ("parse_VkImage: %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkImage: %s\n", name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); } @@ -596,7 +602,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); - Sys_Printf ("parse_VkImageView: %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkImageView: %s\n", name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name); } @@ -981,7 +987,8 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, if (!parser (0, plist, object, messages, &parsectx)) { for (int i = 0; i < PL_A_NumObjects (messages); i++) { - Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "%s\n", + PL_String (PL_ObjectAtIndex (messages, i))); } return 0; } @@ -1264,7 +1271,8 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) return 0; } } else { - Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item)); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "Neither array nor dictionary: %d\n", + PL_Line (item)); delete_memsuper (memsuper); return 0; } @@ -1338,7 +1346,8 @@ QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) VkFramebuffer framebuffer; dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); - printf ("framebuffer, renderPass: %p, %p\n", framebuffer, cInfo.renderPass); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "framebuffer, renderPass: %p, %p\n", + framebuffer, cInfo.renderPass); delete_memsuper (memsuper); return framebuffer; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 69c6faa69..48d4cdba9 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -481,14 +481,15 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) mleaf_t *leaf = Mod_PointInLeaf (&light.position[0], model); DARRAY_APPEND (&lctx->lightleafs, leaf - model->brush.leafs); - printf ("[%g, %g, %g] %d, [%g %g %g] %g, [%g %g %g] %g, %zd\n", - VectorExpand (light.color), light.data, - VectorExpand (light.position), light.radius, - VectorExpand (light.direction), light.cone, - leaf - model->brush.leafs); + Sys_MaskPrintf (SYS_VULKAN, + "[%g, %g, %g] %d, " + "[%g %g %g] %g, [%g %g %g] %g, %zd\n", + VectorExpand (light.color), light.data, + VectorExpand (light.position), light.radius, + VectorExpand (light.direction), light.cone, + leaf - model->brush.leafs); } } - printf ("%zd frames\n", ctx->frames.size); for (size_t i = 0; i < ctx->frames.size; i++) { lightingframe_t *lframe = &lctx->frames.a[i]; DARRAY_RESIZE (&lframe->lightvis, lctx->lights.size); @@ -501,5 +502,5 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) PL_Free (targets); PL_Free (entities); } - printf ("loaded %zd lights\n", lctx->lights.size); + Sys_MaskPrintf (SYS_VULKAN, "loaded %zd lights\n", lctx->lights.size); } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 7c42467de..fccf5843c 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -166,11 +166,12 @@ static const char *device_extensions[] = { void Vulkan_Init_Common (vulkan_ctx_t *ctx) { - Sys_Printf ("Vulkan_Init_Common\n"); + Sys_MaskPrintf (SYS_VULKAN, "Vulkan_Init_Common\n"); QFV_InitParse (ctx); Vulkan_Init_Cvars (); - ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version + ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, + instance_extensions);//FIXME version } static void @@ -188,9 +189,6 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { PL_Free (ctx->pipelineDef); PL_Free (ctx->renderpassDef); - if (ctx->pipeline) { - QFV_DestroyPipeline (ctx->device, ctx->pipeline); - } if (ctx->frames.size) { Vulkan_DestroyFrames (ctx); } @@ -265,7 +263,7 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) if (!item || !(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading %s\n", name); } else { - Sys_Printf ("Found %s def\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found %s def\n", name); } return item; } @@ -282,7 +280,7 @@ qfv_load_renderpass (vulkan_ctx_t *ctx, const char *name) if (!item || !(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading %s\n", name); } else { - Sys_Printf ("Found %s def\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found %s def\n", name); } return item; } @@ -325,7 +323,6 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) name)); item = qfv_load_renderpass (ctx, "clearValues"); QFV_ParseClearValues (ctx, item, ctx->renderpassDef); - printf ("renderpass: %p\n", ctx->renderpass); qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -395,7 +392,7 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading pipeline %s\n", name); return 0; } else { - Sys_Printf ("Found pipeline def %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found pipeline def %s\n", name); } VkPipeline pipeline = QFV_ParsePipeline (ctx, item, ctx->pipelineDef); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, @@ -419,7 +416,8 @@ Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading descriptor pool %s\n", name); return 0; } else { - Sys_Printf ("Found descriptor pool def %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found descriptor pool def %s\n", + name); } pool = QFV_ParseDescriptorPool (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) pool); @@ -444,7 +442,8 @@ Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading pipeline layout %s\n", name); return 0; } else { - Sys_Printf ("Found pipeline layout def %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found pipeline layout def %s\n", + name); } layout = QFV_ParsePipelineLayout (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) layout); @@ -469,7 +468,7 @@ Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading sampler %s\n", name); return 0; } else { - Sys_Printf ("Found sampler def %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found sampler def %s\n", name); } sampler = QFV_ParseSampler (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) sampler); @@ -494,7 +493,8 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading descriptor set %s\n", name); return 0; } else { - Sys_Printf ("Found descriptor set def %s\n", name); + Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found descriptor set def %s\n", + name); } set = QFV_ParseDescriptorSetLayout (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) set); From 51d6ec7c8c3729cf794e560f00ca2347597f3c31 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 Mar 2021 12:04:09 +0900 Subject: [PATCH 1415/3664] [vulkan] Fix what looks like a thinko It looked like the code would have deleted a replacement swapchain instead of the one being replaced. --- libs/video/renderer/vulkan/vulkan_vid_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index fccf5843c..f3f152470 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -245,7 +245,7 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) free (ctx->swapchain); } ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain); - if (ctx->swapchain->swapchain == old_swapchain) { + if (old_swapchain && ctx->swapchain->swapchain != old_swapchain) { ctx->device->funcs->vkDestroySwapchainKHR (ctx->device->dev, old_swapchain, 0); } From c5c44da727893151d5489b6a7a8c159ea2522b10 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 Mar 2021 19:20:53 +0900 Subject: [PATCH 1416/3664] [vulkan] Implement screenshot Finally, I can brag about my progress on irc :) --- include/QF/Vulkan/funclist.h | 1 + include/QF/Vulkan/image.h | 2 + include/QF/Vulkan/qf_vid.h | 1 + include/QF/Vulkan/swapchain.h | 1 + include/vid_vulkan.h | 3 + libs/models/brush/vulkan_model_brush.c | 19 +----- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vid_render_vulkan.c | 68 +++++++++++++++++++ libs/video/renderer/vulkan/image.c | 15 ++++ libs/video/renderer/vulkan/swapchain.c | 5 +- .../video/renderer/vulkan/vulkan_vid_common.c | 11 +++ 11 files changed, 109 insertions(+), 18 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index e4a21d52a..9e5af1ef1 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -164,6 +164,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPipelineBarrier) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyBufferToImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyImageToBuffer) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdCopyImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBlitImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBeginRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 5e5623137..5e4866952 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -66,6 +66,8 @@ VkImageView QFV_CreateImageView (struct qfv_device_s *device, VkImage image, VkImageViewType type, VkFormat format, VkImageAspectFlags aspect); +size_t QFV_GetImageSize (struct qfv_device_s *device, VkImage image); + /** Generate all mipmaps for a given texture down to a 1x1 pixel. * * Uses the GPU blit command from one mip level to the next, thus the base mip diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index b01000d06..80f12ca67 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -60,6 +60,7 @@ enum { struct vulkan_ctx_s; void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); +void Vulkan_CreateCapture (struct vulkan_ctx_s *ctx); void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/swapchain.h b/include/QF/Vulkan/swapchain.h index 9d04b35e4..5c988f90f 100644 --- a/include/QF/Vulkan/swapchain.h +++ b/include/QF/Vulkan/swapchain.h @@ -8,6 +8,7 @@ typedef struct qfv_swapchain_s { VkFormat format; VkExtent2D extent; int32_t numImages; + VkImageUsageFlags usage; struct qfv_imageset_s *images; struct qfv_imageviewset_s *imageViews; } qfv_swapchain_t; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 70deb17f7..2a1f8fd9a 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -92,6 +92,9 @@ typedef struct vulkan_ctx_s { size_t curFrame; vulkan_frameset_t frames; + struct qfv_capture_s *capture; + void (*capture_callback) (const byte *data, int width, int height); + struct qfv_tex_s *default_black; struct qfv_tex_s *default_white; struct qfv_tex_s *default_magenta; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 2248ccdaf..a7b4dc336 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -87,21 +87,6 @@ static void vulkan_brush_clear (model_t *mod, void *data) dfunc->vkFreeMemory (device->dev, mctx->texture_memory, 0); } -static size_t -get_image_size (VkImage image, qfv_device_t *device) -{ - qfv_devfuncs_t *dfunc = device->funcs; - size_t size; - size_t align; - - VkMemoryRequirements requirements; - dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements); - size = requirements.size; - align = requirements.alignment - 1; - size = (size + align) & ~(align); - return size; -} - static void transfer_mips (byte *dst, const void *_src, const texture_t *tx, byte *palette) { @@ -193,7 +178,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) } vulktex_t *tex = tx->render; tex->tex->offset = memsize; - memsize += get_image_size (tex->tex->image, device); + memsize += QFV_GetImageSize (device, tex->tex->image); image_count++; copy_count += MIPLEVELS; if (strncmp (tx->name, "sky", 3) == 0) { @@ -204,7 +189,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) if (tex->glow) { copy_count += MIPLEVELS; tex->glow->offset = memsize; - memsize += get_image_size (tex->glow->image, device); + memsize += QFV_GetImageSize (device, tex->glow->image); image_count++; } } diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index d21a7952d..54fa0a2e3 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -250,6 +250,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/barrier.c \ libs/video/renderer/vulkan/buffer.c \ libs/video/renderer/vulkan/command.c \ + libs/video/renderer/vulkan/capture.c \ libs/video/renderer/vulkan/descriptor.c \ libs/video/renderer/vulkan/device.c \ libs/video/renderer/vulkan/image.c \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 83f0d4b51..82f677e33 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -31,7 +31,10 @@ #include #include "QF/darray.h" +#include "QF/dstring.h" +#include "QF/quakefs.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -46,6 +49,7 @@ #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/capture.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" @@ -90,6 +94,7 @@ vulkan_R_Init (void) Vulkan_CreateMatrices (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx); + Vulkan_CreateCapture (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_CreateFramebuffers (vulkan_ctx); Vulkan_Texture_Init (vulkan_ctx); @@ -165,6 +170,12 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) } dfunc->vkCmdEndRenderPass (frame->cmdBuffer); + if (vulkan_ctx->capture_callback) { + VkImage srcImage = vulkan_ctx->swapchain->images->a[imageIndex]; + VkCommandBuffer cmd = QFV_CaptureImage (vulkan_ctx->capture, srcImage, + vulkan_ctx->curFrame); + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, 1, &cmd); + } dfunc->vkEndCommandBuffer (frame->cmdBuffer); VkPipelineStageFlags waitStage @@ -178,6 +189,17 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) dfunc->vkResetFences (dev, 1, &frame->fence); dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); + if (vulkan_ctx->capture_callback) { + //FIXME look into "threading" this rather than waiting here + dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE, + 1000000000ull); + vulkan_ctx->capture_callback (QFV_CaptureData (vulkan_ctx->capture, + vulkan_ctx->curFrame), + vulkan_ctx->capture->extent.width, + vulkan_ctx->capture->extent.height); + vulkan_ctx->capture_callback = 0; + } + VkPresentInfoKHR presentInfo = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, 1, &frame->renderDoneSemaphore, @@ -358,9 +380,55 @@ vulkan_R_InitParticles (void) Vulkan_InitParticles (vulkan_ctx); } +static int +is_bgr (VkFormat format) +{ + return (format >= VK_FORMAT_B8G8R8A8_UNORM + && format <= VK_FORMAT_B8G8R8A8_SRGB); +} + +static void +capture_screenshot (const byte *data, int width, int height) +{ + dstring_t *name = dstring_new (); + // find a file name to save it to + if (!QFS_NextFilename (name, va (vulkan_ctx->va_ctx, "%s/qf", + qfs_gamedir->dir.shots), + ".ppm")) { + Sys_Printf ("SCR_ScreenShot_f: Couldn't create a ppm file\n"); + } else { + QFile *file = QFS_Open (name->str, "wb"); + if (!file) { + Sys_Printf ("Couldn't open %s\n", name->str); + } else { + Qprintf (file, "P6\n%d\n%d\n255\n", width, height); + if (vulkan_ctx->capture->canBlit || + !is_bgr (vulkan_ctx->swapchain->format)) { + for (int count = width * height; count-- > 0; ) { + Qwrite (file, data, 3); + data += 4; + } + } else { + for (int count = width * height; count-- > 0; ) { + byte rgb[] = { data[2], data[1], data[0] }; + Qwrite (file, rgb, 3); + data += 4; + } + } + Qclose (file); + } + } + dstring_delete (name); +} + static void vulkan_SCR_ScreenShot_f (void) { + if (!vulkan_ctx->capture) { + Sys_Printf ("Screenshot not supported\n"); + return; + } + vulkan_ctx->capture_callback = capture_screenshot; } static void diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 41b4586f0..c05ececf9 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -194,6 +194,21 @@ QFV_CreateImageView (qfv_device_t *device, VkImage image, return view; } +size_t +QFV_GetImageSize (qfv_device_t *device, VkImage image) +{ + qfv_devfuncs_t *dfunc = device->funcs; + size_t size; + size_t align; + + VkMemoryRequirements requirements; + dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements); + size = requirements.size; + align = requirements.alignment - 1; + size = (size + align) & ~(align); + return size; +} + void QFV_GenerateMipMaps (qfv_device_t *device, VkCommandBuffer cmd, VkImage image, unsigned mips, diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 478700e83..762e2c799 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -83,8 +83,10 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) imageSize.width, imageSize.height); VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; imageUsage &= surfCaps.supportedUsageFlags; + Sys_MaskPrintf (SYS_VULKAN, "%x %x\n", imageUsage, + surfCaps.supportedUsageFlags); VkSurfaceTransformFlagBitsKHR surfTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; @@ -147,6 +149,7 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) sc->format = useFormat.format; sc->extent = imageSize; sc->numImages = numImages; + sc->usage = imageUsage; sc->images = DARRAY_ALLOCFIXED (qfv_imageset_t, numImages, malloc); sc->imageViews = DARRAY_ALLOCFIXED (qfv_imageviewset_t, numImages, malloc); dfuncs->vkGetSwapchainImagesKHR (dev, swapchain, &numImages, sc->images->a); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index f3f152470..a0301e1a1 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -54,6 +54,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/capture.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" @@ -189,6 +190,9 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { PL_Free (ctx->pipelineDef); PL_Free (ctx->renderpassDef); + if (ctx->capture) { + QFV_DestroyCapture (ctx->capture); + } if (ctx->frames.size) { Vulkan_DestroyFrames (ctx); } @@ -535,6 +539,13 @@ Vulkan_CreateFrames (vulkan_ctx_t *ctx) } } +void +Vulkan_CreateCapture (vulkan_ctx_t *ctx) +{ + ctx->capture = QFV_CreateCapture (ctx->device, ctx->frames.size, + ctx->swapchain, ctx->cmdpool); +} + void Vulkan_DestroyFrames (vulkan_ctx_t *ctx) { From 999dd8248bf716c1361251d3f2391d4de7449d69 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Mar 2021 15:54:34 +0900 Subject: [PATCH 1417/3664] [vulkan] Implement sky box loading and rendering Loading is broken for multi-file image sets due to the way images are loaded (this needs some thought for making it effecient), but the Blender environment map loading works. --- include/QF/Vulkan/qf_bsp.h | 4 +- include/QF/Vulkan/qf_texture.h | 4 + libs/video/renderer/vid_render_vulkan.c | 1 + libs/video/renderer/vulkan/qfpipeline.plist | 37 +++ .../video/renderer/vulkan/shader/bsp_sky.frag | 15 +- libs/video/renderer/vulkan/vulkan_bsp.c | 138 ++++----- libs/video/renderer/vulkan/vulkan_texture.c | 277 +++++++++++++++--- .../video/renderer/vulkan/vulkan_vid_common.c | 2 +- 8 files changed, 342 insertions(+), 136 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 7f279ffc2..6c69f2586 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -146,7 +146,8 @@ typedef struct bspctx_s { VkDeviceMemory texture_memory; VkPipeline depth; VkPipeline gbuf; - VkPipeline sky; + VkPipeline skysheet; + VkPipeline skybox; VkPipeline turb; VkPipelineLayout layout; size_t vertex_buffer_size; @@ -162,6 +163,7 @@ struct vulkan_ctx_s; void Vulkan_ClearElements (struct vulkan_ctx_s *ctx); void Vulkan_DrawWorld (struct vulkan_ctx_s *ctx); void Vulkan_DrawSky (struct vulkan_ctx_s *ctx); +void Vulkan_LoadSkys (const char *sky, struct vulkan_ctx_s *ctx); void Vulkan_RegisterTextures (model_t **models, int num_models, struct vulkan_ctx_s *ctx); void Vulkan_BuildDisplayLists (model_t **models, int num_models, diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index a70ba1116..55a631f62 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -15,6 +15,10 @@ void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, int alpha, int count); qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip, const char *name); +qfv_tex_t *Vulkan_LoadEnvMap (struct vulkan_ctx_s *ctx, tex_t *tex, + const char *name); +qfv_tex_t *Vulkan_LoadEnvSides (struct vulkan_ctx_s *ctx, tex_t **tex, + const char *name); VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure)); void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex); void Vulkan_Texture_Init (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 82f677e33..836e1349a 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -223,6 +223,7 @@ vulkan_R_ClearState (void) static void vulkan_R_LoadSkys (const char *skyname) { + Vulkan_LoadSkys (skyname, vulkan_ctx); } static void diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 2d95f06b4..d19294a80 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -652,6 +652,43 @@ layout = quakebsp_layout; //renderPass = renderpass; }; + bsp_skybox = { + subpass = 1; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/bsp_sky.frag; + specializationInfo = { + mapEntries = ( + { size = 4; offset = 0; constantID = 1; }, + { size = 4; offset = 4; constantID = 0; }, + ); + data = <00000000ffffffff>; + }; + }, + ); + vertexInput = $properties.vertexInput.brush; + inputAssembly = $properties.inputAssembly.brush; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_only; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.disabled); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = quakebsp_layout; + //renderPass = renderpass; + }; bsp_skysheet = { subpass = 1; stages = ( diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index 28ce41421..ed6828a10 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -14,7 +14,7 @@ layout (location = 1) in vec3 direction; layout (location = 0) out vec4 frag_color; -layout (constant_id = 0) const bool doSkyCube = false; +layout (constant_id = 0) const bool doSkyBox = false; layout (constant_id = 1) const bool doSkySheet = false; const float SCALE = 8.0; @@ -55,12 +55,14 @@ sky_sheet (vec3 dir, float time) } vec4 -sky_cube (vec3 dir, float time) +sky_box (vec3 dir, float time) { // NOTE: quake's world is right-handed with Z up and X forward, but // Vulkan's cube maps are left-handed with Y up and Z forward. The // rotation to X foward is done by the Sky matrix so all that's left // to do here is swizzle the Y and Z coordinates + dir = normalize(dir); + //return vec4(dir.xyz, 1) * 0.5 + vec4(0.5); return texture (SkyCube, dir.xzy); } @@ -68,15 +70,14 @@ vec4 sky_color (vec3 dir, float time) { if (!doSkySheet) { - return vec4 (1, 0, 1, 1); - //return sky_cube (dir, time); - } if (!doSkyCube) { + return sky_box (dir, time); + } if (!doSkyBox) { return sky_sheet (dir, time); } else { // can see through the sheet (may look funny when looking down) // maybe have 4 sheet layers instead of 2? vec4 c1 = sky_sheet (dir, time); - vec4 c2 = sky_cube (dir, time); + vec4 c2 = sky_box (dir, time); return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); return vec4 (1, 0, 1, 1); } @@ -87,7 +88,7 @@ main (void) { vec4 c; - if (doSkyCube || doSkySheet) { + if (doSkyBox || doSkySheet) { c = sky_color (direction, time); } else { c = vec4 (0, 0, 0, 1); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a85625440..bceea6666 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1054,7 +1054,11 @@ sky_begin (vulkan_ctx_t *ctx) bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, bctx->default_skybox); - bsp_begin_subpass (QFV_bspSky, bctx->sky, ctx); + if (bctx->skybox_tex) { + bsp_begin_subpass (QFV_bspSky, bctx->skybox, ctx); + } else { + bsp_begin_subpass (QFV_bspSky, bctx->skysheet, ctx); + } } static void @@ -1370,7 +1374,7 @@ create_default_skys (vulkan_ctx_t *ctx) VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, boxview, - "bsp:iview:default_skysheet"); + "bsp:iview:default_skybox"); sheetview = QFV_CreateImageView (device, skysheet, VK_IMAGE_VIEW_TYPE_2D_ARRAY, @@ -1481,7 +1485,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->depth = Vulkan_CreatePipeline (ctx, "bsp_depth"); bctx->gbuf = Vulkan_CreatePipeline (ctx, "bsp_gbuf"); - bctx->sky = Vulkan_CreatePipeline (ctx, "bsp_skysheet"); + bctx->skybox = Vulkan_CreatePipeline (ctx, "bsp_skybox"); + bctx->skysheet = Vulkan_CreatePipeline (ctx, "bsp_skysheet"); bctx->turb = Vulkan_CreatePipeline (ctx, "bsp_turb"); bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); @@ -1533,7 +1538,8 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) dfunc->vkDestroyPipeline (device->dev, bctx->depth, 0); dfunc->vkDestroyPipeline (device->dev, bctx->gbuf, 0); - dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0); + dfunc->vkDestroyPipeline (device->dev, bctx->skybox, 0); + dfunc->vkDestroyPipeline (device->dev, bctx->skysheet, 0); dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0); DARRAY_CLEAR (&bctx->texture_chains); DARRAY_CLEAR (&bctx->frames); @@ -1548,6 +1554,10 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) dfunc->vkFreeMemory (device->dev, bctx->index_memory, 0); } + if (bctx->skybox_tex) { + Vulkan_UnloadTex (ctx, bctx->skybox_tex); + } + dfunc->vkDestroyImageView (device->dev, bctx->default_skysheet->view, 0); dfunc->vkDestroyImage (device->dev, bctx->default_skysheet->image, 0); @@ -1590,103 +1600,61 @@ copy_sub_tex (tex_t *src, int x, int y, tex_t *dst) dstbytes); }*/ -/*XXX void -Vulkan_R_LoadSkys (const char *sky, vulkan_ctx_t *ctx) +void +Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) { -const char *name; + bspctx_t *bctx = ctx->bsp_context; + + const char *name; int i; tex_t *tex; - // NOTE: quake's world and GL's world are rotated relative to each other - // quake has x right, y in, z up. gl has x right, y up, z out - // quake order: +x -x +z -z +y -y - // gl order: +x -x +y -y +z -z - // fizquake orger: -y +y +z -z +x -x - // to get from quake order to fitzquake order, all that's needed is - // a -90 degree rotation on the (quake) z-axis. This is taken care of in - // the sky_matrix setup code. - // However, from the player's perspective, skymaps have lf and rt - // swapped, but everythink makes sense if looking at the cube from outside - // along the positive y axis, with the front of the cube being the nearest - // face. This matches nicely with Blender's default cube in front (num-1) - // view. static const char *sky_suffix[] = { "ft", "bk", "up", "dn", "rt", "lf"}; - static int sky_coords[][2] = { - {2, 0}, // front - {0, 0}, // back - {1, 1}, // up - {0, 1}, // down - {2, 1}, // left - {1, 0}, // right - }; - if (!sky || !*sky) + if (bctx->skybox_tex) { + Vulkan_UnloadTex (ctx, bctx->skybox_tex); + } + bctx->skybox_tex = 0; + + if (!sky || !*sky) { sky = r_skyname->string; + } if (!*sky || !strcasecmp (sky, "none")) { - skybox_loaded = false; + Sys_MaskPrintf (SYS_VULKAN, "Skybox unloaded\n"); return; } - if (!skybox_tex) - qfeglGenTextures (1, &skybox_tex); - - qfeglBindTexture (GL_TEXTURE_CUBE_MAP, skybox_tex); - - //blender envmap - // bk rt ft - // dn up lt - tex = LoadImage (name = va ("env/%s_map", sky)); - if (tex && tex->format >= 3 && tex->height * 3 == tex->width * 2 - && is_pow2 (tex->height)) { - tex_t *sub; - int size = tex->height / 2; - - skybox_loaded = true; - sub = malloc (field_offset (tex_t, data[size * size * tex->format])); - sub->width = size; - sub->height = size; - sub->format = tex->format; - sub->palette = tex->palette; - for (i = 0; i < 6; i++) { - int x, y; - x = sky_coords[i][0] * size; - y = sky_coords[i][1] * size; - copy_sub_tex (tex, x, y, sub); - qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, - sub->format == 3 ? GL_RGB : GL_RGBA, - sub->width, sub->height, 0, - sub->format == 3 ? GL_RGB : GL_RGBA, - GL_UNSIGNED_BYTE, sub->data); - } - free (sub); + name = va (ctx->va_ctx, "env/%s_map", sky); + tex = LoadImage (name, 1); + if (tex) { + bctx->skybox_tex = Vulkan_LoadEnvMap (ctx, tex, sky); + Sys_MaskPrintf (SYS_VULKAN, "Loaded %s\n", name); } else { - skybox_loaded = true; + int failed = 0; + tex_t *sides[6] = { }; + for (i = 0; i < 6; i++) { - tex = LoadImage (name = va ("env/%s%s", sky, sky_suffix[i])); - if (!tex || tex->format < 3) { // FIXME pcx support - Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); + name = va (ctx->va_ctx, "env/%s%s", sky, sky_suffix[i]); + tex = LoadImage (name, 1); + if (!tex) { + Sys_MaskPrintf (SYS_VULKAN, "Couldn't load %s\n", name); // also look in gfx/env, where Darkplaces looks for skies - tex = LoadImage (name = va ("gfx/env/%s%s", sky, - sky_suffix[i])); - if (!tex || tex->format < 3) { // FIXME pcx support - Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); - skybox_loaded = false; + name = va (ctx->va_ctx, "gfx/env/%s%s", sky, sky_suffix[i]); + tex = LoadImage (name, 1); + if (!tex) { + Sys_MaskPrintf (SYS_VULKAN, "Couldn't load %s\n", name); + failed = 1; continue; } } - Sys_MaskPrintf (SYS_GLSL, "Loaded %s\n", name); - qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, - tex->format == 3 ? GL_RGB : GL_RGBA, - tex->width, tex->height, 0, - tex->format == 3 ? GL_RGB : GL_RGBA, - GL_UNSIGNED_BYTE, tex->data); + sides[i] = tex; + Sys_MaskPrintf (SYS_VULKAN, "Loaded %s\n", name); + } + if (!failed) { + bctx->skybox_tex = Vulkan_LoadEnvSides (ctx, sides, sky); } } - qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - qfeglGenerateMipmap (GL_TEXTURE_CUBE_MAP); -}*/ + if (bctx->skybox_tex) { + Sys_MaskPrintf (SYS_VULKAN, "Skybox %s loaded\n", sky); + } +} diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 7d975298d..7aa8cfc64 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -96,45 +96,76 @@ Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, } } +static int +tex_format (const tex_t *tex, VkFormat *format, int *bpp) +{ + switch (tex->format) { + case tex_l: + case tex_a: + *format = VK_FORMAT_R8_UNORM; + *bpp = 1; + return 1; + case tex_la: + *format = VK_FORMAT_R8G8_UNORM; + *bpp = 2; + return 1; + case tex_palette: + if (!tex->palette) { + return 0; + } + *format = VK_FORMAT_R8G8B8A8_UNORM; + *bpp = 4; + return 1; + case tex_rgb: + *format = VK_FORMAT_R8G8B8A8_UNORM; + *bpp = 4; + return 1; + case tex_rgba: + *format = VK_FORMAT_R8G8B8A8_UNORM; + *bpp = 4; + return 1; + case tex_frgba: + *format = VK_FORMAT_R32G32B32A32_SFLOAT; + *bpp = 16; + return 1; + } + return 0; +} + +static size_t +stage_tex_data (qfv_packet_t *packet, tex_t *tex, int bpp) +{ + size_t texels = tex->width * tex->height; + byte *tex_data = QFV_PacketExtend (packet, bpp * texels); + + if (tex->format == tex_palette) { + Vulkan_ExpandPalette (tex_data, tex->data, tex->palette, 1, texels); + } else { + if (tex->format == 3) { + byte *in = tex->data; + byte *out = tex_data; + while (texels-- > 0) { + *out++ = *in++; + *out++ = *in++; + *out++ = *in++; + *out++ = 255; + } + } else { + memcpy (tex_data, tex->data, bpp * texels); + } + } + return tex_data - (byte *) packet->stage->data; +} + qfv_tex_t * Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - int bpp = 0; - VkFormat format = VK_FORMAT_UNDEFINED; + int bpp; + VkFormat format; - switch (tex->format) { - case tex_l: - case tex_a: - format = VK_FORMAT_R8_UNORM; - bpp = 1; - break; - case tex_la: - format = VK_FORMAT_R8G8_UNORM; - bpp = 2; - break; - case tex_palette: - if (!tex->palette) { - return 0; - } - format = VK_FORMAT_R8G8B8A8_UNORM; - bpp = 4; - break; - case tex_rgb: - format = VK_FORMAT_R8G8B8_UNORM; - bpp = 3; - break; - case tex_rgba: - format = VK_FORMAT_R8G8B8A8_UNORM; - bpp = 4; - break; - case tex_frgba: - format = VK_FORMAT_R32G32B32A32_SFLOAT; - bpp = 16; - break; - } - if (format == VK_FORMAT_UNDEFINED) { + if (!tex_format (tex, &format, &bpp)) { return 0; } @@ -169,16 +200,8 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, qtex->view, va (ctx->va_ctx, "iview:%s", name)); - size_t bytes = bpp * tex->width * tex->height; qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); - byte *tex_data = QFV_PacketExtend (packet, bytes); - - if (tex->format == tex_palette) { - Vulkan_ExpandPalette (tex_data, tex->data, tex->palette, - 1, tex->width * tex->height); - } else { - memcpy (tex_data, tex->data, bytes); - } + stage_tex_data (packet, tex, bpp); VkImageMemoryBarrier barrier; qfv_pipelinestagepair_t stages; @@ -214,6 +237,176 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) return qtex; } +static qfv_tex_t * +create_cubetex (vulkan_ctx_t *ctx, int size, VkFormat format, + const char *name) +{ + qfv_device_t *device = ctx->device; + + qfv_tex_t *qtex = malloc (sizeof (qfv_tex_t)); + + VkExtent3D extent = { size, size, 1 }; + qtex->image = QFV_CreateImage (device, 1, VK_IMAGE_TYPE_2D, format, extent, + 1, 1, VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, qtex->image, + va (ctx->va_ctx, "image:envmap:%s", name)); + qtex->memory = QFV_AllocImageMemory (device, qtex->image, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + 0, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, qtex->memory, + va (ctx->va_ctx, "memory:%s", name)); + QFV_BindImageMemory (device, qtex->image, qtex->memory, 0); + qtex->view = QFV_CreateImageView (device, qtex->image, + VK_IMAGE_VIEW_TYPE_CUBE, format, + VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, qtex->view, + va (ctx->va_ctx, "iview:envmap:%s", name)); + + return qtex; +} + +qfv_tex_t * +Vulkan_LoadEnvMap (vulkan_ctx_t *ctx, tex_t *tex, const char *name) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + int bpp; + VkFormat format; + + static int env_coords[][2] = { + {2, 0}, // right + {0, 0}, // left + {1, 1}, // top + {0, 1}, // bottom + {2, 1}, // front + {1, 0}, // back + }; + + if (!tex_format (tex, &format, &bpp)) { + return 0; + } + if (tex->height * 3 != tex->width * 2) { + return 0; + } + + int size = tex->height / 2; + qfv_tex_t *qtex = create_cubetex (ctx, size, format, name); + + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + stage_tex_data (packet, tex, bpp); + + VkImageMemoryBarrier barrier; + qfv_pipelinestagepair_t stages; + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + barrier.image = qtex->image; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + + VkBufferImageCopy copy[6] = { + { + 0, tex->width, 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, {size, size, 1}, + }, + }; + for (int i = 0; i < 6; i++) { + int x = env_coords[i][0] * size; + int y = env_coords[i][1] * size; + int offset = x + y * tex->width; + copy[i] = copy[0]; + copy[i].bufferOffset = packet->offset + bpp * offset; + copy[i].imageSubresource.baseArrayLayer = i; + } + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + qtex->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 6, copy); + stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier.image = qtex->image; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + QFV_PacketSubmit (packet); + return qtex; +} + +qfv_tex_t * +Vulkan_LoadEnvSides (vulkan_ctx_t *ctx, tex_t **tex, const char *name) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + int bpp; + VkFormat format; + + if (!tex_format (tex[0], &format, &bpp)) { + return 0; + } + if (tex[0]->height != tex[0]->width) { + return 0; + } + for (int i = 1; i < 6; i++) { + if (tex[i]->format != tex[0]->format + || tex[i]->width != tex[0]->width + || tex[i]->height != tex[0]->height) { + return 0; + } + } + + int size = tex[0]->height; + qfv_tex_t *qtex = create_cubetex (ctx, size, format, name); + + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + + VkImageMemoryBarrier barrier; + qfv_pipelinestagepair_t stages; + + stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; + barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; + barrier.image = qtex->image; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + + VkBufferImageCopy copy[6] = { + { + 0, 0, 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, {size, size, 1}, + }, + }; + for (int i = 0; i < 6; i++) { + copy[i] = copy[0]; + copy[i].bufferOffset = stage_tex_data (packet, tex[i], bpp); + copy[i].imageSubresource.baseArrayLayer = i; + } + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + qtex->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 6, copy); + stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + barrier.image = qtex->image; + barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + 0, 0, 0, 0, 0, + 1, &barrier); + QFV_PacketSubmit (packet); + return qtex; +} + VkImageView Vulkan_TexImageView (qfv_tex_t *tex) { diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a0301e1a1..e18b5d689 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -237,7 +237,7 @@ void Vulkan_CreateStagingBuffers (vulkan_ctx_t *ctx) { ctx->staging = QFV_CreateStagingBuffer (ctx->device, "vulkan_ctx", - 4*1024*1024, ctx->cmdpool); + 16*1024*1024, ctx->cmdpool); } void From 457306edad0c14a54d6c81f2714557e28cc48eff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Mar 2021 15:56:01 +0900 Subject: [PATCH 1418/3664] [qw] Fix handling of sky box name The handling was broken during some merge work. Need to find a good way to unify it all (probably by giving nq a fake serverinfo). --- qw/source/cl_parse.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 4f0c93475..a1e8474ca 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -177,15 +177,29 @@ CL_LoadSky (void) { plitem_t *item; const char *name = 0; + static const char *sky_keys[] = { + "sky", // Q2/DarkPlaces + "skyname", // old QF + "qlsky", // QuakeLives + 0 + }; - if (!cl.worldspawn) { - r_funcs->R_LoadSkys (0); - return; + // R_LoadSkys does the right thing with null pointers. + if (cl.serverinfo) { + name = Info_ValueForKey (cl.serverinfo, "sky"); } - if ((item = PL_ObjectForKey (cl.worldspawn, "sky")) // Q2/DarkPlaces - || (item = PL_ObjectForKey (cl.worldspawn, "skyname")) // old QF - || (item = PL_ObjectForKey (cl.worldspawn, "qlsky"))) /* QuakeLives */ { - name = PL_String (item); + + if (!name) { + if (!cl.worldspawn) { + r_funcs->R_LoadSkys (0); + return; + } + for (const char **key = sky_keys; *key; key++) { + if ((item = PL_ObjectForKey (cl.worldspawn, *key))) { + name = PL_String (item); + break; + } + } } r_funcs->R_LoadSkys (name); } From 32c2e013ca6248aaa42edc59177600322b4a4486 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Mar 2021 15:59:28 +0900 Subject: [PATCH 1419/3664] [vulkan] Add missed screen capture files Rather critical to the build (and screenshots) --- include/QF/Vulkan/capture.h | 43 +++++ libs/video/renderer/vulkan/capture.c | 270 +++++++++++++++++++++++++++ 2 files changed, 313 insertions(+) create mode 100644 include/QF/Vulkan/capture.h create mode 100644 libs/video/renderer/vulkan/capture.c diff --git a/include/QF/Vulkan/capture.h b/include/QF/Vulkan/capture.h new file mode 100644 index 000000000..a2fa1397b --- /dev/null +++ b/include/QF/Vulkan/capture.h @@ -0,0 +1,43 @@ +#ifndef __QF_Vulkan_capture_h +#define __QF_Vulkan_capture_h + +#include "QF/darray.h" +#include "QF/qtypes.h" + +typedef struct qfv_capture_image_s { + VkImage image; + VkImageLayout layout; + VkCommandBuffer cmd; + byte *data; +} qfv_capture_image_t; + +typedef struct qfv_capture_image_set_s + DARRAY_TYPE (qfv_capture_image_t) qfv_capture_image_set_t; + +#define QFV_AllocCaptureImageSet(num, allocator) \ + DARRAY_ALLOCFIXED (qfv_capture_image_set_t, num, allocator) + +typedef struct qfv_capture_s { + struct qfv_device_s *device; + + int canBlit; + VkExtent2D extent; + qfv_capture_image_set_t *image_set; + size_t memsize; + VkDeviceMemory memory; +} qfv_capture_t; + +struct qfv_swapchain_s; + +qfv_capture_t *QFV_CreateCapture (struct qfv_device_s *device, int numframes, + struct qfv_swapchain_s *swapchain, + VkCommandPool cmdPool); +void QFV_RenewCapture (qfv_capture_t *capture, + struct qfv_swapchain_s *swapchain); +void QFV_DestroyCapture (qfv_capture_t *capture); + +VkCommandBuffer QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, + int frame); +const byte *QFV_CaptureData (qfv_capture_t *capture, int frame) __attribute__((pure)); + +#endif//__QF_Vulkan_capture_h diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c new file mode 100644 index 000000000..1fa0d8193 --- /dev/null +++ b/libs/video/renderer/vulkan/capture.c @@ -0,0 +1,270 @@ +/* + capture.c + + Vulkan frame capture support + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/capture.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/swapchain.h" + +#include "vid_vulkan.h" + +qfv_capture_t * +QFV_CreateCapture (qfv_device_t *device, int numframes, + qfv_swapchain_t *swapchain, VkCommandPool cmdPool) +{ + qfv_instfuncs_t *ifunc = device->physDev->instance->funcs; + qfv_devfuncs_t *dfunc = device->funcs; + VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; + int canBlit = 1; + + VkFormatProperties format_props; + ifunc->vkGetPhysicalDeviceFormatProperties (device->physDev->dev, + swapchain->format, + &format_props); + if (!(swapchain->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) { + Sys_Printf ("Swapchain does not support reading. FIXME\n"); + return 0; + } + if (!(format_props.optimalTilingFeatures + & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) { + Sys_MaskPrintf (SYS_VULKAN, + "Device does not support blitting from optimal tiled " + "images.\n"); + canBlit = 0; + } + ifunc->vkGetPhysicalDeviceFormatProperties (device->physDev->dev, format, + &format_props); + if (!(format_props.linearTilingFeatures + & VK_FORMAT_FEATURE_BLIT_DST_BIT)) { + Sys_MaskPrintf (SYS_VULKAN, + "Device does not support blitting from optimal tiled " + "images.\n"); + canBlit = 0; + } + + qfv_capture_t *capture = malloc (sizeof (qfv_capture_t)); + capture->device = device; + capture->canBlit = canBlit; + capture->extent = swapchain->extent; + capture->image_set = QFV_AllocCaptureImageSet (numframes, malloc); + + __auto_type cmdset = QFV_AllocCommandBufferSet (numframes, alloca); + QFV_AllocateCommandBuffers (device, cmdPool, 1, cmdset); + + VkImageCreateInfo createInfo = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .imageType = VK_IMAGE_TYPE_2D, + .format = format, + .extent = { swapchain->extent.width, swapchain->extent.height, 1 }, + .arrayLayers = 1, + .mipLevels = 1, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_LINEAR, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT, + }; + + for (int i = 0; i < numframes; i++) { + __auto_type image = &capture->image_set->a[i]; + dfunc->vkCreateImage (device->dev, &createInfo, 0, &image->image); + image->layout = VK_IMAGE_LAYOUT_UNDEFINED; + image->cmd = cmdset->a[i]; + } + size_t image_size = QFV_GetImageSize (device, + capture->image_set->a[0].image); + capture->memsize = numframes * image_size; + capture->memory = QFV_AllocImageMemory (device, + capture->image_set->a[0].image, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + capture->memsize, 0); + byte *data; + dfunc->vkMapMemory (device->dev, capture->memory, 0, capture->memsize, 0, + (void **) &data); + + for (int i = 0; i < numframes; i++) { + __auto_type image = &capture->image_set->a[i]; + image->data = data + i * image_size; + dfunc->vkBindImageMemory (device->dev, image->image, capture->memory, + image->data - data); + } + return capture; +} + +void +QFV_DestroyCapture (qfv_capture_t *capture) +{ + qfv_device_t *device = capture->device; + qfv_devfuncs_t *dfunc = device->funcs; + + for (size_t i = 0; i < capture->image_set->size; i++) { + __auto_type image = &capture->image_set->a[i]; + dfunc->vkDestroyImage (device->dev, image->image, 0); + } + dfunc->vkUnmapMemory (device->dev, capture->memory); + dfunc->vkFreeMemory (device->dev, capture->memory, 0); + free (capture->image_set); + free (capture); +} + +static void +blit_image (qfv_capture_t *capture, qfv_devfuncs_t *dfunc, + VkImage scImage, qfv_capture_image_t *image) +{ + VkImageBlit blit = { + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, + { { }, { capture->extent.width, capture->extent.height, 1 } }, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, + { { }, { capture->extent.width, capture->extent.height, 1 } }, + }; + dfunc->vkCmdBlitImage (image->cmd, + scImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + 1, &blit, VK_FILTER_NEAREST); +} + +static void +copy_image (qfv_capture_t *capture, qfv_devfuncs_t *dfunc, + VkImage scImage, qfv_capture_image_t *image) +{ + VkImageCopy copy = { + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, { }, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, { }, + { capture->extent.width, capture->extent.height, 1 }, + }; + dfunc->vkCmdCopyImage (image->cmd, + scImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©); +} + +VkCommandBuffer +QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame) +{ + qfv_device_t *device = capture->device; + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type image = &capture->image_set->a[frame]; + + dfunc->vkResetCommandBuffer (image->cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + 0, 0, 0, 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (image->cmd, &beginInfo); + + VkImageMemoryBarrier start_barriers[] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .oldLayout = image->layout, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .image = image->image, + .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + .image = scImage, + .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }, + }, + }; + VkImageMemoryBarrier end_barriers[] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .image = image->image, + .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT, + .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .image = scImage, + .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }, + }, + }; + + dfunc->vkCmdPipelineBarrier (image->cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, 0, 0, 0, + 2, start_barriers); + + if (capture->canBlit) { + blit_image (capture, dfunc, scImage, image); + } else { + copy_image (capture, dfunc, scImage, image); + } + + dfunc->vkCmdPipelineBarrier (image->cmd, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, 0, 0, 0, 0, + 2, end_barriers); + image->layout = VK_IMAGE_LAYOUT_GENERAL; + + dfunc->vkEndCommandBuffer (image->cmd); + + return image->cmd; +} + +const byte * +QFV_CaptureData (qfv_capture_t *capture, int frame) +{ + __auto_type image = &capture->image_set->a[frame]; + return image->data; +} From 132e25b0963d3f1d735c9f0a4b3dbdb62fe768b4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Jan 2013 21:38:42 +0900 Subject: [PATCH 1420/3664] Remove a bunch of unnecessary fields from nq. The server never accesses the fields, and they're not used in qw either, so no point in storing pointers to them. --- nq/include/sv_progs.h | 22 ---------------------- nq/source/sv_progs.c | 23 ----------------------- 2 files changed, 45 deletions(-) diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index e1b8d4e4a..d37bd441b 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -105,22 +105,17 @@ typedef struct pr_int_t velocity; //vec3_t pr_int_t angles; //vec3_t pr_int_t avelocity; //vec3_t - pr_int_t basevelocity; //vec3_t pr_int_t punchangle; //vec3_t pr_int_t classname; //string_t pr_int_t model; //string_t pr_int_t frame; //float pr_int_t skin; //float pr_int_t effects; //float - pr_int_t drawPercent; //float pr_int_t gravity; //float - pr_int_t mass; //float - pr_int_t light_level; //float pr_int_t mins; //vec3_t pr_int_t maxs; //vec3_t pr_int_t size; //vec3_t pr_int_t touch; //func_t - pr_int_t use; //func_t pr_int_t think; //func_t pr_int_t blocked; //func_t pr_int_t nextthink; //float @@ -139,7 +134,6 @@ typedef struct pr_int_t items2; //float pr_int_t takedamage; //float pr_int_t chain; //int - pr_int_t deadflag; //float pr_int_t view_ofs; //vec3_t pr_int_t button0; //float pr_int_t button1; //float @@ -148,25 +142,19 @@ typedef struct pr_int_t fixangle; //float pr_int_t v_angle; //vec3_t pr_int_t idealpitch; //float - pr_int_t pitch_speed; //float pr_int_t netname; //string_t pr_int_t enemy; //int pr_int_t flags; //float pr_int_t colormap; //float pr_int_t team; //float - pr_int_t max_health; //float pr_int_t teleport_time; //float - pr_int_t armortype; //float pr_int_t armorvalue; //float pr_int_t waterlevel; //float pr_int_t watertype; //float pr_int_t ideal_yaw; //float pr_int_t yaw_speed; //float - pr_int_t aiment; //int pr_int_t goalentity; //int pr_int_t spawnflags; //float - pr_int_t target; //string_t - pr_int_t targetname; //string_t pr_int_t dmg_take; //float pr_int_t dmg_save; //float pr_int_t dmg_inflictor; //int @@ -174,16 +162,6 @@ typedef struct pr_int_t movedir; //vec3_t pr_int_t message; //string_t pr_int_t sounds; //float - pr_int_t noise; //string_t - pr_int_t noise1; //string_t - pr_int_t noise2; //string_t - pr_int_t noise3; //string_t - pr_int_t dmg; //float - pr_int_t dmgtime; //float - pr_int_t air_finished; //float - pr_int_t pain_finished; //float - pr_int_t radsuit_finished; //float - pr_int_t speed; //float pr_int_t rotated_bbox; //int pr_int_t alpha; //float diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 37b915e9c..ca80ae190 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -255,7 +255,6 @@ static sv_def_t nq_fields[] = { {ev_vector, 36, "maxs", &sv_fields.maxs}, {ev_vector, 39, "size", &sv_fields.size}, {ev_func, 42, "touch", &sv_fields.touch}, - {ev_func, 43, "use", &sv_fields.use}, {ev_func, 44, "think", &sv_fields.think}, {ev_func, 45, "blocked", &sv_fields.blocked}, {ev_float, 46, "nextthink", &sv_fields.nextthink}, @@ -273,7 +272,6 @@ static sv_def_t nq_fields[] = { {ev_float, 58, "items", &sv_fields.items}, {ev_float, 59, "takedamage", &sv_fields.takedamage}, {ev_entity, 60, "chain", &sv_fields.chain}, - {ev_float, 61, "deadflag", &sv_fields.deadflag}, {ev_vector, 62, "view_ofs", &sv_fields.view_ofs}, {ev_float, 65, "button0", &sv_fields.button0}, {ev_float, 66, "button1", &sv_fields.button1}, @@ -287,19 +285,14 @@ static sv_def_t nq_fields[] = { {ev_float, 76, "flags", &sv_fields.flags}, {ev_float, 77, "colormap", &sv_fields.colormap}, {ev_float, 78, "team", &sv_fields.team}, - {ev_float, 79, "max_health", &sv_fields.max_health}, {ev_float, 80, "teleport_time", &sv_fields.teleport_time}, - {ev_float, 81, "armortype", &sv_fields.armortype}, {ev_float, 82, "armorvalue", &sv_fields.armorvalue}, {ev_float, 83, "waterlevel", &sv_fields.waterlevel}, {ev_float, 84, "watertype", &sv_fields.watertype}, {ev_float, 85, "ideal_yaw", &sv_fields.ideal_yaw}, {ev_float, 86, "yaw_speed", &sv_fields.yaw_speed}, - {ev_entity, 87, "aiment", &sv_fields.aiment}, {ev_entity, 88, "goalentity", &sv_fields.goalentity}, {ev_float, 89, "spawnflags", &sv_fields.spawnflags}, - {ev_string, 90, "target", &sv_fields.target}, - {ev_string, 91, "targetname", &sv_fields.targetname}, {ev_float, 92, "dmg_take", &sv_fields.dmg_take}, {ev_float, 93, "dmg_save", &sv_fields.dmg_save}, {ev_entity, 94, "dmg_inflictor", &sv_fields.dmg_inflictor}, @@ -307,10 +300,6 @@ static sv_def_t nq_fields[] = { {ev_vector, 96, "movedir", &sv_fields.movedir}, {ev_string, 99, "message", &sv_fields.message}, {ev_float, 100, "sounds", &sv_fields.sounds}, - {ev_string, 101, "noise", &sv_fields.noise}, - {ev_string, 102, "noise1", &sv_fields.noise1}, - {ev_string, 103, "noise2", &sv_fields.noise2}, - {ev_string, 104, "noise3", &sv_fields.noise3}, {ev_void, 0, 0}, }; @@ -328,19 +317,7 @@ static sv_def_t nq_opt_fields[] = { {ev_integer, 0, "rotated_bbox", &sv_fields.rotated_bbox}, {ev_float, 0, "alpha", &sv_fields.alpha}, {ev_float, 0, "gravity", &sv_fields.gravity}, - // Quake 2 fields? - {ev_float, 0, "dmg", &sv_fields.dmg}, - {ev_float, 0, "dmgtime", &sv_fields.dmgtime}, - {ev_float, 0, "air_finished", &sv_fields.air_finished}, - {ev_float, 0, "pain_finished", &sv_fields.pain_finished}, - {ev_float, 0, "radsuit_finished", &sv_fields.radsuit_finished}, - {ev_float, 0, "speed", &sv_fields.speed}, - {ev_float, 0, "basevelocity", &sv_fields.basevelocity}, - {ev_float, 0, "drawPercent", &sv_fields.drawPercent}, - {ev_float, 0, "mass", &sv_fields.mass}, - {ev_float, 0, "light_level", &sv_fields.light_level}, {ev_float, 0, "items2", &sv_fields.items2}, - {ev_float, 0, "pitch_speed", &sv_fields.pitch_speed}, {ev_float, 0, "lastruntime", &sv_fields.lastruntime}, {ev_void, 0, 0}, }; From 66fda1fddb5579bc3d46be9ea5e161d99659ea95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Jan 2013 14:11:54 +0900 Subject: [PATCH 1421/3664] Rewrite edict access. The server edict arrays are now stored outside of progs memory, only the entity data itself (ie data accessible to progs via ent.fld) is stored in progs memory. Many of the changes were due to code accessing edicts and entity fields directly rather than through the provided macros. --- include/QF/progs.h | 45 +++++++++++++++--------- libs/gamecode/pr_debug.c | 8 ++--- libs/gamecode/pr_edict.c | 20 +++++------ libs/gamecode/pr_exec.c | 62 +++++++++++++++++++++------------- libs/gamecode/pr_load.c | 34 ++++++++----------- libs/gamecode/pr_parse.c | 6 ++-- libs/ruamoko/pr_cmds.c | 6 ++-- nq/source/host_cmd.c | 4 +-- nq/source/sv_main.c | 2 +- nq/source/sv_progs.c | 38 ++++++++++++++------- qw/source/sv_progs.c | 58 +++++++++++++++++++------------ qw/source/sv_user.c | 2 +- tools/qfcc/source/qfprogs.c | 6 ++-- tools/qfcc/test/test-harness.c | 2 +- tools/qwaq/main.c | 2 +- tools/qwaq/qwaq.c | 2 +- 16 files changed, 173 insertions(+), 124 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 7c8bb3341..5f8661341 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -218,10 +218,11 @@ void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); struct edict_s { qboolean free; + progs_t *pr; ///< progs owning this edict int entnum; ///< number of this entity + int edict; ///< offset of this entity in pr_edict_area float freetime; ///< sv.time when the object was freed void *edata; ///< external per-edict data - pr_type_t v[1]; ///< fields from progs }; // pr_edict.c @@ -252,18 +253,18 @@ struct plitem_s *ED_Parse (progs_t *pr, const char *data); void ED_LoadFromFile (progs_t *pr, const char *data); void ED_EntityParseFunction (progs_t *pr); -#define PR_edicts(p) ((byte *) *(p)->edicts) +#define PR_edicts(p) (*(p)->pr_edicts) -#define NEXT_EDICT(p,e) ((edict_t *) ((byte *) e + (p)->pr_edict_size)) -#define EDICT_TO_PROG(p,e) ((pr_int_t)(intptr_t)((byte *)(e) - PR_edicts (p))) -#define PROG_TO_EDICT(p,e) ((edict_t *) (PR_edicts (p) + (e))) +#define NEXT_EDICT(p,e) ((e) + 1) +#define EDICT_TO_PROG(p,e) ((e)->entnum * (p)->pr_edict_size) +#define PROG_TO_EDICT(p,e) (&PR_edicts(p)[(e) / (p)->pr_edict_size]) #define NUM_FOR_BAD_EDICT(p,e) ((e)->entnum) #ifndef PR_PARANOID_PROGS -# define EDICT_NUM(p,n) (PROG_TO_EDICT (p, (n) * (p)->pr_edict_size)) -# define NUM_FOR_EDICT(p,e) NUM_FOR_BAD_EDICT (p, e) +# define EDICT_NUM(p,n) (PR_edicts (p) + (n)) +# define NUM_FOR_EDICT(p,e) NUM_FOR_BAD_EDICT ((p), (e)) #else -# define EDICT_NUM(p,n) ED_EdictNum (p, n) -# define NUM_FOR_EDICT(p,e) ED_NumForEdict (p, e) +# define EDICT_NUM(p,n) ED_EdictNum ((p), (n)) +# define NUM_FOR_EDICT(p,e) ED_NumForEdict ((p), (e)) #endif //@} @@ -420,7 +421,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_EDICT(p,o) ((edict_t *)(PR_edicts (p) + G_INT (p, o))) +#define G_EDICT(p,o) PROG_TO_EDICT ((p), G_INT (p, o)) /** Access an entity global. @@ -610,7 +611,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_EDICT(p,n) ((edict_t *)(PR_edicts (p) + P_INT (p, n))) +#define P_EDICT(p,n) PROG_TO_EDICT ((p), P_INT (p, n)) /** Access an entity parameter. @@ -807,7 +808,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define RETURN_EDICT(p,e) (R_STRING (p) = EDICT_TO_PROG(p, e)) +#define RETURN_EDICT(p,e) (R_INT (p) = EDICT_TO_PROG(p, e)) /** Set the return value to the given C pointer. NULL is converted to 0. @@ -858,7 +859,18 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_var(e,o,t) ((e)->v[o].t##_var) +#define E_fld(e,o) ((e)->pr->pr_edict_area[(e)->edict + (o)]) + + +/** \internal + \param e pointer to the entity + \param o field offset into entity data space + \param t typename prefix (see pr_type_u) + \return lvalue of the appropriate type + + \hideinitializer +*/ +#define E_var(e,o,t) (E_fld (e,o).t##_var) /** Access a float entity field. Can be assigned to. @@ -1592,7 +1604,7 @@ struct progs_s { /// \name edicts //@{ - edict_t **edicts; + edict_t **pr_edicts; int max_edicts; int *num_edicts; int *reserved_edicts; ///< alloc will start at reserved_edicts+1 @@ -1600,8 +1612,9 @@ struct progs_s { void (*flush) (void); int (*prune_edict) (progs_t *pr, edict_t *ent); void (*free_edict) (progs_t *pr, edict_t *ent); - int pr_edict_size; ///< in bytes - int pr_edictareasize; ///< for bounds checking, starts at 0 + pr_type_t *pr_edict_area; + int pr_edict_size; ///< # of pr_type_t slots + int pr_edict_area_size; ///< for bounds checking, starts at 0 func_t edict_parse; //@} diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 602a2cc15..3656c2d0f 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -160,7 +160,7 @@ parse_expression (progs_t *pr, const char *expr, int conditional) if (!field) goto error; d = *field; - expr_ptr = &ent->v[field->ofs]; + expr_ptr = &E_fld (ent, field->ofs); d.ofs = PR_SetPointer (pr, expr_ptr); } else if (isdigit ((byte) es->token->str[0])) { expr_ptr = PR_GetPointer (pr, strtol (es->token->str, 0, 0)); @@ -924,9 +924,9 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) parm_ind = pr->pr_globals[s->b].uinteger_var; if (parm_ind < pr->progs->entityfields && opval >= 0 - && opval < pr->pr_edictareasize) { + && opval < pr->pr_edict_area_size) { ed = PROG_TO_EDICT (pr, opval); - opval = &ed->v[parm_ind] - pr->pr_globals; + opval = &E_fld(ed, parm_ind) - pr->pr_globals; } if (!ed) { str = "bad entity.field"; @@ -1064,7 +1064,7 @@ ED_Print (progs_t *pr, edict_t *ed) && strchr ("xyz", name[strlen (name) -1])) continue; // skip _x, _y, _z vars - v = ed->v + d->ofs; + v = &E_fld(ed, d->ofs); // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 2241e3e9f..1e77dee66 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -66,13 +66,11 @@ ED_ClearEdict (progs_t *pr, edict_t *e, int val) if (NUM_FOR_EDICT (pr, e) < *pr->reserved_edicts) Sys_Printf ("clearing reserved edict %d\n", NUM_FOR_EDICT (pr, e)); for (i=0; i < pr->progs->entityfields; i++) - e->v[i].integer_var = val; + E_INT (e, i) = val; e->free = false; } /* - ED_Alloc - Either finds a free edict, or allocates a new one. Try to avoid reusing an entity that was recently freed, because it can cause the client to think the entity morphed into something else @@ -203,9 +201,9 @@ ED_Count (progs_t *pr) continue; } active++; - if (solid_def && ent->v[solid_def->ofs].float_var) + if (solid_def && E_FLOAT (ent, solid_def->ofs)) solid++; - if (model_def && ent->v[model_def->ofs].float_var) + if (model_def && E_FLOAT (ent, model_def->ofs)) models++; } @@ -219,12 +217,10 @@ ED_Count (progs_t *pr) edict_t * ED_EdictNum (progs_t *pr, pr_int_t n) { - pr_int_t offs = n * pr->pr_edict_size; - - if (offs < 0 || n >= pr->pr_edictareasize) + if (n < 0 || n >= *pr->num_edicts) PR_RunError (pr, "EDICT_NUM: bad number %d", n); - return PROG_TO_EDICT (pr, offs); + return PR_edicts(pr) + n; } pr_int_t @@ -234,9 +230,9 @@ ED_NumForEdict (progs_t *pr, edict_t *e) b = NUM_FOR_BAD_EDICT (pr, e); - if (b && (b < 0 || b >= *(pr)->num_edicts)) + if (b && (b < 0 || b >= *pr->num_edicts)) PR_RunError (pr, "NUM_FOR_EDICT: bad pointer %d %p %p", b, e, - *(pr)->edicts); + pr->pr_edicts); return b; } @@ -244,7 +240,7 @@ ED_NumForEdict (progs_t *pr, edict_t *e) qboolean PR_EdictValid (progs_t *pr, pr_int_t e) { - if (e < 0 || e >= pr->pr_edictareasize) + if (e < 0 || e >= pr->pr_edict_area_size) return false; if (e % pr->pr_edict_size) return false; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 24778dd74..1e995170b 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -355,9 +355,9 @@ VISIBLE void PR_ExecuteProgram (progs_t * pr, func_t fnum) { int exitdepth, profile, startprofile; + int fldofs; pr_uint_t pointer; dstatement_t *st; - edict_t *ed; pr_type_t *ptr; pr_type_t old_val = {0}, *watch = 0; @@ -642,7 +642,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) case OP_ADDRESS: if (pr_boundscheck->int_val) { if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edictareasize) + || OPA.entity_var >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to address an out " "of bounds edict"); if (OPA.entity_var == 0 && pr->null_bad) @@ -651,8 +651,8 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) PR_RunError (pr, "Progs attempted to address an " "invalid field in an edict"); } - ed = PROG_TO_EDICT (pr, OPA.entity_var); - OPC.integer_var = &ed->v[OPB.integer_var] - pr->pr_globals; + fldofs = OPA.entity_var + OPB.integer_var; + OPC.integer_var = &pr->pr_edict_area[fldofs] - pr->pr_globals; break; case OP_ADDRESS_VOID: case OP_ADDRESS_F: @@ -676,41 +676,41 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) case OP_LOAD_P: if (pr_boundscheck->int_val) { if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edictareasize) + || OPA.entity_var >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); if (OPB.uinteger_var >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - ed = PROG_TO_EDICT (pr, OPA.entity_var); - OPC.integer_var = ed->v[OPB.integer_var].integer_var; + fldofs = OPA.entity_var + OPB.integer_var; + OPC.integer_var = pr->pr_edict_area[fldofs].integer_var; break; case OP_LOAD_V: if (pr_boundscheck->int_val) { if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edictareasize) + || OPA.entity_var >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); if (OPB.uinteger_var + 2 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - ed = PROG_TO_EDICT (pr, OPA.entity_var); - memcpy (&OPC, &ed->v[OPB.integer_var], 3 * sizeof (OPC)); + fldofs = OPA.entity_var + OPB.integer_var; + memcpy (&OPC, &pr->pr_edict_area[fldofs], 3 * sizeof (OPC)); break; case OP_LOAD_Q: if (pr_boundscheck->int_val) { if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edictareasize) + || OPA.entity_var >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); if (OPB.uinteger_var + 3 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - ed = PROG_TO_EDICT (pr, OPA.entity_var); - memcpy (&OPC, &ed->v[OPB.integer_var], 3 * sizeof (OPC)); + fldofs = OPA.entity_var + OPB.integer_var; + memcpy (&OPC, &pr->pr_edict_area[fldofs], 4 * sizeof (OPC)); break; case OP_LOADB_F: @@ -965,18 +965,34 @@ op_call: } break; case OP_STATE: - ed = PROG_TO_EDICT (pr, *pr->globals.self); - ed->v[pr->fields.nextthink].float_var = *pr->globals.time + - 0.1; - ed->v[pr->fields.frame].float_var = OPA.float_var; - ed->v[pr->fields.think].func_var = OPB.func_var; + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink; + int frame = pr->fields.frame; + int think = pr->fields.think; + fldofs = self + nextthink; + pr->pr_edict_area[fldofs].float_var = *pr->globals.time + + 0.1; + fldofs = self + frame; + pr->pr_edict_area[fldofs].float_var = OPA.float_var; + fldofs = self + think; + pr->pr_edict_area[fldofs].func_var = OPB.func_var; + } break; case OP_STATE_F: - ed = PROG_TO_EDICT (pr, *pr->globals.self); - ed->v[pr->fields.nextthink].float_var = *pr->globals.time + - OPC.float_var; - ed->v[pr->fields.frame].float_var = OPA.float_var; - ed->v[pr->fields.think].func_var = OPB.func_var; + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink; + int frame = pr->fields.frame; + int think = pr->fields.think; + fldofs = self + nextthink; + pr->pr_edict_area[fldofs].float_var = *pr->globals.time + + OPC.float_var; + fldofs = self + frame; + pr->pr_edict_area[fldofs].float_var = OPA.float_var; + fldofs = self + think; + pr->pr_edict_area[fldofs].func_var = OPB.func_var; + } break; case OP_ADD_I: OPC.integer_var = OPA.integer_var + OPB.integer_var; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index b32cf71c3..76a84e2a2 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -166,6 +166,16 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) pr->progs_size += sizeof (void*) - 1; pr->progs_size &= ~(sizeof (void*) - 1); + // size of edict asked for by progs, but at least 1 + pr->pr_edict_size = max (1, progs.entityfields); + // round off to next highest multiple of 4 words + // this ensures that progs that try to align vectors and quaternions + // get what they want + pr->pr_edict_size += (4 - 1); + pr->pr_edict_size &= ~(4 - 1); + pr->pr_edict_area_size = max_edicts * pr->pr_edict_size; + pr->max_edicts = max_edicts; + // size of heap asked for by vm-subsystem pr->zone_size = zone; // round off to next highest whole word address (esp for Alpha) @@ -174,19 +184,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) pr->zone_size += sizeof (void*) - 1; pr->zone_size &= ~(sizeof (void*) - 1); - // size of edict asked for by progs - pr->pr_edict_size = max (1, progs.entityfields) * 4; - // size of engine data - pr->pr_edict_size += sizeof (edict_t) - sizeof (pr_type_t); - // round off to next highest whole word address (esp for Alpha) - // this ensures that pointers in the engine data area are always - // properly aligned - pr->pr_edict_size += sizeof (void*) - 1; - pr->pr_edict_size &= ~(sizeof (void*) - 1); - pr->pr_edictareasize = max_edicts * pr->pr_edict_size; - pr->max_edicts = max_edicts; - - mem_size = pr->progs_size + pr->zone_size + pr->pr_edictareasize; + mem_size = pr->pr_edict_area_size * sizeof (pr_type_t); + mem_size += pr->progs_size + pr->zone_size; pr->progs = pr->allocate_progs_mem (pr, mem_size + 1); if (!pr->progs) return; @@ -198,13 +197,10 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size, int max_edicts, int zone) CRC_ProcessBlock (base, &pr->crc, size - sizeof (progs)); base -= sizeof (progs); // offsets are from file start - if (pr->edicts) - *pr->edicts = (edict_t *)((byte *) pr->progs + pr->progs_size); - pr->zone = (memzone_t *)((byte *) pr->progs + pr->progs_size - + pr->pr_edictareasize); + pr->pr_edict_area = (pr_type_t *)((byte *) pr->progs + pr->progs_size); + pr->zone = (memzone_t *)(&pr->pr_edict_area[pr->pr_edict_area_size]); - pr->pr_functions = - (dfunction_t *) (base + pr->progs->ofs_functions); + pr->pr_functions = (dfunction_t *) (base + pr->progs->ofs_functions); pr->pr_strings = (char *) base + pr->progs->ofs_strings; pr->pr_stringsize = (char *) pr->zone + pr->zone_size - (char *) base; pr->pr_globaldefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 758e2c4cc..e6900fce9 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -139,7 +139,7 @@ ED_EntityDict (progs_t *pr, edict_t *ed) if (name[strlen (name) - 2] == '_') continue; // skip _x, _y, _z vars - v = &ed->v[d->ofs]; + v = &E_fld (ed, d->ofs); // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; @@ -418,7 +418,7 @@ ED_InitEntity (progs_t *pr, plitem_t *entity, edict_t *ent) continue; } } else { - if (!ED_ParseEpair (pr, ent->v, field, value)) + if (!ED_ParseEpair (pr, &E_fld (ent, 0), field, value)) PR_Error (pr, "ED_InitEntity: parse error"); } init = 1; @@ -439,7 +439,7 @@ ED_SpawnEntities (progs_t *pr, plitem_t *entity_list) int count; const char *classname; dfunction_t *func; - pr_int_t max_edicts = pr->pr_edictareasize / pr->pr_edict_size; + pr_int_t max_edicts = pr->pr_edict_area_size / pr->pr_edict_size; max_edicts -= *pr->num_edicts; count = PL_A_NumObjects (entity_list); diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 8352228d4..1ce9560d1 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -306,7 +306,7 @@ PF_Find (progs_t *pr) } } - RETURN_EDICT (pr, *pr->edicts); + RETURN_EDICT (pr, EDICT_NUM (pr, 0)); } /* @@ -401,7 +401,7 @@ PF_nextent (progs_t *pr) while (1) { i++; if (i == *pr->num_edicts) { - RETURN_EDICT (pr, *pr->edicts); + RETURN_EDICT (pr, EDICT_NUM (pr, 0)); return; } ent = EDICT_NUM (pr, i); @@ -601,7 +601,7 @@ PF_PR_SetField (progs_t *pr) R_INT (pr) = 0; if (field) - R_INT (pr) = ED_ParseEpair (pr, ent->v, field, value); + R_INT (pr) = ED_ParseEpair (pr, &E_fld (ent, 0), field, value); } static void diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 4a819d66c..76e13fe0e 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -700,7 +700,7 @@ Host_Loadgame_f (void) plitem_t *entity = PL_ObjectAtIndex (list, entnum); edict_t *ent = EDICT_NUM (&sv_pr_state, entnum); - memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); + memset (&E_fld (ent, 0), 0, sv_pr_state.progs->entityfields * 4); ent->free = false; ED_InitEntity (&sv_pr_state, entity, ent); @@ -989,7 +989,7 @@ Host_Spawn_f (void) } else { // set up the edict ent = host_client->edict; - memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); + memset (&E_fld (ent, 0), 0, sv_pr_state.progs->entityfields * 4); SVfloat (ent, colormap) = NUM_FOR_EDICT (&sv_pr_state, ent); SVfloat (ent, team) = (host_client->colors & 15) + 1; SVstring (ent, netname) = PR_SetString (&sv_pr_state, diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index d06ec4543..acaccd765 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1193,7 +1193,7 @@ SV_SpawnServer (const char *server) // load the rest of the entities ent = EDICT_NUM (&sv_pr_state, 0); - memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); + memset (&E_fld (ent, 0), 0, sv_pr_state.progs->entityfields * 4); ent->free = false; SVstring (ent, model) = PR_SetString (&sv_pr_state, sv.worldmodel->name); SVfloat (ent, modelindex) = 1; // world model diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index ca80ae190..6e0b5f7d1 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -51,6 +51,7 @@ sv_globals_t sv_globals; sv_funcs_t sv_funcs; sv_fields_t sv_fields; +edict_t sv_edicts[MAX_EDICTS]; sv_data_t sv_data[MAX_EDICTS]; cvar_t *sv_progs; @@ -448,12 +449,32 @@ resolve (progs_t *pr) return ret; } +static int +sv_init_edicts (progs_t *pr) +{ + int i; + + memset (sv_edicts, 0, sizeof (sv_edicts)); + memset (sv_data, 0, sizeof (sv_data)); + + // init the data field of the edicts + for (i = 0; i < sv.max_edicts; i++) { + edict_t *ent = EDICT_NUM (&sv_pr_state, i); + ent->pr = &sv_pr_state; + ent->entnum = i; + ent->edict = EDICT_TO_PROG (&sv_pr_state, ent); + ent->edata = &sv_data[i]; + SVdata (ent)->edict = ent; + } + + return 1; +} + void SV_LoadProgs (void) { const char *progs_name = "progs.dat"; const char *range; - int i; if (strequal (sv_progs_ext->string, "qf")) { sv_range = PR_RANGE_QF; @@ -475,27 +496,18 @@ SV_LoadProgs (void) if (*sv_progs->string) progs_name = sv_progs->string; + sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name, sv.max_edicts, sv_progs_zone->int_val * 1024); if (!sv_pr_state.progs) Host_Error ("SV_LoadProgs: couldn't load %s", progs_name); - - memset (sv_data, 0, sizeof (sv_data)); - - // init the data field of the edicts - for (i = 0; i < sv.max_edicts; i++) { - edict_t *ent = EDICT_NUM (&sv_pr_state, i); - ent->entnum = i; - ent->edata = &sv_data[i]; - SVdata (ent)->edict = ent; - } } void SV_Progs_Init (void) { pr_gametype = "netquake"; - sv_pr_state.edicts = &sv.edicts; + sv_pr_state.pr_edicts = &sv.edicts; sv_pr_state.num_edicts = &sv.num_edicts; sv_pr_state.reserved_edicts = &svs.maxclients; sv_pr_state.unlink = SV_UnlinkEdict; @@ -504,6 +516,8 @@ SV_Progs_Init (void) sv_pr_state.bi_map = bi_map; sv_pr_state.resolve = resolve; + PR_AddLoadFunc (&sv_pr_state, sv_init_edicts); + SV_PR_Cmds_Init (); Cmd_AddCommand ("edict", ED_PrintEdict_f, "Report information on a given " diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index e11805c17..048961186 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -53,6 +53,7 @@ sv_globals_t sv_globals; sv_funcs_t sv_funcs; sv_fields_t sv_fields; +edict_t sv_edicts[MAX_EDICTS]; sv_data_t sv_data[MAX_EDICTS]; cvar_t *r_skyname; @@ -92,16 +93,16 @@ static void free_edict (progs_t *pr, edict_t *ent) { if (sv_old_entity_free->int_val) { - ent->v[sv_fields.model].entity_var = 0; - ent->v[sv_fields.takedamage].float_var = 0; - ent->v[sv_fields.modelindex].float_var = 0; - ent->v[sv_fields.colormap].float_var = 0; - ent->v[sv_fields.skin].float_var = 0; - ent->v[sv_fields.frame].float_var = 0; - ent->v[sv_fields.nextthink].float_var = -1; - ent->v[sv_fields.solid].float_var = 0; - memset (ent->v[sv_fields.origin].vector_var, 0, 3*sizeof (float)); - memset (ent->v[sv_fields.angles].vector_var, 0, 3*sizeof (float)); + E_fld (ent, sv_fields.model).entity_var = 0; + E_fld (ent, sv_fields.takedamage).float_var = 0; + E_fld (ent, sv_fields.modelindex).float_var = 0; + E_fld (ent, sv_fields.colormap).float_var = 0; + E_fld (ent, sv_fields.skin).float_var = 0; + E_fld (ent, sv_fields.frame).float_var = 0; + E_fld (ent, sv_fields.nextthink).float_var = -1; + E_fld (ent, sv_fields.solid).float_var = 0; + memset (E_fld (ent, sv_fields.origin).vector_var, 0, 3*sizeof (float)); + memset (E_fld (ent, sv_fields.angles).vector_var, 0, 3*sizeof (float)); } else { ED_ClearEdict (pr, ent, 0); } @@ -481,12 +482,32 @@ resolve (progs_t *pr) return ret; } +static int +sv_init_edicts (progs_t *pr) +{ + int i; + + memset (sv_edicts, 0, sizeof (sv_edicts)); + memset (sv_data, 0, sizeof (sv_data)); + + // init the data field of the edicts + for (i = 0; i < MAX_EDICTS; i++) { + edict_t *ent = EDICT_NUM (&sv_pr_state, i); + ent->pr = &sv_pr_state; + ent->entnum = i; + ent->edict = EDICT_TO_PROG (&sv_pr_state, ent); + ent->edata = &sv_data[i]; + SVdata (ent)->edict = ent; + } + + return 1; +} + void SV_LoadProgs (void) { const char *progs_name = "qwprogs.dat"; const char *range; - int i; if (strequal (sv_progs_ext->string, "qf")) { sv_range = PR_RANGE_QF; @@ -521,27 +542,18 @@ SV_LoadProgs (void) if (*sv_progs->string) progs_name = sv_progs->string; + sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name, MAX_EDICTS, sv_progs_zone->int_val * 1024); if (!sv_pr_state.progs) Sys_Error ("SV_LoadProgs: couldn't load %s", progs_name); - - memset (sv_data, 0, sizeof (sv_data)); - - // init the data field of the edicts - for (i = 0; i < MAX_EDICTS; i++) { - edict_t *ent = EDICT_NUM (&sv_pr_state, i); - ent->entnum = i; - ent->edata = &sv_data[i]; - SVdata (ent)->edict = ent; - } } void SV_Progs_Init (void) { pr_gametype = "quakeworld"; - sv_pr_state.edicts = &sv.edicts; + sv_pr_state.pr_edicts = &sv.edicts; sv_pr_state.num_edicts = &sv.num_edicts; sv_pr_state.reserved_edicts = &reserved_edicts; sv_pr_state.unlink = SV_UnlinkEdict; @@ -552,6 +564,8 @@ SV_Progs_Init (void) sv_pr_state.bi_map = bi_map; sv_pr_state.resolve = resolve; + PR_AddLoadFunc (&sv_pr_state, sv_init_edicts); + SV_PR_Cmds_Init (); SV_PR_QWE_Init (&sv_pr_state); SV_PR_CPQW_Init (&sv_pr_state); diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 608b44480..4505b3921 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -376,7 +376,7 @@ SV_Spawn (client_t *client) // set up the edict ent = client->edict; - memset (&ent->v, 0, sv_pr_state.progs->entityfields * 4); + memset (&E_fld (ent, 0), 0, sv_pr_state.progs->entityfields * 4); SVfloat (ent, colormap) = NUM_FOR_EDICT (&sv_pr_state, ent); SVfloat (ent, team) = 0; // FIXME SVstring (ent, netname) = PR_SetString (&sv_pr_state, client->name); diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index d6bf84927..7063d1805 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -238,7 +238,7 @@ init_qf (void) PR_Init_Cvars (); PR_Init (); - pr.edicts = &edicts; + pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; pr.file_error = file_error; @@ -267,8 +267,8 @@ convert_qfo (void) pr.pr_fielddefs = P (ddef_t, ofs_fielddefs); pr.pr_globals = P (pr_type_t, ofs_globals); pr.globals_size = pr.progs->numglobals; - pr.pr_edict_size = max (1, pr.progs->entityfields) * 4; - pr.pr_edictareasize = 1 * pr.pr_edict_size; + pr.pr_edict_size = max (1, pr.progs->entityfields); + pr.pr_edict_area_size = 1 * pr.pr_edict_size; #undef P if (verbosity) { diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index eff3ff9a4..061b03d4c 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -138,7 +138,7 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "2", 0, 0, 0); - pr.edicts = &edicts; + pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; pr.load_file = load_file; diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index edb7c0229..78788dded 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -107,7 +107,7 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); - pr.edicts = &edicts; + pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; pr.load_file = load_file; diff --git a/tools/qwaq/qwaq.c b/tools/qwaq/qwaq.c index f1197ccfb..a69c393ae 100644 --- a/tools/qwaq/qwaq.c +++ b/tools/qwaq/qwaq.c @@ -118,7 +118,7 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); - pr.edicts = &edicts; + pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; pr.load_file = load_file; From 91e3769c05fbd2411b6949fb3385470482c091ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Jan 2013 21:09:11 +0900 Subject: [PATCH 1422/3664] Recalculate the fov when the cvar changes. This separate the FOV calculations from other refdef calcs, cleaning up the renderer proper and making it easier for other parts of the engine (eg, csqc) to update the fov. --- include/QF/plugin/vid_render.h | 2 +- include/r_screen.h | 3 +-- libs/video/renderer/gl/gl_screen.c | 5 ----- libs/video/renderer/glsl/glsl_screen.c | 4 ---- libs/video/renderer/r_cvar.c | 12 +++++++++--- libs/video/renderer/r_screen.c | 15 ++++++++++----- libs/video/renderer/sw/screen.c | 5 ----- libs/video/renderer/sw32/screen.c | 5 ----- libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_sw32.c | 1 + 12 files changed, 25 insertions(+), 30 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index bdec285d1..4d2a133aa 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -130,7 +130,7 @@ typedef struct vid_render_funcs_s { void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); - + void (*SCR_SetFOV) (float fov); // scr_funcs is a null terminated array void (*SCR_UpdateScreen) (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs); diff --git a/include/r_screen.h b/include/r_screen.h index 8d3b08e91..737097fdb 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -52,7 +52,6 @@ extern float scr_con_current; extern float scr_conlines; // lines of console to display extern int oldscreensize; -extern float oldfov; extern int oldsbar; extern qboolean scr_initialized; // ready to draw @@ -71,7 +70,7 @@ extern vrect_t scr_vrect; extern qboolean scr_skipupdate; -float CalcFov (float fov_x, float width, float height); +void SCR_SetFOV (float fov); void SCR_SetUpToDrawConsole (void); void SCR_ScreenShot_f (void); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index d463880d8..0e0d2f654 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -226,11 +226,6 @@ gl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) gl_c_alias_polys = 0; } - if (oldfov != scr_fov->value) { // determine size of refresh window - oldfov = scr_fov->value; - vid.recalc_refdef = true; - } - if (vid.recalc_refdef) SCR_CalcRefdef (); diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index 56e481c41..7ee1c0bb7 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -179,10 +179,6 @@ glsl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, begun = 1; - if (oldfov != scr_fov->value) { - oldfov = scr_fov->value; - vid.recalc_refdef = true; - } if (vid.recalc_refdef) SCR_CalcRefdef (); diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index d9f3e14d2..0f6406f61 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -152,6 +152,12 @@ r_nearclip_f (cvar_t *var) vid.recalc_refdef = true; } +static void +scr_fov_f (cvar_t *var) +{ + SCR_SetFOV (var->value); +} + static void scr_fisheye_f (cvar_t *var) { @@ -291,9 +297,9 @@ R_Init_Cvars (void) r_zgraph = Cvar_Get ("r_zgraph", "0", CVAR_NONE, NULL, "Toggle the graph that reports the changes of " "z-axis position"); - scr_fov = Cvar_Get ("fov", "90", CVAR_NONE, NULL, "Your field of view in " - "degrees. Smaller than 90 zooms in. Don't touch in " - "fisheye mode, use ffov instead."); + scr_fov = Cvar_Get ("fov", "90", CVAR_NONE, scr_fov_f, + "Your field of view in degrees. Smaller than 90 zooms " + "in. Don't touch in fisheye mode, use ffov instead."); scr_fisheye = Cvar_Get ("fisheye", "0", CVAR_NONE, scr_fisheye_f, "Toggles fisheye mode."); scr_fviews = Cvar_Get ("fviews", "6", CVAR_NONE, NULL, "The number of " diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index a6d129674..86e6a38a8 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -94,7 +94,6 @@ int scr_copytop; byte *draw_chars; // 8*8 graphic characters FIXME location -float oldfov; int oldsbar; qboolean scr_initialized; // ready to draw @@ -164,15 +163,12 @@ SCR_CalcRefdef (void) R_SetVrect (&vrect, &scr_vrect, vr_data.lineadj); refdef->vrect = scr_vrect; - refdef->fov_x = scr_fov->value; - refdef->fov_y = - CalcFov (refdef->fov_x, refdef->vrect.width, refdef->vrect.height); // notify the refresh of the change vr_funcs->R_ViewChanged (vid.aspect); } -float +static float CalcFov (float fov_x, float width, float height) { float a, x; @@ -189,6 +185,15 @@ CalcFov (float fov_x, float width, float height) return a; } +void +SCR_SetFOV (float fov) +{ + refdef_t *refdef = r_data->refdef; + refdef->fov_x = fov; + refdef->fov_y = CalcFov (fov, refdef->vrect.width, refdef->vrect.height); + vid.recalc_refdef = 1; +} + static void ScreenShot_f (void) { diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index d425f6549..66a8224b1 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -202,11 +202,6 @@ SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) if (!scr_initialized) return; // not initialized yet - if (oldfov != scr_fov->value) { // determine size of refresh window - oldfov = scr_fov->value; - vid.recalc_refdef = true; - } - if (vid.recalc_refdef) SCR_CalcRefdef (); diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index 63f0ce6e1..f1bd73c85 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -160,11 +160,6 @@ sw32_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs if (!scr_initialized) return; // not initialized yet - if (oldfov != scr_fov->value) { // determine size of refresh window - oldfov = scr_fov->value; - vid.recalc_refdef = true; - } - if (vid.recalc_refdef) SCR_CalcRefdef (); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index c79bfaa20..ac6be77f7 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -90,6 +90,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_Picf, gl_Draw_SubPic, + SCR_SetFOV, gl_SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index f09820ab3..b88c7af11 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -90,6 +90,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_Picf, glsl_Draw_SubPic, + SCR_SetFOV, glsl_SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 7ac10a4d4..d9dcfb90d 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -83,6 +83,7 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_Picf, Draw_SubPic, + SCR_SetFOV, SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 9bc135c78..cb0ac344d 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -88,6 +88,7 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_Draw_Picf, sw32_Draw_SubPic, + SCR_SetFOV, sw32_SCR_UpdateScreen, SCR_DrawRam, SCR_DrawTurtle, From 67c220de76117a5a314c8d9fbc36680c5ef0e1d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Jan 2013 21:20:25 +0900 Subject: [PATCH 1423/3664] Make R_SetVrect const-correct. --- include/r_internal.h | 2 +- libs/video/renderer/r_screen.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/r_internal.h b/include/r_internal.h index 3d5e69206..dc3a3e842 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -68,7 +68,7 @@ int D_SurfaceCacheForRes (int width, int height); void D_FlushCaches (void); void D_DeleteSurfaceCache (void); void D_InitCaches (void *buffer, int size); -void R_SetVrect (vrect_t *pvrect, vrect_t *pvrectin, int lineadj); +void R_SetVrect (const vrect_t *pvrect, vrect_t *pvrectin, int lineadj); void R_LoadSkys (const char *); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 86e6a38a8..a9a45efbe 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -111,7 +111,7 @@ vrect_t scr_vrect; qboolean scr_skipupdate; void -R_SetVrect (vrect_t *vrectin, vrect_t *vrect, int lineadj) +R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) { float size; int h; From 167dd2af9bf5c9df5861d05499a467bafbabb752 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Jan 2013 15:58:24 +0900 Subject: [PATCH 1424/3664] Fix the RESMAP macros to allow expressions. Most importantly, *map. Needed only to put () around map in the macros. The rest is just keeping the backslashes tidy. --- include/QF/progs.h | 100 ++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 5f8661341..b45835e77 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1348,27 +1348,27 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \return A pointer to the new resource, or null if no more could be allocated. */ -#define PR_RESNEW(type,map) \ - type *t; \ - \ - if (!map._free) { \ - int i, size; \ - map._size++; \ - size = map._size * sizeof (type *); \ - map._map = realloc (map._map, size); \ - if (!map._map) \ - return 0; \ - map._free = calloc (1024, sizeof (type)); \ - if (!map._free) \ - return 0; \ - map._map[map._size - 1] = map._free; \ - for (i = 0; i < 1023; i++) \ - *(type **) &map._free[i] = &map._free[i + 1]; \ - *(type **) &map._free[i] = 0; \ - } \ - t = map._free; \ - map._free = *(type **) t; \ - memset (t, 0, sizeof (type)); \ +#define PR_RESNEW(type,map) \ + type *t; \ + \ + if (!(map)._free) { \ + int i, size; \ + (map)._size++; \ + size = (map)._size * sizeof (type *); \ + (map)._map = realloc ((map)._map, size); \ + if (!(map)._map) \ + return 0; \ + (map)._free = calloc (1024, sizeof (type)); \ + if (!(map)._free) \ + return 0; \ + (map)._map[(map)._size - 1] = (map)._free; \ + for (i = 0; i < 1023; i++) \ + *(type **) &(map)._free[i] = &(map)._free[i + 1]; \ + *(type **) &(map)._free[i] = 0; \ + } \ + t = (map)._free; \ + (map)._free = *(type **) t; \ + memset (t, 0, sizeof (type)); \ return t /** Free a resource returning it to the resource map. @@ -1378,10 +1378,10 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \param map The resource map. \param t Pointer to the resource to be freed. */ -#define PR_RESFREE(type,map,t) \ - memset (t, 0, sizeof (type)); \ - *(type **) t = map._free; \ - map._free = t +#define PR_RESFREE(type,map,t) \ + memset (t, 0, sizeof (type)); \ + *(type **) t = (map)._free; \ + (map)._free = t /** Free all resources in the resource map. @@ -1392,18 +1392,18 @@ void *PR_Resources_Find (progs_t *pr, const char *name); used for PR_RESMAP. \param map The resource map. */ -#define PR_RESRESET(type,map) \ - unsigned i, j; \ - if (!map._size) \ - return; \ - for (i = 0; i < map._size; i++) { \ - map._free = map._map[i]; \ - for (j = 0; j < 1023; j++) \ - *(type **) &map._free[j] = &map._free[j + 1]; \ - if (i < map._size - 1) \ - *(type **) &map._free[j] = &map._map[i + 1][0]; \ - } \ - map._free = map._map[0]; +#define PR_RESRESET(type,map) \ + unsigned i, j; \ + if (!(map)._size) \ + return; \ + for (i = 0; i < (map)._size; i++) { \ + (map)._free = (map)._map[i]; \ + for (j = 0; j < 1023; j++) \ + *(type **) &(map)._free[j] = &(map)._free[j + 1]; \ + if (i < (map)._size - 1) \ + *(type **) &(map)._free[j] = &(map)._map[i + 1][0]; \ + } \ + (map)._free = (map)._map[0]; /** Retrieve a resource from the resource map using a handle. @@ -1412,12 +1412,12 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \return A pointer to the resource, or NULL if the handle is invalid. */ -#define PR_RESGET(map,col) \ - unsigned row = ~col / 1024; \ - col = ~col % 1024; \ - if (row >= map._size) \ - return 0; \ - return &map._map[row][col] +#define PR_RESGET(map,col) \ + unsigned row = ~col / 1024; \ + col = ~col % 1024; \ + if (row >= (map)._size) \ + return 0; \ + return &(map)._map[row][col] /** Convert a resource pointer to a handle. @@ -1425,13 +1425,13 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \param ptr The resource pointer. \return The handle or 0 if the pointer is invalid. */ -#define PR_RESINDEX(map,ptr) \ - unsigned i; \ - for (i = 0; i < map._size; i++) { \ - long d = ptr - map._map[i]; \ - if (d >= 0 && d < 1024) \ - return ~(i * 1024 + d); \ - } \ +#define PR_RESINDEX(map,ptr) \ + unsigned i; \ + for (i = 0; i < (map)._size; i++) { \ + long d = ptr - (map)._map[i]; \ + if (d >= 0 && d < 1024) \ + return ~(i * 1024 + d); \ + } \ return 0 //@} From 52b714ea5755e327e68fc0151e7e95d84807ae7e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Jan 2013 17:18:29 +0900 Subject: [PATCH 1425/3664] Move qw's player_info_t to client/state.h And use it instead of scoreboard_t in nq. --- include/client/state.h | 58 ++++++++++++++++++++++++++++++++++++++++++ nq/include/client.h | 13 ++-------- nq/source/cl_main.c | 2 +- nq/source/cl_parse.c | 6 ++--- nq/source/sbar.c | 6 ++--- qw/include/client.h | 26 +------------------ 6 files changed, 68 insertions(+), 43 deletions(-) create mode 100644 include/client/state.h diff --git a/include/client/state.h b/include/client/state.h new file mode 100644 index 000000000..a06890822 --- /dev/null +++ b/include/client/state.h @@ -0,0 +1,58 @@ +/* + state.h + + client state + + Copyright (C) 2013 Bill Currie + + Author: Bill Currie + Date: 2013/01/31 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __client_state_h +#define __client_state_h + +typedef struct player_info_s { + int userid; + struct info_s *userinfo; + + // scoreboard information + struct info_key_s *name; + struct info_key_s *team; + struct info_key_s *chat; + float entertime; + int frags; + int ping; + byte pl; + + // skin information + int topcolor; + int bottomcolor; + struct info_key_s *skinname; + struct skin_s *skin; + + int spectator; + int stats[MAX_CL_STATS]; // health, etc + int prevcount; +} player_info_t; + +#endif//__client_state_h diff --git a/nq/include/client.h b/nq/include/client.h index e6dc80e97..4c99e6993 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -38,6 +38,7 @@ #include "QF/render.h" #include "client/entities.h" +#include "client/state.h" #include "game.h" #include "netmain.h" @@ -53,16 +54,6 @@ typedef struct usercmd_s { float upmove; } usercmd_t; -typedef struct { - struct info_s *info; - struct info_key_s *name; - float entertime; - int frags; - int topcolor; - int bottomcolor; -} scoreboard_t; - - // client_state_t should hold all pieces of the client state typedef enum { @@ -225,7 +216,7 @@ typedef struct { int cdtrack; // cd audio // frag scoreboard - scoreboard_t *scores; // [cl.maxclients] + player_info_t *scores; // [cl.maxclients] lightstyle_t lightstyle[MAX_LIGHTSTYLES]; } client_state_t; diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 052b45189..995f7f073 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -205,7 +205,7 @@ CL_ClearState (void) int i; for (i = 0; i < cl.maxclients; i++) - Info_Destroy (cl.scores[i].info); + Info_Destroy (cl.scores[i].userinfo); } // wipe the entire cl structure diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 2b9597e8a..0a1fe5a61 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -361,8 +361,8 @@ CL_ParseServerInfo (void) } cl.scores = Hunk_AllocName (cl.maxclients * sizeof (*cl.scores), "scores"); for (i = 0; i < cl.maxclients; i++) { - cl.scores[i].info = Info_ParseString ("name\\", 0, 0); - cl.scores[i].name = Info_Key (cl.scores[i].info, "name"); + cl.scores[i].userinfo = Info_ParseString ("name\\", 0, 0); + cl.scores[i].name = Info_Key (cl.scores[i].userinfo, "name"); cl.scores[i].topcolor = 0; cl.scores[i].bottomcolor = 0; } @@ -983,7 +983,7 @@ CL_ParseServerMessage (void) if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatename > " "MAX_SCOREBOARD"); - Info_SetValueForKey (cl.scores[i].info, "name", + Info_SetValueForKey (cl.scores[i].userinfo, "name", MSG_ReadString (net_message), 0); break; diff --git a/nq/source/sbar.c b/nq/source/sbar.c index e77ff103a..e2a12c17c 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -574,7 +574,7 @@ draw_frags (view_t *view) int i, k, l, p = -1; int top, bottom; int x; - scoreboard_t *s; + player_info_t *s; if (cl.maxclients == 1) return; @@ -800,7 +800,7 @@ static void draw_rogue_face (view_t *view) { int top, bottom; - scoreboard_t *s; + player_info_t *s; // PGM 01/19/97 - team color drawing @@ -1032,7 +1032,7 @@ Sbar_DeathmatchOverlay (view_t *view) int i, k, l; int top, bottom; int x, y; - scoreboard_t *s; + player_info_t *s; r_data->scr_copyeverything = 1; r_data->scr_fullupdate = 0; diff --git a/qw/include/client.h b/qw/include/client.h index 23d22e893..de55b73ed 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -36,6 +36,7 @@ #include "QF/plugin/vid_render.h" #include "client/entities.h" +#include "client/state.h" #include "netchan.h" #include "qw/bothdefs.h" @@ -62,31 +63,6 @@ typedef struct player_state_s { } player_state_t; -typedef struct player_info_s { - int userid; - struct info_s *userinfo; - - // scoreboard information - struct info_key_s *name; - struct info_key_s *team; - struct info_key_s *chat; - float entertime; - int frags; - int ping; - byte pl; - - // skin information - int topcolor; - int bottomcolor; - struct info_key_s *skinname; - struct skin_s *skin; - - int spectator; - int stats[MAX_CL_STATS]; // health, etc - int prevcount; -} player_info_t; - - typedef struct { // generated on client side usercmd_t cmd; // cmd that generated the frame From d514d4e465f0f5c614fe19886afe7bd7e3710d4f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Jan 2013 17:19:05 +0900 Subject: [PATCH 1426/3664] Bring client_state_t a little closer to matching. --- nq/include/client.h | 6 ++++++ qw/include/client.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/nq/include/client.h b/nq/include/client.h index 4c99e6993..e271dcbee 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -199,14 +199,20 @@ typedef struct { char levelname[40]; // for display on solo scoreboard int spectator; + int playernum; int viewentity; // cl_entitites[cl.viewentity] = player unsigned protocol; + float stdver; int gametype; int maxclients; + // serverinfo mirrors int chase; int sv_cshifts; + int no_pogo_stick; + int teamplay; int watervis; int fpd; + int fbskins; // refresh related state struct model_s *worldmodel; // cl_entitites[0].model diff --git a/qw/include/client.h b/qw/include/client.h index de55b73ed..cd9591629 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -245,7 +245,9 @@ typedef struct { int spectator; int playernum; int viewentity; + unsigned protocol; float stdver; + int gametype; int maxclients; // serverinfo mirrors int chase; From 13677bc5d332cfd12bb50ef917fa21175475d1d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Feb 2013 16:54:05 +0900 Subject: [PATCH 1427/3664] Rename nq's cl.scores to cl.players. --- nq/include/client.h | 4 ++-- nq/source/cl_ents.c | 4 ++-- nq/source/cl_main.c | 4 ++-- nq/source/cl_parse.c | 23 ++++++++++++----------- nq/source/sbar.c | 11 ++++++----- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index e271dcbee..fe6fb5851 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -221,8 +221,8 @@ typedef struct { int cdtrack; // cd audio -// frag scoreboard - player_info_t *scores; // [cl.maxclients] +// all player information + player_info_t *players; lightstyle_t lightstyle[MAX_LIGHTSTYLES]; } client_state_t; diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 87f25f1ed..7ba8f5946 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -356,8 +356,8 @@ CL_RelinkEntities (void) ent->skinnum = new->skinnum; if (i <= cl.maxclients) { ent->skin = mod_funcs->Skin_SetColormap (ent->skin, i); - mod_funcs->Skin_SetTranslation (i, cl.scores[i - 1].topcolor, - cl.scores[i - 1].bottomcolor); + mod_funcs->Skin_SetTranslation (i, cl.players[i - 1].topcolor, + cl.players[i - 1].bottomcolor); } } ent->scale = new->scale / 16.0; diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 995f7f073..054d60677 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -201,11 +201,11 @@ CL_ClearState (void) if (cl.edicts) PL_Free (cl.edicts); - if (cl.scores) { + if (cl.players) { int i; for (i = 0; i < cl.maxclients; i++) - Info_Destroy (cl.scores[i].userinfo); + Info_Destroy (cl.players[i].userinfo); } // wipe the entire cl structure diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 0a1fe5a61..0b8e5972b 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -359,12 +359,13 @@ CL_ParseServerInfo (void) Sys_Printf ("Bad maxclients (%u) from server\n", cl.maxclients); goto done; } - cl.scores = Hunk_AllocName (cl.maxclients * sizeof (*cl.scores), "scores"); + cl.players = Hunk_AllocName (cl.maxclients * sizeof (*cl.players), + "players"); for (i = 0; i < cl.maxclients; i++) { - cl.scores[i].userinfo = Info_ParseString ("name\\", 0, 0); - cl.scores[i].name = Info_Key (cl.scores[i].userinfo, "name"); - cl.scores[i].topcolor = 0; - cl.scores[i].bottomcolor = 0; + cl.players[i].userinfo = Info_ParseString ("name\\", 0, 0); + cl.players[i].name = Info_Key (cl.players[i].userinfo, "name"); + cl.players[i].topcolor = 0; + cl.players[i].bottomcolor = 0; } // parse gametype @@ -983,7 +984,7 @@ CL_ParseServerMessage (void) if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatename > " "MAX_SCOREBOARD"); - Info_SetValueForKey (cl.scores[i].userinfo, "name", + Info_SetValueForKey (cl.players[i].userinfo, "name", MSG_ReadString (net_message), 0); break; @@ -993,7 +994,7 @@ CL_ParseServerMessage (void) if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatefrags > " "MAX_SCOREBOARD"); - cl.scores[i].frags = (short) MSG_ReadShort (net_message); + cl.players[i].frags = (short) MSG_ReadShort (net_message); break; case svc_clientdata: @@ -1016,11 +1017,11 @@ CL_ParseServerMessage (void) byte col = MSG_ReadByte (net_message); byte top = col >> 4; byte bot = col & 0xf; - if (top != cl.scores[i].topcolor - || bot != cl.scores[i].bottomcolor) + if (top != cl.players[i].topcolor + || bot != cl.players[i].bottomcolor) mod_funcs->Skin_SetTranslation (i + 1, top, bot); - cl.scores[i].topcolor = top; - cl.scores[i].bottomcolor = bot; + cl.players[i].topcolor = top; + cl.players[i].bottomcolor = bot; ent->skin = mod_funcs->Skin_SetColormap (ent->skin, i + 1); } break; diff --git a/nq/source/sbar.c b/nq/source/sbar.c index e2a12c17c..de3a6d4ce 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -519,7 +519,7 @@ Sbar_SortFrags (void) // sort by frags scoreboardlines = 0; for (i = 0; i < cl.maxclients; i++) { - if (cl.scores[i].name->value[0]) { + if (cl.players[i].name->value[0]) { fragsort[scoreboardlines] = i; scoreboardlines++; } @@ -527,7 +527,8 @@ Sbar_SortFrags (void) for (i = 0; i < scoreboardlines; i++) { for (j = 0; j < (scoreboardlines - 1 - i); j++) { - if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j + 1]].frags) { + if (cl.players[fragsort[j]].frags + < cl.players[fragsort[j + 1]].frags) { k = fragsort[j]; fragsort[j] = fragsort[j + 1]; fragsort[j + 1] = k; @@ -588,7 +589,7 @@ draw_frags (view_t *view) for (i = 0; i < l; i++) { k = fragsort[i]; - s = &cl.scores[k]; + s = &cl.players[k]; if (!s->name->value[0]) continue; @@ -804,7 +805,7 @@ draw_rogue_face (view_t *view) // PGM 01/19/97 - team color drawing - s = &cl.scores[cl.viewentity - 1]; + s = &cl.players[cl.viewentity - 1]; top = Sbar_ColorForMap (s->topcolor); bottom = Sbar_ColorForMap (s->bottomcolor); @@ -1049,7 +1050,7 @@ Sbar_DeathmatchOverlay (view_t *view) y = 40; for (i = 0; i < l; i++) { k = fragsort[i]; - s = &cl.scores[k]; + s = &cl.players[k]; if (!s->name->value[0]) continue; From bc8e37332c427fee0c06934f2a9be370bdbaf627 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Feb 2013 17:32:46 +0900 Subject: [PATCH 1428/3664] Make qw's cl.players dynamically allocated. --- qw/include/client.h | 2 +- qw/source/cl_main.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/qw/include/client.h b/qw/include/client.h index cd9591629..c9481f209 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -266,7 +266,7 @@ typedef struct { int cdtrack; // cd audio // all player information - player_info_t players[MAX_CLIENTS]; + player_info_t *players; lightstyle_t lightstyle[MAX_LIGHTSTYLES]; } client_state_t; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index dd73f987a..f3e07da90 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -395,7 +395,10 @@ CL_ClearState (void) // wipe the entire cl structure if (cl.serverinfo) Info_Destroy (cl.serverinfo); + if (cl.players) + free (cl.players); memset (&cl, 0, sizeof (cl)); + cl.players = calloc (MAX_CLIENTS, sizeof (player_info_t)); r_data->force_fullscreen = 0; cl.maxclients = MAX_CLIENTS; @@ -1219,6 +1222,7 @@ CL_Init (void) cls.downloadname = dstring_newstr (); cls.downloadurl = dstring_newstr (); cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING, 0); + cl.players = calloc (MAX_CLIENTS, sizeof (player_info_t)); // register our commands Cmd_AddCommand ("version", CL_Version_f, "Report version information"); From 0a89e88ef39348de4df408237d2ea0259f238fbc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Feb 2013 17:33:21 +0900 Subject: [PATCH 1429/3664] Clean up some nasty formatting. --- qw/source/cl_chat.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index 305c14f55..b484eaa3e 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -80,7 +80,8 @@ CL_Ignore_Sanity_Check (void) static qboolean live_iterator (ignore_t *ig, llist_node_t *node) { - Sys_Printf ("%5i - %s\n", ig->uid, Info_ValueForKey (cl.players[ig->slot].userinfo, "name")); + Sys_Printf ("%5i - %s\n", ig->uid, + Info_ValueForKey (cl.players[ig->slot].userinfo, "name")); return true; } @@ -115,7 +116,8 @@ CL_Ignore_f (void) new->slot = i; new->uid = uid; llist_append (ignore_list, new); - Sys_Printf ("User %i (%s) is now ignored.\n", uid, Info_ValueForKey (cl.players[i].userinfo, "name")); + Sys_Printf ("User %i (%s) is now ignored.\n", uid, + Info_ValueForKey (cl.players[i].userinfo, "name")); return; } } @@ -136,11 +138,14 @@ CL_Unignore_f (void) else { uid = atoi (Cmd_Argv (1)); if ((node = llist_findnode (ignore_list, &uid))) { - Sys_Printf ("User %i (%s) is no longer ignored.\n", uid, Info_ValueForKey (cl.players[LLIST_DATA (node, ignore_t)->slot].userinfo, "name")); + int slot = LLIST_DATA (node, ignore_t)->slot; + Sys_Printf ("User %i (%s) is no longer ignored.\n", uid, + Info_ValueForKey (cl.players[slot].userinfo, "name")); CL_Ignore_Free (llist_remove (node), 0); return; } - Sys_Printf ("User %i does not exist or is not presently ignored.\n", uid); + Sys_Printf ("User %i does not exist or is not presently ignored.\n", + uid); } } @@ -159,7 +164,8 @@ static qboolean cam_iterator (ignore_t *ig, llist_node_t *node) llist_remove (node); return true; } - dsprintf (g_cam_test, "%s: ", Info_ValueForKey (cl.players[ig->slot].userinfo, "name")); + dsprintf (g_cam_test, "%s: ", + Info_ValueForKey (cl.players[ig->slot].userinfo, "name")); if (!strncmp (g_cam_test->str, g_cam_str, sizeof (g_cam_test->str))) { return g_cam_allowed = false; } else @@ -187,9 +193,11 @@ CL_Chat_User_Disconnected (int uid) if ((ig = llist_remove (llist_findnode (ignore_list, &uid)))) { if (ig->lastname) free ((void *)ig->lastname); - ig->lastname = strdup (Info_ValueForKey (cl.players[ig->slot].userinfo, "name")); + ig->lastname = strdup (Info_ValueForKey (cl.players[ig->slot].userinfo, + "name")); llist_append (dead_ignore_list, ig); - Sys_Printf ("Ignored user %i (%s) left the server. Now ignoring by name...\n", ig->uid, ig->lastname); + Sys_Printf ("Ignored user %i (%s) left the server. " + "Now ignoring by name...\n", ig->uid, ig->lastname); } } @@ -215,8 +223,12 @@ CL_Chat_Check_Name (const char *name, int slot) if (g_ccn_found) { g_ccn_found->slot = slot; g_ccn_found->uid = cl.players[slot].userid; - llist_append (ignore_list, llist_remove (llist_getnode (dead_ignore_list, g_ccn_found))); - Sys_Printf ("User %i (%s) is using an ignored name. Now ignoring by user id...\n", g_ccn_found->uid, g_ccn_found->lastname); + llist_append (ignore_list, + llist_remove (llist_getnode (dead_ignore_list, + g_ccn_found))); + Sys_Printf ("User %i (%s) is using an ignored name. " + "Now ignoring by user id...\n", g_ccn_found->uid, + g_ccn_found->lastname); } } From 7e2fcd1fbddcbab3ff2f4dd429acaf84e4abe2cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Feb 2013 17:35:09 +0900 Subject: [PATCH 1430/3664] Rename nq's cl.last_received_message to cl.last_servermessage. And make it double rather than float because absolute time should not be stored in a float. --- nq/include/client.h | 2 +- nq/source/cl_main.c | 1 - nq/source/cl_parse.c | 2 ++ nq/source/cl_screen.c | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index fe6fb5851..ff0c203d8 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -185,7 +185,7 @@ typedef struct { double oldtime; // Previous cl.time, time-oldtime is used // to decay light values and smooth step ups - float last_received_message; // (realtime) for net trouble icon + double last_servermessage; // (realtime) for net trouble icon /* information that is static for the entire time connected to a server */ diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 054d60677..00c089a5b 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -426,7 +426,6 @@ CL_ReadFromServer (void) if (!ret) break; - cl.last_received_message = realtime; CL_ParseServerMessage (); } while (ret && cls.state >= ca_connected); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 0b8e5972b..3855481c5 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -833,6 +833,8 @@ CL_ParseServerMessage (void) static dstring_t *stuffbuf; signon_t so; + cl.last_servermessage = realtime; + // if recording demos, copy the message out if (cl_shownet->int_val == 1) Sys_Printf ("%i ", net_message->message->cursize); diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 1a0f8e7be..da5163c5c 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -54,7 +54,7 @@ static qpic_t *scr_net; static void SCR_DrawNet (void) { - if (realtime - cl.last_received_message < 0.3) + if (realtime - cl.last_servermessage < 0.3) return; if (cls.demoplayback) return; From d39adc6a64ce0e50323ba9d03a717d2ea30dd47c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Feb 2013 18:01:37 +0900 Subject: [PATCH 1431/3664] Reduce the diff noise for client_state_t. And add a struct tag. Any added fields are, of course, unused. Most of the changes are to bring the comments into agreement. --- nq/include/client.h | 9 +++++---- qw/include/client.h | 17 +++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index ff0c203d8..b6e4a85bc 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -133,7 +133,7 @@ extern client_static_t cls; /* the client_state_t structure is wiped completely at every server signon */ -typedef struct { +typedef struct client_state_s { qboolean loading; int movemessages; // Since connecting to this server throw out @@ -144,7 +144,7 @@ typedef struct { // information for local display int stats[MAX_CL_STATS]; // Health, etc float item_gettime[32]; // cl.time of aquiring item, for blinking - float faceanimtime; // Use anim frame if cl.time < this + float faceanimtime; // Use anim frame if cl.time < this cshift_t cshifts[NUM_CSHIFTS]; // Color shifts for damage, powerups cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types @@ -170,13 +170,13 @@ typedef struct { double laststop; qboolean paused; // Sent over by server - int onground; + int onground; // -1 when in air float viewheight; float crouch; // Local amount for smoothing stepups qboolean inwater; int intermission; // Don't change view angle, full screen, etc - int completed_time; // Latched at intermission start + int completed_time; // Latched from time at intermission start double mtime[2]; // The timestamp of last two messages double time; // Clients view of time, should be between @@ -185,6 +185,7 @@ typedef struct { double oldtime; // Previous cl.time, time-oldtime is used // to decay light values and smooth step ups + double last_ping_request; // while showing scoreboard double last_servermessage; // (realtime) for net trouble icon /* information that is static for the entire time connected to a server */ diff --git a/qw/include/client.h b/qw/include/client.h index c9481f209..4a23f4c29 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -171,7 +171,7 @@ extern client_static_t cls; /* the client_state_t structure is wiped completely at every server signon */ -typedef struct { +typedef struct client_state_s { qboolean loading; int movemessages; // Since connecting to this server throw out @@ -183,7 +183,7 @@ typedef struct { int prev_sequence; // information for local display - int stats[MAX_CL_STATS]; // health, etc + int stats[MAX_CL_STATS]; // Health, etc float item_gettime[32]; // cl.time of aquiring item, for blinking float faceanimtime; // Use anim frame if cl.time < this @@ -213,10 +213,11 @@ typedef struct { qboolean paused; // Sent over by server int onground; // -1 when in air float viewheight; - float crouch; // local amount for smoothing stepups + float crouch; // Local amount for smoothing stepups + qboolean inwater; - int intermission; // don't change view angle, full screen, etc - int completed_time; // latched from time at intermission start + int intermission; // Don't change view angle, full screen, etc + int completed_time; // Latched from time at intermission start int servercount; // server identification for prespawns struct info_s *serverinfo; @@ -226,7 +227,7 @@ typedef struct { // can't render a frame yet double last_ping_request; // while showing scoreboard - double last_servermessage; + double last_servermessage; // (realtime) for net trouble icon /* information that is static for the entire time connected to a server */ @@ -244,7 +245,7 @@ typedef struct { char levelname[40]; // for display on solo scoreboard int spectator; int playernum; - int viewentity; + int viewentity; // cl_entitites[cl.viewentity] = player unsigned protocol; float stdver; int gametype; @@ -260,7 +261,7 @@ typedef struct { // refresh related state struct model_s *worldmodel; // cl_entitites[0].model - int num_entities; // stored bottom up in cl_entities array + int num_entities; // held in cl_entities array entity_t viewent; // the weapon model int cdtrack; // cd audio From 0cae54d25def912b7cdf12b3ab17edabf72de5ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 May 2013 08:02:43 +0900 Subject: [PATCH 1432/3664] Move the tex conversion to libQFimage. This is for the conversion /to/ paletted textures. The conversion is necessary for csqc support. In the process, the conversion has been sped up by implementing a color cache for the conversion process. I haven't measured the difference yet, but Mr Fixit does seem to load much faster for the sw renderer than it did before the change (many months old memory). --- include/QF/image.h | 17 +++- libs/image/Makefile.am | 2 +- libs/image/convert.c | 175 +++++++++++++++++++++++++++++++++ libs/models/iqm/sw_model_iqm.c | 55 +---------- tools/wad/script.c | 2 +- 5 files changed, 190 insertions(+), 61 deletions(-) create mode 100644 libs/image/convert.c diff --git a/include/QF/image.h b/include/QF/image.h index 33c69c120..73a9b0877 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -29,15 +29,16 @@ #ifndef __QF_image_h #define __QF_image_h +#include "QF/qtypes.h" #include "QF/quakeio.h" // could not use texture_t as that is used for models. typedef struct tex_s { - int width; - int height; - int format; - unsigned char *palette; // 0 = 32 bit, otherwise 8 - unsigned char data[4]; // variable length + int width; + int height; + int format; + const byte *palette; // 0 = 32 bit, otherwise 8 + byte data[4]; // variable length } tex_t; #define tex_palette 0 @@ -47,6 +48,12 @@ typedef struct tex_s { #define tex_rgb 3 #define tex_rgba 4 +typedef struct colcache_s colcache_t; + tex_t *LoadImage (const char *imageFile); +colcache_t *ColorCache_New (void); +void ColorCache_Delete (colcache_t *cache); +byte ConvertColor (const byte *rgb, const byte *pal, colcache_t *cache); +tex_t *ConvertImage (const tex_t *tex, const byte *pal); #endif //__QF_image_h diff --git a/libs/image/Makefile.am b/libs/image/Makefile.am index 344bd7dd7..052c825e1 100644 --- a/libs/image/Makefile.am +++ b/libs/image/Makefile.am @@ -13,6 +13,6 @@ libQFimage_la_LDFLAGS= $(lib_ldflags) libQFimage_la_LIBADD= $(image_deps) $(PNG_LIBS) libQFimage_la_DEPENDENCIES= $(pmage_deps) libQFimage_la_SOURCES= \ - image.c pcx.c png.c tga.c + convert.c image.c pcx.c png.c tga.c EXTRA_DIST= diff --git a/libs/image/convert.c b/libs/image/convert.c new file mode 100644 index 000000000..561405cba --- /dev/null +++ b/libs/image/convert.c @@ -0,0 +1,175 @@ +/* + convert.c + + Image/color conversion routins (RGB to paletted) + + Copyright (C) 2013 Bill Currie + + Author: Bill Currie + Date: 2013/5/10 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/alloc.h" +#include "QF/hash.h" +#include "QF/image.h" +#include "QF/mathlib.h" + +struct colcache_s { + struct colcache_s *next; + hashtab_t *tab; +}; + +typedef struct colcache_color_s { + struct colcache_color_s *next; + byte rgb[3]; + byte col; +} colcache_color_t; + +static colcache_t *colcache_freelist; +static colcache_color_t *colcache_color_freelist; + +static colcache_color_t * +colcache_new_color (const byte *rgb, byte ind) +{ + colcache_color_t *col; + ALLOC (256, colcache_color_t, colcache_color, col); + VectorCopy (rgb, col->rgb); + col->col = ind; + return col; +} + +static void +colcache_free_color (void *_col, void *unused) +{ + colcache_color_t *col = (colcache_color_t *) _col; + FREE (colcache_color, col); +} + +static uintptr_t +colcache_get_hash (const void *_col, void *unused) +{ + colcache_color_t *col = (colcache_color_t *) _col; + uintptr_t r, g, b; + r = col->rgb[0]; + g = col->rgb[1]; + b = col->rgb[2]; + return (r << 8) ^ (g << 4) ^ b; +} + +static int +colcache_compare (const void *_cola, const void *_colb, void *unused) +{ + colcache_color_t *cola = (colcache_color_t *) _cola; + colcache_color_t *colb = (colcache_color_t *) _colb; + + return VectorCompare (cola->rgb, colb->rgb); +} + +colcache_t * +ColorCache_New (void) +{ + colcache_t *cache; + + ALLOC (16, colcache_t, colcache, cache); + cache->tab = Hash_NewTable (1023, 0, colcache_free_color, 0); + Hash_SetHashCompare (cache->tab, colcache_get_hash, colcache_compare); + return cache; +} + +void +ColorCache_Delete (colcache_t *cache) +{ + Hash_DelTable (cache->tab); + FREE (colcache, cache); +} + +byte +ConvertColor (const byte *rgb, const byte *pal, colcache_t *cache) +{ + //FIXME slow! + int dist[3]; + int d, bestd = 256 * 256 * 3, bestc = -1; + int i; + colcache_color_t *col; + + if (cache) { + colcache_color_t search; + VectorCopy (rgb, search.rgb); + col = Hash_FindElement (cache->tab, &search); + if (col) + return col->col; + } + + for (i = 0; i < 256; i++) { + VectorSubtract (pal + i * 3, rgb, dist); + d = DotProduct (dist, dist); + if (d < bestd) { + bestd = d; + bestc = i; + } + } + if (cache) { + col = colcache_new_color (rgb, bestc); + Hash_AddElement (cache->tab, col); + } + return bestc; +} + +tex_t * +ConvertImage (const tex_t *tex, const byte *pal) +{ + tex_t *new; + int pixels; + int bpp = 3; + int i; + colcache_t *cache; + + pixels = tex->width * tex->height; + new = malloc (field_offset (tex_t, data[pixels])); + new->width = tex->width; + new->height = tex->height; + new->format = tex_palette; + new->palette = pal; + switch (tex->format) { + case tex_palette: + case tex_l: // will not work as expected + case tex_a: // will not work as expected + memcpy (new->data, tex->data, pixels); + break; + case tex_la: // will not work as expected + for (i = 0; i < pixels; i++) + new->data[i] = tex->data[i * 2]; + break; + case tex_rgba: + bpp = 4; + case tex_rgb: + cache = ColorCache_New (); + for (i = 0; i < pixels; i++) + new->data[i] = ConvertColor (tex->data + i * bpp, pal, cache); + ColorCache_Delete (cache); + break; + } + return new; +} diff --git a/libs/models/iqm/sw_model_iqm.c b/libs/models/iqm/sw_model_iqm.c index 2a32ecca0..cdf25b8ba 100644 --- a/libs/models/iqm/sw_model_iqm.c +++ b/libs/models/iqm/sw_model_iqm.c @@ -81,59 +81,6 @@ sw_iqm_clear (model_t *mod) Mod_FreeIQM (iqm); } -static byte -convert_color (byte *rgb) -{ - //FIXME slow! - int dist[3]; - int d, bestd = 256 * 256 * 3, bestc = -1; - int i; - - for (i = 0; i < 256; i++) { - VectorSubtract (vid.basepal + i * 3, rgb, dist); - d = DotProduct (dist, dist); - if (d < bestd) { - bestd = d; - bestc = i; - } - } - return bestc; -} - -static tex_t * -convert_tex (tex_t *tex) -{ - tex_t *new; - int pixels; - int bpp = 3; - int i; - - pixels = tex->width * tex->height; - new = malloc (field_offset (tex_t, data[pixels])); - new->width = tex->width; - new->height = tex->height; - new->format = tex_palette; - new->palette = 0; - switch (tex->format) { - case tex_palette: - case tex_l: // will not work as expected - case tex_a: // will not work as expected - memcpy (new->data, tex->data, pixels); - break; - case tex_la: // will not work as expected - for (i = 0; i < pixels; i++) - new->data[i] = tex->data[i * 2]; - break; - case tex_rgba: - bpp = 4; - case tex_rgb: - for (i = 0; i < pixels; i++) - new->data[i] = convert_color (tex->data + i * bpp); - break; - } - return new; -} - static inline void convert_coord (byte *tc, int size) { @@ -166,7 +113,7 @@ sw_iqm_load_textures (iqm_t *iqm) dstring_copystr (str, iqm->text + iqm->meshes[i].material); QFS_StripExtension (str->str, str->str); if ((tex = LoadImage (va ("textures/%s", str->str)))) - tex = sw->skins[i] = convert_tex (tex); + tex = sw->skins[i] = ConvertImage (tex, vid.basepal); else tex = sw->skins[i] = &null_texture; for (j = 0; j < (int) iqm->meshes[i].num_triangles * 3; j++) { diff --git a/tools/wad/script.c b/tools/wad/script.c index eef6a90e9..a9a9dcd5d 100644 --- a/tools/wad/script.c +++ b/tools/wad/script.c @@ -104,7 +104,7 @@ load_image (const char *name) switch (tex->format) { case tex_palette: for (i = 0, s = tex->data, d = image->data; i < pixels; i++) { - byte *v = tex->palette + *s++ * 3; + const byte *v = tex->palette + *s++ * 3; *d++ = *v++; *d++ = *v++; *d++ = *v++; From 669f9a65009276f2cc8dca1d6950034b8996e307 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Mar 2021 15:17:46 +0900 Subject: [PATCH 1433/3664] Revert "[build] Clean up obsolete QF_PROCESS_NEED_DIRS" This reverts commit 22c0bec03a9017529e63467d8769cb32612fe6ae. It turns out to have been a critical part of selective build control. --- config.d/build_control.m4 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 3094a69a6..4151e42c4 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -269,8 +269,13 @@ fi QF_NEED(top, [libs hw nq qtv qw]) +QF_PROCESS_NEED_DIRS(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav]) QF_PROCESS_NEED_FUNC(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav], QF_NEED(top,tools)) +QF_PROCESS_NEED_DIRS(libs,[util gamecode ruamoko gib audio image models video console net qw client]) + +QF_PROCESS_NEED_DIRS(ruamoko,[qwaq]) + if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) qfac_qfcc_include_qf="\$(qfcc_include_qf)" @@ -298,8 +303,11 @@ if test "$HAVE_ZLIB" = "yes"; then fi QF_SUBST(progs_gz) +QF_PROCESS_NEED_DIRS(top, [libs hw nq qtv qw tools ruamoko]) + QF_PROCESS_NEED_LIBS(swrend, [asm]) QF_PROCESS_NEED_LIBS(render, [gl glsl sw sw32 vulkan], [libs/video/renderer]) +QF_PROCESS_NEED_DIRS(vid_render, [gl glsl sw sw32 vulkan]) QF_PROCESS_NEED_LIBS(models, [gl glsl sw vulkan], [libs/models]) QF_PROCESS_NEED_LIBS(alias, [gl glsl sw vulkan], [libs/models/alias]) QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush]) From 7dc7bf138f7ec44422c77f2651d095248d433276 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Mar 2021 15:26:13 +0900 Subject: [PATCH 1434/3664] [build] Rename QF_PROCESS_NEED_DIRS QF_PROCESS_NEED_LIST is a better name as for one, building no longer depends on directories, and the directories were lists anyway, so the name is more generally applicable. --- config.d/build_control.m4 | 10 +++++----- config.d/result.m4 | 2 +- m4/quakeforge.m4 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 4151e42c4..67a706e21 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -269,12 +269,12 @@ fi QF_NEED(top, [libs hw nq qtv qw]) -QF_PROCESS_NEED_DIRS(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav]) +QF_PROCESS_NEED_LIST(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav]) QF_PROCESS_NEED_FUNC(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav], QF_NEED(top,tools)) -QF_PROCESS_NEED_DIRS(libs,[util gamecode ruamoko gib audio image models video console net qw client]) +QF_PROCESS_NEED_LIST(libs,[util gamecode ruamoko gib audio image models video console net qw client]) -QF_PROCESS_NEED_DIRS(ruamoko,[qwaq]) +QF_PROCESS_NEED_LIST(ruamoko,[qwaq]) if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) @@ -303,11 +303,11 @@ if test "$HAVE_ZLIB" = "yes"; then fi QF_SUBST(progs_gz) -QF_PROCESS_NEED_DIRS(top, [libs hw nq qtv qw tools ruamoko]) +QF_PROCESS_NEED_LIST(top, [libs hw nq qtv qw tools ruamoko]) QF_PROCESS_NEED_LIBS(swrend, [asm]) QF_PROCESS_NEED_LIBS(render, [gl glsl sw sw32 vulkan], [libs/video/renderer]) -QF_PROCESS_NEED_DIRS(vid_render, [gl glsl sw sw32 vulkan]) +QF_PROCESS_NEED_LIST(vid_render, [gl glsl sw sw32 vulkan]) QF_PROCESS_NEED_LIBS(models, [gl glsl sw vulkan], [libs/models]) QF_PROCESS_NEED_LIBS(alias, [gl glsl sw vulkan], [libs/models/alias]) QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush]) diff --git a/config.d/result.m4 b/config.d/result.m4 index 87ded6b36..f2dc7fd70 100644 --- a/config.d/result.m4 +++ b/config.d/result.m4 @@ -4,7 +4,7 @@ AC_MSG_RESULT([ Build type :$BUILD_TYPE Server support :${SV_TARGETS:- no} Client support :${CL_TARGETS:- no} - Tools support :${tools_dirs:- no} + Tools support :${tools_list:- no} Sound support :${SOUND_TYPES:- no} ${snd_output_default} CD Audio system :${CDTYPE:- no} ${cd_default} IPv6 networking : $NETTYPE_IPV6 diff --git a/m4/quakeforge.m4 b/m4/quakeforge.m4 index 984cd71f7..5dad02d82 100644 --- a/m4/quakeforge.m4 +++ b/m4/quakeforge.m4 @@ -109,9 +109,9 @@ AC_DEFUN([QF_PROCESS_NEED_LIBS], QF_PROCESS_NEED_subroutine([lib$1_],[$1],[.]qfn_ext,[$1_libs],[$2],[$3]) QF_SUBST([$1_libs])]) -AC_DEFUN([QF_PROCESS_NEED_DIRS], -[QF_PROCESS_NEED_subroutine([],[$1],[],[$1_dirs],[$2]) -QF_SUBST([$1_dirs])]) +AC_DEFUN([QF_PROCESS_NEED_LIST], +[QF_PROCESS_NEED_subroutine([],[$1],[],[$1_list],[$2]) +QF_SUBST([$1_list])]) AC_DEFUN([QF_DEFAULT_PLUGIN], [m4_define([qfn_default], m4_default($3,$1)[_default]) From c901fe74f998d825f64ae9ef793614b5463f3f99 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Mar 2021 15:27:48 +0900 Subject: [PATCH 1435/3664] [qfvis] Fix pthread portability macros Those that were defined were incorrectly defined (didn't swallow the parameter), and portal lock macros were missing. --- tools/qfvis/include/vis.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index a0863d4be..dc24d17f4 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -65,8 +65,11 @@ extern pthread_rwlock_t *portal_locks; #define UNLOCK_PORTAL(p) UNLOCK (&portal_locks[p - portals]) #else -#define LOCK -#define UNLOCK +#define LOCK(l) +#define UNLOCK(l) +#define WRLOCK_PORTAL(p) +#define RDLOCK_PORTAL(p) +#define UNLOCK_PORTAL(p) #endif #include "QF/set.h" From 238e80c89b07d350fb1d5a49414bd84b5ce1ea8a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Mar 2021 16:11:29 +0900 Subject: [PATCH 1436/3664] [build] Fix selective build of tools A couple of things get built when they shouldn't (eg, vkgen) but this gets the build system back to its pre-non-recursive-make configurability. --- config.d/build_control.m4 | 28 ++++++++++++++++++++++++++ tools/bsp2img/Makemodule.am | 3 ++- tools/carne/Makemodule.am | 3 ++- tools/cross/mingw64/cross-configure.sh | 8 ++++---- tools/pak/Makemodule.am | 3 ++- tools/qfbsp/source/Makemodule.am | 3 ++- tools/qfcc/source/Makemodule.am | 3 ++- tools/qflight/source/Makemodule.am | 3 ++- tools/qflmp/Makemodule.am | 3 ++- tools/qfmodelgen/source/Makemodule.am | 3 ++- tools/qfspritegen/Makemodule.am | 3 ++- tools/qfvis/source/Makemodule.am | 3 ++- tools/wad/Makemodule.am | 3 ++- tools/wav/Makemodule.am | 3 ++- 14 files changed, 56 insertions(+), 16 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 67a706e21..49e1b368c 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -27,6 +27,9 @@ QWAQ_TARGETS="" QW_DESKTOP_DATA="" NQ_DESKTOP_DATA="" +PAK_TARGETS +QFCC_TARGETS + CD_TARGETS="" SND_TARGETS="" VID_MODEL_TARGETS="" @@ -211,42 +214,52 @@ if test "x$ENABLE_servers_qw" = xyes; then fi if test "x$ENABLE_tools_bsp2img" = xyes; then + BSP2IMG_TARGETS=bsp2img QF_NEED(tools,[bsp2img]) QF_NEED(libs,[image util]) fi if test "x$ENABLE_tools_carne" = xyes; then + CARNE_TARGETS=carne QF_NEED(tools,[carne]) QF_NEED(libs,[gib ruamoko gamecode util]) fi if test "x$ENABLE_tools_pak" = xyes; then + PAK_TARGETS=pak QF_NEED(tools,[pak]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfbsp" = xyes; then + QFBSP_TARGETS=qfbsp QF_NEED(tools,[qfbsp]) QF_NEED(libs,[models image util]) fi if test "x$ENABLE_tools_qfcc" = xyes; then + QFCC_TARGETS=qfcc qfprogs QF_NEED(tools,[qfcc]) QF_NEED(libs,[gamecode util]) fi if test "x$ENABLE_tools_qflight" = xyes; then + QFLIGHT_TARGETS=qflight QF_NEED(tools,[qflight]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qflmp" = xyes; then + QFLMP_TARGETS=qflmp QF_NEED(tools,[qflmp]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfmodelgen" = xyes; then + QFMODELGEN_TARGETS=qfmodelgen QF_NEED(tools,[qfmodelgen]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfspritegen" = xyes; then + QFSPRITEGEN_TARGETS=qfspritegen QF_NEED(tools,[qfspritegen]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfvis" = xyes; then + QFVIS_TARGETS=qfvis QF_NEED(tools,[qfvis]) QF_NEED(libs,[util]) fi @@ -259,10 +272,12 @@ if test "x$ENABLE_tools_qwaq" = xyes; then QF_NEED(libs,[ruamoko gamecode util]) fi if test "x$ENABLE_tools_wad" = xyes; then + WAD_TARGETS=wad QF_NEED(tools,[wad]) QF_NEED(libs,[image util]) fi if test "x$ENABLE_tools_wav" = xyes; then + WAV_TARGETS=wav QF_NEED(tools,[wav]) QF_NEED(libs,[util]) fi @@ -399,6 +414,19 @@ QF_SUBST(VID_REND_TARGETS) QF_SUBST(VID_REND_NOINST_TARGETS) QF_SUBST(VID_TARGETS) +QF_SUBST(BSP2IMG_TARGETS) +QF_SUBST(CARNE_TARGETS) +QF_SUBST(PAK_TARGETS) +QF_SUBST(QFBSP_TARGETS) +QF_SUBST(QFCC_TARGETS) +QF_SUBST(QFLIGHT_TARGETS) +QF_SUBST(QFLMP_TARGETS) +QF_SUBST(QFMODELGEN_TARGETS) +QF_SUBST(QFSPRITEGEN_TARGETS) +QF_SUBST(QFVIS_TARGETS) +QF_SUBST(WAD_TARGETS) +QF_SUBST(WAV_TARGETS) + QF_DEPS(BSP2IMG, [], [$(top_builddir)/libs/image/libQFimage.la diff --git a/tools/bsp2img/Makemodule.am b/tools/bsp2img/Makemodule.am index bf58c14aa..24b6594c2 100644 --- a/tools/bsp2img/Makemodule.am +++ b/tools/bsp2img/Makemodule.am @@ -2,7 +2,8 @@ BSP2IMG_LIBS=@BSP2IMG_LIBS@ BSP2IMG_DEPS=@BSP2IMG_DEPS@ BSP2IMG_INCS=@BSP2IMG_INCS@ -bin_PROGRAMS += bsp2img +EXTRA_PROGRAMS += bsp2img +bin_PROGRAMS += @BSP2IMG_TARGETS@ bsp2img_SOURCES= tools/bsp2img/bsp2img.c bsp2img_LDADD= $(BSP2IMG_LIBS) diff --git a/tools/carne/Makemodule.am b/tools/carne/Makemodule.am index 24f5f056b..fe5862c0e 100644 --- a/tools/carne/Makemodule.am +++ b/tools/carne/Makemodule.am @@ -1,7 +1,8 @@ CARNE_LIBS=@CARNE_LIBS@ CARNE_DEPS=@CARNE_DEPS@ -noinst_PROGRAMS += carne +EXTRA_PROGRAMS += carne +noinst_PROGRAMS += @CARNE_TARGETS@ carne_SOURCES= tools/carne/main.c carne_LDADD= $(CARNE_LIBS) diff --git a/tools/cross/mingw64/cross-configure.sh b/tools/cross/mingw64/cross-configure.sh index 73f76c677..b9aa14371 100755 --- a/tools/cross/mingw64/cross-configure.sh +++ b/tools/cross/mingw64/cross-configure.sh @@ -1,19 +1,19 @@ #!/bin/sh -x set -e -mkdir -p native x86_64-w64-mingw32 +mkdir -p native i686-w64-mingw32.static cd native ../../configure \ --disable-shared \ --without-clients \ --without-servers \ --with-tools=qfcc,pak -cd ../x86_64-w64-mingw32 +cd ../i686-w64-mingw32.static export MINGW=/opt/mxe -export MINGW_USR=$MINGW/usr/x86_64-w64-mingw32 +export MINGW_USR=$MINGW/usr/i686-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH ../../configure \ - --host=x86_64-w64-mingw32 \ + --host=i686-w64-mingw32.static \ --disable-shared \ $* diff --git a/tools/pak/Makemodule.am b/tools/pak/Makemodule.am index d7a247e88..3716b0b17 100644 --- a/tools/pak/Makemodule.am +++ b/tools/pak/Makemodule.am @@ -2,7 +2,8 @@ PAK_LIBS=@PAK_LIBS@ PAK_DEPS=@PAK_DEPS@ PAK_INCS=@PAK_INCS@ -bin_PROGRAMS += pak +EXTRA_PROGRAMS += pak +bin_PROGRAMS += @PAK_TARGETS@ bin_SCRIPTS += tools/pak/zpak man_MANS += tools/pak/pak.1 tools/pak/zpak.1 diff --git a/tools/qfbsp/source/Makemodule.am b/tools/qfbsp/source/Makemodule.am index 2e3e9a524..1dda50b5c 100644 --- a/tools/qfbsp/source/Makemodule.am +++ b/tools/qfbsp/source/Makemodule.am @@ -2,7 +2,8 @@ QFBSP_LIBS=@QFBSP_LIBS@ QFBSP_DEPS=@QFBSP_DEPS@ QFBSP_INCS=@QFBSP_INCS@ -bin_PROGRAMS += qfbsp +EXTRA_PROGRAMS += qfbsp +bin_PROGRAMS += @QFBSP_TARGETS@ qfbsp_SOURCES= \ tools/qfbsp/source/brush.c \ diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index dacfd3448..97b4eeb5c 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -2,7 +2,8 @@ QFCC_LIBS=@QFCC_LIBS@ QFCC_DEPS=@QFCC_DEPS@ QFCC_INCS=@QFCC_INCS@ -bin_PROGRAMS += qfcc qfprogs +EXTRA_PROGRAMS += qfcc qfprogs +bin_PROGRAMS += @QFCC_TARGETS@ bin_SCRIPTS += tools/qfcc/source/qfpreqcc qfcc_SOURCES = \ diff --git a/tools/qflight/source/Makemodule.am b/tools/qflight/source/Makemodule.am index 0913e37a8..8990cea7a 100644 --- a/tools/qflight/source/Makemodule.am +++ b/tools/qflight/source/Makemodule.am @@ -2,7 +2,8 @@ QFLIGHT_LIBS=@QFLIGHT_LIBS@ QFLIGHT_DEPS=@QFLIGHT_DEPS@ QFLIGHT_INCS=@QFLIGHT_INCS@ -bin_PROGRAMS += qflight +EXTRA_PROGRAMS += qflight +bin_PROGRAMS += @QFLIGHT_TARGETS@ qflight_SOURCES=\ tools/qflight/source/entities.c \ diff --git a/tools/qflmp/Makemodule.am b/tools/qflmp/Makemodule.am index 78dd3a233..f1a07221a 100644 --- a/tools/qflmp/Makemodule.am +++ b/tools/qflmp/Makemodule.am @@ -2,7 +2,8 @@ QFLMP_LIBS=@QFLMP_LIBS@ QFLMP_DEPS=@QFLMP_DEPS@ QFLMP_INCS=@QFLMP_INCS@ -bin_PROGRAMS += qflmp +EXTRA_PROGRAMS += qflmp +bin_PROGRAMS += @QFLMP_TARGETS@ #mans=qflmp.1 man_MANS += $(mans) diff --git a/tools/qfmodelgen/source/Makemodule.am b/tools/qfmodelgen/source/Makemodule.am index 9ca6ae7ef..86d40702e 100644 --- a/tools/qfmodelgen/source/Makemodule.am +++ b/tools/qfmodelgen/source/Makemodule.am @@ -2,7 +2,8 @@ QFMODELGEN_LIBS=@QFMODELGEN_LIBS@ QFMODELGEN_DEPS=@QFMODELGEN_DEPS@ QFMODELGEN_INCS=@QFMODELGEN_INCS@ -bin_PROGRAMS += qfmodelgen +EXTRA_PROGRAMS += qfmodelgen +bin_PROGRAMS += @QFMODELGEN_TARGETS@ qfmodelgen_SOURCES = \ tools/qfmodelgen/source/lbmlib.c \ diff --git a/tools/qfspritegen/Makemodule.am b/tools/qfspritegen/Makemodule.am index a12777453..ae36299e5 100644 --- a/tools/qfspritegen/Makemodule.am +++ b/tools/qfspritegen/Makemodule.am @@ -2,7 +2,8 @@ QFSPRITEGEN_LIBS=@QFSPRITEGEN_LIBS@ QFSPRITEGEN_DEPS=@QFSPRITEGEN_DEPS@ QFSPRITEGEN_INCS=@QFSPRITEGEN_INCS@ -bin_PROGRAMS += qfspritegen +EXTRA_PROGRAMS += qfspritegen +bin_PROGRAMS += @QFSPRITEGEN_TARGETS@ qfspritegen_SOURCES= tools/qfspritegen/spritegen.c diff --git a/tools/qfvis/source/Makemodule.am b/tools/qfvis/source/Makemodule.am index 73ccf547e..cb11f2406 100644 --- a/tools/qfvis/source/Makemodule.am +++ b/tools/qfvis/source/Makemodule.am @@ -2,7 +2,8 @@ QFVIS_LIBS=@QFVIS_LIBS@ QFVIS_DEPS=@QFVIS_DEPS@ QFVIS_INCS=@QFVIS_INCS@ -bin_PROGRAMS += qfvis +EXTRA_PROGRAMS += qfvis +bin_PROGRAMS += @QFVIS_TARGETS@ qfvis_SOURCES = \ tools/qfvis/source/base-vis.c \ diff --git a/tools/wad/Makemodule.am b/tools/wad/Makemodule.am index dd68d6842..13fcf3a43 100644 --- a/tools/wad/Makemodule.am +++ b/tools/wad/Makemodule.am @@ -2,7 +2,8 @@ WAD_LIBS=@WAD_LIBS@ WAD_DEPS=@WAD_DEPS@ WAD_INCS=@WAD_INCS@ -bin_PROGRAMS += wad +EXTRA_PROGRAMS += wad +bin_PROGRAMS += @WAD_TARGETS@ man_MANS += tools/wad/wad.1 diff --git a/tools/wav/Makemodule.am b/tools/wav/Makemodule.am index 4a4726809..6eb727ad0 100644 --- a/tools/wav/Makemodule.am +++ b/tools/wav/Makemodule.am @@ -2,7 +2,8 @@ WAV_LIBS=@WAV_LIBS@ WAV_DEPS=@WAV_DEPS@ WAV_INCS=@WAV_INCS@ -bin_PROGRAMS += qfwavinfo +EXTRA_PROGRAMS += qfwavinfo +bin_PROGRAMS += @WAV_TARGETS@ #man_MANS += tools/wav/qfwavinfo.1 From 065f7e1e155b316eaf240a9fe21d4d586768e3ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Mar 2021 15:17:46 +0900 Subject: [PATCH 1437/3664] Revert "[build] Clean up obsolete QF_PROCESS_NEED_DIRS" This reverts commit 22c0bec03a9017529e63467d8769cb32612fe6ae. It turns out to have been a critical part of selective build control. --- config.d/build_control.m4 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index a5fc7bc51..1a5ade74f 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -267,8 +267,13 @@ fi QF_NEED(top, [libs hw nq qtv qw]) +QF_PROCESS_NEED_DIRS(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav]) QF_PROCESS_NEED_FUNC(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav], QF_NEED(top,tools)) +QF_PROCESS_NEED_DIRS(libs,[util gamecode ruamoko gib audio image models video console net qw client]) + +QF_PROCESS_NEED_DIRS(ruamoko,[qwaq]) + if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) qfac_qfcc_include_qf="\$(qfcc_include_qf)" @@ -296,8 +301,11 @@ if test "$HAVE_ZLIB" = "yes"; then fi QF_SUBST(progs_gz) +QF_PROCESS_NEED_DIRS(top, [libs hw nq qtv qw tools ruamoko]) + QF_PROCESS_NEED_LIBS(swrend, [asm]) QF_PROCESS_NEED_LIBS(render, [gl glsl sw sw32 vulkan], [libs/video/renderer]) +QF_PROCESS_NEED_DIRS(vid_render, [gl glsl sw sw32 vulkan]) QF_PROCESS_NEED_LIBS(models, [gl glsl sw vulkan], [libs/models]) QF_PROCESS_NEED_LIBS(alias, [gl glsl sw vulkan], [libs/models/alias]) QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush]) From f85836762a2f86e335f5d8f2cab0b2abf15f1317 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Mar 2021 15:26:13 +0900 Subject: [PATCH 1438/3664] [build] Rename QF_PROCESS_NEED_DIRS QF_PROCESS_NEED_LIST is a better name as for one, building no longer depends on directories, and the directories were lists anyway, so the name is more generally applicable. --- config.d/build_control.m4 | 10 +++++----- config.d/result.m4 | 2 +- m4/quakeforge.m4 | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 1a5ade74f..e61f2abad 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -267,12 +267,12 @@ fi QF_NEED(top, [libs hw nq qtv qw]) -QF_PROCESS_NEED_DIRS(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav]) +QF_PROCESS_NEED_LIST(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav]) QF_PROCESS_NEED_FUNC(tools,[bsp2img carne pak qfbsp qfcc qflight qflmp qfmodelgen qfspritegen qfvis wad wav], QF_NEED(top,tools)) -QF_PROCESS_NEED_DIRS(libs,[util gamecode ruamoko gib audio image models video console net qw client]) +QF_PROCESS_NEED_LIST(libs,[util gamecode ruamoko gib audio image models video console net qw client]) -QF_PROCESS_NEED_DIRS(ruamoko,[qwaq]) +QF_PROCESS_NEED_LIST(ruamoko,[qwaq]) if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) @@ -301,11 +301,11 @@ if test "$HAVE_ZLIB" = "yes"; then fi QF_SUBST(progs_gz) -QF_PROCESS_NEED_DIRS(top, [libs hw nq qtv qw tools ruamoko]) +QF_PROCESS_NEED_LIST(top, [libs hw nq qtv qw tools ruamoko]) QF_PROCESS_NEED_LIBS(swrend, [asm]) QF_PROCESS_NEED_LIBS(render, [gl glsl sw sw32 vulkan], [libs/video/renderer]) -QF_PROCESS_NEED_DIRS(vid_render, [gl glsl sw sw32 vulkan]) +QF_PROCESS_NEED_LIST(vid_render, [gl glsl sw sw32 vulkan]) QF_PROCESS_NEED_LIBS(models, [gl glsl sw vulkan], [libs/models]) QF_PROCESS_NEED_LIBS(alias, [gl glsl sw vulkan], [libs/models/alias]) QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush]) diff --git a/config.d/result.m4 b/config.d/result.m4 index 87ded6b36..f2dc7fd70 100644 --- a/config.d/result.m4 +++ b/config.d/result.m4 @@ -4,7 +4,7 @@ AC_MSG_RESULT([ Build type :$BUILD_TYPE Server support :${SV_TARGETS:- no} Client support :${CL_TARGETS:- no} - Tools support :${tools_dirs:- no} + Tools support :${tools_list:- no} Sound support :${SOUND_TYPES:- no} ${snd_output_default} CD Audio system :${CDTYPE:- no} ${cd_default} IPv6 networking : $NETTYPE_IPV6 diff --git a/m4/quakeforge.m4 b/m4/quakeforge.m4 index 984cd71f7..5dad02d82 100644 --- a/m4/quakeforge.m4 +++ b/m4/quakeforge.m4 @@ -109,9 +109,9 @@ AC_DEFUN([QF_PROCESS_NEED_LIBS], QF_PROCESS_NEED_subroutine([lib$1_],[$1],[.]qfn_ext,[$1_libs],[$2],[$3]) QF_SUBST([$1_libs])]) -AC_DEFUN([QF_PROCESS_NEED_DIRS], -[QF_PROCESS_NEED_subroutine([],[$1],[],[$1_dirs],[$2]) -QF_SUBST([$1_dirs])]) +AC_DEFUN([QF_PROCESS_NEED_LIST], +[QF_PROCESS_NEED_subroutine([],[$1],[],[$1_list],[$2]) +QF_SUBST([$1_list])]) AC_DEFUN([QF_DEFAULT_PLUGIN], [m4_define([qfn_default], m4_default($3,$1)[_default]) From 9b51907ec840564590b2ed40b162e98d679f40e2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Mar 2021 15:27:48 +0900 Subject: [PATCH 1439/3664] [qfvis] Fix pthread portability macros Those that were defined were incorrectly defined (didn't swallow the parameter), and portal lock macros were missing. --- tools/qfvis/include/vis.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index a0863d4be..dc24d17f4 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -65,8 +65,11 @@ extern pthread_rwlock_t *portal_locks; #define UNLOCK_PORTAL(p) UNLOCK (&portal_locks[p - portals]) #else -#define LOCK -#define UNLOCK +#define LOCK(l) +#define UNLOCK(l) +#define WRLOCK_PORTAL(p) +#define RDLOCK_PORTAL(p) +#define UNLOCK_PORTAL(p) #endif #include "QF/set.h" From f1d7467ae8c181482d08ebb150e22750b1f540e9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Mar 2021 16:11:29 +0900 Subject: [PATCH 1440/3664] [build] Fix selective build of tools A couple of things get built when they shouldn't (eg, vkgen) but this gets the build system back to its pre-non-recursive-make configurability. --- config.d/build_control.m4 | 28 ++++++++++++++++++++++++++ tools/bsp2img/Makemodule.am | 3 ++- tools/carne/Makemodule.am | 3 ++- tools/cross/mingw64/cross-configure.sh | 8 ++++---- tools/pak/Makemodule.am | 3 ++- tools/qfbsp/source/Makemodule.am | 3 ++- tools/qfcc/source/Makemodule.am | 3 ++- tools/qflight/source/Makemodule.am | 3 ++- tools/qflmp/Makemodule.am | 3 ++- tools/qfmodelgen/source/Makemodule.am | 3 ++- tools/qfspritegen/Makemodule.am | 3 ++- tools/qfvis/source/Makemodule.am | 3 ++- tools/wad/Makemodule.am | 3 ++- tools/wav/Makemodule.am | 3 ++- 14 files changed, 56 insertions(+), 16 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index e61f2abad..1b9331f43 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -27,6 +27,9 @@ QWAQ_TARGETS="" QW_DESKTOP_DATA="" NQ_DESKTOP_DATA="" +PAK_TARGETS +QFCC_TARGETS + CD_TARGETS="" SND_TARGETS="" VID_MODEL_TARGETS="" @@ -209,42 +212,52 @@ if test "x$ENABLE_servers_qw" = xyes; then fi if test "x$ENABLE_tools_bsp2img" = xyes; then + BSP2IMG_TARGETS=bsp2img QF_NEED(tools,[bsp2img]) QF_NEED(libs,[image util]) fi if test "x$ENABLE_tools_carne" = xyes; then + CARNE_TARGETS=carne QF_NEED(tools,[carne]) QF_NEED(libs,[gib ruamoko gamecode util]) fi if test "x$ENABLE_tools_pak" = xyes; then + PAK_TARGETS=pak QF_NEED(tools,[pak]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfbsp" = xyes; then + QFBSP_TARGETS=qfbsp QF_NEED(tools,[qfbsp]) QF_NEED(libs,[models image util]) fi if test "x$ENABLE_tools_qfcc" = xyes; then + QFCC_TARGETS=qfcc qfprogs QF_NEED(tools,[qfcc]) QF_NEED(libs,[gamecode util]) fi if test "x$ENABLE_tools_qflight" = xyes; then + QFLIGHT_TARGETS=qflight QF_NEED(tools,[qflight]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qflmp" = xyes; then + QFLMP_TARGETS=qflmp QF_NEED(tools,[qflmp]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfmodelgen" = xyes; then + QFMODELGEN_TARGETS=qfmodelgen QF_NEED(tools,[qfmodelgen]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfspritegen" = xyes; then + QFSPRITEGEN_TARGETS=qfspritegen QF_NEED(tools,[qfspritegen]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfvis" = xyes; then + QFVIS_TARGETS=qfvis QF_NEED(tools,[qfvis]) QF_NEED(libs,[util]) fi @@ -257,10 +270,12 @@ if test "x$ENABLE_tools_qwaq" = xyes; then QF_NEED(libs,[ruamoko gamecode util]) fi if test "x$ENABLE_tools_wad" = xyes; then + WAD_TARGETS=wad QF_NEED(tools,[wad]) QF_NEED(libs,[image util]) fi if test "x$ENABLE_tools_wav" = xyes; then + WAV_TARGETS=wav QF_NEED(tools,[wav]) QF_NEED(libs,[util]) fi @@ -397,6 +412,19 @@ QF_SUBST(VID_REND_TARGETS) QF_SUBST(VID_REND_NOINST_TARGETS) QF_SUBST(VID_TARGETS) +QF_SUBST(BSP2IMG_TARGETS) +QF_SUBST(CARNE_TARGETS) +QF_SUBST(PAK_TARGETS) +QF_SUBST(QFBSP_TARGETS) +QF_SUBST(QFCC_TARGETS) +QF_SUBST(QFLIGHT_TARGETS) +QF_SUBST(QFLMP_TARGETS) +QF_SUBST(QFMODELGEN_TARGETS) +QF_SUBST(QFSPRITEGEN_TARGETS) +QF_SUBST(QFVIS_TARGETS) +QF_SUBST(WAD_TARGETS) +QF_SUBST(WAV_TARGETS) + QF_DEPS(BSP2IMG, [], [$(top_builddir)/libs/image/libQFimage.la diff --git a/tools/bsp2img/Makemodule.am b/tools/bsp2img/Makemodule.am index bf58c14aa..24b6594c2 100644 --- a/tools/bsp2img/Makemodule.am +++ b/tools/bsp2img/Makemodule.am @@ -2,7 +2,8 @@ BSP2IMG_LIBS=@BSP2IMG_LIBS@ BSP2IMG_DEPS=@BSP2IMG_DEPS@ BSP2IMG_INCS=@BSP2IMG_INCS@ -bin_PROGRAMS += bsp2img +EXTRA_PROGRAMS += bsp2img +bin_PROGRAMS += @BSP2IMG_TARGETS@ bsp2img_SOURCES= tools/bsp2img/bsp2img.c bsp2img_LDADD= $(BSP2IMG_LIBS) diff --git a/tools/carne/Makemodule.am b/tools/carne/Makemodule.am index 24f5f056b..fe5862c0e 100644 --- a/tools/carne/Makemodule.am +++ b/tools/carne/Makemodule.am @@ -1,7 +1,8 @@ CARNE_LIBS=@CARNE_LIBS@ CARNE_DEPS=@CARNE_DEPS@ -noinst_PROGRAMS += carne +EXTRA_PROGRAMS += carne +noinst_PROGRAMS += @CARNE_TARGETS@ carne_SOURCES= tools/carne/main.c carne_LDADD= $(CARNE_LIBS) diff --git a/tools/cross/mingw64/cross-configure.sh b/tools/cross/mingw64/cross-configure.sh index 73f76c677..b9aa14371 100755 --- a/tools/cross/mingw64/cross-configure.sh +++ b/tools/cross/mingw64/cross-configure.sh @@ -1,19 +1,19 @@ #!/bin/sh -x set -e -mkdir -p native x86_64-w64-mingw32 +mkdir -p native i686-w64-mingw32.static cd native ../../configure \ --disable-shared \ --without-clients \ --without-servers \ --with-tools=qfcc,pak -cd ../x86_64-w64-mingw32 +cd ../i686-w64-mingw32.static export MINGW=/opt/mxe -export MINGW_USR=$MINGW/usr/x86_64-w64-mingw32 +export MINGW_USR=$MINGW/usr/i686-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH ../../configure \ - --host=x86_64-w64-mingw32 \ + --host=i686-w64-mingw32.static \ --disable-shared \ $* diff --git a/tools/pak/Makemodule.am b/tools/pak/Makemodule.am index d7a247e88..3716b0b17 100644 --- a/tools/pak/Makemodule.am +++ b/tools/pak/Makemodule.am @@ -2,7 +2,8 @@ PAK_LIBS=@PAK_LIBS@ PAK_DEPS=@PAK_DEPS@ PAK_INCS=@PAK_INCS@ -bin_PROGRAMS += pak +EXTRA_PROGRAMS += pak +bin_PROGRAMS += @PAK_TARGETS@ bin_SCRIPTS += tools/pak/zpak man_MANS += tools/pak/pak.1 tools/pak/zpak.1 diff --git a/tools/qfbsp/source/Makemodule.am b/tools/qfbsp/source/Makemodule.am index 2e3e9a524..1dda50b5c 100644 --- a/tools/qfbsp/source/Makemodule.am +++ b/tools/qfbsp/source/Makemodule.am @@ -2,7 +2,8 @@ QFBSP_LIBS=@QFBSP_LIBS@ QFBSP_DEPS=@QFBSP_DEPS@ QFBSP_INCS=@QFBSP_INCS@ -bin_PROGRAMS += qfbsp +EXTRA_PROGRAMS += qfbsp +bin_PROGRAMS += @QFBSP_TARGETS@ qfbsp_SOURCES= \ tools/qfbsp/source/brush.c \ diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index dacfd3448..97b4eeb5c 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -2,7 +2,8 @@ QFCC_LIBS=@QFCC_LIBS@ QFCC_DEPS=@QFCC_DEPS@ QFCC_INCS=@QFCC_INCS@ -bin_PROGRAMS += qfcc qfprogs +EXTRA_PROGRAMS += qfcc qfprogs +bin_PROGRAMS += @QFCC_TARGETS@ bin_SCRIPTS += tools/qfcc/source/qfpreqcc qfcc_SOURCES = \ diff --git a/tools/qflight/source/Makemodule.am b/tools/qflight/source/Makemodule.am index 0913e37a8..8990cea7a 100644 --- a/tools/qflight/source/Makemodule.am +++ b/tools/qflight/source/Makemodule.am @@ -2,7 +2,8 @@ QFLIGHT_LIBS=@QFLIGHT_LIBS@ QFLIGHT_DEPS=@QFLIGHT_DEPS@ QFLIGHT_INCS=@QFLIGHT_INCS@ -bin_PROGRAMS += qflight +EXTRA_PROGRAMS += qflight +bin_PROGRAMS += @QFLIGHT_TARGETS@ qflight_SOURCES=\ tools/qflight/source/entities.c \ diff --git a/tools/qflmp/Makemodule.am b/tools/qflmp/Makemodule.am index 78dd3a233..f1a07221a 100644 --- a/tools/qflmp/Makemodule.am +++ b/tools/qflmp/Makemodule.am @@ -2,7 +2,8 @@ QFLMP_LIBS=@QFLMP_LIBS@ QFLMP_DEPS=@QFLMP_DEPS@ QFLMP_INCS=@QFLMP_INCS@ -bin_PROGRAMS += qflmp +EXTRA_PROGRAMS += qflmp +bin_PROGRAMS += @QFLMP_TARGETS@ #mans=qflmp.1 man_MANS += $(mans) diff --git a/tools/qfmodelgen/source/Makemodule.am b/tools/qfmodelgen/source/Makemodule.am index 9ca6ae7ef..86d40702e 100644 --- a/tools/qfmodelgen/source/Makemodule.am +++ b/tools/qfmodelgen/source/Makemodule.am @@ -2,7 +2,8 @@ QFMODELGEN_LIBS=@QFMODELGEN_LIBS@ QFMODELGEN_DEPS=@QFMODELGEN_DEPS@ QFMODELGEN_INCS=@QFMODELGEN_INCS@ -bin_PROGRAMS += qfmodelgen +EXTRA_PROGRAMS += qfmodelgen +bin_PROGRAMS += @QFMODELGEN_TARGETS@ qfmodelgen_SOURCES = \ tools/qfmodelgen/source/lbmlib.c \ diff --git a/tools/qfspritegen/Makemodule.am b/tools/qfspritegen/Makemodule.am index a12777453..ae36299e5 100644 --- a/tools/qfspritegen/Makemodule.am +++ b/tools/qfspritegen/Makemodule.am @@ -2,7 +2,8 @@ QFSPRITEGEN_LIBS=@QFSPRITEGEN_LIBS@ QFSPRITEGEN_DEPS=@QFSPRITEGEN_DEPS@ QFSPRITEGEN_INCS=@QFSPRITEGEN_INCS@ -bin_PROGRAMS += qfspritegen +EXTRA_PROGRAMS += qfspritegen +bin_PROGRAMS += @QFSPRITEGEN_TARGETS@ qfspritegen_SOURCES= tools/qfspritegen/spritegen.c diff --git a/tools/qfvis/source/Makemodule.am b/tools/qfvis/source/Makemodule.am index 73ccf547e..cb11f2406 100644 --- a/tools/qfvis/source/Makemodule.am +++ b/tools/qfvis/source/Makemodule.am @@ -2,7 +2,8 @@ QFVIS_LIBS=@QFVIS_LIBS@ QFVIS_DEPS=@QFVIS_DEPS@ QFVIS_INCS=@QFVIS_INCS@ -bin_PROGRAMS += qfvis +EXTRA_PROGRAMS += qfvis +bin_PROGRAMS += @QFVIS_TARGETS@ qfvis_SOURCES = \ tools/qfvis/source/base-vis.c \ diff --git a/tools/wad/Makemodule.am b/tools/wad/Makemodule.am index dd68d6842..13fcf3a43 100644 --- a/tools/wad/Makemodule.am +++ b/tools/wad/Makemodule.am @@ -2,7 +2,8 @@ WAD_LIBS=@WAD_LIBS@ WAD_DEPS=@WAD_DEPS@ WAD_INCS=@WAD_INCS@ -bin_PROGRAMS += wad +EXTRA_PROGRAMS += wad +bin_PROGRAMS += @WAD_TARGETS@ man_MANS += tools/wad/wad.1 diff --git a/tools/wav/Makemodule.am b/tools/wav/Makemodule.am index 4a4726809..6eb727ad0 100644 --- a/tools/wav/Makemodule.am +++ b/tools/wav/Makemodule.am @@ -2,7 +2,8 @@ WAV_LIBS=@WAV_LIBS@ WAV_DEPS=@WAV_DEPS@ WAV_INCS=@WAV_INCS@ -bin_PROGRAMS += qfwavinfo +EXTRA_PROGRAMS += qfwavinfo +bin_PROGRAMS += @WAV_TARGETS@ #man_MANS += tools/wav/qfwavinfo.1 From 4cc6e051406a26da3646f460cb2d9afcb74340f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Mar 2021 17:15:22 +0900 Subject: [PATCH 1441/3664] [build] Fix a silly error that got through testing --- config.d/build_control.m4 | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 49e1b368c..74b28afcd 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -27,8 +27,18 @@ QWAQ_TARGETS="" QW_DESKTOP_DATA="" NQ_DESKTOP_DATA="" -PAK_TARGETS -QFCC_TARGETS +BSP2IMG_TARGETS="" +CARNE_TARGETS="" +PAK_TARGETS="" +QFBSP_TARGETS="" +QFCC_TARGETS="" +QFLIGHT_TARGETS="" +QFLMP_TARGETS="" +QFMODELGEN_TARGETS="" +QFSPRITEGEN_TARGETS="" +QFVIS_TARGETS="" +WAD_TARGETS="" +WAV_TARGETS="" CD_TARGETS="" SND_TARGETS="" @@ -277,7 +287,7 @@ if test "x$ENABLE_tools_wad" = xyes; then QF_NEED(libs,[image util]) fi if test "x$ENABLE_tools_wav" = xyes; then - WAV_TARGETS=wav + WAV_TARGETS=qfwavinfo QF_NEED(tools,[wav]) QF_NEED(libs,[util]) fi From 0167456b21444f98a18e155f52fa3ac9cb173832 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 15:04:13 +0900 Subject: [PATCH 1442/3664] [util] Loosen up SEB relative epsilon a little 1e-8 is a little too tight, the normal was 4.5x the computed epsilon. Going to 1e-6 still keeps things tight. --- libs/util/mathlib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 33eae277d..c97fb3b09 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -1352,7 +1352,7 @@ test_support_points(const vec_t **points, int *num_points, const vec3_t center) nn = DotProduct (n, n); dd = DotProduct (d, d); vv = DotProduct (v, v); - in_affine = nn < 1e-8 * vv * dd; + in_affine = nn < 1e-6 * vv * dd; break; case 3: VectorSubtract (points[1], points[0], a); @@ -1362,7 +1362,7 @@ test_support_points(const vec_t **points, int *num_points, const vec3_t center) dn = DotProduct (d, n); dd = DotProduct (d, d); nn = DotProduct (n, n); - in_affine = dn * dn < 1e-8 * dd * nn; + in_affine = dn * dn < 1e-6 * dd * nn; break; case 4: in_affine = 1; @@ -1455,7 +1455,7 @@ SmallestEnclosingBall (const vec3_t points[], int num_points) point_proj = DotProduct (center_to_affine, center_to_point); if (affine_dist - point_proj <= 0 || ((affine_dist - point_proj) * (affine_dist - point_proj) - < 1e-8 * sphere.radius * affine_dist)) + < 1e-6 * sphere.radius * affine_dist)) continue; point_dist = DotProduct (center_to_point, center_to_point); bound = sphere.radius - point_dist; From 7c788a6e7a085de247a312016975d88ba0cbbd74 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 19:08:18 +0900 Subject: [PATCH 1443/3664] [util] Use size_t for dstring length params While not overly wrong, unsigned is not really appropriate. --- include/QF/dstring.h | 32 ++++++++++++++++---------------- libs/util/dstring.c | 38 ++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/include/QF/dstring.h b/include/QF/dstring.h index 937e9be54..5263d6d3d 100644 --- a/include/QF/dstring.h +++ b/include/QF/dstring.h @@ -45,8 +45,8 @@ typedef struct dstring_mem_s { typedef struct dstring_s { dstring_mem_t *mem; - unsigned long int size, truesize; - char *str; + size_t size, truesize; + char *str; } dstring_t; extern dstring_mem_t dstring_default_mem; @@ -72,21 +72,21 @@ void dstring_adjust (dstring_t *dstr); \param len the size of the hole to open. \return pointer to the beginning of the opened hole. */ -char *dstring_reserve (dstring_t *dstr, unsigned len); +char *dstring_reserve (dstring_t *dstr, size_t len); /** Copy len bytes from data into the dstring, replacing any existing data. */ -void dstring_copy (dstring_t *dstr, const char *data, unsigned int len); +void dstring_copy (dstring_t *dstr, const char *data, size_t len); /** Append len bytes from data onto the end of the dstring. */ -void dstring_append (dstring_t *dstr, const char *data, unsigned int len); +void dstring_append (dstring_t *dstr, const char *data, size_t len); /** Insert len bytes from data int the dstring at pos. If pos is past the end of the dstring, equivalent to dstring_append. */ -void dstring_insert (dstring_t *dstr, unsigned int pos, const char *data, - unsigned int len); +void dstring_insert (dstring_t *dstr, size_t pos, const char *data, + size_t len); /** Remove len bytes from the dstring starting at pos. */ -void dstring_snip (dstring_t *dstr, unsigned int pos, unsigned int len); +void dstring_snip (dstring_t *dstr, size_t pos, size_t len); /** Set the size of the dstring to 0 bytes. Does not free the string buffer anticipating reuse. */ @@ -94,8 +94,8 @@ void dstring_clear (dstring_t *dstr); /** Replace rlen bytes in dstring at pos with len bytes from data. Moves trailing bytes as needed. */ -void dstring_replace (dstring_t *dstr, unsigned int pos, unsigned int rlen, - const char *data, unsigned int len); +void dstring_replace (dstring_t *dstr, size_t pos, size_t rlen, + const char *data, size_t len); /** Delete the dstring object retaining the string buffer. The string buffer will be just big enough to hold the data. Does NOT ensure the string is null terminated. @@ -123,7 +123,7 @@ dstring_t *dstring_strdup (const char *str); \return pointer to the current null terminator or beginning of the opened hole if there was no terminator. */ -char *dstring_reservestr (dstring_t *dstr, unsigned len); +char *dstring_reservestr (dstring_t *dstr, size_t len); /** Copy the null terminated string into the dstring. Replaces any existing data. The dstring does not have to be null terminated but will become so. @@ -133,7 +133,7 @@ void dstring_copystr (dstring_t *dstr, const char *str); existing data. The dstring does not have to be null terminated but will become so. */ -void dstring_copysubstr (dstring_t *dstr, const char *str, unsigned int len); +void dstring_copysubstr (dstring_t *dstr, const char *str, size_t len); /** Append the null terminated string to the end of the dstring. The dstring does not have to be null terminated but will become so. However, any embedded nulls will be treated as the end of the dstring. @@ -143,16 +143,16 @@ void dstring_appendstr (dstring_t *dstr, const char *str); The dstring does not have to be null terminated but will become so. However, any embedded nulls will be treated as the end of the dstring. */ -void dstring_appendsubstr (dstring_t *dstr, const char *str, unsigned int len); +void dstring_appendsubstr (dstring_t *dstr, const char *str, size_t len); /** Insert the null terminated string into the dstring at pos. The dstring is NOT forced to be null terminated. */ -void dstring_insertstr (dstring_t *dstr, unsigned int pos, const char *str); +void dstring_insertstr (dstring_t *dstr, size_t pos, const char *str); /** Insert up to len bytes from the string into the dstring at pos. The dstring is NOT forced to be null terminated. */ -void dstring_insertsubstr (dstring_t *dstr, unsigned int pos, const char *str, - unsigned int len); +void dstring_insertsubstr (dstring_t *dstr, size_t pos, const char *str, + size_t len); /** Clear the dstring to be equivalent to "". Does not resize the string buffer but size is set to 1. dstr = dstring_new (); dstring_clearstr (dstr); is exactly equivalent to diff --git a/libs/util/dstring.c b/libs/util/dstring.c index fb495403c..7fbdae1a9 100644 --- a/libs/util/dstring.c +++ b/libs/util/dstring.c @@ -101,7 +101,7 @@ dstring_adjust (dstring_t *dstr) } VISIBLE char * -dstring_reserve (dstring_t *dstr, unsigned len) +dstring_reserve (dstring_t *dstr, size_t len) { dstr->size += len; dstring_adjust (dstr); @@ -109,7 +109,7 @@ dstring_reserve (dstring_t *dstr, unsigned len) } VISIBLE void -dstring_copy (dstring_t *dstr, const char *data, unsigned int len) +dstring_copy (dstring_t *dstr, const char *data, size_t len) { dstr->size = len; dstring_adjust (dstr); @@ -117,9 +117,9 @@ dstring_copy (dstring_t *dstr, const char *data, unsigned int len) } VISIBLE void -dstring_append (dstring_t *dstr, const char *data, unsigned int len) +dstring_append (dstring_t *dstr, const char *data, size_t len) { - unsigned int ins = dstr->size; // Save insertion point + size_t ins = dstr->size; // Save insertion point dstr->size += len; dstring_adjust (dstr); @@ -127,10 +127,9 @@ dstring_append (dstring_t *dstr, const char *data, unsigned int len) } VISIBLE void -dstring_insert (dstring_t *dstr, unsigned int pos, const char *data, - unsigned int len) +dstring_insert (dstring_t *dstr, size_t pos, const char *data, size_t len) { - unsigned int oldsize = dstr->size; + size_t oldsize = dstr->size; if (pos > dstr->size) pos = dstr->size; @@ -141,7 +140,7 @@ dstring_insert (dstring_t *dstr, unsigned int pos, const char *data, } VISIBLE void -dstring_snip (dstring_t *dstr, unsigned int pos, unsigned int len) +dstring_snip (dstring_t *dstr, size_t pos, size_t len) { if (pos > dstr->size) pos = dstr->size; @@ -162,10 +161,10 @@ dstring_clear (dstring_t *dstr) } VISIBLE void -dstring_replace (dstring_t *dstr, unsigned int pos, unsigned int rlen, - const char *data, unsigned int len) +dstring_replace (dstring_t *dstr, size_t pos, size_t rlen, + const char *data, size_t len) { - unsigned int oldsize = dstr->size; + size_t oldsize = dstr->size; if (pos > dstr->size) pos = dstr->size; if (rlen > dstr->size - pos) @@ -223,7 +222,7 @@ dstring_strdup (const char *str) } VISIBLE char * -dstring_reservestr (dstring_t *dstr, unsigned len) +dstring_reservestr (dstring_t *dstr, size_t len) { int pos = dstr->size; if (pos && !dstr->str[pos - 1]) @@ -242,7 +241,7 @@ dstring_copystr (dstring_t *dstr, const char *str) } VISIBLE void -dstring_copysubstr (dstring_t *dstr, const char *str, unsigned int len) +dstring_copysubstr (dstring_t *dstr, const char *str, size_t len) { len = strnlen (str, len); @@ -255,8 +254,8 @@ dstring_copysubstr (dstring_t *dstr, const char *str, unsigned int len) VISIBLE void dstring_appendstr (dstring_t *dstr, const char *str) { - unsigned int pos = strnlen (dstr->str, dstr->size); - unsigned int len = strlen (str); + size_t pos = strnlen (dstr->str, dstr->size); + size_t len = strlen (str); dstr->size = pos + len + 1; dstring_adjust (dstr); @@ -264,9 +263,9 @@ dstring_appendstr (dstring_t *dstr, const char *str) } VISIBLE void -dstring_appendsubstr (dstring_t *dstr, const char *str, unsigned int len) +dstring_appendsubstr (dstring_t *dstr, const char *str, size_t len) { - unsigned int pos = strnlen (dstr->str, dstr->size); + size_t pos = strnlen (dstr->str, dstr->size); len = strnlen (str, len); dstr->size = pos + len + 1; @@ -276,15 +275,14 @@ dstring_appendsubstr (dstring_t *dstr, const char *str, unsigned int len) } VISIBLE void -dstring_insertstr (dstring_t *dstr, unsigned int pos, const char *str) +dstring_insertstr (dstring_t *dstr, size_t pos, const char *str) { // Don't insert strlen + 1 to achieve concatenation dstring_insert (dstr, pos, str, strlen (str)); } VISIBLE void -dstring_insertsubstr (dstring_t *dstr, unsigned int pos, const char *str, - unsigned int len) +dstring_insertsubstr (dstring_t *dstr, size_t pos, const char *str, size_t len) { len = strnlen (str, len); From a9bd4368378a92d1221fc12161a54f1f11f3c757 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 19:52:59 +0900 Subject: [PATCH 1444/3664] [build] Autoconfiscate printf format attribute I don't know if gnu_printf is appropriate for all cases, but it is needed for mingw32. --- config.d/windows.m4 | 13 ++++++++++++- include/QF/cexpr.h | 2 +- include/QF/console.h | 6 +++--- include/QF/dstring.h | 8 ++++---- include/QF/gib.h | 2 +- include/QF/plist.h | 2 +- include/QF/plugin/console.h | 2 +- include/QF/progs.h | 4 ++-- include/QF/quakeio.h | 2 +- include/QF/sys.h | 14 +++++++------- include/QF/va.h | 4 ++-- include/gib_buffer.h | 2 +- include/netchan.h | 4 ++-- include/qstring.h | 2 +- libs/console/client.c | 2 +- libs/console/server.c | 2 +- libs/net/nm/net_dgrm.c | 2 +- libs/util/dstring.c | 2 +- libs/util/sys.c | 4 ++-- libs/video/renderer/vulkan/renderpass.c | 6 +++--- libs/video/renderer/vulkan/test/test-staging.c | 6 +++++- libs/video/targets/keys.c | 2 +- nq/include/host.h | 6 +++--- nq/include/server.h | 4 ++-- nq/source/host_cmd.c | 2 +- qtv/include/qtv.h | 2 +- qtv/source/qtv.c | 2 +- qw/include/host.h | 6 +++--- qw/include/server.h | 14 +++++++------- qw/source/master.c | 4 ++-- qw/source/sv_main.c | 2 +- qw/source/sv_user.c | 2 +- ruamoko/qwaq/builtins/curses.c | 2 +- tools/qfbsp/include/bsp5.h | 2 +- tools/qfbsp/source/map.c | 2 +- tools/qfcc/include/diagnostic.h | 12 ++++++------ tools/qfcc/source/diagnostic.c | 6 +++--- tools/qfcc/source/linker.c | 10 +++++----- 38 files changed, 93 insertions(+), 78 deletions(-) diff --git a/config.d/windows.m4 b/config.d/windows.m4 index cc79255c0..6ed314174 100644 --- a/config.d/windows.m4 +++ b/config.d/windows.m4 @@ -1,5 +1,6 @@ endian="" FNM_FLAGS="" + case "$host_os" in mingw32*) mingw=yes @@ -7,11 +8,12 @@ case "$host_os" in if test "x$host" != "x$build"; then case "$build_os" in cygwin*) - CFLAGS="$CFLAGS -mno-cygwin -mconsole" + CFLAGS="$CFLAGS -mno-cygwin -mconsole -D__USE_MINGW_ANSI_STDIO" CPPFLAGS="$CPPFLAGS $CFLAGS" ;; esac fi + AC_DEFINE(NEED_GNUPRINTF) endian="little" ;; cygwin*) @@ -26,3 +28,12 @@ case "$host_os" in ;; esac AC_SUBST(FNM_FLAGS) + +AH_VERBATIM([NEED_GNUPRINTF], +[/* Define this if gnu_prinf is needed instead of printf for format attributes*/ +#undef NEED_GNUPRINTF +#ifdef NEED_GNUPRINTF +# define PRINTF gnu_printf +#else +# define PRINTF printf +#endif]) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 9a79690a6..7fa1e04fc 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -109,7 +109,7 @@ binop_t *cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) __attribut exprval_t *cexpr_value (exprtype_t *type, exprctx_t *ctx); exprval_t *cexpr_value_reference (exprtype_t *type, void *data, exprctx_t *ctx); int cexpr_eval_string (const char *str, exprctx_t *context); -void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(printf,2,3))); +void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); void cexpr_struct_getfield (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx); diff --git a/include/QF/console.h b/include/QF/console.h index f885404fa..8bae248e9 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -92,8 +92,8 @@ extern struct console_data_s con_data; void Con_CheckResize (void); void Con_DrawConsole (void); -void Con_Printf (const char *fmt, ...) __attribute__((format(printf, 1, 2))); -void Con_Print (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); +void Con_Printf (const char *fmt, ...) __attribute__((format(PRINTF, 1, 2))); +void Con_Print (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); void Con_ToggleConsole_f (void); // wrapper function to attempt to either complete the command line @@ -105,7 +105,7 @@ void Con_BasicCompleteCommandLine (inputline_t *il); // Generic libs/util/console.c function to display a list // formatted in columns on the console void Con_DisplayList(const char **list, int con_linewidth); -extern void (*con_list_print)(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +extern void (*con_list_print)(const char *fmt, ...) __attribute__((format(PRINTF, 1, 2))); inputline_t *Con_CreateInputLine (int lines, int lsize, char prompt); void Con_DestroyInputLine (inputline_t *inputline); diff --git a/include/QF/dstring.h b/include/QF/dstring.h index 5263d6d3d..b3aa32c0a 100644 --- a/include/QF/dstring.h +++ b/include/QF/dstring.h @@ -164,15 +164,15 @@ void dstring_clearstr (dstring_t *dstr); /** Formatted printing to dstrings. Existing data is replaced by the formatted string. */ -char *dvsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); -char *dsprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); +char *dvsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(PRINTF,2,0))); +char *dsprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); ///@} ///@{ /** Formatted printing to dstrings. Formatted string is appened to the dstring. Embedded nulls in the dstring are ignored. */ -char *davsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(printf,2,0))); -char *dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(printf,2,3))); +char *davsprintf (dstring_t *dstr, const char *fmt, va_list args) __attribute__((format(PRINTF,2,0))); +char *dasprintf (dstring_t *dstr, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); ///@} ///@} diff --git a/include/QF/gib.h b/include/QF/gib.h index 09bcf01ad..018eabedd 100644 --- a/include/QF/gib.h +++ b/include/QF/gib.h @@ -182,7 +182,7 @@ extern char * const gib_null_string; #define GIB_CanReturn() (GIB_DATA(cbuf_active)->waitret) dstring_t *GIB_Return (const char *str); -void GIB_Error (const char *type, const char *fmt, ...) __attribute__((format(printf, 2, 3))); +void GIB_Error (const char *type, const char *fmt, ...) __attribute__((format(PRINTF, 2, 3))); void GIB_Builtin_Add (const char *name, void (*func) (void)); void GIB_Builtin_Remove (const char *name); qboolean GIB_Builtin_Exists (const char *name); diff --git a/include/QF/plist.h b/include/QF/plist.h index b14b5e4aa..f2db67193 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -500,7 +500,7 @@ int PL_ParseLabeledArray (const plfield_t *field, const plitem_t *dict, */ int PL_ParseSymtab (const plfield_t *field, const plitem_t *dict, void *data, plitem_t *messages, void *context); -void __attribute__((format(printf,3,4))) +void __attribute__((format(PRINTF,3,4))) PL_Message (plitem_t *messages, const plitem_t *item, const char *fmt, ...); ///@} diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index b404728e3..d7beec399 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -34,7 +34,7 @@ #include #include -typedef void (*P_C_Print) (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); +typedef void (*P_C_Print) (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); typedef void (*P_C_ProcessInput) (void); typedef void (*P_C_KeyEvent) (knum_t key, short unicode, qboolean down); typedef void (*P_C_DrawConsole) (void); diff --git a/include/QF/progs.h b/include/QF/progs.h index b6ced5935..fd36c0c62 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -64,8 +64,8 @@ void PR_Init (progs_t *pr); */ void PR_Init_Cvars (void); -void PR_Error (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3), noreturn)); -void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(printf,2,3), noreturn)); +void PR_Error (progs_t *pr, const char *error, ...) __attribute__((format(PRINTF,2,3), noreturn)); +void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(PRINTF,2,3), noreturn)); ///@} diff --git a/include/QF/quakeio.h b/include/QF/quakeio.h index 1fd7205a0..788b7ee7b 100644 --- a/include/QF/quakeio.h +++ b/include/QF/quakeio.h @@ -48,7 +48,7 @@ QFile *Qsubopen (const char *path, int offs, int len, int zip); void Qclose(QFile *file); int Qread(QFile *file, void *buf, int count); int Qwrite(QFile *file, const void *buf, int count); -int Qprintf(QFile *file, const char *fmt, ...) __attribute__((format(printf,2,3))); +int Qprintf(QFile *file, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); int Qputs(QFile *file, const char *buf); char *Qgets(QFile *file, char *buf, int count); int Qgetc(QFile *file); diff --git a/include/QF/sys.h b/include/QF/sys.h index e54031af2..735fe1ca1 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -62,7 +62,7 @@ int Sys_FileExists (const char *path); int Sys_isdir (const char *path); int Sys_mkdir (const char *path); -typedef void (*sys_printf_t) (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); +typedef void (*sys_printf_t) (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); typedef void (*sys_error_t) (void *data); sys_printf_t Sys_SetStdPrintf (sys_printf_t func); @@ -71,10 +71,10 @@ sys_printf_t Sys_SetErrPrintf (sys_printf_t func); void Sys_PushErrorHandler (sys_error_t func, void *data); void Sys_PopErrorHandler (void); -void Sys_Print (FILE *stream, const char *fmt, va_list args) __attribute__((format(printf, 2, 0))); -void Sys_Printf (const char *fmt, ...) __attribute__((format(printf,1,2))); -void Sys_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); -void Sys_FatalError (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); +void Sys_Print (FILE *stream, const char *fmt, va_list args) __attribute__((format(PRINTF, 2, 0))); +void Sys_Printf (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); +void Sys_Error (const char *error, ...) __attribute__((format(PRINTF,1,2), noreturn)); +void Sys_FatalError (const char *error, ...) __attribute__((format(PRINTF,1,2), noreturn)); void Sys_Quit (void) __attribute__((noreturn)); void Sys_Shutdown (void); void Sys_RegisterShutdown (void (*func) (void *), void *data); @@ -82,7 +82,7 @@ int64_t Sys_LongTime (void); double Sys_DoubleTime (void); void Sys_TimeOfDay(date_t *date); -void Sys_MaskPrintf (int mask, const char *fmt, ...) __attribute__((format(printf,2,3))); +void Sys_MaskPrintf (int mask, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); // remember to update developer_flags in cvar.c #define SYS_DEV (1|0) #define SYS_WARN (1|2) // bit 0 so developer 1 will pick it up @@ -129,7 +129,7 @@ void *Sys_Alloc (size_t size); // // system IO // -void Sys_DebugLog(const char *file, const char *fmt, ...) __attribute__((format(printf,2,3))); +void Sys_DebugLog(const char *file, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); #define SYS_CHECKMEM(x) \ do { \ diff --git a/include/QF/va.h b/include/QF/va.h index 74a28aba7..cc123cde3 100644 --- a/include/QF/va.h +++ b/include/QF/va.h @@ -73,7 +73,7 @@ void va_destroy_context (va_ctx_t *ctx); * to va sent to a 4th) with a reduced risk of strings being * trampled. */ -char *va(va_ctx_t *ctx, const char *format, ...) __attribute__((format(printf,2,3))); +char *va(va_ctx_t *ctx, const char *format, ...) __attribute__((format(PRINTF,2,3))); /** Does a varargs printf into a malloced buffer. * @@ -88,7 +88,7 @@ char *va(va_ctx_t *ctx, const char *format, ...) __attribute__((format(printf,2, * trampled. In addition, it does not use va(), so combining * nva() with va() is safe. */ -char *nva(const char *format, ...) __attribute__((format(printf,1,2))); +char *nva(const char *format, ...) __attribute__((format(PRINTF,1,2))); ///@} diff --git a/include/gib_buffer.h b/include/gib_buffer.h index b0e9219d2..d8be90b45 100644 --- a/include/gib_buffer.h +++ b/include/gib_buffer.h @@ -40,7 +40,7 @@ void GIB_Buffer_Push_Sstack (struct cbuf_s *cbuf); void GIB_Buffer_Pop_Sstack (struct cbuf_s *cbuf); dstring_t *GIB_Buffer_Dsarray_Get (struct cbuf_s *cbuf); void GIB_Buffer_Reply_Callback (int argc, const char **argv, void *data); -void GIB_Buffer_Error (cbuf_t *cbuf, const char *type, const char *fmt, va_list args) __attribute__((format(printf, 3, 0))); +void GIB_Buffer_Error (cbuf_t *cbuf, const char *type, const char *fmt, va_list args) __attribute__((format(PRINTF, 3, 0))); extern struct cbuf_interpreter_s gib_interp; diff --git a/include/netchan.h b/include/netchan.h index 207ed78fe..6197cc8db 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -65,7 +65,7 @@ extern struct msg_s *net_message; extern struct cvar_s *qport; int Net_Log_Init (const char **sound_precache); -void Net_LogPrintf (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +void Net_LogPrintf (const char *fmt, ...) __attribute__ ((format (PRINTF, 1, 2))); void Log_Incoming_Packet (const byte *p, int len, int has_sequence, int is_server); void Log_Outgoing_Packet (const byte *p, int len, int has_sequence, @@ -332,7 +332,7 @@ void Netchan_OutOfBand (netadr_t adr, int length, byte *data); \param format The printf style format string. */ void Netchan_OutOfBandPrint (netadr_t adr, const char *format, ...) - __attribute__ ((format (printf,2,3))); + __attribute__ ((format (PRINTF,2,3))); /** Process a packet for the specifiied connection. diff --git a/include/qstring.h b/include/qstring.h index 55b7ff30d..fa6dd9361 100644 --- a/include/qstring.h +++ b/include/qstring.h @@ -33,7 +33,7 @@ const char * Q_strcasestr (const char *haystack, const char *needle) __attribute__((pure)); size_t Q_strnlen (const char *s, size_t maxlen) __attribute__((pure)); -size_t Q_snprintfz (char *dest, size_t size, const char *fmt, ...) __attribute__((format(printf,3,4))); +size_t Q_snprintfz (char *dest, size_t size, const char *fmt, ...) __attribute__((format(PRINTF,3,4))); size_t Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list argptr); #endif // string_h diff --git a/libs/console/client.c b/libs/console/client.c index 3370a7614..b694b493c 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -360,7 +360,7 @@ Linefeed (void) All console printing must go through this in order to be logged to disk If no console is visible, the notify window will pop up. */ -static __attribute__((format(printf, 1, 0))) void +static __attribute__((format(PRINTF, 1, 0))) void C_Print (const char *fmt, va_list args) { char *s; diff --git a/libs/console/server.c b/libs/console/server.c index 3a0d3f035..201842d27 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -711,7 +711,7 @@ C_shutdown (void) #endif } -static __attribute__((format(printf, 1, 0))) void +static __attribute__((format(PRINTF, 1, 0))) void C_Print (const char *fmt, va_list args) { static dstring_t *buffer; diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 20160e228..f69b246b6 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -104,7 +104,7 @@ NET_Ban_f (void) { char addrStr[32]; //FIXME: overflow char maskStr[32]; //FIXME: overflow - __attribute__((format(printf, 1, 2))) void (*print) (const char *fmt, ...); + __attribute__((format(PRINTF, 1, 2))) void (*print) (const char *fmt, ...); if (cmd_source == src_command) { if (!sv.active) { diff --git a/libs/util/dstring.c b/libs/util/dstring.c index 7fbdae1a9..035a5a42e 100644 --- a/libs/util/dstring.c +++ b/libs/util/dstring.c @@ -297,7 +297,7 @@ dstring_clearstr (dstring_t *dstr) dstr->str[0] = 0; } -static __attribute__((format(printf, 3, 0))) char * +static __attribute__((format(PRINTF, 3, 0))) char * _dvsprintf (dstring_t *dstr, int offs, const char *fmt, va_list args) { int size; diff --git a/libs/util/sys.c b/libs/util/sys.c index db0777f07..6e36c4545 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -90,8 +90,8 @@ #include "compat.h" -static void Sys_StdPrintf (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); -static void Sys_ErrPrintf (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); +static void Sys_StdPrintf (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); +static void Sys_ErrPrintf (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); VISIBLE cvar_t *sys_nostdout; VISIBLE cvar_t *sys_extrasleep; diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 4970b050b..16939b29e 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -72,7 +72,7 @@ QFV_CreateRenderPass (qfv_device_t *device, qfv_devfuncs_t *dfunc = device->funcs; if (developer->int_val & SYS_VULKAN) { - Sys_Printf ("attachments: %ld\n", attachments->size); + Sys_Printf ("attachments: %zd\n", attachments->size); for (size_t i = 0; i < attachments->size; i++) { Sys_Printf (" attachment: %zd\n", i); Sys_Printf (" flags: %x\n", attachments->a[i].flags); @@ -89,7 +89,7 @@ QFV_CreateRenderPass (qfv_device_t *device, Sys_Printf (" finalLayout: %d\n", attachments->a[i].finalLayout); } - Sys_Printf ("subpassparams: %ld\n", subpassparams->size); + Sys_Printf ("subpassparams: %zd\n", subpassparams->size); for (size_t i = 0; i < subpassparams->size; i++) { VkSubpassDescription *sp = &subpassparams->a[i]; Sys_Printf (" flags: %x\n", sp->flags); @@ -126,7 +126,7 @@ QFV_CreateRenderPass (qfv_device_t *device, Sys_Printf (" %d\n", sp->pPreserveAttachments[j]); } } - Sys_Printf ("dependencies: %ld\n", dependencies->size); + Sys_Printf ("dependencies: %zd\n", dependencies->size); for (size_t i = 0; i < dependencies->size; i++) { Sys_Printf (" srcSubpass: %d\n", dependencies->a[i].srcSubpass); Sys_Printf (" dstSubpass: %d\n", dependencies->a[i].dstSubpass); diff --git a/libs/video/renderer/vulkan/test/test-staging.c b/libs/video/renderer/vulkan/test/test-staging.c index fcfa4b8a9..df0b7e282 100644 --- a/libs/video/renderer/vulkan/test/test-staging.c +++ b/libs/video/renderer/vulkan/test/test-staging.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include @@ -162,7 +166,7 @@ qfv_device_t device = { funcs:&dfuncs, }; -static void __attribute__ ((format (printf, 2, 3), noreturn)) +static void __attribute__ ((format (PRINTF, 2, 3), noreturn)) _error (int line, const char *fmt, ...) { va_list args; diff --git a/libs/video/targets/keys.c b/libs/video/targets/keys.c index 92ee71fc0..7e844fb9e 100644 --- a/libs/video/targets/keys.c +++ b/libs/video/targets/keys.c @@ -1086,7 +1086,7 @@ Key_IMT_Keydest_f (void) key_targets[kd].active = imt; } -static void __attribute__((format(printf,2,3))) +static void __attribute__((format(PRINTF,2,3))) key_printf (QFile *f, const char *fmt, ...) { va_list args; diff --git a/nq/include/host.h b/nq/include/host.h index 9300abbfe..8a6ab52c9 100644 --- a/nq/include/host.h +++ b/nq/include/host.h @@ -62,11 +62,11 @@ void Host_ServerFrame (void); void Host_InitCommands (void); void Host_Init (void); void Host_Shutdown(void *data); -void Host_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); -void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2), noreturn)); +void Host_Error (const char *error, ...) __attribute__((format(PRINTF,1,2), noreturn)); +void Host_EndGame (const char *message, ...) __attribute__((format(PRINTF,1,2), noreturn)); void Host_Frame (float time); void Host_Quit_f (void) __attribute__((noreturn)); -void Host_ClientCommands (const char *fmt, ...) __attribute__((format(printf,1,2))); +void Host_ClientCommands (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); void Host_ShutdownServer (qboolean crash); #endif // __host_h diff --git a/nq/include/server.h b/nq/include/server.h index 4960fee5c..7e78394ce 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -264,8 +264,8 @@ void SV_AddUpdates (void); void SV_ClientThink (void); void SV_AddClientToServer (struct qsocket_s *ret); -void SV_ClientPrintf (const char *fmt, ...) __attribute__((format(printf,1,2))); -void SV_BroadcastPrintf (const char *fmt, ...) __attribute__((format(printf,1,2))); +void SV_ClientPrintf (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); +void SV_BroadcastPrintf (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); struct trace_s SV_PushEntity (edict_t *ent, vec3_t push); int SV_EntCanSupportJump (edict_t *ent) __attribute__((pure)); diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 2a579032c..ef98f27da 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -79,7 +79,7 @@ Host_Status_f (void) int minutes; int hours = 0; int j; - __attribute__((format(printf, 1, 2))) void (*print) (const char *fmt, ...); + __attribute__((format(PRINTF, 1, 2))) void (*print) (const char *fmt, ...); if (cmd_source == src_command) { if (!sv.active) { diff --git a/qtv/include/qtv.h b/qtv/include/qtv.h index 732febfb3..f8d0918f3 100644 --- a/qtv/include/qtv.h +++ b/qtv/include/qtv.h @@ -65,7 +65,7 @@ struct client_s; Calling qtv_begin_redirect() before, and qtv_end_redirect() after a series of calls will redirect output. */ -void qtv_printf (const char *fmt, ...) __attribute__((format(printf,1,2))); +void qtv_printf (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); /** Begin redirection of console printing. diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 049f0a568..0348198f8 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -88,7 +88,7 @@ redirect_t qtv_redirected; client_t *qtv_redirect_client; dstring_t outputbuf = {&dstring_default_mem}; -static __attribute__((format(printf, 1, 0))) void +static __attribute__((format(PRINTF, 1, 0))) void qtv_print (const char *fmt, va_list args) { static int pending; diff --git a/qw/include/host.h b/qw/include/host.h index 27ad77325..d7a290284 100644 --- a/qw/include/host.h +++ b/qw/include/host.h @@ -51,11 +51,11 @@ void Host_ServerFrame (void); void Host_InitCommands (void); void Host_Init (void); void Host_Shutdown(void *data); -void Host_Error (const char *error, ...) __attribute__((format(printf,1,2), noreturn)); -void Host_EndGame (const char *message, ...) __attribute__((format(printf,1,2), noreturn)); +void Host_Error (const char *error, ...) __attribute__((format(PRINTF,1,2), noreturn)); +void Host_EndGame (const char *message, ...) __attribute__((format(PRINTF,1,2), noreturn)); void Host_Frame (float time); void Host_Quit_f (void); -void Host_ClientCommands (const char *fmt, ...) __attribute__((format(printf,1,2))); +void Host_ClientCommands (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); void Host_ShutdownServer (qboolean crash); typedef struct diff --git a/qw/include/server.h b/qw/include/server.h index b32a46c63..f91b0dfb5 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -474,8 +474,8 @@ void SV_Progs_Init_Cvars (void); void SV_PR_Cmds_Init (void); void SV_LoadProgs (void); -void Con_Printf (const char *fmt, ...) __attribute__((format(printf,1,2))); -void Con_DPrintf (const char *fmt, ...) __attribute__((format(printf,1,2))); +void Con_Printf (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); +void Con_DPrintf (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); extern struct clip_hull_s *pf_hull_list[]; @@ -554,17 +554,17 @@ int SV_EntCanSupportJump (struct edict_s *ent) __attribute__((pure)); // // sv_send.c // -void SV_Print (const char *fmt, va_list args) __attribute__((format(printf, 1, 0))); -void SV_Printf (const char *fmt, ...) __attribute__((format(printf,1,2))); +void SV_Print (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); +void SV_Printf (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); void SV_SendClientMessages (void); void SV_GetStats (struct edict_s *ent, int spectator, int stats[]); void SV_Multicast (const vec3_t origin, int to); void SV_StartSound (struct edict_s *entity, int channel, const char *sample, int volume, float attenuation); -void SV_ClientPrintf (int recorder, client_t *cl, int level, const char *fmt, ...) __attribute__((format(printf,4,5))); -void SV_BroadcastPrintf (int level, const char *fmt, ...) __attribute__((format(printf,2,3))); -void SV_BroadcastCommand (const char *fmt, ...) __attribute__((format(printf,1,2))); +void SV_ClientPrintf (int recorder, client_t *cl, int level, const char *fmt, ...) __attribute__((format(PRINTF,4,5))); +void SV_BroadcastPrintf (int level, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); +void SV_BroadcastCommand (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); void SV_SendMessagesToAll (void); void SV_FindModelNumbers (void); diff --git a/qw/source/master.c b/qw/source/master.c index 91347ff0a..f8da82e2b 100644 --- a/qw/source/master.c +++ b/qw/source/master.c @@ -76,7 +76,7 @@ # endif #endif -static void __attribute__ ((format (printf, 1, 2))) +static void __attribute__ ((format (PRINTF, 1, 2))) ma_log (const char *fmt, ...); #ifdef HAVE_IN_PKTINFO @@ -514,7 +514,7 @@ main (int argc, char **argv) return 0; } -static void __attribute__ ((format (printf, 1, 2))) +static void __attribute__ ((format (PRINTF, 1, 2))) ma_log (const char *fmt, ...) { va_list args; diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index d91a24832..039aad1fe 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -255,7 +255,7 @@ SV_Shutdown (void *data) Sends a datagram to all the clients informing them of the server crash, then exits */ -static __attribute__((format(printf, 1, 0))) void +static __attribute__((format(PRINTF, 1, 0))) void SV_Error (const char *error, va_list argptr) { static qboolean inerror = false; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 5b3c9f14f..4ad70cf99 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -109,7 +109,7 @@ cvar_t *sv_timecheck_decay; cvar_t *sv_http_url_base; -static void OutofBandPrintf (netadr_t where, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); +static void OutofBandPrintf (netadr_t where, const char *fmt, ...) __attribute__ ((format (PRINTF, 2, 3))); // USER STRINGCMD EXECUTION host_client and sv_player will be valid. diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index cf4f1ebe3..7da55d4e2 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -2004,7 +2004,7 @@ static builtin_t builtins[] = { static FILE *logfile; -static __attribute__((format(printf, 1, 0))) void +static __attribute__((format(PRINTF, 1, 0))) void qwaq_print (const char *fmt, va_list args) { vfprintf (logfile, fmt, args); diff --git a/tools/qfbsp/include/bsp5.h b/tools/qfbsp/include/bsp5.h index b949cf77c..eb05890cb 100644 --- a/tools/qfbsp/include/bsp5.h +++ b/tools/qfbsp/include/bsp5.h @@ -111,7 +111,7 @@ extern struct brushset_s *brushset; Behaves the same as printf except it prints only when verbose is true. */ -void qprintf (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +void qprintf (const char *fmt, ...) __attribute__ ((format (PRINTF, 1, 2))); extern int valid; diff --git a/tools/qfbsp/source/map.c b/tools/qfbsp/source/map.c index 870fb7c07..63fe1bb06 100644 --- a/tools/qfbsp/source/map.c +++ b/tools/qfbsp/source/map.c @@ -64,7 +64,7 @@ int numdetailbrushes; script_t *map_script; -static void __attribute__ ((format (printf, 1, 2), noreturn)) +static void __attribute__ ((format (PRINTF, 1, 2), noreturn)) map_error (const char *fmt, ...) { va_list args; diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index 3a19c9722..100c0f535 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -46,31 +46,31 @@ extern diagnostic_hook notice_hook; struct expr_s *_error (struct expr_s *e, const char *file, int line, const char *fmt, ...) - __attribute__ ((format (printf, 4, 5))); + __attribute__ ((format (PRINTF, 4, 5))); #define error(e, fmt...) _error(e, __FILE__, __LINE__, fmt) void _internal_error (struct expr_s *e, const char *file, int line, const char *fmt, ...) - __attribute__ ((format (printf, 4, 5), noreturn)); + __attribute__ ((format (PRINTF, 4, 5), noreturn)); #define internal_error(e, fmt...) _internal_error(e, __FILE__, __LINE__, fmt) struct expr_s *_warning (struct expr_s *e, const char *file, int line, const char *fmt, ...) - __attribute__ ((format (printf, 4, 5))); + __attribute__ ((format (PRINTF, 4, 5))); #define warning(e, fmt...) _warning(e, __FILE__, __LINE__, fmt) struct expr_s *_notice (struct expr_s *e, const char *file, int line, const char *fmt, ...) - __attribute__ ((format (printf, 4, 5))); + __attribute__ ((format (PRINTF, 4, 5))); #define notice(e, fmt...) _notice(e, __FILE__, __LINE__, fmt) void _debug (struct expr_s *e, const char *file, int line, const char *fmt, ...) - __attribute__ ((format (printf, 4, 5))); + __attribute__ ((format (PRINTF, 4, 5))); #define debug(e, fmt...) _debug(e, __FILE__, __LINE__, fmt) void _bug (struct expr_s *e, const char *file, int line, const char *fmt, ...) - __attribute__ ((format (printf, 4, 5))); + __attribute__ ((format (PRINTF, 4, 5))); #define bug(e, fmt...) _bug(e, __FILE__, __LINE__, fmt) ///@} diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index d7f9fa1fb..d9f18d507 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -77,7 +77,7 @@ report_function (expr_t *e) last_func = current_func; } -static __attribute__((format(printf, 4, 0))) void +static __attribute__((format(PRINTF, 4, 0))) void format_message (dstring_t *message, const char *msg_type, expr_t *e, const char *fmt, va_list args) { @@ -95,7 +95,7 @@ format_message (dstring_t *message, const char *msg_type, expr_t *e, } } -static __attribute__((format(printf, 4, 0))) void +static __attribute__((format(PRINTF, 4, 0))) void __warning (expr_t *e, const char *file, int line, const char *fmt, va_list args) { @@ -146,7 +146,7 @@ _debug (expr_t *e, const char *file, int line, const char *fmt, ...) va_end (args); } -static __attribute__((noreturn, format(printf, 4, 0))) void +static __attribute__((noreturn, format(PRINTF, 4, 0))) void __internal_error (expr_t *e, const char *file, int line, const char *fmt, va_list args) { diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index eb5aeb2bb..502283fb5 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -75,15 +75,15 @@ #include "tools/qfcc/include/type.h" static void linker_internal_error (const char *fmt, ...) - __attribute__ ((format (printf, 1, 2), noreturn)); + __attribute__ ((format (PRINTF, 1, 2), noreturn)); static void linker_error (const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); + __attribute__ ((format (PRINTF, 1, 2))); static void linker_warning (const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); + __attribute__ ((format (PRINTF, 1, 2))); static void def_error (qfo_def_t *def, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); + __attribute__ ((format (PRINTF, 2, 3))); static void def_warning (qfo_def_t *def, const char *fmt, ...) - __attribute__ ((used, format (printf, 2, 3))); + __attribute__ ((used, format (PRINTF, 2, 3))); /** Safe handling of defs in hash tables and other containers. From 5b1ee0e6f62af2525236561a8b4770d8a34dd81b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 19:55:43 +0900 Subject: [PATCH 1445/3664] [vulkan] Fix an inappropriate cast I'm surprised that worked at all (and more surprised it got past linux gcc). --- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 12b3cd11b..879c79aba 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -218,7 +218,7 @@ flush_draw_scrap (vulkan_ctx_t *ctx) static void pic_free (drawctx_t *dctx, qpic_t *pic) { - subpic_t *subpic = *(subpic_t **) pic->data; + subpic_t *subpic = *(subpic_t **) &pic->data[0]; QFV_SubpicDelete (subpic); cmemfree (dctx->pic_memsuper, pic); } From 99f0cde080273146024485bbdb67e6ca10d55285 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 20:00:46 +0900 Subject: [PATCH 1446/3664] [util] Add strndup and reentrant quicksort Needed for portability. --- include/compat.h | 17 +++ include/qstring.h | 1 + include/quicksort.h | 38 ++++++ libs/util/Makemodule.am | 1 + libs/util/qsort_r.c | 250 ++++++++++++++++++++++++++++++++++++++++ libs/util/string.c | 11 ++ 6 files changed, 318 insertions(+) create mode 100644 include/quicksort.h create mode 100644 libs/util/qsort_r.c diff --git a/include/compat.h b/include/compat.h index a3b8cab92..dc36b6745 100644 --- a/include/compat.h +++ b/include/compat.h @@ -94,9 +94,26 @@ size_t strnlen (const char *str, size_t len); # define strnlen Q_strnlen # define need_qstring_h #endif +#ifdef HAVE_STRNDUP +# ifndef HAVE_STRNDUP_PROTO +size_t strndup (const char *str, size_t len); +# endif +#else +# define strndup Q_strndup +# define need_qstring_h +#endif #ifdef need_qstring_h # include "qstring.h" #endif +#ifndef HAVE_QSORT_R +# include "quicksort.h" +# define qsort_r _quicksort +#endif + +#ifndef HAVE_STRERROR_R +#define strerror_r(err,buf,len) strerror_s (buf, len, err) +#endif + #endif // __compat_h diff --git a/include/qstring.h b/include/qstring.h index fa6dd9361..d91503075 100644 --- a/include/qstring.h +++ b/include/qstring.h @@ -33,6 +33,7 @@ const char * Q_strcasestr (const char *haystack, const char *needle) __attribute__((pure)); size_t Q_strnlen (const char *s, size_t maxlen) __attribute__((pure)); +char *Q_strndup (const char *s, size_t maxlen); size_t Q_snprintfz (char *dest, size_t size, const char *fmt, ...) __attribute__((format(PRINTF,3,4))); size_t Q_vsnprintfz (char *dest, size_t size, const char *fmt, va_list argptr); diff --git a/include/quicksort.h b/include/quicksort.h new file mode 100644 index 000000000..6d7743f3d --- /dev/null +++ b/include/quicksort.h @@ -0,0 +1,38 @@ +/* + quicksort.h + + Reentrant qsort for systems that don't have it + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef quicksort_h +#define quicksort_h + +#include + +typedef int (*__compar_d_fn_t)(const void *, const void *, void *); + +void _quicksort(void *base, size_t nmemb, size_t size, __compar_d_fn_t cmp, + void *arg); + +#endif// quicksort_h diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am index 95ce152b9..6b2d0162c 100644 --- a/libs/util/Makemodule.am +++ b/libs/util/Makemodule.am @@ -68,6 +68,7 @@ libs_util_libQFutil_la_SOURCES= \ libs/util/plugin.c \ libs/util/qargs.c \ libs/util/qendian.c \ + libs/util/qsort_r.c \ libs/util/quakefs.c \ libs/util/quakeio.c \ libs/util/riff.c \ diff --git a/libs/util/qsort_r.c b/libs/util/qsort_r.c new file mode 100644 index 000000000..6fbb0297f --- /dev/null +++ b/libs/util/qsort_r.c @@ -0,0 +1,250 @@ +/* Copyright (C) 1991-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Douglas C. Schmidt (schmidt@ics.uci.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* If you consider tuning this algorithm, you should consult first: + Engineering a sort function; Jon Bentley and M. Douglas McIlroy; + Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */ + +#include +#include + +#include "qfalloca.h" +#include "quicksort.h" + +/* Byte-wise swap two items of size SIZE. */ +#define SWAP(a, b, size) \ + do \ + { \ + size_t __size = (size); \ + char *__a = (a), *__b = (b); \ + do \ + { \ + char __tmp = *__a; \ + *__a++ = *__b; \ + *__b++ = __tmp; \ + } while (--__size > 0); \ + } while (0) + +/* Discontinue quicksort algorithm when partition gets below this size. + This particular magic number was chosen to work best on a Sun 4/260. */ +#define MAX_THRESH 4 + +/* Stack node declarations used to store unfulfilled partition obligations. */ +typedef struct + { + char *lo; + char *hi; + } stack_node; + +/* The next 4 #defines implement a very fast in-line stack abstraction. */ +/* The stack needs log (total_elements) entries (we could even subtract + log(MAX_THRESH)). Since total_elements has type size_t, we get as + upper bound for log (total_elements): + bits per byte (CHAR_BIT) * sizeof(size_t). */ +#define STACK_SIZE (CHAR_BIT * sizeof(size_t)) +#define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top)) +#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi))) +#define STACK_NOT_EMPTY (stack < top) + + +/* Order size using quicksort. This implementation incorporates + four optimizations discussed in Sedgewick: + + 1. Non-recursive, using an explicit stack of pointer that store the + next array partition to sort. To save time, this maximum amount + of space required to store an array of SIZE_MAX is allocated on the + stack. Assuming a 32-bit (64 bit) integer for size_t, this needs + only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). + Pretty cheap, actually. + + 2. Chose the pivot element using a median-of-three decision tree. + This reduces the probability of selecting a bad pivot value and + eliminates certain extraneous comparisons. + + 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving + insertion sort to order the MAX_THRESH items within each partition. + This is a big win, since insertion sort is faster for small, mostly + sorted array segments. + + 4. The larger of the two sub-partitions is always pushed onto the + stack first, with the algorithm then concentrating on the + smaller partition. This *guarantees* no more than log (total_elems) + stack size is needed (actually O(1) in this case)! */ + +void +_quicksort (void *const pbase, size_t total_elems, size_t size, + __compar_d_fn_t cmp, void *arg) +{ + char *base_ptr = (char *) pbase; + + const size_t max_thresh = MAX_THRESH * size; + + if (total_elems == 0) + /* Avoid lossage with unsigned arithmetic below. */ + return; + + if (total_elems > MAX_THRESH) + { + char *lo = base_ptr; + char *hi = &lo[size * (total_elems - 1)]; + stack_node stack[STACK_SIZE]; + stack_node *top = stack; + + PUSH (NULL, NULL); + + while (STACK_NOT_EMPTY) + { + char *left_ptr; + char *right_ptr; + + /* Select median value from among LO, MID, and HI. Rearrange + LO and HI so the three values are sorted. This lowers the + probability of picking a pathological pivot value and + skips a comparison for both the LEFT_PTR and RIGHT_PTR in + the while loops. */ + + char *mid = lo + size * ((hi - lo) / size >> 1); + + if ((*cmp) ((void *) mid, (void *) lo, arg) < 0) + SWAP (mid, lo, size); + if ((*cmp) ((void *) hi, (void *) mid, arg) < 0) + SWAP (mid, hi, size); + else + goto jump_over; + if ((*cmp) ((void *) mid, (void *) lo, arg) < 0) + SWAP (mid, lo, size); + jump_over:; + + left_ptr = lo + size; + right_ptr = hi - size; + + /* Here's the famous ``collapse the walls'' section of quicksort. + Gotta like those tight inner loops! They are the main reason + that this algorithm runs much faster than others. */ + do + { + while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0) + left_ptr += size; + + while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0) + right_ptr -= size; + + if (left_ptr < right_ptr) + { + SWAP (left_ptr, right_ptr, size); + if (mid == left_ptr) + mid = right_ptr; + else if (mid == right_ptr) + mid = left_ptr; + left_ptr += size; + right_ptr -= size; + } + else if (left_ptr == right_ptr) + { + left_ptr += size; + right_ptr -= size; + break; + } + } + while (left_ptr <= right_ptr); + + /* Set up pointers for next iteration. First determine whether + left and right partitions are below the threshold size. If so, + ignore one or both. Otherwise, push the larger partition's + bounds on the stack and continue sorting the smaller one. */ + + if ((size_t) (right_ptr - lo) <= max_thresh) + { + if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore both small partitions. */ + POP (lo, hi); + else + /* Ignore small left partition. */ + lo = left_ptr; + } + else if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore small right partition. */ + hi = right_ptr; + else if ((right_ptr - lo) > (hi - left_ptr)) + { + /* Push larger left partition indices. */ + PUSH (lo, right_ptr); + lo = left_ptr; + } + else + { + /* Push larger right partition indices. */ + PUSH (left_ptr, hi); + hi = right_ptr; + } + } + } + + /* Once the BASE_PTR array is partially sorted by quicksort the rest + is completely sorted using insertion sort, since this is efficient + for partitions below MAX_THRESH size. BASE_PTR points to the beginning + of the array to sort, and END_PTR points at the very last element in + the array (*not* one beyond it!). */ + +#define min(x, y) ((x) < (y) ? (x) : (y)) + + { + char *const end_ptr = &base_ptr[size * (total_elems - 1)]; + char *tmp_ptr = base_ptr; + char *thresh = min(end_ptr, base_ptr + max_thresh); + char *run_ptr; + + /* Find smallest element in first threshold and place it at the + array's beginning. This is the smallest array element, + and the operation speeds up insertion sort's inner loop. */ + + for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size) + if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0) + tmp_ptr = run_ptr; + + if (tmp_ptr != base_ptr) + SWAP (tmp_ptr, base_ptr, size); + + /* Insertion sort, running from left-hand-side up to right-hand-side. */ + + run_ptr = base_ptr + size; + while ((run_ptr += size) <= end_ptr) + { + tmp_ptr = run_ptr - size; + while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0) + tmp_ptr -= size; + + tmp_ptr += size; + if (tmp_ptr != run_ptr) + { + char *trav; + + trav = run_ptr + size; + while (--trav >= run_ptr) + { + char c = *trav; + char *hi, *lo; + + for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo) + *hi = *lo; + *hi = c; + } + } + } + } +} diff --git a/libs/util/string.c b/libs/util/string.c index 4eed4a234..aeab6abb2 100644 --- a/libs/util/string.c +++ b/libs/util/string.c @@ -35,6 +35,7 @@ # include #endif #include +#include #include "qstring.h" @@ -72,6 +73,16 @@ Q_strnlen (const char *s, size_t maxlen) return i; } +char * +Q_strndup (const char *s, size_t n) +{ + size_t l = strnlen (s, n); + char *str = malloc (l + 1); + strncpy (str, s, l); + str[l] = 0; + return str; +} + #if defined(HAVE__VSNPRINTF) && !defined(HAVE_VSNPRINTF) size_t Q_snprintfz (char *dest, size_t size, const char *fmt, ...) From 8309e1852a6ea5db1048e847570d88b87496e3b1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 20:04:10 +0900 Subject: [PATCH 1447/3664] [simd] Fix some portability issues Use [u]int64_t instead of long, and fix some incorrect attribute usage (I had misread the gcc docs at the time). --- include/QF/simd/types.h | 4 +++- include/QF/simd/vec4d.h | 3 ++- include/QF/simd/vec4f.h | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index e056abfac..9badcc5f3 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -28,6 +28,8 @@ #ifndef __QF_simd_types_h #define __QF_simd_types_h +#include + #define VEC_TYPE(t,n) typedef t n __attribute__ ((vector_size (4*sizeof (t)))) /** Three element vector type for interfacing with compact data. @@ -51,7 +53,7 @@ VEC_TYPE (double, vec4d_t); /** Used mostly for __builtin_shuffle. */ -VEC_TYPE (long, vec4l_t); +VEC_TYPE (int64_t, vec4l_t); #endif /** Three element vector type for interfacing with compact data. diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index e73873bc0..93b0667c9 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -258,7 +258,8 @@ VISIBLE vec4d_t qconjd (vec4d_t q) { - const vec4l_t neg = { 1lu << 63, 1lu << 63, 1lu << 63, 0 }; + const uint64_t sign = UINT64_C(1) << 63; + const vec4l_t neg = { sign, sign, sign, 0 }; return _mm256_xor_pd (q, (__m256d) neg); } diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 8fe207b74..4c76ba34b 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -91,8 +91,8 @@ GNU89INLINE inline vec4f_t qrotf (vec4f_t a, vec4f_t b) __attribute__((const)); * That is, [-x, -y, -z, w]. */ GNU89INLINE inline vec4f_t qconjf (vec4f_t q) __attribute__((const)); -GNU89INLINE inline vec4f_t loadvec3f (const float v3[3]) __attribute__((pure, access(read_only, 1))); -GNU89INLINE inline void storevec3f (float v3[3], vec4f_t v4) __attribute__((access (write_only, 1))); +GNU89INLINE inline vec4f_t loadvec3f (const float *v3) __attribute__((pure)); +GNU89INLINE inline void storevec3f (float *v3, vec4f_t v4); GNU89INLINE inline vec4f_t normalf (vec4f_t v) __attribute__((pure)); GNU89INLINE inline vec4f_t magnitudef (vec4f_t v) __attribute__((pure)); GNU89INLINE inline vec4f_t magnitude3f (vec4f_t v) __attribute__((pure)); From c4a0f3cc736f3937345cc21a3d26035fbc6335ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 20:06:40 +0900 Subject: [PATCH 1448/3664] [util] Fix a string handling bug Good grief, they still exist :( --- libs/util/quakefs.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index e209d460a..163b77112 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1055,11 +1055,10 @@ _QFS_VOpenFile (const char *filename, int zip, ind = 0; #ifdef HAVE_VORBIS if (strequal (".wav", QFS_FileExtension (path))) { - char *oggfilename; - oggfilename = alloca (strlen (path) + 1); + size_t len = strlen (path); + char *oggfilename = alloca (len + 1); QFS_StripExtension (path, oggfilename); - strncat (oggfilename, ".ogg", - sizeof (oggfilename) - strlen (oggfilename) - 1); + strcat (oggfilename, ".ogg"); fnames[ind] = oggfilename; zip_flags[ind] = 0; ind++; From 88ff254f42053e87ddf8c621b308f507fb1c87fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 20:09:37 +0900 Subject: [PATCH 1449/3664] Get QF cross-compiling using MXE/mingw32 This includes -win clients (no clue if anything actually works yet). --- Makefile.am | 4 +- config.d/build_control.m4 | 24 +- config.d/compiling.m4 | 3 +- config.d/curses.m4 | 52 +- config.d/header_files.m4 | 9 + config.d/library_functions.m4 | 7 +- config.d/vulkan.m4 | 1 + configure.ac | 3 +- include/QF/Vulkan/debug.h | 2 +- include/context_win.h | 76 + include/net_wins.h | 2 +- include/vid_gl.h | 6 +- include/vid_sw.h | 3 - include/win32/fnmatch.h | 2 +- include/win32/stdint.h | 2 - include/winquake.h | 8 +- libs/audio/cd_win.c | 9 +- libs/audio/targets/snd_dx.c | 9 +- libs/console/Makemodule.am | 2 +- libs/console/server.c | 14 +- libs/net/nm/net_dgrm.c | 2 +- libs/net/nm/net_wins.c | 7 +- libs/util/cmem.c | 10 + libs/util/sys.c | 95 +- libs/video/renderer/Makemodule.am | 2 +- libs/video/targets/Makemodule.am | 36 +- libs/video/targets/context_win.c | 1403 ++++++++++++++++ libs/video/targets/in_win.c | 25 +- libs/video/targets/vid_sdl.c | 4 +- libs/video/targets/vid_sdl_sw.c | 5 +- libs/video/targets/vid_win.c | 2045 +----------------------- libs/video/targets/vid_win_gl.c | 185 +++ libs/video/targets/vid_win_sw.c | 234 +++ libs/video/targets/vid_win_vulkan.c | 145 ++ libs/video/targets/vid_x11_gl.c | 15 +- libs/video/targets/vid_x11_sw.c | 4 +- nq/source/Makemodule.am | 17 +- nq/source/sys_sdl.c | 7 +- qw/source/Makemodule.am | 17 +- qw/source/cl_sys_sdl.c | 5 + ruamoko/cl_menu/Makemodule.am | 2 +- ruamoko/qwaq/Makemodule.am | 2 +- ruamoko/qwaq/builtins/curses.c | 2 +- ruamoko/qwaq/builtins/debug.c | 2 - ruamoko/qwaq/builtins/input.c | 19 +- ruamoko/qwaq/builtins/main.c | 2 + ruamoko/qwaq/qwaq.h | 2 + ruamoko/qwaq/ui/curses.h | 2 +- tools/carne/main.c | 4 + tools/cross/mingw64/cross-configure.sh | 11 +- tools/cross/mingw64/cross-make.sh | 11 +- tools/qfcc/source/Makemodule.am | 2 +- tools/qfcc/source/cpp.c | 2 +- tools/qfcc/source/dump_lines.c | 5 +- tools/qfcc/source/dump_strings.c | 8 +- tools/qfcc/source/linker.c | 4 +- tools/qfcc/source/obj_file.c | 2 + tools/qfspritegen/spritegen.c | 4 + 58 files changed, 2448 insertions(+), 2139 deletions(-) create mode 100644 include/context_win.h delete mode 100644 include/win32/stdint.h create mode 100644 libs/video/targets/context_win.c create mode 100644 libs/video/targets/vid_win_gl.c create mode 100644 libs/video/targets/vid_win_sw.c create mode 100644 libs/video/targets/vid_win_vulkan.c diff --git a/Makefile.am b/Makefile.am index c869a6f3a..176c52434 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,7 @@ NOCONV_DIST= \ BUILT_SOURCES = $(top_srcdir)/.version #AM_CFLAGS= @PREFER_NON_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@ @@ -69,6 +69,8 @@ XMMS_LIBS= @XMMS_LIBS@ PAK=$(top_builddir)/pak$(EXEEXT) QFCC_DEP=qfcc$(EXEEXT) QFCC=$(top_builddir)/$(QFCC_DEP) +QWAQ_CURSES=$(top_builddir)/ruamoko/qwaq/qwaq-curses$(EXEEXT) + GZ=@progs_gz@ V_QFCC = $(V_QFCC_@AM_V@) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 74b28afcd..fdd4ce698 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -224,52 +224,52 @@ if test "x$ENABLE_servers_qw" = xyes; then fi if test "x$ENABLE_tools_bsp2img" = xyes; then - BSP2IMG_TARGETS=bsp2img + BSP2IMG_TARGETS="bsp2img\$(EXEEXT)" QF_NEED(tools,[bsp2img]) QF_NEED(libs,[image util]) fi if test "x$ENABLE_tools_carne" = xyes; then - CARNE_TARGETS=carne + CARNE_TARGETS="carne\$(EXEEXT)" QF_NEED(tools,[carne]) QF_NEED(libs,[gib ruamoko gamecode util]) fi if test "x$ENABLE_tools_pak" = xyes; then - PAK_TARGETS=pak + PAK_TARGETS="pak\$(EXEEXT)" QF_NEED(tools,[pak]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfbsp" = xyes; then - QFBSP_TARGETS=qfbsp + QFBSP_TARGETS="qfbsp\$(EXEEXT)" QF_NEED(tools,[qfbsp]) QF_NEED(libs,[models image util]) fi if test "x$ENABLE_tools_qfcc" = xyes; then - QFCC_TARGETS=qfcc qfprogs + QFCC_TARGETS="qfcc qfprogs\$(EXEEXT)" QF_NEED(tools,[qfcc]) QF_NEED(libs,[gamecode util]) fi if test "x$ENABLE_tools_qflight" = xyes; then - QFLIGHT_TARGETS=qflight + QFLIGHT_TARGETS="qflight\$(EXEEXT)" QF_NEED(tools,[qflight]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qflmp" = xyes; then - QFLMP_TARGETS=qflmp + QFLMP_TARGETS="qflmp\$(EXEEXT)" QF_NEED(tools,[qflmp]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfmodelgen" = xyes; then - QFMODELGEN_TARGETS=qfmodelgen + QFMODELGEN_TARGETS="qfmodelgen\$(EXEEXT)" QF_NEED(tools,[qfmodelgen]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfspritegen" = xyes; then - QFSPRITEGEN_TARGETS=qfspritegen + QFSPRITEGEN_TARGETS="qfspritegen\$(EXEEXT)" QF_NEED(tools,[qfspritegen]) QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qfvis" = xyes; then - QFVIS_TARGETS=qfvis + QFVIS_TARGETS="qfvis\$(EXEEXT)" QF_NEED(tools,[qfvis]) QF_NEED(libs,[util]) fi @@ -282,12 +282,12 @@ if test "x$ENABLE_tools_qwaq" = xyes; then QF_NEED(libs,[ruamoko gamecode util]) fi if test "x$ENABLE_tools_wad" = xyes; then - WAD_TARGETS=wad + WAD_TARGETS="wad\$(EXEEXT)" QF_NEED(tools,[wad]) QF_NEED(libs,[image util]) fi if test "x$ENABLE_tools_wav" = xyes; then - WAV_TARGETS=qfwavinfo + WAV_TARGETS="qfwavinfo\$(EXEEXT)" QF_NEED(tools,[wav]) QF_NEED(libs,[util]) fi diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 7a4908efa..f5042ae0f 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -27,8 +27,7 @@ AC_TRY_LINK( AC_MSG_RESULT(yes) ) AH_VERBATIM([HAVE_C99INLINE], -[/* Define this if the GCC __attribute__ keyword is available */ -#undef HAVE_C99INLINE +[#undef HAVE_C99INLINE #ifdef HAVE_C99INLINE # define GNU89INLINE #else diff --git a/config.d/curses.m4 b/config.d/curses.m4 index 02d9ce7f4..6a5757cc1 100644 --- a/config.d/curses.m4 +++ b/config.d/curses.m4 @@ -2,44 +2,52 @@ AC_ARG_ENABLE(curses, [ --disable-curses disable curses support] ) if test "x$enable_curses" != "xno"; then - AC_CHECK_HEADER([curses.h], - [AC_DEFINE([HAVE_CURSES_H], [1], - [Define to 1 if you have .])]) + if test "x$PKG_CONFIG" != "x"; then + PKG_CHECK_MODULES([NCURSES], [ncurses], HAVE_NCURSES=yes, HAVE_NCURSES=no) + else + AC_CHECK_HEADER([curses.h], [], + [AC_CHECK_HEADER([ncurses/curses.h], + [NCURSES_CFLAGS=-I${prefix}/include/ncurses])]) AC_CHECK_LIB(ncurses, initscr, - CURSES_LIBS=-lncurses, + NCURSES_LIBS=-lncurses, AC_CHECK_LIB(pdcurses, initscr, - CURSES_LIBS=-lpdcurses, + NCURSES_LIBS=-lpdcurses, AC_CHECK_LIB(curses, initscr, - CURSES_LIBS=-lcurses, - CURSES_LIBS= + NCURSES_LIBS=-lcurses, + NCURSES_LIBS= ) ) ) - if test "x$CURSES_LIBS" != "x"; then + if test "x$NCURSES_LIBS" != "x"; then AC_DEFINE(HAVE_CURSES, 1, [Define if you have the ncurses library]) HAVE_CURSES=yes else HAVE_CURSES=no fi + fi else HAVE_CURSES=no - CURSES_LIBS= + NCURSES_LIBS= fi -AC_SUBST(CURSES_LIBS) +AC_SUBST(NCURSES_LIBS) -if test "x$HAVE_CURSES" == "xyes"; then - AC_CHECK_HEADER(panel.h, - [AC_CHECK_LIB(panel, new_panel, - [AC_DEFINE(HAVE_PANEL, 1, - [Define if you have the ncurses panel library]) - PANEL_LIBS=-lpanel - HAVE_PANEL=yes], +if test "x$HAVE_NCURSES" == "xyes"; then + if test "x$PKG_CONFIG" != "x"; then + PKG_CHECK_MODULES([PANEL], [panel], HAVE_PANEL=yes, HAVE_PANEL=no) + else + AC_CHECK_HEADER(panel.h, + [AC_CHECK_LIB(panel, new_panel, + [AC_DEFINE(HAVE_PANEL, 1, + [Define if you have the ncurses panel library]) + PANEL_LIBS=-lpanel + HAVE_PANEL=yes], + [HAVE_PANEL=no], + $NCURSES_LIBS + )], [HAVE_PANEL=no], - $CURSES_LIBS - )], - HAVE_PANEL=no, - [] - ) + [$NCURSES_CFLAGS] + ) + fi else PANEL_LIBS= fi diff --git a/config.d/header_files.m4 b/config.d/header_files.m4 index afb4cd37f..2e4e9a7ed 100644 --- a/config.d/header_files.m4 +++ b/config.d/header_files.m4 @@ -50,6 +50,15 @@ AC_TRY_COMPILE( AC_MSG_RESULT(no) ) +AC_MSG_CHECKING(for strndup in string.h) +AC_TRY_COMPILE( + [#include "string.h"], + [int (*foo)() = strndup;], + AC_DEFINE(HAVE_STRNDUP_PROTO, 1, [Define this if strndup is prototyped in string.h]) + AC_MSG_RESULT(yes), + AC_MSG_RESULT(no) +) + AC_MSG_CHECKING(for strcasestr in string.h) AC_TRY_COMPILE( [#include "string.h"], diff --git a/config.d/library_functions.m4 b/config.d/library_functions.m4 index ba76c574e..f4bebf3c0 100644 --- a/config.d/library_functions.m4 +++ b/config.d/library_functions.m4 @@ -10,9 +10,10 @@ AC_FUNC_VPRINTF AC_CHECK_FUNCS( access _access connect dlopen execvp fcntl ftime _ftime getaddrinfo \ gethostbyname gethostname getnameinfo getpagesize gettimeofday getuid \ - getwd ioctl mkdir _mkdir mprotect putenv select snprintf _snprintf \ - socket stat strcasestr strerror strnlen strsep strstr vsnprintf \ - _vsnprintf wait + getwd ioctl mkdir _mkdir mprotect putenv qsort_r select sigaction \ + snprintf _snprintf socket stat strcasestr strerror strerror_r strndup \ + strnlen \ + strsep strstr vsnprintf _vsnprintf wait ) AC_FUNC_VA_COPY diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index 0c780e98a..85ed9d3f0 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -19,3 +19,4 @@ AC_SUBST(VULKAN_LIBS) AC_SUBST(GLSLANGVALIDATOR, [$glslangvalidator]) AM_CONDITIONAL(X11_VULKAN, test "x$HAVE_VULKAN" = "xyes") +AM_CONDITIONAL(WIN_VULKAN, test "x$HAVE_VULKAN" = "xyes") diff --git a/configure.ac b/configure.ac index db59908b8..c19200755 100644 --- a/configure.ac +++ b/configure.ac @@ -74,9 +74,10 @@ dnl Checks for system type dnl ================================================================== dnl Checks for which system driver to use +echo ${host} AC_MSG_CHECKING(for system driver) case "${host}" in - i?86-*-mingw32*|x86_64-w64-mingw32) + i?86-*-mingw32*|x86_64-w64-mingw32*) SYSTYPE=WIN32 AC_MSG_RESULT([Win32 driver]) WIN32_LIBS=' $(NET_LIBS)' diff --git a/include/QF/Vulkan/debug.h b/include/QF/Vulkan/debug.h index 3250d5aca..c5fa70a7b 100644 --- a/include/QF/Vulkan/debug.h +++ b/include/QF/Vulkan/debug.h @@ -86,7 +86,7 @@ if (dfunc->vkSetDebugUtilsObjectNameEXT) { \ VkDebugUtilsObjectNameInfoEXT nameInfo = { \ VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 0, \ - type, (uint64_t) handle, name \ + type, (VkObjectType) handle, name \ }; \ dfunc->vkSetDebugUtilsObjectNameEXT (device->dev, &nameInfo); \ } \ diff --git a/include/context_win.h b/include/context_win.h new file mode 100644 index 000000000..879ea41c1 --- /dev/null +++ b/include/context_win.h @@ -0,0 +1,76 @@ +/* + context_win.h + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __context_win_h +#define __context_win_h + +#include "QF/qtypes.h" +#include "winquake.h" + +extern HWND win_mainwindow; +extern HDC win_maindc; +extern HDC win_dib_section; +extern int win_using_ddraw; +extern int win_palettized; +extern int win_canalttab; +extern DEVMODE win_gdevmode; +extern LPDIRECTDRAWSURFACE win_dd_frontbuffer; +extern LPDIRECTDRAWSURFACE win_dd_backbuffer; +extern RECT win_src_rect; +extern RECT win_dst_rect; +extern RECT win_window_rect; +extern HDC win_gdi; +extern struct sw_ctx_s *win_sw_context; + +void Win_UnloadAllDrivers (void); +void Win_CreateDriver (void); +void Win_OpenDisplay (void); +void Win_CloseDisplay (void); +void Win_SetVidMode (int width, int height, const byte *palette); +void Win_Init_Cvars (void); +void Win_UpdateWindowStatus (int x, int y); +void Win_SetCaption (const char *text); +qboolean Win_SetGamma (double gamma); + +struct gl_ctx_s *Win_GL_Context (void); +void Win_GL_Init_Cvars (void); + +struct sw_ctx_s *Win_SW_Context (void); +void Win_SW_Init_Cvars (void); + +struct vulkan_ctx_s *Win_Vulkan_Context (void); +void Win_Vulkan_Init_Cvars (void); + +void IN_UpdateClipCursor (void); +void IN_ShowMouse (void); +void IN_HideMouse (void); +void IN_ActivateMouse (void); +void IN_DeactivateMouse (void); + +#endif // __context_win_h diff --git a/include/net_wins.h b/include/net_wins.h index c4954f9ac..56c7fdddb 100644 --- a/include/net_wins.h +++ b/include/net_wins.h @@ -54,7 +54,7 @@ const char *WINS_AddrToString (netadr_t *addr); int WINS_GetSocketAddr (int socket, netadr_t *addr); int WINS_GetNameFromAddr (netadr_t *addr, char *name); int WINS_GetAddrFromName (const char *name, netadr_t *addr); -int WINS_AddrCompare (netadr_t *addr1, netadr_t *addr2); +int WINS_AddrCompare (netadr_t *addr1, netadr_t *addr2) __attribute__((pure)); int WINS_GetSocketPort (netadr_t *addr); int WINS_SetSocketPort (netadr_t *addr, int port); diff --git a/include/vid_gl.h b/include/vid_gl.h index 2561af575..7ad9378b1 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -1,11 +1,11 @@ #ifndef __vid_gl_h #define __vid_gl_h -// GLXContext is a pointer to opaque data -typedef struct __GLXcontextRec *GLXContext; +// GL_context is a pointer to opaque data +typedef struct GL_context *GL_context; typedef struct gl_ctx_s { - GLXContext context; + GL_context context; void (*load_gl) (void); void (*choose_visual) (struct gl_ctx_s *ctx); void (*create_context) (struct gl_ctx_s *ctx); diff --git a/include/vid_sw.h b/include/vid_sw.h index 2a5ab20a5..e57d3ee0d 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -1,11 +1,8 @@ #ifndef __vid_sw_h #define __vid_sw_h -// GLXContext is a pointer to opaque data -typedef struct __GLXcontextRec *GLXContext; struct vrect_s; typedef struct sw_ctx_s { - GLXContext context; void (*choose_visual) (struct sw_ctx_s *ctx); void (*create_context) (struct sw_ctx_s *ctx); void (*set_palette) (const byte *palette); diff --git a/include/win32/fnmatch.h b/include/win32/fnmatch.h index 7dd238d67..af8cd3670 100644 --- a/include/win32/fnmatch.h +++ b/include/win32/fnmatch.h @@ -61,7 +61,7 @@ extern "C" { /* Match STRING against the filename pattern PATTERN, returning zero if it matches, FNM_NOMATCH if not. */ extern int fnmatch __P ((const char *__pattern, const char *__string, - int __flags)); + int __flags)) __attribute__((pure)); #ifdef __cplusplus } diff --git a/include/win32/stdint.h b/include/win32/stdint.h deleted file mode 100644 index 495cadcba..000000000 --- a/include/win32/stdint.h +++ /dev/null @@ -1,2 +0,0 @@ -/* stub for compilers not supporting stdint.h */ -#include "pstdint.h" diff --git a/include/winquake.h b/include/winquake.h index 82d73f083..8786d6633 100644 --- a/include/winquake.h +++ b/include/winquake.h @@ -30,6 +30,8 @@ #ifdef _WIN32 +#include + #ifndef __GNUC__ # pragma warning( disable : 4229 ) /* mgraph gets this */ #endif @@ -76,20 +78,14 @@ extern LPDIRECTDRAWSURFACE lpBackBuffer; extern LPDIRECTDRAWPALETTE lpDDPal; #endif -void VID_LockBuffer (void); -void VID_UnlockBuffer (void); -void VID_UpdateWindowStatus (int window_x, int window_y); - typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t; extern modestate_t modestate; -extern HWND mainwindow; extern qboolean ActiveApp, Minimized; extern qboolean WinNT; -void VID_ForceLockState (int lk); extern qboolean winsock_lib_initialized; extern int window_center_x, window_center_y; diff --git a/libs/audio/cd_win.c b/libs/audio/cd_win.c index 93f29e624..5c297adc0 100644 --- a/libs/audio/cd_win.c +++ b/libs/audio/cd_win.c @@ -28,8 +28,6 @@ # include "config.h" #endif -#include "winquake.h" - #include "QF/cdaudio.h" #include "QF/cmd.h" #include "QF/cvar.h" @@ -41,6 +39,7 @@ #include "QF/plugin/cd.h" #include "compat.h" +#include "context_win.h" static plugin_t plugin_info; static plugin_data_t plugin_info_data; @@ -181,7 +180,7 @@ I_CDAudio_Pause (void) if (!playing) return; - mciGenericParms.dwCallback = (DWORD_PTR) mainwindow; + mciGenericParms.dwCallback = (DWORD_PTR) win_mainwindow; dwReturn = mciSendCommand (wDeviceID, MCI_PAUSE, 0, (DWORD_PTR) (LPVOID) & mciGenericParms); @@ -254,7 +253,7 @@ I_CDAudio_Play (int track, qboolean looping) mciPlayParms.dwFrom = MCI_MAKE_TMSF (track, 0, 0, 0); mciPlayParms.dwTo = (mciStatusParms.dwReturn << 8) | track; - mciPlayParms.dwCallback = (DWORD_PTR) mainwindow; + mciPlayParms.dwCallback = (DWORD_PTR) win_mainwindow; dwReturn = mciSendCommand (wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD_PTR) (LPVOID) & mciPlayParms); @@ -286,7 +285,7 @@ I_CDAudio_Resume (void) mciPlayParms.dwFrom = MCI_MAKE_TMSF (playTrack, 0, 0, 0); mciPlayParms.dwTo = MCI_MAKE_TMSF (playTrack + 1, 0, 0, 0); - mciPlayParms.dwCallback = (DWORD_PTR) mainwindow; + mciPlayParms.dwCallback = (DWORD_PTR) win_mainwindow; dwReturn = mciSendCommand (wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD_PTR) (LPVOID) & mciPlayParms); diff --git a/libs/audio/targets/snd_dx.c b/libs/audio/targets/snd_dx.c index 3852a17a5..27618487e 100644 --- a/libs/audio/targets/snd_dx.c +++ b/libs/audio/targets/snd_dx.c @@ -30,12 +30,12 @@ #define CINTERFACE -#include "winquake.h" #include "QF/cvar.h" #include "QF/qargs.h" #include "QF/sys.h" #include "snd_internal.h" +#include "context_win.h" #define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c) @@ -131,7 +131,7 @@ FreeSound (void) } if (pDS) { - IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL); + IDirectSound_SetCooperativeLevel (pDS, win_mainwindow, DSSCL_NORMAL); IDirectSound_Release (pDS); } pDS = NULL; @@ -219,7 +219,8 @@ SNDDMA_InitDirect (void) } if (DS_OK != - IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) { + IDirectSound_SetCooperativeLevel (pDS, win_mainwindow, + DSSCL_EXCLUSIVE)) { Sys_Printf ("Set coop level failed\n"); FreeSound (); return SIS_FAILURE; @@ -276,7 +277,7 @@ SNDDMA_InitDirect (void) } } else { if (DS_OK != - IDirectSound_SetCooperativeLevel (pDS, mainwindow, + IDirectSound_SetCooperativeLevel (pDS, win_mainwindow, DSSCL_WRITEPRIMARY)) { Sys_Printf ("Set coop level failed\n"); FreeSound (); diff --git a/libs/console/Makemodule.am b/libs/console/Makemodule.am index bd745a2e2..97586f514 100644 --- a/libs/console/Makemodule.am +++ b/libs/console/Makemodule.am @@ -28,6 +28,6 @@ libs_console_console_client_la_DEPENDENCIES= $(client_deps) libs_console_console_client_la_SOURCES= $(client_sources) libs_console_console_server_la_LDFLAGS= $(plugin_ldflags) -libs_console_console_server_la_LIBADD= $(server_deps) $(CURSES_LIBS) $(plugin_libadd) +libs_console_console_server_la_LIBADD= $(server_deps) $(NCURSES_LIBS) $(plugin_libadd) libs_console_console_server_la_DEPENDENCIES= $(server_deps) libs_console_console_server_la_SOURCES= $(server_sources) diff --git a/libs/console/server.c b/libs/console/server.c index 201842d27..a621bcc2b 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -31,7 +31,7 @@ # include "config.h" #endif -#ifdef HAVE_CURSES_H +#ifdef HAVE_CURSES # include #endif #ifdef HAVE_STRING_H @@ -84,7 +84,7 @@ static cvar_t *sv_conmode; static void C_KeyEvent (knum_t key, short unicode, qboolean down); -#ifdef HAVE_CURSES_H +#ifdef HAVE_CURSES enum { sv_resize_x = 1, @@ -682,7 +682,7 @@ sv_conmode_f (cvar_t *var) static void C_Init (void) { -#ifdef HAVE_CURSES_H +#ifdef HAVE_CURSES cvar_t *curses = Cvar_Get ("sv_use_curses", "0", CVAR_ROM, NULL, "Set to 1 to enable curses server console."); use_curses = curses->int_val; @@ -705,7 +705,7 @@ C_shutdown (void) Qclose (log_file); log_file = 0; } -#ifdef HAVE_CURSES_H +#ifdef HAVE_CURSES if (use_curses) endwin (); #endif @@ -725,7 +725,7 @@ C_Print (const char *fmt, va_list args) Qputs (log_file, buffer->str); Qflush (log_file); } -#ifdef HAVE_CURSES_H +#ifdef HAVE_CURSES if (use_curses) { print (buffer->str); } else @@ -741,7 +741,7 @@ C_Print (const char *fmt, va_list args) static void C_ProcessInput (void) { -#ifdef HAVE_CURSES_H +#ifdef HAVE_CURSES if (use_curses) { process_input (); } else @@ -757,7 +757,7 @@ C_ProcessInput (void) static void C_KeyEvent (knum_t key, short unicode, qboolean down) { -#ifdef HAVE_CURSES_H +#ifdef HAVE_CURSES key_event (key, unicode, down); #endif } diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index f69b246b6..7d9c88ab4 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -120,7 +120,7 @@ NET_Ban_f (void) switch (Cmd_Argc ()) { case 1: - if (((struct in_addr *) &banAddr)->s_addr) { + if (banAddr) { struct in_addr t; t.s_addr = banAddr; strcpy (addrStr, inet_ntoa (t)); diff --git a/libs/net/nm/net_wins.c b/libs/net/nm/net_wins.c index 77eaccc21..299509a18 100644 --- a/libs/net/nm/net_wins.c +++ b/libs/net/nm/net_wins.c @@ -437,10 +437,11 @@ PartialIPAddress (const char *in, netadr_t *hostaddr) return 0; } //============================================================================= - +static int WINS_Connect_called; int WINS_Connect (int socket, netadr_t *addr) { + WINS_Connect_called++; return 0; } @@ -543,6 +544,10 @@ WINS_AddrToString (netadr_t *addr) { static dstring_t *buffer; + if (!buffer) { + buffer = dstring_new (); + } + dsprintf (buffer, "%d.%d.%d.%d:%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3], ntohs (addr->port)); diff --git a/libs/util/cmem.c b/libs/util/cmem.c index 1879f7ea3..5ff1898f5 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -25,10 +25,20 @@ */ #include +#include #include "QF/alloc.h" #include "QF/cmem.h" +#ifdef _WIN32 +#define aligned_alloc(align, size) _aligned_malloc(size, align) +#define _SC_PAGESIZE 1 +static size_t sysconf (int key) +{ + return 1024; +} +#endif + static size_t __attribute__((const)) ilog2 (size_t x) { diff --git a/libs/util/sys.c b/libs/util/sys.c index 6e36c4545..f448a6f55 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -103,19 +103,6 @@ int sys_checksum; static sys_printf_t sys_std_printf_function = Sys_StdPrintf; static sys_printf_t sys_err_printf_function = Sys_ErrPrintf; -#ifndef _WIN32 -static struct sigaction save_hup; -static struct sigaction save_quit; -static struct sigaction save_trap; -static struct sigaction save_iot; -static struct sigaction save_bus; -#endif -static struct sigaction save_int; -static struct sigaction save_ill; -static struct sigaction save_segv; -static struct sigaction save_term; -static struct sigaction save_fpe; - typedef struct shutdown_list_s { struct shutdown_list_s *next; void (*func) (void *); @@ -635,11 +622,18 @@ Sys_PageIn (void *ptr, size_t size) VISIBLE void * Sys_Alloc (size_t size) { +#ifdef _WIN32 + size_t page_size = 4096; + size_t page_mask = page_size - 1; + size = (size + page_mask) & ~page_mask; + return VirtualAlloc (0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); +#else size_t page_size = sysconf (_SC_PAGESIZE); size_t page_mask = page_size - 1; size = (size + page_mask) & ~page_mask; return mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#endif } VISIBLE void @@ -831,9 +825,69 @@ static void __attribute__((noreturn)) aiee (int sig) { printf ("AIEE, signal %d in shutdown code, giving up\n", sig); +#ifdef _WIN32 + longjmp (aiee_abort, 1); +#else siglongjmp (aiee_abort, 1); +#endif } +#ifdef _WIN32 +static void +signal_handler (int sig) +{ + int volatile recover = 0; // volatile for longjump + static volatile int in_signal_handler = 0; + + if (in_signal_handler) { + aiee (sig); + } + printf ("Received signal %d, exiting...\n", sig); + + switch (sig) { + case SIGINT: + case SIGTERM: + signal (SIGINT, SIG_DFL); + signal (SIGTERM, SIG_DFL); + Sys_Quit (); + default: + if (!setjmp (aiee_abort)) { + if (signal_hook) + recover = signal_hook (sig, signal_hook_data); + Sys_Shutdown (); + } + + if (!recover) { + signal (SIGILL, SIG_DFL); + signal (SIGSEGV, SIG_DFL); + signal (SIGFPE, SIG_DFL); + } + } +} + +static void +hook_signlas (void) +{ + // catch signals + signal (SIGINT, signal_handler); + signal (SIGILL, signal_handler); + signal (SIGSEGV, signal_handler); + signal (SIGTERM, signal_handler); + signal (SIGFPE, signal_handler); +} +#else + +static struct sigaction save_hup; +static struct sigaction save_quit; +static struct sigaction save_trap; +static struct sigaction save_iot; +static struct sigaction save_bus; +static struct sigaction save_int; +static struct sigaction save_ill; +static struct sigaction save_segv; +static struct sigaction save_term; +static struct sigaction save_fpe; + static void signal_handler (int sig, siginfo_t *info, void *ucontext) { @@ -848,10 +902,8 @@ signal_handler (int sig, siginfo_t *info, void *ucontext) switch (sig) { case SIGINT: case SIGTERM: -#ifndef _WIN32 case SIGHUP: sigaction (SIGHUP, &save_hup, 0); -#endif sigaction (SIGINT, &save_int, 0); sigaction (SIGTERM, &save_term, 0); Sys_Quit (); @@ -863,12 +915,10 @@ signal_handler (int sig, siginfo_t *info, void *ucontext) } if (!recover) { -#ifndef _WIN32 sigaction (SIGQUIT, &save_quit, 0); sigaction (SIGTRAP, &save_trap, 0); sigaction (SIGIOT, &save_iot, 0); sigaction (SIGBUS, &save_bus, 0); -#endif sigaction (SIGILL, &save_ill, 0); sigaction (SIGSEGV, &save_segv, 0); sigaction (SIGFPE, &save_fpe, 0); @@ -876,8 +926,8 @@ signal_handler (int sig, siginfo_t *info, void *ucontext) } } -VISIBLE void -Sys_Init (void) +static void +hook_signlas (void) { // catch signals struct sigaction action = {}; @@ -895,6 +945,13 @@ Sys_Init (void) sigaction (SIGSEGV, &action, &save_segv); sigaction (SIGTERM, &action, &save_term); sigaction (SIGFPE, &action, &save_fpe); +} +#endif + +VISIBLE void +Sys_Init (void) +{ + hook_signlas (); Cvar_Init_Hash (); Cmd_Init_Hash (); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 54fa0a2e3..562a9bebc 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -395,7 +395,7 @@ V_VKGEN_0 = @echo " VKGEN " $@; V_VKGEN_1 = $(vkparse_cinc): $(vkgen) $(qwaq_curses) $(vkparse_plist) - $(V_VKGEN)$(qwaq_curses) $(vkgen) -- $(vkparse_plist) $(vkparse_cinc).t $(vkparse_hinc).t &&\ + $(V_VKGEN)$(QWAQ_CURSES) $(vkgen) -- $(vkparse_plist) $(vkparse_cinc).t $(vkparse_hinc).t &&\ $(am__mv) $(vkparse_cinc).t $(vkparse_cinc) &&\ $(am__mv) $(vkparse_hinc).t $(vkparse_hinc) diff --git a/libs/video/targets/Makemodule.am b/libs/video/targets/Makemodule.am index 22425f7c4..710a77c82 100644 --- a/libs/video/targets/Makemodule.am +++ b/libs/video/targets/Makemodule.am @@ -8,10 +8,11 @@ EXTRA_LTLIBRARIES += \ libs/video/targets/libQFsvga.la \ libs/video/targets/libQFx11.la \ libs/video/targets/libQFsdl.la \ - libs/video/targets/libQFwgl.la \ + libs/video/targets/libQFwin.la \ libs/video/targets/libvid_common.la \ libs/video/targets/libvid_sdl.la \ libs/video/targets/libvid_svga.la \ + libs/video/targets/libvid_win.la \ libs/video/targets/libvid_x11.la joy_linux_src= libs/video/targets/joy_linux.c @@ -27,6 +28,15 @@ joy_src= $(joy_null_src) endif endif +win_gl_src = libs/video/targets/vid_win_gl.c +win_sw_src = libs/video/targets/vid_win_sw.c +win_vulkan_src = libs/video/targets/vid_win_vulkan.c +if WIN_VULKAN +win_src = $(win_gl_src) $(win_sw_src) $(win_vulkan_src) +else +win_src = $(win_gl_src) $(win_sw_src) +endif + x11_gl_src = libs/video/targets/vid_x11_gl.c x11_sw_src = libs/video/targets/vid_x11_sw.c x11_vulkan_src = libs/video/targets/vid_x11_vulkan.c @@ -64,6 +74,14 @@ libs_video_targets_libvid_x11_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) libs_video_targets_libvid_x11_la_LDFLAGS= @STATIC@ EXTRA_libs_video_targets_libvid_x11_la_SOURCES= $(x11_vulkan_src) +libs_video_targets_libvid_win_la_SOURCES = \ + libs/video/targets/in_win.c \ + libs/video/targets/context_win.c \ + $(win_src) +libs_video_targets_libvid_win_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) +libs_video_targets_libvid_win_la_LDFLAGS= @STATIC@ +EXTRA_libs_video_targets_libvid_win_la_SOURCES= $(win_vulkan_src) + libs_video_targets_libvid_svga_la_SOURCES= libs/video/targets/in_svgalib.c libs_video_targets_libvid_svga_la_CFLAGS= @PREFER_NON_PIC@ $(SVGA_CFLAGS) libs_video_targets_libvid_svga_la_LDFLAGS= @STATIC@ @@ -117,16 +135,14 @@ libs_video_targets_libQFsvga_la_LIBADD= $(svga_libs) libs_video_targets_libQFsvga_la_DEPENDENCIES= $(svga_libs) # -# OpenGL in Win32 +# MS Windows # -wgl_libs=libs/video/targets/libvid_common.la libs/video/targets/libvid_gl.la -libs_video_targets_libQFwgl_la_CFLAGS= @PREFER_NON_PIC@ $(WGL_CFLAGS) -libs_video_targets_libQFwgl_la_SOURCES = \ - libs/video/targets/in_win.c \ - libs/video/targets/vid_wgl.c -libs_video_targets_libQFwgl_la_LDFLAGS= @STATIC@ -libs_video_targets_libQFwgl_la_LIBADD= $(wgl_libs) -libs_video_targets_libQFwgl_la_DEPENDENCIES= $(wgl_libs) +win_libs=libs/video/targets/libvid_common.la libs/video/targets/libvid_win.la +libs_video_targets_libQFwin_la_CFLAGS= @PREFER_NON_PIC@ $(WGL_CFLAGS) +libs_video_targets_libQFwin_la_SOURCES= libs/video/targets/vid_win.c +libs_video_targets_libQFwin_la_LDFLAGS= @STATIC@ +libs_video_targets_libQFwin_la_LIBADD= $(win_libs) +libs_video_targets_libQFwin_la_DEPENDENCIES= $(win_libs) # # X11 software rendering diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c new file mode 100644 index 000000000..d0bd49db2 --- /dev/null +++ b/libs/video/targets/context_win.c @@ -0,0 +1,1403 @@ +/* + vid_win.c + + Win32 vid component + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "winquake.h" +#include + +#include "QF/cmd.h" +#include "QF/cvar.h" +#include "QF/input.h" +#include "QF/qargs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" + +#include "context_win.h" +#include "r_shared.h" +#include "vid_internal.h" +#include "vid_sw.h" + +HWND win_mainwindow; +HDC win_maindc; +HDC win_dib_section; +int win_using_ddraw; +int win_palettized; +LPDIRECTDRAWSURFACE win_dd_frontbuffer; +LPDIRECTDRAWSURFACE win_dd_backbuffer; +RECT win_src_rect; +RECT win_dst_rect; +RECT win_window_rect; +HDC win_gdi; +int win_canalttab = 0; +int win_palettized; +sw_ctx_t *win_sw_context; + +#define MODE_WINDOWED 0 +#define MODE_SETTABLE_WINDOW 2 +#define NO_MODE (MODE_WINDOWED - 1) +#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) + +static cvar_t *vid_ddraw; + +// Note that 0 is MODE_WINDOWED +static cvar_t *vid_mode; + +// Note that 0 is MODE_WINDOWED +static cvar_t *_vid_default_mode; + +// Note that 3 is MODE_FULLSCREEN_DEFAULT +static cvar_t *_vid_default_mode_win; +static cvar_t *vid_wait; +static cvar_t *vid_nopageflip; +static cvar_t *_vid_wait_override; +static cvar_t *vid_config_x; +static cvar_t *vid_config_y; +static cvar_t *vid_stretch_by_2; +static cvar_t *_windowed_mouse; +static cvar_t *vid_fullscreen_mode; +static cvar_t *vid_windowed_mode; +static cvar_t *block_switch; +static cvar_t *vid_window_x; +static cvar_t *vid_window_y; + +//FIXME?int yeahimconsoled; + +#define MAX_MODE_LIST 36 +#define VID_ROW_SIZE 3 + +extern qboolean Minimized; + +HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); + +int DIBWidth, DIBHeight; +RECT WindowRect; +DWORD WindowStyle, ExWindowStyle; + +int window_center_x, window_center_y, window_width, window_height; +RECT window_rect; + +DEVMODE win_gdevmode; +static qboolean startwindowed = 0, windowed_mode_set; +static qboolean vid_palettized; +static int vid_fulldib_on_focus_mode; +static qboolean force_minimized, in_mode_set, force_mode_set; +static qboolean vid_mode_set; +static HICON hIcon; + + +int vid_modenum = NO_MODE; +int vid_testingmode, vid_realmode; +double vid_testendtime; +int vid_default = MODE_WINDOWED; +static int windowed_default; + +modestate_t modestate = MS_UNINIT; + +byte vid_curpal[256 * 3]; + +unsigned short d_8to16table[256]; + +int mode; + +typedef struct { + modestate_t type; + int width; + int height; + int modenum; + int fullscreen; + char modedesc[13]; +} vmode_t; + +static vmode_t modelist[MAX_MODE_LIST]; +static int nummodes; + +int aPage; // Current active display page +int vPage; // Current visible display page +int waitVRT = true; // True to wait for retrace on flip + +static vmode_t badmode; + +/* +============================================================================= + + DIRECTDRAW VIDEO DRIVER + +============================================================================= +*/ + +LPDIRECTDRAW dd_Object = NULL; +HINSTANCE hInstDDraw = NULL; + +LPDIRECTDRAWCLIPPER dd_Clipper = NULL; + +typedef HRESULT (WINAPI *ddCreateProc_t) (GUID FAR *, + LPDIRECTDRAW FAR *, + IUnknown FAR *); +ddCreateProc_t ddCreate = NULL; + +unsigned ddpal[256]; + +byte *vidbuf = NULL; + + +int dd_window_width = 640; +int dd_window_height = 480; + +static void +DD_UpdateRects (int width, int height) +{ + POINT p = { .x = 0, .y = 0 }; + // first we need to figure out where on the primary surface our window + // lives + ClientToScreen (win_mainwindow, &p); + GetClientRect (win_mainwindow, &win_dst_rect); + OffsetRect (&win_dst_rect, p.x, p.y); + SetRect (&win_src_rect, 0, 0, width, height); +} + + +static void +VID_CreateDDrawDriver (int width, int height, const byte *palette, + void **buffer, int *rowbytes) +{ + DDSURFACEDESC ddsd; + + win_using_ddraw = false; + dd_window_width = width; + dd_window_height = height; + + vidbuf = (byte *) malloc (width * height); + buffer[0] = vidbuf; + rowbytes[0] = width; + + if (!(hInstDDraw = LoadLibrary ("ddraw.dll"))) { + return; + } + if (!(ddCreate = (ddCreateProc_t) GetProcAddress (hInstDDraw, + "DirectDrawCreate"))) { + return; + } + + if (FAILED (ddCreate (NULL, &dd_Object, NULL))) { + return; + } + if (FAILED (dd_Object->lpVtbl->SetCooperativeLevel (dd_Object, + win_mainwindow, + DDSCL_NORMAL))) { + return; + } + + // the primary surface in windowed mode is the full screen + memset (&ddsd, 0, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY; + + // ...and create it + if (FAILED (dd_Object->lpVtbl->CreateSurface (dd_Object, &ddsd, + &win_dd_frontbuffer, NULL))) { + return; + } + + // not using a clipper will slow things down and switch aero off + if (FAILED (IDirectDraw_CreateClipper (dd_Object, 0, &dd_Clipper, NULL))) { + return; + } + if (FAILED (IDirectDrawClipper_SetHWnd (dd_Clipper, 0, win_mainwindow))) { + return; + } + if (FAILED (IDirectDrawSurface_SetClipper (win_dd_frontbuffer, + dd_Clipper))) { + return; + } + + // the secondary surface is an offscreen surface that is the currect + // dimensions + // this will be blitted to the correct location on the primary surface + // (which is the full screen) during our draw op + memset (&ddsd, 0, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + ddsd.dwWidth = width; + ddsd.dwHeight = height; + + if (FAILED (IDirectDraw_CreateSurface (dd_Object, &ddsd, + &win_dd_backbuffer, NULL))) { + return; + } + + // direct draw is working now + win_using_ddraw = true; + + // create a palette + VID_InitGamma (palette); + viddef.vid_internal->set_palette (palette); + + // create initial rects + DD_UpdateRects (dd_window_width, dd_window_height); +} + + +/* +===================================================================== + + GDI VIDEO DRIVER + +===================================================================== +*/ + +// common bitmap definition +typedef struct dibinfo { + BITMAPINFOHEADER header; + RGBQUAD acolors[256]; +} dibinfo_t; + + +static HGDIOBJ previously_selected_GDI_obj = NULL; +HBITMAP hDIBSection; +byte *pDIBBase = NULL; +HDC hdcDIBSection = NULL; +HDC hdcGDI = NULL; + + +static void +VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer, + int *rowbytes) +{ + dibinfo_t dibheader; + BITMAPINFO *pbmiDIB = (BITMAPINFO *) & dibheader; + int i; + + hdcGDI = GetDC (win_mainwindow); + memset (&dibheader, 0, sizeof (dibheader)); + + // fill in the bitmap info + pbmiDIB->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + pbmiDIB->bmiHeader.biWidth = width; + pbmiDIB->bmiHeader.biHeight = height; + pbmiDIB->bmiHeader.biPlanes = 1; + pbmiDIB->bmiHeader.biCompression = BI_RGB; + pbmiDIB->bmiHeader.biSizeImage = 0; + pbmiDIB->bmiHeader.biXPelsPerMeter = 0; + pbmiDIB->bmiHeader.biYPelsPerMeter = 0; + pbmiDIB->bmiHeader.biClrUsed = 256; + pbmiDIB->bmiHeader.biClrImportant = 256; + pbmiDIB->bmiHeader.biBitCount = 8; + + // fill in the palette + for (i = 0; i < 256; i++) { + // d_8to24table isn't filled in yet so this is just for testing + dibheader.acolors[i].rgbRed = palette[i * 3]; + dibheader.acolors[i].rgbGreen = palette[i * 3 + 1]; + dibheader.acolors[i].rgbBlue = palette[i * 3 + 2]; + } + + // create the DIB section + hDIBSection = CreateDIBSection (hdcGDI, + pbmiDIB, + DIB_RGB_COLORS, + (void **) &pDIBBase, NULL, 0); + + // set video buffers + if (pbmiDIB->bmiHeader.biHeight > 0) { + // bottom up + buffer[0] = pDIBBase + (height - 1) * width; + rowbytes[0] = -width; + } else { + // top down + buffer[0] = pDIBBase; + rowbytes[0] = width; + } + + // clear the buffer + memset (pDIBBase, 0xff, width * height); + + if ((hdcDIBSection = CreateCompatibleDC (hdcGDI)) == NULL) + Sys_Error ("DIB_Init() - CreateCompatibleDC failed\n"); + + if ((previously_selected_GDI_obj = + SelectObject (hdcDIBSection, hDIBSection)) == NULL) + Sys_Error ("DIB_Init() - SelectObject failed\n"); + + // create a palette + VID_InitGamma (palette); + viddef.vid_internal->set_palette (palette); +} + +void +Win_CreateDriver (void) +{ + if (vid_ddraw->int_val) { + VID_CreateDDrawDriver (DIBWidth, DIBHeight, viddef.palette, + &viddef.buffer, &viddef.rowbytes); + } + if (!win_using_ddraw) { + // directdraw failed or was not requested + // + // if directdraw failed, it may be partially initialized, so make sure + // the slate is clean + Win_UnloadAllDrivers (); + + VID_CreateGDIDriver (DIBWidth, DIBHeight, viddef.palette, + &viddef.buffer, &viddef.rowbytes); + } +} + +void +Win_UnloadAllDrivers (void) +{ + // shut down ddraw + if (vidbuf) { + free (vidbuf); + vidbuf = NULL; + } + + if (dd_Clipper) { + IDirectDrawClipper_Release (dd_Clipper); + dd_Clipper = NULL; + } + + if (win_dd_frontbuffer) { + IDirectDrawSurface_Release (win_dd_frontbuffer); + win_dd_frontbuffer = NULL; + } + + if (win_dd_backbuffer) { + IDirectDrawSurface_Release (win_dd_backbuffer); + win_dd_backbuffer = NULL; + } + + if (dd_Object) { + IDirectDraw_Release (dd_Object); + dd_Object = NULL; + } + + if (hInstDDraw) { + FreeLibrary (hInstDDraw); + hInstDDraw = NULL; + } + + ddCreate = NULL; + + // shut down gdi + if (hdcDIBSection) { + SelectObject (hdcDIBSection, previously_selected_GDI_obj); + DeleteDC (hdcDIBSection); + hdcDIBSection = NULL; + } + + if (hDIBSection) { + DeleteObject (hDIBSection); + hDIBSection = NULL; + pDIBBase = NULL; + } + + if (hdcGDI) { + // if hdcGDI exists then win_mainwindow must also be valid + ReleaseDC (win_mainwindow, hdcGDI); + hdcGDI = NULL; + } + // not using ddraw now + win_using_ddraw = false; +} + + + +// compatibility +qboolean DDActive; + +void VID_MenuDraw (void); +void VID_MenuKey (int key); + +LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +void AppActivate (BOOL fActive, BOOL minimize); + +static int VID_SetMode (int modenum, const byte *palette); + + +/* +================ +VID_RememberWindowPos +================ +*/ +static void __attribute__ ((used)) +VID_RememberWindowPos (void) +{ + RECT rect; + + if (GetWindowRect (win_mainwindow, &rect)) { + if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && + (rect.top < GetSystemMetrics (SM_CYSCREEN)) && + (rect.right > 0) && (rect.bottom > 0)) { + Cvar_SetValue (vid_window_x, (float) rect.left); + Cvar_SetValue (vid_window_y, (float) rect.top); + } + } +} + + +/* +================ +VID_CheckWindowXY +================ +*/ +static void +VID_CheckWindowXY (void) +{ + if ((vid_window_x->int_val > (GetSystemMetrics (SM_CXSCREEN) - 160)) || + (vid_window_y->int_val > (GetSystemMetrics (SM_CYSCREEN) - 120)) || + (vid_window_x->int_val < 0) || (vid_window_y->int_val < 0)) { + Cvar_SetValue (vid_window_x, 0.0); + Cvar_SetValue (vid_window_y, 0.0); + } +} + + +/* +================ +VID_UpdateWindowStatus +================ +*/ +void +Win_UpdateWindowStatus (int window_x, int window_y) +{ + window_rect.left = window_x; + window_rect.top = window_y; + window_rect.right = window_x + window_width; + window_rect.bottom = window_y + window_height; + window_center_x = (window_rect.left + window_rect.right) / 2; + window_center_y = (window_rect.top + window_rect.bottom) / 2; + IN_UpdateClipCursor (); +} + + +/* +================ +ClearAllStates +================ +*/ +static void +ClearAllStates (void) +{ + int i; + + // send an up event for each key, to make sure the server clears them all + for (i = 0; i < 256; i++) { + Key_Event (i, 0, false); + } + + Key_ClearStates (); + IN_ClearStates (); +} + + +/* +================ +VID_CheckAdequateMem +================ +*/ +static qboolean +VID_CheckAdequateMem (int width, int height) +{ + // there will always be enough ;) + return true; +} + + +static void +VID_InitModes (HINSTANCE hInstance) +{ + WNDCLASS wc; + HDC hdc; + +//FIXME hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2)); + + /* Register the frame class */ + wc.style = CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) MainWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = 0; + wc.lpszClassName = "WinQuake"; + + if (!RegisterClass (&wc)) + Sys_Error ("Couldn't register window class"); + + modelist[0].type = MS_WINDOWED; + modelist[0].width = 320; + modelist[0].height = 240; + strcpy (modelist[0].modedesc, "320x240"); + modelist[0].modenum = MODE_WINDOWED; + modelist[0].fullscreen = 0; + + modelist[1].type = MS_WINDOWED; + modelist[1].width = 640; + modelist[1].height = 480; + strcpy (modelist[1].modedesc, "640x480"); + modelist[1].modenum = MODE_WINDOWED + 1; + modelist[1].fullscreen = 0; + + modelist[2].type = MS_WINDOWED; + modelist[2].width = 800; + modelist[2].height = 600; + strcpy (modelist[2].modedesc, "800x600"); + modelist[2].modenum = MODE_WINDOWED + 2; + modelist[2].fullscreen = 0; + + // automatically stretch the default mode up if > 640x480 desktop + // resolution + hdc = GetDC (NULL); + + if ((GetDeviceCaps (hdc, HORZRES) > 800) + && !COM_CheckParm ("-noautostretch")) { + vid_default = MODE_WINDOWED + 2; + } else if ((GetDeviceCaps (hdc, HORZRES) > 640) + && !COM_CheckParm ("-noautostretch")) { + vid_default = MODE_WINDOWED + 1; + } else { + vid_default = MODE_WINDOWED; + } + + // always start at the lowest mode then switch to the higher one if + // selected + vid_default = MODE_WINDOWED; + + windowed_default = vid_default; + ReleaseDC (NULL, hdc); + nummodes = 3; // reserve space for windowed mode +} + + +/* +================= +VID_GetDisplayModes +================= +*/ +static void +VID_GetDisplayModes (void) +{ + DEVMODE devmode; + int i, modenum, existingmode, originalnummodes, lowestres; + BOOL stat; + + // enumerate > 8 bpp modes + originalnummodes = nummodes; + modenum = 0; + lowestres = 99999; + + do { + stat = EnumDisplaySettings (NULL, modenum, &devmode); + + if ((devmode.dmPelsWidth <= MAXWIDTH) + && (devmode.dmPelsHeight <= MAXHEIGHT) + && (devmode.dmPelsWidth >= 320) + && (devmode.dmPelsHeight >= 240) + && (nummodes < MAX_MODE_LIST)) { + devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == + DISP_CHANGE_SUCCESSFUL) { + modelist[nummodes].type = MS_FULLDIB; + modelist[nummodes].width = devmode.dmPelsWidth; + modelist[nummodes].height = devmode.dmPelsHeight; + modelist[nummodes].modenum = 0; + modelist[nummodes].fullscreen = 1; + sprintf (modelist[nummodes].modedesc, "%dx%d", + (int) devmode.dmPelsWidth, + (int) devmode.dmPelsHeight); + + // see is the mode already there + // (same dimensions but different refresh rate) + for (i = originalnummodes, existingmode = 0; + i < nummodes; i++) { + if ((modelist[nummodes].width == modelist[i].width) + && (modelist[nummodes].height == modelist[i].height)) { + existingmode = 1; + break; + } + } + + // if it's not add it to the list + if (!existingmode) { + if (modelist[nummodes].width < lowestres) + lowestres = modelist[nummodes].width; + + nummodes++; + } + } + } + + modenum++; + } while (stat); + + if (nummodes != originalnummodes) + vid_default = MODE_FULLSCREEN_DEFAULT; + else + Sys_Printf ("No fullscreen DIB modes found\n"); +} + +void +Win_OpenDisplay (void) +{ + VID_InitModes (global_hInstance); + VID_GetDisplayModes (); + + vid_testingmode = 0; + + // if (COM_CheckParm("-startwindowed")) + { + startwindowed = 1; + vid_default = windowed_default; + } + +//FIXME? if (hwnd_dialog) +//FIXME? DestroyWindow (hwnd_dialog); + + // sound initialization has to go here, preceded by a windowed mode set, + // so there's a window for DirectSound to work with but we're not yet + // fullscreen so the "hardware already in use" dialog is visible if it + // gets displayed + // keep the window minimized until we're ready for the first real mode set + win_mainwindow = CreateWindowEx (ExWindowStyle, + "WinQuake", + "WinQuake", + WindowStyle, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + NULL, NULL, global_hInstance, NULL); + + if (!win_mainwindow) + Sys_Error ("Couldn't create DIB window"); + + // done + vid_mode_set = true; +//FIXME if (firsttime) S_Init (); +} + +void +Win_CloseDisplay (void) +{ + if (viddef.initialized) { + if (modestate == MS_FULLDIB) { + ChangeDisplaySettings (NULL, CDS_FULLSCREEN); + } + + PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM) win_mainwindow, + (LPARAM) 0); + PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM) 0, (LPARAM) 0); + AppActivate (false, false); + +//FIXME? if (hwnd_dialog) DestroyWindow (hwnd_dialog); + if (win_mainwindow) + DestroyWindow (win_mainwindow); + + vid_testingmode = 0; + viddef.initialized = false; + } +} + +void +Win_SetVidMode (int width, int height, const byte *palette) +{ +//FIXME SCR_StretchInit(); + + force_mode_set = true; + VID_SetMode (vid_default, palette); + force_mode_set = false; + vid_realmode = vid_modenum; + strcpy (badmode.modedesc, "Bad mode"); +} + +static void +VID_DestroyWindow (void) +{ + if (modestate == MS_FULLDIB) + ChangeDisplaySettings (NULL, CDS_FULLSCREEN); + + Win_UnloadAllDrivers (); +} + +static void +VID_CheckModedescFixup (int mode) +{ +} + +static qboolean +VID_SetWindowedMode (int modenum) +{ + if (!windowed_mode_set) { + if (COM_CheckParm ("-resetwinpos")) { + Cvar_SetValue (vid_window_x, 0.0); + Cvar_SetValue (vid_window_y, 0.0); + } + + windowed_mode_set = true; + } + + VID_CheckModedescFixup (modenum); + VID_DestroyWindow (); + + WindowRect.top = WindowRect.left = 0; + WindowRect.right = modelist[modenum].width; + WindowRect.bottom = modelist[modenum].height; + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + WindowStyle = WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_SIZEBOX | + WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | + WS_CLIPCHILDREN | WS_THICKFRAME; + + // WindowStyle = WS_OVERLAPPEDWINDOW|WS_VISIBLE; + ExWindowStyle = 0; + AdjustWindowRectEx (&WindowRect, WindowStyle, FALSE, 0); + + // the first time we're called to set the mode, create the window we'll use + // for the rest of the session + if (!vid_mode_set) { + } else { + SetWindowLong (win_mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); + SetWindowLong (win_mainwindow, GWL_EXSTYLE, ExWindowStyle); + } + + if (!SetWindowPos (win_mainwindow, + NULL, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + SWP_NOCOPYBITS | SWP_NOZORDER | SWP_HIDEWINDOW)) { + Sys_Error ("Couldn't resize DIB window"); + } + + // position and show the DIB window + VID_CheckWindowXY (); + SetWindowPos (win_mainwindow, NULL, vid_window_x->int_val, + vid_window_y->int_val, 0, 0, + SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); + + if (force_minimized) + ShowWindow (win_mainwindow, SW_MINIMIZE); + else + ShowWindow (win_mainwindow, SW_SHOWDEFAULT); + + UpdateWindow (win_mainwindow); + modestate = MS_WINDOWED; + vid_fulldib_on_focus_mode = 0; + + viddef.numpages = 1; + +// viddef.height = viddef.conheight = DIBHeight; +// viddef.width = viddef.conwidth = DIBWidth; + + viddef.height = viddef.conheight = DIBHeight; + viddef.width = viddef.conwidth = DIBWidth; +//FIXME? if (!yeahimconsoled){ +//FIXME? viddef.vconheight = DIBHeight; +//FIXME? viddef.vconwidth = DIBWidth; +//FIXME? } + SendMessage (win_mainwindow, WM_SETICON, (WPARAM) TRUE, (LPARAM) hIcon); + SendMessage (win_mainwindow, WM_SETICON, (WPARAM) FALSE, (LPARAM) hIcon); + + return true; +} + + +static qboolean +VID_SetFullDIBMode (int modenum) +{ + VID_DestroyWindow (); + + win_gdevmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + win_gdevmode.dmPelsWidth = modelist[modenum].width; + win_gdevmode.dmPelsHeight = modelist[modenum].height; + win_gdevmode.dmSize = sizeof (win_gdevmode); + + if (ChangeDisplaySettings (&win_gdevmode, CDS_FULLSCREEN) != + DISP_CHANGE_SUCCESSFUL) + Sys_Error ("Couldn't set fullscreen DIB mode"); + + modestate = MS_FULLDIB; + vid_fulldib_on_focus_mode = modenum; + WindowRect.top = WindowRect.left = 0; + + WindowRect.right = modelist[modenum].width; + WindowRect.bottom = modelist[modenum].height; + + DIBWidth = modelist[modenum].width; + DIBHeight = modelist[modenum].height; + + WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + ExWindowStyle = 0; + + AdjustWindowRectEx (&WindowRect, WindowStyle, FALSE, 0); + + SetWindowLong (win_mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); + SetWindowLong (win_mainwindow, GWL_EXSTYLE, ExWindowStyle); + + if (!SetWindowPos (win_mainwindow, + NULL, + 0, 0, + WindowRect.right - WindowRect.left, + WindowRect.bottom - WindowRect.top, + SWP_NOCOPYBITS | SWP_NOZORDER)) { + Sys_Error ("Couldn't resize DIB window"); + } + // position and show the DIB window + SetWindowPos (win_mainwindow, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); + ShowWindow (win_mainwindow, SW_SHOWDEFAULT); + UpdateWindow (win_mainwindow); + + viddef.numpages = 1; + +#ifdef SCALED2D + viddef.height = viddef.conheight = DIBHeight; + viddef.width = viddef.conwidth = DIBWidth; + // viddef.vconwidth = 320; + // viddef.vconheight = 200; +//FIXME? if (!yeahimconsoled){ +//FIXME? viddef.vconheight = DIBHeight; +//FIXME? viddef.vconwidth = DIBWidth; +//FIXME? } +#else + viddef.height = viddef.conheight = DIBHeight; + viddef.width = viddef.conwidth = DIBWidth; +#endif + + return true; +} + +static void +VID_RestoreOldMode (int original_mode) +{ + static qboolean inerror = false; + + if (inerror) + return; + + in_mode_set = false; + inerror = true; + // make sure mode set happens (video mode changes) + vid_modenum = original_mode - 1; + + if (!VID_SetMode (original_mode, vid_curpal)) { + vid_modenum = MODE_WINDOWED - 1; + + if (!VID_SetMode (windowed_default, vid_curpal)) + Sys_Error ("Can't set any video mode"); + } + + inerror = false; +} + + +static void __attribute__ ((used)) +VID_SetDefaultMode (void) +{ + if (viddef.initialized) + VID_SetMode (0, vid_curpal); + + IN_DeactivateMouse (); +} + +static vmode_t * +VID_GetModePtr (int modenum) +{ + if ((modenum >= 0) && (modenum < nummodes)) + return &modelist[modenum]; + else + return &badmode; +} + +static char * +VID_GetModeDescription (int mode) +{ + char *pinfo; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + pv = VID_GetModePtr (mode); + pinfo = pv->modedesc; + return pinfo; +} + +static int +VID_SetMode (int modenum, const byte *palette) +{ + int original_mode; // FIXME, temp; + qboolean stat; + MSG msg; + HDC hdc; + + while ((modenum >= nummodes) || (modenum < 0)) { + if (vid_modenum == NO_MODE) { + if (modenum == vid_default) { + modenum = windowed_default; + } else { + modenum = vid_default; + } + + Cvar_SetValue (vid_mode, (float) modenum); + } else { + Cvar_SetValue (vid_mode, (float) vid_modenum); + return 0; + } + } + + if (!force_mode_set && (modenum == vid_modenum)) + return true; + + // so Con_Printfs don't mess us up by forcing vid and snd updates +//FIXME? temp = scr_disabled_for_loading; +//FIXME? scr_disabled_for_loading = true; + in_mode_set = true; +//FIXME CDAudio_Pause (); +//FIXME S_ClearBuffer (); + + if (vid_modenum == NO_MODE) + original_mode = windowed_default; + else + original_mode = vid_modenum; + + // Set either the fullscreen or windowed mode + if (modelist[modenum].type == MS_WINDOWED) { + if (_windowed_mouse->int_val) { + stat = VID_SetWindowedMode (modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } else { + IN_DeactivateMouse (); + IN_ShowMouse (); + stat = VID_SetWindowedMode (modenum); + } + } else { + stat = VID_SetFullDIBMode (modenum); + IN_ActivateMouse (); + IN_HideMouse (); + } + + window_width = viddef.width; + window_height = viddef.height; + + + Win_UpdateWindowStatus (0, 0); // FIXME right numbers? +//FIXME CDAudio_Resume (); +//FIXME? scr_disabled_for_loading = temp; + + if (!stat) { + VID_RestoreOldMode (original_mode); + return false; + } + + // now we try to make sure we get the focus on the mode switch, because + // sometimes in some systems we don't. We grab the foreground, then + // finish setting up, pump all our messages, and sleep for a little while + // to let messages finish bouncing around the system, then we put + // ourselves at the top of the z order, then grab the foreground again, + // Who knows if it helps, but it probably doesn't hurt + if (!force_minimized) + SetForegroundWindow (win_mainwindow); + + hdc = GetDC (NULL); + + if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) + vid_palettized = true; + else + vid_palettized = false; + + viddef.vid_internal->set_palette (palette); + ReleaseDC (NULL, hdc); + vid_modenum = modenum; + Cvar_SetValue (vid_mode, (float) vid_modenum); + + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + Sleep (100); + + if (!force_minimized) { + SetWindowPos (win_mainwindow, HWND_TOP, 0, 0, 0, 0, + SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | + SWP_NOCOPYBITS); + + SetForegroundWindow (win_mainwindow); + } + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + Sys_Printf ("%s\n", VID_GetModeDescription (vid_modenum)); + + viddef.vid_internal->set_palette (palette); + + in_mode_set = false; + + viddef.recalc_refdef = 1; + +//FIXME SCR_StretchInit(); +//FIXME SCR_StretchRefresh(); +//FIXME SCR_CvarCheck(); + return true; +} + + + + +//========================================================================== + + +/* +================ +VID_HandlePause +================ +*/ +static void __attribute__ ((used)) +VID_HandlePause (qboolean pause) +{ + if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val) { + if (pause) { + IN_DeactivateMouse (); + IN_ShowMouse (); + } else { + IN_ActivateMouse (); + IN_HideMouse (); + } + } +} + + +/* +=================================================================== + +MAIN WINDOW + +=================================================================== +*/ + +typedef struct { + int modenum; + char *desc; + int iscur; + int width; +} modedesc_t; + +#define MAX_COLUMN_SIZE 5 +#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6) +#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) + +//static modedesc_t modedescs[MAX_MODEDESCS]; + +static int +VID_NumModes (void) +{ + return nummodes; +} + +static char * __attribute__((used)) +VID_GetModeDescriptionMemCheck (int mode) +{ + char *pinfo; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + pv = VID_GetModePtr (mode); + pinfo = pv->modedesc; + + if (VID_CheckAdequateMem (pv->width, pv->height)) { + return pinfo; + } else { + return NULL; + } +} + + +// Tacks on "windowed" or "fullscreen" +static char * __attribute__((used)) +VID_GetModeDescription2 (int mode) +{ + static char pinfo[40]; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + pv = VID_GetModePtr (mode); + + if (modelist[mode].type == MS_FULLSCREEN) { + sprintf (pinfo, "%s fullscreen", pv->modedesc); + } else if (modelist[mode].type == MS_FULLDIB) { + sprintf (pinfo, "%s fullscreen", pv->modedesc); + } else { + sprintf (pinfo, "%s windowed", pv->modedesc); + } + + return pinfo; +} + + +// KJB: Added this to return the mode driver name in description for console +static char * +VID_GetExtModeDescription (int mode) +{ + static char pinfo[40]; + vmode_t *pv; + + if ((mode < 0) || (mode >= nummodes)) + return NULL; + + VID_CheckModedescFixup (mode); + pv = VID_GetModePtr (mode); + + if (modelist[mode].type == MS_FULLDIB) { + sprintf (pinfo, "%s fullscreen", pv->modedesc); + } else { + sprintf (pinfo, "%s windowed", pv->modedesc); + } + + return pinfo; +} +static void +VID_DescribeCurrentMode_f (void) +{ + Sys_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); +} + +static void +VID_NumModes_f (void) +{ + if (nummodes == 1) + Sys_Printf ("%d video mode is available\n", nummodes); + else + Sys_Printf ("%d video modes are available\n", nummodes); +} + + +static void +VID_DescribeMode_f (void) +{ + int modenum; + + modenum = atoi (Cmd_Argv (1)); + Sys_Printf ("%s\n", VID_GetExtModeDescription (modenum)); +} + + +static void +VID_DescribeModes_f (void) +{ + int i, lnummodes; + char *pinfo; + qboolean na; + vmode_t *pv; + + na = false; + lnummodes = VID_NumModes (); + + for (i = 0; i < lnummodes; i++) { + pv = VID_GetModePtr (i); + pinfo = VID_GetExtModeDescription (i); + + if (VID_CheckAdequateMem (pv->width, pv->height)) { + Sys_Printf ("%2d: %s\n", i, pinfo); + } else { + Sys_Printf ("**: %s\n", pinfo); + na = true; + } + } + + if (na) { + Sys_Printf ("\n[**: not enough system RAM for mode]\n"); + } +} + +static void +VID_TestMode_f (void) +{ + int modenum; + double testduration; + + if (!vid_testingmode) { + modenum = atoi (Cmd_Argv (1)); + + if (VID_SetMode (modenum, vid_curpal)) { + vid_testingmode = 1; + testduration = atof (Cmd_Argv (2)); + + if (testduration == 0) + testduration = 5.0; + + vid_testendtime = Sys_DoubleTime () + testduration; + } + } +} + +static void +VID_Windowed_f (void) +{ + VID_SetMode (vid_windowed_mode->int_val, vid_curpal); +} + +static void +VID_Fullscreen_f (void) +{ + VID_SetMode (vid_fullscreen_mode->int_val, vid_curpal); +} + +static void +VID_Minimize_f (void) +{ + // we only support minimizing windows; if you're fullscreen, + // switch to windowed first + if (modestate == MS_WINDOWED) + ShowWindow (win_mainwindow, SW_MINIMIZE); +} + +static void +VID_ForceMode_f (void) +{ + int modenum; + + if (!vid_testingmode) { + modenum = atoi (Cmd_Argv (1)); + force_mode_set = 1; + VID_SetMode (modenum, vid_curpal); + force_mode_set = 0; + } +} + +void +Win_SetCaption (const char *text) +{ + if (win_mainwindow) { + SetWindowText (win_mainwindow, text); + } +} + +//static WORD systemgammaramps[3][256]; +static WORD currentgammaramps[3][256]; + +qboolean +Win_SetGamma (double gamma) +{ + int i; + HDC hdc = GetDC (NULL); + + for (i = 0; i < 256; i++) { + currentgammaramps[2][i] = currentgammaramps[1][i] = + currentgammaramps[0][i] = viddef.gammatable[i] * 256; + } + + i = SetDeviceGammaRamp (hdc, ¤tgammaramps[0][0]); + ReleaseDC (NULL, hdc); + return i; +} + +#if 0 +static void +VID_SaveGamma (void) +{ + HDC hdc = GetDC (NULL); + + GetDeviceGammaRamp (hdc, &systemgammaramps[0][0]); + ReleaseDC (NULL, hdc); +} + +static void +VID_RestoreGamma (void) +{ + HDC hdc = GetDC (NULL); + + SetDeviceGammaRamp (hdc, &systemgammaramps[0][0]); + ReleaseDC (NULL, hdc); +} +#endif + +#define CVAR_ORIGINAL CVAR_NONE // FIXME +void +Win_Init_Cvars (void) +{ + vid_ddraw = Cvar_Get ("vid_ddraw", "1", CVAR_ORIGINAL, 0, ""); + vid_mode = Cvar_Get ("vid_mode", "0", CVAR_ORIGINAL, 0, ""); + vid_wait = Cvar_Get ("vid_wait", "0", CVAR_ORIGINAL, 0, ""); + vid_nopageflip = + Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + _vid_wait_override = + Cvar_Get ("_vid_wait_override", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + _vid_default_mode = + Cvar_Get ("_vid_default_mode", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + _vid_default_mode_win = + Cvar_Get ("_vid_default_mode_win", "3", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + vid_config_x = + Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_config_y = + Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_stretch_by_2 = + Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + _windowed_mouse = + Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_fullscreen_mode = + Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + vid_windowed_mode = + Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, + ""); + block_switch = + Cvar_Get ("block_switch", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_window_x = + Cvar_Get ("vid_window_x", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + vid_window_y = + Cvar_Get ("vid_window_y", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + + Cmd_AddCommand ("vid_testmode", VID_TestMode_f, ""); + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, ""); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, ""); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, ""); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, ""); + Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f, ""); + Cmd_AddCommand ("vid_windowed", VID_Windowed_f, ""); + Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f, ""); + Cmd_AddCommand ("vid_minimize", VID_Minimize_f, ""); +} diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index cb54631f4..2a79681c3 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -46,6 +46,7 @@ #include "QF/sys.h" #include "compat.h" +#include "context_win.h" #include "in_win.h" #define DINPUT_BUFFERSIZE 16 @@ -55,9 +56,6 @@ HRESULT (WINAPI * pDirectInputCreate) (HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter); -extern qboolean win_canalttab; -extern DEVMODE win_gdevmode; - // mouse local variables static unsigned uiWheelMessage; static unsigned mouse_buttons; @@ -119,8 +117,6 @@ static DIDATAFORMAT df = { rgodf, // and here they are }; -// forward-referenced functions, joy - void IN_UpdateClipCursor (void) { @@ -168,7 +164,7 @@ IN_ActivateMouse (void) SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); SetCursorPos (window_center_x, window_center_y); - SetCapture (mainwindow); + SetCapture (win_mainwindow); ClipCursor (&window_rect); } @@ -255,7 +251,7 @@ IN_InitDInput (void) return false; } // set the cooperativity level. - hr = IDirectInputDevice_SetCooperativeLevel (g_pMouse, mainwindow, + hr = IDirectInputDevice_SetCooperativeLevel (g_pMouse, win_mainwindow, DISCL_EXCLUSIVE | DISCL_FOREGROUND); @@ -741,10 +737,10 @@ AppActivate (BOOL fActive, BOOL minimize) "(try upgrading your video drivers)\n (%lx)", GetLastError()); } - ShowWindow (mainwindow, SW_SHOWNORMAL); + ShowWindow (win_mainwindow, SW_SHOWNORMAL); // Fix for alt-tab bug in NVidia drivers - MoveWindow(mainwindow, 0, 0, win_gdevmode.dmPelsWidth, + MoveWindow(win_mainwindow, 0, 0, win_gdevmode.dmPelsWidth, win_gdevmode.dmPelsHeight, false); } } @@ -782,13 +778,13 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) switch (uMsg) { case WM_KILLFOCUS: if (modestate == MS_FULLDIB) - ShowWindow (mainwindow, SW_SHOWMINNOACTIVE); + ShowWindow (win_mainwindow, SW_SHOWMINNOACTIVE); break; case WM_CREATE: break; case WM_MOVE: - VID_UpdateWindowStatus ((int) LOWORD (lParam), + Win_UpdateWindowStatus ((int) LOWORD (lParam), (int) HIWORD (lParam)); break; @@ -848,7 +844,8 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_CLOSE: if (MessageBox - (mainwindow, "Are you sure you want to quit?", "Confirm Exit", + (win_mainwindow, + "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) { Sys_Quit (); } @@ -864,8 +861,8 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; case WM_DESTROY: - if (mainwindow) - DestroyWindow (mainwindow); + if (win_mainwindow) + DestroyWindow (win_mainwindow); PostQuitMessage (0); break; diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index 738abbb4b..e71660cb6 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -51,7 +51,7 @@ #ifdef _WIN32 // FIXME: evil hack to get full DirectSound support with SDL #include #include -HWND mainwindow; +HWND win_mainwindow; #endif SDL_Surface *sdl_screen = NULL; @@ -116,7 +116,7 @@ VID_Init (byte *palette, byte *colormap) // SDL_GetWMInfo(&info); // mainwindow=info.window; - mainwindow=GetActiveWindow(); + win_mainwindow=GetActiveWindow(); #endif viddef.recalc_refdef = 1; // force a surface cache flush diff --git a/libs/video/targets/vid_sdl_sw.c b/libs/video/targets/vid_sdl_sw.c index 2d4f806d4..5a9a96b42 100644 --- a/libs/video/targets/vid_sdl_sw.c +++ b/libs/video/targets/vid_sdl_sw.c @@ -52,7 +52,6 @@ #ifdef _WIN32 // FIXME: evil hack to get full DirectSound support with SDL #include #include -HWND mainwindow; #endif // The original defaults @@ -95,7 +94,7 @@ sdl_update_palette (const byte *palette) } static void -VID_SetPalette (const byte *palette) +sdl_set_palette (const byte *palette) { if (memcmp (cached_palette, palette, sizeof (cached_palette))) { memcpy (cached_palette, palette, sizeof (cached_palette)); @@ -171,7 +170,7 @@ sw_ctx_t * SDL_SW_Context (void) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); - ctx->set_palette = VID_SetPalette; + ctx->set_palette = sdl_set_palette; ctx->create_context = sdl_set_vid_mode; ctx->update = sdl_sw_update; return ctx; diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index af843eb05..fb4eeef96 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -28,1567 +28,26 @@ # include "config.h" #endif -#include "winquake.h" -#include - -#include "QF/cmd.h" -#include "QF/cvar.h" -#include "QF/input.h" -#include "QF/keys.h" -#include "QF/qargs.h" #include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" -#include "QF/GL/funcs.h" -#include "QF/GL/qf_vid.h" +#include "context_win.h" #include "d_iface.h" -#include "d_local.h" -#include "in_win.h" -#include "r_cvar.h" -#include "r_shared.h" #include "vid_internal.h" +#include "vid_sw.h" -// true if the ddraw driver started up OK -qboolean vid_usingddraw = false; - -// compatibility -HWND mainwindow = NULL; -qboolean win_canalttab = false; - -// main application window -HWND hWndWinQuake = NULL; -HDC maindc; -HGLRC baseRC; - -//FIXME?int yeahimconsoled; - -static void *libgl_handle; -static HGLRC (GLAPIENTRY * qfwglCreateContext) (HDC); -static BOOL (GLAPIENTRY * qfwglDeleteContext) (HGLRC); -static HGLRC (GLAPIENTRY * qfwglGetCurrentContext) (void); -static HDC (GLAPIENTRY * qfwglGetCurrentDC) (void); -static BOOL (GLAPIENTRY * qfwglMakeCurrent) (HDC, HGLRC); - -static void *(WINAPI * glGetProcAddress) (const char *symbol) = NULL; - -static void (*choose_visual) (void); -static void (*create_context) (const byte *palette); - -static void * -QFGL_GetProcAddress (void *handle, const char *name) -{ - void *glfunc = NULL; - - if (glGetProcAddress) - glfunc = glGetProcAddress (name); - if (!glfunc) - glfunc = GetProcAddress (handle, name); - return glfunc; -} - -static void * -QFGL_ProcAddress (const char *name, qboolean crit) -{ - void *glfunc = NULL; - - Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); - - glfunc = QFGL_GetProcAddress (libgl_handle, name); - if (glfunc) { - Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); - return glfunc; - } - Sys_MaskPrintf (SYS_VID, "not found\n"); - - if (crit) { - Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", - name); - } - return NULL; -} - -static void -GL_EndRendering (void) -{ - if (!scr_skipupdate) { - qfglFinish (); - SwapBuffers (maindc); - } - // handle the mouse state when windowed if that's changed - if (!vid_fullscreen->int_val) { - if (!in_grab->int_val) { -//FIXME if (windowed_mouse) { -//FIXME IN_DeactivateMouse (); -//FIXME IN_ShowMouse (); -//FIXME windowed_mouse = false; -//FIXME } - } else { -//FIXME windowed_mouse = true; - } - } -} - -static void -wgl_choose_visual (void) -{ -} - -static void -wgl_create_context (const byte *palette) -{ - DWORD lasterror; - - Sys_Printf ("maindc: %p\n", maindc); - baseRC = qfwglCreateContext (maindc); - if (!baseRC) { - lasterror=GetLastError(); - if (maindc && mainwindow) - ReleaseDC (mainwindow, maindc); - Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\n" - "Make sure you are in 65535 color mode, and try running " - "with -window.\n" - "Error code: (%lx)", lasterror); - } - - if (!qfwglMakeCurrent (maindc, baseRC)) { - lasterror = GetLastError (); - if (baseRC) - qfwglDeleteContext (baseRC); - if (maindc && mainwindow) - ReleaseDC (mainwindow, maindc); - Sys_Error ("wglMakeCurrent failed (%lx)", lasterror); - } - - viddef.init_gl (); -} - -static void -wgl_load_gl (void) -{ - choose_visual = wgl_choose_visual; - create_context = wgl_create_context; - - viddef.get_proc_address = QFGL_ProcAddress; - viddef.end_rendering = GL_EndRendering; - - if (!(libgl_handle = LoadLibrary (gl_driver->string))) - Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); - glGetProcAddress = - (void *) GetProcAddress (libgl_handle, "wglGetProcAddress"); - - qfwglCreateContext = QFGL_ProcAddress ("wglCreateContext", true); - qfwglDeleteContext = QFGL_ProcAddress ("wglDeleteContext", true); - qfwglGetCurrentContext = QFGL_ProcAddress ("wglGetCurrentContext", true); - qfwglGetCurrentDC = QFGL_ProcAddress ("wglGetCurrentDC", true); - qfwglMakeCurrent = QFGL_ProcAddress ("wglMakeCurrent", true); -} - - -/* -============================================================================= - - DIRECTDRAW VIDEO DRIVER - -============================================================================= -*/ - -LPDIRECTDRAW dd_Object = NULL; -HINSTANCE hInstDDraw = NULL; - -LPDIRECTDRAWSURFACE dd_FrontBuffer = NULL; -LPDIRECTDRAWSURFACE dd_BackBuffer = NULL; - -LPDIRECTDRAWCLIPPER dd_Clipper = NULL; - -typedef HRESULT (WINAPI * DIRECTDRAWCREATEPROC) (GUID FAR *, - LPDIRECTDRAW FAR *, - IUnknown FAR *); -DIRECTDRAWCREATEPROC QDirectDrawCreate = NULL; - -unsigned ddpal[256]; - -byte *vidbuf = NULL; - - -int dd_window_width = 640; -int dd_window_height = 480; -RECT SrcRect; -RECT DstRect; - -static void -DD_UpdateRects (int width, int height) -{ - POINT p; - - p.x = 0; - p.y = 0; - - // first we need to figure out where on the primary surface our window - // lives - ClientToScreen (hWndWinQuake, &p); - GetClientRect (hWndWinQuake, &DstRect); - OffsetRect (&DstRect, p.x, p.y); - SetRect (&SrcRect, 0, 0, width, height); -} - - -static void -VID_CreateDDrawDriver (int width, int height, const byte *palette, - void **buffer, int *rowbytes) -{ - HRESULT hr; - DDSURFACEDESC ddsd; - - vid_usingddraw = false; - dd_window_width = width; - dd_window_height = height; - - vidbuf = (byte *) malloc (width * height); - buffer[0] = vidbuf; - rowbytes[0] = width; - - if (!(hInstDDraw = LoadLibrary ("ddraw.dll"))) - return; - if (!(QDirectDrawCreate = - (DIRECTDRAWCREATEPROC) GetProcAddress (hInstDDraw, - "DirectDrawCreate"))) - return; - - if (FAILED (hr = QDirectDrawCreate (NULL, &dd_Object, NULL))) - return; - if (FAILED (hr = dd_Object->lpVtbl->SetCooperativeLevel (dd_Object, - hWndWinQuake, - DDSCL_NORMAL))) - return; - - // the primary surface in windowed mode is the full screen - memset (&ddsd, 0, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY; - - // ...and create it - if (FAILED (hr = dd_Object->lpVtbl->CreateSurface (dd_Object, &ddsd, - &dd_FrontBuffer, NULL))) - return; - - // not using a clipper will slow things down and switch aero off - if (FAILED (hr = IDirectDraw_CreateClipper (dd_Object, 0, &dd_Clipper, - NULL))) - return; - if (FAILED (hr = IDirectDrawClipper_SetHWnd (dd_Clipper, 0, hWndWinQuake))) - return; - if (FAILED (hr = IDirectDrawSurface_SetClipper (dd_FrontBuffer, - dd_Clipper))) - return; - - // the secondary surface is an offscreen surface that is the currect - // dimensions - // this will be blitted to the correct location on the primary surface - // (which is the full screen) during our draw op - memset (&ddsd, 0, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; - ddsd.dwWidth = width; - ddsd.dwHeight = height; - - if (FAILED (hr = IDirectDraw_CreateSurface (dd_Object, &ddsd, - &dd_BackBuffer, NULL))) - return; - - // direct draw is working now - vid_usingddraw = true; - - // create a palette - VID_InitGamma (palette); - viddef.set_palette (palette); - - // create initial rects - DD_UpdateRects (dd_window_width, dd_window_height); -} - - -/* -===================================================================== - - GDI VIDEO DRIVER - -===================================================================== -*/ - -// common bitmap definition -typedef struct dibinfo { - BITMAPINFOHEADER header; - RGBQUAD acolors[256]; -} dibinfo_t; - - -static HGDIOBJ previously_selected_GDI_obj = NULL; -HBITMAP hDIBSection; -byte *pDIBBase = NULL; -HDC hdcDIBSection = NULL; -HDC hdcGDI = NULL; - - -static void -VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer, - int *rowbytes) -{ - dibinfo_t dibheader; - BITMAPINFO *pbmiDIB = (BITMAPINFO *) & dibheader; - int i; - - hdcGDI = GetDC (hWndWinQuake); - memset (&dibheader, 0, sizeof (dibheader)); - - // fill in the bitmap info - pbmiDIB->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); - pbmiDIB->bmiHeader.biWidth = width; - pbmiDIB->bmiHeader.biHeight = height; - pbmiDIB->bmiHeader.biPlanes = 1; - pbmiDIB->bmiHeader.biCompression = BI_RGB; - pbmiDIB->bmiHeader.biSizeImage = 0; - pbmiDIB->bmiHeader.biXPelsPerMeter = 0; - pbmiDIB->bmiHeader.biYPelsPerMeter = 0; - pbmiDIB->bmiHeader.biClrUsed = 256; - pbmiDIB->bmiHeader.biClrImportant = 256; - pbmiDIB->bmiHeader.biBitCount = 8; - - // fill in the palette - for (i = 0; i < 256; i++) { - // d_8to24table isn't filled in yet so this is just for testing - dibheader.acolors[i].rgbRed = palette[i * 3]; - dibheader.acolors[i].rgbGreen = palette[i * 3 + 1]; - dibheader.acolors[i].rgbBlue = palette[i * 3 + 2]; - } - - // create the DIB section - hDIBSection = CreateDIBSection (hdcGDI, - pbmiDIB, - DIB_RGB_COLORS, - (void **) &pDIBBase, NULL, 0); - - // set video buffers - if (pbmiDIB->bmiHeader.biHeight > 0) { - // bottom up - buffer[0] = pDIBBase + (height - 1) * width; - rowbytes[0] = -width; - } else { - // top down - buffer[0] = pDIBBase; - rowbytes[0] = width; - } - - // clear the buffer - memset (pDIBBase, 0xff, width * height); - - if ((hdcDIBSection = CreateCompatibleDC (hdcGDI)) == NULL) - Sys_Error ("DIB_Init() - CreateCompatibleDC failed\n"); - - if ((previously_selected_GDI_obj = - SelectObject (hdcDIBSection, hDIBSection)) == NULL) - Sys_Error ("DIB_Init() - SelectObject failed\n"); - - // create a palette - VID_InitGamma (palette); - viddef.set_palette (palette); -} - - -static void -VID_UnloadAllDrivers (void) -{ - // shut down ddraw - if (vidbuf) { - free (vidbuf); - vidbuf = NULL; - } - - if (dd_Clipper) { - IDirectDrawClipper_Release (dd_Clipper); - dd_Clipper = NULL; - } - - if (dd_FrontBuffer) { - IDirectDrawSurface_Release (dd_FrontBuffer); - dd_FrontBuffer = NULL; - } - - if (dd_BackBuffer) { - IDirectDrawSurface_Release (dd_BackBuffer); - dd_BackBuffer = NULL; - } - - if (dd_Object) { - IDirectDraw_Release (dd_Object); - dd_Object = NULL; - } - - if (hInstDDraw) { - FreeLibrary (hInstDDraw); - hInstDDraw = NULL; - } - - QDirectDrawCreate = NULL; - - // shut down gdi - if (hdcDIBSection) { - SelectObject (hdcDIBSection, previously_selected_GDI_obj); - DeleteDC (hdcDIBSection); - hdcDIBSection = NULL; - } - - if (hDIBSection) { - DeleteObject (hDIBSection); - hDIBSection = NULL; - pDIBBase = NULL; - } - - if (hdcGDI) { - // if hdcGDI exists then hWndWinQuake must also be valid - ReleaseDC (hWndWinQuake, hdcGDI); - hdcGDI = NULL; - } - // not using ddraw now - vid_usingddraw = false; -} - - - -// compatibility -qboolean DDActive; - -// not used any more -void -VID_LockBuffer (void) -{ -} - -void -VID_UnlockBuffer (void) -{ -} - -//static int VID_ForceUnlockedAndReturnState (void) {return 0;} -void -VID_ForceLockState (int lk) -{ -} - - -#define MAX_MODE_LIST 36 -#define VID_ROW_SIZE 3 - -extern qboolean Minimized; - -HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); - -int DIBWidth, DIBHeight; -RECT WindowRect; -DWORD WindowStyle, ExWindowStyle; - -int window_center_x, window_center_y, window_width, window_height; -RECT window_rect; - -DEVMODE win_gdevmode; -static qboolean startwindowed = 0, windowed_mode_set; -static int firstupdate = 1; -static qboolean vid_initialized = false, vid_palettized; -static int vid_fulldib_on_focus_mode; -static qboolean force_minimized, in_mode_set, force_mode_set; -static int windowed_mouse; -static qboolean palette_changed, vid_mode_set; -static HICON hIcon; - -#define MODE_WINDOWED 0 -#define MODE_SETTABLE_WINDOW 2 -#define NO_MODE (MODE_WINDOWED - 1) -#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) - -cvar_t *vid_ddraw; - -// Note that 0 is MODE_WINDOWED -cvar_t *vid_mode; - -// Note that 0 is MODE_WINDOWED -cvar_t *_vid_default_mode; - -// Note that 3 is MODE_FULLSCREEN_DEFAULT -cvar_t *_vid_default_mode_win; -cvar_t *vid_wait; -cvar_t *vid_nopageflip; -cvar_t *_vid_wait_override; -cvar_t *vid_config_x; -cvar_t *vid_config_y; -cvar_t *vid_stretch_by_2; -cvar_t *_windowed_mouse; -cvar_t *vid_fullscreen_mode; -cvar_t *vid_windowed_mode; -cvar_t *block_switch; -cvar_t *vid_window_x; -cvar_t *vid_window_y; - - -int vid_modenum = NO_MODE; -int vid_testingmode, vid_realmode; -double vid_testendtime; -int vid_default = MODE_WINDOWED; -static int windowed_default; - -modestate_t modestate = MS_UNINIT; - -byte vid_curpal[256 * 3]; - -unsigned short d_8to16table[256]; - -int mode; - -typedef struct { - modestate_t type; - int width; - int height; - int modenum; - int fullscreen; - char modedesc[13]; -} vmode_t; - -static vmode_t modelist[MAX_MODE_LIST]; -static int nummodes; - -int aPage; // Current active display page -int vPage; // Current visible display page -int waitVRT = true; // True to wait for retrace on flip - -static vmode_t badmode; +static vid_internal_t vid_internal; static byte backingbuf[48 * 24]; -void VID_MenuDraw (void); -void VID_MenuKey (int key); - -LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -void AppActivate (BOOL fActive, BOOL minimize); - -static int VID_SetMode (int modenum, const byte *palette); - -// video commands -int VID_NumModes (void); -vmode_t *VID_GetModePtr (int modenum); -void VID_TestMode_f (void); -void VID_ForceMode_f (void); -void VID_Minimize_f (void); -void VID_Fullscreen_f (void); -void VID_Windowed_f (void); -void VID_DescribeModes_f (void); -void VID_DescribeMode_f (void); -void VID_NumModes_f (void); -void VID_DescribeCurrentMode_f (void); -char *VID_GetExtModeDescription (int mode); -char *VID_GetModeDescription (int mode); -char *VID_GetModeDescription2 (int mode); -char *VID_GetModeDescriptionMemCheck (int mode); -void VID_CheckModedescFixup (int mode); - - -/* -================ -VID_RememberWindowPos -================ -*/ -static void __attribute__ ((used)) -VID_RememberWindowPos (void) -{ - RECT rect; - - if (GetWindowRect (hWndWinQuake, &rect)) { - if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && - (rect.top < GetSystemMetrics (SM_CYSCREEN)) && - (rect.right > 0) && (rect.bottom > 0)) { - Cvar_SetValue (vid_window_x, (float) rect.left); - Cvar_SetValue (vid_window_y, (float) rect.top); - } - } -} - - -/* -================ -VID_CheckWindowXY -================ -*/ -static void -VID_CheckWindowXY (void) -{ - if ((vid_window_x->int_val > (GetSystemMetrics (SM_CXSCREEN) - 160)) || - (vid_window_y->int_val > (GetSystemMetrics (SM_CYSCREEN) - 120)) || - (vid_window_x->int_val < 0) || (vid_window_y->int_val < 0)) { - Cvar_SetValue (vid_window_x, 0.0); - Cvar_SetValue (vid_window_y, 0.0); - } -} - - -/* -================ -VID_UpdateWindowStatus -================ -*/ -void -VID_UpdateWindowStatus (int window_x, int window_y) -{ - window_rect.left = window_x; - window_rect.top = window_y; - window_rect.right = window_x + window_width; - window_rect.bottom = window_y + window_height; - window_center_x = (window_rect.left + window_rect.right) / 2; - window_center_y = (window_rect.top + window_rect.bottom) / 2; - IN_UpdateClipCursor (); -} - - -/* -================ -ClearAllStates -================ -*/ -static void -ClearAllStates (void) -{ - int i; - - // send an up event for each key, to make sure the server clears them all - for (i = 0; i < 256; i++) { - Key_Event (i, 0, false); - } - - Key_ClearStates (); - IN_ClearStates (); -} - - -/* -================ -VID_CheckAdequateMem -================ -*/ -static qboolean -VID_CheckAdequateMem (int width, int height) -{ - // there will always be enough ;) - return true; -} - - -static void -VID_InitModes (HINSTANCE hInstance) -{ - WNDCLASS wc; - HDC hdc; - -//FIXME hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_ICON2)); - - /* Register the frame class */ - wc.style = CS_OWNDC; - wc.lpfnWndProc = (WNDPROC) MainWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = 0; - wc.hCursor = LoadCursor (NULL, IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = 0; - wc.lpszClassName = "WinQuake"; - - if (!RegisterClass (&wc)) - Sys_Error ("Couldn't register window class"); - - modelist[0].type = MS_WINDOWED; - modelist[0].width = 320; - modelist[0].height = 240; - strcpy (modelist[0].modedesc, "320x240"); - modelist[0].modenum = MODE_WINDOWED; - modelist[0].fullscreen = 0; - - modelist[1].type = MS_WINDOWED; - modelist[1].width = 640; - modelist[1].height = 480; - strcpy (modelist[1].modedesc, "640x480"); - modelist[1].modenum = MODE_WINDOWED + 1; - modelist[1].fullscreen = 0; - - modelist[2].type = MS_WINDOWED; - modelist[2].width = 800; - modelist[2].height = 600; - strcpy (modelist[2].modedesc, "800x600"); - modelist[2].modenum = MODE_WINDOWED + 2; - modelist[2].fullscreen = 0; - - // automatically stretch the default mode up if > 640x480 desktop - // resolution - hdc = GetDC (NULL); - - if ((GetDeviceCaps (hdc, HORZRES) > 800) - && !COM_CheckParm ("-noautostretch")) { - vid_default = MODE_WINDOWED + 2; - } else if ((GetDeviceCaps (hdc, HORZRES) > 640) - && !COM_CheckParm ("-noautostretch")) { - vid_default = MODE_WINDOWED + 1; - } else { - vid_default = MODE_WINDOWED; - } - - // always start at the lowest mode then switch to the higher one if - // selected - vid_default = MODE_WINDOWED; - - windowed_default = vid_default; - ReleaseDC (NULL, hdc); - nummodes = 3; // reserve space for windowed mode -} - - -/* -================= -VID_GetDisplayModes -================= -*/ -static void -VID_GetDisplayModes (void) -{ - DEVMODE devmode; - int i, modenum, existingmode, originalnummodes, lowestres; - BOOL stat; - - // enumerate > 8 bpp modes - originalnummodes = nummodes; - modenum = 0; - lowestres = 99999; - - do { - stat = EnumDisplaySettings (NULL, modenum, &devmode); - - if ((devmode.dmPelsWidth <= MAXWIDTH) - && (devmode.dmPelsHeight <= MAXHEIGHT) - && (devmode.dmPelsWidth >= 320) - && (devmode.dmPelsHeight >= 240) - && (nummodes < MAX_MODE_LIST)) { - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - - if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == - DISP_CHANGE_SUCCESSFUL) { - modelist[nummodes].type = MS_FULLDIB; - modelist[nummodes].width = devmode.dmPelsWidth; - modelist[nummodes].height = devmode.dmPelsHeight; - modelist[nummodes].modenum = 0; - modelist[nummodes].fullscreen = 1; - sprintf (modelist[nummodes].modedesc, "%dx%d", - (int) devmode.dmPelsWidth, - (int) devmode.dmPelsHeight); - - // see is the mode already there - // (same dimensions but different refresh rate) - for (i = originalnummodes, existingmode = 0; - i < nummodes; i++) { - if ((modelist[nummodes].width == modelist[i].width) - && (modelist[nummodes].height == modelist[i].height)) { - existingmode = 1; - break; - } - } - - // if it's not add it to the list - if (!existingmode) { - if (modelist[nummodes].width < lowestres) - lowestres = modelist[nummodes].width; - - nummodes++; - } - } - } - - modenum++; - } while (stat); - - if (nummodes != originalnummodes) - vid_default = MODE_FULLSCREEN_DEFAULT; - else - Sys_Printf ("No fullscreen DIB modes found\n"); -} - -static void -WIN_OpenDisplay (void) -{ - VID_InitModes (global_hInstance); - VID_GetDisplayModes (); - - vid_testingmode = 0; - - // if (COM_CheckParm("-startwindowed")) - { - startwindowed = 1; - vid_default = windowed_default; - } - -//FIXME? if (hwnd_dialog) -//FIXME? DestroyWindow (hwnd_dialog); - - // sound initialization has to go here, preceded by a windowed mode set, - // so there's a window for DirectSound to work with but we're not yet - // fullscreen so the "hardware already in use" dialog is visible if it - // gets displayed - // keep the window minimized until we're ready for the first real mode set - hWndWinQuake = CreateWindowEx (ExWindowStyle, - "WinQuake", - "WinQuake", - WindowStyle, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - NULL, NULL, global_hInstance, NULL); - - if (!hWndWinQuake) - Sys_Error ("Couldn't create DIB window"); - - // compatibility - mainwindow = hWndWinQuake; - - // done - vid_mode_set = true; -//FIXME if (firsttime) S_Init (); -} - -static void -WIN_SetVidMode (unsigned width, unsigned height, const byte *palette) -{ -//FIXME SCR_StretchInit(); - - force_mode_set = true; - VID_SetMode (vid_default, palette); - force_mode_set = false; - vid_realmode = vid_modenum; - strcpy (badmode.modedesc, "Bad mode"); -} - -static void -VID_DestroyWindow (void) -{ - if (modestate == MS_FULLDIB) - ChangeDisplaySettings (NULL, CDS_FULLSCREEN); - - VID_UnloadAllDrivers (); -} - - -static qboolean -VID_SetWindowedMode (int modenum) -{ - if (!windowed_mode_set) { - if (COM_CheckParm ("-resetwinpos")) { - Cvar_SetValue (vid_window_x, 0.0); - Cvar_SetValue (vid_window_y, 0.0); - } - - windowed_mode_set = true; - } - - VID_CheckModedescFixup (modenum); - VID_DestroyWindow (); - - WindowRect.top = WindowRect.left = 0; - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - WindowStyle = WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_SIZEBOX | - WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS | - WS_CLIPCHILDREN | WS_THICKFRAME; - - // WindowStyle = WS_OVERLAPPEDWINDOW|WS_VISIBLE; - ExWindowStyle = 0; - AdjustWindowRectEx (&WindowRect, WindowStyle, FALSE, 0); - - // the first time we're called to set the mode, create the window we'll use - // for the rest of the session - if (!vid_mode_set) { - } else { - SetWindowLong (hWndWinQuake, GWL_STYLE, WindowStyle | WS_VISIBLE); - SetWindowLong (hWndWinQuake, GWL_EXSTYLE, ExWindowStyle); - } - - if (!SetWindowPos (hWndWinQuake, - NULL, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - SWP_NOCOPYBITS | SWP_NOZORDER | SWP_HIDEWINDOW)) { - Sys_Error ("Couldn't resize DIB window"); - } - - // position and show the DIB window - VID_CheckWindowXY (); - SetWindowPos (hWndWinQuake, NULL, vid_window_x->int_val, - vid_window_y->int_val, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); - - if (force_minimized) - ShowWindow (hWndWinQuake, SW_MINIMIZE); - else - ShowWindow (hWndWinQuake, SW_SHOWDEFAULT); - - UpdateWindow (hWndWinQuake); - modestate = MS_WINDOWED; - vid_fulldib_on_focus_mode = 0; - - viddef.numpages = 1; - -// viddef.height = viddef.conheight = DIBHeight; -// viddef.width = viddef.conwidth = DIBWidth; - - viddef.height = viddef.conheight = DIBHeight; - viddef.width = viddef.conwidth = DIBWidth; -//FIXME? if (!yeahimconsoled){ -//FIXME? viddef.vconheight = DIBHeight; -//FIXME? viddef.vconwidth = DIBWidth; -//FIXME? } - SendMessage (hWndWinQuake, WM_SETICON, (WPARAM) TRUE, (LPARAM) hIcon); - SendMessage (hWndWinQuake, WM_SETICON, (WPARAM) FALSE, (LPARAM) hIcon); - - return true; -} - - -static qboolean -VID_SetFullDIBMode (int modenum) -{ - VID_DestroyWindow (); - - win_gdevmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; - win_gdevmode.dmPelsWidth = modelist[modenum].width; - win_gdevmode.dmPelsHeight = modelist[modenum].height; - win_gdevmode.dmSize = sizeof (win_gdevmode); - - if (ChangeDisplaySettings (&win_gdevmode, CDS_FULLSCREEN) != - DISP_CHANGE_SUCCESSFUL) - Sys_Error ("Couldn't set fullscreen DIB mode"); - - modestate = MS_FULLDIB; - vid_fulldib_on_focus_mode = modenum; - WindowRect.top = WindowRect.left = 0; - - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; - - DIBWidth = modelist[modenum].width; - DIBHeight = modelist[modenum].height; - - WindowStyle = WS_POPUP | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - ExWindowStyle = 0; - - AdjustWindowRectEx (&WindowRect, WindowStyle, FALSE, 0); - - SetWindowLong (hWndWinQuake, GWL_STYLE, WindowStyle | WS_VISIBLE); - SetWindowLong (hWndWinQuake, GWL_EXSTYLE, ExWindowStyle); - - if (!SetWindowPos (hWndWinQuake, - NULL, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - SWP_NOCOPYBITS | SWP_NOZORDER)) { - Sys_Error ("Couldn't resize DIB window"); - } - // position and show the DIB window - SetWindowPos (hWndWinQuake, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); - ShowWindow (hWndWinQuake, SW_SHOWDEFAULT); - UpdateWindow (hWndWinQuake); - - viddef.numpages = 1; - -#ifdef SCALED2D - viddef.height = viddef.conheight = DIBHeight; - viddef.width = viddef.conwidth = DIBWidth; - // viddef.vconwidth = 320; - // viddef.vconheight = 200; -//FIXME? if (!yeahimconsoled){ -//FIXME? viddef.vconheight = DIBHeight; -//FIXME? viddef.vconwidth = DIBWidth; -//FIXME? } -#else - viddef.height = viddef.conheight = DIBHeight; - viddef.width = viddef.conwidth = DIBWidth; -#endif - - return true; -} - -static void -VID_RestoreOldMode (int original_mode) -{ - static qboolean inerror = false; - - if (inerror) - return; - - in_mode_set = false; - inerror = true; - // make sure mode set happens (video mode changes) - vid_modenum = original_mode - 1; - - if (!VID_SetMode (original_mode, vid_curpal)) { - vid_modenum = MODE_WINDOWED - 1; - - if (!VID_SetMode (windowed_default, vid_curpal)) - Sys_Error ("Can't set any video mode"); - } - - inerror = false; -} - - -static void __attribute__ ((used)) -VID_SetDefaultMode (void) -{ - if (vid_initialized) - VID_SetMode (0, vid_curpal); - - IN_DeactivateMouse (); -} - -static void -win_init_bufers (void) -{ - // set the rest of the buffers we need (why not just use one single buffer - // instead of all this crap? oh well, it's Quake...) - viddef.direct = (byte *) viddef.buffer; - viddef.conbuffer = viddef.buffer; - - // more crap for the console - viddef.conrowbytes = viddef.rowbytes; -} - -static int -VID_SetMode (int modenum, const byte *palette) -{ - int original_mode; // FIXME, temp; - qboolean stat; - MSG msg; - HDC hdc; - - while ((modenum >= nummodes) || (modenum < 0)) { - if (vid_modenum == NO_MODE) { - if (modenum == vid_default) { - modenum = windowed_default; - } else { - modenum = vid_default; - } - - Cvar_SetValue (vid_mode, (float) modenum); - } else { - Cvar_SetValue (vid_mode, (float) vid_modenum); - return 0; - } - } - - if (!force_mode_set && (modenum == vid_modenum)) - return true; - - // so Con_Printfs don't mess us up by forcing vid and snd updates -//FIXME? temp = scr_disabled_for_loading; -//FIXME? scr_disabled_for_loading = true; - in_mode_set = true; -//FIXME CDAudio_Pause (); -//FIXME S_ClearBuffer (); - - if (vid_modenum == NO_MODE) - original_mode = windowed_default; - else - original_mode = vid_modenum; - - // Set either the fullscreen or windowed mode - if (modelist[modenum].type == MS_WINDOWED) { - if (_windowed_mouse->int_val) { - stat = VID_SetWindowedMode (modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } else { - IN_DeactivateMouse (); - IN_ShowMouse (); - stat = VID_SetWindowedMode (modenum); - } - } else { - stat = VID_SetFullDIBMode (modenum); - IN_ActivateMouse (); - IN_HideMouse (); - } - - window_width = viddef.width; - window_height = viddef.height; - - - VID_UpdateWindowStatus (0, 0); // FIXME right numbers? -//FIXME CDAudio_Resume (); -//FIXME? scr_disabled_for_loading = temp; - - if (!stat) { - VID_RestoreOldMode (original_mode); - return false; - } - - // now we try to make sure we get the focus on the mode switch, because - // sometimes in some systems we don't. We grab the foreground, then - // finish setting up, pump all our messages, and sleep for a little while - // to let messages finish bouncing around the system, then we put - // ourselves at the top of the z order, then grab the foreground again, - // Who knows if it helps, but it probably doesn't hurt - if (!force_minimized) - SetForegroundWindow (hWndWinQuake); - - hdc = GetDC (NULL); - - if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) - vid_palettized = true; - else - vid_palettized = false; - - viddef.set_palette (palette); - ReleaseDC (NULL, hdc); - vid_modenum = modenum; - Cvar_SetValue (vid_mode, (float) vid_modenum); - - while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage (&msg); - DispatchMessage (&msg); - } - - Sleep (100); - - if (!force_minimized) { - SetWindowPos (hWndWinQuake, HWND_TOP, 0, 0, 0, 0, - SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | - SWP_NOCOPYBITS); - - SetForegroundWindow (hWndWinQuake); - } - // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); - - Sys_Printf ("%s\n", VID_GetModeDescription (vid_modenum)); - - viddef.set_palette (palette); - - in_mode_set = false; - - viddef.recalc_refdef = 1; - -//FIXME SCR_StretchInit(); -//FIXME SCR_StretchRefresh(); -//FIXME SCR_CvarCheck(); - return true; -} - - -static void -VID_SetPalette (const byte *palette) -{ - int i; - const byte *pal = palette; - - if (!Minimized) { - if (vid_usingddraw) { - // incoming palette is 3 component - for (i = 0; i < 256; i++, pal += 3) { - PALETTEENTRY *p = (PALETTEENTRY *) & ddpal[i]; - - p->peRed = viddef.gammatable[pal[2]]; - p->peGreen = viddef.gammatable[pal[1]]; - p->peBlue = viddef.gammatable[pal[0]]; - p->peFlags = 255; - } - } else { - RGBQUAD colors[256]; - - if (hdcDIBSection) { - // incoming palette is 3 component - for (i = 0; i < 256; i++, pal += 3) { - PALETTEENTRY *p = (PALETTEENTRY *) & ddpal[i]; - - colors[i].rgbRed = viddef.gammatable[pal[0]]; - colors[i].rgbGreen = viddef.gammatable[pal[1]]; - colors[i].rgbBlue = viddef.gammatable[pal[2]]; - colors[i].rgbReserved = 0; - - p->peRed = viddef.gammatable[pal[2]]; - p->peGreen = viddef.gammatable[pal[1]]; - p->peBlue = viddef.gammatable[pal[0]]; - p->peFlags = 255; - } - - colors[0].rgbRed = 0; - colors[0].rgbGreen = 0; - colors[0].rgbBlue = 0; - colors[255].rgbRed = 0xff; - colors[255].rgbGreen = 0xff; - colors[255].rgbBlue = 0xff; - - if (SetDIBColorTable (hdcDIBSection, 0, 256, colors) == 0) { - Sys_Printf ("DIB_SetPalette() - SetDIBColorTable failed\n"); - } - } - } - } - - memcpy (vid_curpal, palette, sizeof (vid_curpal)); -} - - -#define CVAR_ORIGINAL CVAR_NONE // FIXME -void -VID_Init_Cvars (void) -{ - gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, - "The OpenGL library to use. (path optional)"); - vid_ddraw = Cvar_Get ("vid_ddraw", "1", CVAR_ORIGINAL, 0, ""); - vid_mode = Cvar_Get ("vid_mode", "0", CVAR_ORIGINAL, 0, ""); - vid_wait = Cvar_Get ("vid_wait", "0", CVAR_ORIGINAL, 0, ""); - vid_nopageflip = - Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); - _vid_wait_override = - Cvar_Get ("_vid_wait_override", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); - _vid_default_mode = - Cvar_Get ("_vid_default_mode", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); - _vid_default_mode_win = - Cvar_Get ("_vid_default_mode_win", "3", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); - vid_config_x = - Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); - vid_config_y = - Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); - vid_stretch_by_2 = - Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); - _windowed_mouse = - Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); - vid_fullscreen_mode = - Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); - vid_windowed_mode = - Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); - block_switch = - Cvar_Get ("block_switch", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); - vid_window_x = - Cvar_Get ("vid_window_x", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); - vid_window_y = - Cvar_Get ("vid_window_y", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); -} - -static void -win_choose_visual (void) -{ -} - -static void -win_create_context (const byte *palette) -{ - HDC hdc; - - // shutdown any old driver that was active - VID_UnloadAllDrivers (); - - // because we have set the background brush for the window to NULL (to - // avoid flickering when re-sizing the window on the desktop), we clear - // the window to black when created, otherwise it will be empty while - // Quake starts up. This also prevents a screen flash to white when - // switching drivers. it still flashes, but at least it's black now - hdc = GetDC (hWndWinQuake); - PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); - ReleaseDC (hWndWinQuake, hdc); - - // create the new driver - vid_usingddraw = false; - - // attempt to create a direct draw driver - if (vid_ddraw->int_val) - VID_CreateDDrawDriver (DIBWidth, DIBHeight, palette, &viddef.buffer, - &viddef.rowbytes); - - // create a gdi driver if directdraw failed or if we preferred not to use - // it - if (!vid_usingddraw) { - // because directdraw may have been partially created we must shut it - // down again first - VID_UnloadAllDrivers (); - - // now create the gdi driver - VID_CreateGDIDriver (DIBWidth, DIBHeight, palette, &viddef.buffer, - &viddef.rowbytes); - } - // if ddraw failed to come up we disable the cvar too - if (vid_ddraw->int_val && !vid_usingddraw) - Cvar_Set (vid_ddraw, "0"); - - viddef.do_screen_buffer = win_init_bufers; - VID_InitBuffers (); -} - -void -VID_Init (byte *palette, byte *colormap) -{ - Sys_RegisterShutdown (VID_shutdown); - - choose_visual = win_choose_visual; - create_context = win_create_context; - - R_LoadModule (wgl_load_gl, VID_SetPalette); - - viddef.numpages = 1; - viddef.colormap8 = colormap; - viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; - - VID_GetWindowSize (640, 480); - WIN_OpenDisplay (); - choose_visual (); - WIN_SetVidMode (viddef.width, viddef.height, palette); - create_context (palette); - - VID_InitGamma (palette); - viddef.set_palette (palette); - - vid_initialized = true; -} - -#if 0 -Cmd_AddCommand ("vid_testmode", VID_TestMode_f, ""); -Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, ""); -Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, ""); -Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, ""); -Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, ""); -Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f, ""); -Cmd_AddCommand ("vid_windowed", VID_Windowed_f, ""); -Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f, ""); -Cmd_AddCommand ("vid_minimize", VID_Minimize_f, ""); -#endif - - -static void -VID_shutdown (void) -{ - if (vid_initialized) { - if (modestate == MS_FULLDIB) - ChangeDisplaySettings (NULL, CDS_FULLSCREEN); - - PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM) hWndWinQuake, - (LPARAM) 0); - PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM) 0, (LPARAM) 0); - AppActivate (false, false); - - VID_DestroyWindow (); - -//FIXME? if (hwnd_dialog) DestroyWindow (hwnd_dialog); - if (hWndWinQuake) - DestroyWindow (hWndWinQuake); - - vid_testingmode = 0; - vid_initialized = 0; - } -} - - -/* -================ -FlipScreen -================ -*/ -static void -FlipScreen (vrect_t *rects) -{ - int numrects = 0; - - while (rects) { - if (vid_usingddraw) { - int x, y; - HRESULT hr = S_OK; - byte *src = NULL; - unsigned *dst = NULL; - - if (dd_BackBuffer) { - RECT TheRect; - RECT sRect, dRect; - DDSURFACEDESC ddsd; - - memset (&ddsd, 0, sizeof (ddsd)); - ddsd.dwSize = sizeof (DDSURFACEDESC); - - // lock the correct subrect - TheRect.left = rects->x; - TheRect.right = rects->x + rects->width; - TheRect.top = rects->y; - TheRect.bottom = rects->y + rects->height; - - if ((hr = - IDirectDrawSurface_Lock (dd_BackBuffer, &TheRect, &ddsd, - DDLOCK_WRITEONLY | - DDLOCK_SURFACEMEMORYPTR, - NULL)) == DDERR_WASSTILLDRAWING) - return; - - src = (byte *) vidbuf + rects->y * viddef.rowbytes + rects->x; - dst = (unsigned *) ddsd.lpSurface; - - // convert pitch to unsigned int addressable - ddsd.lPitch >>= 2; - - // because we created a 32 bit backbuffer we need to copy from - // the 8 bit memory buffer to it before flipping - if (!(rects->width & 15)) { - for (y = 0; y < rects->height; - y++, src += viddef.rowbytes, dst += ddsd.lPitch) { - byte *psrc = src; - unsigned *pdst = dst; - - for (x = 0; x < rects->width; - x += 16, psrc += 16, pdst += 16) { - pdst[0] = ddpal[psrc[0]]; - pdst[1] = ddpal[psrc[1]]; - pdst[2] = ddpal[psrc[2]]; - pdst[3] = ddpal[psrc[3]]; - - pdst[4] = ddpal[psrc[4]]; - pdst[5] = ddpal[psrc[5]]; - pdst[6] = ddpal[psrc[6]]; - pdst[7] = ddpal[psrc[7]]; - - pdst[8] = ddpal[psrc[8]]; - pdst[9] = ddpal[psrc[9]]; - pdst[10] = ddpal[psrc[10]]; - pdst[11] = ddpal[psrc[11]]; - - pdst[12] = ddpal[psrc[12]]; - pdst[13] = ddpal[psrc[13]]; - pdst[14] = ddpal[psrc[14]]; - pdst[15] = ddpal[psrc[15]]; - } - } - } else if (!(rects->width % 10)) { - for (y = 0; y < rects->height; - y++, src += viddef.rowbytes, dst += ddsd.lPitch) { - byte *psrc = src; - unsigned *pdst = dst; - - for (x = 0; x < rects->width; - x += 10, psrc += 10, pdst += 10) { - pdst[0] = ddpal[psrc[0]]; - pdst[1] = ddpal[psrc[1]]; - pdst[2] = ddpal[psrc[2]]; - pdst[3] = ddpal[psrc[3]]; - pdst[4] = ddpal[psrc[4]]; - - pdst[5] = ddpal[psrc[5]]; - pdst[6] = ddpal[psrc[6]]; - pdst[7] = ddpal[psrc[7]]; - pdst[8] = ddpal[psrc[8]]; - pdst[9] = ddpal[psrc[9]]; - } - } - } else if (!(rects->width & 7)) { - for (y = 0; y < rects->height; - y++, src += viddef.rowbytes, dst += ddsd.lPitch) { - byte *psrc = src; - unsigned *pdst = dst; - - for (x = 0; x < rects->width; - x += 8, psrc += 8, pdst += 8) { - pdst[0] = ddpal[psrc[0]]; - pdst[1] = ddpal[psrc[1]]; - pdst[2] = ddpal[psrc[2]]; - pdst[3] = ddpal[psrc[3]]; - - pdst[4] = ddpal[psrc[4]]; - pdst[5] = ddpal[psrc[5]]; - pdst[6] = ddpal[psrc[6]]; - pdst[7] = ddpal[psrc[7]]; - } - } - } else if (!(rects->width % 5)) { - for (y = 0; y < rects->height; - y++, src += viddef.rowbytes, dst += ddsd.lPitch) { - byte *psrc = src; - unsigned *pdst = dst; - - for (x = 0; x < rects->width; - x += 5, psrc += 5, pdst += 5) { - pdst[0] = ddpal[psrc[0]]; - pdst[1] = ddpal[psrc[1]]; - pdst[2] = ddpal[psrc[2]]; - pdst[3] = ddpal[psrc[3]]; - pdst[4] = ddpal[psrc[4]]; - } - } - } else if (!(rects->width & 3)) { - for (y = 0; y < rects->height; - y++, src += viddef.rowbytes, dst += ddsd.lPitch) { - byte *psrc = src; - unsigned *pdst = dst; - - for (x = 0; x < rects->width; - x += 4, psrc += 4, pdst += 4) { - pdst[0] = ddpal[psrc[0]]; - pdst[1] = ddpal[psrc[1]]; - pdst[2] = ddpal[psrc[2]]; - pdst[3] = ddpal[psrc[3]]; - } - } - } else { - for (y = 0; y < rects->height; - y++, src += viddef.rowbytes, dst += ddsd.lPitch) { - for (x = 0; x < rects->width; x++) { - dst[x] = ddpal[src[x]]; - } - } - } - - IDirectDrawSurface_Unlock (dd_BackBuffer, NULL); - - // correctly offset source - sRect.left = SrcRect.left + rects->x; - sRect.right = SrcRect.left + rects->x + rects->width; - sRect.top = SrcRect.top + rects->y; - sRect.bottom = SrcRect.top + rects->y + rects->height; - - // correctly offset dest - dRect.left = DstRect.left + rects->x; - dRect.right = DstRect.left + rects->x + rects->width; - dRect.top = DstRect.top + rects->y; - dRect.bottom = DstRect.top + rects->y + rects->height; - - // copy to front buffer - IDirectDrawSurface_Blt (dd_FrontBuffer, &dRect, dd_BackBuffer, - &sRect, 0, NULL); - } - } else if (hdcDIBSection) { - BitBlt (hdcGDI, rects->x, rects->y, - rects->x + rects->width, rects->y + rects->height, - hdcDIBSection, rects->x, rects->y, SRCCOPY); - } - - numrects++; - rects = rects->next; - } -} - - void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { int i, j, reps, repshift; vrect_t rect; - if (!vid_initialized) + if (!viddef.initialized || !win_sw_context) return; if (viddef.aspect > 1.5) { @@ -1620,7 +79,7 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) rect.height = height << repshift; rect.next = NULL; - FlipScreen (&rect); + win_sw_context->update (&rect); } @@ -1630,7 +89,7 @@ D_EndDirectRect (int x, int y, int width, int height) int i, j, reps, repshift; vrect_t rect; - if (!vid_initialized) + if (!viddef.initialized || !win_sw_context) return; if (viddef.aspect > 1.5) { @@ -1658,29 +117,98 @@ D_EndDirectRect (int x, int y, int width, int height) rect.height = height << repshift; rect.next = NULL; - FlipScreen (&rect); + win_sw_context->update (&rect); +} + +static void +VID_shutdown (void *data) +{ + Sys_MaskPrintf (SYS_VID, "VID_shutdown\n"); + Win_CloseDisplay (); +} + +void +VID_Init (byte *palette, byte *colormap) +{ + Sys_RegisterShutdown (VID_shutdown, 0); + + vid_internal.gl_context = Win_GL_Context; + vid_internal.sw_context = Win_SW_Context; +#ifdef HAVE_VULKAN + vid_internal.vulkan_context = Win_Vulkan_Context; +#endif + + R_LoadModule (&vid_internal); + + viddef.numpages = 1; + viddef.colormap8 = colormap; + viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; + + VID_GetWindowSize (640, 480); + Win_OpenDisplay (); + vid_internal.choose_visual (); + Win_SetVidMode (viddef.width, viddef.height, palette); + vid_internal.create_context (); + + VID_InitGamma (palette); + viddef.vid_internal->set_palette (palette); + + Sys_MaskPrintf (SYS_VID, "Video mode %dx%d initialized.\n", + viddef.width, viddef.height); + + viddef.initialized = true; +} + +void +VID_Init_Cvars (void) +{ + Win_Init_Cvars (); +#ifdef HAVE_VULKAN + Win_Vulkan_Init_Cvars (); +#endif + Win_GL_Init_Cvars (); +} + +void +VID_LockBuffer (void) +{ +} + +void +VID_UnlockBuffer (void) +{ +} + +void +VID_SetCaption (const char *text) +{ + if (text && *text) { + char *temp = strdup (text); + + Win_SetCaption (va (0, "%s: %s", PACKAGE_STRING, temp)); + free (temp); + } else { + Win_SetCaption (va (0, "%s", PACKAGE_STRING)); + } +} + +qboolean +VID_SetGamma (double gamma) +{ + return Win_SetGamma (gamma); } +#if 0 void VID_Update (vrect_t *rects) { vrect_t rect; RECT trect; - if (!vid_palettized && palette_changed) { - palette_changed = false; - rect.x = 0; - rect.y = 0; - rect.width = viddef.width; - rect.height = viddef.height; - rect.next = NULL; - rects = ▭ - } - if (firstupdate) { if (modestate == MS_WINDOWED) { - GetWindowRect (hWndWinQuake, &trect); + GetWindowRect (win_mainwindow, &trect); if ((trect.left != vid_window_x->int_val) || (trect.top != vid_window_y->int_val)) { @@ -1690,7 +218,7 @@ VID_Update (vrect_t *rects) } VID_CheckWindowXY (); - SetWindowPos (hWndWinQuake, NULL, vid_window_x->int_val, + SetWindowPos (win_mainwindow, NULL, vid_window_x->int_val, vid_window_y->int_val, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); @@ -1763,401 +291,4 @@ VID_Update (vrect_t *rects) } } } - - -//========================================================================== - - -/* -================ -VID_HandlePause -================ -*/ -static void __attribute__ ((used)) -VID_HandlePause (qboolean pause) -{ - if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val) { - if (pause) { - IN_DeactivateMouse (); - IN_ShowMouse (); - } else { - IN_ActivateMouse (); - IN_HideMouse (); - } - } -} - - -/* -=================================================================== - -MAIN WINDOW - -=================================================================== -*/ - -typedef struct { - int modenum; - char *desc; - int iscur; - int width; -} modedesc_t; - -#define MAX_COLUMN_SIZE 5 -#define MODE_AREA_HEIGHT (MAX_COLUMN_SIZE + 6) -#define MAX_MODEDESCS (MAX_COLUMN_SIZE*3) - -//static modedesc_t modedescs[MAX_MODEDESCS]; - -/* -================= -VID_NumModes -================= -*/ -int -VID_NumModes (void) -{ - return nummodes; -} - - -/* -================= -VID_GetModePtr -================= -*/ -vmode_t * -VID_GetModePtr (int modenum) -{ - if ((modenum >= 0) && (modenum < nummodes)) - return &modelist[modenum]; - else - return &badmode; -} - - -/* -================= -VID_CheckModedescFixup -================= -*/ -void -VID_CheckModedescFixup (int mode) -{ -} - - -/* -================= -VID_GetModeDescriptionMemCheck -================= -*/ -char * -VID_GetModeDescriptionMemCheck (int mode) -{ - char *pinfo; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - - if (VID_CheckAdequateMem (pv->width, pv->height)) { - return pinfo; - } else { - return NULL; - } -} - - -/* -================= -VID_GetModeDescription -================= -*/ -char * -VID_GetModeDescription (int mode) -{ - char *pinfo; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - pv = VID_GetModePtr (mode); - pinfo = pv->modedesc; - return pinfo; -} - - -/* -================= -VID_GetModeDescription2 - -Tacks on "windowed" or "fullscreen" -================= -*/ -char * -VID_GetModeDescription2 (int mode) -{ - static char pinfo[40]; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - pv = VID_GetModePtr (mode); - - if (modelist[mode].type == MS_FULLSCREEN) { - sprintf (pinfo, "%s fullscreen", pv->modedesc); - } else if (modelist[mode].type == MS_FULLDIB) { - sprintf (pinfo, "%s fullscreen", pv->modedesc); - } else { - sprintf (pinfo, "%s windowed", pv->modedesc); - } - - return pinfo; -} - - -// KJB: Added this to return the mode driver name in description for console - -char * -VID_GetExtModeDescription (int mode) -{ - static char pinfo[40]; - vmode_t *pv; - - if ((mode < 0) || (mode >= nummodes)) - return NULL; - - VID_CheckModedescFixup (mode); - pv = VID_GetModePtr (mode); - - if (modelist[mode].type == MS_FULLDIB) { - sprintf (pinfo, "%s fullscreen", pv->modedesc); - } else { - sprintf (pinfo, "%s windowed", pv->modedesc); - } - - return pinfo; -} - - -/* -================= -VID_DescribeCurrentMode_f -================= -*/ -void -VID_DescribeCurrentMode_f (void) -{ - Sys_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); -} - - -/* -================= -VID_NumModes_f -================= -*/ -void -VID_NumModes_f (void) -{ - if (nummodes == 1) - Sys_Printf ("%d video mode is available\n", nummodes); - else - Sys_Printf ("%d video modes are available\n", nummodes); -} - - -/* -================= -VID_DescribeMode_f -================= -*/ -void -VID_DescribeMode_f (void) -{ - int modenum; - - modenum = atoi (Cmd_Argv (1)); - Sys_Printf ("%s\n", VID_GetExtModeDescription (modenum)); -} - - -/* -================= -VID_DescribeModes_f -================= -*/ -void -VID_DescribeModes_f (void) -{ - int i, lnummodes; - char *pinfo; - qboolean na; - vmode_t *pv; - - na = false; - lnummodes = VID_NumModes (); - - for (i = 0; i < lnummodes; i++) { - pv = VID_GetModePtr (i); - pinfo = VID_GetExtModeDescription (i); - - if (VID_CheckAdequateMem (pv->width, pv->height)) { - Sys_Printf ("%2d: %s\n", i, pinfo); - } else { - Sys_Printf ("**: %s\n", pinfo); - na = true; - } - } - - if (na) { - Sys_Printf ("\n[**: not enough system RAM for mode]\n"); - } -} - - -/* -================= -VID_TestMode_f -================= -*/ -void -VID_TestMode_f (void) -{ - int modenum; - double testduration; - - if (!vid_testingmode) { - modenum = atoi (Cmd_Argv (1)); - - if (VID_SetMode (modenum, vid_curpal)) { - vid_testingmode = 1; - testduration = atof (Cmd_Argv (2)); - - if (testduration == 0) - testduration = 5.0; - - vid_testendtime = Sys_DoubleTime () + testduration; - } - } -} - - -/* -================= -VID_Windowed_f -================= -*/ -void -VID_Windowed_f (void) -{ - VID_SetMode (vid_windowed_mode->int_val, vid_curpal); -} - - -/* -================= -VID_Fullscreen_f -================= -*/ -void -VID_Fullscreen_f (void) -{ - VID_SetMode (vid_fullscreen_mode->int_val, vid_curpal); -} - - -/* -================= -VID_Minimize_f -================= -*/ -void -VID_Minimize_f (void) -{ - // we only support minimizing windows; if you're fullscreen, - // switch to windowed first - if (modestate == MS_WINDOWED) - ShowWindow (hWndWinQuake, SW_MINIMIZE); -} - - - -/* -================= -VID_ForceMode_f -================= -*/ -void -VID_ForceMode_f (void) -{ - int modenum; - - if (!vid_testingmode) { - modenum = atoi (Cmd_Argv (1)); - force_mode_set = 1; - VID_SetMode (modenum, vid_curpal); - force_mode_set = 0; - } -} - -void -VID_SetCaption (const char *text) -{ - if (text && *text) { - char *temp = strdup (text); - - SetWindowText (mainwindow, (LPSTR) va ("%s: %s", PACKAGE_STRING, temp)); - free (temp); - } else { - SetWindowText (mainwindow, (LPSTR) va ("%s", PACKAGE_STRING)); - } -} - -//static WORD systemgammaramps[3][256]; -static WORD currentgammaramps[3][256]; - -qboolean -VID_SetGamma (double gamma) -{ - int i; - HDC hdc = GetDC (NULL); - - for (i = 0; i < 256; i++) { - currentgammaramps[2][i] = currentgammaramps[1][i] = - currentgammaramps[0][i] = viddef.gammatable[i] * 256; - } - - i = SetDeviceGammaRamp (hdc, ¤tgammaramps[0][0]); - ReleaseDC (NULL, hdc); - return i; -} - -#if 0 -static void -VID_SaveGamma (void) -{ - HDC hdc = GetDC (NULL); - - GetDeviceGammaRamp (hdc, &systemgammaramps[0][0]); - ReleaseDC (NULL, hdc); -} - -static void -VID_RestoreGamma (void) -{ - HDC hdc = GetDC (NULL); - - SetDeviceGammaRamp (hdc, &systemgammaramps[0][0]); - ReleaseDC (NULL, hdc); -} #endif diff --git a/libs/video/targets/vid_win_gl.c b/libs/video/targets/vid_win_gl.c new file mode 100644 index 000000000..7a194d49b --- /dev/null +++ b/libs/video/targets/vid_win_gl.c @@ -0,0 +1,185 @@ +/* + vid_win_gl.c + + Win32 GL vid component + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "winquake.h" +#include + +#include "QF/cvar.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_win.h" +#include "r_internal.h" +#include "vid_internal.h" +#include "vid_gl.h" + +// Define GLAPIENTRY to a useful value +#ifndef GLAPIENTRY +# define GLAPIENTRY WINAPI +#endif +static void *libgl_handle; +static HGLRC (GLAPIENTRY * qfwglCreateContext) (HDC); +static BOOL (GLAPIENTRY * qfwglDeleteContext) (HGLRC); +static HGLRC (GLAPIENTRY * qfwglGetCurrentContext) (void); +static HDC (GLAPIENTRY * qfwglGetCurrentDC) (void); +static BOOL (GLAPIENTRY * qfwglMakeCurrent) (HDC, HGLRC); +static void (GLAPIENTRY *qfglFinish) (void); +static void *(WINAPI * glGetProcAddress) (const char *symbol) = NULL; +static int use_gl_proceaddress = 0; + +static cvar_t *gl_driver; +static HGLRC baseRC;//FIXME should be in gl_ctx_t, but that's GLXContext... +static void * +QFGL_GetProcAddress (void *handle, const char *name) +{ + void *glfunc = NULL; + + if (use_gl_proceaddress && glGetProcAddress) + glfunc = glGetProcAddress (name); + if (!glfunc) + glfunc = GetProcAddress (handle, name); + return glfunc; +} + +static void * +QFGL_ProcAddress (const char *name, qboolean crit) +{ + void *glfunc = NULL; + + Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); + + glfunc = QFGL_GetProcAddress (libgl_handle, name); + if (glfunc) { + Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); + return glfunc; + } + Sys_MaskPrintf (SYS_VID, "not found\n"); + + if (crit) { + Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", + name); + } + return NULL; +} + +static void +wgl_choose_visual (gl_ctx_t *ctx) +{ +} + +static void +wgl_create_context (gl_ctx_t *ctx) +{ + DWORD lasterror; + + Sys_Printf ("maindc: %p\n", win_maindc); + baseRC = qfwglCreateContext (win_maindc); + if (!baseRC) { + lasterror=GetLastError(); + if (win_maindc && win_mainwindow) + ReleaseDC (win_mainwindow, win_maindc); + Sys_Error ("Could not initialize GL (wglCreateContext failed).\n\n" + "Make sure you are in 65535 color mode, and try running " + "with -window.\n" + "Error code: (%lx)", lasterror); + } + + if (!qfwglMakeCurrent (win_maindc, baseRC)) { + lasterror = GetLastError (); + if (baseRC) + qfwglDeleteContext (baseRC); + if (win_maindc && win_mainwindow) + ReleaseDC (win_mainwindow, win_maindc); + Sys_Error ("wglMakeCurrent failed (%lx)", lasterror); + } + + ctx->init_gl (); +} + +static void +wgl_end_rendering (void) +{ + if (!scr_skipupdate) { + qfglFinish (); + SwapBuffers (win_maindc); + } + // handle the mouse state when windowed if that's changed + if (!vid_fullscreen->int_val) { +//FIXME if (!in_grab->int_val) { +//FIXME if (windowed_mouse) { +//FIXME IN_DeactivateMouse (); +//FIXME IN_ShowMouse (); +//FIXME windowed_mouse = false; +//FIXME } +//FIXME } else { +//FIXME windowed_mouse = true; +//FIXME } + } +} + +static void +wgl_load_gl (void) +{ + libgl_handle = LoadLibrary (gl_driver->string); + if (!libgl_handle) { + Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); + } + glGetProcAddress = + (void *) GetProcAddress (libgl_handle, "wglGetProcAddress"); + + qfwglCreateContext = QFGL_ProcAddress ("wglCreateContext", true); + qfwglDeleteContext = QFGL_ProcAddress ("wglDeleteContext", true); + qfwglGetCurrentContext = QFGL_ProcAddress ("wglGetCurrentContext", true); + qfwglGetCurrentDC = QFGL_ProcAddress ("wglGetCurrentDC", true); + qfwglMakeCurrent = QFGL_ProcAddress ("wglMakeCurrent", true); + + use_gl_proceaddress = 1; + + qfglFinish = QFGL_ProcAddress ("glFinish", true); +} + +gl_ctx_t * +Win_GL_Context (void) +{ + gl_ctx_t *ctx = calloc (1, sizeof (gl_ctx_t)); + ctx->load_gl = wgl_load_gl; + ctx->choose_visual = wgl_choose_visual; + ctx->create_context = wgl_create_context; + ctx->get_proc_address = QFGL_ProcAddress; + ctx->end_rendering = wgl_end_rendering; + return ctx; +} + +void +Win_GL_Init_Cvars (void) +{ + gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, + "The OpenGL library to use. (path optional)"); +} diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c new file mode 100644 index 000000000..a869f273d --- /dev/null +++ b/libs/video/targets/vid_win_sw.c @@ -0,0 +1,234 @@ +/* + vid_win.c + + Win32 SW vid component + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "winquake.h" +#include + +#include "QF/cvar.h" +#include "QF/qargs.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_win.h" +#include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" + +typedef union { + byte bgra[4]; + uint32_t value; +} win_palette_t; + +static win_palette_t st2d_8to32table[256]; +static byte current_palette[768]; +static int palette_changed; + +static void +win_init_bufers (void) +{ + // set the rest of the buffers we need (why not just use one single buffer + // instead of all this crap? oh well, it's Quake...) + viddef.direct = viddef.buffer; + viddef.conbuffer = viddef.buffer; + + // more crap for the console + viddef.conrowbytes = viddef.rowbytes; +} + +static void +win_set_palette (const byte *palette) +{ + palette_changed = 1; + if (palette != current_palette) { + memcpy (current_palette, palette, sizeof (current_palette)); + } + for (int i = 0; i < 256; i++) { + const byte *pal = palette + 3 * i; + st2d_8to32table[i].bgra[0] = viddef.gammatable[pal[2]]; + st2d_8to32table[i].bgra[1] = viddef.gammatable[pal[1]]; + st2d_8to32table[i].bgra[2] = viddef.gammatable[pal[0]]; + st2d_8to32table[i].bgra[3] = 255; + } + if (!Minimized && !win_using_ddraw && win_dib_section) { + RGBQUAD colors[256]; + memcpy (colors, st2d_8to32table, sizeof (colors)); + for (int i = 0; i < 256; i++) { + colors[i].rgbReserved = 0; + } + colors[0].rgbRed = 0; + colors[0].rgbGreen = 0; + colors[0].rgbBlue = 0; + colors[255].rgbRed = 0xff; + colors[255].rgbGreen = 0xff; + colors[255].rgbBlue = 0xff; + + if (SetDIBColorTable (win_dib_section, 0, 256, colors) == 0) { + Sys_Printf ("win_set_palette() - SetDIBColorTable failed\n"); + } + } +} + +static void +dd_blit_rect (vrect_t *rect) +{ + RECT TheRect; + RECT sRect, dRect; + DDSURFACEDESC ddsd; + + memset (&ddsd, 0, sizeof (ddsd)); + ddsd.dwSize = sizeof (DDSURFACEDESC); + + // lock the correct subrect + TheRect.left = rect->x; + TheRect.right = rect->x + rect->width; + TheRect.top = rect->y; + TheRect.bottom = rect->y + rect->height; + + if (IDirectDrawSurface_Lock (win_dd_backbuffer, &TheRect, &ddsd, + DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR, + NULL) == DDERR_WASSTILLDRAWING) { + return; + } + + // convert pitch to 32-bit addressable + ddsd.lPitch >>= 2; + + byte *src = viddef.buffer + rect->y * viddef.rowbytes + rect->x; + unsigned *dst = ddsd.lpSurface; + for (int y = rect->height; y-- > 0; ) { + for (int x = rect->width; x-- > 0; ) { + *dst++ = st2d_8to32table[*src++].value; + } + src += viddef.rowbytes - rect->width; + dst += ddsd.lPitch - rect->width; + } + + IDirectDrawSurface_Unlock (win_dd_backbuffer, NULL); + + // correctly offset source + sRect.left = win_src_rect.left + rect->x; + sRect.right = win_src_rect.left + rect->x + rect->width; + sRect.top = win_src_rect.top + rect->y; + sRect.bottom = win_src_rect.top + rect->y + rect->height; + + // correctly offset dest + dRect.left = win_dst_rect.left + rect->x; + dRect.right = win_dst_rect.left + rect->x + rect->width; + dRect.top = win_dst_rect.top + rect->y; + dRect.bottom = win_dst_rect.top + rect->y + rect->height; + + // copy to front buffer + IDirectDrawSurface_Blt (win_dd_frontbuffer, &dRect, win_dd_backbuffer, + &sRect, 0, NULL); +} + +static void +win_sw_update (vrect_t *rects) +{ + vrect_t full_rect; + if (!win_palettized && palette_changed) { + palette_changed = false; + full_rect.x = 0; + full_rect.y = 0; + full_rect.width = viddef.width; + full_rect.height = viddef.height; + full_rect.next = 0; + rects = &full_rect; + } + + if (win_using_ddraw) { + while (rects) { + dd_blit_rect (rects); + rects = rects->next; + } + } else if (win_dib_section) { + while (rects) { + BitBlt (win_gdi, rects->x, rects->y, + rects->x + rects->width, rects->y + rects->height, + win_dib_section, rects->x, rects->y, SRCCOPY); + rects = rects->next; + } + } +} + + +static void +win_choose_visual (sw_ctx_t *ctx) +{ +} + +static void +win_set_background (void) +{ + // because we have set the background brush for the window to NULL (to + // avoid flickering when re-sizing the window on the desktop), we clear + // the window to black when created, otherwise it will be empty while + // Quake starts up. This also prevents a screen flash to white when + // switching drivers. it still flashes, but at least it's black now + HDC hdc = GetDC (win_mainwindow); + PatBlt (hdc, 0, 0, win_window_rect.right, win_window_rect.bottom, + BLACKNESS); + ReleaseDC (win_mainwindow, hdc); +} + +static void +win_create_context (sw_ctx_t *ctx) +{ + // shutdown any old driver that was active + Win_UnloadAllDrivers (); + + win_sw_context = ctx; + + win_set_background (); + + // create the new driver + win_using_ddraw = false; + + Win_CreateDriver (); + + viddef.vid_internal->do_screen_buffer = win_init_bufers; + VID_InitBuffers (); +} + +sw_ctx_t * +Win_SW_Context (void) +{ + sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); + ctx->set_palette = win_set_palette; + ctx->choose_visual = win_choose_visual; + ctx->create_context = win_create_context; + ctx->update = win_sw_update; + return ctx; +} + +void +Win_SW_Init_Cvars (void) +{ +} diff --git a/libs/video/targets/vid_win_vulkan.c b/libs/video/targets/vid_win_vulkan.c new file mode 100644 index 000000000..2ec53343e --- /dev/null +++ b/libs/video/targets/vid_win_vulkan.c @@ -0,0 +1,145 @@ +/* + vid_win.c + + Win32 vid component + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "winquake.h" + +#include "QF/cvar.h" +#include "QF/set.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "QF/Vulkan/instance.h" + +#include "context_win.h" +#include "vid_internal.h" +#include "vid_vulkan.h" + +static cvar_t *vulkan_library_name; + +typedef struct vulkan_presentation_s { +#define PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; +#include "QF/Vulkan/funclist.h" + + set_t *usable_visuals; +} vulkan_presentation_t; + +static const char *required_extensions[] = { + 0 +}; + +static HMODULE vulkan_library; + +static void +load_vulkan_library (vulkan_ctx_t *ctx) +{ + vulkan_library = LoadLibrary (vulkan_library_name->string); + if (!vulkan_library) { + DWORD errcode = GetLastError (); + Sys_Error ("Couldn't load vulkan library %s: %ld", + vulkan_library_name->string, errcode); + } + + #define EXPORTED_VULKAN_FUNCTION(name) \ + ctx->name = (PFN_##name) GetProcAddress (vulkan_library, #name); \ + if (!ctx->name) { \ + Sys_Error ("Couldn't find exported vulkan function %s", #name); \ + } + + #define GLOBAL_LEVEL_VULKAN_FUNCTION(name) \ + ctx->name = (PFN_##name) ctx->vkGetInstanceProcAddr (0, #name); \ + if (!ctx->name) { \ + Sys_Error ("Couldn't find global-level function %s", #name); \ + } + + #include "QF/Vulkan/funclist.h" +} + +static void +unload_vulkan_library (vulkan_ctx_t *ctx) +{ + FreeLibrary (vulkan_library); + vulkan_library = 0; +} + +static void +win_vulkan_init_presentation (vulkan_ctx_t *ctx) +{ +} + +static int +win_vulkan_get_presentation_support (vulkan_ctx_t *ctx, + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex) +{ + if (!ctx->presentation) { + win_vulkan_init_presentation (ctx); + } + vulkan_presentation_t *pres = ctx->presentation; + return !set_is_empty (pres->usable_visuals); +} + +static void +win_vulkan_choose_visual (vulkan_ctx_t *ctx) +{ +} + +static void +win_vulkan_create_window (vulkan_ctx_t *ctx) +{ +} + +static VkSurfaceKHR +win_vulkan_create_surface (vulkan_ctx_t *ctx) +{ + return 0; +} + +vulkan_ctx_t * +Win_Vulkan_Context (void) +{ + vulkan_ctx_t *ctx = calloc (1, sizeof (vulkan_ctx_t)); + ctx->load_vulkan = load_vulkan_library; + ctx->unload_vulkan = unload_vulkan_library; + ctx->get_presentation_support = win_vulkan_get_presentation_support; + ctx->choose_visual = win_vulkan_choose_visual; + ctx->create_window = win_vulkan_create_window; + ctx->create_surface = win_vulkan_create_surface; + ctx->required_extensions = required_extensions; + ctx->va_ctx = va_create_context (4); + return ctx; +} + +void +Win_Vulkan_Init_Cvars (void) +{ + vulkan_library_name = Cvar_Get ("vulkan_library", "vulkan-1.dll", + CVAR_ROM, 0, + "the name of the vulkan shared library"); +} diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index 28b2f3294..6dca344ab 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -65,19 +65,17 @@ typedef XID GLXDrawable; +// GLXContext is a pointer to opaque data +typedef struct __GLXcontextRec *GLXContext; + + // Define GLAPIENTRY to a useful value #ifndef GLAPIENTRY -# ifdef _WIN32 -# include -# define GLAPIENTRY WINAPI -# undef LoadImage -# else # ifdef APIENTRY # define GLAPIENTRY APIENTRY # else # define GLAPIENTRY # endif -# endif #endif static void *libgl_handle; static void (*qfglXSwapBuffers) (Display *dpy, GLXDrawable drawable); @@ -155,8 +153,9 @@ static void glx_create_context (gl_ctx_t *ctx) { XSync (x_disp, 0); - ctx->context = qfglXCreateContext (x_disp, x_visinfo, NULL, True); - qfglXMakeCurrent (x_disp, x_win, ctx->context); + ctx->context = (GL_context) qfglXCreateContext (x_disp, x_visinfo, NULL, + True); + qfglXMakeCurrent (x_disp, x_win, (GLXContext) ctx->context); ctx->init_gl (); } diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 9c734a635..a04900585 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -188,7 +188,7 @@ xlib_rgb24 (int r, int g, int b) } static void -VID_SetPalette (const byte *palette) +x11_set_palette (const byte *palette) { int i; XColor colors[256]; @@ -529,7 +529,7 @@ sw_ctx_t * X11_SW_Context (void) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); - ctx->set_palette = VID_SetPalette; + ctx->set_palette = x11_set_palette; ctx->choose_visual = x11_choose_visual; ctx->create_context = x11_create_context; ctx->update = x11_sw_update; diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 6caa9fe32..2288bd20c 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -31,7 +31,7 @@ # bin_PROGRAMS += @NQ_TARGETS@ -EXTRA_PROGRAMS += nq-fbdev nq-sdl nq-svga nq-wgl nq-x11 nq-server +EXTRA_PROGRAMS += nq-fbdev nq-sdl nq-svga nq-win nq-x11 nq-server noinst_LIBRARIES += @nq_libs@ EXTRA_LIBRARIES += nq/source/libnq_client.a nq/source/libnq_common.a nq/source/libnq_sdl.a nq/source/libnq_server.a @@ -140,16 +140,17 @@ nq_x11_DEPENDENCIES= $(nq_x11_libs) # OpenGL-using targets # ... SGI/Microsoft WGL (Windows OpenGL) -nq_wgl_libs= \ +nq_win_libs= \ $(nq_client_libs) \ $(nq_cl_plugin_LIBS) \ - $(opengl_QFLIBS) \ - libs/video/targets/libQFwgl.la \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFwin.la \ $(nq_client_LIBS) -nq_wgl_SOURCES= nq/source/sys_win.c -nq_wgl_LDADD= $(nq_wgl_libs) -lgdi32 -lcomctl32 -lwinmm $(NET_LIBS) -nq_wgl_LDFLAGS= $(common_ldflags) -nq_wgl_DEPENDENCIES= $(nq_wgl_libs) +nq_win_SOURCES= nq/source/sys_win.c +nq_win_LDADD= $(nq_win_libs) -lgdi32 -lcomctl32 -lwinmm $(NET_LIBS) +nq_win_LDFLAGS= $(common_ldflags) +nq_win_DEPENDENCIES= $(nq_win_libs) # Dedicated Server if SYSTYPE_WIN32 diff --git a/nq/source/sys_sdl.c b/nq/source/sys_sdl.c index ddc4a8df7..76e84b558 100644 --- a/nq/source/sys_sdl.c +++ b/nq/source/sys_sdl.c @@ -55,7 +55,7 @@ #include "nq/include/host.h" #ifdef _WIN32 -# include "nq/include/winquake.h" +# include "winquake.h" #endif int qf_sdl_link; @@ -123,6 +123,11 @@ SDL_main (int argc, char *argv[]) fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | O_NONBLOCK); Sys_Printf ("Quake -- Version %s\n", NQ_VERSION); } +#else + // hack to prevent gcc suggesting noreturn + if (!sys_nostdout) { + return 1; + } #endif oldtime = Sys_DoubleTime () - 0.1; diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index bad7bd189..7e9c1a61c 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -30,7 +30,7 @@ bin_PROGRAMS += @QW_TARGETS@ EXTRA_PROGRAMS += \ - qw-client-fbdev qw-client-sdl qw-client-svga qw-client-wgl qw-client-x11 \ + qw-client-fbdev qw-client-sdl qw-client-svga qw-client-win qw-client-x11 \ qw-server qw-master noinst_LIBRARIES += @qw_libs@ @@ -164,13 +164,14 @@ qw_client_x11_LDFLAGS= $(common_ldflags) qw_client_x11_DEPENDENCIES= $(qw_client_x11_libs) # ... SGI/Microsoft WGL (Windows OpenGL) -qw_client_wgl_libs= \ +qw_client_win_libs= \ $(qw_client_libs) \ $(qw_cl_plugin_LIBS) \ - $(opengl_LIBS) \ - libs/video/targets/libQFwgl.la \ + libs/video/renderer/libQFrenderer.la \ + libs/models/libQFmodels.la \ + libs/video/targets/libQFwin.la \ $(qw_client_LIBS) -qw_client_wgl_SOURCES= qw/source/cl_sys_win.c -qw_client_wgl_LDADD= $(qw_client_wgl_libs) -lgdi32 -lwinmm $(NET_LIBS) $(LIBCURL_LIBS) -qw_client_wgl_LDFLAGS= $(common_ldflags) -qw_client_wgl_DEPENDENCIES= $(qw_client_wgl_libs) +qw_client_win_SOURCES= qw/source/cl_sys_win.c +qw_client_win_LDADD= $(qw_client_win_libs) -lgdi32 -lwinmm $(NET_LIBS) $(LIBCURL_LIBS) +qw_client_win_LDFLAGS= $(common_ldflags) +qw_client_win_DEPENDENCIES= $(qw_client_win_libs) diff --git a/qw/source/cl_sys_sdl.c b/qw/source/cl_sys_sdl.c index c3b620ca8..0959b94cc 100644 --- a/qw/source/cl_sys_sdl.c +++ b/qw/source/cl_sys_sdl.c @@ -118,6 +118,11 @@ SDL_main (int argc, char *argv[]) #ifndef _WIN32 if (!COM_CheckParm ("-noconinput")) fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | O_NONBLOCK); +#else + // hack to prevent gcc suggesting noreturn + if (!sys_nostdout) { + return 1; + } #endif Sys_RegisterShutdown (Host_Shutdown, 0); Sys_RegisterShutdown (Net_LogStop, 0); diff --git a/ruamoko/cl_menu/Makemodule.am b/ruamoko/cl_menu/Makemodule.am index c6c57aa7a..90dcbb5ba 100644 --- a/ruamoko/cl_menu/Makemodule.am +++ b/ruamoko/cl_menu/Makemodule.am @@ -41,7 +41,7 @@ ruamoko/cl_menu/menu.dat$(EXEEXT): $(ruamoko_menu_obj) $(QFCC_DEP) ruamoko/lib/l include $(ruamoko_menu_dep) # am--include-marker r_depfiles_remade += $(ruamoko_menu_dep) -ruamoko/cl_menu/menu.sym: ruamoko/cl_menu/menu.dat +ruamoko/cl_menu/menu.sym: ruamoko/cl_menu/menu.dat$(EXEEXT) EXTRA_DIST += \ ruamoko/cl_menu/CrosshairCvar.h \ diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 781db5c76..1626d661b 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -57,7 +57,7 @@ ruamoko_qwaq_qwaq_curses_SOURCES= \ $e ruamoko_qwaq_qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ - $(PANEL_LIBS) $(CURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) + $(PANEL_LIBS) $(NCURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) ruamoko_qwaq_qwaq_curses_LDFLAGS= ruamoko_qwaq_qwaq_curses_DEPENDENCIES= $(qwaq_curses_libs) $(QWAQ_DEPS) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 7da55d4e2..976a15ee7 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -659,7 +659,7 @@ dump_command (qwaq_resources_t *res, int len) } void -qwaq_init_timeout (struct timespec *timeout, long time) +qwaq_init_timeout (struct timespec *timeout, int64_t time) { #define SEC 1000000000L struct timeval now; diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index a8c56f280..741bd8a91 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -31,14 +31,12 @@ # include "config.h" #endif -#include #include #include #include #include #include #include -#include #include #include "QF/dstring.h" diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index ce47b1914..afe96a2ec 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -31,16 +31,19 @@ # include "config.h" #endif -#include #include #include #include #include #include #include -#include #include +#ifdef HAVE_SIGACTION // no sigaction, no window resize +#include +#include +#endif + #include "QF/dstring.h" #include "QF/hash.h" #include "QF/keys.h" @@ -164,6 +167,7 @@ static qwaq_key_t default_keys[] = { { "\033[1;6D", QFK_LEFT, 5 }, }; +#ifdef HAVE_SIGACTION static struct sigaction save_winch; static sigset_t winch_mask; static volatile sig_atomic_t winch_arrived; @@ -173,6 +177,7 @@ handle_winch (int sig) { winch_arrived = 1; } +#endif int qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event) @@ -196,7 +201,7 @@ qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event) } pthread_mutex_lock (&res->event_cond.mut); - qwaq_init_timeout (&timeout, 5000 * 1000000L); + qwaq_init_timeout (&timeout, 5000 * (int64_t) 1000000); while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret == 0) { ret = pthread_cond_timedwait (&res->event_cond.wcond, &res->event_cond.mut, &timeout); @@ -207,6 +212,7 @@ qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event) return ret; } +#ifdef HAVE_SIGACTION static void resize_event (qwaq_resources_t *res) { @@ -220,6 +226,7 @@ resize_event (qwaq_resources_t *res) event.resize.height = size.ws_row; qwaq_add_event (res, &event); } +#endif static void key_event (qwaq_resources_t *res, int key, unsigned shift) @@ -428,11 +435,13 @@ void qwaq_input_init (qwaq_resources_t *res) Hash_Add (res->key_sequences, &default_keys[i]); } +#ifdef HAVE_SIGACTION sigemptyset (&winch_mask); sigaddset (&winch_mask, SIGWINCH); struct sigaction action = {}; action.sa_handler = handle_winch; sigaction (SIGWINCH, &action, &save_winch); +#endif // ncurses takes care of input mode for us, so need only tell xterm // what we need @@ -447,13 +456,16 @@ void qwaq_input_shutdown (qwaq_resources_t *res) write(1, SGR_OFF, sizeof (SGR_OFF) - 1); write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); +#ifdef HAVE_SIGACTION sigaction (SIGWINCH, &save_winch, 0); +#endif } void qwaq_process_input (qwaq_resources_t *res) { char buf[256]; int len; +#ifdef HAVE_SIGACTION sigset_t save_set; int saw_winch; @@ -464,6 +476,7 @@ void qwaq_process_input (qwaq_resources_t *res) if (saw_winch) { resize_event (res); } +#endif while (Sys_CheckInput (1, -1)) { len = read(0, buf, sizeof (buf)); for (int i = 0; i < len; i++) { diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index f8800df93..7e4e7f5b4 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -52,6 +52,8 @@ #include "QF/va.h" #include "QF/zone.h" +#include "compat.h" + #include "ruamoko/qwaq/qwaq.h" #include "ruamoko/qwaq/debugger/debug.h" diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 43efc4700..dc7b6f668 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -1,6 +1,8 @@ #ifndef __qwaq_h #define __qwaq_h +#include + #include "QF/darray.h" #include "QF/progs.h" #include "QF/sys.h" diff --git a/ruamoko/qwaq/ui/curses.h b/ruamoko/qwaq/ui/curses.h index f3038365e..538157f58 100644 --- a/ruamoko/qwaq/ui/curses.h +++ b/ruamoko/qwaq/ui/curses.h @@ -201,7 +201,7 @@ typedef struct qwaq_resources_s { void qwaq_input_init (qwaq_resources_t *res); void qwaq_input_shutdown (qwaq_resources_t *res); void qwaq_process_input (qwaq_resources_t *res); -void qwaq_init_timeout (struct timespec *timeout, long time); +void qwaq_init_timeout (struct timespec *timeout, int64_t time); int qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event); void qwaq_init_cond (rwcond_t *cond); #endif diff --git a/tools/carne/main.c b/tools/carne/main.c index 8ecc723cd..db45b88aa 100644 --- a/tools/carne/main.c +++ b/tools/carne/main.c @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include diff --git a/tools/cross/mingw64/cross-configure.sh b/tools/cross/mingw64/cross-configure.sh index b9aa14371..7a886f631 100755 --- a/tools/cross/mingw64/cross-configure.sh +++ b/tools/cross/mingw64/cross-configure.sh @@ -1,19 +1,20 @@ #!/bin/sh -x set -e -mkdir -p native i686-w64-mingw32.static +mkdir -p native x86_64-w64-mingw32.static cd native ../../configure \ + --enable-silent-rules \ --disable-shared \ --without-clients \ --without-servers \ - --with-tools=qfcc,pak -cd ../i686-w64-mingw32.static + --with-tools=qfcc,pak,qwaq +cd ../x86_64-w64-mingw32.static export MINGW=/opt/mxe -export MINGW_USR=$MINGW/usr/i686-w64-mingw32.static +export MINGW_USR=$MINGW/usr/x86_64-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH ../../configure \ - --host=i686-w64-mingw32.static \ + --host=x86_64-w64-mingw32.static \ --disable-shared \ $* diff --git a/tools/cross/mingw64/cross-make.sh b/tools/cross/mingw64/cross-make.sh index 9ecef230e..6282f1cef 100755 --- a/tools/cross/mingw64/cross-make.sh +++ b/tools/cross/mingw64/cross-make.sh @@ -3,14 +3,15 @@ set -e if test -d native; then cd native make $* - cd ../x86_64-w64-mingw32 - ln -fs ../native/tools/qfcc/source/qfcc . - ln -fs ../native/tools/pak/pak . + cd ../x86_64-w64-mingw32.static + ln -fs ../native/qfcc . + ln -fs ../native/pak . + ln -fs ../native/ruamoko/qwaq/qwaq-curses . fi export MINGW=/opt/mxe -export MINGW_USR=$MINGW/usr/x86_64-w64-mingw32 +export MINGW_USR=$MINGW/usr/x86_64-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH -make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' $* +make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ_CURSES='$(top_builddir)/qwaq-curses' $* diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index 97b4eeb5c..76e3f73d8 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -2,7 +2,7 @@ QFCC_LIBS=@QFCC_LIBS@ QFCC_DEPS=@QFCC_DEPS@ QFCC_INCS=@QFCC_INCS@ -EXTRA_PROGRAMS += qfcc qfprogs +EXTRA_PROGRAMS += qfcc$(EXEEXT) qfprogs$(EXEEXT) bin_PROGRAMS += @QFCC_TARGETS@ bin_SCRIPTS += tools/qfcc/source/qfpreqcc diff --git a/tools/qfcc/source/cpp.c b/tools/qfcc/source/cpp.c index 1adb1301b..db2d95d55 100644 --- a/tools/qfcc/source/cpp.c +++ b/tools/qfcc/source/cpp.c @@ -269,7 +269,7 @@ preprocess_file (const char *filename, const char *ext) puts(""); } -#ifdef _WIN64 +#if defined(_WIN64) || defined(_WIN32) status = spawnvp (_P_WAIT, cpp_argv[0], (char **) cpp_argv); #else status = spawnvp (_P_WAIT, cpp_argv[0], cpp_argv); diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index 46382cf11..044c7fdc7 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -168,7 +168,8 @@ qfo_lines (qfo_t *qfo) pr_lineno_t *lineno; qfo_func_t *func = 0; - for (func = qfo->funcs; func - qfo->funcs < qfo->num_funcs; func++) { + for (func = qfo->funcs; + (size_t) (func - qfo->funcs) < qfo->num_funcs; func++) { if (!func->line_info) { // builtin continue; @@ -182,7 +183,7 @@ qfo_lines (qfo_t *qfo) qfo_set_func_data(qfo, func, &func_data); start_lineno = qfo->lines + func->line_info; for (lineno = start_lineno + 1; - lineno - qfo->lines < qfo->num_lines && lineno->line; + (size_t) (lineno - qfo->lines) < qfo->num_lines && lineno->line; lineno++) { } diff --git a/tools/qfcc/source/dump_strings.c b/tools/qfcc/source/dump_strings.c index ce9627f32..ae32856e7 100644 --- a/tools/qfcc/source/dump_strings.c +++ b/tools/qfcc/source/dump_strings.c @@ -40,18 +40,18 @@ #include "tools/qfcc/include/qfprogs.h" static void -dump_string_block (const char *strblock, unsigned size) +dump_string_block (const char *strblock, size_t size) { const char *s = strblock; printf ("%x \"", 0); - while (s - strblock < size) { + while ((size_t) (s - strblock) < size) { char c = *s++; switch (c) { case 0: fputs ("\"\n", stdout); - if (s - strblock < size) - printf ("%lx \"", s - strblock); + if ((size_t) (s - strblock) < size) + printf ("%zx \"", s - strblock); break; case 9: fputs ("\\t", stdout); diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 502283fb5..d93b1ea60 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -1191,7 +1191,7 @@ undefined_def (qfo_def_t *def) pr_uint_t best_dist; pr_lineno_t *line; - while (func - work->funcs < work->num_funcs) { + while (func - work->funcs < (ptrdiff_t) work->num_funcs) { if (func->code >= 0 && (pr_uint_t) func->code <= reloc->offset) { if (!best || reloc->offset - func->code < best_dist) { @@ -1206,7 +1206,7 @@ undefined_def (qfo_def_t *def) line_def.line = best->line; if (!line->line && line->fa.func == (pr_uint_t) (best - work->funcs)) { - while (line - work->lines < work->num_lines - 1 + while (line - work->lines < (ptrdiff_t) work->num_lines - 1 && line[1].line && line[1].fa.addr <= (pr_uint_t) reloc->offset) line++; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index a8e6ae5fb..0380d1fbb 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -46,6 +46,8 @@ #include "QF/quakeio.h" #include "QF/va.h" +#include "compat.h" + #include "tools/qfcc/include/codespace.h" #include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/def.h" diff --git a/tools/qfspritegen/spritegen.c b/tools/qfspritegen/spritegen.c index 08ddc86f1..e1af9e487 100644 --- a/tools/qfspritegen/spritegen.c +++ b/tools/qfspritegen/spritegen.c @@ -22,6 +22,10 @@ // Result is stored in /raid/quake/id1/sprites/.spr. // +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include From 72280186bf2c266f64379021de84d13e41363392 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Jan 2021 18:58:26 +0900 Subject: [PATCH 1450/3664] [qfvis] Use cmem for memory management While the main bulk of the improvement (36s down from 42s for gmsp3v2.bsp on my i7-6850K) comes from using a high-tide allocator for the windings (which necessitated using a fixed size), it is ever so slightly faster than using malloc as the back-end. --- include/QF/cmem.h | 42 ++++++++++++++++++++++++++++++++++++ tools/qfvis/include/vis.h | 15 +++++++------ tools/qfvis/source/flow.c | 44 ++++++++++++++++++++------------------ tools/qfvis/source/qfvis.c | 38 +++++++++++++++++++------------- 4 files changed, 97 insertions(+), 42 deletions(-) diff --git a/include/QF/cmem.h b/include/QF/cmem.h index f9c47d4c1..1f81bf298 100644 --- a/include/QF/cmem.h +++ b/include/QF/cmem.h @@ -115,4 +115,46 @@ void delete_memsuper (memsuper_t *super); void *cmemalloc (memsuper_t *super, size_t size); void cmemfree (memsuper_t *super, void *mem); +/** High-tide structure allocator for use in linked lists. + + Using a free-list with the name of \c NAME_freelist, return a single + element. + The type of the element must be a structure with a field named \c next. + When the free-list is empty, memory is claimed from the system in blocks. + Elements may be returned to the pool by linking them into the free-list. + + \param s The number of structures in the block. + \param t The structure type. + \param n The \c NAME portion of the \c NAME_freelist free-list. + \param super The memsuper_t super block from which to allocate memory. + + \hideinitializer +*/ +#define CMEMALLOC(s, t, n, super) \ + ({ \ + if (!n##_freelist) { \ + int i; \ + n##_freelist = cmemalloc ((super), (s) * sizeof (t)); \ + for (i = 0; i < (s) - 1; i++) \ + n##_freelist[i].next = &n##_freelist[i + 1]; \ + n##_freelist[i].next = 0; \ + } \ + t *v = n##_freelist; \ + n##_freelist = n##_freelist->next; \ + v; \ + }) + +/** Free a block allocated by #ALLOC + + \param n The \c NAME portion of the \c NAME_freelist free-list. + \param p The pointer to the block to be freed. + + \hideinitializer +*/ +#define CMEMFREE(n, p) \ + do { \ + p->next = n##_freelist; \ + n##_freelist = p; \ + } while (0) + #endif//__QF_cmem_h diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index dc24d17f4..6b96f4b3c 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -82,10 +82,11 @@ extern pthread_rwlock_t *portal_locks; #define MAX_POINTS_ON_WINDING 64 #define MAX_PORTALS_ON_CLUSTER 128 -typedef struct { +typedef struct winding_s { + struct winding_s *next; qboolean original; // don't free, it's part of the portal int numpoints; - vec3_t points[8]; // variable sized + vec3_t points[MAX_PORTALS_ON_CLUSTER]; // variable sized } winding_t; typedef enum { @@ -158,7 +159,9 @@ typedef struct threaddata_s { portal_t *base; ///< portal for which this thread is being run pstack_t pstack_head; sep_t *sep_freelist; ///< per-thread list of free separators + winding_t *winding_freelist; ///< per-thread list of free windings set_pool_t set_pool; + struct memsuper_s *memsuper; } threaddata_t; typedef struct { @@ -179,10 +182,10 @@ extern cluster_t *clusters; extern int *leafcluster; extern byte *uncompressed; -void FreeWinding (winding_t *w); -winding_t *NewWinding (int points); -winding_t *ClipWinding (winding_t *in, const plane_t *split, qboolean keepon); -winding_t *CopyWinding (const winding_t *w); +void FreeWinding (threaddata_t *thread, winding_t *w); +winding_t *NewWinding (threaddata_t *thread, int points); +winding_t *ClipWinding (threaddata_t *thread, winding_t *in, const plane_t *split, qboolean keepon); +winding_t *CopyWinding (threaddata_t *thread, const winding_t *w); void ClusterFlow (int clusternum); void PortalBase (basethread_t *thread, portal_t *portal); diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 030ca7a43..520976637 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -48,8 +48,8 @@ #include #include -#include "QF/alloc.h" #include "QF/bspfile.h" +#include "QF/cmem.h" #include "QF/cmd.h" #include "QF/mathlib.h" #include "QF/quakefs.h" @@ -90,14 +90,14 @@ new_separator (threaddata_t *thread) { sep_t *sep; - ALLOC (128, sep_t, thread->sep, sep); + sep = CMEMALLOC (32, sep_t, thread->sep, thread->memsuper); return sep; } static void delete_separator (threaddata_t *thread, sep_t *sep) { - FREE (thread->sep, sep); + CMEMFREE (thread->sep, sep); } static void @@ -247,12 +247,12 @@ FindSeparators (threaddata_t *thread, } static winding_t * -ClipToSeparators (const sep_t *separators, winding_t *target) +ClipToSeparators (threaddata_t *thread, const sep_t *separators, winding_t *target) { const sep_t *sep; for (sep = separators; target && sep; sep = sep->next) { - target = ClipWinding (target, &sep->plane, false); + target = ClipWinding (thread, target, &sep->plane, false); } return target; } @@ -360,7 +360,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) thread->stats.portalcheck++; target_winding = target_portal->winding; - target_winding = ClipWinding (target_winding, source_plane, false); + target_winding = ClipWinding (thread, target_winding, source_plane, false); if (!target_winding) continue; @@ -374,21 +374,21 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) stack->pass_portal = target_portal; RecursiveClusterFlow (target_portal->cluster, thread, stack); - FreeWinding (target_winding); + FreeWinding (thread, target_winding); continue; } - target_winding = ClipWinding (target_winding, pass_plane, false); + target_winding = ClipWinding (thread, target_winding, pass_plane, false); if (!target_winding) continue; // copy source_winding because it likely is already a copy and thus // if it gets clipped away, earlier stack levels will get corrupted - source_winding = CopyWinding (prevstack->source_winding); + source_winding = CopyWinding (thread, prevstack->source_winding); - source_winding = ClipWinding (source_winding, &backplane, false); + source_winding = ClipWinding (thread, source_winding, &backplane, false); if (!source_winding) { - FreeWinding (target_winding); + FreeWinding (thread, target_winding); continue; } @@ -402,11 +402,12 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) source_winding, *source_plane, pass_winding, 0); - target_winding = ClipToSeparators (stack->separators[0], + target_winding = ClipToSeparators (thread, + stack->separators[0], target_winding); if (!target_winding) { thread->stats.targetclipped++; - FreeWinding (source_winding); + FreeWinding (thread, source_winding); continue; } if (target_winding != old) @@ -420,11 +421,12 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) pass_winding, *pass_plane, source_winding, 1); - target_winding = ClipToSeparators (stack->separators[1], + target_winding = ClipToSeparators (thread, + stack->separators[1], target_winding); if (!target_winding) { thread->stats.targetclipped++; - FreeWinding (source_winding); + FreeWinding (thread, source_winding); continue; } if (target_winding != old) @@ -438,11 +440,11 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) sep = FindSeparators (thread, target_winding, target_portal->plane, pass_winding, 0); - source_winding = ClipToSeparators (sep, source_winding); + source_winding = ClipToSeparators (thread, sep, source_winding); free_separators (thread, sep); if (!source_winding) { thread->stats.sourceclipped++; - FreeWinding (target_winding); + FreeWinding (thread, target_winding); continue; } if (source_winding != old) @@ -454,11 +456,11 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) sep_t *sep; sep = FindSeparators (thread, pass_winding, *pass_plane, target_winding, 1); - source_winding = ClipToSeparators (sep, source_winding); + source_winding = ClipToSeparators (thread, sep, source_winding); free_separators (thread, sep); if (!source_winding) { thread->stats.sourceclipped++; - FreeWinding (target_winding); + FreeWinding (thread, target_winding); continue; } if (source_winding != old) @@ -476,8 +478,8 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) // flow through it for real RecursiveClusterFlow (target_portal->cluster, thread, stack); - FreeWinding (source_winding); - FreeWinding (target_winding); + FreeWinding (thread, source_winding); + FreeWinding (thread, target_winding); } free_separators (thread, stack->separators[1]); free_separators (thread, stack->separators[0]); diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index c62eabbcc..3a49e53c1 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -51,6 +51,7 @@ #include "QF/bspfile.h" #include "QF/cmd.h" +#include "QF/cmem.h" #include "QF/dstring.h" #include "QF/mathlib.h" #include "QF/qtypes.h" @@ -71,6 +72,7 @@ bsp_t *bsp; options_t options; +static threaddata_t main_thread; static visstat_t stats; int base_mightsee; @@ -144,7 +146,7 @@ PlaneFromWinding (winding_t *winding, plane_t *plane) } winding_t * -NewWinding (int points) +NewWinding (threaddata_t *thread, int points) { winding_t *winding; size_t size; @@ -153,38 +155,40 @@ NewWinding (int points) Sys_Error ("NewWinding: %i points", points); size = field_offset (winding_t, points[points]); - winding = calloc (1, size); + winding = CMEMALLOC (13, winding_t, thread->winding, thread->memsuper); + memset (winding, 0, size); return winding; } void -FreeWinding (winding_t *w) +FreeWinding (threaddata_t *thread, winding_t *w) { - if (!w->original) - free (w); + if (!w->original) { + CMEMFREE (thread->winding, w); + } } winding_t * -CopyWinding (const winding_t *w) +CopyWinding (threaddata_t *thread, const winding_t *w) { size_t size; winding_t *copy; size = field_offset (winding_t, points[w->numpoints]); - copy = malloc (size); + copy = CMEMALLOC (13, winding_t, thread->winding, thread->memsuper); memcpy (copy, w, size); copy->original = false; return copy; } static winding_t * -NewFlippedWinding (const winding_t *w) +NewFlippedWinding (threaddata_t *thread, const winding_t *w) { winding_t *flipped; int i; - flipped = NewWinding (w->numpoints); + flipped = NewWinding (thread, w->numpoints); for (i = 0; i < w->numpoints; i++) VectorCopy (w->points[i], flipped->points[w->numpoints - 1 - i]); flipped->numpoints = w->numpoints; @@ -203,7 +207,7 @@ NewFlippedWinding (const winding_t *w) it will be clipped away. */ winding_t * -ClipWinding (winding_t *in, const plane_t *split, qboolean keepon) +ClipWinding (threaddata_t *thread, winding_t *in, const plane_t *split, qboolean keepon) { int maxpts, i, j; int counts[3], sides[MAX_POINTS_ON_WINDING]; @@ -236,7 +240,7 @@ ClipWinding (winding_t *in, const plane_t *split, qboolean keepon) return in; if (!counts[0]) { - FreeWinding (in); + FreeWinding (thread, in); return NULL; } if (!counts[1]) @@ -244,7 +248,7 @@ ClipWinding (winding_t *in, const plane_t *split, qboolean keepon) maxpts = in->numpoints + 4; // can't use counts[0] + 2 because // of fp grouping errors - neww = NewWinding (maxpts); + neww = NewWinding (thread, maxpts); for (i = 0; i < in->numpoints; i++) { p1 = in->points[i]; @@ -284,7 +288,7 @@ ClipWinding (winding_t *in, const plane_t *split, qboolean keepon) if (neww->numpoints > maxpts) Sys_Error ("ClipWinding: points exceeded estimate"); // free the original winding - FreeWinding (in); + FreeWinding (thread, in); return neww; } @@ -384,6 +388,7 @@ LeafThread (void *_thread) memset (&data, 0, sizeof (data)); set_pool_init (&data.set_pool); + data.memsuper = new_memsuper (); do { portal = GetNextPortal (); if (!portal) @@ -408,6 +413,7 @@ LeafThread (void *_thread) printf ("thread %d done\n", thread); if (working) working[thread] = -1; + delete_memsuper (data.memsuper); return NULL; } @@ -1033,7 +1039,7 @@ LoadPortals (char *name) || (unsigned) clusternums[1] > (unsigned) portalclusters) Sys_Error ("LoadPortals: reading portal %i", i); - winding = portal->winding = NewWinding (numpoints); + winding = portal->winding = NewWinding (&main_thread, numpoints); winding->original = true; winding->numpoints = numpoints; @@ -1085,7 +1091,7 @@ LoadPortals (char *name) // Use a flipped winding for the reverse portal so the winding // direction and plane normal match. - portal->winding = NewFlippedWinding (winding); + portal->winding = NewFlippedWinding (&main_thread, winding); portal->winding->original = true; portal->plane = plane; portal->cluster = clusternums[0]; @@ -1115,6 +1121,8 @@ main (int argc, char **argv) dstring_t *portalfile = dstring_new (); QFile *f; + main_thread.memsuper = new_memsuper (); + start = Sys_DoubleTime (); this_program = argv[0]; From 5d703c1f3ec32797e03e0dce7d55adebb12eb097 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Jan 2013 22:33:34 +0900 Subject: [PATCH 1451/3664] First stab at keydest sanitization --- nq/include/client.h | 1 + nq/source/cl_demo.c | 1 + nq/source/cl_main.c | 7 ++++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index e3f053016..a00b94890 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -91,6 +91,7 @@ typedef struct { // connection information cactive_t state; signon_t signon; + keydest_t key_dest; // network stuff struct qsocket_s *netcon; diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 03950998a..b15747467 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -478,6 +478,7 @@ CL_StartDemo (void) cls.demoplayback = true; CL_SetState (ca_connected); cls.forcetrack = 0; + cls.key_dest = key_demo; Key_SetKeyDest (key_demo); while ((c = Qgetc (cls.demofile)) != '\n') diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 1bb8ffeb8..14bd9637e 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -323,7 +323,7 @@ CL_EstablishConnection (const char *host) cls.demonum = -1; // not in the demo loop now CL_SetState (ca_connected); - Key_SetKeyDest (key_game); + Key_SetKeyDest (cls.key_dest); } /* @@ -514,14 +514,14 @@ CL_SetState (cactive_t state) cls.signon = so_none; // need all the signon messages // before playing cl.loading = true; - Key_SetKeyDest (key_game); + Key_SetKeyDest (cls.key_dest); IN_ClearStates (); VID_SetCaption ("Connected"); break; case ca_active: // entering active state cl.loading = false; - Key_SetKeyDest (key_game); + Key_SetKeyDest (cls.key_dest); IN_ClearStates (); VID_SetCaption (""); S_AmbientOn (); @@ -583,5 +583,6 @@ CL_Init (cbuf_t *cbuf) "to be level"); SZ_Alloc (&cls.message, 1024); + cls.key_dest = key_game; CL_SetState (ca_disconnected); } From f2b6b23acc830be0109bf44523699f6e57a7ba97 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Jan 2021 16:32:36 +0900 Subject: [PATCH 1452/3664] [qfvis] Switch to unsigned for various counts --- tools/qfvis/include/vis.h | 8 ++-- tools/qfvis/source/base-vis.c | 2 +- tools/qfvis/source/flow.c | 2 +- tools/qfvis/source/qfvis.c | 72 +++++++++++++++++------------------ tools/qfvis/source/soundphs.c | 4 +- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 6b96f4b3c..2d3afacfc 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -85,7 +85,7 @@ extern pthread_rwlock_t *portal_locks; typedef struct winding_s { struct winding_s *next; qboolean original; // don't free, it's part of the portal - int numpoints; + unsigned numpoints; vec3_t points[MAX_PORTALS_ON_CLUSTER]; // variable sized } winding_t; @@ -169,9 +169,9 @@ typedef struct { int clustersee; } basethread_t; -extern int numportals; -extern int portalclusters; -extern int numrealleafs; +extern unsigned numportals; +extern unsigned portalclusters; +extern unsigned numrealleafs; extern int bitbytes; extern int bitbytes_l; extern int bitlongs; diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index 99d5934df..77f2b266b 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -98,7 +98,7 @@ test_sphere (sphere_t *sphere, plane_t *plane) void PortalBase (basethread_t *thread, portal_t *portal) { - int i, j, k; + unsigned i, j, k; float d; portal_t *tp; winding_t *winding; diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 520976637..b73058a72 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -224,7 +224,7 @@ FindSeparators (threaddata_t *thread, const winding_t *source, const plane_t src_pl, const winding_t *pass, int flip) { - int i, j, l; + unsigned i, j, l; vec3_t v1; sep_t *separators = 0, *sep; diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 3a49e53c1..a04c6193c 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -76,11 +76,11 @@ static threaddata_t main_thread; static visstat_t stats; int base_mightsee; -int portal_count; -int numportals; -int portalclusters; -int numrealleafs; -size_t originalvismapsize; +static unsigned portal_count; +unsigned numportals; +unsigned portalclusters; +unsigned numrealleafs; +unsigned originalvismapsize; int totalvis; int count_sep; int bitbytes; // (portalleafs + 63)>>3 @@ -149,7 +149,7 @@ winding_t * NewWinding (threaddata_t *thread, int points) { winding_t *winding; - size_t size; + unsigned size; if (points > MAX_POINTS_ON_WINDING) Sys_Error ("NewWinding: %i points", points); @@ -172,7 +172,7 @@ FreeWinding (threaddata_t *thread, winding_t *w) winding_t * CopyWinding (threaddata_t *thread, const winding_t *w) { - size_t size; + unsigned size; winding_t *copy; size = field_offset (winding_t, points[w->numpoints]); @@ -186,7 +186,7 @@ static winding_t * NewFlippedWinding (threaddata_t *thread, const winding_t *w) { winding_t *flipped; - int i; + unsigned i; flipped = NewWinding (thread, w->numpoints); for (i = 0; i < w->numpoints; i++) @@ -209,7 +209,7 @@ NewFlippedWinding (threaddata_t *thread, const winding_t *w) winding_t * ClipWinding (threaddata_t *thread, winding_t *in, const plane_t *split, qboolean keepon) { - int maxpts, i, j; + unsigned maxpts, i, j; int counts[3], sides[MAX_POINTS_ON_WINDING]; vec_t dot; vec_t dists[MAX_POINTS_ON_WINDING]; @@ -402,7 +402,7 @@ LeafThread (void *_thread) PortalCompleted (&data, portal); if (options.verbosity > 1) - printf ("portal:%5i mightsee:%5i cansee:%5i %5d/%d\n", + printf ("portal:%5i mightsee:%5i cansee:%5i %5u/%u\n", (int) (portal - portals), portal->nummightsee, portal->numcansee, @@ -467,7 +467,7 @@ print_thread_stats (const int *local_work, int thread, int spinner_ind) for (i = 0; i < thread; i++) printf ("%6d", local_work[i]); - printf (" %5d / %5d", portal_count, numportals * 2); + printf (" %5u / %5u", portal_count, numportals * 2); fflush (stdout); printf (" %c\r", spinner[spinner_ind % 4]); fflush (stdout); @@ -495,7 +495,7 @@ WatchThread (void *_thread) int spinner_ind = 0; int count = 0; int prev_prog = 0; - int prev_port = 0; + unsigned prev_port = 0; int stalled = 0; while (1) { @@ -597,7 +597,7 @@ CompressRow (byte *vis, byte *dest) static void ClusterFlowExpand (const set_t *src, byte *dest) { - int i, j; + unsigned i, j; for (j = 1, i = 0; i < numrealleafs; i++) { if (set_is_member (src, leafcluster[i])) @@ -690,7 +690,7 @@ BasePortalVis (void) static void CalcPortalVis (void) { - long i; + unsigned i; double start, end; portal_count = 0; @@ -731,7 +731,7 @@ CalcPortalVis (void) static void CalcVis (void) { - int i; + unsigned i; printf ("Thread count: %d\n", options.threads); BasePortalVis (); @@ -745,7 +745,7 @@ CalcVis (void) bsp->leafs[i + 1].visofs = clusters[leafcluster[i]].visofs; } if (options.verbosity >= 0) - printf ("average clusters visible: %i\n", totalvis / portalclusters); + printf ("average clusters visible: %u\n", totalvis / portalclusters); } #if 0 static qboolean @@ -927,7 +927,7 @@ LoadPortals (char *name) { const char *line; char *err; - int numpoints, i, j, k; + unsigned numpoints, i, j, k; int read_leafs = 0; int clusternums[2]; cluster_t *cluster; @@ -953,34 +953,34 @@ LoadPortals (char *name) if (line && (!strcmp (line, PORTALFILE "\n") || !strcmp (line, PORTALFILE "\r\n"))) { line = Qgetline (f); - if (!line || sscanf (line, "%i\n", &portalclusters) != 1) + if (!line || sscanf (line, "%u\n", &portalclusters) != 1) Sys_Error ("LoadPortals: failed to read header"); line = Qgetline (f); - if (!line || sscanf (line, "%i\n", &numportals) != 1) + if (!line || sscanf (line, "%u\n", &numportals) != 1) Sys_Error ("LoadPortals: failed to read header"); numrealleafs = portalclusters; } else if (line && (!strcmp (line, PORTALFILE_AM "\n") || !strcmp (line, PORTALFILE_AM "\r\n"))) { line = Qgetline (f); - if (!line || sscanf (line, "%i\n", &portalclusters) != 1) + if (!line || sscanf (line, "%u\n", &portalclusters) != 1) Sys_Error ("LoadPortals: failed to read header"); line = Qgetline (f); - if (!line || sscanf (line, "%i\n", &numportals) != 1) + if (!line || sscanf (line, "%u\n", &numportals) != 1) Sys_Error ("LoadPortals: failed to read header"); line = Qgetline (f); - if (!line || sscanf (line, "%i\n", &numrealleafs) != 1) + if (!line || sscanf (line, "%u\n", &numrealleafs) != 1) Sys_Error ("LoadPortals: failed to read header"); read_leafs = 1; } else if (line && (!strcmp (line, PORTALFILE2 "\n") || !strcmp (line, PORTALFILE2 "\r\n"))) { line = Qgetline (f); - if (!line || sscanf (line, "%i\n", &numrealleafs) != 1) + if (!line || sscanf (line, "%u\n", &numrealleafs) != 1) Sys_Error ("LoadPortals: failed to read header"); line = Qgetline (f); - if (!line || sscanf (line, "%i\n", &portalclusters) != 1) + if (!line || sscanf (line, "%u\n", &portalclusters) != 1) Sys_Error ("LoadPortals: failed to read header"); line = Qgetline (f); - if (!line || sscanf (line, "%i\n", &numportals) != 1) + if (!line || sscanf (line, "%u\n", &numportals) != 1) Sys_Error ("LoadPortals: failed to read header"); read_leafs = 1; } else { @@ -988,9 +988,9 @@ LoadPortals (char *name) } if (options.verbosity >= 0) { - printf ("%4i portalclusters\n", portalclusters); - printf ("%4i numportals\n", numportals); - printf ("%4i numrealleafs\n", numrealleafs); + printf ("%4u portalclusters\n", portalclusters); + printf ("%4u numportals\n", numportals); + printf ("%4u numrealleafs\n", numrealleafs); } bitbytes = ((portalclusters + 63) & ~63) >> 3; @@ -1020,24 +1020,24 @@ LoadPortals (char *name) for (i = 0, portal = portals; i < numportals; i++) { line = Qgetline (f); if (!line) - Sys_Error ("LoadPortals: reading portal %i", i); + Sys_Error ("LoadPortals: reading portal %u", i); numpoints = strtol (line, &err, 10); if (err == line) - Sys_Error ("LoadPortals: reading portal %i", i); + Sys_Error ("LoadPortals: reading portal %u", i); line = err; for (j = 0; j < 2; j++) { clusternums[j] = strtol (line, &err, 10); if (err == line) - Sys_Error ("LoadPortals: reading portal %i", i); + Sys_Error ("LoadPortals: reading portal %u", i); line = err; } if (numpoints > MAX_POINTS_ON_WINDING) - Sys_Error ("LoadPortals: portal %i has too many points", i); + Sys_Error ("LoadPortals: portal %u has too many points", i); if ((unsigned) clusternums[0] > (unsigned) portalclusters || (unsigned) clusternums[1] > (unsigned) portalclusters) - Sys_Error ("LoadPortals: reading portal %i", i); + Sys_Error ("LoadPortals: reading portal %u", i); winding = portal->winding = NewWinding (&main_thread, numpoints); winding->original = true; @@ -1048,19 +1048,19 @@ LoadPortals (char *name) while (isspace ((byte) *line)) line++; if (*line++ != '(') - Sys_Error ("LoadPortals: reading portal %i", i); + Sys_Error ("LoadPortals: reading portal %u", i); for (k = 0; k < 3; k++) { winding->points[j][k] = strtod (line, &err); if (err == line) - Sys_Error ("LoadPortals: reading portal %i", i); + Sys_Error ("LoadPortals: reading portal %u", i); line = err; } while (isspace ((byte) *line)) line++; if (*line++ != ')') - Sys_Error ("LoadPortals: reading portal %i", i); + Sys_Error ("LoadPortals: reading portal %u", i); } // calc plane diff --git a/tools/qfvis/source/soundphs.c b/tools/qfvis/source/soundphs.c index f21a9390d..c4be79315 100644 --- a/tools/qfvis/source/soundphs.c +++ b/tools/qfvis/source/soundphs.c @@ -94,8 +94,8 @@ void CalcAmbientSounds (void) { byte *vis; - int ambient_type, ofs, i, j, l; - unsigned k; + unsigned i, j, k; + int ambient_type, ofs, l; float maxd, vol, d; float dists[NUM_AMBIENTS]; dface_t *surf; From 3ef38188cefc947c2488ebfc40f3502f525e23ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Jan 2021 16:36:01 +0900 Subject: [PATCH 1453/3664] [qfvis] Add an option to limit the processed portals It's not documented as I needed it for debugging memory allocations and it causes qfvis to error out due to unprocessed portals. --- tools/qfvis/include/options.h | 1 + tools/qfvis/source/options.c | 9 +++++++++ tools/qfvis/source/qfvis.c | 24 ++++++++++++++---------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/tools/qfvis/include/options.h b/tools/qfvis/include/options.h index 521a4ef94..cd6349aa8 100644 --- a/tools/qfvis/include/options.h +++ b/tools/qfvis/include/options.h @@ -35,6 +35,7 @@ typedef struct { int threads; qboolean minimal; int level; + size_t portal_limit; struct dstring_s *bspfile; } options_t; diff --git a/tools/qfvis/source/options.c b/tools/qfvis/source/options.c index d9a5e3691..e66eca278 100644 --- a/tools/qfvis/source/options.c +++ b/tools/qfvis/source/options.c @@ -46,6 +46,11 @@ const char *this_program; +enum { + start_opts = 255, // not used, starts the enum. + OPT_PORTAL_LIMIT, +}; + static struct option const long_options[] = { {"quiet", no_argument, 0, 'q'}, {"verbose", no_argument, 0, 'v'}, @@ -55,6 +60,7 @@ static struct option const long_options[] = { {"minimal", no_argument, 0, 'm'}, {"level", required_argument, 0, 'l'}, {"file", required_argument, 0, 'f'}, + {"portal-limit", required_argument, 0, OPT_PORTAL_LIMIT}, {NULL, 0, NULL, 0} }; @@ -131,6 +137,9 @@ DecodeArgs (int argc, char **argv) case 't': // threads options.threads = atoi (optarg); break; + case OPT_PORTAL_LIMIT: + options.portal_limit = atoi (optarg); + break; case 'm': // minimal vis options.minimal = true; break; diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index a04c6193c..980699b1e 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -294,16 +294,20 @@ ClipWinding (threaddata_t *thread, winding_t *in, const plane_t *split, qboolean } static portal_t * -GetNextPortal (void) +GetNextPortal (int limit) { portal_t *p = 0; - WRLOCK (global_lock); - if (portal_count < 2 * numportals) { - p = portal_queue[portal_count++]; - p->status = stat_selected; + if (!(limit + && options.portal_limit > 0 + && portal_count >= options.portal_limit)) { + WRLOCK (global_lock); + if (portal_count < 2 * numportals) { + p = portal_queue[portal_count++]; + p->status = stat_selected; + } + UNLOCK (global_lock); } - UNLOCK (global_lock); return p; } @@ -390,7 +394,7 @@ LeafThread (void *_thread) set_pool_init (&data.set_pool); data.memsuper = new_memsuper (); do { - portal = GetNextPortal (); + portal = GetNextPortal (1); if (!portal) break; @@ -430,7 +434,7 @@ BaseVisThread (void *_thread) set_pool_init (&set_pool); data.portalsee = set_new_size_r (&set_pool, numportals * 2); do { - portal = GetNextPortal (); + portal = GetNextPortal (0); if (!portal) break; @@ -693,8 +697,6 @@ CalcPortalVis (void) unsigned i; double start, end; - portal_count = 0; - // fastvis just uses mightsee for a very loose bound if (options.minimal) { for (i = 0; i < numportals * 2; i++) { @@ -714,6 +716,8 @@ CalcPortalVis (void) if (options.verbosity >= 1) printf ("\n"); + portal_count = 0; + RunThreads (LeafThread); if (options.verbosity > 0) { From d072a7b99c5603e690a4db118b094db98316c0d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 23:04:13 +0900 Subject: [PATCH 1454/3664] [qfvis] Add stats for memory usage Verbosity levels probably need more tweaking, but -v is at least a little more usable. --- tools/qfvis/include/vis.h | 14 ++++- tools/qfvis/source/flow.c | 12 ++++ tools/qfvis/source/qfvis.c | 119 ++++++++++++++++++++++++++++++++----- 3 files changed, 130 insertions(+), 15 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 2d3afacfc..ba4537b3d 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -72,6 +72,7 @@ extern pthread_rwlock_t *portal_locks; #define UNLOCK_PORTAL(p) #endif +#include "QF/cmem.h" #include "QF/set.h" #define MAX_PORTALS 32768 @@ -151,6 +152,15 @@ typedef struct { int mighttest; ///< amount mightsee is used for masked tests int vistest; ///< amount visbits is used for masked tests int mightseeupdate; ///< amount of updates to waiting portals + unsigned sep_alloc; ///< how many separators were allocated + unsigned sep_free; ///< how many separators were freed + unsigned sep_highwater; ///< most separators in flight + unsigned sep_maxbulk; ///< most separators freed at once + unsigned winding_alloc; ///< how many windings were allocated + unsigned winding_free; ///< how many windings were freed + unsigned winding_highwater; ///< most windings in flight + unsigned stack_alloc; ///< how many stack blocks were allocated + unsigned stack_free; ///< how many stack blocks were freed } visstat_t; typedef struct threaddata_s { @@ -160,13 +170,15 @@ typedef struct threaddata_s { pstack_t pstack_head; sep_t *sep_freelist; ///< per-thread list of free separators winding_t *winding_freelist; ///< per-thread list of free windings + memsuper_t *memsuper; ///< per-thread memory pool set_pool_t set_pool; - struct memsuper_s *memsuper; + int id; } threaddata_t; typedef struct { set_t *portalsee; int clustersee; + int id; } basethread_t; extern unsigned numportals; diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index b73058a72..671ea7ab7 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -82,6 +82,7 @@ new_stack (threaddata_t *td) stack = malloc (sizeof (pstack_t)); stack->next = 0; stack->mightsee = set_new_size_r (&td->set_pool, portalclusters); + td->stats.stack_alloc++; return stack; } @@ -91,22 +92,33 @@ new_separator (threaddata_t *thread) sep_t *sep; sep = CMEMALLOC (32, sep_t, thread->sep, thread->memsuper); + thread->stats.sep_alloc++; return sep; } static void delete_separator (threaddata_t *thread, sep_t *sep) { + thread->stats.sep_free++; CMEMFREE (thread->sep, sep); } static void free_separators (threaddata_t *thread, sep_t *sep_list) { + unsigned count = thread->stats.sep_alloc - thread->stats.sep_free; + if (count > thread->stats.sep_highwater) { + thread->stats.sep_highwater = count; + } + count = 0; while (sep_list) { sep_t *sep = sep_list; sep_list = sep->next; delete_separator (thread, sep); + count++; + } + if (count > thread->stats.sep_maxbulk) { + thread->stats.sep_maxbulk = count; } } diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 980699b1e..b534e6252 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -157,6 +157,7 @@ NewWinding (threaddata_t *thread, int points) size = field_offset (winding_t, points[points]); winding = CMEMALLOC (13, winding_t, thread->winding, thread->memsuper); memset (winding, 0, size); + thread->stats.winding_alloc++; return winding; } @@ -165,6 +166,11 @@ void FreeWinding (threaddata_t *thread, winding_t *w) { if (!w->original) { + unsigned count = thread->stats.winding_alloc - thread->stats.winding_free; + if (count > thread->stats.winding_highwater) { + thread->stats.winding_highwater = count; + } + thread->stats.winding_free++; CMEMFREE (thread->winding, w); } } @@ -179,6 +185,7 @@ CopyWinding (threaddata_t *thread, const winding_t *w) copy = CMEMALLOC (13, winding_t, thread->winding, thread->memsuper); memcpy (copy, w, size); copy->original = false; + thread->stats.winding_alloc++; return copy; } @@ -356,6 +363,12 @@ PortalCompleted (threaddata_t *thread, portal_t *completed) stats.mighttest += thread->stats.mighttest; stats.vistest += thread->stats.vistest; stats.mightseeupdate += thread->stats.mightseeupdate; + stats.sep_alloc += thread->stats.sep_alloc; + stats.sep_free += thread->stats.sep_free; + stats.winding_alloc += thread->stats.winding_alloc; + stats.winding_free += thread->stats.winding_free; + stats.stack_alloc += thread->stats.stack_alloc; + stats.stack_free += thread->stats.stack_free; UNLOCK (stats_lock); memset (&thread->stats, 0, sizeof (thread->stats)); @@ -383,29 +396,86 @@ PortalCompleted (threaddata_t *thread, portal_t *completed) set_delete_r (&thread->set_pool, changed); } +static void +dump_super_stats (int id, memsuper_t *super) +{ + size_t total_pre_size = 0; + size_t total_pre_allocated = 0; + size_t total_post_size = 0; + size_t total_post_allocated = 0; + size_t num_blocks = 0; + size_t free_counts[MAX_CACHE_LINES]; + + for (memblock_t *block = super->memblocks; block; block = block->next) { + num_blocks++; + total_pre_size += block->pre_size; + total_pre_allocated += block->pre_allocated; + total_post_size += block->post_size; + // post_free is a flag + total_post_allocated += !block->post_free * block->post_size; + } + for (int i = 0; i < MAX_CACHE_LINES; i++) { + free_counts[i] = 0; + for (memline_t *line = super->free_lines[i]; line; + line = line->free_next) { + free_counts[i]++; + } + } + + WRLOCK (global_lock); + printf ("cmem stats for thread %d\n", id); + printf (" blocks: %zd\n", num_blocks); + printf (" pre: s:%-8zd a:%-8zd f:%-8zd\n", total_pre_size, + total_pre_allocated, total_pre_size - total_pre_allocated); + printf (" post: s:%-8zd a:%-8zd f:%-8zd\n", total_post_size, + total_post_allocated, total_post_size - total_post_allocated); + printf (" "); + for (int i = 0; i < MAX_CACHE_LINES; i++) { + printf (" %5d", 64 << i); + } + printf ("\n"); + printf (" "); + for (int i = 0; i < MAX_CACHE_LINES; i++) { + printf (" %5zd", free_counts[i]); + } + printf ("\n"); + UNLOCK (global_lock); +} + static void * LeafThread (void *_thread) { portal_t *portal; int thread = (int) (intptr_t) _thread; threaddata_t data; + int count = 0; memset (&data, 0, sizeof (data)); set_pool_init (&data.set_pool); + data.id = thread; data.memsuper = new_memsuper (); do { portal = GetNextPortal (1); if (!portal) break; + if (options.verbosity >= 3 && (!count++ % 16)) { + dump_super_stats (thread, data.memsuper); + } if (working) working[thread] = (int) (portal - portals); PortalFlow (&data, portal); + int whw = data.stats.winding_highwater; + int shw = data.stats.sep_highwater; + int smb = data.stats.sep_maxbulk; PortalCompleted (&data, portal); + data.stats.sep_highwater = shw; + data.stats.sep_maxbulk = smb; + data.stats.winding_highwater = whw; - if (options.verbosity > 1) + if (options.verbosity >= 4) printf ("portal:%5i mightsee:%5i cansee:%5i %5u/%u\n", (int) (portal - portals), portal->nummightsee, @@ -413,7 +483,16 @@ LeafThread (void *_thread) portal_count, numportals * 2); } while (1); - if (options.verbosity > 0) + if (options.verbosity >= 2) { + printf ("thread %d winding highwater: %d\n", thread, + data.stats.winding_highwater); + printf ("thread %d separator highwater: %d\n", thread, + data.stats.sep_highwater); + printf ("thread %d separator maxbulk: %d\n", thread, + data.stats.sep_maxbulk); + } + + if (options.verbosity >= 4) printf ("thread %d done\n", thread); if (working) working[thread] = -1; @@ -431,6 +510,7 @@ BaseVisThread (void *_thread) int num_mightsee = 0; memset (&data, 0, sizeof (data)); + data.id = thread; set_pool_init (&set_pool); data.portalsee = set_new_size_r (&set_pool, numportals * 2); do { @@ -453,7 +533,7 @@ BaseVisThread (void *_thread) base_mightsee += num_mightsee; UNLOCK (stats_lock); - if (options.verbosity > 0) + if (options.verbosity >= 4) printf ("thread %d done\n", thread); if (working) working[thread] = -1; @@ -514,9 +594,9 @@ WatchThread (void *_thread) for (i = 0; i < thread; i ++) local_work[i] = working[i]; - if (options.verbosity > 0) + if (options.verbosity >= 4) print_thread_stats (local_work, thread, spinner_ind); - else if (options.verbosity == 0) + else if (options.verbosity >= 0) prev_prog = print_progress (prev_prog, spinner_ind); if (prev_port != portal_count || stalled++ == 10) { prev_port = portal_count; @@ -525,9 +605,9 @@ WatchThread (void *_thread) } } } - if (options.verbosity > 0) + if (options.verbosity >= 4) printf ("watch thread done\n"); - else if (options.verbosity == 0) + else if (options.verbosity >= 0) printf ("\n"); free (local_work); @@ -656,7 +736,7 @@ ClusterFlow (int clusternum) set_delete (visclusters); // compress the bit string - if (options.verbosity > 1) + if (options.verbosity >= 4) printf ("cluster %4i : %4i visible\n", clusternum, numvis); totalvis += numvis; @@ -680,14 +760,14 @@ BasePortalVis (void) if (options.verbosity >= 0) printf ("Base vis: "); - if (options.verbosity >= 1) + if (options.verbosity >= 4) printf ("\n"); start = Sys_DoubleTime (); RunThreads (BaseVisThread); end = Sys_DoubleTime (); - if (options.verbosity > 0) + if (options.verbosity >= 1) printf ("base_mightsee: %d %gs\n", base_mightsee, end - start); } @@ -708,19 +788,19 @@ CalcPortalVis (void) start = Sys_DoubleTime (); qsort (portal_queue, numportals * 2, sizeof (portal_t *), portalcmp); end = Sys_DoubleTime (); - if (options.verbosity > 0) + if (options.verbosity >= 1) printf ("qsort: %gs\n", end - start); if (options.verbosity >= 0) printf ("Full vis: "); - if (options.verbosity >= 1) + if (options.verbosity >= 4) printf ("\n"); portal_count = 0; RunThreads (LeafThread); - if (options.verbosity > 0) { + if (options.verbosity >= 1) { printf ("portalcheck: %i portaltest: %i portalpass: %i\n", stats.portalcheck, stats.portaltest, stats.portalpass); printf ("target trimmed: %d clipped: %d tested: %d\n", @@ -729,6 +809,17 @@ CalcPortalVis (void) stats.sourcetrimmed, stats.sourceclipped, stats.sourcetested); printf ("vistest: %i mighttest: %i mightseeupdate: %i\n", stats.vistest, stats.mighttest, stats.mightseeupdate); + if (options.verbosity >= 2) { + printf ("separators allocated: %u freed: %u %u\n", + stats.sep_alloc, stats.sep_free, + stats.sep_alloc - stats.sep_free); + printf ("windings allocated: %u freed: %u %u\n", + stats.winding_alloc, stats.winding_free, + stats.winding_alloc - stats.winding_free); + printf ("stack blocks allocated: %u freed: %u %u\n", + stats.stack_alloc, stats.stack_free, + stats.stack_alloc - stats.stack_free); + } } } @@ -1158,7 +1249,7 @@ main (int argc, char **argv) CalcVis (); - if (options.verbosity > 0) + if (options.verbosity >= 1) printf ("chains: %i%s\n", stats.chains, options.threads > 1 ? " (not reliable)" :""); From 29e029c792b3a889bb86ece8b80b48e4566a3d4e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Mar 2021 23:38:10 +0900 Subject: [PATCH 1455/3664] [util] Add float a simd version of the SEB And its support functions. I can't tell if it's any faster (mtwist_rand is a significant chunk of the benchmark timings, oops), but it's nice to have. --- include/QF/simd/types.h | 6 + include/QF/simd/vec4f.h | 8 + libs/util/simd.c | 292 +++++++++++++++++++++++++++++++++++ libs/util/test/Makemodule.am | 15 ++ libs/util/test/test-baryvf.c | 118 ++++++++++++++ libs/util/test/test-csvf.c | 103 ++++++++++++ libs/util/test/test-sebvf.c | 103 ++++++++++++ 7 files changed, 645 insertions(+) create mode 100644 libs/util/test/test-baryvf.c create mode 100644 libs/util/test/test-csvf.c create mode 100644 libs/util/test/test-sebvf.c diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index 9badcc5f3..c5499f5bb 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -88,4 +88,10 @@ VEC_TYPE (int, vec4i_t); typedef vec4f_t mat4f_t[4]; typedef vec4i_t mat4i_t[4]; + +typedef struct vspheref_s { + vec4f_t center; // w set to 1 + float radius; +} vspheref_t; + #endif//__QF_simd_types_h diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 4c76ba34b..04ee24c94 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -325,4 +325,12 @@ magnitude3f (vec4f_t v) return vsqrtf (dotf (v, v)); } +vec4f_t __attribute__((pure)) +BarycentricCoords_vf (const vec4f_t **points, int num_points, vec4f_t p); + +vspheref_t __attribute__((pure)) +CircumSphere_vf (const vec4f_t *points, int num_points); + +vspheref_t SmallestEnclosingBall_vf (const vec4f_t *points, int num_points); + #endif//__QF_simd_vec4f_h diff --git a/libs/util/simd.c b/libs/util/simd.c index 84acc8798..a442fa2c1 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -37,3 +37,295 @@ #include "QF/simd/vec4d.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" +#include "QF/sys.h" + +vec4f_t +BarycentricCoords_vf (const vec4f_t **points, int num_points, const vec4f_t p) +{ + vec4f_t zero = { }; + vec4f_t a, b, c, x, l, ab, bc, ca, d; + if (num_points > 4) + Sys_Error ("Don't know how to compute the barycentric coordinates " + "for %d points", num_points); + switch (num_points) { + case 1: + l = zero; + l[0] = 1; + return l; + case 2: + x = p - *points[0]; + a = *points[1] - *points[0]; + d = dotf (x, a) / dotf (a, a); + l = zero; + l[1] = d[0]; + l[0] = 1 - d[0]; + return l; + case 3: + x = p - *points[0]; + a = *points[1] - *points[0]; + b = *points[2] - *points[0]; + ab = crossf (a, b); + d = dotf (ab, ab); + l[1] = (dotf (crossf (x, b), ab) / d)[0]; + l[2] = (dotf (crossf (a, x), ab) / d)[0]; + l[0] = 1 - l[1] - l[2]; + return l; + case 4: + x = p - *points[0]; + a = *points[1] - *points[0]; + b = *points[2] - *points[0]; + c = *points[3] - *points[0]; + ab = crossf (a, b); + bc = crossf (b, c); + ca = crossf (c, a); + d = dotf (a, bc); + l[1] = (dotf (x, bc) / d)[0]; + l[2] = (dotf (x, ca) / d)[0]; + l[3] = (dotf (x, ab) / d)[0]; + l[0] = 1 - l[1] - l[2] - l[3]; + return l; + } + Sys_Error ("Not enough points to project or enclose the point"); +} + +static vec4f_t +circum_circle (const vec4f_t points[], int num_points) +{ + vec4f_t a, c, b; + vec4f_t bc, ca, ab; + vec4f_t aa, bb, cc; + vec4f_t div; + vec4f_t alpha, beta, gamma; + + switch (num_points) { + case 1: + return points[0]; + case 2: + return (points[0] + points[1]) / 2; + case 3: + a = points[0] - points[1]; + b = points[0] - points[2]; + c = points[1] - points[2]; + aa = dotf (a, a); + bb = dotf (b, b); + cc = dotf (c, c); + div = dotf (a, c); + div = 2 * (aa * cc - div * div); + alpha = cc * dotf (a, b) / div; + beta = -bb * dotf (a, c) / div; + gamma = aa * dotf (b, c) / div; + return alpha * points[0] + beta * points[1] + gamma * points[2]; + case 4: + a = points[1] - points[0]; + b = points[2] - points[0]; + c = points[3] - points[0]; + bc = crossf (b, c); + ca = crossf (c, a); + ab = crossf (a, b); + div = 2 * dotf (a, bc); + aa = dotf (a, a) / div; + bb = dotf (b, b) / div; + cc = dotf (c, c) / div; + return bc * aa + bb * ca + cc * ab + points[0]; + } + vec4f_t zero = {}; + return zero; +} + +vspheref_t +CircumSphere_vf (const vec4f_t *points, int num_points) +{ + vspheref_t sphere = {}; + if (num_points > 0 && num_points <= 4) { + sphere.center = circum_circle (points, num_points); + vec4f_t d = sphere.center - points[0]; + sphere.radius = sqrt(dotf (d, d)[0]); + } + return sphere; +} + +static vec4f_t +closest_affine_point (const vec4f_t **points, int num_points, const vec4f_t x) +{ + vec4f_t closest = {}; + vec4f_t a, b, n, d; + vec4f_t l; + + switch (num_points) { + default: + case 1: + closest = *points[0]; + break; + case 2: + n = *points[1] - *points[0]; + d = x - *points[0]; + l = dotf (d, n) / dotf (n, n); + closest = *points[0] + l * n; + break; + case 3: + a = *points[1] - *points[0]; + b = *points[2] - *points[0]; + n = crossf (a, b); + d = *points[0] - x; + l = dotf (d, n) / dotf (n, n); + closest = x + l * n; + break; + } + return closest; +} + +static int +test_support_points(const vec4f_t **points, int *num_points, vec4f_t center) +{ + vec4i_t cmp; + int in_affine = 0; + int in_convex = 0; + vec4f_t v, d, n, a, b; + float nn, dd, vv, dn; + + switch (*num_points) { + case 1: + cmp = *points[0] == center; + in_affine = cmp[0] && cmp[1] && cmp[2]; + // the convex hull and affine hull for a single point are the same + in_convex = in_affine; + break; + case 2: + v = *points[1] - *points[0]; + d = center - *points[0]; + n = crossf (v, d); + nn = dotf (n, n)[0]; + dd = dotf (d, d)[0]; + vv = dotf (v, v)[0]; + in_affine = nn < 1e-6 * vv * dd; + break; + case 3: + a = *points[1] - *points[0]; + b = *points[2] - *points[0]; + d = center - *points[0]; + n = crossf (a, b); + dn = dotf (d, n)[0]; + dd = dotf (d, d)[0]; + nn = dotf (n, n)[0]; + in_affine = dn * dn < 1e-6 * dd * nn; + break; + case 4: + in_affine = 1; + break; + default: + Sys_Error ("Invalid number of points (%d) in test_support_points", + *num_points); + } + + // if in_convex is not true while in_affine is, then need to test as + // there is more than one dimension for the affine hull (a single support + // point is never dropped as it cannot be redundant) + if (in_affine && !in_convex) { + vec4f_t lambda; + int dropped = 0; + int count = *num_points; + + lambda = BarycentricCoords_vf (points, count, center); + + for (int i = 0; i < count; i++) { + points[i - dropped] = points[i]; + if (lambda[i] < -1e-4) { + dropped++; + (*num_points)--; + } + } + in_convex = !dropped; + if (dropped) { + for (int i = count - dropped; i < count; i++) { + points[i] = 0; + } + } + } + return in_convex; +} + +vspheref_t +SmallestEnclosingBall_vf (const vec4f_t *points, int num_points) +{ + vspheref_t sphere = {}; + vec4f_t center = {}; + const vec4f_t *best; + const vec4f_t *support[4]; + int num_support; + int i; + int iters = 0; + + if (num_points < 1) { + return sphere; + } + + for (i = 0; i < 4; i++) { + support[i] = 0; + } + + vec4f_t dist = {}; + float best_dist = 0; + center = points[0]; + best = &points[0]; + for (i = 1; i < num_points; i++) { + dist = points[i] - center; + dist = dotf (dist, dist); + if (dist[0] > best_dist) { + best_dist = dist[0]; + best = &points[i]; + } + } + num_support = 1; + support[0] = best; + sphere.radius = best_dist; // note: radius squared until the end + + while (!test_support_points (support, &num_support, center)) { + vec4f_t affine; + vec4f_t center_to_affine, center_to_point; + float affine_dist, point_proj, point_dist, bound; + float scale = 1; + int i; + + if (iters++ > 10) + Sys_Error ("stuck SEB"); + best = 0; + + affine = closest_affine_point (support, num_support, center); + center_to_affine = affine - center; + affine_dist = dotf (center_to_affine, center_to_affine)[0]; + for (i = 0; i < num_points; i++) { + if (&points[i] == support[0] || &points[i] == support[1] + || &points[i] == support[2]) + continue; + center_to_point = points[i] - center; + point_proj = dotf (center_to_affine, center_to_point)[0]; + if (affine_dist - point_proj <= 0 + || ((affine_dist - point_proj) * (affine_dist - point_proj) + < 1e-6 * sphere.radius * affine_dist)) + continue; + point_dist = dotf (center_to_point, center_to_point)[0]; + bound = sphere.radius - point_dist; + bound /= 2 * (affine_dist - point_proj); + if (bound < scale) { + best = &points[i]; + scale = bound; + } + } + center = center + scale * center_to_affine; + dist = center - *support[0]; + sphere.radius = dotf (dist, dist)[0]; + if (best) { + support[num_support++] = best; + } + } + best_dist = 0; + for (i = 0; i < num_points; i++) { + dist = center - points[i]; + dist = dotf (dist, dist); + if (dist[0] > best_dist) + best_dist = dist[0]; + } + sphere.center = center; + sphere.radius = sqrt (best_dist); + return sphere; +} diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index ca777f864..323282bde 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -1,8 +1,10 @@ libs_util_tests = \ libs/util/test/test-bary \ + libs/util/test/test-baryvf \ libs/util/test/test-cexpr \ libs/util/test/test-cmem \ libs/util/test/test-cs \ + libs/util/test/test-csvf \ libs/util/test/test-darray \ libs/util/test/test-dq \ libs/util/test/test-half \ @@ -12,6 +14,7 @@ libs_util_tests = \ libs/util/test/test-qfs \ libs/util/test/test-quat \ libs/util/test/test-seb \ + libs/util/test/test-sebvf \ libs/util/test/test-seg \ libs/util/test/test-set \ libs/util/test/test-simd \ @@ -26,6 +29,10 @@ libs_util_test_test_bary_SOURCES=libs/util/test/test-bary.c libs_util_test_test_bary_LDADD=libs/util/libQFutil.la libs_util_test_test_bary_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_baryvf_SOURCES=libs/util/test/test-baryvf.c +libs_util_test_test_baryvf_LDADD=libs/util/libQFutil.la +libs_util_test_test_baryvf_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_cexpr_SOURCES=libs/util/test/test-cexpr.c libs_util_test_test_cexpr_LDADD=libs/util/libQFutil.la libs_util_test_test_cexpr_DEPENDENCIES=libs/util/libQFutil.la @@ -38,6 +45,10 @@ libs_util_test_test_cs_SOURCES=libs/util/test/test-cs.c libs_util_test_test_cs_LDADD=libs/util/libQFutil.la libs_util_test_test_cs_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_csvf_SOURCES=libs/util/test/test-csvf.c +libs_util_test_test_csvf_LDADD=libs/util/libQFutil.la +libs_util_test_test_csvf_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_darray_SOURCES=libs/util/test/test-darray.c libs_util_test_test_darray_LDADD=libs/util/libQFutil.la libs_util_test_test_darray_DEPENDENCIES=libs/util/libQFutil.la @@ -74,6 +85,10 @@ libs_util_test_test_seb_SOURCES=libs/util/test/test-seb.c libs_util_test_test_seb_LDADD=libs/util/libQFutil.la libs_util_test_test_seb_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_sebvf_SOURCES=libs/util/test/test-sebvf.c +libs_util_test_test_sebvf_LDADD=libs/util/libQFutil.la +libs_util_test_test_sebvf_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_seg_SOURCES=libs/util/test/test-seg.c libs_util_test_test_seg_LDADD=libs/util/libQFutil.la libs_util_test_test_seg_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-baryvf.c b/libs/util/test/test-baryvf.c new file mode 100644 index 000000000..ba4538f4a --- /dev/null +++ b/libs/util/test/test-baryvf.c @@ -0,0 +1,118 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/mathlib.h" +#include "QF/mersenne.h" +#include "QF/sys.h" +#include "QF/simd/vec4f.h" + +vec4f_t points[] = { + {-1, -1, 1}, + { 1, 1, 1}, + {-1, 1, -1}, + { 1, -1, -1}, + {-1, -1, -1}, + { 1, 1, -1}, + {-1, 1, 1}, + { 1, -1, 1}, + { 0, 0, 0}, +}; +const vec4f_t *line[] = {&points[0], &points[1]}; +const vec4f_t *tri[] = {&points[0], &points[1], &points[2]}; +const vec4f_t *tetra[] = {&points[0], &points[1], &points[2], &points[3]}; + +struct { + const vec4f_t **points; + int num_points; + vec4f_t *x; + vec_t expect[4]; +} tests[] = { + {line, 2, &points[0], {1, 0}}, + {line, 2, &points[1], {0, 1}}, + {line, 2, &points[2], {0.5, 0.5}}, + {line, 2, &points[3], {0.5, 0.5}}, + {line, 2, &points[8], {0.5, 0.5}}, + {tri, 3, &points[0], {1, 0, 0}}, + {tri, 3, &points[1], {0, 1, 0}}, + {tri, 3, &points[2], {0, 0, 1}}, + {tri, 3, &points[3], {0.333333284, 0.333333333, 0.333333333}},//rounding :P + {tri, 3, &points[8], {0.333333284, 0.333333333, 0.333333333}},//rounding :P + {tetra, 4, &points[0], {1, 0, 0, 0}}, + {tetra, 4, &points[1], {0, 1, 0, 0}}, + {tetra, 4, &points[2], {0, 0, 1, 0}}, + {tetra, 4, &points[3], {0, 0, 0, 1}}, + {tetra, 4, &points[4], { 0.5, -0.5, 0.5, 0.5}}, + {tetra, 4, &points[5], {-0.5, 0.5, 0.5, 0.5}}, + {tetra, 4, &points[6], { 0.5, 0.5, 0.5, -0.5}}, + {tetra, 4, &points[7], { 0.5, 0.5, -0.5, 0.5}}, + {tetra, 4, &points[8], {0.25, 0.25, 0.25, 0.25}}, +}; +#define num_tests (sizeof (tests) / sizeof (tests[0])) + +static inline float +rnd (mtstate_t *mt) +{ + union { + uint32_t u; + float f; + } uf; + + do { + uf.u = mtwist_rand (mt) & 0x007fffff; + } while (!uf.u); + uf.u |= 0x40000000; + + return uf.f - 3.0; +} + +int +main (int argc, const char **argv) +{ + int res = 0; + size_t i; + int j; + vec4f_t lambda; + mtstate_t mt; + double start, end; + + for (i = 0; i < num_tests; i ++) { + lambda = BarycentricCoords_vf (tests[i].points, tests[i].num_points, *tests[i].x); + for (j = 0; j < tests[i].num_points; j++) { + if (tests[i].expect[j] != lambda[j]) + break; + } + if (j != tests[i].num_points) { + res = 1; + printf ("test %d failed\n", (int) i); + printf ("expect:"); + for (j = 0; j < tests[i].num_points; j++) + printf (" %.9g", tests[i].expect[j]); + printf ("\ngot :"); + for (j = 0; j < tests[i].num_points; j++) + printf (" %.9g", lambda[j]); + printf ("\n"); + } + } + + mtwist_seed (&mt, 0); + start = Sys_DoubleTime (); + for (i = 0; i < 1000000; i++) { + vec4f_t p = { rnd (&mt), rnd (&mt), rnd (&mt) }; + vec4f_t x = {}; + lambda = BarycentricCoords_vf (tetra, 4, p); + for (j = 0; j < 4; j++) { + x = x + lambda[j] * *tetra[j]; + } + if (VectorDistance_fast (x, p) > 1e-4) { + res = 1; + printf ("[%.9g %.9g %.9g] != [%.9g %.9g %.9g]: [%g %g %g %g]\n", + VectorExpand (x), VectorExpand (p), QuatExpand (lambda)); + break; + } + } + end = Sys_DoubleTime (); + printf ("%d itterations in %gs: %g itters/second\n", (int) i, end - start, + i / (end - start)); + return res; +} diff --git a/libs/util/test/test-csvf.c b/libs/util/test/test-csvf.c new file mode 100644 index 000000000..e90aab0c0 --- /dev/null +++ b/libs/util/test/test-csvf.c @@ -0,0 +1,103 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/mathlib.h" +#include "QF/mersenne.h" +#include "QF/simd/vec4f.h" +#include "QF/sys.h" + +const vec4f_t points[] = { + {-1, -1, 1}, + { 1, 1, 1}, + {-1, 1, -1}, + { 1, -1, -1}, + {-1, -1, -1}, + { 1, 1, -1}, + {-1, 1, 1}, + { 1, -1, 1}, + { 0, 0, 0}, +}; + +struct { + const vec4f_t *points; + int num_points; + sphere_t expect; +} tests[] = { + {0, 0, {{ 0, 0, 0}, 0}}, + {points, 1, {{-1, -1, 1}, 0}}, + {points, 2, {{ 0, 0, 1}, 1.41421356}}, + {points, 3, {{-0.333333343, 0.333333343, 0.333333343}, 1.63299322}}, + {points, 4, {{0, 0, 0}, 1.73205081}}, +}; +#define num_tests (sizeof (tests) / sizeof (tests[0])) + +static inline float +rnd (mtstate_t *mt) +{ + union { + uint32_t u; + float f; + } uf; + + do { + uf.u = mtwist_rand (mt) & 0x007fffff; + } while (!uf.u); + uf.u |= 0x40000000; + return uf.f - 3.0; +} + +int +main (int argc, const char **argv) +{ + int res = 0; + size_t i, j; + vspheref_t sphere; + mtstate_t mt; + double start, end; + + for (i = 0; i < num_tests; i ++) { + sphere = CircumSphere_vf (tests[i].points, tests[i].num_points); + if (VectorDistance_fast (sphere.center, tests[i].expect.center) > 1e-4 + || fabs (sphere.radius - tests[i].expect.radius) > 1e-4) { + res = 1; + printf ("test %d failed\n", (int) i); + printf ("expect: [%.9g %.9g %.9g],%.9g\n", + VectorExpand (tests[i].expect.center), + tests[i].expect.radius); + printf ("got : [%.9g %.9g %.9g],%.9g\n", + VectorExpand (sphere.center), + sphere.radius); + } + } + + mtwist_seed (&mt, 0); + start = Sys_DoubleTime (); + for (i = 0; !res && i < 1000000; i++) { + vec4f_t cloud[4]; + vspheref_t cc; + vec_t r2; + + for (j = 0; j < 4; j++) { + VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), cloud[j]); + } + cc = CircumSphere_vf (cloud, 4); + r2 = cc.radius * cc.radius; + for (j = 0; j < 4; j++) { + if (fabs (VectorDistance_fast (cloud[j], cc.center) - r2) + < 1e-3 * r2) + continue; + printf ("%d %.9g - %.9g = %.9g\n", (int)j, + VectorDistance_fast (cloud[j], cc.center), r2, + VectorDistance_fast (cloud[j], cc.center) - r2); + printf ("[%.9g %.9g %.9g] - [%.9g %.9g %.9g] = %.9g != %.9g\n", + VectorExpand (cloud[j]), VectorExpand (cc.center), + VectorDistance_fast (cloud[j], cc.center), r2); + res = 1; + } + } + end = Sys_DoubleTime (); + printf ("%d itterations in %gs: %g itters/second\n", (int) i, end - start, + i / (end - start)); + return res; +} diff --git a/libs/util/test/test-sebvf.c b/libs/util/test/test-sebvf.c new file mode 100644 index 000000000..55fc8b654 --- /dev/null +++ b/libs/util/test/test-sebvf.c @@ -0,0 +1,103 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/mathlib.h" +#include "QF/mersenne.h" +#include "QF/sys.h" +#include "QF/simd/vec4f.h" + +const vec4f_t points[] = { + {-1, -1, 1, 1}, + { 1, 1, 1, 1}, + {-1, 1, -1, 1}, + { 1, -1, -1, 1}, + {-1, -1, -1, 1}, + { 1, 1, -1, 1}, + {-1, 1, 1, 1}, + { 1, -1, 1, 1}, + { 0, 0, 0, 1}, +}; + +struct { + const vec4f_t *points; + int num_points; + vspheref_t expect; +} tests[] = { + {0, 0, {{ 0, 0, 0, 1}, 0}}, + {points, 1, {{-1, -1, 1, 1}, 0}}, + {points, 2, {{ 0, 0, 1, 1}, 1.41421356}}, + {points, 3, {{-0.333333343, 0.333333343, 0.333333343, 1}, 1.63299322}}, + {points, 4, {{0, 0, 0, 1}, 1.73205081}}, +}; +#define num_tests (sizeof (tests) / sizeof (tests[0])) + +static inline float +rnd (mtstate_t *mt) +{ + union { + uint32_t u; + float f; + } uf; + + do { + uf.u = mtwist_rand (mt) & 0x007fffff; + } while (!uf.u); + uf.u |= 0x40000000; + return uf.f - 1.0; +} + +int +main (int argc, const char **argv) +{ + int res = 0; + size_t i, j; + vspheref_t sphere; + mtstate_t mt; + double start, end; + + for (i = 0; i < num_tests; i ++) { + sphere = SmallestEnclosingBall_vf (tests[i].points, tests[i].num_points); + if (VectorDistance_fast (sphere.center, tests[i].expect.center) > 1e-4 + || fabs (sphere.radius - tests[i].expect.radius) > 1e-4) { + res = 1; + printf ("test %d failed\n", (int) i); + printf ("expect: [%.9g %.9g %.9g],%.9g\n", + VectorExpand (tests[i].expect.center), + tests[i].expect.radius); + printf ("got : [%.9g %.9g %.9g],%.9g\n", + VectorExpand (sphere.center), + sphere.radius); + } + } + + mtwist_seed (&mt, 0); + start = Sys_DoubleTime (); + for (i = 0; !res && i < 1000000; i++) { + vec4f_t cloud[10]; + vspheref_t seb; + vec_t r2; + + for (j = 0; j < 5; j++) { + VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), cloud[j]); + } + seb = SmallestEnclosingBall_vf (cloud, 5); + r2 = seb.radius * seb.radius; + for (j = 0; j < 5; j++) { + if (VectorDistance_fast (cloud[j], seb.center) - r2 + > 1e-5 * r2) { + res = 1; + printf ("%d %.9g - %.9g = %.9g\n", (int)j, + VectorDistance_fast (cloud[j], seb.center), r2, + VectorDistance_fast (cloud[j], seb.center) - r2); + printf ("[%.9g %.9g %.9g] - [%.9g %.9g %.9g] = %.9g > %.9g\n", + VectorExpand (cloud[j]), VectorExpand (seb.center), + VectorDistance_fast (cloud[j], seb.center), r2); + } + } + } + end = Sys_DoubleTime (); + printf ("%d iterations in %gs: %g iters/second\n", (int) i, end - start, + i / (end - start)); + return res; +} From eb325376b17d41c3b7a774c3059e40355cb7a878 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Mar 2021 11:59:58 +0900 Subject: [PATCH 1456/3664] [qfvis] Collect base vis culling stats Specifically, just how many are culled by sphere and winding tests. --- tools/qfvis/include/vis.h | 2 ++ tools/qfvis/source/base-vis.c | 10 ++++++++-- tools/qfvis/source/qfvis.c | 9 ++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index ba4537b3d..2e32d0d1e 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -177,6 +177,8 @@ typedef struct threaddata_s { typedef struct { set_t *portalsee; + unsigned spherecull; ///< number of portals culled by sphere tests + unsigned windingcull; ///< number of portals culled by winding tests int clustersee; int id; } basethread_t; diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index 77f2b266b..55928af52 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -122,12 +122,14 @@ PortalBase (basethread_t *thread, portal_t *portal) if (tp_side < 0) { // The test portal definitely is entirely behind the portal's // plane. + thread->spherecull++; continue; // entirely behind } portal_side = test_sphere (&portal->sphere, &tp->plane); if (portal_side > 0) { // The portal definitely is entirely in front of the test // portal's plane. + thread->spherecull++; continue; // entirely in front } @@ -141,8 +143,10 @@ PortalBase (basethread_t *thread, portal_t *portal) if (d > ON_EPSILON) break; } - if (k == winding->numpoints) + if (k == winding->numpoints) { + thread->windingcull++; continue; // no points on front + } } if (portal_side == 0) { @@ -155,8 +159,10 @@ PortalBase (basethread_t *thread, portal_t *portal) if (d < -ON_EPSILON) break; } - if (k == winding->numpoints) + if (k == winding->numpoints) { + thread->windingcull++; continue; // no points on front + } } set_add (thread->portalsee, j); diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index b534e6252..8a4ea3c3f 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -75,6 +75,8 @@ options_t options; static threaddata_t main_thread; static visstat_t stats; int base_mightsee; +unsigned base_spherecull; +unsigned base_windingcull; static unsigned portal_count; unsigned numportals; @@ -530,6 +532,8 @@ BaseVisThread (void *_thread) } while (1); WRLOCK (stats_lock); + base_spherecull += data.spherecull; + base_windingcull += data.windingcull; base_mightsee += num_mightsee; UNLOCK (stats_lock); @@ -767,8 +771,11 @@ BasePortalVis (void) RunThreads (BaseVisThread); end = Sys_DoubleTime (); - if (options.verbosity >= 1) + if (options.verbosity >= 1) { printf ("base_mightsee: %d %gs\n", base_mightsee, end - start); + printf ("sphere cull: %u winding cull %u\n", + base_spherecull, base_windingcull); + } } static void From b6ab832ed4aee2c55f5b66a0227159c763a0f353 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Mar 2021 19:49:43 +0900 Subject: [PATCH 1457/3664] [simd] Add vabsf and some more tests --- include/QF/simd/vec4f.h | 14 +++++++++++++ libs/util/test/test-simd.c | 42 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 04ee24c94..8ae4cbd5e 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -32,6 +32,7 @@ #include "QF/simd/types.h" +GNU89INLINE inline vec4f_t vabsf (vec4f_t v) __attribute__((const)); GNU89INLINE inline vec4f_t vsqrtf (vec4f_t v) __attribute__((const)); GNU89INLINE inline vec4f_t vceilf (vec4f_t v) __attribute__((const)); GNU89INLINE inline vec4f_t vfloorf (vec4f_t v) __attribute__((const)); @@ -97,6 +98,19 @@ GNU89INLINE inline vec4f_t normalf (vec4f_t v) __attribute__((pure)); GNU89INLINE inline vec4f_t magnitudef (vec4f_t v) __attribute__((pure)); GNU89INLINE inline vec4f_t magnitude3f (vec4f_t v) __attribute__((pure)); +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +vabsf (vec4f_t v) +{ + const uint32_t nan = ~0u >> 1; + const vec4i_t abs = { nan, nan, nan, nan }; + return _mm_and_ps (v, (__m128) abs); +} + #ifndef IMPLEMENT_VEC4F_Funcs GNU89INLINE inline #else diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index b14a1be9c..ebaab413f 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -27,6 +27,9 @@ #define none { -1, -1, -1, -1 } #define nqident { 0, 0, 0, -1 } +#define pi { M_PI, M_PI, M_PI, M_PI } // lots of bits +#define pmpi { -M_PI, M_PI, -M_PI, M_PI } // lots of bits + #define identity \ { { 1, 0, 0, 0 }, \ { 0, 1, 0, 0 }, \ @@ -124,6 +127,26 @@ static vec4f_t tqconjf (vec4f_t v, vec4f_t ignore) return qconjf (v); } +static vec4f_t tvabsf (vec4f_t v, vec4f_t ignore) +{ + return vabsf (v); +} + +static vec4f_t tvsqrtf (vec4f_t v, vec4f_t ignore) +{ + return vsqrtf (v); +} + +static vec4f_t tmagnitudef (vec4f_t v, vec4f_t ignore) +{ + return magnitudef (v); +} + +static vec4f_t tmagnitude3f (vec4f_t v, vec4f_t ignore) +{ + return magnitude3f (v); +} + static vec4d_test_t vec4d_tests[] = { // 3D dot products { dotd, right, right, one }, @@ -348,10 +371,29 @@ static vec4f_test_t vec4f_tests[] = { { qrotf, up, forward, { -s05, 0, 0, s05 } }, { qrotf, up, up, qident }, + { tvabsf, pmpi, {}, pi }, + { tvsqrtf, { 1, 4, 9, 16}, {}, {1, 2, 3, 4} }, { tvtruncf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -1, -2 } }, { tvceilf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 2, 3, -1, -2 } }, { tvfloorf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -2, -3 } }, { tqconjf, one, {}, { -1, -1, -1, 1 } }, + { tmagnitudef, { 3, 4, 12, 84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { 3, 4, 12, -84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { 3, 4, -12, 84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { 3, 4, -12, -84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { 3, -4, 12, 84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { 3, -4, 12, -84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { 3, -4, -12, 84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { 3, -4, -12, -84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { -3, 4, 12, 84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { -3, 4, 12, -84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { -3, 4, -12, 84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { -3, 4, -12, -84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { -3, -4, 12, 84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { -3, -4, 12, -84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { -3, -4, -12, 84}, {}, {85, 85, 85, 85} }, + { tmagnitudef, { -3, -4, -12, -84}, {}, {85, 85, 85, 85} }, + { tmagnitude3f, { -3, -4, -12, -84}, {}, {13, 13, 13, 13} }, }; #define num_vec4f_tests (sizeof (vec4f_tests) / (sizeof (vec4f_tests[0]))) From ff4cd84891178329832c2667a89f127aca57570e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Mar 2021 19:55:47 +0900 Subject: [PATCH 1458/3664] [qfvis] Use simd vector code While whether it's any faster is debatable (it's slightly slower, but many more portals are being tested due to different rounding in the base vis stage), it's certainly easier to read. --- tools/qfvis/include/vis.h | 19 +-- tools/qfvis/source/base-vis.c | 37 +++--- tools/qfvis/source/flow.c | 97 +++++++-------- tools/qfvis/source/qfvis.c | 228 +++++++++++++++++++++++----------- 4 files changed, 236 insertions(+), 145 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 2e32d0d1e..279c0e72f 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -74,6 +74,7 @@ extern pthread_rwlock_t *portal_locks; #include "QF/cmem.h" #include "QF/set.h" +#include "QF/simd/vec4f.h" #define MAX_PORTALS 32768 #define PORTALFILE "PRT1" @@ -87,7 +88,9 @@ typedef struct winding_s { struct winding_s *next; qboolean original; // don't free, it's part of the portal unsigned numpoints; - vec3_t points[MAX_PORTALS_ON_CLUSTER]; // variable sized + int id; + int thread; + vec4f_t points[MAX_PORTALS_ON_CLUSTER]; // variable sized } winding_t; typedef enum { @@ -98,9 +101,9 @@ typedef enum { } vstatus_t; typedef struct { - plane_t plane; // normal pointing into neighbor + vec4f_t plane; // normal pointing into neighbor + vspheref_t sphere; // bounding sphere int cluster; // neighbor - sphere_t sphere; // bounding sphere winding_t *winding; vstatus_t status; set_t *visbits; @@ -110,8 +113,8 @@ typedef struct { } portal_t; typedef struct seperating_plane_s { + vec4f_t plane; // from portal is on positive side struct seperating_plane_s *next; - plane_t plane; // from portal is on positive side } sep_t; typedef struct passage_s { @@ -122,9 +125,9 @@ typedef struct passage_s { typedef struct cluster_s { int numportals; + int visofs; passage_t *passages; portal_t *portals[MAX_PORTALS_ON_CLUSTER]; - int visofs; } cluster_t; typedef struct pstack_s { @@ -132,8 +135,8 @@ typedef struct pstack_s { cluster_t *cluster; ///< the cluster being sub-vised winding_t *source_winding; ///< clipped source portal winding portal_t *pass_portal; ///< the portal exiting from the cluster + vec4f_t pass_plane; ///< plane of the pass portal winding_t *pass_winding; ///< clipped pass portal winding - plane_t pass_plane; ///< plane of the pass portal set_t *mightsee; sep_t *separators[2]; } pstack_t; @@ -173,6 +176,7 @@ typedef struct threaddata_s { memsuper_t *memsuper; ///< per-thread memory pool set_pool_t set_pool; int id; + int winding_id; } threaddata_t; typedef struct { @@ -198,7 +202,8 @@ extern byte *uncompressed; void FreeWinding (threaddata_t *thread, winding_t *w); winding_t *NewWinding (threaddata_t *thread, int points); -winding_t *ClipWinding (threaddata_t *thread, winding_t *in, const plane_t *split, qboolean keepon); +winding_t *ClipWinding (threaddata_t *thread, winding_t *in, vec4f_t split, + qboolean keepon); winding_t *CopyWinding (threaddata_t *thread, const winding_t *w); void ClusterFlow (int clusternum); diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index 55928af52..089b196f9 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -84,24 +84,25 @@ SimpleFlood (basethread_t *thread, portal_t *srcportal, int clusternum) } static inline int -test_sphere (sphere_t *sphere, plane_t *plane) +test_sphere (const vspheref_t *sphere, vec4f_t plane) { - float d; - int front, back; + const vec4f_t zero = {}; + float r = sphere->radius; + vec4f_t eps = { r, r, r, r }; + vec4f_t d = _mm_addsub_ps (zero, dotf (sphere->center, plane)); + vec4i_t c = (d - eps) >= 0; - d = DotProduct (sphere->center, plane->normal) - plane->dist; - front = (d >= sphere->radius); - back = (d <= -sphere->radius); - return front - back; + c = (vec4i_t) _mm_hsub_epi32 ((__m128i) c, (__m128i) c); + return c[0]; } void PortalBase (basethread_t *thread, portal_t *portal) { - unsigned i, j, k; - float d; - portal_t *tp; - winding_t *winding; + unsigned i, j, k; + vec4f_t d; + portal_t *tp; + winding_t *winding; int tp_side, portal_side; i = portal - portals; @@ -118,14 +119,14 @@ PortalBase (basethread_t *thread, portal_t *portal) // visibility. // First check using the bounding spheres of the two portals. - tp_side = test_sphere (&tp->sphere, &portal->plane); + tp_side = test_sphere (&tp->sphere, portal->plane); if (tp_side < 0) { // The test portal definitely is entirely behind the portal's // plane. thread->spherecull++; continue; // entirely behind } - portal_side = test_sphere (&portal->sphere, &tp->plane); + portal_side = test_sphere (&portal->sphere, tp->plane); if (portal_side > 0) { // The portal definitely is entirely in front of the test // portal's plane. @@ -138,9 +139,8 @@ PortalBase (basethread_t *thread, portal_t *portal) // do a more refined check. winding = tp->winding; for (k = 0; k < winding->numpoints; k++) { - d = DotProduct (winding->points[k], - portal->plane.normal) - portal->plane.dist; - if (d > ON_EPSILON) + d = dotf (winding->points[k], portal->plane); + if (d[0] > ON_EPSILON) break; } if (k == winding->numpoints) { @@ -154,9 +154,8 @@ PortalBase (basethread_t *thread, portal_t *portal) // do a more refined check. winding = portal->winding; for (k = 0; k < winding->numpoints; k++) { - d = DotProduct (winding->points[k], - tp->plane.normal) - tp->plane.dist; - if (d < -ON_EPSILON) + d = dotf (winding->points[k], tp->plane); + if (d[0] < -ON_EPSILON) break; } if (k == winding->numpoints) { diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 671ea7ab7..14e039ead 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -133,48 +133,47 @@ test_zero (float d) } static int -calc_plane (const vec3_t v1, const vec3_t v2, int flip, const vec3_t p, - plane_t *plane) +calc_plane (vec4f_t v1, vec4f_t v2, int flip, vec4f_t p, vec4f_t *plane) { - vec_t length; + vec4f_t length; if (flip < 0) { //CrossProduct (v2, v1, plane.normal); - plane->normal[0] = v2[1] * v1[2] - v2[2] * v1[1]; - plane->normal[1] = v2[2] * v1[0] - v2[0] * v1[2]; - plane->normal[2] = v2[0] * v1[1] - v2[1] * v1[0]; + (*plane)[0] = v2[1] * v1[2] - v2[2] * v1[1]; + (*plane)[1] = v2[2] * v1[0] - v2[0] * v1[2]; + (*plane)[2] = v2[0] * v1[1] - v2[1] * v1[0]; } else { //CrossProduct (v1, v2, plane.normal); - plane->normal[0] = v1[1] * v2[2] - v1[2] * v2[1]; - plane->normal[1] = v1[2] * v2[0] - v1[0] * v2[2]; - plane->normal[2] = v1[0] * v2[1] - v1[1] * v2[0]; + (*plane)[0] = v1[1] * v2[2] - v1[2] * v2[1]; + (*plane)[1] = v1[2] * v2[0] - v1[0] * v2[2]; + (*plane)[2] = v1[0] * v2[1] - v1[1] * v2[0]; } + (*plane)[3] = 0; - length = DotProduct (plane->normal, plane->normal); + length = dotf (*plane, *plane); // if points don't make a valid plane, skip it - if (length < ON_EPSILON) + if (length[0] < ON_EPSILON) return 0; - length = 1 / sqrt (length); - VectorScale (plane->normal, length, plane->normal); - plane->dist = DotProduct (p, plane->normal); + *plane /= vsqrtf (length); + (*plane)[3] = -dotf (p, *plane)[0]; return 1; } static inline int -test_plane (const plane_t *plane, const winding_t *pass, int index) +test_plane (vec4f_t plane, const winding_t *pass, int index) { int s1, s2; int k; - vec_t d; + vec4f_t d; k = (index + 1) % pass->numpoints; - d = DotProduct (pass->points[k], plane->normal) - plane->dist; - s1 = test_zero (d); + d = dotf (pass->points[k], plane); + s1 = test_zero (d[0]); k = (index + pass->numpoints - 1) % pass->numpoints; - d = DotProduct (pass->points[k], plane->normal) - plane->dist; - s2 = test_zero (d); + d = dotf (pass->points[k], plane); + s2 = test_zero (d[0]); if (s1 == 0 && s2 == 0) return 0; if (s1 < 0 || s2 < 0) @@ -183,32 +182,30 @@ test_plane (const plane_t *plane, const winding_t *pass, int index) } static inline sep_t * -create_separator (threaddata_t *thread, const plane_t *src_pl, - const vec3_t p1, const vec3_t v1, +create_separator (threaddata_t *thread, vec4f_t src_pl, vec4f_t p1, vec4f_t v1, const winding_t *pass, int index, int flip) { int fliptest; - vec_t d; - vec3_t v2; - plane_t plane; + vec4f_t d; + vec4f_t v2; + vec4f_t plane; sep_t *sep; - d = DotProduct (pass->points[index], src_pl->normal) - src_pl->dist; - if ((fliptest = test_zero (d)) == 0) + d = dotf (pass->points[index], src_pl); + if ((fliptest = test_zero (d[0])) == 0) return 0; // The point lies in the source plane - VectorSubtract (pass->points[index], p1, v2); + v2 = pass->points[index] - p1; if (!calc_plane (v1, v2, fliptest, pass->points[index], &plane)) return 0; // point does not form a valid plane - if (!test_plane (&plane, pass, index)) + if (!test_plane (plane, pass, index)) return 0; // not the right point sep = new_separator (thread); // flip the normal if we want the back side if (flip) { - VectorNegate (plane.normal, sep->plane.normal); - sep->plane.dist = -plane.dist; + sep->plane = -plane; } else { sep->plane = plane; } @@ -233,20 +230,20 @@ create_separator (threaddata_t *thread, const plane_t *src_pl, */ static sep_t * FindSeparators (threaddata_t *thread, - const winding_t *source, const plane_t src_pl, + const winding_t *source, vec4f_t src_pl, const winding_t *pass, int flip) { unsigned i, j, l; - vec3_t v1; + vec4f_t v1; sep_t *separators = 0, *sep; for (i = 0; i < source->numpoints; i++) { l = (i + 1) % source->numpoints; - VectorSubtract (source->points[l], source->points[i], v1); + v1 = source->points[l] - source->points[i]; for (j = 0; j < pass->numpoints; j++) { - sep = create_separator (thread, &src_pl, source->points[i], v1, + sep = create_separator (thread, src_pl, source->points[i], v1, pass, j, flip); if (sep) { sep->next = separators; @@ -259,12 +256,13 @@ FindSeparators (threaddata_t *thread, } static winding_t * -ClipToSeparators (threaddata_t *thread, const sep_t *separators, winding_t *target) +ClipToSeparators (threaddata_t *thread, const sep_t *separators, + winding_t *target) { const sep_t *sep; for (sep = separators; target && sep; sep = sep->next) { - target = ClipWinding (thread, target, &sep->plane, false); + target = ClipWinding (thread, target, sep->plane, false); } return target; } @@ -304,7 +302,6 @@ mightsee_more (set_t *might, const set_t *prev_might, const set_t *test, RecursiveClusterFlow Flood fill through the clusters - If src_portal is NULL, this is the originating cluster */ static void RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) @@ -315,8 +312,8 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) cluster_t *cluster; pstack_t *stack; portal_t *target_portal; - plane_t backplane; - const plane_t *source_plane, *pass_plane; + vec4f_t backplane; + vec4f_t source_plane, pass_plane; const winding_t *pass_winding; winding_t *source_winding, *target_winding; @@ -344,9 +341,9 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) might = stack->mightsee; vis = thread->clustervis; - source_plane = &thread->pstack_head.pass_plane; + source_plane = thread->pstack_head.pass_plane; pass_winding = prevstack->pass_winding; - pass_plane = &prevstack->pass_plane; + pass_plane = prevstack->pass_plane; // check all portals for flowing into other clusters for (i = 0; i < cluster->numportals; i++) { @@ -363,11 +360,13 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) } // get plane of target_portal, point normal into the neighbor cluster - VectorNegate (target_portal->plane.normal, backplane.normal); - backplane.dist = -target_portal->plane.dist; + backplane = -target_portal->plane; - if (_VectorCompare (pass_plane->normal, backplane.normal)) + vec4f_t diff = vabsf (pass_plane - backplane); + vec4i_t cmp = diff > (vec4f_t) {0.001, 0.001, 0.001, 0.001}; + if (!(cmp[0] || cmp[1] || cmp[2])) { // dist isn't interesting continue; // can't go out a coplanar face + } thread->stats.portalcheck++; @@ -398,7 +397,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) // if it gets clipped away, earlier stack levels will get corrupted source_winding = CopyWinding (thread, prevstack->source_winding); - source_winding = ClipWinding (thread, source_winding, &backplane, false); + source_winding = ClipWinding (thread, source_winding, backplane, false); if (!source_winding) { FreeWinding (thread, target_winding); continue; @@ -412,7 +411,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) if (!stack->separators[0]) stack->separators[0] = FindSeparators (thread, source_winding, - *source_plane, + source_plane, pass_winding, 0); target_winding = ClipToSeparators (thread, stack->separators[0], @@ -431,7 +430,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) if (!stack->separators[1]) stack->separators[1] = FindSeparators (thread, pass_winding, - *pass_plane, + pass_plane, source_winding, 1); target_winding = ClipToSeparators (thread, stack->separators[1], @@ -466,7 +465,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) if (options.level > 3) { winding_t *old = source_winding; sep_t *sep; - sep = FindSeparators (thread, pass_winding, *pass_plane, + sep = FindSeparators (thread, pass_winding, pass_plane, target_winding, 1); source_winding = ClipToSeparators (thread, sep, source_winding); free_separators (thread, sep); diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 8a4ea3c3f..347f65d51 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -134,17 +134,19 @@ EndThreads (void) #endif } -static void -PlaneFromWinding (winding_t *winding, plane_t *plane) +static vec4f_t +PlaneFromWinding (winding_t *winding) { - vec3_t v1, v2; + vec4f_t plane; + vec4f_t v1, v2; // calc plane using CW winding - VectorSubtract (winding->points[2], winding->points[1], v1); - VectorSubtract (winding->points[0], winding->points[1], v2); - CrossProduct (v2, v1, plane->normal); - _VectorNormalize (plane->normal); - plane->dist = DotProduct (winding->points[0], plane->normal); + v1 = winding->points[2] - winding->points[1]; + v2 = winding->points[0] - winding->points[1]; + plane = normalf (crossf (v2, v1)); + // negative so dot(point, plane) includes -dist (point[3] = 1) + plane[3] = -dotf (winding->points[0], plane)[0]; + return plane; } winding_t * @@ -160,6 +162,8 @@ NewWinding (threaddata_t *thread, int points) winding = CMEMALLOC (13, winding_t, thread->winding, thread->memsuper); memset (winding, 0, size); thread->stats.winding_alloc++; + winding->id = thread->winding_id++; + winding->thread = thread->id; return winding; } @@ -188,6 +192,8 @@ CopyWinding (threaddata_t *thread, const winding_t *w) memcpy (copy, w, size); copy->original = false; thread->stats.winding_alloc++; + copy->id = thread->winding_id++; + copy->thread = thread->id; return copy; } @@ -198,12 +204,111 @@ NewFlippedWinding (threaddata_t *thread, const winding_t *w) unsigned i; flipped = NewWinding (thread, w->numpoints); - for (i = 0; i < w->numpoints; i++) - VectorCopy (w->points[i], flipped->points[w->numpoints - 1 - i]); + for (i = 0; i < w->numpoints; i++) { + flipped->points[w->numpoints - 1 - i] = w->points[i]; + } flipped->numpoints = w->numpoints; return flipped; } +static vec4i_t +signeps (vec4f_t dist) +{ + const vec4f_t zero = {}; + const vec4f_t eps = { ON_EPSILON, ON_EPSILON, ON_EPSILON, ON_EPSILON }; + vec4f_t d = _mm_addsub_ps (zero, dist); + vec4i_t c = (d - eps) > 0; + c = (vec4i_t) _mm_hsub_epi32 ((__m128i) c, (__m128i) c); + return c; +} + +static vec4f_t +split_edge (const vec4f_t *points, const vec4f_t *dists, + int ind1, int ind2, vec4f_t split) +{ + vec4f_t p1 = points[ind1]; + vec4f_t p2 = points[ind2]; + vec4f_t d1 = dists[ind1]; + vec4f_t d2 = dists[ind2]; + // avoid nan/inf in w: d1's w is never 0 (would not be here if it was) + // so the multiply ensures d1.w - d2.w cannot be 0 and thus d1.w/diff + // will not result in division by 0 + static const vec4f_t one = { 1, 1, 1, 0 }; + vec4f_t d = d1 / (d1 - d2 * one); + vec4f_t mid = p1 + d * (p2 - p1); + + // avoid roundoff error when possible by forcing the appropriate + // component to the split-plane's distance when the split-plane's + // normal is signed-canonical. + // "nan" because 0x7fffffff is nan when viewed as a float + static const vec4f_t onenan = { 1, 1, 1, ~0u >> 1 }; + static const vec4i_t nan = { ~0u >> 1, ~0u >> 1, ~0u >> 1, ~0u >> 1}; + vec4i_t x = _mm_and_ps (split, (__m128) nan) == onenan; + // plane vector has -dist in w + vec4f_t y = _mm_and_ps (split, (__m128) x) * -split[3]; + mid = _mm_blendv_ps (mid, y, (__m128) x); + if (isnan (mid[0])) *(int *) 0 = 0; + return mid; +} + +static inline int __attribute__((const)) +is_not_on (int x) +{ + return x & 1; +} + +static inline int __attribute__((const)) +is_back (int x) +{ + return x & 2; +} + +static inline int __attribute__((const)) +is_not_back (unsigned x) +{ + return ~x & 2; +} + +static inline int __attribute__((const)) +is_front (unsigned x) +{ + return is_not_on (x) & (is_not_back (x) >> 1); +} + +static inline int __attribute__((const)) +is_back_front (unsigned x, unsigned y) +{ + return (is_back (x) >> 1) & is_front (y); +} + +static inline int __attribute__((const)) +is_front_back (unsigned x, unsigned y) +{ + return is_front (x) & (is_back (y) >> 1); +} + +static inline int __attribute__((const)) +is_transition (unsigned x, unsigned y) +{ + return is_back_front (x, y) | is_front_back (x, y); +} + +static inline void +test_point (vec4f_t split, const vec4f_t *points, int index, vec4f_t *dists, + int *sides, unsigned *counts) +{ + dists[index] = dotf (points[index], split); + sides[index] = signeps (dists[index])[0]; + counts[sides[index]]++; +} + +#undef SIDE_FRONT +#undef SIDE_BACK +#undef SIDE_ON +#define SIDE_FRONT 1 +#define SIDE_BACK -1 +#define SIDE_ON 0 + /* ClipWinding @@ -216,86 +321,68 @@ NewFlippedWinding (threaddata_t *thread, const winding_t *w) it will be clipped away. */ winding_t * -ClipWinding (threaddata_t *thread, winding_t *in, const plane_t *split, qboolean keepon) +ClipWinding (threaddata_t *thread, winding_t *in, vec4f_t split, + qboolean keepon) { - unsigned maxpts, i, j; - int counts[3], sides[MAX_POINTS_ON_WINDING]; - vec_t dot; - vec_t dists[MAX_POINTS_ON_WINDING]; - vec_t *p1, *p2; - vec3_t mid; + unsigned maxpts = 0; + unsigned i; + unsigned _counts[3]; + unsigned *const counts = _counts + 1; + int *const sides = alloca ((in->numpoints + 1) * sizeof (int)); + vec4f_t *const dists = alloca ((in->numpoints + 1) * sizeof (vec4f_t)); winding_t *neww; - counts[0] = counts[1] = counts[2] = 0; + counts[SIDE_FRONT] = counts[SIDE_ON] = counts[SIDE_BACK] = 0; // determine sides for each point - for (i = 0; i < in->numpoints; i++) { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > ON_EPSILON) - sides[i] = SIDE_FRONT; - else if (dot < -ON_EPSILON) - sides[i] = SIDE_BACK; - else { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; + test_point (split, in->points, 0, dists, sides, counts); + for (i = 1; i < in->numpoints; i++) { + test_point (split, in->points, i, dists, sides, counts); + maxpts += is_transition (sides[i - 1], sides[i]); } sides[i] = sides[0]; dists[i] = dists[0]; + maxpts += is_transition (sides[i - 1], sides[i]); - if (keepon && !counts[0] && !counts[1]) + if (keepon && counts[SIDE_ON] == in->numpoints) { return in; - - if (!counts[0]) { + } + if (!counts[SIDE_FRONT]) { FreeWinding (thread, in); return NULL; } - if (!counts[1]) + if (!counts[SIDE_BACK]) { return in; + } - maxpts = in->numpoints + 4; // can't use counts[0] + 2 because - // of fp grouping errors + maxpts += in->numpoints - counts[SIDE_BACK]; neww = NewWinding (thread, maxpts); for (i = 0; i < in->numpoints; i++) { - p1 = in->points[i]; - if (sides[i] == SIDE_ON) { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; + neww->points[neww->numpoints++] = in->points[i]; continue; } - if (sides[i] == SIDE_FRONT) { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; + neww->points[neww->numpoints++] = in->points[i]; } - - if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) + if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) { continue; - - // generate a split point - p2 = in->points[(i + 1) % in->numpoints]; - - dot = dists[i] / (dists[i] - dists[i + 1]); - for (j = 0; j < 3; j++) { - // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot * (p2[j] - p1[j]); } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; + vec4f_t mid = split_edge (in->points, dists, i, + (i + 1) % in->numpoints, split); + neww->points[neww->numpoints++] = mid; } - if (neww->numpoints > maxpts) - Sys_Error ("ClipWinding: points exceeded estimate"); + if (neww->numpoints < maxpts) { + Sys_Error ("ClipWinding: not all points copied: n:%u m:%u i:%u %u %u %u", + neww->numpoints, maxpts, in->numpoints, + counts[SIDE_BACK], counts[SIDE_ON], counts[SIDE_FRONT]); + } + if (neww->numpoints > maxpts) { + Sys_Error ("ClipWinding: points exceeded estimate: n:%u m:%u", + neww->numpoints, maxpts); + } // free the original winding FreeWinding (thread, in); @@ -1033,10 +1120,10 @@ LoadPortals (char *name) int read_leafs = 0; int clusternums[2]; cluster_t *cluster; - plane_t plane; + vec4f_t plane; portal_t *portal; winding_t *winding; - sphere_t sphere; + vspheref_t sphere; QFile *f; if (!strcmp (name, "-")) @@ -1158,6 +1245,7 @@ LoadPortals (char *name) Sys_Error ("LoadPortals: reading portal %u", i); line = err; } + winding->points[j][3] = 1; while (isspace ((byte) *line)) line++; @@ -1165,10 +1253,11 @@ LoadPortals (char *name) Sys_Error ("LoadPortals: reading portal %u", i); } + sphere = SmallestEnclosingBall_vf(winding->points, winding->numpoints); + //printf (VEC4F_FMT" %.9g\n", VEC4_EXP (sphere.center), sphere.radius); + // calc plane - PlaneFromWinding (winding, &plane); - sphere = SmallestEnclosingBall((const vec_t(*)[3])winding->points, - winding->numpoints); + plane = PlaneFromWinding (winding); // create forward portal cluster = &clusters[clusternums[0]]; @@ -1178,8 +1267,7 @@ LoadPortals (char *name) cluster->numportals++; portal->winding = winding; - VectorNegate (plane.normal, portal->plane.normal); - portal->plane.dist = -plane.dist; // plane is for CW, portal is CCW + portal->plane = -plane; // plane is for CW, portal is CCW portal->cluster = clusternums[1]; portal->sphere = sphere; portal++; From 00aa5845067ada4ba2eba545eecd546fa302dd45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Mar 2021 20:25:57 +0900 Subject: [PATCH 1459/3664] [util] Add re-entrant set_as_string Makes it easier to debug set-related code in multi-threaded code. --- include/QF/set.h | 16 ++++++++++++++++ libs/util/set.c | 26 ++++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/include/QF/set.h b/include/QF/set.h index 1261bdb40..52b1fae85 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -356,6 +356,7 @@ set_iter_t *set_first_r (set_pool_t *set_pool, const set_t *set); set_iter_t *set_next (set_iter_t *set_iter); set_iter_t *set_next_r (set_pool_t *set_pool, set_iter_t *set_iter); +struct dstring_s; /** Return a human-readable string representing the set. Empty sets will be represented by the string "{}". Sets of everything @@ -369,6 +370,21 @@ set_iter_t *set_next_r (set_pool_t *set_pool, set_iter_t *set_iter); will overwrite the results of preceeding calls. */ const char *set_as_string (const set_t *set); +/** Return a human-readable string representing the set. + + Empty sets will be represented by the string "{}". Sets of everything + will be represented by the string "{...}". Inverted sets will have + the first implicit member followed by "..." (eg, "256 ..."). + + \param str dstring to which the representation will be written + \param set The set to be converted to a string. + \return The string held in str + + \warning The string is NOT cleared, but rather the set representation + is appeneded to the string. This makes it more useful when + constructing strings in a threaded environment. +*/ +const char *set_as_string_r (struct dstring_s *str, const set_t *set); ///@} #endif//__QF_set_h diff --git a/libs/util/set.c b/libs/util/set.c index dfdd55b4e..6b15154e8 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -608,22 +608,19 @@ set_next (set_iter_t *set_iter) } const char * -set_as_string (const set_t *set) +set_as_string_r (dstring_t *str, const set_t *set) { - static dstring_t *str; unsigned i; - if (!str) - str = dstring_new (); if (set_is_empty (set)) { - dstring_copystr (str, "{}"); + dstring_appendstr (str, "{}"); return str->str; } if (set_is_everything (set)) { - dstring_copystr (str, "{...}"); + dstring_appendstr (str, "{...}"); return str->str; } - dstring_copystr (str, "{"); + dstring_appendstr (str, "{"); for (i = 0; i < set->size; i++) { if (set_is_member (set, i)) { if (str->str[1]) @@ -632,8 +629,21 @@ set_as_string (const set_t *set) dasprintf (str, "%d", i); } } - if (set->inverted) + if (set->inverted) { dasprintf (str, "%s%d ...", str->str[1] ? " " : "", i); + } dstring_appendstr (str, "}"); return str->str; } + +const char * +set_as_string (const set_t *set) +{ + static dstring_t *str; + + if (!str) { + str = dstring_new (); + } + dstring_clearstr (str); + return set_as_string_r (str, set); +} From 0fa65be106ff92d18f33adcb3ff95fd18895a2f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Mar 2021 20:58:29 +0900 Subject: [PATCH 1460/3664] [qfvis] Fix stats collection for mightseeupdate The stats were being updated before UpdateMightsee was getting called, and it was incrementing the wrong value (so it would not have been thread-safe). --- tools/qfvis/source/qfvis.c | 85 +++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 347f65d51..599899f64 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -73,7 +73,7 @@ bsp_t *bsp; options_t options; static threaddata_t main_thread; -static visstat_t stats; +static visstat_t global_stats; int base_mightsee; unsigned base_spherecull; unsigned base_windingcull; @@ -408,7 +408,7 @@ GetNextPortal (int limit) } static void -UpdateMightsee (cluster_t *source, cluster_t *dest) +UpdateMightsee (threaddata_t *thread, cluster_t *source, cluster_t *dest) { int i, clusternum; portal_t *portal; @@ -421,13 +421,40 @@ UpdateMightsee (cluster_t *source, cluster_t *dest) if (set_is_member (portal->mightsee, clusternum)) { set_remove (portal->mightsee, clusternum); portal->nummightsee--; - stats.mightseeupdate++; + thread->stats.mightseeupdate++; } } UNLOCK_PORTAL (portal); } } +static void +UpdateStates (threaddata_t *thread) +{ + WRLOCK (stats_lock); + global_stats.portaltest += thread->stats.portaltest; + global_stats.portalpass += thread->stats.portalpass; + global_stats.portalcheck += thread->stats.portalcheck; + global_stats.targettested += thread->stats.targettested; + global_stats.targettrimmed += thread->stats.targettrimmed; + global_stats.targetclipped += thread->stats.targetclipped; + global_stats.sourcetested += thread->stats.sourcetested; + global_stats.sourcetrimmed += thread->stats.sourcetrimmed; + global_stats.sourceclipped += thread->stats.sourceclipped; + global_stats.chains += thread->stats.chains; + global_stats.mighttest += thread->stats.mighttest; + global_stats.vistest += thread->stats.vistest; + global_stats.mightseeupdate += thread->stats.mightseeupdate; + global_stats.sep_alloc += thread->stats.sep_alloc; + global_stats.sep_free += thread->stats.sep_free; + global_stats.winding_alloc += thread->stats.winding_alloc; + global_stats.winding_free += thread->stats.winding_free; + global_stats.stack_alloc += thread->stats.stack_alloc; + global_stats.stack_free += thread->stats.stack_free; + UNLOCK (stats_lock); + memset (&thread->stats, 0, sizeof (thread->stats)); +} + static void PortalCompleted (threaddata_t *thread, portal_t *completed) { @@ -438,28 +465,6 @@ PortalCompleted (threaddata_t *thread, portal_t *completed) int i, j; completed->status = stat_done; - WRLOCK (stats_lock); - stats.portaltest += thread->stats.portaltest; - stats.portalpass += thread->stats.portalpass; - stats.portalcheck += thread->stats.portalcheck; - stats.targettested += thread->stats.targettested; - stats.targettrimmed += thread->stats.targettrimmed; - stats.targetclipped += thread->stats.targetclipped; - stats.sourcetested += thread->stats.sourcetested; - stats.sourcetrimmed += thread->stats.sourcetrimmed; - stats.sourceclipped += thread->stats.sourceclipped; - stats.chains += thread->stats.chains; - stats.mighttest += thread->stats.mighttest; - stats.vistest += thread->stats.vistest; - stats.mightseeupdate += thread->stats.mightseeupdate; - stats.sep_alloc += thread->stats.sep_alloc; - stats.sep_free += thread->stats.sep_free; - stats.winding_alloc += thread->stats.winding_alloc; - stats.winding_free += thread->stats.winding_free; - stats.stack_alloc += thread->stats.stack_alloc; - stats.stack_free += thread->stats.stack_free; - UNLOCK (stats_lock); - memset (&thread->stats, 0, sizeof (thread->stats)); changed = set_new_size_r (&thread->set_pool, portalclusters); cluster = &clusters[completed->cluster]; @@ -479,10 +484,12 @@ PortalCompleted (threaddata_t *thread, portal_t *completed) } for (ci = set_first_r (&thread->set_pool, changed); ci; ci = set_next_r (&thread->set_pool, ci)) { - UpdateMightsee (&clusters[ci->element], cluster); + UpdateMightsee (thread, &clusters[ci->element], cluster); } } set_delete_r (&thread->set_pool, changed); + + UpdateStates (thread); } static void @@ -896,23 +903,27 @@ CalcPortalVis (void) if (options.verbosity >= 1) { printf ("portalcheck: %i portaltest: %i portalpass: %i\n", - stats.portalcheck, stats.portaltest, stats.portalpass); + global_stats.portalcheck, global_stats.portaltest, + global_stats.portalpass); printf ("target trimmed: %d clipped: %d tested: %d\n", - stats.targettrimmed, stats.targetclipped, stats.targettested); + global_stats.targettrimmed, global_stats.targetclipped, + global_stats.targettested); printf ("source trimmed: %d clipped: %d tested: %d\n", - stats.sourcetrimmed, stats.sourceclipped, stats.sourcetested); + global_stats.sourcetrimmed, global_stats.sourceclipped, + global_stats.sourcetested); printf ("vistest: %i mighttest: %i mightseeupdate: %i\n", - stats.vistest, stats.mighttest, stats.mightseeupdate); + global_stats.vistest, global_stats.mighttest, + global_stats.mightseeupdate); if (options.verbosity >= 2) { printf ("separators allocated: %u freed: %u %u\n", - stats.sep_alloc, stats.sep_free, - stats.sep_alloc - stats.sep_free); + global_stats.sep_alloc, global_stats.sep_free, + global_stats.sep_alloc - global_stats.sep_free); printf ("windings allocated: %u freed: %u %u\n", - stats.winding_alloc, stats.winding_free, - stats.winding_alloc - stats.winding_free); + global_stats.winding_alloc, global_stats.winding_free, + global_stats.winding_alloc - global_stats.winding_free); printf ("stack blocks allocated: %u freed: %u %u\n", - stats.stack_alloc, stats.stack_free, - stats.stack_alloc - stats.stack_free); + global_stats.stack_alloc, global_stats.stack_free, + global_stats.stack_alloc - global_stats.stack_free); } } } @@ -1345,7 +1356,7 @@ main (int argc, char **argv) CalcVis (); if (options.verbosity >= 1) - printf ("chains: %i%s\n", stats.chains, + printf ("chains: %i%s\n", global_stats.chains, options.threads > 1 ? " (not reliable)" :""); BSP_AddVisibility (bsp, (byte *) visdata->str, visdata->size); From 9f42943589adefe42651a9bb3e195a24f164ea74 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Mar 2021 20:59:46 +0900 Subject: [PATCH 1461/3664] [qfvis] Reset portal status after base vis This fixes the mightsee updates never occurring, but it doesn't make a huge difference (though I suppose it might have back in the 90s, or with a different map). --- tools/qfvis/source/qfvis.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 599899f64..f1cbda52a 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -935,6 +935,9 @@ CalcVis (void) printf ("Thread count: %d\n", options.threads); BasePortalVis (); + for (i = 0; i < 2 * numportals; i++) { + portals[i].status = stat_none; + } CalcPortalVis (); // assemble the leaf vis lists by oring and compressing the portal lists From 634219ea06b4b77b894fdbcccbb7790d0ea734d6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Mar 2021 21:11:13 +0900 Subject: [PATCH 1462/3664] [qfvis] Add set debug prints (disabled) They were useful for narrowing down why mightsee wasn't being updated. --- tools/qfvis/include/vis.h | 2 ++ tools/qfvis/source/qfvis.c | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 279c0e72f..9367760b4 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -73,6 +73,7 @@ extern pthread_rwlock_t *portal_locks; #endif #include "QF/cmem.h" +#include "QF/dstring.h" #include "QF/set.h" #include "QF/simd/vec4f.h" @@ -174,6 +175,7 @@ typedef struct threaddata_s { sep_t *sep_freelist; ///< per-thread list of free separators winding_t *winding_freelist; ///< per-thread list of free windings memsuper_t *memsuper; ///< per-thread memory pool + dstring_t *str; set_pool_t set_pool; int id; int winding_id; diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index f1cbda52a..a1dc5ce33 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -474,6 +474,16 @@ PortalCompleted (threaddata_t *thread, portal_t *completed) continue; set_assign (changed, portal->mightsee); set_difference (changed, portal->visbits); +#if 0 + dstring_copystr (thread->str, "mightsee: "); + set_as_string_r (thread->str, portal->mightsee); + dstring_appendstr (thread->str, "\nvisbits: "); + set_as_string_r (thread->str, portal->visbits); + dstring_appendstr (thread->str, "\nchanged: "); + set_as_string_r (thread->str, changed); + dstring_appendstr (thread->str, "\n"); + write (0, thread->str->str, thread->str->size - 1); +#endif for (j = 0; j < cluster->numportals; j++) { if (j == i) continue; @@ -550,6 +560,7 @@ LeafThread (void *_thread) set_pool_init (&data.set_pool); data.id = thread; data.memsuper = new_memsuper (); + data.str = dstring_new (); do { portal = GetNextPortal (1); if (!portal) @@ -593,6 +604,7 @@ LeafThread (void *_thread) if (working) working[thread] = -1; delete_memsuper (data.memsuper); + dstring_delete (data.str); return NULL; } From 574a1237166659c55d1f75a0ccfea2d5ed4c325b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Mar 2021 21:14:17 +0900 Subject: [PATCH 1463/3664] [qfvis] Remove obsolete notes file While some of it is still correct, I'd rather start afresh next time I need to sort that stuff out. --- tools/qfvis/source/notes | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 tools/qfvis/source/notes diff --git a/tools/qfvis/source/notes b/tools/qfvis/source/notes deleted file mode 100644 index 2bc29508b..000000000 --- a/tools/qfvis/source/notes +++ /dev/null @@ -1,29 +0,0 @@ -non-threaded access only ---- -bsp -originalvismapsize -portalleafs -totalvis -uncompressed -visdata - -threaded read-only ---- -bitbytes -bitlongs -numportals -options - -threaded read/write ---- -portals -leafs - -threaded read/write stats-only ---- -c_chains -c_mighttest -c_portaltest -c_portalpass -c_portalcheck -c_vistest From 2e1f3cda8929e47ecf8eff3a76e47865e3bace66 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 12:03:07 +0900 Subject: [PATCH 1464/3664] [vulkan] Flesh out known required windows functions It looks like choosing a visual is not necessary (at least for normal apps, VR might be another matter). Still no idea if anything works (for -win support in general, let alone vulkan). --- libs/video/targets/vid_win_vulkan.c | 46 +++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/libs/video/targets/vid_win_vulkan.c b/libs/video/targets/vid_win_vulkan.c index 2ec53343e..027abed00 100644 --- a/libs/video/targets/vid_win_vulkan.c +++ b/libs/video/targets/vid_win_vulkan.c @@ -29,6 +29,9 @@ #endif #include "winquake.h" +#define VK_NO_PROTOTYPES +#define VK_USE_PLATFORM_WIN32_KHR +#include #include "QF/cvar.h" #include "QF/set.h" @@ -47,10 +50,13 @@ typedef struct vulkan_presentation_s { #define PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; #include "QF/Vulkan/funclist.h" - set_t *usable_visuals; + HINSTANCE instance; + HWND window; + } vulkan_presentation_t; static const char *required_extensions[] = { + VK_KHR_WIN32_SURFACE_EXTENSION_NAME, 0 }; @@ -91,6 +97,21 @@ unload_vulkan_library (vulkan_ctx_t *ctx) static void win_vulkan_init_presentation (vulkan_ctx_t *ctx) { + ctx->presentation = calloc (1, sizeof (vulkan_presentation_t)); + vulkan_presentation_t *pres = ctx->presentation; + qfv_instance_t *instance = ctx->instance; + VkInstance inst = instance->instance; + +#define PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION(name, ext) \ + if (instance->extension_enabled (instance, ext)) { \ + pres->name = (PFN_##name) ctx->vkGetInstanceProcAddr (inst, #name); \ + if (!pres->name) { \ + Sys_Error ("Couldn't find instance-level function %s", #name); \ + } \ + } +#include "QF/Vulkan/funclist.h" + + pres->instance = GetModuleHandle (0); } static int @@ -102,7 +123,11 @@ win_vulkan_get_presentation_support (vulkan_ctx_t *ctx, win_vulkan_init_presentation (ctx); } vulkan_presentation_t *pres = ctx->presentation; - return !set_is_empty (pres->usable_visuals); + if (pres->vkGetPhysicalDeviceWin32PresentationSupportKHR ( + physicalDevice, queueFamilyIndex)) { + return 1; + } + return 0; } static void @@ -113,12 +138,27 @@ win_vulkan_choose_visual (vulkan_ctx_t *ctx) static void win_vulkan_create_window (vulkan_ctx_t *ctx) { + vulkan_presentation_t *pres = ctx->presentation; + pres->window = win_mainwindow; } static VkSurfaceKHR win_vulkan_create_surface (vulkan_ctx_t *ctx) { - return 0; + vulkan_presentation_t *pres = ctx->presentation; + VkInstance inst = ctx->instance->instance; + VkSurfaceKHR surface; + VkWin32SurfaceCreateInfoKHR createInfo = { + .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, + .flags = 0, + .hinstance = pres->instance, + .hwnd = pres->window, + }; + if (pres->vkCreateWin32SurfaceKHR (inst, &createInfo, 0, &surface) + != VK_SUCCESS) { + return 0; + } + return surface; } vulkan_ctx_t * From a754dbca373b0df0a043370783ba1668b709367c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 17:24:30 +0900 Subject: [PATCH 1465/3664] [util] Make va return const char * And clean up the resulting mess. I don't know why it wasn't doing so, but it certainly should have been. --- include/QF/va.h | 2 +- libs/console/client.c | 2 +- libs/gib/gib_vars.c | 3 ++- libs/models/brush/gl_model_brush.c | 2 +- libs/util/va.c | 2 +- nq/source/cl_main.c | 2 +- qw/source/cl_main.c | 2 +- qw/source/cl_parse.c | 2 +- qw/source/sv_user.c | 6 +++--- 9 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/QF/va.h b/include/QF/va.h index cc123cde3..2d2974e05 100644 --- a/include/QF/va.h +++ b/include/QF/va.h @@ -73,7 +73,7 @@ void va_destroy_context (va_ctx_t *ctx); * to va sent to a 4th) with a reduced risk of strings being * trampled. */ -char *va(va_ctx_t *ctx, const char *format, ...) __attribute__((format(PRINTF,2,3))); +const char *va(va_ctx_t *ctx, const char *format, ...) __attribute__((format(PRINTF,2,3))); /** Does a varargs printf into a malloced buffer. * diff --git a/libs/console/client.c b/libs/console/client.c index b694b493c..054aaa8f5 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -240,7 +240,7 @@ Condump_f (void) int line = con->current - con->numlines; const char *start, *end; QFile *file; - char *name; + const char *name; if (Cmd_Argc () != 2) { Sys_Printf ("usage: condump \n"); diff --git a/libs/gib/gib_vars.c b/libs/gib/gib_vars.c index 2d40141e1..27adc7f4a 100644 --- a/libs/gib/gib_vars.c +++ b/libs/gib/gib_vars.c @@ -162,7 +162,8 @@ GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *ke unsigned int i, index = 0, index2 = 0, n, protect, varstartskip; gib_var_t *var = 0; cvar_t *cvar; - char c, *str; + char c; + const char *str; qboolean done = false; for (i = start, protect = 0; !done; i++) { diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 9585bb108..196bdfd59 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -54,7 +54,7 @@ static gltex_t gl_notexture = { }; static tex_t * -Mod_LoadAnExternalTexture (char *tname, char *mname) +Mod_LoadAnExternalTexture (const char *tname, const char *mname) { char rname[32]; tex_t *image; diff --git a/libs/util/va.c b/libs/util/va.c index c4b83aebb..b47d5d2ba 100644 --- a/libs/util/va.c +++ b/libs/util/va.c @@ -71,7 +71,7 @@ va_destroy_context (va_ctx_t *ctx) free (ctx); } -VISIBLE char * +VISIBLE const char * va (va_ctx_t *ctx, const char *fmt, ...) { static va_ctx_t *_ctx; diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 14bd9637e..c1f13c4eb 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -108,7 +108,7 @@ CL_WriteConfiguration (void) // dedicated servers initialize the host but don't parse and set the // config.cfg cvars if (host_initialized && !isDedicated && cl_writecfg->int_val) { - char *path = va (0, "%s/config.cfg", qfs_gamedir->dir.def); + const char *path = va (0, "%s/config.cfg", qfs_gamedir->dir.def); f = QFS_WOpen (path, 0); if (!f) { Sys_Printf ("Couldn't write config.cfg.\n"); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 4bc686d4d..15617aea3 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1520,7 +1520,7 @@ Host_WriteConfiguration (void) QFile *f; if (host_initialized && cl_writecfg->int_val) { - char *path = va (0, "%s/config.cfg", qfs_gamedir->dir.def); + const char *path = va (0, "%s/config.cfg", qfs_gamedir->dir.def); f = QFS_WOpen (path, 0); if (!f) { diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index a1e8474ca..981871d6c 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -357,7 +357,7 @@ Model_NextDownload (void) map_cfg (cl.model_name[1], 0); for (i = 1; i < cl.nummodels; i++) { - char *info_key = 0; + const char *info_key = 0; if (!cl.model_name[i][0]) break; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 4ad70cf99..dd1fe7bfc 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -309,9 +309,9 @@ SV_Modellist_f (void *unused) static void SV_PreSpawn_f (void *unused) { - char *command; - int buf, size; - unsigned int check; + const char *command; + int buf, size; + unsigned check; sizebuf_t *msg; if (host_client->state != cs_connected) { From 6fea5f5e1a1bbc6cfce8e6377cb7a1de0fa9f6f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 17:27:06 +0900 Subject: [PATCH 1466/3664] [build] Add -Wformat-non-literal option While this caused some trouble for pr_strings and configurable strftime (evil hacks abound), it's the result of discovering an ancient (from maybe as early as 2004, definitely before 2012) bug in qwaq's printing that somehow got past months of trial-by-fire testing (origin understood thanks to the warning finding it). --- config.d/compiling.m4 | 1 + libs/gamecode/pr_debug.c | 2 +- libs/gamecode/pr_strings.c | 10 ++-- libs/util/plugin.c | 73 ++++++++++++++-------------- libs/video/renderer/vulkan/vkparse.c | 3 +- nq/source/sbar.c | 13 +++-- qw/include/cl_main.h | 7 ++- qw/source/cl_main.c | 6 --- qw/source/sbar.c | 14 +++--- qw/source/sv_send.c | 5 +- qw/source/sv_user.c | 9 ++-- ruamoko/qwaq/builtins/main.c | 5 +- ruamoko/qwaq/builtins/qwaq-bi.c | 5 +- 13 files changed, 78 insertions(+), 75 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index f5042ae0f..b432c1709 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -221,6 +221,7 @@ QF_CC_OPTION(-Wsuggest-attribute=pure) QF_CC_OPTION(-Wsuggest-attribute=const) QF_CC_OPTION(-Wsuggest-attribute=noreturn) QF_CC_OPTION(-Wsuggest-attribute=format) +QF_CC_OPTION(-Wformat-nonliteral) AC_ARG_ENABLE(coverage, [ --enable-coverage Enable generation of data for gcov]) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 598c2fa18..3ef208442 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -352,7 +352,7 @@ parse_expression (progs_t *pr, const char *expr, int conditional) } error: if (es->error) { - Sys_Printf (es->error); + Sys_Printf ("%s\n", es->error); } Script_Delete (es); return d; diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 82e9540da..c0a0df833 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -712,22 +712,24 @@ PR_FreeTempStrings (progs_t *pr) pr->pr_xtstr = 0; } +#define hasprintf ((char *(*)(dstring_t *, const char *, ...))dasprintf) + #define PRINT(t) \ switch ((doWidth << 1) | doPrecision) { \ case 3: \ - dasprintf (result, tmp->str, current->minFieldWidth, \ + hasprintf (result, tmp->str, current->minFieldWidth, \ current->precision, current->data.t##_var); \ break; \ case 2: \ - dasprintf (result, tmp->str, current->minFieldWidth, \ + hasprintf (result, tmp->str, current->minFieldWidth, \ current->data.t##_var); \ break; \ case 1: \ - dasprintf (result, tmp->str, current->precision, \ + hasprintf (result, tmp->str, current->precision, \ current->data.t##_var); \ break; \ case 0: \ - dasprintf (result, tmp->str, current->data.t##_var); \ + hasprintf (result, tmp->str, current->data.t##_var); \ break; \ } diff --git a/libs/util/plugin.c b/libs/util/plugin.c index f625ddd15..9505475fc 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -52,11 +52,12 @@ # endif #endif +#include "QF/cmd.h" #include "QF/cvar.h" #include "QF/hash.h" #include "QF/plugin.h" #include "QF/sys.h" -#include "QF/cmd.h" +#include "QF/va.h" #include "QF/plugin/general.h" @@ -150,29 +151,28 @@ pi_open_lib (const char *name, int global_syms) return dlhand; } -static void -pi_realname (char *realname, int size, const char *type, const char *name) +static const char * +pi_realname (const char *type, const char *name) { #if defined(HAVE_DLOPEN) - const char *format = "%s/%s_%s.so"; + return va (0, "%s/%s_%s.so", fs_pluginpath->string, type, name); #elif defined(_WIN32) - const char *format = "%s/%s_%s.dll"; + return va (0, "%s/%s_%s.dll", fs_pluginpath->string, type, name); #else - const char *format = "No shared library support. FIXME"; + return "No shared library support. FIXME"; #endif - - snprintf (realname, size, format, fs_pluginpath->string, type, name); } -static void -pi_info_name (char *info_name, int size, const char *type, const char *name) +static const char * +pi_info_name (const char *type, const char *name) { - if (type && name) - snprintf (info_name, size, "%s_%s_PluginInfo", type, name); - else if (type) - snprintf (info_name, size, "%s_PluginInfo", type); - else - snprintf (info_name, size, "PluginInfo"); + if (type && name) { + return va (0, "%s_%s_PluginInfo", type, name); + } else if (type) { + return va (0, "%s_PluginInfo", type); + } else { + return "PluginInfo"; + } } static void @@ -208,7 +208,7 @@ PI_Plugin_Load_f (void) static void PI_Plugin_Unload_f (void) { - char plugin_name[1024]; + const char *plugin_name; loaded_plugin_t *lp; plugin_t *pi; @@ -218,8 +218,8 @@ PI_Plugin_Unload_f (void) } // try to locate the plugin - snprintf (plugin_name, sizeof (plugin_name), "%s_%s", Cmd_Argv(1), - Cmd_Argv(2)); + plugin_name = va (0, "%s_%s", Cmd_Argv(1), Cmd_Argv(2)); + lp = Hash_Find (loaded_plugins, plugin_name); if (lp) { pi = lp->plugin; @@ -268,23 +268,27 @@ PI_Shutdown (void) VISIBLE plugin_t * PI_LoadPlugin (const char *type, const char *name) { - char realname[4096]; - char plugin_name[1024]; - char plugin_info_name[1024]; - char *tmpname; - void *dlhand = NULL; - plugin_t *plugin = NULL; - P_PluginInfo plugin_info = NULL; - plugin_list_t *pl; + const char *realname = 0; + const char *plugin_name = 0; + const char *plugin_info_name = 0; + const char *tmpname; + void *dlhand = 0; + plugin_t *plugin = 0; + P_PluginInfo plugin_info = 0; + plugin_list_t *pl; loaded_plugin_t *lp; if (!name) return NULL; - tmpname = strrchr (name, '/'); // Get the base name, don't allow paths + // Get the base name, don't allow paths + tmpname = strrchr (name, '/'); + if (tmpname) { + name = tmpname + 1; // skip over '/' + } // Build the plugin name - snprintf (plugin_name, sizeof (plugin_name), "%s_%s", type, name); + plugin_name = va (0, "%s_%s", type, name); // make sure we're not already loaded lp = Hash_Find (loaded_plugins, plugin_name); @@ -299,8 +303,7 @@ PI_LoadPlugin (const char *type, const char *name) } if (!plugin_info) { // Build the path to the file to load - pi_realname (realname, sizeof (realname), type, - (tmpname ? tmpname + 1 : name)); + realname = pi_realname (type, name); if (!(dlhand = pi_open_lib (realname, 0))) { // lib not found @@ -310,15 +313,13 @@ PI_LoadPlugin (const char *type, const char *name) } // Build the plugin info name as $type_$name_PluginInfo - pi_info_name (plugin_info_name, sizeof (plugin_info_name), type, name); + plugin_info_name = pi_info_name (type, name); if (!(plugin_info = pi_get_symbol (dlhand, plugin_info_name))) { // Build the plugin info name as $type_PluginInfo - pi_info_name (plugin_info_name, sizeof (plugin_info_name), - type, 0); + plugin_info_name = pi_info_name (type, 0); if (!(plugin_info = pi_get_symbol (dlhand, plugin_info_name))) { // Build the plugin info name as PluginInfo - pi_info_name (plugin_info_name, sizeof (plugin_info_name), - 0, 0); + plugin_info_name = pi_info_name (0, 0); if (!(plugin_info = pi_get_symbol (dlhand, plugin_info_name))) { // info function not found pi_close_lib (dlhand); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 798cd98f9..1100024fd 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -240,14 +240,13 @@ parse_reference (const plitem_t *item, const char *type, plitem_t *messages, parsectx_t *pctx) { exprctx_t ectx = *pctx->ectx; - vulkan_ctx_t *ctx = pctx->vctx; plitem_t *refItem = 0; exprval_t result = { &cexpr_plitem, &refItem }; ectx.symtab = 0; ectx.result = &result; const char *name = PL_String (item); if (cexpr_eval_string (name, &ectx)) { - PL_Message (messages, item, va (ctx->va_ctx, "not a %s reference", type)); + PL_Message (messages, item, "not a %s reference", type); return 0; } return refItem; diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 506cb7fa3..1a0261db2 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1093,23 +1093,22 @@ draw_overlay (view_t *view) static void draw_time (view_t *view) { - struct tm *local = NULL; + struct tm *local = 0; time_t utc = 0; - const char *timefmt = NULL; char st[80]; //FIXME: overflow // Get local time - utc = time (NULL); + utc = time (0); local = localtime (&utc); if (hud_time->int_val == 1) { // Use international format - timefmt = "%k:%M"; + strftime (st, sizeof (st), "%k:%M", local); + draw_string (view, 8, 0, st); } else if (hud_time->int_val >= 2) { // US AM/PM display - timefmt = "%l:%M %P"; + strftime (st, sizeof (st), "%l:%M %P", local); + draw_string (view, 8, 0, st); } - strftime (st, sizeof (st), timefmt, local); - draw_string (view, 8, 0, st); } static void diff --git a/qw/include/cl_main.h b/qw/include/cl_main.h index f7cd463f1..16727deea 100644 --- a/qw/include/cl_main.h +++ b/qw/include/cl_main.h @@ -44,7 +44,12 @@ qboolean CL_DemoBehind(void); void CL_BeginServerConnect(void); -extern char emodel_name[], pmodel_name[], prespawn_name[], modellist_name[], soundlist_name[]; +#define emodel_name "emodel" +#define pmodel_name "pmodel" +#define prespawn_name "prespawn %i 0 %i" +#define modellist_name "modellist %i %i" +#define soundlist_name "soundlist %i %i" + extern struct cvar_s *cl_timeframes; extern struct cvar_s *cl_predict_players; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 15617aea3..411cfcbc0 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -224,12 +224,6 @@ jmp_buf host_abort; char *server_version = NULL; // version of server we connected to -char emodel_name[] = "emodel"; -char pmodel_name[] = "pmodel"; -char prespawn_name[] = "prespawn %i 0 %i"; -char modellist_name[] = "modellist %i %i"; -char soundlist_name[] = "soundlist %i %i"; - extern cvar_t *hud_scoreboard_uid; static netadr_t cl_cmd_packet_address; diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 4a517887e..0514a9327 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -1555,23 +1555,21 @@ draw_miniteam (view_t *view) static void draw_time (view_t *view) { - struct tm *local = NULL; + struct tm *local = 0; time_t utc = 0; - const char *timefmt = NULL; char st[80]; // Get local time - utc = time (NULL); + utc = time (0); local = localtime (&utc); if (hud_time->int_val == 1) { // Use international format - timefmt = "%k:%M"; + strftime (st, sizeof (st), "%k:%M", local); + draw_string (view, 8, 0, st); } else if (hud_time->int_val >= 2) { // US AM/PM display - timefmt = "%l:%M %P"; + strftime (st, sizeof (st), "%l:%M %P", local); + draw_string (view, 8, 0, st); } - - strftime (st, sizeof (st), timefmt, local); - draw_string (view, 8, 8, st); } static void diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index 0948e6f18..b89438131 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -164,6 +164,9 @@ find_userid (const char *name) return 0; } +#define hstrftime ((size_t (*)(char *s, size_t, const char *, \ + const struct tm*))strftime) + /* SV_Printf @@ -229,7 +232,7 @@ SV_Print (const char *fmt, va_list args) if (timestamps) { mytime = time (NULL); local = localtime (&mytime); - strftime (msg3, sizeof (msg3), sv_timefmt->string, local); + hstrftime (msg3, sizeof (msg3), sv_timefmt->string, local); dsprintf (msg2, "%s%s", msg3, msg->str); } else { diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index dd1fe7bfc..a3760ad03 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -820,7 +820,7 @@ SV_Say (qboolean team) { char *i, *p; dstring_t *text; - const char *t1 = 0, *t2, *type, *fmt; + const char *t1 = 0, *t2, *type; client_t *client; int tmp, j, cls = 0; sizebuf_t *dbuf; @@ -903,16 +903,15 @@ SV_Say (qboolean team) text = dstring_new (); if (host_client->spectator && (!sv_spectalk->int_val || team)) { - fmt = "[SPEC] %s: "; type = "2"; + dsprintf (text, "[SPEC] %s: ", host_client->name); } else if (team) { - fmt = "(%s): "; type = "1"; + dsprintf (text, "(%s): ", host_client->name); } else { - fmt = "%s: "; type = "0"; + dsprintf (text, "%s: ", host_client->name); } - dsprintf (text, fmt, host_client->name); if (sv_chat_e->func) GIB_Event_Callback (sv_chat_e, 2, va (0, "%i", host_client->userid), p, diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 7e4e7f5b4..8c8ec0f69 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -352,8 +352,9 @@ bi_printf (progs_t *pr) dstring_t *dstr = dstring_new (); PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); - if (dstr->str) - Sys_Printf (dstr->str, stdout); + if (dstr->str) { + Sys_Printf ("%s", dstr->str); + } dstring_delete (dstr); } diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c index a78dd7763..d3db5917a 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/qwaq-bi.c @@ -89,8 +89,9 @@ bi_printf (progs_t *pr) dstring_t *dstr = dstring_new (); PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); - if (dstr->str) - Con_Printf (dstr->str, stdout); + if (dstr->str) { + Con_Printf ("%s", dstr->str); + } dstring_delete (dstr); } From 0da127b822ce114c4f6e2a81524d43ae53731ae7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 17:31:17 +0900 Subject: [PATCH 1467/3664] [gamecode] Fix bad progs strings intialization The merge with the improvements I made while hacking on csqc (still undecided as to whether to continue that project) resulted in the size of the progs string area getting mangled when no heap was allocated for the progs due to a null zone pointer being used in some pointer arithmetic. Fixes random(!!!) invalid string error in qfprogs. --- libs/gamecode/pr_load.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 934a8480b..a221124dc 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -113,6 +113,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) int offset_tweak; dprograms_t progs; byte *base; + byte *heap; pr_def_t *xdefs_def = 0; ddef_t *global_ddefs; ddef_t *field_ddefs; @@ -199,20 +200,22 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) base = (byte *) (pr->progs + 1) + offset_tweak; Qread (file, base, size - sizeof (progs)); CRC_ProcessBlock (base, &pr->crc, size - sizeof (progs)); - base -= sizeof (progs); // offsets are from file start pr->pr_edict_area = (pr_type_t *)((byte *) pr->progs + pr->progs_size); + base -= sizeof (progs); // offsets are from file start + heap = (byte *) &pr->pr_edict_area[pr->pr_edict_area_size]; + pr->zone = 0; if (pr->zone_size) { //FIXME zone_size needs to be at least as big as memzone_t, but //memzone_t is opaque so its size is unknown - pr->zone = (memzone_t *)(&pr->pr_edict_area[pr->pr_edict_area_size]); + pr->zone = (memzone_t *) heap; } pr->pr_functions = (dfunction_t *) (base + pr->progs->ofs_functions); pr->pr_strings = (char *) base + pr->progs->ofs_strings; - pr->pr_stringsize = (char *) pr->zone + pr->zone_size - (char *) base; + pr->pr_stringsize = (heap - base) + pr->zone_size; global_ddefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); field_ddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs); pr->pr_statements = (dstatement_t *) (base + pr->progs->ofs_statements); From 64f51bda6e81b9540d88579b320b06896e1c7112 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 17:35:30 +0900 Subject: [PATCH 1468/3664] [build] Get make distcheck working again again... This covers only the basic check with a build in debian, but it's a good start. --- config.d/build_control.m4 | 2 ++ include/Makemodule.am | 5 ++- include/QF/Makemodule.am | 30 +++++++++++++++- libs/client/Makemodule.am | 3 +- libs/entity/Makemodule.am | 3 +- libs/entity/test/Makemodule.am | 6 ++-- libs/image/Makemodule.am | 3 +- libs/video/renderer/Makemodule.am | 36 +++++++++++++++---- libs/video/renderer/vulkan/test/Makemodule.am | 6 ++-- .../video/renderer/vulkan/vkgen/Makemodule.am | 11 ++++-- ruamoko/qwaq/Makemodule.am | 6 ++-- 11 files changed, 82 insertions(+), 29 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index fdd4ce698..e5800c31b 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -313,6 +313,7 @@ if test x"${top_need_libs}" = xyes; then qfac_include_qf_glsl="\$(include_qf_glsl)" qfac_include_qf_math="\$(include_qf_math)" qfac_include_qf_plugin="\$(include_qf_plugin)" + qfac_include_qf_simd="\$(include_qf_simd)" qfac_include_qf_vulkan="\$(include_qf_vulkan)" fi QF_SUBST(qfac_include_qf) @@ -320,6 +321,7 @@ QF_SUBST(qfac_include_qf_gl) QF_SUBST(qfac_include_qf_glsl) QF_SUBST(qfac_include_qf_math) QF_SUBST(qfac_include_qf_plugin) +QF_SUBST(qfac_include_qf_simd) QF_SUBST(qfac_include_qf_vulkan) progs_gz= diff --git a/include/Makemodule.am b/include/Makemodule.am index 0755ed1b5..48acc8173 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -13,6 +13,7 @@ EXTRA_DIST += \ include/buildnum.h \ include/compat.h \ include/context_sdl.h \ + include/context_win.h \ include/context_x11.h \ include/d_iface.h \ include/d_ifacea.h \ @@ -54,10 +55,12 @@ EXTRA_DIST += \ include/qfalloca.h \ include/qstring.h \ include/quakeasm.h \ + include/quicksort.h \ include/r_cvar.h \ include/r_dynamic.h \ include/r_internal.h \ include/r_local.h \ + include/r_scrap.h \ include/r_screen.h \ include/r_shared.h \ include/regex.h \ @@ -79,6 +82,7 @@ EXTRA_DIST += \ include/client/entities.h \ include/client/temp_entities.h \ include/client/locs.h \ + include/client/state.h \ include/client/view.h \ include/qw/bothdefs.h \ include/qw/msg_backbuf.h \ @@ -87,7 +91,6 @@ EXTRA_DIST += \ include/qw/protocol.h \ include/win32/dirent.h \ include/win32/fnmatch.h \ - include/win32/stdint.h \ include/win32/resources/icon1Vista.ico \ include/win32/resources/icon1XP.ico \ include/win32/resources/quakeforge.rc \ diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 4c190feae..6ebb73af6 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -3,9 +3,11 @@ include_qf = \ include/QF/bspfile.h \ include/QF/cbuf.h \ include/QF/cdaudio.h \ + include/QF/cexpr.h \ include/QF/checksum.h \ include/QF/clip_hull.h \ include/QF/cmd.h \ + include/QF/cmem.h \ include/QF/console.h \ include/QF/crc.h \ include/QF/csqc.h \ @@ -13,6 +15,7 @@ include_qf = \ include/QF/darray.h \ include/QF/dstring.h \ include/QF/draw.h \ + include/QF/entity.h \ include/QF/gib.h \ include/QF/hash.h \ include/QF/idparse.h \ @@ -124,20 +127,42 @@ include_qf_plugin = \ include/QF/plugin/snd_render.h \ include/QF/plugin/vid_render.h +include_qf_simd = \ + include/QF/simd/mat4f.h \ + include/QF/simd/types.h \ + include/QF/simd/vec4d.h \ + include/QF/simd/vec4f.h + include_qf_vulkan = \ + include/QF/Vulkan/barrier.h \ include/QF/Vulkan/buffer.h \ + include/QF/Vulkan/capture.h \ include/QF/Vulkan/command.h \ include/QF/Vulkan/cvars.h \ + include/QF/Vulkan/debug.h \ include/QF/Vulkan/descriptor.h \ include/QF/Vulkan/device.h \ + include/QF/Vulkan/draw.h \ include/QF/Vulkan/funclist.h \ include/QF/Vulkan/image.h \ include/QF/Vulkan/instance.h \ include/QF/Vulkan/memory.h \ include/QF/Vulkan/pipeline.h \ + include/QF/Vulkan/qf_alias.h \ + include/QF/Vulkan/qf_bsp.h \ + include/QF/Vulkan/qf_compose.h \ include/QF/Vulkan/qf_draw.h \ + include/QF/Vulkan/qf_lighting.h \ + include/QF/Vulkan/qf_lightmap.h \ + include/QF/Vulkan/qf_main.h \ + include/QF/Vulkan/qf_model.h \ + include/QF/Vulkan/qf_particles.h \ + include/QF/Vulkan/qf_texture.h \ include/QF/Vulkan/qf_vid.h \ include/QF/Vulkan/renderpass.h \ + include/QF/Vulkan/scrap.h \ + include/QF/Vulkan/shader.h \ + include/QF/Vulkan/staging.h \ include/QF/Vulkan/swapchain.h # headers shared with ruamoko @@ -148,12 +173,14 @@ qf_gl_includedir = $(includedir)/QF/GL qf_glsl_includedir = $(includedir)/QF/GLSL qf_math_includedir = $(includedir)/QF/math qf_plugin_includedir = $(includedir)/QF/plugin -qf_vulkan_includedir = $(includedir)/QF/vulkan +qf_simd_includedir = $(includedir)/QF/simd +qf_vulkan_includedir = $(includedir)/QF/Vulkan qf_include_HEADERS = @qfac_include_qf@ qf_gl_include_HEADERS = @qfac_include_qf_gl@ qf_glsl_include_HEADERS = @qfac_include_qf_glsl@ qf_math_include_HEADERS = @qfac_include_qf_math@ qf_plugin_include_HEADERS = @qfac_include_qf_plugin@ +qf_simd_include_HEADERS = @qfac_include_qf_simd@ qf_vulkan_include_HEADERS = @qfac_include_qf_vulkan@ ruamoko_qf_includedir = $(ruamoko_includedir)/QF @@ -165,5 +192,6 @@ EXTRA_HEADERS += \ $(include_qf_glsl) \ $(include_qf_math) \ $(include_qf_plugin) \ + $(include_qf_simd) \ $(include_qf_vulkan) \ $(qfcc_include_qf) diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 074daea58..0e5105806 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -6,5 +6,4 @@ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_effects.c \ libs/client/cl_entities.c \ libs/client/cl_temp_entities.c \ - libs/client/locs.c \ - $e + libs/client/locs.c diff --git a/libs/entity/Makemodule.am b/libs/entity/Makemodule.am index d8ac9a7e1..58dc1f08c 100644 --- a/libs/entity/Makemodule.am +++ b/libs/entity/Makemodule.am @@ -9,5 +9,4 @@ libs_entity_libQFentity_la_LIBADD= $(entity_deps) libs_entity_libQFentity_la_DEPENDENCIES= $(entity_deps) libs_entity_libQFentity_la_SOURCES= \ libs/entity/hierarchy.c \ - libs/entity/transform.c \ - $e + libs/entity/transform.c diff --git a/libs/entity/test/Makemodule.am b/libs/entity/test/Makemodule.am index b0f98ae2b..be280abe9 100644 --- a/libs/entity/test/Makemodule.am +++ b/libs/entity/test/Makemodule.am @@ -1,6 +1,5 @@ libs_entity_tests = \ - libs/entity/test/test-hierarchy \ - $e + libs/entity/test/test-hierarchy TESTS += $(libs_entity_tests) @@ -11,8 +10,7 @@ libs_entity_test_libs= \ libs/util/libQFutil.la libs_entity_test_test_hierarchy_SOURCES= \ - libs/entity/test/test-hierarchy.c \ - $e + libs/entity/test/test-hierarchy.c libs_entity_test_test_hierarchy_LDADD= \ $(libs_entity_test_libs) libs_entity_test_test_hierarchy_DEPENDENCIES= \ diff --git a/libs/image/Makemodule.am b/libs/image/Makemodule.am index 00d1191d1..0e402b796 100644 --- a/libs/image/Makemodule.am +++ b/libs/image/Makemodule.am @@ -10,5 +10,4 @@ libs_image_libQFimage_la_SOURCES= \ libs/image/image.c \ libs/image/pcx.c \ libs/image/png.c \ - libs/image/tga.c \ - $e + libs/image/tga.c diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 562a9bebc..184342781 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -256,7 +256,6 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/image.c \ libs/video/renderer/vulkan/instance.c \ libs/video/renderer/vulkan/memory.c \ - libs/video/renderer/vulkan/namehack.h \ libs/video/renderer/vulkan/pipeline.c \ libs/video/renderer/vulkan/renderpass.c \ libs/video/renderer/vulkan/scrap.c \ @@ -284,9 +283,9 @@ libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vksh libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${renderpass_gen} -qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) -vkparse_cinc = libs/video/renderer/vulkan/vkparse.cinc -vkparse_hinc = libs/video/renderer/vulkan/vkparse.hinc +qwaq_curses = $(top_builddir)/ruamoko/qwaq/qwaq-curses$(EXEEXT) +vkparse_cinc = $(top_builddir)/libs/video/renderer/vulkan/vkparse.cinc +vkparse_hinc = $(top_builddir)/libs/video/renderer/vulkan/vkparse.hinc vkparse_src = \ $(vkparse_cinc) \ $(vkparse_hinc) @@ -403,12 +402,13 @@ $(vkparse_hinc): $(vkparse_cinc) # do nothing: hinc generated at the same time as cinc CLEANFILES += \ + $(top_builddir)/qwaq-curses.log \ libs/video/renderer/glsl/*.vc \ libs/video/renderer/glsl/*.fc \ libs/video/renderer/glsl/*.slc \ libs/video/renderer/vulkan/*.plc \ - libs/video/renderer/vulkan/*.spv \ - libs/video/renderer/vulkan/*.spvc \ + libs/video/renderer/vulkan/shader/*.spv \ + libs/video/renderer/vulkan/shader/*.spvc \ libs/video/renderer/vulkan/vkgen.sym \ $(vkparse_src) @@ -418,4 +418,26 @@ BUILT_SOURCES += $(shader_gen) # libs/video/renderer/vulkan/passthrough.vert.spv \ # libs/video/renderer/vulkan/pushcolor.frag.spv -EXTRA_DIST += $(shader_DATA:.spv=) +EXTRA_DIST += \ + libs/video/renderer/vulkan/deferred.plist \ + libs/video/renderer/vulkan/qfpipeline.plist \ + libs/video/renderer/vulkan/vkparse.plist \ + libs/video/renderer/vulkan/vkparse.h \ + libs/video/renderer/vulkan/shader/alias.frag \ + libs/video/renderer/vulkan/shader/alias.vert \ + libs/video/renderer/vulkan/shader/alias_depth.vert \ + libs/video/renderer/vulkan/shader/alias_gbuf.frag \ + libs/video/renderer/vulkan/shader/bsp_depth.vert \ + libs/video/renderer/vulkan/shader/bsp_gbuf.frag \ + libs/video/renderer/vulkan/shader/bsp_gbuf.geom \ + libs/video/renderer/vulkan/shader/bsp_gbuf.vert \ + libs/video/renderer/vulkan/shader/bsp_sky.frag \ + libs/video/renderer/vulkan/shader/bsp_turb.frag \ + libs/video/renderer/vulkan/shader/compose.frag \ + libs/video/renderer/vulkan/shader/lighting.frag \ + libs/video/renderer/vulkan/shader/passthrough.vert \ + libs/video/renderer/vulkan/shader/pushcolor.frag \ + libs/video/renderer/vulkan/shader/quakebsp.frag \ + libs/video/renderer/vulkan/shader/quakebsp.vert \ + libs/video/renderer/vulkan/shader/twod.frag \ + libs/video/renderer/vulkan/shader/twod.vert diff --git a/libs/video/renderer/vulkan/test/Makemodule.am b/libs/video/renderer/vulkan/test/Makemodule.am index 84c5ff136..f46249d31 100644 --- a/libs/video/renderer/vulkan/test/Makemodule.am +++ b/libs/video/renderer/vulkan/test/Makemodule.am @@ -1,6 +1,5 @@ libs_video_renderer_vulkan_tests = \ - libs/video/renderer/vulkan/test/test-staging \ - $e + libs/video/renderer/vulkan/test/test-staging TESTS += $(libs_video_renderer_vulkan_tests) @@ -11,8 +10,7 @@ libs_video_renderer_vulkan_test_libs= \ libs/util/libQFutil.la libs_video_renderer_vulkan_test_test_staging_SOURCES= \ - libs/video/renderer/vulkan/test/test-staging.c \ - $e + libs/video/renderer/vulkan/test/test-staging.c libs_video_renderer_vulkan_test_test_staging_LDADD= \ $(libs_video_renderer_vulkan_test_libs) libs_video_renderer_vulkan_test_test_staging_DEPENDENCIES= \ diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index ecb5853ee..f28252f7f 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -44,10 +44,17 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/vkgen/stdint.h \ libs/video/renderer/vulkan/vkgen/vkalias.h \ libs/video/renderer/vulkan/vkgen/vkenum.h \ + libs/video/renderer/vulkan/vkgen/vkfieldarray.h \ + libs/video/renderer/vulkan/vkgen/vkfieldauto.h \ + libs/video/renderer/vulkan/vkgen/vkfieldcustom.h \ + libs/video/renderer/vulkan/vkgen/vkfielddata.h \ + libs/video/renderer/vulkan/vkgen/vkfielddef.h \ + libs/video/renderer/vulkan/vkgen/vkfieldsingle.h \ + libs/video/renderer/vulkan/vkgen/vkfieldstring.h \ + libs/video/renderer/vulkan/vkgen/vkfieldtype.h \ libs/video/renderer/vulkan/vkgen/vkgen.h \ libs/video/renderer/vulkan/vkgen/vkstruct.h \ - libs/video/renderer/vulkan/vkgen/vktype.h \ - $e + libs/video/renderer/vulkan/vkgen/vktype.h CLEANFILES += \ libs/video/renderer/vkgen/*.sym diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 1626d661b..8b2d29419 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -39,8 +39,7 @@ qwaq_app_dat_src= \ ruamoko/qwaq/ui/textcontext.r \ ruamoko/qwaq/ui/titlebar.r \ ruamoko/qwaq/ui/view.r \ - ruamoko/qwaq/ui/window.r \ - $e + ruamoko/qwaq/ui/window.r #FIXME this coupling is horrible qwaq_curses_libs= \ @@ -53,8 +52,7 @@ ruamoko_qwaq_qwaq_curses_SOURCES= \ ruamoko/qwaq/builtins/curses.c \ ruamoko/qwaq/builtins/debug.c \ ruamoko/qwaq/builtins/editbuffer.c \ - ruamoko/qwaq/builtins/input.c \ - $e + ruamoko/qwaq/builtins/input.c ruamoko_qwaq_qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ $(PANEL_LIBS) $(NCURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) From 15a5254f04ebfaad7635320c28e08bef47f8989d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 17:54:39 +0900 Subject: [PATCH 1469/3664] [build] Get ncurses support working again Some minor errors dues to getting win32 building (and not testing the results properly in Linux). --- config.d/curses.m4 | 8 ++++---- libs/console/server.c | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/config.d/curses.m4 b/config.d/curses.m4 index 6a5757cc1..2e24c0d84 100644 --- a/config.d/curses.m4 +++ b/config.d/curses.m4 @@ -19,19 +19,19 @@ if test "x$enable_curses" != "xno"; then ) ) if test "x$NCURSES_LIBS" != "x"; then - AC_DEFINE(HAVE_CURSES, 1, [Define if you have the ncurses library]) - HAVE_CURSES=yes + HAVE_NCURSES=yes else - HAVE_CURSES=no + HAVE_NCURSES=no fi fi else - HAVE_CURSES=no + HAVE_NCURSES=no NCURSES_LIBS= fi AC_SUBST(NCURSES_LIBS) if test "x$HAVE_NCURSES" == "xyes"; then + AC_DEFINE(HAVE_NCURSES, 1, [Define if you have the ncurses library]) if test "x$PKG_CONFIG" != "x"; then PKG_CHECK_MODULES([PANEL], [panel], HAVE_PANEL=yes, HAVE_PANEL=no) else diff --git a/libs/console/server.c b/libs/console/server.c index a621bcc2b..005efb786 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -31,7 +31,7 @@ # include "config.h" #endif -#ifdef HAVE_CURSES +#ifdef HAVE_NCURSES # include #endif #ifdef HAVE_STRING_H @@ -84,7 +84,7 @@ static cvar_t *sv_conmode; static void C_KeyEvent (knum_t key, short unicode, qboolean down); -#ifdef HAVE_CURSES +#ifdef HAVE_NCURSES enum { sv_resize_x = 1, @@ -682,7 +682,7 @@ sv_conmode_f (cvar_t *var) static void C_Init (void) { -#ifdef HAVE_CURSES +#ifdef HAVE_NCURSES cvar_t *curses = Cvar_Get ("sv_use_curses", "0", CVAR_ROM, NULL, "Set to 1 to enable curses server console."); use_curses = curses->int_val; @@ -705,7 +705,7 @@ C_shutdown (void) Qclose (log_file); log_file = 0; } -#ifdef HAVE_CURSES +#ifdef HAVE_NCURSES if (use_curses) endwin (); #endif @@ -725,7 +725,7 @@ C_Print (const char *fmt, va_list args) Qputs (log_file, buffer->str); Qflush (log_file); } -#ifdef HAVE_CURSES +#ifdef HAVE_NCURSES if (use_curses) { print (buffer->str); } else @@ -741,7 +741,7 @@ C_Print (const char *fmt, va_list args) static void C_ProcessInput (void) { -#ifdef HAVE_CURSES +#ifdef HAVE_NCURSES if (use_curses) { process_input (); } else @@ -757,7 +757,7 @@ C_ProcessInput (void) static void C_KeyEvent (knum_t key, short unicode, qboolean down) { -#ifdef HAVE_CURSES +#ifdef HAVE_NCURSES key_event (key, unicode, down); #endif } From 0fb316785886e4d9eaef6699661beeafd7bf9db8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 19:02:22 +0900 Subject: [PATCH 1470/3664] [doc] Fix some typos --- doc/config.dox | 2 +- doc/dirconf.dox | 2 +- doc/qtv.dox | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/config.dox b/doc/config.dox index 33b8a5524..14d860694 100644 --- a/doc/config.dox +++ b/doc/config.dox @@ -28,7 +28,7 @@ whitespace. This allows commands and arguments to contain \c + and \c - so long as the preceeding character is not whitespace, but also prevents command line switches (eg \c -nosound) from becoming part of the console command. Using careful quoting, it is even possible for a command or -argument to beging with \c + or \c -. +argument to begin with \c + or \c -. The following command line will fail to set m_pitch because the -0.022 will not be part of the console command. usage: setrom \ diff --git a/doc/dirconf.dox b/doc/dirconf.dox index 4b23454e6..927aa3099 100644 --- a/doc/dirconf.dox +++ b/doc/dirconf.dox @@ -98,7 +98,7 @@ Supported attributes are: QF. -Attribute allow variable substitution. Variables can take the form of +Attributes allow variable substitution. Variables can take the form of either \$NAME or \${NAME}, where the latter is useful when the end of \c NAME is ambiguous (eg, \${NAME}STUFF vs \$NAME/STUFF). diff --git a/doc/qtv.dox b/doc/qtv.dox index 90aba3bc8..9327891be 100644 --- a/doc/qtv.dox +++ b/doc/qtv.dox @@ -10,7 +10,7 @@ The server is "reserved" for playing clients. Any spectators would be referees and/or admins (however, this is up to the server admin). A qtv proxy connects to the server. The proxy may have spectating clients -and other even other proxies connecting to it. The proxies can chain to any +and even other proxies connecting to it. The proxies can chain to any depth as an upstream proxy will pass on its information to any downstream proxies. With just a few levels of proxies, it should be possible to have very large spectator groups. From 1068685677dd26dd1ec9fa3416caec18b7405d27 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 19:55:05 +0900 Subject: [PATCH 1471/3664] [vulkan] Fix incorrect cast The result of an aborted attempt to get QF building for 32-bit windows. --- include/QF/Vulkan/debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/Vulkan/debug.h b/include/QF/Vulkan/debug.h index c5fa70a7b..3250d5aca 100644 --- a/include/QF/Vulkan/debug.h +++ b/include/QF/Vulkan/debug.h @@ -86,7 +86,7 @@ if (dfunc->vkSetDebugUtilsObjectNameEXT) { \ VkDebugUtilsObjectNameInfoEXT nameInfo = { \ VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 0, \ - type, (VkObjectType) handle, name \ + type, (uint64_t) handle, name \ }; \ dfunc->vkSetDebugUtilsObjectNameEXT (device->dev, &nameInfo); \ } \ From 5f93c115ff9b19f98131a47bbe0dcb8908eb7500 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 19:58:00 +0900 Subject: [PATCH 1472/3664] [util] Make developer flag names easier to manage They're now an enum, and the flag part of the name is all lowercase, but now the flag definitions and names list will never get out of sync. --- include/QF/sys.h | 30 ++++----- include/QF/sys_developer.h | 49 ++++++++++++++ libs/audio/cd_linux.c | 26 ++++---- libs/audio/cd_sdl.c | 10 +-- libs/audio/cd_sgi.c | 16 ++--- libs/audio/cd_win.c | 30 ++++----- libs/audio/cd_xmms.c | 2 +- libs/audio/renderer/flac.c | 12 ++-- libs/audio/renderer/midi.c | 2 +- libs/audio/renderer/snd_channels.c | 8 +-- libs/audio/renderer/snd_jack.c | 4 +- libs/audio/renderer/snd_mem.c | 8 +-- libs/audio/renderer/vorbis.c | 12 ++-- libs/audio/renderer/wav.c | 4 +- libs/audio/targets/snd_alsa.c | 6 +- libs/audio/targets/snd_oss.c | 2 +- libs/audio/targets/snd_win.c | 2 +- libs/console/server.c | 2 +- libs/gamecode/pr_builtins.c | 2 +- libs/gamecode/pr_load.c | 2 +- libs/gib/gib_init.c | 2 +- libs/gib/gib_tree.c | 4 +- libs/image/tga.c | 2 +- libs/models/alias/floodfill.c | 2 +- libs/models/alias/gl_mesh.c | 4 +- libs/models/alias/gl_model_alias.c | 4 +- libs/models/brush/gl_model_brush.c | 6 +- libs/models/brush/model_brush.c | 10 +-- libs/models/brush/vulkan_model_brush.c | 6 +- libs/models/gl_model_fullbright.c | 2 +- libs/models/iqm/model_iqm.c | 4 +- libs/models/model.c | 2 +- libs/models/skin.c | 4 +- libs/net/nc/net_udp6.c | 10 +-- libs/net/net_main.c | 6 +- libs/net/nm/net_dgrm.c | 24 +++---- libs/net/nm/net_udp.c | 12 ++-- libs/net/nm/net_wins.c | 2 +- libs/qw/msg_backbuf.c | 4 +- libs/ruamoko/rua_obj.c | 66 +++++++++---------- libs/util/cmd.c | 6 +- libs/util/cvar.c | 21 ++---- libs/util/plugin.c | 4 +- libs/util/quakefs.c | 42 ++++++------ libs/util/wad.c | 2 +- libs/util/zone.c | 10 +-- libs/video/renderer/gl/gl_draw.c | 4 +- libs/video/renderer/gl/gl_dyn_part.c | 10 +-- libs/video/renderer/gl/gl_mod_sprite.c | 4 +- libs/video/renderer/gl/gl_rmain.c | 6 +- libs/video/renderer/gl/gl_screen.c | 2 +- libs/video/renderer/gl/gl_sky.c | 4 +- libs/video/renderer/gl/vid_common_gl.c | 60 ++++++++--------- libs/video/renderer/glsl/glsl_alias.c | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 8 +-- libs/video/renderer/glsl/glsl_particles.c | 8 +-- libs/video/renderer/glsl/glsl_textures.c | 2 +- libs/video/renderer/glsl/vid_common_glsl.c | 14 ++-- libs/video/renderer/r_alias.c | 4 +- libs/video/renderer/r_iqm.c | 2 +- libs/video/renderer/sw/d_surf.c | 2 +- libs/video/renderer/sw/draw.c | 6 +- libs/video/renderer/sw/sw_ralias.c | 4 +- libs/video/renderer/sw32/d_surf.c | 2 +- libs/video/renderer/sw32/draw.c | 6 +- libs/video/renderer/sw32/sw32_ralias.c | 4 +- libs/video/renderer/vid_render_vulkan.c | 4 +- libs/video/renderer/vulkan/capture.c | 4 +- libs/video/renderer/vulkan/device.c | 4 +- libs/video/renderer/vulkan/instance.c | 4 +- libs/video/renderer/vulkan/renderpass.c | 2 +- libs/video/renderer/vulkan/shader.c | 4 +- libs/video/renderer/vulkan/swapchain.c | 6 +- libs/video/renderer/vulkan/vkparse.c | 52 +++++++-------- libs/video/renderer/vulkan/vulkan_bsp.c | 14 ++-- libs/video/renderer/vulkan/vulkan_lighting.c | 4 +- libs/video/renderer/vulkan/vulkan_matrices.c | 20 +++--- .../video/renderer/vulkan/vulkan_vid_common.c | 16 ++--- libs/video/targets/context_x11.c | 10 +-- libs/video/targets/dga_check.c | 8 +-- libs/video/targets/in_common.c | 2 +- libs/video/targets/in_svgalib.c | 8 +-- libs/video/targets/in_win.c | 2 +- libs/video/targets/in_x11.c | 12 ++-- libs/video/targets/joy.c | 6 +- libs/video/targets/joy_linux.c | 4 +- libs/video/targets/vid.c | 4 +- libs/video/targets/vid_3dfxsvga.c | 10 +-- libs/video/targets/vid_fbdev.c | 2 +- libs/video/targets/vid_sdl_gl.c | 6 +- libs/video/targets/vid_svgalib.c | 2 +- libs/video/targets/vid_win.c | 4 +- libs/video/targets/vid_win_gl.c | 6 +- libs/video/targets/vid_x11.c | 4 +- libs/video/targets/vid_x11_gl.c | 6 +- libs/video/targets/vid_x11_sw.c | 24 +++---- nq/source/cl_main.c | 10 +-- nq/source/cl_parse.c | 8 +-- nq/source/host.c | 6 +- nq/source/sv_cl_phys.c | 8 +-- nq/source/sv_main.c | 6 +- nq/source/sv_pr_cmds.c | 2 +- nq/source/sv_progs.c | 2 +- nq/source/sv_user.c | 2 +- qtv/source/client.c | 2 +- qw/source/cl_demo.c | 4 +- qw/source/cl_entparse.c | 8 +-- qw/source/cl_main.c | 10 +-- qw/source/cl_parse.c | 30 ++++----- qw/source/crudefile.c | 2 +- qw/source/pmove.c | 2 +- qw/source/sv_init.c | 4 +- qw/source/sv_main.c | 4 +- qw/source/sv_pr_cmds.c | 2 +- qw/source/sv_progs.c | 2 +- qw/source/sv_qtv.c | 2 +- qw/source/sv_user.c | 6 +- 117 files changed, 526 insertions(+), 494 deletions(-) create mode 100644 include/QF/sys_developer.h diff --git a/include/QF/sys.h b/include/QF/sys.h index 735fe1ca1..eb0f25e00 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -83,23 +83,19 @@ double Sys_DoubleTime (void); void Sys_TimeOfDay(date_t *date); void Sys_MaskPrintf (int mask, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); -// remember to update developer_flags in cvar.c -#define SYS_DEV (1|0) -#define SYS_WARN (1|2) // bit 0 so developer 1 will pick it up -#define SYS_VID (1|4) -#define SYS_FS_NF (1|8) -#define SYS_FS_F (1|16) -#define SYS_FS (1|32) -#define SYS_NET (1|64) -#define SYS_RUA_OBJ (1|128) -#define SYS_RUA_MSG (1|256) -#define SYS_SND (1|512) -#define SYS_GLT (1|1024) -#define SYS_GLSL (1|2048) -#define SYS_SKIN (1|4096) -#define SYS_MODEL (1|8192) -#define SYS_VULKAN (1|16384) -#define SYS_VULKAN_PARSE (1|32768) + +#define SYS_DEVELOPER(developer) SYS_DeveloperID_##developer, +enum { +#include "QF/sys_developer.h" +}; + +// bit 0 so developer 1 will pick it up +#define SYS_DEVELOPER(developer) \ + SYS_##developer = (SYS_dev | (1 << (SYS_DeveloperID_##developer + 1))), +enum { + SYS_dev = 1, +#include "QF/sys_developer.h" +}; int Sys_CheckInput (int idle, int net_socket); const char *Sys_ConsoleInput (void); diff --git a/include/QF/sys_developer.h b/include/QF/sys_developer.h new file mode 100644 index 000000000..46b36a1fd --- /dev/null +++ b/include/QF/sys_developer.h @@ -0,0 +1,49 @@ +/* + sys_developer.h + + Developer flags + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef SYS_DEVELOPER +#define SYS_DEVELOPER(developer) +#endif + +SYS_DEVELOPER (warn) +SYS_DEVELOPER (vid) +SYS_DEVELOPER (input) +SYS_DEVELOPER (fs_nf) +SYS_DEVELOPER (fs_f) +SYS_DEVELOPER (fs) +SYS_DEVELOPER (net) +SYS_DEVELOPER (rua_obj) +SYS_DEVELOPER (rua_msg) +SYS_DEVELOPER (snd) +SYS_DEVELOPER (glt) +SYS_DEVELOPER (glsl) +SYS_DEVELOPER (skin) +SYS_DEVELOPER (model) +SYS_DEVELOPER (vulkan) +SYS_DEVELOPER (vulkan_parse) + +#undef SYS_DEVELOPER diff --git a/libs/audio/cd_linux.c b/libs/audio/cd_linux.c index ff66356df..1bf52e4e1 100644 --- a/libs/audio/cd_linux.c +++ b/libs/audio/cd_linux.c @@ -88,7 +88,7 @@ I_CDAudio_CloseDoor (void) return; // no cd init'd if (ioctl (cdfile, CDROMCLOSETRAY) == -1) - Sys_MaskPrintf (SYS_SND, "CDAudio: ioctl cdromclosetray failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdromclosetray failed\n"); } static void @@ -98,7 +98,7 @@ I_CDAudio_Eject (void) return; // no cd init'd if (ioctl (cdfile, CDROMEJECT) == -1) - Sys_MaskPrintf (SYS_SND, "CDAudio: ioctl cdromeject failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdromeject failed\n"); } static int @@ -109,12 +109,12 @@ I_CDAudio_GetAudioDiskInfo (void) cdValid = false; if (ioctl (cdfile, CDROMREADTOCHDR, &tochdr) == -1) { - Sys_MaskPrintf (SYS_SND, "CDAudio: ioctl cdromreadtochdr failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdromreadtochdr failed\n"); return -1; } if (tochdr.cdth_trk0 < 1) { - Sys_MaskPrintf (SYS_SND, "CDAudio: no music tracks\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: no music tracks\n"); return -1; } @@ -134,7 +134,7 @@ I_CDAudio_Pause (void) return; if (ioctl (cdfile, CDROMPAUSE) == -1) - Sys_MaskPrintf (SYS_SND, "CDAudio: ioctl cdrompause failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdrompause failed\n"); wasPlaying = playing; playing = false; @@ -150,7 +150,7 @@ I_CDAudio_Stop (void) return; if (ioctl (cdfile, CDROMSTOP) == -1) - Sys_MaskPrintf (SYS_SND, "CDAudio: ioctl cdromstop failed (%d)\n", + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdromstop failed (%d)\n", errno); wasPlaying = false; @@ -188,7 +188,7 @@ I_CDAudio_Play (int track, qboolean looping) entry0.cdte_track = track; entry0.cdte_format = CDROM_MSF; if (ioctl (cdfile, CDROMREADTOCENTRY, &entry0) == -1) { - Sys_MaskPrintf (SYS_SND, "CDAudio: ioctl cdromreadtocentry failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdromreadtocentry failed\n"); return; } entry1.cdte_track = track + 1; @@ -197,7 +197,7 @@ I_CDAudio_Play (int track, qboolean looping) entry1.cdte_track = CDROM_LEADOUT; } if (ioctl (cdfile, CDROMREADTOCENTRY, &entry1) == -1) { - Sys_MaskPrintf (SYS_SND, "CDAudio: ioctl cdromreadtocentry failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdromreadtocentry failed\n"); return; } if (entry0.cdte_ctrl == CDROM_DATA_TRACK) { @@ -219,14 +219,14 @@ I_CDAudio_Play (int track, qboolean looping) msf.cdmsf_sec1 = entry1.cdte_addr.msf.second; msf.cdmsf_frame1 = entry1.cdte_addr.msf.frame; - Sys_MaskPrintf (SYS_SND, "%2d:%02d:%02d %2d:%02d:%02d\n", + Sys_MaskPrintf (SYS_snd, "%2d:%02d:%02d %2d:%02d:%02d\n", msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0, msf.cdmsf_min1, msf.cdmsf_sec1, msf.cdmsf_frame1); if (ioctl (cdfile, CDROMPLAYMSF, &msf) == -1) { - Sys_MaskPrintf (SYS_SND, + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdromplaytrkind failed (%s)\n", strerror (errno)); return; @@ -253,7 +253,7 @@ I_CDAudio_Resume (void) return; if (ioctl (cdfile, CDROMRESUME) == -1) - Sys_MaskPrintf (SYS_SND, "CDAudio: ioctl cdromresume failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdromresume failed\n"); playing = true; } @@ -398,7 +398,7 @@ I_CDAudio_Update (void) lastchk = time (NULL) + 2; // two seconds between chks subchnl.cdsc_format = CDROM_MSF; if (ioctl (cdfile, CDROMSUBCHNL, &subchnl) == -1) { - Sys_MaskPrintf (SYS_SND, "CDAudio: ioctl cdromsubchnl failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: ioctl cdromsubchnl failed\n"); playing = false; return; } @@ -423,7 +423,7 @@ Mus_CDChange (cvar_t *mus_cdaudio) cdfile = open (mus_cdaudio->string, O_RDONLY | O_NONBLOCK); if (cdfile == -1) { - Sys_MaskPrintf (SYS_SND, + Sys_MaskPrintf (SYS_snd, "Mus_CDInit: open device \"%s\" failed (error %i)\n", mus_cdaudio->string, errno); return; diff --git a/libs/audio/cd_sdl.c b/libs/audio/cd_sdl.c index 9a0da6c3d..95f8d1b9b 100644 --- a/libs/audio/cd_sdl.c +++ b/libs/audio/cd_sdl.c @@ -74,7 +74,7 @@ I_CDAudio_Eject (void) return; if (SDL_CDEject (cd_id)) - Sys_MaskPrintf (SYS_SND, "Unable to eject CD-ROM tray.\n"); + Sys_MaskPrintf (SYS_snd, "Unable to eject CD-ROM tray.\n"); } static void @@ -86,7 +86,7 @@ I_CDAudio_Pause (void) return; if (SDL_CDPause (cd_id)) - Sys_MaskPrintf (SYS_SND, "CDAudio_Pause: Failed to pause track.\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio_Pause: Failed to pause track.\n"); } static void @@ -101,7 +101,7 @@ I_CDAudio_Stop (void) return; if (SDL_CDStop (cd_id)) - Sys_MaskPrintf (SYS_SND, "CDAudio_Stop: Failed to stop track.\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio_Stop: Failed to stop track.\n"); } static void @@ -134,7 +134,7 @@ I_CDAudio_Play (int track, qboolean looping) if (SDL_CDPlay (cd_id, cd_id->track[track].offset, cd_id->track[track].length)) { - Sys_MaskPrintf (SYS_SND, "CDAudio_Play: Unable to play track: %d\n", + Sys_MaskPrintf (SYS_snd, "CDAudio_Play: Unable to play track: %d\n", track + 1); return; } @@ -150,7 +150,7 @@ I_CDAudio_Resume (void) return; if (SDL_CDResume (cd_id)) - Sys_MaskPrintf (SYS_SND, "CDAudio_Resume: Failed to resume track.\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio_Resume: Failed to resume track.\n"); } static void diff --git a/libs/audio/cd_sgi.c b/libs/audio/cd_sgi.c index 1b9631aab..84858d092 100644 --- a/libs/audio/cd_sgi.c +++ b/libs/audio/cd_sgi.c @@ -72,7 +72,7 @@ I_SGI_Eject (void) return; // no cd init'd if (CDeject (cdp) == 0) - Sys_MaskPrintf (SYS_SND, "I_SGI_Eject: CDeject failed\n"); + Sys_MaskPrintf (SYS_snd, "I_SGI_Eject: CDeject failed\n"); } static int @@ -84,7 +84,7 @@ I_SGI_GetState (void) return -1; // no cd init'd if (CDgetstatus (cdp, &cds) == 0) { - Sys_MaskPrintf (SYS_SND, "CDAudio_GetStatus: CDgetstatus failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio_GetStatus: CDgetstatus failed\n"); return -1; } @@ -100,7 +100,7 @@ I_SGI_MaxTrack (void) return -1; // no cd init'd if (CDgetstatus (cdp, &cds) == 0) { - Sys_MaskPrintf (SYS_SND, "I_SGI_MaxTrack: CDgetstatus failed\n"); + Sys_MaskPrintf (SYS_snd, "I_SGI_MaxTrack: CDgetstatus failed\n"); return -1; } @@ -114,7 +114,7 @@ I_SGI_Pause (void) return; if (CDtogglepause (cdp) == 0) - Sys_MaskPrintf (SYS_SND, "CDAudio_PAUSE: CDtogglepause failed (%d)\n", errno); + Sys_MaskPrintf (SYS_snd, "CDAudio_PAUSE: CDtogglepause failed (%d)\n", errno); } void @@ -132,7 +132,7 @@ I_SGI_Play (int track, qboolean looping) } if (maxtrack < 0) { - Sys_MaskPrintf (SYS_SND, + Sys_MaskPrintf (SYS_snd, "CDAudio_Play: Error getting maximum track number\n"); return; } @@ -172,7 +172,7 @@ I_SGI_Play (int track, qboolean looping) } if (CDplaytrack (cdp, track, cdvolume == 0.0 ? 0 : 1) == 0) { - Sys_MaskPrintf (SYS_SND, "CDAudio_Play: CDplay failed (%d)\n", errno); + Sys_MaskPrintf (SYS_snd, "CDAudio_Play: CDplay failed (%d)\n", errno); return; } @@ -187,7 +187,7 @@ I_SGI_Resume (void) return; if (CDtogglepause (cdp) == 0) - Sys_MaskPrintf (SYS_SND, "CDAudio_Resume: CDtogglepause failed (%d)\n", + Sys_MaskPrintf (SYS_snd, "CDAudio_Resume: CDtogglepause failed (%d)\n", errno); } @@ -210,7 +210,7 @@ I_SGI_Stop (void) return; if (CDstop (cdp) == 0) - Sys_MaskPrintf (SYS_SND, "I_SGI_Stop: CDStop failed (%d)\n", errno); + Sys_MaskPrintf (SYS_snd, "I_SGI_Stop: CDStop failed (%d)\n", errno); } void diff --git a/libs/audio/cd_win.c b/libs/audio/cd_win.c index 5c297adc0..26752a503 100644 --- a/libs/audio/cd_win.c +++ b/libs/audio/cd_win.c @@ -75,7 +75,7 @@ I_CDAudio_CloseDoor (void) dwReturn = mciSendCommand (wDeviceID, MCI_SET, MCI_SET_DOOR_CLOSED, (DWORD_PTR) NULL); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, "MCI_SET_DOOR_CLOSED failed (%li)\n", + Sys_MaskPrintf (SYS_snd, "MCI_SET_DOOR_CLOSED failed (%li)\n", dwReturn); } } @@ -88,7 +88,7 @@ I_CDAudio_Eject (void) dwReturn = mciSendCommand (wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, (DWORD_PTR) NULL); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, "MCI_SET_DOOR_OPEN failed (%li)\n", dwReturn); + Sys_MaskPrintf (SYS_snd, "MCI_SET_DOOR_OPEN failed (%li)\n", dwReturn); } } @@ -105,12 +105,12 @@ I_CDAudio_GetAudioDiskInfo (void) mciSendCommand (wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR) (LPVOID) & mciStatusParms); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, + Sys_MaskPrintf (SYS_snd, "CDAudio: drive ready test - get status failed\n"); return -1; } if (!mciStatusParms.dwReturn) { - Sys_MaskPrintf (SYS_SND, "CDAudio: drive not ready\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: drive not ready\n"); return -1; } @@ -119,11 +119,11 @@ I_CDAudio_GetAudioDiskInfo (void) mciSendCommand (wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD_PTR) (LPVOID) & mciStatusParms); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, "CDAudio: get tracks - status failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: get tracks - status failed\n"); return -1; } if (mciStatusParms.dwReturn < 1) { - Sys_MaskPrintf (SYS_SND, "CDAudio: no music tracks\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio: no music tracks\n"); return -1; } @@ -154,13 +154,13 @@ static I_CDAudio_MessageHandler (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa break; case MCI_NOTIFY_FAILURE: - Sys_MaskPrintf (SYS_SND, "MCI_NOTIFY_FAILURE\n"); + Sys_MaskPrintf (SYS_snd, "MCI_NOTIFY_FAILURE\n"); I_CDAudio_Stop (); cdValid = false; break; default: - Sys_MaskPrintf (SYS_SND, "Unexpected MM_MCINOTIFY type (%i)\n", + Sys_MaskPrintf (SYS_snd, "Unexpected MM_MCINOTIFY type (%i)\n", wParam); return 1; } @@ -185,7 +185,7 @@ I_CDAudio_Pause (void) mciSendCommand (wDeviceID, MCI_PAUSE, 0, (DWORD_PTR) (LPVOID) & mciGenericParms); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, "MCI_PAUSE failed (%li)", dwReturn); + Sys_MaskPrintf (SYS_snd, "MCI_PAUSE failed (%li)", dwReturn); } wasPlaying = playing; @@ -226,7 +226,7 @@ I_CDAudio_Play (int track, qboolean looping) MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD_PTR) (LPVOID) & mciStatusParms); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, "MCI_STATUS failed (%li)\n", dwReturn); + Sys_MaskPrintf (SYS_snd, "MCI_STATUS failed (%li)\n", dwReturn); return; } if (mciStatusParms.dwReturn != MCI_CDA_TRACK_AUDIO) { @@ -241,7 +241,7 @@ I_CDAudio_Play (int track, qboolean looping) MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT, (DWORD_PTR) (LPVOID) & mciStatusParms); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, "MCI_STATUS failed (%li)\n", dwReturn); + Sys_MaskPrintf (SYS_snd, "MCI_STATUS failed (%li)\n", dwReturn); return; } @@ -258,7 +258,7 @@ I_CDAudio_Play (int track, qboolean looping) mciSendCommand (wDeviceID, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD_PTR) (LPVOID) & mciPlayParms); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, "CDAudio: MCI_PLAY failed (%li)\n", dwReturn); + Sys_MaskPrintf (SYS_snd, "CDAudio: MCI_PLAY failed (%li)\n", dwReturn); return; } @@ -290,7 +290,7 @@ I_CDAudio_Resume (void) mciSendCommand (wDeviceID, MCI_PLAY, MCI_TO | MCI_NOTIFY, (DWORD_PTR) (LPVOID) & mciPlayParms); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, "CDAudio: MCI_PLAY failed (%li)\n", dwReturn); + Sys_MaskPrintf (SYS_snd, "CDAudio: MCI_PLAY failed (%li)\n", dwReturn); return; } playing = true; @@ -303,7 +303,7 @@ I_CDAudio_Shutdown (void) return; I_CDAudio_Stop (); if (mciSendCommand (wDeviceID, MCI_CLOSE, MCI_WAIT, (DWORD_PTR) NULL)) - Sys_MaskPrintf (SYS_SND, "CDAudio_Shutdown: MCI_CLOSE failed\n"); + Sys_MaskPrintf (SYS_snd, "CDAudio_Shutdown: MCI_CLOSE failed\n"); } static void @@ -318,7 +318,7 @@ I_CDAudio_Stop (void) dwReturn = mciSendCommand (wDeviceID, MCI_STOP, 0, (DWORD_PTR) NULL); if (dwReturn) { - Sys_MaskPrintf (SYS_SND, "MCI_STOP failed (%li)", dwReturn); + Sys_MaskPrintf (SYS_snd, "MCI_STOP failed (%li)", dwReturn); } wasPlaying = false; diff --git a/libs/audio/cd_xmms.c b/libs/audio/cd_xmms.c index 47c8a187f..de4fe0bae 100644 --- a/libs/audio/cd_xmms.c +++ b/libs/audio/cd_xmms.c @@ -148,7 +148,7 @@ I_XMMS_Running (void) break; case -1: // ICH! // inform user - Sys_MaskPrintf (SYS_SND, "XMMSAudio: error, can't fork!?\n"); + Sys_MaskPrintf (SYS_snd, "XMMSAudio: error, can't fork!?\n"); break; default: // Parent // don't need now :/ diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index be7962522..b94660cc8 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -411,7 +411,7 @@ flac_get_info (flacfile_t *ff) vc = &ff->vorbis_info->data.vorbis_comment; for (i = 0, ve = vc->comments; i < vc->num_comments; ve++, i++) { - Sys_MaskPrintf (SYS_DEV, "%.*s\n", ve->length, ve->entry); + Sys_MaskPrintf (SYS_dev, "%.*s\n", ve->length, ve->entry); if (strncmp ("CUEPOINT=", (char *) ve->entry, 9) == 0) { char *str = alloca (ve->length + 1); strncpy (str, (char *) ve->entry, ve->length); @@ -432,12 +432,12 @@ flac_get_info (flacfile_t *ff) info.dataofs = 0; info.datalen = samples * info.channels * sizeof (float); - Sys_MaskPrintf (SYS_DEV, "\nBitstream is %d channel, %dHz\n", + Sys_MaskPrintf (SYS_dev, "\nBitstream is %d channel, %dHz\n", info.channels, info.rate); - Sys_MaskPrintf (SYS_DEV, "\nDecoded length: %d samples (%d bytes)\n", + Sys_MaskPrintf (SYS_dev, "\nDecoded length: %d samples (%d bytes)\n", info.frames, info.width); if (vc) { - Sys_MaskPrintf (SYS_DEV, "Encoded by: %.*s\n\n", + Sys_MaskPrintf (SYS_dev, "Encoded by: %.*s\n\n", vc->vendor_string.length, vc->vendor_string.entry); } @@ -460,10 +460,10 @@ SND_LoadFLAC (QFile *file, sfx_t *sfx, char *realname) return -1; } if (info.frames / info.rate < 3) { - Sys_MaskPrintf (SYS_DEV, "cache %s\n", realname); + Sys_MaskPrintf (SYS_dev, "cache %s\n", realname); flac_cache (sfx, realname, ff, info); } else { - Sys_MaskPrintf (SYS_DEV, "stream %s\n", realname); + Sys_MaskPrintf (SYS_dev, "stream %s\n", realname); flac_stream (sfx, realname, ff, info); } return 0; diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index c4f44a050..3e2ca6727 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -197,7 +197,7 @@ SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname) WildMidi_Close (handle); - Sys_MaskPrintf (SYS_DEV, "stream %s\n", realname); + Sys_MaskPrintf (SYS_dev, "stream %s\n", realname); // we init stream here cause we will only ever stream SND_SFX_Stream (sfx, realname, info, midi_stream_open); diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 59c068b2c..c736c7553 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -104,7 +104,7 @@ SND_AllocChannel (void) for (free = &free_channels; *free; free = &(*free)->next) { num_free++; } - Sys_MaskPrintf (SYS_WARN, "SND_AllocChannel: out of channels. %d\n", + Sys_MaskPrintf (SYS_warn, "SND_AllocChannel: out of channels. %d\n", num_free); return 0; } @@ -147,7 +147,7 @@ SND_ScanChannels (int wait) return; if (wait) { - Sys_MaskPrintf (SYS_DEV, "scanning channels...\n"); + Sys_MaskPrintf (SYS_dev, "scanning channels...\n"); do { count = 0; for (i = 0; i < MAX_CHANNELS; i++) { @@ -157,12 +157,12 @@ SND_ScanChannels (int wait) ch->stop = 1; count++; } - Sys_MaskPrintf (SYS_DEV, "count = %d\n", count); + Sys_MaskPrintf (SYS_dev, "count = %d\n", count); #ifdef HAVE_USLEEP usleep (1000); #endif } while (count); - Sys_MaskPrintf (SYS_DEV, "scanning done.\n"); + Sys_MaskPrintf (SYS_dev, "scanning done.\n"); } else { for (i = 0; i < MAX_CHANNELS; i++) { ch = &snd_channels[i]; diff --git a/libs/audio/renderer/snd_jack.c b/libs/audio/renderer/snd_jack.c index e35d61e50..faec1c1ac 100644 --- a/libs/audio/renderer/snd_jack.c +++ b/libs/audio/renderer/snd_jack.c @@ -150,7 +150,7 @@ s_jack_activate (void) snd_shutdown = 0; ports = jack_get_ports (jack_handle, 0, 0, JackPortIsPhysical | JackPortIsInput); - if (developer->int_val & SYS_SND) { + if (developer->int_val & SYS_snd) { for (i = 0; ports[i]; i++) Sys_Printf ("%s\n", ports[i]); } @@ -306,7 +306,7 @@ snd_jack_error (const char *desc) static int snd_jack_xrun (void *arg) { - if (developer->int_val & SYS_SND) { + if (developer->int_val & SYS_snd) { fprintf (stderr, "snd_jack: xrun\n"); } return 0; diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 154618899..1be26620d 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -317,7 +317,7 @@ SND_Load (sfx_t *sfx) Qseek (file, 0, SEEK_SET); #ifdef HAVE_VORBIS if (strnequal ("OggS", buf, 4)) { - Sys_MaskPrintf (SYS_DEV, "SND_Load: ogg file\n"); + Sys_MaskPrintf (SYS_dev, "SND_Load: ogg file\n"); if (SND_LoadOgg (file, sfx, realname) == -1) goto bail; return 0; @@ -325,7 +325,7 @@ SND_Load (sfx_t *sfx) #endif #ifdef HAVE_FLAC if (strnequal ("fLaC", buf, 4)) { - Sys_MaskPrintf (SYS_DEV, "SND_Load: flac file\n"); + Sys_MaskPrintf (SYS_dev, "SND_Load: flac file\n"); if (SND_LoadFLAC (file, sfx, realname) == -1) goto bail; return 0; @@ -333,14 +333,14 @@ SND_Load (sfx_t *sfx) #endif #ifdef HAVE_WILDMIDI if (strnequal ("MThd", buf, 4)) { - Sys_MaskPrintf (SYS_DEV, "SND_Load: midi file\n"); + Sys_MaskPrintf (SYS_dev, "SND_Load: midi file\n"); if (SND_LoadMidi (file, sfx, realname) == -1) goto bail; return 0; } #endif if (strnequal ("RIFF", buf, 4)) { - Sys_MaskPrintf (SYS_DEV, "SND_Load: wav file\n"); + Sys_MaskPrintf (SYS_dev, "SND_Load: wav file\n"); if (SND_LoadWav (file, sfx, realname) == -1) goto bail; return 0; diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index 1c346a146..5797c4ce5 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -101,7 +101,7 @@ vorbis_get_info (OggVorbis_File *vf) samples = ov_pcm_total (vf, -1); for (ptr = ov_comment (vf, -1)->user_comments; *ptr; ptr++) { - Sys_MaskPrintf (SYS_DEV, "%s\n", *ptr); + Sys_MaskPrintf (SYS_dev, "%s\n", *ptr); if (strncmp ("CUEPOINT=", *ptr, 9) == 0) { sscanf (*ptr + 9, "%d %d", &sample_start, &sample_count); } @@ -118,11 +118,11 @@ vorbis_get_info (OggVorbis_File *vf) info.dataofs = 0; info.datalen = samples * info.channels * info.width; - Sys_MaskPrintf (SYS_DEV, "\nBitstream is %d channel, %dHz\n", + Sys_MaskPrintf (SYS_dev, "\nBitstream is %d channel, %dHz\n", info.channels, info.rate); - Sys_MaskPrintf (SYS_DEV, "\nDecoded length: %d samples (%d bytes)\n", + Sys_MaskPrintf (SYS_dev, "\nDecoded length: %d samples (%d bytes)\n", info.frames, info.width); - Sys_MaskPrintf (SYS_DEV, "Encoded by: %s\n\n", + Sys_MaskPrintf (SYS_dev, "Encoded by: %s\n\n", ov_comment (vf, -1)->vendor); return info; @@ -302,10 +302,10 @@ SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname) return -1; } if (info.frames / info.rate < 3) { - Sys_MaskPrintf (SYS_DEV, "cache %s\n", realname); + Sys_MaskPrintf (SYS_dev, "cache %s\n", realname); vorbis_cache (sfx, realname, &vf, info); } else { - Sys_MaskPrintf (SYS_DEV, "stream %s\n", realname); + Sys_MaskPrintf (SYS_dev, "stream %s\n", realname); vorbis_stream (sfx, realname, &vf, info); } return 0; diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index b3d59697a..51228cf02 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -280,10 +280,10 @@ SND_LoadWav (QFile *file, sfx_t *sfx, char *realname) } if (info.frames / info.rate < 3) { - Sys_MaskPrintf (SYS_DEV, "cache %s\n", realname); + Sys_MaskPrintf (SYS_dev, "cache %s\n", realname); wav_cache (sfx, realname, file, info); } else { - Sys_MaskPrintf (SYS_DEV, "stream %s\n", realname); + Sys_MaskPrintf (SYS_dev, "stream %s\n", realname); wav_stream (sfx, realname, file, info); } return 0; diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 205153752..329d1a0e7 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -241,12 +241,12 @@ retry_open: err = qfsnd_pcm_hw_params_set_access (pcm, hw, SND_PCM_ACCESS_MMAP_INTERLEAVED); if (0 > err) { - Sys_MaskPrintf (SYS_SND, "ALSA: Failure to set interleaved PCM " + Sys_MaskPrintf (SYS_snd, "ALSA: Failure to set interleaved PCM " "access. %s\n", qfsnd_strerror (err)); err = qfsnd_pcm_hw_params_set_access (pcm, hw, SND_PCM_ACCESS_MMAP_NONINTERLEAVED); if (0 > err) { - Sys_MaskPrintf (SYS_SND, "ALSA: Failure to set noninterleaved PCM " + Sys_MaskPrintf (SYS_snd, "ALSA: Failure to set noninterleaved PCM " "access. %s\n", qfsnd_strerror (err)); // "default" did not work, so retry with "plughw". However do not // second guess the user, even if the user specified "default". @@ -335,7 +335,7 @@ retry_open: for (i = 0; rates[i]; i++) { rate = rates[i]; - Sys_MaskPrintf (SYS_SND, "ALSA: trying %dHz\n", rate); + Sys_MaskPrintf (SYS_snd, "ALSA: trying %dHz\n", rate); err = qfsnd_pcm_hw_params_set_rate_near (pcm, hw, &rate, 0); if (0 <= err) { diff --git a/libs/audio/targets/snd_oss.c b/libs/audio/targets/snd_oss.c index 97383ff82..dc2902b1b 100644 --- a/libs/audio/targets/snd_oss.c +++ b/libs/audio/targets/snd_oss.c @@ -257,7 +257,7 @@ try_open (int rw) len = (len + sz - 1) & ~(sz - 1); sn.buffer = (byte *) mmap (NULL, len, mmmode, mmflags, audio_fd, 0); if (sn.buffer == MAP_FAILED) { - Sys_MaskPrintf (SYS_SND, "Could not mmap %s: %s\n", snd_dev, + Sys_MaskPrintf (SYS_snd, "Could not mmap %s: %s\n", snd_dev, strerror (errno)); close (audio_fd); return 0; diff --git a/libs/audio/targets/snd_win.c b/libs/audio/targets/snd_win.c index 84465516c..59a18344b 100644 --- a/libs/audio/targets/snd_win.c +++ b/libs/audio/targets/snd_win.c @@ -313,7 +313,7 @@ SNDDMA_Submit (void) // find which sound blocks have completed while (1) { if (snd_completed == snd_sent) { - Sys_MaskPrintf (SYS_SND, "Sound overrun\n"); + Sys_MaskPrintf (SYS_snd, "Sound overrun\n"); break; } diff --git a/libs/console/server.c b/libs/console/server.c index 005efb786..625158944 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -370,7 +370,7 @@ process_input (void) interrupted = 0; #ifdef SIGWINCH get_size (&screen_x, &screen_y); - Sys_MaskPrintf (SYS_DEV, "resizing to %d x %d\n", screen_x, screen_y); + Sys_MaskPrintf (SYS_dev, "resizing to %d x %d\n", screen_x, screen_y); resizeterm (screen_y, screen_x); con_linewidth = screen_x; view_resize (sv_con_data.view, screen_x, screen_y); diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index ab159e250..efee00fd2 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -211,7 +211,7 @@ PR_RelocateBuiltins (progs_t *pr) ind = pr->bi_map (pr, ind); bi = PR_FindBuiltinNum (pr, ind); if (!bi || !(proc = bi->proc)) { - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "WARNING: Bad builtin call number: %s = #%d\n", bi_name, -desc->first_statement); proc = bi_no_function; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index a221124dc..f8365bd6f 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -170,7 +170,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) // size of progs themselves pr->progs_size = size + offset_tweak; - Sys_MaskPrintf (SYS_DEV, "Programs occupy %iK.\n", size / 1024); + Sys_MaskPrintf (SYS_dev, "Programs occupy %iK.\n", size / 1024); pr->progs_size = align_size (pr->progs_size); pr->zone_size = align_size (pr->zone_size); diff --git a/libs/gib/gib_init.c b/libs/gib/gib_init.c index b689e141e..28f1fab1d 100644 --- a/libs/gib/gib_init.c +++ b/libs/gib/gib_init.c @@ -77,7 +77,7 @@ GIB_Exec_Override_f (void) } if (!Cvar_Command () && (cmd_warncmd->int_val - || (developer && developer->int_val & SYS_DEV))) + || (developer && developer->int_val & SYS_dev))) Sys_Printf ("execing %s\n", Cmd_Argv (1)); if ((strlen (Cmd_Argv (1)) >= 4 && !strcmp (Cmd_Argv (1) + strlen (Cmd_Argv (1)) - 4, ".gib")) diff --git a/libs/gib/gib_tree.c b/libs/gib/gib_tree.c index 64a6f1172..fbf462072 100644 --- a/libs/gib/gib_tree.c +++ b/libs/gib/gib_tree.c @@ -72,13 +72,13 @@ void GIB_Tree_Ref (gib_tree_t ** tp) { (*tp)->refs++; -// Sys_MaskPrintf (SYS_DEV, "Ref: %p %u\n", *tp, (*tp)->refs); +// Sys_MaskPrintf (SYS_dev, "Ref: %p %u\n", *tp, (*tp)->refs); } void GIB_Tree_Unref (gib_tree_t ** tp) { -// Sys_MaskPrintf (SYS_DEV, "Unref: %p %u\n", *tp, (*tp)->refs - 1); +// Sys_MaskPrintf (SYS_dev, "Unref: %p %u\n", *tp, (*tp)->refs - 1); if (!(--(*tp)->refs)) { GIB_Tree_Free_Recursive (*tp); *tp = 0; diff --git a/libs/image/tga.c b/libs/image/tga.c index 1f72e2687..f28076e6e 100644 --- a/libs/image/tga.c +++ b/libs/image/tga.c @@ -232,7 +232,7 @@ skip_colormap (TargaHeader *targa, byte *data) int bpe; if (!targa->colormap_type) return data; - Sys_MaskPrintf (SYS_DEV, "LoadTGA: skipping colormap\n"); + Sys_MaskPrintf (SYS_dev, "LoadTGA: skipping colormap\n"); bpe = (targa->pixel_size +7) / 8; return data + bpe * targa->colormap_length; } diff --git a/libs/models/alias/floodfill.c b/libs/models/alias/floodfill.c index 29e73a1f5..e7ea195a9 100644 --- a/libs/models/alias/floodfill.c +++ b/libs/models/alias/floodfill.c @@ -82,7 +82,7 @@ Mod_FloodFillSkin (byte * skin, int skinwidth, int skinheight) } // can't fill to filled color or transparent color (used as visited marker) if ((fillcolor == filledcolor) || (fillcolor == 255)) { - Sys_MaskPrintf (SYS_GLT, "not filling skin from %d to %d\n", + Sys_MaskPrintf (SYS_glt, "not filling skin from %d to %d\n", fillcolor, filledcolor); return; } diff --git a/libs/models/alias/gl_mesh.c b/libs/models/alias/gl_mesh.c index 73c65b56d..310795827 100644 --- a/libs/models/alias/gl_mesh.c +++ b/libs/models/alias/gl_mesh.c @@ -321,7 +321,7 @@ BuildTris (mod_alias_ctx_t *alias_ctx) add_command (0); // end of list marker - Sys_MaskPrintf (SYS_DEV, "%3i tri %3i vert %3i cmd\n", + Sys_MaskPrintf (SYS_dev, "%3i tri %3i vert %3i cmd\n", header->mdl.numtris, numorder, numcommands); allverts += numorder; @@ -432,7 +432,7 @@ gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, } if (remesh) { // build it from scratch - Sys_MaskPrintf (SYS_DEV, "meshing %s...\n", alias_ctx->mod->path); + Sys_MaskPrintf (SYS_dev, "meshing %s...\n", alias_ctx->mod->path); BuildTris (alias_ctx); // trifans or lists diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index 4b8d6ccb7..ebc5f3b09 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -85,7 +85,7 @@ gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, } fb_texnum = Mod_Fullbright (pskin, header->mdl.skinwidth, header->mdl.skinheight, name->str); - Sys_MaskPrintf (SYS_GLT, "%s %d\n", name->str, fb_texnum); + Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, fb_texnum); } if (group) { dsprintf (name, "%s_%i_%i", modname, snum, gnum); @@ -94,7 +94,7 @@ gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, } texnum = GL_LoadTexture (name->str, header->mdl.skinwidth, header->mdl.skinheight, pskin, true, false, 1); - Sys_MaskPrintf (SYS_GLT, "%s %d\n", name->str, texnum); + Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, texnum); skindesc->texnum = texnum; skindesc->fb_texnum = fb_texnum; alias_ctx->mod->hasfullbrights = fb_texnum; diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 196bdfd59..42d370c67 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -165,14 +165,14 @@ gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp) && data[3] == 'T') { ver = LittleLong (((int32_t *) data)[1]); if (ver == 1) { - Sys_MaskPrintf (SYS_DEV, "%s loaded", litfilename->str); + Sys_MaskPrintf (SYS_dev, "%s loaded", litfilename->str); brush->lightdata = data + 8; return; } else - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "Unknown .lit file version (%d)\n", ver); } else - Sys_MaskPrintf (SYS_DEV, "Corrupt .lit file (old version?)\n"); + Sys_MaskPrintf (SYS_dev, "Corrupt .lit file (old version?)\n"); } } // LordHavoc: oh well, expand the white lighting data diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index a2f02a322..9e7607595 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -439,7 +439,7 @@ Mod_LoadSubmodels (model_t *mod, bsp_t *bsp) } if (out->visleafs > 8192) - Sys_MaskPrintf (SYS_WARN, + Sys_MaskPrintf (SYS_warn, "%i visleafs exceeds standard limit of 8192.\n", out->visleafs); } @@ -579,7 +579,7 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) out = Hunk_AllocName (count * sizeof (*out), mod->name); if (count > 32767) { - Sys_MaskPrintf (SYS_WARN, + Sys_MaskPrintf (SYS_warn, "%i faces exceeds standard limit of 32767.\n", count); } @@ -666,7 +666,7 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) out = Hunk_AllocName (count * sizeof (*out), mod->name); if (count > 32767) { - Sys_MaskPrintf (SYS_WARN, + Sys_MaskPrintf (SYS_warn, "%i nodes exceeds standard limit of 32767.\n", count); } @@ -778,7 +778,7 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) out = Hunk_AllocName (count * sizeof (*out), mod->name); if (count > 32767) { - Sys_MaskPrintf (SYS_WARN, + Sys_MaskPrintf (SYS_warn, "%i clilpnodes exceeds standard limit of 32767.\n", count); } @@ -884,7 +884,7 @@ Mod_LoadMarksurfaces (model_t *mod, bsp_t *bsp) out = Hunk_AllocName (count * sizeof (*out), mod->name); if (count > 32767) { - Sys_MaskPrintf (SYS_WARN, + Sys_MaskPrintf (SYS_warn, "%i marksurfaces exceeds standard limit of 32767.\n", count); } diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index a7b4dc336..9527a2abe 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -417,14 +417,14 @@ Vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp, vulkan_ctx_t *ctx) && data[3] == 'T') { ver = LittleLong (((int32_t *) data)[1]); if (ver == 1) { - Sys_MaskPrintf (SYS_DEV, "%s loaded", litfilename->str); + Sys_MaskPrintf (SYS_dev, "%s loaded", litfilename->str); brush->lightdata = data + 8; } else { - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "Unknown .lit file version (%d)\n", ver); } } else { - Sys_MaskPrintf (SYS_DEV, "Corrupt .lit file (old version?)\n"); + Sys_MaskPrintf (SYS_dev, "Corrupt .lit file (old version?)\n"); } } dstring_delete (litfilename); diff --git a/libs/models/gl_model_fullbright.c b/libs/models/gl_model_fullbright.c index 6635cbef5..e24050a1f 100644 --- a/libs/models/gl_model_fullbright.c +++ b/libs/models/gl_model_fullbright.c @@ -56,7 +56,7 @@ Mod_Fullbright (byte *skin, int width, int height, const char *name) if (Mod_CalcFullbright (skin, texels, pixels)) { //FIXME black should be transparent for fullbrights (or just fix //fullbright rendering in gl) - Sys_MaskPrintf (SYS_DEV, "FB Model ID: '%s'\n", name); + Sys_MaskPrintf (SYS_dev, "FB Model ID: '%s'\n", name); for (int i = 0; i < pixels; i++) { if (!texels[i]) { texels[i] = 255; diff --git a/libs/models/iqm/model_iqm.c b/libs/models/iqm/model_iqm.c index 1091ee7d9..de01e09a4 100644 --- a/libs/models/iqm/model_iqm.c +++ b/libs/models/iqm/model_iqm.c @@ -162,7 +162,7 @@ load_iqm_vertex_arrays (model_t *mod, const iqmheader *hdr, byte *buffer) for (i = 0; i < hdr->num_vertexarrays; i++) { va = vas + i; - Sys_MaskPrintf (SYS_MODEL, "%u %u %u %u %u %u\n", i, va->type, va->flags, va->format, va->size, va->offset); + Sys_MaskPrintf (SYS_model, "%u %u %u %u %u %u\n", i, va->type, va->flags, va->format, va->size, va->offset); switch (va->type) { case IQM_POSITION: if (position) @@ -588,7 +588,7 @@ Mod_IQMBuildBlendPalette (iqm_t *iqm, int *size) if (!bindices || !bweights) { // Not necessarily an error: might be a static model with no bones // Either way, no need to make a blend palette - Sys_MaskPrintf (SYS_MODEL, "bone index or weight array missing\n"); + Sys_MaskPrintf (SYS_model, "bone index or weight array missing\n"); *size = 0; return 0; } diff --git a/libs/models/model.c b/libs/models/model.c index 4c2d4ac30..e90ef5c00 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -280,7 +280,7 @@ Mod_ForName (const char *name, qboolean crash) mod = Mod_FindName (name); - Sys_MaskPrintf (SYS_DEV, "Mod_ForName: %s, %p\n", name, mod); + Sys_MaskPrintf (SYS_dev, "Mod_ForName: %s, %p\n", name, mod); return Mod_LoadModel (mod, crash); } diff --git a/libs/models/skin.c b/libs/models/skin.c index e5a0353f5..8933dcf51 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -84,7 +84,7 @@ Skin_SetTranslation (int cmap, int top, int bottom) bottom = bound (0, bottom, 13) * 16; if (cmap < 0 || cmap > MAX_TRANSLATIONS) { - Sys_MaskPrintf (SYS_SKIN, "invalid skin slot: %d\n", cmap); + Sys_MaskPrintf (SYS_skin, "invalid skin slot: %d\n", cmap); cmap = 1; } @@ -129,7 +129,7 @@ Skin_SetColormap (skin_t *skin, int cmap) skin = new_skin (); skin->colormap = 0; if (cmap < 0 || cmap > MAX_TRANSLATIONS) { - Sys_MaskPrintf (SYS_SKIN, "invalid skin slot: %d\n", cmap); + Sys_MaskPrintf (SYS_skin, "invalid skin slot: %d\n", cmap); cmap = 0; } if (cmap) diff --git a/libs/net/nc/net_udp6.c b/libs/net/nc/net_udp6.c index c04092a83..fcbcda1f2 100644 --- a/libs/net/nc/net_udp6.c +++ b/libs/net/nc/net_udp6.c @@ -166,7 +166,7 @@ NetadrToSockadr (netadr_t *a, AF_address_t *s) switch (a->family) { case AF_INET: { - Sys_MaskPrintf (SYS_NET, "err, converting v4 to v6...\n"); + Sys_MaskPrintf (SYS_net, "err, converting v4 to v6...\n"); s->ss.ss_family = AF_INET6; s->s6.sin6_addr.s6_addr[10] = s->s6.sin6_addr.s6_addr[11] = 0xff; memcpy (&s->s6.sin6_addr.s6_addr[12], &a->ip, sizeof (s->s4.sin_addr)); @@ -186,7 +186,7 @@ NetadrToSockadr (netadr_t *a, AF_address_t *s) break; } default: - Sys_MaskPrintf (SYS_NET, "%s: Unknown address family %d", __FUNCTION__, a->family); + Sys_MaskPrintf (SYS_net, "%s: Unknown address family %d", __FUNCTION__, a->family); break; } } @@ -207,7 +207,7 @@ SockadrToNetadr (AF_address_t *s, netadr_t *a) break; } default: - Sys_MaskPrintf (SYS_NET, "%s: Unknown address family 0x%x\n", __FUNCTION__, s->ss.ss_family); + Sys_MaskPrintf (SYS_net, "%s: Unknown address family 0x%x\n", __FUNCTION__, s->ss.ss_family); break; } } @@ -387,7 +387,7 @@ NET_StringToAdr (const char *s, netadr_t *a) freeaddrinfo (resultp); SockadrToNetadr (&addr, a); - Sys_MaskPrintf (SYS_NET, "Raw address: %s\n", NET_BaseAdrToString (*a)); + Sys_MaskPrintf (SYS_net, "Raw address: %s\n", NET_BaseAdrToString (*a)); return true; } @@ -509,7 +509,7 @@ UDP_OpenSocket (int port) } else { Host = "::0"; } - Sys_MaskPrintf (SYS_NET, "Binding to IP address [%s]\n", Host); + Sys_MaskPrintf (SYS_net, "Binding to IP address [%s]\n", Host); if (port == PORT_ANY) Service = NULL; diff --git a/libs/net/net_main.c b/libs/net/net_main.c index 996bb10f7..ee0bc4e1f 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -488,7 +488,7 @@ NET_Close (qsocket_t *sock) // call the driver_Close function sfunc.Close (sock); - Sys_MaskPrintf (SYS_NET, "closing socket\n"); + Sys_MaskPrintf (SYS_net, "closing socket\n"); NET_FreeQSocket (sock); } @@ -522,7 +522,7 @@ NET_GetMessage (qsocket_t *sock) // see if this connection has timed out if (ret == 0 && sock->driver) { if (net_time - sock->lastMessageTime > net_messagetimeout->value) { - Sys_MaskPrintf (SYS_NET, "socket timed out\n"); + Sys_MaskPrintf (SYS_net, "socket timed out\n"); NET_Close (sock); return -1; } @@ -816,7 +816,7 @@ NET_Init (void) } if (*my_tcpip_address) - Sys_MaskPrintf (SYS_NET, "TCP/IP address %s\n", my_tcpip_address); + Sys_MaskPrintf (SYS_net, "TCP/IP address %s\n", my_tcpip_address); } diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 7d9c88ab4..1f55dea80 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -342,14 +342,14 @@ Datagram_GetMessage (qsocket_t *sock) if (flags & NETFLAG_UNRELIABLE) { if (sequence < sock->unreliableReceiveSequence) { - Sys_MaskPrintf (SYS_NET, "Got a stale datagram\n"); + Sys_MaskPrintf (SYS_net, "Got a stale datagram\n"); ret = 0; break; } if (sequence != sock->unreliableReceiveSequence) { count = sequence - sock->unreliableReceiveSequence; droppedDatagrams += count; - Sys_MaskPrintf (SYS_NET, "Dropped %u datagram(s)\n", count); + Sys_MaskPrintf (SYS_net, "Dropped %u datagram(s)\n", count); } sock->unreliableReceiveSequence = sequence + 1; @@ -365,15 +365,15 @@ Datagram_GetMessage (qsocket_t *sock) if (flags & NETFLAG_ACK) { if (sequence != (sock->sendSequence - 1)) { - Sys_MaskPrintf (SYS_NET, "Stale ACK received\n"); + Sys_MaskPrintf (SYS_net, "Stale ACK received\n"); continue; } if (sequence == sock->ackSequence) { sock->ackSequence++; if (sock->ackSequence != sock->sendSequence) - Sys_MaskPrintf (SYS_NET, "ack sequencing error\n"); + Sys_MaskPrintf (SYS_net, "ack sequencing error\n"); } else { - Sys_MaskPrintf (SYS_NET, "Duplicate ACK received\n"); + Sys_MaskPrintf (SYS_net, "Duplicate ACK received\n"); continue; } sock->sendMessageLength -= MAX_DATAGRAM; @@ -1021,7 +1021,7 @@ _Datagram_CheckNewConnections (void) } // it's somebody coming back in from a crash/disconnect // so close the old qsocket and let their retry get them back in - Sys_MaskPrintf (SYS_NET, "closing stale socket %d %g\n", ret, + Sys_MaskPrintf (SYS_net, "closing stale socket %d %g\n", ret, net_time - s->connecttime); NET_Close (s); return NULL; @@ -1048,13 +1048,13 @@ _Datagram_CheckNewConnections (void) // allocate a network socket newsock = dfunc.OpenSocket (0); if (newsock == -1) { - Sys_MaskPrintf (SYS_NET, "failed to open socket"); + Sys_MaskPrintf (SYS_net, "failed to open socket"); NET_FreeQSocket (sock); return NULL; } // connect to the client if (dfunc.Connect (newsock, &clientaddr) == -1) { - Sys_MaskPrintf (SYS_NET, "failed to connect client"); + Sys_MaskPrintf (SYS_net, "failed to connect client"); dfunc.CloseSocket (newsock); NET_FreeQSocket (sock); return NULL; @@ -1269,11 +1269,11 @@ _Datagram_Connect (const char *host) if (ret > 0) { // is it from the right place? if (sfunc.AddrCompare (&readaddr, &sendaddr) != 0) { - Sys_MaskPrintf (SYS_NET, "%2d ", + Sys_MaskPrintf (SYS_net, "%2d ", sfunc.AddrCompare (&readaddr, &sendaddr)); - Sys_MaskPrintf (SYS_NET, "%d %s ", readaddr.family, + Sys_MaskPrintf (SYS_net, "%d %s ", readaddr.family, sfunc.AddrToString (&readaddr)); - Sys_MaskPrintf (SYS_NET, "%d %s\n", sendaddr.family, + Sys_MaskPrintf (SYS_net, "%d %s\n", sendaddr.family, sfunc.AddrToString (&sendaddr)); ret = 0; continue; @@ -1363,7 +1363,7 @@ _Datagram_Connect (const char *host) ErrorReturn: // FIXME: MENUCODE - do something with reason - Sys_MaskPrintf (SYS_NET, "FIXME: MENUCODE - do something with reason\n"); + Sys_MaskPrintf (SYS_net, "FIXME: MENUCODE - do something with reason\n"); NET_FreeQSocket (sock); ErrorReturn2: dfunc.CloseSocket (newsock); diff --git a/libs/net/nm/net_udp.c b/libs/net/nm/net_udp.c index 41cf8b9ec..2ad422d16 100644 --- a/libs/net/nm/net_udp.c +++ b/libs/net/nm/net_udp.c @@ -203,7 +203,7 @@ get_iface_list (int sock) num_ifaces = index; } ifaces = malloc (num_ifaces * sizeof (uint32_t)); - Sys_MaskPrintf (SYS_NET, "%d interfaces\n", num_ifaces); + Sys_MaskPrintf (SYS_net, "%d interfaces\n", num_ifaces); for (ifa = ifa_head; ifa; ifa = ifa->ifa_next) { struct sockaddr_in *sa; @@ -214,7 +214,7 @@ get_iface_list (int sock) index = if_nametoindex (ifa->ifa_name) - 1; sa = (struct sockaddr_in *) ifa->ifa_addr; memcpy (&ifaces[index], &sa->sin_addr, sizeof (uint32_t)); - Sys_MaskPrintf (SYS_NET, " %-10s %s\n", ifa->ifa_name, + Sys_MaskPrintf (SYS_net, " %-10s %s\n", ifa->ifa_name, inet_ntoa (sa->sin_addr)); if (!default_iface && ifaces[index] != htonl (0x7f000001)) default_iface = &ifaces[index]; @@ -498,7 +498,7 @@ UDP_Read (int socket, byte *buf, int len, netadr_t *from) return 0; for (cmsg = CMSG_FIRSTHDR (&msghdr); cmsg; cmsg = CMSG_NXTHDR (&msghdr, cmsg)) { - Sys_MaskPrintf (SYS_NET, "%d\n", cmsg->cmsg_type); + Sys_MaskPrintf (SYS_net, "%d\n", cmsg->cmsg_type); if (cmsg->cmsg_type == IP_PKTINFO) { info = (struct in_pktinfo *) CMSG_DATA (cmsg); break; @@ -512,7 +512,7 @@ UDP_Read (int socket, byte *buf, int len, netadr_t *from) last_iface = &ifaces[info->ipi_ifindex - 1]; } SockadrToNetadr (&addr, from); - Sys_MaskPrintf (SYS_NET, "got %d bytes from %s on iface %d (%s)\n", ret, + Sys_MaskPrintf (SYS_net, "got %d bytes from %s on iface %d (%s)\n", ret, UDP_AddrToString (from), info ? info->ipi_ifindex - 1 : -1, last_iface ? inet_ntoa (info->ipi_addr) : "?"); #else @@ -524,7 +524,7 @@ UDP_Read (int socket, byte *buf, int len, netadr_t *from) if (ret == -1 && (errno == EWOULDBLOCK || errno == ECONNREFUSED)) return 0; SockadrToNetadr (&addr, from); - Sys_MaskPrintf (SYS_NET, "got %d bytes from %s\n", ret, + Sys_MaskPrintf (SYS_net, "got %d bytes from %s\n", ret, UDP_AddrToString (from)); last_iface = default_iface; #endif @@ -574,7 +574,7 @@ UDP_Write (int socket, byte *buf, int len, netadr_t *to) SA_LEN (&addr.sa)); if (ret == -1 && errno == EWOULDBLOCK) return 0; - Sys_MaskPrintf (SYS_NET, "sent %d bytes to %s\n", ret, + Sys_MaskPrintf (SYS_net, "sent %d bytes to %s\n", ret, UDP_AddrToString (to)); return ret; } diff --git a/libs/net/nm/net_wins.c b/libs/net/nm/net_wins.c index 299509a18..6b779bfa5 100644 --- a/libs/net/nm/net_wins.c +++ b/libs/net/nm/net_wins.c @@ -247,7 +247,7 @@ WINS_Init (void) // determine my name if (pgethostname (buff, MAXHOSTNAMELEN) == SOCKET_ERROR) { - Sys_MaskPrintf (SYS_NET, "Winsock TCP/IP Initialization failed.\n"); + Sys_MaskPrintf (SYS_net, "Winsock TCP/IP Initialization failed.\n"); if (--winsock_initialized == 0) pWSACleanup (); return -1; diff --git a/libs/qw/msg_backbuf.c b/libs/qw/msg_backbuf.c index ce3607516..90d80704c 100644 --- a/libs/qw/msg_backbuf.c +++ b/libs/qw/msg_backbuf.c @@ -47,7 +47,7 @@ PushBackbuf (backbuf_t *rel) { int tail_backbuf; - Sys_MaskPrintf (SYS_DEV, "backbuffering %d %s\n", rel->num_backbuf, + Sys_MaskPrintf (SYS_dev, "backbuffering %d %s\n", rel->num_backbuf, rel->name); tail_backbuf = (rel->head_backbuf + rel->num_backbuf) % MAX_BACK_BUFFERS; memset (&rel->backbuf, 0, sizeof (rel->backbuf)); @@ -266,7 +266,7 @@ MSG_Reliable_Send (backbuf_t *rel) return; // will it fit? if (msg->cursize + *size < msg->maxsize) { - Sys_MaskPrintf (SYS_DEV, "%s: backbuf %d bytes\n", rel->name, *size); + Sys_MaskPrintf (SYS_dev, "%s: backbuf %d bytes\n", rel->name, *size); // it'll fit SZ_Write (msg, data, *size); diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index a901823b0..6babd2963 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -456,7 +456,7 @@ finish_class (probj_t *probj, pr_class_t *class, pointer_t object_ptr) ml = &G_STRUCT (pr, pr_method_list_t, *ml).method_next; *ml = class->methods; } - Sys_MaskPrintf (SYS_RUA_OBJ, " %x %x %x\n", meta->class_pointer, + Sys_MaskPrintf (SYS_rua_obj, " %x %x %x\n", meta->class_pointer, meta->super_class, class->super_class); } @@ -514,7 +514,7 @@ sel_register_typed_name (probj_t *probj, const char *name, const char *types, } } } else { - Sys_MaskPrintf (SYS_RUA_OBJ, " Registering SEL %s %s\n", + Sys_MaskPrintf (SYS_rua_obj, " Registering SEL %s %s\n", name, types); index = add_sel_name (probj, name); is_new = 1; @@ -533,7 +533,7 @@ sel_register_typed_name (probj_t *probj, const char *name, const char *types, if (is_new) Hash_Add (probj->selector_hash, (void *) index); done: - Sys_MaskPrintf (SYS_RUA_OBJ, " %d @ %x\n", + Sys_MaskPrintf (SYS_rua_obj, " %d @ %x\n", sel->sel_id, PR_SetPointer (pr, sel)); return sel; } @@ -795,32 +795,32 @@ obj_find_message (probj_t *probj, pr_class_t *class, pr_sel_t *selector) int dev = developer->int_val; string_t *names; - if (dev & SYS_RUA_MSG) { + if (dev & SYS_rua_msg) { names = probj->selector_names; Sys_Printf ("Searching for %s\n", PR_GetString (pr, names[selector->sel_id])); } while (c) { - if (dev & SYS_RUA_MSG) + if (dev & SYS_rua_msg) Sys_Printf ("Checking class %s @ %x\n", PR_GetString (pr, c->name), PR_SetPointer (pr, c)); method_list = &G_STRUCT (pr, pr_method_list_t, c->methods); while (method_list) { - if (dev & SYS_RUA_MSG) { + if (dev & SYS_rua_msg) { Sys_Printf ("method list %x\n", PR_SetPointer (pr, method_list)); } for (i = 0, method = method_list->method_list; i < method_list->method_count; i++, method++) { sel = &G_STRUCT (pr, pr_sel_t, method->method_name); - if (developer->int_val & SYS_RUA_MSG) { + if (developer->int_val & SYS_rua_msg) { names = probj->selector_names; Sys_Printf (" %s\n", PR_GetString (pr, names[sel->sel_id])); } if (sel->sel_id == selector->sel_id) { - if (dev & SYS_RUA_MSG) { + if (dev & SYS_rua_msg) { names = probj->selector_names; Sys_Printf ("found %s: %x\n", PR_GetString (pr, names[selector->sel_id]), @@ -912,7 +912,7 @@ obj_install_dispatch_table_for_class (probj_t *probj, pr_class_t *class) pr_class_t *super = &G_STRUCT (pr, pr_class_t, class->super_class); dtable_t *dtable; - Sys_MaskPrintf (SYS_RUA_OBJ, " install dispatch for class %s %x %d\n", + Sys_MaskPrintf (SYS_rua_obj, " install dispatch for class %s %x %d\n", PR_GetString (pr, class->name), class->methods, PR_CLS_ISMETA(class)); @@ -1054,7 +1054,7 @@ obj_init_statics (probj_t *probj) pointer_t *ptr; pointer_t *inst; - Sys_MaskPrintf (SYS_RUA_OBJ, "Initializing statics\n"); + Sys_MaskPrintf (SYS_rua_obj, "Initializing statics\n"); while (*cell) { int initialized = 1; @@ -1063,7 +1063,7 @@ obj_init_statics (probj_t *probj) const char *class_name = PR_GetString (pr, statics->class_name); pr_class_t *class = Hash_Find (probj->classes, class_name); - Sys_MaskPrintf (SYS_RUA_OBJ, " %s %p\n", class_name, class); + Sys_MaskPrintf (SYS_rua_obj, " %s %p\n", class_name, class); if (!class) { initialized = 0; continue; @@ -1107,7 +1107,7 @@ rua___obj_exec_class (progs_t *pr) symtab = &G_STRUCT (pr, pr_symtab_t, module->symtab); if (!symtab) return; - Sys_MaskPrintf (SYS_RUA_OBJ, "Initializing %s module\n" + Sys_MaskPrintf (SYS_rua_obj, "Initializing %s module\n" "symtab @ %x : %d selector%s @ %x, " "%d class%s and %d categor%s\n" "static instance lists: %s\n", @@ -1137,26 +1137,26 @@ rua___obj_exec_class (progs_t *pr) pr_class_t *meta = &G_STRUCT (pr, pr_class_t, class->class_pointer); const char *super_class = PR_GetString (pr, class->super_class); - Sys_MaskPrintf (SYS_RUA_OBJ, "Class %s @ %x\n", + Sys_MaskPrintf (SYS_rua_obj, "Class %s @ %x\n", PR_GetString (pr, class->name), *ptr); - Sys_MaskPrintf (SYS_RUA_OBJ, " class pointer: %x\n", + Sys_MaskPrintf (SYS_rua_obj, " class pointer: %x\n", class->class_pointer); - Sys_MaskPrintf (SYS_RUA_OBJ, " super class: %s\n", + Sys_MaskPrintf (SYS_rua_obj, " super class: %s\n", PR_GetString (pr, class->super_class)); - Sys_MaskPrintf (SYS_RUA_OBJ, " instance variables: %d @ %x\n", + Sys_MaskPrintf (SYS_rua_obj, " instance variables: %d @ %x\n", class->instance_size, class->ivars); - if (developer->int_val & SYS_RUA_OBJ) + if (developer->int_val & SYS_rua_obj) dump_ivars (probj, class->ivars); - Sys_MaskPrintf (SYS_RUA_OBJ, " instance methods: %x\n", + Sys_MaskPrintf (SYS_rua_obj, " instance methods: %x\n", class->methods); - Sys_MaskPrintf (SYS_RUA_OBJ, " protocols: %x\n", class->protocols); + Sys_MaskPrintf (SYS_rua_obj, " protocols: %x\n", class->protocols); - Sys_MaskPrintf (SYS_RUA_OBJ, " class methods: %x\n", meta->methods); - Sys_MaskPrintf (SYS_RUA_OBJ, " instance variables: %d @ %x\n", + Sys_MaskPrintf (SYS_rua_obj, " class methods: %x\n", meta->methods); + Sys_MaskPrintf (SYS_rua_obj, " instance variables: %d @ %x\n", meta->instance_size, meta->ivars); - if (developer->int_val & SYS_RUA_OBJ) + if (developer->int_val & SYS_rua_obj) dump_ivars (probj, meta->ivars); class->subclass_list = 0; @@ -1183,14 +1183,14 @@ rua___obj_exec_class (progs_t *pr) const char *class_name = PR_GetString (pr, category->class_name); pr_class_t *class = Hash_Find (probj->classes, class_name); - Sys_MaskPrintf (SYS_RUA_OBJ, "Category %s (%s) @ %x\n", + Sys_MaskPrintf (SYS_rua_obj, "Category %s (%s) @ %x\n", PR_GetString (pr, category->class_name), PR_GetString (pr, category->category_name), *ptr); - Sys_MaskPrintf (SYS_RUA_OBJ, " instance methods: %x\n", + Sys_MaskPrintf (SYS_rua_obj, " instance methods: %x\n", category->instance_methods); - Sys_MaskPrintf (SYS_RUA_OBJ, " class methods: %x\n", + Sys_MaskPrintf (SYS_rua_obj, " class methods: %x\n", category->class_methods); - Sys_MaskPrintf (SYS_RUA_OBJ, " protocols: %x\n", + Sys_MaskPrintf (SYS_rua_obj, " protocols: %x\n", category->protocols); if (class) { @@ -1202,7 +1202,7 @@ rua___obj_exec_class (progs_t *pr) } if (*ptr) { - Sys_MaskPrintf (SYS_RUA_OBJ, "Static instances lists: %x\n", *ptr); + Sys_MaskPrintf (SYS_rua_obj, "Static instances lists: %x\n", *ptr); probj->uninitialized_statics = list_cons (&G_STRUCT (pr, pointer_t, *ptr), probj->uninitialized_statics); @@ -1232,10 +1232,10 @@ rua___obj_exec_class (progs_t *pr) } } - Sys_MaskPrintf (SYS_RUA_OBJ, "Finished initializing %s module\n", + Sys_MaskPrintf (SYS_rua_obj, "Finished initializing %s module\n", PR_GetString (pr, module->name)); obj_send_load (probj); - Sys_MaskPrintf (SYS_RUA_OBJ, "Leaving %s module init\n", + Sys_MaskPrintf (SYS_rua_obj, "Leaving %s module init\n", PR_GetString (pr, module->name)); } @@ -1989,7 +1989,7 @@ obj_protocol_conformsToProtocol (probj_t *probj, pr_protocol_t *proto, } proto_list = &G_STRUCT (pr, pr_protocol_list_t, proto->protocol_list); while (proto_list) { - Sys_MaskPrintf (SYS_RUA_OBJ, "%x %x %d\n", + Sys_MaskPrintf (SYS_rua_obj, "%x %x %d\n", PR_SetPointer (pr, proto_list), proto_list->next, proto_list->count); for (int i = 0; i < proto_list->count; i++) { @@ -2028,7 +2028,7 @@ rua__c_Object__conformsToProtocol_ (progs_t *pr) } proto_list = &G_STRUCT (pr, pr_protocol_list_t, class->protocols); while (proto_list) { - Sys_MaskPrintf (SYS_RUA_OBJ, "%x %x %d\n", + Sys_MaskPrintf (SYS_rua_obj, "%x %x %d\n", PR_SetPointer (pr, proto_list), proto_list->next, proto_list->count); for (int i = 0; i < proto_list->count; i++) { @@ -2043,11 +2043,11 @@ rua__c_Object__conformsToProtocol_ (progs_t *pr) proto_list = &G_STRUCT (pr, pr_protocol_list_t, proto_list->next); } not_conforms: - Sys_MaskPrintf (SYS_RUA_OBJ, "does not conform\n"); + Sys_MaskPrintf (SYS_rua_obj, "does not conform\n"); R_INT (pr) = 0; return; conforms: - Sys_MaskPrintf (SYS_RUA_OBJ, "conforms\n"); + Sys_MaskPrintf (SYS_rua_obj, "conforms\n"); R_INT (pr) = 1; return; } diff --git a/libs/util/cmd.c b/libs/util/cmd.c index 812fb55b6..ffc6a14e6 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -130,7 +130,7 @@ Cmd_Command (cbuf_args_t *args) return 0; if (cbuf_active->strict) return -1; - else if (cmd_warncmd->int_val || developer->int_val & SYS_DEV) + else if (cmd_warncmd->int_val || developer->int_val & SYS_dev) Sys_Printf ("Unknown command \"%s\"\n", Cmd_Argv (0)); return 0; } @@ -145,7 +145,7 @@ add_command (const char *cmd_name, xcommand_t func, xdatacmd_t datafunc, // fail if the command already exists cmd = (cmd_function_t *) Hash_Find (cmd_hash, cmd_name); if (cmd) { - Sys_MaskPrintf (SYS_DEV, "Cmd_AddCommand: %s already defined\n", + Sys_MaskPrintf (SYS_dev, "Cmd_AddCommand: %s already defined\n", cmd_name); return 0; } @@ -516,7 +516,7 @@ Cmd_Exec_f (void) } if (!Cvar_Command () && (cmd_warncmd->int_val - || (developer && developer->int_val & SYS_DEV))) + || (developer && developer->int_val & SYS_dev))) Sys_Printf ("execing %s\n", Cmd_Argv (1)); Cbuf_InsertText (cbuf_active, f); Hunk_FreeToLowMark (mark); diff --git a/libs/util/cvar.c b/libs/util/cvar.c index afcfeef33..10915818d 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -258,7 +258,7 @@ Cvar_Set (cvar_t *var, const char *value) return; if (var->flags & CVAR_ROM) { - Sys_MaskPrintf (SYS_DEV, "Cvar \"%s\" is read-only, cannot modify\n", + Sys_MaskPrintf (SYS_dev, "Cvar \"%s\" is read-only, cannot modify\n", var->name); return; } @@ -330,23 +330,10 @@ Cvar_WriteVariables (QFile *f) Qprintf (f, "seta %s \"%s\"\n", var->name, var->string); } -// XXX make sure in sync with SYS_* in sys.h +#define SYS_DEVELOPER(developer) #developer, static const char *developer_flags[] = { "dev", - "warn", - "vid", - "fs_nf", - "fs_f", - "fs", - "net", - "rua_obj", - "rua_msg", - "snd", - "glt", - "glsl", - "skin", - "model", - "vulkan", +#include "QF/sys_developer.h" 0 }; @@ -427,7 +414,7 @@ set_cvar (const char *cmd, int orflags) if (var) { if (var->flags & CVAR_ROM) { - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "Cvar \"%s\" is read-only, cannot modify\n", var_name); } else { diff --git a/libs/util/plugin.c b/libs/util/plugin.c index 9505475fc..629b22e28 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -345,7 +345,7 @@ PI_LoadPlugin (const char *type, const char *name) // try to reopen if (!(dlhand = pi_open_lib (realname, 1))) { Sys_Printf ("Error reopening plugin \"%s\".\n", realname); - Sys_MaskPrintf (SYS_DEV, "Reason: \"%s\".\n", pi_error); + Sys_MaskPrintf (SYS_dev, "Reason: \"%s\".\n", pi_error); return NULL; } @@ -391,7 +391,7 @@ PI_UnloadPlugin (plugin_t *plugin) && plugin->functions->general->p_Shutdown) { plugin->functions->general->p_Shutdown (); } else { - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "Warning: No shutdown function for type %d plugin!\n", plugin->type); } diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 163b77112..2b19f32ad 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -625,16 +625,16 @@ qfs_build_gamedir (const char **list) gamedir->dir.shots = strdup ("QF"); qfs_gamedir = gamedir; - Sys_MaskPrintf (SYS_FS, "%s\n", qfs_gamedir->name); - Sys_MaskPrintf (SYS_FS, " gamedir : %s\n", qfs_gamedir->gamedir); - Sys_MaskPrintf (SYS_FS, " path : %s\n", qfs_gamedir->path); - Sys_MaskPrintf (SYS_FS, " gamecode: %s\n", qfs_gamedir->gamecode); - Sys_MaskPrintf (SYS_FS, " hudtype : %s\n", qfs_gamedir->hudtype); - Sys_MaskPrintf (SYS_FS, " def : %s\n", qfs_gamedir->dir.def); - Sys_MaskPrintf (SYS_FS, " skins : %s\n", qfs_gamedir->dir.skins); - Sys_MaskPrintf (SYS_FS, " models : %s\n", qfs_gamedir->dir.models); - Sys_MaskPrintf (SYS_FS, " sound : %s\n", qfs_gamedir->dir.sound); - Sys_MaskPrintf (SYS_FS, " maps : %s\n", qfs_gamedir->dir.maps); + Sys_MaskPrintf (SYS_fs, "%s\n", qfs_gamedir->name); + Sys_MaskPrintf (SYS_fs, " gamedir : %s\n", qfs_gamedir->gamedir); + Sys_MaskPrintf (SYS_fs, " path : %s\n", qfs_gamedir->path); + Sys_MaskPrintf (SYS_fs, " gamecode: %s\n", qfs_gamedir->gamecode); + Sys_MaskPrintf (SYS_fs, " hudtype : %s\n", qfs_gamedir->hudtype); + Sys_MaskPrintf (SYS_fs, " def : %s\n", qfs_gamedir->dir.def); + Sys_MaskPrintf (SYS_fs, " skins : %s\n", qfs_gamedir->dir.skins); + Sys_MaskPrintf (SYS_fs, " models : %s\n", qfs_gamedir->dir.models); + Sys_MaskPrintf (SYS_fs, " sound : %s\n", qfs_gamedir->dir.sound); + Sys_MaskPrintf (SYS_fs, " maps : %s\n", qfs_gamedir->dir.maps); qfs_process_path (qfs_gamedir->path, dir); free (path); Hash_DelTable (dirs); @@ -652,7 +652,7 @@ qfs_load_config (void) if (*fs_dirconf->string) { dirconf = Sys_ExpandSquiggle (fs_dirconf->string); if (!(f = Qopen (dirconf, "rt"))) - Sys_MaskPrintf (SYS_FS, + Sys_MaskPrintf (SYS_fs, "Could not load `%s', using builtin defaults\n", dirconf); free (dirconf); @@ -831,7 +831,7 @@ qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, } } if (packfile) { - Sys_MaskPrintf (SYS_FS_F, "PackFile: %s : %s\n", + Sys_MaskPrintf (SYS_fs_f, "PackFile: %s : %s\n", sp->pack->filename, packfile->name); found.ff.vpath = vpath; found.ff.in_pak = true; @@ -852,7 +852,7 @@ qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, continue; } - Sys_MaskPrintf (SYS_FS_F, "FindFile: %s\n", path->str); + Sys_MaskPrintf (SYS_fs_f, "FindFile: %s\n", path->str); found.ff.vpath = vpath; found.ff.in_pak = false; @@ -1046,7 +1046,7 @@ _QFS_VOpenFile (const char *filename, int zip, // make sure they're not trying to do weird stuff with our private files path = QFS_CompressPath (filename); if (qfs_contains_updir(path, 1)) { - Sys_MaskPrintf (SYS_FS, + Sys_MaskPrintf (SYS_fs, "FindFile: %s: attempt to escape directory tree!\n", path); goto error; @@ -1089,7 +1089,7 @@ _QFS_VOpenFile (const char *filename, int zip, return gzfile; } - Sys_MaskPrintf (SYS_FS_NF, "FindFile: can't find %s\n", filename); + Sys_MaskPrintf (SYS_fs_nf, "FindFile: can't find %s\n", filename); error: qfs_filesize = -1; free (path); @@ -1191,7 +1191,7 @@ qfs_load_pakfile (char *packfile) pack_t *pack = pack_open (packfile); if (pack) - Sys_MaskPrintf (SYS_FS, "Added packfile %s (%i files)\n", + Sys_MaskPrintf (SYS_fs, "Added packfile %s (%i files)\n", packfile, pack->numfiles); return pack; } @@ -1241,7 +1241,7 @@ qfs_load_gamedir (searchpath_t **searchpath, const char *dir) char **pakfiles = NULL; int i = 0, bufsize = 0, count = 0; - Sys_MaskPrintf (SYS_FS, "qfs_load_gamedir (\"%s\")\n", dir); + Sys_MaskPrintf (SYS_fs, "qfs_load_gamedir (\"%s\")\n", dir); pakfiles = calloc (1, FBLOCK_SIZE * sizeof (char *)); @@ -1347,7 +1347,7 @@ qfs_add_gamedir (vpath_t *vpath, const char *dir) Sys_Printf ("dropping bad directory %s\n", dir); break; } - Sys_MaskPrintf (SYS_FS, "qfs_add_gamedir (\"%s\")\n", + Sys_MaskPrintf (SYS_fs, "qfs_add_gamedir (\"%s\")\n", f_dir->str); qfs_add_dir (&vpath->share, f_dir->str); @@ -1357,7 +1357,7 @@ qfs_add_gamedir (vpath_t *vpath, const char *dir) } qfs_expand_userpath (f_dir, dir); - Sys_MaskPrintf (SYS_FS, "qfs_add_gamedir (\"%s\")\n", f_dir->str); + Sys_MaskPrintf (SYS_fs, "qfs_add_gamedir (\"%s\")\n", f_dir->str); qfs_add_dir (&vpath->user, f_dir->str); dstring_delete (f_dir); @@ -1589,7 +1589,7 @@ QFS_Open (const char *path, const char *mode) int write = 0; if (qfs_expand_userpath (full_path, path) == 0) { - Sys_MaskPrintf (SYS_FS, "QFS_Open: %s %s\n", full_path->str, mode); + Sys_MaskPrintf (SYS_fs, "QFS_Open: %s %s\n", full_path->str, mode); for (m = mode; *m; m++) if (*m == 'w' || *m == '+' || *m == 'a') write = 1; @@ -1625,7 +1625,7 @@ QFS_Rename (const char *old_path, const char *new_path) if ((ret = qfs_expand_userpath (full_old, old_path)) != -1) if ((ret = qfs_expand_userpath (full_new, new_path)) != -1) if ((ret = Sys_CreatePath (full_new->str)) != -1) { - Sys_MaskPrintf (SYS_FS, "QFS_Rename %s %s\n", full_old->str, + Sys_MaskPrintf (SYS_fs, "QFS_Rename %s %s\n", full_old->str, full_new->str); ret = Qrename (full_old->str, full_new->str); } diff --git a/libs/util/wad.c b/libs/util/wad.c index ffb5414d3..ed0749594 100644 --- a/libs/util/wad.c +++ b/libs/util/wad.c @@ -118,7 +118,7 @@ W_GetLumpinfo (const char *name) return lump_p; } - Sys_MaskPrintf (SYS_WARN, "W_GetLumpinfo: %s not found", name); + Sys_MaskPrintf (SYS_warn, "W_GetLumpinfo: %s not found", name); return NULL; } diff --git a/libs/util/zone.c b/libs/util/zone.c index ec1b08932..40a43fb07 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -205,7 +205,7 @@ Z_Malloc (memzone_t *zone, int size) { void *buf; - if (!developer || developer->int_val & SYS_DEV) + if (!developer || developer->int_val & SYS_dev) Z_CheckHeap (zone); // DEBUG buf = Z_TagMalloc (zone, size, 1); if (!buf) { @@ -710,7 +710,7 @@ Cache_Move (cache_system_t * c) // we are clearing up space at the bottom, so allocate it late new = Cache_TryAlloc (c->size, true); if (new) { - Sys_MaskPrintf (SYS_DEV, "cache_move ok\n"); + Sys_MaskPrintf (SYS_dev, "cache_move ok\n"); memcpy (new + 1, c + 1, c->size - sizeof (cache_system_t)); new->user = c->user; @@ -718,7 +718,7 @@ Cache_Move (cache_system_t * c) Cache_Free (c->user); new->user->data = (void *) (new + 1); } else { - Sys_MaskPrintf (SYS_DEV, "cache_move failed\n"); + Sys_MaskPrintf (SYS_dev, "cache_move failed\n"); Cache_Free (c->user); // tough luck... } @@ -975,7 +975,7 @@ Cache_Free (cache_user_t *c) if (cs->readlock) Sys_Error ("Cache_Free: attempt to free locked block"); - Sys_MaskPrintf (SYS_DEV, "Cache_Free: freeing '%.16s' %p\n", cs->name, cs); + Sys_MaskPrintf (SYS_dev, "Cache_Free: freeing '%.16s' %p\n", cs->name, cs); Cache_UnlinkLRU (cs); @@ -1038,7 +1038,7 @@ Cache_Alloc (cache_user_t *c, int size, const char *name) VISIBLE void Cache_Report (void) { - Sys_MaskPrintf (SYS_DEV, "%4.1f megabyte data cache\n", + Sys_MaskPrintf (SYS_dev, "%4.1f megabyte data cache\n", (hunk_size - hunk_high_used - hunk_low_used) / (float) (1024 * 1024)); } diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index d84e8f17e..8a3ac7853 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -116,14 +116,14 @@ Draw_InitText (void) if (vaelements < 0) { textUseVA = 0; tVAsize = 2048; - Sys_MaskPrintf (SYS_DEV, "Text: Vertex Array use disabled.\n"); + Sys_MaskPrintf (SYS_dev, "Text: Vertex Array use disabled.\n"); } else { textUseVA = 1; if (vaelements > 3) tVAsize = vaelements - (vaelements % 4); else tVAsize = 2048; - Sys_MaskPrintf (SYS_DEV, "Text: %i maximum vertex elements.\n", + Sys_MaskPrintf (SYS_dev, "Text: %i maximum vertex elements.\n", tVAsize); } diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 13afc1fe9..678e4e72c 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -160,7 +160,7 @@ gl_R_InitParticles (void) if (vaelements) { partUseVA = 0; pVAsize = r_maxparticles * 4; - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "Particles: Vertex Array use disabled.\n"); } else { if (vaelements > 3) @@ -168,7 +168,7 @@ gl_R_InitParticles (void) r_maxparticles * 4); else if (vaelements >= 0) pVAsize = r_maxparticles * 4; - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "Particles: %i maximum vertex elements.\n", pVAsize); } @@ -220,7 +220,7 @@ gl_R_ReadPointFile_f (void) return; } - Sys_MaskPrintf (SYS_DEV, "Reading %s...\n", name); + Sys_MaskPrintf (SYS_dev, "Reading %s...\n", name); c = 0; for (;;) { char buf[64]; @@ -232,7 +232,7 @@ gl_R_ReadPointFile_f (void) c++; if (numparticles >= r_maxparticles) { - Sys_MaskPrintf (SYS_DEV, "Not enough free particles\n"); + Sys_MaskPrintf (SYS_dev, "Not enough free particles\n"); break; } else { particle_new (pt_static, part_tex_dot, org, 1.5, vec3_origin, @@ -240,7 +240,7 @@ gl_R_ReadPointFile_f (void) } } Qclose (f); - Sys_MaskPrintf (SYS_DEV, "%i points read\n", c); + Sys_MaskPrintf (SYS_dev, "%i points read\n", c); } static void diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index d4b1c1f86..56543ef25 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -71,7 +71,7 @@ R_GetSpriteFrame (entity_t *currententity) frame = currententity->animation.frame; if ((frame >= psprite->numframes) || (frame < 0)) { - Sys_MaskPrintf (SYS_DEV, "R_DrawSprite: no such frame %d\n", frame); + Sys_MaskPrintf (SYS_dev, "R_DrawSprite: no such frame %d\n", frame); frame = 0; } @@ -247,7 +247,7 @@ gl_R_InitSprites (void) #else sVAsize = 4; #endif - Sys_MaskPrintf (SYS_DEV, "Sprites: %i maximum vertex elements.\n", + Sys_MaskPrintf (SYS_dev, "Sprites: %i maximum vertex elements.\n", sVAsize); if (gl_spriteVertexArray) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 8bf8ec46a..64f7b84db 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -757,15 +757,15 @@ R_InitFishEyeOnce (void) if (fisheye_init_once_completed) return 1; - Sys_MaskPrintf (SYS_DEV, "GL_ARB_texture_cube_map "); + Sys_MaskPrintf (SYS_dev, "GL_ARB_texture_cube_map "); if (QFGL_ExtensionPresent ("GL_ARB_texture_cube_map")) { qfglGetIntegerv (GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, &gl_cube_map_maxtex); - Sys_MaskPrintf (SYS_DEV, "present, max texture size %d.\n", + Sys_MaskPrintf (SYS_dev, "present, max texture size %d.\n", (int) gl_cube_map_maxtex); gl_cube_map_capable = true; } else { - Sys_MaskPrintf (SYS_DEV, "not found.\n"); + Sys_MaskPrintf (SYS_dev, "not found.\n"); gl_cube_map_capable = false; } fisheye_init_once_completed = true; diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 85de3c89e..9c420cfb0 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -235,7 +235,7 @@ gl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) if (r_speeds->int_val) { // qfglFinish (); time2 = Sys_DoubleTime (); - Sys_MaskPrintf (SYS_DEV, "%3i ms %4i wpoly %4i epoly %4i parts\n", + Sys_MaskPrintf (SYS_dev, "%3i ms %4i wpoly %4i epoly %4i parts\n", (int) ((time2 - time1) * 1000), gl_c_brush_polys, gl_c_alias_polys, numparticles); } diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index db289326b..718343f55 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -133,12 +133,12 @@ gl_R_LoadSkys (const char *skyname) targa = LoadImage (name = va (0, "env/%s%s", skyname, suf[i]), 1); if (!targa || targa->format < 3) { // FIXME Can't do PCX right now - Sys_MaskPrintf (SYS_DEV, "Couldn't load %s\n", name); + Sys_MaskPrintf (SYS_dev, "Couldn't load %s\n", name); // also look in gfx/env, where Darkplaces looks for skies targa = LoadImage (name = va (0, "gfx/env/%s%s", skyname, suf[i]), 1); if (!targa) { - Sys_MaskPrintf (SYS_DEV, "Couldn't load %s\n", name); + Sys_MaskPrintf (SYS_dev, "Couldn't load %s\n", name); gl_skyloaded = false; continue; } diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index ec21df3e5..7eccad855 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -218,7 +218,7 @@ gl_multitexture_f (cvar_t *var) qfglDisable (GL_TEXTURE_2D); } else { gl_mtex_fullbright = false; - Sys_MaskPrintf (SYS_VID, + Sys_MaskPrintf (SYS_vid, "Not enough TMUs for BSP fullbrights.\n"); } } @@ -269,7 +269,7 @@ gl_anisotropy_f (cvar_t * var) } else { gl_aniso = 1.0; if (var) - Sys_MaskPrintf (SYS_VID, + Sys_MaskPrintf (SYS_vid, "Anisotropy (GL_EXT_texture_filter_anisotropic) " "is not supported by your hardware and/or " "drivers.\n"); @@ -288,7 +288,7 @@ gl_tessellate_f (cvar_t * var) } else { gl_tess = 0; if (var) - Sys_MaskPrintf (SYS_VID, + Sys_MaskPrintf (SYS_vid, "TruForm (GL_ATI_pn_triangles) is not supported " "by your hardware and/or drivers.\n"); } @@ -432,14 +432,14 @@ CheckGLVersionString (void) } else { Sys_Error ("Malformed OpenGL version string!"); } - Sys_MaskPrintf (SYS_VID, "GL_VERSION: %s\n", gl_version); + Sys_MaskPrintf (SYS_vid, "GL_VERSION: %s\n", gl_version); gl_vendor = (char *) qfglGetString (GL_VENDOR); - Sys_MaskPrintf (SYS_VID, "GL_VENDOR: %s\n", gl_vendor); + Sys_MaskPrintf (SYS_vid, "GL_VENDOR: %s\n", gl_vendor); gl_renderer = (char *) qfglGetString (GL_RENDERER); - Sys_MaskPrintf (SYS_VID, "GL_RENDERER: %s\n", gl_renderer); + Sys_MaskPrintf (SYS_vid, "GL_RENDERER: %s\n", gl_renderer); gl_extensions = (char *) qfglGetString (GL_EXTENSIONS); - Sys_MaskPrintf (SYS_VID, "GL_EXTENSIONS: %s\n", gl_extensions); + Sys_MaskPrintf (SYS_vid, "GL_EXTENSIONS: %s\n", gl_extensions); if (strstr (gl_renderer, "Mesa DRI Mach64")) gl_feature_mach64 = true; @@ -474,15 +474,15 @@ CheckCombineExtensions (void) { if (gl_major >= 1 && gl_minor >= 3) { gl_combine_capable = true; - Sys_MaskPrintf (SYS_VID, "COMBINE active, multitextured doublebright " + Sys_MaskPrintf (SYS_vid, "COMBINE active, multitextured doublebright " "enabled.\n"); } else if (QFGL_ExtensionPresent ("GL_ARB_texture_env_combine")) { gl_combine_capable = true; - Sys_MaskPrintf (SYS_VID, "COMBINE_ARB active, multitextured " + Sys_MaskPrintf (SYS_vid, "COMBINE_ARB active, multitextured " "doublebright enabled.\n"); } else { gl_combine_capable = false; - Sys_MaskPrintf (SYS_VID, "GL_ARB_texture_env_combine not found. " + Sys_MaskPrintf (SYS_vid, "GL_ARB_texture_env_combine not found. " "gl_doublebright will have no effect with " "gl_multitexture on.\n"); } @@ -496,15 +496,15 @@ CheckCombineExtensions (void) static void CheckMultiTextureExtensions (void) { - Sys_MaskPrintf (SYS_VID, "Checking for multitexture: "); + Sys_MaskPrintf (SYS_vid, "Checking for multitexture: "); if (COM_CheckParm ("-nomtex")) { - Sys_MaskPrintf (SYS_VID, "disabled.\n"); + Sys_MaskPrintf (SYS_vid, "disabled.\n"); return; } if (gl_major >= 1 && gl_minor >= 3) { qfglGetIntegerv (GL_MAX_TEXTURE_UNITS, &gl_mtex_tmus); if (gl_mtex_tmus >= 2) { - Sys_MaskPrintf (SYS_VID, "enabled, %d TMUs.\n", gl_mtex_tmus); + Sys_MaskPrintf (SYS_vid, "enabled, %d TMUs.\n", gl_mtex_tmus); qglMultiTexCoord2f = QFGL_ExtensionAddress ("glMultiTexCoord2f"); qglMultiTexCoord2fv = @@ -514,16 +514,16 @@ CheckMultiTextureExtensions (void) if (qglMultiTexCoord2f && gl_mtex_enum) gl_mtex_capable = true; else - Sys_MaskPrintf (SYS_VID, "Multitexture disabled, could not " + Sys_MaskPrintf (SYS_vid, "Multitexture disabled, could not " "find required functions\n"); } else { - Sys_MaskPrintf (SYS_VID, + Sys_MaskPrintf (SYS_vid, "Multitexture disabled, not enough TMUs.\n"); } } else if (QFGL_ExtensionPresent ("GL_ARB_multitexture")) { qfglGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &gl_mtex_tmus); if (gl_mtex_tmus >= 2) { - Sys_MaskPrintf (SYS_VID, "enabled, %d TMUs.\n", gl_mtex_tmus); + Sys_MaskPrintf (SYS_vid, "enabled, %d TMUs.\n", gl_mtex_tmus); qglMultiTexCoord2f = QFGL_ExtensionAddress ("glMultiTexCoord2fARB"); qglMultiTexCoord2fv = @@ -533,14 +533,14 @@ CheckMultiTextureExtensions (void) if (qglMultiTexCoord2f && gl_mtex_enum) gl_mtex_capable = true; else - Sys_MaskPrintf (SYS_VID, "Multitexture disabled, could not " + Sys_MaskPrintf (SYS_vid, "Multitexture disabled, could not " "find required functions\n"); } else { - Sys_MaskPrintf (SYS_VID, + Sys_MaskPrintf (SYS_vid, "Multitexture disabled, not enough TMUs.\n"); } } else { - Sys_MaskPrintf (SYS_VID, "not found.\n"); + Sys_MaskPrintf (SYS_vid, "not found.\n"); } } @@ -582,7 +582,7 @@ CheckLights (void) specular[4] = {0.1, 0.1, 0.1, 1.0}; qfglGetIntegerv (GL_MAX_LIGHTS, &gl_max_lights); - Sys_MaskPrintf (SYS_VID, "Max GL Lights %d.\n", gl_max_lights); + Sys_MaskPrintf (SYS_vid, "Max GL Lights %d.\n", gl_max_lights); qfglEnable (GL_LIGHTING); qfglLightModelfv (GL_LIGHT_MODEL_AMBIENT, dark); @@ -619,11 +619,11 @@ Tdfx_Init8bitPalette (void) if (!(qgl3DfxSetPaletteEXT = QFGL_ExtensionAddress ("gl3DfxSetPaletteEXT"))) { - Sys_MaskPrintf (SYS_VID, "3DFX_set_global_palette not found.\n"); + Sys_MaskPrintf (SYS_vid, "3DFX_set_global_palette not found.\n"); return; } - Sys_MaskPrintf (SYS_VID, "3DFX_set_global_palette.\n"); + Sys_MaskPrintf (SYS_vid, "3DFX_set_global_palette.\n"); oldpal = (char *) d_8to24table; // d_8to24table3dfx; for (i = 0; i < 256; i++) { @@ -637,7 +637,7 @@ Tdfx_Init8bitPalette (void) qgl3DfxSetPaletteEXT ((GLuint *) table); vr_data.vid->is8bit = true; } else { - Sys_MaskPrintf (SYS_VID, "\n 3DFX_set_global_palette not found."); + Sys_MaskPrintf (SYS_vid, "\n 3DFX_set_global_palette not found."); } } @@ -662,11 +662,11 @@ Shared_Init8bitPalette (void) if (QFGL_ExtensionPresent ("GL_EXT_shared_texture_palette")) { if (!(qglColorTableEXT = QFGL_ExtensionAddress ("glColorTableEXT"))) { - Sys_MaskPrintf (SYS_VID, "glColorTableEXT not found.\n"); + Sys_MaskPrintf (SYS_vid, "glColorTableEXT not found.\n"); return; } - Sys_MaskPrintf (SYS_VID, "GL_EXT_shared_texture_palette\n"); + Sys_MaskPrintf (SYS_vid, "GL_EXT_shared_texture_palette\n"); qfglEnable (GL_SHARED_TEXTURE_PALETTE_EXT); oldPalette = (GLubyte *) d_8to24table; // d_8to24table3dfx; @@ -681,7 +681,7 @@ Shared_Init8bitPalette (void) GL_UNSIGNED_BYTE, (GLvoid *) thePalette); vr_data.vid->is8bit = true; } else { - Sys_MaskPrintf (SYS_VID, + Sys_MaskPrintf (SYS_vid, "\n GL_EXT_shared_texture_palette not found."); } } @@ -689,14 +689,14 @@ Shared_Init8bitPalette (void) static void VID_Init8bitPalette (void) { - Sys_MaskPrintf (SYS_VID, "Checking for 8-bit extension: "); + Sys_MaskPrintf (SYS_vid, "Checking for 8-bit extension: "); if (vid_use8bit->int_val) { Tdfx_Init8bitPalette (); Shared_Init8bitPalette (); if (!vr_data.vid->is8bit) - Sys_MaskPrintf (SYS_VID, "\n 8-bit extension not found.\n"); + Sys_MaskPrintf (SYS_vid, "\n 8-bit extension not found.\n"); } else { - Sys_MaskPrintf (SYS_VID, "disabled.\n"); + Sys_MaskPrintf (SYS_vid, "disabled.\n"); } } @@ -720,7 +720,7 @@ GL_SetPalette (const byte *palette) VID_Init8bitPalette (); } // 8 8 8 encoding - Sys_MaskPrintf (SYS_VID, "Converting 8to24\n"); + Sys_MaskPrintf (SYS_vid, "Converting 8to24\n"); pal = palette; table = d_8to24table; diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 22983ceef..8ea3c3675 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -188,7 +188,7 @@ set_arrays (const shaderparam_t *vert, const shaderparam_t *norm, { byte *pose_offs = (byte *) pose; - if (developer->int_val & SYS_GLSL) { + if (developer->int_val & SYS_glsl) { GLint size; qfeglGetBufferParameteriv (GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 50a4e98af..2d12d0e92 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -639,7 +639,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) } } clear_texture_chains (); - Sys_MaskPrintf (SYS_GLSL, "R_BuildDisplayLists: %ld verts total\n", + Sys_MaskPrintf (SYS_glsl, "R_BuildDisplayLists: %ld verts total\n", (long) (vertices->size / sizeof (bspvert_t))); if (!bsp_vbo) qfeglGenBuffers (1, &bsp_vbo); @@ -1446,17 +1446,17 @@ glsl_R_LoadSkys (const char *sky) for (i = 0; i < 6; i++) { tex = LoadImage (name = va (0, "env/%s%s", sky, sky_suffix[i]), 1); if (!tex || tex->format < 3) { // FIXME pcx support - Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); + Sys_MaskPrintf (SYS_glsl, "Couldn't load %s\n", name); // also look in gfx/env, where Darkplaces looks for skies tex = LoadImage (name = va (0, "gfx/env/%s%s", sky, sky_suffix[i]), 1); if (!tex || tex->format < 3) { // FIXME pcx support - Sys_MaskPrintf (SYS_GLSL, "Couldn't load %s\n", name); + Sys_MaskPrintf (SYS_glsl, "Couldn't load %s\n", name); skybox_loaded = false; continue; } } - Sys_MaskPrintf (SYS_GLSL, "Loaded %s\n", name); + Sys_MaskPrintf (SYS_glsl, "Loaded %s\n", name); qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, tex->format == 3 ? GL_RGB : GL_RGBA, tex->width, tex->height, 0, diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index de8c64602..da96477a7 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -235,7 +235,7 @@ glsl_R_InitParticles (void) qfeglEnable (GL_VERTEX_PROGRAM_POINT_SIZE); qfeglGetFloatv (GL_ALIASED_POINT_SIZE_RANGE, v); - Sys_MaskPrintf (SYS_GLSL, "point size: %g - %g\n", v[0], v[1]); + Sys_MaskPrintf (SYS_glsl, "point size: %g - %g\n", v[0], v[1]); vert_shader = GLSL_BuildShader (particle_point_vert_effects); frag_shader = GLSL_BuildShader (particle_point_frag_effects); @@ -328,7 +328,7 @@ glsl_R_ReadPointFile_f (void) return; } - Sys_MaskPrintf (SYS_DEV, "Reading %s...\n", name); + Sys_MaskPrintf (SYS_dev, "Reading %s...\n", name); c = 0; for (;;) { char buf[64]; @@ -340,7 +340,7 @@ glsl_R_ReadPointFile_f (void) c++; if (numparticles >= r_maxparticles) { - Sys_MaskPrintf (SYS_DEV, "Not enough free particles\n"); + Sys_MaskPrintf (SYS_dev, "Not enough free particles\n"); break; } else { particle_new (pt_static, part_tex_dot, org, 1.5, vec3_origin, @@ -348,7 +348,7 @@ glsl_R_ReadPointFile_f (void) } } Qclose (f); - Sys_MaskPrintf (SYS_DEV, "%i points read\n", c); + Sys_MaskPrintf (SYS_dev, "%i points read\n", c); } static void diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index 1edd77b71..6bef378f5 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -273,7 +273,7 @@ void GLSL_TextureInit (void) { qfeglGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_tex_size); - Sys_MaskPrintf (SYS_GLSL, "max texture size: %d\n", max_tex_size); + Sys_MaskPrintf (SYS_glsl, "max texture size: %d\n", max_tex_size); Cmd_AddCommand ("glsl_scraps", glsl_scraps_f, "Dump GLSL scrap stats"); } diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index 7fabdd6d2..612082480 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -78,7 +78,7 @@ GLSL_SetPalette (const byte *palette) unsigned *table; // 8 8 8 encoding - Sys_MaskPrintf (SYS_VID, "Converting 8to24\n"); + Sys_MaskPrintf (SYS_vid, "Converting 8to24\n"); table = d_8to24table; for (i = 0; i < 255; i++) { // used to be i<256, see d_8to24table below @@ -94,7 +94,7 @@ GLSL_SetPalette (const byte *palette) } d_8to24table[255] = 0; // 255 is transparent - Sys_MaskPrintf (SYS_VID, "Converting palette/colormap to RGBA textures\n"); + Sys_MaskPrintf (SYS_vid, "Converting palette/colormap to RGBA textures\n"); pal = malloc (256 * VID_GRADES * 4); for (i = 0, col = vr_data.vid->colormap8, op = pal; i < 256 * VID_GRADES; i++) { @@ -152,7 +152,7 @@ GLSL_Init_Common (void) GLSL_TextureInit (); - if (developer->int_val & SYS_GLSL) { + if (developer->int_val & SYS_glsl) { GLint max; qfeglGetIntegerv (GL_MAX_VERTEX_UNIFORM_VECTORS, &max); @@ -199,7 +199,7 @@ GLSL_CompileShader (const char *name, const shader_t *shader, int type) qfeglShaderSource (sid, shader->num_strings, shader->strings, 0); qfeglCompileShader (sid); qfeglGetShaderiv (sid, GL_COMPILE_STATUS, &compiled); - if (!compiled || (developer->int_val & SYS_GLSL)) { + if (!compiled || (developer->int_val & SYS_glsl)) { dstring_t *log = dstring_new (); int size; qfeglGetShaderiv (sid, GL_INFO_LOG_LENGTH, &size); @@ -322,7 +322,7 @@ GLSL_LinkProgram (const char *name, int vert, int frag) qfeglLinkProgram (program); qfeglGetProgramiv (program, GL_LINK_STATUS, &linked); - if (!linked || (developer->int_val & SYS_GLSL)) { + if (!linked || (developer->int_val & SYS_glsl)) { dstring_t *log = dstring_new (); int size; qfeglGetProgramiv (program, GL_INFO_LOG_LENGTH, &size); @@ -337,7 +337,7 @@ GLSL_LinkProgram (const char *name, int vert, int frag) if (!linked) return 0; } - if (developer->int_val & SYS_GLSL) + if (developer->int_val & SYS_glsl) dump_program (name, program); return program; } @@ -354,7 +354,7 @@ GLSL_ResolveShaderParam (int program, shaderparam_t *param) Sys_Printf ("could not resolve %s %s\n", param->uniform ? "uniform" : "attribute", param->name); } else { - Sys_MaskPrintf (SYS_GLSL, "Resolved %s %s @ %d\n", + Sys_MaskPrintf (SYS_glsl, "Resolved %s %s @ %d\n", param->uniform ? "uniform" : "attribute", param->name, param->location); } diff --git a/libs/video/renderer/r_alias.c b/libs/video/renderer/r_alias.c index b956f0500..dd99112d2 100644 --- a/libs/video/renderer/r_alias.c +++ b/libs/video/renderer/r_alias.c @@ -43,7 +43,7 @@ R_AliasGetSkindesc (int skinnum, aliashdr_t *ahdr) maliasskingroup_t *paliasskingroup; if ((skinnum >= ahdr->mdl.numskins) || (skinnum < 0)) { - Sys_MaskPrintf (SYS_DEV, "R_AliasSetupSkin: no such skin # %d\n", + Sys_MaskPrintf (SYS_dev, "R_AliasSetupSkin: no such skin # %d\n", skinnum); skinnum = 0; } @@ -91,7 +91,7 @@ alias_get_frame (int framenum, aliashdr_t *hdr, float *frame_interval) int i; if ((framenum >= hdr->mdl.numframes) || (framenum < 0)) { - Sys_MaskPrintf (SYS_DEV, "R_AliasSetupFrame: no such frame %d\n", + Sys_MaskPrintf (SYS_dev, "R_AliasSetupFrame: no such frame %d\n", framenum); framenum = 0; } diff --git a/libs/video/renderer/r_iqm.c b/libs/video/renderer/r_iqm.c index 71dc47b3a..4cfc53693 100644 --- a/libs/video/renderer/r_iqm.c +++ b/libs/video/renderer/r_iqm.c @@ -56,7 +56,7 @@ R_IQMGetLerpedFrames (entity_t *ent, iqm_t *iqm) if (!iqm->num_anims) return R_EntityBlend (ent, 0, 1.0 / 25.0); if (frame >= iqm->num_anims || frame < 0) { - Sys_MaskPrintf (SYS_DEV, "R_IQMGetLerpedFrames: no such frame %d\n", + Sys_MaskPrintf (SYS_dev, "R_IQMGetLerpedFrames: no such frame %d\n", frame); frame = 0; } diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index a2f01f95d..2a8f2f6c3 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -98,7 +98,7 @@ D_ClearCacheGuard (void) void D_InitCaches (void *buffer, int size) { - Sys_MaskPrintf (SYS_DEV, "D_InitCaches: %ik surface cache\n", size/1024); + Sys_MaskPrintf (SYS_dev, "D_InitCaches: %ik surface cache\n", size/1024); sc_size = size - GUARDSIZE; sc_base = (surfcache_t *) buffer; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index f6198e86c..aaf536f50 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -486,7 +486,7 @@ Draw_Pic (int x, int y, qpic_t *pic) if (x < 0 || (x + pic->width) > vid.conwidth || y < 0 || (y + pic->height) > vid.conheight) { - Sys_MaskPrintf (SYS_VID, "Draw_Pic: bad coordinates"); + Sys_MaskPrintf (SYS_vid, "Draw_Pic: bad coordinates"); Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); return; } @@ -545,7 +545,7 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, if ((x < 0) || (x + width > vid.conwidth) || (y < 0) || (y + height > vid.conheight)) { - Sys_MaskPrintf (SYS_VID, "Draw_SubPic: bad coordinates"); + Sys_MaskPrintf (SYS_vid, "Draw_SubPic: bad coordinates"); } // first, clip to screen if (x < 0) { @@ -761,7 +761,7 @@ Draw_Fill (int x, int y, int w, int h, int c) if (x < 0 || x + w > vid.conwidth || y < 0 || y + h > vid.conheight) { - Sys_MaskPrintf (SYS_VID, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", + Sys_MaskPrintf (SYS_vid, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); } CLIP (x, y, w, h, (int) vid.width, (int) vid.height); diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 1fcd1ce12..81b7c9005 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -107,7 +107,7 @@ R_AliasCheckBBox (void) frame = currententity->animation.frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { - Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->path); + Sys_MaskPrintf (SYS_dev, "No such frame %d %s\n", frame, pmodel->path); frame = 0; } @@ -547,7 +547,7 @@ R_AliasSetupSkin (void) skinnum = currententity->renderer.skinnum; if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { - Sys_MaskPrintf (SYS_DEV, "R_AliasSetupSkin: no such skin # %d\n", + Sys_MaskPrintf (SYS_dev, "R_AliasSetupSkin: no such skin # %d\n", skinnum); skinnum = 0; } diff --git a/libs/video/renderer/sw32/d_surf.c b/libs/video/renderer/sw32/d_surf.c index a001bb871..914c0b9c6 100644 --- a/libs/video/renderer/sw32/d_surf.c +++ b/libs/video/renderer/sw32/d_surf.c @@ -107,7 +107,7 @@ D_ClearCacheGuard (void) void sw32_D_InitCaches (void *buffer, int size) { - Sys_MaskPrintf (SYS_DEV, "D_InitCaches: %ik surface cache\n", size/1024); + Sys_MaskPrintf (SYS_dev, "D_InitCaches: %ik surface cache\n", size/1024); sc_size = size - GUARDSIZE; sc_base = (surfcache_t *) buffer; diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c index e8a465dfd..da11e1bb9 100644 --- a/libs/video/renderer/sw32/draw.c +++ b/libs/video/renderer/sw32/draw.c @@ -562,7 +562,7 @@ sw32_Draw_Pic (int x, int y, qpic_t *pic) if (x < 0 || (x + pic->width) > vid.conwidth || y < 0 || (y + pic->height) > vid.conheight) { - Sys_MaskPrintf (SYS_VID, "Draw_Pic: bad coordinates"); + Sys_MaskPrintf (SYS_vid, "Draw_Pic: bad coordinates"); sw32_Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); return; } @@ -661,7 +661,7 @@ sw32_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, if ((x < 0) || (x + width > vid.conwidth) || (y < 0) || (y + height > vid.conheight)) { - Sys_MaskPrintf (SYS_VID, "Draw_SubPic: bad coordinates"); + Sys_MaskPrintf (SYS_vid, "Draw_SubPic: bad coordinates"); } // first, clip to screen if (x < 0) { @@ -1176,7 +1176,7 @@ sw32_Draw_Fill (int x, int y, int w, int h, int c) if (x < 0 || x + w > vid.conwidth || y < 0 || y + h > vid.conheight) { - Sys_MaskPrintf (SYS_VID, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", + Sys_MaskPrintf (SYS_vid, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); } CLIP (x, y, w, h, (int) vid.width, (int) vid.height); diff --git a/libs/video/renderer/sw32/sw32_ralias.c b/libs/video/renderer/sw32/sw32_ralias.c index 1dacb5bc7..1f8ef1cfd 100644 --- a/libs/video/renderer/sw32/sw32_ralias.c +++ b/libs/video/renderer/sw32/sw32_ralias.c @@ -110,7 +110,7 @@ sw32_R_AliasCheckBBox (void) frame = currententity->animation.frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { - Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->path); + Sys_MaskPrintf (SYS_dev, "No such frame %d %s\n", frame, pmodel->path); frame = 0; } @@ -548,7 +548,7 @@ R_AliasSetupSkin (void) skinnum = currententity->renderer.skinnum; if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { - Sys_MaskPrintf (SYS_DEV, "R_AliasSetupSkin: no such skin # %d\n", + Sys_MaskPrintf (SYS_dev, "R_AliasSetupSkin: no such skin # %d\n", skinnum); skinnum = 0; } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 050d2affd..5abf26d61 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -619,7 +619,7 @@ vulkan_vid_render_choose_visual (void) cmdset); vulkan_ctx->cmdbuffer = cmdset->a[0]; vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1); - Sys_MaskPrintf (SYS_VULKAN, "vk choose visual %p %p %d %p\n", + Sys_MaskPrintf (SYS_vulkan, "vk choose visual %p %p %d %p\n", vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue, vulkan_ctx->device->queue.queueFamily, vulkan_ctx->cmdpool); @@ -630,7 +630,7 @@ vulkan_vid_render_create_context (void) { vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); - Sys_MaskPrintf (SYS_VULKAN, "vk create context %p\n", vulkan_ctx->surface); + Sys_MaskPrintf (SYS_vulkan, "vk create context %p\n", vulkan_ctx->surface); } static void diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c index 1fa0d8193..03d57d894 100644 --- a/libs/video/renderer/vulkan/capture.c +++ b/libs/video/renderer/vulkan/capture.c @@ -69,7 +69,7 @@ QFV_CreateCapture (qfv_device_t *device, int numframes, } if (!(format_props.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) { - Sys_MaskPrintf (SYS_VULKAN, + Sys_MaskPrintf (SYS_vulkan, "Device does not support blitting from optimal tiled " "images.\n"); canBlit = 0; @@ -78,7 +78,7 @@ QFV_CreateCapture (qfv_device_t *device, int numframes, &format_props); if (!(format_props.linearTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) { - Sys_MaskPrintf (SYS_VULKAN, + Sys_MaskPrintf (SYS_vulkan, "Device does not support blitting from optimal tiled " "images.\n"); canBlit = 0; diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 778c98273..7569e6daa 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -115,10 +115,10 @@ load_device_funcs (qfv_instance_t *inst, qfv_device_t *dev) if (!ext || dev->extension_enabled (dev, ext)) { \ dfunc->name = (PFN_##name) ifunc->vkGetDeviceProcAddr (device, #name); \ if (!dfunc->name) { \ - Sys_MaskPrintf (SYS_VULKAN_PARSE, \ + Sys_MaskPrintf (SYS_vulkan_parse, \ "Couldn't find device level function %s", #name); \ } else { \ - Sys_MaskPrintf (SYS_VULKAN_PARSE, \ + Sys_MaskPrintf (SYS_vulkan_parse, \ "Found device level function %s\n", #name); \ } \ } diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index f50ec526b..4a9141c73 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -92,7 +92,7 @@ get_instance_layers_and_extensions (vulkan_ctx_t *ctx) strset_add (instanceExtensions, extensions[i].extensionName); } - if (developer->int_val & SYS_VULKAN) { + if (developer->int_val & SYS_vulkan) { for (i = 0; i < numLayers; i++) { Sys_Printf ("%s %x %u %s\n", layers[i].layerName, @@ -306,6 +306,6 @@ QFV_GetMaxSampleCount (qfv_physdev_t *physdev) while (maxSamples && maxSamples > counts) { maxSamples >>= 1; } - Sys_MaskPrintf (SYS_VULKAN, "Max samples: %x (%d)\n", maxSamples, counts); + Sys_MaskPrintf (SYS_vulkan, "Max samples: %x (%d)\n", maxSamples, counts); return maxSamples; } diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 16939b29e..fc86b9375 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -71,7 +71,7 @@ QFV_CreateRenderPass (qfv_device_t *device, VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - if (developer->int_val & SYS_VULKAN) { + if (developer->int_val & SYS_vulkan) { Sys_Printf ("attachments: %zd\n", attachments->size); for (size_t i = 0; i < attachments->size; i++) { Sys_Printf (" attachment: %zd\n", i); diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index c10d9a286..dd28cf8c6 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -161,7 +161,7 @@ QFV_CreateShaderModule (qfv_device_t *device, const char *shader_path) } if (data) { - Sys_MaskPrintf (SYS_VULKAN, + Sys_MaskPrintf (SYS_vulkan, "QFV_CreateShaderModule: creating shader module %s\n", shader_path); VkShaderModuleCreateInfo createInfo = { @@ -171,7 +171,7 @@ QFV_CreateShaderModule (qfv_device_t *device, const char *shader_path) dfunc->vkCreateShaderModule (dev, &createInfo, 0, &shader); } else { - Sys_MaskPrintf (SYS_VULKAN, + Sys_MaskPrintf (SYS_vulkan, "QFV_CreateShaderModule: could not find shader %s\n", shader_path); } diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 762e2c799..74990f37d 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -56,7 +56,7 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) useMode = modes[i]; } } - Sys_MaskPrintf (SYS_VULKAN, "presentation mode: %d (%d)\n", useMode, + Sys_MaskPrintf (SYS_vulkan, "presentation mode: %d (%d)\n", useMode, vulkan_presentation_mode->int_val); VkSurfaceCapabilitiesKHR surfCaps; @@ -79,13 +79,13 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) } else { imageSize = surfCaps.currentExtent; } - Sys_MaskPrintf (SYS_VULKAN, "%d [%d, %d]\n", numImages, + Sys_MaskPrintf (SYS_vulkan, "%d [%d, %d]\n", numImages, imageSize.width, imageSize.height); VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; imageUsage &= surfCaps.supportedUsageFlags; - Sys_MaskPrintf (SYS_VULKAN, "%x %x\n", imageUsage, + Sys_MaskPrintf (SYS_vulkan, "%x %x\n", imageUsage, surfCaps.supportedUsageFlags); VkSurfaceTransformFlagBitsKHR surfTransform diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 1100024fd..7085ac7ea 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -159,7 +159,7 @@ parse_basic (const plfield_t *field, const plitem_t *item, ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); - //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_basic: %s %zd %d %p %p: %s\n", + //Sys_MaskPrintf (SYS_vulkan_parse, "parse_basic: %s %zd %d %p %p: %s\n", // field->name, field->offset, field->type, field->parser, // field->data, valstr); if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) { @@ -172,7 +172,7 @@ parse_basic (const plfield_t *field, const plitem_t *item, field->name, valstr); } } - //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %x\n", *(uint32_t *)data); + //Sys_MaskPrintf (SYS_vulkan_parse, " %x\n", *(uint32_t *)data); return ret; } @@ -190,14 +190,14 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); - //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_uint32_t: %s %zd %d %p %p: %s\n", + //Sys_MaskPrintf (SYS_vulkan_parse, "parse_uint32_t: %s %zd %d %p %p: %s\n", // field->name, field->offset, field->type, field->parser, // field->data, valstr); if (strcmp (valstr, "VK_SUBPASS_EXTERNAL") == 0) { //FIXME handle subpass in a separate parser? *(uint32_t *) data = VK_SUBPASS_EXTERNAL; } else { - //Sys_MaskPrintf (SYS_VULKAN_PARSE, + //Sys_MaskPrintf (SYS_vulkan_parse, // "parse_uint32_t: %s %zd %d %p %p %s\n", // field->name, field->offset, field->type, field->parser, // field->data, valstr); @@ -207,7 +207,7 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, field->name, valstr); } *(uint32_t *) data = val; - //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %d\n", *(uint32_t *)data); + //Sys_MaskPrintf (SYS_vulkan_parse, " %d\n", *(uint32_t *)data); } return ret; @@ -224,14 +224,14 @@ parse_enum (const plfield_t *field, const plitem_t *item, ectx.symtab = enm->symtab; ectx.result = &result; const char *valstr = PL_String (item); - //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_enum: %s %zd %d %p %p %s\n", + //Sys_MaskPrintf (SYS_vulkan_parse, "parse_enum: %s %zd %d %p %p %s\n", // field->name, field->offset, field->type, field->parser, // field->data, valstr); ret = !cexpr_parse_enum (enm, valstr, &ectx, data); if (!ret) { PL_Message (messages, item, "error parsing enum: %s", valstr); } - //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %d\n", *(int *)data); + //Sys_MaskPrintf (SYS_vulkan_parse, " %d\n", *(int *)data); return ret; } @@ -266,7 +266,7 @@ parse_single (const plfield_t *field, const plitem_t *item, __auto_type single = (parse_single_t *) field->data; void *flddata = (byte *)data + single->value_offset; - //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_single: %s %zd %d %p %p\n", + //Sys_MaskPrintf (SYS_vulkan_parse, "parse_single: %s %zd %d %p %p\n", // field->name, field->offset, // field->type, field->parser, field->data); @@ -307,10 +307,10 @@ parse_array (const plfield_t *field, const plitem_t *item, typedef struct arr_s DARRAY_TYPE(byte) arr_t; arr_t *arr; - //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_array: %s %zd %d %p %p %p\n", + //Sys_MaskPrintf (SYS_vulkan_parse, "parse_array: %s %zd %d %p %p %p\n", // field->name, field->offset, field->type, field->parser, // field->data, data); - //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %d %zd %p %zd %zd\n", array->type, + //Sys_MaskPrintf (SYS_vulkan_parse, " %d %zd %p %zd %zd\n", array->type, // array->stride, array->parser, array->value_offset, // array->size_offset); if (!PL_ParseArray (&f, item, &arr, messages, context)) { @@ -335,12 +335,12 @@ parse_data (const plfield_t *field, const plitem_t *item, const void *bindata = PL_BinaryData (item); size_t binsize = PL_BinarySize (item); - Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_data: %s %zd %d %p %p %p\n", + Sys_MaskPrintf (SYS_vulkan_parse, "parse_data: %s %zd %d %p %p %p\n", field->name, field->offset, field->type, field->parser, field->data, data); - Sys_MaskPrintf (SYS_VULKAN_PARSE, " %zd %zd\n", datad->value_offset, + Sys_MaskPrintf (SYS_vulkan_parse, " %zd %zd\n", datad->value_offset, datad->size_offset); - Sys_MaskPrintf (SYS_VULKAN_PARSE, " %zd %p\n", binsize, bindata); + Sys_MaskPrintf (SYS_vulkan_parse, " %zd %p\n", binsize, bindata); *value = vkparse_alloc (context, binsize); memcpy (*value, bindata, binsize); @@ -359,11 +359,11 @@ parse_string (const plfield_t *field, const plitem_t *item, const char *str = PL_String (item); - //Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_string: %s %zd %d %p %p %p\n", + //Sys_MaskPrintf (SYS_vulkan_parse, "parse_string: %s %zd %d %p %p %p\n", // field->name, field->offset, field->type, field->parser, // field->data, data); - //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %zd\n", string->value_offset); - //Sys_MaskPrintf (SYS_VULKAN_PARSE, " %s\n", str); + //Sys_MaskPrintf (SYS_vulkan_parse, " %zd\n", string->value_offset); + //Sys_MaskPrintf (SYS_vulkan_parse, " %s\n", str); size_t len = strlen (str) + 1; *value = vkparse_alloc (context, len); @@ -393,9 +393,9 @@ parse_RGBA (const plitem_t *item, void **data, ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); - Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_RGBA: %s\n", valstr); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_RGBA: %s\n", valstr); ret = !cexpr_eval_string (valstr, &ectx); - Sys_MaskPrintf (SYS_VULKAN_PARSE, " "VEC4F_FMT"\n", + Sys_MaskPrintf (SYS_vulkan_parse, " "VEC4F_FMT"\n", VEC4_EXP (*(vec4f_t *)data[0])); return ret; } @@ -430,7 +430,7 @@ parse_VkRenderPass (const plitem_t *item, void **data, vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); - Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkRenderPass: %s\n", name); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkRenderPass: %s\n", name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); } @@ -487,7 +487,7 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); - Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkDescriptorSetLayout: %s\n", + Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkDescriptorSetLayout: %s\n", name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); @@ -524,7 +524,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); - Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkPipelineLayout: %s\n", name); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkPipelineLayout: %s\n", name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); } @@ -559,7 +559,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); - Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkImage: %s\n", name); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImage: %s\n", name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); } @@ -601,7 +601,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); - Sys_MaskPrintf (SYS_VULKAN_PARSE, "parse_VkImageView: %s\n", name); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImageView: %s\n", name); if (name[0] != '$') { name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name); } @@ -986,7 +986,7 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, if (!parser (0, plist, object, messages, &parsectx)) { for (int i = 0; i < PL_A_NumObjects (messages); i++) { - Sys_MaskPrintf (SYS_VULKAN_PARSE, "%s\n", + Sys_MaskPrintf (SYS_vulkan_parse, "%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } return 0; @@ -1270,7 +1270,7 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) return 0; } } else { - Sys_MaskPrintf (SYS_VULKAN_PARSE, "Neither array nor dictionary: %d\n", + Sys_MaskPrintf (SYS_vulkan_parse, "Neither array nor dictionary: %d\n", PL_Line (item)); delete_memsuper (memsuper); return 0; @@ -1345,7 +1345,7 @@ QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) VkFramebuffer framebuffer; dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); - Sys_MaskPrintf (SYS_VULKAN_PARSE, "framebuffer, renderPass: %p, %p\n", + Sys_MaskPrintf (SYS_vulkan_parse, "framebuffer, renderPass: %p, %p\n", framebuffer, cInfo.renderPass); delete_memsuper (memsuper); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index bceea6666..2c38cd65e 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -523,7 +523,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } } clear_texture_chains (bctx); - Sys_MaskPrintf (SYS_VULKAN, + Sys_MaskPrintf (SYS_vulkan, "R_BuildDisplayLists: verts:%u, inds:%u, polys:%u (%d) %zd\n", vertex_count, index_count, poly_count, count, ((size_t) poly - (size_t) bctx->polys)/sizeof(uint32_t)); @@ -1620,7 +1620,7 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) } if (!*sky || !strcasecmp (sky, "none")) { - Sys_MaskPrintf (SYS_VULKAN, "Skybox unloaded\n"); + Sys_MaskPrintf (SYS_vulkan, "Skybox unloaded\n"); return; } @@ -1628,7 +1628,7 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) tex = LoadImage (name, 1); if (tex) { bctx->skybox_tex = Vulkan_LoadEnvMap (ctx, tex, sky); - Sys_MaskPrintf (SYS_VULKAN, "Loaded %s\n", name); + Sys_MaskPrintf (SYS_vulkan, "Loaded %s\n", name); } else { int failed = 0; tex_t *sides[6] = { }; @@ -1637,24 +1637,24 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) name = va (ctx->va_ctx, "env/%s%s", sky, sky_suffix[i]); tex = LoadImage (name, 1); if (!tex) { - Sys_MaskPrintf (SYS_VULKAN, "Couldn't load %s\n", name); + Sys_MaskPrintf (SYS_vulkan, "Couldn't load %s\n", name); // also look in gfx/env, where Darkplaces looks for skies name = va (ctx->va_ctx, "gfx/env/%s%s", sky, sky_suffix[i]); tex = LoadImage (name, 1); if (!tex) { - Sys_MaskPrintf (SYS_VULKAN, "Couldn't load %s\n", name); + Sys_MaskPrintf (SYS_vulkan, "Couldn't load %s\n", name); failed = 1; continue; } } sides[i] = tex; - Sys_MaskPrintf (SYS_VULKAN, "Loaded %s\n", name); + Sys_MaskPrintf (SYS_vulkan, "Loaded %s\n", name); } if (!failed) { bctx->skybox_tex = Vulkan_LoadEnvSides (ctx, sides, sky); } } if (bctx->skybox_tex) { - Sys_MaskPrintf (SYS_VULKAN, "Skybox %s loaded\n", sky); + Sys_MaskPrintf (SYS_vulkan, "Skybox %s loaded\n", sky); } } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 48d4cdba9..8563aafe1 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -481,7 +481,7 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) mleaf_t *leaf = Mod_PointInLeaf (&light.position[0], model); DARRAY_APPEND (&lctx->lightleafs, leaf - model->brush.leafs); - Sys_MaskPrintf (SYS_VULKAN, + Sys_MaskPrintf (SYS_vulkan, "[%g, %g, %g] %d, " "[%g %g %g] %g, [%g %g %g] %g, %zd\n", VectorExpand (light.color), light.data, @@ -502,5 +502,5 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) PL_Free (targets); PL_Free (entities); } - Sys_MaskPrintf (SYS_VULKAN, "loaded %zd lights\n", lctx->lights.size); + Sys_MaskPrintf (SYS_vulkan, "loaded %zd lights\n", lctx->lights.size); } diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index ffd36219a..66cb3da9a 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -176,23 +176,23 @@ Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx, float aspect) ortho_mat (mat->projection_2d, 0, width, 0, height, -99999, 99999); persp_mat (mat->projection_3d, 0, width, 0, height, aspect); #if 0 - Sys_MaskPrintf (SYS_VULKAN, "ortho:\n"); - Sys_MaskPrintf (SYS_VULKAN, " [[%g, %g, %g, %g],\n", + Sys_MaskPrintf (SYS_vulkan, "ortho:\n"); + Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n", QuatExpand (mat->projection_2d + 0)); - Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", QuatExpand (mat->projection_2d + 4)); - Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", QuatExpand (mat->projection_2d + 8)); - Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g]]\n", + Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g]]\n", QuatExpand (mat->projection_2d + 12)); - Sys_MaskPrintf (SYS_VULKAN, "presp:\n"); - Sys_MaskPrintf (SYS_VULKAN, " [[%g, %g, %g, %g],\n", + Sys_MaskPrintf (SYS_vulkan, "presp:\n"); + Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n", QuatExpand (mat->projection_3d + 0)); - Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", QuatExpand (mat->projection_3d + 4)); - Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g],\n", + Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", QuatExpand (mat->projection_3d + 8)); - Sys_MaskPrintf (SYS_VULKAN, " [%g, %g, %g, %g]]\n", + Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g]]\n", QuatExpand (mat->projection_3d + 12)); #endif VkMappedMemoryRange ranges[] = { diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index e18b5d689..82cb57e38 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -167,7 +167,7 @@ static const char *device_extensions[] = { void Vulkan_Init_Common (vulkan_ctx_t *ctx) { - Sys_MaskPrintf (SYS_VULKAN, "Vulkan_Init_Common\n"); + Sys_MaskPrintf (SYS_vulkan, "Vulkan_Init_Common\n"); QFV_InitParse (ctx); Vulkan_Init_Cvars (); @@ -267,7 +267,7 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) if (!item || !(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading %s\n", name); } else { - Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found %s def\n", name); + Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name); } return item; } @@ -284,7 +284,7 @@ qfv_load_renderpass (vulkan_ctx_t *ctx, const char *name) if (!item || !(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading %s\n", name); } else { - Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found %s def\n", name); + Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name); } return item; } @@ -396,7 +396,7 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading pipeline %s\n", name); return 0; } else { - Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found pipeline def %s\n", name); + Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline def %s\n", name); } VkPipeline pipeline = QFV_ParsePipeline (ctx, item, ctx->pipelineDef); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, @@ -420,7 +420,7 @@ Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading descriptor pool %s\n", name); return 0; } else { - Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found descriptor pool def %s\n", + Sys_MaskPrintf (SYS_vulkan_parse, "Found descriptor pool def %s\n", name); } pool = QFV_ParseDescriptorPool (ctx, item, ctx->pipelineDef); @@ -446,7 +446,7 @@ Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading pipeline layout %s\n", name); return 0; } else { - Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found pipeline layout def %s\n", + Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline layout def %s\n", name); } layout = QFV_ParsePipelineLayout (ctx, item, ctx->pipelineDef); @@ -472,7 +472,7 @@ Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading sampler %s\n", name); return 0; } else { - Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found sampler def %s\n", name); + Sys_MaskPrintf (SYS_vulkan_parse, "Found sampler def %s\n", name); } sampler = QFV_ParseSampler (ctx, item, ctx->pipelineDef); QFV_AddHandle (tab, path, (uint64_t) sampler); @@ -497,7 +497,7 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) Sys_Printf ("error loading descriptor set %s\n", name); return 0; } else { - Sys_MaskPrintf (SYS_VULKAN_PARSE, "Found descriptor set def %s\n", + Sys_MaskPrintf (SYS_vulkan_parse, "Found descriptor set def %s\n", name); } set = QFV_ParseDescriptorSetLayout (ctx, item, ctx->pipelineDef); diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index d2028989e..26d4303f4 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -162,7 +162,7 @@ configure_notify (XEvent *event) if (vidmode_active) X11_ForceViewPort (); #endif - Sys_MaskPrintf (SYS_VID, + Sys_MaskPrintf (SYS_vid, "ConfigureNotify: %ld %d %ld %ld %d,%d (%d,%d) " "%d %ld %d\n", c->serial, c->send_event, c->event, c->window, c->x, c->y, @@ -174,7 +174,7 @@ qboolean X11_AddEvent (int event, void (*event_handler) (XEvent *)) { if (event >= LASTEvent) { - Sys_MaskPrintf (SYS_VID, "event: %d, LASTEvent: %d\n", event, + Sys_MaskPrintf (SYS_vid, "event: %d, LASTEvent: %d\n", event, LASTEvent); return false; } @@ -440,7 +440,7 @@ X11_SetVidMode (int width, int height) &vidmodes); XF86VidModeGetModeLine (x_disp, x_screen, &dotclock, &orig_data); - Sys_MaskPrintf (SYS_VID, "VID: %d modes\n", nummodes); + Sys_MaskPrintf (SYS_vid, "VID: %d modes\n", nummodes); original_mode = -1; for (i = 0; i < nummodes; i++) { if (original_mode == -1 @@ -448,7 +448,7 @@ X11_SetVidMode (int width, int height) (vidmodes[i]->vdisplay == orig_data.vdisplay)) { original_mode = i; } - if (developer->int_val & SYS_VID) { + if (developer->int_val & SYS_vid) { Sys_Printf ("VID:%c%dx%d\n", original_mode == i ? '*' : ' ', vidmodes[i]->hdisplay, vidmodes[i]->vdisplay); @@ -470,7 +470,7 @@ X11_SetVidMode (int width, int height) } if (found_mode) { - Sys_MaskPrintf (SYS_VID, "VID: Chose video mode: %dx%d\n", + Sys_MaskPrintf (SYS_vid, "VID: Chose video mode: %dx%d\n", viddef.width, viddef.height); if (0) { diff --git a/libs/video/targets/dga_check.c b/libs/video/targets/dga_check.c index a3b023308..d17c647b1 100644 --- a/libs/video/targets/dga_check.c +++ b/libs/video/targets/dga_check.c @@ -94,11 +94,11 @@ VID_CheckDGA (Display * dpy, int *maj_ver, int *min_ver, int *hasvideo) } if ((!maj_ver) || (*maj_ver != XDGA_MAJOR_VERSION)) { - Sys_MaskPrintf (SYS_VID, "VID: Incorrect DGA version: %d.%d, \n", + Sys_MaskPrintf (SYS_vid, "VID: Incorrect DGA version: %d.%d, \n", *maj_ver, *min_ver); return false; } - Sys_MaskPrintf (SYS_VID, "VID: DGA version: %d.%d\n", *maj_ver, *min_ver); + Sys_MaskPrintf (SYS_vid, "VID: DGA version: %d.%d\n", *maj_ver, *min_ver); if (!hasvideo) hasvideo = &dummy_video; @@ -148,12 +148,12 @@ VID_CheckVMode (Display * dpy, int *maj_ver, int *min_ver) return false; if ((!maj_ver) || (*maj_ver != XF86VIDMODE_MAJOR_VERSION)) { - Sys_MaskPrintf (SYS_VID, "VID: Incorrect VidMode version: %d.%d\n", + Sys_MaskPrintf (SYS_vid, "VID: Incorrect VidMode version: %d.%d\n", *maj_ver, *min_ver); return false; } - Sys_MaskPrintf (SYS_VID, "VID: VidMode version: %d.%d\n", + Sys_MaskPrintf (SYS_vid, "VID: VidMode version: %d.%d\n", *maj_ver, *min_ver); return true; #else diff --git a/libs/video/targets/in_common.c b/libs/video/targets/in_common.c index 214666e8d..a61401ceb 100644 --- a/libs/video/targets/in_common.c +++ b/libs/video/targets/in_common.c @@ -133,7 +133,7 @@ IN_shutdown (void *data) { JOY_Shutdown (); - Sys_MaskPrintf (SYS_VID, "IN_Shutdown\n"); + Sys_MaskPrintf (SYS_vid, "IN_Shutdown\n"); IN_LL_Shutdown (); IE_Shutdown (); diff --git a/libs/video/targets/in_svgalib.c b/libs/video/targets/in_svgalib.c index a9a5f307f..159b3a9ab 100644 --- a/libs/video/targets/in_svgalib.c +++ b/libs/video/targets/in_svgalib.c @@ -112,7 +112,7 @@ keyhandler (int scancode, int state) default: break; } - //Sys_MaskPrintf (SYS_VID, "%d %02x %02lx %04x %c\n", sc, press, shifts, + //Sys_MaskPrintf (SYS_vid, "%d %02x %02lx %04x %c\n", sc, press, shifts, // key, ascii > 32 && ascii < 127 ? ascii : '#'); Key_Event (key, ascii, press); } @@ -383,14 +383,14 @@ IN_InitMouse (void) mouserate = atoi (com_argv[COM_CheckParm ("-mrate") + 1]); } #if 0 - Sys_MaskPrintf (SYS_VID, "Mouse: dev=%s,type=%s,speed=%d\n", + Sys_MaskPrintf (SYS_vid, "Mouse: dev=%s,type=%s,speed=%d\n", mousedev, mice[mtype].name, mouserate); #endif //FIXME: vga_init() opens the mouse automoatically // closing it to ensure its opened how we want it mouse_close(); if (mouse_init ((char *)mousedev, mtype, mouserate)) { - Sys_MaskPrintf (SYS_VID, + Sys_MaskPrintf (SYS_vid, "No mouse found. Check your libvga.conf mouse settings" " and that the mouse\n" "device has appropriate permission settings.\n"); @@ -404,7 +404,7 @@ IN_InitMouse (void) void IN_LL_Shutdown (void) { - Sys_MaskPrintf (SYS_VID, "IN_LL_Shutdown\n"); + Sys_MaskPrintf (SYS_vid, "IN_LL_Shutdown\n"); if (UseMouse) mouse_close (); diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index 2a79681c3..b372bc379 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -688,7 +688,7 @@ MapKey (unsigned int keycode, int press, int *k, int *u) break; } - Sys_MaskPrintf (SYS_VID, "%08x %d %02x %02lx %04x %c\n", + Sys_MaskPrintf (SYS_vid, "%08x %d %02x %02lx %04x %c\n", keycode, press, scan, shifts, key, uc > 32 && uc < 127 ? uc : '#'); *k = key; diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 83df6ebc7..a2e2a35ce 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -95,7 +95,7 @@ dga_on (void) int ret; ret = XF86DGADirectVideo (x_disp, DefaultScreen (x_disp), XF86DGADirectMouse); - Sys_MaskPrintf (SYS_VID, "XF86DGADirectVideo returned %d\n", ret); + Sys_MaskPrintf (SYS_vid, "XF86DGADirectVideo returned %d\n", ret); if (ret) dga_active = true; } @@ -109,7 +109,7 @@ dga_off (void) if (dga_avail && dga_active) { int ret; ret = XF86DGADirectVideo (x_disp, DefaultScreen (x_disp), 0); - Sys_MaskPrintf (SYS_VID, "XF86DGADirectVideo returned %d\n", ret); + Sys_MaskPrintf (SYS_vid, "XF86DGADirectVideo returned %d\n", ret); if (ret) dga_active = false; } @@ -120,10 +120,10 @@ static void in_dga_f (cvar_t *var) { if (var->int_val && input_grabbed) { - Sys_MaskPrintf (SYS_VID, "VID: in_dga_f on\n"); + Sys_MaskPrintf (SYS_vid, "VID: in_dga_f on\n"); dga_on (); } else { - Sys_MaskPrintf (SYS_VID, "VID: in_dga_f off\n"); + Sys_MaskPrintf (SYS_vid, "VID: in_dga_f off\n"); dga_off (); } } @@ -789,7 +789,7 @@ IN_LL_ProcessEvents (void) void IN_LL_Shutdown (void) { - Sys_MaskPrintf (SYS_VID, "IN_LL_Shutdown\n"); + Sys_MaskPrintf (SYS_vid, "IN_LL_Shutdown\n"); in_mouse_avail = 0; if (x_disp) { // XAutoRepeatOn (x_disp); @@ -833,7 +833,7 @@ IN_LL_Init (void) if (!COM_CheckParm ("-nomouse")) { dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); - Sys_MaskPrintf (SYS_VID, "VID_CheckDGA returned %d\n", dga_avail); + Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", dga_avail); X11_AddEvent (ButtonPress, &event_button); X11_AddEvent (ButtonRelease, &event_button); diff --git a/libs/video/targets/joy.c b/libs/video/targets/joy.c index da25db1f4..a7a55f6dd 100644 --- a/libs/video/targets/joy.c +++ b/libs/video/targets/joy.c @@ -156,7 +156,7 @@ JOY_Init (void) int i; if (JOY_Open () == -1) { - Sys_MaskPrintf (SYS_VID, "JOY: Joystick not found.\n"); + Sys_MaskPrintf (SYS_vid, "JOY: Joystick not found.\n"); joy_found = false; joy_active = false; return; @@ -165,12 +165,12 @@ JOY_Init (void) joy_found = true; if (!joy_enable->int_val) { - Sys_MaskPrintf (SYS_VID, "JOY: Joystick found, but not enabled.\n"); + Sys_MaskPrintf (SYS_vid, "JOY: Joystick found, but not enabled.\n"); joy_active = false; JOY_Close (); } - Sys_MaskPrintf (SYS_VID, "JOY: Joystick found and activated.\n"); + Sys_MaskPrintf (SYS_vid, "JOY: Joystick found and activated.\n"); // Initialize joystick if found and enabled for (i = 0; i < JOY_MAX_BUTTONS; i++) { diff --git a/libs/video/targets/joy_linux.c b/libs/video/targets/joy_linux.c index e99abc8da..c0869553d 100644 --- a/libs/video/targets/joy_linux.c +++ b/libs/video/targets/joy_linux.c @@ -96,8 +96,8 @@ JOY_Close (void) i = close (joy_handle); if (i) { - Sys_MaskPrintf (SYS_VID, "JOY: Failed to close joystick device!\n"); + Sys_MaskPrintf (SYS_vid, "JOY: Failed to close joystick device!\n"); } else { - Sys_MaskPrintf (SYS_VID, "JOY_Shutdown\n"); + Sys_MaskPrintf (SYS_vid, "JOY_Shutdown\n"); } } diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 3f7ba750e..a5acde484 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -211,7 +211,7 @@ VID_UpdateGamma (cvar_t *vid_gamma) viddef.recalc_refdef = 1; // force a surface cache flush if (vid_gamma_avail && vid_system_gamma->int_val) { // Have system, use it - Sys_MaskPrintf (SYS_VID, "Setting hardware gamma to %g\n", gamma); + Sys_MaskPrintf (SYS_vid, "Setting hardware gamma to %g\n", gamma); VID_BuildGammaTable (1.0); // hardware gamma wants a linear palette VID_SetGamma (gamma); p24 = viddef.palette; @@ -225,7 +225,7 @@ VID_UpdateGamma (cvar_t *vid_gamma) } p32[-1] = 0; // color 255 is transparent } else { // We have to hack the palette - Sys_MaskPrintf (SYS_VID, "Setting software gamma to %g\n", gamma); + Sys_MaskPrintf (SYS_vid, "Setting software gamma to %g\n", gamma); VID_BuildGammaTable (gamma); p24 = viddef.palette; p32 = viddef.palette32; diff --git a/libs/video/targets/vid_3dfxsvga.c b/libs/video/targets/vid_3dfxsvga.c index 68078703f..48f7dd389 100644 --- a/libs/video/targets/vid_3dfxsvga.c +++ b/libs/video/targets/vid_3dfxsvga.c @@ -173,20 +173,20 @@ GL_Init (void) if (!(dither_select = QFGL_ExtensionAddress ("gl3DfxSetDitherModeEXT"))) return; - Sys_MaskPrintf (SYS_VID, "Dithering: "); + Sys_MaskPrintf (SYS_vid, "Dithering: "); if ((p = COM_CheckParm ("-dither")) && p < com_argc) { if (strequal (com_argv[p+1], "2x2")) { dither_select (GR_DITHER_2x2); - Sys_MaskPrintf (SYS_VID, "2x2.\n"); + Sys_MaskPrintf (SYS_vid, "2x2.\n"); } if (strequal (com_argv[p+1], "4x4")) { dither_select (GR_DITHER_4x4); - Sys_MaskPrintf (SYS_VID, "4x4.\n"); + Sys_MaskPrintf (SYS_vid, "4x4.\n"); } } else { qfglDisable (GL_DITHER); - Sys_MaskPrintf (SYS_VID, "disabled.\n"); + Sys_MaskPrintf (SYS_vid, "disabled.\n"); } } @@ -322,7 +322,7 @@ VID_Init (byte *palette, byte *colormap) vid.initialized = true; - Sys_MaskPrintf (SYS_VID, "Video mode %dx%d initialized.\n", + Sys_MaskPrintf (SYS_vid, "Video mode %dx%d initialized.\n", vid.width, vid.height); vid.recalc_refdef = 1; // force a surface cache flush diff --git a/libs/video/targets/vid_fbdev.c b/libs/video/targets/vid_fbdev.c index a0d5702da..2f40413d1 100644 --- a/libs/video/targets/vid_fbdev.c +++ b/libs/video/targets/vid_fbdev.c @@ -212,7 +212,7 @@ static struct fb_var_screeninfo orig_var; static void VID_shutdown (void) { - Sys_MaskPrintf (SYS_VID, "VID_Shutdown\n"); + Sys_MaskPrintf (SYS_vid, "VID_Shutdown\n"); if (!fbdev_inited) return; diff --git a/libs/video/targets/vid_sdl_gl.c b/libs/video/targets/vid_sdl_gl.c index 829ca2860..9a0aa0a58 100644 --- a/libs/video/targets/vid_sdl_gl.c +++ b/libs/video/targets/vid_sdl_gl.c @@ -73,14 +73,14 @@ QFGL_ProcAddress (const char *name, qboolean crit) { void *glfunc = NULL; - Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); + Sys_MaskPrintf (SYS_vid, "DEBUG: Finding symbol %s ... ", name); glfunc = SDL_GL_GetProcAddress (name); if (glfunc) { - Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); + Sys_MaskPrintf (SYS_vid, "found [%p]\n", glfunc); return glfunc; } - Sys_MaskPrintf (SYS_VID, "not found\n"); + Sys_MaskPrintf (SYS_vid, "not found\n"); if (crit) { if (strncmp ("fxMesa", name, 6) == 0) { diff --git a/libs/video/targets/vid_svgalib.c b/libs/video/targets/vid_svgalib.c index f556ca212..592d917dc 100644 --- a/libs/video/targets/vid_svgalib.c +++ b/libs/video/targets/vid_svgalib.c @@ -242,7 +242,7 @@ get_mode (int width, int height, int depth) static void VID_shutdown (void) { - Sys_MaskPrintf (SYS_VID, "VID_Shutdown\n"); + Sys_MaskPrintf (SYS_vid, "VID_Shutdown\n"); if (!svgalib_inited) return; diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index fb4eeef96..da4b51abf 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -123,7 +123,7 @@ D_EndDirectRect (int x, int y, int width, int height) static void VID_shutdown (void *data) { - Sys_MaskPrintf (SYS_VID, "VID_shutdown\n"); + Sys_MaskPrintf (SYS_vid, "VID_shutdown\n"); Win_CloseDisplay (); } @@ -153,7 +153,7 @@ VID_Init (byte *palette, byte *colormap) VID_InitGamma (palette); viddef.vid_internal->set_palette (palette); - Sys_MaskPrintf (SYS_VID, "Video mode %dx%d initialized.\n", + Sys_MaskPrintf (SYS_vid, "Video mode %dx%d initialized.\n", viddef.width, viddef.height); viddef.initialized = true; diff --git a/libs/video/targets/vid_win_gl.c b/libs/video/targets/vid_win_gl.c index 7a194d49b..64afb042a 100644 --- a/libs/video/targets/vid_win_gl.c +++ b/libs/video/targets/vid_win_gl.c @@ -73,14 +73,14 @@ QFGL_ProcAddress (const char *name, qboolean crit) { void *glfunc = NULL; - Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); + Sys_MaskPrintf (SYS_vid, "DEBUG: Finding symbol %s ... ", name); glfunc = QFGL_GetProcAddress (libgl_handle, name); if (glfunc) { - Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); + Sys_MaskPrintf (SYS_vid, "found [%p]\n", glfunc); return glfunc; } - Sys_MaskPrintf (SYS_VID, "not found\n"); + Sys_MaskPrintf (SYS_vid, "not found\n"); if (crit) { Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index ce605cda7..dd3ec2a67 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -86,7 +86,7 @@ D_EndDirectRect (int x, int y, int width, int height) static void VID_shutdown (void *data) { - Sys_MaskPrintf (SYS_VID, "VID_shutdown\n"); + Sys_MaskPrintf (SYS_vid, "VID_shutdown\n"); X11_CloseDisplay (); } @@ -125,7 +125,7 @@ VID_Init (byte *palette, byte *colormap) VID_InitGamma (palette); viddef.vid_internal->set_palette (viddef.palette); - Sys_MaskPrintf (SYS_VID, "Video mode %dx%d initialized.\n", + Sys_MaskPrintf (SYS_vid, "Video mode %dx%d initialized.\n", viddef.width, viddef.height); viddef.initialized = true; diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index 6dca344ab..bcfbcd68c 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -108,14 +108,14 @@ QFGL_ProcAddress (const char *name, qboolean crit) { void *glfunc = NULL; - Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); + Sys_MaskPrintf (SYS_vid, "DEBUG: Finding symbol %s ... ", name); glfunc = QFGL_GetProcAddress (libgl_handle, name); if (glfunc) { - Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); + Sys_MaskPrintf (SYS_vid, "found [%p]\n", glfunc); return glfunc; } - Sys_MaskPrintf (SYS_VID, "not found\n"); + Sys_MaskPrintf (SYS_vid, "not found\n"); if (crit) { if (strncmp ("fxMesa", name, 6) == 0) { diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index a04900585..0a6384280 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -349,11 +349,11 @@ x11_choose_visual (sw_ctx_t *ctx) x_vis = x_visinfo->visual; if (num_visuals > 1) { - Sys_MaskPrintf (SYS_VID, + Sys_MaskPrintf (SYS_vid, "Found more than one visual id at depth %d:\n", template.depth); for (i = 0; i < num_visuals; i++) - Sys_MaskPrintf (SYS_VID, " -visualid %d\n", + Sys_MaskPrintf (SYS_vid, " -visualid %d\n", (int) x_visinfo[i].visualid); } else { if (num_visuals == 0) { @@ -365,20 +365,20 @@ x11_choose_visual (sw_ctx_t *ctx) } } - Sys_MaskPrintf (SYS_VID, "Using visualid %d:\n", + Sys_MaskPrintf (SYS_vid, "Using visualid %d:\n", (int) x_visinfo->visualid); - Sys_MaskPrintf (SYS_VID, " class %d\n", x_visinfo->class); - Sys_MaskPrintf (SYS_VID, " screen %d\n", x_visinfo->screen); - Sys_MaskPrintf (SYS_VID, " depth %d\n", x_visinfo->depth); - Sys_MaskPrintf (SYS_VID, " red_mask 0x%x\n", + Sys_MaskPrintf (SYS_vid, " class %d\n", x_visinfo->class); + Sys_MaskPrintf (SYS_vid, " screen %d\n", x_visinfo->screen); + Sys_MaskPrintf (SYS_vid, " depth %d\n", x_visinfo->depth); + Sys_MaskPrintf (SYS_vid, " red_mask 0x%x\n", (int) x_visinfo->red_mask); - Sys_MaskPrintf (SYS_VID, " green_mask 0x%x\n", + Sys_MaskPrintf (SYS_vid, " green_mask 0x%x\n", (int) x_visinfo->green_mask); - Sys_MaskPrintf (SYS_VID, " blue_mask 0x%x\n", + Sys_MaskPrintf (SYS_vid, " blue_mask 0x%x\n", (int) x_visinfo->blue_mask); - Sys_MaskPrintf (SYS_VID, " colormap_size %d\n", + Sys_MaskPrintf (SYS_vid, " colormap_size %d\n", x_visinfo->colormap_size); - Sys_MaskPrintf (SYS_VID, " bits_per_rgb %d\n", + Sys_MaskPrintf (SYS_vid, " bits_per_rgb %d\n", x_visinfo->bits_per_rgb); } @@ -446,7 +446,7 @@ ResetSharedFrameBuffers (void) // attach to the shared memory segment x_shminfo[frm].shmaddr = (void *) shmat (x_shminfo[frm].shmid, 0, 0); - Sys_MaskPrintf (SYS_VID, "VID: shared memory id=%d, addr=0x%lx\n", + Sys_MaskPrintf (SYS_vid, "VID: shared memory id=%d, addr=0x%lx\n", x_shminfo[frm].shmid, (long) x_shminfo[frm].shmaddr); x_framebuffer[frm]->data = x_shminfo[frm].shmaddr; diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index c1f13c4eb..d95aef4c7 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -275,7 +275,7 @@ CL_Disconnect (void) if (cls.demorecording) CL_StopRecording (); - Sys_MaskPrintf (SYS_DEV, "Sending clc_disconnect\n"); + Sys_MaskPrintf (SYS_dev, "Sending clc_disconnect\n"); SZ_Clear (&cls.message); MSG_WriteByte (&cls.message, clc_disconnect); NET_SendUnreliableMessage (cls.netcon, &cls.message); @@ -318,7 +318,7 @@ CL_EstablishConnection (const char *host) cls.netcon = NET_Connect (host); if (!cls.netcon) Host_Error ("CL_Connect: connect failed\n"); - Sys_MaskPrintf (SYS_DEV, "CL_EstablishConnection: connected to %s\n", + Sys_MaskPrintf (SYS_dev, "CL_EstablishConnection: connected to %s\n", host); cls.demonum = -1; // not in the demo loop now @@ -334,7 +334,7 @@ CL_EstablishConnection (const char *host) void CL_SignonReply (void) { - Sys_MaskPrintf (SYS_DEV, "CL_SignonReply: %i\n", cls.signon); + Sys_MaskPrintf (SYS_dev, "CL_SignonReply: %i\n", cls.signon); switch (cls.signon) { case so_none: @@ -480,7 +480,7 @@ CL_SendCmd (void) return; // no message at all if (!NET_CanSendMessage (cls.netcon)) { - Sys_MaskPrintf (SYS_DEV, "CL_WriteToServer: can't send\n"); + Sys_MaskPrintf (SYS_dev, "CL_WriteToServer: can't send\n"); return; } @@ -495,7 +495,7 @@ CL_SetState (cactive_t state) { cactive_t old_state = cls.state; cls.state = state; - Sys_MaskPrintf (SYS_NET, "CL_SetState: %d -> %d\n", old_state, state); + Sys_MaskPrintf (SYS_net, "CL_SetState: %d -> %d\n", old_state, state); if (old_state != state) { if (old_state == ca_active) { // leaving active state diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 84c185c65..f511ec70e 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -339,7 +339,7 @@ CL_ParseServerInfo (void) const char *str; int i; - Sys_MaskPrintf (SYS_DEV, "Serverinfo packet received.\n"); + Sys_MaskPrintf (SYS_dev, "Serverinfo packet received.\n"); S_BlockSound (); S_StopAllSounds (); @@ -934,16 +934,16 @@ CL_ParseServerMessage (void) str = MSG_ReadString (net_message); if (str[strlen (str) - 1] == '\n') { if (stuffbuf && stuffbuf->str[0]) { - Sys_MaskPrintf (SYS_DEV, "stufftext: %s%s\n", + Sys_MaskPrintf (SYS_dev, "stufftext: %s%s\n", stuffbuf->str, str); Cbuf_AddText (host_cbuf, stuffbuf->str); dstring_clearstr (stuffbuf); } else { - Sys_MaskPrintf (SYS_DEV, "stufftext: %s\n", str); + Sys_MaskPrintf (SYS_dev, "stufftext: %s\n", str); } Cbuf_AddText (host_cbuf, str); } else { - Sys_MaskPrintf (SYS_DEV, "partial stufftext: %s\n", str); + Sys_MaskPrintf (SYS_dev, "partial stufftext: %s\n", str); if (!stuffbuf) stuffbuf = dstring_newstr (); dstring_appendstr (stuffbuf, str); diff --git a/nq/source/host.c b/nq/source/host.c index bb4721677..ac13143e7 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -149,7 +149,7 @@ Host_EndGame (const char *message, ...) va_start (argptr, message); dvsprintf (str, message, argptr); va_end (argptr); - Sys_MaskPrintf (SYS_DEV, "Host_EndGame: %s\n", str->str); + Sys_MaskPrintf (SYS_dev, "Host_EndGame: %s\n", str->str); if (sv.active) Host_ShutdownServer (false); @@ -395,7 +395,7 @@ SV_DropClient (qboolean crash) Sys_Printf ("Client %s removed\n", host_client->name); } // break the net connection - Sys_MaskPrintf (SYS_NET, "dropping client\n"); + Sys_MaskPrintf (SYS_net, "dropping client\n"); NET_Close (host_client->netconnection); host_client->netconnection = NULL; @@ -495,7 +495,7 @@ Host_ShutdownServer (qboolean crash) void Host_ClearMemory (void) { - Sys_MaskPrintf (SYS_DEV, "Clearing memory\n"); + Sys_MaskPrintf (SYS_dev, "Clearing memory\n"); CL_ClearMemory (); Mod_ClearAll (); if (host_hunklevel) diff --git a/nq/source/sv_cl_phys.c b/nq/source/sv_cl_phys.c index 1b9517ccc..5a7cda831 100644 --- a/nq/source/sv_cl_phys.c +++ b/nq/source/sv_cl_phys.c @@ -63,7 +63,7 @@ SV_CheckStuck (edict_t *ent) VectorCopy (SVvector (ent, origin), org); VectorCopy (SVvector (ent, oldorigin), SVvector (ent, origin)); if (!SV_TestEntityPosition (ent)) { - Sys_MaskPrintf (SYS_DEV, "Unstuck.\n"); + Sys_MaskPrintf (SYS_dev, "Unstuck.\n"); SV_LinkEdict (ent, true); return; } @@ -75,14 +75,14 @@ SV_CheckStuck (edict_t *ent) SVvector (ent, origin)[1] = org[1] + j; SVvector (ent, origin)[2] = org[2] + z; if (!SV_TestEntityPosition (ent)) { - Sys_MaskPrintf (SYS_DEV, "Unstuck.\n"); + Sys_MaskPrintf (SYS_dev, "Unstuck.\n"); SV_LinkEdict (ent, true); return; } } VectorCopy (org, SVvector (ent, origin)); - Sys_MaskPrintf (SYS_DEV, "player is stuck.\n"); + Sys_MaskPrintf (SYS_dev, "player is stuck.\n"); } static qboolean @@ -205,7 +205,7 @@ SV_TryUnstick (edict_t *ent, vec3_t oldvel) if (fabs (oldorg[1] - SVvector (ent, origin)[1]) > 4 || fabs (oldorg[0] - SVvector (ent, origin)[0]) > 4) { -// Sys_MaskPrintf (SYS_DEV, "unstuck!\n"); +// Sys_MaskPrintf (SYS_dev, "unstuck!\n"); return clip; } // go back to the original pos and try again diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 93aa3fba8..1ec385919 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -310,7 +310,7 @@ SV_ConnectClient (int clientnum) client = svs.clients + clientnum; - Sys_MaskPrintf (SYS_DEV, "Client %s connected\n", + Sys_MaskPrintf (SYS_dev, "Client %s connected\n", client->netconnection->address); edictnum = clientnum + 1; @@ -1114,7 +1114,7 @@ SV_SpawnServer (const char *server) if (hostname->string[0] == 0) Cvar_Set (hostname, "UNNAMED"); - Sys_MaskPrintf (SYS_DEV, "SpawnServer: %s\n", server); + Sys_MaskPrintf (SYS_dev, "SpawnServer: %s\n", server); svs.changelevel_issued = false; // now safe to issue another svs.phys_client = SV_Physics_Client; @@ -1249,6 +1249,6 @@ SV_SpawnServer (const char *server) if (host_client->active) SV_SendServerinfo (host_client); - Sys_MaskPrintf (SYS_DEV, "Server spawned.\n"); + Sys_MaskPrintf (SYS_dev, "Server spawned.\n"); S_UnblockSound (); } diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 0489b4f4c..7bb54d429 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -779,7 +779,7 @@ do_precache (progs_t *pr, const char **cache, int max, const char *name, char *c = Hunk_Alloc (strlen (s) + 1); strcpy (c, s); cache[i] = c; // blah, const - Sys_MaskPrintf (SYS_DEV, "%s: %3d %s\n", func, i, s); + Sys_MaskPrintf (SYS_dev, "%s: %3d %s\n", func, i, s); return i; } if (!strcmp (cache[i], s)) diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 0c79f57bd..4cc567c16 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -490,7 +490,7 @@ SV_LoadProgs (void) sv_range = PR_RANGE_NONE; range = "None"; } - Sys_MaskPrintf (SYS_DEV, "Using %s builtin extention mapping\n", range); + Sys_MaskPrintf (SYS_dev, "Using %s builtin extention mapping\n", range); memset (&sv_globals, 0, sizeof (sv_funcs)); memset (&sv_funcs, 0, sizeof (sv_funcs)); diff --git a/nq/source/sv_user.c b/nq/source/sv_user.c index 95bd01ac9..0475efc0a 100644 --- a/nq/source/sv_user.c +++ b/nq/source/sv_user.c @@ -564,7 +564,7 @@ SV_ReadClientMessage (void) else if (ret == 1) Cmd_ExecuteString (s, src_client); else - Sys_MaskPrintf (SYS_DEV, "%s tried to %s\n", + Sys_MaskPrintf (SYS_dev, "%s tried to %s\n", host_client->name, s); break; diff --git a/qtv/source/client.c b/qtv/source/client.c index 43e3f424f..5e28eafa6 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -580,7 +580,7 @@ client_parse_message (client_t *cl) MSG_GetReadCount (net_message) - checksumIndex - 1, seq_hash); if (calculatedChecksum != checksum) { - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "Failed command checksum for %s(%d) " "(%d != %d)\n", Info_ValueForKey (cl->userinfo, "name"), diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index df54decd7..51789e572 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -1018,9 +1018,9 @@ CL_StartDemo (void) net_blocksend = 1; if (type == 2) { cls.demoplayback2 = true; - Sys_MaskPrintf (SYS_DEV, "mvd\n"); + Sys_MaskPrintf (SYS_dev, "mvd\n"); } else { - Sys_MaskPrintf (SYS_DEV, "qwd\n"); + Sys_MaskPrintf (SYS_dev, "qwd\n"); } CL_SetState (ca_demostart); Netchan_Setup (&cls.netchan, net_from, 0, NC_QPORT_SEND); diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 7100d2726..a47edb4af 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -169,7 +169,7 @@ FlushEntityPacket (void) entity_state_t olde, newe; int word; - Sys_MaskPrintf (SYS_DEV, "FlushEntityPacket\n"); + Sys_MaskPrintf (SYS_dev, "FlushEntityPacket\n"); memset (&olde, 0, sizeof (olde)); @@ -220,7 +220,7 @@ CL_ParsePacketEntities (qboolean delta) if (cls.demoplayback2) from = oldpacket = (cls.netchan.incoming_sequence - 1); if ((from & UPDATE_MASK) != (oldpacket & UPDATE_MASK)) - Sys_MaskPrintf (SYS_DEV, "WARNING: from mismatch\n"); + Sys_MaskPrintf (SYS_dev, "WARNING: from mismatch\n"); } else oldpacket = -1; @@ -619,11 +619,11 @@ CL_SetUpPlayerPrediction (qboolean dopred) msec = 500 * (playertime - state->state_time); if (msec <= 0 || !dopred) { VectorCopy (state->pls.es.origin, pplayer->origin); -// Sys_MaskPrintf (SYS_DEV, "nopredict\n"); +// Sys_MaskPrintf (SYS_dev, "nopredict\n"); } else { // predict players movement state->pls.cmd.msec = msec = min (msec, 255); -// Sys_MaskPrintf (SYS_DEV, "predict: %i\n", msec); +// Sys_MaskPrintf (SYS_dev, "predict: %i\n", msec); CL_PredictUsercmd (state, &exact, &state->pls.cmd, false); VectorCopy (exact.pls.es.origin, pplayer->origin); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 411cfcbc0..09ef477c4 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -411,7 +411,7 @@ CL_ClearState (void) CL_Init_Entity (&cl.viewent); - Sys_MaskPrintf (SYS_DEV, "Clearing memory\n"); + Sys_MaskPrintf (SYS_dev, "Clearing memory\n"); VID_ClearMemory (); Mod_ClearAll (); if (host_hunklevel) // FIXME: check this... @@ -595,10 +595,10 @@ CL_FullServerinfo_f (void) return; } - Sys_MaskPrintf (SYS_DEV, "Cmd_Argv (1): '%s'\n", Cmd_Argv (1)); + Sys_MaskPrintf (SYS_dev, "Cmd_Argv (1): '%s'\n", Cmd_Argv (1)); Info_Destroy (cl.serverinfo); cl.serverinfo = Info_ParseString (Cmd_Argv (1), MAX_SERVERINFO_STRING, 0); - Sys_MaskPrintf (SYS_DEV, "cl.serverinfo: '%s'\n", + Sys_MaskPrintf (SYS_dev, "cl.serverinfo: '%s'\n", Info_MakeString (cl.serverinfo, 0)); if ((p = Info_ValueForKey (cl.serverinfo, "*qf_version")) && *p) { @@ -1038,7 +1038,7 @@ CL_ReadPackets (void) // packet from server if (!cls.demoplayback && !NET_CompareAdr (net_from, cls.netchan.remote_address)) { - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "%s:sequenced packet without connection\n", NET_AdrToString (net_from)); continue; @@ -1136,7 +1136,7 @@ CL_SetState (cactive_t state) }; cactive_t old_state = cls.state; - Sys_MaskPrintf (SYS_DEV, "CL_SetState (%s)\n", state_names[state]); + Sys_MaskPrintf (SYS_dev, "CL_SetState (%s)\n", state_names[state]); cls.state = state; if (old_state != state) { if (old_state == ca_active) { diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 981871d6c..6f1aa90e4 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -478,7 +478,7 @@ CL_RequestNextDownload (void) break; case dl_none: default: - Sys_MaskPrintf (SYS_DEV, "Unknown download type.\n"); + Sys_MaskPrintf (SYS_dev, "Unknown download type.\n"); } } @@ -714,7 +714,7 @@ CL_NextUpload (void) MSG_WriteByte (&cls.netchan.message, percent); SZ_Write (&cls.netchan.message, buffer, r); - Sys_MaskPrintf (SYS_DEV, "UPLOAD: %6d: %d written\n", upload_pos - r, r); + Sys_MaskPrintf (SYS_dev, "UPLOAD: %6d: %d written\n", upload_pos - r, r); if (upload_pos != upload_size) return; @@ -736,7 +736,7 @@ CL_StartUpload (byte * data, int size) if (upload_data) free (upload_data); - Sys_MaskPrintf (SYS_DEV, "Upload starting of %d...\n", size); + Sys_MaskPrintf (SYS_dev, "Upload starting of %d...\n", size); upload_data = malloc (size); memcpy (upload_data, data, size); @@ -788,7 +788,7 @@ CL_ParseServerData (void) int protover; //FIXME qboolean cflag = false; - Sys_MaskPrintf (SYS_DEV, "Serverdata packet received.\n"); + Sys_MaskPrintf (SYS_dev, "Serverdata packet received.\n"); // wipe the client_state_t struct CL_ClearState (); @@ -1195,7 +1195,7 @@ CL_SetInfo (void) CL_ProcessUserInfo (slot, player); - Sys_MaskPrintf (SYS_DEV, "SETINFO %s: %s=%s\n", player->name->value, key, + Sys_MaskPrintf (SYS_dev, "SETINFO %s: %s=%s\n", player->name->value, key, value); } @@ -1209,7 +1209,7 @@ CL_ServerInfo (void) strncpy (value, MSG_ReadString (net_message), sizeof (value) - 1); key[sizeof (value) - 1] = 0; - Sys_MaskPrintf (SYS_DEV, "SERVERINFO: %s=%s\n", key, value); + Sys_MaskPrintf (SYS_dev, "SERVERINFO: %s=%s\n", key, value); Info_SetValueForKey (cl.serverinfo, key, value, 0); if (strequal (key, "chase")) { @@ -1411,16 +1411,16 @@ CL_ParseServerMessage (void) str = MSG_ReadString (net_message); if (str[strlen (str) - 1] == '\n') { if (stuffbuf && stuffbuf->str[0]) { - Sys_MaskPrintf (SYS_DEV, "stufftext: %s%s\n", + Sys_MaskPrintf (SYS_dev, "stufftext: %s%s\n", stuffbuf->str, str); Cbuf_AddText (cl_stbuf, stuffbuf->str); dstring_clearstr (stuffbuf); } else { - Sys_MaskPrintf (SYS_DEV, "stufftext: %s\n", str); + Sys_MaskPrintf (SYS_dev, "stufftext: %s\n", str); } Cbuf_AddText (cl_stbuf, str); } else { - Sys_MaskPrintf (SYS_DEV, "partial stufftext: %s\n", str); + Sys_MaskPrintf (SYS_dev, "partial stufftext: %s\n", str); if (!stuffbuf) stuffbuf = dstring_newstr (); dstring_appendstr (stuffbuf, str); @@ -1548,23 +1548,23 @@ CL_ParseServerMessage (void) break; case svc_intermission: - Sys_MaskPrintf (SYS_DEV, "svc_intermission\n"); + Sys_MaskPrintf (SYS_dev, "svc_intermission\n"); cl.intermission = 1; r_data->force_fullscreen = 1; cl.completed_time = realtime; r_data->vid->recalc_refdef = true; // go to full screen - Sys_MaskPrintf (SYS_DEV, "intermission simorg: "); + Sys_MaskPrintf (SYS_dev, "intermission simorg: "); MSG_ReadCoordV (net_message, &cl.viewstate.origin[0]);//FIXME cl.viewstate.origin[3] = 1; - Sys_MaskPrintf (SYS_DEV, VEC4F_FMT, + Sys_MaskPrintf (SYS_dev, VEC4F_FMT, VEC4_EXP (cl.viewstate.origin)); - Sys_MaskPrintf (SYS_DEV, "\nintermission simangles: "); + Sys_MaskPrintf (SYS_dev, "\nintermission simangles: "); MSG_ReadAngleV (net_message, cl.viewstate.angles); cl.viewstate.angles[ROLL] = 0; // FIXME @@@ - Sys_MaskPrintf (SYS_DEV, "%f %f %f", + Sys_MaskPrintf (SYS_dev, "%f %f %f", VectorExpand (cl.viewstate.angles)); - Sys_MaskPrintf (SYS_DEV, "\n"); + Sys_MaskPrintf (SYS_dev, "\n"); cl.viewstate.velocity = (vec4f_t) { }; // automatic fraglogging (by elmex) diff --git a/qw/source/crudefile.c b/qw/source/crudefile.c index a02bc81bc..4924a03ee 100644 --- a/qw/source/crudefile.c +++ b/qw/source/crudefile.c @@ -182,7 +182,7 @@ CF_CloseAllFiles () for (i = 0; i < cf_filepcount; i++) if (cf_filep[i].file) { - Sys_MaskPrintf (SYS_DEV, "Warning: closing Crude File %d left " + Sys_MaskPrintf (SYS_dev, "Warning: closing Crude File %d left " "over from last map\n", i); CF_Close (i); } diff --git a/qw/source/pmove.c b/qw/source/pmove.c index 358409bc5..07d30f0bc 100644 --- a/qw/source/pmove.c +++ b/qw/source/pmove.c @@ -724,7 +724,7 @@ NudgePosition (void) } } VectorCopy (base, pmove.origin); -// Sys_MaskPrintf (SYS_DEV, "NudgePosition: stuck\n"); +// Sys_MaskPrintf (SYS_dev, "NudgePosition: stuck\n"); } static void diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 6fbd6cbc7..b4e42c391 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -323,7 +323,7 @@ SV_SpawnServer (const char *server) struct recorder_s *recorders; QFile *ent_file; - Sys_MaskPrintf (SYS_DEV, "SpawnServer: %s\n", server); + Sys_MaskPrintf (SYS_dev, "SpawnServer: %s\n", server); SV_SaveSpawnparms (); @@ -468,7 +468,7 @@ SV_SpawnServer (const char *server) sv.signon_buffer_size[sv.num_signon_buffers - 1] = sv.signon.cursize; Info_SetValueForKey (svs.info, "map", sv.name, !sv_highchars->int_val); - Sys_MaskPrintf (SYS_DEV, "Server spawned.\n"); + Sys_MaskPrintf (SYS_dev, "Server spawned.\n"); if (sv_map_e->func) GIB_Event_Callback (sv_map_e, 1, server); } diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 039aad1fe..9a540af08 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -627,7 +627,7 @@ SVC_Log (void) return; } - Sys_MaskPrintf (SYS_DEV, "sending log %i to %s\n", svs.logsequence - 1, + Sys_MaskPrintf (SYS_dev, "sending log %i to %s\n", svs.logsequence - 1, NET_AdrToString (net_from)); // snprintf (data, sizeof (data), "stdlog %i\n", svs.logsequence - 1); @@ -1788,7 +1788,7 @@ SV_ReadPackets (void) if (cl->netchan.qport != qport) continue; if (cl->netchan.remote_address.port != net_from.port) { - Sys_MaskPrintf (SYS_DEV, "SV_ReadPackets: fixing up a " + Sys_MaskPrintf (SYS_dev, "SV_ReadPackets: fixing up a " "translated port\n"); cl->netchan.remote_address.port = net_from.port; } diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index b30664a76..965c79727 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -749,7 +749,7 @@ do_precache (progs_t *pr, const char **cache, int max, const char *name, char *c = Hunk_Alloc (strlen (s) + 1); strcpy (c, s); cache[i] = c; // blah, const - Sys_MaskPrintf (SYS_DEV, "%s: %3d %s\n", func, i, s); + Sys_MaskPrintf (SYS_dev, "%s: %3d %s\n", func, i, s); return; } if (!strcmp (cache[i], s)) diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 0081466ad..acb39f63c 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -530,7 +530,7 @@ SV_LoadProgs (void) sv_range = PR_RANGE_NONE; range = "None"; } - Sys_MaskPrintf (SYS_DEV, "Using %s builtin extention mapping\n", range); + Sys_MaskPrintf (SYS_dev, "Using %s builtin extention mapping\n", range); memset (&sv_globals, 0, sizeof (sv_funcs)); memset (&sv_funcs, 0, sizeof (sv_funcs)); diff --git a/qw/source/sv_qtv.c b/qw/source/sv_qtv.c index 366c2d687..91e310114 100644 --- a/qw/source/sv_qtv.c +++ b/qw/source/sv_qtv.c @@ -434,7 +434,7 @@ SV_qtvPacket (int qport) if (proxies[i].netchan.qport != qport) continue; if (proxies[i].netchan.remote_address.port != net_from.port) { - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "SV_ReadPackets: fixing up a translated port\n"); proxies[i].netchan.remote_address.port = net_from.port; } diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index a3760ad03..f1a8b28cb 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -333,7 +333,7 @@ SV_PreSpawn_f (void *unused) // should be three numbers following containing checksums check = atoi (Cmd_Argv (3)); -// Sys_MaskPrintf (SYS_DEV, , "Client check = %d\n", check); +// Sys_MaskPrintf (SYS_dev, , "Client check = %d\n", check); if (sv_mapcheck->int_val && check != sv.worldmodel->brush.checksum && check != sv.worldmodel->brush.checksum2) { @@ -687,7 +687,7 @@ SV_NextUpload (void) net_message->readcount, size); net_message->readcount += size; - Sys_MaskPrintf (SYS_DEV, "UPLOAD: %d received\n", size); + Sys_MaskPrintf (SYS_dev, "UPLOAD: %d received\n", size); if (percent != 100) { MSG_ReliableWrite_Begin (&host_client->backbuf, svc_stufftext, 8); @@ -1951,7 +1951,7 @@ SV_ExecuteClientMessage (client_t *cl) checksumIndex - 1, seq_hash); if (calculatedChecksum != checksum) { - Sys_MaskPrintf (SYS_DEV, + Sys_MaskPrintf (SYS_dev, "Failed command checksum for %s(%d) " "(%d != %d)\n", cl->name, cl->netchan.incoming_sequence, From dac9166339d71027a92cca682ebca5dc5faf908d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Mar 2021 22:39:43 +0900 Subject: [PATCH 1473/3664] [nq] Sort out some of the issues with keydest Switches to "game" properly when starting a new game after playing menus. Of course, basic bindings are still broken in "demo". --- include/QF/keys.h | 6 ++++++ libs/console/menu.c | 32 ++++++++++++-------------------- libs/video/targets/keys.c | 9 ++++++++- nq/source/cl_demo.c | 2 +- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/include/QF/keys.h b/include/QF/keys.h index c8fe1cbe2..f5acbcc61 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -653,6 +653,12 @@ void Key_SetBinding (imt_t *imt, knum_t keynum, const char *binding); */ void Key_SetKeyDest(keydest_t kd); +/** Get the current keydest target. + + \return The current keydest target. +*/ +keydest_t Key_GetKeyDest(void) __attribute__((pure)); + /** keydest callback signature. \param kd The new current keydest target. diff --git a/libs/console/menu.c b/libs/console/menu.c index d1a5e9c76..7c52b5b25 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -81,6 +81,7 @@ static cvar_t *confirm_quit; static progs_t menu_pr_state; static menu_item_t *menu; +static keydest_t menu_keydest; static hashtab_t *menu_hash; static func_t menu_init; static func_t menu_quit; @@ -375,11 +376,7 @@ bi_Menu_SelectMenu (progs_t *pr) } else { if (name && *name) Sys_Printf ("no menu \"%s\"\n", name); - if (con_data.force_commandline) { - Key_SetKeyDest (key_console); - } else { - Key_SetKeyDest (key_game); - } + Key_SetKeyDest (menu_keydest); } } @@ -464,11 +461,7 @@ bi_Menu_Leave (progs_t *pr) } menu = menu->parent; if (!menu) { - if (con_data.force_commandline) { - Key_SetKeyDest (key_console); - } else { - Key_SetKeyDest (key_game); - } + Key_SetKeyDest (menu_keydest); } } } @@ -792,12 +785,15 @@ Menu_Enter () Key_SetKeyDest (key_console); return; } - Key_SetKeyDest (key_menu); menu = Hash_Find (menu_hash, top_menu); - if (menu && menu->enter_hook) { - run_menu_pre (); - PR_ExecuteProgram (&menu_pr_state, menu->enter_hook); - run_menu_post (); + if (menu) { + menu_keydest = Key_GetKeyDest (); + Key_SetKeyDest (key_menu); + if (menu->enter_hook) { + run_menu_pre (); + PR_ExecuteProgram (&menu_pr_state, menu->enter_hook); + run_menu_post (); + } } } @@ -812,11 +808,7 @@ Menu_Leave () } menu = menu->parent; if (!menu) { - if (con_data.force_commandline) { - Key_SetKeyDest (key_console); - } else { - Key_SetKeyDest (key_game); - } + Key_SetKeyDest (menu_keydest); } } r_data->vid->recalc_refdef = true; diff --git a/libs/video/targets/keys.c b/libs/video/targets/keys.c index 7e844fb9e..eeaf13b83 100644 --- a/libs/video/targets/keys.c +++ b/libs/video/targets/keys.c @@ -1352,12 +1352,19 @@ VISIBLE void Key_SetKeyDest(keydest_t kd) { if ((int) kd < key_unfocused || kd >= key_last) { - Sys_Error ("Bad key_dest"); + Sys_Error ("Bad key_dest: %d", kd); } + Sys_MaskPrintf (SYS_input, "Key_SetKeyDest: %s\n", keydest_names[kd]); key_dest = kd; Key_CallDestCallbacks (key_dest); } +VISIBLE keydest_t +Key_GetKeyDest (void) +{ + return key_dest; +} + VISIBLE void Key_KeydestCallback (keydest_callback_t *callback) { diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index b15747467..0d7e91a51 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -126,6 +126,7 @@ CL_StopPlayback (void) Qclose (cls.demofile); cls.demofile = NULL; + cls.key_dest = key_game; CL_SetState (ca_disconnected); cls.demo_capture = 0; cls.demoplayback = 0; @@ -479,7 +480,6 @@ CL_StartDemo (void) CL_SetState (ca_connected); cls.forcetrack = 0; cls.key_dest = key_demo; - Key_SetKeyDest (key_demo); while ((c = Qgetc (cls.demofile)) != '\n') if (c == '-') From e93cff124ce25ea5d55229e6adb60b9922165fda Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 30 Mar 2021 17:38:42 +0900 Subject: [PATCH 1474/3664] [nq,qw] Fix strftime formats for windows The incorrectness was hidden by the non-literal strings. --- nq/source/sbar.c | 14 +++++++++++--- qw/source/sbar.c | 13 +++++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 1a0261db2..ca47f0ad4 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1101,14 +1101,22 @@ draw_time (view_t *view) utc = time (0); local = localtime (&utc); +#if defined(_WIN32) || defined(_WIN64) +# define HOUR12 "%I" +# define HOUR24 "%H" +# define PM "%p" +#else +# define HOUR12 "%l" +# define HOUR24 "%k" +# define PM "%P" +#endif if (hud_time->int_val == 1) { // Use international format - strftime (st, sizeof (st), "%k:%M", local); + strftime (st, sizeof (st), HOUR24":%M", local); draw_string (view, 8, 0, st); } else if (hud_time->int_val >= 2) { // US AM/PM display - strftime (st, sizeof (st), "%l:%M %P", local); + strftime (st, sizeof (st), HOUR12":%M "PM, local); draw_string (view, 8, 0, st); } - } static void diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 0514a9327..4476b6933 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -1563,11 +1563,20 @@ draw_time (view_t *view) utc = time (0); local = localtime (&utc); +#if defined(_WIN32) || defined(_WIN64) +# define HOUR12 "%I" +# define HOUR24 "%H" +# define PM "%p" +#else +# define HOUR12 "%l" +# define HOUR24 "%k" +# define PM "%P" +#endif if (hud_time->int_val == 1) { // Use international format - strftime (st, sizeof (st), "%k:%M", local); + strftime (st, sizeof (st), HOUR24":%M", local); draw_string (view, 8, 0, st); } else if (hud_time->int_val >= 2) { // US AM/PM display - strftime (st, sizeof (st), "%l:%M %P", local); + strftime (st, sizeof (st), HOUR12":%M "PM, local); draw_string (view, 8, 0, st); } } From ae78c81b3ad6d8422d5767c7adc916cdb0759706 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 30 Mar 2021 18:29:18 +0900 Subject: [PATCH 1475/3664] [render] Fail gracefully on unsupported render targets Ideally, this won't be the case, but it currently is for Vulkan and SDL. --- libs/video/renderer/vid_render_gl.c | 3 +++ libs/video/renderer/vid_render_glsl.c | 3 +++ libs/video/renderer/vid_render_sw.c | 3 +++ libs/video/renderer/vid_render_sw32.c | 3 +++ libs/video/renderer/vid_render_vulkan.c | 3 +++ 5 files changed, 15 insertions(+) diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 29f3eec9e..c74010b99 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -143,6 +143,9 @@ gl_vid_render_create_context (void) static void gl_vid_render_init (void) { + if (!vr_data.vid->vid_internal->sw_context) { + Sys_Error ("Sorry, OpenGL not supported by this program."); + } gl_ctx = vr_data.vid->vid_internal->gl_context (); gl_ctx->init_gl = GL_Init_Common; gl_ctx->load_gl (); diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 60ab6068a..b1e828f11 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -143,6 +143,9 @@ glsl_vid_render_create_context (void) static void glsl_vid_render_init (void) { + if (!vr_data.vid->vid_internal->sw_context) { + Sys_Error ("Sorry, OpenGL (GLSL) not supported by this program."); + } glsl_ctx = vr_data.vid->vid_internal->gl_context (); glsl_ctx->init_gl = GLSL_Init_Common; glsl_ctx->load_gl (); diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 470cd4733..27f9ae6b9 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -136,6 +136,9 @@ sw_vid_render_create_context (void) static void sw_vid_render_init (void) { + if (!vr_data.vid->vid_internal->sw_context) { + Sys_Error ("Sorry, software rendering not supported by this program."); + } sw_ctx = vr_data.vid->vid_internal->sw_context (); vr_data.vid->vid_internal->set_palette = sw_ctx->set_palette; diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index d70521f79..c63a92d88 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -141,6 +141,9 @@ sw32_vid_render_create_context (void) static void sw32_vid_render_init (void) { + if (!vr_data.vid->vid_internal->sw_context) { + Sys_Error ("Sorry, software rendering not supported by this program."); + } sw32_ctx = vr_data.vid->vid_internal->sw_context (); vr_data.vid->vid_internal->set_palette = sw32_ctx->set_palette; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 5abf26d61..78b9fbe7b 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -636,6 +636,9 @@ vulkan_vid_render_create_context (void) static void vulkan_vid_render_init (void) { + if (!vr_data.vid->vid_internal->vulkan_context) { + Sys_Error ("Sorry, Vulkan not supported by this program."); + } vulkan_ctx = vr_data.vid->vid_internal->vulkan_context (); vulkan_ctx->load_vulkan (vulkan_ctx); From 63e30e6ae029af413b6fa095949f2e33d4276ed0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 30 Mar 2021 20:09:13 +0900 Subject: [PATCH 1476/3664] [win] Fix a handful of small bugs for windows Only 64-bit windows is tested, and there are still various failures, but QF is limping along in windows again. nq-sdl works for sw, and sw32, gl and glsl are mostly black (but not entirely for gl?), vulkan is not supported with sdl. nq-win works for sw and sw32, and sort of for vulkan (very dark and upside-down?). gl and glsl complain about vid mode, qw-client-[sdl,win] seem to be the same, but something is wrong with the console (reading keyboard input). --- config.d/windows.m4 | 1 + libs/video/renderer/vulkan/instance.c | 4 ++++ libs/video/targets/context_win.c | 31 ++++++++++----------------- qw/source/cl_sys_sdl.c | 2 +- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/config.d/windows.m4 b/config.d/windows.m4 index 6ed314174..4a59a473b 100644 --- a/config.d/windows.m4 +++ b/config.d/windows.m4 @@ -12,6 +12,7 @@ case "$host_os" in CPPFLAGS="$CPPFLAGS $CFLAGS" ;; esac + SYSTYPE=WIN32 fi AC_DEFINE(NEED_GNUPRINTF) endian="little" diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index 4a9141c73..35a478108 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -166,6 +166,10 @@ setup_debug_callback (qfv_instance_t *instance) .pfnUserCallback = debug_callback, .pUserData = instance, }; + if (!instance->funcs->vkCreateDebugUtilsMessengerEXT) { + Sys_Printf ("Cound not set up Vulkan validation debug callback\n"); + return; + } instance->funcs->vkCreateDebugUtilsMessengerEXT(instance->instance, &createInfo, 0, &debug_handle); diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index d0bd49db2..85597d9dc 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -142,7 +142,9 @@ int aPage; // Current active display page int vPage; // Current visible display page int waitVRT = true; // True to wait for retrace on flip -static vmode_t badmode; +static vmode_t badmode = { + .modedesc = "Bad mode", +}; /* ============================================================================= @@ -257,10 +259,6 @@ VID_CreateDDrawDriver (int width, int height, const byte *palette, // direct draw is working now win_using_ddraw = true; - // create a palette - VID_InitGamma (palette); - viddef.vid_internal->set_palette (palette); - // create initial rects DD_UpdateRects (dd_window_width, dd_window_height); } @@ -738,7 +736,6 @@ Win_SetVidMode (int width, int height, const byte *palette) VID_SetMode (vid_default, palette); force_mode_set = false; vid_realmode = vid_modenum; - strcpy (badmode.modedesc, "Bad mode"); } static void @@ -1034,14 +1031,13 @@ VID_SetMode (int modenum, const byte *palette) SetForegroundWindow (win_mainwindow); hdc = GetDC (NULL); - - if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) + if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) { vid_palettized = true; - else + } else { vid_palettized = false; - - viddef.vid_internal->set_palette (palette); + } ReleaseDC (NULL, hdc); + vid_modenum = modenum; Cvar_SetValue (vid_mode, (float) vid_modenum); @@ -1064,8 +1060,6 @@ VID_SetMode (int modenum, const byte *palette) Sys_Printf ("%s\n", VID_GetModeDescription (vid_modenum)); - viddef.vid_internal->set_palette (palette); - in_mode_set = false; viddef.recalc_refdef = 1; @@ -1151,10 +1145,9 @@ VID_GetModeDescriptionMemCheck (int mode) // Tacks on "windowed" or "fullscreen" -static char * __attribute__((used)) +static const char * __attribute__((used)) VID_GetModeDescription2 (int mode) { - static char pinfo[40]; vmode_t *pv; if ((mode < 0) || (mode >= nummodes)) @@ -1164,14 +1157,12 @@ VID_GetModeDescription2 (int mode) pv = VID_GetModePtr (mode); if (modelist[mode].type == MS_FULLSCREEN) { - sprintf (pinfo, "%s fullscreen", pv->modedesc); + return va (0, "%s fullscreen", pv->modedesc); } else if (modelist[mode].type == MS_FULLDIB) { - sprintf (pinfo, "%s fullscreen", pv->modedesc); + return va (0, "%s fullscreen", pv->modedesc); } else { - sprintf (pinfo, "%s windowed", pv->modedesc); + return va (0, "%s windowed", pv->modedesc); } - - return pinfo; } diff --git a/qw/source/cl_sys_sdl.c b/qw/source/cl_sys_sdl.c index 0959b94cc..7894094d5 100644 --- a/qw/source/cl_sys_sdl.c +++ b/qw/source/cl_sys_sdl.c @@ -120,7 +120,7 @@ SDL_main (int argc, char *argv[]) fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | O_NONBLOCK); #else // hack to prevent gcc suggesting noreturn - if (!sys_nostdout) { + if (sys_nostdout) { return 1; } #endif From 596cd164a34287325cbade84907ddbe25217ea94 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 02:48:25 +0900 Subject: [PATCH 1477/3664] [win] Handle focus in/out events This fixes the errant console behavior (cursor wasn't showing because QF thought it had never received focus). --- config.d/windows.m4 | 2 +- libs/video/targets/in_win.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config.d/windows.m4 b/config.d/windows.m4 index 4a59a473b..e0ee907c8 100644 --- a/config.d/windows.m4 +++ b/config.d/windows.m4 @@ -12,8 +12,8 @@ case "$host_os" in CPPFLAGS="$CPPFLAGS $CFLAGS" ;; esac - SYSTYPE=WIN32 fi + SYSTYPE=WIN32 AC_DEFINE(NEED_GNUPRINTF) endian="little" ;; diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index b372bc379..a610167a1 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -776,9 +776,13 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) uMsg = WM_MOUSEWHEEL; switch (uMsg) { + case WM_SETFOCUS: + Key_FocusEvent (1); + break; case WM_KILLFOCUS: if (modestate == MS_FULLDIB) ShowWindow (win_mainwindow, SW_SHOWMINNOACTIVE); + Key_FocusEvent (0); break; case WM_CREATE: break; From 81a837da0f616350e2c6027a7fc617a51db0910c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 10:36:30 +0900 Subject: [PATCH 1478/3664] [win] Clean up a pile of messy externs --- include/context_win.h | 4 ++ include/winquake.h | 44 ++--------------- libs/audio/targets/snd_dx.c | 7 +-- libs/video/targets/context_win.c | 85 ++++---------------------------- libs/video/targets/in_win.c | 16 +++--- libs/video/targets/vid_win_sw.c | 2 +- 6 files changed, 29 insertions(+), 129 deletions(-) diff --git a/include/context_win.h b/include/context_win.h index 879ea41c1..4603a020b 100644 --- a/include/context_win.h +++ b/include/context_win.h @@ -47,6 +47,10 @@ extern RECT win_dst_rect; extern RECT win_window_rect; extern HDC win_gdi; extern struct sw_ctx_s *win_sw_context; +extern int win_minimized; + +LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +void Win_Activate (BOOL fActive, BOOL minimize); void Win_UnloadAllDrivers (void); void Win_CreateDriver (void); diff --git a/include/winquake.h b/include/winquake.h index 8786d6633..b4c15161a 100644 --- a/include/winquake.h +++ b/include/winquake.h @@ -52,6 +52,10 @@ # endif #endif +#ifdef HAVE_DDRAW_H +# include +#endif + #ifdef HAVE_MGRAPH_H # include #endif @@ -67,23 +71,11 @@ #endif extern HINSTANCE global_hInstance; -extern int global_nCmdShow; - -#ifdef HAVE_DDRAW_H -# include -extern LPDIRECTDRAW lpDD; -extern LPDIRECTDRAWSURFACE lpPrimary; -extern LPDIRECTDRAWSURFACE lpFrontBuffer; -extern LPDIRECTDRAWSURFACE lpBackBuffer; -extern LPDIRECTDRAWPALETTE lpDDPal; -#endif typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t; extern modestate_t modestate; -extern qboolean ActiveApp, Minimized; - extern qboolean WinNT; extern qboolean winsock_lib_initialized; @@ -95,34 +87,6 @@ extern RECT window_rect; extern HWND hwnd_dialog; #endif -extern HANDLE hinput, houtput; - -void S_BlockSound (void); -void S_UnblockSound (void); - -DWORD *DSOUND_LockBuffer(qboolean lockit); -void DSOUND_ClearBuffer(int clear); -void DSOUND_Restore(void); - -extern int (PASCAL FAR *pWSAStartup)(WORD wVersionRequired, LPWSADATA lpWSAData); -extern int (PASCAL FAR *pWSACleanup)(void); -extern int (PASCAL FAR *pWSAGetLastError)(void); -extern SOCKET (PASCAL FAR *psocket)(int af, int type, int protocol); -extern int (PASCAL FAR *pioctlsocket)(SOCKET s, long cmd, u_long FAR *argp); -extern int (PASCAL FAR *psetsockopt)(SOCKET s, int level, int optname, const char FAR * optval, int optlen); -extern int (PASCAL FAR *precvfrom)(SOCKET s, char FAR * buf, int len, int flags, struct sockaddr FAR *from, int FAR * fromlen); -extern int (PASCAL FAR *psendto)(SOCKET s, const char FAR * buf, int len, int flags, const struct sockaddr FAR *to, int tolen); -extern int (PASCAL FAR *pclosesocket)(SOCKET s); -extern int (PASCAL FAR *pgethostname)(char FAR * name, int namelen); -extern struct hostent FAR * (PASCAL FAR *pgethostbyname)(const char FAR * name); -extern struct hostent FAR * (PASCAL FAR *pgethostbyaddr)(const char FAR * addr, int len, int type); -extern int (PASCAL FAR *pgetsockname)(SOCKET s, struct sockaddr FAR *name, int FAR * namelen); - -HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); -LONG CDAudio_MessageHandler (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -void AppActivate (BOOL fActive, BOOL minimize); - #undef E_POINTER #endif /* _WIN32 */ diff --git a/libs/audio/targets/snd_dx.c b/libs/audio/targets/snd_dx.c index 27618487e..0cbb18275 100644 --- a/libs/audio/targets/snd_dx.c +++ b/libs/audio/targets/snd_dx.c @@ -96,6 +96,7 @@ static general_funcs_t plugin_info_general_funcs; static snd_output_data_t plugin_info_snd_output_data; static snd_output_funcs_t plugin_info_snd_output_funcs; +static DWORD *DSOUND_LockBuffer (qboolean lockit); static void SNDDMA_Init_Cvars (void) @@ -424,7 +425,7 @@ SNDDMA_shutdown (void) FreeSound (); } -DWORD * +static DWORD * DSOUND_LockBuffer (qboolean lockit) { int reps; @@ -469,7 +470,7 @@ DSOUND_LockBuffer (qboolean lockit) return (pbuf1); } -void +static void __attribute__((used)) //FIXME make it true DSOUND_ClearBuffer (int clear) { DWORD *pData; @@ -480,7 +481,7 @@ DSOUND_ClearBuffer (int clear) DSOUND_LockBuffer (false); } -void +static void __attribute__((used)) //FIXME make it true DSOUND_Restore (void) { // if the buffer was lost or stopped, restore it and/or restart it diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index 85597d9dc..645c6f404 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -49,6 +49,7 @@ HDC win_maindc; HDC win_dib_section; int win_using_ddraw; int win_palettized; +int win_minimized; LPDIRECTDRAWSURFACE win_dd_frontbuffer; LPDIRECTDRAWSURFACE win_dd_backbuffer; RECT win_src_rect; @@ -56,7 +57,6 @@ RECT win_dst_rect; RECT win_window_rect; HDC win_gdi; int win_canalttab = 0; -int win_palettized; sw_ctx_t *win_sw_context; #define MODE_WINDOWED 0 @@ -92,20 +92,15 @@ static cvar_t *vid_window_y; #define MAX_MODE_LIST 36 #define VID_ROW_SIZE 3 -extern qboolean Minimized; +static int DIBWidth, DIBHeight; +static RECT WindowRect; +static DWORD WindowStyle, ExWindowStyle; -HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); - -int DIBWidth, DIBHeight; -RECT WindowRect; -DWORD WindowStyle, ExWindowStyle; - -int window_center_x, window_center_y, window_width, window_height; -RECT window_rect; +int window_center_x, window_center_y, window_width, window_height; +RECT window_rect; DEVMODE win_gdevmode; static qboolean startwindowed = 0, windowed_mode_set; -static qboolean vid_palettized; static int vid_fulldib_on_focus_mode; static qboolean force_minimized, in_mode_set, force_mode_set; static qboolean vid_mode_set; @@ -427,25 +422,8 @@ Win_UnloadAllDrivers (void) win_using_ddraw = false; } - - -// compatibility -qboolean DDActive; - -void VID_MenuDraw (void); -void VID_MenuKey (int key); - -LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -void AppActivate (BOOL fActive, BOOL minimize); - static int VID_SetMode (int modenum, const byte *palette); - -/* -================ -VID_RememberWindowPos -================ -*/ static void __attribute__ ((used)) VID_RememberWindowPos (void) { @@ -462,11 +440,6 @@ VID_RememberWindowPos (void) } -/* -================ -VID_CheckWindowXY -================ -*/ static void VID_CheckWindowXY (void) { @@ -479,11 +452,6 @@ VID_CheckWindowXY (void) } -/* -================ -VID_UpdateWindowStatus -================ -*/ void Win_UpdateWindowStatus (int window_x, int window_y) { @@ -497,11 +465,6 @@ Win_UpdateWindowStatus (int window_x, int window_y) } -/* -================ -ClearAllStates -================ -*/ static void ClearAllStates (void) { @@ -517,11 +480,6 @@ ClearAllStates (void) } -/* -================ -VID_CheckAdequateMem -================ -*/ static qboolean VID_CheckAdequateMem (int width, int height) { @@ -598,11 +556,6 @@ VID_InitModes (HINSTANCE hInstance) } -/* -================= -VID_GetDisplayModes -================= -*/ static void VID_GetDisplayModes (void) { @@ -716,7 +669,7 @@ Win_CloseDisplay (void) PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM) win_mainwindow, (LPARAM) 0); PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM) 0, (LPARAM) 0); - AppActivate (false, false); + Win_Activate (false, false); //FIXME? if (hwnd_dialog) DestroyWindow (hwnd_dialog); if (win_mainwindow) @@ -1032,9 +985,9 @@ VID_SetMode (int modenum, const byte *palette) hdc = GetDC (NULL); if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) { - vid_palettized = true; + win_palettized = true; } else { - vid_palettized = false; + win_palettized = false; } ReleaseDC (NULL, hdc); @@ -1323,26 +1276,6 @@ Win_SetGamma (double gamma) return i; } -#if 0 -static void -VID_SaveGamma (void) -{ - HDC hdc = GetDC (NULL); - - GetDeviceGammaRamp (hdc, &systemgammaramps[0][0]); - ReleaseDC (NULL, hdc); -} - -static void -VID_RestoreGamma (void) -{ - HDC hdc = GetDC (NULL); - - SetDeviceGammaRamp (hdc, &systemgammaramps[0][0]); - ReleaseDC (NULL, hdc); -} -#endif - #define CVAR_ORIGINAL CVAR_NONE // FIXME void Win_Init_Cvars (void) diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index a610167a1..641788f02 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -43,6 +43,7 @@ #include "QF/keys.h" #include "QF/qargs.h" #include "QF/screen.h" +#include "QF/sound.h" #include "QF/sys.h" #include "compat.h" @@ -700,30 +701,27 @@ MapKey (unsigned int keycode, int press, int *k, int *u) */ /* - AppActivate - fActive - True if app is activating If the application is activating, then swap the system into SYSPAL_NOSTATIC mode so that our palettes will display correctly. */ void -AppActivate (BOOL fActive, BOOL minimize) +Win_Activate (BOOL active, BOOL minimize) { static BOOL sound_active; - ActiveApp = fActive; - Minimized = minimize; + win_minimized = minimize; // enable/disable sound on focus gain/loss - if (!ActiveApp && sound_active) { + if (!active && sound_active) { S_BlockSound (); sound_active = false; - } else if (ActiveApp && !sound_active) { + } else if (active && !sound_active) { S_UnblockSound (); sound_active = true; } - if (fActive) { + if (active) { if (modestate == MS_FULLDIB) { IN_ActivateMouse (); IN_HideMouse (); @@ -858,7 +856,7 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_ACTIVATE: fActive = LOWORD (wParam); fMinimized = (BOOL) HIWORD (wParam); - AppActivate (!(fActive == WA_INACTIVE), fMinimized); + Win_Activate (!(fActive == WA_INACTIVE), fMinimized); // fix leftover Alt from any Alt-Tab or the like that switched us // away IN_ClearStates (); diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index a869f273d..c0926fa6e 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -76,7 +76,7 @@ win_set_palette (const byte *palette) st2d_8to32table[i].bgra[2] = viddef.gammatable[pal[0]]; st2d_8to32table[i].bgra[3] = 255; } - if (!Minimized && !win_using_ddraw && win_dib_section) { + if (!win_minimized && !win_using_ddraw && win_dib_section) { RGBQUAD colors[256]; memcpy (colors, st2d_8to32table, sizeof (colors)); for (int i = 0; i < 256; i++) { From 8ec781a43400e46cfd843d2cb2b7f77238c2f775 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 13:05:50 +0900 Subject: [PATCH 1479/3664] [vid] Fix some naming inconsistencies --- include/vid_internal.h | 2 +- libs/video/targets/vid.c | 4 ++-- libs/video/targets/vid_sdl_sw.c | 4 ++-- libs/video/targets/vid_win_sw.c | 2 +- libs/video/targets/vid_x11_sw.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/vid_internal.h b/include/vid_internal.h index 61ad44fe7..c54f11492 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -8,7 +8,7 @@ typedef struct vid_internal_s { int (*surf_cache_size) (int width, int height); void (*flush_caches) (void); void (*init_caches) (void *cache, int size); - void (*do_screen_buffer) (void); + void (*init_buffers) (void); void (*set_palette) (const byte *palette); void (*choose_visual) (void); diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index a5acde484..71f7977ef 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -296,8 +296,8 @@ VID_InitBuffers (void) free (viddef.surfcache); viddef.surfcache = NULL; } - if (viddef.vid_internal->do_screen_buffer) { - viddef.vid_internal->do_screen_buffer (); + if (viddef.vid_internal->init_buffers) { + viddef.vid_internal->init_buffers (); } else { // Free the old screen buffer if (viddef.buffer) { diff --git a/libs/video/targets/vid_sdl_sw.c b/libs/video/targets/vid_sdl_sw.c index 5a9a96b42..5d5dcfb0d 100644 --- a/libs/video/targets/vid_sdl_sw.c +++ b/libs/video/targets/vid_sdl_sw.c @@ -103,7 +103,7 @@ sdl_set_palette (const byte *palette) } static void -do_screen_buffer (void) +sdl_init_buffers (void) { } @@ -118,7 +118,7 @@ sdl_set_vid_mode (sw_ctx_t *ctx) // now know everything we need to know about the buffer VGA_width = viddef.width; VGA_height = viddef.height; - viddef.vid_internal->do_screen_buffer = do_screen_buffer; + viddef.vid_internal->init_buffers = sdl_init_buffers; VGA_pagebase = viddef.buffer = sdl_screen->pixels; VGA_rowbytes = viddef.rowbytes = sdl_screen->pitch; viddef.conbuffer = viddef.buffer; diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index c0926fa6e..567b5d0c7 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -213,7 +213,7 @@ win_create_context (sw_ctx_t *ctx) Win_CreateDriver (); - viddef.vid_internal->do_screen_buffer = win_init_bufers; + viddef.vid_internal->init_buffers = win_init_bufers; VID_InitBuffers (); } diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 0a6384280..df672ef58 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -518,7 +518,7 @@ x11_create_context (sw_ctx_t *ctx) x_shmeventtype = XShmGetEventBase (x_disp) + ShmCompletion; } - viddef.vid_internal->do_screen_buffer = x11_init_buffers; + viddef.vid_internal->init_buffers = x11_init_buffers; VID_InitBuffers (); // XSynchronize (x_disp, False); From 3eb28000de969b7c915b7b64b0b1aa373789a56e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 13:32:17 +0900 Subject: [PATCH 1480/3664] [vid] Clean up windows video code a bit It turns out the dd and dib "driver" code is very specific to the software renderer. This does not fix the segfault on changing video mode, but I do know where the problem lies: the window is being destroyed and recreated without recreating the buffers. I suspect a clean solution to this will allow for window resizing in X as well. --- include/context_win.h | 12 +- include/winquake.h | 3 - libs/video/targets/context_win.c | 359 +++---------------------------- libs/video/targets/in_win.c | 12 +- libs/video/targets/vid_win_sw.c | 306 +++++++++++++++++++++++--- 5 files changed, 325 insertions(+), 367 deletions(-) diff --git a/include/context_win.h b/include/context_win.h index 4603a020b..cf4010f43 100644 --- a/include/context_win.h +++ b/include/context_win.h @@ -35,25 +35,19 @@ extern HWND win_mainwindow; extern HDC win_maindc; -extern HDC win_dib_section; -extern int win_using_ddraw; extern int win_palettized; extern int win_canalttab; extern DEVMODE win_gdevmode; -extern LPDIRECTDRAWSURFACE win_dd_frontbuffer; -extern LPDIRECTDRAWSURFACE win_dd_backbuffer; -extern RECT win_src_rect; -extern RECT win_dst_rect; -extern RECT win_window_rect; -extern HDC win_gdi; extern struct sw_ctx_s *win_sw_context; extern int win_minimized; +extern struct cvar_s *vid_ddraw; +extern int win_center_x, win_center_y; +extern RECT win_rect; LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void Win_Activate (BOOL fActive, BOOL minimize); void Win_UnloadAllDrivers (void); -void Win_CreateDriver (void); void Win_OpenDisplay (void); void Win_CloseDisplay (void); void Win_SetVidMode (int width, int height, const byte *palette); diff --git a/include/winquake.h b/include/winquake.h index b4c15161a..13c717363 100644 --- a/include/winquake.h +++ b/include/winquake.h @@ -80,9 +80,6 @@ extern qboolean WinNT; extern qboolean winsock_lib_initialized; -extern int window_center_x, window_center_y; -extern RECT window_rect; - #ifdef SPLASH_SCREEN extern HWND hwnd_dialog; #endif diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index 645c6f404..a2694c2e1 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -46,16 +46,8 @@ HWND win_mainwindow; HDC win_maindc; -HDC win_dib_section; -int win_using_ddraw; int win_palettized; int win_minimized; -LPDIRECTDRAWSURFACE win_dd_frontbuffer; -LPDIRECTDRAWSURFACE win_dd_backbuffer; -RECT win_src_rect; -RECT win_dst_rect; -RECT win_window_rect; -HDC win_gdi; int win_canalttab = 0; sw_ctx_t *win_sw_context; @@ -64,7 +56,7 @@ sw_ctx_t *win_sw_context; #define NO_MODE (MODE_WINDOWED - 1) #define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) -static cvar_t *vid_ddraw; +cvar_t *vid_ddraw; // Note that 0 is MODE_WINDOWED static cvar_t *vid_mode; @@ -96,8 +88,8 @@ static int DIBWidth, DIBHeight; static RECT WindowRect; static DWORD WindowStyle, ExWindowStyle; -int window_center_x, window_center_y, window_width, window_height; -RECT window_rect; +int win_center_x, win_center_y; +RECT win_rect; DEVMODE win_gdevmode; static qboolean startwindowed = 0, windowed_mode_set; @@ -130,7 +122,32 @@ typedef struct { char modedesc[13]; } vmode_t; -static vmode_t modelist[MAX_MODE_LIST]; +static vmode_t modelist[MAX_MODE_LIST] = { + { + .type = MS_WINDOWED, + .width = 320, + .height = 240, + .modedesc = "320x240", + .modenum = MODE_WINDOWED, + .fullscreen = 0, + }, + { + .type = MS_WINDOWED, + .width = 640, + .height = 480, + .modedesc = "640x480", + .modenum = MODE_WINDOWED + 1, + .fullscreen = 0, + }, + { + .type = MS_WINDOWED, + .width = 800, + .height = 600, + .modedesc = "800x600", + .modenum = MODE_WINDOWED + 2, + .fullscreen = 0, + } +}; static int nummodes; int aPage; // Current active display page @@ -141,287 +158,6 @@ static vmode_t badmode = { .modedesc = "Bad mode", }; -/* -============================================================================= - - DIRECTDRAW VIDEO DRIVER - -============================================================================= -*/ - -LPDIRECTDRAW dd_Object = NULL; -HINSTANCE hInstDDraw = NULL; - -LPDIRECTDRAWCLIPPER dd_Clipper = NULL; - -typedef HRESULT (WINAPI *ddCreateProc_t) (GUID FAR *, - LPDIRECTDRAW FAR *, - IUnknown FAR *); -ddCreateProc_t ddCreate = NULL; - -unsigned ddpal[256]; - -byte *vidbuf = NULL; - - -int dd_window_width = 640; -int dd_window_height = 480; - -static void -DD_UpdateRects (int width, int height) -{ - POINT p = { .x = 0, .y = 0 }; - // first we need to figure out where on the primary surface our window - // lives - ClientToScreen (win_mainwindow, &p); - GetClientRect (win_mainwindow, &win_dst_rect); - OffsetRect (&win_dst_rect, p.x, p.y); - SetRect (&win_src_rect, 0, 0, width, height); -} - - -static void -VID_CreateDDrawDriver (int width, int height, const byte *palette, - void **buffer, int *rowbytes) -{ - DDSURFACEDESC ddsd; - - win_using_ddraw = false; - dd_window_width = width; - dd_window_height = height; - - vidbuf = (byte *) malloc (width * height); - buffer[0] = vidbuf; - rowbytes[0] = width; - - if (!(hInstDDraw = LoadLibrary ("ddraw.dll"))) { - return; - } - if (!(ddCreate = (ddCreateProc_t) GetProcAddress (hInstDDraw, - "DirectDrawCreate"))) { - return; - } - - if (FAILED (ddCreate (NULL, &dd_Object, NULL))) { - return; - } - if (FAILED (dd_Object->lpVtbl->SetCooperativeLevel (dd_Object, - win_mainwindow, - DDSCL_NORMAL))) { - return; - } - - // the primary surface in windowed mode is the full screen - memset (&ddsd, 0, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY; - - // ...and create it - if (FAILED (dd_Object->lpVtbl->CreateSurface (dd_Object, &ddsd, - &win_dd_frontbuffer, NULL))) { - return; - } - - // not using a clipper will slow things down and switch aero off - if (FAILED (IDirectDraw_CreateClipper (dd_Object, 0, &dd_Clipper, NULL))) { - return; - } - if (FAILED (IDirectDrawClipper_SetHWnd (dd_Clipper, 0, win_mainwindow))) { - return; - } - if (FAILED (IDirectDrawSurface_SetClipper (win_dd_frontbuffer, - dd_Clipper))) { - return; - } - - // the secondary surface is an offscreen surface that is the currect - // dimensions - // this will be blitted to the correct location on the primary surface - // (which is the full screen) during our draw op - memset (&ddsd, 0, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; - ddsd.dwWidth = width; - ddsd.dwHeight = height; - - if (FAILED (IDirectDraw_CreateSurface (dd_Object, &ddsd, - &win_dd_backbuffer, NULL))) { - return; - } - - // direct draw is working now - win_using_ddraw = true; - - // create initial rects - DD_UpdateRects (dd_window_width, dd_window_height); -} - - -/* -===================================================================== - - GDI VIDEO DRIVER - -===================================================================== -*/ - -// common bitmap definition -typedef struct dibinfo { - BITMAPINFOHEADER header; - RGBQUAD acolors[256]; -} dibinfo_t; - - -static HGDIOBJ previously_selected_GDI_obj = NULL; -HBITMAP hDIBSection; -byte *pDIBBase = NULL; -HDC hdcDIBSection = NULL; -HDC hdcGDI = NULL; - - -static void -VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer, - int *rowbytes) -{ - dibinfo_t dibheader; - BITMAPINFO *pbmiDIB = (BITMAPINFO *) & dibheader; - int i; - - hdcGDI = GetDC (win_mainwindow); - memset (&dibheader, 0, sizeof (dibheader)); - - // fill in the bitmap info - pbmiDIB->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); - pbmiDIB->bmiHeader.biWidth = width; - pbmiDIB->bmiHeader.biHeight = height; - pbmiDIB->bmiHeader.biPlanes = 1; - pbmiDIB->bmiHeader.biCompression = BI_RGB; - pbmiDIB->bmiHeader.biSizeImage = 0; - pbmiDIB->bmiHeader.biXPelsPerMeter = 0; - pbmiDIB->bmiHeader.biYPelsPerMeter = 0; - pbmiDIB->bmiHeader.biClrUsed = 256; - pbmiDIB->bmiHeader.biClrImportant = 256; - pbmiDIB->bmiHeader.biBitCount = 8; - - // fill in the palette - for (i = 0; i < 256; i++) { - // d_8to24table isn't filled in yet so this is just for testing - dibheader.acolors[i].rgbRed = palette[i * 3]; - dibheader.acolors[i].rgbGreen = palette[i * 3 + 1]; - dibheader.acolors[i].rgbBlue = palette[i * 3 + 2]; - } - - // create the DIB section - hDIBSection = CreateDIBSection (hdcGDI, - pbmiDIB, - DIB_RGB_COLORS, - (void **) &pDIBBase, NULL, 0); - - // set video buffers - if (pbmiDIB->bmiHeader.biHeight > 0) { - // bottom up - buffer[0] = pDIBBase + (height - 1) * width; - rowbytes[0] = -width; - } else { - // top down - buffer[0] = pDIBBase; - rowbytes[0] = width; - } - - // clear the buffer - memset (pDIBBase, 0xff, width * height); - - if ((hdcDIBSection = CreateCompatibleDC (hdcGDI)) == NULL) - Sys_Error ("DIB_Init() - CreateCompatibleDC failed\n"); - - if ((previously_selected_GDI_obj = - SelectObject (hdcDIBSection, hDIBSection)) == NULL) - Sys_Error ("DIB_Init() - SelectObject failed\n"); - - // create a palette - VID_InitGamma (palette); - viddef.vid_internal->set_palette (palette); -} - -void -Win_CreateDriver (void) -{ - if (vid_ddraw->int_val) { - VID_CreateDDrawDriver (DIBWidth, DIBHeight, viddef.palette, - &viddef.buffer, &viddef.rowbytes); - } - if (!win_using_ddraw) { - // directdraw failed or was not requested - // - // if directdraw failed, it may be partially initialized, so make sure - // the slate is clean - Win_UnloadAllDrivers (); - - VID_CreateGDIDriver (DIBWidth, DIBHeight, viddef.palette, - &viddef.buffer, &viddef.rowbytes); - } -} - -void -Win_UnloadAllDrivers (void) -{ - // shut down ddraw - if (vidbuf) { - free (vidbuf); - vidbuf = NULL; - } - - if (dd_Clipper) { - IDirectDrawClipper_Release (dd_Clipper); - dd_Clipper = NULL; - } - - if (win_dd_frontbuffer) { - IDirectDrawSurface_Release (win_dd_frontbuffer); - win_dd_frontbuffer = NULL; - } - - if (win_dd_backbuffer) { - IDirectDrawSurface_Release (win_dd_backbuffer); - win_dd_backbuffer = NULL; - } - - if (dd_Object) { - IDirectDraw_Release (dd_Object); - dd_Object = NULL; - } - - if (hInstDDraw) { - FreeLibrary (hInstDDraw); - hInstDDraw = NULL; - } - - ddCreate = NULL; - - // shut down gdi - if (hdcDIBSection) { - SelectObject (hdcDIBSection, previously_selected_GDI_obj); - DeleteDC (hdcDIBSection); - hdcDIBSection = NULL; - } - - if (hDIBSection) { - DeleteObject (hDIBSection); - hDIBSection = NULL; - pDIBBase = NULL; - } - - if (hdcGDI) { - // if hdcGDI exists then win_mainwindow must also be valid - ReleaseDC (win_mainwindow, hdcGDI); - hdcGDI = NULL; - } - // not using ddraw now - win_using_ddraw = false; -} - static int VID_SetMode (int modenum, const byte *palette); static void __attribute__ ((used)) @@ -455,12 +191,12 @@ VID_CheckWindowXY (void) void Win_UpdateWindowStatus (int window_x, int window_y) { - window_rect.left = window_x; - window_rect.top = window_y; - window_rect.right = window_x + window_width; - window_rect.bottom = window_y + window_height; - window_center_x = (window_rect.left + window_rect.right) / 2; - window_center_y = (window_rect.top + window_rect.bottom) / 2; + win_rect.left = window_x; + win_rect.top = window_y; + win_rect.right = window_x + viddef.width; + win_rect.bottom = window_y + viddef.height; + win_center_x = (win_rect.left + win_rect.right) / 2; + win_center_y = (win_rect.top + win_rect.bottom) / 2; IN_UpdateClipCursor (); } @@ -511,27 +247,6 @@ VID_InitModes (HINSTANCE hInstance) if (!RegisterClass (&wc)) Sys_Error ("Couldn't register window class"); - modelist[0].type = MS_WINDOWED; - modelist[0].width = 320; - modelist[0].height = 240; - strcpy (modelist[0].modedesc, "320x240"); - modelist[0].modenum = MODE_WINDOWED; - modelist[0].fullscreen = 0; - - modelist[1].type = MS_WINDOWED; - modelist[1].width = 640; - modelist[1].height = 480; - strcpy (modelist[1].modedesc, "640x480"); - modelist[1].modenum = MODE_WINDOWED + 1; - modelist[1].fullscreen = 0; - - modelist[2].type = MS_WINDOWED; - modelist[2].width = 800; - modelist[2].height = 600; - strcpy (modelist[2].modedesc, "800x600"); - modelist[2].modenum = MODE_WINDOWED + 2; - modelist[2].fullscreen = 0; - // automatically stretch the default mode up if > 640x480 desktop // resolution hdc = GetDC (NULL); @@ -961,10 +676,6 @@ VID_SetMode (int modenum, const byte *palette) IN_HideMouse (); } - window_width = viddef.width; - window_height = viddef.height; - - Win_UpdateWindowStatus (0, 0); // FIXME right numbers? //FIXME CDAudio_Resume (); //FIXME? scr_disabled_for_loading = temp; diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index 641788f02..1d4ee1cb1 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -122,7 +122,7 @@ void IN_UpdateClipCursor (void) { if (mouseinitialized && in_mouse_avail && !dinput) { - ClipCursor (&window_rect); + ClipCursor (&win_rect); } } @@ -164,9 +164,9 @@ IN_ActivateMouse (void) restore_spi = SystemParametersInfo (SPI_SETMOUSE, 0, newmouseparms, 0); - SetCursorPos (window_center_x, window_center_y); + SetCursorPos (win_center_x, win_center_y); SetCapture (win_mainwindow); - ClipCursor (&window_rect); + ClipCursor (&win_rect); } in_mouse_avail = true; @@ -522,8 +522,8 @@ IN_LL_ProcessEvents (void) mouse_oldbuttonstate = mstate_di; } else { GetCursorPos (¤t_pos); - mx = current_pos.x - window_center_x + mx_accum; - my = current_pos.y - window_center_y + my_accum; + mx = current_pos.x - win_center_x + mx_accum; + my = current_pos.y - win_center_y + my_accum; mx_accum = 0; my_accum = 0; } @@ -533,7 +533,7 @@ IN_LL_ProcessEvents (void) // if the mouse has moved, force it to the center, so there's room to move if (mx || my) { - SetCursorPos (window_center_x, window_center_y); + SetCursorPos (win_center_x, win_center_y); } } diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index 567b5d0c7..313aad3c8 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -50,9 +50,268 @@ static win_palette_t st2d_8to32table[256]; static byte current_palette[768]; static int palette_changed; +static LPDIRECTDRAW dd_Object; +static HINSTANCE hInstDDraw; +static LPDIRECTDRAWSURFACE dd_frontbuffer; +static LPDIRECTDRAWSURFACE dd_backbuffer; +static RECT src_rect; +static RECT dst_rect; +static HDC win_gdi; +static HDC dib_section; +static HBITMAP dib_bitmap; +static HGDIOBJ previous_dib; +static int using_ddraw; + +static LPDIRECTDRAWCLIPPER dd_Clipper; + +typedef HRESULT (WINAPI *ddCreateProc_t) (GUID FAR *, + LPDIRECTDRAW FAR *, + IUnknown FAR *); +static ddCreateProc_t ddCreate; + +static int dd_window_width = 640; +static int dd_window_height = 480; + +static void +DD_UpdateRects (int width, int height) +{ + POINT p = { .x = 0, .y = 0 }; + // first we need to figure out where on the primary surface our window + // lives + ClientToScreen (win_mainwindow, &p); + GetClientRect (win_mainwindow, &dst_rect); + OffsetRect (&dst_rect, p.x, p.y); + SetRect (&src_rect, 0, 0, width, height); +} + + +static void +VID_CreateDDrawDriver (int width, int height) +{ + DDSURFACEDESC ddsd; + + using_ddraw = false; + dd_window_width = width; + dd_window_height = height; + + viddef.buffer = malloc (width * height); + viddef.rowbytes = width; + + if (!(hInstDDraw = LoadLibrary ("ddraw.dll"))) { + return; + } + if (!(ddCreate = (ddCreateProc_t) GetProcAddress (hInstDDraw, + "DirectDrawCreate"))) { + return; + } + + if (FAILED (ddCreate (0, &dd_Object, 0))) { + return; + } + if (FAILED (dd_Object->lpVtbl->SetCooperativeLevel (dd_Object, + win_mainwindow, + DDSCL_NORMAL))) { + return; + } + + // the primary surface in windowed mode is the full screen + memset (&ddsd, 0, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY; + + // ...and create it + if (FAILED (dd_Object->lpVtbl->CreateSurface (dd_Object, &ddsd, + &dd_frontbuffer, 0))) { + return; + } + + // not using a clipper will slow things down and switch aero off + if (FAILED (IDirectDraw_CreateClipper (dd_Object, 0, &dd_Clipper, 0))) { + return; + } + if (FAILED (IDirectDrawClipper_SetHWnd (dd_Clipper, 0, win_mainwindow))) { + return; + } + if (FAILED (IDirectDrawSurface_SetClipper (dd_frontbuffer, + dd_Clipper))) { + return; + } + + // the secondary surface is an offscreen surface that is the currect + // dimensions + // this will be blitted to the correct location on the primary surface + // (which is the full screen) during our draw op + memset (&ddsd, 0, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + ddsd.dwWidth = width; + ddsd.dwHeight = height; + + if (FAILED (IDirectDraw_CreateSurface (dd_Object, &ddsd, + &dd_backbuffer, 0))) { + return; + } + + // direct draw is working now + using_ddraw = true; + + // create initial rects + DD_UpdateRects (dd_window_width, dd_window_height); +} + +static void +VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer, + int *rowbytes) +{ + // common bitmap definition + typedef struct dibinfo { + BITMAPINFOHEADER header; + RGBQUAD acolors[256]; + } dibinfo_t; + + dibinfo_t dibheader; + BITMAPINFO *pbmiDIB = (BITMAPINFO *) & dibheader; + int i; + byte *dib_base = 0; + + win_gdi = GetDC (win_mainwindow); + memset (&dibheader, 0, sizeof (dibheader)); + + // fill in the bitmap info + pbmiDIB->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); + pbmiDIB->bmiHeader.biWidth = width; + pbmiDIB->bmiHeader.biHeight = height; + pbmiDIB->bmiHeader.biPlanes = 1; + pbmiDIB->bmiHeader.biCompression = BI_RGB; + pbmiDIB->bmiHeader.biSizeImage = 0; + pbmiDIB->bmiHeader.biXPelsPerMeter = 0; + pbmiDIB->bmiHeader.biYPelsPerMeter = 0; + pbmiDIB->bmiHeader.biClrUsed = 256; + pbmiDIB->bmiHeader.biClrImportant = 256; + pbmiDIB->bmiHeader.biBitCount = 8; + + // fill in the palette + for (i = 0; i < 256; i++) { + // d_8to24table isn't filled in yet so this is just for testing + dibheader.acolors[i].rgbRed = palette[i * 3]; + dibheader.acolors[i].rgbGreen = palette[i * 3 + 1]; + dibheader.acolors[i].rgbBlue = palette[i * 3 + 2]; + } + + // create the DIB section + dib_bitmap = CreateDIBSection (win_gdi, + pbmiDIB, + DIB_RGB_COLORS, + (void **) &dib_base, 0, 0); + + // set video buffers + if (pbmiDIB->bmiHeader.biHeight > 0) { + // bottom up + buffer[0] = dib_base + (height - 1) * width; + rowbytes[0] = -width; + } else { + // top down + buffer[0] = dib_base; + rowbytes[0] = width; + } + + // clear the buffer + memset (dib_base, 0xff, width * height); + + if ((dib_section = CreateCompatibleDC (win_gdi)) == 0) + Sys_Error ("DIB_Init() - CreateCompatibleDC failed\n"); + + if ((previous_dib = SelectObject (dib_section, dib_bitmap)) == 0) + Sys_Error ("DIB_Init() - SelectObject failed\n"); + + // create a palette + VID_InitGamma (palette); + viddef.vid_internal->set_palette (palette); +} + +void +Win_UnloadAllDrivers (void) +{ + // shut down ddraw + if (viddef.buffer) { + free (viddef.buffer); + *(int *)0xdb = 0; + viddef.buffer = 0; + } + + if (dd_Clipper) { + IDirectDrawClipper_Release (dd_Clipper); + dd_Clipper = 0; + } + + if (dd_frontbuffer) { + IDirectDrawSurface_Release (dd_frontbuffer); + dd_frontbuffer = 0; + } + + if (dd_backbuffer) { + IDirectDrawSurface_Release (dd_backbuffer); + dd_backbuffer = 0; + } + + if (dd_Object) { + IDirectDraw_Release (dd_Object); + dd_Object = 0; + } + + if (hInstDDraw) { + FreeLibrary (hInstDDraw); + hInstDDraw = 0; + } + + ddCreate = 0; + + // shut down gdi + if (dib_section) { + SelectObject (dib_section, previous_dib); + DeleteDC (dib_section); + dib_section = 0; + } + + if (dib_bitmap) { + DeleteObject (dib_bitmap); + dib_bitmap = 0; + } + + if (win_gdi) { + // if win_gdi exists then win_mainwindow must also be valid + ReleaseDC (win_mainwindow, win_gdi); + win_gdi = 0; + } + // not using ddraw now + using_ddraw = false; +} + +static void +Win_CreateDriver (void) +{ + if (vid_ddraw->int_val) { + VID_CreateDDrawDriver (viddef.width, viddef.height); + } + if (!using_ddraw) { + // directdraw failed or was not requested + // + // if directdraw failed, it may be partially initialized, so make sure + // the slate is clean + Win_UnloadAllDrivers (); + + VID_CreateGDIDriver (viddef.width, viddef.height, viddef.palette, + &viddef.buffer, &viddef.rowbytes); + } +} + static void win_init_bufers (void) { + Win_UnloadAllDrivers (); + Win_CreateDriver (); // set the rest of the buffers we need (why not just use one single buffer // instead of all this crap? oh well, it's Quake...) viddef.direct = viddef.buffer; @@ -60,6 +319,7 @@ win_init_bufers (void) // more crap for the console viddef.conrowbytes = viddef.rowbytes; + } static void @@ -76,7 +336,7 @@ win_set_palette (const byte *palette) st2d_8to32table[i].bgra[2] = viddef.gammatable[pal[0]]; st2d_8to32table[i].bgra[3] = 255; } - if (!win_minimized && !win_using_ddraw && win_dib_section) { + if (!win_minimized && !using_ddraw && dib_section) { RGBQUAD colors[256]; memcpy (colors, st2d_8to32table, sizeof (colors)); for (int i = 0; i < 256; i++) { @@ -89,7 +349,7 @@ win_set_palette (const byte *palette) colors[255].rgbGreen = 0xff; colors[255].rgbBlue = 0xff; - if (SetDIBColorTable (win_dib_section, 0, 256, colors) == 0) { + if (SetDIBColorTable (dib_section, 0, 256, colors) == 0) { Sys_Printf ("win_set_palette() - SetDIBColorTable failed\n"); } } @@ -111,9 +371,9 @@ dd_blit_rect (vrect_t *rect) TheRect.top = rect->y; TheRect.bottom = rect->y + rect->height; - if (IDirectDrawSurface_Lock (win_dd_backbuffer, &TheRect, &ddsd, + if (IDirectDrawSurface_Lock (dd_backbuffer, &TheRect, &ddsd, DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR, - NULL) == DDERR_WASSTILLDRAWING) { + 0) == DDERR_WASSTILLDRAWING) { return; } @@ -130,23 +390,23 @@ dd_blit_rect (vrect_t *rect) dst += ddsd.lPitch - rect->width; } - IDirectDrawSurface_Unlock (win_dd_backbuffer, NULL); + IDirectDrawSurface_Unlock (dd_backbuffer, 0); // correctly offset source - sRect.left = win_src_rect.left + rect->x; - sRect.right = win_src_rect.left + rect->x + rect->width; - sRect.top = win_src_rect.top + rect->y; - sRect.bottom = win_src_rect.top + rect->y + rect->height; + sRect.left = src_rect.left + rect->x; + sRect.right = src_rect.left + rect->x + rect->width; + sRect.top = src_rect.top + rect->y; + sRect.bottom = src_rect.top + rect->y + rect->height; // correctly offset dest - dRect.left = win_dst_rect.left + rect->x; - dRect.right = win_dst_rect.left + rect->x + rect->width; - dRect.top = win_dst_rect.top + rect->y; - dRect.bottom = win_dst_rect.top + rect->y + rect->height; + dRect.left = dst_rect.left + rect->x; + dRect.right = dst_rect.left + rect->x + rect->width; + dRect.top = dst_rect.top + rect->y; + dRect.bottom = dst_rect.top + rect->y + rect->height; // copy to front buffer - IDirectDrawSurface_Blt (win_dd_frontbuffer, &dRect, win_dd_backbuffer, - &sRect, 0, NULL); + IDirectDrawSurface_Blt (dd_frontbuffer, &dRect, dd_backbuffer, + &sRect, 0, 0); } static void @@ -163,16 +423,16 @@ win_sw_update (vrect_t *rects) rects = &full_rect; } - if (win_using_ddraw) { + if (using_ddraw) { while (rects) { dd_blit_rect (rects); rects = rects->next; } - } else if (win_dib_section) { + } else if (dib_section) { while (rects) { BitBlt (win_gdi, rects->x, rects->y, rects->x + rects->width, rects->y + rects->height, - win_dib_section, rects->x, rects->y, SRCCOPY); + dib_section, rects->x, rects->y, SRCCOPY); rects = rects->next; } } @@ -187,14 +447,13 @@ win_choose_visual (sw_ctx_t *ctx) static void win_set_background (void) { - // because we have set the background brush for the window to NULL (to + // because we have set the background brush for the window to 0 (to // avoid flickering when re-sizing the window on the desktop), we clear // the window to black when created, otherwise it will be empty while // Quake starts up. This also prevents a screen flash to white when // switching drivers. it still flashes, but at least it's black now HDC hdc = GetDC (win_mainwindow); - PatBlt (hdc, 0, 0, win_window_rect.right, win_window_rect.bottom, - BLACKNESS); + PatBlt (hdc, 0, 0, win_rect.right, win_rect.bottom, BLACKNESS); ReleaseDC (win_mainwindow, hdc); } @@ -209,12 +468,9 @@ win_create_context (sw_ctx_t *ctx) win_set_background (); // create the new driver - win_using_ddraw = false; - - Win_CreateDriver (); + using_ddraw = false; viddef.vid_internal->init_buffers = win_init_bufers; - VID_InitBuffers (); } sw_ctx_t * From 38e7a63cef090e0be3ced0e4cc73cb1a6e25af5f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 15:10:51 +0900 Subject: [PATCH 1481/3664] [vid] Clean up sdl some more Ugh, its fullscreen is annoying, but later. --- libs/video/targets/vid_sdl_sw.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/libs/video/targets/vid_sdl_sw.c b/libs/video/targets/vid_sdl_sw.c index 5d5dcfb0d..9fa138aac 100644 --- a/libs/video/targets/vid_sdl_sw.c +++ b/libs/video/targets/vid_sdl_sw.c @@ -58,9 +58,6 @@ #define BASEWIDTH 320 #define BASEHEIGHT 200 -byte *VGA_pagebase; -int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0; - // Define GLAPIENTRY to a useful value #ifndef GLAPIENTRY # ifdef _WIN32 @@ -105,10 +102,15 @@ sdl_set_palette (const byte *palette) static void sdl_init_buffers (void) { + viddef.buffer = sdl_screen->pixels; + viddef.rowbytes = sdl_screen->pitch; + viddef.conbuffer = viddef.buffer; + viddef.conrowbytes = viddef.rowbytes; + viddef.direct = 0; } static void -sdl_set_vid_mode (sw_ctx_t *ctx) +sdl_create_context (sw_ctx_t *ctx) { // Initialize display if (!(sdl_screen = SDL_SetVideoMode (viddef.width, viddef.height, 8, @@ -116,16 +118,7 @@ sdl_set_vid_mode (sw_ctx_t *ctx) Sys_Error ("VID: Couldn't set video mode: %s", SDL_GetError ()); // now know everything we need to know about the buffer - VGA_width = viddef.width; - VGA_height = viddef.height; viddef.vid_internal->init_buffers = sdl_init_buffers; - VGA_pagebase = viddef.buffer = sdl_screen->pixels; - VGA_rowbytes = viddef.rowbytes = sdl_screen->pitch; - viddef.conbuffer = viddef.buffer; - viddef.conrowbytes = viddef.rowbytes; - viddef.direct = 0; - - VID_InitBuffers (); // allocate z buffer and surface cache } static void @@ -171,7 +164,7 @@ SDL_SW_Context (void) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); ctx->set_palette = sdl_set_palette; - ctx->create_context = sdl_set_vid_mode; + ctx->create_context = sdl_create_context; ctx->update = sdl_sw_update; return ctx; } From 8e363d424f0461c8ac76c8f51bd2eb33341e351e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 15:11:31 +0900 Subject: [PATCH 1482/3664] [vid] Remove redundant call to VID_InitBuffers --- libs/video/targets/vid_x11_sw.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index df672ef58..b88563a1a 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -519,8 +519,6 @@ x11_create_context (sw_ctx_t *ctx) } viddef.vid_internal->init_buffers = x11_init_buffers; - VID_InitBuffers (); - // XSynchronize (x_disp, False); // X11_AddEvent (x_shmeventtype, event_shm); } From 6f56f987143d7c50a160bcc4df88b67ddc787fca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 15:50:10 +0900 Subject: [PATCH 1483/3664] [vid] Make windows vid init conform to QF's method Ie, respecting cvars. --- include/context_win.h | 3 +- libs/video/targets/context_win.c | 170 +++++++++++++++++++------------ libs/video/targets/vid_win.c | 3 +- 3 files changed, 110 insertions(+), 66 deletions(-) diff --git a/include/context_win.h b/include/context_win.h index cf4010f43..536a01564 100644 --- a/include/context_win.h +++ b/include/context_win.h @@ -50,7 +50,8 @@ void Win_Activate (BOOL fActive, BOOL minimize); void Win_UnloadAllDrivers (void); void Win_OpenDisplay (void); void Win_CloseDisplay (void); -void Win_SetVidMode (int width, int height, const byte *palette); +void Win_SetVidMode (int width, int height); +void Win_CreateWindow (int width, int height); void Win_Init_Cvars (void); void Win_UpdateWindowStatus (int x, int y); void Win_SetCaption (const char *text); diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index a2694c2e1..59bd56096 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -84,19 +84,20 @@ static cvar_t *vid_window_y; #define MAX_MODE_LIST 36 #define VID_ROW_SIZE 3 -static int DIBWidth, DIBHeight; -static RECT WindowRect; static DWORD WindowStyle, ExWindowStyle; int win_center_x, win_center_y; RECT win_rect; DEVMODE win_gdevmode; -static qboolean startwindowed = 0, windowed_mode_set; -static int vid_fulldib_on_focus_mode; -static qboolean force_minimized, in_mode_set, force_mode_set; +static qboolean startwindowed = 0; +//static qboolean windowed_mode_set; +//static int vid_fulldib_on_focus_mode; +static qboolean force_minimized; +static qboolean in_mode_set; +static qboolean force_mode_set; static qboolean vid_mode_set; -static HICON hIcon; +//static HICON hIcon; int vid_modenum = NO_MODE; @@ -175,7 +176,7 @@ VID_RememberWindowPos (void) } } - +#if 0 static void VID_CheckWindowXY (void) { @@ -186,7 +187,7 @@ VID_CheckWindowXY (void) Cvar_SetValue (vid_window_y, 0.0); } } - +#endif void Win_UpdateWindowStatus (int window_x, int window_y) @@ -348,29 +349,10 @@ Win_OpenDisplay (void) vid_default = windowed_default; } -//FIXME? if (hwnd_dialog) -//FIXME? DestroyWindow (hwnd_dialog); - - // sound initialization has to go here, preceded by a windowed mode set, - // so there's a window for DirectSound to work with but we're not yet - // fullscreen so the "hardware already in use" dialog is visible if it - // gets displayed - // keep the window minimized until we're ready for the first real mode set - win_mainwindow = CreateWindowEx (ExWindowStyle, - "WinQuake", - "WinQuake", - WindowStyle, - 0, 0, - WindowRect.right - WindowRect.left, - WindowRect.bottom - WindowRect.top, - NULL, NULL, global_hInstance, NULL); - - if (!win_mainwindow) - Sys_Error ("Couldn't create DIB window"); - - // done - vid_mode_set = true; -//FIXME if (firsttime) S_Init (); +#ifdef SPLASH_SCREEN + if (hwnd_dialog) + DestroyWindow (hwnd_dialog); +#endif } void @@ -396,16 +378,16 @@ Win_CloseDisplay (void) } void -Win_SetVidMode (int width, int height, const byte *palette) +Win_SetVidMode (int width, int height) { //FIXME SCR_StretchInit(); force_mode_set = true; - VID_SetMode (vid_default, palette); + //VID_SetMode (vid_default, palette); force_mode_set = false; vid_realmode = vid_modenum; } - +#if 0 static void VID_DestroyWindow (void) { @@ -414,7 +396,7 @@ VID_DestroyWindow (void) Win_UnloadAllDrivers (); } - +#endif static void VID_CheckModedescFixup (int mode) { @@ -423,6 +405,7 @@ VID_CheckModedescFixup (int mode) static qboolean VID_SetWindowedMode (int modenum) { +#if 0 if (!windowed_mode_set) { if (COM_CheckParm ("-resetwinpos")) { Cvar_SetValue (vid_window_x, 0.0); @@ -435,9 +418,6 @@ VID_SetWindowedMode (int modenum) VID_CheckModedescFixup (modenum); VID_DestroyWindow (); - WindowRect.top = WindowRect.left = 0; - WindowRect.right = modelist[modenum].width; - WindowRect.bottom = modelist[modenum].height; DIBWidth = modelist[modenum].width; DIBHeight = modelist[modenum].height; @@ -447,7 +427,6 @@ VID_SetWindowedMode (int modenum) // WindowStyle = WS_OVERLAPPEDWINDOW|WS_VISIBLE; ExWindowStyle = 0; - AdjustWindowRectEx (&WindowRect, WindowStyle, FALSE, 0); // the first time we're called to set the mode, create the window we'll use // for the rest of the session @@ -494,7 +473,7 @@ VID_SetWindowedMode (int modenum) //FIXME? } SendMessage (win_mainwindow, WM_SETICON, (WPARAM) TRUE, (LPARAM) hIcon); SendMessage (win_mainwindow, WM_SETICON, (WPARAM) FALSE, (LPARAM) hIcon); - +#endif return true; } @@ -502,6 +481,7 @@ VID_SetWindowedMode (int modenum) static qboolean VID_SetFullDIBMode (int modenum) { +#if 0 VID_DestroyWindow (); win_gdevmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; @@ -515,8 +495,8 @@ VID_SetFullDIBMode (int modenum) modestate = MS_FULLDIB; vid_fulldib_on_focus_mode = modenum; - WindowRect.top = WindowRect.left = 0; + WindowRect.top = WindowRect.left = 0; WindowRect.right = modelist[modenum].width; WindowRect.bottom = modelist[modenum].height; @@ -560,7 +540,7 @@ VID_SetFullDIBMode (int modenum) viddef.height = viddef.conheight = DIBHeight; viddef.width = viddef.conwidth = DIBWidth; #endif - +#endif return true; } @@ -735,6 +715,74 @@ VID_SetMode (int modenum, const byte *palette) } +void +Win_CreateWindow (int width, int height) +{ + RECT rect = { + .top = 0, + .left = 0, + .right = width, + .bottom = height, + }; + AdjustWindowRectEx (&rect, WindowStyle, FALSE, 0); + // sound initialization has to go here, preceded by a windowed mode set, + // so there's a window for DirectSound to work with but we're not yet + // fullscreen so the "hardware already in use" dialog is visible if it + // gets displayed + // keep the window minimized until we're ready for the first real mode set + win_mainwindow = CreateWindowEx (ExWindowStyle, + "WinQuake", + "WinQuake", + WindowStyle, + 0, 0, + rect.right - rect.left, + rect.bottom - rect.top, + NULL, NULL, global_hInstance, NULL); + + if (!win_mainwindow) + Sys_Error ("Couldn't create DIB window"); + + // done + vid_mode_set = true; +//FIXME if (firsttime) S_Init (); + Win_UpdateWindowStatus (0, 0); // FIXME right numbers? + + HDC hdc = GetDC (NULL); + if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) { + win_palettized = true; + } else { + win_palettized = false; + } + ReleaseDC (NULL, hdc); + + //vid_modenum = modenum; + //Cvar_SetValue (vid_mode, (float) vid_modenum); + + MSG msg; + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + Sleep (100); + + if (!force_minimized) { + SetWindowPos (win_mainwindow, HWND_TOP, 0, 0, 0, 0, + SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | + SWP_NOCOPYBITS); + + SetForegroundWindow (win_mainwindow); + } + // fix the leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + Sys_Printf ("%s\n", VID_GetModeDescription (vid_modenum)); + + in_mode_set = false; + + viddef.recalc_refdef = 1; +} + //========================================================================== @@ -987,44 +1035,38 @@ Win_SetGamma (double gamma) return i; } -#define CVAR_ORIGINAL CVAR_NONE // FIXME void Win_Init_Cvars (void) { - vid_ddraw = Cvar_Get ("vid_ddraw", "1", CVAR_ORIGINAL, 0, ""); - vid_mode = Cvar_Get ("vid_mode", "0", CVAR_ORIGINAL, 0, ""); - vid_wait = Cvar_Get ("vid_wait", "0", CVAR_ORIGINAL, 0, ""); + vid_ddraw = Cvar_Get ("vid_ddraw", "1", CVAR_NONE, 0, ""); + vid_mode = Cvar_Get ("vid_mode", "0", CVAR_NONE, 0, ""); + vid_wait = Cvar_Get ("vid_wait", "0", CVAR_NONE, 0, ""); vid_nopageflip = - Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE, 0, ""); _vid_wait_override = - Cvar_Get ("_vid_wait_override", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); + Cvar_Get ("_vid_wait_override", "0", CVAR_ARCHIVE, 0, ""); _vid_default_mode = - Cvar_Get ("_vid_default_mode", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); + Cvar_Get ("_vid_default_mode", "0", CVAR_ARCHIVE, 0, ""); _vid_default_mode_win = - Cvar_Get ("_vid_default_mode_win", "3", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); + Cvar_Get ("_vid_default_mode_win", "3", CVAR_ARCHIVE, 0, ""); vid_config_x = - Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE, 0, ""); vid_config_y = - Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE, 0, ""); vid_stretch_by_2 = - Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE, 0, ""); _windowed_mouse = - Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, 0, ""); vid_fullscreen_mode = - Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); + Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE, 0, ""); vid_windowed_mode = - Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, - ""); + Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE, 0, ""); block_switch = - Cvar_Get ("block_switch", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + Cvar_Get ("block_switch", "0", CVAR_ARCHIVE, 0, ""); vid_window_x = - Cvar_Get ("vid_window_x", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + Cvar_Get ("vid_window_x", "0", CVAR_ARCHIVE, 0, ""); vid_window_y = - Cvar_Get ("vid_window_y", "0", CVAR_ARCHIVE | CVAR_ORIGINAL, 0, ""); + Cvar_Get ("vid_window_y", "0", CVAR_ARCHIVE, 0, ""); Cmd_AddCommand ("vid_testmode", VID_TestMode_f, ""); Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, ""); diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index da4b51abf..1e299d252 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -147,7 +147,8 @@ VID_Init (byte *palette, byte *colormap) VID_GetWindowSize (640, 480); Win_OpenDisplay (); vid_internal.choose_visual (); - Win_SetVidMode (viddef.width, viddef.height, palette); + Win_SetVidMode (viddef.width, viddef.height); + Win_CreateWindow (viddef.width, viddef.height); vid_internal.create_context (); VID_InitGamma (palette); From 55d3193b5f7902a9d8881ee7eb7a1fbdad939aaa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 16:25:19 +0900 Subject: [PATCH 1484/3664] [vid] Set pixel format for OpenGL This gets the GL and GLSL renderers working for the -win targets... sort of: they are upside down and GLSL's bsp surfaces are black (same as Vulkan). However, with this, all 5 renderers at least limp along for -win, 4/5 work for -sdl. --- libs/video/targets/vid_win_gl.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/libs/video/targets/vid_win_gl.c b/libs/video/targets/vid_win_gl.c index 64afb042a..1975b8741 100644 --- a/libs/video/targets/vid_win_gl.c +++ b/libs/video/targets/vid_win_gl.c @@ -94,12 +94,36 @@ wgl_choose_visual (gl_ctx_t *ctx) { } +static void +wgl_set_pixel_format (void) +{ + int pixelformat; + PIXELFORMATDESCRIPTOR pfd = { + .nSize = sizeof(PIXELFORMATDESCRIPTOR), + .nVersion = 1, + .dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW, + .iPixelType = PFD_TYPE_RGBA, + .cColorBits = win_gdevmode.dmBitsPerPel, + .cDepthBits = 32, + .iLayerType = PFD_MAIN_PLANE, + }; + + if (!(pixelformat = ChoosePixelFormat (win_maindc, &pfd))) { + Sys_Error ("ChoosePixelFormat failed"); + } + if (!SetPixelFormat (win_maindc, pixelformat, &pfd)) { + Sys_Error ("SetPixelFormat failed"); + } +} + static void wgl_create_context (gl_ctx_t *ctx) { DWORD lasterror; - Sys_Printf ("maindc: %p\n", win_maindc); + win_maindc = GetDC (win_mainwindow); + + wgl_set_pixel_format (); baseRC = qfwglCreateContext (win_maindc); if (!baseRC) { lasterror=GetLastError(); From bc785ab2c2601dbdad32c8aa40323d433ead2120 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 17:49:26 +0900 Subject: [PATCH 1485/3664] [input] Make unbindall less aggressive As it is a legacy command, it should affect only the legacy bindings (imt_drop_all is available for aggressively unbinding all keys). --- libs/video/targets/keys.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libs/video/targets/keys.c b/libs/video/targets/keys.c index eeaf13b83..b978c4758 100644 --- a/libs/video/targets/keys.c +++ b/libs/video/targets/keys.c @@ -748,15 +748,13 @@ Key_In_Unbind_f (void) static void Key_Unbindall_f (void) { - keydest_t kd; imt_t *imt; int i; - for (kd = key_unfocused; kd < key_last; kd++) { - for (imt = key_targets[kd].imts; imt; imt = imt->next) { - for (i = 0; i < QFK_LAST; i++) { - Key_SetBinding (imt, i, 0); - } + imt = Key_FindIMT ("imt_mod"); + if (imt) { + for (i = 0; i < QFK_LAST; i++) { + Key_SetBinding (imt, i, 0); } } } From 92859b7c2eba07d4a9d64195986631770a046c41 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 17:51:11 +0900 Subject: [PATCH 1486/3664] [input] Set up default bindings for other imts Now ` and F10 work by default in all contexts. --- libs/video/targets/keys.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libs/video/targets/keys.c b/libs/video/targets/keys.c index b978c4758..4d5c57e27 100644 --- a/libs/video/targets/keys.c +++ b/libs/video/targets/keys.c @@ -1268,6 +1268,24 @@ static struct { {key_last, 0, 0}, }; +static struct { + const char *imt; + const char *key; + const char *command; +} default_bindings[] = { + {"imt_mod", "K_F10", "quit"}, + {"imt_mod", "K_BACKQUOTE", "toggleconsole"}, + {"imt_0", "K_F10", "quit"}, + {"imt_0", "K_BACKQUOTE", "toggleconsole"}, + {"imt_demo", "K_F10", "quit"}, + {"imt_demo", "K_BACKQUOTE", "toggleconsole"}, + {"imt_console", "K_F10", "quit"}, + {"imt_console", "K_BACKQUOTE", "toggleconsole"}, + {"imt_menu", "K_F10", "quit"}, + {"imt_console", "K_BACKQUOTE", "toggleconsole"}, + { } +}; + static void Key_CreateDefaultIMTs (void) { @@ -1277,6 +1295,10 @@ Key_CreateDefaultIMTs (void) Key_CreateIMT (default_imts[i].kd, default_imts[i].imt_name, default_imts[i].chain_imt_name); } + for (i = 0; default_bindings[i].imt; i++) { + Key_In_Bind (default_bindings[i].imt, default_bindings[i].key, + default_bindings[i].command); + } } void From f13af65b32159c461cc68903382cd4d8147a6e26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Mar 2021 23:38:49 +0900 Subject: [PATCH 1487/3664] [vulkan] Move viewport and scissor into vulkan_ctx Not only does it makes sense to centralize the setting of viewport and scissor, but it's actually necessary in order to fix the upside-down rendering on windows. --- include/vid_vulkan.h | 2 ++ libs/video/renderer/vulkan/instance.c | 2 +- libs/video/renderer/vulkan/vulkan_alias.c | 6 ++---- libs/video/renderer/vulkan/vulkan_bsp.c | 6 ++---- libs/video/renderer/vulkan/vulkan_compose.c | 6 ++---- libs/video/renderer/vulkan/vulkan_draw.c | 6 ++---- libs/video/renderer/vulkan/vulkan_lighting.c | 6 ++---- libs/video/targets/vid_win_vulkan.c | 6 ++++++ libs/video/targets/vid_x11_vulkan.c | 5 +++++ 9 files changed, 24 insertions(+), 21 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 2a1f8fd9a..556780fc0 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -99,6 +99,8 @@ typedef struct vulkan_ctx_s { struct qfv_tex_s *default_white; struct qfv_tex_s *default_magenta; + VkViewport viewport; + VkRect2D scissor; // projection and view matrices (model is push constant) vulkan_matrices_t matrices; diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index 35a478108..db6c6f502 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -208,7 +208,7 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, VK_STRUCTURE_TYPE_APPLICATION_INFO, 0, appName, appVersion, PACKAGE_STRING, 0x000702ff, //FIXME version - VK_API_VERSION_1_0, + VK_API_VERSION_1_1, }; VkInstanceCreateInfo createInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 0, 0, diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index c2581e773..1e104fbef 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -201,10 +201,8 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->layout, 0, 1, aframe->descriptors + 0); - VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; - VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; - dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); //dfunc->vkUpdateDescriptorSets (device->dev, 2, aframe->descriptors, 0, 0); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 2c38cd65e..5e2d4dfd0 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -896,10 +896,8 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; - VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; - dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); VkDeviceSize offsets[] = { 0 }; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &bctx->vertex_buffer, offsets); diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index fc7316ede..66a9afc6d 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -94,10 +94,8 @@ Vulkan_Compose_Draw (vulkan_ctx_t *ctx) dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, cctx->layout, 0, 1, sets, 0, 0); - VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; - VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; - dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); VkDeviceSize offset = 0; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 879c79aba..f7aeabb97 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -732,10 +732,8 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dctx->pipeline); - VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; - VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; - dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); VkDeviceSize offsets[] = {dframe->vert_offset}; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets); dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 8563aafe1..9a4ab76a4 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -230,10 +230,8 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, lctx->layout, 0, 2, sets, 0, 0); - VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; - VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; - dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); VkDeviceSize offset = 0; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); diff --git a/libs/video/targets/vid_win_vulkan.c b/libs/video/targets/vid_win_vulkan.c index 027abed00..240fa2355 100644 --- a/libs/video/targets/vid_win_vulkan.c +++ b/libs/video/targets/vid_win_vulkan.c @@ -154,6 +154,12 @@ win_vulkan_create_surface (vulkan_ctx_t *ctx) .hinstance = pres->instance, .hwnd = pres->window, }; + + int width = viddef.width; + int height = viddef.height; + ctx->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; + ctx->scissor = (VkRect2D) { {0, 0}, {width, height} }; + if (pres->vkCreateWin32SurfaceKHR (inst, &createInfo, 0, &surface) != VK_SUCCESS) { return 0; diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index d64bed09f..a65cd65b0 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -194,6 +194,11 @@ x11_vulkan_create_surface (vulkan_ctx_t *ctx) .window = pres->window }; + int width = viddef.width; + int height = viddef.height; + ctx->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; + ctx->scissor = (VkRect2D) { {0, 0}, {width, height} }; + if (pres->vkCreateXlibSurfaceKHR (inst, &createInfo, 0, &surface) != VK_SUCCESS) { return 0; From 73a610508c52f76a715f3d3030fda027375bd4dd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Apr 2021 18:00:59 +0900 Subject: [PATCH 1488/3664] [util] Fix cmem for windows I had quite messed up the page size (oops), and missed the fact that _aligned_free is to be used with _aligned_malloc rather than just free. --- libs/util/cmem.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/libs/util/cmem.c b/libs/util/cmem.c index 5ff1898f5..651f94993 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -31,12 +31,16 @@ #include "QF/cmem.h" #ifdef _WIN32 -#define aligned_alloc(align, size) _aligned_malloc(size, align) +#define cmem_alloc(align, size) _aligned_malloc(size, align) +#define cmem_free(mem) _aligned_free(mem) #define _SC_PAGESIZE 1 static size_t sysconf (int key) { - return 1024; + return 4096; } +#else +#define cmem_alloc(align, size) aligned_alloc(align, size) +#define cmem_free(mem) free(mem) #endif static size_t __attribute__((const)) @@ -52,7 +56,7 @@ ilog2 (size_t x) memsuper_t * new_memsuper (void) { - memsuper_t *super = aligned_alloc (MEM_LINE_SIZE, sizeof (*super)); + memsuper_t *super = cmem_alloc (MEM_LINE_SIZE, sizeof (*super)); memset (super, 0, sizeof (*super)); super->page_size = sysconf (_SC_PAGESIZE); super->page_mask = (super->page_size - 1); @@ -65,9 +69,9 @@ delete_memsuper (memsuper_t *super) while (super->memblocks) { memblock_t *t = super->memblocks; super->memblocks = super->memblocks->next; - free (t->mem); + cmem_free (t->mem); } - free (super); + cmem_free (super); } static void @@ -164,7 +168,7 @@ block_alloc (memsuper_t *super, size_t size) size_t page_size = super->page_size; size_t alloc_size = sizeof (memblock_t) + page_size + size; - void *mem = aligned_alloc (MEM_LINE_SIZE, alloc_size); + void *mem = cmem_alloc (MEM_LINE_SIZE, alloc_size); block = init_block (super, mem, alloc_size); return block; } @@ -324,7 +328,7 @@ cmemalloc (memsuper_t *super, size_t size) * allocated line is ever page-aligned as that would make the * line indistinguishable from a large block. */ - mem = aligned_alloc (super->page_size, super->page_size); + mem = cmem_alloc (super->page_size, super->page_size); // sets super->free_lines, the block is guarnateed to be big // enough to hold the requested allocation as otherwise a full // block allocation would have been used @@ -418,6 +422,6 @@ cmemfree (memsuper_t *super, void *mem) } if (!block->pre_allocated && (!block->post_size || block->post_free)) { unlink_block (block); - free (block->mem); + cmem_free (block->mem); } } From 9ded490806368ee6c6aaf5f84a6e02b97f49eb23 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Apr 2021 18:20:56 +0900 Subject: [PATCH 1489/3664] [util] Add Sys_PageSize Eliminate that particular problem once and for all. --- include/QF/sys.h | 1 + libs/util/cmem.c | 12 ++++++------ libs/util/sys.c | 37 +++++++++++++++++++++---------------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index eb0f25e00..e1ed1a057 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -120,6 +120,7 @@ void Sys_Init_Cvars (void); // void Sys_MakeCodeWriteable (uintptr_t startaddr, size_t length); void Sys_PageIn (void *ptr, size_t size); +long Sys_PageSize (void); void *Sys_Alloc (size_t size); // diff --git a/libs/util/cmem.c b/libs/util/cmem.c index 651f94993..02f78bb0e 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -24,20 +24,20 @@ Boston, MA 02111-1307, USA */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include "QF/alloc.h" #include "QF/cmem.h" +#include "QF/sys.h" #ifdef _WIN32 #define cmem_alloc(align, size) _aligned_malloc(size, align) #define cmem_free(mem) _aligned_free(mem) -#define _SC_PAGESIZE 1 -static size_t sysconf (int key) -{ - return 4096; -} #else #define cmem_alloc(align, size) aligned_alloc(align, size) #define cmem_free(mem) free(mem) @@ -58,7 +58,7 @@ new_memsuper (void) { memsuper_t *super = cmem_alloc (MEM_LINE_SIZE, sizeof (*super)); memset (super, 0, sizeof (*super)); - super->page_size = sysconf (_SC_PAGESIZE); + super->page_size = Sys_PageSize (); super->page_mask = (super->page_size - 1); return super; } diff --git a/libs/util/sys.c b/libs/util/sys.c index f448a6f55..cada787f2 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -442,20 +442,10 @@ Sys_MakeCodeWriteable (uintptr_t startaddr, size_t length) #else # ifdef HAVE_MPROTECT int r; + long psize = Sys_PageSize (); unsigned long endaddr = startaddr + length; -# ifdef HAVE__SC_PAGESIZE - long psize = sysconf (_SC_PAGESIZE); - - startaddr &= ~(psize - 1); - endaddr = (endaddr + psize - 1) & ~(psize -1); -# else -# ifdef HAVE_GETPAGESIZE - int psize = getpagesize (); - startaddr &= ~(psize - 1); endaddr = (endaddr + psize - 1) & ~(psize - 1); -# endif -# endif // systems with mprotect but not getpagesize (or similar) probably don't // need to page align the arguments to mprotect (eg, QNX) r = mprotect ((char *) startaddr, endaddr - startaddr, @@ -619,18 +609,33 @@ Sys_PageIn (void *ptr, size_t size) //#endif } +VISIBLE long +Sys_PageSize (void) +{ +#ifdef _WIN32 + SYSTEM_INFO si; + GetSystemInfo (&si); + return si.dwPageSize; +#else +# ifdef HAVE__SC_PAGESIZE + return sysconf (_SC_PAGESIZE); +# else +# ifdef HAVE_GETPAGESIZE + return getpagesize (); +# endif +# endif +#endif +} + VISIBLE void * Sys_Alloc (size_t size) { -#ifdef _WIN32 - size_t page_size = 4096; + size_t page_size = Sys_PageSize (); size_t page_mask = page_size - 1; size = (size + page_mask) & ~page_mask; +#ifdef _WIN32 return VirtualAlloc (0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); #else - size_t page_size = sysconf (_SC_PAGESIZE); - size_t page_mask = page_size - 1; - size = (size + page_mask) & ~page_mask; return mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); #endif From 37d35811e34a7d6699e15a143af3e2c515f4db95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Apr 2021 19:17:19 +0900 Subject: [PATCH 1490/3664] [vid,render] Clean up fov and aspect vid.aspect is removed (for now) as it was not really the right idea (I really didn't know what I was doing at the time). Nicely, this *almost* fixes the fov bug on fresh installs: the view is now properly upside-down rather than just flipped vertically (ie, it's now rotated 180 degrees). --- include/QF/Vulkan/qf_vid.h | 2 +- include/QF/plugin/vid_render.h | 2 +- include/QF/vid.h | 1 - include/r_internal.h | 2 +- libs/video/renderer/gl/gl_rmain.c | 2 +- libs/video/renderer/gl/gl_rmisc.c | 2 +- libs/video/renderer/glsl/glsl_main.c | 43 ++++---------------- libs/video/renderer/r_screen.c | 2 +- libs/video/renderer/sw/sw_rmain.c | 4 +- libs/video/renderer/sw/sw_rmisc.c | 7 ++-- libs/video/renderer/sw32/sw32_rmain.c | 4 +- libs/video/renderer/sw32/sw32_rmisc.c | 7 ++-- libs/video/renderer/vid_render_vulkan.c | 4 +- libs/video/renderer/vulkan/vulkan_matrices.c | 36 +++++++--------- libs/video/targets/vid.c | 32 +-------------- libs/video/targets/vid_win.c | 20 +-------- 16 files changed, 45 insertions(+), 125 deletions(-) diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 80f12ca67..8b94b2408 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -67,7 +67,7 @@ void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx); void Vulkan_DestroyMatrices (struct vulkan_ctx_s *ctx); -void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx, float aspect); +void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx); void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 43f4f064b..18788e641 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -161,7 +161,7 @@ typedef struct vid_render_funcs_s { void (*R_RenderView) (void); void (*R_DecayLights) (double frametime); - void (*R_ViewChanged) (float aspect); + void (*R_ViewChanged) (void); void (*R_ClearParticles) (void); void (*R_InitParticles) (void); void (*SCR_ScreenShot_f) (void); diff --git a/include/QF/vid.h b/include/QF/vid.h index 4a78fa46d..16b9bcf37 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -51,7 +51,6 @@ typedef struct { int rowbytes; // may be > width if displayed in a window unsigned width; unsigned height; - float aspect; // width / height -- < 1 is taller than wide int numpages; qboolean recalc_refdef; // if true, recalc vid-based stuff qboolean cshift_changed; diff --git a/include/r_internal.h b/include/r_internal.h index acd201c79..89a8d9cb4 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -80,7 +80,7 @@ void R_ClearState (void); void R_InitSky (struct texture_s *mt); // called at level load void R_Textures_Init (void); void R_RenderView (void); // must set r_refdef first -void R_ViewChanged (float aspect); // must set r_refdef first +void R_ViewChanged (void); // must set r_refdef first // called whenever r_refdef or vid change void R_AddEfrags (mod_brush_t *, entity_t *ent); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 64f7b84db..3516603d8 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -400,7 +400,7 @@ R_SetupGL_Viewport_and_Perspective (void) } // printf ("glViewport(%d, %d, %d, %d)\n", glx + x, gly + y2, w, h); qfglViewport (x, y2, w, h); - screenaspect = r_refdef.vrect.width * vid.aspect / r_refdef.vrect.height; + screenaspect = r_refdef.vrect.width / r_refdef.vrect.height; MYgluPerspective (r_refdef.fov_y, screenaspect, r_nearclip->value, r_farclip->value); } diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index de34bb203..fbfb216f9 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -238,7 +238,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) } void -gl_R_ViewChanged (float aspect) +gl_R_ViewChanged (void) { } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index fed46ed3a..2e07d34e0 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -64,46 +64,21 @@ mat4f_t glsl_projection; mat4f_t glsl_view; void -glsl_R_ViewChanged (float aspect) +glsl_R_ViewChanged (void) { - double xmin, xmax, ymin, ymax; - float fovx, fovy, neard, fard; + float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; + float f = 1 / tan (r_refdef.fov_y * M_PI / 360); + float neard, fard; vec4f_t *proj = glsl_projection; - fovx = r_refdef.fov_x; - fovy = r_refdef.fov_y; neard = r_nearclip->value; fard = r_farclip->value; - ymax = neard * tan (fovy * M_PI / 360); // fov_2 / 2 - ymin = -ymax; - xmax = neard * tan (fovx * M_PI / 360); // fov_2 / 2 - xmin = -xmax; - - proj[0] = (vec4f_t) { - (2 * neard) / (xmax - xmin), - 0, - 0, - 0 - }; - proj[1] = (vec4f_t) { - 0, - (2 * neard) / (ymax - ymin), - 0, - 0 - }; - proj[2] = (vec4f_t) { - (xmax + xmin) / (xmax - xmin), - (ymax + ymin) / (ymax - ymin), - (fard + neard) / (neard - fard), - -1 - }; - proj[3] = (vec4f_t) { - 0, - 0, - (2 * fard * neard) / (neard - fard), - 0 - }; + // NOTE columns! + proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 }; + proj[1] = (vec4f_t) { 0, f, 0, 0 }; + proj[2] = (vec4f_t) { 0, 0, (fard + neard) / (neard - fard), -1 }; + proj[3] = (vec4f_t) { 0, 0, (2 * fard * neard) / (neard - fard), 0 }; } void diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index d092d2154..5748d7274 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -167,7 +167,7 @@ SCR_CalcRefdef (void) refdef->vrect = scr_vrect; // notify the refresh of the change - r_funcs->R_ViewChanged (r_data->vid->aspect); + r_funcs->R_ViewChanged (); } /* diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 6d2358e5f..12a47c285 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -230,7 +230,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) Guaranteed to be called before the first refresh */ void -R_ViewChanged (float aspect) +R_ViewChanged (void) { int i; float res_scale; @@ -263,7 +263,7 @@ R_ViewChanged (float aspect) r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + r_refdef.aliasvrect.height; - pixelAspect = vid.aspect; + pixelAspect = 1;//FIXME vid.aspect; xOrigin = r_refdef.xOrigin; yOrigin = r_refdef.yOrigin; diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index 2ea74ad4e..5c4beae79 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -264,7 +264,7 @@ R_SetupFrame (void) vrect.height = vid.height; R_SetVrect (&vrect, &r_refdef.vrect, vr_data.lineadj); - R_ViewChanged (vid.aspect); + R_ViewChanged (); } else { w = vid.width; h = vid.height; @@ -287,12 +287,11 @@ R_SetupFrame (void) R_SetVrect (&vrect, &r_refdef.vrect, (int) ((float) vr_data.lineadj * (h / (float) vid.height))); - R_ViewChanged (vid.aspect * (h / w) * ((float) vid.width / - (float) vid.height)); + R_ViewChanged (); } } else { r_refdef.vrect = scr_vrect; - R_ViewChanged (vid.aspect); + R_ViewChanged (); } r_viewchanged = false; diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index d6dfd7670..ec334bb22 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -245,7 +245,7 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) Guaranteed to be called before the first refresh */ void -sw32_R_ViewChanged (float aspect) +sw32_R_ViewChanged (void) { int i; float res_scale; @@ -278,7 +278,7 @@ sw32_R_ViewChanged (float aspect) r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + r_refdef.aliasvrect.height; - sw32_pixelAspect = aspect; + sw32_pixelAspect = 1;//FIXME vid.aspect; xOrigin = r_refdef.xOrigin; yOrigin = r_refdef.yOrigin; diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c index 390b13b86..308fc1a08 100644 --- a/libs/video/renderer/sw32/sw32_rmisc.c +++ b/libs/video/renderer/sw32/sw32_rmisc.c @@ -260,7 +260,7 @@ sw32_R_SetupFrame (void) vrect.height = vid.height; R_SetVrect (&vrect, &r_refdef.vrect, vr_data.lineadj); - sw32_R_ViewChanged (vid.aspect); + sw32_R_ViewChanged (); } else { w = vid.width; h = vid.height; @@ -283,8 +283,7 @@ sw32_R_SetupFrame (void) R_SetVrect (&vrect, &r_refdef.vrect, (int) ((float) vr_data.lineadj * (h / (float) vid.height))); - sw32_R_ViewChanged (vid.aspect * (h / w) * ((float) vid.width / - (float) vid.height)); + sw32_R_ViewChanged (); } } else { vrect.x = 0; @@ -293,7 +292,7 @@ sw32_R_SetupFrame (void) vrect.height = vid.height; r_refdef.vrect = scr_vrect; - sw32_R_ViewChanged (vid.aspect); + sw32_R_ViewChanged (); } sw32_r_viewchanged = false; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 78b9fbe7b..21af94eb1 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -364,9 +364,9 @@ vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, in } static void -vulkan_R_ViewChanged (float aspect) +vulkan_R_ViewChanged (void) { - Vulkan_CalcProjectionMatrices (vulkan_ctx, aspect); + Vulkan_CalcProjectionMatrices (vulkan_ctx); } static void diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 66cb3da9a..168b63e2b 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -65,8 +65,8 @@ ortho_mat (float *proj, float xmin, float xmax, float ymin, float ymax, proj[2] = 0; proj[6] = 0; - proj[10] = -2 / (zfar - znear); - proj[14] = -(zfar + znear) / (zfar - znear); + proj[10] = 1 / (znear - zfar); + proj[14] = znear / (znear - zfar); proj[3] = 0; proj[7] = 0; @@ -75,35 +75,28 @@ ortho_mat (float *proj, float xmin, float xmax, float ymin, float ymax, } static void -persp_mat (float *proj, float xmin, float xmax, float ymin, float ymax, - float aspect) +persp_mat (float *proj, float fov, float aspect) { - float fovx, fovy, neard, fard; + float f = 1 / tan (fov * M_PI / 360); + float neard, fard; - fovx = r_refdef.fov_x; - fovy = r_refdef.fov_y; neard = r_nearclip->value; fard = r_farclip->value; - ymax = neard * tan (fovy * M_PI / 360); // fov_2 / 2 - ymin = -ymax; - xmax = neard * tan (fovx * M_PI / 360); // fov_2 / 2 - xmin = -xmax; - - proj[0] = (2 * neard) / (xmax - xmin); + proj[0] = f / aspect; proj[4] = 0; - proj[8] = (xmax + xmin) / (xmax - xmin); + proj[8] = 0; proj[12] = 0; proj[1] = 0; - proj[5] = -(2 * neard) / (ymax - ymin); - proj[9] = (ymax + ymin) / (ymax - ymin); + proj[5] = -f; + proj[9] = 0; proj[13] = 0; proj[2] = 0; proj[6] = 0; - proj[10] = (fard) / (neard - fard); - proj[14] = (fard * neard) / (neard - fard); + proj[10] = fard / (neard - fard); + proj[14] = (neard * fard) / (neard - fard); proj[3] = 0; proj[7] = 0; @@ -163,7 +156,7 @@ Vulkan_CreateMatrices (vulkan_ctx_t *ctx) } void -Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx, float aspect) +Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -172,9 +165,10 @@ Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx, float aspect) int width = vid.conwidth; int height = vid.conheight; - ortho_mat (mat->projection_2d, 0, width, 0, height, -99999, 99999); - persp_mat (mat->projection_3d, 0, width, 0, height, aspect); + + float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; + persp_mat (mat->projection_3d, r_refdef.fov_y, aspect); #if 0 Sys_MaskPrintf (SYS_vulkan, "ortho:\n"); Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n", diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 71f7977ef..25b4b6d27 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -60,31 +60,9 @@ VISIBLE unsigned int d_8to24table[256]; /* Screen size */ cvar_t *vid_width; cvar_t *vid_height; -cvar_t *vid_aspect; cvar_t *vid_fullscreen; -static void -vid_aspect_f (cvar_t *var) -{ - const char *p = strchr (var->string, ':'); - float w, h; - - if (p) { - w = atof (var->string); - h = atof (p + 1); - if (w > 0.0 && h > 0.0) { - var->vec[0] = w; - var->vec[1] = h; - return; - } - } - Sys_Printf ("badly formed aspect ratio: %s. Using default 4:3\n", - var->string); - var->vec[0] = 4.0; - var->vec[1] = 3.0; -} - void VID_GetWindowSize (int def_w, int def_h) { @@ -94,11 +72,6 @@ VID_GetWindowSize (int def_w, int def_h) "screen width"); vid_height = Cvar_Get ("vid_height", va (0, "%d", def_h), CVAR_NONE, NULL, "screen height"); - vid_aspect = Cvar_Get ("vid_aspect", "4:3", CVAR_ROM, vid_aspect_f, - "Physical screen aspect ratio in \"width:height\" format. " - "Common values are 4:3, 5:3, 8:5, 16:9, but any width:height " - "measurement will do (eg, 475:296.875 the approximate dimentions " - "in mm of the display area of a certain monitor)"); if ((pnum = COM_CheckParm ("-width"))) { if (pnum >= com_argc - 1) @@ -140,9 +113,6 @@ VID_GetWindowSize (int def_w, int def_h) viddef.width = vid_width->int_val; viddef.height = vid_height->int_val; - viddef.aspect = ((vid_aspect->vec[0] * viddef.height) - / (vid_aspect->vec[1] * viddef.width)); - con_width = Cvar_Get ("con_width", va (0, "%d", viddef.width), CVAR_NONE, NULL, "console effective width (GL only)"); if ((pnum = COM_CheckParm ("-conwidth"))) { @@ -155,7 +125,7 @@ VID_GetWindowSize (int def_w, int def_h) Cvar_SetFlags (con_width, con_width->flags | CVAR_ROM); viddef.conwidth = con_width->int_val; - conheight = (viddef.conwidth * vid_aspect->vec[1]) / vid_aspect->vec[0]; + conheight = (viddef.conwidth * viddef.height) / viddef.width; con_height = Cvar_Get ("con_height", va (0, "%d", conheight), CVAR_NONE, NULL, "console effective height (GL only)"); if ((pnum = COM_CheckParm ("-conheight"))) { diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 1e299d252..09dc8090f 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -44,20 +44,12 @@ static byte backingbuf[48 * 24]; void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { - int i, j, reps, repshift; + int i, j, reps = 1, repshift = 0; vrect_t rect; if (!viddef.initialized || !win_sw_context) return; - if (viddef.aspect > 1.5) { - reps = 2; - repshift = 1; - } else { - reps = 1; - repshift = 0; - } - if (!viddef.direct) return; @@ -86,20 +78,12 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) void D_EndDirectRect (int x, int y, int width, int height) { - int i, j, reps, repshift; + int i, j, reps = 1, repshift = 0; vrect_t rect; if (!viddef.initialized || !win_sw_context) return; - if (viddef.aspect > 1.5) { - reps = 2; - repshift = 1; - } else { - reps = 1; - repshift = 0; - } - if (!viddef.direct) return; From 612eb49d9cd472b1f43a41ce6d9700e66a56b06f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Apr 2021 19:40:25 +0900 Subject: [PATCH 1491/3664] [render] Separate fov x and y calculations This ensures that fov_y is not calculated until after the render view size is known and thus doesn't become some crazy angle (that happens to result in a negative tan). Fixes upside-down-quake :) --- libs/video/renderer/r_screen.c | 45 +++++++++++++++------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 5748d7274..c4bf94ea1 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -110,8 +110,6 @@ vrect_t scr_vrect; qboolean scr_skipupdate; -static float oldfov = -1; - void R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) { @@ -144,12 +142,32 @@ R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) vrect->y = (h - vrect->height) / 2; } +static float __attribute__((pure)) +CalcFov (float fov_x, float width, float height) +{ + float a, x; + + if (fov_x < 1 || fov_x > 179) + Sys_Error ("Bad fov: %f", fov_x); + + x = width / tan (fov_x * (M_PI / 360)); + + a = (x == 0) ? 90 : atan (height / x); // 0 shouldn't happen + + a = a * (360 / M_PI); + + return a; +} + void SCR_CalcRefdef (void) { vrect_t vrect; refdef_t *refdef = r_data->refdef; + refdef->fov_y = CalcFov (refdef->fov_x, refdef->vrect.width, + refdef->vrect.height); + // force a background redraw r_data->scr_fullupdate = 0; r_data->vid->recalc_refdef = 0; @@ -189,11 +207,6 @@ SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) r_data->realtime = realtime; scr_copytop = r_data->scr_copyeverything = 0; - if (oldfov != scr_fov->value) { - oldfov = scr_fov->value; - r_data->vid->recalc_refdef = true; - } - if (r_data->vid->recalc_refdef) { SCR_CalcRefdef (); } @@ -201,29 +214,11 @@ SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) r_funcs->R_RenderFrame (scr_3dfunc, scr_funcs); } -static float __attribute__((pure)) -CalcFov (float fov_x, float width, float height) -{ - float a, x; - - if (fov_x < 1 || fov_x > 179) - Sys_Error ("Bad fov: %f", fov_x); - - x = width / tan (fov_x * (M_PI / 360)); - - a = (x == 0) ? 90 : atan (height / x); // 0 shouldn't happen - - a = a * (360 / M_PI); - - return a; -} - void SCR_SetFOV (float fov) { refdef_t *refdef = r_data->refdef; refdef->fov_x = fov; - refdef->fov_y = CalcFov (fov, refdef->vrect.width, refdef->vrect.height); r_data->vid->recalc_refdef = 1; } From b2ec1aaf37b8e5b9873934a978922ed3f22b266d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Apr 2021 20:07:37 +0900 Subject: [PATCH 1492/3664] [build] Disable SDL by default Finally, there is no more need to keep it (though I won't nuke the support just yet) as native windows support is now working. --- config.d/build_control.m4 | 17 +++++++++-------- config.d/sdl.m4 | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index e5800c31b..9f7e9d1ab 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -119,14 +119,6 @@ if test "x$HAVE_SDL" = xyes; then NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA desktop/quakeforge-nq-sdl.desktop" CL_TARGETS="$CL_TARGETS SDL" VID_TARGETS="$VID_TARGETS libs/video/targets/libQFsdl.la" - if test "$HAVE_VULKAN" = "yes"; then - QF_NEED(vid_render, [vulkan]) - QF_NEED(render, [vulkan]) - QF_NEED(alias, [vulkan]) - QF_NEED(brush, [vulkan]) - QF_NEED(iqm, [vulkan]) - QF_NEED(sprite, [vulkan]) - fi QF_NEED(vid_render, [sw sw32 gl glsl]) QF_NEED(render, [sw sw32 gl glsl]) QF_NEED(models, [sw gl glsl]) @@ -173,6 +165,15 @@ if test "x$mingw" = xyes; then NQ_TARGETS="$NQ_TARGETS nq-win\$(EXEEXT)" CL_TARGETS="$CL_TARGETS WIN" VID_TARGETS="$VID_TARGETS libs/video/targets/libQFwin.la" + if test "$HAVE_VULKAN" = "yes"; then + QF_NEED(vid_render, [vulkan]) + QF_NEED(render, [vulkan]) + QF_NEED(models, [vulkan]) + QF_NEED(alias, [vulkan]) + QF_NEED(brush, [vulkan]) + QF_NEED(iqm, [vulkan]) + QF_NEED(sprite, [vulkan]) + fi QF_NEED(vid_render, [sw sw32 gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) diff --git a/config.d/sdl.m4 b/config.d/sdl.m4 index 09b49e157..044faa513 100644 --- a/config.d/sdl.m4 +++ b/config.d/sdl.m4 @@ -1,9 +1,9 @@ dnl SDL/SDL-GL checks AC_ARG_ENABLE(sdl, -[ --disable-sdl disable checking for SDL], +[ --enable-sdl enable checking for SDL], ) -if test "x$enable_sdl" != xno; then +if test "x$enable_sdl" = xyes; then if test "x$PKG_CONFIG" != "x"; then PKG_CHECK_MODULES([SDL], [sdl >= 1.2.0], HAVE_SDL=yes, HAVE_SDL=no) else From 2d67bcacd75845d8ddf8ae59517b20ee4259e813 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Apr 2021 08:46:22 +0900 Subject: [PATCH 1493/3664] [vulkan] Use cleaner bsp glow texture handling It was always a bit of a hack, and it didn't work for 32-bit builds. --- include/r_internal.h | 1 + libs/models/brush/vulkan_model_brush.c | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/include/r_internal.h b/include/r_internal.h index 89a8d9cb4..58a4e7599 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -35,6 +35,7 @@ typedef struct vulktex_s { struct elechain_s **elechain_tail; struct qfv_tex_s *tex; struct qfv_tex_s *glow; + byte *glow_pixels; } vulktex_t; extern viddef_t vid; // global video state diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 9527a2abe..711027b7c 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -236,7 +236,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) va (ctx->va_ctx, "iview:%s:%s:tex", mod->name, tx->name)); transfer_mips (buffer + tex->tex->offset, tx + 1, tx, palette); - if (tex->glow) { + if (tex->glow_pixels) { dfunc->vkBindImageMemory (device->dev, tex->glow->image, mem, tex->glow->offset); // skys are unlit so never have a glow texture thus glow @@ -249,7 +249,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) tex->glow->view, va (ctx->va_ctx, "iview:%s:%s:glow", mod->name, tx->name)); - transfer_mips (buffer + tex->glow->offset, tex->glow->memory, tx, + transfer_mips (buffer + tex->glow->offset, tex->glow_pixels, tx, palette); } } @@ -380,10 +380,7 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) tex->glow->image, va (ctx->va_ctx, "image:%s:%s:glow", mod->name, tx->name)); - // store the pointer to the fullbright data: memory will never be set to - // actual device memory because all of the textures will be loaded in one - // big buffer - tex->glow->memory = (VkDeviceMemory) pixels; + tex->glow_pixels = pixels; } void From c9f9c1e36b2df80d9c94f0ccbadb3c39189c450e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Apr 2021 08:46:48 +0900 Subject: [PATCH 1494/3664] [util] Make cmem.h more portable 32-bit size_t doesn't like 64-bit bit-fields. More testing needed to see if cmem works properly (mostly alignment) on 32-bit system. --- include/QF/cmem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/cmem.h b/include/QF/cmem.h index 1f81bf298..a6520d1cf 100644 --- a/include/QF/cmem.h +++ b/include/QF/cmem.h @@ -54,7 +54,7 @@ typedef struct memsline_s { struct memsline_s *next; size_t size:2; size_t list:4; - size_t prev:58; // memsline_t ** + size_t prev:8 * sizeof (void *) - 6; // memsline_t ** } memsline_t; typedef struct memblock_s { From e50a079f727528f989771beedb2b18569c60c6fa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Apr 2021 08:48:11 +0900 Subject: [PATCH 1495/3664] [vulkan] Fix some 32-bit compatibility issues mostly dealing with vulkan's handles always being 64-bit, but pointers being either 32 or 64. --- include/QF/Vulkan/debug.h | 14 ++++++++++++++ libs/video/renderer/vid_render_vulkan.c | 7 ++++--- libs/video/renderer/vulkan/vkparse.c | 4 ++-- libs/video/renderer/vulkan/vulkan_alias.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/debug.h b/include/QF/Vulkan/debug.h index 3250d5aca..1e25930d0 100644 --- a/include/QF/Vulkan/debug.h +++ b/include/QF/Vulkan/debug.h @@ -1,6 +1,19 @@ #ifndef __QF_Vulkan_debug_h #define __QF_Vulkan_debug_h +#if defined(_WIN32) && !defined(_WIN64) +#define QFV_duCmdBeginLabel(device, cmd, name...) +#define QFV_duCmdEndLabel(device, cmd) +#define QFV_duCmdInsertLabel(device, cmd, name...) +#define QFV_duCreateMessenger(inst, severity, type, callback, data, messenger) +#define QFV_duDestroyMessenger(inst, messenger) +#define QFV_duQueueBeginLabel(device, queue, name...) +#define QFV_duQueueEndLabel(device, queue) +#define QFV_duQueueInsertLabel(device, queue, name...) +#define QFV_duSetObjectName(device, type, handle, name) +#define QFV_duSetObjectTag(device, type, handle, name, size, tag) +#define QFV_duSubmitMessage(inst, severity, types, data) +#else #define QFV_duCmdBeginLabel(device, cmd, name...)\ do { \ qfv_devfuncs_t *dfunc = device->funcs; \ @@ -111,5 +124,6 @@ data); \ } \ } while (0) +#endif #endif//__QF_Vulkan_debug_h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 21af94eb1..5436fcc9f 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -619,10 +619,10 @@ vulkan_vid_render_choose_visual (void) cmdset); vulkan_ctx->cmdbuffer = cmdset->a[0]; vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1); - Sys_MaskPrintf (SYS_vulkan, "vk choose visual %p %p %d %p\n", + Sys_MaskPrintf (SYS_vulkan, "vk choose visual %p %p %d %#zx\n", vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue, vulkan_ctx->device->queue.queueFamily, - vulkan_ctx->cmdpool); + (size_t) vulkan_ctx->cmdpool); } static void @@ -630,7 +630,8 @@ vulkan_vid_render_create_context (void) { vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); - Sys_MaskPrintf (SYS_vulkan, "vk create context %p\n", vulkan_ctx->surface); + Sys_MaskPrintf (SYS_vulkan, "vk create context %#zx\n", + (size_t) vulkan_ctx->surface); } static void diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 7085ac7ea..15218e93c 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1345,8 +1345,8 @@ QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) VkFramebuffer framebuffer; dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); - Sys_MaskPrintf (SYS_vulkan_parse, "framebuffer, renderPass: %p, %p\n", - framebuffer, cInfo.renderPass); + Sys_MaskPrintf (SYS_vulkan_parse, "framebuffer, renderPass: %#zx, %#zx\n", + (size_t) framebuffer, (size_t) cInfo.renderPass); delete_memsuper (memsuper); return framebuffer; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 1e104fbef..b00814427 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -64,7 +64,7 @@ #include "r_internal.h" #include "vid_vulkan.h" -static const char *alias_pass_names[] = { +static const char * __attribute__((used)) alias_pass_names[] = { "depth", "g-buffer", "translucent", diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 5e2d4dfd0..07d573caa 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -69,7 +69,7 @@ #include "r_internal.h" #include "vid_vulkan.h" -static const char *bsp_pass_names[] = { +static const char * __attribute__((used)) bsp_pass_names[] = { "depth", "g-buffer", "sky", From 18247a8c8e23676e7048409fd5075cf607c943d4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Apr 2021 08:55:16 +0900 Subject: [PATCH 1496/3664] [tools] Fix up 32-bit cross-compile scripts --- tools/cross/mingw/cross-configure.sh | 11 ++++++----- tools/cross/mingw/cross-make.sh | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tools/cross/mingw/cross-configure.sh b/tools/cross/mingw/cross-configure.sh index 67287e4f1..aae082435 100755 --- a/tools/cross/mingw/cross-configure.sh +++ b/tools/cross/mingw/cross-configure.sh @@ -1,19 +1,20 @@ #!/bin/sh -x set -e -mkdir -p native i686-pc-mingw32 +mkdir -p native i686-w64-mingw32.static cd native ../../configure \ + --enable-silent-rules \ --disable-shared \ --without-clients \ --without-servers \ - --with-tools=qfcc,pak -cd ../i686-pc-mingw32 + --with-tools=qfcc,pak,qwaq +cd ../i686-w64-mingw32.static export MINGW=/opt/mxe -export MINGW_USR=$MINGW/usr/i686-pc-mingw32 +export MINGW_USR=$MINGW/usr/i686-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH ../../configure \ - --host=i686-pc-mingw32 \ + --host=i686-w64-mingw32.static \ --disable-shared \ $* diff --git a/tools/cross/mingw/cross-make.sh b/tools/cross/mingw/cross-make.sh index 61d0fe7f4..d2906a32b 100755 --- a/tools/cross/mingw/cross-make.sh +++ b/tools/cross/mingw/cross-make.sh @@ -3,14 +3,15 @@ set -e if test -d native; then cd native make $* - cd ../i686-pc-mingw32 - ln -fs ../native/tools/qfcc/source/qfcc . - ln -fs ../native/tools/pak/pak . + cd ../i686-w64-mingw32.static + ln -fs ../native/qfcc . + ln -fs ../native/pak . + ln -fs ../native/ruamoko/qwaq/qwaq-curses . fi export MINGW=/opt/mxe -export MINGW_USR=$MINGW/usr/i686-pc-mingw32 +export MINGW_USR=$MINGW/usr/i686-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH -make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' $* +make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ_CURSES='$(top_builddir)/qwaq-curses' $* From 37be6a23a2412fe2fc36245e9e2840f71d35f970 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Apr 2021 21:02:14 +0900 Subject: [PATCH 1497/3664] [entity] Use _aligned_malloc etc for _WIN32 This is a bit of a hack for now (need to look into maybe using cmem), but it gets 32-bit windows working for all but the software renderer (probably just refdef (and maybe viddef) getting out of sync with the assembly code. --- libs/entity/hierarchy.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libs/entity/hierarchy.c b/libs/entity/hierarchy.c index cadb3771c..39d4ed971 100644 --- a/libs/entity/hierarchy.c +++ b/libs/entity/hierarchy.c @@ -37,6 +37,17 @@ #include "QF/entity.h" +#if defined(_WIN32) && !defined(_WIN64) +// FIXME (maybe) this is a hack to make DARRAY arrrays 16-byte aligned on +// 32-bit systems (in particular for this case, windows) as the vectors and +// matrices require 16-byte alignment but system malloc (etc) provide only +// 8-byte alignment. +// Really, a custom allocator (maybe using cmem) would be better. +#define free(mem) _aligned_free(mem) +#define malloc(size) _aligned_malloc(size, 16) +#define realloc(mem, size) _aligned_realloc(mem, size, 16) +#endif + static void hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, int offset) From 39103cc8a3737f253b267a5020f809a11d414b1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Apr 2021 22:17:32 +0900 Subject: [PATCH 1498/3664] [sw] Fix some 32-bit assembly issues I'm not sure that the mismatch between refdef_t and the assembly defines was a problem (many fields unused), but the main problem was due to execute permission on the pages: one chunk of asm was in the data section, and the patched code was not marked as being executable (due to such a thing not existing when quake was written). --- include/QF/render.h | 4 ++-- include/asm_draw.h | 26 ++++++++++++++------------ include/d_local.h | 3 +-- include/r_local.h | 3 +-- include/r_shared.h | 6 ++---- libs/util/sys.c | 2 +- libs/video/renderer/sw/sw_rvarsa.S | 1 + 7 files changed, 22 insertions(+), 23 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index adc5e141e..3b86c9038 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -161,9 +161,9 @@ typedef struct { vec4f_t viewposition; vec4f_t viewrotation; - float fov_x, fov_y; - int ambientlight; + + float fov_x, fov_y; } refdef_t; // color shifts ============================================================= diff --git a/include/asm_draw.h b/include/asm_draw.h index ec6d99283..1e2ae1da4 100644 --- a/include/asm_draw.h +++ b/include/asm_draw.h @@ -42,14 +42,14 @@ #define espan_t_v 4 #define espan_t_count 8 #define espan_t_pnext 12 -#define espan_t_size 16 +#define espan_t_size 16 // sizeof(espan_t) // sspan_t structure // !!! if this is changed, it must be changed in d_local.h too !!! #define sspan_t_u 0 #define sspan_t_v 4 #define sspan_t_count 8 -#define sspan_t_size 12 +#define sspan_t_size 12 // sizeof(sspan_t) // spanpackage_t structure // !!! if this is changed, it must be changed in d_polyset.c too !!! @@ -61,7 +61,7 @@ #define spanpackage_t_tfrac 20 #define spanpackage_t_light 24 #define spanpackage_t_zi 28 -#define spanpackage_t_size 32 +#define spanpackage_t_size 32 // sizeof(spanpackage_t) // edge_t structure // !!! if this is changed, it must be changed in r_shared.h too !!! @@ -73,7 +73,7 @@ #define et_nextremove 20 #define et_nearzi 24 #define et_owner 28 -#define et_size 32 +#define et_size 32 // sizeof(edge_t) // surf_t structure // !!! if this is changed, it must be changed in r_shared.h too !!! @@ -93,7 +93,7 @@ #define st_d_zistepu 48 #define st_d_zistepv 52 #define st_pad 56 -#define st_size 64 +#define st_size 64 // sizeof (surf_t) // clipplane_t structure // !!! if this is changed, it must be changed in r_local.h too !!! @@ -103,18 +103,18 @@ #define cp_leftedge 20 #define cp_rightedge 21 #define cp_reserved 22 -#define cp_size 24 +#define cp_size 24 // sizeof (clipplane_t) // medge_t structure // !!! if this is changed, it must be changed in model.h too !!! #define me_v 0 #define me_cachededgeoffset 8 -#define me_size 12 +#define me_size 12 // sizeof (medge_t) // mvertex_t structure // !!! if this is changed, it must be changed in model.h too !!! #define mv_position 0 -#define mv_size 12 +#define mv_size 12 // sizeof (mvertex_t) // refdef_t structure // !!! if this is changed, it must be changed in render.h too !!! @@ -138,10 +138,12 @@ #define rd_horizontalFieldOfView 100 #define rd_xOrigin 104 #define rd_yOrigin 108 -#define rd_vieworg 112 -#define rd_viewangles 124 -#define rd_ambientlight 136 -#define rd_size 140 +#define rd_viewposition 112 +#define rd_viewrotation 128 +#define rd_ambientlight 144 +#defin rd_fov_x 148 +#defin rd_fov_y 152 +#define rd_size 156 // sizeof (refdef_t) // mtriangle_t structure // !!! if this is changed, it must be changed in model.h too !!! diff --git a/include/d_local.h b/include/d_local.h index 7143277b1..f67dcea74 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -59,8 +59,7 @@ typedef struct surfcache_s } surfcache_t; // !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct sspan_s -{ +typedef struct sspan_s { int u, v, count; } sspan_t; diff --git a/include/r_local.h b/include/r_local.h index 37d5308c1..ba8063561 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -98,8 +98,7 @@ extern float cl_wateralpha; #define DIST_NOT_SET 98765 // !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct clipplane_s -{ +typedef struct clipplane_s { vec3_t normal; float dist; struct clipplane_s *next; diff --git a/include/r_shared.h b/include/r_shared.h index 521024d68..b39e387f8 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -81,16 +81,14 @@ extern struct entity_s *currententity; #define MAXSPANS 3000 // !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct espan_s -{ +typedef struct espan_s { int u, v, count; struct espan_s *pnext; } espan_t; // FIXME: compress, make a union if that will help // insubmodel is only 1, flags is fewer than 32, spanstate could be a byte -typedef struct surf_s -{ +typedef struct surf_s { struct surf_s *next; // active surface stack in r_edge.c struct surf_s *prev; // used in r_edge.c for active surf stack struct espan_s *spans; // pointer to linked list of spans to draw diff --git a/libs/util/sys.c b/libs/util/sys.c index cada787f2..8758f270a 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -437,7 +437,7 @@ Sys_MakeCodeWriteable (uintptr_t startaddr, size_t length) DWORD flOldProtect; if (!VirtualProtect - ((LPVOID) startaddr, length, PAGE_READWRITE, &flOldProtect)) + ((LPVOID) startaddr, length, PAGE_EXECUTE_READWRITE, &flOldProtect)) Sys_Error ("Protection change failed"); #else # ifdef HAVE_MPROTECT diff --git a/libs/video/renderer/sw/sw_rvarsa.S b/libs/video/renderer/sw/sw_rvarsa.S index c53d26cf1..be32f8918 100644 --- a/libs/video/renderer/sw/sw_rvarsa.S +++ b/libs/video/renderer/sw/sw_rvarsa.S @@ -76,6 +76,7 @@ C(r_single_cw): .long 0 .globl C(r_bmodelactive) C(r_bmodelactive): .long 0 + .text .global C(R_InitVars) C(R_InitVars): movl C(ceil_cw), %eax From 9ac4cdc6bd6a17fd1308ebd426fff2ed6cc5de1d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Apr 2021 23:25:14 +0900 Subject: [PATCH 1499/3664] [simd] Fix more portability issues I had missed vec4d.h because it's mostly unused at this stage. --- include/QF/simd/vec4d.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 93b0667c9..01fa42d88 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -93,8 +93,8 @@ GNU89INLINE inline vec4d_t qrotd (vec4d_t a, vec4d_t b) __attribute__((const)); * That is, [-x, -y, -z, w]. */ GNU89INLINE inline vec4d_t qconjd (vec4d_t q) __attribute__((const)); -GNU89INLINE inline vec4d_t loadvec3d (const double v3[]) __attribute__((pure, access(read_only, 1))); -GNU89INLINE inline void storevec3d (double v3[3], vec4d_t v4) __attribute__((access (write_only, 1))); +GNU89INLINE inline vec4d_t loadvec3d (const double v3[]) __attribute__((pure)); +GNU89INLINE inline void storevec3d (double v3[3], vec4d_t v4); #ifndef IMPLEMENT_VEC4D_Funcs GNU89INLINE inline From 64bfaeca6c1308a98af8b5ad9ba3ef0706ef69d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 3 Apr 2021 00:06:54 +0900 Subject: [PATCH 1500/3664] [vulkan] Skip values array for empty enum symtabs Fixes an unused warning/error when the enum has no interesting values (eg, VkRenderPassCreateFlagBits on older versions of the vulkan api). --- libs/video/renderer/vulkan/vkgen/vkenum.r | 34 +++++++++++++++++------ 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index b4dc8b79f..c51fcbfac 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -65,6 +65,20 @@ skip_value(string name) || str_str (name, "_RANGE_SIZE") >= 0); } +-(int) isEmpty +{ + int num_values = 0; + + for (int i = 0, index = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (skip_value (var.name)) { + continue; + } + num_values++; + } + return !num_values; +} + -(void) writeTable { int strip_bit = 0; @@ -84,17 +98,19 @@ skip_value(string name) } fprintf (output_file, "};\n"); - fprintf (output_file, "static %s %s_values[] = {\n", [self name], [self name]); - for (int i = 0, index = 0; i < type.strct.num_fields; i++) { - qfot_var_t *var = &type.strct.fields[i]; - if (skip_value (var.name)) { - continue; + if (![self isEmpty]) { + fprintf (output_file, "static %s %s_values[] = {\n", [self name], [self name]); + for (int i = 0, index = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (skip_value (var.name)) { + continue; + } + fprintf (output_file, "\t%s, // %d 0x%x\n", + var.name, var.offset, var.offset); + index++; } - fprintf (output_file, "\t%s, // %d 0x%x\n", - var.name, var.offset, var.offset); - index++; + fprintf (output_file, "};\n"); } - fprintf (output_file, "};\n"); fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self name]); for (int i = 0, index = 0; i < type.strct.num_fields; i++) { qfot_var_t *var = &type.strct.fields[i]; From a5df5867b68ca2cbb5629f6dd5285e9c25210434 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 3 Apr 2021 00:14:49 +0900 Subject: [PATCH 1501/3664] [qwaq] Avoid ignored return val warning If those particular writes file (and it matters), we probably have bigger problems. --- ruamoko/qwaq/builtins/input.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index afe96a2ec..fe2580fd2 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -445,16 +445,16 @@ void qwaq_input_init (qwaq_resources_t *res) // ncurses takes care of input mode for us, so need only tell xterm // what we need - write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); - write(1, SGR_ON, sizeof (SGR_ON) - 1); + (void) write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); + (void) write(1, SGR_ON, sizeof (SGR_ON) - 1); } void qwaq_input_shutdown (qwaq_resources_t *res) { // ncurses takes care of input mode for us, so need only tell xterm // what we need - write(1, SGR_OFF, sizeof (SGR_OFF) - 1); - write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); + (void) write(1, SGR_OFF, sizeof (SGR_OFF) - 1); + (void) write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); #ifdef HAVE_SIGACTION sigaction (SIGWINCH, &save_winch, 0); From 6e9ee98e88488ecd980ba186ae50cb76e48b6877 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 3 Apr 2021 00:16:25 +0900 Subject: [PATCH 1502/3664] [models] Add floodfill.c to the vulkan alias lib Many thanks to JohnnyonFlame for his testing on a different system. --- libs/models/alias/Makemodule.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/models/alias/Makemodule.am b/libs/models/alias/Makemodule.am index cac8d4a09..71601b573 100644 --- a/libs/models/alias/Makemodule.am +++ b/libs/models/alias/Makemodule.am @@ -9,7 +9,7 @@ alias_src= libs/models/alias/model_alias.c alias_gl_src= libs/models/alias/gl_mesh.c libs/models/alias/gl_model_alias.c libs/models/alias/floodfill.c alias_glsl_src= libs/models/alias/glsl_model_alias.c libs/models/alias/floodfill.c alias_sw_src= libs/models/alias/sw_model_alias.c -alias_vulkan_src= libs/models/alias/vulkan_model_alias.c +alias_vulkan_src= libs/models/alias/vulkan_model_alias.c libs/models/alias/floodfill.c libs_models_alias_libalias_gl_la_SOURCES= $(alias_gl_src) $(alias_src) From 7e6928d7d5ba55a575778a56167986a1cb08683a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 3 Apr 2021 00:27:43 +0900 Subject: [PATCH 1503/3664] [qwaq] Work around a gcc non-conformance *sigh* --- ruamoko/qwaq/builtins/input.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index fe2580fd2..67d491cc8 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -445,16 +445,16 @@ void qwaq_input_init (qwaq_resources_t *res) // ncurses takes care of input mode for us, so need only tell xterm // what we need - (void) write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); - (void) write(1, SGR_ON, sizeof (SGR_ON) - 1); + (void) !write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); + (void) !write(1, SGR_ON, sizeof (SGR_ON) - 1); } void qwaq_input_shutdown (qwaq_resources_t *res) { // ncurses takes care of input mode for us, so need only tell xterm // what we need - (void) write(1, SGR_OFF, sizeof (SGR_OFF) - 1); - (void) write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); + (void) !write(1, SGR_OFF, sizeof (SGR_OFF) - 1); + (void) !write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); #ifdef HAVE_SIGACTION sigaction (SIGWINCH, &save_winch, 0); From e2f545eb23baadaf74f2216c22296d3cabaef954 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 3 Apr 2021 01:14:44 +0900 Subject: [PATCH 1504/3664] [vulkan] Wait on device idle before deleting models This fixes the textures (and presumably mesh data) being deleted while still in use. Oddly, the wait was needed in both brush and alias models (I expected brush to always come first). --- libs/models/alias/vulkan_model_alias.c | 2 ++ libs/models/brush/vulkan_model_brush.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index fd1f8c731..27971ad56 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -83,6 +83,8 @@ vulkan_alias_clear (model_t *m, void *data) aliashdr_t *hdr; qfv_alias_mesh_t *mesh; + QFV_DeviceWaitIdle (device); + m->needload = true; //FIXME is this right? if (!(hdr = m->aliashdr)) { hdr = Cache_Get (&m->cache); diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 711027b7c..e0211b01a 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -71,6 +71,8 @@ static void vulkan_brush_clear (model_t *mod, void *data) qfv_devfuncs_t *dfunc = device->funcs; mod_brush_t *brush = &mod->brush; + QFV_DeviceWaitIdle (device); + for (int i = 0; i < brush->numtextures; i++) { texture_t *tx = brush->textures[i]; if (!tx) { From 658890d6819026d2221d54eaa9e3c9091dbc5477 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 12:20:01 +0900 Subject: [PATCH 1505/3664] [net] Clean up some formatting Doing this before attacking the actual code (lots of potential buffer overflows and possibly unnecessary code). --- libs/net/nm/net_dgrm.c | 380 ++++++++++++++++++++++++----------------- 1 file changed, 228 insertions(+), 152 deletions(-) diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 1f55dea80..a230cc09b 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -83,8 +83,8 @@ int droppedDatagrams; static int myDriverLevel; struct { - unsigned int length; - unsigned int sequence; + unsigned length; + unsigned sequence; byte data[MAX_DATAGRAM]; } packetBuffer; @@ -113,40 +113,43 @@ NET_Ban_f (void) } print = Sys_Printf; } else { - if (*sv_globals.deathmatch - && !host_client->privileged) return; + if (*sv_globals.deathmatch && !host_client->privileged) { + return; + } print = SV_ClientPrintf; } switch (Cmd_Argc ()) { case 1: - if (banAddr) { - struct in_addr t; - t.s_addr = banAddr; - strcpy (addrStr, inet_ntoa (t)); - t.s_addr = banMask; - strcpy (maskStr, inet_ntoa (t)); - print ("Banning %s [%s]\n", addrStr, maskStr); - } else - print ("Banning not active\n"); - break; + if (banAddr) { + struct in_addr t; + t.s_addr = banAddr; + strcpy (addrStr, inet_ntoa (t)); + t.s_addr = banMask; + strcpy (maskStr, inet_ntoa (t)); + print ("Banning %s [%s]\n", addrStr, maskStr); + } else { + print ("Banning not active\n"); + } + break; case 2: - if (strcasecmp (Cmd_Argv (1), "off") == 0) - banAddr = 0x00000000; - else - banAddr = inet_addr (Cmd_Argv (1)); - banMask = 0xffffffff; - break; + if (strcasecmp (Cmd_Argv (1), "off") == 0) { + banAddr = 0x00000000; + } else { + banAddr = inet_addr (Cmd_Argv (1)); + } + banMask = 0xffffffff; + break; case 3: - banAddr = inet_addr (Cmd_Argv (1)); - banMask = inet_addr (Cmd_Argv (2)); - break; + banAddr = inet_addr (Cmd_Argv (1)); + banMask = inet_addr (Cmd_Argv (2)); + break; default: - print ("BAN ip_address [mask]\n"); - break; + print ("BAN ip_address [mask]\n"); + break; } } #endif @@ -155,9 +158,9 @@ NET_Ban_f (void) int Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) { - unsigned int packetLen; - unsigned int dataLen; - unsigned int eom; + unsigned packetLen; + unsigned dataLen; + unsigned eom; memcpy (sock->sendMessage, data->data, data->cursize); @@ -179,8 +182,9 @@ Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) sock->canSend = false; if (sfunc.Write (sock->socket, (byte *) & packetBuffer, packetLen, - &sock->addr) == -1) + &sock->addr) == -1) { return -1; + } sock->lastSendTime = net_time; packetsSent++; @@ -191,9 +195,9 @@ Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) static int SendMessageNext (qsocket_t *sock) { - unsigned int packetLen; - unsigned int dataLen; - unsigned int eom; + unsigned packetLen; + unsigned dataLen; + unsigned eom; if (sock->sendMessageLength <= MAX_DATAGRAM) { dataLen = sock->sendMessageLength; @@ -210,9 +214,10 @@ SendMessageNext (qsocket_t *sock) sock->sendNext = false; - if (sfunc.Write (sock->socket, (byte *) & packetBuffer, packetLen, - &sock->addr) == -1) + if (sfunc.Write (sock->socket, (byte *) &packetBuffer, packetLen, + &sock->addr) == -1) { return -1; + } sock->lastSendTime = net_time; packetsSent++; @@ -223,9 +228,9 @@ SendMessageNext (qsocket_t *sock) static int ReSendMessage (qsocket_t *sock) { - unsigned int packetLen; - unsigned int dataLen; - unsigned int eom; + unsigned packetLen; + unsigned dataLen; + unsigned eom; if (sock->sendMessageLength <= MAX_DATAGRAM) { dataLen = sock->sendMessageLength; @@ -242,9 +247,10 @@ ReSendMessage (qsocket_t *sock) sock->sendNext = false; - if (sfunc.Write (sock->socket, (byte *) & packetBuffer, packetLen, - &sock->addr) == -1) + if (sfunc.Write (sock->socket, (byte *) &packetBuffer, packetLen, + &sock->addr) == -1) { return -1; + } sock->lastSendTime = net_time; packetsReSent++; @@ -255,8 +261,9 @@ ReSendMessage (qsocket_t *sock) qboolean Datagram_CanSendMessage (qsocket_t *sock) { - if (sock->sendNext) + if (sock->sendNext) { SendMessageNext (sock); + } return sock->canSend; } @@ -280,9 +287,10 @@ Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) packetBuffer.sequence = BigLong (sock->unreliableSendSequence++); memcpy (packetBuffer.data, data->data, data->cursize); - if (sfunc.Write (sock->socket, (byte *) & packetBuffer, packetLen, - &sock->addr) == -1) + if (sfunc.Write (sock->socket, (byte *) &packetBuffer, packetLen, + &sock->addr) == -1) { return -1; + } packetsSent++; return 1; @@ -292,29 +300,31 @@ Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) int Datagram_GetMessage (qsocket_t *sock) { - unsigned int length; - unsigned int flags; + unsigned length; + unsigned flags; int ret = 0; netadr_t readaddr; - unsigned int sequence; - unsigned int count; + unsigned sequence; + unsigned count; /// If there is an outstanding reliable packet and more than 1 second has /// passed, resend the packet. - if (!sock->canSend) - if ((net_time - sock->lastSendTime) > 1.0) + if (!sock->canSend) { + if ((net_time - sock->lastSendTime) > 1.0) { ReSendMessage (sock); + } + } while (1) { - length = - sfunc.Read (sock->socket, (byte *) &packetBuffer, NET_DATAGRAMSIZE, - &readaddr); + length = sfunc.Read (sock->socket, (byte *) &packetBuffer, + NET_DATAGRAMSIZE, &readaddr); // if ((rand() & 255) > 220) // continue; - if (length == 0) + if (length == 0) { break; + } if ((int) length == -1) { Sys_Printf ("Read error\n"); @@ -334,8 +344,9 @@ Datagram_GetMessage (qsocket_t *sock) flags = length & (~NETFLAG_LENGTH_MASK); length &= NETFLAG_LENGTH_MASK; - if (flags & NETFLAG_CTL) + if (flags & NETFLAG_CTL) { continue; + } sequence = BigLong (packetBuffer.sequence); packetsReceived++; @@ -370,8 +381,9 @@ Datagram_GetMessage (qsocket_t *sock) } if (sequence == sock->ackSequence) { sock->ackSequence++; - if (sock->ackSequence != sock->sendSequence) + if (sock->ackSequence != sock->sendSequence) { Sys_MaskPrintf (SYS_net, "ack sequencing error\n"); + } } else { Sys_MaskPrintf (SYS_net, "Duplicate ACK received\n"); continue; @@ -421,8 +433,9 @@ Datagram_GetMessage (qsocket_t *sock) } } - if (sock->sendNext) + if (sock->sendNext) { SendMessageNext (sock); + } return ret; } @@ -457,20 +470,28 @@ NET_Stats_f (void) Sys_Printf ("shortPacketCount = %i\n", shortPacketCount); Sys_Printf ("droppedDatagrams = %i\n", droppedDatagrams); } else if (strcmp (Cmd_Argv (1), "*") == 0) { - for (s = net_activeSockets; s; s = s->next) + for (s = net_activeSockets; s; s = s->next) { PrintStats (s); - for (s = net_freeSockets; s; s = s->next) + } + for (s = net_freeSockets; s; s = s->next) { PrintStats (s); + } } else { - for (s = net_activeSockets; s; s = s->next) - if (strcasecmp (Cmd_Argv (1), s->address) == 0) + for (s = net_activeSockets; s; s = s->next) { + if (strcasecmp (Cmd_Argv (1), s->address) == 0) { break; - if (s == NULL) - for (s = net_freeSockets; s; s = s->next) - if (strcasecmp (Cmd_Argv (1), s->address) == 0) + } + } + if (s == NULL) { + for (s = net_freeSockets; s; s = s->next) { + if (strcasecmp (Cmd_Argv (1), s->address) == 0) { break; - if (s == NULL) + } + } + } + if (s == NULL) { return; + } PrintStats (s); } } @@ -491,7 +512,7 @@ Test_Poll (void *unused) int control; int len; char name[32]; //FIXME: overflow - char address[64]; //FIXME: overflow + char address[64]; //FIXME: overflow int colors; int frags; int connectTime; @@ -500,26 +521,30 @@ Test_Poll (void *unused) net_landriverlevel = testDriver; while (1) { - len = - dfunc.Read (testSocket, net_message->message->data, - net_message->message->maxsize, &clientaddr); - if (len < (int) sizeof (int)) + len = dfunc.Read (testSocket, net_message->message->data, + net_message->message->maxsize, &clientaddr); + if (len < (int) sizeof (int)) { break; + } net_message->message->cursize = len; MSG_BeginReading (net_message); control = BigLong (*((int *) net_message->message->data)); MSG_ReadLong (net_message); - if (control == -1) + if (control == -1) { break; - if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) + } + if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) { break; - if ((control & NETFLAG_LENGTH_MASK) != len) + } + if ((control & NETFLAG_LENGTH_MASK) != len) { break; + } - if (MSG_ReadByte (net_message) != CCREP_PLAYER_INFO) + if (MSG_ReadByte (net_message) != CCREP_PLAYER_INFO) { Sys_Error ("Unexpected repsonse to Player Info request"); + } playerNumber = MSG_ReadByte (net_message); strcpy (name, MSG_ReadString (net_message)); @@ -550,43 +575,48 @@ Test_f (void) int max = MAX_SCOREBOARD; netadr_t sendaddr; - if (testInProgress) + if (testInProgress) { return; + } host = Cmd_Argv (1); if (host && hostCacheCount) { for (n = 0; n < hostCacheCount; n++) if (strcasecmp (host, hostcache[n].name) == 0) { - if (hostcache[n].driver != myDriverLevel) + if (hostcache[n].driver != myDriverLevel) { continue; + } net_landriverlevel = hostcache[n].ldriver; max = hostcache[n].maxusers; - memcpy (&sendaddr, &hostcache[n].addr, - - sizeof (netadr_t)); + memcpy (&sendaddr, &hostcache[n].addr, sizeof (netadr_t)); break; } - if (n < hostCacheCount) + if (n < hostCacheCount) { goto JustDoIt; + } } for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) { - if (!net_landrivers[net_landriverlevel].initialized) + if (!net_landrivers[net_landriverlevel].initialized) { continue; + } // see if we can resolve the host name - if (dfunc.GetAddrFromName (host, &sendaddr) != -1) + if (dfunc.GetAddrFromName (host, &sendaddr) != -1) { break; + } } - if (net_landriverlevel == net_numlandrivers) + if (net_landriverlevel == net_numlandrivers) { return; + } JustDoIt: testSocket = dfunc.OpenSocket (0); - if (testSocket == -1) + if (testSocket == -1) { return; + } testInProgress = true; testPollCount = 20; @@ -628,30 +658,35 @@ Test2_Poll (void *unused) net_landriverlevel = test2Driver; name[0] = 0; - len = - dfunc.Read (test2Socket, net_message->message->data, - net_message->message->maxsize, &clientaddr); - if (len < (int) sizeof (int)) + len = dfunc.Read (test2Socket, net_message->message->data, + net_message->message->maxsize, &clientaddr); + if (len < (int) sizeof (int)) { goto Reschedule; + } net_message->message->cursize = len; MSG_BeginReading (net_message); control = BigLong (*((int *) net_message->message->data)); MSG_ReadLong (net_message); - if (control == -1) + if (control == -1) { goto Error; - if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) + } + if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) { goto Error; - if ((control & NETFLAG_LENGTH_MASK) != len) + } + if ((control & NETFLAG_LENGTH_MASK) != len) { goto Error; + } - if (MSG_ReadByte (net_message) != CCREP_RULE_INFO) + if (MSG_ReadByte (net_message) != CCREP_RULE_INFO) { goto Error; + } strcpy (name, MSG_ReadString (net_message)); - if (name[0] == 0) + if (name[0] == 0) { goto Done; + } strcpy (value, MSG_ReadString (net_message)); Sys_Printf ("%-16.16s %-16.16s\n", name, value); @@ -687,42 +722,48 @@ Test2_f (void) int n; netadr_t sendaddr; - if (test2InProgress) + if (test2InProgress) { return; + } host = Cmd_Argv (1); if (host && hostCacheCount) { - for (n = 0; n < hostCacheCount; n++) + for (n = 0; n < hostCacheCount; n++) { if (strcasecmp (host, hostcache[n].name) == 0) { - if (hostcache[n].driver != myDriverLevel) + if (hostcache[n].driver != myDriverLevel) { continue; + } net_landriverlevel = hostcache[n].ldriver; - memcpy (&sendaddr, &hostcache[n].addr, - - sizeof (netadr_t)); + memcpy (&sendaddr, &hostcache[n].addr, sizeof (netadr_t)); break; } - if (n < hostCacheCount) + } + if (n < hostCacheCount) { goto JustDoIt; + } } for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) { - if (!net_landrivers[net_landriverlevel].initialized) + if (!net_landrivers[net_landriverlevel].initialized) { continue; + } // see if we can resolve the host name - if (dfunc.GetAddrFromName (host, &sendaddr) != -1) + if (dfunc.GetAddrFromName (host, &sendaddr) != -1) { break; + } } - if (net_landriverlevel == net_numlandrivers) + if (net_landriverlevel == net_numlandrivers) { return; + } JustDoIt: test2Socket = dfunc.OpenSocket (0); - if (test2Socket == -1) + if (test2Socket == -1) { return; + } test2InProgress = true; test2Driver = net_landriverlevel; @@ -751,13 +792,15 @@ Datagram_Init (void) myDriverLevel = net_driverlevel; Cmd_AddCommand ("net_stats", NET_Stats_f, "No Description"); - if (COM_CheckParm ("-nolan")) + if (COM_CheckParm ("-nolan")) { return -1; + } for (i = 0; i < net_numlandrivers; i++) { csock = net_landrivers[i].Init (); - if (csock == -1) + if (csock == -1) { continue; + } net_landrivers[i].initialized = true; net_landrivers[i].controlSock = csock; } @@ -801,9 +844,11 @@ Datagram_Listen (qboolean state) { int i; - for (i = 0; i < net_numlandrivers; i++) - if (net_landrivers[i].initialized) + for (i = 0; i < net_numlandrivers; i++) { + if (net_landrivers[i].initialized) { net_landrivers[i].Listen (state); + } + } } @@ -822,33 +867,38 @@ _Datagram_CheckNewConnections (void) int ret; acceptsock = dfunc.CheckNewConnections (); - if (acceptsock == -1) + if (acceptsock == -1) { return NULL; + } SZ_Clear (net_message->message); - len = - dfunc.Read (acceptsock, net_message->message->data, - net_message->message->maxsize, &clientaddr); - if (len < (int) sizeof (int)) + len = dfunc.Read (acceptsock, net_message->message->data, + net_message->message->maxsize, &clientaddr); + if (len < (int) sizeof (int)) { return NULL; + } net_message->message->cursize = len; MSG_BeginReading (net_message); control = BigLong (*((int *) net_message->message->data)); MSG_ReadLong (net_message); - if (control == -1) + if (control == -1) { return NULL; - if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) + } + if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) { return NULL; - if ((control & NETFLAG_LENGTH_MASK) != len) + } + if ((control & NETFLAG_LENGTH_MASK) != len) { return NULL; + } command = MSG_ReadByte (net_message); if (command == CCREQ_SERVER_INFO) { - if (strcmp (MSG_ReadString (net_message), "QUAKE") != 0) + if (strcmp (MSG_ReadString (net_message), "QUAKE") != 0) { return NULL; + } SZ_Clear (net_message->message); // save space for the header, filled in later @@ -882,12 +932,14 @@ _Datagram_CheckNewConnections (void) clientNumber < svs.maxclients; clientNumber++, client++) { if (client->active) { activeNumber++; - if (activeNumber == playerNumber) + if (activeNumber == playerNumber) { break; + } } } - if (clientNumber == svs.maxclients) + if (clientNumber == svs.maxclients) { return NULL; + } SZ_Clear (net_message->message); // save space for the header, filled in later @@ -921,13 +973,15 @@ _Datagram_CheckNewConnections (void) if (!var) return NULL; var = var->next; - } else + } else { var = cvar_vars; + } // search for the next server cvar while (var) { - if (var->flags & CVAR_SERVERINFO) + if (var->flags & CVAR_SERVERINFO) { break; + } var = var->next; } @@ -951,11 +1005,13 @@ _Datagram_CheckNewConnections (void) return NULL; } - if (command != CCREQ_CONNECT) + if (command != CCREQ_CONNECT) { return NULL; + } - if (strcmp (MSG_ReadString (net_message), "QUAKE") != 0) + if (strcmp (MSG_ReadString (net_message), "QUAKE") != 0) { return NULL; + } if (MSG_ReadByte (net_message) != NET_PROTOCOL_VERSION) { SZ_Clear (net_message->message); @@ -996,8 +1052,9 @@ _Datagram_CheckNewConnections (void) // see if this guy is already connected for (s = net_activeSockets; s; s = s->next) { - if (s->driver != net_driverlevel) + if (s->driver != net_driverlevel) { continue; + } ret = dfunc.AddrCompare (&clientaddr, &s->addr); if (ret >= 0) { // is this a duplicate connection reqeust? @@ -1084,7 +1141,7 @@ _Datagram_CheckNewConnections (void) return sock; } -qsocket_t * +qsocket_t * Datagram_CheckNewConnections (void) { qsocket_t *ret = NULL; @@ -1124,45 +1181,53 @@ _Datagram_SearchForHosts (qboolean xmit) SZ_Clear (net_message->message); } - while ( - (ret = - dfunc.Read (dfunc.controlSock, net_message->message->data, - net_message->message->maxsize, &readaddr)) > 0) { - if (ret < (int) sizeof (int)) + while ((ret = dfunc.Read (dfunc.controlSock, net_message->message->data, + net_message->message->maxsize, &readaddr)) > 0) { + if (ret < (int) sizeof (int)) { continue; + } net_message->message->cursize = ret; // don't answer our own query - if (dfunc.AddrCompare (&readaddr, &myaddr) >= 0) + if (dfunc.AddrCompare (&readaddr, &myaddr) >= 0) { continue; + } // is the cache full? - if (hostCacheCount == HOSTCACHESIZE) + if (hostCacheCount == HOSTCACHESIZE) { continue; + } MSG_BeginReading (net_message); control = BigLong (*((int *) net_message->message->data)); MSG_ReadLong (net_message); - if (control == -1) + if (control == -1) { continue; - if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) + } + if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) { continue; - if ((control & NETFLAG_LENGTH_MASK) != ret) + } + if ((control & NETFLAG_LENGTH_MASK) != ret) { continue; + } - if (MSG_ReadByte (net_message) != CCREP_SERVER_INFO) + if (MSG_ReadByte (net_message) != CCREP_SERVER_INFO) { continue; + } dfunc.GetAddrFromName (MSG_ReadString (net_message), &readaddr); // search the cache for this server - for (n = 0; n < hostCacheCount; n++) - if (dfunc.AddrCompare (&readaddr, &hostcache[n].addr) == 0) + for (n = 0; n < hostCacheCount; n++) { + if (dfunc.AddrCompare (&readaddr, &hostcache[n].addr) == 0) { break; + } + } // is it already there? - if (n < hostCacheCount) + if (n < hostCacheCount) { continue; + } // add it hostCacheCount++; @@ -1184,15 +1249,17 @@ _Datagram_SearchForHosts (qboolean xmit) // check for a name conflict for (i = 0; i < hostCacheCount; i++) { - if (i == n) + if (i == n) { continue; + } if (strcasecmp (hostcache[n].name, hostcache[i].name) == 0) { i = strlen (hostcache[n].name); if (i < 15 && hostcache[n].name[i - 1] > '8') { hostcache[n].name[i] = '0'; hostcache[n].name[i + 1] = 0; - } else + } else { hostcache[n].name[i - 1]++; + } i = -1; } } @@ -1204,10 +1271,12 @@ Datagram_SearchForHosts (qboolean xmit) { for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) { - if (hostCacheCount == HOSTCACHESIZE) + if (hostCacheCount == HOSTCACHESIZE) { break; - if (net_landrivers[net_landriverlevel].initialized) + } + if (net_landrivers[net_landriverlevel].initialized) { _Datagram_SearchForHosts (xmit); + } } } @@ -1226,22 +1295,26 @@ _Datagram_Connect (const char *host) const char *reason; // see if we can resolve the host name - if (dfunc.GetAddrFromName (host, &sendaddr) == -1) + if (dfunc.GetAddrFromName (host, &sendaddr) == -1) { return NULL; + } newsock = dfunc.OpenSocket (0); - if (newsock == -1) + if (newsock == -1) { return NULL; + } sock = NET_NewQSocket (); - if (sock == NULL) + if (sock == NULL) { goto ErrorReturn2; + } sock->socket = newsock; sock->landriver = net_landriverlevel; // connect to the host - if (dfunc.Connect (newsock, &sendaddr) == -1) + if (dfunc.Connect (newsock, &sendaddr) == -1) { goto ErrorReturn; + } // send the connection request Sys_Printf ("trying...\n"); @@ -1302,10 +1375,11 @@ _Datagram_Connect (const char *host) continue; } } - } - while (ret == 0 && (SetNetTime () - start_time) < 2.5); - if (ret) + } while (ret == 0 && (SetNetTime () - start_time) < 2.5); + + if (ret) { break; + } Sys_Printf ("still trying...\n"); CL_UpdateScreen (cl.time); start_time = SetNetTime (); @@ -1335,7 +1409,6 @@ _Datagram_Connect (const char *host) if (ret == CCREP_ACCEPT) { memcpy (&sock->addr, &sendaddr, sizeof (netadr_t)); - dfunc.SetSocketPort (&sock->addr, MSG_ReadLong (net_message)); } else { reason = "Bad Response"; @@ -1382,9 +1455,12 @@ Datagram_Connect (const char *host) qsocket_t *ret = NULL; for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; - net_landriverlevel++) - if (net_landrivers[net_landriverlevel].initialized) - if ((ret = _Datagram_Connect (host)) != NULL) + net_landriverlevel++) { + if (net_landrivers[net_landriverlevel].initialized) { + if ((ret = _Datagram_Connect (host)) != NULL) { break; + } + } + } return ret; } From 7864bb0ba68485328a839e1e24c056e9f05ae320 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 13:36:29 +0900 Subject: [PATCH 1506/3664] [util] Use a clearer parameter name for SZ_Alloc --- include/QF/sizebuf.h | 2 +- libs/util/sizebuf.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/QF/sizebuf.h b/include/QF/sizebuf.h index a6fc39411..5e0e9a93c 100644 --- a/include/QF/sizebuf.h +++ b/include/QF/sizebuf.h @@ -44,7 +44,7 @@ typedef struct sizebuf_s int cursize; } sizebuf_t; -void SZ_Alloc (sizebuf_t *buf, int startsize); +void SZ_Alloc (sizebuf_t *buf, int maxsize); void SZ_Free (sizebuf_t *buf); void SZ_Clear (sizebuf_t *buf); void *SZ_GetSpace (sizebuf_t *buf, int length); diff --git a/libs/util/sizebuf.c b/libs/util/sizebuf.c index 785287d0c..f7d433110 100644 --- a/libs/util/sizebuf.c +++ b/libs/util/sizebuf.c @@ -41,12 +41,12 @@ VISIBLE void -SZ_Alloc (sizebuf_t *buf, int startsize) +SZ_Alloc (sizebuf_t *buf, int maxsize) { - if (startsize < 256) - startsize = 256; - buf->data = Hunk_AllocName (startsize, "sizebuf"); - buf->maxsize = startsize; + if (maxsize < 256) + maxsize = 256; + buf->data = Hunk_AllocName (maxsize, "sizebuf"); + buf->maxsize = maxsize; buf->cursize = 0; } From 59e5592fed20cc593b784a2ac6fb0e1a47c557ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 14:03:58 +0900 Subject: [PATCH 1507/3664] [net] Dump nq udp packets Probably need some finer control, but it will do for now. --- libs/net/nm/net_udp.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libs/net/nm/net_udp.c b/libs/net/nm/net_udp.c index 2ad422d16..ebc49a886 100644 --- a/libs/net/nm/net_udp.c +++ b/libs/net/nm/net_udp.c @@ -77,6 +77,7 @@ # include #endif +#include #include #include #include @@ -471,6 +472,29 @@ UDP_CheckNewConnections (void) #endif } +static void +hex_dump_buf (byte *buf, int len) +{ + int pos = 0, llen, i; + + while (pos < len) { + llen = (len - pos < 16 ? len - pos : 16); + printf ("%08x: ", pos); + for (i = 0; i < llen; i++) + printf ("%02x ", buf[pos + i]); + for (i = 0; i < 16 - llen; i++) + printf (" "); + printf (" | "); + + for (i = 0; i < llen; i++) + printf ("%c", isprint (buf[pos + i]) ? buf[pos + i] : '.'); + for (i = 0; i < 16 - llen; i++) + printf (" "); + printf ("\n"); + pos += llen; + } +} + int UDP_Read (int socket, byte *buf, int len, netadr_t *from) { @@ -528,6 +552,9 @@ UDP_Read (int socket, byte *buf, int len, netadr_t *from) UDP_AddrToString (from)); last_iface = default_iface; #endif + if (developer->int_val & SYS_net) { + hex_dump_buf (buf, ret); + } return ret; } @@ -576,6 +603,9 @@ UDP_Write (int socket, byte *buf, int len, netadr_t *to) return 0; Sys_MaskPrintf (SYS_net, "sent %d bytes to %s\n", ret, UDP_AddrToString (to)); + if (developer->int_val & SYS_net) { + hex_dump_buf (buf, len); + } return ret; } From afd7b38551bd5dbb092fd3927b8f0f5d87a8afa5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 14:47:58 +0900 Subject: [PATCH 1508/3664] [util] Add big-endian long msg read/write And improve the generated code as well (ie, use a code sequence that gcc recognizes and optimizes to a single 32-bit read and a byte-swap). nq uses big-endian for its packet headers (arg, though it is consistent with IP, it's not with the rest of quake). --- include/QF/msg.h | 14 ++++++++++++++ libs/util/msg.c | 40 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/include/QF/msg.h b/include/QF/msg.h index 4f696f896..310584b2f 100644 --- a/include/QF/msg.h +++ b/include/QF/msg.h @@ -37,6 +37,7 @@ void MSG_WriteByte (sizebuf_t *sb, int c); void MSG_WriteShort (sizebuf_t *sb, int c); void MSG_WriteLong (sizebuf_t *sb, int c); +void MSG_WriteLongBE (sizebuf_t *sb, int c); void MSG_WriteFloat (sizebuf_t *sb, float f); void MSG_WriteString (sizebuf_t *sb, const char *s); void MSG_WriteBytes (sizebuf_t *sb, const void *buf, int len); @@ -108,6 +109,19 @@ int MSG_ReadShort (qmsg_t *msg); */ int MSG_ReadLong (qmsg_t *msg); +/** Read a single big-endian long from the message. + + Advances the read index. + + \param msg The message from which the long will be read. + \return The signed long value or -1 if already at the end of + the message. + \note -1 may be either an error or a value. Check qmsg_t::badread to + differentiate the two cases (false for a value). + \todo Fix? +*/ +int MSG_ReadLongBE (qmsg_t *msg); + /** Read a single little-endian float from the message. Advances the read index. diff --git a/libs/util/msg.c b/libs/util/msg.c index 27ce51d5c..e083c1b39 100644 --- a/libs/util/msg.c +++ b/libs/util/msg.c @@ -80,6 +80,18 @@ MSG_WriteLong (sizebuf_t *sb, int c) *buf = ((unsigned int) c) >> 24; } +VISIBLE void +MSG_WriteLongBE (sizebuf_t *sb, int c) +{ + byte *buf; + + buf = SZ_GetSpace (sb, 4); + *buf++ = ((unsigned int) c) >> 24; + *buf++ = (((unsigned int) c) >> 16) & 0xff; + *buf++ = (((unsigned int) c) >> 8) & 0xff; + *buf = ((unsigned int) c) & 0xff; +} + VISIBLE void MSG_WriteFloat (sizebuf_t *sb, float f) { @@ -269,10 +281,30 @@ MSG_ReadLong (qmsg_t *msg) int c; if (msg->readcount + 4 <= msg->message->cursize) { - c = msg->message->data[msg->readcount] - + (msg->message->data[msg->readcount + 1] << 8) - + (msg->message->data[msg->readcount + 2] << 16) - + (msg->message->data[msg->readcount + 3] << 24); + byte *buf = msg->message->data + msg->readcount; + c = *buf++; + c |= (*buf++) << 8; + c |= (*buf++) << 16; + c |= (*buf) << 24; + msg->readcount += 4; + return c; + } + msg->readcount = msg->message->cursize; + msg->badread = true; + return -1; +} + +VISIBLE int +MSG_ReadLongBE (qmsg_t *msg) +{ + int c; + + if (msg->readcount + 4 <= msg->message->cursize) { + byte *buf = msg->message->data + msg->readcount; + c = (*buf++) << 24; + c |= (*buf++) << 16; + c |= (*buf++) << 8; + c |= *buf; msg->readcount += 4; return c; } From 9a2f82bbc6ca4bb1168c2e04db3e143fdbd13eec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 15:19:38 +0900 Subject: [PATCH 1509/3664] [util] Add big-endian short msg read/write And improve the generated code for MSG_ReadShort I suspect gcc didn't like all the excess pointer dereferences and so couldn't assume that the bytes were being read sequentially. --- include/QF/msg.h | 11 +++++++++++ libs/util/msg.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/include/QF/msg.h b/include/QF/msg.h index 310584b2f..d10d435ae 100644 --- a/include/QF/msg.h +++ b/include/QF/msg.h @@ -36,6 +36,7 @@ void MSG_WriteByte (sizebuf_t *sb, int c); void MSG_WriteShort (sizebuf_t *sb, int c); +void MSG_WriteShortBE (sizebuf_t *sb, int c); void MSG_WriteLong (sizebuf_t *sb, int c); void MSG_WriteLongBE (sizebuf_t *sb, int c); void MSG_WriteFloat (sizebuf_t *sb, float f); @@ -96,6 +97,16 @@ int MSG_ReadByte (qmsg_t *msg); */ int MSG_ReadShort (qmsg_t *msg); +/** Read a single big-endian unsigned short from the message. + + Advances the read index. + + \param msg The message from which the short will be read. + \return The short value (0 - 65535), or -1 if already at + the end of the message. +*/ +int MSG_ReadShortBE (qmsg_t *msg); + /** Read a single little-endian long from the message. Advances the read index. diff --git a/libs/util/msg.c b/libs/util/msg.c index e083c1b39..92596dcc6 100644 --- a/libs/util/msg.c +++ b/libs/util/msg.c @@ -68,6 +68,16 @@ MSG_WriteShort (sizebuf_t *sb, int c) *buf = ((unsigned int) c) >> 8; } +VISIBLE void +MSG_WriteShortBE (sizebuf_t *sb, int c) +{ + byte *buf; + + buf = SZ_GetSpace (sb, 2); + *buf++ = ((unsigned int) c) >> 8; + *buf = ((unsigned int) c) & 0xff; +} + VISIBLE void MSG_WriteLong (sizebuf_t *sb, int c) { @@ -265,8 +275,26 @@ MSG_ReadShort (qmsg_t *msg) int c; if (msg->readcount + 2 <= msg->message->cursize) { - c = (msg->message->data[msg->readcount] - + (msg->message->data[msg->readcount + 1] << 8)); + byte *buf = msg->message->data + msg->readcount; + c = *buf++; + c |= (*buf) << 8; + msg->readcount += 2; + return c; + } + msg->readcount = msg->message->cursize; + msg->badread = true; + return -1; +} + +VISIBLE int +MSG_ReadShortBE (qmsg_t *msg) +{ + int c; + + if (msg->readcount + 2 <= msg->message->cursize) { + byte *buf = msg->message->data + msg->readcount; + c = (*buf++) << 8; + c |= *buf; msg->readcount += 2; return c; } From 972b0f8a705d8e8a7c317f845b3de2db1ad33163 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 15:53:53 +0900 Subject: [PATCH 1510/3664] [util] Make sizebuf and msg sizes unisgned And clean up the mess. --- include/QF/msg.h | 16 ++++++++-------- include/QF/sizebuf.h | 16 ++++++++-------- include/netchan.h | 4 ++-- include/qw/msg_backbuf.h | 8 ++++---- libs/net/net_chan.c | 4 ++-- libs/qw/msg_backbuf.c | 8 ++++---- libs/util/msg.c | 9 +++++---- libs/util/sizebuf.c | 10 +++++----- nq/source/cl_demo.c | 3 ++- qtv/source/server.c | 4 ++-- qw/include/sv_recorder.h | 2 +- qw/source/cl_demo.c | 2 +- qw/source/cl_main.c | 4 +++- qw/source/sv_recorder.c | 14 +++++++------- 14 files changed, 54 insertions(+), 50 deletions(-) diff --git a/include/QF/msg.h b/include/QF/msg.h index d10d435ae..cf0aa8505 100644 --- a/include/QF/msg.h +++ b/include/QF/msg.h @@ -41,7 +41,7 @@ void MSG_WriteLong (sizebuf_t *sb, int c); void MSG_WriteLongBE (sizebuf_t *sb, int c); void MSG_WriteFloat (sizebuf_t *sb, float f); void MSG_WriteString (sizebuf_t *sb, const char *s); -void MSG_WriteBytes (sizebuf_t *sb, const void *buf, int len); +void MSG_WriteBytes (sizebuf_t *sb, const void *buf, unsigned len); void MSG_WriteCoord (sizebuf_t *sb, float coord); void MSG_WriteCoordV (sizebuf_t *sb, const vec3_t coord); void MSG_WriteCoordAngleV (sizebuf_t *sb, const vec3_t coord, @@ -53,11 +53,11 @@ void MSG_WriteAngle16V (sizebuf_t *sb, const vec3_t angle); void MSG_WriteUTF8 (sizebuf_t *sb, unsigned utf8); typedef struct msg_s { - int readcount; - qboolean badread; // set if a read goes beyond end of message - sizebuf_t *message; - size_t badread_string_size; - char *badread_string; + unsigned readcount; + qboolean badread; // set if a read goes beyond end of message + sizebuf_t *message; + size_t badread_string_size; + char *badread_string; } qmsg_t; /** Reset the message read status. @@ -75,7 +75,7 @@ void MSG_BeginReading (qmsg_t *msg); \param msg The message to check. \return The number of bytes that have been read. */ -int MSG_GetReadCount(qmsg_t *msg) __attribute__((pure)); +unsigned MSG_GetReadCount(qmsg_t *msg) __attribute__((pure)); /** Read a single byte from the message. @@ -175,7 +175,7 @@ const char *MSG_ReadString (qmsg_t *msg); \param len The number of bytes to read. \return The number of bytes read from the message. */ -int MSG_ReadBytes (qmsg_t *msg, void *buf, int len); +int MSG_ReadBytes (qmsg_t *msg, void *buf, unsigned len); /** Read a little-endian 16-bit fixed point (13.3) coordinate value from the message. diff --git a/include/QF/sizebuf.h b/include/QF/sizebuf.h index 5e0e9a93c..c454cdc4c 100644 --- a/include/QF/sizebuf.h +++ b/include/QF/sizebuf.h @@ -37,18 +37,18 @@ typedef struct sizebuf_s { - qboolean allowoverflow; // if false, do a Sys_Error - qboolean overflowed; // set to true if the buffer size failed - byte *data; - int maxsize; - int cursize; + qboolean allowoverflow; // if false, do a Sys_Error + qboolean overflowed; // set to true if the buffer size failed + byte *data; + unsigned maxsize; + unsigned cursize; } sizebuf_t; -void SZ_Alloc (sizebuf_t *buf, int maxsize); +void SZ_Alloc (sizebuf_t *buf, unsigned maxsize); void SZ_Free (sizebuf_t *buf); void SZ_Clear (sizebuf_t *buf); -void *SZ_GetSpace (sizebuf_t *buf, int length); -void SZ_Write (sizebuf_t *buf, const void *data, int length); +void *SZ_GetSpace (sizebuf_t *buf, unsigned length); +void SZ_Write (sizebuf_t *buf, const void *data, unsigned length); void SZ_Print (sizebuf_t *buf, const char *data); // strcats onto the sizebuf void SZ_Dump (sizebuf_t *buf); diff --git a/include/netchan.h b/include/netchan.h index 6197cc8db..d502f1030 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -317,7 +317,7 @@ void Netchan_Init_Cvars (void); \param length The size of the unreliable packet. \param data The data of the unreliable packet. */ -void Netchan_Transmit (netchan_t *chan, int length, byte *data); +void Netchan_Transmit (netchan_t *chan, unsigned length, byte *data); /** Send an out-of-band packet. @@ -325,7 +325,7 @@ void Netchan_Transmit (netchan_t *chan, int length, byte *data); \param length The length of the data to be sent. \param data The data to be sent. */ -void Netchan_OutOfBand (netadr_t adr, int length, byte *data); +void Netchan_OutOfBand (netadr_t adr, unsigned length, byte *data); /** Send a formatted string as an out-of-band packet. \param adr The address to which the data will be sent. diff --git a/include/qw/msg_backbuf.h b/include/qw/msg_backbuf.h index 12cbb0b06..0a6cea2db 100644 --- a/include/qw/msg_backbuf.h +++ b/include/qw/msg_backbuf.h @@ -43,10 +43,10 @@ typedef struct backbuf_s { const char *name; } backbuf_t; -int MSG_ReliableCheckSize (backbuf_t *rel, int maxsize, int minsize) __attribute__((pure)); -sizebuf_t *MSG_ReliableCheckBlock(backbuf_t *rel, int maxsize); +int MSG_ReliableCheckSize (backbuf_t *rel, unsigned maxsize, unsigned minsize) __attribute__((pure)); +sizebuf_t *MSG_ReliableCheckBlock(backbuf_t *rel, unsigned maxsize); void MSG_Reliable_FinishWrite(backbuf_t *rel); -sizebuf_t *MSG_ReliableWrite_Begin(backbuf_t *rel, int c, int maxsize); +sizebuf_t *MSG_ReliableWrite_Begin(backbuf_t *rel, int c, unsigned maxsize); void MSG_ReliableWrite_Angle(backbuf_t *rel, float f); void MSG_ReliableWrite_Angle16(backbuf_t *rel, float f); void MSG_ReliableWrite_Byte(backbuf_t *rel, int c); @@ -56,7 +56,7 @@ void MSG_ReliableWrite_Coord(backbuf_t *rel, float f); void MSG_ReliableWrite_Long(backbuf_t *rel, int c); void MSG_ReliableWrite_Short(backbuf_t *rel, int c); void MSG_ReliableWrite_String(backbuf_t *rel, const char *s); -void MSG_ReliableWrite_SZ(backbuf_t *rel, const void *data, int len); +void MSG_ReliableWrite_SZ(backbuf_t *rel, const void *data, unsigned len); void MSG_ReliableWrite_AngleV(backbuf_t *rel, const vec3_t v); void MSG_ReliableWrite_CoordV(backbuf_t *rel, const vec3_t v); void MSG_Reliable_Send (backbuf_t *rel); diff --git a/libs/net/net_chan.c b/libs/net/net_chan.c index 61f125117..53557a95c 100644 --- a/libs/net/net_chan.c +++ b/libs/net/net_chan.c @@ -92,7 +92,7 @@ Netchan_Init_Cvars (void) Sends an out-of-band datagram */ void -Netchan_OutOfBand (netadr_t adr, int length, byte * data) +Netchan_OutOfBand (netadr_t adr, unsigned length, byte * data) { byte send_buf[MAX_MSGLEN + PACKET_HEADER]; sizebuf_t send; @@ -185,7 +185,7 @@ Netchan_CanReliable (netchan_t *chan) } void -Netchan_Transmit (netchan_t *chan, int length, byte *data) +Netchan_Transmit (netchan_t *chan, unsigned length, byte *data) { byte send_buf[MAX_MSGLEN + PACKET_HEADER]; int i; diff --git a/libs/qw/msg_backbuf.c b/libs/qw/msg_backbuf.c index 90d80704c..3a87cedc5 100644 --- a/libs/qw/msg_backbuf.c +++ b/libs/qw/msg_backbuf.c @@ -59,7 +59,7 @@ PushBackbuf (backbuf_t *rel) } int -MSG_ReliableCheckSize (backbuf_t *rel, int maxsize, int minsize) +MSG_ReliableCheckSize (backbuf_t *rel, unsigned maxsize, unsigned minsize) { sizebuf_t *msg = &rel->netchan->message; @@ -80,7 +80,7 @@ MSG_ReliableCheckSize (backbuf_t *rel, int maxsize, int minsize) // check to see if client block will fit, if not, rotate buffers sizebuf_t * -MSG_ReliableCheckBlock (backbuf_t *rel, int maxsize) +MSG_ReliableCheckBlock (backbuf_t *rel, unsigned maxsize) { sizebuf_t *msg = &rel->netchan->message; @@ -108,7 +108,7 @@ MSG_ReliableCheckBlock (backbuf_t *rel, int maxsize) // begin a client block, estimated maximum size sizebuf_t * -MSG_ReliableWrite_Begin (backbuf_t *rel, int c, int maxsize) +MSG_ReliableWrite_Begin (backbuf_t *rel, int c, unsigned maxsize) { sizebuf_t *msg; msg = MSG_ReliableCheckBlock (rel, maxsize); @@ -226,7 +226,7 @@ MSG_ReliableWrite_String (backbuf_t *rel, const char *s) } void -MSG_ReliableWrite_SZ (backbuf_t *rel, const void *data, int len) +MSG_ReliableWrite_SZ (backbuf_t *rel, const void *data, unsigned len) { if (rel->num_backbuf) { SZ_Write (&rel->backbuf, data, len); diff --git a/libs/util/msg.c b/libs/util/msg.c index 92596dcc6..0908dff2b 100644 --- a/libs/util/msg.c +++ b/libs/util/msg.c @@ -126,7 +126,7 @@ MSG_WriteString (sizebuf_t *sb, const char *s) } VISIBLE void -MSG_WriteBytes (sizebuf_t *sb, const void *buf, int len) +MSG_WriteBytes (sizebuf_t *sb, const void *buf, unsigned len) { SZ_Write (sb, buf, len); } @@ -253,7 +253,7 @@ MSG_BeginReading (qmsg_t *msg) msg->badread = false; } -VISIBLE int +VISIBLE unsigned MSG_GetReadCount (qmsg_t *msg) { return msg->readcount; @@ -403,7 +403,7 @@ MSG_ReadString (qmsg_t *msg) } VISIBLE int -MSG_ReadBytes (qmsg_t *msg, void *buf, int len) +MSG_ReadBytes (qmsg_t *msg, void *buf, unsigned len) { if (msg->badread || len > msg->message->cursize - msg->readcount) { msg->badread = true; @@ -474,7 +474,8 @@ VISIBLE int MSG_ReadUTF8 (qmsg_t *msg) { byte *buf, *start, c; - int val = 0, count; + int val = 0; + unsigned count; if (msg->badread || msg->message->cursize == msg->readcount) { msg->badread = true; diff --git a/libs/util/sizebuf.c b/libs/util/sizebuf.c index f7d433110..25f835a4f 100644 --- a/libs/util/sizebuf.c +++ b/libs/util/sizebuf.c @@ -41,7 +41,7 @@ VISIBLE void -SZ_Alloc (sizebuf_t *buf, int maxsize) +SZ_Alloc (sizebuf_t *buf, unsigned maxsize) { if (maxsize < 256) maxsize = 256; @@ -58,7 +58,7 @@ SZ_Clear (sizebuf_t *buf) } VISIBLE void * -SZ_GetSpace (sizebuf_t *buf, int length) +SZ_GetSpace (sizebuf_t *buf, unsigned length) { void *data; @@ -83,7 +83,7 @@ getspace: } VISIBLE void -SZ_Write (sizebuf_t *buf, const void *data, int length) +SZ_Write (sizebuf_t *buf, const void *data, unsigned length) { memcpy (SZ_GetSpace (buf, length), data, length); } @@ -91,7 +91,7 @@ SZ_Write (sizebuf_t *buf, const void *data, int length) VISIBLE void SZ_Print (sizebuf_t *buf, const char *data) { - int len; + unsigned len; len = strlen (data) + 1; if (buf->cursize && !buf->data[buf->cursize - 1]) @@ -103,7 +103,7 @@ SZ_Print (sizebuf_t *buf, const char *data) VISIBLE void SZ_Dump (sizebuf_t *buf) { - int i; + unsigned i; char chars[17], c; chars[16] = 0; diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 0d7e91a51..a119cb8b6 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -174,7 +174,8 @@ check_next_demopacket (void) static int read_demopacket (void) { - int i, r; + int i; + unsigned r; float f; Qread (cls.demofile, &net_message->message->cursize, 4); diff --git a/qtv/source/server.c b/qtv/source/server.c index 00778acea..28f43ad6f 100644 --- a/qtv/source/server.c +++ b/qtv/source/server.c @@ -124,7 +124,7 @@ server_compare (const void *a, const void *b) } static void -setup_sub_message (qmsg_t *msg, qmsg_t *sub, sizebuf_t *buf, int len) +setup_sub_message (qmsg_t *msg, qmsg_t *sub, sizebuf_t *buf, unsigned len) { memset (sub, 0, sizeof (qmsg_t)); memset (buf, 0, sizeof (sizebuf_t)); @@ -274,7 +274,7 @@ server_handler (connection_t *con, void *object) if (!Netchan_Process (&sv->netchan)) return; if (0) { - int i; + unsigned i; for (i = 0; i < net_message->message->cursize; i++) qtv_printf ("%c%02x", (i % 16) ? ' ' : '\n', diff --git a/qw/include/sv_recorder.h b/qw/include/sv_recorder.h index f8be8b97f..a2875360a 100644 --- a/qw/include/sv_recorder.h +++ b/qw/include/sv_recorder.h @@ -41,7 +41,7 @@ recorder_t *SVR_AddUser (void (*writer)(void *, struct sizebuf_s *, int), void (*finish)(void *, struct sizebuf_s *), int demo, void *user); void SVR_RemoveUser (recorder_t *r); -struct sizebuf_s *SVR_WriteBegin (byte type, int to, int size); +struct sizebuf_s *SVR_WriteBegin (byte type, int to, unsigned size); struct sizebuf_s *SVR_Datagram (void) __attribute__((const)); void SVR_ForceFrame (void); void SVR_Pause (recorder_t *r); diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 51789e572..dd4114e14 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -271,7 +271,7 @@ check_next_demopacket (void) static int read_demopacket (void) { - int r; + unsigned r; Qread (cls.demofile, &net_message->message->cursize, 4); net_message->message->cursize = diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 09ef477c4..e2deb673b 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1013,8 +1013,10 @@ CL_ReadPackets (void) { while (CL_GetMessage ()) { - if (net_message->message->cursize == -1) + // non-packet set up by the demo reader + if ((int) net_message->message->cursize == -1) { continue; + } if (cls.demoplayback && net_packetlog->int_val) Log_Incoming_Packet (net_message->message->data, diff --git a/qw/source/sv_recorder.c b/qw/source/sv_recorder.c index d2555862e..cd5cdf1c2 100644 --- a/qw/source/sv_recorder.c +++ b/qw/source/sv_recorder.c @@ -56,8 +56,8 @@ typedef struct dbuffer_s { byte *data; - int start, end, last; - int maxsize; + unsigned start, end, last; + unsigned maxsize; } dbuffer_t; typedef struct header_s { @@ -70,7 +70,7 @@ typedef struct header_s { typedef struct demobuf_s { sizebuf_t sz; - int bufsize; + unsigned bufsize; header_t *h; } demobuf_t; @@ -200,9 +200,9 @@ write_msg (sizebuf_t *msg, int type, int to, float time, sizebuf_t *dst) static void write_to_msg (int type, int to, float time, sizebuf_t *dst) { - int pos = 0; + unsigned pos = 0; header_t *p; - int size; + unsigned size; sizebuf_t msg; p = (header_t *) rec.dbuf->sz.data; @@ -256,7 +256,7 @@ static void set_buf (byte type, int to) { header_t *p; - int pos = 0; + unsigned pos = 0; p = (header_t *) rec.dbuf->sz.data; @@ -464,7 +464,7 @@ write_packet (void) } sizebuf_t * -SVR_WriteBegin (byte type, int to, int size) +SVR_WriteBegin (byte type, int to, unsigned size) { byte *p; qboolean move = false; From f596eacf0c81e054e2b0fc09739af83ac7b41be4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 15:56:14 +0900 Subject: [PATCH 1511/3664] [util] Add message short and long poke functions Both big and little endian. --- include/QF/msg.h | 5 +++++ libs/util/msg.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/include/QF/msg.h b/include/QF/msg.h index cf0aa8505..3fb7a84a3 100644 --- a/include/QF/msg.h +++ b/include/QF/msg.h @@ -52,6 +52,11 @@ void MSG_WriteAngle16 (sizebuf_t *sb, float angle); void MSG_WriteAngle16V (sizebuf_t *sb, const vec3_t angle); void MSG_WriteUTF8 (sizebuf_t *sb, unsigned utf8); +void MSG_PokeShort (sizebuf_t *sb, unsigned offset, int c); +void MSG_PokeShortBE (sizebuf_t *sb, unsigned offset, int c); +void MSG_PokeLong (sizebuf_t *sb, unsigned offset, int c); +void MSG_PokeLongBE (sizebuf_t *sb, unsigned offset, int c); + typedef struct msg_s { unsigned readcount; qboolean badread; // set if a read goes beyond end of message diff --git a/libs/util/msg.c b/libs/util/msg.c index 0908dff2b..aaf3d364c 100644 --- a/libs/util/msg.c +++ b/libs/util/msg.c @@ -244,6 +244,62 @@ MSG_WriteUTF8 (sizebuf_t *sb, unsigned utf8) } } +VISIBLE void +MSG_PokeShort (sizebuf_t *sb, unsigned offset, int c) +{ + if (__builtin_expect (offset + 2 > sb->cursize, 0)) { + Sys_Error ("MSG_PokeShort: invalid offset %d / %d", + offset, sb->cursize); + } + byte *buf = sb->data + offset; + + *buf++ = ((unsigned int) c) & 0xff; + *buf = ((unsigned int) c) >> 8; +} + +VISIBLE void +MSG_PokeShortBE (sizebuf_t *sb, unsigned offset, int c) +{ + if (__builtin_expect (offset + 2 > sb->cursize, 0)) { + Sys_Error ("MSG_PokeShortBE: invalid offset %d / %d", + offset, sb->cursize); + } + byte *buf = sb->data + offset; + + *buf++ = ((unsigned int) c) >> 8; + *buf = ((unsigned int) c) & 0xff; +} + +VISIBLE void +MSG_PokeLong (sizebuf_t *sb, unsigned offset, int c) +{ + if (__builtin_expect (offset + 2 > sb->cursize, 0)) { + Sys_Error ("MSG_PokeLong: invalid offset %d / %d", + offset, sb->cursize); + } + byte *buf = sb->data + offset; + + *buf++ = ((unsigned int) c) & 0xff; + *buf++ = (((unsigned int) c) >> 8) & 0xff; + *buf++ = (((unsigned int) c) >> 16) & 0xff; + *buf = ((unsigned int) c) >> 24; +} + +VISIBLE void +MSG_PokeLongBE (sizebuf_t *sb, unsigned offset, int c) +{ + if (__builtin_expect (offset + 2 > sb->cursize, 0)) { + Sys_Error ("MSG_PokeLongBE: invalid offset %d / %d", + offset, sb->cursize); + } + byte *buf = sb->data + offset; + + *buf++ = ((unsigned int) c) >> 24; + *buf++ = (((unsigned int) c) >> 16) & 0xff; + *buf++ = (((unsigned int) c) >> 8) & 0xff; + *buf = ((unsigned int) c) & 0xff; +} + // reading functions ========================================================== VISIBLE void From 5f682ff1dfc8989767f041fc60ed8096d30c197e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 17:01:53 +0900 Subject: [PATCH 1512/3664] [net] Clean up nq's packet reading and writing It should be more portable now and hopefully future proof against C aliasing. Also, the send and receive buffers are now separate. --- libs/net/nm/net_dgrm.c | 177 +++++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 88 deletions(-) diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index a230cc09b..99aff3f51 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -82,11 +82,20 @@ int droppedDatagrams; static int myDriverLevel; -struct { - unsigned length; - unsigned sequence; - byte data[MAX_DATAGRAM]; -} packetBuffer; +static byte dgrm_send_packet_data[MAX_DATAGRAM + NET_HEADERSIZE]; +static sizebuf_t dgrm_send_packet = { + .data = dgrm_send_packet_data, + .maxsize = sizeof (dgrm_send_packet_data), +}; + +static byte dgrm_receive_packet_data[MAX_DATAGRAM + NET_HEADERSIZE]; +static sizebuf_t dgrm_receive_packet = { + .data = dgrm_receive_packet_data, + .maxsize = sizeof (dgrm_receive_packet_data), +}; +static qmsg_t dgrm_message = { + .message = &dgrm_receive_packet, +}; // FIXME: MENUCODE //extern int m_return_state; @@ -162,7 +171,6 @@ Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) unsigned dataLen; unsigned eom; - memcpy (sock->sendMessage, data->data, data->cursize); sock->sendMessageLength = data->cursize; @@ -175,14 +183,15 @@ Datagram_SendMessage (qsocket_t *sock, sizebuf_t *data) } packetLen = NET_HEADERSIZE + dataLen; - packetBuffer.length = BigLong (packetLen | (NETFLAG_DATA | eom)); - packetBuffer.sequence = BigLong (sock->sendSequence++); - memcpy (packetBuffer.data, sock->sendMessage, dataLen); + SZ_Clear (&dgrm_send_packet); + MSG_WriteLongBE (&dgrm_send_packet, packetLen | (NETFLAG_DATA | eom)); + MSG_WriteLongBE (&dgrm_send_packet, sock->sendSequence++); + MSG_WriteBytes (&dgrm_send_packet, sock->sendMessage, dataLen); sock->canSend = false; - if (sfunc.Write (sock->socket, (byte *) & packetBuffer, packetLen, - &sock->addr) == -1) { + if (sfunc.Write (sock->socket, dgrm_send_packet.data, + dgrm_send_packet.cursize, &sock->addr) == -1) { return -1; } @@ -208,14 +217,15 @@ SendMessageNext (qsocket_t *sock) } packetLen = NET_HEADERSIZE + dataLen; - packetBuffer.length = BigLong (packetLen | (NETFLAG_DATA | eom)); - packetBuffer.sequence = BigLong (sock->sendSequence++); - memcpy (packetBuffer.data, sock->sendMessage, dataLen); + SZ_Clear (&dgrm_send_packet); + MSG_WriteLongBE (&dgrm_send_packet, packetLen | (NETFLAG_DATA | eom)); + MSG_WriteLongBE (&dgrm_send_packet, sock->sendSequence++); + MSG_WriteBytes (&dgrm_send_packet, sock->sendMessage, dataLen); sock->sendNext = false; - if (sfunc.Write (sock->socket, (byte *) &packetBuffer, packetLen, - &sock->addr) == -1) { + if (sfunc.Write (sock->socket, dgrm_send_packet.data, + dgrm_send_packet.cursize, &sock->addr) == -1) { return -1; } @@ -241,14 +251,15 @@ ReSendMessage (qsocket_t *sock) } packetLen = NET_HEADERSIZE + dataLen; - packetBuffer.length = BigLong (packetLen | (NETFLAG_DATA | eom)); - packetBuffer.sequence = BigLong (sock->sendSequence - 1); - memcpy (packetBuffer.data, sock->sendMessage, dataLen); + SZ_Clear (&dgrm_send_packet); + MSG_WriteLongBE (&dgrm_send_packet, packetLen | (NETFLAG_DATA | eom)); + MSG_WriteLongBE (&dgrm_send_packet, sock->sendSequence - 1); + MSG_WriteBytes (&dgrm_send_packet, sock->sendMessage, dataLen); sock->sendNext = false; - if (sfunc.Write (sock->socket, (byte *) &packetBuffer, packetLen, - &sock->addr) == -1) { + if (sfunc.Write (sock->socket, dgrm_send_packet.data, + dgrm_send_packet.cursize, &sock->addr) == -1) { return -1; } @@ -283,12 +294,13 @@ Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) packetLen = NET_HEADERSIZE + data->cursize; - packetBuffer.length = BigLong (packetLen | NETFLAG_UNRELIABLE); - packetBuffer.sequence = BigLong (sock->unreliableSendSequence++); - memcpy (packetBuffer.data, data->data, data->cursize); + SZ_Clear (&dgrm_send_packet); + MSG_WriteLongBE (&dgrm_send_packet, packetLen | NETFLAG_UNRELIABLE); + MSG_WriteLongBE (&dgrm_send_packet, sock->unreliableSendSequence++); + MSG_WriteBytes (&dgrm_send_packet, data->data, data->cursize); - if (sfunc.Write (sock->socket, (byte *) &packetBuffer, packetLen, - &sock->addr) == -1) { + if (sfunc.Write (sock->socket, dgrm_send_packet.data, + dgrm_send_packet.cursize, &sock->addr) == -1) { return -1; } @@ -316,8 +328,10 @@ Datagram_GetMessage (qsocket_t *sock) } while (1) { - length = sfunc.Read (sock->socket, (byte *) &packetBuffer, - NET_DATAGRAMSIZE, &readaddr); + SZ_Clear (&dgrm_receive_packet); + length = sfunc.Read (sock->socket, dgrm_receive_packet.data, + dgrm_receive_packet.maxsize, &readaddr); + dgrm_receive_packet.cursize = length; // if ((rand() & 255) > 220) // continue; @@ -340,7 +354,9 @@ Datagram_GetMessage (qsocket_t *sock) continue; } - length = BigLong (packetBuffer.length); + MSG_BeginReading (&dgrm_message); + length = MSG_ReadLongBE (&dgrm_message); + flags = length & (~NETFLAG_LENGTH_MASK); length &= NETFLAG_LENGTH_MASK; @@ -348,7 +364,7 @@ Datagram_GetMessage (qsocket_t *sock) continue; } - sequence = BigLong (packetBuffer.sequence); + sequence = MSG_ReadLongBE (&dgrm_message); packetsReceived++; if (flags & NETFLAG_UNRELIABLE) { @@ -368,7 +384,8 @@ Datagram_GetMessage (qsocket_t *sock) /// Copy unreliable data to net_message SZ_Clear (net_message->message); - SZ_Write (net_message->message, packetBuffer.data, length); + byte *buf = SZ_GetSpace (net_message->message, length); + MSG_ReadBytes (&dgrm_message, buf, length); ret = 2; break; @@ -401,10 +418,11 @@ Datagram_GetMessage (qsocket_t *sock) } if (flags & NETFLAG_DATA) { - packetBuffer.length = BigLong (NET_HEADERSIZE | NETFLAG_ACK); - packetBuffer.sequence = BigLong (sequence); - sfunc.Write (sock->socket, (byte *) & packetBuffer, NET_HEADERSIZE, - &readaddr); + SZ_Clear (&dgrm_send_packet); + MSG_WriteLongBE (&dgrm_send_packet, NET_HEADERSIZE | NETFLAG_ACK); + MSG_WriteLongBE (&dgrm_send_packet, sequence); + sfunc.Write (sock->socket, dgrm_send_packet.data, + dgrm_send_packet.cursize, &readaddr); if (sequence != sock->receiveSequence) { receivedDuplicateCount++; @@ -418,7 +436,8 @@ Datagram_GetMessage (qsocket_t *sock) SZ_Clear (net_message->message); SZ_Write (net_message->message, sock->receiveMessage, sock->receiveMessageLength); - SZ_Write (net_message->message, packetBuffer.data, length); + byte *buf = SZ_GetSpace (net_message->message, length); + MSG_ReadBytes (&dgrm_message, buf, length); sock->receiveMessageLength = 0; ret = 1; @@ -426,8 +445,9 @@ Datagram_GetMessage (qsocket_t *sock) } /// Append reliable data to sock->receiveMessage. - memcpy (sock->receiveMessage + sock->receiveMessageLength, - packetBuffer.data, length); + MSG_ReadBytes (&dgrm_message, + sock->receiveMessage + sock->receiveMessageLength, + length); sock->receiveMessageLength += length; continue; } @@ -530,8 +550,7 @@ Test_Poll (void *unused) net_message->message->cursize = len; MSG_BeginReading (net_message); - control = BigLong (*((int *) net_message->message->data)); - MSG_ReadLong (net_message); + control = MSG_ReadLongBE (net_message); if (control == -1) { break; } @@ -628,9 +647,8 @@ Test_f (void) MSG_WriteLong (net_message->message, 0); MSG_WriteByte (net_message->message, CCREQ_PLAYER_INFO); MSG_WriteByte (net_message->message, n); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (testSocket, net_message->message->data, net_message->message->cursize, &sendaddr); } @@ -667,8 +685,7 @@ Test2_Poll (void *unused) net_message->message->cursize = len; MSG_BeginReading (net_message); - control = BigLong (*((int *) net_message->message->data)); - MSG_ReadLong (net_message); + control = MSG_ReadLongBE (net_message); if (control == -1) { goto Error; } @@ -696,9 +713,8 @@ Test2_Poll (void *unused) MSG_WriteLong (net_message->message, 0); MSG_WriteByte (net_message->message, CCREQ_RULE_INFO); MSG_WriteString (net_message->message, name); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (test2Socket, net_message->message->data, net_message->message->cursize, &clientaddr); SZ_Clear (net_message->message); @@ -773,9 +789,8 @@ Test2_f (void) MSG_WriteLong (net_message->message, 0); MSG_WriteByte (net_message->message, CCREQ_RULE_INFO); MSG_WriteString (net_message->message, ""); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (test2Socket, net_message->message->data, net_message->message->cursize, &sendaddr); SZ_Clear (net_message->message); @@ -882,8 +897,7 @@ _Datagram_CheckNewConnections (void) net_message->message->cursize = len; MSG_BeginReading (net_message); - control = BigLong (*((int *) net_message->message->data)); - MSG_ReadLong (net_message); + control = MSG_ReadLongBE (net_message); if (control == -1) { return NULL; } @@ -911,9 +925,8 @@ _Datagram_CheckNewConnections (void) MSG_WriteByte (net_message->message, net_activeconnections); MSG_WriteByte (net_message->message, svs.maxclients); MSG_WriteByte (net_message->message, NET_PROTOCOL_VERSION); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (acceptsock, net_message->message->data, net_message->message->cursize, &clientaddr); SZ_Clear (net_message->message); @@ -952,9 +965,8 @@ _Datagram_CheckNewConnections (void) MSG_WriteLong (net_message->message, (int) (net_time - client->netconnection->connecttime)); MSG_WriteString (net_message->message, client->netconnection->address); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (acceptsock, net_message->message->data, net_message->message->cursize, &clientaddr); SZ_Clear (net_message->message); @@ -995,9 +1007,8 @@ _Datagram_CheckNewConnections (void) MSG_WriteString (net_message->message, var->name); MSG_WriteString (net_message->message, var->string); } - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (acceptsock, net_message->message->data, net_message->message->cursize, &clientaddr); SZ_Clear (net_message->message); @@ -1019,9 +1030,8 @@ _Datagram_CheckNewConnections (void) MSG_WriteLong (net_message->message, 0); MSG_WriteByte (net_message->message, CCREP_REJECT); MSG_WriteString (net_message->message, "Incompatible version.\n"); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (acceptsock, net_message->message->data, net_message->message->cursize, &clientaddr); SZ_Clear (net_message->message); @@ -1039,9 +1049,8 @@ _Datagram_CheckNewConnections (void) MSG_WriteLong (net_message->message, 0); MSG_WriteByte (net_message->message, CCREP_REJECT); MSG_WriteString (net_message->message, "You have been banned.\n"); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (acceptsock, net_message->message->data, net_message->message->cursize, &clientaddr); SZ_Clear (net_message->message); @@ -1067,10 +1076,8 @@ _Datagram_CheckNewConnections (void) dfunc.GetSocketAddr (s->socket, &newaddr); MSG_WriteLong (net_message->message, dfunc.GetSocketPort (&newaddr)); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message-> - message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (acceptsock, net_message->message->data, net_message->message->cursize, &clientaddr); SZ_Clear (net_message->message); @@ -1094,9 +1101,8 @@ _Datagram_CheckNewConnections (void) MSG_WriteLong (net_message->message, 0); MSG_WriteByte (net_message->message, CCREP_REJECT); MSG_WriteString (net_message->message, "Server is full.\n"); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (acceptsock, net_message->message->data, net_message->message->cursize, &clientaddr); SZ_Clear (net_message->message); @@ -1131,9 +1137,8 @@ _Datagram_CheckNewConnections (void) dfunc.GetSocketAddr (newsock, &newaddr); MSG_WriteLong (net_message->message, dfunc.GetSocketPort (&newaddr)); // MSG_WriteString(net_message->message, dfunc.AddrToString(&newaddr)); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (acceptsock, net_message->message->data, net_message->message->cursize, &clientaddr); SZ_Clear (net_message->message); @@ -1173,9 +1178,8 @@ _Datagram_SearchForHosts (qboolean xmit) MSG_WriteByte (net_message->message, CCREQ_SERVER_INFO); MSG_WriteString (net_message->message, "QUAKE"); MSG_WriteByte (net_message->message, NET_PROTOCOL_VERSION); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Broadcast (dfunc.controlSock, net_message->message->data, net_message->message->cursize); SZ_Clear (net_message->message); @@ -1200,8 +1204,7 @@ _Datagram_SearchForHosts (qboolean xmit) } MSG_BeginReading (net_message); - control = BigLong (*((int *) net_message->message->data)); - MSG_ReadLong (net_message); + control = MSG_ReadLongBE (net_message); if (control == -1) { continue; } @@ -1328,9 +1331,8 @@ _Datagram_Connect (const char *host) MSG_WriteByte (net_message->message, CCREQ_CONNECT); MSG_WriteString (net_message->message, "QUAKE"); MSG_WriteByte (net_message->message, NET_PROTOCOL_VERSION); - *((int *) net_message->message->data) = - BigLong (NETFLAG_CTL | - (net_message->message->cursize & NETFLAG_LENGTH_MASK)); + MSG_PokeLongBE (net_message->message, 0, + NETFLAG_CTL | net_message->message->cursize); dfunc.Write (newsock, net_message->message->data, net_message->message->cursize, &sendaddr); SZ_Clear (net_message->message); @@ -1360,8 +1362,7 @@ _Datagram_Connect (const char *host) net_message->message->cursize = ret; MSG_BeginReading (net_message); - control = BigLong (*((int *) net_message->message->data)); - MSG_ReadLong (net_message); + control = MSG_ReadLongBE (net_message); if (control == -1) { ret = 0; continue; From a630c95eb6999173c9326516233c10281a064e95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 18:31:57 +0900 Subject: [PATCH 1513/3664] [nat] Remove the datagram test commands They seem to be related to the server list protocol, probably from its development, but no longer needed. --- libs/net/nm/net_dgrm.c | 284 ----------------------------------------- 1 file changed, 284 deletions(-) diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 99aff3f51..fe68f321e 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -516,288 +516,6 @@ NET_Stats_f (void) } } - -static qboolean testInProgress = false; -static int testPollCount; -static int testDriver; -static int testSocket; - -static void Test_Poll (void *); -PollProcedure testPollProcedure = { NULL, 0.0, Test_Poll }; - -static void -Test_Poll (void *unused) -{ - netadr_t clientaddr; - int control; - int len; - char name[32]; //FIXME: overflow - char address[64]; //FIXME: overflow - int colors; - int frags; - int connectTime; - byte playerNumber; - - net_landriverlevel = testDriver; - - while (1) { - len = dfunc.Read (testSocket, net_message->message->data, - net_message->message->maxsize, &clientaddr); - if (len < (int) sizeof (int)) { - break; - } - - net_message->message->cursize = len; - - MSG_BeginReading (net_message); - control = MSG_ReadLongBE (net_message); - if (control == -1) { - break; - } - if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) { - break; - } - if ((control & NETFLAG_LENGTH_MASK) != len) { - break; - } - - if (MSG_ReadByte (net_message) != CCREP_PLAYER_INFO) { - Sys_Error ("Unexpected repsonse to Player Info request"); - } - - playerNumber = MSG_ReadByte (net_message); - strcpy (name, MSG_ReadString (net_message)); - colors = MSG_ReadLong (net_message); - frags = MSG_ReadLong (net_message); - connectTime = MSG_ReadLong (net_message); - strcpy (address, MSG_ReadString (net_message)); - - Sys_Printf ("%d, %s\n frags:%3i colors:%u %u time:%u\n %s\n", - playerNumber, name, frags, colors >> 4, colors & 0x0f, - connectTime / 60, address); - } - - testPollCount--; - if (testPollCount) { - SchedulePollProcedure (&testPollProcedure, 0.1); - } else { - dfunc.CloseSocket (testSocket); - testInProgress = false; - } -} - -static void -Test_f (void) -{ - const char *host; - int n; - int max = MAX_SCOREBOARD; - netadr_t sendaddr; - - if (testInProgress) { - return; - } - - host = Cmd_Argv (1); - - if (host && hostCacheCount) { - for (n = 0; n < hostCacheCount; n++) - if (strcasecmp (host, hostcache[n].name) == 0) { - if (hostcache[n].driver != myDriverLevel) { - continue; - } - net_landriverlevel = hostcache[n].ldriver; - max = hostcache[n].maxusers; - memcpy (&sendaddr, &hostcache[n].addr, sizeof (netadr_t)); - break; - } - if (n < hostCacheCount) { - goto JustDoIt; - } - } - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; - net_landriverlevel++) { - if (!net_landrivers[net_landriverlevel].initialized) { - continue; - } - - // see if we can resolve the host name - if (dfunc.GetAddrFromName (host, &sendaddr) != -1) { - break; - } - } - if (net_landriverlevel == net_numlandrivers) { - return; - } - - JustDoIt: - testSocket = dfunc.OpenSocket (0); - if (testSocket == -1) { - return; - } - - testInProgress = true; - testPollCount = 20; - testDriver = net_landriverlevel; - - for (n = 0; n < max; n++) { - SZ_Clear (net_message->message); - // save space for the header, filled in later - MSG_WriteLong (net_message->message, 0); - MSG_WriteByte (net_message->message, CCREQ_PLAYER_INFO); - MSG_WriteByte (net_message->message, n); - MSG_PokeLongBE (net_message->message, 0, - NETFLAG_CTL | net_message->message->cursize); - dfunc.Write (testSocket, net_message->message->data, - net_message->message->cursize, &sendaddr); - } - SZ_Clear (net_message->message); - SchedulePollProcedure (&testPollProcedure, 0.1); -} - - -static qboolean test2InProgress = false; -static int test2Driver; -static int test2Socket; - -static void Test2_Poll (void *); -PollProcedure test2PollProcedure = { NULL, 0.0, Test2_Poll }; - -static void -Test2_Poll (void *unused) -{ - netadr_t clientaddr; - int control; - int len; - char name[256]; //FIXME: overflow - char value[256]; //FIXME: overflow - - net_landriverlevel = test2Driver; - name[0] = 0; - - len = dfunc.Read (test2Socket, net_message->message->data, - net_message->message->maxsize, &clientaddr); - if (len < (int) sizeof (int)) { - goto Reschedule; - } - - net_message->message->cursize = len; - - MSG_BeginReading (net_message); - control = MSG_ReadLongBE (net_message); - if (control == -1) { - goto Error; - } - if ((control & (~NETFLAG_LENGTH_MASK)) != (int) NETFLAG_CTL) { - goto Error; - } - if ((control & NETFLAG_LENGTH_MASK) != len) { - goto Error; - } - - if (MSG_ReadByte (net_message) != CCREP_RULE_INFO) { - goto Error; - } - - strcpy (name, MSG_ReadString (net_message)); - if (name[0] == 0) { - goto Done; - } - strcpy (value, MSG_ReadString (net_message)); - - Sys_Printf ("%-16.16s %-16.16s\n", name, value); - - SZ_Clear (net_message->message); - // save space for the header, filled in later - MSG_WriteLong (net_message->message, 0); - MSG_WriteByte (net_message->message, CCREQ_RULE_INFO); - MSG_WriteString (net_message->message, name); - MSG_PokeLongBE (net_message->message, 0, - NETFLAG_CTL | net_message->message->cursize); - dfunc.Write (test2Socket, net_message->message->data, - net_message->message->cursize, &clientaddr); - SZ_Clear (net_message->message); - - Reschedule: - SchedulePollProcedure (&test2PollProcedure, 0.05); - return; - - Error: - Sys_Printf ("Unexpected repsonse to Rule Info request\n"); - Done: - dfunc.CloseSocket (test2Socket); - test2InProgress = false; - return; -} - -static void -Test2_f (void) -{ - const char *host; - int n; - netadr_t sendaddr; - - if (test2InProgress) { - return; - } - - host = Cmd_Argv (1); - - if (host && hostCacheCount) { - for (n = 0; n < hostCacheCount; n++) { - if (strcasecmp (host, hostcache[n].name) == 0) { - if (hostcache[n].driver != myDriverLevel) { - continue; - } - net_landriverlevel = hostcache[n].ldriver; - memcpy (&sendaddr, &hostcache[n].addr, sizeof (netadr_t)); - break; - } - } - if (n < hostCacheCount) { - goto JustDoIt; - } - } - - for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; - net_landriverlevel++) { - if (!net_landrivers[net_landriverlevel].initialized) { - continue; - } - - // see if we can resolve the host name - if (dfunc.GetAddrFromName (host, &sendaddr) != -1) { - break; - } - } - if (net_landriverlevel == net_numlandrivers) { - return; - } - - JustDoIt: - test2Socket = dfunc.OpenSocket (0); - if (test2Socket == -1) { - return; - } - - test2InProgress = true; - test2Driver = net_landriverlevel; - - SZ_Clear (net_message->message); - // save space for the header, filled in later - MSG_WriteLong (net_message->message, 0); - MSG_WriteByte (net_message->message, CCREQ_RULE_INFO); - MSG_WriteString (net_message->message, ""); - MSG_PokeLongBE (net_message->message, 0, - NETFLAG_CTL | net_message->message->cursize); - dfunc.Write (test2Socket, net_message->message->data, - net_message->message->cursize, &sendaddr); - SZ_Clear (net_message->message); - SchedulePollProcedure (&test2PollProcedure, 0.05); -} - - int Datagram_Init (void) { @@ -823,8 +541,6 @@ Datagram_Init (void) #ifdef BAN_TEST Cmd_AddCommand ("ban", NET_Ban_f, "No Description"); #endif - Cmd_AddCommand ("test", Test_f, "No Description"); - Cmd_AddCommand ("test2", Test2_f, "No Description"); return 0; } From 9fb337fac41526063348c3374743c50bde121738 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Apr 2021 18:38:14 +0900 Subject: [PATCH 1514/3664] [net] Move found host caching into net_main This unifies all the checks and plugs a set of potential buffer overflows. --- include/netmain.h | 5 +-- libs/net/net_main.c | 60 ++++++++++++++++++++++++++++++++--- libs/net/nm/net_dgrm.c | 72 ++++++++++-------------------------------- libs/net/nm/net_loop.c | 20 ++++++------ 4 files changed, 85 insertions(+), 72 deletions(-) diff --git a/include/netmain.h b/include/netmain.h index 351e615ba..43b947aa7 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -262,8 +262,9 @@ typedef struct { netadr_t addr; } hostcache_t; -extern int hostCacheCount; -extern hostcache_t hostcache[HOSTCACHESIZE]; +void NET_AddCachedHost (const char *name, const char *map, const char *cname, + int users, int maxusers, int driver, int ldriver, + const netadr_t *addr); extern double net_time; extern struct msg_s *net_message; diff --git a/libs/net/net_main.c b/libs/net/net_main.c index ee0bc4e1f..d282674b4 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -97,9 +97,11 @@ qboolean recording = false; int net_driverlevel; - double net_time; +static int hostCacheCount = 0; +static hostcache_t hostcache[HOSTCACHESIZE]; + double SetNetTime (void) { @@ -265,6 +267,58 @@ PrintSlistHeader (void) slistLastShown = 0; } +void +NET_AddCachedHost (const char *name, const char *map, const char *cname, + int users, int maxusers, int driver, int ldriver, + const netadr_t *addr) +{ + if (hostCacheCount == HOSTCACHESIZE) { + return; + } + for (int i = 0; i < hostCacheCount; i++) { + // addr will be 0 for loopback, and there can be only one loopback + // server. + if (!addr || !memcmp (addr, &hostcache[i].addr, sizeof (netadr_t))) { + return; + } + } + + const int namesize = sizeof (hostcache[0].name) - 1; + const int mapsize = sizeof (hostcache[0].map) - 1; + const int cnamesize = sizeof (hostcache[0].cname) - 1; + + hostcache_t *host = &hostcache[hostCacheCount++]; + strncpy (host->name, name, namesize); + strncpy (host->map, map, mapsize); + strncpy (host->cname, cname, cnamesize); + host->name[namesize] = 0; + host->map[mapsize] = 0; + host->cname[cnamesize] = 0; + + host->users = users; + host->maxusers = maxusers; + host->driver = driver; + host->ldriver = ldriver; + if (addr) { + host->addr = *addr; + } else { + memset (&host->addr, 0, sizeof (host->addr)); + } + + // check for and resolve name conflicts + for (int i = 0; i < hostCacheCount - 1; i++) { + if (strcasecmp (host->name, hostcache[i].name) == 0) { + int len = strlen (host->name); + if (len < namesize && host->name[len - 1] > '8') { + host->name[len] = '0'; + host->name[len + 1] = 0; + } else { + host->name[len - 1]++; + } + i = -1; // restart loop + } + } +} static void PrintSlist (void) @@ -359,10 +413,6 @@ Slist_Poll (void *unused) slistLocal = true; } - -int hostCacheCount = 0; -hostcache_t hostcache[HOSTCACHESIZE]; - qsocket_t * NET_Connect (const char *host) { diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index fe68f321e..3f9cf50b1 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -880,8 +880,6 @@ static void _Datagram_SearchForHosts (qboolean xmit) { int ret; - int n; - int i; netadr_t readaddr; netadr_t myaddr; int control; @@ -914,11 +912,6 @@ _Datagram_SearchForHosts (qboolean xmit) continue; } - // is the cache full? - if (hostCacheCount == HOSTCACHESIZE) { - continue; - } - MSG_BeginReading (net_message); control = MSG_ReadLongBE (net_message); if (control == -1) { @@ -935,53 +928,25 @@ _Datagram_SearchForHosts (qboolean xmit) continue; } - dfunc.GetAddrFromName (MSG_ReadString (net_message), &readaddr); - // search the cache for this server - for (n = 0; n < hostCacheCount; n++) { - if (dfunc.AddrCompare (&readaddr, &hostcache[n].addr) == 0) { - break; - } + const char *addrstr = MSG_ReadString (net_message); + dfunc.GetAddrFromName (addrstr, &readaddr); + + const char *name = MSG_ReadString (net_message); + const char *map = MSG_ReadString (net_message); + int users = MSG_ReadByte (net_message); + int maxusers = MSG_ReadByte (net_message); + int protocol = MSG_ReadByte (net_message); + const char *cname = dfunc.AddrToString (&readaddr); + + if (protocol != NET_PROTOCOL_VERSION) { + char *new_name = alloca (strlen (name) + 2); + new_name[0] = '*'; + strcpy (new_name + 1, name); + name = new_name; } - // is it already there? - if (n < hostCacheCount) { - continue; - } - - // add it - hostCacheCount++; - strcpy (hostcache[n].name, MSG_ReadString (net_message)); - strcpy (hostcache[n].map, MSG_ReadString (net_message)); - hostcache[n].users = MSG_ReadByte (net_message); - hostcache[n].maxusers = MSG_ReadByte (net_message); - if (MSG_ReadByte (net_message) != NET_PROTOCOL_VERSION) { - strcpy (hostcache[n].cname, hostcache[n].name); - hostcache[n].cname[14] = 0; - strcpy (hostcache[n].name, "*"); - strcat (hostcache[n].name, hostcache[n].cname); - } - memcpy (&hostcache[n].addr, &readaddr, sizeof (netadr_t)); - - hostcache[n].driver = net_driverlevel; - hostcache[n].ldriver = net_landriverlevel; - strcpy (hostcache[n].cname, dfunc.AddrToString (&readaddr)); - - // check for a name conflict - for (i = 0; i < hostCacheCount; i++) { - if (i == n) { - continue; - } - if (strcasecmp (hostcache[n].name, hostcache[i].name) == 0) { - i = strlen (hostcache[n].name); - if (i < 15 && hostcache[n].name[i - 1] > '8') { - hostcache[n].name[i] = '0'; - hostcache[n].name[i + 1] = 0; - } else { - hostcache[n].name[i - 1]++; - } - i = -1; - } - } + NET_AddCachedHost (name, map, cname, users, maxusers, net_driverlevel, + net_landriverlevel, &readaddr); } } @@ -990,9 +955,6 @@ Datagram_SearchForHosts (qboolean xmit) { for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) { - if (hostCacheCount == HOSTCACHESIZE) { - break; - } if (net_landrivers[net_landriverlevel].initialized) { _Datagram_SearchForHosts (xmit); } diff --git a/libs/net/nm/net_loop.c b/libs/net/nm/net_loop.c index 0624688b9..cb1ddb180 100644 --- a/libs/net/nm/net_loop.c +++ b/libs/net/nm/net_loop.c @@ -69,16 +69,16 @@ Loop_SearchForHosts (qboolean xmit) if (!sv.active) return; - hostCacheCount = 1; - if (strcmp (hostname->string, "UNNAMED") == 0) - strcpy (hostcache[0].name, "local"); - else - strcpy (hostcache[0].name, hostname->string); - strcpy (hostcache[0].map, sv.name); - hostcache[0].users = net_activeconnections; - hostcache[0].maxusers = svs.maxclients; - hostcache[0].driver = net_driverlevel; - strcpy (hostcache[0].cname, "local"); + const char *name = "local"; + if (strcmp (hostname->string, "UNNAMED") != 0) { + name = hostname->string; + } + const char *map = sv.name; + int users = net_activeconnections; + int maxusers = svs.maxclients; + const char *cname = "local"; + NET_AddCachedHost (name, map, cname, users, maxusers, net_driverlevel, + 0, 0); } From 87eccb9e6f7e67b52289b7e49f76328a41d70684 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Apr 2021 20:09:03 +0900 Subject: [PATCH 1515/3664] [nq] Ensure stuffcmd is done for cl_quakerc 0 This was done years ago for qw, but missed for nq. --- nq/source/host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nq/source/host.c b/nq/source/host.c index ac13143e7..6f815ebf9 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -931,7 +931,7 @@ Host_Init (void) Cmd_Exec_File (host_cbuf, fs_usercfg->string, 0); // reparse the command line for + commands other than set // (sets still done, but it doesn't matter) - if (isDedicated || (cl_quakerc->int_val && check_quakerc ())) + if (isDedicated || !cl_quakerc->int_val || check_quakerc ()) Cmd_StuffCmds (host_cbuf); Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); From 1e9329ccf69aecdc3dec5d0ec47070b368811941 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 12 Apr 2021 22:09:09 +0900 Subject: [PATCH 1516/3664] [nq,qw] Stop wring to config.cfg QF now uses its own configuration file (quakeforge.cfg for now) rather than overwriting config.cfg so that people trying out QF in their normal quake installs don't trash their config.cfg for other quake clients. If quakeforge.cfg is present, all other config files are ignored except that quake.rc is scanned for a startdemos command and that is executed. --- include/QF/cmd.h | 2 +- include/QF/qargs.h | 4 ++- libs/util/cmd.c | 7 ++-- libs/util/qargs.c | 65 +++++++++++++++++++++++++++------ nq/source/cl_main.c | 11 +++--- nq/source/host.c | 32 ++--------------- qtv/source/qtv.c | 2 +- qw/source/cl_main.c | 69 ++++++++++-------------------------- qw/source/sv_main.c | 2 +- ruamoko/qwaq/builtins/main.c | 2 +- ruamoko/qwaq/builtins/qwaq.c | 2 +- 11 files changed, 93 insertions(+), 105 deletions(-) diff --git a/include/QF/cmd.h b/include/QF/cmd.h index 3cd74432b..b57e8ca15 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -79,7 +79,7 @@ int Cmd_Command (struct cbuf_args_s *args); int Cmd_ExecuteString (const char *text, cmd_source_t src); struct cbuf_s; void Cmd_StuffCmds (struct cbuf_s *cbuf); -void Cmd_Exec_File (struct cbuf_s *cbuf, const char *path, int qfs); +int Cmd_Exec_File (struct cbuf_s *cbuf, const char *path, int qfs); void Cmd_AddProvider(const char *name, struct cbuf_interpreter_s *interp); struct cbuf_interpreter_s *Cmd_GetProvider(const char *name); diff --git a/include/QF/qargs.h b/include/QF/qargs.h index bf49495a4..89ce6902c 100644 --- a/include/QF/qargs.h +++ b/include/QF/qargs.h @@ -48,7 +48,9 @@ void COM_AddParm (const char *parm); void COM_Init (void); void COM_Init_Cvars (void); void COM_InitArgv (int argc, const char **argv); -void COM_ParseConfig (void); +struct cbuf_s; +void COM_ParseConfig (struct cbuf_s *cbuf); +void COM_ExecConfig (struct cbuf_s *cbuf, int skip_quakerc); ///@} diff --git a/libs/util/cmd.c b/libs/util/cmd.c index ffc6a14e6..c3e2c20c4 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -497,6 +497,7 @@ Cmd_Help_f (void) Sys_Printf ("variable/command not found\n"); } + static void Cmd_Exec_f (void) { @@ -649,7 +650,7 @@ Cmd_ExecuteString (const char *text, cmd_source_t src) return 0; } -VISIBLE void +VISIBLE int Cmd_Exec_File (cbuf_t *cbuf, const char *path, int qfs) { char *f; @@ -657,7 +658,7 @@ Cmd_Exec_File (cbuf_t *cbuf, const char *path, int qfs) QFile *file; if (!path || !*path) - return; + return 0; if (qfs) { file = QFS_FOpenFile (path); } else { @@ -675,7 +676,9 @@ Cmd_Exec_File (cbuf_t *cbuf, const char *path, int qfs) free (f); } Qclose (file); + return 1; } + return 0; } VISIBLE void diff --git a/libs/util/qargs.c b/libs/util/qargs.c index 7f385e5a1..b1d6510db 100644 --- a/libs/util/qargs.c +++ b/libs/util/qargs.c @@ -46,8 +46,10 @@ #include "QF/cvar.h" #include "QF/idparse.h" #include "QF/qargs.h" +#include "QF/quakefs.h" #include "QF/qtypes.h" #include "QF/sys.h" +#include "QF/va.h" cvar_t *fs_globalcfg; cvar_t *fs_usercfg; @@ -151,20 +153,13 @@ COM_AddParm (const char *parm) } void -COM_ParseConfig (void) +COM_ParseConfig (cbuf_t *cbuf) { - cbuf_t *cbuf; - - cbuf = Cbuf_New (&id_interp); - // execute +set as early as possible Cmd_StuffCmds (cbuf); Cbuf_Execute_Sets (cbuf); - // execute the global configuration file if it exists - // would have been nice if Cmd_Exec_f could have been used, but it - // reads from only within the quake file system, and changing that is - // probably Not A Good Thing (tm). + // execute set commands in the global configuration file if it exists fs_globalcfg = Cvar_Get ("fs_globalcfg", FS_GLOBALCFG, CVAR_ROM, NULL, "global configuration file"); Cmd_Exec_File (cbuf, fs_globalcfg->string, 0); @@ -174,6 +169,7 @@ COM_ParseConfig (void) Cmd_StuffCmds (cbuf); Cbuf_Execute_Sets (cbuf); + // execute set commands in the user configuration file if it exists fs_usercfg = Cvar_Get ("fs_usercfg", FS_USERCFG, CVAR_ROM, NULL, "user configuration file"); Cmd_Exec_File (cbuf, fs_usercfg->string, 0); @@ -182,6 +178,53 @@ COM_ParseConfig (void) // execute +set again to override the config file Cmd_StuffCmds (cbuf); Cbuf_Execute_Sets (cbuf); - - Cbuf_Delete (cbuf); +} + +static int +check_quakerc (const char *cmd, cbuf_t *cbuf) +{ + const char *l, *p; + int ret = 0; + QFile *f; + + f = QFS_FOpenFile ("quake.rc"); + while (f && (l = Qgetline (f))) { + if ((p = strstr (l, cmd))) { + if (p == l) { + if (cbuf) { + Cbuf_AddText (cbuf, l); + } + ret = 1; + break; + } + } + } + Qclose (f); + return ret; +} + +void +COM_ExecConfig (cbuf_t *cbuf, int skip_quakerc) +{ + // quakeforge.cfg overrides quake.rc as it contains quakeforge-specific + // commands. If it doesn't exist, then this is the first time quakeforge + // has been used in this installation, thus any existing legacy config + // should be used to set up defaults on the assumption that the user has + // things set up to work with another (hopefully compatible) client + if (Cmd_Exec_File (cbuf, "quakeforge.cfg", 1)) { + Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cmd_StuffCmds (cbuf); + check_quakerc ("startdemos", cbuf); + } else { + if (!skip_quakerc) { + Cbuf_InsertText (cbuf, "exec quake.rc\n"); + } + Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + // Reparse the command line for + commands. + // (sets still done, but it doesn't matter) + // (Note, no non-base commands exist yet) + if (skip_quakerc || !check_quakerc ("stuffcmds", 0)) { + Cmd_StuffCmds (cbuf); + } + } } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index d95aef4c7..88b7a78bb 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -103,21 +103,20 @@ client_state_t cl; static void CL_WriteConfiguration (void) { - QFile *f; - // dedicated servers initialize the host but don't parse and set the // config.cfg cvars if (host_initialized && !isDedicated && cl_writecfg->int_val) { - const char *path = va (0, "%s/config.cfg", qfs_gamedir->dir.def); - f = QFS_WOpen (path, 0); + const char *path = va (0, "%s/quakeforge.cfg", qfs_gamedir->dir.def); + QFile *f = QFS_WOpen (path, 0); + if (!f) { - Sys_Printf ("Couldn't write config.cfg.\n"); + Sys_Printf ("Couldn't write quakeforge.cfg.\n"); return; } Key_WriteBindings (f); - Cvar_WriteVariables (f); Joy_WriteBindings (f); + Cvar_WriteVariables (f); Qclose (f); } diff --git a/nq/source/host.c b/nq/source/host.c index 6f815ebf9..9f6b098d0 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -808,28 +808,6 @@ Host_InitVCR (quakeparms_t *parms) } -static int -check_quakerc (void) -{ - const char *l, *p; - int ret = 1; - QFile *f; - - f = QFS_FOpenFile ("quake.rc"); - if (!f) - return 1; - while ((l = Qgetline (f))) { - if ((p = strstr (l, "stuffcmds"))) { - if (p == l) { // only known case so far - ret = 0; - break; - } - } - } - Qclose (f); - return ret; -} - static void Host_Init_Memory (void) { @@ -886,7 +864,7 @@ Host_Init (void) Sys_Init (); GIB_Init (true); - COM_ParseConfig (); + COM_ParseConfig (host_cbuf); Host_Init_Memory (); @@ -926,13 +904,7 @@ Host_Init (void) CL_UpdateScreen (cl.time); CL_UpdateScreen (cl.time); - if (!isDedicated && cl_quakerc->int_val) - Cbuf_InsertText (host_cbuf, "exec quake.rc\n"); - Cmd_Exec_File (host_cbuf, fs_usercfg->string, 0); - // reparse the command line for + commands other than set - // (sets still done, but it doesn't matter) - if (isDedicated || !cl_quakerc->int_val || check_quakerc ()) - Cmd_StuffCmds (host_cbuf); + COM_ExecConfig (host_cbuf, isDedicated || !cl_quakerc->int_val); Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); host_hunklevel = Hunk_LowMark (); diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 0348198f8..d1da80448 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -255,7 +255,7 @@ qtv_init (void) Sys_RegisterShutdown (qtv_shutdown, 0); Sys_Init (); - COM_ParseConfig (); + COM_ParseConfig (qtv_cbuf); Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); qtv_memory_init (); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index e2deb673b..7199dbb38 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -72,6 +72,7 @@ #include "QF/draw.h" #include "QF/image.h" #include "QF/input.h" +#include "QF/joystick.h" #include "QF/keys.h" #include "QF/model.h" #include "QF/msg.h" @@ -1505,26 +1506,20 @@ Host_Error (const char *error, ...) } } -/* - Host_WriteConfiguration - - Writes key bindings and archived cvars to config.cfg -*/ void Host_WriteConfiguration (void) { - QFile *f; - if (host_initialized && cl_writecfg->int_val) { - const char *path = va (0, "%s/config.cfg", qfs_gamedir->dir.def); + const char *path = va (0, "%s/quakeforge.cfg", qfs_gamedir->dir.def); + QFile *f = QFS_WOpen (path, 0); - f = QFS_WOpen (path, 0); if (!f) { - Sys_Printf ("Couldn't write config.cfg.\n"); + Sys_Printf ("Couldn't write quakeforge.cfg.\n"); return; } Key_WriteBindings (f); + Joy_WriteBindings (f); Cvar_WriteVariables (f); Qclose (f); @@ -1713,28 +1708,6 @@ Host_Frame (float time) fps_count++; } -static int -check_quakerc (void) -{ - const char *l, *p; - int ret = 1; - QFile *f; - - f = QFS_FOpenFile ("quake.rc"); - if (!f) - return 1; - while ((l = Qgetline (f))) { - if ((p = strstr (l, "stuffcmds"))) { - if (p == l) { // only known case so far - ret = 0; - break; - } - } - } - Qclose (f); - return ret; -} - static void CL_Init_Memory (void) { @@ -1773,19 +1746,21 @@ CL_Init_Memory (void) static void CL_Autoexec (int phase) { - int cmd_warncmd_val = cmd_warncmd->int_val; - if (!phase) return; - Cbuf_AddText (cl_cbuf, "cmd_warncmd 0\n"); - Cbuf_AddText (cl_cbuf, "exec config.cfg\n"); - Cbuf_AddText (cl_cbuf, "exec frontend.cfg\n"); + if (!Cmd_Exec_File (cl_cbuf, "quakeforge.cfg", 1)) { + int cmd_warncmd_val = cmd_warncmd->int_val; + + Cbuf_AddText (cl_cbuf, "cmd_warncmd 0\n"); + Cbuf_AddText (cl_cbuf, "exec config.cfg\n"); + Cbuf_AddText (cl_cbuf, "exec frontend.cfg\n"); + + Cbuf_AddText (cl_cbuf, va (0, "cmd_warncmd %d\n", cmd_warncmd_val)); + } if (cl_autoexec->int_val) { Cbuf_AddText (cl_cbuf, "exec autoexec.cfg\n"); } - - Cbuf_AddText (cl_cbuf, va (0, "cmd_warncmd %d\n", cmd_warncmd_val)); } void @@ -1796,7 +1771,7 @@ Host_Init (void) Sys_Init (); GIB_Init (true); - COM_ParseConfig (); + COM_ParseConfig (cl_cbuf); CL_Init_Memory (); @@ -1837,13 +1812,10 @@ Host_Init (void) CL_UpdateScreen (realtime); CL_UpdateScreen (realtime); - if (cl_quakerc->int_val) - Cbuf_InsertText (cl_cbuf, "exec quake.rc\n"); - Cmd_Exec_File (cl_cbuf, fs_usercfg->string, 0); - // Reparse the command line for + commands. - // (Note, no non-base commands exist yet) - if (!cl_quakerc->int_val || check_quakerc ()) - Cmd_StuffCmds (cl_cbuf); + COM_ExecConfig (cl_cbuf, !cl_quakerc->int_val); + + // make sure all + commands have been executed + Cbuf_Execute_Stack (cl_cbuf); Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); host_hunklevel = Hunk_LowMark (); @@ -1853,9 +1825,6 @@ Host_Init (void) Sys_Printf ("\x80\x81\x81\x82 %s initialized \x80\x81\x81\x82\n", PACKAGE_NAME); - // make sure all + commands have been executed - Cbuf_Execute_Stack (cl_cbuf); - host_initialized = true; CL_UpdateScreen (realtime); diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 9a540af08..30e2709c1 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2488,7 +2488,7 @@ SV_Init (void) Sys_Init (); GIB_Init (true); - COM_ParseConfig (); + COM_ParseConfig (sv_cbuf); Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 8c8ec0f69..4404294dc 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -134,7 +134,7 @@ init_qf (void) qwaq_cbuf = Cbuf_New (&id_interp); Sys_Init (); - COM_ParseConfig (); + COM_ParseConfig (qwaq_cbuf); //Cvar_Set (developer, "1"); diff --git a/ruamoko/qwaq/builtins/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c index fa18d01b1..00a7ca135 100644 --- a/ruamoko/qwaq/builtins/qwaq.c +++ b/ruamoko/qwaq/builtins/qwaq.c @@ -110,7 +110,7 @@ init_qf (void) Sys_Init (); GIB_Init (true); - COM_ParseConfig (); + COM_ParseConfig (qwaq_cbuf); //Cvar_Set (developer, "1"); From da39bb2df36361de12fc1f42e1232fa36ac21fee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Apr 2021 18:56:31 +0900 Subject: [PATCH 1517/3664] [vulkan] Use more correct dependency flags I was reading about multi-pass rendering on mobile devices (https://developer.oculus.com/blog/loads-stores-passes-and-advanced-gpu-pipelines/) and discovered that I had used the wrong flags (but then, I think Graham Sellers had, too, since used his Vulkan Programming Guide as a reference). Doesn't seem to make any difference on desktop, but as there's no loss there, but potential gains on mobile, I'd say it's a win. --- libs/video/renderer/vulkan/deferred.plist | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index d956a5792..0e414453e 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -426,19 +426,19 @@ { srcSubpass = 0; // depth dstSubpass = 1; // translucent - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = shader_read; + srcStageMask = late_fragment_tests; + dstStageMask = fragment_shader|early_fragment_tests; + srcAccessMask = depth_stencil_attachment_write; + dstAccessMask = input_attachment_read|depth_stencil_attachment_read; dependencyFlags = by_region; }, { srcSubpass = 0; // depth dstSubpass = 2; // g-buffer - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = shader_read; + srcStageMask = late_fragment_tests; + dstStageMask = early_fragment_tests; + srcAccessMask = depth_stencil_attachment_write; + dstAccessMask = depth_stencil_attachment_read; dependencyFlags = by_region; }, { @@ -447,7 +447,7 @@ srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; - dstAccessMask = shader_read; + dstAccessMask = input_attachment_read; dependencyFlags = by_region; }, { @@ -456,7 +456,7 @@ srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; - dstAccessMask = shader_read; + dstAccessMask = input_attachment_read; dependencyFlags = by_region; }, { @@ -465,7 +465,7 @@ srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; - dstAccessMask = shader_read; + dstAccessMask = input_attachment_read; dependencyFlags = by_region; }, ); From 52bfb0aeb048d0571ca649a9c656e7b837d7c933 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Apr 2021 20:40:43 +0900 Subject: [PATCH 1518/3664] [vulkan] Label the drawing command buffers --- libs/video/renderer/vulkan/vulkan_alias.c | 5 +++++ libs/video/renderer/vulkan/vulkan_bsp.c | 3 ++- libs/video/renderer/vulkan/vulkan_compose.c | 3 +++ libs/video/renderer/vulkan/vulkan_draw.c | 8 ++++++++ libs/video/renderer/vulkan/vulkan_lighting.c | 7 +++++-- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index b00814427..f84e4e9c8 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -191,6 +191,10 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "alias:%s", + alias_pass_names[subpass]), + { 0.6, 0.5, 0, 1}); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); //VkDescriptorSet sets[] = { // aframe->descriptors[0].dstSet, @@ -216,6 +220,7 @@ alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 07d573caa..c498ee09b 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -891,7 +891,8 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - QFV_duCmdBeginLabel (device, cmd, bsp_pass_names[subpass], + QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "bsp:%s", + bsp_pass_names[subpass]), {0, 0.5, 0.6, 1}); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 66a9afc6d..70b41e92a 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -79,6 +79,8 @@ Vulkan_Compose_Draw (vulkan_ctx_t *ctx) }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + QFV_duCmdBeginLabel (device, cmd, "compose", { 0, 0.2, 0.6, 1}); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, cctx->pipeline); @@ -101,6 +103,7 @@ Vulkan_Compose_Draw (vulkan_ctx_t *ctx) dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); + QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index f7aeabb97..9aa532d58 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -46,6 +46,7 @@ #include "QF/quakefs.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/vid.h" #include "compat.h" @@ -54,6 +55,7 @@ #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" @@ -440,6 +442,9 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) }; dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); dframe->cmd = cmdBuffers->a[i]; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + dframe->cmd, + va (ctx->va_ctx, "cmd:draw:%zd", i)); } free (sets); } @@ -730,6 +735,8 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + QFV_duCmdBeginLabel (device, cmd, "twod", { 0.6, 0.2, 0, 1}); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dctx->pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); @@ -745,6 +752,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD, 1, 0, 0, 0); + QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); dframe->num_quads = 0; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 9a4ab76a4..1a1ce9e47 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -143,8 +143,8 @@ update_lights (vulkan_ctx_t *ctx) VectorZero (light_data->lights[i].direction); light_data->lights[i].cone = 1; } - for (size_t i = 0; - i < lframe->lightvis.size && light_data->lightCount < NUM_LIGHTS; i++) { + for (size_t i = 0; (i < lframe->lightvis.size + && light_data->lightCount < NUM_LIGHTS); i++) { if (lframe->lightvis.a[i]) { light_data->lights[light_data->lightCount++] = lctx->lights.a[i]; } @@ -207,6 +207,8 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + QFV_duCmdBeginLabel (device, cmd, "lighting", { 0.6, 0.5, 0.6, 1}); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, lctx->pipeline); @@ -237,6 +239,7 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); + QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); } From 2918410b30484e181f0f133e95bce12b60288007 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Apr 2021 20:41:08 +0900 Subject: [PATCH 1519/3664] [vulkan] Fix a couple of minor issues Magic number for compose descriptors and mistaken masking of vulkan plist parse errors. --- libs/video/renderer/vulkan/vkparse.c | 3 +-- libs/video/renderer/vulkan/vulkan_compose.c | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 15218e93c..51f574ef9 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -986,8 +986,7 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, if (!parser (0, plist, object, messages, &parsectx)) { for (int i = 0; i < PL_A_NumObjects (messages); i++) { - Sys_MaskPrintf (SYS_vulkan_parse, "%s\n", - PL_String (PL_ObjectAtIndex (messages, i))); + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } return 0; } diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 70b41e92a..5b86ca457 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -88,7 +88,8 @@ Vulkan_Compose_Draw (vulkan_ctx_t *ctx) = ctx->attachment_views->a[QFV_attachOpaque]; cframe->imageInfo[1].imageView = ctx->attachment_views->a[QFV_attachTranslucent]; - dfunc->vkUpdateDescriptorSets (device->dev, 2, cframe->descriptors, 0, 0); + dfunc->vkUpdateDescriptorSets (device->dev, COMPOSE_IMAGE_INFOS, + cframe->descriptors, 0, 0); VkDescriptorSet sets[] = { cframe->descriptors[0].dstSet, From 140425be33e301eb6792db1e6c20a442dc3a7d5c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Apr 2021 17:49:03 +0900 Subject: [PATCH 1520/3664] [vulkan] Name some more objects Shaders and descriptor set layouts. --- libs/video/renderer/vulkan/shader.c | 3 +++ libs/video/renderer/vulkan/vkparse.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index dd28cf8c6..687f52be2 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -45,6 +45,7 @@ #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" @@ -170,6 +171,8 @@ QFV_CreateShaderModule (qfv_device_t *device, const char *shader_path) }; dfunc->vkCreateShaderModule (dev, &createInfo, 0, &shader); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_SHADER_MODULE, shader, + shader_path); } else { Sys_MaskPrintf (SYS_vulkan, "QFV_CreateShaderModule: could not find shader %s\n", diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 51f574ef9..d9c49f7c9 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1092,6 +1092,9 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist, VkDescriptorSetLayout setLayout; dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, &setLayout); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, + setLayout, va (ctx->va_ctx, "descriptorSetLayout:%d", + PL_Line (plist))); delete_memsuper (memsuper); return setLayout; From c29e9828b6108004dfbc58aa9fc05b01b0e2d3cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Apr 2021 19:47:42 +0900 Subject: [PATCH 1521/3664] [vulkan] Clean up misuse of va for vulkan handles The built up "path" name of the handle resource was not always surviving the intervening call to cexpr_eval_string (in particular, when other handles were created in the process of creating a handle). Rather than simply increase the number of va buffers (where would it end?), just regenerate the path when adding the new handle. It's probably quick enough, and the code is not usually not on a critical path. --- libs/video/renderer/vulkan/vkparse.c | 90 ++++++++++++++++------------ 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index d9c49f7c9..a1616b722 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -419,6 +419,19 @@ QFV_AddHandle (hashtab_t *tab, const char *name, uint64_t handle) Hash_Add (tab, hr); } +static const char * +resource_path (vulkan_ctx_t *ctx, const char *prefix, const char *name) +{ + if (name[0] != '$') { + if (prefix) { + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s.%s", prefix, name); + } else { + name = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); + } + } + return name; +} + static int parse_VkRenderPass (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context) @@ -430,12 +443,10 @@ parse_VkRenderPass (const plitem_t *item, void **data, vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkRenderPass: %s\n", name); - if (name[0] != '$') { - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); - } + const char *path = resource_path (ctx, 0, name); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkRenderPass: %s\n", path); - *handle = (VkRenderPass) QFV_GetHandle (ctx->renderpasses, name); + *handle = (VkRenderPass) QFV_GetHandle (ctx->renderpasses, path); if (*handle) { return 1; } @@ -444,13 +455,15 @@ parse_VkRenderPass (const plitem_t *item, void **data, exprval_t result = { &cexpr_plitem, &setItem }; ectx.symtab = 0; ectx.result = &result; - ret = !cexpr_eval_string (name, &ectx); + ret = !cexpr_eval_string (path, &ectx); if (ret) { VkRenderPass setLayout; setLayout = QFV_ParseRenderPass (ctx, setItem, pctx->properties); *handle = (VkRenderPass) setLayout; - QFV_AddHandle (ctx->setLayouts, name, (uint64_t) setLayout); + // path not guaranteed to survive cexpr_eval_string due to va + path = resource_path (ctx, 0, name); + QFV_AddHandle (ctx->setLayouts, path, (uint64_t) setLayout); } return ret; } @@ -487,13 +500,11 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); + const char *path = resource_path (ctx, "setLayouts", name); Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkDescriptorSetLayout: %s\n", - name); - if (name[0] != '$') { - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); - } + path); - *handle = (VkDescriptorSetLayout) QFV_GetHandle (ctx->setLayouts, name); + *handle = (VkDescriptorSetLayout) QFV_GetHandle (ctx->setLayouts, path); if (*handle) { return 1; } @@ -502,14 +513,16 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, exprval_t result = { &cexpr_plitem, &setItem }; ectx.symtab = 0; ectx.result = &result; - ret = !cexpr_eval_string (name, &ectx); + ret = !cexpr_eval_string (path, &ectx); if (ret) { VkDescriptorSetLayout setLayout; setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem, pctx->properties); *handle = (VkDescriptorSetLayout) setLayout; - QFV_AddHandle (ctx->setLayouts, name, (uint64_t) setLayout); + // path not guaranteed to survive cexpr_eval_string due to va + path = resource_path (ctx, "setLayouts", name); + QFV_AddHandle (ctx->setLayouts, path, (uint64_t) setLayout); } return ret; } @@ -524,12 +537,10 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkPipelineLayout: %s\n", name); - if (name[0] != '$') { - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); - } + const char *path = resource_path (ctx, "pipelineLayouts", name); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkPipelineLayout: %s\n", path); - *handle = (VkPipelineLayout) QFV_GetHandle (ctx->pipelineLayouts, name); + *handle = (VkPipelineLayout) QFV_GetHandle (ctx->pipelineLayouts, path); if (*handle) { return 1; } @@ -538,13 +549,15 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, exprval_t result = { &cexpr_plitem, &setItem }; ectx.symtab = 0; ectx.result = &result; - ret = !cexpr_eval_string (name, &ectx); + ret = !cexpr_eval_string (path, &ectx); if (ret) { VkPipelineLayout layout; layout = QFV_ParsePipelineLayout (ctx, setItem, context->properties); *handle = (VkPipelineLayout) layout; - QFV_AddHandle (ctx->pipelineLayouts, name, (uint64_t) layout); + // path not guaranteed to survive cexpr_eval_string due to va + path = resource_path (ctx, "pipelineLayouts", name); + QFV_AddHandle (ctx->pipelineLayouts, path, (uint64_t) layout); } return ret; } @@ -559,12 +572,10 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImage: %s\n", name); - if (name[0] != '$') { - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); - } + const char *path = resource_path (ctx, "images", name); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImage: %s\n", path); - *handle = (VkImage) QFV_GetHandle (ctx->images, name); + *handle = (VkImage) QFV_GetHandle (ctx->images, path); if (*handle) { return 1; } @@ -573,13 +584,15 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, exprval_t result = { &cexpr_plitem, &imageItem }; ectx.symtab = 0; ectx.result = &result; - ret = !cexpr_eval_string (name, &ectx); + ret = !cexpr_eval_string (path, &ectx); if (ret) { VkImage image; image = QFV_ParseImage (ctx, imageItem, context->properties); *handle = (VkImage) image; - QFV_AddHandle (ctx->images, name, (uint64_t) image); + // path not guaranteed to survive cexpr_eval_string due to va + path = resource_path (ctx, "images", name); + QFV_AddHandle (ctx->images, path, (uint64_t) image); } return ret; } @@ -601,12 +614,10 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, vulkan_ctx_t *ctx = context->vctx; const char *name = PL_String (item); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImageView: %s\n", name); - if (name[0] != '$') { - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name); - } + const char *path = resource_path (ctx, "imageViews", name); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImageView: %s\n", path); - *handle = (VkImageView) QFV_GetHandle (ctx->imageViews, name); + *handle = (VkImageView) QFV_GetHandle (ctx->imageViews, path); if (*handle) { return 1; } @@ -615,7 +626,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, exprval_t result = { &cexpr_exprval, &value }; ectx.symtab = 0; ectx.result = &result; - ret = !cexpr_eval_string (name, &ectx); + ret = !cexpr_eval_string (path, &ectx); plitem_t *imageViewItem = 0; if (ret) { @@ -625,7 +636,9 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, } else if (value->type == &cexpr_plitem) { imageView = QFV_ParseImageView (ctx, imageViewItem, context->properties); - QFV_AddHandle (ctx->imageViews, name, (uint64_t) imageView); + // path not guaranteed to survive cexpr_eval_string due to va + path = resource_path (ctx, "imageViews", name); + QFV_AddHandle (ctx->imageViews, path, (uint64_t) imageView); } else { PL_Message (messages, item, "not a VkImageView"); return 0; @@ -1118,6 +1131,9 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, VkPipelineLayout layout; dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &layout); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, + layout, va (ctx->va_ctx, "pipelineLayout:%d", + PL_Line (plist))); delete_memsuper (memsuper); return layout; @@ -1285,7 +1301,7 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) const char *name = PL_KeyAtIndex (item, i); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, set->a[i], va (ctx->va_ctx, "image:%s", name)); - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name); + name = resource_path (ctx, "images", name); QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]); } @@ -1322,7 +1338,7 @@ QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, dfunc->vkCreateImageView (device->dev, &create.info[i], 0, &set->a[i]); const char *name = PL_KeyAtIndex (item, i); - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name); + name = resource_path (ctx, "imageViews", name); QFV_AddHandle (ctx->imageViews, name, (uint64_t) set->a[i]); } From 8c03ed8be54ffc2e763235064a86002615d4dab1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Apr 2021 10:40:39 +0900 Subject: [PATCH 1522/3664] [vulkan] Start work on shadows This gets the shaders needed for creating shadow maps, and the changes to the lighting pipeline for binding the shadow maps, but no generation or reading is done yet. It feels like parts of various systems are getting a little big for their britches and I need to do an audit of various things. --- include/QF/Vulkan/qf_lighting.h | 26 ++++- libs/models/brush/model_brush.c | 6 +- libs/video/renderer/Makemodule.am | 20 +++- libs/video/renderer/vulkan/qfpipeline.plist | 106 ++++++++++++++++-- libs/video/renderer/vulkan/shader.c | 9 ++ .../renderer/vulkan/shader/alias_shadow.vert | 23 ++++ .../renderer/vulkan/shader/bsp_shadow.vert | 16 +++ .../renderer/vulkan/shader/lighting.frag | 48 +++++++- libs/video/renderer/vulkan/shader/shadow.geom | 25 +++++ libs/video/renderer/vulkan/shadow.plist | 71 ++++++++++++ libs/video/renderer/vulkan/vulkan_lighting.c | 83 ++++++++++---- 11 files changed, 389 insertions(+), 44 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/alias_shadow.vert create mode 100644 libs/video/renderer/vulkan/shader/bsp_shadow.vert create mode 100644 libs/video/renderer/vulkan/shader/shadow.geom create mode 100644 libs/video/renderer/vulkan/shadow.plist diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 8541d367e..346f2bf5f 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -35,6 +35,7 @@ #include "QF/modelgen.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" +#include "QF/simd/types.h" typedef struct qfv_light_s { vec3_t color; @@ -53,21 +54,35 @@ typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t; #define NUM_STYLES 64 typedef struct qfv_light_buffer_s { - float intensity[NUM_STYLES + 3]; + float intensity[NUM_STYLES + 4]; + int cascadeCount; + int planeCount; + int cubeCount; int lightCount; qfv_light_t lights[NUM_LIGHTS] __attribute__((aligned(16))); + mat4f_t shadowMat[NUM_LIGHTS]; + vec4f_t shadowCascade[NUM_LIGHTS]; } qfv_light_buffer_t; #define LIGHTING_BUFFER_INFOS 1 -#define LIGHTING_IMAGE_INFOS 5 +#define LIGHTING_ATTACH_INFOS 5 +#define LIGHTING_SHADOW_INFOS NUM_LIGHTS +#define LIGHTING_DESCRIPTORS (LIGHTING_BUFFER_INFOS + LIGHTING_ATTACH_INFOS + 1) typedef struct lightingframe_s { VkCommandBuffer cmd; VkBuffer light_buffer; VkDescriptorBufferInfo bufferInfo[LIGHTING_BUFFER_INFOS]; - VkDescriptorImageInfo imageInfo[LIGHTING_IMAGE_INFOS]; - VkWriteDescriptorSet descriptors[LIGHTING_BUFFER_INFOS - + LIGHTING_IMAGE_INFOS]; + VkDescriptorImageInfo attachInfo[LIGHTING_ATTACH_INFOS]; + VkDescriptorImageInfo shadowInfo[LIGHTING_SHADOW_INFOS]; + union { + VkWriteDescriptorSet descriptors[LIGHTING_DESCRIPTORS]; + struct { + VkWriteDescriptorSet bufferWrite[LIGHTING_BUFFER_INFOS]; + VkWriteDescriptorSet attachWrite[LIGHTING_ATTACH_INFOS]; + VkWriteDescriptorSet shadowWrite; + }; + }; // A fat PVS of leafs visible from visible leafs so hidden lights can // illuminate the leafs visible to the player byte pvs[MAP_PVS_BYTES]; @@ -82,6 +97,7 @@ typedef struct lightingctx_s { lightingframeset_t frames; VkPipeline pipeline; VkPipelineLayout layout; + VkSampler sampler; VkDeviceMemory light_memory; qfv_lightset_t lights; qfv_lightleafset_t lightleafs; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 9e7607595..db9298ad5 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -169,8 +169,7 @@ Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, memset (out, defvis, sizeof (mod_novis)); return; } - return Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, defvis, - out); + Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, defvis, out); } VISIBLE void @@ -183,8 +182,7 @@ Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, } return; } - return Mod_DecompressVis_mix (leaf->compressed_vis, &model->brush, defvis, - out); + Mod_DecompressVis_mix (leaf->compressed_vis, &model->brush, defvis, out); } // BRUSHMODEL LOADING ========================================================= diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 184342781..91162d71e 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -311,6 +311,8 @@ bsp_gbufg_src = $(vkshaderpath)/bsp_gbuf.geom bsp_gbufg_c = $(vkshaderpath)/bsp_gbuf.geom.spvc bsp_gbuff_src = $(vkshaderpath)/bsp_gbuf.frag bsp_gbuff_c = $(vkshaderpath)/bsp_gbuf.frag.spvc +bsp_shadow_src = $(vkshaderpath)/bsp_shadow.vert +bsp_shadow_c = $(vkshaderpath)/bsp_shadow.vert.spvc bsp_skyf_src = $(vkshaderpath)/bsp_sky.frag bsp_skyf_c = $(vkshaderpath)/bsp_sky.frag.spvc bsp_turbf_src = $(vkshaderpath)/bsp_turb.frag @@ -327,10 +329,14 @@ alias_depth_src = $(vkshaderpath)/alias_depth.vert alias_depth_c = $(vkshaderpath)/alias_depth.vert.spvc alias_gbuf_src = $(vkshaderpath)/alias_gbuf.frag alias_gbuf_c = $(vkshaderpath)/alias_gbuf.frag.spvc +alias_shadow_src = $(vkshaderpath)/alias_shadow.vert +alias_shadow_c = $(vkshaderpath)/alias_shadow.vert.spvc passthrough_src = $(vkshaderpath)/passthrough.vert passthrough_c = $(vkshaderpath)/passthrough.vert.spvc pushcolor_src = $(vkshaderpath)/pushcolor.frag pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc +shadow_src = $(vkshaderpath)/shadow.geom +shadow_c = $(vkshaderpath)/shadow.geom.spvc $(twodv_c): $(twodv_src) @@ -348,6 +354,8 @@ $(bsp_gbufg_c): $(bsp_gbufg_src) $(bsp_gbuff_c): $(bsp_gbuff_src) +$(bsp_shadow_c): $(bsp_shadow_src) + $(bsp_skyf_c): $(bsp_skyf_src) $(bsp_turbf_c): $(bsp_turbf_src) @@ -364,10 +372,14 @@ $(aliasf_c): $(aliasf_src) $(alias_gbuf_c): $(alias_gbuf_src) +$(alias_shadow_c): $(alias_shadow_src) + $(passthrough_c): $(passthrough_src) $(pushcolor_c): $(pushcolor_src) +$(shadow_c): $(shadow_src) + vkshader_c = \ $(twodv_c) \ $(twodf_c) \ @@ -377,6 +389,7 @@ vkshader_c = \ $(bsp_gbufv_c) \ $(bsp_gbufg_c) \ $(bsp_gbuff_c) \ + $(bsp_shadow_c) \ $(bsp_skyf_c) \ $(bsp_turbf_c) \ $(lightingf_c) \ @@ -385,8 +398,10 @@ vkshader_c = \ $(alias_depth_c) \ $(aliasf_c) \ $(alias_gbuf_c) \ + $(alias_shadow_c) \ $(passthrough_c) \ - $(pushcolor_c) + $(pushcolor_c) \ + $(shadow_c) V_VKGEN = $(V_VKGEN_@AM_V@) V_VKGEN_ = $(V_VKGEN_@AM_DEFAULT_V@) @@ -427,10 +442,12 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/alias.vert \ libs/video/renderer/vulkan/shader/alias_depth.vert \ libs/video/renderer/vulkan/shader/alias_gbuf.frag \ + libs/video/renderer/vulkan/shader/alias_shadow.frag \ libs/video/renderer/vulkan/shader/bsp_depth.vert \ libs/video/renderer/vulkan/shader/bsp_gbuf.frag \ libs/video/renderer/vulkan/shader/bsp_gbuf.geom \ libs/video/renderer/vulkan/shader/bsp_gbuf.vert \ + libs/video/renderer/vulkan/shader/bsp_shadow.vert \ libs/video/renderer/vulkan/shader/bsp_sky.frag \ libs/video/renderer/vulkan/shader/bsp_turb.frag \ libs/video/renderer/vulkan/shader/compose.frag \ @@ -439,5 +456,6 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/pushcolor.frag \ libs/video/renderer/vulkan/shader/quakebsp.frag \ libs/video/renderer/vulkan/shader/quakebsp.vert \ + libs/video/renderer/vulkan/shader/shadow.geom \ libs/video/renderer/vulkan/shader/twod.frag \ libs/video/renderer/vulkan/shader/twod.vert diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index d19294a80..31e14ad7f 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -51,6 +51,23 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; + shadow_sampler = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = true; + compareOp = greater_or_equal; + minLod = 0; + maxLod = 1000; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; }; descriptorPools = { twod_pool = { @@ -97,6 +114,16 @@ }, ); }; + lighting_shadow_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = combined_image_sampler; + descriptorCount = "$frames.size * 256z"; + }, + ); + }; compose_attach_pool = { flags = 0; maxSets = $frames.size; @@ -276,6 +303,16 @@ }, ); }; + lighting_shadow = { + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 256; + stageFlags = fragment; + }, + ); + }; compose_attach = { bindings = ( { @@ -329,7 +366,7 @@ ); }; lighting_layout = { - setLayouts = (lighting_attach, lighting_lights); + setLayouts = (lighting_attach, lighting_lights, lighting_shadow); }; compose_layout = { setLayouts = (compose_attach); @@ -499,6 +536,67 @@ }; pipelines = { + alias_shadow = { + subpass = 0; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/alias_shadow.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.vertexInput.alias.bindings[0]", + "$properties.vertexInput.alias.bindings[1]", + ); + attributes = ( + "$properties.vertexInput.alias.attributes[0]", + "$properties.vertexInput.alias.attributes[1]", + "$properties.vertexInput.alias.attributes[2]", + "$properties.vertexInput.alias.attributes[3]", + ); + }; + inputAssembly = $properties.inputAssembly.alias; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_and_write; + colorBlend = $properties.pipelines.alias_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = alias_layout; + }; + bsp_shadow = { + subpass = 0; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/bsp_shadow.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.vertexInput.brush.bindings[0]", + ); + attributes = ( + "$properties.vertexInput.brush.attributes[0]", + ); + }; + inputAssembly = $properties.inputAssembly.brush; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_and_write; + colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = quakebsp_layout; + //renderPass = renderpass; + }; alias_depth = { subpass = 0; stages = ( @@ -805,12 +903,6 @@ stage = fragment; name = main; module = $builtin/lighting.frag; - specializationInfo = { - mapEntries = ( - { size = 4; offset = 0; constantID = 0; }, - ); - data = <00000100>; - }; }, ); vertexInput = $properties.fsquad.vertexInput; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 687f52be2..d35fe82e5 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -71,6 +71,8 @@ static static #include "libs/video/renderer/vulkan/shader/bsp_gbuf.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/bsp_shadow.vert.spvc" +static #include "libs/video/renderer/vulkan/shader/bsp_sky.frag.spvc" static #include "libs/video/renderer/vulkan/shader/bsp_turb.frag.spvc" @@ -87,9 +89,13 @@ static static #include "libs/video/renderer/vulkan/shader/alias_gbuf.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/alias_shadow.vert.spvc" +static #include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc" static #include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/shadow.geom.spvc" typedef struct shaderdata_s { const char *name; @@ -106,6 +112,7 @@ static shaderdata_t builtin_shaders[] = { { "bsp_gbuf.vert", bsp_gbuf_vert, sizeof (bsp_gbuf_vert) }, { "bsp_gbuf.geom", bsp_gbuf_geom, sizeof (bsp_gbuf_geom) }, { "bsp_gbuf.frag", bsp_gbuf_frag, sizeof (bsp_gbuf_frag) }, + { "bsp_shadow.vert", bsp_shadow_vert, sizeof (bsp_shadow_vert) }, { "bsp_sky.frag", bsp_sky_frag, sizeof (bsp_sky_frag) }, { "bsp_turb.frag", bsp_turb_frag, sizeof (bsp_turb_frag) }, { "lighting.frag", lighting_frag, sizeof (lighting_frag) }, @@ -114,8 +121,10 @@ static shaderdata_t builtin_shaders[] = { { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, { "alias.frag", alias_frag, sizeof (alias_frag) }, { "alias_gbuf.frag", alias_gbuf_frag, sizeof (alias_gbuf_frag) }, + { "alias_shadow.vert", alias_shadow_vert, sizeof (alias_shadow_vert) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, + { "shadow.geom", shadow_geom, sizeof (shadow_geom) }, {} }; diff --git a/libs/video/renderer/vulkan/shader/alias_shadow.vert b/libs/video/renderer/vulkan/shader/alias_shadow.vert new file mode 100644 index 000000000..d99c1b445 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/alias_shadow.vert @@ -0,0 +1,23 @@ +#version 450 + +layout (push_constant) uniform PushConstants { + mat4 Model; + float blend; +}; + +layout (location = 0) in vec4 vertexa; +layout (location = 1) in vec3 normala; +layout (location = 2) in vec4 vertexb; +layout (location = 3) in vec3 normalb; + +layout (location = 0) out int InstanceIndex; + +void +main (void) +{ + vec4 vertex; + + vertex = mix (vertexa, vertexb, blend); + gl_Position = Model * vertex; + InstanceIndex = gl_InstanceIndex; +} diff --git a/libs/video/renderer/vulkan/shader/bsp_shadow.vert b/libs/video/renderer/vulkan/shader/bsp_shadow.vert new file mode 100644 index 000000000..f80dfd673 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/bsp_shadow.vert @@ -0,0 +1,16 @@ +#version 450 + +layout (push_constant) uniform PushConstants { + mat4 Model; +}; + +layout (location = 0) in vec4 vertex; + +layout (location = 0) out int InstanceIndex; + +void +main (void) +{ + gl_Position = Model * vertex; + InstanceIndex = gl_InstanceIndex; +} diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 3be1485ee..5f5524cc8 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -15,12 +15,18 @@ struct LightData { float cone; }; -layout (constant_id = 0) const int MaxLights = 128; +#define MaxLights 256 + +layout (set = 2, binding = 0) uniform sampler2DArrayShadow shadowCascade[MaxLights]; +layout (set = 2, binding = 0) uniform sampler2DShadow shadowPlane[MaxLights]; +layout (set = 2, binding = 0) uniform samplerCubeShadow shadowCube[MaxLights]; + layout (set = 1, binding = 0) uniform Lights { - vec4 intensity[16]; // 64 floats - vec3 intensity2; - int lightCount; + vec4 intensity[17]; // 68 floats + ivec4 lightCounts; LightData lights[MaxLights]; + mat4 shadowMat[MaxLights]; + vec4 shadowCascale[MaxLights]; }; layout (location = 0) out vec4 frag_color; @@ -48,6 +54,24 @@ calc_light (LightData light, vec3 position, vec3 normal) return light.color * i * (r - d); } +vec3 +shadow_cascade (sampler2DArrayShadow map) +{ + return vec3(1); +} + +vec3 +shadow_plane (sampler2DShadow map) +{ + return vec3(1); +} + +vec3 +shadow_cube (samplerCubeShadow map) +{ + return vec3(1); +} + void main (void) { @@ -59,8 +83,22 @@ main (void) vec3 light = vec3 (0); if (MaxLights > 0) { - for (int i = 0; i < lightCount; i++) { + int i = 0; + while (i < lightCounts.x) { + shadow_cascade (shadowCascade[i]); + i++; + } + while (i < lightCounts.y) { + shadow_plane (shadowPlane[i]); + i++; + } + while (i < lightCounts.z) { + shadow_cube (shadowCube[i]); + i++; + } + while (i < lightCounts.w) { light += calc_light (lights[i], p, n); + i++; } } frag_color = vec4 (c * light + e, 1); diff --git a/libs/video/renderer/vulkan/shader/shadow.geom b/libs/video/renderer/vulkan/shader/shadow.geom new file mode 100644 index 000000000..ed4f4de23 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/shadow.geom @@ -0,0 +1,25 @@ +#version 450 + +layout (triangles) in; +layout (triangle_strip, max_vertices = 3) out; + +layout (constant_id = 0) const int MaxLights = 128; + +layout (set = 0, binding = 0) uniform UBO { + mat4 vp[MaxLights]; +} ubo; + +layout (location = 0) in int InstanceIndex[]; + +void +main (void) +{ + int index = InstanceIndex[0]; + + for (int i = 0; i < gl_in.length(); i++) { + gl_Layer = index; + gl_Position = ubo.vp[index] * gl_in[i].gl_Position; + EmitVertex(); + } + EndPrimitive(); +} diff --git a/libs/video/renderer/vulkan/shadow.plist b/libs/video/renderer/vulkan/shadow.plist new file mode 100644 index 000000000..d33855783 --- /dev/null +++ b/libs/video/renderer/vulkan/shadow.plist @@ -0,0 +1,71 @@ +{ + images = { + shadow = { + flags = cube_compatible; + imageType = VK_IMAGE_TYPE_2D; //FIXME short form is 2d... + format = x8_d24_unorm_pack32; + samples = 1; + extent = { + width = 256; // FIXME config + height = 256; // FIXME config + depth = 1; + }; + mipLevels = 1; + arrayLayers = 2048; // FIXME config + tiling = optimal; + usage = depth_stencil_attachment|sampled; + initialLayout = undefined; + }; + }; + imageViews = { + shadow = { + image = depth; + viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + format = $properties.images.shadow.format; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = depth; + levelCount = 1; + layerCount = $properties.images.shadow.arrayLayers; + }; + }; + }; + framebuffer = { + renderPass = $properties.renderpass; + attachments = (shadown); + width = $properties.images.shadow.extent.width; + height = $properties.images.shadow.extent.height; + layers = $properties.images.shadow.arrayLayers; + }; + clearValues = ( + { depthStencil = { depth = 1; stencil = 0; }; }, + ); + renderpass = { + attachments = ( + { + format = $properties.images.depth.format; + samples = 1; + loadOp = dont_care; + storeOp = store; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = shader_read_only_optimal; + }, + ); + subpasses = ( + { // 0 depth + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_attachment_optimal; + }; + } + ); + }; +} diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 1a1ce9e47..dbf2ed8c0 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -49,6 +49,7 @@ #include "QF/va.h" #include "QF/Vulkan/qf_lighting.h" +#include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" @@ -128,7 +129,11 @@ update_lights (vulkan_ctx_t *ctx) light_data->intensity[64] = 1 / 16.0; light_data->intensity[65] = 1 / 16.0; light_data->intensity[66] = 1 / 16.0; + light_data->intensity[67] = 1 / 16.0; + light_data->cascadeCount = 0; + light_data->planeCount = 0; + light_data->cubeCount = 0; light_data->lightCount = 0; R_FindNearLights (r_origin, NUM_LIGHTS - 1, lights); for (int i = 0; i < NUM_LIGHTS - 1; i++) { @@ -213,24 +218,25 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) lctx->pipeline); lframe->bufferInfo[0].buffer = lframe->light_buffer; - lframe->imageInfo[0].imageView = ctx->attachment_views->a[QFV_attachDepth]; - lframe->imageInfo[1].imageView = ctx->attachment_views->a[QFV_attachColor]; - lframe->imageInfo[2].imageView + lframe->attachInfo[0].imageView = ctx->attachment_views->a[QFV_attachDepth]; + lframe->attachInfo[1].imageView = ctx->attachment_views->a[QFV_attachColor]; + lframe->attachInfo[2].imageView = ctx->attachment_views->a[QFV_attachEmission]; - lframe->imageInfo[3].imageView + lframe->attachInfo[3].imageView = ctx->attachment_views->a[QFV_attachNormal]; - lframe->imageInfo[4].imageView + lframe->attachInfo[4].imageView = ctx->attachment_views->a[QFV_attachPosition]; dfunc->vkUpdateDescriptorSets (device->dev, - LIGHTING_BUFFER_INFOS + LIGHTING_IMAGE_INFOS, + LIGHTING_DESCRIPTORS, lframe->descriptors, 0, 0); VkDescriptorSet sets[] = { - lframe->descriptors[1].dstSet, - lframe->descriptors[0].dstSet, + lframe->attachWrite[0].dstSet, + lframe->bufferWrite[0].dstSet, + lframe->shadowWrite.dstSet, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - lctx->layout, 0, 2, sets, 0, 0); + lctx->layout, 0, 3, sets, 0, 0); dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); @@ -255,12 +261,18 @@ static VkWriteDescriptorSet base_buffer_write = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, 0, 0 }; -static VkWriteDescriptorSet base_image_write = { +static VkWriteDescriptorSet base_attachment_write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, 0, 0, 1, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 0, 0, 0 }; +static VkWriteDescriptorSet base_image_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 0, 0, 0 +}; void Vulkan_Lighting_Init (vulkan_ctx_t *ctx) @@ -281,6 +293,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lctx->pipeline = Vulkan_CreatePipeline (ctx, "lighting"); lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout"); + lctx->sampler = Vulkan_CreateSampler (ctx, "shadow_sampler"); __auto_type lbuffers = QFV_AllocBufferSet (frames, alloca); for (size_t i = 0; i < frames; i++) { @@ -305,24 +318,41 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); __auto_type lights = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + __auto_type shadow = QFV_AllocDescriptorSetLayoutSet (frames, alloca); for (size_t i = 0; i < frames; i++) { attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "lighting_attach"); lights->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "lighting_lights"); + shadow->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, + "lighting_shadow"); } __auto_type attach_pool = Vulkan_CreateDescriptorPool (ctx, "lighting_attach_pool"); __auto_type lights_pool = Vulkan_CreateDescriptorPool (ctx, "lighting_lights_pool"); + __auto_type shadow_pool = Vulkan_CreateDescriptorPool (ctx, + "lighting_shadow_pool"); __auto_type attach_set = QFV_AllocateDescriptorSet (device, attach_pool, attach); __auto_type lights_set = QFV_AllocateDescriptorSet (device, lights_pool, lights); + __auto_type shadow_set = QFV_AllocateDescriptorSet (device, shadow_pool, + shadow); for (size_t i = 0; i < frames; i++) { __auto_type lframe = &lctx->frames.a[i]; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, + attach_set->a[i], + va (ctx->va_ctx, "lighting:attach_set:%zd", i)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, + lights_set->a[i], + va (ctx->va_ctx, "lighting:lights_set:%zd", i)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, + shadow_set->a[i], + va (ctx->va_ctx, "lighting:shadow_set:%zd", i)); + DARRAY_INIT (&lframe->lightvis, 16); lframe->leaf = 0; @@ -337,20 +367,29 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->cmd, "cmd:lighting"); for (int j = 0; j < LIGHTING_BUFFER_INFOS; j++) { lframe->bufferInfo[j] = base_buffer_info; - lframe->descriptors[j] = base_buffer_write; - lframe->descriptors[j].dstSet = lights_set->a[i]; - lframe->descriptors[j].dstBinding = j; - lframe->descriptors[j].pBufferInfo = &lframe->bufferInfo[j]; + lframe->bufferWrite[j] = base_buffer_write; + lframe->bufferWrite[j].dstSet = lights_set->a[i]; + lframe->bufferWrite[j].dstBinding = j; + lframe->bufferWrite[j].pBufferInfo = &lframe->bufferInfo[j]; } - for (int j = 0; j < LIGHTING_IMAGE_INFOS; j++) { - lframe->imageInfo[j] = base_image_info; - lframe->imageInfo[j].sampler = 0; - int k = j + LIGHTING_BUFFER_INFOS; - lframe->descriptors[k] = base_image_write; - lframe->descriptors[k].dstSet = attach_set->a[i]; - lframe->descriptors[k].dstBinding = j; - lframe->descriptors[k].pImageInfo = &lframe->imageInfo[j]; + for (int j = 0; j < LIGHTING_ATTACH_INFOS; j++) { + lframe->attachInfo[j] = base_image_info; + lframe->attachInfo[j].sampler = 0; + lframe->attachWrite[j] = base_attachment_write; + lframe->attachWrite[j].dstSet = attach_set->a[i]; + lframe->attachWrite[j].dstBinding = j; + lframe->attachWrite[j].pImageInfo = &lframe->attachInfo[j]; } + for (int j = 0; j < LIGHTING_SHADOW_INFOS; j++) { + lframe->shadowInfo[j] = base_image_info; + lframe->shadowInfo[j].sampler = lctx->sampler; + lframe->shadowInfo[j].imageView = ctx->default_black->view; + } + lframe->shadowWrite = base_image_write; + lframe->shadowWrite.dstSet = shadow_set->a[i]; + lframe->shadowWrite.dstBinding = 0; + lframe->shadowWrite.descriptorCount = NUM_LIGHTS; + lframe->shadowWrite.pImageInfo = lframe->shadowInfo; } free (attach_set); free (lights_set); From dc9b64fadddbd75078361387cf5a772ba05a3f10 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Apr 2021 12:42:29 +0900 Subject: [PATCH 1523/3664] [vulkan] Clean up image barriers a bit Mostly, this gets the stage flags in with the barrier, but also adds a couple more barrier templates. It should make for slightly less verbose code, and one less opportunity for error (mismatched barrier/stages). --- include/QF/Vulkan/barrier.h | 15 +- libs/models/alias/vulkan_model_alias.c | 29 ++-- libs/models/brush/vulkan_model_brush.c | 20 ++- libs/video/renderer/vulkan/barrier.c | 148 ++++++++++++-------- libs/video/renderer/vulkan/image.c | 67 +++------ libs/video/renderer/vulkan/scrap.c | 42 +++--- libs/video/renderer/vulkan/vulkan_bsp.c | 28 ++-- libs/video/renderer/vulkan/vulkan_texture.c | 81 +++++------ 8 files changed, 198 insertions(+), 232 deletions(-) diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h index 56438aeba..8637d7a99 100644 --- a/include/QF/Vulkan/barrier.h +++ b/include/QF/Vulkan/barrier.h @@ -2,21 +2,22 @@ #define __QF_Vulkan_barrier_h typedef struct { - VkPipelineStageFlags src; - VkPipelineStageFlags dst; -} qfv_pipelinestagepair_t; + VkPipelineStageFlags srcStages; + VkPipelineStageFlags dstStages; + VkImageMemoryBarrier barrier; +} qfv_imagebarrier_t; -//XXX Note: imageLayoutTransitionBarriers, imageLayoutTransitionStages and -// the enum must be kept in sync +//XXX Note: imageBarriers and the enum must be kept in sync enum { qfv_LT_Undefined_to_TransferDst, + qfv_LT_TransferDst_to_TransferSrc, qfv_LT_TransferDst_to_ShaderReadOnly, + qfv_LT_TransferSrc_to_ShaderReadOnly, qfv_LT_ShaderReadOnly_to_TransferDst, qfv_LT_Undefined_to_DepthStencil, qfv_LT_Undefined_to_Color, }; -extern const VkImageMemoryBarrier imageLayoutTransitionBarriers[]; -extern const qfv_pipelinestagepair_t imageLayoutTransitionStages[]; +extern const qfv_imagebarrier_t imageBarriers[]; #endif//__QF_Vulkan_barrier_h diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 27971ad56..56a9175bb 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -184,17 +184,13 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, Vulkan_ExpandPalette (base_data, tskin, vid.palette, 1, skinsize); - VkImageMemoryBarrier barrier; - qfv_pipelinestagepair_t stages; - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; - barrier.image = skin->image; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = skin->image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); VkBufferImageCopy copy = { packet->offset, 0, 0, @@ -207,14 +203,13 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, 1, ©); if (mipLevels == 1) { - stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier.image = skin->image; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = skin->image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); } else { QFV_GenerateMipMaps (device, packet->cmd, skin->image, mipLevels, w, h, 4); diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index e0211b01a..a5acbdac3 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -257,10 +257,9 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) } // base barrier - VkImageMemoryBarrier barrier; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; __auto_type barriers = QFV_AllocImageBarrierSet (image_count, malloc); barriers->size = 0; @@ -271,18 +270,15 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) } vulktex_t *tex = tx->render; __auto_type b = &barriers->a[barriers->size++]; - *b = barrier; + *b = ib.barrier; b->image = tex->tex->image; if (tex->glow) { b = &barriers->a[barriers->size++]; - *b = barrier; + *b = ib.barrier; b->image = tex->glow->image; } } - qfv_pipelinestagepair_t stages; - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, barriers->size, barriers->a); for (int i = 0, j = 0; i < brush->numtextures; i++) { @@ -307,8 +303,8 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) } } - stages=imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, barriers->size, barriers->a); QFV_PacketSubmit (packet); diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c index 935b370e0..4fc084cd1 100644 --- a/libs/video/renderer/vulkan/barrier.c +++ b/libs/video/renderer/vulkan/barrier.c @@ -31,71 +31,105 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" -const VkImageMemoryBarrier imageLayoutTransitionBarriers[] = { +const qfv_imagebarrier_t imageBarriers[] = { // undefined -> transfer dst optimal - { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + { + .srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + }, + // transfer dst optimal -> transfer src optimal + { + .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_TRANSFER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, }, // transfer dst optimal -> shader read only optimal - { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + { + .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + }, + // transfer src optimal -> shader read only optimal + { + .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_READ_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, }, // shader read only optimal -> transfer dst optimal - { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_SHADER_READ_BIT, - VK_ACCESS_TRANSFER_WRITE_BIT, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + { + .srcStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, }, // undefined -> depth stencil attachment optimal - { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - 0, - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT - | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, - { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 } + { + .srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + .dstStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + .barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT + | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 } + }, }, // undefined -> color attachment optimal - { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - 0, - VK_ACCESS_COLOR_ATTACHMENT_READ_BIT - | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + { + .srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + .dstStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + .barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT + | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, }, - { /* end of transition barriers */ } -}; - -const qfv_pipelinestagepair_t imageLayoutTransitionStages[] = { - // undefined -> transfer dst optimal - { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT }, - // transfer dst optimal -> shader read only optimal - { VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT }, - // shader read only optimal -> transfer dst optimal - { VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT }, - // undefined -> depth stencil attachment optimal - { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT }, - // undefined -> color attachment optimal - { VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }, }; diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index c05ececf9..61905c982 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -216,45 +216,16 @@ QFV_GenerateMipMaps (qfv_device_t *device, VkCommandBuffer cmd, { qfv_devfuncs_t *dfunc = device->funcs; - qfv_pipelinestagepair_t pre_stages = { - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - }; - qfv_pipelinestagepair_t post_stages = { - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - }; - qfv_pipelinestagepair_t final_stages = { - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - }; - VkImageMemoryBarrier pre_barrier = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - image, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, layers } - }; - VkImageMemoryBarrier post_barrier = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - image, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, layers } - }; - VkImageMemoryBarrier final_barrier = { - VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - image, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, layers } - }; + qfv_imagebarrier_t pre=imageBarriers[qfv_LT_TransferDst_to_TransferSrc]; + qfv_imagebarrier_t pst=imageBarriers[qfv_LT_TransferSrc_to_ShaderReadOnly]; + qfv_imagebarrier_t fnl=imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + + pre.barrier.image = image; + pre.barrier.subresourceRange.layerCount = layers; + pst.barrier.image = image; + pst.barrier.subresourceRange.layerCount = layers; + fnl.barrier.image = image; + fnl.barrier.subresourceRange.layerCount = layers; VkImageBlit blit = { {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, layers}, @@ -264,17 +235,17 @@ QFV_GenerateMipMaps (qfv_device_t *device, VkCommandBuffer cmd, }; while (--mips > 0) { - dfunc->vkCmdPipelineBarrier (cmd, pre_stages.src, pre_stages.dst, 0, + dfunc->vkCmdPipelineBarrier (cmd, pre.srcStages, pre.dstStages, 0, 0, 0, 0, 0, - 1, &pre_barrier); + 1, &pre.barrier); dfunc->vkCmdBlitImage (cmd, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_LINEAR); - dfunc->vkCmdPipelineBarrier (cmd, post_stages.src, post_stages.dst, 0, + dfunc->vkCmdPipelineBarrier (cmd, pst.srcStages, pst.dstStages, 0, 0, 0, 0, 0, - 1, &post_barrier); + 1, &pst.barrier); blit.srcSubresource.mipLevel++; blit.srcOffsets[1].x = blit.dstOffsets[1].x; @@ -282,13 +253,13 @@ QFV_GenerateMipMaps (qfv_device_t *device, VkCommandBuffer cmd, blit.dstSubresource.mipLevel++; blit.dstOffsets[1].x = max (blit.dstOffsets[1].x >> 1, 1); blit.dstOffsets[1].y = max (blit.dstOffsets[1].y >> 1, 1); - pre_barrier.subresourceRange.baseMipLevel++; - post_barrier.subresourceRange.baseMipLevel++; - final_barrier.subresourceRange.baseMipLevel++; + pre.barrier.subresourceRange.baseMipLevel++; + pst.barrier.subresourceRange.baseMipLevel++; + fnl.barrier.subresourceRange.baseMipLevel++; } - dfunc->vkCmdPipelineBarrier (cmd, final_stages.src, final_stages.dst, 0, + dfunc->vkCmdPipelineBarrier (cmd, fnl.srcStages, fnl.dstStages, 0, 0, 0, 0, 0, - 1, &final_barrier); + 1, &fnl.barrier); } static int diff --git a/libs/video/renderer/vulkan/scrap.c b/libs/video/renderer/vulkan/scrap.c index ab053bf10..e56c2a7a5 100644 --- a/libs/video/renderer/vulkan/scrap.c +++ b/libs/video/renderer/vulkan/scrap.c @@ -143,17 +143,13 @@ QFV_CreateScrap (qfv_device_t *device, const char *name, int size, scrap->batch_free = 0; scrap->batch_count = 0; - VkImageMemoryBarrier barrier; - qfv_pipelinestagepair_t stages; - qfv_packet_t *packet = QFV_PacketAcquire (stage); // no data for the packet - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; - barrier.image = scrap->image; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = scrap->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); VkClearColorValue color = { float32:{0xde/255.0, 0xad/255.0, 0xbe/255.0, 0xef/255.0}, }; @@ -161,12 +157,11 @@ QFV_CreateScrap (qfv_device_t *device, const char *name, int size, dfunc->vkCmdClearColorImage (packet->cmd, scrap->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &range); - stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier.image = scrap->image; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = scrap->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); QFV_PacketSubmit (packet); return scrap; } @@ -322,15 +317,11 @@ QFV_ScrapFlush (scrap_t *scrap) copy->a[i].imageExtent.depth = 1; } - VkImageMemoryBarrier barrier; - qfv_pipelinestagepair_t stages; - - stages = imageLayoutTransitionStages[qfv_LT_ShaderReadOnly_to_TransferDst]; - barrier=imageLayoutTransitionBarriers[qfv_LT_ShaderReadOnly_to_TransferDst]; - barrier.image = scrap->image; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_ShaderReadOnly_to_TransferDst]; + ib.barrier.image = scrap->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); size_t offset = packet->offset, size; vrect_t *batch = scrap->batch; @@ -353,12 +344,11 @@ QFV_ScrapFlush (scrap_t *scrap) scrap->batch_count -= i; } - stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier.image = scrap->image; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = scrap->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); *scrap->batch_tail = scrap->batch_free; scrap->batch_free = scrap->batch; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index c498ee09b..75d8a6462 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1390,19 +1390,14 @@ create_default_skys (vulkan_ctx_t *ctx) // temporarily commandeer the light map's staging buffer qfv_packet_t *packet = QFV_PacketAcquire (bctx->light_stage); - VkImageMemoryBarrier barrier; - VkImageMemoryBarrier barriers[2]; - qfv_pipelinestagepair_t stages; - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - barriers[0] = barrier; - barriers[1] = barrier; + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + VkImageMemoryBarrier barriers[2] = { ib.barrier, ib.barrier }; barriers[0].image = skybox; barriers[1].image = skysheet; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, 2, barriers); @@ -1419,15 +1414,14 @@ create_default_skys (vulkan_ctx_t *ctx) VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &range); - stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - barriers[0] = barrier; - barriers[1] = barrier; + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + barriers[0] = ib.barrier; + barriers[1] = ib.barrier; barriers[0].image = skybox; barriers[1].image = skysheet; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, 2, barriers); QFV_PacketSubmit (packet); diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 7aa8cfc64..4a6949881 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -203,16 +203,12 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); stage_tex_data (packet, tex, bpp); - VkImageMemoryBarrier barrier; - qfv_pipelinestagepair_t stages; - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; - barrier.image = qtex->image; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = qtex->image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); VkBufferImageCopy copy = { packet->offset, 0, 0, {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, @@ -223,12 +219,11 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©); if (mip == 1) { - stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier.image = qtex->image; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = qtex->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); } else { QFV_GenerateMipMaps (device, packet->cmd, qtex->image, mip, tex->width, tex->height, 1); @@ -297,17 +292,13 @@ Vulkan_LoadEnvMap (vulkan_ctx_t *ctx, tex_t *tex, const char *name) qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); stage_tex_data (packet, tex, bpp); - VkImageMemoryBarrier barrier; - qfv_pipelinestagepair_t stages; - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; - barrier.image = qtex->image; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = qtex->image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); VkBufferImageCopy copy[6] = { { @@ -328,14 +319,13 @@ Vulkan_LoadEnvMap (vulkan_ctx_t *ctx, tex_t *tex, const char *name) qtex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 6, copy); - stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier.image = qtex->image; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = qtex->image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); QFV_PacketSubmit (packet); return qtex; } @@ -367,17 +357,13 @@ Vulkan_LoadEnvSides (vulkan_ctx_t *ctx, tex_t **tex, const char *name) qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); - VkImageMemoryBarrier barrier; - qfv_pipelinestagepair_t stages; - - stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_TransferDst]; - barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_TransferDst]; - barrier.image = qtex->image; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = qtex->image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); VkBufferImageCopy copy[6] = { { @@ -395,14 +381,13 @@ Vulkan_LoadEnvSides (vulkan_ctx_t *ctx, tex_t **tex, const char *name) qtex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 6, copy); - stages = imageLayoutTransitionStages[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier=imageLayoutTransitionBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - barrier.image = qtex->image; - barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - dfunc->vkCmdPipelineBarrier (packet->cmd, stages.src, stages.dst, + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = qtex->image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, - 1, &barrier); + 1, &ib.barrier); QFV_PacketSubmit (packet); return qtex; } From 785be9d340b6e449eeb073fa6ad57d733b4c0564 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Apr 2021 15:47:31 +0900 Subject: [PATCH 1524/3664] [vulkan] Clean up buffer barriers a bit This even fixes a couple of minor issues that snuck past validation. --- include/QF/Vulkan/barrier.h | 15 ++++++ libs/models/alias/vulkan_model_alias.c | 52 ++++++++----------- libs/video/renderer/vulkan/barrier.c | 44 ++++++++++++++++ libs/video/renderer/vulkan/vulkan_bsp.c | 30 ++++------- libs/video/renderer/vulkan/vulkan_draw.c | 28 ++++------ libs/video/renderer/vulkan/vulkan_lighting.c | 33 +++++------- .../video/renderer/vulkan/vulkan_vid_common.c | 30 ++++------- 7 files changed, 123 insertions(+), 109 deletions(-) diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h index 8637d7a99..98073c418 100644 --- a/include/QF/Vulkan/barrier.h +++ b/include/QF/Vulkan/barrier.h @@ -7,6 +7,12 @@ typedef struct { VkImageMemoryBarrier barrier; } qfv_imagebarrier_t; +typedef struct { + VkPipelineStageFlags srcStages; + VkPipelineStageFlags dstStages; + VkBufferMemoryBarrier barrier; +} qfv_bufferbarrier_t; + //XXX Note: imageBarriers and the enum must be kept in sync enum { qfv_LT_Undefined_to_TransferDst, @@ -18,6 +24,15 @@ enum { qfv_LT_Undefined_to_Color, }; +//XXX Note: bufferBarriers and the enum must be kept in sync +enum { + qfv_BB_Unknown_to_TransferWrite, + qfv_BB_TransferWrite_to_VertexAttrRead, + qfv_BB_TransferWrite_to_IndexRead, + qfv_BB_TransferWrite_to_UniformRead, +}; + extern const qfv_imagebarrier_t imageBarriers[]; +extern const qfv_bufferbarrier_t bufferBarriers[]; #endif//__QF_Vulkan_barrier_h diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 56a9175bb..792e8d166 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -407,23 +407,17 @@ Vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, header->poseverts = numverts; + qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; VkBufferMemoryBarrier wr_barriers[] = { - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - vbuff, 0, vert_size}, - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - uvbuff, 0, uv_size}, - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - ibuff, 0, ind_size}, + bb.barrier, bb.barrier, bb.barrier, }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, + wr_barriers[0].buffer = vbuff; + wr_barriers[0].size = vert_size; + wr_barriers[1].buffer = uvbuff; + wr_barriers[1].size = uv_size; + wr_barriers[2].buffer = ibuff; + wr_barriers[2].size = ind_size; + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, 0, 0, 0, 3, wr_barriers, 0, 0); VkBufferCopy copy_region[] = { { packet->offset, 0, vert_size }, @@ -436,23 +430,21 @@ Vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, uvbuff, 1, ©_region[1]); dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, ibuff, 1, ©_region[2]); + // both qfv_BB_TransferWrite_to_VertexAttrRead and + // qfv_BB_TransferWrite_to_IndexRead have the same stage flags + bb = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead]; VkBufferMemoryBarrier rd_barriers[] = { - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - vbuff, 0, vert_size }, - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - uvbuff, 0, uv_size }, - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - ibuff, 0, ind_size }, + bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead].barrier, + bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead].barrier, + bufferBarriers[qfv_BB_TransferWrite_to_IndexRead].barrier, }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + rd_barriers[0].buffer = vbuff; + rd_barriers[0].size = vert_size; + rd_barriers[1].buffer = uvbuff; + rd_barriers[1].size = uv_size; + rd_barriers[2].buffer = ibuff; + rd_barriers[2].size = ind_size; + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, 0, 0, 0, 3, rd_barriers, 0, 0); QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c index 4fc084cd1..75d96c8cf 100644 --- a/libs/video/renderer/vulkan/barrier.c +++ b/libs/video/renderer/vulkan/barrier.c @@ -133,3 +133,47 @@ const qfv_imagebarrier_t imageBarriers[] = { }, }, }; + +const qfv_bufferbarrier_t bufferBarriers[] = { + // unknown to transfer write + { + .srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, VK_ACCESS_TRANSFER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, + // transfer write to vertex attribute read + { + .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, + // transfer write to index read + { + .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, + // transfer write to uniform read + // note: not necessarily optimal as it uses vertex shader for dst + { + .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, +}; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 75d8a6462..98279481b 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -581,29 +581,19 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) bctx->vertex_buffer_size = vertex_buffer_size; } - VkBufferMemoryBarrier wr_barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - bctx->vertex_buffer, 0, vertex_buffer_size, - }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, 0, 1, &wr_barrier, 0, 0); + qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; + bb.barrier.buffer = bctx->vertex_buffer; + bb.barrier.size = vertex_buffer_size; + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); VkBufferCopy copy_region = { packet->offset, 0, vertex_buffer_size }; dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, bctx->vertex_buffer, 1, ©_region); - VkBufferMemoryBarrier rd_barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - bctx->vertex_buffer, 0, vertex_buffer_size, - }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, 0, 0, 1, &rd_barrier, 0, 0); + bb = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead]; + bb.barrier.buffer = bctx->vertex_buffer; + bb.barrier.size = vertex_buffer_size; + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 9aa532d58..96e462cb7 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -173,27 +173,19 @@ create_quad_buffers (vulkan_ctx_t *ctx) *ind++ = -1; } - VkBufferMemoryBarrier wr_barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, ibuf, 0, ind_size - }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, 0, 1, &wr_barrier, 0, 0); + qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; + bb.barrier.buffer = ibuf; + bb.barrier.size = ind_size; + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); VkBufferCopy copy_region = { packet->offset, 0, ind_size }; dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, ibuf, 1, ©_region); - VkBufferMemoryBarrier rd_barrier = { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, ibuf, 0, ind_size - }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, 0, 0, 1, &rd_barrier, 0, 0); + bb = bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]; + bb.barrier.buffer = ibuf; + bb.barrier.size = ind_size; + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); QFV_PacketSubmit (packet); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index dbf2ed8c0..fc0f59f51 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -50,6 +50,7 @@ #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" @@ -125,7 +126,7 @@ update_lights (vulkan_ctx_t *ctx) for (int i = 0; i < NUM_STYLES; i++) { light_data->intensity[i] = d_lightstylevalue[i] / 65536.0; } - // dynamic lights seem a tad fiant, so 16x map lights + // dynamic lights seem a tad faint, so 16x map lights light_data->intensity[64] = 1 / 16.0; light_data->intensity[65] = 1 / 16.0; light_data->intensity[66] = 1 / 16.0; @@ -155,31 +156,21 @@ update_lights (vulkan_ctx_t *ctx) } } - VkBufferMemoryBarrier wr_barriers[] = { - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - lframe->light_buffer, 0, sizeof (qfv_light_buffer_t) }, - }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, 0, 1, wr_barriers, 0, 0); + qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; + bb.barrier.buffer = lframe->light_buffer; + bb.barrier.size = sizeof (qfv_light_buffer_t); + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); VkBufferCopy copy_region[] = { { packet->offset, 0, sizeof (qfv_light_buffer_t) }, }; dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, lframe->light_buffer, 1, ©_region[0]); - VkBufferMemoryBarrier rd_barriers[] = { - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - lframe->light_buffer, 0, sizeof (qfv_light_buffer_t) }, - }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, 0, 0, 1, rd_barriers, 0, 0); + bb = bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]; + bb.barrier.buffer = lframe->light_buffer; + bb.barrier.size = sizeof (qfv_light_buffer_t); + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); QFV_PacketSubmit (packet); } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 82cb57e38..e5984cc8a 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -348,31 +348,21 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) float *verts = QFV_PacketExtend (packet, sizeof (quad_vertices)); memcpy (verts, quad_vertices, sizeof (quad_vertices)); - VkBufferMemoryBarrier wr_barriers[] = { - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - ctx->quad_buffer, 0, sizeof (quad_vertices) }, - }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, 0, 1, wr_barriers, 0, 0); + qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; + bb.barrier.buffer = ctx->quad_buffer; + bb.barrier.size = sizeof (quad_vertices); + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); VkBufferCopy copy_region[] = { { packet->offset, 0, sizeof (quad_vertices) }, }; dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, ctx->quad_buffer, 1, ©_region[0]); - VkBufferMemoryBarrier rd_barriers[] = { - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - ctx->quad_buffer, 0, sizeof (quad_vertices) }, - }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, 0, 0, 1, rd_barriers, 0, 0); + bb = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead]; + bb.barrier.buffer = ctx->quad_buffer; + bb.barrier.size = sizeof (quad_vertices); + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); QFV_PacketSubmit (packet); } From 40aa629ef80aae4ab63656a644a4988849736023 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Apr 2021 08:38:13 +0900 Subject: [PATCH 1525/3664] [image] Add function to get image memory size --- include/QF/image.h | 2 ++ libs/image/image.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/QF/image.h b/include/QF/image.h index 7ec7d00dc..2bbf7fb0a 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -53,6 +53,8 @@ typedef struct tex_s { tex_t *LoadImage (const char *imageFile, int load); +size_t ImageSize (const tex_t *tex, int incl_struct) __attribute__((pure)); + typedef struct colcache_s colcache_t; colcache_t *ColorCache_New (void); diff --git a/libs/image/image.c b/libs/image/image.c index 4da1e5827..f619727f5 100644 --- a/libs/image/image.c +++ b/libs/image/image.c @@ -106,3 +106,31 @@ LoadImage (const char *imageFile, int load) dstring_delete (tmpFile); return (tex); } + +size_t +ImageSize (const tex_t *tex, int incl_struct) +{ + size_t w =tex->width; + size_t h =tex->height; + size_t bpp = 1; + switch (tex->format) { + case tex_palette: + case tex_rgb: + bpp = 3; + break; + case tex_l: + case tex_a: + bpp = 1; + break; + case tex_la: + bpp = 2; + break; + case tex_rgba: + bpp = 4; + break; + case tex_frgba: + bpp = 16; + break; + } + return bpp * w * h + (incl_struct ? sizeof (tex_t) : 0); +} From 52168da93e9e642912c6bac7baa4c77404ea0065 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Apr 2021 08:38:48 +0900 Subject: [PATCH 1526/3664] [vulkan] Don't lose other sky cube faces Because LoadImage uses Hunk_TempAlloc, the face images need to be copied individually. Really, what's neeeded is to be able to load the image data into a pre-allocated buffer (ideally, the staging buffer for vulkan, but that's for later). --- libs/video/renderer/vulkan/vulkan_bsp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 98279481b..ee2d50870 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1630,12 +1630,18 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) continue; } } - sides[i] = tex; + //FIXME find a better way (also, assumes data and struct together) + sides[i] = malloc (ImageSize (tex, 1)); + memcpy (sides[i], tex, ImageSize (tex, 1)); + sides[i]->data = (byte *)(sides[i] + 1); Sys_MaskPrintf (SYS_vulkan, "Loaded %s\n", name); } if (!failed) { bctx->skybox_tex = Vulkan_LoadEnvSides (ctx, sides, sky); } + for (i = 0; i < 6; i++) { + free (sides[i]); + } } if (bctx->skybox_tex) { Sys_MaskPrintf (SYS_vulkan, "Skybox %s loaded\n", sky); From ae231319eae5c7c511b9d55426700f2537799806 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Apr 2021 10:01:57 +0900 Subject: [PATCH 1527/3664] [vulkan] Implement all the extended light models Standard quake has just linear, but the modding community added inverse, inverse-square (raw and offset (1/(r^2+1)), infinite (sun), and ambient (minlight). Other than the lack of shadows, marcher now looks really good. --- include/QF/Vulkan/qf_lighting.h | 7 +- .../renderer/vulkan/shader/lighting.frag | 177 +++++++++++++----- libs/video/renderer/vulkan/vulkan_lighting.c | 161 ++++++++++++++-- 3 files changed, 281 insertions(+), 64 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 346f2bf5f..516d6acb7 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -41,7 +41,7 @@ typedef struct qfv_light_s { vec3_t color; int data; vec3_t position; - float radius; + float light; vec3_t direction; float cone; } qfv_light_t; @@ -55,9 +55,8 @@ typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t; typedef struct qfv_light_buffer_s { float intensity[NUM_STYLES + 4]; - int cascadeCount; - int planeCount; - int cubeCount; + float distFactor1; + float distFactor2; int lightCount; qfv_light_t lights[NUM_LIGHTS] __attribute__((aligned(16))); mat4f_t shadowMat[NUM_LIGHTS]; diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 5f5524cc8..a6db899c8 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -10,12 +10,28 @@ struct LightData { vec3 color; int data;// bits 0-6: intensity key (however, values 0-66) vec3 position; - float radius; + float light; // doubles as radius for linear vec3 direction; float cone; }; -#define MaxLights 256 +#define MaxLights 256 + +#define StyleMask 0x07f +#define ModelMask 0x380 +#define ShadowMask 0xc00 + +#define LM_LINEAR (0 << 7) // light - dist (or radius + dist if -ve) +#define LM_INVERSE (1 << 7) // distFactor1 * light / dist +#define LM_INVERSE2 (2 << 7) // distFactor2 * light / (dist * dist) +#define LM_INFINITE (3 << 7) // light +#define LM_AMBIENT (4 << 7) // light +#define LM_INVERSE3 (5 << 7) // distFactor2 * light / (dist + distFactor2)**2 + +#define ST_NONE (0 << 10) // no shadows +#define ST_CASCADE (1 << 10) // cascaded shadow maps +#define ST_PLANE (2 << 10) // single plane shadow map (small spotlight) +#define ST_CUBE (3 << 10) // cubemap (omni, large spotlight) layout (set = 2, binding = 0) uniform sampler2DArrayShadow shadowCascade[MaxLights]; layout (set = 2, binding = 0) uniform sampler2DShadow shadowPlane[MaxLights]; @@ -23,7 +39,9 @@ layout (set = 2, binding = 0) uniform samplerCubeShadow shadowCube[MaxLights]; layout (set = 1, binding = 0) uniform Lights { vec4 intensity[17]; // 68 floats - ivec4 lightCounts; + float distFactor1; // for inverse + float distFactor2; // for inverse2 and inverse2 + int lightCount; LightData lights[MaxLights]; mat4 shadowMat[MaxLights]; vec4 shadowCascale[MaxLights]; @@ -31,45 +49,80 @@ layout (set = 1, binding = 0) uniform Lights { layout (location = 0) out vec4 frag_color; -vec3 -calc_light (LightData light, vec3 position, vec3 normal) +float +spot_cone (LightData light, vec3 incoming) { - float r = light.radius; - vec3 dist = light.position - position; - float d = sqrt (dot (dist, dist)); - if (d > r) { - // the light is too far away - return vec3 (0); - } - - vec3 incoming = dist / d; float spotdot = dot (incoming, light.direction); - float lightdot = dot (incoming, normal); - - int style = light.data & 0x7f; - // deliberate array index error: access intensity2 as well - float i = intensity[style / 4][style % 4]; - i *= step (d, r) * clamp (lightdot, 0, 1); - i *= smoothstep (spotdot, 1 - (1 - spotdot) * 0.995, light.cone); - return light.color * i * (r - d); + return smoothstep (spotdot, 1 - (1 - spotdot) * 0.995, light.cone); } -vec3 +float +diffuse (vec3 incoming, vec3 normal) +{ + float lightdot = dot (incoming, normal); + return clamp (lightdot, 0, 1); +} + +float +light_linear (LightData light, float d) +{ + float l = light.light; + if (l < 0) { + return min (l + d, 0); + } else { + return max (l - d, 0); + } +} + +float +light_inverse (LightData light, float d) +{ + float l = light.light; + return l / (distFactor1 * d); +} + +float +light_inverse2 (LightData light, float d) +{ + float l = light.light; + return l / (distFactor2 * d); +} + +float +light_infinite (LightData light) +{ + return light.light; +} + +float +light_ambient (LightData light) +{ + return light.light; +} + +float +light_inverse3 (LightData light, float d) +{ + float l = light.light; + return l / (distFactor2 * d + 1); +} + +float shadow_cascade (sampler2DArrayShadow map) { - return vec3(1); + return 1; } -vec3 +float shadow_plane (sampler2DShadow map) { - return vec3(1); + return 1; } -vec3 +float shadow_cube (samplerCubeShadow map) { - return vec3(1); + return 1; } void @@ -83,23 +136,59 @@ main (void) vec3 light = vec3 (0); if (MaxLights > 0) { - int i = 0; - while (i < lightCounts.x) { - shadow_cascade (shadowCascade[i]); - i++; - } - while (i < lightCounts.y) { - shadow_plane (shadowPlane[i]); - i++; - } - while (i < lightCounts.z) { - shadow_cube (shadowCube[i]); - i++; - } - while (i < lightCounts.w) { - light += calc_light (lights[i], p, n); - i++; + vec3 minLight = vec3 (0); + for (int i = 0; i < lightCount; i++) { + vec3 dist = lights[i].position - p; + float d = dot (dist, dist); + int model = lights[i].data & ModelMask; + + if (model != LM_INFINITE + && d > lights[i].light * lights[i].light) { + continue; + } + + float l = 0; + if (model == LM_LINEAR) { + d = sqrt (d); + l = light_linear (lights[i], d); + } else if (model == LM_INVERSE) { + d = sqrt (d); + l = light_inverse (lights[i], d); + } else if (model == LM_INVERSE2) { + l = light_inverse2 (lights[i], d); + d = sqrt (d); + } else if (model == LM_INFINITE) { + l = light_infinite (lights[i]); + dist = lights[i].direction; + d = -1; + } else if (model == LM_AMBIENT) { + l = light_ambient (lights[i]); + } else if (model == LM_INVERSE3) { + l = light_inverse3 (lights[i], d); + d = sqrt (d); + } + + int style = lights[i].data & StyleMask; + l *= intensity[style / 4][style % 4]; + + int shadow = lights[i].data & ShadowMask; + if (shadow == ST_CASCADE) { + l *= shadow_cascade (shadowCascade[i]); + } else if (shadow == ST_PLANE) { + l *= shadow_plane (shadowPlane[i]); + } else if (shadow == ST_CUBE) { + l *= shadow_cube (shadowCube[i]); + } + + if (model == LM_AMBIENT) { + minLight = max (l * lights[i].color, minLight); + } else { + vec3 incoming = dist / d; + l *= spot_cone (lights[i], incoming) * diffuse (incoming, n); + light += l * lights[i].color; + } } + light = max (light, minLight); } frag_color = vec4 (c * light + e, 1); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index fc0f59f51..8fd57078e 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -98,7 +98,8 @@ find_visible_lights (vulkan_ctx_t *ctx) memset (lframe->lightvis.a, 0, lframe->lightvis.size * sizeof (byte)); for (size_t i = 0; i < lctx->lightleafs.size; i++) { int l = lctx->lightleafs.a[i]; - if (lframe->pvs[l / 8] & (1 << (l % 8))) { + //FIXME -1 needs check for sky + if (l == -1 || lframe->pvs[l / 8] & (1 << (l % 8))) { lframe->lightvis.a[i] = 1; visible++; } @@ -132,9 +133,9 @@ update_lights (vulkan_ctx_t *ctx) light_data->intensity[66] = 1 / 16.0; light_data->intensity[67] = 1 / 16.0; - light_data->cascadeCount = 0; - light_data->planeCount = 0; - light_data->cubeCount = 0; + light_data->distFactor1 = 1 / 128.0; + light_data->distFactor2 = 1 / 16384.0; + light_data->lightCount = 0; R_FindNearLights (r_origin, NUM_LIGHTS - 1, lights); for (int i = 0; i < NUM_LIGHTS - 1; i++) { @@ -144,7 +145,7 @@ update_lights (vulkan_ctx_t *ctx) light_data->lightCount++; VectorCopy (lights[i]->color, light_data->lights[i].color); VectorCopy (lights[i]->origin, light_data->lights[i].position); - light_data->lights[i].radius = lights[i]->radius; + light_data->lights[i].light = lights[i]->radius; light_data->lights[i].data = 64; // default dynamic light VectorZero (light_data->lights[i].direction); light_data->lights[i].cone = 1; @@ -406,11 +407,121 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) free (lctx); } +static void +dump_light (qfv_light_t *light, int leaf) +{ + Sys_MaskPrintf (SYS_vulkan, + "[%g, %g, %g] %d %d %d, " + "[%g %g %g] %g, [%g %g %g] %g, %d\n", + VectorExpand (light->color), + (light->data & 0x07f), + (light->data & 0x380) >> 7, + (light->data & 0xc00) >> 10, + VectorExpand (light->position), light->light, + VectorExpand (light->direction), light->cone, + leaf); +} + +static float +parse_float (const char *str, float defval) +{ + float val = defval; + if (str) { + char *end; + val = strtof (str, &end); + if (end == str) { + val = defval; + } + } + return val; +} + +static void +parse_vector (const char *str, vec_t *val) +{ + if (str) { + int num = sscanf (str, "%f %f %f", VectorExpandAddr (val)); + while (num < 3) { + val[num++] = 0; + } + } +} + +static float +ecos (float ang) +{ + if (ang == 90 || ang == -90) { + return 0; + } + if (ang == 180 || ang == -180) { + return -1; + } + if (ang == 0 || ang == 360) { + return 1; + } + return cos (ang * M_PI / 180); +} + +static float +esin (float ang) +{ + if (ang == 90) { + return 1; + } + if (ang == -90) { + return -1; + } + if (ang == 180 || ang == -180) { + return 0; + } + if (ang == 0 || ang == 360) { + return 0; + } + return sin (ang * M_PI / 180); +} + +static void +sun_vector (const vec_t *ang, vec_t *vec) +{ + // ang is yaw, pitch (maybe roll, but ignored + vec[0] = ecos (ang[1]) * ecos (ang[0]); + vec[1] = ecos (ang[1]) * esin (ang[0]); + vec[2] = esin (ang[1]); +} + +static void +parse_sun (lightingctx_t *lctx, plitem_t *entity) +{ + qfv_light_t light = {}; + float sunlight; + //float sunlight2; + vec3_t sunangle = { 0, -90, 0 }; + + sunlight = parse_float (PL_String (PL_ObjectForKey (entity, + "_sunlight")), 0); + //sunlight2 = parse_float (PL_String (PL_ObjectForKey (entity, + // "_sunlight2")), 0); + parse_vector (PL_String (PL_ObjectForKey (entity, "_sun_mangle")), + sunangle); + if (sunlight <= 0) { + return; + } + VectorSet (1, 1, 1, light.color); + light.data = 3 << 7; //FIXME magic number (LM_INFINITE) + light.light = sunlight; + sun_vector (sunangle, light.direction); + light.cone = 1; + DARRAY_APPEND (&lctx->lights, light); + DARRAY_APPEND (&lctx->lightleafs, -1); + dump_light (&light, -1); +} + static void parse_light (qfv_light_t *light, const plitem_t *entity, const plitem_t *targets) { const char *str; + int model = 0; /*Sys_Printf ("{\n"); for (int i = PL_D_NumKeys (entity); i-- > 0; ) { @@ -422,7 +533,7 @@ parse_light (qfv_light_t *light, const plitem_t *entity, light->cone = 1; light->data = 0; - light->radius = 300; + light->light = 300; VectorSet (1, 1, 1, light->color); if ((str = PL_String (PL_ObjectForKey (entity, "origin")))) { @@ -449,16 +560,34 @@ parse_light (qfv_light_t *light, const plitem_t *entity, if ((str = PL_String (PL_ObjectForKey (entity, "light_lev"))) || (str = PL_String (PL_ObjectForKey (entity, "_light")))) { - light->radius = atof (str); + light->light = atof (str); } if ((str = PL_String (PL_ObjectForKey (entity, "style")))) { light->data = atoi (str) & 0x3f; } + if ((str = PL_String (PL_ObjectForKey (entity, "delay")))) { + model = atoi (str) & 0x7; + if (model == 2) model = 5; //FIXME for marcher (need a map) + light->data |= model << 7; + } + if ((str = PL_String (PL_ObjectForKey (entity, "color"))) || (str = PL_String (PL_ObjectForKey (entity, "_color")))) { sscanf (str, "%f %f %f", VectorExpandAddr (light->color)); + VectorScale (light->color, 1/255.0, light->color); + } + + //FIXME magic numbers + if (model == 3) { // infinite + light->data |= 1 << 10; // cascade + } else if (model != 4) {// ambient + if (light->cone > -0.5) { + light->data |= 3 << 10; // cube + } else { + light->data |= 2 << 10; // plane + } } } @@ -500,11 +629,17 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) } } - for (int i = 1; i < PL_A_NumObjects (entities); i++) { + for (int i = 0; i < PL_A_NumObjects (entities); i++) { plitem_t *entity = PL_ObjectAtIndex (entities, i); const char *classname = PL_String (PL_ObjectForKey (entity, "classname")); - if (classname && strnequal (classname, "light", 5)) { + if (!classname) { + continue; + } + if (strequal (classname, "worldspawn")) { + // parse_sun can add many lights + parse_sun (lctx, entity); + } else if (strnequal (classname, "light", 5)) { qfv_light_t light = {}; parse_light (&light, entity, targets); @@ -512,13 +647,7 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) mleaf_t *leaf = Mod_PointInLeaf (&light.position[0], model); DARRAY_APPEND (&lctx->lightleafs, leaf - model->brush.leafs); - Sys_MaskPrintf (SYS_vulkan, - "[%g, %g, %g] %d, " - "[%g %g %g] %g, [%g %g %g] %g, %zd\n", - VectorExpand (light.color), light.data, - VectorExpand (light.position), light.radius, - VectorExpand (light.direction), light.cone, - leaf - model->brush.leafs); + dump_light (&light, leaf - model->brush.leafs); } } for (size_t i = 0; i < ctx->frames.size; i++) { From d5454faeb76940253c78ed108e2e0647dfb04af7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Apr 2021 12:20:32 +0900 Subject: [PATCH 1528/3664] [gamecode] Set legacy progs def sizes from type Legacy progs do not have the extended defs data (and usually won't have anything more complicated than a vector), so use the basic type size for the def size. Fixes broken edict prints. --- libs/gamecode/pr_load.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index f8365bd6f..2bca49575 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -324,6 +324,16 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) def->ofs = xdef->ofs; def->type_encoding = xdef->type; } + } else { + pr_def_t *def; + for (def = pr->pr_globaldefs, i = 0; i < pr->progs->numglobaldefs; + i++, def++) { + def->size = pr_type_size[def->type]; + } + for (def = pr->pr_fielddefs, i = 0; i < pr->progs->numfielddefs; + i++, def++) { + def->size = pr_type_size[def->type]; + } } pr->pr_trace = 0; pr->pr_trace_depth = 0; From 590f0f18bc2a417e3e4c43009a613d4ebcb1a986 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Apr 2021 12:22:54 +0900 Subject: [PATCH 1529/3664] [vulkan] Check leaf sky visibility for suns And fix some out-by-one errors for leaf visibility (pvs index 0 is actually leaf index 1) --- include/QF/model.h | 1 + libs/models/brush/model_brush.c | 17 +++++++++++++++++ libs/video/renderer/vulkan/vulkan_lighting.c | 19 ++++++++++++++----- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 1c5969820..295035f3d 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -272,6 +272,7 @@ typedef struct mod_brush_s { mnode_t **node_parents; mnode_t **leaf_parents; + int *leaf_flags; // union of surf flags for surfs in leaf unsigned int checksum; unsigned int checksum2; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index db9298ad5..74b6e7a48 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -651,6 +651,20 @@ Mod_SetParent (mod_brush_t *brush, mnode_t *node, mnode_t *parent) Mod_SetParent (brush, node->children[1], node); } +static void +Mod_SetLeafFlags (mod_brush_t *brush) +{ + for (int i = 0; i < brush->numleafs; i++) { + int flags = 0; + mleaf_t *leaf = &brush->leafs[i]; + for (int j = 0; j < leaf->nummarksurfaces; j++) { + msurface_t *surf = leaf->firstmarksurface[j]; + flags |= surf->flags; + } + brush->leaf_flags[i] = flags; + } +} + static void Mod_LoadNodes (model_t *mod, bsp_t *bsp) { @@ -704,9 +718,12 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) } size_t size = (brush->numleafs + brush->numnodes) * sizeof (mnode_t *); + size += brush->numleafs * sizeof (int); brush->node_parents = Hunk_AllocName (size, mod->name); brush->leaf_parents = brush->node_parents + brush->numnodes; + brush->leaf_flags = (int *) (brush->leaf_parents + brush->numleafs); Mod_SetParent (brush, brush->nodes, NULL); // sets nodes and leafs + Mod_SetLeafFlags (brush); } static void diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 8fd57078e..ec72f38b5 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -81,12 +81,19 @@ find_visible_lights (vulkan_ctx_t *ctx) if (leaf != lframe->leaf) { //double start = Sys_DoubleTime (); byte pvs[MAP_PVS_BYTES]; + int flags = 0; Mod_LeafPVS_set (leaf, model, 0, pvs); memcpy (lframe->pvs, pvs, sizeof (pvs)); for (int i = 0; i < model->brush.numleafs; i++) { if (pvs[i / 8] & (1 << (i % 8))) { - Mod_LeafPVS_mix (model->brush.leafs + i, model, 0, lframe->pvs); + Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, + lframe->pvs); + } + } + for (int i = 0; i < model->brush.numleafs; i++) { + if (lframe->pvs[i / 8] & (1 << (i % 8))) { + flags |= model->brush.leaf_flags[i + 1]; } } lframe->leaf = leaf; @@ -98,8 +105,8 @@ find_visible_lights (vulkan_ctx_t *ctx) memset (lframe->lightvis.a, 0, lframe->lightvis.size * sizeof (byte)); for (size_t i = 0; i < lctx->lightleafs.size; i++) { int l = lctx->lightleafs.a[i]; - //FIXME -1 needs check for sky - if (l == -1 || lframe->pvs[l / 8] & (1 << (l % 8))) { + if ((l == -1 && (flags & SURF_DRAWSKY)) + || lframe->pvs[l / 8] & (1 << (l % 8))) { lframe->lightvis.a[i] = 1; visible++; } @@ -646,8 +653,10 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) DARRAY_APPEND (&lctx->lights, light); mleaf_t *leaf = Mod_PointInLeaf (&light.position[0], model); - DARRAY_APPEND (&lctx->lightleafs, leaf - model->brush.leafs); - dump_light (&light, leaf - model->brush.leafs); + DARRAY_APPEND (&lctx->lightleafs, + leaf - model->brush.leafs - 1); + dump_light (&light, + lctx->lightleafs.a[lctx->lightleafs.size - 1]); } } for (size_t i = 0; i < ctx->frames.size; i++) { From e6bc5e3e11959d6d29cbd72992a92611215ea6af Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Apr 2021 15:02:08 +0900 Subject: [PATCH 1530/3664] [simd] Add qexpf function --- include/QF/simd/vec4f.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 8ae4cbd5e..82addbfaf 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -29,6 +29,7 @@ #define __QF_simd_vec4f_h #include +#include #include "QF/simd/types.h" @@ -92,6 +93,7 @@ GNU89INLINE inline vec4f_t qrotf (vec4f_t a, vec4f_t b) __attribute__((const)); * That is, [-x, -y, -z, w]. */ GNU89INLINE inline vec4f_t qconjf (vec4f_t q) __attribute__((const)); +GNU89INLINE inline vec4f_t qexpf (vec4f_t q) __attribute__((const)); GNU89INLINE inline vec4f_t loadvec3f (const float *v3) __attribute__((pure)); GNU89INLINE inline void storevec3f (float *v3, vec4f_t v4); GNU89INLINE inline vec4f_t normalf (vec4f_t v) __attribute__((pure)); @@ -267,6 +269,26 @@ qconjf (vec4f_t q) return _mm_xor_ps (q, (__m128) neg); } +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4f_t +qexpf (vec4f_t q) +{ + vec4f_t th = magnitude3f (q); + float r = expf (q[3]); + if (!th[0]) { + return (vec4f_t) { 0, 0, 0, r }; + } + float c = cosf (th[0]); + float s = sinf (th[0]); + vec4f_t n = (r * s) * (q / th); + n[3] = r * c; + return n; +} + #ifndef IMPLEMENT_VEC4F_Funcs GNU89INLINE inline #else From 8b6136e6f50e9b423a703d9adaf3c1c206ce7da5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Apr 2021 15:02:30 +0900 Subject: [PATCH 1531/3664] [mathlib] Add Blend macro The Blend macro supports any non-integral type supporting * and + (float, double, vec4f_t, etc), so it is essentially a scalar VectorBlend or QuatBlend. --- include/QF/mathlib.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index 851b841eb..ecb2f87f2 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -57,6 +57,8 @@ extern int nanmask; #define IS_NAN(x) (((*(int *) (char *) &x) & nanmask) == nanmask) +#define Blend(a,b,blend) ((1 - (blend)) * (a) + (blend) * (b)) + #include "QF/math/vector.h" #include "QF/math/quaternion.h" #include "QF/math/dual.h" From c86f0c94496b01e8fbcf891a1244cef9e71f2c5b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Apr 2021 15:47:50 +0900 Subject: [PATCH 1532/3664] [vulkan] Move projection matrix code to its own file And move more stuff over to simd. --- include/QF/Makemodule.am | 1 + include/QF/Vulkan/projection.h | 10 +++ include/QF/Vulkan/qf_bsp.h | 8 +- include/QF/Vulkan/qf_lighting.h | 4 + include/vid_vulkan.h | 9 ++- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vulkan/projection.c | 83 ++++++++++++++++++++ libs/video/renderer/vulkan/vulkan_bsp.c | 34 ++++---- libs/video/renderer/vulkan/vulkan_lighting.c | 3 + libs/video/renderer/vulkan/vulkan_matrices.c | 70 ++--------------- 10 files changed, 135 insertions(+), 88 deletions(-) create mode 100644 include/QF/Vulkan/projection.h create mode 100644 libs/video/renderer/vulkan/projection.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 6ebb73af6..79d2d2ec1 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -148,6 +148,7 @@ include_qf_vulkan = \ include/QF/Vulkan/instance.h \ include/QF/Vulkan/memory.h \ include/QF/Vulkan/pipeline.h \ + include/QF/Vulkan/projection.h \ include/QF/Vulkan/qf_alias.h \ include/QF/Vulkan/qf_bsp.h \ include/QF/Vulkan/qf_compose.h \ diff --git a/include/QF/Vulkan/projection.h b/include/QF/Vulkan/projection.h new file mode 100644 index 000000000..345acc3c8 --- /dev/null +++ b/include/QF/Vulkan/projection.h @@ -0,0 +1,10 @@ +#ifndef __QF_Vulkan_projection_h +#define __QF_Vulkan_projection_h + +#include "QF/simd/types.h" + +void QFV_Orthographic (mat4f_t proj, float xmin, float xmax, + float ymin, float ymax, float znear, float zfar); +void QFV_Perspective (mat4f_t proj, float fov, float aspect); + +#endif//__QF_Vulkan_projection_h diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 6c69f2586..249a43286 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -37,6 +37,8 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" +#include "QF/simd/types.h" + typedef struct bspvert_s { quat_t vertex; quat_t tlst; @@ -129,9 +131,9 @@ typedef struct bspctx_s { struct qfv_tex_s *default_skybox; struct qfv_tex_s *skybox_tex; - quat_t sky_rotation[2]; - quat_t sky_velocity; - quat_t sky_fix; + vec4f_t sky_rotation[2]; + vec4f_t sky_velocity; + vec4f_t sky_fix; double sky_time; quat_t default_color; diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 516d6acb7..9c6f2902a 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -35,6 +35,7 @@ #include "QF/modelgen.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" +#include "QF/Vulkan/image.h" #include "QF/simd/types.h" typedef struct qfv_light_s { @@ -49,6 +50,7 @@ typedef struct qfv_light_s { typedef struct qfv_lightset_s DARRAY_TYPE (qfv_light_t) qfv_lightset_t; typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightleafset_t; typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t; +typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t; #define NUM_LIGHTS 256 #define NUM_STYLES 64 @@ -100,6 +102,8 @@ typedef struct lightingctx_s { VkDeviceMemory light_memory; qfv_lightset_t lights; qfv_lightleafset_t lightleafs; + qfv_lightmatset_t lightmats; + //qfv_imageviewset_t lightviews; } lightingctx_t; struct vulkan_ctx_s; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 556780fc0..8a7cd1535 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -7,6 +7,7 @@ #include #include "QF/darray.h" +#include "QF/simd/types.h" typedef struct vulkan_frame_s { VkFramebuffer framebuffer; @@ -23,10 +24,10 @@ typedef struct vulkan_matrices_s { VkBuffer buffer_2d; VkBuffer buffer_3d; VkDeviceMemory memory; - float *projection_2d; - float *projection_3d; - float *view_3d; - float *sky_3d; + vec4f_t *projection_2d; + vec4f_t *projection_3d; + vec4f_t *view_3d; + vec4f_t *sky_3d; } vulkan_matrices_t; typedef struct vulkan_frameset_s diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 91162d71e..c07f98fcc 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -257,6 +257,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/instance.c \ libs/video/renderer/vulkan/memory.c \ libs/video/renderer/vulkan/pipeline.c \ + libs/video/renderer/vulkan/projection.c \ libs/video/renderer/vulkan/renderpass.c \ libs/video/renderer/vulkan/scrap.c \ libs/video/renderer/vulkan/shader.c \ diff --git a/libs/video/renderer/vulkan/projection.c b/libs/video/renderer/vulkan/projection.c new file mode 100644 index 000000000..3f31200d7 --- /dev/null +++ b/libs/video/renderer/vulkan/projection.c @@ -0,0 +1,83 @@ +/* + proejct.c + + Vulkan projection matrices + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/Vulkan/projection.h" + +#include "r_internal.h" + +void +QFV_Orthographic (mat4f_t proj, float xmin, float xmax, float ymin, float ymax, + float znear, float zfar) +{ + proj[0] = (vec4f_t) { + 2 / (xmax - xmin), + 0, + 0, + 0 + }; + proj[1] = (vec4f_t) { + 0, + 2 / (ymax - ymin), + 0, + 0 + }; + proj[2] = (vec4f_t) { + 0, + 0, + 1 / (znear - zfar), + 0 + }; + proj[3] = (vec4f_t) { + -(xmax + xmin) / (xmax - xmin), + -(ymax + ymin) / (ymax - ymin), + znear / (znear - zfar), + 1, + }; +} + +void +QFV_Perspective (mat4f_t proj, float fov, float aspect) +{ + float f = 1 / tan (fov * M_PI / 360); + float neard, fard; + + neard = r_nearclip->value; + fard = r_farclip->value; + + proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 }; + proj[1] = (vec4f_t) { 0, -f, 0, 0 }; + proj[2] = (vec4f_t) { 0, 0, fard / (neard - fard), -1 }; + proj[3] = (vec4f_t) { 0, 0, (neard * fard) / (neard - fard), 0 }; +} diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index ee2d50870..6c3ff0fbb 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -422,11 +422,11 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) bsppoly_t *poly; mod_brush_t *brush; - QuatSet (0, 0, sqrt(0.5), sqrt(0.5), bctx->sky_fix); // proper skies - QuatSet (0, 0, 0, 1, bctx->sky_rotation[0]); - QuatCopy (bctx->sky_rotation[0], bctx->sky_rotation[1]); - QuatSet (0, 0, 0, 0, bctx->sky_velocity); - QuatExp (bctx->sky_velocity, bctx->sky_velocity); + bctx->sky_fix = (vec4f_t) { 0, 0, 1, 1 } * sqrtf (0.5); + bctx->sky_rotation[0] = (vec4f_t) { 0, 0, 0, 1}; + bctx->sky_rotation[1] = bctx->sky_rotation[0]; + bctx->sky_velocity = (vec4f_t) { }; + bctx->sky_velocity = qexpf (bctx->sky_velocity); bctx->sky_time = vr_data.realtime; // now run through all surfaces, chaining them to their textures, thus @@ -995,26 +995,26 @@ turb_end (vulkan_ctx_t *ctx) } static void -spin (mat4_t mat, bspctx_t *bctx) +spin (mat4f_t mat, bspctx_t *bctx) { - quat_t q; - mat4_t m; + vec4f_t q; + mat4f_t m; float blend; while (vr_data.realtime - bctx->sky_time > 1) { - QuatCopy (bctx->sky_rotation[1], bctx->sky_rotation[0]); - QuatMult (bctx->sky_velocity, bctx->sky_rotation[0], - bctx->sky_rotation[1]); + bctx->sky_rotation[0] = bctx->sky_rotation[1]; + bctx->sky_rotation[1] = qmulf (bctx->sky_velocity, + bctx->sky_rotation[0]); bctx->sky_time += 1; } blend = bound (0, (vr_data.realtime - bctx->sky_time), 1); - QuatBlend (bctx->sky_rotation[0], bctx->sky_rotation[1], blend, q); - QuatMult (bctx->sky_fix, q, q); - Mat4Identity (mat); - VectorNegate (r_origin, mat + 12); - QuatToMatrix (q, m, 1, 1); - Mat4Mult (m, mat, mat); + q = Blend (bctx->sky_rotation[0], bctx->sky_rotation[1], blend); + q = normalf (qmulf (bctx->sky_fix, q)); + mat4fidentity (mat); + VectorNegate (r_origin, mat[3]); + mat4fquat (m, q); + mmulf (mat, m, mat); } static void diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index ec72f38b5..5fddc2653 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -284,6 +284,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&lctx->lights, 16); DARRAY_INIT (&lctx->lightleafs, 16); + DARRAY_INIT (&lctx->lightmats, 16); size_t frames = ctx->frames.size; DARRAY_INIT (&lctx->frames, frames); @@ -410,6 +411,7 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0); DARRAY_CLEAR (&lctx->lights); DARRAY_CLEAR (&lctx->lightleafs); + DARRAY_CLEAR (&lctx->lightmats); free (lctx->frames.a); free (lctx); } @@ -606,6 +608,7 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) lctx->lights.size = 0; lctx->lightleafs.size = 0; + lctx->lightmats.size = 0; script_t *script = Script_New (); Script_Start (script, "ent data", entity_data); diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 168b63e2b..359aad1b1 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -32,16 +32,13 @@ # include #endif -#include "QF/cvar.h" -#include "QF/mathlib.h" #include "QF/sys.h" #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/projection.h" -#include "compat.h" -#include "d_iface.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -49,61 +46,6 @@ #define MAT_SIZE (16 * sizeof (float)) -static void -ortho_mat (float *proj, float xmin, float xmax, float ymin, float ymax, - float znear, float zfar) -{ - proj[0] = 2 / (xmax - xmin); - proj[4] = 0; - proj[8] = 0; - proj[12] = -(xmax + xmin) / (xmax - xmin); - - proj[1] = 0; - proj[5] = 2 / (ymax - ymin); - proj[9] = 0; - proj[13] = -(ymax + ymin) / (ymax - ymin); - - proj[2] = 0; - proj[6] = 0; - proj[10] = 1 / (znear - zfar); - proj[14] = znear / (znear - zfar); - - proj[3] = 0; - proj[7] = 0; - proj[11] = 0; - proj[15] = 1; -} - -static void -persp_mat (float *proj, float fov, float aspect) -{ - float f = 1 / tan (fov * M_PI / 360); - float neard, fard; - - neard = r_nearclip->value; - fard = r_farclip->value; - - proj[0] = f / aspect; - proj[4] = 0; - proj[8] = 0; - proj[12] = 0; - - proj[1] = 0; - proj[5] = -f; - proj[9] = 0; - proj[13] = 0; - - proj[2] = 0; - proj[6] = 0; - proj[10] = fard / (neard - fard); - proj[14] = (neard * fard) / (neard - fard); - - proj[3] = 0; - proj[7] = 0; - proj[11] = -1; - proj[15] = 0; -} - void Vulkan_DestroyMatrices (vulkan_ctx_t *ctx) { @@ -150,9 +92,9 @@ Vulkan_CreateMatrices (vulkan_ctx_t *ctx) void *data; dfunc->vkMapMemory (device->dev, mat->memory, 0, size, 0, &data); mat->projection_2d = data; - mat->projection_3d = mat->projection_2d + offset / sizeof (float); - mat->view_3d = mat->projection_3d + 16; - mat->sky_3d = mat->view_3d + 16; + mat->projection_3d = (vec4f_t *) ((byte *) mat->projection_2d + offset); + mat->view_3d = mat->projection_3d + 4; + mat->sky_3d = mat->view_3d + 4; } void @@ -165,10 +107,10 @@ Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx) int width = vid.conwidth; int height = vid.conheight; - ortho_mat (mat->projection_2d, 0, width, 0, height, -99999, 99999); + QFV_Orthographic (mat->projection_2d, 0, width, 0, height, -99999, 99999); float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; - persp_mat (mat->projection_3d, r_refdef.fov_y, aspect); + QFV_Perspective (mat->projection_3d, r_refdef.fov_y, aspect); #if 0 Sys_MaskPrintf (SYS_vulkan, "ortho:\n"); Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n", From cb7d2671d895c94a1752ea460ec2a2571fd08c59 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Apr 2021 19:25:31 +0900 Subject: [PATCH 1533/3664] [simd] Make mmulf safe for src=dst I guess I'd forgotten that the parameters are actually pointers. --- include/QF/simd/mat4f.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/include/QF/simd/mat4f.h b/include/QF/simd/mat4f.h index 658cf582b..e461fe4a3 100644 --- a/include/QF/simd/mat4f.h +++ b/include/QF/simd/mat4f.h @@ -77,10 +77,16 @@ VISIBLE void mmulf (mat4f_t c, const mat4f_t a, const mat4f_t b) { - c[0] = a[0] * b[0][0] + a[1] * b[0][1] + a[2] * b[0][2] + a[3] * b[0][3]; - c[1] = a[0] * b[1][0] + a[1] * b[1][1] + a[2] * b[1][2] + a[3] * b[1][3]; - c[2] = a[0] * b[2][0] + a[1] * b[2][1] + a[2] * b[2][2] + a[3] * b[2][3]; - c[3] = a[0] * b[3][0] + a[1] * b[3][1] + a[2] * b[3][2] + a[3] * b[3][3]; + mat4f_t t; + t[0] = a[0] * b[0][0] + a[1] * b[0][1] + a[2] * b[0][2] + a[3] * b[0][3]; + t[1] = a[0] * b[1][0] + a[1] * b[1][1] + a[2] * b[1][2] + a[3] * b[1][3]; + t[2] = a[0] * b[2][0] + a[1] * b[2][1] + a[2] * b[2][2] + a[3] * b[2][3]; + t[3] = a[0] * b[3][0] + a[1] * b[3][1] + a[2] * b[3][2] + a[3] * b[3][3]; + + c[0] = t[0]; + c[1] = t[1]; + c[2] = t[2]; + c[3] = t[3]; } #ifndef IMPLEMENT_MAT4F_Funcs From 562f3c2fe22e4d0cddf3f4ba1daa0c26caa3ba7f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Apr 2021 19:27:01 +0900 Subject: [PATCH 1534/3664] [vulkan] Add tan and cos perspective projection The tan and cos versions allow specifying the fov directly from the tan or cos of the half angle, useful for dealing with lights. --- include/QF/Vulkan/projection.h | 2 ++ libs/video/renderer/vulkan/projection.c | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/projection.h b/include/QF/Vulkan/projection.h index 345acc3c8..7a1dc96bd 100644 --- a/include/QF/Vulkan/projection.h +++ b/include/QF/Vulkan/projection.h @@ -5,6 +5,8 @@ void QFV_Orthographic (mat4f_t proj, float xmin, float xmax, float ymin, float ymax, float znear, float zfar); +void QFV_PerspectiveTan (mat4f_t proj, float fov, float aspect); +void QFV_PerspectiveCos (mat4f_t proj, float fov, float aspect); void QFV_Perspective (mat4f_t proj, float fov, float aspect); #endif//__QF_Vulkan_projection_h diff --git a/libs/video/renderer/vulkan/projection.c b/libs/video/renderer/vulkan/projection.c index 3f31200d7..a4f597268 100644 --- a/libs/video/renderer/vulkan/projection.c +++ b/libs/video/renderer/vulkan/projection.c @@ -68,9 +68,9 @@ QFV_Orthographic (mat4f_t proj, float xmin, float xmax, float ymin, float ymax, } void -QFV_Perspective (mat4f_t proj, float fov, float aspect) +QFV_PerspectiveTan (mat4f_t proj, float fov, float aspect) { - float f = 1 / tan (fov * M_PI / 360); + float f = 1 / fov; float neard, fard; neard = r_nearclip->value; @@ -81,3 +81,17 @@ QFV_Perspective (mat4f_t proj, float fov, float aspect) proj[2] = (vec4f_t) { 0, 0, fard / (neard - fard), -1 }; proj[3] = (vec4f_t) { 0, 0, (neard * fard) / (neard - fard), 0 }; } + +void +QFV_PerspectiveCos (mat4f_t proj, float fov, float aspect) +{ + // square first for auto-abs (no support for > 180 degree fov) + fov = fov * fov; + QFV_PerspectiveTan (proj, sqrt ((1 - fov) / fov), aspect); +} + +void +QFV_Perspective (mat4f_t proj, float fov, float aspect) +{ + QFV_PerspectiveTan (proj, tan (fov * M_PI / 360), aspect); +} From 1cf40be484c92d1c25662cc7fb496e3112f7c3a1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Apr 2021 20:54:38 +0900 Subject: [PATCH 1535/3664] [vulkan] Create shadow maps and basic data I will definitely need to look into sparse images later (2.3GB for marcher) but the shadow map images, views and matrices are created. --- include/QF/Vulkan/qf_lighting.h | 40 ++- .../renderer/vulkan/shader/lighting.frag | 6 +- libs/video/renderer/vulkan/vulkan_lighting.c | 333 ++++++++++++++++-- 3 files changed, 342 insertions(+), 37 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 9c6f2902a..cdf3b612e 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -48,26 +48,43 @@ typedef struct qfv_light_s { } qfv_light_t; typedef struct qfv_lightset_s DARRAY_TYPE (qfv_light_t) qfv_lightset_t; -typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightleafset_t; +typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightintset_t; typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t; typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t; -#define NUM_LIGHTS 256 -#define NUM_STYLES 64 +#define MaxLights 256 + +#define StyleMask 0x07f +#define ModelMask 0x380 +#define ShadowMask 0xc00 + +#define LM_LINEAR (0 << 7) // light - dist (or radius + dist if -ve) +#define LM_INVERSE (1 << 7) // distFactor1 * light / dist +#define LM_INVERSE2 (2 << 7) // distFactor2 * light / (dist * dist) +#define LM_INFINITE (3 << 7) // light +#define LM_AMBIENT (4 << 7) // light +#define LM_INVERSE3 (5 << 7) // distFactor2 * light / (dist + distFactor2)**2 + +#define ST_NONE (0 << 10) // no shadows +#define ST_PLANE (1 << 10) // single plane shadow map (small spotlight) +#define ST_CASCADE (2 << 10) // cascaded shadow maps +#define ST_CUBE (3 << 10) // cubemap (omni, large spotlight) + +#define NumStyles 64 typedef struct qfv_light_buffer_s { - float intensity[NUM_STYLES + 4]; + float intensity[NumStyles + 4]; float distFactor1; float distFactor2; int lightCount; - qfv_light_t lights[NUM_LIGHTS] __attribute__((aligned(16))); - mat4f_t shadowMat[NUM_LIGHTS]; - vec4f_t shadowCascade[NUM_LIGHTS]; + qfv_light_t lights[MaxLights] __attribute__((aligned(16))); + mat4f_t shadowMat[MaxLights]; + vec4f_t shadowCascade[MaxLights]; } qfv_light_buffer_t; #define LIGHTING_BUFFER_INFOS 1 #define LIGHTING_ATTACH_INFOS 5 -#define LIGHTING_SHADOW_INFOS NUM_LIGHTS +#define LIGHTING_SHADOW_INFOS MaxLights #define LIGHTING_DESCRIPTORS (LIGHTING_BUFFER_INFOS + LIGHTING_ATTACH_INFOS + 1) typedef struct lightingframe_s { @@ -100,10 +117,13 @@ typedef struct lightingctx_s { VkPipelineLayout layout; VkSampler sampler; VkDeviceMemory light_memory; + VkDeviceMemory shadow_memory; qfv_lightset_t lights; - qfv_lightleafset_t lightleafs; + qfv_lightintset_t lightleafs; qfv_lightmatset_t lightmats; - //qfv_imageviewset_t lightviews; + qfv_imageset_t lightimages; + qfv_lightintset_t lightlayers; + qfv_imageviewset_t lightviews; } lightingctx_t; struct vulkan_ctx_s; diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index a6db899c8..4f53c412c 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -14,7 +14,7 @@ struct LightData { vec3 direction; float cone; }; - +//XXX can't include :( be sure to keep up to date with qf_lighting.h #define MaxLights 256 #define StyleMask 0x07f @@ -29,8 +29,8 @@ struct LightData { #define LM_INVERSE3 (5 << 7) // distFactor2 * light / (dist + distFactor2)**2 #define ST_NONE (0 << 10) // no shadows -#define ST_CASCADE (1 << 10) // cascaded shadow maps -#define ST_PLANE (2 << 10) // single plane shadow map (small spotlight) +#define ST_PLANE (1 << 10) // single plane shadow map (small spotlight) +#define ST_CASCADE (2 << 10) // cascaded shadow maps #define ST_CUBE (3 << 10) // cubemap (omni, large spotlight) layout (set = 2, binding = 0) uniform sampler2DArrayShadow shadowCascade[MaxLights]; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 5fddc2653..e666e4c77 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -56,6 +56,8 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/projection.h" #include "QF/Vulkan/staging.h" #include "compat.h" @@ -63,6 +65,8 @@ #include "r_internal.h" #include "vid_vulkan.h" +static vec4f_t ref_direction = { 0, 0, 1, 0 }; + static void find_visible_lights (vulkan_ctx_t *ctx) { @@ -126,12 +130,12 @@ update_lights (vulkan_ctx_t *ctx) find_visible_lights (ctx); - dlight_t *lights[NUM_LIGHTS]; + dlight_t *lights[MaxLights]; qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); qfv_light_buffer_t *light_data = QFV_PacketExtend (packet, sizeof (*light_data)); - for (int i = 0; i < NUM_STYLES; i++) { + for (int i = 0; i < NumStyles; i++) { light_data->intensity[i] = d_lightstylevalue[i] / 65536.0; } // dynamic lights seem a tad faint, so 16x map lights @@ -144,8 +148,8 @@ update_lights (vulkan_ctx_t *ctx) light_data->distFactor2 = 1 / 16384.0; light_data->lightCount = 0; - R_FindNearLights (r_origin, NUM_LIGHTS - 1, lights); - for (int i = 0; i < NUM_LIGHTS - 1; i++) { + R_FindNearLights (r_origin, MaxLights - 1, lights); + for (int i = 0; i < MaxLights - 1; i++) { if (!lights[i]) { break; } @@ -158,7 +162,7 @@ update_lights (vulkan_ctx_t *ctx) light_data->lights[i].cone = 1; } for (size_t i = 0; (i < lframe->lightvis.size - && light_data->lightCount < NUM_LIGHTS); i++) { + && light_data->lightCount < MaxLights); i++) { if (lframe->lightvis.a[i]) { light_data->lights[light_data->lightCount++] = lctx->lights.a[i]; } @@ -285,6 +289,9 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&lctx->lights, 16); DARRAY_INIT (&lctx->lightleafs, 16); DARRAY_INIT (&lctx->lightmats, 16); + DARRAY_INIT (&lctx->lightlayers, 16); + DARRAY_INIT (&lctx->lightimages, 16); + DARRAY_INIT (&lctx->lightviews, 16); size_t frames = ctx->frames.size; DARRAY_INIT (&lctx->frames, frames); @@ -388,13 +395,33 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->shadowWrite = base_image_write; lframe->shadowWrite.dstSet = shadow_set->a[i]; lframe->shadowWrite.dstBinding = 0; - lframe->shadowWrite.descriptorCount = NUM_LIGHTS; + lframe->shadowWrite.descriptorCount = MaxLights; lframe->shadowWrite.pImageInfo = lframe->shadowInfo; } free (attach_set); free (lights_set); } +static void +clear_shadows (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + lightingctx_t *lctx = ctx->lighting_context; + + if (lctx->shadow_memory) { + dfunc->vkFreeMemory (device->dev, lctx->shadow_memory, 0); + } + for (size_t i = 0; i < lctx->lightviews.size; i++) { + dfunc->vkDestroyImageView (device->dev, lctx->lightviews.a[i], 0); + } + for (size_t i = 0; i < lctx->lightimages.size; i++) { + dfunc->vkDestroyImage (device->dev, lctx->lightimages.a[i], 0); + } + lctx->lightimages.size = 0; + lctx->lightviews.size = 0; +} + void Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) { @@ -402,6 +429,8 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; lightingctx_t *lctx = ctx->lighting_context; + clear_shadows (ctx); + for (size_t i = 0; i < lctx->frames.size; i++) { lightingframe_t *lframe = &lctx->frames.a[i]; dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0); @@ -412,12 +441,15 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) DARRAY_CLEAR (&lctx->lights); DARRAY_CLEAR (&lctx->lightleafs); DARRAY_CLEAR (&lctx->lightmats); + DARRAY_CLEAR (&lctx->lightimages); + DARRAY_CLEAR (&lctx->lightlayers); + DARRAY_CLEAR (&lctx->lightviews); free (lctx->frames.a); free (lctx); } static void -dump_light (qfv_light_t *light, int leaf) +dump_light (qfv_light_t *light, int leaf, mat4f_t mat) { Sys_MaskPrintf (SYS_vulkan, "[%g, %g, %g] %d %d %d, " @@ -429,6 +461,10 @@ dump_light (qfv_light_t *light, int leaf) VectorExpand (light->position), light->light, VectorExpand (light->direction), light->cone, leaf); + Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 0)); + Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 1)); + Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 2)); + Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 3)); } static float @@ -516,13 +552,12 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity) return; } VectorSet (1, 1, 1, light.color); - light.data = 3 << 7; //FIXME magic number (LM_INFINITE) + light.data = LM_INFINITE | ST_CASCADE; light.light = sunlight; sun_vector (sunangle, light.direction); light.cone = 1; DARRAY_APPEND (&lctx->lights, light); DARRAY_APPEND (&lctx->lightleafs, -1); - dump_light (&light, -1); } static void @@ -577,9 +612,11 @@ parse_light (qfv_light_t *light, const plitem_t *entity, } if ((str = PL_String (PL_ObjectForKey (entity, "delay")))) { - model = atoi (str) & 0x7; - if (model == 2) model = 5; //FIXME for marcher (need a map) - light->data |= model << 7; + model = (atoi (str) & 0x7) << 7; + if (model == LM_INVERSE2) { + model = LM_INVERSE3; //FIXME for marcher (need a map) + } + light->data |= model; } if ((str = PL_String (PL_ObjectForKey (entity, "color"))) @@ -588,18 +625,263 @@ parse_light (qfv_light_t *light, const plitem_t *entity, VectorScale (light->color, 1/255.0, light->color); } - //FIXME magic numbers - if (model == 3) { // infinite - light->data |= 1 << 10; // cascade - } else if (model != 4) {// ambient + if (model == LM_INFINITE) { + light->data |= ST_CASCADE; + } else if (model != LM_AMBIENT) { if (light->cone > -0.5) { - light->data |= 3 << 10; // cube + light->data |= ST_CUBE; } else { - light->data |= 2 << 10; // plane + light->data |= ST_PLANE; } } } +static void +create_light_matrices (lightingctx_t *lctx) +{ + DARRAY_RESIZE (&lctx->lightmats, lctx->lights.size); + for (size_t i = 0; i < lctx->lights.size; i++) { + qfv_light_t *light = &lctx->lights.a[i]; + mat4f_t view; + mat4f_t proj; + + switch (light->data & ShadowMask) { + case ST_NONE: + case ST_CUBE: + mat4fidentity (view); + break; + case ST_CASCADE: + case ST_PLANE: + //FIXME will fail for -ref_direction + mat4fquat (view, qrotf (loadvec3f (light->direction), + ref_direction)); + break; + } + VectorNegate (light->position, view[3]); + + switch (light->data & ShadowMask) { + case ST_NONE: + mat4fidentity (proj); + break; + case ST_CUBE: + QFV_PerspectiveTan (proj, 1, 1); + break; + case ST_CASCADE: + // dependent on view fustrum and cascade level + mat4fidentity (proj); + break; + case ST_PLANE: + QFV_PerspectiveCos (proj, light->cone, 1); + break; + } + mmulf (lctx->lightmats.a[i], proj, view); + } +} + +static int +light_compare (const void *_l2, const void *_l1) +{ + const qfv_light_t *l1 = _l1; + const qfv_light_t *l2 = _l2; + + if (l1->light == l2->light) { + return (l1->data & ShadowMask) - (l2->data & ShadowMask); + } + return l1->light - l2->light; +} + +static VkImage +create_map (int size, int layers, int cube, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + if (layers < 6) { + cube = 0; + } + + VkImageCreateInfo createInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 0, + cube ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, VK_IMAGE_TYPE_2D, + VK_FORMAT_X8_D24_UNORM_PACK32, + { size, size, 1 }, 1, layers, + VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT, VK_SHARING_MODE_EXCLUSIVE, + 0, 0, + VK_IMAGE_LAYOUT_UNDEFINED, + }; + VkImage image; + dfunc->vkCreateImage (device->dev, &createInfo, 0, &image); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, image, + va (ctx->va_ctx, "image:shadowmap:%d:%d", + size, layers)); + return image; +} + +static VkImageView +create_view (VkImage image, int baseLayer, int data, int id, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + int layers = 0; + VkImageViewType type = 0; + const char *viewtype = 0; + + switch (data & ShadowMask) { + case ST_NONE: + return 0; + case ST_PLANE: + layers = 1; + type = VK_IMAGE_VIEW_TYPE_2D; + viewtype = "plane"; + break; + case ST_CASCADE: + layers = 4; + type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + viewtype = "cascade"; + break; + case ST_CUBE: + layers = 6; + type = VK_IMAGE_VIEW_TYPE_CUBE; + viewtype = "cube"; + break; + } + + VkImageViewCreateInfo createInfo = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0, + 0, + image, type, VK_FORMAT_X8_D24_UNORM_PACK32, + { + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, + }, + { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, baseLayer, layers } + }; + + VkImageView view; + dfunc->vkCreateImageView (device->dev, &createInfo, 0, &view); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, view, + va (ctx->va_ctx, "iview:shadowmap:%s:%d", + viewtype, id)); + return view; +} + +static void +build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + qfv_physdev_t *physDev = device->physDev; + int maxLayers = physDev->properties.limits.maxImageArrayLayers; + qfv_light_t *lights = lctx->lights.a; + int numLights = lctx->lights.size; + int size = -1; + int numLayers = 0; + int totalLayers = 0; + int *imageMap = alloca (numLights * sizeof (int)); + size_t memsize = 0; + + DARRAY_RESIZE (&lctx->lightlayers, numLights); + qsort (lights, numLights, sizeof (qfv_light_t), light_compare); + for (int i = 0; i < numLights; i++) { + int shadow = lights[i].data & ShadowMask; + int layers = 1; + if (shadow == ST_CASCADE || shadow == ST_NONE) { + // cascade shadows will be handled separately, and "none" has no + // shadow map at all + imageMap[i] = -1; + continue; + } + if (shadow == ST_CUBE) { + layers = 6; + } + if (size != (int) lights[i].light || numLayers + layers > maxLayers) { + if (numLayers) { + VkImage shadow_map = create_map (size, numLayers, 1, ctx); + DARRAY_APPEND (&lctx->lightimages, shadow_map); + numLayers = 0; + } + size = lights[i].light; + } + imageMap[i] = lctx->lightimages.size; + lctx->lightlayers.a[i] = numLayers; + numLayers += layers; + totalLayers += layers; + } + if (numLayers) { + VkImage shadow_map = create_map (size, numLayers, 1, ctx); + DARRAY_APPEND (&lctx->lightimages, shadow_map); + } + + numLayers = 0; + size = 1024; + for (int i = 0; i < numLights; i++) { + int shadow = lights[i].data & ShadowMask; + int layers = 4; + + if (shadow != ST_CASCADE) { + continue; + } + if (numLayers + layers > maxLayers) { + VkImage shadow_map = create_map (size, numLayers, 0, ctx); + DARRAY_APPEND (&lctx->lightimages, shadow_map); + numLayers = 0; + } + imageMap[i] = lctx->lightimages.size; + lctx->lightlayers.a[i] = numLayers; + numLayers += layers; + totalLayers += layers; + } + if (numLayers) { + VkImage shadow_map = create_map (size, numLayers, 0, ctx); + DARRAY_APPEND (&lctx->lightimages, shadow_map); + } + + for (size_t i = 0; i < lctx->lightimages.size; i++) { + memsize += QFV_GetImageSize (device, lctx->lightimages.a[i]); + } + lctx->shadow_memory = QFV_AllocImageMemory (device, lctx->lightimages.a[0], + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + memsize, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + lctx->shadow_memory, "memory:shadowmap"); + + size_t offset = 0; + for (size_t i = 0; i < lctx->lightimages.size; i++) { + dfunc->vkBindImageMemory (device->dev, lctx->lightimages.a[i], + lctx->shadow_memory, offset); + offset += QFV_GetImageSize (device, lctx->lightimages.a[i]); + } + + DARRAY_RESIZE (&lctx->lightviews, numLights); + for (int i = 0; i < numLights; i++) { + if (imageMap[i] == -1) { + lctx->lightviews.a[i] = 0; + continue; + } + lctx->lightviews.a[i] = create_view (lctx->lightimages.a[imageMap[i]], + lctx->lightlayers.a[i], + lctx->lights.a[i].data, i, ctx); + } + Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n", + totalLayers, lctx->lightimages.size, memsize); +} + +static void +locate_lights (model_t *model, lightingctx_t *lctx) +{ + qfv_light_t *lights = lctx->lights.a; + DARRAY_RESIZE (&lctx->lightleafs, lctx->lights.size); + for (size_t i = 0; i < lctx->lights.size; i++) { + mleaf_t *leaf = Mod_PointInLeaf (&lights[i].position[0], model); + lctx->lightleafs.a[i] = leaf - model->brush.leafs - 1; + } +} + void Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) { @@ -610,6 +892,8 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) lctx->lightleafs.size = 0; lctx->lightmats.size = 0; + clear_shadows (ctx); + script_t *script = Script_New (); Script_Start (script, "ent data", entity_data); @@ -654,12 +938,6 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) parse_light (&light, entity, targets); DARRAY_APPEND (&lctx->lights, light); - mleaf_t *leaf = Mod_PointInLeaf (&light.position[0], - model); - DARRAY_APPEND (&lctx->lightleafs, - leaf - model->brush.leafs - 1); - dump_light (&light, - lctx->lightleafs.a[lctx->lightleafs.size - 1]); } } for (size_t i = 0; i < ctx->frames.size; i++) { @@ -675,4 +953,11 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) PL_Free (entities); } Sys_MaskPrintf (SYS_vulkan, "loaded %zd lights\n", lctx->lights.size); + build_shadow_maps (lctx, ctx); + create_light_matrices (lctx); + locate_lights (model, lctx); + for (size_t i = 0; i < lctx->lights.size; i++) { + dump_light (&lctx->lights.a[i], lctx->lightleafs.a[i], + lctx->lightmats.a[i]); + } } From 9dca47c0e123c7d03bb1147c9f1dd71c2a6dfc29 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jul 2015 18:50:36 +0900 Subject: [PATCH 1536/3664] Make the set tests word size agnostic. --- libs/util/test/test-set.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index 3771d9f0e..87e216f18 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -4,7 +4,9 @@ #include #include +#include "QF/dstring.h" #include "QF/set.h" +#include "QF/va.h" #define SIZE (SET_DEFMAP_SIZE * sizeof (set_bits_t) * 8) @@ -190,6 +192,21 @@ main (int argc, const char **argv) { size_t i; int res = 0; + dstring_t *str; + + //printf ("set_bits_t: %d, SET_DEFMAP_SIZE: %d, SIZE: %d\n", + // sizeof (set_bits_t), SET_DEFMAP_SIZE, SIZE); + + tests[5].str_expect = nva ("{%d}", SIZE); + tests[7].str_expect = nva ("{%d ...}", SIZE); + tests[8].str_expect = nva ("{%d ...}", SIZE); + + str = dstring_new (); + for (i = 0; i < SIZE; i++) { + dasprintf (str, "%c%d", i ? ' ' : '{', i); + } + dstring_appendstr (str, "}"); + tests[6].str_expect = dstring_freeze (str); for (i = 0; i < num_tests; i++) { set_t *s1, *s2 = 0; From 0a6cb3ad53358a3423d8ccb9f53bd426c5154b81 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 May 2021 13:07:10 +0900 Subject: [PATCH 1537/3664] [vulkan] Don't build vkgen when vulkan is unavailable --- config.d/build_control.m4 | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 9f7e9d1ab..1b888ce14 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -39,6 +39,7 @@ QFSPRITEGEN_TARGETS="" QFVIS_TARGETS="" WAD_TARGETS="" WAV_TARGETS="" +VKGEN_TARGETS="" CD_TARGETS="" SND_TARGETS="" @@ -292,6 +293,10 @@ if test "x$ENABLE_tools_wav" = xyes; then QF_NEED(tools,[wav]) QF_NEED(libs,[util]) fi +if test "x$render_need_vulkan" = xyes; then + VKGEN_TARGETS="vkgen.dat\$(EXEEXT)" + QF_NEED(tools,[qfcc pak qwaq]) +fi QF_NEED(top, [libs hw nq qtv qw]) @@ -440,6 +445,8 @@ QF_SUBST(QFVIS_TARGETS) QF_SUBST(WAD_TARGETS) QF_SUBST(WAV_TARGETS) +QF_SUBST(VKGEN_TARGETS) + QF_DEPS(BSP2IMG, [], [$(top_builddir)/libs/image/libQFimage.la @@ -525,3 +532,8 @@ QF_DEPS(WAV, [$(top_builddir)/libs/util/libQFutil.la], [$(WIN32_LIBS)], ) +QF_DEPS(VKGEN, + [], + [], + [], +) From a461c0958622624965a648d140b79b2ef8b8fb78 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 May 2021 11:19:55 +0900 Subject: [PATCH 1538/3664] [util] Make cmem consistent on 32 and 64 bit systems I don't know that the cache line size is 64 bytes on 32 bit systems, but it should be ok to assume that 64-byte alignment behaves well on systems with smaller cache lines so long as they are powers of two. This does mean there is some waste on 32-bit systems, but it should be fairly minimal (32 bytes per memblock, which manages page sized regions). --- include/QF/cmem.h | 6 ++++-- libs/util/cmem.c | 2 +- libs/util/test/test-cmem.c | 26 +++++++++++++++++++------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/include/QF/cmem.h b/include/QF/cmem.h index a6520d1cf..dd53df256 100644 --- a/include/QF/cmem.h +++ b/include/QF/cmem.h @@ -48,7 +48,7 @@ typedef struct memline_s { */ struct memblock_s *block; size_t pad[2]; -} memline_t; +} __attribute__((aligned (64))) memline_t; typedef struct memsline_s { struct memsline_s *next; @@ -82,9 +82,11 @@ typedef struct memblock_s { /* True if the post-header block is free to be reused. */ int post_free; +#if __WORDSIZE == 64 int pad; +#endif size_t pre_allocated; -} memblock_t; +} __attribute__((aligned (64))) memblock_t; typedef struct memsuper_s { size_t page_size; diff --git a/libs/util/cmem.c b/libs/util/cmem.c index 02f78bb0e..d14f0580a 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -114,7 +114,7 @@ init_block (memsuper_t *super, void *mem, size_t alloc_size) size_t ptr = (size_t) mem; memblock_t *block; - block = (memblock_t *) (((ptr + size) & ~mask) - sizeof (memblock_t)); + block = (memblock_t *) (((ptr + size) & ~mask)) - 1; memset (block, 0, sizeof (memblock_t)); if (super->memblocks) { diff --git a/libs/util/test/test-cmem.c b/libs/util/test/test-cmem.c index 4f146ccc7..51dbd2ab6 100644 --- a/libs/util/test/test-cmem.c +++ b/libs/util/test/test-cmem.c @@ -57,9 +57,11 @@ check_block (memblock_t *block, int line_count, int allocated) for (memline_t **l = &block->free_lines; *l; l = &(*l)->block_next) { memline_t *line = *l; - ptrdiff_t ind = (memline_t *) block - line; + ptrdiff_t ind = (byte *) block - (byte *) line; + ind /= MEM_LINE_SIZE; if (ind < 1 || (size_t ) ind > block->pre_size / MEM_LINE_SIZE) { - fprintf (stderr, "line outside of block\n"); + fprintf (stderr, "line outside of block: %p %p %p\n", + line, block->mem, block); return 0; } if (set_is_member (visited, ind)) { @@ -187,15 +189,18 @@ test_line (memsuper_t *super) return 0; } if (line1 < (memline_t *) block->mem || line1 >= (memline_t *) block) { - fprintf (stderr, "line1 outside block line pool\n"); + fprintf (stderr, "line1 outside block line pool: %p %p %p\n", + line1, block->mem, block); return 0; } if (line2 < (memline_t *) block->mem || line2 >= (memline_t *) block) { - fprintf (stderr, "line2 outside block line pool\n"); + fprintf (stderr, "line2 outside block line pool: %p %p %p\n", + line2, block->mem, block); return 0; } if (line3 < (memline_t *) block->mem || line3 >= (memline_t *) block) { - fprintf (stderr, "line3 outside block line pool\n"); + fprintf (stderr, "line3 outside block line pool: %p %p %p\n", + line3, block->mem, block); return 0; } if (!((size_t) line1 & super->page_mask)) { @@ -531,12 +536,19 @@ main (void) { memsuper_t *super = new_memsuper (); int i; - +#if __WORDSIZE == 32 + if (sizeof (memsuper_t) != 1 * MEM_LINE_SIZE) { + fprintf (stderr, "memsuper_t not 2 * cache size: %zd\n", + sizeof (memsuper_t)); + return 1; + } +#else if (sizeof (memsuper_t) != 2 * MEM_LINE_SIZE) { fprintf (stderr, "memsuper_t not 2 * cache size: %zd\n", sizeof (memsuper_t)); return 1; } +#endif if (sizeof (memline_t) != MEM_LINE_SIZE) { fprintf (stderr, "memline_t not cache size: %zd\n", sizeof (memline_t)); @@ -558,7 +570,7 @@ main (void) } if (super->page_size != (size_t) sysconf (_SC_PAGESIZE)) { fprintf (stderr, "page size not equal to system page size: %zd, %zd\n", - super->page_size, sysconf (_SC_PAGESIZE)); + super->page_size, (size_t) sysconf (_SC_PAGESIZE)); return 1; } if (!super->page_size || (super->page_size & (super->page_size - 1))) { From 778c07e91fb975645116a0e10829722a55459f62 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 May 2021 15:02:18 +0900 Subject: [PATCH 1539/3664] [util] Get vectors working for non-SSE archs GCC does a fairly nice job of producing code for vector types when the hardware doesn't support SIMD, but it seems to break certain math optimization rules due to excess precision (?). Still, it works well enough for the core engine, but may not be well suited to the tools. However, so far, only qfvis uses vector types (and it's not tested yet), and tools should probably be used on suitable machines anyway (not forces, of course). --- config.d/compiling.m4 | 5 +- include/QF/simd/types.h | 30 +++ include/QF/simd/vec4d.h | 3 + include/QF/simd/vec4f.h | 61 +++++ libs/util/test/test-simd.c | 488 ++++++++++++++++++---------------- tools/qfvis/source/base-vis.c | 7 + tools/qfvis/source/qfvis.c | 13 + 7 files changed, 383 insertions(+), 224 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index b432c1709..9f8dcf1e0 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -81,7 +81,10 @@ AC_ARG_ENABLE(optimize, optimize=yes ) -QF_CC_OPTION(-mavx2) +QF_CC_OPTION(-Wno-psabi) +dnl QF_CC_OPTION(-msse2) +dnl QF_CC_OPTION(-Wno-psabi) +dnl QF_CC_OPTION(-mavx2) dnl fma is not used as it is the equivalent of turning on dnl -funsafe-math-optimizations dnl QF_CC_OPTION(-mfma) diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index c5499f5bb..bfe484ace 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -79,7 +79,11 @@ VEC_TYPE (float, vec4f_t); VEC_TYPE (int, vec4i_t); #define VEC4D_FMT "[%.17g, %.17g, %.17g, %.17g]" +#if __WORDSIZE == 64 #define VEC4L_FMT "[%ld, %ld, %ld, %ld]" +#else +#define VEC4L_FMT "[%lld, %lld, %lld, %lld]" +#endif #define VEC4F_FMT "[%.9g, %.9g, %.9g, %.9g]" #define VEC4I_FMT "[%d, %d, %d, %d]" #define VEC4_EXP(v) (v)[0], (v)[1], (v)[2], (v)[3] @@ -94,4 +98,30 @@ typedef struct vspheref_s { float radius; } vspheref_t; +#include +#ifndef __SSE__ +#define _mm_xor_ps __qf_mm_xor_ps +#define _mm_and_ps __qf_mm_and_ps +GNU89INLINE inline __m128 _mm_xor_ps (__m128 a, __m128 b); +GNU89INLINE inline __m128 _mm_and_ps (__m128 a, __m128 b); +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +__m128 _mm_xor_ps (__m128 a, __m128 b) +{ + return (__m128) ((vec4i_t) a ^ (vec4i_t) b); +} +#ifndef IMPLEMENT_MAT4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +__m128 _mm_and_ps (__m128 a, __m128 b) +{ + return (__m128) ((vec4i_t) a & (vec4i_t) b); +} +#endif + #endif//__QF_simd_types_h diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 01fa42d88..f1c6d6a49 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -28,6 +28,7 @@ #ifndef __QF_simd_vec4d_h #define __QF_simd_vec4d_h +#ifdef __AVX__ #include #include "QF/simd/types.h" @@ -292,4 +293,6 @@ storevec3d (double v3[3], vec4d_t v4) v3[2] = v4[2]; } +#endif + #endif//__QF_simd_vec4d_h diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 82addbfaf..07498d706 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -110,7 +110,11 @@ vabsf (vec4f_t v) { const uint32_t nan = ~0u >> 1; const vec4i_t abs = { nan, nan, nan, nan }; +#ifndef __SSE__ + return (vec4f_t) ((vec4i_t) v & abs); +#else return _mm_and_ps (v, (__m128) abs); +#endif } #ifndef IMPLEMENT_VEC4F_Funcs @@ -121,7 +125,12 @@ VISIBLE vec4f_t vsqrtf (vec4f_t v) { +#ifndef __SSE__ + vec4f_t r = { sqrtf (v[0]), sqrtf (v[1]), sqrtf (v[2]), sqrtf (v[3]) }; + return r; +#else return _mm_sqrt_ps (v); +#endif } #ifndef IMPLEMENT_VEC4F_Funcs @@ -132,7 +141,16 @@ VISIBLE vec4f_t vceilf (vec4f_t v) { +#ifndef __SSE4_1__ + return (vec4f_t) { + ceilf (v[0]), + ceilf (v[1]), + ceilf (v[2]), + ceilf (v[3]) + }; +#else return _mm_ceil_ps (v); +#endif } #ifndef IMPLEMENT_VEC4F_Funcs @@ -143,7 +161,16 @@ VISIBLE vec4f_t vfloorf (vec4f_t v) { +#ifndef __SSE4_1__ + return (vec4f_t) { + floorf (v[0]), + floorf (v[1]), + floorf (v[2]), + floorf (v[3]) + }; +#else return _mm_floor_ps (v); +#endif } #ifndef IMPLEMENT_VEC4F_Funcs @@ -154,7 +181,16 @@ VISIBLE vec4f_t vtruncf (vec4f_t v) { +#ifndef __SSE4_1__ + return (vec4f_t) { + truncf (v[0]), + truncf (v[1]), + truncf (v[2]), + truncf (v[3]) + }; +#else return _mm_round_ps (v, _MM_FROUND_TRUNC); +#endif } #ifndef IMPLEMENT_VEC4F_Funcs @@ -179,8 +215,13 @@ vec4f_t dotf (vec4f_t a, vec4f_t b) { vec4f_t c = a * b; +#ifndef __SSE3__ + float x = c[0] + c[1] + c[2] + c[3]; + c = (vec4f_t) { x, x, x, x }; +#else c = _mm_hadd_ps (c, c); c = _mm_hadd_ps (c, c); +#endif return c; } @@ -197,7 +238,11 @@ qmulf (vec4f_t a, vec4f_t b) vec4f_t c = crossf (a, b) + a * b[3] + a[3] * b; vec4f_t d = dotf (a, b); // zero out the vector component of dot product so only the scalar remains +#ifndef __SSE4_1__ + d = (vec4f_t) { 0, 0, 0, d[3] }; +#else d = _mm_insert_ps (d, d, 0xf7); +#endif return c - d; } @@ -212,7 +257,11 @@ qvmulf (vec4f_t q, vec4f_t v) float s = q[3]; // zero the scalar of the quaternion. Results in an extra operation, but // avoids adding precision issues. +#ifndef __SSE4_1__ + q[3] = 0; +#else q = _mm_insert_ps (q, q, 0xf8); +#endif vec4f_t c = crossf (q, v); vec4f_t qv = dotf (q, v); // q.w is 0 so v.w is irrelevant vec4f_t qq = dotf (q, q); @@ -231,7 +280,11 @@ vqmulf (vec4f_t v, vec4f_t q) float s = q[3]; // zero the scalar of the quaternion. Results in an extra operation, but // avoids adding precision issues. +#ifndef __SSE4_1__ + q[3] = 0; +#else q = _mm_insert_ps (q, q, 0xf8); +#endif vec4f_t c = crossf (q, v); vec4f_t qv = dotf (q, v); // q.w is 0 so v.w is irrelevant vec4f_t qq = dotf (q, q); @@ -266,7 +319,11 @@ vec4f_t qconjf (vec4f_t q) { const vec4i_t neg = { 1u << 31, 1u << 31, 1u << 31, 0 }; +#ifndef __SSE__ + return (vec4f_t) ((vec4i_t) q ^ neg); +#else return _mm_xor_ps (q, (__m128) neg); +#endif } #ifndef IMPLEMENT_VEC4F_Funcs @@ -299,6 +356,9 @@ loadvec3f (const float v3[3]) { vec4f_t v4; +#ifndef __SSE4_1__ + v4 = (vec4f_t) { v3[0], v3[1], v3[2], 0 }; +#else // this had to be in asm otherwise gcc thinks v4 is only partially // initialized, and gcc 10 does not use the zero flags when generating // the code, resulting in a memory access to load a 0 into v4[3] @@ -311,6 +371,7 @@ loadvec3f (const float v3[3]) " : "=v"(v4) : "m"(v3[0]), "m"(v3[1]), "m"(v3[2])); +#endif return v4; } diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index ebaab413f..ceb9ad7d4 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -48,15 +48,19 @@ #define s05 0.70710678118654757 +#ifdef __AVX__ typedef struct { + int line; vec4d_t (*op) (vec4d_t a, vec4d_t b); vec4d_t a; vec4d_t b; vec4d_t expect; vec4d_t ulp_errors; } vec4d_test_t; +#endif typedef struct { + int line; vec4f_t (*op) (vec4f_t a, vec4f_t b); vec4f_t a; vec4f_t b; @@ -65,6 +69,7 @@ typedef struct { } vec4f_test_t; typedef struct { + int line; void (*op) (mat4f_t c, const mat4f_t a, const mat4f_t b); mat4f_t a; mat4f_t b; @@ -73,6 +78,7 @@ typedef struct { } mat4f_test_t; typedef struct { + int line; vec4f_t (*op) (const mat4f_t a, vec4f_t b); mat4f_t a; vec4f_t b; @@ -81,12 +87,14 @@ typedef struct { } mv4f_test_t; typedef struct { + int line; void (*op) (mat4f_t m, vec4f_t q); vec4f_t q; mat4f_t expect; mat4f_t ulp_errors; } mq4f_test_t; +#ifdef __AVX__ static vec4d_t tvtruncd (vec4d_t v, vec4d_t ignore) { return vtruncd (v); @@ -106,6 +114,7 @@ static vec4d_t tqconjd (vec4d_t v, vec4d_t ignore) { return qconjd (v); } +#endif static vec4f_t tvtruncf (vec4f_t v, vec4f_t ignore) { @@ -147,290 +156,320 @@ static vec4f_t tmagnitude3f (vec4f_t v, vec4f_t ignore) return magnitude3f (v); } +#define T(t...) { __LINE__, t } + +#ifdef __AVX__ static vec4d_test_t vec4d_tests[] = { // 3D dot products - { dotd, right, right, one }, - { dotd, right, forward, zero }, - { dotd, right, up, zero }, - { dotd, forward, right, zero }, - { dotd, forward, forward, one }, - { dotd, forward, up, zero }, - { dotd, up, right, zero }, - { dotd, up, forward, zero }, - { dotd, up, up, one }, + T(dotd, right, right, one ), + T(dotd, right, forward, zero ), + T(dotd, right, up, zero ), + T(dotd, forward, right, zero ), + T(dotd, forward, forward, one ), + T(dotd, forward, up, zero ), + T(dotd, up, right, zero ), + T(dotd, up, forward, zero ), + T(dotd, up, up, one ), // one is 4D, so its self dot product is 4 - { dotd, one, one, { 4, 4, 4, 4} }, - { dotd, one, none, {-4, -4, -4, -4} }, + T(dotd, one, one, { 4, 4, 4, 4} ), + T(dotd, one, none, {-4, -4, -4, -4} ), // 3D cross products - { crossd, right, right, zero }, - { crossd, right, forward, up }, - { crossd, right, up, nforward }, - { crossd, forward, right, nup }, - { crossd, forward, forward, zero }, - { crossd, forward, up, right }, - { crossd, up, right, forward }, - { crossd, up, forward, nright }, - { crossd, up, up, zero }, + T(crossd, right, right, zero ), + T(crossd, right, forward, up ), + T(crossd, right, up, nforward ), + T(crossd, forward, right, nup ), + T(crossd, forward, forward, zero ), + T(crossd, forward, up, right ), + T(crossd, up, right, forward ), + T(crossd, up, forward, nright ), + T(crossd, up, up, zero ), // double whammy tests: cross product with an angled vector and // ensuring that a 4d vector (non-zero w component) does not affect // the result, including the result's w component remaining zero. - { crossd, right, one, { 0, -1, 1} }, - { crossd, forward, one, { 1, 0, -1} }, - { crossd, up, one, {-1, 1, 0} }, - { crossd, one, right, { 0, 1, -1} }, - { crossd, one, forward, {-1, 0, 1} }, - { crossd, one, up, { 1, -1, 0} }, + T(crossd, right, one, { 0, -1, 1} ), + T(crossd, forward, one, { 1, 0, -1} ), + T(crossd, up, one, {-1, 1, 0} ), + T(crossd, one, right, { 0, 1, -1} ), + T(crossd, one, forward, {-1, 0, 1} ), + T(crossd, one, up, { 1, -1, 0} ), // This one fails when optimizing with -mfma (which is why fma is not // used): ulp errors in z and w - { crossd, qtest, qtest, {0, 0, 0, 0} }, + T(crossd, qtest, qtest, {0, 0, 0, 0} ), - { qmuld, qident, qident, qident }, - { qmuld, qident, right, right }, - { qmuld, qident, forward, forward }, - { qmuld, qident, up, up }, - { qmuld, right, qident, right }, - { qmuld, forward, qident, forward }, - { qmuld, up, qident, up }, - { qmuld, right, right, nqident }, - { qmuld, right, forward, up }, - { qmuld, right, up, nforward }, - { qmuld, forward, right, nup }, - { qmuld, forward, forward, nqident }, - { qmuld, forward, up, right }, - { qmuld, up, right, forward }, - { qmuld, up, forward, nright }, - { qmuld, up, up, nqident }, - { qmuld, one, one, { 2, 2, 2, -2 } }, - { qmuld, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } }, + T(qmuld, qident, qident, qident ), + T(qmuld, qident, right, right ), + T(qmuld, qident, forward, forward ), + T(qmuld, qident, up, up ), + T(qmuld, right, qident, right ), + T(qmuld, forward, qident, forward ), + T(qmuld, up, qident, up ), + T(qmuld, right, right, nqident ), + T(qmuld, right, forward, up ), + T(qmuld, right, up, nforward ), + T(qmuld, forward, right, nup ), + T(qmuld, forward, forward, nqident ), + T(qmuld, forward, up, right ), + T(qmuld, up, right, forward ), + T(qmuld, up, forward, nright ), + T(qmuld, up, up, nqident ), + T(qmuld, one, one, { 2, 2, 2, -2 } ), + T(qmuld, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } ), // This one fails when optimizing with -mfma (which is why fma is not // used): ulp error in z - { qmuld, qtest, qtest, {0.768, 0.576, 0, -0.28} }, + T(qmuld, qtest, qtest, {0.768, 0.576, 0, -0.28} ), // The one vector is not unit (magnitude 2), so using it as a rotation // quaternion results in scaling by 4. However, it still has the effect // of rotating 120 degrees around the axis equidistant from the three // orthogonal axes such that x->y->z->x - { qvmuld, one, right, { 0, 4, 0, 0 } }, - { qvmuld, one, forward, { 0, 0, 4, 0 } }, - { qvmuld, one, up, { 4, 0, 0, 0 } }, - { qvmuld, one, {1,1,1,0}, { 4, 4, 4, 0 } }, - { qvmuld, one, one, { 4, 4, 4, -2 } }, + T(qvmuld, one, right, { 0, 4, 0, 0 } ), + T(qvmuld, one, forward, { 0, 0, 4, 0 } ), + T(qvmuld, one, up, { 4, 0, 0, 0 } ), + T(qvmuld, one, {1,1,1,0}, { 4, 4, 4, 0 } ), + T(qvmuld, one, one, { 4, 4, 4, -2 } ), // inverse rotation, so x->z->y->x - { vqmuld, right, one, { 0, 0, 4, 0 } }, - { vqmuld, forward, one, { 4, 0, 0, 0 } }, - { vqmuld, up, one, { 0, 4, 0, 0 } }, - { vqmuld, {1,1,1,0}, one, { 4, 4, 4, 0 } }, - { vqmuld, one, one, { 4, 4, 4, -2 } }, + T(vqmuld, right, one, { 0, 0, 4, 0 } ), + T(vqmuld, forward, one, { 4, 0, 0, 0 } ), + T(vqmuld, up, one, { 0, 4, 0, 0 } ), + T(vqmuld, {1,1,1,0}, one, { 4, 4, 4, 0 } ), + T(vqmuld, one, one, { 4, 4, 4, -2 } ), // The half vector is unit. - { qvmuld, half, right, forward }, - { qvmuld, half, forward, up }, - { qvmuld, half, up, right }, - { qvmuld, half, {1,1,1,0}, { 1, 1, 1, 0 } }, + T(qvmuld, half, right, forward ), + T(qvmuld, half, forward, up ), + T(qvmuld, half, up, right ), + T(qvmuld, half, {1,1,1,0}, { 1, 1, 1, 0 } ), // inverse - { vqmuld, right, half, up }, - { vqmuld, forward, half, right }, - { vqmuld, up, half, forward }, - { vqmuld, {1,1,1,0}, half, { 1, 1, 1, 0 } }, + T(vqmuld, right, half, up ), + T(vqmuld, forward, half, right ), + T(vqmuld, up, half, forward ), + T(vqmuld, {1,1,1,0}, half, { 1, 1, 1, 0 } ), // one is a 4D vector and qvmuld is meant for 3D vectors. However, it // seems that the vector's w has no effect on the 3d portion of the // result, but the result's w is cosine of the full rotation angle // scaled by quaternion magnitude and vector w - { qvmuld, half, one, { 1, 1, 1, -0.5 } }, - { qvmuld, half, {2,2,2,2}, { 2, 2, 2, -1 } }, - { qvmuld, qtest, right, {0.5392, 0.6144, -0.576, 0} }, - { qvmuld, qtest, forward, {0.6144, 0.1808, 0.768, 0}, - {0, -2.7e-17, 0, 0} }, - { qvmuld, qtest, up, {0.576, -0.768, -0.28, 0} }, + T(qvmuld, half, one, { 1, 1, 1, -0.5 } ), + T(qvmuld, half, {2,2,2,2}, { 2, 2, 2, -1 } ), + T(qvmuld, qtest, right, {0.5392, 0.6144, -0.576, 0} ), + T(qvmuld, qtest, forward, {0.6144, 0.1808, 0.768, 0}, + {0, -2.7e-17, 0, 0} ), + T(qvmuld, qtest, up, {0.576, -0.768, -0.28, 0} ), // inverse - { vqmuld, one, half, { 1, 1, 1, -0.5 } }, - { vqmuld, {2,2,2,2}, half, { 2, 2, 2, -1 } }, - { vqmuld, right, qtest, {0.5392, 0.6144, 0.576, 0} }, - { vqmuld, forward, qtest, {0.6144, 0.1808, -0.768, 0}, - {0, -2.7e-17, 0, 0} }, - { vqmuld, up, qtest, {-0.576, 0.768, -0.28, 0} }, + T(vqmuld, one, half, { 1, 1, 1, -0.5 } ), + T(vqmuld, {2,2,2,2}, half, { 2, 2, 2, -1 } ), + T(vqmuld, right, qtest, {0.5392, 0.6144, 0.576, 0} ), + T(vqmuld, forward, qtest, {0.6144, 0.1808, -0.768, 0}, + {0, -2.7e-17, 0, 0} ), + T(vqmuld, up, qtest, {-0.576, 0.768, -0.28, 0} ), - { qrotd, right, right, qident }, - { qrotd, right, forward, { 0, 0, s05, s05 }, - {0, 0, -1.1e-16, 0} }, - { qrotd, right, up, { 0, -s05, 0, s05 }, - {0, 1.1e-16, 0, 0} }, - { qrotd, forward, right, { 0, 0, -s05, s05 }, - {0, 0, 1.1e-16, 0} }, - { qrotd, forward, forward, qident }, - { qrotd, forward, up, { s05, 0, 0, s05 }, - {-1.1e-16, 0, 0, 0} }, - { qrotd, up, right, { 0, s05, 0, s05 }, - {0, -1.1e-16, 0, 0} }, - { qrotd, up, forward, { -s05, 0, 0, s05 }, - { 1.1e-16, 0, 0, 0} }, - { qrotd, up, up, qident }, + T(qrotd, right, right, qident ), + T(qrotd, right, forward, { 0, 0, s05, s05 }, + {0, 0, -1.1e-16, 0} ), + T(qrotd, right, up, { 0, -s05, 0, s05 }, + {0, 1.1e-16, 0, 0} ), + T(qrotd, forward, right, { 0, 0, -s05, s05 }, + {0, 0, 1.1e-16, 0} ), + T(qrotd, forward, forward, qident ), + T(qrotd, forward, up, { s05, 0, 0, s05 }, + {-1.1e-16, 0, 0, 0} ), + T(qrotd, up, right, { 0, s05, 0, s05 }, + {0, -1.1e-16, 0, 0} ), + T(qrotd, up, forward, { -s05, 0, 0, s05 }, + { 1.1e-16, 0, 0, 0} ), + T(qrotd, up, up, qident ), - { tvtruncd, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -1, -2 } }, - { tvceild, { 1.1, 2.9, -1.1, -2.9 }, {}, { 2, 3, -1, -2 } }, - { tvfloord, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -2, -3 } }, - { tqconjd, one, {}, { -1, -1, -1, 1 } }, + T(tvtruncd, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -1, -2 } ), + T(tvceild, { 1.1, 2.9, -1.1, -2.9 }, {}, { 2, 3, -1, -2 } ), + T(tvfloord, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -2, -3 } ), + T(tqconjd, one, {}, { -1, -1, -1, 1 } ), }; #define num_vec4d_tests (sizeof (vec4d_tests) / (sizeof (vec4d_tests[0]))) +#endif static vec4f_test_t vec4f_tests[] = { // 3D dot products - { dotf, right, right, one }, - { dotf, right, forward, zero }, - { dotf, right, up, zero }, - { dotf, forward, right, zero }, - { dotf, forward, forward, one }, - { dotf, forward, up, zero }, - { dotf, up, right, zero }, - { dotf, up, forward, zero }, - { dotf, up, up, one }, + T(dotf, right, right, one ), + T(dotf, right, forward, zero ), + T(dotf, right, up, zero ), + T(dotf, forward, right, zero ), + T(dotf, forward, forward, one ), + T(dotf, forward, up, zero ), + T(dotf, up, right, zero ), + T(dotf, up, forward, zero ), + T(dotf, up, up, one ), // one is 4D, so its self dot product is 4 - { dotf, one, one, { 4, 4, 4, 4} }, - { dotf, one, none, {-4, -4, -4, -4} }, + T(dotf, one, one, { 4, 4, 4, 4} ), + T(dotf, one, none, {-4, -4, -4, -4} ), // 3D cross products - { crossf, right, right, zero }, - { crossf, right, forward, up }, - { crossf, right, up, nforward }, - { crossf, forward, right, nup }, - { crossf, forward, forward, zero }, - { crossf, forward, up, right }, - { crossf, up, right, forward }, - { crossf, up, forward, nright }, - { crossf, up, up, zero }, + T(crossf, right, right, zero ), + T(crossf, right, forward, up ), + T(crossf, right, up, nforward ), + T(crossf, forward, right, nup ), + T(crossf, forward, forward, zero ), + T(crossf, forward, up, right ), + T(crossf, up, right, forward ), + T(crossf, up, forward, nright ), + T(crossf, up, up, zero ), // double whammy tests: cross product with an angled vector and // ensuring that a 4d vector (non-zero w component) does not affect // the result, including the result's w component remaining zero. - { crossf, right, one, { 0, -1, 1} }, - { crossf, forward, one, { 1, 0, -1} }, - { crossf, up, one, {-1, 1, 0} }, - { crossf, one, right, { 0, 1, -1} }, - { crossf, one, forward, {-1, 0, 1} }, - { crossf, one, up, { 1, -1, 0} }, - { crossf, qtest, qtest, {0, 0, 0, 0} }, + T(crossf, right, one, { 0, -1, 1} ), + T(crossf, forward, one, { 1, 0, -1} ), + T(crossf, up, one, {-1, 1, 0} ), + T(crossf, one, right, { 0, 1, -1} ), + T(crossf, one, forward, {-1, 0, 1} ), + T(crossf, one, up, { 1, -1, 0} ), + T(crossf, qtest, qtest, {0, 0, 0, 0} ), - { qmulf, qident, qident, qident }, - { qmulf, qident, right, right }, - { qmulf, qident, forward, forward }, - { qmulf, qident, up, up }, - { qmulf, right, qident, right }, - { qmulf, forward, qident, forward }, - { qmulf, up, qident, up }, - { qmulf, right, right, nqident }, - { qmulf, right, forward, up }, - { qmulf, right, up, nforward }, - { qmulf, forward, right, nup }, - { qmulf, forward, forward, nqident }, - { qmulf, forward, up, right }, - { qmulf, up, right, forward }, - { qmulf, up, forward, nright }, - { qmulf, up, up, nqident }, - { qmulf, one, one, { 2, 2, 2, -2 } }, - { qmulf, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } }, - { qmulf, qtest, qtest, {0.768, 0.576, 0, -0.28}, - {0, 6e-8, 0, 3e-8} }, + T(qmulf, qident, qident, qident ), + T(qmulf, qident, right, right ), + T(qmulf, qident, forward, forward ), + T(qmulf, qident, up, up ), + T(qmulf, right, qident, right ), + T(qmulf, forward, qident, forward ), + T(qmulf, up, qident, up ), + T(qmulf, right, right, nqident ), + T(qmulf, right, forward, up ), + T(qmulf, right, up, nforward ), + T(qmulf, forward, right, nup ), + T(qmulf, forward, forward, nqident ), + T(qmulf, forward, up, right ), + T(qmulf, up, right, forward ), + T(qmulf, up, forward, nright ), + T(qmulf, up, up, nqident ), + T(qmulf, one, one, { 2, 2, 2, -2 } ), + T(qmulf, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } ), + T(qmulf, qtest, qtest, {0.768, 0.576, 0, -0.28}, +#ifndef __SSE__ + {0, 6e-8, 0, 6e-8} +#else + {0, 6e-8, 0, 3e-8} +#endif + ), // The one vector is not unit (magnitude 2), so using it as a rotation // quaternion results in scaling by 4. However, it still has the effect // of rotating 120 degrees around the axis equidistant from the three // orthogonal axes such that x->y->z->x - { qvmulf, one, right, { 0, 4, 0, 0 } }, - { qvmulf, one, forward, { 0, 0, 4, 0 } }, - { qvmulf, one, up, { 4, 0, 0, 0 } }, - { qvmulf, one, {1,1,1,0}, { 4, 4, 4, 0 } }, - { qvmulf, one, one, { 4, 4, 4, -2 } }, + T(qvmulf, one, right, { 0, 4, 0, 0 } ), + T(qvmulf, one, forward, { 0, 0, 4, 0 } ), + T(qvmulf, one, up, { 4, 0, 0, 0 } ), + T(qvmulf, one, {1,1,1,0}, { 4, 4, 4, 0 } ), + T(qvmulf, one, one, { 4, 4, 4, -2 } ), // inverse rotation, so x->z->y->x - { vqmulf, right, one, { 0, 0, 4, 0 } }, - { vqmulf, forward, one, { 4, 0, 0, 0 } }, - { vqmulf, up, one, { 0, 4, 0, 0 } }, - { vqmulf, {1,1,1,0}, one, { 4, 4, 4, 0 } }, - { vqmulf, one, one, { 4, 4, 4, -2 } }, + T(vqmulf, right, one, { 0, 0, 4, 0 } ), + T(vqmulf, forward, one, { 4, 0, 0, 0 } ), + T(vqmulf, up, one, { 0, 4, 0, 0 } ), + T(vqmulf, {1,1,1,0}, one, { 4, 4, 4, 0 } ), + T(vqmulf, one, one, { 4, 4, 4, -2 } ), // - { qvmulf, qtest, right, {0.5392, 0.6144, -0.576, 0}, - {0, -5.9e-8, -6e-8, 0} }, - { qvmulf, qtest, forward, {0.6144, 0.1808, 0.768, 0}, - {-5.9e-8, 1.5e-8, 0, 0} }, - { qvmulf, qtest, up, {0.576, -0.768, -0.28, 0}, - {6e-8, 0, 3e-8, 0} }, - { vqmulf, right, qtest, {0.5392, 0.6144, 0.576, 0}, - {0, -5.9e-8, 5.9e-8, 0} }, - { vqmulf, forward, qtest, {0.6144, 0.1808, -0.768, 0}, - {-5.9e-8, 1.5e-8, 0, 0} }, - { vqmulf, up, qtest, {-0.576, 0.768, -0.28, 0}, - {-5.9e-8, 0, 3e-8, 0} }, + T(qvmulf, qtest, right, {0.5392, 0.6144, -0.576, 0}, + {0, -5.9e-8, -6e-8, 0} ), + T(qvmulf, qtest, forward, {0.6144, 0.1808, 0.768, 0}, +#ifndef __SSE__ + {-5.9e-8, 3e-8, 0, 0} +#else + {-5.9e-8, 1.5e-8, 0, 0} +#endif + ), + T(qvmulf, qtest, up, {0.576, -0.768, -0.28, 0}, +#ifndef __SSE__ + {6e-8, 0, 6e-8, 0} +#else + {6e-8, 0, 3e-8, 0} +#endif + ), + T(vqmulf, right, qtest, {0.5392, 0.6144, 0.576, 0}, + {0, -5.9e-8, 5.9e-8, 0} ), + T(vqmulf, forward, qtest, {0.6144, 0.1808, -0.768, 0}, +#ifndef __SSE__ + {-5.9e-8, 3e-8, 0, 0} +#else + {-5.9e-8, 1.5e-8, 0, 0} +#endif + ), + T(vqmulf, up, qtest, {-0.576, 0.768, -0.28, 0}, +#ifndef __SSE__ + {-5.9e-8, 0, 6e-8, 0} +#else + {-5.9e-8, 0, 3e-8, 0} +#endif + ), - { qrotf, right, right, qident }, - { qrotf, right, forward, { 0, 0, s05, s05 } }, - { qrotf, right, up, { 0, -s05, 0, s05 } }, - { qrotf, forward, right, { 0, 0, -s05, s05 } }, - { qrotf, forward, forward, qident }, - { qrotf, forward, up, { s05, 0, 0, s05 } }, - { qrotf, up, right, { 0, s05, 0, s05 } }, - { qrotf, up, forward, { -s05, 0, 0, s05 } }, - { qrotf, up, up, qident }, + T(qrotf, right, right, qident ), + T(qrotf, right, forward, { 0, 0, s05, s05 } ), + T(qrotf, right, up, { 0, -s05, 0, s05 } ), + T(qrotf, forward, right, { 0, 0, -s05, s05 } ), + T(qrotf, forward, forward, qident ), + T(qrotf, forward, up, { s05, 0, 0, s05 } ), + T(qrotf, up, right, { 0, s05, 0, s05 } ), + T(qrotf, up, forward, { -s05, 0, 0, s05 } ), + T(qrotf, up, up, qident ), - { tvabsf, pmpi, {}, pi }, - { tvsqrtf, { 1, 4, 9, 16}, {}, {1, 2, 3, 4} }, - { tvtruncf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -1, -2 } }, - { tvceilf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 2, 3, -1, -2 } }, - { tvfloorf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -2, -3 } }, - { tqconjf, one, {}, { -1, -1, -1, 1 } }, - { tmagnitudef, { 3, 4, 12, 84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { 3, 4, 12, -84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { 3, 4, -12, 84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { 3, 4, -12, -84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { 3, -4, 12, 84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { 3, -4, 12, -84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { 3, -4, -12, 84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { 3, -4, -12, -84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { -3, 4, 12, 84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { -3, 4, 12, -84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { -3, 4, -12, 84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { -3, 4, -12, -84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { -3, -4, 12, 84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { -3, -4, 12, -84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { -3, -4, -12, 84}, {}, {85, 85, 85, 85} }, - { tmagnitudef, { -3, -4, -12, -84}, {}, {85, 85, 85, 85} }, - { tmagnitude3f, { -3, -4, -12, -84}, {}, {13, 13, 13, 13} }, + T(tvabsf, pmpi, {}, pi ), + T(tvsqrtf, { 1, 4, 9, 16}, {}, {1, 2, 3, 4} ), + T(tvtruncf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -1, -2 } ), + T(tvceilf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 2, 3, -1, -2 } ), + T(tvfloorf, { 1.1, 2.9, -1.1, -2.9 }, {}, { 1, 2, -2, -3 } ), + T(tqconjf, one, {}, { -1, -1, -1, 1 } ), + T(tmagnitudef, { 3, 4, 12, 84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { 3, 4, 12, -84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { 3, 4, -12, 84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { 3, 4, -12, -84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { 3, -4, 12, 84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { 3, -4, 12, -84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { 3, -4, -12, 84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { 3, -4, -12, -84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { -3, 4, 12, 84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { -3, 4, 12, -84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { -3, 4, -12, 84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { -3, 4, -12, -84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { -3, -4, 12, 84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { -3, -4, 12, -84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { -3, -4, -12, 84}, {}, {85, 85, 85, 85} ), + T(tmagnitudef, { -3, -4, -12, -84}, {}, {85, 85, 85, 85} ), + T(tmagnitude3f, { -3, -4, -12, -84}, {}, {13, 13, 13, 13} ), }; #define num_vec4f_tests (sizeof (vec4f_tests) / (sizeof (vec4f_tests[0]))) static mat4f_test_t mat4f_tests[] = { - { mmulf, identity, identity, identity }, - { mmulf, rotate120, identity, rotate120 }, - { mmulf, identity, rotate120, rotate120 }, - { mmulf, rotate120, rotate120, rotate240 }, - { mmulf, rotate120, rotate240, identity }, - { mmulf, rotate240, rotate120, identity }, + T(mmulf, identity, identity, identity ), + T(mmulf, rotate120, identity, rotate120 ), + T(mmulf, identity, rotate120, rotate120 ), + T(mmulf, rotate120, rotate120, rotate240 ), + T(mmulf, rotate120, rotate240, identity ), + T(mmulf, rotate240, rotate120, identity ), }; #define num_mat4f_tests (sizeof (mat4f_tests) / (sizeof (mat4f_tests[0]))) static mv4f_test_t mv4f_tests[] = { - { mvmulf, identity, { 1, 0, 0, 0 }, { 1, 0, 0, 0 } }, - { mvmulf, identity, { 0, 1, 0, 0 }, { 0, 1, 0, 0 } }, - { mvmulf, identity, { 0, 0, 1, 0 }, { 0, 0, 1, 0 } }, - { mvmulf, identity, { 0, 0, 0, 1 }, { 0, 0, 0, 1 } }, - { mvmulf, rotate120, { 1, 2, 3, 4 }, { 3, 1, 2, 4 } }, - { mvmulf, rotate240, { 1, 2, 3, 4 }, { 2, 3, 1, 4 } }, + T(mvmulf, identity, { 1, 0, 0, 0 }, { 1, 0, 0, 0 } ), + T(mvmulf, identity, { 0, 1, 0, 0 }, { 0, 1, 0, 0 } ), + T(mvmulf, identity, { 0, 0, 1, 0 }, { 0, 0, 1, 0 } ), + T(mvmulf, identity, { 0, 0, 0, 1 }, { 0, 0, 0, 1 } ), + T(mvmulf, rotate120, { 1, 2, 3, 4 }, { 3, 1, 2, 4 } ), + T(mvmulf, rotate240, { 1, 2, 3, 4 }, { 2, 3, 1, 4 } ), }; #define num_mv4f_tests (sizeof (mv4f_tests) / (sizeof (mv4f_tests[0]))) // expect filled in using non-simd QuatToMatrix (has its own tests) static mq4f_test_t mq4f_tests[] = { - { mat4fquat, { 0, 0, 0, 1 } }, - { mat4fquat, { 0.5, 0.5, 0.5, 0.5 } }, - { mat4fquat, { 0.5, 0.5, -0.5, 0.5 } }, - { mat4fquat, { 0.5, -0.5, 0.5, 0.5 } }, - { mat4fquat, { 0.5, -0.5, -0.5, 0.5 } }, - { mat4fquat, { -0.5, 0.5, 0.5, 0.5 } }, - { mat4fquat, { -0.5, 0.5, -0.5, 0.5 } }, - { mat4fquat, { -0.5, -0.5, 0.5, 0.5 } }, - { mat4fquat, { -0.5, -0.5, -0.5, 0.5 } }, + T(mat4fquat, { 0, 0, 0, 1 } ), + T(mat4fquat, { 0.5, 0.5, 0.5, 0.5 } ), + T(mat4fquat, { 0.5, 0.5, -0.5, 0.5 } ), + T(mat4fquat, { 0.5, -0.5, 0.5, 0.5 } ), + T(mat4fquat, { 0.5, -0.5, -0.5, 0.5 } ), + T(mat4fquat, { -0.5, 0.5, 0.5, 0.5 } ), + T(mat4fquat, { -0.5, 0.5, -0.5, 0.5 } ), + T(mat4fquat, { -0.5, -0.5, 0.5, 0.5 } ), + T(mat4fquat, { -0.5, -0.5, -0.5, 0.5 } ), }; #define num_mq4f_tests (sizeof (mq4f_tests) / (sizeof (mq4f_tests[0]))) +#ifdef __AVX__ static int run_vec4d_tests (void) { @@ -443,7 +482,7 @@ run_vec4d_tests (void) vec4l_t res = result != expect; if (res[0] || res[1] || res[2] || res[3]) { ret |= 1; - printf ("\nrun_vec4d_tests %zd\n", i); + printf ("\nrun_vec4d_tests %zd, line %d\n", i, test->line); printf ("a: " VEC4D_FMT "\n", VEC4_EXP(test->a)); printf ("b: " VEC4D_FMT "\n", VEC4_EXP(test->b)); printf ("r: " VEC4D_FMT "\n", VEC4_EXP(result)); @@ -455,6 +494,7 @@ run_vec4d_tests (void) } return ret; } +#endif static int run_vec4f_tests (void) @@ -465,10 +505,10 @@ run_vec4f_tests (void) __auto_type test = &vec4f_tests[i]; vec4f_t result = test->op (test->a, test->b); vec4f_t expect = test->expect + test->ulp_errors; - vec4i_t res = result != expect; + vec4i_t res = (vec4i_t) result != (vec4i_t) expect; if (res[0] || res[1] || res[2] || res[3]) { ret |= 1; - printf ("\nrun_vec4f_tests %zd\n", i); + printf ("\nrun_vec4f_tests %zd, line %d\n", i, test->line); printf ("a: " VEC4F_FMT "\n", VEC4_EXP(test->a)); printf ("b: " VEC4F_FMT "\n", VEC4_EXP(test->b)); printf ("r: " VEC4F_FMT "\n", VEC4_EXP(result)); @@ -502,7 +542,7 @@ run_mat4f_tests (void) } if (fail) { ret |= 1; - printf ("\nrun_mat4f_tests %zd\n", i); + printf ("\nrun_mat4f_tests %zd, line %d\n", i, test->line); printf ("a: " VEC4F_FMT "\n", MAT4_ROW(test->a, 0)); printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 1)); printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 2)); @@ -549,7 +589,7 @@ run_mv4f_tests (void) if (res[0] || res[1] || res[2] || res[3]) { ret |= 1; - printf ("\nrun_mv4f_tests %zd\n", i); + printf ("\nrun_mv4f_tests %zd, line %d\n", i, test->line); printf ("a: " VEC4F_FMT "\n", MAT4_ROW(test->a, 0)); printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 1)); printf (" " VEC4F_FMT "\n", MAT4_ROW(test->a, 2)); @@ -595,7 +635,7 @@ run_mq4f_tests (void) } if (fail) { ret |= 1; - printf ("\nrun_mq4f_tests %zd\n", i); + printf ("\nrun_mq4f_tests %zd, line %d\n", i, test->line); printf ("q: " VEC4F_FMT "\n", VEC4_EXP(test->q)); printf ("r: " VEC4F_FMT "\n", MAT4_ROW(result, 0)); printf (" " VEC4F_FMT "\n", MAT4_ROW(result, 1)); @@ -626,7 +666,9 @@ int main (void) { int ret = 0; +#ifdef __AVX__ ret |= run_vec4d_tests (); +#endif ret |= run_vec4f_tests (); ret |= run_mat4f_tests (); ret |= run_mv4f_tests (); diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index 089b196f9..877f3f97d 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -86,6 +86,7 @@ SimpleFlood (basethread_t *thread, portal_t *srcportal, int clusternum) static inline int test_sphere (const vspheref_t *sphere, vec4f_t plane) { +#ifdef __SSE3__ const vec4f_t zero = {}; float r = sphere->radius; vec4f_t eps = { r, r, r, r }; @@ -94,6 +95,12 @@ test_sphere (const vspheref_t *sphere, vec4f_t plane) c = (vec4i_t) _mm_hsub_epi32 ((__m128i) c, (__m128i) c); return c[0]; +#else + float d = DotProduct (sphere->center, plane) + plane[3]; + int front = (d >= sphere->radius); + int back = (d <= -sphere->radius); + return front - back; +#endif } void diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index a1dc5ce33..156d1650f 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -214,12 +214,20 @@ NewFlippedWinding (threaddata_t *thread, const winding_t *w) static vec4i_t signeps (vec4f_t dist) { +#ifdef __SSE3__ const vec4f_t zero = {}; const vec4f_t eps = { ON_EPSILON, ON_EPSILON, ON_EPSILON, ON_EPSILON }; vec4f_t d = _mm_addsub_ps (zero, dist); vec4i_t c = (d - eps) > 0; c = (vec4i_t) _mm_hsub_epi32 ((__m128i) c, (__m128i) c); return c; +#else + float d = dist[0]; + int front = (d >= ON_EPSILON); + int back = (d <= -ON_EPSILON); + int i = front - back; + return (vec4i_t) { i, i, i, i }; +#endif } static vec4f_t @@ -246,7 +254,12 @@ split_edge (const vec4f_t *points, const vec4f_t *dists, vec4i_t x = _mm_and_ps (split, (__m128) nan) == onenan; // plane vector has -dist in w vec4f_t y = _mm_and_ps (split, (__m128) x) * -split[3]; +#ifdef __SSE3__ mid = _mm_blendv_ps (mid, y, (__m128) x); +#else + mid = (vec4f_t) ((vec4i_t) _mm_and_ps (y, (__m128) x) | + (vec4i_t) _mm_and_ps (mid, (__m128) ~x)); +#endif if (isnan (mid[0])) *(int *) 0 = 0; return mid; } From 85087177bf91b3d79dd0e53588530764d31c6bb8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 May 2021 15:09:41 +0900 Subject: [PATCH 1540/3664] [vulkan] Conditionalize build of vkgen vkgen cannot be built if vulkan headers are unavailable. --- .../video/renderer/vulkan/vkgen/Makemodule.am | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index f28252f7f..0b4f3b2ec 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -1,5 +1,7 @@ -vkgen = libs/video/renderer/vulkan/vkgen.dat$(EXEEXT) -noinst_PROGRAMS += $(vkgen) +vkgen = vkgen.dat$(EXEEXT) +noinst_PROGRAMS += @VKGEN_TARGETS@ + +EXTRA_PROGRAMS += vkgen.dat$(EXEEXT) vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkalias.r \ @@ -19,13 +21,13 @@ vkgen_dat_src= \ VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen -libs_video_renderer_vulkan_vkgen_dat_SOURCES=$(vkgen_dat_src) -libs_video_renderer_vkgen_obj=$(libs_video_renderer_vulkan_vkgen_dat_SOURCES:.r=.o) -libs_video_renderer_vkgen_dep=$(call qcautodep,$(libs_video_renderer_vulkan_vkgen_dat_SOURCES:.o=.Qo)) -libs/video/renderer/vulkan/vkgen.dat$(EXEEXT): $(libs_video_renderer_vkgen_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(V_QFCCLD)$(QLINK) -o $@ $(libs_video_renderer_vkgen_obj) -lcsqc -lr -include $(libs_video_renderer_vkgen_dep) # am--include-marker -r_depfiles_remade += $(libs_video_renderer_vkgen_dep) +vkgen_dat_SOURCES=$(vkgen_dat_src) +vkgen_obj=$(vkgen_dat_SOURCES:.r=.o) +vkgen_dep=$(call qcautodep,$(vkgen_dat_SOURCES:.o=.Qo)) +libs/video/renderer/vulkan/vkgen.dat$(EXEEXT): $(vkgen_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(vkgen_obj) -lcsqc -lr +include $(vkgen_dep) # am--include-marker +r_depfiles_remade += $(vkgen_dep) libs/video/renderer/vulkan/vkgen/vkgen.o: $(top_srcdir)/libs/video/renderer/vulkan/vkgen/vkgen.r $(V_QFCC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ From c5f2aca07d47bbf5a563d4b2ef96e042173145b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 May 2021 16:26:12 +0900 Subject: [PATCH 1541/3664] [vulkan] Conditionalize vulkan tests --- config.d/vulkan.m4 | 1 + libs/video/renderer/vulkan/test/Makemodule.am | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index 85ed9d3f0..a13da8f78 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -20,3 +20,4 @@ AC_SUBST(GLSLANGVALIDATOR, [$glslangvalidator]) AM_CONDITIONAL(X11_VULKAN, test "x$HAVE_VULKAN" = "xyes") AM_CONDITIONAL(WIN_VULKAN, test "x$HAVE_VULKAN" = "xyes") +AM_CONDITIONAL(TEST_VULKAN, test "x$HAVE_VULKAN" = "xyes") diff --git a/libs/video/renderer/vulkan/test/Makemodule.am b/libs/video/renderer/vulkan/test/Makemodule.am index f46249d31..8d4f8f77a 100644 --- a/libs/video/renderer/vulkan/test/Makemodule.am +++ b/libs/video/renderer/vulkan/test/Makemodule.am @@ -1,9 +1,12 @@ libs_video_renderer_vulkan_tests = \ libs/video/renderer/vulkan/test/test-staging +if TEST_VULKAN TESTS += $(libs_video_renderer_vulkan_tests) - check_PROGRAMS += $(libs_video_renderer_vulkan_tests) +endif + +EXTRA_PROGRAMS += $(libs_video_renderer_vulkan_tests) libs_video_renderer_vulkan_test_libs= \ libs/video/renderer/librender_vulkan.la \ From ef9b04ba83b7871a0be7da926be7a0e7e89ba0ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 May 2021 12:28:45 +0900 Subject: [PATCH 1542/3664] [util] Get tests working with sse2 It seems that i686 code generation is all over the place reguarding sse2 vs fp, with the resulting differences in carried precision. I'm not sure I'm happy with the situation, but at least it's being tested to a certain extent. Not sure if this broke basic (no sse) i686 tests. --- config.d/compiling.m4 | 13 +++++++------ libs/util/mathlib.c | 7 ++++--- libs/util/simd.c | 8 ++++---- libs/util/test/test-bary.c | 4 ++-- libs/util/test/test-baryvf.c | 4 ++-- libs/util/test/test-cexpr.c | 12 ++++++------ libs/util/test/test-quat.c | 32 +++++++++++++++++++++++++++++++- 7 files changed, 56 insertions(+), 24 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 9f8dcf1e0..5985d895c 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -81,8 +81,8 @@ AC_ARG_ENABLE(optimize, optimize=yes ) -QF_CC_OPTION(-Wno-psabi) -dnl QF_CC_OPTION(-msse2) +dnl QF_CC_OPTION(-Wno-psabi) +QF_CC_OPTION(-msse2) dnl QF_CC_OPTION(-Wno-psabi) dnl QF_CC_OPTION(-mavx2) dnl fma is not used as it is the equivalent of turning on @@ -97,10 +97,11 @@ if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then saved_cflags="$CFLAGS" CFLAGS="" QF_CC_OPTION(-frename-registers) - if test "$CC_MAJ" -ge 4; then - QF_CC_OPTION(-finline-limit=32000 -Winline) - fi - heavy="-O2 $CFLAGS -ffast-math -fno-unsafe-math-optimizations -funroll-loops -fomit-frame-pointer -fexpensive-optimizations" + dnl if test "$CC_MAJ" -ge 4; then + dnl QF_CC_OPTION(-finline-limit=32000 -Winline) + dnl fi + dnl heavy="-O2 $CFLAGS -ffast-math -fno-unsafe-math-optimizations -funroll-loops -fomit-frame-pointer -fexpensive-optimizations" + heavy="-O2 $CFLAGS -fno-fast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations" CFLAGS="$saved_cflags" light="-O2" AC_ARG_ENABLE(strict-aliasing, diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index c97fb3b09..071c2853b 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -1199,10 +1199,11 @@ BarycentricCoords (const vec_t **points, int num_points, const vec3_t p, CrossProduct (a, b, ab); div = DotProduct (ab, ab); CrossProduct (x, b, n); - lambda[1] = DotProduct (n, ab) / div; + lambda[1] = DotProduct (n, ab); CrossProduct (a, x, n); - lambda[2] = DotProduct (n, ab) / div; - lambda[0] = 1 - lambda[1] - lambda[2]; + lambda[2] = DotProduct (n, ab); + lambda[0] = div - lambda[1] - lambda[2]; + VectorScale (lambda, 1 / div, lambda); return; case 4: VectorSubtract (p, points[0], x); diff --git a/libs/util/simd.c b/libs/util/simd.c index a442fa2c1..2ad4a9d9a 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -66,10 +66,10 @@ BarycentricCoords_vf (const vec4f_t **points, int num_points, const vec4f_t p) b = *points[2] - *points[0]; ab = crossf (a, b); d = dotf (ab, ab); - l[1] = (dotf (crossf (x, b), ab) / d)[0]; - l[2] = (dotf (crossf (a, x), ab) / d)[0]; - l[0] = 1 - l[1] - l[2]; - return l; + l[1] = dotf (crossf (x, b), ab)[0]; + l[2] = dotf (crossf (a, x), ab)[0]; + l[0] = d[0] - l[1] - l[2]; + return l / d; case 4: x = p - *points[0]; a = *points[1] - *points[0]; diff --git a/libs/util/test/test-bary.c b/libs/util/test/test-bary.c index fdb712642..676b0038b 100644 --- a/libs/util/test/test-bary.c +++ b/libs/util/test/test-bary.c @@ -35,8 +35,8 @@ struct { {tri, 3, points[0], {1, 0, 0}}, {tri, 3, points[1], {0, 1, 0}}, {tri, 3, points[2], {0, 0, 1}}, - {tri, 3, points[3], {0.333333284, 0.333333333, 0.333333333}},//rounding :P - {tri, 3, points[8], {0.333333284, 0.333333333, 0.333333333}},//rounding :P + {tri, 3, points[3], {0.333333333, 0.333333333, 0.333333333}}, + {tri, 3, points[8], {0.333333333, 0.333333333, 0.333333333}}, {tetra, 4, points[0], {1, 0, 0, 0}}, {tetra, 4, points[1], {0, 1, 0, 0}}, {tetra, 4, points[2], {0, 0, 1, 0}}, diff --git a/libs/util/test/test-baryvf.c b/libs/util/test/test-baryvf.c index ba4538f4a..9dac89c01 100644 --- a/libs/util/test/test-baryvf.c +++ b/libs/util/test/test-baryvf.c @@ -36,8 +36,8 @@ struct { {tri, 3, &points[0], {1, 0, 0}}, {tri, 3, &points[1], {0, 1, 0}}, {tri, 3, &points[2], {0, 0, 1}}, - {tri, 3, &points[3], {0.333333284, 0.333333333, 0.333333333}},//rounding :P - {tri, 3, &points[8], {0.333333284, 0.333333333, 0.333333333}},//rounding :P + {tri, 3, &points[3], {0.333333333, 0.333333333, 0.333333333}}, + {tri, 3, &points[8], {0.333333333, 0.333333333, 0.333333333}}, {tetra, 4, &points[0], {1, 0, 0, 0}}, {tetra, 4, &points[1], {0, 1, 0, 0}}, {tetra, 4, &points[2], {0, 0, 1, 0}}, diff --git a/libs/util/test/test-cexpr.c b/libs/util/test/test-cexpr.c index 338e71bbc..a87adaeff 100644 --- a/libs/util/test/test-cexpr.c +++ b/libs/util/test/test-cexpr.c @@ -37,11 +37,11 @@ int a = 5; int b = 6; int c; -float point[4] = { 2, 3, 4, 1 }; // a point, so w = 1 -float normal[4] = { 1, 2, 3, 0 }; // a vector, so w = 0 -float direction[4] = { 4, 5, 6, 0 }; // a vector, so w = 0 -float plane[4]; -float intercept[4]; +vec4f_t point = { 2, 3, 4, 1 }; // a point, so w = 1 +vec4f_t normal = { 1, 2, 3, 0 }; // a vector, so w = 0 +vec4f_t direction = { 4, 5, 6, 0 }; // a vector, so w = 0 +vec4f_t plane; +vec4f_t intercept; exprtype_t *vector_params[] = { &cexpr_vector, @@ -134,7 +134,7 @@ exprsym_t symbols[] = { exprval_t test_result = { &cexpr_int, &c }; exprval_t plane_result = { &cexpr_vector, &plane }; // a bit hacky, but no l-values -exprval_t dist_result = { &cexpr_float, &plane[3] }; +exprval_t dist_result = { &cexpr_float, (float *)&plane + 3 }; exprval_t intercept_result = { &cexpr_vector, &intercept }; exprtab_t symtab = { diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index cafceb2c8..64a8cd75b 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -243,6 +243,27 @@ fail: // -ffast-math is any real benefit #define ISNAN(x) (((x) & 0x7f800000) == 0x7f800000 && ((x) & 0x7fffff)) +// FIXME differences in precision between archs +static int +cmp (float a, float b) +{ + typedef union { + float f; + int i; + } fi; + fi ax; + fi bx; + int x; + + ax.f = a; + bx.f = b; + x = ax.i - bx.i; + if (x < 0) { + x = -x; + } + return (x & 0x7ffffffc) == 0; +} + static int test_rotation4 (const vec3_t a, const vec3_t b, const quat_t expect) { @@ -282,7 +303,7 @@ test_rotation4 (const vec3_t a, const vec3_t b, const quat_t expect) // yes, float precision will make it difficult to set up expect // but it is at least consistent (ie, the "errors" are not at all // random and thus will be the same from run to run) - if (quat[i] != expect[i]) { + if (!cmp (quat[i], expect[i])) { goto fail; } } @@ -331,10 +352,19 @@ static struct { {0, 0, 1, 1, 0, 0, 0, 1, 0}}, +#if defined(__i686__) && defined(__OPTIMIZE__) + // the fp unit carries more precision than a 32-bit float, so + // the close-to-zero errors are different + {{s05, 0.0, 0.0, s05}, + {1, 0, 0, + 0, 3.42285418e-08, -0.99999994, + 0, 0.99999994, 3.42285418e-08}}, +#else {{s05, 0.0, 0.0, s05}, {1, 0, 0, 0, 5.96046448e-8, -0.99999994, 0, 0.99999994, 5.96046448e-8}}, +#endif }; #define num_quat_mat_tests (sizeof (quat_mat_tests) / sizeof (quat_mat_tests[0])) From 0293167bd252cc0d52f915e454f4ea0c3e866437 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 May 2021 13:52:19 +0900 Subject: [PATCH 1543/3664] [util] Get simd tests working for emulated simd A bit of a mess for optimized vs unoptimized, but the tests acknowledge the differences in precision while checking that the code produces the right results allowing for that precision. --- config.d/compiling.m4 | 4 ++-- libs/util/test/test-simd.c | 28 +++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 5985d895c..f4ac9c7df 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -81,8 +81,8 @@ AC_ARG_ENABLE(optimize, optimize=yes ) -dnl QF_CC_OPTION(-Wno-psabi) -QF_CC_OPTION(-msse2) +QF_CC_OPTION(-Wno-psabi) +dnl QF_CC_OPTION(-msse2) dnl QF_CC_OPTION(-Wno-psabi) dnl QF_CC_OPTION(-mavx2) dnl fma is not used as it is the equivalent of turning on diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index ceb9ad7d4..4cd5b5076 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -322,7 +322,13 @@ static vec4f_test_t vec4f_tests[] = { T(crossf, one, right, { 0, 1, -1} ), T(crossf, one, forward, {-1, 0, 1} ), T(crossf, one, up, { 1, -1, 0} ), +#if !defined(__SSE__) && !defined(__OPTIMIZE__) + // when not optimizing and SSE is not available (but ok when + // optimizing) + T(crossf, qtest, qtest, {0, 0, -1.47819534e-09, 0} ), +#else T(crossf, qtest, qtest, {0, 0, 0, 0} ), +#endif T(qmulf, qident, qident, qident ), T(qmulf, qident, right, right ), @@ -343,7 +349,11 @@ static vec4f_test_t vec4f_tests[] = { T(qmulf, one, one, { 2, 2, 2, -2 } ), T(qmulf, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } ), T(qmulf, qtest, qtest, {0.768, 0.576, 0, -0.28}, -#ifndef __SSE__ +#if !defined(__SSE__) && !defined(__OPTIMIZE__) + // when not optimizing and SSE is not available (but ok when + // optimizing) + {0, 6e-8, -1.47819534e-09, 3e-8} +#elif !defined( __SSE__) {0, 6e-8, 0, 6e-8} #else {0, 6e-8, 0, 3e-8} @@ -369,14 +379,18 @@ static vec4f_test_t vec4f_tests[] = { T(qvmulf, qtest, right, {0.5392, 0.6144, -0.576, 0}, {0, -5.9e-8, -6e-8, 0} ), T(qvmulf, qtest, forward, {0.6144, 0.1808, 0.768, 0}, -#ifndef __SSE__ +#if !defined(__SSE__) && !defined(__OPTIMIZE__) + {-5.9e-8, 0, 0, 0} +#elif !defined(__SSE__) {-5.9e-8, 3e-8, 0, 0} #else {-5.9e-8, 1.5e-8, 0, 0} #endif ), T(qvmulf, qtest, up, {0.576, -0.768, -0.28, 0}, -#ifndef __SSE__ +#if !defined(__SSE__) && !defined(__OPTIMIZE__) + {6e-8, 0, 3e-8, 0} +#elif !defined(__SSE__) {6e-8, 0, 6e-8, 0} #else {6e-8, 0, 3e-8, 0} @@ -385,14 +399,18 @@ static vec4f_test_t vec4f_tests[] = { T(vqmulf, right, qtest, {0.5392, 0.6144, 0.576, 0}, {0, -5.9e-8, 5.9e-8, 0} ), T(vqmulf, forward, qtest, {0.6144, 0.1808, -0.768, 0}, -#ifndef __SSE__ +#if !defined(__SSE__) && !defined(__OPTIMIZE__) + {-5.9e-8, 0, 0, 0} +#elif !defined(__SSE__) {-5.9e-8, 3e-8, 0, 0} #else {-5.9e-8, 1.5e-8, 0, 0} #endif ), T(vqmulf, up, qtest, {-0.576, 0.768, -0.28, 0}, -#ifndef __SSE__ +#if !defined(__SSE__) && !defined(__OPTIMIZE__) + {-5.9e-8, 0, 3e-8, 0} +#elif !defined(__SSE__) {-5.9e-8, 0, 6e-8, 0} #else {-5.9e-8, 0, 3e-8, 0} From 73cffe283a56be139fd26dba5481595e89eb0dd2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 May 2021 23:42:29 +0900 Subject: [PATCH 1544/3664] [qwaq] Ensure qwaq_event_t's when is aligned While qfcc will always align double values to 8 bytes (really, two global words) regardless of the underlying hardware, gcc does not: doubles are only 4-byte aligned on 32-bit hardware. This fixes the invalid debug target handle when running on i686. --- ruamoko/qwaq/ui/event.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/ui/event.h b/ruamoko/qwaq/ui/event.h index d8fe09c6c..a3c9525b0 100644 --- a/ruamoko/qwaq/ui/event.h +++ b/ruamoko/qwaq/ui/event.h @@ -68,6 +68,7 @@ typedef union qwaq_message_s { typedef struct qwaq_event_s { int what; + int __pad; double when; // NOTE: 1<<32 based union { qwaq_kevent_t key; From 00fb0972a87e54a00f008b6197ed4f2df29d8dff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 May 2021 11:14:05 +0900 Subject: [PATCH 1545/3664] [qwaq] Fix some incorrect parameter acesses They weren't wrong as such (the data was being accessed correctly anyway, just not ideal as the parameter access was slightly hidden. --- ruamoko/qwaq/builtins/curses.c | 2 +- ruamoko/qwaq/builtins/debug.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 976a15ee7..045ab9ae7 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -1436,7 +1436,7 @@ static void bi_get_event (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - qwaq_event_t *event = &G_STRUCT (pr, qwaq_event_t, P_INT (pr, 0)); + qwaq_event_t *event = &P_STRUCT (pr, qwaq_event_t, 0); R_INT (pr) = get_event (res, event); } diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 741bd8a91..fe6796b46 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -363,7 +363,7 @@ qdb_get_event (progs_t *pr) __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); pointer_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); - __auto_type event = &G_STRUCT (pr, qdb_event_t, P_INT (pr, 1)); + __auto_type event = &P_STRUCT (pr, qdb_event_t, 1); memset (event, 0, sizeof (*event)); event->what = target->event; From bcc5686606991f87cf8f2fd6ace5546694025839 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 May 2021 15:47:54 +0900 Subject: [PATCH 1546/3664] [util] Add fuzzy and reentrant bsearch Fuzzy bsearch is useful for finding an entry in a prefix sum array (value is >= ele[0], < ele[1]), and the reentrant version is good when data needs to be passed to the compare function. Adapted from the code used in pr_resolve. --- config.d/library_functions.m4 | 3 +- include/Makemodule.am | 1 + include/QF/Makemodule.am | 1 + include/QF/fbsearch.h | 49 ++++++++++++++ include/bsearch.h | 41 ++++++++++++ include/compat.h | 5 ++ include/quicksort.h | 3 + libs/util/Makemodule.am | 1 + libs/util/bsearch.c | 98 ++++++++++++++++++++++++++++ libs/util/test/Makemodule.am | 5 ++ libs/util/test/test-bsearch.c | 116 ++++++++++++++++++++++++++++++++++ 11 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 include/QF/fbsearch.h create mode 100644 include/bsearch.h create mode 100644 libs/util/bsearch.c create mode 100644 libs/util/test/test-bsearch.c diff --git a/config.d/library_functions.m4 b/config.d/library_functions.m4 index f4bebf3c0..c071dfa94 100644 --- a/config.d/library_functions.m4 +++ b/config.d/library_functions.m4 @@ -8,7 +8,8 @@ AC_FUNC_MMAP AC_TYPE_SIGNAL AC_FUNC_VPRINTF AC_CHECK_FUNCS( - access _access connect dlopen execvp fcntl ftime _ftime getaddrinfo \ + access _access bsearch_r connect dlopen execvp fcntl ftime _ftime \ + getaddrinfo \ gethostbyname gethostname getnameinfo getpagesize gettimeofday getuid \ getwd ioctl mkdir _mkdir mprotect putenv qsort_r select sigaction \ snprintf _snprintf socket stat strcasestr strerror strerror_r strndup \ diff --git a/include/Makemodule.am b/include/Makemodule.am index 48acc8173..6d0039fc8 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -10,6 +10,7 @@ EXTRA_DIST += \ include/asm_i386.h \ include/block16.h \ include/block8.h \ + include/bsearch.h \ include/buildnum.h \ include/compat.h \ include/context_sdl.h \ diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 79d2d2ec1..7c7b726fe 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -16,6 +16,7 @@ include_qf = \ include/QF/dstring.h \ include/QF/draw.h \ include/QF/entity.h \ + include/QF/fbsearch.h \ include/QF/gib.h \ include/QF/hash.h \ include/QF/idparse.h \ diff --git a/include/QF/fbsearch.h b/include/QF/fbsearch.h new file mode 100644 index 000000000..b6463969a --- /dev/null +++ b/include/QF/fbsearch.h @@ -0,0 +1,49 @@ +/* + fbsearch.h + + Fuzzy bsearch + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_bsearch_h +#define __QF_bsearch_h + +#include + +#ifndef __compar_fn_t_defined +#define __compar_fn_t_defined +typedef int (*__compar_fn_t)(const void *, const void *); +#endif + +#ifndef __compar_d_fn_t_defined +#define __compar_d_fn_t_defined +typedef int (*__compar_d_fn_t)(const void *, const void *, void *); +#endif + +void *fbsearch (const void *key, const void *base, size_t nmemb, size_t size, + __compar_fn_t cmp); + +void *fbsearch_r (const void *key, const void *base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg); + +#endif//__QF_bsearch_h diff --git a/include/bsearch.h b/include/bsearch.h new file mode 100644 index 000000000..0a3a507b4 --- /dev/null +++ b/include/bsearch.h @@ -0,0 +1,41 @@ +/* + bsearch.h + + Reentrant bsearch for systems that don't have it + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef bsearch_h +#define bsearch_h + +#include + +#ifndef __compar_d_fn_t_defined +#define __compar_d_fn_t_defined +typedef int (*__compar_d_fn_t)(const void *, const void *, void *); +#endif + +void *_bsearch(const void *key, const void *base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg); + +#endif// quicksort_h diff --git a/include/compat.h b/include/compat.h index dc36b6745..eaab8a6ba 100644 --- a/include/compat.h +++ b/include/compat.h @@ -107,6 +107,11 @@ size_t strndup (const char *str, size_t len); # include "qstring.h" #endif +#ifndef HAVE_BSEARCH_R +# include "bsearch.h" +# define bsearch_r _bsearch +#endif + #ifndef HAVE_QSORT_R # include "quicksort.h" # define qsort_r _quicksort diff --git a/include/quicksort.h b/include/quicksort.h index 6d7743f3d..75d7c43ac 100644 --- a/include/quicksort.h +++ b/include/quicksort.h @@ -30,7 +30,10 @@ #include +#ifndef __compar_d_fn_t_defined +#define __compar_d_fn_t_defined typedef int (*__compar_d_fn_t)(const void *, const void *, void *); +#endif void _quicksort(void *base, size_t nmemb, size_t size, __compar_d_fn_t cmp, void *arg); diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am index 6b2d0162c..0912e064c 100644 --- a/libs/util/Makemodule.am +++ b/libs/util/Makemodule.am @@ -40,6 +40,7 @@ libs_util_libQFutil_la_LDFLAGS= $(lib_ldflags) libs_util_libQFutil_la_LIBADD= $(util_asm) $(Z_LIBS) $(DL_LIBS) $(WIN32_LIBS) libs_util_libQFutil_la_DEPENDENCIES= $(util_asm) libs_util_libQFutil_la_SOURCES= \ + libs/util/bsearch.c \ libs/util/bspfile.c \ libs/util/buildnum.c \ libs/util/cbuf.c \ diff --git a/libs/util/bsearch.c b/libs/util/bsearch.c new file mode 100644 index 000000000..225f2623b --- /dev/null +++ b/libs/util/bsearch.c @@ -0,0 +1,98 @@ +#include +#include + +#include "QF/fbsearch.h" +#include "bsearch.h" + +void *fbsearch (const void *key, const void *_base, size_t nmemb, size_t size, + __compar_fn_t cmp) +{ + // fuzzy bsearh + const char *base = (const char *) _base; + unsigned left = 0; + unsigned right = nmemb - 1; + unsigned mid; + const void *p = 0; + + if (!nmemb) { + return 0; + } + while (left != right) { + mid = (left + right + 1) / 2; + p = base + mid * size; + if (cmp (key, p) < 0) { + right = mid - 1; + } else { + left = mid; + } + } + p = base + left * size; + if (cmp (key, p) >= 0) { + return (void *) p; + } + return 0; +} + +void *fbsearch_r (const void *key, const void *_base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg) +{ + // fuzzy bsearh + const char *base = (const char *) _base; + unsigned left = 0; + unsigned right = nmemb - 1; + unsigned mid; + const void *p = 0; + + if (!nmemb) { + return 0; + } + while (left != right) { + mid = (left + right + 1) / 2; + p = base + mid * size; + if (cmp (key, p, arg) < 0) { + right = mid - 1; + } else { + left = mid; + } + } + p = base + left * size; + if (cmp (key, p, arg) >= 0) { + return (void *) p; + } + return 0; +} + +void * +_bsearch(const void *key, const void *_base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg) +{ + // fuzzy bsearh + const char *base = (const char *) _base; + unsigned left = 0; + unsigned right = nmemb; + unsigned mid; + const void *p = 0; + int c; + + if (!nmemb) { + return 0; + } + while (left != right) { + mid = (left + right + 1) / 2; + p = base + mid * size; + c = cmp (key, p, arg); + if (c == 0) { + return (void *) p; + } + if (c < 0) { + right = mid - 1; + } else { + left = mid; + } + } + p = base + left * size; + if (cmp (key, p, arg) == 0) { + return (void *) p; + } + return 0; +} diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 323282bde..e14c05ccf 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -1,6 +1,7 @@ libs_util_tests = \ libs/util/test/test-bary \ libs/util/test/test-baryvf \ + libs/util/test/test-bsearch \ libs/util/test/test-cexpr \ libs/util/test/test-cmem \ libs/util/test/test-cs \ @@ -33,6 +34,10 @@ libs_util_test_test_baryvf_SOURCES=libs/util/test/test-baryvf.c libs_util_test_test_baryvf_LDADD=libs/util/libQFutil.la libs_util_test_test_baryvf_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_bsearch_SOURCES=libs/util/test/test-bsearch.c +libs_util_test_test_bsearch_LDADD=libs/util/libQFutil.la +libs_util_test_test_bsearch_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_cexpr_SOURCES=libs/util/test/test-cexpr.c libs_util_test_test_cexpr_LDADD=libs/util/libQFutil.la libs_util_test_test_cexpr_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-bsearch.c b/libs/util/test/test-bsearch.c new file mode 100644 index 000000000..7723bddec --- /dev/null +++ b/libs/util/test/test-bsearch.c @@ -0,0 +1,116 @@ +/* + test-bsearch.c + + Fuzzy and reentrant bsearch + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/fbsearch.h" +#include "bsearch.h" + +// will be prefix-summed +int data[] = { + 2, 1, 3, 1, 2, 2, 5, 4, + 2, 1, 3, 1, 2, 2, 5, 4, +}; +#define nele ((int) (sizeof (data) / sizeof (data[0]))) + +static int +compare (const void *a, const void *b) +{ + return *(const int *)a - *(const int *)b; +} + +static int +compared (const void *a, const void *b, void *d) +{ + return *(const int *)a - *(const int *)b; +} + +static int +fuzzy_check (const int *p, int val, const char *func) +{ + if (val < data[0] && p) { + printf ("%s found %d, but should not\n", func, val); + return 0; + } + if (p) { + int ok = p < data + nele - 1; + if (p >= data + nele) { + printf ("%s went out of bounts: %zd\n", func, p - data); + return 0; + } + if (val < *p || (ok && val >= p[1])) { + printf ("%s found %d:%d for %d\n", func, *p, ok ? p[1] : -1, val); + return 0; + } + } + if (!p && val >= data[0]) { + printf ("%s did not find %d, but should have\n", func, val); + return 0; + } + return 1; +} + +int +main(int argc, const char **argv) +{ + int ret = 0; + int *p; + + for (int i = 1; i < nele; i++) { + data[i] += data[i - 1]; + } + for (int i = 0; i < nele; i++) { + printf ("%2d %d\n", i, data[i]); + } + for (int i = 0; i < data[nele - 1] + 2; i++) { + p = fbsearch (&i, data, nele, sizeof (int), compare); + if (!fuzzy_check (p, i, "fbsearch")) { + ret |= 1; + } + p = fbsearch_r (&i, data, nele, sizeof (int), compared, 0); + if (!fuzzy_check (p, i, "fbsearch_r")) { + ret |= 1; + } + if (p && i == *p) { + p = _bsearch (&i, data, nele, sizeof (int), compared, 0); + if (!p || *p != i) { + printf ("_bsearch did not find %d, but should have\n", i); + ret |= 1; + } + } else { + p = _bsearch (&i, data, nele, sizeof (int), compared, 0); + if (p) { + printf ("_bsearch found %d, but should not have\n", i); + ret |= 1; + } + } + } + return ret; +} From d98c92a5c4d70e053c2189b4210fe2c1deb91f45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Jun 2021 12:59:01 +0900 Subject: [PATCH 1547/3664] [qwaq] Start work on cursor management For now, the cursor is always hidden, but the plan is to have it visible in only the focused view if that view has enabled the cursor. --- ruamoko/qwaq/ui/group.h | 2 ++ ruamoko/qwaq/ui/group.r | 16 ++++++++++ ruamoko/qwaq/ui/scrollbar.r | 7 +++++ ruamoko/qwaq/ui/view.h | 8 ++++- ruamoko/qwaq/ui/view.r | 61 ++++++++++++++++++++++++++++++++----- ruamoko/qwaq/ui/window.r | 7 +++++ 6 files changed, 92 insertions(+), 9 deletions(-) diff --git a/ruamoko/qwaq/ui/group.h b/ruamoko/qwaq/ui/group.h index c1b96b80d..2e8dcfa0c 100644 --- a/ruamoko/qwaq/ui/group.h +++ b/ruamoko/qwaq/ui/group.h @@ -26,10 +26,12 @@ -insertSelected: (View *) view; -remove: (View *) view; -(Rect) rect; +-(Rect) absRect; -(Point) origin; -(Extent) size; -draw; -redraw; +-updateAbsPos: (Point) absPos; -resize: (Extent) delta; -handleEvent: (qwaq_event_t *) event; -takeFocus; diff --git a/ruamoko/qwaq/ui/group.r b/ruamoko/qwaq/ui/group.r index e2e8e1890..f76cf3c2a 100644 --- a/ruamoko/qwaq/ui/group.r +++ b/ruamoko/qwaq/ui/group.r @@ -190,6 +190,14 @@ trySetFocus (Group *self, int viewIndex) return {[self origin], [self size]}; } +-(Rect) absRect +{ + if (owner) { + return [owner absRect]; + } + return {[self origin], [self size]}; +} + -(Point) origin { if (owner) { @@ -236,6 +244,14 @@ not_dont_draw (id aView, void *aGroup) return self; } +-updateAbsPos: (Point) absPos +{ + for (int i = [views count]; i-- > 0; ) { + [[views objectAtIndex: i] updateAbsPos: absPos]; + } + return self; +} + -resize: (Extent) delta { for (int i = [views count]; i-- > 0; ) { diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index 3d0eee6ce..253d25911 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -86,6 +86,13 @@ return onScrollBarModified; } +-updateAbsPos: (Point) absPos +{ + [super updateAbsPos: absPos]; + [objects updateAbsPos: absRect.offset]; + return self; +} + -draw { [super draw]; diff --git a/ruamoko/qwaq/ui/view.h b/ruamoko/qwaq/ui/view.h index 15e8d22d3..f05b94326 100644 --- a/ruamoko/qwaq/ui/view.h +++ b/ruamoko/qwaq/ui/view.h @@ -50,6 +50,7 @@ enum { -setGrowMode: (int) mode; -(Rect)rect; +-(Rect)absRect; -(Point)origin; -(Extent)size; @@ -70,6 +71,7 @@ enum { -hide; -redraw; -move: (Point) delta; +-updateAbsPos: (Point) absPos; -resize: (Extent) delta; -move:(Point)dpos andResize:(Extent)dsize; -moveTo:(Point)pos; // does not redraw @@ -82,6 +84,10 @@ enum { -(ListenerGroup *) onReceiveFocus; -(ListenerGroup *) onReleaseFocus; -raise; +-hideCursor; +-showCursor; +-setCursorVisible:(int) visible; +-moveCursor:(Point) pos; - (void) onMouseEnter: (Point) pos; - (void) onMouseLeave: (Point) pos; @@ -115,7 +121,7 @@ enum { int options; int growMode; int cursorState; - Point cursor; + Point cursorPos; ListenerGroup *onReceiveFocus; ListenerGroup *onReleaseFocus; ListenerGroup *onEvent; diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index 014560ffd..3e610cf72 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -138,15 +138,44 @@ updateScreenCursor (View *view) } view = owner; } + */ if (view.state & sfInFocus) { - if (view.cursor.x >= 0 && view.cursor.x < view.xlen - && view.cursor.y >= 0 && view.cursor.y < view.ylen) { + if (view.cursorPos.x >= 0 && view.cursorPos.x < view.xlen + && view.cursorPos.y >= 0 && view.cursorPos.y < view.ylen) { curs_set (view.cursorState); - move(view.cursor.x, view.cursor.y); + move(view.cursorPos.x, view.cursorPos.y); } else { curs_set (0); } - }*/ + } +} + +-hideCursor +{ + return [self setCursorVisible: 0]; +} + +-showCursor +{ + return [self setCursorVisible: 1]; +} + +-setCursorVisible: (int) visible +{ + cursorState = visible; + if ((state & (sfInFocus | sfDrawn)) == (sfInFocus | sfDrawn)) { + updateScreenCursor (self); + } + return self; +} + +-moveCursor: (Point) pos +{ + cursorPos = pos; + if ((state & (sfInFocus | sfDrawn)) == (sfInFocus | sfDrawn)) { + updateScreenCursor (self); + } + return self; } -draw @@ -191,6 +220,11 @@ updateScreenCursor (View *view) return rect; } +- (Rect) absRect +{ + return rect; +} + -(Point)origin { return pos; @@ -280,17 +314,28 @@ updateScreenCursor (View *view) ypos = 0; } if (owner) { + Rect r = [owner absRect]; Extent s = [owner size]; - if (xpos > s.width - 1) { - xpos = s.width - 1; + if (xpos > r.extent.width - 1) { + xpos = r.extent.width - 1; } - if (ypos > s.height - 1) { - ypos = s.height - 1; + if (ypos > r.extent.height - 1) { + ypos = r.extent.height - 1; } + [self updateAbsPos: r.offset]; + } else { + [self updateAbsPos: nil]; } return self; } +-updateAbsPos: (Point) absPos +{ + absRect.offset.x = absPos.x + xpos; + absRect.offset.y = absPos.y + ypos; + return self; +} + -resize: (Extent) delta { xlen += delta.width; diff --git a/ruamoko/qwaq/ui/window.r b/ruamoko/qwaq/ui/window.r index 54dc574d6..b381f5f99 100644 --- a/ruamoko/qwaq/ui/window.r +++ b/ruamoko/qwaq/ui/window.r @@ -241,6 +241,13 @@ return self; } +-updateAbsPos: (Point) absPos +{ + [super updateAbsPos: absPos]; + [objects updateAbsPos: absRect.offset]; + return self; +} + -draw { static box_sides_t box_sides = { From 5ca792c40efae607ccf1e5d6aee8ff2c57991b2a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Jun 2021 13:01:19 +0900 Subject: [PATCH 1548/3664] [ruamoko] Add some stdlib function wrappers For now, just bsearch (normal and fuzzy), qsort, and prefixsum (not in C's stdlib that I know of, but I think having native implementations of float and int prefix sums will be useful. --- include/rua_internal.h | 2 + libs/ruamoko/Makemodule.am | 1 + libs/ruamoko/rua_stdlib.c | 172 ++++++++++++++++++++++++++++++++++ ruamoko/include/Makemodule.am | 1 + ruamoko/include/stdlib.h | 17 ++++ ruamoko/lib/Makemodule.am | 1 + ruamoko/lib/stdlib.r | 11 +++ 7 files changed, 205 insertions(+) create mode 100644 libs/ruamoko/rua_stdlib.c create mode 100644 ruamoko/include/stdlib.h create mode 100644 ruamoko/lib/stdlib.r diff --git a/include/rua_internal.h b/include/rua_internal.h index 7bde98a77..c5aba3569 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -55,6 +55,8 @@ void RUA_Script_Init (progs_t *pr, int secure); void RUA_Set_Init (progs_t *pr, int secure); +void RUA_Stdlib_Init (struct progs_s *pr, int secure); + void RUA_String_Init (struct progs_s *pr, int secure); void RUA_QFile_Init (struct progs_s *pr, int secure); diff --git a/libs/ruamoko/Makemodule.am b/libs/ruamoko/Makemodule.am index c3ed37383..e684d1391 100644 --- a/libs/ruamoko/Makemodule.am +++ b/libs/ruamoko/Makemodule.am @@ -23,4 +23,5 @@ libs_ruamoko_libQFruamoko_la_SOURCES= \ libs/ruamoko/rua_runtime.c \ libs/ruamoko/rua_script.c \ libs/ruamoko/rua_set.c \ + libs/ruamoko/rua_stdlib.c \ libs/ruamoko/rua_string.c diff --git a/libs/ruamoko/rua_stdlib.c b/libs/ruamoko/rua_stdlib.c new file mode 100644 index 000000000..8c375e405 --- /dev/null +++ b/libs/ruamoko/rua_stdlib.c @@ -0,0 +1,172 @@ +/* + bi_stdlib.c + + QuakeC stdlib api + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/5/31 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define _GNU_SOURCE // for qsort_r + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include +#include + +#include "compat.h" +#include "qfalloca.h" + +#if defined(_WIN32) && defined(HAVE_MALLOC_H) +#include +#endif + +#include "QF/fbsearch.h" +#include "QF/progs.h" + +#include "rua_internal.h" + +typedef struct { + progs_t *pr; + func_t func; +} function_t; + +static int +int_compare (const void *_a, const void *_b) +{ + const int *a = _a; + const int *b = _b; + return *a - *b; +} + +static int +rua_compare (const void *a, const void *b, void *_f) +{ + function_t *f = _f; + + PR_RESET_PARAMS (f->pr); + P_POINTER (f->pr, 0) = PR_SetPointer (f->pr, a); + P_POINTER (f->pr, 1) = PR_SetPointer (f->pr, b); + f->pr->pr_argc = 2; + PR_ExecuteProgram (f->pr, f->func); + return R_INT (f->pr); +} + +static void +bi_bsearch (progs_t *pr) +{ + const void *key = P_GPOINTER (pr, 0); + const void *array = P_GPOINTER (pr, 1); + size_t nmemb = P_INT (pr, 2); + size_t size = P_INT (pr, 3) * sizeof (pr_int_t); + func_t cmp = P_FUNCTION (pr, 4); + void *p = 0; + + if (!cmp) { + p = bsearch (key, array, nmemb, size, int_compare); + } else { + function_t func = { pr, cmp }; + p = bsearch_r (key, array, nmemb, size, rua_compare, &func); + } + RETURN_POINTER (pr, p); +} + +static void +bi_fbsearch (progs_t *pr) +{ + const void *key = P_GPOINTER (pr, 0); + const void *array = P_GPOINTER (pr, 1); + size_t nmemb = P_INT (pr, 2); + size_t size = P_INT (pr, 3) * sizeof (pr_int_t); + func_t cmp = P_FUNCTION (pr, 4); + void *p = 0; + + if (!cmp) { + p = fbsearch (key, array, nmemb, size, int_compare); + } else { + function_t func = { pr, cmp }; + p = fbsearch_r (key, array, nmemb, size, rua_compare, &func); + } + RETURN_POINTER (pr, p); +} + +static void +bi_qsort (progs_t *pr) +{ + void *array = P_GPOINTER (pr, 0); + size_t nmemb = P_INT (pr, 1); + size_t size = P_INT (pr, 2) * sizeof (pr_int_t); + func_t cmp = P_FUNCTION (pr, 3); + + if (!cmp) { + qsort (array, nmemb, size, int_compare); + } else { + function_t func = { pr, cmp }; + qsort_r (array, nmemb, size, rua_compare, &func); + } +} + +static void +bi_prefixsumi (progs_t *pr) +{ + int *array = (int *) P_GPOINTER (pr, 0); + int count = P_INT (pr, 1); + + for (int i = 1; i < count; i++) { + array[i] += array[i - 1]; + } +} + +static void +bi_prefixsumf (progs_t *pr) +{ + float *array = (float *) P_GPOINTER (pr, 0); + int count = P_INT (pr, 1); + + for (int i = 1; i < count; i++) { + array[i] += array[i - 1]; + } +} + +static builtin_t builtins[] = { + {"bsearch", bi_bsearch, -1}, + {"fbsearch", bi_fbsearch, -1}, + {"qsort", bi_qsort, -1}, + {"prefixsum|^ii", bi_prefixsumi, -1}, + {"prefixsum|^fi", bi_prefixsumf, -1}, + {0} +}; + +void +RUA_Stdlib_Init (progs_t *pr, int secure) +{ + PR_RegisterBuiltins (pr, builtins); +} diff --git a/ruamoko/include/Makemodule.am b/ruamoko/include/Makemodule.am index d53289e72..8324491d3 100644 --- a/ruamoko/include/Makemodule.am +++ b/ruamoko/include/Makemodule.am @@ -16,6 +16,7 @@ ruamoko_include = \ ruamoko/include/server.h \ ruamoko/include/sound.h \ ruamoko/include/script.h \ + ruamoko/include/stdlib.h \ ruamoko/include/string.h \ ruamoko/include/sv_sound.h \ ruamoko/include/system.h \ diff --git a/ruamoko/include/stdlib.h b/ruamoko/include/stdlib.h new file mode 100644 index 000000000..d645955f4 --- /dev/null +++ b/ruamoko/include/stdlib.h @@ -0,0 +1,17 @@ +#ifndef __stdlib_h +#define __stdlib_h + +//FIXME add const to qfcc? +// If compare is nil, the value pointed to by key and the first member of the +// elements in the array are treated as ints, making for fast searches when the +// first member of the element is the key and is a simple int +void *bsearch (void *key, void *array, int nmemb, int size, + int (*compare) (void *a, void *b)); +void *fbsearch (void *key, void *array, int nmemb, int size, + int (*compare) (void *a, void *b)); +void *qsort (void *array, int nmemb, int size, + int (*compare) (void *a, void *b)); +@overload void prefixsum (int *array, int count); +@overload void prefixsum (float *array, int count); + +#endif//__stdlib_h diff --git a/ruamoko/lib/Makemodule.am b/ruamoko/lib/Makemodule.am index 0d189f6b7..5711a0b24 100644 --- a/ruamoko/lib/Makemodule.am +++ b/ruamoko/lib/Makemodule.am @@ -17,6 +17,7 @@ ruamoko_lib_libr_a_SOURCES=\ ruamoko/lib/qfs.r \ ruamoko/lib/script.r \ ruamoko/lib/sound.r \ + ruamoko/lib/stdlib.r \ ruamoko/lib/string.r \ ruamoko/lib/math.r \ ruamoko/lib/types.r \ diff --git a/ruamoko/lib/stdlib.r b/ruamoko/lib/stdlib.r new file mode 100644 index 000000000..e1145e913 --- /dev/null +++ b/ruamoko/lib/stdlib.r @@ -0,0 +1,11 @@ +#include + +void *bsearch (void *key, void *array, int nmemb, int size, + int (*compare) (void *a, void *b)) = #0; +void *fbsearch (void *key, void *array, int nmemb, int size, + int (*compare) (void *a, void *b)) = #0; +void *qsort (void *array, int nmemb, int size, + int (*compare) (void *a, void *b)) = #0; + +void prefixsum (int *array, int count) = #0; +void prefixsum (float *array, int count) = #0; From 758a44a946903ff3ad8181201ba5d451e5a2428f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Jun 2021 19:09:03 +0900 Subject: [PATCH 1549/3664] [vulkan] Fix an uninitialized variable warning semi-bogus, but I prefer false positives to false negatives. --- libs/video/renderer/vulkan/vulkan_lighting.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index e666e4c77..deb56c1c4 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -646,6 +646,7 @@ create_light_matrices (lightingctx_t *lctx) mat4f_t proj; switch (light->data & ShadowMask) { + default: case ST_NONE: case ST_CUBE: mat4fidentity (view); From 897f8ebfbee00f091c4d045c51c6feb4c154d909 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Jun 2021 19:10:01 +0900 Subject: [PATCH 1550/3664] [vulkan] Fix vkgen linking I had missed the edit while getting qf to build on my eeepc due to not having vulkan. --- libs/video/renderer/vulkan/vkgen/Makemodule.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 0b4f3b2ec..d7d2f5701 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -24,7 +24,7 @@ VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen vkgen_dat_SOURCES=$(vkgen_dat_src) vkgen_obj=$(vkgen_dat_SOURCES:.r=.o) vkgen_dep=$(call qcautodep,$(vkgen_dat_SOURCES:.o=.Qo)) -libs/video/renderer/vulkan/vkgen.dat$(EXEEXT): $(vkgen_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a +vkgen.dat$(EXEEXT): $(vkgen_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a $(V_QFCCLD)$(QLINK) -o $@ $(vkgen_obj) -lcsqc -lr include $(vkgen_dep) # am--include-marker r_depfiles_remade += $(vkgen_dep) From 713862c511187e97bf43a2bb6a36ae72b879e1f1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Jun 2021 19:11:51 +0900 Subject: [PATCH 1551/3664] [util] Fix format issue in set test I guess I hadn't done a "make check" on 64-bit since getting windows builds to work. --- libs/util/test/test-set.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index 87e216f18..3d2b5e6d6 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -197,13 +197,13 @@ main (int argc, const char **argv) //printf ("set_bits_t: %d, SET_DEFMAP_SIZE: %d, SIZE: %d\n", // sizeof (set_bits_t), SET_DEFMAP_SIZE, SIZE); - tests[5].str_expect = nva ("{%d}", SIZE); - tests[7].str_expect = nva ("{%d ...}", SIZE); - tests[8].str_expect = nva ("{%d ...}", SIZE); + tests[5].str_expect = nva ("{%zd}", SIZE); + tests[7].str_expect = nva ("{%zd ...}", SIZE); + tests[8].str_expect = nva ("{%zd ...}", SIZE); str = dstring_new (); for (i = 0; i < SIZE; i++) { - dasprintf (str, "%c%d", i ? ' ' : '{', i); + dasprintf (str, "%c%zd", i ? ' ' : '{', i); } dstring_appendstr (str, "}"); tests[6].str_expect = dstring_freeze (str); From dc5ebd5c3d51fcd63bc33758cdc0793946c2a32f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Jun 2021 23:44:51 +0900 Subject: [PATCH 1552/3664] [ruamoko] Actually hook up the stdlib builtins --- libs/ruamoko/rua_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ruamoko/rua_init.c b/libs/ruamoko/rua_init.c index 6e4333998..8c69a75d9 100644 --- a/libs/ruamoko/rua_init.c +++ b/libs/ruamoko/rua_init.c @@ -48,6 +48,7 @@ static void (*init_funcs[])(progs_t *, int) = { RUA_Runtime_Init, RUA_Script_Init, RUA_Set_Init, + RUA_Stdlib_Init, RUA_String_Init, }; From 53b553e89234306dc0111b107308fb42998e522b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Jun 2021 23:52:04 +0900 Subject: [PATCH 1553/3664] [qwaq] Rework def views to support multi-row defs Needed for structured types (arrays, structs, etc). The multiple rows aren't implemented yet, but the initial groundwork is done. --- ruamoko/qwaq/debugger/localsdata.h | 4 ++ ruamoko/qwaq/debugger/localsdata.r | 58 ++++++++++++++++------- ruamoko/qwaq/debugger/views/basicview.h | 3 +- ruamoko/qwaq/debugger/views/basicview.r | 4 +- ruamoko/qwaq/debugger/views/defview.h | 12 +++-- ruamoko/qwaq/debugger/views/defview.r | 35 ++++++++++---- ruamoko/qwaq/debugger/views/doubleview.h | 2 +- ruamoko/qwaq/debugger/views/doubleview.r | 10 ++-- ruamoko/qwaq/debugger/views/entityview.h | 2 +- ruamoko/qwaq/debugger/views/entityview.r | 10 ++-- ruamoko/qwaq/debugger/views/fieldview.h | 2 +- ruamoko/qwaq/debugger/views/fieldview.r | 10 ++-- ruamoko/qwaq/debugger/views/floatview.h | 2 +- ruamoko/qwaq/debugger/views/floatview.r | 10 ++-- ruamoko/qwaq/debugger/views/funcview.h | 2 +- ruamoko/qwaq/debugger/views/funcview.r | 10 ++-- ruamoko/qwaq/debugger/views/intview.h | 2 +- ruamoko/qwaq/debugger/views/intview.r | 10 ++-- ruamoko/qwaq/debugger/views/nameview.r | 2 +- ruamoko/qwaq/debugger/views/pointerview.h | 2 +- ruamoko/qwaq/debugger/views/pointerview.r | 10 ++-- ruamoko/qwaq/debugger/views/quatview.h | 2 +- ruamoko/qwaq/debugger/views/quatview.r | 10 ++-- ruamoko/qwaq/debugger/views/stringview.h | 2 +- ruamoko/qwaq/debugger/views/stringview.r | 10 ++-- ruamoko/qwaq/debugger/views/uintview.h | 2 +- ruamoko/qwaq/debugger/views/uintview.r | 10 ++-- ruamoko/qwaq/debugger/views/vectorview.h | 2 +- ruamoko/qwaq/debugger/views/vectorview.r | 10 ++-- ruamoko/qwaq/debugger/views/voidview.h | 2 +- ruamoko/qwaq/debugger/views/voidview.r | 10 ++-- 31 files changed, 154 insertions(+), 108 deletions(-) diff --git a/ruamoko/qwaq/debugger/localsdata.h b/ruamoko/qwaq/debugger/localsdata.h index 3428219cb..e153a06a5 100644 --- a/ruamoko/qwaq/debugger/localsdata.h +++ b/ruamoko/qwaq/debugger/localsdata.h @@ -5,6 +5,8 @@ #include "ruamoko/qwaq/ui/tableview.h" #include "ruamoko/qwaq/debugger/debug.h" +@class DefView; + @interface LocalsData : Object { qdb_target_t target; @@ -13,6 +15,8 @@ qdb_function_t *func; qdb_auxfunction_t *aux_func; qdb_def_t *defs; + DefView **def_views; + int *def_rows; void *data; } +(LocalsData *)withTarget:(qdb_target_t)target; diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index c974cdd98..d45a86fb4 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -1,9 +1,9 @@ +#include #include #include #include "ruamoko/qwaq/debugger/views/defview.h" #include "ruamoko/qwaq/debugger/views/nameview.h" #include "ruamoko/qwaq/debugger/localsdata.h" -#include "ruamoko/qwaq/debugger/typeencodings.h" @implementation LocalsData @@ -26,11 +26,24 @@ return [[[self alloc] initWithTarget:target] autorelease]; } +static void +free_defs (LocalsData *self) +{ + obj_free (self.defs); + self.defs = nil; + for (int i = 0; i < self.aux_func.num_locals; i++) { + [self.def_views[i] release]; + } + obj_free (self.def_views); + self.def_views = nil; + obj_free (self.def_rows); + self.def_rows = nil; +} + -(void)dealloc { if (defs) { - obj_free (defs); - defs = nil; + free_defs (self); } if (data) { obj_free (data); @@ -46,20 +59,28 @@ current_fnum =fnum; if (defs) { - obj_free (defs); - defs = nil; + free_defs (self); } if (data) { obj_free (data); data = nil; } func = qdb_get_function (target, fnum); + if (func && func.local_size) { + data = obj_malloc (func.local_size); + } aux_func = qdb_get_auxfunction (target, fnum); if (aux_func) { defs = qdb_get_local_defs (target, fnum); - } - if (func && func.local_size) { - data = obj_malloc (func.local_size); + def_views = obj_malloc (aux_func.num_locals); + def_rows = obj_malloc (aux_func.num_locals + 1); + def_rows[0] = 0; + for (int i = 0; i < aux_func.num_locals; i++) { + def_views[i] = [[DefView withDef:defs[i] in:data target:target] + retain]; + def_rows[i + 1] = [def_views[i] rows]; + } + prefixsum (def_rows, aux_func.num_locals + 1); } return self; } @@ -75,7 +96,10 @@ -(int)numberOfRows:(TableView *)tableview { if (aux_func) { - return aux_func.num_locals; + if (!aux_func.num_locals) { + return 0; + } + return def_rows[aux_func.num_locals]; } else if (func) { return (func.local_size + 3) / 4; } @@ -86,15 +110,15 @@ forColumn:(TableViewColumn *)column row:(int)row { - View *view; + View *view = nil; + int *index = bsearch (&row, def_rows, aux_func.num_locals, 1, nil); - if ([column name] == "name") { - view = [NameView withName:qdb_get_string (target, defs[row].name)]; - } else { - qfot_type_t *type = [TypeEncodings getType:defs[row].type_encoding - fromTarget:target]; - unsigned offset = defs[row].offset; - view = [DefView withType:type at:offset in:data target:target]; + if (index) { + if ([column name] == "name") { + view = [def_views[*index] nameViewAtRow: row - *index]; + } else { + view = [def_views[*index] dataViewAtRow: row - *index]; + } } [view resizeTo:{[column width], 1}]; return view; diff --git a/ruamoko/qwaq/debugger/views/basicview.h b/ruamoko/qwaq/debugger/views/basicview.h index d5424c487..8df776c60 100644 --- a/ruamoko/qwaq/debugger/views/basicview.h +++ b/ruamoko/qwaq/debugger/views/basicview.h @@ -4,8 +4,7 @@ #include "ruamoko/qwaq/debugger/views/defview.h" @interface BasicView : DefView -// might return a NameView (which is also a DefView) -+(DefView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(DefView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_basicview_h diff --git a/ruamoko/qwaq/debugger/views/basicview.r b/ruamoko/qwaq/debugger/views/basicview.r index 96abfc302..8b6b20d35 100644 --- a/ruamoko/qwaq/debugger/views/basicview.r +++ b/ruamoko/qwaq/debugger/views/basicview.r @@ -28,7 +28,7 @@ static string type_views[] = { return self; } -+(DefView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(DefView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { string typename = nil; if (type.type == ty_alias) { @@ -40,7 +40,7 @@ static string type_views[] = { } id class = obj_lookup_class (typename); if (class) { - return [class withType:type at:offset in:data]; + return [class withDef:def in:data type:type]; } return [NameView withName:"Invalid Type"]; } diff --git a/ruamoko/qwaq/debugger/views/defview.h b/ruamoko/qwaq/debugger/views/defview.h index 7e2562104..60ebf9d65 100644 --- a/ruamoko/qwaq/debugger/views/defview.h +++ b/ruamoko/qwaq/debugger/views/defview.h @@ -7,14 +7,16 @@ @interface DefView : View { + qdb_def_t def; qfot_type_t *type; qdb_target_t target; } -+(DefView *)withType:(qfot_type_t *)type - at:(unsigned)offset - in:(void *)data - target:(qdb_target_t)target; --initWithType:(qfot_type_t *)type; ++(DefView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; ++(DefView *)withDef:(qdb_def_t)def in:(void *)data target:(qdb_target_t)target; +-initWithDef:(qdb_def_t)def; +-(int) rows; +-(View *) nameViewAtRow:(int) row; +-(View *) dataViewAtRow:(int) row; @end #endif//__qwaq_debugger_defview_h diff --git a/ruamoko/qwaq/debugger/views/defview.r b/ruamoko/qwaq/debugger/views/defview.r index a972b972f..376bf8a5c 100644 --- a/ruamoko/qwaq/debugger/views/defview.r +++ b/ruamoko/qwaq/debugger/views/defview.r @@ -1,4 +1,5 @@ #include +#include "ruamoko/qwaq/debugger/typeencodings.h" #include "ruamoko/qwaq/debugger/views/defview.h" #include "ruamoko/qwaq/debugger/views/nameview.h" @@ -22,12 +23,12 @@ static string meta_views[] = { return self; } --initWithType:(qfot_type_t *)type +-initWithDef:(qdb_def_t)def { if (!(self = [super init])) { return nil; } - self.type = type; + self.def = def; return self; } @@ -37,16 +38,17 @@ static string meta_views[] = { return self; } -+(DefView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(DefView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [self withType:type at:offset in:data target:nil]; + return [self withDef:def in:data target:nil]; } -+(DefView *)withType:(qfot_type_t *)type - at:(unsigned)offset - in:(void *)data - target:(qdb_target_t)target ++(DefView *)withDef:(qdb_def_t)def + in:(void *)data + target:(qdb_target_t)target { + qfot_type_t *type = [TypeEncodings getType:def.type_encoding + fromTarget:target]; string metaname = nil; if (type.meta == ty_alias) { type = type.alias.aux_type; @@ -57,9 +59,24 @@ static string meta_views[] = { } id class = obj_lookup_class (metaname); if (class) { - return [[class withType:type at:offset in:data] setTarget:target]; + return [[class withDef:def in:data type:type] setTarget:target]; } return [NameView withName:"Invalid Meta"]; } +-(int) rows +{ + return 1; +} + +-(View *) nameViewAtRow:(int) row +{ + return [NameView withName:qdb_get_string (target, def.name)]; +} + +-(View *) dataViewAtRow:(int) row +{ + return self; +} + @end diff --git a/ruamoko/qwaq/debugger/views/doubleview.h b/ruamoko/qwaq/debugger/views/doubleview.h index 90637ecf3..738199d36 100644 --- a/ruamoko/qwaq/debugger/views/doubleview.h +++ b/ruamoko/qwaq/debugger/views/doubleview.h @@ -7,7 +7,7 @@ { double *data; } -+(DoubleView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(DoubleView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_doubleview_h diff --git a/ruamoko/qwaq/debugger/views/doubleview.r b/ruamoko/qwaq/debugger/views/doubleview.r index d94f4e231..02f129553 100644 --- a/ruamoko/qwaq/debugger/views/doubleview.r +++ b/ruamoko/qwaq/debugger/views/doubleview.r @@ -3,18 +3,18 @@ @implementation DoubleView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (double *)(data + offset); + self.data = (double *)(data + def.offset); return self; } -+(DoubleView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(DoubleView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/entityview.h b/ruamoko/qwaq/debugger/views/entityview.h index 5ad8bd908..18453489a 100644 --- a/ruamoko/qwaq/debugger/views/entityview.h +++ b/ruamoko/qwaq/debugger/views/entityview.h @@ -7,7 +7,7 @@ { entity *data; } -+(EntityView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(EntityView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_entityview_h diff --git a/ruamoko/qwaq/debugger/views/entityview.r b/ruamoko/qwaq/debugger/views/entityview.r index 1170a3f7d..34fe591de 100644 --- a/ruamoko/qwaq/debugger/views/entityview.r +++ b/ruamoko/qwaq/debugger/views/entityview.r @@ -3,18 +3,18 @@ @implementation EntityView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (entity *)(data + offset); + self.data = (entity *)(data + def.offset); return self; } -+(EntityView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(EntityView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/fieldview.h b/ruamoko/qwaq/debugger/views/fieldview.h index 0cd314b6b..c97560e2c 100644 --- a/ruamoko/qwaq/debugger/views/fieldview.h +++ b/ruamoko/qwaq/debugger/views/fieldview.h @@ -7,7 +7,7 @@ { unsigned *data; } -+(FieldView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(FieldView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_fieldview_h diff --git a/ruamoko/qwaq/debugger/views/fieldview.r b/ruamoko/qwaq/debugger/views/fieldview.r index f8d1547e3..347957011 100644 --- a/ruamoko/qwaq/debugger/views/fieldview.r +++ b/ruamoko/qwaq/debugger/views/fieldview.r @@ -3,18 +3,18 @@ @implementation FieldView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (unsigned *)(data + offset); + self.data = (unsigned *)(data + def.offset); return self; } -+(FieldView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(FieldView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/floatview.h b/ruamoko/qwaq/debugger/views/floatview.h index 5c33da88b..db73ab864 100644 --- a/ruamoko/qwaq/debugger/views/floatview.h +++ b/ruamoko/qwaq/debugger/views/floatview.h @@ -7,7 +7,7 @@ { float *data; } -+(FloatView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(FloatView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_floatview_h diff --git a/ruamoko/qwaq/debugger/views/floatview.r b/ruamoko/qwaq/debugger/views/floatview.r index 5b4d534eb..dcb86b9e8 100644 --- a/ruamoko/qwaq/debugger/views/floatview.r +++ b/ruamoko/qwaq/debugger/views/floatview.r @@ -3,18 +3,18 @@ @implementation FloatView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (float *)(data + offset); + self.data = (float *)(data + def.offset); return self; } -+(FloatView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(FloatView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/funcview.h b/ruamoko/qwaq/debugger/views/funcview.h index 132812dd3..8b8adeee1 100644 --- a/ruamoko/qwaq/debugger/views/funcview.h +++ b/ruamoko/qwaq/debugger/views/funcview.h @@ -7,7 +7,7 @@ { unsigned *data; } -+(FuncView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(FuncView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_funcview_h diff --git a/ruamoko/qwaq/debugger/views/funcview.r b/ruamoko/qwaq/debugger/views/funcview.r index 2fa2218f0..34d9f5f93 100644 --- a/ruamoko/qwaq/debugger/views/funcview.r +++ b/ruamoko/qwaq/debugger/views/funcview.r @@ -3,18 +3,18 @@ @implementation FuncView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (unsigned *)(data + offset); + self.data = (unsigned *)(data + def.offset); return self; } -+(FuncView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(FuncView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/intview.h b/ruamoko/qwaq/debugger/views/intview.h index d2f271b21..e5fe8f659 100644 --- a/ruamoko/qwaq/debugger/views/intview.h +++ b/ruamoko/qwaq/debugger/views/intview.h @@ -7,7 +7,7 @@ { int *data; } -+(IntView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(IntView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_intview_h diff --git a/ruamoko/qwaq/debugger/views/intview.r b/ruamoko/qwaq/debugger/views/intview.r index a7df120ed..9e2aec16e 100644 --- a/ruamoko/qwaq/debugger/views/intview.r +++ b/ruamoko/qwaq/debugger/views/intview.r @@ -3,18 +3,18 @@ @implementation IntView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (int *)(data + offset); + self.data = (int *)(data + def.offset); return self; } -+(IntView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(IntView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/nameview.r b/ruamoko/qwaq/debugger/views/nameview.r index 0b66d838e..cbb5bd98d 100644 --- a/ruamoko/qwaq/debugger/views/nameview.r +++ b/ruamoko/qwaq/debugger/views/nameview.r @@ -5,7 +5,7 @@ -initWithName:(string)name { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } self.name = name; diff --git a/ruamoko/qwaq/debugger/views/pointerview.h b/ruamoko/qwaq/debugger/views/pointerview.h index fb45f1ae3..0921bba41 100644 --- a/ruamoko/qwaq/debugger/views/pointerview.h +++ b/ruamoko/qwaq/debugger/views/pointerview.h @@ -7,7 +7,7 @@ { unsigned *data; } -+(PointerView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(PointerView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_pointerview_h diff --git a/ruamoko/qwaq/debugger/views/pointerview.r b/ruamoko/qwaq/debugger/views/pointerview.r index 3a000ecf5..e2cad7033 100644 --- a/ruamoko/qwaq/debugger/views/pointerview.r +++ b/ruamoko/qwaq/debugger/views/pointerview.r @@ -3,18 +3,18 @@ @implementation PointerView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (unsigned *)(data + offset); + self.data = (unsigned *)(data + def.offset); return self; } -+(PointerView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(PointerView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/quatview.h b/ruamoko/qwaq/debugger/views/quatview.h index b88f75811..30de36d8f 100644 --- a/ruamoko/qwaq/debugger/views/quatview.h +++ b/ruamoko/qwaq/debugger/views/quatview.h @@ -7,7 +7,7 @@ { quaternion *data; } -+(QuatView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(QuatView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_quatview_h diff --git a/ruamoko/qwaq/debugger/views/quatview.r b/ruamoko/qwaq/debugger/views/quatview.r index fe8ca0ea1..d2b37a82a 100644 --- a/ruamoko/qwaq/debugger/views/quatview.r +++ b/ruamoko/qwaq/debugger/views/quatview.r @@ -3,18 +3,18 @@ @implementation QuatView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (quaternion *)(data + offset); + self.data = (quaternion *)(data + def.offset); return self; } -+(QuatView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(QuatView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/stringview.h b/ruamoko/qwaq/debugger/views/stringview.h index c8a49d131..badbef28c 100644 --- a/ruamoko/qwaq/debugger/views/stringview.h +++ b/ruamoko/qwaq/debugger/views/stringview.h @@ -7,7 +7,7 @@ { int *data; } -+(StringView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(StringView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_stringview_h diff --git a/ruamoko/qwaq/debugger/views/stringview.r b/ruamoko/qwaq/debugger/views/stringview.r index d686fd636..81c6dc90e 100644 --- a/ruamoko/qwaq/debugger/views/stringview.r +++ b/ruamoko/qwaq/debugger/views/stringview.r @@ -3,18 +3,18 @@ @implementation StringView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (int *)(data + offset); + self.data = (int *)(data + def.offset); return self; } -+(StringView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(StringView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/uintview.h b/ruamoko/qwaq/debugger/views/uintview.h index 5211b2ff7..417f9d080 100644 --- a/ruamoko/qwaq/debugger/views/uintview.h +++ b/ruamoko/qwaq/debugger/views/uintview.h @@ -7,7 +7,7 @@ { unsigned *data; } -+(UIntView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(UIntView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_uintview_h diff --git a/ruamoko/qwaq/debugger/views/uintview.r b/ruamoko/qwaq/debugger/views/uintview.r index c80b9b517..cf800f898 100644 --- a/ruamoko/qwaq/debugger/views/uintview.r +++ b/ruamoko/qwaq/debugger/views/uintview.r @@ -3,18 +3,18 @@ @implementation UIntView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (unsigned *)(data + offset); + self.data = (unsigned *)(data + def.offset); return self; } -+(UIntView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(UIntView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/vectorview.h b/ruamoko/qwaq/debugger/views/vectorview.h index 2a00c4e39..b1595ce98 100644 --- a/ruamoko/qwaq/debugger/views/vectorview.h +++ b/ruamoko/qwaq/debugger/views/vectorview.h @@ -7,7 +7,7 @@ { vector *data; } -+(VectorView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(VectorView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_vectorview_h diff --git a/ruamoko/qwaq/debugger/views/vectorview.r b/ruamoko/qwaq/debugger/views/vectorview.r index 61a50c6af..d351bed66 100644 --- a/ruamoko/qwaq/debugger/views/vectorview.r +++ b/ruamoko/qwaq/debugger/views/vectorview.r @@ -3,18 +3,18 @@ @implementation VectorView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (vector *)(data + offset); + self.data = (vector *)(data + def.offset); return self; } -+(VectorView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(VectorView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw diff --git a/ruamoko/qwaq/debugger/views/voidview.h b/ruamoko/qwaq/debugger/views/voidview.h index 1c6655bb1..7a2b6a144 100644 --- a/ruamoko/qwaq/debugger/views/voidview.h +++ b/ruamoko/qwaq/debugger/views/voidview.h @@ -7,7 +7,7 @@ { unsigned *data; } -+(VoidView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data; ++(VoidView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end #endif//__qwaq_debugger_voidview_h diff --git a/ruamoko/qwaq/debugger/views/voidview.r b/ruamoko/qwaq/debugger/views/voidview.r index 81e58b62c..234607102 100644 --- a/ruamoko/qwaq/debugger/views/voidview.r +++ b/ruamoko/qwaq/debugger/views/voidview.r @@ -3,18 +3,18 @@ @implementation VoidView --initWithType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithType:type])) { + if (!(self = [super initWithDef:def])) { return nil; } - self.data = (unsigned *) (data + offset); + self.data = (unsigned *) (data + def.offset); return self; } -+(VoidView *)withType:(qfot_type_t *)type at:(unsigned)offset in:(void *)data ++(VoidView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - return [[[self alloc] initWithType:type at:offset in:data] autorelease]; + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } -draw From 5e29cecf44ec2000755df74fb47a3df8d589ab96 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Jun 2021 13:29:27 +0900 Subject: [PATCH 1554/3664] [ruamoko] Add pr_type_size array to types.[rh] --- ruamoko/include/types.h | 1 + ruamoko/lib/types.r | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index c2f157e76..19ec0c736 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -92,5 +92,6 @@ typedef struct qfot_type_encodings_s { @extern string ty_meta_name[7]; @extern string pr_type_name[ev_type_count]; +@extern int pr_type_size[ev_type_count]; #endif diff --git a/ruamoko/lib/types.r b/ruamoko/lib/types.r index aa1f65a02..45f51c70e 100644 --- a/ruamoko/lib/types.r +++ b/ruamoko/lib/types.r @@ -11,6 +11,23 @@ string ty_meta_name[7] = { "alias", }; +int pr_type_size[ev_type_count] = { + 1, // ev_void + 1, // ev_string + 1, // ev_float + 3, // ev_vector + 1, // ev_entity + 1, // ev_field + 1, // ev_func + 1, // ev_pointer + 4, // ev_quat + 1, // ev_integer + 1, // ev_uinteger + 0, // ev_short value in opcode + 2, // ev_double + 0, // ev_invalid not a valid/simple type +}; + string pr_type_name[ev_type_count] = { "void", "string", @@ -24,6 +41,6 @@ string pr_type_name[ev_type_count] = { "integer", "uinteger", "short", - "double" + "double", "invalid", }; From 7275d9bbf5207f57d6ab88339ea00885b7680708 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Jun 2021 13:31:43 +0900 Subject: [PATCH 1555/3664] [qwaq] Fully load target types into debugger Fully loading the types means that code using the target's type definitions does not need to worry about pulling in sub-types for structured data. --- ruamoko/qwaq/debugger/typeencodings.r | 51 ++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index 7a5fd26d7..109bc33d3 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -10,7 +10,7 @@ // these are encodings that we already have so don't need to copy them from // the target static hashtab_t *static_encodings; -// these are condings that had to be copied from the target +// these are codings that had to be copied from the target static hashtab_t *dynamic_encodings; static qfot_type_t * @@ -79,6 +79,7 @@ static void type_free (void *t, void *unused) qfot_type_t buffer = {}; string encoding; qfot_type_t *type; + qfot_type_t *t; if (qdb_get_data (target, typeAddr, TYPESIZE, &buffer) < 0) { return nil; @@ -105,7 +106,37 @@ static void type_free (void *t, void *unused) } switch (type.meta) { case ty_basic: + if (type.type == ev_pointer || type.type == ev_field) { + t = [TypeEncodings getType:(unsigned)type.fldptr.aux_type + fromTarget:target]; + if (!t) { + goto error; + } + type.fldptr.aux_type = t; + } else if (type.type == ev_func) { + t = [TypeEncodings getType:(unsigned)type.func.return_type + fromTarget:target]; + if (!t) { + goto error; + } + type.func.return_type = t; + for (int i = 0; i < type.func.num_params; i++) { + t = type.func.param_types[i]; + t = [TypeEncodings getType:(unsigned)t fromTarget:target]; + if (!t) { + goto error; + } + type.func.param_types[i] = t; + } + } + goto hash_type; case ty_array: + t = [TypeEncodings getType:(unsigned)type.array.type + fromTarget:target]; + if (!t) { + goto error; + } + type.array.type = t; goto hash_type; case ty_struct: case ty_union: @@ -118,6 +149,12 @@ static void type_free (void *t, void *unused) if (!(var.name = qdb_get_string (target, var.name))) { goto error; } + t = [TypeEncodings getType:(unsigned)var.type + fromTarget:target]; + if (!t) { + goto error; + } + var.type = t; } goto hash_type; case ty_class: @@ -129,6 +166,18 @@ static void type_free (void *t, void *unused) if (!(type.alias.name = qdb_get_string (target, type.alias.name))) { goto error; } + t = [TypeEncodings getType:(unsigned)type.alias.aux_type + fromTarget:target]; + if (!t) { + goto error; + } + type.alias.aux_type = t; + t = [TypeEncodings getType:(unsigned)type.alias.full_type + fromTarget:target]; + if (!t) { + goto error; + } + type.alias.full_type = t; goto hash_type; } goto error; From 22b9bb29f6d93297e483883b4d9e128c5eef9a21 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Jun 2021 13:34:15 +0900 Subject: [PATCH 1556/3664] [qwaq] Calculate type sizes for compound types --- ruamoko/qwaq/debugger/typeencodings.h | 1 + ruamoko/qwaq/debugger/typeencodings.r | 44 +++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/ruamoko/qwaq/debugger/typeencodings.h b/ruamoko/qwaq/debugger/typeencodings.h index 11b78d0da..0ed0f83d7 100644 --- a/ruamoko/qwaq/debugger/typeencodings.h +++ b/ruamoko/qwaq/debugger/typeencodings.h @@ -8,6 +8,7 @@ @interface TypeEncodings : Object +(qfot_type_t *)getType:(unsigned)typeAddr fromTarget:(qdb_target_t)target; ++(int)typeSize:(qfot_type_t *)type; @end #endif//__qwaq_debugger_typeencodings_h diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index 109bc33d3..d6246e2ef 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -191,4 +191,48 @@ error: return nil; } ++(int)typeSize:(qfot_type_t *)type +{ + qfot_type_t *aux_type; + int size = 0; + + switch (type.meta) { + case ty_basic: + size = pr_type_size[type.type]; + break; + case ty_array: + aux_type = type.array.type; + size = type.array.size * [TypeEncodings typeSize:aux_type]; + break; + case ty_struct: + for (int i = 0; i < type.strct.num_fields; i++) { + aux_type = type.strct.fields[i].type; + size += [TypeEncodings typeSize:aux_type]; + } + break; + case ty_union: + for (int i = 0; i < type.strct.num_fields; i++) { + aux_type = type.strct.fields[i].type; + int s = [TypeEncodings typeSize:aux_type]; + if (s > size) { + size = s; + } + } + break; + case ty_enum: + // enums are ints + size = pr_type_size[ev_integer]; + break; + case ty_class: + //FIXME + size = 1; + break; + case ty_alias: + aux_type = type.alias.aux_type; + size = [TypeEncodings typeSize:aux_type]; + break; + } + return size; +} + @end From f50d27ec11453100ff07f2ed78625c5821fdcaa9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Jun 2021 13:35:53 +0900 Subject: [PATCH 1557/3664] [qwaq] Show dereferenced data for poitner defs The code currently assumes a single value is referenced rather than the beginning of an array. --- ruamoko/qwaq/builtins/main.c | 3 +- ruamoko/qwaq/debugger/localsdata.r | 18 ++++--- ruamoko/qwaq/debugger/views/defview.h | 9 ++-- ruamoko/qwaq/debugger/views/defview.r | 35 ++++++++++---- ruamoko/qwaq/debugger/views/doubleview.r | 2 +- ruamoko/qwaq/debugger/views/entityview.r | 2 +- ruamoko/qwaq/debugger/views/fieldview.r | 2 +- ruamoko/qwaq/debugger/views/floatview.r | 2 +- ruamoko/qwaq/debugger/views/funcview.r | 2 +- ruamoko/qwaq/debugger/views/intview.r | 2 +- ruamoko/qwaq/debugger/views/nameview.r | 2 +- ruamoko/qwaq/debugger/views/pointerview.h | 6 +++ ruamoko/qwaq/debugger/views/pointerview.r | 59 ++++++++++++++++++++++- ruamoko/qwaq/debugger/views/quatview.r | 2 +- ruamoko/qwaq/debugger/views/stringview.r | 2 +- ruamoko/qwaq/debugger/views/uintview.r | 2 +- ruamoko/qwaq/debugger/views/vectorview.r | 2 +- ruamoko/qwaq/debugger/views/voidview.r | 2 +- 18 files changed, 121 insertions(+), 33 deletions(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 4404294dc..733dda6b6 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -231,8 +231,9 @@ spawn_progs (qwaq_thread_t *thread) } pr_argv = PR_Zone_Malloc (pr, (pr_argc + 1) * 4); pr_argv[0] = PR_SetTempString (pr, name); - for (i = 1; i < pr_argc; i++) + for (i = 1; i < pr_argc; i++) { pr_argv[i] = PR_SetTempString (pr, thread->args.a[i]); + } pr_argv[i] = 0; PR_RESET_PARAMS (pr); diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index d45a86fb4..808c781de 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -90,6 +90,14 @@ free_defs (LocalsData *self) if (data && func.local_size && func.local_data) { qdb_get_data (target, func.local_data, func.local_size, data); } + if (aux_func) { + def_rows[0] = 0; + for (int i = 0; i < aux_func.num_locals; i++) { + [def_views[i] fetchData]; + def_rows[i + 1] = [def_views[i] rows]; + } + prefixsum (def_rows, aux_func.num_locals + 1); + } return self; } @@ -111,14 +119,12 @@ free_defs (LocalsData *self) row:(int)row { View *view = nil; - int *index = bsearch (&row, def_rows, aux_func.num_locals, 1, nil); + int *index = fbsearch (&row, def_rows, aux_func.num_locals, 1, nil); if (index) { - if ([column name] == "name") { - view = [def_views[*index] nameViewAtRow: row - *index]; - } else { - view = [def_views[*index] dataViewAtRow: row - *index]; - } + DefView *dv = def_views[index - def_rows]; + int r = row - *index; + view = [dv viewAtRow: r forColumn:column]; } [view resizeTo:{[column width], 1}]; return view; diff --git a/ruamoko/qwaq/debugger/views/defview.h b/ruamoko/qwaq/debugger/views/defview.h index 60ebf9d65..f0e6bb392 100644 --- a/ruamoko/qwaq/debugger/views/defview.h +++ b/ruamoko/qwaq/debugger/views/defview.h @@ -5,6 +5,8 @@ #include "ruamoko/qwaq/ui/view.h" #include "ruamoko/qwaq/debugger/debug.h" +@class TableViewColumn; + @interface DefView : View { qdb_def_t def; @@ -13,10 +15,11 @@ } +(DefView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; +(DefView *)withDef:(qdb_def_t)def in:(void *)data target:(qdb_target_t)target; --initWithDef:(qdb_def_t)def; ++(DefView *)withDef:(qdb_def_t)def type:(qfot_type_t *)type in:(void *)data target:(qdb_target_t)target; +-initWithDef:(qdb_def_t)def type:(qfot_type_t *)type; +-fetchData; -(int) rows; --(View *) nameViewAtRow:(int) row; --(View *) dataViewAtRow:(int) row; +-(View *) viewAtRow:(int) row forColumn:(TableViewColumn *)column; @end #endif//__qwaq_debugger_defview_h diff --git a/ruamoko/qwaq/debugger/views/defview.r b/ruamoko/qwaq/debugger/views/defview.r index 376bf8a5c..aff2905f6 100644 --- a/ruamoko/qwaq/debugger/views/defview.r +++ b/ruamoko/qwaq/debugger/views/defview.r @@ -2,6 +2,7 @@ #include "ruamoko/qwaq/debugger/typeencodings.h" #include "ruamoko/qwaq/debugger/views/defview.h" #include "ruamoko/qwaq/debugger/views/nameview.h" +#include "ruamoko/qwaq/ui/tableview.h" static string meta_views[] = { "BasicView", @@ -23,12 +24,13 @@ static string meta_views[] = { return self; } --initWithDef:(qdb_def_t)def +-initWithDef:(qdb_def_t)def type:(qfot_type_t *)type { if (!(self = [super init])) { return nil; } self.def = def; + self.type = type; return self; } @@ -44,11 +46,10 @@ static string meta_views[] = { } +(DefView *)withDef:(qdb_def_t)def + type:(qfot_type_t *)type in:(void *)data target:(qdb_target_t)target { - qfot_type_t *type = [TypeEncodings getType:def.type_encoding - fromTarget:target]; string metaname = nil; if (type.meta == ty_alias) { type = type.alias.aux_type; @@ -64,18 +65,34 @@ static string meta_views[] = { return [NameView withName:"Invalid Meta"]; } ++(DefView *)withDef:(qdb_def_t)def + in:(void *)data + target:(qdb_target_t)target +{ + qfot_type_t *type = [TypeEncodings getType:def.type_encoding + fromTarget:target]; + return [[DefView withDef:def + type:type + in:data + target:target] retain]; +} + +-fetchData +{ + // most def views do not need to update themselves + return self; +} + -(int) rows { return 1; } --(View *) nameViewAtRow:(int) row -{ - return [NameView withName:qdb_get_string (target, def.name)]; -} - --(View *) dataViewAtRow:(int) row +-(View *) viewAtRow:(int) row forColumn:(TableViewColumn *)column { + if ([column name] == "name") { + return [NameView withName:qdb_get_string (target, def.name)]; + } return self; } diff --git a/ruamoko/qwaq/debugger/views/doubleview.r b/ruamoko/qwaq/debugger/views/doubleview.r index 02f129553..16d4653a1 100644 --- a/ruamoko/qwaq/debugger/views/doubleview.r +++ b/ruamoko/qwaq/debugger/views/doubleview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (double *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/entityview.r b/ruamoko/qwaq/debugger/views/entityview.r index 34fe591de..f1200a9c6 100644 --- a/ruamoko/qwaq/debugger/views/entityview.r +++ b/ruamoko/qwaq/debugger/views/entityview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (entity *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/fieldview.r b/ruamoko/qwaq/debugger/views/fieldview.r index 347957011..f09839bf2 100644 --- a/ruamoko/qwaq/debugger/views/fieldview.r +++ b/ruamoko/qwaq/debugger/views/fieldview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (unsigned *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/floatview.r b/ruamoko/qwaq/debugger/views/floatview.r index dcb86b9e8..00f666e69 100644 --- a/ruamoko/qwaq/debugger/views/floatview.r +++ b/ruamoko/qwaq/debugger/views/floatview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (float *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/funcview.r b/ruamoko/qwaq/debugger/views/funcview.r index 34d9f5f93..81025da3a 100644 --- a/ruamoko/qwaq/debugger/views/funcview.r +++ b/ruamoko/qwaq/debugger/views/funcview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (unsigned *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/intview.r b/ruamoko/qwaq/debugger/views/intview.r index 9e2aec16e..f8115bff3 100644 --- a/ruamoko/qwaq/debugger/views/intview.r +++ b/ruamoko/qwaq/debugger/views/intview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (int *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/nameview.r b/ruamoko/qwaq/debugger/views/nameview.r index cbb5bd98d..6393acfd2 100644 --- a/ruamoko/qwaq/debugger/views/nameview.r +++ b/ruamoko/qwaq/debugger/views/nameview.r @@ -5,7 +5,7 @@ -initWithName:(string)name { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:nil])) { return nil; } self.name = name; diff --git a/ruamoko/qwaq/debugger/views/pointerview.h b/ruamoko/qwaq/debugger/views/pointerview.h index 0921bba41..2e314a735 100644 --- a/ruamoko/qwaq/debugger/views/pointerview.h +++ b/ruamoko/qwaq/debugger/views/pointerview.h @@ -6,6 +6,12 @@ @interface PointerView : DefView { unsigned *data; + int invalid; + unsigned ptr; + qfot_type_t *ptr_type; + int ptr_size; + void *ptr_data; + DefView *ptr_view; } +(PointerView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; @end diff --git a/ruamoko/qwaq/debugger/views/pointerview.r b/ruamoko/qwaq/debugger/views/pointerview.r index e2cad7033..69c44edac 100644 --- a/ruamoko/qwaq/debugger/views/pointerview.r +++ b/ruamoko/qwaq/debugger/views/pointerview.r @@ -1,11 +1,14 @@ #include +#include "ruamoko/qwaq/debugger/typeencodings.h" +#include "ruamoko/qwaq/debugger/views/nameview.h" #include "ruamoko/qwaq/debugger/views/pointerview.h" +#include "ruamoko/qwaq/ui/tableview.h" @implementation PointerView -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (unsigned *)(data + def.offset); @@ -17,12 +20,64 @@ return [[[self alloc] initWithDef:def in:data type:type] autorelease]; } +-(void)dealloc +{ + if (ptr_data) { + obj_free (ptr_data); + } + [ptr_view release]; +} + -draw { [super draw]; - string val = sprintf ("FIXME [%x]", data[0]); + string val = sprintf ("%s [0x%x]", type.encoding, data[0]); [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } +-fetchData +{ + if (!ptr_type) { + qdb_def_t def = { 0, 0, 0, (unsigned)type.fldptr.aux_type }; + ptr_type = type.fldptr.aux_type; + ptr_size = [TypeEncodings typeSize:ptr_type]; + ptr_data = obj_malloc (ptr_size); + ptr_view = [[DefView withDef:def + type:ptr_type + in:ptr_data + target:target] retain]; + } + invalid = 1; + if (!ptr_view || ptr != (unsigned) data[0]) { + invalid = qdb_get_data (target, data[0], ptr_size, ptr_data) < 0; + } + return self; +} + +-(int) rows +{ + if (invalid) { + return 2; + } + return 1 + [ptr_view rows]; +} + +-(View *) viewAtRow:(int) row forColumn:(TableViewColumn *)column +{ + if (row == 0) { + if ([column name] == "name") { + return [NameView withName:qdb_get_string (target, def.name)]; + } + return self; + } + if (invalid) { + if ([column name] == "name") { + return nil; + } + return [NameView withName:"Invalid pointer"]; + } + return [ptr_view viewAtRow:row - 1 forColumn:column]; +} + @end diff --git a/ruamoko/qwaq/debugger/views/quatview.r b/ruamoko/qwaq/debugger/views/quatview.r index d2b37a82a..202968415 100644 --- a/ruamoko/qwaq/debugger/views/quatview.r +++ b/ruamoko/qwaq/debugger/views/quatview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (quaternion *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/stringview.r b/ruamoko/qwaq/debugger/views/stringview.r index 81c6dc90e..d1c4808d3 100644 --- a/ruamoko/qwaq/debugger/views/stringview.r +++ b/ruamoko/qwaq/debugger/views/stringview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (int *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/uintview.r b/ruamoko/qwaq/debugger/views/uintview.r index cf800f898..8a0f17e03 100644 --- a/ruamoko/qwaq/debugger/views/uintview.r +++ b/ruamoko/qwaq/debugger/views/uintview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (unsigned *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/vectorview.r b/ruamoko/qwaq/debugger/views/vectorview.r index d351bed66..f7e510742 100644 --- a/ruamoko/qwaq/debugger/views/vectorview.r +++ b/ruamoko/qwaq/debugger/views/vectorview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (vector *)(data + def.offset); diff --git a/ruamoko/qwaq/debugger/views/voidview.r b/ruamoko/qwaq/debugger/views/voidview.r index 234607102..665d28064 100644 --- a/ruamoko/qwaq/debugger/views/voidview.r +++ b/ruamoko/qwaq/debugger/views/voidview.r @@ -5,7 +5,7 @@ -initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type { - if (!(self = [super initWithDef:def])) { + if (!(self = [super initWithDef:def type:type])) { return nil; } self.data = (unsigned *) (data + def.offset); From 88c951762929729911539cd7bc98fb2ca4ffca7a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Jun 2021 14:59:15 +0900 Subject: [PATCH 1558/3664] [qfprogs] Dump class ivars when dumping modules --- tools/qfcc/source/dump_modules.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tools/qfcc/source/dump_modules.c b/tools/qfcc/source/dump_modules.c index 7516f323b..0fcda6e50 100644 --- a/tools/qfcc/source/dump_modules.c +++ b/tools/qfcc/source/dump_modules.c @@ -46,6 +46,29 @@ #include "tools/qfcc/include/qfprogs.h" +static void +dump_ivars (progs_t *pr, pr_ivar_list_t *ivars) +{ + if (!ivars || !ivars->ivar_count) { + puts (" { }"); + return; + } + puts (" {"); + for (int i = 0; i < ivars->ivar_count; i++) { + const char *name = ""; + const char *type = ""; + if (PR_StringValid (pr, ivars->ivar_list[i].ivar_name)) { + name = PR_GetString (pr, ivars->ivar_list[i].ivar_name); + } + if (PR_StringValid (pr, ivars->ivar_list[i].ivar_type)) { + type = PR_GetString (pr, ivars->ivar_list[i].ivar_type); + } + printf (" %d %s %s\n", ivars->ivar_list[i].ivar_offset, + name, type); + } + puts (" }"); +} + static void dump_methods (progs_t *pr, pr_method_list_t *methods, int class) { @@ -158,6 +181,7 @@ dump_class (progs_t *pr, pr_class_t *class) printf (" meta:%x verion:%d info:%u size:%d\n", class->class_pointer, class->version, class->info, class->instance_size); + dump_ivars (pr, &G_STRUCT (pr, pr_ivar_list_t, class->ivars)); dump_methods (pr, &G_STRUCT (pr, pr_method_list_t, class->methods), 0); dump_methods (pr, &G_STRUCT (pr, pr_method_list_t, meta->methods), 1); printf (" %x\n", class->protocols); From 204578772d7396ee4c76b4928fc3ed206fe21566 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Jun 2021 16:32:42 +0900 Subject: [PATCH 1559/3664] [gl] Move clearing to screen's render frame This allows 2d-only to be cleared properly. --- libs/video/renderer/gl/gl_rmain.c | 11 ----------- libs/video/renderer/gl/gl_screen.c | 11 +++++++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 3516603d8..81181619e 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -449,15 +449,6 @@ R_SetupGL (void) qfglShadeModel (GL_FLAT); } -static void -R_Clear (void) -{ - if (gl_clear->int_val) - qfglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - qfglClear (GL_DEPTH_BUFFER_BIT); -} - static void R_RenderScene (void) { @@ -580,8 +571,6 @@ R_RenderView_ (void) gl_mirror = false; - R_Clear (); - // render normal view R_RenderScene (); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 9c420cfb0..73e41a540 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -190,6 +190,15 @@ SCR_TileClear (void) } } +static void +R_Clear (void) +{ + if (gl_clear->int_val) + qfglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else + qfglClear (GL_DEPTH_BUFFER_BIT); +} + void gl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) { @@ -207,6 +216,8 @@ gl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) //update in sw modes but must in gl mode vr_data.scr_copyeverything = 1; + R_Clear (); + begun = 1; if (r_speeds->int_val) { From 3d42f986c36da9c73c525cc0d5c2ca9bd5b1f66d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Jun 2021 15:53:35 +0900 Subject: [PATCH 1560/3664] [qwaq] Add wrapper for wmove --- ruamoko/qwaq/builtins/curses.c | 38 ++++++++++++++++++++++++++++++++++ ruamoko/qwaq/ui/curses.h | 1 + ruamoko/qwaq/ui/textcontext.r | 1 + 3 files changed, 40 insertions(+) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 045ab9ae7..9e4b5269e 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -79,6 +79,7 @@ typedef enum qwaq_commands_e { qwaq_cmd_wbkgd, qwaq_cmd_werase, qwaq_cmd_scrollok, + qwaq_cmd_wmove, qwaq_cmd_move, qwaq_cmd_curs_set, qwaq_cmd_wborder, @@ -114,6 +115,7 @@ static const char *qwaq_command_names[]= { "wbkgd", "werase", "scrollok", + "wmove", "move", "curs_set", "wborder", @@ -538,6 +540,17 @@ cmd_scrollok (qwaq_resources_t *res) scrollok (window->win, flag); } +static void +cmd_wmove (qwaq_resources_t *res) +{ + int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int x = *RB_PEEK_DATA (res->command_queue, 3); + int y = *RB_PEEK_DATA (res->command_queue, 4); + + window_t *window = get_window (res, __FUNCTION__, window_id); + wmove (window->win, y, x); +} + static void cmd_move (qwaq_resources_t *res) { @@ -769,6 +782,9 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_scrollok: cmd_scrollok (res); break; + case qwaq_cmd_wmove: + cmd_wmove (res); + break; case qwaq_cmd_move: cmd_move (res); break; @@ -1532,6 +1548,27 @@ bi_scrollok (progs_t *pr) qwaq_scrollok (pr, window_id, flag); } +static void +qwaq_wmove (progs_t *pr, int window_id, int x, int y) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + if (get_window (res, __FUNCTION__, window_id)) { + int command[] = { qwaq_cmd_wmove, 0, window_id, x, y, }; + command[1] = CMD_SIZE(command); + qwaq_submit_command (res, command); + } +} +static void +bi_wmove (progs_t *pr) +{ + int window_id = P_INT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + + qwaq_wmove (pr, window_id, x, y); +} + static const char qwaq_acs_char_map[] = "lmkjtuvwqxnos`afg~,+.-hi0pryz{|}"; static void qwaq_acs_char (progs_t *pr, unsigned acs) @@ -1963,6 +2000,7 @@ static builtin_t builtins[] = { {"wbkgd", bi_wbkgd, -1}, {"werase", bi_werase, -1}, {"scrollok", bi_scrollok, -1}, + {"wmove", bi_wmove, -1}, {"acs_char", bi_acs_char, -1}, {"move", bi_move, -1}, {"curs_set", bi_curs_set, -1}, diff --git a/ruamoko/qwaq/ui/curses.h b/ruamoko/qwaq/ui/curses.h index 538157f58..6d57ded2a 100644 --- a/ruamoko/qwaq/ui/curses.h +++ b/ruamoko/qwaq/ui/curses.h @@ -120,6 +120,7 @@ int init_pair (int pair, int f, int b); void wbkgd (window_t win, int ch); void werase (window_t win); void scrollok (window_t win, int flag); +int wmove (window_t win, int x, int y); int acs_char (int acs); int curs_set (int visibility); diff --git a/ruamoko/qwaq/ui/textcontext.r b/ruamoko/qwaq/ui/textcontext.r index 9d05765d7..a14f04afd 100644 --- a/ruamoko/qwaq/ui/textcontext.r +++ b/ruamoko/qwaq/ui/textcontext.r @@ -198,6 +198,7 @@ int init_pair (int pair, int f, int b) = #0; void wbkgd (window_t win, int ch) = #0; void werase (window_t win) = #0; void scrollok (window_t win, int flag) = #0; +int wmove (window_t win, int x, int y) = #0; int acs_char (int acs) = #0; panel_t create_panel (window_t window) = #0; From 5e8376340db04d00a4aa85e66ff6b71ea24d24fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Jun 2021 15:56:20 +0900 Subject: [PATCH 1561/3664] [qwaq] Add method to get group's owning view --- ruamoko/qwaq/ui/group.h | 1 + ruamoko/qwaq/ui/group.r | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/ruamoko/qwaq/ui/group.h b/ruamoko/qwaq/ui/group.h index 2e8dcfa0c..52ee2af23 100644 --- a/ruamoko/qwaq/ui/group.h +++ b/ruamoko/qwaq/ui/group.h @@ -25,6 +25,7 @@ -insertDrawn: (View *) view; -insertSelected: (View *) view; -remove: (View *) view; +-(View *) owner; -(Rect) rect; -(Rect) absRect; -(Point) origin; diff --git a/ruamoko/qwaq/ui/group.r b/ruamoko/qwaq/ui/group.r index f76cf3c2a..05a3f344f 100644 --- a/ruamoko/qwaq/ui/group.r +++ b/ruamoko/qwaq/ui/group.r @@ -182,6 +182,11 @@ trySetFocus (Group *self, int viewIndex) return self; } +-(View *) owner +{ + return owner; +} + -(Rect) rect { if (owner) { From d36a75e3ded68f46f1d25059551f26d847679d70 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Jun 2021 15:56:57 +0900 Subject: [PATCH 1562/3664] [qwaq] Fix incorrect screen refresh Or, at least, I think it's incorrect, since stdscr (which was being refreshed) should not be used when using panels. --- ruamoko/qwaq/qwaq-app.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index 9520cf67e..ac00b32a1 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -70,7 +70,7 @@ arp_end (void) -draw { [objects draw]; - [TextContext refresh]; + [screen refresh]; return self; } From 48bf6fff13b4e4b964e3766b3ef4e7080333ef20 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Jun 2021 15:58:19 +0900 Subject: [PATCH 1563/3664] [qwaq] Get the cursor mostly working It's a little flakey with respect to redraws and changes of focus, but I think that's just updating the cursor state in more places. --- ruamoko/qwaq/ui/view.r | 58 ++++++++++++++++++++++++---------------- ruamoko/qwaq/ui/window.r | 8 ++++++ 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index 3e610cf72..c7fbe58c8 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -3,6 +3,7 @@ #include "ruamoko/qwaq/ui/group.h" #include "ruamoko/qwaq/ui/scrollbar.h" #include "ruamoko/qwaq/ui/view.h" +#include "ruamoko/qwaq/debugger/debug.h" @implementation View @@ -122,32 +123,41 @@ setScrollBar (View *self, ScrollBar **sb, ScrollBar *scrollbar) return self; } +-(window_t) window +{ + return nil; +} + +static void updateScreenCursor (View *view); + +-updateScreenCursor +{ + updateScreenCursor (self); + return self; +} + static void updateScreenCursor (View *view) { - // XXX this does not work -/* while ((view.state & sfInFocus) && view.owner) { - View *owner = (View *) view.owner; - if (view.cursor.x >= 0 && view.cursor.x < view.xlen - && view.cursor.y >= 0 && view.cursor.y < view.ylen) { - owner.cursor.x = view.cursor.x + view.xpos; - owner.cursor.y = view.cursor.y + view.ypos; - owner.cursorState = view.cursorState; - } else { - owner.cursorState = 0; - } - view = owner; - } - */ if (view.state & sfInFocus) { - if (view.cursorPos.x >= 0 && view.cursorPos.x < view.xlen - && view.cursorPos.y >= 0 && view.cursorPos.y < view.ylen) { - curs_set (view.cursorState); - move(view.cursorPos.x, view.cursorPos.y); + if (view.owner) { + View *owner = [view.owner owner]; + if (view.cursorPos.x >= 0 && view.cursorPos.x < view.xlen + && view.cursorPos.y >= 0 && view.cursorPos.y < view.ylen) { + owner.cursorPos.x = view.cursorPos.x + view.xpos; + owner.cursorPos.y = view.cursorPos.y + view.ypos; + owner.cursorState = view.cursorState; + } else { + owner.cursorState = 0; + } + [owner updateScreenCursor]; } else { - curs_set (0); } } +/* + curs_set (cursorState); + wmove (get_window (view), cursorPos.x, cursorPos.y); +*/ } -hideCursor @@ -164,7 +174,7 @@ updateScreenCursor (View *view) { cursorState = visible; if ((state & (sfInFocus | sfDrawn)) == (sfInFocus | sfDrawn)) { - updateScreenCursor (self); + [self updateScreenCursor]; } return self; } @@ -173,7 +183,7 @@ updateScreenCursor (View *view) { cursorPos = pos; if ((state & (sfInFocus | sfDrawn)) == (sfInFocus | sfDrawn)) { - updateScreenCursor (self); + [self updateScreenCursor]; } return self; } @@ -181,7 +191,7 @@ updateScreenCursor (View *view) -draw { state |= sfDrawn; - updateScreenCursor (self); + [self updateScreenCursor]; return self; } @@ -189,7 +199,7 @@ updateScreenCursor (View *view) { if (state & sfDrawn) { state &= ~sfDrawn; - updateScreenCursor (self); + [self updateScreenCursor]; } return self; } @@ -432,6 +442,7 @@ updateScreenCursor (View *view) -takeFocus { state |= sfInFocus; + [self updateScreenCursor]; [onReceiveFocus respond:self]; return self; } @@ -439,6 +450,7 @@ updateScreenCursor (View *view) -loseFocus { state &= ~sfInFocus; + [self updateScreenCursor]; [onReleaseFocus respond:self]; return self; } diff --git a/ruamoko/qwaq/ui/window.r b/ruamoko/qwaq/ui/window.r index b381f5f99..da29bd949 100644 --- a/ruamoko/qwaq/ui/window.r +++ b/ruamoko/qwaq/ui/window.r @@ -71,6 +71,14 @@ return self; } +-updateScreenCursor +{ + window_t window = [(id)textContext window]; + curs_set (cursorState); + wmove (window, cursorPos.x, cursorPos.y); + return self; +} + -setTitle:(string) title { [titleBar setTitle:title]; From 589200830687d0c42a14a2f3ce9f91d1ead1a58d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Jun 2021 16:05:32 +0900 Subject: [PATCH 1564/3664] [qwaq] Add char get/put/insert methods to EditBuffer --- ruamoko/qwaq/builtins/editbuffer.c | 49 +++++++++++++++++++++++++++++- ruamoko/qwaq/editor/editbuffer.h | 4 +++ ruamoko/qwaq/editor/editbuffer.r | 4 +++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index 666632944..ac2728904 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -810,6 +810,50 @@ bi_i_EditBuffer__readString_ (progs_t *pr) RETURN_STRING (pr, str); } +static void +bi_i_EditBuffer__getChar_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + if (ptr >= buffer->txtbuffer->textSize) { + PR_RunError (pr, "EditBuffer: character index out of bounds\n"); + } + R_INT (pr) = (byte) getChar (buffer->txtbuffer, ptr); +} + +static void +bi_i_EditBuffer__putChar_at_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + int chr = P_UINT (pr, 2); + unsigned ptr = P_UINT (pr, 3); + + if (ptr >= buffer->txtbuffer->textSize) { + PR_RunError (pr, "EditBuffer: character index out of bounds\n"); + } + buffer->txtbuffer->text[spanGap (buffer->txtbuffer, ptr)] = chr; +} + +static void +bi_i_EditBuffer__insertChar_at_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + char chr = P_UINT (pr, 2); + unsigned ptr = P_UINT (pr, 3); + + if (ptr > buffer->txtbuffer->textSize) { + PR_RunError (pr, "EditBuffer: character index out of bounds\n"); + } + TextBuffer_InsertAt (buffer->txtbuffer, ptr, &chr, 1); +} + static void bi_i_EditBuffer__countLines_ (progs_t *pr) { @@ -939,13 +983,16 @@ static builtin_t builtins[] = { {"_i_EditBuffer__getBOT", bi_i_EditBuffer__getBOT, -1}, {"_i_EditBuffer__getEOT", bi_i_EditBuffer__getEOT, -1}, {"_i_EditBuffer__readString_", bi_i_EditBuffer__readString_, -1}, + {"_i_EditBuffer__getChar_", bi_i_EditBuffer__getChar_, -1}, + {"_i_EditBuffer__putChar_at_", bi_i_EditBuffer__putChar_at_, -1}, + {"_i_EditBuffer__insertChar_at_", bi_i_EditBuffer__insertChar_at_,-1}, {"_i_EditBuffer__countLines_", bi_i_EditBuffer__countLines_, -1}, {"_i_EditBuffer__search_for_direction_", bi_i_EditBuffer__search_for_direction_, -1}, {"_i_EditBuffer__isearch_for_direction_", bi_i_EditBuffer__isearch_for_direction_,-1}, {"_i_EditBuffer__formatLine_from_into_width_highlight_colors_", - bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_, -1}, + bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_, -1}, {"_i_EditBuffer__modified", bi_i_EditBuffer__modified, -1}, {"_i_EditBuffer__textSize", bi_i_EditBuffer__textSize, -1}, {"_i_EditBuffer__saveFile_", bi_i_EditBuffer__saveFile_, -1}, diff --git a/ruamoko/qwaq/editor/editbuffer.h b/ruamoko/qwaq/editor/editbuffer.h index a1bfae616..e57491e80 100644 --- a/ruamoko/qwaq/editor/editbuffer.h +++ b/ruamoko/qwaq/editor/editbuffer.h @@ -50,7 +50,11 @@ typedef struct eb_color_s { - (unsigned) getEOL: (unsigned) linePtr; - (unsigned) getBOT; - (unsigned) getEOT; + - (string) readString: (eb_sel_t) selection; +- (int) getChar: (unsigned) charPtr; +- (void) putChar: (int) char at:(unsigned) charPtr; +- (void) insertChar: (int) char at:(unsigned) charPtr; - (unsigned) countLines: (eb_sel_t) selection; - (eb_sel_t) search: (eb_sel_t) selection diff --git a/ruamoko/qwaq/editor/editbuffer.r b/ruamoko/qwaq/editor/editbuffer.r index cd7644f7d..b3d7a6fe9 100644 --- a/ruamoko/qwaq/editor/editbuffer.r +++ b/ruamoko/qwaq/editor/editbuffer.r @@ -36,7 +36,11 @@ - (unsigned) getEOL: (unsigned) linePtr = #0; - (unsigned) getBOT = #0; - (unsigned) getEOT = #0; + - (string) readString: (eb_sel_t) selection = #0; +- (int) getChar: (unsigned) charPtr = #0; +- (void) putChar: (int) char at:(unsigned) charPtr = #0; +- (void) insertChar: (int) char at:(unsigned) charPtr = #0; - (unsigned) countLines: (eb_sel_t) selection = #0; - (eb_sel_t) search: (eb_sel_t) selection From 551236511d748ce108564df16b5095701ab37db3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Jun 2021 16:20:15 +0900 Subject: [PATCH 1565/3664] [qwaq] Make the editor show the cursor As well as showing the cursor, it keeps the cursor's position up to date (for now, just at 0,y as only gotoLine is implemented, no cursor motion yet) --- ruamoko/qwaq/editor/editor.r | 37 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index 62158dfe9..f34610ff4 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -19,6 +19,7 @@ growMode = gfGrowHi; options = ofCanFocus | ofRelativeEvents; [onViewScrolled addListener:self :@selector(onScroll:)]; + [self setCursorVisible:1]; return self; } @@ -63,7 +64,8 @@ return self; } -static int handleEvent (Editor *self, qwaq_event_t *event) +static int +handleEvent (Editor *self, qwaq_event_t *event) { if (event.what & qe_mouse) { if (event.what == qe_mouseclick) { @@ -159,6 +161,7 @@ static int handleEvent (Editor *self, qwaq_event_t *event) base_index = [buffer prevLine:base_index :base.y - target]; } base.y = target; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; return self; } @@ -178,19 +181,27 @@ static int handleEvent (Editor *self, qwaq_event_t *event) -recenter:(int) force { - if (!force) { - if (cursor.y >= base.y && cursor.y - base.y < ylen) { - return self; + if (force || cursor.y < base.y || cursor.y - base.y >= ylen) { + unsigned target; + if (cursor.y < ylen / 2) { + target = 0; + } else { + target = cursor.y - ylen / 2; + } + [self scrollTo:target]; + } + return self; +} + +static void +trackCursor (Editor *self) +{ + unsigned cx = [self.buffer charPos:self.line_index at:self.char_index]; + if (self.cursor.x != cx) { + if (self.char_index < [self.buffer getEOT]) { + int c = [self.buffer getChar:self.char_index]; } } - unsigned target; - if (cursor.y < ylen / 2) { - target = 0; - } else { - target = cursor.y - ylen / 2; - } - [self scrollTo:target]; - return self; } -gotoLine:(unsigned) line @@ -201,7 +212,9 @@ static int handleEvent (Editor *self, qwaq_event_t *event) line_index = [buffer prevLine:line_index :cursor.y - line]; } cursor.y = line; + char_index = [buffer charPtr:line_index at:cursor.x]; [self recenter: 0]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; return self; } From 1f6a4ed9416891e416dc00468586fa64f9761e9d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Jun 2021 22:21:48 +0900 Subject: [PATCH 1566/3664] [qwaq] Implement cursor motion in the editor Basic arrow key motion, and it's currently limited to not scrolling horizontally (need to figure out how to handle max scroll), but this also fixes the cursor handling on focus switching :) --- ruamoko/qwaq/editor/editor.h | 4 ++ ruamoko/qwaq/editor/editor.r | 72 +++++++++++++++++++++++++++++++++++- ruamoko/qwaq/ui/window.r | 1 + 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index cd04f8a8e..ec46a6bc0 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -28,6 +28,10 @@ -scrollDown:(unsigned) count; -scrollLeft:(unsigned) count; -scrollRight:(unsigned) count; +-cursorUp:(unsigned) count; +-cursorDown:(unsigned) count; +-cursorLeft:(unsigned) count; +-cursorRight:(unsigned) count; -recenter:(int) force; -gotoLine:(unsigned) line; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index f34610ff4..65ea134a1 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -94,6 +94,18 @@ handleEvent (Editor *self, qwaq_event_t *event) case QFK_PAGEDOWN: [self scrollDown: self.ylen]; return 1; + case QFK_UP: + [self cursorUp: 1]; + return 1; + case QFK_DOWN: + [self cursorDown: 1]; + return 1; + case QFK_LEFT: + [self cursorLeft: 1]; + return 1; + case QFK_RIGHT: + [self cursorRight: 1]; + return 1; } } return 0; @@ -139,6 +151,7 @@ handleEvent (Editor *self, qwaq_event_t *event) base.x = 0; } [self redraw]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; return self; } @@ -150,6 +163,7 @@ handleEvent (Editor *self, qwaq_event_t *event) base.x = 1024; } [self redraw]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; return self; } @@ -161,6 +175,60 @@ handleEvent (Editor *self, qwaq_event_t *event) base_index = [buffer prevLine:base_index :base.y - target]; } base.y = target; + [vScrollBar setIndex:base.y]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + +-cursorUp:(unsigned)count +{ + if (count > cursor.y) { + count = cursor.y; + } + cursor.y -= count; + if (base.y > cursor.y) { + [vScrollBar setIndex:cursor.y]; + } + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + +-cursorDown:(unsigned)count +{ + if (count > line_count - cursor.y) { + count = line_count - cursor.y; + } + cursor.y += count; + if (base.y + ylen - 1 < cursor.y) { + [vScrollBar setIndex:cursor.y + 1 - ylen]; + } + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + +-cursorLeft:(unsigned)count +{ + if (count > cursor.x) { + count = cursor.x; + } + cursor.x -= count; + if (base.x > cursor.x) { + [hScrollBar setIndex:cursor.x]; + } + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + +-cursorRight:(unsigned)count +{ + // FIXME handle horizontal scrolling and how to deal with max scroll + cursor.x += count; + if (base.x + xlen - 1 < cursor.x) { + [hScrollBar setIndex:cursor.x + 1 - xlen]; + } + if (base.x + xlen - 1 < cursor.x) { + cursor.x = base.x + xlen - 1; + } [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; return self; } @@ -168,7 +236,9 @@ handleEvent (Editor *self, qwaq_event_t *event) -(void)onScroll:(id)sender { base.x = scroll.x; - [self scrollTo:scroll.y]; + if (base.y != scroll.y) { + [self scrollTo:scroll.y]; + } } -setVerticalScrollBar:(ScrollBar *)scrollbar diff --git a/ruamoko/qwaq/ui/window.r b/ruamoko/qwaq/ui/window.r index da29bd949..b8faf2aba 100644 --- a/ruamoko/qwaq/ui/window.r +++ b/ruamoko/qwaq/ui/window.r @@ -76,6 +76,7 @@ window_t window = [(id)textContext window]; curs_set (cursorState); wmove (window, cursorPos.x, cursorPos.y); + [[TextContext screen] refresh]; return self; } From c06acd3b53110c106fe7c9a75d39251b67da3252 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Jun 2021 16:48:24 +0900 Subject: [PATCH 1567/3664] [qwaq] Update line and char indices with cursor motion --- ruamoko/qwaq/editor/editor.r | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index 65ea134a1..a3c37a8fc 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -182,10 +182,13 @@ handleEvent (Editor *self, qwaq_event_t *event) -cursorUp:(unsigned)count { + [self recenter:0]; if (count > cursor.y) { count = cursor.y; } cursor.y -= count; + line_index = [buffer prevLine:line_index :count]; + char_index = [buffer charPtr:line_index at:cursor.x]; if (base.y > cursor.y) { [vScrollBar setIndex:cursor.y]; } @@ -195,10 +198,13 @@ handleEvent (Editor *self, qwaq_event_t *event) -cursorDown:(unsigned)count { + [self recenter:0]; if (count > line_count - cursor.y) { count = line_count - cursor.y; } cursor.y += count; + line_index = [buffer nextLine:line_index :count]; + char_index = [buffer charPtr:line_index at:cursor.x]; if (base.y + ylen - 1 < cursor.y) { [vScrollBar setIndex:cursor.y + 1 - ylen]; } @@ -208,10 +214,12 @@ handleEvent (Editor *self, qwaq_event_t *event) -cursorLeft:(unsigned)count { + [self recenter:0]; if (count > cursor.x) { count = cursor.x; } cursor.x -= count; + char_index = [buffer charPtr:line_index at:cursor.x]; if (base.x > cursor.x) { [hScrollBar setIndex:cursor.x]; } @@ -221,8 +229,10 @@ handleEvent (Editor *self, qwaq_event_t *event) -cursorRight:(unsigned)count { + [self recenter:0]; // FIXME handle horizontal scrolling and how to deal with max scroll cursor.x += count; + char_index = [buffer charPtr:line_index at:cursor.x]; if (base.x + xlen - 1 < cursor.x) { [hScrollBar setIndex:cursor.x + 1 - xlen]; } @@ -283,7 +293,7 @@ trackCursor (Editor *self) } cursor.y = line; char_index = [buffer charPtr:line_index at:cursor.x]; - [self recenter: 0]; + [self recenter:0]; [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; return self; } From c818a2abf9fd25681e146e2125b710e6476bb183 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Jun 2021 16:50:30 +0900 Subject: [PATCH 1568/3664] [qwaq] Support base filename and cursor fetching Getting the base filename and the current cursor position is needed for execute-to-line support in the debugger. --- ruamoko/qwaq/editor/editor.h | 4 ++++ ruamoko/qwaq/editor/editor.r | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index ec46a6bc0..8f86ef8d7 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -21,9 +21,13 @@ Point cursor; unsigned line_count; string filename; + string filepath; } +(Editor *)withRect:(Rect)rect file:(string)filename; ++(Editor *)withRect:(Rect)rect file:(string)filename path:(string)filepath; -(string)filename; +-(string)filepath; +-(Point)cursor; -scrollUp:(unsigned) count; -scrollDown:(unsigned) count; -scrollLeft:(unsigned) count; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index a3c37a8fc..75f786b9d 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -7,13 +7,18 @@ @implementation Editor --initWithRect:(Rect) rect file:(string) filename +-initWithRect:(Rect) rect file:(string) filename path:(string) filepath { if (!(self = [super initWithRect: rect])) { return nil; } self.filename = str_hold (filename); - buffer = [[EditBuffer withFile:filename] retain]; + if (filepath != filename) { + self.filepath = str_hold (filepath); + } else { + self.filepath = filename; + } + buffer = [[EditBuffer withFile:filepath] retain]; line_count = [buffer countLines: {0, [buffer textSize]}]; linebuffer = [[DrawBuffer buffer: { xlen, 1 }] retain]; growMode = gfGrowHi; @@ -25,11 +30,23 @@ +(Editor *)withRect:(Rect)rect file:(string)filename { - return [[[self alloc] initWithRect:rect file:filename] autorelease]; + return [[[self alloc] initWithRect:rect + file:filename + path:filename] autorelease]; +} + ++(Editor *)withRect:(Rect)rect file:(string)filename path:(string)filepath +{ + return [[[self alloc] initWithRect:rect + file:filename + path:filepath] autorelease]; } -(void)dealloc { + if (filepath != filename) { + str_free (filepath); + } str_free (filename); [vScrollBar release]; [buffer release]; @@ -42,6 +59,16 @@ return filename; } +-(string)filepath +{ + return filepath; +} + +-(Point)cursor +{ + return cursor; +} + -draw { [super draw]; From d23c9582f193c8ad77445035d5575327c27d3f95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Jun 2021 16:54:04 +0900 Subject: [PATCH 1569/3664] [qwaq] Implement execute-to-cursor Support for finding the first address associated with a source line was added to the engine, returning 0 if not found. A temporary breakpoint is set and the progs allowed to run free. However, better handling of temporary breakpoitns is needed as currently a "permanent" breakpoint will be cleared without clearing the temporary breakpoing if the permanent breakpoing is hit while execut-to-cursor is running. --- include/QF/progs.h | 1 + libs/gamecode/pr_debug.c | 94 +++++++++++++++++++++++++++++++- ruamoko/qwaq/builtins/debug.c | 17 +++++- ruamoko/qwaq/debugger/debug.h | 3 +- ruamoko/qwaq/debugger/debug.r | 2 + ruamoko/qwaq/debugger/debugger.h | 1 + ruamoko/qwaq/debugger/debugger.r | 40 +++++++++++++- ruamoko/qwaq/gcd.r | 1 - 8 files changed, 152 insertions(+), 7 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index fd36c0c62..7ccb962d2 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1742,6 +1742,7 @@ pr_auxfunction_t *PR_Get_Lineno_Func (progs_t *pr, pr_lineno_t *lineno) __attrib pr_uint_t PR_Get_Lineno_Addr (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); pr_uint_t PR_Get_Lineno_Line (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); pr_lineno_t *PR_Find_Lineno (progs_t *pr, pr_uint_t addr) __attribute__((pure)); +pr_uint_t PR_FindSourceLineAddr (progs_t *pr, const char *file, pr_uint_t line) __attribute__((pure)); const char *PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); const char *PR_Get_Source_Line (progs_t *pr, pr_uint_t addr); pr_def_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) __attribute__((pure)); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 3ef208442..906ec185f 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -31,6 +31,8 @@ # include "config.h" #endif +#define _GNU_SOURCE // for qsort_r + #ifdef HAVE_STRING_H # include #endif @@ -41,6 +43,7 @@ #include #include +#include "QF/fbsearch.h" #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" @@ -75,6 +78,11 @@ typedef struct compunit_s { pr_compunit_t *unit; } compunit_t; +typedef struct { + const char *file; + pr_uint_t line; +} func_key_t; + typedef struct prdeb_resources_s { progs_t *pr; dstring_t *string; @@ -85,6 +93,7 @@ typedef struct prdeb_resources_s { pr_debug_header_t *debug; pr_auxfunction_t *auxfunctions; pr_auxfunction_t **auxfunction_map; + func_t *sorted_functions; pr_lineno_t *linenos; pr_def_t *local_defs; pr_def_t *type_encodings_def; @@ -379,6 +388,9 @@ pr_debug_clear (progs_t *pr, void *data) if (res->auxfunction_map) pr->free_progs_mem (pr, res->auxfunction_map); res->auxfunction_map = 0; + if (res->sorted_functions) + pr->free_progs_mem (pr, res->sorted_functions); + res->sorted_functions = 0; res->linenos = 0; res->local_defs = 0; @@ -478,6 +490,43 @@ process_compunit (prdeb_resources_t *res, pr_def_t *def) } } +static int +func_compare_sort (const void *_fa, const void *_fb, void *_res) +{ + prdeb_resources_t *res = _res; + progs_t *pr = res->pr; + func_t fa = *(const func_t *)_fa; + func_t fb = *(const func_t *)_fb; + const char *fa_file = PR_GetString (pr, pr->pr_functions[fa].s_file); + const char *fb_file = PR_GetString (pr, pr->pr_functions[fb].s_file); + int cmp = strcmp (fa_file, fb_file); + if (cmp) { + return cmp; + } + pr_auxfunction_t *fa_aux = res->auxfunction_map[fa]; + pr_auxfunction_t *fb_aux = res->auxfunction_map[fb]; + pr_uint_t fa_line = fa_aux ? fa_aux->source_line : 0; + pr_uint_t fb_line = fb_aux ? fb_aux->source_line : 0; + return fa_line - fb_line; +} + +static int +func_compare_search (const void *_key, const void *_f, void *_res) +{ + prdeb_resources_t *res = _res; + progs_t *pr = res->pr; + const func_key_t *key = _key; + func_t f = *(const func_t *)_f; + const char *f_file = PR_GetString (pr, pr->pr_functions[f].s_file); + int cmp = strcmp (key->file, f_file); + if (cmp) { + return cmp; + } + pr_auxfunction_t *f_aux = res->auxfunction_map[f]; + pr_uint_t f_line = f_aux ? f_aux->source_line : 0; + return key->line - f_line; +} + VISIBLE int PR_LoadDebug (progs_t *pr) { @@ -562,8 +611,12 @@ PR_LoadDebug (progs_t *pr) i = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); res->auxfunction_map = pr->allocate_progs_mem (pr, i); - for (i = 0; i < pr->progs->numfunctions; i++) + i = pr->progs->numfunctions * sizeof (func_t); + res->sorted_functions = pr->allocate_progs_mem (pr, i); + for (i = 0; i < pr->progs->numfunctions; i++) { res->auxfunction_map[i] = 0; + res->sorted_functions[i] = i; + } res->type_encodings_def = PR_FindGlobal (pr, ".type_encodings"); if (res->type_encodings_def) { @@ -593,6 +646,8 @@ PR_LoadDebug (progs_t *pr) res->linenos[i].fa.func = LittleLong (res->linenos[i].fa.func); res->linenos[i].line = LittleLong (res->linenos[i].line); } + qsort_r (res->sorted_functions, pr->progs->numfunctions, sizeof (func_t), + func_compare_sort, res); for (i = 0; i < res->debug->num_locals; i++) { byteswap_def (&res->local_defs[i]); if (type_encodings) { @@ -752,6 +807,43 @@ PR_Find_Lineno (progs_t *pr, pr_uint_t addr) return lineno; } +pr_uint_t +PR_FindSourceLineAddr (progs_t *pr, const char *file, pr_uint_t line) +{ + prdeb_resources_t *res = pr->pr_debug_resources; + func_key_t key = { file, line }; + func_t *f = fbsearch_r (&key, res->sorted_functions, + pr->progs->numfunctions, sizeof (func_t), + func_compare_search, res); + if (!f) { + return 0; + } + dfunction_t *func = &pr->pr_functions[*f]; + if (func->first_statement <= 0 + || strcmp (file, PR_GetString (pr, func->s_file)) != 0) { + return 0; + } + pr_auxfunction_t *aux = res->auxfunction_map[*f]; + if (!aux) { + return 0; + } + pr_uint_t addr = func->first_statement; + line -= aux->source_line; + + //FIXME put lineno count in sym file + for (pr_uint_t i = aux->line_info + 1; i < res->debug->num_linenos; i++) { + if (!res->linenos[i].line) { + break; + } + if (res->linenos[i].line <= line) { + addr = res->linenos[i].fa.addr; + } else { + break; + } + } + return addr; +} + const char * PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) { diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index fe6796b46..5d6c598ed 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -225,8 +225,9 @@ qdb_set_breakpoint (progs_t *pr) R_INT (pr) = -1; return; } + int set = (tpr->pr_statements[staddr].op & OP_BREAK) != 0; tpr->pr_statements[staddr].op |= OP_BREAK; - R_INT (pr) = 0; + R_INT (pr) = set; } static void @@ -619,6 +620,19 @@ qdb_get_local_defs (progs_t *pr) } } +static void +qdb_get_source_line_addr (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + const char *file = P_GSTRING (pr, 1); + pr_uint_t line = P_UINT (pr, 2); + + R_UINT (pr) = PR_FindSourceLineAddr (tpr, file, line); +} + static builtin_t builtins[] = { {"qdb_set_trace", qdb_set_trace, -1}, {"qdb_set_breakpoint", qdb_set_breakpoint, -1}, @@ -641,6 +655,7 @@ static builtin_t builtins[] = { {"qdb_find_auxfunction", qdb_find_auxfunction, -1}, {"qdb_get_auxfunction", qdb_get_auxfunction, -1}, {"qdb_get_local_defs", qdb_get_local_defs, -1}, + {"qdb_get_source_line_addr", qdb_get_source_line_addr, -1}, {} }; diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index f6f58f5ed..2e68de316 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -95,7 +95,8 @@ qdb_function_t *qdb_get_function (qdb_target_t target, unsigned fnum); qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, string name); qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, unsigned fnum); qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum); - +unsigned qdb_get_source_line_addr(qdb_target_t target, string file, + unsigned line); void traceon(); void traceoff(); diff --git a/ruamoko/qwaq/debugger/debug.r b/ruamoko/qwaq/debugger/debug.r index feb8adbdd..70126f7a2 100644 --- a/ruamoko/qwaq/debugger/debug.r +++ b/ruamoko/qwaq/debugger/debug.r @@ -27,3 +27,5 @@ qdb_auxfunction_t *qdb_find_auxfunction (qdb_target_t target, qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, unsigned fnum) = #0; qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum) = #0; +unsigned qdb_get_source_line_addr(qdb_target_t target, string file, + unsigned line) = #0; diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 8694d06c0..46c9cbeda 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -28,6 +28,7 @@ int onExit; } sub_cond; SEL traceHandler; + SEL breakHandler; int running; Window *source_window; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index 3acf1707e..aabb06889 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -53,17 +53,17 @@ -(Editor *) find_file:(string) filename { Editor *file; - filename = qdb_get_file_path (target, filename); + string filepath = qdb_get_file_path (target, filename); for (int i = [files count]; i-- > 0; ) { file = [files objectAtIndex: i]; - if ([file filename] == filename) { + if ([file filepath] == filepath) { return file; } } Rect rect = {{1, 1}, [source_window size]}; rect.extent.width -= 2; rect.extent.height -= 2; - file = [Editor withRect:rect file:filename]; + file = [Editor withRect:rect file:filename path:filepath]; [files addObject: file]; return file; } @@ -154,6 +154,27 @@ proxy_event_stopped (Debugger *self, id proxy, qwaq_event_t *event) self.running = 1; qdb_continue (self.target); return 1; + case QFK_F4: + string file = [self.current_file filename]; + unsigned line = [self.current_file cursor].y + 1; + unsigned addr = qdb_get_source_line_addr (self.target, + file, line); + int set = -1; + if (addr) { + set = qdb_set_breakpoint (self.target, addr); + } + if (set >= 0) { + qdb_set_trace (self.target, 0); + if (set) { + self.breakHandler = @selector(breakKeep); + } else { + self.breakHandler = @selector(breakClear); + } + self.running = 1; + qdb_continue (self.target); + } else { + } + return 1; } } return 0; @@ -236,6 +257,18 @@ is_new_line (qdb_state_t last_state, qdb_state_t state) return self; } +-breakKeep +{ + return self; +} + +-breakClear +{ + qdb_state_t state = qdb_get_state (target); + qdb_clear_breakpoint (target, state.staddr); + return self; +} + -handleDebugEvent { if (qdb_get_event (target, &event)) { @@ -247,6 +280,7 @@ is_new_line (qdb_state_t last_state, qdb_state_t state) break; case prd_breakpoint: case prd_watchpoint: + [self performSelector:breakHandler]; [self stop:event.what]; break; case prd_subenter: diff --git a/ruamoko/qwaq/gcd.r b/ruamoko/qwaq/gcd.r index bfa3a5e84..a01cce830 100644 --- a/ruamoko/qwaq/gcd.r +++ b/ruamoko/qwaq/gcd.r @@ -13,7 +13,6 @@ gcd (int a, int b) int main (int argc, string *argv) { - traceon (); x = 130; y = 120; printf ("%d\n", gcd (x, y)); From 2a38135dd9aab73f095191dee0e2bdd09f8f24f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Jun 2021 08:33:50 +0900 Subject: [PATCH 1570/3664] [qwaq] Fix scrollbar thumbtab covering button Caused by an out-by-one error. --- ruamoko/qwaq/ui/scrollbar.r | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index 253d25911..8bb14c0b7 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -113,9 +113,9 @@ position_tab (ScrollBar *self) Point o = [self.thumbTab origin]; if (self.range > 0) { if (self.vertical) { - p.y = 1 + self.index * (self.ylen - 2) / (self.range - 1); + p.y = 1 + self.index * (self.ylen - 3) / (self.range - 1); } else { - p.x = 1 + self.index * (self.xlen - 2) / (self.range - 1); + p.x = 1 + self.index * (self.xlen - 3) / (self.range - 1); } } [self.thumbTab move:{p.x - o.x, p.y - o.y}]; From 927a446bd3e3867df746f3049a28cfd5c6592135 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Jun 2021 12:08:13 +0900 Subject: [PATCH 1571/3664] [qfcc] Ensure type src type is a class If the src type is not a class, there is no inheritance chain to walk. Fixes a segfault when returning self after a syntax error in the following: +(EditStatus *)withRect:(Rect)rect { return [[[self alloc] initWithRect:rect]: } -setCursorMode:(CursorMode)mode { cursorMode = mode; return self; } --- tools/qfcc/source/class.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index ddef199fa..b61be1d26 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -455,7 +455,7 @@ category_implements (category_t *cat, protocol_t *protocol) int obj_types_assignable (const type_t *dst, const type_t *src) { - class_t *dst_class, *src_class; + class_t *dst_class, *src_class = 0; category_t *cat; int dst_is_proto, src_is_proto; protocollist_t *dst_protos = 0, *src_protos = 0; @@ -507,7 +507,9 @@ obj_types_assignable (const type_t *dst, const type_t *src) // check dst is a base class of src dst_class = dst->t.fldptr.type->t.class; - src_class = src->t.fldptr.type->t.class; + if (src->t.fldptr.type->meta == ty_class) { + src_class = src->t.fldptr.type->t.class; + } //printf ("%s %s\n", dst_class->name, src_class->name); while (dst_class != src_class && src_class) { src_class = src_class->super_class; From 055ea46337fd52a867c9392d3d8a768c4013a972 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Jun 2021 12:13:55 +0900 Subject: [PATCH 1572/3664] [qwaq] Fix page up/down and deal with tabs --- ruamoko/qwaq/Makemodule.am | 2 + ruamoko/qwaq/debugger/debugger.h | 2 + ruamoko/qwaq/debugger/debugger.r | 5 + ruamoko/qwaq/editor/editor.h | 19 +++- ruamoko/qwaq/editor/editor.r | 152 +++++++++++++++++++++++++------ ruamoko/qwaq/editor/status.h | 23 +++++ ruamoko/qwaq/editor/status.r | 43 +++++++++ 7 files changed, 216 insertions(+), 30 deletions(-) create mode 100644 ruamoko/qwaq/editor/status.h create mode 100644 ruamoko/qwaq/editor/status.r diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 8b2d29419..378eb8505 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -27,6 +27,7 @@ qwaq_app_dat_src= \ ruamoko/qwaq/debugger/typeencodings.r \ ruamoko/qwaq/editor/editbuffer.r \ ruamoko/qwaq/editor/editor.r \ + ruamoko/qwaq/editor/status.r \ ruamoko/qwaq/ui/button.r \ ruamoko/qwaq/ui/draw.r \ ruamoko/qwaq/ui/garray.r \ @@ -124,6 +125,7 @@ EXTRA_DIST += \ ruamoko/qwaq/debugger/views/voidview.h \ ruamoko/qwaq/editor/editbuffer.h \ ruamoko/qwaq/editor/editor.h \ + ruamoko/qwaq/editor/status.h \ ruamoko/qwaq/qwaq-app.h \ ruamoko/qwaq/qwaq.h \ ruamoko/qwaq/ui/button.h \ diff --git a/ruamoko/qwaq/debugger/debugger.h b/ruamoko/qwaq/debugger/debugger.h index 46c9cbeda..64dce073c 100644 --- a/ruamoko/qwaq/debugger/debugger.h +++ b/ruamoko/qwaq/debugger/debugger.h @@ -9,6 +9,7 @@ @class ProxyView; @class Editor; +@class EditStatus; @class ScrollBar; @class Window; @class Array; @@ -33,6 +34,7 @@ Window *source_window; ScrollBar *source_scrollbar; + EditStatus *source_status; ProxyView *file_proxy; Array *files; Editor *current_file; diff --git a/ruamoko/qwaq/debugger/debugger.r b/ruamoko/qwaq/debugger/debugger.r index aabb06889..6afa14e84 100644 --- a/ruamoko/qwaq/debugger/debugger.r +++ b/ruamoko/qwaq/debugger/debugger.r @@ -40,6 +40,9 @@ source_scrollbar = [ScrollBar vertical:s.height - 2 at:{s.width - 1, 1}]; [source_window insert:source_scrollbar]; + source_status = [EditStatus withRect:{{1, 0}, {2, 1}}]; + [source_window insert:source_status]; + return self; } @@ -77,6 +80,7 @@ [[current_file gotoLine:state.line - 1] highlightLine]; [[current_file onEvent] addListener: self :@selector(proxy_event::)]; [current_file setVerticalScrollBar:source_scrollbar]; + [current_file setStatusView:source_status]; //FIXME id? [source_window insertSelected: (View *) file_proxy]; [source_window setTitle:[current_file filename]]; @@ -111,6 +115,7 @@ [file_proxy setView:file]; [[file onEvent] addListener:self :@selector(proxy_event::)]; [file setVerticalScrollBar:source_scrollbar]; + [file setStatusView:source_status]; [source_window setTitle:[file filename]]; current_file = file; } diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index 8f86ef8d7..a30b2546d 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -2,15 +2,18 @@ #define __qwaq_editor_editor_h #include "ruamoko/qwaq/editor/editbuffer.h" +#include "ruamoko/qwaq/editor/status.h" #include "ruamoko/qwaq/ui/view.h" @class Editor; @class EditBuffer; @class ListenerGroup; +@class EditStatus; @interface Editor : View { EditBuffer *buffer; + EditStatus *status; DrawBuffer *linebuffer; eb_sel_t selection; unsigned base_index; // top left corner @@ -22,20 +25,28 @@ unsigned line_count; string filename; string filepath; + int modified; + CursorMode cursorMode; + + int virtualInsert; + int cursorThroughTabs; } +(Editor *)withRect:(Rect)rect file:(string)filename; +(Editor *)withRect:(Rect)rect file:(string)filename path:(string)filepath; -(string)filename; -(string)filepath; -(Point)cursor; +-setStatusView:(EditStatus *)status; -scrollUp:(unsigned) count; -scrollDown:(unsigned) count; -scrollLeft:(unsigned) count; -scrollRight:(unsigned) count; --cursorUp:(unsigned) count; --cursorDown:(unsigned) count; --cursorLeft:(unsigned) count; --cursorRight:(unsigned) count; +-pageUp; +-pageDown; +-charUp; +-charDown; +-charLeft; +-charRight; -recenter:(int) force; -gotoLine:(unsigned) line; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index 75f786b9d..fc5a69993 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -25,6 +25,7 @@ options = ofCanFocus | ofRelativeEvents; [onViewScrolled addListener:self :@selector(onScroll:)]; [self setCursorVisible:1]; + return self; } @@ -69,6 +70,45 @@ return cursor; } +-setStatusView:(EditStatus *)status +{ + self.status = status; + [status setModified:modified]; + [status setCursorMode:cursorMode]; + [status redraw]; + return self; +} + +-trackCursor:(int)fwd +{ + unsigned tx = [buffer charPos:line_index at:char_index]; + + cursorMode &= ~cmVInsert; + if (tx != cursor.x) { + if (char_index < [buffer getEOT]) { + int c = [buffer getChar:char_index]; + + if (virtualInsert) { + if (c != '\t' || cursorThroughTabs) { + cursorMode |= cmVInsert; + goto done; + } + } + if (c == '\t' && fwd) { + tx = [buffer charPos:line_index at:++char_index]; + } + } else if (virtualInsert) { + cursorMode |= cmVInsert; + goto done; + } + cursor.x = tx; + } +done: + [status setCursorMode:cursorMode]; + [status redraw]; + return self; +} + -draw { [super draw]; @@ -116,22 +156,22 @@ handleEvent (Editor *self, qwaq_event_t *event) } else if (event.what == qe_keydown) { switch (event.key.code) { case QFK_PAGEUP: - [self scrollUp: self.ylen]; + [self pageUp]; return 1; case QFK_PAGEDOWN: - [self scrollDown: self.ylen]; + [self pageDown]; return 1; case QFK_UP: - [self cursorUp: 1]; + [self charUp]; return 1; case QFK_DOWN: - [self cursorDown: 1]; + [self charDown]; return 1; case QFK_LEFT: - [self cursorLeft: 1]; + [self charLeft]; return 1; case QFK_RIGHT: - [self cursorRight: 1]; + [self charRight]; return 1; } } @@ -150,23 +190,35 @@ handleEvent (Editor *self, qwaq_event_t *event) -scrollUp:(unsigned) count { + unsigned index; + unsigned lines; if (count == 1) { - base_index = [buffer prevLine: base_index]; + index = [buffer prevLine: base_index]; } else { - base_index = [buffer prevLine: base_index :count]; + index = [buffer prevLine: base_index :count]; } + lines = [buffer countLines: {index, base_index - index}]; + base.y -= lines; + base_index = index; [self redraw]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; return self; } -scrollDown:(unsigned) count { + unsigned index; + unsigned lines; if (count == 1) { - base_index = [buffer nextLine: base_index]; + index = [buffer nextLine: base_index]; } else { - base_index = [buffer nextLine: base_index :count]; + index = [buffer nextLine: base_index :count]; } + lines = [buffer countLines: {base_index, index - base_index}]; + base.y += lines; + base_index = index; [self redraw]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; return self; } @@ -207,15 +259,57 @@ handleEvent (Editor *self, qwaq_event_t *event) return self; } --cursorUp:(unsigned)count +-pageUp { [self recenter:0]; - if (count > cursor.y) { - count = cursor.y; + unsigned count = cursor.y; + + if (count > ylen) { + count = ylen; } - cursor.y -= count; - line_index = [buffer prevLine:line_index :count]; + if (count) { + cursor.y -= count; + [vScrollBar setIndex:[vScrollBar index] - count]; + line_index = [buffer prevLine:line_index :count]; + char_index = [buffer charPtr:line_index at:cursor.x]; + [self trackCursor:1]; + + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + } + return self; +} + +-pageDown +{ + [self recenter:0]; + unsigned count = line_count - cursor.y; + + if (count > ylen) { + count = ylen; + } + if (count) { + cursor.y += count; + [vScrollBar setIndex:[vScrollBar index] + count]; + line_index = [buffer nextLine:line_index :count]; + char_index = [buffer charPtr:line_index at:cursor.x]; + [self trackCursor:1]; + + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + } + return self; +} + +-charUp +{ + [self recenter:0]; + if (cursor.y < 1) { + return self; + } + cursor.y--; + line_index = [buffer prevLine:line_index :1]; char_index = [buffer charPtr:line_index at:cursor.x]; + [self trackCursor:1]; + if (base.y > cursor.y) { [vScrollBar setIndex:cursor.y]; } @@ -223,15 +317,17 @@ handleEvent (Editor *self, qwaq_event_t *event) return self; } --cursorDown:(unsigned)count +-charDown { [self recenter:0]; - if (count > line_count - cursor.y) { - count = line_count - cursor.y; + if (cursor.y >= line_count) { + return self; } - cursor.y += count; - line_index = [buffer nextLine:line_index :count]; + cursor.y++; + line_index = [buffer nextLine:line_index :1]; char_index = [buffer charPtr:line_index at:cursor.x]; + [self trackCursor:1]; + if (base.y + ylen - 1 < cursor.y) { [vScrollBar setIndex:cursor.y + 1 - ylen]; } @@ -239,14 +335,16 @@ handleEvent (Editor *self, qwaq_event_t *event) return self; } --cursorLeft:(unsigned)count +-charLeft { [self recenter:0]; - if (count > cursor.x) { - count = cursor.x; + if (cursor.x < 1) { + return self; } - cursor.x -= count; + cursor.x--; char_index = [buffer charPtr:line_index at:cursor.x]; + [self trackCursor:0]; + if (base.x > cursor.x) { [hScrollBar setIndex:cursor.x]; } @@ -254,12 +352,14 @@ handleEvent (Editor *self, qwaq_event_t *event) return self; } --cursorRight:(unsigned)count +-charRight { [self recenter:0]; // FIXME handle horizontal scrolling and how to deal with max scroll - cursor.x += count; + cursor.x++; char_index = [buffer charPtr:line_index at:cursor.x]; + [self trackCursor:1]; + if (base.x + xlen - 1 < cursor.x) { [hScrollBar setIndex:cursor.x + 1 - xlen]; } diff --git a/ruamoko/qwaq/editor/status.h b/ruamoko/qwaq/editor/status.h new file mode 100644 index 000000000..0c8dec1eb --- /dev/null +++ b/ruamoko/qwaq/editor/status.h @@ -0,0 +1,23 @@ +#ifndef __qwaq_editor_status_h +#define __qwaq_editor_status_h + +#include "ruamoko/qwaq/ui/view.h" + +typedef enum { + cmInsert, + cmTypeOver, + cmVInsert, + cmVTypeOver, +} CursorMode; + +@interface EditStatus : View +{ + CursorMode cursorMode; + int modified; +} ++(EditStatus *)withRect:(Rect)rect; +-setCursorMode:(CursorMode)mode; +-setModified:(int)modified; +@end + +#endif//__qwaq_editor_status_h diff --git a/ruamoko/qwaq/editor/status.r b/ruamoko/qwaq/editor/status.r new file mode 100644 index 000000000..1f9d1f09d --- /dev/null +++ b/ruamoko/qwaq/editor/status.r @@ -0,0 +1,43 @@ +#include "ruamoko/qwaq/editor/status.h" + +static int cursor_modes[] = { 'I', 'O', 'i', 'o' }; + +@implementation EditStatus + +-initWithRect:(Rect)rect +{ + if (!(self = [super initWithRect: rect])) { + return nil; + } + growMode = gfGrowNone; + return self; +} + ++(EditStatus *)withRect:(Rect)rect +{ + return [[self alloc] initWithRect:rect]; +} + +-setCursorMode:(CursorMode)mode +{ + cursorMode = mode; + return self; +} + +-setModified:(int)modified +{ + self.modified = modified; + return self; +} + +-draw +{ + [super draw]; + if (modified) { + [self mvaddch:{0, 0}, '*']; + } + [self mvaddch:{1, 0}, cursor_modes[cursorMode]]; + return self; +} + +@end From 75ce07a14cd40e2a05312421b459a31bdf2b3fc3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Jun 2021 14:29:32 +0900 Subject: [PATCH 1573/3664] [qwaq] Implement home and end Currently, home always moves the cursor to the very first column, but I'm considering making it move the cursor to the first non-space character of the line if it's not already there, otherwise to the first column (ie, the cursor will toggle between the two positions if it's in one of them). --- ruamoko/qwaq/editor/editor.h | 2 ++ ruamoko/qwaq/editor/editor.r | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index a30b2546d..0e81a5e27 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -47,6 +47,8 @@ -charDown; -charLeft; -charRight; +-moveBOL; +-moveEOL; -recenter:(int) force; -gotoLine:(unsigned) line; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index fc5a69993..dbd7ffec1 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -173,6 +173,12 @@ handleEvent (Editor *self, qwaq_event_t *event) case QFK_RIGHT: [self charRight]; return 1; + case QFK_HOME: + [self moveBOL]; + return 1; + case QFK_END: + [self moveEOL]; + return 1; } } return 0; @@ -370,6 +376,25 @@ handleEvent (Editor *self, qwaq_event_t *event) return self; } +-moveBOL +{ + char_index = line_index; + cursor.x = 0; + base.x = 0; + [self recenter:0]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + +-moveEOL +{ + char_index = [buffer getEOL:line_index]; + cursor.x = [buffer charPos:line_index at:char_index]; + [self recenter:0]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + -(void)onScroll:(id)sender { base.x = scroll.x; From 3cd0d68774854c6fca47bd37419bece5190127c8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Jun 2021 10:14:07 +0900 Subject: [PATCH 1574/3664] [qwaq] Implement word left and right The word boundaries are currently vary simple, just transitions from alnum_ (as it was in my old editor and in Borland's editors), but the basic logic is working. --- ruamoko/qwaq/builtins/editbuffer.c | 19 ++++- ruamoko/qwaq/editor/editbuffer.h | 1 + ruamoko/qwaq/editor/editbuffer.r | 1 + ruamoko/qwaq/editor/editor.h | 2 + ruamoko/qwaq/editor/editor.r | 120 ++++++++++++++++++++++++----- ruamoko/qwaq/ui/event.h | 5 ++ 6 files changed, 126 insertions(+), 22 deletions(-) diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index ac2728904..2cd8fd558 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -162,7 +162,10 @@ prevWord (txtbuffer_t *buffer, unsigned ptr) if (ptr > 0) { while (ptr > 0) { char c = getChar (buffer, ptr - 1); - if (!isword (c)) { + if (c == '\n') { + return ptr; + } + if (isword (c)) { break; } ptr--; @@ -172,7 +175,7 @@ prevWord (txtbuffer_t *buffer, unsigned ptr) if (c == '\n') { return ptr; } - if (isword (c)) { + if (!isword (c)) { break; } ptr--; @@ -619,6 +622,17 @@ bi_i_EditBuffer__prevNonSpace_ (progs_t *pr) R_INT (pr) = prevNonSpace (buffer->txtbuffer, ptr); } +static void +bi_i_EditBuffer__isWord_ (progs_t *pr) +{ + qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; + editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); + unsigned ptr = P_UINT (pr, 2); + + R_INT (pr) = isword (getChar (buffer->txtbuffer, ptr)); +} + static void bi_i_EditBuffer__nextWord_ (progs_t *pr) { @@ -968,6 +982,7 @@ static builtin_t builtins[] = { {"_i_EditBuffer__prevChar_", bi_i_EditBuffer__prevChar_, -1}, {"_i_EditBuffer__nextNonSpace_", bi_i_EditBuffer__nextNonSpace_, -1}, {"_i_EditBuffer__prevNonSpace_", bi_i_EditBuffer__prevNonSpace_, -1}, + {"_i_EditBuffer__isWord_", bi_i_EditBuffer__isWord_, -1}, {"_i_EditBuffer__nextWord_", bi_i_EditBuffer__nextWord_, -1}, {"_i_EditBuffer__prevWord_", bi_i_EditBuffer__prevWord_, -1}, {"_i_EditBuffer__nextLine_", bi_i_EditBuffer__nextLine_, -1}, diff --git a/ruamoko/qwaq/editor/editbuffer.h b/ruamoko/qwaq/editor/editbuffer.h index e57491e80..fe8a15829 100644 --- a/ruamoko/qwaq/editor/editbuffer.h +++ b/ruamoko/qwaq/editor/editbuffer.h @@ -34,6 +34,7 @@ typedef struct eb_color_s { - (unsigned) prevChar: (unsigned) charPtr; - (unsigned) nextNonSpace: (unsigned) charPtr; - (unsigned) prevNonSpace: (unsigned) charPtr; +- (int) isWord: (unsigned) charPtr; - (unsigned) nextWord: (unsigned) wordPtr; - (unsigned) prevWord: (unsigned) wordPtr; - (unsigned) nextLine: (unsigned) linePtr; diff --git a/ruamoko/qwaq/editor/editbuffer.r b/ruamoko/qwaq/editor/editbuffer.r index b3d7a6fe9..779e22077 100644 --- a/ruamoko/qwaq/editor/editbuffer.r +++ b/ruamoko/qwaq/editor/editbuffer.r @@ -18,6 +18,7 @@ - (unsigned) prevChar: (unsigned) charPtr = #0; - (unsigned) nextNonSpace: (unsigned) charPtr = #0; - (unsigned) prevNonSpace: (unsigned) charPtr = #0; +- (int) isWord: (unsigned) charPtr = #0; - (unsigned) nextWord: (unsigned) wordPtr = #0; - (unsigned) prevWord: (unsigned) wordPtr = #0; - (unsigned) nextLine: (unsigned) linePtr = #0; diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index 0e81a5e27..ad3666664 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -47,6 +47,8 @@ -charDown; -charLeft; -charRight; +-wordLeft; +-wordRight; -moveBOL; -moveEOL; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index dbd7ffec1..6f6aa1776 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -7,6 +7,23 @@ @implementation Editor +static int +center (unsigned v, int len) +{ + return v > len / 2 ? v / 2 : 0; +} + +static void +trackCursor (Editor *self) +{ + unsigned cx = [self.buffer charPos:self.line_index at:self.char_index]; + if (self.cursor.x != cx) { + if (self.char_index < [self.buffer getEOT]) { + int c = [self.buffer getChar:self.char_index]; + } + } +} + -initWithRect:(Rect) rect file:(string) filename path:(string) filepath { if (!(self = [super initWithRect: rect])) { @@ -168,10 +185,18 @@ handleEvent (Editor *self, qwaq_event_t *event) [self charDown]; return 1; case QFK_LEFT: - [self charLeft]; + if (event.key.shift & qe_control) { + [self wordLeft]; + } else { + [self charLeft]; + } return 1; case QFK_RIGHT: - [self charRight]; + if (event.key.shift & qe_control) { + [self wordRight]; + } else { + [self charRight]; + } return 1; case QFK_HOME: [self moveBOL]; @@ -376,6 +401,78 @@ handleEvent (Editor *self, qwaq_event_t *event) return self; } +-wordLeft +{ + [self recenter:0]; + //unsigned oc = char_index; + Point b = base; + + do { + if (char_index && char_index == line_index) { + line_index = [buffer prevLine: line_index]; + char_index = [buffer getEOL: line_index]; + if (--cursor.y < b.y) { + b.y = cursor.y; + } + } + char_index = [buffer prevWord:char_index]; + } while (char_index && char_index < [buffer getEOT] + && ![buffer isWord:char_index]); + + cursor.x = [buffer charPos:line_index at:char_index]; + if (cursor.x < b.x) { + b.x = cursor.x; + } else if (cursor.x >= b.x) { + b.x = center (b.x, xlen); + } + base.x = b.x; + [vScrollBar setIndex:b.y]; + trackCursor (self); + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + + return self; +} + +-wordRight +{ + [self recenter:0]; + //unsigned oc = char_index; + Point b = base; + + if (char_index >= [buffer getEOT]) { + return self; + } + if ([buffer getChar:char_index] == '\n') { + while ([buffer getChar:char_index] == '\n') { + char_index = line_index = [buffer nextLine:line_index]; + if (++cursor.y >= b.y + ylen) { + b.y = cursor.y + 1 - ylen; + } + if (char_index >= [buffer getEOT]) { + break; + } + if (![buffer isWord:char_index]) { + char_index = [buffer nextWord: char_index]; + } + } + } else { + char_index = [buffer nextWord: char_index]; + } + + cursor.x = [buffer charPos:line_index at:char_index]; + if (cursor.x < b.x) { + b.x = cursor.x; + } else if (cursor.x >= b.x) { + b.x = center (b.x, xlen); + } + base.x = b.x; + [vScrollBar setIndex:b.y]; + trackCursor (self); + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + + return self; +} + -moveBOL { char_index = line_index; @@ -414,28 +511,11 @@ handleEvent (Editor *self, qwaq_event_t *event) -recenter:(int) force { if (force || cursor.y < base.y || cursor.y - base.y >= ylen) { - unsigned target; - if (cursor.y < ylen / 2) { - target = 0; - } else { - target = cursor.y - ylen / 2; - } - [self scrollTo:target]; + [self scrollTo: center (cursor.y, ylen)]; } return self; } -static void -trackCursor (Editor *self) -{ - unsigned cx = [self.buffer charPos:self.line_index at:self.char_index]; - if (self.cursor.x != cx) { - if (self.char_index < [self.buffer getEOT]) { - int c = [self.buffer getChar:self.char_index]; - } - } -} - -gotoLine:(unsigned) line { if (line > cursor.y) { diff --git a/ruamoko/qwaq/ui/event.h b/ruamoko/qwaq/ui/event.h index a3c9525b0..7e38f52b1 100644 --- a/ruamoko/qwaq/ui/event.h +++ b/ruamoko/qwaq/ui/event.h @@ -13,6 +13,11 @@ typedef enum { qe_keydown = 0x0020, } qwaq_key_event; +typedef enum { + qe_shift = 1, + qe_control = 4, +} qwaq_key_shift; + typedef enum { qe_command = 0x0200, // application level command qe_broadcast = 0x0400, From f09810b595a922d8eb4c3929803c034ee27d31d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Jun 2021 23:34:43 +0900 Subject: [PATCH 1575/3664] [qwaq] Implement the remaining basic cursor motion This gets all the basic cursor motion from my old editor working. arrow keys: left/right/up/down char/line home/end: beginning/end of line page up/down and ctrl versions where left/right are prev/next work, up/down skip over indents, home/end are beginning/end of screen, and page up/down are beginning/end of text. --- ruamoko/qwaq/editor/editor.h | 6 ++ ruamoko/qwaq/editor/editor.r | 131 +++++++++++++++++++++++++++++++++-- 2 files changed, 131 insertions(+), 6 deletions(-) diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index ad3666664..dfcf70d75 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -43,12 +43,18 @@ -scrollRight:(unsigned) count; -pageUp; -pageDown; +-linesUp; +-linesDown; -charUp; -charDown; -charLeft; -charRight; -wordLeft; -wordRight; +-moveBOT; +-moveEOT; +-moveBOS; +-moveEOS; -moveBOL; -moveEOL; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index 6f6aa1776..fd37744ed 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -173,16 +173,32 @@ handleEvent (Editor *self, qwaq_event_t *event) } else if (event.what == qe_keydown) { switch (event.key.code) { case QFK_PAGEUP: - [self pageUp]; + if (event.key.shift & qe_control) { + [self moveBOT]; + } else { + [self pageUp]; + } return 1; case QFK_PAGEDOWN: - [self pageDown]; + if (event.key.shift & qe_control) { + [self moveEOT]; + } else { + [self pageDown]; + } return 1; case QFK_UP: - [self charUp]; + if (event.key.shift & qe_control) { + [self linesUp]; + } else { + [self charUp]; + } return 1; case QFK_DOWN: - [self charDown]; + if (event.key.shift & qe_control) { + [self linesDown]; + } else { + [self charDown]; + } return 1; case QFK_LEFT: if (event.key.shift & qe_control) { @@ -199,10 +215,18 @@ handleEvent (Editor *self, qwaq_event_t *event) } return 1; case QFK_HOME: - [self moveBOL]; + if (event.key.shift & qe_control) { + [self moveBOS]; + } else { + [self moveBOL]; + } return 1; case QFK_END: - [self moveEOL]; + if (event.key.shift & qe_control) { + [self moveEOS]; + } else { + [self moveEOL]; + } return 1; } } @@ -330,6 +354,54 @@ handleEvent (Editor *self, qwaq_event_t *event) return self; } +-linesUp +{ + while (line_index > 0) { + line_index = [buffer prevLine: line_index]; + cursor.y--; + unsigned p = [buffer nextNonSpace: line_index]; + if ([buffer getChar:p] == '\n') { + continue; + } + int x = [buffer charPos:line_index at:p]; + if (x <= cursor.x) { + break; + } + } + char_index = [buffer charPtr:line_index at:cursor.x]; + + [self recenter:0]; + [self trackCursor:1]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + + return self; +} + +-linesDown +{ + unsigned end = [buffer getEOT]; + unsigned last = [buffer getBOL:end]; + while (line_index < last) { + line_index = [buffer nextLine: line_index]; + cursor.y++; + unsigned p = [buffer nextNonSpace: line_index]; + if (p >= end || [buffer getChar:p] == '\n') { + continue; + } + int x = [buffer charPos:line_index at:p]; + if (x <= cursor.x) { + break; + } + } + char_index = [buffer charPtr:line_index at:cursor.x]; + + [self recenter:0]; + [self trackCursor:1]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + + return self; +} + -charUp { [self recenter:0]; @@ -473,6 +545,53 @@ handleEvent (Editor *self, qwaq_event_t *event) return self; } +-moveBOT +{ + line_index = base_index = char_index = 0;; + cursor = nil; + base.x = 0; + [vScrollBar setIndex:0]; + [self trackCursor:1]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + +-moveEOT +{ + char_index = [buffer getEOT]; + line_index = [buffer getBOL:char_index]; + cursor.x = [buffer charPos:line_index at:char_index]; + cursor.y = line_count; + [self recenter:0]; + [self trackCursor:1]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + +-moveBOS +{ + line_index = base_index; + cursor.y = base.y; + char_index = [buffer charPtr:line_index at:cursor.x]; + [self trackCursor:1]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + +-moveEOS +{ + unsigned count = line_count - base.y; + if (count > ylen - 1) { + count = ylen - 1; + } + line_index = [buffer nextLine:base_index :count]; + cursor.y = base.y + count; + char_index = [buffer charPtr:line_index at:cursor.x]; + [self trackCursor:1]; + [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; + return self; +} + -moveBOL { char_index = line_index; From 2572011a4bc6cba682beef5a590449dcde81d856 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Jun 2021 01:30:44 +0900 Subject: [PATCH 1576/3664] [qwaq] Fix various scrollbar related issues The editor now uses the vertical scrollbar for handling mouse wheel scrolling, thus keeping the scrollbar in sync. Scrollbar index can now cover the full range (not sure why I had that -1), and the potential divide by zero is avoided properly. Thumb-tab now positioned properly when the range is 0. --- ruamoko/qwaq/editor/editor.h | 2 -- ruamoko/qwaq/editor/editor.r | 38 ++---------------------------------- ruamoko/qwaq/ui/scrollbar.h | 1 + ruamoko/qwaq/ui/scrollbar.r | 19 ++++++++++++------ 4 files changed, 16 insertions(+), 44 deletions(-) diff --git a/ruamoko/qwaq/editor/editor.h b/ruamoko/qwaq/editor/editor.h index dfcf70d75..8fda028c6 100644 --- a/ruamoko/qwaq/editor/editor.h +++ b/ruamoko/qwaq/editor/editor.h @@ -37,8 +37,6 @@ -(string)filepath; -(Point)cursor; -setStatusView:(EditStatus *)status; --scrollUp:(unsigned) count; --scrollDown:(unsigned) count; -scrollLeft:(unsigned) count; -scrollRight:(unsigned) count; -pageUp; diff --git a/ruamoko/qwaq/editor/editor.r b/ruamoko/qwaq/editor/editor.r index fd37744ed..317d5ae21 100644 --- a/ruamoko/qwaq/editor/editor.r +++ b/ruamoko/qwaq/editor/editor.r @@ -154,11 +154,11 @@ handleEvent (Editor *self, qwaq_event_t *event) if (event.what & qe_mouse) { if (event.what == qe_mouseclick) { if (event.mouse.buttons & (1 << 3)) { - [self scrollUp: 1]; + [self.vScrollBar page:1 dir:0]; return 1; } if (event.mouse.buttons & (1 << 4)) { - [self scrollDown: 1]; + [self.vScrollBar page:1 dir:1]; return 1; } if (event.mouse.buttons & (1 << 5)) { @@ -243,40 +243,6 @@ handleEvent (Editor *self, qwaq_event_t *event) return self; } --scrollUp:(unsigned) count -{ - unsigned index; - unsigned lines; - if (count == 1) { - index = [buffer prevLine: base_index]; - } else { - index = [buffer prevLine: base_index :count]; - } - lines = [buffer countLines: {index, base_index - index}]; - base.y -= lines; - base_index = index; - [self redraw]; - [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; - return self; -} - --scrollDown:(unsigned) count -{ - unsigned index; - unsigned lines; - if (count == 1) { - index = [buffer nextLine: base_index]; - } else { - index = [buffer nextLine: base_index :count]; - } - lines = [buffer countLines: {base_index, index - base_index}]; - base.y += lines; - base_index = index; - [self redraw]; - [self moveCursor: {cursor.x - base.x, cursor.y - base.y}]; - return self; -} - -scrollLeft:(unsigned) count { if (base.x > count) { diff --git a/ruamoko/qwaq/ui/scrollbar.h b/ruamoko/qwaq/ui/scrollbar.h index 404dbfaf7..c1ed0d47a 100644 --- a/ruamoko/qwaq/ui/scrollbar.h +++ b/ruamoko/qwaq/ui/scrollbar.h @@ -35,6 +35,7 @@ -setSingleStep:(unsigned)singleStep; -setIndex:(unsigned)index; -(unsigned)index; +-page:(unsigned)step dir:(unsigned) dir; @end #endif//__qwaq_ui_scrollbar_h diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index 8bb14c0b7..9e5f150f6 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -45,6 +45,8 @@ thumbTab = [Button withPos:thumbPos releasedIcon:icons[2] pressedIcon:icons[2]]; + [forwardButton setGrowMode:gfGrowAll]; + [[backButton onClick] addListener:self :@selector(scrollBack:)]; [[forwardButton onClick] addListener:self :@selector(scrollForward:)]; [[thumbTab onPress] addListener:self :thumbSel]; @@ -110,15 +112,20 @@ static void position_tab (ScrollBar *self) { Point p = {0, 0}; - Point o = [self.thumbTab origin]; if (self.range > 0) { if (self.vertical) { - p.y = 1 + self.index * (self.ylen - 3) / (self.range - 1); + p.y = 1 + self.index * (self.ylen - 3) / self.range; } else { - p.x = 1 + self.index * (self.xlen - 3) / (self.range - 1); + p.x = 1 + self.index * (self.xlen - 3) / self.range; + } + } else { + if (self.vertical) { + p.y = 1; + } else { + p.x = 1; } } - [self.thumbTab move:{p.x - o.x, p.y - o.y}]; + [self.thumbTab moveTo:p]; [self redraw]; } @@ -138,8 +145,8 @@ position_tab (ScrollBar *self) unsigned oind = index; if (dir) { - if (range - 1 - index < step) { - step = range - 1 - index; + if (range - index < step) { + step = range - index; } index += step; } else { From 813497a1aae81250501cb5a98619cda1aa6500e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Jun 2021 22:50:51 +0900 Subject: [PATCH 1577/3664] [ui] Create library for UI support code Currently this has text buffer, input line, vrect and view code. --- include/QF/Makemodule.am | 9 ++-- include/QF/console.h | 31 ++---------- include/QF/render.h | 1 + include/QF/ui/inputline.h | 60 +++++++++++++++++++++++ include/QF/{ => ui}/txtbuffer.h | 6 +-- include/QF/{ => ui}/view.h | 10 ++-- include/QF/{ => ui}/vrect.h | 6 +-- include/QF/vid.h | 1 - libs/Makemodule.am | 1 + libs/console/Makemodule.am | 21 ++++++-- libs/console/bi_inputline.c | 3 +- libs/console/client.c | 5 +- libs/console/complete.c | 2 + libs/console/console.c | 2 + libs/console/menu.c | 3 +- libs/console/server.c | 5 +- libs/ui/Makemodule.am | 12 +++++ libs/{console => ui}/inputline.c | 4 +- libs/{util => ui}/txtbuffer.c | 3 +- libs/{console => ui}/view.c | 2 +- libs/{util => ui}/vrect.c | 3 +- libs/util/Makemodule.am | 2 - libs/video/renderer/glsl/glsl_bsp.c | 1 - libs/video/renderer/glsl/glsl_textures.c | 3 +- libs/video/renderer/r_scrap.c | 3 +- libs/video/renderer/r_screen.c | 1 - libs/video/renderer/vulkan/vulkan_alias.c | 1 - libs/video/renderer/vulkan/vulkan_bsp.c | 1 - nq/source/Makemodule.am | 1 + nq/source/sbar.c | 3 +- qtv/source/Makemodule.am | 1 + qtv/source/sbar.c | 3 +- qw/source/Makemodule.am | 2 + qw/source/sbar.c | 3 +- qw/source/sv_sbar.c | 3 +- ruamoko/qwaq/Makemodule.am | 2 + ruamoko/qwaq/builtins/editbuffer.c | 3 +- 37 files changed, 152 insertions(+), 71 deletions(-) create mode 100644 include/QF/ui/inputline.h rename include/QF/{ => ui}/txtbuffer.h (97%) rename include/QF/{ => ui}/view.h (97%) rename include/QF/{ => ui}/vrect.h (98%) create mode 100644 libs/ui/Makemodule.am rename libs/{console => ui}/inputline.c (98%) rename libs/{util => ui}/txtbuffer.c (99%) rename libs/{console => ui}/view.c (99%) rename libs/{util => ui}/vrect.c (99%) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 7c7b726fe..532422e06 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -68,12 +68,9 @@ include_qf = \ include/QF/sys.h \ include/QF/teamplay.h \ include/QF/tga.h \ - include/QF/txtbuffer.h \ include/QF/va.h \ include/QF/ver_check.h \ include/QF/vid.h \ - include/QF/vrect.h \ - include/QF/view.h \ include/QF/wad.h \ include/QF/wadfile.h \ include/QF/winding.h \ @@ -134,6 +131,12 @@ include_qf_simd = \ include/QF/simd/vec4d.h \ include/QF/simd/vec4f.h +include_qf_ui = \ + include/QF/ui/inputline.h \ + include/QF/ui/txtbuffer.h \ + include/QF/ui/view.h \ + include/QF/ui/vrect.h + include_qf_vulkan = \ include/QF/Vulkan/barrier.h \ include/QF/Vulkan/buffer.h \ diff --git a/include/QF/console.h b/include/QF/console.h index 8bae248e9..1bb6b164e 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -46,27 +46,6 @@ typedef struct int numlines; // number of non-blank text lines, used for backscroling } old_console_t; -typedef struct inputline_s -{ - char **lines; // array of lines for input history - int num_lines; // number of lines in arry. 1 == no history - size_t line_size; // space available in each line. includes \0 - char prompt_char; // char placed at the beginning of the line - int edit_line; // current line being edited - int history_line; // current history line - size_t linepos; // cursor position within the current edit line - size_t scroll; // beginning of displayed line - size_t width; // viewable width for horizontal scrolling - const char *line; - void *user_data; // eg: window pointer - void (*complete)(struct inputline_s *); // tab key pressed - void (*enter)(struct inputline_s *); // enter key pressed - void (*draw)(struct inputline_s *); // draw input line to screen - - int x, y; // coordinates depend on display - int cursor; // is the cursor active (drawn?) -} inputline_t; - typedef struct { byte *text; size_t len; @@ -96,22 +75,18 @@ void Con_Printf (const char *fmt, ...) __attribute__((format(PRINTF, 1, 2))); void Con_Print (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); void Con_ToggleConsole_f (void); +struct inputline_s; // wrapper function to attempt to either complete the command line // or to list possible matches grouped by type // (i.e. will display possible variables, aliases, commands // that match what they've typed so far) -void Con_BasicCompleteCommandLine (inputline_t *il); +void Con_BasicCompleteCommandLine (struct inputline_s *il); // Generic libs/util/console.c function to display a list // formatted in columns on the console void Con_DisplayList(const char **list, int con_linewidth); extern void (*con_list_print)(const char *fmt, ...) __attribute__((format(PRINTF, 1, 2))); -inputline_t *Con_CreateInputLine (int lines, int lsize, char prompt); -void Con_DestroyInputLine (inputline_t *inputline); -void Con_ClearTyping (inputline_t *il, int save); -void Con_ProcessInputLine (inputline_t *il, int ch); - con_buffer_t *Con_CreateBuffer (size_t buffer_size, int max_lines); void Con_DestroyBuffer (con_buffer_t *buffer); void Con_BufferAddText (con_buffer_t *buf, const char *text); @@ -134,7 +109,7 @@ void Con_Demolist_DEM_f (void); //FIXME need a better way to communicate this (bah, need a better menu system // in general :P) -void C_DrawInputLine (inputline_t *il); +void C_DrawInputLine (struct inputline_s *il); struct view_s; void Menu_Init (void); diff --git a/include/QF/render.h b/include/QF/render.h index 3b86c9038..b10c6585e 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -33,6 +33,7 @@ #include "QF/qdefs.h" // FIXME #include "QF/vid.h" #include "QF/simd/types.h" +#include "QF/ui/vrect.h" typedef enum { pt_static, diff --git a/include/QF/ui/inputline.h b/include/QF/ui/inputline.h new file mode 100644 index 000000000..c98774501 --- /dev/null +++ b/include/QF/ui/inputline.h @@ -0,0 +1,60 @@ +/* + inputline.h + + Input line support + + Copyright (C) 2001 Bill Currie + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_ui_inputline_h +#define __QF_ui_inputline_h + +#include + +typedef struct inputline_s +{ + char **lines; // array of lines for input history + int num_lines; // number of lines in arry. 1 == no history + size_t line_size; // space available in each line. includes \0 + char prompt_char; // char placed at the beginning of the line + int edit_line; // current line being edited + int history_line; // current history line + size_t linepos; // cursor position within the current edit line + size_t scroll; // beginning of displayed line + size_t width; // viewable width for horizontal scrolling + const char *line; + void *user_data; // eg: window pointer + void (*complete)(struct inputline_s *); // tab key pressed + void (*enter)(struct inputline_s *); // enter key pressed + void (*draw)(struct inputline_s *); // draw input line to screen + + int x, y; // coordinates depend on display + int cursor; // is the cursor active (drawn?) +} inputline_t; + +inputline_t *Con_CreateInputLine (int lines, int lsize, char prompt); +void Con_DestroyInputLine (inputline_t *inputline); +void Con_ClearTyping (inputline_t *il, int save); +void Con_ProcessInputLine (inputline_t *il, int ch); + +#endif//__QF_ui_inputline_h diff --git a/include/QF/txtbuffer.h b/include/QF/ui/txtbuffer.h similarity index 97% rename from include/QF/txtbuffer.h rename to include/QF/ui/txtbuffer.h index 8e4723fb9..ee3f66d61 100644 --- a/include/QF/txtbuffer.h +++ b/include/QF/ui/txtbuffer.h @@ -25,8 +25,8 @@ */ -#ifndef __QF_txtbuffer_h -#define __QF_txtbuffer_h +#ifndef __QF_ui_txtbuffer_h +#define __QF_ui_txtbuffer_h #include #include @@ -109,4 +109,4 @@ int TextBuffer_DeleteAt (txtbuffer_t *buffer, size_t offset, size_t len); ///@} -#endif//__QF_txtbuffer_h +#endif//__QF_ui_txtbuffer_h diff --git a/include/QF/view.h b/include/QF/ui/view.h similarity index 97% rename from include/QF/view.h rename to include/QF/ui/view.h index 5a6ae339f..fd2dd33ac 100644 --- a/include/QF/view.h +++ b/include/QF/ui/view.h @@ -28,8 +28,8 @@ */ -#ifndef __QF_view_h -#define __QF_view_h +#ifndef __QF_ui_view_h +#define __QF_ui_view_h /** \defgroup console_view Console View Objects \ingroup console @@ -40,8 +40,8 @@ the standard compass rose (north, east, south, west in clockwise order) with north at the top. - The origin of the view is taken to be the point corresponding point on the - edge of the view (eg, southeast is bottom right), or the view's center for + The origin of the view is taken to be the corresponding point on the edge + of the view (eg, southeast is bottom right), or the view's center for center gravity. When the relative coordinates of the view are (0,0), the view's origin is placed on the parent view's gravity point using the view's gravity (\em not the parent view's gravity). That is, the parent view's @@ -217,4 +217,4 @@ void view_move (view_t *view, int xp, int yp); ///@} -#endif//__QF_view_h +#endif//__QF_ui_view_h diff --git a/include/QF/vrect.h b/include/QF/ui/vrect.h similarity index 98% rename from include/QF/vrect.h rename to include/QF/ui/vrect.h index bb0f99061..64d3b6302 100644 --- a/include/QF/vrect.h +++ b/include/QF/ui/vrect.h @@ -28,8 +28,8 @@ */ -#ifndef __QF_vrect_h -#define __QF_vrect_h +#ifndef __QF_ui_vrect_h +#define __QF_ui_vrect_h typedef struct vrect_s { int x; @@ -165,4 +165,4 @@ vrect_t *VRect_Union (const vrect_t *r1, const vrect_t *r2); */ vrect_t *VRect_Merge (const vrect_t *r1, const vrect_t *r2); -#endif//__QF_vrect_h +#endif//__QF_ui_vrect_h diff --git a/include/QF/vid.h b/include/QF/vid.h index 16b9bcf37..c2d92b3a3 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -29,7 +29,6 @@ #define __QF_vid_h #include "QF/qtypes.h" -#include "QF/vrect.h" #define VID_CBITS 6 #define VID_GRADES (1 << VID_CBITS) diff --git a/libs/Makemodule.am b/libs/Makemodule.am index 86fcac7df..a06beabfc 100644 --- a/libs/Makemodule.am +++ b/libs/Makemodule.am @@ -1,4 +1,5 @@ include libs/util/Makemodule.am +include libs/ui/Makemodule.am include libs/gamecode/Makemodule.am include libs/ruamoko/Makemodule.am include libs/gib/Makemodule.am diff --git a/libs/console/Makemodule.am b/libs/console/Makemodule.am index 97586f514..a3f06e346 100644 --- a/libs/console/Makemodule.am +++ b/libs/console/Makemodule.am @@ -4,12 +4,23 @@ noinst_LTLIBRARIES += @client_static_plugins@ @server_static_plugins@ EXTRA_LTLIBRARIES += libs/console/console_server.la libs/console/console_client.la console_common_sources= \ - libs/console/buffer.c libs/console/complete.c libs/console/console.c libs/console/inputline.c libs/console/list.c libs/console/filelist.c libs/console/view.c -client_sources= libs/console/bi_inputline.c libs/console/client.c libs/console/menu.c -server_sources= libs/console/server.c + libs/console/buffer.c \ + libs/console/complete.c \ + libs/console/console.c \ + libs/console/list.c \ + libs/console/filelist.c +client_sources= \ + libs/console/bi_inputline.c \ + libs/console/client.c \ + libs/console/menu.c +server_sources= \ + libs/console/server.c -console_deps=libs/util/libQFutil.la -client_deps= libs/console/libQFconsole.la \ +console_deps=\ + libs/ui/libQFui.la \ + libs/util/libQFutil.la +client_deps= \ + libs/console/libQFconsole.la \ libs/audio/libQFsound.la \ libs/ruamoko/libQFruamoko.la \ libs/gib/libQFgib.la \ diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index b55cfa034..76e9b676c 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -36,13 +36,14 @@ # include #endif -#include "QF/console.h" #include "QF/csqc.h" #include "QF/draw.h" #include "QF/progs.h" #include "QF/sys.h" #include "QF/zone.h" +#include "QF/ui/inputline.h" + typedef struct il_data_s { struct il_data_s *next; struct il_data_s **prev; diff --git a/libs/console/client.c b/libs/console/client.c index 054aaa8f5..43bbcf8f2 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -58,12 +58,15 @@ #include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" -#include "QF/view.h" #include "QF/plugin/general.h" #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/view.h" + +#include "QF/ui/inputline.h" + #include "compat.h" static general_data_t plugin_info_general_data; diff --git a/libs/console/complete.c b/libs/console/complete.c index 220906473..6e5499dd9 100644 --- a/libs/console/complete.c +++ b/libs/console/complete.c @@ -47,6 +47,8 @@ #include "QF/plugin/console.h" +#include "QF/ui/inputline.h" + #include "compat.h" /* diff --git a/libs/console/console.c b/libs/console/console.c index cb966a941..cbf98a463 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -42,6 +42,8 @@ #include "QF/plugin/general.h" #include "QF/plugin/console.h" +#include "QF/ui/inputline.h" + //FIXME probably shouldn't be visible VISIBLE int con_linewidth; // characters across screen diff --git a/libs/console/menu.c b/libs/console/menu.c index 7c52b5b25..23d99c181 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -46,7 +46,8 @@ #include "QF/ruamoko.h" #include "QF/sound.h" #include "QF/sys.h" -#include "QF/view.h" + +#include "QF/ui/view.h" #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" diff --git a/libs/console/server.c b/libs/console/server.c index 625158944..fff7bcdb7 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -68,11 +68,14 @@ #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/va.h" -#include "QF/view.h" #include "QF/plugin/general.h" #include "QF/plugin/console.h" +#include "QF/ui/view.h" + +#include "QF/ui/inputline.h" + #include "compat.h" #include "sv_console.h" diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am new file mode 100644 index 000000000..4a76ecffb --- /dev/null +++ b/libs/ui/Makemodule.am @@ -0,0 +1,12 @@ +#include libs/ui/test/Makemodule.am + +lib_LTLIBRARIES += libs/ui/libQFui.la + +libs_ui_libQFui_la_LDFLAGS= $(lib_ldflags) +libs_ui_libQFui_la_LIBADD= $(ui_deps) +libs_ui_libQFui_la_DEPENDENCIES= $(ui_deps) +libs_ui_libQFui_la_SOURCES= \ + libs/ui/inputline.c \ + libs/ui/txtbuffer.c \ + libs/ui/view.c \ + libs/ui/vrect.c diff --git a/libs/console/inputline.c b/libs/ui/inputline.c similarity index 98% rename from libs/console/inputline.c rename to libs/ui/inputline.c index 0123bf0da..93c13d2bc 100644 --- a/libs/console/inputline.c +++ b/libs/ui/inputline.c @@ -39,12 +39,10 @@ # include #endif -#include "QF/cmd.h" -#include "QF/console.h" #include "QF/keys.h" #include "QF/mathlib.h" -#include "compat.h" +#include "QF/ui/inputline.h" VISIBLE struct inputline_s * Con_CreateInputLine (int lines, int lsize, char prompt) diff --git a/libs/util/txtbuffer.c b/libs/ui/txtbuffer.c similarity index 99% rename from libs/util/txtbuffer.c rename to libs/ui/txtbuffer.c index 0edc785b5..36c82afd6 100644 --- a/libs/util/txtbuffer.c +++ b/libs/ui/txtbuffer.c @@ -38,7 +38,8 @@ #include "QF/alloc.h" #include "QF/qtypes.h" #include "QF/sys.h" -#include "QF/txtbuffer.h" + +#include "QF/ui/txtbuffer.h" #include "compat.h" diff --git a/libs/console/view.c b/libs/ui/view.c similarity index 99% rename from libs/console/view.c rename to libs/ui/view.c index ed1ae064e..9765b223f 100644 --- a/libs/console/view.c +++ b/libs/ui/view.c @@ -39,7 +39,7 @@ #endif #include -#include "QF/view.h" +#include "QF/ui/view.h" static void setgeometry (view_t *view) diff --git a/libs/util/vrect.c b/libs/ui/vrect.c similarity index 99% rename from libs/util/vrect.c rename to libs/ui/vrect.c index 169ea8080..cbfe72595 100644 --- a/libs/util/vrect.c +++ b/libs/ui/vrect.c @@ -34,7 +34,8 @@ #include #include "QF/mathlib.h" -#include "QF/vrect.h" + +#include "QF/ui/vrect.h" //#define TEST_MEMORY diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am index 0912e064c..827696908 100644 --- a/libs/util/Makemodule.am +++ b/libs/util/Makemodule.am @@ -80,10 +80,8 @@ libs_util_libQFutil_la_SOURCES= \ libs/util/sizebuf.c \ libs/util/string.c \ libs/util/sys.c \ - libs/util/txtbuffer.c \ libs/util/va.c \ libs/util/ver_check.c \ - libs/util/vrect.c \ libs/util/wad.c \ libs/util/wadfile.c \ libs/util/zone.c \ diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 2d12d0e92..977816418 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -51,7 +51,6 @@ #include "QF/render.h" #include "QF/sys.h" #include "QF/va.h" -#include "QF/vrect.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index 6bef378f5..9b80351ee 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -46,12 +46,13 @@ #include "QF/model.h" #include "QF/render.h" #include "QF/sys.h" -#include "QF/vrect.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" #include "QF/GLSL/qf_textures.h" +#include "QF/ui/vrect.h" + #include "r_scrap.h" struct scrap_s { diff --git a/libs/video/renderer/r_scrap.c b/libs/video/renderer/r_scrap.c index 86a4ca0a6..9bb6518d7 100644 --- a/libs/video/renderer/r_scrap.c +++ b/libs/video/renderer/r_scrap.c @@ -32,7 +32,8 @@ #endif #include "QF/sys.h" -#include "QF/vrect.h" + +#include "QF/ui/vrect.h" #include "compat.h" #include "r_scrap.h" diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index c4bf94ea1..f49fadd18 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -43,7 +43,6 @@ #include "QF/render.h" #include "QF/screen.h" #include "QF/sys.h" -#include "QF/view.h" #include "compat.h" #include "r_internal.h" diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index f84e4e9c8..4b6b1ae19 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -51,7 +51,6 @@ #include "QF/skin.h" #include "QF/sys.h" #include "QF/va.h" -#include "QF/vrect.h" #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_texture.h" diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 6c3ff0fbb..63ccd433e 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -50,7 +50,6 @@ #include "QF/render.h" #include "QF/sys.h" #include "QF/va.h" -#include "QF/vrect.h" #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 2288bd20c..e35b36737 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -61,6 +61,7 @@ nq_common_LIBFILES= \ libs/gib/libQFgib.la \ libs/ruamoko/libQFruamoko.la \ libs/gamecode/libQFgamecode.la \ + libs/ui/libQFui.la \ libs/util/libQFutil.la nq_client_LIBS= $(nq_client_LIBFILES) $(nq_common_LIBFILES) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index ca47f0ad4..2004b008e 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -47,12 +47,13 @@ #include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" -#include "QF/view.h" #include "QF/wad.h" #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/view.h" + #include "compat.h" #include "sbar.h" diff --git a/qtv/source/Makemodule.am b/qtv/source/Makemodule.am index 3560edecf..07af0ad6f 100644 --- a/qtv/source/Makemodule.am +++ b/qtv/source/Makemodule.am @@ -36,6 +36,7 @@ qtv_LIBS= \ libs/qw/libqw.a \ libs/net/libnet_chan.la \ libs/console/libQFconsole.la \ + libs/ui/libQFui.la \ libs/util/libQFutil.la qtv_server_SOURCES= qtv/source/client.c qtv/source/connection.c qtv/source/qtv.c qtv/source/sbar.c qtv/source/server.c qtv/source/sv_parse.c diff --git a/qtv/source/sbar.c b/qtv/source/sbar.c index c6e9ead8a..468a046b7 100644 --- a/qtv/source/sbar.c +++ b/qtv/source/sbar.c @@ -32,11 +32,12 @@ #endif #include "QF/console.h" -#include "QF/view.h" #include "QF/va.h" #include "QF/plugin/console.h" +#include "QF/ui/view.h" + #include "sv_console.h" #include "qtv/include/client.h" diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 7e9c1a61c..ef6e32ff5 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -67,6 +67,7 @@ qw_server_LIBS= \ libs/ruamoko/libQFruamoko.la \ libs/gamecode/libQFgamecode.la \ libs/console/libQFconsole.la \ + libs/ui/libQFui.la \ libs/util/libQFutil.la qw_server_deps=qw/source/libqw_server.a qw/source/libqw_common.a $(qw_server_LIBS) @@ -95,6 +96,7 @@ qw_client_LIBS= \ libs/image/libQFimage.la \ libs/gib/libQFgib.la \ libs/ruamoko/libQFruamoko.la \ + libs/ui/libQFui.la \ libs/util/libQFutil.la qw_client_libs= qw/source/libqw_client.a qw/source/libqw_common.a \ libs/client/libQFclient.la diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 4476b6933..c3af7a2f0 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -50,10 +50,11 @@ #include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" -#include "QF/view.h" #include "QF/plugin/console.h" +#include "QF/ui/view.h" + #include "compat.h" #include "qw/bothdefs.h" diff --git a/qw/source/sv_sbar.c b/qw/source/sv_sbar.c index 12aa9115a..81523ee33 100644 --- a/qw/source/sv_sbar.c +++ b/qw/source/sv_sbar.c @@ -32,9 +32,10 @@ #endif #include "QF/console.h" -#include "QF/view.h" #include "QF/va.h" +#include "QF/ui/view.h" + #include "QF/plugin/console.h" #include "sv_console.h" diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 378eb8505..0413f223b 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -46,6 +46,7 @@ qwaq_app_dat_src= \ qwaq_curses_libs= \ libs/video/targets/libvid_common.la \ libs/console/libQFconsole.la \ + libs/ui/libQFui.la \ libs/gib/libQFgib.la ruamoko_qwaq_qwaq_curses_SOURCES= \ @@ -66,6 +67,7 @@ qwaq_cl_plugin_libs= \ qwaq_client_libs= \ $(top_builddir)/libs/entity/libQFentity.la \ $(top_builddir)/libs/console/libQFconsole.la \ + $(top_builddir)/libs/ui/libQFui.la \ $(top_builddir)/libs/video/targets/libQFjs.la \ $(top_builddir)/libs/audio/libQFcd.la \ $(top_builddir)/libs/audio/libQFsound.la \ diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index 2cd8fd558..0a1f4981d 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -9,7 +9,8 @@ #include "QF/progs.h" #include "QF/ruamoko.h" #include "QF/quakeio.h" -#include "QF/txtbuffer.h" + +#include "QF/ui/txtbuffer.h" #include "ruamoko/qwaq/qwaq.h" #include "ruamoko/qwaq/editor/editbuffer.h" From 63eaf9e82346bb3d036070a116e69557fd0fcab8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Jun 2021 10:05:51 +0900 Subject: [PATCH 1578/3664] [image] Correct disabled LoadPNG declaration Fixes #14 --- libs/image/png.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/image/png.c b/libs/image/png.c index ddf9066a9..f8fdbcbf6 100644 --- a/libs/image/png.c +++ b/libs/image/png.c @@ -318,7 +318,7 @@ WritePNGqfs (const char *fileName, const byte *data, int width, int height) #include "QF/png.h" VISIBLE tex_t * -LoadPNG (QFile *infile) +LoadPNG (QFile *infile, int load) { return 0; } From 13b4b44e35b4f15c80f986225756d5ef61c77c67 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Jun 2021 13:25:18 +0900 Subject: [PATCH 1579/3664] [qfcc] Handle l and ll integer suffixes They're ignored, but allow recent vulkan headers to compile. Fixes #13 --- tools/qfcc/source/qc-lex.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 50e54817d..1a3cb9d99 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -122,7 +122,7 @@ STRING \"(\\.|[^"\\])*\" ^{s}*#{s}*pragma{s}+ { BEGIN (PRAGMA); } -{INT}+[uU]? { +{INT}+[uU]?([lL][lL]?)? { const char *c = yytext + yyleng - 1; int i; From 24fd443ef39a654c73984c630caaea667b400f30 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Jun 2021 14:29:46 +0900 Subject: [PATCH 1580/3664] [ui] Move txtbuffer and vrect tests to libs/ui Fixes make check --- libs/ui/Makemodule.am | 2 +- libs/ui/test/Makemodule.am | 15 +++++++++++++++ libs/{util => ui}/test/test-txtbuffer.c | 2 +- libs/{util => ui}/test/test-vrect.c | 2 +- libs/util/test/Makemodule.am | 12 +----------- 5 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 libs/ui/test/Makemodule.am rename libs/{util => ui}/test/test-txtbuffer.c (99%) rename libs/{util => ui}/test/test-vrect.c (99%) diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am index 4a76ecffb..a1d72a36e 100644 --- a/libs/ui/Makemodule.am +++ b/libs/ui/Makemodule.am @@ -1,4 +1,4 @@ -#include libs/ui/test/Makemodule.am +include libs/ui/test/Makemodule.am lib_LTLIBRARIES += libs/ui/libQFui.la diff --git a/libs/ui/test/Makemodule.am b/libs/ui/test/Makemodule.am new file mode 100644 index 000000000..7922c9439 --- /dev/null +++ b/libs/ui/test/Makemodule.am @@ -0,0 +1,15 @@ +libs_ui_tests = \ + libs/ui/test/test-txtbuffer \ + libs/ui/test/test-vrect + +TESTS += $(libs_ui_tests) + +check_PROGRAMS += $(libs_ui_tests) + +libs_ui_test_test_txtbuffer_SOURCES=libs/ui/test/test-txtbuffer.c +libs_ui_test_test_txtbuffer_LDADD=libs/ui/libQFui.la +libs_ui_test_test_txtbuffer_DEPENDENCIES=libs/ui/libQFui.la + +libs_ui_test_test_vrect_SOURCES=libs/ui/test/test-vrect.c +libs_ui_test_test_vrect_LDADD=libs/ui/libQFui.la +libs_ui_test_test_vrect_DEPENDENCIES=libs/ui/libQFui.la diff --git a/libs/util/test/test-txtbuffer.c b/libs/ui/test/test-txtbuffer.c similarity index 99% rename from libs/util/test/test-txtbuffer.c rename to libs/ui/test/test-txtbuffer.c index 44ccebdc9..81e24f621 100644 --- a/libs/util/test/test-txtbuffer.c +++ b/libs/ui/test/test-txtbuffer.c @@ -4,7 +4,7 @@ #include #include -#include "QF/txtbuffer.h" +#include "QF/ui/txtbuffer.h" static size_t check_text_ptr (txtbuffer_t *buffer, size_t offset, const char *txt, diff --git a/libs/util/test/test-vrect.c b/libs/ui/test/test-vrect.c similarity index 99% rename from libs/util/test/test-vrect.c rename to libs/ui/test/test-vrect.c index ab2558e8f..6adc4452e 100644 --- a/libs/util/test/test-vrect.c +++ b/libs/ui/test/test-vrect.c @@ -3,7 +3,7 @@ #endif #include -#include "QF/vrect.h" +#include "QF/ui/vrect.h" #define VR(x,y,w,h) {x,y,w,h,0} #define VRn(x,y,w,h,n) {x,y,w,h,n} diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index e14c05ccf..120780135 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -18,9 +18,7 @@ libs_util_tests = \ libs/util/test/test-sebvf \ libs/util/test/test-seg \ libs/util/test/test-set \ - libs/util/test/test-simd \ - libs/util/test/test-txtbuffer \ - libs/util/test/test-vrect + libs/util/test/test-simd TESTS += $(libs_util_tests) @@ -105,11 +103,3 @@ libs_util_test_test_set_DEPENDENCIES=libs/util/libQFutil.la libs_util_test_test_simd_SOURCES=libs/util/test/test-simd.c libs_util_test_test_simd_LDADD=libs/util/libQFutil.la libs_util_test_test_simd_DEPENDENCIES=libs/util/libQFutil.la - -libs_util_test_test_txtbuffer_SOURCES=libs/util/test/test-txtbuffer.c -libs_util_test_test_txtbuffer_LDADD=libs/util/libQFutil.la -libs_util_test_test_txtbuffer_DEPENDENCIES=libs/util/libQFutil.la - -libs_util_test_test_vrect_SOURCES=libs/util/test/test-vrect.c -libs_util_test_test_vrect_LDADD=libs/util/libQFutil.la -libs_util_test_test_vrect_DEPENDENCIES=libs/util/libQFutil.la From 93167279fc4ddae4cdaf0f19f6c6da413e8d4836 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Jun 2021 14:30:59 +0900 Subject: [PATCH 1581/3664] Fix a bunch of issues found by gcc-11 --- include/QF/math/matrix3.h | 2 +- include/QF/simd/vec4f.h | 4 ++-- include/netchan.h | 4 ++-- libs/models/winding.c | 2 ++ tools/qfbsp/source/writebsp.c | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/QF/math/matrix3.h b/include/QF/math/matrix3.h index dfe9b530f..978ca1868 100644 --- a/include/QF/math/matrix3.h +++ b/include/QF/math/matrix3.h @@ -116,7 +116,7 @@ void Mat3SymEigen (const mat3_t m, vec3_t e); VectorShear (shear, v, v); VectorCompMult (scale, v, v); */ -int Mat3Decompose (const mat4_t mat, quat_t rot, vec3_t shear, vec3_t scale); +int Mat3Decompose (const mat3_t mat, quat_t rot, vec3_t shear, vec3_t scale); ///@} diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 07498d706..4cf370101 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -352,7 +352,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -loadvec3f (const float v3[3]) +loadvec3f (const float *v3) { vec4f_t v4; @@ -381,7 +381,7 @@ GNU89INLINE inline VISIBLE #endif void -storevec3f (float v3[3], vec4f_t v4) +storevec3f (float *v3, vec4f_t v4) { v3[0] = v4[0]; v3[1] = v4[1]; diff --git a/include/netchan.h b/include/netchan.h index d502f1030..f90e4f170 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -112,7 +112,7 @@ void NET_SendPacket (int length, const void *data, netadr_t to); \param b The second address to compare. \return True of the addresses match, otherwise false. */ -qboolean NET_CompareAdr (netadr_t a, netadr_t b) __attribute__((pure)); +qboolean NET_CompareAdr (netadr_t a, netadr_t b) __attribute__((const)); /** Compare two network addresses. @@ -122,7 +122,7 @@ qboolean NET_CompareAdr (netadr_t a, netadr_t b) __attribute__((pure)); \param b The second address to compare. \return True of the addresses match, otherwise false. */ -qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) __attribute__((pure)); +qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) __attribute__((const)); /** Convert an address to a string. diff --git a/libs/models/winding.c b/libs/models/winding.c index 62ae9fcb8..7c81b28bf 100644 --- a/libs/models/winding.c +++ b/libs/models/winding.c @@ -171,6 +171,8 @@ ClipWinding (winding_t *in, plane_t *split, qboolean keepon) // +1 for duplicating the first point sides = alloca ((in->numpoints + 1) * sizeof (int)); dists = alloca ((in->numpoints + 1) * sizeof (vec_t)); + sides[0] = 0; + dists[0] = 0; // determine sides for each point for (i = 0; i < in->numpoints; i++) { diff --git a/tools/qfbsp/source/writebsp.c b/tools/qfbsp/source/writebsp.c index dd7d0fa99..9001b92dc 100644 --- a/tools/qfbsp/source/writebsp.c +++ b/tools/qfbsp/source/writebsp.c @@ -124,7 +124,7 @@ WriteNodePlanes (node_t *nodes) static int WriteClipNodes_r (node_t *node) { - dclipnode_t cn; + dclipnode_t cn = { }; int num, c, i; // FIXME: free more stuff? From 36df16eefcaee62fb64614fbfe3576e282e3e5f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Jun 2021 15:00:30 +0900 Subject: [PATCH 1582/3664] [util] Fix incorrect type in test-mat3 Fixes make check for gcc-11 --- libs/util/test/test-mat3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/util/test/test-mat3.c b/libs/util/test/test-mat3.c index f852d281a..903c4de9f 100644 --- a/libs/util/test/test-mat3.c +++ b/libs/util/test/test-mat3.c @@ -127,7 +127,8 @@ test_transform2 (const vec3_t angles, const vec3_t scale) vec3_t x, y; quat_t rotation; mat3_t mat; - vec3_t rot, sc, sh; + quat_t rot; + vec3_t sc, sh; VectorCopy (v, x); AngleQuat (angles, rotation); From 2278f5e4948f49f6ac64068b72e0e5dd4588166f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Jun 2021 22:13:47 +0900 Subject: [PATCH 1583/3664] [gamecode] Make def type when indexing size Fixes #12 However, this is a bit of a band-aid in that the code for global defs seems redundant (there is very similar code a little above that is always executed) and the code for field defs should probably be executed unconditionally: I suspect the problem fixed by d5454faeb76940253c78ed108e2e0647dfb04af7 still shows with game coded compiled with recent versions of the compiler, I just haven't tested any. --- libs/gamecode/pr_load.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 2bca49575..93a69e17d 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -257,7 +257,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->pr_statements[i].c = LittleShort (pr->pr_statements[i].c); } - for (i = 0; i < (size_t) pr->progs->numfunctions; i++) { + for (i = 0; i < pr->progs->numfunctions; i++) { pr->pr_functions[i].first_statement = LittleLong (pr->pr_functions[i].first_statement); pr->pr_functions[i].parm_start = @@ -328,11 +328,11 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr_def_t *def; for (def = pr->pr_globaldefs, i = 0; i < pr->progs->numglobaldefs; i++, def++) { - def->size = pr_type_size[def->type]; + def->size = pr_type_size[def->type & ~DEF_SAVEGLOBAL]; } for (def = pr->pr_fielddefs, i = 0; i < pr->progs->numfielddefs; i++, def++) { - def->size = pr_type_size[def->type]; + def->size = pr_type_size[def->type & ~DEF_SAVEGLOBAL]; } } pr->pr_trace = 0; From 881add2c5191f9cf88ba364c9ac74ae390d6b9b8 Mon Sep 17 00:00:00 2001 From: Ionen Wolkens Date: Sun, 13 Jun 2021 10:12:03 -0400 Subject: [PATCH 1584/3664] Add GNU-stack notes to assembly files Prevents GCC from assuming an executable stack is needed. Signed-off-by: Ionen Wolkens --- libs/util/math.S | 4 ++++ libs/util/sys_ia32.S | 4 ++++ libs/video/renderer/sw/d_copy.S | 4 ++++ libs/video/renderer/sw/d_draw.S | 4 ++++ libs/video/renderer/sw/d_parta.S | 4 ++++ libs/video/renderer/sw/d_polysa.S | 3 +++ libs/video/renderer/sw/d_scana.S | 3 +++ libs/video/renderer/sw/d_spr8.S | 4 ++++ libs/video/renderer/sw/d_varsa.S | 3 +++ libs/video/renderer/sw/fpua.S | 4 ++++ libs/video/renderer/sw/surf8.S | 4 ++++ libs/video/renderer/sw/sw_raclipa.S | 3 +++ libs/video/renderer/sw/sw_raliasa.S | 3 +++ libs/video/renderer/sw/sw_rdrawa.S | 3 +++ libs/video/renderer/sw/sw_redgea.S | 3 +++ libs/video/renderer/sw/sw_rvarsa.S | 3 +++ libs/video/renderer/sw/transform.S | 4 ++++ 17 files changed, 60 insertions(+) diff --git a/libs/util/math.S b/libs/util/math.S index 1118da8c9..f3e1fa13e 100644 --- a/libs/util/math.S +++ b/libs/util/math.S @@ -392,3 +392,7 @@ Lerror: #endif #endif // USE_INTEL_ASM + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/util/sys_ia32.S b/libs/util/sys_ia32.S index 65d7b7388..f993d945b 100644 --- a/libs/util/sys_ia32.S +++ b/libs/util/sys_ia32.S @@ -85,3 +85,7 @@ F_BEGIN(Sys_MaskFPUExceptions) ret F_END(Sys_MaskFPUExceptions) #endif /* USE_INTEL_ASM */ + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/d_copy.S b/libs/video/renderer/sw/d_copy.S index 24f7ded26..722c64d5f 100644 --- a/libs/video/renderer/sw/d_copy.S +++ b/libs/video/renderer/sw/d_copy.S @@ -178,3 +178,7 @@ LLRowLoop: ret #endif /* USE_INTEL_ASM */ + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/d_draw.S b/libs/video/renderer/sw/d_draw.S index 15e33d33c..e4642025b 100644 --- a/libs/video/renderer/sw/d_draw.S +++ b/libs/video/renderer/sw/d_draw.S @@ -1046,3 +1046,7 @@ LFDone: ret #endif // USE_INTEL_ASM + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/d_parta.S b/libs/video/renderer/sw/d_parta.S index fb004638d..30cede548 100644 --- a/libs/video/renderer/sw/d_parta.S +++ b/libs/video/renderer/sw/d_parta.S @@ -485,3 +485,7 @@ LPop1AndDone: jmp LDone #endif // USE_INTEL_ASM + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/d_polysa.S b/libs/video/renderer/sw/d_polysa.S index 8ea71258c..ec2511e30 100644 --- a/libs/video/renderer/sw/d_polysa.S +++ b/libs/video/renderer/sw/d_polysa.S @@ -1753,3 +1753,6 @@ LNextTri: #endif // USE_INTEL_ASM +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/d_scana.S b/libs/video/renderer/sw/d_scana.S index 4c9a62da4..6ca194e72 100644 --- a/libs/video/renderer/sw/d_scana.S +++ b/libs/video/renderer/sw/d_scana.S @@ -98,3 +98,6 @@ Llp: #endif // USE_INTEL_ASM +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/d_spr8.S b/libs/video/renderer/sw/d_spr8.S index 5739f7ee1..fcda6abd6 100644 --- a/libs/video/renderer/sw/d_spr8.S +++ b/libs/video/renderer/sw/d_spr8.S @@ -909,3 +909,7 @@ LNextSpan: ret #endif // USE_INTEL_ASM + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/d_varsa.S b/libs/video/renderer/sw/d_varsa.S index ece5dc2c1..bb6eb6f42 100644 --- a/libs/video/renderer/sw/d_varsa.S +++ b/libs/video/renderer/sw/d_varsa.S @@ -203,3 +203,6 @@ C(spr8entryvec_table): .long 0, C(Spr8Entry2_8), C(Spr8Entry3_8), C(Spr8Entry4_8 #endif // USE_INTEL_ASM +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/fpua.S b/libs/video/renderer/sw/fpua.S index bfe166ee4..df568dcac 100644 --- a/libs/video/renderer/sw/fpua.S +++ b/libs/video/renderer/sw/fpua.S @@ -153,3 +153,7 @@ F_BEGIN(R_SetFPCW) ret F_END(R_SetFPCW) #endif /* USE_INTEL_ASM */ + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/surf8.S b/libs/video/renderer/sw/surf8.S index 59186143e..c15d2c689 100644 --- a/libs/video/renderer/sw/surf8.S +++ b/libs/video/renderer/sw/surf8.S @@ -793,3 +793,7 @@ LPatchLoop8: ret #endif // USE_INTEL_ASM + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/sw_raclipa.S b/libs/video/renderer/sw/sw_raclipa.S index 6af9666b7..510b1fb43 100644 --- a/libs/video/renderer/sw/sw_raclipa.S +++ b/libs/video/renderer/sw/sw_raclipa.S @@ -322,3 +322,6 @@ C(R_Alias_clip_left): #endif // USE_INTEL_ASM +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/sw_raliasa.S b/libs/video/renderer/sw/sw_raliasa.S index 6da8aa673..31df86303 100644 --- a/libs/video/renderer/sw/sw_raliasa.S +++ b/libs/video/renderer/sw/sw_raliasa.S @@ -246,3 +246,6 @@ Lsavelight: #endif // USE_INTEL_ASM +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/sw_rdrawa.S b/libs/video/renderer/sw/sw_rdrawa.S index 8fdde816a..f7b9a4acd 100644 --- a/libs/video/renderer/sw/sw_rdrawa.S +++ b/libs/video/renderer/sw/sw_rdrawa.S @@ -847,3 +847,6 @@ LClampP3: #endif // USE_INTEL_ASM +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/sw_redgea.S b/libs/video/renderer/sw/sw_redgea.S index c549d36f4..ec2b53eed 100644 --- a/libs/video/renderer/sw/sw_redgea.S +++ b/libs/video/renderer/sw/sw_redgea.S @@ -759,3 +759,6 @@ C(R_SurfacePatch): #endif // USE_INTEL_ASM +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/sw_rvarsa.S b/libs/video/renderer/sw/sw_rvarsa.S index be32f8918..523d0e71b 100644 --- a/libs/video/renderer/sw/sw_rvarsa.S +++ b/libs/video/renderer/sw/sw_rvarsa.S @@ -87,3 +87,6 @@ C(R_InitVars): #endif // USE_INTEL_ASM +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/libs/video/renderer/sw/transform.S b/libs/video/renderer/sw/transform.S index b9b2f3d3f..f25e78630 100644 --- a/libs/video/renderer/sw/transform.S +++ b/libs/video/renderer/sw/transform.S @@ -110,3 +110,7 @@ C(TransformVector): ret #endif // USE_INTEL_ASM + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif From 8db195745275244bc0ed9692546b45a409ef6173 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Jun 2021 11:23:51 +0900 Subject: [PATCH 1585/3664] [ruamoko] Add bindings for exp() --- libs/ruamoko/rua_math.c | 14 ++++++++++++++ ruamoko/include/math.h | 6 ++++++ ruamoko/lib/math.r | 2 ++ 3 files changed, 22 insertions(+) diff --git a/libs/ruamoko/rua_math.c b/libs/ruamoko/rua_math.c index a81d33356..f6926fa65 100644 --- a/libs/ruamoko/rua_math.c +++ b/libs/ruamoko/rua_math.c @@ -83,6 +83,12 @@ bi_atan2f (progs_t *pr) R_FLOAT (pr) = atan2f (P_FLOAT (pr, 0), P_FLOAT (pr, 1)); } +static void +bi_expf (progs_t *pr) +{ + R_FLOAT (pr) = expf (P_FLOAT (pr, 0)); +} + static void bi_logf (progs_t *pr) { @@ -228,6 +234,12 @@ bi_atan2 (progs_t *pr) R_DOUBLE (pr) = atan2 (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1)); } +static void +bi_exp (progs_t *pr) +{ + R_DOUBLE (pr) = exp (P_DOUBLE (pr, 0)); +} + static void bi_log (progs_t *pr) { @@ -317,6 +329,7 @@ static builtin_t builtins[] = { {"acos|f", bi_acosf, -1}, {"atan|f", bi_atanf, -1}, {"atan2|ff",bi_atan2f, -1}, + {"exp|f", bi_expf, -1}, {"log|f", bi_logf, -1}, {"log2|f", bi_log2f, -1}, {"log10|f", bi_log10f, -1}, @@ -340,6 +353,7 @@ static builtin_t builtins[] = { {"acos|d", bi_acos, -1}, {"atan|d", bi_atan, -1}, {"atan2|dd",bi_atan2, -1}, + {"exp|d", bi_exp, -1}, {"log|d", bi_log, -1}, {"log2|d", bi_log2, -1}, {"log10|d", bi_log10, -1}, diff --git a/ruamoko/include/math.h b/ruamoko/include/math.h index d6ad33342..5c3978b1c 100644 --- a/ruamoko/include/math.h +++ b/ruamoko/include/math.h @@ -78,6 +78,12 @@ ///\name Exponentials and Logarithms //\{ +/** + Returns e to the power of \a x. +*/ +@extern @overload float exp (float x); +@extern @overload double exp (double x); + /** Returns the natural log of \a x. */ diff --git a/ruamoko/lib/math.r b/ruamoko/lib/math.r index 47624527a..13b206602 100644 --- a/ruamoko/lib/math.r +++ b/ruamoko/lib/math.r @@ -21,6 +21,7 @@ float (float x) asin = #0; float (float x) acos = #0; float (float x) atan = #0; float (float y, float x) atan2 = #0; +float (float x) exp = #0; float (float x) log = #0; float (float x) log2 = #0; float (float x) log10 = #0; @@ -45,6 +46,7 @@ double (double x) asin = #0; double (double x) acos = #0; double (double x) atan = #0; double (double y, double x) atan2 = #0; +double (double x) exp = #0; double (double x) log = #0; double (double x) log2 = #0; double (double x) log10 = #0; From 12ab283c22dd550fbb798f86a55c240c05fabab5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Jun 2021 11:25:05 +0900 Subject: [PATCH 1586/3664] [qwaq] Add a little z-transform program And fix an error in floatview. The z-transform program is so I can test out my math and eventually develop some hopefully interesting sound generators. --- ruamoko/qwaq/Makemodule.am | 10 ++++- ruamoko/qwaq/debugger/views/floatview.r | 2 +- ruamoko/qwaq/z-transform.r | 50 +++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 ruamoko/qwaq/z-transform.r diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 0413f223b..336a79050 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -2,7 +2,7 @@ QWAQ_LIBS=@QWAQ_LIBS@ QWAQ_DEPS=@QWAQ_DEPS@ QWAQ_INCS=@QWAQ_INCS@ -noinst_PROGRAMS += @QWAQ_TARGETS@ ruamoko/qwaq/qwaq-app.dat$(EXEEXT) ruamoko/qwaq/gcd.dat$(EXEEXT) +noinst_PROGRAMS += @QWAQ_TARGETS@ ruamoko/qwaq/qwaq-app.dat$(EXEEXT) ruamoko/qwaq/gcd.dat$(EXEEXT) ruamoko/qwaq/z-transform.dat$(EXEEXT) qwaq_app_dat_src= \ ruamoko/qwaq/qwaq-app.r \ @@ -103,6 +103,14 @@ ruamoko/qwaq/gcd.dat$(EXEEXT): $(ruamoko_qwaq_gcd_obj) $(QFCC_DEP) ruamoko/lib/l include $(ruamoko_qwaq_gcd_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_gcd_dep) +ruamoko_qwaq_z_transform_dat_SOURCES=ruamoko/qwaq/z-transform.r +ruamoko_qwaq_z_transform_obj=$(ruamoko_qwaq_z_transform_dat_SOURCES:.r=.o) +ruamoko_qwaq_z_transform_dep=$(call qcautodep,$(ruamoko_qwaq_z_transform_dat_SOURCES:.o=.Qo)) +ruamoko/qwaq/z-transform.dat$(EXEEXT): $(ruamoko_qwaq_z_transform_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_z_transform_obj) -lcsqc -lr +include $(ruamoko_qwaq_z_transform_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_qwaq_z_transform_dep) + EXTRA_PROGRAMS += ruamoko/qwaq/qwaq-curses ruamoko/qwaq/qwaq-x11 EXTRA_DIST += \ $(qwaq_dat_src) \ diff --git a/ruamoko/qwaq/debugger/views/floatview.r b/ruamoko/qwaq/debugger/views/floatview.r index 00f666e69..516670815 100644 --- a/ruamoko/qwaq/debugger/views/floatview.r +++ b/ruamoko/qwaq/debugger/views/floatview.r @@ -20,7 +20,7 @@ -draw { [super draw]; - string val = sprintf ("%.9", data[0]); + string val = sprintf ("%.9g", data[0]); [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; return self; } diff --git a/ruamoko/qwaq/z-transform.r b/ruamoko/qwaq/z-transform.r new file mode 100644 index 000000000..328e8fd3c --- /dev/null +++ b/ruamoko/qwaq/z-transform.r @@ -0,0 +1,50 @@ +#include + +void printf (string fnt, ...) = #0; + +#define SAMPLES 4 +float output[SAMPLES]; +float input[SAMPLES]; + +float T=0.1; +float w=2; +float a=0.5; + +float A[3], B[3]; + +void +z_transform (float *y, float *x, float *A, float *B, int n, int zind) +{ + zind %= SAMPLES; + float c = x[zind] * A[0]; + for (int i = 1; i < n; i++) { + int z = (SAMPLES + zind - i) % SAMPLES; + c += x[z] * A[i] - y[z] * B[i]; + } + y[zind] = c / B[0]; +} + +int +main () +{ + float e = exp (-a*T); + float c = cos (w*T); + float s = sin (w*T); + + B[0] = 1; + B[1] = -2 * e * c; + B[2] = e * e; + + A[0] = 0; + A[1] = 1 - e*(c + (a/w)*s); + A[2] = e*e + e*((a/w)*s - c); + + for (int i = 0; i < 200; i++) { + int ind = i % SAMPLES; + input[ind] = 1;//i ? 0 : 1; + z_transform (output, input, A, B, 3, i); + printf ("%2d %7.4f %7.4f\n", i, input[ind], output[ind]); + } + + return 0; +} From 770187372dcf00367fd254c2596bfdec86c1342f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Jun 2021 16:40:40 +0900 Subject: [PATCH 1587/3664] [audio] Get testsound working again --- config.d/build_control.m4 | 2 +- libs/audio/Makemodule.am | 1 + libs/audio/test/Makefile.am | 16 ---------------- libs/audio/test/Makemodule.am | 12 ++++++++++++ libs/audio/test/testsound.c | 2 +- 5 files changed, 15 insertions(+), 18 deletions(-) delete mode 100644 libs/audio/test/Makefile.am create mode 100644 libs/audio/test/Makemodule.am diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 1b888ce14..c324b28aa 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -354,7 +354,7 @@ QF_PROCESS_NEED_LIBS(nq, [client common sdl win server], [nq/source], a) if test -n "$CL_TARGETS"; then CD_TARGETS="libs/audio/libQFcd.la" SND_TARGETS="libs/audio/libQFsound.la" - AUDIO_TARGETS="testsound\$(EXEEXT)" + AUDIO_TARGETS="libs/audio/test/testsound\$(EXEEXT)" JOY_TARGETS="libs/video/targets/libQFjs.la" else unset CDTYPE diff --git a/libs/audio/Makemodule.am b/libs/audio/Makemodule.am index c649c7351..8c371c680 100644 --- a/libs/audio/Makemodule.am +++ b/libs/audio/Makemodule.am @@ -1,5 +1,6 @@ include libs/audio/targets/Makemodule.am include libs/audio/renderer/Makemodule.am +include libs/audio/test/Makemodule.am plugin_LTLIBRARIES += @cd_plugins@ noinst_LTLIBRARIES += @cd_static_plugins@ diff --git a/libs/audio/test/Makefile.am b/libs/audio/test/Makefile.am deleted file mode 100644 index ff6d259a4..000000000 --- a/libs/audio/test/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -AUTOMAKE_OPTIONS= foreign - -AM_CPPFLAGS= -I$(top_srcdir)/include - -noinst_PROGRAMS= @AUDIO_TARGETS@ - -EXTRA_PROGRAMS= testsound - -test_libs= \ - libs/audio/libQFsound.la \ - libs/ruamoko/libQFruamoko.la \ - libs/util/libQFutil.la - -testsound_SOURCES= testsound.c -testsound_LDADD= $(test_libs) -testsound_DEPENDENCIES= $(test_libs) diff --git a/libs/audio/test/Makemodule.am b/libs/audio/test/Makemodule.am new file mode 100644 index 000000000..e1a4800b0 --- /dev/null +++ b/libs/audio/test/Makemodule.am @@ -0,0 +1,12 @@ +noinst_PROGRAMS += @AUDIO_TARGETS@ + +EXTRA_PROGRAMS += libs/audio/test/testsound + +testaudio_libs= \ + libs/audio/libQFsound.la \ + libs/ruamoko/libQFruamoko.la \ + libs/util/libQFutil.la + +libs_audio_test_testsound_SOURCES= libs/audio/test/testsound.c +libs_audio_test_testsound_LDADD= $(testaudio_libs) +libs_audio_test_testsound_DEPENDENCIES= $(testaudio_libs) diff --git a/libs/audio/test/testsound.c b/libs/audio/test/testsound.c index 698fc40ec..b513df3cf 100644 --- a/libs/audio/test/testsound.c +++ b/libs/audio/test/testsound.c @@ -65,7 +65,7 @@ init (void) testsound_args = Cbuf_ArgsNew (); Sys_Init (); - COM_ParseConfig (); + COM_ParseConfig (testsound_cbuf); Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); Memory_Init (Sys_Alloc (MEMSIZE), MEMSIZE); From 097d44e2709bb2d095197dca3372219a848da250 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Jun 2021 16:41:15 +0900 Subject: [PATCH 1588/3664] [util] Handle double shutdown If Sys_Shutdown gets called twice, particularly if a shutdown callback hangs and the program is killed with INT or QUIT, shutdown_list would be in an invalid state. Thus, get the required data (function pointer and data pointer) from the list element, then unlink the element before calling the function. This ensures that a reinvocation of Sys_Shutdown continues from the next callback or ends cleanly. Fixes a segfault when killing testsound while using the oss output (it hangs on shutdown). --- libs/util/sys.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/util/sys.c b/libs/util/sys.c index 8758f270a..87241a8c1 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -483,10 +483,13 @@ Sys_Shutdown (void) shutdown_list_t *t; while (shutdown_list) { - shutdown_list->func (shutdown_list->data); + void (*func) (void *) = shutdown_list->func; + void *data = shutdown_list->data; t = shutdown_list; shutdown_list = shutdown_list->next; free (t); + + func (data); } } From 421421e038077d88959d303ae53b987d31852edc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 22 Jun 2021 11:33:22 +0900 Subject: [PATCH 1589/3664] [audio] Correct alsa period size calculation and rename the variable since it's not the size of the frame (may be from the very early days of ALSA development, and I suspect the terminology changed a bit). The calculation was including the bits per sample, which makes no sense as the period size determines the number of samples in a submission chunk (and thus latency). For now, set it to around 5.5ms (will probably need a cvar). --- libs/audio/targets/snd_alsa.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 329d1a0e7..399baae9b 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -201,7 +201,7 @@ SNDDMA_Init (void) snd_pcm_hw_params_t **_hw = &hw; snd_pcm_sw_params_t *sw; snd_pcm_sw_params_t **_sw = &sw; - snd_pcm_uframes_t frag_size; + snd_pcm_uframes_t period_size; if (!load_libasound ()) return false; @@ -339,7 +339,6 @@ retry_open: err = qfsnd_pcm_hw_params_set_rate_near (pcm, hw, &rate, 0); if (0 <= err) { - frag_size = 8 * bps * (rate / 11025); break; } } @@ -360,16 +359,20 @@ retry_open: qfsnd_strerror (err)); goto error; } - frag_size = 8 * bps * (rate / 11025); break; } - err = qfsnd_pcm_hw_params_set_period_size_near (pcm, hw, &frag_size, 0); + // works out to about 5.5ms (5.3 for 48k, 5.8 for 44k1) but consistent for + // different sample rates + period_size = 64 * (rate / 11025); + err = qfsnd_pcm_hw_params_set_period_size_near (pcm, hw, &period_size, 0); if (0 > err) { Sys_Printf ("ALSA: unable to set period size near %i. %s\n", - (int) frag_size, qfsnd_strerror (err)); + (int) period_size, qfsnd_strerror (err)); goto error; } + int dir; + qfsnd_pcm_hw_params_get_period_size (hw, &period_size, &dir); err = qfsnd_pcm_hw_params (pcm, hw); if (0 > err) { Sys_Printf ("ALSA: unable to install hw params: %s\n", @@ -432,11 +435,14 @@ retry_open: sn.frames = buffer_size; sn.speed = rate; SNDDMA_GetDMAPos (); //XXX sets sn.buffer - Sys_Printf ("%5d channels\n", sn.channels); - Sys_Printf ("%5d samples\n", sn.frames); + Sys_Printf ("%5d channels %sinterleaved\n", sn.channels, + sn.xfer ? "non-" : ""); + Sys_Printf ("%5d samples (%.1fms)\n", sn.frames, + 1000.0 * sn.frames / sn.speed); Sys_Printf ("%5d samplepos\n", sn.framepos); Sys_Printf ("%5d samplebits\n", sn.samplebits); - Sys_Printf ("%5d submission_chunk\n", sn.submission_chunk); + Sys_Printf ("%5d submission_chunk (%.1fms)\n", sn.submission_chunk, + 1000.0 * sn.submission_chunk / sn.speed); Sys_Printf ("%5d speed\n", sn.speed); Sys_Printf ("0x%lx dma buffer\n", (long) sn.buffer); From db322ce88b1270ae07cb908e1ebf3d1cce44ec79 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 22 Jun 2021 15:35:37 +0900 Subject: [PATCH 1590/3664] [audio] Clean up snd_render.h namespace polution There's no need for the function typedefs and the warts on the member names were... warty. Also, group the members logically. --- include/QF/plugin/snd_render.h | 65 +++++++++++++--------------------- libs/audio/renderer/snd_dma.c | 30 ++++++++-------- libs/audio/renderer/snd_jack.c | 34 ++++++++---------- libs/audio/snd.c | 32 ++++++++--------- 4 files changed, 69 insertions(+), 92 deletions(-) diff --git a/include/QF/plugin/snd_render.h b/include/QF/plugin/snd_render.h index 437367228..078b6f01d 100644 --- a/include/QF/plugin/snd_render.h +++ b/include/QF/plugin/snd_render.h @@ -30,54 +30,37 @@ #include #include -/* - All sound plugins must export these functions -*/ - struct sfx_s; -typedef void (*P_S_Init) (void); -typedef void (*P_S_Shutdown) (void); -typedef void (*P_S_AmbientOff) (void); -typedef void (*P_S_AmbientOn) (void); -typedef void (*P_S_StartSound) (int entnum, int entchannel, struct sfx_s *sfx, const vec3_t origin, float fvol, float attenuation); -typedef void (*P_S_StaticSound) (struct sfx_s *sfx, const vec3_t origin, float vol, float attenuation); -typedef void (*P_S_StopSound) (int entnum, int entchannel); -typedef struct sfx_s * (*P_S_PrecacheSound) (const char *sample); -typedef void (*P_S_Update) (const vec3_t origin, const vec3_t v_forward, const vec3_t v_right, const vec3_t v_up, const byte *ambient_sound_level); -typedef void (*P_S_StopAllSounds) (void); -typedef void (*P_S_ExtraUpdate) (void); -typedef void (*P_S_LocalSound) (const char *s); -typedef void (*P_S_BlockSound) (void); -typedef void (*P_S_UnblockSound) (void); -typedef struct sfx_s *(*P_S_LoadSound) (const char *name); -typedef struct channel_s *(*P_S_AllocChannel) (void); -typedef void (*P_S_ChannelStop) (struct channel_s *chan); - typedef struct snd_render_funcs_s { - P_S_AmbientOff pS_AmbientOff; - P_S_AmbientOn pS_AmbientOn; - P_S_StaticSound pS_StaticSound; - P_S_StartSound pS_StartSound; - P_S_StopSound pS_StopSound; - P_S_PrecacheSound pS_PrecacheSound; - P_S_Update pS_Update; - P_S_StopAllSounds pS_StopAllSounds; - P_S_ExtraUpdate pS_ExtraUpdate; - P_S_LocalSound pS_LocalSound; - P_S_BlockSound pS_BlockSound; - P_S_UnblockSound pS_UnblockSound; - P_S_LoadSound pS_LoadSound; - P_S_AllocChannel pS_AllocChannel; - P_S_ChannelStop pS_ChannelStop; + void (*ambient_off) (void); + void (*ambient_on) (void); + void (*static_sound) (struct sfx_s *sfx, const vec3_t origin, float vol, float attenuation); + void (*start_sound) (int entnum, int entchannel, struct sfx_s *sfx, const vec3_t origin, float fvol, float attenuation); + void (*local_sound) (const char *s); + void (*stop_sound) (int entnum, int entchannel); + + struct channel_s *(*alloc_channel) (void); + void (*channel_stop) (struct channel_s *chan); + + struct sfx_s *(*precache_sound) (const char *sample); + struct sfx_s *(*load_sound) (const char *name); + + void (*update) (const vec3_t origin, const vec3_t v_forward, + const vec3_t v_right, const vec3_t v_up, + const byte *ambient_sound_levels); + void (*stop_all_sounds) (void); + void (*extra_update) (void); + void (*block_sound) (void); + void (*unblock_sound) (void); } snd_render_funcs_t; typedef struct snd_render_data_s { - double *host_frametime; - int *viewentity; + double *host_frametime; + int *viewentity; - unsigned int *soundtime; - unsigned int *paintedtime; + unsigned *soundtime; + unsigned *paintedtime; struct plugin_s *output; } snd_render_data_t; diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 0d3d883f0..6c06b156c 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -362,21 +362,21 @@ static general_funcs_t plugin_info_general_funcs = { }; static snd_render_funcs_t plugin_info_render_funcs = { - SND_AmbientOff, - SND_AmbientOn, - SND_StaticSound, - SND_StartSound, - SND_StopSound, - SND_PrecacheSound, - s_update, - s_stop_all_sounds, - s_extra_update, - SND_LocalSound, - s_block_sound, - s_unblock_sound, - SND_LoadSound, - SND_AllocChannel, - SND_ChannelStop, + .ambient_off = SND_AmbientOff, + .ambient_on = SND_AmbientOn, + .static_sound = SND_StaticSound, + .start_sound = SND_StartSound, + .stop_sound = SND_StopSound, + .precache_sound = SND_PrecacheSound, + .update = s_update, + .stop_all_sounds = s_stop_all_sounds, + .extra_update = s_extra_update, + .local_sound = SND_LocalSound, + .block_sound = s_block_sound, + .unblock_sound = s_unblock_sound, + .load_sound = SND_LoadSound, + .alloc_channel = SND_AllocChannel, + .channel_stop = SND_ChannelStop, }; static plugin_funcs_t plugin_info_funcs = { diff --git a/libs/audio/renderer/snd_jack.c b/libs/audio/renderer/snd_jack.c index faec1c1ac..173a6e01b 100644 --- a/libs/audio/renderer/snd_jack.c +++ b/libs/audio/renderer/snd_jack.c @@ -123,11 +123,6 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, SND_SetListener (origin, forward, right, up, ambient_sound_level); } -static void -s_extra_update (void) -{ -} - static void s_local_sound (const char *sound) { @@ -378,21 +373,20 @@ static general_funcs_t plugin_info_general_funcs = { }; static snd_render_funcs_t plugin_info_render_funcs = { - s_ambient_off, - s_ambient_on, - s_static_sound, - s_start_sound, - s_stop_sound, - s_precache_sound, - s_update, - s_stop_all_sounds, - s_extra_update, - s_local_sound, - s_block_sound, - s_unblock_sound, - s_load_sound, - s_alloc_channel, - s_channel_stop, + .ambient_off = s_ambient_off, + .ambient_on = s_ambient_on, + .static_sound = s_static_sound, + .start_sound = s_start_sound, + .stop_sound = s_stop_sound, + .precache_sound = s_precache_sound, + .update = s_update, + .stop_all_sounds = s_stop_all_sounds, + .local_sound = s_local_sound, + .block_sound = s_block_sound, + .unblock_sound = s_unblock_sound, + .load_sound = s_load_sound, + .alloc_channel = s_alloc_channel, + .channel_stop = s_channel_stop, }; static general_data_t plugin_info_general_data; diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 552dfad0e..2561c97cd 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -125,21 +125,21 @@ VISIBLE void S_AmbientOff (void) { if (snd_render_funcs) - snd_render_funcs->pS_AmbientOff (); + snd_render_funcs->ambient_off (); } VISIBLE void S_AmbientOn (void) { if (snd_render_funcs) - snd_render_funcs->pS_AmbientOn (); + snd_render_funcs->ambient_on (); } VISIBLE void S_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, float attenuation) { if (snd_render_funcs) - snd_render_funcs->pS_StaticSound (sfx, origin, vol, attenuation); + snd_render_funcs->static_sound (sfx, origin, vol, attenuation); } VISIBLE void @@ -147,7 +147,7 @@ S_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, float fvol, float attenuation) { if (snd_render_funcs) - snd_render_funcs->pS_StartSound (entnum, entchannel, sfx, origin, fvol, + snd_render_funcs->start_sound (entnum, entchannel, sfx, origin, fvol, attenuation); } @@ -155,14 +155,14 @@ VISIBLE void S_StopSound (int entnum, int entchannel) { if (snd_render_funcs) - snd_render_funcs->pS_StopSound (entnum, entchannel); + snd_render_funcs->stop_sound (entnum, entchannel); } VISIBLE sfx_t * S_PrecacheSound (const char *sample) { if (snd_render_funcs) - return snd_render_funcs->pS_PrecacheSound (sample); + return snd_render_funcs->precache_sound (sample); return NULL; } @@ -171,7 +171,7 @@ S_Update (const vec3_t origin, const vec3_t v_forward, const vec3_t v_right, const vec3_t v_up, const byte *ambient_sound_level) { if (snd_render_funcs) - snd_render_funcs->pS_Update (origin, v_forward, v_right, v_up, + snd_render_funcs->update (origin, v_forward, v_right, v_up, ambient_sound_level); } @@ -179,42 +179,42 @@ VISIBLE void S_StopAllSounds (void) { if (snd_render_funcs) - snd_render_funcs->pS_StopAllSounds (); + snd_render_funcs->stop_all_sounds (); } VISIBLE void S_ExtraUpdate (void) { -// if (snd_render_funcs) -// snd_render_funcs->pS_ExtraUpdate (); + if (snd_render_funcs && snd_render_funcs->extra_update) + snd_render_funcs->extra_update (); } VISIBLE void S_LocalSound (const char *s) { if (snd_render_funcs) - snd_render_funcs->pS_LocalSound (s); + snd_render_funcs->local_sound (s); } VISIBLE void S_BlockSound (void) { if (snd_render_funcs) - snd_render_funcs->pS_BlockSound (); + snd_render_funcs->block_sound (); } VISIBLE void S_UnblockSound (void) { if (snd_render_funcs) - snd_render_funcs->pS_UnblockSound (); + snd_render_funcs->unblock_sound (); } VISIBLE sfx_t * S_LoadSound (const char *name) { if (snd_render_funcs) - return snd_render_funcs->pS_LoadSound (name); + return snd_render_funcs->load_sound (name); return 0; } @@ -222,7 +222,7 @@ VISIBLE struct channel_s * S_AllocChannel (void) { if (snd_render_funcs) - return snd_render_funcs->pS_AllocChannel (); + return snd_render_funcs->alloc_channel (); return 0; } @@ -230,5 +230,5 @@ VISIBLE void S_ChannelStop (struct channel_s *chan) { if (snd_render_funcs) - snd_render_funcs->pS_ChannelStop (chan); + snd_render_funcs->channel_stop (chan); } From c9319966ce49828021696bb0eee89edee7e82553 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 22 Jun 2021 19:47:20 +0900 Subject: [PATCH 1591/3664] [plugin] Clean up the rest of the plugin structs --- include/QF/plugin.h | 6 ++-- include/QF/plugin/cd.h | 31 ++++++++------------- include/QF/plugin/console.h | 51 +++++++++++++++------------------- include/QF/plugin/general.h | 19 ++++--------- include/QF/plugin/input.h | 19 ++----------- include/QF/plugin/snd_output.h | 6 ++-- include/QF/plugin/snd_render.h | 6 ++-- include/QF/plugin/vid_render.h | 6 ++-- libs/audio/cd.c | 14 +++++----- libs/audio/snd.c | 4 +-- libs/audio/targets/snd_alsa.c | 4 +-- libs/audio/targets/snd_oss.c | 4 +-- libs/console/console.c | 20 ++++++------- libs/util/plugin.c | 10 +++---- libs/video/renderer/r_init.c | 6 ++-- 15 files changed, 85 insertions(+), 121 deletions(-) diff --git a/include/QF/plugin.h b/include/QF/plugin.h index f1ff974a3..96de3124e 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -88,11 +88,11 @@ typedef struct plugin_s { /* General plugin info return function type */ -typedef plugin_t * (*P_PluginInfo) (void); +typedef plugin_t *(*plugin_info_t) (void); typedef struct plugin_list_s { - const char *name; - P_PluginInfo info; + const char *name; + plugin_info_t info; } plugin_list_t; /* diff --git a/include/QF/plugin/cd.h b/include/QF/plugin/cd.h index ad7495159..337fc6220 100644 --- a/include/QF/plugin/cd.h +++ b/include/QF/plugin/cd.h @@ -24,33 +24,24 @@ Boston, MA 02111-1307, USA */ -#ifndef __QF_plugin_cd_h_ -#define __QF_plugin_cd_h_ +#ifndef __QF_plugin_cd_h +#define __QF_plugin_cd_h #include #include -/* - All CDAudio plugins must export these functions -*/ -typedef void (*P_CDAudio_CD_f) (void); // -typedef void (*P_CDAudio_Pause) (void); -typedef void (*P_CDAudio_Play) (int, qboolean); -typedef void (*P_CDAudio_Resume) (void); -typedef void (*P_CDAudio_Shutdown) (void); -typedef void (*P_CDAudio_Update) (void); -typedef void (*P_CDAudio_Init) (void); - typedef struct cd_funcs_s { - P_CDAudio_CD_f pCD_f; // - P_CDAudio_Pause pCDAudio_Pause; - P_CDAudio_Play pCDAudio_Play; - P_CDAudio_Resume pCDAudio_Resume; - P_CDAudio_Update pCDAudio_Update; + void (*cd_f) (void); // + void (*pause) (void); + void (*play) (int, qboolean); + void (*resume) (void); + void (*shutdown) (void); + void (*update) (void); + void (*init) (void); } cd_funcs_t; typedef struct cd_data_s { - int unused; /* C requires that a struct or union has at least one member */ + int unused; } cd_data_t; -#endif // __QF_plugin_cd_h_ +#endif // __QF_plugin_cd_h diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index d7beec399..a1a61b8fa 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -25,8 +25,8 @@ */ -#ifndef __QF_plugin_console_h_ -#define __QF_plugin_console_h_ +#ifndef __QF_plugin_console_h +#define __QF_plugin_console_h #include @@ -34,36 +34,29 @@ #include #include -typedef void (*P_C_Print) (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); -typedef void (*P_C_ProcessInput) (void); -typedef void (*P_C_KeyEvent) (knum_t key, short unicode, qboolean down); -typedef void (*P_C_DrawConsole) (void); -typedef void (*P_C_CheckResize) (void); -typedef void (*P_C_NewMap) (void); - typedef struct console_funcs_s { - P_C_Print pC_Print; - P_C_ProcessInput pC_ProcessInput; - P_C_KeyEvent pC_KeyEvent; - P_C_DrawConsole pC_DrawConsole; - P_C_CheckResize pC_CheckResize; - P_C_NewMap pC_NewMap; + void (*print) (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); + void (*process_input) (void); + void (*key_event) (knum_t key, short unicode, qboolean down); + void (*draw_console) (void); + void (*check_resize) (void); + void (*new_map) (void); } console_funcs_t; typedef struct console_data_s { - struct dstring_s *dl_name; - int *dl_percent; - double *realtime; - double *frametime; - int force_commandline; - int ormask; - void (*quit)(void); - struct cbuf_s *cbuf; - struct view_s *view; - struct view_s *status_view; - float lines; - int (*exec_line)(void *data, const char *line); - void *exec_data; + struct dstring_s *dl_name; + int *dl_percent; + double *realtime; + double *frametime; + int force_commandline; + int ormask; + void (*quit) (void); + struct cbuf_s *cbuf; + struct view_s *view; + struct view_s *status_view; + float lines; + int (*exec_line)(void *data, const char *line); + void *exec_data; } console_data_t; -#endif // __QF_plugin_console_h_ +#endif // __QF_plugin_console_h diff --git a/include/QF/plugin/general.h b/include/QF/plugin/general.h index 16141e410..7718e375e 100644 --- a/include/QF/plugin/general.h +++ b/include/QF/plugin/general.h @@ -25,28 +25,21 @@ */ -#ifndef __QF_plugin_general_h_ -#define __QF_plugin_general_h_ +#ifndef __QF_plugin_general_h +#define __QF_plugin_general_h #include #include -/* - All plugins, of all types, must export these functions -*/ - -typedef void (*P_Init) (void); -typedef void (*P_Shutdown) (void); - typedef struct general_funcs_s { - P_Init p_Init; - P_Shutdown p_Shutdown; + void (*init) (void); + void (*shutdown) (void); } general_funcs_t; #define PIF_GLOBAL 1 typedef struct general_data_s { - int flag; + int flag; } general_data_t; -#endif // __QF_plugin_general_h_ +#endif // __QF_plugin_general_h diff --git a/include/QF/plugin/input.h b/include/QF/plugin/input.h index 1077c1d99..297a2953b 100644 --- a/include/QF/plugin/input.h +++ b/include/QF/plugin/input.h @@ -25,29 +25,16 @@ */ -#ifndef __QF_plugin_input_h_ -#define __QF_plugin_input_h_ +#ifndef __QF_plugin_input_h +#define __QF_plugin_input_h #include #include -/* - All input plugins must export these functions -*/ -typedef void (*P_IN_Commands) (void); -typedef void (*P_IN_SendKeyEvents) (void); -typedef void (*P_IN_Move) (void); -typedef void (*P_IN_ModeChanged) (void); - typedef struct input_funcs_s { - P_IN_Commands pIN_Commands; - P_IN_SendKeyEvents pIN_SendKeyEvents; - P_IN_Move pIN_Move; - P_IN_ModeChanged pIN_ModeChanged; } input_funcs_t; typedef struct input_data_s { - int unused; /* C requires that a struct or union has at least one member */ } input_data_t; -#endif // __QF_plugin_input_h_ +#endif // __QF_plugin_input_h diff --git a/include/QF/plugin/snd_output.h b/include/QF/plugin/snd_output.h index 5b6cd02d5..1ac445292 100644 --- a/include/QF/plugin/snd_output.h +++ b/include/QF/plugin/snd_output.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __QF_plugin_snd_output_h_ -#define __QF_plugin_snd_output_h_ +#ifndef __QF_plugin_snd_output_h +#define __QF_plugin_snd_output_h #include #include @@ -54,4 +54,4 @@ typedef struct snd_output_data_s { unsigned *paintedtime; } snd_output_data_t; -#endif // __QF_plugin_snd_output_h_ +#endif // __QF_plugin_snd_output_h diff --git a/include/QF/plugin/snd_render.h b/include/QF/plugin/snd_render.h index 078b6f01d..4cf1ea021 100644 --- a/include/QF/plugin/snd_render.h +++ b/include/QF/plugin/snd_render.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __QF_plugin_snd_render_h_ -#define __QF_plugin_snd_render_h_ +#ifndef __QF_plugin_snd_render_h +#define __QF_plugin_snd_render_h #include #include @@ -64,4 +64,4 @@ typedef struct snd_render_data_s { struct plugin_s *output; } snd_render_data_t; -#endif // __QF_plugin_snd_render_h_ +#endif // __QF_plugin_snd_render_h diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 18788e641..7256b54d7 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -24,8 +24,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __QF_plugin_vid_render_h_ -#define __QF_plugin_vid_render_h_ +#ifndef __QF_plugin_vid_render_h +#define __QF_plugin_vid_render_h #include #include @@ -199,4 +199,4 @@ typedef struct vid_render_data_s { vec_t *vup; } vid_render_data_t; -#endif // __QF_plugin_vid_render_h_ +#endif // __QF_plugin_vid_render_h diff --git a/libs/audio/cd.c b/libs/audio/cd.c index c6a9e8893..ebc1777d3 100644 --- a/libs/audio/cd.c +++ b/libs/audio/cd.c @@ -52,42 +52,42 @@ VISIBLE void CDAudio_Pause (void) { if (cdmodule) - cdmodule->functions->cd->pCDAudio_Pause (); + cdmodule->functions->cd->pause (); } VISIBLE void CDAudio_Play (int track, qboolean looping) { if (cdmodule) - cdmodule->functions->cd->pCDAudio_Play (track, looping); + cdmodule->functions->cd->play (track, looping); } VISIBLE void CDAudio_Resume (void) { if (cdmodule) - cdmodule->functions->cd->pCDAudio_Resume (); + cdmodule->functions->cd->resume (); } static void CDAudio_shutdown (void *data) { if (cdmodule) - cdmodule->functions->general->p_Shutdown (); + cdmodule->functions->general->shutdown (); } VISIBLE void CDAudio_Update (void) { if (cdmodule) - cdmodule->functions->cd->pCDAudio_Update (); + cdmodule->functions->cd->update (); } static void CD_f (void) { if (cdmodule) - cdmodule->functions->cd->pCD_f (); + cdmodule->functions->cd->cd_f (); } VISIBLE int @@ -111,7 +111,7 @@ CDAudio_Init (void) Sys_Printf ("Loading of cd module: %s failed!\n", cd_plugin->string); return -1; } - cdmodule->functions->general->p_Init (); + cdmodule->functions->general->init (); Cmd_AddCommand ( "cd", CD_f, "Control the CD player.\n" "Commands:\n" diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 2561c97cd..1c6e3a6f5 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -99,8 +99,8 @@ S_Init (int *viewentity, double *host_frametime) host_frametime; snd_render_module->data->snd_render->output = snd_output_module; - snd_output_module->functions->general->p_Init (); - snd_render_module->functions->general->p_Init (); + snd_output_module->functions->general->init (); + snd_render_module->functions->general->init (); snd_output_module->data->snd_output->soundtime = snd_render_module->data->snd_render->soundtime; diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 399baae9b..89dbc713b 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -552,8 +552,8 @@ PLUGIN_INFO(snd_output, alsa) plugin_info_funcs.input = NULL; plugin_info_funcs.snd_output = &plugin_info_snd_output_funcs; - plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; - plugin_info_general_funcs.p_Shutdown = NULL; + plugin_info_general_funcs.init = SNDDMA_Init_Cvars; + plugin_info_general_funcs.shutdown = NULL; plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; diff --git a/libs/audio/targets/snd_oss.c b/libs/audio/targets/snd_oss.c index dc2902b1b..c7e53b534 100644 --- a/libs/audio/targets/snd_oss.c +++ b/libs/audio/targets/snd_oss.c @@ -410,8 +410,8 @@ PLUGIN_INFO(snd_output, oss) plugin_info_funcs.input = NULL; plugin_info_funcs.snd_output = &plugin_info_snd_output_funcs; - plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; - plugin_info_general_funcs.p_Shutdown = NULL; + plugin_info_general_funcs.init = SNDDMA_Init_Cvars; + plugin_info_general_funcs.shutdown = NULL; plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; diff --git a/libs/console/console.c b/libs/console/console.c index cbf98a463..0484bae1b 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -90,7 +90,7 @@ static void Con_shutdown (void *data) { if (con_module) { - con_module->functions->general->p_Shutdown (); + con_module->functions->general->shutdown (); PI_UnloadPlugin (con_module); } } @@ -102,8 +102,8 @@ Con_Init (const char *plugin_name) con_module = PI_LoadPlugin ("console", plugin_name); if (con_module) { - con_module->functions->general->p_Init (); - Sys_SetStdPrintf (con_module->functions->console->pC_Print); + con_module->functions->general->init (); + Sys_SetStdPrintf (con_module->functions->console->print); } else { setvbuf (stdout, 0, _IOLBF, BUFSIZ); } @@ -143,7 +143,7 @@ Con_Printf (const char *fmt, ...) va_start (args, fmt); if (con_module) - con_module->functions->console->pC_Print (fmt, args); + con_module->functions->console->print (fmt, args); else vfprintf (stdout, fmt, args); va_end (args); @@ -153,7 +153,7 @@ VISIBLE void Con_Print (const char *fmt, va_list args) { if (con_module) - con_module->functions->console->pC_Print (fmt, args); + con_module->functions->console->print (fmt, args); else vfprintf (stdout, fmt, args); } @@ -162,7 +162,7 @@ VISIBLE void Con_ProcessInput (void) { if (con_module) { - con_module->functions->console->pC_ProcessInput (); + con_module->functions->console->process_input (); } else { static int been_there_done_that = 0; @@ -177,7 +177,7 @@ VISIBLE void Con_KeyEvent (knum_t key, short unicode, qboolean down) { if (con_module) - con_module->functions->console->pC_KeyEvent (key, unicode, down); + con_module->functions->console->key_event (key, unicode, down); } VISIBLE void @@ -191,19 +191,19 @@ VISIBLE void Con_DrawConsole (void) { if (con_module) - con_module->functions->console->pC_DrawConsole (); + con_module->functions->console->draw_console (); } VISIBLE void Con_CheckResize (void) { if (con_module) - con_module->functions->console->pC_CheckResize (); + con_module->functions->console->check_resize (); } VISIBLE void Con_NewMap (void) { if (con_module) - con_module->functions->console->pC_NewMap (); + con_module->functions->console->new_map (); } diff --git a/libs/util/plugin.c b/libs/util/plugin.c index 629b22e28..6ce0d9049 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -201,8 +201,8 @@ PI_Plugin_Load_f (void) Sys_Printf ("Error loading plugin %s %s\n", type, name); else if (pi->functions && pi->functions->general && - pi->functions->general->p_Init) - pi->functions->general->p_Init (); + pi->functions->general->init) + pi->functions->general->init (); } static void @@ -274,7 +274,7 @@ PI_LoadPlugin (const char *type, const char *name) const char *tmpname; void *dlhand = 0; plugin_t *plugin = 0; - P_PluginInfo plugin_info = 0; + plugin_info_t plugin_info = 0; plugin_list_t *pl; loaded_plugin_t *lp; @@ -388,8 +388,8 @@ PI_UnloadPlugin (plugin_t *plugin) if (plugin && plugin->functions && plugin->functions->general - && plugin->functions->general->p_Shutdown) { - plugin->functions->general->p_Shutdown (); + && plugin->functions->general->shutdown) { + plugin->functions->general->shutdown (); } else { Sys_MaskPrintf (SYS_dev, "Warning: No shutdown function for type %d plugin!\n", diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 733004a21..25a36e6df 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -68,8 +68,8 @@ static U void (*const r_scrapdelete)(rscrap_t *) = R_ScrapDelete; static void R_shutdown (void *data) { - if (vidrendmodule->functions->general->p_Shutdown) { - vidrendmodule->functions->general->p_Shutdown (); + if (vidrendmodule->functions->general->shutdown) { + vidrendmodule->functions->general->shutdown (); } } @@ -89,7 +89,7 @@ R_LoadModule (vid_internal_t *vid_internal) r_data = vidrendmodule->data->vid_render; r_data->vid->vid_internal = vid_internal; - vidrendmodule->functions->general->p_Init (); + vidrendmodule->functions->general->init (); Sys_RegisterShutdown (R_shutdown, 0); } From b799d48ccb3de839580fcf0805eccd04f471ced5 Mon Sep 17 00:00:00 2001 From: D G Turner Date: Wed, 23 Jun 2021 01:10:42 +0100 Subject: [PATCH 1592/3664] [simd] fix build when avx2 is not available, but avx is. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This failed with errors such as: from ./include/QF/simd/vec4d.h:32, from libs/util/simd.c:37: ./include/QF/simd/vec4d.h: In function ‘qmuld’: /usr/lib/gcc/x86_64-pc-linux-gnu/10.3.0/include/avx2intrin.h:1049:1: error: inlining failed in call to ‘always_inline’ ‘_mm256_permute4x64_pd’: target specific option mismatch 1049 | _mm256_permute4x64_pd (__m256d __X, const int __M) --- include/QF/simd/types.h | 2 +- include/QF/simd/vec4d.h | 2 +- libs/util/test/test-simd.c | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index bfe484ace..5764fe085 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -39,7 +39,7 @@ */ typedef double vec3d_t[3]; -#ifdef __AVX__ +#ifdef __AVX2__ /** Four element vector type for horizontal (AOS) vector data. * * This is used for both vectors (3D and 4D) and quaternions. 3D vectors diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index f1c6d6a49..058635dd7 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -28,7 +28,7 @@ #ifndef __QF_simd_vec4d_h #define __QF_simd_vec4d_h -#ifdef __AVX__ +#ifdef __AVX2__ #include #include "QF/simd/types.h" diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index 4cd5b5076..ae2fd6547 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -48,7 +48,7 @@ #define s05 0.70710678118654757 -#ifdef __AVX__ +#ifdef __AVX2__ typedef struct { int line; vec4d_t (*op) (vec4d_t a, vec4d_t b); @@ -94,7 +94,7 @@ typedef struct { mat4f_t ulp_errors; } mq4f_test_t; -#ifdef __AVX__ +#ifdef __AVX2__ static vec4d_t tvtruncd (vec4d_t v, vec4d_t ignore) { return vtruncd (v); @@ -158,7 +158,7 @@ static vec4f_t tmagnitude3f (vec4f_t v, vec4f_t ignore) #define T(t...) { __LINE__, t } -#ifdef __AVX__ +#ifdef __AVX2__ static vec4d_test_t vec4d_tests[] = { // 3D dot products T(dotd, right, right, one ), @@ -487,7 +487,7 @@ static mq4f_test_t mq4f_tests[] = { }; #define num_mq4f_tests (sizeof (mq4f_tests) / (sizeof (mq4f_tests[0]))) -#ifdef __AVX__ +#ifdef __AVX2__ static int run_vec4d_tests (void) { @@ -684,7 +684,7 @@ int main (void) { int ret = 0; -#ifdef __AVX__ +#ifdef __AVX2__ ret |= run_vec4d_tests (); #endif ret |= run_vec4f_tests (); From fc907e232f0febeeb6bacb4f61a1dbe85d455243 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jun 2021 00:04:02 +0900 Subject: [PATCH 1593/3664] [audio] Rework alsa to use a pull model This brings the alsa driver in line with the jack render (progress towards #16), but breaks most of the other drivers (for now: one step at a time). The idea is that once the pull model is working for at least one other target, the jack renderer can become just another target like it should have been in the first place (but I needed to get the pull model working first, then forgot about it). Correct state checking is not done yet, but testsound does produce what seems to be fairly good sound when it starts up correctly (part of the state checking (or lack thereof), I imagine). --- include/QF/plugin/snd_output.h | 22 +-- include/QF/sound.h | 1 + include/alsa_funcs_list.h | 5 + include/snd_internal.h | 53 ++++--- libs/audio/renderer/snd_channels.c | 147 ++++++++++--------- libs/audio/renderer/snd_dma.c | 222 ++++++++++++++++++++--------- libs/audio/renderer/snd_jack.c | 45 +++--- libs/audio/renderer/snd_mem.c | 8 +- libs/audio/renderer/snd_mix.c | 6 +- libs/audio/renderer/snd_resample.c | 10 +- libs/audio/renderer/snd_sfx.c | 15 +- libs/audio/targets/snd_alsa.c | 181 ++++++++++++++++------- libs/audio/targets/snd_oss.c | 122 ++++++++-------- 13 files changed, 506 insertions(+), 331 deletions(-) diff --git a/include/QF/plugin/snd_output.h b/include/QF/plugin/snd_output.h index 1ac445292..3b8c36bf6 100644 --- a/include/QF/plugin/snd_output.h +++ b/include/QF/plugin/snd_output.h @@ -30,23 +30,15 @@ #include #include -/* - All sound plugins must export these functions -*/ -typedef volatile struct dma_s *(*P_S_O_Init) (void); -typedef void (*P_S_O_Shutdown) (void); -typedef int (*P_S_O_GetDMAPos) (void); -typedef void (*P_S_O_Submit) (void); -typedef void (*P_S_O_BlockSound) (void); -typedef void (*P_S_O_UnblockSound) (void); +struct snd_s; typedef struct snd_output_funcs_s { - P_S_O_Init pS_O_Init; - P_S_O_Shutdown pS_O_Shutdown; - P_S_O_GetDMAPos pS_O_GetDMAPos; - P_S_O_Submit pS_O_Submit; - P_S_O_BlockSound pS_O_BlockSound; - P_S_O_UnblockSound pS_O_UnblockSound; + int (*init) (struct snd_s *snd); + void (*shutdown) (struct snd_s *snd); + int (*get_dma_pos) (struct snd_s *snd); + void (*submit) (struct snd_s *snd); + void (*block_sound) (struct snd_s *snd); + void (*unblock_sound) (struct snd_s *snd); } snd_output_funcs_t; typedef struct snd_output_data_s { diff --git a/include/QF/sound.h b/include/QF/sound.h index 9fba9b158..1362d187c 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -41,6 +41,7 @@ typedef struct sfx_s sfx_t; struct sfx_s { + struct snd_s *snd; //!< ownding snd_t instance const char *name; sfx_t *owner; diff --git a/include/alsa_funcs_list.h b/include/alsa_funcs_list.h index fadedad4b..6b9b15111 100644 --- a/include/alsa_funcs_list.h +++ b/include/alsa_funcs_list.h @@ -67,6 +67,11 @@ QF_ALSA_NEED (int, snd_pcm_sw_params_set_stop_threshold, (snd_pcm_t *pcm, snd_pc QF_ALSA_NEED (size_t, snd_pcm_sw_params_sizeof, (void)) QF_ALSA_NEED (const char *, snd_strerror, (int errnum)) +QF_ALSA_NEED (int, snd_async_add_pcm_handler, (snd_async_handler_t **handler, snd_pcm_t *pcm, snd_async_callback_t callback, void *private_data)) +QF_ALSA_NEED (snd_pcm_t *, snd_async_handler_get_pcm, (snd_async_handler_t *handler)) +QF_ALSA_NEED (void *, snd_async_handler_get_callback_private, (snd_async_handler_t *handler)) +QF_ALSA_NEED (int, snd_async_del_handler, (snd_async_handler_t *handler)) + #ifdef UNDEF_QF_ALSA_NEED #undef QF_ALSA_NEED #undef UNDEF_QF_ALSA_NEED diff --git a/include/snd_internal.h b/include/snd_internal.h index 7978c4307..aa22b2299 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -45,7 +45,7 @@ #include "QF/zone.h" typedef struct portable_samplepair_s portable_samplepair_t; -typedef struct dma_s dma_t; +typedef struct snd_s snd_t; typedef struct wavinfo_s wavinfo_t; typedef struct channel_s channel_t; typedef struct sfxbuffer_s sfxbuffer_t; @@ -70,7 +70,7 @@ struct portable_samplepair_s { /** communication structure between output drivers and renderer */ -struct dma_s { +struct snd_s { int speed; //!< sample rate int samplebits; //!< bits per sample int channels; //!< number of output channels @@ -84,7 +84,8 @@ struct dma_s { \param count The number of sample to transfer. \param volume The gain for the samples. */ - void (*xfer) (portable_samplepair_t *paintbuffer, int count, + void (*xfer) (struct snd_s *snd, + portable_samplepair_t *paintbuffer, int count, float volume); /** Optional data for the xfer function. */ @@ -229,8 +230,6 @@ extern struct cvar_s *snd_volume; extern struct cvar_s *snd_interp; extern struct cvar_s *snd_stereo_phase_separation; -extern volatile dma_t *snd_shm; - extern snd_render_data_t snd_render_data; #define PAINTBUFFER_SIZE 512 extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; @@ -279,16 +278,16 @@ void SND_SFX_StreamClose (sfx_t *sfx); /** Pre-load a sound into the cache. \param sample name of sound to precache */ -sfx_t *SND_PrecacheSound (const char *sample); +sfx_t *SND_PrecacheSound (snd_t *snd, const char *sample); /** Pre-load a sound. \param name name of sound to load */ -sfx_t *SND_LoadSound (const char *name); +sfx_t *SND_LoadSound (snd_t *snd, const char *name); /** Initialize the sfx sub-subsystem */ -void SND_SFX_Init (void); +void SND_SFX_Init (snd_t *snd); ///@} @@ -312,29 +311,29 @@ extern int snd_total_channels; //!< number of active channels /** Allocate a sound channel that can be used for playing sounds. */ -struct channel_s *SND_AllocChannel (void); +struct channel_s *SND_AllocChannel (snd_t *snd); /** Stop a channel from playing. \param chan the channel to stop */ -void SND_ChannelStop (channel_t *chan); +void SND_ChannelStop (snd_t *snd, channel_t *chan); /** Scan channels looking for stopped channels. \param wait if true, wait for the channels to be done. if false, force the channels to be done. true is for threaded, false for non-threaded. */ -void SND_ScanChannels (int wait); +void SND_ScanChannels (snd_t *snd, int wait); /** Disable ambient sounds. \todo not used, remove? */ -void SND_AmbientOff (void); +void SND_AmbientOff (snd_t *snd); /** Enable ambient sounds. \todo not used, remove? */ -void SND_AmbientOn (void); +void SND_AmbientOn (snd_t *snd); /** Update the sound engine with the client's position and orientation and render some sound. @@ -345,17 +344,17 @@ void SND_AmbientOn (void); \param ambient_sound_level Pointer to 4 bytes indicating the levels at which to play the ambient sounds. */ -void SND_SetListener (const vec3_t origin, const vec3_t v_forward, +void SND_SetListener (snd_t *snd, const vec3_t origin, const vec3_t v_forward, const vec3_t v_right, const vec3_t v_up, const byte *ambient_sound_level); /** Stop all sounds from playing. */ -void SND_StopAllSounds(void); +void SND_StopAllSounds (snd_t *snd); /** Initialize the channels sub-subsystem */ -void SND_Channels_Init (void); +void SND_Channels_Init (snd_t *snd); /** Start a sound playing. \param entnum index of entity the sound is associated with. @@ -370,8 +369,8 @@ void SND_Channels_Init (void); \param fvol absolute volume of the sound \param attenuation rate of volume dropoff vs distance */ -void SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, - float fvol, float attenuation); +void SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, + const vec3_t origin, float fvol, float attenuation); /** Create a sound generated by the world. \param sfx sound to play @@ -379,18 +378,18 @@ void SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin \param vol absolute volume of the sound \param attenuation rate of volume dropoff vs distance */ -void SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, - float attenuation); +void SND_StaticSound (snd_t *snd, sfx_t *sfx, const vec3_t origin, float vol, + float attenuation); /** Stop an entity's sound. \param entnum index of entity the sound is associated with. \param entchannel channel to silence */ -void SND_StopSound (int entnum, int entchannel); +void SND_StopSound (snd_t *snd, int entnum, int entchannel); /** Start a sound local to the client view. \param s name of sound to play */ -void SND_LocalSound (const char *s); +void SND_LocalSound (snd_t *snd, const char *s); ///@} @@ -405,11 +404,11 @@ extern unsigned snd_paintedtime; /** Mix all active channels into the output buffer. \param endtime sample time until when to mix */ -void SND_PaintChannels(unsigned int endtime); +void SND_PaintChannels(snd_t *snd, unsigned int endtime); /** Initialize the scale table for painting of 8 bit samples. */ -void SND_InitScaletable (void); +void SND_InitScaletable (snd_t *snd); /** Set the paint function of the sfxbuffer \param sc sfxbuffer to set. @@ -447,8 +446,8 @@ void SND_Resample (sfxbuffer_t *sc, float *data, int length); \param channels number of channels per frame \param width bytes per channel */ -void SND_Convert (byte *idata, float *fdata, int frames, int channels, - int width); +void SND_Convert (byte *idata, float *fdata, int frames, + int channels, int width); ///@} @@ -492,7 +491,7 @@ int SND_LoadWav (QFile *file, sfx_t *sfx, char *realname); \param realname path of sound file should it need to be re-opened \return 0 if ok, -1 on error */ -int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname); +int SND_LoadMidi (snd_t *snd, QFile *file, sfx_t *sfx, char *realname); ///@} /** \defgroup sound_render_cache_stream Cache/Stream Functions. diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index c736c7553..7c0d27efc 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -85,7 +85,7 @@ unlink_channel (channel_t **_ch) } channel_t * -SND_AllocChannel (void) +SND_AllocChannel (snd_t *snd) { channel_t **free = &free_channels; channel_t *chan; @@ -124,7 +124,7 @@ SND_AllocChannel (void) } void -SND_ChannelStop (channel_t *chan) +SND_ChannelStop (snd_t *snd, channel_t *chan) { /* if chan->next is set, then this channel may have already been freed. a rather serious bug as it will create a loop in the free list @@ -137,13 +137,13 @@ SND_ChannelStop (channel_t *chan) } void -SND_ScanChannels (int wait) +SND_ScanChannels (snd_t *snd, int wait) { int i; channel_t *ch; int count = 0; - if (!snd_shm || !snd_shm->speed) + if (!snd || !snd->speed) return; if (wait) { @@ -184,23 +184,23 @@ SND_ScanChannels (int wait) } void -SND_StopAllSounds (void) +SND_StopAllSounds (snd_t *snd) { int i; snd_num_statics = 0; while (dynamic_channels) - SND_ChannelStop (unlink_channel (&dynamic_channels)); + SND_ChannelStop (snd, unlink_channel (&dynamic_channels)); while (looped_dynamic_channels) - SND_ChannelStop (unlink_channel (&looped_dynamic_channels)); + SND_ChannelStop (snd, unlink_channel (&looped_dynamic_channels)); for (i = 0; i < NUM_AMBIENTS; i++) { if (ambient_channels[i]) - SND_ChannelStop (ambient_channels[i]); + SND_ChannelStop (snd, ambient_channels[i]); ambient_channels[i] = 0; } for (i = 0; i < MAX_STATIC_CHANNELS; i++) { if (static_channels[i]) - SND_ChannelStop (static_channels[i]); + SND_ChannelStop (snd, static_channels[i]); static_channels[i] = 0; } if (0) { @@ -217,8 +217,9 @@ SND_StopAllSounds (void) } static void -s_play_f (void) +s_play_f (void *_snd) { + snd_t *snd = _snd; dstring_t *name = dstring_new (); int i; static int hash = 345; @@ -231,16 +232,17 @@ s_play_f (void) } else { dsprintf (name, "%s", Cmd_Argv (i)); } - sfx = SND_PrecacheSound (name->str); - SND_StartSound (hash++, 0, sfx, listener_origin, 1.0, 1.0); + sfx = SND_PrecacheSound (snd, name->str); + SND_StartSound (snd, hash++, 0, sfx, listener_origin, 1.0, 1.0); i++; } dstring_delete (name); } static void -s_playcenter_f (void) +s_playcenter_f (void *_snd) { + snd_t *snd = _snd; dstring_t *name = dstring_new (); int i; sfx_t *sfx; @@ -255,15 +257,16 @@ s_playcenter_f (void) } else { dsprintf (name, "%s", Cmd_Argv (i)); } - sfx = SND_PrecacheSound (name->str); - SND_StartSound (viewent, 0, sfx, listener_origin, 1.0, 1.0); + sfx = SND_PrecacheSound (snd, name->str); + SND_StartSound (snd, viewent, 0, sfx, listener_origin, 1.0, 1.0); } dstring_delete (name); } static void -s_playvol_f (void) +s_playvol_f (void *_snd) { + snd_t *snd = _snd; dstring_t *name = dstring_new (); float vol; int i; @@ -277,9 +280,9 @@ s_playvol_f (void) } else { dsprintf (name, "%s", Cmd_Argv (i)); } - sfx = SND_PrecacheSound (name->str); + sfx = SND_PrecacheSound (snd, name->str); vol = atof (Cmd_Argv (i + 1)); - SND_StartSound (hash++, 0, sfx, listener_origin, vol, 1.0); + SND_StartSound (snd, hash++, 0, sfx, listener_origin, vol, 1.0); i += 2; } dstring_delete (name); @@ -291,14 +294,15 @@ s_channels_gamedir (int phase) //FIXME for some reason, a gamedir change causes semi-random //"already released" cache errors. fortunatly, servers don't change //gamedir often, so I'll put this in the too-hard basket for now. - if (phase) { - ambient_sfx[AMBIENT_WATER] = SND_PrecacheSound ("ambience/water1.wav"); - ambient_sfx[AMBIENT_SKY] = SND_PrecacheSound ("ambience/wind2.wav"); - } + //XXX FIXME set ambient sounds + //if (phase) { + // ambient_sfx[AMBIENT_WATER] = SND_PrecacheSound (snd, "ambience/water1.wav"); + // ambient_sfx[AMBIENT_SKY] = SND_PrecacheSound (snd, "ambience/wind2.wav"); + //} } void -SND_Channels_Init (void) +SND_Channels_Init (snd_t *snd) { int i; @@ -315,12 +319,14 @@ SND_Channels_Init (void) ambient_level = Cvar_Get ("ambient_level", "0.3", CVAR_NONE, NULL, "Ambient sounds' volume"); - Cmd_AddCommand ("play", s_play_f, - "Play selected sound effect (play pathto/sound.wav)"); - Cmd_AddCommand ("playcenter", s_playcenter_f, - "Play selected sound effect without 3D spatialization."); - Cmd_AddCommand ("playvol", s_playvol_f, "Play selected sound effect at " - "selected volume (playvol pathto/sound.wav num"); + Cmd_AddDataCommand ("play", s_play_f, snd, + "Play selected sound effect (play pathto/sound.wav)"); + Cmd_AddDataCommand ("playcenter", s_playcenter_f, snd, + "Play selected sound effect without 3D " + "spatialization."); + Cmd_AddDataCommand ("playvol", s_playvol_f, snd, + "Play selected sound effect at selected volume " + "(playvol pathto/sound.wav num"); for (i = 0; i < MAX_CHANNELS - 1; i++) snd_channels[i].next = &snd_channels[i + 1]; @@ -333,14 +339,14 @@ SND_Channels_Init (void) } static channel_t * -s_pick_channel (int entnum, int entchannel, int looped) +s_pick_channel (snd_t *snd, int entnum, int entchannel, int looped) { channel_t *ch, **_ch; // check for finished non-looped sounds for (_ch = &dynamic_channels; *_ch; ) { if (!(*_ch)->sfx || (*_ch)->done) { - SND_ChannelStop (unlink_channel (_ch)); + SND_ChannelStop (snd, unlink_channel (_ch)); continue; } _ch = &(*_ch)->next; @@ -352,13 +358,13 @@ s_pick_channel (int entnum, int entchannel, int looped) if (!(*_ch)->sfx || (*_ch)->done || ((*_ch)->entnum == entnum && ((*_ch)->entchannel == entchannel || entchannel == -1))) { - SND_ChannelStop (unlink_channel (_ch)); + SND_ChannelStop (snd, unlink_channel (_ch)); continue; } _ch = &(*_ch)->next; } _ch = looped ? &looped_dynamic_channels : &dynamic_channels; - if ((ch = SND_AllocChannel ())) { + if ((ch = SND_AllocChannel (snd))) { ch->next = *_ch; *_ch = ch; } @@ -366,19 +372,19 @@ s_pick_channel (int entnum, int entchannel, int looped) } void -SND_AmbientOff (void) +SND_AmbientOff (snd_t *snd) { snd_ambient = false; } void -SND_AmbientOn (void) +SND_AmbientOn (snd_t *snd) { snd_ambient = true; } static void -s_updateAmbientSounds (const byte *ambient_sound_level) +s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) { float vol; int ambient_channel; @@ -410,7 +416,7 @@ s_updateAmbientSounds (const byte *ambient_sound_level) chan = ambient_channels[ambient_channel]; if (!chan) { - chan = ambient_channels[ambient_channel] = SND_AllocChannel (); + chan = ambient_channels[ambient_channel] = SND_AllocChannel (snd); if (!chan) continue; } @@ -450,7 +456,7 @@ s_updateAmbientSounds (const byte *ambient_sound_level) } static void -s_spatialize (channel_t *ch) +s_spatialize (snd_t *snd, channel_t *ch) { int phase; // in samples vec_t dist, dot, lscale, rscale, scale; @@ -477,14 +483,14 @@ s_spatialize (channel_t *ch) if (snd_swapchannelside->int_val) dot = -dot; - if (snd_shm->channels == 1) { + if (snd->channels == 1) { rscale = 1.0; lscale = 1.0; phase = 0; } else { rscale = 1.0 + dot * snd_volumesep->value; lscale = 1.0 - dot * snd_volumesep->value; - phase = snd_phasesep->value * 0.001 * snd_shm->speed * dot; + phase = snd_phasesep->value * 0.001 * snd->speed * dot; } // add in distance effect @@ -502,11 +508,11 @@ s_spatialize (channel_t *ch) } static inline int -s_update_channel (channel_t *ch) +s_update_channel (snd_t *snd, channel_t *ch) { if (!ch->sfx) return 0; - s_spatialize (ch); // respatialize channel + s_spatialize (snd, ch); if (!ch->leftvol && !ch->rightvol) return 0; return 1; @@ -521,8 +527,9 @@ s_combine_channel (channel_t *combine, channel_t *ch) } void -SND_SetListener (const vec3_t origin, const vec3_t forward, const vec3_t right, - const vec3_t up, const byte *ambient_sound_level) +SND_SetListener (snd_t *snd, const vec3_t origin, const vec3_t forward, + const vec3_t right, const vec3_t up, + const byte *ambient_sound_level) { int i, j; channel_t *combine, *ch; @@ -533,19 +540,19 @@ SND_SetListener (const vec3_t origin, const vec3_t forward, const vec3_t right, VectorCopy (up, listener_up); // update general area ambient sound sources - s_updateAmbientSounds (ambient_sound_level); + s_updateAmbientSounds (snd, ambient_sound_level); // update spatialization for dynamic sounds for (ch = dynamic_channels; ch; ch = ch->next) - s_update_channel (ch); + s_update_channel (snd, ch); for (ch = looped_dynamic_channels; ch; ch = ch->next) - s_update_channel (ch); + s_update_channel (snd, ch); // update spatialization for static sounds combine = 0; for (i = 0; i < snd_num_statics; i++) { ch = static_channels[i]; - if (!s_update_channel (ch)) + if (!s_update_channel (snd, ch)) continue; // try to combine static sounds with a previous channel of the same @@ -573,13 +580,13 @@ SND_SetListener (const vec3_t origin, const vec3_t forward, const vec3_t right, } static int -snd_check_channels (channel_t *target_chan, const channel_t *check, +snd_check_channels (snd_t *snd, channel_t *target_chan, const channel_t *check, const sfx_t *osfx) { if (!check || check == target_chan) return 0; if (check->sfx->owner == osfx->owner && !check->pos) { - int skip = rand () % (int) (0.01 * snd_shm->speed); + int skip = rand () % (int) (0.01 * snd->speed); target_chan->pos = -skip; return 1; } @@ -587,19 +594,19 @@ snd_check_channels (channel_t *target_chan, const channel_t *check, } void -SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, - float fvol, float attenuation) +SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, + const vec3_t origin, float fvol, float attenuation) { int vol; int looped; channel_t *target_chan, *check; sfx_t *osfx; - if (!sfx || !snd_shm->speed) + if (!sfx || !snd->speed) return; // pick a channel to play on looped = sfx->loopstart != (unsigned) -1; - target_chan = s_pick_channel (entnum, entchannel, looped); + target_chan = s_pick_channel (snd, entnum, entchannel, looped); if (!target_chan) return; @@ -611,11 +618,11 @@ SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, target_chan->master_vol = vol; target_chan->entnum = entnum; target_chan->entchannel = entchannel; - s_spatialize (target_chan); + s_spatialize (snd, target_chan); // new channel if (!(osfx = sfx->open (sfx))) { - SND_ChannelStop (unlink_channel (looped ? &looped_dynamic_channels + SND_ChannelStop (snd, unlink_channel (looped ? &looped_dynamic_channels : &dynamic_channels)); return; } @@ -625,13 +632,13 @@ SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, // if an identical sound has also been started this frame, offset the pos // a bit to keep it from just making the first one louder for (check = dynamic_channels; check; check = check->next) - if (snd_check_channels (target_chan, check, osfx)) + if (snd_check_channels (snd, target_chan, check, osfx)) break; for (check = looped_dynamic_channels; check; check = check->next) - if (snd_check_channels (target_chan, check, osfx)) + if (snd_check_channels (snd, target_chan, check, osfx)) break; if (!osfx->retain (osfx)) { - SND_ChannelStop (unlink_channel (looped ? &looped_dynamic_channels + SND_ChannelStop (snd, unlink_channel (looped ? &looped_dynamic_channels : &dynamic_channels)); return; // couldn't load the sound's data } @@ -639,30 +646,30 @@ SND_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, } static int -s_check_stop (channel_t **_ch, int entnum, int entchannel) +s_check_stop (snd_t *snd, channel_t **_ch, int entnum, int entchannel) { if ((*_ch)->entnum == entnum && (*_ch)->entchannel == entchannel) { - SND_ChannelStop (unlink_channel (_ch)); + SND_ChannelStop (snd, unlink_channel (_ch)); return 1; } return 0; } void -SND_StopSound (int entnum, int entchannel) +SND_StopSound (snd_t *snd, int entnum, int entchannel) { channel_t **_ch; for (_ch = &dynamic_channels; *_ch; ) - if (!s_check_stop (_ch, entnum, entchannel)) + if (!s_check_stop (snd, _ch, entnum, entchannel)) _ch = &(*_ch)->next; for (_ch = &looped_dynamic_channels; *_ch; ) - if (!s_check_stop (_ch, entnum, entchannel)) + if (!s_check_stop (snd, _ch, entnum, entchannel)) _ch = &(*_ch)->next; } void -SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, +SND_StaticSound (snd_t *snd, sfx_t *sfx, const vec3_t origin, float vol, float attenuation) { channel_t *ss; @@ -676,7 +683,7 @@ SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, } if (!static_channels[snd_num_statics]) { - if (!(static_channels[snd_num_statics] = SND_AllocChannel ())) { + if (!(static_channels[snd_num_statics] = SND_AllocChannel (snd))) { Sys_Printf ("ran out of channels\n"); return; } @@ -692,7 +699,7 @@ SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, ss->dist_mult = (attenuation / 64) / sound_nominal_clip_dist; ss->end = 0; - s_spatialize (ss); + s_spatialize (snd, ss); ss->oldphase = ss->phase; if (!osfx->retain (osfx)) @@ -702,17 +709,17 @@ SND_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, } void -SND_LocalSound (const char *sound) +SND_LocalSound (snd_t *snd, const char *sound) { sfx_t *sfx; int viewent = 0; - sfx = SND_PrecacheSound (sound); + sfx = SND_PrecacheSound (snd, sound); if (!sfx) { Sys_Printf ("S_LocalSound: can't cache %s\n", sound); return; } if (snd_render_data.viewentity) viewent = *snd_render_data.viewentity; - SND_StartSound (viewent, -1, sfx, vec3_origin, 1, 1); + SND_StartSound (snd, viewent, -1, sfx, vec3_origin, 1, 1); } diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 6c06b156c..6d9c731e5 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -1,5 +1,5 @@ /* - snd_dma.c + snd_default.c main control for any streaming sound output device @@ -69,23 +69,26 @@ static general_data_t plugin_info_general_data; static snd_output_funcs_t *snd_output_funcs; +static snd_t snd; +static int snd_shutdown = 0; + static void -s_xfer_paint_buffer (portable_samplepair_t *paintbuffer, int count, +s_xfer_paint_buffer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, float volume) { int out_idx, out_max, step, val; float *p; p = (float *) paintbuffer; - count *= snd_shm->channels; - out_max = (snd_shm->frames * snd_shm->channels) - 1; - out_idx = snd_paintedtime * snd_shm->channels; + count *= snd->channels; + out_max = (snd->frames * snd->channels) - 1; + out_idx = snd_paintedtime * snd->channels; while (out_idx > out_max) out_idx -= out_max + 1; - step = 3 - snd_shm->channels; + step = 3 - snd->channels; - if (snd_shm->samplebits == 16) { - short *out = (short *) snd_shm->buffer; + if (snd->samplebits == 16) { + short *out = (short *) snd->buffer; while (count--) { val = (*p * volume) * 0x8000; @@ -98,8 +101,8 @@ s_xfer_paint_buffer (portable_samplepair_t *paintbuffer, int count, if (out_idx > out_max) out_idx = 0; } - } else if (snd_shm->samplebits == 8) { - unsigned char *out = (unsigned char *) snd_shm->buffer; + } else if (snd->samplebits == 8) { + unsigned char *out = (unsigned char *) snd->buffer; while (count--) { val = (*p * volume) * 128; @@ -116,35 +119,35 @@ s_xfer_paint_buffer (portable_samplepair_t *paintbuffer, int count, } static void -s_clear_buffer (void) +s_clear_buffer (snd_t *snd) { int clear, i; int count; - if (!sound_started || !snd_shm || !snd_shm->buffer) + if (!sound_started || !snd || !snd->buffer) return; - if (snd_shm->samplebits == 8) + if (snd->samplebits == 8) clear = 0x80; else clear = 0; - count = snd_shm->frames * snd_shm->channels * snd_shm->samplebits / 8; + count = snd->frames * snd->channels * snd->samplebits / 8; for (i = 0; i < count; i++) - snd_shm->buffer[i] = clear; + snd->buffer[i] = clear; } static void s_stop_all_sounds (void) { - SND_StopAllSounds (); - SND_ScanChannels (0); - s_clear_buffer (); + SND_StopAllSounds (&snd); + SND_ScanChannels (&snd, 0); + s_clear_buffer (&snd); } //============================================================================= -static void +/*static void s_get_soundtime (void) { int frames, framepos; @@ -196,7 +199,7 @@ s_update_ (void) SND_PaintChannels (endtime); snd_output_funcs->pS_O_Submit (); -} +}*/ /* s_update @@ -210,27 +213,27 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, if (!sound_started || (snd_blocked > 0)) return; - SND_SetListener (origin, forward, right, up, ambient_sound_level); + SND_SetListener (&snd, origin, forward, right, up, ambient_sound_level); // mix some sound - s_update_ (); - SND_ScanChannels (0); + //s_update_ (); + //SND_ScanChannels (0); } -static void -s_extra_update (void) -{ - if (!sound_started || snd_noextraupdate->int_val) - return; // don't pollute timings - s_update_ (); -} +//static void +//s_extra_update (void) +//{ +// if (!sound_started || snd_noextraupdate->int_val) +// return; // don't pollute timings +// s_update_ (); +//} static void s_block_sound (void) { if (++snd_blocked == 1) { - snd_output_funcs->pS_O_BlockSound (); - s_clear_buffer (); + snd_output_funcs->block_sound (&snd); + s_clear_buffer (&snd); } } @@ -241,8 +244,8 @@ s_unblock_sound (void) return; if (!--snd_blocked) { - s_clear_buffer (); - snd_output_funcs->pS_O_UnblockSound (); + s_clear_buffer (&snd); + snd_output_funcs->unblock_sound (&snd); } } @@ -251,18 +254,20 @@ s_unblock_sound (void) static void s_soundinfo_f (void) { - if (!sound_started || !snd_shm) { + if (!sound_started) { Sys_Printf ("sound system not started\n"); return; } - Sys_Printf ("%5d channels\n", snd_shm->channels); - Sys_Printf ("%5d frames\n", snd_shm->frames); - Sys_Printf ("%5d framepos\n", snd_shm->framepos); - Sys_Printf ("%5d samplebits\n", snd_shm->samplebits); - Sys_Printf ("%5d submission_chunk\n", snd_shm->submission_chunk); - Sys_Printf ("%5d speed\n", snd_shm->speed); - Sys_Printf ("0x%"PRIxPTR" dma buffer\n", (intptr_t) snd_shm->buffer); + Sys_Printf ("%5d channels\n", snd.channels); + Sys_Printf ("%5d frames (%.1fms)\n", snd.frames, + 1000.0 * snd.frames / snd.speed); + Sys_Printf ("%5d framepos\n", snd.framepos); + Sys_Printf ("%5d samplebits\n", snd.samplebits); + Sys_Printf ("%5d submission_chunk (%.1fms)\n", snd.submission_chunk, + 1000.0 * snd.submission_chunk / snd.speed); + Sys_Printf ("%5d speed\n", snd.speed); + Sys_Printf ("0x%"PRIxPTR" dma buffer\n", (intptr_t) snd.buffer); Sys_Printf ("%5d total_channels\n", snd_total_channels); } @@ -278,15 +283,13 @@ s_startup (void) if (!snd_initialized) return; - snd_shm = snd_output_funcs->pS_O_Init (); - - if (!snd_shm) { + if (!snd_output_funcs->init (&snd)) { Sys_Printf ("S_Startup: S_O_Init failed.\n"); sound_started = 0; return; } - if (!snd_shm->xfer) - snd_shm->xfer = s_xfer_paint_buffer; + if (!snd.xfer) + snd.xfer = s_xfer_paint_buffer; sound_started = 1; } @@ -337,8 +340,8 @@ s_init (void) if (sound_started == 0) // sound startup failed? Bail out. return; - SND_SFX_Init (); - SND_Channels_Init (); + SND_SFX_Init (&snd); + SND_Channels_Init (&snd); s_stop_all_sounds (); } @@ -350,10 +353,96 @@ s_shutdown (void) return; sound_started = 0; + snd_shutdown = 1; - snd_output_funcs->pS_O_Shutdown (); + snd_output_funcs->shutdown (&snd); +} - snd_shm = 0; +static void +s_ambient_off (void) +{ + if (!sound_started) + return; + SND_AmbientOff (&snd); +} + +static void +s_ambient_on (void) +{ + if (!sound_started) + return; + SND_AmbientOn (&snd); +} + +static void +s_static_sound (sfx_t *sfx, const vec3_t origin, float vol, + float attenuation) +{ + if (!sound_started) + return; + SND_StaticSound (&snd, sfx, origin, vol, attenuation); +} + +static void +s_start_sound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, + float fvol, float attenuation) +{ + if (!sound_started) + return; + if (!snd_shutdown) + SND_StartSound (&snd, entnum, entchannel, sfx, origin, fvol, + attenuation); +} + +static void +s_stop_sound (int entnum, int entchannel) +{ + if (!sound_started) + return; + SND_StopSound (&snd, entnum, entchannel); +} + +static sfx_t * +s_precache_sound (const char *name) +{ + if (!sound_started) + return 0; + return SND_PrecacheSound (&snd, name); +} + +static sfx_t * +s_load_sound (const char *name) +{ + if (!sound_started) + return 0; + return SND_LoadSound (&snd, name); +} + +static void +s_channel_stop (channel_t *chan) +{ + if (!sound_started) + return; + SND_ChannelStop (&snd, chan); +} + +static void +s_local_sound (const char *sound) +{ + if (!sound_started) + return; + if (!snd_shutdown) + SND_LocalSound (&snd, sound); +} + +static channel_t * +s_alloc_channel (void) +{ + if (!sound_started) + return 0; + if (!snd_shutdown) + return SND_AllocChannel (&snd); + return 0; } static general_funcs_t plugin_info_general_funcs = { @@ -362,21 +451,24 @@ static general_funcs_t plugin_info_general_funcs = { }; static snd_render_funcs_t plugin_info_render_funcs = { - .ambient_off = SND_AmbientOff, - .ambient_on = SND_AmbientOn, - .static_sound = SND_StaticSound, - .start_sound = SND_StartSound, - .stop_sound = SND_StopSound, - .precache_sound = SND_PrecacheSound, - .update = s_update, + .ambient_off = s_ambient_off, + .ambient_on = s_ambient_on, + .static_sound = s_static_sound, + .start_sound = s_start_sound, + .local_sound = s_local_sound, + .stop_sound = s_stop_sound, + + .alloc_channel = s_alloc_channel, + .channel_stop = s_channel_stop, + + .precache_sound = s_precache_sound, + .load_sound = s_load_sound, + + .update = s_update, .stop_all_sounds = s_stop_all_sounds, - .extra_update = s_extra_update, - .local_sound = SND_LocalSound, - .block_sound = s_block_sound, - .unblock_sound = s_unblock_sound, - .load_sound = SND_LoadSound, - .alloc_channel = SND_AllocChannel, - .channel_stop = SND_ChannelStop, + //.extra_update = s_extra_update, + .block_sound = s_block_sound, + .unblock_sound = s_unblock_sound, }; static plugin_funcs_t plugin_info_funcs = { diff --git a/libs/audio/renderer/snd_jack.c b/libs/audio/renderer/snd_jack.c index 173a6e01b..5b35834a1 100644 --- a/libs/audio/renderer/snd_jack.c +++ b/libs/audio/renderer/snd_jack.c @@ -54,7 +54,7 @@ static int snd_alive = 0; static double snd_alive_time = 0; static jack_client_t *jack_handle; static jack_port_t *jack_out[2]; -static dma_t _snd_shm; +static snd_t snd; static float *output[2]; static cvar_t *snd_jack_server; @@ -65,8 +65,8 @@ s_stop_all_sounds (void) { if (!sound_started) return; - SND_StopAllSounds (); - SND_ScanChannels (1); + SND_StopAllSounds (&snd); + SND_ScanChannels (&snd, 1); } static void @@ -76,7 +76,8 @@ s_start_sound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, if (!sound_started) return; if (!snd_shutdown) - SND_StartSound (entnum, entchannel, sfx, origin, fvol, attenuation); + SND_StartSound (&snd, entnum, entchannel, sfx, origin, fvol, + attenuation); } static void @@ -120,7 +121,7 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, if (snd_shutdown) return; } - SND_SetListener (origin, forward, right, up, ambient_sound_level); + SND_SetListener (&snd, origin, forward, right, up, ambient_sound_level); } static void @@ -129,7 +130,7 @@ s_local_sound (const char *sound) if (!sound_started) return; if (!snd_shutdown) - SND_LocalSound (sound); + SND_LocalSound (&snd, sound); } static void @@ -184,7 +185,7 @@ s_alloc_channel (void) if (!sound_started) return 0; if (!snd_shutdown) - return SND_AllocChannel (); + return SND_AllocChannel (&snd); return 0; } @@ -202,7 +203,7 @@ s_ambient_off (void) { if (!sound_started) return; - SND_AmbientOff (); + SND_AmbientOff (&snd); } static void @@ -210,7 +211,7 @@ s_ambient_on (void) { if (!sound_started) return; - SND_AmbientOn (); + SND_AmbientOn (&snd); } static void @@ -219,7 +220,7 @@ s_static_sound (sfx_t *sfx, const vec3_t origin, float vol, { if (!sound_started) return; - SND_StaticSound (sfx, origin, vol, attenuation); + SND_StaticSound (&snd, sfx, origin, vol, attenuation); } static void @@ -227,7 +228,7 @@ s_stop_sound (int entnum, int entchannel) { if (!sound_started) return; - SND_StopSound (entnum, entchannel); + SND_StopSound (&snd, entnum, entchannel); } static sfx_t * @@ -235,7 +236,7 @@ s_precache_sound (const char *name) { if (!sound_started) return 0; - return SND_PrecacheSound (name); + return SND_PrecacheSound (&snd, name); } static sfx_t * @@ -243,7 +244,7 @@ s_load_sound (const char *name) { if (!sound_started) return 0; - return SND_LoadSound (name); + return SND_LoadSound (&snd, name); } static void @@ -251,11 +252,12 @@ s_channel_stop (channel_t *chan) { if (!sound_started) return; - SND_ChannelStop (chan); + SND_ChannelStop (&snd, chan); } static void -snd_jack_xfer (portable_samplepair_t *paintbuffer, int count, float volume) +snd_jack_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, + float volume) { int i; @@ -281,7 +283,7 @@ snd_jack_process (jack_nframes_t nframes, void *arg) snd_alive = 1; for (i = 0; i < 2; i++) output[i] = (float *) jack_port_get_buffer (jack_out[i], nframes); - SND_PaintChannels (snd_paintedtime + nframes); + SND_PaintChannels (&snd, snd_paintedtime + nframes); return 0; } @@ -327,17 +329,16 @@ s_jack_connect (void) jack_out[i] = jack_port_register (jack_handle, va (0, "out_%d", i + 1), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - snd_shm->speed = jack_get_sample_rate (jack_handle); + snd.speed = jack_get_sample_rate (jack_handle); s_jack_activate (); sound_started = 1; - Sys_Printf ("Connected to JACK: %d Sps\n", snd_shm->speed); + Sys_Printf ("Connected to JACK: %d Sps\n", snd.speed); } static void s_init (void) { - snd_shm = &_snd_shm; - snd_shm->xfer = snd_jack_xfer; + snd.xfer = snd_jack_xfer; Cmd_AddCommand ("snd_force_unblock", s_snd_force_unblock, "fix permanently blocked sound"); @@ -347,8 +348,8 @@ s_init (void) snd_jack_server = Cvar_Get ("snd_jack_server", "default", CVAR_ROM, NULL, "The name of the JACK server to connect to"); - SND_SFX_Init (); - SND_Channels_Init (); + SND_SFX_Init (&snd); + SND_Channels_Init (&snd); s_jack_connect (); } diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 1be26620d..6f21a1f6f 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -51,7 +51,6 @@ #define SAMPLE_GAP 4 -volatile dma_t *snd_shm; snd_render_data_t snd_render_data = { 0, 0, @@ -212,7 +211,7 @@ SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos) sfxstream_t *stream = sfx->data.stream; wavinfo_t *info = &stream->wavinfo; - stepscale = (float) info->rate / snd_shm->speed; + stepscale = (float) info->rate / sfx->snd->speed; buffer->head = buffer->tail = 0; buffer->pos = pos; @@ -235,7 +234,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count) if (!count) return 1; - stepscale = (float) info->rate / snd_shm->speed; + stepscale = (float) info->rate / sfx->snd->speed; // find out how many samples the buffer currently holds samples = buffer->head - buffer->tail; @@ -360,8 +359,9 @@ SND_GetCache (long frames, int rate, int channels, float stepscale; sfxbuffer_t *sc; sfx_t *sfx = block->sfx; + snd_t *snd = sfx->snd; - stepscale = (float) rate / snd_shm->speed; + stepscale = (float) rate / snd->speed; len = size = frames / stepscale; size *= sizeof (float) * channels; sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name); diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index 2c54836d1..f993852a9 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -104,7 +104,7 @@ snd_paint_channel (channel_t *ch, sfxbuffer_t *sc, int count) } void -SND_PaintChannels (unsigned endtime) +SND_PaintChannels (snd_t *snd, unsigned endtime) { unsigned end, ltime; int i, count; @@ -171,8 +171,8 @@ SND_PaintChannels (unsigned endtime) } // transfer out according to DMA format - snd_shm->xfer (snd_paintbuffer, end - snd_paintedtime, - snd_volume->value); + snd->xfer (snd, snd_paintbuffer, end - snd_paintedtime, + snd_volume->value); memmove (snd_paintbuffer, snd_paintbuffer + end - snd_paintedtime, max_overpaint * sizeof (snd_paintbuffer[0])); diff --git a/libs/audio/renderer/snd_resample.c b/libs/audio/renderer/snd_resample.c index a3037561d..2045039e0 100644 --- a/libs/audio/renderer/snd_resample.c +++ b/libs/audio/renderer/snd_resample.c @@ -68,11 +68,12 @@ SND_Resample (sfxbuffer_t *sc, float *data, int length) int outcount; double stepscale; wavinfo_t *info = sc->sfx->wavinfo (sc->sfx); + snd_t *snd = sc->sfx->snd; int inrate = info->rate; int outwidth; SRC_DATA src_data; - stepscale = (double) snd_shm->speed / inrate; + stepscale = (double) snd->speed / inrate; outcount = length * stepscale; src_data.data_in = data; @@ -119,7 +120,7 @@ static int snd_resample_read (sfxstream_t *stream, float *data, int frames) { int inrate = stream->wavinfo.rate; - double ratio = (double) snd_shm->speed / inrate; + double ratio = (double) stream->sfx->snd->speed / inrate; return src_callback_read (stream->state, ratio, frames, data); } @@ -143,9 +144,10 @@ SND_SetupResampler (sfxbuffer_t *sc, int streamed) { double stepscale; wavinfo_t *info = sc->sfx->wavinfo (sc->sfx); + snd_t *snd = sc->sfx->snd; int inrate = info->rate; - stepscale = (double) snd_shm->speed / inrate; + stepscale = (double) snd->speed / inrate; sc->sfx->length = info->frames * stepscale; if (info->loopstart != (unsigned int)-1) @@ -159,7 +161,7 @@ SND_SetupResampler (sfxbuffer_t *sc, int streamed) int err; sfxstream_t *stream = sc->sfx->data.stream; - if (snd_shm->speed == inrate) { + if (snd->speed == inrate) { stream->state = calloc (sizeof (snd_null_state_t), 1); stream->read = snd_read; } else { diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 8152213a6..b3abc6f66 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -112,6 +112,7 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file, int (*seek)(sfxstream_t *, int), void (*close) (sfx_t *)) { + snd_t *snd = sfx->snd; sfxstream_t *stream = sfx->data.stream; wavinfo_t *info = &stream->wavinfo; int frames; @@ -119,11 +120,12 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file, // if the speed is 0, there is no sound driver (probably failed to connect // to jackd) - if (!snd_shm->speed) + if (!snd->speed) return 0; sfx_t *new_sfx = calloc (1, sizeof (sfx_t)); + new_sfx->snd = sfx->snd; new_sfx->name = sfx->name; new_sfx->owner = sfx; new_sfx->wavinfo = SND_CacheWavinfo; @@ -132,7 +134,7 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file, new_sfx->getbuffer = SND_StreamGetBuffer; new_sfx->close = close; - frames = snd_shm->speed * 0.3; + frames = snd->speed * 0.3; frames = (frames + 255) & ~255; size = frames * info->channels * sizeof (float); @@ -168,7 +170,7 @@ SND_SFX_StreamClose (sfx_t *sfx) } sfx_t * -SND_LoadSound (const char *name) +SND_LoadSound (snd_t *snd, const char *name) { sfx_t *sfx; @@ -181,6 +183,7 @@ SND_LoadSound (const char *name) Sys_Error ("s_load_sound: out of sfx_t"); sfx = &snd_sfx[snd_num_sfx++]; + sfx->snd = snd; sfx->name = strdup (name); sfx->owner = sfx; if (SND_Load (sfx) == -1) { @@ -192,14 +195,14 @@ SND_LoadSound (const char *name) } sfx_t * -SND_PrecacheSound (const char *name) +SND_PrecacheSound (snd_t *snd, const char *name) { sfx_t *sfx; if (!name) Sys_Error ("SND_PrecacheSound: NULL"); - sfx = SND_LoadSound (va (0, "sound/%s", name)); + sfx = SND_LoadSound (snd, va (0, "sound/%s", name)); if (sfx && precache->int_val) { if (sfx->retain (sfx)) sfx->release (sfx); @@ -243,7 +246,7 @@ s_soundlist_f (void) } void -SND_SFX_Init (void) +SND_SFX_Init (snd_t *snd) { snd_sfx_hash = Hash_NewTable (511, snd_sfx_getkey, snd_sfx_free, 0, 0); precache = Cvar_Get ("precache", "1", CVAR_NONE, NULL, diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 89dbc713b..3ad64381c 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -39,14 +39,20 @@ #include "snd_internal.h" +typedef struct { + const snd_pcm_channel_area_t *areas; + snd_pcm_uframes_t offset; + snd_pcm_uframes_t nframes; +} alsa_pkt_t; + static int snd_inited; static int snd_blocked = 0; -static volatile dma_t sn; static snd_pcm_uframes_t buffer_size; static void *alsa_handle; static const char *pcmname = NULL; static snd_pcm_t *pcm; +static snd_async_handler_t *async_haandler; static plugin_t plugin_info; static plugin_data_t plugin_info_data; @@ -101,7 +107,7 @@ SNDDMA_Init_Cvars (void) "sound sample depth. 0 is system default"); } -static int SNDDMA_GetDMAPos (void); +static int SNDDMA_GetDMAPos (snd_t *snd); static __attribute__((const)) snd_pcm_uframes_t round_buffer_size (snd_pcm_uframes_t sz) @@ -136,25 +142,26 @@ clamp_8 (int val) } static void -SNDDMA_ni_xfer (portable_samplepair_t *paintbuffer, int count, float volume) +alsa_ni_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, + float volume) { const snd_pcm_channel_area_t *areas; int out_idx, out_max; float *p; - areas = sn.xfer_data; + areas = snd->xfer_data; p = (float *) paintbuffer; - out_max = sn.frames - 1; + out_max = snd->frames - 1; out_idx = *plugin_info_snd_output_data.paintedtime; while (out_idx > out_max) out_idx -= out_max + 1; - if (sn.samplebits == 16) { + if (snd->samplebits == 16) { short *out_0 = (short *) areas[0].addr; short *out_1 = (short *) areas[1].addr; - if (sn.channels == 2) { + if (snd->channels == 2) { while (count--) { out_0[out_idx] = clamp_16 ((*p++ * volume) * 0x8000); out_1[out_idx] = clamp_16 ((*p++ * volume) * 0x8000); @@ -169,11 +176,11 @@ SNDDMA_ni_xfer (portable_samplepair_t *paintbuffer, int count, float volume) out_idx = 0; } } - } else if (sn.samplebits == 8) { + } else if (snd->samplebits == 8) { byte *out_0 = (byte *) areas[0].addr; byte *out_1 = (byte *) areas[1].addr; - if (sn.channels == 2) { + if (snd->channels == 2) { while (count--) { out_0[out_idx] = clamp_8 ((*p++ * volume) * 0x80); out_1[out_idx] = clamp_8 ((*p++ * volume) * 0x80); @@ -191,8 +198,71 @@ SNDDMA_ni_xfer (portable_samplepair_t *paintbuffer, int count, float volume) } } -static volatile dma_t * -SNDDMA_Init (void) +static void +alsa_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, + float volume) +{ + int out_idx, out_max, step, val; + float *p; + + p = (float *) paintbuffer; + count *= snd->channels; + out_max = (snd->frames * snd->channels) - 1; + out_idx = snd_paintedtime * snd->channels; + while (out_idx > out_max) + out_idx -= out_max + 1; + step = 3 - snd->channels; + + if (snd->samplebits == 16) { + short *out = (short *) snd->buffer; + + while (count--) { + val = (*p * volume) * 0x8000; + p += step; + if (val > 0x7fff) + val = 0x7fff; + else if (val < -0x8000) + val = -0x8000; + out[out_idx++] = val; + if (out_idx > out_max) + out_idx = 0; + } + } else if (snd->samplebits == 8) { + unsigned char *out = (unsigned char *) snd->buffer; + + while (count--) { + val = (*p * volume) * 128; + p += step; + if (val > 0x7f) + val = 0x7f; + else if (val < -0x80) + val = -0x80; + out[out_idx++] = val + 0x80; + if (out_idx > out_max) + out_idx = 0; + } + } +} + +static void +alsa_callback (snd_async_handler_t *handler) +{ + snd_pcm_t *pcm = qfsnd_async_handler_get_pcm (handler); + snd_t *snd = qfsnd_async_handler_get_callback_private (handler); + alsa_pkt_t packet; + + qfsnd_pcm_avail_update (pcm); + qfsnd_pcm_mmap_begin (pcm, &packet.areas, &packet.offset, &packet.nframes); + + snd->xfer_data = &packet; + + SND_PaintChannels (snd, snd_paintedtime + packet.nframes); + + qfsnd_pcm_mmap_commit (pcm, packet.offset, packet.nframes); +} + +static int +SNDDMA_Init (snd_t *snd) { int err; int bps = -1, stereo = -1; @@ -238,6 +308,7 @@ retry_open: goto error; } + snd->xfer = alsa_xfer; err = qfsnd_pcm_hw_params_set_access (pcm, hw, SND_PCM_ACCESS_MMAP_INTERLEAVED); if (0 > err) { @@ -257,7 +328,7 @@ retry_open: Sys_Printf ("ALSA: could not set mmap access\n"); goto error; } - sn.xfer = SNDDMA_ni_xfer; + snd->xfer = alsa_ni_xfer; } Sys_Printf ("Using PCM %s.\n", pcmname); @@ -371,8 +442,6 @@ retry_open: (int) period_size, qfsnd_strerror (err)); goto error; } - int dir; - qfsnd_pcm_hw_params_get_period_size (hw, &period_size, &dir); err = qfsnd_pcm_hw_params (pcm, hw); if (0 > err) { Sys_Printf ("ALSA: unable to install hw params: %s\n", @@ -404,21 +473,19 @@ retry_open: goto error; } - memset ((dma_t *) &sn, 0, sizeof (sn)); - sn.channels = stereo + 1; + snd->channels = stereo + 1; // don't mix less than this in frames: - err = qfsnd_pcm_hw_params_get_period_size (hw, (snd_pcm_uframes_t *) - (char *) - &sn.submission_chunk, 0); + err = qfsnd_pcm_hw_params_get_period_size (hw, &period_size, 0); if (0 > err) { Sys_Printf ("ALSA: unable to get period size. %s\n", qfsnd_strerror (err)); goto error; } + snd->submission_chunk = period_size; - sn.framepos = 0; - sn.samplebits = bps; + snd->framepos = 0; + snd->samplebits = bps; err = qfsnd_pcm_hw_params_get_buffer_size (hw, &buffer_size); if (0 > err) { @@ -432,46 +499,58 @@ retry_open: Sys_Printf ("to have a power of 2 buffer size\n"); } - sn.frames = buffer_size; - sn.speed = rate; - SNDDMA_GetDMAPos (); //XXX sets sn.buffer - Sys_Printf ("%5d channels %sinterleaved\n", sn.channels, - sn.xfer ? "non-" : ""); - Sys_Printf ("%5d samples (%.1fms)\n", sn.frames, - 1000.0 * sn.frames / sn.speed); - Sys_Printf ("%5d samplepos\n", sn.framepos); - Sys_Printf ("%5d samplebits\n", sn.samplebits); - Sys_Printf ("%5d submission_chunk (%.1fms)\n", sn.submission_chunk, - 1000.0 * sn.submission_chunk / sn.speed); - Sys_Printf ("%5d speed\n", sn.speed); - Sys_Printf ("0x%lx dma buffer\n", (long) sn.buffer); + qfsnd_async_add_pcm_handler (&async_haandler, pcm, alsa_callback, snd); + + snd->frames = buffer_size; + snd->speed = rate; + SNDDMA_GetDMAPos (snd); //XXX sets snd->buffer + Sys_Printf ("%5d channels %sinterleaved\n", snd->channels, + snd->xfer ? "non-" : ""); + Sys_Printf ("%5d samples (%.1fms)\n", snd->frames, + 1000.0 * snd->frames / snd->speed); + Sys_Printf ("%5d samplepos\n", snd->framepos); + Sys_Printf ("%5d samplebits\n", snd->samplebits); + Sys_Printf ("%5d submission_chunk (%.1fms)\n", snd->submission_chunk, + 1000.0 * snd->submission_chunk / snd->speed); + Sys_Printf ("%5d speed\n", snd->speed); + Sys_Printf ("0x%lx dma buffer\n", (long) snd->buffer); snd_inited = 1; - return &sn; + + alsa_pkt_t packet; + qfsnd_pcm_mmap_begin (pcm, &packet.areas, &packet.offset, &packet.nframes); + snd->xfer_data = &packet; + SND_PaintChannels (snd, snd_paintedtime + packet.nframes); + qfsnd_pcm_mmap_commit (pcm, packet.offset, packet.nframes); + qfsnd_pcm_start (pcm); + + return 1; error: qfsnd_pcm_close (pcm); return 0; } static int -SNDDMA_GetDMAPos (void) +SNDDMA_GetDMAPos (snd_t *snd) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t offset; - snd_pcm_uframes_t nframes = sn.frames; + snd_pcm_uframes_t nframes = snd->frames; qfsnd_pcm_avail_update (pcm); qfsnd_pcm_mmap_begin (pcm, &areas, &offset, &nframes); - sn.framepos = offset; - sn.buffer = areas->addr; - sn.xfer_data = (void *) areas; - return sn.framepos; + snd->framepos = offset; + snd->buffer = areas->addr; + snd->xfer_data = (void *) areas; + return snd->framepos; } static void -SNDDMA_shutdown (void) +SNDDMA_shutdown (snd_t *snd) { if (snd_inited) { + qfsnd_async_del_handler (async_haandler); + async_haandler = 0; qfsnd_pcm_close (pcm); snd_inited = 0; } @@ -483,7 +562,7 @@ SNDDMA_shutdown (void) Send sound to device if buffer isn't really the dma buffer */ static void -SNDDMA_Submit (void) +SNDDMA_Submit (snd_t *snd) { int state; int count = (*plugin_info_snd_output_data.paintedtime - @@ -516,14 +595,14 @@ SNDDMA_Submit (void) } static void -SNDDMA_BlockSound (void) +SNDDMA_BlockSound (snd_t *snd) { if (snd_inited && ++snd_blocked == 1) qfsnd_pcm_pause (pcm, 1); } static void -SNDDMA_UnblockSound (void) +SNDDMA_UnblockSound (snd_t *snd) { if (!snd_inited || !snd_blocked) return; @@ -554,12 +633,12 @@ PLUGIN_INFO(snd_output, alsa) plugin_info_general_funcs.init = SNDDMA_Init_Cvars; plugin_info_general_funcs.shutdown = NULL; - plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; - plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; - plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; - plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; - plugin_info_snd_output_funcs.pS_O_UnblockSound = SNDDMA_UnblockSound; + plugin_info_snd_output_funcs.init = SNDDMA_Init; + plugin_info_snd_output_funcs.shutdown = SNDDMA_shutdown; + plugin_info_snd_output_funcs.get_dma_pos = SNDDMA_GetDMAPos; + plugin_info_snd_output_funcs.submit = SNDDMA_Submit; + plugin_info_snd_output_funcs.block_sound = SNDDMA_BlockSound; + plugin_info_snd_output_funcs.unblock_sound = SNDDMA_UnblockSound; return &plugin_info; } diff --git a/libs/audio/targets/snd_oss.c b/libs/audio/targets/snd_oss.c index c7e53b534..59e34cf93 100644 --- a/libs/audio/targets/snd_oss.c +++ b/libs/audio/targets/snd_oss.c @@ -78,7 +78,6 @@ static int audio_fd; static int snd_inited; static int mmaped_io = 0; static const char *snd_dev = "/dev/dsp"; -static volatile dma_t sn; static int tryrates[] = { 44100, 48000, 11025, 22050, 22051, 44100, 8000 }; @@ -112,8 +111,8 @@ SNDDMA_Init_Cvars (void) "mmaped io"); } -static volatile dma_t * -try_open (int rw) +static int +try_open (snd_t *snd, int rw) { int caps, fmt, rc, tmp, i; int retries = 3; @@ -169,21 +168,21 @@ try_open (int rw) } // set sample bits & speed - sn.samplebits = snd_bits->int_val; + snd->samplebits = snd_bits->int_val; - if (sn.samplebits != 16 && sn.samplebits != 8) { + if (snd->samplebits != 16 && snd->samplebits != 8) { ioctl (audio_fd, SNDCTL_DSP_GETFMTS, &fmt); if (fmt & AFMT_S16_LE) { // little-endian 16-bit signed - sn.samplebits = 16; + snd->samplebits = 16; } else { if (fmt & AFMT_U8) { // unsigned 8-bit ulaw - sn.samplebits = 8; + snd->samplebits = 8; } } } - if (sn.samplebits == 16) { + if (snd->samplebits == 16) { rc = AFMT_S16_LE; rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc); if (rc < 0) { @@ -192,7 +191,7 @@ try_open (int rw) close (audio_fd); return 0; } - } else if (sn.samplebits == 8) { + } else if (snd->samplebits == 8) { rc = AFMT_U8; rc = ioctl (audio_fd, SNDCTL_DSP_SETFMT, &rc); if (rc < 0) { @@ -202,39 +201,39 @@ try_open (int rw) return 0; } } else { - Sys_Printf ("%d-bit sound not supported. %s", sn.samplebits, + Sys_Printf ("%d-bit sound not supported. %s", snd->samplebits, strerror (errno)); close (audio_fd); return 0; } - tmp = sn.channels; + tmp = snd->channels; rc = ioctl (audio_fd, SNDCTL_DSP_CHANNELS, &tmp); if (rc < 0) { Sys_Printf ("Could not set %s to stereo=%d: %s\n", snd_dev, - sn.channels, strerror (errno)); + snd->channels, strerror (errno)); close (audio_fd); return 0; } if (snd_rate->int_val) { - sn.speed = snd_rate->int_val; + snd->speed = snd_rate->int_val; } else { for (i = 0; i < ((int) sizeof (tryrates) / 4); i++) if (!ioctl (audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break; - sn.speed = tryrates[i]; + snd->speed = tryrates[i]; } if (!snd_stereo->int_val) { - sn.channels = 1; + snd->channels = 1; } else { - sn.channels = 2; + snd->channels = 2; } - rc = ioctl (audio_fd, SNDCTL_DSP_SPEED, &sn.speed); + rc = ioctl (audio_fd, SNDCTL_DSP_SPEED, &snd->speed); if (rc < 0) { - Sys_Printf ("Could not set %s speed to %d: %s\n", snd_dev, sn.speed, + Sys_Printf ("Could not set %s speed to %d: %s\n", snd_dev, snd->speed, strerror (errno)); close (audio_fd); return 0; @@ -246,25 +245,25 @@ try_open (int rw) return 0; } - sn.frames = info.fragstotal * info.fragsize; - sn.frames /= sn.channels * sn.samplebits / 8; - sn.submission_chunk = 1; + snd->frames = info.fragstotal * info.fragsize; + snd->frames /= snd->channels * snd->samplebits / 8; + snd->submission_chunk = 1; if (mmaped_io) { // memory map the dma buffer unsigned long sz = sysconf (_SC_PAGESIZE); unsigned long len = info.fragstotal * info.fragsize; len = (len + sz - 1) & ~(sz - 1); - sn.buffer = (byte *) mmap (NULL, len, mmmode, mmflags, audio_fd, 0); - if (sn.buffer == MAP_FAILED) { + snd->buffer = (byte *) mmap (NULL, len, mmmode, mmflags, audio_fd, 0); + if (snd->buffer == MAP_FAILED) { Sys_MaskPrintf (SYS_snd, "Could not mmap %s: %s\n", snd_dev, strerror (errno)); close (audio_fd); return 0; } } else { - sn.buffer = malloc (sn.frames * sn.channels * (sn.samplebits / 8)); - if (!sn.buffer) { + snd->buffer = malloc (snd->frames * snd->channels * (snd->samplebits / 8)); + if (!snd->buffer) { Sys_Printf ("SNDDMA_Init: memory allocation failure\n"); close (audio_fd); return 0; @@ -277,7 +276,7 @@ try_open (int rw) if (rc < 0) { Sys_Printf ("Could not toggle.: %s\n", strerror (errno)); if (mmaped_io) - munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8); + munmap (snd->buffer, snd->frames * snd->channels * snd->samplebits / 8); close (audio_fd); return 0; } @@ -286,28 +285,25 @@ try_open (int rw) if (rc < 0) { Sys_Printf ("Could not toggle.: %s\n", strerror (errno)); if (mmaped_io) - munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8); + munmap (snd->buffer, snd->frames * snd->channels * snd->samplebits / 8); close (audio_fd); return 0; } - sn.framepos = 0; + snd->framepos = 0; snd_inited = 1; - return &sn; -} - -static volatile dma_t * -SNDDMA_Init (void) -{ - volatile dma_t *shm; - if ((shm = try_open (0))) - return shm; - return try_open (1); + return 1; } static int -SNDDMA_GetDMAPos (void) +SNDDMA_Init (snd_t *snd) +{ + return try_open (snd, 0) || try_open (snd, 1); +} + +static int +SNDDMA_GetDMAPos (snd_t *snd) { struct count_info count; @@ -317,34 +313,32 @@ SNDDMA_GetDMAPos (void) if (ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &count) == -1) { Sys_Printf ("Uh, %s dead: %s\n", snd_dev, strerror (errno)); if (mmaped_io) - munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8); + munmap (snd->buffer, snd->frames * snd->channels * snd->samplebits / 8); close (audio_fd); snd_inited = 0; return 0; } -// sn.samplepos = (count.bytes / (sn.samplebits / 8)) & (sn.samples-1); -// fprintf(stderr, "%d \r", count.ptr); - sn.framepos = count.ptr / (sn.channels * sn.samplebits / 8); + snd->framepos = count.ptr / (snd->channels * snd->samplebits / 8); - return sn.framepos; + return snd->framepos; } static void -SNDDMA_shutdown (void) +SNDDMA_shutdown (snd_t *snd) { if (snd_inited) { if (mmaped_io) - munmap (sn.buffer, sn.frames * sn.channels * sn.samplebits / 8); + munmap (snd->buffer, snd->frames * snd->channels * snd->samplebits / 8); close (audio_fd); snd_inited = 0; } } static int -sample_bytes (int frames) +sample_bytes (snd_t *snd, int frames) { - return frames * sn.channels * sn.samplebits / 8; + return frames * snd->channels * snd->samplebits / 8; } /* @@ -353,7 +347,7 @@ sample_bytes (int frames) Send sound to device if buffer isn't really the dma buffer */ static void -SNDDMA_Submit (void) +SNDDMA_Submit (snd_t *snd) { int frames; int len; @@ -362,17 +356,17 @@ SNDDMA_Submit (void) if (snd_inited && !mmaped_io) { frames = *plugin_info_snd_output_data.paintedtime - *plugin_info_snd_output_data.soundtime; - offset = frames * sn.channels * sn.samplebits / 8; + offset = frames * snd->channels * snd->samplebits / 8; - if (sn.framepos + frames <= sn.frames) { - len = sample_bytes (frames); - if (write (audio_fd, sn.buffer + offset, len) != len) + if (snd->framepos + frames <= snd->frames) { + len = sample_bytes (snd, frames); + if (write (audio_fd, snd->buffer + offset, len) != len) Sys_Printf ("SNDDMA_Submit(): %s\n", strerror (errno)); } else { - int len = sample_bytes (sn.frames - sn.framepos); - if (write (audio_fd, sn.buffer + offset, len) != len) + int len = sample_bytes (snd, snd->frames - snd->framepos); + if (write (audio_fd, snd->buffer + offset, len) != len) Sys_Printf ("SNDDMA_Submit(): %s\n", strerror (errno)); - if (write (audio_fd, sn.buffer, offset - len) != offset - len) + if (write (audio_fd, snd->buffer, offset - len) != offset - len) Sys_Printf ("SNDDMA_Submit(): %s\n", strerror (errno)); } *plugin_info_snd_output_data.soundtime += frames; @@ -380,12 +374,12 @@ SNDDMA_Submit (void) } static void -SNDDMA_BlockSound (void) +SNDDMA_BlockSound (snd_t *snd) { } static void -SNDDMA_UnblockSound (void) +SNDDMA_UnblockSound (snd_t *snd) { } @@ -412,12 +406,12 @@ PLUGIN_INFO(snd_output, oss) plugin_info_general_funcs.init = SNDDMA_Init_Cvars; plugin_info_general_funcs.shutdown = NULL; - plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; - plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; - plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; - plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; - plugin_info_snd_output_funcs.pS_O_UnblockSound = SNDDMA_UnblockSound; + plugin_info_snd_output_funcs.init = SNDDMA_Init; + plugin_info_snd_output_funcs.shutdown = SNDDMA_shutdown; + plugin_info_snd_output_funcs.get_dma_pos = SNDDMA_GetDMAPos; + plugin_info_snd_output_funcs.submit = SNDDMA_Submit; + plugin_info_snd_output_funcs.block_sound = SNDDMA_BlockSound; + plugin_info_snd_output_funcs.unblock_sound = SNDDMA_UnblockSound; return &plugin_info; } From 54bc7a83ba5aab2f6fd0a5ae3f242fc18f11be4c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jun 2021 00:14:33 +0900 Subject: [PATCH 1594/3664] [audio] Fix missed compile issues Due to not having wildmidi on my eeepc. --- include/snd_internal.h | 2 +- libs/audio/renderer/midi.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index aa22b2299..91e0a53c7 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -491,7 +491,7 @@ int SND_LoadWav (QFile *file, sfx_t *sfx, char *realname); \param realname path of sound file should it need to be re-opened \return 0 if ok, -1 on error */ -int SND_LoadMidi (snd_t *snd, QFile *file, sfx_t *sfx, char *realname); +int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname); ///@} /** \defgroup sound_render_cache_stream Cache/Stream Functions. diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index 3e2ca6727..bdb43975d 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -61,21 +61,21 @@ static cvar_t *wildmidi_volume; static cvar_t *wildmidi_config; static int -midi_init ( void ) { +midi_init (snd_t *snd) { wildmidi_volume = Cvar_Get ("wildmidi_volume", "100", CVAR_ARCHIVE, NULL, "Set the Master Volume"); wildmidi_config = Cvar_Get ("wildmidi_config", "/etc/timidity.cfg", CVAR_ROM, NULL, "path/filename of timidity.cfg"); - if (WildMidi_Init (wildmidi_config->string, snd_shm->speed, 0) == -1) + if (WildMidi_Init (wildmidi_config->string, snd->speed, 0) == -1) return 1; midi_intiialized = 1; return 0; } static wavinfo_t -midi_get_info (void * handle) { +midi_get_info (snd_t *snd, void *handle) { wavinfo_t info; struct _WM_Info *wm_info; @@ -86,7 +86,7 @@ midi_get_info (void * handle) { return info; } - info.rate = snd_shm->speed; + info.rate = snd->speed; info.width = 2; info.channels = 2; info.loopstart = -1; @@ -171,13 +171,14 @@ midi_stream_open (sfx_t *sfx) int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname) { + snd_t *snd = sfx->snd; wavinfo_t info; midi *handle; unsigned char *local_buffer; unsigned long int local_buffer_size = Qfilesize (file); if (!midi_intiialized) { - if (midi_init ()) { + if (midi_init (snd)) { return -1; } } @@ -193,7 +194,7 @@ SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname) if (handle == NULL) return -1; - info = midi_get_info (handle); + info = midi_get_info (snd, handle); WildMidi_Close (handle); From ec66db399ea985ad16f3b1cdbf593f62d3743f30 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Jun 2021 16:32:30 +0900 Subject: [PATCH 1595/3664] [audio] Fix broken cd plugin struct The plugin struct cleanup accidentaly added unwanted fields to the cd plugin functions. --- include/QF/plugin/cd.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/QF/plugin/cd.h b/include/QF/plugin/cd.h index 337fc6220..94e7f8c10 100644 --- a/include/QF/plugin/cd.h +++ b/include/QF/plugin/cd.h @@ -35,9 +35,7 @@ typedef struct cd_funcs_s { void (*pause) (void); void (*play) (int, qboolean); void (*resume) (void); - void (*shutdown) (void); void (*update) (void); - void (*init) (void); } cd_funcs_t; typedef struct cd_data_s { From 79825db539818d3470e28f94ab974b27a9b37d0b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Jun 2021 09:50:31 +0900 Subject: [PATCH 1596/3664] [audio] Clean up alsa init and add error checking This gets the alsa target working nicely for mmapped outout. I'm not certain, but I think it will even deal with NPOT buffer sizes (I copied the code from libasound's sample pcm.c, thus the uncertainty). Non-mmapped output isn't supported yet, but the alsa target now works nicely for pull rendering. However, some work still needs to be done for recovery failure: either disable the sound system, or restart the driver entirely (preferable). --- include/alsa_funcs_list.h | 4 + libs/audio/targets/snd_alsa.c | 580 +++++++++++++++++++++------------- 2 files changed, 360 insertions(+), 224 deletions(-) diff --git a/include/alsa_funcs_list.h b/include/alsa_funcs_list.h index 6b9b15111..af7fcb4be 100644 --- a/include/alsa_funcs_list.h +++ b/include/alsa_funcs_list.h @@ -49,7 +49,11 @@ QF_ALSA_NEED (int, snd_pcm_hw_params_get_period_size, (const snd_pcm_hw_params_t QF_ALSA_NEED (int, snd_pcm_hw_params_set_access, (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access)) QF_ALSA_NEED (int, snd_pcm_hw_params_set_period_size_near, (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir)) QF_ALSA_NEED (int, snd_pcm_hw_params_set_rate_near, (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)) +QF_ALSA_NEED (int, snd_pcm_hw_params_set_rate, (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int dir)) +QF_ALSA_NEED (int, snd_pcm_hw_params_get_rate, (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir)) #endif +QF_ALSA_NEED (int, snd_pcm_prepare, (snd_pcm_t *pcm)) +QF_ALSA_NEED (int, snd_pcm_resume, (snd_pcm_t *pcm)) QF_ALSA_NEED (int, snd_pcm_hw_params_set_channels, (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val)) QF_ALSA_NEED (int, snd_pcm_hw_params_set_format, (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val)) QF_ALSA_NEED (size_t, snd_pcm_hw_params_sizeof, (void)) diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 3ad64381c..28593a5f8 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -50,9 +50,8 @@ static int snd_blocked = 0; static snd_pcm_uframes_t buffer_size; static void *alsa_handle; -static const char *pcmname = NULL; static snd_pcm_t *pcm; -static snd_async_handler_t *async_haandler; +static snd_async_handler_t *async_handler; static plugin_t plugin_info; static plugin_data_t plugin_info_data; @@ -244,265 +243,393 @@ alsa_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, } } +static int +alsa_recover (snd_pcm_t *pcm, int err) +{ + if (err == -EPIPE) { + Sys_Printf ("snd_alsa: xrun\n"); + // xrun + if ((err = qfsnd_pcm_prepare (pcm)) < 0) { + Sys_MaskPrintf (SYS_snd, "snd_alsa: recover from xrun failed: %s\n", + qfsnd_strerror (err)); + return err; + } + return 0; + } else if (err == -ESTRPIPE) { + Sys_Printf ("snd_alsa: suspend\n"); + // suspend + while ((err = qfsnd_pcm_resume(pcm)) == -EAGAIN) { + usleep (20 * 1000); + } + if (err < 0 && (err = qfsnd_pcm_prepare (pcm)) < 0) { + Sys_MaskPrintf (SYS_snd, + "snd_alsa: recover from suspend failed: %s\n", + qfsnd_strerror (err)); + return err; + } + return 0; + } + return err; +} + +static int +alsa_process (snd_pcm_t *pcm, snd_t *snd) +{ + alsa_pkt_t packet; + int res; + int ret = 1; + snd_pcm_uframes_t size = snd->submission_chunk; + + snd->xfer_data = &packet; + while (size > 0) { + packet.nframes = size; + if ((res = qfsnd_pcm_mmap_begin (pcm, &packet.areas, &packet.offset, + &packet.nframes)) < 0) { + if ((res = alsa_recover (pcm, -EPIPE)) < 0) { + Sys_Printf ("snd_alsa: XRUN recovery failed: %s\n", + qfsnd_strerror (res)); + return res; + } + ret = 0; + } + SND_PaintChannels (snd, snd_paintedtime + packet.nframes); + if ((res = qfsnd_pcm_mmap_commit (pcm, packet.offset, + packet.nframes)) < 0 + || (snd_pcm_uframes_t) res != packet.nframes) { + if ((res = alsa_recover (pcm, res >= 0 ? -EPIPE : res)) < 0) { + Sys_Printf ("snd_alsa: XRUN recovery failed: %s\n", + qfsnd_strerror (res)); + return res; + } + ret = 0; + } + size -= packet.nframes; + } + + return ret; +} + static void alsa_callback (snd_async_handler_t *handler) { snd_pcm_t *pcm = qfsnd_async_handler_get_pcm (handler); snd_t *snd = qfsnd_async_handler_get_callback_private (handler); - alsa_pkt_t packet; + int res; + int avail; + int first = 0; - qfsnd_pcm_avail_update (pcm); - qfsnd_pcm_mmap_begin (pcm, &packet.areas, &packet.offset, &packet.nframes); + while (1) { + snd_pcm_state_t state = qfsnd_pcm_state (pcm); + if (state == SND_PCM_STATE_XRUN) { + if ((res = alsa_recover (pcm, -EPIPE)) < 0) { + Sys_Printf ("snd_alsa: XRUN recovery failed: %s\n", + qfsnd_strerror (res)); + //FIXME disable/restart sound + return; + } + } else if (state == SND_PCM_STATE_SUSPENDED) { + if ((res = alsa_recover (pcm, -EPIPE)) < 0) { + Sys_Printf ("snd_alsa: suspend recovery failed: %s\n", + qfsnd_strerror (res)); + //FIXME disable/restart sound + return; + } + } + if ((avail = qfsnd_pcm_avail_update (pcm)) < 0) { + if ((res = alsa_recover (pcm, -EPIPE)) < 0) { + Sys_Printf ("snd_alsa: avail update failed: %s\n", + qfsnd_strerror (res)); + //FIXME disable/restart sound + return; + } + first = 1; + continue; + } + if (avail < snd->submission_chunk) { + if (first) { + first = 0; + if ((res = qfsnd_pcm_start (pcm)) < 0) { + Sys_Printf ("snd_alsa: start failed: %s\n", + qfsnd_strerror (res)); + return; + } + continue; + } + break; + } - snd->xfer_data = &packet; + if ((res = alsa_process (pcm, snd))) { + if (res < 0) { + //FIXME disable/restart sound + return; + } + break; + } + first = 1; + } +} - SND_PaintChannels (snd, snd_paintedtime + packet.nframes); +static int +alsa_open_playback (snd_t *snd, const char *device) +{ + if (!*device) { + device = "default"; + } + Sys_Printf ("Using PCM %s.\n", device); - qfsnd_pcm_mmap_commit (pcm, packet.offset, packet.nframes); + int res = qfsnd_pcm_open (&pcm, device, SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK); + if (res < 0) { + Sys_Printf ("snd_alsa: audio open error: %s\n", qfsnd_strerror (res)); + return 0; + } + + return 1; +} + +static int +alsa_playback_set_mmap (snd_t *snd, snd_pcm_hw_params_t *hw) +{ + int res; + + res = qfsnd_pcm_hw_params_set_access (pcm, hw, + SND_PCM_ACCESS_MMAP_INTERLEAVED); + if (res == 0) { + snd->xfer = alsa_xfer; + return 1; + } + Sys_MaskPrintf (SYS_snd, "snd_alsa: Failure to set interleaved PCM " + "access. (%d) %s\n", res, qfsnd_strerror (res)); + res = qfsnd_pcm_hw_params_set_access (pcm, hw, + SND_PCM_ACCESS_MMAP_NONINTERLEAVED); + if (res == 0) { + snd->xfer = alsa_ni_xfer; + return 1; + } + Sys_MaskPrintf (SYS_snd, "snd_alsa: Failure to set noninterleaved PCM " + "access. (%d) %s\n", res, qfsnd_strerror (res)); + Sys_Printf ("snd_alsa: could not set mmap access\n"); + + return 0; +} + +static int +alsa_playback_set_bps (snd_t *snd, snd_pcm_hw_params_t *hw) +{ + int res; + int bps = 0; + + if (snd_bits->int_val == 16) { + bps = SND_PCM_FORMAT_S16_LE; + snd->samplebits = 16; + } else if (snd_bits->int_val == 8) { + bps = SND_PCM_FORMAT_U8; + snd->samplebits = 8; + } else if (snd_bits->int_val) { + Sys_Printf ("snd_alsa: invalid sample bits: %d\n", bps); + return 0; + } + + if (bps) { + if ((res = qfsnd_pcm_hw_params_set_format (pcm, hw, bps)) == 0) { + return 1; + } + } else { + bps = SND_PCM_FORMAT_S16_LE; + if ((res = qfsnd_pcm_hw_params_set_format (pcm, hw, bps)) == 0) { + snd->samplebits = 16; + return 1; + } + bps = SND_PCM_FORMAT_U8; + if ((res = qfsnd_pcm_hw_params_set_format (pcm, hw, bps)) == 0) { + snd->samplebits = 8; + return 1; + } + Sys_Printf ("snd_alsa: no usable formats. %s\n", qfsnd_strerror (res)); + } + snd->samplebits = -1; + Sys_Printf ("snd_alsa: desired format not supported\n"); + return 0; +} + +static int +alsa_playback_set_channels (snd_t *snd, snd_pcm_hw_params_t *hw) +{ + int res; + int channels = 1; + + if (snd_stereo->int_val) { + channels = 2; + } + if ((res = qfsnd_pcm_hw_params_set_channels (pcm, hw, channels)) == 0) { + snd->channels = channels; + return 1; + } + + Sys_Printf ("snd_alsa: desired channels not supported\n"); + return 0; +} + +static int +alsa_playback_set_rate (snd_t *snd, snd_pcm_hw_params_t *hw) +{ + int res; + unsigned rate = 0; + static int default_rates[] = { 48000, 44100, 22050, 11025, 0 }; + + if (snd_rate->int_val) { + rate = snd_rate->int_val; + } + + if (rate) { + if ((res = qfsnd_pcm_hw_params_set_rate (pcm, hw, rate, 0)) == 0) { + snd->speed = rate; + return 1; + } + Sys_Printf ("snd_alsa: desired rate %i not supported. %s\n", rate, + qfsnd_strerror (res)); + } else { + // use default rate + int dir = 0; + for (int *def_rate = default_rates; *def_rate; def_rate++) { + rate = *def_rate; + res = qfsnd_pcm_hw_params_set_rate_near (pcm, hw, &rate, &dir); + if (res == 0) { + snd->speed = rate; + return 1; + } + } + Sys_Printf ("snd_alsa: no usable rate\n"); + } + + return 0; +} + +static int +alsa_playback_set_period_size (snd_t *snd, snd_pcm_hw_params_t *hw) +{ + int res; + snd_pcm_uframes_t period_size; + + // works out to about 5.5ms (5.3 for 48k, 5.8 for 44k1) but consistent for + // different sample rates give or take rounding + period_size = 64 * (snd->speed / 11025); + res = qfsnd_pcm_hw_params_set_period_size_near (pcm, hw, &period_size, 0); + if (res == 0) { + // don't mix less than this in frames: + res = qfsnd_pcm_hw_params_get_period_size (hw, &period_size, 0); + if (res == 0) { + snd->submission_chunk = period_size; + return 1; + } + Sys_Printf ("snd_alsa: unable to get period size. %s\n", + qfsnd_strerror (res)); + } else { + Sys_Printf ("snd_alsa: unable to set period size near %i. %s\n", + (int) period_size, qfsnd_strerror (res)); + } + return 0; } static int SNDDMA_Init (snd_t *snd) { - int err; - int bps = -1, stereo = -1; - unsigned int rate = 0; - snd_pcm_hw_params_t *hw; - snd_pcm_hw_params_t **_hw = &hw; - snd_pcm_sw_params_t *sw; - snd_pcm_sw_params_t **_sw = &sw; - snd_pcm_uframes_t period_size; + int res; + const char *device = snd_device->string; + + snd_pcm_hw_params_t *hw; + snd_pcm_sw_params_t *sw; if (!load_libasound ()) return false; - snd_pcm_hw_params_alloca (_hw); - snd_pcm_sw_params_alloca (_sw); + snd_pcm_hw_params_alloca (&hw); + snd_pcm_sw_params_alloca (&sw); - if (snd_device->string[0]) - pcmname = snd_device->string; - if (snd_bits->int_val) { - bps = snd_bits->int_val; - if (bps != 16 && bps != 8) { - Sys_Printf ("Error: invalid sample bits: %d\n", bps); + + while (1) { + if (!alsa_open_playback (snd, device)) { return 0; } - } - if (snd_rate->int_val) - rate = snd_rate->int_val; - stereo = snd_stereo->int_val; - if (!pcmname) - pcmname = "default"; -retry_open: - err = qfsnd_pcm_open (&pcm, pcmname, SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK); - if (0 > err) { - Sys_Printf ("Error: audio open error: %s\n", qfsnd_strerror (err)); - return 0; - } - - err = qfsnd_pcm_hw_params_any (pcm, hw); - if (0 > err) { - Sys_Printf ("ALSA: error setting hw_params_any. %s\n", - qfsnd_strerror (err)); - goto error; - } - - snd->xfer = alsa_xfer; - err = qfsnd_pcm_hw_params_set_access (pcm, hw, - SND_PCM_ACCESS_MMAP_INTERLEAVED); - if (0 > err) { - Sys_MaskPrintf (SYS_snd, "ALSA: Failure to set interleaved PCM " - "access. %s\n", qfsnd_strerror (err)); - err = qfsnd_pcm_hw_params_set_access (pcm, hw, - SND_PCM_ACCESS_MMAP_NONINTERLEAVED); - if (0 > err) { - Sys_MaskPrintf (SYS_snd, "ALSA: Failure to set noninterleaved PCM " - "access. %s\n", qfsnd_strerror (err)); - // "default" did not work, so retry with "plughw". However do not - // second guess the user, even if the user specified "default". - if (!snd_device->string[0] && !strcmp (pcmname, "default")) { - pcmname = "plughw"; - goto retry_open; - } - Sys_Printf ("ALSA: could not set mmap access\n"); + if ((res = qfsnd_pcm_hw_params_any (pcm, hw)) < 0) { + Sys_Printf ("snd_alsa: error setting hw_params_any. %s\n", + qfsnd_strerror (res)); goto error; } - snd->xfer = alsa_ni_xfer; - } - Sys_Printf ("Using PCM %s.\n", pcmname); - - - switch (bps) { - case -1: - err = qfsnd_pcm_hw_params_set_format (pcm, hw, - SND_PCM_FORMAT_S16_LE); - if (0 <= err) { - bps = 16; - } else if (0 <= (err = qfsnd_pcm_hw_params_set_format (pcm, hw, - SND_PCM_FORMAT_U8))) { - bps = 8; - } else { - Sys_Printf ("ALSA: no useable formats. %s\n", - qfsnd_strerror (err)); - goto error; - } + if (alsa_playback_set_mmap (snd, hw)) { break; - case 8: - case 16: - err = qfsnd_pcm_hw_params_set_format (pcm, hw, bps == 8 ? - SND_PCM_FORMAT_U8 : - SND_PCM_FORMAT_S16); - if (0 > err) { - Sys_Printf ("ALSA: no usable formats. %s\n", - qfsnd_strerror (err)); - goto error; - } - break; - default: - Sys_Printf ("ALSA: desired format not supported\n"); + } + if (*device) { goto error; + } + qfsnd_pcm_close (pcm); + device = "plughw"; } - switch (stereo) { - case -1: - err = qfsnd_pcm_hw_params_set_channels (pcm, hw, 2); - if (0 <= err) { - stereo = 1; - } else if (0 <= (err = qfsnd_pcm_hw_params_set_channels (pcm, hw, - 1))) { - stereo = 0; - } else { - Sys_Printf ("ALSA: no usable channels. %s\n", - qfsnd_strerror (err)); - goto error; - } - break; - case 0: - case 1: - err = qfsnd_pcm_hw_params_set_channels (pcm, hw, stereo ? 2 : 1); - if (0 > err) { - Sys_Printf ("ALSA: no usable channels. %s\n", - qfsnd_strerror (err)); - goto error; - } - break; - default: - Sys_Printf ("ALSA: desired channels not supported\n"); - goto error; - } - - switch (rate) { - case 0: - { - int rates[] = { - 48000, - 44100, - 22050, - 11025, - 0 - }; - int i; - - for (i = 0; rates[i]; i++) { - rate = rates[i]; - Sys_MaskPrintf (SYS_snd, "ALSA: trying %dHz\n", rate); - err = qfsnd_pcm_hw_params_set_rate_near (pcm, hw, - &rate, 0); - if (0 <= err) { - break; - } - } - if (!rates[i]) { - Sys_Printf ("ALSA: no usable rates. %s\n", - qfsnd_strerror (err)); - goto error; - } - } break; - case 11025: - case 22050: - case 44100: - case 48000: - default: - err = qfsnd_pcm_hw_params_set_rate_near (pcm, hw, &rate, 0); - if (0 > err) { - Sys_Printf ("ALSA: desired rate %i not supported. %s\n", rate, - qfsnd_strerror (err)); - goto error; - } - break; - } - - // works out to about 5.5ms (5.3 for 48k, 5.8 for 44k1) but consistent for - // different sample rates - period_size = 64 * (rate / 11025); - err = qfsnd_pcm_hw_params_set_period_size_near (pcm, hw, &period_size, 0); - if (0 > err) { - Sys_Printf ("ALSA: unable to set period size near %i. %s\n", - (int) period_size, qfsnd_strerror (err)); - goto error; - } - err = qfsnd_pcm_hw_params (pcm, hw); - if (0 > err) { - Sys_Printf ("ALSA: unable to install hw params: %s\n", - qfsnd_strerror (err)); - goto error; - } - err = qfsnd_pcm_sw_params_current (pcm, sw); - if (0 > err) { - Sys_Printf ("ALSA: unable to determine current sw params. %s\n", - qfsnd_strerror (err)); - goto error; - } - err = qfsnd_pcm_sw_params_set_start_threshold (pcm, sw, ~0U); - if (0 > err) { - Sys_Printf ("ALSA: unable to set playback threshold. %s\n", - qfsnd_strerror (err)); - goto error; - } - err = qfsnd_pcm_sw_params_set_stop_threshold (pcm, sw, ~0U); - if (0 > err) { - Sys_Printf ("ALSA: unable to set playback stop threshold. %s\n", - qfsnd_strerror (err)); - goto error; - } - err = qfsnd_pcm_sw_params (pcm, sw); - if (0 > err) { - Sys_Printf ("ALSA: unable to install sw params. %s\n", - qfsnd_strerror (err)); + if (!alsa_playback_set_bps (snd, hw)) { goto error; } - snd->channels = stereo + 1; - - // don't mix less than this in frames: - err = qfsnd_pcm_hw_params_get_period_size (hw, &period_size, 0); - if (0 > err) { - Sys_Printf ("ALSA: unable to get period size. %s\n", - qfsnd_strerror (err)); + if (!alsa_playback_set_channels (snd, hw)) { + goto error; + } + + if (!alsa_playback_set_rate (snd, hw)) { + goto error; + } + + if (!alsa_playback_set_period_size (snd, hw)) { + goto error; + } + + if ((res = qfsnd_pcm_hw_params (pcm, hw)) < 0) { + Sys_Printf ("snd_alsa: unable to install hw params: %s\n", + qfsnd_strerror (res)); + goto error; + } + + if ((res = qfsnd_pcm_sw_params_current (pcm, sw)) < 0) { + Sys_Printf ("snd_alsa: unable to determine current sw params. %s\n", + qfsnd_strerror (res)); + goto error; + } + if ((res = qfsnd_pcm_sw_params_set_start_threshold (pcm, sw, ~0U)) < 0) { + Sys_Printf ("snd_alsa: unable to set playback threshold. %s\n", + qfsnd_strerror (res)); + goto error; + } + if ((res = qfsnd_pcm_sw_params_set_stop_threshold (pcm, sw, ~0U)) < 0) { + Sys_Printf ("snd_alsa: unable to set playback stop threshold. %s\n", + qfsnd_strerror (res)); + goto error; + } + if ((res = qfsnd_pcm_sw_params (pcm, sw)) < 0) { + Sys_Printf ("snd_alsa: unable to install sw params. %s\n", + qfsnd_strerror (res)); goto error; } - snd->submission_chunk = period_size; snd->framepos = 0; - snd->samplebits = bps; - err = qfsnd_pcm_hw_params_get_buffer_size (hw, &buffer_size); - if (0 > err) { - Sys_Printf ("ALSA: unable to get buffer size. %s\n", - qfsnd_strerror (err)); + if ((res = qfsnd_pcm_hw_params_get_buffer_size (hw, &buffer_size)) < 0) { + Sys_Printf ("snd_alsa: unable to get buffer size. %s\n", + qfsnd_strerror (res)); goto error; } if (buffer_size != round_buffer_size (buffer_size)) { - Sys_Printf ("ALSA: WARNING: non-power of 2 buffer size. sound may be unsatisfactory\n"); + Sys_Printf ("snd_alsa: WARNING: non-power of 2 buffer size. sound may be unsatisfactory\n"); Sys_Printf ("recommend using either the plughw, or hw devices or adjusting dmix\n"); Sys_Printf ("to have a power of 2 buffer size\n"); } - qfsnd_async_add_pcm_handler (&async_haandler, pcm, alsa_callback, snd); + if ((res = qfsnd_async_add_pcm_handler (&async_handler, pcm, + alsa_callback, snd)) < 0) { + Sys_Printf ("snd_alsa: unable to register async handler: %s", + qfsnd_strerror (res)); + goto error; + } snd->frames = buffer_size; - snd->speed = rate; SNDDMA_GetDMAPos (snd); //XXX sets snd->buffer Sys_Printf ("%5d channels %sinterleaved\n", snd->channels, snd->xfer ? "non-" : ""); @@ -517,16 +644,21 @@ retry_open: snd_inited = 1; - alsa_pkt_t packet; - qfsnd_pcm_mmap_begin (pcm, &packet.areas, &packet.offset, &packet.nframes); - snd->xfer_data = &packet; - SND_PaintChannels (snd, snd_paintedtime + packet.nframes); - qfsnd_pcm_mmap_commit (pcm, packet.offset, packet.nframes); + // send the first period to fill the buffer + if (alsa_process (pcm, snd) < 0) { + goto error; + } + qfsnd_pcm_start (pcm); return 1; error: qfsnd_pcm_close (pcm); + snd->channels = 0; + snd->frames = 0; + snd->samplebits = 0; + snd->submission_chunk = 0; + snd->speed = 0; return 0; } @@ -549,8 +681,8 @@ static void SNDDMA_shutdown (snd_t *snd) { if (snd_inited) { - qfsnd_async_del_handler (async_haandler); - async_haandler = 0; + qfsnd_async_del_handler (async_handler); + async_handler = 0; qfsnd_pcm_close (pcm); snd_inited = 0; } From db7e99d8429c0d50f65d51c54e7fbc486e7141ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Jun 2021 11:41:42 +0900 Subject: [PATCH 1597/3664] [audio] Allow output plugins to specify model Output plugins can use either a push model (synchronous) or a pull model (asynchronous). The ALSA plugin now uses the pull model. This paves the way for making jack output a simple output plugin rather than the combined render/output plugin it currently is (for #16) as now snd_dma works with both models. --- include/QF/plugin/snd_output.h | 6 ++ libs/audio/renderer/snd_dma.c | 42 +++++---- libs/audio/targets/snd_alsa.c | 158 ++++++++++++--------------------- 3 files changed, 87 insertions(+), 119 deletions(-) diff --git a/include/QF/plugin/snd_output.h b/include/QF/plugin/snd_output.h index 3b8c36bf6..840647b0c 100644 --- a/include/QF/plugin/snd_output.h +++ b/include/QF/plugin/snd_output.h @@ -41,9 +41,15 @@ typedef struct snd_output_funcs_s { void (*unblock_sound) (struct snd_s *snd); } snd_output_funcs_t; +typedef enum { + som_push, // synchronous io (mixer pushes data to driver) + som_pull, // asynchronous io (driver pulls data from mixer) +} snd_output_model_t; + typedef struct snd_output_data_s { unsigned *soundtime; unsigned *paintedtime; + snd_output_model_t model; } snd_output_data_t; #endif // __QF_plugin_snd_output_h diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 6d9c731e5..5f995c5e2 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -68,6 +68,7 @@ static cvar_t *snd_show; static general_data_t plugin_info_general_data; static snd_output_funcs_t *snd_output_funcs; +static snd_output_data_t *snd_output_data; static snd_t snd; static int snd_shutdown = 0; @@ -147,17 +148,17 @@ s_stop_all_sounds (void) //============================================================================= -/*static void +static void s_get_soundtime (void) { int frames, framepos; static int buffers, oldframepos; - frames = snd_shm->frames; + frames = snd.frames; // it is possible to miscount buffers if it has wrapped twice between // calls to s_update. Oh well. - if ((framepos = snd_output_funcs->pS_O_GetDMAPos ()) == -1) + if ((framepos = snd_output_funcs->get_dma_pos (&snd)) == -1) return; if (framepos < oldframepos) { @@ -192,14 +193,14 @@ s_update_ (void) snd_paintedtime = soundtime; } // mix ahead of current position - endtime = soundtime + snd_mixahead->value * snd_shm->speed; - samps = snd_shm->frames; + endtime = soundtime + snd_mixahead->value * snd.speed; + samps = snd.frames; if (endtime - soundtime > samps) endtime = soundtime + samps; - SND_PaintChannels (endtime); - snd_output_funcs->pS_O_Submit (); -}*/ + SND_PaintChannels (&snd, endtime); + snd_output_funcs->submit (&snd); +} /* s_update @@ -215,18 +216,20 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, SND_SetListener (&snd, origin, forward, right, up, ambient_sound_level); - // mix some sound - //s_update_ (); - //SND_ScanChannels (0); + if (snd_output_data->model == som_push) { + // mix some sound + s_update_ (); + SND_ScanChannels (&snd, 0); + } } -//static void -//s_extra_update (void) -//{ -// if (!sound_started || snd_noextraupdate->int_val) -// return; // don't pollute timings -// s_update_ (); -//} +static void +s_extra_update (void) +{ + if (!sound_started || snd_noextraupdate->int_val) + return; // don't pollute timings + s_update_ (); +} static void s_block_sound (void) @@ -305,6 +308,7 @@ static void s_init (void) { snd_output_funcs = snd_render_data.output->functions->snd_output; + snd_output_data = snd_render_data.output->data->snd_output; snd_render_data.soundtime = &soundtime; Sys_Printf ("\nSound Initialization\n"); @@ -466,7 +470,7 @@ static snd_render_funcs_t plugin_info_render_funcs = { .update = s_update, .stop_all_sounds = s_stop_all_sounds, - //.extra_update = s_extra_update, + .extra_update = s_extra_update, .block_sound = s_block_sound, .unblock_sound = s_unblock_sound, }; diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 28593a5f8..f0e1c52a8 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -53,19 +53,15 @@ static void *alsa_handle; static snd_pcm_t *pcm; static snd_async_handler_t *async_handler; -static plugin_t plugin_info; -static plugin_data_t plugin_info_data; -static plugin_funcs_t plugin_info_funcs; -static general_data_t plugin_info_general_data; -static general_funcs_t plugin_info_general_funcs; -static snd_output_data_t plugin_info_snd_output_data; -static snd_output_funcs_t plugin_info_snd_output_funcs; - static cvar_t *snd_bits; static cvar_t *snd_device; static cvar_t *snd_rate; static cvar_t *snd_stereo; +//FIXME xfer probably should not be touching this (such data should probably +//come through snd_t) +static snd_output_data_t plugin_info_snd_output_data; + #define QF_ALSA_NEED(ret, func, params) \ static ret (*qf##func) params; #include "alsa_funcs_list.h" @@ -106,8 +102,6 @@ SNDDMA_Init_Cvars (void) "sound sample depth. 0 is system default"); } -static int SNDDMA_GetDMAPos (snd_t *snd); - static __attribute__((const)) snd_pcm_uframes_t round_buffer_size (snd_pcm_uframes_t sz) { @@ -203,6 +197,7 @@ alsa_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, { int out_idx, out_max, step, val; float *p; + alsa_pkt_t *packet = snd->xfer_data;; p = (float *) paintbuffer; count *= snd->channels; @@ -213,7 +208,7 @@ alsa_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, step = 3 - snd->channels; if (snd->samplebits == 16) { - short *out = (short *) snd->buffer; + short *out = (short *) packet->areas[0].addr; while (count--) { val = (*p * volume) * 0x8000; @@ -227,7 +222,7 @@ alsa_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, out_idx = 0; } } else if (snd->samplebits == 8) { - unsigned char *out = (unsigned char *) snd->buffer; + unsigned char *out = (unsigned char *) packet->areas[0].addr; while (count--) { val = (*p * volume) * 128; @@ -292,6 +287,7 @@ alsa_process (snd_pcm_t *pcm, snd_t *snd) } ret = 0; } + snd->buffer = packet.areas[0].addr; SND_PaintChannels (snd, snd_paintedtime + packet.nframes); if ((res = qfsnd_pcm_mmap_commit (pcm, packet.offset, packet.nframes)) < 0 @@ -630,7 +626,15 @@ SNDDMA_Init (snd_t *snd) } snd->frames = buffer_size; - SNDDMA_GetDMAPos (snd); //XXX sets snd->buffer + + // send the first period to fill the buffer + // also sets snd->buffer + if (alsa_process (pcm, snd) < 0) { + goto error; + } + + qfsnd_pcm_start (pcm); + Sys_Printf ("%5d channels %sinterleaved\n", snd->channels, snd->xfer ? "non-" : ""); Sys_Printf ("%5d samples (%.1fms)\n", snd->frames, @@ -644,13 +648,6 @@ SNDDMA_Init (snd_t *snd) snd_inited = 1; - // send the first period to fill the buffer - if (alsa_process (pcm, snd) < 0) { - goto error; - } - - qfsnd_pcm_start (pcm); - return 1; error: qfsnd_pcm_close (pcm); @@ -662,21 +659,6 @@ error: return 0; } -static int -SNDDMA_GetDMAPos (snd_t *snd) -{ - const snd_pcm_channel_area_t *areas; - snd_pcm_uframes_t offset; - snd_pcm_uframes_t nframes = snd->frames; - - qfsnd_pcm_avail_update (pcm); - qfsnd_pcm_mmap_begin (pcm, &areas, &offset, &nframes); - snd->framepos = offset; - snd->buffer = areas->addr; - snd->xfer_data = (void *) areas; - return snd->framepos; -} - static void SNDDMA_shutdown (snd_t *snd) { @@ -688,44 +670,6 @@ SNDDMA_shutdown (snd_t *snd) } } -/* - SNDDMA_Submit - - Send sound to device if buffer isn't really the dma buffer -*/ -static void -SNDDMA_Submit (snd_t *snd) -{ - int state; - int count = (*plugin_info_snd_output_data.paintedtime - - *plugin_info_snd_output_data.soundtime); - const snd_pcm_channel_area_t *areas; - snd_pcm_uframes_t nframes; - snd_pcm_uframes_t offset; - - if (snd_blocked) - return; - - nframes = count; - - qfsnd_pcm_avail_update (pcm); - qfsnd_pcm_mmap_begin (pcm, &areas, &offset, &nframes); - - state = qfsnd_pcm_state (pcm); - - switch (state) { - case SND_PCM_STATE_PREPARED: - qfsnd_pcm_mmap_commit (pcm, offset, nframes); - qfsnd_pcm_start (pcm); - break; - case SND_PCM_STATE_RUNNING: - qfsnd_pcm_mmap_commit (pcm, offset, nframes); - break; - default: - break; - } -} - static void SNDDMA_BlockSound (snd_t *snd) { @@ -742,35 +686,49 @@ SNDDMA_UnblockSound (snd_t *snd) qfsnd_pcm_pause (pcm, 0); } -PLUGIN_INFO(snd_output, alsa) -{ - plugin_info.type = qfp_snd_output; - plugin_info.api_version = QFPLUGIN_VERSION; - plugin_info.plugin_version = "0.1"; - plugin_info.description = "ALSA digital output"; - plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n" +static general_data_t plugin_info_general_data = { +}; + +static general_funcs_t plugin_info_general_funcs = { + .init = SNDDMA_Init_Cvars, + .shutdown = NULL, +}; + +static snd_output_data_t plugin_info_snd_output_data = { + .model = som_pull, +}; + +static snd_output_funcs_t plugin_info_snd_output_funcs = { + .init = SNDDMA_Init, + .shutdown = SNDDMA_shutdown, + .block_sound = SNDDMA_BlockSound, + .unblock_sound = SNDDMA_UnblockSound, +}; + +static plugin_data_t plugin_info_data = { + .general = &plugin_info_general_data, + .snd_output = &plugin_info_snd_output_data, +}; + +static plugin_funcs_t plugin_info_funcs = { + .general = &plugin_info_general_funcs, + .snd_output = &plugin_info_snd_output_funcs, +}; + +static plugin_t plugin_info = { + .type = qfp_snd_output, + .api_version = QFPLUGIN_VERSION, + .plugin_version = "0.1", + .description = "ALSA digital output", + .copyright = "Copyright (C) 1996-1997 id Software, Inc.\n" "Copyright (C) 1999,2000,2001 contributors of the QuakeForge " "project\n" - "Please see the file \"AUTHORS\" for a list of contributors"; - plugin_info.functions = &plugin_info_funcs; - plugin_info.data = &plugin_info_data; - - plugin_info_data.general = &plugin_info_general_data; - plugin_info_data.input = NULL; - plugin_info_data.snd_output = &plugin_info_snd_output_data; - - plugin_info_funcs.general = &plugin_info_general_funcs; - plugin_info_funcs.input = NULL; - plugin_info_funcs.snd_output = &plugin_info_snd_output_funcs; - - plugin_info_general_funcs.init = SNDDMA_Init_Cvars; - plugin_info_general_funcs.shutdown = NULL; - plugin_info_snd_output_funcs.init = SNDDMA_Init; - plugin_info_snd_output_funcs.shutdown = SNDDMA_shutdown; - plugin_info_snd_output_funcs.get_dma_pos = SNDDMA_GetDMAPos; - plugin_info_snd_output_funcs.submit = SNDDMA_Submit; - plugin_info_snd_output_funcs.block_sound = SNDDMA_BlockSound; - plugin_info_snd_output_funcs.unblock_sound = SNDDMA_UnblockSound; + "Please see the file \"AUTHORS\" for a list of contributors", + .functions = &plugin_info_funcs, + .data = &plugin_info_data, +}; +PLUGIN_INFO(snd_output, alsa) +{ return &plugin_info; } From 02ff875cd6b043e70df88ee786c41d7c5e9a13e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Jun 2021 13:52:50 +0900 Subject: [PATCH 1598/3664] [audio] Add optional on_update output function on_update is for pull-model outpput targets to do periodic synchronous checks (eg, checking that the connection to the actual output device is still alive and reviving it if necessary) --- include/QF/plugin/snd_output.h | 1 + libs/audio/renderer/snd_dma.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/include/QF/plugin/snd_output.h b/include/QF/plugin/snd_output.h index 840647b0c..d989a1571 100644 --- a/include/QF/plugin/snd_output.h +++ b/include/QF/plugin/snd_output.h @@ -37,6 +37,7 @@ typedef struct snd_output_funcs_s { void (*shutdown) (struct snd_s *snd); int (*get_dma_pos) (struct snd_s *snd); void (*submit) (struct snd_s *snd); + void (*on_update) (struct snd_s *snd); void (*block_sound) (struct snd_s *snd); void (*unblock_sound) (struct snd_s *snd); } snd_output_funcs_t; diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 5f995c5e2..390e10524 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -214,6 +214,10 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, if (!sound_started || (snd_blocked > 0)) return; + if (snd_output_funcs->on_update) { + snd_output_funcs->on_update (&snd); + } + SND_SetListener (&snd, origin, forward, right, up, ambient_sound_level); if (snd_output_data->model == som_push) { From 580464d6bea3edbb30b9259dee88207c331f57b1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Jun 2021 14:23:55 +0900 Subject: [PATCH 1599/3664] [audio] Disable extra update for pull targets This fixes a segfault that snuck in due to testsound not using S_ExgraUpdate. --- libs/audio/renderer/snd_dma.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 390e10524..e7cf2390a 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -230,9 +230,11 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, static void s_extra_update (void) { - if (!sound_started || snd_noextraupdate->int_val) - return; // don't pollute timings - s_update_ (); + if (snd_output_data->model == som_push) { + if (!sound_started || snd_noextraupdate->int_val) + return; // don't pollute timings + s_update_ (); + } } static void From a1a89bdb7e294959041853355b945e89d8a58544 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Jun 2021 16:52:09 +0900 Subject: [PATCH 1600/3664] [audio] Clean up a few minor style issues --- include/QF/plugin/snd_render.h | 2 +- include/QF/sound.h | 4 ++-- libs/audio/renderer/midi.c | 6 ++++-- libs/audio/renderer/snd_dma.c | 20 ++++++-------------- libs/audio/snd.c | 4 ++-- 5 files changed, 15 insertions(+), 21 deletions(-) diff --git a/include/QF/plugin/snd_render.h b/include/QF/plugin/snd_render.h index 4cf1ea021..0aef79d6d 100644 --- a/include/QF/plugin/snd_render.h +++ b/include/QF/plugin/snd_render.h @@ -36,7 +36,7 @@ typedef struct snd_render_funcs_s { void (*ambient_off) (void); void (*ambient_on) (void); void (*static_sound) (struct sfx_s *sfx, const vec3_t origin, float vol, float attenuation); - void (*start_sound) (int entnum, int entchannel, struct sfx_s *sfx, const vec3_t origin, float fvol, float attenuation); + void (*start_sound) (int entnum, int entchannel, struct sfx_s *sfx, const vec3_t origin, float vol, float attenuation); void (*local_sound) (const char *s); void (*stop_sound) (int entnum, int entchannel); diff --git a/include/QF/sound.h b/include/QF/sound.h index 1362d187c..06238114d 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -103,11 +103,11 @@ void S_Shutdown (void); - 4 body \param sfx sound to play \param origin 3d coords of where the sound originates - \param fvol absolute volume of the sound + \param vol absolute volume of the sound \param attenuation rate of volume dropoff vs distance */ void S_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, - float fvol, float attenuation); + float vol, float attenuation); /** Create a sound generated by the world. \param sfx sound to play diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index bdb43975d..4a2b51ab2 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -61,7 +61,8 @@ static cvar_t *wildmidi_volume; static cvar_t *wildmidi_config; static int -midi_init (snd_t *snd) { +midi_init (snd_t *snd) +{ wildmidi_volume = Cvar_Get ("wildmidi_volume", "100", CVAR_ARCHIVE, NULL, "Set the Master Volume"); wildmidi_config = Cvar_Get ("wildmidi_config", "/etc/timidity.cfg", @@ -75,7 +76,8 @@ midi_init (snd_t *snd) { } static wavinfo_t -midi_get_info (snd_t *snd, void *handle) { +midi_get_info (snd_t *snd, void *handle) +{ wavinfo_t info; struct _WM_Info *wm_info; diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index e7cf2390a..f888c2e13 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -395,12 +395,12 @@ s_static_sound (sfx_t *sfx, const vec3_t origin, float vol, static void s_start_sound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, - float fvol, float attenuation) + float vol, float attenuation) { if (!sound_started) return; if (!snd_shutdown) - SND_StartSound (&snd, entnum, entchannel, sfx, origin, fvol, + SND_StartSound (&snd, entnum, entchannel, sfx, origin, vol, attenuation); } @@ -482,21 +482,13 @@ static snd_render_funcs_t plugin_info_render_funcs = { }; static plugin_funcs_t plugin_info_funcs = { - &plugin_info_general_funcs, - 0, - 0, - 0, - 0, - &plugin_info_render_funcs, + .general = &plugin_info_general_funcs, + .snd_render = &plugin_info_render_funcs, }; static plugin_data_t plugin_info_data = { - &plugin_info_general_data, - 0, - 0, - 0, - 0, - &snd_render_data, + .general = &plugin_info_general_data, + .snd_render = &snd_render_data, }; static plugin_t plugin_info = { diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 1c6e3a6f5..5bfac7374 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -144,10 +144,10 @@ S_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, float attenuation) VISIBLE void S_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, - float fvol, float attenuation) + float vol, float attenuation) { if (snd_render_funcs) - snd_render_funcs->start_sound (entnum, entchannel, sfx, origin, fvol, + snd_render_funcs->start_sound (entnum, entchannel, sfx, origin, vol, attenuation); } From 53a7fbfe951856586f2790bff80151289069b3b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Jun 2021 18:32:48 +0900 Subject: [PATCH 1601/3664] [audio] Move jack from renderer to targets The JACK Audio Connection Kit support is now just an output target rather than a full duplicate of the renderer (in pull mode). This is what I wanted to to back when I first added jack support, but I needed to get the renderer working asynchronously without affecting any of the other outputs. Fixes #16. --- config.d/build_control.m4 | 8 +- config.d/compiling.m4 | 4 +- config.d/sound.m4 | 6 +- libs/audio/renderer/Makemodule.am | 8 +- libs/audio/targets/Makemodule.am | 16 +- libs/audio/{renderer => targets}/snd_jack.c | 213 ++++---------------- 6 files changed, 69 insertions(+), 186 deletions(-) rename libs/audio/{renderer => targets}/snd_jack.c (61%) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index c324b28aa..23fff6d90 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -394,8 +394,8 @@ if test "x$static_plugins" = xyes; then QF_PROCESS_NEED_STATIC_PLUGINS(console, [server], [libs/console], [server]) QF_PROCESS_NEED_STATIC_PLUGINS(console, [client], [libs/console], [client]) - QF_PROCESS_NEED_STATIC_PLUGINS(snd_output, [sdl mme sgi sun win dx oss alsa], [libs/audio/targets]) - QF_PROCESS_NEED_STATIC_PLUGINS(snd_render, [jack default], [libs/audio/renderer]) + QF_PROCESS_NEED_STATIC_PLUGINS(snd_output, [sdl mme sgi sun win dx oss jack alsa], [libs/audio/targets]) + QF_PROCESS_NEED_STATIC_PLUGINS(snd_render, [default], [libs/audio/renderer]) QF_PROCESS_NEED_STATIC_PLUGINS(cd, [xmms sdl sgi win linux file], [libs/audio]) AC_DEFINE(STATIC_PLUGINS, 1, [Define this if you are building static plugins]) if test -n "$SOUND_TYPES"; then @@ -408,8 +408,8 @@ else QF_PROCESS_NEED_PLUGINS(vid_render, [sw sw32 glsl gl vulkan], [libs/video/renderer]) QF_PROCESS_NEED_PLUGINS(console, [server], [libs/console], [server]) QF_PROCESS_NEED_PLUGINS(console, [client], [libs/console], [client]) - QF_PROCESS_NEED_PLUGINS(snd_output, [sdl mme sgi sun win dx oss alsa], [libs/audio/targets]) - QF_PROCESS_NEED_PLUGINS(snd_render, [jack default], [libs/audio/renderer]) + QF_PROCESS_NEED_PLUGINS(snd_output, [sdl mme sgi sun win dx oss jack alsa], [libs/audio/targets]) + QF_PROCESS_NEED_PLUGINS(snd_render, [default], [libs/audio/renderer]) QF_PROCESS_NEED_PLUGINS(cd, [xmms sdl sgi win linux file], [libs/audio]) fi diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index f4ac9c7df..34a0bc93c 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -81,10 +81,10 @@ AC_ARG_ENABLE(optimize, optimize=yes ) -QF_CC_OPTION(-Wno-psabi) +dnl QF_CC_OPTION(-Wno-psabi) dnl QF_CC_OPTION(-msse2) dnl QF_CC_OPTION(-Wno-psabi) -dnl QF_CC_OPTION(-mavx2) +QF_CC_OPTION(-mavx2) dnl fma is not used as it is the equivalent of turning on dnl -funsafe-math-optimizations dnl QF_CC_OPTION(-mfma) diff --git a/config.d/sound.m4 b/config.d/sound.m4 index c0fd6afce..a720b88a2 100644 --- a/config.d/sound.m4 +++ b/config.d/sound.m4 @@ -106,7 +106,8 @@ QF_maGiC_VALUE if test "x$HAVE_JACK" = "xyes"; then AC_DEFINE(HAVE_JACK, 1, [Define if you have libjack]) SOUND_TYPES="$SOUND_TYPES JACK" - QF_NEED(snd_render, [jack]) + QF_NEED(snd_output, [jack]) + QF_NEED(snd_render, [default]) fi else AC_CHECK_LIB(jack, jack_client_open, HAVE_JACK=yes, HAVE_JACK=no, @@ -117,7 +118,8 @@ QF_maGiC_VALUE JACK_LIBS="-ljack" AC_DEFINE(HAVE_JACK, 1, [Define if you have libjack]) SOUND_TYPES="$SOUND_TYPES JACK" - QF_NEED(snd_render, [jack]) + QF_NEED(snd_output, [jack]) + QF_NEED(snd_render, [default]) fi fi fi diff --git a/libs/audio/renderer/Makemodule.am b/libs/audio/renderer/Makemodule.am index 0ef8bda4f..a98c2214f 100644 --- a/libs/audio/renderer/Makemodule.am +++ b/libs/audio/renderer/Makemodule.am @@ -1,6 +1,6 @@ plugin_LTLIBRARIES += @snd_render_plugins@ noinst_LTLIBRARIES += @snd_render_static_plugins@ -EXTRA_LTLIBRARIES += libs/audio/renderer/snd_render_default.la libs/audio/renderer/snd_render_jack.la +EXTRA_LTLIBRARIES += libs/audio/renderer/snd_render_default.la flac_src=libs/audio/renderer/flac.c midi_src=libs/audio/renderer/midi.c @@ -38,9 +38,3 @@ libs_audio_renderer_snd_render_default_la_SOURCES= libs/audio/renderer/snd_dma. libs_audio_renderer_snd_render_default_la_LIBADD= $(snd_libs) $(format_libs) libs_audio_renderer_snd_render_default_la_DEPENDENCIES= $(snd_libs) EXTRA_libs_audio_renderer_snd_render_default_la_SOURCES=$(extra_format_src) - -libs_audio_renderer_snd_render_jack_la_LDFLAGS= $(plugin_ldflags) -libs_audio_renderer_snd_render_jack_la_SOURCES= libs/audio/renderer/snd_jack.c $(snd_common) $(format_src) -libs_audio_renderer_snd_render_jack_la_LIBADD= $(snd_libs) $(format_libs) $(JACK_LIBS) -libs_audio_renderer_snd_render_jack_la_DEPENDENCIES= $(snd_libs) -EXTRA_libs_audio_renderer_snd_render_jack_la_SOURCES= $(extra_format_src) diff --git a/libs/audio/targets/Makemodule.am b/libs/audio/targets/Makemodule.am index dfc566f2a..9b05e055b 100644 --- a/libs/audio/targets/Makemodule.am +++ b/libs/audio/targets/Makemodule.am @@ -1,8 +1,15 @@ plugin_LTLIBRARIES += @snd_output_plugins@ noinst_LTLIBRARIES += @snd_output_static_plugins@ EXTRA_LTLIBRARIES += \ - libs/audio/targets/snd_output_sdl.la libs/audio/targets/snd_output_alsa.la libs/audio/targets/snd_output_oss.la libs/audio/targets/snd_output_sgi.la \ - libs/audio/targets/snd_output_sun.la libs/audio/targets/snd_output_win.la libs/audio/targets/snd_output_dx.la libs/audio/targets/snd_output_disk.la + libs/audio/targets/snd_output_sdl.la \ + libs/audio/targets/snd_output_alsa.la \ + libs/audio/targets/snd_output_jack.la \ + libs/audio/targets/snd_output_oss.la \ + libs/audio/targets/snd_output_sgi.la \ + libs/audio/targets/snd_output_sun.la \ + libs/audio/targets/snd_output_win.la \ + libs/audio/targets/snd_output_dx.la \ + libs/audio/targets/snd_output_disk.la snd_deps=libs/util/libQFutil.la @@ -18,6 +25,11 @@ libs_audio_targets_snd_output_alsa_la_DEPENDENCIES=$(snd_deps) libs_audio_targets_snd_output_alsa_la_CFLAGS= $(ALSA_CFLAGS) libs_audio_targets_snd_output_alsa_la_SOURCES= libs/audio/targets/snd_alsa.c +libs_audio_targets_snd_output_jack_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_jack_la_SOURCES= libs/audio/targets/snd_jack.c $(snd_common) $(format_src) +libs_audio_targets_snd_output_jack_la_LIBADD= $(snd_libs) $(format_libs) $(JACK_LIBS) +libs_audio_targets_snd_output_jack_la_DEPENDENCIES= $(snd_libs) + libs_audio_targets_snd_output_oss_la_LDFLAGS= $(plugin_ldflags) libs_audio_targets_snd_output_oss_la_LIBADD= $(snd_deps) $(OSS_LIBS) libs_audio_targets_snd_output_oss_la_DEPENDENCIES= $(snd_deps) diff --git a/libs/audio/renderer/snd_jack.c b/libs/audio/targets/snd_jack.c similarity index 61% rename from libs/audio/renderer/snd_jack.c rename to libs/audio/targets/snd_jack.c index 5b35834a1..0d9f282c9 100644 --- a/libs/audio/renderer/snd_jack.c +++ b/libs/audio/targets/snd_jack.c @@ -1,9 +1,9 @@ /* snd_jack.c - JACK version of the renderer + JACK output driver - Copyright (C) 2007 Bill Currie + Copyright (C) 2007-2021 Bill Currie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -54,31 +54,10 @@ static int snd_alive = 0; static double snd_alive_time = 0; static jack_client_t *jack_handle; static jack_port_t *jack_out[2]; -static snd_t snd; static float *output[2]; static cvar_t *snd_jack_server; -static void s_jack_connect (void); - -static void -s_stop_all_sounds (void) -{ - if (!sound_started) - return; - SND_StopAllSounds (&snd); - SND_ScanChannels (&snd, 1); -} - -static void -s_start_sound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, - float fvol, float attenuation) -{ - if (!sound_started) - return; - if (!snd_shutdown) - SND_StartSound (&snd, entnum, entchannel, sfx, origin, fvol, - attenuation); -} +static int s_jack_connect (snd_t *snd); static void s_finish_channels (void) @@ -93,8 +72,7 @@ s_finish_channels (void) } static void -s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, - const vec3_t up, const byte *ambient_sound_level) +s_update (snd_t *snd) { double now = Sys_DoubleTime (); @@ -116,21 +94,11 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, if (snd_shutdown == 1) { snd_shutdown++; Sys_Printf ("Lost connection to jackd\n"); - s_jack_connect (); + s_jack_connect (snd); } if (snd_shutdown) return; } - SND_SetListener (&snd, origin, forward, right, up, ambient_sound_level); -} - -static void -s_local_sound (const char *sound) -{ - if (!sound_started) - return; - if (!snd_shutdown) - SND_LocalSound (&snd, sound); } static void @@ -156,7 +124,7 @@ s_jack_activate (void) } static void -s_block_sound (void) +s_block_sound (snd_t *t) { if (!sound_started) return; @@ -166,7 +134,7 @@ s_block_sound (void) } static void -s_unblock_sound (void) +s_unblock_sound (snd_t *t) { if (!sound_started) return; @@ -179,82 +147,6 @@ s_unblock_sound (void) } } -static channel_t * -s_alloc_channel (void) -{ - if (!sound_started) - return 0; - if (!snd_shutdown) - return SND_AllocChannel (&snd); - return 0; -} - -static void -s_snd_force_unblock (void) -{ - if (!sound_started) - return; - snd_blocked = 1; - s_unblock_sound (); -} - -static void -s_ambient_off (void) -{ - if (!sound_started) - return; - SND_AmbientOff (&snd); -} - -static void -s_ambient_on (void) -{ - if (!sound_started) - return; - SND_AmbientOn (&snd); -} - -static void -s_static_sound (sfx_t *sfx, const vec3_t origin, float vol, - float attenuation) -{ - if (!sound_started) - return; - SND_StaticSound (&snd, sfx, origin, vol, attenuation); -} - -static void -s_stop_sound (int entnum, int entchannel) -{ - if (!sound_started) - return; - SND_StopSound (&snd, entnum, entchannel); -} - -static sfx_t * -s_precache_sound (const char *name) -{ - if (!sound_started) - return 0; - return SND_PrecacheSound (&snd, name); -} - -static sfx_t * -s_load_sound (const char *name) -{ - if (!sound_started) - return 0; - return SND_LoadSound (&snd, name); -} - -static void -s_channel_stop (channel_t *chan) -{ - if (!sound_started) - return; - SND_ChannelStop (&snd, chan); -} - static void snd_jack_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, float volume) @@ -278,12 +170,13 @@ snd_jack_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, static int snd_jack_process (jack_nframes_t nframes, void *arg) { + snd_t *snd = arg; int i; snd_alive = 1; for (i = 0; i < 2; i++) output[i] = (float *) jack_port_get_buffer (jack_out[i], nframes); - SND_PaintChannels (&snd, snd_paintedtime + nframes); + SND_PaintChannels (snd, snd_paintedtime + nframes); return 0; } @@ -309,8 +202,8 @@ snd_jack_xrun (void *arg) return 0; } -static void -s_jack_connect (void) +static int +s_jack_connect (snd_t *snd) { int i; @@ -319,43 +212,32 @@ s_jack_connect (void) JackServerName | JackNoStartServer, 0, snd_jack_server->string)) == 0) { Sys_Printf ("Could not connect to JACK\n"); - return; + return 0; } if (jack_set_xrun_callback (jack_handle, snd_jack_xrun, 0)) Sys_Printf ("Could not set xrun callback\n"); - jack_set_process_callback (jack_handle, snd_jack_process, 0); + jack_set_process_callback (jack_handle, snd_jack_process, snd); jack_on_shutdown (jack_handle, snd_jack_shutdown, 0); for (i = 0; i < 2; i++) jack_out[i] = jack_port_register (jack_handle, va (0, "out_%d", i + 1), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - snd.speed = jack_get_sample_rate (jack_handle); + snd->speed = jack_get_sample_rate (jack_handle); s_jack_activate (); sound_started = 1; - Sys_Printf ("Connected to JACK: %d Sps\n", snd.speed); + Sys_Printf ("Connected to JACK: %d Sps\n", snd->speed); + return 1; } -static void -s_init (void) +static int +s_init (snd_t *snd) { - snd.xfer = snd_jack_xfer; - - Cmd_AddCommand ("snd_force_unblock", s_snd_force_unblock, - "fix permanently blocked sound"); - - snd_volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL, - "Set the volume for sound playback"); - snd_jack_server = Cvar_Get ("snd_jack_server", "default", CVAR_ROM, NULL, - "The name of the JACK server to connect to"); - - SND_SFX_Init (&snd); - SND_Channels_Init (&snd); - - s_jack_connect (); + snd->xfer = snd_jack_xfer; + return s_jack_connect (snd); } static void -s_shutdown (void) +s_shutdown (snd_t *snd) { int i; if (jack_handle) { @@ -368,62 +250,55 @@ s_shutdown (void) } } +static void +s_init_cvars (void) +{ + snd_jack_server = Cvar_Get ("snd_jack_server", "default", CVAR_ROM, NULL, + "The name of the JACK server to connect to"); +} + static general_funcs_t plugin_info_general_funcs = { - s_init, - s_shutdown, + .init = s_init_cvars, }; -static snd_render_funcs_t plugin_info_render_funcs = { - .ambient_off = s_ambient_off, - .ambient_on = s_ambient_on, - .static_sound = s_static_sound, - .start_sound = s_start_sound, - .stop_sound = s_stop_sound, - .precache_sound = s_precache_sound, - .update = s_update, - .stop_all_sounds = s_stop_all_sounds, - .local_sound = s_local_sound, +static snd_output_funcs_t plugin_info_output_funcs = { + .init = s_init, + .shutdown = s_shutdown, + .on_update = s_update, .block_sound = s_block_sound, .unblock_sound = s_unblock_sound, - .load_sound = s_load_sound, - .alloc_channel = s_alloc_channel, - .channel_stop = s_channel_stop, +}; + +static snd_output_data_t plugin_info_output_data = { + .model = som_pull, }; static general_data_t plugin_info_general_data; static plugin_funcs_t plugin_info_funcs = { - &plugin_info_general_funcs, - 0, - 0, - 0, - 0, - &plugin_info_render_funcs, + .general = &plugin_info_general_funcs, + .snd_output = &plugin_info_output_funcs, }; static plugin_data_t plugin_info_data = { - &plugin_info_general_data, - 0, - 0, - 0, - 0, - &snd_render_data, + .general = &plugin_info_general_data, + .snd_output = &plugin_info_output_data, }; static plugin_t plugin_info = { - qfp_snd_render, + qfp_snd_output, 0, QFPLUGIN_VERSION, "0.1", "Sound Renderer", - "Copyright (C) 2007 contributors of the QuakeForge " + "Copyright (C) 2007-2021 contributors of the QuakeForge " "project\n" "Please see the file \"AUTHORS\" for a list of contributors", &plugin_info_funcs, &plugin_info_data, }; -PLUGIN_INFO(snd_render, jack) +PLUGIN_INFO(snd_output, jack) { return &plugin_info; } From a66e6ad26271d52cdf217441d21ec25a8f40f5e0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Jun 2021 14:25:02 +0900 Subject: [PATCH 1602/3664] [sudio] Fix the SDL audio target I forgot about SDL in my testing for #16. I do still need to fix the windows targets. --- libs/audio/targets/snd_sdl.c | 65 ++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/libs/audio/targets/snd_sdl.c b/libs/audio/targets/snd_sdl.c index 5e8dfc409..c9ab69060 100644 --- a/libs/audio/targets/snd_sdl.c +++ b/libs/audio/targets/snd_sdl.c @@ -46,7 +46,6 @@ #include "snd_internal.h" -static dma_t sn; static int snd_inited; static int snd_blocked; @@ -95,13 +94,13 @@ SNDDMA_Init_Cvars (void) "sound sample depth. 0 is system default"); } -static volatile dma_t * -SNDDMA_Init (void) +static int +SNDDMA_Init (snd_t *snd) { SDL_AudioSpec desired, obtained; if (snd_inited) - return &sn; + return 1; if (SDL_Init (SDL_INIT_AUDIO) < 0) { Sys_Printf ("Couldn't initialize SDL AUDIO: %s\n", SDL_GetError ()); @@ -165,17 +164,17 @@ SNDDMA_Init (void) } /* Fill the audio DMA information block */ - sn.samplebits = (obtained.format & 0xFF); - sn.speed = obtained.freq; - sn.channels = obtained.channels; - sn.frames = obtained.samples * 8; // 8 chunks in the buffer - sn.framepos = 0; - sn.submission_chunk = 1; + snd->samplebits = (obtained.format & 0xFF); + snd->speed = obtained.freq; + snd->channels = obtained.channels; + snd->frames = obtained.samples * 8; // 8 chunks in the buffer + snd->framepos = 0; + snd->submission_chunk = 1; - shm_buflen = sn.frames * sn.channels * (sn.samplebits / 8); + shm_buflen = snd->frames * snd->channels * (snd->samplebits / 8); - sn.buffer = calloc (shm_buflen, 1); - if (!sn.buffer) + snd->buffer = calloc (shm_buflen, 1); + if (!snd->buffer) Sys_Error ("Failed to allocate buffer for sound!"); shm_buf = calloc (shm_buflen, 1); @@ -189,28 +188,28 @@ SNDDMA_Init (void) snd_inited = 1; - return &sn; + return 1; } static int -SNDDMA_GetDMAPos (void) +SNDDMA_GetDMAPos (snd_t *snd) { if (!snd_inited) return 0; SDL_LockAudio (); - sn.framepos = shm_rpos / (sn.channels * (sn.samplebits / 8)); + snd->framepos = shm_rpos / (snd->channels * (snd->samplebits / 8)); SDL_UnlockAudio (); - return sn.framepos; + return snd->framepos; } static void -SNDDMA_shutdown (void) +SNDDMA_shutdown (snd_t *snd) { if (snd_inited) { SDL_CloseAudio (); - free (sn.buffer); + free (snd->buffer); free (shm_buf); snd_inited = 0; } @@ -222,7 +221,7 @@ SNDDMA_shutdown (void) Send sound to device if buffer isn't really the dma buffer */ static void -SNDDMA_Submit (void) +SNDDMA_Submit (snd_t *snd) { static unsigned old_paintedtime; unsigned len; @@ -236,17 +235,17 @@ SNDDMA_Submit (void) old_paintedtime = 0; len = (*plugin_info_snd_output_data.paintedtime - old_paintedtime) * - sn.channels * (sn.samplebits / 8); + snd->channels * (snd->samplebits / 8); old_paintedtime = *plugin_info_snd_output_data.paintedtime; while (wpos + len > shm_buflen) { - memcpy (shm_buf + wpos, sn.buffer + wpos, shm_buflen - wpos); + memcpy (shm_buf + wpos, snd->buffer + wpos, shm_buflen - wpos); len -= shm_buflen - wpos; wpos = 0; } if (len) { - memcpy (shm_buf + wpos, sn.buffer + wpos, len); + memcpy (shm_buf + wpos, snd->buffer + wpos, len); wpos += len; } @@ -254,7 +253,7 @@ SNDDMA_Submit (void) } static void -SNDDMA_BlockSound (void) +SNDDMA_BlockSound (snd_t *snd) { if (!snd_inited) return; @@ -264,7 +263,7 @@ SNDDMA_BlockSound (void) } static void -SNDDMA_UnblockSound (void) +SNDDMA_UnblockSound (snd_t *snd) { if (!snd_inited || !snd_blocked) return; @@ -294,14 +293,14 @@ PLUGIN_INFO(snd_output, sdl) plugin_info_funcs.input = NULL; plugin_info_funcs.snd_output = &plugin_info_snd_output_funcs; - plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; - plugin_info_general_funcs.p_Shutdown = NULL; - plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; - plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; - plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; - plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; - plugin_info_snd_output_funcs.pS_O_UnblockSound = SNDDMA_UnblockSound; + plugin_info_general_funcs.init = SNDDMA_Init_Cvars; + plugin_info_general_funcs.shutdown = NULL; + plugin_info_snd_output_funcs.init = SNDDMA_Init; + plugin_info_snd_output_funcs.shutdown = SNDDMA_shutdown; + plugin_info_snd_output_funcs.get_dma_pos = SNDDMA_GetDMAPos; + plugin_info_snd_output_funcs.submit = SNDDMA_Submit; + plugin_info_snd_output_funcs.block_sound = SNDDMA_BlockSound; + plugin_info_snd_output_funcs.unblock_sound = SNDDMA_UnblockSound; return &plugin_info; } From 0be609e0fd28c6040194cdd7b477503df2a6a3b1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Jun 2021 15:43:17 +0900 Subject: [PATCH 1603/3664] [util] Make PI_LoadPlugin always call general init function As the root cause for #16 was something else, this fixes only the basic cvar initialization, but does fix #19 (for now, at least). --- include/QF/plugin/cd.h | 1 + include/QF/plugin/console.h | 1 + include/QF/plugin/snd_render.h | 1 + include/QF/plugin/vid_render.h | 1 + libs/audio/cd.c | 1 - libs/audio/cd_file.c | 1 + libs/audio/cd_linux.c | 1 + libs/audio/cd_sdl.c | 1 + libs/audio/cd_sgi.c | 1 + libs/audio/cd_win.c | 1 + libs/audio/cd_xmms.c | 1 + libs/audio/renderer/snd_dma.c | 34 +++-- libs/audio/snd.c | 3 +- libs/console/client.c | 28 ++-- libs/console/console.c | 1 - libs/console/server.c | 28 ++-- libs/util/plugin.c | 18 +-- libs/video/renderer/r_init.c | 2 +- libs/video/renderer/vid_render_gl.c | 92 ++++++------- libs/video/renderer/vid_render_glsl.c | 90 ++++++------ libs/video/renderer/vid_render_sw.c | 88 ++++++------ libs/video/renderer/vid_render_sw32.c | 88 ++++++------ libs/video/renderer/vid_render_vulkan.c | 174 +++++++++++------------- 23 files changed, 306 insertions(+), 351 deletions(-) diff --git a/include/QF/plugin/cd.h b/include/QF/plugin/cd.h index 94e7f8c10..2eb0aa417 100644 --- a/include/QF/plugin/cd.h +++ b/include/QF/plugin/cd.h @@ -31,6 +31,7 @@ #include typedef struct cd_funcs_s { + void (*init) (void); void (*cd_f) (void); // void (*pause) (void); void (*play) (int, qboolean); diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index a1a61b8fa..7ea0af938 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -35,6 +35,7 @@ #include typedef struct console_funcs_s { + void (*init) (void); void (*print) (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); void (*process_input) (void); void (*key_event) (knum_t key, short unicode, qboolean down); diff --git a/include/QF/plugin/snd_render.h b/include/QF/plugin/snd_render.h index 0aef79d6d..d4add32aa 100644 --- a/include/QF/plugin/snd_render.h +++ b/include/QF/plugin/snd_render.h @@ -33,6 +33,7 @@ struct sfx_s; typedef struct snd_render_funcs_s { + void (*init) (void); void (*ambient_off) (void); void (*ambient_on) (void); void (*static_sound) (struct sfx_s *sfx, const vec3_t origin, float vol, float attenuation); diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 7256b54d7..2fd30ae18 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -112,6 +112,7 @@ typedef struct vid_model_funcs_s { } vid_model_funcs_t; typedef struct vid_render_funcs_s { + void (*init) (void); void (*Draw_Character) (int x, int y, unsigned ch); void (*Draw_String) (int x, int y, const char *str); void (*Draw_nString) (int x, int y, const char *str, int count); diff --git a/libs/audio/cd.c b/libs/audio/cd.c index ebc1777d3..0faee5a13 100644 --- a/libs/audio/cd.c +++ b/libs/audio/cd.c @@ -111,7 +111,6 @@ CDAudio_Init (void) Sys_Printf ("Loading of cd module: %s failed!\n", cd_plugin->string); return -1; } - cdmodule->functions->general->init (); Cmd_AddCommand ( "cd", CD_f, "Control the CD player.\n" "Commands:\n" diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index 0e26a803a..126dabd1e 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -477,6 +477,7 @@ static general_funcs_t plugin_info_general_funcs = { }; static cd_funcs_t plugin_info_cd_funcs = { + 0, I_OGG_f, I_OGGMus_Pause, I_OGGMus_Play, diff --git a/libs/audio/cd_linux.c b/libs/audio/cd_linux.c index 1bf52e4e1..53bc7f450 100644 --- a/libs/audio/cd_linux.c +++ b/libs/audio/cd_linux.c @@ -455,6 +455,7 @@ static general_funcs_t plugin_info_general_funcs = { }; static cd_funcs_t plugin_info_cd_funcs = { + 0, I_CD_f, I_CDAudio_Pause, I_CDAudio_Play, diff --git a/libs/audio/cd_sdl.c b/libs/audio/cd_sdl.c index 95f8d1b9b..fb3b9b502 100644 --- a/libs/audio/cd_sdl.c +++ b/libs/audio/cd_sdl.c @@ -288,6 +288,7 @@ static general_funcs_t plugin_info_general_funcs = { }; static cd_funcs_t plugin_info_cd_funcs = { + 0, I_CD_f, I_CDAudio_Pause, I_CDAudio_Play, diff --git a/libs/audio/cd_sgi.c b/libs/audio/cd_sgi.c index 84858d092..2f235d86b 100644 --- a/libs/audio/cd_sgi.c +++ b/libs/audio/cd_sgi.c @@ -364,6 +364,7 @@ static general_funcs_t plugin_info_general_funcs = { }; static cd_funcs_t plugin_info_cd_funcs = { + 0, I_SGI_f, I_SGI_Pause, I_SGI_Play, diff --git a/libs/audio/cd_win.c b/libs/audio/cd_win.c index 26752a503..919908a79 100644 --- a/libs/audio/cd_win.c +++ b/libs/audio/cd_win.c @@ -499,6 +499,7 @@ static general_funcs_t plugin_info_general_funcs = { }; static cd_funcs_t plugin_info_cd_funcs = { + 0, I_CD_f, I_CDAudio_Pause, I_CDAudio_Play, diff --git a/libs/audio/cd_xmms.c b/libs/audio/cd_xmms.c index de4fe0bae..b26fc1d86 100644 --- a/libs/audio/cd_xmms.c +++ b/libs/audio/cd_xmms.c @@ -489,6 +489,7 @@ static general_funcs_t plugin_info_general_funcs = { }; static cd_funcs_t plugin_info_cd_funcs = { + 0, I_XMMS_f, I_XMMS_Pause, I_XMMS_Play, diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index f888c2e13..35df3fc69 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -310,6 +310,23 @@ s_snd_force_unblock (void) s_unblock_sound (); } +static void +s_init_cvars (void) +{ + nosound = Cvar_Get ("nosound", "0", CVAR_NONE, NULL, + "Set to turn sound off"); + snd_volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL, + "Set the volume for sound playback"); + snd_mixahead = Cvar_Get ("snd_mixahead", "0.1", CVAR_ARCHIVE, NULL, + "Delay time for sounds"); + snd_noextraupdate = Cvar_Get ("snd_noextraupdate", "0", CVAR_NONE, NULL, + "Toggles the correct value display in " + "host_speeds. Usually messes up sound " + "playback when in effect"); + snd_show = Cvar_Get ("snd_show", "0", CVAR_NONE, NULL, + "Toggles display of sounds currently being played"); +} + static void s_init (void) { @@ -325,18 +342,6 @@ s_init (void) Cmd_AddCommand ("snd_force_unblock", s_snd_force_unblock, "fix permanently blocked sound"); - nosound = Cvar_Get ("nosound", "0", CVAR_NONE, NULL, - "Set to turn sound off"); - snd_volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL, - "Set the volume for sound playback"); - snd_mixahead = Cvar_Get ("snd_mixahead", "0.1", CVAR_ARCHIVE, NULL, - "Delay time for sounds"); - snd_noextraupdate = Cvar_Get ("snd_noextraupdate", "0", CVAR_NONE, NULL, - "Toggles the correct value display in " - "host_speeds. Usually messes up sound " - "playback when in effect"); - snd_show = Cvar_Get ("snd_show", "0", CVAR_NONE, NULL, - "Toggles display of sounds currently being played"); // FIXME // if (host_parms.memsize < 0x800000) { // Cvar_Set (snd_loadas8bit, "1"); @@ -456,11 +461,12 @@ s_alloc_channel (void) } static general_funcs_t plugin_info_general_funcs = { - s_init, - s_shutdown, + .init = s_init_cvars, + .shutdown = s_shutdown, }; static snd_render_funcs_t plugin_info_render_funcs = { + .init = s_init, .ambient_off = s_ambient_off, .ambient_on = s_ambient_on, .static_sound = s_static_sound, diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 5bfac7374..5b7c4c082 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -99,8 +99,7 @@ S_Init (int *viewentity, double *host_frametime) host_frametime; snd_render_module->data->snd_render->output = snd_output_module; - snd_output_module->functions->general->init (); - snd_render_module->functions->general->init (); + snd_render_module->functions->snd_render->init (); snd_output_module->data->snd_output->soundtime = snd_render_module->data->snd_render->soundtime; diff --git a/libs/console/client.c b/libs/console/client.c index 43bbcf8f2..f87180a82 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -939,31 +939,27 @@ C_shutdown (void) } static general_funcs_t plugin_info_general_funcs = { - C_Init, - C_shutdown, + .init = C_Init, + .shutdown = C_shutdown, }; static console_funcs_t plugin_info_console_funcs = { - C_Print, - C_ProcessInput, - C_KeyEvent, - C_DrawConsole, - C_CheckResize, - C_NewMap, + .print = C_Print, + .process_input = C_ProcessInput, + .key_event = C_KeyEvent, + .draw_console = C_DrawConsole, + .check_resize = C_CheckResize, + .new_map = C_NewMap, }; static plugin_funcs_t plugin_info_funcs = { - &plugin_info_general_funcs, - 0, - 0, - &plugin_info_console_funcs, + .general = &plugin_info_general_funcs, + .console = &plugin_info_console_funcs, }; static plugin_data_t plugin_info_data = { - &plugin_info_general_data, - 0, - 0, - &con_data, + .general = &plugin_info_general_data, + .console = &con_data, }; static plugin_t plugin_info = { diff --git a/libs/console/console.c b/libs/console/console.c index 0484bae1b..4fd314b3f 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -102,7 +102,6 @@ Con_Init (const char *plugin_name) con_module = PI_LoadPlugin ("console", plugin_name); if (con_module) { - con_module->functions->general->init (); Sys_SetStdPrintf (con_module->functions->console->print); } else { setvbuf (stdout, 0, _IOLBF, BUFSIZ); diff --git a/libs/console/server.c b/libs/console/server.c index fff7bcdb7..6bbae8a6a 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -785,32 +785,28 @@ C_NewMap (void) } static general_funcs_t plugin_info_general_funcs = { - C_Init, - C_shutdown, + .init = C_Init, + .shutdown = C_shutdown, }; static general_data_t plugin_info_general_data; static console_funcs_t plugin_info_console_funcs = { - C_Print, - C_ProcessInput, - C_KeyEvent, - C_DrawConsole, - C_CheckResize, - C_NewMap, + .print = C_Print, + .process_input = C_ProcessInput, + .key_event = C_KeyEvent, + .draw_console = C_DrawConsole, + .check_resize = C_CheckResize, + .new_map = C_NewMap, }; static plugin_funcs_t plugin_info_funcs = { - &plugin_info_general_funcs, - 0, - 0, - &plugin_info_console_funcs, + .general = &plugin_info_general_funcs, + .console = &plugin_info_console_funcs, }; static plugin_data_t plugin_info_data = { - &plugin_info_general_data, - 0, - 0, - &sv_con_data, + .general = &plugin_info_general_data, + .console = &sv_con_data, }; static plugin_t plugin_info = { diff --git a/libs/util/plugin.c b/libs/util/plugin.c index 6ce0d9049..53ca4012e 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -197,12 +197,9 @@ PI_Plugin_Load_f (void) name = Cmd_Argv(2); pi = PI_LoadPlugin (type, name); - if (!pi) + if (!pi) { Sys_Printf ("Error loading plugin %s %s\n", type, name); - - else if (pi->functions && pi->functions->general && - pi->functions->general->init) - pi->functions->general->init (); + } } static void @@ -379,16 +376,19 @@ PI_LoadPlugin (const char *type, const char *name) plugin->full_name = lp->name; plugin->handle = dlhand; + + if (plugin->functions && plugin->functions->general + && plugin->functions->general->init) { + plugin->functions->general->init (); + } return plugin; } VISIBLE qboolean PI_UnloadPlugin (plugin_t *plugin) { - if (plugin - && plugin->functions - && plugin->functions->general - && plugin->functions->general->shutdown) { + if (plugin && plugin->functions && plugin->functions->general + && plugin->functions->general->shutdown) { plugin->functions->general->shutdown (); } else { Sys_MaskPrintf (SYS_dev, diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 25a36e6df..5c39ba165 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -89,7 +89,7 @@ R_LoadModule (vid_internal_t *vid_internal) r_data = vidrendmodule->data->vid_render; r_data->vid->vid_internal = vid_internal; - vidrendmodule->functions->general->init (); + r_funcs->init (); Sys_RegisterShutdown (R_shutdown, 0); } diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index c74010b99..59549d830 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -45,6 +45,18 @@ gl_ctx_t *gl_ctx; +static void +gl_vid_render_choose_visual (void) +{ + gl_ctx->choose_visual (gl_ctx); +} + +static void +gl_vid_render_create_context (void) +{ + gl_ctx->create_context (gl_ctx); +} + static vid_model_funcs_t model_funcs = { sizeof (gltex_t), gl_Mod_LoadLighting, @@ -71,7 +83,31 @@ static vid_model_funcs_t model_funcs = { gl_Skin_InitTranslations, }; +static void +gl_vid_render_init (void) +{ + if (!vr_data.vid->vid_internal->sw_context) { + Sys_Error ("Sorry, OpenGL not supported by this program."); + } + gl_ctx = vr_data.vid->vid_internal->gl_context (); + gl_ctx->init_gl = GL_Init_Common; + gl_ctx->load_gl (); + + vr_data.vid->vid_internal->set_palette = GL_SetPalette; + vr_data.vid->vid_internal->choose_visual = gl_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = gl_vid_render_create_context; + + vr_funcs = &gl_vid_render_funcs; + m_funcs = &model_funcs; +} + +static void +gl_vid_render_shutdown (void) +{ +} + vid_render_funcs_t gl_vid_render_funcs = { + gl_vid_render_init, gl_Draw_Character, gl_Draw_String, gl_Draw_nString, @@ -128,66 +164,20 @@ vid_render_funcs_t gl_vid_render_funcs = { &model_funcs }; -static void -gl_vid_render_choose_visual (void) -{ - gl_ctx->choose_visual (gl_ctx); -} - -static void -gl_vid_render_create_context (void) -{ - gl_ctx->create_context (gl_ctx); -} - -static void -gl_vid_render_init (void) -{ - if (!vr_data.vid->vid_internal->sw_context) { - Sys_Error ("Sorry, OpenGL not supported by this program."); - } - gl_ctx = vr_data.vid->vid_internal->gl_context (); - gl_ctx->init_gl = GL_Init_Common; - gl_ctx->load_gl (); - - vr_data.vid->vid_internal->set_palette = GL_SetPalette; - vr_data.vid->vid_internal->choose_visual = gl_vid_render_choose_visual; - vr_data.vid->vid_internal->create_context = gl_vid_render_create_context; - - vr_funcs = &gl_vid_render_funcs; - m_funcs = &model_funcs; -} - -static void -gl_vid_render_shutdown (void) -{ -} - static general_funcs_t plugin_info_general_funcs = { - gl_vid_render_init, - gl_vid_render_shutdown, + .shutdown = gl_vid_render_shutdown, }; static general_data_t plugin_info_general_data; static plugin_funcs_t plugin_info_funcs = { - &plugin_info_general_funcs, - 0, - 0, - 0, - 0, - 0, - &gl_vid_render_funcs, + .general = &plugin_info_general_funcs, + .vid_render = &gl_vid_render_funcs, }; static plugin_data_t plugin_info_data = { - &plugin_info_general_data, - 0, - 0, - 0, - 0, - 0, - &vid_render_data, + .general = &plugin_info_general_data, + .vid_render = &vid_render_data, }; static plugin_t plugin_info = { diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index b1e828f11..d522d48a4 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -45,6 +45,18 @@ gl_ctx_t *glsl_ctx; +static void +glsl_vid_render_choose_visual (void) +{ + glsl_ctx->choose_visual (glsl_ctx); +} + +static void +glsl_vid_render_create_context (void) +{ + glsl_ctx->create_context (glsl_ctx); +} + static vid_model_funcs_t model_funcs = { sizeof (glsltex_t), glsl_Mod_LoadLighting, @@ -71,7 +83,30 @@ static vid_model_funcs_t model_funcs = { glsl_Skin_InitTranslations, }; +static void +glsl_vid_render_init (void) +{ + if (!vr_data.vid->vid_internal->sw_context) { + Sys_Error ("Sorry, OpenGL (GLSL) not supported by this program."); + } + glsl_ctx = vr_data.vid->vid_internal->gl_context (); + glsl_ctx->init_gl = GLSL_Init_Common; + glsl_ctx->load_gl (); + + vr_data.vid->vid_internal->set_palette = GLSL_SetPalette; + vr_data.vid->vid_internal->choose_visual = glsl_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = glsl_vid_render_create_context; + vr_funcs = &glsl_vid_render_funcs; + m_funcs = &model_funcs; +} + +static void +glsl_vid_render_shutdown (void) +{ +} + vid_render_funcs_t glsl_vid_render_funcs = { + glsl_vid_render_init, glsl_Draw_Character, glsl_Draw_String, glsl_Draw_nString, @@ -128,65 +163,20 @@ vid_render_funcs_t glsl_vid_render_funcs = { &model_funcs }; -static void -glsl_vid_render_choose_visual (void) -{ - glsl_ctx->choose_visual (glsl_ctx); -} - -static void -glsl_vid_render_create_context (void) -{ - glsl_ctx->create_context (glsl_ctx); -} - -static void -glsl_vid_render_init (void) -{ - if (!vr_data.vid->vid_internal->sw_context) { - Sys_Error ("Sorry, OpenGL (GLSL) not supported by this program."); - } - glsl_ctx = vr_data.vid->vid_internal->gl_context (); - glsl_ctx->init_gl = GLSL_Init_Common; - glsl_ctx->load_gl (); - - vr_data.vid->vid_internal->set_palette = GLSL_SetPalette; - vr_data.vid->vid_internal->choose_visual = glsl_vid_render_choose_visual; - vr_data.vid->vid_internal->create_context = glsl_vid_render_create_context; - vr_funcs = &glsl_vid_render_funcs; - m_funcs = &model_funcs; -} - -static void -glsl_vid_render_shutdown (void) -{ -} - static general_funcs_t plugin_info_general_funcs = { - glsl_vid_render_init, - glsl_vid_render_shutdown, + .shutdown = glsl_vid_render_shutdown, }; static general_data_t plugin_info_general_data; static plugin_funcs_t plugin_info_funcs = { - &plugin_info_general_funcs, - 0, - 0, - 0, - 0, - 0, - &glsl_vid_render_funcs, + .general = &plugin_info_general_funcs, + .vid_render = &glsl_vid_render_funcs, }; static plugin_data_t plugin_info_data = { - &plugin_info_general_data, - 0, - 0, - 0, - 0, - 0, - &vid_render_data, + .general = &plugin_info_general_data, + .vid_render = &vid_render_data, }; static plugin_t plugin_info = { diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 27f9ae6b9..a518478cb 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -38,6 +38,18 @@ sw_ctx_t *sw_ctx; +static void +sw_vid_render_choose_visual (void) +{ + sw_ctx->choose_visual (sw_ctx); +} + +static void +sw_vid_render_create_context (void) +{ + sw_ctx->create_context (sw_ctx); +} + static vid_model_funcs_t model_funcs = { 0, sw_Mod_LoadLighting, @@ -64,7 +76,29 @@ static vid_model_funcs_t model_funcs = { sw_Skin_InitTranslations, }; +static void +sw_vid_render_init (void) +{ + if (!vr_data.vid->vid_internal->sw_context) { + Sys_Error ("Sorry, software rendering not supported by this program."); + } + sw_ctx = vr_data.vid->vid_internal->sw_context (); + + vr_data.vid->vid_internal->set_palette = sw_ctx->set_palette; + vr_data.vid->vid_internal->choose_visual = sw_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = sw_vid_render_create_context; + + vr_funcs = &sw_vid_render_funcs; + m_funcs = &model_funcs; +} + +static void +sw_vid_render_shutdown (void) +{ +} + vid_render_funcs_t sw_vid_render_funcs = { + sw_vid_render_init, Draw_Character, Draw_String, Draw_nString, @@ -121,64 +155,20 @@ vid_render_funcs_t sw_vid_render_funcs = { &model_funcs }; -static void -sw_vid_render_choose_visual (void) -{ - sw_ctx->choose_visual (sw_ctx); -} - -static void -sw_vid_render_create_context (void) -{ - sw_ctx->create_context (sw_ctx); -} - -static void -sw_vid_render_init (void) -{ - if (!vr_data.vid->vid_internal->sw_context) { - Sys_Error ("Sorry, software rendering not supported by this program."); - } - sw_ctx = vr_data.vid->vid_internal->sw_context (); - - vr_data.vid->vid_internal->set_palette = sw_ctx->set_palette; - vr_data.vid->vid_internal->choose_visual = sw_vid_render_choose_visual; - vr_data.vid->vid_internal->create_context = sw_vid_render_create_context; - - vr_funcs = &sw_vid_render_funcs; - m_funcs = &model_funcs; -} - -static void -sw_vid_render_shutdown (void) -{ -} - static general_funcs_t plugin_info_general_funcs = { - sw_vid_render_init, - sw_vid_render_shutdown, + .shutdown = sw_vid_render_shutdown, }; static general_data_t plugin_info_general_data; static plugin_funcs_t plugin_info_funcs = { - &plugin_info_general_funcs, - 0, - 0, - 0, - 0, - 0, - &sw_vid_render_funcs, + .general = &plugin_info_general_funcs, + .vid_render = &sw_vid_render_funcs, }; static plugin_data_t plugin_info_data = { - &plugin_info_general_data, - 0, - 0, - 0, - 0, - 0, - &vid_render_data, + .general = &plugin_info_general_data, + .vid_render = &vid_render_data, }; static plugin_t plugin_info = { diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index c63a92d88..9cd0c3a79 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -43,6 +43,18 @@ sw_ctx_t *sw32_ctx; +static void +sw32_vid_render_choose_visual (void) +{ + sw32_ctx->choose_visual (sw32_ctx); +} + +static void +sw32_vid_render_create_context (void) +{ + sw32_ctx->create_context (sw32_ctx); +} + static vid_model_funcs_t model_funcs = { 0, sw_Mod_LoadLighting, @@ -69,7 +81,29 @@ static vid_model_funcs_t model_funcs = { sw_Skin_InitTranslations, }; +static void +sw32_vid_render_init (void) +{ + if (!vr_data.vid->vid_internal->sw_context) { + Sys_Error ("Sorry, software rendering not supported by this program."); + } + sw32_ctx = vr_data.vid->vid_internal->sw_context (); + + vr_data.vid->vid_internal->set_palette = sw32_ctx->set_palette; + vr_data.vid->vid_internal->choose_visual = sw32_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = sw32_vid_render_create_context; + + vr_funcs = &sw32_vid_render_funcs; + m_funcs = &model_funcs; +} + +static void +sw32_vid_render_shutdown (void) +{ +} + vid_render_funcs_t sw32_vid_render_funcs = { + sw32_vid_render_init, sw32_Draw_Character, sw32_Draw_String, sw32_Draw_nString, @@ -126,64 +160,20 @@ vid_render_funcs_t sw32_vid_render_funcs = { &model_funcs }; -static void -sw32_vid_render_choose_visual (void) -{ - sw32_ctx->choose_visual (sw32_ctx); -} - -static void -sw32_vid_render_create_context (void) -{ - sw32_ctx->create_context (sw32_ctx); -} - -static void -sw32_vid_render_init (void) -{ - if (!vr_data.vid->vid_internal->sw_context) { - Sys_Error ("Sorry, software rendering not supported by this program."); - } - sw32_ctx = vr_data.vid->vid_internal->sw_context (); - - vr_data.vid->vid_internal->set_palette = sw32_ctx->set_palette; - vr_data.vid->vid_internal->choose_visual = sw32_vid_render_choose_visual; - vr_data.vid->vid_internal->create_context = sw32_vid_render_create_context; - - vr_funcs = &sw32_vid_render_funcs; - m_funcs = &model_funcs; -} - -static void -sw32_vid_render_shutdown (void) -{ -} - static general_funcs_t plugin_info_general_funcs = { - sw32_vid_render_init, - sw32_vid_render_shutdown, + .shutdown = sw32_vid_render_shutdown, }; static general_data_t plugin_info_general_data; static plugin_funcs_t plugin_info_funcs = { - &plugin_info_general_funcs, - 0, - 0, - 0, - 0, - 0, - &sw32_vid_render_funcs, + .general = &plugin_info_general_funcs, + .vid_render = &sw32_vid_render_funcs, }; static plugin_data_t plugin_info_data = { - &plugin_info_general_data, - 0, - 0, - 0, - 0, - 0, - &vid_render_data, + .general = &plugin_info_general_data, + .vid_render = &vid_render_data, }; static plugin_t plugin_info = { diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 5436fcc9f..499979cd1 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -515,6 +515,42 @@ vulkan_Skin_InitTranslations (void) { } +static void +set_palette (const byte *palette) +{ + //FIXME really don't want this here: need an application domain + //so Quake can be separated from QuakeForge (ie, Quake itself becomes + //an app using the QuakeForge engine) +} + +static void +vulkan_vid_render_choose_visual (void) +{ + Vulkan_CreateDevice (vulkan_ctx); + vulkan_ctx->choose_visual (vulkan_ctx); + vulkan_ctx->cmdpool = QFV_CreateCommandPool (vulkan_ctx->device, + vulkan_ctx->device->queue.queueFamily, + 0, 1); + __auto_type cmdset = QFV_AllocCommandBufferSet (1, alloca); + QFV_AllocateCommandBuffers (vulkan_ctx->device, vulkan_ctx->cmdpool, 0, + cmdset); + vulkan_ctx->cmdbuffer = cmdset->a[0]; + vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1); + Sys_MaskPrintf (SYS_vulkan, "vk choose visual %p %p %d %#zx\n", + vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue, + vulkan_ctx->device->queue.queueFamily, + (size_t) vulkan_ctx->cmdpool); +} + +static void +vulkan_vid_render_create_context (void) +{ + vulkan_ctx->create_window (vulkan_ctx); + vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); + Sys_MaskPrintf (SYS_vulkan, "vk create context %#zx\n", + (size_t) vulkan_ctx->surface); +} + static vid_model_funcs_t model_funcs = { sizeof (vulktex_t) + 2 * sizeof (qfv_tex_t), vulkan_Mod_LoadLighting, @@ -541,7 +577,48 @@ static vid_model_funcs_t model_funcs = { vulkan_Skin_InitTranslations, }; +static void +vulkan_vid_render_init (void) +{ + if (!vr_data.vid->vid_internal->vulkan_context) { + Sys_Error ("Sorry, Vulkan not supported by this program."); + } + vulkan_ctx = vr_data.vid->vid_internal->vulkan_context (); + vulkan_ctx->load_vulkan (vulkan_ctx); + + Vulkan_Init_Common (vulkan_ctx); + + vr_data.vid->vid_internal->set_palette = set_palette; + vr_data.vid->vid_internal->choose_visual = vulkan_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = vulkan_vid_render_create_context; + + vr_funcs = &vulkan_vid_render_funcs; + m_funcs = &model_funcs; +} + +static void +vulkan_vid_render_shutdown (void) +{ + qfv_device_t *device = vulkan_ctx->device; + qfv_devfuncs_t *df = device->funcs; + VkDevice dev = device->dev; + QFV_DeviceWaitIdle (device); + df->vkDestroyFence (dev, vulkan_ctx->fence, 0); + df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); + Vulkan_Compose_Shutdown (vulkan_ctx); + Vulkan_Lighting_Shutdown (vulkan_ctx); + Vulkan_Draw_Shutdown (vulkan_ctx); + Vulkan_Bsp_Shutdown (vulkan_ctx); + Vulkan_Alias_Shutdown (vulkan_ctx); + Mod_ClearAll (); + Vulkan_Texture_Shutdown (vulkan_ctx); + Vulkan_DestroyFramebuffers (vulkan_ctx); + Vulkan_DestroyRenderPass (vulkan_ctx); + Vulkan_Shutdown_Common (vulkan_ctx); +} + vid_render_funcs_t vulkan_vid_render_funcs = { + vulkan_vid_render_init, vulkan_Draw_Character, vulkan_Draw_String, vulkan_Draw_nString, @@ -598,107 +675,20 @@ vid_render_funcs_t vulkan_vid_render_funcs = { &model_funcs }; -static void -set_palette (const byte *palette) -{ - //FIXME really don't want this here: need an application domain - //so Quake can be separated from QuakeForge (ie, Quake itself becomes - //an app using the QuakeForge engine) -} - -static void -vulkan_vid_render_choose_visual (void) -{ - Vulkan_CreateDevice (vulkan_ctx); - vulkan_ctx->choose_visual (vulkan_ctx); - vulkan_ctx->cmdpool = QFV_CreateCommandPool (vulkan_ctx->device, - vulkan_ctx->device->queue.queueFamily, - 0, 1); - __auto_type cmdset = QFV_AllocCommandBufferSet (1, alloca); - QFV_AllocateCommandBuffers (vulkan_ctx->device, vulkan_ctx->cmdpool, 0, - cmdset); - vulkan_ctx->cmdbuffer = cmdset->a[0]; - vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1); - Sys_MaskPrintf (SYS_vulkan, "vk choose visual %p %p %d %#zx\n", - vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue, - vulkan_ctx->device->queue.queueFamily, - (size_t) vulkan_ctx->cmdpool); -} - -static void -vulkan_vid_render_create_context (void) -{ - vulkan_ctx->create_window (vulkan_ctx); - vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); - Sys_MaskPrintf (SYS_vulkan, "vk create context %#zx\n", - (size_t) vulkan_ctx->surface); -} - -static void -vulkan_vid_render_init (void) -{ - if (!vr_data.vid->vid_internal->vulkan_context) { - Sys_Error ("Sorry, Vulkan not supported by this program."); - } - vulkan_ctx = vr_data.vid->vid_internal->vulkan_context (); - vulkan_ctx->load_vulkan (vulkan_ctx); - - Vulkan_Init_Common (vulkan_ctx); - - vr_data.vid->vid_internal->set_palette = set_palette; - vr_data.vid->vid_internal->choose_visual = vulkan_vid_render_choose_visual; - vr_data.vid->vid_internal->create_context = vulkan_vid_render_create_context; - - vr_funcs = &vulkan_vid_render_funcs; - m_funcs = &model_funcs; -} - -static void -vulkan_vid_render_shutdown (void) -{ - qfv_device_t *device = vulkan_ctx->device; - qfv_devfuncs_t *df = device->funcs; - VkDevice dev = device->dev; - QFV_DeviceWaitIdle (device); - df->vkDestroyFence (dev, vulkan_ctx->fence, 0); - df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); - Vulkan_Compose_Shutdown (vulkan_ctx); - Vulkan_Lighting_Shutdown (vulkan_ctx); - Vulkan_Draw_Shutdown (vulkan_ctx); - Vulkan_Bsp_Shutdown (vulkan_ctx); - Vulkan_Alias_Shutdown (vulkan_ctx); - Mod_ClearAll (); - Vulkan_Texture_Shutdown (vulkan_ctx); - Vulkan_DestroyFramebuffers (vulkan_ctx); - Vulkan_DestroyRenderPass (vulkan_ctx); - Vulkan_Shutdown_Common (vulkan_ctx); -} - static general_funcs_t plugin_info_general_funcs = { - vulkan_vid_render_init, - vulkan_vid_render_shutdown, + .shutdown = vulkan_vid_render_shutdown, }; static general_data_t plugin_info_general_data; static plugin_funcs_t plugin_info_funcs = { - &plugin_info_general_funcs, - 0, - 0, - 0, - 0, - 0, - &vulkan_vid_render_funcs, + .general = &plugin_info_general_funcs, + .vid_render = &vulkan_vid_render_funcs, }; static plugin_data_t plugin_info_data = { - &plugin_info_general_data, - 0, - 0, - 0, - 0, - 0, - &vid_render_data, + .general = &plugin_info_general_data, + .vid_render = &vid_render_data, }; static plugin_t plugin_info = { From f8ffb12713e6ad93eba0925f5bf0c4b050a46c4e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Jun 2021 16:18:18 +0900 Subject: [PATCH 1604/3664] [audio] Clean up jack and alsa dependencies I had forgotten to test with shared libs and it turns out jack and alsa were directly accessing symbols in the renderer (and in jack's case, linking in a duplicate of the renderer). Fixes #16. --- include/snd_internal.h | 13 ++++++++++--- libs/audio/renderer/snd_channels.c | 12 ++++++++++++ libs/audio/renderer/snd_dma.c | 19 +++++++++++++------ libs/audio/renderer/snd_mem.c | 8 -------- libs/audio/renderer/snd_mix.c | 18 ++++++++---------- libs/audio/targets/Makemodule.am | 9 +++++---- libs/audio/targets/snd_alsa.c | 4 ++-- libs/audio/targets/snd_jack.c | 27 +++++++++------------------ 8 files changed, 59 insertions(+), 51 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index 91e0a53c7..5690b98fb 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -77,6 +77,7 @@ struct snd_s { int frames; //!< frames in buffer //!< 1 frame = channels samples int submission_chunk; //!< don't mix less than this # + unsigned paintedtime; //!< sound clock in samples int framepos; //!< position of dma cursor unsigned char *buffer; //!< destination for mixed sound /** Transfer mixed samples to the output. @@ -90,6 +91,9 @@ struct snd_s { /** Optional data for the xfer function. */ void *xfer_data; + + void (*finish_channels) (void); + void (*paint_channels) (struct snd_s *snd, unsigned endtime); }; /** Describes the sound data. @@ -318,6 +322,12 @@ struct channel_s *SND_AllocChannel (snd_t *snd); */ void SND_ChannelStop (snd_t *snd, channel_t *chan); +/** Mark all channels as no longer in use. + + For use by asynchronous output drivers. +*/ +void SND_FinishChannels (void); + /** Scan channels looking for stopped channels. \param wait if true, wait for the channels to be done. if false, force the channels to be done. true is for threaded, false for @@ -397,9 +407,6 @@ void SND_LocalSound (snd_t *snd, const char *s); \ingroup sound_render */ ///@{ -/** sound clock in samples -*/ -extern unsigned snd_paintedtime; /** Mix all active channels into the output buffer. \param endtime sample time until when to mix diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 7c0d27efc..d08706d65 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -183,6 +183,18 @@ SND_ScanChannels (snd_t *snd, int wait) } } +void +SND_FinishChannels (void) +{ + int i; + channel_t *ch; + + for (i = 0; i < MAX_CHANNELS; i++) { + ch = &snd_channels[i]; + ch->done = ch->stop = 1; + } +} + void SND_StopAllSounds (snd_t *snd) { diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 35df3fc69..489f3b620 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -70,7 +70,10 @@ static general_data_t plugin_info_general_data; static snd_output_funcs_t *snd_output_funcs; static snd_output_data_t *snd_output_data; -static snd_t snd; +static snd_t snd = { + .finish_channels = SND_FinishChannels, + .paint_channels = SND_PaintChannels, +}; static int snd_shutdown = 0; static void @@ -83,7 +86,7 @@ s_xfer_paint_buffer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, p = (float *) paintbuffer; count *= snd->channels; out_max = (snd->frames * snd->channels) - 1; - out_idx = snd_paintedtime * snd->channels; + out_idx = snd->paintedtime * snd->channels; while (out_idx > out_max) out_idx -= out_max + 1; step = 3 - snd->channels; @@ -164,10 +167,10 @@ s_get_soundtime (void) if (framepos < oldframepos) { buffers++; // buffer wrapped - if (snd_paintedtime > 0x40000000) { // time to chop things off to avoid + if (snd.paintedtime > 0x40000000) { // time to chop things off to avoid // 32 bit limits buffers = 0; - snd_paintedtime = frames; + snd.paintedtime = frames; s_stop_all_sounds (); } } @@ -188,9 +191,9 @@ s_update_ (void) s_get_soundtime (); // check to make sure that we haven't overshot - if (snd_paintedtime < soundtime) { + if (snd.paintedtime < soundtime) { // Sys_Printf ("S_Update_ : overflow\n"); - snd_paintedtime = soundtime; + snd.paintedtime = soundtime; } // mix ahead of current position endtime = soundtime + snd_mixahead->value * snd.speed; @@ -492,6 +495,10 @@ static plugin_funcs_t plugin_info_funcs = { .snd_render = &plugin_info_render_funcs, }; +snd_render_data_t snd_render_data = { + .paintedtime = &snd.paintedtime, +}; + static plugin_data_t plugin_info_data = { .general = &plugin_info_general_data, .snd_render = &snd_render_data, diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 6f21a1f6f..c76d3e923 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -51,14 +51,6 @@ #define SAMPLE_GAP 4 -snd_render_data_t snd_render_data = { - 0, - 0, - 0, - &snd_paintedtime, - 0, -}; - static sfxbuffer_t * snd_fail (sfx_t *sfx) { diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index f993852a9..d26b4e430 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -50,8 +50,6 @@ cvar_t *snd_volume; -unsigned snd_paintedtime; // sample PAIRS - portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; static int max_overpaint; // number of extra samples painted // due to phase shift @@ -118,11 +116,11 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) snd_paintbuffer[i].right = 0; } - while (snd_paintedtime < endtime) { + while (snd->paintedtime < endtime) { // if snd_paintbuffer is smaller than DMA buffer end = endtime; - if (end - snd_paintedtime > PAINTBUFFER_SIZE) - end = snd_paintedtime + PAINTBUFFER_SIZE; + if (end - snd->paintedtime > PAINTBUFFER_SIZE) + end = snd->paintedtime + PAINTBUFFER_SIZE; max_overpaint = 0; @@ -144,9 +142,9 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) } if (!ch->end) - ch->end = snd_paintedtime + sfx->length - ch->pos; + ch->end = snd->paintedtime + sfx->length - ch->pos; - ltime = snd_paintedtime; + ltime = snd->paintedtime; while (ltime < end) { // paint up to end count = ((ch->end < end) ? ch->end : end) - ltime; @@ -171,15 +169,15 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) } // transfer out according to DMA format - snd->xfer (snd, snd_paintbuffer, end - snd_paintedtime, + snd->xfer (snd, snd_paintbuffer, end - snd->paintedtime, snd_volume->value); - memmove (snd_paintbuffer, snd_paintbuffer + end - snd_paintedtime, + memmove (snd_paintbuffer, snd_paintbuffer + end - snd->paintedtime, max_overpaint * sizeof (snd_paintbuffer[0])); memset (snd_paintbuffer + max_overpaint, 0, sizeof (snd_paintbuffer) - max_overpaint * sizeof (snd_paintbuffer[0])); - snd_paintedtime = end; + snd->paintedtime = end; } } diff --git a/libs/audio/targets/Makemodule.am b/libs/audio/targets/Makemodule.am index 9b05e055b..8997eb847 100644 --- a/libs/audio/targets/Makemodule.am +++ b/libs/audio/targets/Makemodule.am @@ -21,14 +21,15 @@ libs_audio_targets_snd_output_sdl_la_SOURCES= libs/audio/targets/snd_sdl.c libs_audio_targets_snd_output_alsa_la_LDFLAGS= $(plugin_ldflags) libs_audio_targets_snd_output_alsa_la_LIBADD= $(snd_deps) -libs_audio_targets_snd_output_alsa_la_DEPENDENCIES=$(snd_deps) +libs_audio_targets_snd_output_alsa_la_DEPENDENCIES= $(snd_deps) libs_audio_targets_snd_output_alsa_la_CFLAGS= $(ALSA_CFLAGS) libs_audio_targets_snd_output_alsa_la_SOURCES= libs/audio/targets/snd_alsa.c -libs_audio_targets_snd_output_jack_la_LDFLAGS= $(plugin_ldflags) -libs_audio_targets_snd_output_jack_la_SOURCES= libs/audio/targets/snd_jack.c $(snd_common) $(format_src) -libs_audio_targets_snd_output_jack_la_LIBADD= $(snd_libs) $(format_libs) $(JACK_LIBS) +libs_audio_targets_snd_output_jack_la_LDFLAGS= $(plugin_ldflags) +libs_audio_targets_snd_output_jack_la_LIBADD= $(snd_deps) $(JACK_LIBS) libs_audio_targets_snd_output_jack_la_DEPENDENCIES= $(snd_libs) +libs_audio_targets_snd_output_jack_la_CFLAGS= $(JACK_CFLAGS) +libs_audio_targets_snd_output_jack_la_SOURCES= libs/audio/targets/snd_jack.c libs_audio_targets_snd_output_oss_la_LDFLAGS= $(plugin_ldflags) libs_audio_targets_snd_output_oss_la_LIBADD= $(snd_deps) $(OSS_LIBS) diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index f0e1c52a8..fdee222b1 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -202,7 +202,7 @@ alsa_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, p = (float *) paintbuffer; count *= snd->channels; out_max = (snd->frames * snd->channels) - 1; - out_idx = snd_paintedtime * snd->channels; + out_idx = snd->paintedtime * snd->channels; while (out_idx > out_max) out_idx -= out_max + 1; step = 3 - snd->channels; @@ -288,7 +288,7 @@ alsa_process (snd_pcm_t *pcm, snd_t *snd) ret = 0; } snd->buffer = packet.areas[0].addr; - SND_PaintChannels (snd, snd_paintedtime + packet.nframes); + snd->paint_channels (snd, snd->paintedtime + packet.nframes); if ((res = qfsnd_pcm_mmap_commit (pcm, packet.offset, packet.nframes)) < 0 || (snd_pcm_uframes_t) res != packet.nframes) { diff --git a/libs/audio/targets/snd_jack.c b/libs/audio/targets/snd_jack.c index 0d9f282c9..d2c299410 100644 --- a/libs/audio/targets/snd_jack.c +++ b/libs/audio/targets/snd_jack.c @@ -59,18 +59,6 @@ static cvar_t *snd_jack_server; static int s_jack_connect (snd_t *snd); -static void -s_finish_channels (void) -{ - int i; - channel_t *ch; - - for (i = 0; i < MAX_CHANNELS; i++) { - ch = &snd_channels[i]; - ch->done = ch->stop = 1; - } -} - static void s_update (snd_t *snd) { @@ -85,7 +73,7 @@ s_update (snd_t *snd) if (!snd_shutdown) { if (now - snd_alive_time > 1.0) { Sys_Printf ("jackd client thread seems to have died\n"); - s_finish_channels (); + snd->finish_channels (); snd_shutdown = 1; } } @@ -162,8 +150,8 @@ snd_jack_xfer (snd_t *snd, portable_samplepair_t *paintbuffer, int count, } for (i = 0; i < count; i++) { /* max is +/- 1.0. need to implement clamping. */ - *output[0]++ = volume * snd_paintbuffer[i].left; - *output[1]++ = volume * snd_paintbuffer[i].right; + *output[0]++ = volume * paintbuffer[i].left; + *output[1]++ = volume * paintbuffer[i].right; } } @@ -176,15 +164,17 @@ snd_jack_process (jack_nframes_t nframes, void *arg) snd_alive = 1; for (i = 0; i < 2; i++) output[i] = (float *) jack_port_get_buffer (jack_out[i], nframes); - SND_PaintChannels (snd, snd_paintedtime + nframes); + snd->paint_channels (snd, snd->paintedtime + nframes); return 0; } static void snd_jack_shutdown (void *arg) { + snd_t *snd = arg; + snd_shutdown = 1; - s_finish_channels (); + snd->finish_channels (); } static void @@ -217,12 +207,13 @@ s_jack_connect (snd_t *snd) if (jack_set_xrun_callback (jack_handle, snd_jack_xrun, 0)) Sys_Printf ("Could not set xrun callback\n"); jack_set_process_callback (jack_handle, snd_jack_process, snd); - jack_on_shutdown (jack_handle, snd_jack_shutdown, 0); + jack_on_shutdown (jack_handle, snd_jack_shutdown, snd); for (i = 0; i < 2; i++) jack_out[i] = jack_port_register (jack_handle, va (0, "out_%d", i + 1), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); snd->speed = jack_get_sample_rate (jack_handle); + snd->channels = 2; s_jack_activate (); sound_started = 1; Sys_Printf ("Connected to JACK: %d Sps\n", snd->speed); From d865095d0b05fdcd7f8f7594cc8fbf31a29990c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Jun 2021 14:47:08 +0900 Subject: [PATCH 1605/3664] [gamecode] Check for nil entity Fixes a segfault when disassembling progs.dat files that access entity fields as the accessed entity will generally be nil. --- libs/gamecode/pr_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 906ec185f..7fc3ba455 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1600,7 +1600,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) opval = pr->pr_globals[s->a].entity_var; parm_ind = pr->pr_globals[s->b].uinteger_var; if (parm_ind < pr->progs->entityfields - && opval >= 0 + && opval > 0 && opval < pr->pr_edict_area_size) { ed = PROG_TO_EDICT (pr, opval); opval = &E_fld(ed, parm_ind) - pr->pr_globals; From 365e298908c31fc213e1a85131a5fc1e2c2aac16 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Jun 2021 14:49:16 +0900 Subject: [PATCH 1606/3664] [qfcc] Make internal_error const correct This way it can be used with const expr objects. --- tools/qfcc/include/diagnostic.h | 2 +- tools/qfcc/source/diagnostic.c | 9 +++++---- tools/qfcc/source/stub.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index 100c0f535..958b44d66 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -49,7 +49,7 @@ struct expr_s *_error (struct expr_s *e, const char *file, int line, __attribute__ ((format (PRINTF, 4, 5))); #define error(e, fmt...) _error(e, __FILE__, __LINE__, fmt) -void _internal_error (struct expr_s *e, const char *file, int line, +void _internal_error (const struct expr_s *e, const char *file, int line, const char *fmt, ...) __attribute__ ((format (PRINTF, 4, 5), noreturn)); #define internal_error(e, fmt...) _internal_error(e, __FILE__, __LINE__, fmt) diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index d9f18d507..9169b42f9 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -47,7 +47,7 @@ diagnostic_hook warning_hook; diagnostic_hook notice_hook; static void -report_function (expr_t *e) +report_function (const expr_t *e) { static function_t *last_func = (function_t *)-1L; static string_t last_file; @@ -78,7 +78,7 @@ report_function (expr_t *e) } static __attribute__((format(PRINTF, 4, 0))) void -format_message (dstring_t *message, const char *msg_type, expr_t *e, +format_message (dstring_t *message, const char *msg_type, const expr_t *e, const char *fmt, va_list args) { string_t file = pr.source_file; @@ -147,7 +147,7 @@ _debug (expr_t *e, const char *file, int line, const char *fmt, ...) } static __attribute__((noreturn, format(PRINTF, 4, 0))) void -__internal_error (expr_t *e, const char *file, int line, +__internal_error (const expr_t *e, const char *file, int line, const char *fmt, va_list args) { dstring_t *message = dstring_new (); @@ -234,7 +234,8 @@ _warning (expr_t *e, const char *file, int line, const char *fmt, ...) } void -_internal_error (expr_t *e, const char *file, int line, const char *fmt, ...) +_internal_error (const expr_t *e, const char *file, int line, + const char *fmt, ...) { va_list args; diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index af31e546f..4a0315d4a 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -37,7 +37,7 @@ __attribute__((const)) codespace_t *codespace_new (void) {return 0;} void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {} __attribute__((const)) int function_parms (function_t *f, byte *parm_size) {return 0;} void def_to_ddef (def_t *def, ddef_t *ddef, int aux) {} -__attribute__((noreturn)) void _internal_error (expr_t *e, const char *file, int line, const char *fmt, ...) {abort();} +__attribute__((noreturn)) void _internal_error (const expr_t *e, const char *file, int line, const char *fmt, ...) {abort();} __attribute__((const)) expr_t *_warning (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;} __attribute__((const)) expr_t *_error (expr_t *e, const char *file, int line, const char *fmt, ...) {return 0;} __attribute__((const)) symbol_t *make_structure (const char *name, int su, struct_def_t *defs, type_t *type) {return 0;} From 38a6ccdc85c827433c59dfa75113c369f84c2def Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Jun 2021 14:53:08 +0900 Subject: [PATCH 1607/3664] [qfcc] Use indexed initializers for expr functions This will make adding new expression types easier (though the current reason for doing so has been abandoned for now). --- tools/qfcc/include/expr.h | 4 ++- tools/qfcc/source/dot_expr.c | 38 ++++++++++---------- tools/qfcc/source/expr.c | 11 ++++++ tools/qfcc/source/expr_assign.c | 2 ++ tools/qfcc/source/statements.c | 63 ++++++++++++++------------------- 5 files changed, 62 insertions(+), 56 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 79fd77f99..843c1baf6 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -58,6 +58,8 @@ typedef enum { ex_value, ///< constant value (::ex_value_t) ex_compound, ///< compound initializer ex_memset, ///< memset needs three params... + + ex_count, ///< number of valid expression types } expr_type; /** Binary and unary expressions. @@ -570,7 +572,7 @@ short expr_short (expr_t *e) __attribute__((pure)); int expr_integral (expr_t *e) __attribute__((pure)); -/** Check of the expression refers to a constant value. +/** Check if the expression refers to a constant value. \param e The expression to check. \return True if the expression is constant. diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 84bae7aa2..d3d584cc3 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -545,23 +545,23 @@ print_memset (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) static void _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { - static print_f print_funcs[] = { - print_error, - print_state, - print_bool, - print_label, - print_labelref, - print_block, - print_subexpr, - print_uexpr, - print_def, - print_symbol, - print_temp, - print_vector, - print_nil, - print_value, - print_compound, - print_memset, + static print_f print_funcs[ex_count] = { + [ex_error] = print_error, + [ex_state] = print_state, + [ex_bool] = print_bool, + [ex_label] = print_label, + [ex_labelref] = print_labelref, + [ex_block] = print_block, + [ex_expr] = print_subexpr, + [ex_uexpr] = print_uexpr, + [ex_def] = print_def, + [ex_symbol] = print_symbol, + [ex_temp] = print_temp, + [ex_vector] = print_vector, + [ex_nil] = print_nil, + [ex_value] = print_value, + [ex_compound] = print_compound, + [ex_memset] = print_memset, }; int indent = level * 2 + 2; @@ -573,12 +573,12 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) return; e->printid = id; - if ((int) e->type < 0 || e->type > ex_memset) { + if ((int) e->type < 0 || e->type > ex_memset || !print_funcs[e->type]) { dasprintf (dstr, "%*se_%p [label=\"(bad expr type)\\n%d\"];\n", indent, "", e, e->line); return; } - print_funcs [e->type] (dstr, e, level, id, next); + print_funcs[e->type] (dstr, e, level, id, next); } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index f86e9dece..fc26a78bd 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -256,6 +256,8 @@ get_type (expr_t *e) break; case ex_vector: return e->e.vector.type; + case ex_count: + internal_error (e, "invalid expression"); } return (type_t *) unalias_type (type);//FIXME cast } @@ -435,6 +437,7 @@ copy_expr (expr_t *e) return n; case ex_vector: n = new_expr (); + *n = *e; n->e.vector.type = e->e.vector.type; n->e.vector.list = copy_expr (e->e.vector.list); t = e->e.vector.list; @@ -459,6 +462,8 @@ copy_expr (expr_t *e) n->e.memset.val = copy_expr (e->e.memset.val); n->e.memset.count = copy_expr (e->e.memset.count); return n; + case ex_count: + break; } internal_error (e, "invalid expression"); } @@ -1683,6 +1688,8 @@ unary_expr (int op, expr_t *e) } case ex_nil: return error (e, "invalid type for unary -"); + case ex_count: + internal_error (e, "invalid expression"); } break; case '!': @@ -1749,6 +1756,8 @@ unary_expr (int op, expr_t *e) } case ex_nil: return error (e, "invalid type for unary !"); + case ex_count: + internal_error (e, "invalid expression"); } break; case '~': @@ -1824,6 +1833,8 @@ bitnot_expr: } case ex_nil: return error (e, "invalid type for unary ~"); + case ex_count: + internal_error (e, "invalid expression"); } break; case '.': diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 472c1f1a5..9ae27b146 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -136,6 +136,8 @@ is_lvalue (const expr_t *expr) case ex_value: case ex_error: break; + case ex_count: + internal_error (expr, "invalid expression"); } return 0; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 0743c5c40..d2ae28e65 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1449,30 +1449,23 @@ expr_value (sblock_t *sblock, expr_t *e, operand_t **op) static sblock_t * statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) { - static expr_f sfuncs[] = { - 0, // ex_error - 0, // ex_state - 0, // ex_bool - 0, // ex_label - 0, // ex_labelref - expr_block, // ex_block - expr_expr, - expr_uexpr, - expr_def, - expr_symbol, - expr_temp, - expr_vector_e, // ex_vector - expr_nil, - expr_value, - 0, // ex_compound - 0, // ex_memset + static expr_f sfuncs[ex_count] = { + [ex_block] = expr_block, + [ex_expr] = expr_expr, + [ex_uexpr] = expr_uexpr, + [ex_def] = expr_def, + [ex_symbol] = expr_symbol, + [ex_temp] = expr_temp, + [ex_vector] = expr_vector_e, + [ex_nil] = expr_nil, + [ex_value] = expr_value, }; if (!e) { *op = 0; return sblock; } - if (e->type > ex_memset) + if (e->type >= ex_count) internal_error (e, "bad sub-expression type"); if (!sfuncs[e->type]) internal_error (e, "unexpected sub-expression type: %s", @@ -1767,27 +1760,25 @@ statement_nonexec (sblock_t *sblock, expr_t *e) static sblock_t * statement_slist (sblock_t *sblock, expr_t *e) { - static statement_f sfuncs[] = { - statement_ignore, // ex_error - statement_state, - statement_bool, - statement_label, - 0, // ex_labelref - statement_block, - statement_expr, - statement_uexpr, - statement_nonexec, // ex_def - statement_nonexec, // ex_symbol - statement_nonexec, // ex_temp - statement_nonexec, // ex_vector - statement_nonexec, // ex_nil - statement_nonexec, // ex_value - 0, // ex_compound - statement_memset, + static statement_f sfuncs[ex_count] = { + [ex_error] = statement_ignore, + [ex_state] = statement_state, + [ex_bool] = statement_bool, + [ex_label] = statement_label, + [ex_block] = statement_block, + [ex_expr] = statement_expr, + [ex_uexpr] = statement_uexpr, + [ex_def] = statement_nonexec, + [ex_symbol] = statement_nonexec, + [ex_temp] = statement_nonexec, + [ex_vector] = statement_nonexec, + [ex_nil] = statement_nonexec, + [ex_value] = statement_nonexec, + [ex_memset] = statement_memset, }; for (/**/; e; e = e->next) { - if (e->type > ex_memset) + if (e->type >= ex_count || !sfuncs[e->type]) internal_error (e, "bad expression type"); sblock = sfuncs[e->type] (sblock, e); } From d50f2c31453f24b1df7dda38aff5309e8b97000e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Jun 2021 20:25:26 +0900 Subject: [PATCH 1608/3664] [qfcc] Correctly check for constant op Identifiers can be constants. I don't remember quite what it fixed other than some bogus kill relations in the dags (which might have caused issues later). --- tools/qfcc/source/dags.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 1d98df411..ea040587a 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -467,6 +467,8 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) static int op_is_identifier (operand_t *op) { + if (!op) + return 0; if (op->op_type == op_label) return 0; if (op->op_type == op_value) @@ -478,6 +480,28 @@ op_is_identifier (operand_t *op) return 1; } +static int +op_is_constant (operand_t *op) +{ + if (!op) + return 0; + if (op->op_type == op_label) + return 1; + if (op->op_type == op_value) + return 1; + if (op->op_type == op_label) + return op->o.def->constant; + return 0; +} + +static int +op_is_temp (operand_t *op) +{ + if (!op) + return 0; + return op->op_type == op_temp; +} + static int dag_tempop_kill_aliases_visit (tempop_t *tempop, void *_l) { @@ -488,7 +512,7 @@ dag_tempop_kill_aliases_visit (tempop_t *tempop, void *_l) if (tempop == &l->op->o.tempop) return 0; label = tempop->daglabel; - if (label && label->dagnode) { + if (label && label->dagnode && !label->dagnode->killed) { set_add (node->edges, label->dagnode->number); set_remove (node->edges, node->number); label->dagnode->killed = node; @@ -506,7 +530,7 @@ dag_def_kill_aliases_visit (def_t *def, void *_l) if (def == l->op->o.def) return 0; label = def->daglabel; - if (label && label->dagnode) { + if (label && label->dagnode && !label->dagnode->killed) { set_add (node->edges, label->dagnode->number); set_remove (node->edges, node->number); label->dagnode->killed = node; @@ -703,19 +727,28 @@ dag_kill_nodes (dag_t *dag, dagnode_t *n) for (i = 0; i < dag->num_nodes; i++) { node = dag->nodes[i]; + if (node->killed) { + //the node is already killed + continue; + } if (node == n->children[1]) { // assume the pointer does not point to itself. This should be // reasonable because without casting, only a void pointer can // point to itself (the required type is recursive). continue; } - if (node->label->op && !op_is_identifier (node->label->op)) { + if (op_is_constant (node->label->op)) { // While constants in the Quake VM can be changed via a pointer, // doing so would cause much more fun than a simple // mis-optimization would, so consider them safe from pointer // operations. continue; } + if (op_is_temp (node->label->op)) { + // Assume that the pointer cannot point to a temporary variable. + // This is reasonable as there is no programmer access to temps. + continue; + } node->killed = n; } n->killed = 0; From 0d1fad12f0855130bf811e48bb4446019f7bcfe5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Jun 2021 09:12:57 +0900 Subject: [PATCH 1609/3664] [qfcc] Add some comments --- tools/qfcc/source/dags.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index ea040587a..cc453ae55 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -266,14 +266,21 @@ dag_make_children (dag_t *dag, statement_t *s, for (i = 0; i < 3; i++) { dagnode_t *node = dag_node (operands[i + 1]); dagnode_t *killer = 0; + if (node && node->killed) { + // If the node has been killed, then a new node is needed killer = node->killed; node = 0; } + if (!node) { + // No valid node found (either first reference to the value, + // or the value's node was killed). node = leaf_node (dag, operands[i + 1], s->expr); } if (killer) { + // When an operand refers to a killed node, it must be + // evaluated AFTER the killing node has been evaluated. set_add (node->edges, killer->number); } children[i] = node; From 5291cfb03d9681da5c6455028665191601a68e2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Jun 2021 09:41:03 +0900 Subject: [PATCH 1610/3664] [qfcc] Keep track of reachable dag nodes In order to correctly handle swap-style code { t = a; a = b; b = t; } edges need to be created for each of the assignments moving an identifier lable, but the dag must remain acyclic (the above example wants to create a cycle). Having the reachable nodes recorded makes checking for potential loops a quick operation. --- tools/qfcc/include/dags.h | 3 +++ tools/qfcc/source/dags.c | 23 ++++++++++++++++++++++- tools/qfcc/source/dot_dag.c | 8 ++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index 2c677a972..6addafcd2 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -79,6 +79,9 @@ typedef struct dagnode_s { struct set_s *edges; ///< includes nodes pointed to by \a children //@} struct set_s *identifiers; ///< set of identifiers attached to this node + struct set_s *reachable; ///< set of nodes reachable via edges (not + ///< parents) for ensuring cycles are not + ///< created } dagnode_t; typedef struct dag_s { diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index cc453ae55..20d26044d 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -116,6 +116,7 @@ new_node (dag_t *dag) node->parents = set_new (); node->edges = set_new (); node->identifiers = set_new (); + node->reachable = set_new (); node->number = dag->num_nodes; set_add (dag->roots, node->number); // nodes start out as root nodes dag->nodes[dag->num_nodes++] = node; @@ -255,6 +256,20 @@ dag_make_leafs (dag_t *dag, statement_t *s, operand_t *operands[FLOW_OPERANDS]) } } +static void +dagnode_set_reachable (dag_t *dag, dagnode_t *node) +{ + for (set_iter_t *edge_iter = set_first (node->edges); edge_iter; + edge_iter = set_next (edge_iter)) { + dagnode_t *r = dag->nodes[edge_iter->element]; + // The other node is directly reachable + set_add (node->reachable, r->number); + // All nodes reachable by the other node are indirectly reachable + // from this node. + set_union (node->reachable, r->reachable); + } +} + static void dag_make_children (dag_t *dag, statement_t *s, operand_t *operands[FLOW_OPERANDS], @@ -282,6 +297,10 @@ dag_make_children (dag_t *dag, statement_t *s, // When an operand refers to a killed node, it must be // evaluated AFTER the killing node has been evaluated. set_add (node->edges, killer->number); + // If killer is set, then node is guaranteed to be a new node + // and thus does not have any parents, so no need to worry about + // updating the reachable sets of any parent nodes. + dagnode_set_reachable (dag, node); } children[i] = node; } @@ -828,6 +847,7 @@ dag_create (flownode_t *flownode) n->label = op; dagnode_add_children (dag, n, operands, children); dagnode_set_edges (dag, n); + dagnode_set_reachable (dag, n); } } lx = operand_label (dag, operands[0]); @@ -835,8 +855,9 @@ dag_create (flownode_t *flownode) lx->expr = s->expr; dagnode_attach_label (n, lx); } - if (n->type == st_ptrassign) + if (n->type == st_ptrassign) { dag_kill_nodes (dag, n); + } } nodes = malloc (dag->num_nodes * sizeof (dagnode_t *)); diff --git a/tools/qfcc/source/dot_dag.c b/tools/qfcc/source/dot_dag.c index 541993735..9d6165a11 100644 --- a/tools/qfcc/source/dot_dag.c +++ b/tools/qfcc/source/dot_dag.c @@ -124,6 +124,14 @@ print_node (dstring_t *dstr, dag_t *dag, dagnode_t *node) node, dag->nodes[edge_iter->element]); } set_delete (edges); + if (0) { + for (edge_iter = set_first (node->reachable); edge_iter; + edge_iter = set_next (edge_iter)) { + dasprintf (dstr, + " \"dagnode_%p\" -> \"dagnode_%p\" [style=dotted];\n", + node, dag->nodes[edge_iter->element]); + } + } if (0 && !set_is_empty (node->identifiers)) { set_iter_t *id_iter; daglabel_t *id; From 76b3bedb72a0a1b92e658c733bf6ff079d18ce10 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Jun 2021 12:09:35 +0900 Subject: [PATCH 1611/3664] [qfcc] Revert "Kill dag leaf nodes on assignment." This reverts commit 2fcda44ab081ec4425d6f54923109bfd5131bd57. Killing the node is not the correcgt answer as it blocks many optimization opportunities. The correct answer is adding edges to describe the temporal dependencies. Of course, this breaks the swap.r test. --- tools/qfcc/source/dags.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 20d26044d..188d8caa3 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -640,11 +640,6 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l) "attempt to attach non-identifer label to dagnode " "identifiers"); if (l->dagnode) { - // if the node is a leaf, then kill its value so no attempt is made - // to reuse it. - if (l->dagnode->type == st_none) { - l->dagnode->killed = n; - } dagnode_t *node = l->dagnode; set_union (n->edges, node->parents); set_remove (n->edges, n->number); From a3aebc983b56e7528e608a94f41fe11c0b624323 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Jun 2021 12:56:23 +0900 Subject: [PATCH 1612/3664] [qfcc] Add dependency edges for moved labels When moving an identifier label from one node to another, the first node must be evaluated before the second node, which the edge guarantees. However, code for swapping two variables t = a; a = b; b = t; creates a dependency cycle. The solution is to create a new leaf node for the source operand of the assignment. This fixes the swap.r test without pessimizing postop code. This takes care of the core problem in #3, but there is still room for improvement in that the load/store can be combined into a move. --- tools/qfcc/source/dags.c | 25 ++++++++++++++++++++----- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/postop.r | 19 +++++++++++++++++++ 3 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 tools/qfcc/test/postop.r diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 188d8caa3..974a917f0 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -629,8 +629,8 @@ dag_make_var_live (set_t *live_vars, operand_t *op) set_add (live_vars, var->number); } -static void -dagnode_attach_label (dagnode_t *n, daglabel_t *l) +static int +dagnode_attach_label (dag_t *dag, dagnode_t *n, daglabel_t *l) { if (!l->op) internal_error (0, "attempt to attach operator label to dagnode " @@ -641,9 +641,12 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l) "identifiers"); if (l->dagnode) { dagnode_t *node = l->dagnode; - set_union (n->edges, node->parents); - set_remove (n->edges, n->number); set_remove (node->identifiers, l->number); + if (set_is_member (node->reachable, n->number)) { + return 0; + } + set_add (n->edges, node->number); + dagnode_set_reachable (dag, n); } l->live = 0; // remove live forcing on assignment l->dagnode = n; @@ -652,6 +655,7 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l) if (n->label->op) { dag_live_aliases (n->label->op); } + return 1; } static int @@ -848,7 +852,18 @@ dag_create (flownode_t *flownode) lx = operand_label (dag, operands[0]); if (lx && lx->dagnode != n) { lx->expr = s->expr; - dagnode_attach_label (n, lx); + if (!dagnode_attach_label (dag, n, lx)) { + // attempting to attach the label to the node would create + // a dependency cycle in the dag, so a new node needs to be + // created for the source operand + if (s->type == st_assign) { + n = leaf_node (dag, operands[1], s->expr); + dagnode_attach_label (dag, n, lx); + } else { + internal_error (s->expr, "unexpected failure to attach" + " label to node"); + } + } } if (n->type == st_ptrassign) { dag_kill_nodes (dag, n); diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index f328fcb6e..4263803fe 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -32,6 +32,7 @@ test_progs_dat=\ tools/qfcc/test/nilparamret.dat \ tools/qfcc/test/overload.dat \ tools/qfcc/test/paramret.dat \ + tools/qfcc/test/postop.dat \ tools/qfcc/test/quaternion.dat \ tools/qfcc/test/return-ivar.dat \ tools/qfcc/test/sendv.dat \ @@ -372,6 +373,16 @@ tools/qfcc/test/paramret.run: $(qfcc_test_run_deps) include $(paramret_dep) # am--include-marker r_depfiles_remade += $(paramret_dep) +tools_qfcc_test_postop_dat_SOURCES=tools/qfcc/test/postop.r +postop_obj=$(tools_qfcc_test_postop_dat_SOURCES:.r=.o) +postop_dep=$(call qcautodep,$(tools_qfcc_test_postop_dat_SOURCES)) +tools/qfcc/test/postop.dat$(EXEEXT): $(postop_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(postop_obj) +tools/qfcc/test/postop.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(postop_dep) # am--include-marker +r_depfiles_remade += $(postop_dep) + tools_qfcc_test_quaternion_dat_SOURCES=tools/qfcc/test/quaternion.r quaternion_obj=$(tools_qfcc_test_quaternion_dat_SOURCES:.r=.o) quaternion_dep=$(call qcautodep,$(tools_qfcc_test_quaternion_dat_SOURCES)) diff --git a/tools/qfcc/test/postop.r b/tools/qfcc/test/postop.r new file mode 100644 index 000000000..4b1091ac5 --- /dev/null +++ b/tools/qfcc/test/postop.r @@ -0,0 +1,19 @@ +int array[3] = { -1, -1, -1 }; + +int array_index (void) +{ + int i = 0; + + for (int c = 0; c < 3; c++) { + array[i++] = 0; + } + return i == 3 && !(array[0] | array[1] | array[2]); +} + +int +main () +{ + int ret = 0; + ret |= !array_index (); + return ret; +} From c554dee0f8cb27db7d5ff37d2e4f7ba3bb994e2c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Jun 2021 15:39:15 +0900 Subject: [PATCH 1613/3664] [build] Autoconfiscate simd support The default is to enable (and autodetect based on lscpu) simd support, or the mode can be specified via --enable-simd=mode. --disable-simd disables the support but ensures gcc will still compile the float vector types. --- config.d/compiling.m4 | 31 ++++++++++++++++++++++++------- config.d/result.m4 | 1 + configure.ac | 2 +- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 34a0bc93c..f0d108a27 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -81,13 +81,30 @@ AC_ARG_ENABLE(optimize, optimize=yes ) -dnl QF_CC_OPTION(-Wno-psabi) -dnl QF_CC_OPTION(-msse2) -dnl QF_CC_OPTION(-Wno-psabi) -QF_CC_OPTION(-mavx2) -dnl fma is not used as it is the equivalent of turning on -dnl -funsafe-math-optimizations -dnl QF_CC_OPTION(-mfma) +AC_ARG_ENABLE(simd, + [ --enable-simd[=arg] Enable SIMD support (default auto)], + [], + [enable_simd=yes] +) + +case "$enable_simd" in + no) + QF_CC_OPTION(-Wno-psabi) + simd=no + ;; + sse|sse2|avx|avx2) + QF_CC_OPTION(-m$enable_simd) + simd=$enable_simd + ;; + yes) + for simd in avx2 avx sse2 sse; do + if lscpu | grep -q -w $simd; then + QF_CC_OPTION(-m$simd) + break + fi + done + ;; +esac AC_MSG_CHECKING(for optimization) if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then diff --git a/config.d/result.m4 b/config.d/result.m4 index f2dc7fd70..7bb199947 100644 --- a/config.d/result.m4 +++ b/config.d/result.m4 @@ -12,6 +12,7 @@ AC_MSG_RESULT([ HTTP support : ${CURL:-no} Compiler version : $CCVER Compiler flags : $CFLAGS + SIMD Support : $simd qfcc cpp invocation: $CPP_NAME Shared game data directory : $sharepath diff --git a/configure.ac b/configure.ac index c19200755..905115d20 100644 --- a/configure.ac +++ b/configure.ac @@ -74,7 +74,7 @@ dnl Checks for system type dnl ================================================================== dnl Checks for which system driver to use -echo ${host} + AC_MSG_CHECKING(for system driver) case "${host}" in i?86-*-mingw32*|x86_64-w64-mingw32*) From d9e7730d91e071428137bc9b084f66fae005a13d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Jun 2021 20:03:13 +0900 Subject: [PATCH 1614/3664] [audio] Add a cvar for jack port names Fixes #2 --- libs/audio/targets/snd_jack.c | 57 ++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/libs/audio/targets/snd_jack.c b/libs/audio/targets/snd_jack.c index d2c299410..095349e1b 100644 --- a/libs/audio/targets/snd_jack.c +++ b/libs/audio/targets/snd_jack.c @@ -56,6 +56,7 @@ static jack_client_t *jack_handle; static jack_port_t *jack_out[2]; static float *output[2]; static cvar_t *snd_jack_server; +static cvar_t *snd_jack_ports; static int s_jack_connect (snd_t *snd); @@ -89,25 +90,60 @@ s_update (snd_t *snd) } } +static const char ** +s_jack_parse_ports (const char *ports_str) +{ + int num_ports = 1; + int ind = 0; + char **ports; + + for (const char *s = ports_str; *s; s++) { + num_ports += *s == ';'; + } + + size_t len = strlen (ports_str) + 1; + ports = malloc ((num_ports + 1) * sizeof (*ports) + len + 1); + ports[num_ports] = 0; + ports[0] = (char *) &ports[num_ports + 1]; + ports[0][len] = 0; + strcpy (ports[0], ports_str); + + for (char *s = ports[0]; *s; s++) { + if (s > ports[0]) { + s[-1] = 0; + } + for (ports[ind++] = s; *s && *s != ';'; s++) { + } + } + + return (const char **) ports; +} + static void s_jack_activate (void) { const char **ports; int i; + snd_shutdown = 0; + if (!*snd_jack_ports->string) { + ports = jack_get_ports (jack_handle, 0, 0, + JackPortIsPhysical | JackPortIsInput); + } else { + ports = s_jack_parse_ports (snd_jack_ports->string); + } + if (developer->int_val & SYS_snd) { + for (i = 0; ports[i]; i++) { + Sys_Printf ("%s\n", ports[i]); + } + } if (jack_activate (jack_handle)) { Sys_Printf ("Could not activate JACK\n"); return; } - snd_shutdown = 0; - ports = jack_get_ports (jack_handle, 0, 0, - JackPortIsPhysical | JackPortIsInput); - if (developer->int_val & SYS_snd) { - for (i = 0; ports[i]; i++) - Sys_Printf ("%s\n", ports[i]); - } - for (i = 0; i < 2; i++) + for (i = 0; i < 2; i++) { jack_connect (jack_handle, jack_port_name (jack_out[i]), ports[i]); + } free (ports); } @@ -246,6 +282,11 @@ s_init_cvars (void) { snd_jack_server = Cvar_Get ("snd_jack_server", "default", CVAR_ROM, NULL, "The name of the JACK server to connect to"); + snd_jack_ports = Cvar_Get ("snd_jack_ports", "", CVAR_ROM, NULL, + "; separated list of port names to which QF " + "will connect. Defaults to the first two " + "physical ports. Currently only two ports " + "are supported."); } static general_funcs_t plugin_info_general_funcs = { From 9d140d1d152c027fc226488fb59fa174895905cf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Jun 2021 08:48:26 +0900 Subject: [PATCH 1615/3664] [qfcc] Use {>...} for unnamed alias types The ... is the encoding of the aliased type. Avoids (null) in the encoding. Fixes #10. --- tools/qfcc/source/type.c | 4 ++-- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/ptraliasenc.r | 25 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tools/qfcc/test/ptraliasenc.r diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index c6b92b94e..56991b790 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -729,8 +729,8 @@ encode_type (dstring_t *encoding, const type_t *type) if (!type) return; switch (type->meta) { - case ty_alias: // XXX do I want this, or just the unaliased type? - dasprintf (encoding, "{%s>", type->name); + case ty_alias: + dasprintf (encoding, "{%s>", type->name ? type->name : ""); encode_type (encoding, type->t.alias.aux_type); dasprintf (encoding, "}"); return; diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 4263803fe..54bb87dcf 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -33,6 +33,7 @@ test_progs_dat=\ tools/qfcc/test/overload.dat \ tools/qfcc/test/paramret.dat \ tools/qfcc/test/postop.dat \ + tools/qfcc/test/ptraliasenc.dat \ tools/qfcc/test/quaternion.dat \ tools/qfcc/test/return-ivar.dat \ tools/qfcc/test/sendv.dat \ @@ -383,6 +384,16 @@ tools/qfcc/test/postop.run: $(qfcc_test_run_deps) include $(postop_dep) # am--include-marker r_depfiles_remade += $(postop_dep) +tools_qfcc_test_ptraliasenc_dat_SOURCES=tools/qfcc/test/ptraliasenc.r +ptraliasenc_obj=$(tools_qfcc_test_ptraliasenc_dat_SOURCES:.r=.o) +ptraliasenc_dep=$(call qcautodep,$(tools_qfcc_test_ptraliasenc_dat_SOURCES)) +tools/qfcc/test/ptraliasenc.dat$(EXEEXT): $(ptraliasenc_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(ptraliasenc_obj) +tools/qfcc/test/ptraliasenc.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(ptraliasenc_dep) # am--include-marker +r_depfiles_remade += $(ptraliasenc_dep) + tools_qfcc_test_quaternion_dat_SOURCES=tools/qfcc/test/quaternion.r quaternion_obj=$(tools_qfcc_test_quaternion_dat_SOURCES:.r=.o) quaternion_dep=$(call qcautodep,$(tools_qfcc_test_quaternion_dat_SOURCES)) diff --git a/tools/qfcc/test/ptraliasenc.r b/tools/qfcc/test/ptraliasenc.r new file mode 100644 index 000000000..2f305617f --- /dev/null +++ b/tools/qfcc/test/ptraliasenc.r @@ -0,0 +1,25 @@ +#include + +#include "test-harness.h" + +typedef int int32_t; +int32_t *int32_ptr; + +typedef struct xdef_s { + qfot_type_t *type; ///< pointer to type definition + void *ofs; ///< 32-bit version of ddef_t.ofs +} xdef_t; + +void *PR_FindGlobal (string name) = #0; + +int +main (void) +{ + //FIXME need a simple way to get at a def's meta-data + xdef_t *xdefs = PR_FindGlobal (".xdefs"); + while (xdefs.ofs != &int32_ptr) { + xdefs++; + } + printf ("int32_ptr: %s\n", xdefs.type.encoding); + return xdefs.type.encoding != "{>^i}"; +} From ddc6f6bcb04c2a37c68cf25f8630acc44cfc310b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Jun 2021 20:05:27 +0900 Subject: [PATCH 1616/3664] [qfcc] Un-dereference src expression early for movep The VM has no pointer to direct reference move instruction. Fixes #9 --- tools/qfcc/source/statements.c | 18 +++++++++++------- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/ptrstructcast.r | 22 ++++++++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 tools/qfcc/test/ptrstructcast.r diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index d2ae28e65..959f0f3c6 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -787,9 +787,13 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) } type = st_memset; if (is_indirect (dst_expr)) { - goto dereference_dst; + need_ptr = 1; } } else { + if (is_indirect (src_expr)) { + src_expr = expr_file_line (address_expr (src_expr, 0, 0), e); + need_ptr = 1; + } if (!src) { // This is the very right-hand node of a non-nil assignment chain // (there may be more chains somwhere within src_expr, but they @@ -802,15 +806,15 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) if (op) { *op = src; } - if (is_indirect (dst_expr) || is_indirect (src_expr)) { + if (is_indirect (dst_expr)) { src = operand_address (src, src_expr); - goto dereference_dst; + need_ptr = 1; } } - if (0) { -dereference_dst: - // dst_expr is a dereferenced pointer, so need to un-dereference it - // to get the pointer and switch to storep instructions. + if (need_ptr) { + // dst_expr and/or src_expr are dereferenced pointers, so need to + // un-dereference dst_expr to get the pointer and switch to movep + // or memsetp instructions. dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); need_ptr = 1; } diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 54bb87dcf..15f9b9309 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -34,6 +34,7 @@ test_progs_dat=\ tools/qfcc/test/paramret.dat \ tools/qfcc/test/postop.dat \ tools/qfcc/test/ptraliasenc.dat \ + tools/qfcc/test/ptrstructcast.dat \ tools/qfcc/test/quaternion.dat \ tools/qfcc/test/return-ivar.dat \ tools/qfcc/test/sendv.dat \ @@ -394,6 +395,16 @@ tools/qfcc/test/ptraliasenc.run: $(qfcc_test_run_deps) include $(ptraliasenc_dep) # am--include-marker r_depfiles_remade += $(ptraliasenc_dep) +tools_qfcc_test_ptrstructcast_dat_SOURCES=tools/qfcc/test/ptrstructcast.r +ptrstructcast_obj=$(tools_qfcc_test_ptrstructcast_dat_SOURCES:.r=.o) +ptrstructcast_dep=$(call qcautodep,$(tools_qfcc_test_ptrstructcast_dat_SOURCES)) +tools/qfcc/test/ptrstructcast.dat$(EXEEXT): $(ptrstructcast_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(ptrstructcast_obj) +tools/qfcc/test/ptrstructcast.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(ptrstructcast_dep) # am--include-marker +r_depfiles_remade += $(ptrstructcast_dep) + tools_qfcc_test_quaternion_dat_SOURCES=tools/qfcc/test/quaternion.r quaternion_obj=$(tools_qfcc_test_quaternion_dat_SOURCES:.r=.o) quaternion_dep=$(call qcautodep,$(tools_qfcc_test_quaternion_dat_SOURCES)) diff --git a/tools/qfcc/test/ptrstructcast.r b/tools/qfcc/test/ptrstructcast.r new file mode 100644 index 000000000..36e560d08 --- /dev/null +++ b/tools/qfcc/test/ptrstructcast.r @@ -0,0 +1,22 @@ +typedef struct Point_s { + int x; + int y; +} Point; + +typedef struct Extent_s { + int width; + int height; +} Extent; + +int +foo (Point p) +{ + Extent e = *(Extent *)&p; + return e.width * e.height; +} + +int +main (void) +{ + return foo ({ 6, 7 }) != 42; +} From e81d690b51dc219518078cad6123576f21b50bad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Jul 2021 16:26:07 +0900 Subject: [PATCH 1617/3664] [input] Create QF input library using keys.c This refactors (as such) keys.c so that it no longer depends on console or gib, and pulls keys out of video targets. The eventual plan is to move all high-level general input handling into libQFinput, and probably low-level (eg, /dev/input handling for joysticks etc on Linux). Fixes #8 --- include/QF/console.h | 1 - include/QF/keys.h | 31 ++++- include/QF/plugin/console.h | 2 - libs/Makemodule.am | 1 + libs/console/client.c | 6 +- libs/console/console.c | 7 -- libs/console/menu.c | 2 +- libs/console/server.c | 1 - libs/gib/Makemodule.am | 10 +- libs/gib/gib_keys.c | 77 ++++++++++++ libs/input/Makemodule.am | 8 ++ libs/{video/targets => input}/keys.c | 110 ++++++------------ libs/{video/targets => input}/old_keys.c | 0 libs/ruamoko/Makemodule.am | 13 ++- .../targets/pr_keys.c => ruamoko/rua_keys.c} | 6 +- libs/video/renderer/sw/vid_common_sw.c | 1 - libs/video/renderer/sw32/vid_common_sw32.c | 1 - libs/video/targets/Makemodule.am | 3 - nq/source/Makemodule.am | 3 + nq/source/host.c | 1 + nq/source/sv_ded.c | 5 + qw/source/Makemodule.am | 3 + qw/source/cl_main.c | 1 + ruamoko/qwaq/Makemodule.am | 10 +- ruamoko/qwaq/builtins/main.c | 1 - ruamoko/qwaq/builtins/qwaq-bi.c | 2 +- 26 files changed, 197 insertions(+), 109 deletions(-) create mode 100644 libs/gib/gib_keys.c create mode 100644 libs/input/Makemodule.am rename libs/{video/targets => input}/keys.c (95%) rename libs/{video/targets => input}/old_keys.c (100%) rename libs/{video/targets/pr_keys.c => ruamoko/rua_keys.c} (98%) diff --git a/include/QF/console.h b/include/QF/console.h index 1bb6b164e..b267a7efb 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -97,7 +97,6 @@ void Con_Init (const char *plugin_name); void Con_ExecLine (const char *line); void Con_ProcessInput (void); -void Con_KeyEvent (knum_t key, short unicode, qboolean down); void Con_SetOrMask (int mask); void Con_NewMap (void); diff --git a/include/QF/keys.h b/include/QF/keys.h index f5acbcc61..50dc7ff0f 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -564,6 +564,31 @@ typedef struct keytarget_s { extern int keydown[QFK_LAST]; +/** Callback for handling key events based on keydest. + + \param key The key that was pressed or released for this event. + \param unicode The unicode value of the key. + \param down True if a press event, false if a release event. + \param data Callback specific data pointer as passed to Key_SetKeyDest +*/ +typedef void (*key_event_t) (knum_t key, short unicode, qboolean down, + void *data); + +/** Set the fallback key event handler callback for the specified keydest. + + The fallback is for handling keys that have not been bound, thus allowing + the callback to handle large numbers of keys without having to create many + explicit bindings (eg, console input). + + If no callback has been set for a specific keydest, then the key event + is simply ignored. + + \param keydest The keydest for which the callback will be set. + \param callback The function to be called when an event occurs. + \param data Opaque data pointerer passed to the callback. +*/ +void Key_SetKeyEvent (keydest_t keydest, key_event_t callback, void *data); + struct cbuf_s; void Key_Init (struct cbuf_s *cb); @@ -693,11 +718,15 @@ int Key_StringToKeynum (const char *str) __attribute__((pure)); struct progs_s; +//FIXME location /** Add the Key builtins to the specified progs instance. */ -void Key_Progs_Init (struct progs_s *pr); +void RUA_Key_Init (struct progs_s *pr); #endif +//FIXME location +void GIB_Key_Init (void); + ///@} #endif//__QF_keys_h diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index 7ea0af938..e244ee5c1 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -30,7 +30,6 @@ #include -#include #include #include @@ -38,7 +37,6 @@ typedef struct console_funcs_s { void (*init) (void); void (*print) (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); void (*process_input) (void); - void (*key_event) (knum_t key, short unicode, qboolean down); void (*draw_console) (void); void (*check_resize) (void); void (*new_map) (void); diff --git a/libs/Makemodule.am b/libs/Makemodule.am index a06beabfc..035f65926 100644 --- a/libs/Makemodule.am +++ b/libs/Makemodule.am @@ -6,6 +6,7 @@ include libs/gib/Makemodule.am include libs/audio/Makemodule.am include libs/image/Makemodule.am include libs/models/Makemodule.am +include libs/input/Makemodule.am include libs/video/Makemodule.am include libs/console/Makemodule.am include libs/entity/Makemodule.am diff --git a/libs/console/client.c b/libs/console/client.c index f87180a82..75eab4652 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -445,7 +445,7 @@ C_Print (const char *fmt, va_list args) } static void -C_KeyEvent (knum_t key, short unicode, qboolean down) +C_KeyEvent (knum_t key, short unicode, qboolean down, void *data) { inputline_t *il; @@ -821,6 +821,9 @@ C_Init (void) #endif Key_KeydestCallback (con_keydest_callback); + Key_SetKeyEvent (key_message, C_KeyEvent, 0); + Key_SetKeyEvent (key_menu, C_KeyEvent, 0); + Key_SetKeyEvent (key_console, C_KeyEvent, 0); Menu_Init (); con_notifytime = Cvar_Get ("con_notifytime", "3", CVAR_NONE, NULL, @@ -946,7 +949,6 @@ static general_funcs_t plugin_info_general_funcs = { static console_funcs_t plugin_info_console_funcs = { .print = C_Print, .process_input = C_ProcessInput, - .key_event = C_KeyEvent, .draw_console = C_DrawConsole, .check_resize = C_CheckResize, .new_map = C_NewMap, diff --git a/libs/console/console.c b/libs/console/console.c index 4fd314b3f..6e0153f49 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -172,13 +172,6 @@ Con_ProcessInput (void) } } -VISIBLE void -Con_KeyEvent (knum_t key, short unicode, qboolean down) -{ - if (con_module) - con_module->functions->console->key_event (key, unicode, down); -} - VISIBLE void Con_SetOrMask (int mask) { diff --git a/libs/console/menu.c b/libs/console/menu.c index 23d99c181..b635fcfaa 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -587,7 +587,7 @@ Menu_Init (void) RUA_Init (&menu_pr_state, 1); InputLine_Progs_Init (&menu_pr_state); - Key_Progs_Init (&menu_pr_state); + RUA_Key_Init (&menu_pr_state); GIB_Progs_Init (&menu_pr_state); PR_Cmds_Init (&menu_pr_state); R_Progs_Init (&menu_pr_state); diff --git a/libs/console/server.c b/libs/console/server.c index 6bbae8a6a..8fc577420 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -793,7 +793,6 @@ static general_data_t plugin_info_general_data; static console_funcs_t plugin_info_console_funcs = { .print = C_Print, .process_input = C_ProcessInput, - .key_event = C_KeyEvent, .draw_console = C_DrawConsole, .check_resize = C_CheckResize, .new_map = C_NewMap, diff --git a/libs/gib/Makemodule.am b/libs/gib/Makemodule.am index e0fbe14c2..5773bbafd 100644 --- a/libs/gib/Makemodule.am +++ b/libs/gib/Makemodule.am @@ -2,7 +2,9 @@ gib_deps= \ libs/ruamoko/libQFruamoko.la \ libs/util/libQFutil.la -lib_LTLIBRARIES += libs/gib/libQFgib.la +lib_LTLIBRARIES += \ + libs/gib/libQFgib.la \ + libs/gib/libQFgib_client.la libs_gib_libQFgib_la_LDFLAGS= $(lib_ldflags) libs_gib_libQFgib_la_LIBADD= $(gib_deps) @@ -27,3 +29,9 @@ libs_gib_libQFgib_la_SOURCES= \ libs/gib/ops.c \ libs/gib/exp.c \ libs/gib/regex.c + +libs_gib_libQFgib_client_la_LDFLAGS= $(lib_ldflags) +libs_gib_libQFgib_client_la_LIBADD= libs/gib/libQFgib.la +libs_gib_libQFgib_client_la_DEPENDENCIES= libs/gib/libQFgib.la ${gib_deps} +libs_gib_libQFgib_client_la_SOURCES= \ + libs/gib/gib_keys.c diff --git a/libs/gib/gib_keys.c b/libs/gib/gib_keys.c new file mode 100644 index 000000000..5cbb095ff --- /dev/null +++ b/libs/gib/gib_keys.c @@ -0,0 +1,77 @@ +/* + gib_keys.c + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2002 Brian Koropoff + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cbuf.h" +#include "QF/cmd.h" +#include "QF/keys.h" +#include "QF/sys.h" +#include "QF/gib.h" + +#include "compat.h" +#include "old_keys.h" + +static void +Key_GIB_Bind_Get_f (void) +{ + const char *key, *cmd; + imt_t *imt; + int k; + + if (GIB_Argc () != 2) { + GIB_USAGE ("key"); + return; + } + + key = OK_TranslateKeyName (GIB_Argv (1)); + + if ((k = Key_StringToKeynum (key)) == -1) { + GIB_Error ("bind", "bind::get: invalid key %s", key); + return; + } + + imt = Key_FindIMT ("imt_mod"); + if (!imt || !(cmd = Key_GetBinding (imt, k))) + GIB_Return (""); + else + GIB_Return (cmd); +} + +void +GIB_Key_Init (void) +{ + GIB_Builtin_Add ("bind::get", Key_GIB_Bind_Get_f); +} diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am new file mode 100644 index 000000000..407eabd11 --- /dev/null +++ b/libs/input/Makemodule.am @@ -0,0 +1,8 @@ +lib_LTLIBRARIES += libs/input/libQFinput.la + +libs_input_libQFinput_la_LDFLAGS= $(lib_ldflags) +libs_input_libQFinput_la_LIBADD= $(input_deps) +libs_input_libQFinput_la_DEPENDENCIES= $(input_deps) +libs_input_libQFinput_la_SOURCES= \ + libs/input/keys.c \ + libs/input/old_keys.c diff --git a/libs/video/targets/keys.c b/libs/input/keys.c similarity index 95% rename from libs/video/targets/keys.c rename to libs/input/keys.c index 4d5c57e27..1f860f081 100644 --- a/libs/video/targets/keys.c +++ b/libs/input/keys.c @@ -41,22 +41,14 @@ #include "QF/cbuf.h" #include "QF/cmd.h" -#include "QF/console.h" -#include "QF/csqc.h" #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/keys.h" -#include "QF/screen.h" #include "QF/sys.h" -#include "QF/zone.h" -#include "QF/gib.h" #include "compat.h" #include "old_keys.h" -#define U __attribute__ ((used)) -static U void (*const key_progs_init)(struct progs_s *) = Key_Progs_Init; -#undef U - /* key up events are sent even if in console mode */ static keydest_t key_dest = key_console; @@ -669,21 +661,6 @@ Key_Game (knum_t key, short unicode) return false; } -/* - Key_Console - - Interactive line editing and console scrollback -*/ -static void -Key_Console (knum_t key, short unicode) -{ - // escape is un-bindable - if (keydown[key] == 1 && key && Key_Game (key, unicode)) - return; - - Con_KeyEvent (key, unicode, keydown[key]); -} - VISIBLE int Key_StringToKeynum (const char *str) { @@ -957,32 +934,6 @@ Key_Bind_f (void) } } -static void -Key_GIB_Bind_Get_f (void) -{ - const char *key, *cmd; - imt_t *imt; - int k; - - if (GIB_Argc () != 2) { - GIB_USAGE ("key"); - return; - } - - key = OK_TranslateKeyName (GIB_Argv (1)); - - if ((k = Key_StringToKeynum (key)) == -1) { - GIB_Error ("bind", "bind::get: invalid key %s", key); - return; - } - - imt = Key_FindIMT ("imt_mod"); - if (!imt || !(cmd = Key_GetBinding (imt, k))) - GIB_Return (""); - else - GIB_Return (cmd); -} - static void in_key_togglemenu_f (cvar_t *var) { @@ -1165,6 +1116,19 @@ keyhelp_f (void) keyhelp = 1; } +static key_event_t key_event_handlers[key_last] = { }; +static void *key_event_data[key_last] = { }; + +VISIBLE void +Key_SetKeyEvent (keydest_t keydest, key_event_t callback, void *data) +{ + if (keydest < 0 || keydest >= key_last) { + Sys_Error ("Key_SetKeyEvent: invalid keydest: %d", keydest); + } + key_event_handlers[keydest] = callback; + key_event_data[keydest] = data; +} + /* Key_Event @@ -1188,32 +1152,29 @@ Key_Event (knum_t key, short unicode, qboolean down) keydown[key] = 0; } - // handle escape specially, so the user can never unbind it - if (key == key_togglemenu || key == key_toggleconsole) { - Key_Console (key, unicode); + // handle menu and console toggle keys specially so the user can never + // override or unbind them + //FIXME maybe still a tad over-coupled. Use callbacks for menu and console + //toggles? Should keys know anything about menu and console? + if (key_dest != key_menu && key == key_togglemenu && keydown[key] == 1) { + Cbuf_AddText (cbuf, "togglemenu"); + return; + } else if (key_dest != key_console && key == key_toggleconsole + && keydown[key] == 1) { + Cbuf_AddText (cbuf, "toggleconsole"); return; } - if (!down && Key_Game (key, unicode)) - return; - - // if not a consolekey, send to the interpreter no matter what mode is - switch (key_dest) { - case key_game: - case key_demo: - Key_Game (key, unicode); - return; - case key_message: - case key_menu: - case key_console: - Key_Console (key, unicode); - return; - case key_unfocused: - return; - case key_last: - break; // should not happen, so hit the error + if (key_dest < 0 || key_dest >= key_last) { + Sys_Error ("Bad key_dest"); + } + + if (!Key_Game (key, unicode)) { + if (key_event_handlers[key_dest]) { + key_event_handlers[key_dest] (key, unicode, down, + key_event_data[key_dest]); + } } - Sys_Error ("Bad key_dest"); } VISIBLE void @@ -1344,9 +1305,6 @@ Key_Init (cbuf_t *cb) Cmd_AddCommand ("keyhelp", keyhelp_f, "display the keyname for the next " "RECOGNIZED key-press. If the key pressed produces no " "output, " PACKAGE_NAME " does not recognise that key."); - - GIB_Builtin_Add ("bind::get", Key_GIB_Bind_Get_f); - } void @@ -1371,7 +1329,7 @@ Key_GetBinding (imt_t *imt, knum_t key) VISIBLE void Key_SetKeyDest(keydest_t kd) { - if ((int) kd < key_unfocused || kd >= key_last) { + if (kd < 0 || kd >= key_last) { Sys_Error ("Bad key_dest: %d", kd); } Sys_MaskPrintf (SYS_input, "Key_SetKeyDest: %s\n", keydest_names[kd]); diff --git a/libs/video/targets/old_keys.c b/libs/input/old_keys.c similarity index 100% rename from libs/video/targets/old_keys.c rename to libs/input/old_keys.c diff --git a/libs/ruamoko/Makemodule.am b/libs/ruamoko/Makemodule.am index e684d1391..6274c75e7 100644 --- a/libs/ruamoko/Makemodule.am +++ b/libs/ruamoko/Makemodule.am @@ -2,7 +2,9 @@ ruamoko_rua_libs= \ libs/gamecode/libQFgamecode.la \ libs/util/libQFutil.la -lib_LTLIBRARIES += libs/ruamoko/libQFruamoko.la +lib_LTLIBRARIES += \ + libs/ruamoko/libQFruamoko.la \ + libs/ruamoko/libQFruamoko_client.la libs_ruamoko_libQFruamoko_la_LDFLAGS= $(lib_ldflags) libs_ruamoko_libQFruamoko_la_LIBADD= $(ruamoko_rua_libs) @@ -25,3 +27,12 @@ libs_ruamoko_libQFruamoko_la_SOURCES= \ libs/ruamoko/rua_set.c \ libs/ruamoko/rua_stdlib.c \ libs/ruamoko/rua_string.c + +libs_ruamoko_libQFruamoko_client_la_LDFLAGS= $(lib_ldflags) +libs_ruamoko_libQFruamoko_client_la_LIBADD= \ + libs/ruamoko/libQFruamoko.la +libs_ruamoko_libQFruamoko_client_la_DEPENDENCIES= \ + libs/ruamoko/libQFruamoko.la \ + $(ruamoko_rua_libs) +libs_ruamoko_libQFruamoko_client_la_SOURCES= \ + libs/ruamoko/rua_keys.c diff --git a/libs/video/targets/pr_keys.c b/libs/ruamoko/rua_keys.c similarity index 98% rename from libs/video/targets/pr_keys.c rename to libs/ruamoko/rua_keys.c index b72eb006e..fbd978071 100644 --- a/libs/video/targets/pr_keys.c +++ b/libs/ruamoko/rua_keys.c @@ -1,7 +1,7 @@ /* - bi_keys.c + rua_keys.c - CSQC key-api builtins + Ruamoko key-api builtins Copyright (C) 1996-1997 Id Software, Inc. @@ -168,7 +168,7 @@ static builtin_t builtins[] = { }; void -Key_Progs_Init (progs_t *pr) +RUA_Key_Init (progs_t *pr) { PR_RegisterBuiltins (pr, builtins); } diff --git a/libs/video/renderer/sw/vid_common_sw.c b/libs/video/renderer/sw/vid_common_sw.c index a01992204..f67a4ce8b 100644 --- a/libs/video/renderer/sw/vid_common_sw.c +++ b/libs/video/renderer/sw/vid_common_sw.c @@ -31,7 +31,6 @@ #include #include -#include "QF/console.h" #include "QF/mathlib.h" #include "QF/sys.h" #include "QF/vid.h" diff --git a/libs/video/renderer/sw32/vid_common_sw32.c b/libs/video/renderer/sw32/vid_common_sw32.c index 943fb2708..5bc9fbc47 100644 --- a/libs/video/renderer/sw32/vid_common_sw32.c +++ b/libs/video/renderer/sw32/vid_common_sw32.c @@ -28,7 +28,6 @@ # include "config.h" #endif -#include "QF/console.h" #include "QF/cvar.h" #include "QF/mathlib.h" #include "QF/qargs.h" diff --git a/libs/video/targets/Makemodule.am b/libs/video/targets/Makemodule.am index 710a77c82..ebee7b19f 100644 --- a/libs/video/targets/Makemodule.am +++ b/libs/video/targets/Makemodule.am @@ -58,9 +58,6 @@ EXTRA_libs_video_targets_libQFjs_la_SOURCES= $(joy_linux_src) $(joy_win_src) $(j libs_video_targets_libvid_common_la_SOURCES = \ libs/video/targets/in_common.c \ libs/video/targets/in_event.c \ - libs/video/targets/keys.c \ - libs/video/targets/old_keys.c \ - libs/video/targets/pr_keys.c \ libs/video/targets/vid.c libs_video_targets_libvid_common_la_CFLAGS= @PREFER_NON_PIC@ libs_video_targets_libvid_common_la_LDFLAGS= @STATIC@ diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index e35b36737..a757a63ea 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -45,6 +45,8 @@ nq_cl_plugin_LIBS= \ @client_static_plugin_libs@ nq_client_LIBFILES= \ + libs/gib/libQFgib_client.la \ + libs/ruamoko/libQFruamoko_client.la \ libs/entity/libQFentity.la \ libs/video/targets/libQFjs.la \ libs/audio/libQFcd.la \ @@ -62,6 +64,7 @@ nq_common_LIBFILES= \ libs/ruamoko/libQFruamoko.la \ libs/gamecode/libQFgamecode.la \ libs/ui/libQFui.la \ + libs/input/libQFinput.la \ libs/util/libQFutil.la nq_client_LIBS= $(nq_client_LIBFILES) $(nq_common_LIBFILES) diff --git a/nq/source/host.c b/nq/source/host.c index 9f6b098d0..53c1e3311 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -864,6 +864,7 @@ Host_Init (void) Sys_Init (); GIB_Init (true); + GIB_Key_Init (); COM_ParseConfig (host_cbuf); Host_Init_Memory (); diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index f79659f57..0d80842e2 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -53,6 +53,11 @@ int viewentity; vid_render_data_t *r_data; vid_render_funcs_t *r_funcs; +void +GIB_Key_Init (void) +{ +} + void Key_KeydestCallback (keydest_callback_t *callback) { diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index ef6e32ff5..68d62a005 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -87,6 +87,8 @@ qw_cl_plugin_LIBS= \ qw_client_LIBS= \ libs/qw/libqw.a \ + libs/gib/libQFgib_client.la \ + libs/ruamoko/libQFruamoko_client.la \ libs/net/libnet_chan.la \ libs/entity/libQFentity.la \ libs/console/libQFconsole.la \ @@ -97,6 +99,7 @@ qw_client_LIBS= \ libs/gib/libQFgib.la \ libs/ruamoko/libQFruamoko.la \ libs/ui/libQFui.la \ + libs/input/libQFinput.la \ libs/util/libQFutil.la qw_client_libs= qw/source/libqw_client.a qw/source/libqw_common.a \ libs/client/libQFclient.la diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 7199dbb38..e00a17d17 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1771,6 +1771,7 @@ Host_Init (void) Sys_Init (); GIB_Init (true); + GIB_Key_Init (); COM_ParseConfig (cl_cbuf); CL_Init_Memory (); diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 336a79050..d7f3d86b4 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -42,12 +42,9 @@ qwaq_app_dat_src= \ ruamoko/qwaq/ui/view.r \ ruamoko/qwaq/ui/window.r -#FIXME this coupling is horrible qwaq_curses_libs= \ - libs/video/targets/libvid_common.la \ - libs/console/libQFconsole.la \ libs/ui/libQFui.la \ - libs/gib/libQFgib.la + libs/input/libQFinput.la ruamoko_qwaq_qwaq_curses_SOURCES= \ ruamoko/qwaq/builtins/main.c \ @@ -68,6 +65,7 @@ qwaq_client_libs= \ $(top_builddir)/libs/entity/libQFentity.la \ $(top_builddir)/libs/console/libQFconsole.la \ $(top_builddir)/libs/ui/libQFui.la \ + $(top_builddir)/libs/input/libQFinput.la \ $(top_builddir)/libs/video/targets/libQFjs.la \ $(top_builddir)/libs/audio/libQFcd.la \ $(top_builddir)/libs/audio/libQFsound.la \ @@ -75,11 +73,11 @@ qwaq_client_libs= \ qwaq_x11_libs= \ $(qwaq_cl_plugin_libs) \ + ${top_builddir}/libs/ruamoko/libQFruamoko_client.la \ $(top_builddir)/libs/video/renderer/libQFrenderer.la \ $(top_builddir)/libs/models/libQFmodels.la \ $(top_builddir)/libs/video/targets/libQFx11.la \ - $(qwaq_client_libs) \ - $(top_builddir)/libs/gib/libQFgib.la + $(qwaq_client_libs) ruamoko_qwaq_qwaq_x11_SOURCES=ruamoko/qwaq/builtins/qwaq.c ruamoko/qwaq/builtins/qwaq-bi.c ruamoko_qwaq_qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \ $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 733dda6b6..9becb4fcd 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -386,7 +386,6 @@ common_builtins_init (progs_t *pr) } static progsinit_f main_app[] = { - Key_Progs_Init, BI_Init, common_builtins_init, QWAQ_EditBuffer_Init, diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c index d3db5917a..4d296ad73 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/qwaq-bi.c @@ -195,7 +195,7 @@ BI_Init (progs_t *pr) Mod_Init (); R_Init (); R_Progs_Init (pr); - Key_Progs_Init (pr); + RUA_Key_Init (pr); S_Progs_Init (pr); Con_Init ("client"); From 490cf966f9baf48ea4498798cac43e623f85011e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 6 Jul 2021 11:53:17 +0900 Subject: [PATCH 1618/3664] [vulkan] Fix compiling on 32-bit systems Casting between ints and pointers can be awkward. --- include/QF/Vulkan/debug.h | 2 +- libs/video/renderer/vulkan/test/test-staging.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/QF/Vulkan/debug.h b/include/QF/Vulkan/debug.h index 1e25930d0..482680eb7 100644 --- a/include/QF/Vulkan/debug.h +++ b/include/QF/Vulkan/debug.h @@ -1,7 +1,7 @@ #ifndef __QF_Vulkan_debug_h #define __QF_Vulkan_debug_h -#if defined(_WIN32) && !defined(_WIN64) +#if (defined(_WIN32) && !defined(_WIN64)) || (__WORDSIZE < 64) #define QFV_duCmdBeginLabel(device, cmd, name...) #define QFV_duCmdEndLabel(device, cmd) #define QFV_duCmdInsertLabel(device, cmd, name...) diff --git a/libs/video/renderer/vulkan/test/test-staging.c b/libs/video/renderer/vulkan/test/test-staging.c index df0b7e282..4eb5b8f58 100644 --- a/libs/video/renderer/vulkan/test/test-staging.c +++ b/libs/video/renderer/vulkan/test/test-staging.c @@ -77,7 +77,7 @@ vkWaitForFences (VkDevice device, uint32_t fenceCount, const VkFence *fences, VkBool32 waitAll, uint64_t timeout) { for (uint32_t i = 0; i < fenceCount; i++) { - int *f = (int *)fences[i]; + int *f = (int *) (intptr_t) fences[i]; if (*f) { wait_count++; } @@ -90,7 +90,7 @@ static VkResult vkResetFences (VkDevice device, uint32_t fenceCount, const VkFence *fences) { for (uint32_t i = 0; i < fenceCount; i++) { - int *f = (int *)fences[i]; + int *f = (int *) (intptr_t) fences[i]; *f = 0; } return VK_SUCCESS; @@ -99,7 +99,7 @@ vkResetFences (VkDevice device, uint32_t fenceCount, const VkFence *fences) static VkResult vkGetFenceStatus (VkDevice device, VkFence fence) { - int *f = (int *)fence; + int *f = (int *) (intptr_t) fence; return *f ? VK_SUCCESS : VK_NOT_READY; } @@ -133,7 +133,7 @@ static VkResult vkQueueSubmit (VkQueue queue, uint32_t count, const VkSubmitInfo *submits, VkFence fence) { - int *f = (int *)fence; + int *f = (int *) (intptr_t) fence; *f = 1; return VK_SUCCESS; } From ae58a8ba5dc94ab8604c61b7b1e46c94fd650bc6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 6 Jul 2021 11:55:29 +0900 Subject: [PATCH 1619/3664] [qwaq] Create a commandline-only version of qwaq qwaq-curses has its place, but its use for running vkgen was really a placeholder because I didn't feel like sorting out the different initialization requirements at the time. qwaq-cmd has the (currently unnecessary) threading power of qwaq-curses, but doesn't include any UI stuff and thus doesn't need curses. The work also paves the way for qwaq-x11 to become a proper engine (though sorting out its init will be taken care of later). Fixes #15. --- Makefile.am | 2 +- config.d/build_control.m4 | 7 +- libs/console/server.c | 14 +-- libs/video/renderer/Makemodule.am | 7 +- libs/video/renderer/vulkan/vulkan_lighting.c | 1 + ruamoko/qwaq/Makemodule.am | 20 +++- ruamoko/qwaq/builtins/main.c | 120 +++++++------------ ruamoko/qwaq/builtins/qwaq-cmd.c | 91 ++++++++++++++ ruamoko/qwaq/builtins/qwaq-curses.c | 99 +++++++++++++++ ruamoko/qwaq/qwaq.h | 4 + 10 files changed, 270 insertions(+), 95 deletions(-) create mode 100644 ruamoko/qwaq/builtins/qwaq-cmd.c create mode 100644 ruamoko/qwaq/builtins/qwaq-curses.c diff --git a/Makefile.am b/Makefile.am index 176c52434..2187fb642 100644 --- a/Makefile.am +++ b/Makefile.am @@ -69,7 +69,7 @@ XMMS_LIBS= @XMMS_LIBS@ PAK=$(top_builddir)/pak$(EXEEXT) QFCC_DEP=qfcc$(EXEEXT) QFCC=$(top_builddir)/$(QFCC_DEP) -QWAQ_CURSES=$(top_builddir)/ruamoko/qwaq/qwaq-curses$(EXEEXT) +QWAQ=$(top_builddir)/ruamoko/qwaq/qwaq-cmd$(EXEEXT) GZ=@progs_gz@ diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 23fff6d90..c67317496 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -276,8 +276,13 @@ if test "x$ENABLE_tools_qfvis" = xyes; then QF_NEED(libs,[util]) fi if test "x$ENABLE_tools_qwaq" = xyes; then - if test "x$HAVE_PANEL" = xyes -a "x$HAVE_PTHREAD" = xyes; then + if test "x$HAVE_NCURSES" == "xyes" -a "x$HAVE_PANEL" = xyes -a "x$HAVE_PTHREAD" = xyes; then QWAQ_TARGETS="$QWAQ_TARGETS ruamoko/qwaq/qwaq-curses\$(EXEEXT)" + dnl FIXME move key code (maybe to ui?) + QF_NEED(vid, [common]) + fi + if test "x$HAVE_PTHREAD" = xyes; then + QWAQ_TARGETS="$QWAQ_TARGETS ruamoko/qwaq/qwaq-cmd\$(EXEEXT)" fi QF_NEED(tools,[qfcc]) QF_NEED(ruamoko,[qwaq]) diff --git a/libs/console/server.c b/libs/console/server.c index 8fc577420..9f7ff0cc1 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -85,10 +85,10 @@ static QFile *log_file; static cvar_t *sv_logfile; static cvar_t *sv_conmode; -static void C_KeyEvent (knum_t key, short unicode, qboolean down); - #ifdef HAVE_NCURSES +static void key_event (knum_t key, short unicode, qboolean down); + enum { sv_resize_x = 1, sv_resize_y = 2, @@ -465,7 +465,7 @@ process_input (void) if (ch < 0 || ch >= 256) ch = 0; } - C_KeyEvent (ch, 0, 1); + key_event (ch, 0, 1); } } @@ -757,14 +757,6 @@ C_ProcessInput (void) } } -static void -C_KeyEvent (knum_t key, short unicode, qboolean down) -{ -#ifdef HAVE_NCURSES - key_event (key, unicode, down); -#endif -} - static void C_DrawConsole (void) { diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index c07f98fcc..37b0f5a72 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -284,7 +284,7 @@ libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vksh libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${renderpass_gen} -qwaq_curses = $(top_builddir)/ruamoko/qwaq/qwaq-curses$(EXEEXT) +qwaq_cmd = $(top_builddir)/ruamoko/qwaq/qwaq-cmd$(EXEEXT) vkparse_cinc = $(top_builddir)/libs/video/renderer/vulkan/vkparse.cinc vkparse_hinc = $(top_builddir)/libs/video/renderer/vulkan/vkparse.hinc vkparse_src = \ @@ -409,8 +409,8 @@ V_VKGEN_ = $(V_VKGEN_@AM_DEFAULT_V@) V_VKGEN_0 = @echo " VKGEN " $@; V_VKGEN_1 = -$(vkparse_cinc): $(vkgen) $(qwaq_curses) $(vkparse_plist) - $(V_VKGEN)$(QWAQ_CURSES) $(vkgen) -- $(vkparse_plist) $(vkparse_cinc).t $(vkparse_hinc).t &&\ +$(vkparse_cinc): $(vkgen) $(qwaq_cmd) $(vkparse_plist) + $(V_VKGEN)$(QWAQ) $(vkgen) -- $(vkparse_plist) $(vkparse_cinc).t $(vkparse_hinc).t &&\ $(am__mv) $(vkparse_cinc).t $(vkparse_cinc) &&\ $(am__mv) $(vkparse_hinc).t $(vkparse_hinc) @@ -418,7 +418,6 @@ $(vkparse_hinc): $(vkparse_cinc) # do nothing: hinc generated at the same time as cinc CLEANFILES += \ - $(top_builddir)/qwaq-curses.log \ libs/video/renderer/glsl/*.vc \ libs/video/renderer/glsl/*.fc \ libs/video/renderer/glsl/*.slc \ diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index deb56c1c4..c24a2ee35 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -768,6 +768,7 @@ create_view (VkImage image, int baseLayer, int data, int id, vulkan_ctx_t *ctx) QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, view, va (ctx->va_ctx, "iview:shadowmap:%s:%d", viewtype, id)); + (void) viewtype;//silence unused warning when vulkan debug disabled return view; } diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index d7f3d86b4..b4a6cedf5 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -51,13 +51,25 @@ ruamoko_qwaq_qwaq_curses_SOURCES= \ ruamoko/qwaq/builtins/curses.c \ ruamoko/qwaq/builtins/debug.c \ ruamoko/qwaq/builtins/editbuffer.c \ - ruamoko/qwaq/builtins/input.c + ruamoko/qwaq/builtins/input.c \ + ruamoko/qwaq/builtins/qwaq-curses.c ruamoko_qwaq_qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ $(PANEL_LIBS) $(NCURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) ruamoko_qwaq_qwaq_curses_LDFLAGS= ruamoko_qwaq_qwaq_curses_DEPENDENCIES= $(qwaq_curses_libs) $(QWAQ_DEPS) +qwaq_cmd_libs= + +ruamoko_qwaq_qwaq_cmd_SOURCES= \ + ruamoko/qwaq/builtins/main.c \ + ruamoko/qwaq/builtins/qwaq-cmd.c + +ruamoko_qwaq_qwaq_cmd_LDADD= $(qwaq_cmd_libs) $(QWAQ_LIBS) \ + $(PTHREAD_LDFLAGS) $(DL_LIBS) +ruamoko_qwaq_qwaq_cmd_LDFLAGS= +ruamoko_qwaq_qwaq_cmd_DEPENDENCIES= $(qwaq_cmd_libs) $(QWAQ_DEPS) + qwaq_cl_plugin_libs= \ @client_static_plugin_libs@ @@ -109,7 +121,11 @@ ruamoko/qwaq/z-transform.dat$(EXEEXT): $(ruamoko_qwaq_z_transform_obj) $(QFCC_DE include $(ruamoko_qwaq_z_transform_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_z_transform_dep) -EXTRA_PROGRAMS += ruamoko/qwaq/qwaq-curses ruamoko/qwaq/qwaq-x11 +EXTRA_PROGRAMS += \ + ruamoko/qwaq/qwaq-cmd \ + ruamoko/qwaq/qwaq-curses \ + ruamoko/qwaq/qwaq-x11 + EXTRA_DIST += \ $(qwaq_dat_src) \ ruamoko/qwaq/debugger/debug.h \ diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 9becb4fcd..f61e31ede 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -77,7 +77,7 @@ static const char *short_options = "-" // magic option parsing mode doohicky (must come first) ; -struct DARRAY_TYPE(qwaq_thread_t *) thread_data; +qwaq_thread_set_t thread_data; static QFile * open_file (const char *path, int *len) @@ -148,6 +148,47 @@ init_qf (void) PR_Opcode_Init (); } +static void +bi_printf (progs_t *pr) +{ + const char *fmt = P_GSTRING (pr, 0); + int count = pr->pr_argc - 1; + pr_type_t **args = pr->pr_params + 1; + dstring_t *dstr = dstring_new (); + + PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); + if (dstr->str) { + Sys_Printf ("%s", dstr->str); + } + dstring_delete (dstr); +} + +static void +bi_traceon (progs_t *pr) +{ + pr->pr_trace = true; + pr->pr_trace_depth = pr->pr_depth; +} + +static void +bi_traceoff (progs_t *pr) +{ + pr->pr_trace = false; +} + +static builtin_t common_builtins[] = { + {"printf", bi_printf, -1}, + {"traceon", bi_traceon, -1}, + {"traceoff", bi_traceoff, -1}, + {}, +}; + +static void +common_builtins_init (progs_t *pr) +{ + PR_RegisterBuiltins (pr, common_builtins); +} + static progs_t * create_progs (qwaq_thread_t *thread) { @@ -163,6 +204,7 @@ create_progs (qwaq_thread_t *thread) PR_Init_Cvars (); PR_Init (pr); RUA_Init (pr, 0); + common_builtins_init (pr); while (*funcs) { (*funcs++) (pr); } @@ -344,60 +386,6 @@ done: return qargs_ind; } -static void -bi_printf (progs_t *pr) -{ - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; - dstring_t *dstr = dstring_new (); - - PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); - if (dstr->str) { - Sys_Printf ("%s", dstr->str); - } - dstring_delete (dstr); -} - -static void -bi_traceon (progs_t *pr) -{ - pr->pr_trace = true; - pr->pr_trace_depth = pr->pr_depth; -} - -static void -bi_traceoff (progs_t *pr) -{ - pr->pr_trace = false; -} - -static builtin_t common_builtins[] = { - {"printf", bi_printf, -1}, - {"traceon", bi_traceon, -1}, - {"traceoff", bi_traceoff, -1}, - {}, -}; - -static void -common_builtins_init (progs_t *pr) -{ - PR_RegisterBuiltins (pr, common_builtins); -} - -static progsinit_f main_app[] = { - BI_Init, - common_builtins_init, - QWAQ_EditBuffer_Init, - QWAQ_Debug_Init, - 0 -}; - -static progsinit_f target_app[] = { - common_builtins_init, - QWAQ_DebugTarget_Init, - 0 -}; int main (int argc, char **argv) @@ -454,27 +442,7 @@ main (int argc, char **argv) DARRAY_APPEND (&thread_data, thread); } - for (size_t i = 1, thread_ind = 0; i < thread_data.size; i++) { - qwaq_thread_t *thread = thread_data.a[i]; - progsinit_f *app_funcs = target_app; - - if (thread->args.size && thread->args.a[0] - && strcmp (thread->args.a[0], "--qargs")) { - // skip the args set that's passed to qargs - continue; - } - if (thread_ind < thread_data.a[0]->args.size) { - thread->args.a[0] = thread_data.a[0]->args.a[thread_ind++]; - } else { - printf ("ignoring extra arg sets\n"); - break; - } - if (main_ind < 0) { - main_ind = i; - app_funcs = main_app; - } - thread->progsinit = app_funcs; - } + main_ind = qwaq_init_threads (&thread_data); if (main_ind >= 0) { // threads might start new threads before the end is reached size_t count = thread_data.size; diff --git a/ruamoko/qwaq/builtins/qwaq-cmd.c b/ruamoko/qwaq/builtins/qwaq-cmd.c new file mode 100644 index 000000000..0f31f362e --- /dev/null +++ b/ruamoko/qwaq/builtins/qwaq-cmd.c @@ -0,0 +1,91 @@ +/* + #FILENAME# + + Qwaq + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2001/06/01 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "QF/cbuf.h" +#include "QF/cmd.h" +#include "QF/cvar.h" +#include "QF/gib.h" +#include "QF/idparse.h" +#include "QF/keys.h" +#include "QF/progs.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/ruamoko.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/zone.h" + +#include "compat.h" + +#include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/debugger/debug.h" + +static progsinit_f main_app[] = { + 0 +}; + +int +qwaq_init_threads (qwaq_thread_set_t *thread_data) +{ + int main_ind = -1; + + for (size_t i = 1, thread_ind = 0; i < thread_data->size; i++) { + qwaq_thread_t *thread = thread_data->a[i]; + progsinit_f *app_funcs = main_app; + + if (thread->args.size && thread->args.a[0] + && strcmp (thread->args.a[0], "--qargs")) { + // skip the args set that's passed to qargs + continue; + } + if (thread_ind < thread_data->a[0]->args.size) { + thread->args.a[0] = thread_data->a[0]->args.a[thread_ind++]; + } else { + printf ("ignoring extra arg sets\n"); + break; + } + if (main_ind < 0) { + main_ind = i; + app_funcs = main_app; + } + thread->progsinit = app_funcs; + } + return main_ind; +} diff --git a/ruamoko/qwaq/builtins/qwaq-curses.c b/ruamoko/qwaq/builtins/qwaq-curses.c new file mode 100644 index 000000000..717617762 --- /dev/null +++ b/ruamoko/qwaq/builtins/qwaq-curses.c @@ -0,0 +1,99 @@ +/* + #FILENAME# + + Qwaq + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2001/06/01 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "QF/cbuf.h" +#include "QF/cmd.h" +#include "QF/cvar.h" +#include "QF/gib.h" +#include "QF/idparse.h" +#include "QF/keys.h" +#include "QF/progs.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/ruamoko.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/zone.h" + +#include "compat.h" + +#include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/debugger/debug.h" + +static progsinit_f main_app[] = { + BI_Init, + QWAQ_EditBuffer_Init, + QWAQ_Debug_Init, + 0 +}; + +static progsinit_f target_app[] = { + QWAQ_DebugTarget_Init, + 0 +}; + +int +qwaq_init_threads (qwaq_thread_set_t *thread_data) +{ + int main_ind = -1; + + for (size_t i = 1, thread_ind = 0; i < thread_data->size; i++) { + qwaq_thread_t *thread = thread_data->a[i]; + progsinit_f *app_funcs = target_app; + + if (thread->args.size && thread->args.a[0] + && strcmp (thread->args.a[0], "--qargs")) { + // skip the args set that's passed to qargs + continue; + } + if (thread_ind < thread_data->a[0]->args.size) { + thread->args.a[0] = thread_data->a[0]->args.a[thread_ind++]; + } else { + printf ("ignoring extra arg sets\n"); + break; + } + if (main_ind < 0) { + main_ind = i; + app_funcs = main_app; + } + thread->progsinit = app_funcs; + } + return main_ind; +} diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index dc7b6f668..8ef009e8c 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -21,9 +21,13 @@ typedef struct qwaq_thread_s { void *data; } qwaq_thread_t; +typedef struct qwaq_thread_set_s DARRAY_TYPE(qwaq_thread_t *) qwaq_thread_set_t; + void BI_Init (progs_t *pr); void QWAQ_EditBuffer_Init (progs_t *pr); extern struct cbuf_s *qwaq_cbuf; qwaq_thread_t *create_thread (void *(*thread_func) (qwaq_thread_t *), void *); +int qwaq_init_threads (qwaq_thread_set_t *thread_data); + #endif//__qwaq_h From f18e1366babf9a7f187a92345bd904c41f52b6bb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 6 Jul 2021 12:27:21 +0900 Subject: [PATCH 1620/3664] [vulkan] Silence vkgen's debug output It was hidden by qwaq-curses, but the switch to using qwaq-cmd made it pretty obvious. --- libs/video/renderer/vulkan/vkgen/vkenum.r | 2 +- .../video/renderer/vulkan/vkgen/vkfieldauto.r | 2 +- libs/video/renderer/vulkan/vkgen/vkgen.r | 28 +++++++++---------- libs/video/renderer/vulkan/vkgen/vkstruct.r | 2 +- ruamoko/qwaq/builtins/main.c | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index c51fcbfac..e9fa4bc87 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -50,7 +50,7 @@ typedef enum VkBool32 { { string name = [self name]; if (!Hash_Find (processed_types, name)) { - printf (" +%s\n", name); + //printf (" +%s\n", name); Hash_Add (processed_types, (void *) name); [queue addObject: self]; } diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldauto.r b/libs/video/renderer/vulkan/vkgen/vkfieldauto.r index dab844c92..ee3d79535 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldauto.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldauto.r @@ -17,7 +17,7 @@ -writeParseData { - printf("FieldDef: '%s' '%s'\n", struct_name, field_name); + //printf("FieldDef: '%s' '%s'\n", struct_name, field_name); return self; } diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 25bcbaf69..96c8af060 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -60,38 +60,38 @@ type_is_null (qfot_type_t *type) void print_type (qfot_type_t *type) { - printf ("type: %p %d %d %s", type, type.meta, type.size, type.encoding); + //printf ("type: %p %d %d %s", type, type.meta, type.size, type.encoding); switch (type.meta) { case ty_basic: - printf (" %d", type.type); + //printf (" %d", type.type); switch (type.type) { case ev_pointer: case ev_field: - printf (" "); + //printf (" "); print_type (type.fldptr.aux_type); break; case ev_func: - printf (" %p %d\n", type.func.return_type, - type.func.num_params); + //printf (" %p %d\n", type.func.return_type, + // type.func.num_params); default: - printf ("\n"); + //printf ("\n"); break; } break; case ty_struct: case ty_union: case ty_enum: - printf (" %s %d\n", type.strct.tag, type.strct.num_fields); + //printf (" %s %d\n", type.strct.tag, type.strct.num_fields); break; case ty_array: - printf (" %p %d %d\n", type.array.type, type.array.base, - type.array.size); + //printf (" %p %d %d\n", type.array.type, type.array.base, + // type.array.size); break; case ty_class: - printf (" %s\n", type.class); + //printf (" %s\n", type.class); break; case ty_alias: - printf (" %d %s ", type.alias.type, type.alias.name); + //printf (" %d %s ", type.alias.type, type.alias.name); print_type (type.alias.aux_type); break; } @@ -116,7 +116,7 @@ scan_types (void) Type *avail_type = [Type fromType: type]; if (avail_type) { if (!Hash_Find (available_types, [avail_type name])) { - printf ("scan: %s %s\n", tag, [avail_type name]); + //printf ("scan: %s %s\n", tag, [avail_type name]); Hash_Add (available_types, avail_type); } } @@ -194,7 +194,7 @@ main(int argc, string *argv) string search_name = [str string]; id obj = (id) Hash_Find (available_types, search_name); obj = [obj resolveType]; - printf("obj: %d %s\n", obj, class_get_class_name([obj class])); + //printf("obj: %d %s\n", obj, class_get_class_name([obj class])); if (obj && [obj class] == [Struct class]) { [obj addToQueue]; } @@ -213,7 +213,7 @@ main(int argc, string *argv) } for (int i = 0; i < argc; i++) { - printf ("vkgen %d %s\n", i, argv[i]); + //printf ("vkgen %d %s\n", i, argv[i]); } arp_end (); diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 77b11fad5..cae352f0b 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -21,7 +21,7 @@ { string name = [self name]; if (!Hash_Find (processed_types, name)) { - printf (" +%s\n", name); + //printf (" +%s\n", name); Hash_Add (processed_types, (void *) name); [queue addObject: self]; } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index f61e31ede..3a1329720 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -290,7 +290,7 @@ run_progs (void *data) __auto_type thread = (qwaq_thread_t *) data; spawn_progs (thread); - Sys_Printf ("starting thread for %s\n", thread->args.a[0]); + //Sys_Printf ("starting thread for %s\n", thread->args.a[0]); PR_ExecuteProgram (thread->pr, thread->main_func); PR_PopFrame (thread->pr); From ef6dd422e5c543b8cc9dae680068041376349c25 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Jul 2021 18:13:08 +0900 Subject: [PATCH 1621/3664] [qfcc] Add source line number to statement blocks For statement dot blocks. --- tools/qfcc/source/dot_sblock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_sblock.c b/tools/qfcc/source/dot_sblock.c index 18089681c..80f292e61 100644 --- a/tools/qfcc/source/dot_sblock.c +++ b/tools/qfcc/source/dot_sblock.c @@ -58,7 +58,7 @@ static void flow_statement (dstring_t *dstr, statement_t *s) { dasprintf (dstr, " "); - dasprintf (dstr, "%d", s->number); + dasprintf (dstr, "%d:%d", s->number, s->expr ? s->expr->line : -1); dasprintf (dstr, "%s", html_string(quote_string (s->opcode))); dasprintf (dstr, "%s", html_string(operand_string (s->opa))); dasprintf (dstr, "%s", html_string(operand_string (s->opb))); From 4b1eb0d76020935fa4edc3f2677ab44011ab2ad4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 Jul 2021 14:18:06 +0900 Subject: [PATCH 1622/3664] [sw] Speed up Draw_FadeScreen It now processes 4 pixels at a time and uses a bit mask instead of a conditional to set 3 of the 4 pixels to black. On top of the 4:1 pixel processing and avoiding inner-loop conditional jumps, gcc unrolls the loop, so Draw_FadeScreen itself is more than 4x as fast as it was. The end result is about 5% (3fps) speedup to timedemo demo1 on my 900MHz EEE Pc when nq has been hacked to always draw the fade-screen. --- libs/video/renderer/sw/draw.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index aaf536f50..cf32d22e0 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -777,21 +777,22 @@ void Draw_FadeScreen (void) { int x, y; - byte *pbuf; + int height = vid.conheight; + int width = vid.conwidth / 4; + uint32_t *pbuf; VID_UnlockBuffer (); S_ExtraUpdate (); VID_LockBuffer (); - for (y = 0; y < vid.conheight; y++) { - unsigned int t; + for (y = 0; y < height; y++) { + uint32_t mask; - pbuf = ((byte *)vid.buffer) + vid.rowbytes * y; - t = (y & 1) << 1; + pbuf = (uint32_t *) ((byte *)vid.buffer + vid.rowbytes * y); + mask = 0xff << ((y & 1) << 4); - for (x = 0; x < vid.conwidth; x++) { - if ((x & 3) != t) - pbuf[x] = 0; + for (x = 0; x < width; x++) { + *pbuf++ &= mask; } } vr_data.scr_copyeverything = 1; From a75c027b7f8f5974ad226b3cbc4d1e7151870144 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Jul 2021 17:57:59 +0900 Subject: [PATCH 1623/3664] [ui] Add two view manipulation functions One moves and resizes the view in one operation as a bit of an optimization as moving and resizing both update any child views, and this does only one update. The other sets the gravity and updates any child views as their absolute positions would change as well as the updated view's absolute position. --- include/QF/ui/view.h | 22 ++++++++++++++++++++++ libs/ui/view.c | 16 ++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index fd2dd33ac..d3d6f17e7 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -215,6 +215,28 @@ void view_resize (view_t *view, int xl, int yl); */ void view_move (view_t *view, int xp, int yp); +/** Chage the location and size of a view in a single operation. + + The absolute X and Y coorinates of the view are updated as necessary to + keep the coordinates of the view's origin correct relative to the view's + geometry. + + \param view The view to move. + \param xp The new X coordinate of the view relative to its gravity. + \param yp The new Y coordinate of the view relative to its gravity. + \param xl The new width of the view. + \param yl The new height of the view. +*/ +void view_setgeometry (view_t *view, int xp, int yp, int xl, int yl); + +/** Change the gravity of a view, adjusting its position appropriately + + \param view The view which will have its gravity set.. + \param grav The gravity of the view. determines the view's origin and + its positioning within the view's parent. +*/ +void view_setgravity (view_t *view, grav_t grav); + ///@} #endif//__QF_ui_view_h diff --git a/libs/ui/view.c b/libs/ui/view.c index 9765b223f..71c4a3b4b 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -221,3 +221,19 @@ view_move (view_t *view, int xp, int yp) view->ypos = yp; setgeometry (view); } + +VISIBLE void +view_setgeometry (view_t *view, int xp, int yp, int xl, int yl) +{ + view->xpos = xp; + view->ypos = yp; + _resize (view, xl, yl); + setgeometry (view); +} + +VISIBLE void +view_setgravity (view_t *view, grav_t grav) +{ + view->gravity = grav; + setgeometry (view); +} From 755ef524e41f6d6f6cd86207760e4f51b6cf8306 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Jul 2021 18:04:34 +0900 Subject: [PATCH 1624/3664] [video] Use views instead of conwidth and conheight conwidth and conheight have been moved into vid.conview (probably change the name at some time), and scr_vrect has been replaced by a view as well. This makes it much easier to create 2d elements that follow the screen size (taking advantage of a view's gravity) which will, in the end, make changing the window size easier. --- include/QF/plugin/vid_render.h | 2 +- include/QF/vid.h | 3 +- include/d_iface.h | 1 - include/r_screen.h | 1 - libs/console/client.c | 13 +-- libs/video/renderer/gl/gl_draw.c | 30 +++---- libs/video/renderer/gl/gl_screen.c | 2 + libs/video/renderer/glsl/glsl_draw.c | 18 ++-- libs/video/renderer/glsl/glsl_screen.c | 3 + libs/video/renderer/r_screen.c | 22 +++-- libs/video/renderer/sw/d_scan.c | 19 +++-- libs/video/renderer/sw/draw.c | 35 ++++---- libs/video/renderer/sw/screen.c | 10 ++- libs/video/renderer/sw/sw_rmisc.c | 6 +- libs/video/renderer/sw32/d_scan.c | 58 +++++++------ libs/video/renderer/sw32/draw.c | 56 +++++++------ libs/video/renderer/sw32/screen.c | 10 ++- libs/video/renderer/sw32/sw32_rmisc.c | 6 +- libs/video/renderer/vid_common.c | 5 +- libs/video/renderer/vid_render_vulkan.c | 3 + libs/video/renderer/vulkan/vulkan_draw.c | 23 +++--- libs/video/renderer/vulkan/vulkan_matrices.c | 5 +- libs/video/targets/vid.c | 14 ++-- nq/source/cl_screen.c | 54 +++++++----- nq/source/sbar.c | 36 ++++---- qw/include/client.h | 3 +- qw/source/cl_ngraph.c | 29 +++---- qw/source/cl_screen.c | 86 ++++++++++++++------ qw/source/sbar.c | 38 ++++----- 29 files changed, 344 insertions(+), 247 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 2fd30ae18..917fd8bbf 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -176,7 +176,7 @@ typedef struct vid_render_funcs_s { typedef struct vid_render_data_s { viddef_t *vid; refdef_t *refdef; - vrect_t *scr_vrect; + struct view_s *scr_view; int scr_copytop; int scr_copyeverything; int scr_fullupdate; // set to 0 to force full redraw diff --git a/include/QF/vid.h b/include/QF/vid.h index c2d92b3a3..2d6a94698 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -56,8 +56,7 @@ typedef struct { quat_t cshift_color; void *conbuffer; int conrowbytes; - int conwidth; - int conheight; + struct view_s *conview; byte *direct; // direct drawing to framebuffer, if not // NULL struct vid_internal_s *vid_internal; diff --git a/include/d_iface.h b/include/d_iface.h index 4f45aa4fa..aa0c16e08 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -257,7 +257,6 @@ extern float r_skyspeed; extern float r_skytime; extern int c_surf; -extern vrect_t scr_vrect; extern byte *r_warpbuffer; diff --git a/include/r_screen.h b/include/r_screen.h index 996cc3a0f..310f59230 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -64,7 +64,6 @@ extern int clearconsole; extern int clearnotify; extern vrect_t *pconupdate; -extern vrect_t scr_vrect; extern qboolean scr_skipupdate; diff --git a/libs/console/client.c b/libs/console/client.c index 75eab4652..32dbb4a62 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -180,7 +180,7 @@ Resize (old_console_t *con) char tbuf[CON_TEXTSIZE]; int width, oldwidth, oldtotallines, numlines, numchars, i, j; - width = (r_data->vid->conwidth >> 3) - 2; + width = (r_data->vid->conview->xlen >> 3) - 2; if (width < 1) { // video hasn't been initialized yet width = 38; @@ -234,7 +234,8 @@ C_CheckResize (void) Resize (&con_main); Resize (&con_chat); - view_resize (con_data.view, r_data->vid->conwidth, r_data->vid->conheight); + view_resize (con_data.view, r_data->vid->conview->xlen, + r_data->vid->conview->ylen); } static void @@ -671,7 +672,7 @@ draw_console (view_t *view) if (con_data.force_commandline) { alpha = 255; } else { - float y = r_data->vid->conheight * con_size->value; + float y = r_data->vid->conview->ylen * con_size->value; alpha = 255 * con_alpha->value * view->ylen / y; alpha = min (alpha, 255); } @@ -732,9 +733,9 @@ setup_console (void) float lines; if (con_data.force_commandline) { - lines = con_data.lines = r_data->vid->conheight; + lines = con_data.lines = r_data->vid->conview->ylen; } else if (con_keydest == key_console) { - lines = r_data->vid->conheight * bound (0.2, con_size->value, 1); + lines = r_data->vid->conview->ylen * bound (0.2, con_size->value, 1); } else { lines = 0; } @@ -750,7 +751,7 @@ setup_console (void) } else { con_data.lines = lines; } - if (con_data.lines >= r_data->vid->conheight - r_data->lineadj) + if (con_data.lines >= r_data->vid->conview->ylen - r_data->lineadj) r_data->scr_copyeverything = 1; } diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 8a3ac7853..7a7bc9048 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -59,6 +59,7 @@ #include "QF/GL/qf_textures.h" #include "QF/GL/qf_vid.h" #include "QF/GL/types.h" +#include "QF/ui/view.h" #include "compat.h" #include "r_internal.h" @@ -682,8 +683,8 @@ gl_Draw_Crosshair (void) if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) return; - x = vid.conwidth / 2 + cl_crossx->int_val; - y = vid.conheight / 2 + cl_crossy->int_val; + x = vid.conview->xlen / 2 + cl_crossx->int_val; + y = vid.conview->ylen / 2 + cl_crossy->int_val; crosshair_func[ch] (x, y); } @@ -808,7 +809,7 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) if (gl_constretch->int_val) { ofs = 0; } else - ofs = (vid.conheight - lines) / (float) vid.conheight; + ofs = (vid.conview->ylen - lines) / (float) vid.conview->ylen; color_0_8[3] = alpha; qfglColor4ubv (color_0_8); @@ -819,9 +820,9 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) qfglTexCoord2f (0, 0 + ofs); qfglVertex2f (0, 0); qfglTexCoord2f (1, 0 + ofs); - qfglVertex2f (vid.conwidth, 0); + qfglVertex2f (vid.conview->xlen, 0); qfglTexCoord2f (1, 1); - qfglVertex2f (vid.conwidth, lines); + qfglVertex2f (vid.conview->xlen, lines); qfglTexCoord2f (0, 1); qfglVertex2f (0, lines); qfglEnd (); @@ -837,8 +838,9 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) qfglPopMatrix (); } - gl_Draw_AltString (vid.conwidth - strlen (cl_verstring->string) * 8 - 11, - lines - 14, cl_verstring->string); + int len = strlen (cl_verstring->string); + gl_Draw_AltString (vid.conview->xlen - len * 8 - 11, lines - 14, + cl_verstring->string); qfglColor3ubv (color_white); } @@ -901,9 +903,9 @@ gl_Draw_FadeScreen (void) qfglBegin (GL_QUADS); qfglVertex2f (0, 0); - qfglVertex2f (vid.conwidth, 0); - qfglVertex2f (vid.conwidth, vid.conheight); - qfglVertex2f (0, vid.conheight); + qfglVertex2f (vid.conview->xlen, 0); + qfglVertex2f (vid.conview->xlen, vid.conview->ylen); + qfglVertex2f (0, vid.conview->ylen); qfglEnd (); qfglColor3ubv (color_white); @@ -943,7 +945,7 @@ GL_Set2D (void) void GL_Set2DScaled (void) { - set_2d (vid.conwidth, vid.conheight); + set_2d (vid.conview->xlen, vid.conview->ylen); } void @@ -974,9 +976,9 @@ gl_Draw_BlendScreen (quat_t color) qfglColor4fv (color); qfglVertex2f (0, 0); - qfglVertex2f (vid.conwidth, 0); - qfglVertex2f (vid.conwidth, vid.conheight); - qfglVertex2f (0, vid.conheight); + qfglVertex2f (vid.conview->xlen, 0); + qfglVertex2f (vid.conview->xlen, vid.conview->ylen); + qfglVertex2f (0, vid.conview->ylen); qfglEnd (); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 73e41a540..48d2565b8 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -55,6 +55,7 @@ #include "QF/GL/qf_draw.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_vid.h" +#include "QF/ui/view.h" #include "compat.h" #include "r_internal.h" @@ -238,6 +239,7 @@ gl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) GL_Set2DScaled (); + view_draw (vr_data.scr_view); while (*scr_funcs) { (*scr_funcs)(); scr_funcs++; diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 6d1f14f0b..f39040ab8 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -48,6 +48,7 @@ #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/vid.h" +#include "QF/ui/view.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" @@ -570,8 +571,8 @@ glsl_Draw_Crosshair (void) { int x, y; - x = vid.conwidth / 2 + cl_crossx->int_val; - y = vid.conheight / 2 + cl_crossy->int_val; + x = vid.conview->xlen / 2 + cl_crossx->int_val; + y = vid.conview->ylen / 2 + cl_crossy->int_val; glsl_Draw_CrosshairAt (crosshair->int_val, x, y); } @@ -603,14 +604,14 @@ glsl_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, void glsl_Draw_ConsoleBackground (int lines, byte alpha) { - float ofs = (vid.conheight - lines) / (float) vid.conheight; + float ofs = (vid.conview->ylen - lines) / (float) vid.conview->ylen; quat_t color = {1, 1, 1, bound (0, alpha, 255) / 255.0}; drawvert_t verts[] = { {{ 0, 0, 0, ofs}}, - {{vid.conwidth, 0, 1, ofs}}, - {{vid.conwidth, lines, 1, 1}}, + {{vid.conview->xlen, 0, 1, ofs}}, + {{vid.conview->xlen, lines, 1, 1}}, {{ 0, 0, 0, ofs}}, - {{vid.conwidth, lines, 1, 1}}, + {{vid.conview->xlen, lines, 1, 1}}, {{ 0, lines, 0, 1}}, }; @@ -684,7 +685,8 @@ glsl_Draw_Fill (int x, int y, int w, int h, int c) static inline void draw_blendscreen (quat_t color) { - draw_pic (0, 0, vid.conwidth, vid.conheight, white_pic, 0, 0, 8, 8, color); + draw_pic (0, 0, vid.conview->xlen, vid.conview->ylen, white_pic, + 0, 0, 8, 8, color); } void @@ -757,7 +759,7 @@ GLSL_Set2D (void) void GLSL_Set2DScaled (void) { - set_2d (vid.conwidth, vid.conheight); + set_2d (vid.conview->xlen, vid.conview->ylen); } void diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index 982f3988c..4c2a65727 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -58,6 +58,7 @@ #include "QF/GLSL/qf_draw.h" #include "QF/GLSL/qf_textures.h" #include "QF/GLSL/qf_vid.h" +#include "QF/ui/view.h" #include "r_internal.h" #include "vid_gl.h" @@ -184,6 +185,8 @@ glsl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) GLSL_DrawReset (); SCR_TileClear (); GLSL_Set2DScaled (); + + view_draw (vr_data.scr_view); while (*scr_funcs) { (*scr_funcs)(); scr_funcs++; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index f49fadd18..f1701c7ba 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -44,6 +44,8 @@ #include "QF/screen.h" #include "QF/sys.h" +#include "QF/ui/view.h" + #include "compat.h" #include "r_internal.h" #include "sbar.h" @@ -105,7 +107,6 @@ qpic_t *scr_turtle; int clearconsole; vrect_t *pconupdate; -vrect_t scr_vrect; qboolean scr_skipupdate; @@ -179,9 +180,10 @@ SCR_CalcRefdef (void) vrect.width = r_data->vid->width; vrect.height = r_data->vid->height; - R_SetVrect (&vrect, &scr_vrect, r_data->lineadj); + R_SetVrect (&vrect, &refdef->vrect, r_data->lineadj); - refdef->vrect = scr_vrect; + view_setgeometry (vr_data.scr_view, refdef->vrect.x, refdef->vrect.y, + refdef->vrect.width, refdef->vrect.height); // notify the refresh of the change r_funcs->R_ViewChanged (); @@ -262,7 +264,9 @@ SCR_DrawRam (void) if (!r_cache_thrash) return; - r_funcs->Draw_Pic (scr_vrect.x + 32, scr_vrect.y, scr_ram); + //FIXME view + r_funcs->Draw_Pic (vr_data.scr_view->xpos + 32, vr_data.scr_view->ypos, + scr_ram); } void @@ -282,7 +286,9 @@ SCR_DrawTurtle (void) if (count < 3) return; - r_funcs->Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); + //FIXME view + r_funcs->Draw_Pic (vr_data.scr_view->xpos, vr_data.scr_view->ypos, + scr_turtle); } void @@ -296,9 +302,11 @@ SCR_DrawPause (void) if (!r_data->paused) return; + //FIXME view conwidth pic = r_funcs->Draw_CachePic ("gfx/pause.lmp", true); - r_funcs->Draw_Pic ((r_data->vid->conwidth - pic->width) / 2, - (r_data->vid->conheight - 48 - pic->height) / 2, pic); + r_funcs->Draw_Pic ((r_data->vid->conview->xlen - pic->width) / 2, + (r_data->vid->conview->ylen - 48 - pic->height) / 2, + pic); } void diff --git a/libs/video/renderer/sw/d_scan.c b/libs/video/renderer/sw/d_scan.c index 2522befbb..c411e8b1e 100644 --- a/libs/video/renderer/sw/d_scan.c +++ b/libs/video/renderer/sw/d_scan.c @@ -29,6 +29,7 @@ #endif #include "QF/render.h" +#include "QF/ui/view.h" #include "d_local.h" #include "r_internal.h" @@ -50,6 +51,10 @@ D_WarpScreen (void) { int w, h; int u, v; + int scr_x = vr_data.scr_view->xpos; + int scr_y = vr_data.scr_view->ypos; + int scr_w = vr_data.scr_view->xlen; + int scr_h = vr_data.scr_view->ylen; byte *dest; int *turb; int *col; @@ -63,26 +68,26 @@ D_WarpScreen (void) w = r_refdef.vrect.width; h = r_refdef.vrect.height; - wratio = w / (float) scr_vrect.width; - hratio = h / (float) scr_vrect.height; + wratio = w / (float) scr_w; + hratio = h / (float) scr_h; - for (v = 0; v < scr_vrect.height + AMP2 * 2; v++) { + for (v = 0; v < scr_h + AMP2 * 2; v++) { rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) + (screenwidth * (int) ((float) v * hratio * h / (h + AMP2 * 2))); } - for (u = 0; u < scr_vrect.width + AMP2 * 2; u++) { + for (u = 0; u < scr_w + AMP2 * 2; u++) { column[u] = r_refdef.vrect.x + (int) ((float) u * wratio * w / (w + AMP2 * 2)); } turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = ((byte*)vid.buffer) + scr_vrect.y * vid.rowbytes + scr_vrect.x; + dest = ((byte*)vid.buffer) + scr_y * vid.rowbytes + scr_x; - for (v = 0; v < scr_vrect.height; v++, dest += vid.rowbytes) { + for (v = 0; v < scr_h; v++, dest += vid.rowbytes) { col = &column[turb[v]]; row = &rowptr[v]; - for (u = 0; u < scr_vrect.width; u += 4) { + for (u = 0; u < scr_w; u += 4) { dest[u + 0] = row[turb[u + 0]][col[u + 0]]; dest[u + 1] = row[turb[u + 1]][col[u + 1]]; dest[u + 2] = row[turb[u + 2]][col[u + 2]]; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index cf32d22e0..603ad25a3 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -42,6 +42,7 @@ #include "QF/quakefs.h" #include "QF/sound.h" #include "QF/sys.h" +#include "QF/ui/view.h" #include "d_iface.h" #include "r_internal.h" @@ -263,7 +264,7 @@ Draw_Character (int x, int y, unsigned int chr) if (y <= -8) return; // totally off screen - if (y > vid.conheight - 8 || x < 0 || x > vid.conwidth - 8) + if (y > vid.conview->ylen - 8 || x < 0 || x > vid.conview->xlen - 8) return; if (chr > 255) return; @@ -461,8 +462,8 @@ Draw_Crosshair (void) if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) return; - x = vid.conwidth / 2 + cl_crossx->int_val; - y = vid.conheight / 2 + cl_crossy->int_val; + x = vid.conview->xlen / 2 + cl_crossx->int_val; + y = vid.conview->ylen / 2 + cl_crossy->int_val; crosshair_func[ch] (x, y); } @@ -484,8 +485,8 @@ Draw_Pic (int x, int y, qpic_t *pic) byte *dest, *source, tbyte; int v, u; - if (x < 0 || (x + pic->width) > vid.conwidth - || y < 0 || (y + pic->height) > vid.conheight) { + if (x < 0 || (x + pic->width) > vid.conview->xlen + || y < 0 || (y + pic->height) > vid.conview->ylen) { Sys_MaskPrintf (SYS_vid, "Draw_Pic: bad coordinates"); Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); return; @@ -543,8 +544,8 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, byte *dest, *source, tbyte; int u, v; - if ((x < 0) || (x + width > vid.conwidth) - || (y < 0) || (y + height > vid.conheight)) { + if ((x < 0) || (x + width > vid.conview->xlen) + || (y < 0) || (y + height > vid.conview->ylen)) { Sys_MaskPrintf (SYS_vid, "Draw_SubPic: bad coordinates"); } // first, clip to screen @@ -623,14 +624,14 @@ Draw_ConsoleBackground (int lines, byte alpha) dest = vid.conbuffer; for (y = 0; y < lines; y++, dest += vid.conrowbytes) { - v = (vid.conheight - lines + y) * 200 / vid.conheight; + v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; src = conback->data + v * 320; - if (vid.conwidth == 320) - memcpy (dest, src, vid.conwidth); + if (vid.conview->xlen == 320) + memcpy (dest, src, vid.conview->xlen); else { f = 0; - fstep = 320 * 0x10000 / vid.conwidth; - for (x = 0; x < vid.conwidth; x += 4) { + fstep = 320 * 0x10000 / vid.conview->xlen; + for (x = 0; x < vid.conview->xlen; x += 4) { dest[x] = src[f >> 16]; f += fstep; dest[x + 1] = src[f >> 16]; @@ -643,7 +644,7 @@ Draw_ConsoleBackground (int lines, byte alpha) } } - Draw_AltString (vid.conwidth - strlen (cl_verstring->string) * 8 - 11, + Draw_AltString (vid.conview->xlen - strlen (cl_verstring->string) * 8 - 11, lines - 14, cl_verstring->string); } @@ -759,8 +760,8 @@ Draw_Fill (int x, int y, int w, int h, int c) byte *dest; int u, v; - if (x < 0 || x + w > vid.conwidth - || y < 0 || y + h > vid.conheight) { + if (x < 0 || x + w > vid.conview->xlen + || y < 0 || y + h > vid.conview->ylen) { Sys_MaskPrintf (SYS_vid, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); } @@ -777,8 +778,8 @@ void Draw_FadeScreen (void) { int x, y; - int height = vid.conheight; - int width = vid.conwidth / 4; + int height = vid.conview->ylen; + int width = vid.conview->xlen / 4; uint32_t *pbuf; VID_UnlockBuffer (); diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 5aa2ed53e..ee6533eb6 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -47,6 +47,7 @@ #include "QF/screen.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/ui/view.h" #include "compat.h" #include "r_internal.h" @@ -207,6 +208,7 @@ R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) D_EnableBackBufferAccess (); // of all overlay stuff if drawing // directly + view_draw (vr_data.scr_view); while (*scr_funcs) { (*scr_funcs)(); scr_funcs++; @@ -232,10 +234,10 @@ R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) vrect.height = vid.height - vr_data.lineadj; vrect.next = 0; } else { - vrect.x = scr_vrect.x; - vrect.y = scr_vrect.y; - vrect.width = scr_vrect.width; - vrect.height = scr_vrect.height; + vrect.x = vr_data.scr_view->xpos; + vrect.y = vr_data.scr_view->ypos; + vrect.width = vr_data.scr_view->xlen; + vrect.height = vr_data.scr_view->ylen; vrect.next = 0; } sw_ctx->update (&vrect); diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index 5c4beae79..f0ab9c9bb 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -33,6 +33,7 @@ #include "QF/draw.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/ui/view.h" #include "compat.h" #include "r_internal.h" @@ -290,7 +291,10 @@ R_SetupFrame (void) R_ViewChanged (); } } else { - r_refdef.vrect = scr_vrect; + r_refdef.vrect.x = vr_data.scr_view->xpos; + r_refdef.vrect.y = vr_data.scr_view->ypos; + r_refdef.vrect.width = vr_data.scr_view->xlen; + r_refdef.vrect.height = vr_data.scr_view->ylen; R_ViewChanged (); } diff --git a/libs/video/renderer/sw32/d_scan.c b/libs/video/renderer/sw32/d_scan.c index d5c2000ea..b49f758d5 100644 --- a/libs/video/renderer/sw32/d_scan.c +++ b/libs/video/renderer/sw32/d_scan.c @@ -34,6 +34,7 @@ #include "QF/qendian.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/ui/view.h" #include "compat.h" #include "d_local.h" @@ -60,6 +61,10 @@ sw32_D_WarpScreen (void) { int w, h; int u, v; + int scr_x = vr_data.scr_view->xpos; + int scr_y = vr_data.scr_view->ylen; + int scr_w = vr_data.scr_view->xpos; + int scr_h = vr_data.scr_view->ylen; byte *dest; int *turb; int *col; @@ -71,29 +76,28 @@ sw32_D_WarpScreen (void) w = r_refdef.vrect.width; h = r_refdef.vrect.height; - wratio = w / (float) scr_vrect.width; - hratio = h / (float) scr_vrect.height; + wratio = w / (float) scr_w; + hratio = h / (float) scr_h; - for (v = 0; v < scr_vrect.height + AMP2 * 2; v++) { + for (v = 0; v < scr_h + AMP2 * 2; v++) { rowptr[v] = (byte *) sw32_d_viewbuffer + (r_refdef.vrect.y * sw32_screenwidth) + (sw32_screenwidth * (int) ((float) v * hratio * h / (h + AMP2 * 2))); } - for (u = 0; u < scr_vrect.width + AMP2 * 2; u++) { + for (u = 0; u < scr_w + AMP2 * 2; u++) { column[u] = r_refdef.vrect.x + (int) ((float) u * wratio * w / (w + AMP2 * 2)); } turb = sw32_intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = (byte *)vid.buffer + scr_vrect.y * vid.rowbytes + - scr_vrect.x; + dest = (byte *)vid.buffer + scr_y * vid.rowbytes + scr_x; - for (v = 0; v < scr_vrect.height; v++, dest += vid.rowbytes) { + for (v = 0; v < scr_h; v++, dest += vid.rowbytes) { col = &column[turb[v]]; row = &rowptr[v]; - for (u = 0; u < scr_vrect.width; u += 4) { + for (u = 0; u < scr_w; u += 4) { dest[u + 0] = row[turb[u + 0]][col[u + 0]]; dest[u + 1] = row[turb[u + 1]][col[u + 1]]; dest[u + 2] = row[turb[u + 2]][col[u + 2]]; @@ -106,6 +110,10 @@ sw32_D_WarpScreen (void) { int w, h; int u, v; + int scr_x = vr_data.scr_view->xpos; + int scr_y = vr_data.scr_view->ylen; + int scr_w = vr_data.scr_view->xpos; + int scr_h = vr_data.scr_view->ylen; short *dest; int *turb; int *col; @@ -117,29 +125,28 @@ sw32_D_WarpScreen (void) w = r_refdef.vrect.width; h = r_refdef.vrect.height; - wratio = w / (float) scr_vrect.width; - hratio = h / (float) scr_vrect.height; + wratio = w / (float) scr_w; + hratio = h / (float) scr_h; - for (v = 0; v < scr_vrect.height + AMP2 * 2; v++) { + for (v = 0; v < scr_h + AMP2 * 2; v++) { rowptr[v] = (short *) sw32_d_viewbuffer + (r_refdef.vrect.y * sw32_screenwidth) + (sw32_screenwidth * (int) ((float) v * hratio * h / (h + AMP2 * 2))); } - for (u = 0; u < scr_vrect.width + AMP2 * 2; u++) { + for (u = 0; u < scr_w + AMP2 * 2; u++) { column[u] = r_refdef.vrect.x + (int) ((float) u * wratio * w / (w + AMP2 * 2)); } turb = sw32_intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = (short *) vid.buffer + scr_vrect.y * (vid.rowbytes >> 1) + - scr_vrect.x; + dest = (short *) vid.buffer + scr_y * (vid.rowbytes >> 1) + scr_x; - for (v = 0; v < scr_vrect.height; v++, dest += (vid.rowbytes >> 1)) { + for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 1)) { col = &column[turb[v]]; row = &rowptr[v]; - for (u = 0; u < scr_vrect.width; u += 4) { + for (u = 0; u < scr_w; u += 4) { dest[u + 0] = row[turb[u + 0]][col[u + 0]]; dest[u + 1] = row[turb[u + 1]][col[u + 1]]; dest[u + 2] = row[turb[u + 2]][col[u + 2]]; @@ -152,6 +159,10 @@ sw32_D_WarpScreen (void) { int w, h; int u, v; + int scr_x = vr_data.scr_view->xpos; + int scr_y = vr_data.scr_view->ylen; + int scr_w = vr_data.scr_view->xpos; + int scr_h = vr_data.scr_view->ylen; int *dest; int *turb; int *col; @@ -163,29 +174,28 @@ sw32_D_WarpScreen (void) w = r_refdef.vrect.width; h = r_refdef.vrect.height; - wratio = w / (float) scr_vrect.width; - hratio = h / (float) scr_vrect.height; + wratio = w / (float) scr_w; + hratio = h / (float) scr_h; - for (v = 0; v < scr_vrect.height + AMP2 * 2; v++) { + for (v = 0; v < scr_h + AMP2 * 2; v++) { rowptr[v] = (int *) sw32_d_viewbuffer + (r_refdef.vrect.y * sw32_screenwidth) + (sw32_screenwidth * (int) ((float) v * hratio * h / (h + AMP2 * 2))); } - for (u = 0; u < scr_vrect.width + AMP2 * 2; u++) { + for (u = 0; u < scr_w + AMP2 * 2; u++) { column[u] = r_refdef.vrect.x + (int) ((float) u * wratio * w / (w + AMP2 * 2)); } turb = sw32_intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = (int *) vid.buffer + scr_vrect.y * (vid.rowbytes >> 2) + - scr_vrect.x; + dest = (int *) vid.buffer + scr_y * (vid.rowbytes >> 2) + scr_x; - for (v = 0; v < scr_vrect.height; v++, dest += (vid.rowbytes >> 2)) { + for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 2)) { col = &column[turb[v]]; row = &rowptr[v]; - for (u = 0; u < scr_vrect.width; u += 4) { + for (u = 0; u < scr_w; u += 4) { dest[u + 0] = row[turb[u + 0]][col[u + 0]]; dest[u + 1] = row[turb[u + 1]][col[u + 1]]; dest[u + 2] = row[turb[u + 2]][col[u + 2]]; diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c index da11e1bb9..9d1e038cf 100644 --- a/libs/video/renderer/sw32/draw.c +++ b/libs/video/renderer/sw32/draw.c @@ -45,6 +45,7 @@ #include "QF/quakefs.h" #include "QF/sound.h" #include "QF/sys.h" +#include "QF/ui/view.h" #include "d_iface.h" #include "r_internal.h" @@ -265,7 +266,7 @@ sw32_Draw_Character (int x, int y, unsigned int chr) if (y <= -8) return; // totally off screen - if (y > vid.conheight - 8 || x < 0 || x > vid.conwidth - 8) + if (y > vid.conview->ylen - 8 || x < 0 || x > vid.conview->xlen - 8) return; if (chr > 255) return; @@ -538,8 +539,8 @@ sw32_Draw_Crosshair (void) if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) return; - x = vid.conwidth / 2 + cl_crossx->int_val; - y = vid.conheight / 2 + cl_crossy->int_val; + x = vid.conview->xlen / 2 + cl_crossx->int_val; + y = vid.conview->ylen / 2 + cl_crossy->int_val; crosshair_func[ch] (x, y); } @@ -560,8 +561,8 @@ sw32_Draw_Pic (int x, int y, qpic_t *pic) byte *source, tbyte; int v, u; - if (x < 0 || (x + pic->width) > vid.conwidth - || y < 0 || (y + pic->height) > vid.conheight) { + if (x < 0 || (x + pic->width) > vid.conview->xlen + || y < 0 || (y + pic->height) > vid.conview->ylen) { Sys_MaskPrintf (SYS_vid, "Draw_Pic: bad coordinates"); sw32_Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); return; @@ -659,8 +660,8 @@ sw32_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, byte *source, tbyte; int v, u; - if ((x < 0) || (x + width > vid.conwidth) - || (y < 0) || (y + height > vid.conheight)) { + if ((x < 0) || (x + width > vid.conview->xlen) + || (y < 0) || (y + height > vid.conview->ylen)) { Sys_MaskPrintf (SYS_vid, "Draw_SubPic: bad coordinates"); } // first, clip to screen @@ -746,14 +747,14 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) byte *dest = vid.conbuffer; for (y = 0; y < lines; y++, dest += vid.conrowbytes) { - v = (vid.conheight - lines + y) * 200 / vid.conheight; + v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; src = conback->data + v * 320; - if (vid.conwidth == 320) - memcpy (dest, src, vid.conwidth); + if (vid.conview->xlen == 320) + memcpy (dest, src, vid.conview->xlen); else { f = 0; - fstep = 320 * 0x10000 / vid.conwidth; - for (x = 0; x < vid.conwidth; x += 4) { + fstep = 320 * 0x10000 / vid.conview->xlen; + for (x = 0; x < vid.conview->xlen; x += 4) { dest[x] = src[f >> 16]; f += fstep; dest[x + 1] = src[f >> 16]; @@ -774,11 +775,11 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) for (y = 0; y < lines; y++, dest += (vid.conrowbytes >> 1)) { // FIXME: pre-expand to native format? // FIXME: does the endian switching go away in production? - v = (vid.conheight - lines + y) * 200 / vid.conheight; + v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; src = conback->data + v * 320; f = 0; - fstep = 320 * 0x10000 / vid.conwidth; - for (x = 0; x < vid.conwidth; x += 4) { + fstep = 320 * 0x10000 / vid.conview->xlen; + for (x = 0; x < vid.conview->xlen; x += 4) { dest[x] = sw32_8to16table[src[f >> 16]]; f += fstep; dest[x + 1] = sw32_8to16table[src[f >> 16]]; @@ -795,11 +796,11 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) { unsigned int *dest = (unsigned int *) vid.conbuffer; for (y = 0; y < lines; y++, dest += (vid.conrowbytes >> 2)) { - v = (vid.conheight - lines + y) * 200 / vid.conheight; + v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; src = conback->data + v * 320; f = 0; - fstep = 320 * 0x10000 / vid.conwidth; - for (x = 0; x < vid.conwidth; x += 4) { + fstep = 320 * 0x10000 / vid.conview->xlen; + for (x = 0; x < vid.conview->xlen; x += 4) { dest[x ] = d_8to24table[src[f >> 16]];f += fstep; dest[x + 1] = d_8to24table[src[f >> 16]];f += fstep; dest[x + 2] = d_8to24table[src[f >> 16]];f += fstep; @@ -815,7 +816,8 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) } // if (!cls.download) - sw32_Draw_AltString (vid.conwidth - strlen (cl_verstring->string) * 8 - 11, + int len = strlen (cl_verstring->string); + sw32_Draw_AltString (vid.conview->xlen - len * 8 - 11, lines - 14, cl_verstring->string); } @@ -1174,8 +1176,8 @@ sw32_Draw_Fill (int x, int y, int w, int h, int c) { int u, v; - if (x < 0 || x + w > vid.conwidth - || y < 0 || y + h > vid.conheight) { + if (x < 0 || x + w > vid.conview->xlen + || y < 0 || y + h > vid.conview->ylen) { Sys_MaskPrintf (SYS_vid, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); } @@ -1228,12 +1230,12 @@ sw32_Draw_FadeScreen (void) switch(sw32_r_pixbytes) { case 1: { - for (y = 0; y < vid.conheight; y++) { + for (y = 0; y < vid.conview->ylen; y++) { unsigned int t; byte *pbuf = (byte *) ((byte *) vid.buffer + vid.rowbytes * y); t = (y & 1) << 1; - for (x = 0; x < vid.conwidth; x++) { + for (x = 0; x < vid.conview->xlen; x++) { if ((x & 3) != t) pbuf[x] = 0; } @@ -1242,21 +1244,21 @@ sw32_Draw_FadeScreen (void) break; case 2: { - for (y = 0; y < vid.conheight; y++) { + for (y = 0; y < vid.conview->ylen; y++) { unsigned short *pbuf = (unsigned short *) ((byte *) vid.buffer + vid.rowbytes * y); pbuf = (unsigned short *) vid.buffer + (vid.rowbytes >> 1) * y; - for (x = 0; x < vid.conwidth; x++) + for (x = 0; x < vid.conview->xlen; x++) pbuf[x] = (pbuf[x] >> 1) & 0x7BEF; } } break; case 4: { - for (y = 0; y < vid.conheight; y++) { + for (y = 0; y < vid.conview->ylen; y++) { unsigned int *pbuf = (unsigned int *) ((byte *) vid.buffer + vid.rowbytes * y); - for (x = 0; x < vid.conwidth; x++) + for (x = 0; x < vid.conview->xlen; x++) pbuf[x] = (pbuf[x] >> 1) & 0x7F7F7F7F; } } diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index 7dabffd9a..201586432 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -50,6 +50,7 @@ #include "QF/screen.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/ui/view.h" #include "compat.h" #include "r_internal.h" @@ -164,6 +165,7 @@ sw32_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) sw32_D_EnableBackBufferAccess (); // of all overlay stuff if drawing // directly + view_draw (vr_data.scr_view); while (*scr_funcs) { (*scr_funcs)(); scr_funcs++; @@ -189,10 +191,10 @@ sw32_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) vrect.height = vid.height - vr_data.lineadj; vrect.next = 0; } else { - vrect.x = scr_vrect.x; - vrect.y = scr_vrect.y; - vrect.width = scr_vrect.width; - vrect.height = scr_vrect.height; + vrect.x = vr_data.scr_view->xpos; + vrect.y = vr_data.scr_view->ypos; + vrect.width = vr_data.scr_view->xlen; + vrect.height = vr_data.scr_view->ylen; vrect.next = 0; } sw32_ctx->update (&vrect); diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c index 308fc1a08..1845fe06e 100644 --- a/libs/video/renderer/sw32/sw32_rmisc.c +++ b/libs/video/renderer/sw32/sw32_rmisc.c @@ -36,6 +36,7 @@ #include "QF/draw.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/ui/view.h" #include "compat.h" #include "r_internal.h" @@ -291,7 +292,10 @@ sw32_R_SetupFrame (void) vrect.width = vid.width; vrect.height = vid.height; - r_refdef.vrect = scr_vrect; + r_refdef.vrect.x = vr_data.scr_view->xpos; + r_refdef.vrect.y = vr_data.scr_view->ypos; + r_refdef.vrect.width = vr_data.scr_view->xlen; + r_refdef.vrect.height = vr_data.scr_view->ylen; sw32_R_ViewChanged (); } diff --git a/libs/video/renderer/vid_common.c b/libs/video/renderer/vid_common.c index 74a1140b0..149cf85fb 100644 --- a/libs/video/renderer/vid_common.c +++ b/libs/video/renderer/vid_common.c @@ -31,13 +31,16 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/view.h" + #include "mod_internal.h" #include "r_internal.h" viddef_t vid; // global video state +view_t scr_view; vid_render_data_t vid_render_data = { - &vid, &r_refdef, &scr_vrect, + &vid, &r_refdef, &scr_view, 0, 0, 0, 0, 0, 0, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 499979cd1..e34768c6c 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -56,6 +56,7 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/swapchain.h" +#include "QF/ui/view.h" #include "mod_internal.h" #include "r_internal.h" @@ -131,6 +132,8 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) frame->framebuffer = vulkan_ctx->framebuffers->a[imageIndex]; scr_3dfunc (); + + view_draw (vr_data.scr_view); while (*scr_funcs) { (*scr_funcs) (); scr_funcs++; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 96e462cb7..d7dc0f8c7 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -61,6 +61,7 @@ #include "QF/Vulkan/image.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" +#include "QF/ui/view.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -508,10 +509,10 @@ Vulkan_Draw_Character (int x, int y, unsigned int chr, vulkan_ctx_t *ctx) if (chr == ' ') { return; } - if (y <= -8 || y >= vid.conheight) { + if (y <= -8 || y >= vid.conview->ylen) { return; } - if (x <= -8 || x >= vid.conwidth) { + if (x <= -8 || x >= vid.conview->xlen) { return; } queue_character (x, y, chr, ctx); @@ -525,11 +526,11 @@ Vulkan_Draw_String (int x, int y, const char *str, vulkan_ctx_t *ctx) if (!str || !str[0]) { return; } - if (y <= -8 || y >= vid.conheight) { + if (y <= -8 || y >= vid.conview->ylen) { return; } while (*str) { - if ((chr = *str++) != ' ' && x >= -8 && x < vid.conwidth) { + if ((chr = *str++) != ' ' && x >= -8 && x < vid.conview->xlen) { queue_character (x, y, chr, ctx); } x += 8; @@ -545,11 +546,11 @@ Vulkan_Draw_nString (int x, int y, const char *str, int count, if (!str || !str[0]) { return; } - if (y <= -8 || y >= vid.conheight) { + if (y <= -8 || y >= vid.conview->ylen) { return; } while (count-- > 0 && *str) { - if ((chr = *str++) != ' ' && x >= -8 && x < vid.conwidth) { + if ((chr = *str++) != ' ' && x >= -8 && x < vid.conview->xlen) { queue_character (x, y, chr, ctx); } x += 8; @@ -564,12 +565,12 @@ Vulkan_Draw_AltString (int x, int y, const char *str, vulkan_ctx_t *ctx) if (!str || !str[0]) { return; } - if (y <= -8 || y >= vid.conheight) { + if (y <= -8 || y >= vid.conview->ylen) { return; } while (*str) { if ((chr = *str++ | 0x80) != (' ' | 0x80) - && x >= -8 && x < vid.conwidth) { + && x >= -8 && x < vid.conview->xlen) { queue_character (x, y, chr, ctx); } x += 8; @@ -632,7 +633,7 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx); int ofs = max (0, cpic->height - lines); lines = min (lines, cpic->height); - draw_pic (0, 0, vid.conwidth, lines, cpic, + draw_pic (0, 0, vid.conview->xlen, lines, cpic, 0, ofs, cpic->width, lines, color, frame); } @@ -660,8 +661,8 @@ draw_blendscreen (quat_t color, vulkan_ctx_t *ctx) drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - draw_pic (0, 0, vid.conwidth, vid.conheight, dctx->white_pic, 0, 0, 1, 1, - color, frame); + draw_pic (0, 0, vid.conview->xlen, vid.conview->ylen, dctx->white_pic, + 0, 0, 1, 1, color, frame); } void diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 359aad1b1..a9cf83b2c 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -38,6 +38,7 @@ #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/projection.h" +#include "QF/ui/view.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -105,8 +106,8 @@ Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx) __auto_type mat = &ctx->matrices; - int width = vid.conwidth; - int height = vid.conheight; + int width = vid.conview->xlen; + int height = vid.conview->ylen; QFV_Orthographic (mat->projection_2d, 0, width, 0, height, -99999, 99999); float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 25b4b6d27..cef424207 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -42,6 +42,7 @@ #include "QF/qargs.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/ui/view.h" #include "compat.h" #include "d_iface.h" @@ -63,6 +64,8 @@ cvar_t *vid_height; cvar_t *vid_fullscreen; +static view_t conview; + void VID_GetWindowSize (int def_w, int def_h) { @@ -112,6 +115,7 @@ VID_GetWindowSize (int def_w, int def_h) viddef.width = vid_width->int_val; viddef.height = vid_height->int_val; + viddef.conview = &conview; con_width = Cvar_Get ("con_width", va (0, "%d", viddef.width), CVAR_NONE, NULL, "console effective width (GL only)"); @@ -123,9 +127,9 @@ VID_GetWindowSize (int def_w, int def_h) // make con_width a multiple of 8 and >= 320 Cvar_Set (con_width, va (0, "%d", max (con_width->int_val & ~7, 320))); Cvar_SetFlags (con_width, con_width->flags | CVAR_ROM); - viddef.conwidth = con_width->int_val; + viddef.conview->xlen = con_width->int_val; - conheight = (viddef.conwidth * viddef.height) / viddef.width; + conheight = (viddef.conview->xlen * viddef.height) / viddef.width; con_height = Cvar_Get ("con_height", va (0, "%d", conheight), CVAR_NONE, NULL, "console effective height (GL only)"); if ((pnum = COM_CheckParm ("-conheight"))) { @@ -136,7 +140,7 @@ VID_GetWindowSize (int def_w, int def_h) // make con_height >= 200 Cvar_Set (con_height, va (0, "%d", max (con_height->int_val, 200))); Cvar_SetFlags (con_height, con_height->flags | CVAR_ROM); - viddef.conheight = con_height->int_val; + viddef.conview->ylen = con_height->int_val; Con_CheckResize (); // Now that we have a window size, fix console } @@ -243,8 +247,8 @@ VID_InitBuffers (void) int buffersize, zbuffersize, cachesize = 1; // No console scaling in the sw renderer - viddef.conwidth = viddef.width; - viddef.conheight = viddef.height; + viddef.conview->xlen = viddef.width; + viddef.conview->ylen = viddef.height; Con_CheckResize (); // Calculate the sizes we want first diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index ca4c3ee8f..a977fdff8 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -46,37 +46,26 @@ #include "QF/plugin/vid_render.h" +#include "QF/ui/view.h" + #include "sbar.h" #include "nq/include/client.h" -static qpic_t *scr_net; +static view_t *net_view; +static view_t *loading_view; static void -SCR_DrawNet (void) +draw_pic (view_t *view) { - if (realtime - cl.last_servermessage < 0.3) - return; - if (cls.demoplayback) - return; - - if (!scr_net) - scr_net = r_funcs->Draw_PicFromWad ("net"); - - r_funcs->Draw_Pic (r_data->scr_vrect->x + 64, r_data->scr_vrect->y, - scr_net); + r_funcs->Draw_Pic (view->xabs, view->yabs, view->data); } static void -SCR_DrawLoading (void) +draw_cachepic (view_t *view) { - qpic_t *pic; - - if (!cl.loading) - return; - pic = r_funcs->Draw_CachePic ("gfx/loading.lmp", 1); - r_funcs->Draw_Pic ((r_data->vid->conwidth - pic->width) / 2, - (r_data->vid->conheight - 48 - pic->height) / 2, pic); + qpic_t *pic = r_funcs->Draw_CachePic (view->data, 1); + r_funcs->Draw_Pic (view->xabs, view->yabs, pic); } static void @@ -100,12 +89,10 @@ static SCR_Func scr_funcs_normal[] = { 0, //SCR_DrawRam, 0, //SCR_DrawTurtle, 0, //SCR_DrawPause, - SCR_DrawNet, Sbar_Draw, SCR_CShift, Sbar_DrawCenterPrint, Con_DrawConsole, - SCR_DrawLoading, 0 }; @@ -135,6 +122,29 @@ CL_UpdateScreen (double realtime) if (index >= sizeof (scr_funcs) / sizeof (scr_funcs[0])) index = 0; + if (!net_view) { + qpic_t *pic = r_funcs->Draw_PicFromWad ("net"); + net_view = view_new (64, 0, pic->width, pic->height, grav_northwest); + net_view->draw = draw_pic; + net_view->data = pic; + net_view->visible = 0; + view_add (r_data->scr_view, net_view); + } + + if (!loading_view) { + const char *name = "gfx/loading.lmp"; + qpic_t *pic = r_funcs->Draw_CachePic (name, 1); + loading_view = view_new (0, -24, pic->width, pic->height, grav_center); + loading_view->draw = draw_cachepic; + loading_view->data = (void *) name; + loading_view->visible = 0; + view_add (r_data->vid->conview, loading_view); + } + + net_view->visible = (!cls.demoplayback + && realtime - cl.last_servermessage >= 0.3); + loading_view->visible = cl.loading; + //FIXME not every time if (cls.state == ca_active) { if (cl.watervis) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 2004b008e..c51e99ec8 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -447,7 +447,7 @@ draw_weapons_hud (view_t *view) if (view->parent->gravity == grav_southeast) x = view->xlen - 24; - for (i = r_data->vid->conheight < 204; i < 7; i++) { + for (i = r_data->vid->conview->ylen < 204; i < 7; i++) { if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); draw_subpic (view, x, i * 16, sb_weapons[flashon][i], 0, 0, 24, 16); @@ -733,7 +733,7 @@ draw_rogue_weapons_hud (view_t *view) int flashon, i, j; qpic_t *pic; - for (i = r_data->vid->conheight < 204; i < 7; i++) { + for (i = r_data->vid->conview->ylen < 204; i < 7; i++) { if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); if (i >= 2) { @@ -1004,7 +1004,7 @@ sbar_update_vis (void) return; if (con_module && - con_module->data->console->lines == r_data->vid->conheight) + con_module->data->console->lines == r_data->vid->conview->ylen) return; // console is full screen if (cls.state == ca_active @@ -1325,8 +1325,8 @@ init_sbar_views (void) view->draw = draw_status; view_add (sbar_view, view); - if (r_data->vid->conwidth > 320) { - int l = (r_data->vid->conwidth - 320) / 2; + if (r_data->vid->conview->xlen > 320) { + int l = (r_data->vid->conview->xlen - 320) / 2; view = view_new (-l, 0, l, 48, grav_southwest); view->draw = draw_tile; @@ -1379,7 +1379,7 @@ init_hud_views (void) if (hud_frags_view) view_add (hud_inventory_view, hud_frags_view); - view = view_new (0, 0, r_data->vid->conwidth, 48, grav_south); + view = view_new (0, 0, r_data->vid->conview->xlen, 48, grav_south); view_add (view, hud_view); hud_view = view; @@ -1430,8 +1430,8 @@ init_hipnotic_sbar_views (void) view->draw = draw_hipnotic_status; view_add (sbar_view, view); - if (r_data->vid->conwidth > 320) { - int l = (r_data->vid->conwidth - 320) / 2; + if (r_data->vid->conview->xlen > 320) { + int l = (r_data->vid->conview->xlen - 320) / 2; view = view_new (-l, 0, l, 48, grav_southwest); view->draw = draw_tile; @@ -1456,9 +1456,10 @@ init_hipnotic_hud_views (void) hud_view->resize_y = 1; - if (r_data->vid->conheight < 252) { + if (r_data->vid->conview->ylen < 252) { hud_armament_view = view_new (0, - min (r_data->vid->conheight - 160, 48), + min (r_data->vid->conview->ylen - 160, + 48), 66, 160, grav_southeast); } else { hud_armament_view = view_new (0, 48, 42, 204, grav_southeast); @@ -1490,7 +1491,7 @@ init_hipnotic_hud_views (void) if (hud_frags_view) view_add (hud_inventory_view, hud_frags_view); - view = view_new (0, 0, r_data->vid->conwidth, 48, grav_south); + view = view_new (0, 0, r_data->vid->conview->xlen, 48, grav_south); view_add (view, hud_view); hud_view = view; @@ -1537,8 +1538,8 @@ init_rogue_sbar_views (void) view->draw = draw_rogue_status; view_add (sbar_view, view); - if (r_data->vid->conwidth > 320) { - int l = (r_data->vid->conwidth - 320) / 2; + if (r_data->vid->conview->xlen > 320) { + int l = (r_data->vid->conview->xlen - 320) / 2; view = view_new (-l, 0, l, 48, grav_southwest); view->draw = draw_tile; @@ -1587,7 +1588,7 @@ init_rogue_hud_views (void) if (hud_frags_view) view_add (hud_inventory_view, hud_frags_view); - view = view_new (0, 0, r_data->vid->conwidth, 48, grav_south); + view = view_new (0, 0, r_data->vid->conview->xlen, 48, grav_south); view_add (view, hud_view); hud_view = view; @@ -1599,17 +1600,18 @@ init_rogue_hud_views (void) static void init_views (void) { - main_view = view_new (0, 0, r_data->vid->conwidth, r_data->vid->conheight, + main_view = view_new (0, 0, r_data->vid->conview->xlen, + r_data->vid->conview->ylen, grav_northwest); if (con_module) view_insert (con_module->data->console->view, main_view, 0); main_view->resize_x = 1; // get resized if the 2d view resizes main_view->resize_y = 1; main_view->visible = 0; // but don't let the console draw our stuff - if (r_data->vid->conheight > 300) + if (r_data->vid->conview->ylen > 300) overlay_view = view_new (0, 0, 320, 300, grav_center); else - overlay_view = view_new (0, 0, 320, r_data->vid->conheight, + overlay_view = view_new (0, 0, 320, r_data->vid->conview->ylen, grav_center); overlay_view->draw = draw_overlay; overlay_view->visible = 0; diff --git a/qw/include/client.h b/qw/include/client.h index c7994c81d..ec761885f 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -331,7 +331,8 @@ extern struct cbuf_s *cl_stbuf; void Cvar_Info (struct cvar_s *var); -void CL_NetGraph (void); +struct view_s; +void CL_NetGraph (struct view_s *view); void CL_UpdateScreen (double realtime); void CL_SetState (cactive_t state); diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 21891f471..572b54334 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -39,6 +39,8 @@ #include "QF/draw.h" #include "QF/render.h" #include "QF/screen.h" +#include "QF/va.h" +#include "QF/ui/view.h" #include "compat.h" @@ -51,17 +53,12 @@ cvar_t *r_netgraph_alpha; cvar_t *r_netgraph_box; void -CL_NetGraph (void) +CL_NetGraph (view_t *view) { - char st[80]; int lost, a, l, x, y, i; - if (!r_netgraph->int_val) - return; - - x = hudswap ? r_data->vid->conwidth - (NET_TIMINGS + 16): 0; - y = r_data->vid->conheight - sb_lines - 24 - - r_data->graphheight->int_val - 1; + x = view->xabs; + y = view->yabs; if (r_netgraph_box->int_val) r_funcs->Draw_TextBox (x, y, NET_TIMINGS / 8, @@ -69,8 +66,8 @@ CL_NetGraph (void) r_netgraph_alpha->value * 255); lost = CL_CalcNet (); - x = hudswap ? r_data->vid->conwidth - (NET_TIMINGS + 8) : 8; - y = r_data->vid->conheight - sb_lines - 9; + x = view->xabs + 8; + y = view->yabs + view->ylen - 9; l = NET_TIMINGS; if (l > r_data->refdef->vrect.width - 8) @@ -85,13 +82,7 @@ CL_NetGraph (void) } r_funcs->R_LineGraph (x, y, &packet_latency[a], l); - y = r_data->vid->conheight - sb_lines - 24 - - r_data->graphheight->int_val + 7; - snprintf (st, sizeof (st), "%3i%% packet loss", lost); - if (hudswap) { - r_funcs->Draw_String (r_data->vid->conwidth - ((strlen (st) * 8) + 8), - y, st); - } else { - r_funcs->Draw_String (8, y, st); - } + x = view->xabs + 8; + y = view->yabs + 8; + r_funcs->Draw_String (x, y, va (0, "%3i%% packet loss", lost)); } diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 12cfb8441..33e2197c2 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -44,40 +44,30 @@ #include "QF/pcx.h" #include "QF/screen.h" +#include "QF/ui/view.h" + #include "sbar.h" #include "client/view.h" #include "qw/include/client.h" +#include "qw/include/cl_parse.h" -static qpic_t *scr_net; +static view_t *net_view; +static view_t *loading_view; +static view_t *graph_view; static void -SCR_DrawNet (void) +draw_pic (view_t *view) { - if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < - UPDATE_BACKUP - 1) - return; - if (cls.demoplayback) - return; - - if (!scr_net) - scr_net = r_funcs->Draw_PicFromWad ("net"); - - r_funcs->Draw_Pic (r_data->scr_vrect->x + 64, r_data->scr_vrect->y, - scr_net); + r_funcs->Draw_Pic (view->xabs, view->yabs, view->data); } static void -SCR_DrawLoading (void) +draw_cachepic (view_t *view) { - qpic_t *pic; - - if (!cl.loading) - return; - pic = r_funcs->Draw_CachePic ("gfx/loading.lmp", 1); - r_funcs->Draw_Pic ((r_data->vid->conwidth - pic->width) / 2, - (r_data->vid->conheight - 48 - pic->height) / 2, pic); + qpic_t *pic = r_funcs->Draw_CachePic (view->data, 1); + r_funcs->Draw_Pic (view->xabs, view->yabs, pic); } static void @@ -96,30 +86,49 @@ SCR_CShift (void) r_funcs->Draw_BlendScreen (r_data->vid->cshift_color); } +static void +scr_draw_views (void) +{ + net_view->visible = (!cls.demoplayback + && (cls.netchan.outgoing_sequence + - cls.netchan.incoming_acknowledged) + >= UPDATE_BACKUP - 1); + loading_view->visible = cl.loading; + graph_view->visible = r_netgraph->int_val != 0; + + //FIXME don't do every frame + view_move (graph_view, graph_view->xpos, sb_lines); + view_setgravity (graph_view, + hud_swap->int_val ? grav_southeast : grav_southwest); + + view_draw (r_data->vid->conview); +} + static SCR_Func scr_funcs_normal[] = { 0, //Draw_Crosshair, 0, //SCR_DrawRam, 0, //SCR_DrawTurtle, 0, //SCR_DrawPause, - SCR_DrawNet, - CL_NetGraph, + //CL_NetGraph,FIXME Sbar_Draw, SCR_CShift, Sbar_DrawCenterPrint, Con_DrawConsole, - SCR_DrawLoading, + scr_draw_views, 0 }; static SCR_Func scr_funcs_intermission[] = { Sbar_IntermissionOverlay, Con_DrawConsole, + scr_draw_views, 0 }; static SCR_Func scr_funcs_finale[] = { Sbar_FinaleOverlay, Con_DrawConsole, + scr_draw_views, 0, }; @@ -137,6 +146,35 @@ CL_UpdateScreen (double realtime) if (index >= sizeof (scr_funcs) / sizeof (scr_funcs[0])) index = 0; + if (!net_view) { + qpic_t *pic = r_funcs->Draw_PicFromWad ("net"); + net_view = view_new (64, 0, pic->width, pic->height, grav_northwest); + net_view->draw = draw_pic; + net_view->data = pic; + net_view->visible = 0; + view_add (r_data->scr_view, net_view); + } + + if (!loading_view) { + const char *name = "gfx/loading.lmp"; + qpic_t *pic = r_funcs->Draw_CachePic (name, 1); + loading_view = view_new (0, -24, pic->width, pic->height, grav_center); + loading_view->draw = draw_cachepic; + loading_view->data = (void *) name; + loading_view->visible = 0; + view_add (r_data->vid->conview, loading_view); + } + + if (!graph_view) { + graph_view = view_new (0, -24, + NET_TIMINGS + 16, + r_data->graphheight->int_val + 25, + grav_southwest); + graph_view->draw = CL_NetGraph; + graph_view->visible = 0; + view_add (r_data->vid->conview, graph_view); + } + //FIXME not every time if (cls.state == ca_active) { if (cl.watervis) diff --git a/qw/source/sbar.c b/qw/source/sbar.c index c3af7a2f0..ca8d7b74d 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -123,15 +123,12 @@ hud_swap_f (cvar_t *var) { hudswap = var->int_val; if (var->int_val) { - hud_armament_view->gravity = grav_southwest; - stuff_view->gravity = grav_southeast; + view_setgravity (hud_armament_view, grav_southwest); + view_setgravity (stuff_view, grav_southeast); } else { - hud_armament_view->gravity = grav_southeast; - stuff_view->gravity = grav_southwest; + view_setgravity (hud_armament_view, grav_southeast); + view_setgravity (stuff_view, grav_southwest); } - view_move (hud_armament_view, hud_armament_view->xpos, - hud_armament_view->ypos); - view_move (stuff_view, stuff_view->xpos, stuff_view->ypos); } static void @@ -571,7 +568,7 @@ draw_weapons_hud (view_t *view) if (view->parent->gravity == grav_southeast) x = view->xlen - 24; - for (i = r_data->vid->conheight < 204; i < 7; i++) { + for (i = r_data->vid->conview->ylen < 204; i < 7; i++) { if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); draw_subpic (view, x, i * 16, sb_weapons[flashon][i], 0, 0, 24, 16); @@ -903,7 +900,7 @@ Sbar_DeathmatchOverlay (view_t *view, int start) int l, y; int skip = 10; - if (r_data->vid->conwidth < 244) // FIXME: magic number, gained through experimentation + if (r_data->vid->conview->xlen < 244) // FIXME: magic number, gained through experimentation return; if (largegame) @@ -1056,7 +1053,7 @@ sbar_update_vis (void) return; if (con_module - && con_module->data->console->lines == r_data->vid->conheight) + && con_module->data->console->lines == r_data->vid->conview->ylen) return; // console is full screen if (!sb_lines) @@ -1750,12 +1747,12 @@ init_sbar_views (void) view_t *minifrags_view = 0; view_t *miniteam_view = 0; - if (r_data->vid->conwidth < 512) { + if (r_data->vid->conview->xlen < 512) { sbar_view = view_new (0, 0, 320, 48, grav_south); sbar_frags_view = view_new (0, 0, 130, 8, grav_northeast); sbar_frags_view->draw = draw_frags; - } else if (r_data->vid->conwidth < 640) { + } else if (r_data->vid->conview->xlen < 640) { sbar_view = view_new (0, 0, 512, 48, grav_south); minifrags_view = view_new (320, 0, 192, 48, grav_southwest); minifrags_view->draw = draw_minifrags; @@ -1817,8 +1814,8 @@ init_sbar_views (void) if (miniteam_view) view_add (sbar_view, miniteam_view); - if (r_data->vid->conwidth > 640) { - int l = (r_data->vid->conwidth - 640) / 2; + if (r_data->vid->conview->xlen > 640) { + int l = (r_data->vid->conview->xlen - 640) / 2; view = view_new (-l, 0, l, 48, grav_southwest); view->draw = draw_tile; @@ -1839,12 +1836,12 @@ init_hud_views (void) view_t *minifrags_view = 0; view_t *miniteam_view = 0; - if (r_data->vid->conwidth < 512) { + if (r_data->vid->conview->xlen < 512) { hud_view = view_new (0, 0, 320, 48, grav_south); hud_frags_view = view_new (0, 0, 130, 8, grav_northeast); hud_frags_view->draw = draw_frags; - } else if (r_data->vid->conwidth < 640) { + } else if (r_data->vid->conview->xlen < 640) { hud_view = view_new (0, 0, 512, 48, grav_south); minifrags_view = view_new (320, 0, 192, 48, grav_southwest); @@ -1896,7 +1893,7 @@ init_hud_views (void) if (miniteam_view) view_add (hud_view, miniteam_view); - view = view_new (0, 0, r_data->vid->conwidth, 48, grav_south); + view = view_new (0, 0, r_data->vid->conview->xlen, 48, grav_south); view_add (view, hud_view); hud_view = view; @@ -1908,17 +1905,18 @@ init_hud_views (void) static void init_views (void) { - main_view = view_new (0, 0, r_data->vid->conwidth, r_data->vid->conheight, + main_view = view_new (0, 0, r_data->vid->conview->xlen, + r_data->vid->conview->ylen, grav_northwest); if (con_module) view_insert (con_module->data->console->view, main_view, 0); main_view->resize_x = 1; // get resized if the 2d view resizes main_view->resize_y = 1; main_view->visible = 0; // but don't let the console draw our stuff - if (r_data->vid->conheight > 300) + if (r_data->vid->conview->ylen > 300) overlay_view = view_new (0, 0, 320, 300, grav_center); else - overlay_view = view_new (0, 0, 320, r_data->vid->conheight, + overlay_view = view_new (0, 0, 320, r_data->vid->conview->ylen, grav_center); overlay_view->draw = draw_overlay; overlay_view->visible = 0; From ed606fb670db1042214d7d0285306c9779d8bdc6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Jul 2021 18:30:46 +0900 Subject: [PATCH 1625/3664] [render] Fix some incorrect r_data references The render plugins have made a bit of a mess of getting at the data and thus it's a tad confusing how to get at it in different places. Really needs a proper cleanup :( --- libs/video/renderer/r_screen.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index f1701c7ba..f1ed6c349 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -182,7 +182,7 @@ SCR_CalcRefdef (void) R_SetVrect (&vrect, &refdef->vrect, r_data->lineadj); - view_setgeometry (vr_data.scr_view, refdef->vrect.x, refdef->vrect.y, + view_setgeometry (r_data->scr_view, refdef->vrect.x, refdef->vrect.y, refdef->vrect.width, refdef->vrect.height); // notify the refresh of the change @@ -265,7 +265,7 @@ SCR_DrawRam (void) return; //FIXME view - r_funcs->Draw_Pic (vr_data.scr_view->xpos + 32, vr_data.scr_view->ypos, + r_funcs->Draw_Pic (r_data->scr_view->xpos + 32, r_data->scr_view->ypos, scr_ram); } @@ -287,7 +287,7 @@ SCR_DrawTurtle (void) return; //FIXME view - r_funcs->Draw_Pic (vr_data.scr_view->xpos, vr_data.scr_view->ypos, + r_funcs->Draw_Pic (r_data->scr_view->xpos, r_data->scr_view->ypos, scr_turtle); } From 34dd434147e1b74afdc2d80a6e37f252ee38478f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Jul 2021 18:31:22 +0900 Subject: [PATCH 1626/3664] [qwaq] Fix missing gib library references Not sure why static builds worked and dynamic didn't, but... --- ruamoko/qwaq/Makemodule.am | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index b4a6cedf5..30f07a8d2 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -85,6 +85,7 @@ qwaq_client_libs= \ qwaq_x11_libs= \ $(qwaq_cl_plugin_libs) \ + ${top_builddir}/libs/gib/libQFgib.la \ ${top_builddir}/libs/ruamoko/libQFruamoko_client.la \ $(top_builddir)/libs/video/renderer/libQFrenderer.la \ $(top_builddir)/libs/models/libQFmodels.la \ From a05210d8640e26d7148b71f3221857f56de9d05b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 00:09:41 +0900 Subject: [PATCH 1627/3664] [video] Get 16 and 32 bit sw32 mostly working in x11 Lighting on alias models seems to be borked, and skies are borked in both sw renderers (seems to be nothing to do with this commit, though). --- include/context_x11.h | 3 +- include/d_iface.h | 1 - include/r_internal.h | 10 +- include/vid_internal.h | 17 +- include/vid_sw.h | 5 +- libs/video/renderer/gl/vid_common_gl.c | 2 +- libs/video/renderer/glsl/vid_common_glsl.c | 2 +- libs/video/renderer/sw/d_surf.c | 6 +- libs/video/renderer/sw/draw.c | 2 +- libs/video/renderer/sw/screen.c | 2 +- libs/video/renderer/sw32/d_edge.c | 5 +- libs/video/renderer/sw32/d_fill.c | 6 +- libs/video/renderer/sw32/d_init.c | 3 +- libs/video/renderer/sw32/d_modech.c | 3 +- libs/video/renderer/sw32/d_part.c | 5 +- libs/video/renderer/sw32/d_polyse.c | 5 +- libs/video/renderer/sw32/d_scan.c | 15 +- libs/video/renderer/sw32/d_sky.c | 5 +- libs/video/renderer/sw32/d_sprite.c | 5 +- libs/video/renderer/sw32/d_surf.c | 15 +- libs/video/renderer/sw32/d_zpoint.c | 5 +- libs/video/renderer/sw32/draw.c | 39 ++-- libs/video/renderer/sw32/screen.c | 6 +- libs/video/renderer/sw32/sw32_graph.c | 5 +- libs/video/renderer/sw32/sw32_ralias.c | 13 +- libs/video/renderer/sw32/sw32_rmain.c | 1 - libs/video/renderer/sw32/sw32_rsky.c | 5 +- libs/video/renderer/sw32/sw32_rsurf.c | 9 +- libs/video/renderer/vid_render_gl.c | 5 +- libs/video/renderer/vid_render_glsl.c | 5 +- libs/video/renderer/vid_render_sw.c | 13 +- libs/video/renderer/vid_render_sw32.c | 15 +- libs/video/renderer/vid_render_vulkan.c | 7 +- libs/video/targets/context_sdl.c | 5 - libs/video/targets/vid.c | 30 +-- libs/video/targets/vid_x11.c | 8 +- libs/video/targets/vid_x11_sw.c | 214 ++++++++++++++++++++- 37 files changed, 371 insertions(+), 131 deletions(-) diff --git a/include/context_x11.h b/include/context_x11.h index 884fafe9e..7f60f44fa 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -81,7 +81,8 @@ struct gl_ctx_s *X11_GL_Context (void); void X11_GL_Init_Cvars (void); struct sw_ctx_s *X11_SW_Context (void); -void X11_SW_Init_Cvars (void); +struct sw_ctx_s *X11_SW32_Context (void); +void X11_SW_Init_Cvars (void); // sw and sw32 cvars shared struct vulkan_ctx_s *X11_Vulkan_Context (void); void X11_Vulkan_Init_Cvars (void); diff --git a/include/d_iface.h b/include/d_iface.h index aa0c16e08..621ccbaca 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -158,7 +158,6 @@ extern qboolean r_recursiveaffinetriangles; // true if a driver wants to use // a certain distance (normally // used only by the software // driver) -extern int r_pixbytes; extern qboolean r_dowarp; extern affinetridesc_t r_affinetridesc; diff --git a/include/r_internal.h b/include/r_internal.h index 58a4e7599..8fa0f06d6 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -94,10 +94,10 @@ void R_PushDlights (const vec3_t entorigin); void R_DrawWaterSurfaces (void); void *D_SurfaceCacheAddress (void) __attribute__((pure)); -int D_SurfaceCacheForRes (int width, int height); -void D_FlushCaches (void); +int D_SurfaceCacheForRes (void *data, int width, int height); +void D_FlushCaches (void *data); void D_DeleteSurfaceCache (void); -void D_InitCaches (void *buffer, int size); +void D_InitCaches (void *data, void *buffer, int size); void R_SetVrect (const vrect_t *pvrect, vrect_t *pvrectin, int lineadj); void R_LoadSkys (const char *); @@ -119,7 +119,7 @@ void R_DrawAliasModel (entity_t *e); void R_MarkLeaves (void); -void GL_SetPalette (const byte *palette); -void GLSL_SetPalette (const byte *palette); +void GL_SetPalette (void *data, const byte *palette); +void GLSL_SetPalette (void *data, const byte *palette); #endif//__r_internal_h diff --git a/include/vid_internal.h b/include/vid_internal.h index c54f11492..035f36170 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -5,17 +5,20 @@ #include "QF/plugin/vid_render.h" typedef struct vid_internal_s { - int (*surf_cache_size) (int width, int height); - void (*flush_caches) (void); - void (*init_caches) (void *cache, int size); - void (*init_buffers) (void); - void (*set_palette) (const byte *palette); + int (*surf_cache_size) (void *data, int width, int height); + void (*flush_caches) (void *data); + void (*init_caches) (void *data, void *cache, int size); + void (*init_buffers) (void *data); + void (*set_palette) (void *data, const byte *palette); - void (*choose_visual) (void); - void (*create_context) (void); + void (*choose_visual) (void *data); + void (*create_context) (void *data); + + void *data; struct gl_ctx_s *(*gl_context) (void); struct sw_ctx_s *(*sw_context) (void); + struct sw_ctx_s *(*sw32_context) (void); struct vulkan_ctx_s *(*vulkan_context) (void); } vid_internal_t; diff --git a/include/vid_sw.h b/include/vid_sw.h index e57d3ee0d..cd60a6d56 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -3,10 +3,11 @@ struct vrect_s; typedef struct sw_ctx_s { + int pixbytes; void (*choose_visual) (struct sw_ctx_s *ctx); void (*create_context) (struct sw_ctx_s *ctx); - void (*set_palette) (const byte *palette); - void (*update) (struct vrect_s *rects); + void (*set_palette) (struct sw_ctx_s *ctx, const byte *palette); + void (*update) (struct sw_ctx_s *ctx, struct vrect_s *rects); } sw_ctx_t; extern sw_ctx_t *sw_ctx; diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index 7eccad855..168cc0d4c 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -701,7 +701,7 @@ VID_Init8bitPalette (void) } void -GL_SetPalette (const byte *palette) +GL_SetPalette (void *data, const byte *palette) { const byte *pal; char s[255]; diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index 612082480..4ca5bc45e 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -69,7 +69,7 @@ GLSL_Common_Init_Cvars (void) } void -GLSL_SetPalette (const byte *palette) +GLSL_SetPalette (void *data, const byte *palette) { const byte *col, *ip; byte *pal, *op; diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 2a8f2f6c3..b348bdeda 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -54,7 +54,7 @@ D_SurfaceCacheAddress (void) } int -D_SurfaceCacheForRes (int width, int height) +D_SurfaceCacheForRes (void *data, int width, int height) { int size, pix; @@ -96,7 +96,7 @@ D_ClearCacheGuard (void) } void -D_InitCaches (void *buffer, int size) +D_InitCaches (void *data, void *buffer, int size) { Sys_MaskPrintf (SYS_dev, "D_InitCaches: %ik surface cache\n", size/1024); @@ -114,7 +114,7 @@ D_InitCaches (void *buffer, int size) } void -D_FlushCaches (void) +D_FlushCaches (void *data) { surfcache_t *c; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 603ad25a3..a73b9a734 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -828,5 +828,5 @@ Draw_BlendScreen (quat_t color) newpal[2] = vid.gammatable[b]; newpal += 3; } - vid.vid_internal->set_palette (pal); + vid.vid_internal->set_palette (vid.vid_internal->data, pal); } diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index ee6533eb6..c833ee200 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -240,5 +240,5 @@ R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) vrect.height = vr_data.scr_view->ylen; vrect.next = 0; } - sw_ctx->update (&vrect); + sw_ctx->update (sw_ctx, &vrect); } diff --git a/libs/video/renderer/sw32/d_edge.c b/libs/video/renderer/sw32/d_edge.c index 6015eaf23..adcc62981 100644 --- a/libs/video/renderer/sw32/d_edge.c +++ b/libs/video/renderer/sw32/d_edge.c @@ -39,6 +39,7 @@ #include "d_local.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" static int miplevel; @@ -81,7 +82,7 @@ D_DrawSolidSurface (surf_t *surf, int color) { espan_t *span; - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { byte *pdest, pix; @@ -132,7 +133,7 @@ D_DrawSolidSurface (surf_t *surf, int color) break; default: Sys_Error("D_DrawSolidSurface: unsupported r_pixbytes %i", - sw32_r_pixbytes); + sw32_ctx->pixbytes); } } diff --git a/libs/video/renderer/sw32/d_fill.c b/libs/video/renderer/sw32/d_fill.c index a4843de35..79cf71cfe 100644 --- a/libs/video/renderer/sw32/d_fill.c +++ b/libs/video/renderer/sw32/d_fill.c @@ -36,12 +36,12 @@ #include "d_iface.h" #include "r_internal.h" #include "vid_internal.h" - +#include "vid_sw.h" void sw32_D_FillRect (vrect_t *rect, int color) { - switch (sw32_r_pixbytes) + switch (sw32_ctx->pixbytes) { case 1: { @@ -159,6 +159,6 @@ sw32_D_FillRect (vrect_t *rect, int color) } break; default: - Sys_Error("D_FillRect: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("D_FillRect: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } diff --git a/libs/video/renderer/sw32/d_init.c b/libs/video/renderer/sw32/d_init.c index e786cf32b..28d0ea85f 100644 --- a/libs/video/renderer/sw32/d_init.c +++ b/libs/video/renderer/sw32/d_init.c @@ -38,6 +38,7 @@ #include "d_local.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" #define NUM_MIPS 4 @@ -105,7 +106,7 @@ sw32_D_SetupFrame (void) if (sw32_r_dowarp) sw32_screenwidth = WARP_WIDTH; else - sw32_screenwidth = vid.rowbytes / sw32_r_pixbytes; + sw32_screenwidth = vid.rowbytes / sw32_ctx->pixbytes; sw32_d_roverwrapped = false; sw32_d_initial_rover = sw32_sc_rover; diff --git a/libs/video/renderer/sw32/d_modech.c b/libs/video/renderer/sw32/d_modech.c index 14d1c690c..71497b5f3 100644 --- a/libs/video/renderer/sw32/d_modech.c +++ b/libs/video/renderer/sw32/d_modech.c @@ -35,6 +35,7 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_sw.h" int sw32_d_vrectx, sw32_d_vrecty, sw32_d_vrectright_particle, sw32_d_vrectbottom_particle; @@ -57,7 +58,7 @@ sw32_D_ViewChanged (void) if (sw32_r_dowarp) rowpixels = WARP_WIDTH; else - rowpixels = vid.rowbytes / sw32_r_pixbytes; + rowpixels = vid.rowbytes / sw32_ctx->pixbytes; sw32_scale_for_mip = sw32_xscale; if (sw32_yscale > sw32_xscale) diff --git a/libs/video/renderer/sw32/d_part.c b/libs/video/renderer/sw32/d_part.c index 30b969a0f..4b30fc398 100644 --- a/libs/video/renderer/sw32/d_part.c +++ b/libs/video/renderer/sw32/d_part.c @@ -36,6 +36,7 @@ #include "d_local.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" void @@ -78,7 +79,7 @@ sw32_D_DrawParticle (particle_t *pparticle) else if (pix > sw32_d_pix_max) pix = sw32_d_pix_max; - switch(sw32_r_pixbytes) + switch(sw32_ctx->pixbytes) { case 1: { @@ -368,6 +369,6 @@ sw32_D_DrawParticle (particle_t *pparticle) break; default: Sys_Error("D_DrawParticles: unsupported r_pixbytes %i", - sw32_r_pixbytes); + sw32_ctx->pixbytes); } } diff --git a/libs/video/renderer/sw32/d_polyse.c b/libs/video/renderer/sw32/d_polyse.c index 25d6a3c58..88fe6e13f 100644 --- a/libs/video/renderer/sw32/d_polyse.c +++ b/libs/video/renderer/sw32/d_polyse.c @@ -36,6 +36,7 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_sw.h" static int ubasestep, errorterm, erroradjustup, erroradjustdown; @@ -383,7 +384,7 @@ D_PolysetDrawSpans (spanpackage_t * pspanpackage) texscantable[i] = j; texscan = texscantable + sw32_r_affinetridesc.skinheight; - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { int lcount, count = 0; @@ -622,7 +623,7 @@ done32: ; default: Sys_Error("D_PolysetDrawSpans: unsupported r_pixbytes %i", - sw32_r_pixbytes); + sw32_ctx->pixbytes); } } diff --git a/libs/video/renderer/sw32/d_scan.c b/libs/video/renderer/sw32/d_scan.c index b49f758d5..50ef352da 100644 --- a/libs/video/renderer/sw32/d_scan.c +++ b/libs/video/renderer/sw32/d_scan.c @@ -40,6 +40,7 @@ #include "d_local.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" static byte *r_turb_pbase; static void *r_turb_pdest; @@ -56,7 +57,7 @@ static int r_turb_spancount; void sw32_D_WarpScreen (void) { - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { int w, h; @@ -205,7 +206,7 @@ sw32_D_WarpScreen (void) } break; default: - Sys_Error("D_WarpScreen: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("D_WarpScreen: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } @@ -214,7 +215,7 @@ D_DrawTurbulentSpan (void) { int sturb, tturb; - switch (sw32_r_pixbytes) { + switch (sw32_ctx->pixbytes) { case 1: { byte *pdest = (byte *) r_turb_pdest; @@ -262,7 +263,7 @@ D_DrawTurbulentSpan (void) break; default: Sys_Error("D_DrawTurbulentSpan: unsupported r_pixbytes %i", - sw32_r_pixbytes); + sw32_ctx->pixbytes); } } @@ -287,7 +288,7 @@ sw32_Turbulent (espan_t *pspan) do { r_turb_pdest = (byte *) sw32_d_viewbuffer + ((sw32_screenwidth * pspan->v) + - pspan->u) * sw32_r_pixbytes; + pspan->u) * sw32_ctx->pixbytes; count = pspan->count; @@ -394,7 +395,7 @@ sw32_Turbulent (espan_t *pspan) void sw32_D_DrawSpans (espan_t *pspan) { - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { byte *pbase = (byte *) sw32_cacheblock, *pdest; @@ -812,7 +813,7 @@ sw32_D_DrawSpans (espan_t *pspan) } break; default: - Sys_Error("D_DrawSpans: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("D_DrawSpans: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } diff --git a/libs/video/renderer/sw32/d_sky.c b/libs/video/renderer/sw32/d_sky.c index 6ceb6095a..989fd4369 100644 --- a/libs/video/renderer/sw32/d_sky.c +++ b/libs/video/renderer/sw32/d_sky.c @@ -36,6 +36,7 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_sw.h" #define SKY_SPAN_SHIFT 5 #define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT) @@ -69,7 +70,7 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) void sw32_D_DrawSkyScans (espan_t *pspan) { - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { int count, spancount, u, v; @@ -278,6 +279,6 @@ sw32_D_DrawSkyScans (espan_t *pspan) break; default: - Sys_Error("D_DrawSkyScans: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("D_DrawSkyScans: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } diff --git a/libs/video/renderer/sw32/d_sprite.c b/libs/video/renderer/sw32/d_sprite.c index fd5fe73f7..d81fda3bb 100644 --- a/libs/video/renderer/sw32/d_sprite.c +++ b/libs/video/renderer/sw32/d_sprite.c @@ -38,6 +38,7 @@ #include "d_local.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" static int sprite_height; static int minindex, maxindex; @@ -48,7 +49,7 @@ static sspan_t *sprite_spans; void sw32_D_SpriteDrawSpans (sspan_t *pspan) { - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { int count, spancount, izistep; @@ -504,7 +505,7 @@ NextSpan4: default: Sys_Error("D_SpriteDrawSpans: unsupported r_pixbytes %i", - sw32_r_pixbytes); + sw32_ctx->pixbytes); } } diff --git a/libs/video/renderer/sw32/d_surf.c b/libs/video/renderer/sw32/d_surf.c index 914c0b9c6..3840d8f53 100644 --- a/libs/video/renderer/sw32/d_surf.c +++ b/libs/video/renderer/sw32/d_surf.c @@ -40,6 +40,7 @@ #include "compat.h" #include "d_local.h" #include "r_internal.h" +#include "vid_sw.h" static float surfscale; @@ -58,7 +59,7 @@ sw32_D_SurfaceCacheAddress (void) int -sw32_D_SurfaceCacheForRes (int width, int height) +sw32_D_SurfaceCacheForRes (void *data, int width, int height) { int size, pix; @@ -73,7 +74,7 @@ sw32_D_SurfaceCacheForRes (int width, int height) if (pix > 64000) size += (pix - 64000) * 3; - size *= sw32_r_pixbytes; + size *= sw32_ctx->pixbytes; return size; } @@ -105,7 +106,7 @@ D_ClearCacheGuard (void) void -sw32_D_InitCaches (void *buffer, int size) +sw32_D_InitCaches (void *data, void *buffer, int size) { Sys_MaskPrintf (SYS_dev, "D_InitCaches: %ik surface cache\n", size/1024); @@ -124,7 +125,7 @@ sw32_D_InitCaches (void *buffer, int size) void -sw32_D_FlushCaches (void) +sw32_D_FlushCaches (void *data) { surfcache_t *c; @@ -152,7 +153,7 @@ D_SCAlloc (int width, int size) if ((width < 0) || (width > 512)) // FIXME shouldn't really have a max Sys_Error ("D_SCAlloc: bad cache width %d", width); - if ((size <= 0) || (size > (0x40000 * sw32_r_pixbytes))) //FIXME ditto + if ((size <= 0) || (size > (0x40000 * sw32_ctx->pixbytes))) //FIXME ditto Sys_Error ("D_SCAlloc: bad cache size %d", size); /* This adds the offset of data[0] in the surfcache_t struct. */ @@ -207,7 +208,7 @@ D_SCAlloc (int width, int size) // DEBUG if (width > 0) new->height = (size - sizeof (*new) + sizeof (new->data)) / - (width * sw32_r_pixbytes); + (width * sw32_ctx->pixbytes); new->owner = NULL; // should be set properly after return @@ -250,7 +251,7 @@ sw32_D_CacheSurface (msurface_t *surface, int miplevel) surfscale = 1.0 / (1 << miplevel); sw32_r_drawsurf.surfmip = miplevel; sw32_r_drawsurf.surfwidth = surface->extents[0] >> miplevel; - sw32_r_drawsurf.rowbytes = sw32_r_drawsurf.surfwidth * sw32_r_pixbytes; + sw32_r_drawsurf.rowbytes = sw32_r_drawsurf.surfwidth * sw32_ctx->pixbytes; sw32_r_drawsurf.surfheight = surface->extents[1] >> miplevel; // allocate memory if needed diff --git a/libs/video/renderer/sw32/d_zpoint.c b/libs/video/renderer/sw32/d_zpoint.c index 24c8e4569..5d0ab372b 100644 --- a/libs/video/renderer/sw32/d_zpoint.c +++ b/libs/video/renderer/sw32/d_zpoint.c @@ -36,6 +36,7 @@ #include "d_local.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" void @@ -49,7 +50,7 @@ sw32_D_DrawZPoint (void) if (*pz <= izi) { *pz = izi; - switch(sw32_r_pixbytes) + switch(sw32_ctx->pixbytes) { case 1: ((byte *) sw32_d_viewbuffer) [sw32_d_scantable[sw32_r_zpointdesc.v] + @@ -66,7 +67,7 @@ sw32_D_DrawZPoint (void) d_8to24table[sw32_r_zpointdesc.color]; break; default: - Sys_Error("D_DrawZPoint: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("D_DrawZPoint: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } } diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c index 9d1e038cf..ea630fc28 100644 --- a/libs/video/renderer/sw32/draw.c +++ b/libs/video/renderer/sw32/draw.c @@ -50,6 +50,7 @@ #include "d_iface.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" typedef struct { vrect_t rect; @@ -283,7 +284,7 @@ sw32_Draw_Character (int x, int y, unsigned int chr) drawline = 8; - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { byte *dest = (byte *) vid.conbuffer + y * vid.conrowbytes + x; @@ -367,7 +368,7 @@ sw32_Draw_Character (int x, int y, unsigned int chr) } break; default: - Sys_Error("Draw_Character: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("Draw_Character: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } @@ -403,7 +404,7 @@ sw32_Draw_AltString (int x, int y, const char *str) static void Draw_Pixel (int x, int y, byte color) { - switch(sw32_r_pixbytes) + switch(sw32_ctx->pixbytes) { case 1: ((byte *) vid.conbuffer)[y * vid.conrowbytes + x] = color; @@ -417,7 +418,7 @@ Draw_Pixel (int x, int y, byte color) d_8to24table[color]; break; default: - Sys_Error("Draw_Pixel: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("Draw_Pixel: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } @@ -570,7 +571,7 @@ sw32_Draw_Pic (int x, int y, qpic_t *pic) source = pic->data; - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; @@ -643,7 +644,7 @@ sw32_Draw_Pic (int x, int y, qpic_t *pic) } break; default: - Sys_Error("Draw_Pic: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("Draw_Pic: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } @@ -688,7 +689,7 @@ sw32_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, source = pic->data + srcy * pic->width + srcx; - switch (sw32_r_pixbytes) { + switch (sw32_ctx->pixbytes) { case 1: { byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; @@ -725,7 +726,7 @@ sw32_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, } break; default: - Sys_Error("Draw_SubPic: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("Draw_SubPic: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } @@ -741,7 +742,7 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) conback = sw32_Draw_CachePic ("gfx/conback.lmp", true); // draw the pic - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { byte *dest = vid.conbuffer; @@ -812,7 +813,7 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) default: Sys_Error("Draw_ConsoleBackground: unsupported r_pixbytes %i", - sw32_r_pixbytes); + sw32_ctx->pixbytes); } // if (!cls.download) @@ -824,7 +825,7 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) static void R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) { - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { byte t; @@ -1097,7 +1098,7 @@ R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) } break; default: - Sys_Error("R_DrawRect: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("R_DrawRect: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } @@ -1183,7 +1184,7 @@ sw32_Draw_Fill (int x, int y, int w, int h, int c) } CLIP (x, y, w, h, (int) vid.width, (int) vid.height); - switch (sw32_r_pixbytes) { + switch (sw32_ctx->pixbytes) { case 1: { byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; @@ -1213,7 +1214,7 @@ sw32_Draw_Fill (int x, int y, int w, int h, int c) } break; default: - Sys_Error("Draw_Fill: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("Draw_Fill: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } } @@ -1227,7 +1228,7 @@ sw32_Draw_FadeScreen (void) S_ExtraUpdate (); VID_LockBuffer (); - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { for (y = 0; y < vid.conview->ylen; y++) { @@ -1264,7 +1265,7 @@ sw32_Draw_FadeScreen (void) } break; default: - Sys_Error("Draw_FadeScreen: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("Draw_FadeScreen: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } vr_data.scr_copyeverything = 1; @@ -1281,7 +1282,7 @@ sw32_Draw_BlendScreen (quat_t color) byte *newpal; byte pal[768]; - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { basepal = vid.basepal; @@ -1302,7 +1303,7 @@ sw32_Draw_BlendScreen (quat_t color) newpal[2] = vid.gammatable[b]; newpal += 3; } - vid.vid_internal->set_palette (pal); + vid.vid_internal->set_palette (vid.vid_internal->data, pal); } break; case 2: @@ -1367,6 +1368,6 @@ sw32_Draw_BlendScreen (quat_t color) break; default: Sys_Error("sw32_Draw_BlendScreen: unsupported r_pixbytes %i", - sw32_r_pixbytes); + sw32_ctx->pixbytes); } } diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index 201586432..e74e3434f 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -112,7 +112,7 @@ sw32_SCR_ScreenShot_f (void) sw32_D_EnableBackBufferAccess (); // save the pcx file - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: pcx = EncodePCX (vid.buffer, vid.width, vid.height, vid.rowbytes, vid.basepal, false, &pcx_len); @@ -124,7 +124,7 @@ sw32_SCR_ScreenShot_f (void) Sys_Printf("SCR_ScreenShot_f: FIXME - add 32bit support\n"); break; default: - Sys_Error("SCR_ScreenShot_f: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("SCR_ScreenShot_f: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } // for adapters that can't stay mapped in for linear writes all the time @@ -197,5 +197,5 @@ sw32_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) vrect.height = vr_data.scr_view->ylen; vrect.next = 0; } - sw32_ctx->update (&vrect); + sw32_ctx->update (sw32_ctx, &vrect); } diff --git a/libs/video/renderer/sw32/sw32_graph.c b/libs/video/renderer/sw32/sw32_graph.c index def69d39f..8da8dae55 100644 --- a/libs/video/renderer/sw32/sw32_graph.c +++ b/libs/video/renderer/sw32/sw32_graph.c @@ -38,6 +38,7 @@ #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" /* R_LineGraph @@ -67,7 +68,7 @@ sw32_R_LineGraph (int x, int y, int *h_vals, int count) if (h > s) h = s; - switch(sw32_r_pixbytes) { + switch(sw32_ctx->pixbytes) { case 1: { byte *dest = (byte *) vid.buffer + vid.rowbytes * y + x; @@ -95,7 +96,7 @@ sw32_R_LineGraph (int x, int y, int *h_vals, int count) break; default: Sys_Error("R_LineGraph: unsupported r_pixbytes %i", - sw32_r_pixbytes); + sw32_ctx->pixbytes); } } } diff --git a/libs/video/renderer/sw32/sw32_ralias.c b/libs/video/renderer/sw32/sw32_ralias.c index 1f8ef1cfd..b2750447b 100644 --- a/libs/video/renderer/sw32/sw32_ralias.c +++ b/libs/video/renderer/sw32/sw32_ralias.c @@ -28,6 +28,8 @@ # include "config.h" #endif +#include + #define NH_DEFINE #include "namehack.h" @@ -39,8 +41,7 @@ #include "d_ifacea.h" #include "r_internal.h" - -#include "stdlib.h" +#include "vid_sw.h" #define LIGHT_MIN 5 // lowest light value we'll allow, to // avoid the need for inner-loop light @@ -650,15 +651,15 @@ sw32_R_AliasDrawModel (alight_t *plighting) if (!sw32_acolormap) sw32_acolormap = vid.colormap8; - if (sw32_acolormap == &vid.colormap8 && sw32_r_pixbytes != 1) + if (sw32_acolormap == &vid.colormap8 && sw32_ctx->pixbytes != 1) { - if (sw32_r_pixbytes == 2) + if (sw32_ctx->pixbytes == 2) sw32_acolormap = vid.colormap16; - else if (sw32_r_pixbytes == 4) + else if (sw32_ctx->pixbytes == 4) sw32_acolormap = vid.colormap32; else Sys_Error("R_AliasDrawmodel: unsupported r_pixbytes %i", - sw32_r_pixbytes); + sw32_ctx->pixbytes); } if (currententity != vr_data.view_model) diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index ec334bb22..8da2648b2 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -62,7 +62,6 @@ int sw32_r_numallocatededges; qboolean sw32_r_drawpolys; qboolean sw32_r_drawculledpolys; qboolean sw32_r_worldpolysbacktofront; -int sw32_r_pixbytes = 1; float sw32_r_aliasuvscale = 1.0; int sw32_r_outofsurfaces; int sw32_r_outofedges; diff --git a/libs/video/renderer/sw32/sw32_rsky.c b/libs/video/renderer/sw32/sw32_rsky.c index ddc2a42f0..c07f07570 100644 --- a/libs/video/renderer/sw32/sw32_rsky.c +++ b/libs/video/renderer/sw32/sw32_rsky.c @@ -43,6 +43,7 @@ #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" static int iskyspeed = 8; @@ -128,7 +129,7 @@ sw32_R_MakeSky (void) xshift1 = xshift2 >> 1; yshift1 = yshift2 >> 1; - switch(sw32_r_pixbytes) + switch(sw32_ctx->pixbytes) { case 1: { @@ -188,7 +189,7 @@ sw32_R_MakeSky (void) } break; default: - Sys_Error("R_MakeSky: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("R_MakeSky: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } sw32_r_skymade = 1; } diff --git a/libs/video/renderer/sw32/sw32_rsurf.c b/libs/video/renderer/sw32/sw32_rsurf.c index 9eba575a9..2bfb5c000 100644 --- a/libs/video/renderer/sw32/sw32_rsurf.c +++ b/libs/video/renderer/sw32/sw32_rsurf.c @@ -37,6 +37,7 @@ #include "compat.h" #include "r_internal.h" +#include "vid_sw.h" drawsurf_t sw32_r_drawsurf; @@ -203,7 +204,7 @@ R_BuildLightMap (void) * JohnnyonFlame: * 32 and 16bpp modes uses the positive lighting, unlike 8bpp */ - switch (sw32_r_pixbytes) { + switch (sw32_ctx->pixbytes) { case 1: // bound, invert, and shift for (i = 0; i < size; i++) { @@ -272,7 +273,7 @@ sw32_R_DrawSurface (void) soffset = sw32_r_drawsurf.surf->texturemins[0]; basetoffset = sw32_r_drawsurf.surf->texturemins[1]; - switch (sw32_r_pixbytes) { + switch (sw32_ctx->pixbytes) { case 1: pblockdrawer = surfmiptable8[sw32_r_drawsurf.surfmip]; break; @@ -283,11 +284,11 @@ sw32_R_DrawSurface (void) pblockdrawer = surfmiptable32[sw32_r_drawsurf.surfmip]; break; default: - Sys_Error("R_DrawSurface: unsupported r_pixbytes %i", sw32_r_pixbytes); + Sys_Error("R_DrawSurface: unsupported r_pixbytes %i", sw32_ctx->pixbytes); pblockdrawer = NULL; } - horzblockstep = blocksize * sw32_r_pixbytes; + horzblockstep = blocksize * sw32_ctx->pixbytes; r_sourcemax = r_source + (tmax * smax); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 59549d830..aabb991be 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -46,13 +46,13 @@ gl_ctx_t *gl_ctx; static void -gl_vid_render_choose_visual (void) +gl_vid_render_choose_visual (void *data) { gl_ctx->choose_visual (gl_ctx); } static void -gl_vid_render_create_context (void) +gl_vid_render_create_context (void *data) { gl_ctx->create_context (gl_ctx); } @@ -93,6 +93,7 @@ gl_vid_render_init (void) gl_ctx->init_gl = GL_Init_Common; gl_ctx->load_gl (); + vr_data.vid->vid_internal->data = gl_ctx; vr_data.vid->vid_internal->set_palette = GL_SetPalette; vr_data.vid->vid_internal->choose_visual = gl_vid_render_choose_visual; vr_data.vid->vid_internal->create_context = gl_vid_render_create_context; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index d522d48a4..3c73ac0b5 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -46,13 +46,13 @@ gl_ctx_t *glsl_ctx; static void -glsl_vid_render_choose_visual (void) +glsl_vid_render_choose_visual (void *data) { glsl_ctx->choose_visual (glsl_ctx); } static void -glsl_vid_render_create_context (void) +glsl_vid_render_create_context (void *data) { glsl_ctx->create_context (glsl_ctx); } @@ -93,6 +93,7 @@ glsl_vid_render_init (void) glsl_ctx->init_gl = GLSL_Init_Common; glsl_ctx->load_gl (); + vr_data.vid->vid_internal->data = glsl_ctx; vr_data.vid->vid_internal->set_palette = GLSL_SetPalette; vr_data.vid->vid_internal->choose_visual = glsl_vid_render_choose_visual; vr_data.vid->vid_internal->create_context = glsl_vid_render_create_context; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index a518478cb..1be610d2e 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -39,17 +39,23 @@ sw_ctx_t *sw_ctx; static void -sw_vid_render_choose_visual (void) +sw_vid_render_choose_visual (void *data) { sw_ctx->choose_visual (sw_ctx); } static void -sw_vid_render_create_context (void) +sw_vid_render_create_context (void *data) { sw_ctx->create_context (sw_ctx); } +static void +sw_vid_render_set_palette (void *data, const byte *palette) +{ + sw_ctx->set_palette (sw_ctx, palette); +} + static vid_model_funcs_t model_funcs = { 0, sw_Mod_LoadLighting, @@ -84,7 +90,8 @@ sw_vid_render_init (void) } sw_ctx = vr_data.vid->vid_internal->sw_context (); - vr_data.vid->vid_internal->set_palette = sw_ctx->set_palette; + vr_data.vid->vid_internal->data = sw_ctx; + vr_data.vid->vid_internal->set_palette = sw_vid_render_set_palette; vr_data.vid->vid_internal->choose_visual = sw_vid_render_choose_visual; vr_data.vid->vid_internal->create_context = sw_vid_render_create_context; diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 9cd0c3a79..8e1aba57c 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -44,17 +44,23 @@ sw_ctx_t *sw32_ctx; static void -sw32_vid_render_choose_visual (void) +sw32_vid_render_choose_visual (void *data) { sw32_ctx->choose_visual (sw32_ctx); } static void -sw32_vid_render_create_context (void) +sw32_vid_render_create_context (void *data) { sw32_ctx->create_context (sw32_ctx); } +static void +sw32_vid_render_set_palette (void *data, const byte *palette) +{ + sw32_ctx->set_palette (sw32_ctx, palette); +} + static vid_model_funcs_t model_funcs = { 0, sw_Mod_LoadLighting, @@ -87,9 +93,10 @@ sw32_vid_render_init (void) if (!vr_data.vid->vid_internal->sw_context) { Sys_Error ("Sorry, software rendering not supported by this program."); } - sw32_ctx = vr_data.vid->vid_internal->sw_context (); + sw32_ctx = vr_data.vid->vid_internal->sw32_context (); - vr_data.vid->vid_internal->set_palette = sw32_ctx->set_palette; + vr_data.vid->vid_internal->data = sw32_ctx; + vr_data.vid->vid_internal->set_palette = sw32_vid_render_set_palette; vr_data.vid->vid_internal->choose_visual = sw32_vid_render_choose_visual; vr_data.vid->vid_internal->create_context = sw32_vid_render_create_context; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index e34768c6c..216285f0d 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -519,7 +519,7 @@ vulkan_Skin_InitTranslations (void) } static void -set_palette (const byte *palette) +set_palette (void *data, const byte *palette) { //FIXME really don't want this here: need an application domain //so Quake can be separated from QuakeForge (ie, Quake itself becomes @@ -527,7 +527,7 @@ set_palette (const byte *palette) } static void -vulkan_vid_render_choose_visual (void) +vulkan_vid_render_choose_visual (void *data) { Vulkan_CreateDevice (vulkan_ctx); vulkan_ctx->choose_visual (vulkan_ctx); @@ -546,7 +546,7 @@ vulkan_vid_render_choose_visual (void) } static void -vulkan_vid_render_create_context (void) +vulkan_vid_render_create_context (void *data) { vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); @@ -591,6 +591,7 @@ vulkan_vid_render_init (void) Vulkan_Init_Common (vulkan_ctx); + vr_data.vid->vid_internal->data = vulkan_ctx; vr_data.vid->vid_internal->set_palette = set_palette; vr_data.vid->vid_internal->choose_visual = vulkan_vid_render_choose_visual; vr_data.vid->vid_internal->create_context = vulkan_vid_render_create_context; diff --git a/libs/video/targets/context_sdl.c b/libs/video/targets/context_sdl.c index 21fde4b06..91a0927de 100644 --- a/libs/video/targets/context_sdl.c +++ b/libs/video/targets/context_sdl.c @@ -21,8 +21,6 @@ #include "context_sdl.h" #include "vid_internal.h" -cvar_t *vid_bitdepth; - void VID_SDL_GammaCheck (void) { @@ -73,7 +71,4 @@ SDL_Init_Cvars (void) "Toggles fullscreen mode"); vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, "Use system gamma control if available"); -// FIXME: vid_colorbpp in common GL setup, make consistent with sdl32 scheme - vid_bitdepth = Cvar_Get ("vid_bitdepth", "8", CVAR_ROM, NULL, "Sets " - "display bitdepth (supported modes: 8 16 32)"); } diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index cef424207..4c73fced2 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -50,6 +50,7 @@ /* Software and hardware gamma support */ #define viddef (*r_data->vid) +#define vi (viddef.vid_internal) cvar_t *vid_gamma; cvar_t *vid_system_gamma; cvar_t *con_width; // FIXME: Try to move with rest of con code @@ -211,7 +212,8 @@ VID_UpdateGamma (cvar_t *vid_gamma) *p32++ = 255; } p32[-1] = 0; // color 255 is transparent - viddef.vid_internal->set_palette (viddef.palette); // update with the new palette + // update with the new palette + vi->set_palette (vi->data, viddef.palette); } } @@ -254,9 +256,10 @@ VID_InitBuffers (void) // Calculate the sizes we want first buffersize = viddef.rowbytes * viddef.height; zbuffersize = viddef.width * viddef.height * sizeof (*viddef.zbuffer); - if (viddef.vid_internal->surf_cache_size) - cachesize = viddef.vid_internal->surf_cache_size (viddef.width, - viddef.height); + if (vi->surf_cache_size) { + cachesize = vi->surf_cache_size (vi->data, + viddef.width, viddef.height); + } // Free the old z-buffer if (viddef.zbuffer) { @@ -265,13 +268,14 @@ VID_InitBuffers (void) } // Free the old surface cache if (viddef.surfcache) { - if (viddef.vid_internal->flush_caches) - viddef.vid_internal->flush_caches (); + if (vi->flush_caches) { + vi->flush_caches (vi->data); + } free (viddef.surfcache); viddef.surfcache = NULL; } - if (viddef.vid_internal->init_buffers) { - viddef.vid_internal->init_buffers (); + if (vi->init_buffers) { + vi->init_buffers (vi->data); } else { // Free the old screen buffer if (viddef.buffer) { @@ -301,13 +305,15 @@ VID_InitBuffers (void) Sys_Error ("Not enough memory for video mode"); } - if (viddef.vid_internal->init_caches) - viddef.vid_internal->init_caches (viddef.surfcache, cachesize); + if (vi->init_caches) { + vi->init_caches (vi->data, viddef.surfcache, cachesize); + } } void VID_ClearMemory (void) { - if (viddef.vid_internal->flush_caches) - viddef.vid_internal->flush_caches (); + if (vi->flush_caches) { + vi->flush_caches (vi->data); + } } diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index dd3ec2a67..0bb695e3a 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -102,6 +102,7 @@ VID_Init (byte *palette, byte *colormap) vid_internal.gl_context = X11_GL_Context; vid_internal.sw_context = X11_SW_Context; + vid_internal.sw32_context = X11_SW32_Context; #ifdef HAVE_VULKAN vid_internal.vulkan_context = X11_Vulkan_Context; #endif @@ -116,14 +117,14 @@ VID_Init (byte *palette, byte *colormap) VID_GetWindowSize (640, 480); X11_OpenDisplay (); - vid_internal.choose_visual (); + vid_internal.choose_visual (vid_internal.data); X11_SetVidMode (viddef.width, viddef.height); X11_CreateWindow (viddef.width, viddef.height); X11_CreateNullCursor (); // hide mouse pointer - vid_internal.create_context (); + vid_internal.create_context (vid_internal.data); VID_InitGamma (palette); - viddef.vid_internal->set_palette (viddef.palette); + vid_internal.set_palette (vid_internal.data, viddef.palette); Sys_MaskPrintf (SYS_vid, "Video mode %dx%d initialized.\n", viddef.width, viddef.height); @@ -140,6 +141,7 @@ VID_Init_Cvars () X11_Vulkan_Init_Cvars (); #endif X11_GL_Init_Cvars (); + X11_SW_Init_Cvars (); } #if 0 diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index b88563a1a..f36847f56 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -69,6 +69,8 @@ int XShmGetEventBase (Display *x); // for broken X11 headers static GC x_gc; +static cvar_t *vid_bitdepth; + static qboolean doShm; static XShmSegmentInfo x_shminfo[2]; @@ -188,7 +190,7 @@ xlib_rgb24 (int r, int g, int b) } static void -x11_set_palette (const byte *palette) +x11_set_palette (sw_ctx_t *ctx, const byte *palette) { int i; XColor colors[256]; @@ -280,7 +282,7 @@ st3_fixup (XImage * framebuf, int x, int y, int width, int height) Flush the given rectangles from the view buffer to the screen. */ static void -x11_sw_update (vrect_t *rects) +x11_sw8_update (sw_ctx_t *ctx, vrect_t *rects) { while (rects) { switch (x_visinfo->depth) { @@ -319,6 +321,148 @@ x11_sw_update (vrect_t *rects) r_data->scr_fullupdate = 0; } +static void +x11_sw16_16_update (sw_ctx_t *ctx, vrect_t *rects) +{ + uint16_t *buffer = (uint16_t *) viddef.buffer; + XImage *framebuf = x_framebuffer[current_framebuffer]; + int rowbytes = framebuf->bytes_per_line; + + while (rects) { + int x = rects->x; + int y = rects->y; + int width = rects->width; + int height = rects->height; + for (int yi = y; yi < (y + height); yi++) { + uint16_t *src = buffer + yi * viddef.width + x; + PIXEL16 *dest = (PIXEL16 *) (framebuf->data + yi * rowbytes) + x; + + for (int count = width; count-- > 0; ) { + *dest++ = *src++; + } + } + if (doShm) { + if (!XShmPutImage (x_disp, x_win, x_gc, + x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height, True)) { + Sys_Error ("VID_Update: XShmPutImage failed"); + } + oktodraw = false; + while (!oktodraw) + X11_ProcessEvent (); + rects = rects->next; + + current_framebuffer = !current_framebuffer; + } else { + if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height)) { + Sys_Error ("VID_Update: XPutImage failed"); + } + rects = rects->next; + } + } + XSync (x_disp, False); + r_data->scr_fullupdate = 0; +} + +static void +x11_sw16_32_update (sw_ctx_t *ctx, vrect_t *rects) +{ + uint16_t *buffer = (uint16_t *) viddef.buffer; + XImage *framebuf = x_framebuffer[current_framebuffer]; + int rowbytes = framebuf->bytes_per_line; + + while (rects) { + int x = rects->x; + int y = rects->y; + int width = rects->width; + int height = rects->height; + for (int yi = y; yi < (y + height); yi++) { + uint16_t *src = buffer + yi * viddef.width + x; + PIXEL24 *dest = (PIXEL24 *) (framebuf->data + yi * rowbytes) + x; + + for (int count = width; count-- > 0; ) { + uint32_t c = *src++; + *dest++ = 0xff000000 + | ((c & 0xf800) << 8) + | ((c & 0x07e0) << 5) + | ((c & 0x001f) << 3); + } + } + if (doShm) { + if (!XShmPutImage (x_disp, x_win, x_gc, + x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height, True)) { + Sys_Error ("VID_Update: XShmPutImage failed"); + } + oktodraw = false; + while (!oktodraw) + X11_ProcessEvent (); + rects = rects->next; + + current_framebuffer = !current_framebuffer; + } else { + if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height)) { + Sys_Error ("VID_Update: XPutImage failed"); + } + rects = rects->next; + } + } + XSync (x_disp, False); + r_data->scr_fullupdate = 0; +} + +static void +x11_sw32_update (sw_ctx_t *ctx, vrect_t *rects) +{ + uint32_t *buffer = (uint32_t *) viddef.buffer; + XImage *framebuf = x_framebuffer[current_framebuffer]; + int rowbytes = framebuf->bytes_per_line; + + while (rects) { + int x = rects->x; + int y = rects->y; + int width = rects->width; + int height = rects->height; + for (int yi = y; yi < (y + height); yi++) { + uint32_t *src = buffer + yi * viddef.width + x; + PIXEL24 *dest = (PIXEL24 *) (framebuf->data + yi * rowbytes) + x; + + for (int count = width; count-- > 0; ) { + *dest++ = *src++; + } + } + if (doShm) { + if (!XShmPutImage (x_disp, x_win, x_gc, + x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height, True)) { + Sys_Error ("VID_Update: XShmPutImage failed"); + } + oktodraw = false; + while (!oktodraw) + X11_ProcessEvent (); + rects = rects->next; + + current_framebuffer = !current_framebuffer; + } else { + if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height)) { + Sys_Error ("VID_Update: XPutImage failed"); + } + rects = rects->next; + } + } + XSync (x_disp, False); + r_data->scr_fullupdate = 0; +} + static void x11_choose_visual (sw_ctx_t *ctx) { @@ -348,6 +492,34 @@ x11_choose_visual (sw_ctx_t *ctx) x_cmap = XCreateColormap (x_disp, x_win, x_vis, AllocAll); x_vis = x_visinfo->visual; + ctx->update = x11_sw8_update; + switch (x_visinfo->depth) { + case 8: + ctx->pixbytes = 1; + ctx->update = x11_sw8_update; + break; + case 16: + if (ctx->pixbytes > 2) { + ctx->pixbytes = 2; + } + if (ctx->pixbytes == 2) { + ctx->update = x11_sw16_16_update; + } + break; + case 24: + switch (ctx->pixbytes) { + case 1: + break; + case 2: + ctx->update = x11_sw16_32_update; + break; + case 4: + ctx->update = x11_sw32_update; + break; + } + break; + } + if (num_visuals > 1) { Sys_MaskPrintf (SYS_vid, "Found more than one visual id at depth %d:\n", @@ -461,8 +633,9 @@ ResetSharedFrameBuffers (void) } static void -x11_init_buffers (void) +x11_init_buffers (void *data) { + sw_ctx_t *ctx = data; if (doShm) ResetSharedFrameBuffers (); else @@ -471,11 +644,11 @@ x11_init_buffers (void) current_framebuffer = 0; viddef.direct = 0; - viddef.rowbytes = viddef.width; + viddef.rowbytes = ctx->pixbytes * viddef.width; if (x_visinfo->depth != 8) { if (viddef.buffer) free (viddef.buffer); - viddef.buffer = calloc (viddef.width, viddef.height); + viddef.buffer = calloc (viddef.rowbytes, viddef.height); if (!viddef.buffer) Sys_Error ("Not enough memory for video mode"); } else { @@ -527,14 +700,43 @@ sw_ctx_t * X11_SW_Context (void) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); + ctx->pixbytes = 1; ctx->set_palette = x11_set_palette; ctx->choose_visual = x11_choose_visual; ctx->create_context = x11_create_context; - ctx->update = x11_sw_update; + ctx->update = x11_sw8_update; + return ctx; +} + +sw_ctx_t * +X11_SW32_Context (void) +{ + sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); + ctx->pixbytes = 1; + ctx->set_palette = x11_set_palette; + ctx->choose_visual = x11_choose_visual; + ctx->create_context = x11_create_context; + + switch (vid_bitdepth->int_val) { + case 8: + ctx->pixbytes = 1; + break; + case 16: + ctx->pixbytes = 2; + break; + case 32: + ctx->pixbytes = 4; + break; + default: + Sys_Error ("X11_SW32_Context: unsupported bit depth"); + } return ctx; } void X11_SW_Init_Cvars (void) { +// FIXME: vid_colorbpp in common GL setup, make consistent with sdl32 scheme + vid_bitdepth = Cvar_Get ("vid_bitdepth", "8", CVAR_ROM, NULL, "Sets " + "display bitdepth (supported modes: 8 16 32)"); } From c4cc5b2756a8d32f3f5738f3bfae8612d3badf21 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 00:12:03 +0900 Subject: [PATCH 1628/3664] [sw32] Fix the over-tall netgraph lines --- libs/video/renderer/sw32/sw32_graph.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/sw32/sw32_graph.c b/libs/video/renderer/sw32/sw32_graph.c index 8da8dae55..d17c08970 100644 --- a/libs/video/renderer/sw32/sw32_graph.c +++ b/libs/video/renderer/sw32/sw32_graph.c @@ -72,7 +72,7 @@ sw32_R_LineGraph (int x, int y, int *h_vals, int count) case 1: { byte *dest = (byte *) vid.buffer + vid.rowbytes * y + x; - for (i = 0; i < h; i++, dest -= vid.rowbytes * 2) + for (i = 0; i < h; i++, dest -= vid.rowbytes) *dest = color; } break; @@ -81,7 +81,7 @@ sw32_R_LineGraph (int x, int y, int *h_vals, int count) short *dest = (short *) vid.buffer + (vid.rowbytes >> 1) * y + x; color = sw32_8to16table[color]; - for (i = 0; i < h; i++, dest -= vid.rowbytes) + for (i = 0; i < h; i++, dest -= (vid.rowbytes >> 1)) *dest = color; } break; @@ -90,7 +90,7 @@ sw32_R_LineGraph (int x, int y, int *h_vals, int count) int *dest = (int *) vid.buffer + (vid.rowbytes >> 2) * y + x; color = d_8to24table[color]; - for (i = 0; i < h; i++, dest -= (vid.rowbytes >> 1)) + for (i = 0; i < h; i++, dest -= (vid.rowbytes >> 2)) *dest = color; } break; From 3c0ad2ca71122e0acfa67fd32643b808cbf84910 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 08:18:02 +0900 Subject: [PATCH 1629/3664] [qw] Fix some server status output issues The uptime display had not been updated for the offset Sys_DoubleTime, so add Sys_DoubleTimeBase to make it easy to use Sys_DoubleTime as uptime. Line up the layout of the client list was not consistent for drop and qport. --- include/QF/sys.h | 1 + libs/util/sys.c | 6 ++++++ qw/source/sv_ccmds.c | 7 ++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index e1ed1a057..00dc40a92 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -80,6 +80,7 @@ void Sys_Shutdown (void); void Sys_RegisterShutdown (void (*func) (void *), void *data); int64_t Sys_LongTime (void); double Sys_DoubleTime (void); +double Sys_DoubleTimeBase (void); void Sys_TimeOfDay(date_t *date); void Sys_MaskPrintf (int mask, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); diff --git a/libs/util/sys.c b/libs/util/sys.c index 87241a8c1..c0619bfdc 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -412,6 +412,12 @@ Sys_DoubleTime (void) return (__INT64_C (4294967296000000) + Sys_LongTime ()) / 1e6; } +VISIBLE double +Sys_DoubleTimeBase (void) +{ + return __INT64_C (4294967296000000) / 1e6; +} + VISIBLE void Sys_TimeOfDay (date_t *date) { diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index 22604df69..4297bf9cc 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -390,7 +390,7 @@ SV_Current_Map (void) } static const char * -nice_time (float time) +nice_time (double time) { int t = time + 0.5; @@ -529,7 +529,8 @@ SV_Status_f (void) pak = (float) svs.stats.latched_packets / STATFRAMES; SV_Printf ("net address : %s\n", NET_AdrToString (net_local_adr)); - SV_Printf ("uptime : %s\n", nice_time (Sys_DoubleTime ())); + SV_Printf ("uptime : %s\n", + nice_time (Sys_DoubleTime () - Sys_DoubleTimeBase ())); SV_Printf ("cpu utilization : %3i%% (%3i%%)\n", (int) cpu, (int)demo); SV_Printf ("avg response time: %i ms\n", (int) avg); SV_Printf ("packets/frame : %5.2f\n", pak); @@ -602,7 +603,7 @@ SV_Status_f (void) SV_Printf ("SERVER %d\n", cl->ping); continue; } - SV_Printf ("%4i %4i %3.1f %4i", + SV_Printf ("%4i %4i %4.1f%% %5i", (int) (1000 * cl->netchan.frame_rate), (int) SV_CalcPing (cl), 100.0 * cl->netchan.drop_count / From c4ee7ff68af999935a978024a5f1d8f521b5bb2d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 09:26:05 +0900 Subject: [PATCH 1630/3664] [qw] Check packet size before checking ping ack Ping ack (A2A_ACK) is always a 1-byte packet, so check that the A2A_ACK is the only byte in the packet before passing the packet to the server list code. Fixes the mysterious dropped packet every 256 packets as the low eight bits of the packet's sequence number equalled A2A_ACK. --- qw/source/cl_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index e00a17d17..ed6347935 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1028,8 +1028,9 @@ CL_ReadPackets (void) CL_ConnectionlessPacket (); continue; } - if (*(char *) net_message->message->data == A2A_ACK) - { + if (net_message->message->cursize == 1 + && *(char *) net_message->message->data == A2A_ACK) { + Sys_Printf ("ping ack\n"); SL_CheckPing (NET_AdrToString (net_from)); continue; } From 91eeae518654ca649ce625d254838c02b9c8cea3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 10:59:27 +0900 Subject: [PATCH 1631/3664] [qw] Clean up netgraph somewhat The renderer's LineGraph now takes a height parameter, and netgraph now uses cl_* cvars instead of r_* (which never really made sense), including it's own height cvar (the render graphs still use r_graphheight). --- include/QF/plugin/vid_render.h | 2 +- include/r_internal.h | 2 +- libs/video/renderer/gl/gl_graph.c | 4 +- libs/video/renderer/glsl/glsl_main.c | 2 +- libs/video/renderer/r_graph.c | 21 +++++--- libs/video/renderer/sw/sw_graph.c | 4 +- libs/video/renderer/sw32/sw32_graph.c | 4 +- libs/video/renderer/vid_render_vulkan.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 67 ++++++++++++++++++++--- qw/include/client.h | 12 +++-- qw/source/cl_main.c | 9 +--- qw/source/cl_ngraph.c | 68 +++++++++++++++++++----- qw/source/cl_screen.c | 23 ++++---- 13 files changed, 161 insertions(+), 59 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 917fd8bbf..98af4aa41 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -155,7 +155,7 @@ typedef struct vid_render_funcs_s { void (*R_AddEfrags) (mod_brush_t *brush, entity_t *ent); void (*R_RemoveEfrags) (entity_t *ent); void (*R_EnqueueEntity) (struct entity_s *ent); //FIXME should not be here - void (*R_LineGraph) (int x, int y, int *h_vals, int count); + void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); dlight_t *(*R_AllocDlight) (int key); entity_t *(*R_AllocEntity) (void); void (*R_MaxDlightsCheck) (struct cvar_s *var); diff --git a/include/r_internal.h b/include/r_internal.h index 8fa0f06d6..b17a11a62 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -54,7 +54,7 @@ extern vid_render_funcs_t *vid_render_funcs; extern refdef_t r_refdef; extern int r_viewsize; -void R_LineGraph (int x, int y, int *h_vals, int count); +void R_LineGraph (int x, int y, int *h_vals, int count, int height); void Fog_Update (float density, float red, float green, float blue, float time); diff --git a/libs/video/renderer/gl/gl_graph.c b/libs/video/renderer/gl/gl_graph.c index b07c6c5f0..821620811 100644 --- a/libs/video/renderer/gl/gl_graph.c +++ b/libs/video/renderer/gl/gl_graph.c @@ -71,7 +71,7 @@ gl_R_InitGraphTextures (int base) } void -gl_R_LineGraph (int x, int y, int *h_vals, int count) +gl_R_LineGraph (int x, int y, int *h_vals, int count, int height) { byte color; byte *dest; @@ -80,7 +80,7 @@ gl_R_LineGraph (int x, int y, int *h_vals, int count) if (!count) return; - s = r_graphheight->int_val; + s = height; size = s * count; if (size > graph_size[graph_index]) { diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 2e07d34e0..06c7b1898 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -265,7 +265,7 @@ glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) } void -glsl_R_LineGraph (int x, int y, int *h_vals, int count) +glsl_R_LineGraph (int x, int y, int *h_vals, int count, int height) { } diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index 4234ca11a..4ca80c262 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -27,7 +27,9 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#include +#include "QF/cvar.h" #include "QF/draw.h" #include "QF/render.h" #include "QF/plugin.h" @@ -52,8 +54,9 @@ R_TimeGraph (void) int a; int l; //XXX float r_time2; - static int r_timings[MAX_TIMINGS]; - int x; + static int r_timings[MAX_TIMINGS]; + int timings[MAX_TIMINGS]; + int x, o; //XXX r_time2 = Sys_DoubleTime (); @@ -65,15 +68,18 @@ R_TimeGraph (void) if (l > r_refdef.vrect.width) l = r_refdef.vrect.width; x = r_refdef.vrect.width - l; + o = 0; a = timex - l; if (a < 0) { - vr_funcs->R_LineGraph (x, r_refdef.vrect.height - 2, - &r_timings[a + MAX_TIMINGS], -a); - x -= a; + memcpy (timings + o, r_timings + a + MAX_TIMINGS, + -a * sizeof (timings[0])); + o -= a; l += a; a = 0; } - vr_funcs->R_LineGraph (x, r_refdef.vrect.height - 2, &r_timings[a], l); + memcpy (timings + o, r_timings + a, l * sizeof (timings[0])); + vr_funcs->R_LineGraph (x, r_refdef.vrect.height - 2, r_timings, + MAX_TIMINGS, vr_data.graphheight->int_val); timex = (timex + 1) % MAX_TIMINGS; } @@ -92,5 +98,6 @@ R_ZGraph (void) height[r_framecount & 255] = ((int) r_origin[2]) & 31; x = 0; - vr_funcs->R_LineGraph (x, r_refdef.vrect.height - 2, height, w); + vr_funcs->R_LineGraph (x, r_refdef.vrect.height - 2, height, + w, vr_data.graphheight->int_val); } diff --git a/libs/video/renderer/sw/sw_graph.c b/libs/video/renderer/sw/sw_graph.c index 02f663cc2..4480a7eb7 100644 --- a/libs/video/renderer/sw/sw_graph.c +++ b/libs/video/renderer/sw/sw_graph.c @@ -40,13 +40,13 @@ Called by only R_DisplayTime */ void -R_LineGraph (int x, int y, int *h_vals, int count) +R_LineGraph (int x, int y, int *h_vals, int count, int height) { int h, i, s, color; byte *dest; // FIXME: disable on no-buffer adapters, or put in the driver - s = r_graphheight->int_val; + s = height; while (count--) { dest = ((byte*)vid.buffer) + vid.rowbytes * y + x++; diff --git a/libs/video/renderer/sw32/sw32_graph.c b/libs/video/renderer/sw32/sw32_graph.c index d17c08970..e5bec2a7e 100644 --- a/libs/video/renderer/sw32/sw32_graph.c +++ b/libs/video/renderer/sw32/sw32_graph.c @@ -46,12 +46,12 @@ Called by only R_DisplayTime */ void -sw32_R_LineGraph (int x, int y, int *h_vals, int count) +sw32_R_LineGraph (int x, int y, int *h_vals, int count, int height) { int h, i, s, color; // FIXME: disable on no-buffer adapters, or put in the driver - s = r_graphheight->int_val; + s = height; while (count--) { h = *h_vals++; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 216285f0d..1963f4ca8 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -236,7 +236,7 @@ vulkan_R_NewMap (model_t *worldmodel, model_t **models, int num_models) } static void -vulkan_R_LineGraph (int x, int y, int *h_vals, int count) +vulkan_R_LineGraph (int x, int y, int *h_vals, int count, int height) { } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index d7dc0f8c7..af525bf2d 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -329,12 +329,6 @@ Vulkan_Draw_UncachePic (const char *path, vulkan_ctx_t *ctx) Hash_Free (dctx->pic_cache, Hash_Del (dctx->pic_cache, path)); } -void -Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, - vulkan_ctx_t *ctx) -{ -} - void Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) { @@ -587,6 +581,67 @@ Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx) { } +void +Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, + vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + + quat_t color = {1, 1, 1, 1}; + qpic_t *p; + int cx, cy, n; +#define draw(px, py, pp) \ + draw_pic (px, py, pp->width, pp->height, pp, \ + 0, 0, pp->width, pp->height, color, frame); + + color[3] = alpha; + // draw left side + cx = x; + cy = y; + p = Vulkan_Draw_CachePic ("gfx/box_tl.lmp", true, ctx); + draw (cx, cy, p); + p = Vulkan_Draw_CachePic ("gfx/box_ml.lmp", true, ctx); + for (n = 0; n < lines; n++) { + cy += 8; + draw (cx, cy, p); + } + p = Vulkan_Draw_CachePic ("gfx/box_bl.lmp", true, ctx); + draw (cx, cy + 8, p); + + // draw middle + cx += 8; + while (width > 0) { + cy = y; + p = Vulkan_Draw_CachePic ("gfx/box_tm.lmp", true, ctx); + draw (cx, cy, p); + p = Vulkan_Draw_CachePic ("gfx/box_mm.lmp", true, ctx); + for (n = 0; n < lines; n++) { + cy += 8; + if (n == 1) + p = Vulkan_Draw_CachePic ("gfx/box_mm2.lmp", true, ctx); + draw (cx, cy, p); + } + p = Vulkan_Draw_CachePic ("gfx/box_bm.lmp", true, ctx); + draw (cx, cy + 8, p); + width -= 2; + cx += 16; + } + + // draw right side + cy = y; + p = Vulkan_Draw_CachePic ("gfx/box_tr.lmp", true, ctx); + draw (cx, cy, p); + p = Vulkan_Draw_CachePic ("gfx/box_mr.lmp", true, ctx); + for (n = 0; n < lines; n++) { + cy += 8; + draw (cx, cy, p); + } + p = Vulkan_Draw_CachePic ("gfx/box_br.lmp", true, ctx); + draw (cx, cy + 8, p); +#undef draw +} + void Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) { diff --git a/qw/include/client.h b/qw/include/client.h index ec761885f..9ccfaf551 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -270,9 +270,11 @@ typedef struct client_state_s { /* cvars */ -extern struct cvar_s *r_netgraph; -extern struct cvar_s *r_netgraph_alpha; -extern struct cvar_s *r_netgraph_box; +extern struct cvar_s *cl_netgraph; +extern struct cvar_s *cl_netgraph_height; +extern struct cvar_s *cl_netgraph_alpha; +extern struct cvar_s *cl_netgraph_box; + extern struct cvar_s *cl_upspeed; extern struct cvar_s *cl_forwardspeed; extern struct cvar_s *cl_backspeed; @@ -331,8 +333,10 @@ extern struct cbuf_s *cl_stbuf; void Cvar_Info (struct cvar_s *var); -struct view_s; +extern struct view_s *cl_netgraph_view; void CL_NetGraph (struct view_s *view); +void CL_NetGraph_Init_Cvars (void); + void CL_UpdateScreen (double realtime); void CL_SetState (cactive_t state); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index ed6347935..48919dbab 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1311,19 +1311,12 @@ CL_Init_Cvars (void) CL_Cam_Init_Cvars (); CL_Input_Init_Cvars (); CL_Prediction_Init_Cvars (); + CL_NetGraph_Init_Cvars (); Game_Init_Cvars (); Pmove_Init_Cvars (); Team_Init_Cvars (); V_Init_Cvars (); - r_netgraph = Cvar_Get ("r_netgraph", "0", CVAR_NONE, NULL, - "Toggle the display of a graph showing network " - "performance"); - r_netgraph_alpha = Cvar_Get ("r_netgraph_alpha", "0.5", CVAR_ARCHIVE, NULL, - "Net graph translucency"); - r_netgraph_box = Cvar_Get ("r_netgraph_box", "1", CVAR_ARCHIVE, NULL, - "Draw box around net graph"); - cls.userinfo = Info_ParseString ("", MAX_INFO_STRING, 0); cl_model_crcs = Cvar_Get ("cl_model_crcs", "1", CVAR_ARCHIVE, NULL, diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 572b54334..1d31f20da 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -48,41 +48,85 @@ #include "qw/include/client.h" #include "sbar.h" -cvar_t *r_netgraph; -cvar_t *r_netgraph_alpha; -cvar_t *r_netgraph_box; +cvar_t *cl_netgraph; +cvar_t *cl_netgraph_alpha; +cvar_t *cl_netgraph_box; +cvar_t *cl_netgraph_height; +view_t *cl_netgraph_view; + +static void +cl_netgraph_f (cvar_t *var) +{ + if (cl_netgraph_view) { + cl_netgraph_view->visible = var->int_val != 0; + } +} + +static void +cl_netgraph_height_f (cvar_t *var) +{ + if (var->int_val < 32) { + Cvar_Set (var, "32"); + } + if (cl_netgraph_view) { + view_resize (cl_netgraph_view, cl_netgraph_view->xlen, + var->int_val + 25); + } +} void CL_NetGraph (view_t *view) { - int lost, a, l, x, y, i; + int lost, a, l, x, y, i, o; + int timings[NET_TIMINGS]; x = view->xabs; y = view->yabs; - if (r_netgraph_box->int_val) + if (cl_netgraph_box->int_val) { r_funcs->Draw_TextBox (x, y, NET_TIMINGS / 8, - r_data->graphheight->int_val / 8 + 1, - r_netgraph_alpha->value * 255); + cl_netgraph_height->int_val / 8 + 1, + cl_netgraph_alpha->value * 255); + } lost = CL_CalcNet (); x = view->xabs + 8; y = view->yabs + view->ylen - 9; l = NET_TIMINGS; - if (l > r_data->refdef->vrect.width - 8) - l = r_data->refdef->vrect.width - 8; + if (l > view->xlen - 8) + l = view->xlen - 8; i = cls.netchan.outgoing_sequence & NET_TIMINGSMASK; a = i - l; + o = 0; if (a < 0) { - r_funcs->R_LineGraph (x, y, &packet_latency[a + NET_TIMINGS], -a); - x -= a; + memcpy (timings + o, packet_latency + a + NET_TIMINGS, + -a * sizeof (timings[0])); + o -= a; l += a; a = 0; } - r_funcs->R_LineGraph (x, y, &packet_latency[a], l); + memcpy (timings + o, packet_latency + a, l * sizeof (timings[0])); + r_funcs->R_LineGraph (x, y, timings, + NET_TIMINGS, cl_netgraph_height->int_val); x = view->xabs + 8; y = view->yabs + 8; r_funcs->Draw_String (x, y, va (0, "%3i%% packet loss", lost)); } + +void +CL_NetGraph_Init_Cvars (void) +{ + cl_netgraph = Cvar_Get ("cl_netgraph", "0", CVAR_NONE, cl_netgraph_f, + "Toggle the display of a graph showing network " + "performance"); + cl_netgraph_alpha = Cvar_Get ("cl_netgraph_alpha", "0.5", CVAR_ARCHIVE, 0, + "Net graph translucency"); + cl_netgraph_box = Cvar_Get ("cl_netgraph_box", "1", CVAR_ARCHIVE, 0, + " Draw box around net graph"); + cl_netgraph_height = Cvar_Get ("cl_netgraph_height", "32", CVAR_ARCHIVE, + cl_netgraph_height_f, + "Set the fullscale (1s) height of the " + "graph"); +} diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 33e2197c2..d0d8ec3bf 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -55,7 +55,6 @@ static view_t *net_view; static view_t *loading_view; -static view_t *graph_view; static void draw_pic (view_t *view) @@ -94,11 +93,11 @@ scr_draw_views (void) - cls.netchan.incoming_acknowledged) >= UPDATE_BACKUP - 1); loading_view->visible = cl.loading; - graph_view->visible = r_netgraph->int_val != 0; + cl_netgraph_view->visible = cl_netgraph->int_val != 0; //FIXME don't do every frame - view_move (graph_view, graph_view->xpos, sb_lines); - view_setgravity (graph_view, + view_move (cl_netgraph_view, cl_netgraph_view->xpos, sb_lines); + view_setgravity (cl_netgraph_view, hud_swap->int_val ? grav_southeast : grav_southwest); view_draw (r_data->vid->conview); @@ -165,14 +164,14 @@ CL_UpdateScreen (double realtime) view_add (r_data->vid->conview, loading_view); } - if (!graph_view) { - graph_view = view_new (0, -24, - NET_TIMINGS + 16, - r_data->graphheight->int_val + 25, - grav_southwest); - graph_view->draw = CL_NetGraph; - graph_view->visible = 0; - view_add (r_data->vid->conview, graph_view); + if (!cl_netgraph_view) { + cl_netgraph_view = view_new (0, sb_lines, + NET_TIMINGS + 16, + cl_netgraph_height->int_val + 25, + grav_southwest); + cl_netgraph_view->draw = CL_NetGraph; + cl_netgraph_view->visible = 0; + view_add (r_data->vid->conview, cl_netgraph_view); } //FIXME not every time From edbf4d262a286b79f8e251e8201dfe4a73c48063 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 11:02:37 +0900 Subject: [PATCH 1632/3664] [qw] Make the netgraph scale logarithmic Full scale is 1s, but now ms timings are visible even with the default height. --- qw/source/cl_parse.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 6f1aa90e4..b1ae42c84 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -213,15 +213,18 @@ CL_CalcNet (void) for (i = cls.netchan.outgoing_sequence - UPDATE_BACKUP + 1; i <= cls.netchan.outgoing_sequence; i++) { frame = &cl.frames[i & UPDATE_MASK]; - if (frame->receivedtime == -1) + if (frame->receivedtime == -1) { packet_latency[i & NET_TIMINGSMASK] = 9999; // dropped - else if (frame->receivedtime == -2) + } else if (frame->receivedtime == -2) { packet_latency[i & NET_TIMINGSMASK] = 10000; // choked - else if (frame->invalid) + } else if (frame->invalid) { packet_latency[i & NET_TIMINGSMASK] = 9998; // invalid delta - else - packet_latency[i & NET_TIMINGSMASK] = - (frame->receivedtime - frame->senttime) * 20; + } else { + double d = frame->receivedtime - frame->senttime; + d = log (d * 1000 + 1) / log (1000); + d *= d * cl_netgraph_height->int_val; + packet_latency[i & NET_TIMINGSMASK] = d; + } } lost = 0; From 6dff00a9da1a5bd970dbf6a588a3842f2ef9c900 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 12:05:14 +0900 Subject: [PATCH 1633/3664] [qw] Move netgraph below the console Also, make nq draw the vid views (in theory, it loads too fast to see the loading pic). --- nq/source/cl_screen.c | 15 +++++++++++---- qw/source/cl_screen.c | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index a977fdff8..03e682d88 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -84,6 +84,16 @@ SCR_CShift (void) r_funcs->Draw_BlendScreen (r_data->vid->cshift_color); } +static void +scr_draw_views (void) +{ + net_view->visible = (!cls.demoplayback + && realtime - cl.last_servermessage >= 0.3); + loading_view->visible = cl.loading; + + view_draw (r_data->vid->conview); +} + static SCR_Func scr_funcs_normal[] = { 0, //Draw_Crosshair, 0, //SCR_DrawRam, @@ -92,6 +102,7 @@ static SCR_Func scr_funcs_normal[] = { Sbar_Draw, SCR_CShift, Sbar_DrawCenterPrint, + scr_draw_views, Con_DrawConsole, 0 }; @@ -141,10 +152,6 @@ CL_UpdateScreen (double realtime) view_add (r_data->vid->conview, loading_view); } - net_view->visible = (!cls.demoplayback - && realtime - cl.last_servermessage >= 0.3); - loading_view->visible = cl.loading; - //FIXME not every time if (cls.state == ca_active) { if (cl.watervis) diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index d0d8ec3bf..7d1db70a4 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -111,9 +111,9 @@ static SCR_Func scr_funcs_normal[] = { //CL_NetGraph,FIXME Sbar_Draw, SCR_CShift, + scr_draw_views, Sbar_DrawCenterPrint, Con_DrawConsole, - scr_draw_views, 0 }; From 108d2a0746da6d357c3e5aef6d79e48cce2e5493 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 12:31:34 +0900 Subject: [PATCH 1634/3664] [qw] Fix an uninitialized var use Found by valgrind --- qw/source/cl_ents.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 9da38dc9c..a63809ba4 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -228,20 +228,18 @@ CL_LinkPacketEntities (void) CL_TransformEntity (ent, new->scale / 16, new->angles, new->origin); animation->pose1 = animation->pose2 = -1; - } else { + } else if (!(renderer->model->flags & EF_ROTATE)) { vec3_t angles, d; vec4f_t origin = old->origin + f * delta; // interpolate the origin and angles - if (!(renderer->model->flags & EF_ROTATE)) { - VectorSubtract (new->angles, old->angles, d); - for (j = 0; j < 3; j++) { - if (d[j] > 180) - d[j] -= 360; - else if (d[j] < -180) - d[j] += 360; - } - VectorMultAdd (old->angles, f, d, angles); + VectorSubtract (new->angles, old->angles, d); + for (j = 0; j < 3; j++) { + if (d[j] > 180) + d[j] -= 360; + else if (d[j] < -180) + d[j] += 360; } + VectorMultAdd (old->angles, f, d, angles); CL_TransformEntity (ent, new->scale / 16.0, angles, origin); } if (i != cl.viewentity || chase_active->int_val) { From c636f7413ded5fb53bf0d90053163a85e5651cf0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 13:29:05 +0900 Subject: [PATCH 1635/3664] [util] Fix yet another suggested const warning I keep forgetting to do an optimized build test --- include/QF/sys.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 00dc40a92..07994f483 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -80,7 +80,7 @@ void Sys_Shutdown (void); void Sys_RegisterShutdown (void (*func) (void *), void *data); int64_t Sys_LongTime (void); double Sys_DoubleTime (void); -double Sys_DoubleTimeBase (void); +double Sys_DoubleTimeBase (void) __attribute__ ((const)); void Sys_TimeOfDay(date_t *date); void Sys_MaskPrintf (int mask, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); From 6db6f8f0e2e26d5c18d33669fa19d4a2d3ef9d66 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 13:30:52 +0900 Subject: [PATCH 1636/3664] [win] Fix a pile of bitrot Man, those bits rot quickly. Must be stored with a rotfish. --- libs/audio/targets/snd_dx.c | 171 +++++++++++++++--------------- libs/audio/targets/snd_win.c | 132 ++++++++++++----------- libs/audio/test/testsound.c | 2 +- libs/video/targets/vid_win.c | 10 +- libs/video/targets/vid_win_sw.c | 8 +- tools/cross/mingw/cross-make.sh | 4 +- tools/cross/mingw64/cross-make.sh | 4 +- 7 files changed, 170 insertions(+), 161 deletions(-) diff --git a/libs/audio/targets/snd_dx.c b/libs/audio/targets/snd_dx.c index 0cbb18275..e53839c4e 100644 --- a/libs/audio/targets/snd_dx.c +++ b/libs/audio/targets/snd_dx.c @@ -56,7 +56,6 @@ static qboolean snd_firsttime = true; static qboolean primary_format_set; static int sample16; -static volatile dma_t sn; /* Global variables. Must be visible to window-procedure function @@ -82,21 +81,13 @@ static LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf; static HINSTANCE hInstDS; -static sndinitstat SNDDMA_InitDirect (void); +static sndinitstat SNDDMA_InitDirect (snd_t *snd); static cvar_t *snd_stereo; static cvar_t *snd_rate; static cvar_t *snd_bits; -static plugin_t plugin_info; -static plugin_data_t plugin_info_data; -static plugin_funcs_t plugin_info_funcs; -static general_data_t plugin_info_general_data; -static general_funcs_t plugin_info_general_funcs; -static snd_output_data_t plugin_info_snd_output_data; -static snd_output_funcs_t plugin_info_snd_output_funcs; - -static DWORD *DSOUND_LockBuffer (qboolean lockit); +static DWORD *DSOUND_LockBuffer (snd_t *snd, qboolean lockit); static void SNDDMA_Init_Cvars (void) @@ -110,12 +101,12 @@ SNDDMA_Init_Cvars (void) } static void -SNDDMA_BlockSound (void) +SNDDMA_BlockSound (snd_t *snd) { } static void -SNDDMA_UnblockSound (void) +SNDDMA_UnblockSound (snd_t *snd) { } @@ -151,7 +142,7 @@ FreeSound (void) Direct-Sound support */ static sndinitstat -SNDDMA_InitDirect (void) +SNDDMA_InitDirect (snd_t *snd) { int reps; DSBUFFERDESC dsbuf; @@ -161,22 +152,20 @@ SNDDMA_InitDirect (void) HRESULT hresult; WAVEFORMATEX format, pformat; - memset ((void *) &sn, 0, sizeof (sn)); - if (!snd_stereo->int_val) { - sn.channels = 1; + snd->channels = 1; } else { - sn.channels = 2; + snd->channels = 2; } - sn.samplebits = snd_bits->int_val; - sn.speed = snd_rate->int_val; + snd->samplebits = snd_bits->int_val; + snd->speed = snd_rate->int_val; memset (&format, 0, sizeof (format)); format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = sn.channels; - format.wBitsPerSample = sn.samplebits; - format.nSamplesPerSec = sn.speed; + format.nChannels = snd->channels; + format.wBitsPerSample = snd->samplebits; + format.nSamplesPerSec = snd->speed; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; @@ -267,9 +256,9 @@ SNDDMA_InitDirect (void) return SIS_FAILURE; } - sn.channels = format.nChannels; - sn.samplebits = format.wBitsPerSample; - sn.speed = format.nSamplesPerSec; + snd->channels = format.nChannels; + snd->samplebits = format.wBitsPerSample; + snd->speed = format.nSamplesPerSec; if (DS_OK != IDirectSound_GetCaps (pDSBuf, &dsbcaps)) { Sys_Printf ("DS:GetCaps failed\n"); @@ -331,11 +320,11 @@ SNDDMA_InitDirect (void) &dwWrite); IDirectSoundBuffer_Play (pDSBuf, 0, 0, DSBPLAY_LOOPING); - sn.frames = gSndBufSize / (sn.samplebits / 8) / sn.channels; - sn.framepos = 0; - sn.submission_chunk = 1; - sn.buffer = (byte *) lpData; - sample16 = (sn.samplebits / 8) - 1; + snd->frames = gSndBufSize / (snd->samplebits / 8) / snd->channels; + snd->framepos = 0; + snd->submission_chunk = 1; + snd->buffer = (byte *) lpData; + sample16 = (snd->samplebits / 8) - 1; dsound_init = true; @@ -349,10 +338,11 @@ SNDDMA_InitDirect (void) Try to find a sound device to mix for. Returns false if nothing is found. */ -static volatile dma_t * -SNDDMA_Init (void) +static int +SNDDMA_Init (snd_t *snd) { sndinitstat stat; + int ret = 0; stat = SIS_FAILURE; // assume DirectSound won't // initialize @@ -360,17 +350,16 @@ SNDDMA_Init (void) /* Init DirectSound */ if (snd_firsttime) { snd_firsttime = false; - stat = SNDDMA_InitDirect (); + stat = SNDDMA_InitDirect (snd); - if (stat == SIS_SUCCESS) { + if ((ret = (stat == SIS_SUCCESS))) { Sys_Printf ("DirectSound initialized\n"); } else { Sys_Printf ("DirectSound failed to init\n"); - return 0; } } - return &sn; + return ret; } /* @@ -381,31 +370,31 @@ SNDDMA_Init (void) how many sample are required to fill it up. */ static int -SNDDMA_GetDMAPos (void) +SNDDMA_GetDMAPos (snd_t *snd) { int s = 0; DWORD dwWrite; MMTIME mmtime; unsigned long *pbuf; - pbuf = DSOUND_LockBuffer (true); + pbuf = DSOUND_LockBuffer (snd, true); if (!pbuf) { Sys_Printf ("DSOUND_LockBuffer fails!\n"); return -1; } - sn.buffer = (unsigned char *) pbuf; + snd->buffer = (unsigned char *) pbuf; mmtime.wType = TIME_SAMPLES; IDirectSoundBuffer_GetCurrentPosition (pDSBuf, &mmtime.u.sample, &dwWrite); s = mmtime.u.sample - mmstarttime.u.sample; s >>= sample16; - s /= sn.channels; + s /= snd->channels; - s %= sn.frames; - sn.framepos = s; + s %= snd->frames; + snd->framepos = s; - return sn.framepos; + return snd->framepos; } /* @@ -414,19 +403,19 @@ SNDDMA_GetDMAPos (void) Send sound to device if buffer isn't really the dma buffer */ static void -SNDDMA_Submit (void) +SNDDMA_Submit (snd_t *snd) { - DSOUND_LockBuffer (false); + DSOUND_LockBuffer (snd, false); } static void -SNDDMA_shutdown (void) +SNDDMA_shutdown (snd_t *snd) { FreeSound (); } static DWORD * -DSOUND_LockBuffer (qboolean lockit) +DSOUND_LockBuffer (snd_t *snd, qboolean lockit) { int reps; @@ -447,16 +436,16 @@ DSOUND_LockBuffer (qboolean lockit) if (hresult != DSERR_BUFFERLOST) { Sys_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n"); - SNDDMA_shutdown (); - SNDDMA_Init (); + SNDDMA_shutdown (snd); + SNDDMA_Init (snd); return NULL; } if (++reps > 10000) { Sys_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n"); - SNDDMA_shutdown (); - SNDDMA_Init (); + SNDDMA_shutdown (snd); + SNDDMA_Init (snd); return NULL; } } @@ -471,14 +460,14 @@ DSOUND_LockBuffer (qboolean lockit) } static void __attribute__((used)) //FIXME make it true -DSOUND_ClearBuffer (int clear) +DSOUND_ClearBuffer (snd_t *snd, int clear) { DWORD *pData; // FIXME: this should be called with 2nd pbuf2 = NULL, dwsize =0 - pData = DSOUND_LockBuffer (true); - memset (pData, clear, sn.frames * sn.channels * sn.samplebits / 8); - DSOUND_LockBuffer (false); + pData = DSOUND_LockBuffer (snd, true); + memset (pData, clear, snd->frames * snd->channels * snd->samplebits / 8); + DSOUND_LockBuffer (snd, false); } static void __attribute__((used)) //FIXME make it true @@ -502,35 +491,49 @@ DSOUND_Restore (void) return; } +static snd_output_data_t plugin_info_snd_output_data = { +}; + +static snd_output_funcs_t plugin_info_snd_output_funcs = { + .init = SNDDMA_Init, + .shutdown = SNDDMA_shutdown, + .get_dma_pos = SNDDMA_GetDMAPos, + .submit = SNDDMA_Submit, + .block_sound = SNDDMA_BlockSound, + .unblock_sound = SNDDMA_UnblockSound, +}; + +static general_data_t plugin_info_general_data = { +}; + +static general_funcs_t plugin_info_general_funcs = { + .init = SNDDMA_Init_Cvars, +}; + +static plugin_data_t plugin_info_data = { + .general = &plugin_info_general_data, + .snd_output = &plugin_info_snd_output_data, +}; + +static plugin_funcs_t plugin_info_funcs = { + .general = &plugin_info_general_funcs, + .snd_output = &plugin_info_snd_output_funcs, +}; + +static plugin_t plugin_info = { + .type = qfp_snd_output, + .api_version = QFPLUGIN_VERSION, + .plugin_version = "0.1", + .description = "Windows DirectX output", + .copyright = "Copyright (C) 1996-1997 id Software, Inc.\n" + "Copyright (C) 1999,2000,2001,2002,2003 contributors of the " + "QuakeForge project\n" + "Please see the file \"AUTHORS\" for a list of contributors", + .functions = &plugin_info_funcs, + .data = &plugin_info_data, +}; + PLUGIN_INFO(snd_output, dx) { - plugin_info.type = qfp_snd_output; - plugin_info.api_version = QFPLUGIN_VERSION; - plugin_info.plugin_version = "0.1"; - plugin_info.description = "Windows DirectX output"; - plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n" - "Copyright (C) 1999,2000,2001,2002,2003 contributors of the QuakeForge " - "project\n" - "Please see the file \"AUTHORS\" for a list of contributors"; - plugin_info.functions = &plugin_info_funcs; - plugin_info.data = &plugin_info_data; - - plugin_info_data.general = &plugin_info_general_data; - plugin_info_data.input = NULL; - plugin_info_data.snd_output = &plugin_info_snd_output_data; - - plugin_info_funcs.general = &plugin_info_general_funcs; - plugin_info_funcs.input = NULL; - plugin_info_funcs.snd_output = &plugin_info_snd_output_funcs; - - plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; - plugin_info_general_funcs.p_Shutdown = NULL; - plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; - plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; - plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; - plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; - plugin_info_snd_output_funcs.pS_O_UnblockSound = SNDDMA_UnblockSound; - return &plugin_info; } diff --git a/libs/audio/targets/snd_win.c b/libs/audio/targets/snd_win.c index 59a18344b..361bb5afc 100644 --- a/libs/audio/targets/snd_win.c +++ b/libs/audio/targets/snd_win.c @@ -50,7 +50,6 @@ static qboolean snd_firsttime = true; static int sample16; static int snd_sent, snd_completed; static int snd_blocked = 0; -static volatile dma_t sn; /* Global variables. Must be visible to window-procedure function @@ -69,20 +68,12 @@ static HWAVEOUT hWaveOut; static DWORD gSndBufSize; -static qboolean SNDDMA_InitWav (void); +static qboolean SNDDMA_InitWav (snd_t *snd); static cvar_t *snd_stereo; static cvar_t *snd_rate; static cvar_t *snd_bits; -static plugin_t plugin_info; -static plugin_data_t plugin_info_data; -static plugin_funcs_t plugin_info_funcs; -static general_data_t plugin_info_general_data; -static general_funcs_t plugin_info_general_funcs; -static snd_output_data_t plugin_info_snd_output_data; -static snd_output_funcs_t plugin_info_snd_output_funcs; - static void SNDDMA_Init_Cvars (void) @@ -96,14 +87,14 @@ SNDDMA_Init_Cvars (void) } static void -SNDDMA_BlockSound (void) +SNDDMA_BlockSound (snd_t *snd) { if (++snd_blocked == 1) waveOutReset (hWaveOut); } static void -SNDDMA_UnblockSound (void) +SNDDMA_UnblockSound (snd_t *snd) { if (snd_blocked) --snd_blocked; @@ -150,7 +141,7 @@ FreeSound (void) Crappy windows multimedia base */ static qboolean -SNDDMA_InitWav (void) +SNDDMA_InitWav (snd_t *snd) { int i; HRESULT hr; @@ -160,19 +151,19 @@ SNDDMA_InitWav (void) snd_completed = 0; if (!snd_stereo->int_val) { - sn.channels = 1; + snd->channels = 1; } else { - sn.channels = 2; + snd->channels = 2; } - sn.samplebits = snd_bits->int_val; - sn.speed = snd_rate->int_val; + snd->samplebits = snd_bits->int_val; + snd->speed = snd_rate->int_val; memset (&format, 0, sizeof (format)); format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = sn.channels; - format.wBitsPerSample = sn.samplebits; - format.nSamplesPerSec = sn.speed; + format.nChannels = snd->channels; + format.wBitsPerSample = snd->samplebits; + format.nSamplesPerSec = snd->speed; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; @@ -246,11 +237,11 @@ SNDDMA_InitWav (void) } } - sn.frames = gSndBufSize / (sn.samplebits / 8) / sn.channels; - sn.framepos = 0; - sn.submission_chunk = 1; - sn.buffer = (unsigned char *) lpData; - sample16 = (sn.samplebits / 8) - 1; + snd->frames = gSndBufSize / (snd->samplebits / 8) / snd->channels; + snd->framepos = 0; + snd->submission_chunk = 1; + snd->buffer = (unsigned char *) lpData; + sample16 = (snd->samplebits / 8) - 1; return true; } @@ -261,11 +252,12 @@ SNDDMA_InitWav (void) Try to find a sound device to mix for. Returns false if nothing is found. */ -static volatile dma_t * -SNDDMA_Init (void) +static int +SNDDMA_Init (snd_t *snd) { + int ret = 0; if (snd_firsttime) { - if (SNDDMA_InitWav ()) { + if ((ret = SNDDMA_InitWav (snd))) { Sys_Printf ("Wave sound initialized\n"); } else { Sys_Printf ("Wave sound failed to init\n"); @@ -273,7 +265,7 @@ SNDDMA_Init (void) } snd_firsttime = false; - return &sn; + return ret; } /* @@ -284,19 +276,19 @@ SNDDMA_Init (void) how many sample are required to fill it up. */ static int -SNDDMA_GetDMAPos (void) +SNDDMA_GetDMAPos (snd_t *snd) { int s = 0; s = snd_sent * WAV_BUFFER_SIZE; s >>= sample16; - s /= sn.channels; + s /= snd->channels; - s %= sn.frames; - sn.framepos = s; + s %= snd->frames; + snd->framepos = s; - return sn.framepos; + return snd->framepos; } /* @@ -305,7 +297,7 @@ SNDDMA_GetDMAPos (void) Send sound to device if buffer isn't really the dma buffer */ static void -SNDDMA_Submit (void) +SNDDMA_Submit (snd_t *snd) { int wResult; LPWAVEHDR h; @@ -345,40 +337,54 @@ SNDDMA_Submit (void) } static void -SNDDMA_shutdown (void) +SNDDMA_shutdown (snd_t *snd) { FreeSound (); } -PLUGIN_INFO(snd_output, win) -{ - plugin_info.type = qfp_snd_output; - plugin_info.api_version = QFPLUGIN_VERSION; - plugin_info.plugin_version = "0.1"; - plugin_info.description = "Windows digital output"; - plugin_info.copyright = "Copyright (C) 1996-1997 id Software, Inc.\n" +static snd_output_data_t plugin_info_snd_output_data = { +}; + +static snd_output_funcs_t plugin_info_snd_output_funcs = { + .init = SNDDMA_Init, + .shutdown = SNDDMA_shutdown, + .get_dma_pos = SNDDMA_GetDMAPos, + .submit = SNDDMA_Submit, + .block_sound = SNDDMA_BlockSound, + .unblock_sound = SNDDMA_UnblockSound, +}; + +static general_data_t plugin_info_general_data = { +}; + +static general_funcs_t plugin_info_general_funcs = { + .init = SNDDMA_Init_Cvars, +}; + +static plugin_data_t plugin_info_data = { + .general = &plugin_info_general_data, + .snd_output = &plugin_info_snd_output_data, +}; + +static plugin_funcs_t plugin_info_funcs = { + .general = &plugin_info_general_funcs, + .snd_output = &plugin_info_snd_output_funcs, +}; + +static plugin_t plugin_info = { + .type = qfp_snd_output, + .api_version = QFPLUGIN_VERSION, + .plugin_version = "0.1", + .description = "Windows digital output", + .copyright = "Copyright (C) 1996-1997 id Software, Inc.\n" "Copyright (C) 1999,2000,2001 contributors of the QuakeForge " "project\n" - "Please see the file \"AUTHORS\" for a list of contributors"; - plugin_info.functions = &plugin_info_funcs; - plugin_info.data = &plugin_info_data; - - plugin_info_data.general = &plugin_info_general_data; - plugin_info_data.input = NULL; - plugin_info_data.snd_output = &plugin_info_snd_output_data; - - plugin_info_funcs.general = &plugin_info_general_funcs; - plugin_info_funcs.input = NULL; - plugin_info_funcs.snd_output = &plugin_info_snd_output_funcs; - - plugin_info_general_funcs.p_Init = SNDDMA_Init_Cvars; - plugin_info_general_funcs.p_Shutdown = NULL; - plugin_info_snd_output_funcs.pS_O_Init = SNDDMA_Init; - plugin_info_snd_output_funcs.pS_O_Shutdown = SNDDMA_shutdown; - plugin_info_snd_output_funcs.pS_O_GetDMAPos = SNDDMA_GetDMAPos; - plugin_info_snd_output_funcs.pS_O_Submit = SNDDMA_Submit; - plugin_info_snd_output_funcs.pS_O_BlockSound = SNDDMA_BlockSound; - plugin_info_snd_output_funcs.pS_O_UnblockSound = SNDDMA_UnblockSound; + "Please see the file \"AUTHORS\" for a list of contributors", + .functions = &plugin_info_funcs, + .data = &plugin_info_data, +}; +PLUGIN_INFO(snd_output, win) +{ return &plugin_info; } diff --git a/libs/audio/test/testsound.c b/libs/audio/test/testsound.c index b513df3cf..ce157c067 100644 --- a/libs/audio/test/testsound.c +++ b/libs/audio/test/testsound.c @@ -49,7 +49,7 @@ #ifdef _WIN32 # include "winquake.h" -HWND mainwindow; +HWND win_mainwindow; #endif #define MEMSIZE (32 * 1024 * 1024) diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 09dc8090f..2a0cbaa38 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -71,7 +71,7 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) rect.height = height << repshift; rect.next = NULL; - win_sw_context->update (&rect); + win_sw_context->update (win_sw_context, &rect); } @@ -101,7 +101,7 @@ D_EndDirectRect (int x, int y, int width, int height) rect.height = height << repshift; rect.next = NULL; - win_sw_context->update (&rect); + win_sw_context->update (win_sw_context, &rect); } static void @@ -130,13 +130,13 @@ VID_Init (byte *palette, byte *colormap) VID_GetWindowSize (640, 480); Win_OpenDisplay (); - vid_internal.choose_visual (); + vid_internal.choose_visual (win_sw_context); Win_SetVidMode (viddef.width, viddef.height); Win_CreateWindow (viddef.width, viddef.height); - vid_internal.create_context (); + vid_internal.create_context (win_sw_context); VID_InitGamma (palette); - viddef.vid_internal->set_palette (palette); + viddef.vid_internal->set_palette (win_sw_context, palette); Sys_MaskPrintf (SYS_vid, "Video mode %dx%d initialized.\n", viddef.width, viddef.height); diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index 313aad3c8..dd0bf4155 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -228,7 +228,7 @@ VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer, // create a palette VID_InitGamma (palette); - viddef.vid_internal->set_palette (palette); + viddef.vid_internal->set_palette (viddef.vid_internal->data, palette); } void @@ -308,7 +308,7 @@ Win_CreateDriver (void) } static void -win_init_bufers (void) +win_init_bufers (void *data) { Win_UnloadAllDrivers (); Win_CreateDriver (); @@ -323,7 +323,7 @@ win_init_bufers (void) } static void -win_set_palette (const byte *palette) +win_set_palette (sw_ctx_t *ctx, const byte *palette) { palette_changed = 1; if (palette != current_palette) { @@ -410,7 +410,7 @@ dd_blit_rect (vrect_t *rect) } static void -win_sw_update (vrect_t *rects) +win_sw_update (sw_ctx_t *ctx, vrect_t *rects) { vrect_t full_rect; if (!win_palettized && palette_changed) { diff --git a/tools/cross/mingw/cross-make.sh b/tools/cross/mingw/cross-make.sh index d2906a32b..b7472edad 100755 --- a/tools/cross/mingw/cross-make.sh +++ b/tools/cross/mingw/cross-make.sh @@ -6,7 +6,7 @@ if test -d native; then cd ../i686-w64-mingw32.static ln -fs ../native/qfcc . ln -fs ../native/pak . - ln -fs ../native/ruamoko/qwaq/qwaq-curses . + ln -fs ../native/ruamoko/qwaq/qwaq-cmd . fi export MINGW=/opt/mxe export MINGW_USR=$MINGW/usr/i686-w64-mingw32.static @@ -14,4 +14,4 @@ export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH -make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ_CURSES='$(top_builddir)/qwaq-curses' $* +make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ='$(top_builddir)/qwaq-cmd' $* diff --git a/tools/cross/mingw64/cross-make.sh b/tools/cross/mingw64/cross-make.sh index 6282f1cef..b1888321f 100755 --- a/tools/cross/mingw64/cross-make.sh +++ b/tools/cross/mingw64/cross-make.sh @@ -6,7 +6,7 @@ if test -d native; then cd ../x86_64-w64-mingw32.static ln -fs ../native/qfcc . ln -fs ../native/pak . - ln -fs ../native/ruamoko/qwaq/qwaq-curses . + ln -fs ../native/ruamoko/qwaq/qwaq-cmd . fi export MINGW=/opt/mxe export MINGW_USR=$MINGW/usr/x86_64-w64-mingw32.static @@ -14,4 +14,4 @@ export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH -make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ_CURSES='$(top_builddir)/qwaq-curses' $* +make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ='$(top_builddir)/qwaq-cmd' $* From 12450fe6b86bf76b9ba44d857cb7700cebd610bc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Jul 2021 13:33:40 +0900 Subject: [PATCH 1637/3664] [vid] Remove redundant direct, conbuffer and conrowbytes --- include/QF/vid.h | 4 ---- libs/video/renderer/sw/draw.c | 10 +++++----- libs/video/renderer/sw32/draw.c | 34 ++++++++++++++++----------------- libs/video/targets/vid.c | 10 +++++----- libs/video/targets/vid_win.c | 10 +++++----- libs/video/targets/vid_win_sw.c | 8 -------- libs/video/targets/vid_x11_sw.c | 4 ---- 7 files changed, 32 insertions(+), 48 deletions(-) diff --git a/include/QF/vid.h b/include/QF/vid.h index 2d6a94698..9255e7210 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -54,11 +54,7 @@ typedef struct { qboolean recalc_refdef; // if true, recalc vid-based stuff qboolean cshift_changed; quat_t cshift_color; - void *conbuffer; - int conrowbytes; struct view_s *conview; - byte *direct; // direct drawing to framebuffer, if not - // NULL struct vid_internal_s *vid_internal; } viddef_t; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index a73b9a734..a24117118 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -280,7 +280,7 @@ Draw_Character (int x, int y, unsigned int chr) } else drawline = 8; - dest = ((byte*)vid.conbuffer) + y * vid.conrowbytes + x; + dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; while (drawline--) { if (source[0]) @@ -300,7 +300,7 @@ Draw_Character (int x, int y, unsigned int chr) if (source[7]) dest[7] = source[7]; source += 128; - dest += vid.conrowbytes; + dest += vid.rowbytes; } } @@ -340,7 +340,7 @@ Draw_Pixel (int x, int y, byte color) { byte *dest; - dest = ((byte*)vid.conbuffer) + y * vid.conrowbytes + x; + dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; *dest = color; } @@ -621,9 +621,9 @@ Draw_ConsoleBackground (int lines, byte alpha) conback = Draw_CachePic ("gfx/conback.lmp", false); // draw the pic - dest = vid.conbuffer; + dest = vid.buffer; - for (y = 0; y < lines; y++, dest += vid.conrowbytes) { + for (y = 0; y < lines; y++, dest += vid.rowbytes) { v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; src = conback->data + v * 320; if (vid.conview->xlen == 320) diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c index ea630fc28..6c8621097 100644 --- a/libs/video/renderer/sw32/draw.c +++ b/libs/video/renderer/sw32/draw.c @@ -287,7 +287,7 @@ sw32_Draw_Character (int x, int y, unsigned int chr) switch(sw32_ctx->pixbytes) { case 1: { - byte *dest = (byte *) vid.conbuffer + y * vid.conrowbytes + x; + byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; while (drawline--) { if (source[0]) @@ -307,14 +307,14 @@ sw32_Draw_Character (int x, int y, unsigned int chr) if (source[7]) dest[7] = source[7]; source += 128; - dest += vid.conrowbytes; + dest += vid.rowbytes; } } break; case 2: { - unsigned short *dest = (unsigned short *) vid.conbuffer + y * - (vid.conrowbytes >> 1) + x; + unsigned short *dest = (unsigned short *) vid.buffer + y * + (vid.rowbytes >> 1) + x; while (drawline--) { if (source[0]) @@ -335,14 +335,14 @@ sw32_Draw_Character (int x, int y, unsigned int chr) dest[7] = sw32_8to16table[source[7]]; source += 128; - dest += (vid.conrowbytes >> 1); + dest += (vid.rowbytes >> 1); } } break; case 4: { - unsigned int *dest = (unsigned int *) vid.conbuffer + y * - (vid.conrowbytes >> 2) + x; + unsigned int *dest = (unsigned int *) vid.buffer + y * + (vid.rowbytes >> 2) + x; while (drawline--) { if (source[0]) @@ -363,7 +363,7 @@ sw32_Draw_Character (int x, int y, unsigned int chr) dest[7] = d_8to24table[source[7]]; source += 128; - dest += (vid.conrowbytes >> 2); + dest += (vid.rowbytes >> 2); } } break; @@ -407,14 +407,14 @@ Draw_Pixel (int x, int y, byte color) switch(sw32_ctx->pixbytes) { case 1: - ((byte *) vid.conbuffer)[y * vid.conrowbytes + x] = color; + ((byte *) vid.buffer)[y * vid.rowbytes + x] = color; break; case 2: - ((unsigned short *) vid.conbuffer)[y * (vid.conrowbytes >> 1) + x] = + ((unsigned short *) vid.buffer)[y * (vid.rowbytes >> 1) + x] = sw32_8to16table[color]; break; case 4: - ((unsigned int *) vid.conbuffer)[y * (vid.conrowbytes >> 2) + x] = + ((unsigned int *) vid.buffer)[y * (vid.rowbytes >> 2) + x] = d_8to24table[color]; break; default: @@ -745,9 +745,9 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) switch(sw32_ctx->pixbytes) { case 1: { - byte *dest = vid.conbuffer; + byte *dest = vid.buffer; - for (y = 0; y < lines; y++, dest += vid.conrowbytes) { + for (y = 0; y < lines; y++, dest += vid.rowbytes) { v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; src = conback->data + v * 320; if (vid.conview->xlen == 320) @@ -771,9 +771,9 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) break; case 2: { - unsigned short *dest = (unsigned short *) vid.conbuffer; + unsigned short *dest = (unsigned short *) vid.buffer; - for (y = 0; y < lines; y++, dest += (vid.conrowbytes >> 1)) { + for (y = 0; y < lines; y++, dest += (vid.rowbytes >> 1)) { // FIXME: pre-expand to native format? // FIXME: does the endian switching go away in production? v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; @@ -795,8 +795,8 @@ sw32_Draw_ConsoleBackground (int lines, byte alpha) break; case 4: { - unsigned int *dest = (unsigned int *) vid.conbuffer; - for (y = 0; y < lines; y++, dest += (vid.conrowbytes >> 2)) { + unsigned int *dest = (unsigned int *) vid.buffer; + for (y = 0; y < lines; y++, dest += (vid.rowbytes >> 2)) { v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; src = conback->data + v * 320; f = 0; diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 4c73fced2..682d301d5 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -280,11 +280,11 @@ VID_InitBuffers (void) // Free the old screen buffer if (viddef.buffer) { free (viddef.buffer); - viddef.conbuffer = viddef.buffer = NULL; + viddef.buffer = NULL; } // Allocate the new screen buffer - viddef.conbuffer = viddef.buffer = calloc (buffersize, 1); - if (!viddef.conbuffer) { + viddef.buffer = calloc (buffersize, 1); + if (!viddef.buffer) { Sys_Error ("Not enough memory for video mode"); } } @@ -292,7 +292,7 @@ VID_InitBuffers (void) viddef.zbuffer = calloc (zbuffersize, 1); if (!viddef.zbuffer) { free (viddef.buffer); - viddef.conbuffer = viddef.buffer = NULL; + viddef.buffer = NULL; Sys_Error ("Not enough memory for video mode"); } // Allocate the new surface cache; free the z-buffer if we fail @@ -300,7 +300,7 @@ VID_InitBuffers (void) if (!viddef.surfcache) { free (viddef.buffer); free (viddef.zbuffer); - viddef.conbuffer = viddef.buffer = NULL; + viddef.buffer = NULL; viddef.zbuffer = NULL; Sys_Error ("Not enough memory for video mode"); } diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 2a0cbaa38..d09f64d43 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -50,16 +50,16 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) if (!viddef.initialized || !win_sw_context) return; - if (!viddef.direct) + if (!viddef.buffer) return; for (i = 0; i < (height << repshift); i += reps) { for (j = 0; j < reps; j++) { memcpy (&backingbuf[(i + j) * 24], - viddef.direct + x + ((y << repshift) + i + + viddef.buffer + x + ((y << repshift) + i + j) * viddef.rowbytes, width); - memcpy (viddef.direct + x + + memcpy (viddef.buffer + x + ((y << repshift) + i + j) * viddef.rowbytes, &pbitmap[(i >> repshift) * width], width); } @@ -84,12 +84,12 @@ D_EndDirectRect (int x, int y, int width, int height) if (!viddef.initialized || !win_sw_context) return; - if (!viddef.direct) + if (!viddef.buffer) return; for (i = 0; i < (height << repshift); i += reps) { for (j = 0; j < reps; j++) { - memcpy (viddef.direct + x + + memcpy (viddef.buffer + x + ((y << repshift) + i + j) * viddef.rowbytes, &backingbuf[(i + j) * 24], width); } diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index dd0bf4155..9ded596fb 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -312,14 +312,6 @@ win_init_bufers (void *data) { Win_UnloadAllDrivers (); Win_CreateDriver (); - // set the rest of the buffers we need (why not just use one single buffer - // instead of all this crap? oh well, it's Quake...) - viddef.direct = viddef.buffer; - viddef.conbuffer = viddef.buffer; - - // more crap for the console - viddef.conrowbytes = viddef.rowbytes; - } static void diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index f36847f56..938e085ba 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -643,7 +643,6 @@ x11_init_buffers (void *data) current_framebuffer = 0; - viddef.direct = 0; viddef.rowbytes = ctx->pixbytes * viddef.width; if (x_visinfo->depth != 8) { if (viddef.buffer) @@ -654,9 +653,6 @@ x11_init_buffers (void *data) } else { viddef.buffer = x_framebuffer[current_framebuffer]->data; } - viddef.conbuffer = viddef.buffer; - - viddef.conrowbytes = viddef.rowbytes; } static void From 0a847f92f1ea2cbc8594aa85733d240546eac66d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 12 Jul 2021 16:33:47 +0900 Subject: [PATCH 1638/3664] [util] Use mmap/munmap for cmem internal alloc/free This reduces the overhead needed to manage the memory blocks as the blocks are guaranteed to be page-aligned. Also, the superblock is now alllocated from within one of the memory blocks it manages. While this does slightly reduce the available cachelines within the first block (by one or two depending on 32 vs 64 bit pointers), it removes the need for an extra memory allocation (probably via malloc) for the superblock. --- include/QF/cmem.h | 17 ++--- include/QF/sys.h | 1 + libs/util/cmem.c | 139 ++++++++++++++++++------------------- libs/util/sys.c | 13 ++++ libs/util/test/test-cmem.c | 129 +++++++++++++++++----------------- tools/qfvis/source/qfvis.c | 12 ++-- 6 files changed, 158 insertions(+), 153 deletions(-) diff --git a/include/QF/cmem.h b/include/QF/cmem.h index dd53df256..2641cabf8 100644 --- a/include/QF/cmem.h +++ b/include/QF/cmem.h @@ -60,20 +60,11 @@ typedef struct memsline_s { typedef struct memblock_s { struct memblock_s *next; struct memblock_s **prev; - /* The pointer to pass to free() - */ - void *mem; memline_t *free_lines; - /* Size of memory region before block "header". - * - * Since large blocks are allocated with page-size alignment, odds are - * high that the there will be many cache lines "wasted" in the space - * between the address returned from aligned_alloc (to cache-line - * alignment) and the block itself. Setting them up as a pool makes the - * lines available for smaller allocations, thus reducing waste. + /* Size of memory available within the page-sized block. */ - size_t pre_size; - /* Size of memory region after block "header". + size_t size; + /* Size of memory region after the page-sized block. * * Will be 0 for blocks that were allocated exclusively for small * allocations, otherwise indicates the size of the allocated block. @@ -85,7 +76,7 @@ typedef struct memblock_s { #if __WORDSIZE == 64 int pad; #endif - size_t pre_allocated; + size_t allocated; } __attribute__((aligned (64))) memblock_t; typedef struct memsuper_s { diff --git a/include/QF/sys.h b/include/QF/sys.h index 07994f483..b5ceb95f8 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -123,6 +123,7 @@ void Sys_MakeCodeWriteable (uintptr_t startaddr, size_t length); void Sys_PageIn (void *ptr, size_t size); long Sys_PageSize (void); void *Sys_Alloc (size_t size); +void Sys_Free (void *mem, size_t size); // // system IO diff --git a/libs/util/cmem.c b/libs/util/cmem.c index d14f0580a..1f448481c 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -28,21 +28,10 @@ # include "config.h" #endif -#include -#include - #include "QF/alloc.h" #include "QF/cmem.h" #include "QF/sys.h" -#ifdef _WIN32 -#define cmem_alloc(align, size) _aligned_malloc(size, align) -#define cmem_free(mem) _aligned_free(mem) -#else -#define cmem_alloc(align, size) aligned_alloc(align, size) -#define cmem_free(mem) free(mem) -#endif - static size_t __attribute__((const)) ilog2 (size_t x) { @@ -53,27 +42,6 @@ ilog2 (size_t x) return l; } -memsuper_t * -new_memsuper (void) -{ - memsuper_t *super = cmem_alloc (MEM_LINE_SIZE, sizeof (*super)); - memset (super, 0, sizeof (*super)); - super->page_size = Sys_PageSize (); - super->page_mask = (super->page_size - 1); - return super; -} - -void -delete_memsuper (memsuper_t *super) -{ - while (super->memblocks) { - memblock_t *t = super->memblocks; - super->memblocks = super->memblocks->next; - cmem_free (t->mem); - } - cmem_free (super); -} - static void link_free_line (memsuper_t *super, memline_t *line) { @@ -109,12 +77,8 @@ unlink_line (memline_t *line) static memblock_t * init_block (memsuper_t *super, void *mem, size_t alloc_size) { - size_t size = super->page_size; - size_t mask = super->page_mask; - size_t ptr = (size_t) mem; - memblock_t *block; + memblock_t *block = mem; - block = (memblock_t *) (((ptr + size) & ~mask)) - 1; memset (block, 0, sizeof (memblock_t)); if (super->memblocks) { @@ -124,26 +88,20 @@ init_block (memsuper_t *super, void *mem, size_t alloc_size) block->prev = &super->memblocks; super->memblocks = block; - block->mem = mem; - block->pre_size = (size_t) block - (size_t) mem; - block->post_size = alloc_size - block->pre_size - sizeof (memblock_t); - if (!((size_t) mem & mask) && block->pre_size) { - // can't use the first cache line of the page as it would be - // indistinguishable from a large block - block->pre_size -= MEM_LINE_SIZE; - } - if (block->pre_size) { - memline_t *line = (memline_t *) ((size_t) block - block->pre_size); + block->size = super->page_size - sizeof (*block); + block->post_size = alloc_size - super->page_size; - line->block = block; - line->size = block->pre_size; + memline_t *line = (memline_t *) (block + 1); - line->block_next = 0; - line->block_prev = &block->free_lines; - block->free_lines = line; + line->block = block; + line->size = block->size; + + line->block_next = 0; + line->block_prev = &block->free_lines; + block->free_lines = line; + + link_free_line (super, line); - link_free_line (super, line); - } return block; } @@ -167,8 +125,8 @@ block_alloc (memsuper_t *super, size_t size) } size_t page_size = super->page_size; - size_t alloc_size = sizeof (memblock_t) + page_size + size; - void *mem = cmem_alloc (MEM_LINE_SIZE, alloc_size); + size_t alloc_size = page_size + size; + void *mem = Sys_Alloc (alloc_size); block = init_block (super, mem, alloc_size); return block; } @@ -199,7 +157,7 @@ alloc_line (memline_t *line, size_t size) line->free_next = split; split->free_prev = &line->free_next; } - line->block->pre_allocated += line->size; + line->block->allocated += line->size; unlink_line (line); return mem; } @@ -213,7 +171,7 @@ line_free (memsuper_t *super, memblock_t *block, void *mem) memline_t **l; memline_t *line = 0; - block->pre_allocated -= size; + block->allocated -= size; for (l = &block->free_lines; *l; l = &(*l)->block_next) { line = *l; @@ -303,7 +261,7 @@ cmemalloc (memsuper_t *super, size_t size) if (!block) { return 0; } - return block + 1; + return (void *) ((size_t) block + super->page_size); } else { size = 4 << ind; if (size >= MEM_LINE_SIZE) { @@ -328,7 +286,7 @@ cmemalloc (memsuper_t *super, size_t size) * allocated line is ever page-aligned as that would make the * line indistinguishable from a large block. */ - mem = cmem_alloc (super->page_size, super->page_size); + mem = Sys_Alloc (super->page_size); // sets super->free_lines, the block is guarnateed to be big // enough to hold the requested allocation as otherwise a full // block allocation would have been used @@ -368,12 +326,11 @@ cmemalloc (memsuper_t *super, size_t size) static void unlink_block (memblock_t *block) { - if (block->pre_size) { - if (!block->free_lines || block->free_lines->block_next) { - *(int *) 0 = 0; - } - unlink_line (block->free_lines); + if (!block->free_lines || block->free_lines->block_next) { + *(int *) 0 = 0; } + unlink_line (block->free_lines); + if (block->next) { block->next->prev = block->prev; } @@ -411,17 +368,57 @@ cmemfree (memsuper_t *super, void *mem) return; } else if ((size_t) mem & super->page_mask) { // cache line - size_t page_size = super->page_size; - size_t page_mask = super->page_mask; - block = (memblock_t *) (((size_t) mem + page_size) & ~page_mask) - 1; + block = (memblock_t *) ((size_t) mem & ~super->page_mask); line_free (super, block, mem); } else { // large block - block = (memblock_t *) mem - 1; + block = (memblock_t *) ((size_t) mem - super->page_size); block->post_free = 1; } - if (!block->pre_allocated && (!block->post_size || block->post_free)) { + if (!block->allocated && (!block->post_size || block->post_free)) { unlink_block (block); - cmem_free (block->mem); + Sys_Free (block, super->page_size + block->post_size); } } + +memsuper_t * +new_memsuper (void) +{ + // Temporary superblock used to bootstrap a pool + memsuper_t bootstrap = { }; + bootstrap.page_size = Sys_PageSize (); + bootstrap.page_mask = (bootstrap.page_size - 1); + + // Allocate the real superblock from the pool. As a superblock is only + // two cache lines large (for 64-byte cache lines), it will always be + // allocated using a block's cache lines, and thus will be inside the first + // block. + memsuper_t *super = cmemalloc (&bootstrap, sizeof (*super)); + *super = bootstrap; + // The block used to allocate the real superblock points to the bootstrap + // superblock, but needs to point to the real superblock. + super->memblocks->prev = &super->memblocks; + + // Any free cache line block chains will also point to the bootstrap + // block instead of the resl superblock, so fix them up too (there should + // be only one, but no harm in being paranoid) + for (int i = 0; i < MAX_CACHE_LINES; i++) { + if (super->free_lines[i]) { + super->free_lines[i]->free_prev = &super->free_lines[i]; + } + } + return super; +} + +void +delete_memsuper (memsuper_t *super) +{ + // The block holding the superblock is always the last block in the list + while (super->memblocks && super->memblocks->next) { + memblock_t *t = super->memblocks; + super->memblocks = super->memblocks->next; + Sys_Free (t, super->page_size + t->post_size); + } + memblock_t *block = super->memblocks; + Sys_Free (block, super->page_size + block->post_size); +} diff --git a/libs/util/sys.c b/libs/util/sys.c index c0619bfdc..55b669f2b 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -650,6 +650,19 @@ Sys_Alloc (size_t size) #endif } +VISIBLE void +Sys_Free (void *mem, size_t size) +{ + size_t page_size = Sys_PageSize (); + size_t page_mask = page_size - 1; + size = (size + page_mask) & ~page_mask; +#ifdef _WIN32 +# error implement Sys_Free for windows +#else + munmap (mem, size); +#endif +} + VISIBLE void Sys_DebugLog (const char *file, const char *fmt, ...) { diff --git a/libs/util/test/test-cmem.c b/libs/util/test/test-cmem.c index 51dbd2ab6..aa8f7fd43 100644 --- a/libs/util/test/test-cmem.c +++ b/libs/util/test/test-cmem.c @@ -6,6 +6,8 @@ #include "QF/cmem.h" #include "QF/set.h" +#define SUPER_LINES (sizeof (memsuper_t) / MEM_LINE_SIZE) + static int test_block (memsuper_t *super) { @@ -24,7 +26,7 @@ test_block (memsuper_t *super) return 0; } block = super->memblocks; - if (mem != block + 1) { + if ((size_t) mem != (size_t) block + super->page_size) { fprintf (stderr, "super does not point to mem\n"); return 0; } @@ -40,7 +42,7 @@ test_block (memsuper_t *super) } memset (mem, 0, size); // valgrind check cmemfree (super, mem); - if (super->memblocks) { + if ((size_t) super->memblocks + super->page_size == (size_t) mem) { fprintf (stderr, "super still points to mem\n"); return 0; } @@ -57,11 +59,11 @@ check_block (memblock_t *block, int line_count, int allocated) for (memline_t **l = &block->free_lines; *l; l = &(*l)->block_next) { memline_t *line = *l; - ptrdiff_t ind = (byte *) block - (byte *) line; + ptrdiff_t ind = (byte *) line - (byte *) block; ind /= MEM_LINE_SIZE; - if (ind < 1 || (size_t ) ind > block->pre_size / MEM_LINE_SIZE) { - fprintf (stderr, "line outside of block: %p %p %p\n", - line, block->mem, block); + if (ind < 1 || (size_t ) (ind - 1) > block->size / MEM_LINE_SIZE) { + fprintf (stderr, "line outside of block: %p %p\n", + line, block); return 0; } if (set_is_member (visited, ind)) { @@ -86,9 +88,9 @@ check_block (memblock_t *block, int line_count, int allocated) fprintf (stderr, "line block_prev link incorrect\n"); ret = 0; } - if (line->size > block->pre_size) { + if (line->size > block->size) { fprintf (stderr, "line size too large: %zd / %zd\n", - line->size, block->pre_size); + line->size, block->size); ret = 0; } if (line->size % MEM_LINE_SIZE) { @@ -101,9 +103,9 @@ check_block (memblock_t *block, int line_count, int allocated) } } if (ret) { - if (free_bytes + block->pre_allocated != block->pre_size) { + if (free_bytes + block->allocated != block->size) { fprintf (stderr, "block space mismatch: s: %zd a: %zd f: %zd\n", - block->pre_size, block->pre_allocated, free_bytes); + block->size, block->allocated, free_bytes); ret = 0; } if (line_count >= 0 && line_count != count) { @@ -111,9 +113,9 @@ check_block (memblock_t *block, int line_count, int allocated) line_count, count); ret = 0; } - if (allocated >= 0 && (size_t) allocated != block->pre_allocated) { - fprintf (stderr, "pre_allocated wrong size: %zd != %d\n", - block->pre_allocated, allocated); + if (allocated >= 0 && (size_t) allocated != block->allocated) { + fprintf (stderr, "allocated wrong size: %zd != %d\n", + block->allocated, allocated); } } set_delete (visited); @@ -188,19 +190,22 @@ test_line (memsuper_t *super) fprintf (stderr, "too many memblocks\n"); return 0; } - if (line1 < (memline_t *) block->mem || line1 >= (memline_t *) block) { - fprintf (stderr, "line1 outside block line pool: %p %p %p\n", - line1, block->mem, block); + if (line1 < (memline_t *) (block + 1) + || line1 >= (memline_t *) ((byte *) block + super->page_size)) { + fprintf (stderr, "line1 outside block line pool: %p %p\n", + line1, block); return 0; } - if (line2 < (memline_t *) block->mem || line2 >= (memline_t *) block) { - fprintf (stderr, "line2 outside block line pool: %p %p %p\n", - line2, block->mem, block); + if (line2 < (memline_t *) (block + 1) + || line2 >= (memline_t *) ((byte *) block + super->page_size)) { + fprintf (stderr, "line2 outside block line pool: %p %p\n", + line2, block); return 0; } - if (line3 < (memline_t *) block->mem || line3 >= (memline_t *) block) { - fprintf (stderr, "line3 outside block line pool: %p %p %p\n", - line3, block->mem, block); + if (line3 < (memline_t *) (block + 1) + || line3 >= (memline_t *) ((byte *) block + super->page_size)) { + fprintf (stderr, "line3 outside block line pool: %p %p\n", + line3, block); return 0; } if (!((size_t) line1 & super->page_mask)) { @@ -224,7 +229,7 @@ test_line (memsuper_t *super) return 0; } - if (!check_block (block, 1, 3 * MEM_LINE_SIZE)) { + if (!check_block (block, 1, (3 + SUPER_LINES) * MEM_LINE_SIZE)) { fprintf (stderr, "line block check 1 failed\n"); return 0; } @@ -235,7 +240,7 @@ test_line (memsuper_t *super) cmemfree (super, line2); - if (!check_block (block, 2, 2 * MEM_LINE_SIZE)) { + if (!check_block (block, 2, (2 + SUPER_LINES) * MEM_LINE_SIZE)) { fprintf (stderr, "line block check 2 failed\n"); return 0; } @@ -254,7 +259,7 @@ test_line (memsuper_t *super) } cmemfree (super, line3); - if (!check_block (block, 1, 1 * MEM_LINE_SIZE)) { + if (!check_block (block, 1, (1 + SUPER_LINES) * MEM_LINE_SIZE)) { fprintf (stderr, "line block check 3 failed\n"); return 0; } @@ -269,12 +274,17 @@ test_line (memsuper_t *super) } cmemfree (super, line1); - if (super->memblocks) { - fprintf (stderr, "line pool not freed\n"); + if (!check_block (block, 1, (0 + SUPER_LINES) * MEM_LINE_SIZE)) { + fprintf (stderr, "line block check 4 failed\n"); return 0; } - if (!check_bins (super, 0x00)) { - fprintf (stderr, "bins not cleared\n"); + if (!check_bins (super, 0x20)) { + fprintf (stderr, "bin check 4 failed\n"); + return 0; + } + + if (super->free_lines[5] != line1) { + fprintf (stderr, "super free_lines[5] not pointing to line1\n"); return 0; } @@ -283,7 +293,7 @@ test_line (memsuper_t *super) line3 = cmemalloc (super, MEM_LINE_SIZE); block = super->memblocks; - if (!check_block (block, 1, 3 * MEM_LINE_SIZE)) { + if (!check_block (block, 1, (3 + SUPER_LINES) * MEM_LINE_SIZE)) { fprintf (stderr, "line block check 4 failed\n"); return 0; } @@ -294,7 +304,7 @@ test_line (memsuper_t *super) cmemfree (super, line1); - if (!check_block (block, 2, 2 * MEM_LINE_SIZE)) { + if (!check_block (block, 2, (2 + SUPER_LINES) * MEM_LINE_SIZE)) { fprintf (stderr, "line block check 5 failed\n"); return 0; } @@ -305,7 +315,7 @@ test_line (memsuper_t *super) cmemfree (super, line2); - if (!check_block (block, 2, 1 * MEM_LINE_SIZE)) { + if (!check_block (block, 2, (1 + SUPER_LINES) * MEM_LINE_SIZE)) { fprintf (stderr, "line block check 6 failed\n"); return 0; } @@ -315,21 +325,13 @@ test_line (memsuper_t *super) } cmemfree (super, line3); - if (super->memblocks) { - fprintf (stderr, "line pool not freed 2\n"); - return 0; - } - if (!check_bins (super, 0x00)) { - fprintf (stderr, "bins not cleared 2\n"); - return 0; - } line1 = cmemalloc (super, MEM_LINE_SIZE); line2 = cmemalloc (super, MEM_LINE_SIZE); line3 = cmemalloc (super, MEM_LINE_SIZE); block = super->memblocks; - if (!check_block (block, 1, 3 * MEM_LINE_SIZE)) { + if (!check_block (block, 1, (3 + SUPER_LINES) * MEM_LINE_SIZE)) { fprintf (stderr, "line block check 7 failed\n"); return 0; } @@ -340,7 +342,7 @@ test_line (memsuper_t *super) cmemfree (super, line3); - if (!check_block (block, 1, 2 * MEM_LINE_SIZE)) { + if (!check_block (block, 1, (2 + SUPER_LINES) * MEM_LINE_SIZE)) { fprintf (stderr, "line block check 8 failed\n"); return 0; } @@ -351,7 +353,7 @@ test_line (memsuper_t *super) cmemfree (super, line2); - if (!check_block (block, 1, 1 * MEM_LINE_SIZE)) { + if (!check_block (block, 1, (1 + SUPER_LINES) * MEM_LINE_SIZE)) { fprintf (stderr, "line block check 9 failed\n"); return 0; } @@ -361,14 +363,6 @@ test_line (memsuper_t *super) } cmemfree (super, line1); - if (super->memblocks) { - fprintf (stderr, "line pool not freed 3\n"); - return 0; - } - if (!check_bins (super, 0x00)) { - fprintf (stderr, "bins not cleared 3\n"); - return 0; - } return 1; } @@ -481,16 +475,16 @@ test_block_line (memsuper_t *super) void *line; memblock_t *block = super->memblocks; - if (block + 1 != (memblock_t *) mem) { + if ((size_t) block + super->page_size != (size_t) mem) { fprintf (stderr, "super memblocks do not point to mem\n"); return 0; } - if (block->pre_size < MEM_LINE_SIZE) { + if (block->size < MEM_LINE_SIZE) { // need to figure out a way to guarantee a shared block fprintf (stderr, "can't allocate line from block\n"); return 0; } - if (block->next) { + if (block->next != (memblock_t *) ((size_t) super & ~super->page_mask)) { fprintf (stderr, "excess blocks in super\n"); return 0; } @@ -499,7 +493,7 @@ test_block_line (memsuper_t *super) fprintf (stderr, "line is page aligned\n"); return 0; } - if (super->memblocks->next) { + if (0 && super->memblocks->next) { // need to figure out a way to guarantee a shared block fprintf (stderr, "mem and line not in same block\n"); return 0; @@ -513,7 +507,9 @@ test_block_line (memsuper_t *super) fprintf (stderr, "block not reused for mem\n"); return 0; } - if (super->memblocks != block || super->memblocks->next) { + //if (super->memblocks != block || super->memblocks->next) { + if (super->memblocks != block || !super->memblocks->next + || super->memblocks->next->next) { // need to figure out a way to guarantee a shared block fprintf (stderr, "blocks corrupt\n"); return 0; @@ -524,7 +520,7 @@ test_block_line (memsuper_t *super) return 0; } cmemfree (super, mem); - if (super->memblocks) { + if (0 && super->memblocks) { fprintf (stderr, "shared block not freed\n"); return 0; } @@ -588,8 +584,9 @@ main (void) super->page_mask); return 1; } - if (super->memblocks) { - fprintf (stderr, "super block list not null\n"); + if (super->memblocks + != (memblock_t *) ((size_t) super & ~super->page_mask)) { + fprintf (stderr, "superblock not in block a: %p %p\n", super->memblocks, super); return 1; } for (i = 4; i-- > 0; ) { @@ -601,6 +598,7 @@ main (void) fprintf (stderr, "super last_freed not all null\n"); return 1; } +#if 0 // no longer valid for (i = MAX_CACHE_LINES; i-- > 0; ) { if (super->free_lines[i]) { break; @@ -610,12 +608,14 @@ main (void) fprintf (stderr, "super free_lines not all null\n"); return 1; } +#endif if (!test_block (super)) { fprintf (stderr, "block tests failed\n"); return 1; } - if (super->memblocks) { - fprintf (stderr, "super block list not null 2\n"); + if (super->memblocks + != (memblock_t *) ((size_t) super & ~super->page_mask)) { + fprintf (stderr, "superblock not in block b: %p %p\n", super->memblocks, super); return 1; } for (i = 4; i-- > 0; ) { @@ -627,6 +627,7 @@ main (void) fprintf (stderr, "super last_freed not all null 2\n"); return 1; } +#if 0 // no longer valid for (i = MAX_CACHE_LINES; i-- > 0; ) { if (super->free_lines[i]) { break; @@ -636,12 +637,14 @@ main (void) fprintf (stderr, "super free_lines not all null 2\n"); return 1; } +#endif if (!test_line (super)) { fprintf (stderr, "line tests failed\n"); return 1; } - if (super->memblocks) { - fprintf (stderr, "super block list not null 2\n"); + if (super->memblocks + != (memblock_t *) ((size_t) super & ~super->page_mask)) { + fprintf (stderr, "superblock not in block c: %p %p\n", super->memblocks, super); return 1; } if (!test_block_line (super)) { diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 156d1650f..b6e0f3248 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -518,8 +518,8 @@ PortalCompleted (threaddata_t *thread, portal_t *completed) static void dump_super_stats (int id, memsuper_t *super) { - size_t total_pre_size = 0; - size_t total_pre_allocated = 0; + size_t total_size = 0; + size_t total_allocated = 0; size_t total_post_size = 0; size_t total_post_allocated = 0; size_t num_blocks = 0; @@ -527,8 +527,8 @@ dump_super_stats (int id, memsuper_t *super) for (memblock_t *block = super->memblocks; block; block = block->next) { num_blocks++; - total_pre_size += block->pre_size; - total_pre_allocated += block->pre_allocated; + total_size += block->size; + total_allocated += block->allocated; total_post_size += block->post_size; // post_free is a flag total_post_allocated += !block->post_free * block->post_size; @@ -544,8 +544,8 @@ dump_super_stats (int id, memsuper_t *super) WRLOCK (global_lock); printf ("cmem stats for thread %d\n", id); printf (" blocks: %zd\n", num_blocks); - printf (" pre: s:%-8zd a:%-8zd f:%-8zd\n", total_pre_size, - total_pre_allocated, total_pre_size - total_pre_allocated); + printf (" : s:%-8zd a:%-8zd f:%-8zd\n", total_size, + total_allocated, total_size - total_allocated); printf (" post: s:%-8zd a:%-8zd f:%-8zd\n", total_post_size, total_post_allocated, total_post_size - total_post_allocated); printf (" "); From 1078bd9efaeed25e15e5789f6b3f77417c728f99 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 12 Jul 2021 18:55:16 +0900 Subject: [PATCH 1639/3664] [util] Implement Sys_Free for windows And get the tests so they can (sort of) be run. --- include/QF/sys.h | 2 +- libs/util/sys.c | 4 ++-- libs/util/test/test-cmem.c | 8 ++++++-- libs/util/test/test-half.c | 4 +++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index b5ceb95f8..19776a474 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -121,7 +121,7 @@ void Sys_Init_Cvars (void); // void Sys_MakeCodeWriteable (uintptr_t startaddr, size_t length); void Sys_PageIn (void *ptr, size_t size); -long Sys_PageSize (void); +size_t Sys_PageSize (void); void *Sys_Alloc (size_t size); void Sys_Free (void *mem, size_t size); diff --git a/libs/util/sys.c b/libs/util/sys.c index 55b669f2b..a87c9df30 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -618,7 +618,7 @@ Sys_PageIn (void *ptr, size_t size) //#endif } -VISIBLE long +VISIBLE size_t Sys_PageSize (void) { #ifdef _WIN32 @@ -657,7 +657,7 @@ Sys_Free (void *mem, size_t size) size_t page_mask = page_size - 1; size = (size + page_mask) & ~page_mask; #ifdef _WIN32 -# error implement Sys_Free for windows + VirtualFree (mem, 0, MEM_RELEASE | MEM_DECOMMIT); #else munmap (mem, size); #endif diff --git a/libs/util/test/test-cmem.c b/libs/util/test/test-cmem.c index aa8f7fd43..d5001a8db 100644 --- a/libs/util/test/test-cmem.c +++ b/libs/util/test/test-cmem.c @@ -1,3 +1,6 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include #include #include @@ -5,6 +8,7 @@ #include "QF/cmem.h" #include "QF/set.h" +#include "QF/sys.h" #define SUPER_LINES (sizeof (memsuper_t) / MEM_LINE_SIZE) @@ -564,9 +568,9 @@ main (void) fprintf (stderr, "super block not cache aligned: %p\n", super); return 1; } - if (super->page_size != (size_t) sysconf (_SC_PAGESIZE)) { + if (super->page_size != Sys_PageSize ()) { fprintf (stderr, "page size not equal to system page size: %zd, %zd\n", - super->page_size, (size_t) sysconf (_SC_PAGESIZE)); + super->page_size, Sys_PageSize ()); return 1; } if (!super->page_size || (super->page_size & (super->page_size - 1))) { diff --git a/libs/util/test/test-half.c b/libs/util/test/test-half.c index b93c46f13..4db8c9a5a 100644 --- a/libs/util/test/test-half.c +++ b/libs/util/test/test-half.c @@ -18,9 +18,11 @@ struct { {0x0001, 5.9604644775390625e-08f}, {0x0000, 0.0f}, {0x8000, -0.0f}, -#if __GNUC_PREREQ(3,3) +#if defined(__GNUC_PREREQ) +# if __GNUC_PREREQ(3,3) {0x7c00, __builtin_huge_val ()}, {0xfc00, -__builtin_huge_val ()}, +# endif #endif {0x3555, 0.333251953125f}, {0x3e00, 1.5f}, From c8e6f71a30de339d5d9282384745267c07fa9555 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Jul 2021 16:02:47 +0900 Subject: [PATCH 1640/3664] [renderer] Remove tinst from msurface_t Its sole purpose was to pass the newly allocated instsurf when chaining an instance model (ammo box, etc) surface, but using expresion statements removes the need for such shenanigans, and even makes msurface_t that little bit smaller (though a separate array would be much better for cache coherence). More importantly, the relevant code is actually easier to understand: I spent way too long working out what tinst was for and why it was never cleared. --- include/QF/model.h | 1 - libs/video/renderer/gl/gl_rsurf.c | 30 ++++++++--------- libs/video/renderer/glsl/glsl_bsp.c | 22 ++++++------- libs/video/renderer/vulkan/vulkan_bsp.c | 44 +++++++------------------ 4 files changed, 35 insertions(+), 62 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 295035f3d..047da3a4d 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -154,7 +154,6 @@ typedef struct msurface_s { glpoly_t *polys; // multiple if warped instsurf_t *instsurf; ///< null if not part of world model/sub-model - instsurf_t *tinst; ///< for instance models mtexinfo_t *texinfo; int ec_index; diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 96d1ec93f..fb0aa71b6 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -66,25 +66,27 @@ static instsurf_t *sky_chain; static instsurf_t **sky_chain_tail; #define CHAIN_SURF_F2B(surf,chain) \ - do { \ + ({ \ instsurf_t *inst = (surf)->instsurf; \ if (__builtin_expect(!inst, 1)) \ - (surf)->tinst = inst = get_instsurf (); \ + inst = get_instsurf (); \ inst->surface = (surf); \ *(chain##_tail) = inst; \ (chain##_tail) = &inst->tex_chain; \ *(chain##_tail) = 0; \ - } while (0) + inst; \ + }) #define CHAIN_SURF_B2F(surf,chain) \ - do { \ + ({ \ instsurf_t *inst = (surf)->instsurf; \ if (__builtin_expect(!inst, 1)) \ - (surf)->tinst = inst = get_instsurf (); \ + inst = get_instsurf (); \ inst->surface = (surf); \ inst->tex_chain = (chain); \ (chain) = inst; \ - } while (0) + inst; \ + }) static gltex_t **r_texture_chains; static int r_num_texture_chains; @@ -268,16 +270,12 @@ R_RenderBrushPoly_1 (msurface_t *fa) } static inline void -R_AddToLightmapChain (mod_brush_t *brush, msurface_t *fa) +R_AddToLightmapChain (mod_brush_t *brush, msurface_t *fa, instsurf_t *sc) { int maps, smax, tmax; glRect_t *theRect; - instsurf_t *sc; // add the poly to the proper lightmap chain - if (!(sc = fa->instsurf)) - sc = fa->tinst; - sc->lm_chain = gl_lightmap_polys[fa->lightmaptexturenum]; gl_lightmap_polys[fa->lightmaptexturenum] = sc; @@ -497,9 +495,9 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, instsurf_t *sc; if (surf->flags & SURF_DRAWTURB) { - CHAIN_SURF_B2F (surf, waterchain); + sc = CHAIN_SURF_B2F (surf, waterchain); } else if (surf->flags & SURF_DRAWSKY) { - CHAIN_SURF_F2B (surf, sky_chain); + sc = CHAIN_SURF_F2B (surf, sky_chain); } else { texture_t *tx; gltex_t *tex; @@ -509,12 +507,10 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, else tx = R_TextureAnimation (surf); tex = tx->render; - CHAIN_SURF_F2B (surf, tex->tex_chain); + sc = CHAIN_SURF_F2B (surf, tex->tex_chain); - R_AddToLightmapChain (brush, surf); + R_AddToLightmapChain (brush, surf, sc); } - if (!(sc = surf->instsurf)) - sc = surf->tinst; sc->transform = transform; sc->color = color; } diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 977816418..eff3d270d 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -238,25 +238,27 @@ static struct { } sky_params; #define CHAIN_SURF_F2B(surf,chain) \ - do { \ + ({ \ instsurf_t *inst = (surf)->instsurf; \ if (__builtin_expect(!inst, 1)) \ - (surf)->tinst = inst = get_instsurf (); \ + inst = get_instsurf (); \ inst->surface = (surf); \ *(chain##_tail) = inst; \ (chain##_tail) = &inst->tex_chain; \ *(chain##_tail) = 0; \ - } while (0) + inst; \ + }) #define CHAIN_SURF_B2F(surf,chain) \ - do { \ + ({ \ instsurf_t *inst = (surf)->instsurf; \ if (__builtin_expect(!inst, 1)) \ - (surf)->tinst = inst = get_instsurf (); \ + inst = get_instsurf (); \ inst->surface = (surf); \ inst->tex_chain = (chain); \ (chain) = inst; \ - } while (0) + inst; \ + }) #define GET_RELEASE(type,name) \ static inline type * \ @@ -380,9 +382,9 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, instsurf_t *is; if (surf->flags & SURF_DRAWSKY) { - CHAIN_SURF_F2B (surf, sky_chain); + is = CHAIN_SURF_F2B (surf, sky_chain); } else if ((surf->flags & SURF_DRAWTURB) || (color && color[3] < 1.0)) { - CHAIN_SURF_B2F (surf, waterchain); + is = CHAIN_SURF_B2F (surf, waterchain); } else { texture_t *tx; glsltex_t *tex; @@ -392,12 +394,10 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, else tx = R_TextureAnimation (surf); tex = tx->render; - CHAIN_SURF_F2B (surf, tex->tex_chain); + is = CHAIN_SURF_F2B (surf, tex->tex_chain); update_lightmap (brush, surf); } - if (!(is = surf->instsurf)) - is = surf->tinst; is->transform = transform; is->color = color; } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 63ccd433e..da8c90641 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -97,25 +97,27 @@ typedef struct bsppoly_s { } bsppoly_t; #define CHAIN_SURF_F2B(surf,chain) \ - do { \ + ({ \ instsurf_t *inst = (surf)->instsurf; \ if (__builtin_expect(!inst, 1)) \ - (surf)->tinst = inst = get_instsurf (bctx); \ + inst = get_instsurf (bctx); \ inst->surface = (surf); \ *(chain##_tail) = inst; \ (chain##_tail) = &inst->tex_chain; \ *(chain##_tail) = 0; \ - } while (0) + inst; \ + }) #define CHAIN_SURF_B2F(surf,chain) \ - do { \ + ({ \ instsurf_t *inst = (surf)->instsurf; \ if (__builtin_expect(!inst, 1)) \ - (surf)->tinst = inst = get_instsurf (bctx); \ + inst = get_instsurf (bctx); \ inst->surface = (surf); \ inst->tex_chain = (chain); \ (chain) = inst; \ - } while (0) + inst; \ + }) #define GET_RELEASE(type,name) \ static inline type * \ @@ -234,9 +236,9 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, instsurf_t *is; if (surf->flags & SURF_DRAWSKY) { - CHAIN_SURF_F2B (surf, bctx->sky_chain); + is = CHAIN_SURF_F2B (surf, bctx->sky_chain); } else if ((surf->flags & SURF_DRAWTURB) || (color && color[3] < 1.0)) { - CHAIN_SURF_B2F (surf, bctx->waterchain); + is = CHAIN_SURF_B2F (surf, bctx->waterchain); } else { texture_t *tx; vulktex_t *tex; @@ -246,12 +248,10 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, else tx = R_TextureAnimation (surf); tex = tx->render; - CHAIN_SURF_F2B (surf, tex->tex_chain); + is = CHAIN_SURF_F2B (surf, tex->tex_chain); //update_lightmap (brush, surf, ctx); } - if (!(is = surf->instsurf)) - is = surf->tinst; is->transform = transform; is->color = color; } @@ -1560,28 +1560,6 @@ is_pow2 (unsigned x) return count == 1; } -// NOTE: this expects the destination tex_t to be set up: memory allocated -// and dimentions/format etc already set. the size of the rect to be copied -// is taken from dst. Also, dst->format and src->format must be the same, and -// either 3 or 4, or bad things will happen. Also, no clipping is done, so if -// x < 0 or y < 0 or x + dst->width > src->width -// or y + dst->height > src->height, bad things will happen. -/*XXX static void -copy_sub_tex (tex_t *src, int x, int y, tex_t *dst) -{ - int dstbytes; - int srcbytes; - int i; - - srcbytes = src->width * src->format; - dstbytes = dst->width * dst->format; - - x *= src->format; - for (i = 0; i < dst->height; i++) - memcpy (dst->data + i * dstbytes, src->data + (i + y) * srcbytes + x, - dstbytes); -}*/ - void Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) { From f7efcde7ab43cc3eb808e73df71a5e2c46a21460 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Jul 2021 22:59:51 +0900 Subject: [PATCH 1641/3664] [vulkan] Clean up and document some of the bsp code Getting close to understanding (again) how it all works. I only just barely understood when I got vulkan's renderer running, but I really need to understand for when I modify things for shadows. The main thing hurdle was tinst, but that was dealt with in the previous commit, and now it's just sorting out the mess of elechains and elementss. --- include/QF/GLSL/qf_bsp.h | 2 +- include/QF/Vulkan/qf_bsp.h | 2 +- include/QF/mathlib.h | 6 ++- include/QF/model.h | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 24 +++++------ libs/video/renderer/vulkan/vulkan_bsp.c | 54 ++++++++++--------------- 6 files changed, 40 insertions(+), 50 deletions(-) diff --git a/include/QF/GLSL/qf_bsp.h b/include/QF/GLSL/qf_bsp.h index 1ed5bba33..d89a9145e 100644 --- a/include/QF/GLSL/qf_bsp.h +++ b/include/QF/GLSL/qf_bsp.h @@ -47,7 +47,7 @@ typedef struct elements_s { typedef struct elechain_s { struct elechain_s *_next; struct elechain_s *next; - int index; + int model_index; elements_t *elements; vec_t *transform; float *color; diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 249a43286..bcf561d7b 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -54,7 +54,7 @@ typedef struct elements_s { typedef struct elechain_s { struct elechain_s *_next; struct elechain_s *next; - int index; + int model_index; ///< < 0: instance, 0 main, > 0: sub elements_t *elements; vec_t *transform; float *color; diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index ecb2f87f2..ef65f6aa8 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -189,9 +189,11 @@ R_CullBox (const vec3_t mins, const vec3_t maxs) { int i; - for (i=0 ; i < 4 ; i++) - if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2) + for (i=0 ; i < 4 ; i++) { + if (BOX_ON_PLANE_SIDE (mins, maxs, &frustum[i]) == 2) { return true; + } + } return false; } diff --git a/include/QF/model.h b/include/QF/model.h index 047da3a4d..53a4b5af3 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -156,7 +156,7 @@ typedef struct msurface_s { instsurf_t *instsurf; ///< null if not part of world model/sub-model mtexinfo_t *texinfo; - int ec_index; + int model_index; ///< < 0: instance, 0 main, > 0: sub byte *base; // lighting info diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index eff3d270d..d81a4f108 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -450,13 +450,13 @@ glsl_R_RegisterTextures (model_t **models, int num_models) } static elechain_t * -add_elechain (glsltex_t *tex, int ec_index) +add_elechain (glsltex_t *tex, int model_index) { elechain_t *ec; ec = get_elechain (); ec->elements = get_elements (); - ec->index = ec_index; + ec->model_index = model_index; ec->transform = 0; ec->color = 0; *tex->elechain_tail = ec; @@ -483,8 +483,8 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, float s, t; mod_brush_t *brush; - if (fa->ec_index < 0) { - brush = &models[-fa->ec_index - 1]->brush; + if (fa->model_index < 0) { + brush = &models[-fa->model_index - 1]->brush; } else { brush = &r_worldentity.renderer.model->brush; } @@ -584,9 +584,9 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) } } surf = brush->surfaces + j; - surf->ec_index = dm - brush->submodels; - if (!surf->ec_index && m != r_worldentity.renderer.model) - surf->ec_index = -1 - i; // instanced model + surf->model_index = dm - brush->submodels; + if (!surf->model_index && m != r_worldentity.renderer.model) + surf->model_index = -1 - i; // instanced model tex = surf->texinfo->texture->render; CHAIN_SURF_F2B (surf, tex->tex_chain); } @@ -609,13 +609,13 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) for (is = tex->tex_chain; is; is = is->tex_chain) { msurface_t *surf = is->surface; if (!tex->elechain) { - ec = add_elechain (tex, surf->ec_index); + ec = add_elechain (tex, surf->model_index); el = ec->elements; el->base = (byte *) (intptr_t) vertices->size; vertex_index_base = 0; } - if (surf->ec_index != ec->index) { // next sub-model - ec = add_elechain (tex, surf->ec_index); + if (surf->model_index != ec->model_index) { // next sub-model + ec = add_elechain (tex, surf->model_index); el = ec->elements; el->base = (byte *) (intptr_t) vertices->size; vertex_index_base = 0; @@ -1080,7 +1080,7 @@ add_surf_elements (glsltex_t *tex, instsurf_t *is, glslpoly_t *poly = (glslpoly_t *) surf->polys; if (!tex->elechain) { - (*ec) = add_elechain (tex, surf->ec_index); + (*ec) = add_elechain (tex, surf->model_index); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; @@ -1090,7 +1090,7 @@ add_surf_elements (glsltex_t *tex, instsurf_t *is, dstring_clear ((*el)->list); } if (is->transform != (*ec)->transform || is->color != (*ec)->color) { - (*ec) = add_elechain (tex, surf->ec_index); + (*ec) = add_elechain (tex, surf->model_index); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index da8c90641..87bf42d0a 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -305,13 +305,13 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) } static elechain_t * -add_elechain (vulktex_t *tex, int ec_index, bspctx_t *bctx) +add_elechain (vulktex_t *tex, int model_index, bspctx_t *bctx) { elechain_t *ec; ec = get_elechain (bctx); ec->elements = get_elements (bctx); - ec->index = ec_index; + ec->model_index = model_index; ec->transform = 0; ec->color = 0; *tex->elechain_tail = ec; @@ -345,9 +345,9 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, float s, t; mod_brush_t *brush; - if (fa->ec_index < 0) { + if (fa->model_index < 0) { // instance model - brush = &models[~fa->ec_index]->brush; + brush = &models[~fa->model_index]->brush; } else { // main or sub model brush = &r_worldentity.renderer.model->brush; @@ -428,7 +428,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) bctx->sky_velocity = qexpf (bctx->sky_velocity); bctx->sky_time = vr_data.realtime; - // now run through all surfaces, chaining them to their textures, thus + // run through all surfaces, chaining them to their textures, thus // effectively sorting the surfaces by texture (without worrying about // surface order on the same texture chain). for (i = 0; i < num_models; i++) { @@ -436,14 +436,15 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!m) continue; // sub-models are done as part of the main model + // and non-bsp models don't have surfaces. if (*m->path == '*' || m->type != mod_brush) continue; brush = &m->brush; - // non-bsp models don't have surfaces. dm = brush->submodels; for (j = 0; j < brush->numsurfaces; j++) { vulktex_t *tex; if (j == dm->firstface + dm->numfaces) { + // move on to the next sub-model dm++; if (dm - brush->submodels == brush->numsubmodels) { // limit the surfaces @@ -454,9 +455,10 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } } surf = brush->surfaces + j; - surf->ec_index = dm - brush->submodels; - if (!surf->ec_index && m != r_worldentity.renderer.model) - surf->ec_index = -1 - i; // instanced model + surf->model_index = dm - brush->submodels; + if (!surf->model_index && m != r_worldentity.renderer.model) { + surf->model_index = -1 - i; // instanced model + } tex = surf->texinfo->texture->render; // append surf to the texture chain CHAIN_SURF_F2B (surf, tex->tex_chain); @@ -489,7 +491,8 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) qfv_packet_t *packet = QFV_PacketAcquire (stage); vertices = QFV_PacketExtend (packet, vertex_buffer_size); vertex_index_base = 0; - // holds all the polygon definitions (count + indices) + // holds all the polygon definitions: vertex indices + poly_count "end of + // primitive" markers. bctx->polys = malloc ((index_count + poly_count) * sizeof (uint32_t)); // All usable surfaces have been chained to the (base) texture they use. @@ -508,10 +511,10 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) for (is = tex->tex_chain; is; is = is->tex_chain) { msurface_t *surf = is->surface; if (!tex->elechain) { - ec = add_elechain (tex, surf->ec_index, bctx); + ec = add_elechain (tex, surf->model_index, bctx); } - if (surf->ec_index != ec->index) { // next sub-model - ec = add_elechain (tex, surf->ec_index, bctx); + if (surf->model_index != ec->model_index) { // next sub-model + ec = add_elechain (tex, surf->model_index, bctx); } surf->polys = (glpoly_t *) poly; @@ -523,9 +526,10 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } clear_texture_chains (bctx); Sys_MaskPrintf (SYS_vulkan, - "R_BuildDisplayLists: verts:%u, inds:%u, polys:%u (%d) %zd\n", + "R_BuildDisplayLists: verts:%u, inds:%u, " + "polys:%u (%d) %zd\n", vertex_count, index_count, poly_count, count, - ((size_t) poly - (size_t) bctx->polys)/sizeof(uint32_t)); + ((size_t) poly - (size_t) bctx->polys) / sizeof(uint32_t)); if (index_buffer_size > bctx->index_buffer_size) { if (bctx->index_buffer) { dfunc->vkUnmapMemory (device->dev, bctx->index_memory); @@ -602,7 +606,6 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) { float dot, radius; int i; - unsigned k; model_t *model; plane_t *plane; msurface_t *surf; @@ -639,21 +642,6 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) org[2] = DotProduct (temp, mat[2]); } - // calculate dynamic lighting for bmodel if it's not an instanced model - if (brush->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { - vec3_t lightorigin; - - for (k = 0; k < r_maxdlights; k++) { - if ((r_dlights[k].die < vr_data.realtime) - || (!r_dlights[k].radius)) - continue; - - VectorSubtract (r_dlights[k].origin, mat[3], lightorigin); - R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, - brush->nodes + brush->hulls[0].firstclipnode); - } - } - surf = &brush->surfaces[brush->firstmodelsurface]; for (i = 0; i < brush->nummodelsurfaces; i++, surf++) { @@ -1067,14 +1055,14 @@ add_surf_elements (vulktex_t *tex, instsurf_t *is, bsppoly_t *poly = (bsppoly_t *) surf->polys; if (!tex->elechain) { - (*ec) = add_elechain (tex, surf->ec_index, bctx); + (*ec) = add_elechain (tex, surf->model_index, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; (*el)->first_index = bframe->index_count; } if (is->transform != (*ec)->transform || is->color != (*ec)->color) { - (*ec) = add_elechain (tex, surf->ec_index, bctx); + (*ec) = add_elechain (tex, surf->model_index, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; From 6b38a17cf1e008f2ad68f7c563a6f4805bd017c3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Jul 2021 16:55:02 +0900 Subject: [PATCH 1642/3664] [gamecode] Clean up state imlementations This makes the code easier to read. Also, yay for automated tests: caught a mistyped time :) --- libs/gamecode/pr_exec.c | 34 ++++++++++++++-------------------- tools/qfcc/test/state.r | 4 ++-- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index a2455a0fb..7140f520b 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1488,31 +1488,25 @@ op_call: case OP_STATE: { int self = *pr->globals.self; - int nextthink = pr->fields.nextthink; - int frame = pr->fields.frame; - int think = pr->fields.think; - fldofs = self + nextthink; - pr->pr_edict_area[fldofs].float_var = *pr->globals.time + - 0.1; - fldofs = self + frame; - pr->pr_edict_area[fldofs].float_var = OPA.float_var; - fldofs = self + think; - pr->pr_edict_area[fldofs].func_var = OPB.func_var; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.time + 0.1; + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA.float_var; + pr->pr_edict_area[think].func_var = OPB.func_var; } break; case OP_STATE_F: { int self = *pr->globals.self; - int nextthink = pr->fields.nextthink; - int frame = pr->fields.frame; - int think = pr->fields.think; - fldofs = self + nextthink; - pr->pr_edict_area[fldofs].float_var = *pr->globals.time + - OPC.float_var; - fldofs = self + frame; - pr->pr_edict_area[fldofs].float_var = OPA.float_var; - fldofs = self + think; - pr->pr_edict_area[fldofs].func_var = OPB.func_var; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.time + OPC.float_var; + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA.float_var; + pr->pr_edict_area[think].func_var = OPB.func_var; } break; case OP_ADD_I: diff --git a/tools/qfcc/test/state.r b/tools/qfcc/test/state.r index a7be65754..839061e8c 100644 --- a/tools/qfcc/test/state.r +++ b/tools/qfcc/test/state.r @@ -25,7 +25,7 @@ state1 (void) { if (self.frame != $frame2 || self.think != state2 || self.nextthink != 0.2f) { - printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink); + printf ("state1: %g %x %g\n", self.frame, self.think, self.nextthink); exit (1); } } @@ -36,7 +36,7 @@ state2 (void) { if (self.frame != $frame0 || self.think != state0 || self.nextthink != 0.5f) { - printf ("state0: %g %x %g\n", self.frame, self.think, self.nextthink); + printf ("state2: %g %x %g\n", self.frame, self.think, self.nextthink); exit (1); } } From 3c93d555e379cd82457137518ef8a131813ad65a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Jul 2021 21:23:06 +0900 Subject: [PATCH 1643/3664] [gl] Correct calculation of screen aspect vrect_t's fields are ints, and it was vid.aspect that prevented the quotient being truncated. Fixes the rather squashed looking world. --- libs/video/renderer/gl/gl_rmain.c | 4 ++-- libs/video/renderer/r_screen.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 81181619e..8ee204a30 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -366,7 +366,7 @@ static void MYgluPerspective (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) { - GLdouble xmin, xmax, ymin, ymax; + GLdouble xmin, xmax, ymin, ymax; ymax = zNear * tan (fovy * M_PI / 360.0); ymin = -ymax; @@ -400,7 +400,7 @@ R_SetupGL_Viewport_and_Perspective (void) } // printf ("glViewport(%d, %d, %d, %d)\n", glx + x, gly + y2, w, h); qfglViewport (x, y2, w, h); - screenaspect = r_refdef.vrect.width / r_refdef.vrect.height; + screenaspect = r_refdef.vrect.width / (float) r_refdef.vrect.height; MYgluPerspective (r_refdef.fov_y, screenaspect, r_nearclip->value, r_farclip->value); } diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index f1ed6c349..54dffbcb0 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -165,16 +165,10 @@ SCR_CalcRefdef (void) vrect_t vrect; refdef_t *refdef = r_data->refdef; - refdef->fov_y = CalcFov (refdef->fov_x, refdef->vrect.width, - refdef->vrect.height); - // force a background redraw r_data->scr_fullupdate = 0; r_data->vid->recalc_refdef = 0; - // bound field of view - Cvar_SetValue (scr_fov, bound (1, scr_fov->value, 170)); - vrect.x = 0; vrect.y = 0; vrect.width = r_data->vid->width; @@ -185,6 +179,12 @@ SCR_CalcRefdef (void) view_setgeometry (r_data->scr_view, refdef->vrect.x, refdef->vrect.y, refdef->vrect.width, refdef->vrect.height); + // bound field of view + Cvar_SetValue (scr_fov, bound (1, scr_fov->value, 170)); + + refdef->fov_y = CalcFov (refdef->fov_x, refdef->vrect.width, + refdef->vrect.height); + // notify the refresh of the change r_funcs->R_ViewChanged (); } From 87dc35e2fd586c729b83304443942e6cc2dd53c5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Jul 2021 21:38:12 +0900 Subject: [PATCH 1644/3664] [renderer] Be more consistent with msurface_t names Use "surf" everywhere in gl, glsl and vulkan. Not worried about sw/sw32 at this stage (I don't poke around in there anywhere near as much). --- libs/video/renderer/gl/gl_lightmap.c | 19 ++-- libs/video/renderer/gl/gl_rmain.c | 18 ++-- libs/video/renderer/gl/gl_rsurf.c | 138 ++++++++++++------------ libs/video/renderer/gl/gl_sky_clip.c | 4 +- libs/video/renderer/gl/gl_warp.c | 4 +- libs/video/renderer/glsl/glsl_bsp.c | 39 +++---- libs/video/renderer/vulkan/vulkan_bsp.c | 47 ++++---- 7 files changed, 136 insertions(+), 133 deletions(-) diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 2ea33a8c0..4ff13a7a2 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -545,7 +545,7 @@ gl_overbright_f (cvar_t *var) { int num, i, j; model_t *m; - msurface_t *fa; + msurface_t *surf; entity_t *ent; mod_brush_t *brush; @@ -602,35 +602,36 @@ gl_overbright_f (cvar_t *var) continue; brush = &m->brush; - for (j = 0, fa = brush->surfaces; j < brush->numsurfaces; j++, fa++) { - if (fa->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) + for (j = 0, surf = brush->surfaces; j < brush->numsurfaces; + j++, surf++) { + if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) continue; - num = fa->lightmaptexturenum; + num = surf->lightmaptexturenum; gl_lightmap_modified[num] = true; gl_lightmap_rectchange[num].l = 0; gl_lightmap_rectchange[num].t = 0; gl_lightmap_rectchange[num].w = BLOCK_WIDTH; gl_lightmap_rectchange[num].h = BLOCK_HEIGHT; - gl_R_BuildLightMap (brush, fa); + gl_R_BuildLightMap (brush, surf); } } brush = &r_worldentity.renderer.model->brush; - for (i = 0, fa = brush->surfaces; i < brush->numsurfaces; i++, fa++) { - if (fa->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) + for (i = 0, surf = brush->surfaces; i < brush->numsurfaces; i++, surf++) { + if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) continue; - num = fa->lightmaptexturenum; + num = surf->lightmaptexturenum; gl_lightmap_modified[num] = true; gl_lightmap_rectchange[num].l = 0; gl_lightmap_rectchange[num].t = 0; gl_lightmap_rectchange[num].w = BLOCK_WIDTH; gl_lightmap_rectchange[num].h = BLOCK_HEIGHT; - gl_R_BuildLightMap (brush, fa); + gl_R_BuildLightMap (brush, surf); } } diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 8ee204a30..3d5502782 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -481,7 +481,7 @@ static void R_Mirror (void) { //float d; -// msurface_t *s; +// msurface_t *surf; // if (!gl_mirror) // FIXME: Broken return; @@ -528,25 +528,25 @@ R_Mirror (void) color_white[3] = r_mirroralpha->value * 255; qfglColor4ubv (color_white); #if 0//FIXME - s = r_worldentity.model->textures[gl_mirrortexturenum]->texturechain; - for (; s; s = s->texturechain) { + surf = r_worldentity.model->textures[gl_mirrortexturenum]->texturechain; + for (; surf; surf = surf->texturechain) { texture_t *tex; - if (!s->texinfo->texture->anim_total) - tex = s->texinfo->texture; + if (!surf->texinfo->texture->anim_total) + tex = surf->texinfo->texture; else - tex = R_TextureAnimation (s); + tex = R_TextureAnimation (surf); // FIXME: Needs to set the texture, the tmu, and include the header, and then // clean up afterwards. // if (tex->gl_fb_texturenum && gl_mtex_fullbright // && gl_fb_models->int_val) { -// s->polys->fb_chain = fullbright_polys[tex->gl_fb_texturenum]; -// fullbright_polys[tex->gl_fb_texturenum] = s->polys; +// surf->polys->fb_chain = fullbright_polys[tex->gl_fb_texturenum]; +// fullbright_polys[tex->gl_fb_texturenum] = surf->polys; // } qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); -// R_RenderBrushPoly (s, tex); // FIXME: Need to move R_Mirror to gl_rsurf.c, and uncommment this line! +// R_RenderBrushPoly (surf, tex); // FIXME: Need to move R_Mirror to gl_rsurf.c, and uncommment this line! } r_worldentity.model->textures[gl_mirrortexturenum]->texturechain = NULL; #endif diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index fb0aa71b6..f031dd9b0 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -210,7 +210,7 @@ R_RenderFullbrights (void) } static inline void -R_RenderBrushPoly_3 (msurface_t *fa) +R_RenderBrushPoly_3 (msurface_t *surf) { float *v; int i; @@ -218,9 +218,9 @@ R_RenderBrushPoly_3 (msurface_t *fa) gl_c_brush_polys++; qfglBegin (GL_POLYGON); - v = fa->polys->verts[0]; + v = surf->polys->verts[0]; - for (i = 0; i < fa->polys->numverts; i++, v += VERTEXSIZE) { + for (i = 0; i < surf->polys->numverts; i++, v += VERTEXSIZE) { qglMultiTexCoord2fv (gl_mtex_enum + 0, &v[3]); qglMultiTexCoord2fv (gl_mtex_enum + 1, &v[5]); qglMultiTexCoord2fv (gl_mtex_enum + 2, &v[3]); @@ -231,7 +231,7 @@ R_RenderBrushPoly_3 (msurface_t *fa) } static inline void -R_RenderBrushPoly_2 (msurface_t *fa) +R_RenderBrushPoly_2 (msurface_t *surf) { float *v; int i; @@ -239,9 +239,9 @@ R_RenderBrushPoly_2 (msurface_t *fa) gl_c_brush_polys++; qfglBegin (GL_POLYGON); - v = fa->polys->verts[0]; + v = surf->polys->verts[0]; - for (i = 0; i < fa->polys->numverts; i++, v += VERTEXSIZE) { + for (i = 0; i < surf->polys->numverts; i++, v += VERTEXSIZE) { qglMultiTexCoord2fv (gl_mtex_enum + 0, &v[3]); qglMultiTexCoord2fv (gl_mtex_enum + 1, &v[5]); qfglVertex3fv (v); @@ -251,7 +251,7 @@ R_RenderBrushPoly_2 (msurface_t *fa) } static inline void -R_RenderBrushPoly_1 (msurface_t *fa) +R_RenderBrushPoly_1 (msurface_t *surf) { float *v; int i; @@ -259,9 +259,9 @@ R_RenderBrushPoly_1 (msurface_t *fa) gl_c_brush_polys++; qfglBegin (GL_POLYGON); - v = fa->polys->verts[0]; + v = surf->polys->verts[0]; - for (i = 0; i < fa->polys->numverts; i++, v += VERTEXSIZE) { + for (i = 0; i < surf->polys->numverts; i++, v += VERTEXSIZE) { qfglTexCoord2fv (&v[3]); qfglVertex3fv (v); } @@ -270,42 +270,42 @@ R_RenderBrushPoly_1 (msurface_t *fa) } static inline void -R_AddToLightmapChain (mod_brush_t *brush, msurface_t *fa, instsurf_t *sc) +R_AddToLightmapChain (mod_brush_t *brush, msurface_t *surf, instsurf_t *sc) { int maps, smax, tmax; glRect_t *theRect; // add the poly to the proper lightmap chain - sc->lm_chain = gl_lightmap_polys[fa->lightmaptexturenum]; - gl_lightmap_polys[fa->lightmaptexturenum] = sc; + sc->lm_chain = gl_lightmap_polys[surf->lightmaptexturenum]; + gl_lightmap_polys[surf->lightmaptexturenum] = sc; // check for lightmap modification - for (maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++) - if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps]) + for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) + if (d_lightstylevalue[surf->styles[maps]] != surf->cached_light[maps]) goto dynamic; - if ((fa->dlightframe == r_framecount) || fa->cached_dlight) { + if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { dynamic: if (r_dynamic->int_val) { - gl_lightmap_modified[fa->lightmaptexturenum] = true; - theRect = &gl_lightmap_rectchange[fa->lightmaptexturenum]; - if (fa->light_t < theRect->t) { + gl_lightmap_modified[surf->lightmaptexturenum] = true; + theRect = &gl_lightmap_rectchange[surf->lightmaptexturenum]; + if (surf->light_t < theRect->t) { if (theRect->h) - theRect->h += theRect->t - fa->light_t; - theRect->t = fa->light_t; + theRect->h += theRect->t - surf->light_t; + theRect->t = surf->light_t; } - if (fa->light_s < theRect->l) { + if (surf->light_s < theRect->l) { if (theRect->w) - theRect->w += theRect->l - fa->light_s; - theRect->l = fa->light_s; + theRect->w += theRect->l - surf->light_s; + theRect->l = surf->light_s; } - smax = (fa->extents[0] >> 4) + 1; - tmax = (fa->extents[1] >> 4) + 1; - if ((theRect->w + theRect->l) < (fa->light_s + smax)) - theRect->w = (fa->light_s - theRect->l) + smax; - if ((theRect->h + theRect->t) < (fa->light_t + tmax)) - theRect->h = (fa->light_t - theRect->t) + tmax; - gl_R_BuildLightMap (brush, fa); + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + if ((theRect->w + theRect->l) < (surf->light_s + smax)) + theRect->w = (surf->light_s - theRect->l) + smax; + if ((theRect->h + theRect->t) < (surf->light_t + tmax)) + theRect->h = (surf->light_t - theRect->t) + tmax; + gl_R_BuildLightMap (brush, surf); } } } @@ -315,7 +315,7 @@ gl_R_DrawWaterSurfaces (void) { int i; instsurf_t *s; - msurface_t *fa; + msurface_t *surf; float wateralpha = max (vr_data.min_wateralpha, r_wateralpha->value); if (!waterchain) @@ -333,17 +333,17 @@ gl_R_DrawWaterSurfaces (void) i = -1; for (s = waterchain; s; s = s->tex_chain) { gltex_t *tex; - fa = s->surface; + surf = s->surface; if (s->transform) qfglLoadMatrixf (s->transform); else qfglLoadMatrixf (gl_r_world_matrix); - tex = fa->texinfo->texture->render; + tex = surf->texinfo->texture->render; if (i != tex->gl_texturenum) { i = tex->gl_texturenum; qfglBindTexture (GL_TEXTURE_2D, i); } - GL_EmitWaterPolys (fa); + GL_EmitWaterPolys (surf); } qfglLoadMatrixf (gl_r_world_matrix); @@ -361,7 +361,7 @@ DrawTextureChains (int disable_blend, int do_bind) { int i; instsurf_t *s; - msurface_t *fa; + msurface_t *surf; gltex_t *tex; if (gl_mtex_active_tmus >= 2) { @@ -386,7 +386,7 @@ DrawTextureChains (int disable_blend, int do_bind) qglActiveTexture (gl_mtex_enum + 1); for (s = tex->tex_chain; s; s = s->tex_chain) { - fa = s->surface; + surf = s->surface; if (s->transform) { qfglPushMatrix (); qfglLoadMatrixf (s->transform); @@ -394,9 +394,9 @@ DrawTextureChains (int disable_blend, int do_bind) if (s->color && do_bind) qfglColor4fv (s->color); qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + - fa->lightmaptexturenum); + surf->lightmaptexturenum); - R_RenderBrushPoly_3 (fa); + R_RenderBrushPoly_3 (surf); if (s->transform) qfglPopMatrix (); @@ -411,9 +411,9 @@ DrawTextureChains (int disable_blend, int do_bind) } else { qglActiveTexture (gl_mtex_enum + 1); for (s = tex->tex_chain; s; s = s->tex_chain) { - fa = s->surface; + surf = s->surface; qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + - fa->lightmaptexturenum); + surf->lightmaptexturenum); if (s->transform) { qfglPushMatrix (); @@ -421,7 +421,7 @@ DrawTextureChains (int disable_blend, int do_bind) } if (s->color && do_bind) qfglColor4fv (s->color); - R_RenderBrushPoly_2 (fa); + R_RenderBrushPoly_2 (surf); if (s->transform) qfglPopMatrix (); @@ -522,8 +522,7 @@ gl_R_DrawBrushModel (entity_t *e) int i; unsigned int k; model_t *model; - plane_t *pplane; - msurface_t *psurf; + msurface_t *surf; qboolean rotated; vec3_t mins, maxs; mod_brush_t *brush; @@ -587,19 +586,19 @@ gl_R_DrawBrushModel (entity_t *e) qfglGetFloatv (GL_MODELVIEW_MATRIX, e->renderer.full_transform); qfglPopMatrix (); - psurf = &brush->surfaces[brush->firstmodelsurface]; + surf = &brush->surfaces[brush->firstmodelsurface]; // draw texture - for (i = 0; i < brush->nummodelsurfaces; i++, psurf++) { + for (i = 0; i < brush->nummodelsurfaces; i++, surf++) { // find which side of the node we are on - pplane = psurf->plane; + plane_t *plane = surf->plane; - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + dot = DotProduct (modelorg, plane->normal) - plane->dist; // draw the polygon - if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || - (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (brush, psurf, e->renderer.full_transform, + if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { + chain_surface (brush, surf, e->renderer.full_transform, e->renderer.colormod); } } @@ -817,7 +816,7 @@ gl_R_DrawWorld (void) model_t *gl_currentmodel; void -GL_BuildSurfaceDisplayList (msurface_t *fa) +GL_BuildSurfaceDisplayList (msurface_t *surf) { float s, t; float *vec; @@ -827,18 +826,19 @@ GL_BuildSurfaceDisplayList (msurface_t *fa) // reconstruct the polygon pedges = gl_currentmodel->brush.edges; - lnumverts = fa->numedges; + lnumverts = surf->numedges; // draw texture poly = Hunk_Alloc (sizeof (glpoly_t) + (lnumverts - 4) * VERTEXSIZE * sizeof (float)); - poly->next = fa->polys; - poly->flags = fa->flags; - fa->polys = poly; + poly->next = surf->polys; + poly->flags = surf->flags; + surf->polys = poly; poly->numverts = lnumverts; + mtexinfo_t *texinfo = surf->texinfo; for (i = 0; i < lnumverts; i++) { - lindex = gl_currentmodel->brush.surfedges[fa->firstedge + i]; + lindex = gl_currentmodel->brush.surfedges[surf->firstedge + i]; if (lindex > 0) { r_pedge = &pedges[lindex]; @@ -847,35 +847,35 @@ GL_BuildSurfaceDisplayList (msurface_t *fa) r_pedge = &pedges[-lindex]; vec = r_pcurrentvertbase[r_pedge->v[1]].position; } - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - s /= fa->texinfo->texture->width; + s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; + s /= texinfo->texture->width; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - t /= fa->texinfo->texture->height; + t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; + t /= texinfo->texture->height; VectorCopy (vec, poly->verts[i]); poly->verts[i][3] = s; poly->verts[i][4] = t; // lightmap texture coordinates - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - s -= fa->texturemins[0]; - s += fa->light_s * 16; + s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; + s -= surf->texturemins[0]; + s += surf->light_s * 16; s += 8; - s /= BLOCK_WIDTH * 16; // fa->texinfo->texture->width; + s /= BLOCK_WIDTH * 16; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - t -= fa->texturemins[1]; - t += fa->light_t * 16; + t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; + t -= surf->texturemins[1]; + t += surf->light_t * 16; t += 8; - t /= BLOCK_HEIGHT * 16; // fa->texinfo->texture->height; + t /= BLOCK_HEIGHT * 16; poly->verts[i][5] = s; poly->verts[i][6] = t; } // remove co-linear points - Ed - if (!gl_keeptjunctions->int_val && !(fa->flags & SURF_UNDERWATER)) { + if (!gl_keeptjunctions->int_val && !(surf->flags & SURF_UNDERWATER)) { for (i = 0; i < lnumverts; ++i) { vec3_t v1, v2; float *prev, *this, *next; diff --git a/libs/video/renderer/gl/gl_sky_clip.c b/libs/video/renderer/gl/gl_sky_clip.c index 697403eb9..0ac4d2dde 100644 --- a/libs/video/renderer/gl/gl_sky_clip.c +++ b/libs/video/renderer/gl/gl_sky_clip.c @@ -644,10 +644,10 @@ EmitSkyPolys (float speedscale, const instsurf_t *sc) int i; glpoly_t *p; vec3_t dir; - msurface_t *fa = sc->surface; + msurface_t *surf = sc->surface; //FIXME transform/color - for (p = fa->polys; p; p = p->next) { + for (p = surf->polys; p; p = p->next) { qfglBegin (GL_POLYGON); for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { VectorSubtract (v, r_origin, dir); diff --git a/libs/video/renderer/gl/gl_warp.c b/libs/video/renderer/gl/gl_warp.c index d73e11f2a..d32bc4141 100644 --- a/libs/video/renderer/gl/gl_warp.c +++ b/libs/video/renderer/gl/gl_warp.c @@ -54,7 +54,7 @@ static float turbsin[] = { Does a water warp on the pre-fragmented glpoly_t chain */ void -GL_EmitWaterPolys (msurface_t *fa) +GL_EmitWaterPolys (msurface_t *surf) { float os, ot, s, t, timetemp; float *v; @@ -63,7 +63,7 @@ GL_EmitWaterPolys (msurface_t *fa) timetemp = vr_data.realtime * TURBSCALE; - for (p = fa->polys; p; p = p->next) { + for (p = surf->polys; p; p = p->next) { qfglBegin (GL_POLYGON); for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { os = turbsin[(int) (v[3] * TURBFRAC + timetemp) & 255]; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index d81a4f108..600fb0eeb 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -465,7 +465,7 @@ add_elechain (glsltex_t *tex, int model_index) } static void -build_surf_displist (model_t **models, msurface_t *fa, int base, +build_surf_displist (model_t **models, msurface_t *surf, int base, dstring_t *vert_list) { int numverts; @@ -483,8 +483,8 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, float s, t; mod_brush_t *brush; - if (fa->model_index < 0) { - brush = &models[-fa->model_index - 1]->brush; + if (surf->model_index < 0) { + brush = &models[-surf->model_index - 1]->brush; } else { brush = &r_worldentity.renderer.model->brush; } @@ -492,7 +492,7 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, edges = brush->edges; surfedges = brush->surfedges; - numverts = fa->numedges; + numverts = surf->numedges; numtris = numverts - 2; numindices = numtris * 3; verts = alloca (numverts * sizeof (bspvert_t)); @@ -503,39 +503,40 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, *ind++ = base + i + 1; *ind++ = base + i + 2; } - fa->polys = (glpoly_t *) poly; + surf->polys = (glpoly_t *) poly; + mtexinfo_t *texinfo = surf->texinfo; for (i = 0; i < numverts; i++) { - index = surfedges[fa->firstedge + i]; + index = surfedges[surf->firstedge + i]; if (index > 0) vec = vertices[edges[index].v[0]].position; else vec = vertices[edges[-index].v[1]].position; - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; + s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; + t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; VectorCopy (vec, verts[i].vertex); verts[i].vertex[3] = 1; - verts[i].tlst[0] = s / fa->texinfo->texture->width; - verts[i].tlst[1] = t / fa->texinfo->texture->height; + verts[i].tlst[0] = s / texinfo->texture->width; + verts[i].tlst[1] = t / texinfo->texture->height; //lightmap texture coordinates - if (!fa->lightpic) { + if (!surf->lightpic) { // sky and water textures don't have lightmaps verts[i].tlst[2] = 0; verts[i].tlst[3] = 0; continue; } - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - s -= fa->texturemins[0]; - t -= fa->texturemins[1]; - s += fa->lightpic->rect->x * 16 + 8; - t += fa->lightpic->rect->y * 16 + 8; + s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; + t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; + s -= surf->texturemins[0]; + t -= surf->texturemins[1]; + s += surf->lightpic->rect->x * 16 + 8; + t += surf->lightpic->rect->y * 16 + 8; s /= 16; t /= 16; - verts[i].tlst[2] = s * fa->lightpic->size; - verts[i].tlst[3] = t * fa->lightpic->size; + verts[i].tlst[2] = s * surf->lightpic->size; + verts[i].tlst[3] = t * surf->lightpic->size; } dstring_append (vert_list, (char *) verts, numverts * sizeof (bspvert_t)); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 87bf42d0a..c18deadb8 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -320,15 +320,15 @@ add_elechain (vulktex_t *tex, int model_index, bspctx_t *bctx) } static void -count_verts_inds (model_t **models, msurface_t *fa, +count_verts_inds (model_t **models, msurface_t *surf, uint32_t *verts, uint32_t *inds) { - *verts = fa->numedges; - *inds = fa->numedges + 1; + *verts = surf->numedges; + *inds = surf->numedges + 1; } static bsppoly_t * -build_surf_displist (model_t **models, msurface_t *fa, int base, +build_surf_displist (model_t **models, msurface_t *surf, int base, bspvert_t **vert_list) { int numverts; @@ -345,9 +345,9 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, float s, t; mod_brush_t *brush; - if (fa->model_index < 0) { + if (surf->model_index < 0) { // instance model - brush = &models[~fa->model_index]->brush; + brush = &models[~surf->model_index]->brush; } else { // main or sub model brush = &r_worldentity.renderer.model->brush; @@ -356,50 +356,51 @@ build_surf_displist (model_t **models, msurface_t *fa, int base, edges = brush->edges; surfedges = brush->surfedges; // create a triangle fan - numverts = fa->numedges; + numverts = surf->numedges; numindices = numverts + 1; verts = *vert_list; // surf->polys is set to the next slot before the call - poly = (bsppoly_t *) fa->polys; + poly = (bsppoly_t *) surf->polys; poly->count = numindices; for (i = 0, ind = poly->indices; i < numverts; i++) { *ind++ = base + i; } *ind++ = -1; // end of primitive - fa->polys = (glpoly_t *) poly; + surf->polys = (glpoly_t *) poly; + mtexinfo_t *texinfo = surf->texinfo; for (i = 0; i < numverts; i++) { - index = surfedges[fa->firstedge + i]; + index = surfedges[surf->firstedge + i]; if (index > 0) { vec = vertices[edges[index].v[0]].position; } else { vec = vertices[edges[-index].v[1]].position; } - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; + s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; + t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; VectorCopy (vec, verts[i].vertex); verts[i].vertex[3] = 1; - verts[i].tlst[0] = s / fa->texinfo->texture->width; - verts[i].tlst[1] = t / fa->texinfo->texture->height; + verts[i].tlst[0] = s / texinfo->texture->width; + verts[i].tlst[1] = t / texinfo->texture->height; //lightmap texture coordinates - if (!fa->lightpic) { + if (!surf->lightpic) { // sky and water textures don't have lightmaps verts[i].tlst[2] = 0; verts[i].tlst[3] = 0; continue; } - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - s -= fa->texturemins[0]; - t -= fa->texturemins[1]; - s += fa->lightpic->rect->x * 16 + 8; - t += fa->lightpic->rect->y * 16 + 8; + s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; + t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; + s -= surf->texturemins[0]; + t -= surf->texturemins[1]; + s += surf->lightpic->rect->x * 16 + 8; + t += surf->lightpic->rect->y * 16 + 8; s /= 16; t /= 16; - verts[i].tlst[2] = s * fa->lightpic->size; - verts[i].tlst[3] = t * fa->lightpic->size; + verts[i].tlst[2] = s * surf->lightpic->size; + verts[i].tlst[3] = t * surf->lightpic->size; } *vert_list += numverts; return (bsppoly_t *) &poly->indices[numindices]; From 3ef89583af4eab68a268f0cadc13825f03eb915f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Jul 2021 22:31:22 +0900 Subject: [PATCH 1645/3664] [gamecode] Correct pop implementations Had src and dst swapped (yay for not testing :P (boo for not having an easy way to test (yay for working on it))). --- libs/gamecode/pr_exec.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 7140f520b..09d8b9fc8 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1225,7 +1225,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); } - stk->integer_var = OPA.integer_var; + OPA.integer_var = stk->integer_var; *pr->globals.stack = stack + 1; } break; @@ -1236,7 +1236,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); } - memcpy (stk, &OPA, 3 * sizeof (OPC)); + memcpy (&OPA, stk, 3 * sizeof (OPC)); *pr->globals.stack = stack + 3; } break; @@ -1247,7 +1247,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); } - memcpy (stk, &OPA, 4 * sizeof (OPC)); + memcpy (&OPA, stk, 4 * sizeof (OPC)); *pr->globals.stack = stack + 4; } break; @@ -1271,7 +1271,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - stk->integer_var = ptr->integer_var; + ptr->integer_var = stk->integer_var; *pr->globals.stack = stack + 1; } break; @@ -1288,7 +1288,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (&ptr->vector_var, &stk->vector_var); + VectorCopy (&stk->vector_var, &ptr->vector_var); *pr->globals.stack = stack + 3; } break; @@ -1305,7 +1305,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (&ptr->quat_var, &stk->quat_var); + QuatCopy (&stk->quat_var, &ptr->quat_var); *pr->globals.stack = stack + 4; } break; @@ -1329,7 +1329,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - stk->integer_var = ptr->integer_var; + ptr->integer_var = stk->integer_var; *pr->globals.stack = stack + 1; } break; @@ -1346,7 +1346,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_integer); } - VectorCopy (&ptr->vector_var, &stk->vector_var); + VectorCopy (&stk->vector_var, &ptr->vector_var); *pr->globals.stack = stack + 3; } break; @@ -1363,7 +1363,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) PR_BoundsCheck (pr, pointer, ev_quat); } - QuatCopy (&ptr->quat_var, &stk->quat_var); + QuatCopy (&stk->quat_var, &ptr->quat_var); *pr->globals.stack = stack + 4; } break; From 924c970868d78f3dc845756ee3cfab673c21f035 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Jul 2021 22:36:51 +0900 Subject: [PATCH 1646/3664] [vulkan] Pre-compute the sun's PVS Any sun (a directional light) is in the outside node, which due to not having its own PVS data is visible to all nodes, but that's a tad excessive. However, any leaf node with sky surfaces will potentially see any suns, and leaf nodes with no sky surfaces will see the sun only if they can see a leaf that does have sky surfaces. This can be quite expensive to calculate (already known to be moderately expensive for just the camera leaf node (singular!) when checking for in-map lights) --- include/QF/Vulkan/qf_lighting.h | 1 + libs/video/renderer/vulkan/vulkan_lighting.c | 39 ++++++++++++++------ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index cdf3b612e..15b094576 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -124,6 +124,7 @@ typedef struct lightingctx_s { qfv_imageset_t lightimages; qfv_lightintset_t lightlayers; qfv_imageviewset_t lightviews; + byte sun_pvs[MAX_MAP_LEAFS]; } lightingctx_t; struct vulkan_ctx_s; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index c24a2ee35..eb2b1fd3a 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -67,6 +67,18 @@ static vec4f_t ref_direction = { 0, 0, 1, 0 }; +static void +expand_pvs (byte *pvs, model_t *model) +{ + byte base_pvs[MAP_PVS_BYTES]; + memcpy (base_pvs, pvs, sizeof (base_pvs)); + for (int i = 0; i < model->brush.numleafs; i++) { + if (base_pvs[(unsigned) i / 8] & (1 << ((unsigned) i % 8))) { + Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, pvs); + } + } +} + static void find_visible_lights (vulkan_ctx_t *ctx) { @@ -84,17 +96,10 @@ find_visible_lights (vulkan_ctx_t *ctx) if (leaf != lframe->leaf) { //double start = Sys_DoubleTime (); - byte pvs[MAP_PVS_BYTES]; int flags = 0; - Mod_LeafPVS_set (leaf, model, 0, pvs); - memcpy (lframe->pvs, pvs, sizeof (pvs)); - for (int i = 0; i < model->brush.numleafs; i++) { - if (pvs[i / 8] & (1 << (i % 8))) { - Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, - lframe->pvs); - } - } + Mod_LeafPVS_set (leaf, model, 0, lframe->pvs); + expand_pvs (lframe->pvs, model); for (int i = 0; i < model->brush.numleafs; i++) { if (lframe->pvs[i / 8] & (1 << (i % 8))) { flags |= model->brush.leaf_flags[i + 1]; @@ -535,13 +540,14 @@ sun_vector (const vec_t *ang, vec_t *vec) } static void -parse_sun (lightingctx_t *lctx, plitem_t *entity) +parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model) { qfv_light_t light = {}; float sunlight; //float sunlight2; vec3_t sunangle = { 0, -90, 0 }; + memset (lctx->sun_pvs, 0, MAX_MAP_LEAFS); sunlight = parse_float (PL_String (PL_ObjectForKey (entity, "_sunlight")), 0); //sunlight2 = parse_float (PL_String (PL_ObjectForKey (entity, @@ -558,6 +564,17 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity) light.cone = 1; DARRAY_APPEND (&lctx->lights, light); DARRAY_APPEND (&lctx->lightleafs, -1); + + // Any leaf with sky surfaces can potentially see the sun, thus put + // the sun "in" every leaf with a sky surface + for (int l = 0; l < model->brush.numleafs; l++) { + if (model->brush.leaf_flags[l] & SURF_DRAWSKY) { + lctx->sun_pvs[l / 8] |= 1 << (l % 8); + } + } + // any leaf visible from a leaf with a sky surface (and thus the sun) + // can receive shadows from the sun + expand_pvs (lctx->sun_pvs, model); } static void @@ -934,7 +951,7 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) } if (strequal (classname, "worldspawn")) { // parse_sun can add many lights - parse_sun (lctx, entity); + parse_sun (lctx, entity, model); } else if (strnequal (classname, "light", 5)) { qfv_light_t light = {}; From 6962c5948aa0ef6116379fda565111fb86195399 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Jul 2021 23:38:09 +0900 Subject: [PATCH 1647/3664] [vulkan] Clean up some more unused bsp data Since vulkan supports 32-bit indexes, there's no need for the shenanigans the EGL-based glsl renderer had to go through to render bsp models (maps often had quite a bit more than 65536 vertices), though the reduced GPU memory requirements of 16-bit indices does have its advantages. --- include/QF/Vulkan/qf_bsp.h | 1 - libs/video/renderer/vulkan/vulkan_bsp.c | 14 +++----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index bcf561d7b..de389d620 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -54,7 +54,6 @@ typedef struct elements_s { typedef struct elechain_s { struct elechain_s *_next; struct elechain_s *next; - int model_index; ///< < 0: instance, 0 main, > 0: sub elements_t *elements; vec_t *transform; float *color; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index c18deadb8..5ba4251ba 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -305,13 +305,12 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) } static elechain_t * -add_elechain (vulktex_t *tex, int model_index, bspctx_t *bctx) +add_elechain (vulktex_t *tex, bspctx_t *bctx) { elechain_t *ec; ec = get_elechain (bctx); ec->elements = get_elements (bctx); - ec->model_index = model_index; ec->transform = 0; ec->color = 0; *tex->elechain_tail = ec; @@ -505,18 +504,11 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) for (size_t i = 0; i < bctx->texture_chains.size; i++) { vulktex_t *tex; instsurf_t *is; - elechain_t *ec = 0; tex = bctx->texture_chains.a[i]; for (is = tex->tex_chain; is; is = is->tex_chain) { msurface_t *surf = is->surface; - if (!tex->elechain) { - ec = add_elechain (tex, surf->model_index, bctx); - } - if (surf->model_index != ec->model_index) { // next sub-model - ec = add_elechain (tex, surf->model_index, bctx); - } surf->polys = (glpoly_t *) poly; poly = build_surf_displist (models, surf, vertex_index_base, @@ -1056,14 +1048,14 @@ add_surf_elements (vulktex_t *tex, instsurf_t *is, bsppoly_t *poly = (bsppoly_t *) surf->polys; if (!tex->elechain) { - (*ec) = add_elechain (tex, surf->model_index, bctx); + (*ec) = add_elechain (tex, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; (*el)->first_index = bframe->index_count; } if (is->transform != (*ec)->transform || is->color != (*ec)->color) { - (*ec) = add_elechain (tex, surf->model_index, bctx); + (*ec) = add_elechain (tex, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; (*el) = (*ec)->elements; From 5864406f4d76f95e652a0ba48a06319f450ba8c5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Jul 2021 14:15:56 +0900 Subject: [PATCH 1648/3664] [vulkan] Enable all lights when camera out of map Without shadows, this is quite the cheat, but noclip is a cheat anyway, so probably not that big a deal. It does, however, make noclip usable for debugging. --- libs/video/renderer/vulkan/vulkan_lighting.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index eb2b1fd3a..a7a59d6c9 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -98,8 +98,12 @@ find_visible_lights (vulkan_ctx_t *ctx) //double start = Sys_DoubleTime (); int flags = 0; - Mod_LeafPVS_set (leaf, model, 0, lframe->pvs); - expand_pvs (lframe->pvs, model); + if (leaf == model->brush.leafs) { + memset (lframe->pvs, 0xff, sizeof (lframe->pvs)); + } else { + Mod_LeafPVS_set (leaf, model, 0, lframe->pvs); + expand_pvs (lframe->pvs, model); + } for (int i = 0; i < model->brush.numleafs; i++) { if (lframe->pvs[i / 8] & (1 << (i % 8))) { flags |= model->brush.leaf_flags[i + 1]; From 0f259c647ba442893dc9825f8dafefd2fde4b059 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Jul 2021 14:18:24 +0900 Subject: [PATCH 1649/3664] [vulkan] Clean out some dead code While I might want to support lightmaps in the future (eg, for ambient occlusion), the commented out code is confusing. --- libs/video/renderer/vulkan/vulkan_bsp.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 5ba4251ba..5d1ad07a3 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -211,23 +211,7 @@ Vulkan_ClearElements (vulkan_ctx_t *ctx) release_elechains (bctx); release_elementss (bctx); } -/* -static void -update_lightmap (mod_brush_t *brush, msurface_t *surf, vulkan_ctx_t *ctx) -{ - int maps; - for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) - if (d_lightstylevalue[surf->styles[maps]] != surf->cached_light[maps]) - goto dynamic; - - if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { -dynamic: - if (r_dynamic->int_val) - Vulkan_BuildLightMap (brush, surf, ctx); - } -} -*/ static inline void chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, float *color, vulkan_ctx_t *ctx) @@ -249,8 +233,6 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, tx = R_TextureAnimation (surf); tex = tx->render; is = CHAIN_SURF_F2B (surf, tex->tex_chain); - - //update_lightmap (brush, surf, ctx); } is->transform = transform; is->color = color; @@ -1096,9 +1078,6 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) worldent.renderer.model = r_worldentity.renderer.model; brush = &r_worldentity.renderer.model->brush; - //vulktex_t *tex = r_worldentity.renderer.model->skytexture->render; - //bctx->skysheet_tex = tex->tex; - currententity = &worldent; R_VisitWorldNodes (brush, ctx); @@ -1113,7 +1092,6 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) } } - //Vulkan_FlushLightmaps (ctx); bsp_begin (ctx); push_transform (identity, bctx->layout, dfunc, @@ -1123,7 +1101,6 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) fragconst_t frag_constants = { time: vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspGBuffer]); - //XXX qfeglActiveTexture (GL_TEXTURE0 + 0); for (size_t i = 0; i < bctx->texture_chains.size; i++) { vulktex_t *tex; elechain_t *ec = 0; From 3351b62318ca58b1857ad39acfaec18edae9d825 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Jul 2021 16:36:51 +0900 Subject: [PATCH 1650/3664] [renderer] Move driver specific texture chain defs The GL/GLSL/Vulklan texture chaining defs never should have been in r_internal.h in the first place. They still need a better name, though. --- include/QF/GL/qf_rsurf.h | 14 ++++++++++++- include/QF/GLSL/qf_bsp.h | 16 +++++++++++++-- include/QF/GLSL/types.h | 4 ++-- include/QF/Vulkan/qf_bsp.h | 13 +++++++++++- include/QF/qtypes.h | 1 + include/r_internal.h | 29 --------------------------- libs/models/brush/gl_model_brush.c | 1 + libs/models/brush/glsl_model_brush.c | 1 + libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + 10 files changed, 46 insertions(+), 35 deletions(-) diff --git a/include/QF/GL/qf_rsurf.h b/include/QF/GL/qf_rsurf.h index 569fcdaf1..e799747ee 100644 --- a/include/QF/GL/qf_rsurf.h +++ b/include/QF/GL/qf_rsurf.h @@ -28,14 +28,26 @@ #ifndef __QF_GL_rsurf_h #define __QF_GL_rsurf_h +typedef struct gltex_s { + struct texture_s *texture; + int gl_texturenum; + int gl_fb_texturenum; + struct instsurf_s *tex_chain; + struct instsurf_s **tex_chain_tail; +} gltex_t; + extern int gl_mirrortexturenum; // quake texturenum, not gltexturenum +struct model_s; +struct entity_s; +struct msurface_s; + void gl_lightmap_init (void); void GL_BuildLightmaps (struct model_s **models, int num_models); void R_DrawBrushModel (struct entity_s *e); void R_DrawWorld (void); -void GL_EmitWaterPolys (msurface_t *fa); +void GL_EmitWaterPolys (struct msurface_s *fa); #endif // __QF_GL_rsurf_h diff --git a/include/QF/GLSL/qf_bsp.h b/include/QF/GLSL/qf_bsp.h index d89a9145e..7e74aa9f7 100644 --- a/include/QF/GLSL/qf_bsp.h +++ b/include/QF/GLSL/qf_bsp.h @@ -32,6 +32,16 @@ #include "QF/GLSL/types.h" +typedef struct glsltex_s { + struct texture_s *texture; + int gl_texturenum; + int sky_tex[2]; + struct instsurf_s *tex_chain; + struct instsurf_s **tex_chain_tail; + struct elechain_s *elechain; + struct elechain_s **elechain_tail; +} glsltex_t; + typedef struct bspvert_s { quat_t vertex; quat_t tlst; @@ -53,11 +63,13 @@ typedef struct elechain_s { float *color; } elechain_t; +struct model_s; + void glsl_R_ClearElements (void); void glsl_R_DrawWorld (void); void glsl_R_DrawSky (void); -void glsl_R_RegisterTextures (model_t **models, int num_models); -void glsl_R_BuildDisplayLists (model_t **models, int num_models); +void glsl_R_RegisterTextures (struct model_s **models, int num_models); +void glsl_R_BuildDisplayLists (struct model_s **models, int num_models); void glsl_R_InitBsp (void); #endif//__QF_GLSL_qf_bsp_h diff --git a/include/QF/GLSL/types.h b/include/QF/GLSL/types.h index 62c50780b..16c04719d 100644 --- a/include/QF/GLSL/types.h +++ b/include/QF/GLSL/types.h @@ -3,8 +3,8 @@ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . */ -#ifndef __QFGL_types_h -#define __QFGL_types_h +#ifndef __QF_GLSL_types_h +#define __QF_GLSL_types_h #include "QF/qtypes.h" diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index de389d620..c9c4e4d90 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -39,6 +39,17 @@ #include "QF/simd/types.h" +typedef struct vulktex_s { + struct texture_s *texture; + struct instsurf_s *tex_chain; // for gl_texsort drawing + struct instsurf_s **tex_chain_tail; + struct elechain_s *elechain; + struct elechain_s **elechain_tail; + struct qfv_tex_s *tex; + struct qfv_tex_s *glow; + byte *glow_pixels; +} vulktex_t; + typedef struct bspvert_s { quat_t vertex; quat_t tlst; @@ -99,7 +110,7 @@ typedef struct bspframeset_s DARRAY_TYPE (bspframe_t) bspframeset_t; typedef struct texchainset_s - DARRAY_TYPE (struct vulktex_s *) texchainset_t; + DARRAY_TYPE (vulktex_t *) texchainset_t; typedef struct bspctx_s { instsurf_t *waterchain; diff --git a/include/QF/qtypes.h b/include/QF/qtypes.h index ea3a4df6c..2c37c286b 100644 --- a/include/QF/qtypes.h +++ b/include/QF/qtypes.h @@ -32,6 +32,7 @@ #include #include +#include #ifdef HAVE_SYSTEM_MSG_T # define msg_t sys_msg_t diff --git a/include/r_internal.h b/include/r_internal.h index b17a11a62..b5847ec03 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -9,35 +9,6 @@ #include "r_screen.h" #include "r_shared.h" -typedef struct gltex_s { - texture_t *texture; - int gl_texturenum; - int gl_fb_texturenum; - instsurf_t *tex_chain; // for gl_texsort drawing - instsurf_t **tex_chain_tail; -} gltex_t; - -typedef struct glsltex_s { - texture_t *texture; - int gl_texturenum; - int sky_tex[2]; - instsurf_t *tex_chain; // for gl_texsort drawing - instsurf_t **tex_chain_tail; - struct elechain_s *elechain; - struct elechain_s **elechain_tail; -} glsltex_t; - -typedef struct vulktex_s { - texture_t *texture; - instsurf_t *tex_chain; // for gl_texsort drawing - instsurf_t **tex_chain_tail; - struct elechain_s *elechain; - struct elechain_s **elechain_tail; - struct qfv_tex_s *tex; - struct qfv_tex_s *glow; - byte *glow_pixels; -} vulktex_t; - extern viddef_t vid; // global video state extern vid_render_data_t vid_render_data; diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 42d370c67..610b0bc1a 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -45,6 +45,7 @@ #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/GL/qf_rsurf.h" #include "QF/GL/qf_textures.h" #include "compat.h" diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index f44327acd..424205115 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -53,6 +53,7 @@ #include "QF/vid.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" +#include "QF/GLSL/qf_bsp.h" #include "QF/GLSL/qf_textures.h" #include "compat.h" diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index aabb991be..01f5a5875 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -34,6 +34,7 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/GL/qf_rsurf.h" #include "QF/GL/qf_vid.h" #include "mod_internal.h" diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 3c73ac0b5..64ba6a0e3 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -34,6 +34,7 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/GLSL/qf_bsp.h" #include "QF/GLSL/qf_vid.h" #include "mod_internal.h" From 8369a2206a79868c73f47c1f81ac1731e8f17125 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jul 2021 10:12:41 +0900 Subject: [PATCH 1651/3664] [glstub] Add functions needed to get glsl working Pity vulkan won't be so easy. --- include/QF/GL/qf_funcs_list.h | 2 +- tools/gl_stub/build | 2 +- tools/gl_stub/gl_stub.c | 5 + tools/gl_stub/gls_norm.c | 502 +++++++++++++++++++++++++++++ tools/gl_stub/gls_trace.c | 584 ++++++++++++++++++++++++++++++++++ 5 files changed, 1093 insertions(+), 2 deletions(-) diff --git a/include/QF/GL/qf_funcs_list.h b/include/QF/GL/qf_funcs_list.h index ebce38899..8c007e804 100644 --- a/include/QF/GL/qf_funcs_list.h +++ b/include/QF/GL/qf_funcs_list.h @@ -416,7 +416,7 @@ QFGL_NEED (void, glVertexPointer, (GLint size, GLenum type, GLsizei stride, cons QFGL_NEED (void, glViewport, (GLint x, GLint y, GLsizei width, GLsizei height)) // ATI Extensions -QFGL_WANT (void, glPNTrianglesiATI, (GLenum pname, GLint param)) +QFGL_WANT (void, glPNTrianglesiATI, (GLint x, GLint y)) #ifdef UNDEF_QFGL_DONT_NEED #undef QFGL_DONT_NEED diff --git a/tools/gl_stub/build b/tools/gl_stub/build index 113879f94..9b31d562e 100755 --- a/tools/gl_stub/build +++ b/tools/gl_stub/build @@ -1,4 +1,4 @@ #! /bin/sh -gcc -o GLstub.so -g -fPIC -shared -O3 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations gl_stub.c gls_norm.c gls_trace.c +gcc -o GLstub.so -I../../include -g -fPIC -shared -O3 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations gl_stub.c gls_norm.c gls_trace.c -Wall -Werror #gcc -o GLstub.so -g -fPIC -shared gl_stub.c gls_norm.c gls_trace.c diff --git a/tools/gl_stub/gl_stub.c b/tools/gl_stub/gl_stub.c index 24f123708..87ff057c3 100644 --- a/tools/gl_stub/gl_stub.c +++ b/tools/gl_stub/gl_stub.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -8,6 +9,7 @@ #include "QF/GL/defines.h" #include "QF/GL/extensions.h" #include "QF/GL/types.h" +#include "QF/GLSL/types.h" #include "QF/hash.h" @@ -28,6 +30,7 @@ ret GLAPIENTRY norm_##name args; #define QFGL_NEED(ret, name, args) \ ret GLAPIENTRY norm_##name args; #include "QF/GL/qf_funcs_list.h" +#include "QF/GLSL/qf_funcs_list.h" #undef QFGL_NEED #undef QFGL_WANT @@ -36,6 +39,7 @@ ret GLAPIENTRY trace_##name args; #define QFGL_NEED(ret, name, args) \ ret GLAPIENTRY trace_##name args; #include "QF/GL/qf_funcs_list.h" +#include "QF/GLSL/qf_funcs_list.h" #undef QFGL_NEED #undef QFGL_WANT @@ -53,6 +57,7 @@ static gl_stub_t gl_stub_funcs[] = { #define QFGL_NEED(ret, name, args) \ {#name, norm_##name, trace_##name}, #include "QF/GL/qf_funcs_list.h" +#include "QF/GLSL/qf_funcs_list.h" #undef QFGL_NEED #undef QFGL_WANT }; diff --git a/tools/gl_stub/gls_norm.c b/tools/gl_stub/gls_norm.c index 5942ffe9a..3fe4c4c67 100644 --- a/tools/gl_stub/gls_norm.c +++ b/tools/gl_stub/gls_norm.c @@ -5,15 +5,35 @@ #include "QF/GL/defines.h" #include "QF/GL/types.h" +#include "QF/GLSL/types.h" typedef struct __GLXcontextRec *GLXContext; typedef XID GLXDrawable; +#define QFGL_DONT_NEED(ret, func, params) QFGL_NEED(ret, func, params) + +#undef QFGL_WANT +#undef QFGL_NEED + +#define QFGL_WANT(ret, name, args) \ +ret GLAPIENTRY norm_##name args; +#define QFGL_NEED(ret, name, args) \ +ret GLAPIENTRY norm_##name args; +#include "QF/GL/qf_funcs_list.h" +#include "QF/GLSL/qf_funcs_list.h" +#undef QFGL_NEED +#undef QFGL_WANT + void norm_glAccum (GLenum op, GLfloat value) { } +void +norm_glActiveTexture (GLenum texture) +{ +} + void norm_glAlphaFunc (GLenum func, GLclampf ref) { @@ -31,11 +51,36 @@ norm_glArrayElement (GLint i) { } +void +norm_glAttachShader (GLuint program, GLuint shader) +{ +} + void norm_glBegin (GLenum mode) { } +void +norm_glBindAttribLocation (GLuint program, GLuint index, const GLchar* name) +{ +} + +void +norm_glBindBuffer (GLenum target, GLuint buffer) +{ +} + +void +norm_glBindFramebuffer (GLenum target, GLuint framebuffer) +{ +} + +void +norm_glBindRenderbuffer (GLenum target, GLuint renderbuffer) +{ +} + void norm_glBindTexture (GLenum target, GLuint texture) { @@ -57,11 +102,31 @@ norm_glBlendEquation (GLenum mode) { } +void +norm_glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) +{ +} + void norm_glBlendFunc (GLenum sfactor, GLenum dfactor) { } +void +norm_glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ +} + +void +norm_glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +{ +} + +void +norm_glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) +{ +} + void norm_glCallList (GLuint list) { @@ -72,6 +137,443 @@ norm_glCallLists (GLsizei n, GLenum type, const GLvoid * lists) { } +GLenum +norm_glCheckFramebufferStatus (GLenum target) +{ + return 0x8CD5; +} + +void +norm_glClearDepthf (GLclampf depth) +{ +} + +void +norm_glCompileShader (GLuint shader) +{ +} + +void +norm_glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) +{ +} + +void +norm_glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) +{ +} + +GLuint +norm_glCreateProgram (void) +{ + static int program; + return ++program; +} + +GLuint +norm_glCreateShader (GLenum type) +{ + static int shader; + return ++shader; +} + +void +norm_glDeleteBuffers (GLsizei n, const GLuint* buffers) +{ +} + +void +norm_glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) +{ +} + +void +norm_glDeleteProgram (GLuint program) +{ +} + +void +norm_glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers) +{ +} + +void +norm_glDeleteShader (GLuint shader) +{ +} + +void +norm_glDepthRangef (GLclampf zNear, GLclampf zFar) +{ +} + +void +norm_glDetachShader (GLuint program, GLuint shader) +{ +} + +void +norm_glDisableVertexAttribArray (GLuint index) +{ +} + +void +norm_glEnableVertexAttribArray (GLuint index) +{ +} + +void +norm_glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ +} + +void +norm_glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ +} + +void +norm_glGenBuffers (GLsizei n, GLuint* buffers) +{ +} + +void +norm_glGenFramebuffers (GLsizei n, GLuint* framebuffers) +{ +} + +void +norm_glGenRenderbuffers (GLsizei n, GLuint* renderbuffers) +{ +} + +void +norm_glGenerateMipmap (GLenum target) +{ +} + +void +norm_glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) +{ +} + +void +norm_glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) +{ +} + +void +norm_glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ +} + +int +norm_glGetAttribLocation (GLuint program, const GLchar* name) +{ + return 0; +} + +void +norm_glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params) +{ +} + +void +norm_glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ +} + +void +norm_glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) +{ +} + +void +norm_glGetProgramiv (GLuint program, GLenum pname, GLint* params) +{ +} + +void +norm_glGetRenderbufferParameteriv (GLuint shader, GLenum pname, GLint* params) +{ +} + +void +norm_glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) +{ +} + +void +norm_glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ +} + +void +norm_glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) +{ +} + +void +norm_glGetShaderiv (GLuint shader, GLenum pname, GLint* params) +{ +} + +int +norm_glGetUniformLocation (GLuint program, const GLchar* name) +{ + return 0; +} + +void +norm_glGetUniformfv (GLuint program, GLint location, GLfloat* params) +{ +} + +void +norm_glGetUniformiv (GLuint program, GLint location, GLint* params) +{ +} + +void +norm_glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer) +{ +} + +void +norm_glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params) +{ +} + +void +norm_glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params) +{ +} + +GLboolean +norm_glIsBuffer (GLuint buffer) +{ + return 0; +} + +GLboolean +norm_glIsFramebuffer (GLuint framebuffer) +{ + return 0; +} + +GLboolean +norm_glIsProgram (GLuint program) +{ + return 0; +} + +GLboolean +norm_glIsRenderbuffer (GLuint renderbuffer) +{ + return 0; +} + +GLboolean +norm_glIsShader (GLuint shader) +{ + return 0; +} + +void +norm_glLinkProgram (GLuint program) +{ +} + +void +norm_glReleaseShaderCompiler (void) +{ +} + +void +norm_glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ +} + +void +norm_glSampleCoverage (GLclampf value, GLboolean invert) +{ +} + +void +norm_glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) +{ +} + +void +norm_glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length) +{ +} + +void +norm_glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) +{ +} + +void +norm_glStencilMaskSeparate (GLenum face, GLuint mask) +{ +} + +void +norm_glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ +} + +void +norm_glUniform1f (GLint location, GLfloat x) +{ +} + +void +norm_glUniform1fv (GLint location, GLsizei count, const GLfloat* v) +{ +} + +void +norm_glUniform1i (GLint location, GLint x) +{ +} + +void +norm_glUniform1iv (GLint location, GLsizei count, const GLint* v) +{ +} + +void +norm_glUniform2f (GLint location, GLfloat x, GLfloat y) +{ +} + +void +norm_glUniform2fv (GLint location, GLsizei count, const GLfloat* v) +{ +} + +void +norm_glUniform2i (GLint location, GLint x, GLint y) +{ +} + +void +norm_glUniform2iv (GLint location, GLsizei count, const GLint* v) +{ +} + +void +norm_glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) +{ +} + +void +norm_glUniform3fv (GLint location, GLsizei count, const GLfloat* v) +{ +} + +void +norm_glUniform3i (GLint location, GLint x, GLint y, GLint z) +{ +} + +void +norm_glUniform3iv (GLint location, GLsizei count, const GLint* v) +{ +} + +void +norm_glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ +} + +void +norm_glUniform4fv (GLint location, GLsizei count, const GLfloat* v) +{ +} + +void +norm_glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w) +{ +} + +void +norm_glUniform4iv (GLint location, GLsizei count, const GLint* v) +{ +} + +void +norm_glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +} + +void +norm_glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +} + +void +norm_glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ +} + +void +norm_glUseProgram (GLuint program) +{ +} + +void +norm_glValidateProgram (GLuint program) +{ +} + +void +norm_glVertexAttrib1f (GLuint indx, GLfloat x) +{ +} + +void +norm_glVertexAttrib1fv (GLuint indx, const GLfloat* values) +{ +} + +void +norm_glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) +{ +} + +void +norm_glVertexAttrib2fv (GLuint indx, const GLfloat* values) +{ +} + +void +norm_glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ +} + +void +norm_glVertexAttrib3fv (GLuint indx, const GLfloat* values) +{ +} + +void +norm_glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ +} + +void +norm_glVertexAttrib4fv (GLuint indx, const GLfloat* values) +{ +} + +void +norm_glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +{ +} + void norm_glClear (GLbitfield mask) { diff --git a/tools/gl_stub/gls_trace.c b/tools/gl_stub/gls_trace.c index 6ca666362..c34f69db9 100644 --- a/tools/gl_stub/gls_trace.c +++ b/tools/gl_stub/gls_trace.c @@ -5,6 +5,7 @@ #include "QF/GL/defines.h" #include "QF/GL/types.h" +#include "QF/GLSL/types.h" typedef struct __GLXcontextRec *GLXContext; typedef XID GLXDrawable; @@ -19,6 +20,12 @@ trace_glAccum (GLenum op, GLfloat value) TRACE; } +void +trace_glActiveTexture (GLenum texture) +{ + TRACE; +} + void trace_glAlphaFunc (GLenum func, GLclampf ref) { @@ -39,12 +46,42 @@ trace_glArrayElement (GLint i) TRACE; } +void +trace_glAttachShader (GLuint program, GLuint shader) +{ + TRACE; +} + void trace_glBegin (GLenum mode) { TRACE; } +void +trace_glBindAttribLocation (GLuint program, GLuint index, const GLchar* name) +{ + TRACE; +} + +void +trace_glBindBuffer (GLenum target, GLuint buffer) +{ + TRACE; +} + +void +trace_glBindFramebuffer (GLenum target, GLuint framebuffer) +{ + TRACE; +} + +void +trace_glBindRenderbuffer (GLenum target, GLuint renderbuffer) +{ + TRACE; +} + void trace_glBindTexture (GLenum target, GLuint texture) { @@ -70,12 +107,36 @@ trace_glBlendEquation (GLenum mode) TRACE; } +void +trace_glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) +{ + TRACE; +} + void trace_glBlendFunc (GLenum sfactor, GLenum dfactor) { TRACE; } +void +trace_glBlendFuncSeparate (GLenum sfactor, GLenum dfactor) +{ + TRACE; +} + +void +trace_glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +{ + TRACE; +} + +void +trace_glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) +{ + TRACE; +} + void trace_glCallList (GLuint list) { @@ -88,6 +149,528 @@ trace_glCallLists (GLsizei n, GLenum type, const GLvoid * lists) TRACE; } +GLenum +trace_glCheckFramebufferStatus (GLenum target) +{ + TRACE; + return 0x8CD5; +} + +void +trace_glClearDepthf (GLclampf depth) +{ + TRACE; +} + +void +trace_glCompileShader (GLuint shader) +{ + TRACE; +} + +void +trace_glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) +{ + TRACE; +} + +void +trace_glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) +{ + TRACE; +} + +GLuint +trace_glCreateProgram (void) +{ + static int program; + TRACE; + return ++program; +} + +GLuint +trace_glCreateShader (GLenum type) +{ + static int shader; + TRACE; + return ++shader; +} + +void +trace_glDeleteBuffers (GLsizei n, const GLuint* buffers) +{ + TRACE; +} + +void +trace_glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) +{ + TRACE; +} + +void +trace_glDeleteProgram (GLuint program) +{ + TRACE; +} + +void +trace_glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers) +{ + TRACE; +} + +void +trace_glDeleteShader (GLuint shader) +{ + TRACE; +} + +void +trace_glDepthRangef (GLclampf zNear, GLclampf zFar) +{ + TRACE; +} + +void +trace_glDetachShader (GLuint program, GLuint shader) +{ + TRACE; +} + +void +trace_glDisableVertexAttribArray (GLuint index) +{ + TRACE; +} + +void +trace_glEnableVertexAttribArray (GLuint index) +{ + TRACE; +} + +void +trace_glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + TRACE; +} + +void +trace_glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + TRACE; +} + +void +trace_glGenBuffers (GLsizei n, GLuint* buffers) +{ + TRACE; +} + +void +trace_glGenFramebuffers (GLsizei n, GLuint* framebuffers) +{ + TRACE; +} + +void +trace_glGenRenderbuffers (GLsizei n, GLuint* renderbuffers) +{ + TRACE; +} + +void +trace_glGenerateMipmap (GLenum target) +{ + TRACE; +} + +void +trace_glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) +{ + TRACE; +} + +void +trace_glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) +{ + TRACE; +} + +void +trace_glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) +{ + TRACE; +} + +int +trace_glGetAttribLocation (GLuint program, const GLchar* name) +{ + TRACE; + return 0; +} + +void +trace_glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params) +{ + TRACE; +} + +void +trace_glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ + TRACE; +} + +void +trace_glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) +{ + TRACE; +} + +void +trace_glGetProgramiv (GLuint program, GLenum pname, GLint* params) +{ + TRACE; +} + +void +trace_glGetRenderbufferParameteriv (GLuint shader, GLenum pname, GLint* params) +{ + TRACE; +} + +void +trace_glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) +{ + TRACE; +} + +void +trace_glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) +{ + TRACE; +} + +void +trace_glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) +{ + TRACE; +} + +void +trace_glGetShaderiv (GLuint shader, GLenum pname, GLint* params) +{ + TRACE; +} + +int +trace_glGetUniformLocation (GLuint program, const GLchar* name) +{ + TRACE; + return 0; +} + +void +trace_glGetUniformfv (GLuint program, GLint location, GLfloat* params) +{ + TRACE; +} + +void +trace_glGetUniformiv (GLuint program, GLint location, GLint* params) +{ + TRACE; +} + +void +trace_glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer) +{ + TRACE; +} + +void +trace_glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params) +{ + TRACE; +} + +void +trace_glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params) +{ + TRACE; +} + +GLboolean +trace_glIsBuffer (GLuint buffer) +{ + TRACE; + return 0; +} + +GLboolean +trace_glIsFramebuffer (GLuint framebuffer) +{ + TRACE; + return 0; +} + +GLboolean +trace_glIsProgram (GLuint program) +{ + TRACE; + return 0; +} + +GLboolean +trace_glIsRenderbuffer (GLuint renderbuffer) +{ + TRACE; + return 0; +} + +GLboolean +trace_glIsShader (GLuint shader) +{ + TRACE; + return 0; +} + +void +trace_glLinkProgram (GLuint program) +{ + TRACE; +} + +void +trace_glReleaseShaderCompiler (void) +{ + TRACE; +} + +void +trace_glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + TRACE; +} + +void +trace_glSampleCoverage (GLclampf value, GLboolean invert) +{ + TRACE; +} + +void +trace_glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) +{ + TRACE; +} + +void +trace_glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length) +{ + TRACE; +} + +void +trace_glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) +{ + TRACE; +} + +void +trace_glStencilMaskSeparate (GLenum face, GLuint mask) +{ + TRACE; +} + +void +trace_glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + TRACE; +} + +void +trace_glUniform1f (GLint location, GLfloat x) +{ + TRACE; +} + +void +trace_glUniform1fv (GLint location, GLsizei count, const GLfloat* v) +{ + TRACE; +} + +void +trace_glUniform1i (GLint location, GLint x) +{ + TRACE; +} + +void +trace_glUniform1iv (GLint location, GLsizei count, const GLint* v) +{ + TRACE; +} + +void +trace_glUniform2f (GLint location, GLfloat x, GLfloat y) +{ + TRACE; +} + +void +trace_glUniform2fv (GLint location, GLsizei count, const GLfloat* v) +{ + TRACE; +} + +void +trace_glUniform2i (GLint location, GLint x, GLint y) +{ + TRACE; +} + +void +trace_glUniform2iv (GLint location, GLsizei count, const GLint* v) +{ + TRACE; +} + +void +trace_glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) +{ + TRACE; +} + +void +trace_glUniform3fv (GLint location, GLsizei count, const GLfloat* v) +{ + TRACE; +} + +void +trace_glUniform3i (GLint location, GLint x, GLint y, GLint z) +{ + TRACE; +} + +void +trace_glUniform3iv (GLint location, GLsizei count, const GLint* v) +{ + TRACE; +} + +void +trace_glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + TRACE; +} + +void +trace_glUniform4fv (GLint location, GLsizei count, const GLfloat* v) +{ + TRACE; +} + +void +trace_glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w) +{ + TRACE; +} + +void +trace_glUniform4iv (GLint location, GLsizei count, const GLint* v) +{ + TRACE; +} + +void +trace_glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + TRACE; +} + +void +trace_glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + TRACE; +} + +void +trace_glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + TRACE; +} + +void +trace_glUseProgram (GLuint program) +{ + TRACE; +} + +void +trace_glValidateProgram (GLuint program) +{ + TRACE; +} + +void +trace_glVertexAttrib1f (GLuint indx, GLfloat x) +{ + TRACE; +} + +void +trace_glVertexAttrib1fv (GLuint indx, const GLfloat* values) +{ + TRACE; +} + +void +trace_glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) +{ + TRACE; +} + +void +trace_glVertexAttrib2fv (GLuint indx, const GLfloat* values) +{ + TRACE; +} + +void +trace_glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) +{ + TRACE; +} + +void +trace_glVertexAttrib3fv (GLuint indx, const GLfloat* values) +{ + TRACE; +} + +void +trace_glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + TRACE; +} + +void +trace_glVertexAttrib4fv (GLuint indx, const GLfloat* values) +{ + TRACE; +} + +void +trace_glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +{ + TRACE; +} + void trace_glClear (GLbitfield mask) { @@ -2341,4 +2924,5 @@ trace_glViewport (GLint x, GLint y, GLsizei width, GLsizei height) void trace_glPNTrianglesiATI (GLint x, GLint y) { + TRACE; } From 41de8c9187f1a8eb29563f9409c61b05c4fa4ae7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jul 2021 14:25:51 +0900 Subject: [PATCH 1652/3664] [util] Cast swapped signed shorts in bspfile This fixes a bug when loading bsp29 files that resulted in leaf nodes having bogus bounding boxes if any coordinates were negative (and thus dynamic lights, and probably all sorts of other things) being broken. And it took me only 9 years to notice :P --- libs/util/bspfile.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libs/util/bspfile.c b/libs/util/bspfile.c index eb438c959..25263ce04 100644 --- a/libs/util/bspfile.c +++ b/libs/util/bspfile.c @@ -233,11 +233,11 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) dnode29_t *node29 = &bsp29->nodes[i]; node29->planenum = LittleLong (node2->planenum); for (j=0 ; j<3 ; j++) { - node29->mins[j] = LittleShort (node2->mins[j]); - node29->maxs[j] = LittleShort (node2->maxs[j]); + node29->mins[j] = LittleShort ((int16_t) node2->mins[j]); + node29->maxs[j] = LittleShort ((int16_t) node2->maxs[j]); } - node29->children[0] = (uint16_t) LittleShort (node2->children[0]); - node29->children[1] = (uint16_t) LittleShort (node2->children[1]); + node29->children[0] = LittleShort (node2->children[0]); + node29->children[1] = LittleShort (node2->children[1]); node29->firstface = LittleShort (node2->firstface); node29->numfaces = LittleShort (node2->numfaces); } @@ -248,8 +248,8 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) dleaf29_t *leaf29 = &bsp29->leafs[i]; leaf29->contents = LittleLong (leaf2->contents); for (j=0 ; j<3 ; j++) { - leaf29->mins[j] = LittleShort (leaf2->mins[j]); - leaf29->maxs[j] = LittleShort (leaf2->maxs[j]); + leaf29->mins[j] = LittleShort ((int16_t) leaf2->mins[j]); + leaf29->maxs[j] = LittleShort ((int16_t) leaf2->maxs[j]); } leaf29->firstmarksurface = LittleShort (leaf2->firstmarksurface); @@ -264,8 +264,8 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) const dclipnode_t *clipnode2 = &bsp2->clipnodes[i]; dclipnode29_t *clipnode29 = (dclipnode29_t *) &bsp29->clipnodes[i]; clipnode29->planenum = LittleLong (clipnode2->planenum); - clipnode29->children[0] = (uint16_t) LittleShort (clipnode2->children[0]); - clipnode29->children[1] = (uint16_t) LittleShort (clipnode2->children[1]); + clipnode29->children[0] = LittleShort (clipnode2->children[0]); + clipnode29->children[1] = LittleShort (clipnode2->children[1]); } // miptex @@ -402,8 +402,8 @@ swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, const dleaf29_t *leaf29 = &bsp29->leafs[i]; leaf2->contents = LittleLong (leaf29->contents); for (j=0 ; j<3 ; j++) { - leaf2->mins[j] = LittleShort (leaf29->mins[j]); - leaf2->maxs[j] = LittleShort (leaf29->maxs[j]); + leaf2->mins[j] = (int16_t) LittleShort (leaf29->mins[j]); + leaf2->maxs[j] = (int16_t) LittleShort (leaf29->maxs[j]); } leaf2->firstmarksurface = LittleShort (leaf29->firstmarksurface); @@ -418,8 +418,8 @@ swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, dclipnode_t *clipnode2 = &bsp2->clipnodes[i]; const dclipnode29_t *clipnode29 = &bsp29->clipnodes[i]; clipnode2->planenum = LittleLong (clipnode29->planenum); - clipnode2->children[0] = (uint16_t) LittleShort (clipnode29->children[0]); - clipnode2->children[1] = (uint16_t) LittleShort (clipnode29->children[1]); + clipnode2->children[0] = LittleShort (clipnode29->children[0]); + clipnode2->children[1] = LittleShort (clipnode29->children[1]); } // miptex From f1ac8f2460c7a661eb015044a731c6f25ce2efee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jul 2021 15:39:28 +0900 Subject: [PATCH 1653/3664] [renderer] Remove currententity from non-sw renderers Really needed only for vulkan, but removing currententity from gl and glsl made testing easier. --- include/QF/GL/qf_lightmap.h | 4 +- include/QF/GLSL/qf_alias.h | 3 +- include/QF/GLSL/qf_iqm.h | 3 +- include/QF/GLSL/qf_lightmap.h | 4 +- include/QF/GLSL/qf_sprite.h | 36 +++++++++++++ include/QF/Makemodule.am | 1 + include/QF/Vulkan/qf_bsp.h | 4 ++ include/r_local.h | 10 ++-- libs/video/renderer/gl/gl_lightmap.c | 36 +++++++------ libs/video/renderer/gl/gl_mod_alias.c | 24 +++++---- libs/video/renderer/gl/gl_mod_sprite.c | 8 +-- libs/video/renderer/gl/gl_rmain.c | 18 +++---- libs/video/renderer/gl/gl_rsurf.c | 63 +++++++++++++---------- libs/video/renderer/gl/namehack.h | 2 - libs/video/renderer/glsl/glsl_alias.c | 12 ++--- libs/video/renderer/glsl/glsl_bsp.c | 62 +++++++++++++--------- libs/video/renderer/glsl/glsl_iqm.c | 3 +- libs/video/renderer/glsl/glsl_lightmap.c | 16 +++--- libs/video/renderer/glsl/glsl_main.c | 10 ++-- libs/video/renderer/glsl/glsl_sprite.c | 35 +++++++------ libs/video/renderer/glsl/namehack.h | 1 - libs/video/renderer/r_alias.c | 20 +++---- libs/video/renderer/r_bsp.c | 4 +- libs/video/renderer/r_ent.c | 28 +++++----- libs/video/renderer/r_iqm.c | 7 +-- libs/video/renderer/r_main.c | 2 - libs/video/renderer/sw/d_surf.c | 2 +- libs/video/renderer/sw/sw_ralias.c | 37 ++++++------- libs/video/renderer/sw32/d_surf.c | 2 +- libs/video/renderer/sw32/sw32_ralias.c | 35 +++++++------ libs/video/renderer/vulkan/vulkan_alias.c | 5 +- libs/video/renderer/vulkan/vulkan_bsp.c | 28 +++++----- libs/video/renderer/vulkan/vulkan_main.c | 4 +- 33 files changed, 304 insertions(+), 225 deletions(-) create mode 100644 include/QF/GLSL/qf_sprite.h diff --git a/include/QF/GL/qf_lightmap.h b/include/QF/GL/qf_lightmap.h index e0a05d4dd..6125ea57e 100644 --- a/include/QF/GL/qf_lightmap.h +++ b/include/QF/GL/qf_lightmap.h @@ -50,6 +50,8 @@ void gl_lightmap_init (void); void GL_BuildLightmaps (struct model_s **models, int num_models); void R_BlendLightmaps (void); void R_CalcLightmaps (void); -extern void (*R_BuildLightMap) (mod_brush_t *brush, msurface_t *surf); +struct transform_s; +extern void (*gl_R_BuildLightMap) (const struct transform_s *transform, + mod_brush_t *brush, msurface_t *surf); #endif // __QF_GL_lightmap_h diff --git a/include/QF/GLSL/qf_alias.h b/include/QF/GLSL/qf_alias.h index 600d6be16..491207783 100644 --- a/include/QF/GLSL/qf_alias.h +++ b/include/QF/GLSL/qf_alias.h @@ -39,7 +39,8 @@ typedef struct aliasvrt_s { } aliasvrt_t; void glsl_R_InitAlias (void); -void glsl_R_DrawAlias (void); +struct entity_s; +void glsl_R_DrawAlias (struct entity_s *ent); void glsl_R_AliasBegin (void); void glsl_R_AliasEnd (void); diff --git a/include/QF/GLSL/qf_iqm.h b/include/QF/GLSL/qf_iqm.h index f37ac5f21..b8a1c41a1 100644 --- a/include/QF/GLSL/qf_iqm.h +++ b/include/QF/GLSL/qf_iqm.h @@ -40,7 +40,8 @@ typedef struct glsliqm_s { } glsliqm_t; void glsl_R_InitIQM (void); -void glsl_R_DrawIQM (void); +struct entity_s; +void glsl_R_DrawIQM (struct entity_s *ent); void glsl_R_IQMBegin (void); void glsl_R_IQMEnd (void); diff --git a/include/QF/GLSL/qf_lightmap.h b/include/QF/GLSL/qf_lightmap.h index 507eaeae6..e3442bab1 100644 --- a/include/QF/GLSL/qf_lightmap.h +++ b/include/QF/GLSL/qf_lightmap.h @@ -34,9 +34,11 @@ #define BLOCK_HEIGHT 64 void glsl_lightmap_init (void); +struct transform_s; void glsl_R_BuildLightmaps (struct model_s **models, int num_models); void glsl_R_CalcLightmaps (void); -extern void (*glsl_R_BuildLightMap) (mod_brush_t *brush, msurface_t *surf); +extern void (*glsl_R_BuildLightMap) (const struct transform_s *transform, + mod_brush_t *brush, msurface_t *surf); int glsl_R_LightmapTexture (void) __attribute__((pure)); void glsl_R_FlushLightmaps (void); diff --git a/include/QF/GLSL/qf_sprite.h b/include/QF/GLSL/qf_sprite.h new file mode 100644 index 000000000..af7817b1b --- /dev/null +++ b/include/QF/GLSL/qf_sprite.h @@ -0,0 +1,36 @@ +/* + qf_sprite.h + + GLSL specific sprite model stuff + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/7/22 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_GLSL_qf_sprite_h +#define __QF_GLSL_qf_sprite_h + +struct entity_s; +void glsl_R_DrawSprite (struct entity_s *ent); + +#endif//__QF_GLSL_qf_sprite_h diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 532422e06..4c6d20451 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -104,6 +104,7 @@ include_qf_glsl = \ include/QF/GLSL/qf_iqm.h \ include/QF/GLSL/qf_lightmap.h \ include/QF/GLSL/qf_particles.h \ + include/QF/GLSL/qf_sprite.h \ include/QF/GLSL/qf_textures.h \ include/QF/GLSL/qf_vid.h \ include/QF/GLSL/types.h diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index c9c4e4d90..19e317ded 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -113,6 +113,10 @@ typedef struct texchainset_s DARRAY_TYPE (vulktex_t *) texchainset_t; typedef struct bspctx_s { + struct entity_s *entity; + vec_t *transform; + float *color; + instsurf_t *waterchain; instsurf_t **waterchain_tail; instsurf_t *sky_chain; diff --git a/include/r_local.h b/include/r_local.h index ba8063561..c45ca74c6 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -152,7 +152,7 @@ void R_TransformPlane (plane_t *p, float *normal, float *dist); void R_TransformFrustum (void); void R_SetSkyFrame (void); void R_DrawSurfaceBlock (void); -texture_t *R_TextureAnimation (msurface_t *surf) __attribute__((pure)); +texture_t *R_TextureAnimation (const entity_t *entity, msurface_t *surf) __attribute__((pure)); void R_GenSkyTile (void *pdest); void R_SurfPatch (void); @@ -164,16 +164,16 @@ surf_t *R_GetSurf (void); void R_AliasClipAndProjectFinalVert (finalvert_t *fv, auxvert_t *av); void R_AliasDrawModel (alight_t *plighting); void R_IQMDrawModel (alight_t *plighting); -maliasskindesc_t *R_AliasGetSkindesc (int skinnum, aliashdr_t *hdr); -maliasframedesc_t *R_AliasGetFramedesc (int framenum, aliashdr_t *hdr); -float R_AliasGetLerpedFrames (entity_t *ent, aliashdr_t *hdr); +maliasskindesc_t *R_AliasGetSkindesc (animation_t *animation, int skinnum, aliashdr_t *hdr); +maliasframedesc_t *R_AliasGetFramedesc (animation_t *animation, aliashdr_t *hdr); +float R_AliasGetLerpedFrames (animation_t *animation, aliashdr_t *hdr); float R_IQMGetLerpedFrames (entity_t *ent, iqm_t *hdr); iqmframe_t *R_IQMBlendFrames (const iqm_t *iqm, int frame1, int frame2, float blend, int extra); iqmframe_t *R_IQMBlendPalette (const iqm_t *iqm, int frame1, int frame2, float blend, int extra, iqmblend_t *blend_palette, int palette_size); -float R_EntityBlend (entity_t *ent, int pose, float interval); +float R_EntityBlend (animation_t *animation, int pose, float interval); void R_BeginEdgeFrame (void); void R_ScanEdges (void); void D_DrawSurfaces (void); diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 4ff13a7a2..8456b5619 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -75,7 +75,8 @@ glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; static int lmshift = 7; -void (*gl_R_BuildLightMap) (mod_brush_t *brush, msurface_t *surf); +void (*gl_R_BuildLightMap) (const transform_t *transform, mod_brush_t *brush, + msurface_t *surf); extern void gl_multitexture_f (cvar_t *var); @@ -108,7 +109,7 @@ R_RecursiveLightUpdate (mnode_t *node) } */ static inline void -R_AddDynamicLights_1 (msurface_t *surf) +R_AddDynamicLights_1 (const transform_t *transform, msurface_t *surf) { float dist; unsigned int maxdist, maxdist2, maxdist3; @@ -124,9 +125,9 @@ R_AddDynamicLights_1 (msurface_t *surf) smax_bytes = smax * gl_internalformat; tmax = (surf->extents[1] >> 4) + 1; - if (currententity->transform) { + if (transform) { //FIXME give world entity a transform - entorigin = Transform_GetWorldPosition (currententity->transform); + entorigin = Transform_GetWorldPosition (transform); } for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -179,7 +180,7 @@ R_AddDynamicLights_1 (msurface_t *surf) } static inline void -R_AddDynamicLights_3 (msurface_t *surf) +R_AddDynamicLights_3 (const transform_t *transform, msurface_t *surf) { float dist; unsigned int maxdist, maxdist2, maxdist3; @@ -195,8 +196,8 @@ R_AddDynamicLights_3 (msurface_t *surf) smax_bytes = smax * gl_internalformat; tmax = (surf->extents[1] >> 4) + 1; - if (currententity->transform) { - entorigin = Transform_GetWorldPosition (currententity->transform); + if (transform) { + entorigin = Transform_GetWorldPosition (transform); } for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -252,7 +253,8 @@ R_AddDynamicLights_3 (msurface_t *surf) } static void -R_BuildLightMap_1 (mod_brush_t *brush, msurface_t *surf) +R_BuildLightMap_1 (const transform_t *transform, mod_brush_t *brush, + msurface_t *surf) { byte *dest; int maps, size, stride, smax, tmax, i, j; @@ -291,7 +293,7 @@ R_BuildLightMap_1 (mod_brush_t *brush, msurface_t *surf) } // add all the dynamic lights if (surf->dlightframe == r_framecount) - R_AddDynamicLights_1 (surf); + R_AddDynamicLights_1 (transform, surf); store: // bound and shift @@ -312,7 +314,8 @@ R_BuildLightMap_1 (mod_brush_t *brush, msurface_t *surf) } static void -R_BuildLightMap_3 (mod_brush_t *brush, msurface_t *surf) +R_BuildLightMap_3 (const transform_t *transform, mod_brush_t *brush, + msurface_t *surf) { byte *dest; int maps, size, stride, smax, tmax, i, j; @@ -353,7 +356,7 @@ R_BuildLightMap_3 (mod_brush_t *brush, msurface_t *surf) } // add all the dynamic lights if (surf->dlightframe == r_framecount) - R_AddDynamicLights_3 (surf); + R_AddDynamicLights_3 (transform, surf); store: // bound and shift @@ -377,7 +380,8 @@ R_BuildLightMap_3 (mod_brush_t *brush, msurface_t *surf) } static void -R_BuildLightMap_4 (mod_brush_t *brush, msurface_t *surf) +R_BuildLightMap_4 (const transform_t *transform, mod_brush_t *brush, + msurface_t *surf) { byte *dest; int maps, size, smax, tmax, i, j, stride; @@ -418,7 +422,7 @@ R_BuildLightMap_4 (mod_brush_t *brush, msurface_t *surf) } // add all the dynamic lights if (surf->dlightframe == r_framecount) - R_AddDynamicLights_3 (surf); + R_AddDynamicLights_3 (transform, surf); store: // bound and shift @@ -614,7 +618,7 @@ gl_overbright_f (cvar_t *var) gl_lightmap_rectchange[num].w = BLOCK_WIDTH; gl_lightmap_rectchange[num].h = BLOCK_HEIGHT; - gl_R_BuildLightMap (brush, surf); + gl_R_BuildLightMap (0, brush, surf); } } @@ -631,7 +635,7 @@ gl_overbright_f (cvar_t *var) gl_lightmap_rectchange[num].w = BLOCK_WIDTH; gl_lightmap_rectchange[num].h = BLOCK_HEIGHT; - gl_R_BuildLightMap (brush, surf); + gl_R_BuildLightMap (0, brush, surf); } } @@ -692,7 +696,7 @@ GL_CreateSurfaceLightmap (mod_brush_t *brush, msurface_t *surf) surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t); - gl_R_BuildLightMap (brush, surf); + gl_R_BuildLightMap (0, brush, surf); } /* diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 3f96b4364..03d403fa9 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -188,7 +188,8 @@ GL_DrawAliasFrameMulti (vert_order_t *vo) Standard shadow drawing (triangles version) */ static void -GL_DrawAliasShadowTri (const aliashdr_t *paliashdr, const vert_order_t *vo) +GL_DrawAliasShadowTri (const transform_t *transform, + const aliashdr_t *paliashdr, const vert_order_t *vo) { int count = vo->count; const blended_vert_t *verts = vo->verts; @@ -198,7 +199,7 @@ GL_DrawAliasShadowTri (const aliashdr_t *paliashdr, const vert_order_t *vo) const vec_t *scale_origin = paliashdr->mdl.scale_origin; vec4f_t entorigin; - entorigin = Transform_GetWorldPosition (currententity->transform); + entorigin = Transform_GetWorldPosition (transform); lheight = entorigin[2] - lightspot[2]; height = -lheight + 1.0; @@ -227,7 +228,8 @@ GL_DrawAliasShadowTri (const aliashdr_t *paliashdr, const vert_order_t *vo) Standard shadow drawing */ static void -GL_DrawAliasShadow (const aliashdr_t *paliashdr, const vert_order_t *vo) +GL_DrawAliasShadow (const transform_t *transform, const aliashdr_t *paliashdr, + const vert_order_t *vo) { float height, lheight; int count; @@ -236,7 +238,7 @@ GL_DrawAliasShadow (const aliashdr_t *paliashdr, const vert_order_t *vo) const blended_vert_t *verts = vo->verts; vec4f_t entorigin; - entorigin = Transform_GetWorldPosition (currententity->transform); + entorigin = Transform_GetWorldPosition (transform); lheight = entorigin[2] - lightspot[2]; height = -lheight + 1.0; @@ -276,13 +278,14 @@ GL_DrawAliasShadow (const aliashdr_t *paliashdr, const vert_order_t *vo) static inline vert_order_t * GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t *e) { + animation_t *animation = &e->animation; float blend; int count, i; trivertx16_t *verts; vert_order_t *vo; blended_vert_t *vo_v; - blend = R_AliasGetLerpedFrames (e, paliashdr); + blend = R_AliasGetLerpedFrames (animation, paliashdr); verts = (trivertx16_t *) ((byte *) paliashdr + paliashdr->posedata); @@ -341,13 +344,14 @@ GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t *e) static inline vert_order_t * GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t *e) { + animation_t *animation = &e->animation; float blend; int count, i; trivertx_t *verts; vert_order_t *vo; blended_vert_t *vo_v; - blend = R_AliasGetLerpedFrames (e, paliashdr); + blend = R_AliasGetLerpedFrames (animation, paliashdr); verts = (trivertx_t *) ((byte *) paliashdr + paliashdr->posedata); @@ -566,8 +570,10 @@ gl_R_DrawAliasModel (entity_t *e) } } else { maliasskindesc_t *skindesc; + animation_t *animation = &e->animation; - skindesc = R_AliasGetSkindesc (e->renderer.skinnum, paliashdr); + skindesc = R_AliasGetSkindesc (animation, e->renderer.skinnum, + paliashdr); texture = skindesc->texnum; if (gl_fb_models->int_val && !is_fullbright) { fb_texture = skindesc->fb_texnum; @@ -718,9 +724,9 @@ gl_R_DrawAliasModel (entity_t *e) vec = m3vmulf (shadow_mat, vec); VectorCopy (vec, shadevector); if (vo->tex_coord) - GL_DrawAliasShadowTri (paliashdr, vo); + GL_DrawAliasShadowTri (e->transform, paliashdr, vo); else - GL_DrawAliasShadow (paliashdr, vo); + GL_DrawAliasShadow (e->transform, paliashdr, vo); qfglDepthMask (GL_TRUE); qfglEnable (GL_TEXTURE_2D); diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index 56543ef25..2aa41ac5e 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -58,7 +58,7 @@ void (*gl_R_DrawSpriteModel) (struct entity_s *ent); static mspriteframe_t * -R_GetSpriteFrame (entity_t *currententity) +R_GetSpriteFrame (entity_t *ent) { float fullinterval, targettime, time; float *pintervals; @@ -67,8 +67,8 @@ R_GetSpriteFrame (entity_t *currententity) mspriteframe_t *pspriteframe; mspritegroup_t *pspritegroup; - psprite = currententity->renderer.model->cache.data; - frame = currententity->animation.frame; + psprite = ent->renderer.model->cache.data; + frame = ent->animation.frame; if ((frame >= psprite->numframes) || (frame < 0)) { Sys_MaskPrintf (SYS_dev, "R_DrawSprite: no such frame %d\n", frame); @@ -83,7 +83,7 @@ R_GetSpriteFrame (entity_t *currententity) numframes = pspritegroup->numframes; fullinterval = pintervals[numframes - 1]; - time = vr_data.realtime + currententity->animation.syncbase; + time = vr_data.realtime + ent->animation.syncbase; // when loading in Mod_LoadSpriteGroup, we guaranteed all interval // values are positive, so we don't have to worry about division by 0 diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 3d5502782..617eb9206 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -221,9 +221,7 @@ R_DrawEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { if (ent->renderer.model->type != mod_alias) continue; - currententity = ent; - - gl_R_DrawAliasModel (currententity); + gl_R_DrawAliasModel (ent); } qfglColor3ubv (color_white); @@ -253,9 +251,7 @@ R_DrawEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { if (ent->renderer.model->type != mod_iqm) continue; - currententity = ent; - - gl_R_DrawIQMModel (currententity); + gl_R_DrawIQMModel (ent); } qfglColor3ubv (color_white); @@ -266,9 +262,7 @@ R_DrawEntitiesOnList (void) for (ent = r_ent_queue; ent; ent = ent->next) { if (ent->renderer.model->type != mod_sprite) continue; - currententity = ent; - - R_DrawSpriteModel (currententity); + R_DrawSpriteModel (ent); } qfglDisable (GL_ALPHA_TEST); } @@ -276,12 +270,12 @@ R_DrawEntitiesOnList (void) static void R_DrawViewModel (void) { - currententity = vr_data.view_model; + entity_t *ent = vr_data.view_model; if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val || gl_envmap || !r_drawentities->int_val - || !currententity->renderer.model) + || !ent->renderer.model) return; // hack the depth range to prevent view model from poking into walls @@ -305,7 +299,7 @@ R_DrawViewModel (void) qglActiveTexture (gl_mtex_enum + 0); } - gl_R_DrawAliasModel (currententity); + gl_R_DrawAliasModel (ent); qfglColor3ubv (color_white); if (gl_mtex_active_tmus >= 2) { // FIXME: Ugly, but faster than cleaning diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index f031dd9b0..e3c4187d1 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -65,6 +65,13 @@ static instsurf_t **waterchain_tail = &waterchain; static instsurf_t *sky_chain; static instsurf_t **sky_chain_tail; +typedef struct glbspctx_s { + mod_brush_t *brush; + entity_t *entity; + vec_t *transform; + float *color; +} glbspctx_t; + #define CHAIN_SURF_F2B(surf,chain) \ ({ \ instsurf_t *inst = (surf)->instsurf; \ @@ -270,7 +277,7 @@ R_RenderBrushPoly_1 (msurface_t *surf) } static inline void -R_AddToLightmapChain (mod_brush_t *brush, msurface_t *surf, instsurf_t *sc) +R_AddToLightmapChain (glbspctx_t *bctx, msurface_t *surf, instsurf_t *sc) { int maps, smax, tmax; glRect_t *theRect; @@ -305,7 +312,7 @@ R_AddToLightmapChain (mod_brush_t *brush, msurface_t *surf, instsurf_t *sc) theRect->w = (surf->light_s - theRect->l) + smax; if ((theRect->h + theRect->t) < (surf->light_t + tmax)) theRect->h = (surf->light_t - theRect->t) + tmax; - gl_R_BuildLightMap (brush, surf); + gl_R_BuildLightMap (bctx->entity->transform, bctx->brush, surf); } } } @@ -489,8 +496,7 @@ clear_texture_chains (void) } static inline void -chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, - float *color) +chain_surface (glbspctx_t *bctx, msurface_t *surf) { instsurf_t *sc; @@ -505,14 +511,14 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, if (!surf->texinfo->texture->anim_total) tx = surf->texinfo->texture; else - tx = R_TextureAnimation (surf); + tx = R_TextureAnimation (bctx->entity, surf); tex = tx->render; sc = CHAIN_SURF_F2B (surf, tex->tex_chain); - R_AddToLightmapChain (brush, surf, sc); + R_AddToLightmapChain (bctx, surf, sc); } - sc->transform = transform; - sc->color = color; + sc->transform = bctx->transform; + sc->color = bctx->color; } void @@ -521,15 +527,18 @@ gl_R_DrawBrushModel (entity_t *e) float dot, radius; int i; unsigned int k; - model_t *model; msurface_t *surf; qboolean rotated; vec3_t mins, maxs; - mod_brush_t *brush; mat4f_t worldMatrix; - - model = e->renderer.model; - brush = &model->brush; + model_t *model = e->renderer.model; + mod_brush_t *brush = &model->brush; + glbspctx_t bspctx = { + brush, + e, + e->renderer.full_transform, + e->renderer.colormod, + }; Transform_GetWorldMatrix (e->transform, worldMatrix); if (worldMatrix[0][0] != 1 || worldMatrix[1][1] != 1 @@ -598,8 +607,7 @@ gl_R_DrawBrushModel (entity_t *e) // draw the polygon if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (brush, surf, e->renderer.full_transform, - e->renderer.colormod); + chain_surface (&bspctx, surf); } } } @@ -626,7 +634,7 @@ get_side (mnode_t *node) } static inline void -visit_node (mod_brush_t *brush, mnode_t *node, int side) +visit_node (glbspctx_t *bctx, mnode_t *node, int side) { int c; msurface_t *surf; @@ -635,7 +643,7 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side) side = (~side + 1) & SURF_PLANEBACK; // draw stuff if ((c = node->numsurfaces)) { - surf = brush->surfaces + node->firstsurface; + surf = bctx->brush->surfaces + node->firstsurface; for (; c; c--, surf++) { if (surf->visframe != r_visframecount) continue; @@ -644,7 +652,7 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side) if (side ^ (surf->flags & SURF_PLANEBACK)) continue; // wrong side - chain_surface (brush, surf, 0, 0); + chain_surface (bctx, surf); } } } @@ -662,12 +670,13 @@ test_node (mnode_t *node) } static void -R_VisitWorldNodes (mod_brush_t *brush) +R_VisitWorldNodes (glbspctx_t *bctx) { typedef struct { mnode_t *node; int side; } rstack_t; + mod_brush_t *brush = bctx->brush; rstack_t *node_ptr; rstack_t *node_stack; mnode_t *node; @@ -692,7 +701,7 @@ R_VisitWorldNodes (mod_brush_t *brush) } if (front->contents < 0 && front->contents != CONTENTS_SOLID) visit_leaf ((mleaf_t *) front); - visit_node (brush, node, side); + visit_node (bctx, node, side); node = node->children[!side]; } if (node->contents < 0 && node->contents != CONTENTS_SOLID) @@ -701,7 +710,7 @@ R_VisitWorldNodes (mod_brush_t *brush) node_ptr--; node = node_ptr->node; side = node_ptr->side; - visit_node (brush, node, side); + visit_node (bctx, node, side); node = node->children[!side]; continue; } @@ -715,30 +724,30 @@ void gl_R_DrawWorld (void) { entity_t worldent; + glbspctx_t bctx = { }; memset (&worldent, 0, sizeof (worldent)); worldent.renderer.model = r_worldentity.renderer.model; VectorCopy (r_refdef.viewposition, modelorg); - currententity = &worldent; - sky_chain = 0; sky_chain_tail = &sky_chain; if (!gl_sky_clip->int_val) { gl_R_DrawSky (); } - R_VisitWorldNodes (&r_worldentity.renderer.model->brush); + bctx.brush = &worldent.renderer.model->brush; + bctx.entity = &r_worldentity; + + R_VisitWorldNodes (&bctx); if (r_drawentities->int_val) { entity_t *ent; for (ent = r_ent_queue; ent; ent = ent->next) { if (ent->renderer.model->type != mod_brush) { continue; } - currententity = ent; - - gl_R_DrawBrushModel (currententity); + gl_R_DrawBrushModel (ent); } } diff --git a/libs/video/renderer/gl/namehack.h b/libs/video/renderer/gl/namehack.h index e33d0aef6..84f48faa6 100644 --- a/libs/video/renderer/gl/namehack.h +++ b/libs/video/renderer/gl/namehack.h @@ -33,7 +33,6 @@ #define Fog_Update gl_Fog_Update #define R_AddTexture gl_R_AddTexture #define R_BlendLightmaps gl_R_BlendLightmaps -#define R_BuildLightMap gl_R_BuildLightMap #define R_CalcLightmaps gl_R_CalcLightmaps #define R_ClearParticles gl_R_ClearParticles #define R_ClearState gl_R_ClearState @@ -88,7 +87,6 @@ #undef Fog_Update #undef R_AddTexture #undef R_BlendLightmaps -#undef R_BuildLightMap #undef R_CalcLightmaps #undef R_ClearParticles #undef R_ClearState diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 8ea3c3675..bb8e2a541 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -210,7 +210,7 @@ set_arrays (const shaderparam_t *vert, const shaderparam_t *norm, } //#define TETRAHEDRON void -glsl_R_DrawAlias (void) +glsl_R_DrawAlias (entity_t *ent) { #ifdef TETRAHEDRON static aliasvrt_t debug_verts[] = { @@ -232,7 +232,7 @@ glsl_R_DrawAlias (void) float shadelight; float skin_size[2]; float blend; - entity_t *ent = currententity; + animation_t *animation = &ent->animation; model_t *model = ent->renderer.model; aliashdr_t *hdr; vec_t norm_mat[9]; @@ -272,13 +272,13 @@ glsl_R_DrawAlias (void) skin_tex = skin->texnum; } else { maliasskindesc_t *skindesc; - skindesc = R_AliasGetSkindesc (ent->renderer.skinnum, hdr); + skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr); skin_tex = skindesc->texnum; } - blend = R_AliasGetLerpedFrames (ent, hdr); + blend = R_AliasGetLerpedFrames (animation, hdr); - pose1 += ent->animation.pose1 * hdr->poseverts; - pose2 += ent->animation.pose2 * hdr->poseverts; + pose1 += animation->pose1 * hdr->poseverts; + pose2 += animation->pose2 * hdr->poseverts; skin_size[0] = hdr->mdl.skinwidth; skin_size[1] = hdr->mdl.skinheight; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 600fb0eeb..24f3c230c 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -237,6 +237,14 @@ static struct { shaderparam_t *fog; } sky_params; +typedef struct glslbspctx_s { + mod_brush_t *brush; + entity_t *entity; + vec_t *transform; + float *color; +} glslbspctx_t; + + #define CHAIN_SURF_F2B(surf,chain) \ ({ \ instsurf_t *inst = (surf)->instsurf; \ @@ -360,7 +368,7 @@ glsl_R_ClearElements (void) } static void -update_lightmap (mod_brush_t *brush, msurface_t *surf) +update_lightmap (glslbspctx_t *bctx, msurface_t *surf) { int maps; @@ -371,19 +379,19 @@ update_lightmap (mod_brush_t *brush, msurface_t *surf) if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { dynamic: if (r_dynamic->int_val) - glsl_R_BuildLightMap (brush, surf); + glsl_R_BuildLightMap (bctx->entity->transform, bctx->brush, surf); } } static inline void -chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, - float *color) +chain_surface (glslbspctx_t *bctx, msurface_t *surf) { instsurf_t *is; if (surf->flags & SURF_DRAWSKY) { is = CHAIN_SURF_F2B (surf, sky_chain); - } else if ((surf->flags & SURF_DRAWTURB) || (color && color[3] < 1.0)) { + } else if ((surf->flags & SURF_DRAWTURB) + || (bctx->color && bctx->color[3] < 1.0)) { is = CHAIN_SURF_B2F (surf, waterchain); } else { texture_t *tx; @@ -392,14 +400,14 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, if (!surf->texinfo->texture->anim_total) tx = surf->texinfo->texture; else - tx = R_TextureAnimation (surf); + tx = R_TextureAnimation (bctx->entity, surf); tex = tx->render; is = CHAIN_SURF_F2B (surf, tex->tex_chain); - update_lightmap (brush, surf); + update_lightmap (bctx, surf); } - is->transform = transform; - is->color = color; + is->transform = bctx->transform; + is->color = bctx->color; } static void @@ -656,16 +664,20 @@ R_DrawBrushModel (entity_t *e) float dot, radius; int i; unsigned k; - model_t *model; + model_t *model = e->renderer.model; + mod_brush_t *brush = &model->brush; plane_t *plane; msurface_t *surf; qboolean rotated; vec3_t mins, maxs; vec4f_t org; - mod_brush_t *brush; + glslbspctx_t bctx = { + brush, + e, + e->renderer.full_transform, + e->renderer.colormod, + }; - model = e->renderer.model; - brush = &model->brush; mat4f_t mat; Transform_GetWorldMatrix (e->transform, mat); memcpy (e->renderer.full_transform, mat, sizeof (mat));//FIXME @@ -718,8 +730,7 @@ R_DrawBrushModel (entity_t *e) // enqueue the polygon if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (brush, surf, e->renderer.full_transform, - e->renderer.colormod); + chain_surface (&bctx, surf); } } } @@ -744,7 +755,7 @@ get_side (mnode_t *node) } static inline void -visit_node (mod_brush_t *brush, mnode_t *node, int side) +visit_node (glslbspctx_t *bctx, mnode_t *node, int side) { int c; msurface_t *surf; @@ -753,7 +764,7 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side) side = (~side + 1) & SURF_PLANEBACK; // draw stuff if ((c = node->numsurfaces)) { - surf = brush->surfaces + node->firstsurface; + surf = bctx->brush->surfaces + node->firstsurface; for (; c; c--, surf++) { if (surf->visframe != r_visframecount) continue; @@ -762,7 +773,7 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side) if (side ^ (surf->flags & SURF_PLANEBACK)) continue; // wrong side - chain_surface (brush, surf, 0, 0); + chain_surface (bctx, surf); } } } @@ -780,12 +791,13 @@ test_node (mnode_t *node) } static void -R_VisitWorldNodes (mod_brush_t *brush) +R_VisitWorldNodes (glslbspctx_t *bctx) { typedef struct { mnode_t *node; int side; } rstack_t; + mod_brush_t *brush = bctx->brush; rstack_t *node_ptr; rstack_t *node_stack; mnode_t *node; @@ -810,7 +822,7 @@ R_VisitWorldNodes (mod_brush_t *brush) } if (front->contents < 0 && front->contents != CONTENTS_SOLID) visit_leaf ((mleaf_t *) front); - visit_node (brush, node, side); + visit_node (bctx, node, side); node = node->children[!side]; } if (node->contents < 0 && node->contents != CONTENTS_SOLID) @@ -819,7 +831,7 @@ R_VisitWorldNodes (mod_brush_t *brush) node_ptr--; node = node_ptr->node; side = node_ptr->side; - visit_node (brush, node, side); + visit_node (bctx, node, side); node = node->children[!side]; continue; } @@ -1128,6 +1140,7 @@ void glsl_R_DrawWorld (void) { entity_t worldent; + glslbspctx_t bctx = { }; int i; clear_texture_chains (); // do this first for water and skys @@ -1135,16 +1148,15 @@ glsl_R_DrawWorld (void) memset (&worldent, 0, sizeof (worldent)); worldent.renderer.model = r_worldentity.renderer.model; - currententity = &worldent; + bctx.brush = &worldent.renderer.model->brush; + bctx.entity = &r_worldentity; - R_VisitWorldNodes (&worldent.renderer.model->brush); + R_VisitWorldNodes (&bctx); if (r_drawentities->int_val) { entity_t *ent; for (ent = r_ent_queue; ent; ent = ent->next) { if (ent->renderer.model->type != mod_brush) continue; - currententity = ent; - R_DrawBrushModel (ent); } } diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index 93a25e982..eeba3f572 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -204,10 +204,9 @@ set_arrays (iqm_t *iqm) } void -glsl_R_DrawIQM (void) +glsl_R_DrawIQM (entity_t *ent) { static quat_t color = { 1, 1, 1, 1}; - entity_t *ent = currententity; model_t *model = ent->renderer.model; iqm_t *iqm = (iqm_t *) model->aliashdr; glsliqm_t *glsl = (glsliqm_t *) iqm->extra_data; diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index f34de4692..f50340d5b 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -62,10 +62,11 @@ static scrap_t *light_scrap; static unsigned *blocklights; static int bl_extents[2]; -void (*glsl_R_BuildLightMap) (mod_brush_t *brush, msurface_t *surf); +void (*glsl_R_BuildLightMap) (const transform_t *transform, mod_brush_t *brush, + msurface_t *surf); static void -R_AddDynamicLights_1 (msurface_t *surf) +R_AddDynamicLights_1 (const transform_t *transform, msurface_t *surf) { unsigned lnum; int sd, td; @@ -80,9 +81,9 @@ R_AddDynamicLights_1 (msurface_t *surf) tmax = (surf->extents[1] >> 4) + 1; tex = surf->texinfo; - if (currententity->transform) { + if (transform) { //FIXME give world entity a transform - entorigin = Transform_GetWorldPosition (currententity->transform); + entorigin = Transform_GetWorldPosition (transform); } for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -127,7 +128,8 @@ R_AddDynamicLights_1 (msurface_t *surf) } static void -R_BuildLightMap_1 (mod_brush_t *brush, msurface_t *surf) +R_BuildLightMap_1 (const transform_t *transform, mod_brush_t *brush, + msurface_t *surf) { int smax, tmax, size; unsigned scale; @@ -168,7 +170,7 @@ R_BuildLightMap_1 (mod_brush_t *brush, msurface_t *surf) } // add all the dynamic lights if (surf->dlightframe == r_framecount) - R_AddDynamicLights_1 (surf); + R_AddDynamicLights_1 (transform, surf); // bound, invert, and shift out = (byte *) blocklights; @@ -248,7 +250,7 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) for (i = 0; i < brush->numsurfaces; i++) { msurface_t *surf = brush->surfaces + i; if (surf->lightpic) - glsl_R_BuildLightMap (brush, surf); + glsl_R_BuildLightMap (0, brush, surf); } } } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 06c7b1898..a5afc45a6 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -54,6 +54,7 @@ #include "QF/GLSL/qf_bsp.h" #include "QF/GLSL/qf_iqm.h" #include "QF/GLSL/qf_lightmap.h" +#include "QF/GLSL/qf_sprite.h" #include "QF/GLSL/qf_textures.h" #include "mod_internal.h" @@ -145,8 +146,7 @@ R_RenderEntities (void) glsl_R_##Type##Begin (); \ begun = 1; \ } \ - currententity = ent; \ - glsl_R_Draw##Type (); \ + glsl_R_Draw##Type (ent); \ } \ if (begun) \ glsl_R_##Type##End (); \ @@ -160,17 +160,17 @@ R_RenderEntities (void) static void R_DrawViewModel (void) { - currententity = vr_data.view_model; + entity_t *ent = vr_data.view_model; if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val || !r_drawentities->int_val - || !currententity->renderer.model) + || !ent->renderer.model) return; // hack the depth range to prevent view model from poking into walls qfeglDepthRangef (0, 0.3); glsl_R_AliasBegin (); - glsl_R_DrawAlias (); + glsl_R_DrawAlias (ent); glsl_R_AliasEnd (); qfeglDepthRangef (0, 1); } diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 7eecea5dd..66b30485d 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -51,6 +51,7 @@ #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" +#include "QF/GLSL/qf_sprite.h" #include "QF/GLSL/qf_textures.h" #include "QF/GLSL/qf_vid.h" @@ -132,7 +133,8 @@ static void R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, mspriteframe_t **frame2, float *blend) { - int framenum = currententity->animation.frame; + animation_t *animation = &ent->animation; + int framenum = animation->frame; int pose; int i, numframes; float *intervals; @@ -154,7 +156,7 @@ R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, numframes = group->numframes; fullinterval = intervals[numframes - 1]; - time = vr_data.realtime + currententity->animation.syncbase; + time = vr_data.realtime + animation->syncbase; targettime = time - ((int) (time / fullinterval)) * fullinterval; for (i = 0; i < numframes - 1; i++) { @@ -169,23 +171,22 @@ R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, //FIXME this will break if the sprite changes between single frames and //group frames. - *blend = R_EntityBlend (ent, pose, frame_interval); + *blend = R_EntityBlend (animation, pose, frame_interval); if (group) { - *frame1 = group->frames[ent->animation.pose1]; - *frame2 = group->frames[ent->animation.pose2]; + *frame1 = group->frames[animation->pose1]; + *frame2 = group->frames[animation->pose2]; } else { - *frame1 = sprite->frames[ent->animation.pose1].frameptr; - *frame2 = sprite->frames[ent->animation.pose2].frameptr; + *frame1 = sprite->frames[animation->pose1].frameptr; + *frame2 = sprite->frames[animation->pose2].frameptr; } } static void -make_quad (mspriteframe_t *frame, vec4f_t vpn, vec4f_t vright, +make_quad (mspriteframe_t *frame, vec4f_t origin, vec4f_t vpn, vec4f_t vright, vec4f_t vup, float verts[6][3]) { vec4f_t left, up, right, down; vec4f_t ul, ur, ll, lr; - vec4f_t origin = Transform_GetWorldPosition (currententity->transform); // build the sprite poster in worldspace // first, rotate the sprite axes into world space @@ -208,9 +209,8 @@ make_quad (mspriteframe_t *frame, vec4f_t vpn, vec4f_t vright, } void -R_DrawSprite (void) +glsl_R_DrawSprite (entity_t *ent) { - entity_t *ent = currententity; msprite_t *sprite = (msprite_t *) ent->renderer.model->cache.data; mspriteframe_t *frame1, *frame2; float blend, sr, cr, dot; @@ -276,16 +276,16 @@ R_DrawSprite (void) case SPR_ORIENTED: // generate the prite's axes according to the sprite's world // orientation - svup = Transform_Up (currententity->transform); - svright = Transform_Right (currententity->transform); - svpn = Transform_Forward (currententity->transform); + svup = Transform_Up (ent->transform); + svright = Transform_Right (ent->transform); + svpn = Transform_Forward (ent->transform); break; case SPR_VP_PARALLEL_ORIENTED: // generate the sprite's axes parallel to the viewplane, but // rotated in that plane round the center according to the sprite // entity's roll angle. Thus svpn stays the same, but svright and // svup rotate - rot = Transform_GetLocalRotation (currententity->transform); + rot = Transform_GetLocalRotation (ent->transform); //FIXME assumes the entity is only rolled sr = 2 * rot[0] * rot[3]; cr = rot[3] * rot[3] - rot[0] * rot[0]; @@ -311,8 +311,9 @@ R_DrawSprite (void) qfeglVertexAttrib4fv (quake_sprite.colorb.location, color); qfeglVertexAttrib1f (quake_sprite.blend.location, blend); - make_quad (frame1, svpn, svright, svup, vertsa); - make_quad (frame2, svpn, svright, svup, vertsb); + vec4f_t origin = Transform_GetWorldPosition (ent->transform); + make_quad (frame1, origin, svpn, svright, svup, vertsa); + make_quad (frame2, origin, svpn, svright, svup, vertsb); qfeglVertexAttribPointer (quake_sprite.vertexa.location, 3, GL_FLOAT, 0, 0, vertsa); diff --git a/libs/video/renderer/glsl/namehack.h b/libs/video/renderer/glsl/namehack.h index a6f62e701..6a8377a9d 100644 --- a/libs/video/renderer/glsl/namehack.h +++ b/libs/video/renderer/glsl/namehack.h @@ -43,7 +43,6 @@ #define R_DrawParticles glsl_R_DrawParticles #define R_DrawSky glsl_R_DrawSky #define R_DrawSkyChain glsl_R_DrawSkyChain -#define R_DrawSprite glsl_R_DrawSprite #define R_DrawSpriteModel glsl_R_DrawSpriteModel #define R_DrawWaterSurfaces glsl_R_DrawWaterSurfaces #define R_DrawWorld glsl_R_DrawWorld diff --git a/libs/video/renderer/r_alias.c b/libs/video/renderer/r_alias.c index dd99112d2..6dea420b6 100644 --- a/libs/video/renderer/r_alias.c +++ b/libs/video/renderer/r_alias.c @@ -37,7 +37,7 @@ float r_avertexnormals[NUMVERTEXNORMALS][3] = { }; maliasskindesc_t * -R_AliasGetSkindesc (int skinnum, aliashdr_t *ahdr) +R_AliasGetSkindesc (animation_t *animation, int skinnum, aliashdr_t *ahdr) { maliasskindesc_t *pskindesc; maliasskingroup_t *paliasskingroup; @@ -63,7 +63,7 @@ R_AliasGetSkindesc (int skinnum, aliashdr_t *ahdr) numskins = paliasskingroup->numskins; fullskininterval = pskinintervals[numskins - 1]; - skintime = vr_data.realtime + currententity->animation.syncbase; + skintime = vr_data.realtime + animation->syncbase; // when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval // values are positive, so we don't have to worry about division by 0 @@ -81,8 +81,10 @@ R_AliasGetSkindesc (int skinnum, aliashdr_t *ahdr) } static maliasframedesc_t * -alias_get_frame (int framenum, aliashdr_t *hdr, float *frame_interval) +alias_get_frame (const animation_t *animation, aliashdr_t *hdr, + float *frame_interval) { + int framenum = animation->frame; float *intervals; float fullinterval, time, targettime; maliasframedesc_t *frame; @@ -118,7 +120,7 @@ alias_get_frame (int framenum, aliashdr_t *hdr, float *frame_interval) numframes = group->numframes; fullinterval = intervals[numframes - 1]; - time = vr_data.realtime + currententity->animation.syncbase; + time = vr_data.realtime + animation->syncbase; // when loading in Mod_LoadAliasGroup, we guaranteed all interval values // are positive, so we don't have to worry about division by 0 @@ -137,17 +139,17 @@ alias_get_frame (int framenum, aliashdr_t *hdr, float *frame_interval) } maliasframedesc_t * -R_AliasGetFramedesc (int framenum, aliashdr_t *hdr) +R_AliasGetFramedesc (animation_t *animation, aliashdr_t *hdr) { - return alias_get_frame (framenum, hdr, 0); + return alias_get_frame (animation, hdr, 0); } float -R_AliasGetLerpedFrames (entity_t *ent, aliashdr_t *hdr) +R_AliasGetLerpedFrames (animation_t *animation, aliashdr_t *hdr) { maliasframedesc_t *frame; float interval; - frame = alias_get_frame (ent->animation.frame, hdr, &interval); - return R_EntityBlend (ent, frame->firstpose, interval); + frame = alias_get_frame (animation, hdr, &interval); + return R_EntityBlend (animation, frame->firstpose, interval); } diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 03af6696b..e9f9cf664 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -100,12 +100,12 @@ R_MarkLeaves (void) Returns the proper texture for a given time and base texture */ texture_t * -R_TextureAnimation (msurface_t *surf) +R_TextureAnimation (const entity_t *entity, msurface_t *surf) { texture_t *base = surf->texinfo->texture; int count, relative; - if (currententity->animation.frame) { + if (entity->animation.frame) { if (base->alternate_anims) base = base->alternate_anims; } diff --git a/libs/video/renderer/r_ent.c b/libs/video/renderer/r_ent.c index 5a20bcb1f..2ce315206 100644 --- a/libs/video/renderer/r_ent.c +++ b/libs/video/renderer/r_ent.c @@ -131,31 +131,31 @@ R_EnqueueEntity (entity_t *ent) } float -R_EntityBlend (entity_t *ent, int pose, float interval) +R_EntityBlend (animation_t *animation, int pose, float interval) { float blend; - if (ent->animation.nolerp) { - ent->animation.nolerp = 0; - ent->animation.pose1 = pose; - ent->animation.pose2 = pose; + if (animation->nolerp) { + animation->nolerp = 0; + animation->pose1 = pose; + animation->pose2 = pose; return 0.0; } - ent->animation.frame_interval = interval; - if (ent->animation.pose2 != pose) { - ent->animation.frame_start_time = vr_data.realtime; - if (ent->animation.pose2 == -1) { - ent->animation.pose1 = pose; + animation->frame_interval = interval; + if (animation->pose2 != pose) { + animation->frame_start_time = vr_data.realtime; + if (animation->pose2 == -1) { + animation->pose1 = pose; } else { - ent->animation.pose1 = ent->animation.pose2; + animation->pose1 = animation->pose2; } - ent->animation.pose2 = pose; + animation->pose2 = pose; blend = 0.0; } else if (vr_data.paused) { blend = 1.0; } else { - blend = (vr_data.realtime - ent->animation.frame_start_time) - / ent->animation.frame_interval; + blend = (vr_data.realtime - animation->frame_start_time) + / animation->frame_interval; blend = min (blend, 1.0); } return blend; diff --git a/libs/video/renderer/r_iqm.c b/libs/video/renderer/r_iqm.c index 4cfc53693..dcf58f44c 100644 --- a/libs/video/renderer/r_iqm.c +++ b/libs/video/renderer/r_iqm.c @@ -49,12 +49,13 @@ float R_IQMGetLerpedFrames (entity_t *ent, iqm_t *iqm) { + animation_t *animation = &ent->animation; int frame = ent->animation.frame; float time, fullinterval; iqmanim *anim; if (!iqm->num_anims) - return R_EntityBlend (ent, 0, 1.0 / 25.0); + return R_EntityBlend (animation, 0, 1.0 / 25.0); if (frame >= iqm->num_anims || frame < 0) { Sys_MaskPrintf (SYS_dev, "R_IQMGetLerpedFrames: no such frame %d\n", frame); @@ -62,10 +63,10 @@ R_IQMGetLerpedFrames (entity_t *ent, iqm_t *iqm) } anim = &iqm->anims[frame]; fullinterval = anim->num_frames / anim->framerate; - time = vr_data.realtime + currententity->animation.syncbase; + time = vr_data.realtime + ent->animation.syncbase; time -= ((int) (time / fullinterval)) * fullinterval; frame = (int) (time * anim->framerate) + anim->first_frame; - return R_EntityBlend (ent, frame, 1.0 / anim->framerate); + return R_EntityBlend (animation, frame, 1.0 / anim->framerate); } iqmframe_t * diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index bc1590dd0..4bb57c720 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -57,8 +57,6 @@ int r_lineadj; qboolean r_active; int r_init; -entity_t *currententity; - int r_visframecount; // bumped when going to a new PVS int r_framecount = 1; // so frame counts initialized to 0 don't match diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index b348bdeda..8e6e53c75 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -231,7 +231,7 @@ D_CacheSurface (msurface_t *surface, int miplevel) surfcache_t *cache; // if the surface is animating or flashing, flush the cache - r_drawsurf.texture = R_TextureAnimation (surface); + r_drawsurf.texture = R_TextureAnimation (currententity, surface); r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 81b7c9005..dd545debc 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -541,18 +541,18 @@ R_AliasPrepareUnclippedPoints (void) } static void -R_AliasSetupSkin (void) +R_AliasSetupSkin (entity_t *ent) { int skinnum; - skinnum = currententity->renderer.skinnum; + skinnum = ent->renderer.skinnum; if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { Sys_MaskPrintf (SYS_dev, "R_AliasSetupSkin: no such skin # %d\n", skinnum); skinnum = 0; } - pskindesc = R_AliasGetSkindesc (skinnum, paliashdr); + pskindesc = R_AliasGetSkindesc (&ent->animation, skinnum, paliashdr); a_skinwidth = pmdl->skinwidth; @@ -562,16 +562,16 @@ R_AliasSetupSkin (void) r_affinetridesc.skinheight = pmdl->skinheight; acolormap = vid.colormap8; - if (currententity->renderer.skin) { + if (ent->renderer.skin) { tex_t *base; - base = currententity->renderer.skin->texels; + base = ent->renderer.skin->texels; if (base) { r_affinetridesc.pskin = base->data; r_affinetridesc.skinwidth = base->width; r_affinetridesc.skinheight = base->height; } - acolormap = currententity->renderer.skin->colormap; + acolormap = ent->renderer.skin->colormap; } } @@ -610,11 +610,11 @@ R_AliasSetupLighting (alight_t *plighting) set r_apverts */ static void -R_AliasSetupFrame (void) +R_AliasSetupFrame (entity_t *ent) { maliasframedesc_t *frame; - frame = R_AliasGetFramedesc (currententity->animation.frame, paliashdr); + frame = R_AliasGetFramedesc (&ent->animation, paliashdr); r_apverts = (trivertx_t *) ((byte *) paliashdr + frame->frame); } @@ -622,13 +622,14 @@ R_AliasSetupFrame (void) void R_AliasDrawModel (alight_t *plighting) { + entity_t *ent = currententity; int size; finalvert_t *finalverts; r_amodels_drawn++; - if (!(paliashdr = currententity->renderer.model->aliashdr)) - paliashdr = Cache_Get (¤tentity->renderer.model->cache); + if (!(paliashdr = ent->renderer.model->aliashdr)) + paliashdr = Cache_Get (&ent->renderer.model->cache); pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model); size = (CACHE_SIZE - 1) @@ -643,12 +644,12 @@ R_AliasDrawModel (alight_t *plighting) (((intptr_t) &finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1]; - R_AliasSetupSkin (); - R_AliasSetUpTransform (currententity->visibility.trivial_accept); + R_AliasSetupSkin (ent); + R_AliasSetUpTransform (ent->visibility.trivial_accept); R_AliasSetupLighting (plighting); - R_AliasSetupFrame (); + R_AliasSetupFrame (ent); - r_affinetridesc.drawtype = ((currententity->visibility.trivial_accept == 3) + r_affinetridesc.drawtype = ((ent->visibility.trivial_accept == 3) && r_recursiveaffinetriangles); if (!acolormap) @@ -662,19 +663,19 @@ R_AliasDrawModel (alight_t *plighting) #endif } - if (currententity != vr_data.view_model) + if (ent != vr_data.view_model) ziscale = (float) 0x8000 *(float) 0x10000; else ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - if (currententity->visibility.trivial_accept + if (ent->visibility.trivial_accept && pmdl->ident != HEADER_MDL16) { R_AliasPrepareUnclippedPoints (); } else { R_AliasPreparePoints (); } - if (!currententity->renderer.model->aliashdr) { - Cache_Release (¤tentity->renderer.model->cache); + if (!ent->renderer.model->aliashdr) { + Cache_Release (&ent->renderer.model->cache); } } diff --git a/libs/video/renderer/sw32/d_surf.c b/libs/video/renderer/sw32/d_surf.c index 3840d8f53..3b1b68c6a 100644 --- a/libs/video/renderer/sw32/d_surf.c +++ b/libs/video/renderer/sw32/d_surf.c @@ -230,7 +230,7 @@ sw32_D_CacheSurface (msurface_t *surface, int miplevel) surfcache_t *cache; // if the surface is animating or flashing, flush the cache - sw32_r_drawsurf.texture = R_TextureAnimation (surface); + sw32_r_drawsurf.texture = R_TextureAnimation (currententity, surface); sw32_r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; sw32_r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; sw32_r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; diff --git a/libs/video/renderer/sw32/sw32_ralias.c b/libs/video/renderer/sw32/sw32_ralias.c index b2750447b..3a73a56db 100644 --- a/libs/video/renderer/sw32/sw32_ralias.c +++ b/libs/video/renderer/sw32/sw32_ralias.c @@ -543,18 +543,18 @@ R_AliasPrepareUnclippedPoints (void) static void -R_AliasSetupSkin (void) +R_AliasSetupSkin (entity_t *ent) { int skinnum; - skinnum = currententity->renderer.skinnum; + skinnum = ent->renderer.skinnum; if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { Sys_MaskPrintf (SYS_dev, "R_AliasSetupSkin: no such skin # %d\n", skinnum); skinnum = 0; } - pskindesc = R_AliasGetSkindesc (skinnum, paliashdr); + pskindesc = R_AliasGetSkindesc (&ent->animation, skinnum, paliashdr); a_skinwidth = pmdl->skinwidth; sw32_r_affinetridesc.pskin = (void *) ((byte *) paliashdr + pskindesc->skin); @@ -563,16 +563,16 @@ R_AliasSetupSkin (void) sw32_r_affinetridesc.skinheight = pmdl->skinheight; sw32_acolormap = vid.colormap8; - if (currententity->renderer.skin) { + if (ent->renderer.skin) { tex_t *base; - base = currententity->renderer.skin->texels; + base = ent->renderer.skin->texels; if (base) { sw32_r_affinetridesc.pskin = base->data; sw32_r_affinetridesc.skinwidth = base->width; sw32_r_affinetridesc.skinheight = base->height; } - sw32_acolormap = currententity->renderer.skin->colormap; + sw32_acolormap = ent->renderer.skin->colormap; } } @@ -611,11 +611,11 @@ R_AliasSetupLighting (alight_t *plighting) set sw32_r_apverts */ static void -R_AliasSetupFrame (void) +R_AliasSetupFrame (entity_t *ent) { maliasframedesc_t *frame; - frame = R_AliasGetFramedesc (currententity->animation.frame, paliashdr); + frame = R_AliasGetFramedesc (&ent->animation, paliashdr); sw32_r_apverts = (trivertx_t *) ((byte *) paliashdr + frame->frame); } @@ -623,13 +623,14 @@ R_AliasSetupFrame (void) void sw32_R_AliasDrawModel (alight_t *plighting) { + entity_t *ent = currententity; int size; finalvert_t *finalverts; sw32_r_amodels_drawn++; - if (!(paliashdr = currententity->renderer.model->aliashdr)) - paliashdr = Cache_Get (¤tentity->renderer.model->cache); + if (!(paliashdr = ent->renderer.model->aliashdr)) + paliashdr = Cache_Get (&ent->renderer.model->cache); pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model); size = (CACHE_SIZE - 1) @@ -644,10 +645,10 @@ sw32_R_AliasDrawModel (alight_t *plighting) (((intptr_t) &finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); sw32_pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1]; - R_AliasSetupSkin (); - sw32_R_AliasSetUpTransform (currententity->visibility.trivial_accept); + R_AliasSetupSkin (ent); + sw32_R_AliasSetUpTransform (ent->visibility.trivial_accept); R_AliasSetupLighting (plighting); - R_AliasSetupFrame (); + R_AliasSetupFrame (ent); if (!sw32_acolormap) sw32_acolormap = vid.colormap8; @@ -662,18 +663,18 @@ sw32_R_AliasDrawModel (alight_t *plighting) sw32_ctx->pixbytes); } - if (currententity != vr_data.view_model) + if (ent != vr_data.view_model) sw32_ziscale = (float) 0x8000 *(float) 0x10000; else sw32_ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - if (currententity->visibility.trivial_accept) { + if (ent->visibility.trivial_accept) { R_AliasPrepareUnclippedPoints (); } else { R_AliasPreparePoints (); } - if (!currententity->renderer.model->aliashdr) { - Cache_Release (¤tentity->renderer.model->cache); + if (!ent->renderer.model->aliashdr) { + Cache_Release (&ent->renderer.model->cache); } } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 4b6b1ae19..83c0a5e0a 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -129,6 +129,7 @@ Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx) model_t *model = ent->renderer.model; aliashdr_t *hdr; qfv_alias_skin_t *skin; + animation_t *animation = &ent->animation; struct { mat4f_t mat; float blend; @@ -140,13 +141,13 @@ Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx) } Transform_GetWorldMatrix (ent->transform, vertex_constants.mat); - vertex_constants.blend = R_AliasGetLerpedFrames (ent, hdr); + vertex_constants.blend = R_AliasGetLerpedFrames (animation, hdr); if (0/*XXX ent->skin && ent->skin->tex*/) { //skin = ent->skin->tex; } else { maliasskindesc_t *skindesc; - skindesc = R_AliasGetSkindesc (ent->renderer.skinnum, hdr); + skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr); skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } QuatScale (ent->renderer.colormod, 255, fragment_constants[0]); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 5d1ad07a3..5fca9c61e 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -213,15 +213,15 @@ Vulkan_ClearElements (vulkan_ctx_t *ctx) } static inline void -chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, - float *color, vulkan_ctx_t *ctx) +chain_surface (msurface_t *surf, vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; instsurf_t *is; if (surf->flags & SURF_DRAWSKY) { is = CHAIN_SURF_F2B (surf, bctx->sky_chain); - } else if ((surf->flags & SURF_DRAWTURB) || (color && color[3] < 1.0)) { + } else if ((surf->flags & SURF_DRAWTURB) + || (bctx->color && bctx->color[3] < 1.0)) { is = CHAIN_SURF_B2F (surf, bctx->waterchain); } else { texture_t *tx; @@ -230,12 +230,12 @@ chain_surface (mod_brush_t *brush, msurface_t *surf, vec_t *transform, if (!surf->texinfo->texture->anim_total) tx = surf->texinfo->texture; else - tx = R_TextureAnimation (surf); + tx = R_TextureAnimation (bctx->entity, surf); tex = tx->render; is = CHAIN_SURF_F2B (surf, tex->tex_chain); } - is->transform = transform; - is->color = color; + is->transform = bctx->transform; + is->color = bctx->color; } static void @@ -588,6 +588,11 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) vec3_t mins, maxs; vec4f_t org; mod_brush_t *brush; + bspctx_t *bctx = ctx->bsp_context; + + bctx->entity = e; + bctx->transform = e->renderer.full_transform; + bctx->color = e->renderer.colormod; model = e->renderer.model; brush = &model->brush; @@ -628,8 +633,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) // enqueue the polygon if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (brush, surf, e->renderer.full_transform, - e->renderer.colormod, ctx); + chain_surface (surf, ctx); } } } @@ -672,7 +676,7 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) if (side ^ (surf->flags & SURF_PLANEBACK)) continue; // wrong side - chain_surface (brush, surf, 0, 0, ctx); + chain_surface (surf, ctx); } } } @@ -1078,7 +1082,9 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) worldent.renderer.model = r_worldentity.renderer.model; brush = &r_worldentity.renderer.model->brush; - currententity = &worldent; + bctx->entity = &r_worldentity; + bctx->transform = 0; + bctx->color = 0; R_VisitWorldNodes (brush, ctx); if (r_drawentities->int_val) { @@ -1086,8 +1092,6 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) for (ent = r_ent_queue; ent; ent = ent->next) { if (ent->renderer.model->type != mod_brush) continue; - currententity = ent; - R_DrawBrushModel (ent, ctx); } } diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 3474b67ed..73e06b2b4 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -132,11 +132,11 @@ R_RenderEntities (vulkan_ctx_t *ctx) static void R_DrawViewModel (void) { - currententity = vr_data.view_model; + entity_t *ent = vr_data.view_model; if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val || !r_drawentities->int_val - || !currententity->renderer.model) + || !ent->renderer.model) return; // hack the depth range to prevent view model from poking into walls From 49afdde77f6cf93405f8373e6fc4634a6778eb46 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jul 2021 16:13:12 +0900 Subject: [PATCH 1654/3664] [vulkan] Add some comments and clean some code Figuring out bsp rendering for shadows is a fair bit harder than expected :P --- libs/video/renderer/vulkan/vulkan_bsp.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 5fca9c61e..ac22d1034 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -722,6 +722,10 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) node = front; continue; } + // front is either not a node (ie, is a leaf) or is not visible + // if node is visible, then at least one of its child nodes + // must also be visible, and a leaf child in front of the node + // will be visible, so no need for vis checks on a leaf if (front->contents < 0 && front->contents != CONTENTS_SOLID) visit_leaf ((mleaf_t *) front); visit_node (brush, node, side, ctx); @@ -1030,8 +1034,7 @@ add_surf_elements (vulktex_t *tex, instsurf_t *is, elechain_t **ec, elements_t **el, bspctx_t *bctx, bspframe_t *bframe) { - msurface_t *surf = is->surface; - bsppoly_t *poly = (bsppoly_t *) surf->polys; + bsppoly_t *poly = (bsppoly_t *) is->surface->polys; if (!tex->elechain) { (*ec) = add_elechain (tex, bctx); @@ -1061,6 +1064,8 @@ build_tex_elechain (vulktex_t *tex, bspctx_t *bctx, bspframe_t *bframe) elements_t *el = 0; for (is = tex->tex_chain; is; is = is->tex_chain) { + // emit the polygon indices for the the surface to the texture's + // element chain add_surf_elements (tex, is, &ec, &el, bctx, bframe); } } @@ -1157,7 +1162,6 @@ Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; instsurf_t *is; - msurface_t *surf; vulktex_t *tex = 0; elechain_t *ec = 0; elements_t *el = 0; @@ -1172,7 +1176,7 @@ Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) push_fragconst (&frag_constants, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); for (is = bctx->waterchain; is; is = is->tex_chain) { - surf = is->surface; + msurface_t *surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { bind_view (qfv_bsp_texture, @@ -1190,6 +1194,8 @@ Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) } tex = surf->texinfo->texture->render; } + // emit the polygon indices for the the surface to the texture's + // element chain add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { @@ -1218,7 +1224,6 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; instsurf_t *is; - msurface_t *surf; vulktex_t *tex = 0; elechain_t *ec = 0; elements_t *el = 0; @@ -1233,7 +1238,7 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) push_fragconst (&frag_constants, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); for (is = bctx->sky_chain; is; is = is->tex_chain) { - surf = is->surface; + msurface_t *surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { bind_view (qfv_bsp_skysheet, @@ -1251,6 +1256,8 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) } tex = surf->texinfo->texture->render; } + // emit the polygon indices for the the surface to the texture's + // element chain add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { From e089234f3819e193dc337352c9069f17fc2f0405 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jul 2021 18:01:18 +0900 Subject: [PATCH 1655/3664] [console] Link against libQFruamoko_console Fixes shared plugin not loading due to missing symbol. --- libs/console/Makemodule.am | 7 ++++--- nq/source/Makemodule.am | 1 - qw/source/Makemodule.am | 1 - ruamoko/qwaq/Makemodule.am | 1 - 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libs/console/Makemodule.am b/libs/console/Makemodule.am index a3f06e346..fee9f194d 100644 --- a/libs/console/Makemodule.am +++ b/libs/console/Makemodule.am @@ -24,21 +24,22 @@ client_deps= \ libs/audio/libQFsound.la \ libs/ruamoko/libQFruamoko.la \ libs/gib/libQFgib.la \ + libs/ruamoko/libQFruamoko_client.la \ libs/ruamoko/libQFruamoko.la \ $(console_deps) server_deps= libs/console/libQFconsole.la $(console_deps) libs_console_libQFconsole_la_LDFLAGS= $(lib_ldflags) -libs_console_libQFconsole_la_LIBADD= $(console_deps) $(plugin_libadd) +libs_console_libQFconsole_la_LIBADD= $(console_deps) $(plugin_libadd) libs_console_libQFconsole_la_DEPENDENCIES= $(console_deps) libs_console_libQFconsole_la_SOURCES= $(console_common_sources) libs_console_console_client_la_LDFLAGS= $(plugin_ldflags) libs_console_console_client_la_LIBADD= $(client_deps) $(plugin_libadd) -libs_console_console_client_la_DEPENDENCIES= $(client_deps) +libs_console_console_client_la_DEPENDENCIES=$(client_deps) libs_console_console_client_la_SOURCES= $(client_sources) libs_console_console_server_la_LDFLAGS= $(plugin_ldflags) libs_console_console_server_la_LIBADD= $(server_deps) $(NCURSES_LIBS) $(plugin_libadd) -libs_console_console_server_la_DEPENDENCIES= $(server_deps) +libs_console_console_server_la_DEPENDENCIES=$(server_deps) libs_console_console_server_la_SOURCES= $(server_sources) diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index a757a63ea..45beb5b0e 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -46,7 +46,6 @@ nq_cl_plugin_LIBS= \ nq_client_LIBFILES= \ libs/gib/libQFgib_client.la \ - libs/ruamoko/libQFruamoko_client.la \ libs/entity/libQFentity.la \ libs/video/targets/libQFjs.la \ libs/audio/libQFcd.la \ diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 68d62a005..95ccd1a67 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -88,7 +88,6 @@ qw_cl_plugin_LIBS= \ qw_client_LIBS= \ libs/qw/libqw.a \ libs/gib/libQFgib_client.la \ - libs/ruamoko/libQFruamoko_client.la \ libs/net/libnet_chan.la \ libs/entity/libQFentity.la \ libs/console/libQFconsole.la \ diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 30f07a8d2..b2f4f300a 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -86,7 +86,6 @@ qwaq_client_libs= \ qwaq_x11_libs= \ $(qwaq_cl_plugin_libs) \ ${top_builddir}/libs/gib/libQFgib.la \ - ${top_builddir}/libs/ruamoko/libQFruamoko_client.la \ $(top_builddir)/libs/video/renderer/libQFrenderer.la \ $(top_builddir)/libs/models/libQFmodels.la \ $(top_builddir)/libs/video/targets/libQFx11.la \ From b3e7b52696983044beda4adbbbb49273c937944f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jul 2021 18:02:36 +0900 Subject: [PATCH 1656/3664] [qw] Check for null file before checking size Fixes a segfault when downloading a file that doesn't exist. --- qw/source/sv_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index f1a8b28cb..23affbb91 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -758,7 +758,7 @@ SV_BeginDownload_f (void *unused) file = _QFS_FOpenFile (name, !zip); host_client->download = file; - host_client->downloadsize = Qfilesize (file); + host_client->downloadsize = file ? Qfilesize (file) : 0; host_client->downloadcount = 0; if (!host_client->download From e799a7ae45b0ab2ad7b642953277db8ccf256cf8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jul 2021 18:08:13 +0900 Subject: [PATCH 1657/3664] [qwaq] Readd libQFruamoko_client to qwaq-x11 Turned out it was needed after all (bad build test) --- ruamoko/qwaq/Makemodule.am | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index b2f4f300a..3c5b0100d 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -86,6 +86,7 @@ qwaq_client_libs= \ qwaq_x11_libs= \ $(qwaq_cl_plugin_libs) \ ${top_builddir}/libs/gib/libQFgib.la \ + ${top_builddir}/libs/ruamoko/libQFruamoko_client.la \ $(top_builddir)/libs/video/renderer/libQFrenderer.la \ $(top_builddir)/libs/models/libQFmodels.la \ $(top_builddir)/libs/video/targets/libQFx11.la \ From 30dc82f2901ea439db3704a44ef416394c601ca6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jul 2021 19:35:12 +0900 Subject: [PATCH 1658/3664] [qw] Use efrags for carried flags This sorts out the unwanted use of R_EnqueueEntity, which will help with removing another global (r_ent_queue), which is necessary for threaded multi-pass rendering (ie, shadows). --- include/client/state.h | 2 + qw/source/cl_ents.c | 97 ++++++++++++++++++++++++++++-------------- 2 files changed, 66 insertions(+), 33 deletions(-) diff --git a/include/client/state.h b/include/client/state.h index a06890822..23be2bbe4 100644 --- a/include/client/state.h +++ b/include/client/state.h @@ -50,6 +50,8 @@ typedef struct player_info_s { struct info_key_s *skinname; struct skin_s *skin; + struct entity_s *flag_ent; + int spectator; int stats[MAX_CL_STATS]; // health, etc int prevcount; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index a63809ba4..04b6cd9c1 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -278,16 +278,8 @@ CL_LinkPacketEntities (void) } } -/* - CL_AddFlagModels - - Called when the CTF flags are set. Flags are effectively temp entities. - - NOTE: this must be called /after/ the entity has been transformed as it - uses the entity's transform matrix to get the frame vectors -*/ static void -CL_AddFlagModels (entity_t *ent, int team, int key) +CL_UpdateFlagModels (entity_t *ent, int key) { static float flag_offsets[] = { 16.0, 22.0, 26.0, 25.0, 24.0, 18.0, // 29-34 axpain @@ -298,12 +290,10 @@ CL_AddFlagModels (entity_t *ent, int team, int key) fent = &cl_flag_ents[key]; - if (cl_flagindex == -1) { - fent->active = 0; + if (!fent->active) { return; } - fent->active = 1; f = 14.0; if (ent->animation.frame >= 29 && ent->animation.frame <= 40) { f = flag_offsets[ent->animation.frame - 29]; @@ -315,23 +305,51 @@ CL_AddFlagModels (entity_t *ent, int team, int key) } } - vec4f_t position = { 22, -f, -16, 1}; + vec4f_t scale = { 1, 1, 1, 1 }; + // -45 degree roll (x is forward) + vec4f_t rotation = { -0.382683432, 0, 0, 0.923879533 }; + vec4f_t position = { -f, -22, 0, 1}; + + Transform_SetLocalPosition (fent->transform, position); + Transform_SetLocalTransform (fent->transform, scale, rotation, position); + position = Transform_GetWorldPosition (fent->transform); + position[3] -= 16; + Transform_SetWorldPosition (fent->transform, position); +} + +static entity_t * +CL_AddFlagModels (entity_t *ent, int team, int key) +{ + entity_t *fent; + + fent = &cl_flag_ents[key]; + + if (cl_flagindex == -1) { + fent->active = 0; + return 0; + } + + fent->active = 1; if (!Transform_GetParent (fent->transform)) { - vec4f_t scale = { 1, 1, 1, 1 }; - // -45 degree roll (x is forward) - vec4f_t rotation = { -0.382683432, 0, 0, 0.923879533 }; Transform_SetParent (fent->transform, ent->transform); - Transform_SetLocalTransform (fent->transform, scale, rotation, - position); - } else { - Transform_SetLocalPosition (fent->transform, position); } + CL_UpdateFlagModels (ent, key); + fent->renderer.model = cl.model_precache[cl_flagindex]; fent->renderer.skinnum = team; - r_funcs->R_EnqueueEntity (fent);//FIXME should use efrag (needs smarter - // handling //in the player code) + return fent; +} + +static void +CL_RemoveFlagModels (int key) +{ + entity_t *fent; + + fent = &cl_flag_ents[key]; + fent->active = 0; + Transform_SetParent (fent->transform, 0); } /* @@ -347,7 +365,7 @@ CL_LinkPlayers (void) int msec, oldphysent, j; entity_t *ent; frame_t *frame; - player_info_t *info; + player_info_t *player; player_state_t exact; player_state_t *state; qboolean clientplayer; @@ -360,15 +378,18 @@ CL_LinkPlayers (void) frame = &cl.frames[cl.parsecount & UPDATE_MASK]; - for (j = 0, info = cl.players, state = frame->playerstate; j < MAX_CLIENTS; - j++, info++, state++) { + for (j = 0, player = cl.players, state = frame->playerstate; + j < MAX_CLIENTS; j++, player++, state++) { ent = &cl_player_ents[j]; if (ent->visibility.efrag) r_funcs->R_RemoveEfrags (ent); + if (player->flag_ent && player->flag_ent->visibility.efrag) { + r_funcs->R_RemoveEfrags (player->flag_ent); + } if (state->messagenum != cl.parsecount) continue; // not present this frame - if (!info->name || !info->name->value[0]) + if (!player->name || !player->name->value[0]) continue; // spawn light flashes, even ones coming from invisible objects @@ -380,7 +401,7 @@ CL_LinkPlayers (void) org = state->pls.es.origin; clientplayer = false; } - if (info->chat && info->chat->value[0] != '0') { + if (player->chat && player->chat->value[0] != '0') { dlight_t *dl = r_funcs->R_AllocDlight (j + 1); VectorCopy (org, dl->origin); dl->radius = 100; @@ -447,7 +468,7 @@ CL_LinkPlayers (void) if (state->pls.es.modelindex == cl_playerindex) { //XXX // use custom skin - ent->renderer.skin = info->skin; + ent->renderer.skin = player->skin; ent->renderer.min_light = min (cl.fbskins, cl_fb_players->value); @@ -459,13 +480,23 @@ CL_LinkPlayers (void) ent->renderer.skin = 0; } + int flag_state = state->pls.es.effects & (EF_FLAG1 | EF_FLAG2); + if (player->flag_ent && !flag_state) { + CL_RemoveFlagModels (j); + player->flag_ent = 0; + } else if (!player->flag_ent && flag_state) { + if (flag_state & EF_FLAG1) + player->flag_ent = CL_AddFlagModels (ent, 0, j); + else if (flag_state & EF_FLAG2) + player->flag_ent = CL_AddFlagModels (ent, 1, j); + } + // stuff entity in map r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); - - if (state->pls.es.effects & EF_FLAG1) - CL_AddFlagModels (ent, 0, j); - else if (state->pls.es.effects & EF_FLAG2) - CL_AddFlagModels (ent, 1, j); + if (player->flag_ent) { + CL_UpdateFlagModels (ent, j); + r_funcs->R_AddEfrags (&cl.worldmodel->brush, player->flag_ent); + } } } From 3b586fc0a6ef54801b30a791cda5f736ed5a6f86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jul 2021 02:25:16 +0900 Subject: [PATCH 1659/3664] [console] Untangle console and menu toggling The recent changes to key handling broke using escape to get out of the console (escape would toggle between console and menu). Thus take care of the menu (escape) part of the coupling FIXME by implementing a callback for the escape key (and removing key_togglemenu) and sorting out the escape key handling in console. Seems to work nicely --- include/QF/keys.h | 32 +++++++--- libs/console/client.c | 103 ++++++++++++++++++-------------- libs/console/menu.c | 8 +++ libs/input/keys.c | 116 ++++++++++++++++++++---------------- libs/video/targets/in_x11.c | 4 +- nq/source/host.c | 4 +- nq/source/sbar.c | 4 +- nq/source/sv_ded.c | 2 +- qw/source/cl_chat.c | 4 +- qw/source/sbar.c | 4 +- 10 files changed, 167 insertions(+), 114 deletions(-) diff --git a/include/QF/keys.h b/include/QF/keys.h index 50dc7ff0f..0159d80bc 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -537,7 +537,6 @@ typedef struct { int state; // low bit is down state } kbutton_t; -extern knum_t key_togglemenu; extern knum_t key_toggleconsole; typedef struct keybind_s { @@ -571,8 +570,8 @@ extern int keydown[QFK_LAST]; \param down True if a press event, false if a release event. \param data Callback specific data pointer as passed to Key_SetKeyDest */ -typedef void (*key_event_t) (knum_t key, short unicode, qboolean down, - void *data); +typedef void key_event_t (knum_t key, short unicode, qboolean down, + void *data); /** Set the fallback key event handler callback for the specified keydest. @@ -585,9 +584,25 @@ typedef void (*key_event_t) (knum_t key, short unicode, qboolean down, \param keydest The keydest for which the callback will be set. \param callback The function to be called when an event occurs. - \param data Opaque data pointerer passed to the callback. + \param data Opaque data pointer passed to the callback. */ -void Key_SetKeyEvent (keydest_t keydest, key_event_t callback, void *data); +void Key_SetKeyEvent (keydest_t keydest, key_event_t *callback, void *data); + +/** Callback for handling the escape key. + \param data Callback specific data pointer as passed to Key_PushEscape +*/ +typedef void key_escape_t (void *data); + +/** Push an escape key event handler callback. + + \param callback The function to be called when the escape key is pressed. + \param data Opaque data pointer passed to the callback. +*/ +void Key_PushEscape (key_escape_t *callback, void *data); + +/** Push an escape key event handler callback. +*/ +void Key_PopEscape (void); struct cbuf_s; @@ -687,14 +702,17 @@ keydest_t Key_GetKeyDest(void) __attribute__((pure)); /** keydest callback signature. \param kd The new current keydest target. + \param data Callback specific data pointer as passed to + Key_KeydestCallback */ -typedef void keydest_callback_t (keydest_t kd); +typedef void keydest_callback_t (keydest_t kd, void *data); /** Add a callback for when the keydest target changes. \param callback The callback to be added. + \param data Opaque data pointer passed to the callback. */ -void Key_KeydestCallback (keydest_callback_t *callback); +void Key_KeydestCallback (keydest_callback_t *callback, void *data); /** Get the string representation of a key. diff --git a/libs/console/client.c b/libs/console/client.c index 32dbb4a62..186d2a509 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -106,7 +106,8 @@ static view_t *hud_view; static qboolean con_initialized; -static keydest_t con_keydest; +static keydest_t con_curr_keydest; +static keydest_t con_prev_keydest; static void ClearNotify (void) @@ -123,9 +124,10 @@ ToggleConsole_f (void) { Con_ClearTyping (input_line, 0); - if (con_keydest == key_console && !con_data.force_commandline) { - Key_SetKeyDest (key_game); + if (con_curr_keydest == key_console && !con_data.force_commandline) { + Key_SetKeyDest (con_prev_keydest); } else { + con_prev_keydest = Key_GetKeyDest (); Key_SetKeyDest (key_console); } @@ -137,7 +139,7 @@ ToggleChat_f (void) { Con_ClearTyping (input_line, 0); - if (con_keydest == key_console && !con_data.force_commandline) { + if (con_curr_keydest == key_console && !con_data.force_commandline) { Key_SetKeyDest (key_game); } else { Key_SetKeyDest (key_console); @@ -453,49 +455,19 @@ C_KeyEvent (knum_t key, short unicode, qboolean down, void *data) if (!down) return; - if (con_keydest == key_menu) { + if (con_curr_keydest == key_menu) { if (Menu_KeyEvent (key, unicode, down)) return; } if (down) { - if (key == key_togglemenu) { - switch (con_keydest) { - case key_menu: - Menu_Leave (); - return; - case key_message: - if (chat_team) { - Con_ClearTyping (say_team_line, 1); - } else { - Con_ClearTyping (say_line, 1); - } - Key_SetKeyDest (key_game); - return; - case key_console: - if (!con_data.force_commandline) { - Cbuf_AddText (con_data.cbuf, "toggleconsole\n"); - return; - } - case key_game: - case key_demo: - Menu_Enter (); - return; - case key_unfocused: - return; - case key_last: - break; // should not happen, so hit error - } - Sys_Error ("Bad con_keydest"); - } else if (key == key_toggleconsole) { + if (key == key_toggleconsole) { ToggleConsole_f (); return; } } - if (con_keydest == key_menu) { - return; - } else if (con_keydest == key_message) { + if (con_curr_keydest == key_message) { if (chat_team) { il = say_team_line; } else { @@ -579,7 +551,7 @@ C_DrawInputLine (inputline_t *il) static void draw_input (view_t *view) { - if (con_keydest != key_console)// && !con_data.force_commandline) + if (con_curr_keydest != key_console)// && !con_data.force_commandline) return; // don't draw anything (always draw if not active) DrawInputLine (view->xabs + 8, view->yabs, 1, input_line); @@ -734,7 +706,7 @@ setup_console (void) if (con_data.force_commandline) { lines = con_data.lines = r_data->vid->conview->ylen; - } else if (con_keydest == key_console) { + } else if (con_curr_keydest == key_console) { lines = r_data->vid->conview->ylen * bound (0.2, con_size->value, 1); } else { lines = 0; @@ -763,9 +735,9 @@ C_DrawConsole (void) if (console_view->ylen != con_data.lines) view_resize (console_view, console_view->xlen, con_data.lines); - say_view->visible = con_keydest == key_message; + say_view->visible = con_curr_keydest == key_message; console_view->visible = con_data.lines != 0; - menu_view->visible = con_keydest == key_menu; + menu_view->visible = con_curr_keydest == key_menu; con_data.view->draw (con_data.view); } @@ -806,10 +778,50 @@ exec_line (inputline_t *il) } static void -con_keydest_callback (keydest_t kd) +con_end_message (void *line) { - // simply cache the value - con_keydest = kd; + Key_PopEscape (); + Con_ClearTyping (line, 1); + Key_SetKeyDest (key_game); +} + +static void +con_leave_console (void *data) +{ + ToggleConsole_f (); +} + +static void +con_keydest_callback (keydest_t kd, void *data) +{ + if (kd == key_unfocused || kd == con_curr_keydest) { + return; + } + if (kd != key_console && con_curr_keydest == key_console) { + Key_PopEscape (); + } + switch (kd) { + case key_last: + case key_game: + case key_demo: + case key_unfocused: + case key_menu: + break; + case key_message: + Key_PushEscape (con_end_message, + chat_team ? say_team_line : say_line); + break; + case key_console: + Key_PushEscape (con_leave_console, 0); + break; + } + con_curr_keydest = kd; +} + +static void +con_enter_menu (void *data) +{ + Menu_Enter (); } static void @@ -821,7 +833,8 @@ C_Init (void) setlocale (LC_ALL, "C-TRADITIONAL"); #endif - Key_KeydestCallback (con_keydest_callback); + Key_PushEscape (con_enter_menu, 0); + Key_KeydestCallback (con_keydest_callback, 0); Key_SetKeyEvent (key_message, C_KeyEvent, 0); Key_SetKeyEvent (key_menu, C_KeyEvent, 0); Key_SetKeyEvent (key_console, C_KeyEvent, 0); diff --git a/libs/console/menu.c b/libs/console/menu.c index b635fcfaa..d7c48df60 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -779,6 +779,12 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) } } +static void +menu_leave (void *data) +{ + Menu_Leave (); +} + void Menu_Enter () { @@ -789,6 +795,7 @@ Menu_Enter () menu = Hash_Find (menu_hash, top_menu); if (menu) { menu_keydest = Key_GetKeyDest (); + Key_PushEscape (menu_leave, 0); Key_SetKeyDest (key_menu); if (menu->enter_hook) { run_menu_pre (); @@ -809,6 +816,7 @@ Menu_Leave () } menu = menu->parent; if (!menu) { + Key_PopEscape (); Key_SetKeyDest (menu_keydest); } } diff --git a/libs/input/keys.c b/libs/input/keys.c index 1f860f081..2a61122fd 100644 --- a/libs/input/keys.c +++ b/libs/input/keys.c @@ -42,6 +42,7 @@ #include "QF/cbuf.h" #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/darray.h" #include "QF/dstring.h" #include "QF/keys.h" #include "QF/sys.h" @@ -53,13 +54,25 @@ static keydest_t key_dest = key_console; static keytarget_t key_targets[key_last]; -VISIBLE knum_t key_togglemenu = QFK_ESCAPE; VISIBLE knum_t key_toggleconsole = QFK_BACKQUOTE; -#define KEYDEST_CALLBACK_CHUNK 16 -static keydest_callback_t **keydest_callbacks; -static int num_keydest_callbacks; -static int max_keydest_callbacks; +typedef struct { + keydest_callback_t *func; + void *data; +} keydest_callback_item_t; + +typedef struct { + key_escape_t *func; + void *data; +} key_escape_item_t; + +#define CALLBACK_CHUNK 16 +static struct DARRAY_TYPE(keydest_callback_item_t) keydest_callbacks = { + .grow = CALLBACK_CHUNK +}; +static struct DARRAY_TYPE(key_escape_item_t) key_escape_callbacks = { + .grow = CALLBACK_CHUNK +}; VISIBLE int keydown[QFK_LAST]; @@ -614,10 +627,10 @@ Key_SetBinding (imt_t *imt, knum_t keynum, const char *binding) static void Key_CallDestCallbacks (keydest_t kd) { - int i; - - for (i = 0; i < num_keydest_callbacks; i++) - keydest_callbacks[i] (kd); + for (size_t i = 0; i < keydest_callbacks.size; i++) { + keydest_callback_item_t *cb = &keydest_callbacks.a[i]; + cb->func (kd, cb->data); + } } static void @@ -934,23 +947,6 @@ Key_Bind_f (void) } } -static void -in_key_togglemenu_f (cvar_t *var) -{ - int k; - - if (!*var->string) { - key_togglemenu = QFK_ESCAPE; - return; - } - if ((k = Key_StringToKeynum (var->string)) == -1) { - k = QFK_ESCAPE; - Sys_Printf ("\"%s\" is not a valid key. setting to \"K_ESCAPE\"\n", - var->string); - } - key_togglemenu = k; -} - static void in_key_toggleconsole_f (cvar_t *var) { @@ -1116,11 +1112,11 @@ keyhelp_f (void) keyhelp = 1; } -static key_event_t key_event_handlers[key_last] = { }; +static key_event_t *key_event_handlers[key_last] = { }; static void *key_event_data[key_last] = { }; VISIBLE void -Key_SetKeyEvent (keydest_t keydest, key_event_t callback, void *data) +Key_SetKeyEvent (keydest_t keydest, key_event_t *callback, void *data) { if (keydest < 0 || keydest >= key_last) { Sys_Error ("Key_SetKeyEvent: invalid keydest: %d", keydest); @@ -1152,15 +1148,20 @@ Key_Event (knum_t key, short unicode, qboolean down) keydown[key] = 0; } - // handle menu and console toggle keys specially so the user can never - // override or unbind them + // handle the escape key specially so it can never be overridden or + // unbound + if (key == QFK_ESCAPE && keydown[key] == 1) { + if (key_escape_callbacks.size) { + int ind = key_escape_callbacks.size - 1; + key_escape_item_t cb = key_escape_callbacks.a[ind]; + cb.func (cb.data); + } + return; + } //FIXME maybe still a tad over-coupled. Use callbacks for menu and console //toggles? Should keys know anything about menu and console? - if (key_dest != key_menu && key == key_togglemenu && keydown[key] == 1) { - Cbuf_AddText (cbuf, "togglemenu"); - return; - } else if (key_dest != key_console && key == key_toggleconsole - && keydown[key] == 1) { + if (key_dest != key_console && key == key_toggleconsole + && keydown[key] == 1) { Cbuf_AddText (cbuf, "toggleconsole"); return; } @@ -1310,8 +1311,6 @@ Key_Init (cbuf_t *cb) void Key_Init_Cvars (void) { - Cvar_Get ("in_key_togglemenu", "", CVAR_NONE, in_key_togglemenu_f, - "Key for toggling the menu."); Cvar_Get ("in_key_toggleconsole", "K_BACKQUOTE", CVAR_NONE, in_key_toggleconsole_f, "Key for toggling the console."); @@ -1333,8 +1332,10 @@ Key_SetKeyDest(keydest_t kd) Sys_Error ("Bad key_dest: %d", kd); } Sys_MaskPrintf (SYS_input, "Key_SetKeyDest: %s\n", keydest_names[kd]); - key_dest = kd; - Key_CallDestCallbacks (key_dest); + if (key_dest != kd) { + key_dest = kd; + Key_CallDestCallbacks (key_dest); + } } VISIBLE keydest_t @@ -1344,19 +1345,32 @@ Key_GetKeyDest (void) } VISIBLE void -Key_KeydestCallback (keydest_callback_t *callback) +Key_KeydestCallback (keydest_callback_t *callback, void *data) { - if (num_keydest_callbacks == max_keydest_callbacks) { - size_t size = (max_keydest_callbacks + KEYDEST_CALLBACK_CHUNK) - * sizeof (keydest_callback_t *); - keydest_callbacks = realloc (keydest_callbacks, size); - if (!keydest_callbacks) - Sys_Error ("Too many keydest callbacks!"); - max_keydest_callbacks += KEYDEST_CALLBACK_CHUNK; + if (!callback) { + Sys_Error ("null keydest callback"); } - if (!callback) - Sys_Error ("null keydest callback"); - - keydest_callbacks[num_keydest_callbacks++] = callback; + keydest_callback_item_t cb = { callback, data }; + DARRAY_APPEND (&keydest_callbacks, cb); +} + +VISIBLE void +Key_PushEscape (key_escape_t *callback, void *data) +{ + if (!callback) { + Sys_Error ("null escape callback"); + } + + key_escape_item_t cb = { callback, data }; + DARRAY_APPEND (&key_escape_callbacks, cb); +} + +VISIBLE void +Key_PopEscape (void) +{ + if (!key_escape_callbacks.size) { + Sys_Error ("no escape callback to pop"); + } + DARRAY_REMOVE (&key_escape_callbacks); } diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index a2e2a35ce..1cb682416 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -597,7 +597,7 @@ XLateKey (XKeyEvent * ev, int *k, int *u) } static void -x11_keydest_callback (keydest_t key_dest) +x11_keydest_callback (keydest_t key_dest, void *data) { // if (key_dest == key_game) { // XAutoRepeatOff (x_disp); @@ -842,7 +842,7 @@ IN_LL_Init (void) in_mouse_avail = 1; } - Key_KeydestCallback (x11_keydest_callback); + Key_KeydestCallback (x11_keydest_callback, 0); Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, "Paste the contents of X's C&P buffer to the console"); diff --git a/nq/source/host.c b/nq/source/host.c index 53c1e3311..69870013d 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -849,7 +849,7 @@ Host_Init_Memory (void) } static void -host_keydest_callback (keydest_t kd) +host_keydest_callback (keydest_t kd, void *data) { host_in_game = kd == key_game; } @@ -888,7 +888,7 @@ Host_Init (void) Mod_Init (); - Key_KeydestCallback (host_keydest_callback); + Key_KeydestCallback (host_keydest_callback, 0); SV_Init (); diff --git a/nq/source/sbar.c b/nq/source/sbar.c index c51e99ec8..5cbf233b9 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1644,7 +1644,7 @@ Sbar_GIB_Print_Center_f (void) } static void -sbar_keydest_callback (keydest_t kd) +sbar_keydest_callback (keydest_t kd, void *data) { overlay_view->visible = kd == key_game; } @@ -1656,7 +1656,7 @@ Sbar_Init (void) init_views (); - Key_KeydestCallback (sbar_keydest_callback); + Key_KeydestCallback (sbar_keydest_callback, 0); for (i = 0; i < 10; i++) { sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index 0d80842e2..6a854084a 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -59,7 +59,7 @@ GIB_Key_Init (void) } void -Key_KeydestCallback (keydest_callback_t *callback) +Key_KeydestCallback (keydest_callback_t *callback, void *data) { } diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index fbc26b983..da3b5f9e8 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -250,7 +250,7 @@ CL_ChatInfo (int val) } static void -cl_chat_keydest (keydest_t keydest) +cl_chat_keydest (keydest_t keydest, void *data) { switch (keydest) { case key_game: @@ -277,5 +277,5 @@ CL_Chat_Init (void) Cmd_AddCommand ("ignore", CL_Ignore_f, "Ignores chat and name-change messages from a user."); Cmd_AddCommand ("unignore", CL_Unignore_f, "Removes a previously ignored user from the ignore list."); - Key_KeydestCallback (cl_chat_keydest); + Key_KeydestCallback (cl_chat_keydest, 0); } diff --git a/qw/source/sbar.c b/qw/source/sbar.c index ca8d7b74d..373b108c6 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -1941,7 +1941,7 @@ Sbar_GIB_Print_Center_f (void) } static void -sbar_keydest_callback (keydest_t kd) +sbar_keydest_callback (keydest_t kd, void *data) { overlay_view->visible = kd == key_game; } @@ -1953,7 +1953,7 @@ Sbar_Init (void) init_views (); - Key_KeydestCallback (sbar_keydest_callback); + Key_KeydestCallback (sbar_keydest_callback, 0); for (i = 0; i < 10; i++) { sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); From c134e9d3485359ad8335b396d11b9add6cb16921 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jul 2021 12:46:53 +0900 Subject: [PATCH 1660/3664] [renderer] Remove R_EnqueueEntity from the plugin funcs Forgot about this when fixing the ctf flags. --- include/QF/plugin/vid_render.h | 1 - libs/video/renderer/vid_render_gl.c | 1 - libs/video/renderer/vid_render_glsl.c | 1 - libs/video/renderer/vid_render_sw.c | 1 - libs/video/renderer/vid_render_sw32.c | 1 - libs/video/renderer/vid_render_vulkan.c | 1 - 6 files changed, 6 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 98af4aa41..108510771 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -154,7 +154,6 @@ typedef struct vid_render_funcs_s { void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); void (*R_AddEfrags) (mod_brush_t *brush, entity_t *ent); void (*R_RemoveEfrags) (entity_t *ent); - void (*R_EnqueueEntity) (struct entity_s *ent); //FIXME should not be here void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); dlight_t *(*R_AllocDlight) (int key); entity_t *(*R_AllocEntity) (void); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 01f5a5875..f233873df 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -149,7 +149,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_NewMap, R_AddEfrags, R_RemoveEfrags, - R_EnqueueEntity, gl_R_LineGraph, R_AllocDlight, R_AllocEntity, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 64ba6a0e3..c457323e5 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -148,7 +148,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_NewMap, R_AddEfrags, R_RemoveEfrags, - R_EnqueueEntity, glsl_R_LineGraph, R_AllocDlight, R_AllocEntity, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 1be610d2e..eff04211b 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -145,7 +145,6 @@ vid_render_funcs_t sw_vid_render_funcs = { R_NewMap, R_AddEfrags, R_RemoveEfrags, - R_EnqueueEntity, R_LineGraph, R_AllocDlight, R_AllocEntity, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 8e1aba57c..504491b76 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -150,7 +150,6 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_R_NewMap, R_AddEfrags, R_RemoveEfrags, - R_EnqueueEntity, sw32_R_LineGraph, R_AllocDlight, R_AllocEntity, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 1963f4ca8..e2f63867d 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -662,7 +662,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_R_NewMap, R_AddEfrags, R_RemoveEfrags, - R_EnqueueEntity, vulkan_R_LineGraph, R_AllocDlight, R_AllocEntity, From fbbf83e6963ba51b761664ec183e62677a43e4f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jul 2021 21:15:01 +0900 Subject: [PATCH 1661/3664] [console] Pop menu escape in forced close menu Fixes loss of access to the menu after selecting a new game via the menu. --- libs/console/menu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/console/menu.c b/libs/console/menu.c index d7c48df60..7dae05b97 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -377,6 +377,7 @@ bi_Menu_SelectMenu (progs_t *pr) } else { if (name && *name) Sys_Printf ("no menu \"%s\"\n", name); + Key_PopEscape (); Key_SetKeyDest (menu_keydest); } } From 632d2cb79c1236b67987abaeeb303dc4530568d2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 00:28:49 +0900 Subject: [PATCH 1662/3664] [console] Plug another escape handler leak --- libs/console/menu.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libs/console/menu.c b/libs/console/menu.c index 7dae05b97..f9b96fda7 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -359,6 +359,12 @@ bi_Menu_TopMenu (progs_t *pr) top_menu = strdup (name); } +static void +menu_leave (void *data) +{ + Menu_Leave (); +} + static void bi_Menu_SelectMenu (progs_t *pr) { @@ -368,7 +374,11 @@ bi_Menu_SelectMenu (progs_t *pr) if (name && *name) menu = Hash_Find (menu_hash, name); if (menu) { - Key_SetKeyDest (key_menu); + if (Key_GetKeyDest () != key_menu) { + menu_keydest = Key_GetKeyDest (); + Key_PushEscape (menu_leave, 0); + Key_SetKeyDest (key_menu); + } if (menu->enter_hook) { run_menu_pre (); PR_ExecuteProgram (&menu_pr_state, menu->enter_hook); @@ -377,7 +387,7 @@ bi_Menu_SelectMenu (progs_t *pr) } else { if (name && *name) Sys_Printf ("no menu \"%s\"\n", name); - Key_PopEscape (); + Key_PopEscape (); Key_SetKeyDest (menu_keydest); } } @@ -463,6 +473,7 @@ bi_Menu_Leave (progs_t *pr) } menu = menu->parent; if (!menu) { + Key_PopEscape (); Key_SetKeyDest (menu_keydest); } } @@ -780,12 +791,6 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) } } -static void -menu_leave (void *data) -{ - Menu_Leave (); -} - void Menu_Enter () { From c715fb384f992a240a5aef857d169acb4bb2189f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 10:12:24 +0900 Subject: [PATCH 1663/3664] Update .gitignore yet again --- .gitignore | 69 ++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index b3bca858c..25d1878ed 100644 --- a/.gitignore +++ b/.gitignore @@ -5,12 +5,17 @@ *.obj *.a *.o +*.output +*.slc +*.dat +*.sym *~ __pycache__/ autom4te.cache/ .deps/ .libs/ .vimrc +.dirstamp ChangeLog Makefile Makefile.in @@ -104,7 +109,7 @@ core /hw/source/*.d /hw/source/*.i /hw/source/*.s -/hw/source/hw-master +/hw-master # /include/ /include/config.h.in @@ -219,16 +224,9 @@ core /nq/source/fbset_modes_l.c /nq/source/fbset_modes_y.c /nq/source/fbset_modes_y.h -/nq/source/nq-3dfx -/nq/source/nq-fbdev -/nq/source/nq-glslx -/nq/source/nq-glx -/nq/source/nq-sdl -/nq/source/nq-sdl32 -/nq/source/nq-sgl -/nq/source/nq-svga -/nq/source/nq-x11 -/nq/source/nq-server +/nq-sdl +/nq-x11 +/nq-server # /pkg-config/ /pkg-config/*.pc @@ -245,7 +243,7 @@ core /qtv/source/*.d /qtv/source/*.i /qtv/source/*.s -/qtv/source/qtv +/qtv-server # /qw/ @@ -262,17 +260,10 @@ core /qw/source/fbset_modes_l.c /qw/source/fbset_modes_y.c /qw/source/fbset_modes_y.h -/qw/source/qw-client-3dfx -/qw/source/qw-client-fbdev -/qw/source/qw-client-glx -/qw/source/qw-client-glslx -/qw/source/qw-client-sdl -/qw/source/qw-client-sdl32 -/qw/source/qw-client-sgl -/qw/source/qw-client-svga -/qw/source/qw-client-x11 -/qw/source/qw-master -/qw/source/qw-server +/qw-client-sdl +/qw-client-x11 +/qw-master +/qw-server # /ruamoko/ /ruamoko/*.d @@ -281,6 +272,9 @@ core /ruamoko/*.sym /ruamoko/Doxyfile /ruamoko/doxygen/ +/ruamoko/qwaq/qwaq-curses +/ruamoko/qwaq/qwaq-x11 + # /ruamoko/cl_menu/ /ruamoko/cl_menu/*.dat @@ -351,10 +345,10 @@ core /tools/Forge/Bundles/MapEdit/*.app # /tools/bsp2img/ -/tools/bsp2img/bsp2img +/bsp2img # /tools/carne/ -/tools/carne/carne +/carne # /tools/cross/ /tools/cross/binutils-i386-mingw32msvc @@ -370,14 +364,14 @@ core # /tools/pak/ /tools/pak/*.d -/tools/pak/pak +/pak # /tools/qfbsp/ # /tools/qfbsp/include/ # /tools/qfbsp/source/ -/tools/qfbsp/source/qfbsp +/qfbsp # /tools/qfcc/ /tools/qfcc/aclocal.m4 @@ -403,14 +397,11 @@ core /tools/qfcc/source/qc-lex.c /tools/qfcc/source/qc-parse.c /tools/qfcc/source/qc-parse.h -/tools/qfcc/source/qc-parse.output -/tools/qfcc/source/qfcc -/tools/qfcc/source/qfpc -/tools/qfcc/source/qfprogs +/qfcc +/qfprogs /tools/qfcc/source/qp-lex.c /tools/qfcc/source/qp-parse.c /tools/qfcc/source/qp-parse.h -/tools/qfcc/source/qp-parse.output # /tools/qfcc/test/ /tools/qfcc/test/*.dat @@ -421,27 +412,27 @@ core # /tools/qflight/include/ # /tools/qflight/source/ -/tools/qflight/source/qflight +/qflight # /tools/qflmp/ -/tools/qflmp/qflmp +/qflmp # /tools/qfmodelgen/ # /tools/qfmodelgen/include/ # /tools/qfmodelgen/source/ -/tools/qfmodelgen/source/qfmodelgen +/qfmodelgen # /tools/qfspritegen/qfspritegen -/tools/qfspritegen/qfspritegen +/qfspritegen # /tools/qfvis/ # /tools/qfvis/include/ # /tools/qfvis/source/ -/tools/qfvis/source/qfvis +/qfvis # /tools/quaketoascii/ /tools/quaketoascii/quaketoascii @@ -466,8 +457,8 @@ core # /tools/wad/ /tools/wad/*.d -/tools/wad/wad +/wad # /tools/wav/ /tools/wav/*.d -/tools/wav/qfwavinfo +/qfwavinfo From 435009e2cd266fb0c29d01b6c8dd3de39e705279 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 11:31:00 +0900 Subject: [PATCH 1664/3664] [entity] Update local rotation and scale caches When setting local rotation/scale/transform, need to cache the rotation and scale, otherwise they can't be fetched easily later on (position is easy as it's just the fourth column of the matrix). --- libs/entity/transform.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/entity/transform.c b/libs/entity/transform.c index 0e274f83a..b2e4b09da 100644 --- a/libs/entity/transform.c +++ b/libs/entity/transform.c @@ -222,6 +222,7 @@ Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation) mat4f_t mat; mat4fquat (mat, rotation); + h->localRotation.a[transform->index] = rotation; h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; @@ -245,6 +246,7 @@ Transform_SetLocalScale (transform_t *transform, vec4f_t scale) mat4f_t mat; mat4fquat (mat, rotation); + h->localScale.a[transform->index] = scale; h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; @@ -304,6 +306,8 @@ Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, mat4fquat (mat, rotation); position[3] = 1; + h->localRotation.a[transform->index] = rotation; + h->localScale.a[transform->index] = scale; h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; From d3b7f7fbc80efa302e7be4f8cd860fec222a6d3b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 11:33:53 +0900 Subject: [PATCH 1665/3664] [nq,qw] Fix broken intermission view The idle scale was 114.591559 time too big (forgot both half angle for the quaternion and converting from degrees to radians for the idle rotations). Also, take the intermission view position and rotation direct from the player entity, not viewstate, as while viewstate.origin is the same, viewstate.rotation is the player's input, not the rotation set by the server. Fixes the unlocked view angle. --- nq/source/cl_view.c | 12 ++++++++---- qw/source/cl_view.c | 8 ++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index d21f267b1..c82b495ca 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -516,8 +516,8 @@ idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level) } float scale = sin (cl.time * cycle->value); float ang = scale * level->value * v_idlescale->value; - float c = cos (ang); - float s = sin (ang); + float c = cos (ang * M_PI / 360); + float s = sin (ang * M_PI / 360); return axis * s + identity * c; } @@ -578,14 +578,18 @@ V_CalcViewRoll (void) static void V_CalcIntermissionRefdef (void) { + // ent is the player model (visible when out of body) + entity_t *ent = &cl_entities[cl.viewentity]; entity_t *view; float old; + vec4f_t origin = Transform_GetWorldPosition (ent->transform); + vec4f_t rotation = Transform_GetWorldRotation (ent->transform); // view is the weapon model (visible only from inside body) view = &cl.viewent; - r_data->refdef->viewposition = cl.viewstate.origin; - AngleQuat (cl.viewstate.angles, &r_data->refdef->viewrotation[0]);//FIXME + r_data->refdef->viewposition = origin; + r_data->refdef->viewrotation = rotation; view->renderer.model = NULL; // always idle in intermission diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 0da8c09cc..cf6a51251 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -580,14 +580,18 @@ V_CalcViewRoll (void) static void V_CalcIntermissionRefdef (void) { + entity_t *ent = &cl_entities[cl.viewentity]; entity_t *view; float old; + vec4f_t origin = Transform_GetWorldPosition (ent->transform); + vec4f_t rotation = Transform_GetWorldRotation (ent->transform); // view is the weapon model (visible only from inside body) view = &cl.viewent; - r_data->refdef->viewposition = cl.viewstate.origin; - AngleQuat (cl.viewstate.angles, &r_data->refdef->viewrotation[0]);//FIXME + r_data->refdef->viewposition = origin; + r_data->refdef->viewrotation = rotation; + view->renderer.model = NULL; view->renderer.model = NULL; // always idle in intermission From 076f424d39dc131e7721e11f63964704484b9e37 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 11:38:28 +0900 Subject: [PATCH 1666/3664] [qw] Actually fix the idle scale Oops. I really need to get cl_view merged. --- qw/source/cl_view.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index cf6a51251..313a920b7 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -518,8 +518,8 @@ idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level) } float scale = sin (cl.time * cycle->value); float ang = scale * level->value * v_idlescale->value; - float c = cos (ang); - float s = sin (ang); + float c = cos (ang * M_PI / 360); + float s = sin (ang * M_PI / 360); return axis * s + identity * c; } From 40a26e4bc8a5f20b3364ef3ba73cb50b8d05cb2d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 14:19:52 +0900 Subject: [PATCH 1667/3664] [scene] Rename libQFentity to libQFscene And start working on scene management. --- config.d/build_control.m4 | 2 + include/QF/Makemodule.am | 11 ++- include/QF/scene/entity.h | 51 +++++++++++ include/QF/scene/hierarchy.h | 76 +++++++++++++++++ include/QF/scene/scene.h | 63 ++++++++++++++ include/QF/{entity.h => scene/transform.h} | 53 ++---------- include/QF/scene/types.h | 54 ++++++++++++ libs/Makemodule.am | 2 +- libs/client/cl_effects.c | 2 +- libs/client/cl_entities.c | 2 +- libs/client/cl_temp_entities.c | 2 +- libs/entity/Makemodule.am | 12 --- libs/entity/test/Makemodule.am | 17 ---- libs/scene/Makemodule.am | 13 +++ libs/{entity => scene}/hierarchy.c | 3 +- libs/scene/scene.c | 89 ++++++++++++++++++++ libs/scene/test/Makemodule.am | 17 ++++ libs/{entity => scene}/test/test-hierarchy.c | 3 +- libs/{entity => scene}/transform.c | 4 +- libs/video/renderer/gl/gl_dyn_part.c | 4 +- libs/video/renderer/gl/gl_lightmap.c | 4 +- libs/video/renderer/gl/gl_mod_alias.c | 4 +- libs/video/renderer/gl/gl_mod_sprite.c | 9 +- libs/video/renderer/gl/gl_rmain.c | 4 +- libs/video/renderer/gl/gl_rsurf.c | 4 +- libs/video/renderer/glsl/glsl_alias.c | 3 +- libs/video/renderer/glsl/glsl_bsp.c | 3 +- libs/video/renderer/glsl/glsl_iqm.c | 3 +- libs/video/renderer/glsl/glsl_lightmap.c | 3 +- libs/video/renderer/glsl/glsl_particles.c | 4 +- libs/video/renderer/glsl/glsl_sprite.c | 3 +- libs/video/renderer/r_efrag.c | 3 +- libs/video/renderer/r_ent.c | 3 +- libs/video/renderer/sw/d_edge.c | 3 +- libs/video/renderer/sw/sw_ralias.c | 3 +- libs/video/renderer/sw/sw_rbsp.c | 3 +- libs/video/renderer/sw/sw_riqm.c | 3 +- libs/video/renderer/sw/sw_rmain.c | 3 +- libs/video/renderer/sw/sw_rpart.c | 3 +- libs/video/renderer/sw/sw_rsprite.c | 3 +- libs/video/renderer/sw/sw_rsurf.c | 3 +- libs/video/renderer/sw32/d_edge.c | 3 +- libs/video/renderer/sw32/sw32_ralias.c | 3 +- libs/video/renderer/sw32/sw32_rbsp.c | 3 +- libs/video/renderer/sw32/sw32_riqm.c | 3 +- libs/video/renderer/sw32/sw32_rmain.c | 3 +- libs/video/renderer/sw32/sw32_rpart.c | 3 +- libs/video/renderer/sw32/sw32_rsprite.c | 3 +- libs/video/renderer/sw32/sw32_rsurf.c | 3 +- libs/video/renderer/vulkan/vulkan_alias.c | 3 +- libs/video/renderer/vulkan/vulkan_bsp.c | 3 +- libs/video/renderer/vulkan/vulkan_lightmap.c | 3 +- nq/source/Makemodule.am | 2 +- nq/source/cl_ents.c | 2 +- nq/source/cl_main.c | 2 +- nq/source/cl_parse.c | 2 +- nq/source/cl_view.c | 2 +- qw/include/client.h | 2 +- qw/source/Makemodule.am | 2 +- qw/source/cl_ents.c | 3 +- ruamoko/qwaq/Makemodule.am | 2 +- 61 files changed, 478 insertions(+), 128 deletions(-) create mode 100644 include/QF/scene/entity.h create mode 100644 include/QF/scene/hierarchy.h create mode 100644 include/QF/scene/scene.h rename include/QF/{entity.h => scene/transform.h} (70%) create mode 100644 include/QF/scene/types.h delete mode 100644 libs/entity/Makemodule.am delete mode 100644 libs/entity/test/Makemodule.am create mode 100644 libs/scene/Makemodule.am rename libs/{entity => scene}/hierarchy.c (99%) create mode 100644 libs/scene/scene.c create mode 100644 libs/scene/test/Makemodule.am rename libs/{entity => scene}/test/test-hierarchy.c (99%) rename libs/{entity => scene}/transform.c (99%) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index c67317496..1fb6f3d9b 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -324,6 +324,7 @@ if test x"${top_need_libs}" = xyes; then qfac_include_qf_glsl="\$(include_qf_glsl)" qfac_include_qf_math="\$(include_qf_math)" qfac_include_qf_plugin="\$(include_qf_plugin)" + qfac_include_qf_scene="\$(include_qf_scene)" qfac_include_qf_simd="\$(include_qf_simd)" qfac_include_qf_vulkan="\$(include_qf_vulkan)" fi @@ -332,6 +333,7 @@ QF_SUBST(qfac_include_qf_gl) QF_SUBST(qfac_include_qf_glsl) QF_SUBST(qfac_include_qf_math) QF_SUBST(qfac_include_qf_plugin) +QF_SUBST(qfac_include_qf_scene) QF_SUBST(qfac_include_qf_simd) QF_SUBST(qfac_include_qf_vulkan) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 4c6d20451..e0f9ebb07 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -15,7 +15,6 @@ include_qf = \ include/QF/darray.h \ include/QF/dstring.h \ include/QF/draw.h \ - include/QF/entity.h \ include/QF/fbsearch.h \ include/QF/gib.h \ include/QF/hash.h \ @@ -126,6 +125,13 @@ include_qf_plugin = \ include/QF/plugin/snd_render.h \ include/QF/plugin/vid_render.h +include_qf_scene = \ + include/QF/scene/entity.h \ + include/QF/scene/hierarchy.h \ + include/QF/scene/transform.h \ + include/QF/scene/scene.h \ + include/QF/scene/types.h + include_qf_simd = \ include/QF/simd/mat4f.h \ include/QF/simd/types.h \ @@ -179,6 +185,7 @@ qf_gl_includedir = $(includedir)/QF/GL qf_glsl_includedir = $(includedir)/QF/GLSL qf_math_includedir = $(includedir)/QF/math qf_plugin_includedir = $(includedir)/QF/plugin +qf_scene_includedir = $(includedir)/QF/scene qf_simd_includedir = $(includedir)/QF/simd qf_vulkan_includedir = $(includedir)/QF/Vulkan qf_include_HEADERS = @qfac_include_qf@ @@ -186,6 +193,7 @@ qf_gl_include_HEADERS = @qfac_include_qf_gl@ qf_glsl_include_HEADERS = @qfac_include_qf_glsl@ qf_math_include_HEADERS = @qfac_include_qf_math@ qf_plugin_include_HEADERS = @qfac_include_qf_plugin@ +qf_scene_include_HEADERS = @qfac_include_qf_scene@ qf_simd_include_HEADERS = @qfac_include_qf_simd@ qf_vulkan_include_HEADERS = @qfac_include_qf_vulkan@ @@ -198,6 +206,7 @@ EXTRA_HEADERS += \ $(include_qf_glsl) \ $(include_qf_math) \ $(include_qf_plugin) \ + $(include_qf_scene) \ $(include_qf_simd) \ $(include_qf_vulkan) \ $(qfcc_include_qf) diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h new file mode 100644 index 000000000..f6bd82e4b --- /dev/null +++ b/include/QF/scene/entity.h @@ -0,0 +1,51 @@ +/* + entity.h + + Entity management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/02/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_scene_entity_h +#define __QF_scene_entity_h + +#include "QF/darray.h" +#include "QF/qtypes.h" +#include "QF/simd/vec4f.h" +#include "QF/simd/mat4f.h" + +/** \defgroup scene_entity Entity management + \ingroup scene +*/ +///@{ + +#include "QF/scene/hierarchy.h" +#include "QF/scene/transform.h" + +#include "QF/render.h" //FIXME move entity_t here + +///@} + +#endif//__QF_scene_entity_h diff --git a/include/QF/scene/hierarchy.h b/include/QF/scene/hierarchy.h new file mode 100644 index 000000000..24c46df0a --- /dev/null +++ b/include/QF/scene/hierarchy.h @@ -0,0 +1,76 @@ +/* + hierarch.h + + Hierarchy management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/02/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_scene_hierarch_h +#define __QF_scene_hierarch_h + +#include "QF/darray.h" +#include "QF/qtypes.h" +#include "QF/scene/types.h" +#include "QF/simd/vec4f.h" +#include "QF/simd/mat4f.h" + +/** \defgroup entity Hierarchy management + \ingroup utils +*/ +///@{ + +#define null_transform (~0u) + +typedef struct hierarchy_s { + xformset_t transform; + entityset_t entity; + uint32set_t childCount; + uint32set_t childIndex; + uint32set_t parentIndex; + stringset_t name; + uint32set_t tag; + byteset_t modified; + mat4fset_t localMatrix; + mat4fset_t localInverse; + mat4fset_t worldMatrix; + mat4fset_t worldInverse; + vec4fset_t localRotation; + vec4fset_t localScale; + vec4fset_t worldRotation; + vec4fset_t worldScale; +} hierarchy_t; + +hierarchy_t *Hierarchy_New (size_t grow, int createRoot); +hierarchy_t *Hierarchy_Copy (hierarchy_t *src); +void Hierarchy_Delete (hierarchy_t *hierarchy); + +void Hierarchy_UpdateMatrices (hierarchy_t *hierarchy); +uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstParent, uint32_t srcRoot); +void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); +///@} + +#endif//__QF_scene_hierarch_h diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h new file mode 100644 index 000000000..cab3110e0 --- /dev/null +++ b/include/QF/scene/scene.h @@ -0,0 +1,63 @@ +/* + scene.h + + Entity management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/02/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_scene_scene_h +#define __QF_scene_scene_h + +#include "QF/darray.h" + +#include "QF/scene/types.h" + +/** \defgroup scene Scene management + \ingroup utils +*/ +///@{ + +typedef struct hierarchyset_s DARRAY_TYPE (struct hierarchy_s *) + hierarchyset_t; +typedef struct visibilityset_s DARRAY_TYPE (struct visibility_s *) + visibilityset_t; + +typedef struct scene_s { + struct scene_resources_s *const resources; + hierarchyset_t roots; + xformset_t transforms; + entityset_t entities; + visibilityset_t visibility; +} scene_t; + +scene_t *Scene_NewScene (void); +struct entity_s *Scene_CreateEntity (scene_t *scene); +void Scene_FreeAllEntities (scene_t *scene); + + +///@} + +#endif//__QF_scene_scene_h diff --git a/include/QF/entity.h b/include/QF/scene/transform.h similarity index 70% rename from include/QF/entity.h rename to include/QF/scene/transform.h index 032db67a2..2a015ff36 100644 --- a/include/QF/entity.h +++ b/include/QF/scene/transform.h @@ -1,7 +1,7 @@ /* - entity.h + transform.h - Entity management + Transform management Copyright (C) 2021 Bill Currie @@ -28,50 +28,21 @@ */ -#ifndef __QF_entity_h -#define __QF_entity_h +#ifndef __QF_scene_transform_h +#define __QF_scene_transform_h #include "QF/darray.h" -#include "QF/mathlib.h" +#include "QF/qtypes.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" -/** \defgroup entity Entity management +/** \defgroup transform Transform management \ingroup utils */ ///@{ -typedef struct mat4fset_s DARRAY_TYPE (mat4f_t) mat4fset_t; -typedef struct vec4fset_s DARRAY_TYPE (vec4f_t) vec4fset_t; -typedef struct uint32set_s DARRAY_TYPE (uint32_t) uint32set_t; -typedef struct byteset_s DARRAY_TYPE (byte) byteset_t; -typedef struct stringset_s DARRAY_TYPE (char *) stringset_t; -typedef struct xformset_s DARRAY_TYPE (struct transform_s *) xformset_t; -typedef struct entityset_s DARRAY_TYPE (struct entity_s *) entityset_t; - -#define null_transform (~0u) - -typedef struct hierarchy_s { - xformset_t transform; - entityset_t entity; - uint32set_t childCount; - uint32set_t childIndex; - uint32set_t parentIndex; - stringset_t name; - uint32set_t tag; - byteset_t modified; - mat4fset_t localMatrix; - mat4fset_t localInverse; - mat4fset_t worldMatrix; - mat4fset_t worldInverse; - vec4fset_t localRotation; - vec4fset_t localScale; - vec4fset_t worldRotation; - vec4fset_t worldScale; -} hierarchy_t; - typedef struct transform_s { - hierarchy_t *hierarchy; + struct hierarchy_s *hierarchy; uint32_t index; } transform_t; @@ -111,14 +82,6 @@ vec4f_t Transform_Right (const transform_t *transform) __attribute__((pure)); vec4f_t Transform_Up (const transform_t *transform) __attribute__((pure)); // no SetWorldScale because after rotations, non uniform scale becomes shear -hierarchy_t *Hierarchy_New (size_t grow, int createRoot); -hierarchy_t *Hierarchy_Copy (hierarchy_t *src); -void Hierarchy_Delete (hierarchy_t *hierarchy); - -void Hierarchy_UpdateMatrices (hierarchy_t *hierarchy); -uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, - uint32_t dstParent, uint32_t srcRoot); -void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); ///@} -#endif//__QF_entity_h +#endif//__QF_scene_transform_h diff --git a/include/QF/scene/types.h b/include/QF/scene/types.h new file mode 100644 index 000000000..550262302 --- /dev/null +++ b/include/QF/scene/types.h @@ -0,0 +1,54 @@ +/* + types.h + + Entity management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/02/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_scene_types_h +#define __QF_scene_types_h + +#include "QF/darray.h" +#include "QF/qtypes.h" +#include "QF/simd/vec4f.h" +#include "QF/simd/mat4f.h" + +/** \defgroup scene_types Scene type definitions + \ingroup scene +*/ +///@{ + +typedef struct mat4fset_s DARRAY_TYPE (mat4f_t) mat4fset_t; +typedef struct vec4fset_s DARRAY_TYPE (vec4f_t) vec4fset_t; +typedef struct uint32set_s DARRAY_TYPE (uint32_t) uint32set_t; +typedef struct byteset_s DARRAY_TYPE (byte) byteset_t; +typedef struct stringset_s DARRAY_TYPE (char *) stringset_t; +typedef struct xformset_s DARRAY_TYPE (struct transform_s *) xformset_t; +typedef struct entityset_s DARRAY_TYPE (struct entity_s *) entityset_t; + +///@} + +#endif//__QF_scene_types_h diff --git a/libs/Makemodule.am b/libs/Makemodule.am index 035f65926..4dcdc3b36 100644 --- a/libs/Makemodule.am +++ b/libs/Makemodule.am @@ -9,7 +9,7 @@ include libs/models/Makemodule.am include libs/input/Makemodule.am include libs/video/Makemodule.am include libs/console/Makemodule.am -include libs/entity/Makemodule.am +include libs/scene/Makemodule.am include libs/net/Makemodule.am include libs/client/Makemodule.am diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index 707699141..c4e66c7ff 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -38,10 +38,10 @@ # include #endif -#include "QF/entity.h" #include "QF/render.h" #include "QF/plugin/vid_render.h" //FIXME +#include "QF/scene/entity.h" #include "client/entities.h" #include "client/effects.h" diff --git a/libs/client/cl_entities.c b/libs/client/cl_entities.c index 599576863..4403a49bd 100644 --- a/libs/client/cl_entities.c +++ b/libs/client/cl_entities.c @@ -31,8 +31,8 @@ # include "config.h" #endif -#include "QF/entity.h" #include "QF/render.h" //FIXME for entity_t +#include "QF/scene/entity.h" #include "QF/simd/vec4f.h" #include "client/entities.h" diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index fdffbf985..2fe2255c9 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -38,7 +38,6 @@ # include #endif -#include "QF/entity.h" #include "QF/msg.h" #include "QF/progs.h" // for PR_RESMAP #include "QF/quakefs.h" @@ -46,6 +45,7 @@ #include "QF/sound.h" #include "QF/plugin/vid_render.h" //FIXME +#include "QF/scene/entity.h" #include "client/entities.h" #include "client/temp_entities.h" diff --git a/libs/entity/Makemodule.am b/libs/entity/Makemodule.am deleted file mode 100644 index 58dc1f08c..000000000 --- a/libs/entity/Makemodule.am +++ /dev/null @@ -1,12 +0,0 @@ -include libs/entity/test/Makemodule.am - -entity_deps=libs/util/libQFutil.la - -lib_LTLIBRARIES += libs/entity/libQFentity.la - -libs_entity_libQFentity_la_LDFLAGS= $(lib_ldflags) -libs_entity_libQFentity_la_LIBADD= $(entity_deps) -libs_entity_libQFentity_la_DEPENDENCIES= $(entity_deps) -libs_entity_libQFentity_la_SOURCES= \ - libs/entity/hierarchy.c \ - libs/entity/transform.c diff --git a/libs/entity/test/Makemodule.am b/libs/entity/test/Makemodule.am deleted file mode 100644 index be280abe9..000000000 --- a/libs/entity/test/Makemodule.am +++ /dev/null @@ -1,17 +0,0 @@ -libs_entity_tests = \ - libs/entity/test/test-hierarchy - -TESTS += $(libs_entity_tests) - -check_PROGRAMS += $(libs_entity_tests) - -libs_entity_test_libs= \ - libs/entity/libQFentity.la \ - libs/util/libQFutil.la - -libs_entity_test_test_hierarchy_SOURCES= \ - libs/entity/test/test-hierarchy.c -libs_entity_test_test_hierarchy_LDADD= \ - $(libs_entity_test_libs) -libs_entity_test_test_hierarchy_DEPENDENCIES= \ - $(libs_entity_test_libs) diff --git a/libs/scene/Makemodule.am b/libs/scene/Makemodule.am new file mode 100644 index 000000000..eaf988539 --- /dev/null +++ b/libs/scene/Makemodule.am @@ -0,0 +1,13 @@ +include libs/scene/test/Makemodule.am + +scene_deps=libs/util/libQFutil.la + +lib_LTLIBRARIES += libs/scene/libQFscene.la + +libs_scene_libQFscene_la_LDFLAGS= $(lib_ldflags) +libs_scene_libQFscene_la_LIBADD= $(scene_deps) +libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps) +libs_scene_libQFscene_la_SOURCES= \ + libs/scene/hierarchy.c \ + libs/scene/scene.c \ + libs/scene/transform.c diff --git a/libs/entity/hierarchy.c b/libs/scene/hierarchy.c similarity index 99% rename from libs/entity/hierarchy.c rename to libs/scene/hierarchy.c index 39d4ed971..43c3ea598 100644 --- a/libs/entity/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -35,7 +35,8 @@ # include #endif -#include "QF/entity.h" +#include "QF/scene/hierarchy.h" +#include "QF/scene/transform.h" #if defined(_WIN32) && !defined(_WIN64) // FIXME (maybe) this is a hack to make DARRAY arrrays 16-byte aligned on diff --git a/libs/scene/scene.c b/libs/scene/scene.c new file mode 100644 index 000000000..421021b7c --- /dev/null +++ b/libs/scene/scene.c @@ -0,0 +1,89 @@ +/* + scene.c + + General scene handling + + Copyright (C) 2021 Bill Currke + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/progs.h" // for PR_RESMAP + +#include "QF/scene/entity.h" +#include "QF/scene/scene.h" +#include "QF/scene/transform.h" + +typedef struct scene_resources_s { + PR_RESMAP (entity_t) entities; +} scene_resources_t; + +scene_t * +Scene_NewScene (void) +{ + scene_t *scene; + scene_resources_t *res; + + scene = calloc (1, sizeof (scene_t)); + res = calloc (1, sizeof (scene_resources_t)); + *(scene_resources_t **)&scene->resources = res; + + DARRAY_INIT (&scene->roots, 16); + DARRAY_INIT (&scene->transforms, 16); + DARRAY_INIT (&scene->entities, 16); + DARRAY_INIT (&scene->visibility, 16); + + return scene; +} + +entity_t * +Scene_CreateEntity (scene_t *scene) +{ + scene_resources_t *res = scene->resources; + + entity_t *ent = PR_RESNEW_NC (res->entities); + ent->transform = 0; + DARRAY_APPEND (&scene->entities, ent); + return ent; +} + +void +Scene_FreeAllEntities (scene_t *scene) +{ + scene_resources_t *res = scene->resources; + for (size_t i = 0; i < scene->entities.size; i++) { + entity_t *ent = scene->entities.a[i]; + if (ent->transform) { + Transform_Delete (ent->transform); + ent->transform = 0; + } + } + PR_RESRESET (res->entities); +} diff --git a/libs/scene/test/Makemodule.am b/libs/scene/test/Makemodule.am new file mode 100644 index 000000000..76f5c9dcf --- /dev/null +++ b/libs/scene/test/Makemodule.am @@ -0,0 +1,17 @@ +libs_scene_tests = \ + libs/scene/test/test-hierarchy + +TESTS += $(libs_scene_tests) + +check_PROGRAMS += $(libs_scene_tests) + +libs_scene_test_libs= \ + libs/scene/libQFscene.la \ + libs/util/libQFutil.la + +libs_scene_test_test_hierarchy_SOURCES= \ + libs/scene/test/test-hierarchy.c +libs_scene_test_test_hierarchy_LDADD= \ + $(libs_scene_test_libs) +libs_scene_test_test_hierarchy_DEPENDENCIES= \ + $(libs_scene_test_libs) diff --git a/libs/entity/test/test-hierarchy.c b/libs/scene/test/test-hierarchy.c similarity index 99% rename from libs/entity/test/test-hierarchy.c rename to libs/scene/test/test-hierarchy.c index 428dfcc5c..b6a3c0ca8 100644 --- a/libs/entity/test/test-hierarchy.c +++ b/libs/scene/test/test-hierarchy.c @@ -6,7 +6,8 @@ #include #include -#include "QF/entity.h" +#include "QF/scene/hierarchy.h" +#include "QF/scene/transform.h" // NOTE: these are the columns of the matrix! (not that it matters for a // symmetrical matrix, but...) diff --git a/libs/entity/transform.c b/libs/scene/transform.c similarity index 99% rename from libs/entity/transform.c rename to libs/scene/transform.c index b2e4b09da..c5919c097 100644 --- a/libs/entity/transform.c +++ b/libs/scene/transform.c @@ -35,8 +35,8 @@ # include #endif -#include "QF/entity.h" -#include "QF/render.h" +#include "QF/scene/hierarchy.h" +#include "QF/scene/transform.h" transform_t * Transform_New (transform_t *parent) diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 678e4e72c..b82785660 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -42,13 +42,15 @@ #include "QF/cmd.h" #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/mersenne.h" #include "QF/qargs.h" #include "QF/quakefs.h" #include "QF/render.h" #include "QF/sys.h" #include "QF/va.h" + +#include "QF/scene/entity.h" + #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_explosions.h" diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 8456b5619..3251a5913 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -43,9 +43,11 @@ #include #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" + +#include "QF/scene/entity.h" + #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_lightmap.h" diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 03d403fa9..18ef24320 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -43,7 +43,6 @@ #include #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/render.h" @@ -51,6 +50,9 @@ #include "QF/sound.h" #include "QF/sys.h" #include "QF/vid.h" + +#include "QF/scene/entity.h" + #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_rlight.h" diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index 2aa41ac5e..d25bec868 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -38,14 +38,15 @@ # include #endif -#include "QF/GL/defines.h" -#include "QF/GL/funcs.h" - -#include "QF/entity.h" #include "QF/model.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + +#include "QF/GL/defines.h" +#include "QF/GL/funcs.h" + #include "compat.h" #include "r_internal.h" #include "varrays.h" diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 617eb9206..b3dfe0c1a 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -44,7 +44,6 @@ #include "QF/cvar.h" #include "QF/draw.h" -#include "QF/entity.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/render.h" @@ -52,6 +51,9 @@ #include "QF/sound.h" #include "QF/sys.h" #include "QF/vid.h" + +#include "QF/scene/entity.h" + #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_draw.h" diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index e3c4187d1..654751fff 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -45,9 +45,11 @@ #include #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" + +#include "QF/scene/entity.h" + #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_lightmap.h" diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index bb8e2a541..d7025fe72 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -43,11 +43,12 @@ #include #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" #include "QF/GLSL/qf_alias.h" diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 24f3c230c..04caf310c 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -46,12 +46,13 @@ #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/entity.h" + #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" #include "QF/GLSL/qf_bsp.h" diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index eeba3f572..2e66e8f74 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -43,11 +43,12 @@ #include #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" #include "QF/GLSL/qf_iqm.h" diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index f50340d5b..750858251 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -44,10 +44,11 @@ #endif #include -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" #include "QF/GLSL/qf_lightmap.h" diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index da96477a7..b8bdf56ca 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -42,7 +42,6 @@ #include "QF/cmd.h" #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/image.h" #include "QF/mersenne.h" #include "QF/qargs.h" @@ -50,6 +49,9 @@ #include "QF/render.h" #include "QF/sys.h" #include "QF/va.h" + +#include "QF/scene/entity.h" + #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" //#include "QF/GL/qf_explosions.h" diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 66b30485d..a56a2fd83 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -42,13 +42,14 @@ #endif #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/draw.h" #include "QF/dstring.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/vid.h" +#include "QF/scene/entity.h" + #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" #include "QF/GLSL/qf_sprite.h" diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index eb559e9cd..4ee676d86 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -30,10 +30,11 @@ #include -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "qfalloca.h" #include "r_internal.h" diff --git a/libs/video/renderer/r_ent.c b/libs/video/renderer/r_ent.c index 2ce315206..303053800 100644 --- a/libs/video/renderer/r_ent.c +++ b/libs/video/renderer/r_ent.c @@ -38,13 +38,14 @@ #include #include -#include "QF/entity.h" #include "QF/model.h" #include "QF/msg.h" #include "QF/render.h" #include "QF/sound.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "r_internal.h" #define ENT_POOL_SIZE 32 diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index d1e8a4e29..59963dc3a 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -29,9 +29,10 @@ #endif #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/render.h" +#include "QF/scene/entity.h" + #include "d_local.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index dd545debc..023c5e039 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -30,12 +30,13 @@ #include -#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "d_ifacea.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index e9b3fde8a..3d726766c 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -33,10 +33,11 @@ #include "qfalloca.h" -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "r_internal.h" // current entity info diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index 8674e3ca6..d2ed9e79c 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -40,12 +40,13 @@ #include #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "d_ifacea.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 12a47c285..e21713984 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -42,13 +42,14 @@ #include "QF/cmd.h" #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/mathlib.h" #include "QF/render.h" #include "QF/screen.h" #include "QF/sound.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "compat.h" #include "mod_internal.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index c429279b2..8dc268955 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -37,7 +37,6 @@ #endif #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/mersenne.h" #include "QF/qargs.h" #include "QF/quakefs.h" @@ -45,6 +44,8 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/entity.h" + #include "compat.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 6a70d2f4f..82c7b0d1b 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -37,10 +37,11 @@ #include -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "r_internal.h" static int clip_current; diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 36ea5fe79..106dd8f29 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -28,10 +28,11 @@ # include "config.h" #endif -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "r_internal.h" #ifdef PIC diff --git a/libs/video/renderer/sw32/d_edge.c b/libs/video/renderer/sw32/d_edge.c index adcc62981..38ee43f63 100644 --- a/libs/video/renderer/sw32/d_edge.c +++ b/libs/video/renderer/sw32/d_edge.c @@ -32,10 +32,11 @@ #include "namehack.h" #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "d_local.h" #include "r_internal.h" #include "vid_internal.h" diff --git a/libs/video/renderer/sw32/sw32_ralias.c b/libs/video/renderer/sw32/sw32_ralias.c index 3a73a56db..fa7c56552 100644 --- a/libs/video/renderer/sw32/sw32_ralias.c +++ b/libs/video/renderer/sw32/sw32_ralias.c @@ -33,12 +33,13 @@ #define NH_DEFINE #include "namehack.h" -#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "d_ifacea.h" #include "r_internal.h" #include "vid_sw.h" diff --git a/libs/video/renderer/sw32/sw32_rbsp.c b/libs/video/renderer/sw32/sw32_rbsp.c index 1f62b381e..44ae8122f 100644 --- a/libs/video/renderer/sw32/sw32_rbsp.c +++ b/libs/video/renderer/sw32/sw32_rbsp.c @@ -36,10 +36,11 @@ #include "qfalloca.h" -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "r_internal.h" // current entity info diff --git a/libs/video/renderer/sw32/sw32_riqm.c b/libs/video/renderer/sw32/sw32_riqm.c index 1db5fbbdc..193d28216 100644 --- a/libs/video/renderer/sw32/sw32_riqm.c +++ b/libs/video/renderer/sw32/sw32_riqm.c @@ -43,12 +43,13 @@ #include "namehack.h" #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "d_ifacea.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 8da2648b2..5377911ae 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -42,13 +42,14 @@ #include "QF/cmd.h" #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/mathlib.h" #include "QF/render.h" #include "QF/screen.h" #include "QF/sound.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "compat.h" #include "mod_internal.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 851618819..45e48a9ed 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -40,7 +40,6 @@ #endif #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/mersenne.h" #include "QF/qargs.h" #include "QF/quakefs.h" @@ -48,6 +47,8 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/entity.h" + #include "compat.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw32/sw32_rsprite.c b/libs/video/renderer/sw32/sw32_rsprite.c index bbdc1996f..153fba1fb 100644 --- a/libs/video/renderer/sw32/sw32_rsprite.c +++ b/libs/video/renderer/sw32/sw32_rsprite.c @@ -40,10 +40,11 @@ #include -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "r_internal.h" static int clip_current; diff --git a/libs/video/renderer/sw32/sw32_rsurf.c b/libs/video/renderer/sw32/sw32_rsurf.c index 2bfb5c000..dac3e2173 100644 --- a/libs/video/renderer/sw32/sw32_rsurf.c +++ b/libs/video/renderer/sw32/sw32_rsurf.c @@ -31,10 +31,11 @@ #define NH_DEFINE #include "namehack.h" -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "compat.h" #include "r_internal.h" #include "vid_sw.h" diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 83c0a5e0a..91413f41c 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -45,13 +45,14 @@ #include "QF/cvar.h" #include "QF/darray.h" -#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/entity.h" + #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index ac22d1034..7bfe34fff 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -45,12 +45,13 @@ #include "QF/cvar.h" #include "QF/darray.h" -#include "QF/entity.h" #include "QF/image.h" #include "QF/render.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/entity.h" + #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_texture.h" diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 3cfbcb7ba..7e6a61cef 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -41,7 +41,6 @@ #include #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/render.h" #include "QF/sys.h" #include "QF/Vulkan/qf_bsp.h" @@ -49,6 +48,8 @@ #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/scrap.h" +#include "QF/scene/entity.h" + #include "compat.h" #include "r_internal.h" #include "vid_vulkan.h" diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 45beb5b0e..0cfd9b915 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -46,7 +46,7 @@ nq_cl_plugin_LIBS= \ nq_client_LIBFILES= \ libs/gib/libQFgib_client.la \ - libs/entity/libQFentity.la \ + libs/scene/libQFscene.la \ libs/video/targets/libQFjs.la \ libs/audio/libQFcd.la \ libs/audio/libQFsound.la diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 79a0f9234..1bfae5670 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -32,7 +32,6 @@ #include "QF/cmd.h" #include "QF/console.h" #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/input.h" #include "QF/keys.h" #include "QF/msg.h" @@ -44,6 +43,7 @@ #include "QF/va.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/entity.h" #include "compat.h" diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 88b7a78bb..c05570794 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -34,7 +34,6 @@ #include "QF/console.h" #include "QF/cvar.h" #include "QF/draw.h" -#include "QF/entity.h" #include "QF/input.h" #include "QF/joystick.h" #include "QF/keys.h" @@ -48,6 +47,7 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/entity.h" #include "compat.h" #include "sbar.h" diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index f511ec70e..a9078edd8 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -41,7 +41,6 @@ #include "QF/console.h" #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/entity.h" #include "QF/idparse.h" #include "QF/input.h" #include "QF/msg.h" @@ -53,6 +52,7 @@ #include "QF/va.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/entity.h" #include "client/temp_entities.h" diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index c82b495ca..ca8b2dd1a 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -30,13 +30,13 @@ #include "QF/cmd.h" #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/msg.h" #include "QF/screen.h" #include "QF/simd/vec4f.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/entity.h" #include "compat.h" diff --git a/qw/include/client.h b/qw/include/client.h index 9ccfaf551..eb78c5a8c 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -28,13 +28,13 @@ #ifndef _CLIENT_H #define _CLIENT_H -#include "QF/entity.h" #include "QF/info.h" #include "QF/quakefs.h" #include "QF/vid.h" #include "QF/zone.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/entity.h" #include "client/entities.h" #include "client/state.h" diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 95ccd1a67..f5335692f 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -89,7 +89,7 @@ qw_client_LIBS= \ libs/qw/libqw.a \ libs/gib/libQFgib_client.la \ libs/net/libnet_chan.la \ - libs/entity/libQFentity.la \ + libs/scene/libQFscene.la \ libs/console/libQFconsole.la \ libs/video/targets/libQFjs.la \ libs/audio/libQFcd.la \ diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 04b6cd9c1..489d5e8de 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -36,12 +36,13 @@ #endif #include "QF/cvar.h" -#include "QF/entity.h" #include "QF/msg.h" #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "compat.h" #include "d_iface.h" diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 3c5b0100d..672aeca18 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -74,7 +74,7 @@ qwaq_cl_plugin_libs= \ @client_static_plugin_libs@ qwaq_client_libs= \ - $(top_builddir)/libs/entity/libQFentity.la \ + $(top_builddir)/libs/scene/libQFscene.la \ $(top_builddir)/libs/console/libQFconsole.la \ $(top_builddir)/libs/ui/libQFui.la \ $(top_builddir)/libs/input/libQFinput.la \ From 1300cfb14ef14382edb7ea08a368374e670445dc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 14:21:54 +0900 Subject: [PATCH 1668/3664] [console] Clean up key_menu input handling Missed this little change in the menu/console untangling. --- libs/console/client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/console/client.c b/libs/console/client.c index 186d2a509..d0329b1d1 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -456,8 +456,8 @@ C_KeyEvent (knum_t key, short unicode, qboolean down, void *data) return; if (con_curr_keydest == key_menu) { - if (Menu_KeyEvent (key, unicode, down)) - return; + Menu_KeyEvent (key, unicode, down); + return; } if (down) { From 7868936b9681d051ea3da669223ed48e97d97cd8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 14:23:06 +0900 Subject: [PATCH 1669/3664] [vulkan] Correct the skysheet scaling Dunno where that 8 came from, but it's quite a bit different from 189/64 (2.953125). Fixes the excessively high skies in vulkan. --- libs/video/renderer/vulkan/shader/bsp_sky.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index ed6828a10..56c75a1ed 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -17,7 +17,7 @@ layout (location = 0) out vec4 frag_color; layout (constant_id = 0) const bool doSkyBox = false; layout (constant_id = 1) const bool doSkySheet = false; -const float SCALE = 8.0; +const float SCALE = 189.0 / 64.0; vec4 fogBlend (vec4 color) From 86cf7fbecdff0be2d21824f14b9e250552bfd308 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 18:04:57 +0900 Subject: [PATCH 1670/3664] [gamecode] Check for null edict before printing number Avoids segfault during double-verbose disassembly of progs code that uses entities. --- libs/gamecode/pr_debug.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 7fc3ba455..6a73f762d 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1237,10 +1237,12 @@ pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, void *_data) if (pr->pr_edicts) { edict_t *edict = PROG_TO_EDICT (pr, value->entity_var); - dasprintf (dstr, "entity %d", NUM_FOR_BAD_EDICT (pr, edict)); - } else { - dasprintf (dstr, "entity [%x]",value->entity_var); + if (edict) { + dasprintf (dstr, "entity %d", NUM_FOR_BAD_EDICT (pr, edict)); + return; + } } + dasprintf (dstr, "entity [%x]", value->entity_var); } static void From 342ba65f570e7d93f70c9b28d790c500c5e9eee8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jul 2021 18:09:54 +0900 Subject: [PATCH 1671/3664] [qfcc] Handle aliased field types Fixes use of structs as entity fields. The test is currently compile-only. --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/def.c | 4 ++-- tools/qfcc/source/dot_expr.c | 8 +++++++- tools/qfcc/source/type.c | 12 ++++++++++++ tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/entity-struct.r | 26 ++++++++++++++++++++++++++ 6 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 tools/qfcc/test/entity-struct.r diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 686e864e1..41e2eef3e 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -152,6 +152,7 @@ type_t *array_type (type_t *aux, int size); type_t *based_array_type (type_t *aux, int base, int top); type_t *alias_type (type_t *type, type_t *alias_chain, const char *name); const type_t *unalias_type (const type_t *type) __attribute__((pure)); +const type_t *dereference_type (const type_t *type) __attribute__((pure)); void print_type_str (struct dstring_s *str, const type_t *type); void print_type (const type_t *type); void dump_dot_type (void *t, const char *filename); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 7ac1d0822..700c5033b 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -278,7 +278,7 @@ free_def (def_t *def) void def_to_ddef (def_t *def, ddef_t *ddef, int aux) { - type_t *type = def->type; + const type_t *type = unalias_type (def->type); if (aux) type = type->t.fldptr.type; // aux is true only for fields @@ -468,7 +468,7 @@ init_vector_components (symbol_t *vector_sym, int is_field) static void init_field_def (def_t *def, expr_t *init, storage_class_t storage) { - type_t *type = def->type->t.fldptr.type; + type_t *type = (type_t *) dereference_type (def->type);//FIXME cast def_t *field_def; symbol_t *field_sym; reloc_t *relocs = 0; diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index d3d584cc3..f8c5464a9 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -488,7 +488,13 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->e.value->v.pointer.val); break; case ev_field: - label = va (0, "field %d", e->e.value->v.pointer.val); + if (e->e.value->v.pointer.def) { + int offset = e->e.value->v.pointer.val; + offset += e->e.value->v.pointer.def->offset; + label = va (0, "field %d", offset); + } else { + label = va (0, "field %d", e->e.value->v.pointer.val); + } break; case ev_entity: label = va (0, "ent %d", e->e.value->v.integer_val); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 56991b790..bb211267a 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -559,6 +559,18 @@ unalias_type (const type_t *type) return type; } +const type_t * +dereference_type (const type_t *type) +{ + if (!is_pointer (type) && !is_field (type)) { + internal_error (0, "dereference non pointer/field type"); + } + if (type->meta == ty_alias) { + type = type->t.alias.full_type; + } + return type->t.fldptr.type; +} + void print_type_str (dstring_t *str, const type_t *type) { diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 15f9b9309..af16e954b 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -20,6 +20,7 @@ test_progs_dat=\ tools/qfcc/test/double.dat \ tools/qfcc/test/double-alias.dat \ tools/qfcc/test/enum.dat \ + tools/qfcc/test/entity-struct.dat \ tools/qfcc/test/fordecl.dat \ tools/qfcc/test/func-expr.dat \ tools/qfcc/test/func-expr2.dat \ @@ -255,6 +256,16 @@ tools/qfcc/test/enum.run: $(qfcc_test_run_deps) include $(enum_dep) # am--include-marker r_depfiles_remade += $(enum_dep) +tools_qfcc_test_entity_struct_dat_SOURCES=tools/qfcc/test/entity-struct.r +entity_struct_obj=$(tools_qfcc_test_entity_struct_dat_SOURCES:.r=.o) +entity_struct_dep=$(call qcautodep,$(tools_qfcc_test_entity_struct_dat_SOURCES)) +tools/qfcc/test/entity-struct.dat$(EXEEXT): $(entity_struct_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(entity_struct_obj) +tools/qfcc/test/entity-struct.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(entity_struct_dep) # am--include-marker +r_depfiles_remade += $(entity_struct_dep) + tools_qfcc_test_fordecl_dat_SOURCES=tools/qfcc/test/fordecl.r fordecl_obj=$(tools_qfcc_test_fordecl_dat_SOURCES:.r=.o) fordecl_dep=$(call qcautodep,$(tools_qfcc_test_fordecl_dat_SOURCES)) diff --git a/tools/qfcc/test/entity-struct.r b/tools/qfcc/test/entity-struct.r new file mode 100644 index 000000000..e342e5b62 --- /dev/null +++ b/tools/qfcc/test/entity-struct.r @@ -0,0 +1,26 @@ +typedef struct foo_s { + int a, b; +} foo_t; + +entity self; +foo_t a, b; +vector x, y; +int i, j; + +.vector v; +.foo_t foo; + +void bar (entity other) +{ + self.v = x; + self.foo.b = i; + j = self.foo.b; + self.foo.a = self.foo.b; + self.foo.b = self.foo.a; +} + +int +main (void) +{ + return 0; // to survive and prevail :) +} From 81f73e45245c18f3c1974747e7adeb23f8d346b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Jul 2021 09:54:08 +0900 Subject: [PATCH 1672/3664] [gamecode] Support printing a single edict field --- include/QF/progs.h | 4 +-- libs/gamecode/pr_debug.c | 58 +++++++++++++++++++++++++++------------- libs/gamecode/pr_edict.c | 8 +++--- libs/gamecode/pr_parse.c | 2 +- libs/ruamoko/pr_cmds.c | 2 +- nq/source/sv_pr_cmds.c | 4 +-- nq/source/sv_progs.c | 11 ++++++-- qw/source/sv_pr_cmds.c | 4 +-- qw/source/sv_progs.c | 11 ++++++-- 9 files changed, 69 insertions(+), 35 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 7ccb962d2..e6ea11575 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -292,9 +292,9 @@ void ED_Count (progs_t *pr); qboolean PR_EdictValid (progs_t *pr, pr_int_t e) __attribute__((pure)); // pr_debug.c -void ED_Print (progs_t *pr, edict_t *ed); +void ED_Print (progs_t *pr, edict_t *ed, const char *fieldname); void ED_PrintEdicts (progs_t *pr, const char *fieldval); -void ED_PrintNum (progs_t *pr, pr_int_t ent); +void ED_PrintNum (progs_t *pr, pr_int_t ent, const char *fieldname); // pr_parse.c struct script_s; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 6a73f762d..535bcab5b 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1716,23 +1716,42 @@ PR_Profile (progs_t * pr) } while (best); } +static void +print_field (progs_t *pr, edict_t *ed, pr_def_t *d) +{ + prdeb_resources_t *res = pr->pr_debug_resources; + int l; + pr_type_t *v; + qfot_type_t dummy_type = { }; + qfot_type_t *type; + pr_debug_data_t data = {pr, res->dstr}; + const char *name; + + name = PR_GetString (pr, d->name); + type = get_def_type (pr, d, &dummy_type); + v = &E_fld (ed, d->ofs); + + l = 15 - strlen (name); + if (l < 1) + l = 1; + + dstring_clearstr (res->dstr); + value_string (&data, type, v); + Sys_Printf ("%s%*s%s\n", name, l, "", res->dstr->str); +} + /* ED_Print For debugging */ VISIBLE void -ED_Print (progs_t *pr, edict_t *ed) +ED_Print (progs_t *pr, edict_t *ed, const char *fieldname) { - prdeb_resources_t *res = pr->pr_debug_resources; - int l; pr_uint_t i, j; const char *name; pr_def_t *d; - pr_type_t *v; - qfot_type_t dummy_type = { }; - qfot_type_t *type; - pr_debug_data_t data = {pr, res->dstr}; + int l; if (ed->free) { Sys_Printf ("FREE\n"); @@ -1740,14 +1759,23 @@ ED_Print (progs_t *pr, edict_t *ed) } Sys_Printf ("\nEDICT %d:\n", NUM_FOR_BAD_EDICT (pr, ed)); + + if (fieldname) { + d = PR_FindField(pr, fieldname); + if (!d) { + Sys_Printf ("unknown field '%s'\n", fieldname); + } else { + print_field (pr, ed, d); + } + return; + } for (i = 0; i < pr->progs->numfielddefs; i++) { d = &pr->pr_fielddefs[i]; if (!d->name) // null field def (probably 1st) continue; - type = get_def_type (pr, d, &dummy_type); name = PR_GetString (pr, d->name); - if (name[strlen (name) - 2] == '_' - && strchr ("xyz", name[strlen (name) -1])) + l = strlen (name); + if (l >= 2 && name[l - 2] == '_' && strchr ("xyz", name[l - 1])) continue; // skip _x, _y, _z vars for (j = 0; j < d->size; j++) { @@ -1759,15 +1787,7 @@ ED_Print (progs_t *pr, edict_t *ed) continue; } - v = &E_fld (ed, d->ofs); - - l = 15 - strlen (name); - if (l < 1) - l = 1; - - dstring_clearstr (res->dstr); - value_string (&data, type, v); - Sys_Printf ("%s%*s%s\n", name, l, "", res->dstr->str); + print_field (pr, ed, d); } } diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 55a96124e..60233a0ce 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -132,13 +132,13 @@ ED_Free (progs_t *pr, edict_t *ed) VISIBLE void -ED_PrintNum (progs_t *pr, pr_int_t ent) +ED_PrintNum (progs_t *pr, pr_int_t ent, const char *fieldname) { if (!pr->num_edicts) { Sys_Printf ("Edicts not supported in this VM\n"); return; } - ED_Print (pr, EDICT_NUM (pr, ent)); + ED_Print (pr, EDICT_NUM (pr, ent), fieldname); } /* @@ -164,13 +164,13 @@ ED_PrintEdicts (progs_t *pr, const char *fieldval) for (i = 0; i < *pr->num_edicts; i++) if (strequal(fieldval, E_GSTRING (pr, EDICT_NUM(pr, i), def->ofs))) { - ED_PrintNum (pr, i); + ED_PrintNum (pr, i, 0); count++; } Sys_Printf ("%i entities\n", count); } else { for (i = 0; i < *pr->num_edicts; i++) - ED_PrintNum (pr, i); + ED_PrintNum (pr, i, 0); Sys_Printf ("%i entities\n", *pr->num_edicts); } } diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index a4c327940..cfc170815 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -475,7 +475,7 @@ ED_SpawnEntities (progs_t *pr, plitem_t *entity_list) func = PR_FindFunction (pr, classname); if (!func) { Sys_Printf ("No spawn function for :\n"); - ED_Print (pr, ent); + ED_Print (pr, ent, 0); ED_Free (pr, ent); continue; } diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 8836de8c9..16f5a21f4 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -343,7 +343,7 @@ PF_traceoff (progs_t *pr) static void PF_eprint (progs_t *pr) { - ED_PrintNum (pr, P_EDICTNUM (pr, 0)); + ED_PrintNum (pr, P_EDICTNUM (pr, 0), 0); } /* diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 7bb54d429..c39afff9e 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -74,7 +74,7 @@ PF_error (progs_t *pr) Sys_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); - ED_Print (pr, ed); + ED_Print (pr, ed, 0); Host_Error ("Program error"); } @@ -98,7 +98,7 @@ PF_objerror (progs_t *pr) Sys_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); - ED_Print (pr, ed); + ED_Print (pr, ed, 0); ED_Free (pr, ed); Host_Error ("Program error"); diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 4cc567c16..58f79bc7e 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -126,10 +126,17 @@ static void ED_PrintEdict_f (void) { int i; + const char *fieldname = 0; + if (Cmd_Argc () < 2) { + Sys_Printf ("edict num [fieldname]\n"); + return; + } + if (Cmd_Argc () >= 3) { + fieldname = Cmd_Argv (2); + } i = atoi (Cmd_Argv (1)); - Sys_Printf ("\n EDICT %i:\n", i); - ED_PrintNum (&sv_pr_state, i); + ED_PrintNum (&sv_pr_state, i, fieldname); } static void diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 965c79727..2b924ed52 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -76,7 +76,7 @@ PF_error (progs_t *pr) Sys_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); - ED_Print (pr, ed); + ED_Print (pr, ed, 0); Sys_Error ("Program error"); } @@ -100,7 +100,7 @@ PF_objerror (progs_t *pr) Sys_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); - ED_Print (pr, ed); + ED_Print (pr, ed, 0); ED_Free (pr, ed); PR_RunError (pr, "object error"); diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index acb39f63c..124a78dd3 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -151,10 +151,17 @@ static void ED_PrintEdict_f (void) { int i; + const char *fieldname = 0; + if (Cmd_Argc () < 2) { + SV_Printf ("edict num [fieldname]\n"); + return; + } + if (Cmd_Argc () >= 3) { + fieldname = Cmd_Argv (2); + } i = atoi (Cmd_Argv (1)); - SV_Printf ("\n EDICT %i:\n", i); - ED_PrintNum (&sv_pr_state, i); + ED_PrintNum (&sv_pr_state, i, fieldname); } static void From 13e1682f5e4bbb50a4dbbe887db959a537ca6308 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Jul 2021 12:14:04 +0900 Subject: [PATCH 1673/3664] [qfbsp] Add an option to dump info about a bsp file Just the header plus some basics of model info. --- tools/qfbsp/include/bsp5.h | 2 + tools/qfbsp/include/options.h | 1 + tools/qfbsp/source/Makemodule.am | 1 + tools/qfbsp/source/info.c | 67 ++++++++++++++++++++++++++++++++ tools/qfbsp/source/options.c | 7 ++++ tools/qfbsp/source/qfbsp.c | 5 ++- 6 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 tools/qfbsp/source/info.c diff --git a/tools/qfbsp/include/bsp5.h b/tools/qfbsp/include/bsp5.h index eb05890cb..3585b2871 100644 --- a/tools/qfbsp/include/bsp5.h +++ b/tools/qfbsp/include/bsp5.h @@ -129,6 +129,8 @@ node_t *AllocNode (void); extern bsp_t *bsp; +void bspinfo (void); + ///@} #endif//qfbsp_bsp5_h diff --git a/tools/qfbsp/include/options.h b/tools/qfbsp/include/options.h index 47a8e0df7..5efdb3f73 100644 --- a/tools/qfbsp/include/options.h +++ b/tools/qfbsp/include/options.h @@ -43,6 +43,7 @@ typedef struct { qboolean noclip; qboolean onlyents; qboolean portal; + qboolean info; qboolean extract; qboolean extract_textures; qboolean extract_entities; diff --git a/tools/qfbsp/source/Makemodule.am b/tools/qfbsp/source/Makemodule.am index 1dda50b5c..084a1ecf9 100644 --- a/tools/qfbsp/source/Makemodule.am +++ b/tools/qfbsp/source/Makemodule.am @@ -8,6 +8,7 @@ bin_PROGRAMS += @QFBSP_TARGETS@ qfbsp_SOURCES= \ tools/qfbsp/source/brush.c \ tools/qfbsp/source/csg4.c \ + tools/qfbsp/source/info.c \ tools/qfbsp/source/map.c \ tools/qfbsp/source/merge.c \ tools/qfbsp/source/nodraw.c \ diff --git a/tools/qfbsp/source/info.c b/tools/qfbsp/source/info.c new file mode 100644 index 000000000..ca4b16df7 --- /dev/null +++ b/tools/qfbsp/source/info.c @@ -0,0 +1,67 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#include + +#include "QF/sys.h" + +#include "tools/qfbsp/include/brush.h" +#include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/draw.h" +#include "tools/qfbsp/include/options.h" + +typedef struct lumpinfo_s { + const char *name; + int size; +} lumpinfo_t; + +#define S(f) sizeof (*((bsp_t *)0)->f) +static lumpinfo_t lump_info[] = { + { "entities", S(entdata) }, + { "planes", S(planes) }, + { "textures", S(texdata) }, + { "vertices", S(vertexes) }, + { "visibility", S(visdata) }, + { "nodes", S(nodes) }, + { "texinfo", S(texinfo) }, + { "faces", S(faces) }, + { "lighting", S(lightdata) }, + { "clipnodes", S(clipnodes) }, + { "leafs", S(leafs) }, + { "marksurfaces", S(marksurfaces) }, + { "edges", S(edges) }, + { "surfedges", S(surfedges) }, + { "models", S(models) }, +}; + +void +bspinfo () +{ + printf ("version: %d\n", bsp->header->version); + for (int i = 0; i < HEADER_LUMPS; i++) { + lump_t *lump = &bsp->header->lumps[i]; + lumpinfo_t *info = &lump_info[i]; + + printf (" %-12s: %7d %7d %7d\n", info->name, + lump->fileofs, lump->filelen, lump->filelen / info->size); + + } + for (int i = 0; i < bsp->nummodels; i++) { + dmodel_t *model = &bsp->models[i]; + printf ("model: *%d\n", i); + printf (" mins : [%g, %g, %g]\n", VectorExpand (model->mins)); + printf (" maxs : [%g, %g, %g]\n", VectorExpand (model->maxs)); + printf (" origin : [%g, %g, %g]\n", VectorExpand (model->origin)); + printf (" headnode:"); + for (int j = 0; j < MAX_MAP_HULLS; j++) { + printf (" %d", model->headnode[j]); + } + printf ("\n"); + printf (" visleafs: %d\n", model->visleafs); + printf (" faces : %7d %7d\n", model->firstface, model->numfaces); + } +} diff --git a/tools/qfbsp/source/options.c b/tools/qfbsp/source/options.c index 70b022b5d..8b5995dce 100644 --- a/tools/qfbsp/source/options.c +++ b/tools/qfbsp/source/options.c @@ -59,6 +59,7 @@ static struct option const long_options[] = { {"noclip", no_argument, 0, 'c'}, {"onlyents", no_argument, 0, 'e'}, {"portal", no_argument, 0, 'p'}, + {"info", no_argument, 0, 'i'}, {"extract-textures", no_argument, 0, 256}, {"extract-entities", no_argument, 0, 257}, {"extract-hull", no_argument, 0, 258}, @@ -81,6 +82,7 @@ static const char *short_options = "f" // nofill "c" // noclip "e" // onlyents + "i" // info "o:" // outputfile "p" // portal "u" // usehulls @@ -102,6 +104,7 @@ usage (int status) " -v, --verbose Display more output than usual\n" " -h, --help Display this help and exit\n" " -V, --version Output version information and exit\n" + " -i, --info Display info about the bsp\n" " -d, --draw\n" " -t, --notjunc\n" " -c, --noclip\n" @@ -163,6 +166,10 @@ DecodeArgs (int argc, char **argv) case 'o': options.output_file = strdup (optarg); break; + case 'i': + options.extract = true; + options.info = true; + break; case 'p': // portal options.extract = true; options.portal = true; diff --git a/tools/qfbsp/source/qfbsp.c b/tools/qfbsp/source/qfbsp.c index abbc81029..a73e6b0af 100644 --- a/tools/qfbsp/source/qfbsp.c +++ b/tools/qfbsp/source/qfbsp.c @@ -404,10 +404,10 @@ CreateHulls (void) static void ProcessFile (void) { - bsp = BSP_New (); - if (options.extract) { LoadBSP (); + if (options.info) + bspinfo (); if (options.portal) bsp2prt (); if (options.extract_textures) @@ -420,6 +420,7 @@ ProcessFile (void) return; } + bsp = BSP_New (); // load brushes and entities LoadMapFile (options.mapfile); From 56c2fa380b8b7e16df40c7beebe17d4b2c70c07f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Jul 2021 14:03:25 +0900 Subject: [PATCH 1674/3664] [vulkan] Implement view model rendering Quake just looked wrong without the view model. I can't say I like the way the depth range is hacked, but it was necessary because the view model needs to be processed along with the rest of the alias models (didn't feel like adding more command buffers, which I imagine would be expensive with the pipeline switching). --- include/QF/Vulkan/qf_alias.h | 2 ++ libs/video/renderer/vulkan/vulkan_alias.c | 18 +++++++++++++ libs/video/renderer/vulkan/vulkan_main.c | 32 ++++++++++++----------- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 7cd5b5bad..4d8f7958a 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -113,4 +113,6 @@ void Vulkan_AliasEnd (struct vulkan_ctx_s *ctx); void Vulkan_Alias_Init (struct vulkan_ctx_s *ctx); void Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx); +void Vulkan_AliasDepthRange (struct vulkan_ctx_s *ctx, float n, float f); + #endif//__QF_Vulkan_qf_alias_h diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 91413f41c..810bc14ef 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -255,6 +255,24 @@ Vulkan_AliasEnd (vulkan_ctx_t *ctx) alias_end_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], ctx); } +void +Vulkan_AliasDepthRange (vulkan_ctx_t *ctx, float minDepth, float maxDepth) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliasctx_t *actx = ctx->alias_context; + aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + + VkViewport viewport = ctx->viewport; + viewport.minDepth = minDepth; + viewport.maxDepth = maxDepth; + + dfunc->vkCmdSetViewport (aframe->cmdSet.a[QFV_aliasDepth], 0, 1, + &viewport); + dfunc->vkCmdSetViewport (aframe->cmdSet.a[QFV_aliasGBuffer], 0, 1, + &viewport); +} + static VkDescriptorBufferInfo base_buffer_info = { 0, 0, VK_WHOLE_SIZE }; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 73e06b2b4..62608393d 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -103,7 +103,7 @@ setup_view (vulkan_ctx_t *ctx) } static void -R_RenderEntities (vulkan_ctx_t *ctx) +Vulkan_RenderEntities (vulkan_ctx_t *ctx) { if (!r_drawentities->int_val) return; @@ -118,7 +118,16 @@ R_RenderEntities (vulkan_ctx_t *ctx) Vulkan_##Type##Begin (ctx); \ begun = 1; \ } \ + /* hack the depth range to prevent view model */\ + /* from poking into walls */\ + if (ent == vr_data.view_model) { \ + Vulkan_AliasDepthRange (ctx, 0, 0.3); \ + } \ Vulkan_Draw##Type (ent, ctx); \ + /* unhack in case the view_model is not the last */\ + if (ent == vr_data.view_model) { \ + Vulkan_AliasDepthRange (ctx, 0, 1); \ + } \ } \ if (begun) \ Vulkan_##Type##End (ctx); \ @@ -130,7 +139,7 @@ R_RenderEntities (vulkan_ctx_t *ctx) } static void -R_DrawViewModel (void) +Vulkan_DrawViewModel (vulkan_ctx_t *ctx) { entity_t *ent = vr_data.view_model; if (vr_data.inhibit_viewmodel @@ -139,18 +148,13 @@ R_DrawViewModel (void) || !ent->renderer.model) return; - // hack the depth range to prevent view model from poking into walls - //qfeglDepthRangef (0, 0.3); - //glsl_R_AliasBegin (); - //glsl_R_DrawAlias (); - //glsl_R_AliasEnd (); - //qfeglDepthRangef (0, 1); + R_EnqueueEntity (ent); } void Vulkan_RenderView (vulkan_ctx_t *ctx) { - double t[10] = {}; + double t[9] = {}; int speeds = r_speeds->int_val; if (speeds) @@ -171,7 +175,8 @@ Vulkan_RenderView (vulkan_ctx_t *ctx) Vulkan_DrawSky (ctx); if (speeds) t[5] = Sys_DoubleTime (); - R_RenderEntities (ctx); + Vulkan_DrawViewModel (ctx); + Vulkan_RenderEntities (ctx); if (speeds) t[6] = Sys_DoubleTime (); Vulkan_DrawWaterSurfaces (ctx); @@ -180,17 +185,14 @@ Vulkan_RenderView (vulkan_ctx_t *ctx) Vulkan_DrawParticles (ctx); if (speeds) t[8] = Sys_DoubleTime (); - R_DrawViewModel (); - if (speeds) - t[9] = Sys_DoubleTime (); if (speeds) { Sys_Printf ("frame: %g, setup: %g, mark: %g, pushdl: %g, world: %g," - " sky: %g, ents: %g, water: %g, part: %g, view: %g\n", + " sky: %g, ents: %g, water: %g, part: %g\n", (t[9] - t[0]) * 1000, (t[1] - t[0]) * 1000, (t[2] - t[1]) * 1000, (t[3] - t[2]) * 1000, (t[4] - t[3]) * 1000, (t[5] - t[4]) * 1000, (t[6] - t[5]) * 1000, (t[7] - t[6]) * 1000, - (t[8] - t[7]) * 1000, (t[9] - t[8]) * 1000); + (t[8] - t[7]) * 1000); } } From 7995f59a907dd98d18e1fc4e48d21e63ddc0236a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Jul 2021 14:21:37 +0900 Subject: [PATCH 1675/3664] [vulkan] Set the 2d near distance to 0 -999999 seems to be a hold-over from the software renderer passed through both gl renderers. I guess it didn't matter in the gl renderers due to various draw hacks, but it made quite a difference in vulkan. Fixes the view model covering the hud. --- libs/video/renderer/vulkan/vulkan_matrices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index a9cf83b2c..670871962 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -108,7 +108,7 @@ Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx) int width = vid.conview->xlen; int height = vid.conview->ylen; - QFV_Orthographic (mat->projection_2d, 0, width, 0, height, -99999, 99999); + QFV_Orthographic (mat->projection_2d, 0, width, 0, height, 0, 99999); float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; QFV_Perspective (mat->projection_3d, r_refdef.fov_y, aspect); From 03921c03c5e4d96d350766cf3d2c06bfcbd4a504 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jul 2021 09:54:03 +0900 Subject: [PATCH 1676/3664] [util] Expose set_expand and fix an out-by-one bug Having set_expand exposed is useful for loading data into a set. However, it turns out there was a bug in its size calculation in that when the requested set size was a multiple of SET_BITS (and greater than the current set size), the new set size one be SET_BITS larger than requested. There's now some tests for this :) --- include/QF/set.h | 22 ++++++++++++++++++++-- libs/util/set.c | 13 ++++++------- libs/util/test/test-set.c | 26 ++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/include/QF/set.h b/include/QF/set.h index 52b1fae85..61bd865aa 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -57,6 +57,10 @@ typedef uint32_t set_bits_t; #define SET_ONE ((set_bits_t) 1) #define SET_TEST_MEMBER(s, x) \ ((s)->map[(x) / SET_BITS] & (SET_ONE << ((x) % SET_BITS))) +#define SET_STATIC_INIT(x, alloc) { \ + .size = SET_SIZE (x), \ + .map = alloc (SET_SIZE (x) / 8), \ +} /** Represent a set using a bitmap. @@ -129,9 +133,11 @@ set_t *set_new_r (set_pool_t *set_pool); \param size The number of elements for which space is to be allocated. \return The newly created, empty set. + \note \a size is the actual amount of elements, not the number of the + highest element (ie, for values 0..n, size is n + 1). */ -set_t *set_new_size (int size); -set_t *set_new_size_r (set_pool_t *set_pool, int size); +set_t *set_new_size (unsigned size); +set_t *set_new_size_r (set_pool_t *set_pool, unsigned size); /** Delete a set that is no longer needed. @@ -140,6 +146,18 @@ set_t *set_new_size_r (set_pool_t *set_pool, int size); void set_delete (set_t *set); void set_delete_r (set_pool_t *set_pool, set_t *set); +/** Pre-expand a set with space for the specified element + + Has no effect if the set is already large enough to hold the specified + element. + + \param set The set to be expanded + \param size The minimum number of elements representable by the set + \note \a size is the actual amount of elements, not the number of the + highest element (ie, for values 0..n, size is n + 1). +*/ +void set_expand (set_t *set, unsigned size); + /** Add an element to a set. It is not an error to add an element that is already a member of the set. diff --git a/libs/util/set.c b/libs/util/set.c index 6b15154e8..869fcc74e 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -111,16 +111,15 @@ set_delete (set_t *set) set_delete_r (&static_set_pool, set); } -static void -set_expand (set_t *set, unsigned x) +void +set_expand (set_t *set, unsigned size) { set_bits_t *map = set->map; - size_t size; - if (x <= set->size) + if (size <= set->size) return; - size = SET_SIZE (x); + size = SET_SIZE (size - 1); set->map = malloc (size / 8); memcpy (set->map, map, set->size / 8); memset (set->map + SET_WORDS (set), 0, (size - set->size) / 8); @@ -130,7 +129,7 @@ set_expand (set_t *set, unsigned x) } inline set_t * -set_new_size_r (set_pool_t *set_pool, int size) +set_new_size_r (set_pool_t *set_pool, unsigned size) { set_t *set; @@ -141,7 +140,7 @@ set_new_size_r (set_pool_t *set_pool, int size) } set_t * -set_new_size (int size) +set_new_size (unsigned size) { return set_new_size_r (&static_set_pool, size); } diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index 3d2b5e6d6..e1b93d137 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -109,6 +109,27 @@ make_not_55 (void) return set_invert (make_55 ()); } +static set_t * +expand_3xSIZEm1 (set_t *set, const set_t *x) +{ + set_expand (set, 3 * SIZE - 1); + return set; +} + +static set_t * +expand_3xSIZEp1 (set_t *set, const set_t *x) +{ + set_expand (set, 3 * SIZE + 1); + return set; +} + +static set_t * +expand_3xSIZE (set_t *set, const set_t *x) +{ + set_expand (set, 3 * SIZE); + return set; +} + struct { setup_func set1; setup_func set2; @@ -135,6 +156,11 @@ struct { {make_0_to_SIZEm1, make_everything, set_reverse_difference, check_size, SIZE, "{64 ...}" }, + {make_SIZE, 0, expand_3xSIZEm1, check_size, 3 * SIZE, + "{64}"}, + {make_SIZE, 0, expand_3xSIZE, check_size, 3 * SIZE, "{64}"}, + {make_SIZE, 0, expand_3xSIZEp1, check_size, + 3 * SIZE + SET_BITS, "{64}"}, {make_everything, make_empty, 0, set_is_subset, 1, 0}, {make_everything, make_empty, 0, set_is_equivalent, 0, 0}, {make_everything, make_empty, 0, set_is_intersecting, 0, 0}, From f47e03e60633f9a76d292ba118d9e33b2edb8533 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jul 2021 11:15:51 +0900 Subject: [PATCH 1677/3664] [model] Remove 64k limit on visible leafs Modern maps can have many more leafs (eg, ad_tears has 98983 leafs). Using set_t makes dynamic leaf counts easy to support and the code much easier to read (though set_is_member and the iterators are a little slower). The main thing to watch out for is the novis set and the set returned by Mod_LeafPVS never shrink, and may have excess elements (ie, indicate that nonexistent leafs are visible). --- include/QF/Vulkan/qf_lighting.h | 4 +- include/QF/model.h | 9 ++- libs/models/brush/model_brush.c | 61 ++++++++++++------- libs/video/renderer/gl/gl_rmisc.c | 9 ++- libs/video/renderer/r_bsp.c | 15 +++-- libs/video/renderer/r_light.c | 2 +- libs/video/renderer/sw/sw_rmain.c | 3 +- libs/video/renderer/sw32/sw32_rmain.c | 3 +- libs/video/renderer/vulkan/vulkan_lighting.c | 30 +++++---- nq/source/sv_main.c | 24 ++++---- nq/source/sv_pr_cmds.c | 12 ++-- qw/include/server.h | 2 +- qw/source/sv_ents.c | 34 +++++------ qw/source/sv_init.c | 64 ++++++++------------ qw/source/sv_pr_cmds.c | 12 ++-- qw/source/sv_send.c | 12 ++-- 16 files changed, 154 insertions(+), 142 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 15b094576..e7940d847 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -103,7 +103,7 @@ typedef struct lightingframe_s { }; // A fat PVS of leafs visible from visible leafs so hidden lights can // illuminate the leafs visible to the player - byte pvs[MAP_PVS_BYTES]; + struct set_s *pvs; struct mleaf_s *leaf; // the last leaf used to generate the pvs qfv_lightvisset_t lightvis; } lightingframe_t; @@ -124,7 +124,7 @@ typedef struct lightingctx_s { qfv_imageset_t lightimages; qfv_lightintset_t lightlayers; qfv_imageviewset_t lightviews; - byte sun_pvs[MAX_MAP_LEAFS]; + struct set_s *sun_pvs; } lightingctx_t; struct vulkan_ctx_s; diff --git a/include/QF/model.h b/include/QF/model.h index 53a4b5af3..5a3b568c3 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -230,7 +230,7 @@ typedef struct mod_brush_s { int numplanes; plane_t *planes; - int numleafs; // number of visible leafs, not counting 0 + unsigned numleafs; // number of visible leafs, not counting 0 mleaf_t *leafs; int numvertexes; @@ -432,13 +432,12 @@ model_t *Mod_ForName (const char *name, qboolean crash); void Mod_TouchModel (const char *name); // brush specific mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure)); -byte *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model); +struct set_s *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model); -// NOTE: the buffer pointed to by out must be at least MAP_PVS_BYTES in size void Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, - byte *out); + struct set_s *pvs); void Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, - byte *out); + struct set_s *pvs); void Mod_Print (void); diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 74b6e7a48..c111cdfb7 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -47,6 +47,7 @@ #include "QF/qendian.h" #include "QF/quakefs.h" #include "QF/render.h" +#include "QF/set.h" #include "QF/sys.h" #include "QF/va.h" @@ -55,8 +56,6 @@ #include "compat.h" #include "mod_internal.h" -static byte mod_novis[MAP_PVS_BYTES]; - VISIBLE cvar_t *gl_sky_divide; //FIXME visibility? VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible? @@ -87,8 +86,9 @@ Mod_PointInLeaf (const vec3_t p, model_t *model) static inline void Mod_DecompressVis_set (const byte *in, const mod_brush_t *brush, byte defvis, - byte *out) + set_t *pvs) { + byte *out = (byte *) pvs->map; byte *start = out; int row, c; @@ -119,8 +119,9 @@ Mod_DecompressVis_set (const byte *in, const mod_brush_t *brush, byte defvis, static inline void Mod_DecompressVis_mix (const byte *in, const mod_brush_t *brush, byte defvis, - byte *out) + set_t *pvs) { + byte *out = (byte *) pvs->map; byte *start = out; int row, c; @@ -146,16 +147,30 @@ Mod_DecompressVis_mix (const byte *in, const mod_brush_t *brush, byte defvis, } while (out - start < row); } -VISIBLE byte * +VISIBLE set_t * Mod_LeafPVS (const mleaf_t *leaf, const model_t *model) { - static byte decompressed[MAP_PVS_BYTES]; + static set_t *novis; + static set_t *decompressed; + unsigned numvis = model->brush.numleafs; + if (leaf == model->brush.leafs) { - if (!mod_novis[0]) { - memset (mod_novis, 0xff, sizeof (mod_novis)); + if (!novis) { + novis = set_new_size (numvis); } - return mod_novis; + if (!novis->map[0] || SET_SIZE (numvis) > novis->size) { + unsigned excess = SET_SIZE (numvis) - numvis; + set_expand (novis, numvis); + memset (novis->map, 0xff, + SET_WORDS (novis) * sizeof (*novis->map)); + novis->map[SET_WORDS (novis) - 1] &= (~SET_ZERO) >> excess; + } + return novis; } + if (!decompressed) { + decompressed = set_new (); + } + set_expand (decompressed, numvis); Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, 0xff, decompressed); return decompressed; @@ -163,10 +178,14 @@ Mod_LeafPVS (const mleaf_t *leaf, const model_t *model) VISIBLE void Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, - byte *out) + set_t *out) { + unsigned numvis = model->brush.numleafs; + set_expand (out, numvis); if (leaf == model->brush.leafs) { - memset (out, defvis, sizeof (mod_novis)); + unsigned excess = SET_SIZE (numvis) - numvis; + memset (out->map, defvis, SET_WORDS (out) * sizeof (*out->map)); + out->map[SET_WORDS (out) - 1] &= (~SET_ZERO) >> excess; return; } Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, defvis, out); @@ -174,12 +193,17 @@ Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, VISIBLE void Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, - byte *out) + set_t *out) { + unsigned numvis = model->brush.numleafs; + set_expand (out, numvis); if (leaf == model->brush.leafs) { - for (int i = MAP_PVS_BYTES; i-- > 0; ) { - *out++ |= defvis; + unsigned excess = SET_SIZE (numvis) - numvis; + byte *o = (byte *) out->map; + for (int i = SET_WORDS (out) * sizeof (*out->map); i-- > 0; ) { + *o++ |= defvis; } + out->map[SET_WORDS (out) - 1] &= (~SET_ZERO) >> excess; return; } Mod_DecompressVis_mix (leaf->compressed_vis, &model->brush, defvis, out); @@ -431,11 +455,6 @@ Mod_LoadSubmodels (model_t *mod, bsp_t *bsp) out = brush->submodels; - if (out->visleafs > MAX_MAP_LEAFS) { - Sys_Error ("Mod_LoadSubmodels: too many visleafs (%d, max = %d) in %s", - out->visleafs, MAX_MAP_LEAFS, mod->path); - } - if (out->visleafs > 8192) Sys_MaskPrintf (SYS_warn, "%i visleafs exceeds standard limit of 8192.\n", @@ -654,7 +673,7 @@ Mod_SetParent (mod_brush_t *brush, mnode_t *node, mnode_t *parent) static void Mod_SetLeafFlags (mod_brush_t *brush) { - for (int i = 0; i < brush->numleafs; i++) { + for (unsigned i = 0; i < brush->numleafs; i++) { int flags = 0; mleaf_t *leaf = &brush->leafs[i]; for (int j = 0; j < leaf->nummarksurfaces; j++) { @@ -704,7 +723,7 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) out->children[j] = brush->nodes + p; } else { p = ~p; - if (p < brush->numleafs) { + if ((unsigned) p < brush->numleafs) { out->children[j] = (mnode_t *) (brush->leafs + p); } else { Sys_Printf ("Mod_LoadNodes: invalid leaf index %i " diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index fbfb216f9..689d38f75 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -184,11 +184,10 @@ register_textures (mod_brush_t *brush) void gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) { - int i; texture_t *tex; mod_brush_t *brush; - for (i = 0; i < 256; i++) + for (int i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value memset (&r_worldentity, 0, sizeof (r_worldentity)); @@ -198,7 +197,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) R_FreeAllEntities (); // clear out efrags in case the level hasn't been reloaded - for (i = 0; i < brush->numleafs; i++) + for (unsigned i = 0; i < brush->numleafs; i++) brush->leafs[i].efrags = NULL; // Force a vis update @@ -212,7 +211,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) // identify sky texture gl_mirrortexturenum = -1; gl_R_ClearTextures (); - for (i = 0; i < brush->numtextures; i++) { + for (int i = 0; i < brush->numtextures; i++) { tex = brush->textures[i]; if (!tex) continue; @@ -226,7 +225,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) gl_R_InitSurfaceChains (brush); gl_R_AddTexture (r_notexture_mip); register_textures (brush); - for (i = 0; i < num_models; i++) { + for (int i = 0; i < num_models; i++) { if (!models[i]) continue; if (*models[i]->path == '*') diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index e9f9cf664..b7ac3614f 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -36,6 +36,7 @@ #endif #include "QF/cvar.h" +#include "QF/set.h" #include "QF/sys.h" #include "r_internal.h" @@ -43,14 +44,13 @@ mvertex_t *r_pcurrentvertbase; mleaf_t *r_viewleaf; static mleaf_t *r_oldviewleaf; +static set_t *solid; void R_MarkLeaves (void) { - byte solid[8192]; - byte *vis; + set_t *vis; int c; - unsigned int i; mleaf_t *leaf; mnode_t *node; msurface_t **mark; @@ -67,13 +67,16 @@ R_MarkLeaves (void) if (r_novis->int_val) { r_oldviewleaf = 0; // so vis will be recalcualted when novis gets // turned off + if (!solid) { + solid = set_new (); + set_everything (solid); + } vis = solid; - memset (solid, 0xff, (brush->numleafs + 7) >> 3); } else vis = Mod_LeafPVS (r_viewleaf, r_worldentity.renderer.model); - for (i = 0; (int) i < brush->numleafs; i++) { - if (vis[i >> 3] & (1 << (i & 7))) { + for (unsigned i = 0; i < brush->numleafs; i++) { + if (set_is_member (vis, i)) { leaf = &brush->leafs[i + 1]; if ((c = leaf->nummarksurfaces)) { mark = leaf->firstmarksurface; diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 96899621e..52169f05b 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -271,7 +271,7 @@ R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, } else { float radius = light->radius; vec3_t mins, maxs; - int leafnum = 0; + unsigned leafnum = 0; byte *in = pvsleaf->compressed_vis; byte vis_bits; diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index e21713984..59699a8aa 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -164,7 +164,6 @@ sw_R_Init (void) void R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) { - int i; mod_brush_t *brush = &worldmodel->brush; memset (&r_worldentity, 0, sizeof (r_worldentity)); @@ -174,7 +173,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) // clear out efrags in case the level hasn't been reloaded // FIXME: is this one short? - for (i = 0; i < brush->numleafs; i++) + for (unsigned i = 0; i < brush->numleafs; i++) brush->leafs[i].efrags = NULL; if (brush->skytexture) diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 5377911ae..2aa7f2921 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -179,7 +179,6 @@ sw32_R_Init (void) void sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) { - int i; mod_brush_t *brush = &worldmodel->brush; memset (&r_worldentity, 0, sizeof (r_worldentity)); @@ -189,7 +188,7 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) // clear out efrags in case the level hasn't been reloaded // FIXME: is this one short? - for (i = 0; i < brush->numleafs; i++) + for (unsigned i = 0; i < brush->numleafs; i++) brush->leafs[i].efrags = NULL; if (brush->skytexture) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index a7a59d6c9..f2e2b012c 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -45,6 +45,7 @@ #include "QF/plist.h" #include "QF/progs.h" #include "QF/script.h" +#include "QF/set.h" #include "QF/sys.h" #include "QF/va.h" @@ -68,12 +69,12 @@ static vec4f_t ref_direction = { 0, 0, 1, 0 }; static void -expand_pvs (byte *pvs, model_t *model) +expand_pvs (set_t *pvs, model_t *model) { - byte base_pvs[MAP_PVS_BYTES]; - memcpy (base_pvs, pvs, sizeof (base_pvs)); - for (int i = 0; i < model->brush.numleafs; i++) { - if (base_pvs[(unsigned) i / 8] & (1 << ((unsigned) i % 8))) { + set_t base_pvs = SET_STATIC_INIT (model->brush.numleafs, alloca); + set_assign (&base_pvs, pvs); + for (unsigned i = 0; i < model->brush.numleafs; i++) { + if (set_is_member (&base_pvs, i)) { Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, pvs); } } @@ -99,13 +100,13 @@ find_visible_lights (vulkan_ctx_t *ctx) int flags = 0; if (leaf == model->brush.leafs) { - memset (lframe->pvs, 0xff, sizeof (lframe->pvs)); + set_everything (lframe->pvs); } else { Mod_LeafPVS_set (leaf, model, 0, lframe->pvs); expand_pvs (lframe->pvs, model); } - for (int i = 0; i < model->brush.numleafs; i++) { - if (lframe->pvs[i / 8] & (1 << (i % 8))) { + for (unsigned i = 0; i < model->brush.numleafs; i++) { + if (set_is_member (lframe->pvs, i)) { flags |= model->brush.leaf_flags[i + 1]; } } @@ -119,7 +120,7 @@ find_visible_lights (vulkan_ctx_t *ctx) for (size_t i = 0; i < lctx->lightleafs.size; i++) { int l = lctx->lightleafs.a[i]; if ((l == -1 && (flags & SURF_DRAWSKY)) - || lframe->pvs[l / 8] & (1 << (l % 8))) { + || set_is_member (lframe->pvs, l)) { lframe->lightvis.a[i] = 1; visible++; } @@ -307,6 +308,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&lctx->frames, frames); lctx->frames.grow = 0; + lctx->sun_pvs = set_new (); + lctx->pipeline = Vulkan_CreatePipeline (ctx, "lighting"); lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout"); lctx->sampler = Vulkan_CreateSampler (ctx, "shadow_sampler"); @@ -369,6 +372,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) shadow_set->a[i], va (ctx->va_ctx, "lighting:shadow_set:%zd", i)); + lframe->pvs = set_new (); + DARRAY_INIT (&lframe->lightvis, 16); lframe->leaf = 0; @@ -551,7 +556,8 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model) //float sunlight2; vec3_t sunangle = { 0, -90, 0 }; - memset (lctx->sun_pvs, 0, MAX_MAP_LEAFS); + set_expand (lctx->sun_pvs, model->brush.numleafs); + set_empty (lctx->sun_pvs); sunlight = parse_float (PL_String (PL_ObjectForKey (entity, "_sunlight")), 0); //sunlight2 = parse_float (PL_String (PL_ObjectForKey (entity, @@ -571,9 +577,9 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model) // Any leaf with sky surfaces can potentially see the sun, thus put // the sun "in" every leaf with a sky surface - for (int l = 0; l < model->brush.numleafs; l++) { + for (unsigned l = 0; l < model->brush.numleafs; l++) { if (model->brush.leaf_flags[l] & SURF_DRAWSKY) { - lctx->sun_pvs[l / 8] |= 1 << (l % 8); + set_add (lctx->sun_pvs, l); } } // any leaf visible from a leaf with a sky surface (and thus the sun) diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 1ec385919..eec256779 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -32,6 +32,7 @@ #include "QF/cvar.h" #include "QF/msg.h" #include "QF/mathlib.h" +#include "QF/set.h" #include "QF/sys.h" #include "QF/va.h" @@ -388,24 +389,20 @@ SV_ClearDatagram (void) crosses a waterline. */ -int fatbytes; -byte fatpvs[MAP_PVS_BYTES]; +static set_t *fatpvs; static void SV_AddToFatPVS (vec3_t org, mnode_t *node) { - int i; float d; - byte *pvs; plane_t *plane; while (1) { // if this is a leaf, accumulate the pvs bits if (node->contents < 0) { if (node->contents != CONTENTS_SOLID) { - pvs = Mod_LeafPVS ((mleaf_t *) node, sv.worldmodel); - for (i = 0; i < fatbytes; i++) - fatpvs[i] |= pvs[i]; + set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node, + sv.worldmodel)); } return; } @@ -429,11 +426,14 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node) Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the given point. */ -static byte * +static set_t * SV_FatPVS (vec3_t org) { - fatbytes = (sv.worldmodel->brush.numleafs + 31) >> 3; - memset (fatpvs, 0, fatbytes); + if (!fatpvs) { + fatpvs = set_new_size (sv.worldmodel->brush.numleafs); + } + set_expand (fatpvs, sv.worldmodel->brush.numleafs); + set_empty (fatpvs); SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); return fatpvs; } @@ -444,7 +444,7 @@ static void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) { int bits, e, i; - byte *pvs; + set_t *pvs; float miss; vec3_t org; edict_t *ent; @@ -473,7 +473,7 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) continue; for (el = SVdata (ent)->leafs; el; el = el->next) { - if (pvs[el->leafnum >> 3] & (1 << (el->leafnum & 7))) + if (set_is_member (pvs, el->leafnum)) break; } diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index c39afff9e..4a0aa76a7 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -42,6 +42,7 @@ #include "QF/cvar.h" #include "QF/msg.h" #include "QF/ruamoko.h" +#include "QF/set.h" #include "QF/sys.h" #include "QF/va.h" @@ -539,12 +540,11 @@ PF_checkpos (progs_t *pr) { } -byte checkpvs[MAP_PVS_BYTES]; +static set_t *checkpvs; static int PF_newcheckclient (progs_t *pr, int check) { - byte *pvs; edict_t *ent; int i; mleaf_t *leaf; @@ -584,8 +584,10 @@ PF_newcheckclient (progs_t *pr, int check) // get the PVS for the entity VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); leaf = Mod_PointInLeaf (org, sv.worldmodel); - pvs = Mod_LeafPVS (leaf, sv.worldmodel); - memcpy (checkpvs, pvs, (sv.worldmodel->brush.numleafs + 7) >> 3); + if (!checkpvs) { + checkpvs = set_new_size (sv.worldmodel->brush.numleafs); + } + set_assign (checkpvs, Mod_LeafPVS (leaf, sv.worldmodel)); return i; } @@ -631,7 +633,7 @@ PF_checkclient (progs_t *pr) VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view); leaf = Mod_PointInLeaf (view, sv.worldmodel); l = (leaf - sv.worldmodel->brush.leafs) - 1; - if ((l < 0) || !(checkpvs[l >> 3] & (1 << (l & 7)))) { + if (!set_is_member (checkpvs, l)) { c_notvis++; RETURN_EDICT (pr, sv.edicts); return; diff --git a/qw/include/server.h b/qw/include/server.h index f91b0dfb5..3693a32fa 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -86,7 +86,7 @@ typedef struct { // struct edict_s is variable sized, but can // be used to reference the world ent - byte *pvs, *phs; // fully expanded and decompressed + struct set_s *pvs, *phs; // fully expanded and decompressed //antilag float lagentsfrac; diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index 5538de54b..b7505dfb0 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -37,6 +37,7 @@ #include "QF/cvar.h" #include "QF/msg.h" +#include "QF/set.h" #include "QF/sys.h" #include "compat.h" @@ -54,25 +55,21 @@ when the bob crosses a waterline. */ -byte fatpvs[MAP_PVS_BYTES]; -int fatbytes; +static set_t *fatpvs; static void SV_AddToFatPVS (vec3_t org, mnode_t *node) { - byte *pvs; - int i; - float d; + float d; plane_t *plane; while (1) { // if this is a leaf, accumulate the pvs bits if (node->contents < 0) { if (node->contents != CONTENTS_SOLID) { - pvs = Mod_LeafPVS ((mleaf_t *) node, sv.worldmodel); - for (i = 0; i < fatbytes; i++) - fatpvs[i] |= pvs[i]; + set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node, + sv.worldmodel)); } return; } @@ -96,11 +93,14 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node) Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the given point. */ -static byte * +static set_t * SV_FatPVS (vec3_t org) { - fatbytes = (sv.worldmodel->brush.numleafs + 31) >> 3; - memset (fatpvs, 0, fatbytes); + if (!fatpvs) { + fatpvs = set_new_size (sv.worldmodel->brush.numleafs); + } + set_expand (fatpvs, sv.worldmodel->brush.numleafs); + set_empty (fatpvs); SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); return fatpvs; } @@ -549,7 +549,7 @@ write_player (delta_t *delta, plent_state_t *from, plent_state_t *to, } static void -SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg) +SV_WritePlayersToClient (delta_t *delta, set_t *pvs, sizebuf_t *msg) { int j, k; client_t *cl; @@ -613,7 +613,7 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg) if (pvs) { // ignore if not touching a PV leaf for (el = SVdata (ent)->leafs; el; el = el->next) { - if (pvs[el->leafnum >> 3] & (1 << (el->leafnum & 7))) + if (set_is_member (pvs, el->leafnum)) break; } if (!el) @@ -706,10 +706,10 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg) } } -static inline byte * +static inline set_t * calc_pvs (delta_t *delta) { - byte *pvs = 0; + set_t *pvs = 0; vec3_t org; // find the client's PVS @@ -756,7 +756,7 @@ calc_pvs (delta_t *delta) void SV_WriteEntitiesToClient (delta_t *delta, sizebuf_t *msg) { - byte *pvs = 0; + set_t *pvs = 0; int e, num_edicts; int max_packet_entities = MAX_DEMO_PACKET_ENTITIES; int stdver = 1; @@ -801,7 +801,7 @@ SV_WriteEntitiesToClient (delta_t *delta, sizebuf_t *msg) if (pvs) { // ignore if not touching a PV leaf for (el = SVdata (ent)->leafs; el; el = el->next) { - if (pvs[el->leafnum >> 3] & (1 << (el->leafnum & 7))) + if (set_is_member (pvs, el->leafnum)) break; } if (!el) diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index b4e42c391..e88459d0d 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -40,6 +40,7 @@ #include "QF/info.h" #include "QF/msg.h" #include "QF/quakefs.h" +#include "QF/set.h" #include "QF/sys.h" #include "QF/va.h" @@ -222,62 +223,45 @@ SV_SaveSpawnparms (void) static void SV_CalcPHS (void) { - byte *scan; - int bitbyte, count, index, num, rowbytes, rowwords, vcount, i, j, - k, l; - unsigned int *dest, *src; + int count, num, vcount, i; SV_Printf ("Building PHS...\n"); num = sv.worldmodel->brush.numleafs; - rowwords = (num + 31) >> 5; - rowbytes = rowwords * 4; - sv.pvs = Hunk_Alloc (rowbytes * num); - scan = sv.pvs; + sv.pvs = Hunk_Alloc (num * sizeof (set_t)); vcount = 0; - for (i = 0; i < num; i++, scan += rowbytes) { - memcpy (scan, Mod_LeafPVS (sv.worldmodel->brush.leafs + i, - sv.worldmodel), - rowbytes); + for (i = 0; i < num; i++) { + sv.pvs[i] = (set_t) SET_STATIC_INIT (num, Hunk_Alloc); + Mod_LeafPVS_set (sv.worldmodel->brush.leafs + i, sv.worldmodel, 0xff, + &sv.pvs[i]); if (i == 0) continue; - for (j = 0; j < num; j++) { - if (scan[j >> 3] & (1 << (j & 7))) { - vcount++; - } + for (set_iter_t *iter = set_first (&sv.pvs[i]); iter; + iter = set_next (iter)) { + vcount++; } } - sv.phs = Hunk_Alloc (rowbytes * num); + sv.phs = Hunk_Alloc (num * sizeof (set_t)); count = 0; - scan = sv.pvs; - dest = (unsigned int *) sv.phs; - for (i = 0; i < num; i++, dest += rowwords, scan += rowbytes) { - memcpy (dest, scan, rowbytes); - for (j = 0; j < rowbytes; j++) { - bitbyte = scan[j]; - if (!bitbyte) - continue; - for (k = 0; k < 8; k++) { - if (!(bitbyte & (1 << k))) - continue; - // or this pvs row into the phs - // +1 because pvs is 1 based - index = ((j << 3) + k + 1); - if (index >= num) - continue; - src = (unsigned int *) sv.pvs + index * rowwords; - for (l = 0; l < rowwords; l++) - dest[l] |= src[l]; - } + for (i = 0; i < num; i++) { + sv.phs[i] = (set_t) SET_STATIC_INIT (num, Hunk_Alloc); + set_assign (&sv.phs[i], &sv.pvs[i]); + + for (set_iter_t *iter = set_first (&sv.pvs[i]); iter; + iter = set_next (iter)) { + // or this pvs row into the phs + // +1 because pvs is 1 based + set_union (&sv.phs[i], &sv.pvs[iter->element + 1]); } if (i == 0) continue; - for (j = 0; j < num; j++) - if (((byte *) dest)[j >> 3] & (1 << (j & 7))) - count++; + for (set_iter_t *iter = set_first (&sv.phs[i]); iter; + iter = set_next (iter)) { + count++; + } } SV_Printf ("Average leafs visible / hearable / total: %i / %i / %i\n", diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 2b924ed52..6b2b85389 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -42,6 +42,7 @@ #include "QF/cvar.h" #include "QF/msg.h" #include "QF/ruamoko.h" +#include "QF/set.h" #include "QF/sys.h" #include "QF/va.h" @@ -460,12 +461,11 @@ PF_checkpos (progs_t *pr) { } -byte checkpvs[MAP_PVS_BYTES]; +set_t *checkpvs; static int PF_newcheckclient (progs_t *pr, int check) { - byte *pvs; edict_t *ent; int i; mleaf_t *leaf; @@ -505,8 +505,10 @@ PF_newcheckclient (progs_t *pr, int check) // get the PVS for the entity VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); leaf = Mod_PointInLeaf (org, sv.worldmodel); - pvs = Mod_LeafPVS (leaf, sv.worldmodel); - memcpy (checkpvs, pvs, (sv.worldmodel->brush.numleafs + 7) >> 3); + if (!checkpvs) { + checkpvs = set_new_size (sv.worldmodel->brush.numleafs); + } + set_assign (checkpvs, Mod_LeafPVS (leaf, sv.worldmodel)); return i; } @@ -552,7 +554,7 @@ PF_checkclient (progs_t *pr) VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view); leaf = Mod_PointInLeaf (view, sv.worldmodel); l = (leaf - sv.worldmodel->brush.leafs) - 1; - if ((l < 0) || !(checkpvs[l >> 3] & (1 << (l & 7)))) { + if (!set_is_member (checkpvs, l)) { c_notvis++; RETURN_EDICT (pr, sv.edicts); return; diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index b89438131..87c65837e 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -43,6 +43,7 @@ #include "QF/console.h" #include "QF/dstring.h" #include "QF/msg.h" +#include "QF/set.h" #include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_* #include "QF/sys.h" @@ -295,7 +296,7 @@ SV_PrintToClient (client_t *cl, int level, const char *string) void SV_Multicast (const vec3_t origin, int to) { - byte *mask; + set_t *mask; client_t *client; int leafnum, j; mleaf_t *leaf; @@ -314,23 +315,22 @@ SV_Multicast (const vec3_t origin, int to) case MULTICAST_ALL_R: reliable = true; // intentional fallthrough case MULTICAST_ALL: - mask = sv.pvs; // leaf 0 is everything; + mask = &sv.pvs[0]; // leaf 0 is everything; break; case MULTICAST_PHS_R: reliable = true; // intentional fallthrough case MULTICAST_PHS: - mask = sv.phs + leafnum * 4 * ((brush->numleafs + 31) >> 5); + mask = &sv.phs[leafnum]; break; case MULTICAST_PVS_R: reliable = true; // intentional fallthrough case MULTICAST_PVS: - mask = sv.pvs + leafnum * 4 * ((brush->numleafs + 31) >> 5); + mask = &sv.pvs[leafnum]; break; default: - mask = NULL; Sys_Error ("SV_Multicast: bad to:%i", to); } @@ -352,7 +352,7 @@ SV_Multicast (const vec3_t origin, int to) if (leaf) { // -1 is because pvs rows are 1 based, not 0 based like leafs leafnum = leaf - brush->leafs - 1; - if (!(mask[leafnum >> 3] & (1 << (leafnum & 7)))) { + if (!set_is_member (mask, leafnum)) { // SV_Printf ("supressed multicast\n"); continue; } From 2e33503c4c59bd71a502fd73d39efa2fe4faadeb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jul 2021 11:43:31 +0900 Subject: [PATCH 1678/3664] [vulkan] Fix a missed array index edit Caused by the view model implementation, and missed because gcc needs optimization to cache such errors (and my own error, of course). --- libs/video/renderer/vulkan/vulkan_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 62608393d..84dfbe830 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -188,7 +188,7 @@ Vulkan_RenderView (vulkan_ctx_t *ctx) if (speeds) { Sys_Printf ("frame: %g, setup: %g, mark: %g, pushdl: %g, world: %g," " sky: %g, ents: %g, water: %g, part: %g\n", - (t[9] - t[0]) * 1000, (t[1] - t[0]) * 1000, + (t[8] - t[0]) * 1000, (t[1] - t[0]) * 1000, (t[2] - t[1]) * 1000, (t[3] - t[2]) * 1000, (t[4] - t[3]) * 1000, (t[5] - t[4]) * 1000, (t[6] - t[5]) * 1000, (t[7] - t[6]) * 1000, From 60d23bdc8fd82500fae18eb3977d2dc73da1ff71 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jul 2021 13:10:06 +0900 Subject: [PATCH 1679/3664] [qfbsp] Remove all arbitrary bsp limits Planes, verts, etc can now all get crazy big. --- include/QF/darray.h | 2 ++ tools/qfbsp/include/brush.h | 5 +++-- tools/qfbsp/include/csg4.h | 4 +++- tools/qfbsp/source/brush.c | 23 ++++++++--------------- tools/qfbsp/source/csg4.c | 20 ++++++++++---------- tools/qfbsp/source/info.c | 2 +- tools/qfbsp/source/merge.c | 2 +- tools/qfbsp/source/outside.c | 4 ++-- tools/qfbsp/source/portals.c | 6 +++--- tools/qfbsp/source/qfbsp.c | 2 -- tools/qfbsp/source/readbsp.c | 11 ++++++----- tools/qfbsp/source/region.c | 9 --------- tools/qfbsp/source/solidbsp.c | 8 ++++---- tools/qfbsp/source/surfaces.c | 22 +++++++++------------- tools/qfbsp/source/writebsp.c | 19 +++++++------------ 15 files changed, 59 insertions(+), 80 deletions(-) diff --git a/include/QF/darray.h b/include/QF/darray.h index e41cd5edb..47f887db3 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -31,6 +31,8 @@ #ifndef __QF_darray_h #define __QF_darray_h +#include + #include "QF/sys.h" /** \defgroup darray Dynamic Arrays diff --git a/tools/qfbsp/include/brush.h b/tools/qfbsp/include/brush.h index 345b14747..83c9528bb 100644 --- a/tools/qfbsp/include/brush.h +++ b/tools/qfbsp/include/brush.h @@ -22,6 +22,7 @@ #ifndef qfbsp_brush_h #define qfbsp_brush_h +#include "QF/darray.h" #include "QF/mathlib.h" #include "bsp5.h" @@ -48,8 +49,8 @@ typedef struct brushset_s { brush_t *brushes; // NULL terminated list } brushset_t; -extern int numbrushplanes; -extern plane_t planes[MAX_MAP_PLANES]; +typedef struct DARRAY_TYPE (plane_t) planeset_t; +extern planeset_t planes; /** Allocate a new brush. diff --git a/tools/qfbsp/include/csg4.h b/tools/qfbsp/include/csg4.h index e6ff8b4a3..fbe44cbd6 100644 --- a/tools/qfbsp/include/csg4.h +++ b/tools/qfbsp/include/csg4.h @@ -23,6 +23,7 @@ #define qfbsp_csg4_h #include "QF/bspfile.h" +#include "QF/darray.h" /** \defgroup qfbsp_csg4 CSG Functions \ingroup qfbsp @@ -34,7 +35,8 @@ struct visfacet_s; struct brushset_s; struct surface_s; -extern struct visfacet_s *validfaces[MAX_MAP_PLANES]; +typedef struct DARRAY_TYPE (struct visfacet_s *) visfacetset_t; +extern visfacetset_t validfaces; /** Build the surface lists for the brushset. diff --git a/tools/qfbsp/source/brush.c b/tools/qfbsp/source/brush.c index e0b05f2d9..39fabf726 100644 --- a/tools/qfbsp/source/brush.c +++ b/tools/qfbsp/source/brush.c @@ -42,8 +42,7 @@ */ //@{ -int numbrushplanes; -plane_t planes[MAX_MAP_PLANES]; +planeset_t planes = DARRAY_STATIC_INIT (1024); int numbrushfaces; mface_t faces[MAX_FACES]; // beveled clipping hull can generate many extra @@ -78,7 +77,7 @@ CheckFace (const face_t *f) if (f->points->numpoints < 3) Sys_Error ("CheckFace: %i points", f->points->numpoints); - VectorCopy (planes[f->planenum].normal, facenormal); + VectorCopy (planes.a[f->planenum].normal, facenormal); if (f->planeside) VectorNegate (facenormal, facenormal); @@ -92,14 +91,14 @@ CheckFace (const face_t *f) j = i + 1 == f->points->numpoints ? 0 : i + 1; // check the point is on the face plane - d = PlaneDiff (p1, &planes[f->planenum]); + d = PlaneDiff (p1, &planes.a[f->planenum]); // point off plane autofix if (d < -ON_EPSILON || d > ON_EPSILON) if (options.verbosity > 1) printf ("CheckFace: point off plane: %g @ (%g %g %g)\n", d, p1[0], p1[1], p1[2]); - VectorMultSub (p1, d, planes[f->planenum].normal, p1); + VectorMultSub (p1, d, planes.a[f->planenum].normal, p1); // check the edge isn't degenerate p2 = f->points->points[j]; @@ -257,7 +256,6 @@ NormalizePlane (plane_t *dp) int FindPlane (const plane_t *dplane, int *side) { - int i; plane_t *dp, pl; vec_t dot; @@ -272,8 +270,8 @@ FindPlane (const plane_t *dplane, int *side) else *side = 1; - dp = planes; - for (i = 0; i < numbrushplanes; i++, dp++) { + dp = planes.a; + for (size_t i = 0; i < planes.size; i++, dp++) { dot = DotProduct (dp->normal, pl.normal); if (dot > 1.0 - ANGLEEPSILON && fabs(dp->dist - pl.dist) < DISTEPSILON) { // regular match @@ -281,14 +279,9 @@ FindPlane (const plane_t *dplane, int *side) } } - if (numbrushplanes == MAX_MAP_PLANES) - Sys_Error ("numbrushplanes == MAX_MAP_PLANES"); + DARRAY_APPEND (&planes, pl); - planes[numbrushplanes] = pl; - - numbrushplanes++; - - return numbrushplanes - 1; + return planes.size - 1; } /* diff --git a/tools/qfbsp/source/csg4.c b/tools/qfbsp/source/csg4.c index 76d11e2d1..05c1b8034 100644 --- a/tools/qfbsp/source/csg4.c +++ b/tools/qfbsp/source/csg4.c @@ -46,7 +46,7 @@ tjunction */ -face_t *validfaces[MAX_MAP_PLANES]; +visfacetset_t validfaces = DARRAY_STATIC_INIT (1024); face_t *inside, *outside; int brushfaces; int csgfaces; @@ -134,7 +134,7 @@ ClipInside (int splitplane, int frontside, qboolean precedence) face_t *frags[2]; plane_t *split; - split = &planes[splitplane]; + split = &planes.a[splitplane]; insidelist = NULL; for (f = inside; f; f = next) { @@ -195,12 +195,12 @@ SaveOutside (qboolean mirror) newf->contents[0] = f->contents[1]; newf->contents[1] = f->contents[0]; - validfaces[planenum] = MergeFaceToList (newf, - validfaces[planenum]); + validfaces.a[planenum] = MergeFaceToList (newf, + validfaces.a[planenum]); } - validfaces[planenum] = MergeFaceToList (f, validfaces[planenum]); - validfaces[planenum] = FreeMergeListScraps (validfaces[planenum]); + validfaces.a[planenum] = MergeFaceToList (f, validfaces.a[planenum]); + validfaces.a[planenum] = FreeMergeListScraps (validfaces.a[planenum]); } } @@ -234,13 +234,12 @@ BuildSurfaces (void) { face_t *count; face_t **f; - int i; surface_t *surfhead, *s; surfhead = NULL; - f = validfaces; - for (i = 0; i < numbrushplanes; i++, f++) { + f = validfaces.a; + for (size_t i = 0; i < planes.size; i++, f++) { if (!*f) continue; // nothing left on this plane @@ -304,7 +303,8 @@ CSGFaces (brushset_t *bs) qprintf ("---- CSGFaces ----\n"); - memset (validfaces, 0, sizeof (validfaces)); + DARRAY_RESIZE (&validfaces, planes.size); + memset (validfaces.a, 0, validfaces.size * sizeof (validfaces.a[0])); csgfaces = brushfaces = csgmergefaces = 0; diff --git a/tools/qfbsp/source/info.c b/tools/qfbsp/source/info.c index ca4b16df7..fb2a6dc0c 100644 --- a/tools/qfbsp/source/info.c +++ b/tools/qfbsp/source/info.c @@ -41,7 +41,7 @@ static lumpinfo_t lump_info[] = { void bspinfo () { - printf ("version: %d\n", bsp->header->version); + printf ("version: %x\n", bsp->header->version); for (int i = 0; i < HEADER_LUMPS; i++) { lump_t *lump = &bsp->header->lumps[i]; lumpinfo_t *info = &lump_info[i]; diff --git a/tools/qfbsp/source/merge.c b/tools/qfbsp/source/merge.c index 480af3896..325353f19 100644 --- a/tools/qfbsp/source/merge.c +++ b/tools/qfbsp/source/merge.c @@ -96,7 +96,7 @@ TryMerge (const face_t *f1, const face_t *f2) found_edge: // check slope of connected lines // if the slopes are colinear, the point can be removed - plane = &planes[f1->planenum]; + plane = &planes.a[f1->planenum]; VectorCopy (plane->normal, planenormal); if (f1->planeside) VectorNegate (planenormal, planenormal); diff --git a/tools/qfbsp/source/outside.c b/tools/qfbsp/source/outside.c index d7ba0d142..81b8b0e30 100644 --- a/tools/qfbsp/source/outside.c +++ b/tools/qfbsp/source/outside.c @@ -47,8 +47,8 @@ PointInLeaf (node_t *node, const vec3_t point) vec_t d; while (!node->contents) { - d = DotProduct (planes[node->planenum].normal, point); - node = node->children[d <= planes[node->planenum].dist]; + d = DotProduct (planes.a[node->planenum].normal, point); + node = node->children[d <= planes.a[node->planenum].dist]; } return node; } diff --git a/tools/qfbsp/source/portals.c b/tools/qfbsp/source/portals.c index cbc128f1e..56c665e3f 100644 --- a/tools/qfbsp/source/portals.c +++ b/tools/qfbsp/source/portals.c @@ -271,7 +271,7 @@ CutNodePortals_r (node_t *node) return; } - plane = &planes[node->planenum]; + plane = &planes.a[node->planenum]; f = node->children[0]; b = node->children[1]; @@ -281,7 +281,7 @@ CutNodePortals_r (node_t *node) /// portals on the node. w = BaseWindingForPlane (plane); for (p = node->portals; p; p = p->next[side]) { - clipplane = planes[p->planenum]; // copy the plane + clipplane = planes.a[p->planenum]; // copy the plane if (p->nodes[0] == node) side = 0; else if (p->nodes[1] == node) { @@ -511,7 +511,7 @@ WritePortalFile_r (const node_t *node) // sometimes planes get turned around when they are very near the // changeover point between different axis. interpret the plane // the same way vis will, and flip the side orders if needed - pl = &planes[p->planenum]; + pl = &planes.a[p->planenum]; PlaneFromWinding (w, &plane2); if (DotProduct (pl->normal, plane2.normal) < 0.99) { // backwards.. fprintf (pf, "%i %i %i ", w->numpoints, diff --git a/tools/qfbsp/source/qfbsp.c b/tools/qfbsp/source/qfbsp.c index a73e6b0af..19a0d5023 100644 --- a/tools/qfbsp/source/qfbsp.c +++ b/tools/qfbsp/source/qfbsp.c @@ -296,8 +296,6 @@ ReadClipHull (int hullnum) firstclipnode = bsp->numclipnodes; for (i = 0; i < n; i++) { - if (bsp->numclipnodes == MAX_MAP_CLIPNODES) - Sys_Error ("ReadClipHull: MAX_MAP_CLIPNODES"); if (fscanf (f, "%d : %f %f %f %f : %d %d\n", &junk, &f1, &f2, &f3, &f4, &c1, &c2) != 7) Sys_Error ("Error parsing %s", options.hullfile); diff --git a/tools/qfbsp/source/readbsp.c b/tools/qfbsp/source/readbsp.c index c554755c5..c71d74b5f 100644 --- a/tools/qfbsp/source/readbsp.c +++ b/tools/qfbsp/source/readbsp.c @@ -101,16 +101,17 @@ static void load_planes (void) { const dplane_t *p; + plane_t tp = { }; int i; - memset (planes, 0, sizeof (planes)); + planes.size = 0; for (i = 0; i < bsp->numplanes; i++) { p = bsp->planes + i; - VectorCopy (p->normal, planes[i].normal); - planes[i].dist = p->dist; - planes[i].type = p->type; + VectorCopy (p->normal, tp.normal); + tp.dist = p->dist; + tp.type = p->type; + DARRAY_APPEND (&planes, tp); } - numbrushplanes = bsp->numplanes; } static void diff --git a/tools/qfbsp/source/region.c b/tools/qfbsp/source/region.c index 03dfd2efd..acb8e5da1 100644 --- a/tools/qfbsp/source/region.c +++ b/tools/qfbsp/source/region.c @@ -160,13 +160,6 @@ RecursiveGrowRegion (dface_t *r, face_t *f) } */ -typedef struct { - int numedges; - int edges[2]; -} checkpoint_t; - -checkpoint_t checkpoints[MAX_MAP_VERTS]; - static void CountRealNumbers (void) { @@ -207,8 +200,6 @@ GrowNodeRegion_r (node_t * node) // continue; // allready grown into an earlier region // emit a region - if (bsp->numfaces == MAX_MAP_FACES) - Sys_Error ("MAX_MAP_FACES"); f->outputnumber = bsp->numfaces; r.planenum = node->outputplanenum; diff --git a/tools/qfbsp/source/solidbsp.c b/tools/qfbsp/source/solidbsp.c index c49422c20..a06ad512a 100644 --- a/tools/qfbsp/source/solidbsp.c +++ b/tools/qfbsp/source/solidbsp.c @@ -138,7 +138,7 @@ ChooseMidPlaneFromList (surface_t *surfaces, if (p->onnode) continue; - plane = &planes[p->planenum]; + plane = &planes.a[p->planenum]; // check for axis aligned surfaces l = plane->type; @@ -215,7 +215,7 @@ ChoosePlaneFromList (surface_t *surfaces, const vec3_t mins, const vec3_t maxs, if (!p->has_struct && !usedetail) continue; - plane = &planes[p->planenum]; + plane = &planes.a[p->planenum]; k = 0; if (!usefloors && plane->normal[2] == 1) @@ -393,7 +393,7 @@ DividePlane (surface_t *in, plane_t *split, surface_t **front, int have[2][2]; // [front|back][detail|struct] - inplane = &planes[in->planenum]; + inplane = &planes.a[in->planenum]; // parallel case is easy if (_VectorCompare (inplane->normal, split->normal)) { @@ -638,7 +638,7 @@ PartitionSurfaces (surface_t *surfaces, node_t *node) node->children[1] = AllocNode (); node->planenum = split->planenum; - splitplane = &planes[split->planenum]; + splitplane = &planes.a[split->planenum]; // multiple surfaces, so split all the polysurfaces into front and back // lists diff --git a/tools/qfbsp/source/surfaces.c b/tools/qfbsp/source/surfaces.c index 2c9c08897..c99b4fb40 100644 --- a/tools/qfbsp/source/surfaces.c +++ b/tools/qfbsp/source/surfaces.c @@ -26,9 +26,11 @@ #endif #include +#include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" #include "tools/qfbsp/include/bsp5.h" +#include "tools/qfbsp/include/brush.h" #include "tools/qfbsp/include/csg4.h" #include "tools/qfbsp/include/options.h" #include "tools/qfbsp/include/region.h" @@ -162,8 +164,8 @@ GatherNodeFaces_r (node_t *node) if (!f->points) { // face was removed outside FreeFace (f); } else { - f->next = validfaces[f->planenum]; - validfaces[f->planenum] = f; + f->next = validfaces.a[f->planenum]; + validfaces.a[f->planenum] = f; } } @@ -180,7 +182,8 @@ GatherNodeFaces_r (node_t *node) surface_t * GatherNodeFaces (node_t *headnode) { - memset (validfaces, 0, sizeof (validfaces)); + DARRAY_RESIZE (&validfaces, planes.size); + memset (validfaces.a, 0, validfaces.size * sizeof (validfaces.a[0])); GatherNodeFaces_r (headnode); return BuildSurfaces (); } @@ -198,8 +201,7 @@ typedef struct hashvert_s { int c_cornerverts; -hashvert_t hvertex[MAX_MAP_VERTS]; -hashvert_t *hvert_p; +static PR_RESMAP (hashvert_t) hvertex; #define EDGEFACE_CHUNK 4096 int numedgefaces = 0; @@ -241,7 +243,7 @@ InitHash (void) hash_scale[1] = newsize[1] / size[1]; hash_scale[2] = newsize[1]; - hvert_p = hvertex; + PR_RESRESET (hvertex); } /** Calulate the hash value of a vector. @@ -302,7 +304,7 @@ GetVertex (const vec3_t in, int planenum) } } - hv = hvert_p; + hv = PR_RESNEW (hvertex); hv->numedges = 1; hv->numplanes = 1; hv->planenums[0] = planenum; @@ -310,14 +312,8 @@ GetVertex (const vec3_t in, int planenum) hashverts[h] = hv; VectorCopy (vert, hv->point); hv->num = bsp->numvertexes; - if (hv->num == MAX_MAP_VERTS) - Sys_Error ("GetVertex: MAX_MAP_VERTS"); - hvert_p++; // emit a vertex - if (bsp->numvertexes == MAX_MAP_VERTS) - Sys_Error ("numvertexes == MAX_MAP_VERTS"); - v.point[0] = vert[0]; v.point[1] = vert[1]; v.point[2] = vert[2]; diff --git a/tools/qfbsp/source/writebsp.c b/tools/qfbsp/source/writebsp.c index 9001b92dc..28943c145 100644 --- a/tools/qfbsp/source/writebsp.c +++ b/tools/qfbsp/source/writebsp.c @@ -67,14 +67,12 @@ FindFinalPlane (const dplane_t *p) } // new plane - if (bsp->numplanes == MAX_MAP_PLANES) - Sys_Error ("numplanes == MAX_MAP_PLANES"); BSP_AddPlane (bsp, p); return bsp->numplanes - 1; } -int planemapping[MAX_MAP_PLANES]; +static struct DARRAY_TYPE(int) planemapping = DARRAY_STATIC_INIT (1024); /** Recursively write the nodes' planes to the bsp file. @@ -91,10 +89,10 @@ WriteNodePlanes_r (node_t *node) if (node->planenum == -1) return; - if (planemapping[node->planenum] == -1) { // a new plane - planemapping[node->planenum] = bsp->numplanes; + if (planemapping.a[node->planenum] == -1) { // a new plane + planemapping.a[node->planenum] = bsp->numplanes; - plane = &planes[node->planenum]; + plane = &planes.a[node->planenum]; VectorCopy (plane->normal, dplane.normal); dplane.dist = plane->dist; @@ -102,7 +100,7 @@ WriteNodePlanes_r (node_t *node) BSP_AddPlane (bsp, &dplane); } - node->outputplanenum = planemapping[node->planenum]; + node->outputplanenum = planemapping.a[node->planenum]; WriteNodePlanes_r (node->children[0]); WriteNodePlanes_r (node->children[1]); @@ -111,7 +109,8 @@ WriteNodePlanes_r (node_t *node) void WriteNodePlanes (node_t *nodes) { - memset (planemapping, -1, sizeof (planemapping)); + DARRAY_RESIZE (&planemapping, planes.size); + memset (planemapping.a, -1, planemapping.size * sizeof (planemapping.a[0])); WriteNodePlanes_r (nodes); } @@ -176,8 +175,6 @@ WriteLeaf (const node_t *node) for (fp = node->markfaces; *fp; fp++) { // emit a marksurface - if (bsp->nummarksurfaces == MAX_MAP_MARKSURFACES) - Sys_Error ("nummarksurfaces == MAX_MAP_MARKSURFACES"); f = *fp; if (f->texturenum < 0) continue; @@ -206,8 +203,6 @@ WriteDrawNodes_r (const node_t *node) int nodenum = bsp->numnodes; // emit a node - if (bsp->numnodes == MAX_MAP_NODES) - Sys_Error ("numnodes == MAX_MAP_NODES"); BSP_AddNode (bsp, &dummy); n = &bsp->nodes[nodenum]; From 5fc1a36d92cb0117f96f940fa396dcf68e2b4f3a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jul 2021 13:35:35 +0900 Subject: [PATCH 1680/3664] [gamecode] Be more forgiving of unresolved builtins If the progs code never calls the functions, then there is no problem. Thus unresolved builtin references get pointed to the bad function builtin. --- include/QF/progs.h | 1 + libs/gamecode/pr_builtins.c | 41 ++++++++++++++++++++++++------------- libs/gamecode/pr_opcode.c | 2 +- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index e6ea11575..8922c0763 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1816,6 +1816,7 @@ struct progs_s { struct hashtab_s *builtin_hash; struct hashtab_s *builtin_num_hash; struct biblock_s *builtin_blocks; + pr_int_t bi_no_function; unsigned bi_next; unsigned (*bi_map) (progs_t *pr, unsigned binum); ///@} diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index efee00fd2..b5c9ae0a0 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -88,6 +88,19 @@ builtin_next (progs_t *pr) return pr->bi_next++; } +static void +bi_no_function (progs_t *pr) +{ + // no need for checking: the /only/ way to get here is via a function + // descriptor with a bad builtin number + dstatement_t *st = pr->pr_statements + pr->pr_xstatement; + dfunction_t *desc = pr->pr_functions + G_FUNCTION (pr, st->a); + const char *bi_name = PR_GetString (pr, desc->s_name); + int ind = -desc->first_statement; + + PR_RunError (pr, "Bad builtin called: %s = #%d", bi_name, ind); +} + VISIBLE void PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins) { @@ -103,6 +116,14 @@ PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins) pr->hashlink_freelist); Hash_SetHashCompare (pr->builtin_num_hash, builtin_get_hash, builtin_compare); + + bi = malloc (sizeof (builtin_t)); + bi->name = "invalid function"; + bi->proc = bi_no_function; + bi->binum = builtin_next (pr); + pr->bi_no_function = bi->binum; + DARRAY_APPEND (pr->builtin_blocks, bi); + Hash_AddElement (pr->builtin_num_hash, bi); } // count = 1 for terminator @@ -149,19 +170,6 @@ PR_FindBuiltinNum (progs_t *pr, pr_int_t num) return (builtin_t *) Hash_FindElement (pr->builtin_num_hash, &bi); } -static void -bi_no_function (progs_t *pr) -{ - // no need for checking: the /only/ way to get here is via a function - // descriptor with a bad builtin number - dstatement_t *st = pr->pr_statements + pr->pr_xstatement; - dfunction_t *desc = pr->pr_functions + G_FUNCTION (pr, st->a); - const char *bi_name = PR_GetString (pr, desc->s_name); - int ind = -desc->first_statement; - - PR_RunError (pr, "Bad builtin called: %s = #%d", bi_name, ind); -} - VISIBLE int PR_RelocateBuiltins (progs_t *pr) { @@ -200,6 +208,7 @@ PR_RelocateBuiltins (progs_t *pr) if (!bi) { Sys_Printf ("PR_RelocateBuiltins: %s: undefined builtin %s\n", pr->progs_name, bi_name); + desc->first_statement = -pr->bi_no_function; bad = 1; continue; } @@ -223,5 +232,9 @@ PR_RelocateBuiltins (progs_t *pr) func->first_statement = desc->first_statement; func->func = proc; } - return !bad; + if (bad) { + Sys_Printf ("PR_RelocateBuiltins: %s: progs may not work due to " + "unresolved builtins\n", pr->progs_name); + } + return 1; } diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 15cdb93ad..2c893b39f 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -1595,7 +1595,7 @@ check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type, msg = "DENORMAL float detected. These progs are probably " "using qccx arrays and integers. If just simple arrays " "are being used, then they should work, but if " - "internal.qc is used, they most definitely will NOT. To" + "internal.qc is used, they most definitely will NOT. To " "allow these progs to be used, set pr_boundscheck to 1."; goto error; } From c02fcee58a128059c2796af202d84f2b19883220 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jul 2021 15:43:57 +0900 Subject: [PATCH 1681/3664] [util] Make zone functions 64-bit clean This allows nq and qw clients/servers to use over 2GB of memory if necessary. --- include/QF/zone.h | 27 +++++----- libs/util/zone.c | 117 +++++++++++++++++++++----------------------- nq/source/host.c | 8 +-- qw/source/cl_main.c | 6 +-- qw/source/sv_main.c | 6 +-- 5 files changed, 81 insertions(+), 83 deletions(-) diff --git a/include/QF/zone.h b/include/QF/zone.h index 023ff07d6..2f0b00520 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -92,31 +92,32 @@ typedef struct memzone_s memzone_t; -void Memory_Init (void *buf, int size); +void Memory_Init (void *buf, size_t size); -void Z_ClearZone (memzone_t *zone, int size, int zone_offset, int ele_size); +void Z_ClearZone (memzone_t *zone, size_t size, size_t zone_offset, + size_t ele_size); void Z_Free (memzone_t *zone, void *ptr); -void *Z_Malloc (memzone_t *zone, int size); // returns 0 filled memory -void *Z_TagMalloc (memzone_t *zone, int size, int tag); -void *Z_Realloc (memzone_t *zone, void *ptr, int size); +void *Z_Malloc (memzone_t *zone, size_t size); // returns 0 filled memory +void *Z_TagMalloc (memzone_t *zone, size_t size, int tag); +void *Z_Realloc (memzone_t *zone, void *ptr, size_t size); void Z_Print (memzone_t *zone); void Z_CheckHeap (memzone_t *zone); void Z_SetError (memzone_t *zone, void (*err) (void *data, const char *msg), void *data); -void Z_CheckPointer (const memzone_t *zone, const void *ptr, int size); +void Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size); void Hunk_Print (qboolean all); -void *Hunk_Alloc (int size); // returns 0 filled memory -void *Hunk_AllocName (int size, const char *name); -int Hunk_LowMark (void) __attribute__((pure)); -void Hunk_FreeToLowMark (int mark); -void *Hunk_TempAlloc (int size); +void *Hunk_Alloc (size_t size); // returns 0 filled memory +void *Hunk_AllocName (size_t size, const char *name); +size_t Hunk_LowMark (void) __attribute__((pure)); +void Hunk_FreeToLowMark (size_t mark); +void *Hunk_TempAlloc (size_t size); void Hunk_Check (void); struct cache_user_s; -typedef void *(*cache_allocator_t) (struct cache_user_s *c, int size, const char *name); +typedef void *(*cache_allocator_t) (struct cache_user_s *c, size_t size, const char *name); typedef void (*cache_loader_t) (void *object, cache_allocator_t allocator); typedef struct cache_user_s { void *data; @@ -130,7 +131,7 @@ void *Cache_Check (cache_user_t *c); // if present, otherwise returns NULL void Cache_Free (cache_user_t *c); -void *Cache_Alloc (cache_user_t *c, int size, const char *name); +void *Cache_Alloc (cache_user_t *c, size_t size, const char *name); // Returns NULL if all purgable data was tossed and there still // wasn't enough room. void Cache_Report (void); diff --git a/libs/util/zone.c b/libs/util/zone.c index 40a43fb07..6cbff65b5 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -70,22 +70,21 @@ static qboolean Cache_FreeLRU (void); all big things are allocated on the hunk. */ -typedef struct memblock_s -{ - int block_size; // including the header and possibly tiny fragments +typedef struct memblock_s { + size_t block_size; // including the header and possibly tiny fragments + struct memblock_s *next; + struct memblock_s *prev; + size_t size; // requested size int tag; // a tag of 0 is a free block - struct memblock_s *next, *prev; - int size; // requested size int id; // should be ZONEID //int id2; // pad to 64 bit boundary } memblock_t; -struct memzone_s -{ - int size; // total bytes malloced, including header - int used; // ammount used, including header - int offset; - int ele_size; +struct memzone_s { + size_t size; // total bytes malloced, including header + size_t used; // ammount used, including header + size_t offset; + size_t ele_size; void (*error) (void *, const char *); void *data; memblock_t blocklist; // start / end cap for linked list @@ -108,7 +107,7 @@ z_offset (memzone_t *zone, memblock_t *block) } VISIBLE void -Z_ClearZone (memzone_t *zone, int size, int zone_offset, int ele_size) +Z_ClearZone (memzone_t *zone, size_t size, size_t zone_offset, size_t ele_size) { memblock_t *block; @@ -201,7 +200,7 @@ Z_Free (memzone_t *zone, void *ptr) } VISIBLE void * -Z_Malloc (memzone_t *zone, int size) +Z_Malloc (memzone_t *zone, size_t size) { void *buf; @@ -210,7 +209,7 @@ Z_Malloc (memzone_t *zone, int size) buf = Z_TagMalloc (zone, size, 1); if (!buf) { const char *msg; - msg = nva ("Z_Malloc: failed on allocation of %i bytes",size); + msg = nva ("Z_Malloc: failed on allocation of %zd bytes", size); if (zone->error) zone->error (zone->data, msg); Sys_Error ("%s", msg); @@ -221,7 +220,7 @@ Z_Malloc (memzone_t *zone, int size) } void * -Z_TagMalloc (memzone_t *zone, int size, int tag) +Z_TagMalloc (memzone_t *zone, size_t size, int tag) { int extra; int requested_size = size; @@ -284,9 +283,9 @@ Z_TagMalloc (memzone_t *zone, int size, int tag) } VISIBLE void * -Z_Realloc (memzone_t *zone, void *ptr, int size) +Z_Realloc (memzone_t *zone, void *ptr, size_t size) { - int old_size; + size_t old_size; memblock_t *block; void *old_ptr; @@ -315,7 +314,7 @@ Z_Realloc (memzone_t *zone, void *ptr, int size) ptr = Z_TagMalloc (zone, size, 1); if (!ptr) { const char *msg; - msg = nva ("Z_Realloc: failed on allocation of %i bytes", size); + msg = nva ("Z_Realloc: failed on allocation of %zd bytes", size); if (zone->error) zone->error (zone->data, msg); Sys_Error ("%s", msg); @@ -334,7 +333,7 @@ Z_Print (memzone_t *zone) { memblock_t *block; - Sys_Printf ("zone size: %i location: %p used: %i\n", + Sys_Printf ("zone size: %zd location: %p used: %zd\n", zone->size, zone, zone->used); for (block = zone->blocklist.next ; ; block = block->next) { @@ -386,7 +385,7 @@ Z_SetError (memzone_t *zone, void (*err) (void *, const char *), void *data) } void -Z_CheckPointer (const memzone_t *zone, const void *ptr, int size) +Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size) { const memblock_t *block; const char *block_mem; @@ -411,17 +410,19 @@ Z_CheckPointer (const memzone_t *zone, const void *ptr, int size) //============================================================================ typedef struct { - int sentinal; - int size; // including sizeof(hunk_t), -1 = not allocated + int sentinal1; + int sentinal2; + size_t size; // including sizeof(hunk_t), -1 = not allocated char name[8]; - char fill[48]; // pad out to 64 bytes + // pad out to 64 bytes + char fill[64 - 2 * sizeof (int) - sizeof (size_t) - 8]; } hunk_t; byte *hunk_base; -int hunk_size; -int hunk_low_used; -int hunk_high_used; -int hunk_tempmark; +size_t hunk_size; +size_t hunk_low_used; +size_t hunk_high_used; +size_t hunk_tempmark; qboolean hunk_tempactive; @@ -435,11 +436,11 @@ Hunk_Check (void) { hunk_t *h; - for (h = (hunk_t *) hunk_base; (byte *) h != hunk_base + hunk_low_used;) { - if (h->sentinal != HUNK_SENTINAL) + for (h = (hunk_t *) hunk_base; (byte *) h < hunk_base + hunk_low_used; ) { + if (h->sentinal1 != HUNK_SENTINAL || h->sentinal2 != HUNK_SENTINAL) Sys_Error ("Hunk_Check: trashed sentinal"); - if (h->size < (int) sizeof (hunk_t) - || h->size + (byte *) h - hunk_base > hunk_size) + if (h->size < sizeof (hunk_t) + || h->size + (byte *) h > hunk_base + hunk_size) Sys_Error ("Hunk_Check: bad size"); h = (hunk_t *) ((byte *) h + h->size); } @@ -468,14 +469,14 @@ Hunk_Print (qboolean all) starthigh = (hunk_t *) (hunk_base + hunk_size - hunk_high_used); endhigh = (hunk_t *) (hunk_base + hunk_size); - Sys_Printf (" :%8i total hunk size\n", hunk_size); + Sys_Printf (" :%8zd total hunk size\n", hunk_size); Sys_Printf ("-------------------------\n"); while (1) { // skip to the high hunk if done with low hunk if (h == endlow) { Sys_Printf ("-------------------------\n"); - Sys_Printf (" :%8i REMAINING\n", + Sys_Printf (" :%8zd REMAINING\n", hunk_size - hunk_low_used - hunk_high_used); Sys_Printf ("-------------------------\n"); h = starthigh; @@ -485,10 +486,10 @@ Hunk_Print (qboolean all) break; // run consistancy checks - if (h->sentinal != HUNK_SENTINAL) + if (h->sentinal1 != HUNK_SENTINAL || h->sentinal2 != HUNK_SENTINAL) Sys_Error ("Hunk_Check: trahsed sentinal"); if (h->size < (int) sizeof (hunk_t) - || h->size + (byte *) h - hunk_base > hunk_size) + || h->size + (byte *) h > hunk_base + hunk_size) Sys_Error ("Hunk_Check: bad size"); next = (hunk_t *) ((byte *) h + h->size); @@ -498,7 +499,7 @@ Hunk_Print (qboolean all) // print the single block if (all) - Sys_Printf ("%8p :%8i %8.8s\n", h, h->size, h->name); + Sys_Printf ("%8p :%8zd %8.8s\n", h, h->size, h->name); // print the total if (next == endlow || next == endhigh || @@ -517,14 +518,14 @@ Hunk_Print (qboolean all) } static void -Hunk_FreeToHighMark (int mark) +Hunk_FreeToHighMark (size_t mark) { if (hunk_tempactive) { hunk_tempactive = false; Hunk_FreeToHighMark (hunk_tempmark); } - if (mark < 0 || mark > hunk_high_used) - Sys_Error ("Hunk_FreeToHighMark: bad mark %i", mark); + if (mark > hunk_high_used) + Sys_Error ("Hunk_FreeToHighMark: bad mark %zd", mark); memset (hunk_base + hunk_size - hunk_high_used, 0, hunk_high_used - mark); hunk_high_used = mark; } @@ -541,7 +542,7 @@ Hunk_HighMark (void) } VISIBLE void * -Hunk_AllocName (int size, const char *name) +Hunk_AllocName (size_t size, const char *name) { hunk_t *h; @@ -549,9 +550,6 @@ Hunk_AllocName (int size, const char *name) Hunk_Check (); #endif - if (size < 0) - Sys_Error ("Hunk_Alloc: bad size: %i", size); - size = sizeof (hunk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); if (hunk_size - hunk_low_used - hunk_high_used < size) { @@ -565,7 +563,7 @@ Hunk_AllocName (int size, const char *name) Cache_Profile (); Sys_Error ("Not enough RAM allocated. Try starting using \"-mem %d\" on " - "the %s command line. (%d - %d - %d < %d)", mem, + "the %s command line. (%zd - %zd - %zd < %zd)", mem, PACKAGE_NAME, hunk_size, hunk_low_used, hunk_high_used, size); } @@ -577,7 +575,8 @@ Hunk_AllocName (int size, const char *name) memset (h, 0, size); h->size = size; - h->sentinal = HUNK_SENTINAL; + h->sentinal1 = HUNK_SENTINAL; + h->sentinal2 = HUNK_SENTINAL; memcpy (h->name, name, 8); h->name[7] = 0; @@ -585,34 +584,31 @@ Hunk_AllocName (int size, const char *name) } VISIBLE void * -Hunk_Alloc (int size) +Hunk_Alloc (size_t size) { return Hunk_AllocName (size, "unknown"); } -VISIBLE int +VISIBLE size_t Hunk_LowMark (void) { return hunk_low_used; } VISIBLE void -Hunk_FreeToLowMark (int mark) +Hunk_FreeToLowMark (size_t mark) { - if (mark < 0 || mark > hunk_low_used) - Sys_Error ("Hunk_FreeToLowMark: bad mark %i", mark); + if (mark > hunk_low_used) + Sys_Error ("Hunk_FreeToLowMark: bad mark %zd", mark); memset (hunk_base + mark, 0, hunk_low_used - mark); hunk_low_used = mark; } static void * -Hunk_HighAlloc (int size) +Hunk_HighAlloc (size_t size) { hunk_t *h; - if (size < 0) - Sys_Error ("Hunk_HighAlloc: bad size: %i", size); - if (hunk_tempactive) { Hunk_FreeToHighMark (hunk_tempmark); hunk_tempactive = false; @@ -624,14 +620,15 @@ Hunk_HighAlloc (int size) size = sizeof (hunk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); if (hunk_size - hunk_low_used - hunk_high_used < size) { - Sys_Printf ("Hunk_HighAlloc: failed on %i bytes\n", size); + Sys_Printf ("Hunk_HighAlloc: failed on %zd bytes\n", size); return NULL; } hunk_high_used += size; h = (void *) (hunk_base + hunk_size - hunk_high_used); - h->sentinal = HUNK_SENTINAL; + h->sentinal1 = HUNK_SENTINAL; + h->sentinal2 = HUNK_SENTINAL; h->size = size; h->name[0] = 0; return h + 1; @@ -643,7 +640,7 @@ Hunk_HighAlloc (int size) Return space from the top of the hunk */ VISIBLE void * -Hunk_TempAlloc (int size) +Hunk_TempAlloc (size_t size) { void *buf; @@ -1006,7 +1003,7 @@ Cache_Free (cache_user_t *c) } VISIBLE void * -Cache_Alloc (cache_user_t *c, int size, const char *name) +Cache_Alloc (cache_user_t *c, size_t size, const char *name) { cache_system_t *cs; @@ -1014,7 +1011,7 @@ Cache_Alloc (cache_user_t *c, int size, const char *name) Sys_Error ("Cache_Alloc: already allocated"); if (size <= 0) - Sys_Error ("Cache_Alloc: size %i", size); + Sys_Error ("Cache_Alloc: size %zd", size); size = (size + sizeof (cache_system_t) + HUNK_ALIGN - 1) & ~(HUNK_ALIGN-1); @@ -1120,7 +1117,7 @@ Cache_ReadLock (cache_user_t *c) //============================================================================ VISIBLE void -Memory_Init (void *buf, int size) +Memory_Init (void *buf, size_t size) { hunk_base = buf; hunk_size = size; diff --git a/nq/source/host.c b/nq/source/host.c index 69870013d..dc96020a9 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -96,7 +96,7 @@ double oldcon_realtime; int host_framecount; int host_hunklevel; int host_in_game; -int minimum_memory; +size_t minimum_memory; client_t *host_client; // current client @@ -812,7 +812,7 @@ static void Host_Init_Memory (void) { int mem_parm = COM_CheckParm ("-mem"); - int mem_size; + size_t mem_size; void *mem_base; if (standard_quake) @@ -831,7 +831,7 @@ Host_Init_Memory (void) Cvar_SetFlags (host_mem_size, host_mem_size->flags | CVAR_ROM); - mem_size = (int) (host_mem_size->value * 1024 * 1024); + mem_size = ((size_t) host_mem_size->value * 1024 * 1024); if (mem_size < minimum_memory) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", @@ -840,7 +840,7 @@ Host_Init_Memory (void) mem_base = Sys_Alloc (mem_size); if (!mem_base) - Sys_Error ("Can't allocate %d", mem_size); + Sys_Error ("Can't allocate %zd", mem_size); Sys_PageIn (mem_base, mem_size); Memory_Init (mem_base, mem_size); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 48919dbab..de8290cb8 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1706,7 +1706,7 @@ static void CL_Init_Memory (void) { int mem_parm = COM_CheckParm ("-mem"); - int mem_size; + size_t mem_size; void *mem_base; cl_mem_size = Cvar_Get ("cl_mem_size", "32", CVAR_NONE, NULL, @@ -1720,7 +1720,7 @@ CL_Init_Memory (void) Cvar_SetFlags (cl_mem_size, cl_mem_size->flags | CVAR_ROM); - mem_size = (int) (cl_mem_size->value * 1024 * 1024); + mem_size = ((size_t) cl_mem_size->value * 1024 * 1024); if (mem_size < MINIMUM_MEMORY) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", @@ -1729,7 +1729,7 @@ CL_Init_Memory (void) mem_base = Sys_Alloc (mem_size); if (!mem_base) - Sys_Error ("Can't allocate %d", mem_size); + Sys_Error ("Can't allocate %zd", mem_size); Sys_PageIn (mem_base, mem_size); Memory_Init (mem_base, mem_size); diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 30e2709c1..4ec4c99af 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2450,7 +2450,7 @@ static void SV_Init_Memory (void) { int mem_parm = COM_CheckParm ("-mem"); - int mem_size; + size_t mem_size; void *mem_base; sv_mem_size = Cvar_Get ("sv_mem_size", "8", CVAR_NONE, NULL, @@ -2464,7 +2464,7 @@ SV_Init_Memory (void) Cvar_SetFlags (sv_mem_size, sv_mem_size->flags | CVAR_ROM); - mem_size = (int) (sv_mem_size->value * 1024 * 1024); + mem_size = ((size_t) sv_mem_size->value * 1024 * 1024); if (mem_size < MINIMUM_MEMORY) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", @@ -2473,7 +2473,7 @@ SV_Init_Memory (void) mem_base = Sys_Alloc (mem_size); if (!mem_base) - Sys_Error ("Can't allocate %d", mem_size); + Sys_Error ("Can't allocate %zd", mem_size); Memory_Init (mem_base, mem_size); } From cf96f340df0e978b018aeecce822767fb4de087b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jul 2021 15:44:27 +0900 Subject: [PATCH 1682/3664] [util] Use same distance calc in simd CC test The test started failing when optimizing (not sure why). Using the same code to calculate the squared distance "fixes" the test. --- libs/util/test/test-csvf.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/util/test/test-csvf.c b/libs/util/test/test-csvf.c index e90aab0c0..58ca3f47c 100644 --- a/libs/util/test/test-csvf.c +++ b/libs/util/test/test-csvf.c @@ -51,7 +51,8 @@ int main (int argc, const char **argv) { int res = 0; - size_t i, j; + size_t i; + int j; vspheref_t sphere; mtstate_t mt; double start, end; @@ -77,6 +78,7 @@ main (int argc, const char **argv) vec4f_t cloud[4]; vspheref_t cc; vec_t r2; + vec_t fr; for (j = 0; j < 4; j++) { VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), cloud[j]); @@ -84,15 +86,13 @@ main (int argc, const char **argv) cc = CircumSphere_vf (cloud, 4); r2 = cc.radius * cc.radius; for (j = 0; j < 4; j++) { - if (fabs (VectorDistance_fast (cloud[j], cc.center) - r2) - < 1e-3 * r2) + vec4f_t d = cloud[j] - cc.center; + fr = dotf (d, d)[0]; + if (fabs (fr - r2) < 1e-3 * r2) continue; - printf ("%d %.9g - %.9g = %.9g\n", (int)j, - VectorDistance_fast (cloud[j], cc.center), r2, - VectorDistance_fast (cloud[j], cc.center) - r2); + printf ("%d %.9g - %.9g = %.9g %.9g\n", j, fr, r2, fr - r2, fabs(fr - r2)); printf ("[%.9g %.9g %.9g] - [%.9g %.9g %.9g] = %.9g != %.9g\n", - VectorExpand (cloud[j]), VectorExpand (cc.center), - VectorDistance_fast (cloud[j], cc.center), r2); + VectorExpand (cloud[j]), VectorExpand (cc.center), fr, r2); res = 1; } } From bd2ceca13a1e909addcdfdd38889480034122156 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jul 2021 22:36:07 +0900 Subject: [PATCH 1683/3664] [qw] Move the pvs and phs sets into single hunks Hunk_Alloc has a rather large per-block overhead. Also, small pvs sets (64 leafs) will fit into just the basic set structure so no need to allocate data for the maps. --- qw/source/sv_init.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index e88459d0d..b63ea71cd 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -214,6 +214,31 @@ SV_SaveSpawnparms (void) } } +static set_t * +sv_alloc_vis_array (unsigned numleafs) +{ + unsigned size = SET_SIZE (numleafs); + + if (size > SET_DEFMAP_SIZE * SET_BITS) { + set_t *sets = Hunk_Alloc (numleafs * (sizeof (set_t) + size / 8)); + unsigned words = size / SET_BITS; + set_bits_t *bits = (set_bits_t *) (&sets[numleafs] + 1); + for (unsigned i = 0; i < numleafs; i++) { + sets[i].size = size; + sets[i].map = bits; + bits += words; + } + return sets; + } else { + set_t *sets = Hunk_Alloc (numleafs * (sizeof (set_t) + size / 8)); + for (unsigned i = 0; i < numleafs; i++) { + sets[i].size = size; + sets[i].map = sets[i].defmap; + } + return sets; + } +} + /* SV_CalcPHS @@ -223,16 +248,15 @@ SV_SaveSpawnparms (void) static void SV_CalcPHS (void) { - int count, num, vcount, i; + int64_t count, vcount; + int num, i; SV_Printf ("Building PHS...\n"); - num = sv.worldmodel->brush.numleafs; - sv.pvs = Hunk_Alloc (num * sizeof (set_t)); + sv.pvs = sv_alloc_vis_array (num); vcount = 0; for (i = 0; i < num; i++) { - sv.pvs[i] = (set_t) SET_STATIC_INIT (num, Hunk_Alloc); Mod_LeafPVS_set (sv.worldmodel->brush.leafs + i, sv.worldmodel, 0xff, &sv.pvs[i]); if (i == 0) @@ -243,10 +267,9 @@ SV_CalcPHS (void) } } - sv.phs = Hunk_Alloc (num * sizeof (set_t)); + sv.phs = sv_alloc_vis_array (num); count = 0; for (i = 0; i < num; i++) { - sv.phs[i] = (set_t) SET_STATIC_INIT (num, Hunk_Alloc); set_assign (&sv.phs[i], &sv.pvs[i]); for (set_iter_t *iter = set_first (&sv.pvs[i]); iter; @@ -265,7 +288,7 @@ SV_CalcPHS (void) } SV_Printf ("Average leafs visible / hearable / total: %i / %i / %i\n", - vcount / num, count / num, num); + (int) (vcount / num), (int) (count / num), num); } static unsigned int From 946867c82e3e912d3f8ca7d9b4d9aa61c01e52ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jul 2021 22:42:03 +0900 Subject: [PATCH 1684/3664] [qfvis] Start work on an off-line fat pvs compiler Extremely large maps take a very long time to process their PVS sets for PHS or shadows, so having an off-line compiler seems like a good idea. The data isn't written out yet, and the fat pvs code may not be optimal for cache access, but it gets through ad_tears in about 500s (12 threads, compared to 2100s single-threaded in the qw server). --- tools/qfvis/include/options.h | 2 + tools/qfvis/include/vis.h | 8 ++ tools/qfvis/source/Makemodule.am | 1 + tools/qfvis/source/fatpvs.c | 214 +++++++++++++++++++++++++++++++ tools/qfvis/source/options.c | 11 ++ tools/qfvis/source/qfvis.c | 114 +++++++++------- 6 files changed, 304 insertions(+), 46 deletions(-) create mode 100644 tools/qfvis/source/fatpvs.c diff --git a/tools/qfvis/include/options.h b/tools/qfvis/include/options.h index cd6349aa8..4af2c67ac 100644 --- a/tools/qfvis/include/options.h +++ b/tools/qfvis/include/options.h @@ -34,6 +34,8 @@ typedef struct { int verbosity; // 0=silent int threads; qboolean minimal; + qboolean no_auto_pvs; + qboolean fat_pvs; int level; size_t portal_limit; struct dstring_s *bspfile; diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 9367760b4..c2c1edfed 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -213,4 +213,12 @@ void PortalBase (basethread_t *thread, portal_t *portal); void PortalFlow (threaddata_t *data, portal_t *portal); void CalcAmbientSounds (void); +void CalcFatPVS (void); + +void RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)); + +extern const char spinner[]; +extern const char progress[]; +extern int *working; + #endif// __vis_h diff --git a/tools/qfvis/source/Makemodule.am b/tools/qfvis/source/Makemodule.am index cb11f2406..7efb7bbe2 100644 --- a/tools/qfvis/source/Makemodule.am +++ b/tools/qfvis/source/Makemodule.am @@ -7,6 +7,7 @@ bin_PROGRAMS += @QFVIS_TARGETS@ qfvis_SOURCES = \ tools/qfvis/source/base-vis.c \ + tools/qfvis/source/fatpvs.c \ tools/qfvis/source/flow.c \ tools/qfvis/source/options.c \ tools/qfvis/source/qfvis.c \ diff --git a/tools/qfvis/source/fatpvs.c b/tools/qfvis/source/fatpvs.c new file mode 100644 index 000000000..749f540d3 --- /dev/null +++ b/tools/qfvis/source/fatpvs.c @@ -0,0 +1,214 @@ +/* + fatpvs.c + + PVS PHS generator tool + + Copyright (C) 2021 Bil Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/bspfile.h" +#include "QF/set.h" +#include "QF/sys.h" + +#include "tools/qfvis/include/options.h" +#include "tools/qfvis/include/vis.h" + +static set_pool_t *set_pool; +static set_t *base_pvs; +static set_t *fat_pvs; + +static unsigned num_leafs; +static unsigned work_leaf; + +static int +print_progress (int prev_prog, int spinner_ind) +{ + int prog; + prog = work_leaf * 50 / num_leafs; + if (prog > prev_prog) + printf ("%.*s", prog - prev_prog, progress + prev_prog); + printf (" %c\b\b", spinner[spinner_ind % 4]); + fflush (stdout); + return prog; +} + +static unsigned +next_leaf (void) +{ + unsigned leaf = ~0; + WRLOCK (global_lock); + if (work_leaf < num_leafs) { + leaf = work_leaf++; + } + UNLOCK (global_lock); + return leaf; +} + +static inline void +decompress_vis (const byte *in, unsigned numleafs, set_t *pvs) +{ + byte *out = (byte *) pvs->map; + byte *start = out; + int row, c; + + row = (numleafs + 7) >> 3; + + if (!in) { // no vis info, so make all visible + while (row) { + *out++ = 0xff; + row--; + } + return; + } + + do { + if (*in) { + *out++ = *in++; + continue; + } + + c = in[1]; + in += 2; + while (c) { + *out++ = 0; + c--; + } + } while (out - start < row); +} + +static void * +decompress_thread (void *d) +{ + int thread = (intptr_t) d; + int64_t count = 0; + + while (1) { + unsigned leaf_num = next_leaf (); + + if (working) + working[thread] = leaf_num; + if (leaf_num == ~0u) { + return 0; + } + byte *visdata = 0; + dleaf_t *leaf = &bsp->leafs[leaf_num]; + if (leaf->visofs >= 0) { + visdata = bsp->visdata + leaf->visofs; + } + decompress_vis (visdata, num_leafs, &base_pvs[leaf_num]); + if (leaf_num == 0) { + continue; + } + for (set_iter_t *iter = set_first_r (&set_pool[thread], + &base_pvs[leaf_num]); + iter; + iter = set_next_r (&set_pool[thread], iter)) { + count++; + } + } +} + +static void * +fatten_thread (void *d) +{ + int thread = (intptr_t) d; + int64_t count = 0; + + while (1) { + unsigned leaf_num = next_leaf (); + + if (working) + working[thread] = leaf_num; + if (leaf_num == ~0u) { + return 0; + } + + set_assign (&fat_pvs[leaf_num], &base_pvs[leaf_num]); + for (set_iter_t *iter = set_first_r (&set_pool[thread], + &base_pvs[leaf_num]); + iter; + iter = set_next_r (&set_pool[thread], iter)) { + + // or this pvs row into the fat pvs + // +1 because pvs is 1 based + set_union (&fat_pvs[leaf_num], &base_pvs[iter->element + 1]); + } + if (leaf_num == 0) { + continue; + } + for (set_iter_t *iter = set_first_r (&set_pool[thread], + &base_pvs[leaf_num]); + iter; + iter = set_next_r (&set_pool[thread], iter)) { + count++; + } + } +} +#if 0 +static void * +fatten_thread2 (void *d) +{ + for (unsigned visword = 0; visword < SET_WORDS (&sv.pvs[0]); visword++) { + Sys_Printf ("%d / %ld\n", visword, SET_WORDS (&sv.pvs[0])); + for (i = 0; i < num; i++) { + for (unsigned j = 0; j < SET_BITS; j++) { + unsigned visbit = visword * SET_BITS + j; + if (visbit >= (unsigned) num) { + break; + } + if (SET_TEST_MEMBER (&sv.pvs[i], visbit)) { + // or this pvs row into the phs + // +1 because pvs is 1 based + set_union (&sv.phs[i], &sv.pvs[visbit + 1]); + } + } + } + } + for (i = 1; i < num; i++) { + for (set_iter_t *iter = set_first (&sv.phs[i]); iter; + iter = set_next (iter)) { + count++; + } + } +} +#endif +void +CalcFatPVS (void) +{ + set_pool = calloc (options.threads, sizeof (set_pool_t)); + num_leafs = bsp->models[0].visleafs; + base_pvs = malloc (num_leafs * sizeof (set_t)); + fat_pvs = malloc (num_leafs * sizeof (set_t)); + for (unsigned i = 0; i < num_leafs; i++) { + base_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs, malloc); + fat_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs, malloc); + } + work_leaf = 0; + RunThreads (decompress_thread, print_progress); + work_leaf = 0; + RunThreads (fatten_thread, print_progress); +} diff --git a/tools/qfvis/source/options.c b/tools/qfvis/source/options.c index e66eca278..291f67c63 100644 --- a/tools/qfvis/source/options.c +++ b/tools/qfvis/source/options.c @@ -49,9 +49,13 @@ const char *this_program; enum { start_opts = 255, // not used, starts the enum. OPT_PORTAL_LIMIT, + OPT_FAT_PVS, + OPT_FULL_PVS, }; static struct option const long_options[] = { + {"fat-pvs", no_argument, 0, OPT_FAT_PVS}, + {"full-pvs", no_argument, 0, OPT_FULL_PVS}, {"quiet", no_argument, 0, 'q'}, {"verbose", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, @@ -140,6 +144,13 @@ DecodeArgs (int argc, char **argv) case OPT_PORTAL_LIMIT: options.portal_limit = atoi (optarg); break; + case OPT_FAT_PVS: + options.fat_pvs = true; + options.no_auto_pvs = true; + break; + case OPT_FULL_PVS: + options.fat_pvs = true; + break; case 'm': // minimal vis options.minimal = true; break; diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index b6e0f3248..e66d8e436 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -693,10 +693,16 @@ print_progress (int prev_prog, int spinner_ind) return prog; } +typedef struct { + int thread; + int (*progress)(int, int); +} watch_data_t; + static void * -WatchThread (void *_thread) +WatchThread (void *_wd) { - int thread = (intptr_t) _thread; + watch_data_t *wd = _wd; + int thread = wd->thread; int *local_work = malloc (thread * sizeof (int)); int i; int spinner_ind = 0; @@ -720,7 +726,7 @@ WatchThread (void *_thread) if (options.verbosity >= 4) print_thread_stats (local_work, thread, spinner_ind); else if (options.verbosity >= 0) - prev_prog = print_progress (prev_prog, spinner_ind); + prev_prog = wd->progress (prev_prog, spinner_ind); if (prev_port != portal_count || stalled++ == 10) { prev_port = portal_count; stalled = 0; @@ -738,8 +744,8 @@ WatchThread (void *_thread) } #endif -static void -RunThreads (void *(*thread_func) (void *)) +void +RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)) { #ifdef USE_PTHREADS pthread_t *work_threads; @@ -754,8 +760,9 @@ RunThreads (void *(*thread_func) (void *)) thread_func, (void *) (intptr_t) i) == -1) Sys_Error ("pthread_create failed"); } + watch_data_t wd = { i, progress }; if (pthread_create (&work_threads[i], &threads_attrib, - WatchThread, (void *) (intptr_t) i) == -1) + WatchThread, &wd) == -1) Sys_Error ("pthread_create failed"); for (i = 0; i < options.threads; i++) { @@ -770,7 +777,7 @@ RunThreads (void *(*thread_func) (void *)) thread_func (0); } #else - LeafThread (0); + thread_func (0); #endif } @@ -887,7 +894,7 @@ BasePortalVis (void) printf ("\n"); start = Sys_DoubleTime (); - RunThreads (BaseVisThread); + RunThreads (BaseVisThread, print_progress); end = Sys_DoubleTime (); if (options.verbosity >= 1) { @@ -924,7 +931,7 @@ CalcPortalVis (void) portal_count = 0; - RunThreads (LeafThread); + RunThreads (LeafThread, print_progress); if (options.verbosity >= 1) { printf ("portalcheck: %i portaltest: %i portalpass: %i\n", @@ -1343,35 +1350,12 @@ LoadPortals (char *name) Qclose (f); } -int -main (int argc, char **argv) +static void +generate_pvs (void) { - double start, stop; - dstring_t *portalfile = dstring_new (); QFile *f; - main_thread.memsuper = new_memsuper (); - - start = Sys_DoubleTime (); - - this_program = argv[0]; - - DecodeArgs (argc, argv); - - InitThreads (); - - if (!options.bspfile) { - usage (1); - Sys_Error ("%s: no bsp file specified.", this_program); - } - - QFS_SetExtension (options.bspfile, ".bsp"); - - f = Qopen (options.bspfile->str, "rb"); - if (!f) - Sys_Error ("couldn't open %s for reading.", options.bspfile->str); - bsp = LoadBSPFile (f, Qfilesize (f)); - Qclose (f); + dstring_t *portalfile = dstring_new (); visdata = dstring_new (); @@ -1400,21 +1384,59 @@ main (int argc, char **argv) WriteBSPFile (bsp, f); Qclose (f); + dstring_delete (portalfile); + dstring_delete (visdata); + dstring_delete (options.bspfile); + free (leafcluster); + free (uncompressed); + free (portals); + free (clusters); +} + +int +main (int argc, char **argv) +{ + double start, stop; + QFile *f; + + main_thread.memsuper = new_memsuper (); + + start = Sys_DoubleTime (); + + this_program = argv[0]; + + DecodeArgs (argc, argv); + + InitThreads (); + + if (!options.bspfile) { + usage (1); + Sys_Error ("%s: no bsp file specified.", this_program); + } + + QFS_SetExtension (options.bspfile, ".bsp"); + + f = Qopen (options.bspfile->str, "rb"); + if (!f) + Sys_Error ("couldn't open %s for reading.", options.bspfile->str); + bsp = LoadBSPFile (f, Qfilesize (f)); + Qclose (f); + + if (!options.no_auto_pvs) { + generate_pvs (); + } + if (options.fat_pvs) { + CalcFatPVS (); + } + + BSP_Free (bsp); + + EndThreads (); + stop = Sys_DoubleTime (); if (options.verbosity >= -1) printf ("%5.1f seconds elapsed\n", stop - start); - dstring_delete (portalfile); - dstring_delete (visdata); - dstring_delete (options.bspfile); - BSP_Free (bsp); - free (leafcluster); - free (uncompressed); - free (portals); - free (clusters); - - EndThreads (); - return 0; } From 05fa0538aba184eb9368998ccbdb76796ded0e9b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 11:34:17 +0900 Subject: [PATCH 1685/3664] [qw] Count leafs correctly for PHS This fixes some out-by-one bugs caused by there being an obo bug in the original SV_CalcPHS: space was being allocated for numleafs leafs, but numleafs does not count the world-surrounding solid leaf 0, but SV_CalcPHS generates pvs and phs data (just the "everything" set) for leaf 0, which is later used for broadcasts and the like. --- qw/source/sv_init.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index b63ea71cd..a5cd05aac 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -217,12 +217,14 @@ SV_SaveSpawnparms (void) static set_t * sv_alloc_vis_array (unsigned numleafs) { - unsigned size = SET_SIZE (numleafs); + // the passed in numleafs is the true number of leafs in the map and thus + // does include leaf 0, but pvs bits do not include leaf 0 + unsigned size = SET_SIZE (numleafs - 1); if (size > SET_DEFMAP_SIZE * SET_BITS) { set_t *sets = Hunk_Alloc (numleafs * (sizeof (set_t) + size / 8)); unsigned words = size / SET_BITS; - set_bits_t *bits = (set_bits_t *) (&sets[numleafs] + 1); + set_bits_t *bits = (set_bits_t *) (&sets[numleafs]); for (unsigned i = 0; i < numleafs; i++) { sets[i].size = size; sets[i].map = bits; @@ -230,7 +232,7 @@ sv_alloc_vis_array (unsigned numleafs) } return sets; } else { - set_t *sets = Hunk_Alloc (numleafs * (sizeof (set_t) + size / 8)); + set_t *sets = Hunk_Alloc (numleafs * sizeof (set_t)); for (unsigned i = 0; i < numleafs; i++) { sets[i].size = size; sets[i].map = sets[i].defmap; @@ -252,7 +254,12 @@ SV_CalcPHS (void) int num, i; SV_Printf ("Building PHS...\n"); - num = sv.worldmodel->brush.numleafs; + //numleafs does NOT include the world-surrounding solid leaf at + //brush.leafs[0], so brush.leafs is actually [0]..[numleafs] + //however, pvs bits also do not include leaf 0 as it should not be + //able to see anything (but instead sees everything) + //FIXME make numleafs actual number of leafs? + num = sv.worldmodel->brush.numleafs + 1; sv.pvs = sv_alloc_vis_array (num); vcount = 0; From 49c3dacbbc5b1a7f5a2fa6d4568d9ed58b7507ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 11:52:21 +0900 Subject: [PATCH 1686/3664] [util] Rename set_size to set_count After seeing set_size and thinking it redundant (thought it returned the capacity of the set until I checked), I realized set_count would be a much better name (set_count (node->successors) in qfcc does make much more sense). --- include/QF/set.h | 2 +- libs/ruamoko/rua_set.c | 8 ++++---- libs/util/set.c | 2 +- ruamoko/include/Set.h | 2 +- ruamoko/lib/Set.r | 2 +- tools/qfcc/source/flow.c | 4 ++-- tools/qfvis/source/qfvis.c | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/QF/set.h b/include/QF/set.h index 61bd865aa..7fb0f8538 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -340,7 +340,7 @@ int set_is_member (const set_t *set, unsigned x) __attribute__((pure)); \return The number of (non-)members. Both empty sets and sets of evertything will return 0. */ -unsigned set_size (const set_t *set) __attribute__((pure)); +unsigned set_count (const set_t *set) __attribute__((pure)); /** Find the first "member" of the set. diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 343e0ced0..8bc1915a9 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -364,11 +364,11 @@ bi_set_is_member (progs_t *pr) } static void -bi_set_size (progs_t *pr) +bi_set_count (progs_t *pr) { bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - R_INT (pr) = set_size (set->set); + R_INT (pr) = set_count (set->set); } static void @@ -645,7 +645,7 @@ bi_i_Set__size (progs_t *pr) PR_RESET_PARAMS (pr); P_INT (pr, 0) = set_obj->set; - bi_set_size (pr); + bi_set_count (pr); } static void @@ -696,7 +696,7 @@ static builtin_t builtins[] = { {"set_is_equivalent", bi_set_is_equivalent, -1}, {"set_is_subset", bi_set_is_subset, -1}, {"set_is_member", bi_set_is_member, -1}, - {"set_size", bi_set_size, -1}, + {"set_count", bi_set_count, -1}, {"set_first", bi_set_first, -1}, {"set_next", bi_set_next, -1}, {"set_as_string", bi_set_as_string, -1}, diff --git a/libs/util/set.c b/libs/util/set.c index 869fcc74e..ffb0e5489 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -551,7 +551,7 @@ set_is_member (const set_t *set, unsigned x) } unsigned -set_size (const set_t *set) +set_count (const set_t *set) { unsigned count = 0; unsigned i; diff --git a/ruamoko/include/Set.h b/ruamoko/include/Set.h index 24a772565..1f7c39177 100644 --- a/ruamoko/include/Set.h +++ b/ruamoko/include/Set.h @@ -25,7 +25,7 @@ typedef struct set_iter_s *set_iter_t; @extern int set_is_equivalent (set_t *s1, set_t *s2); @extern int set_is_subset (set_t *set, set_t *sub); @extern int set_is_member (set_t *set, unsigned x); -@extern unsigned set_size (set_t *set); +@extern unsigned set_count (set_t *set); @extern set_iter_t *set_first (set_t *set); @extern set_iter_t *set_next (set_iter_t *set_iter); @extern string set_as_string (set_t *set); diff --git a/ruamoko/lib/Set.r b/ruamoko/lib/Set.r index 9e215ec51..393bb31ac 100644 --- a/ruamoko/lib/Set.r +++ b/ruamoko/lib/Set.r @@ -20,7 +20,7 @@ int set_is_intersecting (set_t *s1, set_t *s2) = #0; int set_is_equivalent (set_t *s1, set_t *s2) = #0; int set_is_subset (set_t *set, set_t *sub) = #0; int set_is_member (set_t *set, unsigned x) = #0; -unsigned set_size (set_t *set) = #0; +unsigned set_count (set_t *set) = #0; set_iter_t *set_first (set_t *set) = #0; set_iter_t *set_next (set_iter_t *set_iter) = #0; string set_as_string (set_t *set) = #0; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 3a1bb54c1..3128fa686 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1300,12 +1300,12 @@ flow_find_successors (flowgraph_t *graph) set_add (node->successors, graph->num_nodes + 1); } } - graph->num_edges += set_size (node->successors); + graph->num_edges += set_count (node->successors); } // set the successor for the entry dummy node to the real entry node node = graph->nodes[graph->num_nodes]; set_add (node->successors, 0); - graph->num_edges += set_size (node->successors); + graph->num_edges += set_count (node->successors); } static void diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index e66d8e436..4a7e5009e 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -858,7 +858,7 @@ ClusterFlow (int clusternum) set_add (visclusters, clusternum); - numvis = set_size (visclusters); + numvis = set_count (visclusters); // expand to cluster->leaf PVS ClusterFlowExpand (visclusters, outbuffer); From 50740c1014432f601d9864b7d03b2cd5f2cb8588 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 12:32:40 +0900 Subject: [PATCH 1687/3664] [model] Remove the confusion about numleafs The fact that numleafs did not include leaf 0 actually caused in many places due to never being sure whether to add 1. Hopefully this fixes some of the confusion. (and that comment in sv_init didn't last long :P) --- include/QF/model.h | 3 +- libs/models/brush/model_brush.c | 30 +++++++++++--------- libs/video/renderer/gl/gl_rmisc.c | 2 +- libs/video/renderer/r_bsp.c | 2 +- libs/video/renderer/r_light.c | 4 +-- libs/video/renderer/sw/sw_rmain.c | 3 +- libs/video/renderer/sw32/sw32_rmain.c | 3 +- libs/video/renderer/vulkan/vulkan_lighting.c | 13 +++++---- nq/source/sv_main.c | 4 +-- nq/source/sv_pr_cmds.c | 2 +- qw/source/sv_ents.c | 4 +-- qw/source/sv_init.c | 7 +---- qw/source/sv_pr_cmds.c | 2 +- 13 files changed, 39 insertions(+), 40 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 5a3b568c3..9cbc322f6 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -230,7 +230,8 @@ typedef struct mod_brush_s { int numplanes; plane_t *planes; - unsigned numleafs; // number of visible leafs, not counting 0 + unsigned modleafs; ///< number of leafs in model, including 0 + unsigned visleafs; ///< number of visible leafs, not counting 0 mleaf_t *leafs; int numvertexes; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index c111cdfb7..ac9901c01 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -92,7 +92,7 @@ Mod_DecompressVis_set (const byte *in, const mod_brush_t *brush, byte defvis, byte *start = out; int row, c; - row = (brush->numleafs + 7) >> 3; + row = (brush->visleafs + 7) >> 3; if (!in) { // no vis info, so make all visible while (row) { @@ -125,7 +125,7 @@ Mod_DecompressVis_mix (const byte *in, const mod_brush_t *brush, byte defvis, byte *start = out; int row, c; - row = (brush->numleafs + 7) >> 3; + row = (brush->visleafs + 7) >> 3; if (!in) { // no vis info, so make all visible while (row) { @@ -152,7 +152,7 @@ Mod_LeafPVS (const mleaf_t *leaf, const model_t *model) { static set_t *novis; static set_t *decompressed; - unsigned numvis = model->brush.numleafs; + unsigned numvis = model->brush.visleafs; if (leaf == model->brush.leafs) { if (!novis) { @@ -180,7 +180,7 @@ VISIBLE void Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, set_t *out) { - unsigned numvis = model->brush.numleafs; + unsigned numvis = model->brush.visleafs; set_expand (out, numvis); if (leaf == model->brush.leafs) { unsigned excess = SET_SIZE (numvis) - numvis; @@ -195,7 +195,7 @@ VISIBLE void Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, set_t *out) { - unsigned numvis = model->brush.numleafs; + unsigned numvis = model->brush.visleafs; set_expand (out, numvis); if (leaf == model->brush.leafs) { unsigned excess = SET_SIZE (numvis) - numvis; @@ -673,7 +673,7 @@ Mod_SetParent (mod_brush_t *brush, mnode_t *node, mnode_t *parent) static void Mod_SetLeafFlags (mod_brush_t *brush) { - for (unsigned i = 0; i < brush->numleafs; i++) { + for (unsigned i = 0; i < brush->modleafs; i++) { int flags = 0; mleaf_t *leaf = &brush->leafs[i]; for (int j = 0; j < leaf->nummarksurfaces; j++) { @@ -723,12 +723,12 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) out->children[j] = brush->nodes + p; } else { p = ~p; - if ((unsigned) p < brush->numleafs) { + if ((unsigned) p < brush->modleafs) { out->children[j] = (mnode_t *) (brush->leafs + p); } else { Sys_Printf ("Mod_LoadNodes: invalid leaf index %i " "(file has only %i leafs)\n", p, - brush->numleafs); + brush->modleafs); //map it to the solid leaf out->children[j] = (mnode_t *)(brush->leafs); } @@ -736,11 +736,11 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) } } - size_t size = (brush->numleafs + brush->numnodes) * sizeof (mnode_t *); - size += brush->numleafs * sizeof (int); + size_t size = (brush->modleafs + brush->numnodes) * sizeof (mnode_t *); + size += brush->modleafs * sizeof (int); brush->node_parents = Hunk_AllocName (size, mod->name); brush->leaf_parents = brush->node_parents + brush->numnodes; - brush->leaf_flags = (int *) (brush->leaf_parents + brush->numleafs); + brush->leaf_flags = (int *) (brush->leaf_parents + brush->modleafs); Mod_SetParent (brush, brush->nodes, NULL); // sets nodes and leafs Mod_SetLeafFlags (brush); } @@ -759,7 +759,7 @@ Mod_LoadLeafs (model_t *mod, bsp_t *bsp) out = Hunk_AllocName (count * sizeof (*out), mod->name); brush->leafs = out; - brush->numleafs = count; + brush->modleafs = count; // snprintf(s, sizeof (s), "maps/%s.bsp", // Info_ValueForKey(cl.serverinfo,"map")); if (!strncmp ("maps/", mod->path, 5)) @@ -1088,7 +1088,11 @@ Mod_LoadBrushModel (model_t *mod, void *buffer) mod->radius = RadiusFromBounds (mod->mins, mod->maxs); - mod->brush.numleafs = bm->visleafs; + mod->brush.visleafs = bm->visleafs; + // The bsp file has leafs for all submodes and hulls, so update the + // leaf count for this model to be the correct number (which is one + // more than the number of visible leafs) + mod->brush.modleafs = bm->visleafs + 1; if (i < mod->brush.numsubmodels - 1) { // duplicate the basic information diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 689d38f75..c2d98b3f1 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -197,7 +197,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) R_FreeAllEntities (); // clear out efrags in case the level hasn't been reloaded - for (unsigned i = 0; i < brush->numleafs; i++) + for (unsigned i = 0; i < brush->modleafs; i++) brush->leafs[i].efrags = NULL; // Force a vis update diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index b7ac3614f..695f7e063 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -75,7 +75,7 @@ R_MarkLeaves (void) } else vis = Mod_LeafPVS (r_viewleaf, r_worldentity.renderer.model); - for (unsigned i = 0; i < brush->numleafs; i++) { + for (unsigned i = 0; i < brush->visleafs; i++) { if (set_is_member (vis, i)) { leaf = &brush->leafs[i + 1]; if ((c = leaf->nummarksurfaces)) { diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 52169f05b..7debf10c1 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -281,13 +281,13 @@ R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, maxs[0] = lightorigin[0] + radius; maxs[1] = lightorigin[1] + radius; maxs[2] = lightorigin[2] + radius; - while (leafnum < brush->numleafs) { + while (leafnum < brush->visleafs) { int b; if (!(vis_bits = *in++)) { leafnum += (*in++) * 8; continue; } - for (b = 1; b < 256 && leafnum < brush->numleafs; + for (b = 1; b < 256 && leafnum < brush->visleafs; b <<= 1, leafnum++) { int m; mleaf_t *leaf = &brush->leafs[leafnum + 1]; diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 59699a8aa..f84c218b2 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -172,8 +172,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) R_FreeAllEntities (); // clear out efrags in case the level hasn't been reloaded - // FIXME: is this one short? - for (unsigned i = 0; i < brush->numleafs; i++) + for (unsigned i = 0; i < brush->modleafs; i++) brush->leafs[i].efrags = NULL; if (brush->skytexture) diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 2aa7f2921..6f1fee59f 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -187,8 +187,7 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) R_FreeAllEntities (); // clear out efrags in case the level hasn't been reloaded - // FIXME: is this one short? - for (unsigned i = 0; i < brush->numleafs; i++) + for (unsigned i = 0; i < brush->modleafs; i++) brush->leafs[i].efrags = NULL; if (brush->skytexture) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index f2e2b012c..ce13b7bed 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -71,9 +71,9 @@ static vec4f_t ref_direction = { 0, 0, 1, 0 }; static void expand_pvs (set_t *pvs, model_t *model) { - set_t base_pvs = SET_STATIC_INIT (model->brush.numleafs, alloca); + set_t base_pvs = SET_STATIC_INIT (model->brush.visleafs, alloca); set_assign (&base_pvs, pvs); - for (unsigned i = 0; i < model->brush.numleafs; i++) { + for (unsigned i = 0; i < model->brush.visleafs; i++) { if (set_is_member (&base_pvs, i)) { Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, pvs); } @@ -105,7 +105,7 @@ find_visible_lights (vulkan_ctx_t *ctx) Mod_LeafPVS_set (leaf, model, 0, lframe->pvs); expand_pvs (lframe->pvs, model); } - for (unsigned i = 0; i < model->brush.numleafs; i++) { + for (unsigned i = 0; i < model->brush.visleafs; i++) { if (set_is_member (lframe->pvs, i)) { flags |= model->brush.leaf_flags[i + 1]; } @@ -556,7 +556,7 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model) //float sunlight2; vec3_t sunangle = { 0, -90, 0 }; - set_expand (lctx->sun_pvs, model->brush.numleafs); + set_expand (lctx->sun_pvs, model->brush.visleafs); set_empty (lctx->sun_pvs); sunlight = parse_float (PL_String (PL_ObjectForKey (entity, "_sunlight")), 0); @@ -577,9 +577,10 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model) // Any leaf with sky surfaces can potentially see the sun, thus put // the sun "in" every leaf with a sky surface - for (unsigned l = 0; l < model->brush.numleafs; l++) { + // however, skip leaf 0 as it is the exterior solid leaf + for (unsigned l = 1; l < model->brush.modleafs; l++) { if (model->brush.leaf_flags[l] & SURF_DRAWSKY) { - set_add (lctx->sun_pvs, l); + set_add (lctx->sun_pvs, l - 1); //pvs is 1-based } } // any leaf visible from a leaf with a sky surface (and thus the sun) diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index eec256779..f8aace8c4 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -430,9 +430,9 @@ static set_t * SV_FatPVS (vec3_t org) { if (!fatpvs) { - fatpvs = set_new_size (sv.worldmodel->brush.numleafs); + fatpvs = set_new_size (sv.worldmodel->brush.visleafs); } - set_expand (fatpvs, sv.worldmodel->brush.numleafs); + set_expand (fatpvs, sv.worldmodel->brush.visleafs); set_empty (fatpvs); SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); return fatpvs; diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 4a0aa76a7..0e133a2f0 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -585,7 +585,7 @@ PF_newcheckclient (progs_t *pr, int check) VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); leaf = Mod_PointInLeaf (org, sv.worldmodel); if (!checkpvs) { - checkpvs = set_new_size (sv.worldmodel->brush.numleafs); + checkpvs = set_new_size (sv.worldmodel->brush.visleafs); } set_assign (checkpvs, Mod_LeafPVS (leaf, sv.worldmodel)); diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index b7505dfb0..e38c2ca67 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -97,9 +97,9 @@ static set_t * SV_FatPVS (vec3_t org) { if (!fatpvs) { - fatpvs = set_new_size (sv.worldmodel->brush.numleafs); + fatpvs = set_new_size (sv.worldmodel->brush.visleafs); } - set_expand (fatpvs, sv.worldmodel->brush.numleafs); + set_expand (fatpvs, sv.worldmodel->brush.visleafs); set_empty (fatpvs); SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); return fatpvs; diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index a5cd05aac..359b74570 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -254,13 +254,8 @@ SV_CalcPHS (void) int num, i; SV_Printf ("Building PHS...\n"); - //numleafs does NOT include the world-surrounding solid leaf at - //brush.leafs[0], so brush.leafs is actually [0]..[numleafs] - //however, pvs bits also do not include leaf 0 as it should not be - //able to see anything (but instead sees everything) - //FIXME make numleafs actual number of leafs? - num = sv.worldmodel->brush.numleafs + 1; + num = sv.worldmodel->brush.modleafs; sv.pvs = sv_alloc_vis_array (num); vcount = 0; for (i = 0; i < num; i++) { diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 6b2b85389..f651599fb 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -506,7 +506,7 @@ PF_newcheckclient (progs_t *pr, int check) VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); leaf = Mod_PointInLeaf (org, sv.worldmodel); if (!checkpvs) { - checkpvs = set_new_size (sv.worldmodel->brush.numleafs); + checkpvs = set_new_size (sv.worldmodel->brush.visleafs); } set_assign (checkpvs, Mod_LeafPVS (leaf, sv.worldmodel)); From 163d14704491e56d98909b0180c46913cd601366 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 13:54:22 +0900 Subject: [PATCH 1688/3664] [util] Give set_count a >8x speed boost I knew counting bits individually was slow, but it never really mattered until now. However, I didn't expect such a dramatic boost just by going to mapping bytes to bit counts. 16-bit words would be faster still, but the 64kB lookup table would probably start hurting cache performance, and 32-bit words (4GB table) definitely would ruin the cache. The universe isn't big enough for 64-bits :) --- libs/util/set.c | 27 +++++++++++++++++++++++---- libs/util/test/test-set.c | 12 ++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/libs/util/set.c b/libs/util/set.c index ffb0e5489..f0215454c 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -553,12 +553,31 @@ set_is_member (const set_t *set, unsigned x) unsigned set_count (const set_t *set) { + static byte bit_counts[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, + }; unsigned count = 0; - unsigned i; + byte *b = (byte *) set->map; + unsigned i = SET_WORDS (set) * sizeof (set_bits_t); - for (i = 0; i < set->size; i++) - if (_set_is_member (set, i)) - count++; + while (i-- > 0) { + count += bit_counts[*b++]; + } return count; } diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index e1b93d137..6e326268a 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -83,6 +83,12 @@ check_size (const set_t *set, const set_t *unused) return set->size; } +static int +check_count (const set_t *set, const set_t *unused) +{ + return set_count (set); +} + static set_t * make_5 (void) { @@ -198,6 +204,7 @@ struct { {make_55, make_5, set_union, set_is_equivalent, 0, "{5 55}"}, {make_55, make_5, set_union, set_is_intersecting, 1, "{5 55}"}, {make_55, make_5, set_union, set_is_disjoint, 0, "{5 55}"}, + {make_55, make_5, set_union, check_count, 2, "{5 55}"}, {make_not_SIZE, make_everything, 0, set_is_equivalent, 0, 0}, {make_not_SIZE, make_everything, 0, set_is_intersecting, 1, 0}, {make_not_SIZE, make_everything, 0, set_is_disjoint, 0, 0}, @@ -210,6 +217,11 @@ struct { {make_5, make_everything, 0, set_is_equivalent, 0, 0}, {make_5, make_everything, 0, set_is_intersecting, 1, 0}, {make_5, make_everything, 0, set_is_disjoint, 0, 0}, + {make_empty, 0, 0, check_count, 0, 0}, + {make_everything, 0, 0, check_count, 0, 0}, + {make_5, 0, 0, check_count, 1, 0}, + {make_not_5, 0, 0, check_count, 1, 0}, + {make_0_to_SIZEm1, 0, 0, check_size, SIZE, 0}, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) From 1f57f81a207e50594da68aaa52d1534c01834b5c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 14:01:08 +0900 Subject: [PATCH 1689/3664] [qw] Use set_count to count the pvs/phs leafs --- qw/source/sv_init.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 359b74570..15a202e2c 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -263,10 +263,7 @@ SV_CalcPHS (void) &sv.pvs[i]); if (i == 0) continue; - for (set_iter_t *iter = set_first (&sv.pvs[i]); iter; - iter = set_next (iter)) { - vcount++; - } + vcount += set_count (&sv.pvs[i]); } sv.phs = sv_alloc_vis_array (num); @@ -283,10 +280,7 @@ SV_CalcPHS (void) if (i == 0) continue; - for (set_iter_t *iter = set_first (&sv.phs[i]); iter; - iter = set_next (iter)) { - count++; - } + count += set_count (&sv.phs[i]); } SV_Printf ("Average leafs visible / hearable / total: %i / %i / %i\n", From 9e2c474d386e58707a937ed8b304924ca8470029 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 17:54:50 +0900 Subject: [PATCH 1690/3664] [model] Ensure the pvs is not inverted Mod_DecompressVis_set (via Mod_LeafPVS_set) can be used to recycle pvs sets, but the set may have been set to everything at some stage, which is implemented by inverting the set (making the set infinite) and having 1-bits remove elements from the set. This is most definitely not wanted for pvs :) Currently undecided what to do about Mod_DecompressVis_mix, thus the fixme. Fixes the flickering lights in any map where the camera is out of the map for a single frame (eg, start.bsp, The Catacombs (hipnotic, hip2m3)). --- libs/models/brush/model_brush.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index ac9901c01..179fcac7d 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -92,6 +92,8 @@ Mod_DecompressVis_set (const byte *in, const mod_brush_t *brush, byte defvis, byte *start = out; int row, c; + // Ensure the set repesents visible leafs rather than invisible leafs. + pvs->inverted = 0; row = (brush->visleafs + 7) >> 3; if (!in) { // no vis info, so make all visible @@ -125,6 +127,8 @@ Mod_DecompressVis_mix (const byte *in, const mod_brush_t *brush, byte defvis, byte *start = out; int row, c; + //FIXME should pvs->inverted be checked and the vis bits used to remove + // set bits? row = (brush->visleafs + 7) >> 3; if (!in) { // no vis info, so make all visible From b9d2882e022b0f901c79ccbb02ccbf76d6b3c6fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 20:04:19 +0900 Subject: [PATCH 1691/3664] [qfvis] Write out the fat-pvs file The output fat-pvs data is the *difference* between the base pvs and fat pvs. This currently makes for about 64kB savings for marcher.bsp, and about 233MB savings for ad_tears.bsp (or about 50% (470.7MB->237.1MB)). I expect using utf-8 encoding for the run lengths to make for even bigger savings (the second output fat-pvs leaf of marcher.bsp is all 0s, or 6 bytes in the file, which would reduce to 3 bytes using utf-8). --- include/QF/pvsfile.h | 64 ++++++++++++++++++++ tools/qfvis/include/vis.h | 3 + tools/qfvis/source/fatpvs.c | 114 +++++++++++++++++++++++++++++++----- tools/qfvis/source/qfvis.c | 18 +++--- 4 files changed, 175 insertions(+), 24 deletions(-) create mode 100644 include/QF/pvsfile.h diff --git a/include/QF/pvsfile.h b/include/QF/pvsfile.h new file mode 100644 index 000000000..5b57e447c --- /dev/null +++ b/include/QF/pvsfile.h @@ -0,0 +1,64 @@ +/* + pvsfile.h + + External pvs file support + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/07/27 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_pvsfile_h +#define __QF_pvsfile_h + +#include + +#include "QF/qtypes.h" + +/** \defgroup pvsfile External PVS + \ingroup utils + + External PVS data. +*/ +///@{ + +#define PVS_MAGIC "QF PVS\r\n\x1a\x04" +#define PVS_VERSION 1 + +#define PVS_IS_FATPVS 1 ///< data is for fat pvs (phs, lighting, etc) + ///< otherwise it's the base pvs +#define PVS_UTF8_RLE 2 ///< 0-byte run length encoding uses utf-8 + +typedef struct pvsfile_s { + char magic[16]; + + uint32_t version; + uint32_t md4_offset; ///< offset of md4 sum, or 0 if not present + uint32_t flags; + uint32_t visleafs; ///< does NOT include leaf-0 + uint32_t visoffsets[]; ///< does NOT include leaf-0 +} pvsfile_t; + +///@} + +#endif//__QF_pvsfile_h diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index c2c1edfed..2431adfbb 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -41,6 +41,7 @@ #include extern pthread_rwlock_t *global_lock; extern pthread_rwlock_t *portal_locks; +extern pthread_rwlock_t *stats_lock; #define WRLOCK(l) \ do { \ @@ -213,6 +214,8 @@ void PortalBase (basethread_t *thread, portal_t *portal); void PortalFlow (threaddata_t *data, portal_t *portal); void CalcAmbientSounds (void); +int CompressRow (byte *dest, const byte *vis, unsigned num_leafs); + void CalcFatPVS (void); void RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)); diff --git a/tools/qfvis/source/fatpvs.c b/tools/qfvis/source/fatpvs.c index 749f540d3..e5e1e88c5 100644 --- a/tools/qfvis/source/fatpvs.c +++ b/tools/qfvis/source/fatpvs.c @@ -28,10 +28,14 @@ # include "config.h" #endif +#include #include #include "QF/bspfile.h" +#include "QF/pvsfile.h" +#include "QF/quakefs.h" #include "QF/set.h" +#include "QF/sizebuf.h" #include "QF/sys.h" #include "tools/qfvis/include/options.h" @@ -40,10 +44,30 @@ static set_pool_t *set_pool; static set_t *base_pvs; static set_t *fat_pvs; +static sizebuf_t *cmp_pvs; static unsigned num_leafs; +static unsigned visbytes; static unsigned work_leaf; +typedef struct { + long pvs_visible; + long fat_visible; + long fat_bytes; +} fatstats_t; + +fatstats_t fatstats; + +static void +update_stats (fatstats_t *stats) +{ + WRLOCK (stats_lock); + fatstats.pvs_visible += stats->pvs_visible; + fatstats.fat_visible += stats->fat_visible; + fatstats.fat_bytes += stats->fat_bytes; + UNLOCK (stats_lock); +} + static int print_progress (int prev_prog, int spinner_ind) { @@ -103,8 +127,8 @@ decompress_vis (const byte *in, unsigned numleafs, set_t *pvs) static void * decompress_thread (void *d) { + fatstats_t stats = { }; int thread = (intptr_t) d; - int64_t count = 0; while (1) { unsigned leaf_num = next_leaf (); @@ -112,7 +136,7 @@ decompress_thread (void *d) if (working) working[thread] = leaf_num; if (leaf_num == ~0u) { - return 0; + break; } byte *visdata = 0; dleaf_t *leaf = &bsp->leafs[leaf_num]; @@ -123,20 +147,17 @@ decompress_thread (void *d) if (leaf_num == 0) { continue; } - for (set_iter_t *iter = set_first_r (&set_pool[thread], - &base_pvs[leaf_num]); - iter; - iter = set_next_r (&set_pool[thread], iter)) { - count++; - } + stats.pvs_visible += set_count (&base_pvs[leaf_num]); } + update_stats (&stats); + return 0; } static void * fatten_thread (void *d) { + fatstats_t stats = { }; int thread = (intptr_t) d; - int64_t count = 0; while (1) { unsigned leaf_num = next_leaf (); @@ -144,7 +165,7 @@ fatten_thread (void *d) if (working) working[thread] = leaf_num; if (leaf_num == ~0u) { - return 0; + break; } set_assign (&fat_pvs[leaf_num], &base_pvs[leaf_num]); @@ -160,13 +181,11 @@ fatten_thread (void *d) if (leaf_num == 0) { continue; } - for (set_iter_t *iter = set_first_r (&set_pool[thread], - &base_pvs[leaf_num]); - iter; - iter = set_next_r (&set_pool[thread], iter)) { - count++; - } + stats.fat_visible += set_count (&fat_pvs[leaf_num]); + set_difference (&fat_pvs[leaf_num], &base_pvs[leaf_num]); } + update_stats (&stats); + return 0; } #if 0 static void * @@ -196,19 +215,82 @@ fatten_thread2 (void *d) } } #endif + +static void * +compress_thread (void *d) +{ + fatstats_t stats = { }; + int thread = (intptr_t) d; + byte compressed[(visbytes * 3) / 2]; + + while (1) { + unsigned leaf_num = next_leaf (); + + if (working) + working[thread] = leaf_num; + if (leaf_num == ~0u) { + break; + } + const byte *fat_bytes = (const byte *) fat_pvs[leaf_num].map; + int cmp_bytes = CompressRow (compressed, fat_bytes, num_leafs); + SZ_Write (&cmp_pvs[leaf_num], compressed, cmp_bytes); + stats.fat_bytes += cmp_bytes; + } + update_stats (&stats); + return 0; +} + void CalcFatPVS (void) { set_pool = calloc (options.threads, sizeof (set_pool_t)); num_leafs = bsp->models[0].visleafs; + visbytes = (num_leafs + 7) / 8; base_pvs = malloc (num_leafs * sizeof (set_t)); fat_pvs = malloc (num_leafs * sizeof (set_t)); + cmp_pvs = malloc (num_leafs * sizeof (sizebuf_t)); for (unsigned i = 0; i < num_leafs; i++) { base_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs, malloc); fat_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs, malloc); + cmp_pvs[i] = (sizebuf_t) { + .data = malloc ((visbytes * 3) / 2), + .maxsize = (visbytes * 3) / 2, + }; } work_leaf = 0; RunThreads (decompress_thread, print_progress); work_leaf = 0; RunThreads (fatten_thread, print_progress); + work_leaf = 0; + RunThreads (compress_thread, print_progress); + printf ("Average leafs visible / fat visible / total: %d / %d / %d\n", + (int) (fatstats.pvs_visible / num_leafs), + (int) (fatstats.fat_visible / num_leafs), num_leafs); + printf ("Compressed fat vis size: %ld\n", fatstats.fat_bytes); + + uint32_t offset = sizeof (pvsfile_t) + num_leafs * sizeof (uint32_t); + pvsfile_t *pvsfile = malloc (offset + fatstats.fat_bytes); + + strncpy (pvsfile->magic, PVS_MAGIC, sizeof (pvsfile->magic)); + pvsfile->version = PVS_VERSION; + pvsfile->md4_offset = 0; //FIXME add + pvsfile->flags = PVS_IS_FATPVS; + pvsfile->visleafs = num_leafs; + for (unsigned i = 0; i < num_leafs; i++) { + unsigned size = cmp_pvs[i].cursize; + pvsfile->visoffsets[i] = offset; + memcpy ((byte *) pvsfile + offset, cmp_pvs[i].data, size); + offset += size; + } + + dstring_t *pvsname = dstring_new (); + dstring_copystr (pvsname, options.bspfile->str); + QFS_SetExtension (pvsname, ".pvs"); + + QFile *f = Qopen (pvsname->str, "wb"); + if (!f) { + Sys_Error ("couldn't open %s for writing.", pvsname->str); + } + Qwrite (f, pvsfile, offset); + Qclose (f); } diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 4a7e5009e..e27896024 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -442,7 +442,7 @@ UpdateMightsee (threaddata_t *thread, cluster_t *source, cluster_t *dest) } static void -UpdateStates (threaddata_t *thread) +UpdateStats (threaddata_t *thread) { WRLOCK (stats_lock); global_stats.portaltest += thread->stats.portaltest; @@ -512,7 +512,7 @@ PortalCompleted (threaddata_t *thread, portal_t *completed) } set_delete_r (&thread->set_pool, changed); - UpdateStates (thread); + UpdateStats (thread); } static void @@ -734,10 +734,12 @@ WatchThread (void *_wd) } } } - if (options.verbosity >= 4) + if (options.verbosity >= 4) { printf ("watch thread done\n"); - else if (options.verbosity >= 0) + } else if (options.verbosity >= 0) { + prev_prog = wd->progress (prev_prog, spinner_ind); printf ("\n"); + } free (local_work); return NULL; @@ -781,14 +783,14 @@ RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)) #endif } -static int -CompressRow (byte *vis, byte *dest) +int +CompressRow (byte *dest, const byte *vis, unsigned num_leafs) { int rep, visrow, j; byte *dest_p; dest_p = dest; - visrow = (numrealleafs + 7) >> 3; + visrow = (num_leafs + 7) >> 3; for (j = 0; j < visrow; j++) { *dest_p++ = vis[j]; @@ -870,7 +872,7 @@ ClusterFlow (int clusternum) printf ("cluster %4i : %4i visible\n", clusternum, numvis); totalvis += numvis; - i = CompressRow (outbuffer, compressed); + i = CompressRow (compressed, outbuffer, numrealleafs); cluster->visofs = visdata->size; dstring_append (visdata, (char *) compressed, i); } From 5b4428420ed9cbf7ec4bf6af35fa33315150417f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 21:41:35 +0900 Subject: [PATCH 1692/3664] [utils] Get utf-8 writing working for up to 11 bits I need to write some automated tests for this, and reading of course, but 1 and two byte outputs look correct. Kind of sad it took sixteen years to get around to attempting to use the code :( --- libs/util/msg.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/util/msg.c b/libs/util/msg.c index aaf3d364c..338318995 100644 --- a/libs/util/msg.c +++ b/libs/util/msg.c @@ -215,27 +215,27 @@ MSG_WriteUTF8 (sizebuf_t *sb, unsigned utf8) return; // invalid (FIXME die?) } else if (utf8 & 0x7c000000) { buf = SZ_GetSpace (sb, count = 6); - *buf = 0xfc | ((utf8 & 0x40000000) >> 30); // 1 bit + *buf++ = 0xfc | ((utf8 & 0x40000000) >> 30); // 1 bit utf8 <<= 2; } else if (utf8 & 0x03e00000) { buf = SZ_GetSpace (sb, count = 5); - *buf = 0xf8 | ((utf8 & 0x30000000) >> 28); // 2 bits + *buf++ = 0xf8 | ((utf8 & 0x30000000) >> 28); // 2 bits utf8 <<= 4; } else if (utf8 & 0x001f0000) { buf = SZ_GetSpace (sb, count = 4); - *buf = 0xf0 | ((utf8 & 0x001c0000) >> 18); // 3 bits + *buf++ = 0xf0 | ((utf8 & 0x001c0000) >> 18); // 3 bits utf8 <<= 14; } else if (utf8 & 0x0000f800) { buf = SZ_GetSpace (sb, count = 3); - *buf = 0xe0 | ((utf8 & 0x0000f000) >> 12); // 4 bits + *buf++ = 0xe0 | ((utf8 & 0x0000f000) >> 12); // 4 bits utf8 <<= 20; } else if (utf8 & 0x00000780) { buf = SZ_GetSpace (sb, count = 2); - *buf = 0xc0 | ((utf8 & 0x00000780) >> 7); // 5 bits - utf8 <<= 25; + *buf++ = 0xc0 | ((utf8 & 0x000007c0) >> 6); // 5 bits + utf8 <<= 26; } else { buf = SZ_GetSpace (sb, count = 1); - *buf = utf8; + *buf++ = utf8; return; } while (--count) { From e39bc83a6acddb5d42d75c000cf5affca517d649 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 21:47:19 +0900 Subject: [PATCH 1693/3664] [qfvis] Optionally use utf8 to encode run lengths Adds 50 bytes to marcher's fat-pvs, but removes about 4.7MB from ad_tear's fat-pvs. --- tools/qfvis/include/options.h | 1 + tools/qfvis/include/vis.h | 4 +++- tools/qfvis/source/fatpvs.c | 11 +++++++---- tools/qfvis/source/options.c | 5 +++++ tools/qfvis/source/qfvis.c | 35 ++++++++++++++++++++++++----------- 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/tools/qfvis/include/options.h b/tools/qfvis/include/options.h index 4af2c67ac..dd84d17b9 100644 --- a/tools/qfvis/include/options.h +++ b/tools/qfvis/include/options.h @@ -36,6 +36,7 @@ typedef struct { qboolean minimal; qboolean no_auto_pvs; qboolean fat_pvs; + qboolean utf8; int level; size_t portal_limit; struct dstring_s *bspfile; diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 2431adfbb..54b9de0d1 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -214,7 +214,9 @@ void PortalBase (basethread_t *thread, portal_t *portal); void PortalFlow (threaddata_t *data, portal_t *portal); void CalcAmbientSounds (void); -int CompressRow (byte *dest, const byte *vis, unsigned num_leafs); +struct sizebuf_s; +int CompressRow (struct sizebuf_s *dest, const byte *vis, unsigned num_leafs, + int utf8); void CalcFatPVS (void); diff --git a/tools/qfvis/source/fatpvs.c b/tools/qfvis/source/fatpvs.c index e5e1e88c5..c53e08bb5 100644 --- a/tools/qfvis/source/fatpvs.c +++ b/tools/qfvis/source/fatpvs.c @@ -221,7 +221,7 @@ compress_thread (void *d) { fatstats_t stats = { }; int thread = (intptr_t) d; - byte compressed[(visbytes * 3) / 2]; + qboolean rle = options.utf8; while (1) { unsigned leaf_num = next_leaf (); @@ -231,10 +231,10 @@ compress_thread (void *d) if (leaf_num == ~0u) { break; } + sizebuf_t *compressed = &cmp_pvs[leaf_num]; const byte *fat_bytes = (const byte *) fat_pvs[leaf_num].map; - int cmp_bytes = CompressRow (compressed, fat_bytes, num_leafs); - SZ_Write (&cmp_pvs[leaf_num], compressed, cmp_bytes); - stats.fat_bytes += cmp_bytes; + int bytes = CompressRow (compressed, fat_bytes, num_leafs, rle); + stats.fat_bytes += bytes; } update_stats (&stats); return 0; @@ -275,6 +275,9 @@ CalcFatPVS (void) pvsfile->version = PVS_VERSION; pvsfile->md4_offset = 0; //FIXME add pvsfile->flags = PVS_IS_FATPVS; + if (options.utf8) { + pvsfile->flags |= PVS_UTF8_RLE; + } pvsfile->visleafs = num_leafs; for (unsigned i = 0; i < num_leafs; i++) { unsigned size = cmp_pvs[i].cursize; diff --git a/tools/qfvis/source/options.c b/tools/qfvis/source/options.c index 291f67c63..1d384d578 100644 --- a/tools/qfvis/source/options.c +++ b/tools/qfvis/source/options.c @@ -51,11 +51,13 @@ enum { OPT_PORTAL_LIMIT, OPT_FAT_PVS, OPT_FULL_PVS, + OPT_UTF8, }; static struct option const long_options[] = { {"fat-pvs", no_argument, 0, OPT_FAT_PVS}, {"full-pvs", no_argument, 0, OPT_FULL_PVS}, + {"utf8", no_argument, 0, OPT_UTF8}, {"quiet", no_argument, 0, 'q'}, {"verbose", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, @@ -151,6 +153,9 @@ DecodeArgs (int argc, char **argv) case OPT_FULL_PVS: options.fat_pvs = true; break; + case OPT_UTF8: + options.utf8 = true; + break; case 'm': // minimal vis options.minimal = true; break; diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index e27896024..94ba1507f 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -54,8 +54,9 @@ #include "QF/cmem.h" #include "QF/dstring.h" #include "QF/mathlib.h" -#include "QF/qtypes.h" +#include "QF/msg.h" #include "QF/quakefs.h" +#include "QF/sizebuf.h" #include "QF/sys.h" #include "tools/qfvis/include/vis.h" @@ -784,12 +785,14 @@ RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)) } int -CompressRow (byte *dest, const byte *vis, unsigned num_leafs) +CompressRow (sizebuf_t *dest, const byte *vis, unsigned num_leafs, int utf8) { int rep, visrow, j; byte *dest_p; + // if we ever need 2GB (32Gb) of vis data for a single leaf... + int maxrep = utf8 ? 0x7fffffff : 255; - dest_p = dest; + dest_p = dest->data; visrow = (num_leafs + 7) >> 3; for (j = 0; j < visrow; j++) { @@ -799,15 +802,21 @@ CompressRow (byte *dest, const byte *vis, unsigned num_leafs) rep = 1; for (j++; j < visrow; j++) - if (vis[j] || rep == 255) + if (vis[j] || rep == maxrep) break; else rep++; - *dest_p++ = rep; + if (utf8) { + dest->cursize = dest_p - dest->data; + MSG_WriteUTF8 (dest, rep); + dest_p = dest->data + dest->cursize; + } else { + *dest_p++ = rep; + } j--; } - - return dest_p - dest; + dest->cursize = dest_p - dest->data; + return dest->cursize; } static void @@ -835,7 +844,11 @@ void ClusterFlow (int clusternum) { set_t *visclusters; - byte compressed[MAP_PVS_BYTES]; + sizebuf_t compressed = { + .maxsize = (bitbytes_l * 3) / 2, + .data = alloca ((bitbytes_l * 3) / 2) + }; + byte *outbuffer; int numvis, i; cluster_t *cluster; @@ -846,7 +859,7 @@ ClusterFlow (int clusternum) // flow through all portals, collecting visible bits - memset (compressed, 0, sizeof (compressed)); + memset (compressed.data, 0, compressed.maxsize); visclusters = set_new (); for (i = 0; i < cluster->numportals; i++) { portal = cluster->portals[i]; @@ -872,9 +885,9 @@ ClusterFlow (int clusternum) printf ("cluster %4i : %4i visible\n", clusternum, numvis); totalvis += numvis; - i = CompressRow (compressed, outbuffer, numrealleafs); + i = CompressRow (&compressed, outbuffer, numrealleafs, 0); cluster->visofs = visdata->size; - dstring_append (visdata, (char *) compressed, i); + dstring_append (visdata, (char *) compressed.data, i); } static int From 8fdd9c1f5a989ee68a92e8d4b30e6c9c78fb8131 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 27 Jul 2021 23:17:03 +0900 Subject: [PATCH 1694/3664] [util] Write some tests for utf8 r/w And fix some errors with 5-byte encodings. --- libs/util/msg.c | 6 +- libs/util/test/Makemodule.am | 7 ++- libs/util/test/test-utf8.c | 113 +++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 libs/util/test/test-utf8.c diff --git a/libs/util/msg.c b/libs/util/msg.c index 338318995..b221d63c1 100644 --- a/libs/util/msg.c +++ b/libs/util/msg.c @@ -219,8 +219,8 @@ MSG_WriteUTF8 (sizebuf_t *sb, unsigned utf8) utf8 <<= 2; } else if (utf8 & 0x03e00000) { buf = SZ_GetSpace (sb, count = 5); - *buf++ = 0xf8 | ((utf8 & 0x30000000) >> 28); // 2 bits - utf8 <<= 4; + *buf++ = 0xf8 | ((utf8 & 0x03000000) >> 24); // 2 bits + utf8 <<= 8; } else if (utf8 & 0x001f0000) { buf = SZ_GetSpace (sb, count = 4); *buf++ = 0xf0 | ((utf8 & 0x001c0000) >> 18); // 3 bits @@ -231,7 +231,7 @@ MSG_WriteUTF8 (sizebuf_t *sb, unsigned utf8) utf8 <<= 20; } else if (utf8 & 0x00000780) { buf = SZ_GetSpace (sb, count = 2); - *buf++ = 0xc0 | ((utf8 & 0x000007c0) >> 6); // 5 bits + *buf++ = 0xc0 | ((utf8 & 0x000007c0) >> 6); // 5 bits utf8 <<= 26; } else { buf = SZ_GetSpace (sb, count = 1); diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 120780135..4a0e2734c 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -18,7 +18,8 @@ libs_util_tests = \ libs/util/test/test-sebvf \ libs/util/test/test-seg \ libs/util/test/test-set \ - libs/util/test/test-simd + libs/util/test/test-simd \ + libs/util/test/test-utf8 TESTS += $(libs_util_tests) @@ -103,3 +104,7 @@ libs_util_test_test_set_DEPENDENCIES=libs/util/libQFutil.la libs_util_test_test_simd_SOURCES=libs/util/test/test-simd.c libs_util_test_test_simd_LDADD=libs/util/libQFutil.la libs_util_test_test_simd_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_utf8_SOURCES=libs/util/test/test-utf8.c +libs_util_test_test_utf8_LDADD=libs/util/libQFutil.la +libs_util_test_test_utf8_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-utf8.c b/libs/util/test/test-utf8.c new file mode 100644 index 000000000..434d1250d --- /dev/null +++ b/libs/util/test/test-utf8.c @@ -0,0 +1,113 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/msg.h" +#include "QF/sizebuf.h" + +static byte buffer[1024]; +static sizebuf_t sb = { .data = buffer, .maxsize = sizeof (buffer) }; +static qmsg_t msg = { .message = &sb, }; + +typedef struct { + int32_t input; + unsigned bytes; +} utf8_test_t; + +static utf8_test_t tests[] = { + {0x43214321, 6}, + {0x55555555, 6}, + {0x2aaaaaaa, 6}, + {0x55aa55aa, 6}, + {0x1df001ed, 6}, // hey, why not? good bit pattern + {0x089abcde, 6}, + {0x049abcde, 6}, + {0x023abcde, 5}, + {0x012abcde, 5}, + {0x008abcde, 5}, + {0x004abcde, 5}, + {0x002abcde, 5}, + {0x001abcde, 4}, + {0x000abcde, 4}, + {0x0006bcde, 4}, + {0x0002bcde, 4}, + {0x0001bcde, 4}, + {0x0000bcde, 3}, + {0x00007cde, 3}, + {0x00003cde, 3}, + {0x00001cde, 3}, + {0x00000cde, 3}, + {0x000004de, 2}, + {0x000002de, 2}, + {0x000001de, 2}, + {0x000000de, 2}, + {0x0000005e, 1}, + {0x0000004e, 1}, + {0x0000002e, 1}, + {0x0000001e, 1}, + {0x0000000e, 1}, + {0x00000006, 1}, + {0x00000000, 1}, + {0x40000000, 6}, + {0x20000000, 6}, + {0x10000000, 6}, + {0x08000000, 6}, + {0x04000000, 6}, + {0x02000000, 5}, + {0x01000000, 5}, + {0x00800000, 5}, + {0x00400000, 5}, + {0x00200000, 5}, + {0x00100000, 4}, + {0x00080000, 4}, + {0x00040000, 4}, + {0x00020000, 4}, + {0x00010000, 4}, + {0x00008000, 3}, + {0x00004000, 3}, + {0x00002000, 3}, + {0x00001000, 3}, + {0x00000800, 3}, + {0x00000400, 2}, + {0x00000200, 2}, + {0x00000100, 2}, + {0x00000080, 2}, + {0x00000040, 1}, + {0x00000020, 1}, + {0x00000010, 1}, + {0x00000008, 1}, + {0x00000004, 1}, + {0x00000002, 1}, + {0x00000001, 1}, +}; +#define num_tests (sizeof (tests) / (sizeof (tests[0]))) + +int +main (int argc, const char **argv) +{ + int res = 0; + + for (size_t i = 0; i < num_tests; i++) { + sb.cursize = 0; + msg.readcount = 0; + msg.badread = 0; + + MSG_WriteUTF8 (&sb, tests[i].input); + int32_t output = MSG_ReadUTF8 (&msg); + + printf ("%d %08x\n", (int) i, tests[i].input); + SZ_Dump (&sb); + + if (sb.cursize != tests[i].bytes || msg.readcount != tests[i].bytes + || output != tests[i].input || msg.badread) { + res |= 1; + printf ("test %d failed\n", (int) i); + printf ("expect: %8x %d %d 0\n", + tests[i].input, tests[i].bytes, tests[i].bytes); + printf ("got : %8x %d %d %d\n", + output, sb.cursize, msg.readcount, msg.badread); + } + } + return res; +} From 54604d9aa253026ff3b926aa6e2331a24481a4e2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Jul 2021 15:01:45 +0900 Subject: [PATCH 1695/3664] [util] Make hunk (optionally) thread-safe For now, the functions check for a null hunk pointer and use the global hunk (initialized via Memory_Init) if necessary. However, Hunk_Init is available (and used by Memory_Init) to create a hunk from any arbitrary memory block. So long as that block is 64-byte aligned, allocations within the hunk will remain 64-byte aligned. --- include/QF/zone.h | 17 +- libs/gamecode/pr_load.c | 2 +- libs/gib/gib_init.c | 4 +- libs/image/pcx.c | 16 +- libs/image/png.c | 4 +- libs/image/tga.c | 12 +- libs/models/alias/gl_mesh.c | 8 +- libs/models/alias/gl_model_alias.c | 2 +- libs/models/alias/model_alias.c | 21 +- libs/models/alias/sw_model_alias.c | 8 +- libs/models/alias/vulkan_model_alias.c | 4 +- libs/models/brush/gl_model_brush.c | 5 +- libs/models/brush/glsl_model_brush.c | 2 +- libs/models/brush/model_brush.c | 37 +-- libs/models/brush/sw_model_brush.c | 2 +- libs/models/brush/vulkan_model_brush.c | 10 +- libs/models/model.c | 3 +- libs/models/sprite/model_sprite.c | 11 +- libs/net/net_main.c | 2 +- libs/ruamoko/pr_cmds.c | 2 +- libs/util/cmd.c | 4 +- libs/util/info.c | 4 +- libs/util/quakefs.c | 4 +- libs/util/sizebuf.c | 2 +- libs/util/zone.c | 368 +++++++++++++++---------- libs/video/renderer/gl/gl_lightmap.c | 2 +- libs/video/renderer/gl/gl_mod_alias.c | 4 +- libs/video/renderer/gl/gl_rsurf.c | 2 +- libs/video/renderer/gl/gl_screen.c | 2 +- libs/video/renderer/r_iqm.c | 2 +- libs/video/renderer/sw/sw_ralias.c | 2 +- libs/video/renderer/sw/sw_rmain.c | 7 +- libs/video/renderer/sw32/sw32_ralias.c | 2 +- libs/video/renderer/sw32/sw32_rmain.c | 12 +- nq/source/cl_parse.c | 6 +- nq/source/host.c | 8 +- nq/source/host_cmd.c | 8 +- nq/source/sv_phys.c | 10 +- nq/source/sv_pr_cmds.c | 4 +- qw/source/cl_main.c | 6 +- qw/source/cl_parse.c | 2 +- qw/source/cl_skin.c | 2 +- qw/source/sv_ccmds.c | 2 +- qw/source/sv_demo.c | 2 +- qw/source/sv_init.c | 7 +- qw/source/sv_main.c | 4 +- qw/source/sv_phys.c | 10 +- qw/source/sv_pr_cmds.c | 4 +- qw/source/sv_pr_qwe.c | 2 +- qw/source/sv_user.c | 2 +- ruamoko/qwaq/builtins/builtins.c | 2 +- 51 files changed, 375 insertions(+), 295 deletions(-) diff --git a/include/QF/zone.h b/include/QF/zone.h index 2f0b00520..8845cf299 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -106,13 +106,16 @@ void Z_SetError (memzone_t *zone, void (*err) (void *data, const char *msg), void *data); void Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size); -void Hunk_Print (qboolean all); -void *Hunk_Alloc (size_t size); // returns 0 filled memory -void *Hunk_AllocName (size_t size, const char *name); -size_t Hunk_LowMark (void) __attribute__((pure)); -void Hunk_FreeToLowMark (size_t mark); -void *Hunk_TempAlloc (size_t size); -void Hunk_Check (void); +typedef struct memhunk_s memhunk_t; + +memhunk_t *Hunk_Init (void *buf, size_t size); +void Hunk_Print (memhunk_t *hunk, qboolean all); +void Hunk_Check (memhunk_t *hunk); +void *Hunk_Alloc (memhunk_t *hunk, size_t size); // returns 0 filled memory +void *Hunk_AllocName (memhunk_t *hunk, size_t size, const char *name); +size_t Hunk_LowMark (memhunk_t *hunk) __attribute__((pure)); +void Hunk_FreeToLowMark (memhunk_t *hunk, size_t mark); +void *Hunk_TempAlloc (memhunk_t *hunk, size_t size); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 93a69e17d..955242085 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -86,7 +86,7 @@ load_file (progs_t *pr, const char *path, off_t *size) static void * allocate_progs_mem (progs_t *pr, int size) { - return Hunk_AllocName (size, pr->progs_name); + return Hunk_AllocName (0, size, pr->progs_name); } static void diff --git a/libs/gib/gib_init.c b/libs/gib/gib_init.c index 28f1fab1d..f7cc09827 100644 --- a/libs/gib/gib_init.c +++ b/libs/gib/gib_init.c @@ -69,7 +69,7 @@ GIB_Exec_Override_f (void) return; } - mark = Hunk_LowMark (); + mark = Hunk_LowMark (0); f = (char *) QFS_LoadHunkFile (QFS_FOpenFile (Cmd_Argv (1))); if (!f) { Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1)); @@ -95,7 +95,7 @@ GIB_Exec_Override_f (void) Cmd_Argv (0), Cmd_Argv (1)); } else Cbuf_InsertText (cbuf_active, f); - Hunk_FreeToLowMark (mark); + Hunk_FreeToLowMark (0, mark); } VISIBLE void diff --git a/libs/image/pcx.c b/libs/image/pcx.c index a0909536d..2eb512c1d 100644 --- a/libs/image/pcx.c +++ b/libs/image/pcx.c @@ -64,8 +64,8 @@ LoadPCX (QFile *f, qboolean convert, const byte *pal, int load) fsize = Qfilesize(f); } // parse the PCX file - pcx_mark = Hunk_LowMark (); - pcx = Hunk_AllocName (fsize, "PCX"); + pcx_mark = Hunk_LowMark (0); + pcx = Hunk_AllocName (0, fsize, "PCX"); Qread (f, pcx, fsize); pcx->xmax = LittleShort (pcx->xmax); @@ -84,7 +84,7 @@ LoadPCX (QFile *f, qboolean convert, const byte *pal, int load) Sys_Printf ("Bad pcx file: %x %d %d %d\n", pcx->manufacturer, pcx->version, pcx->encoding, pcx->bits_per_pixel); - Hunk_FreeToLowMark (pcx_mark); + Hunk_FreeToLowMark (0, pcx_mark); return 0; } @@ -93,12 +93,12 @@ LoadPCX (QFile *f, qboolean convert, const byte *pal, int load) count = load ? (pcx->xmax + 1) * (pcx->ymax + 1) : 0; if (convert) { - tex = Hunk_TempAlloc (sizeof (tex_t) + count * 3); + tex = Hunk_TempAlloc (0, sizeof (tex_t) + count * 3); tex->data = (byte *) (tex + 1); tex->format = tex_rgb; tex->palette = 0; } else { - tex = Hunk_TempAlloc (sizeof (tex_t) + count); + tex = Hunk_TempAlloc (0, sizeof (tex_t) + count); tex->data = (byte *) (tex + 1); tex->format = tex_palette; if (pal) @@ -110,7 +110,7 @@ LoadPCX (QFile *f, qboolean convert, const byte *pal, int load) tex->height = pcx->ymax + 1; tex->loaded = load; if (!load) { - Hunk_FreeToLowMark (pcx_mark); + Hunk_FreeToLowMark (0, pcx_mark); return tex; } pix = tex->data; @@ -144,7 +144,7 @@ LoadPCX (QFile *f, qboolean convert, const byte *pal, int load) } dataByte++; } - Hunk_FreeToLowMark (pcx_mark); + Hunk_FreeToLowMark (0, pcx_mark); if (count || runLength) { Sys_Printf ("PCX was malformed. You should delete it.\n"); return 0; @@ -162,7 +162,7 @@ EncodePCX (const byte *data, int width, int height, const byte *dataend; size = width * height * 2 + 1000; - if (!(pcx = Hunk_TempAlloc (size))) { + if (!(pcx = Hunk_TempAlloc (0, size))) { Sys_Printf ("EncodePCX: not enough memory\n"); return 0; } diff --git a/libs/image/png.c b/libs/image/png.c index f8fdbcbf6..90fe93463 100644 --- a/libs/image/png.c +++ b/libs/image/png.c @@ -162,10 +162,10 @@ LoadPNG (QFile *infile, int load) /* Allocate tex_t structure */ rowbytes = png_get_rowbytes(png_ptr, info_ptr); - tex = Hunk_TempAlloc (sizeof (tex_t) + height * rowbytes); + tex = Hunk_TempAlloc (0, sizeof (tex_t) + height * rowbytes); tex->data = (byte *) (tex + 1); } else { - tex = Hunk_TempAlloc (sizeof (tex_t)); + tex = Hunk_TempAlloc (0, sizeof (tex_t)); tex->data = 0; } diff --git a/libs/image/tga.c b/libs/image/tga.c index f28076e6e..3491e37ce 100644 --- a/libs/image/tga.c +++ b/libs/image/tga.c @@ -264,7 +264,7 @@ parse_colormap (TargaHeader *targa, byte **dataByte) case 24: case 16: case 15: - cmap = Hunk_AllocName (256 * sizeof (cmap_t), "TGA cmap"); + cmap = Hunk_AllocName (0, 256 * sizeof (cmap_t), "TGA cmap"); break; default: Sys_Error ("LoadTGA: unsupported color map size"); @@ -632,8 +632,8 @@ LoadTGA (QFile *fin, int load) if (load) { fsize = Qfilesize (fin); } - targa_mark = Hunk_LowMark (); - targa = Hunk_AllocName (fsize, "TGA"); + targa_mark = Hunk_LowMark (0); + targa = Hunk_AllocName (0, fsize, "TGA"); Qread (fin, targa, fsize); targa->colormap_index = LittleShort (targa->colormap_index); @@ -646,7 +646,7 @@ LoadTGA (QFile *fin, int load) if (targa->image_type >= NUM_DECODERS || !(decode = decoder_functions[targa->image_type])) { Sys_Printf ("LoadTGA: Unsupported targa type"); - Hunk_FreeToLowMark (targa_mark); + Hunk_FreeToLowMark (0, targa_mark); return 0; } @@ -655,7 +655,7 @@ LoadTGA (QFile *fin, int load) } else { numPixels = 0; } - tex = Hunk_TempAlloc (sizeof (tex_t) + numPixels * 4); + tex = Hunk_TempAlloc (0, sizeof (tex_t) + numPixels * 4); tex->data = (byte *) (tex + 1); tex->width = targa->width; tex->height = targa->height; @@ -670,7 +670,7 @@ LoadTGA (QFile *fin, int load) decode (targa, tex, dataByte); } - Hunk_FreeToLowMark (targa_mark); + Hunk_FreeToLowMark (0, targa_mark); return tex; } diff --git a/libs/models/alias/gl_mesh.c b/libs/models/alias/gl_mesh.c index 310795827..9dba75be7 100644 --- a/libs/models/alias/gl_mesh.c +++ b/libs/models/alias/gl_mesh.c @@ -475,7 +475,7 @@ gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, // save the data out header->poseverts = numorder; - cmds = Hunk_Alloc (numcommands * sizeof (int)); + cmds = Hunk_Alloc (0, numcommands * sizeof (int)); header->commands = (byte *) cmds - (byte *) header; memcpy (cmds, commands, numcommands * sizeof (int)); @@ -490,7 +490,7 @@ gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, } header->poseverts = numorder; - tex_coord = Hunk_Alloc (numorder * sizeof(tex_coord_t)); + tex_coord = Hunk_Alloc (0, numorder * sizeof(tex_coord_t)); header->tex_coord = (byte *) tex_coord - (byte *) header; for (i=0; i < numorder; i++) { float s, t; @@ -510,7 +510,7 @@ gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, if (extra) { trivertx16_t *verts; - verts = Hunk_Alloc (header->numposes * header->poseverts + verts = Hunk_Alloc (0, header->numposes * header->poseverts * sizeof (trivertx16_t)); header->posedata = (byte *) verts - (byte *) header; for (i = 0; i < header->numposes; i++) { @@ -532,7 +532,7 @@ gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, } } else { trivertx_t *verts; - verts = Hunk_Alloc (header->numposes * header->poseverts + verts = Hunk_Alloc (0, header->numposes * header->poseverts * sizeof (trivertx_t)); header->posedata = (byte *) verts - (byte *) header; for (i = 0; i < header->numposes; i++) { diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index ebc5f3b09..85d91c3b2 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -63,7 +63,7 @@ gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, int fb_texnum = 0, texnum = 0; dstring_t *name = dstring_new (); - pskin = Hunk_AllocName (skinsize, alias_ctx->mod->name); + pskin = Hunk_AllocName (0, skinsize, alias_ctx->mod->name); skindesc->skin = (byte *) pskin - (byte *) header; memcpy (pskin, skin, skinsize); diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index 583df43fa..90ec0b9cd 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -66,7 +66,7 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins, Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d", numskins); skinsize = header->mdl.skinwidth * header->mdl.skinheight; - pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), + pskindesc = Hunk_AllocName (0, numskins * sizeof (maliasskindesc_t), alias_ctx->mod->name); *pskinindex = (byte *) pskindesc - (byte *) header; @@ -83,13 +83,13 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins, groupskins = LittleLong (pinskingroup->numskins); t = field_offset (maliasskingroup_t, skindescs[groupskins]); - paliasskingroup = Hunk_AllocName (t, alias_ctx->mod->name); + paliasskingroup = Hunk_AllocName (0, t, alias_ctx->mod->name); paliasskingroup->numskins = groupskins; pskindesc[snum].skin = (byte *) paliasskingroup - (byte *) header; pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1); - poutskinintervals = Hunk_AllocName (groupskins * sizeof (float), + poutskinintervals = Hunk_AllocName (0, groupskins * sizeof (float), alias_ctx->mod->name); paliasskingroup->intervals = (byte *) poutskinintervals - (byte *) header; @@ -173,8 +173,9 @@ Mod_LoadAliasGroup (mod_alias_ctx_t *alias_ctx, void *pin, int *posenum, frame->firstpose = (*posenum); frame->numposes = numframes; - paliasgroup = Hunk_AllocName (field_offset (maliasgroup_t, - frames[numframes]), mod->name); + paliasgroup = Hunk_AllocName (0, field_offset (maliasgroup_t, + frames[numframes]), + mod->name); paliasgroup->numframes = numframes; frame->frame = (byte *) paliasgroup - (byte *) header; @@ -187,7 +188,7 @@ Mod_LoadAliasGroup (mod_alias_ctx_t *alias_ctx, void *pin, int *posenum, alias_ctx->aliasbboxmaxs); pin_intervals = (daliasinterval_t *) (pingroup + 1); - poutintervals = Hunk_AllocName (numframes * sizeof (float), mod->name); + poutintervals = Hunk_AllocName (0, numframes * sizeof (float), mod->name); paliasgroup->intervals = (byte *) poutintervals - (byte *) header; frame->interval = LittleFloat (pin_intervals->interval); for (i = 0; i < numframes; i++) { @@ -237,7 +238,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) CRC_Init (&crc); CRC_ProcessBlock (buffer, &crc, qfs_filesize); - start = Hunk_LowMark (); + start = Hunk_LowMark (0); pinmodel = (mdl_t *) buffer; @@ -249,7 +250,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) // allocate space for a working header, plus all the data except the // frames, skin and group info size = field_offset (aliashdr_t, frames[LittleLong (pinmodel->numframes)]); - header = Hunk_AllocName (size, mod->name); + header = Hunk_AllocName (0, size, mod->name); memset (header, 0, size); alias_ctx.header = header; pmodel = &header->mdl; @@ -375,14 +376,14 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) // move the complete, relocatable alias model to the cache if (m_funcs->alias_cache) { - end = Hunk_LowMark (); + end = Hunk_LowMark (0); total = end - start; mem = allocator (&mod->cache, total, mod->name); if (mem) memcpy (mem, header, total); - Hunk_FreeToLowMark (start); + Hunk_FreeToLowMark (0, start); mod->aliashdr = 0; } else { mod->aliashdr = header; diff --git a/libs/models/alias/sw_model_alias.c b/libs/models/alias/sw_model_alias.c index 0bd57d5ce..62a559332 100644 --- a/libs/models/alias/sw_model_alias.c +++ b/libs/models/alias/sw_model_alias.c @@ -56,7 +56,7 @@ sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, { byte *pskin; - pskin = Hunk_AllocName (skinsize, alias_ctx->mod->name); + pskin = Hunk_AllocName (0, skinsize, alias_ctx->mod->name); skindesc->skin = (byte *) pskin - (byte *) alias_ctx->header; memcpy (pskin, skin, skinsize); @@ -75,7 +75,7 @@ process_frame (mod_alias_ctx_t *alias_ctx, maliasframedesc_t *frame, if (extra) size *= 2; - frame_verts = Hunk_AllocName (size, alias_ctx->mod->name); + frame_verts = Hunk_AllocName (0, size, alias_ctx->mod->name); frame->frame = (byte *) frame_verts - (byte *) header; // The low-order 8 bits (actually, fractional) are completely separate @@ -96,9 +96,9 @@ sw_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, stvert_t *stverts; mtriangle_t *tris; - stverts = (stvert_t *) Hunk_AllocName (numv * sizeof (stvert_t), + stverts = (stvert_t *) Hunk_AllocName (0, numv * sizeof (stvert_t), alias_ctx->mod->name); - tris = (mtriangle_t *) Hunk_AllocName (numt * sizeof (mtriangle_t), + tris = (mtriangle_t *) Hunk_AllocName (0, numt * sizeof (mtriangle_t), alias_ctx->mod->name); header->stverts = (byte *) stverts - (byte *) header; diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 792e8d166..d001909a4 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -121,7 +121,7 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, byte *tskin; int w, h; - skin = Hunk_Alloc (sizeof (qfv_alias_skin_t)); + skin = Hunk_Alloc (0, sizeof (qfv_alias_skin_t)); QuatCopy (vid.palette32 + (TOP_RANGE + 15) * 4, skin->colora); QuatCopy (vid.palette32 + (BOTTOM_RANGE + 15) * 4, skin->colorb); skindesc->skin = (byte *) skin - (byte *) header; @@ -449,7 +449,7 @@ Vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); - qfv_alias_mesh_t *mesh = Hunk_Alloc (sizeof (qfv_alias_mesh_t)); + qfv_alias_mesh_t *mesh = Hunk_Alloc (0, sizeof (qfv_alias_mesh_t)); mesh->vertex_buffer = vbuff; mesh->uv_buffer = uvbuff; mesh->index_buffer = ibuff; diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 610b0bc1a..e4de487e2 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -181,7 +181,8 @@ gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp) dstring_delete (litfilename); return; } - brush->lightdata = Hunk_AllocName (bsp->lightdatasize * mod_lightmap_bytes, + brush->lightdata = Hunk_AllocName (0, + bsp->lightdatasize * mod_lightmap_bytes, litfilename->str); in = bsp->lightdata; out = brush->lightdata; @@ -283,7 +284,7 @@ SubdividePolygon (int numverts, float *verts) return; } - poly = Hunk_Alloc (sizeof (glpoly_t) + (numverts - 4) * VERTEXSIZE * + poly = Hunk_Alloc (0, sizeof (glpoly_t) + (numverts - 4) * VERTEXSIZE * sizeof (float)); poly->next = warpface->polys; warpface->polys = poly; diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index 424205115..6d9942ea6 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -156,6 +156,6 @@ glsl_Mod_LoadLighting (model_t *mod, bsp_t *bsp) mod->brush.lightdata = NULL; return; } - mod->brush.lightdata = Hunk_AllocName (bsp->lightdatasize, mod->name); + mod->brush.lightdata = Hunk_AllocName (0, bsp->lightdatasize, mod->name); memcpy (mod->brush.lightdata, bsp->lightdata, bsp->lightdatasize); } diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 179fcac7d..f121931c7 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -260,7 +260,8 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) m = (dmiptexlump_t *) bsp->texdata; brush->numtextures = m->nummiptex; - brush->textures = Hunk_AllocName (m->nummiptex * sizeof (*brush->textures), + brush->textures = Hunk_AllocName (0, + m->nummiptex * sizeof (*brush->textures), mod->name); for (i = 0; i < m->nummiptex; i++) { @@ -275,7 +276,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) if ((mt->width & 15) || (mt->height & 15)) Sys_Error ("Texture %s is not 16 aligned", mt->name); pixels = mt->width * mt->height / 64 * 85; - tx = Hunk_AllocName (sizeof (texture_t) + pixels, mod->name); + tx = Hunk_AllocName (0, sizeof (texture_t) + pixels, mod->name); brush->textures[i] = tx; @@ -296,7 +297,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) size_t render_size = mod_funcs->texture_render_size; byte *render_data = 0; if (render_size) { - render_data = Hunk_AllocName (m->nummiptex * render_size, + render_data = Hunk_AllocName (0, m->nummiptex * render_size, mod->name); } for (i = 0; i < m->nummiptex; i++) { @@ -397,7 +398,7 @@ Mod_LoadVisibility (model_t *mod, bsp_t *bsp) mod->brush.visdata = NULL; return; } - mod->brush.visdata = Hunk_AllocName (bsp->visdatasize, mod->name); + mod->brush.visdata = Hunk_AllocName (0, bsp->visdatasize, mod->name); memcpy (mod->brush.visdata, bsp->visdata, bsp->visdatasize); } @@ -408,7 +409,7 @@ Mod_LoadEntities (model_t *mod, bsp_t *bsp) mod->brush.entities = NULL; return; } - mod->brush.entities = Hunk_AllocName (bsp->entdatasize, mod->name); + mod->brush.entities = Hunk_AllocName (0, bsp->entdatasize, mod->name); memcpy (mod->brush.entities, bsp->entdata, bsp->entdatasize); } @@ -421,7 +422,7 @@ Mod_LoadVertexes (model_t *mod, bsp_t *bsp) in = bsp->vertexes; count = bsp->numvertexes; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); mod->brush.vertexes = out; mod->brush.numvertexes = count; @@ -439,7 +440,7 @@ Mod_LoadSubmodels (model_t *mod, bsp_t *bsp) in = bsp->models; count = bsp->nummodels; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); brush->submodels = out; brush->numsubmodels = count; @@ -474,7 +475,7 @@ Mod_LoadEdges (model_t *mod, bsp_t *bsp) in = bsp->edges; count = bsp->numedges; - out = Hunk_AllocName ((count + 1) * sizeof (*out), mod->name); + out = Hunk_AllocName (0, (count + 1) * sizeof (*out), mod->name); mod->brush.edges = out; mod->brush.numedges = count; @@ -495,7 +496,7 @@ Mod_LoadTexinfo (model_t *mod, bsp_t *bsp) in = bsp->texinfo; count = bsp->numtexinfo; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); mod->brush.texinfo = out; mod->brush.numtexinfo = count; @@ -597,7 +598,7 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) in = bsp->faces; count = bsp->numfaces; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); if (count > 32767) { Sys_MaskPrintf (SYS_warn, @@ -698,7 +699,7 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) in = bsp->nodes; count = bsp->numnodes; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); if (count > 32767) { Sys_MaskPrintf (SYS_warn, @@ -742,7 +743,7 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) size_t size = (brush->modleafs + brush->numnodes) * sizeof (mnode_t *); size += brush->modleafs * sizeof (int); - brush->node_parents = Hunk_AllocName (size, mod->name); + brush->node_parents = Hunk_AllocName (0, size, mod->name); brush->leaf_parents = brush->node_parents + brush->numnodes; brush->leaf_flags = (int *) (brush->leaf_parents + brush->modleafs); Mod_SetParent (brush, brush->nodes, NULL); // sets nodes and leafs @@ -760,7 +761,7 @@ Mod_LoadLeafs (model_t *mod, bsp_t *bsp) in = bsp->leafs; count = bsp->numleafs; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); brush->leafs = out; brush->modleafs = count; @@ -813,7 +814,7 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) in = bsp->clipnodes; count = bsp->numclipnodes; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); if (count > 32767) { Sys_MaskPrintf (SYS_warn, @@ -890,7 +891,7 @@ Mod_MakeHull0 (model_t *mod) in = brush->nodes; count = brush->numnodes; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); hull->clipnodes = out; hull->firstclipnode = 0; @@ -919,7 +920,7 @@ Mod_LoadMarksurfaces (model_t *mod, bsp_t *bsp) in = bsp->marksurfaces; count = bsp->nummarksurfaces; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); if (count > 32767) { Sys_MaskPrintf (SYS_warn, @@ -948,7 +949,7 @@ Mod_LoadSurfedges (model_t *mod, bsp_t *bsp) in = bsp->surfedges; count = bsp->numsurfedges; - out = Hunk_AllocName (count * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * sizeof (*out), mod->name); brush->surfedges = out; brush->numsurfedges = count; @@ -967,7 +968,7 @@ Mod_LoadPlanes (model_t *mod, bsp_t *bsp) in = bsp->planes; count = bsp->numplanes; - out = Hunk_AllocName (count * 2 * sizeof (*out), mod->name); + out = Hunk_AllocName (0, count * 2 * sizeof (*out), mod->name); brush->planes = out; brush->numplanes = count; diff --git a/libs/models/brush/sw_model_brush.c b/libs/models/brush/sw_model_brush.c index 84080d49d..ca16af58e 100644 --- a/libs/models/brush/sw_model_brush.c +++ b/libs/models/brush/sw_model_brush.c @@ -48,6 +48,6 @@ sw_Mod_LoadLighting (model_t *mod, bsp_t *bsp) mod->brush.lightdata = NULL; return; } - mod->brush.lightdata = Hunk_AllocName (bsp->lightdatasize, mod->name); + mod->brush.lightdata = Hunk_AllocName (0, bsp->lightdatasize, mod->name); memcpy (mod->brush.lightdata, bsp->lightdata, bsp->lightdatasize); } diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index a5acbdac3..b2bd64417 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -318,7 +318,7 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; if (!tx) { - modelctx_t *mctx = Hunk_AllocName (sizeof (modelctx_t), mod->name); + modelctx_t *mctx = Hunk_AllocName (0, sizeof (modelctx_t), mod->name); mctx->ctx = ctx; mod->clear = vulkan_brush_clear; mod->data = mctx; @@ -360,11 +360,11 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) const char *name = va (ctx->va_ctx, "fb_%s", tx->name); int size = (tx->width * tx->height * 85) / 64; - int fullbright_mark = Hunk_LowMark (); - byte *pixels = Hunk_AllocName (size, name); + int fullbright_mark = Hunk_LowMark (0); + byte *pixels = Hunk_AllocName (0, size, name); if (!Mod_CalcFullbright ((byte *) (tx + 1), pixels, size)) { - Hunk_FreeToLowMark (fullbright_mark); + Hunk_FreeToLowMark (0, fullbright_mark); return; } tex->glow = tex->tex + 1; @@ -428,7 +428,7 @@ Vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp, vulkan_ctx_t *ctx) return; } // LordHavoc: oh well, expand the white lighting data - brush->lightdata = Hunk_AllocName (bsp->lightdatasize * 3, mod->name); + brush->lightdata = Hunk_AllocName (0, bsp->lightdatasize * 3, mod->name); in = bsp->lightdata; out = brush->lightdata; diff --git a/libs/models/model.c b/libs/models/model.c index e90ef5c00..bee2ac385 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -73,7 +73,8 @@ Mod_Init (void) int m, x, y; int mip0size = 16*16, mip1size = 8*8, mip2size = 4*4, mip3size = 2*2; - r_notexture_mip = Hunk_AllocName (sizeof (texture_t) + mip0size + mip1size + r_notexture_mip = Hunk_AllocName (0, + sizeof (texture_t) + mip0size + mip1size + mip2size + mip3size, "notexture"); r_notexture_mip->width = r_notexture_mip->height = 16; diff --git a/libs/models/sprite/model_sprite.c b/libs/models/sprite/model_sprite.c index e4806bf6e..ea8432fb4 100644 --- a/libs/models/sprite/model_sprite.c +++ b/libs/models/sprite/model_sprite.c @@ -55,7 +55,8 @@ Mod_LoadSpriteFrame (model_t *mod, void *pin, mspriteframe_t **ppframe, height = LittleLong (pinframe->height); size = width * height; - pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size, mod->name); + pspriteframe = Hunk_AllocName (0, sizeof (mspriteframe_t) + size, + mod->name); memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); @@ -93,8 +94,8 @@ Mod_LoadSpriteGroup (model_t *mod, void *pin, mspriteframe_t **ppframe, numframes = LittleLong (pingroup->numframes); - pspritegroup = Hunk_AllocName (field_offset (mspritegroup_t, - frames[numframes]), + pspritegroup = Hunk_AllocName (0, field_offset (mspritegroup_t, + frames[numframes]), mod->name); pspritegroup->numframes = numframes; @@ -103,7 +104,7 @@ Mod_LoadSpriteGroup (model_t *mod, void *pin, mspriteframe_t **ppframe, pin_intervals = (dspriteinterval_t *) (pingroup + 1); - poutintervals = Hunk_AllocName (numframes * sizeof (float), mod->name); + poutintervals = Hunk_AllocName (0, numframes * sizeof (float), mod->name); pspritegroup->intervals = poutintervals; @@ -146,7 +147,7 @@ Mod_LoadSpriteModel (model_t *mod, void *buffer) size = field_offset (msprite_t, frames[numframes]); - psprite = Hunk_AllocName (size, mod->name); + psprite = Hunk_AllocName (0, size, mod->name); mod->cache.data = psprite; diff --git a/libs/net/net_main.c b/libs/net/net_main.c index d282674b4..9d8a34e09 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -835,7 +835,7 @@ NET_Init (void) SetNetTime (); for (i = 0; i < net_numsockets; i++) { - s = (qsocket_t *) Hunk_AllocName (sizeof (qsocket_t), "qsocket"); + s = (qsocket_t *) Hunk_AllocName (0, sizeof (qsocket_t), "qsocket"); s->next = net_freeSockets; net_freeSockets = s; s->disconnected = true; diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 16f5a21f4..cc7a7d8b9 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -62,7 +62,7 @@ PF_VarString (progs_t *pr, int first) for (len = 0, i = first; i < pr->pr_argc; i++) len += strlen (P_GSTRING (pr, i)); - dst = out = Hunk_TempAlloc (len + 1); + dst = out = Hunk_TempAlloc (0, len + 1); for (i = first; i < pr->pr_argc; i++) { src = P_GSTRING (pr, i); while (*src) diff --git a/libs/util/cmd.c b/libs/util/cmd.c index c3e2c20c4..6ee2ee10c 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -509,7 +509,7 @@ Cmd_Exec_f (void) return; } - mark = Hunk_LowMark (); + mark = Hunk_LowMark (0); f = (char *) QFS_LoadHunkFile (QFS_FOpenFile (Cmd_Argv (1))); if (!f) { Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1)); @@ -520,7 +520,7 @@ Cmd_Exec_f (void) || (developer && developer->int_val & SYS_dev))) Sys_Printf ("execing %s\n", Cmd_Argv (1)); Cbuf_InsertText (cbuf_active, f); - Hunk_FreeToLowMark (mark); + Hunk_FreeToLowMark (0, mark); } /* diff --git a/libs/util/info.c b/libs/util/info.c index 9758942a4..46c4743ed 100644 --- a/libs/util/info.c +++ b/libs/util/info.c @@ -224,7 +224,7 @@ VISIBLE info_t * Info_ParseString (const char *s, int maxsize, int flags) { info_t *info; - char *string = Hunk_TempAlloc (strlen (s) + 1); + char *string = Hunk_TempAlloc (0, strlen (s) + 1); char *key, *value, *end; info = malloc (sizeof (info_t)); @@ -271,7 +271,7 @@ Info_MakeString (info_t *info, int (*filter) (const char *)) info_key_t **key_list; info_key_t **key; - d = string = Hunk_TempAlloc (info->cursize + 1); + d = string = Hunk_TempAlloc (0, info->cursize + 1); key_list = (info_key_t **) Hash_GetList (info->tab); for (key = key_list; *key; key++) { diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 2b19f32ad..34d4988f9 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1141,9 +1141,9 @@ QFS_LoadFile (QFile *file, int usehunk) //base = QFS_FileBase (path); if (usehunk == 1) - buf = Hunk_AllocName (len + 1, base); + buf = Hunk_AllocName (0, len + 1, base); else if (usehunk == 2) - buf = Hunk_TempAlloc (len + 1); + buf = Hunk_TempAlloc (0, len + 1); else if (usehunk == 0) buf = calloc (1, len + 1); else if (usehunk == 3) diff --git a/libs/util/sizebuf.c b/libs/util/sizebuf.c index 25f835a4f..a7b241a41 100644 --- a/libs/util/sizebuf.c +++ b/libs/util/sizebuf.c @@ -45,7 +45,7 @@ SZ_Alloc (sizebuf_t *buf, unsigned maxsize) { if (maxsize < 256) maxsize = 256; - buf->data = Hunk_AllocName (maxsize, "sizebuf"); + buf->data = Hunk_AllocName (0, maxsize, "sizebuf"); buf->maxsize = maxsize; buf->cursize = 0; } diff --git a/libs/util/zone.c b/libs/util/zone.c index 6cbff65b5..f0297f8cd 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -48,9 +48,9 @@ #include "compat.h" -static void Cache_FreeLow (int new_low_hunk); -static void Cache_Profile (void); -static qboolean Cache_FreeLRU (void); +static void Cache_FreeLow (memhunk_t *hunk, int new_low_hunk); +static void Cache_Profile_r (memhunk_t *hunk); +static qboolean Cache_FreeLRU (memhunk_t *hunk); #define ZONEID 0x1d4a11 #define HUNK_SENTINAL 0x1df001ed @@ -409,22 +409,35 @@ Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size) //============================================================================ +typedef struct cache_system_s cache_system_t; +struct cache_system_s { + cache_system_t *prev, *next; + cache_system_t *lru_prev, *lru_next; // for LRU flushing + struct memhunk_s *hunk; + char name[16]; + size_t size; // including this header + int readlock; + cache_user_t *user; +} __attribute__((aligned (64)));//FIXME base 64-bit size is 80, so 128... + typedef struct { int sentinal1; int sentinal2; - size_t size; // including sizeof(hunk_t), -1 = not allocated + size_t size; // including sizeof(hunkblk_t), -1 = not allocated char name[8]; - // pad out to 64 bytes - char fill[64 - 2 * sizeof (int) - sizeof (size_t) - 8]; -} hunk_t; +} __attribute__((aligned (64))) hunkblk_t; -byte *hunk_base; -size_t hunk_size; -size_t hunk_low_used; -size_t hunk_high_used; -size_t hunk_tempmark; +struct memhunk_s { + byte *base; + size_t size; + size_t low_used; + size_t high_used; + size_t tempmark; + qboolean tempactive; + cache_system_t cache_head; +} __attribute__((aligned (64))); -qboolean hunk_tempactive; +static memhunk_t *global_hunk; /* Hunk_Check @@ -432,17 +445,19 @@ qboolean hunk_tempactive; Run consistancy and sentinal trahing checks */ VISIBLE void -Hunk_Check (void) +Hunk_Check (memhunk_t *hunk) { - hunk_t *h; + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + hunkblk_t *h; + byte *hunk_end = hunk->base + hunk->low_used; - for (h = (hunk_t *) hunk_base; (byte *) h < hunk_base + hunk_low_used; ) { + for (h = (hunkblk_t *) hunk->base; (byte *) h < hunk_end; ) { if (h->sentinal1 != HUNK_SENTINAL || h->sentinal2 != HUNK_SENTINAL) Sys_Error ("Hunk_Check: trashed sentinal"); - if (h->size < sizeof (hunk_t) - || h->size + (byte *) h > hunk_base + hunk_size) + if (h->size < sizeof (hunkblk_t) + || h->size + (byte *) h > hunk->base + hunk->size) Sys_Error ("Hunk_Check: bad size"); - h = (hunk_t *) ((byte *) h + h->size); + h = (hunkblk_t *) ((byte *) h + h->size); } } @@ -455,21 +470,22 @@ Hunk_Check (void) */ VISIBLE void -Hunk_Print (qboolean all) +Hunk_Print (memhunk_t *hunk, qboolean all) { - hunk_t *h, *next, *endlow, *starthigh, *endhigh; + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + hunkblk_t *h, *next, *endlow, *starthigh, *endhigh; int count, sum, totalblocks; count = 0; sum = 0; totalblocks = 0; - h = (hunk_t *) hunk_base; - endlow = (hunk_t *) (hunk_base + hunk_low_used); - starthigh = (hunk_t *) (hunk_base + hunk_size - hunk_high_used); - endhigh = (hunk_t *) (hunk_base + hunk_size); + h = (hunkblk_t *) hunk->base; + endlow = (hunkblk_t *) (hunk->base + hunk->low_used); + starthigh = (hunkblk_t *) (hunk->base + hunk->size - hunk->high_used); + endhigh = (hunkblk_t *) (hunk->base + hunk->size); - Sys_Printf (" :%8zd total hunk size\n", hunk_size); + Sys_Printf (" :%8zd total hunk size\n", hunk->size); Sys_Printf ("-------------------------\n"); while (1) { @@ -477,7 +493,7 @@ Hunk_Print (qboolean all) if (h == endlow) { Sys_Printf ("-------------------------\n"); Sys_Printf (" :%8zd REMAINING\n", - hunk_size - hunk_low_used - hunk_high_used); + hunk->size - hunk->low_used - hunk->high_used); Sys_Printf ("-------------------------\n"); h = starthigh; } @@ -488,11 +504,11 @@ Hunk_Print (qboolean all) // run consistancy checks if (h->sentinal1 != HUNK_SENTINAL || h->sentinal2 != HUNK_SENTINAL) Sys_Error ("Hunk_Check: trahsed sentinal"); - if (h->size < (int) sizeof (hunk_t) - || h->size + (byte *) h > hunk_base + hunk_size) + if (h->size < (int) sizeof (hunkblk_t) + || h->size + (byte *) h > hunk->base + hunk->size) Sys_Error ("Hunk_Check: bad size"); - next = (hunk_t *) ((byte *) h + h->size); + next = (hunkblk_t *) ((byte *) h + h->size); count++; totalblocks++; sum += h->size; @@ -518,59 +534,63 @@ Hunk_Print (qboolean all) } static void -Hunk_FreeToHighMark (size_t mark) +Hunk_FreeToHighMark (memhunk_t *hunk, size_t mark) { - if (hunk_tempactive) { - hunk_tempactive = false; - Hunk_FreeToHighMark (hunk_tempmark); + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + if (hunk->tempactive) { + hunk->tempactive = false; + Hunk_FreeToHighMark (hunk, hunk->tempmark); } - if (mark > hunk_high_used) + if (mark > hunk->high_used) Sys_Error ("Hunk_FreeToHighMark: bad mark %zd", mark); - memset (hunk_base + hunk_size - hunk_high_used, 0, hunk_high_used - mark); - hunk_high_used = mark; + memset (hunk->base + hunk->size - hunk->high_used, 0, + hunk->high_used - mark); + hunk->high_used = mark; } static int -Hunk_HighMark (void) +Hunk_HighMark (memhunk_t *hunk) { - if (hunk_tempactive) { - hunk_tempactive = false; - Hunk_FreeToHighMark (hunk_tempmark); + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + if (hunk->tempactive) { + hunk->tempactive = false; + Hunk_FreeToHighMark (hunk, hunk->tempmark); } - return hunk_high_used; + return hunk->high_used; } VISIBLE void * -Hunk_AllocName (size_t size, const char *name) +Hunk_AllocName (memhunk_t *hunk, size_t size, const char *name) { - hunk_t *h; + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + hunkblk_t *h; #ifdef PARANOID Hunk_Check (); #endif - size = sizeof (hunk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); + size = sizeof (hunkblk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); - if (hunk_size - hunk_low_used - hunk_high_used < size) { - Hunk_HighMark(); - Cache_FreeLRU (); + if (hunk->size - hunk->low_used - hunk->high_used < size) { + Hunk_HighMark (hunk); + Cache_FreeLRU (hunk); } - if (hunk_size - hunk_low_used - hunk_high_used < size) { - int mem = hunk_size / (1024 * 1024); + if (hunk->size - hunk->low_used - hunk->high_used < size) { + int mem = hunk->size / (1024 * 1024); mem += 8; mem &= ~7; - Cache_Profile (); + Cache_Profile_r (hunk); Sys_Error ("Not enough RAM allocated. Try starting using \"-mem %d\" on " "the %s command line. (%zd - %zd - %zd < %zd)", mem, - PACKAGE_NAME, hunk_size, hunk_low_used, hunk_high_used, size); + PACKAGE_NAME, hunk->size, hunk->low_used, hunk->high_used, size); } - h = (hunk_t *) (hunk_base + hunk_low_used); - hunk_low_used += size; + h = (hunkblk_t *) (hunk->base + hunk->low_used); + hunk->low_used += size; - Cache_FreeLow (hunk_low_used); + Cache_FreeLow (hunk, hunk->low_used); memset (h, 0, size); @@ -584,49 +604,52 @@ Hunk_AllocName (size_t size, const char *name) } VISIBLE void * -Hunk_Alloc (size_t size) +Hunk_Alloc (memhunk_t *hunk, size_t size) { - return Hunk_AllocName (size, "unknown"); + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + return Hunk_AllocName (hunk, size, "unknown"); } VISIBLE size_t -Hunk_LowMark (void) +Hunk_LowMark (memhunk_t *hunk) { - return hunk_low_used; + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + return hunk->low_used; } VISIBLE void -Hunk_FreeToLowMark (size_t mark) +Hunk_FreeToLowMark (memhunk_t *hunk, size_t mark) { - if (mark > hunk_low_used) + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + if (mark > hunk->low_used) Sys_Error ("Hunk_FreeToLowMark: bad mark %zd", mark); - memset (hunk_base + mark, 0, hunk_low_used - mark); - hunk_low_used = mark; + memset (hunk->base + mark, 0, hunk->low_used - mark); + hunk->low_used = mark; } static void * -Hunk_HighAlloc (size_t size) +Hunk_HighAlloc (memhunk_t *hunk, size_t size) { - hunk_t *h; + hunkblk_t *h; - if (hunk_tempactive) { - Hunk_FreeToHighMark (hunk_tempmark); - hunk_tempactive = false; + if (hunk->tempactive) { + Hunk_FreeToHighMark (hunk, hunk->tempmark); + hunk->tempactive = false; } #ifdef PARANOID - Hunk_Check (); + Hunk_Check (hunk); #endif - size = sizeof (hunk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); + size = sizeof (hunkblk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); - if (hunk_size - hunk_low_used - hunk_high_used < size) { + if (hunk->size - hunk->low_used - hunk->high_used < size) { Sys_Printf ("Hunk_HighAlloc: failed on %zd bytes\n", size); return NULL; } - hunk_high_used += size; + hunk->high_used += size; - h = (void *) (hunk_base + hunk_size - hunk_high_used); + h = (void *) (hunk->base + hunk->size - hunk->high_used); h->sentinal1 = HUNK_SENTINAL; h->sentinal2 = HUNK_SENTINAL; h->size = size; @@ -640,44 +663,37 @@ Hunk_HighAlloc (size_t size) Return space from the top of the hunk */ VISIBLE void * -Hunk_TempAlloc (size_t size) +Hunk_TempAlloc (memhunk_t *hunk, size_t size) { + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers void *buf; size = (size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1); - if (hunk_tempactive) { - if (hunk_high_used - hunk_tempmark >= size + (int) sizeof (hunk_t)) { - return (hunk_t *) (hunk_base + hunk_size - hunk_high_used) + 1; + if (hunk->tempactive) { + size_t temp_free = hunk->high_used - hunk->tempmark; + if (temp_free >= size + (int) sizeof (hunkblk_t)) { + byte *temp_block = hunk->base + hunk->size - hunk->high_used; + return (hunkblk_t *) temp_block + 1; } - Hunk_FreeToHighMark (hunk_tempmark); - hunk_tempactive = false; + Hunk_FreeToHighMark (hunk, hunk->tempmark); + hunk->tempactive = false; } - hunk_tempmark = Hunk_HighMark (); + hunk->tempmark = Hunk_HighMark (hunk); - buf = Hunk_HighAlloc (size); + buf = Hunk_HighAlloc (hunk, size); - hunk_tempactive = true; + hunk->tempactive = true; return buf; } /* CACHE MEMORY */ -typedef struct cache_system_s cache_system_t; -struct cache_system_s { - cache_system_t *prev, *next; - cache_system_t *lru_prev, *lru_next; // for LRU flushing - char name[16]; - size_t size; // including this header - int readlock; - cache_user_t *user; -}; -static cache_system_t cache_head; - -static cache_system_t *Cache_TryAlloc (size_t size, qboolean nobottom); +static cache_system_t *Cache_TryAlloc (memhunk_t *hunk, size_t size, + qboolean nobottom); #if 0 static void check_cache (void) @@ -700,12 +716,13 @@ check_cache (void) } #endif static void -Cache_Move (cache_system_t * c) +Cache_Move (cache_system_t *c) { + memhunk_t *hunk = c->hunk; cache_system_t *new; // we are clearing up space at the bottom, so allocate it late - new = Cache_TryAlloc (c->size, true); + new = Cache_TryAlloc (hunk, c->size, true); if (new) { Sys_MaskPrintf (SYS_dev, "cache_move ok\n"); @@ -727,15 +744,15 @@ Cache_Move (cache_system_t * c) Throw things out until the hunk can be expanded to the given point */ static void -Cache_FreeLow (int new_low_hunk) +Cache_FreeLow (memhunk_t *hunk, int new_low_hunk) { cache_system_t *c; while (1) { - c = cache_head.prev; - if (c == &cache_head) + c = hunk->cache_head.prev; + if (c == &hunk->cache_head) return; // nothing in cache at all - if ((byte *) c >= hunk_base + new_low_hunk) + if ((byte *) c >= hunk->base + new_low_hunk) return; // there is space to grow the hunk Sys_Error ("FIXME: Cache_FreeLow: not enough memory"); Cache_Move (c); // reclaim the space @@ -762,22 +779,22 @@ Cache_MakeLRU (cache_system_t * cs) Sys_Error ("Cache_MakeLRU: active link: %.16s %p %p", cs->name, cs->lru_next, cs->lru_prev); - cache_head.lru_next->lru_prev = cs; - cs->lru_next = cache_head.lru_next; - cs->lru_prev = &cache_head; - cache_head.lru_next = cs; + cs->hunk->cache_head.lru_next->lru_prev = cs; + cs->lru_next = cs->hunk->cache_head.lru_next; + cs->lru_prev = &cs->hunk->cache_head; + cs->hunk->cache_head.lru_next = cs; } static qboolean -Cache_FreeLRU (void) +Cache_FreeLRU (memhunk_t *hunk) { cache_system_t *cs; //check_cache (); - for (cs = cache_head.lru_prev; - cs != &cache_head && cs->readlock; cs = cs->lru_prev) + for (cs = hunk->cache_head.lru_prev; + cs != &hunk->cache_head && cs->readlock; cs = cs->lru_prev) ; - if (cs == &cache_head) + if (cs == &hunk->cache_head) return 0; Cache_Free (cs->user); return 1; @@ -800,27 +817,28 @@ link_cache_system (cache_system_t *new, cache_system_t *cs) Size should already include the header and padding */ static cache_system_t * -Cache_TryAlloc (size_t size, qboolean nobottom) +Cache_TryAlloc (memhunk_t *hunk, size_t size, qboolean nobottom) { cache_system_t *cs, *new; //check_cache (); // is the cache completely empty? - if (!nobottom && cache_head.prev == &cache_head) { - new = (cache_system_t *) Hunk_HighAlloc (size); + if (!nobottom && hunk->cache_head.prev == &hunk->cache_head) { + new = (cache_system_t *) Hunk_HighAlloc (hunk, size); if (!new) return 0; memset (new, 0, size); new->size = size; - cache_head.prev = cache_head.next = new; - new->prev = new->next = &cache_head; + new->hunk = hunk; + hunk->cache_head.prev = hunk->cache_head.next = new; + new->prev = new->next = &hunk->cache_head; Cache_MakeLRU (new); //check_cache (); return new; } // search for space in existing cache - for (cs = cache_head.next; cs != &cache_head; cs = cs->next) { + for (cs = hunk->cache_head.next; cs != &hunk->cache_head; cs = cs->next) { if (cs->user) continue; // block isn't free if (cs->size >= size) { @@ -832,6 +850,7 @@ Cache_TryAlloc (size_t size, qboolean nobottom) new = (cache_system_t *) ((char *) cs + cs->size - size); memset (new, 0, size); new->size = size; + new->hunk = hunk; cs->size -= size; link_cache_system (new, cs); //check_cache (); @@ -845,11 +864,12 @@ Cache_TryAlloc (size_t size, qboolean nobottom) return 0; // didn't find a free block, so make a new one. - new = Hunk_HighAlloc (size); + new = Hunk_HighAlloc (hunk, size); if (new) { memset (new, 0, size); new->size = size; - link_cache_system (new, &cache_head); + new->hunk = hunk; + link_cache_system (new, &hunk->cache_head); Cache_MakeLRU (new); //check_cache (); return new; @@ -859,15 +879,15 @@ Cache_TryAlloc (size_t size, qboolean nobottom) } static void -Cache_Profile (void) +Cache_Profile_r (memhunk_t *hunk) { cache_system_t *cs; unsigned int i; unsigned int items[31] = {0}, sizes[31] = {0}; int count = 0, total = 0; - cs = cache_head.next; - while (cs != &cache_head) { + cs = hunk->cache_head.next; + while (cs != &hunk->cache_head) { for (i = 0; (cs->size >> (i + 1)) && i < 30; i++) ; items[i]++; @@ -893,23 +913,39 @@ Cache_Profile (void) } static void -Cache_Print (void) +Cache_Profile (void) +{ + Cache_Profile_r (global_hunk); +} + +static void +Cache_Print_r (memhunk_t *hunk) { cache_system_t *cd; - for (cd = cache_head.next; cd != &cache_head; cd = cd->next) { + for (cd = hunk->cache_head.next; cd != &hunk->cache_head; cd = cd->next) { Sys_Printf ("%8d : %.16s\n", (int) cd->size, cd->name); } } +static void +Cache_Print (void) +{ + Cache_Print_r (global_hunk); +} + +static void +init_cache (memhunk_t *hunk) +{ + hunk->cache_head.next = hunk->cache_head.prev = &hunk->cache_head; + hunk->cache_head.lru_next = hunk->cache_head.lru_prev = &hunk->cache_head; + hunk->cache_head.user = (cache_user_t *) 1; // make it look allocated + hunk->cache_head.readlock = 1; // don't try to free or move it +} + static void Cache_Init (void) { - cache_head.next = cache_head.prev = &cache_head; - cache_head.lru_next = cache_head.lru_prev = &cache_head; - cache_head.user = (cache_user_t *) 1; // make it look allocated - cache_head.readlock = 1; // don't try to free or move it - Cmd_AddCommand ("cache_flush", Cache_Flush, "Clears the current game " "cache"); Cmd_AddCommand ("cache_profile", Cache_Profile, "Prints a profile of " @@ -923,20 +959,28 @@ Cache_Init (void) Throw everything out, so new data will be demand cached */ -void -Cache_Flush (void) +static void +Cache_Flush_r (memhunk_t *hunk) { // cache_head.prev is guaranteed to not be free because it's the bottom // one and Cache_Free actually properly releases it - while (cache_head.prev != &cache_head) { - if (!cache_head.prev->user->data) + while (hunk->cache_head.prev != &hunk->cache_head) { + if (!hunk->cache_head.prev->user->data) Sys_Error ("Cache_Flush: user/system out of sync for " "'%.16s' with %d size", - cache_head.prev->name, (int) cache_head.prev->size); - Cache_Free (cache_head.prev->user); // reclaim the space + hunk->cache_head.prev->name, + (int) hunk->cache_head.prev->size); + Cache_Free (hunk->cache_head.prev->user); // reclaim the space } } +VISIBLE void +Cache_Flush (void) +{ + // cache_head.prev is guaranteed to not be free because it's the bottom + Cache_Flush_r (global_hunk); +} + VISIBLE void * Cache_Check (cache_user_t *c) { @@ -968,6 +1012,7 @@ Cache_Free (cache_user_t *c) Sys_Error ("Cache_Free: not allocated"); cs = ((cache_system_t *) c->data) - 1; + memhunk_t *hunk = cs->hunk; if (cs->readlock) Sys_Error ("Cache_Free: attempt to free locked block"); @@ -989,35 +1034,36 @@ Cache_Free (cache_user_t *c) cs->prev->prev->next = cs; cs->prev = cs->prev->prev; } - if (cs->next == &cache_head) { + if (cs->next == &hunk->cache_head) { cs->next->prev = cs->prev; cs->prev->next = cs->next; - if (cs->prev != &cache_head) - Hunk_FreeToHighMark (hunk_size - ((byte*)cs->prev - hunk_base)); + if (cs->prev != &hunk->cache_head) + Hunk_FreeToHighMark (hunk, + hunk->size - ((byte*)cs->prev - hunk->base)); else - Hunk_FreeToHighMark (0); + Hunk_FreeToHighMark (hunk, 0); } //check_cache (); c->data = NULL; } -VISIBLE void * -Cache_Alloc (cache_user_t *c, size_t size, const char *name) +static void * +Cache_Alloc_r (memhunk_t *hunk, cache_user_t *c, size_t size, const char *name) { cache_system_t *cs; if (c->data) - Sys_Error ("Cache_Alloc: already allocated"); + Sys_Error ("Cache_Alloc_r: already allocated"); if (size <= 0) - Sys_Error ("Cache_Alloc: size %zd", size); + Sys_Error ("Cache_Alloc_r: size %zd", size); size = (size + sizeof (cache_system_t) + HUNK_ALIGN - 1) & ~(HUNK_ALIGN-1); // find memory for it while (1) { - cs = Cache_TryAlloc (size, false); + cs = Cache_TryAlloc (hunk, size, false); if (cs) { strncpy (cs->name, name, sizeof (cs->name) - 1); c->data = (void *) (cs + 1); @@ -1025,19 +1071,32 @@ Cache_Alloc (cache_user_t *c, size_t size, const char *name) break; } // free the least recently used cachedat - if (!Cache_FreeLRU()) + if (!Cache_FreeLRU (hunk)) Sys_Error ("Cache_Alloc: out of memory"); } return Cache_Check (c); } +VISIBLE void * +Cache_Alloc (cache_user_t *c, size_t size, const char *name) +{ + return Cache_Alloc_r (global_hunk, c, size, name); +} + +static void +Cache_Report_r (memhunk_t *hunk) +{ + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + Sys_MaskPrintf (SYS_dev, "%4.1f megabyte data cache\n", + (hunk->size - hunk->high_used - + hunk->low_used) / (float) (1024 * 1024)); +} + VISIBLE void Cache_Report (void) { - Sys_MaskPrintf (SYS_dev, "%4.1f megabyte data cache\n", - (hunk_size - hunk_high_used - - hunk_low_used) / (float) (1024 * 1024)); + Cache_Report_r (global_hunk); } VISIBLE void @@ -1116,13 +1175,22 @@ Cache_ReadLock (cache_user_t *c) //============================================================================ +VISIBLE memhunk_t * +Hunk_Init (void *buf, size_t size) +{ + memhunk_t *hunk = buf; + hunk->base = (byte *) (hunk + 1); + hunk->size = size - sizeof (memhunk_t); + hunk->low_used = 0; + hunk->high_used = 0; + + init_cache (hunk); + return hunk; +} + VISIBLE void Memory_Init (void *buf, size_t size) { - hunk_base = buf; - hunk_size = size; - hunk_low_used = 0; - hunk_high_used = 0; - + global_hunk = Hunk_Init (buf, size); Cache_Init (); } diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 3251a5913..7c7097ce5 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -459,7 +459,7 @@ do_subimage_2 (int i) width = rect->w * lightmap_bytes; stride = BLOCK_WIDTH * lightmap_bytes; - b = block = Hunk_TempAlloc (rect->h * width); + b = block = Hunk_TempAlloc (0, rect->h * width); lm = lightmaps[i] + (rect->t * BLOCK_WIDTH + rect->l) * lightmap_bytes; for (i = rect->h; i > 0; i--) { memcpy (b, lm, width); diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 18ef24320..f41821031 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -292,7 +292,7 @@ GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t *e) verts = (trivertx16_t *) ((byte *) paliashdr + paliashdr->posedata); count = paliashdr->poseverts; - vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t)); + vo = Hunk_TempAlloc (0, sizeof (*vo) + count * sizeof (blended_vert_t)); vo->order = (int *) ((byte *) paliashdr + paliashdr->commands); vo->verts = (blended_vert_t *) &vo[1]; if (paliashdr->tex_coord) { @@ -358,7 +358,7 @@ GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t *e) verts = (trivertx_t *) ((byte *) paliashdr + paliashdr->posedata); count = paliashdr->poseverts; - vo = Hunk_TempAlloc (sizeof (*vo) + count * sizeof (blended_vert_t)); + vo = Hunk_TempAlloc (0, sizeof (*vo) + count * sizeof (blended_vert_t)); vo->order = (int *) ((byte *) paliashdr + paliashdr->commands); vo->verts = (blended_vert_t *) &vo[1]; if (paliashdr->tex_coord) { diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 654751fff..daed97922 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -840,7 +840,7 @@ GL_BuildSurfaceDisplayList (msurface_t *surf) lnumverts = surf->numedges; // draw texture - poly = Hunk_Alloc (sizeof (glpoly_t) + (lnumverts - 4) * + poly = Hunk_Alloc (0, sizeof (glpoly_t) + (lnumverts - 4) * VERTEXSIZE * sizeof (float)); poly->next = surf->polys; poly->flags = surf->flags; diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 48d2565b8..c70c2067c 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -91,7 +91,7 @@ gl_SCR_ScreenShot (unsigned width, unsigned height) int count, dex, dey, dx, dy, nx, r, g, b, x, y, w, h; tex_t *tex; - snap = Hunk_TempAlloc (vid.width * vid.height * 3); + snap = Hunk_TempAlloc (0, vid.width * vid.height * 3); qfglReadPixels (0, 0, vid.width, vid.height, GL_RGB, GL_UNSIGNED_BYTE, snap); diff --git a/libs/video/renderer/r_iqm.c b/libs/video/renderer/r_iqm.c index dcf58f44c..84ce67744 100644 --- a/libs/video/renderer/r_iqm.c +++ b/libs/video/renderer/r_iqm.c @@ -76,7 +76,7 @@ R_IQMBlendFrames (const iqm_t *iqm, int frame1, int frame2, float blend, iqmframe_t *frame; int i; - frame = Hunk_TempAlloc (iqm->num_joints * sizeof (iqmframe_t) + extra); + frame = Hunk_TempAlloc (0, iqm->num_joints * sizeof (iqmframe_t) + extra); if (iqm->num_frames) { #if 0 for (i = 0; i < iqm->num_joints; i++) { diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 023c5e039..1899e2a47 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -636,7 +636,7 @@ R_AliasDrawModel (alight_t *plighting) size = (CACHE_SIZE - 1) + sizeof (finalvert_t) * (pmdl->numverts + 1) + sizeof (auxvert_t) * pmdl->numverts; - finalverts = (finalvert_t *) Hunk_TempAlloc (size); + finalverts = (finalvert_t *) Hunk_TempAlloc (0, size); if (!finalverts) Sys_Error ("R_AliasDrawModel: out of memory"); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index f84c218b2..f20e2a98c 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -190,7 +190,8 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_cnumsurfs = MINSURFACES; if (r_cnumsurfs > NUMSTACKSURFACES) { - surfaces = Hunk_AllocName (r_cnumsurfs * sizeof (surf_t), "surfaces"); + surfaces = Hunk_AllocName (0, r_cnumsurfs * sizeof (surf_t), + "surfaces"); surface_p = surfaces; surf_max = &surfaces[r_cnumsurfs]; @@ -214,7 +215,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) if (r_numallocatededges <= NUMSTACKEDGES) { auxedges = NULL; } else { - auxedges = Hunk_AllocName (r_numallocatededges * sizeof (edge_t), + auxedges = Hunk_AllocName (0, r_numallocatededges * sizeof (edge_t), "edges"); } @@ -842,7 +843,7 @@ R_RenderView (void) if (delta < -10000 || delta > 10000) Sys_Error ("R_RenderView: called without enough stack"); - if (Hunk_LowMark () & 3) + if (Hunk_LowMark (0) & 3) Sys_Error ("Hunk is missaligned"); if ((intptr_t) (&dummy) & 3) diff --git a/libs/video/renderer/sw32/sw32_ralias.c b/libs/video/renderer/sw32/sw32_ralias.c index fa7c56552..ae7f1350a 100644 --- a/libs/video/renderer/sw32/sw32_ralias.c +++ b/libs/video/renderer/sw32/sw32_ralias.c @@ -637,7 +637,7 @@ sw32_R_AliasDrawModel (alight_t *plighting) size = (CACHE_SIZE - 1) + sizeof (finalvert_t) * (pmdl->numverts + 1) + sizeof (auxvert_t) * pmdl->numverts; - finalverts = (finalvert_t *) Hunk_TempAlloc (size); + finalverts = (finalvert_t *) Hunk_TempAlloc (0, size); if (!finalverts) Sys_Error ("R_AliasDrawModel: out of memory"); diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 6f1fee59f..f928b8c4b 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -115,7 +115,7 @@ sw32_R_Textures_Init (void) // create a simple checkerboard texture for the default r_notexture_mip = - Hunk_AllocName (sizeof (texture_t) + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2, + Hunk_AllocName (0, sizeof (texture_t) + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2, "notexture"); r_notexture_mip->width = r_notexture_mip->height = 16; @@ -205,7 +205,8 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_cnumsurfs = MINSURFACES; if (r_cnumsurfs > NUMSTACKSURFACES) { - sw32_surfaces = Hunk_AllocName (r_cnumsurfs * sizeof (surf_t), "surfaces"); + sw32_surfaces = Hunk_AllocName (0, r_cnumsurfs * sizeof (surf_t), + "surfaces"); sw32_surface_p = sw32_surfaces; sw32_surf_max = &sw32_surfaces[r_cnumsurfs]; @@ -228,8 +229,9 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) if (sw32_r_numallocatededges <= NUMSTACKEDGES) { sw32_auxedges = NULL; } else { - sw32_auxedges = Hunk_AllocName (sw32_r_numallocatededges * sizeof (edge_t), - "edges"); + sw32_auxedges = Hunk_AllocName (0, + sw32_r_numallocatededges * sizeof (edge_t), + "edges"); } sw32_r_dowarpold = false; @@ -839,7 +841,7 @@ sw32_R_RenderView (void) if (delta < -10000 || delta > 10000) Sys_Error ("R_RenderView: called without enough stack"); - if (Hunk_LowMark () & 3) + if (Hunk_LowMark (0) & 3) Sys_Error ("Hunk is missaligned"); if ((intptr_t) (&dummy) & 3) diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index a9078edd8..ae7577b8f 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -315,7 +315,7 @@ CL_NewMap (const char *mapname) { r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels); Con_NewMap (); - Hunk_Check (); // make sure nothing is hurt + Hunk_Check (0); // make sure nothing is hurt Sbar_CenterPrint (0); if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) { @@ -365,7 +365,7 @@ CL_ParseServerInfo (void) Sys_Printf ("Bad maxclients (%u) from server\n", cl.maxclients); goto done; } - cl.players = Hunk_AllocName (cl.maxclients * sizeof (*cl.players), + cl.players = Hunk_AllocName (0, cl.maxclients * sizeof (*cl.players), "players"); for (i = 0; i < cl.maxclients; i++) { cl.players[i].userinfo = Info_ParseString ("name\\", 0, 0); @@ -444,7 +444,7 @@ CL_ParseServerInfo (void) dstring_clearstr (centerprint); CL_NewMap (model_precache[1]); - Hunk_Check (); // make sure nothing is hurt + Hunk_Check (0); // make sure nothing is hurt noclip_anglehack = false; // noclip is turned off at start r_data->gravity = 800.0; // Set up gravity for renderer effects diff --git a/nq/source/host.c b/nq/source/host.c index dc96020a9..f468e4bd9 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -242,7 +242,7 @@ Host_FindMaxClients (void) if (svs.maxclientslimit < 4) svs.maxclientslimit = 4; svs.clients = - Hunk_AllocName (svs.maxclientslimit * sizeof (client_t), "clients"); + Hunk_AllocName (0, svs.maxclientslimit * sizeof (client_t), "clients"); if (svs.maxclients > 1) Cvar_SetValue (deathmatch, 1.0); @@ -499,7 +499,7 @@ Host_ClearMemory (void) CL_ClearMemory (); Mod_ClearAll (); if (host_hunklevel) - Hunk_FreeToLowMark (host_hunklevel); + Hunk_FreeToLowMark (0, host_hunklevel); cls.signon = 0; memset (&sv, 0, sizeof (sv)); @@ -907,8 +907,8 @@ Host_Init (void) COM_ExecConfig (host_cbuf, isDedicated || !cl_quakerc->int_val); - Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); - host_hunklevel = Hunk_LowMark (); + Hunk_AllocName (0, 0, "-HOST_HUNKLEVEL-"); + host_hunklevel = Hunk_LowMark (0); Sys_Printf ("\nVersion %s (build %04d)\n\n", PACKAGE_VERSION, build_number ()); diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index ef98f27da..9f10ed8e9 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -493,7 +493,7 @@ convert_to_game_dict (script_t *script) PL_A_AddObject (item, PL_NewString (script->token->str)); //char *s; - //s = Hunk_Alloc (strlen (script->token->str) + 1); + //s = Hunk_Alloc (0, strlen (script->token->str) + 1); //strcpy (s, script->token->str); //sv.lightstyles[i] = s; } @@ -687,7 +687,7 @@ Host_Loadgame_f (void) break; item = PL_ObjectAtIndex (list, i); style = PL_String (item); - sv.lightstyles[i] = str = Hunk_Alloc (strlen (style) + 1); + sv.lightstyles[i] = str = Hunk_Alloc (0, strlen (style) + 1); strcpy (str, style); } @@ -803,7 +803,7 @@ Host_Say (qboolean teamonly) save = host_client; - p = Hunk_TempAlloc (strlen (Cmd_Args (1)) + 1); + p = Hunk_TempAlloc (0, strlen (Cmd_Args (1)) + 1); strcpy (p, Cmd_Args (1)); // remove quotes if present if (*p == '"') { @@ -869,7 +869,7 @@ Host_Tell_f (void) strcpy (text, host_client->name); strcat (text, ": "); - p = Hunk_TempAlloc (strlen (Cmd_Args (1)) + 1); + p = Hunk_TempAlloc (0, strlen (Cmd_Args (1)) + 1); strcpy (p, Cmd_Args (1)); // remove quotes if present diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index f36dcfde9..f649c0248 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -448,9 +448,9 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) VectorAdd (p_angles, amove, p_angles); SV_LinkEdict (pusher, false); - mark = Hunk_LowMark (); - moved_edict = Hunk_Alloc (sv.num_edicts * sizeof (edict_t *)); - moved_from = Hunk_Alloc (sv.num_edicts * sizeof (vec_t)); + mark = Hunk_LowMark (0); + moved_edict = Hunk_Alloc (0, sv.num_edicts * sizeof (edict_t *)); + moved_from = Hunk_Alloc (0, sv.num_edicts * sizeof (vec_t)); // see if any solid entities are inside the final position num_moved = 0; @@ -550,10 +550,10 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) VectorSubtract (m_angles, amove, m_angles); SV_LinkEdict (moved_edict[i], false); } - Hunk_FreeToLowMark (mark); + Hunk_FreeToLowMark (0, mark); return false; } - Hunk_FreeToLowMark (mark); + Hunk_FreeToLowMark (0, mark); return true; } diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 0e133a2f0..466fa92cb 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -769,7 +769,7 @@ do_precache (progs_t *pr, const char **cache, int max, const char *name, PR_CheckEmptyString (pr, name); - s = Hunk_TempAlloc (strlen (name) + 1); + s = Hunk_TempAlloc (0, strlen (name) + 1); for (i = 0; *name; i++, name++) { int c = (byte) *name; s[i] = tolower (c); @@ -778,7 +778,7 @@ do_precache (progs_t *pr, const char **cache, int max, const char *name, for (i = 0; i < MAX_SOUNDS; i++) { if (!cache[i]) { - char *c = Hunk_Alloc (strlen (s) + 1); + char *c = Hunk_Alloc (0, strlen (s) + 1); strcpy (c, s); cache[i] = c; // blah, const Sys_MaskPrintf (SYS_dev, "%s: %3d %s\n", func, i, s); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index de8290cb8..f35e1b2cd 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -416,7 +416,7 @@ CL_ClearState (void) VID_ClearMemory (); Mod_ClearAll (); if (host_hunklevel) // FIXME: check this... - Hunk_FreeToLowMark (host_hunklevel); + Hunk_FreeToLowMark (0, host_hunklevel); CL_ClearEnts (); CL_ClearTEnts (); @@ -1812,8 +1812,8 @@ Host_Init (void) // make sure all + commands have been executed Cbuf_Execute_Stack (cl_cbuf); - Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); - host_hunklevel = Hunk_LowMark (); + Hunk_AllocName (0, 0, "-HOST_HUNKLEVEL-"); + host_hunklevel = Hunk_LowMark (0); Sys_Printf ("\nClient version %s (build %04d)\n\n", PACKAGE_VERSION, build_number ()); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index b1ae42c84..c0c37fb14 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -319,7 +319,7 @@ CL_NewMap (const char *mapname) r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels); Team_NewMap (); Con_NewMap (); - Hunk_Check (); // make sure nothing is hurt + Hunk_Check (0); // make sure nothing is hurt Sbar_CenterPrint (0); if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) { diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index 491d12652..24f2a809d 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -183,7 +183,7 @@ CL_Color_f (void) static void skin_f (cvar_t *var) { - char *s = Hunk_TempAlloc (strlen (var->string) + 1); + char *s = Hunk_TempAlloc (0, strlen (var->string) + 1); QFS_StripExtension (var->string, s); Cvar_Set (var, s); Cvar_Info (var); diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index 4297bf9cc..780556a82 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -779,7 +779,7 @@ SV_ConSay (const char *prefix, client_t *client) if (Cmd_Argc () < 2) return; - p = Hunk_TempAlloc (strlen (Cmd_Args (1)) + 1); + p = Hunk_TempAlloc (0, strlen (Cmd_Args (1)) + 1); strcpy (p, Cmd_Args (1)); if (*p == '"') { p++; diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index 1018ecb6c..9ddd21a5d 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -787,7 +787,7 @@ Demo_Init (void) demo_name = dstring_newstr (); demo_text = dstring_newstr (); - svs.demomem = Hunk_AllocName (size, "demo"); + svs.demomem = Hunk_AllocName (0, size, "demo"); svs.demomemsize = size; demo_max_size = size - 0x80000; diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 15a202e2c..7fe625c87 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -222,7 +222,8 @@ sv_alloc_vis_array (unsigned numleafs) unsigned size = SET_SIZE (numleafs - 1); if (size > SET_DEFMAP_SIZE * SET_BITS) { - set_t *sets = Hunk_Alloc (numleafs * (sizeof (set_t) + size / 8)); + set_t *sets = Hunk_Alloc (0, + numleafs * (sizeof (set_t) + size / 8)); unsigned words = size / SET_BITS; set_bits_t *bits = (set_bits_t *) (&sets[numleafs]); for (unsigned i = 0; i < numleafs; i++) { @@ -232,7 +233,7 @@ sv_alloc_vis_array (unsigned numleafs) } return sets; } else { - set_t *sets = Hunk_Alloc (numleafs * sizeof (set_t)); + set_t *sets = Hunk_Alloc (0, numleafs * sizeof (set_t)); for (unsigned i = 0; i < numleafs; i++) { sets[i].size = size; sets[i].map = sets[i].defmap; @@ -337,7 +338,7 @@ SV_SpawnServer (const char *server) sv_pr_state.null_bad = 0; Mod_ClearAll (); - Hunk_FreeToLowMark (host_hunklevel); + Hunk_FreeToLowMark (0, host_hunklevel); // wipe the entire per-level structure, but don't lose sv.recorders // or signon buffers (good thing we're not multi-threaded FIXME?) diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 4ec4c99af..9d2002317 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2541,8 +2541,8 @@ SV_Init (void) SVR_Init (); Demo_Init (); - Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); - host_hunklevel = Hunk_LowMark (); + Hunk_AllocName (0, 0, "-HOST_HUNKLEVEL-"); + host_hunklevel = Hunk_LowMark (0); Cbuf_InsertText (sv_cbuf, "exec server.cfg\n"); diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index 9c627f9e9..c7e287d6d 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -451,9 +451,9 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) VectorAdd (p_angles, amove, p_angles); SV_LinkEdict (pusher, false); - mark = Hunk_LowMark (); - moved_edict = Hunk_Alloc (sv.num_edicts * sizeof (edict_t *)); - moved_from = Hunk_Alloc (sv.num_edicts * sizeof (vec_t)); + mark = Hunk_LowMark (0); + moved_edict = Hunk_Alloc (0, sv.num_edicts * sizeof (edict_t *)); + moved_from = Hunk_Alloc (0, sv.num_edicts * sizeof (vec_t)); // see if any solid entities are inside the final position num_moved = 0; @@ -553,10 +553,10 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) VectorSubtract (m_angles, amove, m_angles); SV_LinkEdict (moved_edict[i], false); } - Hunk_FreeToLowMark (mark); + Hunk_FreeToLowMark (0, mark); return false; } - Hunk_FreeToLowMark (mark); + Hunk_FreeToLowMark (0, mark); return true; } diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index f651599fb..563e74591 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -739,7 +739,7 @@ do_precache (progs_t *pr, const char **cache, int max, const char *name, PR_CheckEmptyString (pr, name); - s = Hunk_TempAlloc (strlen (name) + 1); + s = Hunk_TempAlloc (0, strlen (name) + 1); for (i = 0; *name; i++, name++) { int c = (byte) *name; s[i] = tolower (c); @@ -748,7 +748,7 @@ do_precache (progs_t *pr, const char **cache, int max, const char *name, for (i = 0; i < max; i++) { if (!cache[i]) { - char *c = Hunk_Alloc (strlen (s) + 1); + char *c = Hunk_Alloc (0, strlen (s) + 1); strcpy (c, s); cache[i] = c; // blah, const Sys_MaskPrintf (SYS_dev, "%s: %3d %s\n", func, i, s); diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index ea4d533f4..c5e5fb810 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -174,7 +174,7 @@ PF_substr (progs_t *pr) if (len > l) len = l; - tmp = Hunk_TempAlloc (len + 1); + tmp = Hunk_TempAlloc (0, len + 1); strncpy (tmp, s, len); tmp[len] = 0; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 23affbb91..e73835a39 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -862,7 +862,7 @@ SV_Say (qboolean team) host_client->whensaid[host_client->whensaidhead] = realtime; } - p = Hunk_TempAlloc (strlen (Cmd_Args (1)) + 1); + p = Hunk_TempAlloc (0, strlen (Cmd_Args (1)) + 1); strcpy (p, Cmd_Args (1)); if (*p == '"') { diff --git a/ruamoko/qwaq/builtins/builtins.c b/ruamoko/qwaq/builtins/builtins.c index 9f575617c..9528636b9 100644 --- a/ruamoko/qwaq/builtins/builtins.c +++ b/ruamoko/qwaq/builtins/builtins.c @@ -91,7 +91,7 @@ bi_read (progs_t *pr) int res; char *buffer; - buffer = Hunk_TempAlloc (count); + buffer = Hunk_TempAlloc (0, count); if (!buffer) PR_Error (pr, "%s: couldn't allocate %d bytes", "bi_read", count); res = read (handle, buffer, count); From ca63c0360af4a78593f3b940ce566c45d25bd8ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Jul 2021 11:12:37 +0900 Subject: [PATCH 1696/3664] Do an audit of hunk mark usage I realized that after making the hunk 64-bit clean, I had forgotten to go through and convert all the saved marks to size_t. --- libs/gib/gib_init.c | 2 +- libs/image/pcx.c | 2 +- libs/image/tga.c | 3 ++- libs/models/alias/model_alias.c | 3 ++- libs/models/brush/vulkan_model_brush.c | 2 +- libs/util/cmd.c | 2 +- nq/source/host.c | 2 +- nq/source/sv_phys.c | 2 +- qw/include/server.h | 2 +- qw/source/cl_main.c | 2 +- qw/source/sv_main.c | 2 +- qw/source/sv_phys.c | 2 +- 12 files changed, 14 insertions(+), 12 deletions(-) diff --git a/libs/gib/gib_init.c b/libs/gib/gib_init.c index f7cc09827..9b20c61f8 100644 --- a/libs/gib/gib_init.c +++ b/libs/gib/gib_init.c @@ -62,7 +62,7 @@ static void GIB_Exec_Override_f (void) { char *f; - int mark; + size_t mark; if (Cmd_Argc () != 2) { Sys_Printf ("exec : execute a script file\n"); diff --git a/libs/image/pcx.c b/libs/image/pcx.c index 2eb512c1d..250429502 100644 --- a/libs/image/pcx.c +++ b/libs/image/pcx.c @@ -50,7 +50,7 @@ VISIBLE tex_t * LoadPCX (QFile *f, qboolean convert, const byte *pal, int load) { pcx_t *pcx; - int pcx_mark; + size_t pcx_mark; byte *palette; byte *end; byte *pix; diff --git a/libs/image/tga.c b/libs/image/tga.c index 3491e37ce..20db43ddd 100644 --- a/libs/image/tga.c +++ b/libs/image/tga.c @@ -625,7 +625,8 @@ LoadTGA (QFile *fin, int load) byte *dataByte; decoder_t decode; int fsize = sizeof (TargaHeader); - int numPixels, targa_mark; + int numPixels; + size_t targa_mark; TargaHeader *targa; tex_t *tex; diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index 90ec0b9cd..aa1186b98 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -214,7 +214,8 @@ Mod_LoadAliasGroup (mod_alias_ctx_t *alias_ctx, void *pin, int *posenum, void Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) { - int size, version, numframes, start, end, total, i, j; + size_t size, start, end, total; + int version, numframes, i, j; int extra = 0; // extra precision bytes void *mem; dtriangle_t *pintriangles; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index b2bd64417..970ab1f44 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -360,7 +360,7 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) const char *name = va (ctx->va_ctx, "fb_%s", tx->name); int size = (tx->width * tx->height * 85) / 64; - int fullbright_mark = Hunk_LowMark (0); + size_t fullbright_mark = Hunk_LowMark (0); byte *pixels = Hunk_AllocName (0, size, name); if (!Mod_CalcFullbright ((byte *) (tx + 1), pixels, size)) { diff --git a/libs/util/cmd.c b/libs/util/cmd.c index 6ee2ee10c..13038f53d 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -502,7 +502,7 @@ static void Cmd_Exec_f (void) { char *f; - int mark; + size_t mark; if (Cmd_Argc () != 2) { Sys_Printf ("exec : execute a script file\n"); diff --git a/nq/source/host.c b/nq/source/host.c index f468e4bd9..397911f90 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -94,7 +94,7 @@ double con_realtime; double oldcon_realtime; int host_framecount; -int host_hunklevel; +size_t host_hunklevel; int host_in_game; size_t minimum_memory; diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index f649c0248..ffaf35ae1 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -423,7 +423,7 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) vec3_t forward = {1, 0, 0}; vec3_t left = {0, 1, 0}; vec3_t up = {0, 0, 1}; - int mark; + size_t mark; int c_flags, c_movetype, c_groundentity, c_solid; vec_t *c_absmin, *c_absmax, *c_origin, *c_angles, *c_mins, *c_maxs; vec_t *p_origin, *p_angles; diff --git a/qw/include/server.h b/qw/include/server.h index 3693a32fa..c75cfa659 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -452,7 +452,7 @@ extern char localmodels[MAX_MODELS][5]; // inline model names for precache extern struct info_s *localinfo; -extern int host_hunklevel; +extern size_t host_hunklevel; extern QFile *sv_logfile; extern QFile *sv_fraglogfile; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index f35e1b2cd..7362327cf 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -211,7 +211,7 @@ double con_frametime; double con_realtime; double oldcon_realtime; -int host_hunklevel; +size_t host_hunklevel; cvar_t *host_speeds; cvar_t *hud_fps; diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 9d2002317..0e1904137 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -106,7 +106,7 @@ entity_state_t cl_entities[MAX_CLIENTS][UPDATE_BACKUP+1][MAX_PACKET_ENTITIES]; / double sv_frametime; double realtime; // without any filtering or bounding -int host_hunklevel; +size_t host_hunklevel; netadr_t master_adr[MAX_MASTERS]; // address of group servers diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index c7e287d6d..41ae45ccd 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -426,7 +426,7 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) vec3_t forward = {1, 0, 0}; vec3_t left = {0, 1, 0}; vec3_t up = {0, 0, 1}; - int mark; + size_t mark; int c_flags, c_movetype, c_groundentity, c_solid; vec_t *c_absmin, *c_absmax, *c_origin, *c_angles, *c_mins, *c_maxs; vec_t *p_origin, *p_angles; From 8f376a48f8d5ffab7a636106df671f87e8ef40a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Jul 2021 11:44:10 +0900 Subject: [PATCH 1697/3664] [util] Add raw versions of hunk alloc and free They do not clear memory and thus are good for situations where speed is more critical. --- include/QF/zone.h | 3 +++ libs/util/zone.c | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/include/QF/zone.h b/include/QF/zone.h index 8845cf299..0cd55c66d 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -111,9 +111,12 @@ typedef struct memhunk_s memhunk_t; memhunk_t *Hunk_Init (void *buf, size_t size); void Hunk_Print (memhunk_t *hunk, qboolean all); void Hunk_Check (memhunk_t *hunk); +void *Hunk_RawAlloc (memhunk_t *hunk, size_t size) __attribute__((nonnull(1))); +void *Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) __attribute__((nonnull(1))); void *Hunk_Alloc (memhunk_t *hunk, size_t size); // returns 0 filled memory void *Hunk_AllocName (memhunk_t *hunk, size_t size, const char *name); size_t Hunk_LowMark (memhunk_t *hunk) __attribute__((pure)); +void Hunk_RawFreeToLowMark (memhunk_t *hunk, size_t mark) __attribute__((nonnull(1))); void Hunk_FreeToLowMark (memhunk_t *hunk, size_t mark); void *Hunk_TempAlloc (memhunk_t *hunk, size_t size); diff --git a/libs/util/zone.c b/libs/util/zone.c index f0297f8cd..275948126 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -541,6 +541,8 @@ Hunk_FreeToHighMark (memhunk_t *hunk, size_t mark) hunk->tempactive = false; Hunk_FreeToHighMark (hunk, hunk->tempmark); } + if (mark == hunk->high_used) + return; if (mark > hunk->high_used) Sys_Error ("Hunk_FreeToHighMark: bad mark %zd", mark); memset (hunk->base + hunk->size - hunk->high_used, 0, @@ -561,9 +563,8 @@ Hunk_HighMark (memhunk_t *hunk) } VISIBLE void * -Hunk_AllocName (memhunk_t *hunk, size_t size, const char *name) +Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) { - if (!hunk) { hunk = global_hunk; } //FIXME clean up callers hunkblk_t *h; #ifdef PARANOID @@ -592,8 +593,6 @@ Hunk_AllocName (memhunk_t *hunk, size_t size, const char *name) Cache_FreeLow (hunk, hunk->low_used); - memset (h, 0, size); - h->size = size; h->sentinal1 = HUNK_SENTINAL; h->sentinal2 = HUNK_SENTINAL; @@ -603,6 +602,21 @@ Hunk_AllocName (memhunk_t *hunk, size_t size, const char *name) return (void *) (h + 1); } +VISIBLE void * +Hunk_AllocName (memhunk_t *hunk, size_t size, const char *name) +{ + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + void *mem = Hunk_RawAllocName (hunk, size, name); + memset (mem, 0, size); + return mem; +} + +VISIBLE void * +Hunk_RawAlloc (memhunk_t *hunk, size_t size) +{ + return Hunk_RawAllocName (hunk, size, "unknown"); +} + VISIBLE void * Hunk_Alloc (memhunk_t *hunk, size_t size) { @@ -617,10 +631,22 @@ Hunk_LowMark (memhunk_t *hunk) return hunk->low_used; } +VISIBLE void +Hunk_RawFreeToLowMark (memhunk_t *hunk, size_t mark) +{ + if (mark == hunk->low_used) + return; + if (mark > hunk->low_used) + Sys_Error ("Hunk_FreeToLowMark: bad mark %zd", mark); + hunk->low_used = mark; +} + VISIBLE void Hunk_FreeToLowMark (memhunk_t *hunk, size_t mark) { if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + if (mark == hunk->low_used) + return; if (mark > hunk->low_used) Sys_Error ("Hunk_FreeToLowMark: bad mark %zd", mark); memset (hunk->base + mark, 0, hunk->low_used - mark); From 72a1fef7147623a179b2023e35ec98433ef13c16 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Jul 2021 11:49:18 +0900 Subject: [PATCH 1698/3664] [qfvis] Use hunk to manage winding memory It turns out cmem is not so good for many large allocations (probably a bug in handling the blocks), but was really meant for lots of little churning allocations anyway. After an analysis of winding lifetimes, it became clear that the hunk allocator would work very well. The base windings are allocated from a global hunk (currently 1GB, plenty for even ad_tears), and ephemeral windings are allocated from a per-thread hunk of 1MB (seems to be way more than enough: gmsp3v2 uses a maximum of only 56064 bytes, and ad_tears got through 30% before I gave up on it). Any speed difference (for gmsp3v2) seems to be lost in the noise: still completing in 38.4s on my machine. --- tools/qfvis/include/vis.h | 9 ++++--- tools/qfvis/source/flow.c | 17 ++++++------- tools/qfvis/source/qfvis.c | 49 ++++++++++++-------------------------- 3 files changed, 26 insertions(+), 49 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 54b9de0d1..a96ce18ac 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -76,6 +76,7 @@ extern pthread_rwlock_t *stats_lock; #include "QF/cmem.h" #include "QF/dstring.h" #include "QF/set.h" +#include "QF/zone.h" #include "QF/simd/vec4f.h" #define MAX_PORTALS 32768 @@ -92,7 +93,7 @@ typedef struct winding_s { unsigned numpoints; int id; int thread; - vec4f_t points[MAX_PORTALS_ON_CLUSTER]; // variable sized + vec4f_t points[1]; // variable sized } winding_t; typedef enum { @@ -161,9 +162,7 @@ typedef struct { unsigned sep_free; ///< how many separators were freed unsigned sep_highwater; ///< most separators in flight unsigned sep_maxbulk; ///< most separators freed at once - unsigned winding_alloc; ///< how many windings were allocated - unsigned winding_free; ///< how many windings were freed - unsigned winding_highwater; ///< most windings in flight + size_t winding_mark; ///< most memory allocated to windings unsigned stack_alloc; ///< how many stack blocks were allocated unsigned stack_free; ///< how many stack blocks were freed } visstat_t; @@ -176,6 +175,7 @@ typedef struct threaddata_s { sep_t *sep_freelist; ///< per-thread list of free separators winding_t *winding_freelist; ///< per-thread list of free windings memsuper_t *memsuper; ///< per-thread memory pool + memhunk_t *hunk; dstring_t *str; set_pool_t set_pool; int id; @@ -203,7 +203,6 @@ extern cluster_t *clusters; extern int *leafcluster; extern byte *uncompressed; -void FreeWinding (threaddata_t *thread, winding_t *w); winding_t *NewWinding (threaddata_t *thread, int points); winding_t *ClipWinding (threaddata_t *thread, winding_t *in, vec4f_t split, qboolean keepon); diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 14e039ead..e754cbbdb 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -345,13 +345,18 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) pass_winding = prevstack->pass_winding; pass_plane = prevstack->pass_plane; + size_t winding_mark = Hunk_LowMark (thread->hunk); + // check all portals for flowing into other clusters for (i = 0; i < cluster->numportals; i++) { target_portal = cluster->portals[i]; - if (!set_is_member (prevstack->mightsee, target_portal->cluster)) continue; // can't possibly see it + thread->stats.winding_mark = max (thread->stats.winding_mark, + Hunk_LowMark (thread->hunk)); + Hunk_RawFreeToLowMark (thread->hunk, winding_mark); + // if target_portal can't see anything we haven't already seen, skip it test = select_test_set (target_portal, thread); if (!mightsee_more (might, prevstack->mightsee, test, vis)) { @@ -385,7 +390,6 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) stack->pass_portal = target_portal; RecursiveClusterFlow (target_portal->cluster, thread, stack); - FreeWinding (thread, target_winding); continue; } @@ -399,7 +403,6 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) source_winding = ClipWinding (thread, source_winding, backplane, false); if (!source_winding) { - FreeWinding (thread, target_winding); continue; } @@ -418,7 +421,6 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) target_winding); if (!target_winding) { thread->stats.targetclipped++; - FreeWinding (thread, source_winding); continue; } if (target_winding != old) @@ -437,7 +439,6 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) target_winding); if (!target_winding) { thread->stats.targetclipped++; - FreeWinding (thread, source_winding); continue; } if (target_winding != old) @@ -455,7 +456,6 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) free_separators (thread, sep); if (!source_winding) { thread->stats.sourceclipped++; - FreeWinding (thread, target_winding); continue; } if (source_winding != old) @@ -471,7 +471,6 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) free_separators (thread, sep); if (!source_winding) { thread->stats.sourceclipped++; - FreeWinding (thread, target_winding); continue; } if (source_winding != old) @@ -488,10 +487,8 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) // flow through it for real RecursiveClusterFlow (target_portal->cluster, thread, stack); - - FreeWinding (thread, source_winding); - FreeWinding (thread, target_winding); } + Hunk_RawFreeToLowMark (thread->hunk, winding_mark); free_separators (thread, stack->separators[1]); free_separators (thread, stack->separators[0]); } diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 94ba1507f..e37ebe5fd 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -156,32 +156,15 @@ NewWinding (threaddata_t *thread, int points) winding_t *winding; unsigned size; - if (points > MAX_POINTS_ON_WINDING) - Sys_Error ("NewWinding: %i points", points); - size = field_offset (winding_t, points[points]); - winding = CMEMALLOC (13, winding_t, thread->winding, thread->memsuper); + winding = Hunk_RawAlloc (thread->hunk, size); memset (winding, 0, size); - thread->stats.winding_alloc++; winding->id = thread->winding_id++; winding->thread = thread->id; return winding; } -void -FreeWinding (threaddata_t *thread, winding_t *w) -{ - if (!w->original) { - unsigned count = thread->stats.winding_alloc - thread->stats.winding_free; - if (count > thread->stats.winding_highwater) { - thread->stats.winding_highwater = count; - } - thread->stats.winding_free++; - CMEMFREE (thread->winding, w); - } -} - winding_t * CopyWinding (threaddata_t *thread, const winding_t *w) { @@ -189,10 +172,9 @@ CopyWinding (threaddata_t *thread, const winding_t *w) winding_t *copy; size = field_offset (winding_t, points[w->numpoints]); - copy = CMEMALLOC (13, winding_t, thread->winding, thread->memsuper); + copy = Hunk_RawAlloc (thread->hunk, size); memcpy (copy, w, size); copy->original = false; - thread->stats.winding_alloc++; copy->id = thread->winding_id++; copy->thread = thread->id; return copy; @@ -362,7 +344,6 @@ ClipWinding (threaddata_t *thread, winding_t *in, vec4f_t split, return in; } if (!counts[SIDE_FRONT]) { - FreeWinding (thread, in); return NULL; } if (!counts[SIDE_BACK]) { @@ -397,8 +378,6 @@ ClipWinding (threaddata_t *thread, winding_t *in, vec4f_t split, Sys_Error ("ClipWinding: points exceeded estimate: n:%u m:%u", neww->numpoints, maxpts); } - // free the original winding - FreeWinding (thread, in); return neww; } @@ -461,8 +440,8 @@ UpdateStats (threaddata_t *thread) global_stats.mightseeupdate += thread->stats.mightseeupdate; global_stats.sep_alloc += thread->stats.sep_alloc; global_stats.sep_free += thread->stats.sep_free; - global_stats.winding_alloc += thread->stats.winding_alloc; - global_stats.winding_free += thread->stats.winding_free; + global_stats.winding_mark = max (global_stats.winding_mark, + thread->stats.winding_mark); global_stats.stack_alloc += thread->stats.stack_alloc; global_stats.stack_free += thread->stats.stack_free; UNLOCK (stats_lock); @@ -569,8 +548,10 @@ LeafThread (void *_thread) int thread = (int) (intptr_t) _thread; threaddata_t data; int count = 0; + size_t thread_memsize = 1024 * 1024; memset (&data, 0, sizeof (data)); + data.hunk = Hunk_Init (Sys_Alloc (thread_memsize), thread_memsize); set_pool_init (&data.set_pool); data.id = thread; data.memsuper = new_memsuper (); @@ -588,13 +569,13 @@ LeafThread (void *_thread) PortalFlow (&data, portal); - int whw = data.stats.winding_highwater; + int whm = data.stats.winding_mark; int shw = data.stats.sep_highwater; int smb = data.stats.sep_maxbulk; PortalCompleted (&data, portal); data.stats.sep_highwater = shw; data.stats.sep_maxbulk = smb; - data.stats.winding_highwater = whw; + data.stats.winding_mark = whm; if (options.verbosity >= 4) printf ("portal:%5i mightsee:%5i cansee:%5i %5u/%u\n", @@ -605,8 +586,8 @@ LeafThread (void *_thread) } while (1); if (options.verbosity >= 2) { - printf ("thread %d winding highwater: %d\n", thread, - data.stats.winding_highwater); + printf ("thread %d winding mark: %zd\n", thread, + data.stats.winding_mark); printf ("thread %d separator highwater: %d\n", thread, data.stats.sep_highwater); printf ("thread %d separator maxbulk: %d\n", thread, @@ -619,6 +600,8 @@ LeafThread (void *_thread) working[thread] = -1; delete_memsuper (data.memsuper); dstring_delete (data.str); + + Sys_Free (data.hunk, thread_memsize); return NULL; } @@ -965,9 +948,7 @@ CalcPortalVis (void) printf ("separators allocated: %u freed: %u %u\n", global_stats.sep_alloc, global_stats.sep_free, global_stats.sep_alloc - global_stats.sep_free); - printf ("windings allocated: %u freed: %u %u\n", - global_stats.winding_alloc, global_stats.winding_free, - global_stats.winding_alloc - global_stats.winding_free); + printf ("max windings mark: %zd\n", global_stats.winding_mark); printf ("stack blocks allocated: %u freed: %u %u\n", global_stats.stack_alloc, global_stats.stack_free, global_stats.stack_alloc - global_stats.stack_free); @@ -1283,8 +1264,6 @@ LoadPortals (char *name) line = err; } - if (numpoints > MAX_POINTS_ON_WINDING) - Sys_Error ("LoadPortals: portal %u has too many points", i); if ((unsigned) clusternums[0] > (unsigned) portalclusters || (unsigned) clusternums[1] > (unsigned) portalclusters) Sys_Error ("LoadPortals: reading portal %u", i); @@ -1413,8 +1392,10 @@ main (int argc, char **argv) { double start, stop; QFile *f; + size_t main_memsize = 1024 * 1024 * 1024; main_thread.memsuper = new_memsuper (); + main_thread.hunk = Hunk_Init (Sys_Alloc (main_memsize), main_memsize); start = Sys_DoubleTime (); From 4f51a3b40691dea71593298887fec4f355d0fd32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Jul 2021 14:10:18 +0900 Subject: [PATCH 1699/3664] [utils] Fix set tests for 32-bit machines --- libs/util/test/test-set.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index 6e326268a..f26ce7195 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -237,7 +237,10 @@ main (int argc, const char **argv) tests[5].str_expect = nva ("{%zd}", SIZE); tests[7].str_expect = nva ("{%zd ...}", SIZE); - tests[8].str_expect = nva ("{%zd ...}", SIZE); + tests[8].str_expect = tests[7].str_expect; + tests[9].str_expect = tests[5].str_expect; + tests[10].str_expect = tests[5].str_expect; + tests[11].str_expect = tests[5].str_expect; str = dstring_new (); for (i = 0; i < SIZE; i++) { From 45aa8e6504b2c823e6b23adeb81111a095597066 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Jul 2021 15:03:54 +0900 Subject: [PATCH 1700/3664] [util] Loosen affine test epsilon for SEB Scaling the checks by 1e-6 was a little too tight for very small triangles, but 1e-5 seems to work well. This fixes SEB getting stuck for a ridiculously small (for quake) triangle in ad_tears (probably resulted from some bad math in qfbsp when generating the portal file from the bsp). --- libs/util/mathlib.c | 4 ++-- libs/util/simd.c | 4 ++-- libs/util/test/test-cs.c | 25 +++++++++++++++++++++++-- libs/util/test/test-csvf.c | 25 +++++++++++++++++++++++-- libs/util/test/test-seb.c | 15 +++++++++++++-- libs/util/test/test-sebvf.c | 18 +++++++++++++++--- 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 071c2853b..44aebeabb 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -1353,7 +1353,7 @@ test_support_points(const vec_t **points, int *num_points, const vec3_t center) nn = DotProduct (n, n); dd = DotProduct (d, d); vv = DotProduct (v, v); - in_affine = nn < 1e-6 * vv * dd; + in_affine = nn < 1e-5 * vv * dd; break; case 3: VectorSubtract (points[1], points[0], a); @@ -1363,7 +1363,7 @@ test_support_points(const vec_t **points, int *num_points, const vec3_t center) dn = DotProduct (d, n); dd = DotProduct (d, d); nn = DotProduct (n, n); - in_affine = dn * dn < 1e-6 * dd * nn; + in_affine = dn * dn < 1e-5 * dd * nn; break; case 4: in_affine = 1; diff --git a/libs/util/simd.c b/libs/util/simd.c index 2ad4a9d9a..40dd25b2f 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -197,7 +197,7 @@ test_support_points(const vec4f_t **points, int *num_points, vec4f_t center) nn = dotf (n, n)[0]; dd = dotf (d, d)[0]; vv = dotf (v, v)[0]; - in_affine = nn < 1e-6 * vv * dd; + in_affine = nn < 1e-5 * vv * dd; break; case 3: a = *points[1] - *points[0]; @@ -207,7 +207,7 @@ test_support_points(const vec4f_t **points, int *num_points, vec4f_t center) dn = dotf (d, n)[0]; dd = dotf (d, d)[0]; nn = dotf (n, n)[0]; - in_affine = dn * dn < 1e-6 * dd * nn; + in_affine = dn * dn < 1e-5 * dd * nn; break; case 4: in_affine = 1; diff --git a/libs/util/test/test-cs.c b/libs/util/test/test-cs.c index c30e02333..8f5b5b385 100644 --- a/libs/util/test/test-cs.c +++ b/libs/util/test/test-cs.c @@ -18,6 +18,24 @@ const vec3_t points[] = { { 0, 0, 0}, }; +// This particular triangle from ad_tears caused SEB to hit its iteration +// limit because the center in affine hull test failed due to excessivly tight +// epsilon. +// However, the problem isn't here (but good to have a set of tests for it +// anyway). +const vec3_t tears_triangleA[] = { + {2201.82007, -1262, -713.450012}, + {2201.8501, -1262, -713.593994}, +}; +const vec3_t tears_triangleB[] = { + {2201.82007, -1262, -713.450012}, + {2201.84009, -1262, -713.445007}, +}; +const vec3_t tears_triangleC[] = { + {2201.8501, -1262, -713.593994}, + {2201.84009, -1262, -713.445007}, +}; + struct { const vec3_t *points; int num_points; @@ -28,6 +46,9 @@ struct { {points, 2, {{ 0, 0, 1}, 1.41421356}}, {points, 3, {{-0.333333343, 0.333333343, 0.333333343}, 1.63299322}}, {points, 4, {{0, 0, 0}, 1.73205081}}, + {tears_triangleA, 2, {{2201.83496, -1262, -713.521973}, 0.0734853372}}, + {tears_triangleB, 2, {{2201.83008, -1262, -713.44751}, 0.0103178304}}, + {tears_triangleC, 2, {{2201.84521, -1262, -713.519531}, 0.0746228099}}, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) @@ -61,10 +82,10 @@ main (int argc, const char **argv) || fabs (sphere.radius - tests[i].expect.radius) > 1e-4) { res = 1; printf ("test %d failed\n", (int) i); - printf ("expect: [%.9g %.9g %.9g],%.9g\n", + printf ("expect: {%.9g, %.9g, %.9g},%.9g\n", VectorExpand (tests[i].expect.center), tests[i].expect.radius); - printf ("got : [%.9g %.9g %.9g],%.9g\n", + printf ("got : {%.9g, %.9g, %.9g},%.9g\n", VectorExpand (sphere.center), sphere.radius); } diff --git a/libs/util/test/test-csvf.c b/libs/util/test/test-csvf.c index 58ca3f47c..8b73a4aa4 100644 --- a/libs/util/test/test-csvf.c +++ b/libs/util/test/test-csvf.c @@ -19,6 +19,24 @@ const vec4f_t points[] = { { 0, 0, 0}, }; +// This particular triangle from ad_tears caused SEB to hit its iteration +// limit because the center in affine hull test failed due to excessivly tight +// epsilon. +// However, the problem isn't here (but good to have a set of tests for it +// anyway). +const vec4f_t tears_triangleA[] = { + {2201.82007, -1262, -713.450012, 1}, + {2201.8501, -1262, -713.593994, 1}, +}; +const vec4f_t tears_triangleB[] = { + {2201.82007, -1262, -713.450012, 1}, + {2201.84009, -1262, -713.445007, 1}, +}; +const vec4f_t tears_triangleC[] = { + {2201.8501, -1262, -713.593994, 1}, + {2201.84009, -1262, -713.445007, 1}, +}; + struct { const vec4f_t *points; int num_points; @@ -29,6 +47,9 @@ struct { {points, 2, {{ 0, 0, 1}, 1.41421356}}, {points, 3, {{-0.333333343, 0.333333343, 0.333333343}, 1.63299322}}, {points, 4, {{0, 0, 0}, 1.73205081}}, + {tears_triangleA, 2, {{2201.83496, -1262, -713.521973}, 0.0734853372}}, + {tears_triangleB, 2, {{2201.83008, -1262, -713.44751}, 0.0103178304}}, + {tears_triangleC, 2, {{2201.84521, -1262, -713.519531}, 0.0746228099}}, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) @@ -63,10 +84,10 @@ main (int argc, const char **argv) || fabs (sphere.radius - tests[i].expect.radius) > 1e-4) { res = 1; printf ("test %d failed\n", (int) i); - printf ("expect: [%.9g %.9g %.9g],%.9g\n", + printf ("expect: {%.9g, %.9g, %.9g},%.9g\n", VectorExpand (tests[i].expect.center), tests[i].expect.radius); - printf ("got : [%.9g %.9g %.9g],%.9g\n", + printf ("got : {%.9g, %.9g, %.9g},%.9g\n", VectorExpand (sphere.center), sphere.radius); } diff --git a/libs/util/test/test-seb.c b/libs/util/test/test-seb.c index d5e900972..01a4c6b25 100644 --- a/libs/util/test/test-seb.c +++ b/libs/util/test/test-seb.c @@ -18,6 +18,16 @@ const vec3_t points[] = { { 0, 0, 0}, }; +// This particular triangle from ad_tears caused SEB to hit its iteration +// limit because the center in affine hull test failed due to excessivly tight +// epsilon. Yes, a rather insanely small triangle for a quake map. Probably +// due to qfbsp not culling the portal for being too small. +const vec3_t tears_triangle[] = { + {2201.82007, -1262, -713.450012}, + {2201.8501, -1262, -713.593994}, + {2201.84009, -1262, -713.445007}, +}; + struct { const vec3_t *points; int num_points; @@ -28,6 +38,7 @@ struct { {points, 2, {{ 0, 0, 1}, 1.41421356}}, {points, 3, {{-0.333333343, 0.333333343, 0.333333343}, 1.63299322}}, {points, 4, {{0, 0, 0}, 1.73205081}}, + {tears_triangle, 3, {{2201.84521, -1262, -713.519531}, 0.0747000724}}, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) @@ -61,10 +72,10 @@ main (int argc, const char **argv) || fabs (sphere.radius - tests[i].expect.radius) > 1e-4) { res = 1; printf ("test %d failed\n", (int) i); - printf ("expect: [%.9g %.9g %.9g],%.9g\n", + printf ("expect: {%.9g, %.9g, %.9g},%.9g\n", VectorExpand (tests[i].expect.center), tests[i].expect.radius); - printf ("got : [%.9g %.9g %.9g],%.9g\n", + printf ("got : {%.9g, %.9g, %.9g},%.9g\n", VectorExpand (sphere.center), sphere.radius); } diff --git a/libs/util/test/test-sebvf.c b/libs/util/test/test-sebvf.c index 55fc8b654..ef811e364 100644 --- a/libs/util/test/test-sebvf.c +++ b/libs/util/test/test-sebvf.c @@ -19,6 +19,16 @@ const vec4f_t points[] = { { 0, 0, 0, 1}, }; +// This particular triangle from ad_tears caused SEB to hit its iteration +// limit because the center in affine hull test failed due to excessivly tight +// epsilon. Yes, a rather insanely small triangle for a quake map. Probably +// due to qfbsp not culling the portal for being too small. +const vec4f_t tears_triangle[] = { + {2201.82007, -1262, -713.450012, 1}, + {2201.8501, -1262, -713.593994, 1}, + {2201.84009, -1262, -713.445007, 1}, +}; + struct { const vec4f_t *points; int num_points; @@ -29,6 +39,7 @@ struct { {points, 2, {{ 0, 0, 1, 1}, 1.41421356}}, {points, 3, {{-0.333333343, 0.333333343, 0.333333343, 1}, 1.63299322}}, {points, 4, {{0, 0, 0, 1}, 1.73205081}}, + {tears_triangle, 3, {{2201.84521, -1262, -713.519531}, 0.0747000724}}, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) @@ -57,15 +68,16 @@ main (int argc, const char **argv) double start, end; for (i = 0; i < num_tests; i ++) { - sphere = SmallestEnclosingBall_vf (tests[i].points, tests[i].num_points); + sphere = SmallestEnclosingBall_vf (tests[i].points, + tests[i].num_points); if (VectorDistance_fast (sphere.center, tests[i].expect.center) > 1e-4 || fabs (sphere.radius - tests[i].expect.radius) > 1e-4) { res = 1; printf ("test %d failed\n", (int) i); - printf ("expect: [%.9g %.9g %.9g],%.9g\n", + printf ("expect: {%.9g, %.9g, %.9g}, %.9g\n", VectorExpand (tests[i].expect.center), tests[i].expect.radius); - printf ("got : [%.9g %.9g %.9g],%.9g\n", + printf ("got : {%.9g, %.9g, %.9g}, %.9g\n", VectorExpand (sphere.center), sphere.radius); } From 6d312aaa636286426fa70699fbb6a21b6097a426 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Jul 2021 15:15:14 +0900 Subject: [PATCH 1701/3664] [simd] Check the distance to the affine point As per usual, fp math finds a way to confound any epsilon test. So rather than relying entirely on test_support_points, check the distance from the sphere center to the affine point and break out of the loop if the distance is small enough (< 1% of the current radius). This allows qfvis to load ad_tears without hacks. --- libs/util/mathlib.c | 8 +++++++- libs/util/simd.c | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 44aebeabb..1fc03508b 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -1443,11 +1443,17 @@ SmallestEnclosingBall (const vec3_t points[], int num_points) if (iters++ > 10) Sys_Error ("stuck SEB"); - best = 0; closest_affine_point (support, num_support, sphere.center, affine); VectorSubtract (affine, sphere.center, center_to_affine); affine_dist = DotProduct (center_to_affine, center_to_affine); + if (affine_dist < sphere.radius * 1e-5) { + // It's possible test_support_points failed due to precision + // issues + break; + } + + best = 0; for (i = 0; i < num_points; i++) { if (points[i] == support[0] || points[i] == support[1] || points[i] == support[2]) diff --git a/libs/util/simd.c b/libs/util/simd.c index 40dd25b2f..07670219b 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -288,11 +288,17 @@ SmallestEnclosingBall_vf (const vec4f_t *points, int num_points) if (iters++ > 10) Sys_Error ("stuck SEB"); - best = 0; affine = closest_affine_point (support, num_support, center); center_to_affine = affine - center; affine_dist = dotf (center_to_affine, center_to_affine)[0]; + if (affine_dist < sphere.radius * 1e-5) { + // It's possible test_support_points failed due to precision + // issues + break; + } + + best = 0; for (i = 0; i < num_points; i++) { if (&points[i] == support[0] || &points[i] == support[1] || &points[i] == support[2]) From 756214ca8eb5bb93be367f17c9a8666ea46d9502 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Jul 2021 15:25:37 +0900 Subject: [PATCH 1702/3664] [qfvis] Use unsigned for the plane side tests Doesn't make any difference to the number of instructions, but seeing sar instead of shr bothers me when working with bit patterns. --- tools/qfvis/source/qfvis.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index e37ebe5fd..9ed0ca014 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -247,43 +247,43 @@ split_edge (const vec4f_t *points, const vec4f_t *dists, return mid; } -static inline int __attribute__((const)) -is_not_on (int x) +static inline unsigned __attribute__((const)) +is_not_on (unsigned x) { return x & 1; } -static inline int __attribute__((const)) -is_back (int x) +static inline unsigned __attribute__((const)) +is_back (unsigned x) { return x & 2; } -static inline int __attribute__((const)) +static inline unsigned __attribute__((const)) is_not_back (unsigned x) { return ~x & 2; } -static inline int __attribute__((const)) +static inline unsigned __attribute__((const)) is_front (unsigned x) { return is_not_on (x) & (is_not_back (x) >> 1); } -static inline int __attribute__((const)) +static inline unsigned __attribute__((const)) is_back_front (unsigned x, unsigned y) { return (is_back (x) >> 1) & is_front (y); } -static inline int __attribute__((const)) +static inline unsigned __attribute__((const)) is_front_back (unsigned x, unsigned y) { return is_front (x) & (is_back (y) >> 1); } -static inline int __attribute__((const)) +static inline unsigned __attribute__((const)) is_transition (unsigned x, unsigned y) { return is_back_front (x, y) | is_front_back (x, y); From fe98a513bc11e2934e4ca1e39a5d204d2d3ad77a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Jul 2021 15:27:48 +0900 Subject: [PATCH 1703/3664] [util] Add a function to check hunk pointers Its only real utility is to check that a pointer is not pointing into freed space. --- include/QF/zone.h | 1 + libs/util/zone.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/QF/zone.h b/include/QF/zone.h index 0cd55c66d..93dbc8089 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -119,6 +119,7 @@ size_t Hunk_LowMark (memhunk_t *hunk) __attribute__((pure)); void Hunk_RawFreeToLowMark (memhunk_t *hunk, size_t mark) __attribute__((nonnull(1))); void Hunk_FreeToLowMark (memhunk_t *hunk, size_t mark); void *Hunk_TempAlloc (memhunk_t *hunk, size_t size); +int Hunk_PointerIsValid (memhunk_t *hunk, void *ptr) __attribute__((pure)); diff --git a/libs/util/zone.c b/libs/util/zone.c index 275948126..a2b68d754 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -715,6 +715,30 @@ Hunk_TempAlloc (memhunk_t *hunk, size_t size) return buf; } +VISIBLE int +Hunk_PointerIsValid (memhunk_t *hunk, void *ptr) +{ + if (!hunk) { hunk = global_hunk; } //FIXME clean up callers + + size_t offset = (byte *) ptr - hunk->base; + if (offset >= hunk->size) { + return 0; + } + if (offset < hunk->low_used) { + // the pointer is somewhere in the lower space of the hunk + // FIXME better checking? + return 1; + } + if (offset >= hunk->size - hunk->high_used + sizeof (hunkblk_t)) { + // the pointer is somewhere in the upper space of the hunk + // FIXME better checking? + return 1; + } + // the pointer is somewhere in between the two marks, so it has probably + // been freed + return 0; +} + /* CACHE MEMORY */ From 9461779ba7bc546a58bef65c0579206154e74e85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Jul 2021 21:03:07 +0900 Subject: [PATCH 1704/3664] [qfvis] Remove the cluster portals limit This removes the last of the arbitrary limits from qfvis. The goal is not so much supporting crazy maps, but more about better data usage (cluster_t is now 24 (or 16) bytes instead of 1048 (or 528). And passages isn't used (yet?)... --- tools/qfvis/include/vis.h | 5 +- tools/qfvis/source/base-vis.c | 2 +- tools/qfvis/source/flow.c | 2 +- tools/qfvis/source/qfvis.c | 161 ++++++++++++++++++++-------------- 4 files changed, 98 insertions(+), 72 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index a96ce18ac..d3c9ead53 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -79,13 +79,10 @@ extern pthread_rwlock_t *stats_lock; #include "QF/zone.h" #include "QF/simd/vec4f.h" -#define MAX_PORTALS 32768 #define PORTALFILE "PRT1" #define PORTALFILE_AM "PRT1-AM" #define PORTALFILE2 "PRT2" #define ON_EPSILON 0.1 -#define MAX_POINTS_ON_WINDING 64 -#define MAX_PORTALS_ON_CLUSTER 128 typedef struct winding_s { struct winding_s *next; @@ -130,7 +127,7 @@ typedef struct cluster_s { int numportals; int visofs; passage_t *passages; - portal_t *portals[MAX_PORTALS_ON_CLUSTER]; + portal_t *portals; } cluster_t; typedef struct pstack_s { diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index 877f3f97d..a0b0300b7 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -76,7 +76,7 @@ SimpleFlood (basethread_t *thread, portal_t *srcportal, int clusternum) cluster = &clusters[clusternum]; for (i = 0; i < cluster->numportals; i++) { - portal = cluster->portals[i]; + portal = &cluster->portals[i]; if (!set_is_member (thread->portalsee, portal - portals)) continue; SimpleFlood (thread, srcportal, portal->cluster); diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index e754cbbdb..3b653ab7e 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -349,7 +349,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) // check all portals for flowing into other clusters for (i = 0; i < cluster->numportals; i++) { - target_portal = cluster->portals[i]; + target_portal = &cluster->portals[i]; if (!set_is_member (prevstack->mightsee, target_portal->cluster)) continue; // can't possibly see it diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 9ed0ca014..8c44581fe 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -408,7 +408,7 @@ UpdateMightsee (threaddata_t *thread, cluster_t *source, cluster_t *dest) clusternum = dest - clusters; for (i = 0; i < source->numportals; i++) { - portal = source->portals[i]; + portal = &source->portals[i]; WRLOCK_PORTAL (portal); if (portal->status == stat_none) { if (set_is_member (portal->mightsee, clusternum)) { @@ -462,7 +462,7 @@ PortalCompleted (threaddata_t *thread, portal_t *completed) changed = set_new_size_r (&thread->set_pool, portalclusters); cluster = &clusters[completed->cluster]; for (i = 0; i < cluster->numportals; i++) { - portal = cluster->portals[i]; + portal = &cluster->portals[i]; if (portal->status != stat_done) continue; set_assign (changed, portal->mightsee); @@ -480,10 +480,10 @@ PortalCompleted (threaddata_t *thread, portal_t *completed) for (j = 0; j < cluster->numportals; j++) { if (j == i) continue; - if (cluster->portals[j]->status == stat_done) - set_difference (changed, cluster->portals[j]->visbits); + if (cluster->portals[j].status == stat_done) + set_difference (changed, cluster->portals[j].visbits); else - set_difference (changed, cluster->portals[j]->mightsee); + set_difference (changed, cluster->portals[j].mightsee); } for (ci = set_first_r (&thread->set_pool, changed); ci; ci = set_next_r (&thread->set_pool, ci)) { @@ -845,7 +845,7 @@ ClusterFlow (int clusternum) memset (compressed.data, 0, compressed.maxsize); visclusters = set_new (); for (i = 0; i < cluster->numportals; i++) { - portal = cluster->portals[i]; + portal = &cluster->portals[i]; if (portal->status != stat_done) Sys_Error ("portal not done"); set_union (visclusters, portal->visbits); @@ -1153,20 +1153,58 @@ CalcPassages (void) } } #endif + +static winding_t * +parse_winding (const char *line, int numpoints) +{ + winding_t *winding = NewWinding (&main_thread, numpoints); + + winding->original = true; + winding->numpoints = numpoints; + + for (int i = 0; i < numpoints; i++) { + // (%ld %ld %ld) + while (isspace ((byte) *line)) + line++; + if (*line++ != '(') { + return 0; + } + + for (int j = 0; j < 3; j++) { + char *err; + + winding->points[i][j] = strtod (line, &err); + if (err == line) { + return 0; + } + line = err; + } + winding->points[i][3] = 1; + + while (isspace ((byte) *line)) + line++; + if (*line++ != ')') { + return 0; + } + } + return winding; +} + static void LoadPortals (char *name) { + typedef struct { + unsigned clusters[2]; + } clusterpair_t; + const char *line; char *err; - unsigned numpoints, i, j, k; + unsigned numpoints; int read_leafs = 0; - int clusternums[2]; - cluster_t *cluster; vec4f_t plane; - portal_t *portal; - winding_t *winding; vspheref_t sphere; QFile *f; + clusterpair_t *clusternums; if (!strcmp (name, "-")) f = Qdopen (0, "rt"); // create a QFile of stdin @@ -1233,22 +1271,24 @@ LoadPortals (char *name) // direction portals = calloc (2 * numportals, sizeof (portal_t)); portal_queue = malloc (2 * numportals * sizeof (portal_t *)); - for (i = 0; i < 2 * numportals; i++) { + for (unsigned i = 0; i < 2 * numportals; i++) { portal_queue[i] = &portals[i]; } #ifdef USE_PTHREADS portal_locks = calloc (2 * numportals, sizeof (pthread_rwlock_t)); - for (i = 0; i < 2 * numportals; i++) { + for (unsigned i = 0; i < 2 * numportals; i++) { if (pthread_rwlock_init (&portal_locks[i], 0)) Sys_Error ("pthread_rwlock_init failed"); } #endif - clusters = calloc (portalclusters, sizeof (cluster_t)); + clusters = calloc (portalclusters, sizeof (cluster_t)); originalvismapsize = numrealleafs * ((numrealleafs + 7) / 8); - for (i = 0, portal = portals; i < numportals; i++) { + clusternums = calloc (numportals, sizeof (clusterpair_t)); + winding_t **windings = malloc (numportals * sizeof (winding_t *)); + for (unsigned i = 0; i < numportals; i++) { line = Qgetline (f); if (!line) Sys_Error ("LoadPortals: reading portal %u", i); @@ -1257,41 +1297,36 @@ LoadPortals (char *name) if (err == line) Sys_Error ("LoadPortals: reading portal %u", i); line = err; - for (j = 0; j < 2; j++) { - clusternums[j] = strtol (line, &err, 10); + + for (int j = 0; j < 2; j++) { + clusternums[i].clusters[j] = strtoul (line, &err, 10); if (err == line) Sys_Error ("LoadPortals: reading portal %u", i); line = err; - } - if ((unsigned) clusternums[0] > (unsigned) portalclusters - || (unsigned) clusternums[1] > (unsigned) portalclusters) + if (clusternums[i].clusters[j] > portalclusters) + Sys_Error ("LoadPortals: reading portal %u", i); + } + clusters[clusternums[i].clusters[0]].numportals++; + clusters[clusternums[i].clusters[1]].numportals++; + + if (!(windings[i] = parse_winding (line, numpoints))) { Sys_Error ("LoadPortals: reading portal %u", i); - - winding = portal->winding = NewWinding (&main_thread, numpoints); - winding->original = true; - winding->numpoints = numpoints; - - for (j = 0; j < numpoints; j++) { - // (%ld %ld %ld) - while (isspace ((byte) *line)) - line++; - if (*line++ != '(') - Sys_Error ("LoadPortals: reading portal %u", i); - - for (k = 0; k < 3; k++) { - winding->points[j][k] = strtod (line, &err); - if (err == line) - Sys_Error ("LoadPortals: reading portal %u", i); - line = err; - } - winding->points[j][3] = 1; - - while (isspace ((byte) *line)) - line++; - if (*line++ != ')') - Sys_Error ("LoadPortals: reading portal %u", i); } + } + + clusters[0].portals = portals; + for (unsigned i = 1; i < portalclusters; i++) { + portal_t *portal = clusters[i - 1].portals; + clusters[i].portals = portal + clusters[i - 1].numportals; + clusters[i - 1].numportals = 0; + } + clusters[portalclusters - 1].numportals = 0; + + for (unsigned i = 0; i < numportals; i++) { + winding_t *winding = windings[i]; + cluster_t *cluster; + portal_t *portal; sphere = SmallestEnclosingBall_vf(winding->points, winding->numpoints); //printf (VEC4F_FMT" %.9g\n", VEC4_EXP (sphere.center), sphere.radius); @@ -1300,45 +1335,39 @@ LoadPortals (char *name) plane = PlaneFromWinding (winding); // create forward portal - cluster = &clusters[clusternums[0]]; - if (cluster->numportals == MAX_PORTALS_ON_CLUSTER) - Sys_Error ("Cluster with too many portals"); - cluster->portals[cluster->numportals] = portal; - cluster->numportals++; - - portal->winding = winding; + cluster = &clusters[clusternums[i].clusters[0]]; + portal = &cluster->portals[cluster->numportals++]; portal->plane = -plane; // plane is for CW, portal is CCW - portal->cluster = clusternums[1]; portal->sphere = sphere; - portal++; - - // create backwards portal - cluster = &clusters[clusternums[1]]; - if (cluster->numportals == MAX_PORTALS_ON_CLUSTER) - Sys_Error ("Cluster with too many portals"); - cluster->portals[cluster->numportals] = portal; - cluster->numportals++; + portal->cluster = clusternums[i].clusters[1]; + portal->winding = winding; // Use a flipped winding for the reverse portal so the winding // direction and plane normal match. - portal->winding = NewFlippedWinding (&main_thread, winding); - portal->winding->original = true; + winding = NewFlippedWinding (&main_thread, winding); // ** + winding->original = true; + + // create backwards portal + cluster = &clusters[clusternums[i].clusters[1]]; + portal = &cluster->portals[cluster->numportals++]; portal->plane = plane; - portal->cluster = clusternums[0]; portal->sphere = sphere; - portal++; + portal->cluster = clusternums[i].clusters[0]; + portal->winding = winding; } + free (clusternums); + free (windings); leafcluster = calloc (numrealleafs, sizeof (int)); if (read_leafs) { - for (i = 0; i < numrealleafs; i++) { + for (unsigned i = 0; i < numrealleafs; i++) { line = Qgetline (f); if (sscanf (line, "%i\n", &leafcluster[i]) != 1) Sys_Error ("LoadPortals: parse error in leaf->cluster " "mappings"); } } else { - for (i = 0; i < numrealleafs; i++) + for (unsigned i = 0; i < numrealleafs; i++) leafcluster[i] = i; } Qclose (f); From 9d819254d49dd37840566c540e39d404edd379ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 30 Jul 2021 13:50:12 +0900 Subject: [PATCH 1705/3664] [util] Make a number of improvements to SEB Attempting to vis ad_tears drags a few lurking bugs out of SmallestEnclosingBall_vf: poor calculation of 2-point affine space, poor handling of duplicate points and dropped support points, poor calculation of the new center (related to duplicate points), and insufficient iterations for large point sets. qfvis (modified for cluster spheres) now loads ad_tears. --- libs/util/mathlib.c | 59 +++++++------ libs/util/simd.c | 61 +++++++------ libs/util/test/test-seb.c | 169 ++++++++++++++++++++++++++++++++++- libs/util/test/test-sebvf.c | 172 +++++++++++++++++++++++++++++++++++- 4 files changed, 399 insertions(+), 62 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 1fc03508b..f4bf46dba 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -35,6 +35,8 @@ # include #endif +#include "qfalloca.h" + #include #define IMPLEMENT_R_Cull @@ -42,6 +44,7 @@ #include "QF/mathlib.h" #include "QF/qtypes.h" +#include "QF/set.h" #include "QF/sys.h" VISIBLE int nanmask = 255 << 23; @@ -1348,12 +1351,13 @@ test_support_points(const vec_t **points, int *num_points, const vec3_t center) break; case 2: VectorSubtract (points[1], points[0], v); - VectorSubtract (center, points[0], d); + VectorAdd (points[0], points[1], d); + VectorScale (d, 0.5, d); + VectorSubtract (center, d, d); CrossProduct (v, d, n); nn = DotProduct (n, n); - dd = DotProduct (d, d); vv = DotProduct (v, v); - in_affine = nn < 1e-5 * vv * dd; + in_affine = nn < 1e-5 * vv * vv; break; case 3: VectorSubtract (points[1], points[0], a); @@ -1403,12 +1407,14 @@ test_support_points(const vec_t **points, int *num_points, const vec3_t center) sphere_t SmallestEnclosingBall (const vec3_t points[], int num_points) { + set_t was_support = SET_STATIC_INIT (num_points, alloca); sphere_t sphere; const vec_t *best; const vec_t *support[4]; int num_support; vec_t dist, best_dist; int i; + int best_i = 0; int iters = 0; if (num_points < 1) { @@ -1419,6 +1425,7 @@ SmallestEnclosingBall (const vec3_t points[], int num_points) for (i = 0; i < 4; i++) support[i] = 0; + set_empty (&was_support); VectorCopy (points[0], sphere.center); best_dist = dist = 0; @@ -1427,55 +1434,51 @@ SmallestEnclosingBall (const vec3_t points[], int num_points) dist = VectorDistance_fast (points[i], sphere.center); if (dist > best_dist) { best_dist = dist; + best_i = i; best = points[i]; } } num_support = 1; support[0] = best; sphere.radius = best_dist; // note: radius squared until the end + set_add (&was_support, best_i); while (!test_support_points (support, &num_support, sphere.center)) { - vec3_t affine; - vec3_t center_to_affine, center_to_point; - vec_t affine_dist, point_proj, point_dist, bound; - vec_t scale = 1; + vec3_t affine, v, p, r; + vec_t x, best_x = 0, rr, pv, pp; int i; - if (iters++ > 10) + if (iters++ > 2 * num_points) Sys_Error ("stuck SEB"); closest_affine_point (support, num_support, sphere.center, affine); - VectorSubtract (affine, sphere.center, center_to_affine); - affine_dist = DotProduct (center_to_affine, center_to_affine); - if (affine_dist < sphere.radius * 1e-5) { - // It's possible test_support_points failed due to precision - // issues - break; - } + VectorSubtract (support[0], affine, r); + rr = DotProduct (r, r); + VectorSubtract (sphere.center, affine, v); best = 0; for (i = 0; i < num_points; i++) { - if (points[i] == support[0] || points[i] == support[1] - || points[i] == support[2]) + if (SET_TEST_MEMBER (&was_support, i)) { continue; - VectorSubtract (points[i], sphere.center, center_to_point); - point_proj = DotProduct (center_to_affine, center_to_point); - if (affine_dist - point_proj <= 0 - || ((affine_dist - point_proj) * (affine_dist - point_proj) - < 1e-6 * sphere.radius * affine_dist)) + } + VectorSubtract (points[i], affine, p); + pp = DotProduct (p, p); + pv = DotProduct (p, v); + if (pp <= rr || pv <= 0 || pv * pv < 1e-6 * rr) { continue; - point_dist = DotProduct (center_to_point, center_to_point); - bound = sphere.radius - point_dist; - bound /= 2 * (affine_dist - point_proj); - if (bound < scale) { + } + x = (pp - rr) / (2 * pv); + if (x > best_x) { best = points[i]; - scale = bound; + best_i = i; + best_x = x; } } - VectorMultAdd (sphere.center, scale, center_to_affine, sphere.center); + VectorMultAdd (affine, best_x, v, sphere.center); sphere.radius = VectorDistance_fast (sphere.center, support[0]); if (best) { support[num_support++] = best; + set_add (&was_support, best_i); } } best_dist = 0; diff --git a/libs/util/simd.c b/libs/util/simd.c index 07670219b..5ad1ab3e0 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -28,6 +28,8 @@ # include "config.h" #endif +#include "qfalloca.h" + #include #define IMPLEMENT_VEC4F_Funcs @@ -37,6 +39,7 @@ #include "QF/simd/vec4d.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" +#include "QF/set.h" #include "QF/sys.h" vec4f_t @@ -192,12 +195,11 @@ test_support_points(const vec4f_t **points, int *num_points, vec4f_t center) break; case 2: v = *points[1] - *points[0]; - d = center - *points[0]; + d = center - (*points[0] + *points[1]) / 2; n = crossf (v, d); nn = dotf (n, n)[0]; - dd = dotf (d, d)[0]; vv = dotf (v, v)[0]; - in_affine = nn < 1e-5 * vv * dd; + in_affine = nn <= 1e-5 * vv * vv; break; case 3: a = *points[1] - *points[0]; @@ -247,6 +249,7 @@ test_support_points(const vec4f_t **points, int *num_points, vec4f_t center) vspheref_t SmallestEnclosingBall_vf (const vec4f_t *points, int num_points) { + set_t was_support = SET_STATIC_INIT (num_points, alloca); vspheref_t sphere = {}; vec4f_t center = {}; const vec4f_t *best; @@ -262,6 +265,7 @@ SmallestEnclosingBall_vf (const vec4f_t *points, int num_points) for (i = 0; i < 4; i++) { support[i] = 0; } + set_empty (&was_support); vec4f_t dist = {}; float best_dist = 0; @@ -278,50 +282,51 @@ SmallestEnclosingBall_vf (const vec4f_t *points, int num_points) num_support = 1; support[0] = best; sphere.radius = best_dist; // note: radius squared until the end + set_add (&was_support, best - points); while (!test_support_points (support, &num_support, center)) { - vec4f_t affine; - vec4f_t center_to_affine, center_to_point; - float affine_dist, point_proj, point_dist, bound; - float scale = 1; + vec4f_t affine, r, rr; + vec4f_t v, p, pv, pp, x; + vec4f_t best_x = { }; int i; - if (iters++ > 10) + //Sys_Printf ("%d: "VEC4F_FMT", %.9g, %d\n", iters, VEC4_EXP (center), sqrt(sphere.radius), num_support); + if (iters++ > 2 * num_points) { + //for (i = 0; i < num_points; i++) { + // Sys_Printf (VEC4F_FMT",\n", VEC4_EXP (points[i])); + //} Sys_Error ("stuck SEB"); + } affine = closest_affine_point (support, num_support, center); - center_to_affine = affine - center; - affine_dist = dotf (center_to_affine, center_to_affine)[0]; - if (affine_dist < sphere.radius * 1e-5) { - // It's possible test_support_points failed due to precision - // issues - break; - } + r = *support[0] - affine; //FIXME better choice + rr = dotf (r, r); + v = center - affine; best = 0; for (i = 0; i < num_points; i++) { - if (&points[i] == support[0] || &points[i] == support[1] - || &points[i] == support[2]) + if (SET_TEST_MEMBER (&was_support, i)) { continue; - center_to_point = points[i] - center; - point_proj = dotf (center_to_affine, center_to_point)[0]; - if (affine_dist - point_proj <= 0 - || ((affine_dist - point_proj) * (affine_dist - point_proj) - < 1e-6 * sphere.radius * affine_dist)) + } + p = points[i] - affine; + pp = dotf (p, p); + pv = dotf (p, v); + if (pp[0] <= rr[0] || pv[0] <= 0 + || (pv[0] * pv[0]) < 1e-6 * rr[0]) { continue; - point_dist = dotf (center_to_point, center_to_point)[0]; - bound = sphere.radius - point_dist; - bound /= 2 * (affine_dist - point_proj); - if (bound < scale) { + } + x = (pp - rr) / (2 * pv); + if (x[0] > best_x[0]) { best = &points[i]; - scale = bound; + best_x = x; } } - center = center + scale * center_to_affine; + center = affine + best_x * v; dist = center - *support[0]; sphere.radius = dotf (dist, dist)[0]; if (best) { support[num_support++] = best; + set_add (&was_support, best - points); } } best_dist = 0; diff --git a/libs/util/test/test-seb.c b/libs/util/test/test-seb.c index 01a4c6b25..a901e4f70 100644 --- a/libs/util/test/test-seb.c +++ b/libs/util/test/test-seb.c @@ -6,6 +6,8 @@ #include "QF/mersenne.h" #include "QF/sys.h" +#define SIZEOF(x) (sizeof(x) / sizeof(x[0])) + const vec3_t points[] = { {-1, -1, 1}, { 1, 1, 1}, @@ -24,9 +26,155 @@ const vec3_t points[] = { // due to qfbsp not culling the portal for being too small. const vec3_t tears_triangle[] = { {2201.82007, -1262, -713.450012}, - {2201.8501, -1262, -713.593994}, + {2201.8501, -1262, -713.593994}, {2201.84009, -1262, -713.445007}, }; +const vec3_t tears_triangle2[] = { + {-519.989014, 1111.94995, -2592.05005}, + {-520.002991, 1112, -2592.02002}, + {-520.005005, 1112, -2592.04004}, +}; +const vec3_t tears_triangle3[] = { + {284, 624, 2959.76001}, + {284, 624, 2960}, + {284.234985, 624.471008, 2959.53003}, +}; + +const vec3_t tears_quad[] = { + {1792, 1155.53003, 240}, + {1792, 1030.32996, 240}, + {1792.01001, 1030.32996, 240}, + {1792.01001, 1155.53003, 240}, +}; + +const vec3_t tears_quad2[] = { + {304, 3248, 3208}, + {-61.2307014, 3248, 3208}, + {-61.2307014, 3248, 3192}, + {304, 3248, 3192}, +}; + +const vec3_t tears_cluster[] = { + {551.638, -439.277008, 2804.63989}, + {551, -438, 2806.02002}, + {555.999023, -447.998993, 2805.1499}, + {555.999023, -447.998993, 2804.32007}, + {551.638, -439.277008, 2804.63989}, + {555.999023, -447.998993, 2804.32007}, + {555.999023, -447.998993, 2795.19995}, + {550.97699, -437.954987, 2806.02002}, + {551, -438, 2806.02002}, + {555.999023, -447.998993, 2795.19995}, + {555.999023, -447.998993, 2794.6499}, + {550.978027, -437.954987, 2806.02002}, + {545.945984, -442.945007, 2804.78003}, + {546, -442.998993, 2804.77002}, + {546, -443, 2804.69995}, + {546, -443, 2804.78003}, + {545.945007, -442.945007, 2804.78003}, + {556, -448, 2794.6499}, + {556, -448, 2805.1499}, + {546, -443, 2804.78003}, + {546, -443, 2804.69995}, + {550.97699, -437.954987, 2806.02002}, + {556, -448, 2794.6499}, + {546.000977, -443, 2804.69995}, + {545.945007, -442.945007, 2804.78003}, +}; + +const vec3_t tears_cluster2[] = { + {-2160, -192, -704.242004}, + {-2160, -192, -662}, + {-2160, -196, -658}, + {-2160, -220, -646}, + {-2160, -222.332001, -645.416992}, + {-2160, -320, -752}, + {-2160, -192, -752}, + {-2160, -192, -704.242004}, + {-2160, -222.332001, -645.416992}, + {-2160, -244, -640}, + {-2160, -268, -640}, + {-2160, -292, -646}, + {-2160, -316, -658}, + {-2160, -320, -662}, + {-2160, -196, -814}, + {-2160, -192, -810}, + {-2160, -192, -752}, + {-2160, -320, -752}, + {-2160, -320, -810}, + {-2160, -316, -814}, + {-2160, -312, -816}, + {-2160, -200, -816}, + {-2174, -334, -676}, + {-2186, -346, -700}, + {-2192, -352, -724}, + {-2192, -352, -748}, + {-2186, -346, -772}, + {-2174, -334, -796}, + {-2160, -319.998993, -810}, + {-2160, -319.998993, -661.999023}, + {-2174, -178, -796}, + {-2186, -166, -772}, + {-2192, -160, -748}, + {-2192, -160, -724}, + {-2186, -166, -700}, + {-2174, -178, -676}, + {-2160, -192, -662}, + {-2160, -192, -810}, + {-2224, -320, -810}, + {-2224, -330, -800}, + {-2224, -320, -800}, + {-2224, -200, -816}, + {-2224, -312, -816}, + {-2224, -316, -814}, + {-2224, -320, -810}, + {-2224, -320, -800}, + {-2224, -192, -800}, + {-2224, -192, -810}, + {-2224, -196, -814}, + {-2224, -192, -800}, + {-2224, -182, -800}, + {-2224, -192, -810}, + {-2224, -330, -800}, + {-2224, -334, -796}, + {-2224, -178, -796}, + {-2224, -182, -800}, + {-2224, -334, -796}, + {-2224, -346, -772}, + {-2224, -351, -752}, + {-2224, -161, -752}, + {-2224, -166, -772}, + {-2224, -178, -796}, + {-2224, -351, -752}, + {-2224, -352, -748}, + {-2224, -352, -724}, + {-2224, -351, -720}, + {-2224, -161, -720}, + {-2224, -160, -724}, + {-2224, -160, -748}, + {-2224, -161, -752}, + {-2224, -351, -720}, + {-2224, -346, -700}, + {-2224, -334, -676}, + {-2224, -316, -658}, + {-2224, -292, -646}, + {-2224, -268, -640}, + {-2224, -244, -640}, + {-2224, -220, -646}, + {-2224, -196, -658}, + {-2224, -178, -676}, + {-2224, -166, -700}, + {-2224, -161, -720}, +}; + +// random numbers dug this up. needed more than 6 iterations +const vec3_t cloud_points[] = { + {1.70695281, 2.60889673, 2.86233163}, + {2.11825109, 2.59883952, 1.48193693}, + {2.76728868, 1.57646465, 2.39769602}, + {1.88795376, 2.73980999, 1.58031297}, + {2.79736757, 1.89582968, 1.80514407}, +}; struct { const vec3_t *points; @@ -38,9 +186,24 @@ struct { {points, 2, {{ 0, 0, 1}, 1.41421356}}, {points, 3, {{-0.333333343, 0.333333343, 0.333333343}, 1.63299322}}, {points, 4, {{0, 0, 0}, 1.73205081}}, - {tears_triangle, 3, {{2201.84521, -1262, -713.519531}, 0.0747000724}}, + {tears_triangle, SIZEOF (tears_triangle), + {{2201.84521, -1262, -713.519531}, 0.0747000724}},//FIXME numbers? + {tears_cluster, SIZEOF (tears_cluster), + {{552.678101, -443.460876, 2800.40405}, 8.04672813}},//FIXME numbers? + {tears_quad, SIZEOF (tears_quad), + {{1792.005, 1092.92999, 240}, 62.6000302}}, + {tears_triangle2, SIZEOF (tears_triangle2), + {{-519.995972, 1111.97498, -2592.03516}, 0.0300767105}},//FIXME numbers? + {tears_quad2, SIZEOF (tears_quad2), + {{121.384659, 3248, 3200}, 182.790497}}, + {tears_triangle3, SIZEOF (tears_triangle3), + {{284.117493, 624.235535, 2959.76489}, 0.352925777}}, + {tears_cluster2, SIZEOF (tears_cluster2), + {{-2192, -256.000031, -736}, 103.479492}},//FIXME numbers? + {cloud_points, SIZEOF (cloud_points), + {{2.20056152, 2.23369908, 2.2332375}, 0.88327992}}, }; -#define num_tests (sizeof (tests) / sizeof (tests[0])) +#define num_tests SIZEOF (tests) static inline float rnd (mtstate_t *mt) diff --git a/libs/util/test/test-sebvf.c b/libs/util/test/test-sebvf.c index ef811e364..9b0d93a7f 100644 --- a/libs/util/test/test-sebvf.c +++ b/libs/util/test/test-sebvf.c @@ -7,6 +7,8 @@ #include "QF/sys.h" #include "QF/simd/vec4f.h" +#define SIZEOF(x) (sizeof(x) / sizeof(x[0])) + const vec4f_t points[] = { {-1, -1, 1, 1}, { 1, 1, 1, 1}, @@ -25,23 +27,186 @@ const vec4f_t points[] = { // due to qfbsp not culling the portal for being too small. const vec4f_t tears_triangle[] = { {2201.82007, -1262, -713.450012, 1}, - {2201.8501, -1262, -713.593994, 1}, + {2201.8501, -1262, -713.593994, 1}, {2201.84009, -1262, -713.445007, 1}, }; +const vec4f_t tears_triangle2[] = { + {-519.989014, 1111.94995, -2592.05005, 1}, + {-520.002991, 1112, -2592.02002, 1}, + {-520.005005, 1112, -2592.04004, 1}, +}; +const vec4f_t tears_triangle3[] = { + {284, 624, 2959.76001, 1}, + {284, 624, 2960, 1}, + {284.234985, 624.471008, 2959.53003, 1}, +}; + +const vec4f_t tears_quad[] = { + {1792, 1155.53003, 240, 1}, + {1792, 1030.32996, 240, 1}, + {1792.01001, 1030.32996, 240, 1}, + {1792.01001, 1155.53003, 240, 1}, +}; + +const vec4f_t tears_quad2[] = { + {304, 3248, 3208, 1}, + {-61.2307014, 3248, 3208, 1}, + {-61.2307014, 3248, 3192, 1}, + {304, 3248, 3192, 1}, +}; + +const vec4f_t tears_cluster[] = { + {551.638, -439.277008, 2804.63989, 1}, + {551, -438, 2806.02002, 1}, + {555.999023, -447.998993, 2805.1499, 1}, + {555.999023, -447.998993, 2804.32007, 1}, + {551.638, -439.277008, 2804.63989, 1}, + {555.999023, -447.998993, 2804.32007, 1}, + {555.999023, -447.998993, 2795.19995, 1}, + {550.97699, -437.954987, 2806.02002, 1}, + {551, -438, 2806.02002, 1}, + {555.999023, -447.998993, 2795.19995, 1}, + {555.999023, -447.998993, 2794.6499, 1}, + {550.978027, -437.954987, 2806.02002, 1}, + {545.945984, -442.945007, 2804.78003, 1}, + {546, -442.998993, 2804.77002, 1}, + {546, -443, 2804.69995, 1}, + {546, -443, 2804.78003, 1}, + {545.945007, -442.945007, 2804.78003, 1}, + {556, -448, 2794.6499, 1}, + {556, -448, 2805.1499, 1}, + {546, -443, 2804.78003, 1}, + {546, -443, 2804.69995, 1}, + {550.97699, -437.954987, 2806.02002, 1}, + {556, -448, 2794.6499, 1}, + {546.000977, -443, 2804.69995, 1}, + {545.945007, -442.945007, 2804.78003, 1}, +}; + +const vec4f_t tears_cluster2[] = { + {-2160, -192, -704.242004, 1}, + {-2160, -192, -662, 1}, + {-2160, -196, -658, 1}, + {-2160, -220, -646, 1}, + {-2160, -222.332001, -645.416992, 1}, + {-2160, -320, -752, 1}, + {-2160, -192, -752, 1}, + {-2160, -192, -704.242004, 1}, + {-2160, -222.332001, -645.416992, 1}, + {-2160, -244, -640, 1}, + {-2160, -268, -640, 1}, + {-2160, -292, -646, 1}, + {-2160, -316, -658, 1}, + {-2160, -320, -662, 1}, + {-2160, -196, -814, 1}, + {-2160, -192, -810, 1}, + {-2160, -192, -752, 1}, + {-2160, -320, -752, 1}, + {-2160, -320, -810, 1}, + {-2160, -316, -814, 1}, + {-2160, -312, -816, 1}, + {-2160, -200, -816, 1}, + {-2174, -334, -676, 1}, + {-2186, -346, -700, 1}, + {-2192, -352, -724, 1}, + {-2192, -352, -748, 1}, + {-2186, -346, -772, 1}, + {-2174, -334, -796, 1}, + {-2160, -319.998993, -810, 1}, + {-2160, -319.998993, -661.999023, 1}, + {-2174, -178, -796, 1}, + {-2186, -166, -772, 1}, + {-2192, -160, -748, 1}, + {-2192, -160, -724, 1}, + {-2186, -166, -700, 1}, + {-2174, -178, -676, 1}, + {-2160, -192, -662, 1}, + {-2160, -192, -810, 1}, + {-2224, -320, -810, 1}, + {-2224, -330, -800, 1}, + {-2224, -320, -800, 1}, + {-2224, -200, -816, 1}, + {-2224, -312, -816, 1}, + {-2224, -316, -814, 1}, + {-2224, -320, -810, 1}, + {-2224, -320, -800, 1}, + {-2224, -192, -800, 1}, + {-2224, -192, -810, 1}, + {-2224, -196, -814, 1}, + {-2224, -192, -800, 1}, + {-2224, -182, -800, 1}, + {-2224, -192, -810, 1}, + {-2224, -330, -800, 1}, + {-2224, -334, -796, 1}, + {-2224, -178, -796, 1}, + {-2224, -182, -800, 1}, + {-2224, -334, -796, 1}, + {-2224, -346, -772, 1}, + {-2224, -351, -752, 1}, + {-2224, -161, -752, 1}, + {-2224, -166, -772, 1}, + {-2224, -178, -796, 1}, + {-2224, -351, -752, 1}, + {-2224, -352, -748, 1}, + {-2224, -352, -724, 1}, + {-2224, -351, -720, 1}, + {-2224, -161, -720, 1}, + {-2224, -160, -724, 1}, + {-2224, -160, -748, 1}, + {-2224, -161, -752, 1}, + {-2224, -351, -720, 1}, + {-2224, -346, -700, 1}, + {-2224, -334, -676, 1}, + {-2224, -316, -658, 1}, + {-2224, -292, -646, 1}, + {-2224, -268, -640, 1}, + {-2224, -244, -640, 1}, + {-2224, -220, -646, 1}, + {-2224, -196, -658, 1}, + {-2224, -178, -676, 1}, + {-2224, -166, -700, 1}, + {-2224, -161, -720, 1}, +}; + +// random numbers dug this up. needed more than 6 iterations +const vec4f_t cloud_points[] = { + {1.70695281, 2.60889673, 2.86233163, 1}, + {2.11825109, 2.59883952, 1.48193693, 1}, + {2.76728868, 1.57646465, 2.39769602, 1}, + {1.88795376, 2.73980999, 1.58031297, 1}, + {2.79736757, 1.89582968, 1.80514407, 1}, +}; struct { const vec4f_t *points; int num_points; vspheref_t expect; } tests[] = { +#if 0 {0, 0, {{ 0, 0, 0, 1}, 0}}, {points, 1, {{-1, -1, 1, 1}, 0}}, {points, 2, {{ 0, 0, 1, 1}, 1.41421356}}, {points, 3, {{-0.333333343, 0.333333343, 0.333333343, 1}, 1.63299322}}, {points, 4, {{0, 0, 0, 1}, 1.73205081}}, - {tears_triangle, 3, {{2201.84521, -1262, -713.519531}, 0.0747000724}}, + {tears_triangle, SIZEOF (tears_triangle), + {{2201.84521, -1262, -713.519531}, 0.0747000724}},//FIXME numbers? + {tears_cluster, SIZEOF (tears_cluster), + {{552.678101, -443.460876, 2800.40405}, 8.04672813}},//FIXME numbers? + {tears_quad, SIZEOF (tears_quad), + {{1792.005, 1092.92999, 240}, 62.6000302}}, + {tears_triangle2, SIZEOF (tears_triangle2), + {{-519.995972, 1111.97498, -2592.03516}, 0.0300767105}},//FIXME numbers? + {tears_quad2, SIZEOF (tears_quad2), + {{121.384659, 3248, 3200}, 182.790497}}, + {tears_triangle3, SIZEOF (tears_triangle3), + {{284.117493, 624.235535, 2959.76489}, 0.352925777}}, + {tears_cluster2, SIZEOF (tears_cluster2), + {{-2192, -256.000031, -736}, 103.479492}},//FIXME numbers? +#endif + {cloud_points, SIZEOF (cloud_points), + {{2.20056152, 2.23369908, 2.2332375}, 0.88327992}}, }; -#define num_tests (sizeof (tests) / sizeof (tests[0])) +#define num_tests SIZEOF (tests) static inline float rnd (mtstate_t *mt) @@ -92,6 +257,7 @@ main (int argc, const char **argv) for (j = 0; j < 5; j++) { VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), cloud[j]); + cloud[j][3] = 1; } seb = SmallestEnclosingBall_vf (cloud, 5); r2 = seb.radius * seb.radius; From ca8dcf3fa98769c1d4536becdf26704df3635484 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 30 Jul 2021 18:52:47 +0900 Subject: [PATCH 1706/3664] [qfvis] Use cluster sphere culling for base vis While this doesn't give as much of a boost as does basic sphere culling (since it's just culling sphere tests), it took ad_tears' base vis from 1000s to 720s on my machine. --- tools/qfvis/include/vis.h | 2 + tools/qfvis/source/base-vis.c | 175 ++++++++++++++++++++++------------ tools/qfvis/source/qfvis.c | 41 ++++++-- 3 files changed, 153 insertions(+), 65 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index d3c9ead53..3455b8a78 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -126,6 +126,7 @@ typedef struct passage_s { typedef struct cluster_s { int numportals; int visofs; + vspheref_t sphere; passage_t *passages; portal_t *portals; } cluster_t; @@ -181,6 +182,7 @@ typedef struct threaddata_s { typedef struct { set_t *portalsee; + unsigned clustercull; ///< number of portals culled by cluster sphere unsigned spherecull; ///< number of portals culled by sphere tests unsigned windingcull; ///< number of portals culled by winding tests int clustersee; diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index a0b0300b7..004db52af 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -103,75 +103,132 @@ test_sphere (const vspheref_t *sphere, vec4f_t plane) #endif } +static int __attribute__ ((pure)) +test_winding_front (const winding_t *winding, vec4f_t plane) +{ + for (unsigned i = 0; i < winding->numpoints; i++) { + vec4f_t d = dotf (winding->points[i], plane); + if (d[0] > ON_EPSILON) + return 1; + } + return 0; +} + +static int __attribute__ ((pure)) +test_winding_back (const winding_t *winding, vec4f_t plane) +{ + for (unsigned i = 0; i < winding->numpoints; i++) { + vec4f_t d = dotf (winding->points[i], plane); + if (d[0] < -ON_EPSILON) + return 1; + } + return 0; +} + void PortalBase (basethread_t *thread, portal_t *portal) { - unsigned i, j, k; - vec4f_t d; portal_t *tp; - winding_t *winding; + cluster_t *cluster; int tp_side, portal_side; - i = portal - portals; + for (cluster = clusters; cluster - clusters < portalclusters; cluster++) { + int side = test_sphere (&cluster->sphere, portal->plane); - for (j = 0, tp = portals; j < numportals * 2; j++, tp++) { - if (j == i) - continue; - - // If the target portal is behind the portals's plane, then it - // can't possibly be seen by the portal. - // - // If the portal is in front of the target's plane, then the target - // is of no interest as it is facing counter to the flow of - // visibility. - - // First check using the bounding spheres of the two portals. - tp_side = test_sphere (&tp->sphere, portal->plane); - if (tp_side < 0) { - // The test portal definitely is entirely behind the portal's - // plane. - thread->spherecull++; - continue; // entirely behind - } - portal_side = test_sphere (&portal->sphere, tp->plane); - if (portal_side > 0) { - // The portal definitely is entirely in front of the test - // portal's plane. - thread->spherecull++; - continue; // entirely in front - } - - if (tp_side == 0) { - // The test portal's sphere touches the portal's plane, so - // do a more refined check. - winding = tp->winding; - for (k = 0; k < winding->numpoints; k++) { - d = dotf (winding->points[k], portal->plane); - if (d[0] > ON_EPSILON) - break; + if (side < 0) { + // The cluster is entirely behind the portal's plane, thus every + // portal in the cluster is also behind the portal's plane and + // cannot be seen at all. + thread->clustercull += cluster->numportals; + } else if (side > 0) { + // The cluster is entirely in front of the portal's plane, thus + // every portal in the cluster is also in front of the portal's + // plane and may be seen. However, as portals are one-way (ie, + // can see out the portal along its plane normal, but not into + // the portal against its plane normal), for a cluster's portal + // to be considered visible, the current portal must be behind + // the cluster's portal, or straddle its plane. + for (int i = 0; i < cluster->numportals; i++) { + tp = cluster->portals + i; + if (tp == portal) { + continue; + } + portal_side = test_sphere (&portal->sphere, tp->plane); + if (portal_side > 0) { + // The portal definitely is entirely in front of the test + // portal's plane. (cannot see into a portal from its + // front side) + thread->spherecull++; + } else if (portal_side < 0) { + // The portal's sphere is behind the test portal's plane, + // so the portal itself is entirely behind the plane + // thus the test portal is potentially visible. + set_add (thread->portalsee, tp - portals); + } else { + // The portal's sphere straddle's the test portal's + // plane, so need to do a more refined check. + if (test_winding_back (portal->winding, tp->plane)) { + // The portal is at least partially behind the test + // portal's plane, so the test portal is potentially + // visible. + set_add (thread->portalsee, tp - portals); + } else { + thread->windingcull++; + } + } } - if (k == winding->numpoints) { - thread->windingcull++; - continue; // no points on front + } else { + // The cluster's sphere straddle's the portal's plane, thus each + // portal in the cluster must be tested individually. + for (int i = 0; i < cluster->numportals; i++) { + tp = cluster->portals + i; + if (tp == portal) { + continue; + } + // If the target portal is behind the portals's plane, then + // it can't possibly be seen by the portal. + // + // If the portal is in front of the target's plane, then the + // target is of no interest as it is facing counter to the + // flow of visibility. + + // First check using the bounding spheres of the two portals. + tp_side = test_sphere (&tp->sphere, portal->plane); + if (tp_side < 0) { + // The test portal definitely is entirely behind the + // portal's plane. + thread->spherecull++; + continue; // entirely behind + } + portal_side = test_sphere (&portal->sphere, tp->plane); + if (portal_side > 0) { + // The portal definitely is entirely in front of the + // test portal's plane. (cannot see into a portal from + // its front side) + thread->spherecull++; + continue; // entirely in front + } + + if (tp_side == 0) { + // The test portal's sphere touches the portal's plane, + // so do a more refined check. + if (!test_winding_front (tp->winding, portal->plane)) { + thread->windingcull++; + continue; + } + } + if (portal_side == 0) { + // The portal's sphere touches the test portal's plane, + // so do a more refined check. + if (!test_winding_back (portal->winding, tp->plane)) { + thread->windingcull++; + continue; + } + } + + set_add (thread->portalsee, tp - portals); } } - - if (portal_side == 0) { - // The portal's sphere touches the test portal's plane, so - // do a more refined check. - winding = portal->winding; - for (k = 0; k < winding->numpoints; k++) { - d = dotf (winding->points[k], tp->plane); - if (d[0] < -ON_EPSILON) - break; - } - if (k == winding->numpoints) { - thread->windingcull++; - continue; // no points on front - } - } - - set_add (thread->portalsee, j); } SimpleFlood (thread, portal, portal->cluster); diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 8c44581fe..1ec5f151c 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -75,9 +75,10 @@ options_t options; static threaddata_t main_thread; static visstat_t global_stats; -int base_mightsee; -unsigned base_spherecull; -unsigned base_windingcull; +unsigned long base_mightsee; +unsigned long base_clustercull; +unsigned long base_spherecull; +unsigned long base_windingcull; static unsigned portal_count; unsigned numportals; @@ -635,6 +636,7 @@ BaseVisThread (void *_thread) } while (1); WRLOCK (stats_lock); + base_clustercull += data.clustercull; base_spherecull += data.spherecull; base_windingcull += data.windingcull; base_mightsee += num_mightsee; @@ -896,9 +898,10 @@ BasePortalVis (void) end = Sys_DoubleTime (); if (options.verbosity >= 1) { - printf ("base_mightsee: %d %gs\n", base_mightsee, end - start); - printf ("sphere cull: %u winding cull %u\n", - base_spherecull, base_windingcull); + printf ("base_mightsee: %lu %gs\n", base_mightsee, end - start); + printf ("cluster cull: %lu\n", base_clustercull); + printf (" sphere cull: %lu\n", base_spherecull); + printf ("winding cull: %lu\n", base_windingcull); } } @@ -978,6 +981,31 @@ CalcVis (void) if (options.verbosity >= 0) printf ("average clusters visible: %u\n", totalvis / portalclusters); } + +static void +CalcClusterSphers (void) +{ + memhunk_t *hunk = main_thread.hunk; + + for (unsigned i = 0; i < portalclusters; i++) { + cluster_t *cluster = &clusters[i]; + int vertcount = 0; + for (int j = 0; j < cluster->numportals; j++) { + vertcount += cluster->portals[j].winding->numpoints; + } + size_t mark = Hunk_LowMark (hunk); + vec4f_t *verts = Hunk_RawAlloc (hunk, vertcount * sizeof (vec4f_t)); + vertcount = 0; + for (int j = 0; j < cluster->numportals; j++) { + memcpy (verts + vertcount, cluster->portals[j].winding->points, + cluster->portals[j].winding->numpoints * sizeof (vec4f_t)); + vertcount += cluster->portals[j].winding->numpoints; + } + cluster->sphere = SmallestEnclosingBall_vf (verts, vertcount); + Hunk_RawFreeToLowMark (hunk, mark); + } +} + #if 0 static qboolean PlaneCompare (plane_t *p1, plane_t *p2) @@ -1388,6 +1416,7 @@ generate_pvs (void) uncompressed = calloc (bitbytes_l, portalclusters); + CalcClusterSphers (); CalcVis (); if (options.verbosity >= 1) From 523ab007d687d9cb6324194cc9591c3ca104a8a1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 30 Jul 2021 23:07:12 +0900 Subject: [PATCH 1707/3664] [qfvis] Produce more details base-vis stats And nicely, things add up (after fixing 32-bit overflows :P) --- tools/qfvis/include/vis.h | 40 ++++++++++++++++++++--------------- tools/qfvis/source/base-vis.c | 23 +++++++++++++++++--- tools/qfvis/source/qfvis.c | 31 ++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 25 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 3455b8a78..be5f4c702 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -143,19 +143,19 @@ typedef struct pstack_s { } pstack_t; typedef struct { - int portaltest; ///< number of portals tested via separators - int portalpass; ///< number of portals through which vis passes - int portalcheck; ///< number of portal checks - int targettested; ///< number of times target portal tested - int targettrimmed; ///< number of times target portal trimmed - int targetclipped; ///< number of times target portal clipped away - int sourcetested; ///< number of times source portal tested - int sourcetrimmed; ///< number of times source portal trimmed - int sourceclipped; ///< number of times source portal clipped away - int chains; ///< number of visits to clusters - int mighttest; ///< amount mightsee is used for masked tests - int vistest; ///< amount visbits is used for masked tests - int mightseeupdate; ///< amount of updates to waiting portals + unsigned long portaltest; ///< number of portals tested via separators + unsigned long portalpass; ///< number of portals through which vis passes + unsigned long portalcheck; ///< number of portal checks + unsigned long targettested; ///< number of times target portal tested + unsigned long targettrimmed;///< number of times target portal trimmed + unsigned long targetclipped;///< number of times target portal clipped away + unsigned long sourcetested; ///< number of times source portal tested + unsigned long sourcetrimmed;///< number of times source portal trimmed + unsigned long sourceclipped;///< number of times source portal clipped away + unsigned long chains; ///< number of visits to clusters + unsigned long mighttest; ///< amount mightsee is used for masked tests + unsigned long vistest; ///< amount visbits is used for masked tests + unsigned long mightseeupdate;///< amount of updates to waiting portals unsigned sep_alloc; ///< how many separators were allocated unsigned sep_free; ///< how many separators were freed unsigned sep_highwater; ///< most separators in flight @@ -182,10 +182,16 @@ typedef struct threaddata_s { typedef struct { set_t *portalsee; - unsigned clustercull; ///< number of portals culled by cluster sphere - unsigned spherecull; ///< number of portals culled by sphere tests - unsigned windingcull; ///< number of portals culled by winding tests - int clustersee; + unsigned long selfcull; ///< number of protals culled by self + unsigned long clustercull; ///< number of portals culled by cluster sphere + unsigned long clustertest; ///< number of portals tested by cluster + unsigned long spheretest; ///< number of portal sphere tests done + unsigned long spherecull; ///< number of portals culled by sphere tests + unsigned long spherepass; ///< number of portals passed by sphere tests + unsigned long windingtest; ///< number of portal pairs tested by winding + unsigned long windingcull; ///< number of portals culled by winding tests + unsigned long windingpass; ///< number of portals passed by winding tests + unsigned long clustersee; int id; } basethread_t; diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index 004db52af..b87b6481f 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -136,6 +136,7 @@ PortalBase (basethread_t *thread, portal_t *portal) int side = test_sphere (&cluster->sphere, portal->plane); if (side < 0) { + thread->clustertest += cluster->numportals; // The cluster is entirely behind the portal's plane, thus every // portal in the cluster is also behind the portal's plane and // cannot be seen at all. @@ -145,14 +146,17 @@ PortalBase (basethread_t *thread, portal_t *portal) // every portal in the cluster is also in front of the portal's // plane and may be seen. However, as portals are one-way (ie, // can see out the portal along its plane normal, but not into - // the portal against its plane normal), for a cluster's portal - // to be considered visible, the current portal must be behind - // the cluster's portal, or straddle its plane. + // the portal against its plane normal), the current portal + // must be behind the cluster's portal, or straddle its plane, + // for a cluster's portal to be considered visible. + thread->clustertest += cluster->numportals; for (int i = 0; i < cluster->numportals; i++) { tp = cluster->portals + i; if (tp == portal) { + thread->selfcull++; continue; } + thread->spheretest++; portal_side = test_sphere (&portal->sphere, tp->plane); if (portal_side > 0) { // The portal definitely is entirely in front of the test @@ -163,14 +167,17 @@ PortalBase (basethread_t *thread, portal_t *portal) // The portal's sphere is behind the test portal's plane, // so the portal itself is entirely behind the plane // thus the test portal is potentially visible. + thread->spherepass++; set_add (thread->portalsee, tp - portals); } else { // The portal's sphere straddle's the test portal's // plane, so need to do a more refined check. + thread->windingtest++; if (test_winding_back (portal->winding, tp->plane)) { // The portal is at least partially behind the test // portal's plane, so the test portal is potentially // visible. + thread->windingpass++; set_add (thread->portalsee, tp - portals); } else { thread->windingcull++; @@ -178,13 +185,16 @@ PortalBase (basethread_t *thread, portal_t *portal) } } } else { + thread->clustertest += cluster->numportals; // The cluster's sphere straddle's the portal's plane, thus each // portal in the cluster must be tested individually. for (int i = 0; i < cluster->numportals; i++) { tp = cluster->portals + i; if (tp == portal) { + thread->selfcull++; continue; } + thread->spheretest++; // If the target portal is behind the portals's plane, then // it can't possibly be seen by the portal. // @@ -208,7 +218,13 @@ PortalBase (basethread_t *thread, portal_t *portal) thread->spherecull++; continue; // entirely in front } + if (tp_side > 0 && portal_side < 0) { + thread->spherepass++; + set_add (thread->portalsee, tp - portals); + continue; + } + thread->windingtest++; if (tp_side == 0) { // The test portal's sphere touches the portal's plane, // so do a more refined check. @@ -226,6 +242,7 @@ PortalBase (basethread_t *thread, portal_t *portal) } } + thread->windingpass++; set_add (thread->portalsee, tp - portals); } } diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 1ec5f151c..a6d0ef2df 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -76,9 +76,15 @@ options_t options; static threaddata_t main_thread; static visstat_t global_stats; unsigned long base_mightsee; +unsigned long base_selfcull; unsigned long base_clustercull; +unsigned long base_clustertest; unsigned long base_spherecull; +unsigned long base_spheretest; +unsigned long base_spherepass; unsigned long base_windingcull; +unsigned long base_windingtest; +unsigned long base_windingpass; static unsigned portal_count; unsigned numportals; @@ -636,9 +642,15 @@ BaseVisThread (void *_thread) } while (1); WRLOCK (stats_lock); + base_selfcull += data.selfcull; base_clustercull += data.clustercull; + base_clustertest += data.clustertest; base_spherecull += data.spherecull; + base_spheretest += data.spheretest; + base_spherepass += data.spherepass; base_windingcull += data.windingcull; + base_windingtest += data.windingtest; + base_windingpass += data.windingpass; base_mightsee += num_mightsee; UNLOCK (stats_lock); @@ -898,10 +910,19 @@ BasePortalVis (void) end = Sys_DoubleTime (); if (options.verbosity >= 1) { + unsigned long n = numportals; printf ("base_mightsee: %lu %gs\n", base_mightsee, end - start); + printf ("\n"); + printf (" total tests: %lu\n", n * n * 4); + printf ("cluster test: %lu\n", base_clustertest); printf ("cluster cull: %lu\n", base_clustercull); + printf (" self cull: %lu\n", base_selfcull); + printf (" sphere test: %lu\n", base_spheretest); printf (" sphere cull: %lu\n", base_spherecull); + printf (" sphere pass: %lu\n", base_spherepass); + printf ("winding test: %lu\n", base_windingtest); printf ("winding cull: %lu\n", base_windingcull); + printf ("winding pass: %lu\n", base_windingpass); } } @@ -935,16 +956,16 @@ CalcPortalVis (void) RunThreads (LeafThread, print_progress); if (options.verbosity >= 1) { - printf ("portalcheck: %i portaltest: %i portalpass: %i\n", + printf ("portalcheck: %ld portaltest: %ld portalpass: %ld\n", global_stats.portalcheck, global_stats.portaltest, global_stats.portalpass); - printf ("target trimmed: %d clipped: %d tested: %d\n", + printf ("target trimmed: %ld clipped: %ld tested: %ld\n", global_stats.targettrimmed, global_stats.targetclipped, global_stats.targettested); - printf ("source trimmed: %d clipped: %d tested: %d\n", + printf ("source trimmed: %ld clipped: %ld tested: %ld\n", global_stats.sourcetrimmed, global_stats.sourceclipped, global_stats.sourcetested); - printf ("vistest: %i mighttest: %i mightseeupdate: %i\n", + printf ("vistest: %ld mighttest: %ld mightseeupdate: %ld\n", global_stats.vistest, global_stats.mighttest, global_stats.mightseeupdate); if (options.verbosity >= 2) { @@ -1420,7 +1441,7 @@ generate_pvs (void) CalcVis (); if (options.verbosity >= 1) - printf ("chains: %i%s\n", global_stats.chains, + printf ("chains: %ld%s\n", global_stats.chains, options.threads > 1 ? " (not reliable)" :""); BSP_AddVisibility (bsp, (byte *) visdata->str, visdata->size); From 80a89c5e1e370c3f008233b58d62280d67f17791 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Aug 2021 14:07:24 +0900 Subject: [PATCH 1708/3664] [util] Write the correct bsp format id for bsp2 Oops :P --- libs/util/bspfile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/util/bspfile.c b/libs/util/bspfile.c index 25263ce04..b70bb732b 100644 --- a/libs/util/bspfile.c +++ b/libs/util/bspfile.c @@ -810,7 +810,8 @@ do { \ } \ } while (0) - tbsp->header->version = BSPVERSION; + memcpy (&tbsp->header->version, BSP2VERSION, + sizeof (tbsp->header->version)); data = (byte *) &tbsp->header[1]; SET_LUMP (LUMP_PLANES, planes); From e671b3f230181ed66f70acc149fcfb1dadc40682 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Aug 2021 17:06:13 +0900 Subject: [PATCH 1709/3664] [qfvis] Thread the portal vis compaction The compaction deals with merging all the portal visibility into cluster visibility, expanding out to leafs, and final compression. --- tools/qfvis/include/vis.h | 3 +- tools/qfvis/source/fatpvs.c | 16 ++--- tools/qfvis/source/qfvis.c | 136 ++++++++++++++++++++++++++---------- 3 files changed, 105 insertions(+), 50 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index be5f4c702..e1ccefe16 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -171,7 +171,6 @@ typedef struct threaddata_s { portal_t *base; ///< portal for which this thread is being run pstack_t pstack_head; sep_t *sep_freelist; ///< per-thread list of free separators - winding_t *winding_freelist; ///< per-thread list of free windings memsuper_t *memsuper; ///< per-thread memory pool memhunk_t *hunk; dstring_t *str; @@ -224,7 +223,7 @@ int CompressRow (struct sizebuf_s *dest, const byte *vis, unsigned num_leafs, void CalcFatPVS (void); -void RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)); +void RunThreads (void *(*thread_func) (void *), int (*calc_progress)(void)); extern const char spinner[]; extern const char progress[]; diff --git a/tools/qfvis/source/fatpvs.c b/tools/qfvis/source/fatpvs.c index c53e08bb5..2ea925fee 100644 --- a/tools/qfvis/source/fatpvs.c +++ b/tools/qfvis/source/fatpvs.c @@ -69,15 +69,9 @@ update_stats (fatstats_t *stats) } static int -print_progress (int prev_prog, int spinner_ind) +leaf_progress (void) { - int prog; - prog = work_leaf * 50 / num_leafs; - if (prog > prev_prog) - printf ("%.*s", prog - prev_prog, progress + prev_prog); - printf (" %c\b\b", spinner[spinner_ind % 4]); - fflush (stdout); - return prog; + return work_leaf * 100 / num_leafs; } static unsigned @@ -258,11 +252,11 @@ CalcFatPVS (void) }; } work_leaf = 0; - RunThreads (decompress_thread, print_progress); + RunThreads (decompress_thread, leaf_progress); work_leaf = 0; - RunThreads (fatten_thread, print_progress); + RunThreads (fatten_thread, leaf_progress); work_leaf = 0; - RunThreads (compress_thread, print_progress); + RunThreads (compress_thread, leaf_progress); printf ("Average leafs visible / fat visible / total: %d / %d / %d\n", (int) (fatstats.pvs_visible / num_leafs), (int) (fatstats.fat_visible / num_leafs), num_leafs); diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index a6d0ef2df..e49569649 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -679,11 +679,15 @@ print_thread_stats (const int *local_work, int thread, int spinner_ind) } static int -print_progress (int prev_prog, int spinner_ind) +portal_progress (void) { - int prog; + return portal_count * 100 / (numportals * 2) + 1; +} - prog = portal_count * 50 / (numportals * 2) + 1; +static int +print_progress (int prev_prog, int prog, int spinner_ind) +{ + prog /= 2; if (prog > prev_prog) printf ("%.*s", prog - prev_prog, progress + prev_prog); printf (" %c\b\b", spinner[spinner_ind % 4]); @@ -693,7 +697,7 @@ print_progress (int prev_prog, int spinner_ind) typedef struct { int thread; - int (*progress)(int, int); + int (*calc_progress)(void); } watch_data_t; static void * @@ -716,16 +720,18 @@ WatchThread (void *_wd) break; if (i == thread) break; - if (count++ == 100) { + if (count++ == 50) { count = 0; for (i = 0; i < thread; i ++) local_work[i] = working[i]; if (options.verbosity >= 4) print_thread_stats (local_work, thread, spinner_ind); - else if (options.verbosity >= 0) - prev_prog = wd->progress (prev_prog, spinner_ind); - if (prev_port != portal_count || stalled++ == 10) { + else if (options.verbosity >= 0) { + prev_prog = print_progress (prev_prog, wd->calc_progress (), + spinner_ind); + } + if (prev_port != portal_count || stalled++ == 20) { prev_port = portal_count; stalled = 0; spinner_ind++; @@ -735,7 +741,8 @@ WatchThread (void *_wd) if (options.verbosity >= 4) { printf ("watch thread done\n"); } else if (options.verbosity >= 0) { - prev_prog = wd->progress (prev_prog, spinner_ind); + prev_prog = print_progress (prev_prog, wd->calc_progress (), + spinner_ind); printf ("\n"); } free (local_work); @@ -745,7 +752,7 @@ WatchThread (void *_wd) #endif void -RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)) +RunThreads (void *(*thread_func) (void *), int (*calc_progress)(void)) { #ifdef USE_PTHREADS pthread_t *work_threads; @@ -760,7 +767,7 @@ RunThreads (void *(*thread_func) (void *), int (*progress)(int, int)) thread_func, (void *) (intptr_t) i) == -1) Sys_Error ("pthread_create failed"); } - watch_data_t wd = { i, progress }; + watch_data_t wd = { i, calc_progress }; if (pthread_create (&work_threads[i], &threads_attrib, WatchThread, &wd) == -1) Sys_Error ("pthread_create failed"); @@ -832,6 +839,8 @@ ClusterFlowExpand (const set_t *src, byte *dest) } } + +static sizebuf_t *compressed_vis; /* ClusterFlow @@ -840,11 +849,8 @@ ClusterFlowExpand (const set_t *src, byte *dest) void ClusterFlow (int clusternum) { - set_t *visclusters; - sizebuf_t compressed = { - .maxsize = (bitbytes_l * 3) / 2, - .data = alloca ((bitbytes_l * 3) / 2) - }; + set_t visclusters = SET_STATIC_INIT (portalclusters, alloca); + sizebuf_t *compressed = &compressed_vis[clusternum]; byte *outbuffer; int numvis, i; @@ -854,37 +860,94 @@ ClusterFlow (int clusternum) outbuffer = uncompressed + clusternum * bitbytes_l; cluster = &clusters[clusternum]; - // flow through all portals, collecting visible bits + set_empty (&visclusters); - memset (compressed.data, 0, compressed.maxsize); - visclusters = set_new (); + // flow through all portals, collecting visible bits for (i = 0; i < cluster->numportals; i++) { portal = &cluster->portals[i]; if (portal->status != stat_done) Sys_Error ("portal not done"); - set_union (visclusters, portal->visbits); + if (set_is_member (portal->visbits, clusternum)) { + //printf ("cluster %d saw into self via portal %d\n", + // clusternum, (int) (portal - portals)); + } + set_union (&visclusters, portal->visbits); } - if (set_is_member (visclusters, clusternum)) - Sys_Error ("Cluster portals saw into cluster"); + set_add (&visclusters, clusternum); - set_add (visclusters, clusternum); - - numvis = set_count (visclusters); + numvis = set_count (&visclusters); // expand to cluster->leaf PVS - ClusterFlowExpand (visclusters, outbuffer); - - set_delete (visclusters); + ClusterFlowExpand (&visclusters, outbuffer); // compress the bit string if (options.verbosity >= 4) printf ("cluster %4i : %4i visible\n", clusternum, numvis); totalvis += numvis; - i = CompressRow (&compressed, outbuffer, numrealleafs, 0); - cluster->visofs = visdata->size; - dstring_append (visdata, (char *) compressed.data, i); + CompressRow (compressed, outbuffer, numrealleafs, 0); +} + +static unsigned work_cluster; + +static int +flow_progress (void) +{ + return work_cluster * 100 / portalclusters; +} + +static unsigned +next_cluster (void) +{ + unsigned cluster = ~0; + WRLOCK (global_lock); + if (work_cluster < portalclusters) { + cluster = work_cluster++; + } + UNLOCK (global_lock); + return cluster; +} + +static void * +FlowClusters (void *d) +{ + int thread = (intptr_t) d; + + while (1) { + unsigned clusternum = next_cluster (); + + if (working) { + working[thread] = clusternum; + } + if (clusternum == ~0u) { + break; + } + ClusterFlow (clusternum); + } + return 0; +} + +static void +CompactPortalVis (void) +{ + if (options.verbosity >= 0) { + printf ("Comp vis: "); + } + compressed_vis = malloc (portalclusters * sizeof (sizebuf_t)); + for (unsigned i = 0; i < portalclusters; i++) { + compressed_vis[i] = (sizebuf_t) { + .maxsize = (bitbytes_l * 3) / 2, + .data = malloc ((bitbytes_l * 3) / 2) + }; + } + RunThreads (FlowClusters, flow_progress); + + for (unsigned i = 0; i < portalclusters; i++) { + unsigned size = compressed_vis[i].cursize; + clusters[i].visofs = visdata->size; + dstring_append (visdata, (char *) compressed_vis[i].data, size); + } } static int @@ -906,7 +969,7 @@ BasePortalVis (void) printf ("\n"); start = Sys_DoubleTime (); - RunThreads (BaseVisThread, print_progress); + RunThreads (BaseVisThread, portal_progress); end = Sys_DoubleTime (); if (options.verbosity >= 1) { @@ -953,7 +1016,7 @@ CalcPortalVis (void) portal_count = 0; - RunThreads (LeafThread, print_progress); + RunThreads (LeafThread, portal_progress); if (options.verbosity >= 1) { printf ("portalcheck: %ld portaltest: %ld portalpass: %ld\n", @@ -993,8 +1056,7 @@ CalcVis (void) CalcPortalVis (); // assemble the leaf vis lists by oring and compressing the portal lists - for (i = 0; i < portalclusters; i++) - ClusterFlow (i); + CompactPortalVis (); for (i = 0; i < numrealleafs; i++) { bsp->leafs[i + 1].visofs = clusters[leafcluster[i]].visofs; @@ -1004,7 +1066,7 @@ CalcVis (void) } static void -CalcClusterSphers (void) +CalcClusterSpheres (void) { memhunk_t *hunk = main_thread.hunk; @@ -1437,7 +1499,7 @@ generate_pvs (void) uncompressed = calloc (bitbytes_l, portalclusters); - CalcClusterSphers (); + CalcClusterSpheres (); CalcVis (); if (options.verbosity >= 1) From 40367e5bca9ee2b82ef1c67ccba884aba6ce1241 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Aug 2021 18:14:28 +0900 Subject: [PATCH 1710/3664] [qfvis] Thread the ambient sounds computation --- tools/qfvis/source/soundphs.c | 229 ++++++++++++++++++++++------------ 1 file changed, 150 insertions(+), 79 deletions(-) diff --git a/tools/qfvis/source/soundphs.c b/tools/qfvis/source/soundphs.c index c4be79315..a74cf5c88 100644 --- a/tools/qfvis/source/soundphs.c +++ b/tools/qfvis/source/soundphs.c @@ -54,6 +54,7 @@ #include "QF/quakefs.h" #include "QF/sys.h" +#include "tools/qfvis/include/options.h" #include "tools/qfvis/include/vis.h" /* @@ -64,6 +65,8 @@ leaf. */ +static byte *surf_ambients; + static void SurfaceBBox (dface_t *s, vec3_t mins, vec3_t maxs) { @@ -90,87 +93,155 @@ SurfaceBBox (dface_t *s, vec3_t mins, vec3_t maxs) } } +static void +init_surf_ambients (void) +{ + surf_ambients = malloc (bsp->numfaces); + if (!bsp->texdata) { + memset (surf_ambients, -1, bsp->numfaces); + return; + } + + dmiptexlump_t *miptex = (dmiptexlump_t *) bsp->texdata; + + for (int i = 0; i < bsp->numfaces; i++) { + dface_t *surf = &bsp->faces[i]; + texinfo_t *info = &bsp->texinfo[surf->texinfo]; + int ofs = miptex->dataofs[info->miptex]; + miptex_t *miptex = (miptex_t *) &bsp->texdata[ofs]; + + if (!strncasecmp (miptex->name, "*water", 6)) + surf_ambients[i] = AMBIENT_WATER; + else if (!strncasecmp (miptex->name, "sky", 3)) + surf_ambients[i] = AMBIENT_SKY; + else if (!strncasecmp (miptex->name, "*slime", 6)) + surf_ambients[i] = AMBIENT_WATER; + else if (!strncasecmp (miptex->name, "*lava", 6)) + surf_ambients[i] = AMBIENT_LAVA; + else if (!strncasecmp (miptex->name, "*04water", 8)) + surf_ambients[i] = AMBIENT_WATER; + else + surf_ambients[i] = -1; + } +} + +static void +LeafAmbients (dleaf_t *leaf, set_t *vis) +{ + float dists[NUM_AMBIENTS]; + + // clear ambients + for (int j = 0; j < NUM_AMBIENTS; j++) { + dists[j] = 1020; + } + + for (unsigned j = 0; j < numrealleafs - 1; j++) { + if (!set_is_member (vis, j)) { + continue; + } + + if (!bsp->texdata) + continue; + + // check this leaf for sound textures + dleaf_t *hit = &bsp->leafs[j + 1]; + + for (uint32_t k = 0; k < hit->nummarksurfaces; k++) { + unsigned surf_index = bsp->marksurfaces[hit->firstmarksurface + k]; + dface_t *surf = &bsp->faces[surf_index]; + + byte ambient_type; + if ((ambient_type = surf_ambients[surf_index]) == 0xff) { + continue; + } + + // find distance from source leaf to polygon + vec3_t mins, maxs; + float maxd = 0; + SurfaceBBox (surf, mins, maxs); + for (int l = 0; l < 3; l++) { + float d = 0; + if (mins[l] > leaf->maxs[l]) + d = mins[l] - leaf->maxs[l]; + else if (maxs[l] < leaf->mins[l]) + d = leaf->mins[l] - mins[l]; + else + d = 0; + if (d > maxd) + maxd = d; + } + + maxd = 0.25; + if (maxd < dists[ambient_type]) + dists[ambient_type] = maxd; + } + } + + for (int j = 0; j < NUM_AMBIENTS; j++) { + float vol = 0; + + if (dists[j] < 100) + vol = 1.0; + else { + vol = 1.0 - dists[2] * 0.002; + if (vol < 0) + vol = 0; + } + leaf->ambient_level[j] = vol * 255; + } +} + +// vis is 1-based, but bsp leafs are 0-based +static unsigned work_leaf = 1; + +static int +ambient_progress (void) +{ + return (work_leaf - 1) * 100 / (numrealleafs - 1); +} + +static unsigned +next_leaf (void) +{ + unsigned leaf = ~0; + WRLOCK (global_lock); + if (work_leaf < numrealleafs) { + leaf = work_leaf++; + } + UNLOCK (global_lock); + return leaf; +} + +static void * +AmbientThread (void *d) +{ + int thread = (intptr_t) d; + set_t vis = {}; + + vis.size = SET_SIZE (numrealleafs - 1); + + while (1) { + unsigned leaf_num = next_leaf (); + + if (working) + working[thread] = leaf_num; + if (leaf_num == ~0u) { + break; + } + + unsigned cluster_num = leafcluster[leaf_num]; + vis.map = (set_bits_t *) &uncompressed[cluster_num * bitbytes_l]; + LeafAmbients (&bsp->leafs[leaf_num], &vis); + } + return 0; +} + void CalcAmbientSounds (void) { - byte *vis; - unsigned i, j, k; - int ambient_type, ofs, l; - float maxd, vol, d; - float dists[NUM_AMBIENTS]; - dface_t *surf; - dleaf_t *leaf, *hit; - vec3_t mins, maxs; - texinfo_t *info; - miptex_t *miptex; - - for (i = 0; i < numrealleafs - 1; i++) { - leaf = &bsp->leafs[i + 1]; - - // clear ambients - for (j = 0; j < NUM_AMBIENTS; j++) - dists[j] = 1020; - - vis = &uncompressed[leafcluster[i] * bitbytes_l]; - - for (j = 0; j < numrealleafs - 1; j++) { - if (!(vis[j >> 3] & (1 << (j & 7)))) - continue; - - if (!bsp->texdata) - continue; - - // check this leaf for sound textures - hit = &bsp->leafs[j + 1]; - - for (k = 0; k < hit->nummarksurfaces; k++) { - surf = &bsp->faces[bsp->marksurfaces[hit->firstmarksurface + k]]; - info = &bsp->texinfo[surf->texinfo]; - ofs = ((dmiptexlump_t *) bsp->texdata)->dataofs[info->miptex]; - miptex = (miptex_t *) (&bsp->texdata[ofs]); - - if (!strncasecmp (miptex->name, "*water", 6)) - ambient_type = AMBIENT_WATER; - else if (!strncasecmp (miptex->name, "sky", 3)) - ambient_type = AMBIENT_SKY; - else if (!strncasecmp (miptex->name, "*slime", 6)) - ambient_type = AMBIENT_WATER; - else if (!strncasecmp (miptex->name, "*lava", 6)) - ambient_type = AMBIENT_LAVA; - else if (!strncasecmp (miptex->name, "*04water", 8)) - ambient_type = AMBIENT_WATER; - else - continue; - - // find distance from source leaf to polygon - SurfaceBBox (surf, mins, maxs); - maxd = 0; - for (l = 0; l < 3; l++) { - if (mins[l] > leaf->maxs[l]) - d = mins[l] - leaf->maxs[l]; - else if (maxs[l] < leaf->mins[l]) - d = leaf->mins[l] - mins[l]; - else - d = 0; - if (d > maxd) - maxd = d; - } - - maxd = 0.25; - if (maxd < dists[ambient_type]) - dists[ambient_type] = maxd; - } - } - - for (j = 0; j < NUM_AMBIENTS; j++) { - if (dists[j] < 100) - vol = 1.0; - else { - vol = 1.0 - dists[2] * 0.002; - if (vol < 0) - vol = 0; - } - leaf->ambient_level[j] = vol * 255; - } + init_surf_ambients (); + if (options.verbosity >= 0) { + printf ("Ambients: "); } + RunThreads (AmbientThread, ambient_progress); } From 674ffa09410383035457afaf4650f07122192fa9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Aug 2021 21:54:05 +0900 Subject: [PATCH 1711/3664] [util] Make bsp_t counts size_t and other bsp data counts unsigned, and clean up the resulting mess. --- include/QF/bspfile.h | 56 ++++---- include/QF/model.h | 70 +++++----- libs/models/brush/glsl_model_brush.c | 5 +- libs/models/brush/model_brush.c | 30 ++--- libs/models/brush/vulkan_model_brush.c | 10 +- libs/util/bspfile.c | 158 +++++++++++------------ libs/video/renderer/gl/gl_lightmap.c | 17 ++- libs/video/renderer/gl/gl_rmisc.c | 5 +- libs/video/renderer/gl/gl_rsurf.c | 10 +- libs/video/renderer/glsl/glsl_bsp.c | 17 +-- libs/video/renderer/glsl/glsl_lightmap.c | 10 +- libs/video/renderer/vulkan/vulkan_bsp.c | 14 +- nq/source/sv_main.c | 13 +- qw/source/sv_init.c | 5 +- tools/bsp2img/bsp2img.c | 20 +-- tools/qfbsp/source/info.c | 2 +- tools/qfbsp/source/map.c | 7 +- tools/qfbsp/source/qfbsp.c | 24 ++-- tools/qfbsp/source/readbsp.c | 47 +++---- tools/qfbsp/source/region.c | 14 +- tools/qfbsp/source/surfaces.c | 6 +- tools/qfbsp/source/writebsp.c | 6 +- tools/qflight/source/ltface.c | 11 +- tools/qflight/source/qflight.c | 13 +- tools/qflight/source/vis.c | 26 ++-- tools/qfvis/source/soundphs.c | 15 +-- 26 files changed, 288 insertions(+), 323 deletions(-) diff --git a/include/QF/bspfile.h b/include/QF/bspfile.h index 27648f297..18586564d 100644 --- a/include/QF/bspfile.h +++ b/include/QF/bspfile.h @@ -52,8 +52,8 @@ #define TOOLVERSION 2 typedef struct lump_s { - int32_t fileofs; - int32_t filelen; + uint32_t fileofs; + uint32_t filelen; } lump_t; #define LUMP_ENTITIES 0 @@ -76,19 +76,19 @@ typedef struct lump_s { typedef struct dmodel_s { float mins[3], maxs[3]; float origin[3]; - int32_t headnode[MAX_MAP_HULLS]; - int32_t visleafs; // not including the solid leaf 0 - int32_t firstface, numfaces; + uint32_t headnode[MAX_MAP_HULLS]; + uint32_t visleafs; // not including the solid leaf 0 + uint32_t firstface, numfaces; } dmodel_t; typedef struct dheader_s { - int32_t version; + uint32_t version; lump_t lumps[HEADER_LUMPS]; } dheader_t; typedef struct dmiptexlump_s { - int32_t nummiptex; - int32_t dataofs[4]; // [nummiptex] + uint32_t nummiptex; + uint32_t dataofs[4]; // [nummiptex] } dmiptexlump_t; #define MIPTEXNAME 16 @@ -138,7 +138,7 @@ typedef struct dplane_s { //BSP2 version (bsp 29 version is in bspfile.c) typedef struct dnode_s { - int32_t planenum; + uint32_t planenum; int32_t children[2]; // negative numbers are -(leafs+1), not nodes float mins[3]; // for sphere culling float maxs[3]; @@ -148,15 +148,15 @@ typedef struct dnode_s { //BSP2 version (bsp 29 version is in bspfile.c) typedef struct dclipnode_s { - int32_t planenum; + uint32_t planenum; int32_t children[2]; // negative numbers are contents } dclipnode_t; typedef struct texinfo_s { float vecs[2][4]; // [s/t][xyz offset] - int32_t miptex; - int32_t flags; + uint32_t miptex; + uint32_t flags; } texinfo_t; #define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision #define TEX_MISSING 2 // this texinfo does not have a texture @@ -171,16 +171,16 @@ typedef struct dedge_s { #define MAXLIGHTMAPS 4 //BSP2 version (bsp 29 version is in bspfile.c) typedef struct dface_s { - int32_t planenum; + uint32_t planenum; int32_t side; - int32_t firstedge; // we must support > 64k edges - int32_t numedges; - int32_t texinfo; + uint32_t firstedge; // we must support > 64k edges + uint32_t numedges; + uint32_t texinfo; // lighting info byte styles[MAXLIGHTMAPS]; - int32_t lightofs; // start of [numstyles*surfsize] samples + uint32_t lightofs; // start of [numstyles*surfsize] samples } dface_t; @@ -214,7 +214,7 @@ typedef struct bsp_s { dheader_t *header; int own_models; - int nummodels; + size_t nummodels; dmodel_t *models; int own_visdata; @@ -234,43 +234,43 @@ typedef struct bsp_s { char *entdata; int own_leafs; - int numleafs; + size_t numleafs; dleaf_t *leafs; int own_planes; - int numplanes; + size_t numplanes; dplane_t *planes; int own_vertexes; - int numvertexes; + size_t numvertexes; dvertex_t *vertexes; int own_nodes; - int numnodes; + size_t numnodes; dnode_t *nodes; int own_texinfo; - int numtexinfo; + size_t numtexinfo; texinfo_t *texinfo; int own_faces; - int numfaces; + size_t numfaces; dface_t *faces; int own_clipnodes; - int numclipnodes; + size_t numclipnodes; dclipnode_t *clipnodes; int own_edges; - int numedges; + size_t numedges; dedge_t *edges; int own_marksurfaces; - int nummarksurfaces; + size_t nummarksurfaces; uint32_t *marksurfaces; int own_surfedges; - int numsurfedges; + size_t numsurfedges; int32_t *surfedges; } bsp_t; diff --git a/include/QF/model.h b/include/QF/model.h index 9cbc322f6..bc0b8ab22 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -206,7 +206,7 @@ typedef struct mleaf_s { } mleaf_t; typedef struct mclipnode_s { - int planenum; + unsigned planenum; int children[2]; } mclipnode_t; @@ -222,57 +222,57 @@ typedef struct hull_s { } hull_t; typedef struct mod_brush_s { - int firstmodelsurface, nummodelsurfaces; + unsigned firstmodelsurface, nummodelsurfaces; - int numsubmodels; - dmodel_t *submodels; + unsigned numsubmodels; + dmodel_t *submodels; - int numplanes; - plane_t *planes; + unsigned numplanes; + plane_t *planes; unsigned modleafs; ///< number of leafs in model, including 0 unsigned visleafs; ///< number of visible leafs, not counting 0 - mleaf_t *leafs; + mleaf_t *leafs; - int numvertexes; - mvertex_t *vertexes; + unsigned numvertexes; + mvertex_t *vertexes; - int numedges; - medge_t *edges; + unsigned numedges; + medge_t *edges; - int numnodes; - mnode_t *nodes; - int depth; ///< maximum depth of the tree + unsigned numnodes; + mnode_t *nodes; + int depth; ///< maximum depth of the tree - int numtexinfo; - mtexinfo_t *texinfo; + unsigned numtexinfo; + mtexinfo_t *texinfo; - int numsurfaces; - msurface_t *surfaces; + unsigned numsurfaces; + msurface_t *surfaces; - int numsurfedges; - int *surfedges; + unsigned numsurfedges; + int *surfedges; - int numclipnodes; - mclipnode_t *clipnodes; + unsigned numclipnodes; + mclipnode_t *clipnodes; - int nummarksurfaces; - msurface_t **marksurfaces; + unsigned nummarksurfaces; + msurface_t **marksurfaces; - hull_t hulls[MAX_MAP_HULLS]; - hull_t *hull_list[MAX_MAP_HULLS]; + hull_t hulls[MAX_MAP_HULLS]; + hull_t *hull_list[MAX_MAP_HULLS]; - int numtextures; - texture_t **textures; - texture_t *skytexture; + unsigned numtextures; + texture_t **textures; + texture_t *skytexture; - byte *visdata; - byte *lightdata; - char *entities; //FIXME should not be here + byte *visdata; + byte *lightdata; + char *entities; //FIXME should not be here - mnode_t **node_parents; - mnode_t **leaf_parents; - int *leaf_flags; // union of surf flags for surfs in leaf + mnode_t **node_parents; + mnode_t **leaf_parents; + int *leaf_flags; // union of surf flags for surfs in leaf unsigned int checksum; unsigned int checksum2; diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index 6d9942ea6..541982f74 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -65,11 +65,10 @@ static glsltex_t glsl_notexture = { }; static void glsl_brush_clear (model_t *m, void *data) { - int i; mod_brush_t *brush = &m->brush; m->needload = true; - for (i = 0; i < brush->numtextures; i++) { + for (unsigned i = 0; i < brush->numtextures; i++) { // NOTE: some maps (eg e1m2) have empty texture slots glsltex_t *tex = 0; if (brush->textures[i]) { @@ -82,7 +81,7 @@ glsl_brush_clear (model_t *m, void *data) tex->gl_texturenum = 0; } } - for (i = 0; i < brush->numsurfaces; i++) { + for (unsigned i = 0; i < brush->numsurfaces; i++) { if (brush->surfaces[i].polys) { free (brush->surfaces[i].polys); brush->surfaces[i].polys = 0; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index f121931c7..cf5552aed 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -247,7 +247,7 @@ static void Mod_LoadTextures (model_t *mod, bsp_t *bsp) { dmiptexlump_t *m; - int i, j, pixels, num, max, altmax; + int pixels, num, max, altmax; miptex_t *mt; texture_t *tx, *tx2; texture_t *anims[10], *altanims[10]; @@ -264,13 +264,13 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) m->nummiptex * sizeof (*brush->textures), mod->name); - for (i = 0; i < m->nummiptex; i++) { - if (m->dataofs[i] == -1) + for (uint32_t i = 0; i < m->nummiptex; i++) { + if (m->dataofs[i] == ~0u) continue; mt = (miptex_t *) ((byte *) m + m->dataofs[i]); mt->width = LittleLong (mt->width); mt->height = LittleLong (mt->height); - for (j = 0; j < MIPLEVELS; j++) + for (int j = 0; j < MIPLEVELS; j++) mt->offsets[j] = LittleLong (mt->offsets[j]); if ((mt->width & 15) || (mt->height & 15)) @@ -284,7 +284,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) mod_unique_miptex_name (brush->textures, tx, i); tx->width = mt->width; tx->height = mt->height; - for (j = 0; j < MIPLEVELS; j++) + for (int j = 0; j < MIPLEVELS; j++) tx->offsets[j] = mt->offsets[j] + sizeof (texture_t) - sizeof (miptex_t); // the pixels immediately follow the structures @@ -300,7 +300,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) render_data = Hunk_AllocName (0, m->nummiptex * render_size, mod->name); } - for (i = 0; i < m->nummiptex; i++) { + for (uint32_t i = 0; i < m->nummiptex; i++) { if (!(tx = brush->textures[i])) { continue; } @@ -313,7 +313,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) } // sequence the animations - for (i = 0; i < m->nummiptex; i++) { + for (uint32_t i = 0; i < m->nummiptex; i++) { tx = brush->textures[i]; if (!tx || tx->name[0] != '+') continue; @@ -340,7 +340,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) } else Sys_Error ("Bad animating texture %s", tx->name); - for (j = i + 1; j < m->nummiptex; j++) { + for (uint32_t j = i + 1; j < m->nummiptex; j++) { tx2 = brush->textures[j]; if (!tx2 || tx2->name[0] != '+') continue; @@ -366,7 +366,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) #define ANIM_CYCLE 2 // link them all together - for (j = 0; j < max; j++) { + for (int j = 0; j < max; j++) { tx2 = anims[j]; if (!tx2) Sys_Error ("Missing frame %i of %s", j, tx->name); @@ -377,7 +377,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) if (altmax) tx2->alternate_anims = altanims[0]; } - for (j = 0; j < altmax; j++) { + for (int j = 0; j < altmax; j++) { tx2 = altanims[j]; if (!tx2) Sys_Error ("Missing frame %i of %s", j, tx->name); @@ -490,7 +490,7 @@ static void Mod_LoadTexinfo (model_t *mod, bsp_t *bsp) { float len1, len2; - int count, miptex, i, j; + unsigned count, miptex, i, j; mtexinfo_t *out; texinfo_t *in; @@ -809,7 +809,7 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) dclipnode_t *in; mclipnode_t *out; hull_t *hull; - int count, i; + int count, i; mod_brush_t *brush = &mod->brush; in = bsp->clipnodes; @@ -853,7 +853,7 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) for (i = 0; i < count; i++, out++, in++) { out->planenum = in->planenum; - if (out->planenum < 0 || out->planenum >= brush->numplanes) + if (out->planenum >= brush->numplanes) Sys_Error ("Mod_LoadClipnodes: planenum out of bounds"); out->children[0] = in->children[0]; out->children[1] = in->children[1]; @@ -913,7 +913,7 @@ Mod_MakeHull0 (model_t *mod) static void Mod_LoadMarksurfaces (model_t *mod, bsp_t *bsp) { - int count, i, j; + unsigned count, i, j; msurface_t **out; uint32_t *in; mod_brush_t *brush = &mod->brush; @@ -1037,7 +1037,7 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) { dmodel_t *bm; - int i, j; + unsigned i, j; bsp_t *bsp; mod->type = mod_brush; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 970ab1f44..5132daf13 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -73,7 +73,7 @@ static void vulkan_brush_clear (model_t *mod, void *data) QFV_DeviceWaitIdle (device); - for (int i = 0; i < brush->numtextures; i++) { + for (unsigned i = 0; i < brush->numtextures; i++) { texture_t *tx = brush->textures[i]; if (!tx) { continue; @@ -173,7 +173,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) size_t image_count = 0; size_t copy_count = 0; size_t memsize = 0; - for (int i = 0; i < brush->numtextures; i++) { + for (unsigned i = 0; i < brush->numtextures; i++) { texture_t *tx = brush->textures[i]; if (!tx) { continue; @@ -210,7 +210,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) qfv_packet_t *packet = QFV_PacketAcquire (stage); buffer = QFV_PacketExtend (packet, memsize); - for (int i = 0; i < brush->numtextures; i++) { + for (unsigned i = 0; i < brush->numtextures; i++) { texture_t *tx = brush->textures[i]; byte *palette = vid.palette32; if (!tx) { @@ -263,7 +263,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) __auto_type barriers = QFV_AllocImageBarrierSet (image_count, malloc); barriers->size = 0; - for (int i = 0; i < brush->numtextures; i++) { + for (unsigned i = 0; i < brush->numtextures; i++) { texture_t *tx = brush->textures[i]; if (!tx) { continue; @@ -281,7 +281,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, barriers->size, barriers->a); - for (int i = 0, j = 0; i < brush->numtextures; i++) { + for (unsigned i = 0, j = 0; i < brush->numtextures; i++) { texture_t *tx = brush->textures[i]; if (!tx) { continue; diff --git a/libs/util/bspfile.c b/libs/util/bspfile.c index b70bb732b..eb1b50784 100644 --- a/libs/util/bspfile.c +++ b/libs/util/bspfile.c @@ -92,7 +92,7 @@ typedef struct bsp29_s { dheader_t *header; int own_models; - int nummodels; + size_t nummodels; dmodel_t *models; int own_visdata; @@ -112,56 +112,55 @@ typedef struct bsp29_s { char *entdata; int own_leafs; - int numleafs; + size_t numleafs; dleaf29_t *leafs; int own_planes; - int numplanes; + size_t numplanes; dplane_t *planes; int own_vertexes; - int numvertexes; + size_t numvertexes; dvertex_t *vertexes; int own_nodes; - int numnodes; + size_t numnodes; dnode29_t *nodes; int own_texinfo; - int numtexinfo; + size_t numtexinfo; texinfo_t *texinfo; int own_faces; - int numfaces; + size_t numfaces; dface29_t *faces; int own_clipnodes; - int numclipnodes; + size_t numclipnodes; dclipnode29_t *clipnodes; int own_edges; - int numedges; + size_t numedges; dedge29_t *edges; int own_marksurfaces; - int nummarksurfaces; + size_t nummarksurfaces; uint16_t *marksurfaces; int own_surfedges; - int numsurfedges; + size_t numsurfedges; int32_t *surfedges; } bsp29_t; static void swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) { - int c, i, j; dmiptexlump_t *mtl; dmodel_t *d; if (bsp29->header) { bsp29->header->version = LittleLong (bsp29->header->version); - for (i = 0; i < HEADER_LUMPS; i++) { + for (int i = 0; i < HEADER_LUMPS; i++) { bsp29->header->lumps[i].fileofs = LittleLong (bsp29->header->lumps[i].fileofs); bsp29->header->lumps[i].filelen = @@ -170,17 +169,17 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) } // models - for (i=0 ; inummodels ; i++) { + for (size_t i=0 ; inummodels ; i++) { d = &bsp29->models[i]; - for (j=0 ; jheadnode[j] = LittleLong (d->headnode[j]); d->visleafs = LittleLong (d->visleafs); d->firstface = LittleLong (d->firstface); d->numfaces = LittleLong (d->numfaces); - for (j=0 ; j<3 ; j++) { + for (int j = 0; j < 3; j++) { d->mins[j] = LittleFloat(d->mins[j]); d->maxs[j] = LittleFloat(d->maxs[j]); d->origin[j] = LittleFloat(d->origin[j]); @@ -188,25 +187,25 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) } // vertexes - for (i=0 ; inumvertexes ; i++) { + for (size_t i = 0; i < bsp29->numvertexes; i++) { dvertex_t *vertex = &bsp29->vertexes[i]; - for (j=0 ; j<3 ; j++) + for (int j = 0; j < 3; j++) vertex->point[j] = LittleFloat (vertex->point[j]); } // planes - for (i=0 ; inumplanes ; i++) { + for (size_t i = 0; i < bsp29->numplanes; i++) { dplane_t *plane = &bsp29->planes[i]; - for (j=0 ; j<3 ; j++) + for (int j = 0; j < 3; j++) plane->normal[j] = LittleFloat (plane->normal[j]); plane->dist = LittleFloat (plane->dist); plane->type = LittleLong (plane->type); } // texinfos - for (i=0 ; inumtexinfo ; i++) { + for (size_t i = 0; i < bsp29->numtexinfo; i++) { texinfo_t *texinfo = &bsp29->texinfo[i]; - for (j=0 ; j < 4 ; j++) { + for (int j = 0; j < 4; j++) { texinfo->vecs[0][j] = LittleFloat (texinfo->vecs[0][j]); texinfo->vecs[1][j] = LittleFloat (texinfo->vecs[1][j]); } @@ -215,7 +214,7 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) } // faces - for (i=0 ; inumfaces ; i++) { + for (size_t i = 0; i < bsp29->numfaces; i++) { const dface_t *face2 = &bsp2->faces[i]; dface29_t *face29 = &bsp29->faces[i]; face29->planenum = LittleShort (face2->planenum); @@ -228,11 +227,11 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) } // nodes - for (i=0 ; inumnodes ; i++) { + for (size_t i = 0; i < bsp29->numnodes; i++) { const dnode_t *node2 = &bsp2->nodes[i]; dnode29_t *node29 = &bsp29->nodes[i]; node29->planenum = LittleLong (node2->planenum); - for (j=0 ; j<3 ; j++) { + for (int j = 0; j < 3; j++) { node29->mins[j] = LittleShort ((int16_t) node2->mins[j]); node29->maxs[j] = LittleShort ((int16_t) node2->maxs[j]); } @@ -243,11 +242,11 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) } // leafs - for (i=0 ; inumleafs ; i++) { + for (size_t i = 0; i < bsp29->numleafs; i++) { const dleaf_t *leaf2 = &bsp2->leafs[i]; dleaf29_t *leaf29 = &bsp29->leafs[i]; leaf29->contents = LittleLong (leaf2->contents); - for (j=0 ; j<3 ; j++) { + for (int j = 0; j < 3; j++) { leaf29->mins[j] = LittleShort ((int16_t) leaf2->mins[j]); leaf29->maxs[j] = LittleShort ((int16_t) leaf2->maxs[j]); } @@ -260,7 +259,7 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) } // clipnodes - for (i=0 ; inumclipnodes ; i++) { + for (size_t i = 0; i < bsp29->numclipnodes; i++) { const dclipnode_t *clipnode2 = &bsp2->clipnodes[i]; dclipnode29_t *clipnode29 = (dclipnode29_t *) &bsp29->clipnodes[i]; clipnode29->planenum = LittleLong (clipnode2->planenum); @@ -272,27 +271,27 @@ swap_to_bsp29 (bsp29_t *bsp29, const bsp_t *bsp2) if (bsp29->texdatasize) { mtl = (dmiptexlump_t *)bsp29->texdata; //miptexlumps have not yet been swapped - c = mtl->nummiptex; + uint32_t c = mtl->nummiptex; mtl->nummiptex = LittleLong (mtl->nummiptex); - for (i=0 ; idataofs[i] = LittleLong(mtl->dataofs[i]); } // marksurfaces - for (i=0 ; inummarksurfaces ; i++) { + for (size_t i = 0 ; i < bsp29->nummarksurfaces; i++) { const uint32_t *marksurface2 = &bsp2->marksurfaces[i]; uint16_t *marksurface29 = (uint16_t *) &bsp29->marksurfaces[i]; *marksurface29 = LittleShort (*marksurface2); } // surfedges - for (i=0 ; inumsurfedges ; i++) { + for (size_t i = 0; i < bsp29->numsurfedges; i++) { int32_t *surfedge = &bsp29->surfedges[i]; *surfedge = LittleLong (*surfedge); } // edges - for (i=0 ; inumedges ; i++) { + for (size_t i = 0; i < bsp29->numedges; i++) { const dedge_t *edge2 = &bsp2->edges[i]; dedge29_t *edge29 = (dedge29_t *) &bsp29->edges[i]; edge29->v[0] = LittleShort (edge2->v[0]); @@ -304,13 +303,12 @@ static void swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, void (*cb) (const bsp_t *, void *), void *cbdata) { - int c, i, j; dmiptexlump_t *mtl; dmodel_t *d; if (bsp2->header) { bsp2->header->version = LittleLong (bsp2->header->version); - for (i = 0; i < HEADER_LUMPS; i++) { + for (int i = 0; i < HEADER_LUMPS; i++) { bsp2->header->lumps[i].fileofs = LittleLong (bsp2->header->lumps[i].fileofs); bsp2->header->lumps[i].filelen = @@ -321,17 +319,17 @@ swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, } // models - for (i=0 ; inummodels ; i++) { + for (size_t i = 0; i < bsp2->nummodels; i++) { d = &bsp2->models[i]; - for (j=0 ; jheadnode[j] = LittleLong (d->headnode[j]); d->visleafs = LittleLong (d->visleafs); d->firstface = LittleLong (d->firstface); d->numfaces = LittleLong (d->numfaces); - for (j=0 ; j<3 ; j++) { + for (int j = 0; j < 3; j++) { d->mins[j] = LittleFloat(d->mins[j]); d->maxs[j] = LittleFloat(d->maxs[j]); d->origin[j] = LittleFloat(d->origin[j]); @@ -339,25 +337,25 @@ swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, } // vertexes - for (i=0 ; inumvertexes ; i++) { + for (size_t i = 0; i < bsp2->numvertexes; i++) { dvertex_t *vertex = &bsp2->vertexes[i]; - for (j=0 ; j<3 ; j++) + for (int j = 0; j < 3; j++) vertex->point[j] = LittleFloat (vertex->point[j]); } // planes - for (i=0 ; inumplanes ; i++) { + for (size_t i = 0; i < bsp2->numplanes; i++) { dplane_t *plane = &bsp2->planes[i]; - for (j=0 ; j<3 ; j++) + for (int j = 0; j < 3; j++) plane->normal[j] = LittleFloat (plane->normal[j]); plane->dist = LittleFloat (plane->dist); plane->type = LittleLong (plane->type); } // texinfos - for (i=0 ; inumtexinfo ; i++) { + for (size_t i = 0; i < bsp2->numtexinfo; i++) { texinfo_t *texinfo = &bsp2->texinfo[i]; - for (j=0 ; j < 4 ; j++) { + for (int j = 0; j < 4; j++) { texinfo->vecs[0][j] = LittleFloat (texinfo->vecs[0][j]); texinfo->vecs[1][j] = LittleFloat (texinfo->vecs[1][j]); } @@ -366,7 +364,7 @@ swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, } // faces - for (i=0 ; inumfaces ; i++) { + for (size_t i = 0; i < bsp2->numfaces; i++) { dface_t *face2 = &bsp2->faces[i]; const dface29_t *face29 = &bsp29->faces[i]; face2->planenum = LittleShort (face29->planenum); @@ -379,17 +377,17 @@ swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, } // nodes - for (i=0 ; inumnodes ; i++) { + for (size_t i = 0; i < bsp2->numnodes; i++) { dnode_t *node2 = &bsp2->nodes[i]; const dnode29_t *node29 = &bsp29->nodes[i]; node2->planenum = LittleLong (node29->planenum); - for (j=0 ; j<3 ; j++) { + for (int j = 0; j < 3; j++) { node2->mins[j] = (int16_t) LittleShort (node29->mins[j]); node2->maxs[j] = (int16_t) LittleShort (node29->maxs[j]); } - for (j = 0; j < 2; j++) { + for (int j = 0; j < 2; j++) { node2->children[j] = LittleShort (node29->children[j]); - if (node2->children[j] >= bsp2->numnodes) + if (node2->children[j] >= (int32_t) bsp2->numnodes) node2->children[j] = (int16_t) node2->children[j]; } node2->firstface = LittleShort (node29->firstface); @@ -397,11 +395,11 @@ swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, } // leafs - for (i=0 ; inumleafs ; i++) { + for (size_t i = 0; i < bsp2->numleafs; i++) { dleaf_t *leaf2 = &bsp2->leafs[i]; const dleaf29_t *leaf29 = &bsp29->leafs[i]; leaf2->contents = LittleLong (leaf29->contents); - for (j=0 ; j<3 ; j++) { + for (int j = 0; j < 3; j++) { leaf2->mins[j] = (int16_t) LittleShort (leaf29->mins[j]); leaf2->maxs[j] = (int16_t) LittleShort (leaf29->maxs[j]); } @@ -414,7 +412,7 @@ swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, } // clipnodes - for (i=0 ; inumclipnodes ; i++) { + for (size_t i = 0; i < bsp2->numclipnodes; i++) { dclipnode_t *clipnode2 = &bsp2->clipnodes[i]; const dclipnode29_t *clipnode29 = &bsp29->clipnodes[i]; clipnode2->planenum = LittleLong (clipnode29->planenum); @@ -425,27 +423,27 @@ swap_from_bsp29 (bsp_t *bsp2, const bsp29_t *bsp29, // miptex if (bsp2->texdatasize) { mtl = (dmiptexlump_t *)bsp2->texdata; - c = LittleLong(mtl->nummiptex); + uint32_t c = LittleLong (mtl->nummiptex); mtl->nummiptex = LittleLong (mtl->nummiptex); - for (i=0 ; idataofs[i] = LittleLong(mtl->dataofs[i]); + for (uint32_t i = 0; i < c; i++) + mtl->dataofs[i] = LittleLong (mtl->dataofs[i]); } // marksurfaces - for (i=0 ; inummarksurfaces ; i++) { + for (size_t i = 0; i < bsp2->nummarksurfaces; i++) { uint32_t *marksurface2 = &bsp2->marksurfaces[i]; const uint16_t *marksurface29 = &bsp29->marksurfaces[i]; *marksurface2 = LittleShort (*marksurface29); } // surfedges - for (i=0 ; inumsurfedges ; i++) { + for (size_t i = 0; i < bsp2->numsurfedges; i++) { int32_t *surfedge = &bsp2->surfedges[i]; *surfedge = LittleLong (*surfedge); } // edges - for (i=0 ; inumedges ; i++) { + for (size_t i = 0; i < bsp2->numedges; i++) { dedge_t *edge2 = &bsp2->edges[i]; const dedge29_t *edge29 = &bsp29->edges[i]; edge2->v[0] = LittleShort (edge29->v[0]); @@ -457,13 +455,12 @@ static void swap_bsp (bsp_t *bsp, int todisk, void (*cb) (const bsp_t *, void *), void *cbdata) { - int c, i, j; dmiptexlump_t *mtl; dmodel_t *d; if (bsp->header) { bsp->header->version = LittleLong (bsp->header->version); - for (i = 0; i < HEADER_LUMPS; i++) { + for (int i = 0; i < HEADER_LUMPS; i++) { bsp->header->lumps[i].fileofs = LittleLong (bsp->header->lumps[i].fileofs); bsp->header->lumps[i].filelen = @@ -474,17 +471,17 @@ swap_bsp (bsp_t *bsp, int todisk, void (*cb) (const bsp_t *, void *), } // models - for (i=0 ; inummodels ; i++) { + for (size_t i = 0; i < bsp->nummodels; i++) { d = &bsp->models[i]; - for (j=0 ; jheadnode[j] = LittleLong (d->headnode[j]); d->visleafs = LittleLong (d->visleafs); d->firstface = LittleLong (d->firstface); d->numfaces = LittleLong (d->numfaces); - for (j=0 ; j<3 ; j++) { + for (int j = 0; j < 3; j++) { d->mins[j] = LittleFloat(d->mins[j]); d->maxs[j] = LittleFloat(d->maxs[j]); d->origin[j] = LittleFloat(d->origin[j]); @@ -492,25 +489,25 @@ swap_bsp (bsp_t *bsp, int todisk, void (*cb) (const bsp_t *, void *), } // vertexes - for (i=0 ; inumvertexes ; i++) { + for (size_t i = 0; i < bsp->numvertexes; i++) { dvertex_t *vertex = &bsp->vertexes[i]; - for (j=0 ; j<3 ; j++) + for (int j = 0; j < 3; j++) vertex->point[j] = LittleFloat (vertex->point[j]); } // planes - for (i=0 ; inumplanes ; i++) { + for (size_t i = 0; i < bsp->numplanes; i++) { dplane_t *plane = &bsp->planes[i]; - for (j=0 ; j<3 ; j++) + for (int j = 0; j < 3; j++) plane->normal[j] = LittleFloat (plane->normal[j]); plane->dist = LittleFloat (plane->dist); plane->type = LittleLong (plane->type); } // texinfos - for (i=0 ; inumtexinfo ; i++) { + for (size_t i = 0; i < bsp->numtexinfo; i++) { texinfo_t *texinfo = &bsp->texinfo[i]; - for (j=0 ; j < 4 ; j++) { + for (int j = 0; j < 4; j++) { texinfo->vecs[0][j] = LittleFloat (texinfo->vecs[0][j]); texinfo->vecs[1][j] = LittleFloat (texinfo->vecs[1][j]); } @@ -519,7 +516,7 @@ swap_bsp (bsp_t *bsp, int todisk, void (*cb) (const bsp_t *, void *), } // faces - for (i=0 ; inumfaces ; i++) { + for (size_t i = 0; i < bsp->numfaces; i++) { dface_t *face = &bsp->faces[i]; face->texinfo = LittleLong (face->texinfo); face->planenum = LittleLong (face->planenum); @@ -530,10 +527,10 @@ swap_bsp (bsp_t *bsp, int todisk, void (*cb) (const bsp_t *, void *), } // nodes - for (i=0 ; inumnodes ; i++) { + for (size_t i = 0; i < bsp->numnodes; i++) { dnode_t *node = &bsp->nodes[i]; node->planenum = LittleLong (node->planenum); - for (j=0 ; j<3 ; j++) { + for (int j = 0; j < 3; j++) { node->mins[j] = LittleFloat (node->mins[j]); node->maxs[j] = LittleFloat (node->maxs[j]); } @@ -544,10 +541,10 @@ swap_bsp (bsp_t *bsp, int todisk, void (*cb) (const bsp_t *, void *), } // leafs - for (i=0 ; inumleafs ; i++) { + for (size_t i = 0; i < bsp->numleafs; i++) { dleaf_t *leaf = &bsp->leafs[i]; leaf->contents = LittleLong (leaf->contents); - for (j=0 ; j<3 ; j++) { + for (int j = 0; j < 3 ; j++) { leaf->mins[j] = LittleFloat (leaf->mins[j]); leaf->maxs[j] = LittleFloat (leaf->maxs[j]); } @@ -558,7 +555,7 @@ swap_bsp (bsp_t *bsp, int todisk, void (*cb) (const bsp_t *, void *), } // clipnodes - for (i=0 ; inumclipnodes ; i++) { + for (size_t i = 0; i < bsp->numclipnodes; i++) { dclipnode_t *clipnode = &bsp->clipnodes[i]; clipnode->planenum = LittleLong (clipnode->planenum); clipnode->children[0] = LittleLong (clipnode->children[0]); @@ -567,30 +564,31 @@ swap_bsp (bsp_t *bsp, int todisk, void (*cb) (const bsp_t *, void *), // miptex if (bsp->texdatasize) { - mtl = (dmiptexlump_t *)bsp->texdata; + mtl = (dmiptexlump_t *) bsp->texdata; + uint32_t c; if (todisk) c = mtl->nummiptex; else c = LittleLong(mtl->nummiptex); mtl->nummiptex = LittleLong (mtl->nummiptex); - for (i=0 ; idataofs[i] = LittleLong(mtl->dataofs[i]); } // marksurfaces - for (i=0 ; inummarksurfaces ; i++) { + for (size_t i = 0; i < bsp->nummarksurfaces; i++) { uint32_t *marksurface = &bsp->marksurfaces[i]; *marksurface = LittleLong (*marksurface); } // surfedges - for (i=0 ; inumsurfedges ; i++) { + for (size_t i = 0; i < bsp->numsurfedges; i++) { int32_t *surfedge = &bsp->surfedges[i]; *surfedge = LittleLong (*surfedge); } // edges - for (i=0 ; inumedges ; i++) { + for (size_t i = 0; i < bsp->numedges; i++) { dedge_t *edge = &bsp->edges[i]; edge->v[0] = LittleLong (edge->v[0]); edge->v[1] = LittleLong (edge->v[1]); diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 7c7097ce5..0c128069c 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -549,9 +549,8 @@ gl_R_BlendLightmaps (void) void gl_overbright_f (cvar_t *var) { - int num, i, j; + int num; model_t *m; - msurface_t *surf; entity_t *ent; mod_brush_t *brush; @@ -608,8 +607,8 @@ gl_overbright_f (cvar_t *var) continue; brush = &m->brush; - for (j = 0, surf = brush->surfaces; j < brush->numsurfaces; - j++, surf++) { + for (unsigned j = 0; j < brush->numsurfaces; j++) { + msurface_t *surf = brush->surfaces + j; if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) continue; @@ -626,7 +625,8 @@ gl_overbright_f (cvar_t *var) brush = &r_worldentity.renderer.model->brush; - for (i = 0, surf = brush->surfaces; i < brush->numsurfaces; i++, surf++) { + for (unsigned i = 0; i < brush->numsurfaces; i++) { + msurface_t *surf = brush->surfaces + i; if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) continue; @@ -709,7 +709,6 @@ GL_CreateSurfaceLightmap (mod_brush_t *brush, msurface_t *surf) void GL_BuildLightmaps (model_t **models, int num_models) { - int i, j; model_t *m; mod_brush_t *brush; @@ -750,7 +749,7 @@ GL_BuildLightmaps (model_t **models, int num_models) break; } - for (j = 1; j < num_models; j++) { + for (int j = 1; j < num_models; j++) { m = models[j]; if (!m) break; @@ -762,7 +761,7 @@ GL_BuildLightmaps (model_t **models, int num_models) r_pcurrentvertbase = brush->vertexes; gl_currentmodel = m; // non-bsp models don't have surfaces. - for (i = 0; i < brush->numsurfaces; i++) { + for (unsigned i = 0; i < brush->numsurfaces; i++) { if (brush->surfaces[i].flags & SURF_DRAWTURB) continue; if (gl_sky_divide->int_val && (brush->surfaces[i].flags & @@ -774,7 +773,7 @@ GL_BuildLightmaps (model_t **models, int num_models) } // upload all lightmaps that were filled - for (i = 0; i < MAX_LIGHTMAPS; i++) { + for (int i = 0; i < MAX_LIGHTMAPS; i++) { if (!allocated[i][0]) break; // no more used gl_lightmap_modified[i] = false; diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index c2d98b3f1..8a2005910 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -170,10 +170,9 @@ gl_R_Init (void) static void register_textures (mod_brush_t *brush) { - int i; texture_t *tex; - for (i = 0; i < brush->numtextures; i++) { + for (unsigned i = 0; i < brush->numtextures; i++) { tex = brush->textures[i]; if (!tex) continue; @@ -211,7 +210,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) // identify sky texture gl_mirrortexturenum = -1; gl_R_ClearTextures (); - for (int i = 0; i < brush->numtextures; i++) { + for (unsigned i = 0; i < brush->numtextures; i++) { tex = brush->textures[i]; if (!tex) continue; diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index daed97922..c27788a5c 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -160,12 +160,10 @@ gl_R_AddTexture (texture_t *tx) void gl_R_InitSurfaceChains (mod_brush_t *brush) { - int i; - if (static_chains) free (static_chains); static_chains = calloc (brush->nummodelsurfaces, sizeof (instsurf_t)); - for (i = 0; i < brush->nummodelsurfaces; i++) + for (unsigned i = 0; i < brush->nummodelsurfaces; i++) brush->surfaces[i].instsurf = static_chains + i; release_instsurfs (); @@ -527,8 +525,6 @@ void gl_R_DrawBrushModel (entity_t *e) { float dot, radius; - int i; - unsigned int k; msurface_t *surf; qboolean rotated; vec3_t mins, maxs; @@ -581,7 +577,7 @@ gl_R_DrawBrushModel (entity_t *e) if (brush->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { vec3_t lightorigin; - for (k = 0; k < r_maxdlights; k++) { + for (unsigned k = 0; k < r_maxdlights; k++) { if ((r_dlights[k].die < vr_data.realtime) || (!r_dlights[k].radius)) continue; @@ -600,7 +596,7 @@ gl_R_DrawBrushModel (entity_t *e) surf = &brush->surfaces[brush->firstmodelsurface]; // draw texture - for (i = 0; i < brush->nummodelsurfaces; i++, surf++) { + for (unsigned i = 0; i < brush->nummodelsurfaces; i++, surf++) { // find which side of the node we are on plane_t *plane = surf->plane; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 04caf310c..840936b42 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -325,12 +325,10 @@ glsl_R_AddTexture (texture_t *tx) static void glsl_R_InitSurfaceChains (mod_brush_t *brush) { - int i; - release_static_instsurfs (); release_instsurfs (); - for (i = 0; i < brush->nummodelsurfaces; i++) { + for (unsigned i = 0; i < brush->nummodelsurfaces; i++) { brush->surfaces[i].instsurf = get_static_instsurf (); brush->surfaces[i].instsurf->surface = &brush->surfaces[i]; } @@ -414,10 +412,9 @@ chain_surface (glslbspctx_t *bctx, msurface_t *surf) static void register_textures (mod_brush_t *brush) { - int i; texture_t *tex; - for (i = 0; i < brush->numtextures; i++) { + for (unsigned i = 0; i < brush->numtextures; i++) { tex = brush->textures[i]; if (!tex) continue; @@ -553,7 +550,6 @@ build_surf_displist (model_t **models, msurface_t *surf, int base, void glsl_R_BuildDisplayLists (model_t **models, int num_models) { - int i, j; int vertex_index_base; model_t *m; dmodel_t *dm; @@ -571,7 +567,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) // now run through all surfaces, chaining them to their textures, thus // effectively sorting the surfaces by texture (without worrying about // surface order on the same texture chain). - for (i = 0; i < num_models; i++) { + for (int i = 0; i < num_models; i++) { m = models[i]; if (!m) continue; @@ -581,7 +577,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) brush = &m->brush; // non-bsp models don't have surfaces. dm = brush->submodels; - for (j = 0; j < brush->numsurfaces; j++) { + for (uint32_t j = 0; j < brush->numsurfaces; j++) { glsltex_t *tex; if (j == dm->firstface + dm->numfaces) { dm++; @@ -608,7 +604,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) // Run through the textures, using their chains to build display maps. // For animated textures, if a surface is on one texture of the group, it // will be on all. - for (i = 0; i < r_num_texture_chains; i++) { + for (int i = 0; i < r_num_texture_chains; i++) { glsltex_t *tex; instsurf_t *is; elechain_t *ec = 0; @@ -663,7 +659,6 @@ static void R_DrawBrushModel (entity_t *e) { float dot, radius; - int i; unsigned k; model_t *model = e->renderer.model; mod_brush_t *brush = &model->brush; @@ -722,7 +717,7 @@ R_DrawBrushModel (entity_t *e) surf = &brush->surfaces[brush->firstmodelsurface]; - for (i = 0; i < brush->nummodelsurfaces; i++, surf++) { + for (unsigned i = 0; i < brush->nummodelsurfaces; i++, surf++) { // find the node side on which we are plane = surf->plane; diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index 750858251..14561bbb0 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -203,7 +203,7 @@ create_surf_lightmap (msurface_t *surf) void glsl_R_BuildLightmaps (model_t **models, int num_models) { - int i, j, size; + int size; model_t *m; mod_brush_t *brush; @@ -216,7 +216,7 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) glsl_R_BuildLightMap = R_BuildLightMap_1; bl_extents[1] = bl_extents[0] = 0; - for (j = 1; j < num_models; j++) { + for (int j = 1; j < num_models; j++) { m = models[j]; if (!m) break; @@ -226,7 +226,7 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) } brush = &m->brush; // non-bsp models don't have surfaces. - for (i = 0; i < brush->numsurfaces; i++) { + for (unsigned i = 0; i < brush->numsurfaces; i++) { msurface_t *surf = brush->surfaces + i; surf->lightpic = 0; // paranoia if (surf->flags & SURF_DRAWTURB) @@ -238,7 +238,7 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) } size = bl_extents[0] * bl_extents[1] * 3; // * 3 for rgb support blocklights = realloc (blocklights, size * sizeof (blocklights[0])); - for (j = 1; j < num_models; j++) { + for (int j = 1; j < num_models; j++) { m = models[j]; if (!m) break; @@ -248,7 +248,7 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) } brush = &m->brush; // non-bsp models don't have surfaces. - for (i = 0; i < brush->numsurfaces; i++) { + for (unsigned i = 0; i < brush->numsurfaces; i++) { msurface_t *surf = brush->surfaces + i; if (surf->lightpic) glsl_R_BuildLightMap (0, brush, surf); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 7bfe34fff..bbc844a91 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -171,12 +171,11 @@ static void init_surface_chains (mod_brush_t *brush, vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; - int i; release_static_instsurfs (bctx); release_instsurfs (bctx); - for (i = 0; i < brush->nummodelsurfaces; i++) { + for (unsigned i = 0; i < brush->nummodelsurfaces; i++) { brush->surfaces[i].instsurf = get_static_instsurf (bctx); brush->surfaces[i].instsurf->surface = &brush->surfaces[i]; } @@ -242,10 +241,9 @@ chain_surface (msurface_t *surf, vulkan_ctx_t *ctx) static void register_textures (mod_brush_t *brush, vulkan_ctx_t *ctx) { - int i; texture_t *tex; - for (i = 0; i < brush->numtextures; i++) { + for (unsigned i = 0; i < brush->numtextures; i++) { tex = brush->textures[i]; if (!tex) continue; @@ -394,7 +392,6 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; - int i, j; int vertex_index_base; model_t *m; dmodel_t *dm; @@ -414,7 +411,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) // run through all surfaces, chaining them to their textures, thus // effectively sorting the surfaces by texture (without worrying about // surface order on the same texture chain). - for (i = 0; i < num_models; i++) { + for (int i = 0; i < num_models; i++) { m = models[i]; if (!m) continue; @@ -424,7 +421,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) continue; brush = &m->brush; dm = brush->submodels; - for (j = 0; j < brush->numsurfaces; j++) { + for (unsigned j = 0; j < brush->numsurfaces; j++) { vulktex_t *tex; if (j == dm->firstface + dm->numfaces) { // move on to the next sub-model @@ -581,7 +578,6 @@ static void R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) { float dot, radius; - int i; model_t *model; plane_t *plane; msurface_t *surf; @@ -625,7 +621,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) surf = &brush->surfaces[brush->firstmodelsurface]; - for (i = 0; i < brush->nummodelsurfaces; i++, surf++) { + for (unsigned i = 0; i < brush->nummodelsurfaces; i++, surf++) { // find the node side on which we are plane = surf->plane; diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index f8aace8c4..3f5e248e2 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1105,7 +1105,6 @@ SV_SpawnServer (const char *server) { byte *buf; QFile *ent_file; - int i; edict_t *ent; @@ -1162,7 +1161,7 @@ SV_SpawnServer (const char *server) // leave slots at start for only clients sv.num_edicts = svs.maxclients + 1; - for (i = 0; i < svs.maxclients; i++) { + for (int i = 0; i < svs.maxclients; i++) { ent = EDICT_NUM (&sv_pr_state, i + 1); svs.clients[i].edict = ent; } @@ -1190,7 +1189,7 @@ SV_SpawnServer (const char *server) sv.model_precache[0] = sv_pr_state.pr_strings; sv.model_precache[1] = sv.modelname; - for (i = 1; i < sv.worldmodel->brush.numsubmodels; i++) { + for (unsigned i = 1; i < sv.worldmodel->brush.numsubmodels; i++) { sv.model_precache[1 + i] = localmodels[i]; sv.models[i + 1] = Mod_ForName (localmodels[i], false); } @@ -1244,10 +1243,12 @@ SV_SpawnServer (const char *server) sv.signon.cursize); // send serverinfo to all connected clients - for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, - host_client++) - if (host_client->active) + for (int i = 0; i < svs.maxclients; i++) { + host_client = svs.clients + i; + if (host_client->active) { SV_SendServerinfo (host_client); + } + } Sys_MaskPrintf (SYS_dev, "Server spawned.\n"); S_UnblockSound (); diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 7fe625c87..30a0a12d2 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -320,7 +320,6 @@ SV_SpawnServer (const char *server) { byte *buf; edict_t *ent; - int i; void *so_buffers; int *so_sizes; int max_so; @@ -384,7 +383,7 @@ SV_SpawnServer (const char *server) // leave slots at start for only clients sv.num_edicts = MAX_CLIENTS + 1; - for (i = 0; i < MAX_CLIENTS; i++) { + for (int i = 0; i < MAX_CLIENTS; i++) { ent = EDICT_NUM (&sv_pr_state, i + 1); svs.clients[i].edict = ent; // ZOID - make sure we update frags right @@ -407,7 +406,7 @@ SV_SpawnServer (const char *server) sv.model_precache[0] = sv_pr_state.pr_strings; sv.model_precache[1] = sv.modelname; sv.models[1] = sv.worldmodel; - for (i = 1; i < sv.worldmodel->brush.numsubmodels; i++) { + for (unsigned i = 1; i < sv.worldmodel->brush.numsubmodels; i++) { sv.model_precache[1 + i] = localmodels[i]; sv.models[i + 1] = Mod_ForName (localmodels[i], false); } diff --git a/tools/bsp2img/bsp2img.c b/tools/bsp2img/bsp2img.c index bf99eea67..6a1c6ea7a 100644 --- a/tools/bsp2img/bsp2img.c +++ b/tools/bsp2img/bsp2img.c @@ -531,7 +531,7 @@ create_image (long width, long height) static image_t * render_map (bsp_t *bsp) { - long i = 0, j = 0, k = 0, x = 0; + long j = 0, k = 0, x = 0; dvertex_t *vertexlist, *vert1, *vert2; dedge_t *edgelist; @@ -567,14 +567,14 @@ render_map (bsp_t *bsp) exit (2); } /* initialize the array */ - for (i = 0; i < bsp->numedges; i++) { + for (unsigned i = 0; i < bsp->numedges; i++) { edge_extra[i].num_face_ref = 0; - for (j = 0; j < MAX_REF_FACES; j++) { + for (int j = 0; j < MAX_REF_FACES; j++) { edge_extra[i].ref_faces[j] = -1; } } - for (i = 0; i < bsp->numfaces; i++) { + for (unsigned i = 0; i < bsp->numfaces; i++) { /* calculate the normal (cross product) */ /* starting edge: edgelist[ledges[facelist[i].firstedge]] */ /* number of edges: facelist[i].numedges; */ @@ -647,7 +647,7 @@ render_map (bsp_t *bsp) printf ("Collecting min/max\n"); /* Collect min and max */ - for (i = 0; i < bsp->numvertexes; i++) { + for (unsigned i = 0; i < bsp->numvertexes; i++) { /* Ugly hack - flip stuff around for different camera angles */ switch (options.camera_axis) { @@ -788,7 +788,7 @@ render_map (bsp_t *bsp) fprintf (stderr, "Plotting edges..."); k = 0; drawcol = (options.edgeremove) ? 64 : 32; - for (i = 0; i < bsp->numedges; i++) { + for (unsigned i = 0; i < bsp->numedges; i++) { /* Do a check on this line ... see if we keep this line or not */ /* run through all referenced faces */ @@ -840,7 +840,7 @@ render_map (bsp_t *bsp) } } - printf ("%d edges plotted", bsp->numedges); + printf ("%zd edges plotted", bsp->numedges); if (options.edgeremove) { printf (" (%ld edges removed)\n", k); } else { @@ -848,7 +848,7 @@ render_map (bsp_t *bsp) } /* Little gradient */ - for (i = 0; i <= 255; i++) { + for (unsigned i = 0; i <= 255; i++) { // across from top left plotpoint (image, i, 0, 255 - i); // down from top left @@ -872,8 +872,8 @@ render_map (bsp_t *bsp) /* Negate image if necessary */ if (options.negative_image) { - for (i = 0; i < image->height; i++) { - for (j = 0; j < image->width; j++) { + for (int i = 0; i < image->height; i++) { + for (int j = 0; j < image->width; j++) { image->image[i * image->width + j] = 255 - image->image[i * image->width + j]; } diff --git a/tools/qfbsp/source/info.c b/tools/qfbsp/source/info.c index fb2a6dc0c..92a5d2abc 100644 --- a/tools/qfbsp/source/info.c +++ b/tools/qfbsp/source/info.c @@ -50,7 +50,7 @@ bspinfo () lump->fileofs, lump->filelen, lump->filelen / info->size); } - for (int i = 0; i < bsp->nummodels; i++) { + for (unsigned i = 0; i < bsp->nummodels; i++) { dmodel_t *model = &bsp->models[i]; printf ("model: *%d\n", i); printf (" mins : [%g, %g, %g]\n", VectorExpand (model->mins)); diff --git a/tools/qfbsp/source/map.c b/tools/qfbsp/source/map.c index 63fe1bb06..a2490eb38 100644 --- a/tools/qfbsp/source/map.c +++ b/tools/qfbsp/source/map.c @@ -122,10 +122,11 @@ FindMiptex (const char *name) static int FindTexinfo (texinfo_t *t) { - int i, j; + size_t i; + int j; texinfo_t *tex; - if (t->miptex < 0) + if (t->miptex == ~0u) return t->miptex; // it's HINT or SKIP // set the special flag @@ -545,7 +546,7 @@ LoadMapFile (const char *filename) qprintf ("%5i brushes (%i detail)\n", nummapbrushes, numdetailbrushes); qprintf ("%5i entities\n", num_entities); qprintf ("%5i textures\n", nummiptexnames); - qprintf ("%5i texinfo\n", bsp->numtexinfo); + qprintf ("%5zd texinfo\n", bsp->numtexinfo); } void diff --git a/tools/qfbsp/source/qfbsp.c b/tools/qfbsp/source/qfbsp.c index 19a0d5023..308e5e5ef 100644 --- a/tools/qfbsp/source/qfbsp.c +++ b/tools/qfbsp/source/qfbsp.c @@ -103,7 +103,7 @@ ProcessEntity (int entnum) worldmodel = false; if (entnum == 1) qprintf ("--- Internal Entities ---\n"); - sprintf (mod, "*%i", bsp->nummodels); + sprintf (mod, "*%zd", bsp->nummodels); if (options.verbosity) PrintEntity (ent); @@ -225,7 +225,6 @@ WriteClipHull (void) FILE *f; dclipnode_t *d; dplane_t *p; - int i; options.hullfile[strlen (options.hullfile) - 1] = '0' + hullnum; @@ -236,18 +235,18 @@ WriteClipHull (void) if (!f) Sys_Error ("Couldn't open %s", options.hullfile); - fprintf (f, "%i\n", bsp->nummodels); + fprintf (f, "%zd\n", bsp->nummodels); - for (i = 0; i < bsp->nummodels; i++) + for (size_t i = 0; i < bsp->nummodels; i++) fprintf (f, "%i\n", bsp->models[i].headnode[hullnum]); - fprintf (f, "\n%i\n", bsp->numclipnodes); + fprintf (f, "\n%zd\n", bsp->numclipnodes); - for (i = 0; i < bsp->numclipnodes; i++) { + for (size_t i = 0; i < bsp->numclipnodes; i++) { d = &bsp->clipnodes[i]; p = &bsp->planes[d->planenum]; // the node number is written out only for human readability - fprintf (f, "%5i : %f %f %f %f : %5i %5i\n", i, p->normal[0], + fprintf (f, "%5zd : %f %f %f %f : %5i %5i\n", i, p->normal[0], p->normal[1], p->normal[2], p->dist, d->children[0], d->children[1]); } @@ -268,7 +267,8 @@ ReadClipHull (int hullnum) plane_t p; dplane_t dp; float f1, f2, f3, f4; - int firstclipnode, junk, c1, c2, i, j, n; + int firstclipnode, junk, c1, c2; + size_t i, j, n; int flip; options.hullfile[strlen (options.hullfile) - 1] = '0' + hullnum; @@ -277,21 +277,21 @@ ReadClipHull (int hullnum) if (!f) Sys_Error ("Couldn't open %s", options.hullfile); - if (fscanf (f, "%d\n", &n) != 1) + if (fscanf (f, "%zd\n", &n) != 1) Sys_Error ("Error parsing %s", options.hullfile); if (n != bsp->nummodels) - Sys_Error ("ReadClipHull: hull had %i models, base had %i", n, + Sys_Error ("ReadClipHull: hull had %zd models, base had %zd", n, bsp->nummodels); for (i = 0; i < n; i++) { - if (fscanf (f, "%d\n", &j) != 1) + if (fscanf (f, "%zd\n", &j) != 1) Sys_Error ("Error parsing %s", options.hullfile); bsp->models[i].headnode[hullnum] = bsp->numclipnodes + j; } - if (fscanf (f, "\n%d\n", &n) != 1) + if (fscanf (f, "\n%zd\n", &n) != 1) Sys_Error ("Error parsing %s", options.hullfile); firstclipnode = bsp->numclipnodes; diff --git a/tools/qfbsp/source/readbsp.c b/tools/qfbsp/source/readbsp.c index c71d74b5f..fce4e4e84 100644 --- a/tools/qfbsp/source/readbsp.c +++ b/tools/qfbsp/source/readbsp.c @@ -102,10 +102,9 @@ load_planes (void) { const dplane_t *p; plane_t tp = { }; - int i; planes.size = 0; - for (i = 0; i < bsp->numplanes; i++) { + for (size_t i = 0; i < bsp->numplanes; i++) { p = bsp->planes + i; VectorCopy (p->normal, tp.normal); tp.dist = p->dist; @@ -124,11 +123,10 @@ static void load_faces (void) { const dface_t *f; - int i, j; winding_t *points; mfaces = calloc (bsp->numfaces, sizeof (face_t)); - for (i = 0; i < bsp->numfaces; i++) { + for (size_t i = 0; i < bsp->numfaces; i++) { f = bsp->faces + i; mfaces[i].planenum = f->planenum; mfaces[i].planeside = f->side; @@ -138,7 +136,7 @@ load_faces (void) points = mfaces[i].points; points->numpoints = f->numedges; - for (j = 0; j < points->numpoints; j++) { + for (int j = 0; j < points->numpoints; j++) { int e = mfaces[i].edges[j]; int v; @@ -162,11 +160,9 @@ static void load_leafs (void) { const dleaf_t *l; - int i; - unsigned j; leafs = calloc (bsp->numleafs, sizeof (node_t)); - for (i = 0; i < bsp->numleafs; i++) { + for (size_t i = 0; i < bsp->numleafs; i++) { l = bsp->leafs + i; leafs[i].planenum = -1; leafs[i].contents = l->contents; @@ -174,7 +170,7 @@ load_leafs (void) VectorCopy (l->maxs, leafs[i].maxs); leafs[i].markfaces = calloc (l->nummarksurfaces + 1, sizeof (face_t *)); - for (j = 0; j < l->nummarksurfaces; j++) { + for (uint32_t j = 0; j < l->nummarksurfaces; j++) { unsigned short ms = l->firstmarksurface + j; leafs[i].markfaces[j] = mfaces + marksurfaces[ms]; } @@ -185,19 +181,16 @@ static void load_nodes (void) { const dnode_t *n; - face_t *f; - int i; - unsigned j; nodes = calloc (bsp->numnodes, sizeof (node_t)); - for (i = 0; i < bsp->numnodes; i++) { + for (size_t i = 0; i < bsp->numnodes; i++) { n = bsp->nodes + i; VectorCopy (n->mins, nodes[i].mins); VectorCopy (n->maxs, nodes[i].maxs); nodes[i].planenum = n->planenum; nodes[i].firstface = n->firstface; nodes[i].numfaces = n->numfaces; - for (j = 0; j < 2; j++) { + for (int j = 0; j < 2; j++) { if (n->children[j] < 0) { nodes[i].children[j] = leafs - n->children[j] - 1; } else { @@ -206,7 +199,8 @@ load_nodes (void) } if (nodes[i].numfaces) { nodes[i].faces = mfaces + nodes[i].firstface; - for (j = 0, f = nodes[i].faces; j < n->numfaces - 1; j++, f++) { + for (uint32_t j = 0; j < n->numfaces - 1; j++) { + face_t *f = nodes[i].faces + j; f->next = f + 1; } } @@ -375,7 +369,7 @@ extract_textures (void) { const dmiptexlump_t *miptexlump = (dmiptexlump_t *) bsp->texdata; miptex_t *miptex; - int i, mtsize, pixels; + int mtsize, pixels; const char *wadfile; wad_t *wad; const char *uname; @@ -387,15 +381,15 @@ extract_textures (void) wad_add_data (wad, "PALETTE", TYP_PALETTE, default_palette, sizeof (default_palette)); - for (i = 0; i < miptexlump->nummiptex; i++) { - if (miptexlump->dataofs[i] == -1) + for (size_t i = 0; i < miptexlump->nummiptex; i++) { + if (miptexlump->dataofs[i] == ~0u) continue; miptex = (miptex_t *)(bsp->texdata + miptexlump->dataofs[i]); pixels = miptex->width * miptex->height / 64 * 85; mtsize = sizeof (miptex_t) + pixels; uname = unique_name (wad, miptex->name); #if 1 - printf ("%3d %6d ", i, miptexlump->dataofs[i]); + printf ("%3zd %6d ", i, miptexlump->dataofs[i]); printf ("%16.16s %16.16s %3dx%-3d %d %d %d %d %d %d\n", miptex->name, uname, miptex->width, miptex->height, miptex->offsets[0], miptex->offsets[1], @@ -432,7 +426,6 @@ extract_hull (void) { // hullfile = output_file (".c"); const char *hullfile; - int i, j; QFile *hf; hullfile = output_file (".c"); @@ -441,14 +434,14 @@ extract_hull (void) else hf = Qopen (hullfile, "wt"); - printf ("%d\n", bsp->nummodels); - for (i = 0; i < bsp->nummodels; i++) { + printf ("%zd\n", bsp->nummodels); + for (size_t i = 0; i < bsp->nummodels; i++) { dmodel_t *m = bsp->models + i; printf ("mins: (%g, %g, %g)\n", m->mins[0], m->mins[1], m->mins[2]); printf ("maxs: (%g, %g, %g)\n", m->maxs[0], m->maxs[1], m->maxs[2]); printf ("origin: (%g, %g, %g)\n", m->origin[0], m->origin[1], m->origin[2]); - for (j = 0; j < MAX_MAP_HULLS; j++) + for (int j = 0; j < MAX_MAP_HULLS; j++) printf ("headnodes[%d]: %d\n", j, m->headnode[j]); printf ("visleafs: %d\n", m->visleafs); printf ("firstface: %d\n", m->firstface); @@ -456,7 +449,7 @@ extract_hull (void) printf ("\n"); } Qprintf (hf, "dclipnode_t clipnodes[] = {\n"); - for (i = 0; i < bsp->numnodes; i++) { + for (size_t i = 0; i < bsp->numnodes; i++) { int c0, c1; c0 = bsp->nodes[i].children[0]; c1 = bsp->nodes[i].children[1]; @@ -464,13 +457,13 @@ extract_hull (void) c0 = bsp->leafs[-1 - c0].contents; if (c1 < 0) c1 = bsp->leafs[-1 - c1].contents; - Qprintf (hf, "\t{%d, {%d, %d}},\t// %d\n", bsp->nodes[i].planenum, + Qprintf (hf, "\t{%d, {%d, %d}},\t// %zd\n", bsp->nodes[i].planenum, c0, c1, i); } Qprintf (hf, "};\n"); Qprintf (hf, "mplane_t planes[] = {\n"); - for (i = 0; i < bsp->numplanes; i++) { - Qprintf (hf, "\t{{%g, %g, %g}, %g, %d, 0, {0, 0}},\t// %d\n", + for (size_t i = 0; i < bsp->numplanes; i++) { + Qprintf (hf, "\t{{%g, %g, %g}, %g, %d, 0, {0, 0}},\t// %zd\n", bsp->planes[i].normal[0], bsp->planes[i].normal[1], bsp->planes[i].normal[2], bsp->planes[i].dist, bsp->planes[i].type, diff --git a/tools/qfbsp/source/region.c b/tools/qfbsp/source/region.c index acb8e5da1..b8d5b8a1e 100644 --- a/tools/qfbsp/source/region.c +++ b/tools/qfbsp/source/region.c @@ -163,21 +163,19 @@ RecursiveGrowRegion (dface_t *r, face_t *f) static void CountRealNumbers (void) { - int c, i; + qprintf ("%5zd regions\n", bsp->numfaces - firstmodelface); - qprintf ("%5i regions\n", bsp->numfaces - firstmodelface); - - c = 0; - for (i = firstmodelface; i < bsp->numfaces; i++) + size_t c = 0; + for (size_t i = firstmodelface; i < bsp->numfaces; i++) c += bsp->faces[i].numedges; - qprintf ("%5i real marksurfaces\n", c); + qprintf ("%5zd real marksurfaces\n", c); c = 0; - for (i = firstmodeledge; i < bsp->numedges; i++) + for (size_t i = firstmodeledge; i < bsp->numedges; i++) if (edgefaces[i].f[0]) c++; // not removed - qprintf ("%5i real edges\n", c); + qprintf ("%5zd real edges\n", c); } static void diff --git a/tools/qfbsp/source/surfaces.c b/tools/qfbsp/source/surfaces.c index c99b4fb40..2d421eec3 100644 --- a/tools/qfbsp/source/surfaces.c +++ b/tools/qfbsp/source/surfaces.c @@ -204,7 +204,7 @@ int c_cornerverts; static PR_RESMAP (hashvert_t) hvertex; #define EDGEFACE_CHUNK 4096 -int numedgefaces = 0; +size_t numedgefaces = 0; edgeface_t *edgefaces = 0; int firstmodeledge = 1; int firstmodelface; @@ -336,12 +336,12 @@ int c_tryedges; \return The edge number. For a re-used edge, the edge number will be negative, indicating the ends of the edge are reversed. */ -static int +static size_t GetEdge (const vec3_t p1, const vec3_t p2, face_t *f) { dedge_t edge; unsigned v1, v2; - int i; + size_t i; if (!f->contents[0]) Sys_Error ("GetEdge: 0 contents"); diff --git a/tools/qfbsp/source/writebsp.c b/tools/qfbsp/source/writebsp.c index 28943c145..ea535beef 100644 --- a/tools/qfbsp/source/writebsp.c +++ b/tools/qfbsp/source/writebsp.c @@ -53,10 +53,8 @@ int firstface; int FindFinalPlane (const dplane_t *p) { - const dplane_t *dplane; - int i; - - for (i = 0, dplane = bsp->planes; i < bsp->numplanes; i++, dplane++) { + for (size_t i = 0; i < bsp->numplanes; i++) { + const dplane_t *dplane = bsp->planes + i; if (p->type != dplane->type) continue; if (p->dist != dplane->dist) diff --git a/tools/qflight/source/ltface.c b/tools/qflight/source/ltface.c index de947cfff..11204f555 100644 --- a/tools/qflight/source/ltface.c +++ b/tools/qflight/source/ltface.c @@ -71,7 +71,7 @@ get_tex_name (int texindex) if (bsp->texdatasize) { mtl = (dmiptexlump_t *) bsp->texdata; miptex = bsp->texinfo[texindex].miptex; - if (mtl->dataofs[miptex] != -1) { + if (mtl->dataofs[miptex] != ~0u) { mt = (miptex_t *) (bsp->texdata + mtl->dataofs[miptex]); return mt->name; } @@ -172,7 +172,6 @@ CalcFaceVectors (lightinfo_t *l, vec3_t faceorg) static void CalcFaceExtents (lightinfo_t *l) { - int i, j, e; vec_t mins[2], maxs[2], val; dface_t *s; dvertex_t *v; @@ -185,14 +184,14 @@ CalcFaceExtents (lightinfo_t *l) tex = &bsp->texinfo[s->texinfo]; - for (i = 0; i < s->numedges; i++) { - e = bsp->surfedges[s->firstedge + i]; + for (uint32_t i = 0; i < s->numedges; i++) { + int e = bsp->surfedges[s->firstedge + i]; if (e >= 0) v = bsp->vertexes + bsp->edges[e].v[0]; else v = bsp->vertexes + bsp->edges[-e].v[1]; - for (j = 0; j < 2; j++) { + for (int j = 0; j < 2; j++) { val = DotProduct (v->point, tex->vecs[j]) + tex->vecs[j][3]; if (val < mins[j]) mins[j] = val; @@ -201,7 +200,7 @@ CalcFaceExtents (lightinfo_t *l) } } - for (i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) { l->exactmins[i] = mins[i]; l->exactmaxs[i] = maxs[i]; diff --git a/tools/qflight/source/qflight.c b/tools/qflight/source/qflight.c index db133a3b4..4f13614f9 100644 --- a/tools/qflight/source/qflight.c +++ b/tools/qflight/source/qflight.c @@ -71,7 +71,7 @@ dstring_t *lightdata; dstring_t *rgblightdata; dmodel_t *bspmodel; -int bspfileface; // next surface to dispatch +size_t bspfileface; // next surface to dispatch int bspfileent; // next entity to dispatch vec3_t bsp_origin; @@ -119,13 +119,13 @@ VisThread (void *junk) static void * LightThread (void *l) { - int i; + size_t i; while (1) { LOCK; i = bspfileface++; if (i < bsp->numfaces) { - printf ("%5d / %d\r", i, bsp->numfaces); + printf ("%5zd / %zd\r", i, bsp->numfaces); fflush (stdout); } UNLOCK; @@ -139,22 +139,21 @@ LightThread (void *l) static void FindFaceOffsets (void) { - int i, j; entity_t *ent; vec3_t org; const char *name; surfaceorgs = (vec3_t *) calloc (bsp->numfaces, sizeof (vec3_t)); - for (i = 1; i < bsp->nummodels; i++) { - ent = FindEntityWithKeyPair ("model", name = va (0, "*%d", i)); + for (size_t i = 1; i < bsp->nummodels; i++) { + ent = FindEntityWithKeyPair ("model", name = va (0, "*%zd", i)); VectorZero (org); if (!ent) Sys_Error ("FindFaceOffsets: Couldn't find entity for model %s.\n", name); if (!strncmp (ValueForKey (ent, "classname"), "rotate_", 7)) GetVectorForKey (ent, "origin", org); - for (j = 0; j < bsp->models[i].numfaces; j++) + for (uint32_t j = 0; j < bsp->models[i].numfaces; j++) VectorCopy (org, surfaceorgs[bsp->models[i].firstface]); } } diff --git a/tools/qflight/source/vis.c b/tools/qflight/source/vis.c index a4f0e1114..42eec6631 100644 --- a/tools/qflight/source/vis.c +++ b/tools/qflight/source/vis.c @@ -145,9 +145,6 @@ VisEntity (int ent_index) entity_t *entity = entities + ent_index; dleaf_t *leaf; int ignorevis = false; - int i; - unsigned j; - uint32_t *mark; byte *vis, *surfacehit; int vis_size; @@ -193,19 +190,19 @@ VisEntity (int ent_index) memset (surfacehit, 0, (bsp->numfaces + 7) / 8); DecompressVis (bsp->visdata + leaf->visofs, vis, vis_size); - for (i = 0, leaf = bsp->leafs + 1; i < bsp->models[0].visleafs; - i++, leaf++) { + for (uint32_t i = 0; i < bsp->models[0].visleafs; i++) { + leaf = bsp->leafs + 1 + i; if (!leaf->nummarksurfaces) continue; if (vis[i >> 3] & (1 << (i & 7))) { - for (j = 0, mark = bsp->marksurfaces + leaf->firstmarksurface; - j < leaf->nummarksurfaces; j++, mark++) { - mark_face (*mark, surfacehit, entity); + uint32_t *mark = bsp->marksurfaces + leaf->firstmarksurface; + for (size_t j = 0; j < leaf->nummarksurfaces; j++) { + mark_face (*mark++, surfacehit, entity); } } } - for (i = 1; i < bsp->nummodels; i++) { - for (j = 0; (int) j < bsp->models[i].numfaces; j++) { + for (size_t i = 1; i < bsp->nummodels; i++) { + for (uint32_t j = 0; j < bsp->models[i].numfaces; j++) { //FIXME vis mark_face (bsp->models[i].firstface + j, surfacehit, entity); } @@ -216,8 +213,6 @@ VisEntity (int ent_index) void VisStats (void) { - int i, count; - printf ("%4i lights\n", counts.lights); printf ("%4i air\n", counts.empty); printf ("%4i solid\n", counts.solid); @@ -227,10 +222,11 @@ VisStats (void) printf ("%4i sky\n", counts.sky); printf ("%4i unknown\n", counts.misc); - for (i = count = 0; i < bsp->numfaces; i++) + size_t count = 0; + for (size_t i = 0; i < bsp->numfaces; i++) if (surfacelightchain[i]) count++; - printf ("%i faces, %i (%i%%) may receive light\n", bsp->numfaces, + printf ("%zd faces, %zd (%zd%%) may receive light\n", bsp->numfaces, count, count * 100 / bsp->numfaces); if (counts.solid || counts.sky) printf ("warning: %i lights of %i lights (%i%%) were found in sky\n" @@ -238,6 +234,6 @@ VisStats (void) "out of the solid or sky to accelerate compiling\n", counts.solid + counts.sky, counts.lights, (counts.solid + counts.sky) * 100 / counts.lights); - printf ("%i lights will be cast onto %i surfaces, %i casts will " + printf ("%i lights will be cast onto %zd surfaces, %i casts will " "be performed\n", counts.lights, bsp->numfaces, counts.cast); } diff --git a/tools/qfvis/source/soundphs.c b/tools/qfvis/source/soundphs.c index a74cf5c88..51b4ddbc7 100644 --- a/tools/qfvis/source/soundphs.c +++ b/tools/qfvis/source/soundphs.c @@ -70,21 +70,20 @@ static byte *surf_ambients; static void SurfaceBBox (dface_t *s, vec3_t mins, vec3_t maxs) { - int vi, e, i, j; - float *v; - mins[0] = mins[1] = mins[2] = 999999; maxs[0] = maxs[1] = maxs[2] = -99999; - for (i = 0; i < s->numedges; i++) { - e = bsp->surfedges[s->firstedge + i]; + for (uint32_t i = 0; i < s->numedges; i++) { + int e = bsp->surfedges[s->firstedge + i]; + int vi; + if (e >= 0) vi = bsp->edges[e].v[0]; else vi = bsp->edges[-e].v[1]; - v = bsp->vertexes[vi].point; + float *v = bsp->vertexes[vi].point; - for (j = 0; j < 3; j++) { + for (int j = 0; j < 3; j++) { if (v[j] < mins[j]) mins[j] = v[j]; if (v[j] > maxs[j]) @@ -104,7 +103,7 @@ init_surf_ambients (void) dmiptexlump_t *miptex = (dmiptexlump_t *) bsp->texdata; - for (int i = 0; i < bsp->numfaces; i++) { + for (size_t i = 0; i < bsp->numfaces; i++) { dface_t *surf = &bsp->faces[i]; texinfo_t *info = &bsp->texinfo[surf->texinfo]; int ofs = miptex->dataofs[info->miptex]; From f514345d7778358daf31d60873f82ca4f29bc592 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Aug 2021 22:05:31 +0900 Subject: [PATCH 1712/3664] [qfbsp] Show correct object counts for bsp29 files Yes, this was the goal of that size_t change, but it made sense anyway. --- tools/qfbsp/source/info.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/tools/qfbsp/source/info.c b/tools/qfbsp/source/info.c index 92a5d2abc..b5477c02e 100644 --- a/tools/qfbsp/source/info.c +++ b/tools/qfbsp/source/info.c @@ -19,23 +19,23 @@ typedef struct lumpinfo_s { int size; } lumpinfo_t; -#define S(f) sizeof (*((bsp_t *)0)->f) +#define O(f) field_offset (bsp_t, f) static lumpinfo_t lump_info[] = { - { "entities", S(entdata) }, - { "planes", S(planes) }, - { "textures", S(texdata) }, - { "vertices", S(vertexes) }, - { "visibility", S(visdata) }, - { "nodes", S(nodes) }, - { "texinfo", S(texinfo) }, - { "faces", S(faces) }, - { "lighting", S(lightdata) }, - { "clipnodes", S(clipnodes) }, - { "leafs", S(leafs) }, - { "marksurfaces", S(marksurfaces) }, - { "edges", S(edges) }, - { "surfedges", S(surfedges) }, - { "models", S(models) }, + { "entities", O(entdatasize) }, + { "planes", O(numplanes) }, + { "textures", O(texdatasize) }, + { "vertices", O(numvertexes) }, + { "visibility", O(visdatasize) }, + { "nodes", O(numnodes) }, + { "texinfo", O(numtexinfo) }, + { "faces", O(numfaces) }, + { "lighting", O(lightdatasize) }, + { "clipnodes", O(numclipnodes) }, + { "leafs", O(numleafs) }, + { "marksurfaces", O(nummarksurfaces) }, + { "edges", O(numedges) }, + { "surfedges", O(numsurfedges) }, + { "models", O(nummodels) }, }; void @@ -45,9 +45,10 @@ bspinfo () for (int i = 0; i < HEADER_LUMPS; i++) { lump_t *lump = &bsp->header->lumps[i]; lumpinfo_t *info = &lump_info[i]; + size_t *size = (size_t *)((byte *) bsp + info->size); - printf (" %-12s: %7d %7d %7d\n", info->name, - lump->fileofs, lump->filelen, lump->filelen / info->size); + printf (" %-12s: %7d %7d %7zd\n", info->name, + lump->fileofs, lump->filelen, *size); } for (unsigned i = 0; i < bsp->nummodels; i++) { From e4984aad17c6f30c196d4ea9cf51ab4d077a9678 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Aug 2021 10:41:16 +0900 Subject: [PATCH 1713/3664] [util] Add functions for binary heaps Sink, swim, build and sort, both "simple" and with a data parameter for the compare function. --- include/QF/Makemodule.am | 1 + include/QF/fbsearch.h | 6 +- include/QF/heapsort.h | 61 ++++++++++++ libs/util/Makemodule.am | 1 + libs/util/heapsort.c | 146 +++++++++++++++++++++++++++ libs/util/test/Makemodule.am | 5 + libs/util/test/test-heapsort.c | 175 +++++++++++++++++++++++++++++++++ 7 files changed, 392 insertions(+), 3 deletions(-) create mode 100644 include/QF/heapsort.h create mode 100644 libs/util/heapsort.c create mode 100644 libs/util/test/test-heapsort.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index e0f9ebb07..8f8379c01 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -18,6 +18,7 @@ include_qf = \ include/QF/fbsearch.h \ include/QF/gib.h \ include/QF/hash.h \ + include/QF/heapsort.h \ include/QF/idparse.h \ include/QF/image.h \ include/QF/in_event.h \ diff --git a/include/QF/fbsearch.h b/include/QF/fbsearch.h index b6463969a..19611f3c5 100644 --- a/include/QF/fbsearch.h +++ b/include/QF/fbsearch.h @@ -25,8 +25,8 @@ */ -#ifndef __QF_bsearch_h -#define __QF_bsearch_h +#ifndef __QF_fbsearch_h +#define __QF_fbsearch_h #include @@ -46,4 +46,4 @@ void *fbsearch (const void *key, const void *base, size_t nmemb, size_t size, void *fbsearch_r (const void *key, const void *base, size_t nmemb, size_t size, __compar_d_fn_t cmp, void *arg); -#endif//__QF_bsearch_h +#endif//__QF_fbsearch_h diff --git a/include/QF/heapsort.h b/include/QF/heapsort.h new file mode 100644 index 000000000..153c4faee --- /dev/null +++ b/include/QF/heapsort.h @@ -0,0 +1,61 @@ +/* + heapsort.h + + Priority heap related functions + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_heapsort_h +#define __QF_heapsort_h + +#include + +#ifndef __compar_fn_t_defined +#define __compar_fn_t_defined +typedef int (*__compar_fn_t)(const void *, const void *); +#endif + +#ifndef __compar_d_fn_t_defined +#define __compar_d_fn_t_defined +typedef int (*__compar_d_fn_t)(const void *, const void *, void *); +#endif + +void heap_sink (void *base, size_t ind, size_t nmemb, size_t size, + __compar_fn_t cmp); +void heap_sink_r (void *base, size_t ind, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg); + +void heap_swim (void *base, size_t ind, size_t nmemb, size_t size, + __compar_fn_t cmp); +void heap_swim_r (void *base, size_t ind, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg); + +void heap_build (void *base, size_t nmemb, size_t size, __compar_fn_t cmp); +void heap_build_r (void *base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg); + +void heapsort (void *base, size_t nmemb, size_t size, __compar_fn_t cmp); +void heapsort_r (void *base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg); + +#endif//__QF_heapsort_h diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am index 827696908..6e0dbbb23 100644 --- a/libs/util/Makemodule.am +++ b/libs/util/Makemodule.am @@ -56,6 +56,7 @@ libs_util_libQFutil_la_SOURCES= \ libs/util/dstring.c \ libs/util/fendian.c \ libs/util/hash.c \ + libs/util/heapsort.c \ libs/util/idparse.c \ libs/util/info.c \ libs/util/link.c \ diff --git a/libs/util/heapsort.c b/libs/util/heapsort.c new file mode 100644 index 000000000..aca74e574 --- /dev/null +++ b/libs/util/heapsort.c @@ -0,0 +1,146 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "QF/heapsort.h" +#include "QF/qtypes.h" + +static inline void +swap_elements (void *a, void *b, size_t size) +{ + byte tmp[size]; + memcpy (tmp, a, size); + memcpy (a, b, size); + memcpy (b, tmp, size); +} + +VISIBLE void +heap_sink (void *base, size_t ind, size_t nmemb, size_t size, + __compar_fn_t cmp) +{ + size_t left_ind = 2 * ind + 1; + size_t right_ind = 2 * ind + 2; + void *node = (byte *) base + ind * size; + void *left = (byte *) base + left_ind * size; + void *right = (byte *) base + right_ind * size; + + size_t largest_ind = ind; + void *largest = node; + + if (left_ind < nmemb && cmp (left, node) > 0) { + largest = left; + largest_ind = left_ind; + } + if (right_ind < nmemb && cmp (right, largest) > 0) { + largest = right; + largest_ind = right_ind; + } + if (largest_ind != ind) { + swap_elements (largest, node, size); + heap_sink (base, largest_ind, nmemb, size, cmp); + } +} + +VISIBLE void +heap_sink_r (void *base, size_t ind, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg) +{ + size_t left_ind = 2 * ind + 1; + size_t right_ind = 2 * ind + 2; + void *node = (byte *) base + ind * size; + void *left = (byte *) base + left_ind * size; + void *right = (byte *) base + right_ind * size; + + size_t largest_ind = ind; + void *largest = node; + + if (left_ind < nmemb && cmp (left, node, arg) > 0) { + largest = left; + largest_ind = left_ind; + } + if (right_ind < nmemb && cmp (right, largest, arg) > 0) { + largest = right; + largest_ind = right_ind; + } + if (largest_ind != ind) { + swap_elements (largest, node, size); + heap_sink_r (base, largest_ind, nmemb, size, cmp, arg); + } +} + +VISIBLE void +heap_swim (void *base, size_t ind, size_t nmemb, size_t size, + __compar_fn_t cmp) +{ + size_t parent_ind = (ind - 1) / 2; + void *node = (byte *) base + ind * size; + void *parent = (byte *) base + parent_ind * size; + + if (ind > 0 && cmp (node, parent) > 0) { + swap_elements (node, parent, size); + heap_swim (base, parent_ind, nmemb, size, cmp); + } +} + +VISIBLE void +heap_swim_r (void *base, size_t ind, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg) +{ + size_t parent_ind = (ind - 1) / 2; + void *node = (byte *) base + ind * size; + void *parent = (byte *) base + parent_ind * size; + + if (ind > 0 && cmp (node, parent, arg) > 0) { + swap_elements (node, parent, size); + heap_swim_r (base, parent_ind, nmemb, size, cmp, arg); + } +} + +VISIBLE void +heap_build (void *base, size_t nmemb, size_t size, __compar_fn_t cmp) +{ + if (nmemb < 2) { + return; + } + for (size_t i = nmemb / 2; i-- > 0; ) { + heap_sink (base, i, nmemb, size, cmp); + } +} + +VISIBLE void +heap_build_r (void *base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg) +{ + if (nmemb < 2) { + return; + } + for (size_t i = nmemb / 2; i-- > 0; ) { + heap_sink_r (base, i, nmemb, size, cmp, arg); + } +} + +VISIBLE void +heapsort (void *base, size_t nmemb, size_t size, __compar_fn_t cmp) +{ + heap_build (base, nmemb, size, cmp); + for (size_t i = nmemb; i-- > 1; ) { + void *last = (byte *) base + i * size; + swap_elements (base, last, size); + heap_sink (base, 0, i, size, cmp); + } +} + +VISIBLE void +heapsort_r (void *base, size_t nmemb, size_t size, __compar_d_fn_t cmp, + void *arg) +{ + heap_build_r (base, nmemb, size, cmp, arg); + for (size_t i = nmemb; i-- > 1; ) { + void *last = (byte *) base + i * size; + swap_elements (base, last, size); + heap_sink_r (base, 0, i, size, cmp, arg); + } +} diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 4a0e2734c..3b1510082 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -9,6 +9,7 @@ libs_util_tests = \ libs/util/test/test-darray \ libs/util/test/test-dq \ libs/util/test/test-half \ + libs/util/test/test-heapsort \ libs/util/test/test-mat3 \ libs/util/test/test-mat4 \ libs/util/test/test-plist \ @@ -65,6 +66,10 @@ libs_util_test_test_half_SOURCES=libs/util/test/test-half.c libs_util_test_test_half_LDADD=libs/util/libQFutil.la libs_util_test_test_half_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_heapsort_SOURCES=libs/util/test/test-heapsort.c +libs_util_test_test_heapsort_LDADD=libs/util/libQFutil.la +libs_util_test_test_heapsort_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_mat3_SOURCES=libs/util/test/test-mat3.c libs_util_test_test_mat3_LDADD=libs/util/libQFutil.la libs_util_test_test_mat3_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-heapsort.c b/libs/util/test/test-heapsort.c new file mode 100644 index 000000000..d3841cc2c --- /dev/null +++ b/libs/util/test/test-heapsort.c @@ -0,0 +1,175 @@ +/* + test-heapsort.c + + Priority heap related tests + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "QF/heapsort.h" + +#define SIZEOF(x) (sizeof(x) / sizeof(x[0])) + +static int sink_data[] = { + 4, 7, 8, 3, 2, 6, 5, +}; +static int sink_expect[] = { + 8, 7, 6, 3, 2, 4, 5, +}; + +static int swim_data[] = { + 10, 8, 9, 7, 4, 1, 3, 2, +}; +static int swim_expect[] = { + 10, 8, 9, 7, 4, 1, 3, 2, +}; + +static int swim_data2[] = { + 10, 8, 9, 7, 4, 1, 3, 0, 2, 5, +}; +static int swim_expect2[] = { + 10, 8, 9, 7, 5, 1, 3, 0, 2, 4, +}; + +static int build_data[] = { + 1, 4, 3, 7, 8, 9, 10, +}; +static int build_expect1[] = { + 10, 8, 9, 7, 4, 1, 3, +}; +static int build_expect2[] = { + 9, 8, 3, 7, 4, 1, 10, +}; +static int build_expect3[] = { + 8, 7, 3, 1, 4, 9, 10, +}; + +static int sort_data[] = { + 4, 3, 7, 1, 8, 5, +}; +static int sort_expect[] = { + 1, 3, 4, 5, 7, 8, +}; + +static int +compare (const void *a, const void *b) +{ + return *(const int *)a - *(const int *)b; +} +#if 0 +static int +compared (const void *a, const void *b, void *d) +{ + return *(const int *)a - *(const int *)b; +} +#endif + +static void +test_sink (int *data, size_t nele) +{ + heap_sink (data, 0, nele, sizeof (int), compare); +} + +static void +test_swim (int *data, size_t nele) +{ + heap_swim (data, nele - 1, nele, sizeof (int), compare); +} + +static void +test_build (int *data, size_t nele) +{ + heap_build (data, nele, sizeof (int), compare); +} + +static void +test_sort (int *data, size_t nele) +{ + heapsort (data, nele, sizeof (int), compare); +} + +typedef struct { + const int *data; + const int *expect; + size_t nele; + void (*test) (int *data, size_t nele); + size_t sub; +} test_t; + +static test_t tests[] = { + { sink_data, sink_expect, SIZEOF (sink_data), test_sink }, + { swim_data, swim_expect, SIZEOF (swim_data), test_swim }, + { swim_data2, swim_expect2, SIZEOF (swim_data2), test_swim }, + { build_data, build_expect1, SIZEOF (build_data), test_build }, + { build_data, build_expect2, SIZEOF (build_data), test_build, 1 }, + { build_data, build_expect3, SIZEOF (build_data), test_build, 2 }, + { sort_data, sort_expect, SIZEOF (sort_data), test_sort }, +}; +#define num_tests ((int) SIZEOF (tests)) + +static void +dump_array (const int *arr, size_t n) +{ + while (n-- > 0) { + printf (" %d", *arr++); + } + printf ("\n"); +} + +static int +run_test (test_t *test) +{ + int test_data[test->nele]; + + memcpy (test_data, test->data, test->nele * sizeof (int)); + printf ("start : "); + dump_array (test_data, test->nele); + test->test (test_data, test->nele - test->sub); + printf ("got : "); + dump_array (test_data, test->nele); + printf ("expect: "); + dump_array (test->expect, test->nele); + if (memcmp (test_data, test->expect, test->nele * sizeof (int))) { + return 0; + } + return 1; +} + +int +main(int argc, const char **argv) +{ + int ret = 0; + + for (int i = 0; i < num_tests; i++) { + if (!run_test (&tests[i])) { + printf ("test %d failed\n", i); + ret = 1; + } + } + return ret; +} From 4f2113bc05a0bcdd9935652ce96343a69c1c238c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Aug 2021 12:07:18 +0900 Subject: [PATCH 1714/3664] [util] Enable accidentally disabled seb tests --- libs/util/test/test-sebvf.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/util/test/test-sebvf.c b/libs/util/test/test-sebvf.c index 9b0d93a7f..3cc3df9d5 100644 --- a/libs/util/test/test-sebvf.c +++ b/libs/util/test/test-sebvf.c @@ -182,7 +182,6 @@ struct { int num_points; vspheref_t expect; } tests[] = { -#if 0 {0, 0, {{ 0, 0, 0, 1}, 0}}, {points, 1, {{-1, -1, 1, 1}, 0}}, {points, 2, {{ 0, 0, 1, 1}, 1.41421356}}, @@ -202,7 +201,6 @@ struct { {{284.117493, 624.235535, 2959.76489}, 0.352925777}}, {tears_cluster2, SIZEOF (tears_cluster2), {{-2192, -256.000031, -736}, 103.479492}},//FIXME numbers? -#endif {cloud_points, SIZEOF (cloud_points), {{2.20056152, 2.23369908, 2.2332375}, 0.88327992}}, }; From f76964b86bb6fd83a3996f74e06050b7c050e662 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Aug 2021 13:29:55 +0900 Subject: [PATCH 1715/3664] [util] Add an priority queue implementation Done via macros (like darray and ringbuffer). Might prove useful for qfvis and maybe dynamic lights. --- include/QF/Makemodule.am | 1 + include/QF/pqueue.h | 124 +++++++++++++++++ libs/util/test/Makemodule.am | 5 + libs/util/test/test-pqueue.c | 254 +++++++++++++++++++++++++++++++++++ 4 files changed, 384 insertions(+) create mode 100644 include/QF/pqueue.h create mode 100644 libs/util/test/test-pqueue.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 8f8379c01..af3c99982 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -42,6 +42,7 @@ include_qf = \ include/QF/png.h \ include/QF/plist.h \ include/QF/plugin.h \ + include/QF/pqueue.h \ include/QF/pr_comp.h \ include/QF/pr_debug.h \ include/QF/pr_obj.h \ diff --git a/include/QF/pqueue.h b/include/QF/pqueue.h new file mode 100644 index 000000000..a9428ae48 --- /dev/null +++ b/include/QF/pqueue.h @@ -0,0 +1,124 @@ +/* + pqueue.h + + Priority Queues + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/08/02 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_pqueue_h +#define __QF_pqueue_h + +#include + +#include "QF/heapsort.h" +#include "QF/sys.h" + +/** \defgroup pqueue Priority Queues + \ingroup utils + + Priority queue management +*/ +///@{ + +/** The structure def for a priority queue with elements of the given type. + + This is just the def of a struct delcaration: it is useless on its own. + The intended usage is something like: + + typedef struct priority_queue_s PQUEUE_TYPE (int) priority_queue_t; + + This allows full flexibility in just how the actual type is used. + + The \a size field is the number of elements currently in the queue, and + the \a maxSize field is the number of elements the queue can hold. The + priority queue functions will never resize the array. However, with a + little glue logic, priority queues can be used with dynamic arrays. + + \param T The type to use for the element array, which is accessed + by the \a a field. +*/ +#define PQUEUE_TYPE(T) \ + { \ + size_t size; \ + size_t maxSize; \ + T *a; \ + int (*compare) (const T *a, const T *b, void *data); \ + void *data; \ + } + +#define PQUEUE_IS_EMPTY(queue) ((queue)->size == 0) + +#define PQUEUE_IS_FULL(queue) \ + ({ \ + __auto_type q = (queue); \ + q->size == q->maxSize; \ + }) + +#define PQUEUE_PEEK(queue) ((queue)->a[0]) + +#define PQUEUE_INSERT(queue, value) \ + do { \ + __auto_type q = (queue); \ + if (PQUEUE_IS_FULL (q)) { \ + Sys_Error ("Priority queue full"); \ + } \ + q->a[q->size++] = (value); \ + heap_swim_r (q->a, q->size - 1, q->size, sizeof (q->a[0]), \ + (__compar_d_fn_t) q->compare, q->data); \ + } while (0) + +#define PQUEUE_REMOVE(queue) \ + ({ \ + __auto_type q = (queue); \ + if (PQUEUE_IS_EMPTY (q)) { \ + Sys_Error ("Priority queue empty"); \ + } \ + __auto_type value = q->a[0]; \ + q->a[0] = q->a[--q->size]; \ + heap_sink_r (q->a, 0, q->size, sizeof (q->a[0]), \ + (__compar_d_fn_t) q->compare, q->data); \ + value; \ + }) + +#define PQUEUE_ADJUST(queue, index) \ + do { \ + __auto_type q = (queue); \ + size_t ind = (index); \ + if (ind >= q->size) { \ + Sys_Error ("Priority queue index error"); \ + } \ + if (ind>0 && q->compare(q->a + ind, q->a + (ind-1)/2, q->data)>0) { \ + heap_swim_r (q->a, ind, q->size, sizeof (q->a[0]), \ + (__compar_d_fn_t) q->compare, q->data); \ + } else { \ + heap_sink_r (q->a, ind, q->size, sizeof (q->a[0]), \ + (__compar_d_fn_t) q->compare, q->data); \ + } \ + } while (0) + +///@} + +#endif//__QF_pqueue_h diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 3b1510082..ed3b0bb99 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -13,6 +13,7 @@ libs_util_tests = \ libs/util/test/test-mat3 \ libs/util/test/test-mat4 \ libs/util/test/test-plist \ + libs/util/test/test-pqueue \ libs/util/test/test-qfs \ libs/util/test/test-quat \ libs/util/test/test-seb \ @@ -82,6 +83,10 @@ libs_util_test_test_plist_SOURCES=libs/util/test/test-plist.c libs_util_test_test_plist_LDADD=libs/util/libQFutil.la libs_util_test_test_plist_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_pqueue_SOURCES=libs/util/test/test-pqueue.c +libs_util_test_test_pqueue_LDADD=libs/util/libQFutil.la +libs_util_test_test_pqueue_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_qfs_SOURCES=libs/util/test/test-qfs.c libs_util_test_test_qfs_LDADD=libs/util/libQFutil.la libs_util_test_test_qfs_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-pqueue.c b/libs/util/test/test-pqueue.c new file mode 100644 index 000000000..4e877c569 --- /dev/null +++ b/libs/util/test/test-pqueue.c @@ -0,0 +1,254 @@ +/* + test-pqueue.c + + Priority queue related tests + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "QF/pqueue.h" + +#define SIZEOF(x) (sizeof(x) / sizeof(x[0])) + +static int +compare (const int *a, const int *b, void *arg) +{ + //printf ("%d %d\n", *a, *b); + return *a - *b; +} + +static int +rev (const int *a, const int *b, void *arg) +{ + return *b - *a; +} + +static int queue_array[7]; +static struct PQUEUE_TYPE (int) pqueue = { + .maxSize = SIZEOF (queue_array), + .compare = compare, + .a = queue_array, + .data = 0, +}; + +static int +pq_is_empty (void) +{ + return PQUEUE_IS_EMPTY (&pqueue); +} + +static int +pq_is_full (void) +{ + return PQUEUE_IS_FULL (&pqueue); +} + +static int +pq_peek (void) +{ + return PQUEUE_PEEK (&pqueue); +} + +static void +pq_insert (int value) +{ + PQUEUE_INSERT (&pqueue, value); +} + +static int +pq_remove (void) +{ + return PQUEUE_REMOVE (&pqueue); +} + +static void +pq_adjust (int index) +{ + PQUEUE_ADJUST (&pqueue, index); +} + +static void +dump_array (const int *arr, size_t n) +{ + while (n-- > 0) { + printf (" %d", *arr++); + } + printf ("\n"); +} + + +static int +test_insert (const int *data, size_t count) +{ + while (count-- > 0) { + pq_insert (*data++); + } + return 1; +} + +static int +test_remove (const int *data, size_t count) +{ + while (count-- > 0) { + if (pq_remove () != *data++) { + return 0; + } + } + return 1; +} + +static int +test_adjust (const int *data, size_t count) +{ + //printf ("adjust start\n"); + pqueue.a[count] = *data; + pq_adjust (count); + //printf ("adjust end\n"); + return 1; +} + +static int +test_peek (const int *data, size_t count) +{ + return pq_peek () == *data; +} + +static int +test_size (const int *data, size_t count) +{ + return pqueue.size == count; +} + +static int +test_is_empty (const int *data, size_t count) +{ + return pq_is_empty () == *data; +} + +static int +test_is_full (const int *data, size_t count) +{ + return pq_is_full () == *data; +} + +static int +dump_queue (const int *data, size_t count) +{ + if (0) { + dump_array (pqueue.a, pqueue.size); + } + return 1; +} + +static int true = 1; +static int false = 0; + +static int data[] = { 3, 2, 5, 6, 8, 1, 9 }; +static int data1[] = { 3, 7, 5, 6, 8, 1, 9 }; +static int data2[] = { 3, 7, 5, 6, 8, 1, 4 }; +static int data3[] = { 3, 7, 0, 6, 8, 1, 4 }; +static int sort[SIZEOF(data)]; +static int sort1[SIZEOF(data1)]; +static int sort2[SIZEOF(data2)]; +static int sort3[SIZEOF(data3)]; + +typedef struct { + const int *data; + size_t nele; + int (*test) (const int *data, size_t nele); +} test_t; + +static test_t tests[] = { + { &true, 1, test_is_empty }, + { &false, 1, test_is_full }, + { 0, 0, test_size }, + + { data + 0, 1, test_insert }, + { 0, 1, test_size }, + { &false, 1, test_is_empty }, + { &false, 1, test_is_full }, + { data + 0, 1, test_peek }, + { data + 0, 1, test_remove }, + { &true, 1, test_is_empty }, + { &false, 1, test_is_full }, + { 0, 0, test_size }, + + { data + 0, 3, test_insert }, + { 0, 3, test_size }, + { data + 2, 1, test_peek }, + { data + 2, 1, test_remove }, + { data + 0, 1, test_remove }, + { data + 1, 1, test_remove }, + { &true, 1, test_is_empty }, + + { data + 0, SIZEOF(data), test_insert }, + { 0, SIZEOF(data), test_size }, + { &false, 1, test_is_empty }, + { &true, 1, test_is_full }, + { 0, 0, dump_queue }, + { sort1 + 2, 3, test_adjust }, + { 0, 0, dump_queue }, + { sort2 + 4, 0, test_adjust }, + { 0, 0, dump_queue }, + { sort3 + 7, 4, test_adjust }, + { 0, 0, dump_queue }, + { sort3 + 0, SIZEOF(sort), test_remove }, +}; +#define num_tests ((int) SIZEOF (tests)) + +static int +run_test (const test_t *test) +{ + return test->test (test->data, test->nele); +} + +int +main(int argc, const char **argv) +{ + int ret = 0; + + memcpy (sort, data, sizeof (sort)); + memcpy (sort1, data1, sizeof (sort1)); + memcpy (sort2, data2, sizeof (sort2)); + memcpy (sort3, data3, sizeof (sort3)); + heapsort_r (sort, SIZEOF(sort), sizeof(int), (__compar_d_fn_t)rev, 0); + heapsort_r (sort1, SIZEOF(sort1), sizeof(int), (__compar_d_fn_t)rev, 0); + heapsort_r (sort2, SIZEOF(sort2), sizeof(int), (__compar_d_fn_t)rev, 0); + heapsort_r (sort3, SIZEOF(sort3), sizeof(int), (__compar_d_fn_t)rev, 0); + //dump_array (sort, SIZEOF(sort)); + //dump_array (sort1, SIZEOF(sort1)); + //dump_array (sort2, SIZEOF(sort2)); + //dump_array (sort3, SIZEOF(sort3)); + for (int i = 0; i < num_tests; i++) { + if (!run_test (&tests[i])) { + printf ("test %d failed\n", i); + ret = 1; + } + } + return ret; +} From d99fb01b6502c7e1d8aec90ce63948e702de8599 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Aug 2021 13:47:00 +0900 Subject: [PATCH 1716/3664] [build] Fix some distcheck bitrot --- config.d/build_control.m4 | 2 ++ include/QF/Makemodule.am | 5 +++++ libs/video/renderer/Makemodule.am | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 1fb6f3d9b..5564ea8af 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -326,6 +326,7 @@ if test x"${top_need_libs}" = xyes; then qfac_include_qf_plugin="\$(include_qf_plugin)" qfac_include_qf_scene="\$(include_qf_scene)" qfac_include_qf_simd="\$(include_qf_simd)" + qfac_include_qf_ui="\$(include_qf_ui)" qfac_include_qf_vulkan="\$(include_qf_vulkan)" fi QF_SUBST(qfac_include_qf) @@ -335,6 +336,7 @@ QF_SUBST(qfac_include_qf_math) QF_SUBST(qfac_include_qf_plugin) QF_SUBST(qfac_include_qf_scene) QF_SUBST(qfac_include_qf_simd) +QF_SUBST(qfac_include_qf_ui) QF_SUBST(qfac_include_qf_vulkan) progs_gz= diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index af3c99982..8008d89c2 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -48,6 +48,7 @@ include_qf = \ include/QF/pr_obj.h \ include/QF/pr_type.h \ include/QF/progs.h \ + include/QF/pvsfile.h \ include/QF/qargs.h \ include/QF/qdefs.h \ include/QF/qendian.h \ @@ -67,6 +68,7 @@ include_qf = \ include/QF/sound.h \ include/QF/spritegn.h \ include/QF/sys.h \ + include/QF/sys_developer.h \ include/QF/teamplay.h \ include/QF/tga.h \ include/QF/va.h \ @@ -189,6 +191,7 @@ qf_math_includedir = $(includedir)/QF/math qf_plugin_includedir = $(includedir)/QF/plugin qf_scene_includedir = $(includedir)/QF/scene qf_simd_includedir = $(includedir)/QF/simd +qf_ui_includedir = $(includedir)/QF/ui qf_vulkan_includedir = $(includedir)/QF/Vulkan qf_include_HEADERS = @qfac_include_qf@ qf_gl_include_HEADERS = @qfac_include_qf_gl@ @@ -197,6 +200,7 @@ qf_math_include_HEADERS = @qfac_include_qf_math@ qf_plugin_include_HEADERS = @qfac_include_qf_plugin@ qf_scene_include_HEADERS = @qfac_include_qf_scene@ qf_simd_include_HEADERS = @qfac_include_qf_simd@ +qf_ui_include_HEADERS = @qfac_include_qf_ui@ qf_vulkan_include_HEADERS = @qfac_include_qf_vulkan@ ruamoko_qf_includedir = $(ruamoko_includedir)/QF @@ -210,5 +214,6 @@ EXTRA_HEADERS += \ $(include_qf_plugin) \ $(include_qf_scene) \ $(include_qf_simd) \ + $(include_qf_ui) \ $(include_qf_vulkan) \ $(qfcc_include_qf) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 37b0f5a72..9fc6fced0 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -424,7 +424,7 @@ CLEANFILES += \ libs/video/renderer/vulkan/*.plc \ libs/video/renderer/vulkan/shader/*.spv \ libs/video/renderer/vulkan/shader/*.spvc \ - libs/video/renderer/vulkan/vkgen.sym \ + vkgen.sym \ $(vkparse_src) BUILT_SOURCES += $(shader_gen) @@ -442,7 +442,7 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/alias.vert \ libs/video/renderer/vulkan/shader/alias_depth.vert \ libs/video/renderer/vulkan/shader/alias_gbuf.frag \ - libs/video/renderer/vulkan/shader/alias_shadow.frag \ + libs/video/renderer/vulkan/shader/alias_shadow.vert \ libs/video/renderer/vulkan/shader/bsp_depth.vert \ libs/video/renderer/vulkan/shader/bsp_gbuf.frag \ libs/video/renderer/vulkan/shader/bsp_gbuf.geom \ From ec54c542262bd745c56c2d13b52cd98d69b7d475 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Aug 2021 14:02:41 +0900 Subject: [PATCH 1717/3664] [build] Fix some windows bitrot --- libs/video/renderer/glsl/glsl_bsp.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- libs/video/targets/in_sdl.c | 4 ++-- libs/video/targets/in_win.c | 4 ++-- tools/bsp2img/bsp2img.c | 10 +++++----- tools/qfvis/source/base-vis.c | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 840936b42..bdaede468 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -581,7 +581,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) glsltex_t *tex; if (j == dm->firstface + dm->numfaces) { dm++; - if (dm - brush->submodels == brush->numsubmodels) { + if (dm == brush->submodels + brush->numsubmodels) { // limit the surfaces // probably never hit Sys_Printf ("R_BuildDisplayLists: too many surfaces\n"); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index bbc844a91..bcf1b31b4 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -426,7 +426,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) if (j == dm->firstface + dm->numfaces) { // move on to the next sub-model dm++; - if (dm - brush->submodels == brush->numsubmodels) { + if (dm == brush->submodels + brush->numsubmodels) { // limit the surfaces // probably never hit Sys_Printf ("R_BuildDisplayLists: too many surfaces\n"); diff --git a/libs/video/targets/in_sdl.c b/libs/video/targets/in_sdl.c index 990a74b77..7ad9c727d 100644 --- a/libs/video/targets/in_sdl.c +++ b/libs/video/targets/in_sdl.c @@ -71,7 +71,7 @@ event_focusin (void) } static void -sdl_keydest_callback (keydest_t key_dest) +sdl_keydest_callback (keydest_t key_dest, void *data) { if (key_dest == key_game) SDL_EnableKeyRepeat (0, SDL_DEFAULT_REPEAT_INTERVAL); @@ -588,7 +588,7 @@ IN_LL_Init (void) { SDL_EnableUNICODE (1); // Enable UNICODE translation for keyboard input - Key_KeydestCallback (sdl_keydest_callback); + Key_KeydestCallback (sdl_keydest_callback, 0); if (COM_CheckParm ("-nomouse")) return; diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index 1d4ee1cb1..aad54f42b 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -348,7 +348,7 @@ in_paste_buffer_f (void) } static void -win_keydest_callback (keydest_t key_dest) +win_keydest_callback (keydest_t key_dest, void *data) { win_in_game = key_dest == key_game; if (win_in_game) { @@ -367,7 +367,7 @@ IN_LL_Init (void) IN_StartupMouse (); - Key_KeydestCallback (win_keydest_callback); + Key_KeydestCallback (win_keydest_callback, 0); Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, "Paste the contents of the C&P buffer to the console"); } diff --git a/tools/bsp2img/bsp2img.c b/tools/bsp2img/bsp2img.c index 6a1c6ea7a..5301e09fe 100644 --- a/tools/bsp2img/bsp2img.c +++ b/tools/bsp2img/bsp2img.c @@ -73,8 +73,8 @@ Thanks fly to Id for a hackable game! :) /* MW */ typedef struct edge_extra_t { - long num_face_ref; - long ref_faces[MAX_REF_FACES]; // which faces are referenced + uint32_t num_face_ref; + uint32_t ref_faces[MAX_REF_FACES]; // which faces are referenced dvertex_t ref_faces_normal[MAX_REF_FACES]; // normal of referenced // faces int ref_faces_area[MAX_REF_FACES]; // area of the referenced faces @@ -531,7 +531,7 @@ create_image (long width, long height) static image_t * render_map (bsp_t *bsp) { - long j = 0, k = 0, x = 0; + uint32_t j = 0, k = 0, x = 0; dvertex_t *vertexlist, *vert1, *vert2; dedge_t *edgelist; @@ -563,7 +563,7 @@ render_map (bsp_t *bsp) edge_extra = malloc (sizeof (struct edge_extra_t) * bsp->numedges); if (edge_extra == NULL) { fprintf (stderr, "Error allocating %ld bytes for extra edge info.", - (long) sizeof (struct edge_extra_t) * bsp->numedges); + (long) (sizeof (struct edge_extra_t) * bsp->numedges)); exit (2); } /* initialize the array */ @@ -842,7 +842,7 @@ render_map (bsp_t *bsp) } printf ("%zd edges plotted", bsp->numedges); if (options.edgeremove) { - printf (" (%ld edges removed)\n", k); + printf (" (%u edges removed)\n", k); } else { printf ("\n"); } diff --git a/tools/qfvis/source/base-vis.c b/tools/qfvis/source/base-vis.c index b87b6481f..2242409dd 100644 --- a/tools/qfvis/source/base-vis.c +++ b/tools/qfvis/source/base-vis.c @@ -132,7 +132,7 @@ PortalBase (basethread_t *thread, portal_t *portal) cluster_t *cluster; int tp_side, portal_side; - for (cluster = clusters; cluster - clusters < portalclusters; cluster++) { + for (cluster = clusters; cluster < clusters + portalclusters; cluster++) { int side = test_sphere (&cluster->sphere, portal->plane); if (side < 0) { From 80b17623b1753074d95a7c04c096f864f94b1732 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Aug 2021 23:08:14 +0900 Subject: [PATCH 1718/3664] [util] Fix an out-by-one in pqueue tests Showed up only when the data arrays were packed. --- libs/util/test/test-pqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/test/test-pqueue.c b/libs/util/test/test-pqueue.c index 4e877c569..44aceb0c8 100644 --- a/libs/util/test/test-pqueue.c +++ b/libs/util/test/test-pqueue.c @@ -215,7 +215,7 @@ static test_t tests[] = { { 0, 0, dump_queue }, { sort2 + 4, 0, test_adjust }, { 0, 0, dump_queue }, - { sort3 + 7, 4, test_adjust }, + { sort3 + 6, 4, test_adjust }, { 0, 0, dump_queue }, { sort3 + 0, SIZEOF(sort), test_remove }, }; From d56d8ac7077cb616249e069741d65b1120ad1174 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Aug 2021 23:15:20 +0900 Subject: [PATCH 1719/3664] [util] Loosen up the epsilon on simd seb tests It seems my eeepc's SSE units don't get quite the same answers as does my i7's (maybe due to lack of hadd?). --- libs/util/test/test-sebvf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/util/test/test-sebvf.c b/libs/util/test/test-sebvf.c index 3cc3df9d5..c6105d897 100644 --- a/libs/util/test/test-sebvf.c +++ b/libs/util/test/test-sebvf.c @@ -233,8 +233,8 @@ main (int argc, const char **argv) for (i = 0; i < num_tests; i ++) { sphere = SmallestEnclosingBall_vf (tests[i].points, tests[i].num_points); - if (VectorDistance_fast (sphere.center, tests[i].expect.center) > 1e-4 - || fabs (sphere.radius - tests[i].expect.radius) > 1e-4) { + if (VectorDistance_fast (sphere.center, tests[i].expect.center) > 2e-4 + || fabs (sphere.radius - tests[i].expect.radius) > 2e-4) { res = 1; printf ("test %d failed\n", (int) i); printf ("expect: {%.9g, %.9g, %.9g}, %.9g\n", From 421047328abed01a3c30945b5dc5425dcdce95d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Aug 2021 14:22:37 +0900 Subject: [PATCH 1720/3664] [qfvis] Catch a missed winding mark stat --- tools/qfvis/source/flow.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 3b653ab7e..3a364d1d1 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -298,6 +298,14 @@ mightsee_more (set_t *might, const set_t *prev_might, const set_t *test, return more != 0; } +static void +free_winding_memory (threaddata_t *thread, size_t winding_mark) +{ + thread->stats.winding_mark = max (thread->stats.winding_mark, + Hunk_LowMark (thread->hunk)); + Hunk_RawFreeToLowMark (thread->hunk, winding_mark); +} + /* RecursiveClusterFlow @@ -353,9 +361,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) if (!set_is_member (prevstack->mightsee, target_portal->cluster)) continue; // can't possibly see it - thread->stats.winding_mark = max (thread->stats.winding_mark, - Hunk_LowMark (thread->hunk)); - Hunk_RawFreeToLowMark (thread->hunk, winding_mark); + free_winding_memory (thread, winding_mark); // if target_portal can't see anything we haven't already seen, skip it test = select_test_set (target_portal, thread); @@ -488,7 +494,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) // flow through it for real RecursiveClusterFlow (target_portal->cluster, thread, stack); } - Hunk_RawFreeToLowMark (thread->hunk, winding_mark); + free_winding_memory (thread, winding_mark); free_separators (thread, stack->separators[1]); free_separators (thread, stack->separators[0]); } From 42dc30ec29be74d7b6067b6670da040db175583d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 2 Aug 2021 15:12:29 +0900 Subject: [PATCH 1721/3664] [vulkan] Increase main staging buffer to 32MB 1k 32bpp sky textures need 24MB to load. Though there's always better handling of running out of stating buffer (ie, flushing and trying again). --- libs/video/renderer/vulkan/vulkan_vid_common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index e5984cc8a..64fc3d453 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -236,8 +236,9 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) void Vulkan_CreateStagingBuffers (vulkan_ctx_t *ctx) { + // FIXME configurable? ctx->staging = QFV_CreateStagingBuffer (ctx->device, "vulkan_ctx", - 16*1024*1024, ctx->cmdpool); + 32*1024*1024, ctx->cmdpool); } void From 8da019e31c55072587c44ddeff5f281d17d09975 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Aug 2021 11:37:24 +0900 Subject: [PATCH 1722/3664] [qfvis] Reconstruct the leaf clusters in a bsp This is only the first half (vertical) in that the vis bits are still for the leafs rather than the clusters, but ad_tears goes from 500s to 7s for calculating the fat pvs (3852 clusters). --- tools/qfvis/include/vis.h | 2 +- tools/qfvis/source/fatpvs.c | 231 ++++++++++++++++++++++++------------ tools/qfvis/source/qfvis.c | 10 +- 3 files changed, 167 insertions(+), 76 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index e1ccefe16..cc321619d 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -204,7 +204,7 @@ extern struct bsp_s *bsp; extern portal_t *portals; extern cluster_t *clusters; -extern int *leafcluster; +extern uint32_t *leafcluster; extern byte *uncompressed; winding_t *NewWinding (threaddata_t *thread, int points); diff --git a/tools/qfvis/source/fatpvs.c b/tools/qfvis/source/fatpvs.c index 2ea925fee..d832adfe9 100644 --- a/tools/qfvis/source/fatpvs.c +++ b/tools/qfvis/source/fatpvs.c @@ -32,6 +32,7 @@ #include #include "QF/bspfile.h" +#include "QF/heapsort.h" #include "QF/pvsfile.h" #include "QF/quakefs.h" #include "QF/set.h" @@ -41,14 +42,26 @@ #include "tools/qfvis/include/options.h" #include "tools/qfvis/include/vis.h" +typedef struct { + uint32_t visoffs; + uint32_t leafnum; +} leafvis_t; + +typedef struct { + uint32_t first_leaf; + uint32_t num_leafs; +} leafmap_t; + static set_pool_t *set_pool; -static set_t *base_pvs; -static set_t *fat_pvs; +static set_t *base_pvs; +static set_t *fat_pvs; +static leafvis_t *leafvis; +static leafmap_t *leafmap; static sizebuf_t *cmp_pvs; -static unsigned num_leafs; -static unsigned visbytes; -static unsigned work_leaf; +static uint32_t num_leafs; +static uint32_t num_clusters; +static uint32_t work_cluster; typedef struct { long pvs_visible; @@ -69,18 +82,18 @@ update_stats (fatstats_t *stats) } static int -leaf_progress (void) +cluster_progress (void) { - return work_leaf * 100 / num_leafs; + return work_cluster * 100 / num_clusters; } static unsigned -next_leaf (void) +next_cluster (void) { unsigned leaf = ~0; WRLOCK (global_lock); - if (work_leaf < num_leafs) { - leaf = work_leaf++; + if (work_cluster < num_clusters) { + leaf = work_cluster++; } UNLOCK (global_lock); return leaf; @@ -100,22 +113,24 @@ decompress_vis (const byte *in, unsigned numleafs, set_t *pvs) *out++ = 0xff; row--; } - return; + } else { + do { + if (*in) { + *out++ = *in++; + continue; + } + c = in[1]; + in += 2; + while (c) { + *out++ = 0; + c--; + } + } while (out - start < row); } - do { - if (*in) { - *out++ = *in++; - continue; - } - - c = in[1]; - in += 2; - while (c) { - *out++ = 0; - c--; - } - } while (out - start < row); + while ((out - start) & (sizeof (set_bits_t) - 1)) { + *out++ = 0; + } } static void * @@ -125,23 +140,23 @@ decompress_thread (void *d) int thread = (intptr_t) d; while (1) { - unsigned leaf_num = next_leaf (); + unsigned cluster_num = next_cluster (); if (working) - working[thread] = leaf_num; - if (leaf_num == ~0u) { + working[thread] = cluster_num; + if (cluster_num == ~0u) { break; } byte *visdata = 0; - dleaf_t *leaf = &bsp->leafs[leaf_num]; + dleaf_t *leaf = &bsp->leafs[leafmap[cluster_num].first_leaf + 1]; if (leaf->visofs >= 0) { visdata = bsp->visdata + leaf->visofs; } - decompress_vis (visdata, num_leafs, &base_pvs[leaf_num]); - if (leaf_num == 0) { + decompress_vis (visdata, num_leafs, &base_pvs[cluster_num]); + if (cluster_num == 0) { continue; } - stats.pvs_visible += set_count (&base_pvs[leaf_num]); + stats.pvs_visible += set_count (&base_pvs[cluster_num]); } update_stats (&stats); return 0; @@ -154,29 +169,24 @@ fatten_thread (void *d) int thread = (intptr_t) d; while (1) { - unsigned leaf_num = next_leaf (); + unsigned cluster_num = next_cluster (); if (working) - working[thread] = leaf_num; - if (leaf_num == ~0u) { + working[thread] = cluster_num; + if (cluster_num == ~0u) { break; } - set_assign (&fat_pvs[leaf_num], &base_pvs[leaf_num]); + set_assign (&fat_pvs[cluster_num], &base_pvs[cluster_num]); for (set_iter_t *iter = set_first_r (&set_pool[thread], - &base_pvs[leaf_num]); + &base_pvs[cluster_num]); iter; iter = set_next_r (&set_pool[thread], iter)) { - // or this pvs row into the fat pvs - // +1 because pvs is 1 based - set_union (&fat_pvs[leaf_num], &base_pvs[iter->element + 1]); + set_union (&fat_pvs[cluster_num], &base_pvs[leafcluster[iter->element]]); } - if (leaf_num == 0) { - continue; - } - stats.fat_visible += set_count (&fat_pvs[leaf_num]); - set_difference (&fat_pvs[leaf_num], &base_pvs[leaf_num]); + stats.fat_visible += set_count (&fat_pvs[cluster_num]); + set_difference (&fat_pvs[cluster_num], &base_pvs[cluster_num]); } update_stats (&stats); return 0; @@ -218,15 +228,15 @@ compress_thread (void *d) qboolean rle = options.utf8; while (1) { - unsigned leaf_num = next_leaf (); + unsigned cluster_num = next_cluster (); if (working) - working[thread] = leaf_num; - if (leaf_num == ~0u) { + working[thread] = cluster_num; + if (cluster_num == ~0u) { break; } - sizebuf_t *compressed = &cmp_pvs[leaf_num]; - const byte *fat_bytes = (const byte *) fat_pvs[leaf_num].map; + sizebuf_t *compressed = &cmp_pvs[cluster_num]; + const byte *fat_bytes = (const byte *) fat_pvs[cluster_num].map; int bytes = CompressRow (compressed, fat_bytes, num_leafs, rle); stats.fat_bytes += bytes; } @@ -234,34 +244,81 @@ compress_thread (void *d) return 0; } -void -CalcFatPVS (void) +static int +leaf_compare (const void *_la, const void *_lb) +{ + const leafvis_t *la = _la; + const leafvis_t *lb = _lb; + if (la->visoffs == lb->visoffs) { + return la->leafnum - lb->leafnum; + } + return la->visoffs - lb->visoffs; +} + +static void +reconstruct_clusters (void) +{ + leafvis = malloc (num_leafs * sizeof (leafvis_t)); + for (unsigned i = 0; i < num_leafs; i++) { + leafvis[i].visoffs = bsp->leafs[i + 1].visofs; + leafvis[i].leafnum = i; + } + heapsort (leafvis, num_leafs, sizeof (leafvis_t), leaf_compare); + + num_clusters = 1; + for (unsigned i = 1; i < num_leafs; i++) { + num_clusters += leafvis[i].visoffs != leafvis[i - 1].visoffs; + } + + printf ("num_clusters: %u\n", num_clusters); + + leafcluster = malloc (num_leafs * sizeof (uint32_t)); + leafmap = calloc (num_clusters, sizeof (leafmap_t)); + leafmap_t *lm = leafmap; + uint32_t offs = leafvis[0].visoffs; + for (unsigned i = 0; i < num_leafs; i++) { + if (leafvis[i].visoffs != offs) { + lm++; + lm->first_leaf = i; + offs = leafvis[i].visoffs; + } + leafcluster[leafvis[i].leafnum] = lm - leafmap; + lm->num_leafs++; + } + //for (unsigned i = 0; i < num_clusters; i++) { + // printf ("%d %d %d\n", i, leafmap[i].first_leaf, leafmap[i].num_leafs); + //} + printf ("%d\n", num_leafs); +} + +static void +allocate_data (void) { set_pool = calloc (options.threads, sizeof (set_pool_t)); - num_leafs = bsp->models[0].visleafs; - visbytes = (num_leafs + 7) / 8; - base_pvs = malloc (num_leafs * sizeof (set_t)); - fat_pvs = malloc (num_leafs * sizeof (set_t)); - cmp_pvs = malloc (num_leafs * sizeof (sizebuf_t)); - for (unsigned i = 0; i < num_leafs; i++) { - base_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs, malloc); - fat_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs, malloc); + + base_pvs = malloc (num_clusters * sizeof (set_t)); + fat_pvs = malloc (num_clusters * sizeof (set_t)); + cmp_pvs = malloc (num_clusters * sizeof (sizebuf_t)); + + uint32_t visbytes = (num_leafs + 7) / 8; + // Worst case, RLE can add 50% to the bytes required (alternating zero + // and non-zero bytes: 0 x 0 y -> 0 1 x 0 1 y ...). Also, if the map is + // very tiny (8 leafs or fewer), there will be only one byte for vis, but + // if that byte is 0, an extra byte for the count is required. + visbytes = (visbytes * 3) / 2 + 1; + for (unsigned i = 0; i < num_clusters; i++) { + base_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs - 1, malloc); + fat_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs - 1, malloc); cmp_pvs[i] = (sizebuf_t) { - .data = malloc ((visbytes * 3) / 2), - .maxsize = (visbytes * 3) / 2, + .data = malloc (visbytes), + .maxsize = visbytes, }; } - work_leaf = 0; - RunThreads (decompress_thread, leaf_progress); - work_leaf = 0; - RunThreads (fatten_thread, leaf_progress); - work_leaf = 0; - RunThreads (compress_thread, leaf_progress); - printf ("Average leafs visible / fat visible / total: %d / %d / %d\n", - (int) (fatstats.pvs_visible / num_leafs), - (int) (fatstats.fat_visible / num_leafs), num_leafs); - printf ("Compressed fat vis size: %ld\n", fatstats.fat_bytes); +} +static void +write_pvs_file (void) +{ uint32_t offset = sizeof (pvsfile_t) + num_leafs * sizeof (uint32_t); pvsfile_t *pvsfile = malloc (offset + fatstats.fat_bytes); @@ -273,9 +330,12 @@ CalcFatPVS (void) pvsfile->flags |= PVS_UTF8_RLE; } pvsfile->visleafs = num_leafs; - for (unsigned i = 0; i < num_leafs; i++) { + for (uint32_t i = 0; i < num_clusters; i++) { unsigned size = cmp_pvs[i].cursize; - pvsfile->visoffsets[i] = offset; + for (uint32_t j = 0; j < leafmap[i].num_leafs; j++) { + uint32_t l = leafmap[i].first_leaf + j; + pvsfile->visoffsets[leafvis[l].leafnum] = offset; + } memcpy ((byte *) pvsfile + offset, cmp_pvs[i].data, size); offset += size; } @@ -291,3 +351,28 @@ CalcFatPVS (void) Qwrite (f, pvsfile, offset); Qclose (f); } + +void +CalcFatPVS (void) +{ + num_leafs = bsp->models[0].visleafs; + + reconstruct_clusters (); + allocate_data (); + + work_cluster = 0; + RunThreads (decompress_thread, cluster_progress); + + work_cluster = 0; + RunThreads (fatten_thread, cluster_progress); + + work_cluster = 0; + RunThreads (compress_thread, cluster_progress); + + printf ("Average leafs visible / fat visible / total: %d / %d / %d\n", + (int) (fatstats.pvs_visible / num_clusters), + (int) (fatstats.fat_visible / num_clusters), num_leafs); + printf ("Compressed fat vis size: %ld\n", fatstats.fat_bytes); + + write_pvs_file (); +} diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index e49569649..bf600f98f 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -103,7 +103,7 @@ portal_t *portals; cluster_t *clusters; dstring_t *visdata; byte *uncompressed; // [bitbytes * portalleafs] -int *leafcluster; // leaf to cluster mappings as read from .prt file +uint32_t *leafcluster; // leaf to cluster mappings as read from .prt file int *working; // per thread current portal # @@ -1469,7 +1469,7 @@ LoadPortals (char *name) free (clusternums); free (windings); - leafcluster = calloc (numrealleafs, sizeof (int)); + leafcluster = calloc (numrealleafs, sizeof (uint32_t)); if (read_leafs) { for (unsigned i = 0; i < numrealleafs; i++) { line = Qgetline (f); @@ -1490,6 +1490,7 @@ generate_pvs (void) QFile *f; dstring_t *portalfile = dstring_new (); + dstring_t *backupfile = dstring_new (); visdata = dstring_new (); @@ -1513,12 +1514,17 @@ generate_pvs (void) CalcAmbientSounds (); + dstring_copystr (backupfile, options.bspfile->str); + QFS_SetExtension (backupfile, ".bsp~"); + + Qrename (options.bspfile->str, backupfile->str); f = Qopen (options.bspfile->str, "wb"); if (!f) Sys_Error ("couldn't open %s for writing.", options.bspfile->str); WriteBSPFile (bsp, f); Qclose (f); + dstring_delete (backupfile); dstring_delete (portalfile); dstring_delete (visdata); dstring_delete (options.bspfile); From fe998f41b4f31fcd2ee6af97520fc4eb60edd9e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Aug 2021 15:48:45 +0900 Subject: [PATCH 1723/3664] [qfvis] Convert leaf vis to cluster vis Now that only 3852 clusters need to be checked for each cluster, fat-pvs construction for ad_tears completes in about 0.7s, most of which seems to be loading, conversion, compression and writing. O(N^3) cuts both ways (hurts like crazy when N increases, does wonders when N decreases, especially by a factor of 25). And then throw in improved cache performance... I suspect having an off-line compiler is still useful, but even if qfvis's implementation never actually gets used, if cluster reconstruction is put in the engine, large maps will be feasible even for quakeworld. Just the reduced memory requirements alone will be a huge benefit (~3GB down to 1.8MB). --- tools/qfvis/source/fatpvs.c | 51 +++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/tools/qfvis/source/fatpvs.c b/tools/qfvis/source/fatpvs.c index d832adfe9..6a5c9d749 100644 --- a/tools/qfvis/source/fatpvs.c +++ b/tools/qfvis/source/fatpvs.c @@ -138,7 +138,11 @@ decompress_thread (void *d) { fatstats_t stats = { }; int thread = (intptr_t) d; + set_t vis = { }; + if (num_leafs != num_clusters) { + vis = (set_t) SET_STATIC_INIT (num_leafs - 1, alloca); + } while (1) { unsigned cluster_num = next_cluster (); @@ -152,9 +156,15 @@ decompress_thread (void *d) if (leaf->visofs >= 0) { visdata = bsp->visdata + leaf->visofs; } - decompress_vis (visdata, num_leafs, &base_pvs[cluster_num]); - if (cluster_num == 0) { - continue; + if (num_leafs == num_clusters) { + decompress_vis (visdata, num_leafs, &base_pvs[cluster_num]); + } else { + decompress_vis (visdata, num_leafs, &vis); + set_empty (&base_pvs[cluster_num]); + for (set_iter_t *iter = set_first_r (&set_pool[thread], &vis); + iter; iter = set_next_r (&set_pool[thread], iter)) { + set_add (&base_pvs[cluster_num], leafcluster[iter->element]); + } } stats.pvs_visible += set_count (&base_pvs[cluster_num]); } @@ -183,7 +193,7 @@ fatten_thread (void *d) iter; iter = set_next_r (&set_pool[thread], iter)) { - set_union (&fat_pvs[cluster_num], &base_pvs[leafcluster[iter->element]]); + set_union (&fat_pvs[cluster_num], &base_pvs[iter->element]); } stats.fat_visible += set_count (&fat_pvs[cluster_num]); set_difference (&fat_pvs[cluster_num], &base_pvs[cluster_num]); @@ -226,6 +236,11 @@ compress_thread (void *d) fatstats_t stats = { }; int thread = (intptr_t) d; qboolean rle = options.utf8; + set_t vis = { }; + + if (num_leafs != num_clusters) { + vis = (set_t) SET_STATIC_INIT (num_leafs - 1, alloca); + } while (1) { unsigned cluster_num = next_cluster (); @@ -235,10 +250,23 @@ compress_thread (void *d) if (cluster_num == ~0u) { break; } + sizebuf_t *compressed = &cmp_pvs[cluster_num]; const byte *fat_bytes = (const byte *) fat_pvs[cluster_num].map; - int bytes = CompressRow (compressed, fat_bytes, num_leafs, rle); - stats.fat_bytes += bytes; + if (num_leafs != num_clusters) { + fat_bytes = (const byte *) vis.map; + set_empty (&vis); + for (set_iter_t *iter = set_first_r (&set_pool[thread], + &fat_pvs[cluster_num]); + iter; iter = set_next_r (&set_pool[thread], iter)) { + for (uint32_t j = 0; + j < leafmap[iter->element].num_leafs; j++) { + uint32_t l = leafmap[iter->element].first_leaf + j; + set_add (&vis, leafvis[l].leafnum); + } + } + } + stats.fat_bytes += CompressRow (compressed, fat_bytes, num_leafs, rle); } update_stats (&stats); return 0; @@ -285,6 +313,9 @@ reconstruct_clusters (void) leafcluster[leafvis[i].leafnum] = lm - leafmap; lm->num_leafs++; } + //for (unsigned i = 0; i < num_leafs; i++) { + // printf ("%d %d %d\n", i, leafvis[i].visoffs, leafvis[i].leafnum); + //} //for (unsigned i = 0; i < num_clusters; i++) { // printf ("%d %d %d\n", i, leafmap[i].first_leaf, leafmap[i].num_leafs); //} @@ -307,8 +338,8 @@ allocate_data (void) // if that byte is 0, an extra byte for the count is required. visbytes = (visbytes * 3) / 2 + 1; for (unsigned i = 0; i < num_clusters; i++) { - base_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs - 1, malloc); - fat_pvs[i] = (set_t) SET_STATIC_INIT (num_leafs - 1, malloc); + base_pvs[i] = (set_t) SET_STATIC_INIT (num_clusters - 1, malloc); + fat_pvs[i] = (set_t) SET_STATIC_INIT (num_clusters - 1, malloc); cmp_pvs[i] = (sizebuf_t) { .data = malloc (visbytes), .maxsize = visbytes, @@ -369,9 +400,9 @@ CalcFatPVS (void) work_cluster = 0; RunThreads (compress_thread, cluster_progress); - printf ("Average leafs visible / fat visible / total: %d / %d / %d\n", + printf ("Average clusters visible / fat visible / total: %d / %d / %d\n", (int) (fatstats.pvs_visible / num_clusters), - (int) (fatstats.fat_visible / num_clusters), num_leafs); + (int) (fatstats.fat_visible / num_clusters), num_clusters); printf ("Compressed fat vis size: %ld\n", fatstats.fat_bytes); write_pvs_file (); From 648ae3f877f9d3a5814a08e03caf59bbdfa31495 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Aug 2021 21:52:24 +0900 Subject: [PATCH 1724/3664] [qfvis] Clean up the code and output a little Dead code removed, and the job progress lines are now consistent and have a job completion time when done. --- tools/qfvis/include/vis.h | 4 ++- tools/qfvis/source/fatpvs.c | 47 ++++--------------------- tools/qfvis/source/qfvis.c | 65 ++++++++++++++++++++++++----------- tools/qfvis/source/soundphs.c | 6 ++-- 4 files changed, 56 insertions(+), 66 deletions(-) diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index cc321619d..842ab03c7 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -223,10 +223,12 @@ int CompressRow (struct sizebuf_s *dest, const byte *vis, unsigned num_leafs, void CalcFatPVS (void); -void RunThreads (void *(*thread_func) (void *), int (*calc_progress)(void)); +void RunThreads (const char *heading, void *(*thread_func) (void *), + int (*calc_progress)(void)); extern const char spinner[]; extern const char progress[]; extern int *working; +extern int progress_tick; #endif// __vis_h diff --git a/tools/qfvis/source/fatpvs.c b/tools/qfvis/source/fatpvs.c index 6a5c9d749..0cf42d462 100644 --- a/tools/qfvis/source/fatpvs.c +++ b/tools/qfvis/source/fatpvs.c @@ -92,6 +92,7 @@ next_cluster (void) { unsigned leaf = ~0; WRLOCK (global_lock); + progress_tick++; if (work_cluster < num_clusters) { leaf = work_cluster++; } @@ -201,34 +202,6 @@ fatten_thread (void *d) update_stats (&stats); return 0; } -#if 0 -static void * -fatten_thread2 (void *d) -{ - for (unsigned visword = 0; visword < SET_WORDS (&sv.pvs[0]); visword++) { - Sys_Printf ("%d / %ld\n", visword, SET_WORDS (&sv.pvs[0])); - for (i = 0; i < num; i++) { - for (unsigned j = 0; j < SET_BITS; j++) { - unsigned visbit = visword * SET_BITS + j; - if (visbit >= (unsigned) num) { - break; - } - if (SET_TEST_MEMBER (&sv.pvs[i], visbit)) { - // or this pvs row into the phs - // +1 because pvs is 1 based - set_union (&sv.phs[i], &sv.pvs[visbit + 1]); - } - } - } - } - for (i = 1; i < num; i++) { - for (set_iter_t *iter = set_first (&sv.phs[i]); iter; - iter = set_next (iter)) { - count++; - } - } -} -#endif static void * compress_thread (void *d) @@ -298,8 +271,6 @@ reconstruct_clusters (void) num_clusters += leafvis[i].visoffs != leafvis[i - 1].visoffs; } - printf ("num_clusters: %u\n", num_clusters); - leafcluster = malloc (num_leafs * sizeof (uint32_t)); leafmap = calloc (num_clusters, sizeof (leafmap_t)); leafmap_t *lm = leafmap; @@ -313,13 +284,9 @@ reconstruct_clusters (void) leafcluster[leafvis[i].leafnum] = lm - leafmap; lm->num_leafs++; } - //for (unsigned i = 0; i < num_leafs; i++) { - // printf ("%d %d %d\n", i, leafvis[i].visoffs, leafvis[i].leafnum); - //} - //for (unsigned i = 0; i < num_clusters; i++) { - // printf ("%d %d %d\n", i, leafmap[i].first_leaf, leafmap[i].num_leafs); - //} - printf ("%d\n", num_leafs); + + printf ("leafs : %u\n", num_leafs); + printf ("clusters: %u\n", num_clusters); } static void @@ -392,13 +359,13 @@ CalcFatPVS (void) allocate_data (); work_cluster = 0; - RunThreads (decompress_thread, cluster_progress); + RunThreads ("Decompress", decompress_thread, cluster_progress); work_cluster = 0; - RunThreads (fatten_thread, cluster_progress); + RunThreads ("Fatten", fatten_thread, cluster_progress); work_cluster = 0; - RunThreads (compress_thread, cluster_progress); + RunThreads ("Compress", compress_thread, cluster_progress); printf ("Average clusters visible / fat visible / total: %d / %d / %d\n", (int) (fatstats.pvs_visible / num_clusters), diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index bf600f98f..ea0899a1d 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -106,6 +106,7 @@ byte *uncompressed; // [bitbytes * portalleafs] uint32_t *leafcluster; // leaf to cluster mappings as read from .prt file int *working; // per thread current portal # +int progress_tick; static void InitThreads (void) @@ -398,6 +399,7 @@ GetNextPortal (int limit) && options.portal_limit > 0 && portal_count >= options.portal_limit)) { WRLOCK (global_lock); + progress_tick++; if (portal_count < 2 * numportals) { p = portal_queue[portal_count++]; p->status = stat_selected; @@ -710,7 +712,7 @@ WatchThread (void *_wd) int spinner_ind = 0; int count = 0; int prev_prog = 0; - unsigned prev_port = 0; + int prev_tick = 0; int stalled = 0; while (1) { @@ -731,8 +733,8 @@ WatchThread (void *_wd) prev_prog = print_progress (prev_prog, wd->calc_progress (), spinner_ind); } - if (prev_port != portal_count || stalled++ == 20) { - prev_port = portal_count; + if (prev_tick != progress_tick || stalled++ == 20) { + prev_tick = progress_tick; stalled = 0; spinner_ind++; } @@ -743,7 +745,6 @@ WatchThread (void *_wd) } else if (options.verbosity >= 0) { prev_prog = print_progress (prev_prog, wd->calc_progress (), spinner_ind); - printf ("\n"); } free (local_work); @@ -751,17 +752,48 @@ WatchThread (void *_wd) } #endif +static double +thread_start (const char *msg) +{ + if (options.verbosity >= 0) { + printf ("%-10.10s: ", msg); + } + if (options.verbosity >= 4) { + printf ("\n"); + } + return Sys_DoubleTime (); +} + +static void +thread_end (double start) +{ + double end = Sys_DoubleTime (); + double duration = end - start; + + if (options.verbosity >= 0) { + if (duration >= 1.2) { + printf (" %5.1fs", duration); + } else { + printf (" %5.1fms", duration * 1000); + } + } + printf ("\n"); +} + void -RunThreads (void *(*thread_func) (void *), int (*calc_progress)(void)) +RunThreads (const char *heading, void *(*thread_func) (void *), + int (*calc_progress)(void)) { #ifdef USE_PTHREADS pthread_t *work_threads; void *status; int i; + double start; if (options.threads > 1) { work_threads = alloca ((options.threads + 1) * sizeof (pthread_t *)); working = calloc (options.threads, sizeof (int)); + start = thread_start (heading); for (i = 0; i < options.threads; i++) { if (pthread_create (&work_threads[i], &threads_attrib, thread_func, (void *) (intptr_t) i) == -1) @@ -778,10 +810,13 @@ RunThreads (void *(*thread_func) (void *), int (*calc_progress)(void)) } if (pthread_join (work_threads[i], &status) == -1) Sys_Error ("pthread_join failed"); + thread_end (start); free (working); } else { + start = thread_start (heading); thread_func (0); + thread_end (start); } #else thread_func (0); @@ -902,6 +937,7 @@ next_cluster (void) { unsigned cluster = ~0; WRLOCK (global_lock); + progress_tick++; if (work_cluster < portalclusters) { cluster = work_cluster++; } @@ -931,9 +967,6 @@ FlowClusters (void *d) static void CompactPortalVis (void) { - if (options.verbosity >= 0) { - printf ("Comp vis: "); - } compressed_vis = malloc (portalclusters * sizeof (sizebuf_t)); for (unsigned i = 0; i < portalclusters; i++) { compressed_vis[i] = (sizebuf_t) { @@ -941,7 +974,7 @@ CompactPortalVis (void) .data = malloc ((bitbytes_l * 3) / 2) }; } - RunThreads (FlowClusters, flow_progress); + RunThreads ("Comp vis", FlowClusters, flow_progress); for (unsigned i = 0; i < portalclusters; i++) { unsigned size = compressed_vis[i].cursize; @@ -963,13 +996,8 @@ BasePortalVis (void) { double start, end; - if (options.verbosity >= 0) - printf ("Base vis: "); - if (options.verbosity >= 4) - printf ("\n"); - start = Sys_DoubleTime (); - RunThreads (BaseVisThread, portal_progress); + RunThreads ("Base vis", BaseVisThread, portal_progress); end = Sys_DoubleTime (); if (options.verbosity >= 1) { @@ -1009,14 +1037,9 @@ CalcPortalVis (void) if (options.verbosity >= 1) printf ("qsort: %gs\n", end - start); - if (options.verbosity >= 0) - printf ("Full vis: "); - if (options.verbosity >= 4) - printf ("\n"); - portal_count = 0; - RunThreads (LeafThread, portal_progress); + RunThreads ("Full vis", LeafThread, portal_progress); if (options.verbosity >= 1) { printf ("portalcheck: %ld portaltest: %ld portalpass: %ld\n", diff --git a/tools/qfvis/source/soundphs.c b/tools/qfvis/source/soundphs.c index 51b4ddbc7..52686ffda 100644 --- a/tools/qfvis/source/soundphs.c +++ b/tools/qfvis/source/soundphs.c @@ -204,6 +204,7 @@ next_leaf (void) { unsigned leaf = ~0; WRLOCK (global_lock); + progress_tick++; if (work_leaf < numrealleafs) { leaf = work_leaf++; } @@ -239,8 +240,5 @@ void CalcAmbientSounds (void) { init_surf_ambients (); - if (options.verbosity >= 0) { - printf ("Ambients: "); - } - RunThreads (AmbientThread, ambient_progress); + RunThreads ("Ambients", AmbientThread, ambient_progress); } From b320c3352fb8894609eb3518d3366ae715b06ed9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 Aug 2021 11:21:17 +0900 Subject: [PATCH 1725/3664] [util] Make set_t endian-agnostic Most of the set ops were always endian-agnostic since they were simply operating on multiple bits in parallel, but individual element add/remove/test was very endian-dependent. For the most part, this didn't matter, but it does matter very much when loading external data into a set or writing the data out (eg, for PVS). --- include/QF/set.h | 6 +++++- libs/util/set.c | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/QF/set.h b/include/QF/set.h index 7fb0f8538..067d25ed2 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -56,7 +56,11 @@ typedef uint32_t set_bits_t; #define SET_ZERO ((set_bits_t) 0) #define SET_ONE ((set_bits_t) 1) #define SET_TEST_MEMBER(s, x) \ - ((s)->map[(x) / SET_BITS] & (SET_ONE << ((x) % SET_BITS))) + (((const byte *)(s)->map)[(x) / 8] & (SET_ONE << ((x) % 8))) +#define SET_ADD(s, x) \ + (((byte *)(s)->map)[(x) / 8] |= (SET_ONE << ((x) % 8))) +#define SET_REMOVE(s, x) \ + (((byte *)(s)->map)[(x) / 8] &= ~(SET_ONE << ((x) % 8))) #define SET_STATIC_INIT(x, alloc) { \ .size = SET_SIZE (x), \ .map = alloc (SET_SIZE (x) / 8), \ diff --git a/libs/util/set.c b/libs/util/set.c index f0215454c..4503806d8 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -150,7 +150,7 @@ _set_add (set_t *set, unsigned x) { if (x >= set->size) set_expand (set, x + 1); - set->map[x / SET_BITS] |= SET_ONE << (x % SET_BITS); + SET_ADD(set, x); } static inline void @@ -158,7 +158,7 @@ _set_remove (set_t *set, unsigned x) { if (x >= set->size) return; - set->map[x / SET_BITS] &= ~(SET_ONE << (x % SET_BITS)); + SET_REMOVE(set, x); } set_t * @@ -539,7 +539,7 @@ _set_is_member (const set_t *set, unsigned x) { if (x >= set->size) return 0; - return (set->map[x / SET_BITS] & (SET_ONE << (x % SET_BITS))) != 0; + return SET_TEST_MEMBER(set, x) != 0; } int From 9a93bf8d4a212b35ade4b61c707b7f3df608823e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 Aug 2021 13:47:56 +0900 Subject: [PATCH 1726/3664] [qfvis] Make cluster reconstruction O(N) For most (if not all) maps. The heapsort is needed only if the clustered leafs are not contiguous, but most bsp compilers output contiguous leaf clusters, so is just a bit of protection. The difference isn't really noticeable on a fast machine, but no point in doing more work than necessary. --- tools/qfvis/source/fatpvs.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tools/qfvis/source/fatpvs.c b/tools/qfvis/source/fatpvs.c index 0cf42d462..faabace0a 100644 --- a/tools/qfvis/source/fatpvs.c +++ b/tools/qfvis/source/fatpvs.c @@ -260,15 +260,24 @@ static void reconstruct_clusters (void) { leafvis = malloc (num_leafs * sizeof (leafvis_t)); + int sorted = 1; + num_clusters = 1; for (unsigned i = 0; i < num_leafs; i++) { leafvis[i].visoffs = bsp->leafs[i + 1].visofs; leafvis[i].leafnum = i; + if (i > 0) { + num_clusters += leafvis[i].visoffs != leafvis[i - 1].visoffs; + if (leafvis[i].visoffs < leafvis[i - 1].visoffs) { + sorted = 0; + } + } } - heapsort (leafvis, num_leafs, sizeof (leafvis_t), leaf_compare); - - num_clusters = 1; - for (unsigned i = 1; i < num_leafs; i++) { - num_clusters += leafvis[i].visoffs != leafvis[i - 1].visoffs; + if (!sorted) { + heapsort (leafvis, num_leafs, sizeof (leafvis_t), leaf_compare); + num_clusters = 1; + for (unsigned i = 1; i < num_leafs; i++) { + num_clusters += leafvis[i].visoffs != leafvis[i - 1].visoffs; + } } leafcluster = malloc (num_leafs * sizeof (uint32_t)); From 2828500f0418ce49f14c5bc6585163729f72e7e1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 Aug 2021 12:31:29 +0900 Subject: [PATCH 1727/3664] [qfvis] Delay freeing of winding memory If anything, this is probably a nano-optimization, depending on how often portals are vis-rejected. I couldn't see any actual difference. --- tools/qfvis/source/flow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 3a364d1d1..618163e2e 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -361,8 +361,6 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) if (!set_is_member (prevstack->mightsee, target_portal->cluster)) continue; // can't possibly see it - free_winding_memory (thread, winding_mark); - // if target_portal can't see anything we haven't already seen, skip it test = select_test_set (target_portal, thread); if (!mightsee_more (might, prevstack->mightsee, test, vis)) { @@ -379,6 +377,8 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) continue; // can't go out a coplanar face } + free_winding_memory (thread, winding_mark); + thread->stats.portalcheck++; target_winding = target_portal->winding; From c81f2d4b52457f1594c74b8aeee133a62ed8439c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Aug 2021 12:09:07 +0900 Subject: [PATCH 1728/3664] [video] Mark dga funcs as const when dga not available Fixes a compile issue (warning about attribute const) when dga is not available, thanks to spiritiit for finding it :) --- include/dga_check.h | 12 ++++++++++-- libs/video/targets/vid_x11.c | 1 - 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/dga_check.h b/include/dga_check.h index 53ab16fe1..a56161c68 100644 --- a/include/dga_check.h +++ b/include/dga_check.h @@ -38,7 +38,11 @@ Check for the presence of the XFree86-DGA support in the X server */ -qboolean VID_CheckDGA (Display *, int *, int *, int *); +qboolean VID_CheckDGA (Display *, int *, int *, int *) +#ifndef HAVE_DGA // FIXME + __attribute__((const)) +#endif + ; /* @@ -46,6 +50,10 @@ qboolean VID_CheckDGA (Display *, int *, int *, int *); Check for the presence of the XFree86-VMode X server extension */ -qboolean VID_CheckVMode (Display *, int *, int *); +qboolean VID_CheckVMode (Display *, int *, int *) +#ifndef HAVE_DGA // FIXME + __attribute__((const)) +#endif + ; #endif // __dga_check_h_ diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 0bb695e3a..6fc26e050 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -64,7 +64,6 @@ #include "compat.h" #include "context_x11.h" #include "d_iface.h" -#include "dga_check.h" #include "vid_internal.h" static vid_internal_t vid_internal; From aa72f1dc31b97e79682092458daf43e252159e1d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Aug 2021 23:19:17 +0900 Subject: [PATCH 1729/3664] [util] Fix reversed finite-infinite set union ops It looks like I tried to test it, but my tests weren't so good This seems to cover everything for the three main set ops. --- libs/util/set.c | 4 +- libs/util/test/test-set.c | 81 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/libs/util/set.c b/libs/util/set.c index 4503806d8..e04ede052 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -249,9 +249,9 @@ set_union (set_t *dst, const set_t *src) return _set_intersection (dst, src); } else if (src->inverted) { dst->inverted = 1; - return _set_difference (dst, src); - } else if (dst->inverted) { return _set_reverse_difference (dst, src); + } else if (dst->inverted) { + return _set_difference (dst, src); } else { return _set_union (dst, src); } diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index f26ce7195..01caf61b7 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -115,6 +115,25 @@ make_not_55 (void) return set_invert (make_55 ()); } +static set_t * +make_0_1 (void) +{ + set_t *set = set_new (); + set_add (set, 0); + set_add (set, 1); + return set; +} + +static set_t * +make_not_1_2 (void) +{ + set_t *set = set_new (); + set_everything (set); + set_remove (set, 1); + set_remove (set, 2); + return set; +} + static set_t * expand_3xSIZEm1 (set_t *set, const set_t *x) { @@ -222,6 +241,41 @@ struct { {make_5, 0, 0, check_count, 1, 0}, {make_not_5, 0, 0, check_count, 1, 0}, {make_0_to_SIZEm1, 0, 0, check_size, SIZE, 0}, + {make_0_1, 0, 0, 0, 0, "{0 1}"}, + {make_not_1_2, 0, 0, check_count, 2, + "{0 3 4 5 6 7 8 9 10 11 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" + }, + {make_0_1, make_not_1_2, set_union, check_count, 1, + "{0 1 3 4 5 6 7 8 9 10 11 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" + }, + {make_0_1, make_not_1_2, set_intersection, check_count, 1, "{0}"}, + {make_0_1, make_not_1_2, set_difference, check_count, 1, "{1}"}, + {make_0_1, make_not_1_2, set_reverse_difference, check_count, 3, + "{3 4 5 6 7 8 9 10 11 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" + }, + {make_not_1_2, make_0_1, set_union, check_count, 1, + "{0 1 3 4 5 6 7 8 9 10 11 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" + }, + {make_not_1_2, make_0_1, set_intersection, check_count, 1, "{0}"}, + {make_not_1_2, make_0_1, set_difference, check_count, 3, + "{3 4 5 6 7 8 9 10 11 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" + }, + {make_not_1_2, make_0_1, set_reverse_difference, check_count, 1, "{1}"}, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) @@ -249,6 +303,33 @@ main (int argc, const char **argv) dstring_appendstr (str, "}"); tests[6].str_expect = dstring_freeze (str); + str = dstring_new (); + for (i = 0; i < SIZE; i++) { + if (i == 1 || i == 2) + continue; + dasprintf (str, "%c%zd", i > 0 ? ' ' : '{', i); + } + dasprintf (str, " %zd ...}", i); + tests[68].str_expect = dstring_freeze (str); + + str = dstring_new (); + for (i = 0; i < SIZE; i++) { + if (i == 2) + continue; + dasprintf (str, "%c%zd", i > 0 ? ' ' : '{', i); + } + dasprintf (str, " %zd ...}", i); + tests[69].str_expect = dstring_freeze (str); + tests[73].str_expect = tests[69].str_expect; + + str = dstring_new (); + for (i = 3; i < SIZE; i++) { + dasprintf (str, "%c%zd", i > 3 ? ' ' : '{', i); + } + dasprintf (str, " %zd ...}", i); + tests[72].str_expect = dstring_freeze (str); + tests[75].str_expect = tests[72].str_expect; + for (i = 0; i < num_tests; i++) { set_t *s1, *s2 = 0; const char *set_str; From a6a273bb0723d2ebd2569b80f56c528cc3d9dcfe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Aug 2021 00:03:15 +0900 Subject: [PATCH 1730/3664] [vulkan] Fix up test function api Whil I can't automatically run the tests in windows builds, at least I can make sure they build (and run individual ones by hand as necessary). --- .../video/renderer/vulkan/test/test-staging.c | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libs/video/renderer/vulkan/test/test-staging.c b/libs/video/renderer/vulkan/test/test-staging.c index 4eb5b8f58..4f1705ce8 100644 --- a/libs/video/renderer/vulkan/test/test-staging.c +++ b/libs/video/renderer/vulkan/test/test-staging.c @@ -14,7 +14,7 @@ void *stage_memory; -static VkResult +static VkResult VKAPI_CALL vkMapMemory (VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **data) @@ -25,14 +25,14 @@ vkMapMemory (VkDevice device, VkDeviceMemory memory, return VK_SUCCESS; } -static VkResult +static VkResult VKAPI_CALL vkBindBufferMemory (VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize offset) { return VK_SUCCESS; } -static VkResult +static VkResult VKAPI_CALL vkCreateBuffer (VkDevice device, const VkBufferCreateInfo *cinfo, const VkAllocationCallbacks *allocator, VkBuffer *buffer) { @@ -40,14 +40,14 @@ vkCreateBuffer (VkDevice device, const VkBufferCreateInfo *cinfo, return VK_SUCCESS; } -static void +static void VKAPI_CALL vkGetBufferMemoryRequirements (VkDevice device, VkBuffer buffer, VkMemoryRequirements *requirements) { memset (requirements, 0, sizeof (*requirements)); } -static VkResult +static VkResult VKAPI_CALL vkAllocateCommandBuffers (VkDevice device, const VkCommandBufferAllocateInfo *info, VkCommandBuffer *buffers) @@ -60,7 +60,7 @@ vkAllocateCommandBuffers (VkDevice device, return VK_SUCCESS; } -static VkResult +static VkResult VKAPI_CALL vkCreateFence (VkDevice device, const VkFenceCreateInfo *info, const VkAllocationCallbacks *allocator, VkFence *fence) { @@ -72,7 +72,7 @@ vkCreateFence (VkDevice device, const VkFenceCreateInfo *info, int wait_count = 0; -static VkResult +static VkResult VKAPI_CALL vkWaitForFences (VkDevice device, uint32_t fenceCount, const VkFence *fences, VkBool32 waitAll, uint64_t timeout) { @@ -86,7 +86,7 @@ vkWaitForFences (VkDevice device, uint32_t fenceCount, const VkFence *fences, return VK_SUCCESS; } -static VkResult +static VkResult VKAPI_CALL vkResetFences (VkDevice device, uint32_t fenceCount, const VkFence *fences) { for (uint32_t i = 0; i < fenceCount; i++) { @@ -96,40 +96,40 @@ vkResetFences (VkDevice device, uint32_t fenceCount, const VkFence *fences) return VK_SUCCESS; } -static VkResult +static VkResult VKAPI_CALL vkGetFenceStatus (VkDevice device, VkFence fence) { int *f = (int *) (intptr_t) fence; return *f ? VK_SUCCESS : VK_NOT_READY; } -static VkResult +static VkResult VKAPI_CALL vkResetCommandBuffer (VkCommandBuffer buffer, VkCommandBufferResetFlags flags) { return VK_SUCCESS; } -static VkResult +static VkResult VKAPI_CALL vkBeginCommandBuffer (VkCommandBuffer buffer, const VkCommandBufferBeginInfo *info) { return VK_SUCCESS; } -static VkResult +static VkResult VKAPI_CALL vkEndCommandBuffer (VkCommandBuffer buffer) { return VK_SUCCESS; } -static VkResult +static VkResult VKAPI_CALL vkFlushMappedMemoryRanges (VkDevice device, uint32_t count, const VkMappedMemoryRange *ranges) { return VK_SUCCESS; } -static VkResult +static VkResult VKAPI_CALL vkQueueSubmit (VkQueue queue, uint32_t count, const VkSubmitInfo *submits, VkFence fence) { From 37a5b475c0390b5c42556dd64194d80a2a49c4fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Aug 2021 12:12:14 +0900 Subject: [PATCH 1731/3664] [util] Minimize the string for infinite sets Instead of printing every representable member of an infinite set (ie, up to element 63 in a set that can hold 64 elements), only those elements up to one after the last non-member are listed. For example, {...} - {2 3} -> {0 1 4 ...} This makes reading (and testing!) infinite sets much easier. --- include/QF/set.h | 5 +++- libs/util/set.c | 40 +++++++++++++++++-------- libs/util/test/test-set.c | 62 ++++----------------------------------- 3 files changed, 37 insertions(+), 70 deletions(-) diff --git a/include/QF/set.h b/include/QF/set.h index 067d25ed2..57c8342de 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -392,6 +392,7 @@ struct dstring_s; will overwrite the results of preceeding calls. */ const char *set_as_string (const set_t *set); + /** Return a human-readable string representing the set. Empty sets will be represented by the string "{}". Sets of everything @@ -406,7 +407,9 @@ const char *set_as_string (const set_t *set); is appeneded to the string. This makes it more useful when constructing strings in a threaded environment. */ -const char *set_as_string_r (struct dstring_s *str, const set_t *set); +const char *set_to_dstring (struct dstring_s *str, const set_t *set); +const char *set_to_dstring_r (set_pool_t *set_pool, struct dstring_s *str, + const set_t *set); ///@} #endif//__QF_set_h diff --git a/libs/util/set.c b/libs/util/set.c index e04ede052..baabe1057 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -626,9 +626,10 @@ set_next (set_iter_t *set_iter) } const char * -set_as_string_r (dstring_t *str, const set_t *set) +set_to_dstring_r (set_pool_t *set_pool, dstring_t *str, const set_t *set) { - unsigned i; + set_iter_t *iter; + int first = 1; if (set_is_empty (set)) { dstring_appendstr (str, "{}"); @@ -639,21 +640,36 @@ set_as_string_r (dstring_t *str, const set_t *set) return str->str; } dstring_appendstr (str, "{"); - for (i = 0; i < set->size; i++) { - if (set_is_member (set, i)) { - if (str->str[1]) - dasprintf (str, " %d", i); - else - dasprintf (str, "%d", i); - } - } if (set->inverted) { - dasprintf (str, "%s%d ...", str->str[1] ? " " : "", i); + unsigned start = 0; + + for (iter = set_first_r (set_pool, set); iter; + iter = set_next_r (set_pool, iter)) { + unsigned end = iter->element; + while (start < end) { + dasprintf (str, "%s%d", first ? "" : " ", start++); + first = 0; + } + start = end + 1; + } + dasprintf (str, "%s%d ...", first ? "" : " ", start); + } else { + for (iter = set_first_r (set_pool, set); iter; + iter = set_next_r (set_pool, iter)) { + dasprintf (str, "%s%d", first ? "" : " ", iter->element); + first = 0; + } } dstring_appendstr (str, "}"); return str->str; } +const char * +set_to_dstring (dstring_t *str, const set_t *set) +{ + return set_to_dstring_r (&static_set_pool, str, set); +} + const char * set_as_string (const set_t *set) { @@ -663,5 +679,5 @@ set_as_string (const set_t *set) str = dstring_new (); } dstring_clearstr (str); - return set_as_string_r (str, set); + return set_to_dstring_r (&static_set_pool, str, set); } diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index 01caf61b7..4569c0046 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -242,39 +242,14 @@ struct { {make_not_5, 0, 0, check_count, 1, 0}, {make_0_to_SIZEm1, 0, 0, check_size, SIZE, 0}, {make_0_1, 0, 0, 0, 0, "{0 1}"}, - {make_not_1_2, 0, 0, check_count, 2, - "{0 3 4 5 6 7 8 9 10 11 12 13 14 15" - " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" - " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" - " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" - }, - {make_0_1, make_not_1_2, set_union, check_count, 1, - "{0 1 3 4 5 6 7 8 9 10 11 12 13 14 15" - " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" - " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" - " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" - }, + {make_not_1_2, 0, 0, check_count, 2, "{0 3 ...}"},//68 + {make_0_1, make_not_1_2, set_union, check_count, 1, "{0 1 3 ...}"}, {make_0_1, make_not_1_2, set_intersection, check_count, 1, "{0}"}, {make_0_1, make_not_1_2, set_difference, check_count, 1, "{1}"}, - {make_0_1, make_not_1_2, set_reverse_difference, check_count, 3, - "{3 4 5 6 7 8 9 10 11 12 13 14 15" - " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" - " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" - " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" - }, - {make_not_1_2, make_0_1, set_union, check_count, 1, - "{0 1 3 4 5 6 7 8 9 10 11 12 13 14 15" - " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" - " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" - " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" - }, + {make_0_1, make_not_1_2, set_reverse_difference, check_count, 3, "{3 ...}"}, + {make_not_1_2, make_0_1, set_union, check_count, 1, "{0 1 3 ...}"}, {make_not_1_2, make_0_1, set_intersection, check_count, 1, "{0}"}, - {make_not_1_2, make_0_1, set_difference, check_count, 3, - "{3 4 5 6 7 8 9 10 11 12 13 14 15" - " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" - " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" - " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ...}" - }, + {make_not_1_2, make_0_1, set_difference, check_count, 3, "{3 ...}"}, {make_not_1_2, make_0_1, set_reverse_difference, check_count, 1, "{1}"}, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) @@ -303,33 +278,6 @@ main (int argc, const char **argv) dstring_appendstr (str, "}"); tests[6].str_expect = dstring_freeze (str); - str = dstring_new (); - for (i = 0; i < SIZE; i++) { - if (i == 1 || i == 2) - continue; - dasprintf (str, "%c%zd", i > 0 ? ' ' : '{', i); - } - dasprintf (str, " %zd ...}", i); - tests[68].str_expect = dstring_freeze (str); - - str = dstring_new (); - for (i = 0; i < SIZE; i++) { - if (i == 2) - continue; - dasprintf (str, "%c%zd", i > 0 ? ' ' : '{', i); - } - dasprintf (str, " %zd ...}", i); - tests[69].str_expect = dstring_freeze (str); - tests[73].str_expect = tests[69].str_expect; - - str = dstring_new (); - for (i = 3; i < SIZE; i++) { - dasprintf (str, "%c%zd", i > 3 ? ' ' : '{', i); - } - dasprintf (str, " %zd ...}", i); - tests[72].str_expect = dstring_freeze (str); - tests[75].str_expect = tests[72].str_expect; - for (i = 0; i < num_tests; i++) { set_t *s1, *s2 = 0; const char *set_str; From a01cafe972b833003e29490c591bf0a1956b37d6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 Aug 2021 17:10:16 +0900 Subject: [PATCH 1732/3664] [util] Minimize set growth At the low level, only unions can cause a set to grow. Of course, things get interesting at the higher level when infinite (inverted) sets are mixed in. --- include/QF/set.h | 9 ++++++ libs/util/set.c | 60 +++++++++++++++++++++++++++++++-------- libs/util/test/test-set.c | 36 ++++++++++++++++++++++- 3 files changed, 92 insertions(+), 13 deletions(-) diff --git a/include/QF/set.h b/include/QF/set.h index 57c8342de..1d59ed395 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -162,6 +162,15 @@ void set_delete_r (set_pool_t *set_pool, set_t *set); */ void set_expand (set_t *set, unsigned size); +/** Shrink the set's backing memory to the minimum required to hold the set. + + This does not affect (nor is affected by) whether the set is an infinite + set. + + \param set The set to trim +*/ +void set_trim (set_t *set); + /** Add an element to a set. It is not an error to add an element that is already a member of the set. diff --git a/libs/util/set.c b/libs/util/set.c index baabe1057..9b59172a1 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -128,6 +128,30 @@ set_expand (set_t *set, unsigned size) free (map); } +void +set_trim (set_t *set) +{ + if (set->map == set->defmap) { + return; + } + unsigned words = SET_WORDS (set); + + while (words > SET_DEFMAP_SIZE && !set->map[words - 1]) { + words--; + set->size -= SET_BITS; + } + if (words > SET_DEFMAP_SIZE) { + set_bits_t *map = realloc (set->map, words * sizeof (set_bits_t)); + if (map && map != set->map) { + set->map = map; + } + } else { + memcpy (set->defmap, set->map, sizeof (set->defmap)); + free (set->map); + set->map = set->defmap; + } +} + inline set_t * set_new_size_r (set_pool_t *set_pool, unsigned size) { @@ -204,13 +228,14 @@ _set_union (set_t *dst, const set_t *src) static set_t * _set_intersection (set_t *dst, const set_t *src) { - unsigned size; + unsigned words; unsigned i; - size = max (dst->size, src->size); - set_expand (dst, size); - for (i = 0; i < SET_WORDS (src); i++) + words = min (SET_WORDS (dst), SET_WORDS (src)); + for (i = 0; i < words; i++) dst->map[i] &= src->map[i]; + // if dst is larger than src, then none of the excess elements in dst + // can be in the intersection for ( ; i < SET_WORDS (dst); i++) dst->map[i] = 0; return dst; @@ -219,26 +244,37 @@ _set_intersection (set_t *dst, const set_t *src) static set_t * _set_difference (set_t *dst, const set_t *src) { - unsigned size; + unsigned words; unsigned i; - size = max (dst->size, src->size); - set_expand (dst, size); - for (i = 0; i < SET_WORDS (src); i++) + words = min (SET_WORDS (dst), SET_WORDS (src)); + for (i = 0; i < words; i++) dst->map[i] &= ~src->map[i]; + // if src is larger than dst, excess elements in src cannot be in dst thus + // there is nothing to remove + // if dst is larger than src, there is nothing to remove regardless of what + // is in src return dst; } static set_t * _set_reverse_difference (set_t *dst, const set_t *src) { - unsigned size; + unsigned words; unsigned i; - size = max (dst->size, src->size); - set_expand (dst, size); - for (i = 0; i < SET_WORDS (src); i++) + words = min (SET_WORDS (dst), SET_WORDS (src)); + set_expand (dst, src->size); + for (i = 0; i < words; i++) dst->map[i] = ~dst->map[i] & src->map[i]; + // if src is larger than dst, then dst cannot remove the excess elements + // from src and thus the src elements must be copied + for ( ; i < SET_WORDS (src); i++) + dst->map[i] = src->map[i]; + // if dst is larger than src, then the excess elements in dst must be + // removed + for ( ; i < SET_WORDS (dst); i++) + dst->map[i] = 0; return dst; } diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index 4569c0046..412517d22 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -250,7 +250,30 @@ struct { {make_not_1_2, make_0_1, set_union, check_count, 1, "{0 1 3 ...}"}, {make_not_1_2, make_0_1, set_intersection, check_count, 1, "{0}"}, {make_not_1_2, make_0_1, set_difference, check_count, 3, "{3 ...}"}, - {make_not_1_2, make_0_1, set_reverse_difference, check_count, 1, "{1}"}, + {make_not_1_2, make_0_1, set_reverse_difference, check_count, 1, "{1}"},//76 + {make_SIZE, make_not_1_2, set_union, check_size, SIZE + SET_BITS, + "{0 3 ...}"}, + {make_SIZE, make_not_1_2, set_intersection, check_size, SIZE + SET_BITS, + "{64}"}, + {make_SIZE, make_not_1_2, set_difference, check_size, SIZE + SET_BITS, + "{}"}, + {make_SIZE, make_not_1_2, set_reverse_difference, check_size, + SIZE + SET_BITS, + "{0 3 4 5 6 7 8 9 10 11 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 65 ...}" + },//80 + {make_not_1_2, make_SIZE, set_union, check_size, SIZE, "{0 3 ...}"}, + {make_not_1_2, make_SIZE, set_intersection, check_size, SIZE + SET_BITS, + "{64}"}, + {make_not_1_2, make_SIZE, set_difference, check_size, SIZE + SET_BITS, + "{0 3 4 5 6 7 8 9 10 11 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 65 ...}" + }, + {make_not_1_2, make_SIZE, set_reverse_difference, check_size, SIZE, "{}"}, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) @@ -270,6 +293,8 @@ main (int argc, const char **argv) tests[9].str_expect = tests[5].str_expect; tests[10].str_expect = tests[5].str_expect; tests[11].str_expect = tests[5].str_expect; + tests[78].str_expect = tests[5].str_expect; + tests[82].str_expect = tests[5].str_expect; str = dstring_new (); for (i = 0; i < SIZE; i++) { @@ -278,6 +303,15 @@ main (int argc, const char **argv) dstring_appendstr (str, "}"); tests[6].str_expect = dstring_freeze (str); + str = dstring_new (); + dasprintf (str, "{0"); + for (i = 3; i < SIZE; i++) { + dasprintf (str, " %zd", i); + } + dasprintf (str, " %zd ...}", SIZE + 1); + tests[80].str_expect = dstring_freeze (str); + tests[83].str_expect = tests[80].str_expect; + for (i = 0; i < num_tests; i++) { set_t *s1, *s2 = 0; const char *set_str; From 6fb6885b882cec40d99d9c45fc26cb0a73fc0be0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Aug 2021 11:21:05 +0900 Subject: [PATCH 1733/3664] [qfvis] Allocate only 128MB for the main hunk Even ad_tears didn't really need 1GB, and 32-bit machines can't really handle 1GB (at least on windows). --- tools/qfvis/source/qfvis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index ea0899a1d..263e9ebb2 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -1562,7 +1562,7 @@ main (int argc, char **argv) { double start, stop; QFile *f; - size_t main_memsize = 1024 * 1024 * 1024; + size_t main_memsize = 128 * 1024 * 1024; main_thread.memsuper = new_memsuper (); main_thread.hunk = Hunk_Init (Sys_Alloc (main_memsize), main_memsize); From d88bd96390698d87860b5df0feeb419690039867 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Aug 2021 11:22:36 +0900 Subject: [PATCH 1734/3664] [qfvis] Use cmem for portal flow stack node allocation The portal flow stack nodes contain a simd vector, which requires 16-byte alignment. However, on 32-bit Windows, malloc returns 8-byte aligned memory, leading to eventual segfaults. Since pstack_t is 48 bytes on 32-bit systems, it fits nicely into a 64-byte aligned cache line (or two on 64-bit systems due to being 80 bytes). --- tools/qfvis/source/flow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 618163e2e..27399eead 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -79,7 +79,7 @@ new_stack (threaddata_t *td) { pstack_t *stack; - stack = malloc (sizeof (pstack_t)); + stack = cmemalloc (td->memsuper, sizeof (pstack_t)); stack->next = 0; stack->mightsee = set_new_size_r (&td->set_pool, portalclusters); td->stats.stack_alloc++; From 8a5c3c1ac180c3fbdca5b1f699fa86c55dd2236e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Aug 2021 21:26:48 +0900 Subject: [PATCH 1735/3664] [util] Add sys function to get cpu count And use it in qfvis. --- include/QF/sys.h | 2 ++ libs/util/sys.c | 17 +++++++++++++++++ tools/qfvis/source/options.c | 7 ++----- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 19776a474..8f1dac325 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -125,6 +125,8 @@ size_t Sys_PageSize (void); void *Sys_Alloc (size_t size); void Sys_Free (void *mem, size_t size); +int Sys_ProcessorCount (void); + // // system IO // diff --git a/libs/util/sys.c b/libs/util/sys.c index a87c9df30..b96353ecd 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -663,6 +663,23 @@ Sys_Free (void *mem, size_t size) #endif } +VISIBLE int +Sys_ProcessorCount (void) +{ + int cpus = 1; +#if defined (_SC_NPROCESSORS_ONLN) + cpus = sysconf(_SC_NPROCESSORS_ONLN); +#elif defined (_WIN32) + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + cpus = sysinfo.dwNumberOfProcessors; +#endif + if (cpus < 1) { + cpus = 1; + } + return cpus; +} + VISIBLE void Sys_DebugLog (const char *file, const char *fmt, ...) { diff --git a/tools/qfvis/source/options.c b/tools/qfvis/source/options.c index 1d384d578..a0a8ff221 100644 --- a/tools/qfvis/source/options.c +++ b/tools/qfvis/source/options.c @@ -40,6 +40,7 @@ #include #include "QF/dstring.h" +#include "QF/sys.h" #include "tools/qfvis/include/options.h" #include "tools/qfvis/include/vis.h" @@ -105,11 +106,7 @@ default_threads (void) { int threads = 1; #ifdef USE_PTHREADS -# ifdef _SC_NPROCESSORS_ONLN - threads = sysconf(_SC_NPROCESSORS_ONLN); - if (threads < 1) - threads = 1; -# endif + threads = Sys_ProcessorCount (); #endif return threads; } From a91dac60d946c68589b50ca2034e64806886daca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Aug 2021 09:10:21 +0900 Subject: [PATCH 1736/3664] [input] Start work on improved input system The common input code (input outer loop and event handling) has been moved into libQFinput, and modified to have the concept of input drivers that are registered by the appropriate system-level code (x11, win, etc). As well, my evdev input library code (with hotplug support) has been added, but is not yet fully functional. However, the idea is that it will be available on all systems that support evdev (Linux, and from what I've read, FreeBSD). --- include/Makemodule.am | 2 + include/QF/input.h | 15 +- include/evdev/hotplug.h | 14 + include/evdev/inputlib.h | 46 +++ libs/input/Makemodule.am | 10 +- libs/input/evdev/hotplug.c | 124 ++++++ libs/input/evdev/inputlib.c | 479 ++++++++++++++++++++++ libs/{video/targets => input}/in_common.c | 49 ++- libs/input/in_evdev.c | 100 +++++ libs/{video/targets => input}/in_event.c | 0 libs/video/targets/Makemodule.am | 2 - libs/video/targets/context_x11.c | 3 + libs/video/targets/in_x11.c | 62 ++- ruamoko/qwaq/builtins/qwaq-curses.c | 4 + 14 files changed, 867 insertions(+), 43 deletions(-) create mode 100644 include/evdev/hotplug.h create mode 100644 include/evdev/inputlib.h create mode 100644 libs/input/evdev/hotplug.c create mode 100644 libs/input/evdev/inputlib.c rename libs/{video/targets => input}/in_common.c (81%) create mode 100644 libs/input/in_evdev.c rename libs/{video/targets => input}/in_event.c (100%) diff --git a/include/Makemodule.am b/include/Makemodule.am index 6d0039fc8..5c9db840e 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -85,6 +85,8 @@ EXTRA_DIST += \ include/client/locs.h \ include/client/state.h \ include/client/view.h \ + include/evdev/hotplug.h \ + include/evdev/inputlib.h \ include/qw/bothdefs.h \ include/qw/msg_backbuf.h \ include/qw/msg_ucmd.h \ diff --git a/include/QF/input.h b/include/QF/input.h index 7644af8cf..7b28a17af 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -35,12 +35,21 @@ typedef struct { vec3_t position; } viewdelta_t; +typedef struct { + void (*init) (void); + void (*shutdown) (void); + void (*process_events) (void); + void (*clear_states) (void); + void (*grab_input) (int grab); +} in_driver_t; + extern viewdelta_t viewdelta; #define freelook (in_mlook.state & 1 || in_freelook->int_val) struct cvar_s; +void IN_RegisterDriver (in_driver_t *driver); void IN_Init (struct cbuf_s *cbuf); void IN_Init_Cvars (void); @@ -64,12 +73,6 @@ extern struct cvar_s *lookstrafe; extern qboolean in_mouse_avail; extern float in_mouse_x, in_mouse_y; -void IN_LL_Init_Cvars (void); -void IN_LL_Init (void); -void IN_LL_Shutdown (void); -void IN_LL_ProcessEvents (void); -void IN_LL_ClearStates (void); -void IN_LL_Grab_Input (int grab); extern kbutton_t in_strafe, in_klook, in_speed, in_mlook; diff --git a/include/evdev/hotplug.h b/include/evdev/hotplug.h new file mode 100644 index 000000000..d24b8cabd --- /dev/null +++ b/include/evdev/hotplug.h @@ -0,0 +1,14 @@ +#ifndef evdev_hotplug_h +#define evdev_hotplug_h + +int inputlib_hotplug_init(const char *path, + void (*created) (const char*), + void (*deleted) (const char *)); + +void inputlib_hotplug_close (void); + +int inputlib_hotplug_add_select (fd_set *fdset, int *maxfd); + +int inputlib_hotplug_check_select (fd_set *fdset); + +#endif//evdev_hotplug_h diff --git a/include/evdev/inputlib.h b/include/evdev/inputlib.h new file mode 100644 index 000000000..de3e61caf --- /dev/null +++ b/include/evdev/inputlib.h @@ -0,0 +1,46 @@ +#ifndef evdev_inputlib_h +#define evdev_inputlib_h + +typedef struct { + int num; ///< The high-level index of the button. Always 0-N + int evnum; ///< The low-level index of the button. May be sparse + int state; ///< Current state of the button. +} button_t; + +typedef struct { + int num; ///< The high-level index of the axis. Always 0-N + int evnum; ///< The low-level index of the axis. May be sparse + int value; ///< Current value of the input axis. + // relative axes set these to 0 + int min; ///< Minimum value for the axis (usually constant). + int max; ///< Maximum value for the axis (usually constant). +} axis_t; + +typedef struct device_s { + struct device_s *next; + char *path; + char *name; + char *phys; + char *uniq; + int fd; + int max_button; + int *button_map; + int num_buttons; + button_t *buttons; + int max_abs_axis; + int *abs_axis_map; + int max_rel_axis; + int *rel_axis_map; + int num_abs_axes; + int num_rel_axes; + // includes both abs and rel axes, with abs first + int num_axes; + axis_t *axes; + int event_count; +} device_t; + +int inputlib_check_input (void); +void inputlib_close (void); +int inputlib_init (void (*dev_add) (device_t *), void (*dev_rem) (device_t *)); + +#endif//evdev_inputlib_h diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index 407eabd11..431857161 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -1,8 +1,16 @@ lib_LTLIBRARIES += libs/input/libQFinput.la +in_evdev_src= \ + libs/input/evdev/hotplug.c \ + libs/input/evdev/inputlib.c \ + libs/input/in_evdev.c + libs_input_libQFinput_la_LDFLAGS= $(lib_ldflags) libs_input_libQFinput_la_LIBADD= $(input_deps) libs_input_libQFinput_la_DEPENDENCIES= $(input_deps) libs_input_libQFinput_la_SOURCES= \ + $(in_evdev_src) \ libs/input/keys.c \ - libs/input/old_keys.c + libs/input/old_keys.c \ + libs/input/in_common.c \ + libs/input/in_event.c diff --git a/libs/input/evdev/hotplug.c b/libs/input/evdev/hotplug.c new file mode 100644 index 000000000..afaff2715 --- /dev/null +++ b/libs/input/evdev/hotplug.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "evdev/hotplug.h" + +static int inotify_fd; +static int devinput_wd; +static char *devinput_path; +static void (*device_deleted) (const char *name); +static void (*device_created) (const char *name); + +static unsigned +get_queue_size (int fd) +{ + unsigned queue_len; + int ret = ioctl (fd, FIONREAD, &queue_len); + if (ret < 0) { + perror ("ioctl"); + return 0; + } + return queue_len; +} + +static void +parse_inotify_events (int fd) +{ + ssize_t len, i; + ssize_t queue_len = get_queue_size (fd); + char *buf = alloca (queue_len); + struct inotify_event *event; + + len = read (fd, buf, queue_len); + for (i = 0; i < len; i += sizeof (struct inotify_event) + event->len) { + event = (struct inotify_event *) &buf[i]; + //printf ("%-3d %08x %5u %4d %s\n", event->wd, event->mask, + // event->cookie, event->len, + // event->len ? event->name : ""); + if ((event->mask & IN_DELETE) && event->len) { + if (strncmp (event->name, "event", 5) == 0) { + // interested in only evdev devices + //printf("deleted device %s\n", event->name); + device_deleted (event->name); + } + } + if (((event->mask & IN_ATTRIB) || (event->mask & IN_CREATE)) + && event->len) { + // done this way because may not have read permission when the + // device is created, so try again when (presumabely) permission is + // granted + if (strncmp (event->name, "event", 5) == 0) { + // interested in only evdev devices + //printf("created device %s\n", event->name); + device_created (event->name); + } + } + } +} + +int +inputlib_hotplug_init(const char *path, + void (*created) (const char*), + void (*deleted) (const char *)) +{ + inotify_fd = inotify_init (); + if (inotify_fd == -1) { + perror ("inotify_init"); + return -1; + } + devinput_wd = inotify_add_watch (inotify_fd, path, + IN_CREATE | IN_DELETE | IN_ATTRIB + | IN_ONLYDIR); + if (devinput_wd == -1) { + perror ("inotify_add_watch"); + close (inotify_fd); + return -1; + } + devinput_path = strdup (path); + device_created = created; + device_deleted = deleted; + //printf ("inputlib_hotplug_init: %s %d %d\n", path, inotify_fd, + // devinput_wd); + return 0; +} + +void +inputlib_hotplug_close (void) +{ + if (inotify_fd != -1) { + close (inotify_fd); + free (devinput_path); + device_created = 0; + device_deleted = 0; + } +} + +int +inputlib_hotplug_add_select (fd_set *fdset, int *maxfd) +{ + if (inotify_fd != -1) { + FD_SET (inotify_fd, fdset); + if (inotify_fd > *maxfd) { + *maxfd = inotify_fd; + } + } + return inotify_fd; +} + +int +inputlib_hotplug_check_select (fd_set *fdset) +{ + if (inotify_fd != -1) { + if (FD_ISSET (inotify_fd, fdset)) { + parse_inotify_events (inotify_fd); + return 1; + } + } + return 0; +} diff --git a/libs/input/evdev/inputlib.c b/libs/input/evdev/inputlib.c new file mode 100644 index 000000000..cf5ff7bbd --- /dev/null +++ b/libs/input/evdev/inputlib.c @@ -0,0 +1,479 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "QF/dstring.h" + +#include "evdev/hotplug.h" +#include "evdev/inputlib.h" + +static const char *devinput_path = "/dev/input"; +static device_t *devices; +void (*device_add) (device_t *); +void (*device_remove) (device_t *); + +static void +setup_buttons (device_t *dev) +{ + int i, j, len; + unsigned char buf[1024]; + button_t *button; + + dev->max_button = -1; + dev->num_buttons = 0; + dev->button_map = 0; + dev->buttons = 0; + len = ioctl (dev->fd, EVIOCGBIT (EV_KEY, sizeof (buf)), buf); + for (i = 0; i < len; i++) { + //printf("%c%02x", !(i % 16) ? '\n': !(i % 8) ? '-' : ' ', buf[i]); + for (j = 0; j < 8; j++) { + if (buf[i] & (1 << j)) { + dev->num_buttons++; + dev->max_button = i * 8 + j; + } + } + } + //printf("\n"); + dev->button_map = malloc ((dev->max_button + 1) * sizeof (int)); + dev->buttons = malloc (dev->num_buttons * sizeof (button_t)); + for (i = 0, button = dev->buttons; i < len; i++) { + for (j = 0; j < 8; j++) { + int button_ind = i * 8 + j; + if (buf[i] & (1 << j)) { + button->num = button - dev->buttons; + button->evnum = button_ind; + button->state = 0; + dev->button_map[button_ind] = button->num; + + button++; + } else { + if (button_ind <= dev->max_button) { + dev->button_map[button_ind] = -1; + } + } + } + } + len = ioctl (dev->fd, EVIOCGKEY (sizeof (buf)), buf); + for (i = 0; i < dev->num_buttons; i++) { + int key = dev->buttons[i].evnum; + dev->buttons[i].state = !!(buf[key / 8] & (1 << (key % 8))); + } +} + +static int +count_axes (const unsigned char *buf, int len, int *max_axis) +{ + int count = 0; + int i, j; + + for (i = 0; i < len; i++) { + for (j = 0; j < 8; j++) { + if (buf[i] & (1 << j)) { + count++; + *max_axis = i * 8 + j; + } + } + } + return count; +} + +static void +abs_info (device_t *dev, int axis_ind, axis_t *axis) +{ + struct input_absinfo absinfo; + ioctl (dev->fd, EVIOCGABS(axis_ind), &absinfo); + axis->value = absinfo.value; + axis->min = absinfo.minimum; + axis->max = absinfo.maximum; + +} + +static void +rel_info (device_t *dev, int axis_ind, axis_t *axis) +{ + // relative axes are marked by having 0 min/max + axis->value = 0; + axis->min = 0; + axis->max = 0; +} + +static void +map_axes (const unsigned char *buf, int len, device_t *dev, + int max_axis, int *axis_map, axis_t *first_axis, + void (*info)(device_t*, int, axis_t *)) +{ + int i, j; + axis_t *axis; + + for (i = 0, axis = first_axis; i < len; i++) { + for (j = 0; j < 8; j++) { + int axis_ind = i * 8 + j; + if (buf[i] & (1 << j)) { + axis->num = axis - dev->axes; + axis->evnum = axis_ind; + axis_map[axis_ind] = axis->num; + info (dev, axis_ind, axis); + axis++; + } else { + if (axis_ind <= max_axis) { + axis_map[axis_ind] = -1; + } + } + } + } +} + +static void +setup_axes (device_t *dev) +{ + int alen, rlen; + unsigned char abuf[1024]; + unsigned char rbuf[1024]; + + dev->max_abs_axis = -1; + dev->max_rel_axis = -1; + dev->num_axes = 0; + dev->abs_axis_map = 0; + dev->rel_axis_map = 0; + dev->axes = 0; + + alen = ioctl (dev->fd, EVIOCGBIT (EV_ABS, sizeof (abuf)), abuf); + rlen = ioctl (dev->fd, EVIOCGBIT (EV_REL, sizeof (rbuf)), rbuf); + + dev->num_abs_axes = count_axes (abuf, alen, &dev->max_abs_axis); + dev->num_rel_axes = count_axes (rbuf, alen, &dev->max_rel_axis); + + dev->num_axes = dev->num_abs_axes + dev->num_rel_axes; + + dev->abs_axis_map = malloc ((dev->max_abs_axis + 1) * sizeof (int)); + dev->rel_axis_map = malloc ((dev->max_rel_axis + 1) * sizeof (int)); + + dev->axes = malloc (dev->num_axes * sizeof (axis_t)); + map_axes (abuf, alen, dev, dev->max_abs_axis, dev->abs_axis_map, + dev->axes, abs_info); + map_axes (rbuf, rlen, dev, dev->max_rel_axis, dev->rel_axis_map, + dev->axes + dev->num_abs_axes, rel_info); +} + +static void device_created (const char *name); +static void device_deleted (const char *name); + +#define get_string(fd, ioctlid, dstr) \ + ({ \ + int size; \ + while ((size = ioctl (fd, ioctlid (dstr->truesize), dstr->str)) \ + == (int) dstr->truesize) { \ + dstr->size = dstr->truesize + 1024; \ + dstring_adjust (dstr); \ + } \ + dstr->size = size <= 0 ? 1 : size; \ + dstr->str[dstr->size - 1] = 0; \ + dstr->str; \ + }) + +static int +check_device (const char *path) +{ + device_t *dev; + int fd; + dstring_t *buff = dstring_newstr (); + + fd = open (path, O_RDWR); + if (fd == -1) + return -1; + + dev = malloc (sizeof (device_t)); + dev->next = devices; + devices = dev; + + dev->path = strdup (path); + dev->fd = fd; + + dev->name = strdup (get_string (fd, EVIOCGNAME, buff)); + dev->phys = strdup (get_string (fd, EVIOCGPHYS, buff)); + dev->uniq = strdup (get_string (fd, EVIOCGUNIQ, buff)); + + setup_buttons(dev); + setup_axes(dev); + + dev->event_count = 0; + + printf ("%s:\n", path); + printf ("\tname: %s\n", dev->name); + printf ("\tbuttons: %d\n", dev->num_buttons); + printf ("\taxes: %d\n", dev->num_axes); + + if (device_add) { + device_add (dev); + } + + return fd; +} + +/*static const char *event_codes[] = { + "EV_SYN", + "EV_KEY", + "EV_REL", + "EV_ABS", + "EV_MSC", + "EV_SW", + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + "EV_LED", + "EV_SND", + "EV_REP", + "EV_FF", + "EV_PWR", + "EV_FF_STATUS", +};*/ + +static void +read_device_input (device_t *dev) +{ + struct input_event event; + button_t *button; + axis_t *axis; + //int i; + + // zero motion counters for relative axes + //for (i = dev->num_abs_axes; i < dev->num_axes; i++) { + // dev->axes[i].value = 0; + //} + + while (1) { + if (read (dev->fd, &event, sizeof (event)) < 0) { + perror(dev->name); + dev->fd = -1; + return; + } + //const char *ev = event_codes[event.type]; + //printf ("%6d(%s) %6d %6x\n", event.type, ev ? ev : "?", event.code, event.value); + switch (event.type) { + case EV_SYN: + dev->event_count++; + return; + case EV_KEY: + button = &dev->buttons[dev->button_map[event.code]]; + button->state = event.value; + break; + case EV_ABS: + axis = &dev->axes[dev->abs_axis_map[event.code]]; + axis->value = event.value; + break; + case EV_MSC: + break; + case EV_REL: + axis = &dev->axes[dev->rel_axis_map[event.code]]; + //printf ("EV_REL %6d %6x %6d %p\n", event.code, event.value, + // dev->rel_axis_map[event.code], axis); + axis->value = event.value; + break; + case EV_SW: + case EV_LED: + case EV_SND: + case EV_REP: + case EV_FF: + case EV_PWR: + case EV_FF_STATUS: + //printf ("%6d %6d %6x\n", event.type, event.code, event.value); + break; + } + } +} + +int +inputlib_check_input (void) +{ + fd_set fdset; + struct timeval _timeout; + struct timeval *timeout = &_timeout; + int res; + int maxfd = -1; + device_t *dev; + + _timeout.tv_sec = 0; + _timeout.tv_usec = 0; + + FD_ZERO (&fdset); + + inputlib_hotplug_add_select (&fdset, &maxfd); + + for (dev = devices; dev; dev = dev->next) { + if (dev->fd < 0) { + continue; + } + FD_SET (dev->fd, &fdset); + if (dev->fd > maxfd) { + maxfd = dev->fd; + } + } + if (maxfd < 0) { + return 0; + } + res = select (maxfd + 1, &fdset, NULL, NULL, timeout); + if (res <= 0) { + return 0; + } + + inputlib_hotplug_check_select (&fdset); + + for (dev = devices; dev; dev = dev->next) { + if (dev->fd < 0) { + continue; + } + if (FD_ISSET (dev->fd, &fdset)) { + read_device_input (dev); + } + } + return 1; +} + +static void +close_device (device_t *dev) +{ + if (device_remove) { + device_remove (dev); + } + close (dev->fd); + free (dev->button_map); + if (dev->buttons) { + free (dev->buttons); + } + free (dev->abs_axis_map); + free (dev->rel_axis_map); + if (dev->axes) { + free (dev->axes); + } + free (dev->name); + free (dev->path); +} + +static char * +make_devname (const char *path, const char *name) +{ + int plen = strlen (path); + int nlen = strlen (name); + char *devname = malloc (plen + nlen + 2); + + strcpy (devname, path); + devname[plen] = '/'; + strcpy (devname + plen + 1, name); + + return devname; +} + +static int +check_input_device (const char *path, const char *name) +{ + int ret; + char *devname = make_devname (path, name); + + //puts (devname); + ret = check_device (devname); + free (devname); + return ret; +} + +static void +device_created (const char *name) +{ + char *devname = make_devname (devinput_path, name); + device_t *dev; + int olddev = 0; + + for (dev = devices; dev; dev = dev->next) { + if (strcmp (dev->path, devname) == 0) { + // already have this device open + olddev = 1; + break; + } + } + if (!olddev && check_device (devname) >= 0) { + //printf ("found device %s\n", devname); + } + free (devname); +} + +static void +device_deleted (const char *name) +{ + char *devname = make_devname (devinput_path, name); + device_t **dev; + + for (dev = &devices; *dev; dev = &(*dev)->next) { + if (strcmp ((*dev)->path, devname) == 0) { + //printf ("lost device %s\n", (*dev)->path); + close_device (*dev); + device_t *d = *dev; + *dev = (*dev)->next; + free (d); + break; + } + } + free (devname); +} + +static int +scan_devices (void) +{ + struct dirent *dirent; + DIR *dir; + + dir = opendir (devinput_path); + if (!dir) { + return -1; + } + + while ((dirent = readdir (dir))) { + if (dirent->d_type != DT_CHR) { + continue; + } + if (strncmp (dirent->d_name, "event", 5)) { + continue; + } + if (check_input_device (devinput_path, dirent->d_name) < 0) { + continue; + } + //printf("%s\n", dirent->d_name); + } + closedir (dir); + return 0; +} + +int +inputlib_init (void (*dev_add) (device_t *), void (*dev_rem) (device_t *)) +{ + device_add = dev_add; + device_remove = dev_rem; + if (scan_devices () != -1) { + inputlib_hotplug_init (devinput_path, device_created, device_deleted); + return 0; + } + return -1; +} + +void +inputlib_close (void) +{ + inputlib_hotplug_close (); + while (devices) { + close_device (devices); + device_t *dev = devices; + devices = devices->next; + free (dev); + } +} diff --git a/libs/video/targets/in_common.c b/libs/input/in_common.c similarity index 81% rename from libs/video/targets/in_common.c rename to libs/input/in_common.c index a61401ceb..7668bc323 100644 --- a/libs/video/targets/in_common.c +++ b/libs/input/in_common.c @@ -49,6 +49,7 @@ #include "QF/cbuf.h" #include "QF/cvar.h" +#include "QF/darray.h" #include "QF/in_event.h" #include "QF/input.h" #include "QF/joystick.h" @@ -57,6 +58,8 @@ #include "QF/sys.h" #include "QF/vid.h" +static struct DARRAY_TYPE (in_driver_t) in_drivers = { .grow = 8, }; + VISIBLE viewdelta_t viewdelta; cvar_t *in_grab; @@ -76,26 +79,36 @@ qboolean in_mouse_avail; float in_mouse_x, in_mouse_y; static float in_old_mouse_x, in_old_mouse_y; +void +IN_RegisterDriver (in_driver_t *driver) +{ + DARRAY_APPEND (&in_drivers, *driver); +} + void IN_UpdateGrab (cvar_t *var) // called from context_*.c { if (var) { - IN_LL_Grab_Input (var->int_val); + for (size_t i = 0; i < in_drivers.size; i++) { + if (in_drivers.a[i].grab_input) { + in_drivers.a[i].grab_input (var->int_val); + } + } } } void IN_ProcessEvents (void) { - /* Get events from environment. */ - JOY_Command (); - IN_LL_ProcessEvents (); + for (size_t i = 0; i < in_drivers.size; i++) { + in_drivers.a[i].process_events (); + } } void IN_Move (void) { - JOY_Move (); + //JOY_Move (); if (!in_mouse_avail) return; @@ -131,10 +144,14 @@ IN_Move (void) static void IN_shutdown (void *data) { - JOY_Shutdown (); + //JOY_Shutdown (); Sys_MaskPrintf (SYS_vid, "IN_Shutdown\n"); - IN_LL_Shutdown (); + for (size_t i = in_drivers.size; i-- > 0; ) { + if (in_drivers.a[i].shutdown) { + in_drivers.a[i].shutdown (); + } + } IE_Shutdown (); } @@ -145,9 +162,11 @@ IN_Init (cbuf_t *cbuf) Sys_RegisterShutdown (IN_shutdown, 0); IE_Init (); - IN_LL_Init (); + for (size_t i = 0; i < in_drivers.size; i++) { + in_drivers.a[i].init (); + } Key_Init (cbuf); - JOY_Init (); + //JOY_Init (); in_mouse_x = in_mouse_y = 0.0; } @@ -157,7 +176,7 @@ IN_Init_Cvars (void) { IE_Init_Cvars (); Key_Init_Cvars (); - JOY_Init_Cvars (); + //JOY_Init_Cvars (); in_grab = Cvar_Get ("in_grab", "0", CVAR_ARCHIVE, IN_UpdateGrab, "With this set to 1, quake will grab the mouse, " "preventing loss of input focus."); @@ -175,12 +194,18 @@ IN_Init_Cvars (void) "mouse in_mouse_pre_amp multiplier"); lookstrafe = Cvar_Get ("lookstrafe", "0", CVAR_ARCHIVE, NULL, "when mlook/klook on player will strafe"); - IN_LL_Init_Cvars (); } void IN_ClearStates (void) { - IN_LL_ClearStates (); + for (size_t i = 0; i < in_drivers.size; i++) { + if (in_drivers.a[i].clear_states) { + in_drivers.a[i].clear_states (); + } + } Key_ClearStates (); } + +extern int in_evdev_force_link; +static __attribute__((used)) int *evdev_force_link = &in_evdev_force_link; diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c new file mode 100644 index 000000000..cea94ef95 --- /dev/null +++ b/libs/input/in_evdev.c @@ -0,0 +1,100 @@ +/* + in_evdev.c + + general evdev input driver + + Copyright (C) 2021 Bill Currie + Please see the file "AUTHORS" for a list of contributors + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/input.h" +#include "QF/sys.h" + +#include "compat.h" +#include "evdev/inputlib.h" + +static void +in_evdev_keydest_callback (keydest_t key_dest, void *data) +{ +} + +static void +in_evdev_process_events (void) +{ + if (inputlib_check_input ()) { + } +} + +static void +in_evdev_shutdown (void) +{ + inputlib_close (); +} + +static void +device_add (device_t *dev) +{ +} + +static void +device_remove (device_t *dev) +{ +} + +static void +in_evdev_init (void) +{ + Key_KeydestCallback (in_evdev_keydest_callback, 0); + + inputlib_init (device_add, device_remove); +} + +static void +in_evdev_clear_states (void) +{ +} + +static in_driver_t in_evdev_driver = { + .init = in_evdev_init, + .shutdown = in_evdev_shutdown, + .process_events = in_evdev_process_events, + .clear_states = in_evdev_clear_states, +}; + +static void __attribute__((constructor)) +in_evdev_register_driver (void) +{ + IN_RegisterDriver (&in_evdev_driver); +} + +int in_evdev_force_link; diff --git a/libs/video/targets/in_event.c b/libs/input/in_event.c similarity index 100% rename from libs/video/targets/in_event.c rename to libs/input/in_event.c diff --git a/libs/video/targets/Makemodule.am b/libs/video/targets/Makemodule.am index ebee7b19f..2f0773053 100644 --- a/libs/video/targets/Makemodule.am +++ b/libs/video/targets/Makemodule.am @@ -56,8 +56,6 @@ libs_video_targets_libQFjs_la_SOURCES= libs/video/targets/joy.c $(joy_src) EXTRA_libs_video_targets_libQFjs_la_SOURCES= $(joy_linux_src) $(joy_win_src) $(joy_null_src) libs_video_targets_libvid_common_la_SOURCES = \ - libs/video/targets/in_common.c \ - libs/video/targets/in_event.c \ libs/video/targets/vid.c libs_video_targets_libvid_common_la_CFLAGS= @PREFER_NON_PIC@ libs_video_targets_libvid_common_la_LDFLAGS= @STATIC@ diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 26d4303f4..5052fd3b3 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -685,3 +685,6 @@ X11_RestoreMouseAcceleration (void) accel_denominator, accel_threshold); accel_saved = false; } + +extern int x11_force_link; +static __attribute__((used)) int *context_x11_force_link = &x11_force_link; diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 1cb682416..ba9380d42 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -597,7 +597,7 @@ XLateKey (XKeyEvent * ev, int *k, int *u) } static void -x11_keydest_callback (keydest_t key_dest, void *data) +in_x11_keydest_callback (keydest_t key_dest, void *data) { // if (key_dest == key_game) { // XAutoRepeatOff (x_disp); @@ -742,8 +742,8 @@ grab_error (int code, const char *device) Sys_Printf ("failed to grab %s: %s\n", device, reason); } -void -IN_LL_Grab_Input (int grab) +static void +in_x11_grab_input (int grab) { if (!x_disp || !x_win) return; @@ -780,16 +780,16 @@ IN_LL_Grab_Input (int grab) } } -void -IN_LL_ProcessEvents (void) +static void +in_x11_process_events (void) { X11_ProcessEvents (); // Get events from X server. } -void -IN_LL_Shutdown (void) +static void +in_x11_shutdown (void) { - Sys_MaskPrintf (SYS_vid, "IN_LL_Shutdown\n"); + Sys_MaskPrintf (SYS_vid, "in_x11_shutdown\n"); in_mouse_avail = 0; if (x_disp) { // XAutoRepeatOn (x_disp); @@ -800,8 +800,20 @@ IN_LL_Shutdown (void) X11_CloseDisplay (); } -void -IN_LL_Init (void) +static void +in_x11_init_cvars (void) +{ + in_snd_block = Cvar_Get ("in_snd_block", "0", CVAR_ARCHIVE, NULL, + "block sound output on window focus loss"); + in_dga = Cvar_Get ("in_dga", "0", CVAR_ARCHIVE, in_dga_f, //FIXME 0 until X fixed + "DGA Input support"); + in_mouse_accel = Cvar_Get ("in_mouse_accel", "1", CVAR_ARCHIVE, + in_mouse_accel_f, + "set to 0 to remove mouse acceleration"); +} + +static void +in_x11_init (void) { // open the display if (!x_disp) @@ -809,6 +821,8 @@ IN_LL_Init (void) if (!x_win) Sys_Error ("IN: No window!!"); + in_x11_init_cvars (); + X11_OpenDisplay (); // call to increment the reference counter { @@ -842,25 +856,29 @@ IN_LL_Init (void) in_mouse_avail = 1; } - Key_KeydestCallback (x11_keydest_callback, 0); + Key_KeydestCallback (in_x11_keydest_callback, 0); Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, "Paste the contents of X's C&P buffer to the console"); } -void -IN_LL_Init_Cvars (void) +static void +in_x11_clear_states (void) { - in_snd_block = Cvar_Get ("in_snd_block", "0", CVAR_ARCHIVE, NULL, - "block sound output on window focus loss"); - in_dga = Cvar_Get ("in_dga", "0", CVAR_ARCHIVE, in_dga_f, //FIXME 0 until X fixed - "DGA Input support"); - in_mouse_accel = Cvar_Get ("in_mouse_accel", "1", CVAR_ARCHIVE, - in_mouse_accel_f, - "set to 0 to remove mouse acceleration"); } -void -IN_LL_ClearStates (void) +static in_driver_t in_x11_driver = { + .init = in_x11_init, + .shutdown = in_x11_shutdown, + .process_events = in_x11_process_events, + .clear_states = in_x11_clear_states, + .grab_input = in_x11_grab_input, +}; + +static void __attribute__((constructor)) +in_x11_register_driver (void) { + IN_RegisterDriver (&in_x11_driver); } + +int x11_force_link; diff --git a/ruamoko/qwaq/builtins/qwaq-curses.c b/ruamoko/qwaq/builtins/qwaq-curses.c index 717617762..354f7acb9 100644 --- a/ruamoko/qwaq/builtins/qwaq-curses.c +++ b/ruamoko/qwaq/builtins/qwaq-curses.c @@ -43,6 +43,7 @@ #include "QF/cvar.h" #include "QF/gib.h" #include "QF/idparse.h" +#include "QF/input.h" #include "QF/keys.h" #include "QF/progs.h" #include "QF/qargs.h" @@ -74,6 +75,9 @@ qwaq_init_threads (qwaq_thread_set_t *thread_data) { int main_ind = -1; + IN_Init_Cvars (); + IN_Init (qwaq_cbuf); + for (size_t i = 1, thread_ind = 0; i < thread_data->size; i++) { qwaq_thread_t *thread = thread_data->a[i]; progsinit_f *app_funcs = target_app; From 5d4013b485104a4a81c55b72173fdffdbe344f9c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Aug 2021 11:22:57 +0900 Subject: [PATCH 1737/3664] [util] Use clock_gettime for Sys_LongTime While QF doesn't currently use nanoseconds, having access to a clock that is not affected by setting system time is nice, and as a bonus, can handle suspends should the need arise. --- libs/util/sys.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libs/util/sys.c b/libs/util/sys.c index b96353ecd..5176ef123 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -388,14 +388,22 @@ Sys_LongTime (void) + ((currqpccount - lastqpccount) * 1000000 / qpcfreq) + qpcfudge); # endif #else - struct timeval tp; - struct timezone tzp; int64_t now; static int64_t start_time; +#ifdef CLOCK_BOOTTIME + struct timespec tp; + + clock_gettime (CLOCK_BOOTTIME, &tp); + + now = tp.tv_sec * 1000000 + tp.tv_nsec / 1000; +#else + struct timeval tp; + struct timezone tzp; gettimeofday (&tp, &tzp); now = tp.tv_sec * 1000000 + tp.tv_usec; +#endif if (first) { first = false; From 05215e029535d78de7f7665deb435d0305a584b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Aug 2021 12:10:05 +0900 Subject: [PATCH 1738/3664] [util] Add functions to help convert external times --- include/QF/sys.h | 2 ++ libs/util/sys.c | 32 ++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 8f1dac325..abf7d4e37 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -78,8 +78,10 @@ void Sys_FatalError (const char *error, ...) __attribute__((format(PRINTF,1,2), void Sys_Quit (void) __attribute__((noreturn)); void Sys_Shutdown (void); void Sys_RegisterShutdown (void (*func) (void *), void *data); +int64_t Sys_StartTime (void) __attribute__ ((const)); int64_t Sys_LongTime (void); double Sys_DoubleTime (void); +int64_t Sys_TimeBase (void) __attribute__ ((const)); double Sys_DoubleTimeBase (void) __attribute__ ((const)); void Sys_TimeOfDay(date_t *date); diff --git a/libs/util/sys.c b/libs/util/sys.c index 5176ef123..9aad2ee6b 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -320,6 +320,14 @@ Sys_MaskPrintf (int mask, const char *fmt, ...) va_end (args); } +static int64_t sys_starttime = -1; + +VISIBLE int64_t +Sys_StartTime (void) +{ + return sys_starttime; +} + VISIBLE int64_t Sys_LongTime (void) { @@ -353,11 +361,10 @@ Sys_LongTime (void) static int64_t qpcfudge = 0; int64_t currtime = 0; static int64_t lasttime = 0; - static int64_t starttime = 0; if (first) { timeBeginPeriod (1); - starttime = lasttime = timeGetTime (); + sys_starttime = lasttime = timeGetTime () * 1000; QueryPerformanceFrequency ((LARGE_INTEGER *) &qpcfreq); QueryPerformanceCounter ((LARGE_INTEGER *) &lastqpccount); first = false; @@ -365,7 +372,7 @@ Sys_LongTime (void) } // get the current time from both counters - currtime = timeGetTime (); + currtime = timeGetTime () * 1000; QueryPerformanceCounter ((LARGE_INTEGER *) &currqpccount); if (currtime != lasttime) { @@ -376,7 +383,7 @@ Sys_LongTime (void) // store back times and calc a fudge factor as timeGetTime can // overshoot on a sub-millisecond scale qpcfudge = (( (currqpccount - lastqpccount) * 1000000 / qpcfreq)) - - ((currtime - lasttime) * 1000); + - (currtime - lasttime); lastqpccount = currqpccount; lasttime = currtime; } else { @@ -384,12 +391,11 @@ Sys_LongTime (void) } // the final time is the base from timeGetTime plus an addition from QPC - return (((currtime - starttime) * 1000) + return ((currtime - sys_starttime) + ((currqpccount - lastqpccount) * 1000000 / qpcfreq) + qpcfudge); # endif #else int64_t now; - static int64_t start_time; #ifdef CLOCK_BOOTTIME struct timespec tp; @@ -407,23 +413,29 @@ Sys_LongTime (void) if (first) { first = false; - start_time = now; + sys_starttime = now; } - return now - start_time; + return now - sys_starttime; #endif } +VISIBLE int64_t +Sys_TimeBase (void) +{ + return __INT64_C (4294967296000000); +} + VISIBLE double Sys_DoubleTime (void) { - return (__INT64_C (4294967296000000) + Sys_LongTime ()) / 1e6; + return (Sys_TimeBase () + Sys_LongTime ()) / 1e6; } VISIBLE double Sys_DoubleTimeBase (void) { - return __INT64_C (4294967296000000) / 1e6; + return Sys_TimeBase () / 1e6; } VISIBLE void From b39b6031e80774bed64370272354410d8636876a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Aug 2021 09:54:36 +0900 Subject: [PATCH 1739/3664] [input] Give input drivers a private data pointer The pointer can be updated at any time using the driver handle (returned by IN_RegisterData). --- include/QF/input.h | 13 ++++++------ libs/input/in_common.c | 42 ++++++++++++++++++++++++++----------- libs/input/in_evdev.c | 15 ++++++++----- libs/video/targets/in_x11.c | 12 +++++------ 4 files changed, 53 insertions(+), 29 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 7b28a17af..e09ac6c3c 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -36,11 +36,11 @@ typedef struct { } viewdelta_t; typedef struct { - void (*init) (void); - void (*shutdown) (void); - void (*process_events) (void); - void (*clear_states) (void); - void (*grab_input) (int grab); + void (*init) (void *data); + void (*shutdown) (void *data); + void (*process_events) (void *data); + void (*clear_states) (void *data); + void (*grab_input) (void *data, int grab); } in_driver_t; extern viewdelta_t viewdelta; @@ -49,7 +49,8 @@ extern viewdelta_t viewdelta; struct cvar_s; -void IN_RegisterDriver (in_driver_t *driver); +int IN_RegisterDriver (in_driver_t *driver, void *data); +void IN_DriverData (int handlle, void *data); void IN_Init (struct cbuf_s *cbuf); void IN_Init_Cvars (void); diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 7668bc323..609bb0344 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -58,7 +58,12 @@ #include "QF/sys.h" #include "QF/vid.h" -static struct DARRAY_TYPE (in_driver_t) in_drivers = { .grow = 8, }; +typedef struct { + in_driver_t driver; + void *data; +} in_regdriver_t; + +static struct DARRAY_TYPE (in_regdriver_t) in_drivers = { .grow = 8, }; VISIBLE viewdelta_t viewdelta; @@ -79,10 +84,18 @@ qboolean in_mouse_avail; float in_mouse_x, in_mouse_y; static float in_old_mouse_x, in_old_mouse_y; -void -IN_RegisterDriver (in_driver_t *driver) +int +IN_RegisterDriver (in_driver_t *driver, void *data) { - DARRAY_APPEND (&in_drivers, *driver); + in_regdriver_t rdriver = { *driver, data }; + DARRAY_APPEND (&in_drivers, rdriver); + return in_drivers.size - 1; +} + +void +IN_DriverData (int handle, void *data) +{ + in_drivers.a[handle].data = data; } void @@ -90,8 +103,9 @@ IN_UpdateGrab (cvar_t *var) // called from context_*.c { if (var) { for (size_t i = 0; i < in_drivers.size; i++) { - if (in_drivers.a[i].grab_input) { - in_drivers.a[i].grab_input (var->int_val); + in_regdriver_t *rd = &in_drivers.a[i]; + if (rd->driver.grab_input) { + rd->driver.grab_input (rd->data, var->int_val); } } } @@ -101,7 +115,8 @@ void IN_ProcessEvents (void) { for (size_t i = 0; i < in_drivers.size; i++) { - in_drivers.a[i].process_events (); + in_regdriver_t *rd = &in_drivers.a[i]; + rd->driver.process_events (rd->data); } } @@ -148,8 +163,9 @@ IN_shutdown (void *data) Sys_MaskPrintf (SYS_vid, "IN_Shutdown\n"); for (size_t i = in_drivers.size; i-- > 0; ) { - if (in_drivers.a[i].shutdown) { - in_drivers.a[i].shutdown (); + in_regdriver_t *rd = &in_drivers.a[i]; + if (rd->driver.shutdown) { + rd->driver.shutdown (rd->data); } } @@ -163,7 +179,8 @@ IN_Init (cbuf_t *cbuf) IE_Init (); for (size_t i = 0; i < in_drivers.size; i++) { - in_drivers.a[i].init (); + in_regdriver_t *rd = &in_drivers.a[i]; + rd->driver.init (rd->data); } Key_Init (cbuf); //JOY_Init (); @@ -200,8 +217,9 @@ void IN_ClearStates (void) { for (size_t i = 0; i < in_drivers.size; i++) { - if (in_drivers.a[i].clear_states) { - in_drivers.a[i].clear_states (); + in_regdriver_t *rd = &in_drivers.a[i]; + if (rd->driver.clear_states) { + rd->driver.clear_states (rd->data); } } Key_ClearStates (); diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index cea94ef95..125d12e64 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -49,14 +49,14 @@ in_evdev_keydest_callback (keydest_t key_dest, void *data) } static void -in_evdev_process_events (void) +in_evdev_process_events (void *data) { if (inputlib_check_input ()) { } } static void -in_evdev_shutdown (void) +in_evdev_shutdown (void *data) { inputlib_close (); } @@ -64,15 +64,20 @@ in_evdev_shutdown (void) static void device_add (device_t *dev) { + Sys_Printf ("in_evdev: add %s\n", dev->path); + Sys_Printf (" %s\n", dev->name); + Sys_Printf (" %s\n", dev->phys); + Sys_Printf (" %s\n", dev->uniq); } static void device_remove (device_t *dev) { + Sys_Printf ("in_evdev: remove %s\n", dev->path); } static void -in_evdev_init (void) +in_evdev_init (void *data) { Key_KeydestCallback (in_evdev_keydest_callback, 0); @@ -80,7 +85,7 @@ in_evdev_init (void) } static void -in_evdev_clear_states (void) +in_evdev_clear_states (void *data) { } @@ -94,7 +99,7 @@ static in_driver_t in_evdev_driver = { static void __attribute__((constructor)) in_evdev_register_driver (void) { - IN_RegisterDriver (&in_evdev_driver); + IN_RegisterDriver (&in_evdev_driver, 0); } int in_evdev_force_link; diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index ba9380d42..024847c36 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -743,7 +743,7 @@ grab_error (int code, const char *device) } static void -in_x11_grab_input (int grab) +in_x11_grab_input (void *data, int grab) { if (!x_disp || !x_win) return; @@ -781,13 +781,13 @@ in_x11_grab_input (int grab) } static void -in_x11_process_events (void) +in_x11_process_events (void *data) { X11_ProcessEvents (); // Get events from X server. } static void -in_x11_shutdown (void) +in_x11_shutdown (void *data) { Sys_MaskPrintf (SYS_vid, "in_x11_shutdown\n"); in_mouse_avail = 0; @@ -813,7 +813,7 @@ in_x11_init_cvars (void) } static void -in_x11_init (void) +in_x11_init (void *data) { // open the display if (!x_disp) @@ -863,7 +863,7 @@ in_x11_init (void) } static void -in_x11_clear_states (void) +in_x11_clear_states (void *data) { } @@ -878,7 +878,7 @@ static in_driver_t in_x11_driver = { static void __attribute__((constructor)) in_x11_register_driver (void) { - IN_RegisterDriver (&in_x11_driver); + IN_RegisterDriver (&in_x11_driver, 0); } int x11_force_link; From 5d1e515e9efe7dc09b816a0fdb76609100490c17 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Aug 2021 09:59:30 +0900 Subject: [PATCH 1740/3664] [qwaq] Hook up input to a certain extent Really, just enough to show that the initialization process and hotplug are working. The qwaq input driver is not yet properly integrated. --- libs/input/evdev/inputlib.c | 25 ++++---- ruamoko/qwaq/builtins/curses.c | 11 ---- ruamoko/qwaq/builtins/input.c | 94 ++++++++++++++++++++--------- ruamoko/qwaq/builtins/qwaq-curses.c | 12 ++++ 4 files changed, 91 insertions(+), 51 deletions(-) diff --git a/libs/input/evdev/inputlib.c b/libs/input/evdev/inputlib.c index cf5ff7bbd..065c57dc0 100644 --- a/libs/input/evdev/inputlib.c +++ b/libs/input/evdev/inputlib.c @@ -17,6 +17,7 @@ #include #include "QF/dstring.h" +#include "QF/sys.h" #include "evdev/hotplug.h" #include "evdev/inputlib.h" @@ -39,7 +40,7 @@ setup_buttons (device_t *dev) dev->buttons = 0; len = ioctl (dev->fd, EVIOCGBIT (EV_KEY, sizeof (buf)), buf); for (i = 0; i < len; i++) { - //printf("%c%02x", !(i % 16) ? '\n': !(i % 8) ? '-' : ' ', buf[i]); + //Sys_Printf("%c%02x", !(i % 16) ? '\n': !(i % 8) ? '-' : ' ', buf[i]); for (j = 0; j < 8; j++) { if (buf[i] & (1 << j)) { dev->num_buttons++; @@ -47,7 +48,7 @@ setup_buttons (device_t *dev) } } } - //printf("\n"); + //Sys_Printf("\n"); dev->button_map = malloc ((dev->max_button + 1) * sizeof (int)); dev->buttons = malloc (dev->num_buttons * sizeof (button_t)); for (i = 0, button = dev->buttons; i < len; i++) { @@ -212,10 +213,10 @@ check_device (const char *path) dev->event_count = 0; - printf ("%s:\n", path); - printf ("\tname: %s\n", dev->name); - printf ("\tbuttons: %d\n", dev->num_buttons); - printf ("\taxes: %d\n", dev->num_axes); + //Sys_Printf ("%s:\n", path); + //Sys_Printf ("\tname: %s\n", dev->name); + //Sys_Printf ("\tbuttons: %d\n", dev->num_buttons); + //Sys_Printf ("\taxes: %d\n", dev->num_axes); if (device_add) { device_add (dev); @@ -261,7 +262,7 @@ read_device_input (device_t *dev) return; } //const char *ev = event_codes[event.type]; - //printf ("%6d(%s) %6d %6x\n", event.type, ev ? ev : "?", event.code, event.value); + //Sys_Printf ("%6d(%s) %6d %6x\n", event.type, ev ? ev : "?", event.code, event.value); switch (event.type) { case EV_SYN: dev->event_count++; @@ -278,7 +279,7 @@ read_device_input (device_t *dev) break; case EV_REL: axis = &dev->axes[dev->rel_axis_map[event.code]]; - //printf ("EV_REL %6d %6x %6d %p\n", event.code, event.value, + //Sys_Printf ("EV_REL %6d %6x %6d %p\n", event.code, event.value, // dev->rel_axis_map[event.code], axis); axis->value = event.value; break; @@ -289,7 +290,7 @@ read_device_input (device_t *dev) case EV_FF: case EV_PWR: case EV_FF_STATUS: - //printf ("%6d %6d %6x\n", event.type, event.code, event.value); + //Sys_Printf ("%6d %6d %6x\n", event.type, event.code, event.value); break; } } @@ -403,7 +404,7 @@ device_created (const char *name) } } if (!olddev && check_device (devname) >= 0) { - //printf ("found device %s\n", devname); + //Sys_Printf ("found device %s\n", devname); } free (devname); } @@ -416,7 +417,7 @@ device_deleted (const char *name) for (dev = &devices; *dev; dev = &(*dev)->next) { if (strcmp ((*dev)->path, devname) == 0) { - //printf ("lost device %s\n", (*dev)->path); + //Sys_Printf ("lost device %s\n", (*dev)->path); close_device (*dev); device_t *d = *dev; *dev = (*dev)->next; @@ -448,7 +449,7 @@ scan_devices (void) if (check_input_device (devinput_path, dirent->d_name) < 0) { continue; } - //printf("%s\n", dirent->d_name); + //Sys_Printf("%s\n", dirent->d_name); } closedir (dir); return 0; diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 9e4b5269e..ee301c6bc 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -2040,15 +2040,6 @@ static builtin_t builtins[] = { {0} }; -static FILE *logfile; - -static __attribute__((format(PRINTF, 1, 0))) void -qwaq_print (const char *fmt, va_list args) -{ - vfprintf (logfile, fmt, args); - fflush (logfile); -} - void qwaq_init_cond (rwcond_t *cond) { @@ -2079,6 +2070,4 @@ BI_Init (progs_t *pr) PR_Resources_Register (pr, "qwaq", res, bi_qwaq_clear); PR_RegisterBuiltins (pr, builtins); Sys_RegisterShutdown (bi_shutdown, pr); - logfile = fopen ("qwaq-curses.log", "wt"); - Sys_SetStdPrintf (qwaq_print); } diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 67d491cc8..94a95764b 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -46,6 +46,7 @@ #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/input.h" #include "QF/keys.h" #include "QF/sys.h" @@ -355,7 +356,7 @@ static void process_char (qwaq_resources_t *res, char ch) // will wind up accepting P;P... but meh res->escstate = esc_key; dstring_clear (&res->escbuff); - // start the buffer with what got us hear: eases key lookup + // start the buffer with what got us here: eases key lookup dstring_append (&res->escbuff, "\033O", 2); } else { res->escstate = esc_ground; @@ -371,7 +372,7 @@ static void process_char (qwaq_resources_t *res, char ch) } else if (ch >= '0' && ch < 127) { res->escstate = esc_key; dstring_clear (&res->escbuff); - // start the buffer with what got us hear: eases key lookup + // start the buffer with what got us here: eases key lookup dstring_append (&res->escbuff, "\033[", 2); // the csi code might be short (eg, \e[H for home) so // need to check for end of string right away @@ -422,8 +423,60 @@ key_sequence_getkey (const void *_seq, void *unused) return seq->sequence; } -void qwaq_input_init (qwaq_resources_t *res) +static void +term_init (void *_res) { +} + +static void +term_shutdown (void *_res) +{ +} + +static void +term_process_events (void *_res) +{ + qwaq_resources_t *res = _res; + char buf[256]; + int len; +#ifdef HAVE_SIGACTION + sigset_t save_set; + int saw_winch; + + pthread_sigmask (SIG_BLOCK, &winch_mask, &save_set); + saw_winch = winch_arrived; + winch_arrived = 0; + pthread_sigmask (SIG_SETMASK, &save_set, 0); + if (saw_winch) { + resize_event (res); + } +#endif + while (Sys_CheckInput (1, -1)) { + len = read(0, buf, sizeof (buf)); + for (int i = 0; i < len; i++) { + process_char (res, buf[i]); + } + } +} + +static in_driver_t term_driver = { + .init = term_init, + .shutdown = term_shutdown, + .process_events = term_process_events, +}; +static int term_driver_handle; + +static void __attribute__((constructor)) +term_register_driver (void) +{ + term_driver_handle = IN_RegisterDriver (&term_driver, 0); +} + +void +qwaq_input_init (qwaq_resources_t *res) +{ + IN_DriverData (term_driver_handle, res); + if (res->key_sequences) { Hash_FlushTable (res->key_sequences); } else { @@ -449,8 +502,17 @@ void qwaq_input_init (qwaq_resources_t *res) (void) !write(1, SGR_ON, sizeof (SGR_ON) - 1); } -void qwaq_input_shutdown (qwaq_resources_t *res) +void +qwaq_process_input (qwaq_resources_t *res) { + IN_ProcessEvents (); +} + +void +qwaq_input_shutdown (qwaq_resources_t *res) +{ + IN_DriverData (term_driver_handle, 0); + // ncurses takes care of input mode for us, so need only tell xterm // what we need (void) !write(1, SGR_OFF, sizeof (SGR_OFF) - 1); @@ -460,27 +522,3 @@ void qwaq_input_shutdown (qwaq_resources_t *res) sigaction (SIGWINCH, &save_winch, 0); #endif } - -void qwaq_process_input (qwaq_resources_t *res) -{ - char buf[256]; - int len; -#ifdef HAVE_SIGACTION - sigset_t save_set; - int saw_winch; - - pthread_sigmask (SIG_BLOCK, &winch_mask, &save_set); - saw_winch = winch_arrived; - winch_arrived = 0; - pthread_sigmask (SIG_SETMASK, &save_set, 0); - if (saw_winch) { - resize_event (res); - } -#endif - while (Sys_CheckInput (1, -1)) { - len = read(0, buf, sizeof (buf)); - for (int i = 0; i < len; i++) { - process_char (res, buf[i]); - } - } -} diff --git a/ruamoko/qwaq/builtins/qwaq-curses.c b/ruamoko/qwaq/builtins/qwaq-curses.c index 354f7acb9..a5695babc 100644 --- a/ruamoko/qwaq/builtins/qwaq-curses.c +++ b/ruamoko/qwaq/builtins/qwaq-curses.c @@ -70,11 +70,23 @@ static progsinit_f target_app[] = { 0 }; +static FILE *logfile; + +static __attribute__((format(PRINTF, 1, 0))) void +qwaq_print (const char *fmt, va_list args) +{ + vfprintf (logfile, fmt, args); + fflush (logfile); +} + int qwaq_init_threads (qwaq_thread_set_t *thread_data) { int main_ind = -1; + logfile = fopen ("qwaq-curses.log", "wt"); + Sys_SetStdPrintf (qwaq_print); + IN_Init_Cvars (); IN_Init (qwaq_cbuf); From 065d0f38182bae9432c5ecc3a5eee03caaf9db3b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Aug 2021 12:05:34 +0900 Subject: [PATCH 1741/3664] [gamecode] Make PR_RESMAP macros usable in void functions --- include/QF/progs.h | 61 ++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 8922c0763..8fb23efd7 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1550,28 +1550,33 @@ void *PR_Resources_Find (progs_t *pr, const char *name); */ #define PR_RESNEW_NC(map) \ ({ \ - if (!(map)._free) { \ - int i, size; \ - (map)._size++; \ - size = (map)._size * sizeof ((map)._free); \ - (map)._map = realloc ((map)._map, size); \ - if (!(map)._map) { \ - return 0; \ - } \ - (map)._free = malloc (1024 * sizeof (*(map)._free)); \ + __auto_type ret = (map)._free; \ + do { \ if (!(map)._free) { \ - return 0; \ + int i, size; \ + (map)._size++; \ + size = (map)._size * sizeof ((map)._free); \ + (map)._map = realloc ((map)._map, size); \ + if (!(map)._map) { \ + ret = 0; \ + break; \ + } \ + (map)._free = malloc (1024 * sizeof (*(map)._free)); \ + if (!(map)._free) { \ + ret = 0; \ + break; \ + } \ + (map)._map[(map)._size - 1] = (map)._free; \ + for (i = 0; i < 1023; i++) { \ + *(typeof ((map)._free) *) &(map)._free[i] \ + = &(map)._free[i + 1]; \ + } \ + *(typeof ((map)._free) *) &(map)._free[i] = 0; \ } \ - (map)._map[(map)._size - 1] = (map)._free; \ - for (i = 0; i < 1023; i++) { \ - *(typeof ((map)._free) *) &(map)._free[i] \ - = &(map)._free[i + 1]; \ - } \ - *(typeof ((map)._free) *) &(map)._free[i] = 0; \ - } \ - __auto_type t = (map)._free; \ - (map)._free = *(typeof ((map)._free) *) t; \ - t; \ + ret = (map)._free; \ + (map)._free = *(typeof ((map)._free) *) ret; \ + } while (0); \ + ret; \ }) #define PR_RESNEW(map) \ @@ -1631,13 +1636,17 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \return A pointer to the resource, or NULL if the handle is invalid. */ -#define PR_RESGET(map,col) \ +#define PR_RESGET(map,ind) \ ({ \ - unsigned row = ~col / 1024; \ - col = ~col % 1024; \ - if (row >= (map)._size) \ - return 0; \ - &(map)._map[row][col]; \ + __auto_type ret = (map)._free; \ + unsigned row = ~ind / 1024; \ + unsigned col = ~ind % 1024; \ + if (row >= (map)._size) { \ + ret = 0; \ + } else { \ + ret = &(map)._map[row][col]; \ + } \ + ret; \ }) /** Convert a resource pointer to a handle. From 70812b3c497b3c37cca98ef657e9205f51fde2f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Aug 2021 14:40:19 +0900 Subject: [PATCH 1742/3664] [input] Hook up low level input to events This includes device add and remove events, and axis and buttons for evdev. Will need to sort out X11 input later, but next is getting qwaq responding. --- include/QF/in_event.h | 44 +++++++++++++------- include/QF/input.h | 12 +++++- include/evdev/inputlib.h | 4 ++ libs/input/evdev/inputlib.c | 9 +++++ libs/input/in_common.c | 59 ++++++++++++++++++++++++--- libs/input/in_evdev.c | 81 +++++++++++++++++++++++++++++++++++-- libs/input/in_event.c | 66 ++++++++++++------------------ 7 files changed, 211 insertions(+), 64 deletions(-) diff --git a/include/QF/in_event.h b/include/QF/in_event.h index dd1f148cf..31ec88f46 100644 --- a/include/QF/in_event.h +++ b/include/QF/in_event.h @@ -35,7 +35,7 @@ #include "QF/joystick.h" // needed for JOY_MAX_AXES typedef struct { - float x, y; + int x, y; unsigned int buttons; } IE_mouse_event_t; @@ -45,33 +45,49 @@ typedef struct { } IE_key_event_t; typedef struct { - float axis[JOY_MAX_AXES]; - unsigned int buttons; -} IE_joystick_event_t; + int devid; + int axis; + int value; +} IE_axis_event_t; + +typedef struct { + int devid; + int button; + int state; +} IE_button_event_t; + +typedef struct { + int devid; +} IE_device_event_t; typedef enum { ie_none, ie_gain_focus, ie_lose_focus, + ie_add_device, + ie_remove_device, ie_mouse, ie_key, - ie_joystick, + ie_axis, + ie_button, } IE_event_type; typedef struct { - IE_event_type type; + IE_event_type type; + uint64_t when; union { - IE_mouse_event_t mouse; - IE_key_event_t key; - IE_joystick_event_t joystick; - } e; + IE_mouse_event_t mouse; + IE_key_event_t key; + IE_axis_event_t axis; + IE_button_event_t button; + IE_device_event_t device; + }; } IE_event_t; -void IE_Init (void); -void IE_Init_Cvars (void); -void IE_Shutdown (void); +typedef int ie_handler_t (const IE_event_t *, void *data); + int IE_Send_Event (const IE_event_t *event); -int IE_Add_Handler (int (*event_handler)(const IE_event_t*)); +int IE_Add_Handler (ie_handler_t *event_handler, void *data); void IE_Remove_Handler (int handle); void IE_Set_Focus (int handle); diff --git a/include/QF/input.h b/include/QF/input.h index e09ac6c3c..e91014b4e 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -35,7 +35,7 @@ typedef struct { vec3_t position; } viewdelta_t; -typedef struct { +typedef struct in_driver_s { void (*init) (void *data); void (*shutdown) (void *data); void (*process_events) (void *data); @@ -43,6 +43,13 @@ typedef struct { void (*grab_input) (void *data, int grab); } in_driver_t; +typedef struct in_device_s { + int driverid; + void *device; + const char *name; + const char *path; +} in_device_t; + extern viewdelta_t viewdelta; #define freelook (in_mlook.state & 1 || in_freelook->int_val) @@ -54,6 +61,9 @@ void IN_DriverData (int handlle, void *data); void IN_Init (struct cbuf_s *cbuf); void IN_Init_Cvars (void); +int IN_AddDevice (in_device_t *device); +void IN_RemoveDevice (int devid); + void IN_ProcessEvents (void); void IN_UpdateGrab (struct cvar_s *); diff --git a/include/evdev/inputlib.h b/include/evdev/inputlib.h index de3e61caf..9d8c931e5 100644 --- a/include/evdev/inputlib.h +++ b/include/evdev/inputlib.h @@ -37,6 +37,10 @@ typedef struct device_s { int num_axes; axis_t *axes; int event_count; + + void *data; + void (*axis_event) (axis_t *axis, void *data); + void (*button_event) (button_t *button, void *data); } device_t; int inputlib_check_input (void); diff --git a/libs/input/evdev/inputlib.c b/libs/input/evdev/inputlib.c index 065c57dc0..9fd854be4 100644 --- a/libs/input/evdev/inputlib.c +++ b/libs/input/evdev/inputlib.c @@ -270,10 +270,16 @@ read_device_input (device_t *dev) case EV_KEY: button = &dev->buttons[dev->button_map[event.code]]; button->state = event.value; + if (dev->button_event) { + dev->button_event (button, dev->data); + } break; case EV_ABS: axis = &dev->axes[dev->abs_axis_map[event.code]]; axis->value = event.value; + if (dev->axis_event) { + dev->axis_event (axis, dev->data); + } break; case EV_MSC: break; @@ -282,6 +288,9 @@ read_device_input (device_t *dev) //Sys_Printf ("EV_REL %6d %6x %6d %p\n", event.code, event.value, // dev->rel_axis_map[event.code], axis); axis->value = event.value; + if (dev->axis_event) { + dev->axis_event (axis, dev->data); + } break; case EV_SW: case EV_LED: diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 609bb0344..aa49f1331 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -63,7 +63,8 @@ typedef struct { void *data; } in_regdriver_t; -static struct DARRAY_TYPE (in_regdriver_t) in_drivers = { .grow = 8, }; +static struct DARRAY_TYPE (in_regdriver_t) in_drivers = { .grow = 8 }; +static struct DARRAY_TYPE (in_device_t *) in_devices = { .grow = 8 }; VISIBLE viewdelta_t viewdelta; @@ -98,6 +99,58 @@ IN_DriverData (int handle, void *data) in_drivers.a[handle].data = data; } +static int +in_add_device (in_device_t *device) +{ + size_t devid; + + for (devid = 0; devid < in_devices.size; devid++) { + if (!in_devices.a[devid]) { + in_devices.a[devid] = device; + return devid; + } + } + DARRAY_APPEND (&in_devices, device); + return devid; +} + +int +IN_AddDevice (in_device_t *device) +{ + int devid = in_add_device (device); + + IE_event_t event = { + .type = ie_add_device, + .when = Sys_LongTime (), + .device = { + .devid = devid, + }, + }; + IE_Send_Event (&event); + return devid; +} + +void +IN_RemoveDevice (int devid) +{ + size_t d = devid; + + if (d >= in_devices.size) { + Sys_Error ("IN_RemoveDevice: invalid devid: %d", devid); + } + + IE_event_t event = { + .type = ie_remove_device, + .when = Sys_LongTime (), + .device = { + .devid = devid, + }, + }; + IE_Send_Event (&event); + + in_devices.a[devid] = 0; +} + void IN_UpdateGrab (cvar_t *var) // called from context_*.c { @@ -168,8 +221,6 @@ IN_shutdown (void *data) rd->driver.shutdown (rd->data); } } - - IE_Shutdown (); } void @@ -177,7 +228,6 @@ IN_Init (cbuf_t *cbuf) { Sys_RegisterShutdown (IN_shutdown, 0); - IE_Init (); for (size_t i = 0; i < in_drivers.size; i++) { in_regdriver_t *rd = &in_drivers.a[i]; rd->driver.init (rd->data); @@ -191,7 +241,6 @@ IN_Init (cbuf_t *cbuf) void IN_Init_Cvars (void) { - IE_Init_Cvars (); Key_Init_Cvars (); //JOY_Init_Cvars (); in_grab = Cvar_Get ("in_grab", "0", CVAR_ARCHIVE, IN_UpdateGrab, diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 125d12e64..cfd9aa221 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -37,12 +37,22 @@ #endif #include "QF/cvar.h" +#include "QF/in_event.h" #include "QF/input.h" +#include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" #include "compat.h" #include "evdev/inputlib.h" +typedef struct { + in_device_t in_dev; + int devid; +} devmap_t; + +static int evdev_driver_handle = -1; +static PR_RESMAP (devmap_t) devmap; + static void in_evdev_keydest_callback (keydest_t key_dest, void *data) { @@ -61,19 +71,84 @@ in_evdev_shutdown (void *data) inputlib_close (); } +static void +in_evdev_axis_event (axis_t *axis, void *_dm) +{ + devmap_t *dm = _dm; + //Sys_Printf ("in_evdev_axis_event: %d %d\n", axis->num, axis->value); + + IE_event_t event = { + .type = ie_axis, + .when = Sys_LongTime (), + .axis = { + .devid = dm->devid, + .axis = axis->num, + .value = axis->value, + }, + }; + IE_Send_Event (&event); +} + +static void +in_evdev_button_event (button_t *button, void *_dm) +{ + devmap_t *dm = _dm; + //Sys_Printf ("in_evdev_button_event: %d %d\n", button->num, button->state); + + IE_event_t event = { + .type = ie_button, + .when = Sys_LongTime (), + .button = { + .devid = dm->devid, + .button = button->num, + .state = button->state, + }, + }; + IE_Send_Event (&event); +} + static void device_add (device_t *dev) { + devmap_t *dm = PR_RESNEW (devmap); + dm->in_dev.driverid = evdev_driver_handle; + dm->in_dev.device = dev; + dm->in_dev.name = dev->name; + dm->in_dev.path = dev->phys; + dm->devid = IN_AddDevice (&dm->in_dev); + + dev->data = dm; + dev->axis_event = in_evdev_axis_event; + dev->button_event = in_evdev_button_event; + +#if 0 Sys_Printf ("in_evdev: add %s\n", dev->path); Sys_Printf (" %s\n", dev->name); Sys_Printf (" %s\n", dev->phys); - Sys_Printf (" %s\n", dev->uniq); + for (int i = 0; i < dev->num_axes; i++) { + axis_t *axis = dev->axes + i; + Sys_Printf ("axis: %d %d\n", axis->num, axis->value); + } + for (int i = 0; i < dev->num_buttons; i++) { + button_t *button = dev->buttons + i; + Sys_Printf ("button: %d %d\n", button->num, button->state); + } +#endif } static void device_remove (device_t *dev) { - Sys_Printf ("in_evdev: remove %s\n", dev->path); + //Sys_Printf ("in_evdev: remove %s\n", dev->path); + for (unsigned i = 0; i < devmap._size; i++) { + devmap_t *dm = PR_RESGET (devmap, ~i); + if (dm->in_dev.device == dev) { + IN_RemoveDevice (dm->devid); + memset (dm, 0, sizeof (*dm)); + PR_RESFREE (devmap, dm); + break; + } + } } static void @@ -99,7 +174,7 @@ static in_driver_t in_evdev_driver = { static void __attribute__((constructor)) in_evdev_register_driver (void) { - IN_RegisterDriver (&in_evdev_driver, 0); + evdev_driver_handle = IN_RegisterDriver (&in_evdev_driver, 0); } int in_evdev_force_link; diff --git a/libs/input/in_event.c b/libs/input/in_event.c index 28ee17c98..6f74ae4bc 100644 --- a/libs/input/in_event.c +++ b/libs/input/in_event.c @@ -39,72 +39,56 @@ #endif #include +#include "QF/darray.h" #include "QF/in_event.h" -static int (**event_handler_list)(const IE_event_t*); -static int eh_list_size; -static int focus; +typedef struct { + ie_handler_t *handler; + void *data; +} ie_reghandler_t; -void -IE_Init (void) -{ - eh_list_size = 8; // start with 8 slots. will grow dynamicly if needed - event_handler_list = calloc (eh_list_size, sizeof (event_handler_list[0])); -} - -void -IE_Init_Cvars (void) -{ -} - -void -IE_Shutdown (void) -{ -} +static struct DARRAY_TYPE (ie_reghandler_t) ie_handlers = { .grow = 8, }; +static unsigned focus; int IE_Send_Event (const IE_event_t *event) { - if (event_handler_list[focus]) - return event_handler_list[focus](event); + if (focus < ie_handlers.size && ie_handlers.a[focus].handler) { + ie_reghandler_t *reg = &ie_handlers.a[focus]; + return reg->handler (event, reg->data); + } return 0; } int -IE_Add_Handler (int (*event_handler)(const IE_event_t*)) +IE_Add_Handler (ie_handler_t *event_handler, void *data) { - int i; + size_t handle; + ie_reghandler_t reg = { event_handler, data }; - while (1) { - int (**t)(const IE_event_t*); - for (i = 0; i < eh_list_size; i++) { - if (!event_handler_list[i]) { - event_handler_list[i] = event_handler; - return i; - } + for (handle = 0; handle < ie_handlers.size; handle++) { + if (!ie_handlers.a[handle].handler) { + ie_handlers.a[handle] = reg; + return handle; } - if (!(t = realloc (event_handler_list, eh_list_size + 8))) - return -1; - event_handler_list = t; - memset (event_handler_list + eh_list_size, 0, - 8 * sizeof (event_handler_list[0])); - eh_list_size += 8; } + DARRAY_APPEND (&ie_handlers, reg); + return handle; } void IE_Remove_Handler (int handle) { - if (handle >= 0 && handle < eh_list_size) - event_handler_list[handle] = 0; + if ((size_t) (ssize_t) handle < ie_handlers.size) { + ie_handlers.a[handle].handler = 0; + } } void IE_Set_Focus (int handle) { - if (handle >= 0 && handle < eh_list_size - && event_handler_list[handle] - && focus != handle) { + unsigned h = handle; + if (h < ie_handlers.size && ie_handlers.a[handle].handler && focus != h) { IE_event_t event; event.type = ie_lose_focus; IE_Send_Event (&event); From cc730c90b41c2a6dbac0a09b6397bd113d615fa2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Sep 2021 15:21:11 +0900 Subject: [PATCH 1743/3664] [input] Rework device registration And provide functions for collecting axis and button information from a device id. --- include/QF/input.h | 31 ++++++++++- include/QF/ringbuffer.h | 2 +- libs/input/in_common.c | 120 ++++++++++++++++++++++++++++++++++++---- libs/input/in_evdev.c | 61 +++++++++++++++++--- 4 files changed, 192 insertions(+), 22 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index e91014b4e..238e342e1 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -30,6 +30,21 @@ #include "QF/keys.h" +typedef struct in_axisinfo_s { + int deviceid; + int axis; + int value; + int min; + int max; +} in_axisinfo_t; + +typedef struct in_buttoninfo_s { + int deviceid; + int button; + int state; +} in_buttoninfo_t; + +#ifndef __QFCC__ typedef struct { vec3_t angles; vec3_t position; @@ -41,13 +56,18 @@ typedef struct in_driver_s { void (*process_events) (void *data); void (*clear_states) (void *data); void (*grab_input) (void *data, int grab); + + void (*axis_info) (void *data, void *device, in_axisinfo_t *axes, + int *numaxes); + void (*button_info) (void *data, void *device, in_buttoninfo_t *buttons, + int *numbuttons); } in_driver_t; typedef struct in_device_s { int driverid; void *device; const char *name; - const char *path; + const char *id; } in_device_t; extern viewdelta_t viewdelta; @@ -61,9 +81,15 @@ void IN_DriverData (int handlle, void *data); void IN_Init (struct cbuf_s *cbuf); void IN_Init_Cvars (void); -int IN_AddDevice (in_device_t *device); +int IN_AddDevice (int driver, void *device, const char *name, const char *id); void IN_RemoveDevice (int devid); +void IN_SendConnectedDevices (void); +const char *IN_GetDeviceName (int devid); +const char *IN_GetDeviceId (int devid); +int IN_AxisInfo (int devid, in_axisinfo_t *axes, int *numaxes); +int IN_ButtonInfo (int devid, in_buttoninfo_t *button, int *numbuttons); + void IN_ProcessEvents (void); void IN_UpdateGrab (struct cvar_s *); @@ -86,5 +112,6 @@ extern float in_mouse_x, in_mouse_y; extern kbutton_t in_strafe, in_klook, in_speed, in_mlook; +#endif #endif//__QF_input_h diff --git a/include/QF/ringbuffer.h b/include/QF/ringbuffer.h index ac339ea70..c0f99d4ba 100644 --- a/include/QF/ringbuffer.h +++ b/include/QF/ringbuffer.h @@ -31,7 +31,7 @@ /** Type declaration for a type-safe ring buffer. * * While not in itself thread-safe, the buffer is designed (and tested) to be - * used in a threaded environment using sutable locking mechanisms. + * used in a threaded environment using suitable locking mechanisms. * * \param type The type of data element stored in the ring buffer. * \param size The number of objects in the ring buffer. Note that the diff --git a/libs/input/in_common.c b/libs/input/in_common.c index aa49f1331..fc7f85755 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -64,7 +64,7 @@ typedef struct { } in_regdriver_t; static struct DARRAY_TYPE (in_regdriver_t) in_drivers = { .grow = 8 }; -static struct DARRAY_TYPE (in_device_t *) in_devices = { .grow = 8 }; +static struct DARRAY_TYPE (in_device_t) in_devices = { .grow = 8 }; VISIBLE viewdelta_t viewdelta; @@ -100,24 +100,35 @@ IN_DriverData (int handle, void *data) } static int -in_add_device (in_device_t *device) +in_add_device (int driver, in_device_t *device, const char *name, + const char *id) { size_t devid; + in_device_t indev = { + .driverid = driver, + .device = device, + .name = name, + .id = id, + }; for (devid = 0; devid < in_devices.size; devid++) { - if (!in_devices.a[devid]) { - in_devices.a[devid] = device; + if (in_devices.a[devid].driverid == -1) { + in_devices.a[devid] = indev; return devid; } } - DARRAY_APPEND (&in_devices, device); + DARRAY_APPEND (&in_devices, indev); return devid; } int -IN_AddDevice (in_device_t *device) +IN_AddDevice (int driver, void *device, const char *name, const char *id) { - int devid = in_add_device (device); + if ((size_t) driver >= in_drivers.size) { + Sys_Error ("IN_AddDevice: invalid driver: %d", driver); + } + + int devid = in_add_device (driver, device, name, id); IE_event_t event = { .type = ie_add_device, @@ -133,9 +144,7 @@ IN_AddDevice (in_device_t *device) void IN_RemoveDevice (int devid) { - size_t d = devid; - - if (d >= in_devices.size) { + if ((size_t) devid >= in_devices.size) { Sys_Error ("IN_RemoveDevice: invalid devid: %d", devid); } @@ -148,7 +157,96 @@ IN_RemoveDevice (int devid) }; IE_Send_Event (&event); - in_devices.a[devid] = 0; + in_devices.a[devid].device = 0; +} + +void +IN_SendConnectedDevices (void) +{ + for (size_t devid = 0; devid < in_devices.size; devid++) { + if (in_devices.a[devid].driverid >= 0 + && in_devices.a[devid].device) { + IE_event_t event = { + .type = ie_add_device, + .when = Sys_LongTime (),//FIXME actual time? + .device = { + .devid = devid, + }, + }; + IE_Send_Event (&event); + } + } +} + +const char * +IN_GetDeviceName (int devid) +{ + if ((size_t) devid >= in_devices.size) { + return 0; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return 0; + } + return in_devices.a[devid].name; +} + +const char * +IN_GetDeviceId (int devid) +{ + if ((size_t) devid >= in_devices.size) { + return 0; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return 0; + } + return in_devices.a[devid].id; +} + +int +IN_AxisInfo (int devid, in_axisinfo_t *axes, int *numaxes) +{ + if ((size_t) devid >= in_devices.size) { + return -1; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return -1; + } + int driver = in_devices.a[devid].driverid; + in_regdriver_t *rd = &in_drivers.a[driver]; + if (!rd->driver.axis_info) { + return -1; + } + rd->driver.axis_info (rd->data, in_devices.a[devid].device, axes, numaxes); + if (axes) { + for (int i = 0; i < *numaxes; i++) { + axes[i].deviceid = devid; + } + } + return 0; +} + +int +IN_ButtonInfo (int devid, in_buttoninfo_t *buttons, int *numbuttons) +{ + if ((size_t) devid >= in_devices.size) { + return -1; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return -1; + } + int driver = in_devices.a[devid].driverid; + in_regdriver_t *rd = &in_drivers.a[driver]; + if (!rd->driver.button_info) { + return -1; + } + rd->driver.button_info (rd->data, in_devices.a[devid].device, + buttons, numbuttons); + if (buttons) { + for (int i = 0; i < *numbuttons; i++) { + buttons[i].deviceid = devid; + } + } + return 0; } void diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index cfd9aa221..dad2c0c99 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -46,7 +46,7 @@ #include "evdev/inputlib.h" typedef struct { - in_device_t in_dev; + device_t *device; int devid; } devmap_t; @@ -110,12 +110,17 @@ in_evdev_button_event (button_t *button, void *_dm) static void device_add (device_t *dev) { + const char *name = dev->name; + // prefer device unique string if available, otherwise fall back to + // the physical path + const char *id = dev->uniq; + if (!id || !*id) { + id = dev->phys; + } + devmap_t *dm = PR_RESNEW (devmap); - dm->in_dev.driverid = evdev_driver_handle; - dm->in_dev.device = dev; - dm->in_dev.name = dev->name; - dm->in_dev.path = dev->phys; - dm->devid = IN_AddDevice (&dm->in_dev); + dm->device = dev; + dm->devid = IN_AddDevice (evdev_driver_handle, dev, name, id); dev->data = dm; dev->axis_event = in_evdev_axis_event; @@ -142,9 +147,8 @@ device_remove (device_t *dev) //Sys_Printf ("in_evdev: remove %s\n", dev->path); for (unsigned i = 0; i < devmap._size; i++) { devmap_t *dm = PR_RESGET (devmap, ~i); - if (dm->in_dev.device == dev) { + if (dm->device == dev) { IN_RemoveDevice (dm->devid); - memset (dm, 0, sizeof (*dm)); PR_RESFREE (devmap, dm); break; } @@ -164,11 +168,52 @@ in_evdev_clear_states (void *data) { } +static void +in_evdev_axis_info (void *data, void *device, in_axisinfo_t *axes, + int *numaxes) +{ + device_t *dev = device; + if (!axes) { + *numaxes = dev->num_axes; + return; + } + if (*numaxes > dev->num_axes) { + *numaxes = dev->num_axes; + } + for (int i = 0; i < *numaxes; i++) { + axes[i].axis = dev->axes[i].num; + axes[i].value = dev->axes[i].value; + axes[i].min = dev->axes[i].min; + axes[i].max = dev->axes[i].max; + } +} + +static void +in_evdev_button_info (void *data, void *device, in_buttoninfo_t *buttons, + int *numbuttons) +{ + device_t *dev = device; + if (!buttons) { + *numbuttons = dev->num_buttons; + return; + } + if (*numbuttons > dev->num_buttons) { + *numbuttons = dev->num_buttons; + } + for (int i = 0; i < *numbuttons; i++) { + buttons[i].button = dev->buttons[i].num; + buttons[i].state = dev->buttons[i].state; + } +} + static in_driver_t in_evdev_driver = { .init = in_evdev_init, .shutdown = in_evdev_shutdown, .process_events = in_evdev_process_events, .clear_states = in_evdev_clear_states, + + .axis_info = in_evdev_axis_info, + .button_info = in_evdev_button_info, }; static void __attribute__((constructor)) From 106ab86c3ea47088a3b0411fa8eb173c6acf422a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Sep 2021 15:31:50 +0900 Subject: [PATCH 1744/3664] [qwaq] Move the ui code into a library --- ruamoko/qwaq/Makemodule.am | 42 +++++++++++++++++++++++--------------- ruamoko/qwaq/ui/group.r | 2 ++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 672aeca18..01d2fedd1 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -4,6 +4,29 @@ QWAQ_INCS=@QWAQ_INCS@ noinst_PROGRAMS += @QWAQ_TARGETS@ ruamoko/qwaq/qwaq-app.dat$(EXEEXT) ruamoko/qwaq/gcd.dat$(EXEEXT) ruamoko/qwaq/z-transform.dat$(EXEEXT) +libui=ruamoko/qwaq/libui.a +noinst_LIBRARIES += $(libui) + +ruamoko_qwaq_libui_a_SOURCES= \ + ruamoko/qwaq/ui/button.r \ + ruamoko/qwaq/ui/draw.r \ + ruamoko/qwaq/ui/garray.r \ + ruamoko/qwaq/ui/group.r \ + ruamoko/qwaq/ui/listener.r \ + ruamoko/qwaq/ui/proxyview.r \ + ruamoko/qwaq/ui/rect.r \ + ruamoko/qwaq/ui/scrollbar.r \ + ruamoko/qwaq/ui/tableview.r \ + ruamoko/qwaq/ui/textcontext.r \ + ruamoko/qwaq/ui/titlebar.r \ + ruamoko/qwaq/ui/view.r \ + ruamoko/qwaq/ui/window.r +ruamoko_qwaq_libui_a_dep=$(call qcautodep,$(ruamoko_qwaq_libui_a_SOURCES)) +ruamoko_qwaq_libui_a_AR=$(PAK) -cf +EXTRA_ruamoko_qwaq_libui_a_DEPENDENCIES=pak +include $(ruamoko_qwaq_libui_a_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_qwaq_libui_a_dep) + qwaq_app_dat_src= \ ruamoko/qwaq/qwaq-app.r \ ruamoko/qwaq/debugger/views/basicview.r \ @@ -27,20 +50,7 @@ qwaq_app_dat_src= \ ruamoko/qwaq/debugger/typeencodings.r \ ruamoko/qwaq/editor/editbuffer.r \ ruamoko/qwaq/editor/editor.r \ - ruamoko/qwaq/editor/status.r \ - ruamoko/qwaq/ui/button.r \ - ruamoko/qwaq/ui/draw.r \ - ruamoko/qwaq/ui/garray.r \ - ruamoko/qwaq/ui/group.r \ - ruamoko/qwaq/ui/listener.r \ - ruamoko/qwaq/ui/proxyview.r \ - ruamoko/qwaq/ui/rect.r \ - ruamoko/qwaq/ui/scrollbar.r \ - ruamoko/qwaq/ui/tableview.r \ - ruamoko/qwaq/ui/textcontext.r \ - ruamoko/qwaq/ui/titlebar.r \ - ruamoko/qwaq/ui/view.r \ - ruamoko/qwaq/ui/window.r + ruamoko/qwaq/editor/status.r qwaq_curses_libs= \ libs/ui/libQFui.la \ @@ -101,8 +111,8 @@ ruamoko_qwaq_qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) ruamoko_qwaq_qwaq_app_dat_SOURCES=$(qwaq_app_dat_src) ruamoko_qwaq_qwaq_app_obj=$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.r=.o) ruamoko_qwaq_qwaq_app_dep=$(call qcautodep,$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.o=.Qo)) -ruamoko/qwaq/qwaq-app.dat$(EXEEXT): $(ruamoko_qwaq_qwaq_app_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_qwaq_app_obj) -lcsqc -lr +ruamoko/qwaq/qwaq-app.dat$(EXEEXT): $(ruamoko_qwaq_qwaq_app_obj) $(QFCC_DEP) $(libui) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_qwaq_app_obj) $(libui) -lcsqc -lr include $(ruamoko_qwaq_qwaq_app_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_qwaq_app_dep) diff --git a/ruamoko/qwaq/ui/group.r b/ruamoko/qwaq/ui/group.r index 05a3f344f..2e45d3e64 100644 --- a/ruamoko/qwaq/ui/group.r +++ b/ruamoko/qwaq/ui/group.r @@ -5,6 +5,8 @@ #include "ruamoko/qwaq/ui/group.h" #include "ruamoko/qwaq/ui/view.h" +@reference Array (Group); + @implementation Group +(Group *)withContext:(id)context owner:(View *)owner From e942fe652857acf6ca4073315197624f55a3ca0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Sep 2021 12:58:10 +0900 Subject: [PATCH 1745/3664] [qwaq] Add input test app The queues in the curses resources struct have been cleaned up and the threading support code (including for the queues (pipes, really)) has been moved to its own file. The input test app currently just prints the devices and the events as they come in, but demonstrates the new input system working in a separate thread (though it is currently in with the curses thread). --- ruamoko/qwaq/Makemodule.am | 17 +- ruamoko/qwaq/builtins/curses.c | 573 +++++++++++++++++------------- ruamoko/qwaq/builtins/input.c | 71 +++- ruamoko/qwaq/builtins/threading.c | 140 ++++++++ ruamoko/qwaq/input-app.h | 35 ++ ruamoko/qwaq/input-app.r | 183 ++++++++++ ruamoko/qwaq/qwaq-input.h | 52 +++ ruamoko/qwaq/qwaq-input.r | 4 + ruamoko/qwaq/threading.h | 39 ++ ruamoko/qwaq/ui/curses.h | 31 +- ruamoko/qwaq/ui/event.h | 6 + 11 files changed, 863 insertions(+), 288 deletions(-) create mode 100644 ruamoko/qwaq/builtins/threading.c create mode 100644 ruamoko/qwaq/input-app.h create mode 100644 ruamoko/qwaq/input-app.r create mode 100644 ruamoko/qwaq/qwaq-input.h create mode 100644 ruamoko/qwaq/qwaq-input.r create mode 100644 ruamoko/qwaq/threading.h diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 01d2fedd1..81bf44d68 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -2,7 +2,7 @@ QWAQ_LIBS=@QWAQ_LIBS@ QWAQ_DEPS=@QWAQ_DEPS@ QWAQ_INCS=@QWAQ_INCS@ -noinst_PROGRAMS += @QWAQ_TARGETS@ ruamoko/qwaq/qwaq-app.dat$(EXEEXT) ruamoko/qwaq/gcd.dat$(EXEEXT) ruamoko/qwaq/z-transform.dat$(EXEEXT) +noinst_PROGRAMS += @QWAQ_TARGETS@ ruamoko/qwaq/qwaq-app.dat$(EXEEXT) ruamoko/qwaq/gcd.dat$(EXEEXT) ruamoko/qwaq/input-app.dat$(EXEEXT) ruamoko/qwaq/z-transform.dat$(EXEEXT) libui=ruamoko/qwaq/libui.a noinst_LIBRARIES += $(libui) @@ -52,6 +52,10 @@ qwaq_app_dat_src= \ ruamoko/qwaq/editor/editor.r \ ruamoko/qwaq/editor/status.r +qwaq_input_app_dat_src= \ + ruamoko/qwaq/qwaq-input.r \ + ruamoko/qwaq/input-app.r + qwaq_curses_libs= \ libs/ui/libQFui.la \ libs/input/libQFinput.la @@ -62,7 +66,8 @@ ruamoko_qwaq_qwaq_curses_SOURCES= \ ruamoko/qwaq/builtins/debug.c \ ruamoko/qwaq/builtins/editbuffer.c \ ruamoko/qwaq/builtins/input.c \ - ruamoko/qwaq/builtins/qwaq-curses.c + ruamoko/qwaq/builtins/qwaq-curses.c \ + ruamoko/qwaq/builtins/threading.c ruamoko_qwaq_qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ $(PANEL_LIBS) $(NCURSES_LIBS) $(PTHREAD_LDFLAGS) $(DL_LIBS) @@ -116,6 +121,14 @@ ruamoko/qwaq/qwaq-app.dat$(EXEEXT): $(ruamoko_qwaq_qwaq_app_obj) $(QFCC_DEP) $(l include $(ruamoko_qwaq_qwaq_app_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_qwaq_app_dep) +ruamoko_qwaq_input_app_dat_SOURCES=$(qwaq_input_app_dat_src) +ruamoko_qwaq_input_app_obj=$(ruamoko_qwaq_input_app_dat_SOURCES:.r=.o) +ruamoko_qwaq_input_app_dep=$(call qcautodep,$(ruamoko_qwaq_input_app_dat_SOURCES:.o=.Qo)) +ruamoko/qwaq/input-app.dat$(EXEEXT): $(ruamoko_qwaq_input_app_obj) $(QFCC_DEP) $(libui) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_input_app_obj) $(libui) -lcsqc -lr +include $(ruamoko_qwaq_input_app_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_qwaq_input_app_dep) + ruamoko_qwaq_gcd_dat_SOURCES=ruamoko/qwaq/gcd.r ruamoko_qwaq_gcd_obj=$(ruamoko_qwaq_gcd_dat_SOURCES:.r=.o) ruamoko_qwaq_gcd_dep=$(call qcautodep,$(ruamoko_qwaq_gcd_dat_SOURCES:.o=.Qo)) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index ee301c6bc..3be531c33 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -42,11 +42,13 @@ #include #include "QF/dstring.h" +#include "QF/input.h" #include "QF/progs.h" #include "QF/ringbuffer.h" #include "QF/sys.h" #include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/qwaq-input.h" #include "ruamoko/qwaq/ui/curses.h" #include "ruamoko/qwaq/ui/rect.h" #include "ruamoko/qwaq/ui/textcontext.h" @@ -88,6 +90,9 @@ typedef enum qwaq_commands_e { qwaq_cmd_resizeterm, qwaq_cmd_mvwhline, qwaq_cmd_mvwvline, + + qwaq_cmd_send_connected_devices, + qwaq_cmd_get_device_info, } qwaq_commands; static const char *qwaq_command_names[]= { @@ -124,6 +129,9 @@ static const char *qwaq_command_names[]= { "resizeterm", "mvwhline", "mvwvline", + + "send_connected_devices", + "get_device_info", }; static window_t * @@ -214,92 +222,39 @@ get_panel (qwaq_resources_t *res, const char *name, int handle) } static int -acquire_string (qwaq_resources_t *res) +qwaq_cmd_peek (qwaq_resources_t *res, int ahead) { - int string_id = -1; - - pthread_mutex_lock (&res->string_id_cond.mut); - while (RB_DATA_AVAILABLE (res->string_ids) < 1) { - pthread_cond_wait (&res->string_id_cond.rcond, - &res->string_id_cond.mut); - } - RB_READ_DATA (res->string_ids, &string_id, 1); - pthread_cond_broadcast (&res->string_id_cond.wcond); - pthread_mutex_unlock (&res->string_id_cond.mut); - return string_id; + return *RB_PEEK_DATA (res->commands.pipe, ahead); } -static void -release_string (qwaq_resources_t *res, int string_id) +static dstring_t * +qwaq_cmd_string (qwaq_resources_t *res, int string_id) { - pthread_mutex_lock (&res->string_id_cond.mut); - while (RB_SPACE_AVAILABLE (res->string_ids) < 1) { - pthread_cond_wait (&res->string_id_cond.wcond, - &res->string_id_cond.mut); - } - RB_WRITE_DATA (res->string_ids, &string_id, 1); - pthread_cond_broadcast (&res->string_id_cond.rcond); - pthread_mutex_unlock (&res->string_id_cond.mut); + return res->commands.strings + string_id; } -static void -qwaq_submit_command (qwaq_resources_t *res, const int *cmd) +static dstring_t * +qwaq_res_string (qwaq_resources_t *res, int string_id) { - unsigned len = cmd[1]; - - pthread_mutex_lock (&res->command_cond.mut); - while (RB_SPACE_AVAILABLE (res->command_queue) < len) { - pthread_cond_wait (&res->command_cond.wcond, - &res->command_cond.mut); - } - RB_WRITE_DATA (res->command_queue, cmd, len); - pthread_cond_broadcast (&res->command_cond.rcond); - pthread_mutex_unlock (&res->command_cond.mut); -} - -static void -qwaq_submit_result (qwaq_resources_t *res, const int *result, unsigned len) -{ - pthread_mutex_lock (&res->results_cond.mut); - while (RB_SPACE_AVAILABLE (res->results) < len) { - pthread_cond_wait (&res->results_cond.wcond, - &res->results_cond.mut); - } - RB_WRITE_DATA (res->results, result, len); - pthread_cond_broadcast (&res->results_cond.rcond); - pthread_mutex_unlock (&res->results_cond.mut); -} - -static void -qwaq_wait_result (qwaq_resources_t *res, int *result, int cmd, unsigned len) -{ - pthread_mutex_lock (&res->results_cond.mut); - while (RB_DATA_AVAILABLE (res->results) < len - || *RB_PEEK_DATA (res->results, 0) != cmd) { - pthread_cond_wait (&res->results_cond.rcond, - &res->results_cond.mut); - } - RB_READ_DATA (res->results, result, len); - pthread_cond_broadcast (&res->results_cond.wcond); - pthread_mutex_unlock (&res->results_cond.mut); + return res->results.strings + string_id; } static void cmd_syncprint (qwaq_resources_t *res) { - int string_id = *RB_PEEK_DATA (res->command_queue, 2); + int string_id = qwaq_cmd_peek (res, 2); - Sys_Printf ("%s\n", res->strings[string_id].str); - release_string (res, string_id); + Sys_Printf ("%s\n", qwaq_cmd_string (res, string_id)->str); + qwaq_pipe_release_string (&res->commands, string_id); } static void cmd_newwin (qwaq_resources_t *res) { - int xpos = *RB_PEEK_DATA (res->command_queue, 2); - int ypos = *RB_PEEK_DATA (res->command_queue, 3); - int xlen = *RB_PEEK_DATA (res->command_queue, 4); - int ylen = *RB_PEEK_DATA (res->command_queue, 5); + int xpos = qwaq_cmd_peek (res, 2); + int ypos = qwaq_cmd_peek (res, 3); + int xlen = qwaq_cmd_peek (res, 4); + int ylen = qwaq_cmd_peek (res, 5); window_t *window = window_new (res); window->win = newwin (ylen, xlen, ypos, xpos); @@ -307,13 +262,13 @@ cmd_newwin (qwaq_resources_t *res) int window_id = window_index (res, window); int cmd_result[] = { qwaq_cmd_newwin, window_id }; - qwaq_submit_result (res, cmd_result, CMD_SIZE (cmd_result)); + qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result)); } static void cmd_delwin (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int window_id = qwaq_cmd_peek (res, 2); window_t *window = get_window (res, __FUNCTION__, window_id); delwin (window->win); @@ -323,7 +278,7 @@ cmd_delwin (qwaq_resources_t *res) static void cmd_getwrect (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int window_id = qwaq_cmd_peek (res, 2); int xpos, ypos; int xlen, ylen; @@ -335,13 +290,13 @@ cmd_getwrect (qwaq_resources_t *res) getmaxyx (window->win, ylen, xlen); int cmd_result[] = { qwaq_cmd_getwrect, xpos, ypos, xlen, ylen }; - qwaq_submit_result (res, cmd_result, CMD_SIZE (cmd_result)); + qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result)); } static void cmd_new_panel (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int window_id = qwaq_cmd_peek (res, 2); window_t *window = get_window (res, __FUNCTION__, window_id); panel_t *panel = panel_new (res); @@ -350,13 +305,13 @@ cmd_new_panel (qwaq_resources_t *res) int panel_id = panel_index (res, panel); int cmd_result[] = { qwaq_cmd_new_panel, panel_id }; - qwaq_submit_result (res, cmd_result, CMD_SIZE (cmd_result)); + qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result)); } static void cmd_del_panel (qwaq_resources_t *res) { - int panel_id = *RB_PEEK_DATA (res->command_queue, 2); + int panel_id = qwaq_cmd_peek (res, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); del_panel (panel->panel); @@ -366,7 +321,7 @@ cmd_del_panel (qwaq_resources_t *res) static void cmd_hide_panel (qwaq_resources_t *res) { - int panel_id = *RB_PEEK_DATA (res->command_queue, 2); + int panel_id = qwaq_cmd_peek (res, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); hide_panel (panel->panel); @@ -375,7 +330,7 @@ cmd_hide_panel (qwaq_resources_t *res) static void cmd_show_panel (qwaq_resources_t *res) { - int panel_id = *RB_PEEK_DATA (res->command_queue, 2); + int panel_id = qwaq_cmd_peek (res, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); show_panel (panel->panel); @@ -384,7 +339,7 @@ cmd_show_panel (qwaq_resources_t *res) static void cmd_top_panel (qwaq_resources_t *res) { - int panel_id = *RB_PEEK_DATA (res->command_queue, 2); + int panel_id = qwaq_cmd_peek (res, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); top_panel (panel->panel); @@ -393,7 +348,7 @@ cmd_top_panel (qwaq_resources_t *res) static void cmd_bottom_panel (qwaq_resources_t *res) { - int panel_id = *RB_PEEK_DATA (res->command_queue, 2); + int panel_id = qwaq_cmd_peek (res, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); bottom_panel (panel->panel); @@ -402,9 +357,9 @@ cmd_bottom_panel (qwaq_resources_t *res) static void cmd_move_panel (qwaq_resources_t *res) { - int panel_id = *RB_PEEK_DATA (res->command_queue, 2); - int x = *RB_PEEK_DATA (res->command_queue, 3); - int y = *RB_PEEK_DATA (res->command_queue, 4); + int panel_id = qwaq_cmd_peek (res, 2); + int x = qwaq_cmd_peek (res, 3); + int y = qwaq_cmd_peek (res, 4); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); move_panel (panel->panel, y, x); @@ -413,20 +368,20 @@ cmd_move_panel (qwaq_resources_t *res) static void cmd_panel_window (qwaq_resources_t *res) { - int panel_id = *RB_PEEK_DATA (res->command_queue, 2); + int panel_id = qwaq_cmd_peek (res, 2); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); int window_id = panel->window_id; int cmd_result[] = { qwaq_cmd_panel_window, window_id, }; - qwaq_submit_result (res, cmd_result, CMD_SIZE (cmd_result)); + qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result)); } static void cmd_replace_panel (qwaq_resources_t *res) { - int panel_id = *RB_PEEK_DATA (res->command_queue, 2); - int window_id = *RB_PEEK_DATA (res->command_queue, 3); + int panel_id = qwaq_cmd_peek (res, 2); + int window_id = qwaq_cmd_peek (res, 3); panel_t *panel = get_panel (res, __FUNCTION__, panel_id); window_t *window = get_window (res, __FUNCTION__, window_id); @@ -449,34 +404,34 @@ cmd_doupdate (qwaq_resources_t *res) static void cmd_mvwaddstr (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int x = *RB_PEEK_DATA (res->command_queue, 3); - int y = *RB_PEEK_DATA (res->command_queue, 4); - int string_id = *RB_PEEK_DATA (res->command_queue, 5); + int window_id = qwaq_cmd_peek (res, 2); + int x = qwaq_cmd_peek (res, 3); + int y = qwaq_cmd_peek (res, 4); + int string_id = qwaq_cmd_peek (res, 5); window_t *window = get_window (res, __FUNCTION__, window_id); - mvwaddstr (window->win, y, x, res->strings[string_id].str); - release_string (res, string_id); + mvwaddstr (window->win, y, x, qwaq_cmd_string (res, string_id)->str); + qwaq_pipe_release_string (&res->commands, string_id); } static void cmd_waddstr (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int string_id = *RB_PEEK_DATA (res->command_queue, 3); + int window_id = qwaq_cmd_peek (res, 2); + int string_id = qwaq_cmd_peek (res, 3); window_t *window = get_window (res, __FUNCTION__, window_id); - waddstr (window->win, res->strings[string_id].str); - release_string (res, string_id); + waddstr (window->win, qwaq_cmd_string (res, string_id)->str); + qwaq_pipe_release_string (&res->commands, string_id); } static void cmd_mvwaddch (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int x = *RB_PEEK_DATA (res->command_queue, 3); - int y = *RB_PEEK_DATA (res->command_queue, 4); - int ch = *RB_PEEK_DATA (res->command_queue, 5); + int window_id = qwaq_cmd_peek (res, 2); + int x = qwaq_cmd_peek (res, 3); + int y = qwaq_cmd_peek (res, 4); + int ch = qwaq_cmd_peek (res, 5); window_t *window = get_window (res, __FUNCTION__, window_id); mvwaddch (window->win, y, x, ch); @@ -485,8 +440,8 @@ cmd_mvwaddch (qwaq_resources_t *res) static void cmd_waddch (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int ch = *RB_PEEK_DATA (res->command_queue, 3); + int window_id = qwaq_cmd_peek (res, 2); + int ch = qwaq_cmd_peek (res, 3); window_t *window = get_window (res, __FUNCTION__, window_id); waddch (window->win, ch); @@ -495,7 +450,7 @@ cmd_waddch (qwaq_resources_t *res) static void cmd_wrefresh (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int window_id = qwaq_cmd_peek (res, 2); window_t *window = get_window (res, __FUNCTION__, window_id); wrefresh (window->win); @@ -504,9 +459,9 @@ cmd_wrefresh (qwaq_resources_t *res) static void cmd_init_pair (qwaq_resources_t *res) { - int pair = *RB_PEEK_DATA (res->command_queue, 2); - int f = *RB_PEEK_DATA (res->command_queue, 3); - int b = *RB_PEEK_DATA (res->command_queue, 4); + int pair = qwaq_cmd_peek (res, 2); + int f = qwaq_cmd_peek (res, 3); + int b = qwaq_cmd_peek (res, 4); init_pair (pair, f, b); } @@ -514,8 +469,8 @@ cmd_init_pair (qwaq_resources_t *res) static void cmd_wbkgd (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int ch = *RB_PEEK_DATA (res->command_queue, 3); + int window_id = qwaq_cmd_peek (res, 2); + int ch = qwaq_cmd_peek (res, 3); window_t *window = get_window (res, __FUNCTION__, window_id); wbkgd (window->win, ch); @@ -524,7 +479,7 @@ cmd_wbkgd (qwaq_resources_t *res) static void cmd_werase (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); + int window_id = qwaq_cmd_peek (res, 2); window_t *window = get_window (res, __FUNCTION__, window_id); werase (window->win); @@ -533,8 +488,8 @@ cmd_werase (qwaq_resources_t *res) static void cmd_scrollok (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int flag = *RB_PEEK_DATA (res->command_queue, 3); + int window_id = qwaq_cmd_peek (res, 2); + int flag = qwaq_cmd_peek (res, 3); window_t *window = get_window (res, __FUNCTION__, window_id); scrollok (window->win, flag); @@ -543,9 +498,9 @@ cmd_scrollok (qwaq_resources_t *res) static void cmd_wmove (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int x = *RB_PEEK_DATA (res->command_queue, 3); - int y = *RB_PEEK_DATA (res->command_queue, 4); + int window_id = qwaq_cmd_peek (res, 2); + int x = qwaq_cmd_peek (res, 3); + int y = qwaq_cmd_peek (res, 4); window_t *window = get_window (res, __FUNCTION__, window_id); wmove (window->win, y, x); @@ -554,8 +509,8 @@ cmd_wmove (qwaq_resources_t *res) static void cmd_move (qwaq_resources_t *res) { - int x = *RB_PEEK_DATA (res->command_queue, 2); - int y = *RB_PEEK_DATA (res->command_queue, 3); + int x = qwaq_cmd_peek (res, 2); + int y = qwaq_cmd_peek (res, 3); move (y, x); } @@ -563,7 +518,7 @@ cmd_move (qwaq_resources_t *res) static void cmd_curs_set (qwaq_resources_t *res) { - int visibility = *RB_PEEK_DATA (res->command_queue, 2); + int visibility = qwaq_cmd_peek (res, 2); curs_set (visibility); } @@ -571,15 +526,15 @@ cmd_curs_set (qwaq_resources_t *res) static void cmd_wborder (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int ls = *RB_PEEK_DATA (res->command_queue, 3); - int rs = *RB_PEEK_DATA (res->command_queue, 4); - int ts = *RB_PEEK_DATA (res->command_queue, 5); - int bs = *RB_PEEK_DATA (res->command_queue, 6); - int tl = *RB_PEEK_DATA (res->command_queue, 7); - int tr = *RB_PEEK_DATA (res->command_queue, 8); - int bl = *RB_PEEK_DATA (res->command_queue, 9); - int br = *RB_PEEK_DATA (res->command_queue, 10); + int window_id = qwaq_cmd_peek (res, 2); + int ls = qwaq_cmd_peek (res, 3); + int rs = qwaq_cmd_peek (res, 4); + int ts = qwaq_cmd_peek (res, 5); + int bs = qwaq_cmd_peek (res, 6); + int tl = qwaq_cmd_peek (res, 7); + int tr = qwaq_cmd_peek (res, 8); + int bl = qwaq_cmd_peek (res, 9); + int br = qwaq_cmd_peek (res, 10); window_t *window = get_window (res, __FUNCTION__, window_id); wborder (window->win, ls, rs, ts, bs, tl, tr, bl, br); @@ -588,12 +543,12 @@ cmd_wborder (qwaq_resources_t *res) static void cmd_mvwblit_line (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int x = *RB_PEEK_DATA (res->command_queue, 3); - int y = *RB_PEEK_DATA (res->command_queue, 4); - int chs_id = *RB_PEEK_DATA (res->command_queue, 5); - int len = *RB_PEEK_DATA (res->command_queue, 6); - int *chs = (int *) res->strings[chs_id].str; + int window_id = qwaq_cmd_peek (res, 2); + int x = qwaq_cmd_peek (res, 3); + int y = qwaq_cmd_peek (res, 4); + int chs_id = qwaq_cmd_peek (res, 5); + int len = qwaq_cmd_peek (res, 6); + int *chs = (int *) qwaq_cmd_string (res, chs_id)->str; int save_x; int save_y; @@ -605,15 +560,15 @@ cmd_mvwblit_line (qwaq_resources_t *res) } } wmove (window->win, save_y, save_x); - release_string (res, chs_id); + qwaq_pipe_release_string (&res->commands, chs_id); } static void cmd_wresize (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int width = *RB_PEEK_DATA (res->command_queue, 3); - int height = *RB_PEEK_DATA (res->command_queue, 4); + int window_id = qwaq_cmd_peek (res, 2); + int width = qwaq_cmd_peek (res, 3); + int height = qwaq_cmd_peek (res, 4); window_t *window = get_window (res, __FUNCTION__, window_id); wresize (window->win, height, width); @@ -622,8 +577,8 @@ cmd_wresize (qwaq_resources_t *res) static void cmd_resizeterm (qwaq_resources_t *res) { - int width = *RB_PEEK_DATA (res->command_queue, 2); - int height = *RB_PEEK_DATA (res->command_queue, 3); + int width = qwaq_cmd_peek (res, 2); + int height = qwaq_cmd_peek (res, 3); resizeterm (height, width); } @@ -631,11 +586,11 @@ cmd_resizeterm (qwaq_resources_t *res) static void cmd_mvwhline (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int x = *RB_PEEK_DATA (res->command_queue, 3); - int y = *RB_PEEK_DATA (res->command_queue, 4); - int ch = *RB_PEEK_DATA (res->command_queue, 5); - int n = *RB_PEEK_DATA (res->command_queue, 6); + int window_id = qwaq_cmd_peek (res, 2); + int x = qwaq_cmd_peek (res, 3); + int y = qwaq_cmd_peek (res, 4); + int ch = qwaq_cmd_peek (res, 5); + int n = qwaq_cmd_peek (res, 6); window_t *window = get_window (res, __FUNCTION__, window_id); mvwhline (window->win, y, x, ch, n); @@ -644,47 +599,74 @@ cmd_mvwhline (qwaq_resources_t *res) static void cmd_mvwvline (qwaq_resources_t *res) { - int window_id = *RB_PEEK_DATA (res->command_queue, 2); - int x = *RB_PEEK_DATA (res->command_queue, 3); - int y = *RB_PEEK_DATA (res->command_queue, 4); - int ch = *RB_PEEK_DATA (res->command_queue, 5); - int n = *RB_PEEK_DATA (res->command_queue, 6); + int window_id = qwaq_cmd_peek (res, 2); + int x = qwaq_cmd_peek (res, 3); + int y = qwaq_cmd_peek (res, 4); + int ch = qwaq_cmd_peek (res, 5); + int n = qwaq_cmd_peek (res, 6); window_t *window = get_window (res, __FUNCTION__, window_id); mvwvline (window->win, y, x, ch, n); } +static void +cmd_send_connected_devices (qwaq_resources_t *res) +{ + IN_SendConnectedDevices (); +} + +static void +cmd_get_device_info (qwaq_resources_t *res) +{ + int devid = qwaq_cmd_peek (res, 2); + int name_id = qwaq_pipe_acquire_string (&res->results); + int id_id = qwaq_pipe_acquire_string (&res->results); + int axis_id = qwaq_pipe_acquire_string (&res->results); + int button_id = qwaq_pipe_acquire_string (&res->results); + + dstring_t *name_string = qwaq_res_string (res, name_id); + dstring_t *id_string = qwaq_res_string (res, id_id); + dstring_t *axis_buffer = qwaq_res_string (res, axis_id); + dstring_t *button_buffer = qwaq_res_string (res, button_id); + + dstring_copystr (name_string, IN_GetDeviceName (devid)); + dstring_copystr (id_string, IN_GetDeviceId (devid)); + + int num; + IN_AxisInfo (devid, 0, &num); + axis_buffer->size = num * sizeof (in_axisinfo_t); + dstring_adjust (axis_buffer); + IN_AxisInfo (devid, (in_axisinfo_t *) axis_buffer->str, &num); + + IN_ButtonInfo (devid, 0, &num); + button_buffer->size = num * sizeof (in_buttoninfo_t); + dstring_adjust (button_buffer); + IN_ButtonInfo (devid, (in_buttoninfo_t *) button_buffer->str, &num); + + int cmd_result[] = { + qwaq_cmd_get_device_info, + name_id, id_id, axis_id, button_id + }; + qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result)); +} + static void dump_command (qwaq_resources_t *res, int len) { if (0) { - qwaq_commands cmd = *RB_PEEK_DATA (res->command_queue, 0); + qwaq_commands cmd = qwaq_cmd_peek (res, 0); Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); if (cmd == qwaq_cmd_syncprint) { Sys_Printf (" "); } else { for (int i = 2; i < len; i++) { - Sys_Printf (" %d", *RB_PEEK_DATA (res->command_queue, i)); + Sys_Printf (" %d", qwaq_cmd_peek (res, i)); } Sys_Printf ("\n"); } } } -void -qwaq_init_timeout (struct timespec *timeout, int64_t time) -{ - #define SEC 1000000000L - struct timeval now; - gettimeofday(&now, 0); - timeout->tv_sec = now.tv_sec; - timeout->tv_nsec = now.tv_usec * 1000L + time; - if (timeout->tv_nsec >= SEC) { - timeout->tv_sec += timeout->tv_nsec / SEC; - timeout->tv_nsec %= SEC; - } -} - static void process_commands (qwaq_resources_t *res) { @@ -693,22 +675,22 @@ process_commands (qwaq_resources_t *res) int len; int ret = 0; - pthread_mutex_lock (&res->command_cond.mut); + pthread_mutex_lock (&res->commands.pipe_cond.mut); qwaq_init_timeout (&timeout, 20 * 1000000); - while (RB_DATA_AVAILABLE (res->command_queue) < 2 && ret == 0) { - ret = pthread_cond_timedwait (&res->command_cond.rcond, - &res->command_cond.mut, &timeout); + while (RB_DATA_AVAILABLE (res->commands.pipe) < 2 && ret == 0) { + ret = pthread_cond_timedwait (&res->commands.pipe_cond.rcond, + &res->commands.pipe_cond.mut, &timeout); } // The mutex is unlocked at the top of the loop and locked again // (for broadcast) at the bottom, then finally unlocked after the loop. // It should be only the data availability check that's not threadsafe // as the mutex is not released until after the data has been written to // the buffer. - while ((avail = RB_DATA_AVAILABLE (res->command_queue)) >= 2 - && avail >= (len = *RB_PEEK_DATA (res->command_queue, 1))) { - pthread_mutex_unlock (&res->command_cond.mut); + while ((avail = RB_DATA_AVAILABLE (res->commands.pipe)) >= 2 + && avail >= (len = qwaq_cmd_peek (res, 1))) { + pthread_mutex_unlock (&res->commands.pipe_cond.mut); dump_command (res, len); - qwaq_commands cmd = *RB_PEEK_DATA (res->command_queue, 0); + qwaq_commands cmd = qwaq_cmd_peek (res, 0); switch (cmd) { case qwaq_cmd_syncprint: cmd_syncprint (res); @@ -809,14 +791,21 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_mvwvline: cmd_mvwvline (res); break; + + case qwaq_cmd_send_connected_devices: + cmd_send_connected_devices (res); + break; + case qwaq_cmd_get_device_info: + cmd_get_device_info (res); + break; } - pthread_mutex_lock (&res->command_cond.mut); - RB_RELEASE (res->command_queue, len); - pthread_cond_broadcast (&res->command_cond.wcond); + pthread_mutex_lock (&res->commands.pipe_cond.mut); + RB_RELEASE (res->commands.pipe, len); + pthread_cond_broadcast (&res->commands.pipe_cond.wcond); // unlocked at top of top if there's more data, otherwise just after // the loop } - pthread_mutex_unlock (&res->command_cond.mut); + pthread_mutex_unlock (&res->commands.pipe_cond.mut); } static int @@ -826,15 +815,15 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) int ret = 0; int was_event = 0; - pthread_mutex_lock (&res->event_cond.mut); + pthread_mutex_lock (&res->events.cond.mut); qwaq_init_timeout (&timeout, 20 * 1000000); - while (RB_DATA_AVAILABLE (res->event_queue) < 1 && ret == 0) { - ret = pthread_cond_timedwait (&res->event_cond.rcond, - &res->event_cond.mut, &timeout); + while (RB_DATA_AVAILABLE (res->events.queue) < 1 && ret == 0) { + ret = pthread_cond_timedwait (&res->events.cond.rcond, + &res->events.cond.mut, &timeout); } if (event) { if (ret == 0) { - RB_READ_DATA (res->event_queue, event, 1); + RB_READ_DATA (res->events.queue, event, 1); was_event = 1; } else if (res->button_state) { event->what = qe_mouseauto; @@ -846,8 +835,8 @@ get_event (qwaq_resources_t *res, qwaq_event_t *event) event->what = qe_none; } } - pthread_cond_broadcast (&res->event_cond.wcond); - pthread_mutex_unlock (&res->event_cond.mut); + pthread_cond_broadcast (&res->events.cond.wcond); + pthread_mutex_unlock (&res->events.cond.mut); return was_event; } @@ -871,8 +860,8 @@ bi_syncprintf (progs_t *pr) const char *fmt = P_GSTRING (pr, 0); int count = pr->pr_argc - 1; pr_type_t **args = pr->pr_params + 1; - int string_id = acquire_string (res); - dstring_t *print_buffer = res->strings + string_id; + int string_id = qwaq_pipe_acquire_string (&res->commands); + dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_syncprint, 0, string_id }; command[1] = CMD_SIZE(command); @@ -880,7 +869,7 @@ bi_syncprintf (progs_t *pr) dstring_clearstr (print_buffer); PR_Sprintf (pr, print_buffer, "mvwaddstr", fmt, count, args); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } static void @@ -896,10 +885,11 @@ bi_newwin (progs_t *pr) xpos, ypos, xlen, ylen, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); int cmd_result[2]; - qwaq_wait_result (res, cmd_result, qwaq_cmd_newwin, CMD_SIZE (cmd_result)); + qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_newwin, + CMD_SIZE (cmd_result)); R_INT (pr) = cmd_result[1]; } @@ -912,7 +902,7 @@ bi_delwin (progs_t *pr) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_delwin, 0, window_id, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } @@ -924,11 +914,11 @@ qwaq_getwrect (progs_t *pr, int window_id) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_getwrect, 0, window_id, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); int cmd_result[5]; - qwaq_wait_result (res, cmd_result, qwaq_cmd_getwrect, - CMD_SIZE (cmd_result)); + qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_getwrect, + CMD_SIZE (cmd_result)); // return xpos, ypos, xlen, ylen (&R_INT (pr))[0] = cmd_result[1]; (&R_INT (pr))[1] = cmd_result[2]; @@ -951,11 +941,11 @@ bi_new_panel (progs_t *pr) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_new_panel, 0, window_id, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); int cmd_result[2]; - qwaq_wait_result (res, cmd_result, qwaq_cmd_new_panel, - CMD_SIZE (cmd_result)); + qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_new_panel, + CMD_SIZE (cmd_result)); R_INT (pr) = cmd_result[1]; } } @@ -969,7 +959,7 @@ panel_command (progs_t *pr, qwaq_commands cmd) if (get_panel (res, __FUNCTION__, panel_id)) { int command[] = { cmd, 0, panel_id, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } @@ -1014,7 +1004,7 @@ bi_move_panel (progs_t *pr) if (get_panel (res, __FUNCTION__, panel_id)) { int command[] = { qwaq_cmd_move_panel, 0, panel_id, x, y, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } @@ -1027,11 +1017,11 @@ bi_panel_window (progs_t *pr) if (get_panel (res, __FUNCTION__, panel_id)) { int command[] = { qwaq_cmd_panel_window, 0, panel_id, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); int cmd_result[2]; - qwaq_wait_result (res, cmd_result, qwaq_cmd_panel_window, - CMD_SIZE (cmd_result)); + qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_panel_window, + CMD_SIZE (cmd_result)); (&R_INT (pr))[0] = cmd_result[1]; } } @@ -1048,7 +1038,7 @@ bi_replace_panel (progs_t *pr) int command[] = { qwaq_cmd_replace_panel, 0, panel_id, window_id}; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } @@ -1059,7 +1049,7 @@ qwaq_update_panels (progs_t *pr) int command[] = { qwaq_cmd_update_panels, 0, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } static void bi_update_panels (progs_t *pr) @@ -1074,7 +1064,7 @@ qwaq_doupdate (progs_t *pr) int command[] = { qwaq_cmd_doupdate, 0, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } static void bi_doupdate (progs_t *pr) @@ -1088,8 +1078,8 @@ qwaq_waddstr (progs_t *pr, int window_id, const char *str) qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); if (get_window (res, __FUNCTION__, window_id)) { - int string_id = acquire_string (res); - dstring_t *print_buffer = res->strings + string_id; + int string_id = qwaq_pipe_acquire_string (&res->commands); + dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_waddstr, 0, window_id, string_id @@ -1098,7 +1088,7 @@ qwaq_waddstr (progs_t *pr, int window_id, const char *str) command[1] = CMD_SIZE(command); dstring_copystr (print_buffer, str); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1122,7 +1112,7 @@ qwaq_wresize (progs_t *pr, int window_id, int width, int height) }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1143,7 +1133,7 @@ qwaq_resizeterm (progs_t *pr, int width, int height) int command[] = { qwaq_cmd_resizeterm, 0, width, height }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } static void bi_resizeterm (progs_t *pr) @@ -1166,7 +1156,7 @@ qwaq_mvwhline (progs_t *pr, int window_id, int x, int y, int ch, int n) }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1193,7 +1183,7 @@ qwaq_mvwvline (progs_t *pr, int window_id, int x, int y, int ch, int n) }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1214,8 +1204,8 @@ qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str) qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); if (get_window (res, __FUNCTION__, window_id)) { - int string_id = acquire_string (res); - dstring_t *print_buffer = res->strings + string_id; + int string_id = qwaq_pipe_acquire_string (&res->commands); + dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_mvwaddstr, 0, window_id, x, y, string_id @@ -1224,7 +1214,7 @@ qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str) command[1] = CMD_SIZE(command); dstring_copystr (print_buffer, str); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1245,8 +1235,8 @@ qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); if (get_window (res, __FUNCTION__, window_id)) { - int string_id = acquire_string (res); - dstring_t *print_buffer = res->strings + string_id; + int string_id = qwaq_pipe_acquire_string (&res->commands); + dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_mvwaddstr, 0, window_id, x, y, string_id @@ -1257,7 +1247,7 @@ qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, dstring_clearstr (print_buffer); PR_Sprintf (pr, print_buffer, "mvwaddstr", fmt, count, args); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1280,8 +1270,8 @@ qwaq_wprintf (progs_t *pr, int window_id, const char *fmt, qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); if (get_window (res, __FUNCTION__, window_id)) { - int string_id = acquire_string (res); - dstring_t *print_buffer = res->strings + string_id; + int string_id = qwaq_pipe_acquire_string (&res->commands); + dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_waddstr, 0, window_id, string_id @@ -1292,7 +1282,7 @@ qwaq_wprintf (progs_t *pr, int window_id, const char *fmt, dstring_clearstr (print_buffer); PR_Sprintf (pr, print_buffer, "waddstr", fmt, count, args); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1318,8 +1308,8 @@ qwaq_wvprintf (progs_t *pr, int window_id, const char *fmt, pr_va_list_t *args) } if (get_window (res, __FUNCTION__, window_id)) { - int string_id = acquire_string (res); - dstring_t *print_buffer = res->strings + string_id; + int string_id = qwaq_pipe_acquire_string (&res->commands); + dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_waddstr, 0, window_id, string_id @@ -1330,7 +1320,7 @@ qwaq_wvprintf (progs_t *pr, int window_id, const char *fmt, pr_va_list_t *args) dstring_clearstr (print_buffer); PR_Sprintf (pr, print_buffer, "waddstr", fmt, args->count, list); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1352,7 +1342,7 @@ qwaq_waddch (progs_t *pr, int window_id, int ch) int command[] = { qwaq_cmd_waddch, 0, window_id, ch }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1377,8 +1367,8 @@ qwaq_mvwvprintf (progs_t *pr, int window_id, int x, int y, } if (get_window (res, __FUNCTION__, window_id)) { - int string_id = acquire_string (res); - dstring_t *print_buffer = res->strings + string_id; + int string_id = qwaq_pipe_acquire_string (&res->commands); + dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_mvwaddstr, 0, window_id, x, y, string_id @@ -1389,7 +1379,7 @@ qwaq_mvwvprintf (progs_t *pr, int window_id, int x, int y, dstring_clearstr (print_buffer); PR_Sprintf (pr, print_buffer, "waddstr", fmt, args->count, list); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1415,7 +1405,7 @@ qwaq_mvwaddch (progs_t *pr, int window_id, int x, int y, int ch) window_id, x, y, ch }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1437,7 +1427,7 @@ qwaq_wrefresh (progs_t *pr, int window_id) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wrefresh, 0, window_id, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1476,7 +1466,7 @@ qwaq_init_pair (progs_t *pr, int pair, int f, int b) int command[] = { qwaq_cmd_init_pair, 0, pair, f, b, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } static void bi_init_pair (progs_t *pr) @@ -1496,7 +1486,7 @@ qwaq_wbkgd (progs_t *pr, int window_id, int ch) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wbkgd, 0, window_id, ch, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1516,7 +1506,7 @@ qwaq_werase (progs_t *pr, int window_id, int ch) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_werase, 0, window_id, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1536,7 +1526,7 @@ qwaq_scrollok (progs_t *pr, int window_id, int flag) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_scrollok, 0, window_id, flag, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1556,7 +1546,7 @@ qwaq_wmove (progs_t *pr, int window_id, int x, int y) if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wmove, 0, window_id, x, y, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1596,7 +1586,7 @@ qwaq_move (progs_t *pr, int x, int y) int command[] = { qwaq_cmd_move, 0, x, y, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } static void bi_move (progs_t *pr) @@ -1614,7 +1604,7 @@ qwaq_curs_set (progs_t *pr, int visibility) int command[] = { qwaq_cmd_curs_set, 0, visibility, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } static void bi_curs_set (progs_t *pr) @@ -1635,7 +1625,7 @@ qwaq_wborder (progs_t *pr, int window_id, sides.ls, sides.rs, sides.ts, sides.bs, corns.tl, corns.tr, corns.bl, corns.br, }; command[1] = CMD_SIZE(command); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1655,8 +1645,8 @@ qwaq__mvwblit_line (progs_t *pr, int window_id, int x, int y, qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); if (get_window (res, __FUNCTION__, window_id)) { - int chs_id = acquire_string (res); - dstring_t *chs_buf = res->strings + chs_id; + int chs_id = qwaq_pipe_acquire_string (&res->commands); + dstring_t *chs_buf = qwaq_cmd_string (res, chs_id); int command[] = { qwaq_cmd_mvwblit_line, 0, window_id, x, y, chs_id, len,}; @@ -1666,7 +1656,7 @@ qwaq__mvwblit_line (progs_t *pr, int window_id, int x, int y, dstring_adjust (chs_buf); memcpy (chs_buf->str, chs, len * sizeof (int)); - qwaq_submit_command (res, command); + qwaq_pipe_submit (&res->commands, command, command[1]); } } static void @@ -1680,6 +1670,84 @@ bi_mvwblit_line (progs_t *pr) qwaq__mvwblit_line (pr, window_id, x, y, chs, len); } +static void +qwaq_send_connected_devices (progs_t *pr) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + int command[] = { + qwaq_cmd_send_connected_devices, 0, + }; + + command[1] = CMD_SIZE(command); + qwaq_pipe_submit (&res->commands, command, command[1]); +} +static void +bi_send_connected_devices (progs_t *pr) +{ + qwaq_send_connected_devices (pr); +} + +static void +qwaq_get_device_info (progs_t *pr, int devid, int *name_id, int *id_id, + int *axis_id, int *button_id) +{ + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + + Sys_Printf ("qwaq_get_device_info: %d\n", devid); + int command[] = { + qwaq_cmd_get_device_info, 0, + devid, + }; + + command[1] = CMD_SIZE(command); + qwaq_pipe_submit (&res->commands, command, command[1]); + + int cmd_result[5]; + qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_get_device_info, + CMD_SIZE (cmd_result)); + *name_id = cmd_result[1]; + *id_id = cmd_result[2]; + *axis_id = cmd_result[3]; + *button_id = cmd_result[4]; +} +static void +bi_get_device_info (progs_t *pr) +{ + int devid = P_INT (pr, 0); + int name_id, id_id, axis_id, button_id; + + qwaq_get_device_info (pr, devid, &name_id, &id_id, &axis_id, + &button_id); + + qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + dstring_t *name_string = qwaq_res_string (res, name_id); + dstring_t *id_string = qwaq_res_string (res, id_id); + dstring_t *axis_buffer = qwaq_res_string (res, axis_id); + dstring_t *button_buffer = qwaq_res_string (res, button_id); + + qwaq_devinfo_t *devinfo = PR_Zone_Malloc (pr, sizeof (qwaq_devinfo_t)); + in_axisinfo_t *axes = PR_Zone_Malloc (pr, axis_buffer->size); + in_buttoninfo_t *buttons = PR_Zone_Malloc (pr, button_buffer->size); + + memcpy (axes, axis_buffer->str, axis_buffer->size); + memcpy (buttons, button_buffer->str, button_buffer->size); + + devinfo->name = PR_SetDynamicString (pr, name_string->str); + devinfo->id = PR_SetDynamicString (pr, id_string->str); + devinfo->numaxes = axis_buffer->size / sizeof (in_axisinfo_t); + devinfo->axes = PR_SetPointer (pr, axes); + devinfo->numbuttons = button_buffer->size / sizeof (in_buttoninfo_t); + devinfo->buttons = PR_SetPointer (pr, buttons); + + qwaq_pipe_release_string (&res->results, name_id); + qwaq_pipe_release_string (&res->results, id_id); + qwaq_pipe_release_string (&res->results, axis_id); + qwaq_pipe_release_string (&res->results, button_id); + + RETURN_POINTER (pr, devinfo); +} + static void * qwaq_curses_thread (qwaq_thread_t *thread) { @@ -1862,9 +1930,9 @@ bi_i_TextContext__refresh (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; - //qwaq_wrefresh (pr, window_id); qwaq_update_panels (pr); if (window_id == 1) { + qwaq_wrefresh (pr, window_id); qwaq_doupdate (pr); } } @@ -2011,6 +2079,9 @@ static builtin_t builtins[] = { {"mvwhline", bi_mvwhline, -1}, {"mvwvline", bi_mvwvline, -1}, + {"send_connected_devices", bi_send_connected_devices, -1}, + {"get_device_info", bi_get_device_info, -1}, + {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, {"_c_TextContext__max_color_pairs", bi_c_TextContext__max_color_pairs, -1}, @@ -2040,32 +2111,22 @@ static builtin_t builtins[] = { {0} }; -void -qwaq_init_cond (rwcond_t *cond) -{ - pthread_cond_init (&cond->rcond, 0); - pthread_cond_init (&cond->wcond, 0); - pthread_mutex_init (&cond->mut, 0); -} - void BI_Init (progs_t *pr) { qwaq_resources_t *res = calloc (sizeof (*res), 1); res->pr = pr; - for (int i = 0; i < STRING_ID_QUEUE_SIZE - 1; i++) { - RB_WRITE_DATA (res->string_ids, &i, 1); - res->strings[i].mem = &dstring_default_mem; - } + qwaq_init_pipe (&res->commands); + qwaq_init_pipe (&res->results); + res->escbuff.mem = &dstring_default_mem; // ensure the backing buffer exists dstring_clearstr (&res->escbuff); - qwaq_init_cond (&res->event_cond); - qwaq_init_cond (&res->command_cond); - qwaq_init_cond (&res->results_cond); - qwaq_init_cond (&res->string_id_cond); + res->input_event_handler = -1; + + qwaq_init_cond (&res->events.cond); PR_Resources_Register (pr, "qwaq", res, bi_qwaq_clear); PR_RegisterBuiltins (pr, builtins); diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 94a95764b..bcfc11a83 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -46,6 +46,7 @@ #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/in_event.h" #include "QF/input.h" #include "QF/keys.h" #include "QF/sys.h" @@ -188,28 +189,28 @@ qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event) int ret = 0; // merge motion events - pthread_mutex_lock (&res->event_cond.mut); - unsigned last = RB_DATA_AVAILABLE (res->event_queue); + pthread_mutex_lock (&res->events.cond.mut); + unsigned last = RB_DATA_AVAILABLE (res->events.queue); if (event->what == qe_mousemove && last > 1 - && RB_PEEK_DATA(res->event_queue, last - 1)->what == qe_mousemove) { - RB_POKE_DATA(res->event_queue, last - 1, *event); + && RB_PEEK_DATA(res->events.queue, last - 1)->what == qe_mousemove) { + RB_POKE_DATA(res->events.queue, last - 1, *event); merged = 1; - pthread_cond_broadcast (&res->event_cond.rcond); + pthread_cond_broadcast (&res->events.cond.rcond); } - pthread_mutex_unlock (&res->event_cond.mut); + pthread_mutex_unlock (&res->events.cond.mut); if (merged) { return 0; } - pthread_mutex_lock (&res->event_cond.mut); + pthread_mutex_lock (&res->events.cond.mut); qwaq_init_timeout (&timeout, 5000 * (int64_t) 1000000); - while (RB_SPACE_AVAILABLE (res->event_queue) < 1 && ret == 0) { - ret = pthread_cond_timedwait (&res->event_cond.wcond, - &res->event_cond.mut, &timeout); + while (RB_SPACE_AVAILABLE (res->events.queue) < 1 && ret == 0) { + ret = pthread_cond_timedwait (&res->events.cond.wcond, + &res->events.cond.mut, &timeout); } - RB_WRITE_DATA (res->event_queue, event, 1); - pthread_cond_broadcast (&res->event_cond.rcond); - pthread_mutex_unlock (&res->event_cond.mut); + RB_WRITE_DATA (res->events.queue, event, 1); + pthread_cond_broadcast (&res->events.cond.rcond); + pthread_mutex_unlock (&res->events.cond.mut); return ret; } @@ -472,9 +473,52 @@ term_register_driver (void) term_driver_handle = IN_RegisterDriver (&term_driver, 0); } +static int +qwaq_input_event_handler (const IE_event_t *ie_event, void *_res) +{ + qwaq_resources_t *res = _res; + qwaq_event_t event = {}; + + event.when = ie_event->when * 1e-6 + Sys_DoubleTimeBase (); + + switch (ie_event->type) { + case ie_none: + case ie_gain_focus: + case ie_lose_focus: + return 0; + case ie_add_device: + event.what = qe_dev_add; + event.message.int_val = ie_event->device.devid; + break; + case ie_remove_device: + event.what = qe_dev_rem; + event.message.int_val = ie_event->device.devid; + break; + case ie_mouse: + case ie_key: + // these are handled directly for now + break; + case ie_axis: + event.what = qe_axis; + event.message.ivector_val[0] = ie_event->axis.devid; + event.message.ivector_val[1] = ie_event->axis.axis; + event.message.ivector_val[2] = ie_event->axis.value; + break; + case ie_button: + event.what = qe_button; + event.message.ivector_val[0] = ie_event->button.devid; + event.message.ivector_val[1] = ie_event->button.button; + event.message.ivector_val[2] = ie_event->button.state; + break; + } + qwaq_add_event (res, &event); + return 1; +} + void qwaq_input_init (qwaq_resources_t *res) { + res->input_event_handler = IE_Add_Handler (qwaq_input_event_handler, res); IN_DriverData (term_driver_handle, res); if (res->key_sequences) { @@ -511,6 +555,7 @@ qwaq_process_input (qwaq_resources_t *res) void qwaq_input_shutdown (qwaq_resources_t *res) { + IE_Remove_Handler (res->input_event_handler); IN_DriverData (term_driver_handle, 0); // ncurses takes care of input mode for us, so need only tell xterm diff --git a/ruamoko/qwaq/builtins/threading.c b/ruamoko/qwaq/builtins/threading.c new file mode 100644 index 000000000..7f258b90e --- /dev/null +++ b/ruamoko/qwaq/builtins/threading.c @@ -0,0 +1,140 @@ +/* + threading.c + + Ruamoko threading support + + Copyright (C) 2020 Bill Currie + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2020/03/01 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include + +#include "QF/dstring.h" + +#include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/threading.h" + +#define always_inline inline __attribute__((__always_inline__)) + +int +qwaq_pipe_acquire_string (qwaq_pipe_t *pipe) +{ + int string_id = -1; + + pthread_mutex_lock (&pipe->string_id_cond.mut); + while (RB_DATA_AVAILABLE (pipe->string_ids) < 1) { + pthread_cond_wait (&pipe->string_id_cond.rcond, + &pipe->string_id_cond.mut); + } + RB_READ_DATA (pipe->string_ids, &string_id, 1); + pthread_cond_broadcast (&pipe->string_id_cond.wcond); + pthread_mutex_unlock (&pipe->string_id_cond.mut); + return string_id; +} + +void +qwaq_pipe_release_string (qwaq_pipe_t *pipe, int string_id) +{ + pthread_mutex_lock (&pipe->string_id_cond.mut); + while (RB_SPACE_AVAILABLE (pipe->string_ids) < 1) { + pthread_cond_wait (&pipe->string_id_cond.wcond, + &pipe->string_id_cond.mut); + } + RB_WRITE_DATA (pipe->string_ids, &string_id, 1); + pthread_cond_broadcast (&pipe->string_id_cond.rcond); + pthread_mutex_unlock (&pipe->string_id_cond.mut); +} + +void +qwaq_pipe_submit (qwaq_pipe_t *pipe, const int *cmd, unsigned len) +{ + pthread_mutex_lock (&pipe->pipe_cond.mut); + while (RB_SPACE_AVAILABLE (pipe->pipe) < len) { + pthread_cond_wait (&pipe->pipe_cond.wcond, + &pipe->pipe_cond.mut); + } + RB_WRITE_DATA (pipe->pipe, cmd, len); + pthread_cond_broadcast (&pipe->pipe_cond.rcond); + pthread_mutex_unlock (&pipe->pipe_cond.mut); +} + +void +qwaq_pipe_receive (qwaq_pipe_t *pipe, int *result, int cmd, unsigned len) +{ + Sys_Printf ("qwaq_wait_result: %d %d\n", cmd, len); + pthread_mutex_lock (&pipe->pipe_cond.mut); + while (RB_DATA_AVAILABLE (pipe->pipe) < len + || *RB_PEEK_DATA (pipe->pipe, 0) != cmd) { + pthread_cond_wait (&pipe->pipe_cond.rcond, + &pipe->pipe_cond.mut); + } + RB_READ_DATA (pipe->pipe, result, len); + pthread_cond_broadcast (&pipe->pipe_cond.wcond); + pthread_mutex_unlock (&pipe->pipe_cond.mut); + Sys_Printf ("qwaq_wait_result exit: %d %d\n", cmd, len); +} + +void +qwaq_init_timeout (struct timespec *timeout, int64_t time) +{ + #define SEC 1000000000L + struct timeval now; + gettimeofday(&now, 0); + timeout->tv_sec = now.tv_sec; + timeout->tv_nsec = now.tv_usec * 1000L + time; + if (timeout->tv_nsec >= SEC) { + timeout->tv_sec += timeout->tv_nsec / SEC; + timeout->tv_nsec %= SEC; + } +} + +void +qwaq_init_cond (rwcond_t *cond) +{ + pthread_cond_init (&cond->rcond, 0); + pthread_cond_init (&cond->wcond, 0); + pthread_mutex_init (&cond->mut, 0); +} + +void +qwaq_init_pipe (qwaq_pipe_t *pipe) +{ + qwaq_init_cond (&pipe->pipe_cond); + qwaq_init_cond (&pipe->string_id_cond); + + for (int i = 0; i < STRING_ID_QUEUE_SIZE - 1; i++) { + RB_WRITE_DATA (pipe->string_ids, &i, 1); + pipe->strings[i].mem = &dstring_default_mem; + } +} diff --git a/ruamoko/qwaq/input-app.h b/ruamoko/qwaq/input-app.h new file mode 100644 index 000000000..1fd908bb2 --- /dev/null +++ b/ruamoko/qwaq/input-app.h @@ -0,0 +1,35 @@ +#ifndef __qwaq_app_h +#define __qwaq_app_h + +#include + +#include "ruamoko/qwaq/ui/event.h" +#include "ruamoko/qwaq/ui/rect.h" + +@class Array; +@class Group; +@class TextContext; +@class View; + +extern int color_palette[64]; + +@interface InputApplication: Object +{ + qwaq_event_t event; + qwaq_command endState; + + Group *objects; + + TextContext *screen; + Extent screenSize; + int autocount; +} +-(Extent)size; +-(TextContext *)screen; +-addView:(View *)view; +-run; +@end + +extern InputApplication *application; + +#endif//__qwaq_app_h diff --git a/ruamoko/qwaq/input-app.r b/ruamoko/qwaq/input-app.r new file mode 100644 index 000000000..8b7b5d34d --- /dev/null +++ b/ruamoko/qwaq/input-app.r @@ -0,0 +1,183 @@ +int fence; + +#include +#include +#include + +#include "ruamoko/qwaq/ui/color.h" +#include "ruamoko/qwaq/ui/curses.h" +#include "ruamoko/qwaq/ui/group.h" +#include "ruamoko/qwaq/ui/view.h" +#include "ruamoko/qwaq/qwaq-input.h" +#include "ruamoko/qwaq/input-app.h" + +string graph_up = " ⢀⢠⢰⢸⡀⣀⣠⣰⣸⡄⣄⣤⣴⣼⡆⣆⣦⣶⣾⡇⣇⣧⣷⣿"; +string graph_down = " ⠈⠘⠸⢸â â ‰â ™â ¹â¢¹â ƒâ ‹â ›â »â¢»â ‡â â Ÿâ ¿â¢¿â¡‡â¡â¡Ÿâ¡¿â£¿"; + +int color_palette[64]; + +static AutoreleasePool *autorelease_pool; +static void +arp_start (void) +{ + autorelease_pool = [[AutoreleasePool alloc] init]; +} + +static void +arp_end (void) +{ + [autorelease_pool release]; + autorelease_pool = nil; +} + +@implementation InputApplication ++app +{ + return [[[self alloc] init] autorelease]; +} + +-init +{ + if (!(self = [super init])) { + return nil; + } + + initialize (); + for (int i = 1; i < 64; i++) { + init_pair (i, i & 0x7, i >> 3); + color_palette[i] = COLOR_PAIR (i); + } + + screen = [TextContext screen]; + screenSize = [screen size]; + objects = [[Group withContext: screen owner: nil] retain]; + + [screen bkgd: color_palette[047]]; + [screen scrollok: 1]; + [screen clear]; + wrefresh (stdscr);//FIXME + + send_connected_devices (); + + return self; +} + +-(Extent)size +{ + return screenSize; +} + +-(TextContext *)screen +{ + return screen; +} + +-draw +{ + [objects draw]; + [screen refresh]; + return self; +} + +-handleEvent: (qwaq_event_t *) event +{ + switch (event.what) { + case qe_resize: + Extent delta; + delta.width = event.resize.width - screenSize.width; + delta.height = event.resize.height - screenSize.height; + + resizeterm (event.resize.width, event.resize.height); + [screen resizeTo: {event.resize.width, event.resize.height}]; + screenSize = [screen size]; + [objects resize: delta]; + [screen refresh]; + event.what = qe_none; + break; + case qe_key: + if (event.key.code == '\x18' || event.key.code == '\x11') { + endState = event.message.int_val; + event.what = qe_none; + } + break; + case qe_dev_add: + { + int devid = event.message.int_val; + qwaq_devinfo_t *dev = get_device_info (devid); + [screen printf:"dev add: %d %s %s\n", devid, dev.id, dev.name]; + [screen printf:" : %d %d\n", dev.numaxes, dev.numbuttons]; + for (int i = 0; i < dev.numaxes; i++) { + [screen printf:" : %d %d %d\n", dev.axes[i].value, + dev.axes[i].min, dev.axes[i].max]; + } + [screen refresh]; + obj_free (dev.axes); + obj_free (dev.buttons); + str_free (dev.name); + str_free (dev.id); + obj_free (dev); + } + break; + case qe_dev_rem: + [screen printf:"dev rem: %d\n", event.message.int_val]; + [screen refresh]; + break; + case qe_axis: + [screen printf:"axis: %d %d %d\n", event.message.ivector_val[0], + event.message.ivector_val[1], event.message.ivector_val[2]]; + [screen refresh]; + break; + case qe_button: + [screen printf:"button: %d %d %d\n", event.message.ivector_val[0], + event.message.ivector_val[1], event.message.ivector_val[2]]; + [screen refresh]; + } + if (event.what != qe_none) { + [objects handleEvent: event]; + } + return self; +} + +-run +{ + [objects takeFocus]; + [self draw]; + do { + arp_start (); + + get_event (&event); + if (event.what != qe_none) { + [self handleEvent: &event]; + } + + arp_end (); + } while (!endState); + return self; +} + +-addView:(View *)view +{ + [objects insertSelected: view]; + [screen refresh]; + return self; +} +@end + +InputApplication *application; + +int main (int argc, string *argv) +{ + fence = 0; + //while (!fence) {} + + arp_start (); + application = [[InputApplication app] retain]; + arp_end (); + + [application run]; + [application release]; + qwaq_event_t event; + get_event (&event); // XXX need a "wait for queue idle" + + return 0; +} diff --git a/ruamoko/qwaq/qwaq-input.h b/ruamoko/qwaq/qwaq-input.h new file mode 100644 index 000000000..47474f077 --- /dev/null +++ b/ruamoko/qwaq/qwaq-input.h @@ -0,0 +1,52 @@ +#ifndef __qwaq_input_h +#define __qwaq_input_h + +#include "QF/input.h" + +typedef struct qwaq_devinfo_s { + int devid; +#ifdef __QFCC__ + string name; + string id; +#else + string_t name; + string_t id; +#endif + int numaxes; +#ifdef __QFCC__ + in_axisinfo_t *axes; +#else + pointer_t axes; +#endif + int numbuttons; +#ifdef __QFCC__ + in_axisinfo_t *buttons; +#else + pointer_t buttons; +#endif +} qwaq_devinfo_t; + +#ifdef __QFCC__ + +#include + +#include "ruamoko/qwaq/ui/event.h" +#include "ruamoko/qwaq/ui/rect.h" + + +@class Array; +@class Group; +@class TextContext; +@class View; + +@interface QwaqInput: Object +{ +} +@end + +void send_connected_devices (void); +qwaq_devinfo_t *get_device_info (int devid); + +#endif + +#endif//__qwaq_input_h diff --git a/ruamoko/qwaq/qwaq-input.r b/ruamoko/qwaq/qwaq-input.r new file mode 100644 index 000000000..effac892e --- /dev/null +++ b/ruamoko/qwaq/qwaq-input.r @@ -0,0 +1,4 @@ +#include "ruamoko/qwaq/qwaq-input.h" + +void send_connected_devices (void) = #0; +qwaq_devinfo_t *get_device_info (int devid) = #0; diff --git a/ruamoko/qwaq/threading.h b/ruamoko/qwaq/threading.h new file mode 100644 index 000000000..867ca3fc1 --- /dev/null +++ b/ruamoko/qwaq/threading.h @@ -0,0 +1,39 @@ +#ifndef __qwaq_threading_h +#define __qwaq_threading_h + +#ifndef __QFCC__ + +#include "QF/dstring.h" +#include "QF/ringbuffer.h" + +#define QUEUE_SIZE 16 +#define STRING_ID_QUEUE_SIZE 8 +#define COMMAND_QUEUE_SIZE 1280 + +typedef struct rwcond_s { + pthread_cond_t rcond; + pthread_cond_t wcond; + pthread_mutex_t mut; +} rwcond_t; + +typedef struct qwaq_pipe_s { + rwcond_t pipe_cond; + RING_BUFFER (int, COMMAND_QUEUE_SIZE) pipe; + + rwcond_t string_id_cond; + RING_BUFFER (int, STRING_ID_QUEUE_SIZE + 1) string_ids; + dstring_t strings[STRING_ID_QUEUE_SIZE]; +} qwaq_pipe_t; + +void qwaq_pipe_submit (qwaq_pipe_t *pipe, const int *data, unsigned len); +void qwaq_pipe_receive (qwaq_pipe_t *pipe, int *data, int id, unsigned len); +int qwaq_pipe_acquire_string (qwaq_pipe_t *pipe); +void qwaq_pipe_release_string (qwaq_pipe_t *pipe, int string_id); + +void qwaq_init_pipe (qwaq_pipe_t *pipe); +void qwaq_init_timeout (struct timespec *timeout, int64_t time); +void qwaq_init_cond (rwcond_t *cond); + +#endif + +#endif//__qwaq_threading_h diff --git a/ruamoko/qwaq/ui/curses.h b/ruamoko/qwaq/ui/curses.h index 6d57ded2a..5ba402701 100644 --- a/ruamoko/qwaq/ui/curses.h +++ b/ruamoko/qwaq/ui/curses.h @@ -145,6 +145,8 @@ void printf(string fmt, ...); #include "QF/progs.h" #include "QF/ringbuffer.h" +#include "ruamoko/qwaq/threading.h" + #define QUEUE_SIZE 16 #define STRING_ID_QUEUE_SIZE 8 // must be > 1 #define COMMAND_QUEUE_SIZE 1280 @@ -158,12 +160,6 @@ typedef struct panel_s { int window_id; } panel_t; -typedef struct rwcond_s { - pthread_cond_t rcond; - pthread_cond_t wcond; - pthread_mutex_t mut; -} rwcond_t; - typedef enum { esc_ground, esc_escape, @@ -173,21 +169,22 @@ typedef enum { esc_key, } esc_state_t; +typedef struct qwaq_event_queue_s { + rwcond_t cond; + RING_BUFFER (qwaq_event_t, QUEUE_SIZE) queue; +} qwaq_event_queue_t; + typedef struct qwaq_resources_s { progs_t *pr; int initialized; window_t stdscr; PR_RESMAP (window_t) window_map; PR_RESMAP (panel_t) panel_map; - rwcond_t event_cond; - RING_BUFFER (qwaq_event_t, QUEUE_SIZE) event_queue; - rwcond_t command_cond; - RING_BUFFER (int, COMMAND_QUEUE_SIZE) command_queue; - rwcond_t results_cond; - RING_BUFFER (int, COMMAND_QUEUE_SIZE) results; - rwcond_t string_id_cond; - RING_BUFFER (int, STRING_ID_QUEUE_SIZE) string_ids; - dstring_t strings[STRING_ID_QUEUE_SIZE - 1]; + + qwaq_event_queue_t events; + + qwaq_pipe_t commands; + qwaq_pipe_t results; dstring_t escbuff; esc_state_t escstate; @@ -196,15 +193,15 @@ typedef struct qwaq_resources_s { int mouse_y; qwaq_event_t lastClick; struct hashtab_s *key_sequences; + + int input_event_handler; } qwaq_resources_t; // gcc stuff void qwaq_input_init (qwaq_resources_t *res); void qwaq_input_shutdown (qwaq_resources_t *res); void qwaq_process_input (qwaq_resources_t *res); -void qwaq_init_timeout (struct timespec *timeout, int64_t time); int qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event); -void qwaq_init_cond (rwcond_t *cond); #endif #endif//__qwaq_ui_curses_h diff --git a/ruamoko/qwaq/ui/event.h b/ruamoko/qwaq/ui/event.h index 7e38f52b1..6de52297b 100644 --- a/ruamoko/qwaq/ui/event.h +++ b/ruamoko/qwaq/ui/event.h @@ -22,6 +22,11 @@ typedef enum { qe_command = 0x0200, // application level command qe_broadcast = 0x0400, qe_resize = 0x0800, // screen resized + + qe_dev_add = 0x1000, + qe_dev_rem = 0x2000, + qe_axis = 0x4000, + qe_button = 0x8000, } qwaq_message_event; typedef enum { @@ -61,6 +66,7 @@ typedef union qwaq_message_s { int int_val; float float_val; float vector_val[4]; // vector and quaternion + int ivector_val[4]; double double_val; #ifdef __QFCC__ void *pointer_val; From 72900fd16b49beb34d1bf2745e9d9a81a35c3a6b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Sep 2021 16:22:11 +0900 Subject: [PATCH 1746/3664] [qwaq] Move input handling to its own thread As it is now a completely separate sub-system, there is a bit of trouble with mouse handling in that curses must be initialized before input for the mouse to work properly, but the basic scheme seems to be working nicely. I suspect the solution to the init order issue is to make have the curses sub-system initialize the terminal input driver, at least for mouse input (ie, maybe just enable/disable mouse handing). --- ruamoko/qwaq/builtins/curses.c | 275 ++++------------------- ruamoko/qwaq/builtins/debug.c | 6 +- ruamoko/qwaq/builtins/input.c | 337 ++++++++++++++++++++++++++-- ruamoko/qwaq/builtins/qwaq-curses.c | 3 +- ruamoko/qwaq/input-app.r | 1 + ruamoko/qwaq/qwaq-app.r | 4 + ruamoko/qwaq/qwaq-input.h | 1 + ruamoko/qwaq/qwaq-input.r | 1 + ruamoko/qwaq/qwaq.h | 2 + ruamoko/qwaq/ui/curses.h | 31 --- ruamoko/qwaq/ui/event.h | 41 ++++ 11 files changed, 413 insertions(+), 289 deletions(-) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 3be531c33..defb45cbb 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -42,13 +42,11 @@ #include #include "QF/dstring.h" -#include "QF/input.h" #include "QF/progs.h" #include "QF/ringbuffer.h" #include "QF/sys.h" #include "ruamoko/qwaq/qwaq.h" -#include "ruamoko/qwaq/qwaq-input.h" #include "ruamoko/qwaq/ui/curses.h" #include "ruamoko/qwaq/ui/rect.h" #include "ruamoko/qwaq/ui/textcontext.h" @@ -90,9 +88,6 @@ typedef enum qwaq_commands_e { qwaq_cmd_resizeterm, qwaq_cmd_mvwhline, qwaq_cmd_mvwvline, - - qwaq_cmd_send_connected_devices, - qwaq_cmd_get_device_info, } qwaq_commands; static const char *qwaq_command_names[]= { @@ -233,12 +228,6 @@ qwaq_cmd_string (qwaq_resources_t *res, int string_id) return res->commands.strings + string_id; } -static dstring_t * -qwaq_res_string (qwaq_resources_t *res, int string_id) -{ - return res->results.strings + string_id; -} - static void cmd_syncprint (qwaq_resources_t *res) { @@ -609,51 +598,10 @@ cmd_mvwvline (qwaq_resources_t *res) mvwvline (window->win, y, x, ch, n); } -static void -cmd_send_connected_devices (qwaq_resources_t *res) -{ - IN_SendConnectedDevices (); -} - -static void -cmd_get_device_info (qwaq_resources_t *res) -{ - int devid = qwaq_cmd_peek (res, 2); - int name_id = qwaq_pipe_acquire_string (&res->results); - int id_id = qwaq_pipe_acquire_string (&res->results); - int axis_id = qwaq_pipe_acquire_string (&res->results); - int button_id = qwaq_pipe_acquire_string (&res->results); - - dstring_t *name_string = qwaq_res_string (res, name_id); - dstring_t *id_string = qwaq_res_string (res, id_id); - dstring_t *axis_buffer = qwaq_res_string (res, axis_id); - dstring_t *button_buffer = qwaq_res_string (res, button_id); - - dstring_copystr (name_string, IN_GetDeviceName (devid)); - dstring_copystr (id_string, IN_GetDeviceId (devid)); - - int num; - IN_AxisInfo (devid, 0, &num); - axis_buffer->size = num * sizeof (in_axisinfo_t); - dstring_adjust (axis_buffer); - IN_AxisInfo (devid, (in_axisinfo_t *) axis_buffer->str, &num); - - IN_ButtonInfo (devid, 0, &num); - button_buffer->size = num * sizeof (in_buttoninfo_t); - dstring_adjust (button_buffer); - IN_ButtonInfo (devid, (in_buttoninfo_t *) button_buffer->str, &num); - - int cmd_result[] = { - qwaq_cmd_get_device_info, - name_id, id_id, axis_id, button_id - }; - qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result)); -} - static void dump_command (qwaq_resources_t *res, int len) { - if (0) { + if (1) { qwaq_commands cmd = qwaq_cmd_peek (res, 0); Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); if (cmd == qwaq_cmd_syncprint) { @@ -791,13 +739,6 @@ process_commands (qwaq_resources_t *res) case qwaq_cmd_mvwvline: cmd_mvwvline (res); break; - - case qwaq_cmd_send_connected_devices: - cmd_send_connected_devices (res); - break; - case qwaq_cmd_get_device_info: - cmd_get_device_info (res); - break; } pthread_mutex_lock (&res->commands.pipe_cond.mut); RB_RELEASE (res->commands.pipe, len); @@ -808,47 +749,11 @@ process_commands (qwaq_resources_t *res) pthread_mutex_unlock (&res->commands.pipe_cond.mut); } -static int -get_event (qwaq_resources_t *res, qwaq_event_t *event) -{ - struct timespec timeout; - int ret = 0; - int was_event = 0; - - pthread_mutex_lock (&res->events.cond.mut); - qwaq_init_timeout (&timeout, 20 * 1000000); - while (RB_DATA_AVAILABLE (res->events.queue) < 1 && ret == 0) { - ret = pthread_cond_timedwait (&res->events.cond.rcond, - &res->events.cond.mut, &timeout); - } - if (event) { - if (ret == 0) { - RB_READ_DATA (res->events.queue, event, 1); - was_event = 1; - } else if (res->button_state) { - event->what = qe_mouseauto; - event->when = Sys_DoubleTime (); - event->mouse.buttons = res->button_state; - event->mouse.x = res->mouse_x; - event->mouse.y = res->mouse_y; - } else { - event->what = qe_none; - } - } - pthread_cond_broadcast (&res->events.cond.wcond); - pthread_mutex_unlock (&res->events.cond.mut); - return was_event; -} - static int need_endwin; static void bi_shutdown (void *_pr) { - __auto_type pr = (progs_t *) _pr; - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - if (need_endwin) { - qwaq_input_shutdown (res); endwin (); } } @@ -856,7 +761,7 @@ bi_shutdown (void *_pr) static void bi_syncprintf (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); const char *fmt = P_GSTRING (pr, 0); int count = pr->pr_argc - 1; pr_type_t **args = pr->pr_params + 1; @@ -875,7 +780,7 @@ bi_syncprintf (progs_t *pr) static void bi_newwin (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int xpos = P_INT (pr, 0); int ypos = P_INT (pr, 1); int xlen = P_INT (pr, 2); @@ -896,7 +801,7 @@ bi_newwin (progs_t *pr) static void bi_delwin (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int window_id = P_INT (pr, 0); if (get_window (res, __FUNCTION__, window_id)) { @@ -909,7 +814,7 @@ bi_delwin (progs_t *pr) static void qwaq_getwrect (progs_t *pr, int window_id) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_getwrect, 0, window_id, }; @@ -935,7 +840,7 @@ bi_getwrect (progs_t *pr) static void bi_new_panel (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int window_id = P_INT (pr, 0); if (get_window (res, __FUNCTION__, window_id)) { @@ -953,7 +858,7 @@ bi_new_panel (progs_t *pr) static void panel_command (progs_t *pr, qwaq_commands cmd) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int panel_id = P_INT (pr, 0); if (get_panel (res, __FUNCTION__, panel_id)) { @@ -996,7 +901,7 @@ bi_bottom_panel (progs_t *pr) static void bi_move_panel (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int panel_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); @@ -1011,7 +916,7 @@ bi_move_panel (progs_t *pr) static void bi_panel_window (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int panel_id = P_INT (pr, 0); if (get_panel (res, __FUNCTION__, panel_id)) { @@ -1029,7 +934,7 @@ bi_panel_window (progs_t *pr) static void bi_replace_panel (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int panel_id = P_INT (pr, 0); int window_id = P_INT (pr, 1); @@ -1045,7 +950,7 @@ bi_replace_panel (progs_t *pr) static void qwaq_update_panels (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int command[] = { qwaq_cmd_update_panels, 0, }; command[1] = CMD_SIZE(command); @@ -1060,7 +965,7 @@ bi_update_panels (progs_t *pr) static void qwaq_doupdate (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int command[] = { qwaq_cmd_doupdate, 0, }; command[1] = CMD_SIZE(command); @@ -1075,7 +980,7 @@ bi_doupdate (progs_t *pr) static void qwaq_waddstr (progs_t *pr, int window_id, const char *str) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int string_id = qwaq_pipe_acquire_string (&res->commands); @@ -1103,7 +1008,7 @@ bi_waddstr (progs_t *pr) static void qwaq_wresize (progs_t *pr, int window_id, int width, int height) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { @@ -1128,7 +1033,7 @@ bi_wresize (progs_t *pr) static void qwaq_resizeterm (progs_t *pr, int width, int height) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int command[] = { qwaq_cmd_resizeterm, 0, width, height }; @@ -1147,7 +1052,7 @@ bi_resizeterm (progs_t *pr) static void qwaq_mvwhline (progs_t *pr, int window_id, int x, int y, int ch, int n) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { @@ -1174,7 +1079,7 @@ bi_mvwhline (progs_t *pr) static void qwaq_mvwvline (progs_t *pr, int window_id, int x, int y, int ch, int n) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { @@ -1201,7 +1106,7 @@ bi_mvwvline (progs_t *pr) static void qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int string_id = qwaq_pipe_acquire_string (&res->commands); @@ -1232,7 +1137,7 @@ static void qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, int count, pr_type_t **args) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int string_id = qwaq_pipe_acquire_string (&res->commands); @@ -1267,7 +1172,7 @@ static void qwaq_wprintf (progs_t *pr, int window_id, const char *fmt, int count, pr_type_t **args) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int string_id = qwaq_pipe_acquire_string (&res->commands); @@ -1299,7 +1204,7 @@ bi_wprintf (progs_t *pr) static void qwaq_wvprintf (progs_t *pr, int window_id, const char *fmt, pr_va_list_t *args) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); pr_type_t *list_start = PR_GetPointer (pr, args->list); pr_type_t **list = alloca (args->count * sizeof (*list)); @@ -1336,7 +1241,7 @@ bi_wvprintf (progs_t *pr) static void qwaq_waddch (progs_t *pr, int window_id, int ch) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_waddch, 0, window_id, ch }; @@ -1358,7 +1263,7 @@ static void qwaq_mvwvprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, pr_va_list_t *args) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); pr_type_t *list_start = PR_GetPointer (pr, args->list); pr_type_t **list = alloca (args->count * sizeof (*list)); @@ -1397,7 +1302,7 @@ bi_mvwvprintf (progs_t *pr) static void qwaq_mvwaddch (progs_t *pr, int window_id, int x, int y, int ch) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { @@ -1422,7 +1327,7 @@ bi_mvwaddch (progs_t *pr) static void qwaq_wrefresh (progs_t *pr, int window_id) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wrefresh, 0, window_id, }; @@ -1438,15 +1343,6 @@ bi_wrefresh (progs_t *pr) qwaq_wrefresh (pr, window_id); } -static void -bi_get_event (progs_t *pr) -{ - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - qwaq_event_t *event = &P_STRUCT (pr, qwaq_event_t, 0); - - R_INT (pr) = get_event (res, event); -} - static void bi_max_colors (progs_t *pr) { @@ -1462,7 +1358,7 @@ bi_max_color_pairs (progs_t *pr) static void qwaq_init_pair (progs_t *pr, int pair, int f, int b) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int command[] = { qwaq_cmd_init_pair, 0, pair, f, b, }; command[1] = CMD_SIZE(command); @@ -1481,7 +1377,7 @@ bi_init_pair (progs_t *pr) static void qwaq_wbkgd (progs_t *pr, int window_id, int ch) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wbkgd, 0, window_id, ch, }; @@ -1501,7 +1397,7 @@ bi_wbkgd (progs_t *pr) static void qwaq_werase (progs_t *pr, int window_id, int ch) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_werase, 0, window_id, }; @@ -1521,7 +1417,7 @@ bi_werase (progs_t *pr) static void qwaq_scrollok (progs_t *pr, int window_id, int flag) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_scrollok, 0, window_id, flag, }; @@ -1541,7 +1437,7 @@ bi_scrollok (progs_t *pr) static void qwaq_wmove (progs_t *pr, int window_id, int x, int y) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wmove, 0, window_id, x, y, }; @@ -1582,7 +1478,7 @@ bi_acs_char (progs_t *pr) static void qwaq_move (progs_t *pr, int x, int y) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int command[] = { qwaq_cmd_move, 0, x, y, }; command[1] = CMD_SIZE(command); @@ -1600,7 +1496,7 @@ bi_move (progs_t *pr) static void qwaq_curs_set (progs_t *pr, int visibility) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int command[] = { qwaq_cmd_curs_set, 0, visibility, }; command[1] = CMD_SIZE(command); @@ -1618,7 +1514,7 @@ static void qwaq_wborder (progs_t *pr, int window_id, box_sides_t sides, box_corners_t corns) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wborder, 0, window_id, @@ -1642,7 +1538,7 @@ static void qwaq__mvwblit_line (progs_t *pr, int window_id, int x, int y, int *chs, int len) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); if (get_window (res, __FUNCTION__, window_id)) { int chs_id = qwaq_pipe_acquire_string (&res->commands); @@ -1670,84 +1566,6 @@ bi_mvwblit_line (progs_t *pr) qwaq__mvwblit_line (pr, window_id, x, y, chs, len); } -static void -qwaq_send_connected_devices (progs_t *pr) -{ - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - - int command[] = { - qwaq_cmd_send_connected_devices, 0, - }; - - command[1] = CMD_SIZE(command); - qwaq_pipe_submit (&res->commands, command, command[1]); -} -static void -bi_send_connected_devices (progs_t *pr) -{ - qwaq_send_connected_devices (pr); -} - -static void -qwaq_get_device_info (progs_t *pr, int devid, int *name_id, int *id_id, - int *axis_id, int *button_id) -{ - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - - Sys_Printf ("qwaq_get_device_info: %d\n", devid); - int command[] = { - qwaq_cmd_get_device_info, 0, - devid, - }; - - command[1] = CMD_SIZE(command); - qwaq_pipe_submit (&res->commands, command, command[1]); - - int cmd_result[5]; - qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_get_device_info, - CMD_SIZE (cmd_result)); - *name_id = cmd_result[1]; - *id_id = cmd_result[2]; - *axis_id = cmd_result[3]; - *button_id = cmd_result[4]; -} -static void -bi_get_device_info (progs_t *pr) -{ - int devid = P_INT (pr, 0); - int name_id, id_id, axis_id, button_id; - - qwaq_get_device_info (pr, devid, &name_id, &id_id, &axis_id, - &button_id); - - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); - dstring_t *name_string = qwaq_res_string (res, name_id); - dstring_t *id_string = qwaq_res_string (res, id_id); - dstring_t *axis_buffer = qwaq_res_string (res, axis_id); - dstring_t *button_buffer = qwaq_res_string (res, button_id); - - qwaq_devinfo_t *devinfo = PR_Zone_Malloc (pr, sizeof (qwaq_devinfo_t)); - in_axisinfo_t *axes = PR_Zone_Malloc (pr, axis_buffer->size); - in_buttoninfo_t *buttons = PR_Zone_Malloc (pr, button_buffer->size); - - memcpy (axes, axis_buffer->str, axis_buffer->size); - memcpy (buttons, button_buffer->str, button_buffer->size); - - devinfo->name = PR_SetDynamicString (pr, name_string->str); - devinfo->id = PR_SetDynamicString (pr, id_string->str); - devinfo->numaxes = axis_buffer->size / sizeof (in_axisinfo_t); - devinfo->axes = PR_SetPointer (pr, axes); - devinfo->numbuttons = button_buffer->size / sizeof (in_buttoninfo_t); - devinfo->buttons = PR_SetPointer (pr, buttons); - - qwaq_pipe_release_string (&res->results, name_id); - qwaq_pipe_release_string (&res->results, id_id); - qwaq_pipe_release_string (&res->results, axis_id); - qwaq_pipe_release_string (&res->results, button_id); - - RETURN_POINTER (pr, devinfo); -} - static void * qwaq_curses_thread (qwaq_thread_t *thread) { @@ -1755,7 +1573,6 @@ qwaq_curses_thread (qwaq_thread_t *thread) while (1) { process_commands (res); - qwaq_process_input (res); } thread->return_code = 0; return thread; @@ -1764,7 +1581,7 @@ qwaq_curses_thread (qwaq_thread_t *thread) static void bi_initialize (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); initscr (); need_endwin = 1; @@ -1776,7 +1593,6 @@ bi_initialize (progs_t *pr) nonl (); nodelay (stdscr, TRUE); mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); - qwaq_input_init (res); refresh(); res->stdscr.win = stdscr; @@ -1787,7 +1603,7 @@ bi_initialize (progs_t *pr) static void bi_c_TextContext__is_initialized (progs_t *pr) { - qwaq_resources_t *res = PR_Resources_Find (pr, "qwaq"); + qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); R_INT (pr) = res->initialized; } @@ -2022,12 +1838,11 @@ bi_i_TextContext__mvvline_ (progs_t *pr) } static void -bi_qwaq_clear (progs_t *pr, void *data) +bi_curses_clear (progs_t *pr, void *data) { __auto_type res = (qwaq_resources_t *) data; if (res->initialized) { - qwaq_input_shutdown (res); endwin (); } need_endwin = 0; @@ -2061,7 +1876,6 @@ static builtin_t builtins[] = { {"mvwaddstr", bi_mvwaddstr, -1}, {"waddstr", bi_waddstr, -1}, {"wrefresh", bi_wrefresh, -1}, - {"get_event", bi_get_event, -1}, {"max_colors", bi_max_colors, -1}, {"max_color_pairs", bi_max_color_pairs, -1}, {"init_pair", bi_init_pair, -1}, @@ -2079,9 +1893,6 @@ static builtin_t builtins[] = { {"mvwhline", bi_mvwhline, -1}, {"mvwvline", bi_mvwvline, -1}, - {"send_connected_devices", bi_send_connected_devices, -1}, - {"get_device_info", bi_get_device_info, -1}, - {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, {"_c_TextContext__max_color_pairs", bi_c_TextContext__max_color_pairs, -1}, @@ -2112,7 +1923,7 @@ static builtin_t builtins[] = { }; void -BI_Init (progs_t *pr) +BI_Curses_Init (progs_t *pr) { qwaq_resources_t *res = calloc (sizeof (*res), 1); res->pr = pr; @@ -2120,15 +1931,7 @@ BI_Init (progs_t *pr) qwaq_init_pipe (&res->commands); qwaq_init_pipe (&res->results); - res->escbuff.mem = &dstring_default_mem; - // ensure the backing buffer exists - dstring_clearstr (&res->escbuff); - - res->input_event_handler = -1; - - qwaq_init_cond (&res->events.cond); - - PR_Resources_Register (pr, "qwaq", res, bi_qwaq_clear); + PR_Resources_Register (pr, "curses", res, bi_curses_clear); PR_RegisterBuiltins (pr, builtins); Sys_RegisterShutdown (bi_shutdown, pr); } diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 5d6c598ed..929ccc9a5 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -62,7 +62,7 @@ typedef struct qwaq_target_s { typedef struct qwaq_debug_s { progs_t *pr; - qwaq_resources_t *qwaq; // to communicate with the debugger thread + qwaq_input_resources_t *input; // to communicate with the debugger thread PR_RESMAP (qwaq_target_t) targets; } qwaq_debug_t; @@ -122,7 +122,7 @@ qwaq_debug_handler (prdebug_t debug_event, void *param, void *data) event.what = qe_debug_event; event.message.pointer_val = target->handle; - while ((ret = qwaq_add_event (debug->qwaq, &event)) == ETIMEDOUT) { + while ((ret = qwaq_add_event (debug->input, &event)) == ETIMEDOUT) { // spin } if (ret == EINVAL) { @@ -665,7 +665,7 @@ QWAQ_Debug_Init (progs_t *pr) qwaq_debug_t *debug = calloc (sizeof (*debug), 1); debug->pr = pr; - debug->qwaq = PR_Resources_Find (pr, "qwaq"); + debug->input = PR_Resources_Find (pr, "input"); PR_AddLoadFunc (pr, qwaq_debug_load); PR_Resources_Register (pr, "qwaq-debug", debug, qwaq_debug_clear); diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index bcfc11a83..2551c0ee1 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -52,8 +52,8 @@ #include "QF/sys.h" #include "ruamoko/qwaq/qwaq.h" +#include "ruamoko/qwaq/qwaq-input.h" #include "ruamoko/qwaq/ui/event.h" -#include "ruamoko/qwaq/ui/curses.h" #define always_inline inline __attribute__((__always_inline__)) @@ -63,6 +63,16 @@ #define SGR_OFF "\033[?1006l" #define WHEEL_BUTTONS 0x78 // scroll up/down/left/right - always click +typedef enum qwaq_input_commands_e { + qwaq_cmd_send_connected_devices, + qwaq_cmd_get_device_info, +} qwaq_input_commands; + +static const char *qwaq_input_command_names[]= { + "send_connected_devices", + "get_device_info", +}; + typedef struct qwaq_key_s { const char *sequence; knum_t key; @@ -169,6 +179,26 @@ static qwaq_key_t default_keys[] = { { "\033[1;6D", QFK_LEFT, 5 }, }; +#define CMD_SIZE(x) sizeof(x)/sizeof(x[0]) + +static int +qwaq_cmd_peek (qwaq_input_resources_t *res, int ahead) +{ + return *RB_PEEK_DATA (res->commands.pipe, ahead); +} +#if 0 +static dstring_t * +qwaq_cmd_string (qwaq_input_resources_t *res, int string_id) +{ + return res->commands.strings + string_id; +} +#endif +static dstring_t * +qwaq_res_string (qwaq_input_resources_t *res, int string_id) +{ + return res->results.strings + string_id; +} + #ifdef HAVE_SIGACTION static struct sigaction save_winch; static sigset_t winch_mask; @@ -182,7 +212,7 @@ handle_winch (int sig) #endif int -qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event) +qwaq_add_event (qwaq_input_resources_t *res, qwaq_event_t *event) { struct timespec timeout; int merged = 0; @@ -216,7 +246,7 @@ qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event) #ifdef HAVE_SIGACTION static void -resize_event (qwaq_resources_t *res) +resize_event (qwaq_input_resources_t *res) { qwaq_event_t event = {}; struct winsize size; @@ -231,7 +261,7 @@ resize_event (qwaq_resources_t *res) #endif static void -key_event (qwaq_resources_t *res, int key, unsigned shift) +key_event (qwaq_input_resources_t *res, int key, unsigned shift) { qwaq_event_t event = {}; event.what = qe_keydown; @@ -242,7 +272,7 @@ key_event (qwaq_resources_t *res, int key, unsigned shift) } static void -mouse_event (qwaq_resources_t *res, int what, int x, int y) +mouse_event (qwaq_input_resources_t *res, int what, int x, int y) { qwaq_event_t event = {}; @@ -268,7 +298,7 @@ mouse_event (qwaq_resources_t *res, int what, int x, int y) } static void -parse_mouse (qwaq_resources_t *res, unsigned ctrl, int x, int y, int cmd) +parse_mouse (qwaq_input_resources_t *res, unsigned ctrl, int x, int y, int cmd) { int button = ctrl & 3; int ext = (ctrl >> 6); @@ -308,7 +338,7 @@ parse_mouse (qwaq_resources_t *res, unsigned ctrl, int x, int y, int cmd) } static void -parse_x10 (qwaq_resources_t *res) +parse_x10 (qwaq_input_resources_t *res) { int x = (byte) res->escbuff.str[1] - '!'; // want 0-based int y = (byte) res->escbuff.str[2] - '!'; // want 0-based @@ -318,7 +348,7 @@ parse_x10 (qwaq_resources_t *res) } static void -parse_sgr (qwaq_resources_t *res, char cmd) +parse_sgr (qwaq_input_resources_t *res, char cmd) { unsigned ctrl, x, y; @@ -328,7 +358,7 @@ parse_sgr (qwaq_resources_t *res, char cmd) } static void -parse_key (qwaq_resources_t *res) +parse_key (qwaq_input_resources_t *res) { qwaq_key_t *key = Hash_Find (res->key_sequences, res->escbuff.str); @@ -340,7 +370,7 @@ parse_key (qwaq_resources_t *res) } } -static void process_char (qwaq_resources_t *res, char ch) +static void process_char (qwaq_input_resources_t *res, char ch) { if (ch == 0x1b) { // always reset if escape is seen, may be a desync @@ -437,7 +467,7 @@ term_shutdown (void *_res) static void term_process_events (void *_res) { - qwaq_resources_t *res = _res; + qwaq_input_resources_t *res = _res; char buf[256]; int len; #ifdef HAVE_SIGACTION @@ -476,7 +506,7 @@ term_register_driver (void) static int qwaq_input_event_handler (const IE_event_t *ie_event, void *_res) { - qwaq_resources_t *res = _res; + qwaq_input_resources_t *res = _res; qwaq_event_t event = {}; event.when = ie_event->when * 1e-6 + Sys_DoubleTimeBase (); @@ -515,8 +545,8 @@ qwaq_input_event_handler (const IE_event_t *ie_event, void *_res) return 1; } -void -qwaq_input_init (qwaq_resources_t *res) +static void +qwaq_input_init (qwaq_input_resources_t *res) { res->input_event_handler = IE_Add_Handler (qwaq_input_event_handler, res); IN_DriverData (term_driver_handle, res); @@ -546,14 +576,14 @@ qwaq_input_init (qwaq_resources_t *res) (void) !write(1, SGR_ON, sizeof (SGR_ON) - 1); } -void -qwaq_process_input (qwaq_resources_t *res) +static void +qwaq_process_input (qwaq_input_resources_t *res) { IN_ProcessEvents (); } -void -qwaq_input_shutdown (qwaq_resources_t *res) +static void +qwaq_input_shutdown (qwaq_input_resources_t *res) { IE_Remove_Handler (res->input_event_handler); IN_DriverData (term_driver_handle, 0); @@ -567,3 +597,274 @@ qwaq_input_shutdown (qwaq_resources_t *res) sigaction (SIGWINCH, &save_winch, 0); #endif } + +static void +bi_send_connected_devices (progs_t *pr) +{ + qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); + + int command[] = { + qwaq_cmd_send_connected_devices, 0, + }; + + command[1] = CMD_SIZE(command); + qwaq_pipe_submit (&res->commands, command, command[1]); +} + +static void +bi_get_device_info (progs_t *pr) +{ + qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); + int devid = P_INT (pr, 0); + + Sys_Printf ("qwaq_get_device_info: %d\n", devid); + int command[] = { + qwaq_cmd_get_device_info, 0, + devid, + }; + + command[1] = CMD_SIZE(command); + qwaq_pipe_submit (&res->commands, command, command[1]); + + int cmd_result[5]; + qwaq_pipe_receive (&res->results, cmd_result, qwaq_cmd_get_device_info, + CMD_SIZE (cmd_result)); + int name_id = cmd_result[1]; + int id_id = cmd_result[2]; + int axis_id = cmd_result[3]; + int button_id = cmd_result[4]; + + dstring_t *name_string = qwaq_res_string (res, name_id); + dstring_t *id_string = qwaq_res_string (res, id_id); + dstring_t *axis_buffer = qwaq_res_string (res, axis_id); + dstring_t *button_buffer = qwaq_res_string (res, button_id); + + qwaq_devinfo_t *devinfo = PR_Zone_Malloc (pr, sizeof (qwaq_devinfo_t)); + in_axisinfo_t *axes = PR_Zone_Malloc (pr, axis_buffer->size); + in_buttoninfo_t *buttons = PR_Zone_Malloc (pr, button_buffer->size); + + memcpy (axes, axis_buffer->str, axis_buffer->size); + memcpy (buttons, button_buffer->str, button_buffer->size); + + devinfo->name = PR_SetDynamicString (pr, name_string->str); + devinfo->id = PR_SetDynamicString (pr, id_string->str); + devinfo->numaxes = axis_buffer->size / sizeof (in_axisinfo_t); + devinfo->axes = PR_SetPointer (pr, axes); + devinfo->numbuttons = button_buffer->size / sizeof (in_buttoninfo_t); + devinfo->buttons = PR_SetPointer (pr, buttons); + + qwaq_pipe_release_string (&res->results, name_id); + qwaq_pipe_release_string (&res->results, id_id); + qwaq_pipe_release_string (&res->results, axis_id); + qwaq_pipe_release_string (&res->results, button_id); + + RETURN_POINTER (pr, devinfo); +} + +static int +get_event (qwaq_input_resources_t *res, qwaq_event_t *event) +{ + struct timespec timeout; + int ret = 0; + int was_event = 0; + + pthread_mutex_lock (&res->events.cond.mut); + qwaq_init_timeout (&timeout, 20 * 1000000); + while (RB_DATA_AVAILABLE (res->events.queue) < 1 && ret == 0) { + ret = pthread_cond_timedwait (&res->events.cond.rcond, + &res->events.cond.mut, &timeout); + } + if (event) { + if (ret == 0) { + RB_READ_DATA (res->events.queue, event, 1); + was_event = 1; + } else if (res->button_state) { + event->what = qe_mouseauto; + event->when = Sys_DoubleTime (); + event->mouse.buttons = res->button_state; + event->mouse.x = res->mouse_x; + event->mouse.y = res->mouse_y; + } else { + event->what = qe_none; + } + } + pthread_cond_broadcast (&res->events.cond.wcond); + pthread_mutex_unlock (&res->events.cond.mut); + return was_event; +} + +static void +bi_get_event (progs_t *pr) +{ + qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); + qwaq_event_t *event = &P_STRUCT (pr, qwaq_event_t, 0); + + R_INT (pr) = get_event (res, event); +} + +static void +cmd_send_connected_devices (qwaq_input_resources_t *res) +{ + IN_SendConnectedDevices (); +} + +static void +cmd_get_device_info (qwaq_input_resources_t *res) +{ + int devid = qwaq_cmd_peek (res, 2); + int name_id = qwaq_pipe_acquire_string (&res->results); + int id_id = qwaq_pipe_acquire_string (&res->results); + int axis_id = qwaq_pipe_acquire_string (&res->results); + int button_id = qwaq_pipe_acquire_string (&res->results); + + dstring_t *name_string = qwaq_res_string (res, name_id); + dstring_t *id_string = qwaq_res_string (res, id_id); + dstring_t *axis_buffer = qwaq_res_string (res, axis_id); + dstring_t *button_buffer = qwaq_res_string (res, button_id); + + dstring_copystr (name_string, IN_GetDeviceName (devid)); + dstring_copystr (id_string, IN_GetDeviceId (devid)); + + int num; + IN_AxisInfo (devid, 0, &num); + axis_buffer->size = num * sizeof (in_axisinfo_t); + dstring_adjust (axis_buffer); + IN_AxisInfo (devid, (in_axisinfo_t *) axis_buffer->str, &num); + + IN_ButtonInfo (devid, 0, &num); + button_buffer->size = num * sizeof (in_buttoninfo_t); + dstring_adjust (button_buffer); + IN_ButtonInfo (devid, (in_buttoninfo_t *) button_buffer->str, &num); + + int cmd_result[] = { + qwaq_cmd_get_device_info, + name_id, id_id, axis_id, button_id + }; + qwaq_pipe_submit (&res->results, cmd_result, CMD_SIZE (cmd_result)); +} + +static void +dump_command (qwaq_input_resources_t *res, int len) +{ + if (1) { + qwaq_input_commands cmd = qwaq_cmd_peek (res, 0); + Sys_Printf ("%s[%d]", qwaq_input_command_names[cmd], len); + for (int i = 2; i < len; i++) { + Sys_Printf (" %d", qwaq_cmd_peek (res, i)); + } + Sys_Printf ("\n"); + } +} + +static void +process_commands (qwaq_input_resources_t *res) +{ + struct timespec timeout; + int avail; + int len; + int ret = 0; + + pthread_mutex_lock (&res->commands.pipe_cond.mut); + qwaq_init_timeout (&timeout, 20 * 1000000); + while (RB_DATA_AVAILABLE (res->commands.pipe) < 2 && ret == 0) { + ret = pthread_cond_timedwait (&res->commands.pipe_cond.rcond, + &res->commands.pipe_cond.mut, &timeout); + } + // The mutex is unlocked at the top of the loop and locked again + // (for broadcast) at the bottom, then finally unlocked after the loop. + // It should be only the data availability check that's not threadsafe + // as the mutex is not released until after the data has been written to + // the buffer. + while ((avail = RB_DATA_AVAILABLE (res->commands.pipe)) >= 2 + && avail >= (len = qwaq_cmd_peek (res, 1))) { + pthread_mutex_unlock (&res->commands.pipe_cond.mut); + dump_command (res, len); + qwaq_input_commands cmd = qwaq_cmd_peek (res, 0); + switch (cmd) { + case qwaq_cmd_send_connected_devices: + cmd_send_connected_devices (res); + break; + case qwaq_cmd_get_device_info: + cmd_get_device_info (res); + break; + } + pthread_mutex_lock (&res->commands.pipe_cond.mut); + RB_RELEASE (res->commands.pipe, len); + pthread_cond_broadcast (&res->commands.pipe_cond.wcond); + // unlocked at top of top if there's more data, otherwise just after + // the loop + } + pthread_mutex_unlock (&res->commands.pipe_cond.mut); +} + +static void * +qwaq_input_thread (qwaq_thread_t *thread) +{ + qwaq_input_resources_t *res = thread->data; + + while (1) { + qwaq_process_input (res); + process_commands (res); + } + thread->return_code = 0; + return thread; +} + +static void +bi_init_input (progs_t *pr) +{ + qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); + qwaq_input_init (res); + res->initialized = 1; + create_thread (qwaq_input_thread, res); +} + +static builtin_t builtins[] = { + {"send_connected_devices", bi_send_connected_devices, -1}, + {"get_device_info", bi_get_device_info, -1}, + {"get_event", bi_get_event, -1}, + {"init_input", bi_init_input, -1}, + + {0} +}; + +static void +bi_input_clear (progs_t *pr, void *data) +{ + __auto_type res = (qwaq_input_resources_t *) data; + + if (res->initialized) { + qwaq_input_shutdown (res); + } +} + +static void +bi_input_shutdown (void *_pr) +{ + __auto_type pr = (progs_t *) _pr; + qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); + + qwaq_input_shutdown (res); +} + +void +BI_Input_Init (progs_t *pr) +{ + qwaq_input_resources_t *res = calloc (sizeof (*res), 1); + res->pr = pr; + + qwaq_init_pipe (&res->commands); + qwaq_init_pipe (&res->results); + + res->escbuff.mem = &dstring_default_mem; + // ensure the backing buffer exists + dstring_clearstr (&res->escbuff); + + res->input_event_handler = -1; + + qwaq_init_cond (&res->events.cond); + + PR_Resources_Register (pr, "input", res, bi_input_clear); + PR_RegisterBuiltins (pr, builtins); + Sys_RegisterShutdown (bi_input_shutdown, pr); +} diff --git a/ruamoko/qwaq/builtins/qwaq-curses.c b/ruamoko/qwaq/builtins/qwaq-curses.c index a5695babc..4f80e4683 100644 --- a/ruamoko/qwaq/builtins/qwaq-curses.c +++ b/ruamoko/qwaq/builtins/qwaq-curses.c @@ -59,7 +59,8 @@ #include "ruamoko/qwaq/debugger/debug.h" static progsinit_f main_app[] = { - BI_Init, + BI_Curses_Init, + BI_Input_Init, QWAQ_EditBuffer_Init, QWAQ_Debug_Init, 0 diff --git a/ruamoko/qwaq/input-app.r b/ruamoko/qwaq/input-app.r index 8b7b5d34d..0357d17f4 100644 --- a/ruamoko/qwaq/input-app.r +++ b/ruamoko/qwaq/input-app.r @@ -43,6 +43,7 @@ arp_end (void) } initialize (); + init_input (); for (int i = 1; i < 64; i++) { init_pair (i, i & 0x7, i >> 3); color_palette[i] = COLOR_PAIR (i); diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index ac00b32a1..e1d49a31c 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -9,6 +9,9 @@ int fence; #include "ruamoko/qwaq/ui/view.h" #include "ruamoko/qwaq/debugger/debugger.h" #include "ruamoko/qwaq/qwaq-app.h" +#include "ruamoko/qwaq/qwaq-input.h" + +void init_input (void) = #0;//FIXME int color_palette[64]; @@ -39,6 +42,7 @@ arp_end (void) } initialize (); + init_input (); for (int i = 1; i < 64; i++) { init_pair (i, i & 0x7, i >> 3); color_palette[i] = COLOR_PAIR (i); diff --git a/ruamoko/qwaq/qwaq-input.h b/ruamoko/qwaq/qwaq-input.h index 47474f077..f385917e5 100644 --- a/ruamoko/qwaq/qwaq-input.h +++ b/ruamoko/qwaq/qwaq-input.h @@ -44,6 +44,7 @@ typedef struct qwaq_devinfo_s { } @end +void init_input (void); void send_connected_devices (void); qwaq_devinfo_t *get_device_info (int devid); diff --git a/ruamoko/qwaq/qwaq-input.r b/ruamoko/qwaq/qwaq-input.r index effac892e..abea04cf5 100644 --- a/ruamoko/qwaq/qwaq-input.r +++ b/ruamoko/qwaq/qwaq-input.r @@ -1,4 +1,5 @@ #include "ruamoko/qwaq/qwaq-input.h" +void init_input (void) = #0; void send_connected_devices (void) = #0; qwaq_devinfo_t *get_device_info (int devid) = #0; diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 8ef009e8c..899fb1c51 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -24,6 +24,8 @@ typedef struct qwaq_thread_s { typedef struct qwaq_thread_set_s DARRAY_TYPE(qwaq_thread_t *) qwaq_thread_set_t; void BI_Init (progs_t *pr); +void BI_Curses_Init (progs_t *pr); +void BI_Input_Init (progs_t *pr); void QWAQ_EditBuffer_Init (progs_t *pr); extern struct cbuf_s *qwaq_cbuf; qwaq_thread_t *create_thread (void *(*thread_func) (qwaq_thread_t *), void *); diff --git a/ruamoko/qwaq/ui/curses.h b/ruamoko/qwaq/ui/curses.h index 5ba402701..4268915a1 100644 --- a/ruamoko/qwaq/ui/curses.h +++ b/ruamoko/qwaq/ui/curses.h @@ -160,20 +160,6 @@ typedef struct panel_s { int window_id; } panel_t; -typedef enum { - esc_ground, - esc_escape, - esc_csi, - esc_mouse, - esc_sgr, - esc_key, -} esc_state_t; - -typedef struct qwaq_event_queue_s { - rwcond_t cond; - RING_BUFFER (qwaq_event_t, QUEUE_SIZE) queue; -} qwaq_event_queue_t; - typedef struct qwaq_resources_s { progs_t *pr; int initialized; @@ -181,27 +167,10 @@ typedef struct qwaq_resources_s { PR_RESMAP (window_t) window_map; PR_RESMAP (panel_t) panel_map; - qwaq_event_queue_t events; - qwaq_pipe_t commands; qwaq_pipe_t results; - - dstring_t escbuff; - esc_state_t escstate; - unsigned button_state; - int mouse_x; - int mouse_y; - qwaq_event_t lastClick; - struct hashtab_s *key_sequences; - - int input_event_handler; } qwaq_resources_t; // gcc stuff - -void qwaq_input_init (qwaq_resources_t *res); -void qwaq_input_shutdown (qwaq_resources_t *res); -void qwaq_process_input (qwaq_resources_t *res); -int qwaq_add_event (qwaq_resources_t *res, qwaq_event_t *event); #endif #endif//__qwaq_ui_curses_h diff --git a/ruamoko/qwaq/ui/event.h b/ruamoko/qwaq/ui/event.h index 6de52297b..075cd055d 100644 --- a/ruamoko/qwaq/ui/event.h +++ b/ruamoko/qwaq/ui/event.h @@ -1,6 +1,8 @@ #ifndef __qwaq_ui_event_h #define __qwaq_ui_event_h +#include "ruamoko/qwaq/threading.h" + typedef enum { qe_mousedown = 0x0001, qe_mouseup = 0x0002, @@ -89,4 +91,43 @@ typedef struct qwaq_event_s { }; } qwaq_event_t; +#ifndef __QFCC__ +typedef struct qwaq_event_queue_s { + rwcond_t cond; + RING_BUFFER (qwaq_event_t, QUEUE_SIZE) queue; +} qwaq_event_queue_t; + +typedef enum { + esc_ground, + esc_escape, + esc_csi, + esc_mouse, + esc_sgr, + esc_key, +} esc_state_t; + +typedef struct qwaq_input_resources_s { + progs_t *pr; + int initialized; + + qwaq_event_queue_t events; + + qwaq_pipe_t commands; + qwaq_pipe_t results; + + dstring_t escbuff; + esc_state_t escstate; + unsigned button_state; + int mouse_x; + int mouse_y; + qwaq_event_t lastClick; + struct hashtab_s *key_sequences; + + int input_event_handler; +} qwaq_input_resources_t; + +int qwaq_add_event (qwaq_input_resources_t *res, qwaq_event_t *event); + +#endif + #endif//__qwaq_ui_event_h From 6f71ef665741a1d148fb236cef69bc9399010638 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Sep 2021 13:14:42 +0900 Subject: [PATCH 1747/3664] [qwaq] Separate out mouse (de)init code This is the simplest fix for the curses/input initialization order issue. The terminal io code should still be moved to its own file, really, but I think it can wait. --- ruamoko/qwaq/builtins/curses.c | 3 +++ ruamoko/qwaq/builtins/input.c | 18 +++++++++++++----- ruamoko/qwaq/input-app.r | 2 +- ruamoko/qwaq/qwaq-app.r | 2 +- ruamoko/qwaq/ui/event.h | 2 ++ 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index defb45cbb..f46bdc81c 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -1595,6 +1595,8 @@ bi_initialize (progs_t *pr) mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); refresh(); + qwaq_input_enable_mouse (); + res->stdscr.win = stdscr; create_thread (qwaq_curses_thread, res); @@ -1843,6 +1845,7 @@ bi_curses_clear (progs_t *pr, void *data) __auto_type res = (qwaq_resources_t *) data; if (res->initialized) { + qwaq_input_disable_mouse (); endwin (); } need_endwin = 0; diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 2551c0ee1..04fdcd406 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -569,13 +569,26 @@ qwaq_input_init (qwaq_input_resources_t *res) action.sa_handler = handle_winch; sigaction (SIGWINCH, &action, &save_winch); #endif +} +void +qwaq_input_enable_mouse (void) +{ // ncurses takes care of input mode for us, so need only tell xterm // what we need (void) !write(1, MOUSE_MOVES_ON, sizeof (MOUSE_MOVES_ON) - 1); (void) !write(1, SGR_ON, sizeof (SGR_ON) - 1); } +void +qwaq_input_disable_mouse (void) +{ + // ncurses takes care of input mode for us, so need only tell xterm + // what we need + (void) !write(1, SGR_OFF, sizeof (SGR_OFF) - 1); + (void) !write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); +} + static void qwaq_process_input (qwaq_input_resources_t *res) { @@ -588,11 +601,6 @@ qwaq_input_shutdown (qwaq_input_resources_t *res) IE_Remove_Handler (res->input_event_handler); IN_DriverData (term_driver_handle, 0); - // ncurses takes care of input mode for us, so need only tell xterm - // what we need - (void) !write(1, SGR_OFF, sizeof (SGR_OFF) - 1); - (void) !write(1, MOUSE_MOVES_OFF, sizeof (MOUSE_MOVES_OFF) - 1); - #ifdef HAVE_SIGACTION sigaction (SIGWINCH, &save_winch, 0); #endif diff --git a/ruamoko/qwaq/input-app.r b/ruamoko/qwaq/input-app.r index 0357d17f4..fe8243ee4 100644 --- a/ruamoko/qwaq/input-app.r +++ b/ruamoko/qwaq/input-app.r @@ -42,8 +42,8 @@ arp_end (void) return nil; } - initialize (); init_input (); + initialize (); for (int i = 1; i < 64; i++) { init_pair (i, i & 0x7, i >> 3); color_palette[i] = COLOR_PAIR (i); diff --git a/ruamoko/qwaq/qwaq-app.r b/ruamoko/qwaq/qwaq-app.r index e1d49a31c..bf3876687 100644 --- a/ruamoko/qwaq/qwaq-app.r +++ b/ruamoko/qwaq/qwaq-app.r @@ -41,8 +41,8 @@ arp_end (void) return nil; } - initialize (); init_input (); + initialize (); for (int i = 1; i < 64; i++) { init_pair (i, i & 0x7, i >> 3); color_palette[i] = COLOR_PAIR (i); diff --git a/ruamoko/qwaq/ui/event.h b/ruamoko/qwaq/ui/event.h index 075cd055d..8a9f3c608 100644 --- a/ruamoko/qwaq/ui/event.h +++ b/ruamoko/qwaq/ui/event.h @@ -127,6 +127,8 @@ typedef struct qwaq_input_resources_s { } qwaq_input_resources_t; int qwaq_add_event (qwaq_input_resources_t *res, qwaq_event_t *event); +void qwaq_input_enable_mouse (void); +void qwaq_input_disable_mouse (void); #endif From 6144100d9b805d3e0547aa2d836867fc057619ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 24 Sep 2021 19:44:14 +0900 Subject: [PATCH 1748/3664] [qfcc] Check init exists before checking compound Fixes a segfault that occurred during a parse error in a def initializer. --- tools/qfcc/source/def.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 700c5033b..37a06c84e 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -559,7 +559,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, } if (!sym->s.def) { if (is_array (sym->type) && !type_size (sym->type) - && init->type == ex_compound) { + && init && init->type == ex_compound) { sym->type = array_type (sym->type->t.array.type, num_elements (init)); } From 7ed12e2f372b0b3b49034b9130f13b0a52e13c32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 24 Sep 2021 19:49:55 +0900 Subject: [PATCH 1749/3664] [qfcc] Fix static function declarations I'm surprised it took this long for static not working to cause a problem. --- tools/qfcc/include/function.h | 6 ++++-- tools/qfcc/source/class.c | 7 +------ tools/qfcc/source/function.c | 9 +++++---- tools/qfcc/source/qc-parse.y | 15 +++++++++------ tools/qfcc/source/qp-parse.y | 11 +++++++---- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 3ae7c845f..355edea37 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -137,12 +137,14 @@ struct expr_s *find_function (struct expr_s *fexpr, struct expr_s *params); function_t *new_function (const char *name, const char *nice_name); void add_function (function_t *f); function_t *begin_function (struct symbol_s *sym, const char *nicename, - struct symtab_s *parent, int far); + struct symtab_s *parent, int far, + enum storage_class_e storage); function_t *build_code_function (struct symbol_s *fsym, struct expr_s *state_expr, struct expr_s *statements); function_t *build_builtin_function (struct symbol_s *sym, - struct expr_s *bi_val, int far); + struct expr_s *bi_val, int far, + enum storage_class_e storage); void finish_function (function_t *f); void emit_function (function_t *f, struct expr_s *e); int function_parms (function_t *f, byte *parm_size); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index b61be1d26..dfaf638c8 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1507,7 +1507,6 @@ class_finish_module (void) symbol_t *exec_class_sym; symbol_t *init_sym; expr_t *init_expr; - storage_class_t save_storage; data.refs = emit_selectors (); if (class_hash) { @@ -1563,12 +1562,8 @@ class_finish_module (void) build_function_call (new_symbol_expr (exec_class_sym), exec_class_sym->type, module_expr)); - save_storage = current_storage; - current_storage = sc_static; - current_func = begin_function (init_sym, 0, current_symtab, 1); + current_func = begin_function (init_sym, 0, current_symtab, 1, sc_static); build_code_function (init_sym, 0, init_expr); - current_func = 0; - current_storage = save_storage; } protocol_t * diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 4e7ef61f3..e448990b2 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -584,7 +584,7 @@ add_function (function_t *f) function_t * begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, - int far) + int far, storage_class_t storage) { defspace_t *space; @@ -601,7 +601,7 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, space = sym->table->space; if (far) space = pr.far_data; - make_function (sym, nicename, space, current_storage); + make_function (sym, nicename, space, storage); if (!sym->s.func->def->external) { sym->s.func->def->initialized = 1; sym->s.func->def->constant = 1; @@ -651,7 +651,8 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) } function_t * -build_builtin_function (symbol_t *sym, expr_t *bi_val, int far) +build_builtin_function (symbol_t *sym, expr_t *bi_val, int far, + storage_class_t storage) { int bi; defspace_t *space; @@ -671,7 +672,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far) space = sym->table->space; if (far) space = pr.far_data; - make_function (sym, 0, space, current_storage); + make_function (sym, 0, space, storage); if (sym->s.func->def->external) return 0; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 32161c4b7..89a7a2405 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -423,7 +423,8 @@ function_body save_storage { $$ = current_symtab; - current_func = begin_function ($2, 0, current_symtab, 0); + current_func = begin_function ($2, 0, current_symtab, 0, + $-1.storage); current_symtab = current_func->symtab; current_storage = sc_local; } @@ -442,7 +443,7 @@ function_body $-1.type = type_default; sym->type = find_type (append_type (sym->type, $-1.type)); sym = function_symbol (sym, $-1.is_overload, 1); - build_builtin_function (sym, $3, 0); + build_builtin_function (sym, $3, 0, $-1.storage); } ; @@ -1095,7 +1096,7 @@ non_code_func if ($-1.storage == sc_extern) { error (0, "initializing external variable"); } - build_builtin_function ($0, $3, 0); + build_builtin_function ($0, $3, 0, $-1.storage); } | '=' expr { @@ -1135,7 +1136,8 @@ code_func save_storage { $$ = current_symtab; - current_func = begin_function ($0, 0, current_symtab, 0); + current_func = begin_function ($0, 0, current_symtab, 0, + $-1.storage); current_symtab = current_func->symtab; current_storage = sc_local; } @@ -1965,7 +1967,8 @@ methoddef $$ = current_symtab; ivar_scope = class_ivar_scope (current_class, current_symtab); - current_func = begin_function (sym, nicename, ivar_scope, 1); + current_func = begin_function (sym, nicename, ivar_scope, 1, + sc_static); class_finish_ivar_scope (current_class, ivar_scope, current_func->symtab); method->func = sym->s.func; @@ -1988,7 +1991,7 @@ methoddef method->instance = $1; method = class_find_method (current_class, method); sym = method_symbol (current_class, method); - build_builtin_function (sym, $5, 1); + build_builtin_function (sym, $5, 1, sc_static); method->func = sym->s.func; method->def = sym->s.func->def; } diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 15159deb0..28f54bb87 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -154,7 +154,8 @@ build_dotmain (symbol_t *program) exitcode = new_symbol_expr (symtab_lookup (current_symtab, "ExitCode")); - current_func = begin_function (dotmain, 0, current_symtab, 0); + current_func = begin_function (dotmain, 0, current_symtab, 0, + current_storage); current_symtab = current_func->symtab; code = new_block_expr (); append_expr (code, function_expr (new_symbol_expr (program), 0)); @@ -177,7 +178,8 @@ program symtab_removesymbol (current_symtab, $1); symtab_addsymbol (current_symtab, $1); - current_func = begin_function ($1, 0, current_symtab, 0); + current_func = begin_function ($1, 0, current_symtab, 0, + current_storage); current_symtab = current_func->symtab; build_code_function ($1, 0, $4); current_symtab = st; @@ -261,7 +263,8 @@ subprogram_declaration : subprogram_head ';' { $$ = current_storage; - current_func = begin_function ($1, 0, current_symtab, 0); + current_func = begin_function ($1, 0, current_symtab, 0, + current_storage); current_symtab = current_func->symtab; current_storage = sc_local; } @@ -274,7 +277,7 @@ subprogram_declaration } | subprogram_head ASSIGNOP '#' VALUE ';' { - build_builtin_function ($1, $4, 0); + build_builtin_function ($1, $4, 0, current_storage); } ; From 0a60f46a64aeaf117a023db5cb4d7dde072558e1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Sep 2021 01:42:36 +0900 Subject: [PATCH 1750/3664] [qwaq] Implement more debugger def views Structs and arrays now work (though could be better, eg collapsible). --- ruamoko/qwaq/Makemodule.am | 4 + ruamoko/qwaq/builtins/curses.c | 2 +- ruamoko/qwaq/builtins/debug.c | 19 +++- ruamoko/qwaq/builtins/input.c | 2 +- ruamoko/qwaq/builtins/threading.c | 4 +- ruamoko/qwaq/debugger/debug.h | 1 + ruamoko/qwaq/debugger/debug.r | 1 + ruamoko/qwaq/debugger/views/arrayview.h | 15 +++ ruamoko/qwaq/debugger/views/arrayview.r | 115 ++++++++++++++++++++++ ruamoko/qwaq/debugger/views/defview.h | 1 + ruamoko/qwaq/debugger/views/defview.r | 2 +- ruamoko/qwaq/debugger/views/indexview.h | 13 +++ ruamoko/qwaq/debugger/views/indexview.r | 33 +++++++ ruamoko/qwaq/debugger/views/nameview.r | 5 + ruamoko/qwaq/debugger/views/structview.h | 15 +++ ruamoko/qwaq/debugger/views/structview.r | 119 +++++++++++++++++++++++ ruamoko/qwaq/device/nameview.h | 13 +++ ruamoko/qwaq/device/nameview.r | 33 +++++++ ruamoko/qwaq/ui/stringview.h | 15 +++ ruamoko/qwaq/ui/stringview.r | 42 ++++++++ 20 files changed, 448 insertions(+), 6 deletions(-) create mode 100644 ruamoko/qwaq/debugger/views/arrayview.h create mode 100644 ruamoko/qwaq/debugger/views/arrayview.r create mode 100644 ruamoko/qwaq/debugger/views/indexview.h create mode 100644 ruamoko/qwaq/debugger/views/indexview.r create mode 100644 ruamoko/qwaq/debugger/views/structview.h create mode 100644 ruamoko/qwaq/debugger/views/structview.r create mode 100644 ruamoko/qwaq/device/nameview.h create mode 100644 ruamoko/qwaq/device/nameview.r create mode 100644 ruamoko/qwaq/ui/stringview.h create mode 100644 ruamoko/qwaq/ui/stringview.r diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 81bf44d68..79a16aef0 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -16,6 +16,7 @@ ruamoko_qwaq_libui_a_SOURCES= \ ruamoko/qwaq/ui/proxyview.r \ ruamoko/qwaq/ui/rect.r \ ruamoko/qwaq/ui/scrollbar.r \ + ruamoko/qwaq/ui/stringview.r \ ruamoko/qwaq/ui/tableview.r \ ruamoko/qwaq/ui/textcontext.r \ ruamoko/qwaq/ui/titlebar.r \ @@ -29,6 +30,7 @@ r_depfiles_remade += $(ruamoko_qwaq_libui_a_dep) qwaq_app_dat_src= \ ruamoko/qwaq/qwaq-app.r \ + ruamoko/qwaq/debugger/views/arrayview.r \ ruamoko/qwaq/debugger/views/basicview.r \ ruamoko/qwaq/debugger/views/defview.r \ ruamoko/qwaq/debugger/views/doubleview.r \ @@ -36,11 +38,13 @@ qwaq_app_dat_src= \ ruamoko/qwaq/debugger/views/fieldview.r \ ruamoko/qwaq/debugger/views/floatview.r \ ruamoko/qwaq/debugger/views/funcview.r \ + ruamoko/qwaq/debugger/views/indexview.r \ ruamoko/qwaq/debugger/views/intview.r \ ruamoko/qwaq/debugger/views/nameview.r \ ruamoko/qwaq/debugger/views/pointerview.r\ ruamoko/qwaq/debugger/views/quatview.r \ ruamoko/qwaq/debugger/views/stringview.r \ + ruamoko/qwaq/debugger/views/structview.r \ ruamoko/qwaq/debugger/views/uintview.r \ ruamoko/qwaq/debugger/views/vectorview.r \ ruamoko/qwaq/debugger/views/voidview.r \ diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index f46bdc81c..174908399 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -601,7 +601,7 @@ cmd_mvwvline (qwaq_resources_t *res) static void dump_command (qwaq_resources_t *res, int len) { - if (1) { + if (0) { qwaq_commands cmd = qwaq_cmd_peek (res, 0); Sys_Printf ("%s[%d]", qwaq_command_names[cmd], len); if (cmd == qwaq_cmd_syncprint) { diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 929ccc9a5..4826c4166 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -301,7 +301,11 @@ qdb_get_state (progs_t *pr) string_t file = 0; unsigned line = 0; unsigned staddr = tpr->pr_xstatement; - func_t func = tpr->pr_xfunction - tpr->function_table; + func_t func = 0; + + if (tpr->pr_xfunction) { + func = tpr->pr_xfunction - tpr->function_table; + } lineno = PR_Find_Lineno (tpr, staddr); if (lineno) { @@ -458,6 +462,18 @@ qdb_get_file_path (progs_t *pr) } } +static void +qdb_find_string (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pointer_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + const char *str = P_GSTRING (pr, 1); + + R_INT (pr) = PR_FindString (tpr, str); +} + static void qdb_find_global (progs_t *pr) { @@ -648,6 +664,7 @@ static builtin_t builtins[] = { {"qdb_get_string|{tag qdb_target_s=}i", qdb_get_string, -1}, {"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1}, {"qdb_get_file_path", qdb_get_file_path, -1}, + {"qdb_find_string", qdb_find_string, -1}, {"qdb_find_global", qdb_find_global, -1}, {"qdb_find_field", qdb_find_field, -1}, {"qdb_find_function", qdb_find_function, -1}, diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 04fdcd406..5c7b5bfb5 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -754,7 +754,7 @@ cmd_get_device_info (qwaq_input_resources_t *res) static void dump_command (qwaq_input_resources_t *res, int len) { - if (1) { + if (0) { qwaq_input_commands cmd = qwaq_cmd_peek (res, 0); Sys_Printf ("%s[%d]", qwaq_input_command_names[cmd], len); for (int i = 2; i < len; i++) { diff --git a/ruamoko/qwaq/builtins/threading.c b/ruamoko/qwaq/builtins/threading.c index 7f258b90e..020eed645 100644 --- a/ruamoko/qwaq/builtins/threading.c +++ b/ruamoko/qwaq/builtins/threading.c @@ -92,7 +92,7 @@ qwaq_pipe_submit (qwaq_pipe_t *pipe, const int *cmd, unsigned len) void qwaq_pipe_receive (qwaq_pipe_t *pipe, int *result, int cmd, unsigned len) { - Sys_Printf ("qwaq_wait_result: %d %d\n", cmd, len); + //Sys_Printf ("qwaq_wait_result: %d %d\n", cmd, len); pthread_mutex_lock (&pipe->pipe_cond.mut); while (RB_DATA_AVAILABLE (pipe->pipe) < len || *RB_PEEK_DATA (pipe->pipe, 0) != cmd) { @@ -102,7 +102,7 @@ qwaq_pipe_receive (qwaq_pipe_t *pipe, int *result, int cmd, unsigned len) RB_READ_DATA (pipe->pipe, result, len); pthread_cond_broadcast (&pipe->pipe_cond.wcond); pthread_mutex_unlock (&pipe->pipe_cond.mut); - Sys_Printf ("qwaq_wait_result exit: %d %d\n", cmd, len); + //Sys_Printf ("qwaq_wait_result exit: %d %d\n", cmd, len); } void diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index 2e68de316..93ef60f3b 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -88,6 +88,7 @@ int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, void *dst); // avoid cast shenanigans when getting type encoding strings @overload string qdb_get_string (qdb_target_t target, string str); string qdb_get_file_path (qdb_target_t target, string file); +int qdb_find_string (qdb_target_t target, string str); qdb_def_t qdb_find_global (qdb_target_t target, string name); qdb_def_t qdb_find_field (qdb_target_t target, string name); qdb_function_t *qdb_find_function (qdb_target_t target, string name); diff --git a/ruamoko/qwaq/debugger/debug.r b/ruamoko/qwaq/debugger/debug.r index 70126f7a2..3b6d25efe 100644 --- a/ruamoko/qwaq/debugger/debug.r +++ b/ruamoko/qwaq/debugger/debug.r @@ -18,6 +18,7 @@ int qdb_get_data (qdb_target_t target, unsigned src, unsigned len, string qdb_get_string (qdb_target_t target, unsigned str) = #0; string qdb_get_string (qdb_target_t target, string str) = #0; string qdb_get_file_path (qdb_target_t target, string file) = #0; +int qdb_find_string (qdb_target_t target, string str) = #0; qdb_def_t qdb_find_global (qdb_target_t target, string name) = #0; qdb_def_t qdb_find_field (qdb_target_t target, string name) = #0; qdb_function_t *qdb_find_function (qdb_target_t target, string name) = #0; diff --git a/ruamoko/qwaq/debugger/views/arrayview.h b/ruamoko/qwaq/debugger/views/arrayview.h new file mode 100644 index 000000000..22b45a107 --- /dev/null +++ b/ruamoko/qwaq/debugger/views/arrayview.h @@ -0,0 +1,15 @@ +#ifndef __qwaq_debugger_arrayructview_h +#define __qwaq_debugger_arrayructview_h + +#include "ruamoko/qwaq/debugger/views/defview.h" + +@interface ArrayView : DefView +{ + unsigned *data; + DefView **element_views; + int *element_rows; +} ++(ArrayView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; +@end + +#endif//__qwaq_debugger_arrayructview_h diff --git a/ruamoko/qwaq/debugger/views/arrayview.r b/ruamoko/qwaq/debugger/views/arrayview.r new file mode 100644 index 000000000..ec1837bc7 --- /dev/null +++ b/ruamoko/qwaq/debugger/views/arrayview.r @@ -0,0 +1,115 @@ +#include +#include +#include "ruamoko/qwaq/debugger/typeencodings.h" +#include "ruamoko/qwaq/debugger/views/indexview.h" +#include "ruamoko/qwaq/debugger/views/nameview.h" +#include "ruamoko/qwaq/debugger/views/arrayview.h" +#include "ruamoko/qwaq/ui/tableview.h" + +@implementation ArrayView + +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type +{ + if (!(self = [super initWithDef:def type:type])) { + return nil; + } + self.data = (unsigned *)(data + def.offset); + element_views = obj_malloc (type.array.size); + element_rows = obj_malloc (type.array.size); + element_rows[0] = 0; + qfot_type_t *element_type = type.array.type; + int element_size = [TypeEncodings typeSize:element_type]; + for (int i = 0; i < type.array.size; i++) { + qdb_def_t def = { + 0, // XXX type/size not needed at this stage + i * element_size, + 0, // filled in by setTarget + (unsigned)type.fldptr.aux_type + }; + element_views[i] = [[DefView withDef:def + type:element_type + in:data + target:target] retain]; + element_rows[i + 1] = [element_views[i] rows]; + } + prefixsum (element_rows, type.array.size + 1); + return self; +} + ++(ArrayView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type +{ + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; +} + +-setTarget:(qdb_target_t)target +{ + [super setTarget:target]; + for (int i = 0; i < type.array.size; i++) { + [element_views[i] setTarget:target]; + } + return self; +} + +-(void)dealloc +{ + for (int i = 0; i < type.array.size; i++) { + [element_views[i] release]; + } + obj_free (element_views); + obj_free (element_rows); +} + +-draw +{ + [super draw]; + string val = sprintf ("%s[%d..%d]", type.array.type.encoding, + type.array.base, + type.array.base + type.array.size - 1); + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; + return self; +} + +-fetchData +{ + [super fetchData]; + element_rows[0] = 0; + for (int i = 0; i < type.array.size; i++) { + [element_views[i] fetchData]; + element_rows[i + 1] = [element_views[i] rows]; + } + prefixsum (element_rows, type.array.size + 1); + return self; +} + +-(int) rows +{ + return 1 + element_rows[type.array.size]; +} + +-(View *) viewAtRow:(int)row forColumn:(TableViewColumn *)column +{ + if (row == 0) { + if ([column name] == "name") { + return [NameView withName:qdb_get_string (target, def.name)]; + } + return self; + } + + row -= 1; + + View *view = nil; + int *index = fbsearch (&row, element_rows, type.array.size, 1, nil); + + if ([column name] == "name") { + return [IndexView withIndex:index - element_rows + type.array.base]; + } + + if (index) { + DefView *dv = element_views[index - element_rows]; + int r = row - *index; + view = [dv viewAtRow: r forColumn:column]; + } + return view; +} + +@end diff --git a/ruamoko/qwaq/debugger/views/defview.h b/ruamoko/qwaq/debugger/views/defview.h index f0e6bb392..f6e8e9cda 100644 --- a/ruamoko/qwaq/debugger/views/defview.h +++ b/ruamoko/qwaq/debugger/views/defview.h @@ -17,6 +17,7 @@ +(DefView *)withDef:(qdb_def_t)def in:(void *)data target:(qdb_target_t)target; +(DefView *)withDef:(qdb_def_t)def type:(qfot_type_t *)type in:(void *)data target:(qdb_target_t)target; -initWithDef:(qdb_def_t)def type:(qfot_type_t *)type; +-setTarget:(qdb_target_t)target; -fetchData; -(int) rows; -(View *) viewAtRow:(int) row forColumn:(TableViewColumn *)column; diff --git a/ruamoko/qwaq/debugger/views/defview.r b/ruamoko/qwaq/debugger/views/defview.r index aff2905f6..8be59474a 100644 --- a/ruamoko/qwaq/debugger/views/defview.r +++ b/ruamoko/qwaq/debugger/views/defview.r @@ -7,7 +7,7 @@ static string meta_views[] = { "BasicView", "StructView", - "UnionView", + "StructView", "EnumView", "ArrayView", "ClassView", diff --git a/ruamoko/qwaq/debugger/views/indexview.h b/ruamoko/qwaq/debugger/views/indexview.h new file mode 100644 index 000000000..0683e0fc1 --- /dev/null +++ b/ruamoko/qwaq/debugger/views/indexview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_indexview_h +#define __qwaq_debugger_indexview_h + +#include "ruamoko/qwaq/debugger/views/defview.h" + +@interface IndexView : DefView +{ + int index; +} ++(IndexView *)withIndex:(int)index; +@end + +#endif//__qwaq_debugger_indexview_h diff --git a/ruamoko/qwaq/debugger/views/indexview.r b/ruamoko/qwaq/debugger/views/indexview.r new file mode 100644 index 000000000..59689792e --- /dev/null +++ b/ruamoko/qwaq/debugger/views/indexview.r @@ -0,0 +1,33 @@ +#include +#include "ruamoko/qwaq/debugger/views/indexview.h" + +@implementation IndexView + +-initWithIndex:(int)index +{ + if (!(self = [super initWithDef:def type:nil])) { + return nil; + } + self.index = index; + return self; +} + ++(IndexView *)withIndex:(int)index +{ + return [[[self alloc] initWithIndex:index] autorelease]; +} + +-draw +{ + [super draw]; + string val = sprintf ("[%d]", index); + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; + return self; +} + +-(View *) viewAtRow:(int) row forColumn:(TableViewColumn *)column +{ + return self; +} + +@end diff --git a/ruamoko/qwaq/debugger/views/nameview.r b/ruamoko/qwaq/debugger/views/nameview.r index 6393acfd2..d3002aac7 100644 --- a/ruamoko/qwaq/debugger/views/nameview.r +++ b/ruamoko/qwaq/debugger/views/nameview.r @@ -30,4 +30,9 @@ return self; } +-(View *) viewAtRow:(int) row forColumn:(TableViewColumn *)column +{ + return self; +} + @end diff --git a/ruamoko/qwaq/debugger/views/structview.h b/ruamoko/qwaq/debugger/views/structview.h new file mode 100644 index 000000000..85ecccdd4 --- /dev/null +++ b/ruamoko/qwaq/debugger/views/structview.h @@ -0,0 +1,15 @@ +#ifndef __qwaq_debugger_structview_h +#define __qwaq_debugger_structview_h + +#include "ruamoko/qwaq/debugger/views/defview.h" + +@interface StructView : DefView +{ + unsigned *data; + DefView **field_views; + int *field_rows; +} ++(StructView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type; +@end + +#endif//__qwaq_debugger_structview_h diff --git a/ruamoko/qwaq/debugger/views/structview.r b/ruamoko/qwaq/debugger/views/structview.r new file mode 100644 index 000000000..d0f42cd62 --- /dev/null +++ b/ruamoko/qwaq/debugger/views/structview.r @@ -0,0 +1,119 @@ +#include +#include +#include "ruamoko/qwaq/debugger/typeencodings.h" +#include "ruamoko/qwaq/debugger/views/nameview.h" +#include "ruamoko/qwaq/debugger/views/structview.h" +#include "ruamoko/qwaq/ui/tableview.h" + +@implementation StructView + +-initWithDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type +{ + if (!(self = [super initWithDef:def type:type])) { + return nil; + } + self.data = (unsigned *)(data + def.offset); + field_views = obj_malloc (type.strct.num_fields); + field_rows = obj_malloc (type.strct.num_fields); + field_rows[0] = 0; + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_type_t *field_type = type.strct.fields[i].type; + qdb_def_t def = { + 0, // XXX type/size not needed at this stage + type.strct.fields[i].offset, + 0, // filled in by setTarget + (unsigned)type.fldptr.aux_type + }; + field_views[i] = [[DefView withDef:def + type:field_type + in:data + target:target] retain]; + field_rows[i + 1] = 0; + if (str_mid (type.strct.fields[i].name, 0, 11) != ".anonymous.") { + field_rows[i + 1] = [field_views[i] rows]; + } + } + prefixsum (field_rows, type.strct.num_fields + 1); + return self; +} + ++(StructView *)withDef:(qdb_def_t)def in:(void *)data type:(qfot_type_t *)type +{ + return [[[self alloc] initWithDef:def in:data type:type] autorelease]; +} + +-setTarget:(qdb_target_t)target +{ + [super setTarget:target]; + for (int i = 0; i < type.strct.num_fields; i++) { + if (target.handle) { + // the field name is already in local space because the same type + // may be defined in both progs + string name = type.strct.fields[i].name; + field_views[i].def.name = qdb_find_string (target, name); + } + [field_views[i] setTarget:target]; + } + return self; +} + +-(void)dealloc +{ + for (int i = 0; i < type.strct.num_fields; i++) { + [field_views[i] release]; + } + obj_free (field_views); + obj_free (field_rows); +} + +-draw +{ + [super draw]; + string val = sprintf ("%s", type.strct.tag); + [self mvprintf:{0, 0}, "%*.*s", xlen, xlen, val]; + return self; +} + +-fetchData +{ + [super fetchData]; + field_rows[0] = 0; + for (int i = 0; i < type.strct.num_fields; i++) { + [field_views[i] fetchData]; + field_rows[i + 1] = 0; + if (str_mid (type.strct.fields[i].name, 0, 11) != ".anonymous.") { + field_rows[i + 1] = [field_views[i] rows]; + } + } + prefixsum (field_rows, type.strct.num_fields + 1); + return self; +} + +-(int) rows +{ + return 1 + field_rows[type.strct.num_fields]; +} + +-(View *) viewAtRow:(int) row forColumn:(TableViewColumn *)column +{ + if (row == 0) { + if ([column name] == "name") { + return [NameView withName:qdb_get_string (target, def.name)]; + } + return self; + } + + row -= 1; + + View *view = nil; + int *index = fbsearch (&row, field_rows, type.strct.num_fields, 1, nil); + + if (index) { + DefView *dv = field_views[index - field_rows]; + int r = row - *index; + view = [dv viewAtRow: r forColumn:column]; + } + return view; +} + +@end diff --git a/ruamoko/qwaq/device/nameview.h b/ruamoko/qwaq/device/nameview.h new file mode 100644 index 000000000..ee5622062 --- /dev/null +++ b/ruamoko/qwaq/device/nameview.h @@ -0,0 +1,13 @@ +#ifndef __qwaq_debugger_nameview_h +#define __qwaq_debugger_nameview_h + +#include "ruamoko/qwaq/debugger/views/defview.h" + +@interface NameView : DefView +{ + string name; +} ++(NameView *)withName:(string)name; +@end + +#endif//__qwaq_debugger_nameview_h diff --git a/ruamoko/qwaq/device/nameview.r b/ruamoko/qwaq/device/nameview.r new file mode 100644 index 000000000..6393acfd2 --- /dev/null +++ b/ruamoko/qwaq/device/nameview.r @@ -0,0 +1,33 @@ +#include +#include "ruamoko/qwaq/debugger/views/nameview.h" + +@implementation NameView + +-initWithName:(string)name +{ + if (!(self = [super initWithDef:def type:nil])) { + return nil; + } + self.name = name; + return self; +} + +-(void)dealloc +{ + str_free (name); + [super dealloc]; +} + ++(NameView *)withName:(string)name +{ + return [[[self alloc] initWithName:name] autorelease]; +} + +-draw +{ + [super draw]; + [self mvaddstr:{0, 0}, str_mid (name, 0, xlen)]; + return self; +} + +@end diff --git a/ruamoko/qwaq/ui/stringview.h b/ruamoko/qwaq/ui/stringview.h new file mode 100644 index 000000000..b497a8486 --- /dev/null +++ b/ruamoko/qwaq/ui/stringview.h @@ -0,0 +1,15 @@ +#ifndef __qwaq_ui_stringview_h +#define __qwaq_ui_stringview_h + +#include "ruamoko/qwaq/ui/view.h" + +@interface StringView : View +{ + string str; +} ++(StringView *)withRect:(Rect)rect; ++(StringView *)withRect:(Rect)rect string:(string)str; +-setString:(string)newString; +@end + +#endif//__qwaq_ui_stringview_h diff --git a/ruamoko/qwaq/ui/stringview.r b/ruamoko/qwaq/ui/stringview.r new file mode 100644 index 000000000..109a0ac52 --- /dev/null +++ b/ruamoko/qwaq/ui/stringview.r @@ -0,0 +1,42 @@ +#include + +#include "ruamoko/qwaq/ui/group.h" +#include "ruamoko/qwaq/ui/stringview.h" + +@implementation StringView + +-initWithRect:(Rect)rect string:(string)str +{ + if (!(self = [super initWithRect:rect])) { + return nil; + } + self.str = str; + growMode = gfGrowHiX; + return self; +} + ++(StringView *)withRect:(Rect)rect +{ + return [[[self alloc] initWithRect:rect string:nil] autorelease]; +} + ++(StringView *)withRect:(Rect)rect string:(string)str +{ + return [[[self alloc] initWithRect:rect string:str] autorelease]; +} + +-setString:(string) newTitle +{ + str = newTitle; + [self redraw]; + return self; +} + +-draw +{ + [super draw]; + [self mvaddstr: { 0, 0}, str]; + return self; +} + +@end From 0df16fb2106c875243d6216ab28b70adc58d7aed Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Sep 2021 02:14:26 +0900 Subject: [PATCH 1751/3664] [qwaq] Fix TableView's scrolling --- ruamoko/qwaq/debugger/localsdata.h | 2 + ruamoko/qwaq/debugger/localsdata.r | 15 +++- ruamoko/qwaq/ui/scrollbar.r | 5 ++ ruamoko/qwaq/ui/tableview.h | 2 + ruamoko/qwaq/ui/tableview.r | 107 +++++++++++++++++++++++++++++ 5 files changed, 130 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/debugger/localsdata.h b/ruamoko/qwaq/debugger/localsdata.h index e153a06a5..bdc6ea342 100644 --- a/ruamoko/qwaq/debugger/localsdata.h +++ b/ruamoko/qwaq/debugger/localsdata.h @@ -6,9 +6,11 @@ #include "ruamoko/qwaq/debugger/debug.h" @class DefView; +@class ListenerGroup; @interface LocalsData : Object { + ListenerGroup *onRowCountChanged; qdb_target_t target; qfot_type_encodings_t target_encodings; unsigned current_fnum; diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index 808c781de..c183d4b50 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -4,6 +4,7 @@ #include "ruamoko/qwaq/debugger/views/defview.h" #include "ruamoko/qwaq/debugger/views/nameview.h" #include "ruamoko/qwaq/debugger/localsdata.h" +#include "ruamoko/qwaq/ui/listener.h" @implementation LocalsData @@ -18,6 +19,7 @@ qdb_get_data (target, encodings_def.offset, sizeof(target_encodings), &target_encodings); + self.onRowCountChanged = [[ListenerGroup listener] retain]; return self; } @@ -42,6 +44,7 @@ free_defs (LocalsData *self) -(void)dealloc { + [onRowCountChanged release]; if (defs) { free_defs (self); } @@ -56,7 +59,7 @@ free_defs (LocalsData *self) if (current_fnum == fnum) { return self; } - current_fnum =fnum; + current_fnum = fnum; if (defs) { free_defs (self); @@ -82,6 +85,7 @@ free_defs (LocalsData *self) } prefixsum (def_rows, aux_func.num_locals + 1); } + [onRowCountChanged respond:self]; return self; } @@ -90,6 +94,7 @@ free_defs (LocalsData *self) if (data && func.local_size && func.local_data) { qdb_get_data (target, func.local_data, func.local_size, data); } + int rowCount = def_rows[aux_func.num_locals]; if (aux_func) { def_rows[0] = 0; for (int i = 0; i < aux_func.num_locals; i++) { @@ -98,9 +103,17 @@ free_defs (LocalsData *self) } prefixsum (def_rows, aux_func.num_locals + 1); } + if (rowCount != def_rows[aux_func.num_locals]) { + [onRowCountChanged respond:self]; + } return self; } +-(ListenerGroup *)onRowCountChanged +{ + return onRowCountChanged; +} + -(int)numberOfRows:(TableView *)tableview { if (aux_func) { diff --git a/ruamoko/qwaq/ui/scrollbar.r b/ruamoko/qwaq/ui/scrollbar.r index 9e5f150f6..392bd3555 100644 --- a/ruamoko/qwaq/ui/scrollbar.r +++ b/ruamoko/qwaq/ui/scrollbar.r @@ -228,6 +228,11 @@ page (ScrollBar *self, Point pos, Point thumb) -setRange:(unsigned)range { self.range = range; + if (index > range) { + index = range; + [onScrollBarModified respond:self]; + position_tab (self); + } return self; } diff --git a/ruamoko/qwaq/ui/tableview.h b/ruamoko/qwaq/ui/tableview.h index 52bca6880..630b2bf79 100644 --- a/ruamoko/qwaq/ui/tableview.h +++ b/ruamoko/qwaq/ui/tableview.h @@ -7,8 +7,10 @@ @class TableView; @class TableViewColumn; @class Array; +@class ListenerGroup; @protocol TableViewDataSource +-(ListenerGroup *)onRowCountChanged; -(int)numberOfRows:(TableView *)tableview; -(View *)tableView:(TableView *)tableView forColumn:(TableViewColumn *)column diff --git a/ruamoko/qwaq/ui/tableview.r b/ruamoko/qwaq/ui/tableview.r index 940bf1793..dc5a5cbd9 100644 --- a/ruamoko/qwaq/ui/tableview.r +++ b/ruamoko/qwaq/ui/tableview.r @@ -1,5 +1,6 @@ #include #include "ruamoko/qwaq/ui/listener.h" +#include "ruamoko/qwaq/ui/scrollbar.h" #include "ruamoko/qwaq/ui/tableview.h" @implementation TableViewColumn @@ -97,9 +98,16 @@ -setDataSource:(id)dataSource { self.dataSource = [dataSource retain]; + [[dataSource onRowCountChanged] addListener:self + :@selector(onRowCountChanged:)]; return self; } +-(void)onRowCountChanged:(id)sender +{ + [vScrollBar setRange:[sender numberOfRows:self]]; +} + -resize:(Extent)delta { Extent size = self.size; @@ -143,4 +151,103 @@ } } +static int +handleEvent (TableView *self, qwaq_event_t *event) +{ + if (event.what & qe_mouse) { + if (event.what == qe_mouseclick) { + if (event.mouse.buttons & (1 << 3)) { + [self.vScrollBar page:1 dir:0]; + return 1; + } + if (event.mouse.buttons & (1 << 4)) { + [self.vScrollBar page:1 dir:1]; + return 1; + } +#if 0 + if (event.mouse.buttons & (1 << 5)) { + [self scrollLeft: 1]; + return 1; + } + if (event.mouse.buttons & (1 << 6)) { + [self scrollRight: 1]; + return 1; + } +#endif + } + } else if (event.what == qe_keydown) { +#if 0 + switch (event.key.code) { + case QFK_PAGEUP: + if (event.key.shift & qe_control) { + [self moveBOT]; + } else { + [self pageUp]; + } + return 1; + case QFK_PAGEDOWN: + if (event.key.shift & qe_control) { + [self moveEOT]; + } else { + [self pageDown]; + } + return 1; + case QFK_UP: + if (event.key.shift & qe_control) { + [self linesUp]; + } else { + [self charUp]; + } + return 1; + case QFK_DOWN: + if (event.key.shift & qe_control) { + [self linesDown]; + } else { + [self charDown]; + } + return 1; + case QFK_LEFT: + if (event.key.shift & qe_control) { + [self wordLeft]; + } else { + [self charLeft]; + } + return 1; + case QFK_RIGHT: + if (event.key.shift & qe_control) { + [self wordRight]; + } else { + [self charRight]; + } + return 1; + case QFK_HOME: + if (event.key.shift & qe_control) { + [self moveBOS]; + } else { + [self moveBOL]; + } + return 1; + case QFK_END: + if (event.key.shift & qe_control) { + [self moveEOS]; + } else { + [self moveEOL]; + } + return 1; + } +#endif + } + return 0; +} + +-handleEvent:(qwaq_event_t *) event +{ + [super handleEvent: event]; + + if (handleEvent (self, event)) { + event.what = qe_none; + } + return self; +} + @end From 2119688b484d59ab44b6ee65c71edf16a97bdb1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Sep 2021 13:24:48 +0900 Subject: [PATCH 1752/3664] [gamecode] Use a flag for format width This ensures caller specified width always gets through to libc's printf, even if the caller specifies 0. More importantly, * works correctly. --- libs/gamecode/pr_strings.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index c0a0df833..d1093c455 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -51,6 +51,7 @@ #define FMT_ADDBLANK (1<<4) #define FMT_HEX (1<<5) #define FMT_LONG (1<<6) +#define FMT_WIDTH (1<<7) typedef struct fmt_item_s { byte type; @@ -748,7 +749,7 @@ I_DoPrint (dstring_t *tmp, dstring_t *result, fmt_item_t *formatting) qboolean doPrecision, doWidth; doPrecision = -1 != current->precision; - doWidth = 0 != current->minFieldWidth; + doWidth = 0 != (current->flags & FMT_WIDTH); dsprintf (tmp, "%%%s%s%s%s%s%s%s", (current->flags & FMT_ALTFORM) ? "#" : "", // hash @@ -956,6 +957,7 @@ fmt_state_flags (fmt_state_t *state) static void fmt_state_var_field_width (fmt_state_t *state) { + (*state->fi)->flags |= FMT_WIDTH; (*state->fi)->minFieldWidth = P_INT (pr, state->fmt_count); state->fmt_count++; if (*++state->c == '.') { @@ -968,6 +970,7 @@ fmt_state_var_field_width (fmt_state_t *state) static void fmt_state_field_width (fmt_state_t *state) { + (*state->fi)->flags |= FMT_WIDTH; while (isdigit ((byte )*state->c)) { (*state->fi)->minFieldWidth *= 10; (*state->fi)->minFieldWidth += *state->c++ - '0'; From 1a5cce437403c85414a8fdcc18e1553ecd1db722 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Sep 2021 13:27:55 +0900 Subject: [PATCH 1753/3664] [qwaq] Set table cell size in the correct place I have no idea why I made LocalsData set the size instead of TableView, but now the cells are correctly sized automatically. --- ruamoko/qwaq/debugger/localsdata.r | 1 - ruamoko/qwaq/ui/tableview.r | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index c183d4b50..8bb251597 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -139,7 +139,6 @@ free_defs (LocalsData *self) int r = row - *index; view = [dv viewAtRow: r forColumn:column]; } - [view resizeTo:{[column width], 1}]; return view; } diff --git a/ruamoko/qwaq/ui/tableview.r b/ruamoko/qwaq/ui/tableview.r index dc5a5cbd9..91137c718 100644 --- a/ruamoko/qwaq/ui/tableview.r +++ b/ruamoko/qwaq/ui/tableview.r @@ -100,6 +100,7 @@ self.dataSource = [dataSource retain]; [[dataSource onRowCountChanged] addListener:self :@selector(onRowCountChanged:)]; + [vScrollBar setRange:[dataSource numberOfRows:self]]; return self; } @@ -135,7 +136,10 @@ } col = [columns objectAtIndex:i]; cell = [dataSource tableView:self forColumn:col row:row]; - [[[cell setContext:buffer] moveTo:{x, y}] draw]; + [[[[cell setContext:buffer] + moveTo:{x, y}] + resizeTo:{[col width], 1}] + draw]; x += [col width]; } } From 4057500accb9def55275ec27dc0839d792f913ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Sep 2021 14:22:19 +0900 Subject: [PATCH 1754/3664] [qwaq] Implement device management for input-app Currently shows only the axes (along with dev "path" and name), but it has done a good job of pushing dev of other bits of code :) --- ruamoko/qwaq/Makemodule.am | 4 ++ ruamoko/qwaq/builtins/input.c | 1 - ruamoko/qwaq/device/axisdata.h | 19 +++++++++ ruamoko/qwaq/device/axisdata.r | 58 +++++++++++++++++++++++++ ruamoko/qwaq/device/axisview.h | 18 ++++++++ ruamoko/qwaq/device/axisview.r | 42 +++++++++++++++++++ ruamoko/qwaq/device/device.h | 26 ++++++++++++ ruamoko/qwaq/device/device.r | 77 ++++++++++++++++++++++++++++++++++ ruamoko/qwaq/device/nameview.h | 2 +- ruamoko/qwaq/device/nameview.r | 4 +- ruamoko/qwaq/input-app.h | 3 ++ ruamoko/qwaq/input-app.r | 58 ++++++++++++++++--------- 12 files changed, 288 insertions(+), 24 deletions(-) create mode 100644 ruamoko/qwaq/device/axisdata.h create mode 100644 ruamoko/qwaq/device/axisdata.r create mode 100644 ruamoko/qwaq/device/axisview.h create mode 100644 ruamoko/qwaq/device/axisview.r create mode 100644 ruamoko/qwaq/device/device.h create mode 100644 ruamoko/qwaq/device/device.r diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 79a16aef0..43c306003 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -57,6 +57,10 @@ qwaq_app_dat_src= \ ruamoko/qwaq/editor/status.r qwaq_input_app_dat_src= \ + ruamoko/qwaq/device/axisdata.r \ + ruamoko/qwaq/device/axisview.r \ + ruamoko/qwaq/device/nameview.r \ + ruamoko/qwaq/device/device.r \ ruamoko/qwaq/qwaq-input.r \ ruamoko/qwaq/input-app.r diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 5c7b5bfb5..3affcdcc7 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -625,7 +625,6 @@ bi_get_device_info (progs_t *pr) qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); int devid = P_INT (pr, 0); - Sys_Printf ("qwaq_get_device_info: %d\n", devid); int command[] = { qwaq_cmd_get_device_info, 0, devid, diff --git a/ruamoko/qwaq/device/axisdata.h b/ruamoko/qwaq/device/axisdata.h new file mode 100644 index 000000000..c743bad3d --- /dev/null +++ b/ruamoko/qwaq/device/axisdata.h @@ -0,0 +1,19 @@ +#ifndef __qwaq_device_axisdata_h +#define __qwaq_device_axisdata_h + +#include "ruamoko/qwaq/qwaq-input.h" +#include "ruamoko/qwaq/ui/tableview.h" + +@class AxisView; + +@interface AxisData : Object +{ + int numaxes; + in_axisinfo_t *axes; + AxisView **axis_views; +} ++withDevice:(qwaq_devinfo_t *)device; +-updateAxis:(int)axis value:(int)value; +@end + +#endif//__qwaq_device_axisdata_h diff --git a/ruamoko/qwaq/device/axisdata.r b/ruamoko/qwaq/device/axisdata.r new file mode 100644 index 000000000..5fa92c270 --- /dev/null +++ b/ruamoko/qwaq/device/axisdata.r @@ -0,0 +1,58 @@ +#include "ruamoko/qwaq/device/axisdata.h" +#include "ruamoko/qwaq/device/axisview.h" + +@implementation AxisData + +-initWithDevice:(qwaq_devinfo_t *)device +{ + if (!(self = [super init])) { + return nil; + } + numaxes = device.numaxes; + axes = device.axes; + axis_views = obj_malloc (numaxes); + for (int i = 0; i < numaxes; i++) { + axis_views[i] = [[AxisView withAxis:&axes[i]] retain]; + } + return self; +} + ++withDevice:(qwaq_devinfo_t *)device +{ + return [[[self alloc] initWithDevice:device] autorelease]; +} + +-(void)dalloc +{ +} + +-updateAxis:(int)axis value:(int)value +{ + axes[axis].value = value; + return self; +} + +-(ListenerGroup *)onRowCountChanged +{ + return nil; +} + +-(int)numberOfRows:(TableView *)tableview +{ + return numaxes; +} + +-(View *)tableView:(TableView *)tableview + forColumn:(TableViewColumn *)column + row:(int)row +{ + View *view = nil; + + if (row >= 0 && row < numaxes) { + AxisView *av = axis_views[row]; + view = [av viewAtRow:0 forColumn:column]; + } + return view; +} + +@end diff --git a/ruamoko/qwaq/device/axisview.h b/ruamoko/qwaq/device/axisview.h new file mode 100644 index 000000000..4ea867b9d --- /dev/null +++ b/ruamoko/qwaq/device/axisview.h @@ -0,0 +1,18 @@ +#ifndef __qwaq_device_axisview_h +#define __qwaq_device_axisview_h + +#include "ruamoko/qwaq/qwaq-input.h" +#include "ruamoko/qwaq/ui/view.h" + +@class TableViewColumn; + +@interface AxisView : View +{ + in_axisinfo_t *axis; +} ++withAxis:(in_axisinfo_t *)axis; +-(int)rows; +-(View *)viewAtRow:(int)row forColumn:(TableViewColumn *)column; +@end + +#endif//__qwaq_device_axisview_h diff --git a/ruamoko/qwaq/device/axisview.r b/ruamoko/qwaq/device/axisview.r new file mode 100644 index 000000000..621af66b1 --- /dev/null +++ b/ruamoko/qwaq/device/axisview.r @@ -0,0 +1,42 @@ +#include +#include "ruamoko/qwaq/ui/tableview.h" +#include "ruamoko/qwaq/device/axisview.h" +#include "ruamoko/qwaq/device/nameview.h" + +@implementation AxisView + +-initWithAxis:(in_axisinfo_t *)axis +{ + if (!(self = [super init])) { + return nil; + } + self.axis = axis; + return self; +} + ++withAxis:(in_axisinfo_t *)axis +{ + return [[[self alloc] initWithAxis:axis] retain]; +} + +-draw +{ + [super draw]; + [self mvprintf:{0, 0}, "%*.*d", xlen, xlen, axis.value]; + return self; +} + +-(int)rows +{ + return 1; +} + +-(View *)viewAtRow:(int)row forColumn:(TableViewColumn *)column +{ + if ([column name] == "axis") { + return [NameView withName:sprintf("%d", axis.axis)]; + } + return self; +} + +@end diff --git a/ruamoko/qwaq/device/device.h b/ruamoko/qwaq/device/device.h new file mode 100644 index 000000000..df287b4ce --- /dev/null +++ b/ruamoko/qwaq/device/device.h @@ -0,0 +1,26 @@ +#ifndef __qwaq_device_device_h +#define __qwaq_device_device_h + +#include "ruamoko/qwaq/qwaq-input.h" + +@class Window; +@class TableView; +@class AxisData; + +@interface Device : Object +{ + int devid; + qwaq_devinfo_t *device; + + Window *window; + TableView *axis_view; + AxisData *axis_data; +} ++withDevice:(qwaq_devinfo_t *)device id:(int)devid; +-updateAxis:(int)axis value:(int)value; +-updateButton:(int)button state:(int)state; +-(int)devid; +-redraw; +@end + +#endif//__qwaq_device_device_h diff --git a/ruamoko/qwaq/device/device.r b/ruamoko/qwaq/device/device.r new file mode 100644 index 000000000..9ae04c628 --- /dev/null +++ b/ruamoko/qwaq/device/device.r @@ -0,0 +1,77 @@ +#include +#include "ruamoko/qwaq/input-app.h" +#include "ruamoko/qwaq/ui/scrollbar.h" +#include "ruamoko/qwaq/ui/stringview.h" +#include "ruamoko/qwaq/ui/tableview.h" +#include "ruamoko/qwaq/ui/window.h" +#include "ruamoko/qwaq/device/axisdata.h" +#include "ruamoko/qwaq/device/device.h" + +@implementation Device + +-initWithDevice:(qwaq_devinfo_t *)device id:(int)devid +{ + if (!(self = [super init])) { + return nil; + } + self.device = device; + self.devid = devid; + + window = [Window withRect:{{0, 0}, {40, 10}}]; + [window setBackground: color_palette[064]]; + [window setTitle: device.id]; + + [window insert:[StringView withRect:{{1, 1}, {38, 1}} string:device.name]]; + axis_data = [[AxisData withDevice:device] retain]; + axis_view = [TableView withRect:{{1, 2}, {38, 7}}]; + [axis_view addColumn:[TableViewColumn named:"axis" width:3]]; + [axis_view addColumn:[TableViewColumn named:"value" width:6]]; + ScrollBar *sb = [ScrollBar vertical:7 at:{39, 2}]; + [axis_view setVerticalScrollBar:sb]; + [axis_view setDataSource:axis_data]; + [window insertSelected: axis_view]; + [window insert: sb]; + [application addView: window]; + + return self; +} + ++withDevice:(qwaq_devinfo_t *)device id:(int)devid +{ + return [[[self alloc] initWithDevice:device id:devid] autorelease]; +} + +-(void)dealloc +{ + obj_free (device.axes); + obj_free (device.buttons); + str_free (device.name); + str_free (device.id); + obj_free (device); + + [application removeView:window]; +} + +-updateAxis:(int)axis value:(int)value +{ + [axis_data updateAxis:axis value:value]; + return self; +} + +-updateButton:(int)button state:(int)state +{ + return self; +} + +-(int)devid +{ + return devid; +} + +-redraw +{ + [axis_view redraw]; + return self; +} + +@end diff --git a/ruamoko/qwaq/device/nameview.h b/ruamoko/qwaq/device/nameview.h index ee5622062..8ba0a8df8 100644 --- a/ruamoko/qwaq/device/nameview.h +++ b/ruamoko/qwaq/device/nameview.h @@ -3,7 +3,7 @@ #include "ruamoko/qwaq/debugger/views/defview.h" -@interface NameView : DefView +@interface NameView : View { string name; } diff --git a/ruamoko/qwaq/device/nameview.r b/ruamoko/qwaq/device/nameview.r index 6393acfd2..5568870e6 100644 --- a/ruamoko/qwaq/device/nameview.r +++ b/ruamoko/qwaq/device/nameview.r @@ -1,11 +1,11 @@ #include -#include "ruamoko/qwaq/debugger/views/nameview.h" +#include "ruamoko/qwaq/device/nameview.h" @implementation NameView -initWithName:(string)name { - if (!(self = [super initWithDef:def type:nil])) { + if (!(self = [super init])) { return nil; } self.name = name; diff --git a/ruamoko/qwaq/input-app.h b/ruamoko/qwaq/input-app.h index 1fd908bb2..7947b13bb 100644 --- a/ruamoko/qwaq/input-app.h +++ b/ruamoko/qwaq/input-app.h @@ -23,10 +23,13 @@ extern int color_palette[64]; TextContext *screen; Extent screenSize; int autocount; + + Array *devices; } -(Extent)size; -(TextContext *)screen; -addView:(View *)view; +-removeView:(View *)view; -run; @end diff --git a/ruamoko/qwaq/input-app.r b/ruamoko/qwaq/input-app.r index fe8243ee4..550a91f70 100644 --- a/ruamoko/qwaq/input-app.r +++ b/ruamoko/qwaq/input-app.r @@ -8,6 +8,7 @@ int fence; #include "ruamoko/qwaq/ui/curses.h" #include "ruamoko/qwaq/ui/group.h" #include "ruamoko/qwaq/ui/view.h" +#include "ruamoko/qwaq/device/device.h" #include "ruamoko/qwaq/qwaq-input.h" #include "ruamoko/qwaq/input-app.h" @@ -58,6 +59,8 @@ arp_end (void) [screen clear]; wrefresh (stdscr);//FIXME + devices = [[Array array] retain]; + send_connected_devices (); return self; @@ -105,33 +108,41 @@ arp_end (void) { int devid = event.message.int_val; qwaq_devinfo_t *dev = get_device_info (devid); - [screen printf:"dev add: %d %s %s\n", devid, dev.id, dev.name]; - [screen printf:" : %d %d\n", dev.numaxes, dev.numbuttons]; - for (int i = 0; i < dev.numaxes; i++) { - [screen printf:" : %d %d %d\n", dev.axes[i].value, - dev.axes[i].min, dev.axes[i].max]; - } - [screen refresh]; - obj_free (dev.axes); - obj_free (dev.buttons); - str_free (dev.name); - str_free (dev.id); - obj_free (dev); + Device *device = [Device withDevice:dev id:devid]; + [devices addObject:device]; } break; case qe_dev_rem: - [screen printf:"dev rem: %d\n", event.message.int_val]; - [screen refresh]; + for (int i = [devices count]; i-- > 0; ) { + Device *device = [devices objectAtIndex:i]; + if ([device devid] == event.message.ivector_val[0]) { + [devices removeObjectAtIndex:i]; + break; + } + } break; case qe_axis: - [screen printf:"axis: %d %d %d\n", event.message.ivector_val[0], - event.message.ivector_val[1], event.message.ivector_val[2]]; - [screen refresh]; + for (int i = [devices count]; i-- > 0; ) { + Device *device = [devices objectAtIndex:i]; + if ([device devid] == event.message.ivector_val[0]) { + [device updateAxis:event.message.ivector_val[1] + value:event.message.ivector_val[2]]; + [device redraw]; + break; + } + } break; case qe_button: - [screen printf:"button: %d %d %d\n", event.message.ivector_val[0], - event.message.ivector_val[1], event.message.ivector_val[2]]; - [screen refresh]; + for (int i = [devices count]; i-- > 0; ) { + Device *device = [devices objectAtIndex:i]; + if ([device devid] == event.message.ivector_val[0]) { + [device updateButton:event.message.ivector_val[1] + state:event.message.ivector_val[2]]; + [device redraw]; + break; + } + } + break; } if (event.what != qe_none) { [objects handleEvent: event]; @@ -162,6 +173,13 @@ arp_end (void) [screen refresh]; return self; } + +-removeView:(View *)view +{ + [objects remove: view]; + [screen refresh]; + return self; +} @end InputApplication *application; From 13bc38a55b56ca55d88ce7be4d894e922818376c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Sep 2021 15:42:54 +0900 Subject: [PATCH 1755/3664] [input,ruamoko,qwaq] Fix incorrect use of PR_RESMAP I had forgotten that _size was the number of rows in the map, not the number of objects (1024 objects per row). This fixes the missed device removal messages. And probably a slew of other bugs I'd yet to encounter :P --- include/QF/progs.h | 3 +++ libs/input/in_evdev.c | 22 ++++++++++++++++++---- libs/ruamoko/rua_obj.c | 22 +++++++++++++--------- ruamoko/qwaq/builtins/editbuffer.c | 27 +++++++++++++++++++-------- 4 files changed, 53 insertions(+), 21 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 8fb23efd7..df88b16b7 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1539,6 +1539,9 @@ void *PR_Resources_Find (progs_t *pr, const char *name); \param type The type of the resource. The size must be at least as large as \c sizeof(type *). + \note \a _size is NOT the number of objects in the + map. It is the number of rows in the map array (each row + has multiple objects). */ #define PR_RESMAP(type) struct { type *_free; type **_map; unsigned _size; } diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index dad2c0c99..608dc8682 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -45,13 +45,16 @@ #include "compat.h" #include "evdev/inputlib.h" -typedef struct { +typedef struct devmap_s { + struct devmap_s *next; + struct devmap_s **prev; device_t *device; int devid; } devmap_t; static int evdev_driver_handle = -1; static PR_RESMAP (devmap_t) devmap; +static devmap_t *devmap_list; static void in_evdev_keydest_callback (keydest_t key_dest, void *data) @@ -119,6 +122,13 @@ device_add (device_t *dev) } devmap_t *dm = PR_RESNEW (devmap); + dm->next = devmap_list; + dm->prev = &devmap_list; + if (devmap_list) { + devmap_list->prev = &dm->next; + } + devmap_list = dm; + dm->device = dev; dm->devid = IN_AddDevice (evdev_driver_handle, dev, name, id); @@ -144,11 +154,15 @@ device_add (device_t *dev) static void device_remove (device_t *dev) { - //Sys_Printf ("in_evdev: remove %s\n", dev->path); - for (unsigned i = 0; i < devmap._size; i++) { - devmap_t *dm = PR_RESGET (devmap, ~i); + for (devmap_t *dm = devmap_list; dm; dm = dm->next) { if (dm->device == dev) { IN_RemoveDevice (dm->devid); + + if (dm->next) { + dm->next->prev = dm->prev; + } + *dm->prev = dm->next; + PR_RESFREE (devmap, dm); break; } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 6babd2963..ca81790ac 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -64,6 +64,8 @@ typedef struct obj_list_s { } obj_list; typedef struct dtable_s { + struct dtable_s *next; + struct dtable_s **prev; size_t size; func_t *imp; } dtable_t; @@ -75,6 +77,7 @@ typedef struct probj_resources_s { obj_list **selector_sels; string_t *selector_names; PR_RESMAP (dtable_t) dtables; + dtable_t *dtable_list; func_t obj_forward; pr_sel_t *forward_selector; dstring_t *msg; @@ -93,7 +96,14 @@ typedef struct probj_resources_s { static dtable_t * dtable_new (probj_t *probj) { - return PR_RESNEW (probj->dtables); + dtable_t *dtable = PR_RESNEW (probj->dtables); + dtable->next = probj->dtable_list; + dtable->prev = &probj->dtable_list; + if (probj->dtable_list) { + probj->dtable_list->prev = &dtable->next; + } + probj->dtable_list = dtable; + return dtable; } static void @@ -2195,14 +2205,8 @@ rua_obj_cleanup (progs_t *pr, void *data) probj->selector_names[i] = 0; } - for (i = 0; i < probj->dtables._size; i++) { - /* dtable_get expects a handle, but a handle is the ones-compliment - * negative of the index. - */ - dtable_t *dtable = dtable_get (probj, ~i); - if (!dtable->imp) { - break; - } + for (dtable_t *dtable = probj->dtable_list; dtable; + dtable = dtable->next) { free (dtable->imp); } dtable_reset (probj); diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index 0a1f4981d..4b276f248 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -18,7 +18,8 @@ #define always_inline inline __attribute__((__always_inline__)) typedef struct editbuffer_s { - void *freenext; // for PR_RESMAP + struct editbuffer_s *next; + struct editbuffer_s **prev; txtbuffer_t *txtbuffer; int modified; int tabSize; @@ -27,17 +28,29 @@ typedef struct editbuffer_s { typedef struct qwaq_ebresources_s { progs_t *pr; PR_RESMAP (editbuffer_t) buffers; + editbuffer_t *buffer_list; } qwaq_ebresources_t; static editbuffer_t * editbuffer_new (qwaq_ebresources_t *res) { - return PR_RESNEW (res->buffers); + editbuffer_t *buffer = PR_RESNEW (res->buffers); + buffer->next = res->buffer_list; + buffer->prev = &res->buffer_list; + if (res->buffer_list) { + res->buffer_list->prev = &buffer->next; + } + res->buffer_list = buffer; + return buffer; } static void editbuffer_free (qwaq_ebresources_t *res, editbuffer_t *buffer) { + if (buffer->next) { + buffer->next->prev = buffer->prev; + } + *buffer->prev = buffer->next; PR_RESFREE (res->buffers, buffer); } @@ -965,12 +978,10 @@ qwaq_ebresources_clear (progs_t *pr, void *data) { __auto_type res = (qwaq_ebresources_t *) data; - for (size_t i = 0; i < res->buffers._size; i++) { - editbuffer_t *buffer = editbuffer_get (res, ~i); - if (buffer->txtbuffer) { - TextBuffer_Destroy (buffer->txtbuffer); - buffer->txtbuffer = 0; - } + for (editbuffer_t *buffer = res->buffer_list; buffer; + buffer = buffer->next) { + TextBuffer_Destroy (buffer->txtbuffer); + buffer->txtbuffer = 0; } editbuffer_reset (res); } From 192b76ddc6a17949167abc8e6f6d66648d8d3aa2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Sep 2021 16:37:38 +0900 Subject: [PATCH 1756/3664] [input] Remove closed device in correct place Removing the device from the devices list after closing the device could cause the device to be double-freed if something went wrong in the device removal callback resulting in system shutdown which would then close all open devices. The device is removed from the list before the callback is called. There's still a small opportunity for such in a multi-threaded environment, but that would take device removal occurring at the same time as the input system is shut down. Probably the responsibility of the threaded environment rather than inputlib. --- include/evdev/inputlib.h | 1 + libs/input/evdev/inputlib.c | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/evdev/inputlib.h b/include/evdev/inputlib.h index 9d8c931e5..9e7e35ea5 100644 --- a/include/evdev/inputlib.h +++ b/include/evdev/inputlib.h @@ -18,6 +18,7 @@ typedef struct { typedef struct device_s { struct device_s *next; + struct device_s **prev; char *path; char *name; char *phys; diff --git a/libs/input/evdev/inputlib.c b/libs/input/evdev/inputlib.c index 9fd854be4..d1bf3d06f 100644 --- a/libs/input/evdev/inputlib.c +++ b/libs/input/evdev/inputlib.c @@ -199,6 +199,10 @@ check_device (const char *path) dev = malloc (sizeof (device_t)); dev->next = devices; + dev->prev = &devices; + if (devices) { + devices->prev = &dev->next; + } devices = dev; dev->path = strdup (path); @@ -355,6 +359,11 @@ inputlib_check_input (void) static void close_device (device_t *dev) { + if (dev->next) { + dev->next->prev = dev->prev; + } + *dev->prev = dev->next; + if (device_remove) { device_remove (dev); } @@ -370,6 +379,7 @@ close_device (device_t *dev) } free (dev->name); free (dev->path); + free (dev); } static char * @@ -428,9 +438,6 @@ device_deleted (const char *name) if (strcmp ((*dev)->path, devname) == 0) { //Sys_Printf ("lost device %s\n", (*dev)->path); close_device (*dev); - device_t *d = *dev; - *dev = (*dev)->next; - free (d); break; } } @@ -482,8 +489,5 @@ inputlib_close (void) inputlib_hotplug_close (); while (devices) { close_device (devices); - device_t *dev = devices; - devices = devices->next; - free (dev); } } From ac25d9f1c138aabfcdb03ae8b0990cf0ce32898d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Sep 2021 10:07:34 +0900 Subject: [PATCH 1757/3664] [qwaq] Fix window closure Now the device windows close properly when an input device is removed. --- ruamoko/qwaq/debugger/localsdata.r | 1 + ruamoko/qwaq/debugger/views/arrayview.r | 1 + ruamoko/qwaq/debugger/views/pointerview.r | 1 + ruamoko/qwaq/debugger/views/structview.r | 1 + ruamoko/qwaq/device/axisview.r | 2 +- ruamoko/qwaq/device/device.h | 2 ++ ruamoko/qwaq/device/device.r | 16 ++++++++++++++-- ruamoko/qwaq/input-app.r | 4 ++++ ruamoko/qwaq/ui/draw.h | 1 + ruamoko/qwaq/ui/group.r | 3 ++- ruamoko/qwaq/ui/textcontext.r | 7 +++++++ ruamoko/qwaq/ui/titlebar.h | 1 + ruamoko/qwaq/ui/titlebar.r | 5 +++++ ruamoko/qwaq/ui/window.r | 8 ++++++++ 14 files changed, 49 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index 8bb251597..8fb34b601 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -52,6 +52,7 @@ free_defs (LocalsData *self) obj_free (data); data = nil; } + [super dealloc]; } -setFunction:(unsigned) fnum diff --git a/ruamoko/qwaq/debugger/views/arrayview.r b/ruamoko/qwaq/debugger/views/arrayview.r index ec1837bc7..0faf2ab1b 100644 --- a/ruamoko/qwaq/debugger/views/arrayview.r +++ b/ruamoko/qwaq/debugger/views/arrayview.r @@ -57,6 +57,7 @@ } obj_free (element_views); obj_free (element_rows); + [super dealloc]; } -draw diff --git a/ruamoko/qwaq/debugger/views/pointerview.r b/ruamoko/qwaq/debugger/views/pointerview.r index 69c44edac..f82c099e3 100644 --- a/ruamoko/qwaq/debugger/views/pointerview.r +++ b/ruamoko/qwaq/debugger/views/pointerview.r @@ -26,6 +26,7 @@ obj_free (ptr_data); } [ptr_view release]; + [super dealloc]; } -draw diff --git a/ruamoko/qwaq/debugger/views/structview.r b/ruamoko/qwaq/debugger/views/structview.r index d0f42cd62..1db4f5fe9 100644 --- a/ruamoko/qwaq/debugger/views/structview.r +++ b/ruamoko/qwaq/debugger/views/structview.r @@ -64,6 +64,7 @@ } obj_free (field_views); obj_free (field_rows); + [super dealloc]; } -draw diff --git a/ruamoko/qwaq/device/axisview.r b/ruamoko/qwaq/device/axisview.r index 621af66b1..8509634cf 100644 --- a/ruamoko/qwaq/device/axisview.r +++ b/ruamoko/qwaq/device/axisview.r @@ -22,7 +22,7 @@ -draw { [super draw]; - [self mvprintf:{0, 0}, "%*.*d", xlen, xlen, axis.value]; + [self mvprintf:{0, 0}, "%*d", xlen, axis.value]; return self; } diff --git a/ruamoko/qwaq/device/device.h b/ruamoko/qwaq/device/device.h index df287b4ce..1e5864706 100644 --- a/ruamoko/qwaq/device/device.h +++ b/ruamoko/qwaq/device/device.h @@ -20,6 +20,8 @@ -updateAxis:(int)axis value:(int)value; -updateButton:(int)button state:(int)state; -(int)devid; +-(string)name; +-(string)id; -redraw; @end diff --git a/ruamoko/qwaq/device/device.r b/ruamoko/qwaq/device/device.r index 9ae04c628..3a8c1e7a0 100644 --- a/ruamoko/qwaq/device/device.r +++ b/ruamoko/qwaq/device/device.r @@ -43,13 +43,15 @@ -(void)dealloc { + [application removeView:window]; + [axis_data release]; + obj_free (device.axes); obj_free (device.buttons); str_free (device.name); str_free (device.id); obj_free (device); - - [application removeView:window]; + [super dealloc]; } -updateAxis:(int)axis value:(int)value @@ -68,6 +70,16 @@ return devid; } +-(string)name +{ + return device.name; +} + +-(string)id +{ + return device.id; +} + -redraw { [axis_view redraw]; diff --git a/ruamoko/qwaq/input-app.r b/ruamoko/qwaq/input-app.r index 550a91f70..3aa3b111b 100644 --- a/ruamoko/qwaq/input-app.r +++ b/ruamoko/qwaq/input-app.r @@ -111,6 +111,7 @@ arp_end (void) Device *device = [Device withDevice:dev id:devid]; [devices addObject:device]; } + event.what = qe_none; break; case qe_dev_rem: for (int i = [devices count]; i-- > 0; ) { @@ -120,6 +121,7 @@ arp_end (void) break; } } + event.what = qe_none; break; case qe_axis: for (int i = [devices count]; i-- > 0; ) { @@ -131,6 +133,7 @@ arp_end (void) break; } } + event.what = qe_none; break; case qe_button: for (int i = [devices count]; i-- > 0; ) { @@ -142,6 +145,7 @@ arp_end (void) break; } } + event.what = qe_none; break; } if (event.what != qe_none) { diff --git a/ruamoko/qwaq/ui/draw.h b/ruamoko/qwaq/ui/draw.h index e9a9e44b5..a271d3c45 100644 --- a/ruamoko/qwaq/ui/draw.h +++ b/ruamoko/qwaq/ui/draw.h @@ -15,6 +15,7 @@ @end @protocol TextContext +- (void) release; - blitFromBuffer: (DrawBuffer *) srcBuffer to: (Point) pos from: (Rect) rect; - clearReact: (Rect) rect; - (Extent) size; diff --git a/ruamoko/qwaq/ui/group.r b/ruamoko/qwaq/ui/group.r index 2e45d3e64..6ba7926ac 100644 --- a/ruamoko/qwaq/ui/group.r +++ b/ruamoko/qwaq/ui/group.r @@ -71,7 +71,9 @@ { int index = [views indexOfObject: view]; if (index != NotFound) { + [views removeObjectAtIndex: index]; if (focused == index) { + focused--; [self selectPrev]; if (focused == index) { focused = -1; @@ -79,7 +81,6 @@ } else if (focused > index) { focused--; } - [views removeObjectAtIndex: index]; if (mouse_within == view) { mouse_within = nil; } diff --git a/ruamoko/qwaq/ui/textcontext.r b/ruamoko/qwaq/ui/textcontext.r index a14f04afd..791f5b693 100644 --- a/ruamoko/qwaq/ui/textcontext.r +++ b/ruamoko/qwaq/ui/textcontext.r @@ -73,6 +73,13 @@ static TextContext *screen; return self; } +-(void)delloc +{ + if (window != stdscr) { + destroy_window (window); + } +} + -(window_t) window { return window; diff --git a/ruamoko/qwaq/ui/titlebar.h b/ruamoko/qwaq/ui/titlebar.h index a3290a20d..0ad8f9f10 100644 --- a/ruamoko/qwaq/ui/titlebar.h +++ b/ruamoko/qwaq/ui/titlebar.h @@ -12,6 +12,7 @@ +(TitleBar *)withTitle:(string)title; -initWithTitle:(string)title; -setTitle:(string)newTitle; +-(string)title; @end #endif//__qwaq_ui_titlebar_h diff --git a/ruamoko/qwaq/ui/titlebar.r b/ruamoko/qwaq/ui/titlebar.r index d6634c2ad..e005fa4cf 100644 --- a/ruamoko/qwaq/ui/titlebar.r +++ b/ruamoko/qwaq/ui/titlebar.r @@ -29,6 +29,11 @@ return self; } +-(string)title +{ + return title; +} + -setOwner: (Group *) owner { [super setOwner: owner]; diff --git a/ruamoko/qwaq/ui/window.r b/ruamoko/qwaq/ui/window.r index b8faf2aba..d12ac974b 100644 --- a/ruamoko/qwaq/ui/window.r +++ b/ruamoko/qwaq/ui/window.r @@ -71,6 +71,14 @@ return self; } +-(void)dealloc +{ + destroy_panel (panel); + [textContext release]; + [objects release]; + [super dealloc]; +} + -updateScreenCursor { window_t window = [(id)textContext window]; From 349f8067c3f8a187d7037b7c0c44f870bc625dcf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Sep 2021 12:03:44 +0900 Subject: [PATCH 1758/3664] [gamecode] Conform with libc malloc for pr zone Allocating 0 bytes returns null and freeing a null pointer is safe. --- libs/gamecode/pr_zone.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/libs/gamecode/pr_zone.c b/libs/gamecode/pr_zone.c index 5b85a7ffd..44f527ffe 100644 --- a/libs/gamecode/pr_zone.c +++ b/libs/gamecode/pr_zone.c @@ -64,22 +64,32 @@ PR_Zone_Init (progs_t *pr) VISIBLE void PR_Zone_Free (progs_t *pr, void *ptr) { - Z_Free (pr->zone, ptr); + if (ptr) { + Z_Free (pr->zone, ptr); + } } VISIBLE void * PR_Zone_Malloc (progs_t *pr, pr_int_t size) { - if (size <= 0) - PR_RunError (pr, "attempt to allocate less than 1 byte"); + if (!size) { + return 0; + } + if (size < 0) { + PR_RunError (pr, "attempt to allocate less than 0 bytes"); + } return Z_Malloc (pr->zone, size); } VISIBLE void * PR_Zone_TagMalloc (progs_t *pr, int size, int tag) { - if (size <= 0) - PR_RunError (pr, "attempt to allocate less than 1 byte"); + if (!size) { + return 0; + } + if (size < 0) { + PR_RunError (pr, "attempt to allocate less than 0 bytes"); + } return Z_TagMalloc (pr->zone, size, tag); } @@ -90,7 +100,11 @@ PR_Zone_Realloc (progs_t *pr, void *ptr, pr_int_t size) Z_Free (pr->zone, ptr); return 0; } - if (size <= 0) - PR_RunError (pr, "attempt to allocate less than 1 byte"); + if (!size) { + return 0; + } + if (size < 0) { + PR_RunError (pr, "attempt to allocate less than 0 bytes"); + } return Z_Realloc (pr->zone, ptr, size); } From 1d86a18eb1ed92226dcb4b790515e343a74f582c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Sep 2021 12:05:16 +0900 Subject: [PATCH 1759/3664] [qwaq] Be paranoid about memcpy and null pointers Although I suspect memcpy does the right thing when the byte count is 0, the man page wasn't explicit and this is more portable. --- ruamoko/qwaq/builtins/input.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 3affcdcc7..5a31d2ffc 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -650,8 +650,12 @@ bi_get_device_info (progs_t *pr) in_axisinfo_t *axes = PR_Zone_Malloc (pr, axis_buffer->size); in_buttoninfo_t *buttons = PR_Zone_Malloc (pr, button_buffer->size); - memcpy (axes, axis_buffer->str, axis_buffer->size); - memcpy (buttons, button_buffer->str, button_buffer->size); + if (axes) { + memcpy (axes, axis_buffer->str, axis_buffer->size); + } + if (buttons) { + memcpy (buttons, button_buffer->str, button_buffer->size); + } devinfo->name = PR_SetDynamicString (pr, name_string->str); devinfo->id = PR_SetDynamicString (pr, id_string->str); From 940d824be0a4d0f62f6819cf890c4b1a05a104c4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Sep 2021 14:54:24 +0900 Subject: [PATCH 1760/3664] [util] Split out the select code to Sys_Select While select itself is fairly portable, it's not super convenient. --- include/QF/sys.h | 2 ++ libs/util/sys.c | 35 ++++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index abf7d4e37..a012062bc 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -37,6 +37,7 @@ #include #include #include +#include extern struct cvar_s *sys_nostdout; extern struct cvar_s *sys_extrasleep; @@ -100,6 +101,7 @@ enum { #include "QF/sys_developer.h" }; +int Sys_Select (int maxfd, fd_set *fdset, int64_t usec); int Sys_CheckInput (int idle, int net_socket); const char *Sys_ConsoleInput (void); diff --git a/libs/util/sys.c b/libs/util/sys.c index 9aad2ee6b..5f1de8986 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -720,13 +720,32 @@ Sys_DebugLog (const char *file, const char *fmt, ...) } } +VISIBLE int +Sys_Select (int maxfd, fd_set *fdset, int64_t usec) +{ + struct timeval _timeout; + struct timeval *timeout = 0; + + if (usec >= 0) { + timeout = &_timeout; + if (usec < 1000000) { + _timeout.tv_sec = 0; + _timeout.tv_usec = usec; + } else { + _timeout.tv_sec = usec / 1000000; + _timeout.tv_usec = usec % 1000000; + } + } + + return select (maxfd + 1, fdset, NULL, NULL, timeout); +} + VISIBLE int Sys_CheckInput (int idle, int net_socket) { fd_set fdset; int res; - struct timeval _timeout; - struct timeval *timeout = 0; + int64_t usec; #ifdef _WIN32 int sleep_msec; @@ -739,11 +758,9 @@ Sys_CheckInput (int idle, int net_socket) Sleep (sleep_msec); } - _timeout.tv_sec = 0; - _timeout.tv_usec = net_socket < 0 ? 0 : 20; + usec = net_socket < 0 ? 0 : 20; #else - _timeout.tv_sec = 0; - _timeout.tv_usec = net_socket < 0 ? 0 : 2000; + usec = net_socket < 0 ? 0 : 2000; #endif // select on the net socket and stdin // the only reason we have a timeout at all is so that if the last @@ -757,10 +774,10 @@ Sys_CheckInput (int idle, int net_socket) if (net_socket >= 0) FD_SET (((unsigned) net_socket), &fdset); // cast needed for windows - if (!idle || !sys_dead_sleep->int_val) - timeout = &_timeout; + if (idle && sys_dead_sleep->int_val) + usec = -1; - res = select (max (net_socket, 0) + 1, &fdset, NULL, NULL, timeout); + res = Sys_Select (max (net_socket, 0), &fdset, usec); if (res == 0 || res == -1) return 0; #ifndef _WIN32 From 7f408351b9db194944c54ba1c12e48bbaab4b175 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Sep 2021 15:11:07 +0900 Subject: [PATCH 1761/3664] [input] Use a single select call for all drivers For drivers that support it. Polling is still supported and forces the select timeout to 0 if any driver requires polling. For now, the default timeout when all drivers use select is 10ms. --- include/QF/input.h | 10 +++++++ include/evdev/inputlib.h | 2 ++ libs/input/evdev/inputlib.c | 55 +++++++++++++++++++++-------------- libs/input/in_common.c | 23 ++++++++++++++- libs/input/in_evdev.c | 14 ++++++--- ruamoko/qwaq/builtins/input.c | 17 +++++++++-- 6 files changed, 91 insertions(+), 30 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 238e342e1..74ce5750b 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -45,6 +45,9 @@ typedef struct in_buttoninfo_s { } in_buttoninfo_t; #ifndef __QFCC__ + +#include + typedef struct { vec3_t angles; vec3_t position; @@ -53,7 +56,14 @@ typedef struct { typedef struct in_driver_s { void (*init) (void *data); void (*shutdown) (void *data); + + // The driver must provide either both or none of add_select and + // chec_select. + void (*add_select) (fd_set *fdset, int *maxfd, void *data); + void (*check_select) (fd_set *fdset, void *data); + // Generally musually exclusive with add_select/check_select void (*process_events) (void *data); + void (*clear_states) (void *data); void (*grab_input) (void *data, int grab); diff --git a/include/evdev/inputlib.h b/include/evdev/inputlib.h index 9e7e35ea5..16f647311 100644 --- a/include/evdev/inputlib.h +++ b/include/evdev/inputlib.h @@ -44,6 +44,8 @@ typedef struct device_s { void (*button_event) (button_t *button, void *data); } device_t; +void inputlib_add_select (fd_set *fdset, int *maxfd); +void inputlib_check_select (fd_set *fdset); int inputlib_check_input (void); void inputlib_close (void); int inputlib_init (void (*dev_add) (device_t *), void (*dev_rem) (device_t *)); diff --git a/libs/input/evdev/inputlib.c b/libs/input/evdev/inputlib.c index d1bf3d06f..3085102b3 100644 --- a/libs/input/evdev/inputlib.c +++ b/libs/input/evdev/inputlib.c @@ -309,6 +309,37 @@ read_device_input (device_t *dev) } } +void +inputlib_add_select (fd_set *fdset, int *maxfd) +{ + inputlib_hotplug_add_select (fdset, maxfd); + + for (device_t *dev = devices; dev; dev = dev->next) { + if (dev->fd < 0) { + continue; + } + FD_SET (dev->fd, fdset); + if (dev->fd > *maxfd) { + *maxfd = dev->fd; + } + } +} + +void +inputlib_check_select (fd_set *fdset) +{ + inputlib_hotplug_check_select (fdset); + + for (device_t *dev = devices; dev; dev = dev->next) { + if (dev->fd < 0) { + continue; + } + if (FD_ISSET (dev->fd, fdset)) { + read_device_input (dev); + } + } +} + int inputlib_check_input (void) { @@ -317,24 +348,13 @@ inputlib_check_input (void) struct timeval *timeout = &_timeout; int res; int maxfd = -1; - device_t *dev; _timeout.tv_sec = 0; _timeout.tv_usec = 0; FD_ZERO (&fdset); - inputlib_hotplug_add_select (&fdset, &maxfd); - - for (dev = devices; dev; dev = dev->next) { - if (dev->fd < 0) { - continue; - } - FD_SET (dev->fd, &fdset); - if (dev->fd > maxfd) { - maxfd = dev->fd; - } - } + inputlib_add_select (&fdset, &maxfd); if (maxfd < 0) { return 0; } @@ -343,16 +363,7 @@ inputlib_check_input (void) return 0; } - inputlib_hotplug_check_select (&fdset); - - for (dev = devices; dev; dev = dev->next) { - if (dev->fd < 0) { - continue; - } - if (FD_ISSET (dev->fd, &fdset)) { - read_device_input (dev); - } - } + inputlib_check_select (&fdset); return 1; } diff --git a/libs/input/in_common.c b/libs/input/in_common.c index fc7f85755..0a90ef7f4 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -77,6 +77,7 @@ cvar_t *in_mouse_amp; cvar_t *in_mouse_pre_amp; cvar_t *lookstrafe; +int64_t in_timeout = 10000;//10ms default timeout kbutton_t in_mlook, in_klook; kbutton_t in_strafe; kbutton_t in_speed; @@ -265,9 +266,29 @@ IN_UpdateGrab (cvar_t *var) // called from context_*.c void IN_ProcessEvents (void) { + fd_set fdset; + int maxfd = -1; + int64_t timeout = in_timeout; + + FD_ZERO (&fdset); for (size_t i = 0; i < in_drivers.size; i++) { in_regdriver_t *rd = &in_drivers.a[i]; - rd->driver.process_events (rd->data); + if (rd->driver.add_select) { + rd->driver.add_select (&fdset, &maxfd, rd->data); + } + if (rd->driver.process_events) { + rd->driver.process_events (rd->data); + // if a driver can't use select, then we can't block in select + timeout = 0; + } + } + if (maxfd >= 0 && Sys_Select (maxfd, &fdset, timeout) > 0) { + for (size_t i = 0; i < in_drivers.size; i++) { + in_regdriver_t *rd = &in_drivers.a[i]; + if (rd->driver.check_select) { + rd->driver.check_select (&fdset, rd->data); + } + } } } diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 608dc8682..9eaad7b92 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -62,10 +62,15 @@ in_evdev_keydest_callback (keydest_t key_dest, void *data) } static void -in_evdev_process_events (void *data) +in_evdev_add_select (fd_set *fdset, int *maxfd, void *data) { - if (inputlib_check_input ()) { - } + inputlib_add_select (fdset, maxfd); +} + +static void +in_evdev_check_select (fd_set *fdset, void *data) +{ + inputlib_check_select (fdset); } static void @@ -223,7 +228,8 @@ in_evdev_button_info (void *data, void *device, in_buttoninfo_t *buttons, static in_driver_t in_evdev_driver = { .init = in_evdev_init, .shutdown = in_evdev_shutdown, - .process_events = in_evdev_process_events, + .add_select = in_evdev_add_select, + .check_select = in_evdev_check_select, .clear_states = in_evdev_clear_states, .axis_info = in_evdev_axis_info, diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 5a31d2ffc..316ae8bf3 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -464,8 +464,18 @@ term_shutdown (void *_res) { } +#define FD 0 static void -term_process_events (void *_res) +term_add_select (fd_set *fdset, int *maxfd, void *_res) +{ + FD_SET (FD, fdset); + if (*maxfd < FD) { + *maxfd = FD; + } +} + +static void +term_check_select (fd_set *fdset, void *_res) { qwaq_input_resources_t *res = _res; char buf[256]; @@ -482,7 +492,7 @@ term_process_events (void *_res) resize_event (res); } #endif - while (Sys_CheckInput (1, -1)) { + if (FD_ISSET (FD, fdset)) { len = read(0, buf, sizeof (buf)); for (int i = 0; i < len; i++) { process_char (res, buf[i]); @@ -493,7 +503,8 @@ term_process_events (void *_res) static in_driver_t term_driver = { .init = term_init, .shutdown = term_shutdown, - .process_events = term_process_events, + .add_select = term_add_select, + .check_select = term_check_select, }; static int term_driver_handle; From 97329527094a913db89a66a119692ef2d6be6f1f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Sep 2021 11:24:35 +0900 Subject: [PATCH 1762/3664] [x11] Use select for checking input It seems that there's always some incoming event anyway (possibly due to the constant screen updates) so it doesn't make much difference currently. --- libs/video/targets/in_x11.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 024847c36..2026158e5 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -87,6 +87,8 @@ static qboolean dga_active; static int p_mouse_x, p_mouse_y; static int input_grabbed = 0; +static int x11_fd; + static void dga_on (void) { @@ -781,9 +783,20 @@ in_x11_grab_input (void *data, int grab) } static void -in_x11_process_events (void *data) +in_x11_add_select (fd_set *fdset, int *maxfd, void *data) { - X11_ProcessEvents (); // Get events from X server. + FD_SET (x11_fd, fdset); + if (*maxfd < x11_fd) { + *maxfd = x11_fd; + } +} + +static void +in_x11_check_select (fd_set *fdset, void *data) +{ + if (FD_ISSET (x11_fd, fdset)) { + X11_ProcessEvents (); // Get events from X server. + } } static void @@ -825,6 +838,8 @@ in_x11_init (void *data) X11_OpenDisplay (); // call to increment the reference counter + x11_fd = ConnectionNumber (x_disp); + { int attribmask = CWEventMask; @@ -870,7 +885,8 @@ in_x11_clear_states (void *data) static in_driver_t in_x11_driver = { .init = in_x11_init, .shutdown = in_x11_shutdown, - .process_events = in_x11_process_events, + .add_select = in_x11_add_select, + .check_select = in_x11_check_select, .clear_states = in_x11_clear_states, .grab_input = in_x11_grab_input, }; From 144a83d761ef857e4a91b0b8487579c4fd1651c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Sep 2021 19:53:16 +0900 Subject: [PATCH 1763/3664] [input] Free phys and uniq device strings Forgot to do so when I added the strings. --- libs/input/evdev/inputlib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/input/evdev/inputlib.c b/libs/input/evdev/inputlib.c index 3085102b3..02a3611f8 100644 --- a/libs/input/evdev/inputlib.c +++ b/libs/input/evdev/inputlib.c @@ -388,6 +388,8 @@ close_device (device_t *dev) if (dev->axes) { free (dev->axes); } + free (dev->phys); + free (dev->uniq); free (dev->name); free (dev->path); free (dev); From 29f8ed388e6ad09da382ecc5aae4717b6997fcac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Sep 2021 19:54:08 +0900 Subject: [PATCH 1764/3664] [x11] Clean up some formatting --- libs/video/targets/in_x11.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 2026158e5..7855728ca 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -196,7 +196,7 @@ enter_notify (XEvent *event) } static void -XLateKey (XKeyEvent * ev, int *k, int *u) +XLateKey (XKeyEvent *ev, int *k, int *u) { char buffer[4]; int unicode; @@ -205,8 +205,7 @@ XLateKey (XKeyEvent * ev, int *k, int *u) XComposeStatus compose; keysym = XLookupKeysym (ev, 0); - XLookupString (ev, buffer, sizeof(buffer), &shifted_keysym, - &compose); + XLookupString (ev, buffer, sizeof(buffer), &shifted_keysym, &compose); unicode = (byte) buffer[0]; switch (keysym) { From cacf0be7f6e1a56e633b98f19b3e194d5cd59f7a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Sep 2021 10:53:51 +0900 Subject: [PATCH 1765/3664] [util] Wrap fd_set While select itself is reasonably portable, it turns out that including the declaration for fd_set makes a bit of a mess for QF's clean headers. --- include/QF/input.h | 12 ++--- include/QF/sys.h | 4 +- include/qfselect.h | 98 +++++++++++++++++++++++++++++++++++ libs/input/in_common.c | 6 ++- libs/input/in_evdev.c | 9 ++-- libs/util/sys.c | 16 +++--- libs/video/targets/in_x11.c | 9 ++-- ruamoko/qwaq/builtins/input.c | 10 ++-- 8 files changed, 135 insertions(+), 29 deletions(-) create mode 100644 include/qfselect.h diff --git a/include/QF/input.h b/include/QF/input.h index 74ce5750b..5f3d3e424 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -46,21 +46,21 @@ typedef struct in_buttoninfo_s { #ifndef __QFCC__ -#include - typedef struct { vec3_t angles; vec3_t position; } viewdelta_t; +struct qf_fd_set; + typedef struct in_driver_s { void (*init) (void *data); void (*shutdown) (void *data); // The driver must provide either both or none of add_select and // chec_select. - void (*add_select) (fd_set *fdset, int *maxfd, void *data); - void (*check_select) (fd_set *fdset, void *data); + void (*add_select) (struct qf_fd_set *fdset, int *maxfd, void *data); + void (*check_select) (struct qf_fd_set *fdset, void *data); // Generally musually exclusive with add_select/check_select void (*process_events) (void *data); @@ -95,8 +95,8 @@ int IN_AddDevice (int driver, void *device, const char *name, const char *id); void IN_RemoveDevice (int devid); void IN_SendConnectedDevices (void); -const char *IN_GetDeviceName (int devid); -const char *IN_GetDeviceId (int devid); +const char *IN_GetDeviceName (int devid) __attribute__((pure)); +const char *IN_GetDeviceId (int devid) __attribute__((pure)); int IN_AxisInfo (int devid, in_axisinfo_t *axes, int *numaxes); int IN_ButtonInfo (int devid, in_buttoninfo_t *button, int *numbuttons); diff --git a/include/QF/sys.h b/include/QF/sys.h index a012062bc..631489d79 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -37,7 +37,6 @@ #include #include #include -#include extern struct cvar_s *sys_nostdout; extern struct cvar_s *sys_extrasleep; @@ -101,7 +100,8 @@ enum { #include "QF/sys_developer.h" }; -int Sys_Select (int maxfd, fd_set *fdset, int64_t usec); +struct qf_fd_set; +int Sys_Select (int maxfd, struct qf_fd_set *fdset, int64_t usec); int Sys_CheckInput (int idle, int net_socket); const char *Sys_ConsoleInput (void); diff --git a/include/qfselect.h b/include/qfselect.h new file mode 100644 index 000000000..14e282d3c --- /dev/null +++ b/include/qfselect.h @@ -0,0 +1,98 @@ +/* + qfselect.h + + select fd_set wrapper + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/09/28 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __qfselect_h +#define __qfselect_h + +#include "config.h" + +#ifdef HAVE_WINDOWS_H +# define mouse_event __hide_mouse_event +# include "winquake.h" +# undef mouse_event +#endif +#ifdef HAVE_SYS_SELECT_H +# include +#endif + +typedef struct qf_fd_set { + fd_set fdset; +} qf_fd_set; + +GNU89INLINE inline void QF_FD_CLR (int fd, qf_fd_set *set); +GNU89INLINE inline int QF_FD_ISSET (int fd, qf_fd_set *set); +GNU89INLINE inline void QF_FD_SET (int fd, qf_fd_set *set); +GNU89INLINE inline void QF_FD_ZERO (qf_fd_set *set); + +#ifndef IMPLEMENT_QFSELECT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +QF_FD_CLR (int fd, qf_fd_set *set) +{ + FD_CLR (fd, &set->fdset); +} + +#ifndef IMPLEMENT_QFSELECT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +QF_FD_ISSET(int fd, qf_fd_set *set) +{ + return FD_ISSET(fd, &set->fdset); +} + +#ifndef IMPLEMENT_QFSELECT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +QF_FD_SET(int fd, qf_fd_set *set) +{ + FD_SET(fd, &set->fdset); +} + +#ifndef IMPLEMENT_QFSELECT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +QF_FD_ZERO(qf_fd_set *set) +{ + FD_ZERO(&set->fdset); +} + +#endif//__qfselect_h diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 0a90ef7f4..093e472e2 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -58,6 +58,8 @@ #include "QF/sys.h" #include "QF/vid.h" +#include "qfselect.h" + typedef struct { in_driver_t driver; void *data; @@ -266,11 +268,11 @@ IN_UpdateGrab (cvar_t *var) // called from context_*.c void IN_ProcessEvents (void) { - fd_set fdset; + qf_fd_set fdset; int maxfd = -1; int64_t timeout = in_timeout; - FD_ZERO (&fdset); + QF_FD_ZERO (&fdset); for (size_t i = 0; i < in_drivers.size; i++) { in_regdriver_t *rd = &in_drivers.a[i]; if (rd->driver.add_select) { diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 9eaad7b92..95ae1a82d 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -43,6 +43,7 @@ #include "QF/sys.h" #include "compat.h" +#include "qfselect.h" #include "evdev/inputlib.h" typedef struct devmap_s { @@ -62,15 +63,15 @@ in_evdev_keydest_callback (keydest_t key_dest, void *data) } static void -in_evdev_add_select (fd_set *fdset, int *maxfd, void *data) +in_evdev_add_select (qf_fd_set *fdset, int *maxfd, void *data) { - inputlib_add_select (fdset, maxfd); + inputlib_add_select (&fdset->fdset, maxfd); } static void -in_evdev_check_select (fd_set *fdset, void *data) +in_evdev_check_select (qf_fd_set *fdset, void *data) { - inputlib_check_select (fdset); + inputlib_check_select (&fdset->fdset); } static void diff --git a/libs/util/sys.c b/libs/util/sys.c index 5f1de8986..a08a3350b 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -89,6 +89,8 @@ #include "QF/va.h" #include "compat.h" +#define IMPLEMENT_QFSELECT_Funcs +#include "qfselect.h" static void Sys_StdPrintf (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); static void Sys_ErrPrintf (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); @@ -721,7 +723,7 @@ Sys_DebugLog (const char *file, const char *fmt, ...) } VISIBLE int -Sys_Select (int maxfd, fd_set *fdset, int64_t usec) +Sys_Select (int maxfd, qf_fd_set *fdset, int64_t usec) { struct timeval _timeout; struct timeval *timeout = 0; @@ -737,13 +739,13 @@ Sys_Select (int maxfd, fd_set *fdset, int64_t usec) } } - return select (maxfd + 1, fdset, NULL, NULL, timeout); + return select (maxfd + 1, &fdset->fdset, NULL, NULL, timeout); } VISIBLE int Sys_CheckInput (int idle, int net_socket) { - fd_set fdset; + qf_fd_set fdset; int res; int64_t usec; @@ -766,13 +768,13 @@ Sys_CheckInput (int idle, int net_socket) // the only reason we have a timeout at all is so that if the last // connected client times out, the message would not otherwise // be printed until the next event. - FD_ZERO (&fdset); + QF_FD_ZERO (&fdset); #ifndef _WIN32 if (do_stdin) - FD_SET (0, &fdset); + QF_FD_SET (0, &fdset); #endif if (net_socket >= 0) - FD_SET (((unsigned) net_socket), &fdset); // cast needed for windows + QF_FD_SET (((unsigned) net_socket), &fdset);// cast needed for windows if (idle && sys_dead_sleep->int_val) usec = -1; @@ -781,7 +783,7 @@ Sys_CheckInput (int idle, int net_socket) if (res == 0 || res == -1) return 0; #ifndef _WIN32 - stdin_ready = FD_ISSET (0, &fdset); + stdin_ready = QF_FD_ISSET (0, &fdset); #endif return 1; } diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 7855728ca..39eaf89bd 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -76,6 +76,7 @@ #include "compat.h" #include "context_x11.h" #include "dga_check.h" +#include "qfselect.h" #include "vid_internal.h" cvar_t *in_snd_block; @@ -782,18 +783,18 @@ in_x11_grab_input (void *data, int grab) } static void -in_x11_add_select (fd_set *fdset, int *maxfd, void *data) +in_x11_add_select (qf_fd_set *fdset, int *maxfd, void *data) { - FD_SET (x11_fd, fdset); + QF_FD_SET (x11_fd, fdset); if (*maxfd < x11_fd) { *maxfd = x11_fd; } } static void -in_x11_check_select (fd_set *fdset, void *data) +in_x11_check_select (qf_fd_set *fdset, void *data) { - if (FD_ISSET (x11_fd, fdset)) { + if (QF_FD_ISSET (x11_fd, fdset)) { X11_ProcessEvents (); // Get events from X server. } } diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 316ae8bf3..cad843d86 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -51,6 +51,8 @@ #include "QF/keys.h" #include "QF/sys.h" +#include "qfselect.h" + #include "ruamoko/qwaq/qwaq.h" #include "ruamoko/qwaq/qwaq-input.h" #include "ruamoko/qwaq/ui/event.h" @@ -466,16 +468,16 @@ term_shutdown (void *_res) #define FD 0 static void -term_add_select (fd_set *fdset, int *maxfd, void *_res) +term_add_select (qf_fd_set *fdset, int *maxfd, void *_res) { - FD_SET (FD, fdset); + QF_FD_SET (FD, fdset); if (*maxfd < FD) { *maxfd = FD; } } static void -term_check_select (fd_set *fdset, void *_res) +term_check_select (qf_fd_set *fdset, void *_res) { qwaq_input_resources_t *res = _res; char buf[256]; @@ -492,7 +494,7 @@ term_check_select (fd_set *fdset, void *_res) resize_event (res); } #endif - if (FD_ISSET (FD, fdset)) { + if (QF_FD_ISSET (FD, fdset)) { len = read(0, buf, sizeof (buf)); for (int i = 0; i < len; i++) { process_char (res, buf[i]); From 7fcf6bfef5f154cac306d1ce6aeac56db998ec52 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Sep 2021 10:57:12 +0900 Subject: [PATCH 1766/3664] [build] Autoconfiscate evdev --- config.d/build_control.m4 | 1 + config.d/evdev.m4 | 7 +++++++ configure.ac | 1 + libs/input/Makemodule.am | 13 ++++++++++++- libs/input/in_common.c | 2 ++ 5 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 config.d/evdev.m4 diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 5564ea8af..641e1b1f5 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -356,6 +356,7 @@ QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush]) QF_PROCESS_NEED_LIBS(iqm, [gl glsl sw vulkan], [libs/models/iqm]) QF_PROCESS_NEED_LIBS(sprite, [gl glsl sw vulkan], [libs/models/sprite]) +QF_PROCESS_NEED_LIBS(input, [evdev], [libs/input]) QF_PROCESS_NEED_LIBS(vid, [common sdl svga win x11], [libs/video/targets]) QF_PROCESS_NEED_LIBS(qw, [client common sdl win server], [qw/source], a) QF_PROCESS_NEED_LIBS(nq, [client common sdl win server], [nq/source], a) diff --git a/config.d/evdev.m4 b/config.d/evdev.m4 new file mode 100644 index 000000000..643fb9e76 --- /dev/null +++ b/config.d/evdev.m4 @@ -0,0 +1,7 @@ +dnl ================================================================== +dnl Checks for evdev +dnl ================================================================== + +AC_CHECK_HEADER(linux/input.h, + [QF_NEED(input,[evdev]) + AC_DEFINE([HAVE_EVDEV], [1], [Define if you have evdev])]) diff --git a/configure.ac b/configure.ac index 905115d20..17ad222cf 100644 --- a/configure.ac +++ b/configure.ac @@ -111,6 +111,7 @@ AC_SUBST(WIN32_LIBS) m4_include(config.d/sound.m4) m4_include(config.d/joystick.m4) +m4_include(config.d/evdev.m4) m4_include(config.d/cdrom.m4) m4_include(config.d/networking.m4) diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index 431857161..c74f6c998 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -1,16 +1,27 @@ lib_LTLIBRARIES += libs/input/libQFinput.la +noinst_LTLIBRARIES += @input_libs@ + +input_deps = @input_libs@ in_evdev_src= \ libs/input/evdev/hotplug.c \ libs/input/evdev/inputlib.c \ libs/input/in_evdev.c +libs_input_libinput_evdev_la_LDFLAGS= $(lib_ldflags) +libs_input_libinput_evdev_la_LIBADD= +libs_input_libinput_evdev_la_DEPENDENCIES= +libs_input_libinput_evdev_la_CFLAGS= +libs_input_libinput_evdev_la_SOURCES= $(in_evdev_src) + libs_input_libQFinput_la_LDFLAGS= $(lib_ldflags) libs_input_libQFinput_la_LIBADD= $(input_deps) libs_input_libQFinput_la_DEPENDENCIES= $(input_deps) libs_input_libQFinput_la_SOURCES= \ - $(in_evdev_src) \ libs/input/keys.c \ libs/input/old_keys.c \ libs/input/in_common.c \ libs/input/in_event.c + +EXTRA_LTLIBRARIES += \ + libs/input/libinput_evdev.la diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 093e472e2..c31f117d0 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -395,5 +395,7 @@ IN_ClearStates (void) Key_ClearStates (); } +#ifdef HAVE_EVDEV extern int in_evdev_force_link; static __attribute__((used)) int *evdev_force_link = &in_evdev_force_link; +#endif From c6a073c1f3e9955f42dd371b803252e586b5c618 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Sep 2021 12:48:47 +0900 Subject: [PATCH 1767/3664] [win] Hook up windows input Not sure it actually works yet (can't test right now), but since the x11 switch-over worked, it should. --- libs/video/targets/context_win.c | 3 +++ libs/video/targets/in_win.c | 43 +++++++++++++++++++------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index 59bd56096..f58ec9d1c 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -1078,3 +1078,6 @@ Win_Init_Cvars (void) Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f, ""); Cmd_AddCommand ("vid_minimize", VID_Minimize_f, ""); } + +extern int win_force_link; +static __attribute__((used)) int *context_win_force_link = &win_force_link; diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index aad54f42b..d523598b6 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -360,8 +360,8 @@ win_keydest_callback (keydest_t key_dest, void *data) } } -void -IN_LL_Init (void) +static void +in_win_init (void *data) { uiWheelMessage = RegisterWindowMessage ("MSWHEEL_ROLLMSG"); @@ -372,13 +372,8 @@ IN_LL_Init (void) "Paste the contents of the C&P buffer to the console"); } -void -IN_LL_Init_Cvars (void) -{ -} - -void -IN_LL_Shutdown (void) +static void +in_win_shutdown (void *data) { IN_DeactivateMouse (); @@ -416,13 +411,8 @@ IN_MouseEvent (unsigned mstate) } } -void -IN_LL_Grab_Input (int grab) -{ -} - -void -IN_LL_ClearStates (void) +static void +in_win_clear_states (void *data) { if (in_mouse_avail) { mx_accum = 0; @@ -431,8 +421,8 @@ IN_LL_ClearStates (void) } } -void -IN_LL_ProcessEvents (void) +static void +in_win_process_events (void *data) { MSG msg; int mx, my; @@ -881,3 +871,20 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) /* return 1 if handled message, 0 if not */ return lRet; } + +static in_driver_t in_win_driver = { + .init = in_win_init, + .shutdown = in_win_shutdown, + .process_events = in_win_process_events, + .clear_states = in_win_clear_states, + //.grab_input = in_win_grab_input, +}; + +static void __attribute__((constructor)) +in_win_register_driver (void) +{ + IN_RegisterDriver (&in_win_driver, 0); +} + + +int win_force_link; From fed8f66824ea6f7931110ddb3427ec47e047d7c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Oct 2021 09:16:31 +0900 Subject: [PATCH 1768/3664] [input] Rework logical buttons kbutton_t is now in_button_t and has been moved to input.h. Also, a button registration function has been added to take care of +button and -button command creation and, eventually, direct binding of "physical" buttons to logical buttons. "Physical" buttons are those coming in from the OS (keyboard, mouse, joystick...), logical buttons are what the code looks at for button state. Additionally, the button edge detection code has been cleaned up such that it no longer uses magic numbers, and the conversion to a float is cleaner. Interestingly, I found that the handling is extremely frame-rate dependent (eg, +forward will accelerate the player to full speed much faster at 72fps than it does at 20fps). This may be a factor in why gamers are frame rate obsessed: other games doing the same thing would certainly feel different under varying frame rates. --- include/QF/in_event.h | 9 +- include/QF/input.h | 119 +++++++++++++- include/QF/keys.h | 5 - libs/input/Makemodule.am | 1 + libs/input/in_button.c | 185 +++++++++++++++++++++ libs/input/in_common.c | 7 +- nq/include/client.h | 10 +- nq/source/cl_chase.c | 12 +- nq/source/cl_input.c | 333 +++++++++++--------------------------- qw/include/cl_input.h | 10 +- qw/source/cl_chase.c | 12 +- qw/source/cl_input.c | 340 +++++++++++---------------------------- 12 files changed, 527 insertions(+), 516 deletions(-) create mode 100644 libs/input/in_button.c diff --git a/include/QF/in_event.h b/include/QF/in_event.h index 31ec88f46..1f960bda8 100644 --- a/include/QF/in_event.h +++ b/include/QF/in_event.h @@ -32,16 +32,15 @@ #define __QF_in_event_h #include "QF/qtypes.h" -#include "QF/joystick.h" // needed for JOY_MAX_AXES typedef struct { - int x, y; - unsigned int buttons; + int x, y; + unsigned buttons; } IE_mouse_event_t; typedef struct { - int key_code; - qboolean pressed; + int key_code; + qboolean pressed; } IE_key_event_t; typedef struct { diff --git a/include/QF/input.h b/include/QF/input.h index 5f3d3e424..c46819981 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -80,6 +80,120 @@ typedef struct in_device_s { const char *id; } in_device_t; +/*** Current state of the button. + + Captures the current state and any transitions during the last frame. + Not all combinations are valid (inb_edge_up|inb_down and inb_edge_down + (no inb_down) are not valid states), but inb_edge_up|inb_edge_down )with + or without inb_down) is valid as it represents a double transition during + the frame. +*/ +typedef enum { + inb_down = 1<<0, ///< button is held + inb_edge_down = 1<<1, ///< button pressed this frame + inb_edge_up = 1<<2, ///< button released this frame +} in_button_state; + +typedef struct in_button_s { + int down[2]; ///< button ids holding this button down + int state; ///< in_button_state +} in_button_t; + +/*** Represent the button's activity in the last frame as a float. + + The detected activity is: + steady off (up) + steady on (down) + off to on (up to down) transition + on to off )down to up) transition + pulse on (off-on-off or up-down-up) + pulse off (on-off-on or down-up-down) + Any additional transitions are treated as a pulse appropriate for the + final state of the button. + + \param button Pointer to the button being tested. + \return Float value between 0 (off/up) and 1 (on/down) + \note The edge transitions are cleared, so for each frame, this + is a one-shot function (ie, it is NOT idempotent). +*/ +GNU89INLINE inline float IN_ButtonState (in_button_t *button); + +/*** Test whether a button has been pressed in the last frame. + + Both steady-state on, and brief clicks are detected. + + \return True if the button is currently held or was pulsed on + in the last frame. + \note The edge transitions are cleared, so for each frame, this + is a one-shot function (ie, it is NOT idempotent). +*/ +GNU89INLINE inline int IN_ButtonPressed (in_button_t *button); + +/*** Test whether a button was released in the last frame. + + Valid only if the button is still released. A pulsed off does not + count as being released as the button is still held. + + \return True if the button is currently released and the release + was in the last frame. + \note The edge transitions are cleared, so for each frame, this + is a one-shot function (ie, it is NOT idempotent). +*/ +GNU89INLINE inline int IN_ButtonReleased (in_button_t *button); + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +float +IN_ButtonState (in_button_t *button) +{ + static const float state_values[8] = { + // held down for the entire frame + [inb_down] = 1, + // released this frame + [inb_edge_up] = 0, // instant falloff + // pressed this frame + [inb_edge_down|inb_down] = 0.5, + // pressed and released this frame + [inb_edge_down|inb_edge_up] = 0.25, + // released and pressed this frame + [inb_edge_down|inb_edge_up|inb_down] = 0.75, + }; + int state = button->state; + button->state &= inb_down; // clear edges, preserve pressed + return state_values[state & (inb_down|inb_edge_down|inb_edge_up)]; +} + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +IN_ButtonPressed (in_button_t *button) +{ + int state = button->state; + button->state &= inb_down; // clear edges, preserve pressed + // catch even press and release that occurs between frames + return (state & (inb_down | inb_edge_down)) != 0; +} + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +IN_ButtonReleased (in_button_t *button) +{ + int state = button->state; + button->state &= inb_down; // clear edges, preserve pressed + // catch only full release (a pulsed on does count as a release) + return (state & (inb_down | inb_edge_up)) == inb_edge_up; +} + extern viewdelta_t viewdelta; #define freelook (in_mlook.state & 1 || in_freelook->int_val) @@ -106,6 +220,9 @@ void IN_UpdateGrab (struct cvar_s *); void IN_ClearStates (void); +int IN_RegisterButton (in_button_t *button, const char *name, + const char *description); + void IN_Move (void); // FIXME: was cmduser_t? // add additional movement on top of the keyboard move cmd @@ -121,7 +238,7 @@ extern qboolean in_mouse_avail; extern float in_mouse_x, in_mouse_y; -extern kbutton_t in_strafe, in_klook, in_speed, in_mlook; +extern in_button_t in_strafe, in_klook, in_speed, in_mlook; #endif #endif//__QF_input_h diff --git a/include/QF/keys.h b/include/QF/keys.h index 0159d80bc..3919eebc3 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -532,11 +532,6 @@ typedef enum { } keydest_t; #ifndef __QFCC__ -typedef struct { - int down[2]; // key nums holding it down - int state; // low bit is down state -} kbutton_t; - extern knum_t key_toggleconsole; typedef struct keybind_s { diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index c74f6c998..e160f456f 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -20,6 +20,7 @@ libs_input_libQFinput_la_DEPENDENCIES= $(input_deps) libs_input_libQFinput_la_SOURCES= \ libs/input/keys.c \ libs/input/old_keys.c \ + libs/input/in_button.c \ libs/input/in_common.c \ libs/input/in_event.c diff --git a/libs/input/in_button.c b/libs/input/in_button.c new file mode 100644 index 000000000..027f868ba --- /dev/null +++ b/libs/input/in_button.c @@ -0,0 +1,185 @@ +/* + in_button.c + + Logical button support + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/09/29 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cmd.h" +#include "QF/hash.h" +#include "QF/input.h" +#include "QF/sys.h" + +typedef struct regbutton_s { + const char *name; + const char *description; + in_button_t *button; + char *press_cmd; + char *release_cmd; +} regbutton_t; + +static hashtab_t *button_tab; + +static const char * +button_get_key (const void *b, void *data) +{ + __auto_type regbutton = (const regbutton_t *) b; + return regbutton->name; +} + +static void +button_free (void *b, void *data) +{ + free (b); +} + +static void +button_press (in_button_t *button, int id) +{ + if (id == button->down[0] || id == button->down[1]) { + // repeating key + return; + } + + if (!button->down[0]) { + button->down[0] = id; + } else if (!button->down[1]) { + button->down[1] = id; + } else { + Sys_Printf ("Three keys down for a button!\n"); + return; + } + + if (button->state & inb_down) { + // still down + return; + } + button->state |= inb_down | inb_edge_down; +} + +static void +button_release (in_button_t *button, int id) +{ + if (id == -1) { + // typed manually at the console, assume for unsticking, so clear all + button->down[0] = button->down[1] = 0; + button->state = inb_edge_up; + return; + } + + if (button->down[0] == id) { + button->down[0] = 0; + } else if (button->down[1] == id) { + button->down[1] = 0; + } else { + // key up without coresponding down (menu pass through) + return; + } + if (button->down[0] || button->down[1]) { + // some other key is still holding it down + return; + } + + if (!(button->state & inb_down)) { + // still up (this should not happen) + return; + } + button->state &= ~inb_down; // now up + button->state |= inb_edge_up; +} + +static void +button_press_cmd (void *_b) +{ + in_button_t *button = _b; + const char *idstr = Cmd_Argv (1); + // assume typed manually at the console for continuous down + int id = -1; + + if (idstr[0]) { + id = atoi (idstr); + } + button_press (button, id); +} + +static void +button_release_cmd (void *_b) +{ + in_button_t *button = _b; + const char *idstr = Cmd_Argv (1); + // assume typed manually at the console, probably for unsticking + int id = -1; + + if (idstr[0]) { + id = atoi (idstr); + } + button_release (button, id); +} + +VISIBLE int +IN_RegisterButton (in_button_t *button, const char *name, + const char *description) +{ + if (Hash_Find (button_tab, name)) { + return 0; + } + size_t size = strlen (name) + 2; + regbutton_t *regbutton = malloc (sizeof (regbutton_t) + 2 * size); + regbutton->name = name; + regbutton->description = description; + regbutton->button = button; + + regbutton->press_cmd = (char *) (regbutton + 1); + regbutton->release_cmd = regbutton->press_cmd + size; + *regbutton->press_cmd = '+'; + *regbutton->release_cmd = '-'; + strcpy (regbutton->press_cmd + 1, name); + strcpy (regbutton->release_cmd + 1, name); + + Cmd_AddDataCommand (regbutton->press_cmd, button_press_cmd, button, + "Set the button's state to on/pressed."); + Cmd_AddDataCommand (regbutton->release_cmd, button_release_cmd, button, + "Set the button's state to on/pressed."); + + return 1; +} + +static void __attribute__((constructor)) +in_evdev_register_driver (void) +{ + button_tab = Hash_NewTable (127, button_get_key, button_free, 0, 0); +} diff --git a/libs/input/in_common.c b/libs/input/in_common.c index c31f117d0..07dcf2d66 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -51,6 +51,7 @@ #include "QF/cvar.h" #include "QF/darray.h" #include "QF/in_event.h" +#define IMPLEMENT_INPUT_Funcs #include "QF/input.h" #include "QF/joystick.h" #include "QF/keys.h" @@ -80,9 +81,6 @@ cvar_t *in_mouse_pre_amp; cvar_t *lookstrafe; int64_t in_timeout = 10000;//10ms default timeout -kbutton_t in_mlook, in_klook; -kbutton_t in_strafe; -kbutton_t in_speed; qboolean in_mouse_avail; float in_mouse_x, in_mouse_y; @@ -315,7 +313,7 @@ IN_Move (void) in_mouse_x *= in_mouse_amp->value * in_amp->value; in_mouse_y *= in_mouse_amp->value * in_amp->value; - +#if 0 if ((in_strafe.state & 1) || (lookstrafe->int_val && freelook)) viewdelta.position[0] += in_mouse_x; else @@ -326,6 +324,7 @@ IN_Move (void) } else { viewdelta.position[2] -= in_mouse_y; } +#endif in_mouse_x = in_mouse_y = 0.0; } diff --git a/nq/include/client.h b/nq/include/client.h index a00b94890..5f58349e3 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -307,8 +307,6 @@ int CL_ReadFromServer (void); void CL_WriteToServer (usercmd_t *cmd); void CL_BaseMove (usercmd_t *cmd); -float CL_KeyState (kbutton_t *key); - // cl_demo.c void CL_StopPlayback (void); void CL_StopRecording (void); @@ -341,10 +339,10 @@ void CL_SignonReply (void); void CL_RelinkEntities (void); void CL_ClearEnts (void); -extern kbutton_t in_left, in_right, in_forward, in_back; -extern kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -extern kbutton_t in_use, in_jump, in_attack; -extern kbutton_t in_up, in_down; +extern in_button_t in_left, in_right, in_forward, in_back; +extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +extern in_button_t in_use, in_jump, in_attack; +extern in_button_t in_up, in_down; extern double realtime; diff --git a/nq/source/cl_chase.c b/nq/source/cl_chase.c index 6f0c430c6..151a1d739 100644 --- a/nq/source/cl_chase.c +++ b/nq/source/cl_chase.c @@ -192,16 +192,16 @@ Chase_Update (void) // VectorCopy (cl.viewstate.angles, cmd.angles); if (in_strafe.state & 1) { - cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_right); - cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_left); + cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); + cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); } - cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright); - cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft); + cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); + cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); if (!(in_klook.state & 1)) { cmd.forwardmove += cl_forwardspeed->value - * CL_KeyState (&in_forward); - cmd.forwardmove -= cl_backspeed->value * CL_KeyState (&in_back); + * IN_ButtonState (&in_forward); + cmd.forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); } if (in_speed.state & 1) { cmd.forwardmove *= cl_movespeedkey->value; diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 58787e7e7..c480700e1 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -67,144 +67,83 @@ state bit 2 is edge triggered on the down to up transition */ -kbutton_t in_left, in_right, in_forward, in_back; -kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -kbutton_t in_use, in_jump, in_attack; -kbutton_t in_up, in_down; +in_button_t in_left, in_right, in_forward, in_back; +in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +in_button_t in_use, in_jump, in_attack; +in_button_t in_up, in_down; +in_button_t in_strafe, in_klook, in_speed, in_mlook; + +static struct { + const char *name; + in_button_t *button; + const char *description; +} cl_in_buttons[] = { + { "left", &in_left, + "When active the player is turning left" + }, + { "right", &in_right, + "When active the player is turning right" + }, + { "forward", &in_forward, + "When active the player is moving forward" + }, + { "back", &in_back, + "When active the player is moving backwards" + }, + { "lookup", &in_lookup, + "When active the player's view is looking up" + }, + { "lookdown", &in_lookdown, + "When active the player's view is looking down" + }, + { "moveleft", &in_moveleft, + "When active the player is strafing left" + }, + { "moveright", &in_moveright, + "When active the player is strafing right" + }, + { "use", &in_use, + "Left over command for opening doors and triggering switches" + }, + { "jump", &in_jump, + "When active the player is jumping" + }, + { "attack", &in_attack, + "When active player is firing/using current weapon" + }, + { "moveup", &in_up, + "When active the player is swimming up in a liquid" + }, + { "movedown", &in_down, + "When active the player is swimming down in a liquid" + }, + { "strafe", &in_strafe, + "When active, +left and +right function like +moveleft and +moveright" + }, + { "speed", &in_speed, + "When active the player is running" + }, + { "klook", &in_klook, + "When active, +forward and +back perform +lookup and +lookdown" + }, + { "mlook", &in_mlook, + "When active moving the mouse or joystick forwards " + "and backwards performs +lookup and " + "+lookdown" + }, + { } +}; int in_impulse; void (*write_angles) (sizebuf_t *sb, const vec3_t angles); -static void -KeyPress (void *_b) -{ - kbutton_t *b = _b; - const char *c; - int k; - - c = Cmd_Argv (1); - if (c[0]) - k = atoi (c); - else - k = -1; // typed manually at the console for - // continuous down - - if (k == b->down[0] || k == b->down[1]) - return; // repeating key - - if (!b->down[0]) - b->down[0] = k; - else if (!b->down[1]) - b->down[1] = k; - else { - Sys_Printf ("Three keys down for a button!\n"); - return; - } - - if (b->state & 1) - return; // still down - b->state |= 1 + 2; // down + impulse down -} - -static void -KeyRelease (void *_b) -{ - kbutton_t *b = _b; - const char *c; - int k; - - c = Cmd_Argv (1); - if (c[0]) - k = atoi (c); - else { // typed manually at the console, - // assume for unsticking, so clear - // all - b->down[0] = b->down[1] = 0; - b->state = 4; // impulse up - return; - } - - if (b->down[0] == k) - b->down[0] = 0; - else if (b->down[1] == k) - b->down[1] = 0; - else - return; // key up without coresponding down - // (menu pass through) - if (b->down[0] || b->down[1]) - return; // some other key is still holding it - // down - - if (!(b->state & 1)) - return; // still up (this should not happen) - b->state &= ~1; // now up - b->state |= 4; // impulse up -} - -static void -IN_MLookRelease (void *data) -{ - KeyRelease (&in_mlook); - if (!freelook && lookspring->int_val) - V_StartPitchDrift (); -} - static void IN_Impulse (void *data) { in_impulse = atoi (Cmd_Argv (1)); } -/* - CL_KeyState - - Returns 0.25 if a key was pressed and released during the frame, - 0.5 if it was pressed and held - 0 if held then released, and - 1.0 if held for the entire time -*/ -float -CL_KeyState (kbutton_t *key) -{ - float val; - qboolean impulsedown, impulseup, down; - - impulsedown = key->state & 2; - impulseup = key->state & 4; - down = key->state & 1; - val = 0; - - if (impulsedown && !impulseup) { - if (down) - val = 0.5; // pressed and held this frame - else - val = 0; // I_Error (); - } - if (impulseup && !impulsedown) { - if (down) - val = 0; // I_Error (); - else - val = 0; // released this frame - } - if (!impulsedown && !impulseup) { - if (down) - val = 1.0; // held the entire frame - else - val = 0; // up the entire frame - } - if (impulsedown && impulseup) { - if (down) - val = 0.75; // released and re-pressed this frame - else - val = 0.25; // pressed and released this frame - } - - key->state &= 1; // clear impulses - - return val; -} - cvar_t *cl_anglespeedkey; cvar_t *cl_backspeed; cvar_t *cl_forwardspeed; @@ -228,7 +167,7 @@ CL_AdjustAngles (void) pitchspeed = cl_pitchspeed->value; yawspeed = cl_yawspeed->value; - if (in_speed.state & 1) { + if (in_speed.state & inb_down) { pitchspeed *= cl_anglespeedkey->value; yawspeed *= cl_anglespeedkey->value; } @@ -241,19 +180,19 @@ CL_AdjustAngles (void) pitchspeed *= host_frametime; yawspeed *= host_frametime; - if (!(in_strafe.state & 1)) { - cl.viewstate.angles[YAW] -= yawspeed * CL_KeyState (&in_right); - cl.viewstate.angles[YAW] += yawspeed * CL_KeyState (&in_left); + if (!(in_strafe.state & inb_down)) { + cl.viewstate.angles[YAW] -= yawspeed * IN_ButtonState (&in_right); + cl.viewstate.angles[YAW] += yawspeed * IN_ButtonState (&in_left); cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); } - if (in_klook.state & 1) { + if (in_klook.state & inb_down) { V_StopPitchDrift (); - cl.viewstate.angles[PITCH] -= pitchspeed * CL_KeyState (&in_forward); - cl.viewstate.angles[PITCH] += pitchspeed * CL_KeyState (&in_back); + cl.viewstate.angles[PITCH] -= pitchspeed * IN_ButtonState (&in_forward); + cl.viewstate.angles[PITCH] += pitchspeed * IN_ButtonState (&in_back); } - up = CL_KeyState (&in_lookup); - down = CL_KeyState (&in_lookdown); + up = IN_ButtonState (&in_lookup); + down = IN_ButtonState (&in_lookdown); cl.viewstate.angles[PITCH] -= pitchspeed * up; cl.viewstate.angles[PITCH] += pitchspeed * down; @@ -281,6 +220,10 @@ CL_AdjustAngles (void) void CL_BaseMove (usercmd_t *cmd) { + if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring->int_val) { + V_StartPitchDrift (); + } + if (cls.state != ca_active) { return; } @@ -289,24 +232,24 @@ CL_BaseMove (usercmd_t *cmd) memset (cmd, 0, sizeof (*cmd)); - if (in_strafe.state & 1) { - cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right); - cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left); + if (in_strafe.state & inb_down) { + cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); + cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); } - cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright); - cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft); + cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); + cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); - cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up); - cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down); + cmd->upmove += cl_upspeed->value * IN_ButtonState (&in_up); + cmd->upmove -= cl_upspeed->value * IN_ButtonState (&in_down); - if (!(in_klook.state & 1)) { - cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward); - cmd->forwardmove -= cl_backspeed->value * CL_KeyState (&in_back); + if (!(in_klook.state & inb_down)) { + cmd->forwardmove += cl_forwardspeed->value * IN_ButtonState (&in_forward); + cmd->forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); } // adjust for speed key - if (in_speed.state & 1) { + if (in_speed.state & inb_down) { cmd->forwardmove *= cl_movespeedkey->value; cmd->sidemove *= cl_movespeedkey->value; cmd->upmove *= cl_movespeedkey->value; @@ -347,7 +290,7 @@ CL_BaseMove (usercmd_t *cmd) cl.viewstate.angles[YAW] += viewdelta.angles[YAW] * m_yaw->value; cl.viewstate.angles[ROLL] += viewdelta.angles[ROLL]; - if (freelook && !(in_strafe.state & 1)) { + if (freelook && !(in_strafe.state & inb_down)) { cl.viewstate.angles[PITCH] = bound (-70, cl.viewstate.angles[PITCH], 80); } @@ -381,13 +324,9 @@ CL_SendMove (usercmd_t *cmd) // send button bits bits = 0; - if (in_attack.state & 3) - bits |= 1; - in_attack.state &= ~2; - - if (in_jump.state & 3) - bits |= 2; - in_jump.state &= ~2; + bits |= IN_ButtonPressed (&in_attack) << 0; + bits |= IN_ButtonPressed (&in_jump) << 1; + bits |= IN_ButtonPressed (&in_use) << 2; MSG_WriteByte (&buf, bits); @@ -412,86 +351,10 @@ CL_SendMove (usercmd_t *cmd) void CL_Input_Init (void) { - Cmd_AddDataCommand ("+moveup", KeyPress, &in_up, - "When active the player is swimming up in a liquid"); - Cmd_AddDataCommand ("-moveup", KeyRelease, &in_up, - "When active the player is not swimming up in a " - "liquid"); - Cmd_AddDataCommand ("+movedown", KeyPress, &in_down, - "When active the player is swimming down in a liquid"); - Cmd_AddDataCommand ("-movedown", KeyRelease, &in_down, - "When active the player is not swimming down in a " - "liquid"); - Cmd_AddDataCommand ("+left", KeyPress, &in_left, - "When active the player is turning left"); - Cmd_AddDataCommand ("-left", KeyRelease, &in_left, - "When active the player is not turning left"); - Cmd_AddDataCommand ("+right", KeyPress, &in_right, - "When active the player is turning right"); - Cmd_AddDataCommand ("-right", KeyRelease, &in_right, - "When active the player is not turning right"); - Cmd_AddDataCommand ("+forward", KeyPress, &in_forward, - "When active the player is moving forward"); - Cmd_AddDataCommand ("-forward", KeyRelease, &in_forward, - "When active the player is not moving forward"); - Cmd_AddDataCommand ("+back", KeyPress, &in_back, - "When active the player is moving backwards"); - Cmd_AddDataCommand ("-back", KeyRelease, &in_back, - "When active the player is not moving backwards"); - Cmd_AddDataCommand ("+lookup", KeyPress, &in_lookup, - "When active the player's view is looking up"); - Cmd_AddDataCommand ("-lookup", KeyRelease, &in_lookup, - "When active the player's view is not looking up"); - Cmd_AddDataCommand ("+lookdown", KeyPress, &in_lookdown, - "When active the player's view is looking down"); - Cmd_AddDataCommand ("-lookdown", KeyRelease, &in_lookdown, - "When active the player's view is not looking up"); - Cmd_AddDataCommand ("+strafe", KeyPress, &in_strafe, - "When active, +left and +right function like " - "+moveleft and +moveright"); - Cmd_AddDataCommand ("-strafe", KeyRelease, &in_strafe, - "When active, +left and +right stop functioning like " - "+moveleft and +moveright"); - Cmd_AddDataCommand ("+moveleft", KeyPress, &in_moveleft, - "When active the player is strafing left"); - Cmd_AddDataCommand ("-moveleft", KeyRelease, &in_moveleft, - "When active the player is not strafing left"); - Cmd_AddDataCommand ("+moveright", KeyPress, &in_moveright, - "When active the player is strafing right"); - Cmd_AddDataCommand ("-moveright", KeyRelease, &in_moveright, - "When active the player is not strafing right"); - Cmd_AddDataCommand ("+speed", KeyPress, &in_speed, - "When active the player is running"); - Cmd_AddDataCommand ("-speed", KeyRelease, &in_speed, - "When active the player is not running"); - Cmd_AddDataCommand ("+attack", KeyPress, &in_attack, - "When active player is firing/using current weapon"); - Cmd_AddDataCommand ("-attack", KeyRelease, &in_attack, - "When active player is not firing/using current " - "weapon"); - Cmd_AddDataCommand ("+use", KeyPress, &in_use, - "Non-functional. Left over command for opening doors " - "and triggering switches"); - Cmd_AddDataCommand ("-use", KeyRelease, &in_use, - "Non-functional. Left over command for opening doors " - "and triggering switches"); - Cmd_AddDataCommand ("+jump", KeyPress, &in_jump, - "When active the player is jumping"); - Cmd_AddDataCommand ("-jump", KeyRelease, &in_jump, - "When active the player is not jumping"); + for (int i = 0; cl_in_buttons[i].name; i++) { + IN_RegisterButton (cl_in_buttons[i].button, cl_in_buttons[i].name, + cl_in_buttons[i].description); + } Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); - Cmd_AddDataCommand ("+klook", KeyPress, &in_klook, - "When active, +forward and +back perform +lookup and " - "+lookdown"); - Cmd_AddDataCommand ("-klook", KeyRelease, &in_klook, - "When active, +forward and +back don't perform " - "+lookup and +lookdown"); - Cmd_AddDataCommand ("+mlook", KeyPress, &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards performs +lookup and " - "+lookdown"); - Cmd_AddDataCommand ("-mlook", IN_MLookRelease, &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards doesn't perform +lookup and +lookdown"); } diff --git a/qw/include/cl_input.h b/qw/include/cl_input.h index a722967d6..0413e6ffa 100644 --- a/qw/include/cl_input.h +++ b/qw/include/cl_input.h @@ -46,12 +46,10 @@ int CL_ReadFromServer (void); void CL_WriteToServer (usercmd_t *cmd); void CL_BaseMove (usercmd_t *cmd); -float CL_KeyState (kbutton_t *key); - -extern kbutton_t in_left, in_right, in_forward, in_back; -extern kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -extern kbutton_t in_use, in_jump, in_attack; -extern kbutton_t in_up, in_down; +extern in_button_t in_left, in_right, in_forward, in_back; +extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +extern in_button_t in_use, in_jump, in_attack; +extern in_button_t in_up, in_down; extern int in_impulse; #endif diff --git a/qw/source/cl_chase.c b/qw/source/cl_chase.c index 68c9e207a..481002354 100644 --- a/qw/source/cl_chase.c +++ b/qw/source/cl_chase.c @@ -192,16 +192,16 @@ Chase_Update (void) // VectorCopy (cl.viewstate.angles, cmd.angles); if (in_strafe.state & 1) { - cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_right); - cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_left); + cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); + cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); } - cmd.sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright); - cmd.sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft); + cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); + cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); if (!(in_klook.state & 1)) { cmd.forwardmove += cl_forwardspeed->value - * CL_KeyState (&in_forward); - cmd.forwardmove -= cl_backspeed->value * CL_KeyState (&in_back); + * IN_ButtonState (&in_forward); + cmd.forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); } if (in_speed.state & 1) { cmd.forwardmove *= cl_movespeedkey->value; diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 770e16358..9bbc86e6a 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -80,88 +80,75 @@ cvar_t *cl_spamimpulse; state bit 2 is edge triggered on the down to up transition */ -kbutton_t in_left, in_right, in_forward, in_back; -kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -kbutton_t in_use, in_jump, in_attack; -kbutton_t in_up, in_down; +in_button_t in_left, in_right, in_forward, in_back; +in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +in_button_t in_use, in_jump, in_attack; +in_button_t in_up, in_down; +in_button_t in_strafe, in_klook, in_speed, in_mlook; + +static struct { + const char *name; + in_button_t *button; + const char *description; +} cl_in_buttons[] = { + { "left", &in_left, + "When active the player is turning left" + }, + { "right", &in_right, + "When active the player is turning right" + }, + { "forward", &in_forward, + "When active the player is moving forward" + }, + { "back", &in_back, + "When active the player is moving backwards" + }, + { "lookup", &in_lookup, + "When active the player's view is looking up" + }, + { "lookdown", &in_lookdown, + "When active the player's view is looking down" + }, + { "moveleft", &in_moveleft, + "When active the player is strafing left" + }, + { "moveright", &in_moveright, + "When active the player is strafing right" + }, + { "use", &in_use, + "Left over command for opening doors and triggering switches" + }, + { "jump", &in_jump, + "When active the player is jumping" + }, + { "attack", &in_attack, + "When active player is firing/using current weapon" + }, + { "moveup", &in_up, + "When active the player is swimming up in a liquid" + }, + { "movedown", &in_down, + "When active the player is swimming down in a liquid" + }, + { "strafe", &in_strafe, + "When active, +left and +right function like +moveleft and +moveright" + }, + { "speed", &in_speed, + "When active the player is running" + }, + { "klook", &in_klook, + "When active, +forward and +back perform +lookup and +lookdown" + }, + { "mlook", &in_mlook, + "When active moving the mouse or joystick forwards " + "and backwards performs +lookup and " + "+lookdown" + }, + { } +}; int in_impulse; - -static void -KeyPress (void *_b) -{ - kbutton_t *b = _b; - const char *c; - int k; - - c = Cmd_Argv (1); - if (c[0]) - k = atoi (c); - else - k = -1; // typed manually at the console for - // continuous down - - if (k == b->down[0] || k == b->down[1]) - return; // repeating key - - if (!b->down[0]) - b->down[0] = k; - else if (!b->down[1]) - b->down[1] = k; - else { - Sys_Printf ("Three keys down for a button!\n"); - return; - } - - if (b->state & 1) - return; // still down - b->state |= 1 + 2; // down + impulse down -} - -static void -KeyRelease (void *_b) -{ - kbutton_t *b = _b; - const char *c; - int k; - - c = Cmd_Argv (1); - if (c[0]) - k = atoi (c); - else { // typed manually at the console, - // assume for unsticking, so clear - // all - b->down[0] = b->down[1] = 0; - b->state = 4; // impulse up - return; - } - - if (b->down[0] == k) - b->down[0] = 0; - else if (b->down[1] == k) - b->down[1] = 0; - else - return; // key up without coresponding down - // (menu pass through) - if (b->down[0] || b->down[1]) - return; // some other key is still holding it - // down - - if (!(b->state & 1)) - return; // still up (this should not happen) - b->state &= ~1; // now up - b->state |= 4; // impulse up -} - -static void -IN_MLookRelease (void *data) -{ - KeyRelease (&in_mlook); - if (!freelook && lookspring->int_val) - V_StartPitchDrift (); -} - static void IN_Impulse (void *data) { @@ -172,55 +159,6 @@ IN_Impulse (void *data) Team_BestWeaponImpulse (); // HACK HACK HACK } -/* - CL_KeyState - - Returns 0.25 if a key was pressed and released during the frame, - 0.5 if it was pressed and held - 0 if held then released, and - 1.0 if held for the entire time -*/ -float -CL_KeyState (kbutton_t *key) -{ - float val; - qboolean impulsedown, impulseup, down; - - impulsedown = key->state & 2; - impulseup = key->state & 4; - down = key->state & 1; - val = 0; - - if (impulsedown && !impulseup) { - if (down) - val = 0.5; // pressed and held this frame - else - val = 0; // I_Error (); - } - if (impulseup && !impulsedown) { - if (down) - val = 0; // I_Error (); - else - val = 0; // released this frame - } - if (!impulsedown && !impulseup) { - if (down) - val = 1.0; // held the entire frame - else - val = 0; // up the entire frame - } - if (impulsedown && impulseup) { - if (down) - val = 0.75; // released and re-pressed this frame - else - val = 0.25; // pressed and released this frame - } - - key->state &= 1; // clear impulses - - return val; -} - cvar_t *cl_anglespeedkey; cvar_t *cl_backspeed; cvar_t *cl_forwardspeed; @@ -244,7 +182,7 @@ CL_AdjustAngles (void) pitchspeed = cl_pitchspeed->value; yawspeed = cl_yawspeed->value; - if (in_speed.state & 1) { + if (in_speed.state & inb_down) { pitchspeed *= cl_anglespeedkey->value; yawspeed *= cl_anglespeedkey->value; } @@ -257,19 +195,19 @@ CL_AdjustAngles (void) pitchspeed *= host_frametime; yawspeed *= host_frametime; - if (!(in_strafe.state & 1)) { - cl.viewstate.angles[YAW] -= yawspeed * CL_KeyState (&in_right); - cl.viewstate.angles[YAW] += yawspeed * CL_KeyState (&in_left); + if (!(in_strafe.state & inb_down)) { + cl.viewstate.angles[YAW] -= yawspeed * IN_ButtonState (&in_right); + cl.viewstate.angles[YAW] += yawspeed * IN_ButtonState (&in_left); cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); } - if (in_klook.state & 1) { + if (in_klook.state & inb_down) { V_StopPitchDrift (); - cl.viewstate.angles[PITCH] -= pitchspeed * CL_KeyState (&in_forward); - cl.viewstate.angles[PITCH] += pitchspeed * CL_KeyState (&in_back); + cl.viewstate.angles[PITCH] -= pitchspeed * IN_ButtonState (&in_forward); + cl.viewstate.angles[PITCH] += pitchspeed * IN_ButtonState (&in_back); } - up = CL_KeyState (&in_lookup); - down = CL_KeyState (&in_lookdown); + up = IN_ButtonState (&in_lookup); + down = IN_ButtonState (&in_lookdown); cl.viewstate.angles[PITCH] -= pitchspeed * up; cl.viewstate.angles[PITCH] += pitchspeed * down; @@ -297,6 +235,10 @@ CL_AdjustAngles (void) void CL_BaseMove (usercmd_t *cmd) { + if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring->int_val) { + V_StartPitchDrift (); + } + if (cls.state != ca_active) { return; } @@ -306,24 +248,24 @@ CL_BaseMove (usercmd_t *cmd) memset (cmd, 0, sizeof (*cmd)); VectorCopy (cl.viewstate.angles, cmd->angles); - if (in_strafe.state & 1) { - cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_right); - cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_left); + if (in_strafe.state & inb_down) { + cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); + cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); } - cmd->sidemove += cl_sidespeed->value * CL_KeyState (&in_moveright); - cmd->sidemove -= cl_sidespeed->value * CL_KeyState (&in_moveleft); + cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); + cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); - cmd->upmove += cl_upspeed->value * CL_KeyState (&in_up); - cmd->upmove -= cl_upspeed->value * CL_KeyState (&in_down); + cmd->upmove += cl_upspeed->value * IN_ButtonState (&in_up); + cmd->upmove -= cl_upspeed->value * IN_ButtonState (&in_down); - if (!(in_klook.state & 1)) { - cmd->forwardmove += cl_forwardspeed->value * CL_KeyState (&in_forward); - cmd->forwardmove -= cl_backspeed->value * CL_KeyState (&in_back); + if (!(in_klook.state & inb_down)) { + cmd->forwardmove += cl_forwardspeed->value * IN_ButtonState (&in_forward); + cmd->forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); } // adjust for speed key - if (in_speed.state & 1) { + if (in_speed.state & inb_down) { cmd->forwardmove *= cl_movespeedkey->value; cmd->sidemove *= cl_movespeedkey->value; cmd->upmove *= cl_movespeedkey->value; @@ -364,7 +306,7 @@ CL_BaseMove (usercmd_t *cmd) cl.viewstate.angles[YAW] += viewdelta.angles[YAW] * m_yaw->value; cl.viewstate.angles[ROLL] += viewdelta.angles[ROLL]; - if (freelook && !(in_strafe.state & 1)) { + if (freelook && !(in_strafe.state & inb_down)) { cl.viewstate.angles[PITCH] = bound (-70, cl.viewstate.angles[PITCH], 80); } @@ -393,19 +335,9 @@ CL_FinishMove (usercmd_t *cmd) return; // figure button bits - if (in_attack.state & 3) - cmd->buttons |= 1; - in_attack.state &= ~2; - - if (in_jump.state & 3) - cmd->buttons |= 2; - in_jump.state &= ~2; - -// 1999-10-29 +USE fix by Maddes start - if (in_use.state & 3) - cmd->buttons |= 4; - in_use.state &= ~2; -// 1999-10-29 +USE fix by Maddes end + cmd->buttons |= IN_ButtonPressed (&in_attack) << 0; + cmd->buttons |= IN_ButtonPressed (&in_jump) << 1; + cmd->buttons |= IN_ButtonPressed (&in_use) << 2; // send milliseconds of time to apply the move accum += (host_frametime * 1000.0); @@ -576,88 +508,12 @@ CL_SendCmd (void) void CL_Input_Init (void) { - Cmd_AddDataCommand ("+moveup", KeyPress, &in_up, - "When active the player is swimming up in a liquid"); - Cmd_AddDataCommand ("-moveup", KeyRelease, &in_up, - "When active the player is not swimming up in a " - "liquid"); - Cmd_AddDataCommand ("+movedown", KeyPress, &in_down, - "When active the player is swimming down in a liquid"); - Cmd_AddDataCommand ("-movedown", KeyRelease, &in_down, - "When active the player is not swimming down in a " - "liquid"); - Cmd_AddDataCommand ("+left", KeyPress, &in_left, - "When active the player is turning left"); - Cmd_AddDataCommand ("-left", KeyRelease, &in_left, - "When active the player is not turning left"); - Cmd_AddDataCommand ("+right", KeyPress, &in_right, - "When active the player is turning right"); - Cmd_AddDataCommand ("-right", KeyRelease, &in_right, - "When active the player is not turning right"); - Cmd_AddDataCommand ("+forward", KeyPress, &in_forward, - "When active the player is moving forward"); - Cmd_AddDataCommand ("-forward", KeyRelease, &in_forward, - "When active the player is not moving forward"); - Cmd_AddDataCommand ("+back", KeyPress, &in_back, - "When active the player is moving backwards"); - Cmd_AddDataCommand ("-back", KeyRelease, &in_back, - "When active the player is not moving backwards"); - Cmd_AddDataCommand ("+lookup", KeyPress, &in_lookup, - "When active the player's view is looking up"); - Cmd_AddDataCommand ("-lookup", KeyRelease, &in_lookup, - "When active the player's view is not looking up"); - Cmd_AddDataCommand ("+lookdown", KeyPress, &in_lookdown, - "When active the player's view is looking down"); - Cmd_AddDataCommand ("-lookdown", KeyRelease, &in_lookdown, - "When active the player's view is not looking up"); - Cmd_AddDataCommand ("+strafe", KeyPress, &in_strafe, - "When active, +left and +right function like " - "+moveleft and +moveright"); - Cmd_AddDataCommand ("-strafe", KeyRelease, &in_strafe, - "When active, +left and +right stop functioning like " - "+moveleft and +moveright"); - Cmd_AddDataCommand ("+moveleft", KeyPress, &in_moveleft, - "When active the player is strafing left"); - Cmd_AddDataCommand ("-moveleft", KeyRelease, &in_moveleft, - "When active the player is not strafing left"); - Cmd_AddDataCommand ("+moveright", KeyPress, &in_moveright, - "When active the player is strafing right"); - Cmd_AddDataCommand ("-moveright", KeyRelease, &in_moveright, - "When active the player is not strafing right"); - Cmd_AddDataCommand ("+speed", KeyPress, &in_speed, - "When active the player is running"); - Cmd_AddDataCommand ("-speed", KeyRelease, &in_speed, - "When active the player is not running"); - Cmd_AddDataCommand ("+attack", KeyPress, &in_attack, - "When active player is firing/using current weapon"); - Cmd_AddDataCommand ("-attack", KeyRelease, &in_attack, - "When active player is not firing/using current " - "weapon"); - Cmd_AddDataCommand ("+use", KeyPress, &in_use, - "Non-functional. Left over command for opening doors " - "and triggering switches"); - Cmd_AddDataCommand ("-use", KeyRelease, &in_use, - "Non-functional. Left over command for opening doors " - "and triggering switches"); - Cmd_AddDataCommand ("+jump", KeyPress, &in_jump, - "When active the player is jumping"); - Cmd_AddDataCommand ("-jump", KeyRelease, &in_jump, - "When active the player is not jumping"); + for (int i = 0; cl_in_buttons[i].name; i++) { + IN_RegisterButton (cl_in_buttons[i].button, cl_in_buttons[i].name, + cl_in_buttons[i].description); + } Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); - Cmd_AddDataCommand ("+klook", KeyPress, &in_klook, - "When active, +forward and +back perform +lookup and " - "+lookdown"); - Cmd_AddDataCommand ("-klook", KeyRelease, &in_klook, - "When active, +forward and +back don't perform " - "+lookup and +lookdown"); - Cmd_AddDataCommand ("+mlook", KeyPress, &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards performs +lookup and " - "+lookdown"); - Cmd_AddDataCommand ("-mlook", IN_MLookRelease, &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards doesn't perform +lookup and +lookdown"); } void From 63c2f829b3d80562a5df9748c42e1587b4de24fa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Oct 2021 12:10:26 +0900 Subject: [PATCH 1769/3664] [input] Fix a cut-and-paste error Just the name of a static function, but still... --- libs/input/in_button.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/input/in_button.c b/libs/input/in_button.c index 027f868ba..7ab40f78a 100644 --- a/libs/input/in_button.c +++ b/libs/input/in_button.c @@ -179,7 +179,7 @@ IN_RegisterButton (in_button_t *button, const char *name, } static void __attribute__((constructor)) -in_evdev_register_driver (void) +in_button_init (void) { button_tab = Hash_NewTable (127, button_get_key, button_free, 0, 0); } From a4f71cb4d51a04013b67a5c46746fda67db33aea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Oct 2021 13:11:14 +0900 Subject: [PATCH 1770/3664] [renderer] Clean out unneeded input.h includes I really don't know how it goot into the gl/glsl vid_common files, but I imagine it propogated to vulkan because I copied one then cloned from there. --- libs/video/renderer/gl/vid_common_gl.c | 1 - libs/video/renderer/glsl/vid_common_glsl.c | 1 - libs/video/renderer/vulkan/buffer.c | 1 - libs/video/renderer/vulkan/command.c | 1 - libs/video/renderer/vulkan/descriptor.c | 1 - libs/video/renderer/vulkan/device.c | 1 - libs/video/renderer/vulkan/image.c | 1 - libs/video/renderer/vulkan/instance.c | 1 - libs/video/renderer/vulkan/memory.c | 1 - libs/video/renderer/vulkan/pipeline.c | 1 - libs/video/renderer/vulkan/renderpass.c | 1 - libs/video/renderer/vulkan/vkparse.c | 1 - libs/video/renderer/vulkan/vulkan_vid_common.c | 1 - 13 files changed, 13 deletions(-) diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index 168cc0d4c..7b8c213e7 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -40,7 +40,6 @@ #endif #include "QF/cvar.h" -#include "QF/input.h" #include "QF/qargs.h" #include "QF/quakefs.h" #include "QF/sys.h" diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index 4ca5bc45e..0dffe7d11 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -41,7 +41,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/input.h" #include "QF/qargs.h" #include "QF/quakefs.h" #include "QF/sys.h" diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index 71b094e68..eb9da832c 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -41,7 +41,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 10f0cc559..dbf856dcc 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -41,7 +41,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" diff --git a/libs/video/renderer/vulkan/descriptor.c b/libs/video/renderer/vulkan/descriptor.c index dc7cc6fa4..30cbd0cad 100644 --- a/libs/video/renderer/vulkan/descriptor.c +++ b/libs/video/renderer/vulkan/descriptor.c @@ -42,7 +42,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/quakefs.h" #include "QF/sys.h" diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 7569e6daa..392953826 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -41,7 +41,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 61905c982..49d234b62 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -41,7 +41,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index db6c6f502..d096df421 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -35,7 +35,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" diff --git a/libs/video/renderer/vulkan/memory.c b/libs/video/renderer/vulkan/memory.c index 9397f4366..8f0ea2b9e 100644 --- a/libs/video/renderer/vulkan/memory.c +++ b/libs/video/renderer/vulkan/memory.c @@ -41,7 +41,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c index 2db39812c..baade73a1 100644 --- a/libs/video/renderer/vulkan/pipeline.c +++ b/libs/video/renderer/vulkan/pipeline.c @@ -42,7 +42,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index fc86b9375..3be4f7295 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -42,7 +42,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/qargs.h" #include "QF/quakefs.h" diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index a1616b722..1873c2d42 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -43,7 +43,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/plist.h" #include "QF/qargs.h" diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 64fc3d453..2209f89e0 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -43,7 +43,6 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/plist.h" #include "QF/qargs.h" From 36f6dcc65e06a4d06227c65616a03ad0c886a44c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Oct 2021 15:38:48 +0900 Subject: [PATCH 1771/3664] [input] Add logical axes Like logical buttons, logical axes are engine-defined destinations to which input ("physical") axes can be bound. --- include/QF/input.h | 46 +++++++++++++++++++++- libs/input/Makemodule.am | 1 + libs/input/in_axis.c | 85 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 libs/input/in_axis.c diff --git a/include/QF/input.h b/include/QF/input.h index c46819981..71f4eac02 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -80,7 +80,41 @@ typedef struct in_device_s { const char *id; } in_device_t; -/*** Current state of the button. +/*** Recipe for converting an axis to a floating point value. + + Recipes apply only to absolute axes. + + \a deadzone applies only to balanced axes, thus it doubles as a flag + for balanced (>= 0) or unbalanced (< 0). + + \a curve is applied after the input has been converted +*/ +typedef struct in_recipe_s { + int minzone; ///< Size of deadzone near axis minimum + int maxzone; ///< Size of deadzone near axis maximum + int deadzone; ///< Size of deadzone near axis center (balanced) + float curve; ///< Power factor for absolute axes +} in_recipe_t; + +typedef enum { + ina_set, ///< write the axis value to the destination + ina_accumulate, ///< add the axis value to the destination +} in_axis_mode; + +/*** Logical axis. + + Logical axes are the inputs defined by the game on which axis inputs + (usually "physical" axes) can act. Depending on the mode, the physical + axis value is either written as-is, or added to the existing value. It is + the responsibility of the code using the axis to clear the value for + accumulated inputs. +*/ +typedef struct in_axis_s { + float value; ///< converted value of the axis + in_axis_mode mode; ///< method used for updating the destination +} in_axis_t; + +/*** Current state of the logical button. Captures the current state and any transitions during the last frame. Not all combinations are valid (inb_edge_up|inb_down and inb_edge_down @@ -94,6 +128,14 @@ typedef enum { inb_edge_up = 1<<2, ///< button released this frame } in_button_state; +/*** Logical button. + + Logical buttons are the inputs defined by the game on which button inputs + (usually "physical" buttons) can act. Up to two button inputs can be + bound to a logical button. The logical button acts as an or gate where + either input will put the logical button in the pressed state, and both + inputs must be inactive for the logical button to be released. +*/ typedef struct in_button_s { int down[2]; ///< button ids holding this button down int state; ///< in_button_state @@ -222,6 +264,8 @@ void IN_ClearStates (void); int IN_RegisterButton (in_button_t *button, const char *name, const char *description); +int IN_RegisterAxis (in_axis_t *axis, const char *name, + const char *description); void IN_Move (void); // FIXME: was cmduser_t? // add additional movement on top of the keyboard move cmd diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index e160f456f..7f9bdfff2 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -20,6 +20,7 @@ libs_input_libQFinput_la_DEPENDENCIES= $(input_deps) libs_input_libQFinput_la_SOURCES= \ libs/input/keys.c \ libs/input/old_keys.c \ + libs/input/in_axis.c \ libs/input/in_button.c \ libs/input/in_common.c \ libs/input/in_event.c diff --git a/libs/input/in_axis.c b/libs/input/in_axis.c new file mode 100644 index 000000000..b9e980fda --- /dev/null +++ b/libs/input/in_axis.c @@ -0,0 +1,85 @@ +/* + in_axis.c + + Logical axis support + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/10/1 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cmd.h" +#include "QF/hash.h" +#include "QF/input.h" +#include "QF/sys.h" + +typedef struct regaxis_s { + const char *name; + const char *description; + in_axis_t *axis; +} regaxis_t; + +static hashtab_t *axis_tab; + +static const char * +axis_get_key (const void *b, void *data) +{ + __auto_type regaxis = (const regaxis_t *) b; + return regaxis->name; +} + +static void +axis_free (void *b, void *data) +{ + free (b); +} + +VISIBLE int +IN_RegisterAxis (in_axis_t *axis, const char *name, const char *description) +{ + if (Hash_Find (axis_tab, name)) { + return 0; + } + regaxis_t *regaxis = malloc (sizeof (regaxis_t)); + regaxis->name = name; + regaxis->description = description; + regaxis->axis = axis; + + return 1; +} + +static void __attribute__((constructor)) +in_axis_init (void) +{ + axis_tab = Hash_NewTable (127, axis_get_key, axis_free, 0, 0); +} From abe77523ae6bde783338caab0cb54bc7d7418861 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Oct 2021 10:16:42 +0900 Subject: [PATCH 1772/3664] [qwaq] Disable xterm mouse handling on shutdown Getting mouse escape codes on the command line is not very pleasant (even if display-only). --- ruamoko/qwaq/builtins/curses.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 174908399..1e7c7d58c 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -754,6 +754,7 @@ static void bi_shutdown (void *_pr) { if (need_endwin) { + qwaq_input_disable_mouse (); endwin (); } } From 4406be8de37376e691097749d6c276d69a968630 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Nov 2021 12:13:28 +0900 Subject: [PATCH 1773/3664] [input] Move last button declarations This puts all the client button declarations in the right place (for now: eventually there will be just the one client input header). --- include/QF/input.h | 1 - nq/include/client.h | 1 + qw/include/cl_input.h | 11 ++++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 71f4eac02..4a84b51f0 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -282,7 +282,6 @@ extern qboolean in_mouse_avail; extern float in_mouse_x, in_mouse_y; -extern in_button_t in_strafe, in_klook, in_speed, in_mlook; #endif #endif//__QF_input_h diff --git a/nq/include/client.h b/nq/include/client.h index 5f58349e3..6c10ef375 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -343,6 +343,7 @@ extern in_button_t in_left, in_right, in_forward, in_back; extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; extern in_button_t in_use, in_jump, in_attack; extern in_button_t in_up, in_down; +extern in_button_t in_strafe, in_klook, in_speed, in_mlook; extern double realtime; diff --git a/qw/include/cl_input.h b/qw/include/cl_input.h index 0413e6ffa..4493f9806 100644 --- a/qw/include/cl_input.h +++ b/qw/include/cl_input.h @@ -46,10 +46,11 @@ int CL_ReadFromServer (void); void CL_WriteToServer (usercmd_t *cmd); void CL_BaseMove (usercmd_t *cmd); -extern in_button_t in_left, in_right, in_forward, in_back; -extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; -extern in_button_t in_use, in_jump, in_attack; -extern in_button_t in_up, in_down; -extern int in_impulse; +extern in_button_t in_left, in_right, in_forward, in_back; +extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +extern in_button_t in_use, in_jump, in_attack; +extern in_button_t in_up, in_down; +extern in_button_t in_strafe, in_klook, in_speed, in_mlook; +extern int in_impulse; #endif From bb1a0325645fdcaeabffdbe00fff71c28844ccf2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Nov 2021 12:14:40 +0900 Subject: [PATCH 1774/3664] Update packages in INSTALL Add packages for Vulkan, and update libpng --- INSTALL | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index 8b747944a..69c495ae6 100644 --- a/INSTALL +++ b/INSTALL @@ -57,7 +57,7 @@ The following is the list of relevant package names in debian. \li libflac-dev \li libogg-dev \li libvorbis-dev -\li libpng12-dev +\li libpng-dev \li zlib1g-dev \li libcurl4-openssl-dev (or libcurl4-gnutls-dev) @@ -69,6 +69,11 @@ The following is the list of relevant package names in debian. \li libxxf86dga-dev \li libxxf86vm-dev +\li libvulkan-dev +\li vulkan-tools +\li vulkan-validationlayers +\li glslang-tools + \section building-and-installing Build and Install Procedure Basic process to build and install QuakeForge: \verbatim From 665790f562caef5128a441e4306fd72633015ef5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Nov 2021 12:30:45 +0900 Subject: [PATCH 1775/3664] [video] Remove libQFjs It is now redundant with the libQFinput, though nothing actually works yet. --- config.d/build_control.m4 | 3 --- libs/video/targets/Makemodule.am | 23 +---------------------- nq/source/Makemodule.am | 1 - nq/source/cl_main.c | 1 - qw/source/Makemodule.am | 1 - qw/source/cl_main.c | 1 - ruamoko/qwaq/Makemodule.am | 1 - 7 files changed, 1 insertion(+), 30 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 641e1b1f5..275cac8a9 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -365,12 +365,10 @@ if test -n "$CL_TARGETS"; then CD_TARGETS="libs/audio/libQFcd.la" SND_TARGETS="libs/audio/libQFsound.la" AUDIO_TARGETS="libs/audio/test/testsound\$(EXEEXT)" - JOY_TARGETS="libs/video/targets/libQFjs.la" else unset CDTYPE unset SOUND_TYPES CD_TARGETS="" - JOY_TARGETS="" SND_TARGETS="" AUDIO_TARGETS="" fi @@ -434,7 +432,6 @@ QF_SUBST(QWAQ_TARGETS) QF_SUBST(QW_TARGETS) QF_SUBST(QW_DESKTOP_DATA) QF_SUBST(CD_TARGETS) -QF_SUBST(JOY_TARGETS) QF_SUBST(SND_TARGETS) QF_SUBST(AUDIO_TARGETS) QF_SUBST(VID_MODEL_TARGETS) diff --git a/libs/video/targets/Makemodule.am b/libs/video/targets/Makemodule.am index 2f0773053..0dbeb4882 100644 --- a/libs/video/targets/Makemodule.am +++ b/libs/video/targets/Makemodule.am @@ -1,9 +1,8 @@ -lib_LTLIBRARIES += @JOY_TARGETS@ +#lib_LTLIBRARIES += noinst_LTLIBRARIES += @VID_TARGETS@ @vid_libs@ EXTRA_LTLIBRARIES += \ - libs/video/targets/libQFjs.la \ libs/video/targets/libQFfbdev.la \ libs/video/targets/libQFsvga.la \ libs/video/targets/libQFx11.la \ @@ -15,19 +14,6 @@ EXTRA_LTLIBRARIES += \ libs/video/targets/libvid_win.la \ libs/video/targets/libvid_x11.la -joy_linux_src= libs/video/targets/joy_linux.c -joy_win_src= libs/video/targets/joy_win.c -joy_null_src= libs/video/targets/joy_null.c -if JOYTYPE_LINUX -joy_src= $(joy_linux_src) -else -if JOYTYPE_WIN32 -joy_src= $(joy_win_src) -else -joy_src= $(joy_null_src) -endif -endif - win_gl_src = libs/video/targets/vid_win_gl.c win_sw_src = libs/video/targets/vid_win_sw.c win_vulkan_src = libs/video/targets/vid_win_vulkan.c @@ -48,13 +34,6 @@ endif js_libs = libs/util/libQFutil.la -libs_video_targets_libQFjs_la_LDFLAGS= $(lib_ldflags) -libs_video_targets_libQFjs_la_LIBADD= $(js_libs) -libs_video_targets_libQFjs_la_DEPENDENCIES=$(js_libs) -libs_video_targets_libQFjs_la_CFLAGS= @PREFER_PIC@ $(JOY_CFLAGS) -libs_video_targets_libQFjs_la_SOURCES= libs/video/targets/joy.c $(joy_src) -EXTRA_libs_video_targets_libQFjs_la_SOURCES= $(joy_linux_src) $(joy_win_src) $(joy_null_src) - libs_video_targets_libvid_common_la_SOURCES = \ libs/video/targets/vid.c libs_video_targets_libvid_common_la_CFLAGS= @PREFER_NON_PIC@ diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 0cfd9b915..1d3a70ebe 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -47,7 +47,6 @@ nq_cl_plugin_LIBS= \ nq_client_LIBFILES= \ libs/gib/libQFgib_client.la \ libs/scene/libQFscene.la \ - libs/video/targets/libQFjs.la \ libs/audio/libQFcd.la \ libs/audio/libQFsound.la diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index c05570794..a48d593d5 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -115,7 +115,6 @@ CL_WriteConfiguration (void) } Key_WriteBindings (f); - Joy_WriteBindings (f); Cvar_WriteVariables (f); Qclose (f); diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index f5335692f..61cf327c0 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -91,7 +91,6 @@ qw_client_LIBS= \ libs/net/libnet_chan.la \ libs/scene/libQFscene.la \ libs/console/libQFconsole.la \ - libs/video/targets/libQFjs.la \ libs/audio/libQFcd.la \ libs/audio/libQFsound.la \ libs/image/libQFimage.la \ diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 7362327cf..ce71b1ad8 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1513,7 +1513,6 @@ Host_WriteConfiguration (void) } Key_WriteBindings (f); - Joy_WriteBindings (f); Cvar_WriteVariables (f); Qclose (f); diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 43c306003..001671f8f 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -101,7 +101,6 @@ qwaq_client_libs= \ $(top_builddir)/libs/console/libQFconsole.la \ $(top_builddir)/libs/ui/libQFui.la \ $(top_builddir)/libs/input/libQFinput.la \ - $(top_builddir)/libs/video/targets/libQFjs.la \ $(top_builddir)/libs/audio/libQFcd.la \ $(top_builddir)/libs/audio/libQFsound.la \ $(top_builddir)/libs/image/libQFimage.la From 09e3e62a0a6d2428f12651dfd5b5fed1e3e5dfd1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Nov 2021 13:05:05 +0900 Subject: [PATCH 1776/3664] [input] Move in_event.h and binding defs They now live in the include QF/input directory. This cleans up include/QF a little, and input.h as well. --- include/QF/Makemodule.am | 5 +- include/QF/input.h | 190 ++++--------------- include/QF/input/binding.h | 222 +++++++++++++++++++++++ include/QF/{in_event.h => input/event.h} | 0 libs/input/in_button.c | 20 +- libs/input/in_common.c | 3 +- libs/input/in_evdev.c | 3 +- libs/input/in_event.c | 3 +- ruamoko/qwaq/builtins/input.c | 3 +- 9 files changed, 287 insertions(+), 162 deletions(-) create mode 100644 include/QF/input/binding.h rename include/QF/{in_event.h => input/event.h} (100%) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 8008d89c2..1e590ff2e 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -21,7 +21,6 @@ include_qf = \ include/QF/heapsort.h \ include/QF/idparse.h \ include/QF/image.h \ - include/QF/in_event.h \ include/QF/info.h \ include/QF/input.h \ include/QF/iqm.h \ @@ -112,6 +111,9 @@ include_qf_glsl = \ include/QF/GLSL/qf_vid.h \ include/QF/GLSL/types.h +include_qf_input = \ + include/QF/binding.h \ + include/QF/event.h include_qf_math = \ include/QF/math/dual.h \ include/QF/math/half.h \ @@ -210,6 +212,7 @@ EXTRA_HEADERS += \ $(include_qf) \ $(include_qf_gl) \ $(include_qf_glsl) \ + $(include_qf_input) \ $(include_qf_math) \ $(include_qf_plugin) \ $(include_qf_scene) \ diff --git a/include/QF/input.h b/include/QF/input.h index 4a84b51f0..9405e0e02 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -44,6 +44,8 @@ typedef struct in_buttoninfo_s { int state; } in_buttoninfo_t; +#include "QF/input/binding.h" + #ifndef __QFCC__ typedef struct { @@ -80,161 +82,42 @@ typedef struct in_device_s { const char *id; } in_device_t; -/*** Recipe for converting an axis to a floating point value. +/*** Connect a device and its axes and buttons to logical axes and buttons. - Recipes apply only to absolute axes. + \a name is used to specify the device when creating bindings, and + identifying the device for hints etc (eg, "press joy1 1 to ..."). - \a deadzone applies only to balanced axes, thus it doubles as a flag - for balanced (>= 0) or unbalanced (< 0). + \a id is the device name (eg, "6d spacemouse") or (preferred) the device + id (eg "usb-0000:00:1d.1-2/input0"). The device name is useful for ease of + user identification and allowing the device to be plugged into any USB + socket. However, it doesn't allow multiple devices with the same name + (eg, using twin joysticks of the same model). Thus the device id is + preferred, but does require the device to be plugged into the same uSB + path (ie, same socket on the same hub connected to the same port on the PC) - \a curve is applied after the input has been converted + \a device is the actual device associated with the bindings. If null, the + device is not currently connected. + + \a axis_info holds the device/axis specific range info and the current + raw value of the axis. + + \a button_info holds the current raw state of the button + + \a axis_imt_id is 0 if the device has no axis bindings, otherwise it is + the based index into the imt array for the imt group. + + \a button_imt_i is 0 if the device has no button bindings, otherwise it + is the index into the imt array for the imt group. */ -typedef struct in_recipe_s { - int minzone; ///< Size of deadzone near axis minimum - int maxzone; ///< Size of deadzone near axis maximum - int deadzone; ///< Size of deadzone near axis center (balanced) - float curve; ///< Power factor for absolute axes -} in_recipe_t; - -typedef enum { - ina_set, ///< write the axis value to the destination - ina_accumulate, ///< add the axis value to the destination -} in_axis_mode; - -/*** Logical axis. - - Logical axes are the inputs defined by the game on which axis inputs - (usually "physical" axes) can act. Depending on the mode, the physical - axis value is either written as-is, or added to the existing value. It is - the responsibility of the code using the axis to clear the value for - accumulated inputs. -*/ -typedef struct in_axis_s { - float value; ///< converted value of the axis - in_axis_mode mode; ///< method used for updating the destination -} in_axis_t; - -/*** Current state of the logical button. - - Captures the current state and any transitions during the last frame. - Not all combinations are valid (inb_edge_up|inb_down and inb_edge_down - (no inb_down) are not valid states), but inb_edge_up|inb_edge_down )with - or without inb_down) is valid as it represents a double transition during - the frame. -*/ -typedef enum { - inb_down = 1<<0, ///< button is held - inb_edge_down = 1<<1, ///< button pressed this frame - inb_edge_up = 1<<2, ///< button released this frame -} in_button_state; - -/*** Logical button. - - Logical buttons are the inputs defined by the game on which button inputs - (usually "physical" buttons) can act. Up to two button inputs can be - bound to a logical button. The logical button acts as an or gate where - either input will put the logical button in the pressed state, and both - inputs must be inactive for the logical button to be released. -*/ -typedef struct in_button_s { - int down[2]; ///< button ids holding this button down - int state; ///< in_button_state -} in_button_t; - -/*** Represent the button's activity in the last frame as a float. - - The detected activity is: - steady off (up) - steady on (down) - off to on (up to down) transition - on to off )down to up) transition - pulse on (off-on-off or up-down-up) - pulse off (on-off-on or down-up-down) - Any additional transitions are treated as a pulse appropriate for the - final state of the button. - - \param button Pointer to the button being tested. - \return Float value between 0 (off/up) and 1 (on/down) - \note The edge transitions are cleared, so for each frame, this - is a one-shot function (ie, it is NOT idempotent). -*/ -GNU89INLINE inline float IN_ButtonState (in_button_t *button); - -/*** Test whether a button has been pressed in the last frame. - - Both steady-state on, and brief clicks are detected. - - \return True if the button is currently held or was pulsed on - in the last frame. - \note The edge transitions are cleared, so for each frame, this - is a one-shot function (ie, it is NOT idempotent). -*/ -GNU89INLINE inline int IN_ButtonPressed (in_button_t *button); - -/*** Test whether a button was released in the last frame. - - Valid only if the button is still released. A pulsed off does not - count as being released as the button is still held. - - \return True if the button is currently released and the release - was in the last frame. - \note The edge transitions are cleared, so for each frame, this - is a one-shot function (ie, it is NOT idempotent). -*/ -GNU89INLINE inline int IN_ButtonReleased (in_button_t *button); - -#ifndef IMPLEMENT_INPUT_Funcs -GNU89INLINE inline -#else -VISIBLE -#endif -float -IN_ButtonState (in_button_t *button) -{ - static const float state_values[8] = { - // held down for the entire frame - [inb_down] = 1, - // released this frame - [inb_edge_up] = 0, // instant falloff - // pressed this frame - [inb_edge_down|inb_down] = 0.5, - // pressed and released this frame - [inb_edge_down|inb_edge_up] = 0.25, - // released and pressed this frame - [inb_edge_down|inb_edge_up|inb_down] = 0.75, - }; - int state = button->state; - button->state &= inb_down; // clear edges, preserve pressed - return state_values[state & (inb_down|inb_edge_down|inb_edge_up)]; -} - -#ifndef IMPLEMENT_INPUT_Funcs -GNU89INLINE inline -#else -VISIBLE -#endif -int -IN_ButtonPressed (in_button_t *button) -{ - int state = button->state; - button->state &= inb_down; // clear edges, preserve pressed - // catch even press and release that occurs between frames - return (state & (inb_down | inb_edge_down)) != 0; -} - -#ifndef IMPLEMENT_INPUT_Funcs -GNU89INLINE inline -#else -VISIBLE -#endif -int -IN_ButtonReleased (in_button_t *button) -{ - int state = button->state; - button->state &= inb_down; // clear edges, preserve pressed - // catch only full release (a pulsed on does count as a release) - return (state & (inb_down | inb_edge_up)) == inb_edge_up; -} +typedef struct in_devbindings_s { + const char *name; ///< name used when binding inputs + const char *id; ///< physical device name or id (preferred) + in_device_t *device; ///< device associated with these bindings + in_axisinfo_t *axis_info; ///< axis range info and raw state + in_buttoninfo_t *button_info; ///< button raw state + int axis_imt_id; ///< index into array of imt axis bindings + int button_imt_id; ///< index into array of imt button bindings +} in_devbindings_t; extern viewdelta_t viewdelta; @@ -262,11 +145,6 @@ void IN_UpdateGrab (struct cvar_s *); void IN_ClearStates (void); -int IN_RegisterButton (in_button_t *button, const char *name, - const char *description); -int IN_RegisterAxis (in_axis_t *axis, const char *name, - const char *description); - void IN_Move (void); // FIXME: was cmduser_t? // add additional movement on top of the keyboard move cmd diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h new file mode 100644 index 000000000..effa27fc4 --- /dev/null +++ b/include/QF/input/binding.h @@ -0,0 +1,222 @@ +/* + binding.h + + Input Mapping Table management + + Copyright (C) 2001 Zephaniah E. Hull + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_input_binding_h +#define __QF_input_binding_h + +#ifndef __QFCC__ + +/*** Recipe for converting an axis to a floating point value. + + Recipes apply only to absolute axes. + + \a deadzone applies only to balanced axes, thus it doubles as a flag + for balanced (>= 0) or unbalanced (< 0). + + \a curve is applied after the input has been converted +*/ +typedef struct in_recipe_s { + int minzone; ///< Size of deadzone near axis minimum + int maxzone; ///< Size of deadzone near axis maximum + int deadzone; ///< Size of deadzone near axis center (balanced) + float curve; ///< Power factor for absolute axes +} in_recipe_t; + +typedef enum { + ina_set, ///< write the axis value to the destination + ina_accumulate, ///< add the axis value to the destination +} in_axis_mode; + +/*** Logical axis. + + Logical axes are the inputs defined by the game on which axis inputs + (usually "physical" axes) can act. Depending on the mode, the physical + axis value is either written as-is, or added to the existing value. It is + the responsibility of the code using the axis to clear the value for + accumulated inputs. +*/ +typedef struct in_axis_s { + float value; ///< converted value of the axis + in_axis_mode mode; ///< method used for updating the destination +} in_axis_t; + +/*** Current state of the logical button. + + Captures the current state and any transitions during the last frame. + Not all combinations are valid (inb_edge_up|inb_down and inb_edge_down + (no inb_down) are not valid states), but inb_edge_up|inb_edge_down )with + or without inb_down) is valid as it represents a double transition during + the frame. +*/ +typedef enum { + inb_down = 1<<0, ///< button is held + inb_edge_down = 1<<1, ///< button pressed this frame + inb_edge_up = 1<<2, ///< button released this frame +} in_button_state; + +/*** Logical button. + + Logical buttons are the inputs defined by the game on which button inputs + (usually "physical" buttons) can act. Up to two button inputs can be + bound to a logical button. The logical button acts as an or gate where + either input will put the logical button in the pressed state, and both + inputs must be inactive for the logical button to be released. +*/ +typedef struct in_button_s { + int down[2]; ///< button ids holding this button down + int state; ///< in_button_state + const char *name; +} in_button_t; + +typedef struct in_axisbinding_s { + in_recipe_t *recipe; + in_axis_t *axis; +} in_axisbinding_t; + +typedef enum { + inb_button, + inb_command, +} in_button_type; + +typedef struct in_buttonbinding_s { + in_button_type type; + union { + struct { + int bind_id; ///< for button multi-press support + in_button_t *button; + }; + char *command; + }; +} in_buttonbinding_t; + +/*** Represent the button's activity in the last frame as a float. + + The detected activity is: + steady off (up) + steady on (down) + off to on (up to down) transition + on to off )down to up) transition + pulse on (off-on-off or up-down-up) + pulse off (on-off-on or down-up-down) + Any additional transitions are treated as a pulse appropriate for the + final state of the button. + + \param button Pointer to the button being tested. + \return Float value between 0 (off/up) and 1 (on/down) + \note The edge transitions are cleared, so for each frame, this + is a one-shot function (ie, it is NOT idempotent). +*/ +GNU89INLINE inline float IN_ButtonState (in_button_t *button); + +/*** Test whether a button has been pressed in the last frame. + + Both steady-state on, and brief clicks are detected. + + \return True if the button is currently held or was pulsed on + in the last frame. + \note The edge transitions are cleared, so for each frame, this + is a one-shot function (ie, it is NOT idempotent). +*/ +GNU89INLINE inline int IN_ButtonPressed (in_button_t *button); + +/*** Test whether a button was released in the last frame. + + Valid only if the button is still released. A pulsed off does not + count as being released as the button is still held. + + \return True if the button is currently released and the release + was in the last frame. + \note The edge transitions are cleared, so for each frame, this + is a one-shot function (ie, it is NOT idempotent). +*/ +GNU89INLINE inline int IN_ButtonReleased (in_button_t *button); + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +float +IN_ButtonState (in_button_t *button) +{ + static const float state_values[8] = { + // held down for the entire frame + [inb_down] = 1, + // released this frame + [inb_edge_up] = 0, // instant falloff + // pressed this frame + [inb_edge_down|inb_down] = 0.5, + // pressed and released this frame + [inb_edge_down|inb_edge_up] = 0.25, + // released and pressed this frame + [inb_edge_down|inb_edge_up|inb_down] = 0.75, + }; + int state = button->state; + button->state &= inb_down; // clear edges, preserve pressed + return state_values[state & (inb_down|inb_edge_down|inb_edge_up)]; +} + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +IN_ButtonPressed (in_button_t *button) +{ + int state = button->state; + button->state &= inb_down; // clear edges, preserve pressed + // catch even press and release that occurs between frames + return (state & (inb_down | inb_edge_down)) != 0; +} + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +IN_ButtonReleased (in_button_t *button) +{ + int state = button->state; + button->state &= inb_down; // clear edges, preserve pressed + // catch only full release (a pulsed on does count as a release) + return (state & (inb_down | inb_edge_up)) == inb_edge_up; +} + +void IN_ButtonAction (in_button_t *buttin, int id, int pressed); + +int IN_RegisterButton (in_button_t *button, const char *name, + const char *description); +int IN_RegisterAxis (in_axis_t *axis, const char *name, + const char *description); +in_button_t *IN_FindButton (const char *name); + +#endif + +#endif//__QF_input_binding_h diff --git a/include/QF/in_event.h b/include/QF/input/event.h similarity index 100% rename from include/QF/in_event.h rename to include/QF/input/event.h diff --git a/libs/input/in_button.c b/libs/input/in_button.c index 7ab40f78a..793ce97cc 100644 --- a/libs/input/in_button.c +++ b/libs/input/in_button.c @@ -122,6 +122,17 @@ button_release (in_button_t *button, int id) button->state |= inb_edge_up; } +void +IN_ButtonAction (in_button_t *button, int id, int pressed) +{ + if (pressed) { + button_press (button, id); + } else { + button_release (button, id); + } +} + + static void button_press_cmd (void *_b) { @@ -173,11 +184,18 @@ IN_RegisterButton (in_button_t *button, const char *name, Cmd_AddDataCommand (regbutton->press_cmd, button_press_cmd, button, "Set the button's state to on/pressed."); Cmd_AddDataCommand (regbutton->release_cmd, button_release_cmd, button, - "Set the button's state to on/pressed."); + "Set the button's state to off/released."); + Hash_Add (button_tab, regbutton); return 1; } +in_button_t * +IN_FindButton (const char *name) +{ + return Hash_Find (button_tab, name); +} + static void __attribute__((constructor)) in_button_init (void) { diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 07dcf2d66..37378647a 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -50,7 +50,6 @@ #include "QF/cbuf.h" #include "QF/cvar.h" #include "QF/darray.h" -#include "QF/in_event.h" #define IMPLEMENT_INPUT_Funcs #include "QF/input.h" #include "QF/joystick.h" @@ -59,6 +58,8 @@ #include "QF/sys.h" #include "QF/vid.h" +#include "QF/input/event.h" + #include "qfselect.h" typedef struct { diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 95ae1a82d..81ca2e6f9 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -37,11 +37,12 @@ #endif #include "QF/cvar.h" -#include "QF/in_event.h" #include "QF/input.h" #include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" +#include "QF/input/event.h" + #include "compat.h" #include "qfselect.h" #include "evdev/inputlib.h" diff --git a/libs/input/in_event.c b/libs/input/in_event.c index 6f74ae4bc..aa302cf5b 100644 --- a/libs/input/in_event.c +++ b/libs/input/in_event.c @@ -40,7 +40,8 @@ #include #include "QF/darray.h" -#include "QF/in_event.h" + +#include "QF/input/event.h" typedef struct { ie_handler_t *handler; diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index cad843d86..a37b45acb 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -46,11 +46,12 @@ #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/in_event.h" #include "QF/input.h" #include "QF/keys.h" #include "QF/sys.h" +#include "QF/input/event.h" + #include "qfselect.h" #include "ruamoko/qwaq/qwaq.h" From fae9e043dfa2ff8dfd33e8ab9ce7cd24a5035393 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 1 Nov 2021 13:54:16 +0900 Subject: [PATCH 1777/3664] [input] Move button name and description This puts the name and description into the button itself, making it much easier to look them up. --- include/QF/input/binding.h | 4 +- libs/input/in_button.c | 10 +-- nq/source/cl_input.c | 178 ++++++++++++++++++++----------------- qw/source/cl_input.c | 178 ++++++++++++++++++++----------------- 4 files changed, 193 insertions(+), 177 deletions(-) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index effa27fc4..60cf27196 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -91,6 +91,7 @@ typedef struct in_button_s { int down[2]; ///< button ids holding this button down int state; ///< in_button_state const char *name; + const char *description; } in_button_t; typedef struct in_axisbinding_s { @@ -211,8 +212,7 @@ IN_ButtonReleased (in_button_t *button) void IN_ButtonAction (in_button_t *buttin, int id, int pressed); -int IN_RegisterButton (in_button_t *button, const char *name, - const char *description); +int IN_RegisterButton (in_button_t *button); int IN_RegisterAxis (in_axis_t *axis, const char *name, const char *description); in_button_t *IN_FindButton (const char *name); diff --git a/libs/input/in_button.c b/libs/input/in_button.c index 793ce97cc..1c0fe51f7 100644 --- a/libs/input/in_button.c +++ b/libs/input/in_button.c @@ -45,8 +45,6 @@ #include "QF/sys.h" typedef struct regbutton_s { - const char *name; - const char *description; in_button_t *button; char *press_cmd; char *release_cmd; @@ -58,7 +56,7 @@ static const char * button_get_key (const void *b, void *data) { __auto_type regbutton = (const regbutton_t *) b; - return regbutton->name; + return regbutton->button->name; } static void @@ -162,16 +160,14 @@ button_release_cmd (void *_b) } VISIBLE int -IN_RegisterButton (in_button_t *button, const char *name, - const char *description) +IN_RegisterButton (in_button_t *button) { + const char *name = button->name; if (Hash_Find (button_tab, name)) { return 0; } size_t size = strlen (name) + 2; regbutton_t *regbutton = malloc (sizeof (regbutton_t) + 2 * size); - regbutton->name = name; - regbutton->description = description; regbutton->button = button; regbutton->press_cmd = (char *) (regbutton + 1); diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index c480700e1..3f22eafee 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -50,88 +50,99 @@ #include "nq/include/client.h" #include "nq/include/host.h" -/* - KEY BUTTONS +in_button_t in_left = { + .name = "left", + .description = "When active the player is turning left" +}; +in_button_t in_right = { + .name = "right", + .description = "When active the player is turning right" +}; +in_button_t in_forward = { + .name = "forward", + .description = "When active the player is moving forward" +}; +in_button_t in_back = { + .name = "back", + .description = "When active the player is moving backwards" +}; +in_button_t in_lookup = { + .name = "lookup", + .description = "When active the player's view is looking up" +}; +in_button_t in_lookdown = { + .name = "lookdown", + .description = "When active the player's view is looking down" +}; +in_button_t in_moveleft = { + .name = "moveleft", + .description = "When active the player is strafing left" +}; +in_button_t in_moveright = { + .name = "moveright", + .description = "When active the player is strafing right" +}; +in_button_t in_use = { + .name = "use", + .description = "Left over command for opening doors and triggering" + " switches" +}; +in_button_t in_jump = { + .name = "jump", + .description = "When active the player is jumping" +}; +in_button_t in_attack = { + .name = "attack", + .description = "When active player is firing/using current weapon" +}; +in_button_t in_up = { + .name = "moveup", + .description = "When active the player is swimming up in a liquid" +}; +in_button_t in_down = { + .name = "movedown", + .description = "When active the player is swimming down in a liquid" +}; +in_button_t in_strafe = { + .name = "strafe", + .description = "When active, +left and +right function like +moveleft and" + " +moveright" +}; +in_button_t in_klook = { + .name = "klook", + .description = "When active, +forward and +back perform +lookup and" + " +lookdown" +}; +in_button_t in_speed = { + .name = "speed", + .description = "When active the player is running" +}; +in_button_t in_mlook = { + .name = "mlook", + .description = "When active moving the mouse or joystick forwards " + "and backwards performs +lookup and " + "+lookdown" +}; - Continuous button event tracking is complicated by the fact that two - different input sources (say, mouse button 1 and the control key) can - both press the same button, but the button should be released only when - both of the pressing key have been released. - - When a key event issues a button command (+forward, +attack, etc), it - appends its key number as a parameter to the command so it can be - matched up with the release. - - state bit 0 is the current state of the key - state bit 1 is edge triggered on the up to down transition - state bit 2 is edge triggered on the down to up transition -*/ - -in_button_t in_left, in_right, in_forward, in_back; -in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; -in_button_t in_use, in_jump, in_attack; -in_button_t in_up, in_down; -in_button_t in_strafe, in_klook, in_speed, in_mlook; - -static struct { - const char *name; - in_button_t *button; - const char *description; -} cl_in_buttons[] = { - { "left", &in_left, - "When active the player is turning left" - }, - { "right", &in_right, - "When active the player is turning right" - }, - { "forward", &in_forward, - "When active the player is moving forward" - }, - { "back", &in_back, - "When active the player is moving backwards" - }, - { "lookup", &in_lookup, - "When active the player's view is looking up" - }, - { "lookdown", &in_lookdown, - "When active the player's view is looking down" - }, - { "moveleft", &in_moveleft, - "When active the player is strafing left" - }, - { "moveright", &in_moveright, - "When active the player is strafing right" - }, - { "use", &in_use, - "Left over command for opening doors and triggering switches" - }, - { "jump", &in_jump, - "When active the player is jumping" - }, - { "attack", &in_attack, - "When active player is firing/using current weapon" - }, - { "moveup", &in_up, - "When active the player is swimming up in a liquid" - }, - { "movedown", &in_down, - "When active the player is swimming down in a liquid" - }, - { "strafe", &in_strafe, - "When active, +left and +right function like +moveleft and +moveright" - }, - { "speed", &in_speed, - "When active the player is running" - }, - { "klook", &in_klook, - "When active, +forward and +back perform +lookup and +lookdown" - }, - { "mlook", &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards performs +lookup and " - "+lookdown" - }, - { } +static in_button_t *cl_in_buttons[] = { + &in_left, + &in_right, + &in_forward, + &in_back, + &in_lookup, + &in_lookdown, + &in_moveleft, + &in_moveright, + &in_use, + &in_jump, + &in_attack, + &in_up, + &in_down, + &in_strafe, + &in_klook, + &in_speed, + &in_mlook, + 0 }; int in_impulse; @@ -351,9 +362,8 @@ CL_SendMove (usercmd_t *cmd) void CL_Input_Init (void) { - for (int i = 0; cl_in_buttons[i].name; i++) { - IN_RegisterButton (cl_in_buttons[i].button, cl_in_buttons[i].name, - cl_in_buttons[i].description); + for (int i = 0; cl_in_buttons[i]; i++) { + IN_RegisterButton (cl_in_buttons[i]); } Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 9bbc86e6a..cd6b497c6 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -63,88 +63,99 @@ cvar_t *cl_nodelta; cvar_t *cl_maxnetfps; cvar_t *cl_spamimpulse; -/* - KEY BUTTONS +in_button_t in_left = { + .name = "left", + .description = "When active the player is turning left" +}; +in_button_t in_right = { + .name = "right", + .description = "When active the player is turning right" +}; +in_button_t in_forward = { + .name = "forward", + .description = "When active the player is moving forward" +}; +in_button_t in_back = { + .name = "back", + .description = "When active the player is moving backwards" +}; +in_button_t in_lookup = { + .name = "lookup", + .description = "When active the player's view is looking up" +}; +in_button_t in_lookdown = { + .name = "lookdown", + .description = "When active the player's view is looking down" +}; +in_button_t in_moveleft = { + .name = "moveleft", + .description = "When active the player is strafing left" +}; +in_button_t in_moveright = { + .name = "moveright", + .description = "When active the player is strafing right" +}; +in_button_t in_use = { + .name = "use", + .description = "Left over command for opening doors and triggering" + " switches" +}; +in_button_t in_jump = { + .name = "jump", + .description = "When active the player is jumping" +}; +in_button_t in_attack = { + .name = "attack", + .description = "When active player is firing/using current weapon" +}; +in_button_t in_up = { + .name = "moveup", + .description = "When active the player is swimming up in a liquid" +}; +in_button_t in_down = { + .name = "movedown", + .description = "When active the player is swimming down in a liquid" +}; +in_button_t in_strafe = { + .name = "strafe", + .description = "When active, +left and +right function like +moveleft and" + " +moveright" +}; +in_button_t in_klook = { + .name = "klook", + .description = "When active, +forward and +back perform +lookup and" + " +lookdown" +}; +in_button_t in_speed = { + .name = "speed", + .description = "When active the player is running" +}; +in_button_t in_mlook = { + .name = "mlook", + .description = "When active moving the mouse or joystick forwards " + "and backwards performs +lookup and " + "+lookdown" +}; - Continuous button event tracking is complicated by the fact that two - different input sources (say, mouse button 1 and the control key) can - both press the same button, but the button should be released only when - both of the pressing key have been released. - - When a key event issues a button command (+forward, +attack, etc), it - appends its key number as a parameter to the command so it can be - matched up with the release. - - state bit 0 is the current state of the key - state bit 1 is edge triggered on the up to down transition - state bit 2 is edge triggered on the down to up transition -*/ - -in_button_t in_left, in_right, in_forward, in_back; -in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; -in_button_t in_use, in_jump, in_attack; -in_button_t in_up, in_down; -in_button_t in_strafe, in_klook, in_speed, in_mlook; - -static struct { - const char *name; - in_button_t *button; - const char *description; -} cl_in_buttons[] = { - { "left", &in_left, - "When active the player is turning left" - }, - { "right", &in_right, - "When active the player is turning right" - }, - { "forward", &in_forward, - "When active the player is moving forward" - }, - { "back", &in_back, - "When active the player is moving backwards" - }, - { "lookup", &in_lookup, - "When active the player's view is looking up" - }, - { "lookdown", &in_lookdown, - "When active the player's view is looking down" - }, - { "moveleft", &in_moveleft, - "When active the player is strafing left" - }, - { "moveright", &in_moveright, - "When active the player is strafing right" - }, - { "use", &in_use, - "Left over command for opening doors and triggering switches" - }, - { "jump", &in_jump, - "When active the player is jumping" - }, - { "attack", &in_attack, - "When active player is firing/using current weapon" - }, - { "moveup", &in_up, - "When active the player is swimming up in a liquid" - }, - { "movedown", &in_down, - "When active the player is swimming down in a liquid" - }, - { "strafe", &in_strafe, - "When active, +left and +right function like +moveleft and +moveright" - }, - { "speed", &in_speed, - "When active the player is running" - }, - { "klook", &in_klook, - "When active, +forward and +back perform +lookup and +lookdown" - }, - { "mlook", &in_mlook, - "When active moving the mouse or joystick forwards " - "and backwards performs +lookup and " - "+lookdown" - }, - { } +static in_button_t *cl_in_buttons[] = { + &in_left, + &in_right, + &in_forward, + &in_back, + &in_lookup, + &in_lookdown, + &in_moveleft, + &in_moveright, + &in_use, + &in_jump, + &in_attack, + &in_up, + &in_down, + &in_strafe, + &in_klook, + &in_speed, + &in_mlook, + 0 }; int in_impulse; @@ -508,9 +519,8 @@ CL_SendCmd (void) void CL_Input_Init (void) { - for (int i = 0; cl_in_buttons[i].name; i++) { - IN_RegisterButton (cl_in_buttons[i].button, cl_in_buttons[i].name, - cl_in_buttons[i].description); + for (int i = 0; cl_in_buttons[i]; i++) { + IN_RegisterButton (cl_in_buttons[i]); } Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); From 14a5ec7b41ec52b5a0fb0f75490331117b618a08 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Nov 2021 14:08:41 +0900 Subject: [PATCH 1778/3664] [input] Make device add/remove events broadcast It proved necessary to support broadcasting events to all event handlers, with device add/remove being the first such events. --- include/QF/input/event.h | 5 +++++ libs/input/in_event.c | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/QF/input/event.h b/include/QF/input/event.h index 1f960bda8..d16e66ac2 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -71,6 +71,11 @@ typedef enum { ie_button, } IE_event_type; +#define IE_broadcast_events (0 \ + | (1 << ie_add_device) \ + | (1 << ie_remove_device) \ + ) + typedef struct { IE_event_type type; uint64_t when; diff --git a/libs/input/in_event.c b/libs/input/in_event.c index aa302cf5b..b2aaf362c 100644 --- a/libs/input/in_event.c +++ b/libs/input/in_event.c @@ -54,6 +54,16 @@ static unsigned focus; int IE_Send_Event (const IE_event_t *event) { + if ((1 << event->type) & IE_broadcast_events) { + for (size_t i = 0; i < ie_handlers.size; i++) { + ie_reghandler_t *reg = &ie_handlers.a[i]; + if (reg->handler) { + reg->handler (event, reg->data); + } + } + return 1; + } + if (focus < ie_handlers.size && ie_handlers.a[focus].handler) { ie_reghandler_t *reg = &ie_handlers.a[focus]; return reg->handler (event, reg->data); From 825d8b7a49c57ff3ff8ba14408f77da2bbcbb6da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Nov 2021 19:02:39 +0900 Subject: [PATCH 1779/3664] [input] Make a start on the new binding system Input Mapping Tables are still at the core as they are a good concept, however they include both axis and button mappings, and the size is not hard-coded, but dependent on the known devices. Not much actually works yet (nq segfaults when a key is pressed). --- include/QF/Makemodule.am | 2 + include/QF/input.h | 9 +- include/QF/input/binding.h | 2 + include/QF/input/imt.h | 87 +++++++++++++ include/QF/keys.h | 24 +--- libs/gib/gib_keys.c | 2 +- libs/input/Makemodule.am | 4 +- libs/input/in_binding.c | 154 ++++++++++++++++++++++ libs/input/in_common.c | 9 +- libs/input/in_evdev.c | 7 - libs/input/in_imt.c | 238 ++++++++++++++++++++++++++++++++++ libs/input/keys.c | 165 +++++++++++++++++------ libs/ruamoko/rua_keys.c | 6 +- ruamoko/qwaq/builtins/input.c | 1 + 14 files changed, 629 insertions(+), 81 deletions(-) create mode 100644 include/QF/input/imt.h create mode 100644 libs/input/in_binding.c create mode 100644 libs/input/in_imt.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 1e590ff2e..939878f42 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -114,6 +114,8 @@ include_qf_glsl = \ include_qf_input = \ include/QF/binding.h \ include/QF/event.h + include/QF/imt.h + include_qf_math = \ include/QF/math/dual.h \ include/QF/math/half.h \ diff --git a/include/QF/input.h b/include/QF/input.h index 9405e0e02..eb2cc9e3b 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -45,6 +45,7 @@ typedef struct in_buttoninfo_s { } in_buttoninfo_t; #include "QF/input/binding.h" +#include "QF/input/imt.h" #ifndef __QFCC__ @@ -104,15 +105,17 @@ typedef struct in_device_s { \a button_info holds the current raw state of the button \a axis_imt_id is 0 if the device has no axis bindings, otherwise it is - the based index into the imt array for the imt group. + the index into the imt array for the imt group. - \a button_imt_i is 0 if the device has no button bindings, otherwise it + \a button_imt_id is 0 if the device has no button bindings, otherwise it is the index into the imt array for the imt group. */ typedef struct in_devbindings_s { const char *name; ///< name used when binding inputs const char *id; ///< physical device name or id (preferred) - in_device_t *device; ///< device associated with these bindings + int devid; ///< id of device associated with these bindings + int num_axes; + int num_buttons; in_axisinfo_t *axis_info; ///< axis range info and raw state in_buttoninfo_t *button_info; ///< button raw state int axis_imt_id; ///< index into array of imt axis bindings diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 60cf27196..bf02cef4b 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -217,6 +217,8 @@ int IN_RegisterAxis (in_axis_t *axis, const char *name, const char *description); in_button_t *IN_FindButton (const char *name); +void IN_Binding_Init (void); + #endif #endif//__QF_input_binding_h diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h new file mode 100644 index 000000000..e5cc8b02d --- /dev/null +++ b/include/QF/input/imt.h @@ -0,0 +1,87 @@ +/* + imt.h + + Input Mapping Table management + + Copyright (C) 2001 Zephaniah E. Hull + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_input_imt_h +#define __QF_input_imt_h + +#ifndef __QFCC__ + +#include "QF/darray.h" + +#include "QF/input/binding.h" + +typedef enum { + imt_button, + imt_axis, +} imt_type; + +/** Describe a region of imt bindings (axis or button) + + Each device may have a block of axis bindings and a block of button + bindings (some devices will have only the one block). The device name is + used instead of a pointer to the device descriptor so configs can be + preserved even if the device is not present. + + Bindings are allocated to a device in contiguous blocks. +*/ +typedef struct imt_block_s { + const char *device; ///< name of the owning device + int base; ///< index of first binding + int count; ///< number of bindings +} imt_block_t; + +/** Input Mapping Table +*/ +typedef struct imt_s { + struct imt_s *next; ///< list of tables attached to key_dest + struct imt_s *chain; ///< fallback table if input not bound + const char *name; ///< for user interaction + int written; + struct DARRAY_TYPE (in_axisbinding_t *) axis_bindings; + struct DARRAY_TYPE (in_buttonbinding_t *) button_bindings; +} imt_t; + +typedef struct in_context_s { + imt_t *imts; + imt_t **imt_tail; + imt_t *active_imt; + imt_t *default_imt; +} in_context_t; + +int IMT_GetAxisBlock (const char *device, int num_axes); +int IMT_GetButtonBlock (const char *device, int num_buttons); +int IMT_CreateContext (void); +imt_t *IMT_FindIMT (const char *name); +int IMT_CreateIMT (int context, const char *imt_name, + const char *chain_imt_name); +void IMT_ProcessAxis (int axis, int value); +void IMT_ProcessButton (int button, int state); + +#endif + +#endif//__QF_input_imt_h diff --git a/include/QF/keys.h b/include/QF/keys.h index 3919eebc3..c55d76fd8 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -534,26 +534,12 @@ typedef enum { #ifndef __QFCC__ extern knum_t key_toggleconsole; -typedef struct keybind_s { - char *str; -} keybind_t; - -/** Input Mapping Table -*/ -typedef struct imt_s { - struct imt_s *next; ///< list of tables attached to key_dest - struct imt_s *chain; ///< fallback table if key not bound - const char *name; ///< for user interaction - keybind_t bindings[QFK_LAST]; - int written; ///< avoid duplicate config file writes -} imt_t; - /** Chain of input mapping tables ascociated with a keydest sub-system (game, menu, etc). */ typedef struct keytarget_s { - imt_t *imts; ///< list of tables attached to this target - imt_t *active; ///< currently active table in this target + struct imt_s *imts; ///< list of tables attached to this target + struct imt_s *active; ///< currently active table in this target } keytarget_t; extern int keydown[QFK_LAST]; @@ -612,7 +598,7 @@ void Key_Init_Cvars (void); \param imt_name The name of the imt to find. Case insensitive. \return The named imt, or null if not found. */ -imt_t *Key_FindIMT (const char *imt_name) __attribute__((pure)); +struct imt_s *Key_FindIMT (const char *imt_name) __attribute__((pure)); /** Create a new imt and attach it to the specified keydest target. @@ -667,7 +653,7 @@ void Key_ClearStates (void); \param key The key for which to get the binding. \return The command string bound to the key, or null if unbound. */ -const char *Key_GetBinding (imt_t *imt, knum_t key) __attribute__((pure)); +const char *Key_GetBinding (struct imt_s *imt, knum_t key) __attribute__((pure)); /** Bind a command string to a key in the specified input mapping table. @@ -678,7 +664,7 @@ const char *Key_GetBinding (imt_t *imt, knum_t key) __attribute__((pure)); \param keynum The key to which the command string will be bound. \param binding The command string that will be bound. */ -void Key_SetBinding (imt_t *imt, knum_t keynum, const char *binding); +void Key_SetBinding (struct imt_s *imt, knum_t keynum, const char *binding); /** Set the current keydest target. diff --git a/libs/gib/gib_keys.c b/libs/gib/gib_keys.c index 5cbb095ff..c40e1bb1c 100644 --- a/libs/gib/gib_keys.c +++ b/libs/gib/gib_keys.c @@ -37,7 +37,7 @@ #include "QF/cbuf.h" #include "QF/cmd.h" -#include "QF/keys.h" +#include "QF/input.h" #include "QF/sys.h" #include "QF/gib.h" diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index 7f9bdfff2..3455be6ab 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -21,9 +21,11 @@ libs_input_libQFinput_la_SOURCES= \ libs/input/keys.c \ libs/input/old_keys.c \ libs/input/in_axis.c \ + libs/input/in_binding.c \ libs/input/in_button.c \ libs/input/in_common.c \ - libs/input/in_event.c + libs/input/in_event.c \ + libs/input/in_imt.c EXTRA_LTLIBRARIES += \ libs/input/libinput_evdev.la diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c new file mode 100644 index 000000000..6bcbb5e66 --- /dev/null +++ b/libs/input/in_binding.c @@ -0,0 +1,154 @@ +/* + in_binding.c + + Input binding management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/11/2 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cmd.h" +#include "QF/hash.h" +#include "QF/input.h" +#include "QF/sys.h" + +#include "QF/input/imt.h" + +#include "QF/input/binding.h" +#include "QF/input/event.h" +#include "QF/input/imt.h" + +typedef struct DARRAY_TYPE (in_devbindings_t) in_devbindingset_t; + +static in_devbindingset_t devbindings = DARRAY_STATIC_INIT (8); + +static void +in_binding_add_device (const IE_event_t *ie_event) +{ + size_t devid = ie_event->device.devid; + if (devid >= devbindings.size) { + DARRAY_RESIZE (&devbindings, devid + 1); + memset (&devbindings.a[devid], 0, sizeof (in_devbindings_t)); + } + in_devbindings_t *db = &devbindings.a[devid]; + if (db->id) { + if (db->id != IN_GetDeviceId (devid)) { + Sys_Error ("in_binding_add_device: devid conflict: %zd", devid); + } + Sys_Printf ("in_binding_add_device: readd %s\n", db->id); + return; + } + db->id = IN_GetDeviceId (devid); + db->devid = devid; + IN_AxisInfo (devid, 0, &db->num_axes); + IN_ButtonInfo (devid, 0, &db->num_buttons); + db->axis_info = malloc (db->num_axes * sizeof (in_axisinfo_t) + + db->num_buttons * sizeof (in_buttoninfo_t)); + db->button_info = (in_buttoninfo_t *) &db->axis_info[db->num_axes]; + IN_AxisInfo (devid, db->axis_info, &db->num_axes); + IN_ButtonInfo (devid, db->button_info, &db->num_buttons); + Sys_Printf ("in_binding_add_device: %s %d %d\n", db->id, db->num_axes, + db->num_buttons); +} + +static void +in_binding_remove_device (const IE_event_t *ie_event) +{ + size_t devid = ie_event->device.devid; + in_devbindings_t *db = &devbindings.a[devid]; + + if (devid >= devbindings.size) { + Sys_Error ("in_binding_remove_device: invalid devid: %zd", devid); + } + if (!db->id) { + return; + } + free (db->axis_info); // axis and button info in same block + memset (db, 0, sizeof (*db)); +} + +static void +in_binding_axis (const IE_event_t *ie_event) +{ + size_t devid = ie_event->axis.devid; + int axis = ie_event->axis.axis; + int value = ie_event->axis.value; + in_devbindings_t *db = &devbindings.a[devid]; + + if (devid < devbindings.size && axis < db->num_axes) { + db->axis_info[axis].value = value; + if (db->axis_imt_id) { + IMT_ProcessAxis (db->axis_imt_id + axis, value); + } + } +} + +static void +in_binding_button (const IE_event_t *ie_event) +{ + size_t devid = ie_event->button.devid; + int button = ie_event->button.button; + int state = ie_event->button.state; + in_devbindings_t *db = &devbindings.a[devid]; + + if (devid < devbindings.size && button < db->num_buttons) { + db->button_info[button].state = state; + if (db->button_imt_id) { + IMT_ProcessButton (db->button_imt_id + button, state); + } + } +} + +static int +in_binding_event_handler (const IE_event_t *ie_event, void *unused) +{ + static void (*handlers[]) (const IE_event_t *ie_event) = { + [ie_add_device] = in_binding_add_device, + [ie_remove_device] = in_binding_remove_device, + [ie_axis] = in_binding_axis, + [ie_button] = in_binding_button, + }; + if (ie_event->type < 0 || ie_event->type > ie_button + || !handlers[ie_event->type]) { + return 0; + } + handlers[ie_event->type] (ie_event); + return 1; +} + +void +IN_Binding_Init (void) +{ + IE_Add_Handler (in_binding_event_handler, 0); +} diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 37378647a..01d6c023a 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -102,7 +102,7 @@ IN_DriverData (int handle, void *data) } static int -in_add_device (int driver, in_device_t *device, const char *name, +in_add_device (int driver, void *device, const char *name, const char *id) { size_t devid; @@ -353,7 +353,8 @@ IN_Init (cbuf_t *cbuf) in_regdriver_t *rd = &in_drivers.a[i]; rd->driver.init (rd->data); } - Key_Init (cbuf); + IN_Binding_Init (); + //Key_Init (cbuf); //JOY_Init (); in_mouse_x = in_mouse_y = 0.0; @@ -362,7 +363,7 @@ IN_Init (cbuf_t *cbuf) void IN_Init_Cvars (void) { - Key_Init_Cvars (); + //Key_Init_Cvars (); //JOY_Init_Cvars (); in_grab = Cvar_Get ("in_grab", "0", CVAR_ARCHIVE, IN_UpdateGrab, "With this set to 1, quake will grab the mouse, " @@ -392,7 +393,7 @@ IN_ClearStates (void) rd->driver.clear_states (rd->data); } } - Key_ClearStates (); + //Key_ClearStates (); } #ifdef HAVE_EVDEV diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 81ca2e6f9..0e1f50ecc 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -58,11 +58,6 @@ static int evdev_driver_handle = -1; static PR_RESMAP (devmap_t) devmap; static devmap_t *devmap_list; -static void -in_evdev_keydest_callback (keydest_t key_dest, void *data) -{ -} - static void in_evdev_add_select (qf_fd_set *fdset, int *maxfd, void *data) { @@ -179,8 +174,6 @@ device_remove (device_t *dev) static void in_evdev_init (void *data) { - Key_KeydestCallback (in_evdev_keydest_callback, 0); - inputlib_init (device_add, device_remove); } diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c new file mode 100644 index 000000000..4a00032f9 --- /dev/null +++ b/libs/input/in_imt.c @@ -0,0 +1,238 @@ +/* + in_imt.c + + Input Mapping Table management + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/10/30 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cmd.h" +#include "QF/hash.h" +#include "QF/sys.h" + +#include "QF/input/imt.h" + +#include "QF/input/binding.h" +#include "QF/input/imt.h" + +typedef struct DARRAY_TYPE (in_context_t) in_contextset_t; +typedef struct DARRAY_TYPE (imt_block_t) imt_blockset_t; +/** Binding blocks are allocated across all imts +*/ +static imt_blockset_t axis_blocks = DARRAY_STATIC_INIT (8); +static imt_blockset_t button_blocks = DARRAY_STATIC_INIT (8); + +static in_contextset_t in_contexts = DARRAY_STATIC_INIT (8); + +static imt_block_t * __attribute__((pure)) +imt_find_block (imt_blockset_t *blockset, const char *device) +{ + for (size_t i = 0; i < blockset->size; i++) { + if (strcmp (blockset->a[i].device, device) == 0) { + return &blockset->a[i]; + } + } + return 0; +} + +static imt_block_t * +imt_get_block (imt_blockset_t *blockset) +{ + return DARRAY_OPEN_AT (blockset, blockset->size, 1); +} + +static int +imt_get_next_base (imt_blockset_t *blockset) +{ + if (!blockset->size) { + return 0; + } + imt_block_t *b = &blockset->a[blockset->size - 1]; + return b->base + b->count; +} + +static int +imt_get_axis_block (int count) +{ + int base = imt_get_next_base (&axis_blocks); + + for (size_t i = 0; i < in_contexts.size; i++) { + for (imt_t *imt = in_contexts.a[i].imts; imt; imt = imt->next) { + in_axisbinding_t **binding; + binding = DARRAY_OPEN_AT (&imt->axis_bindings, base, count); + memset (binding, 0, count * sizeof (binding)); + } + } + return base; +} + +static int +imt_get_button_block (int count) +{ + int base = imt_get_next_base (&button_blocks); + + for (size_t i = 0; i < in_contexts.size; i++) { + for (imt_t *imt = in_contexts.a[i].imts; imt; imt = imt->next) { + in_buttonbinding_t **binding; + binding = DARRAY_OPEN_AT (&imt->button_bindings, base, count); + memset (binding, 0, count * sizeof (binding)); + } + } + return base; +} + +int +IMT_GetAxisBlock (const char *device, int num_axes) +{ + imt_block_t *block; + if (!(block = imt_find_block (&axis_blocks, device))) { + block = imt_get_block (&axis_blocks); + block->device = device; + block->base = imt_get_axis_block (num_axes); + block->count = num_axes; + } + return block - axis_blocks.a; +} + +int +IMT_GetButtonBlock (const char *device, int num_buttons) +{ + imt_block_t *block; + if (!(block = imt_find_block (&button_blocks, device))) { + block = imt_get_block (&button_blocks); + block->device = device; + block->base = imt_get_button_block (num_buttons); + block->count = num_buttons; + } + return block - button_blocks.a; +} + +int +IMT_CreateContext (void) +{ + in_context_t *ctx = DARRAY_OPEN_AT (&in_contexts, in_contexts.size, 1); + memset (ctx, 0, sizeof (*ctx)); + ctx->imt_tail = &ctx->imts; + return ctx - in_contexts.a; +} + +static imt_t * __attribute__ ((pure)) +imt_find_imt (in_context_t *ctx, const char *name) +{ + for (imt_t *imt = ctx->imts; imt; imt = imt->next) { + if (strcasecmp (imt->name, name) == 0) { + return imt; + } + } + return 0; +} + +imt_t * __attribute__ ((pure)) +IMT_FindIMT (const char *name) +{ + for (size_t i = 0; i < in_contexts.size; i++) { + in_context_t *ctx = &in_contexts.a[i]; + imt_t *imt = imt_find_imt (ctx, name); + if (imt) { + return imt; + } + } + return 0; +} + +int +IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name) +{ + in_context_t *ctx = &in_contexts.a[context]; + imt_t *imt; + imt_t *chain_imt = 0; + + if ((size_t) context >= in_contexts.size) { + Sys_Printf ("invalid imt context %d\n", context); + return 0; + } + + if (IMT_FindIMT (imt_name)) { + Sys_Printf ("imt %s already exists\n", imt_name); + return 0; + } + if (chain_imt_name) { + chain_imt = IMT_FindIMT (chain_imt_name); + if (!chain_imt) { + Sys_Printf ("chain imt %s does not exist\n", chain_imt_name); + return 0; + } + chain_imt = imt_find_imt (ctx, chain_imt_name); + if (!chain_imt) { + Sys_Printf ("chain imt %s not in target context\n", + chain_imt_name); + return 0; + } + } + imt = malloc (sizeof (imt_t)); + *ctx->imt_tail = imt; + ctx->imt_tail = &imt->next; + + imt->next = 0; + imt->chain = chain_imt; + imt->name = strdup (imt_name); + imt->written = 0; + DARRAY_INIT (&imt->axis_bindings, 8); + DARRAY_INIT (&imt->button_bindings, 8); + int num_axes = imt_get_next_base (&axis_blocks); + int num_buttons = imt_get_next_base (&button_blocks); + DARRAY_RESIZE (&imt->axis_bindings, num_axes); + DARRAY_RESIZE (&imt->button_bindings, num_buttons); + if (num_axes) { + memset (imt->axis_bindings.a, 0, + num_axes * sizeof (in_axisbinding_t *)); + } + if (num_buttons) { + memset (imt->axis_bindings.a, 0, + num_buttons * sizeof (in_buttonbinding_t *)); + } + return 1; +} + +void +IMT_ProcessAxis (int axis, int value) +{ +} + +void +IMT_ProcessButton (int button, int state) +{ +} diff --git a/libs/input/keys.c b/libs/input/keys.c index 2a61122fd..87fc283f5 100644 --- a/libs/input/keys.c +++ b/libs/input/keys.c @@ -41,15 +41,44 @@ #include "QF/cbuf.h" #include "QF/cmd.h" +#include "QF/cmem.h" #include "QF/cvar.h" #include "QF/darray.h" #include "QF/dstring.h" #include "QF/keys.h" +#include "QF/input.h" #include "QF/sys.h" +#include "QF/va.h" #include "compat.h" #include "old_keys.h" +static memsuper_t *binding_mem; +/* +static in_axisbinding_t * +alloc_axis_binding (void) +{ + return cmemalloc (binding_mem, sizeof (in_axisbinding_t)); +} +*/ +static void +free_axis_binding (in_axisbinding_t *binding) +{ + cmemfree (binding_mem, binding); +} + +static in_buttonbinding_t * +alloc_button_binding (void) +{ + return cmemalloc (binding_mem, sizeof (in_buttonbinding_t)); +} + +static void +free_button_binding (in_buttonbinding_t *binding) +{ + cmemfree (binding_mem, binding); +} + /* key up events are sent even if in console mode */ static keydest_t key_dest = key_console; @@ -90,12 +119,6 @@ static const char *keydest_names[] = { "key_last" }; - -typedef struct { - const char *name; - imt_t imtnum; -} imtname_t; - typedef struct { const char *name; knum_t keynum; @@ -615,12 +638,25 @@ Key_SetBinding (imt_t *imt, knum_t keynum, const char *binding) if (keynum == (knum_t) -1) return; - if (imt->bindings[keynum].str) { - free (imt->bindings[keynum].str); - imt->bindings[keynum].str = NULL; + if (imt->button_bindings.a[keynum]) { + if (imt->button_bindings.a[keynum]->type == inb_command) { + free (imt->button_bindings.a[keynum]->command); + } + free_button_binding (imt->button_bindings.a[keynum]); + imt->button_bindings.a[keynum] = 0; } if (binding) { - imt->bindings[keynum].str = strdup(binding); + in_buttonbinding_t *b = alloc_button_binding (); + imt->button_bindings.a[keynum] = b; + in_button_t *button; + if (binding[0] == '+' && (button = IN_FindButton (binding + 1))) { + b->type = inb_button; + b->bind_id = keynum; //FIXME alloc? + b->button = button; + } else { + b->type = inb_command; + b->command = strdup(binding); + } } } @@ -659,14 +695,23 @@ process_binding (knum_t key, const char *kb) static qboolean Key_Game (knum_t key, short unicode) { - const char *kb; imt_t *imt = key_targets[key_dest].active; while (imt) { - kb = imt->bindings[key].str; - if (kb) { - if (keydown[key] <= 1) - process_binding (key, kb); + in_buttonbinding_t *b = imt->button_bindings.a[key]; + if (b) { + switch (b->type) { + case inb_button: + if (keydown[key] <= 1) { + IN_ButtonAction (b->button, key, keydown[key]); + } + break; + case inb_command: + if (keydown[key] <= 1) { + process_binding (key, b->command); + } + break; + } return true; } imt = imt->chain; @@ -830,9 +875,20 @@ Key_IMT_Drop_All_f (void) while (key_targets[kd].imts) { imt = key_targets[kd].imts; key_targets[kd].imts = imt->next; - for (int i = 0; i < QFK_LAST; i++) { - if (imt->bindings[i].str) { - free (imt->bindings[i].str); + for (size_t i = 0; i < imt->axis_bindings.size; i++) { + free_axis_binding (imt->axis_bindings.a[i]); + } + for (size_t i = 0; i < imt->button_bindings.size; i++) { + in_buttonbinding_t *b = imt->button_bindings.a[i]; + if (b) { + switch (b->type) { + case inb_button: + break; + case inb_command: + free (b->command); + break; + } + free_button_binding (b); } } free ((char *) imt->name); @@ -843,7 +899,7 @@ Key_IMT_Drop_All_f (void) } static void -Key_In_Bind (const char *imt_name, const char *key_name, const char *cmd) +Key_In_BindButton (const char *imt_name, const char *key_name, const char *cmd) { imt_t *imt; int key; @@ -861,11 +917,21 @@ Key_In_Bind (const char *imt_name, const char *key_name, const char *cmd) } if (!cmd) { - if (imt->bindings[key].str) - Sys_Printf ("%s %s \"%s\"\n", imt_name, key_name, - imt->bindings[key].str); - else + in_buttonbinding_t *b = imt->button_bindings.a[key]; + if (b) { + switch (b->type) { + case inb_button: + Sys_Printf ("%s %s \"+%s\"\n", imt_name, key_name, + b->button->name); + break; + case inb_command: + Sys_Printf ("%s %s \"%s\"\n", imt_name, key_name, + b->command); + break; + } + } else { Sys_Printf ("%s %s is not bound\n", imt_name, key_name); + } return; } Key_SetBinding (imt, key, cmd); @@ -880,25 +946,25 @@ Key_In_Bind_f (void) c = Cmd_Argc (); - if (c < 3) { - Sys_Printf ("in_bind [command] : attach a command to a " - "key\n"); + if (c < 4 || strcmp (Cmd_Argv (2), "button") != 0) { + Sys_Printf ("in_bind button [command]\n" + " attach a command to a key\n"); return; } imt = Cmd_Argv (1); - key = Cmd_Argv (2); + key = Cmd_Argv (3); - if (c >= 4) { + if (c >= 5) { cmd_buf = dstring_newstr (); - for (i = 3; i < c; i++) { + for (i = 4; i < c; i++) { dasprintf (cmd_buf, "%s%s", i > 3 ? " " : "", Cmd_Argv (i)); } cmd = cmd_buf->str; } - Key_In_Bind (imt, key, cmd); + Key_In_BindButton (imt, key, cmd); if (cmd_buf) { dstring_delete (cmd_buf); } @@ -941,7 +1007,7 @@ Key_Bind_f (void) cmd = cmd_buf->str; } - Key_In_Bind ("imt_mod", key, cmd); + Key_In_BindButton ("imt_mod", key, cmd); if (cmd_buf) { dstring_delete (cmd_buf); } @@ -1054,9 +1120,6 @@ key_printf (QFile *f, const char *fmt, ...) static void key_write_imt (QFile *f, keydest_t kd, imt_t *imt) { - int i; - const char *bind; - if (!imt || imt->written) { return; } @@ -1068,11 +1131,19 @@ key_write_imt (QFile *f, keydest_t kd, imt_t *imt) } else { key_printf (f, "imt_create %s %s\n", keydest_names[kd], imt->name); } - for (i = 0; i < QFK_LAST; i++) { - bind = imt->bindings[i].str; - if (bind) { - key_printf (f, "in_bind %s %s \"%s\"\n", imt->name, - Key_KeynumToString (i), bind); + for (size_t i = 0; i < imt->button_bindings.size; i++) { + in_buttonbinding_t *b = imt->button_bindings.a[i]; + if (b) { + switch (b->type) { + case inb_button: + key_printf (f, "in_bind %s button %s \"+%s\"\n", imt->name, + Key_KeynumToString (i), b->button->name); + break; + case inb_command: + key_printf (f, "in_bind %s button %s \"%s\"\n", imt->name, + Key_KeynumToString (i), b->command); + break; + } } } } @@ -1161,7 +1232,7 @@ Key_Event (knum_t key, short unicode, qboolean down) //FIXME maybe still a tad over-coupled. Use callbacks for menu and console //toggles? Should keys know anything about menu and console? if (key_dest != key_console && key == key_toggleconsole - && keydown[key] == 1) { + && keydown[key] == 1) { Cbuf_AddText (cbuf, "toggleconsole"); return; } @@ -1258,8 +1329,8 @@ Key_CreateDefaultIMTs (void) default_imts[i].chain_imt_name); } for (i = 0; default_bindings[i].imt; i++) { - Key_In_Bind (default_bindings[i].imt, default_bindings[i].key, - default_bindings[i].command); + Key_In_BindButton (default_bindings[i].imt, default_bindings[i].key, + default_bindings[i].command); } } @@ -1320,7 +1391,15 @@ const char * Key_GetBinding (imt_t *imt, knum_t key) { if (imt) { - return imt->bindings[key].str; + in_buttonbinding_t *b = imt->button_bindings.a[key]; + if (b) { + switch (b->type) { + case inb_button: + return va (0, "+%s", b->button->name); + case inb_command: + return b->command; + } + } } return 0; } diff --git a/libs/ruamoko/rua_keys.c b/libs/ruamoko/rua_keys.c index fbd978071..f5617406b 100644 --- a/libs/ruamoko/rua_keys.c +++ b/libs/ruamoko/rua_keys.c @@ -36,7 +36,7 @@ #endif #include "QF/csqc.h" -#include "QF/keys.h" +#include "QF/input.h" #include "QF/progs.h" #include "QF/zone.h" @@ -89,7 +89,7 @@ bi_Key_LookupBinding (progs_t *pr) imt = Key_FindIMT (imt_name); if (imt) { for (i = 0; i < QFK_LAST; i++) { - keybind = imt->bindings[i].str; +//XXX keybind = imt->button_bindings.a[i].str; if (keybind == NULL) { continue; } @@ -123,7 +123,7 @@ bi_Key_CountBinding (progs_t *pr) imt = Key_FindIMT (imt_name); if (imt) { for (i = 0; i < QFK_LAST; i++) { - keybind = imt->bindings[i].str; +//XXX keybind = imt->button_bindings.a[i].str; if (keybind == NULL) { continue; } diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index a37b45acb..6d62ce4a2 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -563,6 +563,7 @@ static void qwaq_input_init (qwaq_input_resources_t *res) { res->input_event_handler = IE_Add_Handler (qwaq_input_event_handler, res); + IE_Set_Focus (res->input_event_handler); IN_DriverData (term_driver_handle, res); if (res->key_sequences) { From 16d1232b9198ad7e6e32cb186bc7a395a9818209 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Nov 2021 22:20:17 +0900 Subject: [PATCH 1780/3664] [x11] Connect the X11 input driver to input events Now nothing works at all ;) However, that's only because the binding system is incomplete: the X11 input events are getting through to the binding system, so now it's just a matter of getting that to work. --- libs/input/in_common.c | 2 +- libs/video/targets/in_x11.c | 206 ++++++++++++++++++++++++++++-------- 2 files changed, 162 insertions(+), 46 deletions(-) diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 01d6c023a..1cded200c 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -348,12 +348,12 @@ void IN_Init (cbuf_t *cbuf) { Sys_RegisterShutdown (IN_shutdown, 0); + IN_Binding_Init (); for (size_t i = 0; i < in_drivers.size; i++) { in_regdriver_t *rd = &in_drivers.a[i]; rd->driver.init (rd->data); } - IN_Binding_Init (); //Key_Init (cbuf); //JOY_Init (); diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 39eaf89bd..f68fed410 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -73,12 +73,44 @@ #include "QF/sound.h" #include "QF/sys.h" +#include "QF/input/event.h" + #include "compat.h" #include "context_x11.h" #include "dga_check.h" #include "qfselect.h" #include "vid_internal.h" +typedef struct x11_device_s { + const char *name; + int num_axes; + int num_buttons; + in_axisinfo_t *axes; + in_buttoninfo_t *buttons; + int devid; +} x11_device_t; + +// The X11 protocol supports only 256 keys +static in_buttoninfo_t x11_key_buttons[256]; +// X11 mice have only two axes (FIXME always true?) +static in_axisinfo_t x11_mouse_axes[2]; +// FIXME assume up to 32 mouse buttons +static in_buttoninfo_t x11_mouse_buttons[32]; + +#define infosize(x) (sizeof (x) / sizeof (x[0])) + +static x11_device_t x11_keyboard_device = { + "x11:keyboard", + 0, infosize (x11_key_buttons), + 0, x11_key_buttons, +}; + +static x11_device_t x11_mouse_device = { + "x11:mouse", + infosize (x11_mouse_axes), infosize (x11_mouse_buttons), + x11_mouse_axes, x11_mouse_buttons, +}; + cvar_t *in_snd_block; cvar_t *in_dga; cvar_t *in_mouse_accel; @@ -89,6 +121,7 @@ static int p_mouse_x, p_mouse_y; static int input_grabbed = 0; static int x11_fd; +static int x11_driver_handle = -1; static void dga_on (void) @@ -195,7 +228,7 @@ enter_notify (XEvent *event) p_mouse_x = event->xmotion.x; p_mouse_y = event->xmotion.y; } - +#if 0 static void XLateKey (XKeyEvent *ev, int *k, int *u) { @@ -597,6 +630,7 @@ XLateKey (XKeyEvent *ev, int *k, int *u) *k = key; *u = unicode; } +#endif static void in_x11_keydest_callback (keydest_t key_dest, void *data) @@ -608,43 +642,6 @@ in_x11_keydest_callback (keydest_t key_dest, void *data) // } } -static void -event_key (XEvent *event) -{ - int key, unicode; - - x_time = event->xkey.time; - XLateKey (&event->xkey, &key, &unicode); - Key_Event (key, unicode, event->type == KeyPress); -} - -static void -event_button (XEvent *event) -{ - unsigned but; - - x_time = event->xbutton.time; - - but = event->xbutton.button; - if (but > 32) - return; - if (but == 2) - but = 3; - else if (but == 3) - but = 2; - switch (but) { - default: - Key_Event (QFM_BUTTON1 + but - 1, 0, event->type == ButtonPress); - break; - case 4: - Key_Event (QFM_WHEEL_UP, 0, event->type == ButtonPress); - break; - case 5: - Key_Event (QFM_WHEEL_DOWN, 0, event->type == ButtonPress); - break; - } -} - static void event_focusout (XEvent *event) { @@ -686,6 +683,36 @@ center_pointer (void) viddef.width / 2, viddef.height / 2); } +static void +in_x11_send_axis_event (int devid, in_axisinfo_t *axis) +{ + IE_event_t event = { + .type = ie_axis, + .when = Sys_LongTime (), + .axis = { + .devid = devid, + .axis = axis->axis, + .value = axis->value, + }, + }; + IE_Send_Event (&event); +} + +static void +in_x11_send_button_event (int devid, in_buttoninfo_t *button) +{ + IE_event_t event = { + .type = ie_button, + .when = Sys_LongTime (), + .button = { + .devid = devid, + .button = button->button, + .state = button->state, + }, + }; + IE_Send_Event (&event); +} + static void event_motion (XEvent *event) { @@ -697,26 +724,67 @@ event_motion (XEvent *event) } if (dga_active) { - in_mouse_x += event->xmotion.x_root; - in_mouse_y += event->xmotion.y_root; + x11_mouse_axes[0].value = event->xmotion.x_root; + x11_mouse_axes[1].value = event->xmotion.y_root; } else { if (vid_fullscreen->int_val || input_grabbed) { if (!event->xmotion.send_event) { unsigned dist_x = abs (viddef.width / 2 - event->xmotion.x); unsigned dist_y = abs (viddef.height / 2 - event->xmotion.y); - in_mouse_x += (event->xmotion.x - p_mouse_x); - in_mouse_y += (event->xmotion.y - p_mouse_y); + + x11_mouse_axes[0].value = event->xmotion.x - p_mouse_x; + x11_mouse_axes[1].value = event->xmotion.y - p_mouse_y; if (dist_x > viddef.width / 4 || dist_y > viddef.height / 4) { center_pointer (); } } } else { - in_mouse_x += (event->xmotion.x - p_mouse_x); - in_mouse_y += (event->xmotion.y - p_mouse_y); + x11_mouse_axes[0].value = event->xmotion.x - p_mouse_x; + x11_mouse_axes[1].value = event->xmotion.y - p_mouse_y; } p_mouse_x = event->xmotion.x; p_mouse_y = event->xmotion.y; } + in_x11_send_axis_event (x11_mouse_device.devid, &x11_mouse_axes[0]); + in_x11_send_axis_event (x11_mouse_device.devid, &x11_mouse_axes[1]); +} + +static void +event_button (XEvent *event) +{ + unsigned but; + + x_time = event->xbutton.time; + + but = event->xbutton.button; + if (but > 32) { + return; + } + + if (but == 2) { + but = 3; + } else if (but == 3) { + but = 2; + } + + x11_mouse_buttons[but].state = event->type == ButtonPress; + in_x11_send_button_event (x11_mouse_device.devid, &x11_mouse_buttons[but]); +} + +static void +event_key (XEvent *event) +{ + int key/*, unicode*/; + + x_time = event->xkey.time; + // X11 protocol supports only 256 keys. The key codes are the AT scan codes + // offset by 8 (so Esc is 9 instead of 1). + key = (event->xkey.keycode - 8) & 0xff; + x11_key_buttons[key].state = event->type == KeyPress; + in_x11_send_button_event (x11_keyboard_device.devid, + &x11_key_buttons[key]); + //XLateKey (&event->xkey, &key, &unicode); + //Key_Event (key, unicode, event->type == KeyPress); } static void @@ -799,6 +867,35 @@ in_x11_check_select (qf_fd_set *fdset, void *data) } } +static void +in_x11_axis_info (void *data, void *device, in_axisinfo_t *axes, int *numaxes) +{ + x11_device_t *dev = device; + if (!axes) { + *numaxes = dev->num_axes; + return; + } + if (*numaxes > dev->num_axes) { + *numaxes = dev->num_axes; + } + memcpy (axes, dev->axes, *numaxes * sizeof (in_axisinfo_t)); +} + +static void +in_x11_button_info (void *data, void *device, in_buttoninfo_t *buttons, + int *numbuttons) +{ + x11_device_t *dev = device; + if (!buttons) { + *numbuttons = dev->num_buttons; + return; + } + if (*numbuttons > dev->num_buttons) { + *numbuttons = dev->num_buttons; + } + memcpy (buttons, dev->buttons, *numbuttons * sizeof (in_buttoninfo_t)); +} + static void in_x11_shutdown (void *data) { @@ -825,6 +922,18 @@ in_x11_init_cvars (void) "set to 0 to remove mouse acceleration"); } +static void +x11_add_device (x11_device_t *dev) +{ + for (int i = 0; i < dev->num_axes; i++) { + dev->axes[i].axis = i; + } + for (int i = 0; i < dev->num_buttons; i++) { + dev->buttons[i].button = i; + } + dev->devid = IN_AddDevice (x11_driver_handle, dev, dev->name, dev->name); +} + static void in_x11_init (void *data) { @@ -860,6 +969,8 @@ in_x11_init (void *data) X11_AddEvent (SelectionNotify, &selection_notify); X11_AddEvent (EnterNotify, &enter_notify); + x11_add_device (&x11_keyboard_device); + if (!COM_CheckParm ("-nomouse")) { dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", dga_avail); @@ -868,6 +979,8 @@ in_x11_init (void *data) X11_AddEvent (ButtonRelease, &event_button); X11_AddEvent (MotionNotify, &event_motion); + x11_add_device (&x11_mouse_device); + in_mouse_avail = 1; } @@ -889,12 +1002,15 @@ static in_driver_t in_x11_driver = { .check_select = in_x11_check_select, .clear_states = in_x11_clear_states, .grab_input = in_x11_grab_input, + + .axis_info = in_x11_axis_info, + .button_info = in_x11_button_info, }; static void __attribute__((constructor)) in_x11_register_driver (void) { - IN_RegisterDriver (&in_x11_driver, 0); + x11_driver_handle = IN_RegisterDriver (&in_x11_driver, 0); } int x11_force_link; From af56e9242bd0dbbdb8410ac0017302d67fe769e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 3 Nov 2021 22:22:37 +0900 Subject: [PATCH 1781/3664] [x11] Clean up duplicate code in software updates The actual x11 update code was identical between all versions, so it was moved into the one function. --- libs/video/targets/vid_x11_sw.c | 116 +++++++++----------------------- 1 file changed, 32 insertions(+), 84 deletions(-) diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 938e085ba..b52d3366d 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -278,6 +278,30 @@ st3_fixup (XImage * framebuf, int x, int y, int width, int height) } } +static void +x11_put_image (vrect_t *rects) +{ + if (doShm) { + if (!XShmPutImage (x_disp, x_win, x_gc, + x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height, True)) { + Sys_Error ("VID_Update: XShmPutImage failed"); + } + oktodraw = false; + while (!oktodraw) + X11_ProcessEvent (); + + current_framebuffer = !current_framebuffer; + } else { + if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height)) { + Sys_Error ("VID_Update: XPutImage failed"); + } + } +} + /* Flush the given rectangles from the view buffer to the screen. */ @@ -295,27 +319,8 @@ x11_sw8_update (sw_ctx_t *ctx, vrect_t *rects) rects->x, rects->y, rects->width, rects->height); break; } - if (doShm) { - if (!XShmPutImage (x_disp, x_win, x_gc, - x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height, True)) { - Sys_Error ("VID_Update: XShmPutImage failed"); - } - oktodraw = false; - while (!oktodraw) - X11_ProcessEvent (); - rects = rects->next; - - current_framebuffer = !current_framebuffer; - } else { - if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height)) { - Sys_Error ("VID_Update: XPutImage failed"); - } - rects = rects->next; - } + x11_put_image (rects); + rects = rects->next; } XSync (x_disp, False); r_data->scr_fullupdate = 0; @@ -341,27 +346,8 @@ x11_sw16_16_update (sw_ctx_t *ctx, vrect_t *rects) *dest++ = *src++; } } - if (doShm) { - if (!XShmPutImage (x_disp, x_win, x_gc, - x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height, True)) { - Sys_Error ("VID_Update: XShmPutImage failed"); - } - oktodraw = false; - while (!oktodraw) - X11_ProcessEvent (); - rects = rects->next; - - current_framebuffer = !current_framebuffer; - } else { - if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height)) { - Sys_Error ("VID_Update: XPutImage failed"); - } - rects = rects->next; - } + x11_put_image (rects); + rects = rects->next; } XSync (x_disp, False); r_data->scr_fullupdate = 0; @@ -391,27 +377,8 @@ x11_sw16_32_update (sw_ctx_t *ctx, vrect_t *rects) | ((c & 0x001f) << 3); } } - if (doShm) { - if (!XShmPutImage (x_disp, x_win, x_gc, - x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height, True)) { - Sys_Error ("VID_Update: XShmPutImage failed"); - } - oktodraw = false; - while (!oktodraw) - X11_ProcessEvent (); - rects = rects->next; - - current_framebuffer = !current_framebuffer; - } else { - if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height)) { - Sys_Error ("VID_Update: XPutImage failed"); - } - rects = rects->next; - } + x11_put_image (rects); + rects = rects->next; } XSync (x_disp, False); r_data->scr_fullupdate = 0; @@ -437,27 +404,8 @@ x11_sw32_update (sw_ctx_t *ctx, vrect_t *rects) *dest++ = *src++; } } - if (doShm) { - if (!XShmPutImage (x_disp, x_win, x_gc, - x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height, True)) { - Sys_Error ("VID_Update: XShmPutImage failed"); - } - oktodraw = false; - while (!oktodraw) - X11_ProcessEvent (); - rects = rects->next; - - current_framebuffer = !current_framebuffer; - } else { - if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height)) { - Sys_Error ("VID_Update: XPutImage failed"); - } - rects = rects->next; - } + x11_put_image (rects); + rects = rects->next; } XSync (x_disp, False); r_data->scr_fullupdate = 0; From 7d022db702c43bd19e11a57de971969fbbd4cc81 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Nov 2021 09:56:08 +0900 Subject: [PATCH 1782/3664] [util] Avoid Sys_Shutdown for IO signals It turns out that calling Sys_Shutdown in the signal handler can cause lockups due to the signal occurring at unsafe times. Fortunately, this is just the IO related signals (INT, HUP, TERM, QUIT) as the others are usually caused by actual errors and should not occur in system code thus timing should not be an issue. However, care will need to be taken when it comes to handling SIGINT or similar for breaking runaway progs code when that time comes. --- libs/util/sys.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/util/sys.c b/libs/util/sys.c index a08a3350b..07ed52d05 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -932,7 +932,7 @@ signal_handler (int sig) case SIGTERM: signal (SIGINT, SIG_DFL); signal (SIGTERM, SIG_DFL); - Sys_Quit (); + exit(1); default: if (!setjmp (aiee_abort)) { if (signal_hook) @@ -986,10 +986,12 @@ signal_handler (int sig, siginfo_t *info, void *ucontext) case SIGINT: case SIGTERM: case SIGHUP: + case SIGQUIT: sigaction (SIGHUP, &save_hup, 0); sigaction (SIGINT, &save_int, 0); sigaction (SIGTERM, &save_term, 0); - Sys_Quit (); + sigaction (SIGQUIT, &save_quit, 0); + exit(1); default: if (!sigsetjmp (aiee_abort, 1)) { if (signal_hook) @@ -998,7 +1000,6 @@ signal_handler (int sig, siginfo_t *info, void *ucontext) } if (!recover) { - sigaction (SIGQUIT, &save_quit, 0); sigaction (SIGTRAP, &save_trap, 0); sigaction (SIGIOT, &save_iot, 0); sigaction (SIGBUS, &save_bus, 0); From 0a885fe7040332cea845d8fdda814baadecc4be6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Nov 2021 10:02:21 +0900 Subject: [PATCH 1783/3664] [x11] Rename x11 input devices to core The x11 keyboard and mouse devices are really core input devices rather than x11 input devices in that keyboard and mouse will be present on most systems and thus not specific to the main user interface (x11, windows, etc). --- libs/video/targets/in_x11.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index f68fed410..725e96925 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -100,13 +100,13 @@ static in_buttoninfo_t x11_mouse_buttons[32]; #define infosize(x) (sizeof (x) / sizeof (x[0])) static x11_device_t x11_keyboard_device = { - "x11:keyboard", + "core:keyboard", 0, infosize (x11_key_buttons), 0, x11_key_buttons, }; static x11_device_t x11_mouse_device = { - "x11:mouse", + "core:mouse", infosize (x11_mouse_axes), infosize (x11_mouse_buttons), x11_mouse_axes, x11_mouse_buttons, }; From 63f5c738cae6cb76e8074206f6214fcf5b9306c8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Nov 2021 13:26:44 +0900 Subject: [PATCH 1784/3664] [x11] Send cooked keyboard and mouse events For the mouse in x11, I'm not sure which is more cooked: deltas or window-relative coordinates, but I don't imagine that really matters too much. However, keyboard and mouse events suitable for 2D user interfaces are sent at the same time as the more game oriented button and axis events. --- include/QF/input/event.h | 23 ++++++++++- libs/video/targets/in_x11.c | 82 ++++++++++++++++++++++++++----------- 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/include/QF/input/event.h b/include/QF/input/event.h index d16e66ac2..648852258 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -33,14 +33,33 @@ #include "QF/qtypes.h" +typedef enum { + ies_shift = 1, + ies_capslock = 2, + ies_control = 4, + ies_alt = 8, +} IE_shift; + +typedef enum { + ie_mousedown, + ie_mouseup, + ie_mouseclick, + ie_mousemove, + ie_mouseauto, +} IE_mouse_type; + typedef struct { + IE_mouse_type type; + unsigned shift; ///< ored bit pattern of IE_shift int x, y; unsigned buttons; + int click; } IE_mouse_event_t; typedef struct { - int key_code; - qboolean pressed; + int code; + int unicode; + unsigned shift; ///< ored bit pattern of IE_shift } IE_key_event_t; typedef struct { diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 725e96925..5dee7cb3d 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -117,7 +117,8 @@ cvar_t *in_mouse_accel; static qboolean dga_avail; static qboolean dga_active; -static int p_mouse_x, p_mouse_y; +static IE_mouse_event_t x11_mouse; +static IE_key_event_t x11_key; static int input_grabbed = 0; static int x11_fd; @@ -225,10 +226,10 @@ enter_notify (XEvent *event) { x_time = event->xcrossing.time; - p_mouse_x = event->xmotion.x; - p_mouse_y = event->xmotion.y; + x11_mouse.x = event->xmotion.x; + x11_mouse.y = event->xmotion.y; } -#if 0 + static void XLateKey (XKeyEvent *ev, int *k, int *u) { @@ -630,7 +631,6 @@ XLateKey (XKeyEvent *ev, int *k, int *u) *k = key; *u = unicode; } -#endif static void in_x11_keydest_callback (keydest_t key_dest, void *data) @@ -698,6 +698,29 @@ in_x11_send_axis_event (int devid, in_axisinfo_t *axis) IE_Send_Event (&event); } +static void +in_x11_send_mouse_event (IE_mouse_type type) +{ + IE_event_t event = { + .type = ie_mouse, + .when = Sys_LongTime (), + .mouse = x11_mouse, + }; + event.mouse.type = type; + IE_Send_Event (&event); +} + +static void +in_x11_send_key_event (int press) +{ + IE_event_t event = { + .type = ie_key, + .when = Sys_LongTime (), + .key = x11_key, + }; + IE_Send_Event (&event); +} + static void in_x11_send_button_event (int devid, in_buttoninfo_t *button) { @@ -718,8 +741,8 @@ event_motion (XEvent *event) { x_time = event->xmotion.time; if (x_time <= x_mouse_time) { - p_mouse_x = event->xmotion.x; - p_mouse_y = event->xmotion.y; + x11_mouse.x = event->xmotion.x; + x11_mouse.y = event->xmotion.y; return; } @@ -732,21 +755,24 @@ event_motion (XEvent *event) unsigned dist_x = abs (viddef.width / 2 - event->xmotion.x); unsigned dist_y = abs (viddef.height / 2 - event->xmotion.y); - x11_mouse_axes[0].value = event->xmotion.x - p_mouse_x; - x11_mouse_axes[1].value = event->xmotion.y - p_mouse_y; + x11_mouse_axes[0].value = event->xmotion.x - x11_mouse.x; + x11_mouse_axes[1].value = event->xmotion.y - x11_mouse.y; if (dist_x > viddef.width / 4 || dist_y > viddef.height / 4) { center_pointer (); } } } else { - x11_mouse_axes[0].value = event->xmotion.x - p_mouse_x; - x11_mouse_axes[1].value = event->xmotion.y - p_mouse_y; + x11_mouse_axes[0].value = event->xmotion.x - x11_mouse.x; + x11_mouse_axes[1].value = event->xmotion.y - x11_mouse.y; } - p_mouse_x = event->xmotion.x; - p_mouse_y = event->xmotion.y; } in_x11_send_axis_event (x11_mouse_device.devid, &x11_mouse_axes[0]); in_x11_send_axis_event (x11_mouse_device.devid, &x11_mouse_axes[1]); + + x11_mouse.shift = event->xmotion.state & 0xff; + x11_mouse.x = event->xmotion.x; + x11_mouse.y = event->xmotion.y; + in_x11_send_mouse_event (ie_mousemove); } static void @@ -756,25 +782,31 @@ event_button (XEvent *event) x_time = event->xbutton.time; - but = event->xbutton.button; - if (but > 32) { + but = event->xbutton.button - 1; + if (but >= 32) { return; } - if (but == 2) { - but = 3; - } else if (but == 3) { - but = 2; - } + int press = event->type == ButtonPress; - x11_mouse_buttons[but].state = event->type == ButtonPress; + x11_mouse_buttons[but].state = press; in_x11_send_button_event (x11_mouse_device.devid, &x11_mouse_buttons[but]); + + x11_mouse.shift = event->xmotion.state & 0xff; + x11_mouse.x = event->xmotion.x; + x11_mouse.y = event->xmotion.y; + if (press) { + x11_mouse.buttons |= 1 << but; + } else { + x11_mouse.buttons &= ~(1 << but); + } + in_x11_send_mouse_event (press ? ie_mousedown : ie_mouseup); } static void event_key (XEvent *event) { - int key/*, unicode*/; + int key; x_time = event->xkey.time; // X11 protocol supports only 256 keys. The key codes are the AT scan codes @@ -783,8 +815,10 @@ event_key (XEvent *event) x11_key_buttons[key].state = event->type == KeyPress; in_x11_send_button_event (x11_keyboard_device.devid, &x11_key_buttons[key]); - //XLateKey (&event->xkey, &key, &unicode); - //Key_Event (key, unicode, event->type == KeyPress); + + x11_key.shift = event->xmotion.state & 0xff; + XLateKey (&event->xkey, &x11_key.code, &x11_key.unicode); + in_x11_send_key_event (event->type == KeyPress); } static void From 0c8fbf0ce434a333b965fd7731e76283301cc5af Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Nov 2021 13:30:01 +0900 Subject: [PATCH 1785/3664] [x11] Don't use select for checking for events It seems that under certain circumstances (window managers?), select is not reliable for getting key events, so use of select has been disabled until I figure out what's going on and how to fix it. --- libs/video/targets/in_x11.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 5dee7cb3d..9d3d45619 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -883,7 +883,7 @@ in_x11_grab_input (void *data, int grab) in_dga_f (in_dga); } } - +#ifdef X11_USE_SELECT static void in_x11_add_select (qf_fd_set *fdset, int *maxfd, void *data) { @@ -897,10 +897,17 @@ static void in_x11_check_select (qf_fd_set *fdset, void *data) { if (QF_FD_ISSET (x11_fd, fdset)) { + Sys_Printf ("in_x11_check_select\n"); X11_ProcessEvents (); // Get events from X server. } } - +#else +static void +in_x11_process_events (void *data) +{ + X11_ProcessEvents (); // Get events from X server. +} +#endif static void in_x11_axis_info (void *data, void *device, in_axisinfo_t *axes, int *numaxes) { @@ -1032,8 +1039,12 @@ in_x11_clear_states (void *data) static in_driver_t in_x11_driver = { .init = in_x11_init, .shutdown = in_x11_shutdown, +#ifdef X11_USE_SELECT .add_select = in_x11_add_select, .check_select = in_x11_check_select, +#else + .process_events = in_x11_process_events, +#endif .clear_states = in_x11_clear_states, .grab_input = in_x11_grab_input, From 31c1eae1ecce6a5749338567a4161e3b6dd37219 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Nov 2021 14:54:33 +0900 Subject: [PATCH 1786/3664] [x11] Send key events for pasted text I'm undecided if the pasted text should be sent as a string rather than individual key events, but this will do the job for now as it gets me closer to being able to test everything. --- libs/video/targets/in_x11.c | 71 +++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 9d3d45619..561365c9b 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -188,39 +188,6 @@ in_paste_buffer_f (void) XFlush (x_disp); } -static void -selection_notify (XEvent *event) -{ - unsigned char *data, *p; - unsigned long num_bytes; - unsigned long tmp, len; - int format; - Atom type, property; - - x_time = event->xselection.time; - - if ((property = event->xselection.property) == None) - return; - - XGetWindowProperty (x_disp, x_win, property, 0, 0, False, AnyPropertyType, - &type, &format, &len, &num_bytes, &data); - if (num_bytes <= 0) - return; - if (XGetWindowProperty (x_disp, x_win, property, 0, num_bytes, True, - AnyPropertyType, &type, &format, &len, &tmp, &data) - != Success) { - XFree (data); // FIXME is this correct for this instance? - return; - } - - // get bytes to keys.c - for (p = data; num_bytes && *p; p++, num_bytes--) { - Key_Event (QFK_UNKNOWN, *p, 1); - Key_Event (QFK_UNKNOWN, 0, 0); - } - XFree (data); -} - static void enter_notify (XEvent *event) { @@ -711,7 +678,7 @@ in_x11_send_mouse_event (IE_mouse_type type) } static void -in_x11_send_key_event (int press) +in_x11_send_key_event (void) { IE_event_t event = { .type = ie_key, @@ -736,6 +703,40 @@ in_x11_send_button_event (int devid, in_buttoninfo_t *button) IE_Send_Event (&event); } +static void +selection_notify (XEvent *event) +{ + unsigned char *data, *p; + unsigned long num_bytes; + unsigned long tmp, len; + int format; + Atom type, property; + + x_time = event->xselection.time; + + if ((property = event->xselection.property) == None) + return; + + XGetWindowProperty (x_disp, x_win, property, 0, 0, False, AnyPropertyType, + &type, &format, &len, &num_bytes, &data); + if (num_bytes <= 0) + return; + if (XGetWindowProperty (x_disp, x_win, property, 0, num_bytes, True, + AnyPropertyType, &type, &format, &len, &tmp, &data) + != Success) { + XFree (data); // FIXME is this correct for this instance? + return; + } + + //FIXME send paste event instead of key presses? + x11_key.code = 0; + for (p = data; num_bytes && *p; p++, num_bytes--) { + x11_key.unicode = *p; + in_x11_send_key_event (); + } + XFree (data); +} + static void event_motion (XEvent *event) { @@ -818,7 +819,7 @@ event_key (XEvent *event) x11_key.shift = event->xmotion.state & 0xff; XLateKey (&event->xkey, &x11_key.code, &x11_key.unicode); - in_x11_send_key_event (event->type == KeyPress); + in_x11_send_key_event (); } static void From 6dc90c5497f15b006a9396be968e3bde2a156f25 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 5 Nov 2021 14:56:27 +0900 Subject: [PATCH 1787/3664] [x11] Remove key focus and destination handling I'm undecided on how to handle application focus (probably gain/lose events), and the destination handler has been a stub for a while. One less dependency on the "old" key handling code. --- libs/video/targets/in_x11.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 561365c9b..cd5d2bde8 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -599,20 +599,9 @@ XLateKey (XKeyEvent *ev, int *k, int *u) *u = unicode; } -static void -in_x11_keydest_callback (keydest_t key_dest, void *data) -{ -// if (key_dest == key_game) { -// XAutoRepeatOff (x_disp); -// } else { -// XAutoRepeatOn (x_disp); -// } -} - static void event_focusout (XEvent *event) { - Key_FocusEvent (0); if (x_have_focus) { x_have_focus = false; if (in_snd_block->int_val) { @@ -627,7 +616,6 @@ static void event_focusin (XEvent *event) { x_have_focus = true; - Key_FocusEvent (1); if (in_snd_block->int_val) { S_UnblockSound (); CDAudio_Resume (); @@ -1026,8 +1014,6 @@ in_x11_init (void *data) in_mouse_avail = 1; } - Key_KeydestCallback (in_x11_keydest_callback, 0); - Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, "Paste the contents of X's C&P buffer to the console"); } From 4898a44263b02cbc326751087a40b7190bba2db2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 8 Nov 2021 11:20:04 +0900 Subject: [PATCH 1788/3664] [console] Hook up new input system This has smashed the keydest handling for many things, and bindings, but seems to be a good start with the new input system: the console in qw-client-x11 is usable (keyboard-only). The button and axis values have been removed from the knum_t enum as mouse events are separate from key events, and other button and axis inputs will be handled separately. keys.c has been disabled in the build as it is obsolute (thus much of the breakage). --- include/QF/console.h | 8 +- include/QF/input/event.h | 3 + include/QF/input/imt.h | 9 +- include/QF/keys.h | 143 +--------------- include/QF/plugin/console.h | 3 +- libs/console/client.c | 270 +++++++++++++++++++------------ libs/console/console.c | 8 + libs/console/menu.c | 36 ++--- libs/gib/gib_keys.c | 2 + libs/input/Makemodule.am | 1 - libs/input/in_binding.c | 104 +++++++++++- libs/input/in_event.c | 6 + libs/input/in_imt.c | 82 +++++++++- libs/ruamoko/rua_keys.c | 22 ++- libs/video/targets/in_x11.c | 4 +- nq/source/cl_main.c | 10 +- nq/source/host.c | 6 +- nq/source/sbar.c | 6 +- qw/source/cl_chat.c | 5 +- qw/source/cl_demo.c | 2 +- qw/source/cl_main.c | 9 +- qw/source/sbar.c | 6 +- ruamoko/cl_menu/CrosshairView.r | 2 +- ruamoko/cl_menu/CvarToggleView.r | 2 +- ruamoko/cl_menu/MenuGroup.r | 4 +- ruamoko/cl_menu/client_menu.r | 26 +-- ruamoko/qwaq/builtins/input.c | 1 + ruamoko/qwaq/builtins/qwaq-bi.c | 2 +- 28 files changed, 459 insertions(+), 323 deletions(-) diff --git a/include/QF/console.h b/include/QF/console.h index b267a7efb..159c99c4d 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -60,6 +60,12 @@ typedef struct { int cur_line; // current line } con_buffer_t; +typedef enum { + con_inactive, + con_active, + con_fullscreen, +} con_state_t; + extern int con_linewidth; extern struct plugin_s *con_module; extern struct console_data_s con_data; @@ -73,7 +79,7 @@ void Con_DrawConsole (void); void Con_Printf (const char *fmt, ...) __attribute__((format(PRINTF, 1, 2))); void Con_Print (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); -void Con_ToggleConsole_f (void); +void Con_SetState (con_state_t state); struct inputline_s; // wrapper function to attempt to either complete the command line diff --git a/include/QF/input/event.h b/include/QF/input/event.h index 648852258..4ce0dd2b3 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -88,6 +88,8 @@ typedef enum { ie_key, ie_axis, ie_button, + + ie_event_count } IE_event_type; #define IE_broadcast_events (0 \ @@ -113,5 +115,6 @@ int IE_Send_Event (const IE_event_t *event); int IE_Add_Handler (ie_handler_t *event_handler, void *data); void IE_Remove_Handler (int handle); void IE_Set_Focus (int handle); +int IE_Get_Focus (void); #endif//__QF_in_event_h diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index e5cc8b02d..1b7bf38fe 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -32,6 +32,7 @@ #ifndef __QFCC__ #include "QF/darray.h" +#include "QF/qtypes.h" #include "QF/input/binding.h" @@ -71,16 +72,20 @@ typedef struct in_context_s { imt_t **imt_tail; imt_t *active_imt; imt_t *default_imt; + struct cbuf_s *cbuf; } in_context_t; int IMT_GetAxisBlock (const char *device, int num_axes); int IMT_GetButtonBlock (const char *device, int num_buttons); int IMT_CreateContext (void); +int IMT_GetContext (void); +void IMT_SetContext (int ctx); +void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf); imt_t *IMT_FindIMT (const char *name); int IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name); -void IMT_ProcessAxis (int axis, int value); -void IMT_ProcessButton (int button, int state); +qboolean IMT_ProcessAxis (int axis, int value); +qboolean IMT_ProcessButton (int button, int state); #endif diff --git a/include/QF/keys.h b/include/QF/keys.h index c55d76fd8..b66f99414 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -42,6 +42,7 @@ ///@{ /// these are the key numbers that should be passed to Key_Event +/// FIXME clashes with actual inicode and OS keys typedef enum { /* The keyboard syms have been cleverly chosen to map to ASCII */ QFK_UNKNOWN = 0, @@ -375,148 +376,6 @@ typedef enum { QFK_BACK, QFK_FORWARD, - /* Add any other keys here */ - -// -// mouse buttons generate virtual keys -// - QFM_BUTTON1, - QFM_BUTTON2, - QFM_BUTTON3, - QFM_WHEEL_UP, - QFM_WHEEL_DOWN, - QFM_BUTTON6, - QFM_BUTTON7, - QFM_BUTTON8, - QFM_BUTTON9, - QFM_BUTTON10, - QFM_BUTTON11, - QFM_BUTTON12, - QFM_BUTTON13, - QFM_BUTTON14, - QFM_BUTTON15, - QFM_BUTTON16, - QFM_BUTTON17, - QFM_BUTTON18, - QFM_BUTTON19, - QFM_BUTTON20, - QFM_BUTTON21, - QFM_BUTTON22, - QFM_BUTTON23, - QFM_BUTTON24, - QFM_BUTTON25, - QFM_BUTTON26, - QFM_BUTTON27, - QFM_BUTTON28, - QFM_BUTTON29, - QFM_BUTTON30, - QFM_BUTTON31, - QFM_BUTTON32, - -// -// joystick buttons -// - QFJ_BUTTON1, - QFJ_BUTTON2, - QFJ_BUTTON3, - QFJ_BUTTON4, - QFJ_BUTTON5, - QFJ_BUTTON6, - QFJ_BUTTON7, - QFJ_BUTTON8, - QFJ_BUTTON9, - QFJ_BUTTON10, - QFJ_BUTTON11, - QFJ_BUTTON12, - QFJ_BUTTON13, - QFJ_BUTTON14, - QFJ_BUTTON15, - QFJ_BUTTON16, - QFJ_BUTTON17, - QFJ_BUTTON18, - QFJ_BUTTON19, - QFJ_BUTTON20, - QFJ_BUTTON21, - QFJ_BUTTON22, - QFJ_BUTTON23, - QFJ_BUTTON24, - QFJ_BUTTON25, - QFJ_BUTTON26, - QFJ_BUTTON27, - QFJ_BUTTON28, - QFJ_BUTTON29, - QFJ_BUTTON30, - QFJ_BUTTON31, - QFJ_BUTTON32, - QFJ_BUTTON33, - QFJ_BUTTON34, - QFJ_BUTTON35, - QFJ_BUTTON36, - QFJ_BUTTON37, - QFJ_BUTTON38, - QFJ_BUTTON39, - QFJ_BUTTON40, - QFJ_BUTTON41, - QFJ_BUTTON42, - QFJ_BUTTON43, - QFJ_BUTTON44, - QFJ_BUTTON45, - QFJ_BUTTON46, - QFJ_BUTTON47, - QFJ_BUTTON48, - QFJ_BUTTON49, - QFJ_BUTTON50, - QFJ_BUTTON51, - QFJ_BUTTON52, - QFJ_BUTTON53, - QFJ_BUTTON54, - QFJ_BUTTON55, - QFJ_BUTTON56, - QFJ_BUTTON57, - QFJ_BUTTON58, - QFJ_BUTTON59, - QFJ_BUTTON60, - QFJ_BUTTON61, - QFJ_BUTTON62, - QFJ_BUTTON63, - QFJ_BUTTON64, - -// -// joystick axes (for button emulation without consuming buttons) -// - QFJ_AXIS1, - QFJ_AXIS2, - QFJ_AXIS3, - QFJ_AXIS4, - QFJ_AXIS5, - QFJ_AXIS6, - QFJ_AXIS7, - QFJ_AXIS8, - QFJ_AXIS9, - QFJ_AXIS10, - QFJ_AXIS11, - QFJ_AXIS12, - QFJ_AXIS13, - QFJ_AXIS14, - QFJ_AXIS15, - QFJ_AXIS16, - QFJ_AXIS17, - QFJ_AXIS18, - QFJ_AXIS19, - QFJ_AXIS20, - QFJ_AXIS21, - QFJ_AXIS22, - QFJ_AXIS23, - QFJ_AXIS24, - QFJ_AXIS25, - QFJ_AXIS26, - QFJ_AXIS27, - QFJ_AXIS28, - QFJ_AXIS29, - QFJ_AXIS30, - QFJ_AXIS31, - QFJ_AXIS32, - QFK_LAST } knum_t; diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index e244ee5c1..e14c4d7dc 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -30,8 +30,8 @@ #include +#include #include -#include typedef struct console_funcs_s { void (*init) (void); @@ -40,6 +40,7 @@ typedef struct console_funcs_s { void (*draw_console) (void); void (*check_resize) (void); void (*new_map) (void); + void (*set_state) (con_state_t state); } console_funcs_t; typedef struct console_data_s { diff --git a/libs/console/client.c b/libs/console/client.c index d0329b1d1..1e907be83 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -59,6 +59,8 @@ #include "QF/va.h" #include "QF/vid.h" +#include "QF/input/event.h" + #include "QF/plugin/general.h" #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" @@ -89,6 +91,9 @@ static float con_times[NUM_CON_TIMES]; // realtime time the line was generated // for transparent notify lines static int con_totallines; // total lines in console scrollback +static con_state_t con_state; +static int con_event_id; +static int con_saved_focos; static qboolean con_debuglog; static qboolean chat_team; @@ -107,7 +112,7 @@ static view_t *hud_view; static qboolean con_initialized; static keydest_t con_curr_keydest; -static keydest_t con_prev_keydest; +//static keydest_t con_prev_keydest; static void ClearNotify (void) @@ -118,19 +123,33 @@ ClearNotify (void) con_times[i] = 0; } +static void +C_SetState (con_state_t state) +{ + con_state = state; + if (con_state == con_inactive) { + IE_Set_Focus (con_saved_focos); + } else { + con_saved_focos = IE_Get_Focus (); + IE_Set_Focus (con_event_id); + } +} static void ToggleConsole_f (void) { Con_ClearTyping (input_line, 0); - if (con_curr_keydest == key_console && !con_data.force_commandline) { - Key_SetKeyDest (con_prev_keydest); - } else { - con_prev_keydest = Key_GetKeyDest (); - Key_SetKeyDest (key_console); + switch (con_state) { + case con_inactive: + C_SetState (con_active); + break; + case con_active: + C_SetState (con_inactive); + break; + case con_fullscreen: + break; } - ClearNotify (); } @@ -140,9 +159,9 @@ ToggleChat_f (void) Con_ClearTyping (input_line, 0); if (con_curr_keydest == key_console && !con_data.force_commandline) { - Key_SetKeyDest (key_game); + //Key_SetKeyDest (key_game); } else { - Key_SetKeyDest (key_console); + //Key_SetKeyDest (key_console); } ClearNotify (); @@ -164,7 +183,7 @@ MessageMode_f (void) if (con_data.force_commandline) return; chat_team = false; - Key_SetKeyDest (key_message); + //Key_SetKeyDest (key_message); } static void @@ -173,7 +192,7 @@ MessageMode2_f (void) if (con_data.force_commandline) return; chat_team = true; - Key_SetKeyDest (key_message); + //Key_SetKeyDest (key_message); } static void @@ -330,7 +349,7 @@ C_Say (inputline_t *il) Cbuf_AddText (con_data.cbuf, "say \""); Cbuf_AddText (con_data.cbuf, line); Cbuf_AddText (con_data.cbuf, "\"\n"); - Key_SetKeyDest (key_game); + //Key_SetKeyDest (key_game); } static void @@ -343,7 +362,7 @@ C_SayTeam (inputline_t *il) Cbuf_AddText (con_data.cbuf, "say_team \""); Cbuf_AddText (con_data.cbuf, line); Cbuf_AddText (con_data.cbuf, "\"\n"); - Key_SetKeyDest (key_game); + //Key_SetKeyDest (key_game); } static void @@ -447,79 +466,6 @@ C_Print (const char *fmt, va_list args) fputs (buffer->str + 1, stdout); } -static void -C_KeyEvent (knum_t key, short unicode, qboolean down, void *data) -{ - inputline_t *il; - - if (!down) - return; - - if (con_curr_keydest == key_menu) { - Menu_KeyEvent (key, unicode, down); - return; - } - - if (down) { - if (key == key_toggleconsole) { - ToggleConsole_f (); - return; - } - } - - if (con_curr_keydest == key_message) { - if (chat_team) { - il = say_team_line; - } else { - il = say_line; - } - } else { - switch (key) { - case QFK_PAGEUP: - if (keydown[QFK_RCTRL] || keydown[QFK_LCTRL]) - con->display = 0; - else - con->display -= 10; - if (con->display < con->current - con->numlines) - con->display = con->current - con->numlines; - return; - case QFK_PAGEDOWN: - if (keydown[QFK_RCTRL] || keydown[QFK_LCTRL]) - con->display = con->current; - else - con->display += 10; - if (con->display > con->current) - con->display = con->current; - return; - case QFM_WHEEL_UP: - con->display -= 3; - if (con->display < con->current - con->numlines) - con->display = con->current - con->numlines; - return; - case QFM_WHEEL_DOWN: - con->display += 3; - if (con->display > con->current) - con->display = con->current; - return; - default: - break; - } - il = input_line; - } - //FIXME should this translation be here? - if ((unicode==0x0A) && (key==QFK_RETURN)) { - Con_ProcessInputLine (il, key); - } - if ((unicode==0x7F) && (key==QFK_BACKSPACE)) { - Con_ProcessInputLine (il, key); - } - if (unicode!=0) { - Con_ProcessInputLine (il, key >= 256 ? (int) key : unicode); - } else { - Con_ProcessInputLine (il, key); - } -} - /* DRAWING */ static void @@ -551,8 +497,8 @@ C_DrawInputLine (inputline_t *il) static void draw_input (view_t *view) { - if (con_curr_keydest != key_console)// && !con_data.force_commandline) - return; // don't draw anything (always draw if not active) + if (con_state == con_inactive)// && !con_data.force_commandline) + return; DrawInputLine (view->xabs + 8, view->yabs, 1, input_line); } @@ -641,7 +587,7 @@ draw_console (view_t *view) { byte alpha; - if (con_data.force_commandline) { + if (con_state == con_fullscreen) { alpha = 255; } else { float y = r_data->vid->conview->ylen * con_size->value; @@ -704,12 +650,17 @@ setup_console (void) { float lines; - if (con_data.force_commandline) { - lines = con_data.lines = r_data->vid->conview->ylen; - } else if (con_curr_keydest == key_console) { - lines = r_data->vid->conview->ylen * bound (0.2, con_size->value, 1); - } else { - lines = 0; + switch (con_state) { + case con_inactive: + lines = 0; + break; + case con_active: + lines = r_data->vid->conview->ylen * bound (0.2, con_size->value, + 1); + break; + case con_fullscreen: + lines = con_data.lines = r_data->vid->conview->ylen; + break; } if (con_speed->value) { @@ -776,13 +727,13 @@ exec_line (inputline_t *il) { Con_ExecLine (il->line); } - +#if 0 static void con_end_message (void *line) { - Key_PopEscape (); + //Key_PopEscape (); Con_ClearTyping (line, 1); - Key_SetKeyDest (key_game); + //Key_SetKeyDest (key_game); } static void @@ -798,7 +749,7 @@ con_keydest_callback (keydest_t kd, void *data) return; } if (kd != key_console && con_curr_keydest == key_console) { - Key_PopEscape (); + //Key_PopEscape (); } switch (kd) { case key_last: @@ -808,11 +759,11 @@ con_keydest_callback (keydest_t kd, void *data) case key_menu: break; case key_message: - Key_PushEscape (con_end_message, - chat_team ? say_team_line : say_line); + //Key_PushEscape (con_end_message, + // chat_team ? say_team_line : say_line); break; case key_console: - Key_PushEscape (con_leave_console, 0); + //Key_PushEscape (con_leave_console, 0); break; } con_curr_keydest = kd; @@ -823,6 +774,108 @@ con_enter_menu (void *data) { Menu_Enter (); } +#endif + +static void +con_key_event (const IE_event_t *event) +{ + inputline_t *il; + __auto_type key = &event->key; + +#if 0 + if (con_curr_keydest == key_menu) { + Menu_KeyEvent (key, unicode, down); + return; + } + + if (down) { + if (key == key_toggleconsole) { + ToggleConsole_f (); + return; + } + } +#endif +#if 0 + if (con_curr_keydest == key_message) { + if (chat_team) { + il = say_team_line; + } else { + il = say_line; + } + } else { +#endif + switch (key->code) { + case QFK_PAGEUP: + if (key->shift & ies_control) + con->display = 0; + else + con->display -= 10; + if (con->display < con->current - con->numlines) + con->display = con->current - con->numlines; + return; + case QFK_PAGEDOWN: + if (key->shift & ies_control) + con->display = con->current; + else + con->display += 10; + if (con->display > con->current) + con->display = con->current; + return; +#if 0 + case QFM_WHEEL_UP: + con->display -= 3; + if (con->display < con->current - con->numlines) + con->display = con->current - con->numlines; + return; + case QFM_WHEEL_DOWN: + con->display += 3; + if (con->display > con->current) + con->display = con->current; + return; +#endif + default: + break; + } + il = input_line; +#if 0 + } +#endif +#if 0 + //FIXME should this translation be here? + if ((unicode==0x0A) && (key==QFK_RETURN)) { + Con_ProcessInputLine (il, key); + } + if ((unicode==0x7F) && (key==QFK_BACKSPACE)) { + Con_ProcessInputLine (il, key); + } +#endif + if (key->unicode) { + Con_ProcessInputLine (il, key->code >= 256 ? (int) key->code + : key->unicode); + } else { + Con_ProcessInputLine (il, key->code); + } +} + +static void +con_mouse_event (const IE_event_t *event) +{ +} + +static int +con_event_handler (const IE_event_t *ie_event, void *data) +{ + static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { + [ie_key] = con_key_event, + [ie_mouse] = con_mouse_event, + }; + if (ie_event->type < 0 || ie_event->type >= ie_event_count + || !handlers[ie_event->type]) { + return 0; + } + handlers[ie_event->type] (ie_event); + return 1; +} static void C_Init (void) @@ -833,11 +886,13 @@ C_Init (void) setlocale (LC_ALL, "C-TRADITIONAL"); #endif - Key_PushEscape (con_enter_menu, 0); - Key_KeydestCallback (con_keydest_callback, 0); - Key_SetKeyEvent (key_message, C_KeyEvent, 0); - Key_SetKeyEvent (key_menu, C_KeyEvent, 0); - Key_SetKeyEvent (key_console, C_KeyEvent, 0); + con_event_id = IE_Add_Handler (con_event_handler, 0); + + //Key_PushEscape (con_enter_menu, 0); + //Key_KeydestCallback (con_keydest_callback, 0); + //Key_SetKeyEvent (key_message, C_KeyEvent, 0); + //Key_SetKeyEvent (key_menu, C_KeyEvent, 0); + //Key_SetKeyEvent (key_console, C_KeyEvent, 0); Menu_Init (); con_notifytime = Cvar_Get ("con_notifytime", "3", CVAR_NONE, NULL, @@ -966,6 +1021,7 @@ static console_funcs_t plugin_info_console_funcs = { .draw_console = C_DrawConsole, .check_resize = C_CheckResize, .new_map = C_NewMap, + .set_state = C_SetState, }; static plugin_funcs_t plugin_info_funcs = { diff --git a/libs/console/console.c b/libs/console/console.c index 6e0153f49..5c7323fb0 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -157,6 +157,14 @@ Con_Print (const char *fmt, va_list args) vfprintf (stdout, fmt, args); } +VISIBLE void +Con_SetState (con_state_t state) +{ + if (con_module) { + con_module->functions->console->set_state (state); + } +} + VISIBLE void Con_ProcessInput (void) { diff --git a/libs/console/menu.c b/libs/console/menu.c index f9b96fda7..a90547ffa 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -82,7 +82,7 @@ static cvar_t *confirm_quit; static progs_t menu_pr_state; static menu_item_t *menu; -static keydest_t menu_keydest; +//static keydest_t menu_keydest; static hashtab_t *menu_hash; static func_t menu_init; static func_t menu_quit; @@ -358,13 +358,13 @@ bi_Menu_TopMenu (progs_t *pr) free ((char *) top_menu); top_menu = strdup (name); } - +/* static void menu_leave (void *data) { Menu_Leave (); } - +*/ static void bi_Menu_SelectMenu (progs_t *pr) { @@ -374,11 +374,11 @@ bi_Menu_SelectMenu (progs_t *pr) if (name && *name) menu = Hash_Find (menu_hash, name); if (menu) { - if (Key_GetKeyDest () != key_menu) { + /*if (Key_GetKeyDest () != key_menu) { menu_keydest = Key_GetKeyDest (); Key_PushEscape (menu_leave, 0); Key_SetKeyDest (key_menu); - } + }*/ if (menu->enter_hook) { run_menu_pre (); PR_ExecuteProgram (&menu_pr_state, menu->enter_hook); @@ -387,8 +387,8 @@ bi_Menu_SelectMenu (progs_t *pr) } else { if (name && *name) Sys_Printf ("no menu \"%s\"\n", name); - Key_PopEscape (); - Key_SetKeyDest (menu_keydest); + //Key_PopEscape (); + //Key_SetKeyDest (menu_keydest); } } @@ -473,8 +473,8 @@ bi_Menu_Leave (progs_t *pr) } menu = menu->parent; if (!menu) { - Key_PopEscape (); - Key_SetKeyDest (menu_keydest); + //Key_PopEscape (); + //Key_SetKeyDest (menu_keydest); } } } @@ -775,15 +775,15 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) return 0; switch (key) { case QFK_DOWN: - case QFM_WHEEL_DOWN: +// case QFM_WHEEL_DOWN: bi_Menu_Next (&menu_pr_state); return 1; case QFK_UP: - case QFM_WHEEL_UP: +// case QFM_WHEEL_UP: bi_Menu_Prev (&menu_pr_state); return 1; case QFK_RETURN: - case QFM_BUTTON1: +// case QFM_BUTTON1: bi_Menu_Enter (&menu_pr_state); return 1; default: @@ -795,14 +795,14 @@ void Menu_Enter () { if (!top_menu) { - Key_SetKeyDest (key_console); + //Key_SetKeyDest (key_console); return; } menu = Hash_Find (menu_hash, top_menu); if (menu) { - menu_keydest = Key_GetKeyDest (); - Key_PushEscape (menu_leave, 0); - Key_SetKeyDest (key_menu); + //menu_keydest = Key_GetKeyDest (); + //Key_PushEscape (menu_leave, 0); + //Key_SetKeyDest (key_menu); if (menu->enter_hook) { run_menu_pre (); PR_ExecuteProgram (&menu_pr_state, menu->enter_hook); @@ -822,8 +822,8 @@ Menu_Leave () } menu = menu->parent; if (!menu) { - Key_PopEscape (); - Key_SetKeyDest (menu_keydest); + //Key_PopEscape (); + //Key_SetKeyDest (menu_keydest); } } r_data->vid->recalc_refdef = true; diff --git a/libs/gib/gib_keys.c b/libs/gib/gib_keys.c index c40e1bb1c..a45428acd 100644 --- a/libs/gib/gib_keys.c +++ b/libs/gib/gib_keys.c @@ -47,6 +47,7 @@ static void Key_GIB_Bind_Get_f (void) { +#if 0 const char *key, *cmd; imt_t *imt; int k; @@ -68,6 +69,7 @@ Key_GIB_Bind_Get_f (void) GIB_Return (""); else GIB_Return (cmd); +#endif } void diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index 3455be6ab..774141caf 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -18,7 +18,6 @@ libs_input_libQFinput_la_LDFLAGS= $(lib_ldflags) libs_input_libQFinput_la_LIBADD= $(input_deps) libs_input_libQFinput_la_DEPENDENCIES= $(input_deps) libs_input_libQFinput_la_SOURCES= \ - libs/input/keys.c \ libs/input/old_keys.c \ libs/input/in_axis.c \ libs/input/in_binding.c \ diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 6bcbb5e66..6e663f5f0 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -52,6 +52,7 @@ typedef struct DARRAY_TYPE (in_devbindings_t) in_devbindingset_t; static in_devbindingset_t devbindings = DARRAY_STATIC_INIT (8); +static int in_binding_handler; static void in_binding_add_device (const IE_event_t *ie_event) @@ -133,13 +134,13 @@ in_binding_button (const IE_event_t *ie_event) static int in_binding_event_handler (const IE_event_t *ie_event, void *unused) { - static void (*handlers[]) (const IE_event_t *ie_event) = { + static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { [ie_add_device] = in_binding_add_device, [ie_remove_device] = in_binding_remove_device, [ie_axis] = in_binding_axis, [ie_button] = in_binding_button, }; - if (ie_event->type < 0 || ie_event->type > ie_button + if (ie_event->type < 0 || ie_event->type >= ie_event_count || !handlers[ie_event->type]) { return 0; } @@ -147,8 +148,105 @@ in_binding_event_handler (const IE_event_t *ie_event, void *unused) return 1; } +static void +in_bind_f (void) +{ +} + +static void +in_unbind_f (void) +{ +} + +static void +in_clear_f (void) +{ +} + +static void +in_devices_f (void) +{ +} + +static void +keyhelp_f (void) +{ +} + +typedef struct { + const char *name; + xcommand_t func; + const char *desc; +} bindcmd_t; + +static bindcmd_t in_binding_commands[] = { + { "in_bind", in_bind_f, + "Assign a command or a set of commands to a key.\n" + "Note: To bind multiple commands to a key, enclose the " + "commands in quotes and separate with semi-colons." + }, + { "in_unbind", in_unbind_f, + "Remove the bind from the the selected key" + }, + { "in_clear", in_clear_f, + "Remove all binds from the specified imts" + }, + { "in_devices", in_devices_f, + "List the known devices and their status." + }, + { "keyhelp", keyhelp_f, + "Identify the next active input axis or button.\n" + "The identification includes the device binding name, axis or button " + "number, and (if known) the name of the axis or button. Axes and " + "buttons can always be bound by number, so even those for which a " + "name is not known, but" PACKAGE_NAME " sees, can be bound." + }, + { } +#if 0 + { "bindlist", Key_Bindlist_f, + "list all of the key bindings" + }, + { "unbindall", Key_Unbindall_f, + "Remove all binds (USE CAUTIOUSLY!!!" + }, + { "unbind", Key_Unbind_f, + "wrapper for in_unbind that uses in_bind_imt for the imt " + "parameter" + }, + { "bind", Key_Bind_f, + "wrapper for in_bind that uses " + "in_bind_imt for the imt parameter" + }, + { "imt", Key_InputMappingTable_f, + "" + }, + { "imt_keydest", Key_IMT_Keydest_f, + "" + }, + { "imt_create", Key_IMT_Create_f, + "create a new imt table:\n" + " imt_create [chain_name]\n" + "\n" + "The new table will be attached to the specified keydest\n" + "imt_name must not already exist.\n" + "If given, chain_name must already exist and be on " + "keydest.\n" + }, + { "imt_drop_all", Key_IMT_Drop_All_f, + "delete all imt tables\n" + }, + { "in_type", Key_In_Type_f, + "Send the given string as simulated key presses." + }, +#endif +}; + void IN_Binding_Init (void) { - IE_Add_Handler (in_binding_event_handler, 0); + in_binding_handler = IE_Add_Handler (in_binding_event_handler, 0); + + for (bindcmd_t *cmd = in_binding_commands; cmd->name; cmd++) { + Cmd_AddCommand (cmd->name, cmd->func, cmd->desc); + } } diff --git a/libs/input/in_event.c b/libs/input/in_event.c index b2aaf362c..0fdfa0f9b 100644 --- a/libs/input/in_event.c +++ b/libs/input/in_event.c @@ -108,3 +108,9 @@ IE_Set_Focus (int handle) IE_Send_Event (&event); } } + +int +IE_Get_Focus (void) +{ + return focus; +} diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 4a00032f9..3c1a3eddb 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -42,6 +42,7 @@ #include "QF/cmd.h" #include "QF/hash.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/input/imt.h" @@ -56,6 +57,7 @@ static imt_blockset_t axis_blocks = DARRAY_STATIC_INIT (8); static imt_blockset_t button_blocks = DARRAY_STATIC_INIT (8); static in_contextset_t in_contexts = DARRAY_STATIC_INIT (8); +static size_t imt_current_context; static imt_block_t * __attribute__((pure)) imt_find_block (imt_blockset_t *blockset, const char *device) @@ -149,6 +151,30 @@ IMT_CreateContext (void) return ctx - in_contexts.a; } +int +IMT_GetContext (void) +{ + return imt_current_context; +} + +void +IMT_SetContext (int ctx) +{ + if ((size_t) ctx >= in_contexts.size) { + Sys_Error ("IMT_SetContext: invalid context %d", ctx); + } + imt_current_context = ctx; +} + +void +IMT_SetContextCbuf (int ctx, cbuf_t *cbuf) +{ + if ((size_t) ctx >= in_contexts.size) { + Sys_Error ("IMT_SetContextCbuf: invalid context %d", ctx); + } + in_contexts.a[imt_current_context].cbuf = cbuf; +} + static imt_t * __attribute__ ((pure)) imt_find_imt (in_context_t *ctx, const char *name) { @@ -227,12 +253,64 @@ IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name) return 1; } -void +qboolean IMT_ProcessAxis (int axis, int value) { + imt_t *imt = in_contexts.a[imt_current_context].active_imt; + + while (imt) { + in_axisbinding_t *a = imt->axis_bindings.a[axis]; + if (a) { + return true; + } + imt = imt->chain; + } + return false; } -void +static void +process_binding (int button, int state, const char *cmd) +{ + cbuf_t *cbuf = in_contexts.a[imt_current_context].cbuf; + + if (!cbuf) { + return; + } + + if (cmd[0] == '+') { + if (state) { + Cbuf_AddText (cbuf, va (0, "%s %d\n", cmd, button)); + } else { + Cbuf_AddText (cbuf, va (0, "-%s %d\n", cmd + 1, button)); + } + } else { + if (state) { + Cbuf_AddText (cbuf, va (0, "%s\n", cmd)); + } + } +} + +qboolean IMT_ProcessButton (int button, int state) { + imt_t *imt = in_contexts.a[imt_current_context].active_imt; + + Sys_Printf ("IMT_ProcessButton: %d %d\n", button, state); + while (imt) { + in_buttonbinding_t *b = imt->button_bindings.a[button]; + if (b) { + switch (b->type) { + case inb_button: + IN_ButtonAction (b->button, button, state); + break; + case inb_command: + //FIXME avoid repeat + process_binding (button, state, b->command); + break; + } + return true; + } + imt = imt->chain; + } + return false; } diff --git a/libs/ruamoko/rua_keys.c b/libs/ruamoko/rua_keys.c index f5617406b..32229a4c4 100644 --- a/libs/ruamoko/rua_keys.c +++ b/libs/ruamoko/rua_keys.c @@ -43,8 +43,10 @@ static void bi_Key_keydown (progs_t *pr) { +#if 0 int keynum = P_INT (pr, 0); R_INT (pr) = keydown[keynum]; +#endif } /* @@ -55,6 +57,7 @@ bi_Key_keydown (progs_t *pr) static void bi_Key_SetBinding (progs_t *pr) { +#if 0 const char *imt_name = P_GSTRING (pr, 0); int keynum = P_INT (pr, 1); const char *binding = P_GSTRING (pr, 2); @@ -68,6 +71,7 @@ bi_Key_SetBinding (progs_t *pr) if (imt) { Key_SetBinding (imt, keynum, binding); } +#endif } /* @@ -78,6 +82,7 @@ bi_Key_SetBinding (progs_t *pr) static void bi_Key_LookupBinding (progs_t *pr) { +#if 0 const char *imt_name = P_GSTRING (pr, 0); int bindnum = P_INT (pr, 1); const char *binding = P_GSTRING (pr, 2); @@ -89,7 +94,7 @@ bi_Key_LookupBinding (progs_t *pr) imt = Key_FindIMT (imt_name); if (imt) { for (i = 0; i < QFK_LAST; i++) { -//XXX keybind = imt->button_bindings.a[i].str; + keybind = imt->button_bindings.a[i].str; if (keybind == NULL) { continue; } @@ -104,7 +109,8 @@ bi_Key_LookupBinding (progs_t *pr) } R_INT (pr) = keynum; -}; +#endif +} /* bi_Key_CountBinding @@ -114,6 +120,7 @@ bi_Key_LookupBinding (progs_t *pr) static void bi_Key_CountBinding (progs_t *pr) { +#if 0 const char *imt_name = P_GSTRING (pr, 0); const char *binding = P_GSTRING (pr, 1); int i, res = 0; @@ -123,7 +130,7 @@ bi_Key_CountBinding (progs_t *pr) imt = Key_FindIMT (imt_name); if (imt) { for (i = 0; i < QFK_LAST; i++) { -//XXX keybind = imt->button_bindings.a[i].str; + keybind = imt->button_bindings.a[i].str; if (keybind == NULL) { continue; } @@ -134,7 +141,8 @@ bi_Key_CountBinding (progs_t *pr) } R_INT (pr) = res; -}; +#endif +} /* @@ -145,16 +153,20 @@ bi_Key_CountBinding (progs_t *pr) static void bi_Key_KeynumToString (progs_t *pr) { +#if 0 int keynum = P_INT (pr, 0); RETURN_STRING (pr, Key_KeynumToString (keynum)); -}; +#endif +} static void bi_Key_StringToKeynum (progs_t *pr) { +#if 0 const char *keyname = P_GSTRING (pr, 0); R_INT (pr) = Key_StringToKeynum (keyname); +#endif } static builtin_t builtins[] = { diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index cd5d2bde8..7c7afe24e 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -807,7 +807,9 @@ event_key (XEvent *event) x11_key.shift = event->xmotion.state & 0xff; XLateKey (&event->xkey, &x11_key.code, &x11_key.unicode); - in_x11_send_key_event (); + if (event->type == KeyPress) { + in_x11_send_key_event (); + } } static void diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index a48d593d5..c1c879cac 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -114,7 +114,7 @@ CL_WriteConfiguration (void) return; } - Key_WriteBindings (f); + //Key_WriteBindings (f); Cvar_WriteVariables (f); Qclose (f); @@ -321,7 +321,7 @@ CL_EstablishConnection (const char *host) cls.demonum = -1; // not in the demo loop now CL_SetState (ca_connected); - Key_SetKeyDest (cls.key_dest); + //Key_SetKeyDest (cls.key_dest); } /* @@ -497,7 +497,7 @@ CL_SetState (cactive_t state) if (old_state != state) { if (old_state == ca_active) { // leaving active state - Key_SetKeyDest (key_console); + //Key_SetKeyDest (key_console); S_AmbientOff (); } switch (state) { @@ -512,14 +512,14 @@ CL_SetState (cactive_t state) cls.signon = so_none; // need all the signon messages // before playing cl.loading = true; - Key_SetKeyDest (cls.key_dest); + //Key_SetKeyDest (cls.key_dest); IN_ClearStates (); VID_SetCaption ("Connected"); break; case ca_active: // entering active state cl.loading = false; - Key_SetKeyDest (cls.key_dest); + //Key_SetKeyDest (cls.key_dest); IN_ClearStates (); VID_SetCaption (""); S_AmbientOn (); diff --git a/nq/source/host.c b/nq/source/host.c index 397911f90..2128e7f74 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -847,13 +847,13 @@ Host_Init_Memory (void) Sys_Printf ("%4.1f megabyte heap\n", host_mem_size->value); } - +#if 0 static void host_keydest_callback (keydest_t kd, void *data) { host_in_game = kd == key_game; } - +#endif void Host_Init (void) { @@ -888,7 +888,7 @@ Host_Init (void) Mod_Init (); - Key_KeydestCallback (host_keydest_callback, 0); + //Key_KeydestCallback (host_keydest_callback, 0); SV_Init (); diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 5cbf233b9..5798a0112 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1642,13 +1642,13 @@ Sbar_GIB_Print_Center_f (void) } else Sbar_CenterPrint (GIB_Argv(1)); } - +#if 0 static void sbar_keydest_callback (keydest_t kd, void *data) { overlay_view->visible = kd == key_game; } - +#endif void Sbar_Init (void) { @@ -1656,7 +1656,7 @@ Sbar_Init (void) init_views (); - Key_KeydestCallback (sbar_keydest_callback, 0); + //Key_KeydestCallback (sbar_keydest_callback, 0); for (i = 0; i < 10; i++) { sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index da3b5f9e8..a101a5f27 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -237,7 +237,7 @@ CL_Chat_Flush_Ignores (void) { llist_flush (ignore_list); } - +#if 0 static void CL_ChatInfo (int val) { @@ -268,6 +268,7 @@ cl_chat_keydest (keydest_t keydest, void *data) break; } } +#endif void CL_Chat_Init (void) @@ -277,5 +278,5 @@ CL_Chat_Init (void) Cmd_AddCommand ("ignore", CL_Ignore_f, "Ignores chat and name-change messages from a user."); Cmd_AddCommand ("unignore", CL_Unignore_f, "Removes a previously ignored user from the ignore list."); - Key_KeydestCallback (cl_chat_keydest, 0); + //Key_KeydestCallback (cl_chat_keydest, 0); } diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index dd4114e14..9d10c2897 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -1014,7 +1014,7 @@ CL_StartDemo (void) Sys_Printf ("Playing demo from %s.\n", name->str); cls.demoplayback = true; - Key_SetKeyDest (key_demo); + //Key_SetKeyDest (key_demo); net_blocksend = 1; if (type == 2) { cls.demoplayback2 = true; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index ce71b1ad8..82e2df4d7 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1146,7 +1146,7 @@ CL_SetState (cactive_t state) if (old_state == ca_active) { // leaving active state IN_ClearStates (); - Key_SetKeyDest (key_console); + //Key_SetKeyDest (key_console); // Auto demo recorder stops here if (cl_autorecord->int_val && cls.demorecording) @@ -1155,7 +1155,7 @@ CL_SetState (cactive_t state) // entering active state VID_SetCaption (cls.servername->str); IN_ClearStates (); - Key_SetKeyDest (key_game); + //Key_SetKeyDest (key_game); // Auto demo recorder starts here if (cl_autorecord->int_val && !cls.demoplayback @@ -1163,8 +1163,7 @@ CL_SetState (cactive_t state) CL_Record (0, -1); } } - if (con_module) - con_module->data->console->force_commandline = (state != ca_active); + Con_SetState (state == ca_active ? con_inactive : con_fullscreen); } void @@ -1512,7 +1511,7 @@ Host_WriteConfiguration (void) return; } - Key_WriteBindings (f); + //Key_WriteBindings (f); Cvar_WriteVariables (f); Qclose (f); diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 373b108c6..4c6d58710 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -1939,13 +1939,13 @@ Sbar_GIB_Print_Center_f (void) } else Sbar_CenterPrint (GIB_Argv(1)); } - +#if 0 static void sbar_keydest_callback (keydest_t kd, void *data) { overlay_view->visible = kd == key_game; } - +#endif void Sbar_Init (void) { @@ -1953,7 +1953,7 @@ Sbar_Init (void) init_views (); - Key_KeydestCallback (sbar_keydest_callback, 0); + //Key_KeydestCallback (sbar_keydest_callback, 0); for (i = 0; i < 10; i++) { sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); diff --git a/ruamoko/cl_menu/CrosshairView.r b/ruamoko/cl_menu/CrosshairView.r index 81152efee..0ca4e9532 100644 --- a/ruamoko/cl_menu/CrosshairView.r +++ b/ruamoko/cl_menu/CrosshairView.r @@ -32,7 +32,7 @@ { switch (key) { case QFK_RETURN: - case QFM_BUTTON1: + //case QFM_BUTTON1: [self next]; return 1; default: diff --git a/ruamoko/cl_menu/CvarToggleView.r b/ruamoko/cl_menu/CvarToggleView.r index 2102e99ab..8c1e96840 100644 --- a/ruamoko/cl_menu/CvarToggleView.r +++ b/ruamoko/cl_menu/CvarToggleView.r @@ -47,7 +47,7 @@ { switch (key) { case QFK_RETURN: - case QFM_BUTTON1: + //case QFM_BUTTON1: [self toggle]; return 1; default: diff --git a/ruamoko/cl_menu/MenuGroup.r b/ruamoko/cl_menu/MenuGroup.r index 5c89382c7..356d9d795 100644 --- a/ruamoko/cl_menu/MenuGroup.r +++ b/ruamoko/cl_menu/MenuGroup.r @@ -30,11 +30,11 @@ if (!ret) { switch (key) { case QFK_DOWN: - case QFM_WHEEL_DOWN: + //case QFM_WHEEL_DOWN: [self next]; return 1; case QFK_UP: - case QFM_WHEEL_UP: + //case QFM_WHEEL_UP: [self prev]; return 1; } diff --git a/ruamoko/cl_menu/client_menu.r b/ruamoko/cl_menu/client_menu.r index dc4cd487e..a962f4305 100644 --- a/ruamoko/cl_menu/client_menu.r +++ b/ruamoko/cl_menu/client_menu.r @@ -47,11 +47,11 @@ menu_key_sound = { switch (key) { case QFK_DOWN: - case QFM_WHEEL_DOWN: + //case QFM_WHEEL_DOWN: S_LocalSound ("misc/menu1.wav"); break; case QFK_UP: - case QFM_WHEEL_UP: + //case QFM_WHEEL_UP: S_LocalSound ("misc/menu1.wav"); break; } @@ -231,19 +231,19 @@ int (int key, int unicode, int down) load_quickbup_keyevent = { switch (key) { case QFK_DOWN: - case QFM_WHEEL_DOWN: + //case QFM_WHEEL_DOWN: S_LocalSound ("misc/menu1.wav"); load_cursor++; load_cursor %= MAX_QUICK; return 1; case QFK_UP: - case QFM_WHEEL_UP: + //case QFM_WHEEL_UP: S_LocalSound ("misc/menu1.wav"); load_cursor += MAX_QUICK - 1; load_cursor %= MAX_QUICK; return 1; case QFK_RETURN: - case QFM_BUTTON1: + //case QFM_BUTTON1: if (loadable[load_cursor]) { S_LocalSound ("misc/menu2.wav"); Menu_SelectMenu (nil); @@ -259,19 +259,19 @@ int (int key, int unicode, int down) load_keyevent = { switch (key) { case QFK_DOWN: - case QFM_WHEEL_DOWN: + //case QFM_WHEEL_DOWN: S_LocalSound ("misc/menu1.wav"); load_cursor++; load_cursor %= MAX_SAVEGAMES + 1; return 1; case QFK_UP: - case QFM_WHEEL_UP: + //case QFM_WHEEL_UP: S_LocalSound ("misc/menu1.wav"); load_cursor += MAX_SAVEGAMES; load_cursor %= MAX_SAVEGAMES + 1; return 1; case QFK_RETURN: - case QFM_BUTTON1: + //case QFM_BUTTON1: if (load_cursor == MAX_SAVEGAMES) { load_cursor = 0; scan_saves (1); @@ -290,19 +290,19 @@ int (int key, int unicode, int down) save_keyevent = { switch (key) { case QFK_DOWN: - case QFM_WHEEL_DOWN: + //case QFM_WHEEL_DOWN: S_LocalSound ("misc/menu1.wav"); save_cursor++; save_cursor %= MAX_SAVEGAMES; return 1; case QFK_UP: - case QFM_WHEEL_UP: + //case QFM_WHEEL_UP: S_LocalSound ("misc/menu1.wav"); save_cursor += MAX_SAVEGAMES - 1; save_cursor %= MAX_SAVEGAMES; return 1; case QFK_RETURN: - case QFM_BUTTON1: + //case QFM_BUTTON1: Menu_SelectMenu (nil); Cbuf_AddText (sprintf ("save s%i.sav\n", save_cursor)); return 1; @@ -494,7 +494,7 @@ int (int key, int unicode, int down) lanconfig_keyevent = [input_active processInput:(key >= 256 ? key : unicode)]; switch (key) { case QFK_DOWN: - case QFM_WHEEL_DOWN: + //case QFM_WHEEL_DOWN: if (!input_active) { S_LocalSound ("misc/menu2.wav"); lanConfig_cursor ++; @@ -502,7 +502,7 @@ int (int key, int unicode, int down) lanconfig_keyevent = } return 1; case QFK_UP: - case QFM_WHEEL_UP: + //case QFM_WHEEL_UP: if (!input_active) { S_LocalSound ("misc/menu2.wav"); lanConfig_cursor += NUM_LANCONFIG_CMDS - 1; diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 6d62ce4a2..82c3f8f16 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -526,6 +526,7 @@ qwaq_input_event_handler (const IE_event_t *ie_event, void *_res) event.when = ie_event->when * 1e-6 + Sys_DoubleTimeBase (); switch (ie_event->type) { + case ie_event_count: case ie_none: case ie_gain_focus: case ie_lose_focus: diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c index 4d296ad73..ee29dbc5b 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/qwaq-bi.c @@ -205,7 +205,7 @@ BI_Init (progs_t *pr) con_module->data->console->quit = quit_f; con_module->data->console->cbuf = qwaq_cbuf; } - Key_SetKeyDest (key_game); + //Key_SetKeyDest (key_game); S_Init (0, &con_frametime); //CDAudio_Init (); From 839808e659df44d3c01ba66faf319e1d598fccaf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 8 Nov 2021 15:38:26 +0900 Subject: [PATCH 1789/3664] [input] Implement several binding commands in_bind is only partially implemented (waiting on imt), but device listing, device naming, and input identification are working. The event handling system made for a fairly clean implementation for input identification thanks to the focused event handling. --- include/QF/input.h | 2 +- include/QF/input/imt.h | 3 +- libs/input/in_binding.c | 179 ++++++++++++++++++++++++++++++++++++++++ libs/input/in_imt.c | 3 +- 4 files changed, 184 insertions(+), 3 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index eb2cc9e3b..7d8a5c96c 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -96,7 +96,7 @@ typedef struct in_device_s { preferred, but does require the device to be plugged into the same uSB path (ie, same socket on the same hub connected to the same port on the PC) - \a device is the actual device associated with the bindings. If null, the + \a devid is the actual device associated with the bindings. If -1, the device is not currently connected. \a axis_info holds the device/axis specific range info and the current diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 1b7bf38fe..6cbda2e4b 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -68,6 +68,7 @@ typedef struct imt_s { } imt_t; typedef struct in_context_s { + const char *name; imt_t *imts; imt_t **imt_tail; imt_t *active_imt; @@ -77,7 +78,7 @@ typedef struct in_context_s { int IMT_GetAxisBlock (const char *device, int num_axes); int IMT_GetButtonBlock (const char *device, int num_buttons); -int IMT_CreateContext (void); +int IMT_CreateContext (const char *name); int IMT_GetContext (void); void IMT_SetContext (int ctx); void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf); diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 6e663f5f0..13bedce75 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -53,6 +53,8 @@ typedef struct DARRAY_TYPE (in_devbindings_t) in_devbindingset_t; static in_devbindingset_t devbindings = DARRAY_STATIC_INIT (8); static int in_binding_handler; +static int in_keyhelp_handler; +static int in_keyhelp_saved_handler; static void in_binding_add_device (const IE_event_t *ie_event) @@ -148,9 +150,123 @@ in_binding_event_handler (const IE_event_t *ie_event, void *unused) return 1; } +static int +in_keyhelp_event_handler (const IE_event_t *ie_event, void *unused) +{ + if (ie_event->type != ie_axis && ie_event->type != ie_button) { + return 0; + } + + size_t devid = ie_event->button.devid; + in_devbindings_t *db = &devbindings.a[devid]; + const char *name = db->name; + const char *type = 0; + int num = -1; + + if (!name) { + name = db->id; + } + + if (ie_event->type == ie_axis) { + int axis = ie_event->axis.axis; + int value = ie_event->axis.value; + in_axisinfo_t *ai = &db->axis_info[axis]; + if (!ai->min && !ai->max) { + if (value > 2) { + num = axis; + type = "axis"; + } + } else { + int diff = abs (value - ai->value); + if (diff * 5 >= ai->max - ai->min) { + num = axis; + type = "axis"; + } + } + } else if (ie_event->type == ie_button) { + if (ie_event->button.state) { + num = ie_event->button.button; + type = "button"; + } + } + if (!type) { + return 0; + } + IE_Set_Focus (in_keyhelp_saved_handler); + Sys_Printf ("%s %s %d\n", name, type, num); + return 1; +} + +static in_devbindings_t * +in_binding_find_device (const char *name) +{ + for (size_t i = 0; i < devbindings.size; i++) { + in_devbindings_t *dev = &devbindings.a[i]; + if (strcmp (name, dev->id) == 0 + || (dev->name && strcmp (name, dev->name) == 0)) { + return dev; + } + } + return 0; +} + static void in_bind_f (void) { + if (Cmd_Argc () < 5) { + Sys_Printf ("in_bind imt device type number binding...\n"); + Sys_Printf (" imt: the name of the input mapping table in which the" + " intput will be bound\n"); + Sys_Printf (" device: the nickname or id of the devise owning" + " the input to be bound\n"); + Sys_Printf (" type: the type of input to be bound (axis or" + " button)\n"); + // FIXME support names + Sys_Printf (" number: the numeric id of the input to be bound\n"); + Sys_Printf (" binging...: the destination to which the input will" + " be bound\n"); + Sys_Printf (" for axis inputs, this can be an analog input or" + " an axis-button\n"); + Sys_Printf (" for button inputs, this can be a button or a" + " command (spaces ok, but\n" + " quotes recommended)\n"); + return; + } + + const char *imt_name = Cmd_Argv (1); + const char *dev_name = Cmd_Argv (2); + const char *type = Cmd_Argv (3); + const char *number = Cmd_Argv (4); + // the rest of the command line is the binding + //const char *binding = Cmd_Args (5); + + imt_t *imt = IMT_FindIMT (imt_name); + in_devbindings_t *dev = in_binding_find_device (dev_name); + char *end; + int num = strtol (number, &end, 0); + if (!imt) { + Sys_Printf ("unknown imt: %s\n", imt_name); + return; + } + if (!dev) { + Sys_Printf ("unknown device: %s\n", dev_name); + return; + } + if (strcmp (type, "axis") != 0 || strcmp (type, "button") != 0) { + Sys_Printf ("invalid input type: %s\n", type); + return; + } + if (*type == 'a') { + if (*end || num < 0 || num >= dev->num_axes) { + Sys_Printf ("invalid axis number: %s\n", number); + return; + } + } else { + if (*end || num < 0 || num >= dev->num_buttons) { + Sys_Printf ("invalid button number: %s\n", number); + return; + } + } } static void @@ -166,11 +282,70 @@ in_clear_f (void) static void in_devices_f (void) { + for (size_t i = 0; i < devbindings.size; i++) { + in_devbindings_t *dev = &devbindings.a[i]; + Sys_Printf ("%s %s %s\n", dev->name, dev->id, + dev->devid >= 0 ? "connected" : "disconnected"); + Sys_Printf (" axes: %d\n", dev->num_axes); + Sys_Printf (" buttons: %d\n", dev->num_buttons); + } +} + +static void +in_devname_f (void) +{ + switch (Cmd_Argc ()) { + case 2: { + const char *name = Cmd_Argv (1); + in_devbindings_t *dev = in_binding_find_device (name); + if (dev) { + if (strcmp (name, dev->id) == 0) { + Sys_Printf ("nickname for %s is %s\n", dev->id, dev->name); + } else { + Sys_Printf ("device_id for %s is %s\n", dev->name, dev->id); + } + } else { + Sys_Printf ("No device identified by %s\n", name); + } + break; + } + case 3: { + const char *device_id = Cmd_Argv (1); + const char *nickname = Cmd_Argv (2); + in_devbindings_t *dev = in_binding_find_device (nickname); + if (dev) { + Sys_Printf ("%s already exists: %s %s\n", + nickname, dev->name, dev->id); + return; + } + dev = in_binding_find_device (device_id); + if (!dev) { + Sys_Printf ("%s does not exist\n", device_id); + return; + } + if (dev->name) { + free ((char *) dev->name); + } + dev->name = strdup (nickname); + break; + } + default: + Sys_Printf ("in_devname device_id nickname\n"); + Sys_Printf (" Name a deviced identified by device_id as nickname\n"); + Sys_Printf ("in_devname device_id\n"); + Sys_Printf (" Show the nickname given to the device identified by device_id\n"); + Sys_Printf ("in_devname nickname\n"); + Sys_Printf (" Show the device_id of the device named by nickname\n"); + break; + } } static void keyhelp_f (void) { + in_keyhelp_saved_handler = IE_Get_Focus (); + IE_Set_Focus (in_keyhelp_handler); + Sys_Printf ("Press button or move axis to identify\n"); } typedef struct { @@ -194,6 +369,9 @@ static bindcmd_t in_binding_commands[] = { { "in_devices", in_devices_f, "List the known devices and their status." }, + { "in_devname", in_devname_f, + "Give a device a nickname." + }, { "keyhelp", keyhelp_f, "Identify the next active input axis or button.\n" "The identification includes the device binding name, axis or button " @@ -245,6 +423,7 @@ void IN_Binding_Init (void) { in_binding_handler = IE_Add_Handler (in_binding_event_handler, 0); + in_keyhelp_handler = IE_Add_Handler (in_keyhelp_event_handler, 0); for (bindcmd_t *cmd = in_binding_commands; cmd->name; cmd++) { Cmd_AddCommand (cmd->name, cmd->func, cmd->desc); diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 3c1a3eddb..af0aa8433 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -143,11 +143,12 @@ IMT_GetButtonBlock (const char *device, int num_buttons) } int -IMT_CreateContext (void) +IMT_CreateContext (const char *name) { in_context_t *ctx = DARRAY_OPEN_AT (&in_contexts, in_contexts.size, 1); memset (ctx, 0, sizeof (*ctx)); ctx->imt_tail = &ctx->imts; + ctx->name = name; return ctx - in_contexts.a; } From fd5abb4c61cb3e0e74e0562edf1ed240d41d2cd7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 8 Nov 2021 15:53:43 +0900 Subject: [PATCH 1790/3664] Correct the libjack package name Debian has been using jack2 for ages, about time the right lib was recommended. --- INSTALL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL b/INSTALL index 69c495ae6..4538b8716 100644 --- a/INSTALL +++ b/INSTALL @@ -50,7 +50,7 @@ The following is the list of relevant package names in debian. \li git \li libasound2-dev -\li libjack-dev +\li libjack-jackd2-dev \li libsamplerate0-dev From 925ca8081cd9497b32feebe2759bbfb337cb1d4f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 8 Nov 2021 16:54:52 +0900 Subject: [PATCH 1791/3664] [input] Implement imt creation, binding, etc Much testing is needed, but the bulk of imt management is implemented. Axis bindings are not properly implemented yet, though. --- include/QF/input/binding.h | 5 +- include/QF/input/imt.h | 3 + libs/input/in_common.c | 1 + libs/input/in_imt.c | 225 +++++++++++++++++++++++++++++++++++++ qw/source/cl_input.c | 5 + 5 files changed, 235 insertions(+), 4 deletions(-) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index bf02cef4b..36140cdb5 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -107,10 +107,7 @@ typedef enum { typedef struct in_buttonbinding_s { in_button_type type; union { - struct { - int bind_id; ///< for button multi-press support - in_button_t *button; - }; + in_button_t *button; char *command; }; } in_buttonbinding_t; diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 6cbda2e4b..7d279bbd3 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -85,8 +85,11 @@ void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf); imt_t *IMT_FindIMT (const char *name); int IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name); +void IMT_BindAxis (imt_t *imt, int axis, const char *binding); +void IMT_BindButton (imt_t *imt, int button, const char *binding); qboolean IMT_ProcessAxis (int axis, int value); qboolean IMT_ProcessButton (int button, int state); +void IMT_Init (void); #endif diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 1cded200c..102a8e8ff 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -348,6 +348,7 @@ void IN_Init (cbuf_t *cbuf) { Sys_RegisterShutdown (IN_shutdown, 0); + IMT_Init (); IN_Binding_Init (); for (size_t i = 0; i < in_drivers.size; i++) { diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index af0aa8433..2f0bf8d7c 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -40,6 +40,7 @@ #endif #include "QF/cmd.h" +#include "QF/cmem.h" #include "QF/hash.h" #include "QF/sys.h" #include "QF/va.h" @@ -59,6 +60,45 @@ static imt_blockset_t button_blocks = DARRAY_STATIC_INIT (8); static in_contextset_t in_contexts = DARRAY_STATIC_INIT (8); static size_t imt_current_context; +static memsuper_t *binding_mem; + +static in_axisbinding_t * +alloc_axis_binding (void) +{ + return cmemalloc (binding_mem, sizeof (in_axisbinding_t)); +} + +static void +free_axis_binding (in_axisbinding_t *binding) +{ + if (!binding) { + return; + } + cmemfree (binding_mem, binding); +} + +static in_buttonbinding_t * +alloc_button_binding (void) +{ + return cmemalloc (binding_mem, sizeof (in_buttonbinding_t)); +} + +static void +free_button_binding (in_buttonbinding_t *binding) +{ + if (!binding) { + return; + } + switch (binding->type) { + case inb_button: + break; + case inb_command: + free (binding->command); + break; + } + cmemfree (binding_mem, binding); +} + static imt_block_t * __attribute__((pure)) imt_find_block (imt_blockset_t *blockset, const char *device) { @@ -152,6 +192,17 @@ IMT_CreateContext (const char *name) return ctx - in_contexts.a; } +static in_context_t * +imt_find_context (const char *name) +{ + for (size_t i = 0; i < in_contexts.size; i++) { + if (strcmp (name, in_contexts.a[i].name) == 0) { + return &in_contexts.a[i]; + } + } + return 0; +} + int IMT_GetContext (void) { @@ -254,6 +305,45 @@ IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name) return 1; } +void +IMT_BindAxis (imt_t *imt, int axis, const char *binding) +{ + if ((size_t) axis >= imt->axis_bindings.size) + return; + + in_axisbinding_t **bind = &imt->axis_bindings.a[axis]; + free_axis_binding ((*bind)); + (*bind) = 0; + if (binding) { + in_axisbinding_t *a = alloc_axis_binding (); + (*bind) = a; + *a = (in_axisbinding_t) {}; + } +} + +void +IMT_BindButton (imt_t *imt, int button, const char *binding) +{ + if ((size_t) button >= imt->button_bindings.size) + return; + + in_buttonbinding_t **bind = &imt->button_bindings.a[button]; + free_button_binding ((*bind)); + (*bind) = 0; + if (binding) { + in_buttonbinding_t *b = alloc_button_binding (); + (*bind) = b; + in_button_t *button; + if (binding[0] == '+' && (button = IN_FindButton (binding + 1))) { + b->type = inb_button; + b->button = button; + } else { + b->type = inb_command; + b->command = strdup(binding); + } + } +} + qboolean IMT_ProcessAxis (int axis, int value) { @@ -315,3 +405,138 @@ IMT_ProcessButton (int button, int state) } return false; } + +static void +imt_f (void) +{ + int c; + imt_t *imt; + const char *imt_name = 0; + const char *context_name; + + c = Cmd_Argc (); + switch (c) { + case 3: + imt_name = Cmd_Argv (2); + case 2: + context_name = Cmd_Argv (1); + break; + default: + return; + } + in_context_t *ctx = imt_find_context (context_name); + if (!ctx) { + Sys_Printf ("imt error: invalid context: %s\n", context_name); + return; + } + + if (!imt_name) { + Sys_Printf ("Current imt is %s\n", ctx->active_imt->name); + Sys_Printf ("imt : set to a specific input mapping table\n"); + return; + } + + imt = imt_find_imt (ctx, imt_name); + if (!imt) { + Sys_Printf ("\"%s\" is not an imt in %s\n", imt_name, ctx->name); + return; + } + + ctx->active_imt = imt; +} + +static void +imt_list_f (void) +{ + for (size_t i = 0; i < in_contexts.size; i++) { + in_context_t *ctx = &in_contexts.a[i]; + Sys_Printf ("context: %s\n", ctx->name); + for (imt_t *imt = ctx->imts; imt; imt = imt->next) { + if (imt->chain) { + Sys_Printf (" %s -> %s\n", imt->name, imt->chain->name); + } else { + Sys_Printf (" %s\n", imt->name); + } + } + } +} + +static void +imt_create_f (void) +{ + const char *context_name; + const char *imt_name; + const char *chain_imt_name = 0; + + if (Cmd_Argc () < 3 || Cmd_Argc () > 4) { + Sys_Printf ("see help imt_create\n"); + return; + } + context_name = Cmd_Argv (1); + imt_name = Cmd_Argv (2); + if (Cmd_Argc () == 4) { + chain_imt_name = Cmd_Argv (3); + } + in_context_t *ctx = imt_find_context (context_name); + if (!ctx) { + Sys_Printf ("imt error: invalid context: %s\n", context_name); + return; + } + IMT_CreateIMT (ctx - in_contexts.a, imt_name, chain_imt_name); +} + +static void +imt_drop_all_f (void) +{ + for (size_t i = 0; i < in_contexts.size; i++) { + in_context_t *ctx = &in_contexts.a[i]; + while (ctx->imts) { + imt_t *imt = ctx->imts; + ctx->imts = imt->next; + for (size_t i = 0; i < imt->axis_bindings.size; i++) { + free_axis_binding (imt->axis_bindings.a[i]); + } + for (size_t i = 0; i < imt->button_bindings.size; i++) { + free_button_binding (imt->button_bindings.a[i]); + } + free ((char *) imt->name); + free (imt); + } + ctx->active_imt = 0; + } +} + +typedef struct { + const char *name; + xcommand_t func; + const char *desc; +} imtcmd_t; + +static imtcmd_t imt_commands[] = { + { "imt", imt_f, + "Set the active imt of the specified context" + }, + { "imt_list", imt_list_f, + "List the available input mapping tables" + }, + { "imt_create", imt_create_f, + "create a new imt table:\n" + " imt_create [chain_name]\n" + "\n" + "The new table will be attached to the specified keydest\n" + "imt_name must not already exist.\n" + "If given, chain_name must already exist and be on keydest.\n" + }, + { "imt_drop_all", imt_drop_all_f, + "delete all imt tables\n" + }, +}; + +void +IMT_Init (void) +{ + binding_mem = new_memsuper (); + for (imtcmd_t *cmd = imt_commands; cmd->name; cmd++) { + Cmd_AddCommand (cmd->name, cmd->func, cmd->desc); + } +} diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index cd6b497c6..d426609e5 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -59,6 +59,9 @@ #include "qw/include/client.h" #include "qw/include/host.h" +int cl_game_context; +int cl_demo_context; + cvar_t *cl_nodelta; cvar_t *cl_maxnetfps; cvar_t *cl_spamimpulse; @@ -522,6 +525,8 @@ CL_Input_Init (void) for (int i = 0; cl_in_buttons[i]; i++) { IN_RegisterButton (cl_in_buttons[i]); } + cl_game_context = IMT_CreateContext ("key_game"); + cl_demo_context = IMT_CreateContext ("key_demo"); Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); } From 620ea30683ee0afa021d9e64b02ce7d72fa6a217 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 8 Nov 2021 16:56:26 +0900 Subject: [PATCH 1792/3664] [input] Implement the core binding commands Again, much testing is needed, but all the core binding commands are implemented (ie, not the legacy support commands). --- libs/input/in_binding.c | 74 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 13bedce75..85e1016af 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -213,7 +213,7 @@ in_binding_find_device (const char *name) static void in_bind_f (void) { - if (Cmd_Argc () < 5) { + if (Cmd_Argc () < 6) { Sys_Printf ("in_bind imt device type number binding...\n"); Sys_Printf (" imt: the name of the input mapping table in which the" " intput will be bound\n"); @@ -238,7 +238,7 @@ in_bind_f (void) const char *type = Cmd_Argv (3); const char *number = Cmd_Argv (4); // the rest of the command line is the binding - //const char *binding = Cmd_Args (5); + const char *binding = Cmd_Args (5); imt_t *imt = IMT_FindIMT (imt_name); in_devbindings_t *dev = in_binding_find_device (dev_name); @@ -252,7 +252,7 @@ in_bind_f (void) Sys_Printf ("unknown device: %s\n", dev_name); return; } - if (strcmp (type, "axis") != 0 || strcmp (type, "button") != 0) { + if (strcmp (type, "axis") != 0 && strcmp (type, "button") != 0) { Sys_Printf ("invalid input type: %s\n", type); return; } @@ -261,22 +261,90 @@ in_bind_f (void) Sys_Printf ("invalid axis number: %s\n", number); return; } + IMT_BindAxis (imt, dev->axis_imt_id + num, binding); } else { if (*end || num < 0 || num >= dev->num_buttons) { Sys_Printf ("invalid button number: %s\n", number); return; } + IMT_BindButton (imt, dev->button_imt_id + num, binding); } } static void in_unbind_f (void) { + if (Cmd_Argc () < 6) { + Sys_Printf ("in_unbind imt device type number\n"); + Sys_Printf (" imt: the name of the input mapping table in which the" + " intput will be unbound\n"); + Sys_Printf (" device: the nickname or id of the devise owning" + " the input to be unbound\n"); + Sys_Printf (" type: the type of input to be unbound (axis or" + " button)\n"); + // FIXME support names + Sys_Printf (" number: the numeric id of the input to be unbound\n"); + return; + } + + const char *imt_name = Cmd_Argv (1); + const char *dev_name = Cmd_Argv (2); + const char *type = Cmd_Argv (3); + const char *number = Cmd_Argv (4); + + imt_t *imt = IMT_FindIMT (imt_name); + in_devbindings_t *dev = in_binding_find_device (dev_name); + char *end; + int num = strtol (number, &end, 0); + if (!imt) { + Sys_Printf ("unknown imt: %s\n", imt_name); + return; + } + if (!dev) { + Sys_Printf ("unknown device: %s\n", dev_name); + return; + } + if (strcmp (type, "axis") != 0 && strcmp (type, "button") != 0) { + Sys_Printf ("invalid input type: %s\n", type); + return; + } + if (*type == 'a') { + if (*end || num < 0 || num >= dev->num_axes) { + Sys_Printf ("invalid axis number: %s\n", number); + return; + } + IMT_BindAxis (imt, dev->axis_imt_id + num, 0); + } else { + if (*end || num < 0 || num >= dev->num_buttons) { + Sys_Printf ("invalid button number: %s\n", number); + return; + } + IMT_BindButton (imt, dev->button_imt_id + num, 0); + } } static void in_clear_f (void) { + int argc = Cmd_Argc (); + if (argc < 2) { + Sys_Printf ("in_clear imt [imt...]\n"); + return; + } + for (int i = 1; i < argc; i++) { + const char *imt_name = Cmd_Argv (i); + imt_t *imt = IMT_FindIMT (imt_name); + if (!imt) { + Sys_Printf ("unknown imt: %s\n", imt_name); + continue; + } + for (size_t ind = 0; ind < imt->axis_bindings.size; ind++) { + IMT_BindAxis (imt, ind, 0); + } + for (size_t ind = 0; ind < imt->button_bindings.size; ind++) { + IMT_BindButton (imt, ind, 0); + } + } } static void From 5328c06fbfa6cf1c69e3fde57669f7701237c332 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Nov 2021 22:23:57 +0900 Subject: [PATCH 1793/3664] [input] Clean up imt.h a little Unnecessary enum removed, and the imt block struct moved to imt.c (doesn't need to be public). Also, remove device name from the imt block (and thus the parameter to the functions) as it turns out not to be needed. --- include/QF/input/imt.h | 24 ++------------------- libs/input/in_imt.c | 47 ++++++++++++++++++------------------------ 2 files changed, 22 insertions(+), 49 deletions(-) diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 7d279bbd3..a6e38334e 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -36,26 +36,6 @@ #include "QF/input/binding.h" -typedef enum { - imt_button, - imt_axis, -} imt_type; - -/** Describe a region of imt bindings (axis or button) - - Each device may have a block of axis bindings and a block of button - bindings (some devices will have only the one block). The device name is - used instead of a pointer to the device descriptor so configs can be - preserved even if the device is not present. - - Bindings are allocated to a device in contiguous blocks. -*/ -typedef struct imt_block_s { - const char *device; ///< name of the owning device - int base; ///< index of first binding - int count; ///< number of bindings -} imt_block_t; - /** Input Mapping Table */ typedef struct imt_s { @@ -76,8 +56,8 @@ typedef struct in_context_s { struct cbuf_s *cbuf; } in_context_t; -int IMT_GetAxisBlock (const char *device, int num_axes); -int IMT_GetButtonBlock (const char *device, int num_buttons); +int IMT_GetAxisBlock (int num_axes); +int IMT_GetButtonBlock (int num_buttons); int IMT_CreateContext (const char *name); int IMT_GetContext (void); void IMT_SetContext (int ctx); diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 2f0bf8d7c..2589d2f28 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -50,6 +50,18 @@ #include "QF/input/binding.h" #include "QF/input/imt.h" +/** Describe a region of imt bindings (axis or button) + + Each device may have a block of axis bindings and a block of button + bindings (some devices will have only the one block). + + Bindings are allocated to a device in contiguous blocks. +*/ +typedef struct imt_block_s { + int base; ///< index of first binding + int count; ///< number of bindings +} imt_block_t; + typedef struct DARRAY_TYPE (in_context_t) in_contextset_t; typedef struct DARRAY_TYPE (imt_block_t) imt_blockset_t; /** Binding blocks are allocated across all imts @@ -99,17 +111,6 @@ free_button_binding (in_buttonbinding_t *binding) cmemfree (binding_mem, binding); } -static imt_block_t * __attribute__((pure)) -imt_find_block (imt_blockset_t *blockset, const char *device) -{ - for (size_t i = 0; i < blockset->size; i++) { - if (strcmp (blockset->a[i].device, device) == 0) { - return &blockset->a[i]; - } - } - return 0; -} - static imt_block_t * imt_get_block (imt_blockset_t *blockset) { @@ -157,28 +158,20 @@ imt_get_button_block (int count) } int -IMT_GetAxisBlock (const char *device, int num_axes) +IMT_GetAxisBlock (int num_axes) { - imt_block_t *block; - if (!(block = imt_find_block (&axis_blocks, device))) { - block = imt_get_block (&axis_blocks); - block->device = device; - block->base = imt_get_axis_block (num_axes); - block->count = num_axes; - } + imt_block_t *block = imt_get_block (&axis_blocks); + block->base = imt_get_axis_block (num_axes); + block->count = num_axes; return block - axis_blocks.a; } int -IMT_GetButtonBlock (const char *device, int num_buttons) +IMT_GetButtonBlock (int num_buttons) { - imt_block_t *block; - if (!(block = imt_find_block (&button_blocks, device))) { - block = imt_get_block (&button_blocks); - block->device = device; - block->base = imt_get_button_block (num_buttons); - block->count = num_buttons; - } + imt_block_t *block = imt_get_block (&button_blocks); + block->base = imt_get_button_block (num_buttons); + block->count = num_buttons; return block - button_blocks.a; } From f5ccf46ae3f667ca2a18bbe9acf6f7bfc3bc5066 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Nov 2021 22:28:56 +0900 Subject: [PATCH 1794/3664] [input] Correct some comments Not much worse than incorrect comments. --- include/QF/input.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 7d8a5c96c..91be187c4 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -104,11 +104,11 @@ typedef struct in_device_s { \a button_info holds the current raw state of the button - \a axis_imt_id is 0 if the device has no axis bindings, otherwise it is - the index into the imt array for the imt group. + \a axis_imt_id is -1 if the device has no axis bindings, otherwise it is + the base index into the imt axis bindings array. - \a button_imt_id is 0 if the device has no button bindings, otherwise it - is the index into the imt array for the imt group. + \a button_imt_id is -1 if the device has no button bindings, otherwise it + is the base index into the imt button bindings array. */ typedef struct in_devbindings_s { const char *name; ///< name used when binding inputs From b95c749438407b039fe761e0b2807fbccf69453f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Nov 2021 22:31:09 +0900 Subject: [PATCH 1795/3664] [input] Add a per-device event data pointer This might pose a problem with multiple event targets (we'll see), but it will make connecting input devices to bindings much easier. --- include/QF/input.h | 6 ++++++ include/QF/input/event.h | 2 ++ libs/input/in_common.c | 28 ++++++++++++++++++++++++++++ libs/input/in_evdev.c | 21 +++++++++++++++++++++ libs/video/targets/in_win.c | 13 +++++++++++++ libs/video/targets/in_x11.c | 27 ++++++++++++++++++++++++--- ruamoko/qwaq/builtins/input.c | 13 +++++++++++++ 7 files changed, 107 insertions(+), 3 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 91be187c4..4e7cf01a1 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -60,6 +60,9 @@ typedef struct in_driver_s { void (*init) (void *data); void (*shutdown) (void *data); + void (*set_device_event_data) (void *device, void *event_data, void *data); + void *(*get_device_event_data) (void *device, void *data); + // The driver must provide either both or none of add_select and // chec_select. void (*add_select) (struct qf_fd_set *fdset, int *maxfd, void *data); @@ -81,6 +84,7 @@ typedef struct in_device_s { void *device; const char *name; const char *id; + void *event_data; } in_device_t; /*** Connect a device and its axes and buttons to logical axes and buttons. @@ -139,6 +143,8 @@ void IN_RemoveDevice (int devid); void IN_SendConnectedDevices (void); const char *IN_GetDeviceName (int devid) __attribute__((pure)); const char *IN_GetDeviceId (int devid) __attribute__((pure)); +void IN_SetDeviceEventData (int devid, void *data); +void *IN_GetDeviceEventData (int devid); int IN_AxisInfo (int devid, in_axisinfo_t *axes, int *numaxes); int IN_ButtonInfo (int devid, in_buttoninfo_t *button, int *numbuttons); diff --git a/include/QF/input/event.h b/include/QF/input/event.h index 4ce0dd2b3..2339dd732 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -63,12 +63,14 @@ typedef struct { } IE_key_event_t; typedef struct { + void *data; int devid; int axis; int value; } IE_axis_event_t; typedef struct { + void *data; int devid; int button; int state; diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 102a8e8ff..fa85b3982 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -204,6 +204,34 @@ IN_GetDeviceId (int devid) return in_devices.a[devid].id; } +void +IN_SetDeviceEventData (int devid, void *data) +{ + if ((size_t) devid >= in_devices.size) { + return; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return; + } + in_regdriver_t *rd = &in_drivers.a[in_devices.a[devid].driverid]; + rd->driver.set_device_event_data (in_devices.a[devid].device, data, + rd->data); +} + +void * +IN_GetDeviceEventData (int devid) +{ + if ((size_t) devid >= in_devices.size) { + return 0; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return 0; + } + in_regdriver_t *rd = &in_drivers.a[in_devices.a[devid].driverid]; + return rd->driver.get_device_event_data (in_devices.a[devid].device, + rd->data); +} + int IN_AxisInfo (int devid, in_axisinfo_t *axes, int *numaxes) { diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 0e1f50ecc..0e693eb26 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -51,6 +51,7 @@ typedef struct devmap_s { struct devmap_s *next; struct devmap_s **prev; device_t *device; + void *event_data; int devid; } devmap_t; @@ -76,6 +77,22 @@ in_evdev_shutdown (void *data) inputlib_close (); } +static void +in_evdev_set_device_event_data (void *device, void *event_data, void *data) +{ + device_t *dev = device; + devmap_t *dm = dev->data; + dm->event_data = event_data; +} + +static void * +in_evdev_get_device_event_data (void *device, void *data) +{ + device_t *dev = device; + devmap_t *dm = dev->data; + return dm->event_data; +} + static void in_evdev_axis_event (axis_t *axis, void *_dm) { @@ -86,6 +103,7 @@ in_evdev_axis_event (axis_t *axis, void *_dm) .type = ie_axis, .when = Sys_LongTime (), .axis = { + .data = dm->event_data, .devid = dm->devid, .axis = axis->num, .value = axis->value, @@ -104,6 +122,7 @@ in_evdev_button_event (button_t *button, void *_dm) .type = ie_button, .when = Sys_LongTime (), .button = { + .data = dm->event_data, .devid = dm->devid, .button = button->num, .state = button->state, @@ -223,6 +242,8 @@ in_evdev_button_info (void *data, void *device, in_buttoninfo_t *buttons, static in_driver_t in_evdev_driver = { .init = in_evdev_init, .shutdown = in_evdev_shutdown, + .set_device_event_data = in_evdev_set_device_event_data, + .get_device_event_data = in_evdev_get_device_event_data, .add_select = in_evdev_add_select, .check_select = in_evdev_check_select, .clear_states = in_evdev_clear_states, diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index d523598b6..588e58c35 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -390,6 +390,17 @@ in_win_shutdown (void *data) } } +static void +in_win_set_device_event_data (void *device, void *event_data, void *data) +{ +} + +static void * +in_win_get_device_event_data (void *device, void *data) +{ + return 0; +} + static void IN_MouseEvent (unsigned mstate) { @@ -875,6 +886,8 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) static in_driver_t in_win_driver = { .init = in_win_init, .shutdown = in_win_shutdown, + .set_device_event_data = in_win_set_device_event_data, + .get_device_event_data = in_win_get_device_event_data, .process_events = in_win_process_events, .clear_states = in_win_clear_states, //.grab_input = in_win_grab_input, diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 7c7afe24e..17c08ce67 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -87,6 +87,7 @@ typedef struct x11_device_s { int num_buttons; in_axisinfo_t *axes; in_buttoninfo_t *buttons; + void *event_data; int devid; } x11_device_t; @@ -645,6 +646,7 @@ in_x11_send_axis_event (int devid, in_axisinfo_t *axis) .type = ie_axis, .when = Sys_LongTime (), .axis = { + .data = x11_mouse_device.event_data, .devid = devid, .axis = axis->axis, .value = axis->value, @@ -677,12 +679,13 @@ in_x11_send_key_event (void) } static void -in_x11_send_button_event (int devid, in_buttoninfo_t *button) +in_x11_send_button_event (int devid, in_buttoninfo_t *button, void *event_data) { IE_event_t event = { .type = ie_button, .when = Sys_LongTime (), .button = { + .data = event_data, .devid = devid, .button = button->button, .state = button->state, @@ -779,7 +782,8 @@ event_button (XEvent *event) int press = event->type == ButtonPress; x11_mouse_buttons[but].state = press; - in_x11_send_button_event (x11_mouse_device.devid, &x11_mouse_buttons[but]); + in_x11_send_button_event (x11_mouse_device.devid, &x11_mouse_buttons[but], + x11_mouse_device.event_data); x11_mouse.shift = event->xmotion.state & 0xff; x11_mouse.x = event->xmotion.x; @@ -803,7 +807,8 @@ event_key (XEvent *event) key = (event->xkey.keycode - 8) & 0xff; x11_key_buttons[key].state = event->type == KeyPress; in_x11_send_button_event (x11_keyboard_device.devid, - &x11_key_buttons[key]); + &x11_key_buttons[key], + x11_keyboard_device.event_data); x11_key.shift = event->xmotion.state & 0xff; XLateKey (&event->xkey, &x11_key.code, &x11_key.unicode); @@ -942,6 +947,20 @@ in_x11_shutdown (void *data) X11_CloseDisplay (); } +static void +in_x11_set_device_event_data (void *device, void *event_data, void *data) +{ + x11_device_t *dev = device; + dev->event_data = event_data; +} + +static void * +in_x11_get_device_event_data (void *device, void *data) +{ + x11_device_t *dev = device; + return dev->event_data; +} + static void in_x11_init_cvars (void) { @@ -1028,6 +1047,8 @@ in_x11_clear_states (void *data) static in_driver_t in_x11_driver = { .init = in_x11_init, .shutdown = in_x11_shutdown, + .set_device_event_data = in_x11_set_device_event_data, + .get_device_event_data = in_x11_get_device_event_data, #ifdef X11_USE_SELECT .add_select = in_x11_add_select, .check_select = in_x11_check_select, diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 82c3f8f16..43b6c78b0 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -467,6 +467,17 @@ term_shutdown (void *_res) { } +static void +term_set_device_event_data (void *device, void *event_data, void *data) +{ +} + +static void * +term_get_device_event_data (void *device, void *data) +{ + return 0; +} + #define FD 0 static void term_add_select (qf_fd_set *fdset, int *maxfd, void *_res) @@ -506,6 +517,8 @@ term_check_select (qf_fd_set *fdset, void *_res) static in_driver_t term_driver = { .init = term_init, .shutdown = term_shutdown, + .set_device_event_data = term_set_device_event_data, + .get_device_event_data = term_get_device_event_data, .add_select = term_add_select, .check_select = term_check_select, }; From b231b63413b5455af174d247417b49d691bedeae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Nov 2021 13:22:44 +0900 Subject: [PATCH 1796/3664] [input] Implement hot-plug support for bindings Hot-plug support is done via "connections" (not sure I'm happy with the name) that provide a user specifiable name to input devices. The connections record the device name (eg, "6d spacemouse") and id (usually usb path for evdev devices, but may be the device unique id if available) and whether automatic reconnection should match just the device name or both device name and id (prevents problems with changing the device connected to the one usb port). --- include/QF/input.h | 25 +-- libs/input/in_binding.c | 345 +++++++++++++++++++++++++++++----------- libs/input/in_evdev.c | 6 +- 3 files changed, 267 insertions(+), 109 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 4e7cf01a1..6618e1a0f 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -92,13 +92,17 @@ typedef struct in_device_s { \a name is used to specify the device when creating bindings, and identifying the device for hints etc (eg, "press joy1 1 to ..."). - \a id is the device name (eg, "6d spacemouse") or (preferred) the device - id (eg "usb-0000:00:1d.1-2/input0"). The device name is useful for ease of - user identification and allowing the device to be plugged into any USB - socket. However, it doesn't allow multiple devices with the same name - (eg, using twin joysticks of the same model). Thus the device id is - preferred, but does require the device to be plugged into the same uSB - path (ie, same socket on the same hub connected to the same port on the PC) + \a devname is the device name (eg, "6d spacemouse") + + \a id is the device id (eg "usb-0000:00:1d.1-2/input0"). + + The device name is useful for ease of user identification and allowing + the device to be plugged into any USB socket. However, it doesn't allow + multiple devices with the same name (eg, using twin joysticks of the same + model). Thus if \a match_id is true, both the device name and the device + id used to auto-connect the device, but it does require the device to be + plugged into the same uSB path (ie, same socket on the same hub connected + to the same port on the PC) \a devid is the actual device associated with the bindings. If -1, the device is not currently connected. @@ -115,8 +119,11 @@ typedef struct in_device_s { is the base index into the imt button bindings array. */ typedef struct in_devbindings_s { - const char *name; ///< name used when binding inputs - const char *id; ///< physical device name or id (preferred) + struct in_devbindings_s *next; + char *name; ///< name used when binding inputs + char *devname; ///< physical device name + char *id; ///< physical device id + int match_id; ///< if true, both devname and id must match int devid; ///< id of device associated with these bindings int num_axes; int num_buttons; diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 85e1016af..bd7b1206a 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -40,7 +40,9 @@ #include "QF/cmd.h" #include "QF/hash.h" +#include "QF/heapsort.h" #include "QF/input.h" +#include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" #include "QF/input/imt.h" @@ -49,67 +51,111 @@ #include "QF/input/event.h" #include "QF/input/imt.h" -typedef struct DARRAY_TYPE (in_devbindings_t) in_devbindingset_t; +typedef struct DARRAY_TYPE (int) in_knowndevset_t; -static in_devbindingset_t devbindings = DARRAY_STATIC_INIT (8); +static in_knowndevset_t known_devices = DARRAY_STATIC_INIT (8); static int in_binding_handler; static int in_keyhelp_handler; static int in_keyhelp_saved_handler; +static PR_RESMAP (in_devbindings_t) devbindings; +static in_devbindings_t *devbindings_list; + +static int +devid_cmp (const void *a, const void *b) +{ + return *(const int *)a - *(const int *)b; +} + +static int * +in_find_devid (int devid) +{ + return bsearch (&devid, known_devices.a, known_devices.size, + sizeof (int), devid_cmp); +} + +static in_devbindings_t * +in_binding_find_connection (const char *devname, const char *id) +{ + in_devbindings_t *db; + + //FIXME slow + for (db = devbindings_list; db; db = db->next) { + if (strcmp (devname, db->devname) != 0) { + continue; + } + if (db->match_id && strcmp (id, db->id) != 0) { + continue; + } + return db; + } + return 0; +} + static void in_binding_add_device (const IE_event_t *ie_event) { size_t devid = ie_event->device.devid; - if (devid >= devbindings.size) { - DARRAY_RESIZE (&devbindings, devid + 1); - memset (&devbindings.a[devid], 0, sizeof (in_devbindings_t)); - } - in_devbindings_t *db = &devbindings.a[devid]; - if (db->id) { - if (db->id != IN_GetDeviceId (devid)) { - Sys_Error ("in_binding_add_device: devid conflict: %zd", devid); - } - Sys_Printf ("in_binding_add_device: readd %s\n", db->id); + + if (in_find_devid (devid)) { + // the device is already known. this is likely the result of a + // broadcast of connected devices return; } - db->id = IN_GetDeviceId (devid); - db->devid = devid; - IN_AxisInfo (devid, 0, &db->num_axes); - IN_ButtonInfo (devid, 0, &db->num_buttons); - db->axis_info = malloc (db->num_axes * sizeof (in_axisinfo_t) - + db->num_buttons * sizeof (in_buttoninfo_t)); - db->button_info = (in_buttoninfo_t *) &db->axis_info[db->num_axes]; - IN_AxisInfo (devid, db->axis_info, &db->num_axes); - IN_ButtonInfo (devid, db->button_info, &db->num_buttons); - Sys_Printf ("in_binding_add_device: %s %d %d\n", db->id, db->num_axes, - db->num_buttons); + DARRAY_APPEND (&known_devices, devid); + // keep the known devices sorted by id + heapsort (known_devices.a, known_devices.size, sizeof (int), devid_cmp); + + const char *devname = IN_GetDeviceName (devid); + const char *id = IN_GetDeviceId (devid); + in_devbindings_t *db = in_binding_find_connection (devname, id); + + if (db) { + if (db->match_id) { + Sys_Printf ("Reconnected %s to %s %s\n", db->name, devname, id); + } else { + Sys_Printf ("Reconnected %s to %s\n", db->name, devname); + } + db->devid = devid; + IN_SetDeviceEventData (devid, db); + } else { + Sys_Printf ("Added device %s %s\n", devname, id); + } } static void in_binding_remove_device (const IE_event_t *ie_event) { size_t devid = ie_event->device.devid; - in_devbindings_t *db = &devbindings.a[devid]; + in_devbindings_t *db = IN_GetDeviceEventData (devid); + int *kd; - if (devid >= devbindings.size) { + if (!(kd = in_find_devid (devid))) { Sys_Error ("in_binding_remove_device: invalid devid: %zd", devid); } - if (!db->id) { - return; + DARRAY_REMOVE_AT (&known_devices, kd - known_devices.a); + + const char *devname = IN_GetDeviceName (devid); + const char *id = IN_GetDeviceId (devid); + if (db) { + db->devid = -1; + if (db->match_id) { + Sys_Printf ("Disconnected %s from %s %s\n", db->name, devname, id); + } else { + Sys_Printf ("Disconnected %s from %s\n", db->name, devname); + } } - free (db->axis_info); // axis and button info in same block - memset (db, 0, sizeof (*db)); + Sys_Printf ("Removed device %s %s\n", devname, id); } static void in_binding_axis (const IE_event_t *ie_event) { - size_t devid = ie_event->axis.devid; int axis = ie_event->axis.axis; int value = ie_event->axis.value; - in_devbindings_t *db = &devbindings.a[devid]; + in_devbindings_t *db = ie_event->axis.data;; - if (devid < devbindings.size && axis < db->num_axes) { + if (db && axis < db->num_axes) { db->axis_info[axis].value = value; if (db->axis_imt_id) { IMT_ProcessAxis (db->axis_imt_id + axis, value); @@ -120,12 +166,11 @@ in_binding_axis (const IE_event_t *ie_event) static void in_binding_button (const IE_event_t *ie_event) { - size_t devid = ie_event->button.devid; int button = ie_event->button.button; int state = ie_event->button.state; - in_devbindings_t *db = &devbindings.a[devid]; + in_devbindings_t *db = ie_event->button.data; - if (devid < devbindings.size && button < db->num_buttons) { + if (db && button < db->num_buttons) { db->button_info[button].state = state; if (db->button_imt_id) { IMT_ProcessButton (db->button_imt_id + button, state); @@ -150,6 +195,8 @@ in_binding_event_handler (const IE_event_t *ie_event, void *unused) return 1; } +static int keyhelp_axis_threshold; + static int in_keyhelp_event_handler (const IE_event_t *ie_event, void *unused) { @@ -158,25 +205,35 @@ in_keyhelp_event_handler (const IE_event_t *ie_event, void *unused) } size_t devid = ie_event->button.devid; - in_devbindings_t *db = &devbindings.a[devid]; - const char *name = db->name; + in_devbindings_t *db = ie_event->button.data; + const char *name = db ? db->name : 0; const char *type = 0; int num = -1; - - if (!name) { - name = db->id; - } + const char *devname = IN_GetDeviceName (devid); + const char *id = IN_GetDeviceId (devid); if (ie_event->type == ie_axis) { int axis = ie_event->axis.axis; int value = ie_event->axis.value; - in_axisinfo_t *ai = &db->axis_info[axis]; + in_axisinfo_t *ai; + if (db) { + ai = &db->axis_info[axis]; + } else { + //FIXME set single axis info entry + int num_axes; + in_axisinfo_t *axis_info; + IN_AxisInfo (devid, 0, &num_axes); + axis_info = alloca (num_axes * sizeof (in_axisinfo_t)); + IN_AxisInfo (devid, axis_info, &num_axes); + ai = &axis_info[axis]; + } if (!ai->min && !ai->max) { - if (value > 2) { + if (abs (value) > keyhelp_axis_threshold) { num = axis; type = "axis"; } } else { + //FIXME does not work if device has not been connected (db is null) int diff = abs (value - ai->value); if (diff * 5 >= ai->max - ai->min) { num = axis; @@ -193,18 +250,18 @@ in_keyhelp_event_handler (const IE_event_t *ie_event, void *unused) return 0; } IE_Set_Focus (in_keyhelp_saved_handler); - Sys_Printf ("%s %s %d\n", name, type, num); + Sys_Printf ("%s (%s %s) %s %d\n", name, devname, id, type, num); return 1; } static in_devbindings_t * in_binding_find_device (const char *name) { - for (size_t i = 0; i < devbindings.size; i++) { - in_devbindings_t *dev = &devbindings.a[i]; - if (strcmp (name, dev->id) == 0 - || (dev->name && strcmp (name, dev->name) == 0)) { - return dev; + in_devbindings_t *db; + + for (db = devbindings_list; db; db = db->next) { + if (strcmp (name, db->name) == 0) { + break; } } return 0; @@ -261,12 +318,18 @@ in_bind_f (void) Sys_Printf ("invalid axis number: %s\n", number); return; } + if (dev->axis_imt_id == -1) { + dev->axis_imt_id = IMT_GetAxisBlock (dev->num_axes); + } IMT_BindAxis (imt, dev->axis_imt_id + num, binding); } else { if (*end || num < 0 || num >= dev->num_buttons) { Sys_Printf ("invalid button number: %s\n", number); return; } + if (dev->button_imt_id == -1) { + dev->button_imt_id = IMT_GetAxisBlock (dev->num_buttons); + } IMT_BindButton (imt, dev->button_imt_id + num, binding); } } @@ -350,67 +413,150 @@ in_clear_f (void) static void in_devices_f (void) { - for (size_t i = 0; i < devbindings.size; i++) { - in_devbindings_t *dev = &devbindings.a[i]; - Sys_Printf ("%s %s %s\n", dev->name, dev->id, - dev->devid >= 0 ? "connected" : "disconnected"); - Sys_Printf (" axes: %d\n", dev->num_axes); - Sys_Printf (" buttons: %d\n", dev->num_buttons); + for (size_t i = 0; i < known_devices.size; i++) { + int devid = known_devices.a[i]; + in_devbindings_t *db = IN_GetDeviceEventData (devid); + const char *name = IN_GetDeviceName (devid); + const char *id = IN_GetDeviceId (devid); + int num_axes, num_buttons; + IN_AxisInfo (devid, 0, &num_axes); + IN_ButtonInfo (devid, 0, &num_buttons); + + Sys_Printf ("devid %d:\n", devid); + if (db) { + Sys_Printf (" bind name: %s\n", db->name); + } else { + Sys_Printf (" no bind name\n"); + } + Sys_Printf (" name: %s\n", name); + Sys_Printf (" id: %s\n", id); + Sys_Printf (" axes: %d\n", num_axes); + Sys_Printf (" buttons: %d\n", num_buttons); } } static void -in_devname_f (void) +in_connect_f (void) { - switch (Cmd_Argc ()) { - case 2: { - const char *name = Cmd_Argv (1); - in_devbindings_t *dev = in_binding_find_device (name); - if (dev) { - if (strcmp (name, dev->id) == 0) { - Sys_Printf ("nickname for %s is %s\n", dev->id, dev->name); - } else { - Sys_Printf ("device_id for %s is %s\n", dev->name, dev->id); + int argc = Cmd_Argc (); + const char *fullid = 0; + + if (argc == 4) { + fullid = Cmd_Argv (3); + } + if (argc < 3 || argc > 4 || (fullid && strcmp (fullid, "fullid"))) { + goto in_connect_usage; + } + const char *bindname = Cmd_Argv (1); + const char *device_id = Cmd_Argv (2); + int devid = -1; + + for (in_devbindings_t *db = devbindings_list; db; db = db->next) { + if (strcmp (bindname, db->name) == 0) { + Sys_Printf ("%s already exists\n", bindname); + return; + } + } + + if (device_id[0] == '#') { + char *end; + devid = strtol (device_id + 1, &end, 0); + if (*end || !in_find_devid (devid)) { + Sys_Printf ("Not a valid device number: %s", device_id); + return; + } + } else { + int len = strlen (device_id); + + for (size_t i = 0; i < known_devices.size; i++) { + if (strcmp (device_id, IN_GetDeviceId (known_devices.a[i])) == 0) { + devid = known_devices.a[i]; + break; + } + if (strncasecmp (device_id, + IN_GetDeviceName (known_devices.a[i]), + len) == 0) { + if (devid > -1) { + Sys_Printf ("'%s' is ambiguous\n", device_id); + return; } - } else { - Sys_Printf ("No device identified by %s\n", name); + devid = known_devices.a[i]; } - break; } - case 3: { - const char *device_id = Cmd_Argv (1); - const char *nickname = Cmd_Argv (2); - in_devbindings_t *dev = in_binding_find_device (nickname); - if (dev) { - Sys_Printf ("%s already exists: %s %s\n", - nickname, dev->name, dev->id); - return; - } - dev = in_binding_find_device (device_id); - if (!dev) { - Sys_Printf ("%s does not exist\n", device_id); - return; - } - if (dev->name) { - free ((char *) dev->name); - } - dev->name = strdup (nickname); - break; + } + if (devid == -1) { + Sys_Printf ("No such device: %s\n", device_id); + return; + } + if (IN_GetDeviceEventData (devid)) { + Sys_Printf ("%s already connected\n", device_id); + return; + } + + in_devbindings_t *db = PR_RESNEW (devbindings); + db->next = devbindings_list; + devbindings_list = db; + + db->name = strdup (bindname); + db->devname = strdup (IN_GetDeviceName (devid)); + db->id = strdup (IN_GetDeviceId (devid)); + db->match_id = !!fullid; + db->devid = devid; + + IN_AxisInfo (devid, 0, &db->num_axes); + IN_ButtonInfo (devid, 0, &db->num_buttons); + db->axis_info = malloc (db->num_axes * sizeof (in_axisinfo_t) + + db->num_buttons * sizeof (in_buttoninfo_t)); + db->button_info = (in_buttoninfo_t *) &db->axis_info[db->num_axes]; + IN_AxisInfo (devid, db->axis_info, &db->num_axes); + IN_ButtonInfo (devid, db->button_info, &db->num_buttons); + + db->axis_imt_id = -1; + db->button_imt_id = -1; + + IN_SetDeviceEventData (devid, db); + + return; +in_connect_usage: + Sys_Printf ("in_connect bindname device_id [fullid]\n"); + Sys_Printf (" Create a new device binding connection.\n"); + Sys_Printf (" bindname: Connection name used for binding inputs\n."); + Sys_Printf (" device_id: Specify the device to be connected.\n"); + Sys_Printf (" May be the numeric device number (#N), the device\n"); + Sys_Printf (" name or device id as shown by in_devices.\n"); + Sys_Printf (" fullid: if present, both device name and device id\n"); + Sys_Printf (" will be used when automatically reconnecting the\n"); + Sys_Printf (" device.\n"); +} + +static void +in_connections_f (void) +{ + for (in_devbindings_t *db = devbindings_list; db; db = db->next) { + if (db->match_id) { + Sys_Printf ("%s: %s %s\n", db->name, db->devname, db->id); + } else { + Sys_Printf ("%s: %s\n", db->name, db->devname); + } + if (db->devid > -1) { + Sys_Printf (" connected\n"); + } else { + Sys_Printf (" disconnected\n"); } - default: - Sys_Printf ("in_devname device_id nickname\n"); - Sys_Printf (" Name a deviced identified by device_id as nickname\n"); - Sys_Printf ("in_devname device_id\n"); - Sys_Printf (" Show the nickname given to the device identified by device_id\n"); - Sys_Printf ("in_devname nickname\n"); - Sys_Printf (" Show the device_id of the device named by nickname\n"); - break; } } static void keyhelp_f (void) { + keyhelp_axis_threshold = 3; + if (Cmd_Argc () > 1) { + char *end; + int threshold = strtol (Cmd_Argv (1), &end, 0); + if (!*end && threshold > 0) { + keyhelp_axis_threshold = threshold; + } + } in_keyhelp_saved_handler = IE_Get_Focus (); IE_Set_Focus (in_keyhelp_handler); Sys_Printf ("Press button or move axis to identify\n"); @@ -437,8 +583,13 @@ static bindcmd_t in_binding_commands[] = { { "in_devices", in_devices_f, "List the known devices and their status." }, - { "in_devname", in_devname_f, - "Give a device a nickname." + { "in_connect", in_connect_f, + "Create a device binding connection. Supports hot-plug in that the " + "device will be automatically reconnected when plugged in or" + PACKAGE_NAME " is restarted." + }, + { "in_connections", in_connections_f, + "List device bindings and statuses." }, { "keyhelp", keyhelp_f, "Identify the next active input axis or button.\n" diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 0e693eb26..a2c6a7faa 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -150,13 +150,13 @@ device_add (device_t *dev) } devmap_list = dm; - dm->device = dev; - dm->devid = IN_AddDevice (evdev_driver_handle, dev, name, id); - dev->data = dm; dev->axis_event = in_evdev_axis_event; dev->button_event = in_evdev_button_event; + dm->device = dev; + dm->devid = IN_AddDevice (evdev_driver_handle, dev, name, id); + #if 0 Sys_Printf ("in_evdev: add %s\n", dev->path); Sys_Printf (" %s\n", dev->name); From 9172e761078a38e8f3363c5712f7dcef0b8caf68 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Nov 2021 15:48:22 +0900 Subject: [PATCH 1797/3664] [input] Move name and description into in_axis_t Like with in_button_t, it makes creating static axes a little easier. --- include/QF/input/binding.h | 10 +++++++--- libs/input/in_axis.c | 23 +++++++---------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 36140cdb5..1b8fadcc0 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -63,6 +63,8 @@ typedef enum { typedef struct in_axis_s { float value; ///< converted value of the axis in_axis_mode mode; ///< method used for updating the destination + const char *name; + const char *description; } in_axis_t; /*** Current state of the logical button. @@ -95,7 +97,10 @@ typedef struct in_button_s { } in_button_t; typedef struct in_axisbinding_s { - in_recipe_t *recipe; + union { + in_recipe_t *recipe;///< for absolute axes + float scale; ///< for relative axes + }; in_axis_t *axis; } in_axisbinding_t; @@ -210,8 +215,7 @@ IN_ButtonReleased (in_button_t *button) void IN_ButtonAction (in_button_t *buttin, int id, int pressed); int IN_RegisterButton (in_button_t *button); -int IN_RegisterAxis (in_axis_t *axis, const char *name, - const char *description); +int IN_RegisterAxis (in_axis_t *axis); in_button_t *IN_FindButton (const char *name); void IN_Binding_Init (void); diff --git a/libs/input/in_axis.c b/libs/input/in_axis.c index b9e980fda..f945e2590 100644 --- a/libs/input/in_axis.c +++ b/libs/input/in_axis.c @@ -43,38 +43,29 @@ #include "QF/input.h" #include "QF/sys.h" -typedef struct regaxis_s { - const char *name; - const char *description; - in_axis_t *axis; -} regaxis_t; - static hashtab_t *axis_tab; static const char * -axis_get_key (const void *b, void *data) +axis_get_key (const void *a, void *data) { - __auto_type regaxis = (const regaxis_t *) b; - return regaxis->name; + __auto_type axis = (const in_axis_t *) a; + return axis->name; } static void -axis_free (void *b, void *data) +axis_free (void *a, void *data) { - free (b); } VISIBLE int -IN_RegisterAxis (in_axis_t *axis, const char *name, const char *description) +IN_RegisterAxis (in_axis_t *axis) { + const char *name = axis->name; if (Hash_Find (axis_tab, name)) { return 0; } - regaxis_t *regaxis = malloc (sizeof (regaxis_t)); - regaxis->name = name; - regaxis->description = description; - regaxis->axis = axis; + Hash_Add (axis_tab, axis); return 1; } From 6da8a2622f59dc2626a408f1adb202749eed8a53 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Nov 2021 15:50:14 +0900 Subject: [PATCH 1798/3664] [qw] Create axes for viewdelta First step in removing IN_Move. Once nq is updated, IN_Move can be removed entirely. --- qw/source/cl_input.c | 71 +++++++++++++++++++++++++++++++++++++------- qw/source/cl_main.c | 2 -- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index d426609e5..0d3893bfd 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -66,6 +66,38 @@ cvar_t *cl_nodelta; cvar_t *cl_maxnetfps; cvar_t *cl_spamimpulse; +in_axis_t viewdelta_position_forward = { + .mode = ina_accumulate, + .name = "move.forward", + .description = "Move forward (positive) or backward (negative)", +}; +in_axis_t viewdelta_position_left = { + .mode = ina_accumulate, + .name = "move.left", + .description = "Move left (positive) or right (negative)", +}; +in_axis_t viewdelta_position_up = { + .mode = ina_accumulate, + .name = "move.up", + .description = "Move up (positive) or down (negative)", +}; + +in_axis_t viewdelta_angles_pitch = { + .mode = ina_accumulate, + .name = "move.pitch", + .description = "Pitch axis", +}; +in_axis_t viewdelta_angles_yaw = { + .mode = ina_accumulate, + .name = "move.yaw", + .description = "Yaw axis", +}; +in_axis_t viewdelta_angles_roll = { + .mode = ina_accumulate, + .name = "move.roll", + .description = "Roll axis", +}; + in_button_t in_left = { .name = "left", .description = "When active the player is turning left" @@ -140,6 +172,16 @@ in_button_t in_mlook = { "+lookdown" }; +static in_axis_t *cl_in_axes[] = { + &viewdelta_position_forward, + &viewdelta_position_left, + &viewdelta_position_up, + &viewdelta_angles_pitch, + &viewdelta_angles_yaw, + &viewdelta_angles_roll, + 0, +}; + static in_button_t *cl_in_buttons[] = { &in_left, &in_right, @@ -288,11 +330,6 @@ CL_BaseMove (usercmd_t *cmd) if (freelook) V_StopPitchDrift (); - viewdelta.angles[0] = viewdelta.angles[1] = viewdelta.angles[2] = 0; - viewdelta.position[0] = viewdelta.position[1] = viewdelta.position[2] = 0; - - IN_Move (); - // adjust for chase camera angles /*FIXME:chase figure out just what this does and get it working if (cl.chase @@ -313,12 +350,19 @@ CL_BaseMove (usercmd_t *cmd) } */ - cmd->forwardmove += viewdelta.position[2] * m_forward->value; - cmd->sidemove += viewdelta.position[0] * m_side->value; - cmd->upmove += viewdelta.position[1]; - cl.viewstate.angles[PITCH] += viewdelta.angles[PITCH] * m_pitch->value; - cl.viewstate.angles[YAW] += viewdelta.angles[YAW] * m_yaw->value; - cl.viewstate.angles[ROLL] += viewdelta.angles[ROLL]; + cmd->forwardmove += viewdelta_position_forward.value * m_forward->value; + cmd->sidemove += viewdelta_position_left.value * m_side->value; + cmd->upmove += viewdelta_position_up.value; + cl.viewstate.angles[PITCH] += viewdelta_angles_pitch.value * m_pitch->value; + cl.viewstate.angles[YAW] += viewdelta_angles_yaw.value * m_yaw->value; + cl.viewstate.angles[ROLL] += viewdelta_angles_roll.value; + + viewdelta_angles_pitch.value = 0; + viewdelta_angles_yaw.value = 0; + viewdelta_angles_roll.value = 0; + viewdelta_position_forward.value = 0; + viewdelta_position_left.value = 0; + viewdelta_position_up.value = 0; if (freelook && !(in_strafe.state & inb_down)) { cl.viewstate.angles[PITCH] @@ -522,11 +566,16 @@ CL_SendCmd (void) void CL_Input_Init (void) { + for (int i = 0; cl_in_axes[i]; i++) { + IN_RegisterAxis (cl_in_axes[i]); + } for (int i = 0; cl_in_buttons[i]; i++) { IN_RegisterButton (cl_in_buttons[i]); } cl_game_context = IMT_CreateContext ("key_game"); + IMT_SetContextCbuf (cl_game_context, cl_cbuf); cl_demo_context = IMT_CreateContext ("key_demo"); + IMT_SetContextCbuf (cl_demo_context, cl_cbuf); Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 82e2df4d7..e43c26fcf 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1146,7 +1146,6 @@ CL_SetState (cactive_t state) if (old_state == ca_active) { // leaving active state IN_ClearStates (); - //Key_SetKeyDest (key_console); // Auto demo recorder stops here if (cl_autorecord->int_val && cls.demorecording) @@ -1155,7 +1154,6 @@ CL_SetState (cactive_t state) // entering active state VID_SetCaption (cls.servername->str); IN_ClearStates (); - //Key_SetKeyDest (key_game); // Auto demo recorder starts here if (cl_autorecord->int_val && !cls.demoplayback From f77b4199c46311ae1d2af7b66afcfb8651b718bc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Nov 2021 15:43:07 +0900 Subject: [PATCH 1799/3664] Fix some optimization warnings --- include/QF/input/event.h | 2 +- include/QF/input/imt.h | 2 +- libs/console/client.c | 2 +- libs/input/in_imt.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/QF/input/event.h b/include/QF/input/event.h index 2339dd732..399d25f9f 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -117,6 +117,6 @@ int IE_Send_Event (const IE_event_t *event); int IE_Add_Handler (ie_handler_t *event_handler, void *data); void IE_Remove_Handler (int handle); void IE_Set_Focus (int handle); -int IE_Get_Focus (void); +int IE_Get_Focus (void) __attribute__ ((pure)); #endif//__QF_in_event_h diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index a6e38334e..fc5192d9a 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -59,7 +59,7 @@ typedef struct in_context_s { int IMT_GetAxisBlock (int num_axes); int IMT_GetButtonBlock (int num_buttons); int IMT_CreateContext (const char *name); -int IMT_GetContext (void); +int IMT_GetContext (void) __attribute__ ((pure)); void IMT_SetContext (int ctx); void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf); imt_t *IMT_FindIMT (const char *name); diff --git a/libs/console/client.c b/libs/console/client.c index 1e907be83..24b6acf78 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -648,7 +648,7 @@ draw_notify (view_t *view) static void setup_console (void) { - float lines; + float lines = 0; switch (con_state) { case con_inactive: diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 2589d2f28..b47ae1b8a 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -185,7 +185,7 @@ IMT_CreateContext (const char *name) return ctx - in_contexts.a; } -static in_context_t * +static in_context_t * __attribute__ ((pure)) imt_find_context (const char *name) { for (size_t i = 0; i < in_contexts.size; i++) { From 5557bf0b09f2e98d3a56727b0158a81af0ae3afa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 Nov 2021 15:51:47 +0900 Subject: [PATCH 1800/3664] [input] Implement axis binding Each axis binding has its own recipe (meaning the same input axis can be interpreted differently for each binding) Recipes are specified with field=value pairs after the axis name. Valid fields are minzone, maxzone, deadzone, curve and scale, with deadzone doubling as a balanced/unbalanced flag. The default recipe has no zones, is balanced, and curve and scale are 1. --- include/QF/input/binding.h | 30 +++++++--- include/QF/input/imt.h | 3 +- libs/input/in_axis.c | 6 ++ libs/input/in_binding.c | 68 ++++++++++++++++++---- libs/input/in_imt.c | 116 ++++++++++++++++++++++++++++++++++--- 5 files changed, 198 insertions(+), 25 deletions(-) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 1b8fadcc0..aeb06468a 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -33,18 +33,36 @@ /*** Recipe for converting an axis to a floating point value. - Recipes apply only to absolute axes. + Absolute axes are converted to the 0..1 range for unbalanced axes, and + the -1..1 range for balanced axes, and then scaled. + + Relative axes are simply converted to floating point and scaled as they + have no fixed limits. + + Relative axes should have \a minzone and \a maxzone set to 0, or weird + things will happen. + + \a min and \a max normally come from the system. \a min and \a max being + equal indicates the axis is relative. \a deadzone applies only to balanced axes, thus it doubles as a flag - for balanced (>= 0) or unbalanced (< 0). + for balanced (>= 0) or unbalanced (< 0). However, relative axes are always + balanced and so \a deadzone < 0 is the same as 0 for relative axes. - \a curve is applied after the input has been converted + \a curve is applied after the input has been converted to a float, and the + 0..1 or -1..1 ranges for absolute axes. + + \a scale is applied after \a curve for absolute axes, but before \a curve + for relative axes. */ typedef struct in_recipe_s { + int min; ///< Axis minimum value (from system) + int max; ///< Axis maximum value (from system) int minzone; ///< Size of deadzone near axis minimum int maxzone; ///< Size of deadzone near axis maximum int deadzone; ///< Size of deadzone near axis center (balanced) float curve; ///< Power factor for absolute axes + float scale; ///< Final scale factor } in_recipe_t; typedef enum { @@ -97,10 +115,7 @@ typedef struct in_button_s { } in_button_t; typedef struct in_axisbinding_s { - union { - in_recipe_t *recipe;///< for absolute axes - float scale; ///< for relative axes - }; + in_recipe_t *recipe; in_axis_t *axis; } in_axisbinding_t; @@ -217,6 +232,7 @@ void IN_ButtonAction (in_button_t *buttin, int id, int pressed); int IN_RegisterButton (in_button_t *button); int IN_RegisterAxis (in_axis_t *axis); in_button_t *IN_FindButton (const char *name); +in_axis_t *IN_FindAxis (const char *name); void IN_Binding_Init (void); diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index fc5192d9a..6d92576a1 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -65,7 +65,8 @@ void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf); imt_t *IMT_FindIMT (const char *name); int IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name); -void IMT_BindAxis (imt_t *imt, int axis, const char *binding); +void IMT_BindAxis (imt_t *imt, int axis_num, in_axis_t *axis, + const in_recipe_t *recipe); void IMT_BindButton (imt_t *imt, int button, const char *binding); qboolean IMT_ProcessAxis (int axis, int value); qboolean IMT_ProcessButton (int button, int state); diff --git a/libs/input/in_axis.c b/libs/input/in_axis.c index f945e2590..85489b8b7 100644 --- a/libs/input/in_axis.c +++ b/libs/input/in_axis.c @@ -69,6 +69,12 @@ IN_RegisterAxis (in_axis_t *axis) return 1; } +VISIBLE in_axis_t * +IN_FindAxis (const char *name) +{ + return Hash_Find (axis_tab, name); +} + static void __attribute__((constructor)) in_axis_init (void) { diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index bd7b1206a..6705de222 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -38,10 +38,13 @@ # include #endif +#include "QF/cexpr.h" #include "QF/cmd.h" +#include "QF/cmem.h" #include "QF/hash.h" #include "QF/heapsort.h" #include "QF/input.h" +#include "QF/plist.h" #include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" @@ -67,14 +70,14 @@ devid_cmp (const void *a, const void *b) return *(const int *)a - *(const int *)b; } -static int * +static int * __attribute__ ((pure)) in_find_devid (int devid) { return bsearch (&devid, known_devices.a, known_devices.size, sizeof (int), devid_cmp); } -static in_devbindings_t * +static in_devbindings_t * __attribute__ ((pure)) in_binding_find_connection (const char *devname, const char *id) { in_devbindings_t *db; @@ -254,7 +257,7 @@ in_keyhelp_event_handler (const IE_event_t *ie_event, void *unused) return 1; } -static in_devbindings_t * +static in_devbindings_t * __attribute__ ((pure)) in_binding_find_device (const char *name) { in_devbindings_t *db; @@ -264,13 +267,14 @@ in_binding_find_device (const char *name) break; } } - return 0; + return db; } static void in_bind_f (void) { - if (Cmd_Argc () < 6) { + int argc = Cmd_Argc (); + if (argc < 6) { Sys_Printf ("in_bind imt device type number binding...\n"); Sys_Printf (" imt: the name of the input mapping table in which the" " intput will be bound\n"); @@ -294,8 +298,6 @@ in_bind_f (void) const char *dev_name = Cmd_Argv (2); const char *type = Cmd_Argv (3); const char *number = Cmd_Argv (4); - // the rest of the command line is the binding - const char *binding = Cmd_Args (5); imt_t *imt = IMT_FindIMT (imt_name); in_devbindings_t *dev = in_binding_find_device (dev_name); @@ -321,8 +323,54 @@ in_bind_f (void) if (dev->axis_imt_id == -1) { dev->axis_imt_id = IMT_GetAxisBlock (dev->num_axes); } - IMT_BindAxis (imt, dev->axis_imt_id + num, binding); + const char *axis_name = Cmd_Argv (5); + in_axis_t *axis = IN_FindAxis (axis_name); + if (!axis) { + Sys_Printf ("unknown axis: %s\n", axis_name); + return; + } + in_axisinfo_t *axisinfo = &dev->axis_info[num]; + in_recipe_t recipe = { + .min = axisinfo->min, + .max = axisinfo->max, + .curve = 1, + .scale = 1, + }; + exprsym_t var_syms[] = { + {"minzone", &cexpr_int, &recipe.minzone}, + {"maxzone", &cexpr_int, &recipe.maxzone}, + {"deadzone", &cexpr_int, &recipe.deadzone}, + {"curve", &cexpr_float, &recipe.curve}, + {"scale", &cexpr_float, &recipe.scale}, + {} + }; + exprtab_t vars_tab = { var_syms, 0 }; + exprctx_t exprctx = { + .external_variables = &vars_tab, + .memsuper = new_memsuper (), + .messages = PL_NewArray (), + }; + cexpr_init_symtab (&vars_tab, &exprctx); + + int i; + for (i = 6; i < argc; i++) { + const char *arg = Cmd_Argv (i); + if (!cexpr_eval_string (arg, &exprctx)) { + PL_Message (exprctx.messages, 0, "error parsing recipe: %s", + arg); + break; + } + } + if (i == argc) { + IMT_BindAxis (imt, dev->axis_imt_id + num, axis, &recipe); + } + Hash_DelTable (vars_tab.tab); + PL_Free (exprctx.messages); + delete_memsuper (exprctx.memsuper); } else { + // the rest of the command line is the binding + const char *binding = Cmd_Args (5); + if (*end || num < 0 || num >= dev->num_buttons) { Sys_Printf ("invalid button number: %s\n", number); return; @@ -376,7 +424,7 @@ in_unbind_f (void) Sys_Printf ("invalid axis number: %s\n", number); return; } - IMT_BindAxis (imt, dev->axis_imt_id + num, 0); + IMT_BindAxis (imt, dev->axis_imt_id + num, 0, 0); } else { if (*end || num < 0 || num >= dev->num_buttons) { Sys_Printf ("invalid button number: %s\n", number); @@ -402,7 +450,7 @@ in_clear_f (void) continue; } for (size_t ind = 0; ind < imt->axis_bindings.size; ind++) { - IMT_BindAxis (imt, ind, 0); + IMT_BindAxis (imt, ind, 0, 0); } for (size_t ind = 0; ind < imt->button_bindings.size; ind++) { IMT_BindButton (imt, ind, 0); diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index b47ae1b8a..ea7a7ebbf 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -42,6 +42,8 @@ #include "QF/cmd.h" #include "QF/cmem.h" #include "QF/hash.h" +#include "QF/input.h" +#include "QF/mathlib.h" #include "QF/sys.h" #include "QF/va.h" @@ -73,6 +75,40 @@ static in_contextset_t in_contexts = DARRAY_STATIC_INIT (8); static size_t imt_current_context; static memsuper_t *binding_mem; +static hashtab_t *recipe_tab; + +static in_recipe_t * +alloc_recipe (void) +{ + return cmemalloc (binding_mem, sizeof (in_recipe_t)); +} + +static void +free_recipe (in_recipe_t *recipe) +{ + if (!recipe) { + return; + } + cmemfree (binding_mem, recipe); +} + +static void +recipe_free (void *recipe, void *data) +{ + free_recipe (recipe); +} + +static uintptr_t +recipe_get_hash (const void *recipe, void *data) +{ + return Hash_Buffer (recipe, sizeof (in_recipe_t)); +} + +static int +recipe_compare (const void *a, const void *b, void *data) +{ + return !memcmp (a, b, sizeof (in_recipe_t)); +} static in_axisbinding_t * alloc_axis_binding (void) @@ -160,8 +196,9 @@ imt_get_button_block (int count) int IMT_GetAxisBlock (int num_axes) { + int base = imt_get_axis_block (num_axes); imt_block_t *block = imt_get_block (&axis_blocks); - block->base = imt_get_axis_block (num_axes); + block->base = base; block->count = num_axes; return block - axis_blocks.a; } @@ -169,8 +206,9 @@ IMT_GetAxisBlock (int num_axes) int IMT_GetButtonBlock (int num_buttons) { + int base = imt_get_button_block (num_buttons); imt_block_t *block = imt_get_block (&button_blocks); - block->base = imt_get_button_block (num_buttons); + block->base = base; block->count = num_buttons; return block - button_blocks.a; } @@ -299,18 +337,22 @@ IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name) } void -IMT_BindAxis (imt_t *imt, int axis, const char *binding) +IMT_BindAxis (imt_t *imt, int axis_num, in_axis_t *axis, + const in_recipe_t *recipe) { - if ((size_t) axis >= imt->axis_bindings.size) + if ((size_t) axis_num >= imt->axis_bindings.size) return; - in_axisbinding_t **bind = &imt->axis_bindings.a[axis]; + in_axisbinding_t **bind = &imt->axis_bindings.a[axis_num]; free_axis_binding ((*bind)); (*bind) = 0; - if (binding) { + if (axis && recipe) { in_axisbinding_t *a = alloc_axis_binding (); (*bind) = a; - *a = (in_axisbinding_t) {}; + if (!(a->recipe = Hash_FindElement (recipe_tab, recipe))) { + *(a->recipe = alloc_recipe ()) = *recipe; + Hash_AddElement (recipe_tab, a->recipe); + } } } @@ -345,6 +387,64 @@ IMT_ProcessAxis (int axis, int value) while (imt) { in_axisbinding_t *a = imt->axis_bindings.a[axis]; if (a) { + in_recipe_t *recipe = a->recipe; + int relative = recipe->min == recipe->max; + int deadzone = recipe->deadzone; + int minval = recipe->min + recipe->minzone; + int maxval = recipe->max - recipe->maxzone; + int input = bound (minval, value, maxval); + float output; + if (relative) { + if (deadzone > 0) { + if (input > deadzone) { + input -= deadzone; + } else if (input < -deadzone) { + input += deadzone; + } else { + input = 0; + } + } + output = input * recipe->scale; + if (recipe->curve != 1) { + output = powf (output, recipe->curve); + } + } else { + int range = maxval - minval; + int zero = minval; + if (recipe->deadzone >= 0) { + // balanced axis: -1..1 + int center = (recipe->min + recipe->max + 1) / 2; + minval += deadzone - center; + maxval -= deadzone + center; + input -= center; + if (input < -deadzone) { + input += deadzone; + } else if (input > deadzone) { + input -= deadzone; + } else { + input = 0; + } + if (center - minval > maxval - center) { + range = center - minval; + } else { + range = maxval - center; + } + zero = 0; + } + output = (float)(input - zero) / (range); + if (recipe->curve != 1) { + output = powf (output, recipe->curve); + } + output *= recipe->scale; + } + switch (a->axis->mode) { + case ina_set: + a->axis->value = output; + break; + case ina_accumulate: + a->axis->value += output; + break; + } return true; } imt = imt->chain; @@ -529,6 +629,8 @@ void IMT_Init (void) { binding_mem = new_memsuper (); + recipe_tab = Hash_NewTable (61, 0, recipe_free, 0, 0); + Hash_SetHashCompare (recipe_tab, recipe_get_hash, recipe_compare); for (imtcmd_t *cmd = imt_commands; cmd->name; cmd++) { Cmd_AddCommand (cmd->name, cmd->func, cmd->desc); } From 6e85377d7a5733dccd811429b58866090393b8a6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Nov 2021 00:19:58 +0900 Subject: [PATCH 1801/3664] [cexpr] Support variable assignment I might have to add code to block it when necessary, but it's needed for axis recipe parsing. --- libs/util/cexpr-lex.l | 9 +++++++++ libs/util/cexpr-parse.y | 16 +++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index 3fafef8e6..026f7eea2 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -166,15 +166,23 @@ STRING \"(\\.|[^"\\])*\" } [+\-*/&|^%]= { + yylval->op = yytext[0]; + return ASX; } "%%=" { + yylval->op = MOD; + return ASX; } "<<=" { + yylval->op = SHL; + return ASX; } ">>=" { + yylval->op = SHR; + return ASX; } [!(){}.*/&|^~+\-=\[\];,#%?:] { @@ -182,6 +190,7 @@ STRING \"(\\.|[^"\\])*\" } "%%" { + return MOD; } "<<" return SHL; diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index fca9171af..46eaae7fe 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -51,8 +51,8 @@ #include "QF/cexpr.h" -static void assign_expr (exprval_t *dst, const exprval_t *src, - exprctx_t *context); +static exprval_t *assign_expr (exprval_t *dst, const exprval_t *src, + exprctx_t *context); static exprval_t *binary_expr (int op, const exprval_t *a, const exprval_t *b, exprctx_t *context); static exprval_t *field_expr (const exprval_t *a, const exprval_t *b, @@ -138,6 +138,7 @@ uexpr expr : uexpr + | expr '=' expr { $$ = assign_expr ($1, $3, context); } | expr SHL expr { $$ = binary_expr (SHL, $1, $3, context); } | expr SHR expr { $$ = binary_expr (SHR, $1, $3, context); } | expr '+' expr { $$ = binary_expr ('+', $1, $3, context); } @@ -184,16 +185,16 @@ arg_expr %% -static void +static exprval_t * assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context) { binop_t *binop; - if (!src) { - return; + if (!dst || !src) { + return 0; } if (dst->type == &cexpr_exprval) { *(exprval_t **) dst->value = (exprval_t *) src; - return; + return dst; } binop = cexpr_find_cast (dst->type, src->type); if (binop && binop->op) { @@ -203,10 +204,11 @@ assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context) cexpr_error (context, "type mismatch in expression result: %s = %s", dst->type->name, src->type->name); - return; + return dst; } memcpy (dst->value, src->value, dst->type->size); } + return dst; } static exprval_t * From adaa3c5485683efa9d8ec1d926eab51dafa2626d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Nov 2021 00:24:04 +0900 Subject: [PATCH 1802/3664] [input] Get bindings actually working The mouse bound to movement axes works (though signs are all over the place, so movement direction is a little off), and binding F10 (key 68) to quit works :) --- include/QF/input/binding.h | 1 + libs/input/in_binding.c | 23 ++++++++++++++++------- libs/input/in_imt.c | 5 ++++- qw/include/cl_input.h | 1 + qw/source/cl_input.c | 7 +++++++ qw/source/cl_main.c | 3 +++ 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index aeb06468a..ba9f0ffb2 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -234,6 +234,7 @@ int IN_RegisterAxis (in_axis_t *axis); in_button_t *IN_FindButton (const char *name); in_axis_t *IN_FindAxis (const char *name); +void IN_Binding_Activate (void); void IN_Binding_Init (void); #endif diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 6705de222..ebd30dcf7 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -160,7 +160,7 @@ in_binding_axis (const IE_event_t *ie_event) if (db && axis < db->num_axes) { db->axis_info[axis].value = value; - if (db->axis_imt_id) { + if (db->axis_imt_id >= 0) { IMT_ProcessAxis (db->axis_imt_id + axis, value); } } @@ -175,7 +175,7 @@ in_binding_button (const IE_event_t *ie_event) if (db && button < db->num_buttons) { db->button_info[button].state = state; - if (db->button_imt_id) { + if (db->button_imt_id >= 0) { IMT_ProcessButton (db->button_imt_id + button, state); } } @@ -346,7 +346,7 @@ in_bind_f (void) }; exprtab_t vars_tab = { var_syms, 0 }; exprctx_t exprctx = { - .external_variables = &vars_tab, + .symtab = &vars_tab, .memsuper = new_memsuper (), .messages = PL_NewArray (), }; @@ -355,9 +355,12 @@ in_bind_f (void) int i; for (i = 6; i < argc; i++) { const char *arg = Cmd_Argv (i); - if (!cexpr_eval_string (arg, &exprctx)) { - PL_Message (exprctx.messages, 0, "error parsing recipe: %s", - arg); + if (cexpr_eval_string (arg, &exprctx)) { + plitem_t *messages = exprctx.messages; + for (int j = 0; j < PL_A_NumObjects (messages); j++) { + Sys_Printf ("%s\n", + PL_String (PL_ObjectAtIndex (messages, j))); + } break; } } @@ -376,7 +379,7 @@ in_bind_f (void) return; } if (dev->button_imt_id == -1) { - dev->button_imt_id = IMT_GetAxisBlock (dev->num_buttons); + dev->button_imt_id = IMT_GetButtonBlock (dev->num_buttons); } IMT_BindButton (imt, dev->button_imt_id + num, binding); } @@ -686,6 +689,12 @@ static bindcmd_t in_binding_commands[] = { #endif }; +void +IN_Binding_Activate (void) +{ + IE_Set_Focus (in_binding_handler); +} + void IN_Binding_Init (void) { diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index ea7a7ebbf..96121f20b 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -353,6 +353,7 @@ IMT_BindAxis (imt_t *imt, int axis_num, in_axis_t *axis, *(a->recipe = alloc_recipe ()) = *recipe; Hash_AddElement (recipe_tab, a->recipe); } + a->axis = axis; } } @@ -392,9 +393,9 @@ IMT_ProcessAxis (int axis, int value) int deadzone = recipe->deadzone; int minval = recipe->min + recipe->minzone; int maxval = recipe->max - recipe->maxzone; - int input = bound (minval, value, maxval); float output; if (relative) { + int input = value; if (deadzone > 0) { if (input > deadzone) { input -= deadzone; @@ -409,6 +410,7 @@ IMT_ProcessAxis (int axis, int value) output = powf (output, recipe->curve); } } else { + int input = bound (minval, value, maxval); int range = maxval - minval; int zero = minval; if (recipe->deadzone >= 0) { @@ -623,6 +625,7 @@ static imtcmd_t imt_commands[] = { { "imt_drop_all", imt_drop_all_f, "delete all imt tables\n" }, + {}, }; void diff --git a/qw/include/cl_input.h b/qw/include/cl_input.h index 4493f9806..a1c32c4f1 100644 --- a/qw/include/cl_input.h +++ b/qw/include/cl_input.h @@ -32,6 +32,7 @@ #include "qw/protocol.h" +void CL_Input_Activate (void); void CL_Input_Init (void); void CL_Input_Init_Cvars (void); void CL_ClearStates (void); diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 0d3893bfd..df8f709ba 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -580,6 +580,13 @@ CL_Input_Init (void) "Call a game function or QuakeC function."); } +void +CL_Input_Activate (void) +{ + IMT_SetContext (cl_game_context); + IN_Binding_Activate (); +} + void CL_Input_Init_Cvars (void) { diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index e43c26fcf..b3d8c2f1a 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1162,6 +1162,9 @@ CL_SetState (cactive_t state) } } Con_SetState (state == ca_active ? con_inactive : con_fullscreen); + if (state != old_state && state == ca_active) { + CL_Input_Activate (); + } } void From 08083b863006133ec93d7fafe278652e0dc657e3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 12 Nov 2021 08:09:41 +0900 Subject: [PATCH 1803/3664] [input] Use double for recipe float values Recipes themselves still use float, but using double in the cexpr values allows bare floating point numbers (which parse as double) to be used, making the bind command line a little more user-friendly. --- libs/input/in_binding.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index ebd30dcf7..1f28810ed 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -336,12 +336,14 @@ in_bind_f (void) .curve = 1, .scale = 1, }; + double curve = recipe.curve; + double scale = recipe.scale; exprsym_t var_syms[] = { {"minzone", &cexpr_int, &recipe.minzone}, {"maxzone", &cexpr_int, &recipe.maxzone}, {"deadzone", &cexpr_int, &recipe.deadzone}, - {"curve", &cexpr_float, &recipe.curve}, - {"scale", &cexpr_float, &recipe.scale}, + {"curve", &cexpr_double, &curve}, + {"scale", &cexpr_double, &scale}, {} }; exprtab_t vars_tab = { var_syms, 0 }; @@ -365,6 +367,8 @@ in_bind_f (void) } } if (i == argc) { + recipe.curve = curve; + recipe.scale = scale; IMT_BindAxis (imt, dev->axis_imt_id + num, axis, &recipe); } Hash_DelTable (vars_tab.tab); From 08bf3a6b8e698cf02ab19ae0dcb54cf02deb93a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 Nov 2021 10:07:40 +0900 Subject: [PATCH 1804/3664] [gamecode] Fix incorrect return in PR_RESRESET I think it's a holdover from before switching the resmap macros to be usable in larger functions. I'm surprised it took this long to run into. --- include/QF/progs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index df88b16b7..47f7a80a2 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1614,7 +1614,7 @@ void *PR_Resources_Find (progs_t *pr, const char *name); do { \ unsigned i, j; \ if (!(map)._size) { \ - return; \ + break; \ } \ for (i = 0; i < (map)._size; i++) { \ (map)._free = (map)._map[i]; \ From 6a9e5f497030c7dd0882396817e640c4ef210e5f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 Nov 2021 10:10:39 +0900 Subject: [PATCH 1805/3664] [input] Fix incorrect placement of pure attribute Should be on the prototype, not definition (for public functions). --- include/QF/input/imt.h | 2 +- libs/input/in_imt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 6d92576a1..0ca4af1f7 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -62,7 +62,7 @@ int IMT_CreateContext (const char *name); int IMT_GetContext (void) __attribute__ ((pure)); void IMT_SetContext (int ctx); void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf); -imt_t *IMT_FindIMT (const char *name); +imt_t *IMT_FindIMT (const char *name) __attribute__ ((pure)); int IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name); void IMT_BindAxis (imt_t *imt, int axis_num, in_axis_t *axis, diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 96121f20b..72b8a75c2 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -269,7 +269,7 @@ imt_find_imt (in_context_t *ctx, const char *name) return 0; } -imt_t * __attribute__ ((pure)) +imt_t * IMT_FindIMT (const char *name) { for (size_t i = 0; i < in_contexts.size; i++) { From 7c9f3a3b0989b309c8e7773c3314eefbe2579d08 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 Nov 2021 10:12:14 +0900 Subject: [PATCH 1806/3664] [util] Expose the quakerc check function qargs probably needs to go away. It certainly needs to be rethought. For now, this is good enough to get qw working with plist-based quakeforge.cfg --- include/QF/qargs.h | 1 + libs/util/qargs.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/QF/qargs.h b/include/QF/qargs.h index 89ce6902c..947bea592 100644 --- a/include/QF/qargs.h +++ b/include/QF/qargs.h @@ -51,6 +51,7 @@ void COM_InitArgv (int argc, const char **argv); struct cbuf_s; void COM_ParseConfig (struct cbuf_s *cbuf); void COM_ExecConfig (struct cbuf_s *cbuf, int skip_quakerc); +int COM_Check_quakerc (const char *cmd, struct cbuf_s *cbuf); ///@} diff --git a/libs/util/qargs.c b/libs/util/qargs.c index b1d6510db..45bd04636 100644 --- a/libs/util/qargs.c +++ b/libs/util/qargs.c @@ -180,8 +180,8 @@ COM_ParseConfig (cbuf_t *cbuf) Cbuf_Execute_Sets (cbuf); } -static int -check_quakerc (const char *cmd, cbuf_t *cbuf) +int +COM_Check_quakerc (const char *cmd, cbuf_t *cbuf) { const char *l, *p; int ret = 0; @@ -214,7 +214,7 @@ COM_ExecConfig (cbuf_t *cbuf, int skip_quakerc) if (Cmd_Exec_File (cbuf, "quakeforge.cfg", 1)) { Cmd_Exec_File (cbuf, fs_usercfg->string, 0); Cmd_StuffCmds (cbuf); - check_quakerc ("startdemos", cbuf); + COM_Check_quakerc ("startdemos", cbuf); } else { if (!skip_quakerc) { Cbuf_InsertText (cbuf, "exec quake.rc\n"); @@ -223,7 +223,7 @@ COM_ExecConfig (cbuf_t *cbuf, int skip_quakerc) // Reparse the command line for + commands. // (sets still done, but it doesn't matter) // (Note, no non-base commands exist yet) - if (skip_quakerc || !check_quakerc ("stuffcmds", 0)) { + if (skip_quakerc || !COM_Check_quakerc ("stuffcmds", 0)) { Cmd_StuffCmds (cbuf); } } From fede9125e10306a5be368b8ec6a0fb5521ec525d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 Nov 2021 10:17:05 +0900 Subject: [PATCH 1807/3664] [input] Save/load config to/from plist configs While the console command line is quite good for setting everything up, the devices being bound do need to be present when the commands are executed (due to needing extra data provided by the devices). Thus property lists that store the extra data (button and axis counts, device names/ids, connection names, etc) seems to be the best solution. --- include/QF/input.h | 3 + include/QF/input/binding.h | 3 + include/QF/input/imt.h | 6 + libs/input/in_binding.c | 254 ++++++++++++++++++++++++++++++++++--- libs/input/in_common.c | 22 ++++ libs/input/in_imt.c | 158 ++++++++++++++++++++++- 6 files changed, 420 insertions(+), 26 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 6618e1a0f..a49bc541b 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -143,6 +143,9 @@ int IN_RegisterDriver (in_driver_t *driver, void *data); void IN_DriverData (int handlle, void *data); void IN_Init (struct cbuf_s *cbuf); void IN_Init_Cvars (void); +struct plitem_s; +void IN_SaveConfig (struct plitem_s *config); +void IN_LoadConfig (struct plitem_s *config); int IN_AddDevice (int driver, void *device, const char *name, const char *id); void IN_RemoveDevice (int devid); diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index ba9f0ffb2..3b3bc3aa2 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -236,6 +236,9 @@ in_axis_t *IN_FindAxis (const char *name); void IN_Binding_Activate (void); void IN_Binding_Init (void); +struct plitem_s; +void IN_Binding_SaveConfig (struct plitem_s *config); +void IN_Binding_LoadConfig (struct plitem_s *config); #endif diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 0ca4af1f7..508433e73 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -71,6 +71,12 @@ void IMT_BindButton (imt_t *imt, int button, const char *binding); qboolean IMT_ProcessAxis (int axis, int value); qboolean IMT_ProcessButton (int button, int state); void IMT_Init (void); +struct plitem_s; +void IMT_SaveConfig (struct plitem_s *config); +void IMT_SaveAxisConfig (struct plitem_s *axes, int axis_ind, int dev_axis); +void IMT_SaveButtonConfig (struct plitem_s *buttons, int button_ind, + int dev_button); +void IMT_LoadConfig (struct plitem_s *config); #endif diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 1f28810ed..bb846605b 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -47,6 +47,7 @@ #include "QF/plist.h" #include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" +#include "QF/va.h" #include "QF/input/imt.h" @@ -95,23 +96,34 @@ in_binding_find_connection (const char *devname, const char *id) return 0; } +static void +alloc_input_info (in_devbindings_t *db) +{ + db->axis_info = malloc (db->num_axes * sizeof (in_axisinfo_t) + + db->num_buttons * sizeof (in_buttoninfo_t)); + db->button_info = (in_buttoninfo_t *) &db->axis_info[db->num_axes]; +} + static void in_binding_add_device (const IE_event_t *ie_event) { size_t devid = ie_event->device.devid; - - if (in_find_devid (devid)) { - // the device is already known. this is likely the result of a - // broadcast of connected devices - return; - } - DARRAY_APPEND (&known_devices, devid); - // keep the known devices sorted by id - heapsort (known_devices.a, known_devices.size, sizeof (int), devid_cmp); - const char *devname = IN_GetDeviceName (devid); const char *id = IN_GetDeviceId (devid); - in_devbindings_t *db = in_binding_find_connection (devname, id); + + if (!in_find_devid (devid)) { + DARRAY_APPEND (&known_devices, devid); + // keep the known devices sorted by id + heapsort (known_devices.a, known_devices.size, sizeof (int), devid_cmp); + Sys_Printf ("Added device %s %s\n", devname, id); + } + + in_devbindings_t *db = IN_GetDeviceEventData (devid); + if (db) { + return; + } + + db = in_binding_find_connection (devname, id); if (db) { if (db->match_id) { @@ -121,8 +133,11 @@ in_binding_add_device (const IE_event_t *ie_event) } db->devid = devid; IN_SetDeviceEventData (devid, db); - } else { - Sys_Printf ("Added device %s %s\n", devname, id); + if (!db->axis_info) { + alloc_input_info (db); + } + IN_AxisInfo (devid, db->axis_info, &db->num_axes); + IN_ButtonInfo (devid, db->button_info, &db->num_buttons); } } @@ -270,6 +285,18 @@ in_binding_find_device (const char *name) return db; } +static void +clear_connection (in_devbindings_t *db) +{ + if (db->devid >= 0) { + IN_SetDeviceEventData (db->devid, 0); + } + free (db->name); + free (db->devname); + free (db->id); + free (db->axis_info); +} + static void in_bind_f (void) { @@ -506,11 +533,9 @@ in_connect_f (void) const char *device_id = Cmd_Argv (2); int devid = -1; - for (in_devbindings_t *db = devbindings_list; db; db = db->next) { - if (strcmp (bindname, db->name) == 0) { - Sys_Printf ("%s already exists\n", bindname); - return; - } + if (in_binding_find_device (bindname)) { + Sys_Printf ("%s already exists\n", bindname); + return; } if (device_id[0] == '#') { @@ -560,9 +585,7 @@ in_connect_f (void) IN_AxisInfo (devid, 0, &db->num_axes); IN_ButtonInfo (devid, 0, &db->num_buttons); - db->axis_info = malloc (db->num_axes * sizeof (in_axisinfo_t) - + db->num_buttons * sizeof (in_buttoninfo_t)); - db->button_info = (in_buttoninfo_t *) &db->axis_info[db->num_axes]; + alloc_input_info (db); IN_AxisInfo (devid, db->axis_info, &db->num_axes); IN_ButtonInfo (devid, db->button_info, &db->num_buttons); @@ -709,3 +732,192 @@ IN_Binding_Init (void) Cmd_AddCommand (cmd->name, cmd->func, cmd->desc); } } + +void +IN_Binding_SaveConfig (plitem_t *config) +{ + plitem_t *devices = PL_NewArray (); + PL_D_AddObject (config, "devices", devices); + for (in_devbindings_t *db = devbindings_list; db; db = db->next) { + plitem_t *db_cfg = PL_NewDictionary (0); //FIXME hashlinks + PL_A_AddObject (devices, db_cfg); + PL_D_AddObject (db_cfg, "name", PL_NewString (db->name)); + PL_D_AddObject (db_cfg, "devname", PL_NewString (db->devname)); + if (db->match_id) { + PL_D_AddObject (db_cfg, "id", PL_NewString (db->id)); + } + PL_D_AddObject (db_cfg, "num_axes", + PL_NewString (va (0, "%d", db->num_axes))); + PL_D_AddObject (db_cfg, "num_buttons", + PL_NewString (va (0, "%d", db->num_buttons))); + if (db->axis_imt_id >= 0) { + plitem_t *axes = PL_NewArray (); + PL_D_AddObject (db_cfg, "axes", axes); + for (int i = 0; i < db->num_axes; i++) { + IMT_SaveAxisConfig (axes, db->axis_imt_id + i, i); + } + } + if (db->button_imt_id >= 0) { + plitem_t *buttons = PL_NewArray (); + PL_D_AddObject (db_cfg, "buttons", buttons); + for (int i = 0; i < db->num_buttons; i++) { + IMT_SaveButtonConfig (buttons, db->button_imt_id + i, i); + } + } + } +} + +static int +parse_num (plitem_t *item) +{ + char *end; + const char *str = PL_String (item); + if (!str) { + return -1; + } + int num = strtol (str, &end, 0); + if (*end || num < 0) { + return -1; + } + return num; +} + +static int +parse_int (plitem_t *item, int dflt) +{ + char *end; + const char *str = PL_String (item); + if (!str) { + return dflt; + } + int num = strtol (str, &end, 0); + if (*end) { + return dflt; + } + return num; +} + +static float +parse_float (plitem_t *item, float dflt) +{ + char *end; + const char *str = PL_String (item); + if (!str) { + return dflt; + } + float num = strtof (str, &end); + if (*end) { + return dflt; + } + return num; +} + +void +IN_Binding_LoadConfig (plitem_t *config) +{ + for (in_devbindings_t *db = devbindings_list; db; db = db->next) { + clear_connection (db); + } + PR_RESRESET (devbindings); + devbindings_list = 0; + + plitem_t *devices = PL_ObjectForKey (config, "devices"); + if (PL_Type (devices) != QFArray) { + Sys_Printf ("IN_Binding_LoadConfig: devices not an array\n"); + return; + } + for (int i = 0, count = PL_A_NumObjects (devices); i < count; i++) { + plitem_t *db_cfg = PL_ObjectAtIndex (devices, i); + const char *bindname = PL_String (PL_ObjectForKey (db_cfg, "name")); + const char *devname = PL_String (PL_ObjectForKey (db_cfg, "devname")); + const char *id = PL_String (PL_ObjectForKey (db_cfg, "id")); + int num_axes = parse_num (PL_ObjectForKey (db_cfg, + "num_axes")); + int num_buttons = parse_num (PL_ObjectForKey (db_cfg, + "num_buttons")); + if (in_binding_find_device (bindname)) { + Sys_Printf ("%s already exists\n", bindname); + continue; + } + if (num_axes < 0) { + continue; + } + if (num_buttons < 0) { + continue; + } + + in_devbindings_t *db = PR_RESNEW (devbindings); + db->next = devbindings_list; + devbindings_list = db; + + db->name = strdup (bindname); + db->devname = strdup (devname); + if (id) { + db->id = strdup (id); + db->match_id = 1; + } else { + db->id = 0; + db->match_id = 0; + } + db->devid = -1; // not connected yet + + db->num_axes = num_axes; + db->num_buttons = num_buttons; + + db->axis_imt_id = -1; + db->button_imt_id = -1; + + plitem_t *axes = PL_ObjectForKey (db_cfg, "axes"); + if (PL_A_NumObjects (axes)) { + db->axis_imt_id = IMT_GetAxisBlock (db->num_axes); + } + for (int i = 0, count = PL_A_NumObjects (axes); i < count; i++) { + plitem_t *a = PL_ObjectAtIndex (axes, i); + const char *imt_name = PL_String (PL_ObjectForKey (a, "imt")); + int num = parse_num (PL_ObjectForKey (a, "num")); + const char *axis_name = PL_String (PL_ObjectForKey (a, "axis")); + in_recipe_t recipe = { + .min = parse_int (PL_ObjectForKey (a, "min"), 0), + .max = parse_int (PL_ObjectForKey (a, "max"), 0), + .minzone = parse_int (PL_ObjectForKey (a, "minzone"), 0), + .maxzone = parse_int (PL_ObjectForKey (a, "maxzone"), 0), + .deadzone = parse_int (PL_ObjectForKey (a, "deadzone"), 0), + .curve = parse_float (PL_ObjectForKey (a, "curve"), 1), + .scale = parse_float (PL_ObjectForKey (a, "scale"), 1), + }; + if (!imt_name || num < 0 || num >= db->num_axes) { + continue; + } + imt_t *imt = IMT_FindIMT (imt_name); + if (!imt) { + continue; + } + in_axis_t *axis = IN_FindAxis (axis_name); + if (!axis) { + continue; + } + IMT_BindAxis (imt, db->axis_imt_id + num, axis, &recipe); + } + plitem_t *buttons = PL_ObjectForKey (db_cfg, "buttons"); + if (PL_A_NumObjects (buttons)) { + db->button_imt_id = IMT_GetButtonBlock (db->num_buttons); + } + for (int i = 0, count = PL_A_NumObjects (buttons); i < count; i++) { + plitem_t *b = PL_ObjectAtIndex (buttons, i); + const char *imt_name = PL_String (PL_ObjectForKey (b, "imt")); + int num = parse_num (PL_ObjectForKey (b, "num")); + const char *binding = PL_String (PL_ObjectForKey (b, "binding")); + if (!imt_name || num < 0 || num >= db->num_buttons) { + continue; + } + imt_t *imt = IMT_FindIMT (imt_name); + if (!imt) { + continue; + } + IMT_BindButton (imt, db->button_imt_id + num, binding); + } + } + // force device connection events so any connected devices get hoocked up + // with their bindings + IN_SendConnectedDevices (); +} diff --git a/libs/input/in_common.c b/libs/input/in_common.c index fa85b3982..1c0ff86fb 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -55,6 +55,7 @@ #include "QF/joystick.h" #include "QF/keys.h" #include "QF/mathlib.h" +#include "QF/plist.h" #include "QF/sys.h" #include "QF/vid.h" @@ -321,6 +322,27 @@ IN_ProcessEvents (void) } } +void +IN_SaveConfig (plitem_t *config) +{ + plitem_t *input_config = PL_NewDictionary (0); //FIXME hashlinks + PL_D_AddObject (config, "input", input_config); + + IMT_SaveConfig (input_config); + IN_Binding_SaveConfig (input_config); +} + +void +IN_LoadConfig (plitem_t *config) +{ + plitem_t *input_config = PL_ObjectForKey (config, "input"); + + if (input_config) { + IMT_LoadConfig (input_config); + IN_Binding_LoadConfig (input_config); + } +} + void IN_Move (void) { diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 72b8a75c2..77b8ae4f3 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -44,6 +44,7 @@ #include "QF/hash.h" #include "QF/input.h" #include "QF/mathlib.h" +#include "QF/plist.h" #include "QF/sys.h" #include "QF/va.h" @@ -226,9 +227,11 @@ IMT_CreateContext (const char *name) static in_context_t * __attribute__ ((pure)) imt_find_context (const char *name) { - for (size_t i = 0; i < in_contexts.size; i++) { - if (strcmp (name, in_contexts.a[i].name) == 0) { - return &in_contexts.a[i]; + if (name) { + for (size_t i = 0; i < in_contexts.size; i++) { + if (strcmp (name, in_contexts.a[i].name) == 0) { + return &in_contexts.a[i]; + } } } return 0; @@ -312,6 +315,10 @@ IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name) } } imt = malloc (sizeof (imt_t)); + if (!ctx->imts) { + ctx->default_imt = imt; + ctx->active_imt = imt; + } *ctx->imt_tail = imt; ctx->imt_tail = &imt->next; @@ -330,7 +337,7 @@ IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name) num_axes * sizeof (in_axisbinding_t *)); } if (num_buttons) { - memset (imt->axis_bindings.a, 0, + memset (imt->button_bindings.a, 0, num_buttons * sizeof (in_buttonbinding_t *)); } return 1; @@ -481,7 +488,6 @@ IMT_ProcessButton (int button, int state) { imt_t *imt = in_contexts.a[imt_current_context].active_imt; - Sys_Printf ("IMT_ProcessButton: %d %d\n", button, state); while (imt) { in_buttonbinding_t *b = imt->button_bindings.a[button]; if (b) { @@ -598,6 +604,8 @@ imt_drop_all_f (void) free (imt); } ctx->active_imt = 0; + ctx->default_imt = 0; + ctx->imt_tail = &ctx->imts; } } @@ -638,3 +646,143 @@ IMT_Init (void) Cmd_AddCommand (cmd->name, cmd->func, cmd->desc); } } + +void +IMT_SaveConfig (plitem_t *config) +{ + plitem_t *ctx_list = PL_NewArray (); + PL_D_AddObject (config, "contexts", ctx_list); + for (size_t i = 0; i < in_contexts.size; i++) { + in_context_t *context = &in_contexts.a[i]; + plitem_t *ctx = PL_NewDictionary (0); //FIXME hashlinks + PL_A_AddObject (ctx_list, ctx); + PL_D_AddObject (ctx, "name", PL_NewString (context->name)); + if (context->imts) { + plitem_t *imt_list = PL_NewArray (); + PL_D_AddObject (ctx, "imts", imt_list); + for (imt_t *imt = context->imts; imt; imt = imt->next) { + plitem_t *imt_cfg = PL_NewDictionary (0); //FIXME hashlinks + PL_D_AddObject (imt_cfg, "name", PL_NewString (imt->name)); + if (imt->chain) { + PL_D_AddObject (imt_cfg, "chain", + PL_NewString (imt->chain->name)); + } + PL_A_AddObject (imt_list, imt_cfg); + // the bindings are not written here because they are managed + // by IN_Binding_SaveConfig: IMT does not really know the + // device-input structure (it cound via the blocks, but it + // doesn't know the device names (by design)) + } + } + if (context->default_imt) { + PL_D_AddObject (ctx, "default_imt", + PL_NewString (context->default_imt->name)); + } + } +} + +void +IMT_SaveAxisConfig (plitem_t *axes, int axis_ind, int dev_axis) +{ + for (size_t i = 0; i < in_contexts.size; i++) { + in_context_t *context = &in_contexts.a[i]; + for (imt_t *imt = context->imts; imt; imt = imt->next) { + in_axisbinding_t *a = imt->axis_bindings.a[axis_ind]; + if (a) { + in_recipe_t *recipe = a->recipe; + plitem_t *axis = PL_NewDictionary (0); //FIXME hashlinks + PL_A_AddObject (axes, axis); + + PL_D_AddObject (axis, "imt", PL_NewString (imt->name)); + PL_D_AddObject (axis, "num", + PL_NewString (va (0, "%d", dev_axis))); + PL_D_AddObject (axis, "axis", PL_NewString (a->axis->name)); + PL_D_AddObject (axis, "min", + PL_NewString (va (0, "%d", recipe->min))); + PL_D_AddObject (axis, "max", + PL_NewString (va (0, "%d", recipe->max))); + PL_D_AddObject (axis, "minzone", + PL_NewString (va (0, "%d", recipe->minzone))); + PL_D_AddObject (axis, "maxzone", + PL_NewString (va (0, "%d", recipe->maxzone))); + PL_D_AddObject (axis, "deadzone", + PL_NewString (va (0, "%d", recipe->deadzone))); + PL_D_AddObject (axis, "curve", + PL_NewString (va (0, "%.9g", recipe->curve))); + PL_D_AddObject (axis, "scale", + PL_NewString (va (0, "%.9g", recipe->scale))); + } + } + } +} + +void +IMT_SaveButtonConfig (plitem_t *buttons, int button_ind, int dev_button) +{ + for (size_t i = 0; i < in_contexts.size; i++) { + in_context_t *context = &in_contexts.a[i]; + for (imt_t *imt = context->imts; imt; imt = imt->next) { + in_buttonbinding_t *b = imt->button_bindings.a[button_ind]; + if (b) { + plitem_t *button = PL_NewDictionary (0); //FIXME hashlinks + PL_A_AddObject (buttons, button); + + PL_D_AddObject (button, "imt", PL_NewString (imt->name)); + PL_D_AddObject (button, "num", + PL_NewString (va (0, "%d", dev_button))); + switch (b->type) { + case inb_button: + PL_D_AddObject (button, "binding", + PL_NewString (va (0, "+%s", + b->button->name))); + break; + case inb_command: + PL_D_AddObject (button, "binding", + PL_NewString (b->command)); + break; + } + } + } + } +} + +void +IMT_LoadConfig (plitem_t *config) +{ + imt_drop_all_f (); + + plitem_t *ctx_list = PL_ObjectForKey (config, "contexts"); + if (PL_Type (ctx_list) != QFArray) { + Sys_Printf ("IMT_LoadConfig: contexts not an array\n"); + return; + } + for (int i = 0, count = PL_A_NumObjects (ctx_list); i < count; i++) { + plitem_t *ctx = PL_ObjectAtIndex (ctx_list, i); + const char *name = PL_String (PL_ObjectForKey (ctx, "name")); + in_context_t *context = imt_find_context (name); + if (!context) { + continue; + } + plitem_t *imts = PL_ObjectForKey (ctx, "imts"); + if (!imts || PL_Type (imts) != QFArray) { + continue; + } + for (int j = 0, num_imts = PL_A_NumObjects (imts); j < num_imts; j++) { + plitem_t *imt = PL_ObjectAtIndex (imts, j); + const char *imt_name = PL_String (PL_ObjectForKey (imt, "name")); + const char *imt_chain = PL_String (PL_ObjectForKey (imt, "chain")); + if (imt_name) { + IMT_CreateIMT (context - in_contexts.a, imt_name, imt_chain); + } + } + const char *default_imt = PL_String (PL_ObjectForKey (ctx, + "default_imt")); + if (default_imt) { + context->default_imt = IMT_FindIMT (default_imt); + } + if (!context->default_imt) { + context->default_imt = context->imts; + } + context->active_imt = context->default_imt; + } +} From 8cf0d00eda07c11b80b4e20454badb600bcc8f8b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 Nov 2021 10:32:35 +0900 Subject: [PATCH 1808/3664] [qw] Switch quakeforge.cfg to property list format Cvars aren't handled yet, but input configuration is. Seems to work :) --- qw/include/cl_main.h | 1 + qw/source/cl_main.c | 68 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/qw/include/cl_main.h b/qw/include/cl_main.h index 16727deea..640c206cc 100644 --- a/qw/include/cl_main.h +++ b/qw/include/cl_main.h @@ -34,6 +34,7 @@ void CL_Init (void); void Host_WriteConfiguration (void); +int Host_ReadConfiguration (const char *cfg_name); void CL_EstablishConnection (const char *host); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index b3d8c2f1a..4f9b6068f 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -81,7 +81,9 @@ #include "QF/qargs.h" #include "QF/qendian.h" #include "QF/quakefs.h" +#include "QF/quakeio.h" #include "QF/ruamoko.h" +#include "QF/plist.h" #include "QF/screen.h" #include "QF/sound.h" #include "QF/sys.h" @@ -1504,18 +1506,72 @@ void Host_WriteConfiguration (void) { if (host_initialized && cl_writecfg->int_val) { + plitem_t *config = PL_NewDictionary (0); //FIXME hashlinks + IN_SaveConfig (config); + //Cvar_WriteVariables (f); + const char *path = va (0, "%s/quakeforge.cfg", qfs_gamedir->dir.def); QFile *f = QFS_WOpen (path, 0); if (!f) { Sys_Printf ("Couldn't write quakeforge.cfg.\n"); - return; + } else { + char *cfg = PL_WritePropertyList (config); + Qputs (f, cfg); + free (cfg); + Qclose (f); } + PL_Free (config); + } +} - //Key_WriteBindings (f); - Cvar_WriteVariables (f); +int +Host_ReadConfiguration (const char *cfg_name) +{ + QFile *cfg_file = QFS_FOpenFile (cfg_name); + if (!cfg_file) { + return 0; + } + size_t len = Qfilesize (cfg_file); + char *cfg = malloc (len + 1); + Qread (cfg_file, cfg, len); + cfg[len] = 0; + Qclose (cfg_file); - Qclose (f); + plitem_t *config = PL_GetPropertyList (cfg, 0); // FIXME hashlinks + if (!config) { + return 0; + } + + IN_LoadConfig (config); + + PL_Free (config); + return 1; +} + +static void +Host_ExecConfig (cbuf_t *cbuf, int skip_quakerc) +{ + // quakeforge.cfg overrides quake.rc as it contains quakeforge-specific + // commands. If it doesn't exist, then this is the first time quakeforge + // has been used in this installation, thus any existing legacy config + // should be used to set up defaults on the assumption that the user has + // things set up to work with another (hopefully compatible) client + if (Host_ReadConfiguration ("quakeforge.cfg")) { + Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cmd_StuffCmds (cbuf); + COM_Check_quakerc ("startdemos", cbuf); + } else { + if (!skip_quakerc) { + Cbuf_InsertText (cbuf, "exec quake.rc\n"); + } + Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + // Reparse the command line for + commands. + // (sets still done, but it doesn't matter) + // (Note, no non-base commands exist yet) + if (skip_quakerc || !COM_Check_quakerc ("stuffcmds", 0)) { + Cmd_StuffCmds (cbuf); + } } } @@ -1741,7 +1797,7 @@ CL_Autoexec (int phase) { if (!phase) return; - if (!Cmd_Exec_File (cl_cbuf, "quakeforge.cfg", 1)) { + if (!Host_ReadConfiguration ("quakeforge.cfg")) { int cmd_warncmd_val = cmd_warncmd->int_val; Cbuf_AddText (cl_cbuf, "cmd_warncmd 0\n"); @@ -1806,7 +1862,7 @@ Host_Init (void) CL_UpdateScreen (realtime); CL_UpdateScreen (realtime); - COM_ExecConfig (cl_cbuf, !cl_quakerc->int_val); + Host_ExecConfig (cl_cbuf, !cl_quakerc->int_val); // make sure all + commands have been executed Cbuf_Execute_Stack (cl_cbuf); From b80c19bd77810177675724f721457b860c74a63b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 15 Nov 2021 22:04:29 +0900 Subject: [PATCH 1809/3664] [util] Save and load cvars to/from plist configs Other than some backwards compatibility, this completes the configuration updates for now. --- include/QF/cvar.h | 4 ++++ libs/util/cvar.c | 33 +++++++++++++++++++++++++++++++++ qw/source/cl_main.c | 3 ++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/include/QF/cvar.h b/include/QF/cvar.h index 946a20f13..461ff4bf6 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -120,6 +120,10 @@ qboolean Cvar_Command (void); // with the archive flag set to true. void Cvar_WriteVariables (QFile *f); +struct plitem_s; +void Cvar_SaveConfig (struct plitem_s *config); +void Cvar_LoadConfig (struct plitem_s *config); + // attempts to match a partial variable name for command line completion // returns NULL if nothing fits const char *Cvar_CompleteVariable (const char *partial) __attribute__((pure)); diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 10915818d..333e1ca9b 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -45,6 +45,7 @@ #include "QF/cvar.h" #include "QF/hash.h" #include "QF/mathlib.h" +#include "QF/plist.h" #include "QF/qargs.h" #include "QF/quakefs.h" #include "QF/sys.h" @@ -330,6 +331,38 @@ Cvar_WriteVariables (QFile *f) Qprintf (f, "seta %s \"%s\"\n", var->name, var->string); } +VISIBLE void +Cvar_SaveConfig (plitem_t *config) +{ + plitem_t *cvars = PL_NewDictionary (0); //FIXME hashlinks + PL_D_AddObject (config, "cvars", cvars); + for (cvar_t *var = cvar_vars; var; var = var->next) { + if (var->flags & CVAR_ARCHIVE) { + PL_D_AddObject (cvars, var->name, PL_NewString (var->string)); + } + } +} + +VISIBLE void +Cvar_LoadConfig (plitem_t *config) +{ + plitem_t *cvars = PL_ObjectForKey (config, "cvars"); + + if (!cvars) { + return; + } + for (int i = 0, count = PL_D_NumKeys (cvars); i < count; i++) { + const char *cvar_name = PL_KeyAtIndex (cvars, i); + const char *value = PL_String (PL_ObjectForKey (cvars, cvar_name)); + if (value) { + cvar_t *var = Cvar_FindVar (cvar_name); + if (var) { + Cvar_Set (var, value); + } + } + } +} + #define SYS_DEVELOPER(developer) #developer, static const char *developer_flags[] = { "dev", diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 4f9b6068f..540fcedec 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1508,7 +1508,7 @@ Host_WriteConfiguration (void) if (host_initialized && cl_writecfg->int_val) { plitem_t *config = PL_NewDictionary (0); //FIXME hashlinks IN_SaveConfig (config); - //Cvar_WriteVariables (f); + Cvar_SaveConfig (config); const char *path = va (0, "%s/quakeforge.cfg", qfs_gamedir->dir.def); QFile *f = QFS_WOpen (path, 0); @@ -1544,6 +1544,7 @@ Host_ReadConfiguration (const char *cfg_name) } IN_LoadConfig (config); + Cvar_LoadConfig (config); PL_Free (config); return 1; From 1868fe74042aa3ae866152c161df8c9cfd70936c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 16 Nov 2021 08:48:35 +0900 Subject: [PATCH 1810/3664] [qw] Save and load cvars before input config Saving is not so important, but for loading, while the input system doesn't make much use of cvars at this stage, it makes sense for them to be loaded before the input system configuration is loaded. --- qw/source/cl_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 540fcedec..a4a72ed45 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1507,8 +1507,8 @@ Host_WriteConfiguration (void) { if (host_initialized && cl_writecfg->int_val) { plitem_t *config = PL_NewDictionary (0); //FIXME hashlinks - IN_SaveConfig (config); Cvar_SaveConfig (config); + IN_SaveConfig (config); const char *path = va (0, "%s/quakeforge.cfg", qfs_gamedir->dir.def); QFile *f = QFS_WOpen (path, 0); @@ -1543,8 +1543,8 @@ Host_ReadConfiguration (const char *cfg_name) return 0; } - IN_LoadConfig (config); Cvar_LoadConfig (config); + IN_LoadConfig (config); PL_Free (config); return 1; From b8baa04b2e5166fc1cd53f696db7d0151041e7db Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 16 Nov 2021 09:37:39 +0900 Subject: [PATCH 1811/3664] [input] Split binding event handler There's now an internal event handler for taking care of device addition and removal, and a public event handler for dealing with device input events in various contexts In particular, so the clients can check for the escape key. --- include/QF/input/binding.h | 2 ++ include/QF/input/event.h | 2 +- libs/input/in_binding.c | 13 +++++++++++++ qw/source/cl_input.c | 21 ++++++++++++++++++++- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 3b3bc3aa2..5c82d08c2 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -234,6 +234,8 @@ int IN_RegisterAxis (in_axis_t *axis); in_button_t *IN_FindButton (const char *name); in_axis_t *IN_FindAxis (const char *name); +struct IE_event_s; +int IN_Binding_HandleEvent (const struct IE_event_s *ie_event); void IN_Binding_Activate (void); void IN_Binding_Init (void); struct plitem_s; diff --git a/include/QF/input/event.h b/include/QF/input/event.h index 399d25f9f..4b526fa61 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -99,7 +99,7 @@ typedef enum { | (1 << ie_remove_device) \ ) -typedef struct { +typedef struct IE_event_s { IE_event_type type; uint64_t when; union { diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index bb846605b..d7da6878c 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -202,6 +202,19 @@ in_binding_event_handler (const IE_event_t *ie_event, void *unused) static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { [ie_add_device] = in_binding_add_device, [ie_remove_device] = in_binding_remove_device, + }; + if (ie_event->type < 0 || ie_event->type >= ie_event_count + || !handlers[ie_event->type]) { + return 0; + } + handlers[ie_event->type] (ie_event); + return 1; +} + +int +IN_Binding_HandleEvent (const IE_event_t *ie_event) +{ + static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { [ie_axis] = in_binding_axis, [ie_button] = in_binding_button, }; diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index df8f709ba..8f710c948 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -37,6 +37,7 @@ #include "QF/checksum.h" #include "QF/cmd.h" +#include "QF/console.h" #include "QF/cvar.h" #include "QF/input.h" #include "QF/keys.h" @@ -45,6 +46,8 @@ #include "QF/teamplay.h" #include "QF/va.h" +#include "QF/input/event.h" + #include "compat.h" #include "client/view.h" @@ -61,6 +64,7 @@ int cl_game_context; int cl_demo_context; +static int cl_event_id; cvar_t *cl_nodelta; cvar_t *cl_maxnetfps; @@ -563,9 +567,24 @@ CL_SendCmd (void) Netchan_Transmit (&cls.netchan, buf.cursize, buf.data); } +static int +cl_event_handler (const IE_event_t *ie_event, void *unused) +{ + if (ie_event->type == ie_key) { + if (ie_event->key.code == QFK_ESCAPE) { + // FIXME this should bring up the menu + Con_SetState (con_active); + return 1; + } + } + return IN_Binding_HandleEvent (ie_event); +} + void CL_Input_Init (void) { + cl_event_id = IE_Add_Handler (cl_event_handler, 0); + for (int i = 0; cl_in_axes[i]; i++) { IN_RegisterAxis (cl_in_axes[i]); } @@ -584,7 +603,7 @@ void CL_Input_Activate (void) { IMT_SetContext (cl_game_context); - IN_Binding_Activate (); + IE_Set_Focus (cl_event_id); } void From 7739972f196137f97c41af67c47270689d32980f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 16 Nov 2021 12:55:55 +0900 Subject: [PATCH 1812/3664] [x11] Block raw inputs if cooked inputs are handled The cooked inputs (ie_key, ie_mouse) are intended for UI interaction, so generally should have priority over the raw events, which are intended for game interaction. --- libs/video/targets/in_x11.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 17c08ce67..9e3ef5f4c 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -655,7 +655,7 @@ in_x11_send_axis_event (int devid, in_axisinfo_t *axis) IE_Send_Event (&event); } -static void +static int in_x11_send_mouse_event (IE_mouse_type type) { IE_event_t event = { @@ -664,10 +664,10 @@ in_x11_send_mouse_event (IE_mouse_type type) .mouse = x11_mouse, }; event.mouse.type = type; - IE_Send_Event (&event); + return IE_Send_Event (&event); } -static void +static int in_x11_send_key_event (void) { IE_event_t event = { @@ -675,7 +675,7 @@ in_x11_send_key_event (void) .when = Sys_LongTime (), .key = x11_key, }; - IE_Send_Event (&event); + return IE_Send_Event (&event); } static void @@ -758,13 +758,14 @@ event_motion (XEvent *event) x11_mouse_axes[1].value = event->xmotion.y - x11_mouse.y; } } - in_x11_send_axis_event (x11_mouse_device.devid, &x11_mouse_axes[0]); - in_x11_send_axis_event (x11_mouse_device.devid, &x11_mouse_axes[1]); x11_mouse.shift = event->xmotion.state & 0xff; x11_mouse.x = event->xmotion.x; x11_mouse.y = event->xmotion.y; - in_x11_send_mouse_event (ie_mousemove); + if (!in_x11_send_mouse_event (ie_mousemove)) { + in_x11_send_axis_event (x11_mouse_device.devid, &x11_mouse_axes[0]); + in_x11_send_axis_event (x11_mouse_device.devid, &x11_mouse_axes[1]); + } } static void @@ -782,8 +783,6 @@ event_button (XEvent *event) int press = event->type == ButtonPress; x11_mouse_buttons[but].state = press; - in_x11_send_button_event (x11_mouse_device.devid, &x11_mouse_buttons[but], - x11_mouse_device.event_data); x11_mouse.shift = event->xmotion.state & 0xff; x11_mouse.x = event->xmotion.x; @@ -793,7 +792,11 @@ event_button (XEvent *event) } else { x11_mouse.buttons &= ~(1 << but); } - in_x11_send_mouse_event (press ? ie_mousedown : ie_mouseup); + if (!in_x11_send_mouse_event (press ? ie_mousedown : ie_mouseup)) { + in_x11_send_button_event (x11_mouse_device.devid, + &x11_mouse_buttons[but], + x11_mouse_device.event_data); + } } static void @@ -806,14 +809,13 @@ event_key (XEvent *event) // offset by 8 (so Esc is 9 instead of 1). key = (event->xkey.keycode - 8) & 0xff; x11_key_buttons[key].state = event->type == KeyPress; - in_x11_send_button_event (x11_keyboard_device.devid, - &x11_key_buttons[key], - x11_keyboard_device.event_data); x11_key.shift = event->xmotion.state & 0xff; XLateKey (&event->xkey, &x11_key.code, &x11_key.unicode); - if (event->type == KeyPress) { - in_x11_send_key_event (); + if (event->type != KeyPress || !in_x11_send_key_event ()) { + in_x11_send_button_event (x11_keyboard_device.devid, + &x11_key_buttons[key], + x11_keyboard_device.event_data); } } From 73ab33ba977443df3b9ab794282e71b4944564b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 16 Nov 2021 16:33:53 +0900 Subject: [PATCH 1813/3664] [input] Actually return the button in IN_FindButton Returning the wrapper object makes for some weird behaviour. --- libs/input/in_button.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/input/in_button.c b/libs/input/in_button.c index 1c0fe51f7..17cfc5944 100644 --- a/libs/input/in_button.c +++ b/libs/input/in_button.c @@ -189,7 +189,11 @@ IN_RegisterButton (in_button_t *button) in_button_t * IN_FindButton (const char *name) { - return Hash_Find (button_tab, name); + regbutton_t *regbutton = Hash_Find (button_tab, name); + if (regbutton) { + return regbutton->button; + } + return 0; } static void __attribute__((constructor)) From 111e5d923ea65a5fbbaf03db659f729cdfa0cac8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 16 Nov 2021 19:59:47 +0900 Subject: [PATCH 1814/3664] [cexpr] Support casting to double For int, uint and float, also add uint to float (not that it will do any good for values over 16M). --- libs/util/cexpr-type.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 7ee34f5c2..2b2fa70f4 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -45,6 +45,14 @@ pre##_##opname (const exprval_t *a, const exprval_t *b, exprval_t *c, \ (*(type *) c->value) = (*(type *) a->value) op (*(type *) b->value); \ } +#define CASTOP(dst_type, src_type) \ +static void \ +dst_type##_##cast##_##src_type (const exprval_t *a, const exprval_t *src, \ + exprval_t *res, exprctx_t *ctx) \ +{ \ + (*(dst_type *) res->value) = *(src_type *) src->value; \ +} + #define UNOP(pre, opname, type, op) \ static void \ pre##_##opname (const exprval_t *a, exprval_t *b, exprctx_t *ctx) \ @@ -291,12 +299,8 @@ float_div_quat (const exprval_t *val1, const exprval_t *val2, *c = a * qconjf (b) / dotf (b, b); } -static void -float_cast_int (const exprval_t *val1, const exprval_t *src, exprval_t *result, - exprctx_t *ctx) -{ - *(float *) result->value = *(int *) src->value; -} +CASTOP (float, int) +CASTOP (float, uint) UNOP(float, pos, float, +) UNOP(float, neg, float, -) @@ -313,6 +317,7 @@ binop_t float_binops[] = { { '%', &cexpr_float, &cexpr_float, float_rem }, { MOD, &cexpr_float, &cexpr_float, float_mod }, { '=', &cexpr_int, &cexpr_float, float_cast_int }, + { '=', &cexpr_uint, &cexpr_float, float_cast_uint }, { '=', &cexpr_plitem, &cexpr_float, cexpr_cast_plitem }, {} }; @@ -359,6 +364,10 @@ double_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, *(double *) result->value = a - b * floorf (a / b); } +CASTOP (double, int) +CASTOP (double, uint) +CASTOP (double, float) + UNOP(double, pos, double, +) UNOP(double, neg, double, -) UNOP(double, tnot, double, !) @@ -370,6 +379,9 @@ binop_t double_binops[] = { { '/', &cexpr_double, &cexpr_double, double_div }, { '%', &cexpr_double, &cexpr_double, double_rem }, { MOD, &cexpr_double, &cexpr_double, double_mod }, + { '=', &cexpr_int, &cexpr_double, double_cast_int }, + { '=', &cexpr_uint, &cexpr_double, double_cast_uint }, + { '=', &cexpr_uint, &cexpr_double, double_cast_float }, { '=', &cexpr_plitem, &cexpr_double, cexpr_cast_plitem }, {} }; From 1381932552af30161f2926b1f539ffc18f2c7755 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 16 Nov 2021 20:12:53 +0900 Subject: [PATCH 1815/3664] [input] Fix imt block management Reset the blocks completely when loading configs and fix a leftover from when I thought I'd expose the block numbers to bindings but then changed my mind to simply track the base binding. --- libs/input/in_imt.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 77b8ae4f3..4417126f3 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -194,24 +194,37 @@ imt_get_button_block (int count) return base; } +static void +imt_reset_blocks (void) +{ + DARRAY_RESIZE (&axis_blocks, 0); + DARRAY_RESIZE (&button_blocks, 0); + for (size_t i = 0; i < in_contexts.size; i++) { + for (imt_t *imt = in_contexts.a[i].imts; imt; imt = imt->next) { + DARRAY_RESIZE (&imt->axis_bindings, 0); + DARRAY_RESIZE (&imt->button_bindings, 0); + } + } +} + int IMT_GetAxisBlock (int num_axes) { int base = imt_get_axis_block (num_axes); - imt_block_t *block = imt_get_block (&axis_blocks); + imt_block_t *block = imt_get_block (&axis_blocks); block->base = base; block->count = num_axes; - return block - axis_blocks.a; + return base; } int IMT_GetButtonBlock (int num_buttons) { int base = imt_get_button_block (num_buttons); - imt_block_t *block = imt_get_block (&button_blocks); + imt_block_t *block = imt_get_block (&button_blocks); block->base = base; block->count = num_buttons; - return block - button_blocks.a; + return base; } int @@ -749,6 +762,7 @@ IMT_SaveButtonConfig (plitem_t *buttons, int button_ind, int dev_button) void IMT_LoadConfig (plitem_t *config) { + imt_reset_blocks (); imt_drop_all_f (); plitem_t *ctx_list = PL_ObjectForKey (config, "contexts"); From c3fa0d6464568dd10552f1e50b51ee59b1cb6e83 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 16 Nov 2021 20:14:33 +0900 Subject: [PATCH 1816/3664] [input] Fix incorrect arg count in in_unbind_f Yay for copying and editing code :P --- libs/input/in_binding.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index d7da6878c..0afe205a0 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -432,7 +432,7 @@ in_bind_f (void) static void in_unbind_f (void) { - if (Cmd_Argc () < 6) { + if (Cmd_Argc () < 5) { Sys_Printf ("in_unbind imt device type number\n"); Sys_Printf (" imt: the name of the input mapping table in which the" " intput will be unbound\n"); From fbcb22d41a87c84eb6400eb3de833ebcd1da7419 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 16 Nov 2021 20:26:19 +0900 Subject: [PATCH 1817/3664] [qw] Sort out move axis directions and names Everything is set up so default recipes work as expected (by me) for a 3Dconnexion SpaceNavigator: translation axes move quakeguy in the direction the puck is moved tilting the puck forward pitches forward (look down) tilting the puck to the left rolls to the left twisting the puck clockwise (looked at from the top) turns quakeguy to the right. This does mean that the default pitch motion for a regular mouse is now push forward to pitch forward (look down) (inverted from before). Mouse scaling is out (too small), but that's because in_amp etc are ignored for now (thinking about how to integrate cvars with axis recipes). Joystick input will be the same. --- qw/source/cl_input.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 8f710c948..77a799bef 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -73,12 +73,12 @@ cvar_t *cl_spamimpulse; in_axis_t viewdelta_position_forward = { .mode = ina_accumulate, .name = "move.forward", - .description = "Move forward (positive) or backward (negative)", + .description = "Move forward (negative) or backward (positive)", }; -in_axis_t viewdelta_position_left = { +in_axis_t viewdelta_position_side = { .mode = ina_accumulate, - .name = "move.left", - .description = "Move left (positive) or right (negative)", + .name = "move.side", + .description = "Move right (positive) or left (negative)", }; in_axis_t viewdelta_position_up = { .mode = ina_accumulate, @@ -178,7 +178,7 @@ in_button_t in_mlook = { static in_axis_t *cl_in_axes[] = { &viewdelta_position_forward, - &viewdelta_position_left, + &viewdelta_position_side, &viewdelta_position_up, &viewdelta_angles_pitch, &viewdelta_angles_yaw, @@ -354,18 +354,18 @@ CL_BaseMove (usercmd_t *cmd) } */ - cmd->forwardmove += viewdelta_position_forward.value * m_forward->value; - cmd->sidemove += viewdelta_position_left.value * m_side->value; - cmd->upmove += viewdelta_position_up.value; - cl.viewstate.angles[PITCH] += viewdelta_angles_pitch.value * m_pitch->value; - cl.viewstate.angles[YAW] += viewdelta_angles_yaw.value * m_yaw->value; - cl.viewstate.angles[ROLL] += viewdelta_angles_roll.value; + cmd->forwardmove -= viewdelta_position_forward.value * m_forward->value; + cmd->sidemove += viewdelta_position_side.value * m_side->value; + cmd->upmove -= viewdelta_position_up.value; + cl.viewstate.angles[PITCH] -= viewdelta_angles_pitch.value * m_pitch->value; + cl.viewstate.angles[YAW] -= viewdelta_angles_yaw.value * m_yaw->value; + cl.viewstate.angles[ROLL] -= viewdelta_angles_roll.value * m_pitch->value; viewdelta_angles_pitch.value = 0; viewdelta_angles_yaw.value = 0; viewdelta_angles_roll.value = 0; viewdelta_position_forward.value = 0; - viewdelta_position_left.value = 0; + viewdelta_position_side.value = 0; viewdelta_position_up.value = 0; if (freelook && !(in_strafe.state & inb_down)) { From f4c521d51d5de2113bc9aacc38affebc456cae55 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Nov 2021 11:17:04 +0900 Subject: [PATCH 1818/3664] [input] Move in_devbindings_t definition In the end, it doesn't need to be public, so move it into in_binding.c --- include/QF/input.h | 46 ----------------------------------------- libs/input/in_binding.c | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index a49bc541b..78f4f7663 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -87,52 +87,6 @@ typedef struct in_device_s { void *event_data; } in_device_t; -/*** Connect a device and its axes and buttons to logical axes and buttons. - - \a name is used to specify the device when creating bindings, and - identifying the device for hints etc (eg, "press joy1 1 to ..."). - - \a devname is the device name (eg, "6d spacemouse") - - \a id is the device id (eg "usb-0000:00:1d.1-2/input0"). - - The device name is useful for ease of user identification and allowing - the device to be plugged into any USB socket. However, it doesn't allow - multiple devices with the same name (eg, using twin joysticks of the same - model). Thus if \a match_id is true, both the device name and the device - id used to auto-connect the device, but it does require the device to be - plugged into the same uSB path (ie, same socket on the same hub connected - to the same port on the PC) - - \a devid is the actual device associated with the bindings. If -1, the - device is not currently connected. - - \a axis_info holds the device/axis specific range info and the current - raw value of the axis. - - \a button_info holds the current raw state of the button - - \a axis_imt_id is -1 if the device has no axis bindings, otherwise it is - the base index into the imt axis bindings array. - - \a button_imt_id is -1 if the device has no button bindings, otherwise it - is the base index into the imt button bindings array. -*/ -typedef struct in_devbindings_s { - struct in_devbindings_s *next; - char *name; ///< name used when binding inputs - char *devname; ///< physical device name - char *id; ///< physical device id - int match_id; ///< if true, both devname and id must match - int devid; ///< id of device associated with these bindings - int num_axes; - int num_buttons; - in_axisinfo_t *axis_info; ///< axis range info and raw state - in_buttoninfo_t *button_info; ///< button raw state - int axis_imt_id; ///< index into array of imt axis bindings - int button_imt_id; ///< index into array of imt button bindings -} in_devbindings_t; - extern viewdelta_t viewdelta; #define freelook (in_mlook.state & 1 || in_freelook->int_val) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 0afe205a0..9f30f33f6 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -55,6 +55,52 @@ #include "QF/input/event.h" #include "QF/input/imt.h" +/*** Connect a device and its axes and buttons to logical axes and buttons. + + \a name is used to specify the device when creating bindings, and + identifying the device for hints etc (eg, "press joy1 1 to ..."). + + \a devname is the device name (eg, "6d spacemouse") + + \a id is the device id (eg "usb-0000:00:1d.1-2/input0"). + + The device name is useful for ease of user identification and allowing + the device to be plugged into any USB socket. However, it doesn't allow + multiple devices with the same name (eg, using twin joysticks of the same + model). Thus if \a match_id is true, both the device name and the device + id used to auto-connect the device, but it does require the device to be + plugged into the same uSB path (ie, same socket on the same hub connected + to the same port on the PC) + + \a devid is the actual device associated with the bindings. If -1, the + device is not currently connected. + + \a axis_info holds the device/axis specific range info and the current + raw value of the axis. + + \a button_info holds the current raw state of the button + + \a axis_imt_id is -1 if the device has no axis bindings, otherwise it is + the base index into the imt axis bindings array. + + \a button_imt_id is -1 if the device has no button bindings, otherwise it + is the base index into the imt button bindings array. +*/ +typedef struct in_devbindings_s { + struct in_devbindings_s *next; + char *name; ///< name used when binding inputs + char *devname; ///< physical device name + char *id; ///< physical device id + int match_id; ///< if true, both devname and id must match + int devid; ///< id of device associated with these bindings + int num_axes; + int num_buttons; + in_axisinfo_t *axis_info; ///< axis range info and raw state + in_buttoninfo_t *button_info; ///< button raw state + int axis_imt_id; ///< index into array of imt axis bindings + int button_imt_id; ///< index into array of imt button bindings +} in_devbindings_t; + typedef struct DARRAY_TYPE (int) in_knowndevset_t; static in_knowndevset_t known_devices = DARRAY_STATIC_INIT (8); From 84f746dab24493626a1d670cbd31c8ca0844e312 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Nov 2021 12:59:18 +0900 Subject: [PATCH 1819/3664] [input] Allow button and axis inputs to be named keyhelp provides the input name if it is known, and in_bind tries to use the provided input name if not a number. Case sensitivity for name lookups is dependent on the input driver. --- include/QF/input.h | 10 ++++++ libs/input/in_binding.c | 18 ++++++++--- libs/input/in_common.c | 72 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 78f4f7663..7952d82aa 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -77,6 +77,12 @@ typedef struct in_driver_s { int *numaxes); void (*button_info) (void *data, void *device, in_buttoninfo_t *buttons, int *numbuttons); + // null means either invalid number or the name is not known + const char *(*get_axis_name) (void *data, void *device, int axis_num); + const char *(*get_button_name) (void *data, void *device, int button_num); + // -1 for invalid name + int (*get_axis_num) (void *data, void *device, const char *axis_name); + int (*get_button_num) (void *data, void *device, const char *button_name); } in_driver_t; typedef struct in_device_s { @@ -111,6 +117,10 @@ void IN_SetDeviceEventData (int devid, void *data); void *IN_GetDeviceEventData (int devid); int IN_AxisInfo (int devid, in_axisinfo_t *axes, int *numaxes); int IN_ButtonInfo (int devid, in_buttoninfo_t *button, int *numbuttons); +const char *IN_GetAxisName (int devid, int axis_num); +const char *IN_GetButtonName (int devid, int button_num); +int IN_GetAxisNumber (int devid, const char *axis_name); +int IN_GetButtonNumber (int devid, const char *button_name); void IN_ProcessEvents (void); diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 9f30f33f6..0f66ae831 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -283,11 +283,12 @@ in_keyhelp_event_handler (const IE_event_t *ie_event, void *unused) size_t devid = ie_event->button.devid; in_devbindings_t *db = ie_event->button.data; - const char *name = db ? db->name : 0; + const char *bind_name = db ? db->name : 0; const char *type = 0; int num = -1; const char *devname = IN_GetDeviceName (devid); const char *id = IN_GetDeviceId (devid); + const char *name = 0; if (ie_event->type == ie_axis) { int axis = ie_event->axis.axis; @@ -317,17 +318,20 @@ in_keyhelp_event_handler (const IE_event_t *ie_event, void *unused) type = "axis"; } } + name = IN_GetAxisName (devid, num); } else if (ie_event->type == ie_button) { if (ie_event->button.state) { num = ie_event->button.button; type = "button"; } + name = IN_GetButtonName (devid, num); } if (!type) { return 0; } IE_Set_Focus (in_keyhelp_saved_handler); - Sys_Printf ("%s (%s %s) %s %d\n", name, devname, id, type, num); + Sys_Printf ("%s (%s %s) %s %d (%s)\n", bind_name, devname, id, type, num, + name ? name : ""); return 1; } @@ -402,7 +406,10 @@ in_bind_f (void) return; } if (*type == 'a') { - if (*end || num < 0 || num >= dev->num_axes) { + if (*end) { + num = IN_GetAxisNumber (dev->devid, number); + } + if (num < 0 || num >= dev->num_axes) { Sys_Printf ("invalid axis number: %s\n", number); return; } @@ -464,7 +471,10 @@ in_bind_f (void) // the rest of the command line is the binding const char *binding = Cmd_Args (5); - if (*end || num < 0 || num >= dev->num_buttons) { + if (*end) { + num = IN_GetButtonNumber (dev->devid, number); + } + if (num < 0 || num >= dev->num_buttons) { Sys_Printf ("invalid button number: %s\n", number); return; } diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 1c0ff86fb..4cbb637c5 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -280,6 +280,78 @@ IN_ButtonInfo (int devid, in_buttoninfo_t *buttons, int *numbuttons) return 0; } +const char * +IN_GetAxisName (int devid, int axis_num) +{ + if ((size_t) devid >= in_devices.size) { + return 0; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return 0; + } + int driver = in_devices.a[devid].driverid; + in_regdriver_t *rd = &in_drivers.a[driver]; + if (!rd->driver.get_axis_name) { + return 0; + } + return rd->driver.get_axis_name (rd->data, in_devices.a[devid].device, + axis_num); +} + +const char * +IN_GetButtonName (int devid, int button_num) +{ + if ((size_t) devid >= in_devices.size) { + return 0; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return 0; + } + int driver = in_devices.a[devid].driverid; + in_regdriver_t *rd = &in_drivers.a[driver]; + if (!rd->driver.get_button_name) { + return 0; + } + return rd->driver.get_button_name (rd->data, in_devices.a[devid].device, + button_num); +} + +int +IN_GetAxisNumber (int devid, const char *axis_name) +{ + if ((size_t) devid >= in_devices.size) { + return -1; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return -1; + } + int driver = in_devices.a[devid].driverid; + in_regdriver_t *rd = &in_drivers.a[driver]; + if (!rd->driver.get_axis_num) { + return -1; + } + return rd->driver.get_axis_num (rd->data, in_devices.a[devid].device, + axis_name); +} + +int +IN_GetButtonNumber (int devid, const char *button_name) +{ + if ((size_t) devid >= in_devices.size) { + return -1; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return -1; + } + int driver = in_devices.a[devid].driverid; + in_regdriver_t *rd = &in_drivers.a[driver]; + if (!rd->driver.get_button_num) { + return -1; + } + return rd->driver.get_button_num (rd->data, in_devices.a[devid].device, + button_name); +} + void IN_UpdateGrab (cvar_t *var) // called from context_*.c { From 793914718fcdd86445bc265251914fb640fadee7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Nov 2021 13:01:33 +0900 Subject: [PATCH 1820/3664] [x11] Implement input names Mouse axis and button names are handled internally (and thus case-insensitive). Key names are handled by X11. Case-sensitivity is currently determined by Xlib. --- libs/video/targets/in_x11.c | 107 +++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 9e3ef5f4c..59308f52c 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -97,18 +98,29 @@ static in_buttoninfo_t x11_key_buttons[256]; static in_axisinfo_t x11_mouse_axes[2]; // FIXME assume up to 32 mouse buttons static in_buttoninfo_t x11_mouse_buttons[32]; +static const char *x11_mouse_axis_names[] = {"M_X", "M_Y"}; +static const char *x11_mouse_button_names[] = { + "M_BUTTON1", "M_BUTTON2", "M_BUTTON3", "M_WHEEL_UP", + "M_WHEEL_DOWN", "M_BUTTON6", "M_BUTTON7", "M_BUTTON8", + "M_BUTTON9", "M_BUTTON10", "M_BUTTON11", "M_BUTTON12", + "M_BUTTON13", "M_BUTTON14", "M_BUTTON15", "M_BUTTON16", + "M_BUTTON17", "M_BUTTON18", "M_BUTTON19", "M_BUTTON20", + "M_BUTTON21", "M_BUTTON22", "M_BUTTON23", "M_BUTTON24", + "M_BUTTON25", "M_BUTTON26", "M_BUTTON27", "M_BUTTON28", + "M_BUTTON29", "M_BUTTON30", "M_BUTTON31", "M_BUTTON32", +}; -#define infosize(x) (sizeof (x) / sizeof (x[0])) +#define SIZE(x) (sizeof (x) / sizeof (x[0])) static x11_device_t x11_keyboard_device = { "core:keyboard", - 0, infosize (x11_key_buttons), + 0, SIZE (x11_key_buttons), 0, x11_key_buttons, }; static x11_device_t x11_mouse_device = { "core:mouse", - infosize (x11_mouse_axes), infosize (x11_mouse_buttons), + SIZE (x11_mouse_axes), SIZE (x11_mouse_buttons), x11_mouse_axes, x11_mouse_buttons, }; @@ -935,6 +947,90 @@ in_x11_button_info (void *data, void *device, in_buttoninfo_t *buttons, memcpy (buttons, dev->buttons, *numbuttons * sizeof (in_buttoninfo_t)); } +static const char * +in_x11_get_axis_name (void *data, void *device, int axis_num) +{ + x11_device_t *dev = device; + const char *name = 0; + + if (dev == &x11_keyboard_device) { + // keyboards don't have axes... + } else if (dev == &x11_mouse_device) { + if ((unsigned) axis_num < SIZE (x11_mouse_axis_names)) { + name = x11_mouse_axis_names[axis_num]; + } + } + return name; +} + +static const char * +in_x11_get_button_name (void *data, void *device, int button_num) +{ + x11_device_t *dev = device; + const char *name = 0; + + if (dev == &x11_keyboard_device) { + // X11 protocol supports only 256 keys. The key codes are the AT scan + // codes offset by 8 (so Esc is 9 instead of 1). + KeyCode keycode = (button_num + 8) & 0xff; + KeySym keysym = XkbKeycodeToKeysym (x_disp, keycode, 0, 0); + if (keysym != NoSymbol) { + name = XKeysymToString (keysym); + } + } else if (dev == &x11_mouse_device) { + if ((unsigned) button_num < SIZE (x11_mouse_button_names)) { + name = x11_mouse_button_names[button_num]; + } + } + return name; +} + +static int +in_x11_get_axis_num (void *data, void *device, const char *axis_name) +{ + x11_device_t *dev = device; + int num = -1; + + if (dev == &x11_keyboard_device) { + // keyboards don't have axes... + } else if (dev == &x11_mouse_device) { + for (size_t i = 0; i < SIZE (x11_mouse_axis_names); i++) { + if (strcasecmp (axis_name, x11_mouse_axis_names[i]) == 0) { + num = i; + break; + } + } + } + return num; +} + +static int +in_x11_get_button_num (void *data, void *device, const char *button_name) +{ + x11_device_t *dev = device; + int num = -1; + + if (dev == &x11_keyboard_device) { + KeySym keysym = XStringToKeysym (button_name); + if (keysym != NoSymbol) { + KeyCode keycode = XKeysymToKeycode (x_disp, keysym); + if (keycode != 0) { + // X11 protocol supports only 256 keys. The key codes are the + // AT scan codes offset by 8 (so Esc is 9 instead of 1). + num = (keycode - 8) & 0xff; + } + } + } else if (dev == &x11_mouse_device) { + for (size_t i = 0; i < SIZE (x11_mouse_button_names); i++) { + if (strcasecmp (button_name, x11_mouse_button_names[i]) == 0) { + num = i; + break; + } + } + } + return num; +} + static void in_x11_shutdown (void *data) { @@ -1062,6 +1158,11 @@ static in_driver_t in_x11_driver = { .axis_info = in_x11_axis_info, .button_info = in_x11_button_info, + + .get_axis_name = in_x11_get_axis_name, + .get_button_name = in_x11_get_button_name, + .get_axis_num = in_x11_get_axis_num, + .get_button_num = in_x11_get_button_num, }; static void __attribute__((constructor)) From 15dbe443b0924ecf18de0b37e4ea0a02130eebaa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Nov 2021 15:27:44 +0900 Subject: [PATCH 1821/3664] [nq] Hook up the new input and config systems This gets nq in line with qw (and highlights more places than need merging, *sigh*) --- nq/include/client.h | 4 +- nq/source/cl_input.c | 106 +++++++++++++++++++++++++++++++++++++------ nq/source/cl_main.c | 50 ++++++++++++++++---- nq/source/host.c | 32 ++++++++++--- nq/source/sv_ded.c | 6 +++ 5 files changed, 168 insertions(+), 30 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index 6c10ef375..4a35a3770 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -284,6 +284,7 @@ struct cbuf_s; void CL_Init (struct cbuf_s *cbuf); void CL_InitCvars (void); void CL_ClearMemory (void); +int CL_ReadConfiguration (const char *cfg_name); void CL_EstablishConnection (const char *host); void CL_Signon1 (void); @@ -297,7 +298,8 @@ void CL_NextDemo (void); // cl_input -void CL_Input_Init (void); +void CL_Input_Init (struct cbuf_s *cbuf); +void CL_Input_Activate (void); void CL_SendCmd (void); void CL_SendMove (usercmd_t *cmd); diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 3f22eafee..021b73bed 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -36,12 +36,14 @@ #endif #include "QF/cmd.h" +#include "QF/console.h" #include "QF/cvar.h" #include "QF/input.h" #include "QF/keys.h" #include "QF/msg.h" #include "QF/sys.h" +#include "QF/input/event.h" #include "QF/plugin/vid_render.h" #include "compat.h" @@ -50,6 +52,42 @@ #include "nq/include/client.h" #include "nq/include/host.h" +int cl_game_context; +int cl_demo_context; +static int cl_event_id; + +in_axis_t viewdelta_position_forward = { + .mode = ina_accumulate, + .name = "move.forward", + .description = "Move forward (negative) or backward (positive)", +}; +in_axis_t viewdelta_position_side = { + .mode = ina_accumulate, + .name = "move.side", + .description = "Move right (positive) or left (negative)", +}; +in_axis_t viewdelta_position_up = { + .mode = ina_accumulate, + .name = "move.up", + .description = "Move up (positive) or down (negative)", +}; + +in_axis_t viewdelta_angles_pitch = { + .mode = ina_accumulate, + .name = "move.pitch", + .description = "Pitch axis", +}; +in_axis_t viewdelta_angles_yaw = { + .mode = ina_accumulate, + .name = "move.yaw", + .description = "Yaw axis", +}; +in_axis_t viewdelta_angles_roll = { + .mode = ina_accumulate, + .name = "move.roll", + .description = "Roll axis", +}; + in_button_t in_left = { .name = "left", .description = "When active the player is turning left" @@ -124,6 +162,16 @@ in_button_t in_mlook = { "+lookdown" }; +static in_axis_t *cl_in_axes[] = { + &viewdelta_position_forward, + &viewdelta_position_side, + &viewdelta_position_up, + &viewdelta_angles_pitch, + &viewdelta_angles_yaw, + &viewdelta_angles_roll, + 0, +}; + static in_button_t *cl_in_buttons[] = { &in_left, &in_right, @@ -269,11 +317,6 @@ CL_BaseMove (usercmd_t *cmd) if (freelook) V_StopPitchDrift (); - viewdelta.angles[0] = viewdelta.angles[1] = viewdelta.angles[2] = 0; - viewdelta.position[0] = viewdelta.position[1] = viewdelta.position[2] = 0; - - IN_Move (); - // adjust for chase camera angles /*FIXME:chase figure out just what this does and get it working if (cl.chase @@ -294,12 +337,19 @@ CL_BaseMove (usercmd_t *cmd) } */ - cmd->forwardmove += viewdelta.position[2] * m_forward->value; - cmd->sidemove += viewdelta.position[0] * m_side->value; - cmd->upmove += viewdelta.position[1]; - cl.viewstate.angles[PITCH] += viewdelta.angles[PITCH] * m_pitch->value; - cl.viewstate.angles[YAW] += viewdelta.angles[YAW] * m_yaw->value; - cl.viewstate.angles[ROLL] += viewdelta.angles[ROLL]; + cmd->forwardmove -= viewdelta_position_forward.value * m_forward->value; + cmd->sidemove += viewdelta_position_side.value * m_side->value; + cmd->upmove -= viewdelta_position_up.value; + cl.viewstate.angles[PITCH] -= viewdelta_angles_pitch.value * m_pitch->value; + cl.viewstate.angles[YAW] -= viewdelta_angles_yaw.value * m_yaw->value; + cl.viewstate.angles[ROLL] -= viewdelta_angles_roll.value * m_pitch->value; + + viewdelta_angles_pitch.value = 0; + viewdelta_angles_yaw.value = 0; + viewdelta_angles_roll.value = 0; + viewdelta_position_forward.value = 0; + viewdelta_position_side.value = 0; + viewdelta_position_up.value = 0; if (freelook && !(in_strafe.state & inb_down)) { cl.viewstate.angles[PITCH] @@ -359,12 +409,42 @@ CL_SendMove (usercmd_t *cmd) } } -void -CL_Input_Init (void) +static int +cl_event_handler (const IE_event_t *ie_event, void *unused) { + if (ie_event->type == ie_key) { + if (ie_event->key.code == QFK_ESCAPE) { + // FIXME this should bring up the menu + Con_SetState (con_active); + return 1; + } + } + return IN_Binding_HandleEvent (ie_event); +} + +void +CL_Input_Init (cbuf_t *cbuf) +{ + cl_event_id = IE_Add_Handler (cl_event_handler, 0); + + for (int i = 0; cl_in_axes[i]; i++) { + IN_RegisterAxis (cl_in_axes[i]); + } for (int i = 0; cl_in_buttons[i]; i++) { IN_RegisterButton (cl_in_buttons[i]); } + cl_game_context = IMT_CreateContext ("key_game"); + IMT_SetContextCbuf (cl_game_context, cbuf); + cl_demo_context = IMT_CreateContext ("key_demo"); + IMT_SetContextCbuf (cl_demo_context, cbuf); Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); } + +void +CL_Input_Activate (void) +{ + host_in_game = 1; + IMT_SetContext (cl_game_context); + IE_Set_Focus (cl_event_id); +} diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index c1c879cac..865da8507 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -106,21 +106,50 @@ CL_WriteConfiguration (void) // dedicated servers initialize the host but don't parse and set the // config.cfg cvars if (host_initialized && !isDedicated && cl_writecfg->int_val) { + plitem_t *config = PL_NewDictionary (0); //FIXME hashlinks + Cvar_SaveConfig (config); + IN_SaveConfig (config); + const char *path = va (0, "%s/quakeforge.cfg", qfs_gamedir->dir.def); QFile *f = QFS_WOpen (path, 0); if (!f) { Sys_Printf ("Couldn't write quakeforge.cfg.\n"); - return; + } else { + char *cfg = PL_WritePropertyList (config); + Qputs (f, cfg); + free (cfg); + Qclose (f); } - - //Key_WriteBindings (f); - Cvar_WriteVariables (f); - - Qclose (f); + PL_Free (config); } } +int +CL_ReadConfiguration (const char *cfg_name) +{ + QFile *cfg_file = QFS_FOpenFile (cfg_name); + if (!cfg_file) { + return 0; + } + size_t len = Qfilesize (cfg_file); + char *cfg = malloc (len + 1); + Qread (cfg_file, cfg, len); + cfg[len] = 0; + Qclose (cfg_file); + + plitem_t *config = PL_GetPropertyList (cfg, 0); // FIXME hashlinks + if (!config) { + return 0; + } + + Cvar_LoadConfig (config); + IN_LoadConfig (config); + + PL_Free (config); + return 1; +} + static void CL_Shutdown (void *data) { @@ -527,8 +556,11 @@ CL_SetState (cactive_t state) } CL_UpdateScreen (cl.time); } - if (con_module) - con_module->data->console->force_commandline = (state < ca_connected); + host_in_game = 0; + Con_SetState (state == ca_active ? con_inactive : con_fullscreen); + if (state != old_state && state == ca_active) { + CL_Input_Activate (); + } } static void @@ -566,7 +598,7 @@ CL_Init (cbuf_t *cbuf) Sbar_Init (); - CL_Input_Init (); + CL_Input_Init (cbuf); CL_TEnts_Init (); CL_ClearState (); diff --git a/nq/source/host.c b/nq/source/host.c index 2128e7f74..d4d33e10c 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -847,13 +847,33 @@ Host_Init_Memory (void) Sys_Printf ("%4.1f megabyte heap\n", host_mem_size->value); } -#if 0 + static void -host_keydest_callback (keydest_t kd, void *data) +Host_ExecConfig (cbuf_t *cbuf, int skip_quakerc) { - host_in_game = kd == key_game; + // quakeforge.cfg overrides quake.rc as it contains quakeforge-specific + // commands. If it doesn't exist, then this is the first time quakeforge + // has been used in this installation, thus any existing legacy config + // should be used to set up defaults on the assumption that the user has + // things set up to work with another (hopefully compatible) client + if (CL_ReadConfiguration ("quakeforge.cfg")) { + Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cmd_StuffCmds (cbuf); + COM_Check_quakerc ("startdemos", cbuf); + } else { + if (!skip_quakerc) { + Cbuf_InsertText (cbuf, "exec quake.rc\n"); + } + Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + // Reparse the command line for + commands. + // (sets still done, but it doesn't matter) + // (Note, no non-base commands exist yet) + if (skip_quakerc || !COM_Check_quakerc ("stuffcmds", 0)) { + Cmd_StuffCmds (cbuf); + } + } } -#endif + void Host_Init (void) { @@ -888,8 +908,6 @@ Host_Init (void) Mod_Init (); - //Key_KeydestCallback (host_keydest_callback, 0); - SV_Init (); if (cls.state != ca_dedicated) @@ -905,7 +923,7 @@ Host_Init (void) CL_UpdateScreen (cl.time); CL_UpdateScreen (cl.time); - COM_ExecConfig (host_cbuf, isDedicated || !cl_quakerc->int_val); + Host_ExecConfig (host_cbuf, isDedicated || !cl_quakerc->int_val); Hunk_AllocName (0, 0, "-HOST_HUNKLEVEL-"); host_hunklevel = Hunk_LowMark (0); diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index 6a854084a..80eefe3ec 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -118,6 +118,12 @@ CL_NextDemo (void) { } +__attribute__((const)) int +CL_ReadConfiguration (const char *cfg_name) +{ + return 0; +} + __attribute__((const)) int CL_ReadFromServer (void) { From b892ce637a3378e66a90c7a197bcc993f37fb87d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Nov 2021 15:33:49 +0900 Subject: [PATCH 1822/3664] [input] Nuke IN_Move from orbit gotta be sure :) On a serious note, it was always a problem in that it had client-specific code and concepts embedded in the libraries. --- include/QF/input.h | 16 +-------- libs/input/in_common.c | 52 +---------------------------- libs/video/targets/in_x11.c | 3 -- nq/source/cl_chase.c | 4 +-- nq/source/cl_main.c | 2 +- qw/source/cl_chase.c | 4 +-- qw/source/cl_main.c | 2 +- ruamoko/qwaq/builtins/qwaq-bi.c | 2 +- ruamoko/qwaq/builtins/qwaq-curses.c | 2 +- 9 files changed, 10 insertions(+), 77 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 7952d82aa..aa7c07a5b 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -49,11 +49,6 @@ typedef struct in_buttoninfo_s { #ifndef __QFCC__ -typedef struct { - vec3_t angles; - vec3_t position; -} viewdelta_t; - struct qf_fd_set; typedef struct in_driver_s { @@ -93,15 +88,13 @@ typedef struct in_device_s { void *event_data; } in_device_t; -extern viewdelta_t viewdelta; - #define freelook (in_mlook.state & 1 || in_freelook->int_val) struct cvar_s; int IN_RegisterDriver (in_driver_t *driver, void *data); void IN_DriverData (int handlle, void *data); -void IN_Init (struct cbuf_s *cbuf); +void IN_Init (void); void IN_Init_Cvars (void); struct plitem_s; void IN_SaveConfig (struct plitem_s *config); @@ -128,9 +121,6 @@ void IN_UpdateGrab (struct cvar_s *); void IN_ClearStates (void); -void IN_Move (void); // FIXME: was cmduser_t? -// add additional movement on top of the keyboard move cmd - extern struct cvar_s *in_grab; extern struct cvar_s *in_amp; extern struct cvar_s *in_pre_amp; @@ -139,10 +129,6 @@ extern struct cvar_s *in_mouse_accel; extern struct cvar_s *in_freelook; extern struct cvar_s *lookstrafe; -extern qboolean in_mouse_avail; -extern float in_mouse_x, in_mouse_y; - - #endif #endif//__QF_input_h diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 4cbb637c5..0d57b4e76 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -47,7 +47,6 @@ #include #include -#include "QF/cbuf.h" #include "QF/cvar.h" #include "QF/darray.h" #define IMPLEMENT_INPUT_Funcs @@ -71,8 +70,6 @@ typedef struct { static struct DARRAY_TYPE (in_regdriver_t) in_drivers = { .grow = 8 }; static struct DARRAY_TYPE (in_device_t) in_devices = { .grow = 8 }; -VISIBLE viewdelta_t viewdelta; - cvar_t *in_grab; VISIBLE cvar_t *in_amp; VISIBLE cvar_t *in_pre_amp; @@ -84,10 +81,6 @@ cvar_t *lookstrafe; int64_t in_timeout = 10000;//10ms default timeout -qboolean in_mouse_avail; -float in_mouse_x, in_mouse_y; -static float in_old_mouse_x, in_old_mouse_y; - int IN_RegisterDriver (in_driver_t *driver, void *data) { @@ -415,42 +408,6 @@ IN_LoadConfig (plitem_t *config) } } -void -IN_Move (void) -{ - //JOY_Move (); - - if (!in_mouse_avail) - return; - - in_mouse_x *= in_mouse_pre_amp->value * in_pre_amp->value; - in_mouse_y *= in_mouse_pre_amp->value * in_pre_amp->value; - - if (in_mouse_filter->int_val) { - in_mouse_x = (in_mouse_x + in_old_mouse_x) * 0.5; - in_mouse_y = (in_mouse_y + in_old_mouse_y) * 0.5; - - in_old_mouse_x = in_mouse_x; - in_old_mouse_y = in_mouse_y; - } - - in_mouse_x *= in_mouse_amp->value * in_amp->value; - in_mouse_y *= in_mouse_amp->value * in_amp->value; -#if 0 - if ((in_strafe.state & 1) || (lookstrafe->int_val && freelook)) - viewdelta.position[0] += in_mouse_x; - else - viewdelta.angles[YAW] -= in_mouse_x; - - if (freelook && !(in_strafe.state & 1)) { - viewdelta.angles[PITCH] += in_mouse_y; - } else { - viewdelta.position[2] -= in_mouse_y; - } -#endif - in_mouse_x = in_mouse_y = 0.0; -} - /* Called at shutdown */ static void IN_shutdown (void *data) @@ -467,7 +424,7 @@ IN_shutdown (void *data) } void -IN_Init (cbuf_t *cbuf) +IN_Init (void) { Sys_RegisterShutdown (IN_shutdown, 0); IMT_Init (); @@ -477,17 +434,11 @@ IN_Init (cbuf_t *cbuf) in_regdriver_t *rd = &in_drivers.a[i]; rd->driver.init (rd->data); } - //Key_Init (cbuf); - //JOY_Init (); - - in_mouse_x = in_mouse_y = 0.0; } void IN_Init_Cvars (void) { - //Key_Init_Cvars (); - //JOY_Init_Cvars (); in_grab = Cvar_Get ("in_grab", "0", CVAR_ARCHIVE, IN_UpdateGrab, "With this set to 1, quake will grab the mouse, " "preventing loss of input focus."); @@ -516,7 +467,6 @@ IN_ClearStates (void) rd->driver.clear_states (rd->data); } } - //Key_ClearStates (); } #ifdef HAVE_EVDEV diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 59308f52c..1898a2482 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -1035,7 +1035,6 @@ static void in_x11_shutdown (void *data) { Sys_MaskPrintf (SYS_vid, "in_x11_shutdown\n"); - in_mouse_avail = 0; if (x_disp) { // XAutoRepeatOn (x_disp); dga_off (); @@ -1129,8 +1128,6 @@ in_x11_init (void *data) X11_AddEvent (MotionNotify, &event_motion); x11_add_device (&x11_mouse_device); - - in_mouse_avail = 1; } Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, diff --git a/nq/source/cl_chase.c b/nq/source/cl_chase.c index 151a1d739..1b88e15c8 100644 --- a/nq/source/cl_chase.c +++ b/nq/source/cl_chase.c @@ -211,8 +211,8 @@ Chase_Update (void) // mouse and joystick controllers add to movement VectorSet (0, cl.viewstate.angles[1] - camera_angles[1], 0, dir); AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME - forward *= viewdelta.position[2] * m_forward->value; - right *= viewdelta.position[0] * m_side->value; + //forward *= viewdelta.position[2] * m_forward->value; FIXME + //right *= viewdelta.position[0] * m_side->value; FIXME dir = forward + right; cmd.forwardmove += dir[0]; cmd.sidemove -= dir[1]; diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 865da8507..488c86b5a 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -585,7 +585,7 @@ CL_Init (cbuf_t *cbuf) W_LoadWadFile ("gfx.wad"); VID_Init (basepal, colormap); - IN_Init (cbuf); + IN_Init (); R_Init (); r_data->lightstyle = cl.lightstyle; diff --git a/qw/source/cl_chase.c b/qw/source/cl_chase.c index 481002354..6c747f6f9 100644 --- a/qw/source/cl_chase.c +++ b/qw/source/cl_chase.c @@ -211,8 +211,8 @@ Chase_Update (void) // mouse and joystick controllers add to movement VectorSet (0, cl.viewstate.angles[1] - camera_angles[1], 0, dir); AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME - forward *= viewdelta.position[2] * m_forward->value; - right *= viewdelta.position[0] * m_side->value; + //forward *= viewdelta.position[2] * m_forward->value; FIXME + //right *= viewdelta.position[0] * m_side->value; FIXME dir = forward + right; cmd.forwardmove += dir[0]; cmd.sidemove -= dir[1]; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index a4a72ed45..f3eab261e 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1183,7 +1183,7 @@ CL_Init (void) W_LoadWadFile ("gfx.wad"); VID_Init (basepal, colormap); - IN_Init (cl_cbuf); + IN_Init (); Mod_Init (); R_Init (); r_data->lightstyle = cl.lightstyle; diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c index ee29dbc5b..1468380fa 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/qwaq-bi.c @@ -191,7 +191,7 @@ BI_Init (progs_t *pr) W_LoadWadFile ("gfx.wad"); VID_Init (basepal, colormap); - IN_Init (qwaq_cbuf); + IN_Init (); Mod_Init (); R_Init (); R_Progs_Init (pr); diff --git a/ruamoko/qwaq/builtins/qwaq-curses.c b/ruamoko/qwaq/builtins/qwaq-curses.c index 4f80e4683..b2aab8f94 100644 --- a/ruamoko/qwaq/builtins/qwaq-curses.c +++ b/ruamoko/qwaq/builtins/qwaq-curses.c @@ -89,7 +89,7 @@ qwaq_init_threads (qwaq_thread_set_t *thread_data) Sys_SetStdPrintf (qwaq_print); IN_Init_Cvars (); - IN_Init (qwaq_cbuf); + IN_Init (); for (size_t i = 1, thread_ind = 0; i < thread_data->size; i++) { qwaq_thread_t *thread = thread_data->a[i]; From 48ecfcf4113be2dbfb7419ff82c3dc9abfc9e663 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Nov 2021 15:42:47 +0900 Subject: [PATCH 1823/3664] [cexpr] Fix a naming issue with uint I didn't notice that uint is defined somewhere on Linux... until I tried compiling for windows (not defined). Use a define to keep the cast function naming nice. --- libs/util/cexpr-type.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 2b2fa70f4..9ecba1804 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -37,6 +37,9 @@ #include "libs/util/cexpr-parse.h" +#undef uint +#define uint unsigned + #define BINOP(pre, opname, type, op) \ static void \ pre##_##opname (const exprval_t *a, const exprval_t *b, exprval_t *c, \ From aa7fe66d9d1eca8689b804dc8575a8927ff66d25 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Nov 2021 11:55:32 +0900 Subject: [PATCH 1824/3664] [gamecode] Check resmap return before memset New gcc (11) Caught another issue (only one this time, which is nice). --- include/QF/progs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 47f7a80a2..d9c3aebf0 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1585,7 +1585,9 @@ void *PR_Resources_Find (progs_t *pr, const char *name); #define PR_RESNEW(map) \ ({ \ __auto_type t = PR_RESNEW_NC (map); \ - memset (t, 0, sizeof (*(map)._free)); \ + if (t) { \ + memset (t, 0, sizeof (*(map)._free)); \ + } \ t; \ }) From 83abdfa7b98b4e622c8d85ca32f204dfac9064b4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Nov 2021 11:57:16 +0900 Subject: [PATCH 1825/3664] [qw] Rmove include of rpc/types.h I have no idea why it was necessary, and certainly should not be now as any such portability issues should be tucked away such that the client code never sees such. --- config.d/header_files.m4 | 2 +- qw/source/cl_main.c | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/config.d/header_files.m4 b/config.d/header_files.m4 index 2e4e9a7ed..2e3de3103 100644 --- a/config.d/header_files.m4 +++ b/config.d/header_files.m4 @@ -12,7 +12,7 @@ AC_CHECK_HEADERS( dmedia/cdaudio.h dpmi.h dsound.h errno.h fcntl.h io.h \ ifaddrs.h libc.h limits.h linux/cdrom.h linux/joystick.h \ linux/soundcard.h machine/soundcard.h malloc.h math.h mgraph.h _mingw.h \ - netdb.h net/if.h netinet/in.h process.h pthread.h pwd.h rpc/types.h \ + netdb.h net/if.h netinet/in.h process.h pthread.h pwd.h \ setjmp.h signal.h stdarg.h stdio.h stdlib.h string.h strings.h \ sys/asoundlib.h sys/audioio.h sys/filio.h sys/ioctl.h sys/io.h sys/ipc.h \ sys/mman.h sys/param.h sys/poll.h sys/select.h sys/shm.h sys/signal.h \ diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index f3eab261e..9ece76d4e 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -49,9 +49,6 @@ #ifdef HAVE_WINSOCK_H # include #endif -#ifdef HAVE_RPC_TYPES_H -# include -#endif #if defined(_WIN32) && defined(HAVE_MALLOC_H) #include From b1d388563e5bb1c318fb80eeb505623dae615f57 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Nov 2021 12:08:58 +0900 Subject: [PATCH 1826/3664] [input] Don't specify ld flags for evdev lib libtool gets confused if the convenience library has normal library linker flags and fails to properly relink the main library when installing. --- libs/input/Makemodule.am | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index 774141caf..6e9db94df 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -8,7 +8,6 @@ in_evdev_src= \ libs/input/evdev/inputlib.c \ libs/input/in_evdev.c -libs_input_libinput_evdev_la_LDFLAGS= $(lib_ldflags) libs_input_libinput_evdev_la_LIBADD= libs_input_libinput_evdev_la_DEPENDENCIES= libs_input_libinput_evdev_la_CFLAGS= From e080bb333c861b4b38776893ee571f52ee811e12 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Nov 2021 13:52:40 +0900 Subject: [PATCH 1827/3664] [win] Update windows input for new binding system Seems to work nicely for keyboard (though key bindings are not cross-platform). Mouse not tested yet, and I expect there are problems with it for absolute inputs (yay mouse warp :P). --- libs/video/targets/context_win.c | 19 +- libs/video/targets/in_win.c | 723 ++++++++++++++++++++++--------- 2 files changed, 513 insertions(+), 229 deletions(-) diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index f58ec9d1c..283c4cdfe 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -202,21 +202,6 @@ Win_UpdateWindowStatus (int window_x, int window_y) } -static void -ClearAllStates (void) -{ - int i; - - // send an up event for each key, to make sure the server clears them all - for (i = 0; i < 256; i++) { - Key_Event (i, 0, false); - } - - Key_ClearStates (); - IN_ClearStates (); -} - - static qboolean VID_CheckAdequateMem (int width, int height) { @@ -700,7 +685,7 @@ VID_SetMode (int modenum, const byte *palette) SetForegroundWindow (win_mainwindow); } // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); + IN_ClearStates (); Sys_Printf ("%s\n", VID_GetModeDescription (vid_modenum)); @@ -774,7 +759,7 @@ Win_CreateWindow (int width, int height) SetForegroundWindow (win_mainwindow); } // fix the leftover Alt from any Alt-Tab or the like that switched us away - ClearAllStates (); + IN_ClearStates (); Sys_Printf ("%s\n", VID_GetModeDescription (vid_modenum)); diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index 588e58c35..e9cc1a331 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -46,6 +46,8 @@ #include "QF/sound.h" #include "QF/sys.h" +#include "QF/input/event.h" + #include "compat.h" #include "context_win.h" #include "in_win.h" @@ -60,9 +62,7 @@ HRESULT (WINAPI * pDirectInputCreate) (HINSTANCE hinst, DWORD dwVersion, // mouse local variables static unsigned uiWheelMessage; static unsigned mouse_buttons; -static unsigned mouse_oldbuttonstate; static POINT current_pos; -static float mx_accum, my_accum; static qboolean mouseinitialized; static qboolean restore_spi; static int originalmouseparms[3], newmouseparms[3] = { 0, 0, 1 }; @@ -82,6 +82,313 @@ static qboolean dinput; static qboolean vid_wassuspended = false; static qboolean win_in_game = false; +typedef struct win_device_s { + const char *name; + int num_axes; + int num_buttons; + in_axisinfo_t *axes; + in_buttoninfo_t *buttons; + void *event_data; + int devid; +} win_device_t; + +static int in_mouse_avail; + +#define WIN_MOUSE_BUTTONS 32 + +static int win_driver_handle = -1; +static in_buttoninfo_t win_key_buttons[256]; +static in_axisinfo_t win_mouse_axes[2]; +static in_buttoninfo_t win_mouse_buttons[WIN_MOUSE_BUTTONS]; +static const char *win_mouse_axis_names[] = {"M_X", "M_Y"}; +static const char *win_mouse_button_names[] = { + "M_BUTTON1", "M_BUTTON2", "M_BUTTON3", "M_WHEEL_UP", + "M_WHEEL_DOWN", "M_BUTTON6", "M_BUTTON7", "M_BUTTON8", + "M_BUTTON9", "M_BUTTON10", "M_BUTTON11", "M_BUTTON12", + "M_BUTTON13", "M_BUTTON14", "M_BUTTON15", "M_BUTTON16", + "M_BUTTON17", "M_BUTTON18", "M_BUTTON19", "M_BUTTON20", + "M_BUTTON21", "M_BUTTON22", "M_BUTTON23", "M_BUTTON24", + "M_BUTTON25", "M_BUTTON26", "M_BUTTON27", "M_BUTTON28", + "M_BUTTON29", "M_BUTTON30", "M_BUTTON31", "M_BUTTON32", +}; + +#define SIZE(x) (sizeof (x) / sizeof (x[0])) + +static unsigned short scantokey[128] = { +// 0 1 2 3 +// 4 5 6 7 +// 8 9 A B +// C D E F + 0, QFK_ESCAPE, '1', '2', + '3', '4', '5', '6', + '7', '8', '9', '0', + '-', '=', QFK_BACKSPACE, QFK_TAB, // 0 + 'q', 'w', 'e', 'r', + 't', 'y', 'u', 'i', + 'o', 'p', '[', ']', + QFK_RETURN, QFK_LCTRL, 'a', 's', // 1 + 'd', 'f', 'g', 'h', + 'j', 'k', 'l', ';', + '\'', '`', QFK_LSHIFT, '\\', + 'z', 'x', 'c', 'v', // 2 + 'b', 'n', 'm', ',', + '.', '/', QFK_RSHIFT, QFK_KP_MULTIPLY, + QFK_LALT, ' ', QFK_CAPSLOCK, QFK_F1, + QFK_F2, QFK_F3, QFK_F4, QFK_F5, // 3 + QFK_F6, QFK_F7, QFK_F8, QFK_F9, + QFK_F10, QFK_PAUSE, QFK_SCROLLOCK, QFK_KP7, + QFK_KP8, QFK_KP9, QFK_KP_MINUS, QFK_KP4, + QFK_KP5, QFK_KP6, QFK_KP_PLUS, QFK_KP1, // 4 + QFK_KP2, QFK_KP3, QFK_KP0, QFK_KP_PERIOD, + 0, 0, 0, QFK_F11, + QFK_F12, 0, 0, 0, + 0, 0, 0, 0, // 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static unsigned short shift_scantokey[128] = { +// 0 1 2 3 +// 4 5 6 7 +// 8 9 A B +// C D E F + 0, QFK_ESCAPE, '!', '@', // 0 + '#', '$', '%', '^', // 0 + '&', '*', '(', ')', // 0 + '_', '+', QFK_BACKSPACE, QFK_TAB, // 0 + 'Q', 'W', 'E', 'R', // 1 + 'T', 'Y', 'U', 'I', // 1 + 'O', 'P', '{', '}', // 1 + QFK_RETURN, QFK_LCTRL, 'A', 'S', // 1 + 'D', 'F', 'G', 'H', // 2 + 'J', 'K', 'L', ':', // 2 + '"', '~', QFK_LSHIFT, '|', // 2 + 'Z', 'X', 'C', 'V', // 2 + 'B', 'N', 'M', '<', // 3 + '>', '?', QFK_RSHIFT, QFK_KP_MULTIPLY,// 3 + QFK_LALT, ' ', QFK_CAPSLOCK, QFK_F1, // 3 + QFK_F2, QFK_F3, QFK_F4, QFK_F5, // 3 + QFK_F6, QFK_F7, QFK_F8, QFK_F9, // 4 + QFK_F10, QFK_PAUSE, QFK_SCROLLOCK, QFK_KP7, // 4 + QFK_KP8, QFK_KP9, QFK_KP_MINUS, QFK_KP4, // 4 + QFK_KP5, QFK_KP6, QFK_KP_PLUS, QFK_KP1, // 4 + QFK_KP2, QFK_KP3, QFK_KP0, QFK_KP_PERIOD,//5 + 0, 0, 0, QFK_F11, // 5 + QFK_F12, 0, 0, 0, // 5 + 0, 0, 0, 0, // 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 +}; + +static unsigned short ext_scantokey[128] = { +// 0 1 2 3 +// 4 5 6 7 +// 8 9 A B +// C D E F + 0, QFK_ESCAPE, '1', '2', + '3', '4', '5', '6',// 0 + '7', '8', '9', '0', + '-', '=', QFK_BACKSPACE, QFK_TAB, + 'q', 'w', 'e', 'r', + 't', 'y', 'u', 'i', // 1 + 'o', 'p', '[', ']', + QFK_KP_ENTER, QFK_RCTRL, 'a', 's', + 'd', 'f', 'g', 'h', + 'j', 'k', 'l', ';', // 2 + '\'', '`', QFK_LSHIFT, '\\', + 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', + '.', QFK_KP_DIVIDE, QFK_RSHIFT, '*', // 3 + QFK_RALT, ' ', QFK_CAPSLOCK, QFK_F1, + QFK_F2, QFK_F3, QFK_F4, QFK_F5, + QFK_F6, QFK_F7, QFK_F8, QFK_F9, + QFK_F10, QFK_NUMLOCK, 0, QFK_HOME, // 4 + QFK_UP, QFK_PAGEUP, '-', QFK_LEFT, + '5', QFK_RIGHT, '+', QFK_END, + QFK_DOWN, QFK_PAGEDOWN, QFK_INSERT, QFK_DELETE, + 0, 0, 0, QFK_F11, // 5 + QFK_F12, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static unsigned short shift_ext_scantokey[128] = { +// 0 1 2 3 +// 4 5 6 7 +// 8 9 A B +// C D E F + 0, QFK_ESCAPE, '!', '@', + '#', '$', '%', '^', + '&', '*', '(', ')', + '_', '+', QFK_BACKSPACE, QFK_ESCAPE, // 0 + 'Q', 'W', 'E', 'R', + 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', + QFK_KP_ENTER, QFK_RCTRL, 'A', 'S', // 1 + 'D', 'F', 'G', 'H', + 'J', 'K', 'L', ':', + '"', '~', QFK_LSHIFT, '|', + 'Z', 'X', 'C', 'V', // 2 + 'B', 'N', 'M', '<', + '>', QFK_KP_DIVIDE, QFK_RSHIFT, '*', + QFK_RALT, ' ', QFK_CAPSLOCK, QFK_F1, + QFK_F2, QFK_F3, QFK_F4, QFK_F5, + QFK_F6, QFK_F7, QFK_F8, QFK_F9, + QFK_F10, QFK_NUMLOCK, 0, QFK_HOME, // 4 + QFK_UP, QFK_PAGEUP, '-', QFK_LEFT, + '5', QFK_RIGHT, '+', QFK_END, + QFK_DOWN, QFK_PAGEDOWN, QFK_INSERT, QFK_DELETE, + 0, 0, 0, QFK_F11, // 5 + QFK_F12, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +#define ROTL(x,n) (((x)<<(n))|(x)>>(32-n)) + +/* + MapKey + + Map from windows to quake keynums +*/ +static void +MapKey (unsigned int keycode, int press, int *k, int *u) +{ + int extended; + int scan; + int key; + int uc; + unsigned long mask = ~1L; + static unsigned long shifts; + + extended = (keycode >> 24) & 1; + scan = (keycode >> 16) & 255; + + if (scan > 127) { + *u = *k = 0; + return; + } + + if (extended) + key = ext_scantokey[scan]; + else + key = scantokey[scan]; + + if (shifts & 0x03) { + if (extended) + uc = shift_ext_scantokey[scan]; + else + uc = shift_scantokey[scan]; + } else { + if (extended) + uc = ext_scantokey[scan]; + else + uc = scantokey[scan]; + } + + if (uc > 255) + uc = 0; + + switch (key) { + case QFK_RSHIFT: + shifts &= mask; + shifts |= press; + break; + case QFK_LSHIFT: + shifts &= ROTL(mask, 1); + shifts |= ROTL(press, 1); + break; + case QFK_RCTRL: + shifts &= ROTL(mask, 2); + shifts |= ROTL(press, 2); + break; + case QFK_LCTRL: + shifts &= ROTL(mask, 3); + shifts |= ROTL(press, 3); + break; + default: + break; + } + + Sys_MaskPrintf (SYS_vid, "%08x %d %02x %02lx %04x %c\n", + keycode, press, scan, shifts, + key, uc > 32 && uc < 127 ? uc : '#'); + *k = key; + *u = uc; +} + +static win_device_t win_keyboard_device = { + "core:keyboard", + 0, SIZE (win_key_buttons), + 0, win_key_buttons, +}; + +static win_device_t win_mouse_device = { + "core:mouse", + SIZE (win_mouse_axes), SIZE (win_mouse_buttons), + win_mouse_axes, win_mouse_buttons, +}; + +static IE_mouse_event_t win_mouse; +static IE_key_event_t win_key; + +static void +in_win_send_axis_event (int devid, in_axisinfo_t *axis) +{ + IE_event_t event = { + .type = ie_axis, + .when = Sys_LongTime (), + .axis = { + .data = win_mouse_device.event_data, + .devid = devid, + .axis = axis->axis, + .value = axis->value, + }, + }; + IE_Send_Event (&event); +} + +static int +in_win_send_mouse_event (IE_mouse_type type) +{ + IE_event_t event = { + .type = ie_mouse, + .when = Sys_LongTime (), + .mouse = win_mouse, + }; + event.mouse.type = type; + return IE_Send_Event (&event); +} + +static int +in_win_send_key_event (void) +{ + IE_event_t event = { + .type = ie_key, + .when = Sys_LongTime (), + .key = win_key, + }; + return IE_Send_Event (&event); +} + +static void +in_win_send_button_event (int devid, in_buttoninfo_t *button, void *event_data) +{ + IE_event_t event = { + .type = ie_button, + .when = Sys_LongTime (), + .button = { + .data = event_data, + .devid = devid, + .button = button->button, + .state = button->state, + }, + }; + IE_Send_Event (&event); +} + typedef struct MYDATA { LONG lX; // X axis goes here LONG lY; // Y axis goes here @@ -274,13 +581,13 @@ IN_InitDInput (void) return true; } -static void +static int IN_StartupMouse (void) { // HDC hdc; if (COM_CheckParm ("-nomouse")) - return; + return 0; mouseinitialized = true; @@ -315,12 +622,13 @@ IN_StartupMouse (void) } } - mouse_buttons = 32; + mouse_buttons = WIN_MOUSE_BUTTONS; // if a fullscreen video mode was set before the mouse was initialized, // set the mouse state appropriately if (mouseactivatetoggle) IN_ActivateMouse (); + return 1; } static void @@ -335,10 +643,11 @@ in_paste_buffer_f (void) if (th) { clipText = GlobalLock (th); if (clipText) { + win_key.code = 0; for (i = 0; clipText[i] && !strchr ("\n\r\b", clipText[i]); i++) { - Key_Event (QFK_UNKNOWN, clipText[i], 1); - Key_Event (QFK_UNKNOWN, 0, 0); + win_key.unicode = clipText[i]; + in_win_send_key_event (); } } GlobalUnlock (th); @@ -346,7 +655,7 @@ in_paste_buffer_f (void) CloseClipboard (); } } - +#if 0 static void win_keydest_callback (keydest_t key_dest, void *data) { @@ -359,19 +668,106 @@ win_keydest_callback (keydest_t key_dest, void *data) IN_ShowMouse (); } } +#endif + +static void +win_add_device (win_device_t *dev) +{ + for (int i = 0; i < dev->num_axes; i++) { + dev->axes[i].axis = i; + } + for (int i = 0; i < dev->num_buttons; i++) { + dev->buttons[i].button = i; + } + dev->devid = IN_AddDevice (win_driver_handle, dev, dev->name, dev->name); +} static void in_win_init (void *data) { uiWheelMessage = RegisterWindowMessage ("MSWHEEL_ROLLMSG"); - IN_StartupMouse (); + win_add_device (&win_keyboard_device); - Key_KeydestCallback (win_keydest_callback, 0); + if (IN_StartupMouse ()) { + win_add_device (&win_mouse_device); + } + + //Key_KeydestCallback (win_keydest_callback, 0); Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, "Paste the contents of the C&P buffer to the console"); } +static const char * +in_win_get_axis_name (void *data, void *device, int axis_num) +{ + win_device_t *dev = device; + const char *name = 0; + + if (dev == &win_keyboard_device) { + // keyboards don't have axes... + } else if (dev == &win_mouse_device) { + if ((unsigned) axis_num < SIZE (win_mouse_axis_names)) { + name = win_mouse_axis_names[axis_num]; + } + } + return name; +} + +static const char * +in_win_get_button_name (void *data, void *device, int button_num) +{ + win_device_t *dev = device; + const char *name = 0; + + if (dev == &win_keyboard_device) { + // FIXME + } else if (dev == &win_mouse_device) { + if ((unsigned) button_num < SIZE (win_mouse_button_names)) { + name = win_mouse_button_names[button_num]; + } + } + return name; +} + +static int +in_win_get_axis_num (void *data, void *device, const char *axis_name) +{ + win_device_t *dev = device; + int num = -1; + + if (dev == &win_keyboard_device) { + // keyboards don't have axes... + } else if (dev == &win_mouse_device) { + for (size_t i = 0; i < SIZE (win_mouse_axis_names); i++) { + if (strcasecmp (axis_name, win_mouse_axis_names[i]) == 0) { + num = i; + break; + } + } + } + return num; +} + +static int +in_win_get_button_num (void *data, void *device, const char *button_name) +{ + win_device_t *dev = device; + int num = -1; + + if (dev == &win_keyboard_device) { + // FIXME + } else if (dev == &win_mouse_device) { + for (size_t i = 0; i < SIZE (win_mouse_button_names); i++) { + if (strcasecmp (button_name, win_mouse_button_names[i]) == 0) { + num = i; + break; + } + } + } + return num; +} + static void in_win_shutdown (void *data) { @@ -393,43 +789,84 @@ in_win_shutdown (void *data) static void in_win_set_device_event_data (void *device, void *event_data, void *data) { + win_device_t *dev = device; + dev->event_data = event_data; } static void * in_win_get_device_event_data (void *device, void *data) { - return 0; + win_device_t *dev = device; + return dev->event_data; } static void -IN_MouseEvent (unsigned mstate) +event_motion (int dmx, int dmy, int mx, int my) { - unsigned i; + win_mouse_axes[0].value = dmx; + win_mouse_axes[1].value = dmy; - if (in_mouse_avail && !dinput) { - // perform button actions - for (i = 0; i < mouse_buttons; i++) { - if ((mstate & (1 << i)) && !(mouse_oldbuttonstate & (1 << i))) { - Key_Event (QFM_BUTTON1 + i, -1, true); - } + win_mouse.shift = win_key.shift; + win_mouse.x = mx; + win_mouse.x = my; + if (!in_win_send_mouse_event (ie_mousemove)) { + in_win_send_axis_event (win_mouse_device.devid, &win_mouse_axes[0]); + in_win_send_axis_event (win_mouse_device.devid, &win_mouse_axes[1]); + } +} - if (!(mstate & (1 << i)) && (mouse_oldbuttonstate & (1 << i))) { - Key_Event (QFM_BUTTON1 + i, -1, false); +static void +event_button (unsigned buttons) +{ + unsigned mask = win_mouse.buttons ^ buttons; + + if (!mask) { + // no change + return; + } + + // FIXME this won't be right if multiple buttons change state + int press = buttons & mask; + + for (int i = 0; i < WIN_MOUSE_BUTTONS; i++) { + win_mouse_buttons[i].state = buttons & (1 << i); + } + + win_mouse.buttons = buttons; + if (!in_win_send_mouse_event (press ? ie_mousedown : ie_mouseup)) { + for (int i = 0; i < WIN_MOUSE_BUTTONS; i++) { + if (!(mask & (1 << i))) { + continue; } + in_win_send_button_event (win_mouse_device.devid, + &win_mouse_buttons[i], + win_mouse_device.event_data); } + } +} - mouse_oldbuttonstate = mstate; +static void +event_key (LPARAM keydata, int pressed) +{ + int extended = (keydata >> 24) & 1; + // This assumes windows key codes are really only 7 bits (should be, since + // they seem to be regular scan codes) + int scan = (keydata >> 16) & 0x7f; + int key = (extended << 7) | scan; + MapKey (keydata, pressed, &win_key.code, &win_key.unicode); + //FIXME windows key codes and x11 key code's don't match, so binding + //configs are not cross-platform (is this actually a problem?) + win_key_buttons[key].state = pressed; + if (!pressed || !in_win_send_key_event ()) { + in_win_send_button_event (win_keyboard_device.devid, + &win_key_buttons[key], + win_keyboard_device.event_data); } } static void in_win_clear_states (void *data) { - if (in_mouse_avail) { - mx_accum = 0; - my_accum = 0; - mouse_oldbuttonstate = 0; - } } static void @@ -438,7 +875,6 @@ in_win_process_events (void *data) MSG msg; int mx, my; // HDC hdc; - unsigned i; DIDEVICEOBJECTDATA od; DWORD dwElements; HRESULT hr; @@ -509,194 +945,52 @@ in_win_process_events (void *data) } } - // perform button actions - for (i = 0; i < mouse_buttons; i++) { - if ((mstate_di & (1 << i)) && !(mouse_oldbuttonstate & (1 << i))) { - Key_Event (QFM_BUTTON1 + i, -1, true); - } - - if (!(mstate_di & (1 << i)) && (mouse_oldbuttonstate & (1 << i))) { - Key_Event (QFM_BUTTON1 + i, -1, false); - } - } - - mouse_oldbuttonstate = mstate_di; + event_button (mstate_di); } else { GetCursorPos (¤t_pos); - mx = current_pos.x - win_center_x + mx_accum; - my = current_pos.y - win_center_y + my_accum; - mx_accum = 0; - my_accum = 0; + mx = current_pos.x - win_center_x; + my = current_pos.y - win_center_y; } - in_mouse_x = mx; - in_mouse_y = my; - // if the mouse has moved, force it to the center, so there's room to move if (mx || my) { + //FIXME abs pos + event_motion (mx, my, 0, 0); SetCursorPos (win_center_x, win_center_y); } } -//========================================================================== - -static unsigned short scantokey[128] = { -// 0 1 2 3 4 5 6 7 -// 8 9 A B C D E F - 0, 27, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', QFK_BACKSPACE, 9, // 0 - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', 13, QFK_LCTRL, 'a', 's', // 1 - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'', '`', QFK_LSHIFT, '\\', 'z', 'x', 'c', 'v', // 2 - 'b', 'n', 'm', ',', '.', '/', QFK_RSHIFT, QFK_KP_MULTIPLY, - QFK_LALT, ' ', QFK_CAPSLOCK, QFK_F1, QFK_F2, QFK_F3, QFK_F4, QFK_F5, // 3 - QFK_F6, QFK_F7, QFK_F8, QFK_F9, QFK_F10, QFK_PAUSE, QFK_SCROLLOCK, QFK_KP7, - QFK_KP8, QFK_KP9, QFK_KP_MINUS, QFK_KP4, QFK_KP5, QFK_KP6, QFK_KP_PLUS, QFK_KP1, // 4 - QFK_KP2, QFK_KP3, QFK_KP0, QFK_KP_PERIOD, 0, 0, 0, QFK_F11, - QFK_F12, 0, 0, 0, 0, 0, 0, 0, // 5 - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static unsigned short shift_scantokey[128] = { -// 0 1 2 3 4 5 6 7 -// 8 9 A B C D E F - 0, 27, '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', QFK_BACKSPACE, 9, // 0 - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', 13, QFK_LCTRL, 'A', 'S', // 1 - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '"', '~', QFK_LSHIFT, '|', 'Z', 'X', 'C', 'V', // 2 - 'B', 'N', 'M', '<', '>', '?', QFK_RSHIFT, QFK_KP_MULTIPLY, - QFK_LALT, ' ', QFK_CAPSLOCK, QFK_F1, QFK_F2, QFK_F3, QFK_F4, QFK_F5, // 3 - QFK_F6, QFK_F7, QFK_F8, QFK_F9, QFK_F10, QFK_PAUSE, QFK_SCROLLOCK, QFK_KP7, - QFK_KP8, QFK_KP9, QFK_KP_MINUS, QFK_KP4, QFK_KP5, QFK_KP6, QFK_KP_PLUS, QFK_KP1, // 4 - QFK_KP2, QFK_KP3, QFK_KP0, QFK_KP_PERIOD, 0, 0, 0, QFK_F11, - QFK_F12, 0, 0, 0, 0, 0, 0, 0, // 5 - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static unsigned short ext_scantokey[128] = { -// 0 1 2 3 4 5 6 7 -// 8 9 A B C D E F - 0, 27, '1', '2', '3', '4', '5', '6', // 0 - '7', '8', '9', '0', '-', '=', QFK_BACKSPACE, 9, - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', // 1 - 'o', 'p', '[', ']', QFK_KP_ENTER, QFK_RCTRL, 'a', 's', - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 2 - '\'', '`', QFK_LSHIFT, '\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', QFK_KP_DIVIDE, QFK_RSHIFT, '*', // 3 - QFK_RALT, ' ', QFK_CAPSLOCK, QFK_F1, QFK_F2, QFK_F3, QFK_F4, QFK_F5, - QFK_F6, QFK_F7, QFK_F8, QFK_F9, QFK_F10, QFK_NUMLOCK, 0, QFK_HOME, // 4 - QFK_UP, QFK_PAGEUP, '-', QFK_LEFT, '5', QFK_RIGHT, '+', QFK_END, - QFK_DOWN, QFK_PAGEDOWN, QFK_INSERT, QFK_DELETE, 0, 0, 0, QFK_F11, // 5 - QFK_F12, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static unsigned short shift_ext_scantokey[128] = { -// 0 1 2 3 4 5 6 7 -// 8 9 A B C D E F - 0, 27, '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', QFK_BACKSPACE, 9, // 0 - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', QFK_KP_ENTER, QFK_RCTRL, 'A', 'S', // 1 - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '"', '~', QFK_LSHIFT, '|', 'Z', 'X', 'C', 'V', // 2 - 'B', 'N', 'M', '<', '>', QFK_KP_DIVIDE, QFK_RSHIFT, '*', - QFK_RALT, ' ', QFK_CAPSLOCK, QFK_F1, QFK_F2, QFK_F3, QFK_F4, QFK_F5, // 3 - QFK_F6, QFK_F7, QFK_F8, QFK_F9, QFK_F10, QFK_NUMLOCK, 0, QFK_HOME, - QFK_UP, QFK_PAGEUP, '-', QFK_LEFT, '5', QFK_RIGHT, '+', QFK_END, // 4 - QFK_DOWN, QFK_PAGEDOWN, QFK_INSERT, QFK_DELETE, 0, 0, 0, QFK_F11, - QFK_F12, 0, 0, 0, 0, 0, 0, 0, // 5 - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#define ROTL(x,n) (((x)<<(n))|(x)>>(32-n)) - -/* - MapKey - - Map from windows to quake keynums -*/ static void -MapKey (unsigned int keycode, int press, int *k, int *u) +in_win_axis_info (void *data, void *device, in_axisinfo_t *axes, int *numaxes) { - int extended; - int scan; - int key; - int uc; - unsigned long mask = ~1L; - static unsigned long shifts; - - extended = (keycode >> 24) & 1; - scan = (keycode >> 16) & 255; - - if (scan > 127) { - *u = *k = 0; + win_device_t *dev = device; + if (!axes) { + *numaxes = dev->num_axes; return; } - - if (extended) - key = ext_scantokey[scan]; - else - key = scantokey[scan]; - - if (shifts & 0x03) { - if (extended) - uc = shift_ext_scantokey[scan]; - else - uc = shift_scantokey[scan]; - } else { - if (extended) - uc = ext_scantokey[scan]; - else - uc = scantokey[scan]; + if (*numaxes > dev->num_axes) { + *numaxes = dev->num_axes; } - - if (uc > 255) - uc = 0; - - switch (key) { - case QFK_RSHIFT: - shifts &= mask; - shifts |= press; - break; - case QFK_LSHIFT: - shifts &= ROTL(mask, 1); - shifts |= ROTL(press, 1); - break; - case QFK_RCTRL: - shifts &= ROTL(mask, 2); - shifts |= ROTL(press, 2); - break; - case QFK_LCTRL: - shifts &= ROTL(mask, 3); - shifts |= ROTL(press, 3); - break; - default: - break; - } - - Sys_MaskPrintf (SYS_vid, "%08x %d %02x %02lx %04x %c\n", - keycode, press, scan, shifts, - key, uc > 32 && uc < 127 ? uc : '#'); - *k = key; - *u = uc; + memcpy (axes, dev->axes, *numaxes * sizeof (in_axisinfo_t)); } +static void +in_win_button_info (void *data, void *device, in_buttoninfo_t *buttons, + int *numbuttons) +{ + win_device_t *dev = device; + if (!buttons) { + *numbuttons = dev->num_buttons; + return; + } + if (*numbuttons > dev->num_buttons) { + *numbuttons = dev->num_buttons; + } + memcpy (buttons, dev->buttons, *numbuttons * sizeof (in_buttoninfo_t)); +} + +//========================================================================== + /* MAIN WINDOW */ @@ -769,19 +1063,18 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LONG lRet = 1; int fActive, fMinimized, temp; - int key, unicode; if (uMsg == uiWheelMessage) uMsg = WM_MOUSEWHEEL; switch (uMsg) { case WM_SETFOCUS: - Key_FocusEvent (1); + //Key_FocusEvent (1); break; case WM_KILLFOCUS: if (modestate == MS_FULLDIB) ShowWindow (win_mainwindow, SW_SHOWMINNOACTIVE); - Key_FocusEvent (0); + //Key_FocusEvent (0); break; case WM_CREATE: break; @@ -793,14 +1086,12 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_KEYDOWN: case WM_SYSKEYDOWN: - MapKey (lParam, 1, &key, &unicode); - Key_Event (key, unicode, true); + event_key (lParam, 1); break; case WM_KEYUP: case WM_SYSKEYUP: - MapKey (lParam, 0, &key, &unicode); - Key_Event (key, unicode, false); + event_key (lParam, 0); break; case WM_SYSCHAR: @@ -825,7 +1116,7 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) temp |= 2; if (wParam & MK_MBUTTON) temp |= 4; - IN_MouseEvent (temp); + event_button (temp); break; @@ -833,13 +1124,13 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) // It's delta is either positive or neg, and we generate the proper // Event. case WM_MOUSEWHEEL: + temp = win_mouse.buttons & ~((1 << 3) | (1 << 4));; if ((short) HIWORD (wParam) > 0) { - Key_Event (QFM_WHEEL_UP, -1, true); - Key_Event (QFM_WHEEL_UP, -1, false); + event_button (temp | (1 << 3)); } else { - Key_Event (QFM_WHEEL_DOWN, -1, true); - Key_Event (QFM_WHEEL_DOWN, -1, false); + event_button (temp | (1 << 4)); } + event_button (temp); break; case WM_SIZE: @@ -891,12 +1182,20 @@ static in_driver_t in_win_driver = { .process_events = in_win_process_events, .clear_states = in_win_clear_states, //.grab_input = in_win_grab_input, + + .axis_info = in_win_axis_info, + .button_info = in_win_button_info, + + .get_axis_name = in_win_get_axis_name, + .get_button_name = in_win_get_button_name, + .get_axis_num = in_win_get_axis_num, + .get_button_num = in_win_get_button_num, }; static void __attribute__((constructor)) in_win_register_driver (void) { - IN_RegisterDriver (&in_win_driver, 0); + win_driver_handle = IN_RegisterDriver (&in_win_driver, 0); } From 88b39657941f3951bc8e008825c5dc7f5b25f23d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Nov 2021 22:36:19 +0900 Subject: [PATCH 1828/3664] [vulkan] Pick up vulkan.h from correct location Well... it could be done better, but this works for now assuming it's in /usr/include (and it's correct for mxe builts). Does need proper autoconfiscation, though. --- libs/video/renderer/vulkan/vkgen/Makemodule.am | 3 ++- libs/video/renderer/vulkan/vkgen/vulkan.r | 2 +- tools/cross/mingw/cross-make.sh | 2 +- tools/cross/mingw64/cross-make.sh | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index d7d2f5701..7ff0081d2 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -19,7 +19,8 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vktype.r \ libs/video/renderer/vulkan/vkgen/vulkan.r -VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen +VKGENUSRINC = /usr/include +VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen -I$(VKGENUSRINC) vkgen_dat_SOURCES=$(vkgen_dat_src) vkgen_obj=$(vkgen_dat_SOURCES:.r=.o) diff --git a/libs/video/renderer/vulkan/vkgen/vulkan.r b/libs/video/renderer/vulkan/vkgen/vulkan.r index a2a53be7c..b42b8e75c 100644 --- a/libs/video/renderer/vulkan/vkgen/vulkan.r +++ b/libs/video/renderer/vulkan/vkgen/vulkan.r @@ -1,3 +1,3 @@ #define __x86_64__ -#include +#include #include "QF/Vulkan/swapchain.h" diff --git a/tools/cross/mingw/cross-make.sh b/tools/cross/mingw/cross-make.sh index b7472edad..6d405a09e 100755 --- a/tools/cross/mingw/cross-make.sh +++ b/tools/cross/mingw/cross-make.sh @@ -14,4 +14,4 @@ export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH -make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ='$(top_builddir)/qwaq-cmd' $* +make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ='$(top_builddir)/qwaq-cmd' VKGENUSRINC=$MINGW_USR/include $* diff --git a/tools/cross/mingw64/cross-make.sh b/tools/cross/mingw64/cross-make.sh index b1888321f..0f3481592 100755 --- a/tools/cross/mingw64/cross-make.sh +++ b/tools/cross/mingw64/cross-make.sh @@ -14,4 +14,4 @@ export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH -make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ='$(top_builddir)/qwaq-cmd' $* +make PAK='$(top_builddir)/pak' QFCC='$(top_builddir)/qfcc' QWAQ='$(top_builddir)/qwaq-cmd' VKGENUSRINC=$MINGW_USR/include $* From ba8da88f5697e357ca2d27caf9b7a7c75c6f2eef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Nov 2021 12:13:46 +0900 Subject: [PATCH 1829/3664] [build] Update for autoconf 2.71 Only because I didn't appreciate the warnings about things being obsolete. --- INSTALL | 2 +- bootstrap | 6 +- config.d/asm.m4 | 12 +-- config.d/compiling.m4 | 37 +++---- config.d/fbdev.m4 | 30 ++---- config.d/header_files.m4 | 41 +++----- config.d/library_functions.m4 | 52 +++------- config.d/networking.m4 | 37 +++---- config.d/programs.m4 | 1 + config.d/pthread.m4 | 20 ++-- config.d/typedefs_structs_compiler.m4 | 135 ++++++++------------------ config.d/versions.m4 | 2 +- configure.ac | 8 +- m4/libFLAC.m4 | 12 +-- m4/libOggFLAC.m4 | 12 +-- m4/libcurl.m4 | 2 +- m4/ogg.m4 | 12 +-- m4/quakeforge.m4 | 41 +++----- m4/sdl.m4 | 12 +-- m4/vorbis.m4 | 12 +-- 20 files changed, 167 insertions(+), 319 deletions(-) diff --git a/INSTALL b/INSTALL index 4538b8716..a2a11be9a 100644 --- a/INSTALL +++ b/INSTALL @@ -20,7 +20,7 @@ necessary packages installed. \section req-pack Required Packages The following packages are required to build QuakeForge: -\li GNU autoconf 2.50 or later +\li GNU autoconf 2.71 or later \li GNU automake 1.6 or later \li GNU libtool 1.4 or later \li GNU bison 2.6 or later diff --git a/bootstrap b/bootstrap index abd34252f..805df70d8 100755 --- a/bootstrap +++ b/bootstrap @@ -71,11 +71,11 @@ if test -n "$ac" ; then AC_VER_MINOR=`echo $AC_VER | cut -f2 -d'.' | sed 's/[^0-9]*$//'` if test "$AC_VER_MAJOR" -lt "2" ; then - errors="Autoconf 2.61 or greater needed to build configure.\n$errors" + errors="Autoconf 2.71 or greater needed to build configure.\n$errors" fi - if test "$AC_VER_MAJOR" -eq "2" -a "$AC_VER_MINOR" -lt "61" ; then - errors="Autoconf 2.61 or greater needed to build configure.\n$errors" + if test "$AC_VER_MAJOR" -eq "2" -a "$AC_VER_MINOR" -lt "71" ; then + errors="Autoconf 2.71 or greater needed to build configure.\n$errors" fi fi else diff --git a/config.d/asm.m4 b/config.d/asm.m4 index 79e5ceea8..33f249096 100644 --- a/config.d/asm.m4 +++ b/config.d/asm.m4 @@ -17,10 +17,8 @@ esac AM_CONDITIONAL(ASM_ARCH, test "x$ASM_ARCH" = "xyes") AC_MSG_CHECKING(for underscore prefix in names) -AC_TRY_LINK( - [asm(".long _bar"); - int bar;], - [], - AC_DEFINE(HAVE_SYM_PREFIX_UNDERSCORE, 1, [Define this if C symbols are prefixed with an underscore]) AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[asm(".long _bar"); int bar;]], [[]])], + [AC_DEFINE(HAVE_SYM_PREFIX_UNDERSCORE, 1, Define this if C symbols are prefixed with an underscore) AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no) +]) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index f0d108a27..5fc0ea03e 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -16,15 +16,16 @@ AC_MSG_RESULT([$leave_cflags_alone]) AC_MSG_CHECKING(for C99 inline) c99_inline=no -AC_TRY_LINK( - [inline int foo (int x) { return x * x; } - int (*bar) (int) = foo;], - [], - c99_inline=no - AC_MSG_RESULT(no), - c99_inline=yes - AC_DEFINE(HAVE_C99INLINE, extern, [define this if using c99 inline]) - AC_MSG_RESULT(yes) +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[inline int foo (int x) { return x * x; } + int (*bar) (int) = foo;]], + [[]])], + [c99_inline=no + AC_MSG_RESULT(no)], + [c99_inline=yes + AC_DEFINE(HAVE_C99INLINE, extern, define this if using c99 inline) + AC_MSG_RESULT(yes)] ) AH_VERBATIM([HAVE_C99INLINE], [#undef HAVE_C99INLINE @@ -169,25 +170,17 @@ if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then else save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $MORE_CFLAGS" - AC_TRY_COMPILE( - [], - [], - AC_MSG_RESULT(yes), - CFLAGS="$save_CFLAGS" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[AC_MSG_RESULT(yes)],[CFLAGS="$save_CFLAGS" AC_MSG_RESULT(no) - ) + ]) fi if test $CC_MAJ = 2 -a $CC_MIN = 96; then AC_MSG_CHECKING(if align options work) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -malign-loops=2 -malign-jumps=2 -malign-functions=2" - AC_TRY_COMPILE( - [], - [], - light="$light -malign-loops=2 -malign-jumps=2 -malign-functions=2" - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - ) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[light="$light -malign-loops=2 -malign-jumps=2 -malign-functions=2" + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) + ]) CFLAGS="$save_CFLAGS" CFLAGS="$CFLAGS $light" else diff --git a/config.d/fbdev.m4 b/config.d/fbdev.m4 index afc519003..8af090ab1 100644 --- a/config.d/fbdev.m4 +++ b/config.d/fbdev.m4 @@ -10,27 +10,15 @@ fi if test "x$HAVE_FBDEV" = xyes; then AC_MSG_CHECKING(for FB_AUX_VGA_PLANES_VGA4) - AC_TRY_COMPILE( - [#include "linux/fb.h"], - [int foo = FB_AUX_VGA_PLANES_VGA4;], - AC_DEFINE(HAVE_FB_AUX_VGA_PLANES_VGA4, 1, [Define this if you have FB_AUX_VGA_PLANES_VGA4]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - ) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "linux/fb.h"]], [[int foo = FB_AUX_VGA_PLANES_VGA4;]])],[AC_DEFINE(HAVE_FB_AUX_VGA_PLANES_VGA4, 1, Define this if you have FB_AUX_VGA_PLANES_VGA4) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) + ]) AC_MSG_CHECKING(for FB_AUX_VGA_PLANES_CFB4) - AC_TRY_COMPILE( - [#include "linux/fb.h"], - [int foo = FB_AUX_VGA_PLANES_CFB4;], - AC_DEFINE(HAVE_FB_AUX_VGA_PLANES_CFB4, 1, [Define this if you have FB_AUX_VGA_PLANES_CFB4]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - ) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "linux/fb.h"]], [[int foo = FB_AUX_VGA_PLANES_CFB4;]])],[AC_DEFINE(HAVE_FB_AUX_VGA_PLANES_CFB4, 1, Define this if you have FB_AUX_VGA_PLANES_CFB4) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) + ]) AC_MSG_CHECKING(for FB_AUX_VGA_PLANES_CFB8) - AC_TRY_COMPILE( - [#include "linux/fb.h"], - [int foo = FB_AUX_VGA_PLANES_CFB8;], - AC_DEFINE(HAVE_FB_AUX_VGA_PLANES_CFB8, 1, [Define this if you have FB_AUX_VGA_PLANES_CFB4]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - ) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "linux/fb.h"]], [[int foo = FB_AUX_VGA_PLANES_CFB8;]])],[AC_DEFINE(HAVE_FB_AUX_VGA_PLANES_CFB8, 1, Define this if you have FB_AUX_VGA_PLANES_CFB4) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) + ]) fi diff --git a/config.d/header_files.m4 b/config.d/header_files.m4 index 2e3de3103..93513dc8c 100644 --- a/config.d/header_files.m4 +++ b/config.d/header_files.m4 @@ -3,7 +3,6 @@ dnl Checks for header files. dnl ================================================================== AC_HEADER_DIRENT -AC_HEADER_STDC AC_HEADER_MAJOR AC_HEADER_SYS_WAIT AC_CHECK_HEADERS( @@ -33,37 +32,21 @@ fi AC_FUNC_ALLOCA AC_MSG_CHECKING(for fnmatch in fnmatch.h) -AC_TRY_COMPILE( - [#include "fnmatch.h"], - [int (*foo)() = fnmatch;], - AC_DEFINE(HAVE_FNMATCH_PROTO, 1, [Define this if fnmatch is prototyped in fnmatch.h]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "fnmatch.h"]], [[int (*foo)() = fnmatch;]])],[AC_DEFINE(HAVE_FNMATCH_PROTO, 1, Define this if fnmatch is prototyped in fnmatch.h) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) AC_MSG_CHECKING(for strnlen in string.h) -AC_TRY_COMPILE( - [#include "string.h"], - [int (*foo)() = strnlen;], - AC_DEFINE(HAVE_STRNLEN_PROTO, 1, [Define this if strnlen is prototyped in string.h]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "string.h"]], [[int (*foo)() = strnlen;]])],[AC_DEFINE(HAVE_STRNLEN_PROTO, 1, Define this if strnlen is prototyped in string.h) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) AC_MSG_CHECKING(for strndup in string.h) -AC_TRY_COMPILE( - [#include "string.h"], - [int (*foo)() = strndup;], - AC_DEFINE(HAVE_STRNDUP_PROTO, 1, [Define this if strndup is prototyped in string.h]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "string.h"]], [[int (*foo)() = strndup;]])],[AC_DEFINE(HAVE_STRNDUP_PROTO, 1, Define this if strndup is prototyped in string.h) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) AC_MSG_CHECKING(for strcasestr in string.h) -AC_TRY_COMPILE( - [#include "string.h"], - [int (*foo)() = strcasestr;], - AC_DEFINE(HAVE_STRCASESTR_PROTO, 1, [Define this if strcasestr is prototyped in string.h]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "string.h"]], [[int (*foo)() = strcasestr;]])],[AC_DEFINE(HAVE_STRCASESTR_PROTO, 1, Define this if strcasestr is prototyped in string.h) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) diff --git a/config.d/library_functions.m4 b/config.d/library_functions.m4 index c071dfa94..533e5cb78 100644 --- a/config.d/library_functions.m4 +++ b/config.d/library_functions.m4 @@ -5,7 +5,7 @@ dnl ================================================================== AC_FUNC_ALLOCA AC_FUNC_MEMCMP AC_FUNC_MMAP -AC_TYPE_SIGNAL + AC_FUNC_VPRINTF AC_CHECK_FUNCS( access _access bsearch_r connect dlopen execvp fcntl ftime _ftime \ @@ -39,21 +39,13 @@ AC_SUBST(DL_LIBS) if test "x$DL_LIBS" != "x"; then AC_MSG_CHECKING([for RTLD_NOW]) -AC_TRY_COMPILE( - [#include ], - [int foo = RTLD_NOW], - AC_DEFINE(HAVE_RTLD_NOW, 1, [Define if you have RTLD_NOW.]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int foo = RTLD_NOW]])],[AC_DEFINE(HAVE_RTLD_NOW, 1, Define if you have RTLD_NOW.) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) AC_MSG_CHECKING([for RTLD_DEEPBIND]) -AC_TRY_COMPILE( - [#include ], - [int foo = RTLD_DEEPBIND], - AC_DEFINE(HAVE_RTLD_DEEPBIND, 1, [Define if you have RTLD_DEEPBIND.]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int foo = RTLD_DEEPBIND]])],[AC_DEFINE(HAVE_RTLD_DEEPBIND, 1, Define if you have RTLD_DEEPBIND.) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) fi dnl Checks for stricmp/strcasecmp @@ -81,36 +73,24 @@ fi AC_CHECK_FUNCS(usleep) AC_MSG_CHECKING(for fnmatch) -AC_TRY_LINK( - [], - [fnmatch();], - BUILD_FNMATCH=no - AC_MSG_RESULT(yes), - BUILD_FNMATCH=yes +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[fnmatch();]])],[BUILD_FNMATCH=no + AC_MSG_RESULT(yes)],[BUILD_FNMATCH=yes AC_MSG_RESULT(no) -) +]) AM_CONDITIONAL(BUILD_FNMATCH, test "x$BUILD_FNMATCH" = "xyes") AC_MSG_CHECKING(for opendir) -AC_TRY_LINK( - [], - [opendir();], - BUILD_DIRENT=no - AC_MSG_RESULT(yes), - BUILD_DIRENT=yes +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[opendir();]])],[BUILD_DIRENT=no + AC_MSG_RESULT(yes)],[BUILD_DIRENT=yes AC_MSG_RESULT(no) -) +]) AM_CONDITIONAL(BUILD_DIRENT, test "x$BUILD_DIRENT" = "xyes") AC_MSG_CHECKING(for getopt_long) -AC_TRY_LINK( - [], - [getopt_long();], - BUILD_GETOPT=no - AC_MSG_RESULT(yes), - BUILD_GETOPT=yes +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[getopt_long();]])],[BUILD_GETOPT=no + AC_MSG_RESULT(yes)],[BUILD_GETOPT=yes AC_MSG_RESULT(no) -) +]) AM_CONDITIONAL(BUILD_GETOPT, test "x$BUILD_GETOPT" = "xyes") AC_MSG_CHECKING(for log2f) diff --git a/config.d/networking.m4 b/config.d/networking.m4 index a7fb22783..74c214c83 100644 --- a/config.d/networking.m4 +++ b/config.d/networking.m4 @@ -60,19 +60,16 @@ fi AC_MSG_CHECKING([for connect in -lwsock32]) SAVELIBS="$LIBS" LIBS="$LIBS -lwsock32" -AC_TRY_LINK([ +AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include -], -[ +]], [[ connect(0, NULL, 42); -], - NET_LIBS="$NET_LIBS -lwsock32 -lwinmm" +]])],[NET_LIBS="$NET_LIBS -lwsock32 -lwinmm" ac_cv_func_connect=yes ac_cv_func_gethostbyname=yes HAVE_WSOCK=yes - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) LIBS="$SAVELIBS" AC_MSG_CHECKING(for UDP support) @@ -87,16 +84,13 @@ if test "x$ac_cv_func_connect" != "xyes"; then AC_MSG_CHECKING([for connect in -lwsock32]) SAVELIBS="$LIBS" LIBS="$LIBS -lwsock32" - AC_TRY_LINK([ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include - ], - [ + ]], [[ connect (0, NULL, 42); - ], - NET_LIBS="$NET_LIBS -lwsock32 -lwinmm" - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - ) + ]])],[NET_LIBS="$NET_LIBS -lwsock32 -lwinmm" + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) + ]) LIBS="$SAVELIBS" fi AC_SUBST(NET_LIBS) @@ -104,12 +98,9 @@ AC_SUBST(NET_LIBS) AC_MSG_CHECKING([for getifaddrs]) SAVELIBS="$LIBS" LIBS="$LIBS $NET_LIBS" -AC_TRY_LINK([], - [ +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[ getifaddrs (0); - ], - AC_DEFINE(HAVE_GETIFADDRS, 1, [Define this if you have getifaddrs()]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) + ]])],[AC_DEFINE(HAVE_GETIFADDRS, 1, Define this if you have getifaddrs()) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) LIBS="$SAVELIBS" diff --git a/config.d/programs.m4 b/config.d/programs.m4 index 439fb7c93..bcff065c5 100644 --- a/config.d/programs.m4 +++ b/config.d/programs.m4 @@ -32,6 +32,7 @@ AS_VERSION_COMPARE([$BISON_VER], [2.6], AC_MSG_RESULT([yes]) ) +AC_PROG_LEX(noyywrap) AM_PROG_LEX if echo $LEX | grep -v flex > /dev/null; then AC_MSG_ERROR(GNU flex is required but was not found) diff --git a/config.d/pthread.m4 b/config.d/pthread.m4 index 6fc05c13c..6ed5626a9 100644 --- a/config.d/pthread.m4 +++ b/config.d/pthread.m4 @@ -11,22 +11,14 @@ if test "x$ac_cv_header_pthread_h" = "xyes"; then ;; *openbsd*) LIBS="$LIBS -pthread" - AC_TRY_LINK( - [#include ], - [pthread_attr_t type; - pthread_attr_setstacksize(&type, 0x100000);], - [PTHREAD_LDFLAGS=-pthread], - [PTHREAD_LDFLAGS=-lpthread] - ) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[pthread_attr_t type; + pthread_attr_setstacksize(&type, 0x100000);]])],[PTHREAD_LDFLAGS=-pthread],[PTHREAD_LDFLAGS=-lpthread + ]) ;; *) LIBS="$LIBS -lpthread" - AC_TRY_LINK( - [#include ], - [pthread_attr_t type; - pthread_attr_setstacksize(&type, 0x100000);], - [PTHREAD_LDFLAGS=-lpthread], - [PTHREAD_LDFLAGS=-pthread] - ) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[pthread_attr_t type; + pthread_attr_setstacksize(&type, 0x100000);]])],[PTHREAD_LDFLAGS=-lpthread],[PTHREAD_LDFLAGS=-pthread + ]) ;; esac LIBS="$save_LIBS" diff --git a/config.d/typedefs_structs_compiler.m4 b/config.d/typedefs_structs_compiler.m4 index 8e6acac2e..c38e7c56c 100644 --- a/config.d/typedefs_structs_compiler.m4 +++ b/config.d/typedefs_structs_compiler.m4 @@ -5,29 +5,19 @@ dnl ================================================================== AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T -AC_STRUCT_ST_BLKSIZE -AC_HEADER_TIME AC_STRUCT_TM if test "x$ac_cv_header_unistd_h" = xyes; then AC_MSG_CHECKING(for _SC_PAGESIZE) -AC_TRY_COMPILE( - [#include ], - [int foo = _SC_PAGESIZE;], - AC_DEFINE(HAVE__SC_PAGESIZE,1,[Define this if you have _SC_PAGESIZE]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int foo = _SC_PAGESIZE;]])],[AC_DEFINE(HAVE__SC_PAGESIZE,1,Define this if you have _SC_PAGESIZE) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) fi AC_MSG_CHECKING(for __attribute__) -AC_TRY_COMPILE( - [static __attribute__ ((unused)) const char *foo = "bar";], - [], - AC_DEFINE(HAVE___ATTRIBUTE__) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[static __attribute__ ((unused)) const char *foo = "bar";]], [[]])],[AC_DEFINE(HAVE___ATTRIBUTE__) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) AH_VERBATIM([HAVE___ATTRIBUTE__], [/* Define this if the GCC __attribute__ keyword is available */ #undef HAVE___ATTRIBUTE__ @@ -36,14 +26,10 @@ AH_VERBATIM([HAVE___ATTRIBUTE__], #endif]) AC_MSG_CHECKING(for __attribute__ ((visibility))) -AC_TRY_COMPILE( - [void foo (void); - __attribute__ ((sivibility ("default"))) void foo (void) {}], - [], - AC_DEFINE(HAVE___ATTRIBUTE__VISIBILITY) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[void foo (void); + __attribute__ ((sivibility ("default"))) void foo (void) {}]], [[]])],[AC_DEFINE(HAVE___ATTRIBUTE__VISIBILITY) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) AH_VERBATIM([HAVE___ATTRIBUTE__VISIBILITY], [/* Define this if the GCC visibility __attribute__ is available */ #undef HAVE___ATTRIBUTE__VISIBILITY @@ -55,14 +41,10 @@ AH_VERBATIM([HAVE___ATTRIBUTE__VISIBILITY], if test "x$SYSTYPE" = "xWIN32"; then AC_MSG_CHECKING(for __attribute__ ((gcc_struct))) - AC_TRY_COMPILE( - [typedef struct { int foo; } - __attribute__ ((gcc_struct)) gcc_struct_test;], - [], - AC_DEFINE(HAVE___ATTRIBUTE__GCC_STRUCT) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - ) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[typedef struct { int foo; } + __attribute__ ((gcc_struct)) gcc_struct_test;]], [[]])],[AC_DEFINE(HAVE___ATTRIBUTE__GCC_STRUCT) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) + ]) fi AH_VERBATIM([HAVE___ATTRIBUTE__GCC_STRUCT], [/* Define this if the GCC gcc_struct __attribute__ is available */ @@ -74,13 +56,9 @@ AH_VERBATIM([HAVE___ATTRIBUTE__GCC_STRUCT], #endif]) AC_MSG_CHECKING(for __builtin_expect) -AC_TRY_LINK( - [int x;], - [if (__builtin_expect(!x, 1)) {}], - AC_DEFINE(HAVE___BUILTIN_EXPECT) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[int x;]], [[if (__builtin_expect(!x, 1)) {}]])],[AC_DEFINE(HAVE___BUILTIN_EXPECT) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) AH_VERBATIM([HAVE___BUILTIN_EXPECT], [/* Define this if the GCC __builtin_expect keyword is available */ #undef HAVE___BUILTIN_EXPECT @@ -89,78 +67,47 @@ AH_VERBATIM([HAVE___BUILTIN_EXPECT], #endif]) AC_MSG_CHECKING(for type of fpos_t) -AC_TRY_COMPILE( - [#include ], - [fpos_t x = 0], - AC_MSG_RESULT(off_t), - AC_DEFINE(HAVE_FPOS_T_STRUCT, 1, [Define this if FPOS_T is a struct]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[fpos_t x = 0]])],[AC_MSG_RESULT(off_t)],[AC_DEFINE(HAVE_FPOS_T_STRUCT, 1, Define this if FPOS_T is a struct) AC_MSG_RESULT(struct) -) +]) AC_MSG_CHECKING(for socklen_t in sys/types.h) -AC_TRY_COMPILE( - [#include ], - [ socklen_t x = 0;], - AC_DEFINE(HAVE_SOCKLEN_T, 1, [Define this if your system has socklen_t]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[socklen_t x = 0;]])],[AC_DEFINE(HAVE_SOCKLEN_T, 1, Define this if your system has socklen_t) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) dnl FreeBSD 4.0 has it in sys/socket.h AC_MSG_CHECKING(for socklen_t in sys/socket.h) - AC_TRY_COMPILE( - [#include - #include ], - [ socklen_t x = 0;], - AC_DEFINE(HAVE_SOCKLEN_T, 1, [Define this if your system has socklen_t]) AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - ) -) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], [[socklen_t x = 0;]])],[AC_DEFINE(HAVE_SOCKLEN_T, 1, Define this if your system has socklen_t) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) + ]) +]) if test "x$ac_cv_header_sys_uio_h" = xyes; then AC_MSG_CHECKING(for struct in_pktinfo) - AC_TRY_COMPILE( - [#include + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include #include - #include ], - [struct in_pktinfo x;], - AC_DEFINE(HAVE_IN_PKTINFO, 1, [Define this if your system has struct in_pktinfo]) - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) - ) + #include ]], [[struct in_pktinfo x;]])],[AC_DEFINE(HAVE_IN_PKTINFO, 1, Define this if your system has struct in_pktinfo) + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) + ]) fi AC_MSG_CHECKING(for size_t in sys/types.h) -AC_TRY_COMPILE( - [#include ], - [ size_t x = 0;], - AC_DEFINE(HAVE_SIZE_T, 1, [Define this if your system has size_t]) AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ size_t x = 0;]])],[AC_DEFINE(HAVE_SIZE_T, 1, Define this if your system has size_t) AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) dnl maybe these two (at least the 2nd) should be checked only if ipv6 is enabled? AC_MSG_CHECKING(for ss_len in struct sockaddr_storage) -AC_TRY_COMPILE( - [#include - #include ], - [ void f(void) { struct sockaddr_storage ss; ss.ss_len=0; }], - AC_DEFINE(HAVE_SS_LEN, 1, [Define this if you have ss_len member in struct sockaddr_storage (BSD)]) AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], [[ void f(void) { struct sockaddr_storage ss; ss.ss_len=0; }]])],[AC_DEFINE(HAVE_SS_LEN, 1, Define this if you have ss_len member in struct sockaddr_storage (BSD)) AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) AC_MSG_CHECKING(for sin6_len in struct sockaddr_in6) -AC_TRY_COMPILE( - [#include - #include ], - [ void f(void) { struct sockaddr_in6 s6; s6.sin6_len=0; }], - AC_DEFINE(HAVE_SIN6_LEN, 1, [Define this if you have sin6_len member in struct sockaddr_in6 (BSD)]) AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], [[ void f(void) { struct sockaddr_in6 s6; s6.sin6_len=0; }]])],[AC_DEFINE(HAVE_SIN6_LEN, 1, Define this if you have sin6_len member in struct sockaddr_in6 (BSD)) AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) AC_MSG_CHECKING(for sa_len in struct sockaddr) -AC_TRY_COMPILE( - [#include - #include ], - [ void f(void) { struct sockaddr sa; sa.sa_len=0; }], - AC_DEFINE(HAVE_SA_LEN, 1, [Define this if you have sa_len member in struct sockaddr (BSD)]) AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include + #include ]], [[ void f(void) { struct sockaddr sa; sa.sa_len=0; }]])],[AC_DEFINE(HAVE_SA_LEN, 1, Define this if you have sa_len member in struct sockaddr (BSD)) AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) diff --git a/config.d/versions.m4 b/config.d/versions.m4 index 7550013d6..32d6f85ae 100644 --- a/config.d/versions.m4 +++ b/config.d/versions.m4 @@ -15,7 +15,7 @@ AC_DEFINE_UNQUOTED(QW_VERSION, "$QW_VERSION", AC_DEFINE_UNQUOTED(QW_QSG_VERSION, "$QW_QSG_VERSION", [Define this to the QSG standard version you support in QuakeWorld]) -AC_ARG_ENABLE([version-info], AC_HELP_STRING([--enable-version-info=CURRENT:REVISION:AGE], +AC_ARG_ENABLE([version-info], AS_HELP_STRING([--enable-version-info=CURRENT:REVISION:AGE], [Override the value passed to libtool -version-info.]), [], [enable_version_info=1:0:0]) QUAKE_LIBRARY_VERSION_INFO=$enable_version_info diff --git a/configure.ac b/configure.ac index 17ad222cf..d90db713b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ dnl Process this file with autoconf to produce a configure script. -AC_PREREQ(2.61) +AC_PREREQ([2.71]) dnl This is the only place where the package name and version appear -AC_INIT([QuakeForge], m4_esyscmd([config.d/git-version-gen --prefix '' .tarball-version])) +AC_INIT([QuakeForge],m4_esyscmd(config.d/git-version-gen --prefix '' .tarball-version)) AM_INIT_AUTOMAKE([foreign subdir-objects]) dnl LT_INIT messes with CFLAGS (evil bastard) @@ -11,7 +11,7 @@ if test "x${CFLAGS-unset}" = xunset; then fi saved_CFLAGS="$CFLAGS" dnl LT_INIT([win32-dll]) -AM_PROG_LIBTOOL +LT_INIT CFLAGS="$saved_CFLAGS" AC_REVISION([$Revision$]) dnl @@ -23,7 +23,7 @@ AC_CANONICAL_HOST m4_include(config.d/versions.m4) -AC_LANG_C +AC_LANG([C]) if test "$x{AR-unset}" = xunset; then AR="ar" diff --git a/m4/libFLAC.m4 b/m4/libFLAC.m4 index 8f9ef741c..c43a0caa6 100644 --- a/m4/libFLAC.m4 +++ b/m4/libFLAC.m4 @@ -46,7 +46,7 @@ dnl dnl Now check if the installed libFLAC is sufficiently new. dnl rm -f conf.libFLACtest - AC_TRY_RUN([ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include @@ -58,7 +58,7 @@ int main () return 0; } -],, no_libFLAC=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) +]])],[],[no_libFLAC=yes],[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi @@ -74,11 +74,10 @@ int main () echo "*** Could not run libFLAC test program, checking why..." CFLAGS="$CFLAGS $LIBFLAC_CFLAGS" LIBS="$LIBS $LIBFLAC_LIBS" - AC_TRY_LINK([ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" +]], [[ return 0; ]])],[ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding libFLAC or finding the wrong" echo "*** version of libFLAC. If it is not finding libFLAC, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" @@ -86,8 +85,7 @@ int main () echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],[ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means libFLAC was incorrectly installed" echo "*** or that you have moved libFLAC since it was installed. In the latter case, you" echo "*** may want to edit the libFLAC-config script: $LIBFLAC_CONFIG" ]) diff --git a/m4/libOggFLAC.m4 b/m4/libOggFLAC.m4 index a04623f6c..eefc77b6a 100644 --- a/m4/libOggFLAC.m4 +++ b/m4/libOggFLAC.m4 @@ -46,7 +46,7 @@ dnl dnl Now check if the installed libOggFLAC is sufficiently new. dnl rm -f conf.libOggFLACtest - AC_TRY_RUN([ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include @@ -58,7 +58,7 @@ int main () return 0; } -],, no_libOggFLAC=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) +]])],[],[no_libOggFLAC=yes],[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi @@ -74,11 +74,10 @@ int main () echo "*** Could not run libOggFLAC test program, checking why..." CFLAGS="$CFLAGS $LIBOGGFLAC_CFLAGS" LIBS="$LIBS $LIBOGGFLAC_LIBS" - AC_TRY_LINK([ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" +]], [[ return 0; ]])],[ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding libOggFLAC or finding the wrong" echo "*** version of libOggFLAC. If it is not finding libOggFLAC, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" @@ -86,8 +85,7 @@ int main () echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],[ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means libOggFLAC was incorrectly installed" echo "*** or that you have moved libOggFLAC since it was installed. In the latter case, you" echo "*** may want to edit the libOggFLAC-config script: $LIBOGGFLAC_CONFIG" ]) diff --git a/m4/libcurl.m4 b/m4/libcurl.m4 index 01a0575cc..66857d6e7 100644 --- a/m4/libcurl.m4 +++ b/m4/libcurl.m4 @@ -61,7 +61,7 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP]) AC_ARG_WITH(libcurl, - AC_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]), + AS_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]), [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])]) if test "$_libcurl_with" != "no" ; then diff --git a/m4/ogg.m4 b/m4/ogg.m4 index 0e1f1abf5..87b018508 100644 --- a/m4/ogg.m4 +++ b/m4/ogg.m4 @@ -45,7 +45,7 @@ dnl dnl Now check if the installed Ogg is sufficiently new. dnl rm -f conf.oggtest - AC_TRY_RUN([ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include @@ -57,7 +57,7 @@ int main () return 0; } -],, no_ogg=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) +]])],[],[no_ogg=yes],[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi @@ -73,11 +73,10 @@ int main () echo "*** Could not run Ogg test program, checking why..." CFLAGS="$CFLAGS $OGG_CFLAGS" LIBS="$LIBS $OGG_LIBS" - AC_TRY_LINK([ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" +]], [[ return 0; ]])],[ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding Ogg or finding the wrong" echo "*** version of Ogg. If it is not finding Ogg, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" @@ -85,8 +84,7 @@ int main () echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],[ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means Ogg was incorrectly installed" echo "*** or that you have moved Ogg since it was installed." ]) CFLAGS="$ac_save_CFLAGS" diff --git a/m4/quakeforge.m4 b/m4/quakeforge.m4 index 5dad02d82..ce2d9b38b 100644 --- a/m4/quakeforge.m4 +++ b/m4/quakeforge.m4 @@ -5,9 +5,7 @@ dnl AC_HAVE_STRUCT_FIELD(struct, field, headers) AC_DEFUN([AC_HAVE_STRUCT_FIELD], [ define(cache_val, translit(ac_cv_type_$1_$2, [A-Z ], [a-z_])) AC_CACHE_CHECK([for $2 in $1], cache_val,[ -AC_TRY_COMPILE([$3],[$1 x; x.$2;], -cache_val=yes, -cache_val=no)]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$3]], [[$1 x; x.$2;]])],[cache_val=yes],[cache_val=no])]) if test "$cache_val" = yes; then define(foo, translit(HAVE_$1_$2, [a-z ], [A-Z_])) AC_DEFINE(foo, 1, [Define if $1 has field $2.]) @@ -20,18 +18,15 @@ dnl Checks if function/macro va_copy() is available dnl Defines HAVE_VA_COPY on success. AC_DEFUN([AC_FUNC_VA_COPY], [AC_CACHE_CHECK([for va_copy], ac_cv_func_va_copy, - [AC_TRY_LINK([ + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #ifdef HAVE_STDARG_H # include #else # include -#endif], - [ +#endif]], [[ va_list a, b; -va_copy(a, b);], - [ac_cv_func_va_copy=yes], - [ac_cv_func_va_copy=no])]) +va_copy(a, b);]])],[ac_cv_func_va_copy=yes],[ac_cv_func_va_copy=no])]) if test $ac_cv_func_va_copy = yes; then AC_DEFINE(HAVE_VA_COPY, 1, [Define if va_copy is available]) fi]) @@ -40,18 +35,15 @@ dnl Checks if function/macro __va_copy() is available dnl Defines HAVE__VA_COPY on success. AC_DEFUN([AC_FUNC__VA_COPY], [AC_CACHE_CHECK([for __va_copy], ac_cv_func__va_copy, - [AC_TRY_LINK([ + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #ifdef HAVE_STDARG_H # include #else # include -#endif], - [ +#endif]], [[ va_list a, b; -__va_copy(a, b);], - [ac_cv_func__va_copy=yes], - [ac_cv_func__va_copy=no])]) +__va_copy(a, b);]])],[ac_cv_func__va_copy=yes],[ac_cv_func__va_copy=no])]) if test $ac_cv_func__va_copy = yes; then AC_DEFINE(HAVE__VA_COPY, 1, [Define if __va_copy is available]) fi]) @@ -60,19 +52,16 @@ dnl Checks if va_list is an array dnl Defines VA_LIST_IS_ARRAY on success. AC_DEFUN([AC_TYPE_VA_LIST], [AC_CACHE_CHECK([if va_list is an array], ac_cv_type_va_list_array, - [AC_TRY_LINK([ + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #ifdef HAVE_STDARG_H # include #else # include #endif -], - [ +]], [[ va_list a, b; -a = b;], - [ac_cv_type_va_list_array=no], - [ac_cv_type_va_list_array=yes])]) +a = b;]])],[ac_cv_type_va_list_array=no],[ac_cv_type_va_list_array=yes])]) if test $ac_cv_type_va_list_array = yes; then AC_DEFINE(VA_LIST_IS_ARRAY, 1, [Define if va_list is an array]) fi]) @@ -179,13 +168,9 @@ AC_MSG_CHECKING(whether $1 works) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $1" qf_opt_ok=no -AC_TRY_COMPILE( - [], - [], - qf_opt_ok=yes - AC_MSG_RESULT(yes), - AC_MSG_RESULT(no) -) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[qf_opt_ok=yes + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +]) CFLAGS="$save_CFLAGS" if test "x$qf_opt_ok" = xyes; then true diff --git a/m4/sdl.m4 b/m4/sdl.m4 index 0928a9ddf..9018ad5e8 100644 --- a/m4/sdl.m4 +++ b/m4/sdl.m4 @@ -63,7 +63,7 @@ dnl Now check if the installed SDL is sufficiently new. (Also sanity dnl checks the results of sdl-config to some extent dnl rm -f conf.sdltest - AC_TRY_RUN([ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include @@ -120,7 +120,7 @@ int main (int argc, char *argv[]) } } -],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) +]])],[],[no_sdl=yes],[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" CXXFLAGS="$ac_save_CXXFLAGS" LIBS="$ac_save_LIBS" @@ -144,7 +144,7 @@ int main (int argc, char *argv[]) CFLAGS="$CFLAGS $SDL_CFLAGS" CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" - AC_TRY_LINK([ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include "SDL.h" @@ -152,8 +152,7 @@ int main(int argc, char *argv[]) { return 0; } #undef main #define main K_and_R_C_main -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" +]], [[ return 0; ]])],[ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding SDL or finding the wrong" echo "*** version of SDL. If it is not finding SDL, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" @@ -161,8 +160,7 @@ int main(int argc, char *argv[]) echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],[ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means SDL was incorrectly installed" echo "*** or that you have moved SDL since it was installed. In the latter case, you" echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) diff --git a/m4/vorbis.m4 b/m4/vorbis.m4 index 300cc6c7d..8071ab886 100644 --- a/m4/vorbis.m4 +++ b/m4/vorbis.m4 @@ -49,7 +49,7 @@ dnl dnl Now check if the installed Vorbis is sufficiently new. dnl rm -f conf.vorbistest - AC_TRY_RUN([ + AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include #include @@ -73,7 +73,7 @@ int main () return 0; } -],, no_vorbis=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) +]])],[],[no_vorbis=yes],[echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi @@ -89,11 +89,10 @@ int main () echo "*** Could not run Vorbis test program, checking why..." CFLAGS="$CFLAGS $VORBIS_CFLAGS" LIBS="$LIBS $VORBIS_LIBS $OGG_LIBS" - AC_TRY_LINK([ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" +]], [[ return 0; ]])],[ echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding Vorbis or finding the wrong" echo "*** version of Vorbis. If it is not finding Vorbis, you'll need to set your" echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" @@ -101,8 +100,7 @@ int main () echo "*** is required on your system" echo "***" echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],[ echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means Vorbis was incorrectly installed" echo "*** or that you have moved Vorbis since it was installed." ]) CFLAGS="$ac_save_CFLAGS" From 799d247e1af6b5b732b5e74df80510d02ddcdd57 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 Nov 2021 14:17:57 +0900 Subject: [PATCH 1830/3664] [build] Fix which obsolete warning bootstrap uses sh, so command should always be a thing. --- bootstrap | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bootstrap b/bootstrap index 805df70d8..6844d47a0 100755 --- a/bootstrap +++ b/bootstrap @@ -44,7 +44,7 @@ if test x`uname` = xDarwin ; then else libtoolize=libtoolize fi -lt=`which $libtoolize` +lt=`command -v $libtoolize --version` if test -n "$lt" ; then if test -x "$lt" ; then LTIZE_VER=`$libtoolize --version | head -1 | sed 's/.* \([1-9][0-9]*\(\.[1-9][0-9]*\)\(\.[1-9][0-9]*\)*\).*/\1/'` @@ -63,7 +63,7 @@ else fi # Check Autoconf version -ac=`which autoconf` +ac=`command -v autoconf` if test -n "$ac" ; then if test -x "$ac" ; then AC_VER=`autoconf --version | head -1 | sed 's/^[^0-9]*//'` @@ -82,7 +82,7 @@ else errors="Autoconf not found. QuakeForge git requires autoconf to bootstrap itself.\n$errors" fi -am=`which automake` +am=`command -v automake` if test -n "$am" ; then if test -x "$am" ; then AM_VER=`automake --version | head -1 | sed -e 's/automake (GNU automake) //' -e 's/\-p.*$//'` From 925a55f6cc55717ab8ad1cc1143d1547ed783739 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Nov 2021 11:33:58 +0900 Subject: [PATCH 1831/3664] [input] Allow drivers to initialize cvars early Input driver can now have an optional init_cvars function. This allows them to create all their cvars before the actual init pass thus avoiding some initialization order interdependency issues (in this case, fixing a segfault when starting x11 clients fullscreen due to the in_dga cvar not existing yet). --- include/QF/input.h | 1 + libs/input/in_common.c | 6 ++++++ libs/video/targets/in_x11.c | 5 ++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index aa7c07a5b..1c492efec 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -52,6 +52,7 @@ typedef struct in_buttoninfo_s { struct qf_fd_set; typedef struct in_driver_s { + void (*init_cvars) (void *data); void (*init) (void *data); void (*shutdown) (void *data); diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 0d57b4e76..f9d18a07c 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -456,6 +456,12 @@ IN_Init_Cvars (void) "mouse in_mouse_pre_amp multiplier"); lookstrafe = Cvar_Get ("lookstrafe", "0", CVAR_ARCHIVE, NULL, "when mlook/klook on player will strafe"); + for (size_t i = 0; i < in_drivers.size; i++) { + in_regdriver_t *rd = &in_drivers.a[i]; + if (rd->driver.init_cvars) { + rd->driver.init_cvars (rd->data); + } + } } void diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 1898a2482..5e2a93745 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -1059,7 +1059,7 @@ in_x11_get_device_event_data (void *device, void *data) } static void -in_x11_init_cvars (void) +in_x11_init_cvars (void *data) { in_snd_block = Cvar_Get ("in_snd_block", "0", CVAR_ARCHIVE, NULL, "block sound output on window focus loss"); @@ -1091,8 +1091,6 @@ in_x11_init (void *data) if (!x_win) Sys_Error ("IN: No window!!"); - in_x11_init_cvars (); - X11_OpenDisplay (); // call to increment the reference counter x11_fd = ConnectionNumber (x_disp); @@ -1140,6 +1138,7 @@ in_x11_clear_states (void *data) } static in_driver_t in_x11_driver = { + .init_cvars = in_x11_init_cvars, .init = in_x11_init, .shutdown = in_x11_shutdown, .set_device_event_data = in_x11_set_device_event_data, From 8988008ad6406a12df87bb47020cc0c859b5a6ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Nov 2021 20:55:20 +0900 Subject: [PATCH 1832/3664] [x11] Don't mess with the mouse when going fullscreen This was always a horrible hack just to get the screen centered on the window back when we were doing fullscreen badly. With my experiments with XInput, it has proven to be a liability (I'd forgotten it was even there until it started imposing a 2s delay to QF's startup). --- libs/video/targets/context_x11.c | 34 -------------------------------- 1 file changed, 34 deletions(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 5052fd3b3..170941385 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -335,37 +335,6 @@ X11_CreateNullCursor (void) XDefineCursor (x_disp, x_win, nullcursor); } -static Bool -check_mouse_event (Display *disp, XEvent *ev, XPointer arg) -{ - XMotionEvent *me = &ev->xmotion; - if (ev->type != MotionNotify) - return False; - if ((unsigned) me->x != viddef.width / 2 - || (unsigned) me->y != viddef.height / 2) - return False; - return True; -} - -static void -X11_SetMouse (void) -{ - XEvent ev; - - XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, 0, 0); - XWarpPointer (x_disp, None, x_win, 0, 0, 0, 0, - viddef.width / 2, viddef.height / 2); - //FIXME this should be done in a state machine that handles events without - //blocking - double start = Sys_DoubleTime (); - while (!XCheckIfEvent (x_disp, &ev, check_mouse_event, 0)) { - if (Sys_DoubleTime () - start > 2) { - break; - } - } - x_mouse_time = ev.xmotion.time; -} - #ifdef HAVE_VIDMODE static vec3_t * X11_GetGamma (void) @@ -499,12 +468,9 @@ X11_UpdateFullscreen (cvar_t *fullscreen) X11_RestoreVidMode (); set_fullscreen (0); IN_UpdateGrab (in_grab); - X11_SetMouse (); - return; } else { set_fullscreen (1); X11_SetVidMode (viddef.width, viddef.height); - X11_SetMouse (); IN_UpdateGrab (in_grab); } } From fe2dd013beb29ec6405b02c7921a93c74ca8c15f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Nov 2021 21:08:15 +0900 Subject: [PATCH 1833/3664] [x11] Clean out some unnecessary includes --- libs/video/targets/context_x11.c | 5 ----- libs/video/targets/in_x11.c | 1 - 2 files changed, 6 deletions(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 170941385..7d355ef36 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -55,11 +55,6 @@ #ifdef HAVE_VIDMODE # include -# ifdef DGA_OLD_HEADERS -# include -# else -# include -# endif #endif #include "QF/cmd.h" diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 5e2a93745..e02078464 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -55,7 +55,6 @@ #include #ifdef HAVE_DGA -# include # ifdef DGA_OLD_HEADERS # include # else From 95becc5c05b6866a476b3777e6a71cab6180fbf8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Nov 2021 21:09:00 +0900 Subject: [PATCH 1834/3664] [x11] Add some braces around an if block --- libs/video/targets/context_x11.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 7d355ef36..b5e8d4050 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -507,8 +507,9 @@ X11_CreateWindow (int width, int height) attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = x_cmap; - if (!attr.colormap) + if (!attr.colormap) { attr.colormap = XCreateColormap (x_disp, x_root, x_vis, AllocNone); + } attr.event_mask = X11_MASK; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; From 26a1f66b4e4ba1e13c85448858af03971a3adabb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Nov 2021 21:22:11 +0900 Subject: [PATCH 1835/3664] [x11] Split up in_x11_init into three stages There's now IN_X11_Preinit, IN_X11_Postinit (both for want of better names), and in_x11_init. The first two are for taking care of initialization that needs to be done before window creation and between window creation and mapping (ie, are very specific to X11 stuff) while in_x11_init takes care of the setup for the input system. This proved necessary in my XInput experimentation: a passive enter grab takes effect only when the pointer enters the window, thus setting up the grab with the pointer already in the window has no effect until the pointer leaves the window and returns. --- include/in_x11.h | 37 ++++++++++++++++++ libs/video/targets/context_x11.c | 6 ++- libs/video/targets/in_x11.c | 66 +++++++++++++++++--------------- 3 files changed, 78 insertions(+), 31 deletions(-) create mode 100644 include/in_x11.h diff --git a/include/in_x11.h b/include/in_x11.h new file mode 100644 index 000000000..a9b83cd77 --- /dev/null +++ b/include/in_x11.h @@ -0,0 +1,37 @@ +/* + in_x11.h + + X11 input handling + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/11/21 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __in_x11_h +#define __in_x11_h + +long IN_X11_Preinit (void); +void IN_X11_Postinit (void); + +#endif//__in_x11_h diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index b5e8d4050..923203f01 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -68,6 +68,7 @@ #include "context_x11.h" #include "dga_check.h" +#include "in_x11.h" #include "vid_internal.h" static void (*event_handlers[LASTEvent]) (XEvent *); @@ -510,11 +511,14 @@ X11_CreateWindow (int width, int height) if (!attr.colormap) { attr.colormap = XCreateColormap (x_disp, x_root, x_vis, AllocNone); } - attr.event_mask = X11_MASK; + attr.event_mask = X11_MASK | IN_X11_Preinit (); + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + x_win = XCreateWindow (x_disp, x_root, 0, 0, width, height, 0, x_visinfo->depth, InputOutput, x_vis, mask, &attr); + IN_X11_Postinit (); // Set window size hints SizeHints = XAllocSizeHints (); diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index e02078464..fb4193d1d 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -78,6 +78,7 @@ #include "compat.h" #include "context_x11.h" #include "dga_check.h" +#include "in_x11.h" #include "qfselect.h" #include "vid_internal.h" @@ -1040,7 +1041,6 @@ in_x11_shutdown (void *data) } if (in_mouse_accel && !in_mouse_accel->int_val) X11_RestoreMouseAcceleration (); - X11_CloseDisplay (); } static void @@ -1081,31 +1081,13 @@ x11_add_device (x11_device_t *dev) dev->devid = IN_AddDevice (x11_driver_handle, dev, dev->name, dev->name); } -static void -in_x11_init (void *data) +long +IN_X11_Preinit (void) { - // open the display if (!x_disp) Sys_Error ("IN: No display!!"); - if (!x_win) - Sys_Error ("IN: No window!!"); - X11_OpenDisplay (); // call to increment the reference counter - - x11_fd = ConnectionNumber (x_disp); - - { - int attribmask = CWEventMask; - - XWindowAttributes attribs_1; - XSetWindowAttributes attribs_2; - - XGetWindowAttributes (x_disp, x_win, &attribs_1); - - attribs_2.event_mask = attribs_1.your_event_mask | X11_INPUT_MASK; - - XChangeWindowAttributes (x_disp, x_win, attribmask, &attribs_2); - } + long event_mask = X11_INPUT_MASK; X11_AddEvent (KeyPress, &event_key); X11_AddEvent (KeyRelease, &event_key); @@ -1114,21 +1096,45 @@ in_x11_init (void *data) X11_AddEvent (SelectionNotify, &selection_notify); X11_AddEvent (EnterNotify, &enter_notify); - x11_add_device (&x11_keyboard_device); - if (!COM_CheckParm ("-nomouse")) { - dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); - Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", dga_avail); - + X11_AddEvent (MotionNotify, &event_motion); X11_AddEvent (ButtonPress, &event_button); X11_AddEvent (ButtonRelease, &event_button); - X11_AddEvent (MotionNotify, &event_motion); - - x11_add_device (&x11_mouse_device); } Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, "Paste the contents of X's C&P buffer to the console"); + return event_mask; +} + +void +IN_X11_Postinit (void) +{ + if (!x_disp) + Sys_Error ("IN: No display!!"); + if (!x_win) + Sys_Error ("IN: No window!!"); + + if (!COM_CheckParm ("-nomouse")) { + dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); + Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", dga_avail); + dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); + Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", + dga_avail); + + } +} + +static void +in_x11_init (void *data) +{ + x11_fd = ConnectionNumber (x_disp); + + x11_add_device (&x11_keyboard_device); + + if (!COM_CheckParm ("-nomouse")) { + x11_add_device (&x11_mouse_device); + } } static void From 4944c40f8616f3a458631eccc782b86dba9d6fc1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Nov 2021 22:16:08 +0900 Subject: [PATCH 1836/3664] [x11] Remove the magic number for mouse buttons The current limit is still 32. Dealing with it properly will take some rather advanced messing with XInput, and will be necessary assuming non-XInput support is continued. --- libs/video/targets/in_x11.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index fb4193d1d..b7c1f962f 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -92,12 +92,13 @@ typedef struct x11_device_s { int devid; } x11_device_t; +#define X11_MOUSE_BUTTONS 32 // The X11 protocol supports only 256 keys static in_buttoninfo_t x11_key_buttons[256]; // X11 mice have only two axes (FIXME always true?) static in_axisinfo_t x11_mouse_axes[2]; -// FIXME assume up to 32 mouse buttons -static in_buttoninfo_t x11_mouse_buttons[32]; +// FIXME assume up to 32 mouse buttons (see X11_MOUSE_BUTTONS) +static in_buttoninfo_t x11_mouse_buttons[X11_MOUSE_BUTTONS]; static const char *x11_mouse_axis_names[] = {"M_X", "M_Y"}; static const char *x11_mouse_button_names[] = { "M_BUTTON1", "M_BUTTON2", "M_BUTTON3", "M_WHEEL_UP", @@ -787,8 +788,9 @@ event_button (XEvent *event) x_time = event->xbutton.time; + // x11 buttons are 1-based but = event->xbutton.button - 1; - if (but >= 32) { + if (but > X11_MOUSE_BUTTONS) { return; } From e45d19835c55259fdfea2de771e08126c29ae230 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Nov 2021 23:01:12 +0900 Subject: [PATCH 1837/3664] [x11] Add initial support for XInput2 Right now, only raw pointer motion and button events are handled, and the mouse escapes the window, and there are some issues with focus in focus-follows-mouse environments. However, this should be a much nicer setup than DGA. --- config.d/x11.m4 | 20 ++++ libs/video/targets/in_x11.c | 179 ++++++++++++++++++++++++++++++++++-- nq/source/Makemodule.am | 2 +- qw/source/Makemodule.am | 2 +- ruamoko/qwaq/Makemodule.am | 2 +- 5 files changed, 195 insertions(+), 10 deletions(-) diff --git a/config.d/x11.m4 b/config.d/x11.m4 index 8a9d24fda..caf3eb15d 100644 --- a/config.d/x11.m4 +++ b/config.d/x11.m4 @@ -33,6 +33,26 @@ if test "x$HAVE_VIDMODE" != xno; then fi AC_SUBST(VIDMODE_LIBS) +dnl Check for XInput2 support +AC_ARG_ENABLE(xi2, +[ --disable-xi2 do not use Xorg XInput2 extension], +HAVE_XI2=$enable_xi2, HAVE_XI2=auto) +if test "x$HAVE_XI2" != xno; then + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$X_CFLAGS $CPPFLAGS" + AC_CHECK_HEADER(X11/extensions/XInput2.h, + dnl Make sure the library works + [AC_CHECK_LIB(Xi, XIQueryVersion, + AC_DEFINE(HAVE_XI2, 1, [Define if you have the Xorg XInput2 extension]) + XI2_LIBS="-lXi",, + [$X_LIBS -lXext -lX11 $X_EXTRA_LIBS] + )],, + [#include ] + ) + CPPFLAGS="$save_CPPFLAGS" +fi +AC_SUBST(XI2_LIBS) + dnl Check for DGA support AC_ARG_ENABLE(dga, [ --disable-dga do not use XFree86 DGA extension], diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index b7c1f962f..951b038f1 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -59,7 +59,10 @@ # include # else # include +# endif #endif +#ifdef HAVE_XI2 +# include #endif #include "QF/cdaudio.h" @@ -135,6 +138,8 @@ static IE_mouse_event_t x11_mouse; static IE_key_event_t x11_key; static int input_grabbed = 0; +static int xi_opcode; +static int x11_have_xi; static int x11_fd; static int x11_driver_handle = -1; @@ -833,6 +838,93 @@ event_key (XEvent *event) } } +static void +xi_raw_motion (void *event) +{ + int root_x, root_y; + Window root_w, child_w; + XIRawEvent *re = event; + + x11_mouse_axes[0].value = re->raw_values[0]; + x11_mouse_axes[1].value = re->raw_values[1]; + XQueryPointer (x_disp, x_win, &root_w, &child_w, &root_x, &root_y, + &x11_mouse.x, &x11_mouse.y, &x11_mouse.shift); + // want only the modifier state + x11_mouse.shift &= 0xff; + if (!in_x11_send_mouse_event (ie_mousemove)) { + in_x11_send_axis_event (x11_mouse_device.devid, + &x11_mouse_axes[0]); + in_x11_send_axis_event (x11_mouse_device.devid, + &x11_mouse_axes[1]); + } +} + +static void +xi_raw_button (void *event, int press) +{ + + int root_x, root_y; + Window root_w, child_w; + unsigned button; + XIRawEvent *re = event; + + // x11 buttons are 1-based + button = re->detail - 1; + if (button > X11_MOUSE_BUTTONS) { + return; + } + XQueryPointer (x_disp, x_win, &root_w, &child_w, &root_x, &root_y, + &x11_mouse.x, &x11_mouse.y, &x11_mouse.shift); + // want only the modifier state + x11_mouse.shift &= 0xff; + if (press) { + x11_mouse.buttons |= 1 << button; + } else { + x11_mouse.buttons &= ~(1 << button); + } + if (!in_x11_send_mouse_event (press ? ie_mousedown : ie_mouseup)) { + in_x11_send_button_event (x11_mouse_device.devid, + &x11_mouse_buttons[button], + x11_mouse_device.event_data); + } +} + +static void +xi_raw_button_press (void *event) +{ + xi_raw_button (event, 1); +} + +static void +xi_raw_button_resease (void *event) +{ + xi_raw_button (event, 0); +} + +static void +event_generic (XEvent *event) +{ + // XI_LASTEVENT is the actual last event, not +1 + static void (*xi_event_handlers[XI_LASTEVENT + 1]) (void *) = { + [XI_RawMotion] = xi_raw_motion, + [XI_RawButtonPress] = xi_raw_button_press, + [XI_RawButtonRelease] = xi_raw_button_resease, + }; + XGenericEventCookie *cookie = &event->xcookie; + + if (cookie->type != GenericEvent || cookie->extension != xi_opcode + || !XGetEventData (x_disp, cookie)) { + return; + } + + if ((unsigned) cookie->evtype <= XI_LASTEVENT + && xi_event_handlers[cookie->evtype]) { + xi_event_handlers[cookie->evtype] (cookie->data); + } + + XFreeEventData (x_disp, cookie); +} + static void grab_error (int code, const char *device) { @@ -861,6 +953,7 @@ grab_error (int code, const char *device) static void in_x11_grab_input (void *data, int grab) { + return;//FIXME if (!x_disp || !x_win) return; @@ -1064,7 +1157,7 @@ in_x11_init_cvars (void *data) { in_snd_block = Cvar_Get ("in_snd_block", "0", CVAR_ARCHIVE, NULL, "block sound output on window focus loss"); - in_dga = Cvar_Get ("in_dga", "0", CVAR_ARCHIVE, in_dga_f, //FIXME 0 until X fixed + in_dga = Cvar_Get ("in_dga", "0", CVAR_ARCHIVE, in_dga_f, "DGA Input support"); in_mouse_accel = Cvar_Get ("in_mouse_accel", "1", CVAR_ARCHIVE, in_mouse_accel_f, @@ -1083,6 +1176,72 @@ x11_add_device (x11_device_t *dev) dev->devid = IN_AddDevice (x11_driver_handle, dev, dev->name, dev->name); } +static int +in_x11_check_xi2 (void) +{ + // Support XI 2.2 + int major = 2, minor = 2; + int event, error; + int ret; + + if (!XQueryExtension (x_disp, "XInputExtension", + &xi_opcode, &event, &error)) { + Sys_MaskPrintf (SYS_vid, "X Input extenions not available.\n"); + return 0; + } + if ((ret = XIQueryVersion (x_disp, &major, &minor)) == BadRequest) { + Sys_MaskPrintf (SYS_vid, + "No XI2 support. Server supports only %d.%d\n", + major, minor); + return 0; + } else if (ret != Success) { + Sys_MaskPrintf (SYS_vid, "in_x11_check_xi2: Xlib return bad: %d\n", + ret); + } + Sys_MaskPrintf (SYS_vid, "XI2 supported: version %d.%d\n", major, minor); + return 1; +} + +static void +in_x11_xi_select_events (void) +{ + //Raw events do not have target windows, so must specify the root + //window + //XISelectEvents(x_disp, x_root, &evmask, 1); + //XFlush (x_disp); +} + +static void +in_x11_xi_setup_grabs (void) +{ + // FIXME normal apps aren't supposed to care about the client pointer, + // but grabbing all master devices grabs the keyboard, too, which blocks + // alt-tab and the like + int dev; + XIGetClientPointer (x_disp, x_win, &dev); + + byte mask[(XI_LASTEVENT + 7) / 8] = {}; + XIEventMask evmask = { + .deviceid = dev, + .mask_len = sizeof (mask), + .mask = mask, + }; + XISetMask (mask, XI_RawMotion); + XISetMask (mask, XI_RawButtonPress); + XISetMask (mask, XI_RawButtonRelease); + + XIGrabModifiers modif = { + .modifiers = XIAnyModifier, + }; + + XIGrabEnter (x_disp, dev, x_win, None, XIGrabModeAsync, XIGrabModeAsync, + 0, &evmask, 1, &modif); + //FIXME doesn't seem to do anything. Is it actually necessary? + //here for reference + //XIGrabFocusIn (x_disp, dev, x_win, XIGrabModeAsync, XIGrabModeAsync, + // 0, &evmask, 1, &modif); +} + long IN_X11_Preinit (void) { @@ -1099,9 +1258,13 @@ IN_X11_Preinit (void) X11_AddEvent (EnterNotify, &enter_notify); if (!COM_CheckParm ("-nomouse")) { - X11_AddEvent (MotionNotify, &event_motion); - X11_AddEvent (ButtonPress, &event_button); - X11_AddEvent (ButtonRelease, &event_button); + if ((x11_have_xi = in_x11_check_xi2 ())) { + X11_AddEvent (GenericEvent, &event_generic); + } else { + X11_AddEvent (MotionNotify, &event_motion); + X11_AddEvent (ButtonPress, &event_button); + X11_AddEvent (ButtonRelease, &event_button); + } } Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, @@ -1118,12 +1281,14 @@ IN_X11_Postinit (void) Sys_Error ("IN: No window!!"); if (!COM_CheckParm ("-nomouse")) { - dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); - Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", dga_avail); + if (x11_have_xi) { + in_x11_xi_select_events (); + in_x11_xi_setup_grabs (); + } else { dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", dga_avail); - + } } } diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 1d3a70ebe..771009c44 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -134,7 +134,7 @@ nq_x11_libs= \ $(nq_client_LIBS) nq_x11_SOURCES= nq/source/sys_unix.c nq_x11_LDADD= $(nq_x11_libs) \ - $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ + $(VIDMODE_LIBS) $(DGA_LIBS) $(XI2_LIBS) $(X_LIBS) -lX11 \ $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(DL_LIBS) nq_x11_LDFLAGS= $(common_ldflags) nq_x11_DEPENDENCIES= $(nq_x11_libs) diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 61cf327c0..397652770 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -161,7 +161,7 @@ qw_client_x11_libs= \ $(qw_client_LIBS) qw_client_x11_SOURCES= qw/source/cl_sys_unix.c qw_client_x11_LDADD= $(qw_client_x11_libs) \ - $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ + $(VIDMODE_LIBS) $(DGA_LIBS) $(XI2_LIBS) $(X_LIBS) -lX11 \ $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(LIBCURL_LIBS) $(DL_LIBS) qw_client_x11_LDFLAGS= $(common_ldflags) qw_client_x11_DEPENDENCIES= $(qw_client_x11_libs) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 001671f8f..1d959e1c6 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -115,7 +115,7 @@ qwaq_x11_libs= \ $(qwaq_client_libs) ruamoko_qwaq_qwaq_x11_SOURCES=ruamoko/qwaq/builtins/qwaq.c ruamoko/qwaq/builtins/qwaq-bi.c ruamoko_qwaq_qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \ - $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ + $(VIDMODE_LIBS) $(DGA_LIBS) $(XI2_LIBS) $(X_LIBS) -lX11 \ $(X_EXTRA_LIBS) $(X_SHM_LIB) $(DL_LIBS) ruamoko_qwaq_qwaq_x11_LDFLAGS= ruamoko_qwaq_qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) From a32f83d50faef0eba7081bbad935ce23a5f2db40 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Nov 2021 23:23:16 +0900 Subject: [PATCH 1838/3664] whitespace --- libs/video/targets/in_x11.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 951b038f1..b771f3575 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -128,9 +128,9 @@ static x11_device_t x11_mouse_device = { x11_mouse_axes, x11_mouse_buttons, }; -cvar_t *in_snd_block; -cvar_t *in_dga; -cvar_t *in_mouse_accel; +cvar_t *in_snd_block; +cvar_t *in_dga; +cvar_t *in_mouse_accel; static qboolean dga_avail; static qboolean dga_active; @@ -150,7 +150,7 @@ dga_on (void) if (dga_avail && !dga_active) { int ret; ret = XF86DGADirectVideo (x_disp, DefaultScreen (x_disp), - XF86DGADirectMouse); + XF86DGADirectMouse); Sys_MaskPrintf (SYS_vid, "XF86DGADirectVideo returned %d\n", ret); if (ret) dga_active = true; From 4391b87d04581446747363bbf6e10c8d435263c3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 Nov 2021 23:37:42 +0900 Subject: [PATCH 1839/3664] [x11] Grab focus when the pointer enters the window This is necessary in focus-follows-mouse environments (at least for openbox, but it wouldn't surprise me if most other WMs behave the same way) because the WMs don't set focus when the pointer is grabbed (which XInput does before the WM sees the enter event). This is especially important when the window is fullscreen on a multi-monitor setup as there is no border to *maybe* catch the mouse before it enters the window. --- libs/video/targets/in_x11.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index b771f3575..50b12ce36 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -128,6 +128,7 @@ static x11_device_t x11_mouse_device = { x11_mouse_axes, x11_mouse_buttons, }; +cvar_t *in_auto_focus; cvar_t *in_snd_block; cvar_t *in_dga; cvar_t *in_mouse_accel; @@ -214,6 +215,9 @@ enter_notify (XEvent *event) x11_mouse.x = event->xmotion.x; x11_mouse.y = event->xmotion.y; + if (!x_have_focus && (!in_auto_focus || in_auto_focus->int_val)) { + XSetInputFocus (x_disp, x_win, RevertToPointerRoot, CurrentTime); + } } static void @@ -1155,6 +1159,11 @@ in_x11_get_device_event_data (void *device, void *data) static void in_x11_init_cvars (void *data) { + in_auto_focus = Cvar_Get ("in_auto_focus", "1", CVAR_ARCHIVE, 0, + "grab input focus when the mouse enters the" + " window when using xinput2 with certain" + " window managers using focus-follows-mouse" + " (eg, openbox)"); in_snd_block = Cvar_Get ("in_snd_block", "0", CVAR_ARCHIVE, NULL, "block sound output on window focus loss"); in_dga = Cvar_Get ("in_dga", "0", CVAR_ARCHIVE, in_dga_f, From f5b8fb0220d5589a95e07d5cadb341b38bacc929 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 07:35:54 +0900 Subject: [PATCH 1840/3664] [build] Relax autoconf version requirement It seems 2.71 only made things we use deprecated, and the new stuff was at least in 2.69. --- bootstrap | 6 +++--- configure.ac | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bootstrap b/bootstrap index 6844d47a0..902b8a69d 100755 --- a/bootstrap +++ b/bootstrap @@ -71,11 +71,11 @@ if test -n "$ac" ; then AC_VER_MINOR=`echo $AC_VER | cut -f2 -d'.' | sed 's/[^0-9]*$//'` if test "$AC_VER_MAJOR" -lt "2" ; then - errors="Autoconf 2.71 or greater needed to build configure.\n$errors" + errors="Autoconf 2.69 or greater needed to build configure.\n$errors" fi - if test "$AC_VER_MAJOR" -eq "2" -a "$AC_VER_MINOR" -lt "71" ; then - errors="Autoconf 2.71 or greater needed to build configure.\n$errors" + if test "$AC_VER_MAJOR" -eq "2" -a "$AC_VER_MINOR" -lt "69" ; then + errors="Autoconf 2.69 or greater needed to build configure.\n$errors" fi fi else diff --git a/configure.ac b/configure.ac index d90db713b..dc4839e7e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_PREREQ([2.71]) +AC_PREREQ([2.69]) dnl This is the only place where the package name and version appear AC_INIT([QuakeForge],m4_esyscmd(config.d/git-version-gen --prefix '' .tarball-version)) From 52c5f0545bcfd67e723f5ebbcdd0f3eabe216a51 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 13:06:08 +0900 Subject: [PATCH 1841/3664] [input] Add broadcast event for application window changes This is the first step in the long-sought goal of allowing the window size to change, but is required for passing on getting window position and size information (though size is in viddef, it makes sense to pass both together). --- include/QF/input/event.h | 8 ++++++++ ruamoko/qwaq/builtins/input.c | 1 + 2 files changed, 9 insertions(+) diff --git a/include/QF/input/event.h b/include/QF/input/event.h index 4b526fa61..de80c2b16 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -33,6 +33,11 @@ #include "QF/qtypes.h" +typedef struct { + int xpos, ypos; + int xlen, ylen; +} IE_app_window_event_t; + typedef enum { ies_shift = 1, ies_capslock = 2, @@ -84,6 +89,7 @@ typedef enum { ie_none, ie_gain_focus, ie_lose_focus, + ie_app_window, ie_add_device, ie_remove_device, ie_mouse, @@ -97,12 +103,14 @@ typedef enum { #define IE_broadcast_events (0 \ | (1 << ie_add_device) \ | (1 << ie_remove_device) \ + | (1 << ie_app_window) \ ) typedef struct IE_event_s { IE_event_type type; uint64_t when; union { + IE_app_window_event_t app_window; IE_mouse_event_t mouse; IE_key_event_t key; IE_axis_event_t axis; diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 43b6c78b0..0e7305047 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -543,6 +543,7 @@ qwaq_input_event_handler (const IE_event_t *ie_event, void *_res) case ie_none: case ie_gain_focus: case ie_lose_focus: + case ie_app_window: return 0; case ie_add_device: event.what = qe_dev_add; From 3af078b77a6457b2dc2508f8203bfbbf83bd9f89 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 13:11:37 +0900 Subject: [PATCH 1842/3664] [x11] Send app_window event when window moves This is needed for getting window position info into in_x11 without exposing more globals, and is likely to be useful for other things, especially as it doubles as a resize event when that's eventually supported. --- libs/video/targets/context_x11.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 923203f01..d5b6f8dd4 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -66,6 +66,8 @@ #include "QF/va.h" #include "QF/vid.h" +#include "QF/input/event.h" + #include "context_x11.h" #include "dga_check.h" #include "in_x11.h" @@ -164,6 +166,17 @@ configure_notify (XEvent *event) c->serial, c->send_event, c->event, c->window, c->x, c->y, c->width, c->height, c->border_width, c->above, c->override_redirect); + IE_event_t ie_event = { + .type = ie_app_window, + .when = Sys_LongTime (), + .app_window = { + .xpos = c->x, + .ypos = c->y, + .xlen = c->width, + .ylen = c->height, + }, + }; + IE_Send_Event (&ie_event); } qboolean From 3ac6d2aa220163a2c014594df571446597d40956 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 13:16:05 +0900 Subject: [PATCH 1843/3664] [x11] Use barriers to trap the pointer in the window This should be a much friendlier way of "grabbing" input, though I suspect that using raw keyboard events will result in a keyboard grab, which is part of the reason for wanting a friendly grab. There does seem to be a problem with the mouse sneaking out of the top-right and bottom-left corners. I currently suspect a bug in the X server, but further investigation is needed. --- config.d/x11.m4 | 20 ++++++ include/context_x11.h | 2 +- libs/video/targets/in_x11.c | 127 ++++++++++++++++++++++++++++++++++-- nq/source/Makemodule.am | 4 +- qw/source/Makemodule.am | 5 +- ruamoko/qwaq/Makemodule.am | 4 +- 6 files changed, 149 insertions(+), 13 deletions(-) diff --git a/config.d/x11.m4 b/config.d/x11.m4 index caf3eb15d..00903aa72 100644 --- a/config.d/x11.m4 +++ b/config.d/x11.m4 @@ -53,6 +53,26 @@ if test "x$HAVE_XI2" != xno; then fi AC_SUBST(XI2_LIBS) +dnl Check for XInput2 support +AC_ARG_ENABLE(xfixes, +[ --disable-xfixes do not use Xorg Xfixes extension], +HAVE_XFIXES=$enable_xfixes, HAVE_XFIXES=auto) +if test "x$HAVE_XFIXES" != xno; then + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$X_CFLAGS $CPPFLAGS" + AC_CHECK_HEADER(X11/extensions/Xfixes.h, + dnl Make sure the library works + [AC_CHECK_LIB(Xi, XIQueryVersion, + AC_DEFINE(HAVE_XFIXES, 1, [Define if you have the Xorg Xfixes extension]) + XFIXES_LIBS="-lXfixes",, + [$X_LIBS -lXext -lX11 $X_EXTRA_LIBS] + )],, + [#include ] + ) + CPPFLAGS="$save_CPPFLAGS" +fi +AC_SUBST(XFIXES_LIBS) + dnl Check for DGA support AC_ARG_ENABLE(dga, [ --disable-dga do not use XFree86 DGA extension], diff --git a/include/context_x11.h b/include/context_x11.h index 7f60f44fa..ec29458d6 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -41,7 +41,7 @@ #define X11_KEY_MASK (KeyPressMask | KeyReleaseMask) #define X11_MOUSE_MASK (ButtonPressMask | ButtonReleaseMask \ | PointerMotionMask) -#define X11_FOCUS_MASK (FocusChangeMask | EnterWindowMask) +#define X11_FOCUS_MASK (FocusChangeMask | EnterWindowMask | LeaveWindowMask) #define X11_INPUT_MASK (X11_KEY_MASK | X11_MOUSE_MASK | X11_FOCUS_MASK) #define X11_MASK (X11_WINDOW_MASK | X11_FOCUS_MASK | PointerMotionMask) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 50b12ce36..56728c3df 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -64,6 +64,9 @@ #ifdef HAVE_XI2 # include #endif +#ifdef HAVE_XFIXES +# include +#endif #include "QF/cdaudio.h" #include "QF/cmd.h" @@ -140,9 +143,16 @@ static IE_key_event_t x11_key; static int input_grabbed = 0; static int xi_opcode; +static int xf_opcode; +static PointerBarrier x11_left_barrier; +static PointerBarrier x11_right_barrier; +static PointerBarrier x11_top_barrier; +static PointerBarrier x11_bottom_barrier; static int x11_have_xi; static int x11_fd; static int x11_driver_handle = -1; +static int x11_event_handler_id; +static qboolean x11_have_pointer; static void dga_on (void) @@ -211,6 +221,7 @@ in_paste_buffer_f (void) static void enter_notify (XEvent *event) { + x11_have_pointer = true; x_time = event->xcrossing.time; x11_mouse.x = event->xmotion.x; @@ -220,6 +231,12 @@ enter_notify (XEvent *event) } } +static void +leave_notify (XEvent *event) +{ + x11_have_pointer = false; +} + static void XLateKey (XKeyEvent *ev, int *k, int *u) { @@ -905,6 +922,21 @@ xi_raw_button_resease (void *event) xi_raw_button (event, 0); } +static void +xi_barrier_hit (void *event) +{ + __auto_type be = *(XIBarrierEvent *) event; + + if (!x11_have_pointer || !input_grabbed) { + XIBarrierReleasePointer (x_disp, be.deviceid, be.barrier, be.eventid); + } +} + +static void +xi_barrier_leave (void *event) +{ +} + static void event_generic (XEvent *event) { @@ -913,6 +945,8 @@ event_generic (XEvent *event) [XI_RawMotion] = xi_raw_motion, [XI_RawButtonPress] = xi_raw_button_press, [XI_RawButtonRelease] = xi_raw_button_resease, + [XI_BarrierHit] = xi_barrier_hit, + [XI_BarrierLeave] = xi_barrier_leave, }; XGenericEventCookie *cookie = &event->xcookie; @@ -957,10 +991,14 @@ grab_error (int code, const char *device) static void in_x11_grab_input (void *data, int grab) { - return;//FIXME if (!x_disp || !x_win) return; + if (xf_opcode) { + input_grabbed = grab; + return; + } + if (vid_fullscreen) grab = grab || vid_fullscreen->int_val; @@ -1207,17 +1245,36 @@ in_x11_check_xi2 (void) Sys_MaskPrintf (SYS_vid, "in_x11_check_xi2: Xlib return bad: %d\n", ret); } - Sys_MaskPrintf (SYS_vid, "XI2 supported: version %d.%d\n", major, minor); + Sys_MaskPrintf (SYS_vid, "XI2 supported: version %d.%d, op: %d\n", + major, minor, xi_opcode); + + if (!XQueryExtension (x_disp, "XFIXES", &xf_opcode, &event, &error)) { + Sys_MaskPrintf (SYS_vid, "X fixes extenions not available.\n"); + return 0; + } + major = 5, minor = 0; + if (!XFixesQueryVersion (x_disp, &major, &minor) + || (major * 10 + minor) < 50) { + Sys_MaskPrintf (SYS_vid, "Need X fixes 5.0.\n"); + return 0; + } + Sys_MaskPrintf (SYS_vid, "XFixes supported: version %d.%d, op: %d\n", + major, minor, xf_opcode); return 1; } static void in_x11_xi_select_events (void) { - //Raw events do not have target windows, so must specify the root - //window - //XISelectEvents(x_disp, x_root, &evmask, 1); - //XFlush (x_disp); + byte mask[(XI_LASTEVENT + 7) / 8] = {}; + XIEventMask evmask = { + .deviceid = XIAllMasterDevices, + .mask_len = sizeof (mask), + .mask = mask, + }; + XISetMask (mask, XI_BarrierHit); + XISetMask (mask, XI_BarrierLeave); + XISelectEvents (x_disp, x_win, &evmask, 1); } static void @@ -1251,6 +1308,61 @@ in_x11_xi_setup_grabs (void) // 0, &evmask, 1, &modif); } +static void +in_x11_setup_barriers (int xpos, int ypos, int xlen, int ylen) +{ + if (x11_left_barrier > 0) { + XFixesDestroyPointerBarrier (x_disp, x11_left_barrier); + } + if (x11_right_barrier > 0) { + XFixesDestroyPointerBarrier (x_disp, x11_right_barrier); + } + if (x11_top_barrier > 0) { + XFixesDestroyPointerBarrier (x_disp, x11_top_barrier); + } + if (x11_bottom_barrier > 0) { + XFixesDestroyPointerBarrier (x_disp, x11_bottom_barrier); + } + + int lx = xpos; + int ty = ypos; + int rx = xpos + xlen - 1; + int by = ypos + ylen - 1; + x11_left_barrier = XFixesCreatePointerBarrier (x_disp, x_win, + lx, ty-1, lx, by+1, + BarrierPositiveX, 0, 0); + x11_right_barrier = XFixesCreatePointerBarrier (x_disp, x_win, + rx, ty-1, rx, by+1, + BarrierNegativeX, 0, 0); + x11_top_barrier = XFixesCreatePointerBarrier (x_disp, x_win, + lx-1, ty, rx+1, ty, + BarrierPositiveY, 0, 0); + x11_bottom_barrier = XFixesCreatePointerBarrier (x_disp, x_win, + lx-1, by, rx+1, by, + BarrierNegativeY, 0, 0); +} + +static void +x11_app_window (const IE_event_t *ie_event) +{ + __auto_type aw = ie_event->app_window; + in_x11_setup_barriers (aw.xpos, aw.ypos, aw.xlen, aw.ylen); +} + +static int +x11_event_handler (const IE_event_t *ie_event, void *unused) +{ + static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { + [ie_app_window] = x11_app_window, + }; + if (ie_event->type < 0 || ie_event->type >= ie_event_count + || !handlers[ie_event->type]) { + return 0; + } + handlers[ie_event->type] (ie_event); + return 1; +} + long IN_X11_Preinit (void) { @@ -1259,12 +1371,15 @@ IN_X11_Preinit (void) long event_mask = X11_INPUT_MASK; + x11_event_handler_id = IE_Add_Handler (x11_event_handler, 0); + X11_AddEvent (KeyPress, &event_key); X11_AddEvent (KeyRelease, &event_key); X11_AddEvent (FocusIn, &event_focusin); X11_AddEvent (FocusOut, &event_focusout); X11_AddEvent (SelectionNotify, &selection_notify); X11_AddEvent (EnterNotify, &enter_notify); + X11_AddEvent (LeaveNotify, &leave_notify); if (!COM_CheckParm ("-nomouse")) { if ((x11_have_xi = in_x11_check_xi2 ())) { diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 771009c44..61767a4df 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -134,8 +134,8 @@ nq_x11_libs= \ $(nq_client_LIBS) nq_x11_SOURCES= nq/source/sys_unix.c nq_x11_LDADD= $(nq_x11_libs) \ - $(VIDMODE_LIBS) $(DGA_LIBS) $(XI2_LIBS) $(X_LIBS) -lX11 \ - $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(DL_LIBS) + $(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \ + -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(DL_LIBS) nq_x11_LDFLAGS= $(common_ldflags) nq_x11_DEPENDENCIES= $(nq_x11_libs) diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 397652770..315fe6c37 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -161,8 +161,9 @@ qw_client_x11_libs= \ $(qw_client_LIBS) qw_client_x11_SOURCES= qw/source/cl_sys_unix.c qw_client_x11_LDADD= $(qw_client_x11_libs) \ - $(VIDMODE_LIBS) $(DGA_LIBS) $(XI2_LIBS) $(X_LIBS) -lX11 \ - $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(LIBCURL_LIBS) $(DL_LIBS) + $(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \ + -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(LIBCURL_LIBS) \ + $(DL_LIBS) qw_client_x11_LDFLAGS= $(common_ldflags) qw_client_x11_DEPENDENCIES= $(qw_client_x11_libs) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 1d959e1c6..12b71d6bd 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -115,8 +115,8 @@ qwaq_x11_libs= \ $(qwaq_client_libs) ruamoko_qwaq_qwaq_x11_SOURCES=ruamoko/qwaq/builtins/qwaq.c ruamoko/qwaq/builtins/qwaq-bi.c ruamoko_qwaq_qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \ - $(VIDMODE_LIBS) $(DGA_LIBS) $(XI2_LIBS) $(X_LIBS) -lX11 \ - $(X_EXTRA_LIBS) $(X_SHM_LIB) $(DL_LIBS) + $(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \ + -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(DL_LIBS) ruamoko_qwaq_qwaq_x11_LDFLAGS= ruamoko_qwaq_qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) From d8a836e9da3119949264967610f87e7d8649126c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 13:23:17 +0900 Subject: [PATCH 1844/3664] [input] Add broadcast events for app focus gain/loss These are for when the application itself gains or loses focus, rather than individual event handlers. --- include/QF/input/event.h | 4 ++++ ruamoko/qwaq/builtins/input.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/include/QF/input/event.h b/include/QF/input/event.h index de80c2b16..413685fc9 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -89,6 +89,8 @@ typedef enum { ie_none, ie_gain_focus, ie_lose_focus, + ie_app_gain_focus, + ie_app_lose_focus, ie_app_window, ie_add_device, ie_remove_device, @@ -103,6 +105,8 @@ typedef enum { #define IE_broadcast_events (0 \ | (1 << ie_add_device) \ | (1 << ie_remove_device) \ + | (1 << ie_app_gain_focus) \ + | (1 << ie_app_lose_focus) \ | (1 << ie_app_window) \ ) diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/input.c index 0e7305047..3c2d7a694 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/input.c @@ -543,6 +543,8 @@ qwaq_input_event_handler (const IE_event_t *ie_event, void *_res) case ie_none: case ie_gain_focus: case ie_lose_focus: + case ie_app_gain_focus: + case ie_app_lose_focus: case ie_app_window: return 0; case ie_add_device: From e8a7e8218e2192fc922b9825b954dbf1617b0c3e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 13:49:50 +0900 Subject: [PATCH 1845/3664] [x11] Check hit barrier is valid before releasing pointer It turns out to be possible to get a barrier event at the same time as a configure notify event (which rebuilds the barriers), and trying to release the pointer at such a time results in a bad barrier error and program crash. Thus check the event barrier against the currently existing barriers before attempting to release the pointer. This does mean that a better mechanism for sequencing window repositioning and barrier creation may be required. --- libs/video/targets/in_x11.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 56728c3df..f30832a9f 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -927,6 +927,15 @@ xi_barrier_hit (void *event) { __auto_type be = *(XIBarrierEvent *) event; + if (be.barrier != x11_left_barrier + && be.barrier != x11_right_barrier + && be.barrier != x11_top_barrier + && be.barrier != x11_bottom_barrier) { + Sys_MaskPrintf (SYS_vid, "xi_barrier_hit: bad barrier %ld\n", + be.barrier); + return; + } + if (!x11_have_pointer || !input_grabbed) { XIBarrierReleasePointer (x_disp, be.deviceid, be.barrier, be.eventid); } @@ -1245,8 +1254,8 @@ in_x11_check_xi2 (void) Sys_MaskPrintf (SYS_vid, "in_x11_check_xi2: Xlib return bad: %d\n", ret); } - Sys_MaskPrintf (SYS_vid, "XI2 supported: version %d.%d, op: %d\n", - major, minor, xi_opcode); + Sys_MaskPrintf (SYS_vid, "XI2 supported: version %d.%d, op: %d err: %d\n", + major, minor, xi_opcode, error); if (!XQueryExtension (x_disp, "XFIXES", &xf_opcode, &event, &error)) { Sys_MaskPrintf (SYS_vid, "X fixes extenions not available.\n"); @@ -1258,8 +1267,9 @@ in_x11_check_xi2 (void) Sys_MaskPrintf (SYS_vid, "Need X fixes 5.0.\n"); return 0; } - Sys_MaskPrintf (SYS_vid, "XFixes supported: version %d.%d, op: %d\n", - major, minor, xf_opcode); + Sys_MaskPrintf (SYS_vid, + "XFixes supported: version %d.%d, op: %d err: %d\n", + major, minor, xf_opcode, error); return 1; } From 67483eea37b9ecf23fb958b8776589b4ca684d13 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 14:07:30 +0900 Subject: [PATCH 1846/3664] [input] Make event names easy to print Handy for debugging and testing. --- include/QF/input/event.h | 17 +++---------- include/QF/input/event_names.h | 45 ++++++++++++++++++++++++++++++++++ libs/input/in_event.c | 6 +++++ 3 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 include/QF/input/event_names.h diff --git a/include/QF/input/event.h b/include/QF/input/event.h index 413685fc9..97902029d 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -85,23 +85,14 @@ typedef struct { int devid; } IE_device_event_t; +#define IE_EVENT(event) ie_##event, typedef enum { - ie_none, - ie_gain_focus, - ie_lose_focus, - ie_app_gain_focus, - ie_app_lose_focus, - ie_app_window, - ie_add_device, - ie_remove_device, - ie_mouse, - ie_key, - ie_axis, - ie_button, - +#include "QF/input/event_names.h" ie_event_count } IE_event_type; +extern const char *ie_event_names[]; + #define IE_broadcast_events (0 \ | (1 << ie_add_device) \ | (1 << ie_remove_device) \ diff --git a/include/QF/input/event_names.h b/include/QF/input/event_names.h new file mode 100644 index 000000000..9e2e5f150 --- /dev/null +++ b/include/QF/input/event_names.h @@ -0,0 +1,45 @@ +/* + event_names.h + + Input event enum names + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef IE_EVENT +#define IE_EVENT(event) +#endif + +IE_EVENT (none) +IE_EVENT (gain_focus) +IE_EVENT (lose_focus) +IE_EVENT (app_gain_focus) +IE_EVENT (app_lose_focus) +IE_EVENT (app_window) +IE_EVENT (add_device) +IE_EVENT (remove_device) +IE_EVENT (mouse) +IE_EVENT (key) +IE_EVENT (axis) +IE_EVENT (button) + +#undef IE_EVENT diff --git a/libs/input/in_event.c b/libs/input/in_event.c index 0fdfa0f9b..caa9e9ccb 100644 --- a/libs/input/in_event.c +++ b/libs/input/in_event.c @@ -43,6 +43,12 @@ #include "QF/input/event.h" +#define IE_EVENT(event) #event, +const char *ie_event_names[] = { +#include "QF/input/event_names.h" + 0 +}; + typedef struct { ie_handler_t *handler; void *data; From ce8eac5ca00b4aad73e0c48bebc75cd61f2c97c4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 14:07:55 +0900 Subject: [PATCH 1847/3664] [x11] Send app focus loss/gain events Other subsystems, especially low-level input drivers, need to know when the app has input focus. eg, as the evdev driver uses the raw stream from the kernel, which has no idea about X application focus (in fact, it seems the events are shared across multiple apps without any issue), the evdev driver sees all the events thus needs to know when to drop them. --- libs/video/targets/in_x11.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index f30832a9f..d936e08ae 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -639,11 +639,22 @@ XLateKey (XKeyEvent *ev, int *k, int *u) *u = unicode; } +static void +in_x11_send_focus_event (int gain) +{ + IE_event_t event = { + .type = gain ? ie_app_gain_focus : ie_app_lose_focus, + .when = Sys_LongTime (), + }; + IE_Send_Event (&event); +} + static void event_focusout (XEvent *event) { if (x_have_focus) { x_have_focus = false; + in_x11_send_focus_event (0); if (in_snd_block->int_val) { S_BlockSound (); CDAudio_Pause (); @@ -655,6 +666,7 @@ event_focusout (XEvent *event) static void event_focusin (XEvent *event) { + in_x11_send_focus_event (1); x_have_focus = true; if (in_snd_block->int_val) { S_UnblockSound (); From bc0451634a1584d3b763e10ad049bee848cce58c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 14:32:19 +0900 Subject: [PATCH 1848/3664] [input] Drop unfocused evdev axis/button events The kernel knows nothing about X11 application focus, so we need to take care of it ourselves. Device add/remove events are unaffected: the are always passed on. --- libs/input/in_evdev.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index a2c6a7faa..6666cedd7 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -56,6 +56,7 @@ typedef struct devmap_s { } devmap_t; static int evdev_driver_handle = -1; +static int evdev_have_focus; static PR_RESMAP (devmap_t) devmap; static devmap_t *devmap_list; @@ -96,6 +97,10 @@ in_evdev_get_device_event_data (void *device, void *data) static void in_evdev_axis_event (axis_t *axis, void *_dm) { + if (!evdev_have_focus) { + return; + } + devmap_t *dm = _dm; //Sys_Printf ("in_evdev_axis_event: %d %d\n", axis->num, axis->value); @@ -115,6 +120,10 @@ in_evdev_axis_event (axis_t *axis, void *_dm) static void in_evdev_button_event (button_t *button, void *_dm) { + if (!evdev_have_focus) { + return; + } + devmap_t *dm = _dm; //Sys_Printf ("in_evdev_button_event: %d %d\n", button->num, button->state); @@ -252,10 +261,25 @@ static in_driver_t in_evdev_driver = { .button_info = in_evdev_button_info, }; +static int +in_evdev_evend_handler (const IE_event_t *event, void *data) +{ + if (event->type == ie_app_gain_focus) { + evdev_have_focus = 1; + return 1; + } else if (event->type == ie_app_lose_focus) { + evdev_have_focus = 0; + return 1; + } + return 0; +} + static void __attribute__((constructor)) in_evdev_register_driver (void) { evdev_driver_handle = IN_RegisterDriver (&in_evdev_driver, 0); + //FIXME probably shouldn't be here + IE_Add_Handler (in_evdev_evend_handler, 0); } int in_evdev_force_link; From d930a49de6aebab91d9b6fa3cb7ca52866b8381f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 14:40:34 +0900 Subject: [PATCH 1849/3664] [console] Close console when escape key is pressed I should have fixed this back when I got console working with the new input system. --- libs/console/client.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/console/client.c b/libs/console/client.c index 24b6acf78..06f740a20 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -805,6 +805,9 @@ con_key_event (const IE_event_t *event) } else { #endif switch (key->code) { + case QFK_ESCAPE: + ToggleConsole_f (); + break; case QFK_PAGEUP: if (key->shift & ies_control) con->display = 0; From c3ce12de4cad3405b65c56bd1c2ee9aee81b3a14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 15:42:22 +0900 Subject: [PATCH 1850/3664] [x11] Use root window for barriers It turns out that if the barriers are set on the app window, and the app grabs the pointer (even passively), barrier events will no longer be sent to the app. However, creating the barriers on the root window and the events are selected on the root window, the barrier events are sent regardless of the grab state. --- libs/video/targets/in_x11.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index d936e08ae..a94b74799 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -1296,7 +1296,7 @@ in_x11_xi_select_events (void) }; XISetMask (mask, XI_BarrierHit); XISetMask (mask, XI_BarrierLeave); - XISelectEvents (x_disp, x_win, &evmask, 1); + XISelectEvents (x_disp, x_root, &evmask, 1); } static void @@ -1350,16 +1350,16 @@ in_x11_setup_barriers (int xpos, int ypos, int xlen, int ylen) int ty = ypos; int rx = xpos + xlen - 1; int by = ypos + ylen - 1; - x11_left_barrier = XFixesCreatePointerBarrier (x_disp, x_win, + x11_left_barrier = XFixesCreatePointerBarrier (x_disp, x_root, lx, ty-1, lx, by+1, BarrierPositiveX, 0, 0); - x11_right_barrier = XFixesCreatePointerBarrier (x_disp, x_win, + x11_right_barrier = XFixesCreatePointerBarrier (x_disp, x_root, rx, ty-1, rx, by+1, BarrierNegativeX, 0, 0); - x11_top_barrier = XFixesCreatePointerBarrier (x_disp, x_win, + x11_top_barrier = XFixesCreatePointerBarrier (x_disp, x_root, lx-1, ty, rx+1, ty, BarrierPositiveY, 0, 0); - x11_bottom_barrier = XFixesCreatePointerBarrier (x_disp, x_win, + x11_bottom_barrier = XFixesCreatePointerBarrier (x_disp, x_root, lx-1, by, rx+1, by, BarrierNegativeY, 0, 0); } From 0c1927d6312de44ca059fae0b0ef5ecd82bcf442 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 Nov 2021 23:54:31 +0900 Subject: [PATCH 1851/3664] [x11] Remove -nomouse handling After a lot of thought, it really doesn't make sense to have an option to block mouse input in x11 (not grabbing or similar does make sense, of course). Not initializing mouse input made perfect sense in DOS and even console Linux (SVGA) what with the low level access. --- libs/video/targets/in_x11.c | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index a94b74799..8bc27e910 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -1403,14 +1403,12 @@ IN_X11_Preinit (void) X11_AddEvent (EnterNotify, &enter_notify); X11_AddEvent (LeaveNotify, &leave_notify); - if (!COM_CheckParm ("-nomouse")) { - if ((x11_have_xi = in_x11_check_xi2 ())) { - X11_AddEvent (GenericEvent, &event_generic); - } else { - X11_AddEvent (MotionNotify, &event_motion); - X11_AddEvent (ButtonPress, &event_button); - X11_AddEvent (ButtonRelease, &event_button); - } + if (x11_have_xi) { + X11_AddEvent (GenericEvent, &event_generic); + } else { + X11_AddEvent (MotionNotify, &event_motion); + X11_AddEvent (ButtonPress, &event_button); + X11_AddEvent (ButtonRelease, &event_button); } Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f, @@ -1426,15 +1424,13 @@ IN_X11_Postinit (void) if (!x_win) Sys_Error ("IN: No window!!"); - if (!COM_CheckParm ("-nomouse")) { - if (x11_have_xi) { - in_x11_xi_select_events (); - in_x11_xi_setup_grabs (); - } else { - dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); - Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", - dga_avail); - } + if (x11_have_xi) { + in_x11_xi_select_events (); + in_x11_xi_setup_grabs (); + } else { + dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); + Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", + dga_avail); } } @@ -1444,10 +1440,7 @@ in_x11_init (void *data) x11_fd = ConnectionNumber (x_disp); x11_add_device (&x11_keyboard_device); - - if (!COM_CheckParm ("-nomouse")) { - x11_add_device (&x11_mouse_device); - } + x11_add_device (&x11_mouse_device); } static void From af5d92708de41f6332bcc7964031c902dfa19303 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Nov 2021 11:18:32 +0900 Subject: [PATCH 1852/3664] [x11] Implement raw keyboard input via XInput2 UI key presses are still handled by regular X events, but in-game "button" presses arrive via raw keyboard events. This gives transparent handling of keyboard repeat (UI keys see repeat, game keys do not), without messing with the server's settings (yay, that was most annoying when it came to debugging), and the keyboard is never grabbed, so this is a fairly user-friendly setup. At first, I wasn't too keen on capturing them from the root window (thinking about the user's security), but after a lot of investigation, I found a post by Peter Hutterer (http://who-t.blogspot.com/2011/09/whats-new-in-xi-21-raw-events.html) commenting that root window events were added to XInput2 specifically for games. Since application focus is tracked and unfocused key events are dropped very early on, there's no way for code further down the food-chain to know there even was an event, abusing the access would require modifying the x11 input code, in which case all bets are off anyway and any attempt at security anywhere in the code will fail, meaning that nefarious progs code and the like shouldn't be a problem. --- libs/video/targets/in_x11.c | 64 ++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 8bc27e910..7f7d7ccc9 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -851,26 +851,66 @@ event_button (XEvent *event) } } +static unsigned +in_x11_process_key_button (unsigned keycode, int press) +{ + // X11 protocol supports only 256 keys. The key codes are the AT scan codes + // offset by 8 (so Esc is 9 instead of 1). + unsigned key = (keycode - 8) & 0xff; + x11_key_buttons[key].state = press; + return key; +} + static void event_key (XEvent *event) { - int key; + unsigned key = 0; x_time = event->xkey.time; - // X11 protocol supports only 256 keys. The key codes are the AT scan codes - // offset by 8 (so Esc is 9 instead of 1). - key = (event->xkey.keycode - 8) & 0xff; - x11_key_buttons[key].state = event->type == KeyPress; - + if (!x11_have_xi) { + key = in_x11_process_key_button (event->xkey.keycode, + event->type == KeyPress); + } x11_key.shift = event->xmotion.state & 0xff; XLateKey (&event->xkey, &x11_key.code, &x11_key.unicode); - if (event->type != KeyPress || !in_x11_send_key_event ()) { + if (!(event->type == KeyPress && in_x11_send_key_event ()) + && !x11_have_xi) { in_x11_send_button_event (x11_keyboard_device.devid, &x11_key_buttons[key], x11_keyboard_device.event_data); } } +static void +xi_raw_key (void *event, int press) +{ + if (!x_have_focus) { + //avoid being a keylogger + return; + } + XIRawEvent *re = event; + unsigned key = in_x11_process_key_button (re->detail, press); + + // Send only the button press: event_key takes care of the UI key event, + // which includes character translation and repeat (XInput2 raw key events + // do not repeat) + in_x11_send_button_event (x11_keyboard_device.devid, + &x11_key_buttons[key], + x11_keyboard_device.event_data); +} + +static void +xi_raw_key_press (void *event) +{ + xi_raw_key (event, 1); +} + +static void +xi_raw_key_resease (void *event) +{ + xi_raw_key (event, 0); +} + static void xi_raw_motion (void *event) { @@ -963,6 +1003,8 @@ event_generic (XEvent *event) { // XI_LASTEVENT is the actual last event, not +1 static void (*xi_event_handlers[XI_LASTEVENT + 1]) (void *) = { + [XI_RawKeyPress] = xi_raw_key_press, + [XI_RawKeyRelease] = xi_raw_key_resease, [XI_RawMotion] = xi_raw_motion, [XI_RawButtonPress] = xi_raw_button_press, [XI_RawButtonRelease] = xi_raw_button_resease, @@ -1296,6 +1338,8 @@ in_x11_xi_select_events (void) }; XISetMask (mask, XI_BarrierHit); XISetMask (mask, XI_BarrierLeave); + XISetMask (mask, XI_RawKeyPress); + XISetMask (mask, XI_RawKeyRelease); XISelectEvents (x_disp, x_root, &evmask, 1); } @@ -1324,10 +1368,6 @@ in_x11_xi_setup_grabs (void) XIGrabEnter (x_disp, dev, x_win, None, XIGrabModeAsync, XIGrabModeAsync, 0, &evmask, 1, &modif); - //FIXME doesn't seem to do anything. Is it actually necessary? - //here for reference - //XIGrabFocusIn (x_disp, dev, x_win, XIGrabModeAsync, XIGrabModeAsync, - // 0, &evmask, 1, &modif); } static void @@ -1395,6 +1435,8 @@ IN_X11_Preinit (void) x11_event_handler_id = IE_Add_Handler (x11_event_handler, 0); + x11_have_xi = in_x11_check_xi2 (); + X11_AddEvent (KeyPress, &event_key); X11_AddEvent (KeyRelease, &event_key); X11_AddEvent (FocusIn, &event_focusin); From 78b4e8217e4bc1fb3cc57937c1728debcae73f06 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Nov 2021 12:44:21 +0900 Subject: [PATCH 1853/3664] [x11] Fix a optimization compiler warning With the old headers removed, X11_SetGamma became a stub and gcc complained about it wanting the const attribute. On investigation, it turned out the X_XF86VidModeSetGamma was a holdover from the initial implementation of hardware gamma support. --- libs/video/targets/context_x11.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index d5b6f8dd4..94df3b68f 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -609,7 +609,6 @@ qboolean X11_SetGamma (double gamma) { #ifdef HAVE_VIDMODE -# ifdef X_XF86VidModeSetGamma XF86VidModeGamma xgamma; if (vid_gamma_avail && vid_system_gamma->int_val && x_have_focus) { @@ -617,7 +616,8 @@ X11_SetGamma (double gamma) if (XF86VidModeSetGamma (x_disp, x_screen, &xgamma)) return true; } -# endif +#else + Sys_MaskPrintf (SYS_vid, "X11_SetGamma: cannot adjust gamma\n"); #endif return false; } @@ -626,7 +626,6 @@ void X11_RestoreGamma (void) { #ifdef HAVE_VIDMODE -# ifdef X_XF86VidModeSetGamma XF86VidModeGamma xgamma; if (vid_gamma_avail && x_gamma[0] > 0) { @@ -635,7 +634,8 @@ X11_RestoreGamma (void) xgamma.blue = x_gamma[2]; XF86VidModeSetGamma (x_disp, x_screen, &xgamma); } -# endif +#else + Sys_MaskPrintf (SYS_vid, "X11_RestoreGamma: cannot adjust gamma\n"); #endif } From 1ef99a9130d9c9f79de4cfe3b8eef2d93f49b991 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Nov 2021 22:04:17 +0900 Subject: [PATCH 1854/3664] [input] Separate absolute and relative axis inputs Combining absolute and relative inputs at the binding does not work well because absolute inputs generally update only when the physical input updates, so clearing the axis input each frame results in a brief pulse from the physical input, but relative inputs must be cleared each frame (where frame here is each time the axis is read) but must accumulate the relative updates between frames. Other than the axis mode being incorrect, this seems to work quite nicely. --- include/QF/input/binding.h | 74 ++++++++++++++++++++++++++++++++++++++ libs/input/in_imt.c | 10 ++---- nq/source/cl_input.c | 19 ++++------ qw/source/cl_input.c | 19 ++++------ 4 files changed, 88 insertions(+), 34 deletions(-) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 5c82d08c2..ddcb4c35a 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -31,6 +31,8 @@ #ifndef __QFCC__ +#include "QF/mathlib.h" + /*** Recipe for converting an axis to a floating point value. Absolute axes are converted to the 0..1 range for unbalanced axes, and @@ -81,6 +83,8 @@ typedef enum { typedef struct in_axis_s { float value; ///< converted value of the axis in_axis_mode mode; ///< method used for updating the destination + float abs_input; ///< input from an absolute axis (eg, joystick) + float rel_input; ///< input from a relative axis (eg, mouse) const char *name; const char *description; } in_axis_t; @@ -155,6 +159,7 @@ GNU89INLINE inline float IN_ButtonState (in_button_t *button); Both steady-state on, and brief clicks are detected. + \param button Pointer to the button being tested. \return True if the button is currently held or was pulsed on in the last frame. \note The edge transitions are cleared, so for each frame, this @@ -167,6 +172,7 @@ GNU89INLINE inline int IN_ButtonPressed (in_button_t *button); Valid only if the button is still released. A pulsed off does not count as being released as the button is still held. + \param button Pointer to the button being tested. \return True if the button is currently released and the release was in the last frame. \note The edge transitions are cleared, so for each frame, this @@ -174,6 +180,41 @@ GNU89INLINE inline int IN_ButtonPressed (in_button_t *button); */ GNU89INLINE inline int IN_ButtonReleased (in_button_t *button); +/*** Update the axis value based on its mode and clear its relative input. + + The absolute and relative inputs are separate because absolute inputs + usually get written when the input actually changes (and thus must not + be cleared each frame), while relative inputs indicate a per-frame delta + and thus must be cleared each frame. + + \param axis Pointer to the axis being updated. + \return The resulting output value of the axis. + \note The relative input (\a rel_input) is zeroed. +*/ +GNU89INLINE inline float IN_UpdateAxis (in_axis_t *axis); + +/*** Update and clamp the axis value (see IN_UpdateAxis()) + + Like IN_UpdateAxis(), but clamps the final output to the specified range. + This is most useful for \a ina_accumulate axes, but can be used to ensure + \a ina_set axes never exceed a given range. + + The absolute and relative inputs are separate because absolute inputs + usually get written when the input actually changes (and thus must not + be cleared each frame), while relative inputs indicate a per-frame delta + and thus must be cleared each frame. + + \param axis Pointer to the axis being updated. + \param minval The minimum value to which the axis output will be clamped. + \param minval The minimum value to which the axis output will be clamped. + \return The resulting output value of the axis. + \note The relative input (\a rel_input) is zeroed. The absolute + input is not affected by the clamping, only the output + \a value. +*/ +GNU89INLINE inline float IN_ClampAxis (in_axis_t *axis, + float minval, float maxval); + #ifndef IMPLEMENT_INPUT_Funcs GNU89INLINE inline #else @@ -227,6 +268,39 @@ IN_ButtonReleased (in_button_t *button) return (state & (inb_down | inb_edge_up)) == inb_edge_up; } +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +float +IN_UpdateAxis (in_axis_t *axis) +{ + switch (axis->mode) { + case ina_set: + axis->value = axis->abs_input + axis->rel_input; + break; + case ina_accumulate: + axis->value += axis->abs_input + axis->rel_input; + break; + } + axis->rel_input = 0; + return axis->value; +} + +#ifndef IMPLEMENT_INPUT_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +float +IN_ClampAxis (in_axis_t *axis, float minval, float maxval) +{ + IN_UpdateAxis (axis); + axis->value = bound (minval, axis->value, maxval); + return axis->value; +} + void IN_ButtonAction (in_button_t *buttin, int id, int pressed); int IN_RegisterButton (in_button_t *button); diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 4417126f3..828b3f36e 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -429,6 +429,7 @@ IMT_ProcessAxis (int axis, int value) if (recipe->curve != 1) { output = powf (output, recipe->curve); } + a->axis->rel_input += output; } else { int input = bound (minval, value, maxval); int range = maxval - minval; @@ -458,14 +459,7 @@ IMT_ProcessAxis (int axis, int value) output = powf (output, recipe->curve); } output *= recipe->scale; - } - switch (a->axis->mode) { - case ina_set: - a->axis->value = output; - break; - case ina_accumulate: - a->axis->value += output; - break; + a->axis->abs_input = output; } return true; } diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 021b73bed..75029ae83 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -337,19 +337,12 @@ CL_BaseMove (usercmd_t *cmd) } */ - cmd->forwardmove -= viewdelta_position_forward.value * m_forward->value; - cmd->sidemove += viewdelta_position_side.value * m_side->value; - cmd->upmove -= viewdelta_position_up.value; - cl.viewstate.angles[PITCH] -= viewdelta_angles_pitch.value * m_pitch->value; - cl.viewstate.angles[YAW] -= viewdelta_angles_yaw.value * m_yaw->value; - cl.viewstate.angles[ROLL] -= viewdelta_angles_roll.value * m_pitch->value; - - viewdelta_angles_pitch.value = 0; - viewdelta_angles_yaw.value = 0; - viewdelta_angles_roll.value = 0; - viewdelta_position_forward.value = 0; - viewdelta_position_side.value = 0; - viewdelta_position_up.value = 0; + cmd->forwardmove -= IN_UpdateAxis (&viewdelta_position_forward) * m_forward->value; + cmd->sidemove += IN_UpdateAxis (&viewdelta_position_side) * m_side->value; + cmd->upmove -= IN_UpdateAxis (&viewdelta_position_up); + cl.viewstate.angles[PITCH] -= IN_UpdateAxis (&viewdelta_angles_pitch) * m_pitch->value; + cl.viewstate.angles[YAW] -= IN_UpdateAxis (&viewdelta_angles_yaw) * m_yaw->value; + cl.viewstate.angles[ROLL] -= IN_UpdateAxis (&viewdelta_angles_roll) * m_pitch->value; if (freelook && !(in_strafe.state & inb_down)) { cl.viewstate.angles[PITCH] diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 77a799bef..513e5594d 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -354,19 +354,12 @@ CL_BaseMove (usercmd_t *cmd) } */ - cmd->forwardmove -= viewdelta_position_forward.value * m_forward->value; - cmd->sidemove += viewdelta_position_side.value * m_side->value; - cmd->upmove -= viewdelta_position_up.value; - cl.viewstate.angles[PITCH] -= viewdelta_angles_pitch.value * m_pitch->value; - cl.viewstate.angles[YAW] -= viewdelta_angles_yaw.value * m_yaw->value; - cl.viewstate.angles[ROLL] -= viewdelta_angles_roll.value * m_pitch->value; - - viewdelta_angles_pitch.value = 0; - viewdelta_angles_yaw.value = 0; - viewdelta_angles_roll.value = 0; - viewdelta_position_forward.value = 0; - viewdelta_position_side.value = 0; - viewdelta_position_up.value = 0; + cmd->forwardmove -= IN_UpdateAxis (&viewdelta_position_forward) * m_forward->value; + cmd->sidemove += IN_UpdateAxis (&viewdelta_position_side) * m_side->value; + cmd->upmove -= IN_UpdateAxis (&viewdelta_position_up); + cl.viewstate.angles[PITCH] -= IN_UpdateAxis (&viewdelta_angles_pitch) * m_pitch->value; + cl.viewstate.angles[YAW] -= IN_UpdateAxis (&viewdelta_angles_yaw) * m_yaw->value; + cl.viewstate.angles[ROLL] -= IN_UpdateAxis (&viewdelta_angles_roll) * m_pitch->value; if (freelook && !(in_strafe.state & inb_down)) { cl.viewstate.angles[PITCH] From 06c21d3c34a56d4151da6b46b0fe8c1e79c17dba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Nov 2021 22:04:56 +0900 Subject: [PATCH 1855/3664] [qw,nq] Correct the axis modes It turns out accumulate is not really suitable now that relative axis accumulation is done in the binding processing, and was never suitable for absolute inputs (in this context, of course: there are contexts where accumulate is suitable for absolute inputs). --- nq/source/cl_input.c | 12 ++++++------ qw/source/cl_input.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 75029ae83..5e788a195 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -57,33 +57,33 @@ int cl_demo_context; static int cl_event_id; in_axis_t viewdelta_position_forward = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.forward", .description = "Move forward (negative) or backward (positive)", }; in_axis_t viewdelta_position_side = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.side", .description = "Move right (positive) or left (negative)", }; in_axis_t viewdelta_position_up = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.up", .description = "Move up (positive) or down (negative)", }; in_axis_t viewdelta_angles_pitch = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.pitch", .description = "Pitch axis", }; in_axis_t viewdelta_angles_yaw = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.yaw", .description = "Yaw axis", }; in_axis_t viewdelta_angles_roll = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.roll", .description = "Roll axis", }; diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 513e5594d..811ff697c 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -71,33 +71,33 @@ cvar_t *cl_maxnetfps; cvar_t *cl_spamimpulse; in_axis_t viewdelta_position_forward = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.forward", .description = "Move forward (negative) or backward (positive)", }; in_axis_t viewdelta_position_side = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.side", .description = "Move right (positive) or left (negative)", }; in_axis_t viewdelta_position_up = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.up", .description = "Move up (positive) or down (negative)", }; in_axis_t viewdelta_angles_pitch = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.pitch", .description = "Pitch axis", }; in_axis_t viewdelta_angles_yaw = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.yaw", .description = "Yaw axis", }; in_axis_t viewdelta_angles_roll = { - .mode = ina_accumulate, + .mode = ina_set, .name = "move.roll", .description = "Roll axis", }; From 28b80d8bf851d3f1fbbc678f5573b8a39cd7b95f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Nov 2021 23:15:08 +0900 Subject: [PATCH 1856/3664] [x11] Handle raw motion events (more) correctly For now, only the first two axis (mouse X and Y) are supported (XInput treats the scroll wheel events as axes too, so mice have up to 4!), but most importantly, this prevents the scroll wheel from being seen as the X axis. Oops. --- libs/video/targets/in_x11.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 7f7d7ccc9..d4b7c1090 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -99,10 +99,11 @@ typedef struct x11_device_s { } x11_device_t; #define X11_MOUSE_BUTTONS 32 +#define X11_MOUSE_AXES 2 // The X11 protocol supports only 256 keys static in_buttoninfo_t x11_key_buttons[256]; -// X11 mice have only two axes (FIXME always true?) -static in_axisinfo_t x11_mouse_axes[2]; +// X11 mice have only two axes (FIXME NOT always true (XInput says otherwise!) +static in_axisinfo_t x11_mouse_axes[X11_MOUSE_AXES]; // FIXME assume up to 32 mouse buttons (see X11_MOUSE_BUTTONS) static in_buttoninfo_t x11_mouse_buttons[X11_MOUSE_BUTTONS]; static const char *x11_mouse_axis_names[] = {"M_X", "M_Y"}; @@ -918,8 +919,21 @@ xi_raw_motion (void *event) Window root_w, child_w; XIRawEvent *re = event; - x11_mouse_axes[0].value = re->raw_values[0]; - x11_mouse_axes[1].value = re->raw_values[1]; + //FIXME it turns out mice can have multiple axes (my trackball has 4: + //usual x and y, +scroll up/down and left/right (clicky and icky, but + //still...) + unsigned mask = re->valuators.mask[0] & 3; + if (!mask) { + return; + } + + x11_mouse_axes[0].value = 0; + x11_mouse_axes[1].value = 0; + for (int axis = 0, ind = 0; mask; axis++, mask >>= 1) { + if (mask & 1) { + x11_mouse_axes[axis].value = re->raw_values[ind++]; + } + } XQueryPointer (x_disp, x_win, &root_w, &child_w, &root_x, &root_y, &x11_mouse.x, &x11_mouse.y, &x11_mouse.shift); // want only the modifier state @@ -935,7 +949,6 @@ xi_raw_motion (void *event) static void xi_raw_button (void *event, int press) { - int root_x, root_y; Window root_w, child_w; unsigned button; From 719525a4a1f5fa25bea3432a1c33bb30f586848d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 23 Nov 2021 23:21:43 +0900 Subject: [PATCH 1857/3664] [x11] Set backed mouse button state for raw presses Fixes button press events being treated as button releases in the event handlers. --- libs/video/targets/in_x11.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index d4b7c1090..659ea1bb0 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -968,6 +968,7 @@ xi_raw_button (void *event, int press) } else { x11_mouse.buttons &= ~(1 << button); } + x11_mouse_buttons[button].state = press; if (!in_x11_send_mouse_event (press ? ie_mousedown : ie_mouseup)) { in_x11_send_button_event (x11_mouse_device.devid, &x11_mouse_buttons[button], From b45acf7974b7d443793039335081df446eb6ea96 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 Nov 2021 01:51:52 +0900 Subject: [PATCH 1858/3664] [x11] Add a comment about grabbing design --- libs/video/targets/in_x11.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 659ea1bb0..e2a37b985 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -1380,6 +1380,10 @@ in_x11_xi_setup_grabs (void) .modifiers = XIAnyModifier, }; + // Grab mouse events on the app window so window manager actions (eg, + // alt-middle-click) don't interfere. However, the keyboard is not grabbed + // so the user always has a way to take control (assuming the window + // manager provides such, but most do). XIGrabEnter (x_disp, dev, x_win, None, XIGrabModeAsync, XIGrabModeAsync, 0, &evmask, 1, &modif); } From 67735182d76fe87201e1e55777a0e699f40101c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 Nov 2021 02:06:22 +0900 Subject: [PATCH 1859/3664] [x11] Protect XInput2 and XFixes code This will allow QF to be built in the unlikely event XInput2 or XFixes are not available. nq-x11 seemed to work nicely with both disabled. --- libs/video/targets/in_x11.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index e2a37b985..3b2c53d04 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -143,12 +143,16 @@ static IE_mouse_event_t x11_mouse; static IE_key_event_t x11_key; static int input_grabbed = 0; +#ifdef HAVE_XI2 static int xi_opcode; +#endif +#ifdef HAVE_XFIXES static int xf_opcode; static PointerBarrier x11_left_barrier; static PointerBarrier x11_right_barrier; static PointerBarrier x11_top_barrier; static PointerBarrier x11_bottom_barrier; +#endif static int x11_have_xi; static int x11_fd; static int x11_driver_handle = -1; @@ -882,6 +886,7 @@ event_key (XEvent *event) } } +#ifdef HAVE_XI2 static void xi_raw_key (void *event, int press) { @@ -1039,6 +1044,7 @@ event_generic (XEvent *event) XFreeEventData (x_disp, cookie); } +#endif static void grab_error (int code, const char *device) @@ -1071,10 +1077,12 @@ in_x11_grab_input (void *data, int grab) if (!x_disp || !x_win) return; +#ifdef HAVE_XFIXES if (xf_opcode) { input_grabbed = grab; return; } +#endif if (vid_fullscreen) grab = grab || vid_fullscreen->int_val; @@ -1300,6 +1308,7 @@ x11_add_device (x11_device_t *dev) dev->devid = IN_AddDevice (x11_driver_handle, dev, dev->name, dev->name); } +#ifdef HAVE_XI2 static int in_x11_check_xi2 (void) { @@ -1387,7 +1396,9 @@ in_x11_xi_setup_grabs (void) XIGrabEnter (x_disp, dev, x_win, None, XIGrabModeAsync, XIGrabModeAsync, 0, &evmask, 1, &modif); } +#endif +#ifdef HAVE_XFIXES static void in_x11_setup_barriers (int xpos, int ypos, int xlen, int ylen) { @@ -1421,12 +1432,16 @@ in_x11_setup_barriers (int xpos, int ypos, int xlen, int ylen) lx-1, by, rx+1, by, BarrierNegativeY, 0, 0); } +#endif static void x11_app_window (const IE_event_t *ie_event) { +#ifdef HAVE_XFIXES + //FIXME aw may be needed even without XFixes when resizing is supported __auto_type aw = ie_event->app_window; in_x11_setup_barriers (aw.xpos, aw.ypos, aw.xlen, aw.ylen); +#endif } static int @@ -1452,9 +1467,9 @@ IN_X11_Preinit (void) long event_mask = X11_INPUT_MASK; x11_event_handler_id = IE_Add_Handler (x11_event_handler, 0); - +#ifdef HAVE_XI2 x11_have_xi = in_x11_check_xi2 (); - +#endif X11_AddEvent (KeyPress, &event_key); X11_AddEvent (KeyRelease, &event_key); X11_AddEvent (FocusIn, &event_focusin); @@ -1464,7 +1479,9 @@ IN_X11_Preinit (void) X11_AddEvent (LeaveNotify, &leave_notify); if (x11_have_xi) { +#ifdef HAVE_XI2 X11_AddEvent (GenericEvent, &event_generic); +#endif } else { X11_AddEvent (MotionNotify, &event_motion); X11_AddEvent (ButtonPress, &event_button); @@ -1485,8 +1502,10 @@ IN_X11_Postinit (void) Sys_Error ("IN: No window!!"); if (x11_have_xi) { +#ifdef HAVE_XI2 in_x11_xi_select_events (); in_x11_xi_setup_grabs (); +#endif } else { dga_avail = VID_CheckDGA (x_disp, NULL, NULL, NULL); Sys_MaskPrintf (SYS_vid, "VID_CheckDGA returned %d\n", From c069e7754f9d2d2fa6cefba294cb4ab996d473f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 10:46:42 +0900 Subject: [PATCH 1860/3664] [util] Add a listener object I decided cvars and input buttons/axes need listeners so any changes to them can be propagated. This will make using cvars in bindings feasible and I have an idea for automatic imt switching that would benefit from listeners attached to buttons and cvars. --- include/QF/listener.h | 158 +++++++++++++++++++++++++++++++++ libs/util/test/Makemodule.am | 5 ++ libs/util/test/test-listener.c | 59 ++++++++++++ 3 files changed, 222 insertions(+) create mode 100644 include/QF/listener.h create mode 100644 libs/util/test/test-listener.c diff --git a/include/QF/listener.h b/include/QF/listener.h new file mode 100644 index 000000000..553c79a3e --- /dev/null +++ b/include/QF/listener.h @@ -0,0 +1,158 @@ +/* + listener.h + + Listener objects + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/11/25 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_listener_h +#define __QF_listener_h + +#include "QF/darray.h" + +/** \defgroup listener Listeners + \ingroup utils + + Listener objects +*/ +///@{ + +/** The structure defs for a listener set for an object of the given type. + + This is just the defs of a struct delcaration: it is useless on its own. + The intended usage is something like: + + typedef struct obj_listenerset_s LISTENER_SET_TYPE(obj_t) + obj_listenerset_t; + + This allows full flexibility in just how the actual type is used. + + The \a lfunc field is the function that will be called whenever the + listener is invoked. \a ldata is an aribtrary pointer that is passed to + the function as its \a data parameter. The function's \a obj parameter + is the \a obj parameter passed to LISTENER_INVOKE(), and is intended to + be the object being listened to. + + There can be any number of \a lfunc, \a ldata pairs, but they should be + unique, though this is not enforced. + + \param type The type of the listened objects. A pointer to an object + being listend to is passed to LISTENER_INVOKE() and that + pointer is passed on to each listener function in the + listener set. + \hideinitializer +*/ +#define LISTENER_SET_TYPE(type) \ + DARRAY_TYPE(struct { \ + void (*lfunc) (void *data, const type *obj); \ + void *ldata; \ + }) + +#define LISTENER_SET_STATIC_INIT(g) DARRAY_STATIC_INIT(g) + +/** Initialize the listener set. + + The set is initialized to be emtpy. + + \param lset The *address* of the listener set being initialized (ie, + a pointer to the listener set). + \param growSice Amount by which the underlying array will grow. + \hideinitializer +*/ +#define LISTENER_SET_INIT(lset, growSice) DARRAY_INIT(lset, growSice) + +/** Add a listener function/data par to the listener set. + + The function's first parameter is the \a data pointer in the \a func + \a data pair. The function's second parameter is the \a obj parameter + of LISTENER_INVOKE(). Thus each added listener function will be called + with its associated data pointer and the \a obj parameter from + LISTENER_INVOKE(). + + Each pair should be unique in order to avoid double-action and so + listeners can be removed properly. + + \param lset The *address* of the listener set being modified (ie, + a pointer to the listener set). + \param func The function to be called when the listener is invoked. + \param data Arbitrary pointer passed on to the function as its first + parameter when when the listener is invoked. + \hideinitializer +*/ +#define LISTENER_ADD(lset, func, data) \ + do { \ + __auto_type ls = (lset); \ + typeof(ls->a[0]) l = {(func), (data)}; \ + DARRAY_APPEND (ls, l); \ + } while (0) + +/** Remove a listener function/data pair from the listener set. + + Each individual listener is identifed by its \a func \a data pair. Only + the first instance of a pair is removed, thus only unique pairs should be + added. + + \param lset The *address* of the listener set being modified (ie, + a pointer to the listener set). + \param func The listener function being removed. + \param data The function's associated data pointer. + \hideinitializer +*/ +#define LISTENER_REMOVE(lset, func, data) \ + do { \ + __auto_type ls = (lset); \ + typeof(ls->a[0]) l = {(func), (data)}; \ + for (size_t i = 0; i < ls->size; i++) { \ + if (ls->a[i].lfunc == l.lfunc && ls->a[i].ldata == l.ldata) { \ + DARRAY_REMOVE_AT (ls, i); \ + break; \ + } \ + } \ + } while (0) + +/** Call all listener functions in the listener set. + + Each listener function is passed its data pointer as the first parameter + and \a obj as the second parameter. + + \param lset The *address* of the listener set being invoked (ie, + a pointer to the listener set). + \param obj Pointer passed to each listener function as its second + parameter. + \hideinitializer +*/ +#define LISTENER_INVOKE(lset, obj) \ + do { \ + __auto_type ls = (lset); \ + __auto_type o = (obj); \ + for (size_t i = 0; i < ls->size; i++) { \ + ls->a[i].lfunc (ls->a[i].ldata, o); \ + } \ + } while (0) + +///@} + +#endif//__QF_listener_h diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index ed3b0bb99..188239e11 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -10,6 +10,7 @@ libs_util_tests = \ libs/util/test/test-dq \ libs/util/test/test-half \ libs/util/test/test-heapsort \ + libs/util/test/test-listener \ libs/util/test/test-mat3 \ libs/util/test/test-mat4 \ libs/util/test/test-plist \ @@ -71,6 +72,10 @@ libs_util_test_test_heapsort_SOURCES=libs/util/test/test-heapsort.c libs_util_test_test_heapsort_LDADD=libs/util/libQFutil.la libs_util_test_test_heapsort_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_listener_SOURCES=libs/util/test/test-listener.c +libs_util_test_test_listener_LDADD=libs/util/libQFutil.la +libs_util_test_test_listener_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_mat3_SOURCES=libs/util/test/test-mat3.c libs_util_test_test_mat3_LDADD=libs/util/libQFutil.la libs_util_test_test_mat3_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-listener.c b/libs/util/test/test-listener.c new file mode 100644 index 000000000..0c9654b38 --- /dev/null +++ b/libs/util/test/test-listener.c @@ -0,0 +1,59 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#define remove remove_renamed +#include +#include +#include + +#include "QF/listener.h" +#include "QF/sys.h" +#undef remove + +typedef struct obj_s { + int count; +} obj_t; + +struct LISTENER_SET_TYPE (obj_t) listeners = LISTENER_SET_STATIC_INIT(8); + +static void +listener_a (void *data, const obj_t *obj) +{ + *(int *) data += 1; + ((obj_t *) obj)->count += 1; +} + +static void +listener_b (void *data, const obj_t *obj) +{ + *(int *) data += 2; + ((obj_t *) obj)->count += 2; +} + +int +main (int argc, const char **argv) +{ + int res = 0; + int a_count = 0; + int b_count = 0; + obj_t obj = { 0 }; + + LISTENER_ADD (&listeners, listener_a, &a_count); + LISTENER_ADD (&listeners, listener_b, &b_count); + LISTENER_INVOKE (&listeners, &obj); + if (a_count != 1 || b_count != 2) { + Sys_Error ("a_count = %d, b_count = %d", a_count, b_count); + } + if (obj.count != 3) { + Sys_Error ("obj.count = %d", obj.count); + } + LISTENER_REMOVE (&listeners, listener_b, &b_count); + LISTENER_INVOKE (&listeners, &obj); + if (a_count != 2 || b_count != 2) { + Sys_Error ("a_count = %d, b_count = %d", a_count, b_count); + } + if (obj.count != 4) { + Sys_Error ("obj.count = %d", obj.count); + } + return res; +} From ad892921ce85fb63124ffe7aa1309378c865a1fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 10:50:42 +0900 Subject: [PATCH 1861/3664] [util] Hide some initializers from the darray docs I'd forgotten to add the tag when adding the new macros. --- include/QF/darray.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/QF/darray.h b/include/QF/darray.h index 47f887db3..57111e772 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -82,6 +82,7 @@ type of the array. \param array_size The size of the array. \param alloc Allocator compatible with malloc (eg, alloca). + \hideinitializer */ #define DARRAY_ALLOCFIXED(array_type, array_size, alloc) \ ({ \ @@ -105,6 +106,7 @@ \param alloc Allocator taking (obj, size) where obj is allocator specific data (eg, a memory pool). \param obj Additional data for the allocator. + \hideinitializer */ #define DARRAY_ALLOCFIXED_OBJ(array_type, array_size, alloc, obj) \ ({ \ From 3bd922e4736479798d125937f85afe501840e4b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 12:17:59 +0900 Subject: [PATCH 1862/3664] [input] Correct a typo in in_bind's help text --- libs/input/in_binding.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 0f66ae831..f3fdd627a 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -374,7 +374,7 @@ in_bind_f (void) " button)\n"); // FIXME support names Sys_Printf (" number: the numeric id of the input to be bound\n"); - Sys_Printf (" binging...: the destination to which the input will" + Sys_Printf (" binding...: the destination to which the input will" " be bound\n"); Sys_Printf (" for axis inputs, this can be an analog input or" " an axis-button\n"); From fba1a1ac6bc3c0547b9aa340855d465ec2fd82f1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 12:18:35 +0900 Subject: [PATCH 1863/3664] [input] Rebuild the button binding string I had forgotten that Cmd_Args() preserves quotes, which resulted in button bindings having excess quotes when used to bind complex commands (eg, the default quicksave and quickload bindings). --- libs/input/in_binding.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index f3fdd627a..b4146132c 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -41,6 +41,7 @@ #include "QF/cexpr.h" #include "QF/cmd.h" #include "QF/cmem.h" +#include "QF/dstring.h" #include "QF/hash.h" #include "QF/heapsort.h" #include "QF/input.h" @@ -469,7 +470,16 @@ in_bind_f (void) delete_memsuper (exprctx.memsuper); } else { // the rest of the command line is the binding - const char *binding = Cmd_Args (5); + // However, have to put the args into a single string ourselves because + // Cmd_Args includes any quotes used to build compound commands + static dstring_t *binding; + if (!binding) { + binding = dstring_new (); + } + dsprintf (binding, "%s", Cmd_Argv (5)); + for (int i = 6; i < argc; i++) { + dasprintf (binding, " %s", Cmd_Argv (i)); + } if (*end) { num = IN_GetButtonNumber (dev->devid, number); @@ -481,7 +491,7 @@ in_bind_f (void) if (dev->button_imt_id == -1) { dev->button_imt_id = IMT_GetButtonBlock (dev->num_buttons); } - IMT_BindButton (imt, dev->button_imt_id + num, binding); + IMT_BindButton (imt, dev->button_imt_id + num, binding->str); } } From 6a395e341641cd5534f5571d63c6a434935b968f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 12:27:54 +0900 Subject: [PATCH 1864/3664] [input] Remove some cruft The disabled commands were implemented elsewhere or are no longer relevant. --- libs/input/in_binding.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index b4146132c..061ece4de 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -763,32 +763,12 @@ static bindcmd_t in_binding_commands[] = { { "unbindall", Key_Unbindall_f, "Remove all binds (USE CAUTIOUSLY!!!" }, - { "unbind", Key_Unbind_f, - "wrapper for in_unbind that uses in_bind_imt for the imt " - "parameter" - }, - { "bind", Key_Bind_f, - "wrapper for in_bind that uses " - "in_bind_imt for the imt parameter" - }, { "imt", Key_InputMappingTable_f, "" }, { "imt_keydest", Key_IMT_Keydest_f, "" }, - { "imt_create", Key_IMT_Create_f, - "create a new imt table:\n" - " imt_create [chain_name]\n" - "\n" - "The new table will be attached to the specified keydest\n" - "imt_name must not already exist.\n" - "If given, chain_name must already exist and be on " - "keydest.\n" - }, - { "imt_drop_all", Key_IMT_Drop_All_f, - "delete all imt tables\n" - }, { "in_type", Key_In_Type_f, "Send the given string as simulated key presses." }, From 3f299155a39608502094f886094d0d90bf463c1c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 12:46:54 +0900 Subject: [PATCH 1865/3664] [client] Reimplement legacy bind and unbind commands This allows id1/qw config files, and to a certain extent scripts, to work with the new binding system. It does highlight just how limited the original system was (many keys could not bound). Mouse axis input does not work yet as that needs a little more work to support +strafe and +mlook. --- include/client/input.h | 32 +++++ libs/client/Makemodule.am | 4 +- libs/client/cl_input.c | 143 +++++++++++++++++++++ libs/client/old_keys.c | 205 ++++++++++++++++++++++++++++++ libs/input/Makemodule.am | 1 - libs/input/old_keys.c | 257 -------------------------------------- nq/source/cl_input.c | 3 + qw/source/cl_input.c | 2 + 8 files changed, 388 insertions(+), 259 deletions(-) create mode 100644 include/client/input.h create mode 100644 libs/client/cl_input.c create mode 100644 libs/client/old_keys.c delete mode 100644 libs/input/old_keys.c diff --git a/include/client/input.h b/include/client/input.h new file mode 100644 index 000000000..fad8a5092 --- /dev/null +++ b/include/client/input.h @@ -0,0 +1,32 @@ +/* + input.h + + Client input handling + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __client_input_h_ +#define __client_input_h_ + +void CL_Legacy_Init (void); + +#endif // __client_input_h_ diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 0e5105806..1f282f054 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -5,5 +5,7 @@ libs_client_libQFclient_la_LIBADD= libs/gamecode/libQFgamecode.la libs/util/libQ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_effects.c \ libs/client/cl_entities.c \ + libs/client/cl_input.c \ libs/client/cl_temp_entities.c \ - libs/client/locs.c + libs/client/locs.c \ + libs/client/old_keys.c diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c new file mode 100644 index 000000000..f145837ac --- /dev/null +++ b/libs/client/cl_input.c @@ -0,0 +1,143 @@ +/* + cl_legacy.c + + Client legacy commands + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/11/24 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "QF/cmd.h" +#include "QF/cvar.h" +#include "QF/dstring.h" +#include "QF/input.h" +#include "QF/plist.h" +#include "QF/sys.h" + +#include "old_keys.h" + +#include "client/input.h" + +static const char *default_input_config = "" + "{" + " input = {" + " contexts = (" + " {" + " name = key_game;" + " imts = (" + " {" + " name = imt_mod;" + " }" + " );" + " default_imt = imt_mod;" + " }," + " {" + " name = key_demo;" + " }" + " );" + " devices = (" + " {" + " name = mouse;" + " devname = core:mouse;" + " num_axes = 2;" + " num_buttons = 32;" + " }," + " {" + " name = key;" + " devname = core:keyboard;" + " num_axes = 0;" + " num_buttons = 256;" + " }," + " );" + " };" + "};"; + +static void +cl_bind_f (void) +{ + int c, i; + const char *key; + static dstring_t *cmd_buf; + + if (!cmd_buf) { + cmd_buf = dstring_newstr (); + } + + c = Cmd_Argc (); + + if (c < 2) { + Sys_Printf ("bind [command] : attach a command to a key\n"); + return; + } + + if (!(key = OK_TranslateKeyName (Cmd_Argv (1)))) { + return; + } + + dsprintf (cmd_buf, "in_bind imt_mod %s", key); + if (c >= 3) { + for (i = 2; i < c; i++) { + dasprintf (cmd_buf, " \"%s\"", Cmd_Argv (i)); + } + } + + Cmd_ExecuteString (cmd_buf->str, src_command); +} + +static void +cl_unbind_f (void) +{ + int c; + const char *key; + static dstring_t *cmd_buf; + + if (!cmd_buf) { + cmd_buf = dstring_newstr (); + } + + c = Cmd_Argc (); + + if (c < 2) { + Sys_Printf ("bind [command] : attach a command to a key\n"); + return; + } + + if (!(key = OK_TranslateKeyName (Cmd_Argv (1)))) { + return; + } + dsprintf (cmd_buf, "in_unbind imt_mod %s", key); + Cmd_ExecuteString (cmd_buf->str, src_command); +} + +void +CL_Legacy_Init (void) +{ + OK_Init (); + Cmd_AddCommand ("bind", cl_bind_f, "compatibility wrapper for in_bind"); + Cmd_AddCommand ("unbind", cl_unbind_f, "compatibility wrapper for in_bind"); + // FIXME hashlinks + IN_LoadConfig (PL_GetPropertyList (default_input_config, 0)); +} diff --git a/libs/client/old_keys.c b/libs/client/old_keys.c new file mode 100644 index 000000000..69b008c83 --- /dev/null +++ b/libs/client/old_keys.c @@ -0,0 +1,205 @@ +/* + old_keys.c + + translations from old to new keynames + + Copyright (C) 2001 Bill Currie + + Author: Bill Currie + Date: 2001/8/16 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#if defined(_WIN32) && defined(HAVE_MALLOC_H) +#include +#endif + +#include +#include + +#include "qfalloca.h" + +#include "QF/hash.h" +#include "QF/qtypes.h" +#include "QF/sys.h" + +#include "old_keys.h" + +typedef struct { + const char *old_name; + const char *new_name; +} old_keyname_t; + +old_keyname_t old_keynames[] = { + {"ESCAPE", "key button 0x01"}, + {"1", "key button 0x02"}, + {"2", "key button 0x03"}, + {"3", "key button 0x04"}, + {"4", "key button 0x05"}, + {"5", "key button 0x06"}, + {"6", "key button 0x07"}, + {"7", "key button 0x08"}, + {"8", "key button 0x09"}, + {"9", "key button 0x0a"}, + {"0", "key button 0x0b"}, + {"-", "key button 0x0c"}, + {"=", "key button 0x0d"}, + {"BACKSPACE", "key button 0x0e"}, + {"TAB", "key button 0x0f"}, + + {"Q", "key button 0x10"}, + {"W", "key button 0x11"}, + {"E", "key button 0x12"}, + {"R", "key button 0x13"}, + {"T", "key button 0x14"}, + {"Y", "key button 0x15"}, + {"U", "key button 0x16"}, + {"I", "key button 0x17"}, + {"O", "key button 0x18"}, + {"P", "key button 0x19"}, + {"[", "key button 0x1a"}, + {"]", "key button 0x1b"}, + {"ENTER", "key button 0x1c"}, + {"CTRL", "key button 0x1d"}, + {"A", "key button 0x1e"}, + {"S", "key button 0x1f"}, + + {"D", "key button 0x20"}, + {"F", "key button 0x21"}, + {"G", "key button 0x22"}, + {"H", "key button 0x23"}, + {"J", "key button 0x24"}, + {"K", "key button 0x25"}, + {"L", "key button 0x26"}, + {"SEMICOLON", "key button 0x27"}, + {"'", "key button 0x28"}, + {"`", "key button 0x29"}, + {"SHIFT", "key button 0x2a"}, + {"\\", "key button 0x2b"}, + {"Z", "key button 0x2c"}, + {"X", "key button 0x2d"}, + {"C", "key button 0x2e"}, + {"V", "key button 0x2f"}, + + {"B", "key button 0x30"}, + {"N", "key button 0x31"}, + {"M", "key button 0x32"}, + {",", "key button 0x33"}, + {".", "key button 0x34"}, + {"/", "key button 0x35"}, + // quake had no right shift + {"*", "key button 0x37"}, + {"ALT", "key button 0x38"}, + {"SPACE", "key button 0x39"}, + //{"CAPSLOCK", "key button 0x3a"}, quake had no way of binding capslock + {"F1", "key button 0x3b"}, + {"F2", "key button 0x3c"}, + {"F3", "key button 0x3d"}, + {"F4", "key button 0x3e"}, + {"F5", "key button 0x3f"}, + + {"F6", "key button 0x40"}, + {"F7", "key button 0x41"}, + {"F8", "key button 0x42"}, + {"F9", "key button 0x43"}, + {"F10", "key button 0x44"}, + {"PAUSE", "key button 0x45"}, + {"SCRLCK", "key button 0x46"}, + {"HOME", "key button 0x47"}, + {"UPARROW", "key button 0x48"}, + {"PGUP", "key button 0x49"}, + //{"-", "key button 0x4a"}, quake had no way of binding kp - + {"LEFTARROW", "key button 0x4b"}, + //{"5", "key button 0x4c"}, quake had no way of binding kp 5 + {"RIGHTARROW", "key button 0x4d"}, + {"+", "key button 0x4e"}, + {"END", "key button 0x4f"}, + {"DOWNARROW", "key button 0x50"}, + {"PGDN", "key button 0x51"}, + {"INS", "key button 0x52"}, + {"DEL", "key button 0x53"}, + // nothing 0x54 + // nothing 0x55 + // nothing 0x56 + {"F11", "key button 0x57"}, + {"F12", "key button 0x58"}, + + {";", "key button 0x27"}, + {":", "key button 0x27"}, + + {"MOUSE1", "mouse button 0"}, + {"MOUSE2", "mouse button 2"}, + {"MOUSE3", "mouse button 1"}, + {"MOUSE6", "mouse button 5"}, + {"MOUSE7", "mouse button 6"}, + + {"MWHEELUP", "mouse button 3"}, + {"MWHEELDOWN", "mouse button 4"}, + + {0, 0} +}; + +hashtab_t *old_key_table; + +static const char * +ok_get_key (const void *_ok, void *unused) +{ + old_keyname_t *ok = (old_keyname_t *)_ok; + return ok->old_name; +} + +void +OK_Init (void) +{ + old_keyname_t *ok; + + old_key_table = Hash_NewTable (1021, ok_get_key, 0, 0, 0); + for (ok = old_keynames; ok->old_name; ok++) + Hash_Add (old_key_table, ok); +} + +const char * +OK_TranslateKeyName (const char *name) +{ + old_keyname_t *ok; + char *uname = alloca (strlen (name) + 1); + const char *s = name; + char *d = uname; + + while ((*d++ = toupper ((byte) *s))) + s++; + ok = Hash_Find (old_key_table, uname); + if (!ok) { + Sys_Printf ("unknown old keyname: %s\n", uname); + return 0; + } + return ok->new_name; +} diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index 6e9db94df..6bda3f0f3 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -17,7 +17,6 @@ libs_input_libQFinput_la_LDFLAGS= $(lib_ldflags) libs_input_libQFinput_la_LIBADD= $(input_deps) libs_input_libQFinput_la_DEPENDENCIES= $(input_deps) libs_input_libQFinput_la_SOURCES= \ - libs/input/old_keys.c \ libs/input/in_axis.c \ libs/input/in_binding.c \ libs/input/in_button.c \ diff --git a/libs/input/old_keys.c b/libs/input/old_keys.c deleted file mode 100644 index e96cc02ff..000000000 --- a/libs/input/old_keys.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - old_keys.c - - translations from old to new keynames - - Copyright (C) 2001 Bill Currie - - Author: Bill Currie - Date: 2001/8/16 - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#if defined(_WIN32) && defined(HAVE_MALLOC_H) -#include -#endif - -#include -#include - -#include "qfalloca.h" - -#include "QF/hash.h" -#include "QF/qtypes.h" -#include "QF/sys.h" - -#include "old_keys.h" - -typedef struct { - const char *old_name; - const char *new_name; -} old_keyname_t; - -old_keyname_t old_keynames[] = { - {"TAB", "K_TAB"}, - {"ENTER", "K_RETURN"}, - {"ESCAPE", "K_ESCAPE"}, - {"SPACE", "K_SPACE"}, - {"BACKSPACE", "K_BACKSPACE"}, - - {"CAPSLOCK", "K_CAPSLOCK"}, - {"PRINTSCR", "K_PRINT"}, - {"SCRLCK", "K_SCROLLOCK"}, - {"PAUSE", "K_PAUSE"}, - - {"UPARROW", "K_UP"}, - {"DOWNARROW", "K_DOWN"}, - {"LEFTARROW", "K_LEFT"}, - {"RIGHTARROW", "K_RIGHT"}, - - {"ALT", "K_LALT"}, - {"CTRL", "K_LCTRL"}, - {"SHIFT", "K_LSHIFT"}, - - {"NUMLOCK", "K_NUMLOCK"}, - {"KP_NUMLCK", "K_NUMLOCK"}, - {"KP_NUMLOCK", "K_NUMLOCK"}, - {"KP_SLASH", "K_KP_DIVIDE"}, - {"KP_DIVIDE", "K_KP_DIVIDE"}, - {"KP_STAR", "K_KP_MULTIPLY"}, - {"KP_MULTIPLY", "K_KP_MULTIPLY"}, - {"KP_MINUS", "K_KP_MINUS"}, - - {"KP_HOME", "K_KP7"}, - {"KP_UPARROW", "K_KP8"}, - {"KP_PGUP", "K_KP9"}, - {"KP_PLUS", "K_KP_PLUS"}, - - {"KP_LEFTARROW", "K_KP4"}, - {"KP_5", "K_KP5"}, - {"KP_RIGHTARROW", "K_KP6"}, - - {"KP_END", "K_KP1"}, - {"KP_DOWNARROW", "K_KP2"}, - {"KP_PGDN", "K_KP3"}, - - {"KP_INS", "K_KP0"}, - {"KP_DEL", "K_KP_PERIOD"}, - {"KP_ENTER", "K_KP_ENTER"}, - - {"F1", "K_F1"}, - {"F2", "K_F2"}, - {"F3", "K_F3"}, - {"F4", "K_F4"}, - {"F5", "K_F5"}, - {"F6", "K_F6"}, - {"F7", "K_F7"}, - {"F8", "K_F8"}, - {"F9", "K_F9"}, - {"F10", "K_F10"}, - {"F11", "K_F11"}, - {"F12", "K_F12"}, - - {"INS", "K_INSERT"}, - {"DEL", "K_DELETE"}, - {"PGDN", "K_PAGEDOWN"}, - {"PGUP", "K_PAGEUP"}, - {"HOME", "K_HOME"}, - {"END", "K_END"}, - - {"MOUSE1", "M_BUTTON1"}, - {"MOUSE2", "M_BUTTON2"}, - {"MOUSE3", "M_BUTTON3"}, - {"MOUSE6", "M_BUTTON6"}, - {"MOUSE7", "M_BUTTON7"}, - - {"JOY1", "J_BUTTON1"}, - {"JOY2", "J_BUTTON2"}, - {"JOY3", "J_BUTTON3"}, - {"JOY4", "J_BUTTON4"}, - - {"MWHEELUP", "M_WHEEL_UP"}, - {"MWHEELDOWN", "M_WHEEL_DOWN"}, - - {"ASC178", "K_WORLD_18"}, - {"ASC233", "K_WORLD_73"}, - {"ASC167", "K_WORLD_7"}, - {"ASC232", "K_WORLD_72"}, - {"ASC231", "K_WORLD_71"}, - {"ASC224", "K_WORLD_64"}, - - {"0", "K_0"}, - {"1", "K_1"}, - {"2", "K_2"}, - {"3", "K_3"}, - {"4", "K_4"}, - {"5", "K_5"}, - {"6", "K_6"}, - {"7", "K_7"}, - {"8", "K_8"}, - {"9", "K_9"}, - - {"A", "K_a"}, - {"B", "K_b"}, - {"C", "K_c"}, - {"D", "K_d"}, - {"E", "K_e"}, - {"F", "K_f"}, - {"G", "K_g"}, - {"H", "K_h"}, - {"I", "K_i"}, - {"J", "K_j"}, - {"K", "K_k"}, - {"L", "K_l"}, - {"M", "K_m"}, - {"N", "K_n"}, - {"O", "K_o"}, - {"P", "K_p"}, - {"Q", "K_q"}, - {"R", "K_r"}, - {"S", "K_s"}, - {"T", "K_t"}, - {"U", "K_u"}, - {"V", "K_v"}, - {"W", "K_w"}, - {"X", "K_x"}, - {"Y", "K_y"}, - {"Z", "K_z"}, - - {" ", "K_SPACE"}, - {"!", "K_EXCLAIM"}, - {"DOUBLEQUOTE", "K_QUOTEDBL"}, - {"#", "K_HASH"}, - {"$", "K_DOLLAR"}, - {"&", "K_AMPERSAND"}, - {"'", "K_QUOTE"}, - {"(", "K_LEFTPAREN"}, - {")", "K_RIGHTPAREN"}, - {"*", "K_ASTERISK"}, - {"+", "K_PLUS"}, - {",", "K_COMMA"}, - {"-", "K_MINUS"}, - {".", "K_PERIOD"}, - {"/", "K_SLASH"}, - - {":", "K_COLON"}, - {"SEMICOLON", "K_SEMICOLON"}, - {"<", "K_LESS"}, - {"=", "K_EQUALS"}, - {">", "K_GREATER"}, - {"?", "K_QUESTION"}, - {"@", "K_AT"}, - - {"[", "K_LEFTBRACKET"}, - {"\\", "K_BACKSLASH"}, - {"]", "K_RIGHTBRACKET"}, - {"^", "K_CARET"}, - {"_", "K_UNDERSCORE"}, - {"`", "K_BACKQUOTE"}, - {"~", "K_BACKQUOTE"}, - - {0, 0} -}; - -hashtab_t *old_key_table; - -static const char * -ok_get_key (const void *_ok, void *unused) -{ - old_keyname_t *ok = (old_keyname_t *)_ok; - return ok->old_name; -} - -void -OK_Init (void) -{ - old_keyname_t *ok; - - old_key_table = Hash_NewTable (1021, ok_get_key, 0, 0, 0); - for (ok = old_keynames; ok->old_name; ok++) - Hash_Add (old_key_table, ok); -} - -const char * -OK_TranslateKeyName (const char *name) -{ - old_keyname_t *ok; - char *uname = alloca (strlen (name) + 1); - const char *s = name; - char *d = uname; - - while ((*d++ = toupper ((byte) *s))) - s++; - ok = Hash_Find (old_key_table, uname); - if (!ok) { - Sys_Printf ("unknown old keyname: %s\n", uname); - return name; - } - return ok->new_name; -} diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 5e788a195..95be1d38c 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -48,6 +48,8 @@ #include "compat.h" +#include "client/input.h" + #include "nq/include/chase.h" #include "nq/include/client.h" #include "nq/include/host.h" @@ -432,6 +434,7 @@ CL_Input_Init (cbuf_t *cbuf) IMT_SetContextCbuf (cl_demo_context, cbuf); Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); + CL_Legacy_Init (); } void diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 811ff697c..daf3b7019 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -50,6 +50,7 @@ #include "compat.h" +#include "client/input.h" #include "client/view.h" #include "qw/msg_ucmd.h" @@ -590,6 +591,7 @@ CL_Input_Init (void) IMT_SetContextCbuf (cl_demo_context, cl_cbuf); Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); + CL_Legacy_Init (); } void From c4118a4bf19ae2a5fb168867952e7737ac576204 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 17:46:16 +0900 Subject: [PATCH 1866/3664] [util] Add listeners to cvars Listeners are separate to the main callback as listeners have only read-only access to the objects, but the main callback is free to modify the cvar and thus can act as a parser and validator. The listeners are invoked after the main callback if the cvar is modified. There does not need to be a main callback for the listeners to be invoked. --- include/QF/cvar.h | 8 ++++++++ libs/util/cvar.c | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/include/QF/cvar.h b/include/QF/cvar.h index 461ff4bf6..2fe20aafa 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -33,6 +33,7 @@ */ ///@{ +#include "QF/listener.h" #include "QF/qtypes.h" #include "QF/quakeio.h" @@ -51,6 +52,7 @@ typedef struct cvar_s { \param var This cvar. */ void (*callback)(struct cvar_s *var); + struct cvar_listener_set_s *listeners; const char *description; ///< for "help" command float value; ///< The current cvar value as a float int int_val; ///< The current cvar value as an integer @@ -58,6 +60,10 @@ typedef struct cvar_s { struct cvar_s *next; ///< \internal Linked list of cvars. } cvar_t; +typedef struct cvar_listener_set_s LISTENER_SET_TYPE (cvar_t) + cvar_listener_set_t; +typedef void (*cvar_listener_t) (void *data, const cvar_t *cvar); + typedef struct cvar_alias_s { char *name; ///< The name of the alias. cvar_t *cvar; ///< The cvar to which this alias refers @@ -97,6 +103,8 @@ cvar_t *Cvar_FindAlias (const char *alias_name); cvar_t *Cvar_MakeAlias (const char *name, cvar_t *cvar); cvar_t *Cvar_RemoveAlias (const char *name); +void Cvar_AddListener (cvar_t *cvar, cvar_listener_t listener, void *data); +void Cvar_RemoveListener (cvar_t *cvar, cvar_listener_t listener, void *data); // equivelants to " " typed at the console void Cvar_Set (cvar_t *var, const char *value); diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 333e1ca9b..add043f11 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -249,6 +249,24 @@ Cvar_CompleteBuildList (const char *partial) return buf; } +VISIBLE void +Cvar_AddListener (cvar_t *cvar, cvar_listener_t listener, void *data) +{ + if (!cvar->listeners) { + cvar->listeners = malloc (sizeof (*cvar->listeners)); + LISTENER_SET_INIT (cvar->listeners, 8); + } + LISTENER_ADD (cvar->listeners, listener, data); +} + +VISIBLE void +Cvar_RemoveListener (cvar_t *cvar, cvar_listener_t listener, void *data) +{ + if (cvar->listeners) { + LISTENER_REMOVE (cvar->listeners, listener, data); + } +} + VISIBLE void Cvar_Set (cvar_t *var, const char *value) { @@ -279,6 +297,10 @@ Cvar_Set (cvar_t *var, const char *value) if (var->callback) var->callback (var); + + if (var->listeners) { + LISTENER_INVOKE (var->listeners, var); + } } } @@ -710,7 +732,7 @@ VISIBLE cvar_t * Cvar_Get (const char *name, const char *string, int cvarflags, void (*callback)(cvar_t*), const char *description) { - + int changed = 0; cvar_t *var; if (Cmd_Exists (name)) { @@ -740,10 +762,13 @@ Cvar_Get (const char *name, const char *string, int cvarflags, break; var->next = *v; *v = var; + + changed = 1; } else { // Cvar does exist, so we update the flags and return. var->flags &= ~CVAR_USER_CREATED; var->flags |= cvarflags; + changed = !strequal (var->string, string) || var->callback != callback; if (!var->callback) var->callback = callback; if (!var->description @@ -753,8 +778,14 @@ Cvar_Get (const char *name, const char *string, int cvarflags, if (!var->default_string) var->default_string = strdup (string); } - if (var->callback) - var->callback (var); + if (changed) { + if (var->callback) + var->callback (var); + + if (var->listeners) { + LISTENER_INVOKE (var->listeners, var); + } + } return var; } From 8e8a573876b00d74db520ea5609294628c02e5c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 17:52:27 +0900 Subject: [PATCH 1867/3664] [input] Add listeners to buttons The listener is invoked when the button state changes. --- include/QF/input/binding.h | 13 +++++++++++++ libs/input/in_button.c | 26 ++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index ddcb4c35a..704cd61e7 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -31,6 +31,7 @@ #ifndef __QFCC__ +#include "QF/listener.h" #include "QF/mathlib.h" /*** Recipe for converting an axis to a floating point value. @@ -114,10 +115,18 @@ typedef enum { typedef struct in_button_s { int down[2]; ///< button ids holding this button down int state; ///< in_button_state + struct button_listener_set_s *listeners; const char *name; const char *description; } in_button_t; +typedef struct button_listener_set_s LISTENER_SET_TYPE (in_button_t) + button_listener_set_t; + +/*** Function type for button listeners. +*/ +typedef void (*button_listener_t) (void *data, const in_button_t *button); + typedef struct in_axisbinding_s { in_recipe_t *recipe; in_axis_t *axis; @@ -307,6 +316,10 @@ int IN_RegisterButton (in_button_t *button); int IN_RegisterAxis (in_axis_t *axis); in_button_t *IN_FindButton (const char *name); in_axis_t *IN_FindAxis (const char *name); +void IN_ButtonAddListener (in_button_t *button, button_listener_t listener, + void *data); +void IN_ButtonRemoveListener (in_button_t *button, button_listener_t listener, + void *data); struct IE_event_s; int IN_Binding_HandleEvent (const struct IE_event_s *ie_event); diff --git a/libs/input/in_button.c b/libs/input/in_button.c index 17cfc5944..15d28160d 100644 --- a/libs/input/in_button.c +++ b/libs/input/in_button.c @@ -87,6 +87,9 @@ button_press (in_button_t *button, int id) return; } button->state |= inb_down | inb_edge_down; + if (button->listeners) { + LISTENER_INVOKE (button->listeners, button); + } } static void @@ -118,6 +121,9 @@ button_release (in_button_t *button, int id) } button->state &= ~inb_down; // now up button->state |= inb_edge_up; + if (button->listeners) { + LISTENER_INVOKE (button->listeners, button); + } } void @@ -196,6 +202,26 @@ IN_FindButton (const char *name) return 0; } +void +IN_ButtonAddListener (in_button_t *button, button_listener_t listener, + void *data) +{ + if (!button->listeners) { + button->listeners = malloc (sizeof (*button->listeners)); + LISTENER_SET_INIT (button->listeners, 8); + } + LISTENER_ADD (button->listeners, listener, data); +} + +void +IN_ButtonRemoveListener (in_button_t *button, button_listener_t listener, + void *data) +{ + if (button->listeners) { + LISTENER_REMOVE (button->listeners, listener, data); + } +} + static void __attribute__((constructor)) in_button_init (void) { From 1a79915d225afaf95f451dce4f7200e901319008 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 17:55:22 +0900 Subject: [PATCH 1868/3664] [input] Add axis listeners The listener is invoked when the axis value changes due to IN_UpdateAxis or IN_ClampAxis updating the axis. This does mean the listener invocation make be somewhat delayed. I am a tad uncertain about this design thus it being a separate commit. --- include/QF/input/binding.h | 30 +++++++++++++++++++++++++++++- libs/input/in_axis.c | 19 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 704cd61e7..9e70f3240 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -86,10 +86,18 @@ typedef struct in_axis_s { in_axis_mode mode; ///< method used for updating the destination float abs_input; ///< input from an absolute axis (eg, joystick) float rel_input; ///< input from a relative axis (eg, mouse) + struct axis_listener_set_s *listeners; const char *name; const char *description; } in_axis_t; +typedef struct axis_listener_set_s LISTENER_SET_TYPE (in_axis_t) + axis_listener_set_t; + +/*** Function type for axis listeners. +*/ +typedef void (*axis_listener_t) (void *data, const in_axis_t *axis); + /*** Current state of the logical button. Captures the current state and any transitions during the last frame. @@ -285,6 +293,7 @@ VISIBLE float IN_UpdateAxis (in_axis_t *axis) { + float prev_value = axis->value; switch (axis->mode) { case ina_set: axis->value = axis->abs_input + axis->rel_input; @@ -294,6 +303,9 @@ IN_UpdateAxis (in_axis_t *axis) break; } axis->rel_input = 0; + if (axis->value != prev_value && axis->listeners) { + LISTENER_INVOKE (axis->listeners, axis); + } return axis->value; } @@ -305,8 +317,20 @@ VISIBLE float IN_ClampAxis (in_axis_t *axis, float minval, float maxval) { - IN_UpdateAxis (axis); + float prev_value = axis->value; + switch (axis->mode) { + case ina_set: + axis->value = axis->abs_input + axis->rel_input; + break; + case ina_accumulate: + axis->value += axis->abs_input + axis->rel_input; + break; + } + axis->rel_input = 0; axis->value = bound (minval, axis->value, maxval); + if (axis->value != prev_value && axis->listeners) { + LISTENER_INVOKE (axis->listeners, axis); + } return axis->value; } @@ -320,6 +344,10 @@ void IN_ButtonAddListener (in_button_t *button, button_listener_t listener, void *data); void IN_ButtonRemoveListener (in_button_t *button, button_listener_t listener, void *data); +void IN_AxisAddListener (in_axis_t *axis, axis_listener_t listener, + void *data); +void IN_AxisRemoveListener (in_axis_t *axis, axis_listener_t listener, + void *data); struct IE_event_s; int IN_Binding_HandleEvent (const struct IE_event_s *ie_event); diff --git a/libs/input/in_axis.c b/libs/input/in_axis.c index 85489b8b7..ccf061eeb 100644 --- a/libs/input/in_axis.c +++ b/libs/input/in_axis.c @@ -75,6 +75,25 @@ IN_FindAxis (const char *name) return Hash_Find (axis_tab, name); } +void +IN_AxisAddListener (in_axis_t *axis, axis_listener_t listener, void *data) +{ + if (!axis->listeners) { + axis->listeners = malloc (sizeof (*axis->listeners)); + LISTENER_SET_INIT (axis->listeners, 8); + } + LISTENER_ADD (axis->listeners, listener, data); +} + +void +IN_AxisRemoveListener (in_axis_t *axis, axis_listener_t listener, void *data) +{ + if (axis->listeners) { + LISTENER_REMOVE (axis->listeners, listener, data); + } +} + + static void __attribute__((constructor)) in_axis_init (void) { From 62f592b92c3cec280693e751aa9a6eaadc93a721 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 18:01:07 +0900 Subject: [PATCH 1869/3664] [input] Create an automatic imt switcher An imt switcher automatically changes the context's active imt based on a user specified list of binary inputs. The inputs may be either buttons (indicated as +button) or cvars (bare name). For buttons, the pressed/not pressed state is used, and cvars are interpreted as ints being 0 or not 0. The order of the inputs determines the bit number of the input, with the first input being bit 0, second bit 1, third bit 2 etc. A default imt is given so large switchers do not need to be fully configured (the default imt is written to all states). A context can have any number of switchers attached. The switchers can wind up fighting over the active imt, but this seems to be something for the "user" (eg, configuration system) to sort out rather than the switcher code enforcing anything. As a result of the inputs being treated as bits, a switcher with N inputs will have 2**N states, thus there's a maximum of 16 inputs for now as 65536 states is a lot of configuration. Using a switcher, setting up a standard strafe/mouse look configuration is fairly easy. imt_create key_game imt_mod imt_create key_game imt_mod_strafe imt_mod imt_create key_game imt_mod_freelook imt_create key_game imt_mod_lookstrafe imt_mod_freelook imt_switcher_create mouse key_game imt_mod_strafe +strafe lookstrafe +mlook freelook imt_switcher 0 imt_mod 2 imt_mod 4 imt_mod_freelook 8 imt_mod_freelook 12 imt_mod_freelook imt_switcher 6 imt_mod_lookstrafe 10 imt_mod_lookstrafe 14 imt_mod_lookstrafe in_bind imt_mod mouse axis 0 move.yaw in_bind imt_mod mouse axis 1 move.forward in_bind imt_mod_strafe mouse axis 0 move.side in_bind imt_mod_lookstrafe mouse axis 0 move.side in_bind imt_mod_freelook mouse axis 1 move.pitch This takes advantage of imt chaining and the default imt for the switcher (there are 8 states that use imt_mod_strafe). The switcher name must be unique across all contexts, and every imt used in a switcher must be in the switcher's context. --- include/QF/input/imt.h | 28 ++++ libs/input/in_imt.c | 362 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 387 insertions(+), 3 deletions(-) diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 508433e73..9cbf52bcd 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -47,12 +47,36 @@ typedef struct imt_s { struct DARRAY_TYPE (in_buttonbinding_t *) button_bindings; } imt_t; +typedef enum { + imti_button, + imti_cvar, +} imt_input_type; + +typedef struct imt_input_s { + imt_input_type type; + union { + struct in_button_s *button; + struct cvar_s *cvar; + }; +} imt_input_t; + +typedef struct imt_switcher_s { + struct imt_switcher_s *next; + const char *name; + int num_inputs; + imt_input_t *inputs; // one per input + imt_t **imts; // 2**(num_inputs) + struct in_context_s *context; +} imt_switcher_t; + typedef struct in_context_s { const char *name; imt_t *imts; imt_t **imt_tail; imt_t *active_imt; imt_t *default_imt; + imt_switcher_t *switchers; + imt_switcher_t **switcher_tail; struct cbuf_s *cbuf; } in_context_t; @@ -63,8 +87,12 @@ int IMT_GetContext (void) __attribute__ ((pure)); void IMT_SetContext (int ctx); void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf); imt_t *IMT_FindIMT (const char *name) __attribute__ ((pure)); +imt_switcher_t *IMT_FindSwitcher (const char *name) __attribute__ ((pure)); int IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name); +int IMT_CreateSwitcher (const char *switcher_name, + int context, imt_t *default_imt, + int num_inputs, const char **input_names); void IMT_BindAxis (imt_t *imt, int axis_num, in_axis_t *axis, const in_recipe_t *recipe); void IMT_BindButton (imt_t *imt, int button, const char *binding); diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 828b3f36e..0cb2f9bbf 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -41,6 +41,7 @@ #include "QF/cmd.h" #include "QF/cmem.h" +#include "QF/cvar.h" #include "QF/hash.h" #include "QF/input.h" #include "QF/mathlib.h" @@ -53,6 +54,8 @@ #include "QF/input/binding.h" #include "QF/input/imt.h" +#include "qfalloca.h" + /** Describe a region of imt bindings (axis or button) Each device may have a block of axis bindings and a block of button @@ -233,6 +236,7 @@ IMT_CreateContext (const char *name) in_context_t *ctx = DARRAY_OPEN_AT (&in_contexts, in_contexts.size, 1); memset (ctx, 0, sizeof (*ctx)); ctx->imt_tail = &ctx->imts; + ctx->switcher_tail = &ctx->switchers; ctx->name = name; return ctx - in_contexts.a; } @@ -250,6 +254,39 @@ imt_find_context (const char *name) return 0; } +static void +imt_switcher_update (imt_switcher_t *switcher) +{ + int state = 0; + + for (int i = 0; i < switcher->num_inputs; i++) { + imt_input_t *input = &switcher->inputs[i]; + int val = 0; + switch (input->type) { + case imti_button: + val = !!(input->button->state & inb_down); + break; + case imti_cvar: + val = !!input->cvar->int_val; + break; + } + state |= val << i; + } + switcher->context->active_imt = switcher->imts[state]; +} + +static void +imt_switcher_button_update (void *_switcher, const in_button_t *button) +{ + imt_switcher_update (_switcher); +} + +static void +imt_switcher_cvar_update (void *_switcher, const cvar_t *cvar) +{ + imt_switcher_update (_switcher); +} + int IMT_GetContext (void) { @@ -263,6 +300,10 @@ IMT_SetContext (int ctx) Sys_Error ("IMT_SetContext: invalid context %d", ctx); } imt_current_context = ctx; + for (imt_switcher_t *switcher = in_contexts.a[ctx].switchers; switcher; + switcher = switcher->next) { + imt_switcher_update (switcher); + } } void @@ -298,6 +339,31 @@ IMT_FindIMT (const char *name) return 0; } +static imt_switcher_t * __attribute__((pure)) +imt_find_switcher (in_context_t *ctx, const char *name) +{ + for (imt_switcher_t *switcher = ctx->switchers; switcher; + switcher = switcher->next) { + if (strcasecmp (switcher->name, name) == 0) { + return switcher; + } + } + return 0; +} + +imt_switcher_t * +IMT_FindSwitcher (const char *name) +{ + for (size_t i = 0; i < in_contexts.size; i++) { + in_context_t *ctx = &in_contexts.a[i]; + imt_switcher_t *switcher = imt_find_switcher (ctx, name); + if (switcher) { + return switcher; + } + } + return 0; +} + int IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name) { @@ -356,6 +422,87 @@ IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name) return 1; } +int +IMT_CreateSwitcher (const char *switcher_name, int context, imt_t *default_imt, + int num_inputs, const char **input_names) +{ + if (IMT_FindSwitcher (switcher_name)) { + Sys_Printf ("imt switcher %s already exists\n", switcher_name); + return 0; + } + + if ((size_t) context >= in_contexts.size) { + Sys_Printf ("invalid imt context %d\n", context); + return 0; + } + in_context_t *ctx = &in_contexts.a[context]; + + if (!imt_find_imt (ctx, default_imt->name)) { + Sys_Printf ("default imt %s not in context %s\n", + default_imt->name, ctx->name); + return 0; + } + + int input_error = 0; + if (num_inputs > 16) { + Sys_Printf ("too many inputs %d\n", num_inputs); + return 0; + } + for (int i = 0; i < num_inputs; i++) { + const char *input_name = input_names[i]; + if (!input_name) { + input_error = 1; + continue; + } + if (input_name[0] == '+') { + if (!IN_FindButton (input_name + 1)) { + Sys_Printf ("invalid button %s\n", input_name); + input_error = 1; + } + } else { + if (!Cvar_FindVar (input_name)) { + Sys_Printf ("invalid cvar %s\n", input_name); + input_error = 1; + } + } + } + if (input_error) { + return 0; + } + int num_states = 1 << num_inputs; + size_t size = sizeof (imt_switcher_t) + + num_inputs * sizeof (imt_input_t) + + num_states * sizeof (imt_t *); + imt_switcher_t *switcher = malloc (size); + *ctx->switcher_tail = switcher; + ctx->switcher_tail = &switcher->next; + + switcher->next = 0; + switcher->name = strdup (switcher_name); + switcher->num_inputs = num_inputs; + switcher->inputs = (imt_input_t *) (switcher + 1); + switcher->imts = (imt_t **) (switcher->inputs + num_inputs); + switcher->context = ctx; + for (int i = 0; i < num_inputs; i++) { + imt_input_t *input = &switcher->inputs[i]; + const char *input_name = input_names[i]; + if (input_name[0] == '+') { + input->type = imti_button; + input->button = IN_FindButton (input_name + 1); + IN_ButtonAddListener (input->button, imt_switcher_button_update, + switcher); + } else { + input->type = imti_cvar; + input->cvar = Cvar_FindVar (input_name); + Cvar_AddListener (input->cvar, imt_switcher_cvar_update, switcher); + } + } + for (int i = 0; i < num_states; i++) { + switcher->imts[i] = default_imt; + } + return 1; +} + void IMT_BindAxis (imt_t *imt, int axis_num, in_axis_t *axis, const in_recipe_t *recipe) @@ -593,6 +740,79 @@ imt_create_f (void) IMT_CreateIMT (ctx - in_contexts.a, imt_name, chain_imt_name); } +static void +imt_switcher_create_f (void) +{ + int argc = Cmd_Argc (); + + if (argc < 5) { + Sys_Printf ("see help imt_switcher_create\n"); + return; + } + + const char *switcher_name = Cmd_Argv (1); + const char *context_name = Cmd_Argv (2); + const char *default_imt_name = Cmd_Argv (3); + + in_context_t *ctx = imt_find_context (context_name); + if (!ctx) { + Sys_Printf ("imt error: invalid context: %s\n", context_name); + return; + } + + imt_t *default_imt = imt_find_imt (ctx, default_imt_name); + if (!default_imt) { + Sys_Printf ("default imt %s not in context %s\n", + default_imt_name, context_name); + return; + } + + int num_inputs = argc - 4; + const char **input_names = alloca (num_inputs * sizeof (const char*)); + for (int i = 0; i < num_inputs; i++) { + input_names[i] = Cmd_Argv (i + 4); + } + + IMT_CreateSwitcher (switcher_name, ctx - in_contexts.a, default_imt, + num_inputs, input_names); +} + +static void +imt_switcher_f (void) +{ + int argc = Cmd_Argc (); + + // state/imt pairs result in an even number of arguments + if (argc < 4 || (argc & 1)) { + Sys_Printf ("see help imt_switcher\n"); + return; + } + const char *switcher_name = Cmd_Argv (1); + imt_switcher_t *switcher = IMT_FindSwitcher (switcher_name); + if (!switcher) { + Sys_Printf ("switcher %s does not exist\n", switcher_name); + return; + } + int num_states = 1 << switcher->num_inputs; + for (int i = 2; i < argc; i += 2) { + const char *state_str = Cmd_Argv (i + 0); + const char *imt_name = Cmd_Argv (i + 1); + char *end; + int state = strtol (state_str, &end, 0); + imt_t *imt = imt_find_imt (switcher->context, imt_name); + if (*end || state < 0 || state >= num_states) { + Sys_Printf ("invalid state: %s\n", state_str); + continue; + } + if (!imt) { + Sys_Printf ("imt %s not in context %s\n", + imt_name, switcher->context->name); + continue; + } + switcher->imts[state] = imt; + } +} + static void imt_drop_all_f (void) { @@ -610,9 +830,31 @@ imt_drop_all_f (void) free ((char *) imt->name); free (imt); } + while (ctx->switchers) { + imt_switcher_t *switcher = ctx->switchers; + ctx->switchers = switcher->next; + for (int i = 0; i < switcher->num_inputs; i++) { + imt_input_t *input = &switcher->inputs[i]; + switch (input->type) { + case imti_button: + IN_ButtonRemoveListener (input->button, + imt_switcher_button_update, + switcher); + break; + case imti_cvar: + Cvar_RemoveListener (input->cvar, + imt_switcher_cvar_update, + switcher); + break; + } + } + free ((char *) switcher->name); + free (switcher); + } ctx->active_imt = 0; ctx->default_imt = 0; ctx->imt_tail = &ctx->imts; + ctx->switcher_tail = &ctx->switchers; } } @@ -631,11 +873,47 @@ static imtcmd_t imt_commands[] = { }, { "imt_create", imt_create_f, "create a new imt table:\n" - " imt_create [chain_name]\n" + " imt_create [chain_name]\n" "\n" - "The new table will be attached to the specified keydest\n" + "The new table will be attached to the specified context\n" "imt_name must not already exist.\n" - "If given, chain_name must already exist and be on keydest.\n" + "If given, chain_name must already exist and be in the context.\n" + }, + { "imt_switcher_create", imt_switcher_create_f, + "create a new imt switcher:\n" + " imt_switcher_create " + " [..]\n" + "name is the name of the switcher and must be unique across all\n" + "contexts\n" + "The new switcher will be attached to the specified context\n" + "default_imt specifies the default imt to be used for all possible\n" + "states and must axis and be in the context.\n" + "input0..inputN specify the inputs (cvar or button) used to set the\n" + "switcher's state. As each input forms a bit in the state index,\n" + "there will be 2**(N+1) states (so 4 inputs will result in 16\n" + "states, and 16 inputs will result in 65536 states). Up to 16 inputs\n" + "are allowed\n" + "\n" + "Buttons are spefied as +buttonname (eg, +mlook, +strafe).\n" + "Cvars are just the cvar name (eg, freelook, lookstrafe).\n" + "\n" + "Use imt_switcher to set the imt for each state.\n" + "\n" + "There can be multiple switchers in a context, but they can wind up\n" + "fighting over the active imt for the context if they share inputs.\n" + }, + { "imt_switcher", imt_switcher_f, + "Set the imts for states in an imt switcher:\n" + " imt_switcher " + " [.. ]\n" + "name is the name of the switcher to be modifed and must exist\n" + "state_index is the state index formed by the binary number\n" + "interpretation of the inputs with input0 being bit 0 and inputN\n" + "being bit N.\n" + "imt is the name of the imt to be assigned to the state and must\n" + "exist and be in the same context as the switcher.\n" + "\n" + "Any number of state_index imt pairs can be specified.\n" }, { "imt_drop_all", imt_drop_all_f, "delete all imt tables\n" @@ -685,6 +963,43 @@ IMT_SaveConfig (plitem_t *config) PL_D_AddObject (ctx, "default_imt", PL_NewString (context->default_imt->name)); } + if (context->switchers) { + plitem_t *switcher_list = PL_NewArray (); + PL_D_AddObject (ctx, "switchers", switcher_list); + for (imt_switcher_t *switcher = context->switchers; switcher; + switcher = switcher->next) { + //FIXME hashlinks + plitem_t *switcher_cfg = PL_NewDictionary (0); + PL_A_AddObject (switcher_list, switcher_cfg); + + PL_D_AddObject (switcher_cfg, "name", + PL_NewString (switcher->name)); + + plitem_t *input_list = PL_NewArray (); + PL_D_AddObject (switcher_cfg, "inputs", input_list); + for (int i = 0; i < switcher->num_inputs; i++) { + imt_input_t *input = &switcher->inputs[i]; + const char *name = 0; + switch (input->type) { + case imti_button: + name = va (0, "+%s", input->button->name); + break; + case imti_cvar: + name = input->cvar->name; + break; + } + PL_A_AddObject (input_list, PL_NewString (name)); + } + + plitem_t *state_list = PL_NewArray (); + PL_D_AddObject (switcher_cfg, "imts", state_list); + int num_states = 1 << switcher->num_inputs; + for (int i = 0; i < num_states; i++) { + imt_t *imt = switcher->imts[i]; + PL_A_AddObject (state_list, PL_NewString (imt->name)); + } + } + } } } @@ -792,5 +1107,46 @@ IMT_LoadConfig (plitem_t *config) context->default_imt = context->imts; } context->active_imt = context->default_imt; + + plitem_t *switcher_list = PL_ObjectForKey (ctx, "switchers"); + if (!switcher_list || PL_Type (switcher_list) != QFArray) { + continue; + } + for (int j = 0, num_switchers = PL_A_NumObjects (switcher_list); + j < num_switchers; j++) { + plitem_t *switcher = PL_ObjectAtIndex (switcher_list, j); + const char *name = PL_String (PL_ObjectForKey (switcher, "name")); + plitem_t *input_list = PL_ObjectForKey (switcher, "inputs"); + if (!name || !input_list || PL_Type (input_list) != QFArray) { + continue; + } + int num_inputs = PL_A_NumObjects (input_list); + const char **input_names = alloca (num_inputs * sizeof (char *)); + for (int k = 0; k < num_inputs; k++) { + input_names[k] = PL_String (PL_ObjectAtIndex (input_list, k)); + } + if (!IMT_CreateSwitcher (name, context - in_contexts.a, + context->default_imt, + num_inputs, input_names)) { + continue; + } + imt_switcher_t *s = imt_find_switcher (context, name); + + plitem_t *imt_list = PL_ObjectForKey (switcher, "imts"); + if (!imt_list || PL_Type (imt_list) != QFArray) { + continue; + } + for (int k = 0, count = PL_A_NumObjects (imt_list); k < count; + k++) { + const char *imt_name = PL_String(PL_ObjectAtIndex(imt_list, k)); + if (!imt_name) { + continue; + } + imt_t *imt = imt_find_imt (context, imt_name); + if (imt) { + s->imts[k] = imt; + } + } + } } } From d1153be5942a6e04dcafad167064a7fd5d16055a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 19:59:17 +0900 Subject: [PATCH 1870/3664] [build] Move plist rules to root Makefile They are globally useful rather than specific to the vulkan renderer. --- Makefile.am | 11 +++++++++++ libs/video/renderer/Makemodule.am | 11 +---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2187fb642..dbc83cea2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,6 +30,7 @@ AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CF common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@ +SUFFICES = TESTS = XFAIL_TESTS = bin_PROGRAMS = @@ -119,6 +120,16 @@ V_XXD_ = $(V_XXD_@AM_DEFAULT_V@) V_XXD_0 = @echo " XXD " $@; V_XXD_1 = +V_SED = $(V_SED_@AM_V@) +V_SED_ = $(V_SED_@AM_DEFAULT_V@) +V_SED_0 = @echo " SED " $@; +V_SED_1 = + +SUFFICES += .plist .plc +.plist.plc: + $(V_SED)sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\ + $(am__mv) $@.t $@ + %.spv: % @$(mkdir_p) $(builddir)/`dirname $@` $(V_GLSLANG)(((($(GLSLANGVALIDATOR) -V $< -o $@; echo $$? >&3) | sed -e '1d' 1>&2) 3>&1) | (read xs; exit $$xs)) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 9fc6fced0..c5ff6407a 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -91,20 +91,11 @@ libs_video_renderer_librender_gl_la_SOURCES = \ shader_src= libs/video/renderer/glsl/quakeforge.glsl shader_gen= libs/video/renderer/glsl/quakeforge.slc -V_SED = $(V_SED_@AM_V@) -V_SED_ = $(V_SED_@AM_DEFAULT_V@) -V_SED_0 = @echo " SED " $@; -V_SED_1 = - -SUFFICES=.frag .vert .spv .spvc .fc .vc .slc .glsl .plist .plc +SUFFICES += .frag .vert .spv .spvc .fc .vc .slc .glsl .glsl.slc: $(V_SED)sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\ $(am__mv) $@.t $@ -.plist.plc: - $(V_SED)sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\ - $(am__mv) $@.t $@ - video_renderer_glsl_libs= \ libs/video/renderer/librender_glsl.la \ libs/models/libmodels_glsl.la From b01c38903d535eb2ade2296550e9bad93683baa6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 20:01:13 +0900 Subject: [PATCH 1871/3664] [x11] Clamp barriers to the screen It seems X11 does not like creating barriers entirely off the screen, though the error seems to be a little unreliable (however, off the left edge was definitely bad). --- include/context_x11.h | 2 ++ libs/video/targets/context_x11.c | 4 ++++ libs/video/targets/in_x11.c | 8 ++++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/context_x11.h b/include/context_x11.h index ec29458d6..0bc29df44 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -52,6 +52,8 @@ extern Window x_win; extern Colormap x_cmap; extern XVisualInfo *x_visinfo; extern int x_screen; +extern int x_width; +extern int x_height; extern int x_shmeventtype; extern Time x_time; extern Time x_mouse_time; diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 94df3b68f..0f960d7a4 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -82,6 +82,8 @@ static Cursor nullcursor = None; Display *x_disp = NULL; int x_screen; +int x_width; +int x_height; Window x_root = None; XVisualInfo *x_visinfo; Visual *x_vis; @@ -283,6 +285,8 @@ X11_OpenDisplay (void) False); x_screen = DefaultScreen (x_disp); + x_width = DisplayWidth (x_disp, x_screen); + x_height = DisplayHeight (x_disp, x_screen); x_root = RootWindow (x_disp, x_screen); XSynchronize (x_disp, true); // only for debugging diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 3b2c53d04..8b0d6937d 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -1415,10 +1415,10 @@ in_x11_setup_barriers (int xpos, int ypos, int xlen, int ylen) XFixesDestroyPointerBarrier (x_disp, x11_bottom_barrier); } - int lx = xpos; - int ty = ypos; - int rx = xpos + xlen - 1; - int by = ypos + ylen - 1; + int lx = bound (0, xpos, x_width - 1); + int ty = bound (0, ypos, x_height - 1); + int rx = bound (0, xpos + xlen - 1, x_width - 1); + int by = bound (0, ypos + ylen - 1, x_height - 1); x11_left_barrier = XFixesCreatePointerBarrier (x_disp, x_root, lx, ty-1, lx, by+1, BarrierPositiveX, 0, 0); From 70c2fdce9ed63179325cb9fb91f3d9dc1d63ffb3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 Nov 2021 20:02:48 +0900 Subject: [PATCH 1872/3664] [client] Move default input config to its own file This makes it much easier to maintain the config. --- libs/client/Makemodule.am | 5 ++ libs/client/cl_input.c | 36 +-------- libs/client/default_input.plist | 135 ++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 33 deletions(-) create mode 100644 libs/client/default_input.plist diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 1f282f054..24e28397f 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -9,3 +9,8 @@ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_temp_entities.c \ libs/client/locs.c \ libs/client/old_keys.c + +default_input_src = libs/client/default_input.plist +default_input_gen = libs/client/default_input.plc + +libs/client/cl_input.lo: libs/client/cl_input.c $(default_input_gen) diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index f145837ac..75564c559 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -41,39 +41,9 @@ #include "client/input.h" -static const char *default_input_config = "" - "{" - " input = {" - " contexts = (" - " {" - " name = key_game;" - " imts = (" - " {" - " name = imt_mod;" - " }" - " );" - " default_imt = imt_mod;" - " }," - " {" - " name = key_demo;" - " }" - " );" - " devices = (" - " {" - " name = mouse;" - " devname = core:mouse;" - " num_axes = 2;" - " num_buttons = 32;" - " }," - " {" - " name = key;" - " devname = core:keyboard;" - " num_axes = 0;" - " num_buttons = 256;" - " }," - " );" - " };" - "};"; +static const char default_input_config[] = { +#include "libs/client/default_input.plc" +}; static void cl_bind_f (void) diff --git a/libs/client/default_input.plist b/libs/client/default_input.plist new file mode 100644 index 000000000..7e6e03b00 --- /dev/null +++ b/libs/client/default_input.plist @@ -0,0 +1,135 @@ +{ + input = { + contexts = ( + { + name = key_game; + imts = ( + { + name = imt_mod; + }, + { + name = imt_mod_strafe; + chain = imt_mod; + }, + { + name = imt_mod_freelook; + chain = imt_mod; + }, + { + name = imt_mod_lookstrafe; + chain = imt_mod_freelook; + } + ); + default_imt = imt_mod; + switchers = ( + { + name = mouse; + inputs = ( + +strafe, + lookstrafe, + +mlook, + freelook + ); + imts = ( + imt_mod, + imt_mod_strafe, + imt_mod, + imt_mod_strafe, + imt_mod_freelook, + imt_mod_strafe, + imt_mod_lookstrafe, + imt_mod_strafe, + imt_mod_freelook, + imt_mod_strafe, + imt_mod_lookstrafe, + imt_mod_strafe, + imt_mod_freelook, + imt_mod_strafe, + imt_mod_lookstrafe, + imt_mod_strafe + ); + } + ); + }, + { + name = key_demo; + } + ); + devices = ( + { + name = mouse; + devname = core:mouse; + num_axes = 2; + num_buttons = 32; + axes = ( + { + imt = imt_mod; + num = 0; + axis = move.yaw; + min = 0; + max = 0; + minzone = 0; + maxzone = 0; + deadzone = 0; + curve = 1; + scale = 1; + }, + { + imt = imt_mod_strafe; + num = 0; + axis = move.side; + min = 0; + max = 0; + minzone = 0; + maxzone = 0; + deadzone = 0; + curve = 1; + scale = 1; + }, + { + imt = imt_mod_lookstrafe; + num = 0; + axis = move.side; + min = 0; + max = 0; + minzone = 0; + maxzone = 0; + deadzone = 0; + curve = 1; + scale = 1; + }, + { + imt = imt_mod; + num = 1; + axis = move.forward; + min = 0; + max = 0; + minzone = 0; + maxzone = 0; + deadzone = 0; + curve = 1; + scale = 1; + }, + { + imt = imt_mod_freelook; + num = 1; + axis = move.pitch; + min = 0; + max = 0; + minzone = 0; + maxzone = 0; + deadzone = 0; + curve = 1; + scale = 1; + } + ); + }, + { + name = key; + devname = core:keyboard; + num_axes = 0; + num_buttons = 256; + } + ); + }; +} From 413cea6b4a4255c5b08e69819cf88bf75e22089b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 Nov 2021 01:59:18 +0900 Subject: [PATCH 1873/3664] [qw,nq] Connect up key_demo And clean up some remaining keydest refs (still a few more to go). Need to sort out default bindings for key_demo, though. --- nq/source/cl_demo.c | 2 -- nq/source/cl_input.c | 4 ++-- nq/source/cl_main.c | 5 ----- nq/source/sv_ded.c | 10 ---------- qw/source/cl_demo.c | 1 - qw/source/cl_input.c | 2 +- 6 files changed, 3 insertions(+), 21 deletions(-) diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index a119cb8b6..606eb243e 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -126,7 +126,6 @@ CL_StopPlayback (void) Qclose (cls.demofile); cls.demofile = NULL; - cls.key_dest = key_game; CL_SetState (ca_disconnected); cls.demo_capture = 0; cls.demoplayback = 0; @@ -480,7 +479,6 @@ CL_StartDemo (void) cls.demoplayback = true; CL_SetState (ca_connected); cls.forcetrack = 0; - cls.key_dest = key_demo; while ((c = Qgetc (cls.demofile)) != '\n') if (c == '-') diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 95be1d38c..f2bd1bce5 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -440,7 +440,7 @@ CL_Input_Init (cbuf_t *cbuf) void CL_Input_Activate (void) { - host_in_game = 1; - IMT_SetContext (cl_game_context); + host_in_game = !cls.demoplayback; + IMT_SetContext (cls.demoplayback ? cl_demo_context : cl_game_context); IE_Set_Focus (cl_event_id); } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 488c86b5a..683aa910e 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -350,7 +350,6 @@ CL_EstablishConnection (const char *host) cls.demonum = -1; // not in the demo loop now CL_SetState (ca_connected); - //Key_SetKeyDest (cls.key_dest); } /* @@ -526,7 +525,6 @@ CL_SetState (cactive_t state) if (old_state != state) { if (old_state == ca_active) { // leaving active state - //Key_SetKeyDest (key_console); S_AmbientOff (); } switch (state) { @@ -541,14 +539,12 @@ CL_SetState (cactive_t state) cls.signon = so_none; // need all the signon messages // before playing cl.loading = true; - //Key_SetKeyDest (cls.key_dest); IN_ClearStates (); VID_SetCaption ("Connected"); break; case ca_active: // entering active state cl.loading = false; - //Key_SetKeyDest (cls.key_dest); IN_ClearStates (); VID_SetCaption (""); S_AmbientOn (); @@ -613,6 +609,5 @@ CL_Init (cbuf_t *cbuf) "to be level"); SZ_Alloc (&cls.message, 1024); - cls.key_dest = key_game; CL_SetState (ca_disconnected); } diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index 80eefe3ec..ea693c175 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -58,11 +58,6 @@ GIB_Key_Init (void) { } -void -Key_KeydestCallback (keydest_callback_t *callback, void *data) -{ -} - void CL_SetState (cactive_t state) { @@ -145,11 +140,6 @@ IN_ProcessEvents (void) { } -void -Key_WriteBindings (QFile *f) -{ -} - void S_Update (const vec3_t origin, const vec3_t v_forward, const vec3_t v_right, const vec3_t v_up, const byte *ambient_sound_level) diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 9d10c2897..39d27b249 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -1014,7 +1014,6 @@ CL_StartDemo (void) Sys_Printf ("Playing demo from %s.\n", name->str); cls.demoplayback = true; - //Key_SetKeyDest (key_demo); net_blocksend = 1; if (type == 2) { cls.demoplayback2 = true; diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index daf3b7019..afa952fd9 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -597,7 +597,7 @@ CL_Input_Init (void) void CL_Input_Activate (void) { - IMT_SetContext (cl_game_context); + IMT_SetContext (cls.demoplayback ? cl_demo_context : cl_game_context); IE_Set_Focus (cl_event_id); } From fe9241e57307c28638536072608688d8fa516ca4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Nov 2021 12:01:07 +0900 Subject: [PATCH 1874/3664] [input] Move some IMT documentation And update to reflect some of the changed concepts (context vs keydest) --- include/QF/input/imt.h | 26 ++++++++++++++++++++++++++ include/QF/keys.h | 26 -------------------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 9cbf52bcd..7eeed7aa9 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -86,8 +86,34 @@ int IMT_CreateContext (const char *name); int IMT_GetContext (void) __attribute__ ((pure)); void IMT_SetContext (int ctx); void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf); + +/** Find an Input Mapping Table by name. + + Searches through all contexts for the named imt. The search is case + insensitive. + + \param imt_name The name of the imt to find. Case insensitive. + \return The named imt, or null if not found. +*/ imt_t *IMT_FindIMT (const char *name) __attribute__ ((pure)); imt_switcher_t *IMT_FindSwitcher (const char *name) __attribute__ ((pure)); + +/** Create a new imt and attach it to the specified context. + + The name of the new imt must be unique (case insensitive) across all + contexts. This is to simplify the in_bind command. + + If \a chain_imt_name is not null, then it species the fallback imt for when + the input is not bound in the new imt. It must be an already existing imt + in the specified context. This is to prevent loops and other weird + behavior. + + \param context The context to which the new imt will be attached. + \param imt_name The name for the new imt. Must be unique (case + insensitive). + \param chain_imt_name The name of the fallback imt if not null. Must + already exist on the specified context. +*/ int IMT_CreateIMT (int context, const char *imt_name, const char *chain_imt_name); int IMT_CreateSwitcher (const char *switcher_name, diff --git a/include/QF/keys.h b/include/QF/keys.h index b66f99414..449872ad9 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -448,33 +448,7 @@ struct cbuf_s; void Key_Init (struct cbuf_s *cb); void Key_Init_Cvars (void); - -/** Find an Input Mapping Table by name. - - Searches through all keydest targets for the named imt. The search is case - insensitive. - - \param imt_name The name of the imt to find. Case insensitive. - \return The named imt, or null if not found. -*/ struct imt_s *Key_FindIMT (const char *imt_name) __attribute__((pure)); - -/** Create a new imt and attach it to the specified keydest target. - - The name of the new imt must be unique (case insensitive) across all - keydest targets. This is to simplify the in_bind command. - - If \a chain_imt_name is not null, then it species the fallback imt for when - the key is not bound in the new imt. It must be an already existing imt in - the specified keydest target. This is to prevent loops and other weird - behavior. - - \param kd The keydest target to which the new imt will be attached. - \param imt_name The name for the new imt. Must be unique (case - insensitive). - \param chain_imt_name The name of the fallback imt if not null. Must - already exist on the specified keydest target. -*/ void Key_CreateIMT (keydest_t kd, const char *imt_name, const char *chain_imt_name); From 652546a4fbf2c2a00c1aedd33386d1237d4a7cc4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Nov 2021 12:31:24 +0900 Subject: [PATCH 1875/3664] [input] Clean out a lot of obsolete stuff from keys The new binding system makes much of keys.[ch] obsolete leaving only the key name translations. --- include/QF/keys.h | 147 ------ libs/console/client.c | 13 +- libs/input/Makemodule.am | 3 +- libs/input/keys.c | 1049 -------------------------------------- libs/ruamoko/rua_keys.c | 4 - nq/include/client.h | 1 - 6 files changed, 7 insertions(+), 1210 deletions(-) diff --git a/include/QF/keys.h b/include/QF/keys.h index 449872ad9..caf8f55de 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -379,154 +379,7 @@ typedef enum { QFK_LAST } knum_t; -typedef enum { - key_unfocused, ///< engine has lost input focus - key_game, ///< Normal in-game key bindings - key_demo, ///< Demo playback key bindings - key_console, ///< Command console key bindings - key_message, ///< Message input line key bindings - key_menu, ///< Menu key bindings. - - key_last ///< enum size -} keydest_t; - #ifndef __QFCC__ -extern knum_t key_toggleconsole; - -/** Chain of input mapping tables ascociated with a keydest sub-system (game, - menu, etc). -*/ -typedef struct keytarget_s { - struct imt_s *imts; ///< list of tables attached to this target - struct imt_s *active; ///< currently active table in this target -} keytarget_t; - -extern int keydown[QFK_LAST]; - -/** Callback for handling key events based on keydest. - - \param key The key that was pressed or released for this event. - \param unicode The unicode value of the key. - \param down True if a press event, false if a release event. - \param data Callback specific data pointer as passed to Key_SetKeyDest -*/ -typedef void key_event_t (knum_t key, short unicode, qboolean down, - void *data); - -/** Set the fallback key event handler callback for the specified keydest. - - The fallback is for handling keys that have not been bound, thus allowing - the callback to handle large numbers of keys without having to create many - explicit bindings (eg, console input). - - If no callback has been set for a specific keydest, then the key event - is simply ignored. - - \param keydest The keydest for which the callback will be set. - \param callback The function to be called when an event occurs. - \param data Opaque data pointer passed to the callback. -*/ -void Key_SetKeyEvent (keydest_t keydest, key_event_t *callback, void *data); - -/** Callback for handling the escape key. - \param data Callback specific data pointer as passed to Key_PushEscape -*/ -typedef void key_escape_t (void *data); - -/** Push an escape key event handler callback. - - \param callback The function to be called when the escape key is pressed. - \param data Opaque data pointer passed to the callback. -*/ -void Key_PushEscape (key_escape_t *callback, void *data); - -/** Push an escape key event handler callback. -*/ -void Key_PopEscape (void); - -struct cbuf_s; - -void Key_Init (struct cbuf_s *cb); -void Key_Init_Cvars (void); -struct imt_s *Key_FindIMT (const char *imt_name) __attribute__((pure)); -void Key_CreateIMT (keydest_t kd, const char *imt_name, - const char *chain_imt_name); - -/** Handle a key press/release event. - - \param key The key that was pressed or released for this event. - \param unicode The unicode value of the key. - \param down True if a press event, false if a release event. -*/ -void Key_Event (knum_t key, short unicode, qboolean down); - -/** Handle loss or gain of input focus (usually in windowed enviroments). - - Sets the keydest target to key_unfocuses when input focus is lost. - - Triggers keydest callbacks. - - \bug Always sets the target to key_game when focus is gained. - - \param gain True if focus is gained, false if focus is lost. -*/ -void Key_FocusEvent (int gain); - -void Key_WriteBindings (QFile *f); - -/** Force all key states to unpressed. - - Sends a key release event for any keys that are seen as down. -*/ -void Key_ClearStates (void); - -/** Return a key binding in the specified input mapping table. - - \param imt The input mapping table from which to get the binding. - \param key The key for which to get the binding. - \return The command string bound to the key, or null if unbound. -*/ -const char *Key_GetBinding (struct imt_s *imt, knum_t key) __attribute__((pure)); - -/** Bind a command string to a key in the specified input mapping table. - - Only one command string can be bound to a key, but the command string may - contain multiple commands. - - \param imt The input mapping table in which the key will be bound. - \param keynum The key to which the command string will be bound. - \param binding The command string that will be bound. -*/ -void Key_SetBinding (struct imt_s *imt, knum_t keynum, const char *binding); - -/** Set the current keydest target. - - Triggers keydest callbacks. - - \param kd The keydest target to make current. -*/ -void Key_SetKeyDest(keydest_t kd); - -/** Get the current keydest target. - - \return The current keydest target. -*/ -keydest_t Key_GetKeyDest(void) __attribute__((pure)); - -/** keydest callback signature. - - \param kd The new current keydest target. - \param data Callback specific data pointer as passed to - Key_KeydestCallback -*/ -typedef void keydest_callback_t (keydest_t kd, void *data); - -/** Add a callback for when the keydest target changes. - - \param callback The callback to be added. - \param data Opaque data pointer passed to the callback. -*/ -void Key_KeydestCallback (keydest_callback_t *callback, void *data); /** Get the string representation of a key. diff --git a/libs/console/client.c b/libs/console/client.c index 06f740a20..ce4413efc 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -111,9 +111,6 @@ static view_t *hud_view; static qboolean con_initialized; -static keydest_t con_curr_keydest; -//static keydest_t con_prev_keydest; - static void ClearNotify (void) { @@ -158,11 +155,11 @@ ToggleChat_f (void) { Con_ClearTyping (input_line, 0); - if (con_curr_keydest == key_console && !con_data.force_commandline) { + //if (con_curr_keydest == key_console && !con_data.force_commandline) { //Key_SetKeyDest (key_game); - } else { + //} else { //Key_SetKeyDest (key_console); - } + //} ClearNotify (); } @@ -686,9 +683,9 @@ C_DrawConsole (void) if (console_view->ylen != con_data.lines) view_resize (console_view, console_view->xlen, con_data.lines); - say_view->visible = con_curr_keydest == key_message; + say_view->visible = 0;//FIXME console_view->visible = con_data.lines != 0; - menu_view->visible = con_curr_keydest == key_menu; + menu_view->visible = 0;//FIXME con_data.view->draw (con_data.view); } diff --git a/libs/input/Makemodule.am b/libs/input/Makemodule.am index 6bda3f0f3..79d0f851e 100644 --- a/libs/input/Makemodule.am +++ b/libs/input/Makemodule.am @@ -22,7 +22,8 @@ libs_input_libQFinput_la_SOURCES= \ libs/input/in_button.c \ libs/input/in_common.c \ libs/input/in_event.c \ - libs/input/in_imt.c + libs/input/in_imt.c \ + libs/input/keys.c EXTRA_LTLIBRARIES += \ libs/input/libinput_evdev.la diff --git a/libs/input/keys.c b/libs/input/keys.c index 87fc283f5..d519c3fb8 100644 --- a/libs/input/keys.c +++ b/libs/input/keys.c @@ -53,72 +53,6 @@ #include "compat.h" #include "old_keys.h" -static memsuper_t *binding_mem; -/* -static in_axisbinding_t * -alloc_axis_binding (void) -{ - return cmemalloc (binding_mem, sizeof (in_axisbinding_t)); -} -*/ -static void -free_axis_binding (in_axisbinding_t *binding) -{ - cmemfree (binding_mem, binding); -} - -static in_buttonbinding_t * -alloc_button_binding (void) -{ - return cmemalloc (binding_mem, sizeof (in_buttonbinding_t)); -} - -static void -free_button_binding (in_buttonbinding_t *binding) -{ - cmemfree (binding_mem, binding); -} - -/* key up events are sent even if in console mode */ - -static keydest_t key_dest = key_console; -static keytarget_t key_targets[key_last]; -VISIBLE knum_t key_toggleconsole = QFK_BACKQUOTE; - -typedef struct { - keydest_callback_t *func; - void *data; -} keydest_callback_item_t; - -typedef struct { - key_escape_t *func; - void *data; -} key_escape_item_t; - -#define CALLBACK_CHUNK 16 -static struct DARRAY_TYPE(keydest_callback_item_t) keydest_callbacks = { - .grow = CALLBACK_CHUNK -}; -static struct DARRAY_TYPE(key_escape_item_t) key_escape_callbacks = { - .grow = CALLBACK_CHUNK -}; - -VISIBLE int keydown[QFK_LAST]; - -static int keyhelp; -static cbuf_t *cbuf; - -static const char *keydest_names[] = { - "key_unfocused", - "key_game", - "key_demo", - "key_console", - "key_message", - "key_menu", - - "key_last" -}; - typedef struct { const char *name; knum_t keynum; @@ -438,287 +372,9 @@ keyname_t keynames[] = { { "K_BACK", QFK_BACK }, { "K_FORWARD", QFK_FORWARD }, - { "M_BUTTON1", QFM_BUTTON1 }, - { "M_BUTTON2", QFM_BUTTON2 }, - { "M_BUTTON3", QFM_BUTTON3 }, - { "M_WHEEL_UP", QFM_WHEEL_UP }, - { "M_WHEEL_DOWN", QFM_WHEEL_DOWN }, - { "M_BUTTON6", QFM_BUTTON6 }, - { "M_BUTTON7", QFM_BUTTON7 }, - { "M_BUTTON8", QFM_BUTTON8 }, - { "M_BUTTON9", QFM_BUTTON9 }, - { "M_BUTTON10", QFM_BUTTON10 }, - { "M_BUTTON11", QFM_BUTTON11 }, - { "M_BUTTON12", QFM_BUTTON12 }, - { "M_BUTTON13", QFM_BUTTON13 }, - { "M_BUTTON14", QFM_BUTTON14 }, - { "M_BUTTON15", QFM_BUTTON15 }, - { "M_BUTTON16", QFM_BUTTON16 }, - { "M_BUTTON17", QFM_BUTTON17 }, - { "M_BUTTON18", QFM_BUTTON18 }, - { "M_BUTTON19", QFM_BUTTON19 }, - { "M_BUTTON20", QFM_BUTTON20 }, - { "M_BUTTON21", QFM_BUTTON21 }, - { "M_BUTTON22", QFM_BUTTON22 }, - { "M_BUTTON23", QFM_BUTTON23 }, - { "M_BUTTON24", QFM_BUTTON24 }, - { "M_BUTTON25", QFM_BUTTON25 }, - { "M_BUTTON26", QFM_BUTTON26 }, - { "M_BUTTON27", QFM_BUTTON27 }, - { "M_BUTTON28", QFM_BUTTON28 }, - { "M_BUTTON29", QFM_BUTTON29 }, - { "M_BUTTON30", QFM_BUTTON30 }, - { "M_BUTTON31", QFM_BUTTON31 }, - { "M_BUTTON32", QFM_BUTTON32 }, - - { "J_BUTTON1", QFJ_BUTTON1 }, - { "J_BUTTON2", QFJ_BUTTON2 }, - { "J_BUTTON3", QFJ_BUTTON3 }, - { "J_BUTTON4", QFJ_BUTTON4 }, - { "J_BUTTON5", QFJ_BUTTON5 }, - { "J_BUTTON6", QFJ_BUTTON6 }, - { "J_BUTTON7", QFJ_BUTTON7 }, - { "J_BUTTON8", QFJ_BUTTON8 }, - { "J_BUTTON9", QFJ_BUTTON9 }, - { "J_BUTTON10", QFJ_BUTTON10 }, - { "J_BUTTON11", QFJ_BUTTON11 }, - { "J_BUTTON12", QFJ_BUTTON12 }, - { "J_BUTTON13", QFJ_BUTTON13 }, - { "J_BUTTON14", QFJ_BUTTON14 }, - { "J_BUTTON15", QFJ_BUTTON15 }, - { "J_BUTTON16", QFJ_BUTTON16 }, - { "J_BUTTON17", QFJ_BUTTON17 }, - { "J_BUTTON18", QFJ_BUTTON18 }, - { "J_BUTTON19", QFJ_BUTTON19 }, - { "J_BUTTON20", QFJ_BUTTON20 }, - { "J_BUTTON21", QFJ_BUTTON21 }, - { "J_BUTTON22", QFJ_BUTTON22 }, - { "J_BUTTON23", QFJ_BUTTON23 }, - { "J_BUTTON24", QFJ_BUTTON24 }, - { "J_BUTTON25", QFJ_BUTTON25 }, - { "J_BUTTON26", QFJ_BUTTON26 }, - { "J_BUTTON27", QFJ_BUTTON27 }, - { "J_BUTTON28", QFJ_BUTTON28 }, - { "J_BUTTON29", QFJ_BUTTON29 }, - { "J_BUTTON30", QFJ_BUTTON30 }, - { "J_BUTTON31", QFJ_BUTTON31 }, - { "J_BUTTON32", QFJ_BUTTON32 }, - { "J_BUTTON33", QFJ_BUTTON33 }, - { "J_BUTTON34", QFJ_BUTTON34 }, - { "J_BUTTON35", QFJ_BUTTON35 }, - { "J_BUTTON36", QFJ_BUTTON36 }, - { "J_BUTTON37", QFJ_BUTTON37 }, - { "J_BUTTON38", QFJ_BUTTON38 }, - { "J_BUTTON39", QFJ_BUTTON39 }, - { "J_BUTTON40", QFJ_BUTTON40 }, - { "J_BUTTON41", QFJ_BUTTON41 }, - { "J_BUTTON42", QFJ_BUTTON42 }, - { "J_BUTTON43", QFJ_BUTTON43 }, - { "J_BUTTON44", QFJ_BUTTON44 }, - { "J_BUTTON45", QFJ_BUTTON45 }, - { "J_BUTTON46", QFJ_BUTTON46 }, - { "J_BUTTON47", QFJ_BUTTON47 }, - { "J_BUTTON48", QFJ_BUTTON48 }, - { "J_BUTTON49", QFJ_BUTTON49 }, - { "J_BUTTON50", QFJ_BUTTON50 }, - { "J_BUTTON51", QFJ_BUTTON51 }, - { "J_BUTTON52", QFJ_BUTTON52 }, - { "J_BUTTON53", QFJ_BUTTON53 }, - { "J_BUTTON54", QFJ_BUTTON54 }, - { "J_BUTTON55", QFJ_BUTTON55 }, - { "J_BUTTON56", QFJ_BUTTON56 }, - { "J_BUTTON57", QFJ_BUTTON57 }, - { "J_BUTTON58", QFJ_BUTTON58 }, - { "J_BUTTON59", QFJ_BUTTON59 }, - { "J_BUTTON60", QFJ_BUTTON60 }, - { "J_BUTTON61", QFJ_BUTTON61 }, - { "J_BUTTON62", QFJ_BUTTON62 }, - { "J_BUTTON63", QFJ_BUTTON63 }, - { "J_BUTTON64", QFJ_BUTTON64 }, - - { "J_AXIS1", QFJ_AXIS1 }, - { "J_AXIS2", QFJ_AXIS2 }, - { "J_AXIS3", QFJ_AXIS3 }, - { "J_AXIS4", QFJ_AXIS4 }, - { "J_AXIS5", QFJ_AXIS5 }, - { "J_AXIS6", QFJ_AXIS6 }, - { "J_AXIS7", QFJ_AXIS7 }, - { "J_AXIS8", QFJ_AXIS8 }, - { "J_AXIS9", QFJ_AXIS9 }, - { "J_AXIS10", QFJ_AXIS10 }, - { "J_AXIS11", QFJ_AXIS11 }, - { "J_AXIS12", QFJ_AXIS12 }, - { "J_AXIS13", QFJ_AXIS13 }, - { "J_AXIS14", QFJ_AXIS14 }, - { "J_AXIS15", QFJ_AXIS15 }, - { "J_AXIS16", QFJ_AXIS16 }, - { "J_AXIS17", QFJ_AXIS17 }, - { "J_AXIS18", QFJ_AXIS18 }, - { "J_AXIS19", QFJ_AXIS19 }, - { "J_AXIS20", QFJ_AXIS20 }, - { "J_AXIS21", QFJ_AXIS21 }, - { "J_AXIS22", QFJ_AXIS22 }, - { "J_AXIS23", QFJ_AXIS23 }, - { "J_AXIS24", QFJ_AXIS24 }, - { "J_AXIS25", QFJ_AXIS25 }, - { "J_AXIS26", QFJ_AXIS26 }, - { "J_AXIS27", QFJ_AXIS27 }, - { "J_AXIS28", QFJ_AXIS28 }, - { "J_AXIS29", QFJ_AXIS29 }, - { "J_AXIS30", QFJ_AXIS30 }, - { "J_AXIS31", QFJ_AXIS31 }, - { "J_AXIS32", QFJ_AXIS32 }, - {NULL, 0} }; -static __attribute__((pure)) imt_t * -key_target_find_imt (keytarget_t *kt, const char *imt_name) -{ - imt_t *imt; - for (imt = kt->imts; imt; imt = imt->next) { - if (!strcasecmp (imt->name, imt_name)) { - return imt; - } - } - return 0; -} - -VISIBLE imt_t * -Key_FindIMT (const char *imt_name) -{ - keydest_t kd; - imt_t *imt = 0; - - for (kd = key_unfocused; !imt && kd < key_last; kd++) { - imt = key_target_find_imt (&key_targets[kd], imt_name); - } - return imt; -} - -void -Key_CreateIMT (keydest_t kd, const char *imt_name, const char *chain_imt_name) -{ - imt_t *imt; - imt_t *chain_imt = 0; - keytarget_t *kt = &key_targets[kd]; - - imt = Key_FindIMT (imt_name); - if (imt) { - Sys_Printf ("imt error: imt %s already exists\n", imt_name); - return; - } - if (chain_imt_name) { - chain_imt = Key_FindIMT (chain_imt_name); - if (!chain_imt) { - Sys_Printf ("imt error: chain imt %s does not exist\n", - chain_imt_name); - return; - } - imt = key_target_find_imt (kt, chain_imt_name); - if (!imt) { - Sys_Printf ("imt error: chain imt %s not on target key " - "destination\n", chain_imt_name); - return; - } - } - imt = calloc (1, sizeof (imt_t)); - imt->name = strdup (imt_name); - imt->chain = chain_imt; - imt->next = kt->imts; - kt->imts = imt; - if (!kt->active) { - kt->active = imt; - } -} - -VISIBLE void -Key_SetBinding (imt_t *imt, knum_t keynum, const char *binding) -{ - if (keynum == (knum_t) -1) - return; - - if (imt->button_bindings.a[keynum]) { - if (imt->button_bindings.a[keynum]->type == inb_command) { - free (imt->button_bindings.a[keynum]->command); - } - free_button_binding (imt->button_bindings.a[keynum]); - imt->button_bindings.a[keynum] = 0; - } - if (binding) { - in_buttonbinding_t *b = alloc_button_binding (); - imt->button_bindings.a[keynum] = b; - in_button_t *button; - if (binding[0] == '+' && (button = IN_FindButton (binding + 1))) { - b->type = inb_button; - b->bind_id = keynum; //FIXME alloc? - b->button = button; - } else { - b->type = inb_command; - b->command = strdup(binding); - } - } -} - -static void -Key_CallDestCallbacks (keydest_t kd) -{ - for (size_t i = 0; i < keydest_callbacks.size; i++) { - keydest_callback_item_t *cb = &keydest_callbacks.a[i]; - cb->func (kd, cb->data); - } -} - -static void -process_binding (knum_t key, const char *kb) -{ - char cmd[1024]; - - if (kb[0] == '+') { - if (keydown[key]) - snprintf (cmd, sizeof (cmd), "%s %d\n", kb, key); - else - snprintf (cmd, sizeof (cmd), "-%s %d\n", kb + 1, key); - } else { - if (!keydown[key]) - return; - snprintf (cmd, sizeof (cmd), "%s\n", kb); - } - Cbuf_AddText (cbuf, cmd); -} - -/* - Key_Game - - Game key handling. -*/ -static qboolean -Key_Game (knum_t key, short unicode) -{ - imt_t *imt = key_targets[key_dest].active; - - while (imt) { - in_buttonbinding_t *b = imt->button_bindings.a[key]; - if (b) { - switch (b->type) { - case inb_button: - if (keydown[key] <= 1) { - IN_ButtonAction (b->button, key, keydown[key]); - } - break; - case inb_command: - if (keydown[key] <= 1) { - process_binding (key, b->command); - } - break; - } - return true; - } - imt = imt->chain; - } - return false; -} - VISIBLE int Key_StringToKeynum (const char *str) { @@ -748,708 +404,3 @@ Key_KeynumToString (knum_t keynum) return ""; } - -static void -Key_In_Unbind (const char *imt_name, const char *key_name) -{ - imt_t *imt; - int key; - - imt = Key_FindIMT (imt_name); - if (!imt) { - Sys_Printf ("\"%s\" is not a valid imt\n", imt_name); - return; - } - - key = Key_StringToKeynum (key_name); - if (key == -1) { - Sys_Printf ("\"%s\" is not a valid key\n", key_name); - return; - } - - Key_SetBinding (imt, key, NULL); -} - -static void -Key_In_Unbind_f (void) -{ - if (Cmd_Argc () != 3) { - Sys_Printf ("in_unbind : remove commands from a key\n"); - return; - } - Key_In_Unbind (Cmd_Argv (1), Cmd_Argv (2)); -} - -static void -Key_Unbindall_f (void) -{ - imt_t *imt; - int i; - - imt = Key_FindIMT ("imt_mod"); - if (imt) { - for (i = 0; i < QFK_LAST; i++) { - Key_SetBinding (imt, i, 0); - } - } -} - -static void -Key_In_Type_f (void) -{ - const char *str, *p; - if (Cmd_Argc () != 2) { - Sys_Printf ("in_type \n"); - Sys_Printf (" Send the given string as simulated key presses.\n"); - return; - } - str = Cmd_Argv (1); - for (p = str; *p; p++) { - Key_Event (QFK_UNKNOWN, *p, 1); - Key_Event (QFK_UNKNOWN, 0, 0); - } -} - -static void -Key_In_Clear (void) -{ - int err = 0; - imt_t *imt; - int i, j; - - if (Cmd_Argc () == 1) { - Sys_Printf ("in_clear ...\n"); - return; - } - for (i = 1; i < Cmd_Argc (); i++) { - if (!Key_FindIMT (Cmd_Argv (i))) { - Sys_Printf ("\"%s\" is not a valid imt\n", Cmd_Argv (i)); - err = 1; - } - } - if (err) - return; - for (i = 1; i < Cmd_Argc (); i++) { - imt = Key_FindIMT (Cmd_Argv (i)); - for (j = 0; j < QFK_LAST; j++) - Key_SetBinding (imt, j, NULL); - } -} - -static void -Key_IMT_Create_f (void) -{ - const char *keydest; - const char *imt_name; - const char *chain_imt_name = 0; - keydest_t kd; - - if (Cmd_Argc () < 3 || Cmd_Argc () > 4) { - Sys_Printf ("see help imt_create\n"); - return; - } - keydest = Cmd_Argv (1); - imt_name = Cmd_Argv (2); - if (Cmd_Argc () == 4) { - chain_imt_name = Cmd_Argv (3); - } - for (kd = key_game; kd < key_last; kd++) { - if (!strcasecmp (keydest_names[kd], keydest)) { - break; - } - } - if (kd == key_last) { - Sys_Printf ("imt error: invalid keydest: %s\n", keydest); - return; - } - Key_CreateIMT (kd, imt_name, chain_imt_name); -} - -static void -Key_IMT_Drop_All_f (void) -{ - keydest_t kd; - imt_t *imt; - - for (kd = key_unfocused; kd < key_last; kd++) { - while (key_targets[kd].imts) { - imt = key_targets[kd].imts; - key_targets[kd].imts = imt->next; - for (size_t i = 0; i < imt->axis_bindings.size; i++) { - free_axis_binding (imt->axis_bindings.a[i]); - } - for (size_t i = 0; i < imt->button_bindings.size; i++) { - in_buttonbinding_t *b = imt->button_bindings.a[i]; - if (b) { - switch (b->type) { - case inb_button: - break; - case inb_command: - free (b->command); - break; - } - free_button_binding (b); - } - } - free ((char *) imt->name); - free (imt); - } - key_targets[kd].active = 0; - } -} - -static void -Key_In_BindButton (const char *imt_name, const char *key_name, const char *cmd) -{ - imt_t *imt; - int key; - - imt = Key_FindIMT (imt_name); - if (!imt) { - Sys_Printf ("\"%s\" is not a valid imt\n", imt_name); - return; - } - - key = Key_StringToKeynum (key_name); - if (key == -1) { - Sys_Printf ("\"%s\" is not a valid key\n", key_name); - return; - } - - if (!cmd) { - in_buttonbinding_t *b = imt->button_bindings.a[key]; - if (b) { - switch (b->type) { - case inb_button: - Sys_Printf ("%s %s \"+%s\"\n", imt_name, key_name, - b->button->name); - break; - case inb_command: - Sys_Printf ("%s %s \"%s\"\n", imt_name, key_name, - b->command); - break; - } - } else { - Sys_Printf ("%s %s is not bound\n", imt_name, key_name); - } - return; - } - Key_SetBinding (imt, key, cmd); -} - -static void -Key_In_Bind_f (void) -{ - int c, i; - const char *imt, *key, *cmd = 0; - dstring_t *cmd_buf = 0; - - c = Cmd_Argc (); - - if (c < 4 || strcmp (Cmd_Argv (2), "button") != 0) { - Sys_Printf ("in_bind button [command]\n" - " attach a command to a key\n"); - return; - } - - imt = Cmd_Argv (1); - - key = Cmd_Argv (3); - - if (c >= 5) { - cmd_buf = dstring_newstr (); - for (i = 4; i < c; i++) { - dasprintf (cmd_buf, "%s%s", i > 3 ? " " : "", Cmd_Argv (i)); - } - cmd = cmd_buf->str; - } - - Key_In_BindButton (imt, key, cmd); - if (cmd_buf) { - dstring_delete (cmd_buf); - } -} - -static void -Key_Unbind_f (void) -{ - const char *key; - - if (Cmd_Argc () != 2) { - Sys_Printf ("unbind : remove commands from a key\n"); - return; - } - key = OK_TranslateKeyName (Cmd_Argv (1)); - Key_In_Unbind ("imt_mod", key); -} - -static void -Key_Bind_f (void) -{ - int c, i; - const char *key, *cmd = 0; - dstring_t *cmd_buf = 0; - - c = Cmd_Argc (); - - if (c < 2) { - Sys_Printf ("bind [command] : attach a command to a key\n"); - return; - } - - key = OK_TranslateKeyName (Cmd_Argv (1)); - - if (c >= 3) { - cmd_buf = dstring_newstr (); - for (i = 2; i < c; i++) { - dasprintf (cmd_buf, "%s%s", i > 2 ? " " : "", Cmd_Argv (i)); - } - cmd = cmd_buf->str; - } - - Key_In_BindButton ("imt_mod", key, cmd); - if (cmd_buf) { - dstring_delete (cmd_buf); - } -} - -static void -in_key_toggleconsole_f (cvar_t *var) -{ - int k; - - if (!*var->string) { - key_toggleconsole = -1; - return; - } - if ((k = Key_StringToKeynum (var->string)) == -1) { - Sys_Printf ("\"%s\" is not a valid key. not setting\n", - var->string); - return; - } - key_toggleconsole = k; -} - -static void -Key_InputMappingTable_f (void) -{ - int c; - imt_t *imt; - - c = Cmd_Argc (); - - if (c != 2) { - Sys_Printf ("Current imt is %s\n", key_targets[key_game].active->name); - Sys_Printf ("imt : set to a specific input mapping table\n"); - return; - } - - imt = Key_FindIMT (Cmd_Argv (1)); - if (!imt) { - Sys_Printf ("\"%s\" is not a valid imt\n", Cmd_Argv (1)); - return; - } - - key_targets[key_game].active = imt; -} - -static void -Key_IMT_Keydest_f (void) -{ - int c; - imt_t *imt; - const char *imt_name = 0; - const char *keydest; - keydest_t kd; - - c = Cmd_Argc (); - switch (c) { - case 3: - imt_name = Cmd_Argv (2); - case 2: - keydest = Cmd_Argv (1); - break; - default: - return; - } - for (kd = key_game; kd < key_last; kd++) { - if (!strcasecmp (keydest_names[kd], keydest)) { - break; - } - } - if (kd == key_last) { - Sys_Printf ("imt error: invalid keydest: %s\n", keydest); - return; - } - - if (!imt_name) { - Sys_Printf ("Current imt is %s\n", key_targets[key_game].active->name); - Sys_Printf ("imt : set to a specific input mapping table\n"); - return; - } - - imt = key_target_find_imt (&key_targets[kd], imt_name); - if (!imt) { - Sys_Printf ("\"%s\" is not an imt on %s\n", imt_name, keydest); - return; - } - - key_targets[kd].active = imt; -} - -static void __attribute__((format(PRINTF,2,3))) -key_printf (QFile *f, const char *fmt, ...) -{ - va_list args; - static dstring_t *string; - - if (!string) { - string = dstring_new (); - } - va_start (args, fmt); - dvsprintf (string, fmt, args); - va_end (args); - - if (f) { - Qprintf (f, "%s", string->str); - } else { - Sys_Printf ("%s", string->str); - } -} - -static void -key_write_imt (QFile *f, keydest_t kd, imt_t *imt) -{ - if (!imt || imt->written) { - return; - } - imt->written = 1; - key_write_imt (f, kd, imt->chain); - if (imt->chain) { - key_printf (f, "imt_create %s %s %s\n", keydest_names[kd], - imt->name, imt->chain->name); - } else { - key_printf (f, "imt_create %s %s\n", keydest_names[kd], imt->name); - } - for (size_t i = 0; i < imt->button_bindings.size; i++) { - in_buttonbinding_t *b = imt->button_bindings.a[i]; - if (b) { - switch (b->type) { - case inb_button: - key_printf (f, "in_bind %s button %s \"+%s\"\n", imt->name, - Key_KeynumToString (i), b->button->name); - break; - case inb_command: - key_printf (f, "in_bind %s button %s \"%s\"\n", imt->name, - Key_KeynumToString (i), b->command); - break; - } - } - } -} - -void -Key_WriteBindings (QFile *f) -{ - keydest_t kd; - imt_t *imt; - - for (kd = key_unfocused; kd < key_last; kd++) { - for (imt = key_targets[kd].imts; imt; imt = imt->next) { - imt->written = 0; - } - } - key_printf (f, "imt_drop_all\n"); - for (kd = key_unfocused; kd < key_last; kd++) { - if (key_targets[kd].imts) { - for (imt = key_targets[kd].imts; imt; imt = imt->next) { - key_write_imt (f, kd, imt); - } - key_printf (f, "imt_keydest %s %s\n", keydest_names[kd], - key_targets[kd].active->name); - } - } -} - -static void -Key_Bindlist_f (void) -{ - Key_WriteBindings (0); -} - -static void -keyhelp_f (void) -{ - keyhelp = 1; -} - -static key_event_t *key_event_handlers[key_last] = { }; -static void *key_event_data[key_last] = { }; - -VISIBLE void -Key_SetKeyEvent (keydest_t keydest, key_event_t *callback, void *data) -{ - if (keydest < 0 || keydest >= key_last) { - Sys_Error ("Key_SetKeyEvent: invalid keydest: %d", keydest); - } - key_event_handlers[keydest] = callback; - key_event_data[keydest] = data; -} - -/* - Key_Event - - Called by the system between frames for both key up and key down events - Should NOT be called during an interrupt! -*/ -VISIBLE void -Key_Event (knum_t key, short unicode, qboolean down) -{ -// Sys_Printf ("%d %d %d : %d\n", key_target, key_dest, key, down); //@@@ - - if (down) { - keydown[key]++; - if (keyhelp) { - Sys_Printf ("Key name for that key is \"%s\"\n", - Key_KeynumToString (key)); - keyhelp = 0; - return; // gobble the key - } - } else { - keydown[key] = 0; - } - - // handle the escape key specially so it can never be overridden or - // unbound - if (key == QFK_ESCAPE && keydown[key] == 1) { - if (key_escape_callbacks.size) { - int ind = key_escape_callbacks.size - 1; - key_escape_item_t cb = key_escape_callbacks.a[ind]; - cb.func (cb.data); - } - return; - } - //FIXME maybe still a tad over-coupled. Use callbacks for menu and console - //toggles? Should keys know anything about menu and console? - if (key_dest != key_console && key == key_toggleconsole - && keydown[key] == 1) { - Cbuf_AddText (cbuf, "toggleconsole"); - return; - } - - if (key_dest < 0 || key_dest >= key_last) { - Sys_Error ("Bad key_dest"); - } - - if (!Key_Game (key, unicode)) { - if (key_event_handlers[key_dest]) { - key_event_handlers[key_dest] (key, unicode, down, - key_event_data[key_dest]); - } - } -} - -VISIBLE void -Key_FocusEvent (int gain) -{ - if (gain) { - Key_CallDestCallbacks (key_dest); - } else { - Key_CallDestCallbacks (key_unfocused); - } -} - -void -Key_ClearStates (void) -{ - int i; - - for (i = 0; i < QFK_LAST; i++) { - if (keydown[i]) - Key_Event (i, 0, false); - keydown[i] = false; - } -} - -static struct { - keydest_t kd; - const char *imt_name; - const char *chain_imt_name; -} default_imts[] = { - {key_game, "imt_mod", 0}, - {key_game, "imt_0", "imt_mod"}, - {key_game, "imt_1", "imt_0"}, - {key_game, "imt_2", "imt_0"}, - {key_game, "imt_3", "imt_0"}, - {key_game, "imt_4", "imt_0"}, - {key_game, "imt_5", "imt_0"}, - {key_game, "imt_6", "imt_0"}, - {key_game, "imt_7", "imt_0"}, - {key_game, "imt_8", "imt_0"}, - {key_game, "imt_9", "imt_0"}, - {key_game, "imt_10", "imt_0"}, - {key_game, "imt_11", "imt_0"}, - {key_game, "imt_12", "imt_0"}, - {key_game, "imt_13", "imt_0"}, - {key_game, "imt_14", "imt_0"}, - {key_game, "imt_15", "imt_0"}, - {key_game, "imt_16", "imt_0"}, - {key_demo, "imt_demo", 0}, - {key_console, "imt_console", 0}, - {key_message, "imt_message", 0}, - {key_menu, "imt_menu", 0}, - {key_last, 0, 0}, -}; - -static struct { - const char *imt; - const char *key; - const char *command; -} default_bindings[] = { - {"imt_mod", "K_F10", "quit"}, - {"imt_mod", "K_BACKQUOTE", "toggleconsole"}, - {"imt_0", "K_F10", "quit"}, - {"imt_0", "K_BACKQUOTE", "toggleconsole"}, - {"imt_demo", "K_F10", "quit"}, - {"imt_demo", "K_BACKQUOTE", "toggleconsole"}, - {"imt_console", "K_F10", "quit"}, - {"imt_console", "K_BACKQUOTE", "toggleconsole"}, - {"imt_menu", "K_F10", "quit"}, - {"imt_console", "K_BACKQUOTE", "toggleconsole"}, - { } -}; - -static void -Key_CreateDefaultIMTs (void) -{ - int i; - - for (i = 0; default_imts[i].kd != key_last; i++) { - Key_CreateIMT (default_imts[i].kd, default_imts[i].imt_name, - default_imts[i].chain_imt_name); - } - for (i = 0; default_bindings[i].imt; i++) { - Key_In_BindButton (default_bindings[i].imt, default_bindings[i].key, - default_bindings[i].command); - } -} - -void -Key_Init (cbuf_t *cb) -{ - cbuf = cb; - - Key_CreateDefaultIMTs (); - - OK_Init (); - - // register our functions - Cmd_AddCommand ("in_bind", Key_In_Bind_f, "Assign a command or a set of " - "commands to a key.\n" - "Note: To bind multiple commands to a key, enclose the " - "commands in quotes and separate with semi-colons."); - Cmd_AddCommand ("in_unbind", Key_In_Unbind_f, - "Remove the bind from the the selected key"); - Cmd_AddCommand ("unbindall", Key_Unbindall_f, - "Remove all binds (USE CAUTIOUSLY!!!)"); - Cmd_AddCommand ("in_clear", Key_In_Clear, - "Remove all binds from the specified imts"); - Cmd_AddCommand ("in_type", Key_In_Type_f, - "Send the given string as simulated key presses."); - Cmd_AddCommand ("imt", Key_InputMappingTable_f, ""); - Cmd_AddCommand ("imt_keydest", Key_IMT_Keydest_f, ""); - Cmd_AddCommand ("imt_create", Key_IMT_Create_f, - "create a new imt table:\n" - " imt_create [chain_name]\n" - "\n" - "The new table will be attached to the specified keydest\n" - "imt_name must not already exist.\n" - "If given, chain_name must already exist and be on " - "keydest.\n"); - Cmd_AddCommand ("imt_drop_all", Key_IMT_Drop_All_f, - "delete all imt tables\n"); - Cmd_AddCommand ("bind", Key_Bind_f, "wrapper for in_bind that uses " - "in_bind_imt for the imt parameter"); - Cmd_AddCommand ("unbind", Key_Unbind_f, - "wrapper for in_unbind that uses in_bind_imt for the imt " - "parameter"); - Cmd_AddCommand ("bindlist", Key_Bindlist_f, "list all of the key bindings"); - Cmd_AddCommand ("keyhelp", keyhelp_f, "display the keyname for the next " - "RECOGNIZED key-press. If the key pressed produces no " - "output, " PACKAGE_NAME " does not recognise that key."); -} - -void -Key_Init_Cvars (void) -{ - Cvar_Get ("in_key_toggleconsole", "K_BACKQUOTE", CVAR_NONE, - in_key_toggleconsole_f, - "Key for toggling the console."); -} - -const char * -Key_GetBinding (imt_t *imt, knum_t key) -{ - if (imt) { - in_buttonbinding_t *b = imt->button_bindings.a[key]; - if (b) { - switch (b->type) { - case inb_button: - return va (0, "+%s", b->button->name); - case inb_command: - return b->command; - } - } - } - return 0; -} - -VISIBLE void -Key_SetKeyDest(keydest_t kd) -{ - if (kd < 0 || kd >= key_last) { - Sys_Error ("Bad key_dest: %d", kd); - } - Sys_MaskPrintf (SYS_input, "Key_SetKeyDest: %s\n", keydest_names[kd]); - if (key_dest != kd) { - key_dest = kd; - Key_CallDestCallbacks (key_dest); - } -} - -VISIBLE keydest_t -Key_GetKeyDest (void) -{ - return key_dest; -} - -VISIBLE void -Key_KeydestCallback (keydest_callback_t *callback, void *data) -{ - if (!callback) { - Sys_Error ("null keydest callback"); - } - - keydest_callback_item_t cb = { callback, data }; - DARRAY_APPEND (&keydest_callbacks, cb); -} - -VISIBLE void -Key_PushEscape (key_escape_t *callback, void *data) -{ - if (!callback) { - Sys_Error ("null escape callback"); - } - - key_escape_item_t cb = { callback, data }; - DARRAY_APPEND (&key_escape_callbacks, cb); -} - -VISIBLE void -Key_PopEscape (void) -{ - if (!key_escape_callbacks.size) { - Sys_Error ("no escape callback to pop"); - } - DARRAY_REMOVE (&key_escape_callbacks); -} diff --git a/libs/ruamoko/rua_keys.c b/libs/ruamoko/rua_keys.c index 32229a4c4..11747304e 100644 --- a/libs/ruamoko/rua_keys.c +++ b/libs/ruamoko/rua_keys.c @@ -153,20 +153,16 @@ bi_Key_CountBinding (progs_t *pr) static void bi_Key_KeynumToString (progs_t *pr) { -#if 0 int keynum = P_INT (pr, 0); RETURN_STRING (pr, Key_KeynumToString (keynum)); -#endif } static void bi_Key_StringToKeynum (progs_t *pr) { -#if 0 const char *keyname = P_GSTRING (pr, 0); R_INT (pr) = Key_StringToKeynum (keyname); -#endif } static builtin_t builtins[] = { diff --git a/nq/include/client.h b/nq/include/client.h index 4a35a3770..4702aa44a 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -91,7 +91,6 @@ typedef struct { // connection information cactive_t state; signon_t signon; - keydest_t key_dest; // network stuff struct qsocket_s *netcon; From 376e838d1c5427fa070a6ea31b89e9b8f513e99e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Nov 2021 21:17:06 +0900 Subject: [PATCH 1876/3664] [console] Remove togglechat implementation It has always been just a clone of toggleconsole, so the command has been linked to toggleconsole's implementation instead. --- libs/console/client.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/libs/console/client.c b/libs/console/client.c index ce4413efc..c35dc9a0c 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -150,20 +150,6 @@ ToggleConsole_f (void) ClearNotify (); } -static void -ToggleChat_f (void) -{ - Con_ClearTyping (input_line, 0); - - //if (con_curr_keydest == key_console && !con_data.force_commandline) { - //Key_SetKeyDest (key_game); - //} else { - //Key_SetKeyDest (key_console); - //} - - ClearNotify (); -} - static void Clear_f (void) { @@ -988,7 +974,7 @@ C_Init (void) // register our commands Cmd_AddCommand ("toggleconsole", ToggleConsole_f, "Toggle the console up and down"); - Cmd_AddCommand ("togglechat", ToggleChat_f, + Cmd_AddCommand ("togglechat", ToggleConsole_f, "Toggle the console up and down"); Cmd_AddCommand ("messagemode", MessageMode_f, "Prompt to send a message to everyone"); From b0447c1cf1a1c1863d1a3ae182ef75d57bf4fec8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Nov 2021 22:42:01 +0900 Subject: [PATCH 1877/3664] [console] Get message modes and menus working again I'm not at all happy with con_message and con_menu, but fixing them properly will take a rework of the menus (planned, though). Also, the Menu_ console command implementations are a bit iffy and could also do with a rewrite (probably part of the rest of the menu rework) or just nuking (they were part of Johnny on Flame's work, so I suspect had something to do with joystick bindings). --- include/QF/console.h | 5 +- libs/console/client.c | 137 +++++++++++++++--------------------------- libs/console/menu.c | 98 +++++++++++++++++++----------- nq/source/cl_input.c | 3 +- qw/source/cl_input.c | 3 +- 5 files changed, 116 insertions(+), 130 deletions(-) diff --git a/include/QF/console.h b/include/QF/console.h index 159c99c4d..372263803 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -64,6 +64,8 @@ typedef enum { con_inactive, con_active, con_fullscreen, + con_message, //FIXME should not be here ? + con_menu, //FIXME should not be here ? } con_state_t; extern int con_linewidth; @@ -121,7 +123,8 @@ void Menu_Init (void); void Menu_Load (void); void Menu_Draw (struct view_s *view); void Menu_Draw_Hud (struct view_s *view); -int Menu_KeyEvent (knum_t key, short unicode, qboolean down); +struct IE_event_s; +int Menu_EventHandler (const struct IE_event_s *ie_event); void Menu_Enter (void); void Menu_Leave (void); diff --git a/libs/console/client.c b/libs/console/client.c index c35dc9a0c..7bf1493d0 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -123,21 +123,26 @@ ClearNotify (void) static void C_SetState (con_state_t state) { + con_state_t old_state = con_state; con_state = state; if (con_state == con_inactive) { IE_Set_Focus (con_saved_focos); - } else { + } else if (old_state == con_inactive) { con_saved_focos = IE_Get_Focus (); IE_Set_Focus (con_event_id); } + if (con_state == con_menu && old_state != con_menu) { + Menu_Enter (); + } } static void ToggleConsole_f (void) { - Con_ClearTyping (input_line, 0); - switch (con_state) { + case con_menu: + case con_message: + return; case con_inactive: C_SetState (con_active); break; @@ -147,6 +152,8 @@ ToggleConsole_f (void) case con_fullscreen: break; } + Con_ClearTyping (input_line, 0); + ClearNotify (); } @@ -163,19 +170,19 @@ Clear_f (void) static void MessageMode_f (void) { - if (con_data.force_commandline) + if (con_state != con_inactive) return; chat_team = false; - //Key_SetKeyDest (key_message); + C_SetState (con_message); } static void MessageMode2_f (void) { - if (con_data.force_commandline) + if (con_state != con_inactive) return; chat_team = true; - //Key_SetKeyDest (key_message); + C_SetState (con_message); } static void @@ -322,30 +329,36 @@ cl_conmode_f (cvar_t *var) } } +static void +con_end_message (inputline_t *line) +{ + Con_ClearTyping (line, 1); + C_SetState (con_inactive); +} + static void C_Say (inputline_t *il) { const char *line = il->line; - if (!*line) - return; - - Cbuf_AddText (con_data.cbuf, "say \""); - Cbuf_AddText (con_data.cbuf, line); - Cbuf_AddText (con_data.cbuf, "\"\n"); - //Key_SetKeyDest (key_game); + if (*line) { + Cbuf_AddText (con_data.cbuf, "say \""); + Cbuf_AddText (con_data.cbuf, line); + Cbuf_AddText (con_data.cbuf, "\"\n"); + } + con_end_message (il); } static void C_SayTeam (inputline_t *il) { const char *line = il->line; - if (!*line) - return; - Cbuf_AddText (con_data.cbuf, "say_team \""); - Cbuf_AddText (con_data.cbuf, line); - Cbuf_AddText (con_data.cbuf, "\"\n"); - //Key_SetKeyDest (key_game); + if (*line) { + Cbuf_AddText (con_data.cbuf, "say_team \""); + Cbuf_AddText (con_data.cbuf, line); + Cbuf_AddText (con_data.cbuf, "\"\n"); + } + con_end_message (il); } static void @@ -480,7 +493,7 @@ C_DrawInputLine (inputline_t *il) static void draw_input (view_t *view) { - if (con_state == con_inactive)// && !con_data.force_commandline) + if (con_state == con_inactive) return; DrawInputLine (view->xabs + 8, view->yabs, 1, input_line); @@ -634,6 +647,8 @@ setup_console (void) float lines = 0; switch (con_state) { + case con_message: + case con_menu: case con_inactive: lines = 0; break; @@ -669,9 +684,9 @@ C_DrawConsole (void) if (console_view->ylen != con_data.lines) view_resize (console_view, console_view->xlen, con_data.lines); - say_view->visible = 0;//FIXME + say_view->visible = con_state == con_message; console_view->visible = con_data.lines != 0; - menu_view->visible = 0;//FIXME + menu_view->visible = con_state == con_menu; con_data.view->draw (con_data.view); } @@ -710,54 +725,6 @@ exec_line (inputline_t *il) { Con_ExecLine (il->line); } -#if 0 -static void -con_end_message (void *line) -{ - //Key_PopEscape (); - Con_ClearTyping (line, 1); - //Key_SetKeyDest (key_game); -} - -static void -con_leave_console (void *data) -{ - ToggleConsole_f (); -} - -static void -con_keydest_callback (keydest_t kd, void *data) -{ - if (kd == key_unfocused || kd == con_curr_keydest) { - return; - } - if (kd != key_console && con_curr_keydest == key_console) { - //Key_PopEscape (); - } - switch (kd) { - case key_last: - case key_game: - case key_demo: - case key_unfocused: - case key_menu: - break; - case key_message: - //Key_PushEscape (con_end_message, - // chat_team ? say_team_line : say_line); - break; - case key_console: - //Key_PushEscape (con_leave_console, 0); - break; - } - con_curr_keydest = kd; -} - -static void -con_enter_menu (void *data) -{ - Menu_Enter (); -} -#endif static void con_key_event (const IE_event_t *event) @@ -778,15 +745,17 @@ con_key_event (const IE_event_t *event) } } #endif -#if 0 - if (con_curr_keydest == key_message) { + if (con_state == con_message) { if (chat_team) { il = say_team_line; } else { il = say_line; } + if (key->code == QFK_ESCAPE) { + con_end_message (il); + return; + } } else { -#endif switch (key->code) { case QFK_ESCAPE: ToggleConsole_f (); @@ -823,18 +792,8 @@ con_key_event (const IE_event_t *event) break; } il = input_line; -#if 0 } -#endif -#if 0 - //FIXME should this translation be here? - if ((unicode==0x0A) && (key==QFK_RETURN)) { - Con_ProcessInputLine (il, key); - } - if ((unicode==0x7F) && (key==QFK_BACKSPACE)) { - Con_ProcessInputLine (il, key); - } -#endif + if (key->unicode) { Con_ProcessInputLine (il, key->code >= 256 ? (int) key->code : key->unicode); @@ -851,6 +810,9 @@ con_mouse_event (const IE_event_t *event) static int con_event_handler (const IE_event_t *ie_event, void *data) { + if (con_state == con_menu) { + return Menu_EventHandler (ie_event); + } static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { [ie_key] = con_key_event, [ie_mouse] = con_mouse_event, @@ -874,11 +836,6 @@ C_Init (void) con_event_id = IE_Add_Handler (con_event_handler, 0); - //Key_PushEscape (con_enter_menu, 0); - //Key_KeydestCallback (con_keydest_callback, 0); - //Key_SetKeyEvent (key_message, C_KeyEvent, 0); - //Key_SetKeyEvent (key_menu, C_KeyEvent, 0); - //Key_SetKeyEvent (key_console, C_KeyEvent, 0); Menu_Init (); con_notifytime = Cvar_Get ("con_notifytime", "3", CVAR_NONE, NULL, diff --git a/libs/console/menu.c b/libs/console/menu.c index a90547ffa..1288b1bab 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -47,6 +47,7 @@ #include "QF/sound.h" #include "QF/sys.h" +#include "QF/input/event.h" #include "QF/ui/view.h" #include "QF/plugin/console.h" @@ -358,13 +359,7 @@ bi_Menu_TopMenu (progs_t *pr) free ((char *) top_menu); top_menu = strdup (name); } -/* -static void -menu_leave (void *data) -{ - Menu_Leave (); -} -*/ + static void bi_Menu_SelectMenu (progs_t *pr) { @@ -374,11 +369,7 @@ bi_Menu_SelectMenu (progs_t *pr) if (name && *name) menu = Hash_Find (menu_hash, name); if (menu) { - /*if (Key_GetKeyDest () != key_menu) { - menu_keydest = Key_GetKeyDest (); - Key_PushEscape (menu_leave, 0); - Key_SetKeyDest (key_menu); - }*/ + Con_SetState (con_menu); if (menu->enter_hook) { run_menu_pre (); PR_ExecuteProgram (&menu_pr_state, menu->enter_hook); @@ -387,8 +378,7 @@ bi_Menu_SelectMenu (progs_t *pr) } else { if (name && *name) Sys_Printf ("no menu \"%s\"\n", name); - //Key_PopEscape (); - //Key_SetKeyDest (menu_keydest); + Con_SetState (con_inactive); } } @@ -473,8 +463,7 @@ bi_Menu_Leave (progs_t *pr) } menu = menu->parent; if (!menu) { - //Key_PopEscape (); - //Key_SetKeyDest (menu_keydest); + Con_SetState (con_inactive); } } } @@ -550,7 +539,19 @@ static builtin_t builtins[] = { {0}, }; - +static int//FIXME reimplement users properly (or remove?) +Menu_KeyEvent (int key, int unicode, int pressed) +{ + IE_event_t event = { + .type = ie_key, + .when = Sys_LongTime (), + .key = { + .code = key, + .unicode = unicode, + } + }; + return IE_Send_Event (&event); +} void Menu_Enter_f (void) @@ -734,20 +735,21 @@ Menu_Draw_Hud (view_t *view) run_menu_post (); } -int -Menu_KeyEvent (knum_t key, short unicode, qboolean down) +static int +menu_key_event (const IE_event_t *ie_event) { menu_item_t *item; int ret; + __auto_type key = ie_event->key; if (!menu) return 0; if (menu->keyevent) { run_menu_pre (); PR_RESET_PARAMS (&menu_pr_state); - P_INT (&menu_pr_state, 0) = key; - P_INT (&menu_pr_state, 1) = unicode; - P_INT (&menu_pr_state, 2) = down; + P_INT (&menu_pr_state, 0) = key.code; + P_INT (&menu_pr_state, 1) = key.unicode; + P_INT (&menu_pr_state, 2) = 1; //FIXME only presses now menu_pr_state.pr_argc = 3; PR_ExecuteProgram (&menu_pr_state, menu->keyevent); ret = R_INT (&menu_pr_state); @@ -762,7 +764,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) PR_RESET_PARAMS (&menu_pr_state); P_STRING (&menu_pr_state, 0) = PR_SetTempString (&menu_pr_state, item->text); - P_INT (&menu_pr_state, 1) = key; + P_INT (&menu_pr_state, 1) = key.code; menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, item->func); PR_PopFrame (&menu_pr_state); @@ -771,38 +773,65 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) if (ret) return 1; } + if (key.code == QFK_ESCAPE) { + Menu_Leave (); + return 1; + } if (!menu || !menu->items) return 0; - switch (key) { + switch (key.code) { + case QFK_ESCAPE: + break; case QFK_DOWN: // case QFM_WHEEL_DOWN: bi_Menu_Next (&menu_pr_state); - return 1; + break; case QFK_UP: // case QFM_WHEEL_UP: bi_Menu_Prev (&menu_pr_state); - return 1; + break; case QFK_RETURN: // case QFM_BUTTON1: bi_Menu_Enter (&menu_pr_state); - return 1; + break; default: - return 0; + break; } + return 1; +} + +static int +menu_mouse_event (const IE_event_t *ie_event) +{ + return 0; +} + +int +Menu_EventHandler (const IE_event_t *ie_event) +{ + static int (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { + [ie_key] = menu_key_event, + [ie_mouse] = menu_mouse_event, + }; + if (ie_event->type < 0 || ie_event->type >= ie_event_count + || !handlers[ie_event->type]) { + return 0; + } + return handlers[ie_event->type] (ie_event); } void Menu_Enter () { if (!top_menu) { - //Key_SetKeyDest (key_console); + Con_SetState (con_active); return; } - menu = Hash_Find (menu_hash, top_menu); + if (!menu) { + menu = Hash_Find (menu_hash, top_menu); + } if (menu) { - //menu_keydest = Key_GetKeyDest (); - //Key_PushEscape (menu_leave, 0); - //Key_SetKeyDest (key_menu); + Con_SetState (con_menu); if (menu->enter_hook) { run_menu_pre (); PR_ExecuteProgram (&menu_pr_state, menu->enter_hook); @@ -822,8 +851,7 @@ Menu_Leave () } menu = menu->parent; if (!menu) { - //Key_PopEscape (); - //Key_SetKeyDest (menu_keydest); + Con_SetState (con_inactive); } } r_data->vid->recalc_refdef = true; diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index f2bd1bce5..0943b4fdc 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -409,8 +409,7 @@ cl_event_handler (const IE_event_t *ie_event, void *unused) { if (ie_event->type == ie_key) { if (ie_event->key.code == QFK_ESCAPE) { - // FIXME this should bring up the menu - Con_SetState (con_active); + Con_SetState (con_menu); return 1; } } diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index afa952fd9..0e093344b 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -566,8 +566,7 @@ cl_event_handler (const IE_event_t *ie_event, void *unused) { if (ie_event->type == ie_key) { if (ie_event->key.code == QFK_ESCAPE) { - // FIXME this should bring up the menu - Con_SetState (con_active); + Con_SetState (con_menu); return 1; } } From f36fa236666dca9122f904b5944d5e2d37bb0cec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 28 Nov 2021 23:22:11 +0900 Subject: [PATCH 1878/3664] [client] Block binding of the escape key Id's binding of escape to togglemenu interfered with the hard-coding (want escape to togglemenu (or console as a fallback) no matter what). This idea was part of mercury's original design, too. --- libs/client/cl_input.c | 12 ++++++++++++ libs/client/old_keys.c | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 75564c559..80ea95ff9 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -30,6 +30,14 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/dstring.h" @@ -63,6 +71,10 @@ cl_bind_f (void) return; } + if (strcasecmp (Cmd_Argv (1), "ESCAPE") == 0) { + return; + } + if (!(key = OK_TranslateKeyName (Cmd_Argv (1)))) { return; } diff --git a/libs/client/old_keys.c b/libs/client/old_keys.c index 69b008c83..2fea7d733 100644 --- a/libs/client/old_keys.c +++ b/libs/client/old_keys.c @@ -59,7 +59,7 @@ typedef struct { } old_keyname_t; old_keyname_t old_keynames[] = { - {"ESCAPE", "key button 0x01"}, + //{"ESCAPE", "key button 0x01"}, binding not allowed {"1", "key button 0x02"}, {"2", "key button 0x03"}, {"3", "key button 0x04"}, From ca23065b907bbe0fca6c9b9f8c5464332b10ecf0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Nov 2021 00:01:57 +0900 Subject: [PATCH 1879/3664] [qw] Get chat info flag mostly working again Currently does only chat (not afk), but the whole thing needs work anyway (billboarded world-space canvas or similar). --- qw/include/cl_input.h | 2 ++ qw/source/cl_chat.c | 26 +++++++---------------- qw/source/cl_input.c | 49 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/qw/include/cl_input.h b/qw/include/cl_input.h index a1c32c4f1..90c125171 100644 --- a/qw/include/cl_input.h +++ b/qw/include/cl_input.h @@ -32,6 +32,8 @@ #include "qw/protocol.h" +void CL_OnFocusChange (void (*func) (int game)); + void CL_Input_Activate (void); void CL_Input_Init (void); void CL_Input_Init_Cvars (void); diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index a101a5f27..a20eb7b89 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -46,6 +46,7 @@ #include "qw/include/client.h" #include "qw/include/cl_chat.h" +#include "qw/include/cl_input.h" llist_t *ignore_list, *dead_ignore_list; @@ -237,7 +238,7 @@ CL_Chat_Flush_Ignores (void) { llist_flush (ignore_list); } -#if 0 + static void CL_ChatInfo (int val) { @@ -250,25 +251,12 @@ CL_ChatInfo (int val) } static void -cl_chat_keydest (keydest_t keydest, void *data) +cl_chat_on_focus_change (int game) { - switch (keydest) { - case key_game: - case key_demo: - CL_ChatInfo (0); - break; - case key_message: - CL_ChatInfo (1); - break; - case key_console: - case key_menu: - case key_unfocused: - case key_last: // should not happen - CL_ChatInfo (2); - break; - } + //FIXME afk mode + CL_ChatInfo (!!game); } -#endif + void CL_Chat_Init (void) @@ -278,5 +266,5 @@ CL_Chat_Init (void) Cmd_AddCommand ("ignore", CL_Ignore_f, "Ignores chat and name-change messages from a user."); Cmd_AddCommand ("unignore", CL_Unignore_f, "Removes a previously ignored user from the ignore list."); - //Key_KeydestCallback (cl_chat_keydest, 0); + CL_OnFocusChange (cl_chat_on_focus_change); } diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 0e093344b..c33cd4966 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -41,6 +41,7 @@ #include "QF/cvar.h" #include "QF/input.h" #include "QF/keys.h" +#include "QF/listener.h" #include "QF/msg.h" #include "QF/sys.h" #include "QF/teamplay.h" @@ -66,6 +67,8 @@ int cl_game_context; int cl_demo_context; static int cl_event_id; +static struct LISTENER_SET_TYPE(int) cl_on_focus_change + = LISTENER_SET_STATIC_INIT(4); cvar_t *cl_nodelta; cvar_t *cl_maxnetfps; @@ -561,16 +564,50 @@ CL_SendCmd (void) Netchan_Transmit (&cls.netchan, buf.cursize, buf.data); } +static int +cl_key_event (const IE_event_t *ie_event) +{ + if (ie_event->key.code == QFK_ESCAPE) { + Con_SetState (con_menu); + return 1; + } + return 0; +} + +static void +cl_on_focus_change_redirect (void *_func, const int *game) +{ + void (*func) (int game) = _func; + func (*game); +} + +void +CL_OnFocusChange (void (*func) (int game)) +{ + LISTENER_ADD (&cl_on_focus_change, cl_on_focus_change_redirect, func); +} + +static int +cl_focus_event (const IE_event_t *ie_event) +{ + int game = ie_event->type == ie_gain_focus; + LISTENER_INVOKE (&cl_on_focus_change, &game); + return 1; +} + static int cl_event_handler (const IE_event_t *ie_event, void *unused) { - if (ie_event->type == ie_key) { - if (ie_event->key.code == QFK_ESCAPE) { - Con_SetState (con_menu); - return 1; - } + static int (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { + [ie_key] = cl_key_event, + [ie_gain_focus] = cl_focus_event, + [ie_lose_focus] = cl_focus_event, + }; + if (ie_event->type < 0 || ie_event->type >= ie_event_count + || !handlers[ie_event->type]) { + return IN_Binding_HandleEvent (ie_event); } - return IN_Binding_HandleEvent (ie_event); + return handlers[ie_event->type] (ie_event); } void From ba49c64fc33f91d3d79c2aea0db3e4e1de636356 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Nov 2021 00:03:53 +0900 Subject: [PATCH 1880/3664] [qw,nq] Clean out sbar key_dest handling I really don't remember why it mattered if key_dest was game. If it was draw layer issues, then this wasn't the correct fix anyway. --- nq/source/sbar.c | 10 +--------- qw/source/sbar.c | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 5798a0112..3bef29f54 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1642,13 +1642,7 @@ Sbar_GIB_Print_Center_f (void) } else Sbar_CenterPrint (GIB_Argv(1)); } -#if 0 -static void -sbar_keydest_callback (keydest_t kd, void *data) -{ - overlay_view->visible = kd == key_game; -} -#endif + void Sbar_Init (void) { @@ -1656,8 +1650,6 @@ Sbar_Init (void) init_views (); - //Key_KeydestCallback (sbar_keydest_callback, 0); - for (i = 0; i < 10; i++) { sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); sb_nums[1][i] = r_funcs->Draw_PicFromWad (va (0, "anum_%i", i)); diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 4c6d58710..ecf74c3e3 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -1939,13 +1939,7 @@ Sbar_GIB_Print_Center_f (void) } else Sbar_CenterPrint (GIB_Argv(1)); } -#if 0 -static void -sbar_keydest_callback (keydest_t kd, void *data) -{ - overlay_view->visible = kd == key_game; -} -#endif + void Sbar_Init (void) { @@ -1953,8 +1947,6 @@ Sbar_Init (void) init_views (); - //Key_KeydestCallback (sbar_keydest_callback, 0); - for (i = 0; i < 10; i++) { sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); sb_nums[1][i] = r_funcs->Draw_PicFromWad (va (0, "anum_%i", i)); From 3b1acf8a7bd541f6b4b7c12b84f4e35cd94ce513 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Nov 2021 11:38:54 +0900 Subject: [PATCH 1881/3664] [qfcc] Correct some errors in the man page --- tools/qfcc/doc/man/qfcc.1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index 045aa8963..5d49b816a 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -332,8 +332,8 @@ for advanced. .TP .B v6only -Restrict the compiler to only version 6 progs (original Quake/QuakeWorld) -features. +Restrict the compiler to produce only version 6 progs (original +Quake/QuakeWorld) features. This means that the compiled data file should be able to run on older servers, as long as you have not used any QuakeForge-specific built-in functions. Also disables compiler features (such as integers and string manipulation @@ -497,7 +497,7 @@ are really just white-space separated strings (use double quotes around files with spaces, though using files with spaces is a gibbing offence). \fB//\fP is used to denote a comment. The comment extends to the end of the current line. -The first file name in the file specified the output file name. +The first file name in the file specifies the output file name. This may be overridden using the \fB-o\fP option. All subsequent file names specify QuakeC source files. .P From 1efeac6d60585779768f07e3f581ffa577102160 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Nov 2021 13:02:30 +0900 Subject: [PATCH 1882/3664] [vkgen] Support specifying enum "searches" directly Being able to parse enums that aren't part of a specified struct is handy for cvars. --- libs/video/renderer/vulkan/vkgen/vkgen.r | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 96c8af060..a186024b8 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -195,7 +195,8 @@ main(int argc, string *argv) id obj = (id) Hash_Find (available_types, search_name); obj = [obj resolveType]; //printf("obj: %d %s\n", obj, class_get_class_name([obj class])); - if (obj && [obj class] == [Struct class]) { + if (obj && ([obj class] == [Struct class] + || [obj class] == [Enum class])) { [obj addToQueue]; } } From c9508f726166253c24318557adb3cb21b20c4b65 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Nov 2021 13:04:08 +0900 Subject: [PATCH 1883/3664] [vkgen] Name-shorten extension enum flag bits The prefix was being stripped, but not the _BIT_EXT suffix. This makes extension flags a little easier to use. --- libs/video/renderer/vulkan/vkgen/vkenum.r | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index e9fa4bc87..ab0ec084c 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -18,6 +18,8 @@ typedef enum VkBool32 { if (str_mid([self name], -8) == "FlagBits") { end = "_FLAG_BITS_MAX_ENUM"; + } else if (str_mid([self name], -11) == "FlagBitsEXT") { + end = "_FLAG_BITS_MAX_ENUM_EXT"; } len = -strlen (end); for (int i = 0; i < type.strct.num_fields; i++) { @@ -82,7 +84,8 @@ skip_value(string name) -(void) writeTable { int strip_bit = 0; - if (str_mid([self name], -8) == "FlagBits") { + if (str_mid([self name], -8) == "FlagBits" + || str_mid([self name], -11) == "FlagBitsEXT") { strip_bit = 1; } From 52f86adb842bcb5f9c1943d9f3f0e1ab56c3ed71 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Nov 2021 13:40:56 +0900 Subject: [PATCH 1884/3664] [vulkan] Fail gracefully if vulkan driver init fails Well, a little more gracefully than a segfault, at least. --- libs/video/renderer/vid_render_vulkan.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index e2f63867d..c3318acdd 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -30,6 +30,7 @@ #include +#include "QF/cvar.h" #include "QF/darray.h" #include "QF/dstring.h" #include "QF/quakefs.h" @@ -530,6 +531,11 @@ static void vulkan_vid_render_choose_visual (void *data) { Vulkan_CreateDevice (vulkan_ctx); + if (!vulkan_ctx->device) { + Sys_Error ("Unable to create Vulkan device.%s", + vulkan_use_validation->int_val ? "" + : "\nSet vulkan_use_validation for details"); + } vulkan_ctx->choose_visual (vulkan_ctx); vulkan_ctx->cmdpool = QFV_CreateCommandPool (vulkan_ctx->device, vulkan_ctx->device->queue.queueFamily, @@ -603,6 +609,9 @@ vulkan_vid_render_init (void) static void vulkan_vid_render_shutdown (void) { + if (!vulkan_ctx || !vulkan_ctx->device) { + return; + } qfv_device_t *device = vulkan_ctx->device; qfv_devfuncs_t *df = device->funcs; VkDevice dev = device->dev; From 901619235b70d55d09f2f7b0a7108d965c69f3ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Nov 2021 13:43:07 +0900 Subject: [PATCH 1885/3664] [vulkan] Split out cvar enum parsing code Need to reuse it :) --- .../video/renderer/vulkan/vulkan_vid_common.c | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 2209f89e0..b7a6530ac 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -86,6 +86,21 @@ cvar_t *vulkan_frame_count; cvar_t *vulkan_presentation_mode; cvar_t *msaaSamples; +static void +parse_cvar_enum (const char *enum_name, const char *err_str, int err_val, + cvar_t *var) +{ + exprctx_t context = {}; + context.memsuper = new_memsuper(); + + if (cexpr_parse_enum (QFV_GetEnum (enum_name), var->string, + &context, &var->int_val)) { + Sys_Printf ("%s\n", err_str); + var->int_val = err_val; + } + delete_memsuper (context.memsuper); +} + static void vulkan_presentation_mode_f (cvar_t *var) { @@ -115,15 +130,8 @@ vulkan_frame_count_f (cvar_t *var) static void msaaSamples_f (cvar_t *var) { - exprctx_t context = {}; - context.memsuper = new_memsuper(); - - if (cexpr_parse_enum (QFV_GetEnum ("VkSampleCountFlagBits"), var->string, - &context, &var->int_val)) { - Sys_Printf ("Invalid MSAA samples, using 1\n"); - var->int_val = VK_SAMPLE_COUNT_1_BIT; - } - delete_memsuper (context.memsuper); + parse_cvar_enum ("VkSampleCountFlagBits", "Invalid MSAA samples, using 1", + VK_SAMPLE_COUNT_1_BIT, var); } static void From 2334798432886a98a2dbfb4f5da2a10e27e561ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Nov 2021 13:44:10 +0900 Subject: [PATCH 1886/3664] [vulkan] Make vulkan_use_validation easier more useful Rather than just 0/1, it now acts as flags to control what messages are printed. In addition to the Vulkan enum names (long and short), none and all are supported (as well as raw numbers, but they're not checked for validity). This makes vulkan_use_validation a bit easier to use and less verbose by default. Now, if only it was easier to remember the name :P --- libs/video/renderer/vulkan/instance.c | 4 ++++ libs/video/renderer/vulkan/vkparse.plist | 1 + .../video/renderer/vulkan/vulkan_vid_common.c | 20 +++++++++++++++++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index d096df421..acb9234bf 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -116,6 +116,7 @@ instance_extension_enabled (qfv_instance_t *inst, const char *ext) } static int message_severities = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; @@ -135,6 +136,9 @@ debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void *data) { + if (!(messageSeverity & vulkan_use_validation->int_val)) { + return 0; + } const char *msgSev = ""; if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { msgSev = "verbose: "; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 22d9173dc..303f00145 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -1,6 +1,7 @@ { search = ( VkAttachmentDescription, + VkDebugUtilsMessageSeverityFlagBitsEXT, VkSubpassDescription, VkSubpassDependency, VkSpecializationInfo, diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index b7a6530ac..12b14c15a 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -118,6 +118,21 @@ vulkan_presentation_mode_f (cvar_t *var) } } +static void +vulkan_use_validation_f (cvar_t *var) +{ + if (!strcmp (var->string, "none")) { + var->int_val = 0; + } else if (!strcmp (var->string, "all")) { + var->int_val = VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT; + } else { + parse_cvar_enum ("VkDebugUtilsMessageSeverityFlagBitsEXT", + "Invalid validation flags, using all", + VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT, + var); + } +} + static void vulkan_frame_count_f (cvar_t *var) { @@ -137,8 +152,9 @@ msaaSamples_f (cvar_t *var) static void Vulkan_Init_Cvars (void) { - vulkan_use_validation = Cvar_Get ("vulkan_use_validation", "1", CVAR_NONE, - 0, + vulkan_use_validation = Cvar_Get ("vulkan_use_validation", + "error|warning", CVAR_NONE, + vulkan_use_validation_f, "enable KRONOS Validation Layer if " "available (requires instance " "restart)."); From a961111b2e05ffa8bc66f7e65abe856f0d07c181 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 Nov 2021 14:30:47 +0900 Subject: [PATCH 1887/3664] [vulkan] Fetch vkCmdPushDescriptorSetKHR as extension Which it is. This allows QF to continue even if the function is not available. --- include/QF/Vulkan/funclist.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 9e5af1ef1..1dec3bcc3 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -173,7 +173,6 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdClearColorImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdExecuteCommands) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPushConstants) -DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPushDescriptorSetKHR) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetViewport) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor) @@ -217,4 +216,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION (vkSetDebugUtilsObjectTagEXT, 0) +DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION + (vkCmdPushDescriptorSetKHR, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME) + #undef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION From 8b85e422d7b2bc061a91aa72db25582ce15a9fde Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 30 Nov 2021 12:24:45 +0900 Subject: [PATCH 1888/3664] [vulkan] Add a debug stack to the vulkan instance The stack is arbitrary strings that the validation layer debug callback prints in reverse order after each message. This makes it easy to work out what nodes in a pipeline/render pass plist are causing validation errors. Still have to narrow down the actual line, but the messages seem to help with that. Putting qfvPushDebug/qfvPopDebug around other calls to vulkan should help out a lot, tool. As a bonus, the stack is printed before debug_breakpoint is called, so it's immediately visible in gdb. --- include/QF/Vulkan/instance.h | 4 ++++ include/vid_vulkan.h | 14 ++++++++++++++ libs/video/renderer/vulkan/instance.c | 5 +++++ libs/video/renderer/vulkan/vkparse.c | 27 ++++++++++++++++++++++++++- libs/video/targets/vid_x11_vulkan.c | 2 +- 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/instance.h b/include/QF/Vulkan/instance.h index 4df1827c5..692dd5964 100644 --- a/include/QF/Vulkan/instance.h +++ b/include/QF/Vulkan/instance.h @@ -28,6 +28,7 @@ #include +#include "QF/darray.h" #include "QF/qtypes.h" typedef struct qfv_instfuncs_s { @@ -36,6 +37,8 @@ typedef struct qfv_instfuncs_s { #include "QF/Vulkan/funclist.h" } qfv_instfuncs_t; +typedef struct DARRAY_TYPE(const char *) qfv_debugstack_t; + typedef struct qfv_physdev_s { struct qfv_instance_s *instance; VkPhysicalDevice dev; @@ -52,6 +55,7 @@ typedef struct qfv_instance_s { VkDebugUtilsMessengerEXT debug_handle; uint32_t numDevices; qfv_physdev_t *devices; + qfv_debugstack_t debug_stack; } qfv_instance_t; struct vulkan_ctx_s; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 8a7cd1535..55841b1d0 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -110,4 +110,18 @@ typedef struct vulkan_ctx_s { #include "QF/Vulkan/funclist.h" } vulkan_ctx_t; +#define qfvPushDebug(ctx, x) \ + do { \ + if (developer->int_val & SYS_vulkan) { \ + DARRAY_APPEND(&(ctx)->instance->debug_stack, (x)); \ + } \ + } while (0) +#define qfvPopDebug(ctx) \ + do { \ + if (developer->int_val & SYS_vulkan) { \ + __auto_type ds = &(ctx)->instance->debug_stack; \ + DARRAY_REMOVE_AT(ds, ds->size - 1); \ + } \ + } while (0) + #endif//__vid_vulkan_h diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index acb9234bf..4ba0a9cd8 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -136,6 +136,7 @@ debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void *data) { + qfv_instance_t *instance = data; if (!(messageSeverity & vulkan_use_validation->int_val)) { return 0; } @@ -154,6 +155,9 @@ debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, } fprintf (stderr, "validation layer: %s%s\n", msgSev, callbackData->pMessage); + for (size_t i = instance->debug_stack.size; i-- > 0; ) { + fprintf (stderr, " %s\n", instance->debug_stack.a[i]); + } debug_breakpoint (messageSeverity); return VK_FALSE; } @@ -264,6 +268,7 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, inst->funcs = (qfv_instfuncs_t *)(inst + 1); inst->enabled_extensions = new_strset (ext); inst->extension_enabled = instance_extension_enabled; + DARRAY_INIT (&inst->debug_stack, 8); ctx->instance = inst; load_instance_funcs (ctx); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 1873c2d42..822c562a6 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -480,7 +480,10 @@ parse_VkShaderModule (const plitem_t *item, void **data, if (*handle) { return 1; } - if (!(*handle = QFV_CreateShaderModule (device, name))) { + qfvPushDebug (ctx, va (ctx->va_ctx, "parse_VkShaderModule: %d", PL_Line (item))); + *handle = QFV_CreateShaderModule (device, name); + qfvPopDebug (ctx); + if (!*handle) { PL_Message (messages, item, "could not find shader %s", name); return 0; } @@ -1030,10 +1033,12 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkRenderPass renderpass; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseRenderPass: %d", PL_Line (plist))); renderpass = QFV_CreateRenderPass (device, renderpass_data.attachments, renderpass_data.subpasses, renderpass_data.dependencies); + qfvPopDebug (ctx); delete_memsuper (memsuper); return renderpass; @@ -1055,7 +1060,9 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } cInfo->a[0].renderPass = ctx->renderpass; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParsePipeline: %d", PL_Line (plist))); __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); + qfvPopDebug (ctx); VkPipeline pipeline = plSet->a[0]; free (plSet); delete_memsuper (memsuper); @@ -1079,7 +1086,9 @@ QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, } VkDescriptorPool pool; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseDescriptorPool: %d", PL_Line (plist))); dfunc->vkCreateDescriptorPool (device->dev, &cInfo, 0, &pool); + qfvPopDebug (ctx); delete_memsuper (memsuper); return pool; @@ -1103,10 +1112,12 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist, } VkDescriptorSetLayout setLayout; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseDescriptorSetLayout: %d", PL_Line (plist))); dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, &setLayout); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, setLayout, va (ctx->va_ctx, "descriptorSetLayout:%d", PL_Line (plist))); + qfvPopDebug (ctx); delete_memsuper (memsuper); return setLayout; @@ -1129,10 +1140,12 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, } VkPipelineLayout layout; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParsePipelineLayout: %d", PL_Line (plist))); dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &layout); QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, va (ctx->va_ctx, "pipelineLayout:%d", PL_Line (plist))); + qfvPopDebug (ctx); delete_memsuper (memsuper); return layout; @@ -1154,7 +1167,9 @@ QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkSampler sampler; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseSampler: %d", PL_Line (plist))); dfunc->vkCreateSampler (device->dev, &cInfo, 0, &sampler); + qfvPopDebug (ctx); delete_memsuper (memsuper); return sampler; @@ -1176,7 +1191,9 @@ QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkImage image; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImage: %d", PL_Line (plist))); dfunc->vkCreateImage (device->dev, &cInfo, 0, &image); + qfvPopDebug (ctx); delete_memsuper (memsuper); return image; @@ -1198,7 +1215,9 @@ QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkImageView imageView; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImageView: %d", PL_Line (plist))); dfunc->vkCreateImageView (device->dev, &cInfo, 0, &imageView); + qfvPopDebug (ctx); delete_memsuper (memsuper); return imageView; @@ -1295,11 +1314,13 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) __auto_type set = QFV_AllocImages (create.count, malloc); for (uint32_t i = 0; i < create.count; i++) { + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImageSet: %d", PL_Line (item))); dfunc->vkCreateImage (device->dev, &create.info[i], 0, &set->a[i]); const char *name = PL_KeyAtIndex (item, i); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, set->a[i], va (ctx->va_ctx, "image:%s", name)); + qfvPopDebug (ctx); name = resource_path (ctx, "images", name); QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]); } @@ -1334,7 +1355,9 @@ QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, __auto_type set = QFV_AllocImageViews (create.count, malloc); for (uint32_t i = 0; i < create.count; i++) { + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImageViewSet: %d", PL_Line (item))); dfunc->vkCreateImageView (device->dev, &create.info[i], 0, &set->a[i]); + qfvPopDebug (ctx); const char *name = PL_KeyAtIndex (item, i); name = resource_path (ctx, "imageViews", name); @@ -1361,7 +1384,9 @@ QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkFramebuffer framebuffer; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseFramebuffer: %d", PL_Line (plist))); dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); + qfvPopDebug (ctx); Sys_MaskPrintf (SYS_vulkan_parse, "framebuffer, renderPass: %#zx, %#zx\n", (size_t) framebuffer, (size_t) cInfo.renderPass); diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index a65cd65b0..39bf90310 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -217,7 +217,7 @@ X11_Vulkan_Context (void) ctx->create_window = x11_vulkan_create_window; ctx->create_surface = x11_vulkan_create_surface; ctx->required_extensions = required_extensions; - ctx->va_ctx = va_create_context (4); + ctx->va_ctx = va_create_context (32); return ctx; } From d76cf9202d5f7987f5286c24d6dc7696628828b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Dec 2021 07:24:06 +0900 Subject: [PATCH 1889/3664] [x11] Create barriers only when grabbing While using barriers is a zillion times better than actually grabbing the mouse and keyboard, they're still a pain when debugging as qf is not able to respond to the barrier-hit events. All the other logic is still there so even when "grabbing", the mouse will not be blocked if the window doesn't have focus. --- libs/video/targets/in_x11.c | 99 ++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 39 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 8b0d6937d..51acca70e 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -153,6 +153,7 @@ static PointerBarrier x11_right_barrier; static PointerBarrier x11_top_barrier; static PointerBarrier x11_bottom_barrier; #endif +static IE_app_window_event_t x11_aw; static int x11_have_xi; static int x11_fd; static int x11_driver_handle = -1; @@ -1071,6 +1072,52 @@ grab_error (int code, const char *device) Sys_Printf ("failed to grab %s: %s\n", device, reason); } +#ifdef HAVE_XFIXES +static void +in_x11_remove_barriers (void) +{ + if (x11_left_barrier > 0) { + XFixesDestroyPointerBarrier (x_disp, x11_left_barrier); + x11_left_barrier = 0; + } + if (x11_right_barrier > 0) { + XFixesDestroyPointerBarrier (x_disp, x11_right_barrier); + x11_right_barrier = 0; + } + if (x11_top_barrier > 0) { + XFixesDestroyPointerBarrier (x_disp, x11_top_barrier); + x11_top_barrier = 0; + } + if (x11_bottom_barrier > 0) { + XFixesDestroyPointerBarrier (x_disp, x11_bottom_barrier); + x11_bottom_barrier = 0; + } +} + +static void +in_x11_setup_barriers (int xpos, int ypos, int xlen, int ylen) +{ + in_x11_remove_barriers (); + + int lx = bound (0, xpos, x_width - 1); + int ty = bound (0, ypos, x_height - 1); + int rx = bound (0, xpos + xlen - 1, x_width - 1); + int by = bound (0, ypos + ylen - 1, x_height - 1); + x11_left_barrier = XFixesCreatePointerBarrier (x_disp, x_root, + lx, ty-1, lx, by+1, + BarrierPositiveX, 0, 0); + x11_right_barrier = XFixesCreatePointerBarrier (x_disp, x_root, + rx, ty-1, rx, by+1, + BarrierNegativeX, 0, 0); + x11_top_barrier = XFixesCreatePointerBarrier (x_disp, x_root, + lx-1, ty, rx+1, ty, + BarrierPositiveY, 0, 0); + x11_bottom_barrier = XFixesCreatePointerBarrier (x_disp, x_root, + lx-1, by, rx+1, by, + BarrierNegativeY, 0, 0); +} +#endif + static void in_x11_grab_input (void *data, int grab) { @@ -1080,6 +1127,12 @@ in_x11_grab_input (void *data, int grab) #ifdef HAVE_XFIXES if (xf_opcode) { input_grabbed = grab; + if (input_grabbed) { + in_x11_setup_barriers (x11_aw.xpos, x11_aw.ypos, + x11_aw.xlen, x11_aw.ylen); + } else { + in_x11_remove_barriers (); + } return; } #endif @@ -1398,49 +1451,17 @@ in_x11_xi_setup_grabs (void) } #endif -#ifdef HAVE_XFIXES -static void -in_x11_setup_barriers (int xpos, int ypos, int xlen, int ylen) -{ - if (x11_left_barrier > 0) { - XFixesDestroyPointerBarrier (x_disp, x11_left_barrier); - } - if (x11_right_barrier > 0) { - XFixesDestroyPointerBarrier (x_disp, x11_right_barrier); - } - if (x11_top_barrier > 0) { - XFixesDestroyPointerBarrier (x_disp, x11_top_barrier); - } - if (x11_bottom_barrier > 0) { - XFixesDestroyPointerBarrier (x_disp, x11_bottom_barrier); - } - - int lx = bound (0, xpos, x_width - 1); - int ty = bound (0, ypos, x_height - 1); - int rx = bound (0, xpos + xlen - 1, x_width - 1); - int by = bound (0, ypos + ylen - 1, x_height - 1); - x11_left_barrier = XFixesCreatePointerBarrier (x_disp, x_root, - lx, ty-1, lx, by+1, - BarrierPositiveX, 0, 0); - x11_right_barrier = XFixesCreatePointerBarrier (x_disp, x_root, - rx, ty-1, rx, by+1, - BarrierNegativeX, 0, 0); - x11_top_barrier = XFixesCreatePointerBarrier (x_disp, x_root, - lx-1, ty, rx+1, ty, - BarrierPositiveY, 0, 0); - x11_bottom_barrier = XFixesCreatePointerBarrier (x_disp, x_root, - lx-1, by, rx+1, by, - BarrierNegativeY, 0, 0); -} -#endif - static void x11_app_window (const IE_event_t *ie_event) { + x11_aw = ie_event->app_window; + Sys_MaskPrintf (SYS_vid, "window: %d %d %d %d\n", + x11_aw.xpos, x11_aw.ypos, x11_aw.xlen, x11_aw.ylen); #ifdef HAVE_XFIXES - //FIXME aw may be needed even without XFixes when resizing is supported - __auto_type aw = ie_event->app_window; - in_x11_setup_barriers (aw.xpos, aw.ypos, aw.xlen, aw.ylen); + if (input_grabbed) { + in_x11_setup_barriers (x11_aw.xpos, x11_aw.ypos, + x11_aw.xlen, x11_aw.ylen); + } #endif } From f7807831d374aff55c03caf45bf7db06c2050c2c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Dec 2021 09:05:34 +0900 Subject: [PATCH 1890/3664] Replace the ancient cygwin readme I don't know if cygwin itself is even relevant these days, but any of our docs for it are way out of date anyway. Also, as github takes any old readme as the repository documentation, it's not the best candidate. --- README.cygwin | 40 ---------------------------------- README.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 40 deletions(-) delete mode 100644 README.cygwin create mode 100644 README.md diff --git a/README.cygwin b/README.cygwin deleted file mode 100644 index 146988522..000000000 --- a/README.cygwin +++ /dev/null @@ -1,40 +0,0 @@ -This file gives instruction for compiling QF with cygwin to run in MS Windows(R). - -DISCLAIMER: Use at your own risk, NO WARRANTY of any kind. NO GUARANTEE of correctness or usability. - -If you have problems with these instructions please let me know. - -email: wildcode@users.sourceforge.net -IRC: irc.xiph.org #quakeforge -========================================================================== - -WARNING: This is not intended for inexperienced users, binaries are available on request. - - QuakeForge may take several hours from bootstrap to the completion - of make install on some systems - -To build win32(mingw) QuakeForge bins you will need to download and install cygwin, and the Microsoft DirectX SDK. Cygwin can be found at http://www.cygwin.org - -Once cygwin is installed along with the appropriate developement modules, copy dinput.h from the DirectX SDK and place it in /usr/include/w32api/ - -If you want to use DirectSound also copy dsound.h to the same spot. - -in the quakeforge source dir, within cygwin, type -./bootstrap -./configure --host=i386-mingw32 --build=i386-cygwin --target=i386-mingw32 --program-prefix= --with-static-plugins --disable-shared --disable-oss --disable-vorbis --disable-Werror --enable-optimize --enable-asmopt --disable-debug --enable-zlib -make -make install - ---disable-Werror is needed as some versions of the DX SDK are buggy. - -Go to the /usr/local/bin directory and copy the qw-* and nq-* files to your dos -quake dir - -Let us know how it works for you. - -NOTE: At the time of writing qw-server.exe was not working correctly. Please refrain from using it unless you are willing to fix it. - -Special Note: QuakeForge supplies only our own version of the programs for Quake. To get the game data, you still need to have purchased Quake or get the shareware version from Id Software. - -Chris Ison (WildCode) for QuakeForge -March 11, 2003 diff --git a/README.md b/README.md new file mode 100644 index 000000000..1bc396b4a --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +# QuakeFor + +QuakeForge is descended from the original Quake engine as released by Id +Software in December 1999, and can be used to play original Quake and +QuakeWorld games and mods (including many modern mods). While this will +always be the case, development continues. + +However, QuakeForge is not just a Quake engine, but includes a +collection of tools for creating Quake mods, and is progressing towards +being a more general game engine. + +## Quake and QuakeWorld + +Support for Quake and QuakeWorld is split into two program sets: nq for +Quake and qw-client for QuakeWorld, with the target system as an +additional suffix: -x11 For the X Window system (Linux, BSD, etc), -win +for MS Windows (plus others that are not currently maintained). + +Both nq and qw-client support multiple renderers: 8-bit software, 32-bit +software, OpenGL 2, EGL (mostly, one non-EGL function is used), and +Vulkan (very WIP), all within the one executable. + +Dedicated servers for both Quake (nq-server) and QuakeWorld (qw-server) +are included, as well as a master server for QuakeWorld (qw-master). + +## Tool + +QuakeForge includes several tools for working with Quake data: +- bsp2image produces wireframe images from Quake maps (bsp files) +- io_mesh_qfmdl for importing and exporting Quake mdl files to/from + Blender +- io_qfmap for Quake map source files (WIP Blender addon) +- pak create, list and extract Quake pak files. There's also zpak which + can be used to compress the contents of pak files using gzip + (QuakeForge has transparent support for gzip compressed files) +- qfbsp for compiling map files to bsp files, includes support for + vis clusters, and can be used to extract data and information from bsp + files. +- qfcc is QuakeForge's version of qcc, but is significantly more + advanced, with support for standard C syntax, including most C types, + as well as Objective-C object oriented programming (Ruamoko). Mmost of + the advanced features require the QuakeForge engine, but qfcc can + produce progs files compatible with the original Quake engine with + limited support for some of the advanced featuers (C syntax, reduced + global usage, some additional operators (eg, better bit operators, + remainder (%)). Includes qfprogs for inspecting progs files. +- qflight creates lightmaps for Quake maps +- qfvis for compiling PVS data for Quake maps. One of the faster + implementations available. +- Plus a few others in various stages of usefulness: qflmp, qfmodelgen, + qfspritegen, wad, qfwavinfo + +## Building + +For now, please refer to INSTALL for information on building on Linux. +Building for windows is done by cross-compiling using MXE. There are +scripts in tools/mingw and tools/mingw64 that automate the process of +configuring and building both the tools run on the build-host and the +windows targets. From 740c70ba2cf0c5fc64c701dad2ddb841e24cce09 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Dec 2021 09:10:16 +0900 Subject: [PATCH 1891/3664] Fix a spelling error Oops --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1bc396b4a..1d36cd9d8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# QuakeFor +# QuakeForge QuakeForge is descended from the original Quake engine as released by Id Software in December 1999, and can be used to play original Quake and From 4dc2e6cac25d36d54a8129ff631925e28d08074a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Dec 2021 01:10:59 +0900 Subject: [PATCH 1892/3664] [nq,qw] Reset view animation pose when model changes I think this bug has been haunting us since we introduced lerping. I do remember chasing bad pose indices 20 years ago and never finding the cause. I guess we never thought to check the view model. --- nq/source/cl_view.c | 6 +++++- qw/source/cl_view.c | 9 ++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index ca8b2dd1a..33fd48187 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -661,7 +661,11 @@ V_CalcRefdef (void) origin += (vec4f_t) { 0, 0, 0.5, 0}; } - view->renderer.model = cl.model_precache[cl.stats[STAT_WEAPON]]; + model_t *model = cl.model_precache[cl.stats[STAT_WEAPON]]; + if (view->renderer.model != model) { + view->animation.pose2 = -1; + } + view->renderer.model = model; view->animation.frame = cl.stats[STAT_WEAPONFRAME]; view->renderer.skin = 0; diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 313a920b7..3a67a4d3c 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -663,11 +663,14 @@ V_CalcRefdef (void) origin += (vec4f_t) { 0, 0, 0.5, 0}; } + model_t *model = cl.model_precache[cl.stats[STAT_WEAPON]]; if (cl.viewstate.flags & (VF_GIB | VF_DEAD)) { - view->renderer.model = NULL; - } else { - view->renderer.model = cl.model_precache[cl.stats[STAT_WEAPON]]; + model = NULL; } + if (view->renderer.model != model) { + view->animation.pose2 = -1; + } + view->renderer.model = model; view->animation.frame = cl.viewstate.weaponframe; view->renderer.skin = 0; From ca9566a425e2b01a7336c46ee0ca42759a68afdd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Dec 2021 16:52:43 +0900 Subject: [PATCH 1893/3664] [qfbsp] Print the number of textures in the bsp I needed to check what sort of numbers to expect for bsp texture counts. It turns out id maps use only 81 max, but oum uses up to 173. --- tools/qfbsp/source/info.c | 51 ++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/tools/qfbsp/source/info.c b/tools/qfbsp/source/info.c index b5477c02e..d641dd9d5 100644 --- a/tools/qfbsp/source/info.c +++ b/tools/qfbsp/source/info.c @@ -7,7 +7,9 @@ #endif #include +#include "QF/qendian.h" #include "QF/sys.h" +#include "QF/va.h" #include "tools/qfbsp/include/brush.h" #include "tools/qfbsp/include/bsp5.h" @@ -16,26 +18,35 @@ typedef struct lumpinfo_s { const char *name; + int data; int size; + const char *(*extra) (const void *data); } lumpinfo_t; +static const char * +num_textures (const void *data) +{ + __auto_type d = (const dmiptexlump_t *)data; + return va (0, " %7d", LittleLong (d->nummiptex)); +} + #define O(f) field_offset (bsp_t, f) static lumpinfo_t lump_info[] = { - { "entities", O(entdatasize) }, - { "planes", O(numplanes) }, - { "textures", O(texdatasize) }, - { "vertices", O(numvertexes) }, - { "visibility", O(visdatasize) }, - { "nodes", O(numnodes) }, - { "texinfo", O(numtexinfo) }, - { "faces", O(numfaces) }, - { "lighting", O(lightdatasize) }, - { "clipnodes", O(numclipnodes) }, - { "leafs", O(numleafs) }, - { "marksurfaces", O(nummarksurfaces) }, - { "edges", O(numedges) }, - { "surfedges", O(numsurfedges) }, - { "models", O(nummodels) }, + { "entities", O(entdata), O(entdatasize) }, + { "planes", O(planes), O(numplanes) }, + { "textures", O(texdata), O(texdatasize), num_textures }, + { "vertices", O(vertexes), O(numvertexes) }, + { "visibility", O(visdata), O(visdatasize) }, + { "nodes", O(nodes), O(numnodes) }, + { "texinfo", O(texinfo), O(numtexinfo) }, + { "faces", O(faces), O(numfaces) }, + { "lighting", O(lightdata), O(lightdatasize) }, + { "clipnodes", O(clipnodes), O(numclipnodes) }, + { "leafs", O(leafs), O(numleafs) }, + { "marksurfaces", O(marksurfaces), O(nummarksurfaces) }, + { "edges", O(edges), O(numedges) }, + { "surfedges", O(surfedges), O(numsurfedges) }, + { "models", O(models), O(nummodels) }, }; void @@ -45,10 +56,16 @@ bspinfo () for (int i = 0; i < HEADER_LUMPS; i++) { lump_t *lump = &bsp->header->lumps[i]; lumpinfo_t *info = &lump_info[i]; + const void *data = *(void **)((byte *) bsp + info->data); size_t *size = (size_t *)((byte *) bsp + info->size); + const char *extra = ""; - printf (" %-12s: %7d %7d %7zd\n", info->name, - lump->fileofs, lump->filelen, *size); + if (info->extra) { + extra = info->extra (data); + } + + printf (" %-12s: %7d %7d %7zd%s\n", info->name, + lump->fileofs, lump->filelen, *size, extra); } for (unsigned i = 0; i < bsp->nummodels; i++) { From 032f9971ed7236f1ed59043eeaecc5fe8a5d9c9c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Dec 2021 13:03:49 +0900 Subject: [PATCH 1894/3664] [plist] Remove incorrect const from PL_RemoveObjectForKey I'm not sure what I was thinking when I made PL_RemoveObjectForKey take a const plitem. One of those times where C could do with being a little more strict. --- include/QF/plist.h | 2 +- libs/util/plist.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/plist.h b/include/QF/plist.h index f2db67193..c83f8d5a3 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -196,7 +196,7 @@ plitem_t *PL_ObjectForKey (const plitem_t *dict, const char *key); isn't a dictionary (includes if \a dict is null). \note You are responsible for freeing the returned object. */ -plitem_t *PL_RemoveObjectForKey (const plitem_t *dict, const char *key); +plitem_t *PL_RemoveObjectForKey (plitem_t *dict, const char *key); /** Retrieve a key from a dictionary object. diff --git a/libs/util/plist.c b/libs/util/plist.c index b731f982f..32bde8a73 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -312,7 +312,7 @@ PL_KeyAtIndex (const plitem_t *item, int index) } VISIBLE plitem_t * -PL_RemoveObjectForKey (const plitem_t *item, const char *key) +PL_RemoveObjectForKey (plitem_t *item, const char *key) { if (!item || item->type != QFDictionary) { return NULL; From e0497c7fffd9f8e383c6be0045ba57b81e43d0cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Dec 2021 15:55:14 +0900 Subject: [PATCH 1895/3664] [tools] Add a tool to dump sprite info --- tools/misc/sprite.py | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tools/misc/sprite.py diff --git a/tools/misc/sprite.py b/tools/misc/sprite.py new file mode 100644 index 000000000..56eda578b --- /dev/null +++ b/tools/misc/sprite.py @@ -0,0 +1,51 @@ +from struct import * +from pprint import * +import sys + +sprite_types = [ + "vp parallel upright", + "facing upright", + "vp parallel", + "oriented", + "vp parallel oriented", +] + +def read_frame(frame, sprite, pref=""): + x,y,w,h = unpack("4i", sprite[:4*4]) + sprite = sprite[4*4:] + print(f"{pref}[{x},{y},{w},{h}]"); + return sprite[w*h:] + +def read_group(frame, sprite): + numFrames = unpack(" Date: Wed, 15 Dec 2021 07:25:03 +0900 Subject: [PATCH 1896/3664] [cvar] Preserve cvars loaded from config files This restores the equivalent functionality that seta in config.cfg provided (no more losing my volume setting after using -nosound). --- libs/util/cvar.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index add043f11..0b383bd8f 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -380,6 +380,10 @@ Cvar_LoadConfig (plitem_t *config) cvar_t *var = Cvar_FindVar (cvar_name); if (var) { Cvar_Set (var, value); + Cvar_SetFlags (var, var->flags | CVAR_ARCHIVE); + } else { + Cvar_Get (cvar_name, value, CVAR_USER_CREATED | CVAR_ARCHIVE, + 0, USER_CVAR); } } } From cbf84d815f58882e8e62b6d24ea3be92ebc6e227 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Dec 2021 12:01:52 +0900 Subject: [PATCH 1897/3664] [client] Add default bindings for key_demo Just F10 (quite) and ` (toggleconsole) so the two can be used during demos, but just this is a major improvement. --- libs/client/default_input.plist | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/libs/client/default_input.plist b/libs/client/default_input.plist index 7e6e03b00..d06390cd1 100644 --- a/libs/client/default_input.plist +++ b/libs/client/default_input.plist @@ -53,6 +53,11 @@ }, { name = key_demo; + imts = ( + { + name = imt_demo; + }, + ); } ); devices = ( @@ -129,6 +134,18 @@ devname = core:keyboard; num_axes = 0; num_buttons = 256; + buttons = ( + { + imt = imt_demo; + num = 41; + binding = toggleconsole; + }, + { + imt = imt_demo; + num = 68; + binding = quit; + }, + ); } ); }; From 68de8615d6e1aae185cda7c1ba5244f7d1244472 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Dec 2021 12:04:30 +0900 Subject: [PATCH 1898/3664] [input] Set cbuf of correct imt context This fixes key_demo bindings not working. Quite the face-palm. --- libs/input/in_imt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 0cb2f9bbf..f3fdaeb41 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -304,6 +304,10 @@ IMT_SetContext (int ctx) switcher = switcher->next) { imt_switcher_update (switcher); } + imt_t *imt = in_contexts.a[imt_current_context].active_imt; + Sys_MaskPrintf (SYS_input, "Switched to %s context, imt %s\n", + in_contexts.a[imt_current_context].name, + imt ? imt->name : 0); } void @@ -312,7 +316,7 @@ IMT_SetContextCbuf (int ctx, cbuf_t *cbuf) if ((size_t) ctx >= in_contexts.size) { Sys_Error ("IMT_SetContextCbuf: invalid context %d", ctx); } - in_contexts.a[imt_current_context].cbuf = cbuf; + in_contexts.a[ctx].cbuf = cbuf; } static imt_t * __attribute__ ((pure)) From 8d58dee4b1a077619cf7b2445924d6f80fe48b41 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Dec 2021 14:14:12 +0900 Subject: [PATCH 1899/3664] [input] Ensure button id is never 0 IN_ButtonAction treats id 0 as not pressed in its internal processing, and the previous input implementation treated 0 as "no key", so this is both the simplest and most correct fix. Fixes mouse left button not working every second time the game is run (due to keyboard and mouse bindings swapping places in the config file (separate issue, if it really is one)). --- libs/input/in_imt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index f3fdaeb41..d64fc7a1d 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -649,6 +649,8 @@ IMT_ProcessButton (int button, int state) while (imt) { in_buttonbinding_t *b = imt->button_bindings.a[button]; if (b) { + // ensure IN_ButtonAction never sees button id 0 + button += 1; switch (b->type) { case inb_button: IN_ButtonAction (b->button, button, state); From 25559243ae09db2f278cff24bb6288c453468149 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 30 Nov 2021 21:00:33 +0900 Subject: [PATCH 1900/3664] [vulkan] Add function to compute next offset When allocating memory for multiple objects that have alignment requirements, it gets tedious keeping track of the offset and the alignment. This is a simple function for walking the offset respecting size and alignment requirements, and doubles as a size calculator. --- include/QF/Vulkan/buffer.h | 4 ++++ libs/video/renderer/vulkan/buffer.c | 9 +++++++++ libs/video/renderer/vulkan/vulkan_lighting.c | 8 +++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h index 712b14a96..f9cbbb0c9 100644 --- a/include/QF/Vulkan/buffer.h +++ b/include/QF/Vulkan/buffer.h @@ -45,4 +45,8 @@ VkBufferView QFV_CreateBufferView (struct qfv_device_s *device, VkBuffer buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize size); +VkDeviceSize QFV_NextOffset (VkDeviceSize current, VkDeviceSize count, + const VkMemoryRequirements *requirements) + __attribute__((pure)); + #endif//__QF_Vulkan_buffer_h diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index eb9da832c..063fe8c73 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -162,3 +162,12 @@ QFV_CreateBufferView (qfv_device_t *device, VkBuffer buffer, VkFormat format, dfunc->vkCreateBufferView (dev, &createInfo, 0, &view); return view; } + +VkDeviceSize +QFV_NextOffset (VkDeviceSize current, VkDeviceSize count, + const VkMemoryRequirements *requirements) +{ + VkDeviceSize align = requirements->alignment - 1; + VkDeviceSize size = (requirements->size + align) & ~align; + return ((current + align) & ~align) + count * size; +} diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index ce13b7bed..755e7d919 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -327,8 +327,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) dfunc->vkGetBufferMemoryRequirements (device->dev, lbuffers->a[0], &requirements); lctx->light_memory = QFV_AllocBufferMemory (device, lbuffers->a[0], - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - frames * requirements.size, 0); + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + QFV_NextOffset (0, frames, &requirements), 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, lctx->light_memory, "memory:lighting"); @@ -359,6 +359,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lights); __auto_type shadow_set = QFV_AllocateDescriptorSet (device, shadow_pool, shadow); + VkDeviceSize light_offset = 0; for (size_t i = 0; i < frames; i++) { __auto_type lframe = &lctx->frames.a[i]; @@ -382,7 +383,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->light_buffer = lbuffers->a[i]; QFV_BindBufferMemory (device, lbuffers->a[i], lctx->light_memory, - i * requirements.size); + light_offset); + light_offset = QFV_NextOffset (light_offset, 1, &requirements); QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, lframe->cmd, "cmd:lighting"); From 5b1052087a58e661305b8981d1aa37f4374d544d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 30 Nov 2021 21:51:21 +0900 Subject: [PATCH 1901/3664] [vulkan] Calculate matrix offset correctly When I changed the matrices from an array of floats to an array of vec4f_t, I forgot to update the flush offsets. Yay for having a Vulkan-capable Intel device with its different alignment requirements. --- libs/video/renderer/vulkan/vulkan_matrices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 670871962..d43ecc7f2 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -135,7 +135,7 @@ Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx) VkMappedMemoryRange ranges[] = { { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, 0, MAT_SIZE }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, - (mat->projection_3d - mat->projection_2d) * sizeof (float), + (mat->projection_3d - mat->projection_2d) * sizeof (mat->projection_2d[0]), MAT_SIZE}, }; dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); From 08721f7a2163a2e3bb56c36dfe99f4594c03a65e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 30 Nov 2021 21:56:57 +0900 Subject: [PATCH 1902/3664] [vulkan] Destroy the right framebuffers Why nvidia's drivers accepted double-destroyed framebuffers is beyond me, but this fixes the Intel drivers complaining about such (and the subsequent segfault). --- libs/video/renderer/vulkan/vulkan_vid_common.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 12b14c15a..01b991e9d 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -572,7 +572,7 @@ Vulkan_DestroyFrames (vulkan_ctx_t *ctx) df->vkDestroyFence (dev, frame->fence, 0); df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0); df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); - df->vkDestroyFramebuffer (dev, frame->framebuffer, 0); + frame->framebuffer = 0; for (int j = 0; j < frame->cmdSetCount; j++) { DARRAY_CLEAR (&frame->cmdSets[j]); } @@ -580,6 +580,11 @@ Vulkan_DestroyFrames (vulkan_ctx_t *ctx) } DARRAY_CLEAR (&ctx->frames); + + for (size_t i = 0; i < ctx->framebuffers->size; i++) { + df->vkDestroyFramebuffer (dev, ctx->framebuffers->a[i], 0); + } + free (ctx->framebuffers); } void From 0c0fce2f037424add8dfdcdcb44f37496ad6a36b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Dec 2021 01:09:38 +0900 Subject: [PATCH 1903/3664] [vulkan] Drop lights with size 0 They can't contribute any light, so no point in keeping them. Fixes the erroneous size-0 shadow maps in the second nq demo. --- libs/video/renderer/vulkan/vulkan_lighting.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 755e7d919..d2fcd5f5a 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -969,7 +969,10 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) qfv_light_t light = {}; parse_light (&light, entity, targets); - DARRAY_APPEND (&lctx->lights, light); + // some lights have 0 output, so drop them + if (light.light) { + DARRAY_APPEND (&lctx->lights, light); + } } } for (size_t i = 0; i < ctx->frames.size; i++) { From 422ad2a6c9a2dc085d5b2b7d5cde85d92fab5b56 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Dec 2021 07:51:38 +0900 Subject: [PATCH 1904/3664] [vulkan] Recreate lighting pvs sets when loading lights Sets never shrink, so assigning a dynamically created set to a statically created set after the working size has reduced (going from demo2 to demo3) causes the set code to attempt to resize the statically created set, which leads to libc having a bad time. --- libs/video/renderer/vulkan/vulkan_lighting.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index d2fcd5f5a..7ceb025e5 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -308,8 +308,6 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&lctx->frames, frames); lctx->frames.grow = 0; - lctx->sun_pvs = set_new (); - lctx->pipeline = Vulkan_CreatePipeline (ctx, "lighting"); lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout"); lctx->sampler = Vulkan_CreateSampler (ctx, "shadow_sampler"); @@ -373,9 +371,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) shadow_set->a[i], va (ctx->va_ctx, "lighting:shadow_set:%zd", i)); - lframe->pvs = set_new (); - DARRAY_INIT (&lframe->lightvis, 16); + lframe->pvs = 0; lframe->leaf = 0; QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); @@ -923,6 +920,17 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) lctx->lights.size = 0; lctx->lightleafs.size = 0; lctx->lightmats.size = 0; + if (lctx->sun_pvs) { + set_delete (lctx->sun_pvs); + } + lctx->sun_pvs = set_new_size (model->brush.visleafs); + for (size_t i = 0; i < ctx->frames.size; i++) { + __auto_type lframe = &lctx->frames.a[i]; + if (lframe->pvs) { + set_delete (lframe->pvs); + } + lframe->pvs = set_new_size (model->brush.visleafs); + } clear_shadows (ctx); From bd31f40c9b8abbb70eb62507875b3cf4ada046c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Dec 2021 14:39:28 +0900 Subject: [PATCH 1905/3664] [cexpr] Support varargs functions While there may be better solutions, I needed a varargs function for building Vulkan specialization data. Like progs functions, negative parameter counts indicate ellipsis with the number of fixed parameters being equal to -param_count - 1. --- libs/util/cexpr-parse.y | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index 46eaae7fe..1f76071ad 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -363,7 +363,7 @@ static exprval_t *function_expr (exprsym_t *fsym, exprlist_t *list, exprctx_t *context) { exprlist_t *l; - int num_args = 0; + int num_args = 1;// one extra for terminating null exprfunc_t *func = 0; exprval_t *result; @@ -371,6 +371,7 @@ static exprval_t *function_expr (exprsym_t *fsym, exprlist_t *list, num_args++; } __auto_type args = (const exprval_t **) alloca (num_args * sizeof (exprval_t *)); + args[num_args - 1] = 0; // terminate array of args for varargs functions __auto_type types = (exprtype_t **) alloca (num_args * sizeof (exprtype_t *)); for (num_args = 0; list; list = l, num_args++) { args[num_args] = list->value; @@ -385,8 +386,15 @@ static exprval_t *function_expr (exprsym_t *fsym, exprlist_t *list, return result; } for (exprfunc_t *f = fsym->value; f->result; f++) { - if (f->num_params == num_args - && memcmp (f->param_types, types, + int num_params = f->num_params; + if (num_params >= 0 && num_args == num_params) { + } else if (num_params < 0 && num_args >= ~num_params) { + num_params = ~num_params; + } else { + continue; + } + if (!num_params + || memcmp (f->param_types, types, num_args * sizeof (exprtype_t *)) == 0) { func = f; break; From 02ba3da0ba801d0fe7740501e2f5b6ea758f240b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Dec 2021 14:49:23 +0900 Subject: [PATCH 1906/3664] [vulkan] Ease writing of specialization data While using binary data objects for specialization data works for bools (as they can be 0 or -1), they don't work so well for numeric values due to having to get the byte order correct and thus are not portable, and difficult to get right. Binary data is still supported, but the data can be written as a string with an array(...) "constructor" expression taking any number of parameters, with each parameter itself being an expression (though values are limited at this stage). Due to the plist format, quotes are required around the expression ("array(...)") --- libs/video/renderer/vulkan/vkparse.c | 101 +++++++++++++++++------ libs/video/renderer/vulkan/vkparse.plist | 6 +- 2 files changed, 78 insertions(+), 29 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 822c562a6..1be4facf8 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -323,32 +323,6 @@ parse_array (const plfield_t *field, const plitem_t *item, return 1; } -static int -parse_data (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) -{ - __auto_type datad = (parse_data_t *) field->data; - __auto_type value = (void **) ((byte *)data + datad->value_offset); - __auto_type size = (size_t *) ((byte *)data + datad->size_offset); - - const void *bindata = PL_BinaryData (item); - size_t binsize = PL_BinarySize (item); - - Sys_MaskPrintf (SYS_vulkan_parse, "parse_data: %s %zd %d %p %p %p\n", - field->name, field->offset, field->type, field->parser, - field->data, data); - Sys_MaskPrintf (SYS_vulkan_parse, " %zd %zd\n", datad->value_offset, - datad->size_offset); - Sys_MaskPrintf (SYS_vulkan_parse, " %zd %p\n", binsize, bindata); - - *value = vkparse_alloc (context, binsize); - memcpy (*value, bindata, binsize); - if ((void *) size > data) { - *size = binsize; - } - return 1; -} - static int parse_string (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -795,6 +769,80 @@ parse_BasePipeline (const plitem_t *item, void **data, return 0; } +typedef struct data_array_s DARRAY_TYPE(byte) data_array_t; +static void +data_array (const exprval_t **params, exprval_t *result, exprctx_t *context) +{ + size_t offset = 0; + for (const exprval_t **param = params; *param; param++) { + offset += (*param)->type->size; + } + __auto_type data = DARRAY_ALLOCFIXED_OBJ (data_array_t, offset, + cmemalloc, context->memsuper); + for (const exprval_t **param = params; *param; param++) { + size_t size = (*param)->type->size; + memcpy (data->a + offset, (*param)->value, size); + offset += size; + } + *(data_array_t **) result->value = data; +} + +static exprtype_t data_array_type = { + "array", + sizeof (data_array_t *), + 0, + 0, +}; +static exprfunc_t data_array_func[] = { + { &data_array_type, -1, 0, data_array }, + {} +}; +static exprsym_t data_array_symbols[] = { + { "array", &cexpr_function, data_array_func }, + {} +}; +static exprtab_t data_array_symtab = { + data_array_symbols, +}; + +static int +parse_specialization_data (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *context) +{ + size_t *size_ptr = (size_t *) data[0]; + void **data_ptr = (void **) data[1]; + + if (PL_Type (item) == QFBinary) { + const void *bindata = PL_BinaryData (item); + size_t binsize = PL_BinarySize (item); + + *data_ptr = vkparse_alloc (context, binsize); + memcpy (*data_ptr, bindata, binsize); + *size_ptr = binsize; + return 1; + } + + data_array_t *da= 0; + exprctx_t ectx = *((parsectx_t *)context)->ectx; + exprval_t result = { &data_array_type, &da }; + ectx.symtab = &data_array_symtab; + ectx.result = &result; + const char *valstr = PL_String (item); + //Sys_MaskPrintf (SYS_vulkan_parse, + // "parse_specialization_data: %s %zd %d %p %p %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); + int ret = !cexpr_eval_string (valstr, &ectx); + if (!ret) { + PL_Message (messages, item, "error parsing specialization data: %s", + valstr); + } else { + *size_ptr = da->size; + *data_ptr = da->a; + } + return ret; +} + #include "libs/video/renderer/vulkan/vkparse.cinc" static void @@ -955,6 +1003,7 @@ QFV_InitParse (vulkan_ctx_t *ctx) cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); cexpr_init_symtab (&imageviewset_symtab, &context); + cexpr_init_symtab (&data_array_symtab, &context); if (!ctx->setLayouts) { ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 303f00145..dad5e4169 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -80,9 +80,9 @@ values = pMapEntries; }; data = { - type = data; - size = dataSize; - data = pData; + type = (custom, (QFBinary, QFString), + parse_specialization_data); + fields = (dataSize, pData); }; }; VkPipelineShaderStageCreateInfo = { From 9e755f270eee6402850eade5e96d77dc7413f48d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Dec 2021 15:01:03 +0900 Subject: [PATCH 1907/3664] [vulkan] Set staging fence timeout to 5 seconds 0.5s seemes to be unreliable on my VersaPro, particularly after a large build. --- libs/video/renderer/vulkan/staging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 28ea169a7..6de9ba21e 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -117,7 +117,7 @@ QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage) fences->a[i] = stage->packets.buffer[i].fence; } dfunc->vkWaitForFences (device->dev, fences->size, fences->a, VK_TRUE, - 500000000ull); + 5000000000ull); for (int i = 0; i < count; i++) { dfunc->vkDestroyFence (device->dev, fences->a[i], 0); } From a6703c95cf2c8406977c090a2259d363a238e1ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Dec 2021 13:38:12 +0900 Subject: [PATCH 1908/3664] [plist] Allow ` to be used without quotes It has no special meaning when parsing property lists, so there's no reason to require quotes around it. --- libs/util/plist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/plist.c b/libs/util/plist.c index 32bde8a73..1fd72f8e2 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -125,7 +125,7 @@ static void init_quotables (void) { const char *unquotables = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz!#$%&*+-./:?@|~_^"; + "`abcdefghijklmnopqrstuvwxyz!#$%&*+-./:?@|~_^"; const byte *c; memset (quotable_bitmap, ~0, sizeof (quotable_bitmap)); for (c = (byte *) unquotables; *c; c++) From 614c744693cd6df426ba9bc9fc42d91ee227e11c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Dec 2021 13:40:52 +0900 Subject: [PATCH 1909/3664] [cexpr] Use ` to allow identifiers to start with a number The generated short names for a lot of Vulkan enums start with a number (eg VK_IMAGE_TYPE_2D -> 2d). Having to prefix the short name with ` is a tiny cost for the convenience. --- libs/util/cexpr-lex.l | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index 026f7eea2..77734c01c 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -108,7 +108,8 @@ m [\-+] D [0-9] B [01] X [0-9a-fA-F] -ID [a-zA-Z_][a-zA-Z_0-9]* +id [a-zA-Z_0-9]* +ID [a-zA-Z_]{id} FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)? FLOATf {FLOAT}[fF] FLOATd {FLOAT}[dD] @@ -153,6 +154,11 @@ STRING \"(\\.|[^"\\])*\" return NAME; } +`{id} { + yylval->symbol = parse_name (yytext + 1, context); + return NAME; + } + \${ID} { yylval->value = parse_variable (yytext + 1, context); return VALUE; From b1ba87e5aad0a0ca95f2ea9cbd51fd5b815b6fa9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Dec 2021 13:44:58 +0900 Subject: [PATCH 1910/3664] [vulkan] Use the short name for the image types Yay for coming up with a solution for enums short names that start with a number, makes things more readable. --- libs/video/renderer/vulkan/deferred.plist | 14 +++++++------- libs/video/renderer/vulkan/shadow.plist | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 0e414453e..1582d1ea7 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -1,7 +1,7 @@ { images = { depth = { - imageType = VK_IMAGE_TYPE_2D; //FIXME short form is 2d... + imageType = `2d; format = x8_d24_unorm_pack32; samples = 1; extent = { @@ -16,7 +16,7 @@ initialLayout = undefined; }; color = { - imageType = VK_IMAGE_TYPE_2D; + imageType = `2d; format = r8g8b8a8_unorm; samples = 1; extent = { @@ -31,7 +31,7 @@ initialLayout = undefined; }; emission = { - imageType = VK_IMAGE_TYPE_2D; + imageType = `2d; format = r16g16b16a16_sfloat; samples = 1; extent = { @@ -46,7 +46,7 @@ initialLayout = undefined; }; normal = { - imageType = VK_IMAGE_TYPE_2D; + imageType = `2d; format = r16g16b16a16_sfloat; samples = 1; extent = { @@ -61,7 +61,7 @@ initialLayout = undefined; }; position = { - imageType = VK_IMAGE_TYPE_2D; + imageType = `2d; format = r32g32b32a32_sfloat; samples = 1; extent = { @@ -76,7 +76,7 @@ initialLayout = undefined; }; opaque = { - imageType = VK_IMAGE_TYPE_2D; + imageType = `2d; format = r8g8b8a8_unorm; samples = 1; extent = { @@ -91,7 +91,7 @@ initialLayout = undefined; }; translucent = { - imageType = VK_IMAGE_TYPE_2D; + imageType = `2d; format = r8g8b8a8_unorm; samples = 1; extent = { diff --git a/libs/video/renderer/vulkan/shadow.plist b/libs/video/renderer/vulkan/shadow.plist index d33855783..93eb8da31 100644 --- a/libs/video/renderer/vulkan/shadow.plist +++ b/libs/video/renderer/vulkan/shadow.plist @@ -2,7 +2,7 @@ images = { shadow = { flags = cube_compatible; - imageType = VK_IMAGE_TYPE_2D; //FIXME short form is 2d... + imageType = `2d; format = x8_d24_unorm_pack32; samples = 1; extent = { From eb828007e975905a8b33468a7be93b2ebb3041ca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Dec 2021 14:40:56 +0900 Subject: [PATCH 1911/3664] [vulkan] Add a comment about next pass timing --- libs/video/renderer/vid_render_vulkan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index c3318acdd..10a13e8c3 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -168,6 +168,9 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) // reset for next time around frame->cmdSets[i].size = 0; + //Regardless of whether any commands were submitted for this subpass, + //must step through each and every subpass, otherwise the attachments + //won't be transitioned correctly. if (i < frame->cmdSetCount - 1) { dfunc->vkCmdNextSubpass (frame->cmdBuffer, subpassContents); } From 84a24dbb34b0ff76790d4822af0556d5efcdf97c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Dec 2021 18:30:57 +0900 Subject: [PATCH 1912/3664] [renderer] Make R_RenderView private This is actually a better solution to the renderer directly accessing client code than provided by 7e078c7f9c8ab27af92ff268f49bac070c9ff617. Essentially, V_RenderView should not have been calling R_RenderView, and CL_UpdateScreen should have been calling V_RenderView directly. The issue was that the renderers expected the world entity model to be valid at all times. Now, R_RenderView checks the world entity model's validity and immediately bails if it is not, and R_ClearState (which is called whenever the client disconnects and thus no longer has a world to render) clears the world entity model. Thus R_RenderView can (and is) now called unconditionally from within the renderer, simplifying renderer-specific variants. --- include/QF/plugin/vid_render.h | 3 +-- include/QF/screen.h | 3 +-- include/r_internal.h | 2 +- include/r_screen.h | 2 -- libs/video/renderer/gl/gl_rmain.c | 2 +- libs/video/renderer/gl/gl_screen.c | 4 ++-- libs/video/renderer/glsl/glsl_main.c | 5 +++++ libs/video/renderer/glsl/glsl_screen.c | 4 ++-- libs/video/renderer/r_screen.c | 4 ++-- libs/video/renderer/sw/screen.c | 4 ++-- libs/video/renderer/sw/sw_rmain.c | 4 ++++ libs/video/renderer/sw32/screen.c | 4 ++-- libs/video/renderer/sw32/sw32_rmain.c | 4 ++++ libs/video/renderer/vid_render_gl.c | 1 - libs/video/renderer/vid_render_glsl.c | 1 - libs/video/renderer/vid_render_sw.c | 1 - libs/video/renderer/vid_render_sw32.c | 1 - libs/video/renderer/vid_render_vulkan.c | 13 +++---------- libs/video/renderer/vulkan/vulkan_main.c | 4 ++++ nq/include/client.h | 1 - nq/source/cl_main.c | 1 + nq/source/cl_screen.c | 3 ++- nq/source/cl_view.c | 2 -- qw/source/cl_main.c | 1 + qw/source/cl_screen.c | 3 ++- qw/source/cl_view.c | 2 -- ruamoko/qwaq/builtins/qwaq-bi.c | 18 ++---------------- 27 files changed, 42 insertions(+), 55 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 108510771..699bef12e 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -148,7 +148,7 @@ typedef struct vid_render_funcs_s { void (*Fog_ParseWorldspawn) (struct plitem_s *worldspawn); void (*R_Init) (void); - void (*R_RenderFrame) (SCR_Func scr_3dfunc, SCR_Func *scr_funcs); + void (*R_RenderFrame) (SCR_Func *scr_funcs); void (*R_ClearState) (void); void (*R_LoadSkys) (const char *); void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); @@ -158,7 +158,6 @@ typedef struct vid_render_funcs_s { dlight_t *(*R_AllocDlight) (int key); entity_t *(*R_AllocEntity) (void); void (*R_MaxDlightsCheck) (struct cvar_s *var); - void (*R_RenderView) (void); void (*R_DecayLights) (double frametime); void (*R_ViewChanged) (void); diff --git a/include/QF/screen.h b/include/QF/screen.h index b904f1c7c..514bb7b60 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -36,8 +36,7 @@ void SCR_Init (void); typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array -void SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, - SCR_Func *scr_funcs); +void SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs); void SCR_SizeUp (void); void SCR_SizeDown (void); diff --git a/include/r_internal.h b/include/r_internal.h index b5847ec03..dfcab0056 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -45,7 +45,7 @@ void gl_R_Init (void); void glsl_R_Init (void); void sw_R_Init (void); void sw32_R_Init (void); -void R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs); +void R_RenderFrame (SCR_Func *scr_funcs); void R_Init_Cvars (void); void R_InitEfrags (void); void R_ClearState (void); diff --git a/include/r_screen.h b/include/r_screen.h index 310f59230..e684b2028 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -34,8 +34,6 @@ #include "QF/screen.h" #include "QF/vid.h" -void SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, - SCR_Func *scr_funcs); void SCR_DrawRam (void); void SCR_DrawFPS (void); void SCR_DrawTime (void); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index b3dfe0c1a..429191157 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -562,7 +562,7 @@ R_RenderView_ (void) return; } if (!r_worldentity.renderer.model) { - Sys_Error ("R_RenderView: NULL worldmodel"); + return; } gl_mirror = false; diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index c70c2067c..ada0b6c9a 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -201,7 +201,7 @@ R_Clear (void) } void -gl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +gl_R_RenderFrame (SCR_Func *scr_funcs) { double time1 = 0, time2; static int begun = 0; @@ -228,7 +228,7 @@ gl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) } // do 3D refresh drawing, and then update the screen - scr_3dfunc (); + gl_R_RenderView (); SCR_SetUpToDrawConsole (); GL_Set2D (); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index a5afc45a6..46b865913 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -181,6 +181,10 @@ glsl_R_RenderView (void) double t[10] = {}; int speeds = r_speeds->int_val; + if (!r_worldentity.renderer.model) { + return; + } + if (speeds) t[0] = Sys_DoubleTime (); glsl_R_SetupFrame (); @@ -272,6 +276,7 @@ glsl_R_LineGraph (int x, int y, int *h_vals, int count, int height) void glsl_R_ClearState (void) { + r_worldentity.renderer.model = 0; R_ClearEfrags (); R_ClearDlights (); glsl_R_ClearParticles (); diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index 4c2a65727..d484799c3 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -156,7 +156,7 @@ SCR_TileClear (void) } void -glsl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +glsl_R_RenderFrame (SCR_Func *scr_funcs) { static int begun = 0; @@ -178,7 +178,7 @@ glsl_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) //update in sw modes but must in glsl mode vr_data.scr_copyeverything = 1; - scr_3dfunc (); + glsl_R_RenderView (); SCR_SetUpToDrawConsole (); GLSL_Set2D (); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 54dffbcb0..30ff8ab1c 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -199,7 +199,7 @@ SCR_CalcRefdef (void) needs almost the entire 256k of stack space! */ void -SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs) { if (scr_skipupdate || !scr_initialized) { return; @@ -212,7 +212,7 @@ SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) SCR_CalcRefdef (); } - r_funcs->R_RenderFrame (scr_3dfunc, scr_funcs); + r_funcs->R_RenderFrame (scr_funcs); } void diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index c833ee200..a3b7966c0 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -182,7 +182,7 @@ SCR_ScreenShot_f (void) } void -R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +R_RenderFrame (SCR_Func *scr_funcs) { vrect_t vrect; @@ -202,7 +202,7 @@ R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) D_DisableBackBufferAccess (); // for adapters that can't stay mapped // in for linear writes all the time VID_LockBuffer (); - scr_3dfunc (); + R_RenderView (); VID_UnlockBuffer (); D_EnableBackBufferAccess (); // of all overlay stuff if drawing diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index f20e2a98c..64a2836b6 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -744,6 +744,9 @@ R_RenderView_ (void) if (r_norefresh->int_val) return; + if (!r_worldentity.renderer.model) { + return; + } r_warpbuffer = warpbuffer; @@ -1160,6 +1163,7 @@ R_RenderViewFishEye (void) void R_ClearState (void) { + r_worldentity.renderer.model = 0; R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index e74e3434f..be5fd5fec 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -139,7 +139,7 @@ sw32_SCR_ScreenShot_f (void) } void -sw32_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +sw32_R_RenderFrame (SCR_Func *scr_funcs) { vrect_t vrect; @@ -159,7 +159,7 @@ sw32_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) sw32_D_DisableBackBufferAccess (); // for adapters that can't stay mapped // in for linear writes all the time VID_LockBuffer (); - scr_3dfunc (); + sw32_R_RenderView (); VID_UnlockBuffer (); sw32_D_EnableBackBufferAccess (); // of all overlay stuff if drawing diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index f928b8c4b..65d400dad 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -750,6 +750,9 @@ R_RenderView_ (void) { if (r_norefresh->int_val) return; + if (!r_worldentity.renderer.model) { + return; + } sw32_r_warpbuffer = warpbuffer; @@ -868,6 +871,7 @@ sw32_R_InitTurb (void) void sw32_R_ClearState (void) { + r_worldentity.renderer.model = 0; R_ClearEfrags (); R_ClearDlights (); sw32_R_ClearParticles (); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index f233873df..380ab3ca2 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -153,7 +153,6 @@ vid_render_funcs_t gl_vid_render_funcs = { R_AllocDlight, R_AllocEntity, R_MaxDlightsCheck, - gl_R_RenderView, R_DecayLights, gl_R_ViewChanged, gl_R_ClearParticles, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index c457323e5..17e7be558 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -152,7 +152,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { R_AllocDlight, R_AllocEntity, R_MaxDlightsCheck, - glsl_R_RenderView, R_DecayLights, glsl_R_ViewChanged, glsl_R_ClearParticles, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index eff04211b..992292c7f 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -149,7 +149,6 @@ vid_render_funcs_t sw_vid_render_funcs = { R_AllocDlight, R_AllocEntity, R_MaxDlightsCheck, - R_RenderView, R_DecayLights, R_ViewChanged, R_ClearParticles, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 504491b76..4139b9008 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -154,7 +154,6 @@ vid_render_funcs_t sw32_vid_render_funcs = { R_AllocDlight, R_AllocEntity, R_MaxDlightsCheck, - sw32_R_RenderView, R_DecayLights, sw32_R_ViewChanged, sw32_R_ClearParticles, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 10a13e8c3..2495d7c8d 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -112,7 +112,7 @@ vulkan_R_Init (void) } static void -vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) +vulkan_R_RenderFrame (SCR_Func *scr_funcs) { const VkSubpassContents subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; @@ -132,13 +132,12 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) frame->framebuffer = vulkan_ctx->framebuffers->a[imageIndex]; - scr_3dfunc (); - view_draw (vr_data.scr_view); while (*scr_funcs) { (*scr_funcs) (); scr_funcs++; } + Vulkan_RenderView (vulkan_ctx); Vulkan_FlushText (vulkan_ctx); @@ -222,6 +221,7 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) static void vulkan_R_ClearState (void) { + r_worldentity.renderer.model = 0; R_ClearEfrags (); R_ClearDlights (); Vulkan_ClearParticles (vulkan_ctx); @@ -244,12 +244,6 @@ vulkan_R_LineGraph (int x, int y, int *h_vals, int count, int height) { } -static void -vulkan_R_RenderView (void) -{ - Vulkan_RenderView (vulkan_ctx); -} - static void vulkan_Draw_Character (int x, int y, unsigned ch) { @@ -678,7 +672,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { R_AllocDlight, R_AllocEntity, R_MaxDlightsCheck, - vulkan_R_RenderView, R_DecayLights, vulkan_R_ViewChanged, vulkan_R_ClearParticles, diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 84dfbe830..ea7ac5508 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -157,6 +157,10 @@ Vulkan_RenderView (vulkan_ctx_t *ctx) double t[9] = {}; int speeds = r_speeds->int_val; + if (!r_worldentity.renderer.model) { + return; + } + if (speeds) t[0] = Sys_DoubleTime (); setup_frame (ctx); diff --git a/nq/include/client.h b/nq/include/client.h index 4702aa44a..20e4347c8 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -328,7 +328,6 @@ void CL_NewTranslation (int slot, struct skin_s *skin); void V_StartPitchDrift (void); void V_StopPitchDrift (void); -void V_RenderView (void); void V_UpdatePalette (void); void V_Register (void); void V_ParseDamage (void); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 683aa910e..8467187b1 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -531,6 +531,7 @@ CL_SetState (cactive_t state) case ca_dedicated: break; case ca_disconnected: + CL_ClearState (); cls.signon = so_none; cl.loading = false; VID_SetCaption ("Disconnected"); diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 03e682d88..d238a204a 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -165,5 +165,6 @@ CL_UpdateScreen (double realtime) scr_funcs_normal[3] = r_funcs->SCR_DrawPause; V_PrepBlend (); - SCR_UpdateScreen (realtime, V_RenderView, scr_funcs[index]); + V_RenderView (); + SCR_UpdateScreen (realtime, scr_funcs[index]); } diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index 33fd48187..80a5dbe1d 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -720,8 +720,6 @@ V_RenderView (void) } else { V_CalcRefdef (); } - - r_funcs->R_RenderView (); } void diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 9ece76d4e..df48b4614 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1145,6 +1145,7 @@ CL_SetState (cactive_t state) if (old_state == ca_active) { // leaving active state IN_ClearStates (); + CL_ClearState (); // Auto demo recorder stops here if (cl_autorecord->int_val && cls.demorecording) diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 7d1db70a4..8eb1ecb3b 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -187,5 +187,6 @@ CL_UpdateScreen (double realtime) scr_funcs_normal[3] = r_funcs->SCR_DrawPause; V_PrepBlend (); - SCR_UpdateScreen (realtime, V_RenderView, scr_funcs[index]); + V_RenderView (); + SCR_UpdateScreen (realtime, scr_funcs[index]); } diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 3a67a4d3c..bf9fe4ae9 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -760,8 +760,6 @@ V_RenderView (void) } else { V_CalcRefdef (); } - - r_funcs->R_RenderView (); } void diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c index 1468380fa..4353d5c14 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/qwaq-bi.c @@ -96,14 +96,7 @@ bi_printf (progs_t *pr) } static progs_t *bi_rprogs; -static func_t qc3d, qc2d; - -static void -bi_3d (void) -{ - if (qc3d) - PR_ExecuteProgram (bi_rprogs, qc3d); -} +static func_t qc2d; static void bi_2d (void) @@ -128,7 +121,7 @@ bi_refresh (progs_t *pr) IN_ProcessEvents (); //GIB_Thread_Execute (); Cbuf_Execute_Stack (qwaq_cbuf); - SCR_UpdateScreen (con_realtime, bi_3d, bi_2dfuncs); + SCR_UpdateScreen (con_realtime, bi_2dfuncs); R_FLOAT (pr) = con_frametime; } @@ -138,12 +131,6 @@ bi_refresh_2d (progs_t *pr) qc2d = P_FUNCTION (pr, 0); } -static void -bi_refresh_3d (progs_t *pr) -{ - qc3d = P_FUNCTION (pr, 0); -} - static void bi_shutdown_ (progs_t *pr) { @@ -154,7 +141,6 @@ static builtin_t builtins[] = { {"printf", bi_printf, -1}, {"refresh", bi_refresh, -1}, {"refresh_2d", bi_refresh_2d, -1}, - {"refresh_3d", bi_refresh_3d, -1}, {"shutdown", bi_shutdown_, -1}, {0} }; From 928408bad9a8cb7ea4b335f5b9263f13428f138c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Dec 2021 21:58:29 +0900 Subject: [PATCH 1913/3664] [vulkan] Support multiple render passes Multiple render passes are needed for supporting shadow mapping, and this is a huge step towards breaking the Vulkan render free of Quake, and hopefully will lead the way for breaking the GL renderers free as well. --- include/QF/Vulkan/qf_alias.h | 10 +- include/QF/Vulkan/qf_bsp.h | 7 +- include/QF/Vulkan/qf_compose.h | 3 +- include/QF/Vulkan/qf_draw.h | 25 +- include/QF/Vulkan/qf_lighting.h | 3 +- include/QF/Vulkan/qf_main.h | 3 +- include/QF/Vulkan/qf_vid.h | 4 +- include/QF/Vulkan/renderpass.h | 29 ++ include/vid_vulkan.h | 16 +- libs/video/renderer/vid_render_vulkan.c | 75 ++--- libs/video/renderer/vulkan/qfpipeline.plist | 22 +- libs/video/renderer/vulkan/vkparse.c | 31 +- libs/video/renderer/vulkan/vkparse.h | 5 +- libs/video/renderer/vulkan/vkparse.plist | 4 + libs/video/renderer/vulkan/vulkan_alias.c | 35 ++- libs/video/renderer/vulkan/vulkan_bsp.c | 51 ++-- libs/video/renderer/vulkan/vulkan_compose.c | 13 +- libs/video/renderer/vulkan/vulkan_draw.c | 8 +- libs/video/renderer/vulkan/vulkan_lighting.c | 21 +- libs/video/renderer/vulkan/vulkan_main.c | 24 +- .../video/renderer/vulkan/vulkan_vid_common.c | 267 +++++++++++------- 21 files changed, 393 insertions(+), 263 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 4d8f7958a..5d414f175 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -92,8 +92,10 @@ typedef struct aliasctx_s { } aliasctx_t; struct vulkan_ctx_s; +struct qfv_renderframe_s; struct entity_s; struct mod_alias_ctx_s; + void *Vulkan_Mod_LoadSkin (struct mod_alias_ctx_s *alias_ctx, byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc, @@ -106,13 +108,13 @@ void Vulkan_Mod_MakeAliasModelDisplayLists (struct mod_alias_ctx_s *alias_ctx, void *_m, int _s, int extra, struct vulkan_ctx_s *ctx); -void Vulkan_AliasBegin (struct vulkan_ctx_s *ctx); -void Vulkan_DrawAlias (struct entity_s *ent, struct vulkan_ctx_s *ctx); -void Vulkan_AliasEnd (struct vulkan_ctx_s *ctx); +void Vulkan_AliasBegin (struct qfv_renderframe_s *rFrame); +void Vulkan_DrawAlias (struct entity_s *ent, struct qfv_renderframe_s *rFrame); +void Vulkan_AliasEnd (struct qfv_renderframe_s *rFrame); void Vulkan_Alias_Init (struct vulkan_ctx_s *ctx); void Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_AliasDepthRange (struct vulkan_ctx_s *ctx, float n, float f); +void Vulkan_AliasDepthRange (struct qfv_renderframe_s *rFrame, float n, float f); #endif//__QF_Vulkan_qf_alias_h diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 19e317ded..3618d8680 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -176,9 +176,11 @@ typedef struct bspctx_s { } bspctx_t; struct vulkan_ctx_s; +struct qfv_renderframe_s; void Vulkan_ClearElements (struct vulkan_ctx_s *ctx); -void Vulkan_DrawWorld (struct vulkan_ctx_s *ctx); -void Vulkan_DrawSky (struct vulkan_ctx_s *ctx); +void Vulkan_DrawWorld (struct qfv_renderframe_s *rFrame); +void Vulkan_DrawSky (struct qfv_renderframe_s *rFrame); +void Vulkan_DrawWaterSurfaces (struct qfv_renderframe_s *rFrame); void Vulkan_LoadSkys (const char *sky, struct vulkan_ctx_s *ctx); void Vulkan_RegisterTextures (model_t **models, int num_models, struct vulkan_ctx_s *ctx); @@ -186,6 +188,5 @@ void Vulkan_BuildDisplayLists (model_t **models, int num_models, struct vulkan_ctx_s *ctx); void Vulkan_Bsp_Init (struct vulkan_ctx_s *ctx); void Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_DrawWaterSurfaces (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_bsp_h diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h index f8fd497a1..b8942dba7 100644 --- a/include/QF/Vulkan/qf_compose.h +++ b/include/QF/Vulkan/qf_compose.h @@ -54,9 +54,10 @@ typedef struct composectx_s { } composectx_t; struct vulkan_ctx_s; +struct qfv_renderframe_s; void Vulkan_Compose_Init (struct vulkan_ctx_s *ctx); void Vulkan_Compose_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Compose_Draw (struct vulkan_ctx_s *ctx); +void Vulkan_Compose_Draw (struct qfv_renderframe_s *fFrame); #endif//__QF_Vulkan_qf_compose_h diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index c9e8b20ad..26f9d2a28 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -29,6 +29,8 @@ #define __QF_Vulkan_qf_draw_h struct vulkan_ctx_s; +struct qfv_renderframe_s; +struct qpic_s; void Vulkan_Draw_Init (struct vulkan_ctx_s *ctx); void Vulkan_Draw_Shutdown (struct vulkan_ctx_s *ctx); @@ -52,16 +54,19 @@ void Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, struct vulkan_ctx_s *ctx); void Vulkan_Draw_FadeScreen (struct vulkan_ctx_s *ctx); void Vulkan_Draw_BlendScreen (quat_t color, struct vulkan_ctx_s *ctx); -qpic_t *Vulkan_Draw_CachePic (const char *path, qboolean alpha, - struct vulkan_ctx_s *ctx); +struct qpic_s *Vulkan_Draw_CachePic (const char *path, qboolean alpha, + struct vulkan_ctx_s *ctx); void Vulkan_Draw_UncachePic (const char *path, struct vulkan_ctx_s *ctx); -qpic_t *Vulkan_Draw_MakePic (int width, int height, const byte *data, - struct vulkan_ctx_s *ctx); -void Vulkan_Draw_DestroyPic (qpic_t *pic, struct vulkan_ctx_s *ctx); -qpic_t *Vulkan_Draw_PicFromWad (const char *name, struct vulkan_ctx_s *ctx); -void Vulkan_Draw_Pic (int x, int y, qpic_t *pic, struct vulkan_ctx_s *ctx); -void Vulkan_Draw_Picf (float x, float y, qpic_t *pic, struct vulkan_ctx_s *ctx); -void Vulkan_Draw_SubPic(int x, int y, qpic_t *pic, +struct qpic_s *Vulkan_Draw_MakePic (int width, int height, const byte *data, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_DestroyPic (struct qpic_s *pic, struct vulkan_ctx_s *ctx); +struct qpic_s *Vulkan_Draw_PicFromWad (const char *name, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Pic (int x, int y, struct qpic_s *pic, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Picf (float x, float y, struct qpic_s *pic, + struct vulkan_ctx_s *ctx); +void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height, struct vulkan_ctx_s *ctx); @@ -69,6 +74,6 @@ void Vulkan_Set2D (struct vulkan_ctx_s *ctx); void Vulkan_Set2DScaled (struct vulkan_ctx_s *ctx); void Vulkan_End2D (struct vulkan_ctx_s *ctx); void Vulkan_DrawReset (struct vulkan_ctx_s *ctx); -void Vulkan_FlushText (struct vulkan_ctx_s *ctx); +void Vulkan_FlushText (struct qfv_renderframe_s *rFrame); #endif//__QF_Vulkan_qf_draw_h diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index e7940d847..c96c08f0e 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -128,10 +128,11 @@ typedef struct lightingctx_s { } lightingctx_t; struct vulkan_ctx_s; +struct qfv_renderframe_s;; void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Lighting_Draw (struct vulkan_ctx_s *ctx); +void Vulkan_Lighting_Draw (struct qfv_renderframe_s *fFrame); void Vulkan_LoadLights (model_t *model, const char *entity_data, struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_main.h b/include/QF/Vulkan/qf_main.h index 4b487da5e..23a02e11d 100644 --- a/include/QF/Vulkan/qf_main.h +++ b/include/QF/Vulkan/qf_main.h @@ -29,9 +29,10 @@ #define __QF_Vulkan_qf_main_h struct vulkan_ctx_s; +struct qfv_renderframe_s; void Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, struct vulkan_ctx_s *ctx); -void Vulkan_RenderView (struct vulkan_ctx_s *ctx); +void Vulkan_RenderView (struct qfv_renderframe_s *rFrame); #endif//__QF_Vulkan_qf_main_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 8b94b2408..db37faa59 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -61,10 +61,8 @@ struct vulkan_ctx_s; void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateCapture (struct vulkan_ctx_s *ctx); -void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); -void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); -void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); +void Vulkan_DestroyRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx); void Vulkan_DestroyMatrices (struct vulkan_ctx_s *ctx); void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index a584d476d..31ea607ca 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -47,4 +47,33 @@ QFV_CreateFramebuffer (struct qfv_device_s *device, struct qfv_imageviewset_s *attachments, VkExtent2D, uint32_t layers); +typedef struct qfv_renderframe_s { + struct vulkan_ctx_s *vulkan_ctx; + struct qfv_renderpass_s *renderpass; + VkSubpassContents subpassContents; + int subpassCount; + struct qfv_cmdbufferset_s *subpassCmdSets; +} qfv_renderframe_t; + +typedef struct qfv_renderframeset_s + DARRAY_TYPE (qfv_renderframe_t) qfv_renderframeset_t; + +typedef struct clearvalueset_s + DARRAY_TYPE (VkClearValue) clearvalueset_t; + +typedef struct qfv_renderpass_s { + struct plitem_s *renderpassDef; + VkRenderPass renderpass; + clearvalueset_t *clearValues; + struct qfv_imageset_s *attachment_images; + struct qfv_imageviewset_s *attachment_views; + VkDeviceMemory attachmentMemory; + + qfv_framebufferset_t *framebuffers; + + qfv_renderframeset_t frames; + + void (*draw) (qfv_renderframe_t *rFrame); +} qfv_renderpass_t; + #endif//__QF_Vulkan_renderpass_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 55841b1d0..584502b9c 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -15,9 +15,6 @@ typedef struct vulkan_frame_s { VkSemaphore imageAvailableSemaphore; VkSemaphore renderDoneSemaphore; VkCommandBuffer cmdBuffer; - - int cmdSetCount; - struct qfv_cmdbufferset_s *cmdSets; } vulkan_frame_t; typedef struct vulkan_matrices_s { @@ -33,8 +30,8 @@ typedef struct vulkan_matrices_s { typedef struct vulkan_frameset_s DARRAY_TYPE (vulkan_frame_t) vulkan_frameset_t; -typedef struct clearvalueset_s - DARRAY_TYPE (VkClearValue) clearvalueset_t; +typedef struct qfv_renderpassset_s + DARRAY_TYPE (struct qfv_renderpass_s *) qfv_renderpassset_t; typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); @@ -58,15 +55,7 @@ typedef struct vulkan_ctx_s { VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain struct plitem_s *pipelineDef; - struct plitem_s *renderpassDef; - VkRenderPass renderpass; - clearvalueset_t *clearValues; - struct qfv_imageset_s *attachment_images; - struct qfv_imageviewset_s *attachment_views; - VkDeviceMemory attachmentMemory; - uint32_t swapImageIndex; - struct qfv_framebufferset_s *framebuffers; struct hashtab_s *shaderModules; struct hashtab_s *setLayouts; @@ -92,6 +81,7 @@ typedef struct vulkan_ctx_s { struct qfv_stagebuf_s *staging; size_t curFrame; vulkan_frameset_t frames; + qfv_renderpassset_t renderPasses; struct qfv_capture_s *capture; void (*capture_callback) (const byte *data, int width, int height); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 2495d7c8d..718d22464 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -98,14 +98,15 @@ vulkan_R_Init (void) Vulkan_CreateFrames (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); - Vulkan_CreateFramebuffers (vulkan_ctx); Vulkan_Texture_Init (vulkan_ctx); + Vulkan_Alias_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); Vulkan_Particles_Init (vulkan_ctx); Vulkan_Lighting_Init (vulkan_ctx); Vulkan_Compose_Init (vulkan_ctx); + Skin_Init (); SCR_Init (); @@ -114,8 +115,6 @@ vulkan_R_Init (void) static void vulkan_R_RenderFrame (SCR_Func *scr_funcs) { - const VkSubpassContents subpassContents - = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; uint32_t imageIndex = 0; qfv_device_t *device = vulkan_ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -130,52 +129,61 @@ vulkan_R_RenderFrame (SCR_Func *scr_funcs) 0, &imageIndex); vulkan_ctx->swapImageIndex = imageIndex; - frame->framebuffer = vulkan_ctx->framebuffers->a[imageIndex]; - view_draw (vr_data.scr_view); while (*scr_funcs) { (*scr_funcs) (); scr_funcs++; } - Vulkan_RenderView (vulkan_ctx); - Vulkan_FlushText (vulkan_ctx); - - Vulkan_Lighting_Draw (vulkan_ctx); - Vulkan_Compose_Draw (vulkan_ctx); + for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { + __auto_type rp = vulkan_ctx->renderPasses.a[i]; + __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + rp->draw (rpFrame); + } VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + VkRenderPassBeginInfo renderPassInfo = { - VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, - vulkan_ctx->renderpass, 0, - { {0, 0}, vulkan_ctx->swapchain->extent }, - vulkan_ctx->clearValues->size, vulkan_ctx->clearValues->a + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderArea = { {0, 0}, vulkan_ctx->swapchain->extent }, }; dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); - renderPassInfo.framebuffer = frame->framebuffer; - dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, - subpassContents); + for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { + __auto_type rp = vulkan_ctx->renderPasses.a[i]; + __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - for (int i = 0; i < frame->cmdSetCount; i++) { - if (frame->cmdSets[i].size) { - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, - frame->cmdSets[i].size, - frame->cmdSets[i].a); - } - // reset for next time around - frame->cmdSets[i].size = 0; - //Regardless of whether any commands were submitted for this subpass, - //must step through each and every subpass, otherwise the attachments - //won't be transitioned correctly. - if (i < frame->cmdSetCount - 1) { - dfunc->vkCmdNextSubpass (frame->cmdBuffer, subpassContents); + frame->framebuffer = rp->framebuffers->a[imageIndex]; + renderPassInfo.framebuffer = frame->framebuffer, + renderPassInfo.renderPass = rp->renderpass; + renderPassInfo.clearValueCount = rp->clearValues->size; + renderPassInfo.pClearValues = rp->clearValues->a; + + dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, + rpFrame->subpassContents); + + for (int j = 0; j < rpFrame->subpassCount; j++) { + __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; + if (cmdSet->size) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, + cmdSet->size, cmdSet->a); + } + // reset for next time around + cmdSet->size = 0; + + //Regardless of whether any commands were submitted for this + //subpass, must step through each and every subpass, otherwise + //the attachments won't be transitioned correctly. + if (j < rpFrame->subpassCount - 1) { + dfunc->vkCmdNextSubpass (frame->cmdBuffer, + rpFrame->subpassContents); + } } + dfunc->vkCmdEndRenderPass (frame->cmdBuffer); } - dfunc->vkCmdEndRenderPass (frame->cmdBuffer); if (vulkan_ctx->capture_callback) { VkImage srcImage = vulkan_ctx->swapchain->images->a[imageIndex]; VkCommandBuffer cmd = QFV_CaptureImage (vulkan_ctx->capture, srcImage, @@ -615,15 +623,16 @@ vulkan_vid_render_shutdown (void) QFV_DeviceWaitIdle (device); df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); + Vulkan_Compose_Shutdown (vulkan_ctx); Vulkan_Lighting_Shutdown (vulkan_ctx); Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Alias_Shutdown (vulkan_ctx); + Mod_ClearAll (); Vulkan_Texture_Shutdown (vulkan_ctx); - Vulkan_DestroyFramebuffers (vulkan_ctx); - Vulkan_DestroyRenderPass (vulkan_ctx); + Vulkan_DestroyRenderPasses (vulkan_ctx); Vulkan_Shutdown_Common (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 31e14ad7f..3bbbb7b46 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -595,7 +595,7 @@ dynamicState = ( viewport, scissor ); }; layout = quakebsp_layout; - //renderPass = renderpass; + renderPass = renderpass; }; alias_depth = { subpass = 0; @@ -629,7 +629,7 @@ dynamicState = ( viewport, scissor ); }; layout = alias_layout; - //renderPass = renderpass; + renderPass = renderpass; }; alias_gbuf = { subpass = 2; @@ -670,7 +670,7 @@ dynamicState = ( viewport, scissor, blend_constants ); }; layout = alias_layout; - //renderPass = renderpass; + renderPass = renderpass; }; bsp_depth = { subpass = 0; @@ -699,7 +699,7 @@ dynamicState = ( viewport, scissor ); }; layout = quakebsp_layout; - //renderPass = renderpass; + renderPass = renderpass; }; bsp_gbuf = { subpass = 2; @@ -748,7 +748,7 @@ dynamicState = ( viewport, scissor, blend_constants ); }; layout = quakebsp_layout; - //renderPass = renderpass; + renderPass = renderpass; }; bsp_skybox = { subpass = 1; @@ -785,7 +785,7 @@ dynamicState = ( viewport, scissor ); }; layout = quakebsp_layout; - //renderPass = renderpass; + renderPass = renderpass; }; bsp_skysheet = { subpass = 1; @@ -822,7 +822,7 @@ dynamicState = ( viewport, scissor ); }; layout = quakebsp_layout; - //renderPass = renderpass; + renderPass = renderpass; }; bsp_turb = { subpass = 1; @@ -859,7 +859,7 @@ dynamicState = ( viewport, scissor ); }; layout = quakebsp_layout; - //renderPass = renderpass; + renderPass = renderpass; }; twod = { subpass = 1; @@ -889,7 +889,7 @@ dynamicState = ( viewport, scissor ); }; layout = twod_layout; - //renderPass = renderpass; + renderPass = renderpass; }; lighting = { subpass = 3; @@ -916,7 +916,7 @@ dynamicState = ( viewport, scissor ); }; layout = lighting_layout; - //renderPass = renderpass; + renderPass = renderpass; }; compose = { subpass = 4; @@ -943,7 +943,7 @@ dynamicState = ( viewport, scissor ); }; layout = compose_layout; - //renderPass = renderpass; + renderPass = renderpass; }; }; } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 1be4facf8..3a5431db4 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -938,11 +938,11 @@ exprtype_t vulkan_frameset_t_type = { &vulkan_frameset_t_symtab, }; -typedef struct qfv_renderpass_s { +typedef struct { qfv_attachmentdescription_t *attachments; qfv_subpassparametersset_t *subpasses; qfv_subpassdependency_t *dependencies; -} qfv_renderpass_t; +} vkparse_renderpass_t; static plelement_t parse_qfv_renderpass_attachments_data = { QFDictionary, @@ -969,11 +969,11 @@ static plelement_t parse_qfv_renderpass_dependencies_data = { }; static plfield_t renderpass_fields[] = { - { "attachments", field_offset (qfv_renderpass_t, attachments), QFArray, + { "attachments", field_offset(vkparse_renderpass_t,attachments), QFArray, PL_ParseArray, &parse_qfv_renderpass_attachments_data }, - { "subpasses", field_offset (qfv_renderpass_t, subpasses), QFArray, + { "subpasses", field_offset(vkparse_renderpass_t,subpasses), QFArray, PL_ParseArray, &parse_qfv_renderpass_subpasses_data }, - { "dependencies", field_offset (qfv_renderpass_t, dependencies), QFArray, + { "dependencies", field_offset(vkparse_renderpass_t,dependencies), QFArray, PL_ParseArray, &parse_qfv_renderpass_dependencies_data }, {} }; @@ -1073,7 +1073,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) memsuper_t *memsuper = new_memsuper (); qfv_device_t *device = ctx->device; - qfv_renderpass_t renderpass_data = {}; + vkparse_renderpass_t renderpass_data = {}; if (!parse_object (ctx, memsuper, plist, parse_qfv_renderpass, &renderpass_data, properties)) { @@ -1108,8 +1108,9 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) return 0; } - cInfo->a[0].renderPass = ctx->renderpass; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParsePipeline: %d", PL_Line (plist))); + qfvPushDebug (ctx, va (ctx->va_ctx, + "QFV_ParsePipeline: %d", PL_Line (plist))); + __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); qfvPopDebug (ctx); VkPipeline pipeline = plSet->a[0]; @@ -1462,22 +1463,18 @@ parse_clearvalueset (const plfield_t *field, const plitem_t *item, void *data, return 1; } -int +clearvalueset_t * QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { - int ret = 0; + clearvalueset_t *cv = 0; memsuper_t *memsuper = new_memsuper (); clearvalueset_t *clearValues = 0; - ctx->clearValues = 0; if (parse_object (ctx, memsuper, plist, parse_clearvalueset, &clearValues, properties)) { - ret = 1; - ctx->clearValues = DARRAY_ALLOCFIXED (clearvalueset_t, - clearValues->size, malloc); - memcpy (ctx->clearValues->a, clearValues->a, - clearValues->size * sizeof (clearValues->a[0])); + cv = DARRAY_ALLOCFIXED (clearvalueset_t, clearValues->size, malloc); + memcpy (cv->a, clearValues->a, cv->size * sizeof (cv->a[0])); } delete_memsuper (memsuper); - return ret; + return cv; } diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 4f258a96f..6e2ef92b2 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -58,8 +58,9 @@ struct qfv_imageviewset_s *QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *properties); VkFramebuffer QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties); -int QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); +struct clearvalueset_s *QFV_ParseClearValues (vulkan_ctx_t *ctx, + plitem_t *plist, + plitem_t *properties); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index dad5e4169..415e31d0a 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -282,6 +282,10 @@ type = (custom, QFString, parse_VkPipelineLayout); fields = (layout); }; + renderPass = { + type = (custom, QFString, parse_VkRenderPass); + fields = (renderPass); + }; subpass = auto; basePipelineHandle = { type = (custom, QFString, parse_BasePipeline); diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 810bc14ef..50aacfe4a 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -60,6 +60,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/renderpass.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -81,8 +82,9 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_alias_skin_t *skin, void *vert_constants, int vert_size, void *frag_constants, int frag_size, - aliashdr_t *hdr, vulkan_ctx_t *ctx) + aliashdr_t *hdr, qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; @@ -123,8 +125,9 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, } void -Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx) +Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; aliasctx_t *actx = ctx->alias_context; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; model_t *model = ent->renderer.model; @@ -159,18 +162,19 @@ Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx) ent->animation.pose1, ent->animation.pose2, 0, &vertex_constants, 17 * sizeof (float), fragment_constants, sizeof (fragment_constants), - hdr, ctx); + hdr, rFrame); emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], ent->animation.pose1, ent->animation.pose2, skin, &vertex_constants, 17 * sizeof (float), fragment_constants, sizeof (fragment_constants), - hdr, ctx); + hdr, rFrame); } static void alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, - vulkan_ctx_t *ctx) + qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; @@ -181,7 +185,7 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, subpass_map[subpass], + rFrame->renderpass->renderpass, subpass_map[subpass], cframe->framebuffer, 0, 0, 0, }; @@ -226,28 +230,29 @@ alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) } void -Vulkan_AliasBegin (vulkan_ctx_t *ctx) +Vulkan_AliasBegin (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; aliasctx_t *actx = ctx->alias_context; - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; //XXX quat_t fog; - DARRAY_APPEND (&cframe->cmdSets[QFV_passDepth], + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], aframe->cmdSet.a[QFV_aliasDepth]); - DARRAY_APPEND (&cframe->cmdSets[QFV_passGBuffer], + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], aframe->cmdSet.a[QFV_aliasGBuffer]); //FIXME need per frame matrices aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - alias_begin_subpass (QFV_aliasDepth, actx->depth, ctx); - alias_begin_subpass (QFV_aliasGBuffer, actx->gbuf, ctx); + alias_begin_subpass (QFV_aliasDepth, actx->depth, rFrame); + alias_begin_subpass (QFV_aliasGBuffer, actx->gbuf, rFrame); } void -Vulkan_AliasEnd (vulkan_ctx_t *ctx) +Vulkan_AliasEnd (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; aliasctx_t *actx = ctx->alias_context; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; @@ -256,8 +261,10 @@ Vulkan_AliasEnd (vulkan_ctx_t *ctx) } void -Vulkan_AliasDepthRange (vulkan_ctx_t *ctx, float minDepth, float maxDepth) +Vulkan_AliasDepthRange (qfv_renderframe_t *rFrame, + float minDepth, float maxDepth) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index bcf1b31b4..7a009943f 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -63,6 +63,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" @@ -825,8 +826,9 @@ get_view (qfv_tex_t *tex, qfv_tex_t *default_tex) static void bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, - vulkan_ctx_t *ctx) + qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; @@ -837,7 +839,7 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, subpass_map[subpass], + rFrame->renderpass->renderpass, subpass_map[subpass], cframe->framebuffer, 0, 0, 0, }; @@ -886,20 +888,20 @@ bsp_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) } static void -bsp_begin (vulkan_ctx_t *ctx) +bsp_begin (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; bspctx_t *bctx = ctx->bsp_context; //XXX quat_t fog; bctx->default_color[3] = 1; QuatCopy (bctx->default_color, bctx->last_color); - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - DARRAY_APPEND (&cframe->cmdSets[QFV_passDepth], + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], bframe->cmdSet.a[QFV_bspDepth]); - DARRAY_APPEND (&cframe->cmdSets[QFV_passGBuffer], + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], bframe->cmdSet.a[QFV_bspGBuffer]); //FIXME need per frame matrices @@ -912,8 +914,8 @@ bsp_begin (vulkan_ctx_t *ctx) bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, bctx->default_skybox); - bsp_begin_subpass (QFV_bspDepth, bctx->depth, ctx); - bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, ctx); + bsp_begin_subpass (QFV_bspDepth, bctx->depth, rFrame); + bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, rFrame); } static void @@ -927,18 +929,18 @@ bsp_end (vulkan_ctx_t *ctx) } static void -turb_begin (vulkan_ctx_t *ctx) +turb_begin (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; bspctx_t *bctx = ctx->bsp_context; bctx->default_color[3] = bound (0, r_wateralpha->value, 1); QuatCopy (bctx->default_color, bctx->last_color); - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], bframe->cmdSet.a[QFV_bspTurb]); //FIXME need per frame matrices @@ -949,7 +951,7 @@ turb_begin (vulkan_ctx_t *ctx) bframe->imageInfo[3].imageView = bctx->default_skysheet->view; bframe->imageInfo[4].imageView = bctx->default_skybox->view; - bsp_begin_subpass (QFV_bspTurb, bctx->turb, ctx); + bsp_begin_subpass (QFV_bspTurb, bctx->turb, rFrame); } static void @@ -985,8 +987,9 @@ spin (mat4f_t mat, bspctx_t *bctx) } static void -sky_begin (vulkan_ctx_t *ctx) +sky_begin (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; bspctx_t *bctx = ctx->bsp_context; bctx->default_color[3] = 1; @@ -994,10 +997,9 @@ sky_begin (vulkan_ctx_t *ctx) spin (ctx->matrices.sky_3d, bctx); - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], bframe->cmdSet.a[QFV_bspSky]); //FIXME need per frame matrices @@ -1011,9 +1013,9 @@ sky_begin (vulkan_ctx_t *ctx) bctx->default_skybox); if (bctx->skybox_tex) { - bsp_begin_subpass (QFV_bspSky, bctx->skybox, ctx); + bsp_begin_subpass (QFV_bspSky, bctx->skybox, rFrame); } else { - bsp_begin_subpass (QFV_bspSky, bctx->skysheet, ctx); + bsp_begin_subpass (QFV_bspSky, bctx->skysheet, rFrame); } } @@ -1068,8 +1070,9 @@ build_tex_elechain (vulktex_t *tex, bspctx_t *bctx, bspframe_t *bframe) } void -Vulkan_DrawWorld (vulkan_ctx_t *ctx) +Vulkan_DrawWorld (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; @@ -1098,7 +1101,7 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) } } - bsp_begin (ctx); + bsp_begin (rFrame); push_transform (identity, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspDepth]); @@ -1152,8 +1155,9 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx) } void -Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) +Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; @@ -1166,7 +1170,7 @@ Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) if (!bctx->waterchain) return; - turb_begin (ctx); + turb_begin (rFrame); push_transform (identity, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); fragconst_t frag_constants = { time: vr_data.realtime }; @@ -1214,8 +1218,9 @@ Vulkan_DrawWaterSurfaces (vulkan_ctx_t *ctx) } void -Vulkan_DrawSky (vulkan_ctx_t *ctx) +Vulkan_DrawSky (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; @@ -1228,7 +1233,7 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx) if (!bctx->sky_chain) return; - sky_begin (ctx); + sky_begin (rFrame); push_transform (identity, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); fragconst_t frag_constants = { time: vr_data.realtime }; diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 5b86ca457..4288ca462 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -48,27 +48,30 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/renderpass.h" #include "r_internal.h" #include "vid_vulkan.h" void -Vulkan_Compose_Draw (vulkan_ctx_t *ctx) +Vulkan_Compose_Draw (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + qfv_renderpass_t *renderpass = rFrame->renderpass; composectx_t *cctx = ctx->compose_context; __auto_type frame = &ctx->frames.a[ctx->curFrame]; composeframe_t *cframe = &cctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = cframe->cmd; - DARRAY_APPEND (&frame->cmdSets[QFV_passCompose], cmd); + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passCompose], cmd); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, QFV_passCompose, + renderpass->renderpass, QFV_passCompose, frame->framebuffer, 0, 0, 0, }; @@ -85,9 +88,9 @@ Vulkan_Compose_Draw (vulkan_ctx_t *ctx) cctx->pipeline); cframe->imageInfo[0].imageView - = ctx->attachment_views->a[QFV_attachOpaque]; + = renderpass->attachment_views->a[QFV_attachOpaque]; cframe->imageInfo[1].imageView - = ctx->attachment_views->a[QFV_attachTranslucent]; + = renderpass->attachment_views->a[QFV_attachTranslucent]; dfunc->vkUpdateDescriptorSets (device->dev, COMPOSE_IMAGE_INFOS, cframe->descriptors, 0, 0); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index af525bf2d..2d3dc4156 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -59,6 +59,7 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" #include "QF/ui/view.h" @@ -748,8 +749,9 @@ Vulkan_DrawReset (vulkan_ctx_t *ctx) } void -Vulkan_FlushText (vulkan_ctx_t *ctx) +Vulkan_FlushText (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; flush_draw_scrap (ctx); qfv_device_t *device = ctx->device; @@ -760,7 +762,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) VkCommandBuffer cmd = dframe->cmd; //FIXME which pass? - DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], cmd); + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], cmd); VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, @@ -772,7 +774,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx) dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, QFV_passTranslucent, + rFrame->renderpass->renderpass, QFV_passTranslucent, cframe->framebuffer, 0, 0, 0 }; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 7ceb025e5..de7bc409f 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -59,6 +59,7 @@ #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" +#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/staging.h" #include "compat.h" @@ -197,10 +198,12 @@ update_lights (vulkan_ctx_t *ctx) } void -Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) +Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + qfv_renderpass_t *renderpass = rFrame->renderpass; update_lights (ctx); @@ -209,12 +212,12 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = lframe->cmd; - DARRAY_APPEND (&cframe->cmdSets[QFV_passLighting], cmd); + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passLighting], cmd); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - ctx->renderpass, QFV_passLighting, + renderpass->renderpass, QFV_passLighting, cframe->framebuffer, 0, 0, 0, }; @@ -231,14 +234,16 @@ Vulkan_Lighting_Draw (vulkan_ctx_t *ctx) lctx->pipeline); lframe->bufferInfo[0].buffer = lframe->light_buffer; - lframe->attachInfo[0].imageView = ctx->attachment_views->a[QFV_attachDepth]; - lframe->attachInfo[1].imageView = ctx->attachment_views->a[QFV_attachColor]; + lframe->attachInfo[0].imageView + = renderpass->attachment_views->a[QFV_attachDepth]; + lframe->attachInfo[1].imageView + = renderpass->attachment_views->a[QFV_attachColor]; lframe->attachInfo[2].imageView - = ctx->attachment_views->a[QFV_attachEmission]; + = renderpass->attachment_views->a[QFV_attachEmission]; lframe->attachInfo[3].imageView - = ctx->attachment_views->a[QFV_attachNormal]; + = renderpass->attachment_views->a[QFV_attachNormal]; lframe->attachInfo[4].imageView - = ctx->attachment_views->a[QFV_attachPosition]; + = renderpass->attachment_views->a[QFV_attachPosition]; dfunc->vkUpdateDescriptorSets (device->dev, LIGHTING_DESCRIPTORS, lframe->descriptors, 0, 0); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index ea7ac5508..5cfa90094 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -54,6 +54,7 @@ #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_particles.h" //#include "QF/Vulkan/qf_textures.h" +#include "QF/Vulkan/renderpass.h" #include "mod_internal.h" #include "r_internal.h" @@ -103,7 +104,7 @@ setup_view (vulkan_ctx_t *ctx) } static void -Vulkan_RenderEntities (vulkan_ctx_t *ctx) +Vulkan_RenderEntities (qfv_renderframe_t *rFrame) { if (!r_drawentities->int_val) return; @@ -115,22 +116,22 @@ Vulkan_RenderEntities (vulkan_ctx_t *ctx) if (ent->renderer.model->type != mod_##type_name) \ continue; \ if (!begun) { \ - Vulkan_##Type##Begin (ctx); \ + Vulkan_##Type##Begin (rFrame); \ begun = 1; \ } \ /* hack the depth range to prevent view model */\ /* from poking into walls */\ if (ent == vr_data.view_model) { \ - Vulkan_AliasDepthRange (ctx, 0, 0.3); \ + Vulkan_AliasDepthRange (rFrame, 0, 0.3); \ } \ - Vulkan_Draw##Type (ent, ctx); \ + Vulkan_Draw##Type (ent, rFrame); \ /* unhack in case the view_model is not the last */\ if (ent == vr_data.view_model) { \ - Vulkan_AliasDepthRange (ctx, 0, 1); \ + Vulkan_AliasDepthRange (rFrame, 0, 1); \ } \ } \ if (begun) \ - Vulkan_##Type##End (ctx); \ + Vulkan_##Type##End (rFrame); \ } while (0) RE_LOOP (alias, Alias); @@ -152,8 +153,9 @@ Vulkan_DrawViewModel (vulkan_ctx_t *ctx) } void -Vulkan_RenderView (vulkan_ctx_t *ctx) +Vulkan_RenderView (qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; double t[9] = {}; int speeds = r_speeds->int_val; @@ -173,17 +175,17 @@ Vulkan_RenderView (vulkan_ctx_t *ctx) R_PushDlights (vec3_origin); if (speeds) t[3] = Sys_DoubleTime (); - Vulkan_DrawWorld (ctx); + Vulkan_DrawWorld (rFrame); if (speeds) t[4] = Sys_DoubleTime (); - Vulkan_DrawSky (ctx); + Vulkan_DrawSky (rFrame); if (speeds) t[5] = Sys_DoubleTime (); Vulkan_DrawViewModel (ctx); - Vulkan_RenderEntities (ctx); + Vulkan_RenderEntities (rFrame); if (speeds) t[6] = Sys_DoubleTime (); - Vulkan_DrawWaterSurfaces (ctx); + Vulkan_DrawWaterSurfaces (rFrame); if (speeds) t[7] = Sys_DoubleTime (); Vulkan_DrawParticles (ctx); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 01b991e9d..384cd8b16 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -66,6 +66,13 @@ #include "QF/Vulkan/staging.h" #include "QF/Vulkan/swapchain.h" +#include "QF/Vulkan/qf_alias.h" +#include "QF/Vulkan/qf_bsp.h" +#include "QF/Vulkan/qf_compose.h" +#include "QF/Vulkan/qf_draw.h" +#include "QF/Vulkan/qf_lighting.h" +#include "QF/Vulkan/qf_main.h" + #include "compat.h" #include "d_iface.h" #include "r_internal.h" @@ -212,7 +219,6 @@ void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { PL_Free (ctx->pipelineDef); - PL_Free (ctx->renderpassDef); if (ctx->capture) { QFV_DestroyCapture (ctx->capture); } @@ -297,14 +303,14 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) } static plitem_t * -qfv_load_renderpass (vulkan_ctx_t *ctx, const char *name) +qfv_load_renderpass (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name) { - if (!ctx->renderpassDef) { - ctx->renderpassDef = PL_GetPropertyList (quakeforge_renderpass, - &ctx->hashlinks); + if (!rp->renderpassDef) { + rp->renderpassDef = PL_GetPropertyList (quakeforge_renderpass, + &ctx->hashlinks); } - plitem_t *item = ctx->renderpassDef; + plitem_t *item = rp->renderpassDef; if (!item || !(item = PL_ObjectForKey (item, name))) { Sys_Printf ("error loading %s\n", name); } else { @@ -328,29 +334,121 @@ get_image_size (VkImage image, qfv_device_t *device) return size; } +static void +renderpass_draw (qfv_renderframe_t *rFrame) +{ + Vulkan_RenderView (rFrame); + Vulkan_FlushText (rFrame); + Vulkan_Lighting_Draw (rFrame); + Vulkan_Compose_Draw (rFrame); +} + +static void +create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +{ + qfv_device_t *device = ctx->device; + + plitem_t *item = qfv_load_renderpass (ctx, rp, "images"); + if (!item) { + return; + } + + __auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef); + rp->attachment_images = images; + size_t memSize = 0; + for (size_t i = 0; i < images->size; i++) { + memSize += get_image_size (images->a[i], device); + } + VkDeviceMemory mem; + mem = QFV_AllocImageMemory (device, images->a[0], + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + memSize, 0); + rp->attachmentMemory = mem; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + mem, "memory:framebuffers"); + size_t offset = 0; + for (size_t i = 0; i < images->size; i++) { + QFV_BindImageMemory (device, images->a[i], mem, offset); + offset += get_image_size (images->a[i], device); + } + + item = qfv_load_renderpass (ctx, rp, "imageViews"); + if (!item) { + return; + } + + __auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef); + rp->attachment_views = views; + + item = qfv_load_renderpass (ctx, rp, "framebuffer"); + if (!item) { + return; + } + + rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, + malloc); + for (size_t i = 0; i < rp->framebuffers->size; i++) { + ctx->swapImageIndex = i; // for $swapImageIndex in the config + rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, + rp->renderpassDef); + } +} + +static void +init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, + qfv_renderframe_t *rFrame) +{ + rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; + rFrame->vulkan_ctx = ctx; + rFrame->renderpass = rp; + rFrame->subpassCount = QFV_NumPasses; + rFrame->subpassCmdSets = malloc (QFV_NumPasses + * sizeof (qfv_cmdbufferset_t)); + for (int j = 0; j < QFV_NumPasses; j++) { + DARRAY_INIT (&rFrame->subpassCmdSets[j], 4); + } +} + void Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) { const char *name = "renderpass";//FIXME + plitem_t *item; + + qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); hashtab_t *tab = ctx->renderpasses; const char *path; path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); if (renderpass) { - ctx->renderpass = renderpass; - return; + rp->renderpass = renderpass; + } else { + item = qfv_load_renderpass (ctx, rp, name); + rp->renderpass = QFV_ParseRenderPass (ctx, item, rp->renderpassDef); + QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, + rp->renderpass, va (ctx->va_ctx, "renderpass:%s", + name)); } - plitem_t *item = qfv_load_renderpass (ctx, name); + DARRAY_INIT (&rp->frames, 4); + DARRAY_RESIZE (&rp->frames, ctx->frames.size); + for (size_t i = 0; i < rp->frames.size; i++) { + init_renderframe (ctx, rp, &rp->frames.a[i]); + } - ctx->renderpass = QFV_ParseRenderPass (ctx, item, ctx->renderpassDef); - QFV_AddHandle (tab, path, (uint64_t) ctx->renderpass); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, - ctx->renderpass, va (ctx->va_ctx, "renderpass:%s", - name)); - item = qfv_load_renderpass (ctx, "clearValues"); - QFV_ParseClearValues (ctx, item, ctx->renderpassDef); + create_attachements (ctx, rp); + + item = qfv_load_renderpass (ctx, rp, "clearValues"); + rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef); + + rp->draw = renderpass_draw; + + if (!ctx->renderPasses.grow) { + DARRAY_INIT (&ctx->renderPasses, 4); + } + DARRAY_APPEND (&ctx->renderPasses, rp); qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -390,13 +488,63 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) QFV_PacketSubmit (packet); } -void -Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) +static void +destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkDestroyRenderPass (device->dev, ctx->renderpass, 0); + for (size_t i = 0; i < rp->attachment_views->size; i++) { + dfunc->vkDestroyImageView (device->dev, rp->attachment_views->a[i], 0); + } + for (size_t i = 0; i < rp->attachment_images->size; i++) { + dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); + } + dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); +} + +static void +destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +{ + for (size_t i = 0; i < rp->frames.size; i++) { + __auto_type rFrame = &rp->frames.a[i]; + for (int j = 0; j < rFrame->subpassCount; j++) { + DARRAY_CLEAR (&rFrame->subpassCmdSets[j]); + } + free (rFrame->subpassCmdSets); + } +} + +static void +destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + for (size_t i = 0; i < rp->framebuffers->size; i++) { + dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0); + } + free (rp->framebuffers); +} + +void +Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + for (size_t i = 0; i < ctx->renderPasses.size; i++) { + __auto_type rp = ctx->renderPasses.a[i]; + + PL_Free (rp->renderpassDef); + + destroy_attachments (ctx, rp); + dfunc->vkDestroyRenderPass (device->dev, rp->renderpass, 0); + destroy_renderframes (ctx, rp); + destroy_framebuffers (ctx, rp); + + free (rp); + } dfunc->vkFreeMemory (device->dev, ctx->quad_memory, 0); dfunc->vkDestroyBuffer (device->dev, ctx->quad_buffer, 0); @@ -544,12 +692,6 @@ Vulkan_CreateFrames (vulkan_ctx_t *ctx) frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); frame->renderDoneSemaphore = QFV_CreateSemaphore (device); frame->cmdBuffer = cmdBuffers->a[i]; - - frame->cmdSetCount = QFV_NumPasses; - frame->cmdSets = malloc (QFV_NumPasses * sizeof (qfv_cmdbufferset_t)); - for (int j = 0; j < QFV_NumPasses; j++) { - DARRAY_INIT (&frame->cmdSets[j], 4); - } } } @@ -573,82 +715,7 @@ Vulkan_DestroyFrames (vulkan_ctx_t *ctx) df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0); df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); frame->framebuffer = 0; - for (int j = 0; j < frame->cmdSetCount; j++) { - DARRAY_CLEAR (&frame->cmdSets[j]); - } - free (frame->cmdSets); } DARRAY_CLEAR (&ctx->frames); - - for (size_t i = 0; i < ctx->framebuffers->size; i++) { - df->vkDestroyFramebuffer (dev, ctx->framebuffers->a[i], 0); - } - free (ctx->framebuffers); -} - -void -Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - - plitem_t *item = qfv_load_renderpass (ctx, "images"); - if (!item) { - return; - } - - __auto_type images = QFV_ParseImageSet (ctx, item, ctx->renderpassDef); - ctx->attachment_images = images; - size_t memSize = 0; - for (size_t i = 0; i < images->size; i++) { - memSize += get_image_size (images->a[i], device); - } - VkDeviceMemory mem; - mem = QFV_AllocImageMemory (device, images->a[0], - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - memSize, 0); - ctx->attachmentMemory = mem; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - mem, "memory:framebuffers"); - size_t offset = 0; - for (size_t i = 0; i < images->size; i++) { - QFV_BindImageMemory (device, images->a[i], mem, offset); - offset += get_image_size (images->a[i], device); - } - - item = qfv_load_renderpass (ctx, "imageViews"); - if (!item) { - return; - } - - __auto_type views = QFV_ParseImageViewSet (ctx, item, ctx->renderpassDef); - ctx->attachment_views = views; - - item = qfv_load_renderpass (ctx, "framebuffer"); - if (!item) { - return; - } - - ctx->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, - malloc); - for (size_t i = 0; i < ctx->framebuffers->size; i++) { - ctx->swapImageIndex = i; - ctx->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, - ctx->renderpassDef); - } -} - -void -Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - for (size_t i = 0; i < ctx->attachment_views->size; i++) { - dfunc->vkDestroyImageView (device->dev, ctx->attachment_views->a[i], 0); - } - for (size_t i = 0; i < ctx->attachment_images->size; i++) { - dfunc->vkDestroyImage (device->dev, ctx->attachment_images->a[i], 0); - } - dfunc->vkFreeMemory (device->dev, ctx->attachmentMemory, 0); } From 75d06c4f98180c80ec1c964076c87bb615acf29f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Dec 2021 22:40:02 +0900 Subject: [PATCH 1914/3664] [vulkan] Clean out some expired FIXME comments --- libs/video/renderer/vulkan/command.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index dbf856dcc..5843a15f3 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -48,10 +48,10 @@ #include "QF/va.h" #include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" -#include "QF/Vulkan/buffer.h"//FIXME should QFV_CmdPipelineBarrier be here? -#include "QF/Vulkan/image.h"//FIXME should QFV_CmdPipelineBarrier be here? -#include "QF/Vulkan/renderpass.h"//FIXME should QFV_CmdPipelineBarrier be here? -#include "QF/Vulkan/pipeline.h"//FIXME should QFV_CmdPipelineBarrier be here? +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/renderpass.h" +#include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" From c402275112651ef61f90e42f311339b778f8f4dd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Dec 2021 22:48:50 +0900 Subject: [PATCH 1915/3664] [vulkan] Add some more debug stack contexts --- libs/models/alias/vulkan_model_alias.c | 3 +++ libs/models/brush/vulkan_model_brush.c | 3 +++ libs/video/renderer/vulkan/vulkan_alias.c | 4 ++++ libs/video/renderer/vulkan/vulkan_bsp.c | 3 +++ libs/video/renderer/vulkan/vulkan_compose.c | 5 +++++ libs/video/renderer/vulkan/vulkan_draw.c | 4 ++++ libs/video/renderer/vulkan/vulkan_lighting.c | 4 ++++ 7 files changed, 26 insertions(+) diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index d001909a4..c29eb50e0 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -40,6 +40,7 @@ #include +#include "QF/cvar.h" #include "QF/va.h" #include "QF/modelgen.h" @@ -114,6 +115,7 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc, vulkan_ctx_t *ctx) { + qfvPushDebug (ctx, va (ctx->va_ctx, "alias.load_skin: %s", alias_ctx->mod->name)); qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliashdr_t *header = alias_ctx->header; @@ -219,6 +221,7 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, free (tskin); + qfvPopDebug (ctx); return skinpix + skinsize; } diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 5132daf13..f83869b0f 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -53,6 +53,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" #include "QF/Vulkan/staging.h" #include "qfalloca.h" @@ -163,6 +164,7 @@ copy_mips (qfv_packet_t *packet, texture_t *tx, qfv_tex_t *tex, static void load_textures (model_t *mod, vulkan_ctx_t *ctx) { + qfvPushDebug (ctx, va (ctx->va_ctx, "brush.load_textures: %s", mod->name)); qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; modelctx_t *mctx = mod->data; @@ -310,6 +312,7 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); free (barriers); + qfvPopDebug (ctx); } void diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 50aacfe4a..b842d85d4 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -60,6 +60,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" #include "QF/Vulkan/renderpass.h" #include "r_internal.h" @@ -304,6 +305,8 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + qfvPushDebug (ctx, "alias init"); + aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); ctx->alias_context = actx; @@ -365,6 +368,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) } } //free (sets); + qfvPopDebug (ctx); } void diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 7a009943f..11403a607 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1411,6 +1411,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + qfvPushDebug (ctx, "bsp init"); + bspctx_t *bctx = calloc (1, sizeof (bspctx_t)); ctx->bsp_context = bctx; @@ -1475,6 +1477,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bframe->descriptors[k].pImageInfo = &bframe->imageInfo[j]; } } + qfvPopDebug (ctx); } void diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 4288ca462..b188cae95 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -41,6 +41,7 @@ #include "qfalloca.h" +#include "QF/cvar.h" #include "QF/sys.h" #include "QF/Vulkan/qf_compose.h" @@ -48,6 +49,7 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" #include "QF/Vulkan/renderpass.h" #include "r_internal.h" @@ -126,6 +128,8 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + qfvPushDebug (ctx, "compose init"); + composectx_t *cctx = calloc (1, sizeof (composectx_t)); ctx->compose_context = cctx; @@ -167,6 +171,7 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) } } free (attach_set); + qfvPopDebug (ctx); } void diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 2d3dc4156..6a2d792ae 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -59,6 +59,7 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" #include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" @@ -353,6 +354,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + qfvPushDebug (ctx, "draw init"); + drawctx_t *dctx = calloc (1, sizeof (drawctx_t)); ctx->draw_context = dctx; @@ -435,6 +438,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) va (ctx->va_ctx, "cmd:draw:%zd", i)); } free (sets); + qfvPopDebug (ctx); } static inline void diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index de7bc409f..754ba242a 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -41,6 +41,7 @@ #include "qfalloca.h" +#include "QF/cvar.h" #include "QF/dstring.h" #include "QF/plist.h" #include "QF/progs.h" @@ -298,6 +299,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + qfvPushDebug (ctx, "lighting init"); + lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); ctx->lighting_context = lctx; @@ -418,6 +421,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) } free (attach_set); free (lights_set); + qfvPopDebug (ctx); } static void From a522464fc1f9b0044c0b4337c12aff72945eb731 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 09:18:57 +0900 Subject: [PATCH 1916/3664] [vkgen] Clean up an unnecessary function redirect I think it was mostly a holdover from early development, but it certainly makes sense to tuck the functionality away in Struct. --- libs/video/renderer/vulkan/vkgen/vkgen.r | 8 +------- libs/video/renderer/vulkan/vkgen/vkstruct.h | 2 +- libs/video/renderer/vulkan/vkgen/vkstruct.r | 5 +++-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index a186024b8..53b067b16 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -97,12 +97,6 @@ void print_type (qfot_type_t *type) } } -void struct_func (qfot_var_t *var) -{ - Type *type = [Type findType:var.type]; - [type addToQueue]; -} - void scan_types (void) { @@ -208,7 +202,7 @@ main(int argc, string *argv) if ([[parse getObjectForKey:[obj name]] string] == "skip") { continue; } - [obj forEachFieldCall:struct_func]; + [obj queueFieldTypes]; } [output_types addObject:obj]; } diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index 08b489592..445c9fc34 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -12,7 +12,7 @@ { string outname; } --(void) forEachFieldCall: (varfunc) func; +-(void) queueFieldTypes; -(qfot_var_t *)findField:(string) fieldName; -(void) writeTable; -(void) writeSymtabInit; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index cae352f0b..4d94ac8a5 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -27,12 +27,13 @@ } } --(void) forEachFieldCall: (varfunc) func +-(void) queueFieldTypes { qfot_struct_t *strct =&type.strct; for (int i = 0; i < strct.num_fields; i++) { - func (&strct.fields[i]); + Type *type = [Type findType:var.type]; + [type addToQueue]; } } From c73e4efcb75a05ecee6d7ab7c10b001db495cc04 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 09:29:38 +0900 Subject: [PATCH 1917/3664] [vkgen] Don't queue types for fields with custom parsers This ensures that unused parser blocks do not get emitted. In the testing of the upcoming support for fixed arrays, the blend color constants were being double emitted (both as custom and normal parser) due to being an array. gcc did not like that (what with all those warning flags). --- libs/video/renderer/vulkan/vkgen/vkfieldcustom.r | 5 +++++ libs/video/renderer/vulkan/vkgen/vkfielddef.h | 1 + libs/video/renderer/vulkan/vkgen/vkfielddef.r | 5 +++++ libs/video/renderer/vulkan/vkgen/vkstruct.r | 11 +++++++++++ 4 files changed, 22 insertions(+) diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r index 611cd7a9b..57d8fa54e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r @@ -65,4 +65,9 @@ return self; } +-(int) searchType +{ + return 0; +} + @end diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.h b/libs/video/renderer/vulkan/vkgen/vkfielddef.h index 0363a9e7f..747df01e6 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfielddef.h +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.h @@ -23,6 +23,7 @@ -writeField; -writeSymbol; -(string) name; +-(int) searchType; @end #endif//__renderer_vulkan_vkgen_vkfielddef_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.r b/libs/video/renderer/vulkan/vkgen/vkfielddef.r index 6aba1df05..b3c81096f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfielddef.r +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.r @@ -95,4 +95,9 @@ return field_name; } +-(int) searchType +{ + return 1; +} + @end diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 4d94ac8a5..500659bc0 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -30,8 +30,19 @@ -(void) queueFieldTypes { qfot_struct_t *strct =&type.strct; + PLItem *field_dict = [parse getObjectForKey:[self name]]; for (int i = 0; i < strct.num_fields; i++) { + qfot_var_t *var = &strct.fields[i]; + if (field_dict) { + PLItem *item = [field_dict getObjectForKey:var.name]; + FieldDef *def = [FieldDef fielddef:item + struct:self + field:var.name]; + if (![def searchType]) { + continue; + } + } Type *type = [Type findType:var.type]; [type addToQueue]; } From c8846f8007254c36417864a10f0c048361d5e43d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 10:04:58 +0900 Subject: [PATCH 1918/3664] [cexpr] Support array indexing The index is currently limited to ints, and is bounds checked (the array type has a size field indicating the number of elements). --- include/QF/cexpr.h | 8 ++++++++ libs/util/cexpr-vars.c | 23 +++++++++++++++++++++++ libs/util/test/test-cexpr.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 7fa1e04fc..149c320e2 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -87,6 +87,11 @@ typedef struct exprtab_s { struct hashtab_s *tab; } exprtab_t; +typedef struct exprarray_s { + exprtype_t *type; + unsigned size; +} exprarray_t; + typedef struct exprctx_s { exprval_t *result; exprtab_t *symtab; // directly accessible symbols @@ -111,6 +116,8 @@ exprval_t *cexpr_value_reference (exprtype_t *type, void *data, exprctx_t *ctx); int cexpr_eval_string (const char *str, exprctx_t *context); void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); +void cexpr_array_getelement (const exprval_t *a, const exprval_t *b, + exprval_t *c, exprctx_t *ctx); void cexpr_struct_getfield (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx); void cexpr_struct_pointer_getfield (const exprval_t *a, const exprval_t *b, @@ -137,6 +144,7 @@ extern exprtype_t cexpr_field; extern exprtype_t cexpr_function; extern exprtype_t cexpr_plitem; +extern binop_t cexpr_array_binops[]; extern binop_t cexpr_struct_binops[]; extern binop_t cexpr_struct_pointer_binops[]; diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c index 9b390b523..ec152a00e 100644 --- a/libs/util/cexpr-vars.c +++ b/libs/util/cexpr-vars.c @@ -37,6 +37,29 @@ #include "libs/util/cexpr-parse.h" +VISIBLE void +cexpr_array_getelement (const exprval_t *a, const exprval_t *b, exprval_t *c, + exprctx_t *ctx) +{ + __auto_type array = (exprarray_t *) a->type->data; + unsigned index = *(const unsigned *) b->value; + exprval_t *val = 0; + if (index < array->size) { + val = cmemalloc (ctx->memsuper, sizeof (exprval_t)); + val->type = array->type; + val->value = a->value + array->type->size * index; + } else { + cexpr_error (ctx, "index %d out of bounds for %s", index, + a->type->name); + } + *(exprval_t **) c->value = val; +} + +VISIBLE binop_t cexpr_array_binops[] = { + { '[', &cexpr_int, &cexpr_exprval, cexpr_array_getelement }, + {} +}; + VISIBLE void cexpr_struct_getfield (const exprval_t *a, const exprval_t *b, exprval_t *c, exprctx_t *ctx) diff --git a/libs/util/test/test-cexpr.c b/libs/util/test/test-cexpr.c index a87adaeff..ae1aaaa25 100644 --- a/libs/util/test/test-cexpr.c +++ b/libs/util/test/test-cexpr.c @@ -32,17 +32,31 @@ #include "QF/cmem.h" #include "QF/hash.h" #include "QF/mathlib.h" +#include "QF/va.h" #include "QF/simd/vec4f.h" int a = 5; int b = 6; int c; +int array[4] = { 9, 16, 25, 36 }; vec4f_t point = { 2, 3, 4, 1 }; // a point, so w = 1 vec4f_t normal = { 1, 2, 3, 0 }; // a vector, so w = 0 vec4f_t direction = { 4, 5, 6, 0 }; // a vector, so w = 0 vec4f_t plane; vec4f_t intercept; +exprarray_t int_array_4_data = { + &cexpr_int, + sizeof (array) / sizeof (array[0]), +}; +exprtype_t int_array_4 = { + "int[4]", + 4 * sizeof (int), + cexpr_array_binops, + 0, + &int_array_4_data, +}; + exprtype_t *vector_params[] = { &cexpr_vector, &cexpr_vector, @@ -117,6 +131,7 @@ exprfunc_t double_func[] = { exprsym_t symbols[] = { { "a", &cexpr_int, &a }, { "b", &cexpr_int, &b }, + { "array", &int_array_4, &array }, { "point", &cexpr_vector, &point }, { "normal", &cexpr_vector, &normal }, { "plane", &cexpr_vector, &plane }, @@ -147,6 +162,7 @@ exprctx_t context = { &test_result, &symtab }; #define TEST_BINOP(op) \ do { \ c = -4096; \ + context.result = &test_result; \ cexpr_eval_string ("a " #op " b", &context); \ printf ("c = a %s b -> %d = %d %s %d\n", #op, c, a, #op, b); \ if (c != (a op b)) { \ @@ -154,6 +170,17 @@ exprctx_t context = { &test_result, &symtab }; } \ } while (0) +#define TEST_ARRAY(ind) \ + do { \ + c = -4096; \ + context.result = &test_result; \ + cexpr_eval_string (va (0, "array[%d]", ind), &context); \ + printf ("c = array[%d] -> %d = %d\n", ind, c, array[ind]); \ + if (c != array[ind]) { \ + ret |= 1; \ + } \ + } while (0) + int main(int argc, const char **argv) { @@ -173,6 +200,11 @@ main(int argc, const char **argv) TEST_BINOP (^); TEST_BINOP (%); + TEST_ARRAY (0); + TEST_ARRAY (1); + TEST_ARRAY (2); + TEST_ARRAY (3); + context.result = &plane_result; cexpr_eval_string ("point.wzyx", &context); if (plane[0] != point[3] || plane[1] != point[2] From 8271860fb3ebc3a1fbde85012d5093190605eab8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 10:08:27 +0900 Subject: [PATCH 1919/3664] [vkgen] Add support for fixed arrays I want to support reading VkPhysicalDeviceLimits but it has some arrays. While I don't need to parse them (VkPhysicalDeviceLimits should be treated as read-only), I do need to be able to access them in property list expressions, and vkgen generates the cexpr type descriptors too. However, I will probably want to parse arrays some time in the future. --- .../video/renderer/vulkan/vkgen/Makemodule.am | 2 + .../renderer/vulkan/vkgen/vkfixedarray.h | 19 ++++ .../renderer/vulkan/vkgen/vkfixedarray.r | 92 +++++++++++++++++++ libs/video/renderer/vulkan/vkgen/vkgen.r | 14 +++ libs/video/renderer/vulkan/vkgen/vktype.r | 8 +- libs/video/renderer/vulkan/vkparse.c | 34 +++++++ 6 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkfixedarray.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfixedarray.r diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 7ff0081d2..39c73f081 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -14,6 +14,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.r \ libs/video/renderer/vulkan/vkgen/vkfieldstring.r \ libs/video/renderer/vulkan/vkgen/vkfieldtype.r \ + libs/video/renderer/vulkan/vkgen/vkfixedarray.r \ libs/video/renderer/vulkan/vkgen/vkgen.r \ libs/video/renderer/vulkan/vkgen/vkstruct.r \ libs/video/renderer/vulkan/vkgen/vktype.r \ @@ -55,6 +56,7 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.h \ libs/video/renderer/vulkan/vkgen/vkfieldstring.h \ libs/video/renderer/vulkan/vkgen/vkfieldtype.h \ + libs/video/renderer/vulkan/vkgen/vkfixedarray.h \ libs/video/renderer/vulkan/vkgen/vkgen.h \ libs/video/renderer/vulkan/vkgen/vkstruct.h \ libs/video/renderer/vulkan/vkgen/vktype.h diff --git a/libs/video/renderer/vulkan/vkgen/vkfixedarray.h b/libs/video/renderer/vulkan/vkgen/vkfixedarray.h new file mode 100644 index 000000000..649dc1308 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfixedarray.h @@ -0,0 +1,19 @@ +#ifndef __renderer_vulkan_vkgen_vkfixedarray_h +#define __renderer_vulkan_vkgen_vkfixedarray_h + +#include + +#include "vkgen.h" +#include "vktype.h" + +@interface FixedArray: Type +{ + Type *ele_type; + int ele_count; +} +-(void) writeTable; +-(void) writeSymtabInit; +-(void) writeSymtabEntry; +@end + +#endif//__renderer_vulkan_vkgen_vkfixedarray_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfixedarray.r b/libs/video/renderer/vulkan/vkgen/vkfixedarray.r new file mode 100644 index 000000000..36ad6f2f7 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfixedarray.r @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "vkfielddef.h" +#include "vkgen.h" +#include "vkfixedarray.h" + +@implementation FixedArray + +-initWithType: (qfot_type_t *) type +{ + if (!(self = [super initWithType: type])) { + return nil; + } + ele_type = [Type fromType: type.array.type]; + ele_count = type.array.size; + return self; +} + +-(string) name +{ + return sprintf ("%s_array_%d", [ele_type name], ele_count); +} + +-(void) addToQueue +{ + string name = [self name]; + if (!Hash_Find (processed_types, name)) { + //printf (" +%s\n", name); + Hash_Add (processed_types, (void *) name); + [queue addObject: self]; + } +} + +-(void) writeTable +{ + fprintf (output_file, "static parse_fixed_array_t parse_%s_data = {\n", + [self name]); + fprintf (output_file, "\t%s,\n", [ele_type parseType]); + fprintf (output_file, "\tsizeof (%s),\n", [ele_type name]); + fprintf (output_file, "\t%s,\n", [ele_type parseFunc]); + fprintf (output_file, "\t%d,\n", ele_count); + fprintf (output_file, "};\n"); + + fprintf (output_file, "exprarray_t %s_array = {\n", [self name]); + fprintf (output_file, "\t&%s,\n", [ele_type cexprType]); + fprintf (output_file, "\t%d,\n", ele_count); + fprintf (output_file, "};\n"); + fprintf (output_file, "exprtype_t %s_type = {\n", [self name]); + fprintf (output_file, "\t\"%s[%d]\",\n", [ele_type name], ele_count); + fprintf (output_file, "\t%d * sizeof (%s),\n", ele_count, [ele_type name]); + fprintf (output_file, "\tcexpr_array_binops,\n"); + fprintf (output_file, "\t0,\n"); + fprintf (output_file, "\t&%s_array,\n", [self name]); + fprintf (output_file, "};\n"); + fprintf (output_file, "\n"); + fprintf (header_file, "extern exprtype_t %s_type;\n", [self name]); +} + +-(void) writeSymtabInit +{ +} + +-(void) writeSymtabEntry +{ +} + +-(string) cexprType +{ + return [self name] + "_type"; +} + +-(string) parseType +{ + return "QFMultiType | (1 << QFString) | (1 << QFArray)"; +} + +-(string) parseFunc +{ + return "parse_fixed_array"; +} + +-(string) parseData +{ + return "&parse_" + [self name] + "_data";; +} +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 53b067b16..4bcd74ee4 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -9,6 +9,7 @@ #include "vkgen.h" #include "vkstruct.h" +#include "vkfixedarray.h" #include "vkenum.h" static AutoreleasePool *autorelease_pool; @@ -228,6 +229,19 @@ main(int argc, string *argv) [obj writeTable]; arp_end (); } + for (int i = [output_types count]; i-- > 0; ) { + id obj = [output_types objectAtIndex:i]; + if ([obj name] == "VkStructureType") { + continue; + } + if ([obj class] != [FixedArray class]) { + continue; + } + + arp_start (); + [obj writeTable]; + arp_end (); + } for (int i = [output_types count]; i-- > 0; ) { id obj = [output_types objectAtIndex:i]; if ([obj name] == "VkStructureType") { diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index 735e88339..f9776dcd4 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -2,6 +2,7 @@ #include "vkalias.h" #include "vkenum.h" +#include "vkfixedarray.h" #include "vkgen.h" #include "vkstruct.h" #include "vktype.h" @@ -50,9 +51,10 @@ static string get_type_key (void *type, void *unused) } switch (type.meta) { case ty_basic: - case ty_array: case ty_class: return [[Type alloc] initWithType: type]; + case ty_array: + return [[FixedArray alloc] initWithType: type]; case ty_enum: return [[Enum alloc] initWithType: type]; case ty_struct: @@ -62,7 +64,7 @@ static string get_type_key (void *type, void *unused) if (type.alias.name) { return [[Alias alloc] initWithType: type]; } - break; + return [Type fromType: type.alias.full_type]; } return nil; } @@ -107,7 +109,7 @@ static string get_type_key (void *type, void *unused) if (type.meta == ty_basic) { return "QFString"; } - return "no parse"; + return "no parse " + [self name]; } -(string) parseFunc diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 3a5431db4..504a7927d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -131,6 +131,13 @@ typedef struct parse_array_s { size_t size_offset; } parse_array_t; +typedef struct parse_fixed_array_s { + pltype_t type; + size_t stride; + plparser_t parser; + size_t size; +} parse_fixed_array_t; + typedef struct parse_data_s { size_t value_offset; size_t size_offset; @@ -323,6 +330,33 @@ parse_array (const plfield_t *field, const plitem_t *item, return 1; } +static int +parse_fixed_array (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + __auto_type array = (parse_fixed_array_t *) field->data; + + plelement_t element = { + array->type, + array->stride, + vkparse_alloc, + array->parser, + 0, + }; + plfield_t f = { 0, 0, 0, 0, &element }; + + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr; + + if (!PL_ParseArray (&f, item, &arr, messages, context)) { + return 0; + } + memset (data, 0, array->stride * array->size); + size_t size = min (array->size, arr->size); + memcpy (data, arr->a, array->stride * size); + return 1; +} + static int parse_string (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) From 4e8718980fe0bd766abbede1f8b4df757d3d2783 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 11:09:18 +0900 Subject: [PATCH 1920/3664] [cexpr] Remove some disabled code It looks like a munged commit, but I think I had decided that it was best to make cvar access explicit. --- libs/util/cexpr-lex.l | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index 77734c01c..5ae76d21b 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -306,8 +306,6 @@ parse_variable (const char *name, exprctx_t *context) __auto_type sym = (exprsym_t *) Hash_Find (symtab->tab, name); if (sym) { val = cexpr_value_reference (sym->type, sym->value, context); - } else { - //val = cexpr_cvar (name, context); } } if (!val) { From 049968b38e4f6da117cb831b0ef69c62cff1b8d7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 11:38:50 +0900 Subject: [PATCH 1921/3664] white space --- libs/util/cexpr-vars.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c index ec152a00e..afe8de859 100644 --- a/libs/util/cexpr-vars.c +++ b/libs/util/cexpr-vars.c @@ -157,13 +157,15 @@ cexpr_cvar_struct (exprctx_t *ctx) return cvars; } -static const char *expr_getkey (const void *s, void *unused) +static const char * +expr_getkey (const void *s, void *unused) { __auto_type sym = (exprsym_t *) s; return sym->name; } -void cexpr_init_symtab (exprtab_t *symtab, exprctx_t *ctx) +void +cexpr_init_symtab (exprtab_t *symtab, exprctx_t *ctx) { exprsym_t *sym; From 44102f26392f7d601869e9e18753ccac3ce97bfe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 12:28:46 +0900 Subject: [PATCH 1922/3664] [cexpr] Support chained contexts for scoping cexpr's symbol tables currently aren't readily extended, and dynamic scoping is usually a good thing anyway. The chain of contexts is walked when a symbol is not found in the current context's symtab, but minor efforts are made to avoid checking the same symtab twice (usually cased by cloning a context but not updating the symtab). --- include/QF/cexpr.h | 1 + libs/util/cexpr-lex.l | 35 +++++++++++++++++++++++++++++------ libs/util/test/test-cexpr.c | 8 +++++--- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 149c320e2..64df48873 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -93,6 +93,7 @@ typedef struct exprarray_s { } exprarray_t; typedef struct exprctx_s { + struct exprctx_s *parent; // for nested symol scopes exprval_t *result; exprtab_t *symtab; // directly accessible symbols exprtab_t *external_variables; // accessible via $id diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index 5ae76d21b..bb4387a10 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -286,12 +286,23 @@ static exprval_t *parse_double (const char *str, exprctx_t *context) static exprsym_t * parse_name (const char *name, exprctx_t *context) { - exprtab_t *symtab = context->symtab; + exprsym_t *sym = 0; + exprtab_t *prev_tab = 0; - if (!symtab) { - return 0; + for (exprctx_t *ctx = context; ctx && !sym; ctx = ctx->parent) { + exprtab_t *symtab = ctx->symtab; + if (!symtab) { + // scope barrier + break; + } + if (symtab == prev_tab) { + // already checked this symtab + continue; + } + prev_tab = symtab; + + sym = Hash_Find (symtab->tab, name); } - __auto_type sym = (exprsym_t *) Hash_Find (symtab->tab, name); return sym; } @@ -302,8 +313,20 @@ parse_variable (const char *name, exprctx_t *context) if (strcmp (name, "cvars") == 0) { val = cexpr_cvar_struct (context); } else { - exprtab_t *symtab = context->external_variables; - __auto_type sym = (exprsym_t *) Hash_Find (symtab->tab, name); + exprsym_t *sym = 0; + exprtab_t *prev_tab = 0; + for (exprctx_t *ctx = context; ctx && !sym; ctx = ctx->parent) { + exprtab_t *symtab = ctx->external_variables; + if (!symtab) { + // scope barrier + break; + } + if (symtab == prev_tab) { + // already checked this symtab + continue; + } + sym = Hash_Find (symtab->tab, name); + } if (sym) { val = cexpr_value_reference (sym->type, sym->value, context); } diff --git a/libs/util/test/test-cexpr.c b/libs/util/test/test-cexpr.c index ae1aaaa25..a8358e4b0 100644 --- a/libs/util/test/test-cexpr.c +++ b/libs/util/test/test-cexpr.c @@ -153,11 +153,13 @@ exprval_t dist_result = { &cexpr_float, (float *)&plane + 3 }; exprval_t intercept_result = { &cexpr_vector, &intercept }; exprtab_t symtab = { - symbols, - 0 + .symbols = symbols, }; -exprctx_t context = { &test_result, &symtab }; +exprctx_t context = { + .result = &test_result, + .symtab = &symtab +}; #define TEST_BINOP(op) \ do { \ From d2eb9282102a901ac791169a76d34e89797d491d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 14:04:45 +0900 Subject: [PATCH 1923/3664] [cexpr] Add a small library with some useful functions For now, just dot product, trig, and min/max/bound, but it works well as a proof of concept. The main goal was actually min. Only the list of symbols is provided, it is the user's responsibility to set up the symbol table and context. --- include/QF/cexpr.h | 2 + libs/util/Makemodule.am | 1 + libs/util/cexpr-lib.c | 258 ++++++++++++++++++++++++++++++++++++ libs/util/test/test-cexpr.c | 86 ++---------- 4 files changed, 269 insertions(+), 78 deletions(-) create mode 100644 libs/util/cexpr-lib.c diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 64df48873..75e7e8ae1 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -149,4 +149,6 @@ extern binop_t cexpr_array_binops[]; extern binop_t cexpr_struct_binops[]; extern binop_t cexpr_struct_pointer_binops[]; +extern exprsym_t cexpr_lib_symbols[]; + #endif//__QF_expr_h diff --git a/libs/util/Makemodule.am b/libs/util/Makemodule.am index 6e0dbbb23..fdf579f10 100644 --- a/libs/util/Makemodule.am +++ b/libs/util/Makemodule.am @@ -45,6 +45,7 @@ libs_util_libQFutil_la_SOURCES= \ libs/util/buildnum.c \ libs/util/cbuf.c \ libs/util/cexpr-lex.l \ + libs/util/cexpr-lib.c \ libs/util/cexpr-parse.y \ libs/util/cexpr-type.c \ libs/util/cexpr-vars.c \ diff --git a/libs/util/cexpr-lib.c b/libs/util/cexpr-lib.c new file mode 100644 index 000000000..5bbf3bca4 --- /dev/null +++ b/libs/util/cexpr-lib.c @@ -0,0 +1,258 @@ +/* + cexpr-lib.c + + Config expression parser. Or concurrent. + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include + +#include "QF/cexpr.h" +#include "QF/mathlib.h" +#include "QF/simd/vec4f.h" + +#include "libs/util/cexpr-parse.h" + +#define FUNC1(name, rtype, ptype, func) \ +static void \ +name (const exprval_t **params, exprval_t *result, exprctx_t *context) \ +{ \ + ptype *a = params[0]->value; \ + rtype *r = result->value; \ + *r = func (*a); \ +} + +#define FUNC2(name, rtype, ptype, func) \ +static void \ +name (const exprval_t **params, exprval_t *result, exprctx_t *context) \ +{ \ + /* parameters are reversed! */ \ + ptype *a = params[1]->value; \ + ptype *b = params[0]->value; \ + rtype *r = result->value; \ + *r = func (*a, *b); \ +} + +#define FUNC3(name, rtype, ptype, func) \ +static void \ +name (const exprval_t **params, exprval_t *result, exprctx_t *context) \ +{ \ + /* parameters are reversed! */ \ + ptype *a = params[2]->value; \ + ptype *b = params[1]->value; \ + ptype *c = params[0]->value; \ + rtype *r = result->value; \ + *r = func (*a, *b, *c); \ +} + +FUNC2 (vec4f_dot, vec4f_t, vec4f_t, dotf) + +FUNC1 (float_sin, float, float, sinf) +FUNC1 (double_sin, double, double, sin) + +FUNC1 (float_cos, float, float, cosf) +FUNC1 (double_cos, double, double, cos) + +FUNC1 (float_tan, float, float, tanf) +FUNC1 (double_tan, double, double, tan) + +FUNC1 (float_asin, float, float, asinf) +FUNC1 (double_asin, double, double, asin) + +FUNC1 (float_acos, float, float, acosf) +FUNC1 (double_acos, double, double, acos) + +FUNC1 (float_atan, float, float, atanf) +FUNC1 (double_atan, double, double, atan) + +FUNC2 (float_atan2, float, float, atan2f) +FUNC2 (double_atan2, float, float, atan2) + +FUNC1 (int_int_cast, int, int, (int)) +FUNC1 (int_float_cast, int, float, (int)) +FUNC1 (int_double_cast, int, double, (int)) + +FUNC1 (float_int_cast, float, int, (float)) +FUNC1 (float_float_cast, float, float, (float)) +FUNC1 (float_double_cast, float, double, (float)) + +FUNC1 (double_int_cast, double, int, (double)) +FUNC1 (double_float_cast, double, float, (double)) +FUNC1 (double_double_cast, double, double, (double)) + +FUNC2 (int_min, int, int, min) +FUNC2 (uint_min, unsigned, unsigned, min) +FUNC2 (float_min, float, float, min) +FUNC2 (double_min, double, double, min) + +FUNC2 (int_max, int, int, max) +FUNC2 (uint_max, unsigned, unsigned, max) +FUNC2 (float_max, float, float, max) +FUNC2 (double_max, double, double, max) + +FUNC3 (int_bound, int, int, bound) +FUNC3 (uint_bound, unsigned, unsigned, bound) +FUNC3 (float_bound, float, float, bound) +FUNC3 (double_bound, double, double, bound) + +static exprtype_t *vector_params[] = { + &cexpr_vector, + &cexpr_vector, +}; + +static exprtype_t *int_params[] = { + &cexpr_int, + &cexpr_int, + &cexpr_int, +}; + +static exprtype_t *uint_params[] = { + &cexpr_uint, + &cexpr_uint, + &cexpr_uint, +}; + +static exprtype_t *float_params[] = { + &cexpr_float, + &cexpr_float, + &cexpr_float, +}; + +static exprtype_t *double_params[] = { + &cexpr_double, + &cexpr_double, + &cexpr_double, +}; + +static exprfunc_t dot_func[] = { + { &cexpr_vector, 2, vector_params, vec4f_dot}, + {} +}; + +static exprfunc_t sin_func[] = { + { &cexpr_float, 1, float_params, float_sin }, + { &cexpr_double, 1, double_params, double_sin }, + {} +}; + +static exprfunc_t cos_func[] = { + { &cexpr_float, 1, float_params, float_cos }, + { &cexpr_double, 1, double_params, double_cos }, + {} +}; + +static exprfunc_t tan_func[] = { + { &cexpr_float, 1, float_params, float_tan }, + { &cexpr_double, 1, double_params, double_tan }, + {} +}; + +static exprfunc_t asin_func[] = { + { &cexpr_float, 1, float_params, float_asin }, + { &cexpr_double, 1, double_params, double_asin }, + {} +}; + +static exprfunc_t acos_func[] = { + { &cexpr_float, 1, float_params, float_acos }, + { &cexpr_double, 1, double_params, double_acos }, + {} +}; + +static exprfunc_t atan_func[] = { + { &cexpr_float, 1, float_params, float_atan }, + { &cexpr_double, 1, double_params, double_atan }, + {} +}; + +static exprfunc_t atan2_func[] = { + { &cexpr_float, 2, float_params, float_atan2 }, + { &cexpr_double, 2, double_params, double_atan2 }, + {} +}; + +static exprfunc_t int_func[] = { + { &cexpr_int, 1, int_params, int_int_cast }, + { &cexpr_int, 1, float_params, int_float_cast }, + { &cexpr_int, 1, double_params, int_double_cast }, + {} +}; + +static exprfunc_t float_func[] = { + { &cexpr_float, 1, int_params, float_int_cast }, + { &cexpr_float, 1, float_params, float_float_cast }, + { &cexpr_float, 1, double_params, float_double_cast }, + {} +}; + +static exprfunc_t double_func[] = { + { &cexpr_double, 1, int_params, double_int_cast }, + { &cexpr_double, 1, float_params, double_float_cast }, + { &cexpr_double, 1, double_params, double_double_cast }, + {} +}; + +static exprfunc_t min_func[] = { + { &cexpr_int, 2, int_params, int_min }, + { &cexpr_uint, 2, uint_params, uint_min }, + { &cexpr_float, 2, float_params, float_min }, + { &cexpr_double, 2, double_params, double_min }, + {} +}; + +static exprfunc_t max_func[] = { + { &cexpr_int, 2, int_params, int_max }, + { &cexpr_uint, 2, uint_params, uint_max }, + { &cexpr_float, 2, float_params, float_max }, + { &cexpr_double, 2, double_params, double_max }, + {} +}; + +static exprfunc_t bound_func[] = { + { &cexpr_int, 3, int_params, int_bound }, + { &cexpr_uint, 3, uint_params, uint_bound }, + { &cexpr_float, 3, float_params, float_bound }, + { &cexpr_double, 3, double_params, double_bound }, + {} +}; + +VISIBLE exprsym_t cexpr_lib_symbols[] = { + { "dot", &cexpr_function, dot_func }, + { "sin", &cexpr_function, sin_func }, + { "cos", &cexpr_function, cos_func }, + { "tan", &cexpr_function, tan_func }, + { "asin", &cexpr_function, asin_func }, + { "acos", &cexpr_function, acos_func }, + { "atan", &cexpr_function, atan_func }, + { "atan2", &cexpr_function, atan2_func }, + { "int", &cexpr_function, int_func }, + { "float", &cexpr_function, float_func }, + { "double", &cexpr_function, double_func }, + { "min", &cexpr_function, min_func }, + { "max", &cexpr_function, max_func }, + { "bound", &cexpr_function, bound_func }, + {} +}; diff --git a/libs/util/test/test-cexpr.c b/libs/util/test/test-cexpr.c index a8358e4b0..b67eea284 100644 --- a/libs/util/test/test-cexpr.c +++ b/libs/util/test/test-cexpr.c @@ -57,77 +57,6 @@ exprtype_t int_array_4 = { &int_array_4_data, }; -exprtype_t *vector_params[] = { - &cexpr_vector, - &cexpr_vector, -}; - -exprtype_t *int_params[] = { - &cexpr_int, - &cexpr_int, -}; - -exprtype_t *float_params[] = { - &cexpr_float, - &cexpr_float, -}; - -exprtype_t *double_params[] = { - &cexpr_double, - &cexpr_double, -}; - -static void -float_dot (const exprval_t **params, exprval_t *result, exprctx_t *context) -{ - // parameters are reversed! - vec4f_t *a = params[1]->value; - vec4f_t *b = params[0]->value; - vec4f_t *d = result->value; - *d = dotf (*a, *b); -} - -exprfunc_t dot_func[] = { - { &cexpr_vector, 2, vector_params, float_dot}, - {} -}; - -exprfunc_t sin_func[] = { - { &cexpr_float, 1, float_params }, - { &cexpr_double, 1, double_params }, - {} -}; - -exprfunc_t cos_func[] = { - { &cexpr_float, 1, float_params }, - { &cexpr_double, 1, double_params }, - {} -}; - -exprfunc_t atan2_func[] = { - { &cexpr_float, 2, float_params }, - { &cexpr_double, 2, double_params }, - {} -}; - -exprfunc_t int_func[] = { - { &cexpr_int, 1, float_params }, - { &cexpr_int, 1, double_params }, - {} -}; - -exprfunc_t float_func[] = { - { &cexpr_float, 1, int_params }, - { &cexpr_float, 1, double_params }, - {} -}; - -exprfunc_t double_func[] = { - { &cexpr_double, 1, float_params }, - { &cexpr_double, 1, double_params }, - {} -}; - exprsym_t symbols[] = { { "a", &cexpr_int, &a }, { "b", &cexpr_int, &b }, @@ -137,13 +66,6 @@ exprsym_t symbols[] = { { "plane", &cexpr_vector, &plane }, { "direction", &cexpr_vector, &direction }, { "intercept", &cexpr_vector, &intercept }, - { "dot", &cexpr_function, dot_func }, - { "sin", &cexpr_function, sin_func }, - { "cos", &cexpr_function, cos_func }, - { "atan2", &cexpr_function, atan2_func }, - { "float", &cexpr_function, float_func }, - { "double", &cexpr_function, double_func }, - { "int", &cexpr_function, int_func }, {} }; exprval_t test_result = { &cexpr_int, &c }; @@ -152,11 +74,18 @@ exprval_t plane_result = { &cexpr_vector, &plane }; exprval_t dist_result = { &cexpr_float, (float *)&plane + 3 }; exprval_t intercept_result = { &cexpr_vector, &intercept }; +exprtab_t root_symtab = { + .symbols = cexpr_lib_symbols, +}; exprtab_t symtab = { .symbols = symbols, }; +exprctx_t root_context = { + .symtab = &root_symtab +}; exprctx_t context = { + .parent = &root_context, .result = &test_result, .symtab = &symtab }; @@ -188,6 +117,7 @@ main(int argc, const char **argv) { int ret = 0; + cexpr_init_symtab (&root_symtab, &context); cexpr_init_symtab (&symtab, &context); context.memsuper = new_memsuper(); From cff23ac93cb0657bd9488abf739c8c3864563d4f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 14:09:57 +0900 Subject: [PATCH 1924/3664] [vulkan] Connect up the cexpr library This will make property list expressions easier to work with. The library is rather limited right now (trig, dot, min/max/bound) but even just min adds a lot of functionality. --- libs/video/renderer/vulkan/vkparse.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 504a7927d..93c0bc6a6 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -162,7 +162,6 @@ parse_basic (const plfield_t *field, const plitem_t *item, __auto_type etype = (exprtype_t *) field->data; exprctx_t ectx = *((parsectx_t *) context)->ectx; exprval_t result = { etype, data }; - ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); //Sys_MaskPrintf (SYS_vulkan_parse, "parse_basic: %s %zd %d %p %p: %s\n", @@ -193,7 +192,6 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, size_t val = 0; exprval_t result = { &cexpr_size_t, &val }; exprctx_t ectx = *((parsectx_t *) context)->ectx; - ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); //Sys_MaskPrintf (SYS_vulkan_parse, "parse_uint32_t: %s %zd %d %p %p: %s\n", @@ -227,6 +225,7 @@ parse_enum (const plfield_t *field, const plitem_t *item, __auto_type enm = (exprenum_t *) field->data; exprctx_t ectx = *((parsectx_t *)context)->ectx; exprval_t result = { enm->type, data }; + ectx.parent = ((parsectx_t *)context)->ectx; ectx.symtab = enm->symtab; ectx.result = &result; const char *valstr = PL_String (item); @@ -248,7 +247,6 @@ parse_reference (const plitem_t *item, const char *type, plitem_t *messages, exprctx_t ectx = *pctx->ectx; plitem_t *refItem = 0; exprval_t result = { &cexpr_plitem, &refItem }; - ectx.symtab = 0; ectx.result = &result; const char *name = PL_String (item); if (cexpr_eval_string (name, &ectx)) { @@ -397,7 +395,6 @@ parse_RGBA (const plitem_t *item, void **data, int ret = 1; exprctx_t ectx = *context->ectx; exprval_t result = { &cexpr_vector, data[0] }; - ectx.symtab = 0; ectx.result = &result; const char *valstr = PL_String (item); Sys_MaskPrintf (SYS_vulkan_parse, "parse_RGBA: %s\n", valstr); @@ -460,7 +457,6 @@ parse_VkRenderPass (const plitem_t *item, void **data, plitem_t *setItem = 0; exprval_t result = { &cexpr_plitem, &setItem }; - ectx.symtab = 0; ectx.result = &result; ret = !cexpr_eval_string (path, &ectx); if (ret) { @@ -521,7 +517,6 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, plitem_t *setItem = 0; exprval_t result = { &cexpr_plitem, &setItem }; - ectx.symtab = 0; ectx.result = &result; ret = !cexpr_eval_string (path, &ectx); if (ret) { @@ -557,7 +552,6 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, plitem_t *setItem = 0; exprval_t result = { &cexpr_plitem, &setItem }; - ectx.symtab = 0; ectx.result = &result; ret = !cexpr_eval_string (path, &ectx); if (ret) { @@ -592,7 +586,6 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, plitem_t *imageItem = 0; exprval_t result = { &cexpr_plitem, &imageItem }; - ectx.symtab = 0; ectx.result = &result; ret = !cexpr_eval_string (path, &ectx); if (ret) { @@ -634,7 +627,6 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, exprval_t *value = 0; exprval_t result = { &cexpr_exprval, &value }; - ectx.symtab = 0; ectx.result = &result; ret = !cexpr_eval_string (path, &ectx); @@ -859,6 +851,7 @@ parse_specialization_data (const plitem_t *item, void **data, data_array_t *da= 0; exprctx_t ectx = *((parsectx_t *)context)->ectx; exprval_t result = { &data_array_type, &da }; + ectx.parent = ((parsectx_t *)context)->ectx; ectx.symtab = &data_array_symtab; ectx.result = &result; const char *valstr = PL_String (item); @@ -1026,6 +1019,18 @@ enum_symtab_getkey (const void *e, void *unused) return enm->type->name; } +static exprtab_t root_symtab = { + .symbols = cexpr_lib_symbols, +}; +static void __attribute__((constructor)) +root_symtab_init (void) +{ + // using a null hashlinks here is safe because this function is run before + // main and thus before any possibility of threading. + exprctx_t root_context = { .symtab = &root_symtab }; + cexpr_init_symtab (&root_symtab, &root_context); +} + void QFV_InitParse (vulkan_ctx_t *ctx) { @@ -1062,7 +1067,7 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, plparser_t parser, void *object, plitem_t *properties) { plitem_t *messages = PL_NewArray (); - exprctx_t exprctx = {}; + exprctx_t exprctx = { .symtab = &root_symtab }; parsectx_t parsectx = { &exprctx, ctx, properties }; exprsym_t var_syms[] = { {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, From f6cc138f48c3a9524e8132f8e2954a81b1c1f5f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Dec 2021 14:31:39 +0900 Subject: [PATCH 1925/3664] [vulkan] Provide access to VkPhysicalDeviceLimits Fixes the warning about parse_fixed_array not being used (oops, the problem with partial commits), but more importantly, gives access to things like maxDescriptorSetSamplers. --- libs/video/renderer/vulkan/vkparse.c | 2 ++ libs/video/renderer/vulkan/vkparse.plist | 1 + 2 files changed, 3 insertions(+) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 93c0bc6a6..0bb190b0a 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1074,6 +1074,8 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {"swapImageIndex", &cexpr_uint, &ctx->swapImageIndex}, + {"physDevLimits", &VkPhysicalDeviceLimits_type, + &ctx->device->physDev->properties.limits }, {QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties}, {} }; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 415e31d0a..6f5efa6d3 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -25,6 +25,7 @@ VkImageViewCreateInfo, VkFramebufferCreateInfo, VkClearValue, + VkPhysicalDeviceLimits, ); parse = { VkSubpassDescription = { From ee1c3e7db5a6fd0aa0ccb0502bb23bcc3368ca93 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Dec 2021 17:39:27 +0900 Subject: [PATCH 1926/3664] [cexpr] Clean up the macros a little --- libs/util/cexpr-lib.c | 174 ++++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 84 deletions(-) diff --git a/libs/util/cexpr-lib.c b/libs/util/cexpr-lib.c index 5bbf3bca4..fd54c4740 100644 --- a/libs/util/cexpr-lib.c +++ b/libs/util/cexpr-lib.c @@ -36,9 +36,17 @@ #include "libs/util/cexpr-parse.h" +#undef uint +#define uint unsigned +#undef cexpr_unsigned +#define cexpr_unsigned cexpr_uint + +#define FNAME(name, rtype, ptype) name##_##rtype##_##ptype + #define FUNC1(name, rtype, ptype, func) \ static void \ -name (const exprval_t **params, exprval_t *result, exprctx_t *context) \ +FNAME(name, rtype, ptype) (const exprval_t **params, exprval_t *result, \ + exprctx_t *context) \ { \ ptype *a = params[0]->value; \ rtype *r = result->value; \ @@ -47,7 +55,8 @@ name (const exprval_t **params, exprval_t *result, exprctx_t *context) \ #define FUNC2(name, rtype, ptype, func) \ static void \ -name (const exprval_t **params, exprval_t *result, exprctx_t *context) \ +FNAME(name, rtype, ptype) (const exprval_t **params, exprval_t *result, \ + exprctx_t *context) \ { \ /* parameters are reversed! */ \ ptype *a = params[1]->value; \ @@ -58,7 +67,8 @@ name (const exprval_t **params, exprval_t *result, exprctx_t *context) \ #define FUNC3(name, rtype, ptype, func) \ static void \ -name (const exprval_t **params, exprval_t *result, exprctx_t *context) \ +FNAME(name, rtype, ptype) (const exprval_t **params, exprval_t *result, \ + exprctx_t *context) \ { \ /* parameters are reversed! */ \ ptype *a = params[2]->value; \ @@ -68,55 +78,56 @@ name (const exprval_t **params, exprval_t *result, exprctx_t *context) \ *r = func (*a, *b, *c); \ } -FUNC2 (vec4f_dot, vec4f_t, vec4f_t, dotf) +#undef vector +#define vector vec4f_t -FUNC1 (float_sin, float, float, sinf) -FUNC1 (double_sin, double, double, sin) +FUNC2 (dot, vector, vector, dotf) -FUNC1 (float_cos, float, float, cosf) -FUNC1 (double_cos, double, double, cos) +FUNC1 (sin, float, float, sinf) +FUNC1 (sin, double, double, sin) -FUNC1 (float_tan, float, float, tanf) -FUNC1 (double_tan, double, double, tan) +FUNC1 (cos, float, float, cosf) +FUNC1 (cos, double, double, cos) -FUNC1 (float_asin, float, float, asinf) -FUNC1 (double_asin, double, double, asin) +FUNC1 (tan, float, float, tanf) +FUNC1 (tan, double, double, tan) -FUNC1 (float_acos, float, float, acosf) -FUNC1 (double_acos, double, double, acos) +FUNC1 (asin, float, float, asinf) +FUNC1 (asin, double, double, asin) -FUNC1 (float_atan, float, float, atanf) -FUNC1 (double_atan, double, double, atan) +FUNC1 (acos, float, float, acosf) +FUNC1 (acos, double, double, acos) -FUNC2 (float_atan2, float, float, atan2f) -FUNC2 (double_atan2, float, float, atan2) +FUNC1 (atan, float, float, atanf) +FUNC1 (atan, double, double, atan) -FUNC1 (int_int_cast, int, int, (int)) -FUNC1 (int_float_cast, int, float, (int)) -FUNC1 (int_double_cast, int, double, (int)) +FUNC2 (atan2, float, float, atan2f) +FUNC2 (atan2, double, double, atan2) -FUNC1 (float_int_cast, float, int, (float)) -FUNC1 (float_float_cast, float, float, (float)) -FUNC1 (float_double_cast, float, double, (float)) +#define CAST_TO(rtype) \ +FUNC1 (cast, rtype, int, (rtype)) \ +FUNC1 (cast, rtype, float, (rtype)) \ +FUNC1 (cast, rtype, double, (rtype)) -FUNC1 (double_int_cast, double, int, (double)) -FUNC1 (double_float_cast, double, float, (double)) -FUNC1 (double_double_cast, double, double, (double)) +CAST_TO (int) +CAST_TO (float) +CAST_TO (double) +#undef CAST_TO -FUNC2 (int_min, int, int, min) -FUNC2 (uint_min, unsigned, unsigned, min) -FUNC2 (float_min, float, float, min) -FUNC2 (double_min, double, double, min) +FUNC2 (min, int, int, min) +FUNC2 (min, uint, uint, min) +FUNC2 (min, float, float, min) +FUNC2 (min, double, double, min) -FUNC2 (int_max, int, int, max) -FUNC2 (uint_max, unsigned, unsigned, max) -FUNC2 (float_max, float, float, max) -FUNC2 (double_max, double, double, max) +FUNC2 (max, int, int, max) +FUNC2 (max, uint, uint, max) +FUNC2 (max, float, float, max) +FUNC2 (max, double, double, max) -FUNC3 (int_bound, int, int, bound) -FUNC3 (uint_bound, unsigned, unsigned, bound) -FUNC3 (float_bound, float, float, bound) -FUNC3 (double_bound, double, double, bound) +FUNC3 (bound, int, int, bound) +FUNC3 (bound, uint, uint, bound) +FUNC3 (bound, float, float, bound) +FUNC3 (bound, double, double, bound) static exprtype_t *vector_params[] = { &cexpr_vector, @@ -147,95 +158,90 @@ static exprtype_t *double_params[] = { &cexpr_double, }; +#define FUNC(name, rtype, n, ptype) \ + { &cexpr_##rtype, n, ptype##_params, FNAME(name, rtype, ptype) } + static exprfunc_t dot_func[] = { - { &cexpr_vector, 2, vector_params, vec4f_dot}, + FUNC (dot, vector, 2, vector), {} }; static exprfunc_t sin_func[] = { - { &cexpr_float, 1, float_params, float_sin }, - { &cexpr_double, 1, double_params, double_sin }, + FUNC (sin, float, 1, float), + FUNC (sin, double, 1, double), {} }; static exprfunc_t cos_func[] = { - { &cexpr_float, 1, float_params, float_cos }, - { &cexpr_double, 1, double_params, double_cos }, + FUNC (cos, float, 1, float), + FUNC (cos, double, 1, double), {} }; static exprfunc_t tan_func[] = { - { &cexpr_float, 1, float_params, float_tan }, - { &cexpr_double, 1, double_params, double_tan }, + FUNC (tan, float, 1, float), + FUNC (tan, double, 1, double), {} }; static exprfunc_t asin_func[] = { - { &cexpr_float, 1, float_params, float_asin }, - { &cexpr_double, 1, double_params, double_asin }, + FUNC (asin, float, 1, float), + FUNC (asin, double, 1, double), {} }; static exprfunc_t acos_func[] = { - { &cexpr_float, 1, float_params, float_acos }, - { &cexpr_double, 1, double_params, double_acos }, + FUNC (acos, float, 1, float), + FUNC (acos, double, 1, double), {} }; static exprfunc_t atan_func[] = { - { &cexpr_float, 1, float_params, float_atan }, - { &cexpr_double, 1, double_params, double_atan }, + FUNC (atan, float, 1, float), + FUNC (atan, double, 1, double), {} }; static exprfunc_t atan2_func[] = { - { &cexpr_float, 2, float_params, float_atan2 }, - { &cexpr_double, 2, double_params, double_atan2 }, + FUNC (atan2, float, 2, float), + FUNC (atan2, double, 2, double), {} }; -static exprfunc_t int_func[] = { - { &cexpr_int, 1, int_params, int_int_cast }, - { &cexpr_int, 1, float_params, int_float_cast }, - { &cexpr_int, 1, double_params, int_double_cast }, - {} +#define CAST_TO(rtype) \ +static exprfunc_t rtype##_func[] = { \ + FUNC (cast, rtype, 1, int), \ + FUNC (cast, rtype, 1, float), \ + FUNC (cast, rtype, 1, double), \ + {} \ }; -static exprfunc_t float_func[] = { - { &cexpr_float, 1, int_params, float_int_cast }, - { &cexpr_float, 1, float_params, float_float_cast }, - { &cexpr_float, 1, double_params, float_double_cast }, - {} -}; - -static exprfunc_t double_func[] = { - { &cexpr_double, 1, int_params, double_int_cast }, - { &cexpr_double, 1, float_params, double_float_cast }, - { &cexpr_double, 1, double_params, double_double_cast }, - {} -}; +CAST_TO (int) +CAST_TO (float) +CAST_TO (double) +#undef CAST_TO static exprfunc_t min_func[] = { - { &cexpr_int, 2, int_params, int_min }, - { &cexpr_uint, 2, uint_params, uint_min }, - { &cexpr_float, 2, float_params, float_min }, - { &cexpr_double, 2, double_params, double_min }, + FUNC (min, int, 2, int), + FUNC (min, uint, 2, uint), + FUNC (min, float, 2, float), + FUNC (min, double, 2, double), {} }; static exprfunc_t max_func[] = { - { &cexpr_int, 2, int_params, int_max }, - { &cexpr_uint, 2, uint_params, uint_max }, - { &cexpr_float, 2, float_params, float_max }, - { &cexpr_double, 2, double_params, double_max }, + FUNC (max, int, 2, int), + FUNC (max, uint, 2, uint), + FUNC (max, float, 2, float), + FUNC (max, double, 2, double), {} }; static exprfunc_t bound_func[] = { - { &cexpr_int, 3, int_params, int_bound }, - { &cexpr_uint, 3, uint_params, uint_bound }, - { &cexpr_float, 3, float_params, float_bound }, - { &cexpr_double, 3, double_params, double_bound }, + FUNC (bound, int, 3, int), + FUNC (bound, uint, 3, uint), + FUNC (bound, float, 3, float), + FUNC (bound, double, 3, double), {} }; From e7b067d6a9b75d883ff4e5d7d7312381a2263f94 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Dec 2021 17:40:55 +0900 Subject: [PATCH 1927/3664] [cexpr] Add some functions for size_t and uint Casting for size_t and uint, and min/max/bound for size_t. --- libs/util/cexpr-lib.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libs/util/cexpr-lib.c b/libs/util/cexpr-lib.c index fd54c4740..e30a16ece 100644 --- a/libs/util/cexpr-lib.c +++ b/libs/util/cexpr-lib.c @@ -106,26 +106,33 @@ FUNC2 (atan2, double, double, atan2) #define CAST_TO(rtype) \ FUNC1 (cast, rtype, int, (rtype)) \ +FUNC1 (cast, rtype, uint, (rtype)) \ +FUNC1 (cast, rtype, size_t, (rtype)) \ FUNC1 (cast, rtype, float, (rtype)) \ FUNC1 (cast, rtype, double, (rtype)) CAST_TO (int) +CAST_TO (uint) +CAST_TO (size_t) CAST_TO (float) CAST_TO (double) #undef CAST_TO FUNC2 (min, int, int, min) FUNC2 (min, uint, uint, min) +FUNC2 (min, size_t, size_t, min) FUNC2 (min, float, float, min) FUNC2 (min, double, double, min) FUNC2 (max, int, int, max) FUNC2 (max, uint, uint, max) +FUNC2 (max, size_t, size_t, max) FUNC2 (max, float, float, max) FUNC2 (max, double, double, max) FUNC3 (bound, int, int, bound) FUNC3 (bound, uint, uint, bound) +FUNC3 (bound, size_t, size_t, bound) FUNC3 (bound, float, float, bound) FUNC3 (bound, double, double, bound) @@ -146,6 +153,12 @@ static exprtype_t *uint_params[] = { &cexpr_uint, }; +static exprtype_t *size_t_params[] = { + &cexpr_size_t, + &cexpr_size_t, + &cexpr_size_t, +}; + static exprtype_t *float_params[] = { &cexpr_float, &cexpr_float, @@ -211,12 +224,16 @@ static exprfunc_t atan2_func[] = { #define CAST_TO(rtype) \ static exprfunc_t rtype##_func[] = { \ FUNC (cast, rtype, 1, int), \ + FUNC (cast, rtype, 1, uint), \ + FUNC (cast, rtype, 1, size_t), \ FUNC (cast, rtype, 1, float), \ FUNC (cast, rtype, 1, double), \ {} \ }; CAST_TO (int) +CAST_TO (uint) +CAST_TO (size_t) CAST_TO (float) CAST_TO (double) #undef CAST_TO @@ -224,6 +241,7 @@ CAST_TO (double) static exprfunc_t min_func[] = { FUNC (min, int, 2, int), FUNC (min, uint, 2, uint), + FUNC (min, size_t, 2, size_t), FUNC (min, float, 2, float), FUNC (min, double, 2, double), {} @@ -232,6 +250,7 @@ static exprfunc_t min_func[] = { static exprfunc_t max_func[] = { FUNC (max, int, 2, int), FUNC (max, uint, 2, uint), + FUNC (max, size_t, 2, size_t), FUNC (max, float, 2, float), FUNC (max, double, 2, double), {} @@ -240,6 +259,7 @@ static exprfunc_t max_func[] = { static exprfunc_t bound_func[] = { FUNC (bound, int, 3, int), FUNC (bound, uint, 3, uint), + FUNC (bound, size_t, 3, size_t), FUNC (bound, float, 3, float), FUNC (bound, double, 3, double), {} @@ -255,6 +275,8 @@ VISIBLE exprsym_t cexpr_lib_symbols[] = { { "atan", &cexpr_function, atan_func }, { "atan2", &cexpr_function, atan2_func }, { "int", &cexpr_function, int_func }, + { "uint", &cexpr_function, uint_func }, + { "size_t", &cexpr_function, size_t_func }, { "float", &cexpr_function, float_func }, { "double", &cexpr_function, double_func }, { "min", &cexpr_function, min_func }, From 062f616548f900d522a7aaf7ee8bdba4c23a8dae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Dec 2021 18:24:59 +0900 Subject: [PATCH 1928/3664] [cexpr] Add support for casting plitems This allows using references in expressions, eg: $frames.size * size_t($properties.limits.maxSamplers) As references remain property list items until actually evaluated. --- libs/util/cexpr-lib.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libs/util/cexpr-lib.c b/libs/util/cexpr-lib.c index e30a16ece..4fa920752 100644 --- a/libs/util/cexpr-lib.c +++ b/libs/util/cexpr-lib.c @@ -118,6 +118,14 @@ CAST_TO (float) CAST_TO (double) #undef CAST_TO +static void +cast_plitem (const exprval_t **params, exprval_t *result, exprctx_t *context) +{ + // first argument is ignored because cexpr_cast_plitem is meant to used + // in an operator list + cexpr_cast_plitem (0, params[0], result, context); +} + FUNC2 (min, int, int, min) FUNC2 (min, uint, uint, min) FUNC2 (min, size_t, size_t, min) @@ -171,6 +179,12 @@ static exprtype_t *double_params[] = { &cexpr_double, }; +static exprtype_t *plitem_params[] = { + &cexpr_plitem, + &cexpr_plitem, + &cexpr_plitem, +}; + #define FUNC(name, rtype, n, ptype) \ { &cexpr_##rtype, n, ptype##_params, FNAME(name, rtype, ptype) } @@ -228,6 +242,7 @@ static exprfunc_t rtype##_func[] = { \ FUNC (cast, rtype, 1, size_t), \ FUNC (cast, rtype, 1, float), \ FUNC (cast, rtype, 1, double), \ + { &cexpr_##rtype, 1, plitem_params, cast_plitem }, \ {} \ }; From a0c935e8bc4d85b6a4a3e4dcf2a2d22bab95f5dd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Dec 2021 14:21:10 +0900 Subject: [PATCH 1929/3664] [vulkan] Make lighting samplers configurable My VersaPro doesn't support more than 32 per-stage samplers (lavapipe). This is a small part of getting Vulkan to run on lavapipe and even in itself is rather incomplete. --- libs/video/renderer/vulkan/qfpipeline.plist | 16 ++++++++++++++-- libs/video/renderer/vulkan/shader/lighting.frag | 4 ++-- libs/video/renderer/vulkan/vulkan_lighting.c | 4 +++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 3bbbb7b46..c4b8433b2 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -1,4 +1,10 @@ { + limits = { + //FIXME this really needs to be an external variable as the C code + //needs to agree on the size, so it might as well set maxSamplers + //directly (and any other such variable) + maxSamplers = "min (256u, $physDevLimits.maxPerStageDescriptorSamplers)"; + }; samplers = { quakepic = { magFilter = nearest; @@ -120,7 +126,7 @@ bindings = ( { type = combined_image_sampler; - descriptorCount = "$frames.size * 256z"; + descriptorCount = "$frames.size * size_t($properties.limits.maxSamplers)"; }, ); }; @@ -308,7 +314,7 @@ { binding = 0; descriptorType = combined_image_sampler; - descriptorCount = 256; + descriptorCount = $properties.limits.maxSamplers; stageFlags = fragment; }, ); @@ -903,6 +909,12 @@ stage = fragment; name = main; module = $builtin/lighting.frag; + specializationInfo = { + mapEntries = ( + { size = 4; offset = 0; constantID = 0; }, + ); + data = "array($properties.limits.maxSamplers)"; + }; }, ); vertexInput = $properties.fsquad.vertexInput; diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 4f53c412c..9c8009d43 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -14,8 +14,6 @@ struct LightData { vec3 direction; float cone; }; -//XXX can't include :( be sure to keep up to date with qf_lighting.h -#define MaxLights 256 #define StyleMask 0x07f #define ModelMask 0x380 @@ -33,6 +31,8 @@ struct LightData { #define ST_CASCADE (2 << 10) // cascaded shadow maps #define ST_CUBE (3 << 10) // cubemap (omni, large spotlight) +layout (constant_id = 0) const int MaxLights = 256; + layout (set = 2, binding = 0) uniform sampler2DArrayShadow shadowCascade[MaxLights]; layout (set = 2, binding = 0) uniform sampler2DShadow shadowPlane[MaxLights]; layout (set = 2, binding = 0) uniform samplerCubeShadow shadowCube[MaxLights]; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 754ba242a..b3edfb640 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -416,7 +416,9 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->shadowWrite = base_image_write; lframe->shadowWrite.dstSet = shadow_set->a[i]; lframe->shadowWrite.dstBinding = 0; - lframe->shadowWrite.descriptorCount = MaxLights; + lframe->shadowWrite.descriptorCount + = min (MaxLights, + device->physDev->properties.limits.maxPerStageDescriptorSamplers); lframe->shadowWrite.pImageInfo = lframe->shadowInfo; } free (attach_set); From 3a742f59f7982a645b1d6a17944b9cffe593046a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Dec 2021 19:29:37 +0900 Subject: [PATCH 1930/3664] [vulkan] Copy array() parameters correctly I had forgotten that the parameters are in reverse order, and even if I had remembered, I forgot to reset offset before the second loop. Pre-decrementing offset takes care of both issues at once. --- libs/video/renderer/vulkan/vkparse.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 0bb190b0a..b9db14277 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -800,6 +800,8 @@ static void data_array (const exprval_t **params, exprval_t *result, exprctx_t *context) { size_t offset = 0; + // params are in reverse order, but this works for calculating the size + // of the buffer for (const exprval_t **param = params; *param; param++) { offset += (*param)->type->size; } @@ -807,8 +809,9 @@ data_array (const exprval_t **params, exprval_t *result, exprctx_t *context) cmemalloc, context->memsuper); for (const exprval_t **param = params; *param; param++) { size_t size = (*param)->type->size; + // pre-decrement offset because params are in reverse order + offset -= size; memcpy (data->a + offset, (*param)->value, size); - offset += size; } *(data_array_t **) result->value = data; } @@ -866,6 +869,10 @@ parse_specialization_data (const plitem_t *item, void **data, } else { *size_ptr = da->size; *data_ptr = da->a; + //for (size_t i = 0; i < da->size; i++) { + // Sys_Printf (" %02x", da->a[i]); + //} + //Sys_Printf ("\n"); } return ret; } From ff6d6f6dd63e17e4e5a3bc176c6a4fb52eed7104 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Dec 2021 20:38:06 +0900 Subject: [PATCH 1931/3664] [vulkan] Rework shaders and pipelines for bindless textures Smashing everything in the process :P (need to work on the C side). However, while bindless is supposedly good for performance, the biggest gain this will bring is portability: the texture counts are automatically limited to what the hardware can handle, and the reliance on push descriptors is removed (though they were nice and did help get things up and running). --- libs/video/renderer/vulkan/qfpipeline.plist | 49 +++++---- .../renderer/vulkan/shader/alias_gbuf.frag | 15 ++- .../renderer/vulkan/shader/bsp_gbuf.frag | 100 ++---------------- .../video/renderer/vulkan/shader/bsp_sky.frag | 32 +++--- .../renderer/vulkan/shader/bsp_turb.frag | 8 +- .../video/renderer/vulkan/vulkan_vid_common.c | 1 - 6 files changed, 74 insertions(+), 131 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index c4b8433b2..9ef5661a8 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -4,6 +4,7 @@ //needs to agree on the size, so it might as well set maxSamplers //directly (and any other such variable) maxSamplers = "min (256u, $physDevLimits.maxPerStageDescriptorSamplers)"; + maxImages = "min (256u, $physDevLimits.maxPerStageDescriptorSampledImages - 8u)"; }; samplers = { quakepic = { @@ -159,7 +160,6 @@ ); }; quakebsp_set = { - flags = push_descriptor; bindings = ( { binding = 0; @@ -200,7 +200,6 @@ ); }; alias_set = { - flags = push_descriptor; bindings = ( { binding = 0; @@ -210,7 +209,13 @@ }, { binding = 1; - descriptorType = combined_image_sampler; + descriptorType = sampled_image; + descriptorCount = $properties.limits.maxImages; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = sampler; descriptorCount = 1; stageFlags = fragment; }, @@ -227,7 +232,6 @@ ); }; alias_textures = { - flags = push_descriptor; bindings = ( { binding = 0; @@ -367,7 +371,7 @@ { stageFlags = fragment; offset = 68; - size = "3 * 4 + 2 * 4 * 4"; + size = "3 * 4 + 2 * 4 * 4 + 4"; }, ); }; @@ -651,9 +655,10 @@ module = $builtin/alias_gbuf.frag; specializationInfo = { mapEntries = ( + // MaxTextures { size = 4; offset = 0; constantID = 0; }, ); - data = <00000008>; + data = "array(uint($properties.limits.maxImages))"; }; }, ); @@ -726,12 +731,10 @@ module = $builtin/bsp_gbuf.frag; specializationInfo = { mapEntries = ( + // MaxTextures { size = 4; offset = 0; constantID = 0; }, - { size = 4; offset = 0; constantID = 1; }, - { size = 4; offset = 0; constantID = 2; }, - { size = 4; offset = 0; constantID = 3; }, ); - data = <00000000ffffffff>; + data = "array(uint($properties.limits.maxImages))"; }; }, ); @@ -770,10 +773,14 @@ module = $builtin/bsp_sky.frag; specializationInfo = { mapEntries = ( - { size = 4; offset = 0; constantID = 1; }, - { size = 4; offset = 4; constantID = 0; }, + // MaxTextures + { size = 4; offset = 8; constantID = 0; }, + // doSkyBox + { size = 4; offset = 4; constantID = 1; }, + // doSkySheet + { size = 4; offset = 0; constantID = 2; }, ); - data = <00000000ffffffff>; + data = "array(0, 1, uint($properties.limits.maxImages))"; }; }, ); @@ -807,10 +814,14 @@ module = $builtin/bsp_sky.frag; specializationInfo = { mapEntries = ( - { size = 4; offset = 0; constantID = 0; }, - { size = 4; offset = 4; constantID = 1; }, + // MaxTextures + { size = 4; offset = 8; constantID = 0; }, + // doSkyBox + { size = 4; offset = 0; constantID = 1; }, + // doSkySheet + { size = 4; offset = 4; constantID = 2; }, ); - data = <00000000ffffffff>; + data = "array(0, 1, uint($properties.limits.maxImages))"; }; }, ); @@ -844,10 +855,10 @@ module = $builtin/bsp_turb.frag; specializationInfo = { mapEntries = ( + // MaxTextures { size = 4; offset = 0; constantID = 0; }, - { size = 4; offset = 4; constantID = 1; }, ); - data = <00000000ffffffff>; + data = "array(uint($properties.limits.maxImages))"; }; }, ); @@ -913,7 +924,7 @@ mapEntries = ( { size = 4; offset = 0; constantID = 0; }, ); - data = "array($properties.limits.maxSamplers)"; + data = "array(uint($properties.limits.maxSamplers))"; }; }, ); diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index c9cc81db0..b09997caf 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -1,5 +1,9 @@ #version 450 -layout (set = 0, binding = 1) uniform sampler2DArray Skin; + +layout (constant_id = 0) const int MaxTextures = 256; + +layout (set = 0, binding = 1) uniform texture2DArray skins[MaxTextures]; +layout (set = 0, binding = 2) uniform sampler samp; layout (push_constant) uniform PushConstants { layout (offset = 68) @@ -8,6 +12,7 @@ layout (push_constant) uniform PushConstants { uint colorB; vec4 fog; vec4 color; + int texind; }; layout (location = 0) in vec2 st; @@ -26,10 +31,10 @@ main (void) vec4 e; int i; vec3 light = vec3 (0); - c = texture (Skin, vec3 (st, 0)) * unpackUnorm4x8(base_color); - c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA); - c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB); - e = texture (Skin, vec3 (st, 3)); + c = texture (sampler2DArray(skins[texind], samp), vec3 (st, 0)) * unpackUnorm4x8(base_color); + c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 1)) * unpackUnorm4x8(colorA); + c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 2)) * unpackUnorm4x8(colorB); + e = texture (sampler2DArray(skins[texind], samp), vec3 (st, 3)); frag_color = c; frag_emission = e; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index c00c0d72d..2be3743ca 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -1,15 +1,18 @@ #version 450 +layout (constant_id = 0) const int MaxTextures = 256; + +layout (set = 0, binding = 1) uniform texture2DArray textures[MaxTextures]; +layout (set = 0, binding = 2) uniform sampler samp; + layout (set = 0, binding = 1) uniform sampler2D Texture; layout (set = 0, binding = 2) uniform sampler2D GlowMap; -layout (set = 0, binding = 3) uniform sampler2D LightMap; -layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; -layout (set = 0, binding = 5) uniform samplerCube SkyCube; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; + int texind; }; layout (location = 0) in vec4 tl_st; @@ -22,26 +25,6 @@ layout (location = 1) out vec4 frag_emission; layout (location = 2) out vec4 frag_normal; layout (location = 3) out vec4 frag_position; -layout (constant_id = 0) const bool doWarp = false; -layout (constant_id = 1) const bool doLight = true; -layout (constant_id = 2) const bool doSkyCube = false; -layout (constant_id = 3) const bool doSkySheet = false; - -const float PI = 3.14159265; -const float SPEED = 20.0; -const float CYCLE = 128.0; -const float FACTOR = PI * 2.0 / CYCLE; -const vec2 BIAS = vec2 (1.0, 1.0); -const float SCALE = 8.0; - -vec2 -warp_st (vec2 st, float time) -{ - vec2 angle = st.ts * CYCLE / 2.0; - vec2 phase = vec2 (time, time) * SPEED; - return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; -} - vec4 fogBlend (vec4 color) { @@ -52,79 +35,16 @@ fogBlend (vec4 color) return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); } -vec4 -sky_sheet (vec3 dir, float time) -{ - float len; - vec2 flow = vec2 (1.0, 1.0); - vec2 base; - vec3 st1, st2; - vec4 c1, c2, c; - - dir.z *= 3.0; - len = dot (dir, dir); - len = SCALE * inversesqrt (len); - base = dir.yx * vec2(1.0, -1.0) * len; - - st1 = vec3 (base + flow * time / 8.0, 0); - st2 = vec3 (base + flow * time / 16.0, 1); - - c1 = texture (SkySheet, st1); - c2 = texture (SkySheet, st2); - - c = vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); - - return c; -} - -vec4 -sky_cube (vec3 dir, float time) -{ - // NOTE: quake's world is right-handed with Z up and X forward, but - // Vulkan's cube maps are left-handed with Y up and Z forward. The - // rotation to X foward is done by the Sky matrix so all that's left - // to do here is swizzle the Y and Z coordinates - return texture (SkyCube, dir.xzy); -} - -vec4 -sky_color (vec3 dir, float time) -{ - if (!doSkySheet) { - return vec4 (1, 0, 1, 1); - //return sky_cube (dir, time); - } if (!doSkyCube) { - return sky_sheet (dir, time); - } else { - // can see through the sheet (may look funny when looking down) - // maybe have 4 sheet layers instead of 2? - vec4 c1 = sky_sheet (dir, time); - vec4 c2 = sky_cube (dir, time); - return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); - return vec4 (1, 0, 1, 1); - } -} - void main (void) { vec4 c = vec4 (0); vec4 e; - vec2 t_st = tl_st.xy; - vec2 l_st = tl_st.zw; + vec3 t_st = vec3 (tl_st.xy, 0); + vec3 l_st = vec3 (tl_st.zw, 1); - if (doWarp) { - t_st = warp_st (t_st, time); - } - if (doSkyCube || doSkySheet) { - e = sky_color (direction, time); - } else { - c = texture (Texture, t_st); - if (doLight) { - c *= vec4 (texture (LightMap, l_st).xyz, 1); - } - e = texture (GlowMap, t_st); - } + c = texture (sampler2DArray (textures[texind], samp), t_st); + e = texture (sampler2DArray (textures[texind], samp), t_st); frag_color = c;//fogBlend (c); frag_emission = e; frag_normal = vec4 (normal, 0); diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index 56c75a1ed..0c8dc7893 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -1,12 +1,19 @@ #version 450 -layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; -layout (set = 0, binding = 5) uniform samplerCube SkyCube; +layout (constant_id = 0) const int MaxTextures = 256; +layout (constant_id = 1) const bool doSkyBox = false; +layout (constant_id = 2) const bool doSkySheet = false; + +layout (set = 0, binding = 1) uniform texture2DArray sheet_tex[MaxTextures]; +layout (set = 0, binding = 1) uniform textureCube cube_tex[MaxTextures]; +layout (set = 0, binding = 2) uniform sampler samp; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; + int sheet_ind; + int cube_ind; }; layout (location = 0) in vec4 tl_st; @@ -14,9 +21,6 @@ layout (location = 1) in vec3 direction; layout (location = 0) out vec4 frag_color; -layout (constant_id = 0) const bool doSkyBox = false; -layout (constant_id = 1) const bool doSkySheet = false; - const float SCALE = 189.0 / 64.0; vec4 @@ -30,7 +34,7 @@ fogBlend (vec4 color) } vec4 -sky_sheet (vec3 dir, float time) +sky_sheet (vec3 dir, float time, texture2DArray tex) { float len; vec2 flow = vec2 (1.0, 1.0); @@ -46,8 +50,8 @@ sky_sheet (vec3 dir, float time) st1 = vec3 (base + flow * time / 8.0, 0); st2 = vec3 (base + flow * time / 16.0, 1); - c1 = texture (SkySheet, st1); - c2 = texture (SkySheet, st2); + c1 = texture (sampler2DArray(tex, samp), st1); + c2 = texture (sampler2DArray(tex, samp), st2); c = vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); @@ -55,7 +59,7 @@ sky_sheet (vec3 dir, float time) } vec4 -sky_box (vec3 dir, float time) +sky_box (vec3 dir, float time, textureCube tex) { // NOTE: quake's world is right-handed with Z up and X forward, but // Vulkan's cube maps are left-handed with Y up and Z forward. The @@ -63,21 +67,21 @@ sky_box (vec3 dir, float time) // to do here is swizzle the Y and Z coordinates dir = normalize(dir); //return vec4(dir.xyz, 1) * 0.5 + vec4(0.5); - return texture (SkyCube, dir.xzy); + return texture (samplerCube (tex, samp), dir.xzy); } vec4 sky_color (vec3 dir, float time) { if (!doSkySheet) { - return sky_box (dir, time); + return sky_box (dir, time, cube_tex[cube_ind]); } if (!doSkyBox) { - return sky_sheet (dir, time); + return sky_sheet (dir, time, sheet_tex[sheet_ind]); } else { // can see through the sheet (may look funny when looking down) // maybe have 4 sheet layers instead of 2? - vec4 c1 = sky_sheet (dir, time); - vec4 c2 = sky_box (dir, time); + vec4 c1 = sky_sheet (dir, time, sheet_tex[sheet_ind]); + vec4 c2 = sky_box (dir, time, cube_tex[cube_ind]); return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); return vec4 (1, 0, 1, 1); } diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index ab4b04c7d..9929e60e1 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -1,11 +1,15 @@ #version 450 -layout (set = 0, binding = 1) uniform sampler2D Texture; +layout (constant_id = 0) const int MaxTextures = 256; + +layout (set = 0, binding = 1) uniform texture2D textures[MaxTextures]; +layout (set = 0, binding = 2) uniform sampler samp; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; + int texind; }; layout (location = 0) in vec4 tl_st; @@ -47,6 +51,6 @@ main (void) vec2 l_st = tl_st.zw; t_st = warp_st (t_st, time); - c = texture (Texture, t_st); + c = texture (sampler2D (textures[texind], samp), t_st); frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 384cd8b16..8bea24b51 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -190,7 +190,6 @@ static const char *instance_extensions[] = { static const char *device_extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, - VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, 0, }; From ea4ac894d8dd5a41049d16a92135af6ea2897d5d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 7 Dec 2021 12:51:33 +0900 Subject: [PATCH 1932/3664] [model] Swap fullbright/top/bottom color func params This makes them semantically compatible with memcpy. --- include/mod_internal.h | 12 ++++++------ libs/models/alias/vulkan_model_alias.c | 6 +++--- libs/models/brush/vulkan_model_brush.c | 2 +- libs/models/fullbright.c | 7 ++++--- libs/models/gl_model_fullbright.c | 2 +- libs/models/gl_skin.c | 2 +- libs/models/skin.c | 14 ++++++++------ 7 files changed, 24 insertions(+), 21 deletions(-) diff --git a/include/mod_internal.h b/include/mod_internal.h index d498ee9ce..b82de630b 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -22,8 +22,8 @@ typedef struct mod_alias_ctx_s { } mod_alias_ctx_t; -int Mod_CalcFullbright (const byte *in, byte *out, int pixels); -void Mod_ClearFullbright (const byte *in, byte *out, int pixels); +int Mod_CalcFullbright (byte *out, const byte *in, size_t pixels); +int Mod_ClearFullbright (byte *out, const byte *in, size_t pixels); void Mod_FloodFillSkin (byte *skin, int skinwidth, int skinheight); //FIXME gl specific. rewrite to use above int Mod_Fullbright (byte * skin, int width, int height, const char *name); @@ -97,10 +97,10 @@ void Skin_Init (void); skin_t *Skin_SetColormap (skin_t *skin, int cmap); skin_t *Skin_SetSkin (skin_t *skin, int cmap, const char *skinname); void Skin_SetTranslation (int cmap, int top, int bottom); -int Skin_CalcTopColors (const byte *in, byte *out, int pixels); -int Skin_CalcBottomColors (const byte *in, byte *out, int pixels); -void Skin_ClearTopColors (const byte *in, byte *out, int pixels); -void Skin_ClearBottomColors (const byte *in, byte *out, int pixels); +int Skin_CalcTopColors (byte *out, const byte *in, size_t pixels); +int Skin_CalcBottomColors (byte *out, const byte *in, size_t pixels); +int Skin_ClearTopColors (byte *out, const byte *in, size_t pixels); +int Skin_ClearBottomColors (byte *out, const byte *in, size_t pixels); void sw_Skin_SetupSkin (skin_t *skin, int cmap); void sw_Skin_ProcessTranslation (int cmap, const byte *translation); diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index c29eb50e0..ecaae8a6a 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -169,17 +169,17 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, byte *colb_data = QFV_PacketExtend (packet, skinsize * 4); byte *glow_data = QFV_PacketExtend (packet, skinsize * 4); - Mod_CalcFullbright (tskin, tskin + skinsize, skinsize); + Mod_CalcFullbright (tskin + skinsize, tskin, skinsize); Vulkan_ExpandPalette (glow_data, tskin + skinsize, vid.palette, 1, skinsize); Mod_ClearFullbright (tskin, tskin, skinsize); - Skin_CalcTopColors (tskin, tskin + skinsize, skinsize); + Skin_CalcTopColors (tskin + skinsize, tskin, skinsize); Vulkan_ExpandPalette (cola_data, tskin + skinsize, vid.palette, 1, skinsize); Skin_ClearTopColors (tskin, tskin, skinsize); - Skin_CalcBottomColors (tskin, tskin + skinsize, skinsize); + Skin_CalcBottomColors (tskin + skinsize, tskin, skinsize); Vulkan_ExpandPalette (colb_data, tskin + skinsize, vid.palette, 1, skinsize); Skin_ClearBottomColors (tskin, tskin, skinsize); diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index f83869b0f..6e1a7359a 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -366,7 +366,7 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) size_t fullbright_mark = Hunk_LowMark (0); byte *pixels = Hunk_AllocName (0, size, name); - if (!Mod_CalcFullbright ((byte *) (tx + 1), pixels, size)) { + if (!Mod_CalcFullbright (pixels, (byte *) (tx + 1), size)) { Hunk_FreeToLowMark (0, fullbright_mark); return; } diff --git a/libs/models/fullbright.c b/libs/models/fullbright.c index 8d76b9db4..56588f4c3 100644 --- a/libs/models/fullbright.c +++ b/libs/models/fullbright.c @@ -34,7 +34,7 @@ #include "mod_internal.h" VISIBLE int -Mod_CalcFullbright (const byte *in, byte *out, int pixels) +Mod_CalcFullbright (byte *out, const byte *in, size_t pixels) { byte fb = 0; @@ -50,8 +50,8 @@ Mod_CalcFullbright (const byte *in, byte *out, int pixels) return fb; } -VISIBLE void -Mod_ClearFullbright (const byte *in, byte *out, int pixels) +VISIBLE int +Mod_ClearFullbright (byte *out, const byte *in, size_t pixels) { while (pixels-- > 0) { byte pix = *in++; @@ -61,4 +61,5 @@ Mod_ClearFullbright (const byte *in, byte *out, int pixels) *out++ = pix; } } + return 0; } diff --git a/libs/models/gl_model_fullbright.c b/libs/models/gl_model_fullbright.c index e24050a1f..fbb330b94 100644 --- a/libs/models/gl_model_fullbright.c +++ b/libs/models/gl_model_fullbright.c @@ -53,7 +53,7 @@ Mod_Fullbright (byte *skin, int width, int height, const char *name) SYS_CHECKMEM (texels); // Check for fullbright pixels - if (Mod_CalcFullbright (skin, texels, pixels)) { + if (Mod_CalcFullbright (texels, skin, pixels)) { //FIXME black should be transparent for fullbrights (or just fix //fullbright rendering in gl) Sys_MaskPrintf (SYS_dev, "FB Model ID: '%s'\n", name); diff --git a/libs/models/gl_skin.c b/libs/models/gl_skin.c index ae9c9ac37..e55a88791 100644 --- a/libs/models/gl_skin.c +++ b/libs/models/gl_skin.c @@ -78,7 +78,7 @@ do_fb_skin (glskin_t *s) s->fb_tex->height = s->tex->height; s->fb_tex->format = tex_palette; s->fb_tex->palette = vid.palette; - s->fb = Mod_CalcFullbright (s->tex->data, s->fb_tex->data, size); + s->fb = Mod_CalcFullbright (s->fb_tex->data, s->tex->data, size); } void diff --git a/libs/models/skin.c b/libs/models/skin.c index 8933dcf51..2cbe90839 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -248,7 +248,7 @@ Skin_Init (void) } VISIBLE int -Skin_CalcTopColors (const byte *in, byte *out, int pixels) +Skin_CalcTopColors (byte *out, const byte *in, size_t pixels) { byte tc = 0; @@ -265,7 +265,7 @@ Skin_CalcTopColors (const byte *in, byte *out, int pixels) } VISIBLE int -Skin_CalcBottomColors (const byte *in, byte *out, int pixels) +Skin_CalcBottomColors (byte *out, const byte *in, size_t pixels) { byte bc = 0; @@ -281,8 +281,8 @@ Skin_CalcBottomColors (const byte *in, byte *out, int pixels) return bc; } -VISIBLE void -Skin_ClearTopColors (const byte *in, byte *out, int pixels) +VISIBLE int +Skin_ClearTopColors (byte *out, const byte *in, size_t pixels) { while (pixels-- > 0) { byte pix = *in++; @@ -292,10 +292,11 @@ Skin_ClearTopColors (const byte *in, byte *out, int pixels) *out++ = pix; } } + return 0; } -VISIBLE void -Skin_ClearBottomColors (const byte *in, byte *out, int pixels) +VISIBLE int +Skin_ClearBottomColors (byte *out, const byte *in, size_t pixels) { while (pixels-- > 0) { byte pix = *in++; @@ -305,4 +306,5 @@ Skin_ClearBottomColors (const byte *in, byte *out, int pixels) *out++ = pix; } } + return 0; } From d7f588ecfefb86d6b484b70535ad830c4542da54 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 7 Dec 2021 22:43:12 +0900 Subject: [PATCH 1933/3664] [vulkan] Rework bsp texture loader BSP textures are now two-layered with the albedo and emission in the two layers rather than two separate images. While this does increase memory usage for the textures themselves (most do not have fullbright pixels), it cuts down on image and image view handles (and shader resources). --- include/QF/Vulkan/qf_bsp.h | 2 - include/QF/Vulkan/qf_texture.h | 1 - libs/models/brush/vulkan_model_brush.c | 227 +++++++++--------------- libs/video/renderer/vulkan/vulkan_bsp.c | 2 - 4 files changed, 87 insertions(+), 145 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 3618d8680..914997364 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -46,8 +46,6 @@ typedef struct vulktex_s { struct elechain_s *elechain; struct elechain_s **elechain_tail; struct qfv_tex_s *tex; - struct qfv_tex_s *glow; - byte *glow_pixels; } vulktex_t; typedef struct bspvert_s { diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index 55a631f62..fec02a8f9 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -6,7 +6,6 @@ typedef struct qfv_tex_s { VkDeviceMemory memory; - size_t offset; VkImage image; VkImageView view; } qfv_tex_t; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 6e1a7359a..471cfac4c 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -64,7 +64,8 @@ static vulktex_t vulkan_notexture = { }; -static void vulkan_brush_clear (model_t *mod, void *data) +static void +vulkan_brush_clear (model_t *mod, void *data) { modelctx_t *mctx = data; vulkan_ctx_t *ctx = mctx->ctx; @@ -82,16 +83,22 @@ static void vulkan_brush_clear (model_t *mod, void *data) vulktex_t *tex = tx->render; dfunc->vkDestroyImage (device->dev, tex->tex->image, 0); dfunc->vkDestroyImageView (device->dev, tex->tex->view, 0); - if (tex->glow) { - dfunc->vkDestroyImage (device->dev, tex->glow->image, 0); - dfunc->vkDestroyImageView (device->dev, tex->glow->view, 0); - } } dfunc->vkFreeMemory (device->dev, mctx->texture_memory, 0); } +typedef int (*vprocess_t) (byte *, const byte *, size_t); + +static size_t +mipsize (size_t size) +{ + const int n = MIPLEVELS; + return size * ((1 << (2 * n)) - 1) / (3 * (1 << (2 * n - 2))); +} + static void -transfer_mips (byte *dst, const void *_src, const texture_t *tx, byte *palette) +transfer_mips (byte *dst, const void *_src, const texture_t *tx, byte *palette, + vprocess_t process) { const byte *src = _src; unsigned width = tx->width; @@ -103,7 +110,13 @@ transfer_mips (byte *dst, const void *_src, const texture_t *tx, byte *palette) // end of the texture struct offset = tx->offsets[i] - sizeof (texture_t); count = width * height; - Vulkan_ExpandPalette (dst, src + offset, palette, 2, count); + // use the upper block of the destination as a temporary buffer for + // the processed pixels. Vulkan_ExpandPalette works in a linearly + // increasing manner thus the processed pixels will be overwritten + // only after they have been read + byte *tmp = dst + count * 3; + process (tmp, src + offset, count); + Vulkan_ExpandPalette (dst, tmp, palette, 2, count); dst += count * 4; width >>= 1; height >>= 1; @@ -111,13 +124,13 @@ transfer_mips (byte *dst, const void *_src, const texture_t *tx, byte *palette) } static void -copy_mips (qfv_packet_t *packet, texture_t *tx, qfv_tex_t *tex, - qfv_devfuncs_t *dfunc) +copy_mips (qfv_packet_t *packet, texture_t *tx, size_t offset, VkImage image, + int layer, qfv_devfuncs_t *dfunc) { // base copy VkBufferImageCopy copy = { - tex->offset, tx->width, tx->height, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + offset, tx->width, tx->height, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, layer, 1}, {0, 0, 0}, {tx->width, tx->height, 1}, }; int is_sky = 0; @@ -128,6 +141,7 @@ copy_mips (qfv_packet_t *packet, texture_t *tx, qfv_tex_t *tex, if (strncmp (tx->name, "sky", 3) == 0) { if (tx->width == 2 * tx->height) { copy.imageExtent.width /= 2; + // sky layers are interleaved on each row sky_offset = tx->width * 4 / 2; } is_sky = 1; @@ -156,11 +170,48 @@ copy_mips (qfv_packet_t *packet, texture_t *tx, qfv_tex_t *tex, sky_offset >>= 1; } dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, - tex->image, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copies->size, copies->a); } +static void +transfer_texture (texture_t *tx, VkImage image, qfv_packet_t *packet, + byte *palette, qfv_devfuncs_t *dfunc) +{ + byte *base = packet->stage->data; + + size_t layer_size = mipsize (tx->width * tx->height * 4); + byte *dst = QFV_PacketExtend (packet, layer_size); + + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + + if (strncmp (tx->name, "sky", 3) == 0) { + transfer_mips (dst, tx + 1, tx, palette, (vprocess_t) memcpy); + copy_mips (packet, tx, dst - base, image, 0, dfunc); + } else { + transfer_mips (dst, tx + 1, tx, palette, Mod_ClearFullbright); + copy_mips (packet, tx, dst - base, image, 0, dfunc); + byte *glow = QFV_PacketExtend (packet, layer_size); + transfer_mips (glow, tx + 1, tx, palette, Mod_CalcFullbright); + copy_mips (packet, tx, glow - base, image, 1, dfunc); + } + + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); +} + static void load_textures (model_t *mod, vulkan_ctx_t *ctx) { @@ -168,12 +219,17 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; modelctx_t *mctx = mod->data; - VkImage image = 0; - byte *buffer; mod_brush_t *brush = &mod->brush; + VkImage image = 0; + byte sky_palette[256 * 4]; + + memcpy (sky_palette, vid.palette32, sizeof (sky_palette)); + // sky's black is transparent + // this hits both layers, but so long as the screen is cleared + // to black, no one should notice :) + sky_palette[3] = 0; size_t image_count = 0; - size_t copy_count = 0; size_t memsize = 0; for (unsigned i = 0; i < brush->numtextures; i++) { texture_t *tx = brush->textures[i]; @@ -181,21 +237,10 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) continue; } vulktex_t *tex = tx->render; - tex->tex->offset = memsize; memsize += QFV_GetImageSize (device, tex->tex->image); image_count++; - copy_count += MIPLEVELS; - if (strncmp (tx->name, "sky", 3) == 0) { - copy_count += MIPLEVELS; - } // just so we have one in the end image = tex->tex->image; - if (tex->glow) { - copy_count += MIPLEVELS; - tex->glow->offset = memsize; - memsize += QFV_GetImageSize (device, tex->glow->image); - image_count++; - } } VkDeviceMemory mem; mem = QFV_AllocImageMemory (device, image, @@ -210,108 +255,35 @@ load_textures (model_t *mod, vulkan_ctx_t *ctx) "brush:%s", mod->name), memsize, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); - buffer = QFV_PacketExtend (packet, memsize); - + size_t offset = 0; for (unsigned i = 0; i < brush->numtextures; i++) { texture_t *tx = brush->textures[i]; - byte *palette = vid.palette32; + if (!tx) { continue; } - vulktex_t *tex = tx->render; + qfv_tex_t *tex = ((vulktex_t *) tx->render)->tex; - dfunc->vkBindImageMemory (device->dev, tex->tex->image, mem, - tex->tex->offset); - VkImageViewType type = VK_IMAGE_VIEW_TYPE_2D; - if (strncmp (tx->name, "sky", 3) == 0) { - palette = alloca (256 * 4); - memcpy (palette, vid.palette32, 256 * 4); - // sky's black is transparent - // this hits both layers, but so long as the screen is cleared - // to black, no one should notice :) - palette[3] = 0; - type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - } - tex->tex->view = QFV_CreateImageView (device, tex->tex->image, + dfunc->vkBindImageMemory (device->dev, tex->image, mem, offset); + offset += QFV_GetImageSize (device, tex->image); + + VkImageViewType type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + tex->view = QFV_CreateImageView (device, tex->image, type, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, - tex->tex->view, + tex->view, va (ctx->va_ctx, "iview:%s:%s:tex", mod->name, tx->name)); - transfer_mips (buffer + tex->tex->offset, tx + 1, tx, palette); - if (tex->glow_pixels) { - dfunc->vkBindImageMemory (device->dev, tex->glow->image, mem, - tex->glow->offset); - // skys are unlit so never have a glow texture thus glow - // textures are always simple 2D - tex->glow->view = QFV_CreateImageView (device, tex->tex->image, - VK_IMAGE_VIEW_TYPE_2D, - VK_FORMAT_R8G8B8A8_UNORM, - VK_IMAGE_ASPECT_COLOR_BIT); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, - tex->glow->view, - va (ctx->va_ctx, "iview:%s:%s:glow", - mod->name, tx->name)); - transfer_mips (buffer + tex->glow->offset, tex->glow_pixels, tx, - palette); - } - } - // base barrier - qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; - ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - - __auto_type barriers = QFV_AllocImageBarrierSet (image_count, malloc); - barriers->size = 0; - for (unsigned i = 0; i < brush->numtextures; i++) { - texture_t *tx = brush->textures[i]; - if (!tx) { - continue; - } - vulktex_t *tex = tx->render; - __auto_type b = &barriers->a[barriers->size++]; - *b = ib.barrier; - b->image = tex->tex->image; - if (tex->glow) { - b = &barriers->a[barriers->size++]; - *b = ib.barrier; - b->image = tex->glow->image; + byte *palette = vid.palette32; + if (strncmp (tx->name, "sky", 3) == 0) { + palette = sky_palette; } + transfer_texture (tx, tex->image, packet, palette, dfunc); } - dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, - 0, 0, 0, 0, 0, - barriers->size, barriers->a); - for (unsigned i = 0, j = 0; i < brush->numtextures; i++) { - texture_t *tx = brush->textures[i]; - if (!tx) { - continue; - } - vulktex_t *tex = tx->render; - __auto_type b = &barriers->a[j++]; - b->oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - b->newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - b->srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - b->dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - copy_mips (packet, tx, tex->tex, dfunc); - if (tex->glow) { - b = &barriers->a[j++]; - b->oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - b->newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - b->srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - b->dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - copy_mips (packet, tx, tex->glow, dfunc); - } - } - - ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; - dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, - 0, 0, 0, 0, 0, - barriers->size, barriers->a); QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); - free (barriers); qfvPopDebug (ctx); } @@ -336,9 +308,10 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) tex->tex = (qfv_tex_t *) (tex + 1); VkExtent3D extent = { tx->width, tx->height, 1 }; - int layers = 1; + // Skies are two overlapping layers (one partly transparent), other + // textures are split into main color and glow color on separate layers + int layers = 2; if (strncmp (tx->name, "sky", 3) == 0) { - layers = 2; // the sky texture is normally 2 side-by-side squares, but // some maps have just a single square if (tx->width == 2 * tx->height) { @@ -356,32 +329,6 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) tex->tex->image, va (ctx->va_ctx, "image:%s:%s:tex", mod->name, tx->name)); - if (layers > 1) { - // skys are unlit, so no fullbrights - return; - } - - const char *name = va (ctx->va_ctx, "fb_%s", tx->name); - int size = (tx->width * tx->height * 85) / 64; - size_t fullbright_mark = Hunk_LowMark (0); - byte *pixels = Hunk_AllocName (0, size, name); - - if (!Mod_CalcFullbright (pixels, (byte *) (tx + 1), size)) { - Hunk_FreeToLowMark (0, fullbright_mark); - return; - } - tex->glow = tex->tex + 1; - tex->glow->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, - VK_FORMAT_R8G8B8A8_UNORM, - extent, 4, 1, - VK_SAMPLE_COUNT_1_BIT, - VK_IMAGE_USAGE_TRANSFER_DST_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, - tex->glow->image, - va (ctx->va_ctx, "image:%s:%s:glow", mod->name, - tx->name)); - tex->glow_pixels = pixels; } void diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 11403a607..735a03fe0 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1120,8 +1120,6 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bframe->imageInfo[0].imageView = get_view (tex->tex, ctx->default_white); - bframe->imageInfo[1].imageView = get_view (tex->glow, - ctx->default_black); push_descriptors (2, bframe->descriptors + 1, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspGBuffer]); From e8961342d5f95a582102d6fab2c2808ebbf7af1c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Dec 2021 15:23:01 +0900 Subject: [PATCH 1934/3664] [vulkan] Fix some mostly harmless typos --- include/QF/Vulkan/qf_compose.h | 2 +- include/QF/Vulkan/qf_lighting.h | 4 ++-- libs/video/renderer/vulkan/shader/lighting.frag | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h index b8942dba7..4c4f0507b 100644 --- a/include/QF/Vulkan/qf_compose.h +++ b/include/QF/Vulkan/qf_compose.h @@ -58,6 +58,6 @@ struct qfv_renderframe_s; void Vulkan_Compose_Init (struct vulkan_ctx_s *ctx); void Vulkan_Compose_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Compose_Draw (struct qfv_renderframe_s *fFrame); +void Vulkan_Compose_Draw (struct qfv_renderframe_s *rFrame); #endif//__QF_Vulkan_qf_compose_h diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index c96c08f0e..ec4de2c3f 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -128,11 +128,11 @@ typedef struct lightingctx_s { } lightingctx_t; struct vulkan_ctx_s; -struct qfv_renderframe_s;; +struct qfv_renderframe_s; void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Lighting_Draw (struct qfv_renderframe_s *fFrame); +void Vulkan_Lighting_Draw (struct qfv_renderframe_s *rFrame); void Vulkan_LoadLights (model_t *model, const char *entity_data, struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 9c8009d43..2d384e622 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -40,7 +40,7 @@ layout (set = 2, binding = 0) uniform samplerCubeShadow shadowCube[MaxLights]; layout (set = 1, binding = 0) uniform Lights { vec4 intensity[17]; // 68 floats float distFactor1; // for inverse - float distFactor2; // for inverse2 and inverse2 + float distFactor2; // for inverse2 and inverse3 int lightCount; LightData lights[MaxLights]; mat4 shadowMat[MaxLights]; From 84227325050eb0c4c2631635f3270b1c58840806 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Dec 2021 15:28:21 +0900 Subject: [PATCH 1935/3664] [vulkan] Move matrices into per-frame buffers This should fix the horrid frame rate dependent behavior of the view model. They are also in their own descriptor set so they can be easily shared between pipelines. This has been verified to work for Draw. --- include/QF/Vulkan/qf_matrices.h | 87 ++++++ include/QF/Vulkan/qf_vid.h | 4 - include/vid_vulkan.h | 13 +- libs/video/renderer/vid_render_vulkan.c | 4 +- libs/video/renderer/vulkan/qfpipeline.plist | 18 +- libs/video/renderer/vulkan/shader/twod.frag | 2 +- libs/video/renderer/vulkan/shader/twod.vert | 7 +- libs/video/renderer/vulkan/vulkan_alias.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 12 +- libs/video/renderer/vulkan/vulkan_draw.c | 17 +- libs/video/renderer/vulkan/vulkan_main.c | 27 -- libs/video/renderer/vulkan/vulkan_matrices.c | 257 ++++++++++++++---- .../video/renderer/vulkan/vulkan_vid_common.c | 3 +- 13 files changed, 325 insertions(+), 128 deletions(-) create mode 100644 include/QF/Vulkan/qf_matrices.h diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h new file mode 100644 index 000000000..6abbdde61 --- /dev/null +++ b/include/QF/Vulkan/qf_matrices.h @@ -0,0 +1,87 @@ +/* + qf_matrices.h + + Vulkan matrix "pass" + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/12/8 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_matrices_h +#define __QF_Vulkan_qf_matrices_h + +#include "QF/darray.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/image.h" +#include "QF/simd/types.h" + +typedef struct qfv_matrix_buffer_s { + // projection and view matrices (model is push constant) + mat4f_t Projection3d; + mat4f_t View; + mat4f_t Sky; + mat4f_t Projection2d; +} qfv_matrix_buffer_t; + +#define LIGHTING_BUFFER_INFOS 1 +#define LIGHTING_ATTACH_INFOS 5 +#define LIGHTING_SHADOW_INFOS MaxLights +#define LIGHTING_DESCRIPTORS (LIGHTING_BUFFER_INFOS + LIGHTING_ATTACH_INFOS + 1) + +typedef struct matrixframe_s { + //VkCommandBuffer cmd; + VkBuffer buffer; + VkDescriptorSet descriptors; +} matrixframe_t; + +typedef struct matrixframeset_s + DARRAY_TYPE (matrixframe_t) matrixframeset_t; + +typedef struct matrixctx_s { + matrixframeset_t frames; + VkPipeline pipeline; + VkPipelineLayout layout; + VkDeviceMemory memory; + qfv_matrix_buffer_t matrices; + int dirty; + struct qfv_stagebuf_s *stage; + VkDescriptorPool pool; + VkDescriptorSetLayout setLayout; +} matrixctx_t; + +struct vulkan_ctx_s; +struct qfv_renderframe_s; + +void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx); +void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx); +void Vulkan_SetViewMatrix (struct vulkan_ctx_s *ctx, mat4f_t view); +void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky); + +void Vulkan_Matrix_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Matrix_Shutdown (struct vulkan_ctx_s *ctx); +// "Draw" :) +void Vulkan_Matrix_Draw (struct qfv_renderframe_s *rFrame); +VkDescriptorSet Vulkan_Matrix_Descrptors (struct vulkan_ctx_s *ctx, int frame); + +#endif//__QF_Vulkan_qf_matrices_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index db37faa59..1a94898a3 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -63,10 +63,6 @@ void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateCapture (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPasses (struct vulkan_ctx_s *ctx); -void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx); -void Vulkan_DestroyMatrices (struct vulkan_ctx_s *ctx); -void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx); -void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 584502b9c..27fadb159 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -17,16 +17,6 @@ typedef struct vulkan_frame_s { VkCommandBuffer cmdBuffer; } vulkan_frame_t; -typedef struct vulkan_matrices_s { - VkBuffer buffer_2d; - VkBuffer buffer_3d; - VkDeviceMemory memory; - vec4f_t *projection_2d; - vec4f_t *projection_3d; - vec4f_t *view_3d; - vec4f_t *sky_3d; -} vulkan_matrices_t; - typedef struct vulkan_frameset_s DARRAY_TYPE (vulkan_frame_t) vulkan_frameset_t; @@ -66,6 +56,7 @@ typedef struct vulkan_ctx_s { struct hashtab_s *imageViews; struct hashtab_s *renderpasses; + struct matrixctx_s *matrix_context; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; struct drawctx_s *draw_context; @@ -92,8 +83,6 @@ typedef struct vulkan_ctx_s { VkViewport viewport; VkRect2D scissor; - // projection and view matrices (model is push constant) - vulkan_matrices_t matrices; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 718d22464..0114610b8 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -47,6 +47,7 @@ #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" +#include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_vid.h" @@ -93,13 +94,13 @@ static void vulkan_R_Init (void) { Vulkan_CreateStagingBuffers (vulkan_ctx); - Vulkan_CreateMatrices (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_Texture_Init (vulkan_ctx); + Vulkan_Matrix_Init (vulkan_ctx); Vulkan_Alias_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); @@ -629,6 +630,7 @@ vulkan_vid_render_shutdown (void) Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Alias_Shutdown (vulkan_ctx); + Vulkan_Matrix_Shutdown (vulkan_ctx); Mod_ClearAll (); Vulkan_Texture_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 9ef5661a8..b2c83ceb5 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -77,7 +77,7 @@ }; }; descriptorPools = { - twod_pool = { + matrix_pool = { flags = 0; maxSets = $frames.size; bindings = ( @@ -85,6 +85,12 @@ type = uniform_buffer; descriptorCount = $frames.size; }, + ); + }; + twod_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( { type = combined_image_sampler; descriptorCount = $frames.size; @@ -143,7 +149,7 @@ }; }; setLayouts = { - twod_set = { + matrix_set = { bindings = ( { binding = 0; @@ -151,8 +157,12 @@ descriptorCount = 1; stageFlags = vertex; }, + ); + }; + twod_set = { + bindings = ( { - binding = 1; + binding = 0; descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; @@ -342,7 +352,7 @@ }; pipelineLayouts = { twod_layout = { - setLayouts = (twod_set); + setLayouts = (matrix_set, twod_set); }; quakebsp_layout = { setLayouts = (quakebsp_set); diff --git a/libs/video/renderer/vulkan/shader/twod.frag b/libs/video/renderer/vulkan/shader/twod.frag index a6a40212d..b705b270a 100644 --- a/libs/video/renderer/vulkan/shader/twod.frag +++ b/libs/video/renderer/vulkan/shader/twod.frag @@ -1,6 +1,6 @@ #version 450 -layout (set = 0, binding = 1) uniform sampler2D Texture; +layout (set = 1, binding = 0) uniform sampler2D Texture; layout (location = 0) in vec2 st; layout (location = 1) in vec4 color; diff --git a/libs/video/renderer/vulkan/shader/twod.vert b/libs/video/renderer/vulkan/shader/twod.vert index c5dc5063a..8f0a25f57 100644 --- a/libs/video/renderer/vulkan/shader/twod.vert +++ b/libs/video/renderer/vulkan/shader/twod.vert @@ -1,7 +1,10 @@ #version 450 layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection; + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; }; /** Vertex position. @@ -20,7 +23,7 @@ layout (location = 1) out vec4 color; void main (void) { - gl_Position = Projection * vec4 (vertex.xy, 0.0, 1.0); + gl_Position = Projection2d * vec4 (vertex.xy, 0.0, 1.0); st = uv; color = vcolor; } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index b842d85d4..9a99e307a 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -244,7 +244,7 @@ Vulkan_AliasBegin (qfv_renderframe_t *rFrame) aframe->cmdSet.a[QFV_aliasGBuffer]); //FIXME need per frame matrices - aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + //XXX aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; alias_begin_subpass (QFV_aliasDepth, actx->depth, rFrame); alias_begin_subpass (QFV_aliasGBuffer, actx->gbuf, rFrame); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 735a03fe0..266b7c3a5 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -905,7 +905,7 @@ bsp_begin (qfv_renderframe_t *rFrame) bframe->cmdSet.a[QFV_bspGBuffer]); //FIXME need per frame matrices - bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + //XXX bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; bframe->imageInfo[0].imageView = 0; // set by tex chain loop bframe->imageInfo[1].imageView = 0; // set by tex chain loop bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); @@ -944,7 +944,7 @@ turb_begin (qfv_renderframe_t *rFrame) bframe->cmdSet.a[QFV_bspTurb]); //FIXME need per frame matrices - bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + //XXX bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; bframe->imageInfo[0].imageView = ctx->default_magenta->view; bframe->imageInfo[1].imageView = ctx->default_magenta->view; bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); @@ -962,7 +962,7 @@ turb_end (vulkan_ctx_t *ctx) bsp_end_subpass (bframe->cmdSet.a[QFV_bspTurb], ctx); } - +/*XXX static void spin (mat4f_t mat, bspctx_t *bctx) { @@ -985,7 +985,7 @@ spin (mat4f_t mat, bspctx_t *bctx) mat4fquat (m, q); mmulf (mat, m, mat); } - +*/ static void sky_begin (qfv_renderframe_t *rFrame) { @@ -995,7 +995,7 @@ sky_begin (qfv_renderframe_t *rFrame) bctx->default_color[3] = 1; QuatCopy (bctx->default_color, bctx->last_color); - spin (ctx->matrices.sky_3d, bctx); + //XXX spin (ctx->matrices.sky_3d, bctx); bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; @@ -1003,7 +1003,7 @@ sky_begin (qfv_renderframe_t *rFrame) bframe->cmdSet.a[QFV_bspSky]); //FIXME need per frame matrices - bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; + //XXX bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; bframe->imageInfo[0].imageView = ctx->default_magenta->view; bframe->imageInfo[1].imageView = ctx->default_magenta->view; bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 6a2d792ae..ed068032d 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -51,6 +51,7 @@ #include "compat.h" #include "QF/Vulkan/qf_draw.h" +#include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" @@ -405,9 +406,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) } __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "twod_pool"); - VkDescriptorBufferInfo bufferInfo = { - ctx->matrices.buffer_2d, 0, VK_WHOLE_SIZE - }; VkDescriptorImageInfo imageInfo = { dctx->sampler, QFV_ScrapImageView (dctx->scrap), @@ -424,14 +422,10 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, dframe->descriptors, 0, 0, 1, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - 0, &bufferInfo, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - dframe->descriptors, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo, 0, 0 }, }; - dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); dframe->cmd = cmdBuffers->a[i]; QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, dframe->cmd, @@ -799,10 +793,13 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets); dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, VK_INDEX_TYPE_UINT32); - VkDescriptorSet set = dframe->descriptors; + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descrptors (ctx, ctx->curFrame), + dframe->descriptors, + }; VkPipelineLayout layout = dctx->layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 1, &set, 0, 0); + layout, 0, 2, set, 0, 0); dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD, 1, 0, 0, 0); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 5cfa90094..b4ba322dc 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -77,32 +77,6 @@ setup_frame (vulkan_ctx_t *ctx) r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); } -static void -setup_view (vulkan_ctx_t *ctx) -{ - mat4f_t view; - static mat4f_t z_up = { - { 0, 0, -1, 0}, - {-1, 0, 0, 0}, - { 0, 1, 0, 0}, - { 0, 0, 0, 1}, - }; - vec4f_t offset = { 0, 0, 0, 1 }; - - /*x = r_refdef.vrect.x; - y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - qfeglViewport (x, y, w, h);*/ - - mat4fquat (view, qconjf (r_refdef.viewrotation)); - mmulf (view, z_up, view); - offset = -r_refdef.viewposition; - offset[3] = 1; - view[3] = mvmulf (view, offset); - memcpy (ctx->matrices.view_3d, view, sizeof (view)); -} - static void Vulkan_RenderEntities (qfv_renderframe_t *rFrame) { @@ -166,7 +140,6 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) if (speeds) t[0] = Sys_DoubleTime (); setup_frame (ctx); - setup_view (ctx); if (speeds) t[1] = Sys_DoubleTime (); R_MarkLeaves (); diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index d43ecc7f2..9a892fdb0 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -28,16 +28,31 @@ # include "config.h" #endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + #ifdef HAVE_MATH_H # include #endif +#include "QF/cvar.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/vid.h" -#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" +#include "QF/Vulkan/renderpass.h" +#include "QF/Vulkan/staging.h" #include "QF/ui/view.h" #include "r_internal.h" @@ -45,98 +60,222 @@ #include "util.h" -#define MAT_SIZE (16 * sizeof (float)) - -void -Vulkan_DestroyMatrices (vulkan_ctx_t *ctx) +static void +setup_view (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; + mat4f_t view; + static mat4f_t z_up = { + { 0, 0, -1, 0}, + {-1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 0, 1}, + }; + vec4f_t offset = { 0, 0, 0, 1 }; - __auto_type mat = &ctx->matrices; + /*x = r_refdef.vrect.x; + y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); + w = r_refdef.vrect.width; + h = r_refdef.vrect.height; + qfeglViewport (x, y, w, h);*/ - dfunc->vkUnmapMemory (device->dev, mat->memory); - dfunc->vkFreeMemory (device->dev, mat->memory, 0); - dfunc->vkDestroyBuffer (device->dev, mat->buffer_2d, 0); - dfunc->vkDestroyBuffer (device->dev, mat->buffer_3d, 0); + mat4fquat (view, qconjf (r_refdef.viewrotation)); + mmulf (view, z_up, view); + offset = -r_refdef.viewposition; + offset[3] = 1; + view[3] = mvmulf (view, offset); + Vulkan_SetViewMatrix (ctx, view); } void -Vulkan_CreateMatrices (vulkan_ctx_t *ctx) +Vulkan_SetViewMatrix (vulkan_ctx_t *ctx, mat4f_t view) { + __auto_type mctx = ctx->matrix_context; + + if (memcmp (mctx->matrices.View, view, sizeof (mat4f_t))) { + memcpy (mctx->matrices.View, view, sizeof (mat4f_t)); + mctx->dirty = mctx->frames.size; + } +} + +void +Vulkan_Matrix_Draw (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - __auto_type mat = &ctx->matrices; - mat->buffer_2d = QFV_CreateBuffer (device, 1 * MAT_SIZE, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); - mat->buffer_3d = QFV_CreateBuffer (device, 3 * MAT_SIZE, - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + __auto_type mctx = ctx->matrix_context; + __auto_type mframe = &mctx->frames.a[ctx->curFrame]; - size_t size = 0; - size_t offset; - VkMemoryRequirements req; + setup_view (ctx); - dfunc->vkGetBufferMemoryRequirements (device->dev, mat->buffer_2d, &req); - size += req.size; - offset = size; + if (mctx->dirty <= 0) { + mctx->dirty = 0; + return; + } - dfunc->vkGetBufferMemoryRequirements (device->dev, mat->buffer_3d, &req); - offset = (offset + req.alignment - 1) & ~(req.alignment - 1); - size += req.size; + mctx->dirty--; - mat->memory = QFV_AllocBufferMemory (device, mat->buffer_2d, - VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - size, 0); - QFV_BindBufferMemory (device, mat->buffer_2d, mat->memory, 0); - QFV_BindBufferMemory (device, mat->buffer_3d, mat->memory, offset); - void *data; - dfunc->vkMapMemory (device->dev, mat->memory, 0, size, 0, &data); - mat->projection_2d = data; - mat->projection_3d = (vec4f_t *) ((byte *) mat->projection_2d + offset); - mat->view_3d = mat->projection_3d + 4; - mat->sky_3d = mat->view_3d + 4; + qfv_packet_t *packet = QFV_PacketAcquire (mctx->stage); + qfv_matrix_buffer_t *m = QFV_PacketExtend (packet, sizeof (*m)); + *m = mctx->matrices; + + qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; bb.barrier.buffer = mframe->buffer; + bb.barrier.size = packet->length; + + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); + + VkBufferCopy copy_region = { packet->offset, 0, packet->length }; + dfunc->vkCmdCopyBuffer (packet->cmd, mctx->stage->buffer, + mframe->buffer, 1, ©_region); + + bb = bufferBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + bb.barrier.buffer = mframe->buffer; + bb.barrier.size = packet->length; + + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); + + QFV_PacketSubmit (packet); } void Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - __auto_type mat = &ctx->matrices; + __auto_type mctx = ctx->matrix_context; + __auto_type mat = &mctx->matrices; int width = vid.conview->xlen; int height = vid.conview->ylen; - QFV_Orthographic (mat->projection_2d, 0, width, 0, height, 0, 99999); + QFV_Orthographic (mat->Projection2d, 0, width, 0, height, 0, 99999); float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; - QFV_Perspective (mat->projection_3d, r_refdef.fov_y, aspect); + QFV_Perspective (mat->Projection3d, r_refdef.fov_y, aspect); #if 0 Sys_MaskPrintf (SYS_vulkan, "ortho:\n"); Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n", - QuatExpand (mat->projection_2d + 0)); + QuatExpand (mat->Projection2d + 0)); Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", - QuatExpand (mat->projection_2d + 4)); + QuatExpand (mat->Projection2d + 4)); Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", - QuatExpand (mat->projection_2d + 8)); + QuatExpand (mat->Projection2d + 8)); Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g]]\n", - QuatExpand (mat->projection_2d + 12)); + QuatExpand (mat->Projection2d + 12)); Sys_MaskPrintf (SYS_vulkan, "presp:\n"); Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n", - QuatExpand (mat->projection_3d + 0)); + QuatExpand (mat->Projection3d + 0)); Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", - QuatExpand (mat->projection_3d + 4)); + QuatExpand (mat->Projection3d + 4)); Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", - QuatExpand (mat->projection_3d + 8)); + QuatExpand (mat->Projection3d + 8)); Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g]]\n", - QuatExpand (mat->projection_3d + 12)); + QuatExpand (mat->Projection3d + 12)); #endif - VkMappedMemoryRange ranges[] = { - { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, 0, MAT_SIZE }, - { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, mat->memory, - (mat->projection_3d - mat->projection_2d) * sizeof (mat->projection_2d[0]), - MAT_SIZE}, - }; - dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); + mctx->dirty = mctx->frames.size; +} + +void +Vulkan_Matrix_Init (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "matrix init"); + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + matrixctx_t *mctx = calloc (1, sizeof (matrixctx_t)); + ctx->matrix_context = mctx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&mctx->frames, frames); + DARRAY_RESIZE (&mctx->frames, frames); + mctx->frames.grow = 0; + + //__auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); + //QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); + + mctx->pool = Vulkan_CreateDescriptorPool (ctx, "matrix_pool"); + mctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "matrix_set"); + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = mctx->setLayout; + } + + for (size_t i = 0; i < frames; i++) { + __auto_type mframe = &mctx->frames.a[i]; + //mframe->cmd = cmdBuffers->a[i]; + mframe->buffer = QFV_CreateBuffer (device, sizeof (qfv_matrix_buffer_t), + VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, + mframe->buffer, va (ctx->va_ctx, + "buffer:matrices:%zd", i)); + } + + VkMemoryRequirements req; + //offset = (offset + req.alignment - 1) & ~(req.alignment - 1); + dfunc->vkGetBufferMemoryRequirements (device->dev, + mctx->frames.a[0].buffer, &req); + mctx->memory = QFV_AllocBufferMemory (device, mctx->frames.a[0].buffer, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + frames * req.size, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + mctx->memory, "memory:matrices"); + + __auto_type sets = QFV_AllocateDescriptorSet (device, mctx->pool, layouts); + for (size_t i = 0; i < frames; i++) { + __auto_type mframe = &mctx->frames.a[i]; + QFV_BindBufferMemory (device, mframe->buffer, mctx->memory, + i * req.size); + + mframe->descriptors = sets->a[i]; + VkDescriptorBufferInfo bufferInfo = { + mframe->buffer, 0, VK_WHOLE_SIZE + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + mframe->descriptors, 0, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + 0, &bufferInfo, 0 }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + } + free (sets); + + mat4fidentity (mctx->matrices.Projection3d); + mat4fidentity (mctx->matrices.View); + mat4fidentity (mctx->matrices.Sky); + mat4fidentity (mctx->matrices.Projection2d); + mctx->dirty = mctx->frames.size; + + mctx->stage = QFV_CreateStagingBuffer (device, "matrix", + frames * sizeof (qfv_matrix_buffer_t), + ctx->cmdpool); + + qfvPopDebug (ctx); +} + +void +Vulkan_Matrix_Shutdown (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "matrix shutdown"); + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + __auto_type mctx = ctx->matrix_context; + + QFV_DestroyStagingBuffer (mctx->stage); + + for (size_t i = 0; i < mctx->frames.size; i++) { + __auto_type mframe = &mctx->frames.a[i]; + dfunc->vkDestroyBuffer (device->dev, mframe->buffer, 0); + } + dfunc->vkFreeMemory (device->dev, mctx->memory, 0); + qfvPopDebug (ctx); +} + +VkDescriptorSet +Vulkan_Matrix_Descrptors (vulkan_ctx_t *ctx, int frame) +{ + __auto_type mctx = ctx->matrix_context; + return mctx->frames.a[frame].descriptors; } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 8bea24b51..de553fde0 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -50,6 +50,7 @@ #include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" +#include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" @@ -228,7 +229,6 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) QFV_DestroySwapchain (ctx->swapchain); } QFV_DestroyStagingBuffer (ctx->staging); - Vulkan_DestroyMatrices (ctx); ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, ctx->surface, 0); clear_table (&ctx->pipelineLayouts); @@ -336,6 +336,7 @@ get_image_size (VkImage image, qfv_device_t *device) static void renderpass_draw (qfv_renderframe_t *rFrame) { + Vulkan_Matrix_Draw (rFrame); Vulkan_RenderView (rFrame); Vulkan_FlushText (rFrame); Vulkan_Lighting_Draw (rFrame); From 2740f6093b8c12aa340a6ef02e06a5eed7f88dab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Dec 2021 16:44:22 +0900 Subject: [PATCH 1936/3664] [vulkan] Update shaders and layouts for new scheme Still need to work on the code, though. --- libs/video/renderer/vulkan/qfpipeline.plist | 97 ++----------------- libs/video/renderer/vulkan/shader/alias.vert | 5 +- .../renderer/vulkan/shader/alias_depth.vert | 5 +- .../renderer/vulkan/shader/alias_gbuf.frag | 4 +- .../renderer/vulkan/shader/bsp_depth.vert | 5 +- .../renderer/vulkan/shader/bsp_gbuf.frag | 7 +- .../renderer/vulkan/shader/bsp_gbuf.geom | 5 +- .../renderer/vulkan/shader/bsp_gbuf.vert | 3 +- .../video/renderer/vulkan/shader/bsp_sky.frag | 6 +- .../renderer/vulkan/shader/bsp_turb.frag | 4 +- .../renderer/vulkan/shader/quakebsp.vert | 5 +- 11 files changed, 35 insertions(+), 111 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index b2c83ceb5..2a917b573 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -155,7 +155,7 @@ binding = 0; descriptorType = uniform_buffer; descriptorCount = 1; - stageFlags = vertex; + stageFlags = vertex|geometry; }, ); }; @@ -173,38 +173,14 @@ bindings = ( { binding = 0; - descriptorType = uniform_buffer; + descriptorType = sampler; descriptorCount = 1; - stageFlags = vertex|geometry; + stageFlags = fragment; }, { binding = 1; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 2; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 3; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 4; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 5; - descriptorType = combined_image_sampler; - descriptorCount = 1; + descriptorType = sampled_image; + descriptorCount = $properties.limits.maxImages; stageFlags = fragment; }, ); @@ -213,9 +189,9 @@ bindings = ( { binding = 0; - descriptorType = uniform_buffer; + descriptorType = sampler; descriptorCount = 1; - stageFlags = vertex; + stageFlags = fragment; }, { binding = 1; @@ -223,60 +199,6 @@ descriptorCount = $properties.limits.maxImages; stageFlags = fragment; }, - { - binding = 2; - descriptorType = sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - alias_matrices = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, - ); - }; - alias_textures = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 1; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 2; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 3; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - alias_lights = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = fragment; - }, ); }; lighting_attach = { @@ -355,7 +277,7 @@ setLayouts = (matrix_set, twod_set); }; quakebsp_layout = { - setLayouts = (quakebsp_set); + setLayouts = (matrix_set, quakebsp_set); pushConstantRanges = ( { stageFlags = vertex; @@ -370,8 +292,7 @@ ); }; alias_layout = { - //setLayouts = (alias_matrices, alias_lights, alias_textures); - setLayouts = (alias_set); + setLayouts = (matrix_set, alias_set); pushConstantRanges = ( { stageFlags = vertex; diff --git a/libs/video/renderer/vulkan/shader/alias.vert b/libs/video/renderer/vulkan/shader/alias.vert index a54b43674..52f390781 100644 --- a/libs/video/renderer/vulkan/shader/alias.vert +++ b/libs/video/renderer/vulkan/shader/alias.vert @@ -1,9 +1,10 @@ #version 450 layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection; + mat4 Projection3d; mat4 View; mat4 Sky; + mat4 Projection2d; }; layout (push_constant) uniform PushConstants { @@ -31,7 +32,7 @@ main (void) vertex = mix (vertexa, vertexb, blend); norm = mix (normala, normalb, blend); pos = (Model * vertex); - gl_Position = Projection * (View * pos); + gl_Position = Projection3d * (View * pos); position = pos; normal = mat3 (Model) * norm; st = uv; diff --git a/libs/video/renderer/vulkan/shader/alias_depth.vert b/libs/video/renderer/vulkan/shader/alias_depth.vert index 44437788e..2d580cd11 100644 --- a/libs/video/renderer/vulkan/shader/alias_depth.vert +++ b/libs/video/renderer/vulkan/shader/alias_depth.vert @@ -1,9 +1,10 @@ #version 450 layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection; + mat4 Projection3d; mat4 View; mat4 Sky; + mat4 Projection2d; }; layout (push_constant) uniform PushConstants { @@ -24,5 +25,5 @@ main (void) vertex = mix (vertexa, vertexb, blend); pos = (Model * vertex); - gl_Position = Projection * (View * pos); + gl_Position = Projection3d * (View * pos); } diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index b09997caf..74c33e58f 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -2,8 +2,8 @@ layout (constant_id = 0) const int MaxTextures = 256; -layout (set = 0, binding = 1) uniform texture2DArray skins[MaxTextures]; -layout (set = 0, binding = 2) uniform sampler samp; +layout (set = 1, binding = 0) uniform sampler samp; +layout (set = 1, binding = 1) uniform texture2DArray skins[MaxTextures]; layout (push_constant) uniform PushConstants { layout (offset = 68) diff --git a/libs/video/renderer/vulkan/shader/bsp_depth.vert b/libs/video/renderer/vulkan/shader/bsp_depth.vert index 02a4fed80..8ee96735f 100644 --- a/libs/video/renderer/vulkan/shader/bsp_depth.vert +++ b/libs/video/renderer/vulkan/shader/bsp_depth.vert @@ -1,9 +1,10 @@ #version 450 layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection; + mat4 Projection3d; mat4 View; mat4 Sky; + mat4 Projection2d; }; layout (push_constant) uniform PushConstants { @@ -15,5 +16,5 @@ layout (location = 0) in vec4 vertex; void main (void) { - gl_Position = Projection * (View * (Model * vertex)); + gl_Position = Projection3d * (View * (Model * vertex)); } diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index 2be3743ca..1e70788b5 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -2,11 +2,8 @@ layout (constant_id = 0) const int MaxTextures = 256; -layout (set = 0, binding = 1) uniform texture2DArray textures[MaxTextures]; -layout (set = 0, binding = 2) uniform sampler samp; - -layout (set = 0, binding = 1) uniform sampler2D Texture; -layout (set = 0, binding = 2) uniform sampler2D GlowMap; +layout (set = 1, binding = 0) uniform sampler samp; +layout (set = 1, binding = 1) uniform texture2DArray textures[MaxTextures]; layout (push_constant) uniform PushConstants { layout (offset = 64) diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom index bb46ae43a..44f17a3b1 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom @@ -1,9 +1,10 @@ #version 450 layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection; + mat4 Projection3d; mat4 View; mat4 Sky; + mat4 Projection2d; }; layout (triangles) in; @@ -27,7 +28,7 @@ main() for (int vert = 0; vert < 3; vert++) { vec4 p = gl_in[vert].gl_Position; - gl_Position = Projection * (View * (p)); + gl_Position = Projection3d * (View * (p)); tl_st = v_tl_st[vert]; direction = v_direction[vert]; normal = n; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert index abfb6c4e6..7b80384c5 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert @@ -1,9 +1,10 @@ #version 450 layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection; + mat4 Projection3d; mat4 View; mat4 Sky; + mat4 Projection2d; }; layout (push_constant) uniform PushConstants { diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index 0c8dc7893..dc6fe6d6a 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -4,9 +4,9 @@ layout (constant_id = 0) const int MaxTextures = 256; layout (constant_id = 1) const bool doSkyBox = false; layout (constant_id = 2) const bool doSkySheet = false; -layout (set = 0, binding = 1) uniform texture2DArray sheet_tex[MaxTextures]; -layout (set = 0, binding = 1) uniform textureCube cube_tex[MaxTextures]; -layout (set = 0, binding = 2) uniform sampler samp; +layout (set = 1, binding = 0) uniform sampler samp; +layout (set = 1, binding = 1) uniform texture2DArray sheet_tex[MaxTextures]; +layout (set = 1, binding = 1) uniform textureCube cube_tex[MaxTextures]; layout (push_constant) uniform PushConstants { layout (offset = 64) diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index 9929e60e1..969e9221f 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -2,8 +2,8 @@ layout (constant_id = 0) const int MaxTextures = 256; -layout (set = 0, binding = 1) uniform texture2D textures[MaxTextures]; -layout (set = 0, binding = 2) uniform sampler samp; +layout (set = 1, binding = 0) uniform sampler samp; +layout (set = 1, binding = 1) uniform texture2D textures[MaxTextures]; layout (push_constant) uniform PushConstants { layout (offset = 64) diff --git a/libs/video/renderer/vulkan/shader/quakebsp.vert b/libs/video/renderer/vulkan/shader/quakebsp.vert index bb9e87e4a..397bd2595 100644 --- a/libs/video/renderer/vulkan/shader/quakebsp.vert +++ b/libs/video/renderer/vulkan/shader/quakebsp.vert @@ -1,9 +1,10 @@ #version 450 layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection; + mat4 Projection3d; mat4 View; mat4 Sky; + mat4 Projection2d; }; layout (push_constant) uniform PushConstants { @@ -19,7 +20,7 @@ layout (location = 1) out vec3 direction; void main (void) { - gl_Position = Projection * (View * (Model * vertex)); + gl_Position = Projection3d * (View * (Model * vertex)); direction = (Sky * vertex).xyz; tl_st = tl_uv; } From 6fbce335bbe5829976854335b1c5863a454cb079 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Dec 2021 21:08:37 +0900 Subject: [PATCH 1937/3664] [vulkan] Add an array view for default_magenta The validation layers get very picky about image view types (rightfully so, I imagine). --- include/vid_vulkan.h | 1 + libs/video/renderer/vulkan/vulkan_texture.c | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 27fadb159..bb5b8a779 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -80,6 +80,7 @@ typedef struct vulkan_ctx_s { struct qfv_tex_s *default_black; struct qfv_tex_s *default_white; struct qfv_tex_s *default_magenta; + struct qfv_tex_s *default_magenta_array; VkViewport viewport; VkRect2D scissor; diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 4a6949881..b90601102 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -404,9 +404,15 @@ Vulkan_UnloadTex (vulkan_ctx_t *ctx, qfv_tex_t *tex) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkDestroyImageView (device->dev, tex->view, 0); - dfunc->vkDestroyImage (device->dev, tex->image, 0); - dfunc->vkFreeMemory (device->dev, tex->memory, 0); + if (tex->view) { + dfunc->vkDestroyImageView (device->dev, tex->view, 0); + } + if (tex->image) { + dfunc->vkDestroyImage (device->dev, tex->image, 0); + } + if (tex->memory) { + dfunc->vkFreeMemory (device->dev, tex->memory, 0); + } free (tex); } @@ -426,6 +432,14 @@ Vulkan_Texture_Init (vulkan_ctx_t *ctx) "default_white"); ctx->default_magenta = Vulkan_LoadTex (ctx, &default_magenta_tex, 1, "default_magenta"); + qfv_tex_t *tex; + tex = ctx->default_magenta_array = malloc (sizeof (qfv_tex_t)); + tex->memory = 0; + tex->image = 0; + tex->view = QFV_CreateImageView (ctx->device, ctx->default_magenta->image, + VK_IMAGE_VIEW_TYPE_2D_ARRAY, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_ASPECT_COLOR_BIT); } void @@ -434,4 +448,5 @@ Vulkan_Texture_Shutdown (vulkan_ctx_t *ctx) Vulkan_UnloadTex (ctx, ctx->default_black); Vulkan_UnloadTex (ctx, ctx->default_white); Vulkan_UnloadTex (ctx, ctx->default_magenta); + Vulkan_UnloadTex (ctx, ctx->default_magenta_array); } From 11492d77ce737c8aca8a43253ee50b99acf7a628 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Dec 2021 21:11:36 +0900 Subject: [PATCH 1938/3664] [vulkan] Switch bsp renderer to multi-texture I guess it's not quite bindless as the texture index is a push constant, but it seems to work well (and I may have fixed some full-bright issues by accident, though I suspect that's just my imagination, but they do look good). --- include/QF/Vulkan/qf_bsp.h | 16 +- libs/video/renderer/vulkan/qfpipeline.plist | 14 ++ .../renderer/vulkan/shader/bsp_gbuf.frag | 5 +- .../renderer/vulkan/shader/bsp_turb.frag | 8 +- libs/video/renderer/vulkan/vulkan_bsp.c | 223 ++++++++---------- 5 files changed, 122 insertions(+), 144 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 914997364..0f5d54f7a 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -46,6 +46,7 @@ typedef struct vulktex_s { struct elechain_s *elechain; struct elechain_s **elechain_tail; struct qfv_tex_s *tex; + int texind; } vulktex_t; typedef struct bspvert_s { @@ -75,10 +76,6 @@ typedef enum { qfv_bsp_skysheet, qfv_bsp_skycube, } qfv_bsp_tex; -// view matrix -#define BSP_BUFFER_INFOS 1 -// Texture, GlowMap, LightMap, SkySheet, SkyCube -#define BSP_IMAGE_INFOS 5 typedef enum { QFV_bspDepth, @@ -94,14 +91,12 @@ typedef struct bspframe_s { uint32_t index_offset; // offset of index_data within mega-buffer (c) uint32_t index_count; // number if indices queued (d) qfv_cmdbufferset_t cmdSet; - VkDescriptorBufferInfo bufferInfo[BSP_BUFFER_INFOS]; - VkDescriptorImageInfo imageInfo[BSP_IMAGE_INFOS]; - VkWriteDescriptorSet descriptors[BSP_BUFFER_INFOS + BSP_IMAGE_INFOS]; } bspframe_t; typedef struct fragconst_s { quat_t fog; float time; + int texind; } fragconst_t; typedef struct bspframeset_s @@ -157,13 +152,18 @@ typedef struct bspctx_s { struct bsppoly_s *polys; VkSampler sampler; + VkDescriptorSet descriptors; + VkDescriptorPool pool; + VkDescriptorSetLayout setLayout; + VkPipelineLayout layout; + unsigned maxImages; + VkDeviceMemory texture_memory; VkPipeline depth; VkPipeline gbuf; VkPipeline skysheet; VkPipeline skybox; VkPipeline turb; - VkPipelineLayout layout; size_t vertex_buffer_size; size_t index_buffer_size; VkBuffer vertex_buffer; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 2a917b573..50015707a 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -107,6 +107,20 @@ }, ); }; + quakebsp_pool = { + flags = 0; + maxSets = 1; + bindings = ( + { + type = sampler; + descriptorCount = 1; + }, + { + type = sampled_image; + descriptorCount = $properties.limits.maxImages; + }, + ); + }; lighting_attach_pool = { flags = 0; maxSets = $frames.size; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index 1e70788b5..7d1c7c3c9 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -38,10 +38,11 @@ main (void) vec4 c = vec4 (0); vec4 e; vec3 t_st = vec3 (tl_st.xy, 0); - vec3 l_st = vec3 (tl_st.zw, 1); + vec3 e_st = vec3 (tl_st.xy, 1); + vec2 l_st = vec2 (tl_st.zw); c = texture (sampler2DArray (textures[texind], samp), t_st); - e = texture (sampler2DArray (textures[texind], samp), t_st); + e = texture (sampler2DArray (textures[texind], samp), e_st); frag_color = c;//fogBlend (c); frag_emission = e; frag_normal = vec4 (normal, 0); diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index 969e9221f..acce754bf 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -3,7 +3,7 @@ layout (constant_id = 0) const int MaxTextures = 256; layout (set = 1, binding = 0) uniform sampler samp; -layout (set = 1, binding = 1) uniform texture2D textures[MaxTextures]; +layout (set = 1, binding = 1) uniform texture2DArray textures[MaxTextures]; layout (push_constant) uniform PushConstants { layout (offset = 64) @@ -47,10 +47,8 @@ main (void) { vec4 c = vec4 (0); vec4 e; - vec2 t_st = tl_st.xy; - vec2 l_st = tl_st.zw; + vec3 t_st = vec3 (warp_st (tl_st.xy, time), 0); - t_st = warp_st (t_st, time); - c = texture (sampler2D (textures[texind], samp), t_st); + c = texture (sampler2DArray (textures[texind], samp), t_st); frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 266b7c3a5..ce41cfdf2 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -54,6 +54,7 @@ #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" +#include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/barrier.h" @@ -161,6 +162,7 @@ add_texture (texture_t *tx, vulkan_ctx_t *ctx) bspctx_t *bctx = ctx->bsp_context; vulktex_t *tex = tx->render; + tex->texind = bctx->texture_chains.size; DARRAY_APPEND (&bctx->texture_chains, tex); tex->tex_chain = 0; tex->tex_chain_tail = &tex->tex_chain; @@ -259,9 +261,29 @@ clear_textures (vulkan_ctx_t *ctx) bctx->texture_chains.size = 0; } +static VkDescriptorImageInfo base_sampler_info = { }; +static VkDescriptorImageInfo base_image_info = { + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL +}; +static VkWriteDescriptorSet base_sampler_write = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstBinding = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, +}; +static VkWriteDescriptorSet base_image_write = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstBinding = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, +}; + void Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) { + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; + int i; model_t *m; mod_brush_t *brush = &r_worldentity.renderer.model->brush; @@ -284,6 +306,33 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) brush->numsubmodels = 1; // no support for submodels in non-world model register_textures (brush, ctx); } + if (bctx->texture_chains.size > bctx->maxImages) { + Sys_Error ("smart texture handling not implemented, want %zd textures," + "can support %d.", + bctx->texture_chains.size, bctx->maxImages); + } + + VkDescriptorImageInfo samplerInfo[1]; + samplerInfo[0] = base_sampler_info; + samplerInfo[0].sampler = bctx->sampler; + + VkDescriptorImageInfo imageInfo[bctx->maxImages]; + for (unsigned i = 0; i < bctx->maxImages; i++) { + imageInfo[i] = base_image_info; + imageInfo[i].imageView = ctx->default_magenta_array->view; + if (i && i < bctx->texture_chains.size) { + imageInfo[i].imageView = bctx->texture_chains.a[i]->tex->view; + } + } + VkWriteDescriptorSet write[2]; + write[0] = base_sampler_write; + write[0].dstSet = bctx->descriptors; + write[0].pImageInfo = samplerInfo; + write[1] = base_image_write; + write[1].dstSet = bctx->descriptors; + write[1].descriptorCount = bctx->maxImages; + write[1].pImageInfo = imageInfo; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); } static elechain_t * @@ -745,17 +794,6 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) visit_leaf ((mleaf_t *) node); } -static void -bind_view (qfv_bsp_tex tex, VkImageView view, bspframe_t *bframe, - VkCommandBuffer cmd, VkPipelineLayout layout, qfv_devfuncs_t *dfunc) -{ - bframe->imageInfo[tex].imageView = view; - dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 1, - bframe->descriptors + tex - + BSP_BUFFER_INFOS); -} - static void push_transform (vec_t *transform, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) @@ -764,6 +802,15 @@ push_transform (vec_t *transform, VkPipelineLayout layout, 0, 16 * sizeof (float), transform); } +static void +push_texind (int32_t texind, VkPipelineLayout layout, + qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) +{ + dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, + /*FIXME 64*/ 64 + field_offset (fragconst_t, texind), + sizeof (int32_t), &texind); +} + static void push_fragconst (fragconst_t *fragconst, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) @@ -772,15 +819,6 @@ push_fragconst (fragconst_t *fragconst, VkPipelineLayout layout, 64, sizeof (fragconst_t), fragconst);//FIXME 64 } -static void -push_descriptors (int count, VkWriteDescriptorSet *descriptors, - VkPipelineLayout layout, qfv_devfuncs_t *dfunc, - VkCommandBuffer cmd) -{ - dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, count, descriptors); -} - static void draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) @@ -812,21 +850,9 @@ reset_elechain (elechain_t *ec) } } -static VkImageView -get_view (qfv_tex_t *tex, qfv_tex_t *default_tex) -{ - if (tex) { - return tex->view; - } - if (default_tex) { - return default_tex->view; - } - return 0; -} - static void bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, - qfv_renderframe_t *rFrame) + VkPipelineLayout layout, qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -864,14 +890,12 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, VK_INDEX_TYPE_UINT32); - // push VP matrices - dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, - 0, 1, bframe->descriptors + 0); - // push static images - dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - bctx->layout, - 0, 3, bframe->descriptors + 3); + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descrptors (ctx, ctx->curFrame), + bctx->descriptors, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -904,18 +928,8 @@ bsp_begin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], bframe->cmdSet.a[QFV_bspGBuffer]); - //FIXME need per frame matrices - //XXX bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - bframe->imageInfo[0].imageView = 0; // set by tex chain loop - bframe->imageInfo[1].imageView = 0; // set by tex chain loop - bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); - bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, - bctx->default_skysheet); - bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, - bctx->default_skybox); - - bsp_begin_subpass (QFV_bspDepth, bctx->depth, rFrame); - bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, rFrame); + bsp_begin_subpass (QFV_bspDepth, bctx->depth, bctx->layout, rFrame); + bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, bctx->layout, rFrame); } static void @@ -943,15 +957,7 @@ turb_begin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], bframe->cmdSet.a[QFV_bspTurb]); - //FIXME need per frame matrices - //XXX bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - bframe->imageInfo[0].imageView = ctx->default_magenta->view; - bframe->imageInfo[1].imageView = ctx->default_magenta->view; - bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); - bframe->imageInfo[3].imageView = bctx->default_skysheet->view; - bframe->imageInfo[4].imageView = bctx->default_skybox->view; - - bsp_begin_subpass (QFV_bspTurb, bctx->turb, rFrame); + bsp_begin_subpass (QFV_bspTurb, bctx->turb, bctx->layout, rFrame); } static void @@ -1002,20 +1008,10 @@ sky_begin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], bframe->cmdSet.a[QFV_bspSky]); - //FIXME need per frame matrices - //XXX bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - bframe->imageInfo[0].imageView = ctx->default_magenta->view; - bframe->imageInfo[1].imageView = ctx->default_magenta->view; - bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap); - bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex, - bctx->default_skysheet); - bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, - bctx->default_skybox); - if (bctx->skybox_tex) { - bsp_begin_subpass (QFV_bspSky, bctx->skybox, rFrame); + bsp_begin_subpass (QFV_bspSky, bctx->skybox, bctx->layout, rFrame); } else { - bsp_begin_subpass (QFV_bspSky, bctx->skysheet, rFrame); + bsp_begin_subpass (QFV_bspSky, bctx->skysheet, bctx->layout, rFrame); } } @@ -1118,11 +1114,8 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) build_tex_elechain (tex, bctx, bframe); - bframe->imageInfo[0].imageView = get_view (tex->tex, - ctx->default_white); - - push_descriptors (2, bframe->descriptors + 1, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspGBuffer]); + push_texind (tex->texind, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, @@ -1178,11 +1171,8 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) msurface_t *surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { - bind_view (qfv_bsp_texture, - get_view (tex->tex, ctx->default_black), - bframe, - bframe->cmdSet.a[QFV_bspTurb], - bctx->layout, dfunc); + push_texind (tex->texind, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); @@ -1198,9 +1188,8 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - bind_view (qfv_bsp_texture, get_view (tex->tex, ctx->default_black), - bframe, bframe->cmdSet.a[QFV_bspTurb], - bctx->layout, dfunc); + push_texind (tex->texind, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); @@ -1241,11 +1230,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) msurface_t *surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { - bind_view (qfv_bsp_skysheet, - get_view (tex->tex, ctx->default_black), - bframe, - bframe->cmdSet.a[QFV_bspSky], - bctx->layout, dfunc); + push_texind (tex->texind, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); @@ -1261,9 +1247,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black), - bframe, bframe->cmdSet.a[QFV_bspSky], - bctx->layout, dfunc); + push_texind (tex->texind, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); @@ -1385,25 +1370,6 @@ create_default_skys (vulkan_ctx_t *ctx) QFV_PacketSubmit (packet); } -static VkDescriptorBufferInfo base_buffer_info = { - 0, 0, VK_WHOLE_SIZE -}; -static VkDescriptorImageInfo base_image_info = { - 0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -}; -static VkWriteDescriptorSet base_buffer_write = { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 0, 0, 1, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - 0, 0, 0 -}; -static VkWriteDescriptorSet base_image_write = { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 0, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 0, 0, 0 -}; - void Vulkan_Bsp_Init (vulkan_ctx_t *ctx) { @@ -1444,6 +1410,20 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); + //FIXME too many places + __auto_type limits = device->physDev->properties.limits; + bctx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8); + bctx->pool = Vulkan_CreateDescriptorPool (ctx, "quakebsp_pool"); + bctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "quakebsp_set"); + //FIXME kinda dumb + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = bctx->setLayout; + } + __auto_type sets = QFV_AllocateDescriptorSet (device, bctx->pool, layouts); + bctx->descriptors = sets->a[0]; + free (sets); + for (size_t i = 0; i < frames; i++) { __auto_type bframe = &bctx->frames.a[i]; @@ -1459,21 +1439,6 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) va (ctx->va_ctx, "cmd:bsp:%zd:%s", i, bsp_pass_names[j])); } - - for (int j = 0; j < BSP_BUFFER_INFOS; j++) { - bframe->bufferInfo[j] = base_buffer_info; - bframe->descriptors[j] = base_buffer_write; - bframe->descriptors[j].dstBinding = j; - bframe->descriptors[j].pBufferInfo = &bframe->bufferInfo[j]; - } - for (int j = 0; j < BSP_IMAGE_INFOS; j++) { - bframe->imageInfo[j] = base_image_info; - bframe->imageInfo[j].sampler = bctx->sampler; - int k = j + BSP_BUFFER_INFOS; - bframe->descriptors[k] = base_image_write; - bframe->descriptors[k].dstBinding = k; - bframe->descriptors[k].pImageInfo = &bframe->imageInfo[j]; - } } qfvPopDebug (ctx); } From d5b824a47ca39d602c6b11668e24eeebacc720a4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Dec 2021 00:25:50 +0900 Subject: [PATCH 1939/3664] [vulkan] Switch alias pipeline to multi-texture This gets the alias pipeline in line with the bsp pipeline, and thus everything is about as functional as it was before the rework (minus dealing with large texture sets). --- include/QF/Vulkan/qf_alias.h | 18 +- libs/models/alias/vulkan_model_alias.c | 3 + libs/video/renderer/vulkan/qfpipeline.plist | 10 +- .../renderer/vulkan/shader/alias_gbuf.frag | 7 +- libs/video/renderer/vulkan/vulkan_alias.c | 193 +++++++++++------- libs/video/renderer/vulkan/vulkan_bsp.c | 4 +- 6 files changed, 148 insertions(+), 87 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 5d414f175..c42602d39 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -60,11 +60,9 @@ typedef struct qfv_alias_skin_s { VkImageView view; byte colora[4]; byte colorb[4]; + int texind; } qfv_alias_skin_t; -#define ALIAS_BUFFER_INFOS 1 -#define ALIAS_IMAGE_INFOS 1 - typedef enum { QFV_aliasDepth, QFV_aliasGBuffer, @@ -75,20 +73,25 @@ typedef enum { typedef struct aliasframe_s { qfv_cmdbufferset_t cmdSet; - VkDescriptorBufferInfo bufferInfo[ALIAS_BUFFER_INFOS]; - VkDescriptorImageInfo imageInfo[ALIAS_IMAGE_INFOS]; - VkWriteDescriptorSet descriptors[ALIAS_BUFFER_INFOS + ALIAS_IMAGE_INFOS]; } aliasframe_t; typedef struct aliasframeset_s DARRAY_TYPE (aliasframe_t) aliasframeset_t; +typedef struct aliasindset_s + DARRAY_TYPE (unsigned) aliasindset_t; + typedef struct aliasctx_s { aliasframeset_t frames; VkPipeline depth; VkPipeline gbuf; + VkDescriptorSet descriptors; + VkDescriptorPool pool; + VkDescriptorSetLayout setLayout; VkPipelineLayout layout; + unsigned maxImages; VkSampler sampler; + aliasindset_t texindices; } aliasctx_t; struct vulkan_ctx_s; @@ -108,6 +111,9 @@ void Vulkan_Mod_MakeAliasModelDisplayLists (struct mod_alias_ctx_s *alias_ctx, void *_m, int _s, int extra, struct vulkan_ctx_s *ctx); +void Vulkan_AliasAddSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); +void Vulkan_AliasRemoveSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); + void Vulkan_AliasBegin (struct qfv_renderframe_s *rFrame); void Vulkan_DrawAlias (struct entity_s *ent, struct qfv_renderframe_s *rFrame); void Vulkan_AliasEnd (struct qfv_renderframe_s *rFrame); diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index ecaae8a6a..0bda057bb 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -70,6 +70,7 @@ skin_clear (int skin_offset, aliashdr_t *hdr, vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; qfv_alias_skin_t *skin = (qfv_alias_skin_t *) ((byte *) hdr + skin_offset); + Vulkan_AliasRemoveSkin (ctx, skin); dfunc->vkDestroyImageView (device->dev, skin->view, 0); dfunc->vkDestroyImage (device->dev, skin->image, 0); dfunc->vkFreeMemory (device->dev, skin->memory, 0); @@ -221,6 +222,8 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, free (tskin); + Vulkan_AliasAddSkin (ctx, skin); + qfvPopDebug (ctx); return skinpix + skinsize; } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 50015707a..1527843e5 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -99,11 +99,15 @@ }; alias_pool = { flags = 0; - maxSets = "2z * $frames.size"; + maxSets = 1; bindings = ( { - type = uniform_buffer; - descriptorCount = "2z * $frames.size"; + type = sampler; + descriptorCount = 1; + }, + { + type = sampled_image; + descriptorCount = $properties.limits.maxImages; }, ); }; diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index 74c33e58f..28c37fec8 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -7,12 +7,11 @@ layout (set = 1, binding = 1) uniform texture2DArray skins[MaxTextures]; layout (push_constant) uniform PushConstants { layout (offset = 68) - uint base_color; + uint texind; uint colorA; uint colorB; + vec4 base_color; vec4 fog; - vec4 color; - int texind; }; layout (location = 0) in vec2 st; @@ -31,7 +30,7 @@ main (void) vec4 e; int i; vec3 light = vec3 (0); - c = texture (sampler2DArray(skins[texind], samp), vec3 (st, 0)) * unpackUnorm4x8(base_color); + c = texture (sampler2DArray(skins[texind], samp), vec3 (st, 0)) * base_color; c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 1)) * unpackUnorm4x8(colorA); c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 2)) * unpackUnorm4x8(colorB); e = texture (sampler2DArray(skins[texind], samp), vec3 (st, 3)); diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 9a99e307a..8d97ee13c 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -54,6 +54,7 @@ #include "QF/scene/entity.h" #include "QF/Vulkan/qf_alias.h" +#include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" @@ -89,7 +90,6 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; - aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; __auto_type mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); @@ -114,13 +114,6 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, dfunc->vkCmdPushConstants (cmd, actx->layout, VK_SHADER_STAGE_FRAGMENT_BIT, 68, frag_size, frag_constants); - aframe->imageInfo[0].imageView = skin->view; - dfunc->vkCmdPushDescriptorSetKHR (cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, - 0, ALIAS_IMAGE_INFOS, - aframe->descriptors - + ALIAS_BUFFER_INFOS); } dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); } @@ -139,7 +132,13 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) mat4f_t mat; float blend; } vertex_constants; - byte fragment_constants[3][4]; + struct { + uint32_t texind; + byte colorA[4]; + byte colorB[4]; + float base_color[4]; + float fog[4]; + } fragment_constants; if (!(hdr = model->aliashdr)) { hdr = Cache_Get (&model->cache); @@ -155,19 +154,21 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr); skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } - QuatScale (ent->renderer.colormod, 255, fragment_constants[0]); - QuatCopy (skin->colora, fragment_constants[1]); - QuatCopy (skin->colorb, fragment_constants[2]); + fragment_constants.texind = skin->texind; + QuatCopy (ent->renderer.colormod, fragment_constants.base_color); + QuatCopy (skin->colora, fragment_constants.colorA); + QuatCopy (skin->colorb, fragment_constants.colorB); + QuatZero (fragment_constants.fog); emit_commands (aframe->cmdSet.a[QFV_aliasDepth], ent->animation.pose1, ent->animation.pose2, 0, &vertex_constants, 17 * sizeof (float), - fragment_constants, sizeof (fragment_constants), + &fragment_constants, sizeof (fragment_constants), hdr, rFrame); emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], ent->animation.pose1, ent->animation.pose2, skin, &vertex_constants, 17 * sizeof (float), - fragment_constants, sizeof (fragment_constants), + &fragment_constants, sizeof (fragment_constants), hdr, rFrame); } @@ -202,20 +203,15 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, { 0.6, 0.5, 0, 1}); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - //VkDescriptorSet sets[] = { - // aframe->descriptors[0].dstSet, - // aframe->descriptors[1].dstSet, - //}; - //dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - // actx->layout, 0, 2, sets, 0, 0); - dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, - 0, 1, aframe->descriptors + 0); + VkDescriptorSet sets[] = { + Vulkan_Matrix_Descrptors (ctx, ctx->curFrame), + actx->descriptors, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + actx->layout, 0, 2, sets, 0, 0); dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); - //dfunc->vkUpdateDescriptorSets (device->dev, 2, aframe->descriptors, 0, 0); - //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; } @@ -243,9 +239,6 @@ Vulkan_AliasBegin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], aframe->cmdSet.a[QFV_aliasGBuffer]); - //FIXME need per frame matrices - //XXX aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; - alias_begin_subpass (QFV_aliasDepth, actx->depth, rFrame); alias_begin_subpass (QFV_aliasGBuffer, actx->gbuf, rFrame); } @@ -281,29 +274,74 @@ Vulkan_AliasDepthRange (qfv_renderframe_t *rFrame, &viewport); } -static VkDescriptorBufferInfo base_buffer_info = { - 0, 0, VK_WHOLE_SIZE -}; +static VkDescriptorImageInfo base_sampler_info = { }; static VkDescriptorImageInfo base_image_info = { - 0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; -static VkWriteDescriptorSet base_buffer_write = { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 0, 0, 1, - VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - 0, 0, 0 +static VkWriteDescriptorSet base_sampler_write = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstBinding = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, }; static VkWriteDescriptorSet base_image_write = { - VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, - 0, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 0, 0, 0 + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstBinding = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, }; +void +Vulkan_AliasAddSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliasctx_t *actx = ctx->alias_context; + + if (!actx->texindices.size) { + Sys_Error ("ran out of skins (smart texture handling not implemented)"); + } + skin->texind = DARRAY_REMOVE (&actx->texindices); + + VkDescriptorImageInfo imageInfo[1]; + imageInfo[0] = base_image_info; + imageInfo[0].imageView = skin->view; + + VkWriteDescriptorSet write[2]; + write[0] = base_image_write; + write[0].dstSet = actx->descriptors; + write[0].dstArrayElement = skin->texind; + write[0].descriptorCount = 1; + write[0].pImageInfo = imageInfo; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); +} + +void +Vulkan_AliasRemoveSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + aliasctx_t *actx = ctx->alias_context; + + DARRAY_APPEND (&actx->texindices, skin->texind); + + VkDescriptorImageInfo imageInfo[1]; + imageInfo[0] = base_image_info; + imageInfo[0].imageView = ctx->default_magenta_array->view; + + VkWriteDescriptorSet write[2]; + write[0] = base_image_write; + write[0].dstSet = actx->descriptors; + write[0].dstArrayElement = skin->texind; + write[0].descriptorCount = 1; + write[0].pImageInfo = imageInfo; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); +} + void Vulkan_Alias_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; qfvPushDebug (ctx, "alias init"); @@ -320,22 +358,49 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); - /*__auto_type layouts = QFV_AllocDescriptorSetLayoutSet (2 * frames, alloca); - for (size_t i = 0; i < layouts->size / 2; i++) { - __auto_type mats = QFV_GetDescriptorSetLayout (ctx, "alias.matrices"); - __auto_type lights = QFV_GetDescriptorSetLayout (ctx, "alias.lights"); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, - mats, va (ctx->va_ctx, "set_layout:%s:%d", - "alias.matrices", i)); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, - lights, va (ctx->va_ctx, "set_layout:%s:%d", - "alias.lights", i)); - layouts->a[2 * i + 0] = mats; - layouts->a[2 * i + 1] = lights; - }*/ - //__auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool"); + //FIXME too many places + __auto_type limits = device->physDev->properties.limits; + actx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8); + actx->pool = Vulkan_CreateDescriptorPool (ctx, "alias_pool"); + actx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "alias_set"); + //FIXME kinda dumb + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = actx->setLayout; + } + __auto_type sets = QFV_AllocateDescriptorSet (device, actx->pool, layouts); + actx->descriptors = sets->a[0]; + free (sets); + + DARRAY_INIT (&actx->texindices, actx->maxImages); + DARRAY_RESIZE (&actx->texindices, actx->maxImages); + actx->texindices.grow = 0; + actx->texindices.maxSize = actx->maxImages; + for (unsigned i = 0; i < actx->maxImages; i++) { + actx->texindices.a[i] = i; + } + + VkDescriptorImageInfo samplerInfo[1]; + samplerInfo[0] = base_sampler_info; + samplerInfo[0].sampler = actx->sampler; + + VkDescriptorImageInfo imageInfo[actx->maxImages]; + for (unsigned i = 0; i < actx->maxImages; i++) { + imageInfo[i] = base_image_info; + imageInfo[i].imageView = ctx->default_magenta_array->view; + } + VkWriteDescriptorSet write[2]; + write[0] = base_sampler_write; + write[0].dstSet = actx->descriptors; + write[0].pImageInfo = samplerInfo; + write[1] = base_image_write; + write[1].dstSet = actx->descriptors; + write[1].descriptorCount = actx->maxImages; + write[1].pImageInfo = imageInfo; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + + - //__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < frames; i++) { __auto_type aframe = &actx->frames.a[i]; @@ -351,23 +416,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) va (ctx->va_ctx, "cmd:alias:%zd:%s", i, alias_pass_names[j])); } - for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) { - aframe->bufferInfo[j] = base_buffer_info; - aframe->descriptors[j] = base_buffer_write; - //aframe->descriptors[j].dstSet = sets->a[ALIAS_BUFFER_INFOS*i + j]; - aframe->descriptors[j].dstBinding = j; - aframe->descriptors[j].pBufferInfo = &aframe->bufferInfo[j]; - } - for (int j = 0; j < ALIAS_IMAGE_INFOS; j++) { - aframe->imageInfo[j] = base_image_info; - aframe->imageInfo[j].sampler = actx->sampler; - int k = j + ALIAS_BUFFER_INFOS; - aframe->descriptors[k] = base_image_write; - aframe->descriptors[k].dstBinding = k; - aframe->descriptors[k].pImageInfo = &aframe->imageInfo[j]; - } } - //free (sets); qfvPopDebug (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index ce41cfdf2..b52b6db4c 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -890,12 +890,12 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, VK_INDEX_TYPE_UINT32); - VkDescriptorSet set[2] = { + VkDescriptorSet sets[] = { Vulkan_Matrix_Descrptors (ctx, ctx->curFrame), bctx->descriptors, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); + layout, 0, 2, sets, 0, 0); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; From 8c5c39cbe4ed609339d653e089bf7ae1c2e898f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Dec 2021 00:28:57 +0900 Subject: [PATCH 1940/3664] [vulkan] Mix turb full-brights into main color I'd forgotten (when doing the original brush texture loader) that turbulent surfaces were unlit and thus always full-bright, then never wrote the turb shader to take care of it. The best solution seems to be to just mix the two colors in the shader as it will allow turb surfaces to be lit in the future (probably with severely limited light counts due to being a forward renderer). --- libs/video/renderer/vulkan/shader/bsp_turb.frag | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index acce754bf..bee7a6a02 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -48,7 +48,9 @@ main (void) vec4 c = vec4 (0); vec4 e; vec3 t_st = vec3 (warp_st (tl_st.xy, time), 0); + vec3 e_st = vec3 (warp_st (tl_st.xy, time), 1); c = texture (sampler2DArray (textures[texind], samp), t_st); - frag_color = c;//fogBlend (c); + e = texture (sampler2DArray (textures[texind], samp), e_st); + frag_color = c + e;//fogBlend (c); } From 3a17e062dadd3774af7f652d113b953f6a9a4a96 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Dec 2021 14:34:04 +0900 Subject: [PATCH 1941/3664] [renderer] Merge sprite billboarding code As the sw renderer's implementation was the closest to id's, it was used as the model (thus a fair bit of cleanup is still needed). This fixes some incorrect implementations in glsl and gl. --- include/r_internal.h | 3 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/gl/gl_mod_sprite.c | 24 ++--- libs/video/renderer/glsl/glsl_sprite.c | 85 ++------------- libs/video/renderer/r_billboard.c | 134 ++++++++++++++++++++++++ libs/video/renderer/sw/sw_rsprite.c | 105 ++----------------- libs/video/renderer/sw32/sw32_rsprite.c | 105 ++----------------- 7 files changed, 178 insertions(+), 279 deletions(-) create mode 100644 libs/video/renderer/r_billboard.c diff --git a/include/r_internal.h b/include/r_internal.h index dfcab0056..af3e1d645 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -93,4 +93,7 @@ void R_MarkLeaves (void); void GL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette); +int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, + vec3_t bbup, vec3_t bbright, vec3_t bbpn); + #endif//__r_internal_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index c5ff6407a..11f8e343a 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -29,6 +29,7 @@ video_renderer_common_sources = \ libs/video/renderer/font8x8.c \ libs/video/renderer/noisetextures.c \ libs/video/renderer/r_alias.c \ + libs/video/renderer/r_billboard.c \ libs/video/renderer/r_bsp.c \ libs/video/renderer/r_dyn_textures.c \ libs/video/renderer/r_efrag.c \ diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index d25bec868..abd858321 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -105,24 +105,23 @@ static void R_DrawSpriteModel_f (entity_t *e) { float modelalpha, color[4]; - vec4f_t up = {}, right = {}; + vec4f_t cameravec = {}; + vec4f_t up = {}, right = {}, pn = {}; vec4f_t origin, point; - msprite_t *psprite; + msprite_t *sprite = e->renderer.model->cache.data; mspriteframe_t *frame; + origin = Transform_GetWorldPosition (e->transform); + VectorCopy (r_origin, cameravec); + cameravec -= origin; + // don't bother culling, it's just a single polygon without a surface cache frame = R_GetSpriteFrame (e); - psprite = e->renderer.model->cache.data; - if (psprite->type == SPR_ORIENTED) { // bullet marks on walls - up = Transform_Up (e->transform); - right = Transform_Right (e->transform); - } else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) { - up = (vec4f_t) { 0, 0, 1, 0 }; - VectorCopy (vright, right); - } else { // normal sprite - VectorCopy (vup, up); - VectorCopy (vright, right); + if (!R_BillboardFrame (e, sprite->type, &cameravec[0], + &up[0], &right[0], &pn[0])) { + // the orientation is undefined so can't draw the sprite + return; } VectorCopy (e->renderer.colormod, color); @@ -136,7 +135,6 @@ R_DrawSpriteModel_f (entity_t *e) qfglColor4fv (color); - origin = Transform_GetWorldPosition (e->transform); point = origin + frame->down * up + frame->left * right; qfglTexCoord2f (0, 1); diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index a56a2fd83..56fe571f7 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -214,9 +214,9 @@ glsl_R_DrawSprite (entity_t *ent) { msprite_t *sprite = (msprite_t *) ent->renderer.model->cache.data; mspriteframe_t *frame1, *frame2; - float blend, sr, cr, dot; - vec3_t tvec; - vec4f_t svpn = {}, svright = {}, svup = {}, rot; + float blend; + vec4f_t cameravec = {}; + vec4f_t svpn = {}, svright = {}, svup = {}; static quat_t color = { 1, 1, 1, 1}; float vertsa[6][3], vertsb[6][3]; static float uvab[6][4] = { @@ -228,76 +228,14 @@ glsl_R_DrawSprite (entity_t *ent) { 0, 1, 0, 1 }, }; - switch (sprite->type) { - case SPR_FACING_UPRIGHT: - // generate the sprite's exes with svup straight up in worldspace - // and svright perpendicular to r_origin. This will not work if the - // view direction is very close to straight up or down because the - // cross product will be between two nearly parallel vectors and - // starts to approach an undefined staate, so we don't draw if the - // two vectors are less than 1 degree apart - VectorNegate (r_origin, tvec); - VectorNormalize (tvec); - dot = tvec[2]; // same as DotProcut (tvec, svup) because - // svup is 0, 0, 1 - if ((dot > 0.999848) || (dot < -0.99848)) // cos (1 degree) - return; - VectorSet (0, 0, 1, svup); - // CrossProduct (svup, -r_origin, svright) - VectorSet (tvec[1], -tvec[0], 0, svright); - svright = normalf (svright); - // CrossProduct (svright, svup, svpn); - VectorSet (-svright[1], svright[0], 0, svpn); - break; - case SPR_VP_PARALLEL: - // generate the prite's axes completely parallel to the viewplane. - // There are no problem situations, because the prite is always in - // the same position relative to the viewer. - VectorCopy (vup, svup); - VectorCopy (vright, svright); - VectorCopy (vpn, svpn); - break; - case SPR_VP_PARALLEL_UPRIGHT: - // generate the sprite's axes with svup straight up in worldspace, - // and svright parallel to the viewplane. This will not work if the - // view diretion iss very close to straight up or down because the - // cross prodcut will be between two nearly parallel vectors and - // starts to approach an undefined state, so we don't draw if the - // two vectros are less that 1 degree apart - dot = vpn[2]; - if ((dot > 0.999848) || (dot < -0.99848)) // cos (1 degree) - return; - VectorSet (0, 0, 1, svup); - // CrossProduct (svup, -r_origin, svright) - VectorSet (vpn[1], -vpn[0], 0, svright); - svright = normalf (svright); - // CrossProduct (svright, svup, svpn); - VectorSet (-svright[1], svright[0], 0, svpn); - break; - case SPR_ORIENTED: - // generate the prite's axes according to the sprite's world - // orientation - svup = Transform_Up (ent->transform); - svright = Transform_Right (ent->transform); - svpn = Transform_Forward (ent->transform); - break; - case SPR_VP_PARALLEL_ORIENTED: - // generate the sprite's axes parallel to the viewplane, but - // rotated in that plane round the center according to the sprite - // entity's roll angle. Thus svpn stays the same, but svright and - // svup rotate - rot = Transform_GetLocalRotation (ent->transform); - //FIXME assumes the entity is only rolled - sr = 2 * rot[0] * rot[3]; - cr = rot[3] * rot[3] - rot[0] * rot[0]; - VectorCopy (vpn, svpn); - VectorScale (vright, cr, svright); - VectorMultAdd (svright, sr, vup, svright); - VectorScale (vup, cr, svup); - VectorMultAdd (svup, -sr, vright, svup); - break; - default: - Sys_Error ("R_DrawSprite: Bad sprite type %d", sprite->type); + vec4f_t origin = Transform_GetWorldPosition (ent->transform); + VectorCopy (r_origin, cameravec); + cameravec -= origin; + + if (!R_BillboardFrame (ent, sprite->type, &cameravec[0], + &svup[0], &svright[0], &svpn[0])) { + // the orientation is undefined so can't draw the sprite + return; } R_GetSpriteFrames (ent, sprite, &frame1, &frame2, &blend); @@ -312,7 +250,6 @@ glsl_R_DrawSprite (entity_t *ent) qfeglVertexAttrib4fv (quake_sprite.colorb.location, color); qfeglVertexAttrib1f (quake_sprite.blend.location, blend); - vec4f_t origin = Transform_GetWorldPosition (ent->transform); make_quad (frame1, origin, svpn, svright, svup, vertsa); make_quad (frame2, origin, svpn, svright, svup, vertsb); diff --git a/libs/video/renderer/r_billboard.c b/libs/video/renderer/r_billboard.c new file mode 100644 index 000000000..9df63be8a --- /dev/null +++ b/libs/video/renderer/r_billboard.c @@ -0,0 +1,134 @@ +/* + r_billboard.c + + Billboard frame setup + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include "QF/render.h" +#include "QF/sys.h" + +#include "QF/scene/entity.h" + +#include "r_internal.h" + + +int +R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, + vec3_t bbup, vec3_t bbright, vec3_t bbpn) +{ + vec3_t tvec; + float dot; + + switch (orientation) { + case SPR_FACING_UPRIGHT: + // generate the sprite's axes, with vup straight up in worldspace, + // and bbright perpendicular to cameravec. This will not work if + // the camera origin is directly above the entity origin + // (cameravec is straight up or down), because the cross product + // will be between two nearly parallel vectors and starts to + // approach an undefined state, so we don't draw if the two + // vectors are less than 1 degree apart + VectorNegate (cameravec, tvec); + VectorNormalize (tvec); + dot = tvec[2]; // same as DotProduct (tvec, bbup) because + // bbup is 0, 0, 1 + if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) + return 0; + VectorSet (0, 0, 1, bbup); + //CrossProduct(bbup, -cameravec, bbright) + VectorSet (tvec[1], -tvec[0], 0, bbright); + VectorNormalize (bbright); + //CrossProduct (bbright, bbup, bbpn) + VectorSet (-bbright[1], bbright[0], 0, bbpn); + break; + case SPR_VP_PARALLEL: + // generate the sprite's axes, completely parallel to the + // viewplane. There are no problem situations, because the + // sprite is always in the same orientation relative to the viewer + VectorCopy (vup, bbup); + VectorCopy (vright, bbright); + VectorCopy (vpn, bbpn); + break; + case SPR_VP_PARALLEL_UPRIGHT: + // generate the sprite's axes, with vup straight up in worldspace, + // and bbright parallel to the viewplane. + // This will not work if the view direction is very close to + // straight up or down, because the cross product will be between + // two nearly parallel vectors and starts to approach an undefined + // state, so we don't draw if the two vectors are less than 1 + // degree apart + dot = vpn[2]; // same as DotProduct (vpn, bbup) because + // bbup is 0, 0, 1 + if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = + return 0; + VectorSet (0, 0, 1, bbup); + //CrossProduct(bbup, vpn, bbright) + VectorSet (vpn[1], -vpn[0], 0, bbright); + VectorNormalize (bbright); + //CrossProduct (bbright, bbup, bbpn) + VectorSet (-bbright[1], bbright[0], 0, bbpn); + break; + case SPR_ORIENTED: + { + // generate the sprite's axes, according to the sprite's world + // orientation + mat4f_t mat; + Transform_GetWorldMatrix (ent->transform, mat); + VectorCopy (mat[0], bbpn); + VectorNegate (mat[1], bbright); + VectorCopy (mat[2], bbup); + } + break; + case SPR_VP_PARALLEL_ORIENTED: + { + // generate the sprite's axes, parallel to the viewplane, but + // rotated in that plane around the center according to the + // sprite entity's roll angle. So vpn stays the same, but + // vright and vup rotate + vec4f_t rot = Transform_GetLocalRotation (ent->transform); + // FIXME needs proper testing (need to find, make, or fake a + // parallel oriented sprite) + rot = qmulf (r_refdef.viewrotation, rot); + QuatMultVec (&rot[0], vpn, bbpn); + QuatMultVec (&rot[0], vright, bbright); + QuatMultVec (&rot[0], vup, bbup); + } + break; + default: + Sys_Error ("R_BillboardFrame: Bad orientation %d", orientation); + } + return 1; +} diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 82c7b0d1b..610b078dd 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -284,109 +284,22 @@ R_GetSpriteframe (msprite_t *psprite) void R_DrawSprite (void) { - int i; - msprite_t *psprite; - vec3_t tvec; - float dot, sr, cr; + msprite_t *sprite = currententity->renderer.model->cache.data; - psprite = currententity->renderer.model->cache.data; - - r_spritedesc.pspriteframe = R_GetSpriteframe (psprite); + r_spritedesc.pspriteframe = R_GetSpriteframe (sprite); sprite_width = r_spritedesc.pspriteframe->width; sprite_height = r_spritedesc.pspriteframe->height; - // TODO: make this caller-selectable - if (psprite->type == SPR_FACING_UPRIGHT) { - // generate the sprite's axes, with vup straight up in worldspace, and - // r_spritedesc.vright perpendicular to modelorg. - // This will not work if the view direction is very close to straight - // up or down, because the cross product will be between two nearly - // parallel vectors and starts to approach an undefined state, so we - // don't draw if the two vectors are less than 1 degree apart - tvec[0] = -modelorg[0]; - tvec[1] = -modelorg[1]; - tvec[2] = -modelorg[2]; - VectorNormalize (tvec); - dot = tvec[2]; // same as DotProduct (tvec, - // r_spritedesc.vup) because - // r_spritedesc.vup is 0, 0, 1 - if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = - // 0.999848 - return; - r_spritedesc.vup[0] = 0; - r_spritedesc.vup[1] = 0; - r_spritedesc.vup[2] = 1; - r_spritedesc.vright[0] = tvec[1]; - //CrossProduct(r_spritedesc.vup, -modelorg, r_spritedesc.vright) - r_spritedesc.vright[1] = -tvec[0]; - r_spritedesc.vright[2] = 0; - VectorNormalize (r_spritedesc.vright); - r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; - r_spritedesc.vpn[1] = r_spritedesc.vright[0]; - r_spritedesc.vpn[2] = 0; - //CrossProduct (r_spritedesc.vright, r_spritedesc.vup, r_spritedesc.vpn) - } else if (psprite->type == SPR_VP_PARALLEL) { - // generate the sprite's axes, completely parallel to the viewplane. - // There are no problem situations, because the sprite is always in the - // same position relative to the viewer - for (i = 0; i < 3; i++) { - r_spritedesc.vup[i] = vup[i]; - r_spritedesc.vright[i] = vright[i]; - r_spritedesc.vpn[i] = vpn[i]; - } - } else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) { - // generate the sprite's axes, with vup straight up in worldspace, and - // r_spritedesc.vright parallel to the viewplane. - // This will not work if the view direction is very close to straight - // up or down, because the cross product will be between two nearly - // parallel vectors and starts to approach an undefined state, so we - // don't draw if the two vectors are less than 1 degree apart - dot = vpn[2]; // same as DotProduct (vpn, - // r_spritedesc.vup) because - // r_spritedesc.vup is 0, 0, 1 - if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = - // 0.999848 - return; - r_spritedesc.vup[0] = 0; - r_spritedesc.vup[1] = 0; - r_spritedesc.vup[2] = 1; - r_spritedesc.vright[0] = vpn[1]; - //CrossProduct (r_spritedesc.vup, vpn, - r_spritedesc.vright[1] = -vpn[0]; // r_spritedesc.vright) - r_spritedesc.vright[2] = 0; - VectorNormalize (r_spritedesc.vright); - r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; - r_spritedesc.vpn[1] = r_spritedesc.vright[0]; - r_spritedesc.vpn[2] = 0; - //CrossProduct (r_spritedesc.vright, r_spritedesc.vup, r_spritedesc.vpn) - } else if (psprite->type == SPR_ORIENTED) { - // generate the sprite's axes, according to the sprite's world - // orientation - mat4f_t mat; - Transform_GetWorldMatrix (currententity->transform, mat); - VectorCopy (mat[0], r_spritedesc.vpn); - VectorNegate (mat[1], r_spritedesc.vright); - VectorCopy (mat[2], r_spritedesc.vup); - } else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) { - // generate the sprite's axes, parallel to the viewplane, but rotated - // in that plane around the center according to the sprite entity's - // roll angle. So vpn stays the same, but vright and vup rotate - vec4f_t rot = Transform_GetLocalRotation (currententity->transform); - //FIXME assumes the entity is only rolled - sr = 2 * rot[0] * rot[3]; - cr = rot[3] * rot[3] - rot[0] * rot[0]; - - for (i = 0; i < 3; i++) { - r_spritedesc.vpn[i] = vpn[i]; - r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr; - r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr; - } - } else { - Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type); + if (!R_BillboardFrame (currententity, sprite->type, modelorg, + r_spritedesc.vup, + r_spritedesc.vright, + r_spritedesc.vpn)) { + // the orientation is undefined so can't draw the sprite + return; } - R_RotateSprite (psprite->beamlength); + R_RotateSprite (sprite->beamlength); R_SetupAndDrawSprite (); } diff --git a/libs/video/renderer/sw32/sw32_rsprite.c b/libs/video/renderer/sw32/sw32_rsprite.c index 153fba1fb..da4d5687a 100644 --- a/libs/video/renderer/sw32/sw32_rsprite.c +++ b/libs/video/renderer/sw32/sw32_rsprite.c @@ -280,109 +280,22 @@ R_GetSpriteframe (msprite_t *psprite) void sw32_R_DrawSprite (void) { - int i; - msprite_t *psprite; - vec3_t tvec; - float dot, sr, cr; + msprite_t *sprite = currententity->renderer.model->cache.data; - psprite = currententity->renderer.model->cache.data; - - sw32_r_spritedesc.pspriteframe = R_GetSpriteframe (psprite); + sw32_r_spritedesc.pspriteframe = R_GetSpriteframe (sprite); sprite_width = sw32_r_spritedesc.pspriteframe->width; sprite_height = sw32_r_spritedesc.pspriteframe->height; - // TODO: make this caller-selectable - if (psprite->type == SPR_FACING_UPRIGHT) { - // generate the sprite's axes, with vup straight up in worldspace, and - // sw32_r_spritedesc.vright perpendicular to modelorg. - // This will not work if the view direction is very close to straight - // up or down, because the cross product will be between two nearly - // parallel vectors and starts to approach an undefined state, so we - // don't draw if the two vectors are less than 1 degree apart - tvec[0] = -modelorg[0]; - tvec[1] = -modelorg[1]; - tvec[2] = -modelorg[2]; - VectorNormalize (tvec); - dot = tvec[2]; // same as DotProduct (tvec, - // sw32_r_spritedesc.vup) because - // sw32_r_spritedesc.vup is 0, 0, 1 - if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = - // 0.999848 - return; - sw32_r_spritedesc.vup[0] = 0; - sw32_r_spritedesc.vup[1] = 0; - sw32_r_spritedesc.vup[2] = 1; - sw32_r_spritedesc.vright[0] = tvec[1]; - //CrossProduct(sw32_r_spritedesc.vup, -modelorg, sw32_r_spritedesc.vright) - sw32_r_spritedesc.vright[1] = -tvec[0]; - sw32_r_spritedesc.vright[2] = 0; - VectorNormalize (sw32_r_spritedesc.vright); - sw32_r_spritedesc.vpn[0] = -sw32_r_spritedesc.vright[1]; - sw32_r_spritedesc.vpn[1] = sw32_r_spritedesc.vright[0]; - sw32_r_spritedesc.vpn[2] = 0; - //CrossProduct (sw32_r_spritedesc.vright, sw32_r_spritedesc.vup, sw32_r_spritedesc.vpn) - } else if (psprite->type == SPR_VP_PARALLEL) { - // generate the sprite's axes, completely parallel to the viewplane. - // There are no problem situations, because the sprite is always in the - // same position relative to the viewer - for (i = 0; i < 3; i++) { - sw32_r_spritedesc.vup[i] = vup[i]; - sw32_r_spritedesc.vright[i] = vright[i]; - sw32_r_spritedesc.vpn[i] = vpn[i]; - } - } else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) { - // generate the sprite's axes, with vup straight up in worldspace, and - // sw32_r_spritedesc.vright parallel to the viewplane. - // This will not work if the view direction is very close to straight - // up or down, because the cross product will be between two nearly - // parallel vectors and starts to approach an undefined state, so we - // don't draw if the two vectors are less than 1 degree apart - dot = vpn[2]; // same as DotProduct (vpn, - // sw32_r_spritedesc.vup) because - // sw32_r_spritedesc.vup is 0, 0, 1 - if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = - // 0.999848 - return; - sw32_r_spritedesc.vup[0] = 0; - sw32_r_spritedesc.vup[1] = 0; - sw32_r_spritedesc.vup[2] = 1; - sw32_r_spritedesc.vright[0] = vpn[1]; - //CrossProduct (sw32_r_spritedesc.vup, vpn, - sw32_r_spritedesc.vright[1] = -vpn[0]; // sw32_r_spritedesc.vright) - sw32_r_spritedesc.vright[2] = 0; - VectorNormalize (sw32_r_spritedesc.vright); - sw32_r_spritedesc.vpn[0] = -sw32_r_spritedesc.vright[1]; - sw32_r_spritedesc.vpn[1] = sw32_r_spritedesc.vright[0]; - sw32_r_spritedesc.vpn[2] = 0; - //CrossProduct (sw32_r_spritedesc.vright, sw32_r_spritedesc.vup, sw32_r_spritedesc.vpn) - } else if (psprite->type == SPR_ORIENTED) { - // generate the sprite's axes, according to the sprite's world - // orientation - mat4f_t mat; - Transform_GetWorldMatrix (currententity->transform, mat); - VectorCopy (mat[0], r_spritedesc.vpn); - VectorNegate (mat[1], r_spritedesc.vright); - VectorCopy (mat[2], r_spritedesc.vup); - } else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) { - // generate the sprite's axes, parallel to the viewplane, but rotated - // in that plane around the center according to the sprite entity's - // roll angle. So vpn stays the same, but vright and vup rotate - vec4f_t rot = Transform_GetLocalRotation (currententity->transform); - //FIXME assumes the entity is only rolled - sr = 2 * rot[0] * rot[3]; - cr = rot[3] * rot[3] - rot[0] * rot[0]; - - for (i = 0; i < 3; i++) { - sw32_r_spritedesc.vpn[i] = vpn[i]; - sw32_r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr; - sw32_r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr; - } - } else { - Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type); + if (!R_BillboardFrame (currententity, sprite->type, modelorg, + r_spritedesc.vup, + r_spritedesc.vright, + r_spritedesc.vpn)) { + // the orientation is undefined so can't draw the sprite + return; } - R_RotateSprite (psprite->beamlength); + R_RotateSprite (sprite->beamlength); R_SetupAndDrawSprite (); } From 1df3c2eea06c3431ff50509b44a8245094361433 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Dec 2021 14:54:18 +0900 Subject: [PATCH 1942/3664] [renderer] Make R_BillboarFrame's comments true While they weren't entirely false, they were overly verbose and thus clouded the point. --- libs/video/renderer/r_billboard.c | 42 +++++++++++-------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/libs/video/renderer/r_billboard.c b/libs/video/renderer/r_billboard.c index 9df63be8a..d66d954ad 100644 --- a/libs/video/renderer/r_billboard.c +++ b/libs/video/renderer/r_billboard.c @@ -54,17 +54,12 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, switch (orientation) { case SPR_FACING_UPRIGHT: - // generate the sprite's axes, with vup straight up in worldspace, - // and bbright perpendicular to cameravec. This will not work if - // the camera origin is directly above the entity origin - // (cameravec is straight up or down), because the cross product - // will be between two nearly parallel vectors and starts to - // approach an undefined state, so we don't draw if the two - // vectors are less than 1 degree apart + // the billboard has its up vector parallel with world up, and + // its right vector perpendicular to cameravec. + // Undefined if the camera is too close to the entity. VectorNegate (cameravec, tvec); VectorNormalize (tvec); - dot = tvec[2]; // same as DotProduct (tvec, bbup) because - // bbup is 0, 0, 1 + dot = tvec[2]; // DotProduct (tvec, world up) if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) return 0; VectorSet (0, 0, 1, bbup); @@ -75,24 +70,17 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, VectorSet (-bbright[1], bbright[0], 0, bbpn); break; case SPR_VP_PARALLEL: - // generate the sprite's axes, completely parallel to the - // viewplane. There are no problem situations, because the - // sprite is always in the same orientation relative to the viewer + // the billboard always has the same orientation as the camera VectorCopy (vup, bbup); VectorCopy (vright, bbright); VectorCopy (vpn, bbpn); break; case SPR_VP_PARALLEL_UPRIGHT: - // generate the sprite's axes, with vup straight up in worldspace, - // and bbright parallel to the viewplane. - // This will not work if the view direction is very close to - // straight up or down, because the cross product will be between - // two nearly parallel vectors and starts to approach an undefined - // state, so we don't draw if the two vectors are less than 1 - // degree apart - dot = vpn[2]; // same as DotProduct (vpn, bbup) because - // bbup is 0, 0, 1 - if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = + // the billboar has its up vector parallel with world up, and + // its right vector parallel with the view plane. + // Undefined if the camera is looking straight up or down. + dot = vpn[2]; // DotProduct (vpn, world up) + if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) return 0; VectorSet (0, 0, 1, bbup); //CrossProduct(bbup, vpn, bbright) @@ -103,8 +91,8 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, break; case SPR_ORIENTED: { - // generate the sprite's axes, according to the sprite's world - // orientation + // The billboard's orientation is fully specified by the + // entity's orientation. mat4f_t mat; Transform_GetWorldMatrix (ent->transform, mat); VectorCopy (mat[0], bbpn); @@ -114,10 +102,8 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, break; case SPR_VP_PARALLEL_ORIENTED: { - // generate the sprite's axes, parallel to the viewplane, but - // rotated in that plane around the center according to the - // sprite entity's roll angle. So vpn stays the same, but - // vright and vup rotate + // The billboard is rotated relative to the camera using + // the entity's local rotation. vec4f_t rot = Transform_GetLocalRotation (ent->transform); // FIXME needs proper testing (need to find, make, or fake a // parallel oriented sprite) From 0a5981878bff8e03796a583594d3f326a1510a1f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Dec 2021 17:05:40 +0900 Subject: [PATCH 1943/3664] [sprite] Clean up field names and casting No wonder I hated the sprite code: I couldn't see the code for all the casts (and hungarian warts). --- include/QF/model.h | 8 ++- libs/models/sprite/glsl_model_sprite.c | 4 +- libs/models/sprite/model_sprite.c | 91 +++++++++++-------------- libs/video/renderer/gl/gl_mod_sprite.c | 4 +- libs/video/renderer/glsl/glsl_sprite.c | 6 +- libs/video/renderer/sw/sw_rsprite.c | 4 +- libs/video/renderer/sw32/sw32_rsprite.c | 4 +- 7 files changed, 56 insertions(+), 65 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index bc0b8ab22..0efd7be00 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -297,16 +297,18 @@ typedef struct { typedef struct { spriteframetype_t type; - mspriteframe_t *frameptr; + union { + mspriteframe_t *frame; + mspritegroup_t *group; + }; } mspriteframedesc_t; typedef struct { int type; int maxwidth; int maxheight; + float beamlength; int numframes; - float beamlength; // remove? - void *cachespot; // remove? mspriteframedesc_t frames[1]; } msprite_t; diff --git a/libs/models/sprite/glsl_model_sprite.c b/libs/models/sprite/glsl_model_sprite.c index b5781124f..ae1f12a10 100644 --- a/libs/models/sprite/glsl_model_sprite.c +++ b/libs/models/sprite/glsl_model_sprite.c @@ -58,10 +58,10 @@ glsl_sprite_clear (model_t *m, void *data) m->cache.data = 0; for (i = 0; i < sprite->numframes; i++) { if (sprite->frames[i].type == SPR_SINGLE) { - frame = sprite->frames[i].frameptr; + frame = sprite->frames[i].frame; GLSL_ReleaseTexture (frame->gl_texturenum); } else { - group = (mspritegroup_t *) sprite->frames[i].frameptr; + group = sprite->frames[i].group; for (j = 0; j < group->numframes; j++) { frame = group->frames[j]; GLSL_ReleaseTexture (frame->gl_texturenum); diff --git a/libs/models/sprite/model_sprite.c b/libs/models/sprite/model_sprite.c index ea8432fb4..a38d66dfa 100644 --- a/libs/models/sprite/model_sprite.c +++ b/libs/models/sprite/model_sprite.c @@ -42,90 +42,79 @@ #include "mod_internal.h" static void * -Mod_LoadSpriteFrame (model_t *mod, void *pin, mspriteframe_t **ppframe, +Mod_LoadSpriteFrame (model_t *mod, void *pin, mspriteframe_t **frame, int framenum) { - dspriteframe_t *pinframe; + dspriteframe_t *in_frame; int width, height, size, origin[2]; - mspriteframe_t *pspriteframe; - pinframe = (dspriteframe_t *) pin; + in_frame = (dspriteframe_t *) pin; - width = LittleLong (pinframe->width); - height = LittleLong (pinframe->height); + width = LittleLong (in_frame->width); + height = LittleLong (in_frame->height); size = width * height; - pspriteframe = Hunk_AllocName (0, sizeof (mspriteframe_t) + size, - mod->name); + *frame = Hunk_AllocName (0, sizeof (mspriteframe_t) + size, mod->name); - memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); + (*frame)->width = width; + (*frame)->height = height; + origin[0] = LittleLong (in_frame->origin[0]); + origin[1] = LittleLong (in_frame->origin[1]); - *ppframe = pspriteframe; + (*frame)->up = origin[1]; + (*frame)->down = origin[1] - height; + (*frame)->left = origin[0]; + (*frame)->right = width + origin[0]; - pspriteframe->width = width; - pspriteframe->height = height; - origin[0] = LittleLong (pinframe->origin[0]); - origin[1] = LittleLong (pinframe->origin[1]); + memcpy ((*frame)->pixels, (byte *) (in_frame + 1), size); - pspriteframe->up = origin[1]; - pspriteframe->down = origin[1] - height; - pspriteframe->left = origin[0]; - pspriteframe->right = width + origin[0]; + m_funcs->Mod_SpriteLoadTexture (mod, *frame, framenum); - memcpy (pspriteframe->pixels, (byte *) (pinframe + 1), size); - - m_funcs->Mod_SpriteLoadTexture (mod, pspriteframe, framenum); - - return (void *) ((byte *) pinframe + sizeof (dspriteframe_t) + size); + return (void *) ((byte *) in_frame + sizeof (dspriteframe_t) + size); } static void * -Mod_LoadSpriteGroup (model_t *mod, void *pin, mspriteframe_t **ppframe, +Mod_LoadSpriteGroup (model_t *mod, void *pin, mspritegroup_t **group, int framenum) { - dspritegroup_t *pingroup; - dspriteinterval_t *pin_intervals; - float *poutintervals; + dspritegroup_t *in_group; + dspriteinterval_t *in_intervals; + float *intervals; int numframes, i; - mspritegroup_t *pspritegroup; - void *ptemp; + void *temp; - pingroup = (dspritegroup_t *) pin; + in_group = (dspritegroup_t *) pin; - numframes = LittleLong (pingroup->numframes); + numframes = LittleLong (in_group->numframes); - pspritegroup = Hunk_AllocName (0, field_offset (mspritegroup_t, - frames[numframes]), - mod->name); + int size = field_offset (mspritegroup_t, frames[numframes]); + *group = Hunk_AllocName (0, size, mod->name); - pspritegroup->numframes = numframes; + (*group)->numframes = numframes; - *ppframe = (mspriteframe_t *) pspritegroup; + in_intervals = (dspriteinterval_t *) (in_group + 1); - pin_intervals = (dspriteinterval_t *) (pingroup + 1); + intervals = Hunk_AllocName (0, numframes * sizeof (float), mod->name); - poutintervals = Hunk_AllocName (0, numframes * sizeof (float), mod->name); - - pspritegroup->intervals = poutintervals; + (*group)->intervals = intervals; for (i = 0; i < numframes; i++) { - *poutintervals = LittleFloat (pin_intervals->interval); - if (*poutintervals <= 0.0) + *intervals = LittleFloat (in_intervals->interval); + if (*intervals <= 0.0) Sys_Error ("Mod_LoadSpriteGroup: interval<=0"); - poutintervals++; - pin_intervals++; + intervals++; + in_intervals++; } - ptemp = (void *) pin_intervals; + temp = (void *) in_intervals; for (i = 0; i < numframes; i++) { - ptemp = - Mod_LoadSpriteFrame (mod, ptemp, &pspritegroup->frames[i], - framenum * 100 + i); + temp = Mod_LoadSpriteFrame (mod, temp, &(*group)->frames[i], + framenum * 100 + i); } - return ptemp; + return temp; } void @@ -180,11 +169,11 @@ Mod_LoadSpriteModel (model_t *mod, void *buffer) if (frametype == SPR_SINGLE) { pframetype = (dspriteframetype_t *) Mod_LoadSpriteFrame (mod, pframetype + 1, - &psprite->frames[i].frameptr, i); + &psprite->frames[i].frame, i); } else { pframetype = (dspriteframetype_t *) Mod_LoadSpriteGroup (mod, pframetype + 1, - &psprite->frames[i].frameptr, i); + &psprite->frames[i].group, i); } } diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index abd858321..913234776 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -77,9 +77,9 @@ R_GetSpriteFrame (entity_t *ent) } if (psprite->frames[frame].type == SPR_SINGLE) { - pspriteframe = psprite->frames[frame].frameptr; + pspriteframe = psprite->frames[frame].frame; } else { - pspritegroup = (mspritegroup_t *) psprite->frames[frame].frameptr; + pspritegroup = psprite->frames[frame].group; pintervals = pspritegroup->intervals; numframes = pspritegroup->numframes; fullinterval = pintervals[numframes - 1]; diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 56fe571f7..71f3c08f8 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -152,7 +152,7 @@ R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, frame_interval = 0.1; pose = framenum; } else { - group = (mspritegroup_t *) framedesc->frameptr; + group = framedesc->group; intervals = group->intervals; numframes = group->numframes; fullinterval = intervals[numframes - 1]; @@ -177,8 +177,8 @@ R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, *frame1 = group->frames[animation->pose1]; *frame2 = group->frames[animation->pose2]; } else { - *frame1 = sprite->frames[animation->pose1].frameptr; - *frame2 = sprite->frames[animation->pose2].frameptr; + *frame1 = sprite->frames[animation->pose1].frame; + *frame2 = sprite->frames[animation->pose2].frame; } } diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 610b078dd..88b9c7782 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -256,9 +256,9 @@ R_GetSpriteframe (msprite_t *psprite) } if (psprite->frames[frame].type == SPR_SINGLE) { - pspriteframe = psprite->frames[frame].frameptr; + pspriteframe = psprite->frames[frame].frame; } else { - pspritegroup = (mspritegroup_t *) psprite->frames[frame].frameptr; + pspritegroup = psprite->frames[frame].group; pintervals = pspritegroup->intervals; numframes = pspritegroup->numframes; fullinterval = pintervals[numframes - 1]; diff --git a/libs/video/renderer/sw32/sw32_rsprite.c b/libs/video/renderer/sw32/sw32_rsprite.c index da4d5687a..dc6e4a340 100644 --- a/libs/video/renderer/sw32/sw32_rsprite.c +++ b/libs/video/renderer/sw32/sw32_rsprite.c @@ -252,9 +252,9 @@ R_GetSpriteframe (msprite_t *psprite) } if (psprite->frames[frame].type == SPR_SINGLE) { - pspriteframe = psprite->frames[frame].frameptr; + pspriteframe = psprite->frames[frame].frame; } else { - pspritegroup = (mspritegroup_t *) psprite->frames[frame].frameptr; + pspritegroup = psprite->frames[frame].group; pintervals = pspritegroup->intervals; numframes = pspritegroup->numframes; fullinterval = pintervals[numframes - 1]; From 39c020908c1d52f3020f4efa7b86a6c54c76fe50 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Dec 2021 09:07:43 +0900 Subject: [PATCH 1944/3664] [zone] Return the pointer to the global hunk In trying to reduce unnecessary memsets when loading files, I found that Hunk_RawAllocName already had nonnull on it, so quakefs needed to know the hunk it was to use. It seemed much better to to go this way (first step in what is likely to be a lengthy process) than backtracking a little and removing the nonnull attribute. --- include/QF/zone.h | 5 ++--- libs/util/zone.c | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/QF/zone.h b/include/QF/zone.h index 93dbc8089..b19aef350 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -91,8 +91,9 @@ ///@{ typedef struct memzone_s memzone_t; +typedef struct memhunk_s memhunk_t; -void Memory_Init (void *buf, size_t size); +memhunk_t *Memory_Init (void *buf, size_t size); void Z_ClearZone (memzone_t *zone, size_t size, size_t zone_offset, size_t ele_size); @@ -106,8 +107,6 @@ void Z_SetError (memzone_t *zone, void (*err) (void *data, const char *msg), void *data); void Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size); -typedef struct memhunk_s memhunk_t; - memhunk_t *Hunk_Init (void *buf, size_t size); void Hunk_Print (memhunk_t *hunk, qboolean all); void Hunk_Check (memhunk_t *hunk); diff --git a/libs/util/zone.c b/libs/util/zone.c index a2b68d754..d436d15a7 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -1238,9 +1238,10 @@ Hunk_Init (void *buf, size_t size) return hunk; } -VISIBLE void +VISIBLE memhunk_t * Memory_Init (void *buf, size_t size) { global_hunk = Hunk_Init (buf, size); Cache_Init (); + return global_hunk; } From 2086125e0b3d61f1f286a1db5e30c1365822a23b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Dec 2021 09:13:39 +0900 Subject: [PATCH 1945/3664] [quakefs] Take in the pointer to the global hunk This is needed for cleaning up excess memsets when loading files because Hunk_RawAllocName has nonnull on its hunk pointer (as the rest of the hunk functions really should, but not just yet). --- include/QF/quakefs.h | 4 +++- libs/audio/test/testsound.c | 4 ++-- libs/util/quakefs.c | 5 ++++- nq/include/game.h | 3 ++- nq/source/game.c | 4 ++-- nq/source/host.c | 9 +++++---- qtv/source/qtv.c | 8 ++++---- qw/source/cl_main.c | 9 +++++---- qw/source/sv_main.c | 8 ++++---- ruamoko/qwaq/builtins/qwaq-bi.c | 4 ++-- ruamoko/qwaq/builtins/qwaq.c | 5 +++-- ruamoko/qwaq/qwaq.h | 3 ++- 12 files changed, 38 insertions(+), 28 deletions(-) diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index 761997eea..064193ce9 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -107,6 +107,7 @@ extern int qfs_filesize; struct cache_user_s; struct dstring_s; +struct memhunk_s; /** Initialize the Quake Filesystem. @@ -114,13 +115,14 @@ struct dstring_s; \c fs_dirconf Cvars. It then loads the \ref dirconf and parses the \c -game command line option. + \param hunk Memory pool to use for hunk-based allocations. \param game The game type used for searching the directory configuration. Currently, this is \"qw\" for quakeworld clients and servers, and one of \"nq\", \"hexen\", \"rogue\" or \"abyss\" for the netquake clients and servers. */ -void QFS_Init (const char *game); +void QFS_Init (struct memhunk_s *hunk, const char *game); /** Change the current game directory. diff --git a/libs/audio/test/testsound.c b/libs/audio/test/testsound.c index ce157c067..1af4730c1 100644 --- a/libs/audio/test/testsound.c +++ b/libs/audio/test/testsound.c @@ -68,9 +68,9 @@ init (void) COM_ParseConfig (testsound_cbuf); Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); - Memory_Init (Sys_Alloc (MEMSIZE), MEMSIZE); + memhunk_t *hunk = Memory_Init (Sys_Alloc (MEMSIZE), MEMSIZE); - QFS_Init ("qw"); + QFS_Init (hunk, "qw"); PI_Init (); S_Init_Cvars (); diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 34d4988f9..7ca9f8cab 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -122,6 +122,7 @@ int fnmatch (const char *__pattern, const char *__string, int __flags); // QUAKE FILESYSTEM +static memhunk_t *qfs_hunk; static cvar_t *fs_userpath; static cvar_t *fs_sharepath; static cvar_t *fs_dirconf; @@ -1427,10 +1428,12 @@ qfs_shutdown (void *data) } VISIBLE void -QFS_Init (const char *game) +QFS_Init (memhunk_t *hunk, const char *game) { int i; + qfs_hunk = hunk; + fs_sharepath = Cvar_Get ("fs_sharepath", FS_SHAREPATH, CVAR_ROM, qfs_path_cvar, "location of shared (read-only) game " diff --git a/nq/include/game.h b/nq/include/game.h index 44eb7ee19..6cf6a978f 100644 --- a/nq/include/game.h +++ b/nq/include/game.h @@ -158,6 +158,7 @@ extern qboolean isDedicated; extern qboolean standard_quake; extern struct cvar_s *registered; -void Game_Init (void); +struct memhunk_s; +void Game_Init (struct memhunk_s *hunk); #endif // __game_h diff --git a/nq/source/game.c b/nq/source/game.c index 356cbb05b..6fc7c225b 100644 --- a/nq/source/game.c +++ b/nq/source/game.c @@ -72,7 +72,7 @@ Game_CheckRegistered (void) } void -Game_Init (void) +Game_Init (memhunk_t *hunk) { int i; const char *game = "nq"; @@ -89,7 +89,7 @@ Game_Init (void) } else if ((i = COM_CheckParm ("-abyss"))) { game = "abyss"; } - QFS_Init (game); + QFS_Init (hunk, game); registered = Cvar_Get ("registered", "0", CVAR_NONE, NULL, "Is the game the registered version. 1 yes 0 no"); diff --git a/nq/source/host.c b/nq/source/host.c index d4d33e10c..be2b2d232 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -808,7 +808,7 @@ Host_InitVCR (quakeparms_t *parms) } -static void +static memhunk_t * Host_Init_Memory (void) { int mem_parm = COM_CheckParm ("-mem"); @@ -843,9 +843,10 @@ Host_Init_Memory (void) Sys_Error ("Can't allocate %zd", mem_size); Sys_PageIn (mem_base, mem_size); - Memory_Init (mem_base, mem_size); + memhunk_t *hunk = Memory_Init (mem_base, mem_size); Sys_Printf ("%4.1f megabyte heap\n", host_mem_size->value); + return hunk; } static void @@ -887,11 +888,11 @@ Host_Init (void) GIB_Key_Init (); COM_ParseConfig (host_cbuf); - Host_Init_Memory (); + memhunk_t *hunk = Host_Init_Memory (); PI_Init (); - Game_Init (); + Game_Init (hunk); if (!isDedicated) CL_InitCvars (); diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index d1da80448..e00bbaf31 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -202,7 +202,7 @@ qtv_end_redirect (void) qtv_redirect_client = 0; } -static void +static memhunk_t * qtv_memory_init (void) { int mem_size; @@ -217,7 +217,7 @@ qtv_memory_init (void) mem_base = Sys_Alloc (mem_size); if (!mem_base) Sys_Error ("Can't allocate %d", mem_size); - Memory_Init (mem_base, mem_size); + return Memory_Init (mem_base, mem_size); } static void @@ -258,9 +258,9 @@ qtv_init (void) COM_ParseConfig (qtv_cbuf); Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); - qtv_memory_init (); + memhunk_t *hunk = qtv_memory_init (); - QFS_Init ("qw"); + QFS_Init (hunk, "qw"); PI_Init (); qtv_console_plugin = Cvar_Get ("qtv_console_plugin", "server", diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index df48b4614..6585ce04f 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1756,7 +1756,7 @@ Host_Frame (float time) fps_count++; } -static void +static memhunk_t * CL_Init_Memory (void) { int mem_parm = COM_CheckParm ("-mem"); @@ -1786,9 +1786,10 @@ CL_Init_Memory (void) Sys_Error ("Can't allocate %zd", mem_size); Sys_PageIn (mem_base, mem_size); - Memory_Init (mem_base, mem_size); + memhunk_t *hunk = Memory_Init (mem_base, mem_size); Sys_Printf ("%4.1f megabyte heap.\n", cl_mem_size->value); + return hunk; } static void @@ -1822,11 +1823,11 @@ Host_Init (void) GIB_Key_Init (); COM_ParseConfig (cl_cbuf); - CL_Init_Memory (); + memhunk_t *hunk = CL_Init_Memory (); pr_gametype = "quakeworld"; - QFS_Init ("qw"); + QFS_Init (hunk, "qw"); QFS_GamedirCallback (CL_Autoexec); PI_Init (); diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 0e1904137..915ea58ea 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2446,7 +2446,7 @@ SV_InitNet (void) sv_net_initialized = 1; } -static void +static memhunk_t * SV_Init_Memory (void) { int mem_parm = COM_CheckParm ("-mem"); @@ -2475,7 +2475,7 @@ SV_Init_Memory (void) if (!mem_base) Sys_Error ("Can't allocate %zd", mem_size); - Memory_Init (mem_base, mem_size); + return Memory_Init (mem_base, mem_size); } void @@ -2495,7 +2495,7 @@ SV_Init (void) // snax: Init experimental object system and run a test //Object_Init(); - SV_Init_Memory (); + memhunk_t *hunk = SV_Init_Memory (); QFS_GamedirCallback (gamedir_f); svs.maxclients = MAX_CLIENTS; @@ -2504,7 +2504,7 @@ SV_Init (void) SV_InitOperatorCommands (); SV_GIB_Init (); - QFS_Init ("qw"); + QFS_Init (hunk, "qw"); PI_Init (); sv_console_plugin = Cvar_Get ("sv_console_plugin", "server", diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c index 4353d5c14..8c30dd47c 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/qwaq-bi.c @@ -151,13 +151,13 @@ bi_shutdown (void *data) } void -BI_Init (progs_t *pr) +BI_Init (memhunk_t *hunk, progs_t *pr) { byte *basepal, *colormap; PR_RegisterBuiltins (pr, builtins); - QFS_Init ("nq"); + QFS_Init (hunk, "nq"); PI_Init (); PI_RegisterPlugins (client_plugin_list); diff --git a/ruamoko/qwaq/builtins/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c index 00a7ca135..b23f1c632 100644 --- a/ruamoko/qwaq/builtins/qwaq.c +++ b/ruamoko/qwaq/builtins/qwaq.c @@ -114,7 +114,8 @@ init_qf (void) //Cvar_Set (developer, "1"); - Memory_Init (Sys_Alloc (8 * 1024 * 1024), 8 * 1024 * 1024); + size_t memsize = 8 * 1024 * 1024; + memhunk_t *hunk = Memory_Init (Sys_Alloc (memsize), memsize); Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); @@ -131,7 +132,7 @@ init_qf (void) PR_Init (&pr); RUA_Init (&pr, 0); PR_Cmds_Init (&pr); - BI_Init (&pr); + BI_Init (hunk, &pr); } static int diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 899fb1c51..0a919a0c8 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -23,7 +23,8 @@ typedef struct qwaq_thread_s { typedef struct qwaq_thread_set_s DARRAY_TYPE(qwaq_thread_t *) qwaq_thread_set_t; -void BI_Init (progs_t *pr); +struct memhunk_s; +void BI_Init (struct memhunk_s *hunk, progs_t *pr); void BI_Curses_Init (progs_t *pr); void BI_Input_Init (progs_t *pr); void QWAQ_EditBuffer_Init (progs_t *pr); From fde47d6983e4ed301d59183f50a9a927ef0b72a0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Dec 2021 09:15:51 +0900 Subject: [PATCH 1946/3664] [quakefs] Clean out some excess memsets There's no point in zeroing out memory that is only going to be overwritten by the loaded file (excess bytes beyond the end of a massaged text file shouldn't be accessed anyway, and the terminating null is still written). --- libs/util/quakefs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 7ca9f8cab..465b8c534 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1142,11 +1142,11 @@ QFS_LoadFile (QFile *file, int usehunk) //base = QFS_FileBase (path); if (usehunk == 1) - buf = Hunk_AllocName (0, len + 1, base); + buf = Hunk_RawAllocName (qfs_hunk, len + 1, base); else if (usehunk == 2) - buf = Hunk_TempAlloc (0, len + 1); + buf = Hunk_TempAlloc (qfs_hunk, len + 1); else if (usehunk == 0) - buf = calloc (1, len + 1); + buf = malloc (len + 1); else if (usehunk == 3) buf = Cache_Alloc (loadcache, len + 1, base); else @@ -1156,8 +1156,8 @@ QFS_LoadFile (QFile *file, int usehunk) Sys_Error ("QFS_LoadFile: not enough space"); //Sys_Error ("QFS_LoadFile: not enough space for %s", path); + len = Qread (file, buf, len); buf[len] = 0; - Qread (file, buf, len); Qclose (file); free (base); From d857bdea7786c018404bed312a0f60233e324600 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Dec 2021 10:39:01 +0900 Subject: [PATCH 1947/3664] [vulkan] Fix a typo and gcc purity warning --- include/QF/Vulkan/qf_matrices.h | 3 ++- libs/video/renderer/vulkan/vulkan_alias.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- libs/video/renderer/vulkan/vulkan_matrices.c | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index 6abbdde61..5b6537e28 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -82,6 +82,7 @@ void Vulkan_Matrix_Init (struct vulkan_ctx_s *ctx); void Vulkan_Matrix_Shutdown (struct vulkan_ctx_s *ctx); // "Draw" :) void Vulkan_Matrix_Draw (struct qfv_renderframe_s *rFrame); -VkDescriptorSet Vulkan_Matrix_Descrptors (struct vulkan_ctx_s *ctx, int frame); +VkDescriptorSet Vulkan_Matrix_Descriptors (struct vulkan_ctx_s *ctx, int frame) + __attribute__((pure)); #endif//__QF_Vulkan_qf_matrices_h diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 8d97ee13c..848748a23 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -204,7 +204,7 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); VkDescriptorSet sets[] = { - Vulkan_Matrix_Descrptors (ctx, ctx->curFrame), + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), actx->descriptors, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index b52b6db4c..3c63c1fb8 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -891,7 +891,7 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, VK_INDEX_TYPE_UINT32); VkDescriptorSet sets[] = { - Vulkan_Matrix_Descrptors (ctx, ctx->curFrame), + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), bctx->descriptors, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index ed068032d..6c5824d26 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -794,7 +794,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, VK_INDEX_TYPE_UINT32); VkDescriptorSet set[2] = { - Vulkan_Matrix_Descrptors (ctx, ctx->curFrame), + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), dframe->descriptors, }; VkPipelineLayout layout = dctx->layout; diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 9a892fdb0..0f5536596 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -274,7 +274,7 @@ Vulkan_Matrix_Shutdown (vulkan_ctx_t *ctx) } VkDescriptorSet -Vulkan_Matrix_Descrptors (vulkan_ctx_t *ctx, int frame) +Vulkan_Matrix_Descriptors (vulkan_ctx_t *ctx, int frame) { __auto_type mctx = ctx->matrix_context; return mctx->frames.a[frame].descriptors; From ff40563fc02f36c5c91fbbf214509db8cfda9df1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Dec 2021 11:23:25 +0900 Subject: [PATCH 1948/3664] [zone] Squeeze cache_system_t to fit into 64 bytes The cache system pointers are now indices into an array of cache_system_t blocks, allowing them to be 32 bits instead of 64, thus allowing cache_system_t to fit into a single CPU cache line. This still gives and effective 38 bits (256GB) of addressing for cache/hunk. This does mean that the cache functions cannot work with more than 256GB, but should that become a problem, cache and working hunking hunk can be separate, and it should be possible to have multiple cache systems. --- libs/util/zone.c | 171 ++++++++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 78 deletions(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index d436d15a7..ea41827ca 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -77,8 +77,7 @@ typedef struct memblock_s { size_t size; // requested size int tag; // a tag of 0 is a free block int id; // should be ZONEID - //int id2; // pad to 64 bit boundary -} memblock_t; +} __attribute__((aligned (64))) memblock_t; struct memzone_s { size_t size; // total bytes malloced, including header @@ -87,10 +86,9 @@ struct memzone_s { size_t ele_size; void (*error) (void *, const char *); void *data; - memblock_t blocklist; // start / end cap for linked list memblock_t *rover; -}; - + memblock_t blocklist; // start / end cap for linked list +} __attribute__((aligned (64))); static int z_block_size (memblock_t *block) @@ -411,14 +409,16 @@ Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size) typedef struct cache_system_s cache_system_t; struct cache_system_s { - cache_system_t *prev, *next; - cache_system_t *lru_prev, *lru_next; // for LRU flushing + uint32_t prev; + uint32_t next; + uint32_t lru_prev; + uint32_t lru_next; struct memhunk_s *hunk; - char name[16]; size_t size; // including this header - int readlock; cache_user_t *user; -} __attribute__((aligned (64)));//FIXME base 64-bit size is 80, so 128... + char name[16]; + int readlock; +} __attribute__((aligned (64))); typedef struct { int sentinal1; @@ -434,9 +434,21 @@ struct memhunk_s { size_t high_used; size_t tempmark; qboolean tempactive; - cache_system_t cache_head; + cache_system_t cache_head[1]; } __attribute__((aligned (64))); +static cache_system_t * +cs_ptr (memhunk_t *hunk, uint32_t cs_ind) +{ + return &hunk->cache_head[cs_ind]; +} + +static uint32_t +cs_ind (memhunk_t *hunk, cache_system_t *cs_ptr) +{ + return cs_ptr - hunk->cache_head; +} + static memhunk_t *global_hunk; /* @@ -799,8 +811,8 @@ Cache_FreeLow (memhunk_t *hunk, int new_low_hunk) cache_system_t *c; while (1) { - c = hunk->cache_head.prev; - if (c == &hunk->cache_head) + c = cs_ptr (hunk, hunk->cache_head[0].prev); + if (c == hunk->cache_head) return; // nothing in cache at all if ((byte *) c >= hunk->base + new_low_hunk) return; // there is space to grow the hunk @@ -812,27 +824,22 @@ Cache_FreeLow (memhunk_t *hunk, int new_low_hunk) static inline void Cache_UnlinkLRU (cache_system_t * cs) { - if (!cs->lru_next || !cs->lru_prev) - Sys_Error ("Cache_UnlinkLRU: NULL link: %.16s %p %p", - cs->name, cs->lru_next, cs->lru_prev); + memhunk_t *hunk = cs->hunk; + cs_ptr (hunk, cs->lru_next)->lru_prev = cs->lru_prev; + cs_ptr (hunk, cs->lru_prev)->lru_next = cs->lru_next; - cs->lru_next->lru_prev = cs->lru_prev; - cs->lru_prev->lru_next = cs->lru_next; - - cs->lru_prev = cs->lru_next = NULL; + cs->lru_prev = cs->lru_next = 0; } static void Cache_MakeLRU (cache_system_t * cs) { - if (cs->lru_next || cs->lru_prev) - Sys_Error ("Cache_MakeLRU: active link: %.16s %p %p", - cs->name, cs->lru_next, cs->lru_prev); - - cs->hunk->cache_head.lru_next->lru_prev = cs; - cs->lru_next = cs->hunk->cache_head.lru_next; - cs->lru_prev = &cs->hunk->cache_head; - cs->hunk->cache_head.lru_next = cs; + memhunk_t *hunk = cs->hunk; + __auto_type nx = cs_ptr (hunk, hunk->cache_head[0].lru_next); + nx->lru_prev = cs_ind (hunk, cs); + cs->lru_next = cs_ind (hunk, nx); + cs->lru_prev = 0; + hunk->cache_head[0].lru_next = cs_ind (hunk, cs); } static qboolean @@ -841,10 +848,11 @@ Cache_FreeLRU (memhunk_t *hunk) cache_system_t *cs; //check_cache (); - for (cs = hunk->cache_head.lru_prev; - cs != &hunk->cache_head && cs->readlock; cs = cs->lru_prev) - ; - if (cs == &hunk->cache_head) + for (cs = cs_ptr (hunk, hunk->cache_head[0].lru_prev); + cs != hunk->cache_head && cs->readlock; + cs = cs_ptr (hunk, cs->lru_prev)) { + } + if (cs == hunk->cache_head) return 0; Cache_Free (cs->user); return 1; @@ -853,10 +861,11 @@ Cache_FreeLRU (memhunk_t *hunk) static void link_cache_system (cache_system_t *new, cache_system_t *cs) { - new->next = cs; + memhunk_t *hunk = cs->hunk; + new->next = cs_ind (hunk, cs); new->prev = cs->prev; - cs->prev->next = new; - cs->prev = new; + cs_ptr (hunk, cs->prev)->next = cs_ind (hunk, new); + cs->prev = cs_ind (hunk, new); } @@ -873,22 +882,25 @@ Cache_TryAlloc (memhunk_t *hunk, size_t size, qboolean nobottom) //check_cache (); // is the cache completely empty? - if (!nobottom && hunk->cache_head.prev == &hunk->cache_head) { + if (!nobottom && hunk->cache_head[0].prev == 0) { new = (cache_system_t *) Hunk_HighAlloc (hunk, size); if (!new) return 0; memset (new, 0, size); new->size = size; new->hunk = hunk; - hunk->cache_head.prev = hunk->cache_head.next = new; - new->prev = new->next = &hunk->cache_head; + hunk->cache_head[0].prev = cs_ind (hunk, new); + hunk->cache_head[0].next = cs_ind (hunk, new); + new->prev = new->next = 0; Cache_MakeLRU (new); //check_cache (); return new; } // search for space in existing cache - for (cs = hunk->cache_head.next; cs != &hunk->cache_head; cs = cs->next) { + for (cs = cs_ptr (hunk, hunk->cache_head[0].next); + cs != hunk->cache_head; + cs = cs_ptr (hunk, cs->next)) { if (cs->user) continue; // block isn't free if (cs->size >= size) { @@ -919,7 +931,7 @@ Cache_TryAlloc (memhunk_t *hunk, size_t size, qboolean nobottom) memset (new, 0, size); new->size = size; new->hunk = hunk; - link_cache_system (new, &hunk->cache_head); + link_cache_system (new, hunk->cache_head); Cache_MakeLRU (new); //check_cache (); return new; @@ -931,20 +943,20 @@ Cache_TryAlloc (memhunk_t *hunk, size_t size, qboolean nobottom) static void Cache_Profile_r (memhunk_t *hunk) { - cache_system_t *cs; unsigned int i; unsigned int items[31] = {0}, sizes[31] = {0}; int count = 0, total = 0; + cache_system_t *cs; - cs = hunk->cache_head.next; - while (cs != &hunk->cache_head) { - for (i = 0; (cs->size >> (i + 1)) && i < 30; i++) - ; + for (uint32_t ind = hunk->cache_head[0].next; ind; ind = cs->next) { + cs = cs_ptr (hunk, ind); + for (i = 0; (cs->size >> (i + 1)) && i < 30; i++) { + } items[i]++; sizes[i] += cs->size; total += cs->size; count++; - cs = cs->next; + ind = cs->next; } Sys_Printf ("Cache Profile:\n"); Sys_Printf ("%8s %8s %8s %8s %8s\n", @@ -971,10 +983,10 @@ Cache_Profile (void) static void Cache_Print_r (memhunk_t *hunk) { - cache_system_t *cd; - - for (cd = hunk->cache_head.next; cd != &hunk->cache_head; cd = cd->next) { - Sys_Printf ("%8d : %.16s\n", (int) cd->size, cd->name); + cache_system_t *cs; + for (uint32_t ind = hunk->cache_head[0].next; ind; ind = cs->next) { + cs = cs_ptr (hunk, ind); + Sys_Printf ("%8d : %.16s\n", (int) cs->size, cs->name); } } @@ -987,10 +999,12 @@ Cache_Print (void) static void init_cache (memhunk_t *hunk) { - hunk->cache_head.next = hunk->cache_head.prev = &hunk->cache_head; - hunk->cache_head.lru_next = hunk->cache_head.lru_prev = &hunk->cache_head; - hunk->cache_head.user = (cache_user_t *) 1; // make it look allocated - hunk->cache_head.readlock = 1; // don't try to free or move it + hunk->cache_head[0].hunk = hunk; + hunk->cache_head[0].size = 0; + hunk->cache_head[0].next = hunk->cache_head[0].prev = 0; + hunk->cache_head[0].lru_next = hunk->cache_head[0].lru_prev = 0; + hunk->cache_head[0].user = (cache_user_t *) 1; // make it look allocated + hunk->cache_head[0].readlock = 1; // don't try to free or move it } static void @@ -1014,13 +1028,13 @@ Cache_Flush_r (memhunk_t *hunk) { // cache_head.prev is guaranteed to not be free because it's the bottom // one and Cache_Free actually properly releases it - while (hunk->cache_head.prev != &hunk->cache_head) { - if (!hunk->cache_head.prev->user->data) + while (hunk->cache_head[0].prev) { + __auto_type cs = cs_ptr (hunk, hunk->cache_head[0].prev); + if (!cs->user->data) Sys_Error ("Cache_Flush: user/system out of sync for " - "'%.16s' with %d size", - hunk->cache_head.prev->name, - (int) hunk->cache_head.prev->size); - Cache_Free (hunk->cache_head.prev->user); // reclaim the space + "'%.16s' with %zd size", + cs->name, cs->size); + Cache_Free (cs->user); // reclaim the space } } @@ -1062,7 +1076,6 @@ Cache_Free (cache_user_t *c) Sys_Error ("Cache_Free: not allocated"); cs = ((cache_system_t *) c->data) - 1; - memhunk_t *hunk = cs->hunk; if (cs->readlock) Sys_Error ("Cache_Free: attempt to free locked block"); @@ -1071,27 +1084,29 @@ Cache_Free (cache_user_t *c) Cache_UnlinkLRU (cs); + memhunk_t *h = cs->hunk; //check_cache (); cs->user = 0; - if (!cs->prev->user) { - cs->size += cs->prev->size; - cs->prev->prev->next = cs; - cs->prev = cs->prev->prev; + if (!cs_ptr (h, cs->prev)->user) { + cs->size += cs_ptr (h, cs->prev)->size; + cs_ptr (h, cs_ptr (h, cs->prev)->prev)->next = cs_ind (h, cs); + cs->prev = cs_ptr (h, cs->prev)->prev; } - if (!cs->next->user) { - cs = cs->next; - cs->size += cs->prev->size; - cs->prev->prev->next = cs; - cs->prev = cs->prev->prev; + if (!cs_ptr (h, cs->next)->user) { + cs = cs_ptr (h, cs->next); + cs->size += cs_ptr (h, cs->prev)->size; + cs_ptr (h, cs_ptr (h, cs->prev)->prev)->next = cs_ind (h, cs); + cs->prev = cs_ptr (h, cs->prev)->prev; } - if (cs->next == &hunk->cache_head) { - cs->next->prev = cs->prev; - cs->prev->next = cs->next; - if (cs->prev != &hunk->cache_head) - Hunk_FreeToHighMark (hunk, - hunk->size - ((byte*)cs->prev - hunk->base)); - else - Hunk_FreeToHighMark (hunk, 0); + if (!cs->next) { + cs_ptr (h, cs->next)->prev = cs->prev; + cs_ptr (h, cs->prev)->next = cs->next; + if (cs->prev) { + __auto_type ptr = (byte *) cs_ptr (h, cs->prev); + Hunk_FreeToHighMark (h, h->size - (ptr - h->base)); + } else { + Hunk_FreeToHighMark (h, 0); + } } //check_cache (); From eee25d21ba6acef69b358766981571882f243989 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Dec 2021 11:49:37 +0900 Subject: [PATCH 1949/3664] [zone] Clean out unnecessary memsets As the cache blocks are always filled in with a memcpy, there's no need to zero out the whole allocation, and the header is initialized anyway. --- libs/util/zone.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index ea41827ca..8817e91b9 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -790,7 +790,7 @@ Cache_Move (cache_system_t *c) memcpy (new + 1, c + 1, c->size - sizeof (cache_system_t)); new->user = c->user; - memcpy (new->name, c->name, sizeof (new->name)); + strncpy (new->name, c->name, sizeof (new->name)); Cache_Free (c->user); new->user->data = (void *) (new + 1); } else { @@ -886,12 +886,13 @@ Cache_TryAlloc (memhunk_t *hunk, size_t size, qboolean nobottom) new = (cache_system_t *) Hunk_HighAlloc (hunk, size); if (!new) return 0; - memset (new, 0, size); new->size = size; new->hunk = hunk; hunk->cache_head[0].prev = cs_ind (hunk, new); hunk->cache_head[0].next = cs_ind (hunk, new); new->prev = new->next = 0; + new->readlock = 0; + new->name[0] = 0; Cache_MakeLRU (new); //check_cache (); return new; @@ -910,7 +911,8 @@ Cache_TryAlloc (memhunk_t *hunk, size_t size, qboolean nobottom) new = cs; if (size - cs->size >= sizeof (cache_system_t)) { new = (cache_system_t *) ((char *) cs + cs->size - size); - memset (new, 0, size); + new->readlock = 0; + new->name[0] = 0; new->size = size; new->hunk = hunk; cs->size -= size; @@ -928,7 +930,8 @@ Cache_TryAlloc (memhunk_t *hunk, size_t size, qboolean nobottom) // didn't find a free block, so make a new one. new = Hunk_HighAlloc (hunk, size); if (new) { - memset (new, 0, size); + new->readlock = 0; + new->name[0] = 0; new->size = size; new->hunk = hunk; link_cache_system (new, hunk->cache_head); @@ -1131,6 +1134,7 @@ Cache_Alloc_r (memhunk_t *hunk, cache_user_t *c, size_t size, const char *name) cs = Cache_TryAlloc (hunk, size, false); if (cs) { strncpy (cs->name, name, sizeof (cs->name) - 1); + cs->name[sizeof (cs->name) - 1] = 0; c->data = (void *) (cs + 1); cs->user = c; break; From 854c92d10e40b580b325513473e02175cf798ae8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Dec 2021 15:13:19 +0900 Subject: [PATCH 1950/3664] [simd] Indicate when the circumsphere is degenerate CircumSphere_vf sets the sphere radius to -1 when the points are degenerate (co-linear for three points, co-planar for four points). --- libs/util/simd.c | 38 +++++++++++++++++++++++++++----------- libs/util/test/test-csvf.c | 7 ++++++- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/libs/util/simd.c b/libs/util/simd.c index 5ad1ab3e0..f10c97acd 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -36,6 +36,7 @@ #define IMPLEMENT_VEC4D_Funcs #define IMPLEMENT_MAT4F_Funcs +#include "QF/mathlib.h" #include "QF/simd/vec4d.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" @@ -91,8 +92,8 @@ BarycentricCoords_vf (const vec4f_t **points, int num_points, const vec4f_t p) Sys_Error ("Not enough points to project or enclose the point"); } -static vec4f_t -circum_circle (const vec4f_t points[], int num_points) +static int +circum_circle (const vec4f_t points[], int num_points, vec4f_t *center) { vec4f_t a, c, b; vec4f_t bc, ca, ab; @@ -102,9 +103,11 @@ circum_circle (const vec4f_t points[], int num_points) switch (num_points) { case 1: - return points[0]; + *center = points[0]; + return 1; case 2: - return (points[0] + points[1]) / 2; + *center = (points[0] + points[1]) / 2; + return 1; case 3: a = points[0] - points[1]; b = points[0] - points[2]; @@ -114,10 +117,15 @@ circum_circle (const vec4f_t points[], int num_points) cc = dotf (c, c); div = dotf (a, c); div = 2 * (aa * cc - div * div); + if (fabs (div[0]) < EQUAL_EPSILON) { + // degenerate + return 0; + } alpha = cc * dotf (a, b) / div; beta = -bb * dotf (a, c) / div; gamma = aa * dotf (b, c) / div; - return alpha * points[0] + beta * points[1] + gamma * points[2]; + *center = alpha * points[0] + beta * points[1] + gamma * points[2]; + return 1; case 4: a = points[1] - points[0]; b = points[2] - points[0]; @@ -126,13 +134,17 @@ circum_circle (const vec4f_t points[], int num_points) ca = crossf (c, a); ab = crossf (a, b); div = 2 * dotf (a, bc); + if (fabs (div[0]) < EQUAL_EPSILON) { + // degenerate + return 0; + } aa = dotf (a, a) / div; bb = dotf (b, b) / div; cc = dotf (c, c) / div; - return bc * aa + bb * ca + cc * ab + points[0]; + *center = bc * aa + bb * ca + cc * ab + points[0]; + return 1; } - vec4f_t zero = {}; - return zero; + return 0; } vspheref_t @@ -140,9 +152,13 @@ CircumSphere_vf (const vec4f_t *points, int num_points) { vspheref_t sphere = {}; if (num_points > 0 && num_points <= 4) { - sphere.center = circum_circle (points, num_points); - vec4f_t d = sphere.center - points[0]; - sphere.radius = sqrt(dotf (d, d)[0]); + if (circum_circle (points, num_points, &sphere.center)) { + vec4f_t d = sphere.center - points[0]; + sphere.radius = sqrt(dotf (d, d)[0]); + } else { + // degenerate + sphere.radius = -1; + } } return sphere; } diff --git a/libs/util/test/test-csvf.c b/libs/util/test/test-csvf.c index 8b73a4aa4..5f56f18c0 100644 --- a/libs/util/test/test-csvf.c +++ b/libs/util/test/test-csvf.c @@ -105,13 +105,18 @@ main (int argc, const char **argv) VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), cloud[j]); } cc = CircumSphere_vf (cloud, 4); + if (cc.radius < 0) { + // degenerate + continue; + } r2 = cc.radius * cc.radius; for (j = 0; j < 4; j++) { vec4f_t d = cloud[j] - cc.center; fr = dotf (d, d)[0]; if (fabs (fr - r2) < 1e-3 * r2) continue; - printf ("%d %.9g - %.9g = %.9g %.9g\n", j, fr, r2, fr - r2, fabs(fr - r2)); + printf ("%zd %d %.9g - %.9g = %.9g %.9g\n", + i, j, fr, r2, fr - r2, fabs(fr - r2)); printf ("[%.9g %.9g %.9g] - [%.9g %.9g %.9g] = %.9g != %.9g\n", VectorExpand (cloud[j]), VectorExpand (cc.center), fr, r2); res = 1; From 2b332cfe4a5502ce9b7a909ab7064df6cb73dd67 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Dec 2021 16:33:09 +0900 Subject: [PATCH 1951/3664] [zone] Clean up some magic numbers --- libs/util/zone.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index 8817e91b9..2f083d282 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -424,7 +424,7 @@ typedef struct { int sentinal1; int sentinal2; size_t size; // including sizeof(hunkblk_t), -1 = not allocated - char name[8]; + char name[16]; } __attribute__((aligned (64))) hunkblk_t; struct memhunk_s { @@ -526,14 +526,19 @@ Hunk_Print (memhunk_t *hunk, qboolean all) sum += h->size; // print the single block - if (all) - Sys_Printf ("%8p :%8zd %8.8s\n", h, h->size, h->name); + if (all) { + const int sz = sizeof (h->name); + Sys_Printf ("%8p :%8zd %*.*s\n", h, h->size, sz, sz, h->name); + } // print the total if (next == endlow || next == endhigh || - strncmp (h->name, next->name, 8)) { - if (!all) - Sys_Printf (" :%8i %8.8s (TOTAL)\n", sum, h->name); + strncmp (h->name, next->name, sizeof (h->name))) { + if (!all) { + const int sz = sizeof (h->name); + Sys_Printf (" :%8i %*.*s (TOTAL)\n", + sum, sz, sz, h->name); + } count = 0; sum = 0; } @@ -608,8 +613,7 @@ Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) h->size = size; h->sentinal1 = HUNK_SENTINAL; h->sentinal2 = HUNK_SENTINAL; - memcpy (h->name, name, 8); - h->name[7] = 0; + strncpy (h->name, name, sizeof (h->name)); return (void *) (h + 1); } @@ -988,8 +992,9 @@ Cache_Print_r (memhunk_t *hunk) { cache_system_t *cs; for (uint32_t ind = hunk->cache_head[0].next; ind; ind = cs->next) { + const int sz = sizeof (cs->name); cs = cs_ptr (hunk, ind); - Sys_Printf ("%8d : %.16s\n", (int) cs->size, cs->name); + Sys_Printf ("%8zd : %.*s\n", cs->size, sz, cs->name); } } @@ -1033,10 +1038,12 @@ Cache_Flush_r (memhunk_t *hunk) // one and Cache_Free actually properly releases it while (hunk->cache_head[0].prev) { __auto_type cs = cs_ptr (hunk, hunk->cache_head[0].prev); - if (!cs->user->data) + if (!cs->user->data) { + const int sz = sizeof (cs->name); Sys_Error ("Cache_Flush: user/system out of sync for " - "'%.16s' with %zd size", - cs->name, cs->size); + "'%.*s' with %zd size", + sz, cs->name, cs->size); + } Cache_Free (cs->user); // reclaim the space } } @@ -1083,7 +1090,9 @@ Cache_Free (cache_user_t *c) if (cs->readlock) Sys_Error ("Cache_Free: attempt to free locked block"); - Sys_MaskPrintf (SYS_dev, "Cache_Free: freeing '%.16s' %p\n", cs->name, cs); + const int sz = sizeof (cs->name); + Sys_MaskPrintf (SYS_dev, "Cache_Free: freeing '%.*s' %p\n", + sz, cs->name, cs); Cache_UnlinkLRU (cs); @@ -1133,8 +1142,7 @@ Cache_Alloc_r (memhunk_t *hunk, cache_user_t *c, size_t size, const char *name) while (1) { cs = Cache_TryAlloc (hunk, size, false); if (cs) { - strncpy (cs->name, name, sizeof (cs->name) - 1); - cs->name[sizeof (cs->name) - 1] = 0; + strncpy (cs->name, name, sizeof (cs->name)); c->data = (void *) (cs + 1); cs->user = c; break; From e7e6dd87e872113a9983a07c4db7272096818cf2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Dec 2021 00:42:22 +0900 Subject: [PATCH 1952/3664] [glsl] Fix some const-correct issues for textures --- include/QF/GLSL/qf_textures.h | 6 +++--- libs/video/renderer/glsl/glsl_textures.c | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/QF/GLSL/qf_textures.h b/include/QF/GLSL/qf_textures.h index 2298c3e16..3a5f0b8b7 100644 --- a/include/QF/GLSL/qf_textures.h +++ b/include/QF/GLSL/qf_textures.h @@ -33,13 +33,13 @@ typedef struct scrap_s scrap_t; int GLSL_LoadQuakeTexture (const char *identifier, int width, int height, - byte *data); + const byte *data); struct texture_s; int GLSL_LoadQuakeMipTex (const struct texture_s *tex); int GLSL_LoadRGBTexture (const char *identifier, int width, int height, - byte *data); + const byte *data); int GLSL_LoadRGBATexture (const char *identifier, int width, int height, - byte *data); + const byte *data); void GLSL_ReleaseTexture (int tex); void GLSL_TextureInit (void); diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index 9b80351ee..96c0f0c77 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -72,7 +72,7 @@ static int max_tex_size; int GLSL_LoadQuakeTexture (const char *identifier, int width, int height, - byte *data) + const byte *data) { GLuint tnum; @@ -204,7 +204,8 @@ GLSL_LoadQuakeMipTex (const texture_t *tex) } int -GLSL_LoadRGBTexture (const char *identifier, int width, int height, byte *data) +GLSL_LoadRGBTexture (const char *identifier, int width, int height, + const byte *data) { GLuint tnum; @@ -222,7 +223,8 @@ GLSL_LoadRGBTexture (const char *identifier, int width, int height, byte *data) } int -GLSL_LoadRGBATexture (const char *identifier, int width, int height, byte *data) +GLSL_LoadRGBATexture (const char *identifier, int width, int height, + const byte *data) { GLuint tnum; From ad5415a860b4bd290b898e046f8224776c54fd91 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Dec 2021 00:43:07 +0900 Subject: [PATCH 1953/3664] [zone] Make zone.h stand-alone ie, including just it from QF will compile. --- include/QF/zone.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/QF/zone.h b/include/QF/zone.h index b19aef350..56dbbcc8f 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -27,6 +27,8 @@ #ifndef __QF_zone_h #define __QF_zone_h +#include "QF/qtypes.h" + /** \defgroup zone Memory Management \ingroup utils From 6eed89151c9d58e2c7a8bd223ec0c51792aaf8aa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Dec 2021 00:45:37 +0900 Subject: [PATCH 1954/3664] [vulkan] Fix a function doc typo --- include/QF/Vulkan/image.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 5e4866952..d146b298c 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -85,7 +85,7 @@ size_t QFV_GetImageSize (struct qfv_device_s *device, VkImage image); * \param mips The total number of mip levels of the processed image. * \param width The pixel width of the base image. * \param height The pixel height of the base image. - * \param layers The number of array layers in the mbase image. + * \param layers The number of array layers in the base image. * * \note The processed image will be in "shader read only optimal" layout on * completion. From c5cfcc7bfde29ec0beeeb8a44921be43d71e1d93 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Dec 2021 08:36:19 +0900 Subject: [PATCH 1955/3664] [sprite] Separate model and texture loading As much as it can be since the texture data is interleaved with the model data in the files (I guess not that bad a design for 25 years ago with the tight memory constraints), but this paves the way for supporting sprites in Vulkan. --- include/QF/model.h | 10 +- include/QF/plugin/vid_render.h | 4 +- include/mod_internal.h | 21 +- libs/models/sprite/gl_model_sprite.c | 40 ++-- libs/models/sprite/glsl_model_sprite.c | 23 +- libs/models/sprite/model_sprite.c | 269 ++++++++++++++---------- libs/models/sprite/sw_model_sprite.c | 18 +- libs/video/renderer/vid_render_gl.c | 2 +- libs/video/renderer/vid_render_glsl.c | 2 +- libs/video/renderer/vid_render_sw.c | 2 +- libs/video/renderer/vid_render_sw32.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 5 +- 12 files changed, 237 insertions(+), 161 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 0efd7be00..9f308e997 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -280,7 +280,6 @@ typedef struct mod_brush_s { // SPRITE MODELS ============================================================== -// FIXME: shorten these? typedef struct mspriteframe_s { int width; int height; @@ -304,11 +303,10 @@ typedef struct { } mspriteframedesc_t; typedef struct { - int type; - int maxwidth; - int maxheight; - float beamlength; - int numframes; + int type; + float beamlength; + int numframes; + int data; mspriteframedesc_t frames[1]; } msprite_t; diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 699bef12e..8ed240c84 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -38,6 +38,7 @@ struct cvar_s; struct skin_s; struct mod_alias_ctx_s; +struct mod_sprite_ctx_s; /* All video plugins must export these functions @@ -99,8 +100,7 @@ typedef struct vid_model_funcs_s { void (*Mod_LoadExternalSkins) (struct mod_alias_ctx_s *alias_ctx); void (*Mod_IQMFinish) (model_t *mod); int alias_cache; - void (*Mod_SpriteLoadTexture) (model_t *mod, mspriteframe_t *pspriteframe, - int framenum); + void (*Mod_SpriteLoadFrames) (struct mod_sprite_ctx_s *sprite_ctx); struct skin_s *(*Skin_SetColormap) (struct skin_s *skin, int cmap); struct skin_s *(*Skin_SetSkin) (struct skin_s *skin, int cmap, diff --git a/include/mod_internal.h b/include/mod_internal.h index b82de630b..9126a3280 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -19,9 +19,18 @@ typedef struct mod_alias_ctx_s { trivertxset_t poseverts; int aliasbboxmins[3]; int aliasbboxmaxs[3]; - } mod_alias_ctx_t; +typedef struct mod_sprite_ctx_s { + model_t *mod; + dsprite_t *dsprite; + msprite_t *sprite; + int numframes; + int *frame_numbers; + dspriteframe_t **dframes; ///< array of pointers to dframes (in) + mspriteframe_t ***frames; ///< array of pointers to mframe pointers (out) +} mod_sprite_ctx_t; + int Mod_CalcFullbright (byte *out, const byte *in, size_t pixels); int Mod_ClearFullbright (byte *out, const byte *in, size_t pixels); void Mod_FloodFillSkin (byte *skin, int skinwidth, int skinheight); @@ -79,12 +88,10 @@ void Vulkan_Mod_SubdivideSurface (model_t *mod, msurface_t *fa, void Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, struct vulkan_ctx_s *ctx); -void gl_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, - int framenum); -void glsl_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, - int framenum); -void sw_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, - int framenum); +void Mod_LoadSpriteFrame (mspriteframe_t *frame, const dspriteframe_t *dframe); +void gl_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx); +void glsl_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx); +void sw_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx); void Mod_LoadIQM (model_t *mod, void *buffer); void Mod_FreeIQM (iqm_t *iqm); diff --git a/libs/models/sprite/gl_model_sprite.c b/libs/models/sprite/gl_model_sprite.c index 2abef1dfc..546e97e96 100644 --- a/libs/models/sprite/gl_model_sprite.c +++ b/libs/models/sprite/gl_model_sprite.c @@ -43,26 +43,36 @@ #include "compat.h" #include "mod_internal.h" -void -gl_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, - int framenum) +static int +load_texture (model_t *mod, int framenum, const dspriteframe_t *dframe) { tex_t *targa; const char *name; targa = LoadImage (name = va (0, "%s_%i", mod->path, framenum), 1); if (targa) { - if (targa->format < 4) - pspriteframe->gl_texturenum = GL_LoadTexture (name, - targa->width, targa->height, targa->data, - true, false, 3); - else - pspriteframe->gl_texturenum = GL_LoadTexture (name, - targa->width, targa->height, targa->data, - true, true, 4); - return; + if (targa->format < 4) { + return GL_LoadTexture (name, targa->width, targa->height, + targa->data, true, false, 3); + } else { + return GL_LoadTexture (name, targa->width, targa->height, + targa->data, true, true, 4); + } + } + return GL_LoadTexture (name, dframe->width, dframe->height, + (const byte *)(dframe + 1), true, true, 1); +} + +void +gl_Mod_SpriteLoadFrames (mod_sprite_ctx_t *ctx) +{ + for (int i = 0; i < ctx->numframes; i++) { + __auto_type dframe = ctx->dframes[i]; + size_t size = sizeof (mspriteframe_t); + mspriteframe_t *frame = Hunk_AllocName (0, size, ctx->mod->name); + *ctx->frames[i] = frame; + Mod_LoadSpriteFrame (frame, dframe); + frame->gl_texturenum = load_texture (ctx->mod, ctx->frame_numbers[i], + dframe); } - pspriteframe->gl_texturenum = - GL_LoadTexture (name, pspriteframe->width, pspriteframe->height, - pspriteframe->pixels, true, true, 1); } diff --git a/libs/models/sprite/glsl_model_sprite.c b/libs/models/sprite/glsl_model_sprite.c index ae1f12a10..c6f267d57 100644 --- a/libs/models/sprite/glsl_model_sprite.c +++ b/libs/models/sprite/glsl_model_sprite.c @@ -71,14 +71,19 @@ glsl_sprite_clear (model_t *m, void *data) } void -glsl_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, - int framenum) +glsl_Mod_SpriteLoadFrames (mod_sprite_ctx_t *ctx) { - const char *name; - - mod->clear = glsl_sprite_clear; - name = va (0, "%s_%i", mod->path, framenum); - pspriteframe->gl_texturenum = - GLSL_LoadQuakeTexture (name, pspriteframe->width, pspriteframe->height, - pspriteframe->pixels); + ctx->mod->clear = glsl_sprite_clear; + for (int i = 0; i < ctx->numframes; i++) { + __auto_type dframe = ctx->dframes[i]; + size_t size = sizeof (mspriteframe_t); + mspriteframe_t *frame = Hunk_AllocName (0, size, ctx->mod->name); + *ctx->frames[i] = frame; + Mod_LoadSpriteFrame (frame, dframe); + const char *name = va (0, "%s_%i", ctx->mod->path, + ctx->frame_numbers[i]); + frame->gl_texturenum = + GLSL_LoadQuakeTexture (name, dframe->width, dframe->height, + (const byte *)(dframe + 1)); + } } diff --git a/libs/models/sprite/model_sprite.c b/libs/models/sprite/model_sprite.c index a38d66dfa..1bd9ca2cc 100644 --- a/libs/models/sprite/model_sprite.c +++ b/libs/models/sprite/model_sprite.c @@ -38,144 +38,187 @@ #include "QF/qendian.h" #include "QF/sys.h" -#include "compat.h" #include "mod_internal.h" +#include "qfalloca.h" -static void * -Mod_LoadSpriteFrame (model_t *mod, void *pin, mspriteframe_t **frame, - int framenum) +void +Mod_LoadSpriteFrame (mspriteframe_t *frame, const dspriteframe_t *dframe) { - dspriteframe_t *in_frame; - int width, height, size, origin[2]; + frame->width = dframe->width; + frame->height = dframe->height; - in_frame = (dspriteframe_t *) pin; - - width = LittleLong (in_frame->width); - height = LittleLong (in_frame->height); - size = width * height; - - *frame = Hunk_AllocName (0, sizeof (mspriteframe_t) + size, mod->name); - - (*frame)->width = width; - (*frame)->height = height; - origin[0] = LittleLong (in_frame->origin[0]); - origin[1] = LittleLong (in_frame->origin[1]); - - (*frame)->up = origin[1]; - (*frame)->down = origin[1] - height; - (*frame)->left = origin[0]; - (*frame)->right = width + origin[0]; - - memcpy ((*frame)->pixels, (byte *) (in_frame + 1), size); - - m_funcs->Mod_SpriteLoadTexture (mod, *frame, framenum); - - return (void *) ((byte *) in_frame + sizeof (dspriteframe_t) + size); + frame->up = dframe->origin[1]; + frame->down = dframe->origin[1] - dframe->height; + frame->left = dframe->origin[0]; + frame->right = dframe->width + dframe->origin[0]; } static void * -Mod_LoadSpriteGroup (model_t *mod, void *pin, mspritegroup_t **group, - int framenum) +skip_frame (dspriteframe_t *frame) { - dspritegroup_t *in_group; - dspriteinterval_t *in_intervals; - float *intervals; - int numframes, i; - void *temp; + __auto_type pixels = (byte *) (frame + 1); + return pixels + frame->width * frame->height; +} - in_group = (dspritegroup_t *) pin; +static void * +swap_frame (dspriteframe_t *frame) +{ + for (int i = 0; i < 2; i++) { + frame->origin[i] = LittleLong (frame->origin[i]); + } + frame->width = LittleLong (frame->width); + frame->height = LittleLong (frame->height); + return skip_frame (frame); +} - numframes = LittleLong (in_group->numframes); +static void * +swap_group (dspritegroup_t *group) +{ + group->numframes = LittleLong (group->numframes); + __auto_type interval = (dspriteinterval_t *) (group + 1); + for (int i = 0; i < group->numframes; i++) { + interval->interval = LittleFloat (interval->interval); + interval++; + } + __auto_type frame = (dspriteframe_t *) interval; + for (int i = 0; i < group->numframes; i++) { + frame = swap_frame (frame); + } + return frame + 1; +} - int size = field_offset (mspritegroup_t, frames[numframes]); - *group = Hunk_AllocName (0, size, mod->name); +static int +swap_sprite (dsprite_t *sprite) +{ + sprite->ident = LittleLong (sprite->ident); + sprite->version = LittleLong (sprite->version); + sprite->type = LittleLong (sprite->type); + sprite->boundingradius = LittleFloat (sprite->boundingradius); + sprite->width = LittleLong (sprite->width); + sprite->height = LittleLong (sprite->height); + sprite->numframes = LittleLong (sprite->numframes); + sprite->beamlength = LittleFloat (sprite->beamlength); + sprite->synctype = LittleLong (sprite->synctype); + int numframes = 0; + __auto_type type = (dspriteframetype_t *) (sprite + 1); + for (int i = 0; i < sprite->numframes; i++) { + type->type = LittleLong (type->type); + if (type->type == SPR_SINGLE) { + __auto_type frame = (dspriteframe_t *) (type + 1); + type = swap_frame (frame); + numframes += 1; + } else { + __auto_type group = (dspritegroup_t *) (type + 1); + type = swap_group (group); + numframes += group->numframes; + } + } + return numframes; +} + +static void * +find_group_frames (mspritegroup_t **group, dspritegroup_t *dgroup, + mspriteframe_t ***frames, dspriteframe_t **dframes, + int *frame_numbers, const char *modname) +{ + int numframes = dgroup->numframes; + size_t size = field_offset (mspritegroup_t, frames[numframes]); + *group = Hunk_AllocName (0, size, modname); (*group)->numframes = numframes; + (*group)->intervals = Hunk_AllocName (0, numframes * sizeof (float), + modname); - in_intervals = (dspriteinterval_t *) (in_group + 1); - - intervals = Hunk_AllocName (0, numframes * sizeof (float), mod->name); - - (*group)->intervals = intervals; - - for (i = 0; i < numframes; i++) { - *intervals = LittleFloat (in_intervals->interval); - if (*intervals <= 0.0) - Sys_Error ("Mod_LoadSpriteGroup: interval<=0"); - - intervals++; - in_intervals++; + __auto_type interval = (dspriteinterval_t *) (dgroup + 1); + for (int i = 0; i < numframes; i++) { + (*group)->intervals[i] = interval->interval; + interval++; } - - temp = (void *) in_intervals; - - for (i = 0; i < numframes; i++) { - temp = Mod_LoadSpriteFrame (mod, temp, &(*group)->frames[i], - framenum * 100 + i); + __auto_type dframe = (dspriteframe_t *) interval; + for (int i = 0; i < numframes; i++) { + frames[i] = &(*group)->frames[i]; + dframes[i] = dframe; + frame_numbers[i] = i; + dframe = skip_frame (dframe); } + return dframe; +} - return temp; +static void +find_frames (msprite_t *sprite, dsprite_t *dsprite, + mspriteframe_t ***frames, dspriteframe_t **dframes, + int *frame_numbers, const char *modname) +{ + int frame_index = 0; + __auto_type type = (dspriteframetype_t *) (dsprite + 1); + for (int i = 0; i < dsprite->numframes; i++) { + sprite->frames[i].type = type->type; + if (type->type == SPR_SINGLE) { + __auto_type frame = (dspriteframe_t *) (type + 1); + dframes[frame_index] = frame; + frames[frame_index] = &sprite->frames[i].frame; + frame_numbers[frame_index] = i; + frame_index += 1; + type = skip_frame (frame); + } else { + __auto_type group = (dspritegroup_t *) (type + 1); + type = find_group_frames (&sprite->frames[i].group, group, + frames + frame_index, + dframes + frame_index, + frame_numbers + frame_index, + modname); + for (int j = 0; j < group->numframes; j++) { + frame_numbers[frame_index + j] += i * 100; + } + frame_index += group->numframes; + } + } } void Mod_LoadSpriteModel (model_t *mod, void *buffer) { - dsprite_t *pin; - dspriteframetype_t *pframetype; - int numframes, size, version, i; - msprite_t *psprite; + __auto_type dsprite = (dsprite_t *) buffer; + msprite_t *sprite; - pin = (dsprite_t *) buffer; - - version = LittleLong (pin->version); - if (version != SPR_VERSION) + if (LittleLong (dsprite->version) != SPR_VERSION) { Sys_Error ("%s has wrong version number (%i should be %i)", - mod->path, version, SPR_VERSION); - - numframes = LittleLong (pin->numframes); - - size = field_offset (msprite_t, frames[numframes]); - - psprite = Hunk_AllocName (0, size, mod->name); - - mod->cache.data = psprite; - - psprite->type = LittleLong (pin->type); - psprite->maxwidth = LittleLong (pin->width); - psprite->maxheight = LittleLong (pin->height); - psprite->beamlength = LittleFloat (pin->beamlength); - mod->synctype = LittleLong (pin->synctype); - psprite->numframes = numframes; - - mod->mins[0] = mod->mins[1] = -psprite->maxwidth / 2; - mod->maxs[0] = mod->maxs[1] = psprite->maxwidth / 2; - mod->mins[2] = -psprite->maxheight / 2; - mod->maxs[2] = psprite->maxheight / 2; - - // load the frames - if (numframes < 1) - Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d", numframes); - - mod->numframes = numframes; - - pframetype = (dspriteframetype_t *) (pin + 1); - - for (i = 0; i < numframes; i++) { - spriteframetype_t frametype; - - frametype = LittleLong (pframetype->type); - psprite->frames[i].type = frametype; - - if (frametype == SPR_SINGLE) { - pframetype = (dspriteframetype_t *) - Mod_LoadSpriteFrame (mod, pframetype + 1, - &psprite->frames[i].frame, i); - } else { - pframetype = (dspriteframetype_t *) - Mod_LoadSpriteGroup (mod, pframetype + 1, - &psprite->frames[i].group, i); - } + mod->path, LittleLong (dsprite->version), SPR_VERSION); } + // total number of frames (direct and in groups) + int numframes = swap_sprite (dsprite); + + if (numframes < 1) { + Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d", numframes); + } + + sprite = Hunk_AllocName (0, field_offset (msprite_t, + frames[dsprite->numframes]), + mod->name); + sprite->type = dsprite->type; + sprite->beamlength = dsprite->beamlength; + sprite->numframes = dsprite->numframes; + sprite->data = 0; + + mod->cache.data = sprite; + mod->mins[0] = mod->mins[1] = -dsprite->width / 2; + mod->maxs[0] = mod->maxs[1] = dsprite->width / 2; + mod->mins[2] = -dsprite->height / 2; + mod->maxs[2] = dsprite->height / 2; + mod->numframes = dsprite->numframes; mod->type = mod_sprite; + + mod_sprite_ctx_t sprite_ctx = { + .mod = mod, + .dsprite = dsprite, + .sprite = sprite, + .numframes = numframes, + .frame_numbers = alloca (numframes * sizeof (int)), + .dframes = alloca (numframes * sizeof (dspriteframe_t *)), + .frames = alloca (numframes * sizeof (mspriteframe_t **)), + }; + find_frames (sprite, dsprite, sprite_ctx.frames, sprite_ctx.dframes, + sprite_ctx.frame_numbers, mod->name); + m_funcs->Mod_SpriteLoadFrames (&sprite_ctx); } diff --git a/libs/models/sprite/sw_model_sprite.c b/libs/models/sprite/sw_model_sprite.c index 8dc5a5461..6834413e9 100644 --- a/libs/models/sprite/sw_model_sprite.c +++ b/libs/models/sprite/sw_model_sprite.c @@ -28,10 +28,24 @@ # include "config.h" #endif +#ifdef HAVE_STRING_H +# include +#endif + +#include "QF/zone.h" + #include "mod_internal.h" void -sw_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, - int framenum) +sw_Mod_SpriteLoadFrames (mod_sprite_ctx_t *ctx) { + for (int i = 0; i < ctx->numframes; i++) { + __auto_type dframe = ctx->dframes[i]; + size_t pixels = dframe->width * dframe->height; + size_t size = field_offset (mspriteframe_t, pixels[pixels]); + mspriteframe_t *frame = Hunk_AllocName (0, size, ctx->mod->name); + *ctx->frames[i] = frame; + Mod_LoadSpriteFrame (frame, dframe); + memcpy (frame->pixels, dframe + 1, pixels); + } } diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 380ab3ca2..850d13beb 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -74,7 +74,7 @@ static vid_model_funcs_t model_funcs = { gl_Mod_LoadExternalSkins, gl_Mod_IQMFinish, 1, - gl_Mod_SpriteLoadTexture, + gl_Mod_SpriteLoadFrames, Skin_SetColormap, Skin_SetSkin, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 17e7be558..a4ad536f4 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -74,7 +74,7 @@ static vid_model_funcs_t model_funcs = { glsl_Mod_LoadExternalSkins, glsl_Mod_IQMFinish, 0, - glsl_Mod_SpriteLoadTexture, + glsl_Mod_SpriteLoadFrames, Skin_SetColormap, Skin_SetSkin, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 992292c7f..cc0186750 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -72,7 +72,7 @@ static vid_model_funcs_t model_funcs = { 0, sw_Mod_IQMFinish, 1, - sw_Mod_SpriteLoadTexture, + sw_Mod_SpriteLoadFrames, Skin_SetColormap, Skin_SetSkin, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 4139b9008..3a3638c1a 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -77,7 +77,7 @@ static vid_model_funcs_t model_funcs = { 0, sw_Mod_IQMFinish, 1, - sw_Mod_SpriteLoadTexture, + sw_Mod_SpriteLoadFrames, Skin_SetColormap, Skin_SetSkin, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 0114610b8..c2a5cca21 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -505,8 +505,7 @@ vulkan_Mod_IQMFinish (model_t *mod) } static void -vulkan_Mod_SpriteLoadTexture (model_t *mod, mspriteframe_t *pspriteframe, - int framenum) +vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx) { } @@ -582,7 +581,7 @@ static vid_model_funcs_t model_funcs = { vulkan_Mod_LoadExternalSkins, vulkan_Mod_IQMFinish, 0, - vulkan_Mod_SpriteLoadTexture, + vulkan_Mod_SpriteLoadFrames, Skin_SetColormap, Skin_SetSkin, From 0eb556b8f9b85128331d9d24d69b6cb30717329e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Dec 2021 10:02:35 +0900 Subject: [PATCH 1956/3664] [vulkan] Load sprite model data The vertices and frame images are loaded into the one memory object, with the vertices first followed by the images. The vertices are 2D xy+uv sets meant to be applied to the model transform frame, and are pre-computed for the sprite size (this part does support sprites with varying frame image sizes). The frame images are loaded into one image with each frame on its own layer. This will cause some problems if any sprites with varying frame image sizes are found, but the three sprites in quake are all uniform size. --- include/QF/Vulkan/qf_sprite.h | 98 +++++++++++ libs/models/sprite/vulkan_model_sprite.c | 201 +++++++++++++++++++++++ libs/video/renderer/vid_render_vulkan.c | 2 + 3 files changed, 301 insertions(+) create mode 100644 include/QF/Vulkan/qf_sprite.h diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h new file mode 100644 index 000000000..38b8f3e86 --- /dev/null +++ b/include/QF/Vulkan/qf_sprite.h @@ -0,0 +1,98 @@ +/* + qf_sprite.h + + Vulkan specific sprite model stuff + + Copyright (C) 2012 Bill Currie + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2012/1/7 + Date: 2021/1/18 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_sprite_h +#define __QF_Vulkan_qf_sprite_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/modelgen.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" + +typedef struct spritevrt_s { + float x, y, u, v; +} spritevrt_t; + +typedef struct qfv_sprite_s { + VkDeviceMemory memory; + VkBuffer verts; + VkImage image; + VkImageView view; +} qfv_sprite_t; + +typedef enum { + QFV_spriteDepth, + QFV_spriteGBuffer, + QFV_spriteTranslucent, + + QFV_spriteNumPasses +} QFV_SpriteSubpass; + +typedef struct spriteframe_s { + qfv_cmdbufferset_t cmdSet; +} spriteframe_t; + +typedef struct spriteframeset_s + DARRAY_TYPE (spriteframe_t) spriteframeset_t; + +typedef struct spriteindset_s + DARRAY_TYPE (unsigned) spriteindset_t; + +typedef struct spritectx_s { + spriteframeset_t frames; + VkPipeline depth; + VkPipeline gbuf; + VkDescriptorSet descriptors; + VkDescriptorPool pool; + VkDescriptorSetLayout setLayout; + VkPipelineLayout layout; + unsigned maxImages; + VkSampler sampler; + spriteindset_t texindices; +} spritectx_t; + +struct vulkan_ctx_s; +struct qfv_renderframe_s; +struct entity_s; +struct mod_sprite_ctx_s; + +void Vulkan_Mod_SpriteLoadFrames (struct mod_sprite_ctx_s *sprite_ctx, + struct vulkan_ctx_s *ctx); + +void Vulkan_SpriteBegin (struct qfv_renderframe_s *rFrame); +void Vulkan_DrawSprite (struct entity_s *ent, struct qfv_renderframe_s *rFrame); +void Vulkan_SpriteEnd (struct qfv_renderframe_s *rFrame); + +void Vulkan_Sprite_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Sprite_Shutdown (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_sprite_h diff --git a/libs/models/sprite/vulkan_model_sprite.c b/libs/models/sprite/vulkan_model_sprite.c index e69de29bb..434de6310 100644 --- a/libs/models/sprite/vulkan_model_sprite.c +++ b/libs/models/sprite/vulkan_model_sprite.c @@ -0,0 +1,201 @@ +/* + vulkan_model_sprite.c + + Sprite model mesh processing for Vulkan + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/12/13 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cvar.h" +#include "QF/darray.h" +#include "QF/image.h" +#include "QF/quakefs.h" +#include "QF/va.h" +#include "QF/Vulkan/qf_sprite.h" +#include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/barrier.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/staging.h" + +#include "compat.h" +#include "mod_internal.h" +#include "r_internal.h" +#include "vid_vulkan.h" + +static void +vulkan_sprite_clear (model_t *m, void *data) +{ + vulkan_ctx_t *ctx = data; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + msprite_t *msprite = m->cache.data; + __auto_type sprite = (qfv_sprite_t *) ((byte *) msprite + msprite->data); + + dfunc->vkDestroyBuffer (device->dev, sprite->verts, 0); + dfunc->vkDestroyImageView (device->dev, sprite->view, 0); + dfunc->vkDestroyImage (device->dev, sprite->image, 0); + dfunc->vkFreeMemory (device->dev, sprite->memory, 0); +} + +void +Vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx, vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, va (ctx->va_ctx, "sprite.load_frames: %s", + sprite_ctx->mod->name)); + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + model_t *mod = sprite_ctx->mod; + dsprite_t *dsprite = sprite_ctx->dsprite; + mod->clear = vulkan_sprite_clear; + mod->data = ctx; + + qfv_sprite_t *sprite = Hunk_AllocName (0, sizeof (*sprite), mod->name); + int mipLevels = QFV_MipLevels (dsprite->width, dsprite->height); + VkExtent3D extent = { dsprite->width, dsprite->height, 1 }; + sprite->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, + VK_FORMAT_R8G8B8A8_UNORM, extent, + mipLevels, sprite_ctx->numframes, + VK_SAMPLE_COUNT_1_BIT, + VK_IMAGE_USAGE_SAMPLED_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, sprite->image, + va (ctx->va_ctx, "image:%s", mod->name)); + + int numverts = 4 * sprite_ctx->numframes; + sprite->verts = QFV_CreateBuffer (device, numverts * sizeof (spritevrt_t), + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, sprite->verts, + va (ctx->va_ctx, "buffer:sprite:vertex:%s", + mod->name)); + + VkMemoryRequirements ireq; + dfunc->vkGetImageMemoryRequirements (device->dev, sprite->image, &ireq); + VkMemoryRequirements vreq; + dfunc->vkGetBufferMemoryRequirements (device->dev, sprite->verts, &vreq); + size_t size = QFV_NextOffset (QFV_NextOffset (0, 1, &vreq), 1, &ireq); + + sprite->memory = QFV_AllocBufferMemory (device, sprite->verts, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + size, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, sprite->memory, + va (ctx->va_ctx, "memory:sprite:%s", + sprite_ctx->mod->name)); + + QFV_BindBufferMemory (device, sprite->verts, sprite->memory, 0); + QFV_BindImageMemory (device, sprite->image, sprite->memory, + QFV_NextOffset (0, 1, &vreq)); + sprite->view = QFV_CreateImageView (device, sprite->image, + VK_IMAGE_VIEW_TYPE_2D_ARRAY, + VK_FORMAT_R8G8B8A8_UNORM, + VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, sprite->view, + va (ctx->va_ctx, "view:sprite:%s", + sprite_ctx->mod->name)); + + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, + va (ctx->va_ctx, + "sprite:%s", + sprite_ctx->mod->name), + size, ctx->cmdpool); + qfv_packet_t *packet = QFV_PacketAcquire (stage); + spritevrt_t *verts = QFV_PacketExtend (packet, + numverts * sizeof (spritevrt_t)); + int texsize = 4 * dsprite->width * dsprite->height; + byte *pixels = QFV_PacketExtend (packet, + sprite_ctx->numframes * texsize); + + for (int i = 0; i < sprite_ctx->numframes; i++) { + __auto_type dframe = sprite_ctx->dframes[i]; + mspriteframe_t f; + Mod_LoadSpriteFrame (&f, dframe); + verts[i * 4 + 0] = (spritevrt_t) { f.left, f.up, 0, 0 }; + verts[i * 4 + 1] = (spritevrt_t) { f.right, f.up, 1, 0 }; + verts[i * 4 + 2] = (spritevrt_t) { f.right, f.down, 1, 1 }; + verts[i * 4 + 3] = (spritevrt_t) { f.left, f.down, 0, 1 }; + Vulkan_ExpandPalette (pixels + i * texsize, (const byte *)(dframe + 1), + vid.palette32, 2, texsize / 4); + } + + qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; + bb.barrier.buffer = sprite->verts; + bb.barrier.size = numverts * sizeof (spritevrt_t); + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); + VkBufferCopy copy_region[] = { + { packet->offset, 0, numverts * sizeof (spritevrt_t) }, + }; + dfunc->vkCmdCopyBuffer (packet->cmd, stage->buffer, + sprite->verts, 1, ©_region[0]); + bb = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead]; + bb.barrier.buffer = sprite->verts; + bb.barrier.size = numverts * sizeof (spritevrt_t); + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); + + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = sprite->image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + + VkBufferImageCopy copy = { + packet->offset + numverts * sizeof (spritevrt_t), 0, 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, sprite_ctx->numframes}, + {0, 0, 0}, {dsprite->width, dsprite->height, 1}, + }; + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + sprite->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©); + QFV_GenerateMipMaps (device, packet->cmd, sprite->image, + mipLevels, dsprite->width, dsprite->height, + sprite_ctx->numframes); + + QFV_PacketSubmit (packet); + QFV_DestroyStagingBuffer (stage); + + sprite_ctx->sprite->data = (byte *) sprite - (byte *) sprite_ctx->sprite; + + qfvPopDebug (ctx); +} diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index c2a5cca21..bfaa95d0e 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -49,6 +49,7 @@ #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_particles.h" +#include "QF/Vulkan/qf_sprite.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/capture.h" @@ -507,6 +508,7 @@ vulkan_Mod_IQMFinish (model_t *mod) static void vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx) { + Vulkan_Mod_SpriteLoadFrames (sprite_ctx, vulkan_ctx); } static void From 2db8d11dd0dab9693a12994c23accaf1cde9c143 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Dec 2021 14:39:48 +0900 Subject: [PATCH 1957/3664] [vulkan] Clean up some excessive descriptor sets With the switch to multi-layer textures for brush models, the bsp and alias texture descriptor sets became identical and thus the definitions shareable. However, due to complications I don't want to address yet, they're still separately identified, but I should be able to use the texture set for most, if not all, pipelines. --- libs/video/renderer/vulkan/qfpipeline.plist | 39 ++++----------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 1527843e5..4026aa5ff 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -97,21 +97,7 @@ }, ); }; - alias_pool = { - flags = 0; - maxSets = 1; - bindings = ( - { - type = sampler; - descriptorCount = 1; - }, - { - type = sampled_image; - descriptorCount = $properties.limits.maxImages; - }, - ); - }; - quakebsp_pool = { + texture_pool = { flags = 0; maxSets = 1; bindings = ( @@ -125,6 +111,9 @@ }, ); }; + //FIXME probably should just share a larger pool + alias_pool = $properties.descriptorPools.texture_pool; + quakebsp_pool = $properties.descriptorPools.texture_pool; lighting_attach_pool = { flags = 0; maxSets = $frames.size; @@ -187,23 +176,7 @@ }, ); }; - quakebsp_set = { - bindings = ( - { - binding = 0; - descriptorType = sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 1; - descriptorType = sampled_image; - descriptorCount = $properties.limits.maxImages; - stageFlags = fragment; - }, - ); - }; - alias_set = { + texture_set = { bindings = ( { binding = 0; @@ -219,6 +192,8 @@ }, ); }; + quakebsp_set = $properties.setLayouts.texture_set; + alias_set = $properties.setLayouts.texture_set; lighting_attach = { bindings = ( { From 36e0d857a28ce3d2675ee7b28df76c5f3137a386 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Dec 2021 14:44:16 +0900 Subject: [PATCH 1958/3664] [vulkan] Create the non-C side of the sprite pipeline This adds the shaders and the pipeline specs. I'm not sure that the deferred rendering side of the render pass is appropriate, but I thought I'd give it a go, since quake sprites are really cutoff rather than translucent. --- libs/video/renderer/Makemodule.am | 20 +++++ libs/video/renderer/vulkan/qfpipeline.plist | 76 +++++++++++++++++++ libs/video/renderer/vulkan/shader.c | 12 +++ .../renderer/vulkan/shader/sprite_depth.frag | 27 +++++++ .../renderer/vulkan/shader/sprite_depth.vert | 31 ++++++++ .../renderer/vulkan/shader/sprite_gbuf.frag | 38 ++++++++++ .../renderer/vulkan/shader/sprite_gbuf.vert | 35 +++++++++ 7 files changed, 239 insertions(+) create mode 100644 libs/video/renderer/vulkan/shader/sprite_depth.frag create mode 100644 libs/video/renderer/vulkan/shader/sprite_depth.vert create mode 100644 libs/video/renderer/vulkan/shader/sprite_gbuf.frag create mode 100644 libs/video/renderer/vulkan/shader/sprite_gbuf.vert diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 11f8e343a..08b448ffd 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -287,6 +287,14 @@ vkparse_plist = \ vkshaderpath = libs/video/renderer/vulkan/shader +sprite_gbufv_src = $(vkshaderpath)/sprite_gbuf.vert +sprite_gbufv_c = $(vkshaderpath)/sprite_gbuf.vert.spvc +sprite_gbuff_src = $(vkshaderpath)/sprite_gbuf.frag +sprite_gbuff_c = $(vkshaderpath)/sprite_gbuf.frag.spvc +sprite_depthv_src = $(vkshaderpath)/sprite_depth.vert +sprite_depthv_c = $(vkshaderpath)/sprite_depth.vert.spvc +sprite_depthf_src = $(vkshaderpath)/sprite_depth.frag +sprite_depthf_c = $(vkshaderpath)/sprite_depth.frag.spvc twodv_src = $(vkshaderpath)/twod.vert twodv_c = $(vkshaderpath)/twod.vert.spvc twodf_src = $(vkshaderpath)/twod.frag @@ -331,6 +339,14 @@ pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc shadow_src = $(vkshaderpath)/shadow.geom shadow_c = $(vkshaderpath)/shadow.geom.spvc +$(sprite_gbufv_c): $(sprite_gbufv_src) + +$(sprite_gbuff_c): $(sprite_gbuff_src) + +$(sprite_depthv_c): $(sprite_depthv_src) + +$(sprite_depthf_c): $(sprite_depthf_src) + $(twodv_c): $(twodv_src) $(twodf_c): $(twodf_src) @@ -374,6 +390,10 @@ $(pushcolor_c): $(pushcolor_src) $(shadow_c): $(shadow_src) vkshader_c = \ + $(sprite_gbufv_c) \ + $(sprite_gbuff_c) \ + $(sprite_depthv_c) \ + $(sprite_depthf_c) \ $(twodv_c) \ $(twodf_c) \ $(quakebspv_c) \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 4026aa5ff..399352c0a 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -299,6 +299,26 @@ }, ); }; + sprite_layout = { + setLayouts = (matrix_set, spritevrt_set, texture_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4"; + }, + { + stageFlags = vertex|fragment; + offset = 64; + size = "4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "2 * 4 + 2 * 4 + 4 * 4"; + }, + ); + }; lighting_layout = { setLayouts = (lighting_attach, lighting_lights, lighting_shadow); }; @@ -344,6 +364,10 @@ topology = triangle_strip; primitiveRestartEnable = true; }; + sprite = { + topology = triangle_strip; + primitiveRestartEnable = true; + }; }; vertexInput = { @@ -802,6 +826,58 @@ layout = quakebsp_layout; renderPass = renderpass; }; + sprite_gbuf = { + subpass = 2; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/sprite_gbuf.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/sprite_gbuf.frag; + }, + ); + inputAssembly = $properties.inputAssembly.sprite; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_only; + colorBlend = $properties.pipelines.alias_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor, blend_constants ); + }; + layout = sprite_layout; + renderPass = renderpass; + }; + sprite_depth = { + subpass = 0; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/sprite_depth.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/sprite_depth.frag; + }, + ); + inputAssembly = $properties.inputAssembly.alias; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_and_write; + colorBlend = $properties.pipelines.alias_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = alias_layout; + renderPass = renderpass; + }; twod = { subpass = 1; stages = ( diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index d35fe82e5..a5329c443 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -54,6 +54,14 @@ #include "vid_vulkan.h" +static +#include "libs/video/renderer/vulkan/shader/sprite_gbuf.vert.spvc" +static +#include "libs/video/renderer/vulkan/shader/sprite_gbuf.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/sprite_depth.vert.spvc" +static +#include "libs/video/renderer/vulkan/shader/sprite_depth.frag.spvc" static #include "libs/video/renderer/vulkan/shader/twod.vert.spvc" static @@ -104,6 +112,10 @@ typedef struct shaderdata_s { } shaderdata_t; static shaderdata_t builtin_shaders[] = { + { "sprite_gbuf.vert", sprite_gbuf_vert, sizeof (sprite_gbuf_vert) }, + { "sprite_gbuf.frag", sprite_gbuf_frag, sizeof (sprite_gbuf_frag) }, + { "sprite_depth.vert", sprite_depth_vert, sizeof (sprite_depth_vert) }, + { "sprite_depth.frag", sprite_depth_frag, sizeof (sprite_depth_frag) }, { "twod.vert", twod_vert, sizeof (twod_vert) }, { "twod.frag", twod_frag, sizeof (twod_frag) }, { "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) }, diff --git a/libs/video/renderer/vulkan/shader/sprite_depth.frag b/libs/video/renderer/vulkan/shader/sprite_depth.frag new file mode 100644 index 000000000..c7d18cbd8 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/sprite_depth.frag @@ -0,0 +1,27 @@ +#version 450 + +layout (constant_id = 0) const int MaxTextures = 256; + +layout (set = 2, binding = 0) uniform sampler samp; +layout (set = 2, binding = 1) uniform texture2DArray sprites[MaxTextures]; + +layout (push_constant) uniform PushConstants { + layout (offset = 64) + int frame; + int spriteind; + // two slots + vec4 fog; +}; + +layout (location = 0) in vec2 st; + +void +main (void) +{ + vec4 pix; + + pix = texture (sampler2DArray(sprites[spriteind], samp), vec3 (st, frame)); + if (pix.a < 0.5) { + discard; + } +} diff --git a/libs/video/renderer/vulkan/shader/sprite_depth.vert b/libs/video/renderer/vulkan/shader/sprite_depth.vert new file mode 100644 index 000000000..39c1af0c7 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/sprite_depth.vert @@ -0,0 +1,31 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; +}; + +layout (set = 1, binding = 0) buffer Vertices { + vec4 xyuv[]; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; + int frame; +}; + +layout (location = 0) out vec2 st; + +void +main (void) +{ + vec4 v = xyuv[frame * 4 + gl_VertexIndex]; + + vec4 pos = vec4 (0, 0, 0, 1); + pos += v.x * Model[1] + v.y * Model[2]; + + gl_Position = Projection3d * (View * pos); + st = v.zw; +} diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag new file mode 100644 index 000000000..30cf24060 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag @@ -0,0 +1,38 @@ +#version 450 + +layout (constant_id = 0) const int MaxTextures = 256; + +layout (set = 2, binding = 0) uniform sampler samp; +layout (set = 2, binding = 1) uniform texture2DArray sprites[MaxTextures]; + +layout (push_constant) uniform PushConstants { + layout (offset = 64) + int frame; + int spriteind; + // two slots + vec4 fog; +}; + +layout (location = 0) in vec2 st; +layout (location = 1) in vec4 position; +layout (location = 2) in vec3 normal; + +layout (location = 0) out vec4 frag_color; +layout (location = 1) out vec4 frag_emission; +layout (location = 2) out vec4 frag_normal; +layout (location = 3) out vec4 frag_position; + +void +main (void) +{ + vec4 pix; + + pix = texture (sampler2DArray(sprites[spriteind], samp), vec3 (st, frame)); + if (pix.a < 0.5) { + discard; + } + frag_color = vec4(0,0,0,1); + frag_emission = pix; + frag_normal = vec4(normal, 1); + frag_position = position; +} diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.vert b/libs/video/renderer/vulkan/shader/sprite_gbuf.vert new file mode 100644 index 000000000..1aabd9a03 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.vert @@ -0,0 +1,35 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; +}; + +layout (set = 1, binding = 0) buffer Vertices { + vec4 xyuv[]; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; + int frame; +}; + +layout (location = 0) out vec2 st; +layout (location = 1) out vec4 position; +layout (location = 2) out vec3 normal; + +void +main (void) +{ + vec4 v = xyuv[frame * 4 + gl_VertexIndex]; + + vec4 pos = vec4 (0, 0, 0, 1); + pos += v.x * Model[1] + v.y * Model[2]; + + gl_Position = Projection3d * (View * pos); + st = v.zw; + position = pos; + normal = -vec3(Model[0]); +} From 743a732bd7b388fa43ad962db14a493606739c51 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Dec 2021 19:30:36 +0900 Subject: [PATCH 1959/3664] [vulkan] Correct the semantics of QFV_NextOffset I'm not at all sure what I was thinking when I designed it, but I certainly designed it wrong (to the point of being fairly useless). It turns out memory requirements are already aligned in size (so just multiplying is fine), and what I really wanted was to get the next offset aligned to the given requirements. --- include/QF/Vulkan/buffer.h | 2 +- libs/models/sprite/vulkan_model_sprite.c | 4 ++-- libs/video/renderer/vulkan/buffer.c | 6 ++---- libs/video/renderer/vulkan/vulkan_lighting.c | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h index f9cbbb0c9..374a496b1 100644 --- a/include/QF/Vulkan/buffer.h +++ b/include/QF/Vulkan/buffer.h @@ -45,7 +45,7 @@ VkBufferView QFV_CreateBufferView (struct qfv_device_s *device, VkBuffer buffer, VkFormat format, VkDeviceSize offset, VkDeviceSize size); -VkDeviceSize QFV_NextOffset (VkDeviceSize current, VkDeviceSize count, +VkDeviceSize QFV_NextOffset (VkDeviceSize current, const VkMemoryRequirements *requirements) __attribute__((pure)); diff --git a/libs/models/sprite/vulkan_model_sprite.c b/libs/models/sprite/vulkan_model_sprite.c index 434de6310..4372d118e 100644 --- a/libs/models/sprite/vulkan_model_sprite.c +++ b/libs/models/sprite/vulkan_model_sprite.c @@ -111,7 +111,7 @@ Vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx, vulkan_ctx_t *ctx) dfunc->vkGetImageMemoryRequirements (device->dev, sprite->image, &ireq); VkMemoryRequirements vreq; dfunc->vkGetBufferMemoryRequirements (device->dev, sprite->verts, &vreq); - size_t size = QFV_NextOffset (QFV_NextOffset (0, 1, &vreq), 1, &ireq); + size_t size = QFV_NextOffset (vreq.size, &ireq) + ireq.size; sprite->memory = QFV_AllocBufferMemory (device, sprite->verts, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, @@ -122,7 +122,7 @@ Vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx, vulkan_ctx_t *ctx) QFV_BindBufferMemory (device, sprite->verts, sprite->memory, 0); QFV_BindImageMemory (device, sprite->image, sprite->memory, - QFV_NextOffset (0, 1, &vreq)); + QFV_NextOffset (vreq.size, &ireq)); sprite->view = QFV_CreateImageView (device, sprite->image, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_R8G8B8A8_UNORM, diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index 063fe8c73..9d8b05679 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -164,10 +164,8 @@ QFV_CreateBufferView (qfv_device_t *device, VkBuffer buffer, VkFormat format, } VkDeviceSize -QFV_NextOffset (VkDeviceSize current, VkDeviceSize count, - const VkMemoryRequirements *requirements) +QFV_NextOffset (VkDeviceSize current, const VkMemoryRequirements *requirements) { VkDeviceSize align = requirements->alignment - 1; - VkDeviceSize size = (requirements->size + align) & ~align; - return ((current + align) & ~align) + count * size; + return ((current + align) & ~align); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index b3edfb640..2f1125602 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -334,7 +334,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) &requirements); lctx->light_memory = QFV_AllocBufferMemory (device, lbuffers->a[0], VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - QFV_NextOffset (0, frames, &requirements), 0); + frames * requirements.size, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, lctx->light_memory, "memory:lighting"); @@ -389,7 +389,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->light_buffer = lbuffers->a[i]; QFV_BindBufferMemory (device, lbuffers->a[i], lctx->light_memory, light_offset); - light_offset = QFV_NextOffset (light_offset, 1, &requirements); + light_offset += requirements.size; QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, lframe->cmd, "cmd:lighting"); From dafe59144639bf3088be9722351d0bf76fea0637 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Dec 2021 01:18:02 +0900 Subject: [PATCH 1960/3664] [renderer] Start merging sprite frame calculation This covers gl and sw. sw32 should be trivial (just haven't done it), but glsl will take a little. Vulkan will use it. --- include/r_internal.h | 2 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/gl/gl_mod_sprite.c | 51 ++---------------- libs/video/renderer/r_sprite.c | 73 ++++++++++++++++++++++++++ libs/video/renderer/sw/sw_rsprite.c | 45 +--------------- 5 files changed, 81 insertions(+), 91 deletions(-) create mode 100644 libs/video/renderer/r_sprite.c diff --git a/include/r_internal.h b/include/r_internal.h index af3e1d645..a1ea3d17c 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -95,5 +95,7 @@ void GLSL_SetPalette (void *data, const byte *palette); int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, vec3_t bbup, vec3_t bbright, vec3_t bbpn); +mspriteframe_t *R_GetSpriteFrame (const msprite_t *sprite, + const animation_t *animation); #endif//__r_internal_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 08b448ffd..772b70d86 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -39,6 +39,7 @@ video_renderer_common_sources = \ libs/video/renderer/r_light.c \ libs/video/renderer/r_main.c \ libs/video/renderer/r_part.c \ + libs/video/renderer/r_sprite.c \ libs/video/renderer/vid_common.c renderer_libs= \ diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index 913234776..583f518dc 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -57,50 +57,6 @@ varray_t2f_c4ub_v3f_t *gl_spriteVertexArray; void (*gl_R_DrawSpriteModel) (struct entity_s *ent); - -static mspriteframe_t * -R_GetSpriteFrame (entity_t *ent) -{ - float fullinterval, targettime, time; - float *pintervals; - int frame, numframes, i; - msprite_t *psprite; - mspriteframe_t *pspriteframe; - mspritegroup_t *pspritegroup; - - psprite = ent->renderer.model->cache.data; - frame = ent->animation.frame; - - if ((frame >= psprite->numframes) || (frame < 0)) { - Sys_MaskPrintf (SYS_dev, "R_DrawSprite: no such frame %d\n", frame); - frame = 0; - } - - if (psprite->frames[frame].type == SPR_SINGLE) { - pspriteframe = psprite->frames[frame].frame; - } else { - pspritegroup = psprite->frames[frame].group; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes - 1]; - - time = vr_data.realtime + ent->animation.syncbase; - - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval - // values are positive, so we don't have to worry about division by 0 - targettime = time - ((int) (time / fullinterval)) * fullinterval; - - for (i = 0; i < (numframes - 1); i++) { - if (pintervals[i] > targettime) - break; - } - - pspriteframe = pspritegroup->frames[i]; - } - - return pspriteframe; -} - static void R_DrawSpriteModel_f (entity_t *e) { @@ -116,7 +72,7 @@ R_DrawSpriteModel_f (entity_t *e) cameravec -= origin; // don't bother culling, it's just a single polygon without a surface cache - frame = R_GetSpriteFrame (e); + frame = R_GetSpriteFrame (sprite, &e->animation); if (!R_BillboardFrame (e, sprite->type, &cameravec[0], &up[0], &right[0], &pn[0])) { @@ -167,15 +123,14 @@ R_DrawSpriteModel_VA_f (entity_t *e) vec4f_t origin, point; int i; // unsigned int vacount; - msprite_t *psprite; + msprite_t *psprite = e->renderer.model->cache.data; mspriteframe_t *frame; varray_t2f_c4ub_v3f_t *VA; VA = gl_spriteVertexArray; // FIXME: Despair // don't bother culling, it's just a single polygon without a surface cache - frame = R_GetSpriteFrame (e); - psprite = e->renderer.model->cache.data; + frame = R_GetSpriteFrame (psprite, &e->animation); qfglBindTexture (GL_TEXTURE_2D, frame->gl_texturenum); // FIXME: DESPAIR diff --git a/libs/video/renderer/r_sprite.c b/libs/video/renderer/r_sprite.c new file mode 100644 index 000000000..ecce7ad55 --- /dev/null +++ b/libs/video/renderer/r_sprite.c @@ -0,0 +1,73 @@ +/* + r_sprite.c + + Draw Sprite Model + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/sys.h" + +#include "r_internal.h" + +mspriteframe_t * +R_GetSpriteFrame (const msprite_t *sprite, const animation_t *animation) +{ + mspritegroup_t *group; + mspriteframe_t *frame; + int i, numframes, frame_num; + float *intervals, fullinterval, targettime, time; + + frame_num = animation->frame; + + if ((frame_num >= sprite->numframes) || (frame_num < 0)) { + Sys_Printf ("R_DrawSprite: no such frame %d\n", frame_num); + frame_num = 0; + } + + if (sprite->frames[frame_num].type == SPR_SINGLE) { + frame = sprite->frames[frame_num].frame; + } else { + group = sprite->frames[frame_num].group; + intervals = group->intervals; + numframes = group->numframes; + fullinterval = intervals[numframes - 1]; + + time = vr_data.realtime + animation->syncbase; + + // when loading in Mod_LoadSpriteGroup, we guaranteed all interval + // values are positive, so we don't have to worry about division by 0 + targettime = time - ((int) (time / fullinterval)) * fullinterval; + + for (i = 0; i < (numframes - 1); i++) { + if (intervals[i] > targettime) + break; + } + + frame = group->frames[i]; + } + + return frame; +} diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 88b9c7782..ca2ee5d9b 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -239,54 +239,13 @@ R_SetupAndDrawSprite (void) D_DrawSprite (); } - -static mspriteframe_t * -R_GetSpriteframe (msprite_t *psprite) -{ - mspritegroup_t *pspritegroup; - mspriteframe_t *pspriteframe; - int i, numframes, frame; - float *pintervals, fullinterval, targettime, time; - - frame = currententity->animation.frame; - - if ((frame >= psprite->numframes) || (frame < 0)) { - Sys_Printf ("R_DrawSprite: no such frame %d\n", frame); - frame = 0; - } - - if (psprite->frames[frame].type == SPR_SINGLE) { - pspriteframe = psprite->frames[frame].frame; - } else { - pspritegroup = psprite->frames[frame].group; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes - 1]; - - time = vr_data.realtime + currententity->animation.syncbase; - - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval - // values are positive, so we don't have to worry about division by 0 - targettime = time - ((int) (time / fullinterval)) * fullinterval; - - for (i = 0; i < (numframes - 1); i++) { - if (pintervals[i] > targettime) - break; - } - - pspriteframe = pspritegroup->frames[i]; - } - - return pspriteframe; -} - - void R_DrawSprite (void) { msprite_t *sprite = currententity->renderer.model->cache.data; - r_spritedesc.pspriteframe = R_GetSpriteframe (sprite); + r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, + ¤tentity->animation); sprite_width = r_spritedesc.pspriteframe->width; sprite_height = r_spritedesc.pspriteframe->height; From c366b1b7bb6328f3178176272478ad2e7a3e6c24 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Dec 2021 01:22:05 +0900 Subject: [PATCH 1961/3664] [vulkan] Implement the sprite render passes It turned out the bindless approach wouldn't work too well for my design of the sprite objects, but I don't think that's a big issue at this stage (and it seems bindless is causing problems for brush/alias rendering via renderdoc and on my versa pro). However, I have figured out how to make effective use of descriptor sets (finally :P). The actual normal still needs checking, but the sprites are currently unlit so not an issue at this stage. --- include/QF/Vulkan/qf_sprite.h | 8 +- include/vid_vulkan.h | 1 + libs/models/sprite/vulkan_model_sprite.c | 9 +- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vid_render_vulkan.c | 2 + libs/video/renderer/vulkan/qfpipeline.plist | 50 ++- .../renderer/vulkan/shader/sprite_depth.frag | 5 +- .../renderer/vulkan/shader/sprite_depth.vert | 6 +- .../renderer/vulkan/shader/sprite_gbuf.frag | 5 +- .../renderer/vulkan/shader/sprite_gbuf.vert | 6 +- libs/video/renderer/vulkan/vulkan_main.c | 3 +- libs/video/renderer/vulkan/vulkan_sprite.c | 346 ++++++++++++++++++ 12 files changed, 412 insertions(+), 30 deletions(-) create mode 100644 libs/video/renderer/vulkan/vulkan_sprite.c diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index 38b8f3e86..a9a147380 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -47,6 +47,7 @@ typedef struct qfv_sprite_s { VkBuffer verts; VkImage image; VkImageView view; + VkDescriptorSet descriptors; } qfv_sprite_t; typedef enum { @@ -64,20 +65,15 @@ typedef struct spriteframe_s { typedef struct spriteframeset_s DARRAY_TYPE (spriteframe_t) spriteframeset_t; -typedef struct spriteindset_s - DARRAY_TYPE (unsigned) spriteindset_t; - typedef struct spritectx_s { spriteframeset_t frames; VkPipeline depth; VkPipeline gbuf; - VkDescriptorSet descriptors; VkDescriptorPool pool; VkDescriptorSetLayout setLayout; VkPipelineLayout layout; unsigned maxImages; VkSampler sampler; - spriteindset_t texindices; } spritectx_t; struct vulkan_ctx_s; @@ -85,6 +81,8 @@ struct qfv_renderframe_s; struct entity_s; struct mod_sprite_ctx_s; +void Vulkan_Sprite_DescriptorSet (struct vulkan_ctx_s *ctx, + qfv_sprite_t *sprite); void Vulkan_Mod_SpriteLoadFrames (struct mod_sprite_ctx_s *sprite_ctx, struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index bb5b8a779..fec50b878 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -59,6 +59,7 @@ typedef struct vulkan_ctx_s { struct matrixctx_s *matrix_context; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; + struct spritectx_s *sprite_context; struct drawctx_s *draw_context; struct lightingctx_s *lighting_context; struct composectx_s *compose_context; diff --git a/libs/models/sprite/vulkan_model_sprite.c b/libs/models/sprite/vulkan_model_sprite.c index 4372d118e..0eaba1534 100644 --- a/libs/models/sprite/vulkan_model_sprite.c +++ b/libs/models/sprite/vulkan_model_sprite.c @@ -102,7 +102,7 @@ Vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx, vulkan_ctx_t *ctx) int numverts = 4 * sprite_ctx->numframes; sprite->verts = QFV_CreateBuffer (device, numverts * sizeof (spritevrt_t), VK_BUFFER_USAGE_TRANSFER_DST_BIT - | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, sprite->verts, va (ctx->va_ctx, "buffer:sprite:vertex:%s", mod->name)); @@ -149,10 +149,11 @@ Vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx, vulkan_ctx_t *ctx) Mod_LoadSpriteFrame (&f, dframe); verts[i * 4 + 0] = (spritevrt_t) { f.left, f.up, 0, 0 }; verts[i * 4 + 1] = (spritevrt_t) { f.right, f.up, 1, 0 }; - verts[i * 4 + 2] = (spritevrt_t) { f.right, f.down, 1, 1 }; - verts[i * 4 + 3] = (spritevrt_t) { f.left, f.down, 0, 1 }; + verts[i * 4 + 2] = (spritevrt_t) { f.left, f.down, 0, 1 }; + verts[i * 4 + 3] = (spritevrt_t) { f.right, f.down, 1, 1 }; Vulkan_ExpandPalette (pixels + i * texsize, (const byte *)(dframe + 1), vid.palette32, 2, texsize / 4); + *sprite_ctx->frames[i] = (mspriteframe_t *) (ptrdiff_t) i; } qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; @@ -195,6 +196,8 @@ Vulkan_Mod_SpriteLoadFrames (mod_sprite_ctx_t *sprite_ctx, vulkan_ctx_t *ctx) QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); + Vulkan_Sprite_DescriptorSet (ctx, sprite); + sprite_ctx->sprite->data = (byte *) sprite - (byte *) sprite_ctx->sprite; qfvPopDebug (ctx); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 772b70d86..086bc6675 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -267,6 +267,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ libs/video/renderer/vulkan/vulkan_particles.c \ + libs/video/renderer/vulkan/vulkan_sprite.c \ libs/video/renderer/vulkan/vulkan_texture.c \ libs/video/renderer/vulkan/vulkan_vid_common.c diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index bfaa95d0e..7c2e03ca6 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -104,6 +104,7 @@ vulkan_R_Init (void) Vulkan_Matrix_Init (vulkan_ctx); Vulkan_Alias_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); + Vulkan_Sprite_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); Vulkan_Particles_Init (vulkan_ctx); Vulkan_Lighting_Init (vulkan_ctx); @@ -629,6 +630,7 @@ vulkan_vid_render_shutdown (void) Vulkan_Compose_Shutdown (vulkan_ctx); Vulkan_Lighting_Shutdown (vulkan_ctx); Vulkan_Draw_Shutdown (vulkan_ctx); + Vulkan_Sprite_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Alias_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 399352c0a..6739202a9 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -58,6 +58,7 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; + sprite_sampler = $properties.samplers.alias_sampler; shadow_sampler = { magFilter = linear; minFilter = linear; @@ -111,6 +112,20 @@ }, ); }; + sprite_pool = { + flags = free_descriptor_set; + maxSets = 64; //FIXME cvar? + bindings = ( + { + type = uniform_buffer; + descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; + }, + { + type = combined_image_sampler; + descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; + }, + ); + }; //FIXME probably should just share a larger pool alias_pool = $properties.descriptorPools.texture_pool; quakebsp_pool = $properties.descriptorPools.texture_pool; @@ -194,6 +209,22 @@ }; quakebsp_set = $properties.setLayouts.texture_set; alias_set = $properties.setLayouts.texture_set; + sprite_set = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + binding = 1; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; lighting_attach = { bindings = ( { @@ -300,21 +331,16 @@ ); }; sprite_layout = { - setLayouts = (matrix_set, spritevrt_set, texture_set); + setLayouts = (matrix_set, sprite_set); pushConstantRanges = ( { stageFlags = vertex; offset = 0; - size = "16 * 4"; - }, - { - stageFlags = vertex|fragment; - offset = 64; - size = "4"; + size = "16 * 4 + 4"; }, { stageFlags = fragment; - offset = 68; + offset = 64; size = "2 * 4 + 2 * 4 + 4 * 4"; }, ); @@ -371,6 +397,10 @@ }; vertexInput = { + index_only = { + bindings = (); + attributes = (); + }; alias = { bindings = ( { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, @@ -840,6 +870,7 @@ module = $builtin/sprite_gbuf.frag; }, ); + vertexInput = $properties.vertexInput.index_only; inputAssembly = $properties.inputAssembly.sprite; viewport = $properties.viewport; rasterization = $properties.rasterization.cw_cull_back; @@ -866,6 +897,7 @@ module = $builtin/sprite_depth.frag; }, ); + vertexInput = $properties.vertexInput.index_only; inputAssembly = $properties.inputAssembly.alias; viewport = $properties.viewport; rasterization = $properties.rasterization.cw_cull_back; @@ -875,7 +907,7 @@ dynamic = { dynamicState = ( viewport, scissor ); }; - layout = alias_layout; + layout = sprite_layout; renderPass = renderpass; }; twod = { diff --git a/libs/video/renderer/vulkan/shader/sprite_depth.frag b/libs/video/renderer/vulkan/shader/sprite_depth.frag index c7d18cbd8..3d7b95522 100644 --- a/libs/video/renderer/vulkan/shader/sprite_depth.frag +++ b/libs/video/renderer/vulkan/shader/sprite_depth.frag @@ -2,8 +2,7 @@ layout (constant_id = 0) const int MaxTextures = 256; -layout (set = 2, binding = 0) uniform sampler samp; -layout (set = 2, binding = 1) uniform texture2DArray sprites[MaxTextures]; +layout (set = 1, binding = 1) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { layout (offset = 64) @@ -20,7 +19,7 @@ main (void) { vec4 pix; - pix = texture (sampler2DArray(sprites[spriteind], samp), vec3 (st, frame)); + pix = texture (Texture, vec3 (st, frame)); if (pix.a < 0.5) { discard; } diff --git a/libs/video/renderer/vulkan/shader/sprite_depth.vert b/libs/video/renderer/vulkan/shader/sprite_depth.vert index 39c1af0c7..430603dd3 100644 --- a/libs/video/renderer/vulkan/shader/sprite_depth.vert +++ b/libs/video/renderer/vulkan/shader/sprite_depth.vert @@ -7,8 +7,8 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 Projection2d; }; -layout (set = 1, binding = 0) buffer Vertices { - vec4 xyuv[]; +layout (set = 1, binding = 0) uniform Vertices { + vec4 xyuv[4]; }; layout (push_constant) uniform PushConstants { @@ -23,7 +23,7 @@ main (void) { vec4 v = xyuv[frame * 4 + gl_VertexIndex]; - vec4 pos = vec4 (0, 0, 0, 1); + vec4 pos = Model[3]; pos += v.x * Model[1] + v.y * Model[2]; gl_Position = Projection3d * (View * pos); diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag index 30cf24060..bb2716def 100644 --- a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag @@ -2,8 +2,7 @@ layout (constant_id = 0) const int MaxTextures = 256; -layout (set = 2, binding = 0) uniform sampler samp; -layout (set = 2, binding = 1) uniform texture2DArray sprites[MaxTextures]; +layout (set = 1, binding = 1) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { layout (offset = 64) @@ -27,7 +26,7 @@ main (void) { vec4 pix; - pix = texture (sampler2DArray(sprites[spriteind], samp), vec3 (st, frame)); + pix = texture (Texture, vec3 (st, frame)); if (pix.a < 0.5) { discard; } diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.vert b/libs/video/renderer/vulkan/shader/sprite_gbuf.vert index 1aabd9a03..acbf18a2e 100644 --- a/libs/video/renderer/vulkan/shader/sprite_gbuf.vert +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.vert @@ -7,8 +7,8 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 Projection2d; }; -layout (set = 1, binding = 0) buffer Vertices { - vec4 xyuv[]; +layout (set = 1, binding = 0) uniform Vertices { + vec4 xyuv[4]; }; layout (push_constant) uniform PushConstants { @@ -25,7 +25,7 @@ main (void) { vec4 v = xyuv[frame * 4 + gl_VertexIndex]; - vec4 pos = vec4 (0, 0, 0, 1); + vec4 pos = Model[3]; pos += v.x * Model[1] + v.y * Model[2]; gl_Position = Projection3d * (View * pos); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index b4ba322dc..a8cf1a1d7 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -53,6 +53,7 @@ #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_particles.h" +#include "QF/Vulkan/qf_sprite.h" //#include "QF/Vulkan/qf_textures.h" #include "QF/Vulkan/renderpass.h" @@ -110,7 +111,7 @@ Vulkan_RenderEntities (qfv_renderframe_t *rFrame) RE_LOOP (alias, Alias); //RE_LOOP (iqm, IQM); - //RE_LOOP (sprite, Sprite); + RE_LOOP (sprite, Sprite); } static void diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c new file mode 100644 index 000000000..ce4dcc599 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -0,0 +1,346 @@ +/* + vulkan_sprite.c + + Vulkan sprite model pipeline + + Copyright (C) 2012 Bill Currie + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2012/1/7 + Date: 2021/12/14 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "qfalloca.h" + +#include "QF/cvar.h" +#include "QF/darray.h" +#include "QF/image.h" +#include "QF/render.h" +#include "QF/skin.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "QF/scene/entity.h" + +#include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_sprite.h" +#include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/renderpass.h" + +#include "r_internal.h" +#include "vid_vulkan.h" + +typedef struct { + VkShaderStageFlags stageFlags; + uint32_t offset; + uint32_t size; + const void *data; +} qfv_push_constants_t; + +static const char * __attribute__((used)) sprite_pass_names[] = { + "depth", + "g-buffer", + "translucent", +}; + +static QFV_Subpass subpass_map[] = { + QFV_passDepth, // QFV_spriteDepth + QFV_passGBuffer, // QFV_spriteGBuffer + QFV_passTranslucent, // QFV_spriteTranslucent +}; + +static void +emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, + int numPC, qfv_push_constants_t *constants, + qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + spritectx_t *sctx = ctx->sprite_context; + + for (int i = 0; i < numPC; i++) { + dfunc->vkCmdPushConstants (cmd, sctx->layout, constants[i].stageFlags, + constants[i].offset, constants[i].size, + constants[i].data); + } + VkDescriptorSet sets[] = { + sprite->descriptors, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + sctx->layout, 1, 1, sets, 0, 0); + dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); +} + +void +Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + spritectx_t *sctx = ctx->sprite_context; + spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame]; + model_t *model = ent->renderer.model; + msprite_t *sprite = model->cache.data; + animation_t *animation = &ent->animation; + + mat4f_t mat; + uint32_t frame; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat), mat }, + { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + 64, sizeof (frame), &frame }, + }; + + frame = (ptrdiff_t) R_GetSpriteFrame (sprite, animation); + + mat[3] = Transform_GetWorldPosition (ent->transform); + vec4f_t cameravec = {r_origin[0], r_origin[1], r_origin[2], 0 }; + vec4f_t svpn = {}, svright = {}, svup = {}; + cameravec -= mat[3]; + R_BillboardFrame (ent, sprite->type, &cameravec[0], + &svup[0], &svright[0], &svpn[0]); + mat[2] = svup; + mat[1] = svright; + mat[0] = -svpn; + + emit_commands (aframe->cmdSet.a[QFV_spriteDepth], + (qfv_sprite_t *) ((byte *) sprite + sprite->data), + 2, push_constants, rFrame); + emit_commands (aframe->cmdSet.a[QFV_spriteGBuffer], + (qfv_sprite_t *) ((byte *) sprite + sprite->data), + 2, push_constants, rFrame); +} + +static void +sprite_begin_subpass (QFV_SpriteSubpass subpass, VkPipeline pipeline, + qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + spritectx_t *sctx = ctx->sprite_context; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; + spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = aframe->cmdSet.a[subpass]; + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + rFrame->renderpass->renderpass, subpass_map[subpass], + cframe->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "sprite:%s", + sprite_pass_names[subpass]), + { 0.6, 0.5, 0, 1}); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + VkDescriptorSet sets[] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + sctx->layout, 0, 1, sets, 0, 0); + dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); + + //XXX glsl_Fog_GetColor (fog); + //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; +} + +static void +sprite_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + QFV_duCmdEndLabel (device, cmd); + dfunc->vkEndCommandBuffer (cmd); +} + +void +Vulkan_SpriteBegin (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + spritectx_t *sctx = ctx->sprite_context; + spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame]; + + //XXX quat_t fog; + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], + aframe->cmdSet.a[QFV_spriteDepth]); + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], + aframe->cmdSet.a[QFV_spriteGBuffer]); + + sprite_begin_subpass (QFV_spriteDepth, sctx->depth, rFrame); + sprite_begin_subpass (QFV_spriteGBuffer, sctx->gbuf, rFrame); +} + +void +Vulkan_SpriteEnd (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + spritectx_t *sctx = ctx->sprite_context; + spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame]; + + sprite_end_subpass (aframe->cmdSet.a[QFV_spriteDepth], ctx); + sprite_end_subpass (aframe->cmdSet.a[QFV_spriteGBuffer], ctx); +} + +static VkDescriptorBufferInfo base_buffer_info = { + .range = VK_WHOLE_SIZE, +}; +static VkDescriptorImageInfo base_image_info = { + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, +}; +static VkWriteDescriptorSet base_buffer_write = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstBinding = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, +}; +static VkWriteDescriptorSet base_image_write = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstBinding = 1, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, +}; + +void +Vulkan_Sprite_DescriptorSet (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + spritectx_t *sctx = ctx->sprite_context; + + //FIXME kinda dumb + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = sctx->setLayout; + } + __auto_type sets = QFV_AllocateDescriptorSet (device, sctx->pool, layouts); + sprite->descriptors = sets->a[0]; + free (sets); + + VkDescriptorBufferInfo bufferInfo[1]; + bufferInfo[0] = base_buffer_info; + bufferInfo[0].buffer = sprite->verts; + + VkDescriptorImageInfo imageInfo[1]; + imageInfo[0] = base_image_info; + imageInfo[0].sampler = sctx->sampler; + imageInfo[0].imageView = sprite->view; + + VkWriteDescriptorSet write[2]; + write[0] = base_buffer_write; + write[0].dstSet = sprite->descriptors; + write[0].pBufferInfo = bufferInfo; + write[1] = base_image_write; + write[1].dstSet = sprite->descriptors; + write[1].pImageInfo = imageInfo; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); +} + +void +Vulkan_Sprite_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + qfvPushDebug (ctx, "sprite init"); + + spritectx_t *sctx = calloc (1, sizeof (spritectx_t)); + ctx->sprite_context = sctx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&sctx->frames, frames); + DARRAY_RESIZE (&sctx->frames, frames); + sctx->frames.grow = 0; + + sctx->depth = Vulkan_CreatePipeline (ctx, "sprite_depth"); + sctx->gbuf = Vulkan_CreatePipeline (ctx, "sprite_gbuf"); + sctx->layout = Vulkan_CreatePipelineLayout (ctx, "sprite_layout"); + sctx->sampler = Vulkan_CreateSampler (ctx, "sprite_sampler"); + + //FIXME too many places + __auto_type limits = device->physDev->properties.limits; + sctx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8); + sctx->pool = Vulkan_CreateDescriptorPool (ctx, "sprite_pool"); + sctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "sprite_set"); + + for (size_t i = 0; i < frames; i++) { + __auto_type aframe = &sctx->frames.a[i]; + + DARRAY_INIT (&aframe->cmdSet, QFV_spriteNumPasses); + DARRAY_RESIZE (&aframe->cmdSet, QFV_spriteNumPasses); + aframe->cmdSet.grow = 0; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &aframe->cmdSet); + + for (int j = 0; j < QFV_spriteNumPasses; j++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + aframe->cmdSet.a[j], + va (ctx->va_ctx, "cmd:sprite:%zd:%s", i, + sprite_pass_names[j])); + } + } + qfvPopDebug (ctx); +} + +void +Vulkan_Sprite_Shutdown (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + spritectx_t *sctx = ctx->sprite_context; + + for (size_t i = 0; i < sctx->frames.size; i++) { + __auto_type aframe = &sctx->frames.a[i]; + free (aframe->cmdSet.a); + } + + dfunc->vkDestroyPipeline (device->dev, sctx->depth, 0); + dfunc->vkDestroyPipeline (device->dev, sctx->gbuf, 0); + free (sctx->frames.a); + free (sctx); +} From 5223752f9e86d4f88fed84aa497449441928b4bb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Dec 2021 10:45:25 +0900 Subject: [PATCH 1962/3664] [vulkan] Fix lighting size calculation It turns out the required memory size is not guaranteed to be aligned. --- libs/video/renderer/vulkan/vulkan_lighting.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 2f1125602..5e62e9f31 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -332,9 +332,10 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) VkMemoryRequirements requirements; dfunc->vkGetBufferMemoryRequirements (device->dev, lbuffers->a[0], &requirements); + size_t light_size = QFV_NextOffset (requirements.size, &requirements); lctx->light_memory = QFV_AllocBufferMemory (device, lbuffers->a[0], VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - frames * requirements.size, 0); + frames * light_size, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, lctx->light_memory, "memory:lighting"); @@ -389,7 +390,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->light_buffer = lbuffers->a[i]; QFV_BindBufferMemory (device, lbuffers->a[i], lctx->light_memory, light_offset); - light_offset += requirements.size; + light_offset += light_size; QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, lframe->cmd, "cmd:lighting"); From f7c14a9b3912e93092f4b664b2463b4e35fe03ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Dec 2021 16:24:53 +0900 Subject: [PATCH 1963/3664] [sw32] Use the shared R_GetSpriteFrame One less copy of near-identical code. --- libs/video/renderer/sw32/sw32_rsprite.c | 44 ++----------------------- 1 file changed, 2 insertions(+), 42 deletions(-) diff --git a/libs/video/renderer/sw32/sw32_rsprite.c b/libs/video/renderer/sw32/sw32_rsprite.c index dc6e4a340..40f8f5a38 100644 --- a/libs/video/renderer/sw32/sw32_rsprite.c +++ b/libs/video/renderer/sw32/sw32_rsprite.c @@ -236,53 +236,13 @@ R_SetupAndDrawSprite (void) } -static mspriteframe_t * -R_GetSpriteframe (msprite_t *psprite) -{ - mspritegroup_t *pspritegroup; - mspriteframe_t *pspriteframe; - int i, numframes, frame; - float *pintervals, fullinterval, targettime, time; - - frame = currententity->animation.frame; - - if ((frame >= psprite->numframes) || (frame < 0)) { - Sys_Printf ("R_DrawSprite: no such frame %d\n", frame); - frame = 0; - } - - if (psprite->frames[frame].type == SPR_SINGLE) { - pspriteframe = psprite->frames[frame].frame; - } else { - pspritegroup = psprite->frames[frame].group; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes - 1]; - - time = vr_data.realtime + currententity->animation.syncbase; - - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval - // values are positive, so we don't have to worry about division by 0 - targettime = time - ((int) (time / fullinterval)) * fullinterval; - - for (i = 0; i < (numframes - 1); i++) { - if (pintervals[i] > targettime) - break; - } - - pspriteframe = pspritegroup->frames[i]; - } - - return pspriteframe; -} - - void sw32_R_DrawSprite (void) { msprite_t *sprite = currententity->renderer.model->cache.data; - sw32_r_spritedesc.pspriteframe = R_GetSpriteframe (sprite); + sw32_r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, + ¤tentity->animation); sprite_width = sw32_r_spritedesc.pspriteframe->width; sprite_height = sw32_r_spritedesc.pspriteframe->height; From 6a7f78485a2b4f52cf998e95724d0deae255ade9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Dec 2021 16:40:51 +0900 Subject: [PATCH 1964/3664] [zone] Use memccpy instead of strncpy Probably the best way to tell gcc I know what I'm doing. --- libs/util/zone.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index 2f083d282..98e4febfb 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -613,7 +613,7 @@ Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) h->size = size; h->sentinal1 = HUNK_SENTINAL; h->sentinal2 = HUNK_SENTINAL; - strncpy (h->name, name, sizeof (h->name)); + memccpy (h->name, name, 0, sizeof (h->name)); return (void *) (h + 1); } @@ -794,7 +794,7 @@ Cache_Move (cache_system_t *c) memcpy (new + 1, c + 1, c->size - sizeof (cache_system_t)); new->user = c->user; - strncpy (new->name, c->name, sizeof (new->name)); + memccpy (new->name, c->name, 0, sizeof (new->name)); Cache_Free (c->user); new->user->data = (void *) (new + 1); } else { @@ -1142,7 +1142,7 @@ Cache_Alloc_r (memhunk_t *hunk, cache_user_t *c, size_t size, const char *name) while (1) { cs = Cache_TryAlloc (hunk, size, false); if (cs) { - strncpy (cs->name, name, sizeof (cs->name)); + memccpy (cs->name, name, 0, sizeof (cs->name)); c->data = (void *) (cs + 1); cs->user = c; break; From 0d4ece875d50b1e81e0eef42474a769b23d739fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Dec 2021 22:53:19 +0900 Subject: [PATCH 1965/3664] [vulkan] Use indexed initializers for barriers This will make maintaining the arrays much easier: no worries about getting things out of sync. --- include/QF/Vulkan/barrier.h | 4 ++-- libs/video/renderer/vulkan/barrier.c | 35 ++++++++++------------------ 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h index 98073c418..0a6d78af1 100644 --- a/include/QF/Vulkan/barrier.h +++ b/include/QF/Vulkan/barrier.h @@ -13,7 +13,7 @@ typedef struct { VkBufferMemoryBarrier barrier; } qfv_bufferbarrier_t; -//XXX Note: imageBarriers and the enum must be kept in sync +// image layout transitions enum { qfv_LT_Undefined_to_TransferDst, qfv_LT_TransferDst_to_TransferSrc, @@ -24,7 +24,7 @@ enum { qfv_LT_Undefined_to_Color, }; -//XXX Note: bufferBarriers and the enum must be kept in sync +// buffer barriers enum { qfv_BB_Unknown_to_TransferWrite, qfv_BB_TransferWrite_to_VertexAttrRead, diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c index 75d96c8cf..2ab04d423 100644 --- a/libs/video/renderer/vulkan/barrier.c +++ b/libs/video/renderer/vulkan/barrier.c @@ -32,8 +32,7 @@ #include "QF/Vulkan/barrier.h" const qfv_imagebarrier_t imageBarriers[] = { - // undefined -> transfer dst optimal - { + [qfv_LT_Undefined_to_TransferDst] = { .srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .barrier = { @@ -46,8 +45,7 @@ const qfv_imagebarrier_t imageBarriers[] = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } }, }, - // transfer dst optimal -> transfer src optimal - { + [qfv_LT_TransferDst_to_TransferSrc] = { .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .barrier = { @@ -60,8 +58,7 @@ const qfv_imagebarrier_t imageBarriers[] = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } }, }, - // transfer dst optimal -> shader read only optimal - { + [qfv_LT_TransferDst_to_ShaderReadOnly] = { .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, .barrier = { @@ -74,8 +71,7 @@ const qfv_imagebarrier_t imageBarriers[] = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } }, }, - // transfer src optimal -> shader read only optimal - { + [qfv_LT_TransferSrc_to_ShaderReadOnly] = { .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, .barrier = { @@ -88,8 +84,7 @@ const qfv_imagebarrier_t imageBarriers[] = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } }, }, - // shader read only optimal -> transfer dst optimal - { + [qfv_LT_ShaderReadOnly_to_TransferDst] = { .srcStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .barrier = { @@ -102,8 +97,7 @@ const qfv_imagebarrier_t imageBarriers[] = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } }, }, - // undefined -> depth stencil attachment optimal - { + [qfv_LT_Undefined_to_DepthStencil] = { .srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, .dstStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, .barrier = { @@ -117,8 +111,7 @@ const qfv_imagebarrier_t imageBarriers[] = { { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 } }, }, - // undefined -> color attachment optimal - { + [qfv_LT_Undefined_to_Color] = { .srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, .dstStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .barrier = { @@ -135,8 +128,7 @@ const qfv_imagebarrier_t imageBarriers[] = { }; const qfv_bufferbarrier_t bufferBarriers[] = { - // unknown to transfer write - { + [qfv_BB_Unknown_to_TransferWrite] = { .srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .barrier = { @@ -145,8 +137,7 @@ const qfv_bufferbarrier_t bufferBarriers[] = { VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, }, }, - // transfer write to vertex attribute read - { + [qfv_BB_TransferWrite_to_VertexAttrRead] = { .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, .barrier = { @@ -155,8 +146,7 @@ const qfv_bufferbarrier_t bufferBarriers[] = { VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, }, }, - // transfer write to index read - { + [qfv_BB_TransferWrite_to_IndexRead] = { .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, .barrier = { @@ -165,9 +155,8 @@ const qfv_bufferbarrier_t bufferBarriers[] = { VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, }, }, - // transfer write to uniform read - // note: not necessarily optimal as it uses vertex shader for dst - { + [qfv_BB_TransferWrite_to_UniformRead] = { + // note: not necessarily optimal as it uses vertex shader for dst .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, .barrier = { From 93f806ccfb1464738dd46c6be6ac8dce67556921 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Dec 2021 22:55:44 +0900 Subject: [PATCH 1966/3664] [vulkan] Make device.h more include-order independent --- include/QF/Vulkan/device.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h index 2ebc7b1d9..f93a8a5c2 100644 --- a/include/QF/Vulkan/device.h +++ b/include/QF/Vulkan/device.h @@ -1,6 +1,8 @@ #ifndef __QF_Vulkan_device_h #define __QF_Vulkan_device_h +#include "QF/Vulkan/qf_vid.h" + typedef struct qfv_devfuncs_s { #define DEVICE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; #define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; From 7901f8796018e67df73ae23131763bb6b4e0ea2e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Dec 2021 23:00:17 +0900 Subject: [PATCH 1967/3664] [vulkan] Add support for compute shaders This needed changing Vulkan_CreatePipeline to Vulkan_CreateGraphicsPipeline for consistency (and parsing the difference from a plist seemed... not worth thinking about). --- include/QF/Vulkan/qf_vid.h | 5 +++- libs/video/renderer/vulkan/vkparse.c | 30 ++++++++++++++++++- libs/video/renderer/vulkan/vkparse.h | 6 ++-- libs/video/renderer/vulkan/vkparse.plist | 14 +++++++++ libs/video/renderer/vulkan/vulkan_alias.c | 4 +-- libs/video/renderer/vulkan/vulkan_bsp.c | 10 +++---- libs/video/renderer/vulkan/vulkan_compose.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- libs/video/renderer/vulkan/vulkan_sprite.c | 4 +-- .../video/renderer/vulkan/vulkan_vid_common.c | 22 ++++++++++++-- 11 files changed, 83 insertions(+), 18 deletions(-) diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 1a94898a3..f729c2b65 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -69,7 +69,10 @@ void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); void Vulkan_Shutdown_Common (struct vulkan_ctx_s *ctx); void Vulkan_CreateStagingBuffers (struct vulkan_ctx_s *ctx); -VkPipeline Vulkan_CreatePipeline (struct vulkan_ctx_s *ctx, const char *name); +VkPipeline Vulkan_CreateComputePipeline (struct vulkan_ctx_s *ctx, + const char *name); +VkPipeline Vulkan_CreateGraphicsPipeline (struct vulkan_ctx_s *ctx, + const char *name); VkDescriptorPool Vulkan_CreateDescriptorPool (struct vulkan_ctx_s *ctx, const char *name); VkPipelineLayout Vulkan_CreatePipelineLayout (struct vulkan_ctx_s *ctx, diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index b9db14277..51ef1136f 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1142,7 +1142,35 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkPipeline -QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) +QFV_ParseComputePipeline (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties) +{ + memsuper_t *memsuper = new_memsuper (); + qfv_device_t *device = ctx->device; + + __auto_type cInfo = QFV_AllocComputePipelineCreateInfoSet (1, alloca); + memset (&cInfo->a[0], 0, sizeof (cInfo->a[0])); + + if (!parse_object (ctx, memsuper, plist, parse_VkComputePipelineCreateInfo, + &cInfo->a[0], properties)) { + delete_memsuper (memsuper); + return 0; + } + + qfvPushDebug (ctx, va (ctx->va_ctx, + "QFV_ParseComputePipeline: %d", PL_Line (plist))); + + __auto_type plSet = QFV_CreateComputePipelines (device, 0, cInfo); + qfvPopDebug (ctx); + VkPipeline pipeline = plSet->a[0]; + free (plSet); + delete_memsuper (memsuper); + return pipeline; +} + +VkPipeline +QFV_ParseGraphicsPipeline (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties) { memsuper_t *memsuper = new_memsuper (); qfv_device_t *device = ctx->device; diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 6e2ef92b2..6f2ea6357 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -36,8 +36,10 @@ void QFV_AddHandle (struct hashtab_s *tab, const char *name, uint64_t handle); VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties); -VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); +VkPipeline QFV_ParseComputePipeline (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); +VkPipeline QFV_ParseGraphicsPipeline (vulkan_ctx_t *ctx, plitem_t *plist, + plitem_t *properties); VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties); VkDescriptorSetLayout QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 6f5efa6d3..23577cb79 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -19,6 +19,7 @@ VkPushConstantRange, VkPipelineLayoutCreateInfo, VkGraphicsPipelineCreateInfo, + VkComputePipelineCreateInfo, VkDescriptorPoolCreateInfo, VkSamplerCreateInfo, VkImageCreateInfo, @@ -294,6 +295,19 @@ }; basePipelineIndex = auto; }; + VkComputePipelineCreateInfo = { + flags = auto; + stage = auto; + layout = { + type = (custom, QFString, parse_VkPipelineLayout); + fields = (layout); + }; + basePipelineHandle = { + type = (custom, QFString, parse_BasePipeline); + fields = (basePipelineHandle); + }; + basePipelineIndex = auto; + }; VkImageCreateInfo = { flags = auto; imageType = auto; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 848748a23..d40ea4562 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -353,8 +353,8 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&actx->frames, frames); actx->frames.grow = 0; - actx->depth = Vulkan_CreatePipeline (ctx, "alias_depth"); - actx->gbuf = Vulkan_CreatePipeline (ctx, "alias_gbuf"); + actx->depth = Vulkan_CreateGraphicsPipeline (ctx, "alias_depth"); + actx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "alias_gbuf"); actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 3c63c1fb8..db0877881 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1402,11 +1402,11 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&bctx->frames, frames); bctx->frames.grow = 0; - bctx->depth = Vulkan_CreatePipeline (ctx, "bsp_depth"); - bctx->gbuf = Vulkan_CreatePipeline (ctx, "bsp_gbuf"); - bctx->skybox = Vulkan_CreatePipeline (ctx, "bsp_skybox"); - bctx->skysheet = Vulkan_CreatePipeline (ctx, "bsp_skysheet"); - bctx->turb = Vulkan_CreatePipeline (ctx, "bsp_turb"); + bctx->depth = Vulkan_CreateGraphicsPipeline (ctx, "bsp_depth"); + bctx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "bsp_gbuf"); + bctx->skybox = Vulkan_CreateGraphicsPipeline (ctx, "bsp_skybox"); + bctx->skysheet = Vulkan_CreateGraphicsPipeline (ctx, "bsp_skysheet"); + bctx->turb = Vulkan_CreateGraphicsPipeline (ctx, "bsp_turb"); bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index b188cae95..161012ae0 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -138,7 +138,7 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&cctx->frames, frames); cctx->frames.grow = 0; - cctx->pipeline = Vulkan_CreatePipeline (ctx, "compose"); + cctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "compose"); cctx->layout = Vulkan_CreatePipelineLayout (ctx, "compose_layout"); __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 6c5824d26..f64c6515e 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -396,7 +396,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); - dctx->pipeline = Vulkan_CreatePipeline (ctx, "twod"); + dctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout"); diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 5e62e9f31..5fd4c9dfb 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -316,7 +316,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&lctx->frames, frames); lctx->frames.grow = 0; - lctx->pipeline = Vulkan_CreatePipeline (ctx, "lighting"); + lctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lighting"); lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout"); lctx->sampler = Vulkan_CreateSampler (ctx, "shadow_sampler"); diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index ce4dcc599..53a7d2efe 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -297,8 +297,8 @@ Vulkan_Sprite_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&sctx->frames, frames); sctx->frames.grow = 0; - sctx->depth = Vulkan_CreatePipeline (ctx, "sprite_depth"); - sctx->gbuf = Vulkan_CreatePipeline (ctx, "sprite_gbuf"); + sctx->depth = Vulkan_CreateGraphicsPipeline (ctx, "sprite_depth"); + sctx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "sprite_gbuf"); sctx->layout = Vulkan_CreatePipelineLayout (ctx, "sprite_layout"); sctx->sampler = Vulkan_CreateSampler (ctx, "sprite_sampler"); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index de553fde0..2e1f57c2b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -551,7 +551,7 @@ Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) } VkPipeline -Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) +Vulkan_CreateComputePipeline (vulkan_ctx_t *ctx, const char *name) { plitem_t *item = qfv_load_pipeline (ctx, "pipelines"); if (!(item = PL_ObjectForKey (item, name))) { @@ -560,7 +560,25 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name) } else { Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline def %s\n", name); } - VkPipeline pipeline = QFV_ParsePipeline (ctx, item, ctx->pipelineDef); + VkPipeline pipeline = QFV_ParseComputePipeline (ctx, item, + ctx->pipelineDef); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, + va (ctx->va_ctx, "pipeline:%s", name)); + return pipeline; +} + +VkPipeline +Vulkan_CreateGraphicsPipeline (vulkan_ctx_t *ctx, const char *name) +{ + plitem_t *item = qfv_load_pipeline (ctx, "pipelines"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading pipeline %s\n", name); + return 0; + } else { + Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline def %s\n", name); + } + VkPipeline pipeline = QFV_ParseGraphicsPipeline (ctx, item, + ctx->pipelineDef); QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, va (ctx->va_ctx, "pipeline:%s", name)); return pipeline; From e0af6541e67f901fb8a3aa6da1dee5d3d3acd178 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Dec 2021 23:02:16 +0900 Subject: [PATCH 1968/3664] [vulkan] And a bunch of buffer barrier transitions These seem to be the most likely ones for compute shaders (some based on my ideas for particles). --- include/QF/Vulkan/barrier.h | 6 +++ libs/video/renderer/vulkan/barrier.c | 62 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h index 0a6d78af1..a28e07817 100644 --- a/include/QF/Vulkan/barrier.h +++ b/include/QF/Vulkan/barrier.h @@ -30,6 +30,12 @@ enum { qfv_BB_TransferWrite_to_VertexAttrRead, qfv_BB_TransferWrite_to_IndexRead, qfv_BB_TransferWrite_to_UniformRead, + qfv_BB_ShaderRW_to_ShaderRO, + qfv_BB_ShaderRW_to_ShaderRO_VA, + qfv_BB_ShaderRO_to_ShaderWrite, + qfv_BB_ShaderRO_VA_to_ShaderWrite, + qfv_BB_ShaderWrite_to_ShaderRO, + qfv_BB_ShaderWrite_to_ShaderRW, }; extern const qfv_imagebarrier_t imageBarriers[]; diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c index 2ab04d423..7c4f6b788 100644 --- a/libs/video/renderer/vulkan/barrier.c +++ b/libs/video/renderer/vulkan/barrier.c @@ -165,4 +165,66 @@ const qfv_bufferbarrier_t bufferBarriers[] = { VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, }, }, + [qfv_BB_ShaderRW_to_ShaderRO] = { + .srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, + [qfv_BB_ShaderRW_to_ShaderRO_VA] = { + .srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT + | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, + [qfv_BB_ShaderRO_to_ShaderWrite] = { + .srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_READ_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, + [qfv_BB_ShaderRO_VA_to_ShaderWrite] = { + .srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT + | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + .dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, + [qfv_BB_ShaderWrite_to_ShaderRO] = { + .srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, + [qfv_BB_ShaderWrite_to_ShaderRW] = { + .srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, }; From 9dcaa98205433d4b294a1d1a85bbd214a8388e32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Dec 2021 23:04:19 +0900 Subject: [PATCH 1969/3664] [vulkan] Clean up a pile of C&P fluff --- include/QF/Vulkan/qf_sprite.h | 8 ++--- libs/video/renderer/vulkan/vulkan_sprite.c | 41 ++++++++++------------ 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index a9a147380..31d95a3aa 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -67,13 +67,13 @@ typedef struct spriteframeset_s typedef struct spritectx_s { spriteframeset_t frames; - VkPipeline depth; - VkPipeline gbuf; + VkPipeline depth; + VkPipeline gbuf; VkDescriptorPool pool; VkDescriptorSetLayout setLayout; VkPipelineLayout layout; - unsigned maxImages; - VkSampler sampler; + unsigned maxImages; + VkSampler sampler; } spritectx_t; struct vulkan_ctx_s; diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 53a7d2efe..6b8935e26 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -114,7 +114,7 @@ Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; spritectx_t *sctx = ctx->sprite_context; - spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame]; + spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; model_t *model = ent->renderer.model; msprite_t *sprite = model->cache.data; animation_t *animation = &ent->animation; @@ -139,10 +139,10 @@ Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) mat[1] = svright; mat[0] = -svpn; - emit_commands (aframe->cmdSet.a[QFV_spriteDepth], + emit_commands (sframe->cmdSet.a[QFV_spriteDepth], (qfv_sprite_t *) ((byte *) sprite + sprite->data), 2, push_constants, rFrame); - emit_commands (aframe->cmdSet.a[QFV_spriteGBuffer], + emit_commands (sframe->cmdSet.a[QFV_spriteGBuffer], (qfv_sprite_t *) ((byte *) sprite + sprite->data), 2, push_constants, rFrame); } @@ -156,8 +156,8 @@ sprite_begin_subpass (QFV_SpriteSubpass subpass, VkPipeline pipeline, qfv_devfuncs_t *dfunc = device->funcs; spritectx_t *sctx = ctx->sprite_context; __auto_type cframe = &ctx->frames.a[ctx->curFrame]; - spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = aframe->cmdSet.a[subpass]; + spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = sframe->cmdSet.a[subpass]; dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { @@ -205,13 +205,13 @@ Vulkan_SpriteBegin (qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; spritectx_t *sctx = ctx->sprite_context; - spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame]; + spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; //XXX quat_t fog; DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], - aframe->cmdSet.a[QFV_spriteDepth]); + sframe->cmdSet.a[QFV_spriteDepth]); DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], - aframe->cmdSet.a[QFV_spriteGBuffer]); + sframe->cmdSet.a[QFV_spriteGBuffer]); sprite_begin_subpass (QFV_spriteDepth, sctx->depth, rFrame); sprite_begin_subpass (QFV_spriteGBuffer, sctx->gbuf, rFrame); @@ -222,10 +222,10 @@ Vulkan_SpriteEnd (qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; spritectx_t *sctx = ctx->sprite_context; - spriteframe_t *aframe = &sctx->frames.a[ctx->curFrame]; + spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; - sprite_end_subpass (aframe->cmdSet.a[QFV_spriteDepth], ctx); - sprite_end_subpass (aframe->cmdSet.a[QFV_spriteGBuffer], ctx); + sprite_end_subpass (sframe->cmdSet.a[QFV_spriteDepth], ctx); + sprite_end_subpass (sframe->cmdSet.a[QFV_spriteGBuffer], ctx); } static VkDescriptorBufferInfo base_buffer_info = { @@ -302,24 +302,21 @@ Vulkan_Sprite_Init (vulkan_ctx_t *ctx) sctx->layout = Vulkan_CreatePipelineLayout (ctx, "sprite_layout"); sctx->sampler = Vulkan_CreateSampler (ctx, "sprite_sampler"); - //FIXME too many places - __auto_type limits = device->physDev->properties.limits; - sctx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8); sctx->pool = Vulkan_CreateDescriptorPool (ctx, "sprite_pool"); sctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "sprite_set"); for (size_t i = 0; i < frames; i++) { - __auto_type aframe = &sctx->frames.a[i]; + __auto_type sframe = &sctx->frames.a[i]; - DARRAY_INIT (&aframe->cmdSet, QFV_spriteNumPasses); - DARRAY_RESIZE (&aframe->cmdSet, QFV_spriteNumPasses); - aframe->cmdSet.grow = 0; + DARRAY_INIT (&sframe->cmdSet, QFV_spriteNumPasses); + DARRAY_RESIZE (&sframe->cmdSet, QFV_spriteNumPasses); + sframe->cmdSet.grow = 0; - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &aframe->cmdSet); + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &sframe->cmdSet); for (int j = 0; j < QFV_spriteNumPasses; j++) { QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - aframe->cmdSet.a[j], + sframe->cmdSet.a[j], va (ctx->va_ctx, "cmd:sprite:%zd:%s", i, sprite_pass_names[j])); } @@ -335,8 +332,8 @@ Vulkan_Sprite_Shutdown (vulkan_ctx_t *ctx) spritectx_t *sctx = ctx->sprite_context; for (size_t i = 0; i < sctx->frames.size; i++) { - __auto_type aframe = &sctx->frames.a[i]; - free (aframe->cmdSet.a); + __auto_type sframe = &sctx->frames.a[i]; + free (sframe->cmdSet.a); } dfunc->vkDestroyPipeline (device->dev, sctx->depth, 0); From 6aaf5c37225917daaf7138ee79f3f8c71925c65f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 16 Dec 2021 23:17:01 +0900 Subject: [PATCH 1970/3664] [vulkan] Start work on particles for Vulkan This gets the pipelines loaded (and unloaded on shutdown). Probably the easy part :P. Still need to sort out the command buffers, synchronization, and particle generation (and probably a bunch else that's not coming to mind). --- include/QF/Vulkan/qf_particles.h | 55 +++++++++ include/vid_vulkan.h | 1 + libs/video/renderer/Makemodule.am | 21 ++++ libs/video/renderer/vid_render_vulkan.c | 3 +- libs/video/renderer/vulkan/qfpipeline.plist | 114 ++++++++++++++++++ libs/video/renderer/vulkan/shader.c | 15 +++ .../renderer/vulkan/shader/particle.frag | 22 ++++ .../renderer/vulkan/shader/particle.geom | 57 +++++++++ .../renderer/vulkan/shader/particle.vert | 31 +++++ .../renderer/vulkan/shader/partphysics.comp | 56 +++++++++ .../renderer/vulkan/shader/partupdate.comp | 93 ++++++++++++++ libs/video/renderer/vulkan/vulkan_particles.c | 101 ++++++++++++---- 12 files changed, 544 insertions(+), 25 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/particle.frag create mode 100644 libs/video/renderer/vulkan/shader/particle.geom create mode 100644 libs/video/renderer/vulkan/shader/particle.vert create mode 100644 libs/video/renderer/vulkan/shader/partphysics.comp create mode 100644 libs/video/renderer/vulkan/shader/partupdate.comp diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index c256a9610..45754fc85 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -1,8 +1,62 @@ #ifndef __QF_Vulkan_qf_particles_h #define __QF_Vulkan_qf_particles_h +#include "QF/darray.h" #include "QF/image.h" +#include "QF/Vulkan/command.h" + +typedef struct qfv_particle_s { + vec4f_t pos; + vec4f_t vel; + vec4f_t color; + float texture; + float ramp; + float scale; + float live; +} qfv_particle_t; + +typedef struct qfv_parameters_s { + vec4f_t drag; + vec4f_t ramp; +} qfv_parameters_t; + +typedef enum { + QFV_particleTranslucent, + + QFV_particleNumPasses +} QFV_ParticleSubpass; + +typedef struct particleframe_s { + VkCommandBuffer compute; + VkSemaphore physSem; + VkSemaphore drawSem; + VkSemaphore updateSem; + VkBuffer state; + VkBuffer params; + VkBuffer system; + + VkDescriptorSet descriptors; + + qfv_cmdbufferset_t cmdSet; +} particleframe_t; + +typedef struct particleframeset_s + DARRAY_TYPE (particleframe_t) particleframeset_t; + +typedef struct particlectx_s { + particleframeset_t frames; + VkPipeline physics; + VkPipeline update; + VkPipeline draw; + + VkDescriptorPool pool; + VkDescriptorSetLayout setLayout; + VkPipelineLayout physics_layout; + VkPipelineLayout update_layout; + VkPipelineLayout draw_layout; +} particlectx_t; + struct cvar_s; struct vulkan_ctx_s;; @@ -11,6 +65,7 @@ void Vulkan_InitParticles (struct vulkan_ctx_s *ctx); void Vulkan_r_easter_eggs_f (struct cvar_s *var, struct vulkan_ctx_s *ctx); void Vulkan_r_particles_style_f (struct cvar_s *var, struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_DrawParticles (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_particles_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index fec50b878..e0be2a993 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -59,6 +59,7 @@ typedef struct vulkan_ctx_s { struct matrixctx_s *matrix_context; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; + struct particlectx_s *particle_context; struct spritectx_s *sprite_context; struct drawctx_s *draw_context; struct lightingctx_s *lighting_context; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 086bc6675..db58b894c 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -289,6 +289,16 @@ vkparse_plist = \ vkshaderpath = libs/video/renderer/vulkan/shader +partphysicsc_src = $(vkshaderpath)/partphysics.comp +partphysicsc_c = $(vkshaderpath)/partphysics.comp.spvc +partupdatec_src = $(vkshaderpath)/partupdate.comp +partupdatec_c = $(vkshaderpath)/partupdate.comp.spvc +particlev_src = $(vkshaderpath)/particle.vert +particlev_c = $(vkshaderpath)/particle.vert.spvc +particleg_src = $(vkshaderpath)/particle.geom +particleg_c = $(vkshaderpath)/particle.geom.spvc +particlef_src = $(vkshaderpath)/particle.frag +particlef_c = $(vkshaderpath)/particle.frag.spvc sprite_gbufv_src = $(vkshaderpath)/sprite_gbuf.vert sprite_gbufv_c = $(vkshaderpath)/sprite_gbuf.vert.spvc sprite_gbuff_src = $(vkshaderpath)/sprite_gbuf.frag @@ -341,6 +351,12 @@ pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc shadow_src = $(vkshaderpath)/shadow.geom shadow_c = $(vkshaderpath)/shadow.geom.spvc +$(partphysicsc_c): $(partphysicsc_src) +$(partupdatec_c): $(partupdatec_src) +$(particlev_c): $(particlev_src) +$(particleg_c): $(particleg_src) +$(particlef_c): $(particlef_src) + $(sprite_gbufv_c): $(sprite_gbufv_src) $(sprite_gbuff_c): $(sprite_gbuff_src) @@ -392,6 +408,11 @@ $(pushcolor_c): $(pushcolor_src) $(shadow_c): $(shadow_src) vkshader_c = \ + $(partphysicsc_c) \ + $(partupdatec_c) \ + $(particlev_c) \ + $(particleg_c) \ + $(particlef_c) \ $(sprite_gbufv_c) \ $(sprite_gbuff_c) \ $(sprite_depthv_c) \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 7c2e03ca6..b5a994768 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -104,9 +104,9 @@ vulkan_R_Init (void) Vulkan_Matrix_Init (vulkan_ctx); Vulkan_Alias_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); + Vulkan_Particles_Init (vulkan_ctx); Vulkan_Sprite_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); - Vulkan_Particles_Init (vulkan_ctx); Vulkan_Lighting_Init (vulkan_ctx); Vulkan_Compose_Init (vulkan_ctx); @@ -631,6 +631,7 @@ vulkan_vid_render_shutdown (void) Vulkan_Lighting_Shutdown (vulkan_ctx); Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Sprite_Shutdown (vulkan_ctx); + Vulkan_Particles_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Alias_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 6739202a9..dfd5e1a43 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -112,6 +112,16 @@ }, ); }; + particle_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = storage_buffer; + descriptorCount = 3; + }, + ); + }; sprite_pool = { flags = free_descriptor_set; maxSets = 64; //FIXME cvar? @@ -295,6 +305,28 @@ }, ); }; + particle_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 1; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 2; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + ); + }; }; pipelineLayouts = { twod_layout = { @@ -351,6 +383,29 @@ compose_layout = { setLayouts = (compose_attach); }; + partphysics_layout = { + setLayouts = (particle_set); + pushConstantRanges = ( + { + stageFlags = compute; + offset = 0; + size = "16 * 4 + 4"; + }, + ); + }; + partupdate_layout = { + setLayouts = (particle_set, particle_set, particle_set); + }; + partdraw_layout = { + setLayouts = (matrix_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4"; + }, + ); + }; }; depthStencil = { @@ -424,6 +479,17 @@ { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, ); }; + particle = { + bindings = ( + { binding = 0; stride = "4 * 4 * 4"; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + ); + }; twod = { bindings = ( { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, @@ -856,6 +922,38 @@ layout = quakebsp_layout; renderPass = renderpass; }; + partdraw = { + subpass = 1; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/particle.vert; + }, + { + stage = geometry; + name = main; + module = $builtin/particle.geom; + }, + { + stage = fragment; + name = main; + module = $builtin/particle.frag; + }, + ); + vertexInput = $properties.vertexInput.particle; + inputAssembly = $properties.inputAssembly.sprite; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_only; + colorBlend = $properties.pipelines.bsp_turb.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor, blend_constants ); + }; + layout = partdraw_layout; + renderPass = renderpass; + }; sprite_gbuf = { subpass = 2; stages = ( @@ -1000,5 +1098,21 @@ layout = compose_layout; renderPass = renderpass; }; + partphysics = { + stage = { + stage = compute; + name = main; + module = $builtin/partphysics.comp; + }; + layout = partphysics_layout; + }; + partupdate = { + stage = { + stage = compute; + name = main; + module = $builtin/partupdate.comp; + }; + layout = partupdate_layout; + }; }; } diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index a5329c443..bd12d3b79 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -54,6 +54,16 @@ #include "vid_vulkan.h" +static +#include "libs/video/renderer/vulkan/shader/particle.vert.spvc" +static +#include "libs/video/renderer/vulkan/shader/particle.geom.spvc" +static +#include "libs/video/renderer/vulkan/shader/particle.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/partphysics.comp.spvc" +static +#include "libs/video/renderer/vulkan/shader/partupdate.comp.spvc" static #include "libs/video/renderer/vulkan/shader/sprite_gbuf.vert.spvc" static @@ -112,6 +122,11 @@ typedef struct shaderdata_s { } shaderdata_t; static shaderdata_t builtin_shaders[] = { + { "particle.vert", particle_vert, sizeof (particle_vert) }, + { "particle.geom", particle_geom, sizeof (particle_geom) }, + { "particle.frag", particle_frag, sizeof (particle_frag) }, + { "partphysics.comp", partphysics_comp, sizeof (partphysics_comp) }, + { "partupdate.comp", partupdate_comp, sizeof (partupdate_comp) }, { "sprite_gbuf.vert", sprite_gbuf_vert, sizeof (sprite_gbuf_vert) }, { "sprite_gbuf.frag", sprite_gbuf_frag, sizeof (sprite_gbuf_frag) }, { "sprite_depth.vert", sprite_depth_vert, sizeof (sprite_depth_vert) }, diff --git a/libs/video/renderer/vulkan/shader/particle.frag b/libs/video/renderer/vulkan/shader/particle.frag new file mode 100644 index 000000000..e9272912f --- /dev/null +++ b/libs/video/renderer/vulkan/shader/particle.frag @@ -0,0 +1,22 @@ +#version 450 + +layout (constant_id = 0) const int MaxTextures = 256; + +layout (location = 0) in vec4 uv_tr; +layout (location = 1) in vec4 color; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + vec4 c = color; + vec2 x = uv_tr.xy; + + float a = 1 - dot (x, x); + if (a <= 0) { + discard; + } + c.a *= sqrt (a); + frag_color = c; +} diff --git a/libs/video/renderer/vulkan/shader/particle.geom b/libs/video/renderer/vulkan/shader/particle.geom new file mode 100644 index 000000000..4669408ab --- /dev/null +++ b/libs/video/renderer/vulkan/shader/particle.geom @@ -0,0 +1,57 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; +}; + +layout (points) in; +layout (triangle_strip, max_vertices = 4) out; +layout (location = 0) in vec4 velocity[]; +layout (location = 1) in vec4 color[]; +layout (location = 2) in vec4 ramp[]; + +layout (location = 0) out vec4 uv_tr; +layout (location = 1) out vec4 o_color; + +void +main() +{ + vec4 pos = gl_in[0].gl_Position; + vec4 tr = vec4 (0, 0, ramp[0].xy); + float s = ramp[0].z; + vec4 d, p; + vec4 c = color[0]; + + d = vec4 (-1, 1, 0, 0); + p = pos + s * d; + gl_Position = Projection3d * p; + uv_tr = d + tr; + o_color = c; + EmitVertex (); + + d = vec4 (-1, -1, 0, 0); + p = pos + s * d; + gl_Position = Projection3d * p; + uv_tr = d + tr; + o_color = c; + EmitVertex (); + + d = vec4 (1, 1, 0, 0); + p = pos + s * d; + gl_Position = Projection3d * p; + uv_tr = d + tr; + o_color = c; + EmitVertex (); + + d = vec4 (1, -1, 0, 0); + p = pos + s * d; + gl_Position = Projection3d * p; + uv_tr = d + tr; + o_color = c; + EmitVertex (); + + EndPrimitive (); +} diff --git a/libs/video/renderer/vulkan/shader/particle.vert b/libs/video/renderer/vulkan/shader/particle.vert new file mode 100644 index 000000000..655e31042 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/particle.vert @@ -0,0 +1,31 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; +}; + +layout (location = 0) in vec4 position; +layout (location = 1) in vec4 velocity; +layout (location = 2) in vec4 color; +layout (location = 3) in vec4 ramp; + +layout (location = 0) out vec4 o_velocity; +layout (location = 1) out vec4 o_color; +layout (location = 2) out vec4 o_ramp; + +void +main (void) +{ + // geometry shader will take care of Projection and View + gl_Position = Model * position; + o_velocity = Model * velocity; + o_color = color; + o_ramp = ramp; +} diff --git a/libs/video/renderer/vulkan/shader/partphysics.comp b/libs/video/renderer/vulkan/shader/partphysics.comp new file mode 100644 index 000000000..654cd62f6 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/partphysics.comp @@ -0,0 +1,56 @@ +#version 450 + +layout (local_size_x = 32, local_size_y = 32) in; + +struct Particle { + vec4 pos; + vec4 vel; + vec4 color; + float tex; + float ramp; + float scale; + float live; +}; + +struct Parameters { + vec4 drag; // [dx, dy, dz, grav scale] + vec4 ramp; // [rate, max, alpha rate, scale rate] +}; + +layout(std140, set = 0, binding = 0) buffer ParticleStates { + Particle particles[]; +}; + +layout(std140, set = 0, binding = 1) buffer ParticleParameters { + Parameters parameters[]; +}; + +layout(std140, set = 0, binding = 2) buffer ParticleSystem { + uint particleCount; +}; + +layout (push_constant) uniform PushConstants { + vec4 gravity; + float dT; +}; + +void +main () +{ + uint ind = gl_GlobalInvocationID.x; + if (ind >= particleCount) { + return; + } + Particle part = particles[ind]; + Parameters parm = parameters[ind]; + + part.pos += dT * part.vel; + part.vel += dT * (part.vel * parm.drag + gravity * parm.drag.w); + + part.ramp += dT * parm.ramp.x; + part.scale += dT * parm.ramp.z; + part.color.a -= dT * parm.ramp.a; + part.live -= dT; + + particles[ind] = part; +} diff --git a/libs/video/renderer/vulkan/shader/partupdate.comp b/libs/video/renderer/vulkan/shader/partupdate.comp new file mode 100644 index 000000000..e979c941a --- /dev/null +++ b/libs/video/renderer/vulkan/shader/partupdate.comp @@ -0,0 +1,93 @@ +#version 450 + +layout (constant_id = 0) const int MaxParticles = 2048; + +layout (local_size_x = 1, local_size_y = 1) in; + +struct Particle { + vec4 pos; + vec4 vel; + vec4 color; + float tex; + float ramp; + float scale; + float live; +}; + +struct Parameters { + vec4 drag; // [dx, dy, dz, grav scale] + vec4 ramp; // [rate, max, alpha rate, scale rate] +}; + +layout(std140, set = 0, binding = 0) buffer InStates { + Particle particles[]; +} inState; + +layout(std140, set = 0, binding = 1) buffer InParameters { + Parameters parameters[]; +} inParameters; + +layout(std140, set = 0, binding = 2) buffer InSystem { + uint particleCount; +} inSystem; + +layout(std140, set = 1, binding = 0) buffer OutStates { + Particle particles[]; +} outStates; + +layout(std140, set = 1, binding = 1) buffer OutParameters { + Parameters parameters[]; +} outParameters; + +layout(std140, set = 1, binding = 2) buffer OutSystem { + uint particleCount; +} outSystem; + +layout(std140, set = 2, binding = 0) buffer NewStates { + Particle particles[]; +} newStates; + +layout(std140, set = 2, binding = 1) buffer NewParameters { + Parameters parameters[]; +} newParameters; + +layout(std140, set = 2, binding = 2) buffer NewSystem { + uint particleCount; +} newSystem; + +bool +is_dead (in Particle part, in Parameters parm) +{ + if (part.live <= 0) { + return true; + } + if (part.ramp >= parm.ramp.y || part.color.a <= 0 || part.scale <= 0) { + return true; + } + return false; +} + +void +main () +{ + uint j = 0; + // compact existing partles removing dead particles + for (uint i = 0; i < inSystem.particleCount; i++) { + if (is_dead (inState.particles[i], inParameters.parameters[i])) { + continue; + } + outStates.particles[j] = inState.particles[i]; + outParameters.parameters[j] = inParameters.parameters[i]; + j++; + } + // inject any new particles that aren't DOA + for (uint i = 0; i < newSystem.particleCount && j < MaxParticles; i++) { + if (is_dead (inState.particles[i], inParameters.parameters[i])) { + continue; + } + outStates.particles[j] = newStates.particles[i]; + outParameters.parameters[j] = newParameters.parameters[i]; + j++; + } + outSystem.particleCount = j; +} diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index abb24924b..a20e66b25 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -40,20 +40,29 @@ #include "QF/cvar.h" #include "QF/render.h" +#include "QF/va.h" + #include "QF/plugin/vid_render.h" -#include "QF/Vulkan/qf_vid.h" + +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" #include "QF/Vulkan/qf_particles.h" #include "r_internal.h" #include "vid_vulkan.h" +static const char * __attribute__((used)) particle_pass_names[] = { + "draw", +}; + void -Vulkan_ClearParticles (struct vulkan_ctx_s *ctx) +Vulkan_ClearParticles (vulkan_ctx_t *ctx) { } void -Vulkan_InitParticles (struct vulkan_ctx_s *ctx) +Vulkan_InitParticles (vulkan_ctx_t *ctx) { } @@ -217,7 +226,7 @@ static vid_particle_funcs_t vulkan_particles_QF = { }; void -Vulkan_r_easter_eggs_f (cvar_t *var, struct vulkan_ctx_s *ctx) +Vulkan_r_easter_eggs_f (cvar_t *var, vulkan_ctx_t *ctx) { if (!easter_eggs || !r_particles_style) { return; @@ -239,35 +248,79 @@ Vulkan_r_easter_eggs_f (cvar_t *var, struct vulkan_ctx_s *ctx) } void -Vulkan_r_particles_style_f (cvar_t *var, struct vulkan_ctx_s *ctx) +Vulkan_r_particles_style_f (cvar_t *var, vulkan_ctx_t *ctx) { Vulkan_r_easter_eggs_f (var, ctx); } void -Vulkan_DrawParticles (struct vulkan_ctx_s *ctx) +Vulkan_DrawParticles (vulkan_ctx_t *ctx) { } void -Vulkan_Particles_Init (struct vulkan_ctx_s *ctx) +Vulkan_Particles_Init (vulkan_ctx_t *ctx) { - /* - easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, r_easter_eggs_f, - "Enables easter eggs."); - r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, - "Toggles drawing of particles."); - r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, - r_particles_max_f, "Maximum amount of " - "particles to display. No maximum, minimum " - "is 0."); - r_particles_nearclip = Cvar_Get ("r_particles_nearclip", "32", - CVAR_ARCHIVE, r_particles_nearclip_f, - "Distance of the particle near clipping " - "plane from the player."); - r_particles_style = Cvar_Get ("r_particles_style", "1", CVAR_ARCHIVE, - r_particles_style_f, "Sets particle style. " - "0 for Id, 1 for QF."); - */ vulkan_vid_render_funcs.particles = &vulkan_particles_QF; + + qfv_device_t *device = ctx->device; + + qfvPushDebug (ctx, "particles init"); + + particlectx_t *pctx = calloc (1, sizeof (particlectx_t)); + ctx->particle_context = pctx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&pctx->frames, frames); + DARRAY_RESIZE (&pctx->frames, frames); + pctx->frames.grow = 0; + + pctx->physics = Vulkan_CreateComputePipeline (ctx, "partphysics"); + pctx->update = Vulkan_CreateComputePipeline (ctx, "partupdate"); + pctx->draw = Vulkan_CreateGraphicsPipeline (ctx, "partdraw"); + pctx->physics_layout = Vulkan_CreatePipelineLayout (ctx, + "partphysics_layout"); + pctx->update_layout = Vulkan_CreatePipelineLayout (ctx, + "partupdate_layout"); + pctx->draw_layout = Vulkan_CreatePipelineLayout (ctx, "draw_layout"); + + pctx->pool = Vulkan_CreateDescriptorPool (ctx, "particle_pool"); + pctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "particle_set"); + + for (size_t i = 0; i < frames; i++) { + __auto_type pframe = &pctx->frames.a[i]; + + DARRAY_INIT (&pframe->cmdSet, QFV_particleNumPasses); + DARRAY_RESIZE (&pframe->cmdSet, QFV_particleNumPasses); + pframe->cmdSet.grow = 0; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &pframe->cmdSet); + + for (int j = 0; j < QFV_particleNumPasses; j++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + pframe->cmdSet.a[j], + va (ctx->va_ctx, "cmd:particle:%zd:%s", i, + particle_pass_names[j])); + } + } + qfvPopDebug (ctx); +} + +void +Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + particlectx_t *pctx = ctx->particle_context; + + for (size_t i = 0; i < pctx->frames.size; i++) { + __auto_type pframe = &pctx->frames.a[i]; + free (pframe->cmdSet.a); + } + + dfunc->vkDestroyPipeline (device->dev, pctx->physics, 0); + dfunc->vkDestroyPipeline (device->dev, pctx->update, 0); + dfunc->vkDestroyPipeline (device->dev, pctx->draw, 0); + free (pctx->frames.a); + free (pctx); } From 8228146ac082557856c2ff18a48efe5ea1c2eeea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 00:18:25 +0900 Subject: [PATCH 1971/3664] [vulkan] Use the particle system buffer for indirect draws I realized I'd need to get the particle counts out to the draw commands somehow, and this seemed to be the most natural way. --- .../renderer/vulkan/shader/partphysics.comp | 6 +++++- .../renderer/vulkan/shader/partupdate.comp | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/partphysics.comp b/libs/video/renderer/vulkan/shader/partphysics.comp index 654cd62f6..89dbc3ff6 100644 --- a/libs/video/renderer/vulkan/shader/partphysics.comp +++ b/libs/video/renderer/vulkan/shader/partphysics.comp @@ -25,8 +25,12 @@ layout(std140, set = 0, binding = 1) buffer ParticleParameters { Parameters parameters[]; }; +//doubles as VkDrawIndirectCommand layout(std140, set = 0, binding = 2) buffer ParticleSystem { - uint particleCount; + uint vertexCount; + uint particleCount; //instanceCount + uint firstVertex; + uint firstInstance; }; layout (push_constant) uniform PushConstants { diff --git a/libs/video/renderer/vulkan/shader/partupdate.comp b/libs/video/renderer/vulkan/shader/partupdate.comp index e979c941a..adce81094 100644 --- a/libs/video/renderer/vulkan/shader/partupdate.comp +++ b/libs/video/renderer/vulkan/shader/partupdate.comp @@ -27,8 +27,12 @@ layout(std140, set = 0, binding = 1) buffer InParameters { Parameters parameters[]; } inParameters; +//doubles as VkDrawIndirectCommand layout(std140, set = 0, binding = 2) buffer InSystem { - uint particleCount; + uint vertexCount; + uint particleCount; //instanceCount + uint firstVertex; + uint firstInstance; } inSystem; layout(std140, set = 1, binding = 0) buffer OutStates { @@ -39,8 +43,12 @@ layout(std140, set = 1, binding = 1) buffer OutParameters { Parameters parameters[]; } outParameters; +//doubles as VkDrawIndirectCommand layout(std140, set = 1, binding = 2) buffer OutSystem { - uint particleCount; + uint vertexCount; + uint particleCount; //instanceCount + uint firstVertex; + uint firstInstance; } outSystem; layout(std140, set = 2, binding = 0) buffer NewStates { @@ -51,8 +59,12 @@ layout(std140, set = 2, binding = 1) buffer NewParameters { Parameters parameters[]; } newParameters; +//doubles as VkDrawIndirectCommand layout(std140, set = 2, binding = 2) buffer NewSystem { - uint particleCount; + uint vertexCount; + uint particleCount; //instanceCount + uint firstVertex; + uint firstInstance; } newSystem; bool From db6c76d583f5aa5f2e0cef9352988fcbf9c615ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 12:20:32 +0900 Subject: [PATCH 1972/3664] [vulkan] Abandon bindless rendering At least for now, it is more trouble than it is worth as it (or my implementation of it) breaks lavapipe and renderdoc. --- include/QF/Vulkan/qf_alias.h | 7 +- include/QF/Vulkan/qf_bsp.h | 8 +- include/QF/Vulkan/qf_texture.h | 12 ++ include/vid_vulkan.h | 1 + libs/models/brush/vulkan_model_brush.c | 4 + libs/video/renderer/vulkan/qfpipeline.plist | 62 ++------- .../renderer/vulkan/shader/alias_gbuf.frag | 14 +- .../renderer/vulkan/shader/bsp_gbuf.frag | 10 +- .../video/renderer/vulkan/shader/bsp_sky.frag | 26 ++-- .../renderer/vulkan/shader/bsp_turb.frag | 10 +- .../renderer/vulkan/shader/particle.frag | 2 - .../renderer/vulkan/shader/sprite_depth.frag | 2 - .../renderer/vulkan/shader/sprite_gbuf.frag | 2 - libs/video/renderer/vulkan/vulkan_alias.c | 112 ++-------------- libs/video/renderer/vulkan/vulkan_bsp.c | 124 +++++++----------- libs/video/renderer/vulkan/vulkan_texture.c | 72 ++++++++++ 16 files changed, 183 insertions(+), 285 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index c42602d39..08ca86e94 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -60,7 +60,7 @@ typedef struct qfv_alias_skin_s { VkImageView view; byte colora[4]; byte colorb[4]; - int texind; + VkDescriptorSet descriptor; } qfv_alias_skin_t; typedef enum { @@ -85,13 +85,8 @@ typedef struct aliasctx_s { aliasframeset_t frames; VkPipeline depth; VkPipeline gbuf; - VkDescriptorSet descriptors; - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; VkPipelineLayout layout; - unsigned maxImages; VkSampler sampler; - aliasindset_t texindices; } aliasctx_t; struct vulkan_ctx_s; diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 0f5d54f7a..38c738c43 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -46,7 +46,7 @@ typedef struct vulktex_s { struct elechain_s *elechain; struct elechain_s **elechain_tail; struct qfv_tex_s *tex; - int texind; + VkDescriptorSet descriptor; } vulktex_t; typedef struct bspvert_s { @@ -96,7 +96,6 @@ typedef struct bspframe_s { typedef struct fragconst_s { quat_t fog; float time; - int texind; } fragconst_t; typedef struct bspframeset_s @@ -138,6 +137,7 @@ typedef struct bspctx_s { struct qfv_tex_s *default_skybox; struct qfv_tex_s *skybox_tex; + VkDescriptorSet skybox_descriptor; vec4f_t sky_rotation[2]; vec4f_t sky_velocity; vec4f_t sky_fix; @@ -152,11 +152,7 @@ typedef struct bspctx_s { struct bsppoly_s *polys; VkSampler sampler; - VkDescriptorSet descriptors; - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; VkPipelineLayout layout; - unsigned maxImages; VkDeviceMemory texture_memory; VkPipeline depth; diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index fec02a8f9..eadbc8b16 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -10,6 +10,11 @@ typedef struct qfv_tex_s { VkImageView view; } qfv_tex_t; +typedef struct texturectx_s { + VkDescriptorPool pool; + VkDescriptorSetLayout setLayout; +} texturectx_t; + void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, int alpha, int count); qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip, @@ -22,5 +27,12 @@ VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure)); void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex); void Vulkan_Texture_Init (struct vulkan_ctx_s *ctx); void Vulkan_Texture_Shutdown (struct vulkan_ctx_s *ctx); +VkDescriptorSet Vulkan_CreateCombinedImageSampler (struct vulkan_ctx_s *ctx, + VkImageView view, + VkSampler sampler); +VkDescriptorSet Vulkan_CreateTextureDescriptor (struct vulkan_ctx_s *ctx, + qfv_tex_t *tex, + VkSampler sampler); +void Vulkan_FreeTexture (struct vulkan_ctx_s *ctx, VkDescriptorSet texture); #endif//__QF_Vulkan_qf_texture_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index e0be2a993..66d394181 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -56,6 +56,7 @@ typedef struct vulkan_ctx_s { struct hashtab_s *imageViews; struct hashtab_s *renderpasses; + struct texturectx_s *texture_context; struct matrixctx_s *matrix_context; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 471cfac4c..2fcc9f5bd 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -83,6 +83,10 @@ vulkan_brush_clear (model_t *mod, void *data) vulktex_t *tex = tx->render; dfunc->vkDestroyImage (device->dev, tex->tex->image, 0); dfunc->vkDestroyImageView (device->dev, tex->tex->view, 0); + if (tex->descriptor) { + Vulkan_FreeTexture (ctx, tex->descriptor); + tex->descriptor = 0; + } } dfunc->vkFreeMemory (device->dev, mctx->texture_memory, 0); } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index dfd5e1a43..d503ac144 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -4,7 +4,6 @@ //needs to agree on the size, so it might as well set maxSamplers //directly (and any other such variable) maxSamplers = "min (256u, $physDevLimits.maxPerStageDescriptorSamplers)"; - maxImages = "min (256u, $physDevLimits.maxPerStageDescriptorSampledImages - 8u)"; }; samplers = { quakepic = { @@ -99,16 +98,12 @@ ); }; texture_pool = { - flags = 0; - maxSets = 1; + flags = free_descriptor_set; + maxSets = 512; bindings = ( { - type = sampler; - descriptorCount = 1; - }, - { - type = sampled_image; - descriptorCount = $properties.limits.maxImages; + type = combined_image_sampler; + descriptorCount = $properties.descriptorPools.texture_pool.maxSets; }, ); }; @@ -205,16 +200,10 @@ bindings = ( { binding = 0; - descriptorType = sampler; + descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; }, - { - binding = 1; - descriptorType = sampled_image; - descriptorCount = $properties.limits.maxImages; - stageFlags = fragment; - }, ); }; quakebsp_set = $properties.setLayouts.texture_set; @@ -333,7 +322,7 @@ setLayouts = (matrix_set, twod_set); }; quakebsp_layout = { - setLayouts = (matrix_set, quakebsp_set); + setLayouts = (matrix_set, texture_set, texture_set); pushConstantRanges = ( { stageFlags = vertex; @@ -343,7 +332,7 @@ { stageFlags = fragment; offset = 64; - size = 32; + size = "4 * 4 + 4"; }, ); }; @@ -697,13 +686,6 @@ stage = fragment; name = main; module = $builtin/alias_gbuf.frag; - specializationInfo = { - mapEntries = ( - // MaxTextures - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(uint($properties.limits.maxImages))"; - }; }, ); vertexInput = $properties.vertexInput.alias; @@ -773,13 +755,6 @@ stage = fragment; name = main; module = $builtin/bsp_gbuf.frag; - specializationInfo = { - mapEntries = ( - // MaxTextures - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(uint($properties.limits.maxImages))"; - }; }, ); vertexInput = $properties.vertexInput.brush; @@ -817,14 +792,12 @@ module = $builtin/bsp_sky.frag; specializationInfo = { mapEntries = ( - // MaxTextures - { size = 4; offset = 8; constantID = 0; }, // doSkyBox - { size = 4; offset = 4; constantID = 1; }, + { size = 4; offset = 4; constantID = 0; }, // doSkySheet - { size = 4; offset = 0; constantID = 2; }, + { size = 4; offset = 0; constantID = 1; }, ); - data = "array(0, 1, uint($properties.limits.maxImages))"; + data = "array(0, 1)"; }; }, ); @@ -858,14 +831,12 @@ module = $builtin/bsp_sky.frag; specializationInfo = { mapEntries = ( - // MaxTextures - { size = 4; offset = 8; constantID = 0; }, // doSkyBox - { size = 4; offset = 0; constantID = 1; }, + { size = 4; offset = 0; constantID = 0; }, // doSkySheet - { size = 4; offset = 4; constantID = 2; }, + { size = 4; offset = 4; constantID = 1; }, ); - data = "array(0, 1, uint($properties.limits.maxImages))"; + data = "array(0, 1)"; }; }, ); @@ -897,13 +868,6 @@ stage = fragment; name = main; module = $builtin/bsp_turb.frag; - specializationInfo = { - mapEntries = ( - // MaxTextures - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(uint($properties.limits.maxImages))"; - }; }, ); vertexInput = $properties.vertexInput.brush; diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index 28c37fec8..2b751a0c7 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -1,13 +1,9 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - -layout (set = 1, binding = 0) uniform sampler samp; -layout (set = 1, binding = 1) uniform texture2DArray skins[MaxTextures]; +layout (set = 1, binding = 0) uniform sampler2DArray Skin; layout (push_constant) uniform PushConstants { layout (offset = 68) - uint texind; uint colorA; uint colorB; vec4 base_color; @@ -30,10 +26,10 @@ main (void) vec4 e; int i; vec3 light = vec3 (0); - c = texture (sampler2DArray(skins[texind], samp), vec3 (st, 0)) * base_color; - c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 1)) * unpackUnorm4x8(colorA); - c += texture (sampler2DArray(skins[texind], samp), vec3 (st, 2)) * unpackUnorm4x8(colorB); - e = texture (sampler2DArray(skins[texind], samp), vec3 (st, 3)); + c = texture (Skin, vec3 (st, 0)) * base_color; + c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA); + c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB); + e = texture (Skin, vec3 (st, 3)); frag_color = c; frag_emission = e; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index 7d1c7c3c9..843148635 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -1,15 +1,11 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - -layout (set = 1, binding = 0) uniform sampler samp; -layout (set = 1, binding = 1) uniform texture2DArray textures[MaxTextures]; +layout (set = 1, binding = 0) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; - int texind; }; layout (location = 0) in vec4 tl_st; @@ -41,8 +37,8 @@ main (void) vec3 e_st = vec3 (tl_st.xy, 1); vec2 l_st = vec2 (tl_st.zw); - c = texture (sampler2DArray (textures[texind], samp), t_st); - e = texture (sampler2DArray (textures[texind], samp), e_st); + c = texture (Texture, t_st); + e = texture (Texture, e_st); frag_color = c;//fogBlend (c); frag_emission = e; frag_normal = vec4 (normal, 0); diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index dc6fe6d6a..25ccf9ba0 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -1,19 +1,15 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; layout (constant_id = 1) const bool doSkyBox = false; layout (constant_id = 2) const bool doSkySheet = false; -layout (set = 1, binding = 0) uniform sampler samp; -layout (set = 1, binding = 1) uniform texture2DArray sheet_tex[MaxTextures]; -layout (set = 1, binding = 1) uniform textureCube cube_tex[MaxTextures]; +layout (set = 1, binding = 0) uniform sampler2DArray SkySheet; +layout (set = 2, binding = 0) uniform samplerCube SkyBox; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; - int sheet_ind; - int cube_ind; }; layout (location = 0) in vec4 tl_st; @@ -34,7 +30,7 @@ fogBlend (vec4 color) } vec4 -sky_sheet (vec3 dir, float time, texture2DArray tex) +sky_sheet (vec3 dir, float time) { float len; vec2 flow = vec2 (1.0, 1.0); @@ -50,8 +46,8 @@ sky_sheet (vec3 dir, float time, texture2DArray tex) st1 = vec3 (base + flow * time / 8.0, 0); st2 = vec3 (base + flow * time / 16.0, 1); - c1 = texture (sampler2DArray(tex, samp), st1); - c2 = texture (sampler2DArray(tex, samp), st2); + c1 = texture (SkySheet, st1); + c2 = texture (SkySheet, st2); c = vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); @@ -59,7 +55,7 @@ sky_sheet (vec3 dir, float time, texture2DArray tex) } vec4 -sky_box (vec3 dir, float time, textureCube tex) +sky_box (vec3 dir, float time) { // NOTE: quake's world is right-handed with Z up and X forward, but // Vulkan's cube maps are left-handed with Y up and Z forward. The @@ -67,21 +63,21 @@ sky_box (vec3 dir, float time, textureCube tex) // to do here is swizzle the Y and Z coordinates dir = normalize(dir); //return vec4(dir.xyz, 1) * 0.5 + vec4(0.5); - return texture (samplerCube (tex, samp), dir.xzy); + return texture (SkyBox, dir.xzy); } vec4 sky_color (vec3 dir, float time) { if (!doSkySheet) { - return sky_box (dir, time, cube_tex[cube_ind]); + return sky_box (dir, time); } if (!doSkyBox) { - return sky_sheet (dir, time, sheet_tex[sheet_ind]); + return sky_sheet (dir, time); } else { // can see through the sheet (may look funny when looking down) // maybe have 4 sheet layers instead of 2? - vec4 c1 = sky_sheet (dir, time, sheet_tex[sheet_ind]); - vec4 c2 = sky_box (dir, time, cube_tex[cube_ind]); + vec4 c1 = sky_sheet (dir, time); + vec4 c2 = sky_box (dir, time); return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); return vec4 (1, 0, 1, 1); } diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index bee7a6a02..35faa1428 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -1,15 +1,11 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - -layout (set = 1, binding = 0) uniform sampler samp; -layout (set = 1, binding = 1) uniform texture2DArray textures[MaxTextures]; +layout (set = 1, binding = 0) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; - int texind; }; layout (location = 0) in vec4 tl_st; @@ -50,7 +46,7 @@ main (void) vec3 t_st = vec3 (warp_st (tl_st.xy, time), 0); vec3 e_st = vec3 (warp_st (tl_st.xy, time), 1); - c = texture (sampler2DArray (textures[texind], samp), t_st); - e = texture (sampler2DArray (textures[texind], samp), e_st); + c = texture (Texture, t_st); + e = texture (Texture, e_st); frag_color = c + e;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/shader/particle.frag b/libs/video/renderer/vulkan/shader/particle.frag index e9272912f..167c1f014 100644 --- a/libs/video/renderer/vulkan/shader/particle.frag +++ b/libs/video/renderer/vulkan/shader/particle.frag @@ -1,7 +1,5 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - layout (location = 0) in vec4 uv_tr; layout (location = 1) in vec4 color; diff --git a/libs/video/renderer/vulkan/shader/sprite_depth.frag b/libs/video/renderer/vulkan/shader/sprite_depth.frag index 3d7b95522..d44ba3725 100644 --- a/libs/video/renderer/vulkan/shader/sprite_depth.frag +++ b/libs/video/renderer/vulkan/shader/sprite_depth.frag @@ -1,7 +1,5 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - layout (set = 1, binding = 1) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag index bb2716def..a890ca94d 100644 --- a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag @@ -1,7 +1,5 @@ #version 450 -layout (constant_id = 0) const int MaxTextures = 256; - layout (set = 1, binding = 1) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index d40ea4562..f1ceed2d3 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -114,6 +114,11 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, dfunc->vkCmdPushConstants (cmd, actx->layout, VK_SHADER_STAGE_FRAGMENT_BIT, 68, frag_size, frag_constants); + VkDescriptorSet sets[] = { + skin->descriptor, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + actx->layout, 1, 1, sets, 0, 0); } dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); } @@ -133,9 +138,9 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) float blend; } vertex_constants; struct { - uint32_t texind; byte colorA[4]; byte colorB[4]; + float pad; float base_color[4]; float fog[4]; } fragment_constants; @@ -154,7 +159,7 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr); skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } - fragment_constants.texind = skin->texind; + fragment_constants.pad = 0; QuatCopy (ent->renderer.colormod, fragment_constants.base_color); QuatCopy (skin->colora, fragment_constants.colorA); QuatCopy (skin->colorb, fragment_constants.colorB); @@ -205,10 +210,9 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - actx->descriptors, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, 0, 2, sets, 0, 0); + actx->layout, 0, 1, sets, 0, 0); dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); @@ -274,74 +278,25 @@ Vulkan_AliasDepthRange (qfv_renderframe_t *rFrame, &viewport); } -static VkDescriptorImageInfo base_sampler_info = { }; -static VkDescriptorImageInfo base_image_info = { - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -}; -static VkWriteDescriptorSet base_sampler_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstBinding = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, -}; -static VkWriteDescriptorSet base_image_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstBinding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, -}; - void Vulkan_AliasAddSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; - - if (!actx->texindices.size) { - Sys_Error ("ran out of skins (smart texture handling not implemented)"); - } - skin->texind = DARRAY_REMOVE (&actx->texindices); - - VkDescriptorImageInfo imageInfo[1]; - imageInfo[0] = base_image_info; - imageInfo[0].imageView = skin->view; - - VkWriteDescriptorSet write[2]; - write[0] = base_image_write; - write[0].dstSet = actx->descriptors; - write[0].dstArrayElement = skin->texind; - write[0].descriptorCount = 1; - write[0].pImageInfo = imageInfo; - dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + skin->descriptor = Vulkan_CreateCombinedImageSampler (ctx, skin->view, + actx->sampler); } void Vulkan_AliasRemoveSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - aliasctx_t *actx = ctx->alias_context; - - DARRAY_APPEND (&actx->texindices, skin->texind); - - VkDescriptorImageInfo imageInfo[1]; - imageInfo[0] = base_image_info; - imageInfo[0].imageView = ctx->default_magenta_array->view; - - VkWriteDescriptorSet write[2]; - write[0] = base_image_write; - write[0].dstSet = actx->descriptors; - write[0].dstArrayElement = skin->texind; - write[0].descriptorCount = 1; - write[0].pImageInfo = imageInfo; - dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + Vulkan_FreeTexture (ctx, skin->descriptor); + skin->descriptor = 0; } void Vulkan_Alias_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; qfvPushDebug (ctx, "alias init"); @@ -358,49 +313,6 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); - //FIXME too many places - __auto_type limits = device->physDev->properties.limits; - actx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8); - actx->pool = Vulkan_CreateDescriptorPool (ctx, "alias_pool"); - actx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "alias_set"); - //FIXME kinda dumb - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = actx->setLayout; - } - __auto_type sets = QFV_AllocateDescriptorSet (device, actx->pool, layouts); - actx->descriptors = sets->a[0]; - free (sets); - - DARRAY_INIT (&actx->texindices, actx->maxImages); - DARRAY_RESIZE (&actx->texindices, actx->maxImages); - actx->texindices.grow = 0; - actx->texindices.maxSize = actx->maxImages; - for (unsigned i = 0; i < actx->maxImages; i++) { - actx->texindices.a[i] = i; - } - - VkDescriptorImageInfo samplerInfo[1]; - samplerInfo[0] = base_sampler_info; - samplerInfo[0].sampler = actx->sampler; - - VkDescriptorImageInfo imageInfo[actx->maxImages]; - for (unsigned i = 0; i < actx->maxImages; i++) { - imageInfo[i] = base_image_info; - imageInfo[i].imageView = ctx->default_magenta_array->view; - } - VkWriteDescriptorSet write[2]; - write[0] = base_sampler_write; - write[0].dstSet = actx->descriptors; - write[0].pImageInfo = samplerInfo; - write[1] = base_image_write; - write[1].dstSet = actx->descriptors; - write[1].descriptorCount = actx->maxImages; - write[1].pImageInfo = imageInfo; - dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); - - - for (size_t i = 0; i < frames; i++) { __auto_type aframe = &actx->frames.a[i]; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index db0877881..697d46070 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -162,8 +162,11 @@ add_texture (texture_t *tx, vulkan_ctx_t *ctx) bspctx_t *bctx = ctx->bsp_context; vulktex_t *tex = tx->render; - tex->texind = bctx->texture_chains.size; - DARRAY_APPEND (&bctx->texture_chains, tex); + if (tex->tex) { + DARRAY_APPEND (&bctx->texture_chains, tex); + tex->descriptor = Vulkan_CreateTextureDescriptor (ctx, tex->tex, + bctx->sampler); + } tex->tex_chain = 0; tex->tex_chain_tail = &tex->tex_chain; tex->elechain = 0; @@ -261,29 +264,9 @@ clear_textures (vulkan_ctx_t *ctx) bctx->texture_chains.size = 0; } -static VkDescriptorImageInfo base_sampler_info = { }; -static VkDescriptorImageInfo base_image_info = { - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL -}; -static VkWriteDescriptorSet base_sampler_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstBinding = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER, -}; -static VkWriteDescriptorSet base_image_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstBinding = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, -}; - void Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - bspctx_t *bctx = ctx->bsp_context; - int i; model_t *m; mod_brush_t *brush = &r_worldentity.renderer.model->brush; @@ -306,33 +289,6 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) brush->numsubmodels = 1; // no support for submodels in non-world model register_textures (brush, ctx); } - if (bctx->texture_chains.size > bctx->maxImages) { - Sys_Error ("smart texture handling not implemented, want %zd textures," - "can support %d.", - bctx->texture_chains.size, bctx->maxImages); - } - - VkDescriptorImageInfo samplerInfo[1]; - samplerInfo[0] = base_sampler_info; - samplerInfo[0].sampler = bctx->sampler; - - VkDescriptorImageInfo imageInfo[bctx->maxImages]; - for (unsigned i = 0; i < bctx->maxImages; i++) { - imageInfo[i] = base_image_info; - imageInfo[i].imageView = ctx->default_magenta_array->view; - if (i && i < bctx->texture_chains.size) { - imageInfo[i].imageView = bctx->texture_chains.a[i]->tex->view; - } - } - VkWriteDescriptorSet write[2]; - write[0] = base_sampler_write; - write[0].dstSet = bctx->descriptors; - write[0].pImageInfo = samplerInfo; - write[1] = base_image_write; - write[1].dstSet = bctx->descriptors; - write[1].descriptorCount = bctx->maxImages; - write[1].pImageInfo = imageInfo; - dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); } static elechain_t * @@ -803,12 +759,14 @@ push_transform (vec_t *transform, VkPipelineLayout layout, } static void -push_texind (int32_t texind, VkPipelineLayout layout, - qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) +bind_texture (vulktex_t *tex, uint32_t setnum, VkPipelineLayout layout, + qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) { - dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, - /*FIXME 64*/ 64 + field_offset (fragconst_t, texind), - sizeof (int32_t), &texind); + VkDescriptorSet sets[] = { + tex->descriptor, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, setnum, 1, sets, 0, 0); } static void @@ -892,10 +850,9 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - bctx->descriptors, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, sets, 0, 0); + layout, 0, 1, sets, 0, 0); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -928,8 +885,10 @@ bsp_begin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], bframe->cmdSet.a[QFV_bspGBuffer]); + qfvPushDebug (ctx, "bsp_begin_subpass"); bsp_begin_subpass (QFV_bspDepth, bctx->depth, bctx->layout, rFrame); bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, bctx->layout, rFrame); + qfvPopDebug (ctx); } static void @@ -957,7 +916,9 @@ turb_begin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], bframe->cmdSet.a[QFV_bspTurb]); + qfvPushDebug (ctx, "bsp_begin_subpass"); bsp_begin_subpass (QFV_bspTurb, bctx->turb, bctx->layout, rFrame); + qfvPopDebug (ctx); } static void @@ -1008,11 +969,13 @@ sky_begin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], bframe->cmdSet.a[QFV_bspSky]); + qfvPushDebug (ctx, "bsp_begin_subpass"); if (bctx->skybox_tex) { bsp_begin_subpass (QFV_bspSky, bctx->skybox, bctx->layout, rFrame); } else { bsp_begin_subpass (QFV_bspSky, bctx->skysheet, bctx->layout, rFrame); } + qfvPopDebug (ctx); } static void @@ -1114,8 +1077,8 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) build_tex_elechain (tex, bctx, bframe); - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspGBuffer]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspGBuffer]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, @@ -1171,8 +1134,8 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) msurface_t *surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspTurb]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); @@ -1188,8 +1151,8 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspTurb]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspTurb]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); @@ -1221,6 +1184,9 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) return; sky_begin (rFrame); + vulktex_t skybox = { .descriptor = bctx->skybox_descriptor }; + bind_texture (&skybox, 2, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); push_transform (identity, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); fragconst_t frag_constants = { time: vr_data.realtime }; @@ -1230,8 +1196,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) msurface_t *surf = is->surface; if (tex != surf->texinfo->texture->render) { if (tex) { - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspSky]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); @@ -1247,8 +1213,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) add_surf_elements (tex, is, &ec, &el, bctx, bframe); } if (tex) { - push_texind (tex->texind, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspSky]); + bind_texture (tex, 1, bctx->layout, dfunc, + bframe->cmdSet.a[QFV_bspSky]); for (ec = tex->elechain; ec; ec = ec->next) { draw_elechain (ec, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); @@ -1410,20 +1376,6 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); - //FIXME too many places - __auto_type limits = device->physDev->properties.limits; - bctx->maxImages = min (256, limits.maxPerStageDescriptorSampledImages - 8); - bctx->pool = Vulkan_CreateDescriptorPool (ctx, "quakebsp_pool"); - bctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "quakebsp_set"); - //FIXME kinda dumb - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = bctx->setLayout; - } - __auto_type sets = QFV_AllocateDescriptorSet (device, bctx->pool, layouts); - bctx->descriptors = sets->a[0]; - free (sets); - for (size_t i = 0; i < frames; i++) { __auto_type bframe = &bctx->frames.a[i]; @@ -1440,6 +1392,11 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bsp_pass_names[j])); } } + + bctx->skybox_descriptor + = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, + bctx->sampler); + qfvPopDebug (ctx); } @@ -1509,6 +1466,7 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) if (bctx->skybox_tex) { Vulkan_UnloadTex (ctx, bctx->skybox_tex); + Vulkan_FreeTexture (ctx, bctx->skybox_descriptor); } bctx->skybox_tex = 0; @@ -1518,6 +1476,9 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) if (!*sky || !strcasecmp (sky, "none")) { Sys_MaskPrintf (SYS_vulkan, "Skybox unloaded\n"); + bctx->skybox_descriptor + = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, + bctx->sampler); return; } @@ -1558,6 +1519,9 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) } } if (bctx->skybox_tex) { + bctx->skybox_descriptor + = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, + bctx->sampler); Sys_MaskPrintf (SYS_vulkan, "Skybox %s loaded\n", sky); } } diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index b90601102..611836cc2 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -54,6 +54,7 @@ #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" @@ -426,6 +427,14 @@ static tex_t default_magenta_tex = {1, 1, tex_rgba, 1, 0, magenta_data}; void Vulkan_Texture_Init (vulkan_ctx_t *ctx) { + qfvPushDebug (ctx, "texture init"); + + texturectx_t *tctx = calloc (1, sizeof (texturectx_t)); + ctx->texture_context = tctx; + + tctx->pool = Vulkan_CreateDescriptorPool (ctx, "texture_pool"); + tctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "texture_set"); + ctx->default_black = Vulkan_LoadTex (ctx, &default_black_tex, 1, "default_black"); ctx->default_white = Vulkan_LoadTex (ctx, &default_white_tex, 1, @@ -440,6 +449,7 @@ Vulkan_Texture_Init (vulkan_ctx_t *ctx) VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + qfvPopDebug (ctx); } void @@ -450,3 +460,65 @@ Vulkan_Texture_Shutdown (vulkan_ctx_t *ctx) Vulkan_UnloadTex (ctx, ctx->default_magenta); Vulkan_UnloadTex (ctx, ctx->default_magenta_array); } + +static VkDescriptorImageInfo base_image_info = { + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, +}; +static VkWriteDescriptorSet base_image_write = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstBinding = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, +}; + +VkDescriptorSet +Vulkan_CreateCombinedImageSampler (vulkan_ctx_t *ctx, VkImageView view, + VkSampler sampler) +{ + qfvPushDebug (ctx, "Vulkan_CreateCombinedImageSampler"); + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + texturectx_t *tctx = ctx->texture_context; + + //FIXME kinda dumb + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = tctx->setLayout; + } + __auto_type sets = QFV_AllocateDescriptorSet (device, tctx->pool, layouts); + VkDescriptorSet descriptor = sets->a[0]; + free (sets); + + VkDescriptorImageInfo imageInfo[1]; + imageInfo[0] = base_image_info; + imageInfo[0].sampler = sampler; + imageInfo[0].imageView = view; + + VkWriteDescriptorSet write[1]; + write[0] = base_image_write; + write[0].dstSet = descriptor; + write[0].pImageInfo = imageInfo; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + + qfvPopDebug (ctx); + + return descriptor; +} + +VkDescriptorSet +Vulkan_CreateTextureDescriptor (vulkan_ctx_t *ctx, qfv_tex_t *tex, + VkSampler sampler) +{ + return Vulkan_CreateCombinedImageSampler (ctx, tex->view, sampler); +} + +void +Vulkan_FreeTexture (vulkan_ctx_t *ctx, VkDescriptorSet texture) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + texturectx_t *tctx = ctx->texture_context; + + dfunc->vkFreeDescriptorSets (device->dev, tctx->pool, 1, &texture); +} From 0b99ff104df690e96a529cc1aad99afab66f5caf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 14:51:16 +0900 Subject: [PATCH 1973/3664] [vulkan] Clear the color attachments This means color, emission, and translucent. Fixes the HOM issues on my VersaPro (but halves the frame-rate... definitely need to bring back the forward renderer as an option). --- libs/video/renderer/vulkan/deferred.plist | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 1582d1ea7..087710d8c 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -253,7 +253,7 @@ { format = $properties.images.color.format; samples = 1; - loadOp = dont_care; + loadOp = clear; storeOp = dont_care; stencilLoadOp = dont_care; stencilStoreOp = dont_care; @@ -263,7 +263,7 @@ { format = $properties.images.emission.format; samples = 1; - loadOp = dont_care; + loadOp = clear; storeOp = dont_care; stencilLoadOp = dont_care; stencilStoreOp = dont_care; @@ -303,7 +303,7 @@ { format = $properties.images.translucent.format; samples = 1; - loadOp = dont_care; + loadOp = clear; storeOp = dont_care; stencilLoadOp = dont_care; stencilStoreOp = dont_care; From b9bc3fa132cd8acda1aed92c585b73e1a285f7ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 14:54:02 +0900 Subject: [PATCH 1974/3664] [vulkan] Split out the push constants helper It proved to work well in the sprite pipeline, and should be useful for cleaning up the magic numbers in bsp and alias. --- include/QF/Vulkan/command.h | 11 +++++++++++ libs/video/renderer/vulkan/command.c | 14 ++++++++++++++ libs/video/renderer/vulkan/vulkan_sprite.c | 13 +------------ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index c9ed3021e..d568e03f2 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -44,4 +44,15 @@ int QFV_QueueSubmit (struct qfv_queue_s *queue, qfv_semaphoreset_t *signalSemaphores, VkFence fence); int QFV_QueueWaitIdle (struct qfv_queue_s *queue); +typedef struct { + VkShaderStageFlags stageFlags; + uint32_t offset; + uint32_t size; + const void *data; +} qfv_push_constants_t; + +void QFV_PushConstants (struct qfv_device_s *device, VkCommandBuffer cmd, + VkPipelineLayout layout, uint32_t numPC, + const qfv_push_constants_t *constants); + #endif//__QF_Vulkan_command_h diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 5843a15f3..bd21bb8b6 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -162,3 +162,17 @@ QFV_QueueWaitIdle (qfv_queue_t *queue) qfv_devfuncs_t *dfunc = device->funcs; return dfunc->vkQueueWaitIdle (queue->queue) == VK_SUCCESS; } + +void +QFV_PushConstants (qfv_device_t *device, VkCommandBuffer cmd, + VkPipelineLayout layout, uint32_t numPC, + const qfv_push_constants_t *constants) +{ + qfv_devfuncs_t *dfunc = device->funcs; + + for (uint32_t i = 0; i < numPC; i++) { + dfunc->vkCmdPushConstants (cmd, layout, constants[i].stageFlags, + constants[i].offset, constants[i].size, + constants[i].data); + } +} diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 6b8935e26..a27f9947c 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -67,13 +67,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -typedef struct { - VkShaderStageFlags stageFlags; - uint32_t offset; - uint32_t size; - const void *data; -} qfv_push_constants_t; - static const char * __attribute__((used)) sprite_pass_names[] = { "depth", "g-buffer", @@ -96,11 +89,7 @@ emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, qfv_devfuncs_t *dfunc = device->funcs; spritectx_t *sctx = ctx->sprite_context; - for (int i = 0; i < numPC; i++) { - dfunc->vkCmdPushConstants (cmd, sctx->layout, constants[i].stageFlags, - constants[i].offset, constants[i].size, - constants[i].data); - } + QFV_PushConstants (device, cmd, sctx->layout, numPC, constants); VkDescriptorSet sets[] = { sprite->descriptors, }; From 081c46da7a7debd7c5f39e5e32184c5f6a67cfdb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 14:55:49 +0900 Subject: [PATCH 1975/3664] Clean up some white space --- libs/video/renderer/vid_render_vulkan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index b5a994768..b877569d4 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -157,7 +157,6 @@ vulkan_R_RenderFrame (SCR_Func *scr_funcs) __auto_type rp = vulkan_ctx->renderPasses.a[i]; __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - frame->framebuffer = rp->framebuffers->a[imageIndex]; renderPassInfo.framebuffer = frame->framebuffer, renderPassInfo.renderPass = rp->renderpass; From 36e98f013e6cebdc832a25498b2108ca80218fb2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 15:51:33 +0900 Subject: [PATCH 1976/3664] [vulkan] Clean up bsp push-constants. --- include/QF/Vulkan/qf_bsp.h | 5 -- libs/video/renderer/vulkan/vulkan_bsp.c | 71 ++++++++++++++++--------- 2 files changed, 45 insertions(+), 31 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 38c738c43..1408ce64a 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -93,11 +93,6 @@ typedef struct bspframe_s { qfv_cmdbufferset_t cmdSet; } bspframe_t; -typedef struct fragconst_s { - quat_t fog; - float time; -} fragconst_t; - typedef struct bspframeset_s DARRAY_TYPE (bspframe_t) bspframeset_t; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 697d46070..26ea253f1 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -71,6 +71,12 @@ #include "r_internal.h" #include "vid_vulkan.h" +typedef struct bsp_push_constants_s { + mat4f_t Model; + quat_t fog; + float time; +} bsp_push_constants_t; + static const char * __attribute__((used)) bsp_pass_names[] = { "depth", "g-buffer", @@ -752,10 +758,14 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) static void push_transform (vec_t *transform, VkPipelineLayout layout, - qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) + qfv_device_t *device, VkCommandBuffer cmd) { - dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, 16 * sizeof (float), transform); + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_VERTEX_BIT, + field_offset (bsp_push_constants_t, Model), + sizeof (mat4f_t), transform }, + }; + QFV_PushConstants (device, cmd, layout, 1, push_constants); } static void @@ -770,24 +780,33 @@ bind_texture (vulktex_t *tex, uint32_t setnum, VkPipelineLayout layout, } static void -push_fragconst (fragconst_t *fragconst, VkPipelineLayout layout, - qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) +push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout, + qfv_device_t *device, VkCommandBuffer cmd) { - dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT, - 64, sizeof (fragconst_t), fragconst);//FIXME 64 + qfv_push_constants_t push_constants[] = { + //{ VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat), mat }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (bsp_push_constants_t, fog), + sizeof (constants->fog), &constants->fog }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (bsp_push_constants_t, time), + sizeof (constants->time), &constants->time }, + }; + QFV_PushConstants (device, cmd, layout, 2, push_constants); } static void -draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, +draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_device_t *device, VkCommandBuffer cmd) { + qfv_devfuncs_t *dfunc = device->funcs; elements_t *el; if (ec->transform) { - push_transform (ec->transform, layout, dfunc, cmd); + push_transform (ec->transform, layout, device, cmd); } else { //FIXME should cache current transform - push_transform (identity, layout, dfunc, cmd); + push_transform (identity, layout, device, cmd); } for (el = ec->elements; el; el = el->next) { if (!el->index_count) @@ -1062,12 +1081,12 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bsp_begin (rFrame); - push_transform (identity, bctx->layout, dfunc, + push_transform (identity, bctx->layout, device, bframe->cmdSet.a[QFV_bspDepth]); - push_transform (identity, bctx->layout, dfunc, + push_transform (identity, bctx->layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); - fragconst_t frag_constants = { time: vr_data.realtime }; - push_fragconst (&frag_constants, bctx->layout, dfunc, + bsp_push_constants_t frag_constants = { time: vr_data.realtime }; + push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); for (size_t i = 0; i < bctx->texture_chains.size; i++) { vulktex_t *tex; @@ -1081,9 +1100,9 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bframe->cmdSet.a[QFV_bspGBuffer]); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, + draw_elechain (ec, bctx->layout, device, bframe->cmdSet.a[QFV_bspDepth]); - draw_elechain (ec, bctx->layout, dfunc, + draw_elechain (ec, bctx->layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); reset_elechain (ec); } @@ -1125,10 +1144,10 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) return; turb_begin (rFrame); - push_transform (identity, bctx->layout, dfunc, + push_transform (identity, bctx->layout, device, bframe->cmdSet.a[QFV_bspTurb]); - fragconst_t frag_constants = { time: vr_data.realtime }; - push_fragconst (&frag_constants, bctx->layout, dfunc, + bsp_push_constants_t frag_constants = { time: vr_data.realtime }; + push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspTurb]); for (is = bctx->waterchain; is; is = is->tex_chain) { msurface_t *surf = is->surface; @@ -1137,7 +1156,7 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) bind_texture (tex, 1, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, + draw_elechain (ec, bctx->layout, device, bframe->cmdSet.a[QFV_bspTurb]); reset_elechain (ec); } @@ -1154,7 +1173,7 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) bind_texture (tex, 1, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspTurb]); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, + draw_elechain (ec, bctx->layout, device, bframe->cmdSet.a[QFV_bspTurb]); reset_elechain (ec); } @@ -1187,10 +1206,10 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) vulktex_t skybox = { .descriptor = bctx->skybox_descriptor }; bind_texture (&skybox, 2, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); - push_transform (identity, bctx->layout, dfunc, + push_transform (identity, bctx->layout, device, bframe->cmdSet.a[QFV_bspSky]); - fragconst_t frag_constants = { time: vr_data.realtime }; - push_fragconst (&frag_constants, bctx->layout, dfunc, + bsp_push_constants_t frag_constants = { time: vr_data.realtime }; + push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspSky]); for (is = bctx->sky_chain; is; is = is->tex_chain) { msurface_t *surf = is->surface; @@ -1199,7 +1218,7 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) bind_texture (tex, 1, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, + draw_elechain (ec, bctx->layout, device, bframe->cmdSet.a[QFV_bspSky]); reset_elechain (ec); } @@ -1216,7 +1235,7 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) bind_texture (tex, 1, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, dfunc, + draw_elechain (ec, bctx->layout, device, bframe->cmdSet.a[QFV_bspSky]); reset_elechain (ec); } From 869cc4050ca098c44dfe11cd25f3980851a8b6d3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 15:52:17 +0900 Subject: [PATCH 1977/3664] [vulkan] Flush bsp vertex indices after all drawing --- include/QF/Vulkan/qf_bsp.h | 1 + libs/video/renderer/vulkan/vulkan_bsp.c | 15 +++++++++++---- libs/video/renderer/vulkan/vulkan_main.c | 18 +++++++++++------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 1408ce64a..9f1108601 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -170,6 +170,7 @@ void Vulkan_ClearElements (struct vulkan_ctx_s *ctx); void Vulkan_DrawWorld (struct qfv_renderframe_s *rFrame); void Vulkan_DrawSky (struct qfv_renderframe_s *rFrame); void Vulkan_DrawWaterSurfaces (struct qfv_renderframe_s *rFrame); +void Vulkan_Bsp_Flush (struct vulkan_ctx_s *ctx); void Vulkan_LoadSkys (const char *sky, struct vulkan_ctx_s *ctx); void Vulkan_RegisterTextures (model_t **models, int num_models, struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 26ea253f1..98ccb1ecc 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1041,7 +1041,7 @@ build_tex_elechain (vulktex_t *tex, bspctx_t *bctx, bspframe_t *bframe) elements_t *el = 0; for (is = tex->tex_chain; is; is = is->tex_chain) { - // emit the polygon indices for the the surface to the texture's + // emit the polygon indices for the surface to the texture's // element chain add_surf_elements (tex, is, &ec, &el, bctx, bframe); } @@ -1110,7 +1110,15 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) tex->elechain_tail = &tex->elechain; } bsp_end (ctx); +} +void +Vulkan_Bsp_Flush (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; size_t atom_mask = atom - 1; size_t offset = bframe->index_offset; @@ -1119,7 +1127,6 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) offset &= ~atom_mask; size = (size + atom_mask) & ~atom_mask; - //FIXME this needs to come at the end of the frame after all passes VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, bctx->index_memory, offset, size @@ -1165,7 +1172,7 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) } tex = surf->texinfo->texture->render; } - // emit the polygon indices for the the surface to the texture's + // emit the polygon indices for the surface to the texture's // element chain add_surf_elements (tex, is, &ec, &el, bctx, bframe); } @@ -1227,7 +1234,7 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) } tex = surf->texinfo->texture->render; } - // emit the polygon indices for the the surface to the texture's + // emit the polygon indices for the surface to the texture's // element chain add_surf_elements (tex, is, &ec, &el, bctx, bframe); } diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index a8cf1a1d7..62775419e 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -131,7 +131,7 @@ void Vulkan_RenderView (qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - double t[9] = {}; + double t[10] = {}; int speeds = r_speeds->int_val; if (!r_worldentity.renderer.model) { @@ -165,14 +165,18 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) Vulkan_DrawParticles (ctx); if (speeds) t[8] = Sys_DoubleTime (); + Vulkan_Bsp_Flush (ctx); + if (speeds) + t[9] = Sys_DoubleTime (); if (speeds) { + double total = (t[9] - t[0]) * 1000; + for (int i = 0; i < 9; i++) { + t[i] = (t[i + 1] - t[i]) * 1000; + } Sys_Printf ("frame: %g, setup: %g, mark: %g, pushdl: %g, world: %g," - " sky: %g, ents: %g, water: %g, part: %g\n", - (t[8] - t[0]) * 1000, (t[1] - t[0]) * 1000, - (t[2] - t[1]) * 1000, (t[3] - t[2]) * 1000, - (t[4] - t[3]) * 1000, (t[5] - t[4]) * 1000, - (t[6] - t[5]) * 1000, (t[7] - t[6]) * 1000, - (t[8] - t[7]) * 1000); + " sky: %g, ents: %g, water: %g, flush: %g, part: %g\n", + total, + t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8]); } } From 8b1eec08cff554763194a6a78c47e0878f99adc1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 16:42:31 +0900 Subject: [PATCH 1978/3664] [scene] Provide direct access to the world matrix Holding onto the pointer is not a good idea, and it is read-only as direct manipulation of the world matrix is not supported. However, this is useful for passing the matrix to the GPU. --- include/QF/scene/transform.h | 2 ++ libs/scene/transform.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index 2a015ff36..94595447c 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -61,6 +61,8 @@ uint32_t Transform_GetTag (const transform_t *transform) __attribute__((pure)); void Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat); void Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat); void Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat); +// XXX the pointer may be invalidated by hierarchy updates +const vec4f_t *Transform_GetWorldMatrixPtr (const transform_t *transform) __attribute__((pure)); void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat); vec4f_t Transform_GetLocalPosition (const transform_t *transform) __attribute__((pure)); void Transform_SetLocalPosition (transform_t *transform, vec4f_t position); diff --git a/libs/scene/transform.c b/libs/scene/transform.c index c5919c097..5983d83bb 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -183,6 +183,13 @@ Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat) memcpy (mat, h->worldMatrix.a[transform->index], sizeof (mat4f_t)); } +const vec4f_t * +Transform_GetWorldMatrixPtr (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldMatrix.a[transform->index]; +} + void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat) { From cd641e2b1c919a722eefd1dbc0bafd0b3f43e4c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 17 Dec 2021 16:46:54 +0900 Subject: [PATCH 1979/3664] [vulkan] Clean up alias push-constants --- libs/video/renderer/vulkan/vulkan_alias.c | 71 +++++++++++++---------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index f1ceed2d3..24e11fd8b 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -67,6 +67,15 @@ #include "r_internal.h" #include "vid_vulkan.h" +typedef struct { + mat4f_t mat; + float blend; + byte colorA[4]; + byte colorB[4]; + vec4f_t base_color; + vec4f_t fog; +} alias_push_constants_t; + static const char * __attribute__((used)) alias_pass_names[] = { "depth", "g-buffer", @@ -82,8 +91,7 @@ static QFV_Subpass subpass_map[] = { static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_alias_skin_t *skin, - void *vert_constants, int vert_size, - void *frag_constants, int frag_size, + uint32_t numPC, qfv_push_constants_t *constants, aliashdr_t *hdr, qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; @@ -108,12 +116,8 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, VK_INDEX_TYPE_UINT32); - dfunc->vkCmdPushConstants (cmd, actx->layout, VK_SHADER_STAGE_VERTEX_BIT, - 0, vert_size, vert_constants); + QFV_PushConstants (device, cmd, actx->layout, numPC, constants); if (skin) { - dfunc->vkCmdPushConstants (cmd, actx->layout, - VK_SHADER_STAGE_FRAGMENT_BIT, - 68, frag_size, frag_constants); VkDescriptorSet sets[] = { skin->descriptor, }; @@ -133,24 +137,34 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) aliashdr_t *hdr; qfv_alias_skin_t *skin; animation_t *animation = &ent->animation; - struct { - mat4f_t mat; - float blend; - } vertex_constants; - struct { - byte colorA[4]; - byte colorB[4]; - float pad; - float base_color[4]; - float fog[4]; - } fragment_constants; + alias_push_constants_t constants = {}; if (!(hdr = model->aliashdr)) { hdr = Cache_Get (&model->cache); } - Transform_GetWorldMatrix (ent->transform, vertex_constants.mat); - vertex_constants.blend = R_AliasGetLerpedFrames (animation, hdr); + constants.blend = R_AliasGetLerpedFrames (animation, hdr); + + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_VERTEX_BIT, + field_offset (alias_push_constants_t, mat), + sizeof (mat4f_t), Transform_GetWorldMatrixPtr (ent->transform) }, + { VK_SHADER_STAGE_VERTEX_BIT, + field_offset (alias_push_constants_t, blend), + sizeof (float), &constants.blend }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (alias_push_constants_t, colorA), + sizeof (constants.colorA), constants.colorA }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (alias_push_constants_t, colorB), + sizeof (constants.colorB), constants.colorB }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (alias_push_constants_t, base_color), + sizeof (constants.base_color), &constants.base_color }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (alias_push_constants_t, fog), + sizeof (constants.fog), &constants.fog }, + }; if (0/*XXX ent->skin && ent->skin->tex*/) { //skin = ent->skin->tex; @@ -159,22 +173,17 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr); skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } - fragment_constants.pad = 0; - QuatCopy (ent->renderer.colormod, fragment_constants.base_color); - QuatCopy (skin->colora, fragment_constants.colorA); - QuatCopy (skin->colorb, fragment_constants.colorB); - QuatZero (fragment_constants.fog); + QuatCopy (ent->renderer.colormod, constants.base_color); + QuatCopy (skin->colora, constants.colorA); + QuatCopy (skin->colorb, constants.colorB); + QuatZero (constants.fog); emit_commands (aframe->cmdSet.a[QFV_aliasDepth], ent->animation.pose1, ent->animation.pose2, - 0, &vertex_constants, 17 * sizeof (float), - &fragment_constants, sizeof (fragment_constants), - hdr, rFrame); + 0, 2, push_constants, hdr, rFrame); emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], ent->animation.pose1, ent->animation.pose2, - skin, &vertex_constants, 17 * sizeof (float), - &fragment_constants, sizeof (fragment_constants), - hdr, rFrame); + skin, 6, push_constants, hdr, rFrame); } static void From 5128029368cae106f80ef081b2839cfbe396417f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Dec 2021 11:28:59 +0900 Subject: [PATCH 1980/3664] [nq,qw] Clear render state when leaving active state This fixes a segfault caused by b0517e89293 that I had missed due to not actually playing: ie, demo map changes were ok, but not in-game map changes. --- nq/source/cl_main.c | 1 + qw/source/cl_main.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 8467187b1..2548a2518 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -526,6 +526,7 @@ CL_SetState (cactive_t state) if (old_state == ca_active) { // leaving active state S_AmbientOff (); + r_funcs->R_ClearState (); } switch (state) { case ca_dedicated: diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 6585ce04f..26c7f87d5 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1150,6 +1150,8 @@ CL_SetState (cactive_t state) // Auto demo recorder stops here if (cl_autorecord->int_val && cls.demorecording) CL_StopRecording (); + + r_funcs->R_ClearState (); } else if (state == ca_active) { // entering active state VID_SetCaption (cls.servername->str); From 83ec2be2a62b71204d7fdec857c84d9c3e7e42a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Dec 2021 13:02:42 +0900 Subject: [PATCH 1981/3664] [vid] Add a listener set for palette changes This was needed to get crosshaircolor working correctly, but is likely another step towards resizable windows (the listener set types are generic for any viddef event, not just palette changes). --- include/QF/vid.h | 11 +++++++++++ libs/video/targets/vid.c | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/QF/vid.h b/include/QF/vid.h index 9255e7210..499989f20 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -28,6 +28,7 @@ #ifndef __QF_vid_h #define __QF_vid_h +#include "QF/listener.h" #include "QF/qtypes.h" #define VID_CBITS 6 @@ -56,8 +57,14 @@ typedef struct { quat_t cshift_color; struct view_s *conview; struct vid_internal_s *vid_internal; + + struct viddef_listener_set_s *onPaletteChanged; } viddef_t; +typedef struct viddef_listener_set_s LISTENER_SET_TYPE (viddef_t) + viddef_listener_set_t; +typedef void (*viddef_listener_t) (void *data, const viddef_t *viddef); + #define viddef (*r_data->vid) extern unsigned int d_8to24table[256]; //FIXME nq/qw uses @@ -73,4 +80,8 @@ void VID_Init (byte *palette, byte *colormap); void VID_SetCaption (const char *text); void VID_ClearMemory (void); +void VID_OnPaletteChange_AddListener (viddef_listener_t listener, void *data); +void VID_OnPaletteChange_RemoveListener (viddef_listener_t listener, + void *data); + #endif//__QF_vid_h diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 682d301d5..b918dd1b9 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -241,6 +241,10 @@ VID_InitGamma (const byte *pal) VID_UpdateGamma, "Gamma correction"); VID_BuildGammaTable (vid_gamma->value); + + if (viddef.onPaletteChanged) { + LISTENER_INVOKE (viddef.onPaletteChanged, &viddef); + } } void @@ -317,3 +321,21 @@ VID_ClearMemory (void) vi->flush_caches (vi->data); } } + +VISIBLE void +VID_OnPaletteChange_AddListener (viddef_listener_t listener, void *data) +{ + if (!viddef.onPaletteChanged) { + viddef.onPaletteChanged = malloc (sizeof (*viddef.onPaletteChanged)); + LISTENER_SET_INIT (viddef.onPaletteChanged, 8); + } + LISTENER_ADD (viddef.onPaletteChanged, listener, data); +} + +VISIBLE void +VID_OnPaletteChange_RemoveListener (viddef_listener_t listener, void *data) +{ + if (viddef.onPaletteChanged) { + LISTENER_REMOVE (viddef.onPaletteChanged, listener, data); + } +} From 6b84ae5554f8333b052d8ffa860f3321a2145a9a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Dec 2021 13:05:10 +0900 Subject: [PATCH 1982/3664] [renderer] Update crosshair color on palette changes This gets the crosshair working in Vulkan (next commit) and fixes issues with changing the palette (though I've never seen a different palette for quate, there's still the change from "all black" to an actual palette). --- libs/video/renderer/r_cvar.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index 934e5bdbb..72a537223 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -107,12 +107,23 @@ int r_viewsize; quat_t crosshair_color; +static void +crosshaircolor_update (void *_var, const viddef_t *vid) +{ + cvar_t *var = _var; + byte *color; + color = &vid->palette32[bound (0, var->int_val, 255) * 4]; + QuatScale (color, 1.0 / 255, crosshair_color); +} + static void crosshaircolor_f (cvar_t *var) { - byte *color; - color = (byte *) &d_8to24table[bound (0, var->int_val, 255)]; - QuatScale (color, 1.0 / 255, crosshair_color); + if (!r_data->vid->palette32) { + // palette not initialized yet + return; + } + crosshaircolor_update (var, r_data->vid); } static void @@ -208,6 +219,7 @@ R_Init_Cvars (void) "type. 0 off, 1 old white, 2 new with colors"); crosshaircolor = Cvar_Get ("crosshaircolor", "79", CVAR_ARCHIVE, crosshaircolor_f, "Color of the new crosshair"); + VID_OnPaletteChange_AddListener (crosshaircolor_update, crosshaircolor); d_mipcap = Cvar_Get ("d_mipcap", "0", CVAR_NONE, NULL, "Detail level. 0 is highest, 3 is lowest."); d_mipscale = Cvar_Get ("d_mipscale", "1", CVAR_NONE, NULL, "Detail level " From be7216e660009c2fe4dca8ee67bbb338fa6cefb0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Dec 2021 13:07:56 +0900 Subject: [PATCH 1983/3664] [vulkan] Implement crosshair rendering That makes quite the difference to playability. --- libs/video/renderer/vulkan/vulkan_draw.c | 53 ++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index f64c6515e..2b13f7c35 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -95,6 +95,7 @@ typedef struct drawctx_s { VkSampler sampler; scrap_t *scrap; qfv_stagebuf_t *stage; + qpic_t *crosshair; qpic_t *conchars; qpic_t *conback; qpic_t *white_pic; @@ -389,6 +390,13 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) qpic_t *charspic = Draw_Font8x8Pic (); dctx->conchars = pic_data ("conchars", charspic->width, charspic->height, charspic->data, dctx); + free (charspic); + } + { + qpic_t *hairpic = Draw_CrosshairPic (); + dctx->crosshair = pic_data ("crosshair", hairpic->width, + hairpic->height, hairpic->data, dctx); + free (hairpic); } byte white_block = 0xfe; @@ -570,14 +578,59 @@ Vulkan_Draw_AltString (int x, int y, const char *str, vulkan_ctx_t *ctx) } } +static void +draw_crosshair_plus (int ch, int x, int y, vulkan_ctx_t *ctx) +{ + Vulkan_Draw_Character (x - 4, y - 4, '+', ctx); +} + +static void +draw_crosshair_pic (int ch, int x, int y, vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + + static const int pos[CROSSHAIR_COUNT][4] = { + {0, 0, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT}, + {CROSSHAIR_WIDTH, 0, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT}, + {0, CROSSHAIR_HEIGHT, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT}, + {CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT}, + }; + const int *p = pos[ch - 1]; + + draw_pic (x - CROSSHAIR_WIDTH + 1, y - CROSSHAIR_HEIGHT + 1, + CROSSHAIR_WIDTH * 2, CROSSHAIR_HEIGHT * 2, dctx->crosshair, + p[0], p[1], p[2], p[3], crosshair_color, frame); +} + +static void (*crosshair_func[]) (int ch, int x, int y, vulkan_ctx_t *ctx) = { + draw_crosshair_plus, + draw_crosshair_pic, + draw_crosshair_pic, + draw_crosshair_pic, + draw_crosshair_pic, +}; + void Vulkan_Draw_CrosshairAt (int ch, int x, int y, vulkan_ctx_t *ctx) { + unsigned c = ch - 1; + + if (c >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) + return; + + crosshair_func[c] (c, x, y, ctx); } void Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx) { + int x, y; + + x = vid.conview->xlen / 2 + cl_crossx->int_val; + y = vid.conview->ylen / 2 + cl_crossy->int_val; + + Vulkan_Draw_CrosshairAt (crosshair->int_val, x, y, ctx); } void From 4d1e8b2375b7295ea11e1e55bc1f9ed3f74db989 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Dec 2021 13:09:09 +0900 Subject: [PATCH 1984/3664] [vulkan] Update the number of drawn quads correctly They should increment by one for each pic, not 4 (I think some fluff remaining from copying glsl's draw code). I noticed the problem when I saw large gaps of 0s in the vertex data in renderdoc. --- libs/video/renderer/vulkan/vulkan_draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 2b13f7c35..a936f0b6f 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -448,12 +448,12 @@ draw_pic (float x, float y, int w, int h, qpic_t *pic, int srcx, int srcy, int srcw, int srch, float *color, drawframe_t *frame) { - if (frame->num_quads + VERTS_PER_QUAD > MAX_QUADS) { + if (frame->num_quads >= MAX_QUADS) { return; } drawvert_t *verts = frame->verts + frame->num_quads * VERTS_PER_QUAD; - frame->num_quads += VERTS_PER_QUAD; + frame->num_quads++; subpic_t *subpic = *(subpic_t **) pic->data; srcx += subpic->rect->x; From ce4bb1d56c841e319957b8cc462fafcc9542d599 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Dec 2021 01:21:39 +0900 Subject: [PATCH 1985/3664] [renderer] Move particles over to simd This has the advantage of getting entity_t out of the particle system, and much easier to read math. Also, it served as a nice test for my particle physics shaders (implemented the ideas in C). There's a lot of code that needs merging down: all but the actual drawing can be merged. There's some weirdness with color ramps, but I'll look into that later. --- include/QF/plugin/vid_render.h | 54 +- include/d_iface.h | 42 +- include/d_ifacea.h | 22 +- include/r_dynamic.h | 5 +- libs/client/cl_effects.c | 26 +- libs/client/cl_temp_entities.c | 50 +- libs/client/locs.c | 7 +- libs/video/renderer/gl/gl_dyn_part.c | 1462 +++++++--------- libs/video/renderer/glsl/glsl_particles.c | 1523 +++++++---------- libs/video/renderer/r_part.c | 313 +--- libs/video/renderer/sw/d_part.c | 24 +- libs/video/renderer/sw/sw_rpart.c | 838 ++++----- libs/video/renderer/sw32/d_part.c | 8 +- libs/video/renderer/sw32/sw32_rpart.c | 896 ++++------ libs/video/renderer/vulkan/vulkan_particles.c | 52 +- 15 files changed, 2078 insertions(+), 3244 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 8ed240c84..57e72a92f 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -45,38 +45,36 @@ struct mod_sprite_ctx_s; */ typedef struct vid_particle_funcs_s { - void (*R_RocketTrail) (const struct entity_s *ent); - void (*R_GrenadeTrail) (const struct entity_s *ent); - void (*R_BloodTrail) (const struct entity_s *ent); - void (*R_SlightBloodTrail) (const struct entity_s *ent); - void (*R_WizTrail) (const struct entity_s *ent); - void (*R_FlameTrail) (const struct entity_s *ent); - void (*R_VoorTrail) (const struct entity_s *ent); - void (*R_GlowTrail) (const struct entity_s *ent, int glow_color); + void (*R_RocketTrail) (vec4f_t start, vec4f_t end); + void (*R_GrenadeTrail) (vec4f_t start, vec4f_t end); + void (*R_BloodTrail) (vec4f_t start, vec4f_t end); + void (*R_SlightBloodTrail) (vec4f_t start, vec4f_t end); + void (*R_WizTrail) (vec4f_t start, vec4f_t end); + void (*R_FlameTrail) (vec4f_t start, vec4f_t end); + void (*R_VoorTrail) (vec4f_t start, vec4f_t end); + void (*R_GlowTrail) (vec4f_t start, vec4f_t end, int glow_color); - void (*R_RunParticleEffect) (const vec3_t org, const vec3_t dir, - int color, int count); - void (*R_BloodPuffEffect) (const vec3_t org, int count); - void (*R_GunshotEffect) (const vec3_t org, int count); - void (*R_LightningBloodEffect) (const vec3_t org); - void (*R_SpikeEffect) (const vec3_t org); - void (*R_KnightSpikeEffect) (const vec3_t org); - void (*R_SuperSpikeEffect) (const vec3_t org); - void (*R_WizSpikeEffect) (const vec3_t org); + void (*R_RunParticleEffect) (vec4f_t org, vec4f_t dir, int color, int count); + void (*R_BloodPuffEffect) (vec4f_t org, int count); + void (*R_GunshotEffect) (vec4f_t org, int count); + void (*R_LightningBloodEffect) (vec4f_t org); + void (*R_SpikeEffect) (vec4f_t org); + void (*R_KnightSpikeEffect) (vec4f_t org); + void (*R_SuperSpikeEffect) (vec4f_t org); + void (*R_WizSpikeEffect) (vec4f_t org); - void (*R_BlobExplosion) (const vec3_t org); - void (*R_ParticleExplosion) (const vec3_t org); - void (*R_ParticleExplosion2) (const vec3_t org, int colorStart, - int colorLength); - void (*R_LavaSplash) (const vec3_t org); - void (*R_TeleportSplash) (const vec3_t org); - void (*R_DarkFieldParticles) (const struct entity_s *ent); - void (*R_EntityParticles) (const struct entity_s *ent); + void (*R_BlobExplosion) (vec4f_t org); + void (*R_ParticleExplosion) (vec4f_t org); + void (*R_ParticleExplosion2) (vec4f_t org, int colorStart, int colorLength); + void (*R_LavaSplash) (vec4f_t org); + void (*R_TeleportSplash) (vec4f_t org); + void (*R_DarkFieldParticles) (vec4f_t org); + void (*R_EntityParticles) (vec4f_t org); - void (*R_Particle_New) (ptype_t type, int texnum, const vec3_t org, - float scale, const vec3_t vel, float die, + void (*R_Particle_New) (ptype_t type, int texnum, vec4f_t org, + float scale, vec4f_t vel, float die, int color, float alpha, float ramp); - void (*R_Particle_NewRandom) (ptype_t type, int texnum, const vec3_t org, + void (*R_Particle_NewRandom) (ptype_t type, int texnum, vec4f_t org, int org_fuzz, float scale, int vel_fuzz, float die, int color, float alpha, float ramp); diff --git a/include/d_iface.h b/include/d_iface.h index 621ccbaca..873ac2b7b 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -63,28 +63,38 @@ typedef enum { } ptextype_t; typedef struct particle_s particle_t; -typedef void (*pt_phys_func)(particle_t *); - -pt_phys_func R_ParticlePhysics (ptype_t type) __attribute__((pure)); // !!! if this is changed, it must be changed in d_ifacea.h too !!! -struct particle_s -{ -// driver-usable fields - vec3_t org; - int color; - float alpha; +struct particle_s { + vec4f_t pos; + vec4f_t vel; + + union { + struct { + int icolor; + int pad[2]; + float alpha; + }; + vec4f_t color; + }; + ptextype_t tex; - float scale; -// drivers never touch the following fields - vec3_t vel; - ptype_t type; - float die; float ramp; - pt_phys_func phys; - particle_t *next; + float scale; + float live; }; +typedef struct partparm_s { + vec4f_t drag; // drag[3] is grav scale + float ramp; + float ramp_max; + float scale_rate; + float alpha_rate; +} partparm_t; + +partparm_t R_ParticlePhysics (ptype_t type) __attribute__((pure)); +const int *R_ParticleRamp (ptype_t type) __attribute__((pure)); + #define PARTICLE_Z_CLIP 8.0 typedef struct polyvert_s { diff --git a/include/d_ifacea.h b/include/d_ifacea.h index fa61655e0..4f6118b76 100644 --- a/include/d_ifacea.h +++ b/include/d_ifacea.h @@ -50,19 +50,15 @@ // particle_t structure // !!! if this is changed, it must be changed in d_iface.h too !!! -// driver-usable fields -#define pt_org 0 -#define pt_color 12 -#define pt_alpha 16 -#define pt_tex 20 -#define pt_scale 24 -// drivers never touch the following fields -#define pt_vel 28 -#define pt_type 40 -#define pt_die 44 -#define pt_ramp 48 -#define pt_next 52 -#define pt_size 56 +#define pt_pos 0 +#define pt_vel 16 +#define pt_color 32 +#define pt_alpha 44 +#define pt_tex 48 +#define pt_ramp 52 +#define pt_scale 56 +#define pt_live 60 +#define pt_size 64 #define PARTICLE_Z_CLIP 8.0 diff --git a/include/r_dynamic.h b/include/r_dynamic.h index 8968cfa1c..1027879bc 100644 --- a/include/r_dynamic.h +++ b/include/r_dynamic.h @@ -61,9 +61,8 @@ void R_InitSprites (void); extern unsigned int r_maxparticles; extern unsigned int numparticles; -extern struct particle_s *active_particles; -extern struct particle_s *free_particles; extern struct particle_s *particles; -extern struct particle_s **freeparticles; +extern struct partparm_s *partparams; +extern const int **partramps; #endif // _R_DYNAMIC_H diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index c4e66c7ff..faa451839 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -118,35 +118,37 @@ CL_ModelEffects (entity_t *ent, int num, int glow_color, double time) { dlight_t *dl; model_t *model = ent->renderer.model; + vec4f_t old_origin = ent->old_origin; + vec4f_t ent_origin = Transform_GetWorldPosition (ent->transform); // add automatic particle trails if (model->flags & EF_ROCKET) { dl = r_funcs->R_AllocDlight (num); if (dl) { - VectorCopy (Transform_GetWorldPosition (ent->transform), - dl->origin); + VectorCopy (ent_origin, dl->origin); dl->radius = 200.0; dl->die = time + 0.1; //FIXME VectorCopy (r_firecolor->vec, dl->color); VectorSet (0.9, 0.7, 0.0, dl->color); dl->color[3] = 0.7; } - r_funcs->particles->R_RocketTrail (ent); + r_funcs->particles->R_RocketTrail (old_origin, ent_origin); } else if (model->flags & EF_GRENADE) - r_funcs->particles->R_GrenadeTrail (ent); + r_funcs->particles->R_GrenadeTrail (old_origin, ent_origin); else if (model->flags & EF_GIB) - r_funcs->particles->R_BloodTrail (ent); + r_funcs->particles->R_BloodTrail (old_origin, ent_origin); else if (model->flags & EF_ZOMGIB) - r_funcs->particles->R_SlightBloodTrail (ent); + r_funcs->particles->R_SlightBloodTrail (old_origin, ent_origin); else if (model->flags & EF_TRACER) - r_funcs->particles->R_WizTrail (ent); + r_funcs->particles->R_WizTrail (old_origin, ent_origin); else if (model->flags & EF_TRACER2) - r_funcs->particles->R_FlameTrail (ent); + r_funcs->particles->R_FlameTrail (old_origin, ent_origin); else if (model->flags & EF_TRACER3) - r_funcs->particles->R_VoorTrail (ent); + r_funcs->particles->R_VoorTrail (old_origin, ent_origin); else if (model->flags & EF_GLOWTRAIL) if (r_funcs->particles->R_GlowTrail) - r_funcs->particles->R_GlowTrail (ent, glow_color); + r_funcs->particles->R_GlowTrail (old_origin, ent_origin, + glow_color); } void @@ -171,10 +173,10 @@ CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num, void CL_EntityEffects (int num, entity_t *ent, entity_state_t *state, double time) { + vec4f_t position = Transform_GetWorldPosition (ent->transform); if (state->effects & EF_BRIGHTFIELD) - r_funcs->particles->R_EntityParticles (ent); + r_funcs->particles->R_EntityParticles (position); if (state->effects & EF_MUZZLEFLASH) { - vec4f_t position = Transform_GetWorldPosition (ent->transform); vec4f_t fv = Transform_Forward (ent->transform); CL_MuzzleFlash (position, fv, 16, num, time); } diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 2fe2255c9..412946f65 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -323,7 +323,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, explosion_t *ex; int colorStart, colorLength; quat_t color; - vec3_t position; + vec4f_t position = {0, 0, 0, 1}; int count; const char *name; @@ -336,11 +336,11 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, break; case TE_Blood: count = MSG_ReadByte (net_message) * 20; - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_BloodPuffEffect (position, count); break; case TE_Explosion: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); // particles r_funcs->particles->R_ParticleExplosion (position); @@ -357,7 +357,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } // sound - S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); // sprite to = new_tent_object (); @@ -376,10 +376,10 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, (vec4f_t) {VectorExpand (position), 1}); break; case TE_Explosion2: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); colorStart = MSG_ReadByte (net_message); colorLength = MSG_ReadByte (net_message); - S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); r_funcs->particles->R_ParticleExplosion2 (position, colorStart, colorLength); dl = r_funcs->R_AllocDlight (0); @@ -395,11 +395,11 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, dl->color[3] = 0.7; break; case TE_Explosion3: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); MSG_ReadCoordV (net_message, color); // OUCH! color[3] = 0.7; r_funcs->particles->R_ParticleExplosion (position); - S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); dl = r_funcs->R_AllocDlight (0); if (dl) { VectorCopy (position, dl->origin); @@ -410,21 +410,21 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } break; case TE_Gunshot1: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_GunshotEffect (position, 20); break; case TE_Gunshot2: count = MSG_ReadByte (net_message) * 20; - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_GunshotEffect (position, count); break; case TE_KnightSpike: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_KnightSpikeEffect (position); - S_StartSound (-1, 0, cl_sfx_knighthit, position, 1, 1); + S_StartSound (-1, 0, cl_sfx_knighthit, &position[0], 1, 1); break; case TE_LavaSplash: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_LavaSplash (position); break; case TE_Lightning1: @@ -441,7 +441,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, CL_ParseBeam (net_message, Mod_ForName (name, true), time, ctx); break; case TE_LightningBlood: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); // light dl = r_funcs->R_AllocDlight (0); @@ -456,7 +456,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, r_funcs->particles->R_LightningBloodEffect (position); break; case TE_Spike: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_SpikeEffect (position); { int i; @@ -468,11 +468,11 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } else { sound = cl_sfx_tink1; } - S_StartSound (-1, 0, sound, position, 1, 1); + S_StartSound (-1, 0, sound, &position[0], 1, 1); } break; case TE_SuperSpike: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_SuperSpikeEffect (position); { int i; @@ -484,23 +484,23 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } else { sound = cl_sfx_tink1; } - S_StartSound (-1, 0, sound, position, 1, 1); + S_StartSound (-1, 0, sound, &position[0], 1, 1); } break; case TE_TarExplosion: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_BlobExplosion (position); - S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); break; case TE_Teleport: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_TeleportSplash (position); break; case TE_WizSpike: - MSG_ReadCoordV (net_message, position); + MSG_ReadCoordV (net_message, &position[0]); r_funcs->particles->R_WizSpikeEffect (position); - S_StartSound (-1, 0, cl_sfx_wizhit, position, 1, 1); + S_StartSound (-1, 0, cl_sfx_wizhit, &position[0], 1, 1); break; } } @@ -650,9 +650,9 @@ void CL_ParseParticleEffect (qmsg_t *net_message) { int i, count, color; - vec3_t org, dir; + vec4f_t org = {0, 0, 0, 1}, dir = {}; - MSG_ReadCoordV (net_message, org); + MSG_ReadCoordV (net_message, &org[0]); for (i = 0; i < 3; i++) dir[i] = ((signed char) MSG_ReadByte (net_message)) * (15.0 / 16.0); count = MSG_ReadByte (net_message); diff --git a/libs/client/locs.c b/libs/client/locs.c index 2ab477921..4998694bf 100644 --- a/libs/client/locs.c +++ b/libs/client/locs.c @@ -291,6 +291,7 @@ locs_draw (vec4f_t simorg) dlight_t *dl; location_t *nearloc; vec4f_t trueloc; + vec4f_t zero = {}; int i; nearloc = locs_find (simorg); @@ -307,12 +308,12 @@ locs_draw (vec4f_t simorg) } trueloc = nearloc->loc; r_funcs->particles->R_Particle_New (pt_smokecloud, part_tex_smoke, - &trueloc[0], 2.0,//FIXME - vec3_origin, r_data->realtime + 9.0, 254, + trueloc, 2.0, + zero, r_data->realtime + 9.0, 254, 0.25 + qfrandom (0.125), 0.0); for (i = 0; i < 15; i++) r_funcs->particles->R_Particle_NewRandom (pt_fallfade, - part_tex_dot, &trueloc[0], 12,//FIXME + part_tex_dot, trueloc, 12, 0.7, 96, r_data->realtime + 5.0, 104 + (rand () & 7), 1.0, 0.0); } diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index b82785660..988c91432 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -61,10 +61,6 @@ #include "r_internal.h" #include "varrays.h" -static int ramp1[8] = { 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61 }; -//static int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 }; -static int ramp3[8] = { 0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; - static int partUseVA; static int pVAsize; static int *pVAindices; @@ -73,31 +69,30 @@ static varray_t2f_c4ub_v3f_t *particleVertexArray; static mtstate_t mt; // private PRNG state inline static void -particle_new (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, float ramp) +particle_new (ptype_t type, int texnum, vec4f_t pos, float scale, + vec4f_t vel, float live, int color, float alpha, float ramp) { - particle_t *part; + if (numparticles >= r_maxparticles) + return; + particle_t *p = &particles[numparticles]; + partparm_t *parm = &partparams[numparticles]; + const int **rampptr = &partramps[numparticles]; + numparticles += 1; -/* - // Uncomment this for particle debugging! - if (numparticles >= r_maxparticles) { - Sys_Error ("FAILED PARTICLE ALLOC!"); - return NULL; + p->pos = pos; + p->vel = vel; + p->icolor = color; + p->alpha = alpha; + p->tex = texnum; + p->ramp = ramp; + p->scale = scale; + p->live = live; + + *parm = R_ParticlePhysics (type); + *rampptr = R_ParticleRamp (type); + if (*rampptr) { + p->icolor = (*rampptr) [(int) p->ramp]; } -*/ - - part = &particles[numparticles++]; - - VectorCopy (org, part->org); - part->color = color; - part->tex = texnum; - part->scale = scale; - part->alpha = alpha; - VectorCopy (vel, part->vel); - part->type = type; - part->die = die; - part->ramp = ramp; - part->phys = R_ParticlePhysics (type); } /* @@ -107,30 +102,32 @@ particle_new (ptype_t type, int texnum, const vec3_t org, float scale, going to bother using this function. */ inline static void -particle_new_random (ptype_t type, int texnum, const vec3_t org, int org_fuzz, - float scale, int vel_fuzz, float die, int color, +particle_new_random (ptype_t type, int texnum, vec4f_t org, int org_fuzz, + float scale, int vel_fuzz, float live, int color, float alpha, float ramp) { float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; int rnd; - vec3_t porg, pvel; + vec4f_t porg, pvel; rnd = mtwist_rand (&mt); porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; porg[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; + porg[3] = 1; rnd = mtwist_rand (&mt); pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; pvel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; + pvel[3] = 0; - particle_new (type, texnum, porg, scale, pvel, die, color, alpha, ramp); + particle_new (type, texnum, porg, scale, pvel, live, color, alpha, ramp); } /* inline static void -particle_new_veryrandom (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, float die, +particle_new_veryrandom (ptype_t type, int texnum, vec4f_t org, + int org_fuzz, float scale, int vel_fuzz, float live, int color, float alpha, float ramp) { vec3_t porg, pvel; @@ -141,10 +138,39 @@ particle_new_veryrandom (ptype_t type, int texnum, const vec3_t org, pvel[0] = qfrandom (vel_fuzz * 2) - vel_fuzz; pvel[1] = qfrandom (vel_fuzz * 2) - vel_fuzz; pvel[2] = qfrandom (vel_fuzz * 2) - vel_fuzz; - particle_new (type, texnum, porg, scale, pvel, die, color, alpha, ramp); + particle_new (type, texnum, porg, scale, pvel, live, color, alpha, ramp); } */ +static vec4f_t +roffs (int mod) +{ + vec4f_t offs = { + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + 0 + }; + return offs; +} + +static vec4f_t +tracer_vel (int tracercount, vec4f_t vec) +{ + if (tracercount & 1) { + return (vec4f_t) { vec[1], -vec[0], 0, 0 }; + } else { + return (vec4f_t) { -vec[1], vec[0], 0, 0 }; + } +} + +static void +add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, + float ramp) +{ + particle_new (type, part_tex_dot, pos, 1, vel, live, color, 1, ramp); +} + void gl_R_ClearParticles (void) { @@ -199,13 +225,13 @@ gl_R_InitParticles (void) } } + void gl_R_ReadPointFile_f (void) { const char *name; char *mapname; - int c, r; - vec3_t org; + int c; QFile *f; mapname = strdup (r_worldentity.renderer.model->path); @@ -224,11 +250,13 @@ gl_R_ReadPointFile_f (void) Sys_MaskPrintf (SYS_dev, "Reading %s...\n", name); c = 0; + vec4f_t zero = {}; for (;;) { char buf[64]; + vec4f_t org = { 0, 0, 0, 1 }; Qgets (f, buf, sizeof (buf)); - r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); + int r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); if (r != 3) break; c++; @@ -237,7 +265,7 @@ gl_R_ReadPointFile_f (void) Sys_MaskPrintf (SYS_dev, "Not enough free particles\n"); break; } else { - particle_new (pt_static, part_tex_dot, org, 1.5, vec3_origin, + particle_new (pt_static, part_tex_dot, org, 1.5, zero, 99999, (-c) & 15, 1.0, 0.0); } } @@ -246,18 +274,18 @@ gl_R_ReadPointFile_f (void) } static void -R_ParticleExplosion_QF (const vec3_t org) +R_ParticleExplosion_QF (vec4f_t org) { // R_NewExplosion (org); if (numparticles >= r_maxparticles) return; particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, - vr_data.realtime + 5.0, (mtwist_rand (&mt) & 7) + 8, + 5.0, (mtwist_rand (&mt) & 7) + 8, 0.5 + qfrandom (0.25), 0.0); } static void -R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) +R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) { unsigned int i, j = 512; @@ -268,13 +296,13 @@ R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) for (i = 0; i < j; i++) { particle_new_random (pt_blob, part_tex_dot, org, 16, 2, 256, - vr_data.realtime + 0.3, - colorStart + (i % colorLength), 1.0, 0.0); + 0.3, + colorStart + (i % colorLength), 1.0, 0.0); } } static void -R_BlobExplosion_QF (const vec3_t org) +R_BlobExplosion_QF (vec4f_t org) { unsigned int i; unsigned int j = 1024; @@ -286,28 +314,28 @@ R_BlobExplosion_QF (const vec3_t org) for (i = 0; i < j >> 1; i++) { particle_new_random (pt_blob, part_tex_dot, org, 12, 2, 256, - vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, 66 + i % 6, 1.0, 0.0); } for (i = 0; i < j / 2; i++) { particle_new_random (pt_blob2, part_tex_dot, org, 12, 2, 256, - vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, 150 + i % 6, 1.0, 0.0); } } static inline void -R_RunSparkEffect_QF (const vec3_t org, int count, int ofuzz) +R_RunSparkEffect_QF (vec4f_t org, int count, int ofuzz) { - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; + + vec4f_t zero = {}; particle_new (pt_smokecloud, part_tex_smoke, org, ofuzz * 0.08, - vec3_origin, vr_data.realtime + 9, 12 + (mtwist_rand (&mt) & 3), + zero, 9, 12 + (mtwist_rand (&mt) & 3), 0.25 + qfrandom (0.125), 0.0); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - if (count) { + if (count > 0) { int orgfuzz = ofuzz * 3 / 4; if (orgfuzz < 1) orgfuzz = 1; @@ -316,30 +344,30 @@ R_RunSparkEffect_QF (const vec3_t org, int count, int ofuzz) int color = mtwist_rand (&mt) & 7; particle_new_random (pt_fallfadespark, part_tex_dot, org, orgfuzz, - 0.7, 96, vr_data.realtime + 5.0, ramp1[color], - 1.0, color); + 0.7, 96, 5.0, 0, 1.0, color); } } } static inline void -R_BloodPuff_QF (const vec3_t org, int count) +R_BloodPuff_QF (vec4f_t org, int count) { - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - particle_new (pt_bloodcloud, part_tex_smoke, org, count / 5, vec3_origin, - vr_data.realtime + 99.0, 70 + (mtwist_rand (&mt) & 3), 0.5, 0.0); + vec4f_t zero = {}; + particle_new (pt_bloodcloud, part_tex_smoke, org, count / 5, zero, + 99.0, 70 + (mtwist_rand (&mt) & 3), 0.5, 0.0); } static void -R_BloodPuffEffect_QF (const vec3_t org, int count) +R_BloodPuffEffect_QF (vec4f_t org, int count) { R_BloodPuff_QF (org, count); } static void -R_GunshotEffect_QF (const vec3_t org, int count) +R_GunshotEffect_QF (vec4f_t org, int count) { int scale = 16; @@ -348,170 +376,133 @@ R_GunshotEffect_QF (const vec3_t org, int count) } static void -R_LightningBloodEffect_QF (const vec3_t org) +R_LightningBloodEffect_QF (vec4f_t org) { - int count = 7; + if (!r_particles->int_val) + return; R_BloodPuff_QF (org, 50); - if (numparticles >= r_maxparticles) - return; - particle_new (pt_smokecloud, part_tex_smoke, org, 3.0, vec3_origin, - vr_data.realtime + 9.0, 12 + (mtwist_rand (&mt) & 3), + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, 3.0, zero, + 9.0, 12 + (mtwist_rand (&mt) & 3), 0.25 + qfrandom (0.125), 0.0); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - while (count--) + for (int count = 7; count-- > 0; ) { particle_new_random (pt_fallfade, part_tex_spark, org, 12, 2.0, 128, - vr_data.realtime + 5.0, 244 + (count % 3), 1.0, - 0.0); + 5.0, 244 + (count % 3), 1.0, 0.0); + } } static void -R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, +R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, int count) { - float scale; - int i; - vec3_t porg; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - scale = pow (count, 0.23); // calculate scale before clipping to part. max + float scale = pow (count, 0.23); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - - for (i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { int rnd = mtwist_rand (&mt); - porg[0] = org[0] + scale * (((rnd >> 3) & 15) - 7.5); - porg[1] = org[1] + scale * (((rnd >> 7) & 15) - 7.5); - porg[2] = org[2] + scale * (((rnd >> 11) & 15) - 7.5); // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, porg, 1.5, dir, - vr_data.realtime + 0.1 * (i % 5), + particle_new (pt_grav, part_tex_dot, org + scale * roffs (16), 1.5, + dir, 0.1 * (i % 5), (color & ~7) + (rnd & 7), 1.0, 0.0); } } static void -R_SpikeEffect_QF (const vec3_t org) +R_SpikeEffect_QF (vec4f_t org) { R_RunSparkEffect_QF (org, 5, 8); } static void -R_SuperSpikeEffect_QF (const vec3_t org) +R_SuperSpikeEffect_QF (vec4f_t org) { R_RunSparkEffect_QF (org, 10, 8); } static void -R_KnightSpikeEffect_QF (const vec3_t org) +R_KnightSpikeEffect_QF (vec4f_t org) { - unsigned int count = 10; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 1.0, vec3_origin, - vr_data.realtime + 9.0, 234, 0.25 + qfrandom (0.125), 0.0); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - while (count--) + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, 1.0, zero, + 9.0, 234, 0.25 + qfrandom (0.125), 0.0); + + for (int count = 10; count-- > 0; ) { particle_new_random (pt_fallfade, part_tex_dot, org, 6, 0.7, 96, - vr_data.realtime + 5.0, 234, 1.0, 0.0); + 5.0, 234, 1.0, 0.0); + } } static void -R_WizSpikeEffect_QF (const vec3_t org) +R_WizSpikeEffect_QF (vec4f_t org) { - unsigned int count = 15; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 2.0, vec3_origin, - vr_data.realtime + 9.0, 63, 0.25 + qfrandom (0.125), 0.0); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - while (count--) + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, 2.0, zero, + 9.0, 63, 0.25 + qfrandom (0.125), 0.0); + + for (int count = 15; count-- > 0; ) { particle_new_random (pt_fallfade, part_tex_dot, org, 12, 0.7, 96, - vr_data.realtime + 5.0, 63, 1.0, 0.0); + 5.0, 63, 1.0, 0.0); + } } static void -R_LavaSplash_QF (const vec3_t org) +R_LavaSplash_QF (vec4f_t org) { - float vel; - int rnd, i, j; - int k = 256; - vec3_t dir, porg, pvel; - - if (numparticles + k >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + k >= r_maxparticles) { -// k = r_maxparticles - numparticles; -// } - dir[2] = 256; - for (i = -128; i < 128; i += 16) { - for (j = -128; j < 128; j += 16) { - rnd = mtwist_rand (&mt); - dir[0] = j + (rnd & 7); - dir[1] = i + ((rnd >> 6) & 7); - - porg[0] = org[0] + dir[0]; - porg[1] = org[1] + dir[1]; - porg[2] = org[2] + ((rnd >> 9) & 63); - - VectorNormalize (dir); - rnd = mtwist_rand (&mt); - vel = 50.0 + 0.5 * (float) (rnd & 127); - VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 3, pvel, - vr_data.realtime + 2.0 + ((rnd >> 7) & 31) * 0.02, + for (int i = -16; i < 16; i++) { + for (int j = -16; j < 16; j++) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50.0 + 0.5 * (mtwist_rand (&mt) & 127); + vec4f_t dir = { + j * 8 + (rnd & 7), + i * 8 + ((rnd >> 6) & 7), + 256, + 0 + }; + vec4f_t offs = { dir[0], dir[1], ((rnd >> 9) & 63), 0 }; + dir = normalf (dir); + particle_new (pt_grav, part_tex_dot, org + offs, 3, vel * dir, + 2.0 + ((rnd >> 7) & 31) * 0.02, 224 + ((rnd >> 12) & 7), 0.75, 0.0); } } } static void -R_TeleportSplash_QF (const vec3_t org) +R_TeleportSplash_QF (vec4f_t org) { - float vel; - int rnd, i, j, k; - int l = 896; - vec3_t dir, pdir, porg, pvel; - - if (numparticles + l >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + l >= r_maxparticles) { -// l = r_maxparticles - numparticles; -// } - for (k = -24; k < 32; k += 4) { - dir[2] = k * 8; - for (i = -16; i < 16; i += 4) { - dir[1] = i * 8; - for (j = -16; j < 16; j += 4) { - dir[0] = j * 8; - - VectorCopy (dir, pdir); - VectorNormalize (pdir); - - rnd = mtwist_rand (&mt); - porg[0] = org[0] + i + (rnd & 3); - porg[1] = org[1] + j + ((rnd >> 2) & 3); - porg[2] = org[2] + k + ((rnd >> 4) & 3); - - vel = 50 + ((rnd >> 6) & 63); - VectorScale (pdir, vel, pvel); - particle_new (pt_grav, part_tex_spark, porg, 0.6, pvel, - (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 15) * 0.01), + for (int k = -24; k < 32; k += 4) { + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 6) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (rnd & 3), + j + ((rnd >> 2) & 3), + k + ((rnd >> 4) & 3), + 0 + }; + particle_new (pt_grav, part_tex_spark, org + offs, 0.6, + vel * dir, + (0.2 + (mtwist_rand (&mt) & 15) * 0.01), (7 + ((rnd >> 12) & 7)), 1.0, 0.0); } } @@ -519,320 +510,272 @@ R_TeleportSplash_QF (const vec3_t org) } static void -R_RocketTrail_QF (const entity_t *ent) +R_RocketTrail_QF (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - vec3_t old_origin, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 1.5 + qfrandom (1.5); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + float pscale = 1.5 + qfrandom (1.5); while (len < maxlen) { - pscalenext = 1.5 + qfrandom (1.5); - dist = (pscale + pscalenext) * 3.0; - percent = len * origlen; + float pscalenext = 1.5 + qfrandom (1.5); + float dist = (pscale + pscalenext) * 3.0; + float percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, - pscale + percent * 4.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, 12 + (mtwist_rand (&mt) & 3), 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorMultAdd (old_origin, len, vec, old_origin); + pos += step; pscale = pscalenext; } } static void -R_GrenadeTrail_QF (const entity_t *ent) +R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - vec3_t old_origin, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 6.0 + qfrandom (7.0); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + float pscale = 6.0 + qfrandom (7.0); while (len < maxlen) { - pscalenext = 6.0 + qfrandom (7.0); - dist = (pscale + pscalenext) * 2.0; - percent = len * origlen; + float pscalenext = 6.0 + qfrandom (7.0); + float dist = (pscale + pscalenext) * 2.0; + float percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, - pscale + percent * 4.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, 1 + (mtwist_rand (&mt) & 3), 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorMultAdd (old_origin, len, vec, old_origin); + pos += step; pscale = pscalenext; } } static void -R_BloodTrail_QF (const entity_t *ent) +R_BloodTrail_QF (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - int j; - vec3_t old_origin, porg, pvel, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 5.0 + qfrandom (10.0); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t pos = start; + float pscale = 5.0 + qfrandom (10.0); while (len < maxlen) { - pscalenext = 5.0 + qfrandom (10.0); - dist = (pscale + pscalenext) * 1.5; + float pscalenext = 5.0 + qfrandom (10.0); + float dist = (pscale + pscalenext) * 1.5; + float percent = len * origlen; + vec4f_t vel = roffs (24); + vel[2] -= percent * 40; - for (j = 0; j < 3; j++) { - pvel[j] = qfrandom (24.0) - 12.0; - porg[j] = old_origin[j] + qfrandom (3.0) - 1.5; - } - - percent = len * origlen; - pvel[2] -= percent * 40.0; - - particle_new (pt_grav, part_tex_smoke, porg, pscale, pvel, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, + 2.0 - percent * 2.0, 68 + (mtwist_rand (&mt) & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorMultAdd (old_origin, len, vec, old_origin); + pos += step; pscale = pscalenext; } } static void -R_SlightBloodTrail_QF (const entity_t *ent) +R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - int j; - vec3_t old_origin, porg, pvel, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 1.5 + qfrandom (7.5); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t pos = start; + float pscale = 1.5 + qfrandom (7.5); while (len < maxlen) { - pscalenext = 1.5 + qfrandom (7.5); - dist = (pscale + pscalenext) * 1.5; + float pscalenext = 1.5 + qfrandom (7.5); + float dist = (pscale + pscalenext) * 1.5; + float percent = len * origlen; + vec4f_t vel = roffs (12); + vel[2] -= percent * 40; - for (j = 0; j < 3; j++) { - pvel[j] = (qfrandom (12.0) - 6.0); - porg[j] = old_origin[j] + qfrandom (3.0) - 1.5; - } - - percent = len * origlen; - pvel[2] -= percent * 40; - - particle_new (pt_grav, part_tex_smoke, porg, pscale, pvel, - vr_data.realtime + 1.5 - percent * 1.5, + particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, + 1.5 - percent * 1.5, 68 + (mtwist_rand (&mt) & 3), 0.75, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorMultAdd (old_origin, len, vec, old_origin); + pos += step; pscale = pscalenext; } } static void -R_WizTrail_QF (const entity_t *ent) +R_WizTrail_QF (vec4f_t start, vec4f_t end) { - float maxlen, origlen, percent; - float dist = 3.0, len = 0.0; - static int tracercount; - vec3_t old_origin, pvel, subtract, vec; - vec3_t org; + float dist = 3.0; if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t pos = start; while (len < maxlen) { - percent = len * origlen; + static int tracercount; + float percent = len * origlen; - tracercount++; - if (tracercount & 1) { - pvel[0] = 30.0 * vec[1]; - pvel[1] = 30.0 * -vec[0]; - } else { - pvel[0] = 30.0 * -vec[1]; - pvel[1] = 30.0 * vec[0]; - } - pvel[2] = 0.0; - - particle_new (pt_flame, part_tex_smoke, old_origin, - 2.0 + qfrandom (1.0) - percent * 2.0, pvel, - vr_data.realtime + 0.5 - percent * 0.5, + particle_new (pt_flame, part_tex_smoke, pos, + 2.0 + qfrandom (1.0) - percent * 2.0, + 30 * tracer_vel (tracercount++, vec), + 0.5 - percent * 0.5, 52 + (mtwist_rand (&mt) & 4), 1.0 - percent * 0.125, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += step; } } static void -R_FlameTrail_QF (const entity_t *ent) +R_FlameTrail_QF (vec4f_t start, vec4f_t end) { - float maxlen, origlen, percent; - float dist = 3.0, len = 0.0; - static int tracercount; - vec3_t old_origin, pvel, subtract, vec; - vec3_t org; + float dist = 3.0; if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t pos = start; while (len < maxlen) { - percent = len * origlen; + static int tracercount; + float percent = len * origlen; - tracercount++; - if (tracercount & 1) { - pvel[0] = 30.0 * vec[1]; - pvel[1] = 30.0 * -vec[0]; - } else { - pvel[0] = 30.0 * -vec[1]; - pvel[1] = 30.0 * vec[0]; - } - pvel[2] = 0.0; - - particle_new (pt_flame, part_tex_smoke, old_origin, - 2.0 + qfrandom (1.0) - percent * 2.0, pvel, - vr_data.realtime + 0.5 - percent * 0.5, 234, + particle_new (pt_flame, part_tex_smoke, pos, + 2.0 + qfrandom (1.0) - percent * 2.0, + 30 * tracer_vel (tracercount++, vec), + 0.5 - percent * 0.5, 234, 1.0 - percent * 0.125, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += step; } } static void -R_VoorTrail_QF (const entity_t *ent) +R_VoorTrail_QF (vec4f_t start, vec4f_t end) { - float maxlen, origlen, percent; - float dist = 3.0, len = 0.0; - int j; - vec3_t subtract, old_origin, porg, vec; - vec3_t org; + float dist = 3.0; if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; while (len < maxlen) { - percent = len * origlen; + float percent = len * origlen; - for (j = 0; j < 3; j++) - porg[j] = old_origin[j] + qfrandom (16.0) - 8.0; - - particle_new (pt_static, part_tex_dot, porg, 1.0 + qfrandom (1.0), - vec3_origin, vr_data.realtime + 0.3 - percent * 0.3, + particle_new (pt_static, part_tex_dot, pos + roffs (16), + 1.0 + qfrandom (1.0), + zero, 0.3 - percent * 0.3, 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += step; } } static void -R_GlowTrail_QF (const entity_t *ent, int glow_color) +R_GlowTrail_QF (vec4f_t start, vec4f_t end, int glow_color) { - float maxlen, origlen, percent; - float dist = 3.0, len = 0.0; - int rnd; - vec3_t old_origin, org, subtract, vec; + float dist = 3.0; if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - VectorScale (vec, (maxlen - dist), subtract); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; while (len < maxlen) { - percent = len * origlen; + float percent = len * origlen; - rnd = mtwist_rand (&mt); - org[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - org[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - - particle_new (pt_smoke, part_tex_dot, org, 1.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 0.2, - glow_color, 1.0, 0.0); + particle_new (pt_smoke, part_tex_dot, pos + roffs (5), 1.0, zero, + 2.0 - percent * 0.2, glow_color, 1.0, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += step; } } static void -R_ParticleExplosion_EE (const vec3_t org) +R_ParticleExplosion_EE (vec4f_t org) { /* R_NewExplosion (org); @@ -840,41 +783,31 @@ R_ParticleExplosion_EE (const vec3_t org) if (numparticles >= r_maxparticles) return; particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, - vr_data.realtime + 5.0, mtwist_rand (&mt) & 255, + 5.0, mtwist_rand (&mt) & 255, 0.5 + qfrandom (0.25), 0.0); } static void -R_TeleportSplash_EE (const vec3_t org) +R_TeleportSplash_EE (vec4f_t org) { - float vel; - int rnd, i, j, k; - int l = 896; - vec3_t dir, porg, pvel; - - if (numparticles + l >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + l >= r_maxparticles) { -// l = r_maxparticles - numparticles; -// } - for (k = -24; k < 32; k += 4) { - dir[2] = k * 8; - for (i = -16; i < 16; i += 4) { - dir[1] = i * 8; - for (j = -16; j < 16; j += 4) { - dir[0] = j * 8; - - rnd = mtwist_rand (&mt); - porg[0] = org[0] + i + (rnd & 3); - porg[1] = org[1] + j + ((rnd >> 2) & 3); - porg[2] = org[2] + k + ((rnd >> 4) & 3); - - VectorNormalize (dir); - vel = 50 + ((rnd >> 6) & 63); - VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_spark, porg, 0.6, pvel, - (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 15) * 0.01), + for (int k = -24; k < 32; k += 4) { + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 6) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (rnd & 3), + j + ((rnd >> 2) & 3), + k + ((rnd >> 4) & 3), + 0 + }; + particle_new (pt_grav, part_tex_spark, org + offs, 0.6, + vel * dir, + (0.2 + (mtwist_rand (&mt) & 15) * 0.01), qfrandom (1.0), 1.0, 0.0); } } @@ -882,347 +815,274 @@ R_TeleportSplash_EE (const vec3_t org) } static void -R_RocketTrail_EE (const entity_t *ent) +R_RocketTrail_EE (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - vec3_t old_origin, subtract, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 1.5 + qfrandom (1.5); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + float pscale = 1.5 + qfrandom (1.5); + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; while (len < maxlen) { - pscalenext = 1.5 + qfrandom (1.5); - dist = (pscale + pscalenext) * 3.0; - percent = len * origlen; + float pscalenext = 1.5 + qfrandom (1.5); + float dist = (pscale + pscalenext) * 3.0; + float percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, - pscale + percent * 4.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, mtwist_rand (&mt) & 255, 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorScale (vec, len, subtract); - VectorAdd (old_origin, subtract, old_origin); + pos += len * vec; pscale = pscalenext; } } static void -R_GrenadeTrail_EE (const entity_t *ent) +R_GrenadeTrail_EE (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - vec3_t old_origin, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, ent->old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 6.0 + qfrandom (7.0); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + float pscale = 6.0 + qfrandom (7.0); + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; while (len < maxlen) { - pscalenext = 6.0 + qfrandom (7.0); - dist = (pscale + pscalenext) * 2.0; - percent = len * origlen; + float pscalenext = 6.0 + qfrandom (7.0); + float dist = (pscale + pscalenext) * 2.0; + float percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, - pscale + percent * 4.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, mtwist_rand (&mt) & 255, 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; - VectorScale (vec, len, subtract); - VectorAdd (old_origin, subtract, old_origin); + pos += len * vec; pscale = pscalenext; } } static void -R_ParticleExplosion_ID (const vec3_t org) +R_ParticleExplosion_ID (vec4f_t org) { - unsigned int i; - unsigned int j = 1024; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_explode, part_tex_dot, org, 16, 1.0, 256, - vr_data.realtime + 5.0, ramp1[0], 1.0, i & 3); - } - for (i = 0; i < j / 2; i++) { - particle_new_random (pt_explode2, part_tex_dot, org, 16, 1.0, 256, - vr_data.realtime + 5.0, ramp1[0], 1.0, i & 3); + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_explode2 : pt_explode; + add_particle (type, org + roffs (32), roffs (512), 5, + 0, mtwist_rand (&mt) & 3); } } static void -R_BlobExplosion_ID (const vec3_t org) +R_BlobExplosion_ID (vec4f_t org) { - unsigned int i; - unsigned int j = 1024; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 12, 1.0, 256, - vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 8) * 0.05, - 66 + i % 6, 1.0, 0.0); - } - for (i = 0; i < j / 2; i++) { - particle_new_random (pt_blob2, part_tex_dot, org, 12, 1.0, 256, - vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 8) * 0.05, - 150 + i % 6, 1.0, 0.0); + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_blob : pt_blob2; + int color = i & 1 ? 66 : 150; + add_particle (type, org + roffs (32), roffs (512), + color + mtwist_rand (&mt) % 6, + (color & ~7) + (mtwist_rand (&mt) & 7), 0); } } static inline void // FIXME: inline? -R_RunParticleEffect_ID (const vec3_t org, const vec3_t dir, int color, +R_RunParticleEffect_ID (vec4f_t org, vec4f_t dir, int color, int count) { - float scale; - int i; - vec3_t porg; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - if (count > 130) // calculate scale before clipping to particle max - scale = 3.0; - else if (count > 20) - scale = 2.0; - else - scale = 1.0; - - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - - for (i = 0; i < count; i++) { - int rnd = mtwist_rand (&mt); - - porg[0] = org[0] + scale * (((rnd >> 3) & 15) - 8); - porg[1] = org[1] + scale * (((rnd >> 7) & 15) - 8); - porg[2] = org[2] + scale * (((rnd >> 11) & 15) - 8); - - // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, porg, 1.0, dir, - vr_data.realtime + 0.1 * (i % 5), - (color & ~7) + (rnd & 7), 1.0, 0.0); + for (int i = 0; i < count; i++) { + add_particle (pt_slowgrav, org + roffs (16), + dir/* + roffs (300)*/, + 0.1 * (mtwist_rand (&mt) % 5), + (color & ~7) + (mtwist_rand (&mt) & 7), 0); } } static void -R_BloodPuffEffect_ID (const vec3_t org, int count) +R_BloodPuffEffect_ID (vec4f_t org, int count) { - R_RunParticleEffect_ID (org, vec3_origin, 73, count); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 73, count); } static void -R_GunshotEffect_ID (const vec3_t org, int count) +R_GunshotEffect_ID (vec4f_t org, int count) { - R_RunParticleEffect_ID (org, vec3_origin, 0, count); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 0, count); } static void -R_LightningBloodEffect_ID (const vec3_t org) +R_LightningBloodEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 225, 50); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 225, 50); } static void -R_SpikeEffect_ID (const vec3_t org) +R_SpikeEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 0, 10); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 0, 10); } static void -R_SuperSpikeEffect_ID (const vec3_t org) +R_SuperSpikeEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 0, 20); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 0, 20); } static void -R_KnightSpikeEffect_ID (const vec3_t org) +R_KnightSpikeEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 226, 20); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 226, 20); } static void -R_WizSpikeEffect_ID (const vec3_t org) +R_WizSpikeEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 20, 30); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 20, 30); } static void -R_LavaSplash_ID (const vec3_t org) +R_LavaSplash_ID (vec4f_t org) { - float vel; - int rnd, i, j; - int k = 256; - vec3_t dir, porg, pvel; - - if (numparticles + k >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + k >= r_maxparticles) { -// k = r_maxparticles - numparticles; -// } - dir[2] = 256; - for (i = -128; i < 128; i += 16) { - for (j = -128; j < 128; j += 16) { - rnd = mtwist_rand (&mt); - dir[0] = j + (rnd & 7); - dir[1] = i + ((rnd >> 6) & 7); - - porg[0] = org[0] + dir[0]; - porg[1] = org[1] + dir[1]; - porg[2] = org[2] + ((rnd >> 9) & 63); - - VectorNormalize (dir); - rnd = mtwist_rand (&mt); - vel = 50 + (rnd & 63); - VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 1.0, pvel, - vr_data.realtime + 2 + ((rnd >> 7) & 31) * 0.02, - 224 + ((rnd >> 12) & 7), 1.0, 0.0); - } - } -} - -static void -R_TeleportSplash_ID (const vec3_t org) -{ - float vel; - int rnd, i, j, k; - int l = 896; - vec3_t dir, pdir, porg, pvel; - - if (numparticles + l >= r_maxparticles) { - return; - } // else if (numparticles + l >= r_maxparticles) { -// l = r_maxparticles - numparticles; -// } - - for (k = -24; k < 32; k += 4) { - dir[2] = k * 8; - for (i = -16; i < 16; i += 4) { - dir[1] = i * 8; - for (j = -16; j < 16; j += 4) { - dir[0] = j * 8; - - VectorCopy (dir, pdir); - VectorNormalize (pdir); - - rnd = mtwist_rand (&mt); - porg[0] = org[0] + i + (rnd & 3); - porg[1] = org[1] + j + ((rnd >> 2) & 3); - porg[2] = org[2] + k + ((rnd >> 4) & 3); - - vel = 50 + ((rnd >> 6) & 63); - VectorScale (pdir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 1.0, pvel, - (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 7) * 0.02), - (7 + ((rnd >> 12) & 7)), 1.0, 0.0); + for (int i = -16; i < 16; i++) { + for (int j = -16; j < 16; j++) { + for (int k = 0; k < 1; k++) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = { + j * 8 + (mtwist_rand (&mt) & 7), + i * 8 + (mtwist_rand (&mt) & 7), + 256, + 0 + }; + vec4f_t offs = { + dir[0], + dir[1], + (mtwist_rand (&mt) & 63), + 0 + }; + dir = normalf (dir); + add_particle (pt_grav, org + offs, vel * dir, + 2 + (mtwist_rand (&mt) & 31) * 0.02, + 224 + (mtwist_rand (&mt) & 7), 0); } } } } static void -R_DarkFieldParticles_ID (const entity_t *ent) +R_TeleportSplash_ID (vec4f_t org) { - int i, j, k, l = 64; - unsigned int rnd; - float vel; - vec3_t dir, org, porg, pvel; - - if (numparticles + l >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + l >= r_maxparticles) { -// l = r_maxparticles - numparticles; -// } - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - - for (i = -16; i < 16; i += 8) { - dir [1] = i * 8; - for (j = -16; j < 16; j += 8) { - dir [0] = j * 8; - for (k = 0; k < 32; k += 8) { - dir [2] = k * 8; - rnd = mtwist_rand (&mt); - - porg[0] = org[0] + i + ((rnd >> 3) & 3); - porg[1] = org[1] + j + ((rnd >> 5) & 3); - porg[2] = org[2] + k + ((rnd >> 7) & 3); - - VectorNormalize (dir); - vel = 50 + ((rnd >> 9) & 63); - VectorScale (dir, vel, pvel); - particle_new (pt_slowgrav, part_tex_dot, porg, 1.5, pvel, - (vr_data.realtime + 0.2 + (rnd & 7) * 0.02), - (150 + mtwist_rand (&mt) % 6), 1.0, 0.0); - } + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + for (int k = -24; k < 32; k += 4) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (mtwist_rand (&mt) & 3), + j + (mtwist_rand (&mt) & 3), + k + (mtwist_rand (&mt) & 3), + 0 + }; + add_particle (pt_grav, org + offs, vel * dir, + 0.2 + (mtwist_rand (&mt) & 7) * 0.02, + 7 + (mtwist_rand (&mt) & 7), 0); + } } } } -static vec3_t avelocities[NUMVERTEXNORMALS]; - static void -R_EntityParticles_ID (const entity_t *ent) +R_DarkFieldParticles_ID (vec4f_t org) { - int i, j = NUMVERTEXNORMALS; - float angle, sp, sy, cp, cy; // cr, sr - float beamlength = 16.0, dist = 64.0; - vec3_t forward, porg; - vec3_t org; - - if (numparticles + j >= r_maxparticles) { + if (!r_particles->int_val) return; - } else if (numparticles + j >= r_maxparticles) { - j = r_maxparticles - numparticles; - } - VectorCopy (Transform_GetWorldPosition (ent->transform), org); + for (int i = -16; i < 16; i += 8) { + for (int j = -16; j < 16; j += 8) { + for (int k = 0; k < 32; k += 8) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 9) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + ((rnd >> 3) & 3), + j + ((rnd >> 5) & 3), + k + ((rnd >> 7) & 3), + 0 + }; - if (!avelocities[0][0]) { - for (i = 0; i < NUMVERTEXNORMALS; i++) { - int k; - for (k = 0; k < 3; k++) { - avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + add_particle (pt_slowgrav, org + offs, vel * dir, + 0.2 + (rnd & 7) * 0.02, + 150 + mtwist_rand (&mt) % 6, 0); } } } +} - for (i = 0; i < j; i++) { - angle = vr_data.realtime * avelocities[i][0]; +static vec4f_t velocities[NUMVERTEXNORMALS]; +static vec4f_t normals[NUMVERTEXNORMALS] = { +#include "anorms.h" +}; + +static void +R_EntityParticles_ID (vec4f_t org) +{ + int i; + float angle, sp, sy, cp, cy; // cr, sr + float beamlength = 16.0, dist = 64.0; + + if (!r_particles->int_val) + return; + + for (i = 0; i < NUMVERTEXNORMALS; i++) { + int k; + for (k = 0; k < 3; k++) { + velocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + } + } + + vec4f_t zero = {}; + for (i = 0; i < NUMVERTEXNORMALS; i++) { + angle = vr_data.realtime * velocities[i][0]; cy = cos (angle); sy = sin (angle); - angle = vr_data.realtime * avelocities[i][1]; + angle = vr_data.realtime * velocities[i][1]; cp = cos (angle); sp = sin (angle); // Next 3 lines results aren't currently used, may be in future. --Despair @@ -1230,262 +1090,152 @@ R_EntityParticles_ID (const entity_t *ent) // sr = sin (angle); // cr = cos (angle); - forward[0] = cp * cy; - forward[1] = cp * sy; - forward[2] = -sp; - - porg[0] = org[0] + r_avertexnormals[i][0] * dist + - forward[0] * beamlength; - porg[1] = org[1] + r_avertexnormals[i][1] * dist + - forward[1] * beamlength; - porg[2] = org[2] + r_avertexnormals[i][2] * dist + - forward[2] * beamlength; - particle_new (pt_explode, part_tex_dot, porg, 1.0, vec3_origin, - vr_data.realtime + 0.01, 0x6f, 1.0, 0); + vec4f_t forward = { cp * cy, cp * sy, -sp, 0 }; + vec4f_t pos = org + normals[i] * dist + forward * beamlength; + //FIXME 0 velocity? + add_particle (pt_explode, pos, zero, 0.01, 0x6f, 0); } } static void -R_RocketTrail_ID (const entity_t *ent) +R_RocketTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - int ramp, rnd; - vec3_t old_origin, org, subtract, vec; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, ent->old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, (maxlen - dist), subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - org[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - org[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - ramp = rnd & 3; - - particle_new (pt_fire, part_tex_dot, org, 1.0, vec3_origin, - vr_data.realtime + 2.0, ramp3[ramp], 1.0, ramp); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3)); + pos += vec; } } static void -R_GrenadeTrail_ID (const entity_t *ent) +R_GrenadeTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - unsigned int ramp, rnd; - vec3_t old_origin, org, subtract, vec; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, ent->old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - org[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - org[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - ramp = (rnd & 3) + 2; - - particle_new (pt_fire, part_tex_dot, org, 1.0, vec3_origin, - vr_data.realtime + 2.0, ramp3[ramp], 1.0, ramp); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3) + 2); + pos += vec; } } static void -R_BloodTrail_ID (const entity_t *ent) +R_BloodTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - unsigned int rnd; - vec3_t old_origin, subtract, vec, porg; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - porg[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - porg[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - porg[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - - particle_new (pt_grav, part_tex_dot, porg, 1.0, vec3_origin, - vr_data.realtime + 2.0, 67 + (rnd & 3), 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } static void -R_SlightBloodTrail_ID (const entity_t *ent) +R_SlightBloodTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 6.0, len = 0.0; - unsigned int rnd; - vec3_t old_origin, porg, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - porg[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - porg[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - porg[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - - particle_new (pt_grav, part_tex_dot, porg, 1.0, vec3_origin, - vr_data.realtime + 1.5, 67 + (rnd & 3), 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 6; + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } static void -R_WizTrail_ID (const entity_t *ent) +R_WizTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - static int tracercount; - vec3_t old_origin, pvel, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { + vec4f_t pos = start; + while (len > 0) { + static int tracercount; + len -= 3; + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 52 + ((tracercount & 4) << 1), 0); tracercount++; - if (tracercount & 1) { - pvel[0] = 30.0 * vec[1]; - pvel[1] = 30.0 * -vec[0]; - } else { - pvel[0] = 30.0 * -vec[1]; - pvel[1] = 30.0 * vec[0]; - } - pvel[2] = 0.0; - - particle_new (pt_static, part_tex_dot, old_origin, 1.0, pvel, - vr_data.realtime + 0.5, 52 + ((tracercount & 4) << 1), - 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += vec; } } static void -R_FlameTrail_ID (const entity_t *ent) +R_FlameTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - static int tracercount; - vec3_t old_origin, pvel, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { + vec4f_t pos = start; + while (len > 0) { + static int tracercount; + len -= 3; + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 230 + ((tracercount & 4) << 1), 0); tracercount++; - if (tracercount & 1) { - pvel[0] = 30.0 * vec[1]; - pvel[1] = 30.0 * -vec[0]; - } else { - pvel[0] = 30.0 * -vec[1]; - pvel[1] = 30.0 * vec[0]; - } - pvel[2] = 0.0; - - particle_new (pt_static, part_tex_dot, old_origin, 1.0, pvel, - vr_data.realtime + 0.5, 230 + ((tracercount & 4) << 1), - 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += vec; } } static void -R_VoorTrail_ID (const entity_t *ent) +R_VoorTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - unsigned int rnd; - vec3_t old_origin, porg, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - porg[0] = old_origin[0] + ((rnd >> 3) & 15) - 7.5; - porg[1] = old_origin[1] + ((rnd >> 7) & 15) - 7.5; - porg[2] = old_origin[2] + ((rnd >> 11) & 15) - 7.5; - - particle_new (pt_static, part_tex_dot, porg, 1.0, vec3_origin, - vr_data.realtime + 0.3, 9 * 16 + 8 + (rnd & 3), - 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_static, pos + roffs (16), zero, 0.3, + 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } @@ -1493,10 +1243,8 @@ void gl_R_DrawParticles (void) { unsigned char *at; - int activeparticles, maxparticle, j, vacount; - unsigned int k; + int vacount; float minparticledist, scale; - particle_t *part; vec3_t up_scale, right_scale, up_right_scale, down_right_scale; varray_t2f_c4ub_v3f_t *VA; @@ -1511,26 +1259,43 @@ gl_R_DrawParticles (void) minparticledist = DotProduct (r_refdef.viewposition, vpn) + r_particles_nearclip->value; - activeparticles = 0; vacount = 0; VA = particleVertexArray; - maxparticle = -1; - j = 0; - for (k = 0, part = particles; k < numparticles; k++, part++) { + vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; + + unsigned j = 0; + for (unsigned i = 0; i < numparticles; i++) { + particle_t *p = &particles[i]; + partparm_t *parm = &partparams[i]; + + if (p->live <= 0 || p->ramp >= parm->ramp_max + || p->alpha <= 0 || p->scale <= 0) { + continue; + } + const int *ramp = partramps[j]; + if (i > j) { + particles[j] = *p; + partparams[j] = *parm; + partramps[j] = ramp; + } + p = &particles[j]; + parm = &partparams[j]; + j += 1; + // Don't render particles too close to us. // Note, we must still do physics and such on them. - if (!(DotProduct (part->org, vpn) < minparticledist)) { - at = (byte *) &d_8to24table[(byte) part->color]; + if (!(DotProduct (p->pos, vpn) < minparticledist)) { + at = (byte *) &d_8to24table[(byte) p->icolor]; VA[0].color[0] = at[0]; VA[0].color[1] = at[1]; VA[0].color[2] = at[2]; - VA[0].color[3] = part->alpha * 255; + VA[0].color[3] = p->alpha * 255; memcpy (VA[1].color, VA[0].color, sizeof (VA[0].color)); memcpy (VA[2].color, VA[0].color, sizeof (VA[0].color)); memcpy (VA[3].color, VA[0].color, sizeof (VA[0].color)); - switch (part->tex) { + switch (p->tex) { case part_tex_dot: VA[0].texcoord[0] = 0.0; VA[0].texcoord[1] = 0.0; @@ -1563,7 +1328,7 @@ gl_R_DrawParticles (void) break; } - scale = part->scale; + scale = p->scale; VectorScale (vup, scale, up_scale); VectorScale (vright, scale, right_scale); @@ -1571,10 +1336,10 @@ gl_R_DrawParticles (void) VectorAdd (right_scale, up_scale, up_right_scale); VectorSubtract (right_scale, up_scale, down_right_scale); - VectorAdd (part->org, down_right_scale, VA[0].vertex); - VectorSubtract (part->org, up_right_scale, VA[1].vertex); - VectorSubtract (part->org, down_right_scale, VA[2].vertex); - VectorAdd (part->org, up_right_scale, VA[3].vertex); + VectorAdd (p->pos, down_right_scale, VA[0].vertex); + VectorSubtract (p->pos, up_right_scale, VA[1].vertex); + VectorSubtract (p->pos, down_right_scale, VA[2].vertex); + VectorAdd (p->pos, up_right_scale, VA[3].vertex); VA += 4; vacount += 4; @@ -1587,17 +1352,19 @@ gl_R_DrawParticles (void) } } - part->phys (part); - - // LordHavoc: immediate removal of unnecessary particles (must be done - // to ensure compactor below operates properly in all cases) - if (part->die < vr_data.realtime) { - freeparticles[j++] = part; - } else { - maxparticle = k; - activeparticles++; + float dT = vr_data.frametime; + p->pos += dT * p->vel; + p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); + p->ramp += dT * parm->ramp; + p->live -= dT; + p->alpha -= dT * parm->alpha_rate; + p->scale += dT * parm->scale_rate; + if (ramp) { + p->icolor = ramp[(int)p->ramp]; } } + numparticles = j; + if (vacount) { if (partUseVA) { qfglDrawElements (GL_QUADS, vacount, GL_UNSIGNED_INT, pVAindices); @@ -1615,37 +1382,28 @@ gl_R_DrawParticles (void) } } - k = 0; - while (maxparticle >= activeparticles) { - *freeparticles[k++] = particles[maxparticle--]; - while (maxparticle >= activeparticles && - particles[maxparticle].die <= vr_data.realtime) - maxparticle--; - } - numparticles = activeparticles; - qfglColor3ubv (color_white); qfglDepthMask (GL_TRUE); } static void -gl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, +gl_R_Particle_New (ptype_t type, int texnum, vec4f_t org, float scale, + vec4f_t vel, float live, int color, float alpha, float ramp) { if (numparticles >= r_maxparticles) return; - particle_new (type, texnum, org, scale, vel, die, color, alpha, ramp); + particle_new (type, texnum, org, scale, vel, live, color, alpha, ramp); } static void -gl_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, float die, +gl_R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, + int org_fuzz, float scale, int vel_fuzz, float live, int color, float alpha, float ramp) { if (numparticles >= r_maxparticles) return; - particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, die, + particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, live, color, alpha, ramp); } diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index b8bdf56ca..9975f73f2 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -61,21 +61,11 @@ #include "r_internal.h" -static mtstate_t mt; // private PRNG state - //FIXME not part of GLES, but needed for GL #ifndef GL_VERTEX_PROGRAM_POINT_SIZE # define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 #endif -//FIXME should not be here -static int ramp1[8] = { 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61 }; -//static int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 }; -static int ramp3[8] = { 0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; -static vec3_t vertex_normals[NUMVERTEXNORMALS] = { -#include "anorms.h" -}; - static GLushort *pVAindices; static partvert_t *particleVertexArray; @@ -143,32 +133,33 @@ static struct { {"fog", 1}, }; +static mtstate_t mt; // private PRNG state + inline static void -particle_new (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, float ramp) +particle_new (ptype_t type, int texnum, vec4f_t pos, float scale, + vec4f_t vel, float live, int color, float alpha, float ramp) { - particle_t *part; + if (numparticles >= r_maxparticles) + return; + particle_t *p = &particles[numparticles]; + partparm_t *parm = &partparams[numparticles]; + const int **rampptr = &partramps[numparticles]; + numparticles += 1; -/* - // Uncomment this for particle debugging! - if (numparticles >= r_maxparticles) { - Sys_Error ("FAILED PARTICLE ALLOC!"); - return NULL; + p->pos = pos; + p->vel = vel; + p->icolor = color; + p->alpha = alpha; + p->tex = texnum; + p->ramp = ramp; + p->scale = scale; + p->live = live; + + *parm = R_ParticlePhysics (type); + *rampptr = R_ParticleRamp (type); + if (*rampptr) { + p->icolor = (*rampptr) [(int) p->ramp]; } -*/ - - part = &particles[numparticles++]; - - VectorCopy (org, part->org); - part->color = color; - part->tex = texnum; - part->scale = scale; - part->alpha = alpha; - VectorCopy (vel, part->vel); - part->type = type; - part->die = die; - part->ramp = ramp; - part->phys = R_ParticlePhysics (type); } /* @@ -178,30 +169,32 @@ particle_new (ptype_t type, int texnum, const vec3_t org, float scale, going to bother using this function. */ inline static void -particle_new_random (ptype_t type, int texnum, const vec3_t org, int org_fuzz, - float scale, int vel_fuzz, float die, int color, +particle_new_random (ptype_t type, int texnum, vec4f_t org, int org_fuzz, + float scale, int vel_fuzz, float live, int color, float alpha, float ramp) { float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; int rnd; - vec3_t porg, pvel; + vec4f_t porg, pvel; rnd = mtwist_rand (&mt); porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; porg[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; + porg[3] = 1; rnd = mtwist_rand (&mt); pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; pvel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; + pvel[3] = 0; - particle_new (type, texnum, porg, scale, pvel, die, color, alpha, ramp); + particle_new (type, texnum, porg, scale, pvel, live, color, alpha, ramp); } /* inline static void -particle_new_veryrandom (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, float die, +particle_new_veryrandom (ptype_t type, int texnum, vec4f_t org, + int org_fuzz, float scale, int vel_fuzz, float live, int color, float alpha, float ramp) { vec3_t porg, pvel; @@ -212,10 +205,39 @@ particle_new_veryrandom (ptype_t type, int texnum, const vec3_t org, pvel[0] = qfrandom (vel_fuzz * 2) - vel_fuzz; pvel[1] = qfrandom (vel_fuzz * 2) - vel_fuzz; pvel[2] = qfrandom (vel_fuzz * 2) - vel_fuzz; - particle_new (type, texnum, porg, scale, pvel, die, color, alpha, ramp); + particle_new (type, texnum, porg, scale, pvel, live, color, alpha, ramp); } */ +static vec4f_t +roffs (int mod) +{ + vec4f_t offs = { + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + 0 + }; + return offs; +} + +static vec4f_t +tracer_vel (int tracercount, vec4f_t vec) +{ + if (tracercount & 1) { + return (vec4f_t) { vec[1], -vec[0], 0, 0 }; + } else { + return (vec4f_t) { -vec[1], vec[0], 0, 0 }; + } +} + +static void +add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, + float ramp) +{ + particle_new (type, part_tex_dot, pos, 1, vel, live, color, 1, ramp); +} + void glsl_R_ClearParticles (void) { @@ -312,8 +334,7 @@ glsl_R_ReadPointFile_f (void) { const char *name; char *mapname; - int c, r; - vec3_t org; + int c; QFile *f; mapname = strdup (r_worldentity.renderer.model->path); @@ -332,11 +353,13 @@ glsl_R_ReadPointFile_f (void) Sys_MaskPrintf (SYS_dev, "Reading %s...\n", name); c = 0; + vec4f_t zero = {}; for (;;) { char buf[64]; + vec4f_t org = { 0, 0, 0, 1 }; Qgets (f, buf, sizeof (buf)); - r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); + int r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); if (r != 3) break; c++; @@ -345,7 +368,7 @@ glsl_R_ReadPointFile_f (void) Sys_MaskPrintf (SYS_dev, "Not enough free particles\n"); break; } else { - particle_new (pt_static, part_tex_dot, org, 1.5, vec3_origin, + particle_new (pt_static, part_tex_dot, org, 1.5, zero, 99999, (-c) & 15, 1.0, 0.0); } } @@ -354,18 +377,18 @@ glsl_R_ReadPointFile_f (void) } static void -R_ParticleExplosion_QF (const vec3_t org) +R_ParticleExplosion_QF (vec4f_t org) { // R_NewExplosion (org); if (numparticles >= r_maxparticles) return; particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, - vr_data.realtime + 5.0, (mtwist_rand (&mt) & 7) + 8, + 5.0, (mtwist_rand (&mt) & 7) + 8, 0.5 + qfrandom (0.25), 0.0); } static void -R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) +R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) { unsigned int i, j = 512; @@ -376,13 +399,13 @@ R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) for (i = 0; i < j; i++) { particle_new_random (pt_blob, part_tex_dot, org, 16, 2, 256, - vr_data.realtime + 0.3, + 0.3, colorStart + (i % colorLength), 1.0, 0.0); } } static void -R_BlobExplosion_QF (const vec3_t org) +R_BlobExplosion_QF (vec4f_t org) { unsigned int i; unsigned int j = 1024; @@ -394,28 +417,28 @@ R_BlobExplosion_QF (const vec3_t org) for (i = 0; i < j >> 1; i++) { particle_new_random (pt_blob, part_tex_dot, org, 12, 2, 256, - vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, 66 + i % 6, 1.0, 0.0); } for (i = 0; i < j / 2; i++) { particle_new_random (pt_blob2, part_tex_dot, org, 12, 2, 256, - vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, 150 + i % 6, 1.0, 0.0); } } static inline void -R_RunSparkEffect_QF (const vec3_t org, int count, int ofuzz) +R_RunSparkEffect_QF (vec4f_t org, int count, int ofuzz) { - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; + + vec4f_t zero = {}; particle_new (pt_smokecloud, part_tex_smoke, org, ofuzz * 0.08, - vec3_origin, vr_data.realtime + 9, 12 + (mtwist_rand (&mt) & 3), + zero, 9, 12 + (mtwist_rand (&mt) & 3), 0.25 + qfrandom (0.125), 0.0); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - if (count) { + if (count > 0) { int orgfuzz = ofuzz * 3 / 4; if (orgfuzz < 1) orgfuzz = 1; @@ -424,30 +447,30 @@ R_RunSparkEffect_QF (const vec3_t org, int count, int ofuzz) int color = mtwist_rand (&mt) & 7; particle_new_random (pt_fallfadespark, part_tex_dot, org, orgfuzz, - 0.7, 96, vr_data.realtime + 5.0, ramp1[color], - 1.0, color); + 0.7, 96, 5.0, 0, 1.0, color); } } } static inline void -R_BloodPuff_QF (const vec3_t org, int count) +R_BloodPuff_QF (vec4f_t org, int count) { - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - particle_new (pt_bloodcloud, part_tex_smoke, org, count / 5, vec3_origin, - vr_data.realtime + 99.0, 70 + (mtwist_rand (&mt) & 3), 0.5, 0.0); + vec4f_t zero = {}; + particle_new (pt_bloodcloud, part_tex_smoke, org, count / 5, zero, + 99.0, 70 + (mtwist_rand (&mt) & 3), 0.5, 0.0); } static void -R_BloodPuffEffect_QF (const vec3_t org, int count) +R_BloodPuffEffect_QF (vec4f_t org, int count) { R_BloodPuff_QF (org, count); } static void -R_GunshotEffect_QF (const vec3_t org, int count) +R_GunshotEffect_QF (vec4f_t org, int count) { int scale = 16; @@ -456,170 +479,133 @@ R_GunshotEffect_QF (const vec3_t org, int count) } static void -R_LightningBloodEffect_QF (const vec3_t org) +R_LightningBloodEffect_QF (vec4f_t org) { - int count = 7; + if (!r_particles->int_val) + return; R_BloodPuff_QF (org, 50); - if (numparticles >= r_maxparticles) - return; - particle_new (pt_smokecloud, part_tex_smoke, org, 3.0, vec3_origin, - vr_data.realtime + 9.0, 12 + (mtwist_rand (&mt) & 3), + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, 3.0, zero, + 9.0, 12 + (mtwist_rand (&mt) & 3), 0.25 + qfrandom (0.125), 0.0); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - while (count--) + for (int count = 7; count-- > 0; ) { particle_new_random (pt_fallfade, part_tex_spark, org, 12, 2.0, 128, - vr_data.realtime + 5.0, 244 + (count % 3), - 1.0, 0.0); + 5.0, 244 + (count % 3), 1.0, 0.0); + } } static void -R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, +R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, int count) { - float scale; - int i; - vec3_t porg; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - scale = pow (count, 0.23); // calculate scale before clipping to part. max + float scale = pow (count, 0.23); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - - for (i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { int rnd = mtwist_rand (&mt); - porg[0] = org[0] + scale * (((rnd >> 3) & 15) - 7.5); - porg[1] = org[1] + scale * (((rnd >> 7) & 15) - 7.5); - porg[2] = org[2] + scale * (((rnd >> 11) & 15) - 7.5); // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, porg, 1.5, dir, - vr_data.realtime + 0.1 * (i % 5), + particle_new (pt_grav, part_tex_dot, org + scale * roffs (16), 1.5, + dir, 0.1 * (i % 5), (color & ~7) + (rnd & 7), 1.0, 0.0); } } static void -R_SpikeEffect_QF (const vec3_t org) +R_SpikeEffect_QF (vec4f_t org) { R_RunSparkEffect_QF (org, 5, 8); } static void -R_SuperSpikeEffect_QF (const vec3_t org) +R_SuperSpikeEffect_QF (vec4f_t org) { R_RunSparkEffect_QF (org, 10, 8); } static void -R_KnightSpikeEffect_QF (const vec3_t org) +R_KnightSpikeEffect_QF (vec4f_t org) { - unsigned int count = 10; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 1.0, vec3_origin, - vr_data.realtime + 9.0, 234, 0.25 + qfrandom (0.125), 0.0); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - while (count--) + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, 1.0, zero, + 9.0, 234, 0.25 + qfrandom (0.125), 0.0); + + for (int count = 10; count-- > 0; ) { particle_new_random (pt_fallfade, part_tex_dot, org, 6, 0.7, 96, - vr_data.realtime + 5.0, 234, 1.0, 0.0); + 5.0, 234, 1.0, 0.0); + } } static void -R_WizSpikeEffect_QF (const vec3_t org) +R_WizSpikeEffect_QF (vec4f_t org) { - unsigned int count = 15; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - particle_new (pt_smokecloud, part_tex_smoke, org, 2.0, vec3_origin, - vr_data.realtime + 9.0, 63, 0.25 + qfrandom (0.125), 0.0); - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - while (count--) + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, 2.0, zero, + 9.0, 63, 0.25 + qfrandom (0.125), 0.0); + + for (int count = 15; count-- > 0; ) { particle_new_random (pt_fallfade, part_tex_dot, org, 12, 0.7, 96, - vr_data.realtime + 5.0, 63, 1.0, 0.0); + 5.0, 63, 1.0, 0.0); + } } static void -R_LavaSplash_QF (const vec3_t org) +R_LavaSplash_QF (vec4f_t org) { - float vel; - int rnd, i, j; - int k = 256; - vec3_t dir, porg, pvel; - - if (numparticles + k >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + k >= r_maxparticles) { -// k = r_maxparticles - numparticles; -// } - dir[2] = 256; - for (i = -128; i < 128; i += 16) { - for (j = -128; j < 128; j += 16) { - rnd = mtwist_rand (&mt); - dir[0] = j + (rnd & 7); - dir[1] = i + ((rnd >> 6) & 7); - - porg[0] = org[0] + dir[0]; - porg[1] = org[1] + dir[1]; - porg[2] = org[2] + ((rnd >> 9) & 63); - - VectorNormalize (dir); - rnd = mtwist_rand (&mt); - vel = 50.0 + 0.5 * (float) (rnd & 127); - VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 3, pvel, - vr_data.realtime + 2.0 + ((rnd >> 7) & 31) * 0.02, + for (int i = -16; i < 16; i++) { + for (int j = -16; j < 16; j++) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50.0 + 0.5 * (mtwist_rand (&mt) & 127); + vec4f_t dir = { + j * 8 + (rnd & 7), + i * 8 + ((rnd >> 6) & 7), + 256, + 0 + }; + vec4f_t offs = { dir[0], dir[1], ((rnd >> 9) & 63), 0 }; + dir = normalf (dir); + particle_new (pt_grav, part_tex_dot, org + offs, 3, vel * dir, + 2.0 + ((rnd >> 7) & 31) * 0.02, 224 + ((rnd >> 12) & 7), 0.75, 0.0); } } } static void -R_TeleportSplash_QF (const vec3_t org) +R_TeleportSplash_QF (vec4f_t org) { - float vel; - int rnd, i, j, k; - int l = 896; - vec3_t dir, pdir, porg, pvel; - - if (numparticles + l >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + l >= r_maxparticles) { -// l = r_maxparticles - numparticles; -// } - for (k = -24; k < 32; k += 4) { - dir[2] = k * 8; - for (i = -16; i < 16; i += 4) { - dir[1] = i * 8; - for (j = -16; j < 16; j += 4) { - dir[0] = j * 8; - - VectorCopy (dir, pdir); - VectorNormalize (pdir); - - rnd = mtwist_rand (&mt); - porg[0] = org[0] + i + (rnd & 3); - porg[1] = org[1] + j + ((rnd >> 2) & 3); - porg[2] = org[2] + k + ((rnd >> 4) & 3); - - vel = 50 + ((rnd >> 6) & 63); - VectorScale (pdir, vel, pvel); - particle_new (pt_grav, part_tex_spark, porg, 0.6, pvel, - (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 15) * 0.01), + for (int k = -24; k < 32; k += 4) { + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 6) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (rnd & 3), + j + ((rnd >> 2) & 3), + k + ((rnd >> 4) & 3), + 0 + }; + particle_new (pt_grav, part_tex_spark, org + offs, 0.6, + vel * dir, + (0.2 + (mtwist_rand (&mt) & 15) * 0.01), (7 + ((rnd >> 12) & 7)), 1.0, 0.0); } } @@ -627,320 +613,272 @@ R_TeleportSplash_QF (const vec3_t org) } static void -R_RocketTrail_QF (const entity_t *ent) +R_RocketTrail_QF (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - vec3_t old_origin, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 1.5 + qfrandom (1.5); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + float pscale = 1.5 + qfrandom (1.5); while (len < maxlen) { - pscalenext = 1.5 + qfrandom (1.5); - dist = (pscale + pscalenext) * 3.0; - percent = len * origlen; + float pscalenext = 1.5 + qfrandom (1.5); + float dist = (pscale + pscalenext) * 3.0; + float percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, - pscale + percent * 4.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, 12 + (mtwist_rand (&mt) & 3), 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorMultAdd (old_origin, len, vec, old_origin); + pos += step; pscale = pscalenext; } } static void -R_GrenadeTrail_QF (const entity_t *ent) +R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - vec3_t old_origin, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 6.0 + qfrandom (7.0); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + float pscale = 6.0 + qfrandom (7.0); while (len < maxlen) { - pscalenext = 6.0 + qfrandom (7.0); - dist = (pscale + pscalenext) * 2.0; - percent = len * origlen; + float pscalenext = 6.0 + qfrandom (7.0); + float dist = (pscale + pscalenext) * 2.0; + float percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, - pscale + percent * 4.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, 1 + (mtwist_rand (&mt) & 3), 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorMultAdd (old_origin, len, vec, old_origin); + pos += step; pscale = pscalenext; } } static void -R_BloodTrail_QF (const entity_t *ent) +R_BloodTrail_QF (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - int j; - vec3_t old_origin, porg, pvel, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 5.0 + qfrandom (10.0); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t pos = start; + float pscale = 5.0 + qfrandom (10.0); while (len < maxlen) { - pscalenext = 5.0 + qfrandom (10.0); - dist = (pscale + pscalenext) * 1.5; + float pscalenext = 5.0 + qfrandom (10.0); + float dist = (pscale + pscalenext) * 1.5; + float percent = len * origlen; + vec4f_t vel = roffs (24); + vel[2] -= percent * 40; - for (j = 0; j < 3; j++) { - pvel[j] = qfrandom (24.0) - 12.0; - porg[j] = old_origin[j] + qfrandom (3.0) - 1.5; - } - - percent = len * origlen; - pvel[2] -= percent * 40.0; - - particle_new (pt_grav, part_tex_smoke, porg, pscale, pvel, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, + 2.0 - percent * 2.0, 68 + (mtwist_rand (&mt) & 3), 1.0, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorMultAdd (old_origin, len, vec, old_origin); + pos += step; pscale = pscalenext; } } static void -R_SlightBloodTrail_QF (const entity_t *ent) +R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - int j; - vec3_t old_origin, porg, pvel, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 1.5 + qfrandom (7.5); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t pos = start; + float pscale = 1.5 + qfrandom (7.5); while (len < maxlen) { - pscalenext = 1.5 + qfrandom (7.5); - dist = (pscale + pscalenext) * 1.5; + float pscalenext = 1.5 + qfrandom (7.5); + float dist = (pscale + pscalenext) * 1.5; + float percent = len * origlen; + vec4f_t vel = roffs (12); + vel[2] -= percent * 40; - for (j = 0; j < 3; j++) { - pvel[j] = (qfrandom (12.0) - 6.0); - porg[j] = old_origin[j] + qfrandom (3.0) - 1.5; - } - - percent = len * origlen; - pvel[2] -= percent * 40; - - particle_new (pt_grav, part_tex_smoke, porg, pscale, pvel, - vr_data.realtime + 1.5 - percent * 1.5, + particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, + 1.5 - percent * 1.5, 68 + (mtwist_rand (&mt) & 3), 0.75, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorMultAdd (old_origin, len, vec, old_origin); + pos += step; pscale = pscalenext; } } static void -R_WizTrail_QF (const entity_t *ent) +R_WizTrail_QF (vec4f_t start, vec4f_t end) { - float maxlen, origlen, percent; - float dist = 3.0, len = 0.0; - static int tracercount; - vec3_t old_origin, pvel, subtract, vec; - vec3_t org; + float dist = 3.0; if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t pos = start; while (len < maxlen) { - percent = len * origlen; + static int tracercount; + float percent = len * origlen; - tracercount++; - if (tracercount & 1) { - pvel[0] = 30.0 * vec[1]; - pvel[1] = 30.0 * -vec[0]; - } else { - pvel[0] = 30.0 * -vec[1]; - pvel[1] = 30.0 * vec[0]; - } - pvel[2] = 0.0; - - particle_new (pt_flame, part_tex_smoke, old_origin, - 2.0 + qfrandom (1.0) - percent * 2.0, pvel, - vr_data.realtime + 0.5 - percent * 0.5, + particle_new (pt_flame, part_tex_smoke, pos, + 2.0 + qfrandom (1.0) - percent * 2.0, + 30 * tracer_vel (tracercount++, vec), + 0.5 - percent * 0.5, 52 + (mtwist_rand (&mt) & 4), 1.0 - percent * 0.125, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += step; } } static void -R_FlameTrail_QF (const entity_t *ent) +R_FlameTrail_QF (vec4f_t start, vec4f_t end) { - float maxlen, origlen, percent; - float dist = 3.0, len = 0.0; - static int tracercount; - vec3_t old_origin, pvel, subtract, vec; - vec3_t org; + float dist = 3.0; if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t pos = start; while (len < maxlen) { - percent = len * origlen; + static int tracercount; + float percent = len * origlen; - tracercount++; - if (tracercount & 1) { - pvel[0] = 30.0 * vec[1]; - pvel[1] = 30.0 * -vec[0]; - } else { - pvel[0] = 30.0 * -vec[1]; - pvel[1] = 30.0 * vec[0]; - } - pvel[2] = 0.0; - - particle_new (pt_flame, part_tex_smoke, old_origin, - 2.0 + qfrandom (1.0) - percent * 2.0, pvel, - vr_data.realtime + 0.5 - percent * 0.5, 234, + particle_new (pt_flame, part_tex_smoke, pos, + 2.0 + qfrandom (1.0) - percent * 2.0, + 30 * tracer_vel (tracercount++, vec), + 0.5 - percent * 0.5, 234, 1.0 - percent * 0.125, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += step; } } static void -R_VoorTrail_QF (const entity_t *ent) +R_VoorTrail_QF (vec4f_t start, vec4f_t end) { - float maxlen, origlen, percent; - float dist = 3.0, len = 0.0; - int j; - vec3_t subtract, old_origin, porg, vec; - vec3_t org; + float dist = 3.0; if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; while (len < maxlen) { - percent = len * origlen; + float percent = len * origlen; - for (j = 0; j < 3; j++) - porg[j] = old_origin[j] + qfrandom (16.0) - 8.0; - - particle_new (pt_static, part_tex_dot, porg, 1.0 + qfrandom (1.0), - vec3_origin, vr_data.realtime + 0.3 - percent * 0.3, + particle_new (pt_static, part_tex_dot, pos + roffs (16), + 1.0 + qfrandom (1.0), + zero, 0.3 - percent * 0.3, 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += step; } } static void -R_GlowTrail_QF (const entity_t *ent, int glow_color) +R_GlowTrail_QF (vec4f_t start, vec4f_t end, int glow_color) { - float maxlen, origlen, percent; - float dist = 3.0, len = 0.0; - int rnd; - vec3_t old_origin, org, subtract, vec; + float dist = 3.0; if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - VectorScale (vec, (maxlen - dist), subtract); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; while (len < maxlen) { - percent = len * origlen; + float percent = len * origlen; - rnd = mtwist_rand (&mt); - org[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - org[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - - particle_new (pt_smoke, part_tex_dot, org, 1.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 0.2, glow_color, - 1.0, 0.0); + particle_new (pt_smoke, part_tex_dot, pos + roffs (5), 1.0, zero, + 2.0 - percent * 0.2, glow_color, 1.0, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += step; } } static void -R_ParticleExplosion_EE (const vec3_t org) +R_ParticleExplosion_EE (vec4f_t org) { /* R_NewExplosion (org); @@ -948,41 +886,31 @@ R_ParticleExplosion_EE (const vec3_t org) if (numparticles >= r_maxparticles) return; particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, - vr_data.realtime + 5.0, mtwist_rand (&mt) & 255, + 5.0, mtwist_rand (&mt) & 255, 0.5 + qfrandom (0.25), 0.0); } static void -R_TeleportSplash_EE (const vec3_t org) +R_TeleportSplash_EE (vec4f_t org) { - float vel; - int rnd, i, j, k; - int l = 896; - vec3_t dir, porg, pvel; - - if (numparticles + l >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + l >= r_maxparticles) { -// l = r_maxparticles - numparticles; -// } - for (k = -24; k < 32; k += 4) { - dir[2] = k * 8; - for (i = -16; i < 16; i += 4) { - dir[1] = i * 8; - for (j = -16; j < 16; j += 4) { - dir[0] = j * 8; - - rnd = mtwist_rand (&mt); - porg[0] = org[0] + i + (rnd & 3); - porg[1] = org[1] + j + ((rnd >> 2) & 3); - porg[2] = org[2] + k + ((rnd >> 4) & 3); - - VectorNormalize (dir); - vel = 50 + ((rnd >> 6) & 63); - VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_spark, porg, 0.6, pvel, - (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 15) * 0.01), + for (int k = -24; k < 32; k += 4) { + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 6) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (rnd & 3), + j + ((rnd >> 2) & 3), + k + ((rnd >> 4) & 3), + 0 + }; + particle_new (pt_grav, part_tex_spark, org + offs, 0.6, + vel * dir, + (0.2 + (mtwist_rand (&mt) & 15) * 0.01), qfrandom (1.0), 1.0, 0.0); } } @@ -990,345 +918,274 @@ R_TeleportSplash_EE (const vec3_t org) } static void -R_RocketTrail_EE (const entity_t *ent) +R_RocketTrail_EE (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - vec3_t old_origin, subtract, vec; - vec3_t org; - if (numparticles >= r_maxparticles) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 1.5 + qfrandom (1.5); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + float pscale = 1.5 + qfrandom (1.5); + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; while (len < maxlen) { - pscalenext = 1.5 + qfrandom (1.5); - dist = (pscale + pscalenext) * 3.0; - percent = len * origlen; + float pscalenext = 1.5 + qfrandom (1.5); + float dist = (pscale + pscalenext) * 3.0; + float percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, - pscale + percent * 4.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, mtwist_rand (&mt) & 255, 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); if (numparticles >= r_maxparticles) break; len += dist; - VectorScale (vec, len, subtract); - VectorAdd (old_origin, subtract, old_origin); + pos += len * vec; pscale = pscalenext; } } static void -R_GrenadeTrail_EE (const entity_t *ent) +R_GrenadeTrail_EE (vec4f_t start, vec4f_t end) { - float dist, maxlen, origlen, percent, pscale, pscalenext; - float len = 0.0; - vec3_t old_origin, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, ent->old_origin, vec); - maxlen = VectorNormalize (vec); - origlen = vr_data.frametime / maxlen; - pscale = 6.0 + qfrandom (7.0); + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + float origlen = vr_data.frametime / maxlen; + float pscale = 6.0 + qfrandom (7.0); + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; while (len < maxlen) { - pscalenext = 6.0 + qfrandom (7.0); - dist = (pscale + pscalenext) * 2.0; - percent = len * origlen; + float pscalenext = 6.0 + qfrandom (7.0); + float dist = (pscale + pscalenext) * 2.0; + float percent = len * origlen; - particle_new (pt_smoke, part_tex_smoke, old_origin, - pscale + percent * 4.0, vec3_origin, - vr_data.realtime + 2.0 - percent * 2.0, + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, mtwist_rand (&mt) & 255, 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; - VectorScale (vec, len, subtract); - VectorAdd (old_origin, subtract, old_origin); + pos += len * vec; pscale = pscalenext; } } static void -R_ParticleExplosion_ID (const vec3_t org) +R_ParticleExplosion_ID (vec4f_t org) { - unsigned int i; - unsigned int j = 1024; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_explode, part_tex_dot, org, 16, 1.0, 256, - vr_data.realtime + 5.0, ramp1[0], 1.0, i & 3); - } - for (i = 0; i < j / 2; i++) { - particle_new_random (pt_explode2, part_tex_dot, org, 16, 1.0, 256, - vr_data.realtime + 5.0, ramp1[0], 1.0, i & 3); + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_explode2 : pt_explode; + add_particle (type, org + roffs (32), roffs (512), 5, + 0, mtwist_rand (&mt) & 3); } } static void -R_BlobExplosion_ID (const vec3_t org) +R_BlobExplosion_ID (vec4f_t org) { - unsigned int i; - unsigned int j = 1024; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 12, 1.0, 256, - vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 8) * 0.05, - 66 + i % 6, 1.0, 0.0); - } - for (i = 0; i < j / 2; i++) { - particle_new_random (pt_blob2, part_tex_dot, org, 12, 1.0, 256, - vr_data.realtime + 1.0 + (mtwist_rand (&mt) & 8) * 0.05, - 150 + i % 6, 1.0, 0.0); + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_blob : pt_blob2; + int color = i & 1 ? 66 : 150; + add_particle (type, org + roffs (32), roffs (512), + color + mtwist_rand (&mt) % 6, + (color & ~7) + (mtwist_rand (&mt) & 7), 0); } } static inline void // FIXME: inline? -R_RunParticleEffect_ID (const vec3_t org, const vec3_t dir, int color, +R_RunParticleEffect_ID (vec4f_t org, vec4f_t dir, int color, int count) { - float scale; - int i; - vec3_t porg; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - if (count > 130) // calculate scale before clipping to particle max - scale = 3.0; - else if (count > 20) - scale = 2.0; - else - scale = 1.0; - - if (numparticles + count >= r_maxparticles) - count = r_maxparticles - numparticles; - - for (i = 0; i < count; i++) { - int rnd = mtwist_rand (&mt); - - porg[0] = org[0] + scale * (((rnd >> 3) & 15) - 8); - porg[1] = org[1] + scale * (((rnd >> 7) & 15) - 8); - porg[2] = org[2] + scale * (((rnd >> 11) & 15) - 8); - - // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, porg, 1.0, dir, - vr_data.realtime + 0.1 * (i % 5), - (color & ~7) + (rnd & 7), 1.0, 0.0); + for (int i = 0; i < count; i++) { + add_particle (pt_slowgrav, org + roffs (16), + dir/* + roffs (300)*/, + 0.1 * (mtwist_rand (&mt) % 5), + (color & ~7) + (mtwist_rand (&mt) & 7), 0); } } static void -R_BloodPuffEffect_ID (const vec3_t org, int count) +R_BloodPuffEffect_ID (vec4f_t org, int count) { - R_RunParticleEffect_ID (org, vec3_origin, 73, count); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 73, count); } static void -R_GunshotEffect_ID (const vec3_t org, int count) +R_GunshotEffect_ID (vec4f_t org, int count) { - R_RunParticleEffect_ID (org, vec3_origin, 0, count); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 0, count); } static void -R_LightningBloodEffect_ID (const vec3_t org) +R_LightningBloodEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 225, 50); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 225, 50); } static void -R_SpikeEffect_ID (const vec3_t org) +R_SpikeEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 0, 10); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 0, 10); } static void -R_SuperSpikeEffect_ID (const vec3_t org) +R_SuperSpikeEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 0, 20); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 0, 20); } static void -R_KnightSpikeEffect_ID (const vec3_t org) +R_KnightSpikeEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 226, 20); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 226, 20); } static void -R_WizSpikeEffect_ID (const vec3_t org) +R_WizSpikeEffect_ID (vec4f_t org) { - R_RunParticleEffect_ID (org, vec3_origin, 20, 30); + vec4f_t zero = {}; + R_RunParticleEffect_ID (org, zero, 20, 30); } static void -R_LavaSplash_ID (const vec3_t org) +R_LavaSplash_ID (vec4f_t org) { - float vel; - int rnd, i, j; - int k = 256; - vec3_t dir, porg, pvel; - - if (numparticles + k >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + k >= r_maxparticles) { -// k = r_maxparticles - numparticles; -// } - dir[2] = 256; - for (i = -128; i < 128; i += 16) { - for (j = -128; j < 128; j += 16) { - rnd = mtwist_rand (&mt); - dir[0] = j + (rnd & 7); - dir[1] = i + ((rnd >> 6) & 7); - - porg[0] = org[0] + dir[0]; - porg[1] = org[1] + dir[1]; - porg[2] = org[2] + ((rnd >> 9) & 63); - - VectorNormalize (dir); - rnd = mtwist_rand (&mt); - vel = 50 + (rnd & 63); - VectorScale (dir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 1.0, pvel, - vr_data.realtime + 2 + ((rnd >> 7) & 31) * 0.02, - 224 + ((rnd >> 12) & 7), 1.0, 0.0); - } - } -} - -static void -R_TeleportSplash_ID (const vec3_t org) -{ - float vel; - int rnd, i, j, k; - int l = 896; - vec3_t dir, pdir, porg, pvel; - - if (numparticles + l >= r_maxparticles) { - return; - } // else if (numparticles + l >= r_maxparticles) { -// l = r_maxparticles - numparticles; -// } - - for (k = -24; k < 32; k += 4) { - dir[2] = k * 8; - for (i = -16; i < 16; i += 4) { - dir[1] = i * 8; - for (j = -16; j < 16; j += 4) { - dir[0] = j * 8; - - VectorCopy (dir, pdir); - VectorNormalize (pdir); - - rnd = mtwist_rand (&mt); - porg[0] = org[0] + i + (rnd & 3); - porg[1] = org[1] + j + ((rnd >> 2) & 3); - porg[2] = org[2] + k + ((rnd >> 4) & 3); - - vel = 50 + ((rnd >> 6) & 63); - VectorScale (pdir, vel, pvel); - particle_new (pt_grav, part_tex_dot, porg, 1.0, pvel, - (vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 7) * 0.02), - (7 + ((rnd >> 12) & 7)), 1.0, 0.0); + for (int i = -16; i < 16; i++) { + for (int j = -16; j < 16; j++) { + for (int k = 0; k < 1; k++) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = { + j * 8 + (mtwist_rand (&mt) & 7), + i * 8 + (mtwist_rand (&mt) & 7), + 256, + 0 + }; + vec4f_t offs = { + dir[0], + dir[1], + (mtwist_rand (&mt) & 63), + 0 + }; + dir = normalf (dir); + add_particle (pt_grav, org + offs, vel * dir, + 2 + (mtwist_rand (&mt) & 31) * 0.02, + 224 + (mtwist_rand (&mt) & 7), 0); } } } } static void -R_DarkFieldParticles_ID (const entity_t *ent) +R_TeleportSplash_ID (vec4f_t org) { - int i, j, k, l = 64; - unsigned int rnd; - float vel; - vec3_t dir, org, porg, pvel; - - if (numparticles + l >= r_maxparticles) { + if (!r_particles->int_val) return; - } // else if (numparticles + l >= r_maxparticles) { -// l = r_maxparticles - numparticles; -// } - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - - for (i = -16; i < 16; i += 8) { - dir [1] = i * 8; - for (j = -16; j < 16; j += 8) { - dir [0] = j * 8; - for (k = 0; k < 32; k += 8) { - dir [2] = k * 8; - rnd = mtwist_rand (&mt); - - porg[0] = org[0] + i + ((rnd >> 3) & 3); - porg[1] = org[1] + j + ((rnd >> 5) & 3); - porg[2] = org[2] + k + ((rnd >> 7) & 3); - - VectorNormalize (dir); - vel = 50 + ((rnd >> 9) & 63); - VectorScale (dir, vel, pvel); - particle_new (pt_slowgrav, part_tex_dot, porg, 1.5, pvel, - (vr_data.realtime + 0.2 + (rnd & 7) * 0.02), - (150 + mtwist_rand (&mt) % 6), 1.0, 0.0); - } + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + for (int k = -24; k < 32; k += 4) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (mtwist_rand (&mt) & 3), + j + (mtwist_rand (&mt) & 3), + k + (mtwist_rand (&mt) & 3), + 0 + }; + add_particle (pt_grav, org + offs, vel * dir, + 0.2 + (mtwist_rand (&mt) & 7) * 0.02, + 7 + (mtwist_rand (&mt) & 7), 0); + } } } } -static vec3_t avelocities[NUMVERTEXNORMALS]; +static void +R_DarkFieldParticles_ID (vec4f_t org) +{ + if (!r_particles->int_val) + return; + + for (int i = -16; i < 16; i += 8) { + for (int j = -16; j < 16; j += 8) { + for (int k = 0; k < 32; k += 8) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 9) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + ((rnd >> 3) & 3), + j + ((rnd >> 5) & 3), + k + ((rnd >> 7) & 3), + 0 + }; + + add_particle (pt_slowgrav, org + offs, vel * dir, + 0.2 + (rnd & 7) * 0.02, + 150 + mtwist_rand (&mt) % 6, 0); + } + } + } +} + +static vec4f_t velocities[NUMVERTEXNORMALS]; +static vec4f_t normals[NUMVERTEXNORMALS] = { +#include "anorms.h" +}; static void -R_EntityParticles_ID (const entity_t *ent) +R_EntityParticles_ID (vec4f_t org) { - int i, j = NUMVERTEXNORMALS; - float angle, sp, sy, cp, cy; // cr, sr - float beamlength = 16.0, dist = 64.0; - vec3_t forward, porg; - vec3_t org; + int i; + float angle, sp, sy, cp, cy; // cr, sr + float beamlength = 16.0, dist = 64.0; - if (numparticles + j >= r_maxparticles) { + if (!r_particles->int_val) return; - } else if (numparticles + j >= r_maxparticles) { - j = r_maxparticles - numparticles; - } - - VectorCopy (Transform_GetWorldPosition (ent->transform), org); for (i = 0; i < NUMVERTEXNORMALS; i++) { int k; for (k = 0; k < 3; k++) { - avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + velocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; } } - for (i = 0; i < j; i++) { - angle = vr_data.realtime * avelocities[i][0]; + vec4f_t zero = {}; + for (i = 0; i < NUMVERTEXNORMALS; i++) { + angle = vr_data.realtime * velocities[i][0]; cy = cos (angle); sy = sin (angle); - angle = vr_data.realtime * avelocities[i][1]; + angle = vr_data.realtime * velocities[i][1]; cp = cos (angle); sp = sin (angle); // Next 3 lines results aren't currently used, may be in future. --Despair @@ -1336,262 +1193,152 @@ R_EntityParticles_ID (const entity_t *ent) // sr = sin (angle); // cr = cos (angle); - forward[0] = cp * cy; - forward[1] = cp * sy; - forward[2] = -sp; - - porg[0] = org[0] + vertex_normals[i][0] * dist + - forward[0] * beamlength; - porg[1] = org[1] + vertex_normals[i][1] * dist + - forward[1] * beamlength; - porg[2] = org[2] + vertex_normals[i][2] * dist + - forward[2] * beamlength; - particle_new (pt_explode, part_tex_dot, porg, 1.0, vec3_origin, - vr_data.realtime + 0.01, 0x6f, 1.0, 0); + vec4f_t forward = { cp * cy, cp * sy, -sp, 0 }; + vec4f_t pos = org + normals[i] * dist + forward * beamlength; + //FIXME 0 velocity? + add_particle (pt_explode, pos, zero, 0.01, 0x6f, 0); } } static void -R_RocketTrail_ID (const entity_t *ent) +R_RocketTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - int ramp, rnd; - vec3_t old_origin, org, subtract, vec; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, ent->old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, (maxlen - dist), subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - org[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - org[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - ramp = rnd & 3; - - particle_new (pt_fire, part_tex_dot, org, 1.0, vec3_origin, - vr_data.realtime + 2.0, ramp3[ramp], 1.0, ramp); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3)); + pos += vec; } } static void -R_GrenadeTrail_ID (const entity_t *ent) +R_GrenadeTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - unsigned int ramp, rnd; - vec3_t old_origin, org, subtract, vec; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, ent->old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - org[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - org[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - org[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - ramp = (rnd & 3) + 2; - - particle_new (pt_fire, part_tex_dot, org, 1.0, vec3_origin, - vr_data.realtime + 2.0, ramp3[ramp], 1.0, ramp); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3) + 2); + pos += vec; } } static void -R_BloodTrail_ID (const entity_t *ent) +R_BloodTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - unsigned int rnd; - vec3_t old_origin, subtract, vec, porg; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - porg[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - porg[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - porg[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - - particle_new (pt_grav, part_tex_dot, porg, 1.0, vec3_origin, - vr_data.realtime + 2.0, 67 + (rnd & 3), 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } static void -R_SlightBloodTrail_ID (const entity_t *ent) +R_SlightBloodTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 6.0, len = 0.0; - unsigned int rnd; - vec3_t old_origin, porg, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - porg[0] = old_origin[0] + ((rnd >> 12) & 7) * (5.0/7.0) - 2.5; - porg[1] = old_origin[1] + ((rnd >> 9) & 7) * (5.0/7.0) - 2.5; - porg[2] = old_origin[2] + ((rnd >> 6) & 7) * (5.0/7.0) - 2.5; - - particle_new (pt_grav, part_tex_dot, porg, 1.0, vec3_origin, - vr_data.realtime + 1.5, 67 + (rnd & 3), 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 6; + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } static void -R_WizTrail_ID (const entity_t *ent) +R_WizTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - static int tracercount; - vec3_t old_origin, pvel, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { + vec4f_t pos = start; + while (len > 0) { + static int tracercount; + len -= 3; + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 52 + ((tracercount & 4) << 1), 0); tracercount++; - if (tracercount & 1) { - pvel[0] = 30.0 * vec[1]; - pvel[1] = 30.0 * -vec[0]; - } else { - pvel[0] = 30.0 * -vec[1]; - pvel[1] = 30.0 * vec[0]; - } - pvel[2] = 0.0; - - particle_new (pt_static, part_tex_dot, old_origin, 1.0, pvel, - vr_data.realtime + 0.5, 52 + ((tracercount & 4) << 1), - 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += vec; } } static void -R_FlameTrail_ID (const entity_t *ent) +R_FlameTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - static int tracercount; - vec3_t old_origin, pvel, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { + vec4f_t pos = start; + while (len > 0) { + static int tracercount; + len -= 3; + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 230 + ((tracercount & 4) << 1), 0); tracercount++; - if (tracercount & 1) { - pvel[0] = 30.0 * vec[1]; - pvel[1] = 30.0 * -vec[0]; - } else { - pvel[0] = 30.0 * -vec[1]; - pvel[1] = 30.0 * vec[0]; - } - pvel[2] = 0.0; - - particle_new (pt_static, part_tex_dot, old_origin, 1.0, pvel, - vr_data.realtime + 0.5, 230 + ((tracercount & 4) << 1), - 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + pos += vec; } } static void -R_VoorTrail_ID (const entity_t *ent) +R_VoorTrail_ID (vec4f_t start, vec4f_t end) { - float maxlen; - float dist = 3.0, len = 0.0; - unsigned int rnd; - vec3_t old_origin, porg, subtract, vec; - vec3_t org; - - if (numparticles >= r_maxparticles) + if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - maxlen = VectorNormalize (vec); - VectorScale (vec, maxlen - dist, subtract); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); - while (len < maxlen) { - rnd = mtwist_rand (&mt); - porg[0] = old_origin[0] + ((rnd >> 3) & 15) - 7.5; - porg[1] = old_origin[1] + ((rnd >> 7) & 15) - 7.5; - porg[2] = old_origin[2] + ((rnd >> 11) & 15) - 7.5; - - particle_new (pt_static, part_tex_dot, porg, 1.0, vec3_origin, - vr_data.realtime + 0.3, 9 * 16 + 8 + (rnd & 3), - 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - VectorAdd (old_origin, subtract, old_origin); + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_static, pos + roffs (16), zero, 0.3, + 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } @@ -1599,10 +1346,8 @@ static void draw_qf_particles (void) { byte *at; - int activeparticles, maxparticle, j, vacount; - unsigned k; + int vacount; float minparticledist, scale; - particle_t *part; vec3_t up_scale, right_scale, up_right_scale, down_right_scale; partvert_t *VA; mat4f_t vp_mat; @@ -1634,26 +1379,43 @@ draw_qf_particles (void) minparticledist = DotProduct (r_refdef.viewposition, vpn) + r_particles_nearclip->value; - activeparticles = 0; vacount = 0; VA = particleVertexArray; - maxparticle = -1; - j = 0; - for (k = 0, part = particles; k < numparticles; k++, part++) { + vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; + + unsigned j = 0; + for (unsigned i = 0; i < numparticles; i++) { + particle_t *p = &particles[i]; + partparm_t *parm = &partparams[i]; + + if (p->live <= 0 || p->ramp >= parm->ramp_max + || p->alpha <= 0 || p->scale <= 0) { + continue; + } + const int *ramp = partramps[j]; + if (i > j) { + particles[j] = *p; + partparams[j] = *parm; + partramps[j] = ramp; + } + p = &particles[j]; + parm = &partparams[j]; + j += 1; + // Don't render particles too close to us. // Note, we must still do physics and such on them. - if (!(DotProduct (part->org, vpn) < minparticledist)) { - at = (byte *) &d_8to24table[(byte) part->color]; + if (!(DotProduct (p->pos, vpn) < minparticledist)) { + at = (byte *) &d_8to24table[(byte) p->icolor]; VA[0].color[0] = at[0]; VA[0].color[1] = at[1]; VA[0].color[2] = at[2]; - VA[0].color[3] = part->alpha * 255; + VA[0].color[3] = p->alpha * 255; memcpy (VA[1].color, VA[0].color, sizeof (VA[0].color)); memcpy (VA[2].color, VA[0].color, sizeof (VA[0].color)); memcpy (VA[3].color, VA[0].color, sizeof (VA[0].color)); - switch (part->tex) { + switch (p->tex) { case part_tex_dot: VA[0].texcoord[0] = 0.0; VA[0].texcoord[1] = 0.0; @@ -1686,7 +1448,7 @@ draw_qf_particles (void) break; } - scale = part->scale; + scale = p->scale; VectorScale (vup, scale, up_scale); VectorScale (vright, scale, right_scale); @@ -1694,26 +1456,28 @@ draw_qf_particles (void) VectorAdd (right_scale, up_scale, up_right_scale); VectorSubtract (right_scale, up_scale, down_right_scale); - VectorAdd (part->org, down_right_scale, VA[0].vertex); - VectorSubtract (part->org, up_right_scale, VA[1].vertex); - VectorSubtract (part->org, down_right_scale, VA[2].vertex); - VectorAdd (part->org, up_right_scale, VA[3].vertex); + VectorAdd (p->pos, down_right_scale, VA[0].vertex); + VectorSubtract (p->pos, up_right_scale, VA[1].vertex); + VectorSubtract (p->pos, down_right_scale, VA[2].vertex); + VectorAdd (p->pos, up_right_scale, VA[3].vertex); VA += 4; vacount += 6; } - part->phys (part); - - // LordHavoc: immediate removal of unnecessary particles (must be done - // to ensure compactor below operates properly in all cases) - if (part->die < vr_data.realtime) { - freeparticles[j++] = part; - } else { - maxparticle = k; - activeparticles++; + float dT = vr_data.frametime; + p->pos += dT * p->vel; + p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); + p->ramp += dT * parm->ramp; + p->live -= dT; + p->alpha -= dT * parm->alpha_rate; + p->scale += dT * parm->scale_rate; + if (ramp) { + p->icolor = ramp[(int)p->ramp]; } } + numparticles = j; + qfeglVertexAttribPointer (quake_part.vertex.location, 3, GL_FLOAT, 0, sizeof (partvert_t), &particleVertexArray[0].vertex); @@ -1725,15 +1489,6 @@ draw_qf_particles (void) &particleVertexArray[0].texcoord); qfeglDrawElements (GL_TRIANGLES, vacount, GL_UNSIGNED_SHORT, pVAindices); - k = 0; - while (maxparticle >= activeparticles) { - *freeparticles[k++] = particles[maxparticle--]; - while (maxparticle >= activeparticles && - particles[maxparticle].die <= vr_data.realtime) - maxparticle--; - } - numparticles = activeparticles; - qfeglDepthMask (GL_TRUE); qfeglDisableVertexAttribArray (quake_part.vertex.location); qfeglDisableVertexAttribArray (quake_part.color.location); @@ -1745,10 +1500,8 @@ draw_qf_particles (void) static void draw_id_particles (void) { - int activeparticles, maxparticle, j, vacount; - unsigned k; + int vacount; float minparticledist; - particle_t *part; partvert_t *VA; mat4f_t vp_mat; quat_t fog; @@ -1776,33 +1529,52 @@ draw_id_particles (void) minparticledist = DotProduct (r_refdef.viewposition, vpn) + r_particles_nearclip->value; - activeparticles = 0; vacount = 0; VA = particleVertexArray; - maxparticle = -1; - j = 0; - for (k = 0, part = particles; k < numparticles; k++, part++) { + vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; + + unsigned j = 0; + for (unsigned i = 0; i < numparticles; i++) { + particle_t *p = &particles[i]; + partparm_t *parm = &partparams[i]; + + if (p->live <= 0 || p->ramp >= parm->ramp_max + || p->alpha <= 0 || p->scale <= 0) { + continue; + } + const int *ramp = partramps[j]; + if (i > j) { + particles[j] = *p; + partparams[j] = *parm; + partramps[j] = ramp; + } + p = &particles[j]; + parm = &partparams[j]; + j += 1; + // Don't render particles too close to us. // Note, we must still do physics and such on them. - if (!(DotProduct (part->org, vpn) < minparticledist)) { - VA[0].color[0] = (byte) part->color; - VectorCopy (part->org, VA[0].vertex); + if (!(DotProduct (p->pos, vpn) < minparticledist)) { + VA[0].color[0] = (byte) p->icolor; + VectorCopy (p->pos, VA[0].vertex); VA++; vacount++; } - part->phys (part); - - // LordHavoc: immediate removal of unnecessary particles (must be done - // to ensure compactor below operates properly in all cases) - if (part->die < vr_data.realtime) { - freeparticles[j++] = part; - } else { - maxparticle = k; - activeparticles++; + float dT = vr_data.frametime; + p->pos += dT * p->vel; + p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); + p->ramp += dT * parm->ramp; + p->live -= dT; + p->alpha -= dT * parm->alpha_rate; + p->scale += dT * parm->scale_rate; + if (ramp) { + p->icolor = ramp[(int)p->ramp]; } } + numparticles = j; + qfeglVertexAttribPointer (quake_point.vertex.location, 3, GL_FLOAT, 0, sizeof (partvert_t), &particleVertexArray[0].vertex); @@ -1811,15 +1583,6 @@ draw_id_particles (void) &particleVertexArray[0].color); qfeglDrawArrays (GL_POINTS, 0, vacount); - k = 0; - while (maxparticle >= activeparticles) { - *freeparticles[k++] = particles[maxparticle--]; - while (maxparticle >= activeparticles && - particles[maxparticle].die <= vr_data.realtime) - maxparticle--; - } - numparticles = activeparticles; - qfeglDepthMask (GL_TRUE); qfeglDisableVertexAttribArray (quake_point.vertex.location); qfeglDisableVertexAttribArray (quake_point.color.location); @@ -1840,23 +1603,23 @@ glsl_R_DrawParticles (void) } static void -glsl_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, +glsl_R_Particle_New (ptype_t type, int texnum, vec4f_t org, float scale, + vec4f_t vel, float live, int color, float alpha, float ramp) { if (numparticles >= r_maxparticles) return; - particle_new (type, texnum, org, scale, vel, die, color, alpha, ramp); + particle_new (type, texnum, org, scale, vel, live, color, alpha, ramp); } static void -glsl_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, float die, +glsl_R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, + int org_fuzz, float scale, int vel_fuzz, float live, int color, float alpha, float ramp) { if (numparticles >= r_maxparticles) return; - particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, die, + particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, live, color, alpha, ramp); } diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index d49c224b7..5a610f9f3 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -36,9 +36,11 @@ #include "compat.h" #include "r_internal.h" -unsigned int r_maxparticles, numparticles; -particle_t *active_particles, *free_particles, *particles, **freeparticles; -vec3_t r_pright, r_pup, r_ppn; +unsigned int r_maxparticles, numparticles; +particle_t *particles; +partparm_t *partparams; +const int **partramps; +vec3_t r_pright, r_pup, r_ppn; /* R_MaxParticlesCheck @@ -50,34 +52,30 @@ vec3_t r_pright, r_pup, r_ppn; void R_MaxParticlesCheck (cvar_t *r_particles, cvar_t *r_particles_max) { -/* - Catchall. If the user changed the setting to a number less than zero *or* - if we had a wacky cfg get past the init code check, this will make sure we - don't have problems. Also note that grabbing the var->int_val is IMPORTANT: - Prevents a segfault since if we grabbed the int_val of r_particles_max - we'd sig11 right here at startup. -*/ - if (r_particles && r_particles->int_val) - r_maxparticles = r_particles_max ? r_particles_max->int_val : 0; - else - r_maxparticles = 0; + unsigned maxparticles = 0; + if (r_particles && r_particles->int_val) { + maxparticles = r_particles_max ? r_particles_max->int_val : 0; + } -/* - Be very careful the next time we do something like this. calloc/free are - IMPORTANT and the compiler doesn't know when we do bad things with them. -*/ - if (particles) - free (particles); - if (freeparticles) - free (freeparticles); + if (r_maxparticles == maxparticles) { + return; + } - particles = 0; - freeparticles = 0; + size_t size = sizeof (particle_t) + sizeof (partparm_t) + + sizeof (int *); + + if (particles) { + Sys_Free (particles, r_maxparticles * size); + particles = 0; + partparams = 0; + partramps = 0; + } + r_maxparticles = maxparticles; if (r_maxparticles) { - particles = (particle_t *) calloc (r_maxparticles, sizeof (particle_t)); - freeparticles = (particle_t **) calloc (r_maxparticles, - sizeof (particle_t *)); + particles = Sys_Alloc (r_maxparticles * size); + partparams = (partparm_t *) &particles[r_maxparticles]; + partramps = (const int **) &partparams[r_maxparticles]; } vr_funcs->R_ClearParticles (); @@ -86,226 +84,53 @@ R_MaxParticlesCheck (cvar_t *r_particles, cvar_t *r_particles_max) vr_funcs->R_InitParticles (); } -static int ramp1[8] = { 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61 }; -static int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 }; -static int ramp3[8] = { 0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; - -static inline float -slow_grav (void) -{ - return -vr_data.frametime * vr_data.gravity * 0.0375; -} - -static inline float -grav (void) -{ - return -vr_data.frametime * vr_data.gravity * 0.05; -} - -static inline float -fast_grav (void) -{ - return -vr_data.frametime * vr_data.gravity; -} - -static inline void -add_vel (particle_t *part) -{ - VectorMultAdd (part->org, vr_data.frametime, part->vel, part->org); -} - -static inline void -sub_slowgrav (particle_t *part) -{ - part->vel[2] -= slow_grav (); -} - -static inline void -add_grav (particle_t *part) -{ - part->vel[2] += grav (); -} - -static inline void -sub_grav (particle_t *part) -{ - part->vel[2] -= grav (); -} - -static inline void -add_fastgrav (particle_t *part) -{ - part->vel[2] += fast_grav (); -} - -static inline qboolean -add_ramp (particle_t *part, float time, int max) -{ - part->ramp += vr_data.frametime * time; - if (part->ramp >= max) { - part->die = -1; - return true; - } - return false; -} - -static inline qboolean -fade_alpha (particle_t *part, float time) -{ - part->alpha -= vr_data.frametime * time; - if (part->alpha <= 0.0) { - part->die = -1; - return true; - } - return false; -} - -static void -part_phys_static (particle_t *part) -{ - add_vel (part); -} - -static void -part_phys_grav (particle_t *part) -{ - add_vel (part); - add_grav (part); -} - -static void -part_phys_fire (particle_t *part) -{ - if (add_ramp (part, 5.0, 6)) - return; - add_vel (part); - part->color = ramp3[(int) part->ramp]; - part->alpha = (6.0 - part->ramp) / 6.0; - sub_grav (part); -} - -static void -part_phys_explode (particle_t *part) -{ - if (add_ramp (part, 10.0, 8)) - return; - add_vel (part); - part->color = ramp1[(int) part->ramp]; - VectorMultAdd (part->vel, vr_data.frametime * 4.0, part->vel, part->vel); - add_grav (part); -} - -static void -part_phys_explode2 (particle_t *part) -{ - if (add_ramp (part, 15.0, 8)) - return; - add_vel (part); - part->color = ramp2[(int) part->ramp]; - VectorMultAdd (part->vel, vr_data.frametime, part->vel, part->vel); - add_grav (part); -} - -static void -part_phys_blob (particle_t *part) -{ - add_vel (part); - VectorMultAdd (part->vel, vr_data.frametime * 4.0, part->vel, part->vel); - add_grav (part); -} - -static void -part_phys_blob2 (particle_t *part) -{ - add_vel (part); - part->vel[0] -= part->vel[0] * vr_data.frametime * 4.0; - part->vel[1] -= part->vel[1] * vr_data.frametime * 4.0; - add_grav (part); -} - -static void -part_phys_smoke (particle_t *part) -{ - if (fade_alpha (part, 0.4)) - return; - add_vel (part); - part->scale += vr_data.frametime * 4.0; - //sub_slowgrav (part); -} - -static void -part_phys_smokecloud (particle_t *part) -{ - if (fade_alpha (part, 0.55)) - return; - add_vel (part); - part->scale += vr_data.frametime * 50.0; - sub_slowgrav (part); -} - -static void -part_phys_bloodcloud (particle_t *part) -{ - if (fade_alpha (part, 0.25)) - return; - add_vel (part); - part->scale += vr_data.frametime * 4.0; - add_grav (part); -} - -static void -part_phys_fallfade (particle_t *part) -{ - if (fade_alpha (part, 1.0)) - return; - add_vel (part); - add_fastgrav (part); -} - -static void -part_phys_fallfadespark (particle_t *part) -{ - if (add_ramp (part, 15.0, 8)) - return; - if (fade_alpha (part, 1.0)) - return; - part->color = ramp1[(int) part->ramp]; - add_vel (part); - add_fastgrav (part); -} - -static void -part_phys_flame (particle_t *part) -{ - if (fade_alpha (part, 0.125)) - return; - add_vel (part); - part->scale -= vr_data.frametime * 2.0; -} - -static pt_phys_func part_phys[] = { - part_phys_static, // pt_static - part_phys_grav, // pt_grav - part_phys_grav, // pt_slowgrav - part_phys_fire, // pt_fire - part_phys_explode, // pt_explode - part_phys_explode2, // pt_explode2 - part_phys_blob, // pt_blob - part_phys_blob2, // pt_blob2 - part_phys_smoke, // pt_smoke - part_phys_smokecloud, // pt_smokecloud - part_phys_bloodcloud, // pt_bloodcloud - part_phys_static, // pt_fadespark - part_phys_static, // pt_fadespark2 - part_phys_fallfade, // pt_fallfade - part_phys_fallfadespark,// pt_fallfadespark - part_phys_flame, // pt_flame +static int ramp[] = { + /*ramp1*/ 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61, + /*ramp2*/ 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66, + /*ramp3*/ 0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, }; -pt_phys_func +static partparm_t part_params[] = { + [pt_static] = {{0, 0, 0, 0}, 0, 1, 0, 0}, + [pt_grav] = {{0, 0, 0, 0.05}, 0, 1, 0, 0}, + [pt_slowgrav] = {{0, 0, 0, 0.05}, 0, 1, 0, 0}, + [pt_fire] = {{0, 0, 0, 0.05}, 5, 6, 0, 5./6}, + [pt_explode] = {{4, 4, 4, 0.05}, 10, 8, 0, 0}, + [pt_explode2] = {{1, 1, 1, 0.05}, 15, 8, 0, 0}, + [pt_blob] = {{4, 4, 4, 0.05}, 0, 1, 0, 0}, + [pt_blob2] = {{4, 4, 0, 0.05}, 0, 1, 0, 0}, + [pt_smoke] = {{0, 0, 0, 0}, 0, 1, 4, 0.4}, + [pt_smokecloud] = {{0, 0, 0, 0.0375}, 0, 1, 50, 0.55}, + [pt_bloodcloud] = {{0, 0, 0, 0.05}, 0, 1, 4, 0.25}, + [pt_fadespark] = {{0, 0, 0, 0}, 0, 1, 0, 0}, + [pt_fadespark2] = {{0, 0, 0, 0}, 0, 1, 0, 0}, + [pt_fallfade] = {{0, 0, 0, 1}, 0, 1, 0, 1}, + [pt_fallfadespark] = {{0, 0, 0, 1}, 15, 8, 0, 1}, + [pt_flame] = {{0, 0, 0, 0}, 0, 1, -2, 0.125}, +}; + +static const int *part_ramps[] = { + [pt_fire] = ramp + 2 * 8, // ramp3 + [pt_explode] = ramp + 0 * 8, // ramp1 + [pt_explode2] = ramp + 1 * 8, // ramp2 + [pt_fallfadespark] = ramp + 0 * 8, // ramp1 + [pt_flame] = 0, +}; + +partparm_t R_ParticlePhysics (ptype_t type) { - if (type > pt_flame) + if (type > pt_flame) { Sys_Error ("R_ParticlePhysics: invalid particle type"); - return part_phys[type]; + } + return part_params[type]; +} + +const int * +R_ParticleRamp (ptype_t type) +{ + if (type > pt_flame) { + Sys_Error ("R_ParticleRamp: invalid particle type"); + } + return part_ramps[type]; } diff --git a/libs/video/renderer/sw/d_part.c b/libs/video/renderer/sw/d_part.c index 38de44a09..b8b5b1c82 100644 --- a/libs/video/renderer/sw/d_part.c +++ b/libs/video/renderer/sw/d_part.c @@ -47,7 +47,7 @@ D_DrawParticle (particle_t *pparticle) int i, izi, pix, count, u, v; // transform point - VectorSubtract (pparticle->org, r_origin, local); + VectorSubtract (pparticle->pos, r_origin, local); transformed[0] = DotProduct (local, r_pright); transformed[1] = DotProduct (local, r_pup); @@ -84,7 +84,7 @@ D_DrawParticle (particle_t *pparticle) for (; count; count--, pz += d_zwidth, pdest += screenwidth) { if (pz[0] <= izi) { pz[0] = izi; - pdest[0] = pparticle->color; + pdest[0] = pparticle->icolor; } } break; @@ -94,12 +94,12 @@ D_DrawParticle (particle_t *pparticle) for (; count; count--, pz += d_zwidth, pdest += screenwidth) { if (pz[0] <= izi) { pz[0] = izi; - pdest[0] = pparticle->color; + pdest[0] = pparticle->icolor; } if (pz[1] <= izi) { pz[1] = izi; - pdest[1] = pparticle->color; + pdest[1] = pparticle->icolor; } } break; @@ -109,17 +109,17 @@ D_DrawParticle (particle_t *pparticle) for (; count; count--, pz += d_zwidth, pdest += screenwidth) { if (pz[0] <= izi) { pz[0] = izi; - pdest[0] = pparticle->color; + pdest[0] = pparticle->icolor; } if (pz[1] <= izi) { pz[1] = izi; - pdest[1] = pparticle->color; + pdest[1] = pparticle->icolor; } if (pz[2] <= izi) { pz[2] = izi; - pdest[2] = pparticle->color; + pdest[2] = pparticle->icolor; } } break; @@ -129,22 +129,22 @@ D_DrawParticle (particle_t *pparticle) for (; count; count--, pz += d_zwidth, pdest += screenwidth) { if (pz[0] <= izi) { pz[0] = izi; - pdest[0] = pparticle->color; + pdest[0] = pparticle->icolor; } if (pz[1] <= izi) { pz[1] = izi; - pdest[1] = pparticle->color; + pdest[1] = pparticle->icolor; } if (pz[2] <= izi) { pz[2] = izi; - pdest[2] = pparticle->color; + pdest[2] = pparticle->icolor; } if (pz[3] <= izi) { pz[3] = izi; - pdest[3] = pparticle->color; + pdest[3] = pparticle->icolor; } } break; @@ -155,7 +155,7 @@ D_DrawParticle (particle_t *pparticle) for (i = 0; i < pix; i++) { if (pz[i] <= izi) { pz[i] = izi; - pdest[i] = pparticle->color; + pdest[i] = pparticle->icolor; } } } diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index 8dc268955..ede081f77 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -49,12 +49,57 @@ #include "compat.h" #include "r_internal.h" -static int ramp1[8] = { 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61 }; -//static int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 }; -static int ramp3[8] = { 0x6d, 0x6b, 6, 5, 4, 3 }; - static mtstate_t mt; // private PRNG state +static vec4f_t +roffs (int mod) +{ + vec4f_t offs = { + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + 0 + }; + return offs; +} + +static vec4f_t +tracer_vel (int tracercount, vec4f_t vec) +{ + if (tracercount & 1) { + return (vec4f_t) { vec[1], -vec[0], 0, 0 }; + } else { + return (vec4f_t) { -vec[1], vec[0], 0, 0 }; + } +} + +static void +add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, + float ramp) +{ + if (numparticles >= r_maxparticles) + return; + particle_t *p = &particles[numparticles]; + partparm_t *parm = &partparams[numparticles]; + const int **rampptr = &partramps[numparticles]; + numparticles += 1; + + p->pos = pos; + p->vel = vel; + p->icolor = color; + p->alpha = 1; + p->tex = 0; + p->ramp = ramp; + p->scale = 1; + p->live = live; + + *parm = R_ParticlePhysics (type); + *rampptr = R_ParticleRamp (type); + if (*rampptr) { + p->icolor = (*rampptr) [(int) p->ramp]; + } +} + void R_InitParticles (void) { @@ -64,26 +109,19 @@ R_InitParticles (void) void R_ClearParticles (void) { - unsigned int i; - - free_particles = &particles[0]; - active_particles = NULL; - - for (i = 0; i < r_maxparticles; i++) - particles[i].next = &particles[i + 1]; - if (r_maxparticles) - particles[r_maxparticles - 1].next = NULL; + if (r_maxparticles) { + memset (particles, 0, r_maxparticles * sizeof (*particles)); + } } void R_ReadPointFile_f (void) { QFile *f; - vec3_t org; int c, r; - particle_t *p; const char *name; char *mapname; + vec4f_t zero = {}; mapname = strdup (r_worldentity.renderer.model->path); if (!mapname) @@ -103,6 +141,7 @@ R_ReadPointFile_f (void) c = 0; for (;;) { char buf[64]; + vec4f_t org = { 0, 0, 0, 1 }; Qgets (f, buf, sizeof (buf)); r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); @@ -110,21 +149,11 @@ R_ReadPointFile_f (void) break; c++; - if (!free_particles) { - Sys_Printf ("Not enough free particles\n"); - break; - } - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = 99999; - p->color = (-c) & 15; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); - VectorZero (p->vel); - VectorCopy (org, p->org); + //if (!free_particles) { + // Sys_Printf ("Not enough free particles\n"); + // break; + //} + add_particle (pt_static, org, zero, INFINITY, (-c) & 15, 0); } Qclose (f); @@ -132,324 +161,218 @@ R_ReadPointFile_f (void) } static void -R_ParticleExplosion_QF (const vec3_t org) +R_ParticleExplosion_QF (vec4f_t org) { - int i, j; - particle_t *p; - if (!r_particles->int_val) return; - for (i = 0; i < 1024; i++) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 5; - p->color = ramp1[0]; - p->ramp = mtwist_rand (&mt) & 3; - if (i & 1) - p->type = pt_explode; - else - p->type = pt_explode2; - p->phys = R_ParticlePhysics (p->type); - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); - p->vel[j] = (mtwist_rand (&mt) % 512) - 256; - } + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_explode2 : pt_explode; + add_particle (type, org + roffs (32), roffs (512), 5, + 0, mtwist_rand (&mt) & 3); } } static void -R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) +R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) { - int i, j; int colorMod = 0; - particle_t *p; - for (i=0; i<512; i++) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.3; - p->color = colorStart + (colorMod % colorLength); - colorMod++; - - p->type = pt_blob; - p->phys = R_ParticlePhysics (p->type); - for (j=0 ; j<3 ; j++) { - p->org[j] = org[j] + ((mtwist_rand (&mt)%32)-16); - p->vel[j] = (mtwist_rand (&mt)%512)-256; - } + for (int i=0; i<512; i++) { + add_particle (pt_blob, org + roffs (32), roffs (512), 0.3, + colorStart + (colorMod % colorLength), 0); } } static void -R_BlobExplosion_QF (const vec3_t org) +R_BlobExplosion_QF (vec4f_t org) { - int i, j; - particle_t *p; - if (!r_particles->int_val) return; - for (i = 0; i < 1024; i++) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 1 + (mtwist_rand (&mt) & 8) * 0.05; - - if (i & 1) { - p->type = pt_blob; - p->color = 66 + mtwist_rand (&mt) % 6; - } else { - p->type = pt_blob2; - p->color = 150 + mtwist_rand (&mt) % 6; - } - p->phys = R_ParticlePhysics (p->type); - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); - p->vel[j] = (mtwist_rand (&mt) % 512) - 256; - } + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_blob : pt_blob2; + int color = i & 1 ? 66 : 150; + add_particle (type, org + roffs (32), roffs (512), + color + mtwist_rand (&mt) % 6, + (color & ~7) + (mtwist_rand (&mt) & 7), 0); } } static void -R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, - int count) +R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, int count) { - int i, j; - particle_t *p; - if (!r_particles->int_val) return; - for (i = 0; i < count; i++) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.1 * (mtwist_rand (&mt) % 5); - p->color = (color & ~7) + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((mtwist_rand (&mt) & 15) - 8); - p->vel[j] = dir[j]; // + (mtwist_rand (&mt)%300)-150; - } + for (int i = 0; i < count; i++) { + add_particle (pt_slowgrav, org + roffs (16), + dir/* + roffs (300)*/, + 0.1 * (mtwist_rand (&mt) % 5), + (color & ~7) + (mtwist_rand (&mt) & 7), 0); } } static void -R_SpikeEffect_QF (const vec3_t org) +R_SpikeEffect_QF (vec4f_t org) { - R_RunParticleEffect_QF (org, vec3_origin, 0, 10); + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 0, 10); } static void -R_SuperSpikeEffect_QF (const vec3_t org) +R_SuperSpikeEffect_QF (vec4f_t org) { - R_RunParticleEffect_QF (org, vec3_origin, 0, 20); + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 0, 20); } static void -R_KnightSpikeEffect_QF (const vec3_t org) +R_KnightSpikeEffect_QF (vec4f_t org) { - R_RunParticleEffect_QF (org, vec3_origin, 226, 20); + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 226, 20); } static void -R_WizSpikeEffect_QF (const vec3_t org) +R_WizSpikeEffect_QF (vec4f_t org) { - R_RunParticleEffect_QF (org, vec3_origin, 20, 30); + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 20, 30); } static void -R_BloodPuffEffect_QF (const vec3_t org, int count) +R_BloodPuffEffect_QF (vec4f_t org, int count) { - R_RunParticleEffect_QF (org, vec3_origin, 73, count); + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 73, count); } static void -R_GunshotEffect_QF (const vec3_t org, int count) +R_GunshotEffect_QF (vec4f_t org, int count) { - R_RunParticleEffect_QF (org, vec3_origin, 0, count); + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 0, count); } static void -R_LightningBloodEffect_QF (const vec3_t org) +R_LightningBloodEffect_QF (vec4f_t org) { - R_RunParticleEffect_QF (org, vec3_origin, 225, 50); + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 225, 50); } static void -R_LavaSplash_QF (const vec3_t org) +R_LavaSplash_QF (vec4f_t org) { - int i, j, k; - particle_t *p; - float vel; - vec3_t dir; - if (!r_particles->int_val) return; - for (i = -16; i < 16; i++) - for (j = -16; j < 16; j++) - for (k = 0; k < 1; k++) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 2 + (mtwist_rand (&mt) & 31) * 0.02; - p->color = 224 + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); - - dir[0] = j * 8 + (mtwist_rand (&mt) & 7); - dir[1] = i * 8 + (mtwist_rand (&mt) & 7); - dir[2] = 256; - - p->org[0] = org[0] + dir[0]; - p->org[1] = org[1] + dir[1]; - p->org[2] = org[2] + (mtwist_rand (&mt) & 63); - - VectorNormalize (dir); - vel = 50 + (mtwist_rand (&mt) & 63); - VectorScale (dir, vel, p->vel); - } -} - -static void -R_TeleportSplash_QF (const vec3_t org) -{ - int i, j, k; - particle_t *p; - float vel; - vec3_t dir; - - if (!r_particles->int_val) - return; - - for (i = -16; i < 16; i += 4) - for (j = -16; j < 16; j += 4) - for (k = -24; k < 32; k += 4) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 7) * 0.02; - p->color = 7 + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); - - dir[0] = j * 8; - dir[1] = i * 8; - dir[2] = k * 8; - - p->org[0] = org[0] + i + (mtwist_rand (&mt) & 3); - p->org[1] = org[1] + j + (mtwist_rand (&mt) & 3); - p->org[2] = org[2] + k + (mtwist_rand (&mt) & 3); - - VectorNormalize (dir); - vel = 50 + (mtwist_rand (&mt) & 63); - VectorScale (dir, vel, p->vel); - } -} - -static void -R_DarkFieldParticles_ID (const entity_t *ent) -{ - int i, j, k; - unsigned int rnd; - float vel; - particle_t *p; - vec3_t dir, org; - - if (!r_particles->int_val) - return; - - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - for (i = -16; i < 16; i += 8) { - for (j = -16; j < 16; j += 8) { - for (k = 0; k < 32; k += 8) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - rnd = mtwist_rand (&mt); - - p->die = vr_data.realtime + 0.2 + (rnd & 7) * 0.02; - p->color = 150 + mtwist_rand (&mt) % 6; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); - dir[0] = j * 8; - dir[1] = i * 8; - dir[2] = k * 8; - - p->org[0] = org[0] + i + ((rnd >> 3) & 3); - p->org[1] = org[1] + j + ((rnd >> 5) & 3); - p->org[2] = org[2] + k + ((rnd >> 7) & 3); - - VectorNormalize (dir); - vel = 50 + ((rnd >> 9) & 63); - VectorScale (dir, vel, p->vel); + for (int i = -16; i < 16; i++) { + for (int j = -16; j < 16; j++) { + for (int k = 0; k < 1; k++) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = { + j * 8 + (mtwist_rand (&mt) & 7), + i * 8 + (mtwist_rand (&mt) & 7), + 256, + 0 + }; + vec4f_t offs = { + dir[0], + dir[1], + (mtwist_rand (&mt) & 63), + 0 + }; + dir = normalf (dir); + add_particle (pt_grav, org + offs, vel * dir, + 2 + (mtwist_rand (&mt) & 31) * 0.02, + 224 + (mtwist_rand (&mt) & 7), 0); } } } } -static vec3_t avelocities[NUMVERTEXNORMALS]; +static void +R_TeleportSplash_QF (vec4f_t org) +{ + if (!r_particles->int_val) + return; + + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + for (int k = -24; k < 32; k += 4) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (mtwist_rand (&mt) & 3), + j + (mtwist_rand (&mt) & 3), + k + (mtwist_rand (&mt) & 3), + 0 + }; + add_particle (pt_grav, org + offs, vel * dir, + 0.2 + (mtwist_rand (&mt) & 7) * 0.02, + 7 + (mtwist_rand (&mt) & 7), 0); + } + } + } +} static void -R_EntityParticles_ID (const entity_t *ent) +R_DarkFieldParticles_ID (vec4f_t org) +{ + if (!r_particles->int_val) + return; + + for (int i = -16; i < 16; i += 8) { + for (int j = -16; j < 16; j += 8) { + for (int k = 0; k < 32; k += 8) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 9) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + ((rnd >> 3) & 3), + j + ((rnd >> 5) & 3), + k + ((rnd >> 7) & 3), + 0 + }; + + add_particle (pt_slowgrav, org + offs, vel * dir, + 0.2 + (rnd & 7) * 0.02, + 150 + mtwist_rand (&mt) % 6, 0); + } + } + } +} + +static vec4f_t velocities[NUMVERTEXNORMALS]; +static vec4f_t normals[NUMVERTEXNORMALS] = { +#include "anorms.h" +}; + +static void +R_EntityParticles_ID (vec4f_t org) { int i; float angle, sp, sy, cp, cy; // cr, sr float beamlength = 16.0, dist = 64.0; - particle_t *p; - vec3_t forward; - vec3_t org; if (!r_particles->int_val) return; - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - for (i = 0; i < NUMVERTEXNORMALS; i++) { int k; for (k = 0; k < 3; k++) { - avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + velocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; } } + vec4f_t zero = {}; for (i = 0; i < NUMVERTEXNORMALS; i++) { - angle = vr_data.realtime * avelocities[i][0]; + angle = vr_data.realtime * velocities[i][0]; cy = cos (angle); sy = sin (angle); - angle = vr_data.realtime * avelocities[i][1]; + angle = vr_data.realtime * velocities[i][1]; cp = cos (angle); sp = sin (angle); // Next 3 lines results aren't currently used, may be in future. --Despair @@ -457,355 +380,194 @@ R_EntityParticles_ID (const entity_t *ent) // sr = sin (angle); // cr = cos (angle); - forward[0] = cp * cy; - forward[1] = cp * sy; - forward[2] = -sp; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.01; - p->color = 0x6f; - p->type = pt_explode; - p->phys = R_ParticlePhysics (p->type); - - p->org[0] = org[0] + r_avertexnormals[i][0] * dist + - forward[0] * beamlength; - p->org[1] = org[1] + r_avertexnormals[i][1] * dist + - forward[1] * beamlength; - p->org[2] = org[2] + r_avertexnormals[i][2] * dist + - forward[2] * beamlength; + vec4f_t forward = { cp * cy, cp * sy, -sp, 0 }; + vec4f_t pos = org + normals[i] * dist + forward * beamlength; + //FIXME 0 velocity? + add_particle (pt_explode, pos, zero, 0.01, 0x6f, 0); } } static void -R_RocketTrail_QF (const entity_t *ent) +R_RocketTrail_QF (vec4f_t start, vec4f_t end) { - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorCopy (ent->old_origin, old_origin); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 2; - p->ramp = (mtwist_rand (&mt) & 3); - p->color = ramp3[(int) p->ramp]; - p->type = pt_fire; - p->phys = R_ParticlePhysics (p->type); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3)); + pos += vec; } } static void -R_GrenadeTrail_QF (const entity_t *ent) +R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) { - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 2; - p->ramp = (mtwist_rand (&mt) & 3) + 2; - p->color = ramp3[(int) p->ramp]; - p->type = pt_fire; - p->phys = R_ParticlePhysics (p->type); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3) + 2); + pos += vec; } } static void -R_BloodTrail_QF (const entity_t *ent) +R_BloodTrail_QF (vec4f_t start, vec4f_t end) { - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 2; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); - p->color = 67 + (mtwist_rand (&mt) & 3); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } static void -R_SlightBloodTrail_QF (const entity_t *ent) +R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) { - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 6; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 2; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); - p->color = 67 + (mtwist_rand (&mt) & 3); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } static void -R_WizTrail_QF (const entity_t *ent) +R_WizTrail_QF (vec4f_t start, vec4f_t end) { - float len; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t pos = start; while (len > 0) { static int tracercount; - len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.5; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); - p->color = 52 + ((tracercount & 4) << 1); - + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 52 + ((tracercount & 4) << 1), 0); tracercount++; - - VectorCopy (old_origin, p->org); - if (tracercount & 1) { - p->vel[0] = 30.0 * vec[1]; - p->vel[1] = 30.0 * -vec[0]; - } else { - p->vel[0] = 30.0 * -vec[1]; - p->vel[1] = 30.0 * vec[0]; - } - p->vel[2] = 0.0; - - VectorAdd (old_origin, vec, old_origin); + pos += vec; } } static void -R_FlameTrail_QF (const entity_t *ent) +R_FlameTrail_QF (vec4f_t start, vec4f_t end) { - float len; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t pos = start; while (len > 0) { static int tracercount; - len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.5; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); - p->color = 230 + ((tracercount & 4) << 1); - + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 230 + ((tracercount & 4) << 1), 0); tracercount++; - - VectorCopy (old_origin, p->org); - if (tracercount & 1) { - p->vel[0] = 30 * vec[1]; - p->vel[1] = 30 * -vec[0]; - } else { - p->vel[0] = 30 * -vec[1]; - p->vel[1] = 30 * vec[0]; - } - p->vel[2] = 0.0; - - VectorAdd (old_origin, vec, old_origin); + pos += vec; } } static void -R_VoorTrail_QF (const entity_t *ent) +R_VoorTrail_QF (vec4f_t start, vec4f_t end) { - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 0.3; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); - p->color = 9 * 16 + 8 + (mtwist_rand (&mt) & 3); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) & 15) - 8); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_static, pos + roffs (16), zero, 0.3, + 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } void R_DrawParticles (void) { - particle_t *p, **particle; - VectorScale (vright, xscaleshrink, r_pright); VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); - for (particle = &active_particles; *particle;) { - if ((*particle)->die < vr_data.realtime) { - p = (*particle)->next; - (*particle)->next = free_particles; - free_particles = (*particle); - (*particle) = p; - } else { - p = *particle; - particle = &(*particle)->next; + vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; - D_DrawParticle (p); + unsigned j = 0; + for (unsigned i = 0; i < numparticles; i++) { + particle_t *p = &particles[i]; + partparm_t *parm = &partparams[i]; - p->phys (p); + if (p->live <= 0 || p->ramp >= parm->ramp_max) { + continue; + } + const int *ramp = partramps[j]; + if (i > j) { + particles[j] = *p; + partparams[j] = *parm; + partramps[j] = ramp; + } + p = &particles[j]; + parm = &partparams[j]; + j += 1; + + D_DrawParticle (p); + + float dT = vr_data.frametime; + p->pos += dT * p->vel; + p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); + p->ramp += dT * parm->ramp; + p->live -= dT; + if (ramp) { + p->icolor = ramp[(int)p->ramp]; } } + numparticles = j; } void @@ -819,49 +581,33 @@ r_particles_style_f (cvar_t *var) } static void -R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, float ramp) +R_Particle_New (ptype_t type, int texnum, vec4f_t pos, float scale, + vec4f_t vel, float live, int color, float alpha, float ramp) { - particle_t *p; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorCopy (org, p->org); - p->color = color; - p->tex = texnum; - p->scale = scale; - p->alpha = alpha; - VectorCopy (vel, p->vel); - p->type = type; - p->phys = R_ParticlePhysics (p->type); - p->die = die; - p->ramp = ramp; + add_particle (type, pos, vel, live, color, ramp); } static void -R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, int org_fuzz, - float scale, int vel_fuzz, float die, int color, +R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, int org_fuzz, + float scale, int vel_fuzz, float live, int color, float alpha, float ramp) { float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; int rnd; - vec3_t porg, pvel; + vec4f_t pos, vel; rnd = mtwist_rand (&mt); - porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; - porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; - porg[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; + pos[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; + pos[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; + pos[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; + pos[3] = 1; rnd = mtwist_rand (&mt); - pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; - pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; - pvel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; + vel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; + vel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; + vel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; + vel[3] = 0; - R_Particle_New (type, texnum, porg, scale, pvel, die, color, alpha, ramp); + add_particle (type, pos, vel, live, color, ramp); } static vid_particle_funcs_t particles_QF = { diff --git a/libs/video/renderer/sw32/d_part.c b/libs/video/renderer/sw32/d_part.c index 4b30fc398..8ac57af54 100644 --- a/libs/video/renderer/sw32/d_part.c +++ b/libs/video/renderer/sw32/d_part.c @@ -48,7 +48,7 @@ sw32_D_DrawParticle (particle_t *pparticle) int i, izi, pix, count, u, v; // transform point - VectorSubtract (pparticle->org, r_origin, local); + VectorSubtract (pparticle->pos, r_origin, local); transformed[0] = DotProduct (local, r_pright); transformed[1] = DotProduct (local, r_pup); @@ -84,7 +84,7 @@ sw32_D_DrawParticle (particle_t *pparticle) case 1: { byte *pdest = (byte *) sw32_d_viewbuffer + sw32_d_scantable[v] + u, - pixcolor = pparticle->color; + pixcolor = pparticle->icolor; switch (pix) { case 1: count = 1 << sw32_d_y_aspect_shift; @@ -180,7 +180,7 @@ sw32_D_DrawParticle (particle_t *pparticle) { unsigned short *pdest = (unsigned short *) sw32_d_viewbuffer + sw32_d_scantable[v] + u, - pixcolor = sw32_8to16table[(int) pparticle->color]; + pixcolor = sw32_8to16table[(int) pparticle->icolor]; switch (pix) { case 1: count = 1 << sw32_d_y_aspect_shift; @@ -275,7 +275,7 @@ sw32_D_DrawParticle (particle_t *pparticle) case 4: { int *pdest = (int *) sw32_d_viewbuffer + sw32_d_scantable[v] + u, - pixcolor = d_8to24table[(int) pparticle->color]; + pixcolor = d_8to24table[(int) pparticle->icolor]; switch (pix) { case 1: count = 1 << sw32_d_y_aspect_shift; diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 45e48a9ed..26a9255ed 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -52,12 +52,56 @@ #include "compat.h" #include "r_internal.h" -static int ramp1[8] = { 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61 }; -//static int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 }; -static int ramp3[8] = { 0x6d, 0x6b, 6, 5, 4, 3 }; - static mtstate_t mt; // private PRNG state +static vec4f_t +roffs (int mod) +{ + vec4f_t offs = { + (mtwist_rand (&mt) & mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) & mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) & mod) - 0.5 * (mod - 1), + 0 + }; + return offs; +} + +static vec4f_t +tracer_vel (int tracercount, vec4f_t vec) +{ + if (tracercount & 1) { + return (vec4f_t) { vec[1], -vec[0], 0, 0 }; + } else { + return (vec4f_t) { -vec[1], vec[0], 0, 0 }; + } +} + +static void +add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, + float ramp) +{ + if (numparticles >= r_maxparticles) + return; + particle_t *p = &particles[numparticles]; + partparm_t *parm = &partparams[numparticles]; + const int **rampptr = &partramps[numparticles]; + numparticles += 1; + + p->pos = pos; + p->vel = vel; + p->icolor = color; + p->alpha = 1; + p->tex = 0; + p->ramp = ramp; + p->scale = 1; + p->live = live; + + *parm = R_ParticlePhysics (type); + *rampptr = R_ParticleRamp (type); + if (*rampptr) { + p->icolor = (*rampptr) [(int) p->ramp]; + } +} void sw32_R_InitParticles (void) @@ -68,27 +112,19 @@ sw32_R_InitParticles (void) void sw32_R_ClearParticles (void) { - unsigned int i; - - free_particles = &particles[0]; - active_particles = NULL; - - for (i = 0; i < r_maxparticles; i++) - particles[i].next = &particles[i + 1]; - if (r_maxparticles) - particles[r_maxparticles - 1].next = NULL; + if (r_maxparticles) { + memset (particles, 0, r_maxparticles * sizeof (*particles)); + } } void sw32_R_ReadPointFile_f (void) { QFile *f; - vec3_t org; - int r; - int c; - particle_t *p; + int c, r; const char *name; char *mapname; + vec4f_t zero = {}; mapname = strdup (r_worldentity.renderer.model->path); if (!mapname) @@ -108,6 +144,7 @@ sw32_R_ReadPointFile_f (void) c = 0; for (;;) { char buf[64]; + vec4f_t org = { 0, 0, 0, 1 }; Qgets (f, buf, sizeof (buf)); r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); @@ -115,21 +152,11 @@ sw32_R_ReadPointFile_f (void) break; c++; - if (!free_particles) { - Sys_Printf ("Not enough free particles\n"); - break; - } - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = 99999; - p->color = (-c) & 15; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); - VectorZero (p->vel); - VectorCopy (org, p->org); + //if (!free_particles) { + // Sys_Printf ("Not enough free particles\n"); + // break; + //} + add_particle (pt_static, org, zero, INFINITY, (-c) & 15, 0); } Qclose (f); @@ -137,261 +164,218 @@ sw32_R_ReadPointFile_f (void) } static void -R_ParticleExplosion_QF (const vec3_t org) +R_ParticleExplosion_QF (vec4f_t org) { - int i, j; - particle_t *p; - if (!r_particles->int_val) return; - for (i = 0; i < 1024; i++) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 5; - p->color = ramp1[0]; - p->ramp = mtwist_rand (&mt) & 3; - if (i & 1) { - p->type = pt_explode; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); - p->vel[j] = (mtwist_rand (&mt) % 512) - 256; - } - } else { - p->type = pt_explode2; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); - p->vel[j] = (mtwist_rand (&mt) % 512) - 256; - } - } - p->phys = R_ParticlePhysics (p->type); + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_explode2 : pt_explode; + add_particle (type, org + roffs (32), roffs (512), 5, + 0, mtwist_rand (&mt) & 3); } } static void -R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) +R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) { - int i, j; - particle_t *p; int colorMod = 0; - for (i=0; i<512; i++) - { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.3; - p->color = colorStart + (colorMod % colorLength); - colorMod++; - - p->type = pt_blob; - p->phys = R_ParticlePhysics (p->type); - for (j=0 ; j<3 ; j++) - { - p->org[j] = org[j] + ((mtwist_rand (&mt)%32)-16); - p->vel[j] = (mtwist_rand (&mt)%512)-256; - } + for (int i=0; i<512; i++) { + add_particle (pt_blob, org + roffs (32), roffs (512), 0.3, + colorStart + (colorMod % colorLength), 0); } } static void -R_BlobExplosion_QF (const vec3_t org) +R_BlobExplosion_QF (vec4f_t org) { - int i, j; - particle_t *p; - if (!r_particles->int_val) return; - for (i = 0; i < 1024; i++) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 1 + (mtwist_rand (&mt) & 8) * 0.05; - - if (i & 1) { - p->type = pt_blob; - p->color = 66 + mtwist_rand (&mt) % 6; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); - p->vel[j] = (mtwist_rand (&mt) % 512) - 256; - } - } else { - p->type = pt_blob2; - p->color = 150 + mtwist_rand (&mt) % 6; - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((mtwist_rand (&mt) % 32) - 16); - p->vel[j] = (mtwist_rand (&mt) % 512) - 256; - } - } - p->phys = R_ParticlePhysics (p->type); + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_blob : pt_blob2; + int color = i & 1 ? 66 : 150; + add_particle (type, org + roffs (32), roffs (512), + color + mtwist_rand (&mt) % 6, + (color & ~7) + (mtwist_rand (&mt) & 7), 0); } } static void -R_LavaSplash_QF (const vec3_t org) +R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, int count) { - int i, j, k; - particle_t *p; - float vel; - vec3_t dir; - if (!r_particles->int_val) return; - for (i = -16; i < 16; i++) - for (j = -16; j < 16; j++) - for (k = 0; k < 1; k++) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 2 + (mtwist_rand (&mt) & 31) * 0.02; - p->color = 224 + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); - - dir[0] = j * 8 + (mtwist_rand (&mt) & 7); - dir[1] = i * 8 + (mtwist_rand (&mt) & 7); - dir[2] = 256; - - p->org[0] = org[0] + dir[0]; - p->org[1] = org[1] + dir[1]; - p->org[2] = org[2] + (mtwist_rand (&mt) & 63); - - VectorNormalize (dir); - vel = 50 + (mtwist_rand (&mt) & 63); - VectorScale (dir, vel, p->vel); - } + for (int i = 0; i < count; i++) { + add_particle (pt_slowgrav, org + roffs (16), + dir/* + roffs (300)*/, + 0.1 * (mtwist_rand (&mt) % 5), + (color & ~7) + (mtwist_rand (&mt) & 7), 0); + } } static void -R_TeleportSplash_QF (const vec3_t org) +R_SpikeEffect_QF (vec4f_t org) { - float vel; - int i, j, k; - particle_t *p; - vec3_t dir; + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 0, 10); +} +static void +R_SuperSpikeEffect_QF (vec4f_t org) +{ + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 0, 20); +} + +static void +R_KnightSpikeEffect_QF (vec4f_t org) +{ + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 226, 20); +} + +static void +R_WizSpikeEffect_QF (vec4f_t org) +{ + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 20, 30); +} + +static void +R_BloodPuffEffect_QF (vec4f_t org, int count) +{ + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 73, count); +} + +static void +R_GunshotEffect_QF (vec4f_t org, int count) +{ + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 0, count); +} + +static void +R_LightningBloodEffect_QF (vec4f_t org) +{ + vec4f_t zero = {}; + R_RunParticleEffect_QF (org, zero, 225, 50); +} + +static void +R_LavaSplash_QF (vec4f_t org) +{ if (!r_particles->int_val) return; - for (i = -16; i < 16; i += 4) { - for (j = -16; j < 16; j += 4) { - for (k = -24; k < 32; k += 4) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.2 + (mtwist_rand (&mt) & 7) * 0.02; - p->color = 7 + (mtwist_rand (&mt) & 7); - p->type = pt_grav; - p->phys = R_ParticlePhysics (p->type); - - dir[0] = j * 8; - dir[1] = i * 8; - dir[2] = k * 8; - - p->org[0] = org[0] + i + (mtwist_rand (&mt) & 3); - p->org[1] = org[1] + j + (mtwist_rand (&mt) & 3); - p->org[2] = org[2] + k + (mtwist_rand (&mt) & 3); - - VectorNormalize (dir); - vel = 50 + (mtwist_rand (&mt) & 63); - VectorScale (dir, vel, p->vel); + for (int i = -16; i < 16; i++) { + for (int j = -16; j < 16; j++) { + for (int k = 0; k < 1; k++) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = { + j * 8 + (mtwist_rand (&mt) & 7), + i * 8 + (mtwist_rand (&mt) & 7), + 256, + 0 + }; + vec4f_t offs = { + dir[0], + dir[1], + (mtwist_rand (&mt) & 63), + 0 + }; + dir = normalf (dir); + add_particle (pt_grav, org + offs, vel * dir, + 2 + (mtwist_rand (&mt) & 31) * 0.02, + 224 + (mtwist_rand (&mt) & 7), 0); } } } } static void -R_DarkFieldParticles_ID (const entity_t *ent) +R_TeleportSplash_QF (vec4f_t org) { - int i, j, k; - unsigned int rnd; - float vel; - particle_t *p; - vec3_t dir, org; + if (!r_particles->int_val) + return; - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - for (i = -16; i < 16; i += 8) { - for (j = -16; j < 16; j += 8) { - for (k = 0; k < 32; k += 8) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - rnd = mtwist_rand (&mt); - - p->die = vr_data.realtime + 0.2 + (rnd & 7) * 0.02; - p->color = 150 + mtwist_rand (&mt) % 6; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); - - dir[0] = j * 8; - dir[1] = i * 8; - dir[2] = k * 8; - - p->org[0] = org[0] + i + ((rnd >> 3) & 3); - p->org[1] = org[1] + j + ((rnd >> 5) & 3); - p->org[2] = org[2] + k + ((rnd >> 7) & 3); - - VectorNormalize (dir); - vel = 50 + ((rnd >> 9) & 63); - VectorScale (dir, vel, p->vel); + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + for (int k = -24; k < 32; k += 4) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (mtwist_rand (&mt) & 3), + j + (mtwist_rand (&mt) & 3), + k + (mtwist_rand (&mt) & 3), + 0 + }; + add_particle (pt_grav, org + offs, vel * dir, + 0.2 + (mtwist_rand (&mt) & 7) * 0.02, + 7 + (mtwist_rand (&mt) & 7), 0); } } } } -static vec3_t avelocities[NUMVERTEXNORMALS]; +static void +R_DarkFieldParticles_ID (vec4f_t org) +{ + if (!r_particles->int_val) + return; + + for (int i = -16; i < 16; i += 8) { + for (int j = -16; j < 16; j += 8) { + for (int k = 0; k < 32; k += 8) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 9) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + ((rnd >> 3) & 3), + j + ((rnd >> 5) & 3), + k + ((rnd >> 7) & 3), + 0 + }; + + add_particle (pt_slowgrav, org + offs, vel * dir, + 0.2 + (rnd & 7) * 0.02, + 150 + mtwist_rand (&mt) % 6, 0); + } + } + } +} + +static vec4f_t velocities[NUMVERTEXNORMALS]; +static vec4f_t normals[NUMVERTEXNORMALS] = { +#include "anorms.h" +}; static void -R_EntityParticles_ID (const entity_t *ent) +R_EntityParticles_ID (vec4f_t org) { int i; float angle, sp, sy, cp, cy; // cr, sr float beamlength = 16.0, dist = 64.0; - particle_t *p; - vec3_t forward; - vec3_t org; - VectorCopy (Transform_GetWorldPosition (ent->transform), org); + if (!r_particles->int_val) + return; for (i = 0; i < NUMVERTEXNORMALS; i++) { int k; for (k = 0; k < 3; k++) { - avelocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + velocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; } } + vec4f_t zero = {}; for (i = 0; i < NUMVERTEXNORMALS; i++) { - angle = vr_data.realtime * avelocities[i][0]; + angle = vr_data.realtime * velocities[i][0]; cy = cos (angle); sy = sin (angle); - angle = vr_data.realtime * avelocities[i][1]; + angle = vr_data.realtime * velocities[i][1]; cp = cos (angle); sp = sin (angle); // Next 3 lines results aren't currently used, may be in future. --Despair @@ -399,426 +383,194 @@ R_EntityParticles_ID (const entity_t *ent) // sr = sin (angle); // cr = cos (angle); - forward[0] = cp * cy; - forward[1] = cp * sy; - forward[2] = -sp; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.01; - p->color = 0x6f; - p->type = pt_explode; - p->phys = R_ParticlePhysics (p->type); - - p->org[0] = org[0] + r_avertexnormals[i][0] * dist + - forward[0] * beamlength; - p->org[1] = org[1] + r_avertexnormals[i][1] * dist + - forward[1] * beamlength; - p->org[2] = org[2] + r_avertexnormals[i][2] * dist + - forward[2] * beamlength; + vec4f_t forward = { cp * cy, cp * sy, -sp, 0 }; + vec4f_t pos = org + normals[i] * dist + forward * beamlength; + //FIXME 0 velocity? + add_particle (pt_explode, pos, zero, 0.01, 0x6f, 0); } } static void -R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, - int count) +R_RocketTrail_QF (vec4f_t start, vec4f_t end) { - int i, j; - particle_t *p; - if (!r_particles->int_val) return; - for (i = 0; i < count; i++) { - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.1 * (mtwist_rand (&mt) % 5); - p->color = (color & ~7) + (mtwist_rand (&mt) & 7); - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); - for (j = 0; j < 3; j++) { - p->org[j] = org[j] + ((mtwist_rand (&mt) & 15) - 8); - p->vel[j] = dir[j]; // + (mtwist_rand (&mt)%300)-150; - } - } -} - -static void -R_SpikeEffect_QF (const vec3_t org) -{ - R_RunParticleEffect_QF (org, vec3_origin, 0, 10); -} - -static void -R_SuperSpikeEffect_QF (const vec3_t org) -{ - R_RunParticleEffect_QF (org, vec3_origin, 0, 20); -} - -static void -R_KnightSpikeEffect_QF (const vec3_t org) -{ - R_RunParticleEffect_QF (org, vec3_origin, 226, 20); -} - -static void -R_WizSpikeEffect_QF (const vec3_t org) -{ - R_RunParticleEffect_QF (org, vec3_origin, 20, 30); -} - -static void -R_BloodPuffEffect_QF (const vec3_t org, int count) -{ - R_RunParticleEffect_QF (org, vec3_origin, 73, count); -} - -static void -R_GunshotEffect_QF (const vec3_t org, int count) -{ - R_RunParticleEffect_QF (org, vec3_origin, 0, count); -} - -static void -R_LightningBloodEffect_QF (const vec3_t org) -{ - R_RunParticleEffect_QF (org, vec3_origin, 225, 50); -} - -static void -R_RocketTrail_QF (const entity_t *ent) -{ - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - - if (!r_particles->int_val) - return; - - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, ent->old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 2; - p->ramp = (mtwist_rand (&mt) & 3); - p->color = ramp3[(int) p->ramp]; - p->type = pt_fire; - p->phys = R_ParticlePhysics (p->type); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3)); + pos += vec; } } static void -R_GrenadeTrail_QF (const entity_t *ent) +R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) { - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 2; - p->ramp = (mtwist_rand (&mt) & 3) + 2; - p->color = ramp3[(int) p->ramp]; - p->type = pt_fire; - p->phys = R_ParticlePhysics (p->type); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3) + 2); + pos += vec; } } static void -R_BloodTrail_QF (const entity_t *ent) +R_BloodTrail_QF (vec4f_t start, vec4f_t end) { - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 2; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); - p->color = 67 + (mtwist_rand (&mt) & 3); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } static void -R_SlightBloodTrail_QF (const entity_t *ent) +R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) { - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 6; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 2; - p->type = pt_slowgrav; - p->phys = R_ParticlePhysics (p->type); - p->color = 67 + (mtwist_rand (&mt) & 3); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) % 6) - 3); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } static void -R_WizTrail_QF (const entity_t *ent) +R_WizTrail_QF (vec4f_t start, vec4f_t end) { - float len; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t pos = start; while (len > 0) { static int tracercount; - len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.5; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); - p->color = 52 + ((tracercount & 4) << 1); - + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 52 + ((tracercount & 4) << 1), 0); tracercount++; - - VectorCopy (old_origin, p->org); - if (tracercount & 1) { - p->vel[0] = 30.0 * vec[1]; - p->vel[1] = 30.0 * -vec[0]; - } else { - p->vel[0] = 30.0 * -vec[1]; - p->vel[1] = 30.0 * vec[0]; - } - p->vel[2] = 0.0; - - VectorAdd (old_origin, vec, old_origin); + pos += vec; } } static void -R_FlameTrail_QF (const entity_t *ent) +R_FlameTrail_QF (vec4f_t start, vec4f_t end) { - float len; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t pos = start; while (len > 0) { static int tracercount; - len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->die = vr_data.realtime + 0.5; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); - p->color = 230 + ((tracercount & 4) << 1); - + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 230 + ((tracercount & 4) << 1), 0); tracercount++; - - VectorCopy (old_origin, p->org); - if (tracercount & 1) { - p->vel[0] = 30.0 * vec[1]; - p->vel[1] = 30.0 * -vec[0]; - } else { - p->vel[0] = 30.0 * -vec[1]; - p->vel[1] = 30.0 * vec[0]; - } - p->vel[2] = 0.0; - - VectorAdd (old_origin, vec, old_origin); + pos += vec; } } static void -R_VoorTrail_QF (const entity_t *ent) +R_VoorTrail_QF (vec4f_t start, vec4f_t end) { - float len; - int j; - particle_t *p; - vec3_t old_origin, vec; - vec3_t org; - if (!r_particles->int_val) return; - VectorCopy (ent->old_origin, old_origin); - VectorCopy (Transform_GetWorldPosition (ent->transform), org); - VectorSubtract (org, old_origin, vec); - len = VectorNormalize (vec); + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + vec4f_t zero = {}; + vec4f_t pos = start; while (len > 0) { len -= 3; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorZero (p->vel); - - p->die = vr_data.realtime + 0.3; - p->type = pt_static; - p->phys = R_ParticlePhysics (p->type); - p->color = 9 * 16 + 8 + (mtwist_rand (&mt) & 3); - for (j = 0; j < 3; j++) - p->org[j] = old_origin[j] + ((mtwist_rand (&mt) & 15) - 8); - - VectorAdd (old_origin, vec, old_origin); + add_particle (pt_static, pos + roffs (16), zero, 0.3, + 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 0); + pos += vec; } } void sw32_R_DrawParticles (void) { - particle_t *p, **particle; - - VectorScale (vright, sw32_xscaleshrink, r_pright); - VectorScale (vup, sw32_yscaleshrink, r_pup); + VectorScale (vright, xscaleshrink, r_pright); + VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); - for (particle = &active_particles; *particle;) { - if ((*particle)->die < vr_data.realtime) { - p = (*particle)->next; - (*particle)->next = free_particles; - free_particles = (*particle); - (*particle) = p; - } else { - p = *particle; - particle = &(*particle)->next; + vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; - sw32_D_DrawParticle (p); + unsigned j = 0; + for (unsigned i = 0; i < numparticles; i++) { + particle_t *p = &particles[i]; + partparm_t *parm = &partparams[i]; - p->phys (p); + if (p->live <= 0 || p->ramp >= parm->ramp_max) { + continue; + } + const int *ramp = partramps[j]; + if (i > j) { + particles[j] = *p; + partparams[j] = *parm; + partramps[j] = ramp; + } + p = &particles[j]; + parm = &partparams[j]; + j += 1; + + sw32_D_DrawParticle (p); + + float dT = vr_data.frametime; + p->pos += dT * p->vel; + p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); + p->ramp += dT * parm->ramp; + p->live -= dT; + if (ramp) { + p->icolor = ramp[(int)p->ramp]; } } + numparticles = j; } void @@ -832,50 +584,34 @@ sw32_r_particles_style_f (cvar_t *var) } static void -sw32_R_Particle_New (ptype_t type, int texnum, const vec3_t org, float scale, - const vec3_t vel, float die, int color, float alpha, +sw32_R_Particle_New (ptype_t type, int texnum, vec4f_t pos, float scale, + vec4f_t vel, float live, int color, float alpha, float ramp) { - particle_t *p; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - VectorCopy (org, p->org); - p->color = color; - p->tex = texnum; - p->scale = scale; - p->alpha = alpha; - VectorCopy (vel, p->vel); - p->type = type; - p->phys = R_ParticlePhysics (p->type); - p->die = die; - p->ramp = ramp; + add_particle (type, pos, vel, live, color, ramp); } static void -sw32_R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, - int org_fuzz, float scale, int vel_fuzz, float die, +sw32_R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, + int org_fuzz, float scale, int vel_fuzz, float live, int color, float alpha, float ramp) { float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; int rnd; - vec3_t porg, pvel; + vec4f_t pos, vel; rnd = mtwist_rand (&mt); - porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; - porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; - porg[2] = o_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0 + org[2]; + pos[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; + pos[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; + pos[2] = o_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0 + org[2]; + pos[3] = 1; rnd = mtwist_rand (&mt); - pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; - pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; - pvel[2] = v_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0; + vel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; + vel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; + vel[2] = v_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0; + vel[3] = 0; - sw32_R_Particle_New (type, texnum, porg, scale, pvel, die, color, alpha, ramp); + add_particle (type, pos, vel, live, color, ramp); } static vid_particle_funcs_t particles_QF = { diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index a20e66b25..8c6679ba2 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -67,130 +67,130 @@ Vulkan_InitParticles (vulkan_ctx_t *ctx) } static void -R_RocketTrail_QF (const entity_t *ent) +R_RocketTrail_QF (vec4f_t start, vec4f_t end) { } static void -R_GrenadeTrail_QF (const entity_t *ent) +R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) { } static void -R_BloodTrail_QF (const entity_t *ent) +R_BloodTrail_QF (vec4f_t start, vec4f_t end) { } static void -R_SlightBloodTrail_QF (const entity_t *ent) +R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) { } static void -R_WizTrail_QF (const entity_t *ent) +R_WizTrail_QF (vec4f_t start, vec4f_t end) { } static void -R_FlameTrail_QF (const entity_t *ent) +R_FlameTrail_QF (vec4f_t start, vec4f_t end) { } static void -R_VoorTrail_QF (const entity_t *ent) +R_VoorTrail_QF (vec4f_t start, vec4f_t end) { } static void -R_GlowTrail_QF (const entity_t *ent, int glow_color) +R_GlowTrail_QF (vec4f_t start, vec4f_t end, int glow_color) { } static void -R_RunParticleEffect_QF (const vec3_t org, const vec3_t dir, int color, +R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, int count) { } static void -R_BloodPuffEffect_QF (const vec3_t org, int count) +R_BloodPuffEffect_QF (vec4f_t org, int count) { } static void -R_GunshotEffect_QF (const vec3_t org, int count) +R_GunshotEffect_QF (vec4f_t org, int count) { } static void -R_LightningBloodEffect_QF (const vec3_t org) +R_LightningBloodEffect_QF (vec4f_t org) { } static void -R_SpikeEffect_QF (const vec3_t org) +R_SpikeEffect_QF (vec4f_t org) { } static void -R_KnightSpikeEffect_QF (const vec3_t org) +R_KnightSpikeEffect_QF (vec4f_t org) { } static void -R_SuperSpikeEffect_QF (const vec3_t org) +R_SuperSpikeEffect_QF (vec4f_t org) { } static void -R_WizSpikeEffect_QF (const vec3_t org) +R_WizSpikeEffect_QF (vec4f_t org) { } static void -R_BlobExplosion_QF (const vec3_t org) +R_BlobExplosion_QF (vec4f_t org) { } static void -R_ParticleExplosion_QF (const vec3_t org) +R_ParticleExplosion_QF (vec4f_t org) { } static void -R_ParticleExplosion2_QF (const vec3_t org, int colorStart, int colorLength) +R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) { } static void -R_LavaSplash_QF (const vec3_t org) +R_LavaSplash_QF (vec4f_t org) { } static void -R_TeleportSplash_QF (const vec3_t org) +R_TeleportSplash_QF (vec4f_t org) { } static void -R_DarkFieldParticles_ID (const entity_t *ent) +R_DarkFieldParticles_ID (vec4f_t org) { } static void -R_EntityParticles_ID (const entity_t *ent) +R_EntityParticles_ID (vec4f_t org) { } static void -R_Particle_New (ptype_t type, int texnum, const vec3_t org, - float scale, const vec3_t vel, float die, +R_Particle_New (ptype_t type, int texnum, vec4f_t org, + float scale, vec4f_t vel, float die, int color, float alpha, float ramp) { } static void -R_Particle_NewRandom (ptype_t type, int texnum, const vec3_t org, +R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, int org_fuzz, float scale, int vel_fuzz, float die, int color, float alpha, float ramp) From aacd2575d2ddb74c296a13023a1a554baeec84c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Dec 2021 01:28:37 +0900 Subject: [PATCH 1986/3664] [sw,sw32] Ensure the particle system is initialized This fixes the missing particles (because mtwist_rand was returning 0). --- libs/video/renderer/sw/sw_rmain.c | 1 + libs/video/renderer/sw32/sw32_rmain.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 64a2836b6..93cc58493 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -131,6 +131,7 @@ sw_R_Init (void) #endif R_InitTurb (); + R_InitParticles (); Cmd_AddCommand ("timerefresh", R_TimeRefresh_f, "Tests the current " "refresh rate for the current location"); diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 65d400dad..01a99be25 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -151,6 +151,7 @@ sw32_R_Init (void) sw32_Draw_Init (); SCR_Init (); sw32_R_InitTurb (); + sw32_R_InitParticles (); Cmd_AddCommand ("timerefresh", sw32_R_TimeRefresh_f, "Tests the current " "refresh rate for the current location"); From 43cdca330be98aad7cf93749dba137040ac442b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Dec 2021 08:57:04 +0900 Subject: [PATCH 1987/3664] [client] Add bindings for load and quickload in demos --- libs/client/default_input.plist | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libs/client/default_input.plist b/libs/client/default_input.plist index d06390cd1..765ec9e2c 100644 --- a/libs/client/default_input.plist +++ b/libs/client/default_input.plist @@ -140,6 +140,16 @@ num = 41; binding = toggleconsole; }, + { + imt = imt_demo; + num = 61; + binding = menu_load; + }, + { + imt = imt_demo; + num = 67; + binding = "echo Quickloading...; wait; load quick"; + }, { imt = imt_demo; num = 68; From 2be19046b6dd9e4f844127bc44b1a7049a43c9bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Dec 2021 08:58:35 +0900 Subject: [PATCH 1988/3664] [vulkan] Allow render passes to not have a render pass This may seem a little contradictory, but it's due to the difference between a high level (engine) render pass and a Vulkan render pass object (and quite likely a poor choice in names for the high level object). This is necessary for supporting compute shader dispatches as they cannot be submitted inside a Vulkan render pass. --- libs/video/renderer/vid_render_vulkan.c | 58 +++++++++++++++---------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index b877569d4..912a2c58c 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -157,33 +157,45 @@ vulkan_R_RenderFrame (SCR_Func *scr_funcs) __auto_type rp = vulkan_ctx->renderPasses.a[i]; __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - frame->framebuffer = rp->framebuffers->a[imageIndex]; - renderPassInfo.framebuffer = frame->framebuffer, - renderPassInfo.renderPass = rp->renderpass; - renderPassInfo.clearValueCount = rp->clearValues->size; - renderPassInfo.pClearValues = rp->clearValues->a; + if (rpFrame->renderpass) { + frame->framebuffer = rp->framebuffers->a[imageIndex]; + renderPassInfo.framebuffer = frame->framebuffer, + renderPassInfo.renderPass = rp->renderpass; + renderPassInfo.clearValueCount = rp->clearValues->size; + renderPassInfo.pClearValues = rp->clearValues->a; - dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, - rpFrame->subpassContents); - - for (int j = 0; j < rpFrame->subpassCount; j++) { - __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; - if (cmdSet->size) { - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, - cmdSet->size, cmdSet->a); - } - // reset for next time around - cmdSet->size = 0; - - //Regardless of whether any commands were submitted for this - //subpass, must step through each and every subpass, otherwise - //the attachments won't be transitioned correctly. - if (j < rpFrame->subpassCount - 1) { - dfunc->vkCmdNextSubpass (frame->cmdBuffer, + dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, rpFrame->subpassContents); + + for (int j = 0; j < rpFrame->subpassCount; j++) { + __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; + if (cmdSet->size) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, + cmdSet->size, cmdSet->a); + } + // reset for next time around + cmdSet->size = 0; + + //Regardless of whether any commands were submitted for this + //subpass, must step through each and every subpass, otherwise + //the attachments won't be transitioned correctly. + if (j < rpFrame->subpassCount - 1) { + dfunc->vkCmdNextSubpass (frame->cmdBuffer, + rpFrame->subpassContents); + } + } + dfunc->vkCmdEndRenderPass (frame->cmdBuffer); + } else { + for (int j = 0; j < rpFrame->subpassCount; j++) { + __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; + if (cmdSet->size) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, + cmdSet->size, cmdSet->a); + } + // reset for next time around + cmdSet->size = 0; } } - dfunc->vkCmdEndRenderPass (frame->cmdBuffer); } if (vulkan_ctx->capture_callback) { From 81a5e076aca378c435817b1958588cd72d9315e2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Dec 2021 09:14:11 +0900 Subject: [PATCH 1989/3664] [vulkan] Move render pass array init Having it in Vulkan_Init_Common means the array can be used in more places than just Vulkan_CreateRenderPass (which probably needs a rename). --- libs/video/renderer/vulkan/vulkan_vid_common.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 2e1f57c2b..3d85fcd08 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -203,6 +203,7 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) Vulkan_Init_Cvars (); ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version + DARRAY_INIT (&ctx->renderPasses, 4); } static void @@ -445,9 +446,6 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) rp->draw = renderpass_draw; - if (!ctx->renderPasses.grow) { - DARRAY_INIT (&ctx->renderPasses, 4); - } DARRAY_APPEND (&ctx->renderPasses, rp); qfv_device_t *device = ctx->device; From 8d2791752e0db8d3aec7292f0da4fe8f331cb5d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Dec 2021 13:08:39 +0900 Subject: [PATCH 1990/3664] [particles] Merge particle spawning into client After yesterday's crazy marathon editing all the particles files, and starting to do another big change to them today, I realized that I really do need to merge them down. All the actual spawning is now in the client library (though particle insertion will need to be moved). GLSL particle rendering is semi-broken in that it now does only points (until I come up with a way to select between points and quads (probably a context object, which I need anyway for Vulkan)). --- include/QF/Vulkan/qf_particles.h | 5 +- include/QF/plugin/vid_render.h | 41 - include/QF/render.h | 43 + include/client/particles.h | 74 + include/d_iface.h | 39 - include/r_cvar.h | 5 - include/r_dynamic.h | 6 - libs/client/Makemodule.am | 1 + libs/client/cl_effects.c | 21 +- libs/client/cl_particles.c | 1347 +++++++++++++++++ libs/client/cl_temp_entities.c | 35 +- libs/client/locs.c | 10 +- libs/video/renderer/gl/gl_dyn_part.c | 1299 ---------------- libs/video/renderer/gl/gl_rmain.c | 2 +- libs/video/renderer/gl/gl_rmisc.c | 4 +- libs/video/renderer/gl/namehack.h | 2 - libs/video/renderer/glsl/glsl_main.c | 6 +- libs/video/renderer/glsl/glsl_particles.c | 1300 +--------------- libs/video/renderer/glsl/namehack.h | 2 - libs/video/renderer/r_cvar.c | 3 - libs/video/renderer/r_part.c | 57 +- libs/video/renderer/sw/sw_rmain.c | 3 - libs/video/renderer/sw/sw_rpart.c | 560 ------- libs/video/renderer/sw32/namehack.h | 2 - libs/video/renderer/sw32/sw32_rmain.c | 7 +- libs/video/renderer/sw32/sw32_rpart.c | 561 ------- libs/video/renderer/vid_render_gl.c | 5 - libs/video/renderer/vid_render_glsl.c | 5 - libs/video/renderer/vid_render_sw.c | 5 - libs/video/renderer/vid_render_sw32.c | 5 - libs/video/renderer/vid_render_vulkan.c | 31 +- libs/video/renderer/vulkan/vulkan_main.c | 2 +- libs/video/renderer/vulkan/vulkan_particles.c | 199 --- nq/source/cl_main.c | 2 + qw/source/cl_main.c | 2 + 35 files changed, 1516 insertions(+), 4175 deletions(-) create mode 100644 include/client/particles.h create mode 100644 libs/client/cl_particles.c diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index 45754fc85..52a228299 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -60,10 +60,7 @@ typedef struct particlectx_s { struct cvar_s; struct vulkan_ctx_s;; -void Vulkan_ClearParticles (struct vulkan_ctx_s *ctx); -void Vulkan_InitParticles (struct vulkan_ctx_s *ctx); -void Vulkan_r_easter_eggs_f (struct cvar_s *var, struct vulkan_ctx_s *ctx); -void Vulkan_r_particles_style_f (struct cvar_s *var, struct vulkan_ctx_s *ctx); +struct r_particle_ctx_s *Vulkan_ParticleContext (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_DrawParticles (struct vulkan_ctx_s *ctx); diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 57e72a92f..e3fba0342 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -44,42 +44,6 @@ struct mod_sprite_ctx_s; All video plugins must export these functions */ -typedef struct vid_particle_funcs_s { - void (*R_RocketTrail) (vec4f_t start, vec4f_t end); - void (*R_GrenadeTrail) (vec4f_t start, vec4f_t end); - void (*R_BloodTrail) (vec4f_t start, vec4f_t end); - void (*R_SlightBloodTrail) (vec4f_t start, vec4f_t end); - void (*R_WizTrail) (vec4f_t start, vec4f_t end); - void (*R_FlameTrail) (vec4f_t start, vec4f_t end); - void (*R_VoorTrail) (vec4f_t start, vec4f_t end); - void (*R_GlowTrail) (vec4f_t start, vec4f_t end, int glow_color); - - void (*R_RunParticleEffect) (vec4f_t org, vec4f_t dir, int color, int count); - void (*R_BloodPuffEffect) (vec4f_t org, int count); - void (*R_GunshotEffect) (vec4f_t org, int count); - void (*R_LightningBloodEffect) (vec4f_t org); - void (*R_SpikeEffect) (vec4f_t org); - void (*R_KnightSpikeEffect) (vec4f_t org); - void (*R_SuperSpikeEffect) (vec4f_t org); - void (*R_WizSpikeEffect) (vec4f_t org); - - void (*R_BlobExplosion) (vec4f_t org); - void (*R_ParticleExplosion) (vec4f_t org); - void (*R_ParticleExplosion2) (vec4f_t org, int colorStart, int colorLength); - void (*R_LavaSplash) (vec4f_t org); - void (*R_TeleportSplash) (vec4f_t org); - void (*R_DarkFieldParticles) (vec4f_t org); - void (*R_EntityParticles) (vec4f_t org); - - void (*R_Particle_New) (ptype_t type, int texnum, vec4f_t org, - float scale, vec4f_t vel, float die, - int color, float alpha, float ramp); - void (*R_Particle_NewRandom) (ptype_t type, int texnum, vec4f_t org, - int org_fuzz, float scale, int vel_fuzz, - float die, int color, float alpha, - float ramp); -} vid_particle_funcs_t; - typedef struct vid_model_funcs_s { size_t texture_render_size;// size of renderer specific texture data void (*Mod_LoadLighting) (model_t *mod, bsp_t *bsp); @@ -159,13 +123,8 @@ typedef struct vid_render_funcs_s { void (*R_DecayLights) (double frametime); void (*R_ViewChanged) (void); - void (*R_ClearParticles) (void); - void (*R_InitParticles) (void); void (*SCR_ScreenShot_f) (void); - void (*r_easter_eggs_f) (struct cvar_s *var); - void (*r_particles_style_f) (struct cvar_s *var); - vid_particle_funcs_t *particles; vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/QF/render.h b/include/QF/render.h index b10c6585e..617952ed3 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -54,6 +54,49 @@ typedef enum { pt_flame } ptype_t; +typedef enum { + part_tex_dot, + part_tex_spark, + part_tex_smoke, +} ptextype_t; + +typedef struct particle_s particle_t; + +// !!! if this is changed, it must be changed in d_ifacea.h too !!! +struct particle_s { + vec4f_t pos; + vec4f_t vel; + + union { + struct { + int icolor; + int pad[2]; + float alpha; + }; + vec4f_t color; + }; + + ptextype_t tex; + float ramp; + float scale; + float live; +}; + +typedef struct partparm_s { + vec4f_t drag; // drag[3] is grav scale + float ramp; + float ramp_max; + float scale_rate; + float alpha_rate; +} partparm_t; + +// FIXME these really shouldn't be global, but they speed up particle creation +extern unsigned int r_maxparticles; +extern unsigned int numparticles; +extern struct particle_s *particles; +extern struct partparm_s *partparams; +extern const int **partramps; + extern struct vid_render_funcs_s *r_funcs; extern struct vid_render_data_s *r_data; diff --git a/include/client/particles.h b/include/client/particles.h new file mode 100644 index 000000000..0e499f53b --- /dev/null +++ b/include/client/particles.h @@ -0,0 +1,74 @@ +/* + particles.h + + Client particles handling + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __client_particles_h_ +#define __client_particles_h_ + +#include "QF/render.h" + +typedef struct cl_particle_funcs_s { + void (*RocketTrail) (vec4f_t start, vec4f_t end); + void (*GrenadeTrail) (vec4f_t start, vec4f_t end); + void (*BloodTrail) (vec4f_t start, vec4f_t end); + void (*SlightBloodTrail) (vec4f_t start, vec4f_t end); + void (*WizTrail) (vec4f_t start, vec4f_t end); + void (*FlameTrail) (vec4f_t start, vec4f_t end); + void (*VoorTrail) (vec4f_t start, vec4f_t end); + void (*GlowTrail) (vec4f_t start, vec4f_t end, int glow_color); + + void (*RunParticleEffect) (vec4f_t org, vec4f_t dir, int color, int count); + void (*BloodPuffEffect) (vec4f_t org, int count); + void (*GunshotEffect) (vec4f_t org, int count); + void (*LightningBloodEffect) (vec4f_t org); + void (*SpikeEffect) (vec4f_t org); + void (*KnightSpikeEffect) (vec4f_t org); + void (*SuperSpikeEffect) (vec4f_t org); + void (*WizSpikeEffect) (vec4f_t org); + + void (*BlobExplosion) (vec4f_t org); + void (*ParticleExplosion) (vec4f_t org); + void (*ParticleExplosion2) (vec4f_t org, int colorStart, int colorLength); + void (*LavaSplash) (vec4f_t org); + void (*TeleportSplash) (vec4f_t org); + void (*DarkFieldParticles) (vec4f_t org); + void (*EntityParticles) (vec4f_t org); + + void (*Particle_New) (ptype_t type, int texnum, vec4f_t org, + float scale, vec4f_t vel, float die, + int color, float alpha, float ramp); + void (*Particle_NewRandom) (ptype_t type, int texnum, vec4f_t org, + int org_fuzz, float scale, int vel_fuzz, + float die, int color, float alpha, + float ramp); +} cl_particle_funcs_t; + +extern cl_particle_funcs_t *clp_funcs; +extern float cl_frametime; +extern float cl_realtime; + +void CL_Particles_Init (void); + +#endif // __client_particles_h_ diff --git a/include/d_iface.h b/include/d_iface.h index 873ac2b7b..f4272e508 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -56,45 +56,6 @@ typedef struct float zi; } emitpoint_t; -typedef enum { - part_tex_dot, - part_tex_spark, - part_tex_smoke, -} ptextype_t; - -typedef struct particle_s particle_t; - -// !!! if this is changed, it must be changed in d_ifacea.h too !!! -struct particle_s { - vec4f_t pos; - vec4f_t vel; - - union { - struct { - int icolor; - int pad[2]; - float alpha; - }; - vec4f_t color; - }; - - ptextype_t tex; - float ramp; - float scale; - float live; -}; - -typedef struct partparm_s { - vec4f_t drag; // drag[3] is grav scale - float ramp; - float ramp_max; - float scale_rate; - float alpha_rate; -} partparm_t; - -partparm_t R_ParticlePhysics (ptype_t type) __attribute__((pure)); -const int *R_ParticleRamp (ptype_t type) __attribute__((pure)); - #define PARTICLE_Z_CLIP 8.0 typedef struct polyvert_s { diff --git a/include/r_cvar.h b/include/r_cvar.h index e8a85a679..c8b02f489 100644 --- a/include/r_cvar.h +++ b/include/r_cvar.h @@ -1,9 +1,5 @@ #include "QF/mathlib.h" -extern struct cvar_s *easter_eggs; -extern void r_easter_eggs_f (struct cvar_s *var); -extern void r_particles_style_f (struct cvar_s *var); - extern void gl_overbright_f (struct cvar_s *cvar); extern struct cvar_s *cl_crossx; @@ -80,7 +76,6 @@ extern struct cvar_s *r_numsurfs; extern struct cvar_s *r_particles; extern struct cvar_s *r_particles_max; extern struct cvar_s *r_particles_nearclip; -extern struct cvar_s *r_particles_style; extern struct cvar_s *r_reportedgeout; extern struct cvar_s *r_reportsurfout; extern struct cvar_s *r_shadows; diff --git a/include/r_dynamic.h b/include/r_dynamic.h index 1027879bc..611d2a158 100644 --- a/include/r_dynamic.h +++ b/include/r_dynamic.h @@ -59,10 +59,4 @@ void R_MaxParticlesCheck (struct cvar_s *r_particles, struct cvar_s *r_particles_max); void R_InitSprites (void); -extern unsigned int r_maxparticles; -extern unsigned int numparticles; -extern struct particle_s *particles; -extern struct partparm_s *partparams; -extern const int **partramps; - #endif // _R_DYNAMIC_H diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 24e28397f..0d926b242 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -6,6 +6,7 @@ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_effects.c \ libs/client/cl_entities.c \ libs/client/cl_input.c \ + libs/client/cl_particles.c \ libs/client/cl_temp_entities.c \ libs/client/locs.c \ libs/client/old_keys.c diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index faa451839..f327a1e6d 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -45,6 +45,7 @@ #include "client/entities.h" #include "client/effects.h" +#include "client/particles.h" void CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size, @@ -132,23 +133,21 @@ CL_ModelEffects (entity_t *ent, int num, int glow_color, double time) VectorSet (0.9, 0.7, 0.0, dl->color); dl->color[3] = 0.7; } - r_funcs->particles->R_RocketTrail (old_origin, ent_origin); + clp_funcs->RocketTrail (old_origin, ent_origin); } else if (model->flags & EF_GRENADE) - r_funcs->particles->R_GrenadeTrail (old_origin, ent_origin); + clp_funcs->GrenadeTrail (old_origin, ent_origin); else if (model->flags & EF_GIB) - r_funcs->particles->R_BloodTrail (old_origin, ent_origin); + clp_funcs->BloodTrail (old_origin, ent_origin); else if (model->flags & EF_ZOMGIB) - r_funcs->particles->R_SlightBloodTrail (old_origin, ent_origin); + clp_funcs->SlightBloodTrail (old_origin, ent_origin); else if (model->flags & EF_TRACER) - r_funcs->particles->R_WizTrail (old_origin, ent_origin); + clp_funcs->WizTrail (old_origin, ent_origin); else if (model->flags & EF_TRACER2) - r_funcs->particles->R_FlameTrail (old_origin, ent_origin); + clp_funcs->FlameTrail (old_origin, ent_origin); else if (model->flags & EF_TRACER3) - r_funcs->particles->R_VoorTrail (old_origin, ent_origin); + clp_funcs->VoorTrail (old_origin, ent_origin); else if (model->flags & EF_GLOWTRAIL) - if (r_funcs->particles->R_GlowTrail) - r_funcs->particles->R_GlowTrail (old_origin, ent_origin, - glow_color); + clp_funcs->GlowTrail (old_origin, ent_origin, glow_color); } void @@ -175,7 +174,7 @@ CL_EntityEffects (int num, entity_t *ent, entity_state_t *state, double time) { vec4f_t position = Transform_GetWorldPosition (ent->transform); if (state->effects & EF_BRIGHTFIELD) - r_funcs->particles->R_EntityParticles (position); + clp_funcs->EntityParticles (position); if (state->effects & EF_MUZZLEFLASH) { vec4f_t fv = Transform_Forward (ent->transform); CL_MuzzleFlash (position, fv, 16, num, time); diff --git a/libs/client/cl_particles.c b/libs/client/cl_particles.c new file mode 100644 index 000000000..f13a765f0 --- /dev/null +++ b/libs/client/cl_particles.c @@ -0,0 +1,1347 @@ +/* + cl_particles.c + + OpenGL particle system. + + Copyright (C) 1996-1997 Id Software, Inc. + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include "QF/cmd.h" +#include "QF/cvar.h" +#include "QF/mersenne.h" +#include "QF/qargs.h" +#include "QF/quakefs.h" +#include "QF/render.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "QF/scene/entity.h" + +#include "compat.h" + +#include "client/particles.h" + +float cl_frametime; +float cl_realtime; +cl_particle_funcs_t *clp_funcs; + +static mtstate_t mt; // private PRNG state + +static cvar_t *easter_eggs; +static cvar_t *particles_style; + +static int ramp[] = { + /*ramp1*/ 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61, + /*ramp2*/ 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66, + /*ramp3*/ 0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, +}; + +static partparm_t part_params[] = { + [pt_static] = {{0, 0, 0, 0}, 0, 1, 0, 0}, + [pt_grav] = {{0, 0, 0, 0.05}, 0, 1, 0, 0}, + [pt_slowgrav] = {{0, 0, 0, 0.05}, 0, 1, 0, 0}, + [pt_fire] = {{0, 0, 0, 0.05}, 5, 6, 0, 5./6}, + [pt_explode] = {{4, 4, 4, 0.05}, 10, 8, 0, 0}, + [pt_explode2] = {{1, 1, 1, 0.05}, 15, 8, 0, 0}, + [pt_blob] = {{4, 4, 4, 0.05}, 0, 1, 0, 0}, + [pt_blob2] = {{4, 4, 0, 0.05}, 0, 1, 0, 0}, + [pt_smoke] = {{0, 0, 0, 0}, 0, 1, 4, 0.4}, + [pt_smokecloud] = {{0, 0, 0, 0.0375}, 0, 1, 50, 0.55}, + [pt_bloodcloud] = {{0, 0, 0, 0.05}, 0, 1, 4, 0.25}, + [pt_fadespark] = {{0, 0, 0, 0}, 0, 1, 0, 0}, + [pt_fadespark2] = {{0, 0, 0, 0}, 0, 1, 0, 0}, + [pt_fallfade] = {{0, 0, 0, 1}, 0, 1, 0, 1}, + [pt_fallfadespark] = {{0, 0, 0, 1}, 15, 8, 0, 1}, + [pt_flame] = {{0, 0, 0, 0}, 0, 1, -2, 0.125}, +}; + +static const int *part_ramps[] = { + [pt_fire] = ramp + 2 * 8, // ramp3 + [pt_explode] = ramp + 0 * 8, // ramp1 + [pt_explode2] = ramp + 1 * 8, // ramp2 + [pt_fallfadespark] = ramp + 0 * 8, // ramp1 + [pt_flame] = 0, +}; + +static partparm_t __attribute__((pure)) +particle_params (ptype_t type) +{ + if (type > pt_flame) { + Sys_Error ("particle_params: invalid particle type"); + } + return part_params[type]; +} + +static const int * __attribute__((pure)) +particle_ramp (ptype_t type) +{ + if (type > pt_flame) { + Sys_Error ("particle_ramp: invalid particle type"); + } + return part_ramps[type]; +} + +inline static int +particle_new (ptype_t type, int texnum, vec4f_t pos, float scale, + vec4f_t vel, float live, int color, float alpha, float ramp) +{ + if (numparticles >= r_maxparticles) + return 0; + particle_t *p = &particles[numparticles]; + partparm_t *parm = &partparams[numparticles]; + const int **rampptr = &partramps[numparticles]; + numparticles += 1; + + p->pos = pos; + p->vel = vel; + p->icolor = color; + p->alpha = alpha; + p->tex = texnum; + p->ramp = ramp; + p->scale = scale; + p->live = live; + + *parm = particle_params (type); + *rampptr = particle_ramp (type); + if (*rampptr) { + p->icolor = (*rampptr) [(int) p->ramp]; + } + return 1; +} + +/* + particle_new_random + + note that org_fuzz & vel_fuzz should be ints greater than 0 if you are + going to bother using this function. +*/ +inline static int +particle_new_random (ptype_t type, int texnum, vec4f_t org, int org_fuzz, + float scale, int vel_fuzz, float live, int color, + float alpha, float ramp) +{ + float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; + int rnd; + vec4f_t porg, pvel; + + rnd = mtwist_rand (&mt); + porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; + porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; + porg[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; + porg[3] = 1; + rnd = mtwist_rand (&mt); + pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; + pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; + pvel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; + pvel[3] = 0; + + return particle_new (type, texnum, porg, scale, pvel, live, color, alpha, + ramp); +} + +/* +inline static void +particle_new_veryrandom (ptype_t type, int texnum, vec4f_t org, + int org_fuzz, float scale, int vel_fuzz, float live, + int color, float alpha, float ramp) +{ + vec3_t porg, pvel; + + porg[0] = qfrandom (org_fuzz * 2) - org_fuzz + org[0]; + porg[1] = qfrandom (org_fuzz * 2) - org_fuzz + org[1]; + porg[2] = qfrandom (org_fuzz * 2) - org_fuzz + org[2]; + pvel[0] = qfrandom (vel_fuzz * 2) - vel_fuzz; + pvel[1] = qfrandom (vel_fuzz * 2) - vel_fuzz; + pvel[2] = qfrandom (vel_fuzz * 2) - vel_fuzz; + particle_new (type, texnum, porg, scale, pvel, live, color, alpha, ramp); +} +*/ + +static vec4f_t +roffs (int mod) +{ + vec4f_t offs = { + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), + 0 + }; + return offs; +} + +static vec4f_t +tracer_vel (int tracercount, vec4f_t vec) +{ + if (tracercount & 1) { + return (vec4f_t) { vec[1], -vec[0], 0, 0 }; + } else { + return (vec4f_t) { -vec[1], vec[0], 0, 0 }; + } +} + +static void +add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, + float ramp) +{ + particle_new (type, part_tex_dot, pos, 1, vel, live, color, 1, ramp); +} +/* +void +CL_ClearParticles (void) +{ + numparticles = 0; +} +*/ + + +static void +pointfile_f (void) +{ + const char *name; + char *mapname; + int c; + QFile *f; + + mapname = strdup (r_worldentity.renderer.model->path); + if (!mapname) + Sys_Error ("Can't duplicate mapname!"); + QFS_StripExtension (mapname, mapname); + + name = va (0, "%s.pts", mapname); + free (mapname); + + f = QFS_FOpenFile (name); + if (!f) { + Sys_Printf ("couldn't open %s\n", name); + return; + } + + Sys_MaskPrintf (SYS_dev, "Reading %s...\n", name); + c = 0; + vec4f_t zero = {}; + for (;;) { + char buf[64]; + vec4f_t org = { 0, 0, 0, 1 }; + + Qgets (f, buf, sizeof (buf)); + int r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); + if (r != 3) + break; + c++; + + if (numparticles >= r_maxparticles) { + Sys_MaskPrintf (SYS_dev, "Not enough free particles\n"); + break; + } else { + particle_new (pt_static, part_tex_dot, org, 1.5, zero, + 99999, (-c) & 15, 1.0, 0.0); + } + } + Qclose (f); + Sys_MaskPrintf (SYS_dev, "%i points read\n", c); +} + +static void +CL_ParticleExplosion_QF (vec4f_t org) +{ +// CL_NewExplosion (org); + if (numparticles >= r_maxparticles) + return; + particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, + 5.0, (mtwist_rand (&mt) & 7) + 8, + 0.5 + qfrandom (0.25), 0.0); +} + +static void +CL_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) +{ + unsigned int i, j = 512; + + if (numparticles >= r_maxparticles) + return; + else if (numparticles + j >= r_maxparticles) + j = r_maxparticles - numparticles; + + for (i = 0; i < j; i++) { + particle_new_random (pt_blob, part_tex_dot, org, 16, 2, 256, + 0.3, + colorStart + (i % colorLength), 1.0, 0.0); + } +} + +static void +CL_BlobExplosion_QF (vec4f_t org) +{ + unsigned int i; + unsigned int j = 1024; + + if (numparticles >= r_maxparticles) + return; + else if (numparticles + j >= r_maxparticles) + j = r_maxparticles - numparticles; + + for (i = 0; i < j >> 1; i++) { + particle_new_random (pt_blob, part_tex_dot, org, 12, 2, 256, + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, + 66 + i % 6, 1.0, 0.0); + } + for (i = 0; i < j / 2; i++) { + particle_new_random (pt_blob2, part_tex_dot, org, 12, 2, 256, + 1.0 + (mtwist_rand (&mt) & 7) * 0.05, + 150 + i % 6, 1.0, 0.0); + } +} + +static inline void +CL_RunSparkEffect_QF (vec4f_t org, int count, int ofuzz) +{ + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, ofuzz * 0.08, + zero, 9, 12 + (mtwist_rand (&mt) & 3), + 0.25 + qfrandom (0.125), 0.0); + + if (count > 0) { + int orgfuzz = ofuzz * 3 / 4; + if (orgfuzz < 1) + orgfuzz = 1; + + while (count--) { + int color = mtwist_rand (&mt) & 7; + + particle_new_random (pt_fallfadespark, part_tex_dot, org, orgfuzz, + 0.7, 96, 5.0, 0, 1.0, color); + } + } +} + +static inline void +CL_BloodPuff_QF (vec4f_t org, int count) +{ + vec4f_t zero = {}; + particle_new (pt_bloodcloud, part_tex_smoke, org, count / 5, zero, + 99.0, 70 + (mtwist_rand (&mt) & 3), 0.5, 0.0); +} + +static void +CL_BloodPuffEffect_QF (vec4f_t org, int count) +{ + CL_BloodPuff_QF (org, count); +} + +static void +CL_GunshotEffect_QF (vec4f_t org, int count) +{ + int scale = 16; + + scale += count / 15; + CL_RunSparkEffect_QF (org, count >> 1, scale); +} + +static void +CL_LightningBloodEffect_QF (vec4f_t org) +{ + CL_BloodPuff_QF (org, 50); + + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, 3.0, zero, + 9.0, 12 + (mtwist_rand (&mt) & 3), + 0.25 + qfrandom (0.125), 0.0); + + for (int count = 7; count-- > 0; ) { + particle_new_random (pt_fallfade, part_tex_spark, org, 12, 2.0, 128, + 5.0, 244 + (count % 3), 1.0, 0.0); + } +} + +static void +CL_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, int count) +{ + float scale = pow (count, 0.23); + + for (int i = 0; i < count; i++) { + int rnd = mtwist_rand (&mt); + + // Note that ParseParticleEffect handles (dir * 15) + particle_new (pt_grav, part_tex_dot, org + scale * roffs (16), 1.5, + dir, 0.1 * (i % 5), + (color & ~7) + (rnd & 7), 1.0, 0.0); + } +} + +static void +CL_SpikeEffect_QF (vec4f_t org) +{ + CL_RunSparkEffect_QF (org, 5, 8); +} + +static void +CL_SuperSpikeEffect_QF (vec4f_t org) +{ + CL_RunSparkEffect_QF (org, 10, 8); +} + +static void +CL_KnightSpikeEffect_QF (vec4f_t org) +{ + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, 1.0, zero, + 9.0, 234, 0.25 + qfrandom (0.125), 0.0); + + for (int count = 10; count-- > 0; ) { + particle_new_random (pt_fallfade, part_tex_dot, org, 6, 0.7, 96, + 5.0, 234, 1.0, 0.0); + } +} + +static void +CL_WizSpikeEffect_QF (vec4f_t org) +{ + vec4f_t zero = {}; + particle_new (pt_smokecloud, part_tex_smoke, org, 2.0, zero, + 9.0, 63, 0.25 + qfrandom (0.125), 0.0); + + for (int count = 15; count-- > 0; ) { + particle_new_random (pt_fallfade, part_tex_dot, org, 12, 0.7, 96, + 5.0, 63, 1.0, 0.0); + } +} + +static void +CL_LavaSplash_QF (vec4f_t org) +{ + for (int i = -16; i < 16; i++) { + for (int j = -16; j < 16; j++) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50.0 + 0.5 * (mtwist_rand (&mt) & 127); + vec4f_t dir = { + j * 8 + (rnd & 7), + i * 8 + ((rnd >> 6) & 7), + 256, + 0 + }; + vec4f_t offs = { dir[0], dir[1], ((rnd >> 9) & 63), 0 }; + dir = normalf (dir); + particle_new (pt_grav, part_tex_dot, org + offs, 3, vel * dir, + 2.0 + ((rnd >> 7) & 31) * 0.02, + 224 + ((rnd >> 12) & 7), 0.75, 0.0); + } + } +} + +static void +CL_TeleportSplash_QF (vec4f_t org) +{ + for (int k = -24; k < 32; k += 4) { + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 6) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (rnd & 3), + j + ((rnd >> 2) & 3), + k + ((rnd >> 4) & 3), + 0 + }; + particle_new (pt_grav, part_tex_spark, org + offs, 0.6, + vel * dir, + (0.2 + (mtwist_rand (&mt) & 15) * 0.01), + (7 + ((rnd >> 12) & 7)), 1.0, 0.0); + } + } + } +} + +static void +CL_RocketTrail_QF (vec4f_t start, vec4f_t end) +{ + if (numparticles >= r_maxparticles) + return; + + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + float pscale = 1.5 + qfrandom (1.5); + + while (len < maxlen) { + float pscalenext = 1.5 + qfrandom (1.5); + float dist = (pscale + pscalenext) * 3.0; + float percent = len * origlen; + + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, + 12 + (mtwist_rand (&mt) & 3), + 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); + if (numparticles >= r_maxparticles) + break; + len += dist; + pos += step; + pscale = pscalenext; + } +} + +static void +CL_GrenadeTrail_QF (vec4f_t start, vec4f_t end) +{ + if (numparticles >= r_maxparticles) + return; + + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + float pscale = 6.0 + qfrandom (7.0); + + while (len < maxlen) { + float pscalenext = 6.0 + qfrandom (7.0); + float dist = (pscale + pscalenext) * 2.0; + float percent = len * origlen; + + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, + 1 + (mtwist_rand (&mt) & 3), + 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); + if (numparticles >= r_maxparticles) + break; + len += dist; + pos += step; + pscale = pscalenext; + } +} + +static void +CL_BloodTrail_QF (vec4f_t start, vec4f_t end) +{ + if (numparticles >= r_maxparticles) + return; + + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t pos = start; + float pscale = 5.0 + qfrandom (10.0); + + while (len < maxlen) { + float pscalenext = 5.0 + qfrandom (10.0); + float dist = (pscale + pscalenext) * 1.5; + float percent = len * origlen; + vec4f_t vel = roffs (24); + vel[2] -= percent * 40; + + particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, + 2.0 - percent * 2.0, + 68 + (mtwist_rand (&mt) & 3), 1.0, 0.0); + if (numparticles >= r_maxparticles) + break; + len += dist; + pos += step; + pscale = pscalenext; + } +} + +static void +CL_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) +{ + if (numparticles >= r_maxparticles) + return; + + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + vec4f_t step = (maxlen - 3) * vec; + + float len = 0; + vec4f_t pos = start; + float pscale = 1.5 + qfrandom (7.5); + while (len < maxlen) { + float pscalenext = 1.5 + qfrandom (7.5); + float dist = (pscale + pscalenext) * 1.5; + float percent = len * origlen; + vec4f_t vel = roffs (12); + vel[2] -= percent * 40; + + particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, + 1.5 - percent * 1.5, + 68 + (mtwist_rand (&mt) & 3), 0.75, 0.0); + if (numparticles >= r_maxparticles) + break; + len += dist; + pos += step; + pscale = pscalenext; + } +} + +static void +CL_WizTrail_QF (vec4f_t start, vec4f_t end) +{ + float dist = 3.0; + + if (numparticles >= r_maxparticles) + return; + + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t pos = start; + while (len < maxlen) { + static int tracercount; + float percent = len * origlen; + + particle_new (pt_flame, part_tex_smoke, pos, + 2.0 + qfrandom (1.0) - percent * 2.0, + 30 * tracer_vel (tracercount++, vec), + 0.5 - percent * 0.5, + 52 + (mtwist_rand (&mt) & 4), 1.0 - percent * 0.125, 0.0); + if (numparticles >= r_maxparticles) + break; + len += dist; + pos += step; + } +} + +static void +CL_FlameTrail_QF (vec4f_t start, vec4f_t end) +{ + float dist = 3.0; + + if (numparticles >= r_maxparticles) + return; + + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t pos = start; + while (len < maxlen) { + static int tracercount; + float percent = len * origlen; + + particle_new (pt_flame, part_tex_smoke, pos, + 2.0 + qfrandom (1.0) - percent * 2.0, + 30 * tracer_vel (tracercount++, vec), + 0.5 - percent * 0.5, 234, + 1.0 - percent * 0.125, 0.0); + len += dist; + pos += step; + } +} + +static void +CL_VoorTrail_QF (vec4f_t start, vec4f_t end) +{ + float dist = 3.0; + + if (numparticles >= r_maxparticles) + return; + + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + while (len < maxlen) { + float percent = len * origlen; + + particle_new (pt_static, part_tex_dot, pos + roffs (16), + 1.0 + qfrandom (1.0), + zero, 0.3 - percent * 0.3, + 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 1.0, 0.0); + len += dist; + pos += step; + } +} + +static void +CL_GlowTrail_QF (vec4f_t start, vec4f_t end, int glow_color) +{ + float dist = 3.0; + + if (numparticles >= r_maxparticles) + return; + + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + vec4f_t step = (maxlen - dist) * vec; + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + while (len < maxlen) { + float percent = len * origlen; + + particle_new (pt_smoke, part_tex_dot, pos + roffs (5), 1.0, zero, + 2.0 - percent * 0.2, glow_color, 1.0, 0.0); + if (numparticles >= r_maxparticles) + break; + len += dist; + pos += step; + } +} + +static void +CL_ParticleExplosion_EE (vec4f_t org) +{ +/* + CL_NewExplosion (org); +*/ + if (numparticles >= r_maxparticles) + return; + particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, + 5.0, mtwist_rand (&mt) & 255, + 0.5 + qfrandom (0.25), 0.0); +} + +static void +CL_TeleportSplash_EE (vec4f_t org) +{ + for (int k = -24; k < 32; k += 4) { + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 6) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (rnd & 3), + j + ((rnd >> 2) & 3), + k + ((rnd >> 4) & 3), + 0 + }; + particle_new (pt_grav, part_tex_spark, org + offs, 0.6, + vel * dir, + (0.2 + (mtwist_rand (&mt) & 15) * 0.01), + qfrandom (1.0), 1.0, 0.0); + } + } + } +} + +static void +CL_RocketTrail_EE (vec4f_t start, vec4f_t end) +{ + if (numparticles >= r_maxparticles) + return; + + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + float pscale = 1.5 + qfrandom (1.5); + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + while (len < maxlen) { + float pscalenext = 1.5 + qfrandom (1.5); + float dist = (pscale + pscalenext) * 3.0; + float percent = len * origlen; + + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, + mtwist_rand (&mt) & 255, + 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); + if (numparticles >= r_maxparticles) + break; + len += dist; + pos += len * vec; + pscale = pscalenext; + } +} + +static void +CL_GrenadeTrail_EE (vec4f_t start, vec4f_t end) +{ + vec4f_t vec = end - start; + float maxlen = magnitudef (vec)[0]; + vec = normalf (vec); + + float origlen = cl_frametime / maxlen; + float pscale = 6.0 + qfrandom (7.0); + + float len = 0; + vec4f_t zero = {}; + vec4f_t pos = start; + while (len < maxlen) { + float pscalenext = 6.0 + qfrandom (7.0); + float dist = (pscale + pscalenext) * 2.0; + float percent = len * origlen; + + particle_new (pt_smoke, part_tex_smoke, pos, + pscale + percent * 4.0, zero, + 2.0 - percent * 2.0, + mtwist_rand (&mt) & 255, + 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); + len += dist; + pos += len * vec; + pscale = pscalenext; + } +} + +static void +CL_ParticleExplosion_ID (vec4f_t org) +{ + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_explode2 : pt_explode; + add_particle (type, org + roffs (32), roffs (512), 5, + 0, mtwist_rand (&mt) & 3); + } +} + +static void +CL_BlobExplosion_ID (vec4f_t org) +{ + for (int i = 0; i < 1024; i++) { + ptype_t type = i & 1 ? pt_blob : pt_blob2; + int color = i & 1 ? 66 : 150; + add_particle (type, org + roffs (32), roffs (512), + color + mtwist_rand (&mt) % 6, + (color & ~7) + (mtwist_rand (&mt) & 7), 0); + } +} + +static inline void // FIXME: inline? +CL_RunParticleEffect_ID (vec4f_t org, vec4f_t dir, int color, int count) +{ + for (int i = 0; i < count; i++) { + add_particle (pt_slowgrav, org + roffs (16), + dir/* + roffs (300)*/, + 0.1 * (mtwist_rand (&mt) % 5), + (color & ~7) + (mtwist_rand (&mt) & 7), 0); + } +} + +static void +CL_BloodPuffEffect_ID (vec4f_t org, int count) +{ + vec4f_t zero = {}; + CL_RunParticleEffect_ID (org, zero, 73, count); +} + +static void +CL_GunshotEffect_ID (vec4f_t org, int count) +{ + vec4f_t zero = {}; + CL_RunParticleEffect_ID (org, zero, 0, count); +} + +static void +CL_LightningBloodEffect_ID (vec4f_t org) +{ + vec4f_t zero = {}; + CL_RunParticleEffect_ID (org, zero, 225, 50); +} + +static void +CL_SpikeEffect_ID (vec4f_t org) +{ + vec4f_t zero = {}; + CL_RunParticleEffect_ID (org, zero, 0, 10); +} + +static void +CL_SuperSpikeEffect_ID (vec4f_t org) +{ + vec4f_t zero = {}; + CL_RunParticleEffect_ID (org, zero, 0, 20); +} + +static void +CL_KnightSpikeEffect_ID (vec4f_t org) +{ + vec4f_t zero = {}; + CL_RunParticleEffect_ID (org, zero, 226, 20); +} + +static void +CL_WizSpikeEffect_ID (vec4f_t org) +{ + vec4f_t zero = {}; + CL_RunParticleEffect_ID (org, zero, 20, 30); +} + +static void +CL_LavaSplash_ID (vec4f_t org) +{ + for (int i = -16; i < 16; i++) { + for (int j = -16; j < 16; j++) { + for (int k = 0; k < 1; k++) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = { + j * 8 + (mtwist_rand (&mt) & 7), + i * 8 + (mtwist_rand (&mt) & 7), + 256, + 0 + }; + vec4f_t offs = { + dir[0], + dir[1], + (mtwist_rand (&mt) & 63), + 0 + }; + dir = normalf (dir); + add_particle (pt_grav, org + offs, vel * dir, + 2 + (mtwist_rand (&mt) & 31) * 0.02, + 224 + (mtwist_rand (&mt) & 7), 0); + } + } + } +} + +static void +CL_TeleportSplash_ID (vec4f_t org) +{ + for (int i = -16; i < 16; i += 4) { + for (int j = -16; j < 16; j += 4) { + for (int k = -24; k < 32; k += 4) { + float vel = 50 + (mtwist_rand (&mt) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + (mtwist_rand (&mt) & 3), + j + (mtwist_rand (&mt) & 3), + k + (mtwist_rand (&mt) & 3), + 0 + }; + add_particle (pt_grav, org + offs, vel * dir, + 0.2 + (mtwist_rand (&mt) & 7) * 0.02, + 7 + (mtwist_rand (&mt) & 7), 0); + } + } + } +} + +static void +CL_DarkFieldParticles_ID (vec4f_t org) +{ + for (int i = -16; i < 16; i += 8) { + for (int j = -16; j < 16; j += 8) { + for (int k = 0; k < 32; k += 8) { + uint32_t rnd = mtwist_rand (&mt); + float vel = 50 + ((rnd >> 9) & 63); + vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); + vec4f_t offs = { + i + ((rnd >> 3) & 3), + j + ((rnd >> 5) & 3), + k + ((rnd >> 7) & 3), + 0 + }; + + add_particle (pt_slowgrav, org + offs, vel * dir, + 0.2 + (rnd & 7) * 0.02, + 150 + mtwist_rand (&mt) % 6, 0); + } + } + } +} + +#define num_normals (int)(sizeof (normals) / sizeof (normals[0])) +static vec4f_t normals[] = { +#include "anorms.h" +}; +static vec4f_t velocities[num_normals]; + +static void +CL_EntityParticles_ID (vec4f_t org) +{ + float angle, sp, sy, cp, cy; // cr, sr + float beamlength = 16.0, dist = 64.0; + + for (int i = 0; i < num_normals; i++) { + int k; + for (k = 0; k < 3; k++) { + velocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; + } + } + + vec4f_t zero = {}; + for (int i = 0; i < num_normals; i++) { + angle = cl_realtime * velocities[i][0]; + cy = cos (angle); + sy = sin (angle); + angle = cl_realtime * velocities[i][1]; + cp = cos (angle); + sp = sin (angle); +// Next 3 lines results aren't currently used, may be in future. --Despair +// angle = cl_realtime * avelocities[i][2]; +// sr = sin (angle); +// cr = cos (angle); + + vec4f_t forward = { cp * cy, cp * sy, -sp, 0 }; + vec4f_t pos = org + normals[i] * dist + forward * beamlength; + //FIXME 0 velocity? + add_particle (pt_explode, pos, zero, 0.01, 0x6f, 0); + } +} + +static void +CL_RocketTrail_ID (vec4f_t start, vec4f_t end) +{ + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3)); + pos += vec; + } +} + +static void +CL_GrenadeTrail_ID (vec4f_t start, vec4f_t end) +{ + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_fire, pos + roffs (6), zero, 2, + 0, (mtwist_rand (&mt) & 3) + 2); + pos += vec; + } +} + +static void +CL_BloodTrail_ID (vec4f_t start, vec4f_t end) +{ + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; + } +} + +static void +CL_SlightBloodTrail_ID (vec4f_t start, vec4f_t end) +{ + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 6; + add_particle (pt_slowgrav, pos + roffs (6), zero, 2, + 67 + (mtwist_rand (&mt) & 3), 0); + pos += vec; + } +} + +static void +CL_WizTrail_ID (vec4f_t start, vec4f_t end) +{ + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + + vec4f_t pos = start; + while (len > 0) { + static int tracercount; + len -= 3; + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 52 + ((tracercount & 4) << 1), 0); + tracercount++; + pos += vec; + } +} + +static void +CL_FlameTrail_ID (vec4f_t start, vec4f_t end) +{ + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + + vec4f_t pos = start; + while (len > 0) { + static int tracercount; + len -= 3; + add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, + 230 + ((tracercount & 4) << 1), 0); + tracercount++; + pos += vec; + } +} + +static void +CL_VoorTrail_ID (vec4f_t start, vec4f_t end) +{ + vec4f_t vec = end - start; + float len = magnitudef (vec)[0]; + vec = normalf (vec); + + vec4f_t zero = {}; + vec4f_t pos = start; + while (len > 0) { + len -= 3; + add_particle (pt_static, pos + roffs (16), zero, 0.3, + 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 0); + pos += vec; + } +} + +static void +CL_Particle_New (ptype_t type, int texnum, vec4f_t org, float scale, + vec4f_t vel, float live, int color, float alpha, + float ramp) +{ + if (numparticles >= r_maxparticles) + return; + particle_new (type, texnum, org, scale, vel, live, color, alpha, ramp); +} + +static void +CL_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, + int org_fuzz, float scale, int vel_fuzz, float live, + int color, float alpha, float ramp) +{ + if (numparticles >= r_maxparticles) + return; + particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, live, + color, alpha, ramp); +} + +static cl_particle_funcs_t particles_QF = { + CL_RocketTrail_QF, + CL_GrenadeTrail_QF, + CL_BloodTrail_QF, + CL_SlightBloodTrail_QF, + CL_WizTrail_QF, + CL_FlameTrail_QF, + CL_VoorTrail_QF, + CL_GlowTrail_QF, + CL_RunParticleEffect_QF, + CL_BloodPuffEffect_QF, + CL_GunshotEffect_QF, + CL_LightningBloodEffect_QF, + CL_SpikeEffect_QF, + CL_KnightSpikeEffect_QF, + CL_SuperSpikeEffect_QF, + CL_WizSpikeEffect_QF, + CL_BlobExplosion_QF, + CL_ParticleExplosion_QF, + CL_ParticleExplosion2_QF, + CL_LavaSplash_QF, + CL_TeleportSplash_QF, + CL_DarkFieldParticles_ID, + CL_EntityParticles_ID, + CL_Particle_New, + CL_Particle_NewRandom, +}; + +static cl_particle_funcs_t particles_ID = { + CL_RocketTrail_ID, + CL_GrenadeTrail_ID, + CL_BloodTrail_ID, + CL_SlightBloodTrail_ID, + CL_WizTrail_ID, + CL_FlameTrail_ID, + CL_VoorTrail_ID, + CL_GlowTrail_QF, + CL_RunParticleEffect_ID, + CL_BloodPuffEffect_ID, + CL_GunshotEffect_ID, + CL_LightningBloodEffect_ID, + CL_SpikeEffect_ID, + CL_KnightSpikeEffect_ID, + CL_SuperSpikeEffect_ID, + CL_WizSpikeEffect_ID, + CL_BlobExplosion_ID, + CL_ParticleExplosion_ID, + CL_ParticleExplosion2_QF, + CL_LavaSplash_ID, + CL_TeleportSplash_ID, + CL_DarkFieldParticles_ID, + CL_EntityParticles_ID, + CL_Particle_New, + CL_Particle_NewRandom, +}; + +static cl_particle_funcs_t particles_QF_egg = { + CL_RocketTrail_EE, + CL_GrenadeTrail_EE, + CL_BloodTrail_QF, + CL_SlightBloodTrail_QF, + CL_WizTrail_QF, + CL_FlameTrail_QF, + CL_VoorTrail_QF, + CL_GlowTrail_QF, + CL_RunParticleEffect_QF, + CL_BloodPuffEffect_QF, + CL_GunshotEffect_QF, + CL_LightningBloodEffect_QF, + CL_SpikeEffect_QF, + CL_KnightSpikeEffect_QF, + CL_SuperSpikeEffect_QF, + CL_WizSpikeEffect_QF, + CL_BlobExplosion_QF, + CL_ParticleExplosion_EE, + CL_ParticleExplosion2_QF, + CL_LavaSplash_QF, + CL_TeleportSplash_EE, + CL_DarkFieldParticles_ID, + CL_EntityParticles_ID, + CL_Particle_New, + CL_Particle_NewRandom, +}; + +static cl_particle_funcs_t particles_ID_egg = { + CL_RocketTrail_EE, + CL_GrenadeTrail_EE, + CL_BloodTrail_ID, + CL_SlightBloodTrail_ID, + CL_WizTrail_ID, + CL_FlameTrail_ID, + CL_VoorTrail_ID, + CL_GlowTrail_QF, + CL_RunParticleEffect_ID, + CL_BloodPuffEffect_ID, + CL_GunshotEffect_ID, + CL_LightningBloodEffect_ID, + CL_SpikeEffect_ID, + CL_KnightSpikeEffect_ID, + CL_SuperSpikeEffect_ID, + CL_WizSpikeEffect_ID, + CL_BlobExplosion_ID, + CL_ParticleExplosion_EE, + CL_ParticleExplosion2_QF, + CL_LavaSplash_ID, + CL_TeleportSplash_EE, + CL_DarkFieldParticles_ID, + CL_EntityParticles_ID, + CL_Particle_New, + CL_Particle_NewRandom, +}; + +static void +easter_eggs_f (cvar_t *var) +{ + if (easter_eggs) { + if (easter_eggs->int_val) { + if (particles_style->int_val) { + clp_funcs = &particles_QF_egg; + } else { + clp_funcs = &particles_ID_egg; + } + } else if (particles_style) { + if (particles_style->int_val) { + clp_funcs = &particles_QF; + } else { + clp_funcs = &particles_ID; + } + } + } +} + +static void +particles_style_f (cvar_t *var) +{ + easter_eggs_f (easter_eggs); +} + +static void +CL_ParticleFunctionInit (void) +{ + particles_style_f (particles_style); + easter_eggs_f (easter_eggs); +} + +/* + */ +void +CL_Particles_Init (void) +{ + mtwist_seed (&mt, 0xdeadbeef); + Cmd_AddCommand ("pointfile", pointfile_f, + "Load a pointfile to determine map leaks."); + easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, easter_eggs_f, + "Enables easter eggs."); + particles_style = Cvar_Get ("particles_style", "1", CVAR_ARCHIVE, + particles_style_f, + "Sets particle style. 0 for Id, 1 for QF."); + CL_ParticleFunctionInit (); +} diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 412946f65..9ce856d70 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -47,7 +47,9 @@ #include "QF/plugin/vid_render.h" //FIXME #include "QF/scene/entity.h" +#include "client/effects.h" #include "client/entities.h" +#include "client/particles.h" #include "client/temp_entities.h" typedef struct tent_s { @@ -337,13 +339,13 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, case TE_Blood: count = MSG_ReadByte (net_message) * 20; MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_BloodPuffEffect (position, count); + clp_funcs->BloodPuffEffect (position, count); break; case TE_Explosion: MSG_ReadCoordV (net_message, &position[0]); // particles - r_funcs->particles->R_ParticleExplosion (position); + clp_funcs->ParticleExplosion (position); // light dl = r_funcs->R_AllocDlight (0); @@ -380,8 +382,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, colorStart = MSG_ReadByte (net_message); colorLength = MSG_ReadByte (net_message); S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); - r_funcs->particles->R_ParticleExplosion2 (position, colorStart, - colorLength); + clp_funcs->ParticleExplosion2 (position, colorStart, colorLength); dl = r_funcs->R_AllocDlight (0); if (!dl) break; @@ -398,7 +399,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, MSG_ReadCoordV (net_message, &position[0]); MSG_ReadCoordV (net_message, color); // OUCH! color[3] = 0.7; - r_funcs->particles->R_ParticleExplosion (position); + clp_funcs->ParticleExplosion (position); S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); dl = r_funcs->R_AllocDlight (0); if (dl) { @@ -411,21 +412,21 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, break; case TE_Gunshot1: MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_GunshotEffect (position, 20); + clp_funcs->GunshotEffect (position, 20); break; case TE_Gunshot2: count = MSG_ReadByte (net_message) * 20; MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_GunshotEffect (position, count); + clp_funcs->GunshotEffect (position, count); break; case TE_KnightSpike: MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_KnightSpikeEffect (position); + clp_funcs->KnightSpikeEffect (position); S_StartSound (-1, 0, cl_sfx_knighthit, &position[0], 1, 1); break; case TE_LavaSplash: MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_LavaSplash (position); + clp_funcs->LavaSplash (position); break; case TE_Lightning1: CL_ParseBeam (net_message, cl_mod_bolt, time, ctx); @@ -453,11 +454,11 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, QuatSet (0.25, 0.40, 0.65, 1, dl->color); } - r_funcs->particles->R_LightningBloodEffect (position); + clp_funcs->LightningBloodEffect (position); break; case TE_Spike: MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_SpikeEffect (position); + clp_funcs->SpikeEffect (position); { int i; sfx_t *sound; @@ -473,7 +474,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, break; case TE_SuperSpike: MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_SuperSpikeEffect (position); + clp_funcs->SuperSpikeEffect (position); { int i; sfx_t *sound; @@ -489,17 +490,17 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, break; case TE_TarExplosion: MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_BlobExplosion (position); + clp_funcs->BlobExplosion (position); S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); break; case TE_Teleport: MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_TeleportSplash (position); + clp_funcs->TeleportSplash (position); break; case TE_WizSpike: MSG_ReadCoordV (net_message, &position[0]); - r_funcs->particles->R_WizSpikeEffect (position); + clp_funcs->WizSpikeEffect (position); S_StartSound (-1, 0, cl_sfx_wizhit, &position[0], 1, 1); break; } @@ -659,9 +660,9 @@ CL_ParseParticleEffect (qmsg_t *net_message) color = MSG_ReadByte (net_message); if (count == 255) - r_funcs->particles->R_ParticleExplosion (org); + clp_funcs->ParticleExplosion (org); else - r_funcs->particles->R_RunParticleEffect (org, dir, color, count); + clp_funcs->RunParticleEffect (org, dir, color, count); } void diff --git a/libs/client/locs.c b/libs/client/locs.c index 4998694bf..ce5bd3ef4 100644 --- a/libs/client/locs.c +++ b/libs/client/locs.c @@ -55,7 +55,9 @@ #include "compat.h" #include "d_iface.h" //FIXME part_tex_smoke and part_tex_dot +#include "client/effects.h" #include "client/locs.h" +#include "client/particles.h" #define LOCATION_BLOCK 128 // 128 locations per block. @@ -307,14 +309,12 @@ locs_draw (vec4f_t simorg) dl->color[3] = 0.7; } trueloc = nearloc->loc; - r_funcs->particles->R_Particle_New (pt_smokecloud, part_tex_smoke, - trueloc, 2.0, + clp_funcs->Particle_New (pt_smokecloud, part_tex_smoke, trueloc, 2.0, zero, r_data->realtime + 9.0, 254, 0.25 + qfrandom (0.125), 0.0); for (i = 0; i < 15; i++) - r_funcs->particles->R_Particle_NewRandom (pt_fallfade, - part_tex_dot, trueloc, 12, - 0.7, 96, r_data->realtime + 5.0, + clp_funcs->Particle_NewRandom (pt_fallfade, part_tex_dot, trueloc, + 12, 0.7, 96, r_data->realtime + 5.0, 104 + (rand () & 7), 1.0, 0.0); } } diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 988c91432..5b0db4da3 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -66,124 +66,11 @@ static int pVAsize; static int *pVAindices; static varray_t2f_c4ub_v3f_t *particleVertexArray; -static mtstate_t mt; // private PRNG state - -inline static void -particle_new (ptype_t type, int texnum, vec4f_t pos, float scale, - vec4f_t vel, float live, int color, float alpha, float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_t *p = &particles[numparticles]; - partparm_t *parm = &partparams[numparticles]; - const int **rampptr = &partramps[numparticles]; - numparticles += 1; - - p->pos = pos; - p->vel = vel; - p->icolor = color; - p->alpha = alpha; - p->tex = texnum; - p->ramp = ramp; - p->scale = scale; - p->live = live; - - *parm = R_ParticlePhysics (type); - *rampptr = R_ParticleRamp (type); - if (*rampptr) { - p->icolor = (*rampptr) [(int) p->ramp]; - } -} - -/* - particle_new_random - - note that org_fuzz & vel_fuzz should be ints greater than 0 if you are - going to bother using this function. -*/ -inline static void -particle_new_random (ptype_t type, int texnum, vec4f_t org, int org_fuzz, - float scale, int vel_fuzz, float live, int color, - float alpha, float ramp) -{ - float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; - int rnd; - vec4f_t porg, pvel; - - rnd = mtwist_rand (&mt); - porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; - porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; - porg[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; - porg[3] = 1; - rnd = mtwist_rand (&mt); - pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; - pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; - pvel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; - pvel[3] = 0; - - particle_new (type, texnum, porg, scale, pvel, live, color, alpha, ramp); -} - -/* -inline static void -particle_new_veryrandom (ptype_t type, int texnum, vec4f_t org, - int org_fuzz, float scale, int vel_fuzz, float live, - int color, float alpha, float ramp) -{ - vec3_t porg, pvel; - - porg[0] = qfrandom (org_fuzz * 2) - org_fuzz + org[0]; - porg[1] = qfrandom (org_fuzz * 2) - org_fuzz + org[1]; - porg[2] = qfrandom (org_fuzz * 2) - org_fuzz + org[2]; - pvel[0] = qfrandom (vel_fuzz * 2) - vel_fuzz; - pvel[1] = qfrandom (vel_fuzz * 2) - vel_fuzz; - pvel[2] = qfrandom (vel_fuzz * 2) - vel_fuzz; - particle_new (type, texnum, porg, scale, pvel, live, color, alpha, ramp); -} -*/ - -static vec4f_t -roffs (int mod) -{ - vec4f_t offs = { - (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), - (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), - (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), - 0 - }; - return offs; -} - -static vec4f_t -tracer_vel (int tracercount, vec4f_t vec) -{ - if (tracercount & 1) { - return (vec4f_t) { vec[1], -vec[0], 0, 0 }; - } else { - return (vec4f_t) { -vec[1], vec[0], 0, 0 }; - } -} - -static void -add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, - float ramp) -{ - particle_new (type, part_tex_dot, pos, 1, vel, live, color, 1, ramp); -} - -void -gl_R_ClearParticles (void) -{ - numparticles = 0; -} - void gl_R_InitParticles (void) { int i; - mtwist_seed (&mt, 0xdeadbeef); - if (r_maxparticles && r_init) { if (vaelements) { partUseVA = 0; @@ -225,1020 +112,6 @@ gl_R_InitParticles (void) } } - -void -gl_R_ReadPointFile_f (void) -{ - const char *name; - char *mapname; - int c; - QFile *f; - - mapname = strdup (r_worldentity.renderer.model->path); - if (!mapname) - Sys_Error ("Can't duplicate mapname!"); - QFS_StripExtension (mapname, mapname); - - name = va (0, "%s.pts", mapname); - free (mapname); - - f = QFS_FOpenFile (name); - if (!f) { - Sys_Printf ("couldn't open %s\n", name); - return; - } - - Sys_MaskPrintf (SYS_dev, "Reading %s...\n", name); - c = 0; - vec4f_t zero = {}; - for (;;) { - char buf[64]; - vec4f_t org = { 0, 0, 0, 1 }; - - Qgets (f, buf, sizeof (buf)); - int r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); - if (r != 3) - break; - c++; - - if (numparticles >= r_maxparticles) { - Sys_MaskPrintf (SYS_dev, "Not enough free particles\n"); - break; - } else { - particle_new (pt_static, part_tex_dot, org, 1.5, zero, - 99999, (-c) & 15, 1.0, 0.0); - } - } - Qclose (f); - Sys_MaskPrintf (SYS_dev, "%i points read\n", c); -} - -static void -R_ParticleExplosion_QF (vec4f_t org) -{ -// R_NewExplosion (org); - if (numparticles >= r_maxparticles) - return; - particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, - 5.0, (mtwist_rand (&mt) & 7) + 8, - 0.5 + qfrandom (0.25), 0.0); -} - -static void -R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) -{ - unsigned int i, j = 512; - - if (numparticles >= r_maxparticles) - return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - - for (i = 0; i < j; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 16, 2, 256, - 0.3, - colorStart + (i % colorLength), 1.0, 0.0); - } -} - -static void -R_BlobExplosion_QF (vec4f_t org) -{ - unsigned int i; - unsigned int j = 1024; - - if (numparticles >= r_maxparticles) - return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - - for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 12, 2, 256, - 1.0 + (mtwist_rand (&mt) & 7) * 0.05, - 66 + i % 6, 1.0, 0.0); - } - for (i = 0; i < j / 2; i++) { - particle_new_random (pt_blob2, part_tex_dot, org, 12, 2, 256, - 1.0 + (mtwist_rand (&mt) & 7) * 0.05, - 150 + i % 6, 1.0, 0.0); - } -} - -static inline void -R_RunSparkEffect_QF (vec4f_t org, int count, int ofuzz) -{ - if (!r_particles->int_val) - return; - - vec4f_t zero = {}; - particle_new (pt_smokecloud, part_tex_smoke, org, ofuzz * 0.08, - zero, 9, 12 + (mtwist_rand (&mt) & 3), - 0.25 + qfrandom (0.125), 0.0); - - if (count > 0) { - int orgfuzz = ofuzz * 3 / 4; - if (orgfuzz < 1) - orgfuzz = 1; - - while (count--) { - int color = mtwist_rand (&mt) & 7; - - particle_new_random (pt_fallfadespark, part_tex_dot, org, orgfuzz, - 0.7, 96, 5.0, 0, 1.0, color); - } - } -} - -static inline void -R_BloodPuff_QF (vec4f_t org, int count) -{ - if (!r_particles->int_val) - return; - - vec4f_t zero = {}; - particle_new (pt_bloodcloud, part_tex_smoke, org, count / 5, zero, - 99.0, 70 + (mtwist_rand (&mt) & 3), 0.5, 0.0); -} - -static void -R_BloodPuffEffect_QF (vec4f_t org, int count) -{ - R_BloodPuff_QF (org, count); -} - -static void -R_GunshotEffect_QF (vec4f_t org, int count) -{ - int scale = 16; - - scale += count / 15; - R_RunSparkEffect_QF (org, count >> 1, scale); -} - -static void -R_LightningBloodEffect_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - R_BloodPuff_QF (org, 50); - - vec4f_t zero = {}; - particle_new (pt_smokecloud, part_tex_smoke, org, 3.0, zero, - 9.0, 12 + (mtwist_rand (&mt) & 3), - 0.25 + qfrandom (0.125), 0.0); - - for (int count = 7; count-- > 0; ) { - particle_new_random (pt_fallfade, part_tex_spark, org, 12, 2.0, 128, - 5.0, 244 + (count % 3), 1.0, 0.0); - } -} - -static void -R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, - int count) -{ - if (!r_particles->int_val) - return; - - float scale = pow (count, 0.23); - - for (int i = 0; i < count; i++) { - int rnd = mtwist_rand (&mt); - - // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, org + scale * roffs (16), 1.5, - dir, 0.1 * (i % 5), - (color & ~7) + (rnd & 7), 1.0, 0.0); - } -} - -static void -R_SpikeEffect_QF (vec4f_t org) -{ - R_RunSparkEffect_QF (org, 5, 8); -} - -static void -R_SuperSpikeEffect_QF (vec4f_t org) -{ - R_RunSparkEffect_QF (org, 10, 8); -} - -static void -R_KnightSpikeEffect_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - vec4f_t zero = {}; - particle_new (pt_smokecloud, part_tex_smoke, org, 1.0, zero, - 9.0, 234, 0.25 + qfrandom (0.125), 0.0); - - for (int count = 10; count-- > 0; ) { - particle_new_random (pt_fallfade, part_tex_dot, org, 6, 0.7, 96, - 5.0, 234, 1.0, 0.0); - } -} - -static void -R_WizSpikeEffect_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - vec4f_t zero = {}; - particle_new (pt_smokecloud, part_tex_smoke, org, 2.0, zero, - 9.0, 63, 0.25 + qfrandom (0.125), 0.0); - - for (int count = 15; count-- > 0; ) { - particle_new_random (pt_fallfade, part_tex_dot, org, 12, 0.7, 96, - 5.0, 63, 1.0, 0.0); - } -} - -static void -R_LavaSplash_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i++) { - for (int j = -16; j < 16; j++) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50.0 + 0.5 * (mtwist_rand (&mt) & 127); - vec4f_t dir = { - j * 8 + (rnd & 7), - i * 8 + ((rnd >> 6) & 7), - 256, - 0 - }; - vec4f_t offs = { dir[0], dir[1], ((rnd >> 9) & 63), 0 }; - dir = normalf (dir); - particle_new (pt_grav, part_tex_dot, org + offs, 3, vel * dir, - 2.0 + ((rnd >> 7) & 31) * 0.02, - 224 + ((rnd >> 12) & 7), 0.75, 0.0); - } - } -} - -static void -R_TeleportSplash_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int k = -24; k < 32; k += 4) { - for (int i = -16; i < 16; i += 4) { - for (int j = -16; j < 16; j += 4) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50 + ((rnd >> 6) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + (rnd & 3), - j + ((rnd >> 2) & 3), - k + ((rnd >> 4) & 3), - 0 - }; - particle_new (pt_grav, part_tex_spark, org + offs, 0.6, - vel * dir, - (0.2 + (mtwist_rand (&mt) & 15) * 0.01), - (7 + ((rnd >> 12) & 7)), 1.0, 0.0); - } - } - } -} - -static void -R_RocketTrail_QF (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - 3) * vec; - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - float pscale = 1.5 + qfrandom (1.5); - - while (len < maxlen) { - float pscalenext = 1.5 + qfrandom (1.5); - float dist = (pscale + pscalenext) * 3.0; - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_smoke, pos, - pscale + percent * 4.0, zero, - 2.0 - percent * 2.0, - 12 + (mtwist_rand (&mt) & 3), - 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - pscale = pscalenext; - } -} - -static void -R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - 3) * vec; - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - float pscale = 6.0 + qfrandom (7.0); - - while (len < maxlen) { - float pscalenext = 6.0 + qfrandom (7.0); - float dist = (pscale + pscalenext) * 2.0; - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_smoke, pos, - pscale + percent * 4.0, zero, - 2.0 - percent * 2.0, - 1 + (mtwist_rand (&mt) & 3), - 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - pscale = pscalenext; - } -} - -static void -R_BloodTrail_QF (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - 3) * vec; - - float len = 0; - vec4f_t pos = start; - float pscale = 5.0 + qfrandom (10.0); - - while (len < maxlen) { - float pscalenext = 5.0 + qfrandom (10.0); - float dist = (pscale + pscalenext) * 1.5; - float percent = len * origlen; - vec4f_t vel = roffs (24); - vel[2] -= percent * 40; - - particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, - 2.0 - percent * 2.0, - 68 + (mtwist_rand (&mt) & 3), 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - pscale = pscalenext; - } -} - -static void -R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - 3) * vec; - - float len = 0; - vec4f_t pos = start; - float pscale = 1.5 + qfrandom (7.5); - while (len < maxlen) { - float pscalenext = 1.5 + qfrandom (7.5); - float dist = (pscale + pscalenext) * 1.5; - float percent = len * origlen; - vec4f_t vel = roffs (12); - vel[2] -= percent * 40; - - particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, - 1.5 - percent * 1.5, - 68 + (mtwist_rand (&mt) & 3), 0.75, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - pscale = pscalenext; - } -} - -static void -R_WizTrail_QF (vec4f_t start, vec4f_t end) -{ - float dist = 3.0; - - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - dist) * vec; - - float len = 0; - vec4f_t pos = start; - while (len < maxlen) { - static int tracercount; - float percent = len * origlen; - - particle_new (pt_flame, part_tex_smoke, pos, - 2.0 + qfrandom (1.0) - percent * 2.0, - 30 * tracer_vel (tracercount++, vec), - 0.5 - percent * 0.5, - 52 + (mtwist_rand (&mt) & 4), 1.0 - percent * 0.125, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - } -} - -static void -R_FlameTrail_QF (vec4f_t start, vec4f_t end) -{ - float dist = 3.0; - - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - dist) * vec; - - float len = 0; - vec4f_t pos = start; - while (len < maxlen) { - static int tracercount; - float percent = len * origlen; - - particle_new (pt_flame, part_tex_smoke, pos, - 2.0 + qfrandom (1.0) - percent * 2.0, - 30 * tracer_vel (tracercount++, vec), - 0.5 - percent * 0.5, 234, - 1.0 - percent * 0.125, 0.0); - len += dist; - pos += step; - } -} - -static void -R_VoorTrail_QF (vec4f_t start, vec4f_t end) -{ - float dist = 3.0; - - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - dist) * vec; - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - while (len < maxlen) { - float percent = len * origlen; - - particle_new (pt_static, part_tex_dot, pos + roffs (16), - 1.0 + qfrandom (1.0), - zero, 0.3 - percent * 0.3, - 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 1.0, 0.0); - len += dist; - pos += step; - } -} - -static void -R_GlowTrail_QF (vec4f_t start, vec4f_t end, int glow_color) -{ - float dist = 3.0; - - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - dist) * vec; - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - while (len < maxlen) { - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_dot, pos + roffs (5), 1.0, zero, - 2.0 - percent * 0.2, glow_color, 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - } -} - -static void -R_ParticleExplosion_EE (vec4f_t org) -{ -/* - R_NewExplosion (org); -*/ - if (numparticles >= r_maxparticles) - return; - particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, - 5.0, mtwist_rand (&mt) & 255, - 0.5 + qfrandom (0.25), 0.0); -} - -static void -R_TeleportSplash_EE (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int k = -24; k < 32; k += 4) { - for (int i = -16; i < 16; i += 4) { - for (int j = -16; j < 16; j += 4) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50 + ((rnd >> 6) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + (rnd & 3), - j + ((rnd >> 2) & 3), - k + ((rnd >> 4) & 3), - 0 - }; - particle_new (pt_grav, part_tex_spark, org + offs, 0.6, - vel * dir, - (0.2 + (mtwist_rand (&mt) & 15) * 0.01), - qfrandom (1.0), 1.0, 0.0); - } - } - } -} - -static void -R_RocketTrail_EE (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - float pscale = 1.5 + qfrandom (1.5); - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - while (len < maxlen) { - float pscalenext = 1.5 + qfrandom (1.5); - float dist = (pscale + pscalenext) * 3.0; - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_smoke, pos, - pscale + percent * 4.0, zero, - 2.0 - percent * 2.0, - mtwist_rand (&mt) & 255, - 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += len * vec; - pscale = pscalenext; - } -} - -static void -R_GrenadeTrail_EE (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - float pscale = 6.0 + qfrandom (7.0); - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - while (len < maxlen) { - float pscalenext = 6.0 + qfrandom (7.0); - float dist = (pscale + pscalenext) * 2.0; - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_smoke, pos, - pscale + percent * 4.0, zero, - 2.0 - percent * 2.0, - mtwist_rand (&mt) & 255, - 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); - len += dist; - pos += len * vec; - pscale = pscalenext; - } -} - -static void -R_ParticleExplosion_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < 1024; i++) { - ptype_t type = i & 1 ? pt_explode2 : pt_explode; - add_particle (type, org + roffs (32), roffs (512), 5, - 0, mtwist_rand (&mt) & 3); - } -} - -static void -R_BlobExplosion_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < 1024; i++) { - ptype_t type = i & 1 ? pt_blob : pt_blob2; - int color = i & 1 ? 66 : 150; - add_particle (type, org + roffs (32), roffs (512), - color + mtwist_rand (&mt) % 6, - (color & ~7) + (mtwist_rand (&mt) & 7), 0); - } -} - -static inline void // FIXME: inline? -R_RunParticleEffect_ID (vec4f_t org, vec4f_t dir, int color, - int count) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < count; i++) { - add_particle (pt_slowgrav, org + roffs (16), - dir/* + roffs (300)*/, - 0.1 * (mtwist_rand (&mt) % 5), - (color & ~7) + (mtwist_rand (&mt) & 7), 0); - } -} - -static void -R_BloodPuffEffect_ID (vec4f_t org, int count) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 73, count); -} - -static void -R_GunshotEffect_ID (vec4f_t org, int count) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 0, count); -} - -static void -R_LightningBloodEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 225, 50); -} - -static void -R_SpikeEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 0, 10); -} - -static void -R_SuperSpikeEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 0, 20); -} - -static void -R_KnightSpikeEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 226, 20); -} - -static void -R_WizSpikeEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 20, 30); -} - -static void -R_LavaSplash_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i++) { - for (int j = -16; j < 16; j++) { - for (int k = 0; k < 1; k++) { - float vel = 50 + (mtwist_rand (&mt) & 63); - vec4f_t dir = { - j * 8 + (mtwist_rand (&mt) & 7), - i * 8 + (mtwist_rand (&mt) & 7), - 256, - 0 - }; - vec4f_t offs = { - dir[0], - dir[1], - (mtwist_rand (&mt) & 63), - 0 - }; - dir = normalf (dir); - add_particle (pt_grav, org + offs, vel * dir, - 2 + (mtwist_rand (&mt) & 31) * 0.02, - 224 + (mtwist_rand (&mt) & 7), 0); - } - } - } -} - -static void -R_TeleportSplash_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i += 4) { - for (int j = -16; j < 16; j += 4) { - for (int k = -24; k < 32; k += 4) { - float vel = 50 + (mtwist_rand (&mt) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + (mtwist_rand (&mt) & 3), - j + (mtwist_rand (&mt) & 3), - k + (mtwist_rand (&mt) & 3), - 0 - }; - add_particle (pt_grav, org + offs, vel * dir, - 0.2 + (mtwist_rand (&mt) & 7) * 0.02, - 7 + (mtwist_rand (&mt) & 7), 0); - } - } - } -} - -static void -R_DarkFieldParticles_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i += 8) { - for (int j = -16; j < 16; j += 8) { - for (int k = 0; k < 32; k += 8) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50 + ((rnd >> 9) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + ((rnd >> 3) & 3), - j + ((rnd >> 5) & 3), - k + ((rnd >> 7) & 3), - 0 - }; - - add_particle (pt_slowgrav, org + offs, vel * dir, - 0.2 + (rnd & 7) * 0.02, - 150 + mtwist_rand (&mt) % 6, 0); - } - } - } -} - -static vec4f_t velocities[NUMVERTEXNORMALS]; -static vec4f_t normals[NUMVERTEXNORMALS] = { -#include "anorms.h" -}; - -static void -R_EntityParticles_ID (vec4f_t org) -{ - int i; - float angle, sp, sy, cp, cy; // cr, sr - float beamlength = 16.0, dist = 64.0; - - if (!r_particles->int_val) - return; - - for (i = 0; i < NUMVERTEXNORMALS; i++) { - int k; - for (k = 0; k < 3; k++) { - velocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; - } - } - - vec4f_t zero = {}; - for (i = 0; i < NUMVERTEXNORMALS; i++) { - angle = vr_data.realtime * velocities[i][0]; - cy = cos (angle); - sy = sin (angle); - angle = vr_data.realtime * velocities[i][1]; - cp = cos (angle); - sp = sin (angle); -// Next 3 lines results aren't currently used, may be in future. --Despair -// angle = vr_data.realtime * avelocities[i][2]; -// sr = sin (angle); -// cr = cos (angle); - - vec4f_t forward = { cp * cy, cp * sy, -sp, 0 }; - vec4f_t pos = org + normals[i] * dist + forward * beamlength; - //FIXME 0 velocity? - add_particle (pt_explode, pos, zero, 0.01, 0x6f, 0); - } -} - -static void -R_RocketTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_fire, pos + roffs (6), zero, 2, - 0, (mtwist_rand (&mt) & 3)); - pos += vec; - } -} - -static void -R_GrenadeTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_fire, pos + roffs (6), zero, 2, - 0, (mtwist_rand (&mt) & 3) + 2); - pos += vec; - } -} - -static void -R_BloodTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_slowgrav, pos + roffs (6), zero, 2, - 67 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - -static void -R_SlightBloodTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 6; - add_particle (pt_slowgrav, pos + roffs (6), zero, 2, - 67 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - -static void -R_WizTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t pos = start; - while (len > 0) { - static int tracercount; - len -= 3; - add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, - 52 + ((tracercount & 4) << 1), 0); - tracercount++; - pos += vec; - } -} - -static void -R_FlameTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t pos = start; - while (len > 0) { - static int tracercount; - len -= 3; - add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, - 230 + ((tracercount & 4) << 1), 0); - tracercount++; - pos += vec; - } -} - -static void -R_VoorTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_static, pos + roffs (16), zero, 0.3, - 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - void gl_R_DrawParticles (void) { @@ -1386,172 +259,6 @@ gl_R_DrawParticles (void) qfglDepthMask (GL_TRUE); } -static void -gl_R_Particle_New (ptype_t type, int texnum, vec4f_t org, float scale, - vec4f_t vel, float live, int color, float alpha, - float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_new (type, texnum, org, scale, vel, live, color, alpha, ramp); -} - -static void -gl_R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, - int org_fuzz, float scale, int vel_fuzz, float live, - int color, float alpha, float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, live, - color, alpha, ramp); -} - -static vid_particle_funcs_t particles_QF = { - R_RocketTrail_QF, - R_GrenadeTrail_QF, - R_BloodTrail_QF, - R_SlightBloodTrail_QF, - R_WizTrail_QF, - R_FlameTrail_QF, - R_VoorTrail_QF, - R_GlowTrail_QF, - R_RunParticleEffect_QF, - R_BloodPuffEffect_QF, - R_GunshotEffect_QF, - R_LightningBloodEffect_QF, - R_SpikeEffect_QF, - R_KnightSpikeEffect_QF, - R_SuperSpikeEffect_QF, - R_WizSpikeEffect_QF, - R_BlobExplosion_QF, - R_ParticleExplosion_QF, - R_ParticleExplosion2_QF, - R_LavaSplash_QF, - R_TeleportSplash_QF, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -static vid_particle_funcs_t particles_ID = { - R_RocketTrail_ID, - R_GrenadeTrail_ID, - R_BloodTrail_ID, - R_SlightBloodTrail_ID, - R_WizTrail_ID, - R_FlameTrail_ID, - R_VoorTrail_ID, - R_GlowTrail_QF, - R_RunParticleEffect_ID, - R_BloodPuffEffect_ID, - R_GunshotEffect_ID, - R_LightningBloodEffect_ID, - R_SpikeEffect_ID, - R_KnightSpikeEffect_ID, - R_SuperSpikeEffect_ID, - R_WizSpikeEffect_ID, - R_BlobExplosion_ID, - R_ParticleExplosion_ID, - R_ParticleExplosion2_QF, - R_LavaSplash_ID, - R_TeleportSplash_ID, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -static vid_particle_funcs_t particles_QF_egg = { - R_RocketTrail_EE, - R_GrenadeTrail_EE, - R_BloodTrail_QF, - R_SlightBloodTrail_QF, - R_WizTrail_QF, - R_FlameTrail_QF, - R_VoorTrail_QF, - R_GlowTrail_QF, - R_RunParticleEffect_QF, - R_BloodPuffEffect_QF, - R_GunshotEffect_QF, - R_LightningBloodEffect_QF, - R_SpikeEffect_QF, - R_KnightSpikeEffect_QF, - R_SuperSpikeEffect_QF, - R_WizSpikeEffect_QF, - R_BlobExplosion_QF, - R_ParticleExplosion_EE, - R_ParticleExplosion2_QF, - R_LavaSplash_QF, - R_TeleportSplash_EE, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -static vid_particle_funcs_t particles_ID_egg = { - R_RocketTrail_EE, - R_GrenadeTrail_EE, - R_BloodTrail_ID, - R_SlightBloodTrail_ID, - R_WizTrail_ID, - R_FlameTrail_ID, - R_VoorTrail_ID, - R_GlowTrail_QF, - R_RunParticleEffect_ID, - R_BloodPuffEffect_ID, - R_GunshotEffect_ID, - R_LightningBloodEffect_ID, - R_SpikeEffect_ID, - R_KnightSpikeEffect_ID, - R_SuperSpikeEffect_ID, - R_WizSpikeEffect_ID, - R_BlobExplosion_ID, - R_ParticleExplosion_EE, - R_ParticleExplosion2_QF, - R_LavaSplash_ID, - R_TeleportSplash_EE, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -void -gl_r_easter_eggs_f (cvar_t *var) -{ - if (easter_eggs && !gl_feature_mach64) { - if (easter_eggs->int_val) { - if (r_particles_style->int_val) { - gl_vid_render_funcs.particles = &particles_QF_egg; - } else { - gl_vid_render_funcs.particles = &particles_ID_egg; - } - } else if (r_particles_style) { - if (r_particles_style->int_val) { - gl_vid_render_funcs.particles = &particles_QF; - } else { - gl_vid_render_funcs.particles = &particles_ID; - } - } - } -} - -void -gl_r_particles_style_f (cvar_t *var) -{ - gl_r_easter_eggs_f (easter_eggs); -} - -static void -R_ParticleFunctionInit (void) -{ - gl_r_particles_style_f (r_particles_style); - gl_r_easter_eggs_f (easter_eggs); -} - static void r_particles_nearclip_f (cvar_t *var) { @@ -1574,8 +281,6 @@ r_particles_max_f (cvar_t *var) void gl_R_Particles_Init_Cvars (void) { - easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, r_easter_eggs_f, - "Enables easter eggs."); r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, "Toggles drawing of particles."); r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, @@ -1586,8 +291,4 @@ gl_R_Particles_Init_Cvars (void) CVAR_ARCHIVE, r_particles_nearclip_f, "Distance of the particle near clipping " "plane from the player."); - r_particles_style = Cvar_Get ("r_particles_style", "1", CVAR_ARCHIVE, - r_particles_style_f, "Sets particle style. " - "0 for Id, 1 for QF."); - R_ParticleFunctionInit (); } diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 429191157..cd5e406a1 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -895,5 +895,5 @@ gl_R_ClearState (void) r_worldentity.renderer.model = 0; R_ClearEfrags (); R_ClearDlights (); - gl_R_ClearParticles (); + R_ClearParticles (); } diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 8a2005910..f035be9dd 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -146,8 +146,6 @@ gl_R_Init (void) Cmd_AddCommand ("timerefresh", gl_R_TimeRefresh_f, "Tests the current refresh rate for the current location"); Cmd_AddCommand ("envmap", R_Envmap_f, "No Description"); - Cmd_AddCommand ("pointfile", gl_R_ReadPointFile_f, - "Load a pointfile to determine map leaks"); Cmd_AddCommand ("loadsky", gl_R_LoadSky_f, "Load a skybox"); gl_Draw_Init (); @@ -203,7 +201,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_viewleaf = NULL; R_MarkLeaves (); - gl_R_ClearParticles (); + R_ClearParticles (); GL_BuildLightmaps (models, num_models); diff --git a/libs/video/renderer/gl/namehack.h b/libs/video/renderer/gl/namehack.h index 84f48faa6..2f2b37ae4 100644 --- a/libs/video/renderer/gl/namehack.h +++ b/libs/video/renderer/gl/namehack.h @@ -34,7 +34,6 @@ #define R_AddTexture gl_R_AddTexture #define R_BlendLightmaps gl_R_BlendLightmaps #define R_CalcLightmaps gl_R_CalcLightmaps -#define R_ClearParticles gl_R_ClearParticles #define R_ClearState gl_R_ClearState #define R_ClearTextures gl_R_ClearTextures #define R_DrawAliasModel gl_R_DrawAliasModel @@ -88,7 +87,6 @@ #undef R_AddTexture #undef R_BlendLightmaps #undef R_CalcLightmaps -#undef R_ClearParticles #undef R_ClearState #undef R_ClearTextures #undef R_DrawAliasModel diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 46b865913..1295ca7e4 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -229,8 +229,6 @@ glsl_R_RenderView (void) void glsl_R_Init (void) { - Cmd_AddCommand ("pointfile", glsl_R_ReadPointFile_f, - "Load a pointfile to determine map leaks."); Cmd_AddCommand ("timerefresh", glsl_R_TimeRefresh_f, "Test the current refresh rate for the current location."); R_Init_Cvars (); @@ -262,7 +260,7 @@ glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) R_MarkLeaves (); R_FreeAllEntities (); - glsl_R_ClearParticles (); + R_ClearParticles (); glsl_R_RegisterTextures (models, num_models); glsl_R_BuildLightmaps (models, num_models); glsl_R_BuildDisplayLists (models, num_models); @@ -279,7 +277,7 @@ glsl_R_ClearState (void) r_worldentity.renderer.model = 0; R_ClearEfrags (); R_ClearDlights (); - glsl_R_ClearParticles (); + R_ClearParticles (); } void diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 9975f73f2..ebda3b447 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -133,117 +133,6 @@ static struct { {"fog", 1}, }; -static mtstate_t mt; // private PRNG state - -inline static void -particle_new (ptype_t type, int texnum, vec4f_t pos, float scale, - vec4f_t vel, float live, int color, float alpha, float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_t *p = &particles[numparticles]; - partparm_t *parm = &partparams[numparticles]; - const int **rampptr = &partramps[numparticles]; - numparticles += 1; - - p->pos = pos; - p->vel = vel; - p->icolor = color; - p->alpha = alpha; - p->tex = texnum; - p->ramp = ramp; - p->scale = scale; - p->live = live; - - *parm = R_ParticlePhysics (type); - *rampptr = R_ParticleRamp (type); - if (*rampptr) { - p->icolor = (*rampptr) [(int) p->ramp]; - } -} - -/* - particle_new_random - - note that org_fuzz & vel_fuzz should be ints greater than 0 if you are - going to bother using this function. -*/ -inline static void -particle_new_random (ptype_t type, int texnum, vec4f_t org, int org_fuzz, - float scale, int vel_fuzz, float live, int color, - float alpha, float ramp) -{ - float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; - int rnd; - vec4f_t porg, pvel; - - rnd = mtwist_rand (&mt); - porg[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; - porg[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; - porg[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; - porg[3] = 1; - rnd = mtwist_rand (&mt); - pvel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; - pvel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; - pvel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; - pvel[3] = 0; - - particle_new (type, texnum, porg, scale, pvel, live, color, alpha, ramp); -} - -/* -inline static void -particle_new_veryrandom (ptype_t type, int texnum, vec4f_t org, - int org_fuzz, float scale, int vel_fuzz, float live, - int color, float alpha, float ramp) -{ - vec3_t porg, pvel; - - porg[0] = qfrandom (org_fuzz * 2) - org_fuzz + org[0]; - porg[1] = qfrandom (org_fuzz * 2) - org_fuzz + org[1]; - porg[2] = qfrandom (org_fuzz * 2) - org_fuzz + org[2]; - pvel[0] = qfrandom (vel_fuzz * 2) - vel_fuzz; - pvel[1] = qfrandom (vel_fuzz * 2) - vel_fuzz; - pvel[2] = qfrandom (vel_fuzz * 2) - vel_fuzz; - particle_new (type, texnum, porg, scale, pvel, live, color, alpha, ramp); -} -*/ - -static vec4f_t -roffs (int mod) -{ - vec4f_t offs = { - (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), - (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), - (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), - 0 - }; - return offs; -} - -static vec4f_t -tracer_vel (int tracercount, vec4f_t vec) -{ - if (tracercount & 1) { - return (vec4f_t) { vec[1], -vec[0], 0, 0 }; - } else { - return (vec4f_t) { -vec[1], vec[0], 0, 0 }; - } -} - -static void -add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, - float ramp) -{ - particle_new (type, part_tex_dot, pos, 1, vel, live, color, 1, ramp); -} - -void -glsl_R_ClearParticles (void) -{ - numparticles = 0; -} - void glsl_R_InitParticles (void) { @@ -255,8 +144,6 @@ glsl_R_InitParticles (void) byte data[64][64][2]; tex_t *tex; - mtwist_seed (&mt, 0xdeadbeef); - qfeglEnable (GL_VERTEX_PROGRAM_POINT_SIZE); qfeglGetFloatv (GL_ALIASED_POINT_SIZE_RANGE, v); Sys_MaskPrintf (SYS_glsl, "point size: %g - %g\n", v[0], v[1]); @@ -329,1019 +216,6 @@ glsl_R_InitParticles (void) } } -void -glsl_R_ReadPointFile_f (void) -{ - const char *name; - char *mapname; - int c; - QFile *f; - - mapname = strdup (r_worldentity.renderer.model->path); - if (!mapname) - Sys_Error ("Can't duplicate mapname!"); - QFS_StripExtension (mapname, mapname); - - name = va (0, "%s.pts", mapname); - free (mapname); - - f = QFS_FOpenFile (name); - if (!f) { - Sys_Printf ("couldn't open %s\n", name); - return; - } - - Sys_MaskPrintf (SYS_dev, "Reading %s...\n", name); - c = 0; - vec4f_t zero = {}; - for (;;) { - char buf[64]; - vec4f_t org = { 0, 0, 0, 1 }; - - Qgets (f, buf, sizeof (buf)); - int r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); - if (r != 3) - break; - c++; - - if (numparticles >= r_maxparticles) { - Sys_MaskPrintf (SYS_dev, "Not enough free particles\n"); - break; - } else { - particle_new (pt_static, part_tex_dot, org, 1.5, zero, - 99999, (-c) & 15, 1.0, 0.0); - } - } - Qclose (f); - Sys_MaskPrintf (SYS_dev, "%i points read\n", c); -} - -static void -R_ParticleExplosion_QF (vec4f_t org) -{ -// R_NewExplosion (org); - if (numparticles >= r_maxparticles) - return; - particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, - 5.0, (mtwist_rand (&mt) & 7) + 8, - 0.5 + qfrandom (0.25), 0.0); -} - -static void -R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) -{ - unsigned int i, j = 512; - - if (numparticles >= r_maxparticles) - return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - - for (i = 0; i < j; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 16, 2, 256, - 0.3, - colorStart + (i % colorLength), 1.0, 0.0); - } -} - -static void -R_BlobExplosion_QF (vec4f_t org) -{ - unsigned int i; - unsigned int j = 1024; - - if (numparticles >= r_maxparticles) - return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - - for (i = 0; i < j >> 1; i++) { - particle_new_random (pt_blob, part_tex_dot, org, 12, 2, 256, - 1.0 + (mtwist_rand (&mt) & 7) * 0.05, - 66 + i % 6, 1.0, 0.0); - } - for (i = 0; i < j / 2; i++) { - particle_new_random (pt_blob2, part_tex_dot, org, 12, 2, 256, - 1.0 + (mtwist_rand (&mt) & 7) * 0.05, - 150 + i % 6, 1.0, 0.0); - } -} - -static inline void -R_RunSparkEffect_QF (vec4f_t org, int count, int ofuzz) -{ - if (!r_particles->int_val) - return; - - vec4f_t zero = {}; - particle_new (pt_smokecloud, part_tex_smoke, org, ofuzz * 0.08, - zero, 9, 12 + (mtwist_rand (&mt) & 3), - 0.25 + qfrandom (0.125), 0.0); - - if (count > 0) { - int orgfuzz = ofuzz * 3 / 4; - if (orgfuzz < 1) - orgfuzz = 1; - - while (count--) { - int color = mtwist_rand (&mt) & 7; - - particle_new_random (pt_fallfadespark, part_tex_dot, org, orgfuzz, - 0.7, 96, 5.0, 0, 1.0, color); - } - } -} - -static inline void -R_BloodPuff_QF (vec4f_t org, int count) -{ - if (!r_particles->int_val) - return; - - vec4f_t zero = {}; - particle_new (pt_bloodcloud, part_tex_smoke, org, count / 5, zero, - 99.0, 70 + (mtwist_rand (&mt) & 3), 0.5, 0.0); -} - -static void -R_BloodPuffEffect_QF (vec4f_t org, int count) -{ - R_BloodPuff_QF (org, count); -} - -static void -R_GunshotEffect_QF (vec4f_t org, int count) -{ - int scale = 16; - - scale += count / 15; - R_RunSparkEffect_QF (org, count >> 1, scale); -} - -static void -R_LightningBloodEffect_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - R_BloodPuff_QF (org, 50); - - vec4f_t zero = {}; - particle_new (pt_smokecloud, part_tex_smoke, org, 3.0, zero, - 9.0, 12 + (mtwist_rand (&mt) & 3), - 0.25 + qfrandom (0.125), 0.0); - - for (int count = 7; count-- > 0; ) { - particle_new_random (pt_fallfade, part_tex_spark, org, 12, 2.0, 128, - 5.0, 244 + (count % 3), 1.0, 0.0); - } -} - -static void -R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, - int count) -{ - if (!r_particles->int_val) - return; - - float scale = pow (count, 0.23); - - for (int i = 0; i < count; i++) { - int rnd = mtwist_rand (&mt); - - // Note that ParseParticleEffect handles (dir * 15) - particle_new (pt_grav, part_tex_dot, org + scale * roffs (16), 1.5, - dir, 0.1 * (i % 5), - (color & ~7) + (rnd & 7), 1.0, 0.0); - } -} - -static void -R_SpikeEffect_QF (vec4f_t org) -{ - R_RunSparkEffect_QF (org, 5, 8); -} - -static void -R_SuperSpikeEffect_QF (vec4f_t org) -{ - R_RunSparkEffect_QF (org, 10, 8); -} - -static void -R_KnightSpikeEffect_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - vec4f_t zero = {}; - particle_new (pt_smokecloud, part_tex_smoke, org, 1.0, zero, - 9.0, 234, 0.25 + qfrandom (0.125), 0.0); - - for (int count = 10; count-- > 0; ) { - particle_new_random (pt_fallfade, part_tex_dot, org, 6, 0.7, 96, - 5.0, 234, 1.0, 0.0); - } -} - -static void -R_WizSpikeEffect_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - vec4f_t zero = {}; - particle_new (pt_smokecloud, part_tex_smoke, org, 2.0, zero, - 9.0, 63, 0.25 + qfrandom (0.125), 0.0); - - for (int count = 15; count-- > 0; ) { - particle_new_random (pt_fallfade, part_tex_dot, org, 12, 0.7, 96, - 5.0, 63, 1.0, 0.0); - } -} - -static void -R_LavaSplash_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i++) { - for (int j = -16; j < 16; j++) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50.0 + 0.5 * (mtwist_rand (&mt) & 127); - vec4f_t dir = { - j * 8 + (rnd & 7), - i * 8 + ((rnd >> 6) & 7), - 256, - 0 - }; - vec4f_t offs = { dir[0], dir[1], ((rnd >> 9) & 63), 0 }; - dir = normalf (dir); - particle_new (pt_grav, part_tex_dot, org + offs, 3, vel * dir, - 2.0 + ((rnd >> 7) & 31) * 0.02, - 224 + ((rnd >> 12) & 7), 0.75, 0.0); - } - } -} - -static void -R_TeleportSplash_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int k = -24; k < 32; k += 4) { - for (int i = -16; i < 16; i += 4) { - for (int j = -16; j < 16; j += 4) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50 + ((rnd >> 6) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + (rnd & 3), - j + ((rnd >> 2) & 3), - k + ((rnd >> 4) & 3), - 0 - }; - particle_new (pt_grav, part_tex_spark, org + offs, 0.6, - vel * dir, - (0.2 + (mtwist_rand (&mt) & 15) * 0.01), - (7 + ((rnd >> 12) & 7)), 1.0, 0.0); - } - } - } -} - -static void -R_RocketTrail_QF (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - 3) * vec; - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - float pscale = 1.5 + qfrandom (1.5); - - while (len < maxlen) { - float pscalenext = 1.5 + qfrandom (1.5); - float dist = (pscale + pscalenext) * 3.0; - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_smoke, pos, - pscale + percent * 4.0, zero, - 2.0 - percent * 2.0, - 12 + (mtwist_rand (&mt) & 3), - 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - pscale = pscalenext; - } -} - -static void -R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - 3) * vec; - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - float pscale = 6.0 + qfrandom (7.0); - - while (len < maxlen) { - float pscalenext = 6.0 + qfrandom (7.0); - float dist = (pscale + pscalenext) * 2.0; - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_smoke, pos, - pscale + percent * 4.0, zero, - 2.0 - percent * 2.0, - 1 + (mtwist_rand (&mt) & 3), - 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - pscale = pscalenext; - } -} - -static void -R_BloodTrail_QF (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - 3) * vec; - - float len = 0; - vec4f_t pos = start; - float pscale = 5.0 + qfrandom (10.0); - - while (len < maxlen) { - float pscalenext = 5.0 + qfrandom (10.0); - float dist = (pscale + pscalenext) * 1.5; - float percent = len * origlen; - vec4f_t vel = roffs (24); - vel[2] -= percent * 40; - - particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, - 2.0 - percent * 2.0, - 68 + (mtwist_rand (&mt) & 3), 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - pscale = pscalenext; - } -} - -static void -R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - 3) * vec; - - float len = 0; - vec4f_t pos = start; - float pscale = 1.5 + qfrandom (7.5); - while (len < maxlen) { - float pscalenext = 1.5 + qfrandom (7.5); - float dist = (pscale + pscalenext) * 1.5; - float percent = len * origlen; - vec4f_t vel = roffs (12); - vel[2] -= percent * 40; - - particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, - 1.5 - percent * 1.5, - 68 + (mtwist_rand (&mt) & 3), 0.75, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - pscale = pscalenext; - } -} - -static void -R_WizTrail_QF (vec4f_t start, vec4f_t end) -{ - float dist = 3.0; - - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - dist) * vec; - - float len = 0; - vec4f_t pos = start; - while (len < maxlen) { - static int tracercount; - float percent = len * origlen; - - particle_new (pt_flame, part_tex_smoke, pos, - 2.0 + qfrandom (1.0) - percent * 2.0, - 30 * tracer_vel (tracercount++, vec), - 0.5 - percent * 0.5, - 52 + (mtwist_rand (&mt) & 4), 1.0 - percent * 0.125, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - } -} - -static void -R_FlameTrail_QF (vec4f_t start, vec4f_t end) -{ - float dist = 3.0; - - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - dist) * vec; - - float len = 0; - vec4f_t pos = start; - while (len < maxlen) { - static int tracercount; - float percent = len * origlen; - - particle_new (pt_flame, part_tex_smoke, pos, - 2.0 + qfrandom (1.0) - percent * 2.0, - 30 * tracer_vel (tracercount++, vec), - 0.5 - percent * 0.5, 234, - 1.0 - percent * 0.125, 0.0); - len += dist; - pos += step; - } -} - -static void -R_VoorTrail_QF (vec4f_t start, vec4f_t end) -{ - float dist = 3.0; - - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - dist) * vec; - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - while (len < maxlen) { - float percent = len * origlen; - - particle_new (pt_static, part_tex_dot, pos + roffs (16), - 1.0 + qfrandom (1.0), - zero, 0.3 - percent * 0.3, - 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 1.0, 0.0); - len += dist; - pos += step; - } -} - -static void -R_GlowTrail_QF (vec4f_t start, vec4f_t end, int glow_color) -{ - float dist = 3.0; - - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - vec4f_t step = (maxlen - dist) * vec; - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - while (len < maxlen) { - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_dot, pos + roffs (5), 1.0, zero, - 2.0 - percent * 0.2, glow_color, 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += step; - } -} - -static void -R_ParticleExplosion_EE (vec4f_t org) -{ -/* - R_NewExplosion (org); -*/ - if (numparticles >= r_maxparticles) - return; - particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, - 5.0, mtwist_rand (&mt) & 255, - 0.5 + qfrandom (0.25), 0.0); -} - -static void -R_TeleportSplash_EE (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int k = -24; k < 32; k += 4) { - for (int i = -16; i < 16; i += 4) { - for (int j = -16; j < 16; j += 4) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50 + ((rnd >> 6) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + (rnd & 3), - j + ((rnd >> 2) & 3), - k + ((rnd >> 4) & 3), - 0 - }; - particle_new (pt_grav, part_tex_spark, org + offs, 0.6, - vel * dir, - (0.2 + (mtwist_rand (&mt) & 15) * 0.01), - qfrandom (1.0), 1.0, 0.0); - } - } - } -} - -static void -R_RocketTrail_EE (vec4f_t start, vec4f_t end) -{ - if (numparticles >= r_maxparticles) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - float pscale = 1.5 + qfrandom (1.5); - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - while (len < maxlen) { - float pscalenext = 1.5 + qfrandom (1.5); - float dist = (pscale + pscalenext) * 3.0; - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_smoke, pos, - pscale + percent * 4.0, zero, - 2.0 - percent * 2.0, - mtwist_rand (&mt) & 255, - 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; - len += dist; - pos += len * vec; - pscale = pscalenext; - } -} - -static void -R_GrenadeTrail_EE (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float maxlen = magnitudef (vec)[0]; - vec = normalf (vec); - - float origlen = vr_data.frametime / maxlen; - float pscale = 6.0 + qfrandom (7.0); - - float len = 0; - vec4f_t zero = {}; - vec4f_t pos = start; - while (len < maxlen) { - float pscalenext = 6.0 + qfrandom (7.0); - float dist = (pscale + pscalenext) * 2.0; - float percent = len * origlen; - - particle_new (pt_smoke, part_tex_smoke, pos, - pscale + percent * 4.0, zero, - 2.0 - percent * 2.0, - mtwist_rand (&mt) & 255, - 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); - len += dist; - pos += len * vec; - pscale = pscalenext; - } -} - -static void -R_ParticleExplosion_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < 1024; i++) { - ptype_t type = i & 1 ? pt_explode2 : pt_explode; - add_particle (type, org + roffs (32), roffs (512), 5, - 0, mtwist_rand (&mt) & 3); - } -} - -static void -R_BlobExplosion_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < 1024; i++) { - ptype_t type = i & 1 ? pt_blob : pt_blob2; - int color = i & 1 ? 66 : 150; - add_particle (type, org + roffs (32), roffs (512), - color + mtwist_rand (&mt) % 6, - (color & ~7) + (mtwist_rand (&mt) & 7), 0); - } -} - -static inline void // FIXME: inline? -R_RunParticleEffect_ID (vec4f_t org, vec4f_t dir, int color, - int count) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < count; i++) { - add_particle (pt_slowgrav, org + roffs (16), - dir/* + roffs (300)*/, - 0.1 * (mtwist_rand (&mt) % 5), - (color & ~7) + (mtwist_rand (&mt) & 7), 0); - } -} - -static void -R_BloodPuffEffect_ID (vec4f_t org, int count) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 73, count); -} - -static void -R_GunshotEffect_ID (vec4f_t org, int count) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 0, count); -} - -static void -R_LightningBloodEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 225, 50); -} - -static void -R_SpikeEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 0, 10); -} - -static void -R_SuperSpikeEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 0, 20); -} - -static void -R_KnightSpikeEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 226, 20); -} - -static void -R_WizSpikeEffect_ID (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_ID (org, zero, 20, 30); -} - -static void -R_LavaSplash_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i++) { - for (int j = -16; j < 16; j++) { - for (int k = 0; k < 1; k++) { - float vel = 50 + (mtwist_rand (&mt) & 63); - vec4f_t dir = { - j * 8 + (mtwist_rand (&mt) & 7), - i * 8 + (mtwist_rand (&mt) & 7), - 256, - 0 - }; - vec4f_t offs = { - dir[0], - dir[1], - (mtwist_rand (&mt) & 63), - 0 - }; - dir = normalf (dir); - add_particle (pt_grav, org + offs, vel * dir, - 2 + (mtwist_rand (&mt) & 31) * 0.02, - 224 + (mtwist_rand (&mt) & 7), 0); - } - } - } -} - -static void -R_TeleportSplash_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i += 4) { - for (int j = -16; j < 16; j += 4) { - for (int k = -24; k < 32; k += 4) { - float vel = 50 + (mtwist_rand (&mt) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + (mtwist_rand (&mt) & 3), - j + (mtwist_rand (&mt) & 3), - k + (mtwist_rand (&mt) & 3), - 0 - }; - add_particle (pt_grav, org + offs, vel * dir, - 0.2 + (mtwist_rand (&mt) & 7) * 0.02, - 7 + (mtwist_rand (&mt) & 7), 0); - } - } - } -} - -static void -R_DarkFieldParticles_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i += 8) { - for (int j = -16; j < 16; j += 8) { - for (int k = 0; k < 32; k += 8) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50 + ((rnd >> 9) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + ((rnd >> 3) & 3), - j + ((rnd >> 5) & 3), - k + ((rnd >> 7) & 3), - 0 - }; - - add_particle (pt_slowgrav, org + offs, vel * dir, - 0.2 + (rnd & 7) * 0.02, - 150 + mtwist_rand (&mt) % 6, 0); - } - } - } -} - -static vec4f_t velocities[NUMVERTEXNORMALS]; -static vec4f_t normals[NUMVERTEXNORMALS] = { -#include "anorms.h" -}; - -static void -R_EntityParticles_ID (vec4f_t org) -{ - int i; - float angle, sp, sy, cp, cy; // cr, sr - float beamlength = 16.0, dist = 64.0; - - if (!r_particles->int_val) - return; - - for (i = 0; i < NUMVERTEXNORMALS; i++) { - int k; - for (k = 0; k < 3; k++) { - velocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; - } - } - - vec4f_t zero = {}; - for (i = 0; i < NUMVERTEXNORMALS; i++) { - angle = vr_data.realtime * velocities[i][0]; - cy = cos (angle); - sy = sin (angle); - angle = vr_data.realtime * velocities[i][1]; - cp = cos (angle); - sp = sin (angle); -// Next 3 lines results aren't currently used, may be in future. --Despair -// angle = vr_data.realtime * avelocities[i][2]; -// sr = sin (angle); -// cr = cos (angle); - - vec4f_t forward = { cp * cy, cp * sy, -sp, 0 }; - vec4f_t pos = org + normals[i] * dist + forward * beamlength; - //FIXME 0 velocity? - add_particle (pt_explode, pos, zero, 0.01, 0x6f, 0); - } -} - -static void -R_RocketTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_fire, pos + roffs (6), zero, 2, - 0, (mtwist_rand (&mt) & 3)); - pos += vec; - } -} - -static void -R_GrenadeTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_fire, pos + roffs (6), zero, 2, - 0, (mtwist_rand (&mt) & 3) + 2); - pos += vec; - } -} - -static void -R_BloodTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_slowgrav, pos + roffs (6), zero, 2, - 67 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - -static void -R_SlightBloodTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 6; - add_particle (pt_slowgrav, pos + roffs (6), zero, 2, - 67 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - -static void -R_WizTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t pos = start; - while (len > 0) { - static int tracercount; - len -= 3; - add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, - 52 + ((tracercount & 4) << 1), 0); - tracercount++; - pos += vec; - } -} - -static void -R_FlameTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t pos = start; - while (len > 0) { - static int tracercount; - len -= 3; - add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, - 230 + ((tracercount & 4) << 1), 0); - tracercount++; - pos += vec; - } -} - -static void -R_VoorTrail_ID (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_static, pos + roffs (16), zero, 0.3, - 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - static void draw_qf_particles (void) { @@ -1595,179 +469,13 @@ glsl_R_DrawParticles (void) { if (!r_particles->int_val || !numparticles) return; - if (r_particles_style->int_val) { + if (0/*FIXME r_particles_style->int_val*/) { draw_qf_particles (); } else { draw_id_particles (); } } -static void -glsl_R_Particle_New (ptype_t type, int texnum, vec4f_t org, float scale, - vec4f_t vel, float live, int color, float alpha, - float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_new (type, texnum, org, scale, vel, live, color, alpha, ramp); -} - -static void -glsl_R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, - int org_fuzz, float scale, int vel_fuzz, float live, - int color, float alpha, float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, live, - color, alpha, ramp); -} - -static vid_particle_funcs_t particles_QF = { - R_RocketTrail_QF, - R_GrenadeTrail_QF, - R_BloodTrail_QF, - R_SlightBloodTrail_QF, - R_WizTrail_QF, - R_FlameTrail_QF, - R_VoorTrail_QF, - R_GlowTrail_QF, - R_RunParticleEffect_QF, - R_BloodPuffEffect_QF, - R_GunshotEffect_QF, - R_LightningBloodEffect_QF, - R_SpikeEffect_QF, - R_KnightSpikeEffect_QF, - R_SuperSpikeEffect_QF, - R_WizSpikeEffect_QF, - R_BlobExplosion_QF, - R_ParticleExplosion_QF, - R_ParticleExplosion2_QF, - R_LavaSplash_QF, - R_TeleportSplash_QF, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -static vid_particle_funcs_t particles_ID = { - R_RocketTrail_ID, - R_GrenadeTrail_ID, - R_BloodTrail_ID, - R_SlightBloodTrail_ID, - R_WizTrail_ID, - R_FlameTrail_ID, - R_VoorTrail_ID, - R_GlowTrail_QF, - R_RunParticleEffect_ID, - R_BloodPuffEffect_ID, - R_GunshotEffect_ID, - R_LightningBloodEffect_ID, - R_SpikeEffect_ID, - R_KnightSpikeEffect_ID, - R_SuperSpikeEffect_ID, - R_WizSpikeEffect_ID, - R_BlobExplosion_ID, - R_ParticleExplosion_ID, - R_ParticleExplosion2_QF, - R_LavaSplash_ID, - R_TeleportSplash_ID, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -static vid_particle_funcs_t particles_QF_egg = { - R_RocketTrail_EE, - R_GrenadeTrail_EE, - R_BloodTrail_QF, - R_SlightBloodTrail_QF, - R_WizTrail_QF, - R_FlameTrail_QF, - R_VoorTrail_QF, - R_GlowTrail_QF, - R_RunParticleEffect_QF, - R_BloodPuffEffect_QF, - R_GunshotEffect_QF, - R_LightningBloodEffect_QF, - R_SpikeEffect_QF, - R_KnightSpikeEffect_QF, - R_SuperSpikeEffect_QF, - R_WizSpikeEffect_QF, - R_BlobExplosion_QF, - R_ParticleExplosion_EE, - R_ParticleExplosion2_QF, - R_LavaSplash_QF, - R_TeleportSplash_EE, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -static vid_particle_funcs_t particles_ID_egg = { - R_RocketTrail_EE, - R_GrenadeTrail_EE, - R_BloodTrail_ID, - R_SlightBloodTrail_ID, - R_WizTrail_ID, - R_FlameTrail_ID, - R_VoorTrail_ID, - R_GlowTrail_QF, - R_RunParticleEffect_ID, - R_BloodPuffEffect_ID, - R_GunshotEffect_ID, - R_LightningBloodEffect_ID, - R_SpikeEffect_ID, - R_KnightSpikeEffect_ID, - R_SuperSpikeEffect_ID, - R_WizSpikeEffect_ID, - R_BlobExplosion_ID, - R_ParticleExplosion_EE, - R_ParticleExplosion2_QF, - R_LavaSplash_ID, - R_TeleportSplash_EE, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -void -glsl_r_easter_eggs_f (cvar_t *var) -{ - if (easter_eggs) { - if (easter_eggs->int_val) { - if (r_particles_style->int_val) { - glsl_vid_render_funcs.particles = &particles_QF_egg; - } else { - glsl_vid_render_funcs.particles = &particles_ID_egg; - } - } else if (r_particles_style) { - if (r_particles_style->int_val) { - glsl_vid_render_funcs.particles = &particles_QF; - } else { - glsl_vid_render_funcs.particles = &particles_ID; - } - } - } -} - -void -glsl_r_particles_style_f (cvar_t *var) -{ - glsl_r_easter_eggs_f (easter_eggs); -} - -static void -R_ParticleFunctionInit (void) -{ - glsl_r_particles_style_f (r_particles_style); - glsl_r_easter_eggs_f (easter_eggs); -} - static void r_particles_nearclip_f (cvar_t *var) { @@ -1790,8 +498,6 @@ r_particles_max_f (cvar_t *var) void glsl_R_Particles_Init_Cvars (void) { - easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, r_easter_eggs_f, - "Enables easter eggs."); r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, "Toggles drawing of particles."); r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, @@ -1802,8 +508,4 @@ glsl_R_Particles_Init_Cvars (void) CVAR_ARCHIVE, r_particles_nearclip_f, "Distance of the particle near clipping " "plane from the player."); - r_particles_style = Cvar_Get ("r_particles_style", "1", CVAR_ARCHIVE, - r_particles_style_f, "Sets particle style. " - "0 for Id, 1 for QF."); - R_ParticleFunctionInit (); } diff --git a/libs/video/renderer/glsl/namehack.h b/libs/video/renderer/glsl/namehack.h index 6a8377a9d..62e75dc87 100644 --- a/libs/video/renderer/glsl/namehack.h +++ b/libs/video/renderer/glsl/namehack.h @@ -35,7 +35,6 @@ #define R_BlendLightmaps glsl_R_BlendLightmaps #define R_BuildLightMap glsl_R_BuildLightMap #define R_CalcLightmaps glsl_R_CalcLightmaps -#define R_ClearParticles glsl_R_ClearParticles #define R_ClearState glsl_R_ClearState #define R_ClearTextures glsl_R_ClearTextures #define R_DrawAliasModel glsl_R_DrawAliasModel @@ -91,7 +90,6 @@ #undef R_BlendLightmaps #undef R_BuildLightMap #undef R_CalcLightmaps -#undef R_ClearParticles #undef R_ClearState #undef R_ClearTextures #undef R_DrawAliasModel diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index 72a537223..24a9b6234 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -41,8 +41,6 @@ #include "compat.h" #include "r_internal.h" -cvar_t *easter_eggs; - cvar_t *cl_crossx; cvar_t *cl_crossy; cvar_t *cl_verstring; @@ -80,7 +78,6 @@ cvar_t *r_novis; cvar_t *r_numedges; cvar_t *r_numsurfs; cvar_t *r_particles; -cvar_t *r_particles_style; cvar_t *r_particles_max; cvar_t *r_particles_nearclip; cvar_t *r_reportedgeout; diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index 5a610f9f3..b2c83fc02 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -77,60 +77,11 @@ R_MaxParticlesCheck (cvar_t *r_particles, cvar_t *r_particles_max) partparams = (partparm_t *) &particles[r_maxparticles]; partramps = (const int **) &partparams[r_maxparticles]; } - - vr_funcs->R_ClearParticles (); - - if (r_init) - vr_funcs->R_InitParticles (); + R_ClearParticles (); } -static int ramp[] = { - /*ramp1*/ 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61, - /*ramp2*/ 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66, - /*ramp3*/ 0x6d, 0x6b, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, -}; - -static partparm_t part_params[] = { - [pt_static] = {{0, 0, 0, 0}, 0, 1, 0, 0}, - [pt_grav] = {{0, 0, 0, 0.05}, 0, 1, 0, 0}, - [pt_slowgrav] = {{0, 0, 0, 0.05}, 0, 1, 0, 0}, - [pt_fire] = {{0, 0, 0, 0.05}, 5, 6, 0, 5./6}, - [pt_explode] = {{4, 4, 4, 0.05}, 10, 8, 0, 0}, - [pt_explode2] = {{1, 1, 1, 0.05}, 15, 8, 0, 0}, - [pt_blob] = {{4, 4, 4, 0.05}, 0, 1, 0, 0}, - [pt_blob2] = {{4, 4, 0, 0.05}, 0, 1, 0, 0}, - [pt_smoke] = {{0, 0, 0, 0}, 0, 1, 4, 0.4}, - [pt_smokecloud] = {{0, 0, 0, 0.0375}, 0, 1, 50, 0.55}, - [pt_bloodcloud] = {{0, 0, 0, 0.05}, 0, 1, 4, 0.25}, - [pt_fadespark] = {{0, 0, 0, 0}, 0, 1, 0, 0}, - [pt_fadespark2] = {{0, 0, 0, 0}, 0, 1, 0, 0}, - [pt_fallfade] = {{0, 0, 0, 1}, 0, 1, 0, 1}, - [pt_fallfadespark] = {{0, 0, 0, 1}, 15, 8, 0, 1}, - [pt_flame] = {{0, 0, 0, 0}, 0, 1, -2, 0.125}, -}; - -static const int *part_ramps[] = { - [pt_fire] = ramp + 2 * 8, // ramp3 - [pt_explode] = ramp + 0 * 8, // ramp1 - [pt_explode2] = ramp + 1 * 8, // ramp2 - [pt_fallfadespark] = ramp + 0 * 8, // ramp1 - [pt_flame] = 0, -}; - -partparm_t -R_ParticlePhysics (ptype_t type) +void +R_ClearParticles (void) { - if (type > pt_flame) { - Sys_Error ("R_ParticlePhysics: invalid particle type"); - } - return part_params[type]; -} - -const int * -R_ParticleRamp (ptype_t type) -{ - if (type > pt_flame) { - Sys_Error ("R_ParticleRamp: invalid particle type"); - } - return part_ramps[type]; + numparticles = 0; } diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 93cc58493..d99259e4b 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -131,12 +131,9 @@ sw_R_Init (void) #endif R_InitTurb (); - R_InitParticles (); Cmd_AddCommand ("timerefresh", R_TimeRefresh_f, "Tests the current " "refresh rate for the current location"); - Cmd_AddCommand ("pointfile", R_ReadPointFile_f, "Load a pointfile to " - "determine map leaks"); Cmd_AddCommand ("loadsky", R_LoadSky_f, "Load a skybox"); Cvar_SetValue (r_maxedges, (float) NUMSTACKEDGES); diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index ede081f77..ceeda14a0 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -49,486 +49,6 @@ #include "compat.h" #include "r_internal.h" -static mtstate_t mt; // private PRNG state - -static vec4f_t -roffs (int mod) -{ - vec4f_t offs = { - (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), - (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), - (mtwist_rand (&mt) % mod) - 0.5 * (mod - 1), - 0 - }; - return offs; -} - -static vec4f_t -tracer_vel (int tracercount, vec4f_t vec) -{ - if (tracercount & 1) { - return (vec4f_t) { vec[1], -vec[0], 0, 0 }; - } else { - return (vec4f_t) { -vec[1], vec[0], 0, 0 }; - } -} - -static void -add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, - float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_t *p = &particles[numparticles]; - partparm_t *parm = &partparams[numparticles]; - const int **rampptr = &partramps[numparticles]; - numparticles += 1; - - p->pos = pos; - p->vel = vel; - p->icolor = color; - p->alpha = 1; - p->tex = 0; - p->ramp = ramp; - p->scale = 1; - p->live = live; - - *parm = R_ParticlePhysics (type); - *rampptr = R_ParticleRamp (type); - if (*rampptr) { - p->icolor = (*rampptr) [(int) p->ramp]; - } -} - -void -R_InitParticles (void) -{ - mtwist_seed (&mt, 0xdeadbeef); -} - -void -R_ClearParticles (void) -{ - if (r_maxparticles) { - memset (particles, 0, r_maxparticles * sizeof (*particles)); - } -} - -void -R_ReadPointFile_f (void) -{ - QFile *f; - int c, r; - const char *name; - char *mapname; - vec4f_t zero = {}; - - mapname = strdup (r_worldentity.renderer.model->path); - if (!mapname) - Sys_Error ("Can't duplicate mapname!"); - QFS_StripExtension (mapname, mapname); - - name = va (0, "maps/%s.pts", mapname); - free (mapname); - - f = QFS_FOpenFile (name); - if (!f) { - Sys_Printf ("couldn't open %s\n", name); - return; - } - - Sys_Printf ("Reading %s...\n", name); - c = 0; - for (;;) { - char buf[64]; - vec4f_t org = { 0, 0, 0, 1 }; - - Qgets (f, buf, sizeof (buf)); - r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); - if (r != 3) - break; - c++; - - //if (!free_particles) { - // Sys_Printf ("Not enough free particles\n"); - // break; - //} - add_particle (pt_static, org, zero, INFINITY, (-c) & 15, 0); - } - - Qclose (f); - Sys_Printf ("%i points read\n", c); -} - -static void -R_ParticleExplosion_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < 1024; i++) { - ptype_t type = i & 1 ? pt_explode2 : pt_explode; - add_particle (type, org + roffs (32), roffs (512), 5, - 0, mtwist_rand (&mt) & 3); - } -} - -static void -R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) -{ - int colorMod = 0; - - for (int i=0; i<512; i++) { - add_particle (pt_blob, org + roffs (32), roffs (512), 0.3, - colorStart + (colorMod % colorLength), 0); - } -} - -static void -R_BlobExplosion_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < 1024; i++) { - ptype_t type = i & 1 ? pt_blob : pt_blob2; - int color = i & 1 ? 66 : 150; - add_particle (type, org + roffs (32), roffs (512), - color + mtwist_rand (&mt) % 6, - (color & ~7) + (mtwist_rand (&mt) & 7), 0); - } -} - -static void -R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, int count) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < count; i++) { - add_particle (pt_slowgrav, org + roffs (16), - dir/* + roffs (300)*/, - 0.1 * (mtwist_rand (&mt) % 5), - (color & ~7) + (mtwist_rand (&mt) & 7), 0); - } -} - -static void -R_SpikeEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 0, 10); -} - -static void -R_SuperSpikeEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 0, 20); -} - -static void -R_KnightSpikeEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 226, 20); -} - -static void -R_WizSpikeEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 20, 30); -} - -static void -R_BloodPuffEffect_QF (vec4f_t org, int count) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 73, count); -} - -static void -R_GunshotEffect_QF (vec4f_t org, int count) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 0, count); -} - -static void -R_LightningBloodEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 225, 50); -} - -static void -R_LavaSplash_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i++) { - for (int j = -16; j < 16; j++) { - for (int k = 0; k < 1; k++) { - float vel = 50 + (mtwist_rand (&mt) & 63); - vec4f_t dir = { - j * 8 + (mtwist_rand (&mt) & 7), - i * 8 + (mtwist_rand (&mt) & 7), - 256, - 0 - }; - vec4f_t offs = { - dir[0], - dir[1], - (mtwist_rand (&mt) & 63), - 0 - }; - dir = normalf (dir); - add_particle (pt_grav, org + offs, vel * dir, - 2 + (mtwist_rand (&mt) & 31) * 0.02, - 224 + (mtwist_rand (&mt) & 7), 0); - } - } - } -} - -static void -R_TeleportSplash_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i += 4) { - for (int j = -16; j < 16; j += 4) { - for (int k = -24; k < 32; k += 4) { - float vel = 50 + (mtwist_rand (&mt) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + (mtwist_rand (&mt) & 3), - j + (mtwist_rand (&mt) & 3), - k + (mtwist_rand (&mt) & 3), - 0 - }; - add_particle (pt_grav, org + offs, vel * dir, - 0.2 + (mtwist_rand (&mt) & 7) * 0.02, - 7 + (mtwist_rand (&mt) & 7), 0); - } - } - } -} - -static void -R_DarkFieldParticles_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i += 8) { - for (int j = -16; j < 16; j += 8) { - for (int k = 0; k < 32; k += 8) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50 + ((rnd >> 9) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + ((rnd >> 3) & 3), - j + ((rnd >> 5) & 3), - k + ((rnd >> 7) & 3), - 0 - }; - - add_particle (pt_slowgrav, org + offs, vel * dir, - 0.2 + (rnd & 7) * 0.02, - 150 + mtwist_rand (&mt) % 6, 0); - } - } - } -} - -static vec4f_t velocities[NUMVERTEXNORMALS]; -static vec4f_t normals[NUMVERTEXNORMALS] = { -#include "anorms.h" -}; - -static void -R_EntityParticles_ID (vec4f_t org) -{ - int i; - float angle, sp, sy, cp, cy; // cr, sr - float beamlength = 16.0, dist = 64.0; - - if (!r_particles->int_val) - return; - - for (i = 0; i < NUMVERTEXNORMALS; i++) { - int k; - for (k = 0; k < 3; k++) { - velocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; - } - } - - vec4f_t zero = {}; - for (i = 0; i < NUMVERTEXNORMALS; i++) { - angle = vr_data.realtime * velocities[i][0]; - cy = cos (angle); - sy = sin (angle); - angle = vr_data.realtime * velocities[i][1]; - cp = cos (angle); - sp = sin (angle); -// Next 3 lines results aren't currently used, may be in future. --Despair -// angle = vr_data.realtime * avelocities[i][2]; -// sr = sin (angle); -// cr = cos (angle); - - vec4f_t forward = { cp * cy, cp * sy, -sp, 0 }; - vec4f_t pos = org + normals[i] * dist + forward * beamlength; - //FIXME 0 velocity? - add_particle (pt_explode, pos, zero, 0.01, 0x6f, 0); - } -} - -static void -R_RocketTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_fire, pos + roffs (6), zero, 2, - 0, (mtwist_rand (&mt) & 3)); - pos += vec; - } -} - -static void -R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_fire, pos + roffs (6), zero, 2, - 0, (mtwist_rand (&mt) & 3) + 2); - pos += vec; - } -} - -static void -R_BloodTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_slowgrav, pos + roffs (6), zero, 2, - 67 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - -static void -R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 6; - add_particle (pt_slowgrav, pos + roffs (6), zero, 2, - 67 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - -static void -R_WizTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t pos = start; - while (len > 0) { - static int tracercount; - len -= 3; - add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, - 52 + ((tracercount & 4) << 1), 0); - tracercount++; - pos += vec; - } -} - -static void -R_FlameTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t pos = start; - while (len > 0) { - static int tracercount; - len -= 3; - add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, - 230 + ((tracercount & 4) << 1), 0); - tracercount++; - pos += vec; - } -} - -static void -R_VoorTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_static, pos + roffs (16), zero, 0.3, - 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - void R_DrawParticles (void) { @@ -570,80 +90,6 @@ R_DrawParticles (void) numparticles = j; } -void -r_easter_eggs_f (cvar_t *var) -{ -} - -void -r_particles_style_f (cvar_t *var) -{ -} - -static void -R_Particle_New (ptype_t type, int texnum, vec4f_t pos, float scale, - vec4f_t vel, float live, int color, float alpha, float ramp) -{ - add_particle (type, pos, vel, live, color, ramp); -} - -static void -R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, int org_fuzz, - float scale, int vel_fuzz, float live, int color, - float alpha, float ramp) -{ - float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; - int rnd; - vec4f_t pos, vel; - - rnd = mtwist_rand (&mt); - pos[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; - pos[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; - pos[2] = o_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0 + org[2]; - pos[3] = 1; - rnd = mtwist_rand (&mt); - vel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; - vel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; - vel[2] = v_fuzz * (((rnd >> 10) & 63) - 31.5) / 63.0; - vel[3] = 0; - - add_particle (type, pos, vel, live, color, ramp); -} - -static vid_particle_funcs_t particles_QF = { - R_RocketTrail_QF, - R_GrenadeTrail_QF, - R_BloodTrail_QF, - R_SlightBloodTrail_QF, - R_WizTrail_QF, - R_FlameTrail_QF, - R_VoorTrail_QF, - 0,//R_GlowTrail_QF, - R_RunParticleEffect_QF, - R_BloodPuffEffect_QF, - R_GunshotEffect_QF, - R_LightningBloodEffect_QF, - R_SpikeEffect_QF, - R_KnightSpikeEffect_QF, - R_SuperSpikeEffect_QF, - R_WizSpikeEffect_QF, - R_BlobExplosion_QF, - R_ParticleExplosion_QF, - R_ParticleExplosion2_QF, - R_LavaSplash_QF, - R_TeleportSplash_QF, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -static void -R_ParticleFunctionInit (void) -{ - sw_vid_render_funcs.particles = &particles_QF; -} - static void r_particles_nearclip_f (cvar_t *var) { @@ -666,8 +112,6 @@ r_particles_max_f (cvar_t *var) void R_Particles_Init_Cvars (void) { - easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, r_easter_eggs_f, - "Enables easter eggs."); r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, "Toggles drawing of particles."); r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, @@ -678,8 +122,4 @@ R_Particles_Init_Cvars (void) CVAR_ARCHIVE, r_particles_nearclip_f, "Distance of the particle near clipping " "plane from the player."); - r_particles_style = Cvar_Get ("r_particles_style", "1", CVAR_ARCHIVE, - r_particles_style_f, "Sets particle style. " - "0 for Id, 1 for QF."); - R_ParticleFunctionInit (); } diff --git a/libs/video/renderer/sw32/namehack.h b/libs/video/renderer/sw32/namehack.h index 6642d2d54..b1cf44f01 100644 --- a/libs/video/renderer/sw32/namehack.h +++ b/libs/video/renderer/sw32/namehack.h @@ -65,7 +65,6 @@ #define R_Alias_clip_top sw32_R_Alias_clip_top #define R_IQMDrawModel sw32_R_IQMDrawModel #define R_BeginEdgeFrame sw32_R_BeginEdgeFrame -#define R_ClearParticles sw32_R_ClearParticles #define R_ClearState sw32_R_ClearState #define R_ClipEdge sw32_R_ClipEdge #define R_DrawParticles sw32_R_DrawParticles @@ -305,7 +304,6 @@ extern struct surf_s *sw32_surfaces; #undef R_Alias_clip_top #undef R_IQMDrawModel #undef R_BeginEdgeFrame -#undef R_ClearParticles #undef R_ClearState #undef R_ClipEdge #undef R_DrawParticles diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 01a99be25..2dc129df9 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -151,12 +151,9 @@ sw32_R_Init (void) sw32_Draw_Init (); SCR_Init (); sw32_R_InitTurb (); - sw32_R_InitParticles (); Cmd_AddCommand ("timerefresh", sw32_R_TimeRefresh_f, "Tests the current " "refresh rate for the current location"); - Cmd_AddCommand ("pointfile", sw32_R_ReadPointFile_f, "Load a pointfile to " - "determine map leaks"); Cmd_AddCommand ("loadsky", sw32_R_LoadSky_f, "Load a skybox"); Cvar_SetValue (r_maxedges, (float) NUMSTACKEDGES); @@ -198,7 +195,7 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_viewleaf = NULL; R_MarkLeaves (); - sw32_R_ClearParticles (); + R_ClearParticles (); r_cnumsurfs = r_maxsurfs->int_val; @@ -875,5 +872,5 @@ sw32_R_ClearState (void) r_worldentity.renderer.model = 0; R_ClearEfrags (); R_ClearDlights (); - sw32_R_ClearParticles (); + R_ClearParticles (); } diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 26a9255ed..4bef2bc2b 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -52,486 +52,6 @@ #include "compat.h" #include "r_internal.h" -static mtstate_t mt; // private PRNG state - -static vec4f_t -roffs (int mod) -{ - vec4f_t offs = { - (mtwist_rand (&mt) & mod) - 0.5 * (mod - 1), - (mtwist_rand (&mt) & mod) - 0.5 * (mod - 1), - (mtwist_rand (&mt) & mod) - 0.5 * (mod - 1), - 0 - }; - return offs; -} - -static vec4f_t -tracer_vel (int tracercount, vec4f_t vec) -{ - if (tracercount & 1) { - return (vec4f_t) { vec[1], -vec[0], 0, 0 }; - } else { - return (vec4f_t) { -vec[1], vec[0], 0, 0 }; - } -} - -static void -add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, - float ramp) -{ - if (numparticles >= r_maxparticles) - return; - particle_t *p = &particles[numparticles]; - partparm_t *parm = &partparams[numparticles]; - const int **rampptr = &partramps[numparticles]; - numparticles += 1; - - p->pos = pos; - p->vel = vel; - p->icolor = color; - p->alpha = 1; - p->tex = 0; - p->ramp = ramp; - p->scale = 1; - p->live = live; - - *parm = R_ParticlePhysics (type); - *rampptr = R_ParticleRamp (type); - if (*rampptr) { - p->icolor = (*rampptr) [(int) p->ramp]; - } -} - -void -sw32_R_InitParticles (void) -{ - mtwist_seed (&mt, 0xdeadbeef); -} - -void -sw32_R_ClearParticles (void) -{ - if (r_maxparticles) { - memset (particles, 0, r_maxparticles * sizeof (*particles)); - } -} - -void -sw32_R_ReadPointFile_f (void) -{ - QFile *f; - int c, r; - const char *name; - char *mapname; - vec4f_t zero = {}; - - mapname = strdup (r_worldentity.renderer.model->path); - if (!mapname) - Sys_Error ("Can't duplicate mapname!"); - QFS_StripExtension (mapname, mapname); - - name = va (0, "maps/%s.pts", mapname); - free (mapname); - - f = QFS_FOpenFile (name); - if (!f) { - Sys_Printf ("couldn't open %s\n", name); - return; - } - - Sys_Printf ("Reading %s...\n", name); - c = 0; - for (;;) { - char buf[64]; - vec4f_t org = { 0, 0, 0, 1 }; - - Qgets (f, buf, sizeof (buf)); - r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); - if (r != 3) - break; - c++; - - //if (!free_particles) { - // Sys_Printf ("Not enough free particles\n"); - // break; - //} - add_particle (pt_static, org, zero, INFINITY, (-c) & 15, 0); - } - - Qclose (f); - Sys_Printf ("%i points read\n", c); -} - -static void -R_ParticleExplosion_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < 1024; i++) { - ptype_t type = i & 1 ? pt_explode2 : pt_explode; - add_particle (type, org + roffs (32), roffs (512), 5, - 0, mtwist_rand (&mt) & 3); - } -} - -static void -R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) -{ - int colorMod = 0; - - for (int i=0; i<512; i++) { - add_particle (pt_blob, org + roffs (32), roffs (512), 0.3, - colorStart + (colorMod % colorLength), 0); - } -} - -static void -R_BlobExplosion_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < 1024; i++) { - ptype_t type = i & 1 ? pt_blob : pt_blob2; - int color = i & 1 ? 66 : 150; - add_particle (type, org + roffs (32), roffs (512), - color + mtwist_rand (&mt) % 6, - (color & ~7) + (mtwist_rand (&mt) & 7), 0); - } -} - -static void -R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, int count) -{ - if (!r_particles->int_val) - return; - - for (int i = 0; i < count; i++) { - add_particle (pt_slowgrav, org + roffs (16), - dir/* + roffs (300)*/, - 0.1 * (mtwist_rand (&mt) % 5), - (color & ~7) + (mtwist_rand (&mt) & 7), 0); - } -} - -static void -R_SpikeEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 0, 10); -} - -static void -R_SuperSpikeEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 0, 20); -} - -static void -R_KnightSpikeEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 226, 20); -} - -static void -R_WizSpikeEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 20, 30); -} - -static void -R_BloodPuffEffect_QF (vec4f_t org, int count) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 73, count); -} - -static void -R_GunshotEffect_QF (vec4f_t org, int count) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 0, count); -} - -static void -R_LightningBloodEffect_QF (vec4f_t org) -{ - vec4f_t zero = {}; - R_RunParticleEffect_QF (org, zero, 225, 50); -} - -static void -R_LavaSplash_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i++) { - for (int j = -16; j < 16; j++) { - for (int k = 0; k < 1; k++) { - float vel = 50 + (mtwist_rand (&mt) & 63); - vec4f_t dir = { - j * 8 + (mtwist_rand (&mt) & 7), - i * 8 + (mtwist_rand (&mt) & 7), - 256, - 0 - }; - vec4f_t offs = { - dir[0], - dir[1], - (mtwist_rand (&mt) & 63), - 0 - }; - dir = normalf (dir); - add_particle (pt_grav, org + offs, vel * dir, - 2 + (mtwist_rand (&mt) & 31) * 0.02, - 224 + (mtwist_rand (&mt) & 7), 0); - } - } - } -} - -static void -R_TeleportSplash_QF (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i += 4) { - for (int j = -16; j < 16; j += 4) { - for (int k = -24; k < 32; k += 4) { - float vel = 50 + (mtwist_rand (&mt) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + (mtwist_rand (&mt) & 3), - j + (mtwist_rand (&mt) & 3), - k + (mtwist_rand (&mt) & 3), - 0 - }; - add_particle (pt_grav, org + offs, vel * dir, - 0.2 + (mtwist_rand (&mt) & 7) * 0.02, - 7 + (mtwist_rand (&mt) & 7), 0); - } - } - } -} - -static void -R_DarkFieldParticles_ID (vec4f_t org) -{ - if (!r_particles->int_val) - return; - - for (int i = -16; i < 16; i += 8) { - for (int j = -16; j < 16; j += 8) { - for (int k = 0; k < 32; k += 8) { - uint32_t rnd = mtwist_rand (&mt); - float vel = 50 + ((rnd >> 9) & 63); - vec4f_t dir = normalf ((vec4f_t) { j, i, k, 0 } * 8); - vec4f_t offs = { - i + ((rnd >> 3) & 3), - j + ((rnd >> 5) & 3), - k + ((rnd >> 7) & 3), - 0 - }; - - add_particle (pt_slowgrav, org + offs, vel * dir, - 0.2 + (rnd & 7) * 0.02, - 150 + mtwist_rand (&mt) % 6, 0); - } - } - } -} - -static vec4f_t velocities[NUMVERTEXNORMALS]; -static vec4f_t normals[NUMVERTEXNORMALS] = { -#include "anorms.h" -}; - -static void -R_EntityParticles_ID (vec4f_t org) -{ - int i; - float angle, sp, sy, cp, cy; // cr, sr - float beamlength = 16.0, dist = 64.0; - - if (!r_particles->int_val) - return; - - for (i = 0; i < NUMVERTEXNORMALS; i++) { - int k; - for (k = 0; k < 3; k++) { - velocities[i][k] = (mtwist_rand (&mt) & 255) * 0.01; - } - } - - vec4f_t zero = {}; - for (i = 0; i < NUMVERTEXNORMALS; i++) { - angle = vr_data.realtime * velocities[i][0]; - cy = cos (angle); - sy = sin (angle); - angle = vr_data.realtime * velocities[i][1]; - cp = cos (angle); - sp = sin (angle); -// Next 3 lines results aren't currently used, may be in future. --Despair -// angle = vr_data.realtime * avelocities[i][2]; -// sr = sin (angle); -// cr = cos (angle); - - vec4f_t forward = { cp * cy, cp * sy, -sp, 0 }; - vec4f_t pos = org + normals[i] * dist + forward * beamlength; - //FIXME 0 velocity? - add_particle (pt_explode, pos, zero, 0.01, 0x6f, 0); - } -} - -static void -R_RocketTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_fire, pos + roffs (6), zero, 2, - 0, (mtwist_rand (&mt) & 3)); - pos += vec; - } -} - -static void -R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_fire, pos + roffs (6), zero, 2, - 0, (mtwist_rand (&mt) & 3) + 2); - pos += vec; - } -} - -static void -R_BloodTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_slowgrav, pos + roffs (6), zero, 2, - 67 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - -static void -R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 6; - add_particle (pt_slowgrav, pos + roffs (6), zero, 2, - 67 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - -static void -R_WizTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t pos = start; - while (len > 0) { - static int tracercount; - len -= 3; - add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, - 52 + ((tracercount & 4) << 1), 0); - tracercount++; - pos += vec; - } -} - -static void -R_FlameTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t pos = start; - while (len > 0) { - static int tracercount; - len -= 3; - add_particle (pt_static, pos, 30 * tracer_vel (tracercount, vec), 0.5, - 230 + ((tracercount & 4) << 1), 0); - tracercount++; - pos += vec; - } -} - -static void -R_VoorTrail_QF (vec4f_t start, vec4f_t end) -{ - if (!r_particles->int_val) - return; - - vec4f_t vec = end - start; - float len = magnitudef (vec)[0]; - vec = normalf (vec); - - vec4f_t zero = {}; - vec4f_t pos = start; - while (len > 0) { - len -= 3; - add_particle (pt_static, pos + roffs (16), zero, 0.3, - 9 * 16 + 8 + (mtwist_rand (&mt) & 3), 0); - pos += vec; - } -} - void sw32_R_DrawParticles (void) { @@ -573,81 +93,6 @@ sw32_R_DrawParticles (void) numparticles = j; } -void -sw32_r_easter_eggs_f (cvar_t *var) -{ -} - -void -sw32_r_particles_style_f (cvar_t *var) -{ -} - -static void -sw32_R_Particle_New (ptype_t type, int texnum, vec4f_t pos, float scale, - vec4f_t vel, float live, int color, float alpha, - float ramp) -{ - add_particle (type, pos, vel, live, color, ramp); -} - -static void -sw32_R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, - int org_fuzz, float scale, int vel_fuzz, float live, - int color, float alpha, float ramp) -{ - float o_fuzz = org_fuzz, v_fuzz = vel_fuzz; - int rnd; - vec4f_t pos, vel; - - rnd = mtwist_rand (&mt); - pos[0] = o_fuzz * ((rnd & 63) - 31.5) / 63.0 + org[0]; - pos[1] = o_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0 + org[1]; - pos[2] = o_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0 + org[2]; - pos[3] = 1; - rnd = mtwist_rand (&mt); - vel[0] = v_fuzz * ((rnd & 63) - 31.5) / 63.0; - vel[1] = v_fuzz * (((rnd >> 6) & 63) - 31.5) / 63.0; - vel[2] = v_fuzz * (((rnd >> 12) & 63) - 31.5) / 63.0; - vel[3] = 0; - - add_particle (type, pos, vel, live, color, ramp); -} - -static vid_particle_funcs_t particles_QF = { - R_RocketTrail_QF, - R_GrenadeTrail_QF, - R_BloodTrail_QF, - R_SlightBloodTrail_QF, - R_WizTrail_QF, - R_FlameTrail_QF, - R_VoorTrail_QF, - 0,//R_GlowTrail_QF, - R_RunParticleEffect_QF, - R_BloodPuffEffect_QF, - R_GunshotEffect_QF, - R_LightningBloodEffect_QF, - R_SpikeEffect_QF, - R_KnightSpikeEffect_QF, - R_SuperSpikeEffect_QF, - R_WizSpikeEffect_QF, - R_BlobExplosion_QF, - R_ParticleExplosion_QF, - R_ParticleExplosion2_QF, - R_LavaSplash_QF, - R_TeleportSplash_QF, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -static void -R_ParticleFunctionInit (void) -{ - sw32_vid_render_funcs.particles = &particles_QF; -} - static void r_particles_nearclip_f (cvar_t *var) { @@ -670,8 +115,6 @@ r_particles_max_f (cvar_t *var) void sw32_R_Particles_Init_Cvars (void) { - easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, r_easter_eggs_f, - "Enables easter eggs."); r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, "Toggles drawing of particles."); r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, @@ -682,8 +125,4 @@ sw32_R_Particles_Init_Cvars (void) CVAR_ARCHIVE, r_particles_nearclip_f, "Distance of the particle near clipping " "plane from the player."); - r_particles_style = Cvar_Get ("r_particles_style", "1", CVAR_ARCHIVE, - r_particles_style_f, "Sets particle style. " - "0 for Id, 1 for QF."); - R_ParticleFunctionInit (); } diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 850d13beb..e3b1d6597 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -155,12 +155,7 @@ vid_render_funcs_t gl_vid_render_funcs = { R_MaxDlightsCheck, R_DecayLights, gl_R_ViewChanged, - gl_R_ClearParticles, - gl_R_InitParticles, gl_SCR_ScreenShot_f, - gl_r_easter_eggs_f, - gl_r_particles_style_f, - 0, &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index a4ad536f4..836f2f6ed 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -154,12 +154,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { R_MaxDlightsCheck, R_DecayLights, glsl_R_ViewChanged, - glsl_R_ClearParticles, - glsl_R_InitParticles, glsl_SCR_ScreenShot_f, - glsl_r_easter_eggs_f, - glsl_r_particles_style_f, - 0, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index cc0186750..f888a979d 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -151,12 +151,7 @@ vid_render_funcs_t sw_vid_render_funcs = { R_MaxDlightsCheck, R_DecayLights, R_ViewChanged, - R_ClearParticles, - R_InitParticles, SCR_ScreenShot_f, - r_easter_eggs_f, - r_particles_style_f, - 0, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 3a3638c1a..b9a0acac7 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -156,12 +156,7 @@ vid_render_funcs_t sw32_vid_render_funcs = { R_MaxDlightsCheck, R_DecayLights, sw32_R_ViewChanged, - sw32_R_ClearParticles, - sw32_R_InitParticles, sw32_SCR_ScreenShot_f, - sw32_r_easter_eggs_f, - sw32_r_particles_style_f, - 0, &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 912a2c58c..cc7904d39 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -246,7 +246,7 @@ vulkan_R_ClearState (void) r_worldentity.renderer.model = 0; R_ClearEfrags (); R_ClearDlights (); - Vulkan_ClearParticles (vulkan_ctx); + R_ClearParticles (); } static void @@ -392,18 +392,6 @@ vulkan_R_ViewChanged (void) Vulkan_CalcProjectionMatrices (vulkan_ctx); } -static void -vulkan_R_ClearParticles (void) -{ - Vulkan_ClearParticles (vulkan_ctx); -} - -static void -vulkan_R_InitParticles (void) -{ - Vulkan_InitParticles (vulkan_ctx); -} - static int is_bgr (VkFormat format) { @@ -455,18 +443,6 @@ vulkan_SCR_ScreenShot_f (void) vulkan_ctx->capture_callback = capture_screenshot; } -static void -vulkan_r_easter_eggs_f (struct cvar_s *var) -{ - Vulkan_r_easter_eggs_f (var, vulkan_ctx); -} - -static void -vulkan_r_particles_style_f (struct cvar_s *var) -{ - Vulkan_r_particles_style_f (var, vulkan_ctx); -} - static void vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp) { @@ -700,12 +676,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { R_MaxDlightsCheck, R_DecayLights, vulkan_R_ViewChanged, - vulkan_R_ClearParticles, - vulkan_R_InitParticles, vulkan_SCR_ScreenShot_f, - vulkan_r_easter_eggs_f, - vulkan_r_particles_style_f, - 0, &model_funcs }; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 62775419e..06a99a046 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -198,7 +198,7 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, R_MarkLeaves (); R_FreeAllEntities (); - Vulkan_ClearParticles (ctx); + R_ClearParticles (); Vulkan_RegisterTextures (models, num_models, ctx); //Vulkan_BuildLightmaps (models, num_models, ctx); Vulkan_BuildDisplayLists (models, num_models, ctx); diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 8c6679ba2..6eb8e74ba 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -56,203 +56,6 @@ static const char * __attribute__((used)) particle_pass_names[] = { "draw", }; -void -Vulkan_ClearParticles (vulkan_ctx_t *ctx) -{ -} - -void -Vulkan_InitParticles (vulkan_ctx_t *ctx) -{ -} - -static void -R_RocketTrail_QF (vec4f_t start, vec4f_t end) -{ -} - -static void -R_GrenadeTrail_QF (vec4f_t start, vec4f_t end) -{ -} - -static void -R_BloodTrail_QF (vec4f_t start, vec4f_t end) -{ -} - -static void -R_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) -{ -} - -static void -R_WizTrail_QF (vec4f_t start, vec4f_t end) -{ -} - -static void -R_FlameTrail_QF (vec4f_t start, vec4f_t end) -{ -} - -static void -R_VoorTrail_QF (vec4f_t start, vec4f_t end) -{ -} - -static void -R_GlowTrail_QF (vec4f_t start, vec4f_t end, int glow_color) -{ -} - -static void -R_RunParticleEffect_QF (vec4f_t org, vec4f_t dir, int color, - int count) -{ -} - -static void -R_BloodPuffEffect_QF (vec4f_t org, int count) -{ -} - -static void -R_GunshotEffect_QF (vec4f_t org, int count) -{ -} - -static void -R_LightningBloodEffect_QF (vec4f_t org) -{ -} - -static void -R_SpikeEffect_QF (vec4f_t org) -{ -} - -static void -R_KnightSpikeEffect_QF (vec4f_t org) -{ -} - -static void -R_SuperSpikeEffect_QF (vec4f_t org) -{ -} - -static void -R_WizSpikeEffect_QF (vec4f_t org) -{ -} - -static void -R_BlobExplosion_QF (vec4f_t org) -{ -} - -static void -R_ParticleExplosion_QF (vec4f_t org) -{ -} - -static void -R_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) -{ -} - -static void -R_LavaSplash_QF (vec4f_t org) -{ -} - -static void -R_TeleportSplash_QF (vec4f_t org) -{ -} - -static void -R_DarkFieldParticles_ID (vec4f_t org) -{ -} - -static void -R_EntityParticles_ID (vec4f_t org) -{ -} - -static void -R_Particle_New (ptype_t type, int texnum, vec4f_t org, - float scale, vec4f_t vel, float die, - int color, float alpha, float ramp) -{ -} - -static void -R_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, - int org_fuzz, float scale, int vel_fuzz, - float die, int color, float alpha, - float ramp) -{ -} - -static vid_particle_funcs_t vulkan_particles_QF = { - R_RocketTrail_QF, - R_GrenadeTrail_QF, - R_BloodTrail_QF, - R_SlightBloodTrail_QF, - R_WizTrail_QF, - R_FlameTrail_QF, - R_VoorTrail_QF, - R_GlowTrail_QF, - R_RunParticleEffect_QF, - R_BloodPuffEffect_QF, - R_GunshotEffect_QF, - R_LightningBloodEffect_QF, - R_SpikeEffect_QF, - R_KnightSpikeEffect_QF, - R_SuperSpikeEffect_QF, - R_WizSpikeEffect_QF, - R_BlobExplosion_QF, - R_ParticleExplosion_QF, - R_ParticleExplosion2_QF, - R_LavaSplash_QF, - R_TeleportSplash_QF, - R_DarkFieldParticles_ID, - R_EntityParticles_ID, - R_Particle_New, - R_Particle_NewRandom, -}; - -void -Vulkan_r_easter_eggs_f (cvar_t *var, vulkan_ctx_t *ctx) -{ - if (!easter_eggs || !r_particles_style) { - return; - } - if (easter_eggs->int_val) { - if (r_particles_style->int_val) { - //vulkan_vid_render_funcs.particles = &vulkan_particles_QF_egg; - } else { - //vulkan_vid_render_funcs.particles = &vulkan_particles_ID_egg; - } - } else { - if (r_particles_style->int_val) { - //vulkan_vid_render_funcs.particles = &vulkan_particles_QF; - } else { - //vulkan_vid_render_funcs.particles = &vulkan_particles_ID; - } - } - vulkan_vid_render_funcs.particles = &vulkan_particles_QF; -} - -void -Vulkan_r_particles_style_f (cvar_t *var, vulkan_ctx_t *ctx) -{ - Vulkan_r_easter_eggs_f (var, ctx); -} - void Vulkan_DrawParticles (vulkan_ctx_t *ctx) { @@ -261,8 +64,6 @@ Vulkan_DrawParticles (vulkan_ctx_t *ctx) void Vulkan_Particles_Init (vulkan_ctx_t *ctx) { - vulkan_vid_render_funcs.particles = &vulkan_particles_QF; - qfv_device_t *device = ctx->device; qfvPushDebug (ctx, "particles init"); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 2548a2518..d7b474171 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -52,6 +52,7 @@ #include "compat.h" #include "sbar.h" +#include "client/particles.h" #include "client/temp_entities.h" #include "nq/include/chase.h" @@ -597,6 +598,7 @@ CL_Init (cbuf_t *cbuf) Sbar_Init (); CL_Input_Init (cbuf); + CL_Particles_Init (); CL_TEnts_Init (); CL_ClearState (); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 26c7f87d5..a5b462735 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -95,6 +95,7 @@ #include "compat.h" #include "sbar.h" +#include "client/particles.h" #include "client/temp_entities.h" #include "client/view.h" @@ -1206,6 +1207,7 @@ CL_Init (void) CL_Input_Init (); CL_Ents_Init (); + CL_Particles_Init (); CL_TEnts_Init (); CL_ClearState (); Pmove_Init (); From 372c89b4799f444a7fe9de1fddbfcf7d08225f00 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Dec 2021 13:38:50 +0900 Subject: [PATCH 1991/3664] [particles] Merge physics code The particle physics is called by the renderer. --- include/r_internal.h | 1 + libs/video/renderer/gl/gl_dyn_part.c | 33 +----------- libs/video/renderer/glsl/glsl_particles.c | 63 +---------------------- libs/video/renderer/r_part.c | 34 ++++++++++++ libs/video/renderer/sw/sw_rpart.c | 28 +--------- libs/video/renderer/sw32/sw32_rpart.c | 28 +--------- 6 files changed, 40 insertions(+), 147 deletions(-) diff --git a/include/r_internal.h b/include/r_internal.h index a1ea3d17c..09f4f3878 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -51,6 +51,7 @@ void R_InitEfrags (void); void R_ClearState (void); void R_InitSky (struct texture_s *mt); // called at level load void R_Textures_Init (void); +void R_RunParticles (float dT); void R_RenderView (void); // must set r_refdef first void R_ViewChanged (void); // must set r_refdef first // called whenever r_refdef or vid change diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 5b0db4da3..b915880e8 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -124,6 +124,8 @@ gl_R_DrawParticles (void) if (!r_particles->int_val) return; + R_RunParticles (vr_data.frametime); + qfglBindTexture (GL_TEXTURE_2D, gl_part_tex); // LordHavoc: particles should not affect zbuffer qfglDepthMask (GL_FALSE); @@ -135,27 +137,8 @@ gl_R_DrawParticles (void) vacount = 0; VA = particleVertexArray; - vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; - - unsigned j = 0; for (unsigned i = 0; i < numparticles; i++) { particle_t *p = &particles[i]; - partparm_t *parm = &partparams[i]; - - if (p->live <= 0 || p->ramp >= parm->ramp_max - || p->alpha <= 0 || p->scale <= 0) { - continue; - } - const int *ramp = partramps[j]; - if (i > j) { - particles[j] = *p; - partparams[j] = *parm; - partramps[j] = ramp; - } - p = &particles[j]; - parm = &partparams[j]; - j += 1; - // Don't render particles too close to us. // Note, we must still do physics and such on them. if (!(DotProduct (p->pos, vpn) < minparticledist)) { @@ -224,19 +207,7 @@ gl_R_DrawParticles (void) VA = particleVertexArray; } } - - float dT = vr_data.frametime; - p->pos += dT * p->vel; - p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); - p->ramp += dT * parm->ramp; - p->live -= dT; - p->alpha -= dT * parm->alpha_rate; - p->scale += dT * parm->scale_rate; - if (ramp) { - p->icolor = ramp[(int)p->ramp]; - } } - numparticles = j; if (vacount) { if (partUseVA) { diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index ebda3b447..128473e02 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -256,27 +256,8 @@ draw_qf_particles (void) vacount = 0; VA = particleVertexArray; - vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; - - unsigned j = 0; for (unsigned i = 0; i < numparticles; i++) { particle_t *p = &particles[i]; - partparm_t *parm = &partparams[i]; - - if (p->live <= 0 || p->ramp >= parm->ramp_max - || p->alpha <= 0 || p->scale <= 0) { - continue; - } - const int *ramp = partramps[j]; - if (i > j) { - particles[j] = *p; - partparams[j] = *parm; - partramps[j] = ramp; - } - p = &particles[j]; - parm = &partparams[j]; - j += 1; - // Don't render particles too close to us. // Note, we must still do physics and such on them. if (!(DotProduct (p->pos, vpn) < minparticledist)) { @@ -338,19 +319,7 @@ draw_qf_particles (void) VA += 4; vacount += 6; } - - float dT = vr_data.frametime; - p->pos += dT * p->vel; - p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); - p->ramp += dT * parm->ramp; - p->live -= dT; - p->alpha -= dT * parm->alpha_rate; - p->scale += dT * parm->scale_rate; - if (ramp) { - p->icolor = ramp[(int)p->ramp]; - } } - numparticles = j; qfeglVertexAttribPointer (quake_part.vertex.location, 3, GL_FLOAT, 0, sizeof (partvert_t), @@ -406,27 +375,8 @@ draw_id_particles (void) vacount = 0; VA = particleVertexArray; - vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; - - unsigned j = 0; for (unsigned i = 0; i < numparticles; i++) { particle_t *p = &particles[i]; - partparm_t *parm = &partparams[i]; - - if (p->live <= 0 || p->ramp >= parm->ramp_max - || p->alpha <= 0 || p->scale <= 0) { - continue; - } - const int *ramp = partramps[j]; - if (i > j) { - particles[j] = *p; - partparams[j] = *parm; - partramps[j] = ramp; - } - p = &particles[j]; - parm = &partparams[j]; - j += 1; - // Don't render particles too close to us. // Note, we must still do physics and such on them. if (!(DotProduct (p->pos, vpn) < minparticledist)) { @@ -435,19 +385,7 @@ draw_id_particles (void) VA++; vacount++; } - - float dT = vr_data.frametime; - p->pos += dT * p->vel; - p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); - p->ramp += dT * parm->ramp; - p->live -= dT; - p->alpha -= dT * parm->alpha_rate; - p->scale += dT * parm->scale_rate; - if (ramp) { - p->icolor = ramp[(int)p->ramp]; - } } - numparticles = j; qfeglVertexAttribPointer (quake_point.vertex.location, 3, GL_FLOAT, 0, sizeof (partvert_t), @@ -469,6 +407,7 @@ glsl_R_DrawParticles (void) { if (!r_particles->int_val || !numparticles) return; + R_RunParticles (vr_data.frametime); if (0/*FIXME r_particles_style->int_val*/) { draw_qf_particles (); } else { diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index b2c83fc02..7dabe54f6 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -85,3 +85,37 @@ R_ClearParticles (void) { numparticles = 0; } + +void +R_RunParticles (float dT) +{ + vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; + + unsigned j = 0; + for (unsigned i = 0; i < numparticles; i++) { + particle_t *p = &particles[i]; + partparm_t *parm = &partparams[i]; + + if (p->live <= 0 || p->ramp >= parm->ramp_max) { + continue; + } + const int *ramp = partramps[j]; + if (i > j) { + particles[j] = *p; + partparams[j] = *parm; + partramps[j] = ramp; + } + p = &particles[j]; + parm = &partparams[j]; + j += 1; + + p->pos += dT * p->vel; + p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); + p->ramp += dT * parm->ramp; + p->live -= dT; + if (ramp) { + p->icolor = ramp[(int)p->ramp]; + } + } + numparticles = j; +} diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index ceeda14a0..5445a83cd 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -56,38 +56,12 @@ R_DrawParticles (void) VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); - vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; + R_RunParticles (vr_data.frametime); - unsigned j = 0; for (unsigned i = 0; i < numparticles; i++) { particle_t *p = &particles[i]; - partparm_t *parm = &partparams[i]; - - if (p->live <= 0 || p->ramp >= parm->ramp_max) { - continue; - } - const int *ramp = partramps[j]; - if (i > j) { - particles[j] = *p; - partparams[j] = *parm; - partramps[j] = ramp; - } - p = &particles[j]; - parm = &partparams[j]; - j += 1; - D_DrawParticle (p); - - float dT = vr_data.frametime; - p->pos += dT * p->vel; - p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); - p->ramp += dT * parm->ramp; - p->live -= dT; - if (ramp) { - p->icolor = ramp[(int)p->ramp]; - } } - numparticles = j; } static void diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index 4bef2bc2b..a7234463f 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -59,38 +59,12 @@ sw32_R_DrawParticles (void) VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); - vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; + R_RunParticles (vr_data.frametime); - unsigned j = 0; for (unsigned i = 0; i < numparticles; i++) { particle_t *p = &particles[i]; - partparm_t *parm = &partparams[i]; - - if (p->live <= 0 || p->ramp >= parm->ramp_max) { - continue; - } - const int *ramp = partramps[j]; - if (i > j) { - particles[j] = *p; - partparams[j] = *parm; - partramps[j] = ramp; - } - p = &particles[j]; - parm = &partparams[j]; - j += 1; - sw32_D_DrawParticle (p); - - float dT = vr_data.frametime; - p->pos += dT * p->vel; - p->vel += dT * (p->vel * parm->drag + gravity * parm->drag[3]); - p->ramp += dT * parm->ramp; - p->live -= dT; - if (ramp) { - p->icolor = ramp[(int)p->ramp]; - } } - numparticles = j; } static void From d70d72e6e49f0ed12add0683f7526482f2bd4b21 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Dec 2021 14:47:25 +0900 Subject: [PATCH 1992/3664] [particles] Create a psystem object This takes care of the global variables to a point (there is still the global struct shared between the non-vulkan renderers), but it also takes care of glsl's points-only rendering. --- include/QF/Vulkan/qf_particles.h | 4 +- include/QF/plugin/vid_render.h | 1 + include/QF/render.h | 15 +-- include/r_internal.h | 8 +- libs/client/cl_particles.c | 92 +++---------------- libs/video/renderer/gl/gl_dyn_part.c | 18 ++-- libs/video/renderer/gl/gl_screen.c | 2 +- libs/video/renderer/glsl/glsl_particles.c | 27 ++++-- libs/video/renderer/r_part.c | 53 +++++------ libs/video/renderer/sw/sw_rpart.c | 10 +- libs/video/renderer/sw32/sw32_rpart.c | 10 +- libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_sw32.c | 1 + libs/video/renderer/vid_render_vulkan.c | 7 ++ libs/video/renderer/vulkan/vulkan_particles.c | 6 ++ 17 files changed, 124 insertions(+), 133 deletions(-) diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index 52a228299..4e2c7f0b6 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -55,12 +55,14 @@ typedef struct particlectx_s { VkPipelineLayout physics_layout; VkPipelineLayout update_layout; VkPipelineLayout draw_layout; + + psystem_t psystem; } particlectx_t; struct cvar_s; struct vulkan_ctx_s;; -struct r_particle_ctx_s *Vulkan_ParticleContext (struct vulkan_ctx_s *ctx); +struct psystem_s *Vulkan_ParticleSystem (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_DrawParticles (struct vulkan_ctx_s *ctx); diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index e3fba0342..46e48a040 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -109,6 +109,7 @@ typedef struct vid_render_funcs_s { float time); void (*Fog_ParseWorldspawn) (struct plitem_s *worldspawn); + struct psystem_s *(*ParticleSystem) (void); void (*R_Init) (void); void (*R_RenderFrame) (SCR_Func *scr_funcs); void (*R_ClearState) (void); diff --git a/include/QF/render.h b/include/QF/render.h index 617952ed3..3a3f7ae7e 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -90,12 +90,15 @@ typedef struct partparm_s { float alpha_rate; } partparm_t; -// FIXME these really shouldn't be global, but they speed up particle creation -extern unsigned int r_maxparticles; -extern unsigned int numparticles; -extern struct particle_s *particles; -extern struct partparm_s *partparams; -extern const int **partramps; +typedef struct psystem_s { + uint32_t maxparticles; + uint32_t numparticles; + particle_t *particles; + partparm_t *partparams; + const int **partramps; + + int points_only; +} psystem_t; extern struct vid_render_funcs_s *r_funcs; extern struct vid_render_data_s *r_data; diff --git a/include/r_internal.h b/include/r_internal.h index 09f4f3878..bc2b2b464 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -51,11 +51,17 @@ void R_InitEfrags (void); void R_ClearState (void); void R_InitSky (struct texture_s *mt); // called at level load void R_Textures_Init (void); -void R_RunParticles (float dT); void R_RenderView (void); // must set r_refdef first void R_ViewChanged (void); // must set r_refdef first // called whenever r_refdef or vid change +extern struct psystem_s r_psystem; +struct psystem_s *gl_ParticleSystem (void); +struct psystem_s *glsl_ParticleSystem (void); +struct psystem_s *sw_ParticleSystem (void); +struct psystem_s *sw32_ParticleSystem (void); +void R_RunParticles (float dT); + void R_AddEfrags (mod_brush_t *, entity_t *ent); void R_RemoveEfrags (entity_t *ent); diff --git a/libs/client/cl_particles.c b/libs/client/cl_particles.c index f13a765f0..5f92df3bc 100644 --- a/libs/client/cl_particles.c +++ b/libs/client/cl_particles.c @@ -46,6 +46,7 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/plugin/vid_render.h" //FIXME #include "QF/scene/entity.h" #include "compat.h" @@ -57,6 +58,7 @@ float cl_realtime; cl_particle_funcs_t *clp_funcs; static mtstate_t mt; // private PRNG state +static psystem_t *cl_psystem; static cvar_t *easter_eggs; static cvar_t *particles_style; @@ -116,12 +118,15 @@ inline static int particle_new (ptype_t type, int texnum, vec4f_t pos, float scale, vec4f_t vel, float live, int color, float alpha, float ramp) { - if (numparticles >= r_maxparticles) + if (cl_psystem->numparticles >= cl_psystem->maxparticles) { return 0; - particle_t *p = &particles[numparticles]; - partparm_t *parm = &partparams[numparticles]; - const int **rampptr = &partramps[numparticles]; - numparticles += 1; + } + + __auto_type ps = cl_psystem; + particle_t *p = &ps->particles[ps->numparticles]; + partparm_t *parm = &ps->partparams[ps->numparticles]; + const int **rampptr = &ps->partramps[ps->numparticles]; + ps->numparticles += 1; p->pos = pos; p->vel = vel; @@ -216,14 +221,6 @@ add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, { particle_new (type, part_tex_dot, pos, 1, vel, live, color, 1, ramp); } -/* -void -CL_ClearParticles (void) -{ - numparticles = 0; -} -*/ - static void pointfile_f (void) @@ -260,12 +257,10 @@ pointfile_f (void) break; c++; - if (numparticles >= r_maxparticles) { + if (!particle_new (pt_static, part_tex_dot, org, 1.5, zero, + 99999, (-c) & 15, 1.0, 0.0)) { Sys_MaskPrintf (SYS_dev, "Not enough free particles\n"); break; - } else { - particle_new (pt_static, part_tex_dot, org, 1.5, zero, - 99999, (-c) & 15, 1.0, 0.0); } } Qclose (f); @@ -276,8 +271,6 @@ static void CL_ParticleExplosion_QF (vec4f_t org) { // CL_NewExplosion (org); - if (numparticles >= r_maxparticles) - return; particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, 5.0, (mtwist_rand (&mt) & 7) + 8, 0.5 + qfrandom (0.25), 0.0); @@ -288,11 +281,6 @@ CL_ParticleExplosion2_QF (vec4f_t org, int colorStart, int colorLength) { unsigned int i, j = 512; - if (numparticles >= r_maxparticles) - return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - for (i = 0; i < j; i++) { particle_new_random (pt_blob, part_tex_dot, org, 16, 2, 256, 0.3, @@ -306,11 +294,6 @@ CL_BlobExplosion_QF (vec4f_t org) unsigned int i; unsigned int j = 1024; - if (numparticles >= r_maxparticles) - return; - else if (numparticles + j >= r_maxparticles) - j = r_maxparticles - numparticles; - for (i = 0; i < j >> 1; i++) { particle_new_random (pt_blob, part_tex_dot, org, 12, 2, 256, 1.0 + (mtwist_rand (&mt) & 7) * 0.05, @@ -486,9 +469,6 @@ CL_TeleportSplash_QF (vec4f_t org) static void CL_RocketTrail_QF (vec4f_t start, vec4f_t end) { - if (numparticles >= r_maxparticles) - return; - vec4f_t vec = end - start; float maxlen = magnitudef (vec)[0]; vec = normalf (vec); @@ -511,8 +491,6 @@ CL_RocketTrail_QF (vec4f_t start, vec4f_t end) 2.0 - percent * 2.0, 12 + (mtwist_rand (&mt) & 3), 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; pos += step; pscale = pscalenext; @@ -522,9 +500,6 @@ CL_RocketTrail_QF (vec4f_t start, vec4f_t end) static void CL_GrenadeTrail_QF (vec4f_t start, vec4f_t end) { - if (numparticles >= r_maxparticles) - return; - vec4f_t vec = end - start; float maxlen = magnitudef (vec)[0]; vec = normalf (vec); @@ -547,8 +522,6 @@ CL_GrenadeTrail_QF (vec4f_t start, vec4f_t end) 2.0 - percent * 2.0, 1 + (mtwist_rand (&mt) & 3), 0.625 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; pos += step; pscale = pscalenext; @@ -558,9 +531,6 @@ CL_GrenadeTrail_QF (vec4f_t start, vec4f_t end) static void CL_BloodTrail_QF (vec4f_t start, vec4f_t end) { - if (numparticles >= r_maxparticles) - return; - vec4f_t vec = end - start; float maxlen = magnitudef (vec)[0]; vec = normalf (vec); @@ -582,8 +552,6 @@ CL_BloodTrail_QF (vec4f_t start, vec4f_t end) particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, 2.0 - percent * 2.0, 68 + (mtwist_rand (&mt) & 3), 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; pos += step; pscale = pscalenext; @@ -593,9 +561,6 @@ CL_BloodTrail_QF (vec4f_t start, vec4f_t end) static void CL_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) { - if (numparticles >= r_maxparticles) - return; - vec4f_t vec = end - start; float maxlen = magnitudef (vec)[0]; vec = normalf (vec); @@ -616,8 +581,6 @@ CL_SlightBloodTrail_QF (vec4f_t start, vec4f_t end) particle_new (pt_grav, part_tex_smoke, pos + roffs (4), pscale, vel, 1.5 - percent * 1.5, 68 + (mtwist_rand (&mt) & 3), 0.75, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; pos += step; pscale = pscalenext; @@ -629,9 +592,6 @@ CL_WizTrail_QF (vec4f_t start, vec4f_t end) { float dist = 3.0; - if (numparticles >= r_maxparticles) - return; - vec4f_t vec = end - start; float maxlen = magnitudef (vec)[0]; vec = normalf (vec); @@ -650,8 +610,6 @@ CL_WizTrail_QF (vec4f_t start, vec4f_t end) 30 * tracer_vel (tracercount++, vec), 0.5 - percent * 0.5, 52 + (mtwist_rand (&mt) & 4), 1.0 - percent * 0.125, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; pos += step; } @@ -662,9 +620,6 @@ CL_FlameTrail_QF (vec4f_t start, vec4f_t end) { float dist = 3.0; - if (numparticles >= r_maxparticles) - return; - vec4f_t vec = end - start; float maxlen = magnitudef (vec)[0]; vec = normalf (vec); @@ -693,9 +648,6 @@ CL_VoorTrail_QF (vec4f_t start, vec4f_t end) { float dist = 3.0; - if (numparticles >= r_maxparticles) - return; - vec4f_t vec = end - start; float maxlen = magnitudef (vec)[0]; vec = normalf (vec); @@ -723,9 +675,6 @@ CL_GlowTrail_QF (vec4f_t start, vec4f_t end, int glow_color) { float dist = 3.0; - if (numparticles >= r_maxparticles) - return; - vec4f_t vec = end - start; float maxlen = magnitudef (vec)[0]; vec = normalf (vec); @@ -741,8 +690,6 @@ CL_GlowTrail_QF (vec4f_t start, vec4f_t end, int glow_color) particle_new (pt_smoke, part_tex_dot, pos + roffs (5), 1.0, zero, 2.0 - percent * 0.2, glow_color, 1.0, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; pos += step; } @@ -754,8 +701,6 @@ CL_ParticleExplosion_EE (vec4f_t org) /* CL_NewExplosion (org); */ - if (numparticles >= r_maxparticles) - return; particle_new_random (pt_smokecloud, part_tex_smoke, org, 4, 30, 8, 5.0, mtwist_rand (&mt) & 255, 0.5 + qfrandom (0.25), 0.0); @@ -788,9 +733,6 @@ CL_TeleportSplash_EE (vec4f_t org) static void CL_RocketTrail_EE (vec4f_t start, vec4f_t end) { - if (numparticles >= r_maxparticles) - return; - vec4f_t vec = end - start; float maxlen = magnitudef (vec)[0]; vec = normalf (vec); @@ -811,8 +753,6 @@ CL_RocketTrail_EE (vec4f_t start, vec4f_t end) 2.0 - percent * 2.0, mtwist_rand (&mt) & 255, 0.5 + qfrandom (0.125) - percent * 0.40, 0.0); - if (numparticles >= r_maxparticles) - break; len += dist; pos += len * vec; pscale = pscalenext; @@ -1169,8 +1109,6 @@ CL_Particle_New (ptype_t type, int texnum, vec4f_t org, float scale, vec4f_t vel, float live, int color, float alpha, float ramp) { - if (numparticles >= r_maxparticles) - return; particle_new (type, texnum, org, scale, vel, live, color, alpha, ramp); } @@ -1179,8 +1117,6 @@ CL_Particle_NewRandom (ptype_t type, int texnum, vec4f_t org, int org_fuzz, float scale, int vel_fuzz, float live, int color, float alpha, float ramp) { - if (numparticles >= r_maxparticles) - return; particle_new_random (type, texnum, org, org_fuzz, scale, vel_fuzz, live, color, alpha, ramp); } @@ -1321,6 +1257,7 @@ static void particles_style_f (cvar_t *var) { easter_eggs_f (easter_eggs); + cl_psystem->points_only = !var->int_val; } static void @@ -1330,12 +1267,11 @@ CL_ParticleFunctionInit (void) easter_eggs_f (easter_eggs); } -/* - */ void CL_Particles_Init (void) { mtwist_seed (&mt, 0xdeadbeef); + cl_psystem = r_funcs->ParticleSystem (); Cmd_AddCommand ("pointfile", pointfile_f, "Load a pointfile to determine map leaks."); easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, easter_eggs_f, diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index b915880e8..6ed7d01c6 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -71,18 +71,18 @@ gl_R_InitParticles (void) { int i; - if (r_maxparticles && r_init) { + if (r_psystem.maxparticles && r_init) { if (vaelements) { partUseVA = 0; - pVAsize = r_maxparticles * 4; + pVAsize = r_psystem.maxparticles * 4; Sys_MaskPrintf (SYS_dev, "Particles: Vertex Array use disabled.\n"); } else { if (vaelements > 3) pVAsize = min ((unsigned int) (vaelements - (vaelements % 4)), - r_maxparticles * 4); + r_psystem.maxparticles * 4); else if (vaelements >= 0) - pVAsize = r_maxparticles * 4; + pVAsize = r_psystem.maxparticles * 4; Sys_MaskPrintf (SYS_dev, "Particles: %i maximum vertex elements.\n", pVAsize); @@ -137,8 +137,8 @@ gl_R_DrawParticles (void) vacount = 0; VA = particleVertexArray; - for (unsigned i = 0; i < numparticles; i++) { - particle_t *p = &particles[i]; + for (unsigned i = 0; i < r_psystem.numparticles; i++) { + particle_t *p = &r_psystem.particles[i]; // Don't render particles too close to us. // Note, we must still do physics and such on them. if (!(DotProduct (p->pos, vpn) < minparticledist)) { @@ -263,3 +263,9 @@ gl_R_Particles_Init_Cvars (void) "Distance of the particle near clipping " "plane from the player."); } + +psystem_t * __attribute__((const))//FIXME +gl_ParticleSystem (void) +{ + return &r_psystem; +} diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index ada0b6c9a..dff7b88b9 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -250,7 +250,7 @@ gl_R_RenderFrame (SCR_Func *scr_funcs) time2 = Sys_DoubleTime (); Sys_MaskPrintf (SYS_dev, "%3i ms %4i wpoly %4i epoly %4i parts\n", (int) ((time2 - time1) * 1000), gl_c_brush_polys, - gl_c_alias_polys, numparticles); + gl_c_alias_polys, r_psystem.numparticles); } GL_FlushText (); diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 128473e02..c6b4b0153 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -1,5 +1,5 @@ /* - gl_dyn_part.c + glsl_particles.c OpenGL particle system. @@ -201,12 +201,13 @@ glsl_R_InitParticles (void) if (particleVertexArray) free (particleVertexArray); - particleVertexArray = calloc (r_maxparticles * 4, sizeof (partvert_t)); + particleVertexArray = calloc (r_psystem.maxparticles * 4, + sizeof (partvert_t)); if (pVAindices) free (pVAindices); - pVAindices = calloc (r_maxparticles * 6, sizeof (GLushort)); - for (i = 0; i < r_maxparticles; i++) { + pVAindices = calloc (r_psystem.maxparticles * 6, sizeof (GLushort)); + for (i = 0; i < r_psystem.maxparticles; i++) { pVAindices[i * 6 + 0] = i * 4 + 0; pVAindices[i * 6 + 1] = i * 4 + 1; pVAindices[i * 6 + 2] = i * 4 + 2; @@ -256,8 +257,8 @@ draw_qf_particles (void) vacount = 0; VA = particleVertexArray; - for (unsigned i = 0; i < numparticles; i++) { - particle_t *p = &particles[i]; + for (unsigned i = 0; i < r_psystem.numparticles; i++) { + particle_t *p = &r_psystem.particles[i]; // Don't render particles too close to us. // Note, we must still do physics and such on them. if (!(DotProduct (p->pos, vpn) < minparticledist)) { @@ -375,8 +376,8 @@ draw_id_particles (void) vacount = 0; VA = particleVertexArray; - for (unsigned i = 0; i < numparticles; i++) { - particle_t *p = &particles[i]; + for (unsigned i = 0; i < r_psystem.numparticles; i++) { + particle_t *p = &r_psystem.particles[i]; // Don't render particles too close to us. // Note, we must still do physics and such on them. if (!(DotProduct (p->pos, vpn) < minparticledist)) { @@ -405,10 +406,10 @@ draw_id_particles (void) void glsl_R_DrawParticles (void) { - if (!r_particles->int_val || !numparticles) + if (!r_particles->int_val || !r_psystem.numparticles) return; R_RunParticles (vr_data.frametime); - if (0/*FIXME r_particles_style->int_val*/) { + if (!r_psystem.points_only) { draw_qf_particles (); } else { draw_id_particles (); @@ -448,3 +449,9 @@ glsl_R_Particles_Init_Cvars (void) "Distance of the particle near clipping " "plane from the player."); } + +psystem_t * __attribute__((const))//FIXME +glsl_ParticleSystem (void) +{ + return &r_psystem; +} diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index 7dabe54f6..1eafeca54 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -36,10 +36,8 @@ #include "compat.h" #include "r_internal.h" -unsigned int r_maxparticles, numparticles; -particle_t *particles; -partparm_t *partparams; -const int **partramps; +psystem_t r_psystem; //FIXME singleton + vec3_t r_pright, r_pup, r_ppn; /* @@ -52,30 +50,31 @@ vec3_t r_pright, r_pup, r_ppn; void R_MaxParticlesCheck (cvar_t *r_particles, cvar_t *r_particles_max) { + psystem_t *ps = &r_psystem;//FIXME unsigned maxparticles = 0; if (r_particles && r_particles->int_val) { maxparticles = r_particles_max ? r_particles_max->int_val : 0; } - if (r_maxparticles == maxparticles) { + if (ps->maxparticles == maxparticles) { return; } size_t size = sizeof (particle_t) + sizeof (partparm_t) + sizeof (int *); - if (particles) { - Sys_Free (particles, r_maxparticles * size); - particles = 0; - partparams = 0; - partramps = 0; + if (ps->particles) { + Sys_Free (ps->particles, ps->maxparticles * size); + ps->particles = 0; + ps->partparams = 0; + ps->partramps = 0; } - r_maxparticles = maxparticles; + ps->maxparticles = maxparticles; - if (r_maxparticles) { - particles = Sys_Alloc (r_maxparticles * size); - partparams = (partparm_t *) &particles[r_maxparticles]; - partramps = (const int **) &partparams[r_maxparticles]; + if (ps->maxparticles) { + ps->particles = Sys_Alloc (ps->maxparticles * size); + ps->partparams = (partparm_t *) &ps->particles[ps->maxparticles]; + ps->partramps = (const int **) &ps->partparams[ps->maxparticles]; } R_ClearParticles (); } @@ -83,30 +82,32 @@ R_MaxParticlesCheck (cvar_t *r_particles, cvar_t *r_particles_max) void R_ClearParticles (void) { - numparticles = 0; + psystem_t *ps = &r_psystem;//FIXME + ps->numparticles = 0; } void R_RunParticles (float dT) { + psystem_t *ps = &r_psystem;//FIXME vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; unsigned j = 0; - for (unsigned i = 0; i < numparticles; i++) { - particle_t *p = &particles[i]; - partparm_t *parm = &partparams[i]; + for (unsigned i = 0; i < ps->numparticles; i++) { + particle_t *p = &ps->particles[i]; + partparm_t *parm = &ps->partparams[i]; if (p->live <= 0 || p->ramp >= parm->ramp_max) { continue; } - const int *ramp = partramps[j]; + const int *ramp = ps->partramps[j]; if (i > j) { - particles[j] = *p; - partparams[j] = *parm; - partramps[j] = ramp; + ps->particles[j] = *p; + ps->partparams[j] = *parm; + ps->partramps[j] = ramp; } - p = &particles[j]; - parm = &partparams[j]; + p = &ps->particles[j]; + parm = &ps->partparams[j]; j += 1; p->pos += dT * p->vel; @@ -117,5 +118,5 @@ R_RunParticles (float dT) p->icolor = ramp[(int)p->ramp]; } } - numparticles = j; + ps->numparticles = j; } diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index 5445a83cd..a76d2d105 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -58,8 +58,8 @@ R_DrawParticles (void) R_RunParticles (vr_data.frametime); - for (unsigned i = 0; i < numparticles; i++) { - particle_t *p = &particles[i]; + for (unsigned i = 0; i < r_psystem.numparticles; i++) { + particle_t *p = &r_psystem.particles[i]; D_DrawParticle (p); } } @@ -97,3 +97,9 @@ R_Particles_Init_Cvars (void) "Distance of the particle near clipping " "plane from the player."); } + +psystem_t * __attribute__((const))//FIXME +sw_ParticleSystem (void) +{ + return &r_psystem; +} diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c index a7234463f..d43397a89 100644 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -61,8 +61,8 @@ sw32_R_DrawParticles (void) R_RunParticles (vr_data.frametime); - for (unsigned i = 0; i < numparticles; i++) { - particle_t *p = &particles[i]; + for (unsigned i = 0; i < r_psystem.numparticles; i++) { + particle_t *p = &r_psystem.particles[i]; sw32_D_DrawParticle (p); } } @@ -100,3 +100,9 @@ sw32_R_Particles_Init_Cvars (void) "Distance of the particle near clipping " "plane from the player."); } + +psystem_t * __attribute__((const))//FIXME +sw32_ParticleSystem (void) +{ + return &r_psystem; +} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index e3b1d6597..d95f53a3c 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -142,6 +142,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Fog_Update, gl_Fog_ParseWorldspawn, + gl_ParticleSystem, gl_R_Init, gl_R_RenderFrame, gl_R_ClearState, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 836f2f6ed..8b98654a1 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -141,6 +141,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Fog_Update, glsl_Fog_ParseWorldspawn, + glsl_ParticleSystem, glsl_R_Init, glsl_R_RenderFrame, glsl_R_ClearState, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index f888a979d..45f961f6b 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -138,6 +138,7 @@ vid_render_funcs_t sw_vid_render_funcs = { 0, 0, + sw_ParticleSystem, sw_R_Init, R_RenderFrame, R_ClearState, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index b9a0acac7..d24da6128 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -143,6 +143,7 @@ vid_render_funcs_t sw32_vid_render_funcs = { 0, 0, + sw32_ParticleSystem, sw32_R_Init, sw32_R_RenderFrame, sw32_R_ClearState, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index cc7904d39..2d7c5bf97 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -91,6 +91,12 @@ vulkan_Fog_ParseWorldspawn (struct plitem_s *worldspawn) { } +static struct psystem_s * +vulkan_ParticleSystem (void) +{ + return Vulkan_ParticleSystem (vulkan_ctx); +} + static void vulkan_R_Init (void) { @@ -663,6 +669,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Fog_Update, vulkan_Fog_ParseWorldspawn, + vulkan_ParticleSystem, vulkan_R_Init, vulkan_R_RenderFrame, vulkan_R_ClearState, diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 6eb8e74ba..14a98df44 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -125,3 +125,9 @@ Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx) free (pctx->frames.a); free (pctx); } + +psystem_t *__attribute__((pure))//FIXME? +Vulkan_ParticleSystem (vulkan_ctx_t *ctx) +{ + return &ctx->particle_context->psystem; //FIXME support more +} From e0863ff06725bcbac21baa35f132d7530eb5fb3e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Dec 2021 09:19:36 +0900 Subject: [PATCH 1993/3664] [net_chan] Clean out unnecessary include net_chan was still including client.h from qw when it no longer needed it (I guess I forgot to clean that out when I resolved any last dependencies). --- libs/net/net_chan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/net/net_chan.c b/libs/net/net_chan.c index 53557a95c..1289866d7 100644 --- a/libs/net/net_chan.c +++ b/libs/net/net_chan.c @@ -49,8 +49,6 @@ #include "compat.h" #include "netchan.h" -#include "../qw/include/client.h" - #define PACKET_HEADER 8 int net_nochoke; From 577959ec6b9110323e50f6782993f27cdf318873 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Dec 2021 14:48:02 +0900 Subject: [PATCH 1994/3664] [build] Use AS_HELP_STRING on all the help strings Cleans up the inconsistently wrapped lines. --- config.d/asm.m4 | 10 ++++++--- config.d/build_control.m4 | 9 ++++---- config.d/cdrom.m4 | 6 +++--- config.d/compiling.m4 | 23 ++++++++++++-------- config.d/compression.m4 | 16 +++++--------- config.d/cross_compile.m4 | 5 +++-- config.d/curses.m4 | 3 +-- config.d/fbdev.m4 | 5 +++-- config.d/networking.m4 | 4 ++-- config.d/paths.m4 | 44 +++++++++++++++++++-------------------- config.d/qfcc.m4 | 5 ++--- config.d/sdl.m4 | 10 +++------ config.d/sound.m4 | 14 +++++-------- config.d/svga.m4 | 4 ++-- config.d/versions.m4 | 5 +++-- config.d/vulkan.m4 | 2 +- config.d/x11.m4 | 15 ++++++------- configure.ac | 7 ++++--- m4/libFLAC.m4 | 8 +++---- m4/libOggFLAC.m4 | 8 +++---- m4/ogg.m4 | 8 +++---- m4/quakeforge.m4 | 6 ++---- m4/sdl.m4 | 6 +++--- m4/vorbis.m4 | 8 +++---- m4/xmms.m4 | 4 ++-- 25 files changed, 116 insertions(+), 119 deletions(-) diff --git a/config.d/asm.m4 b/config.d/asm.m4 index 33f249096..2a9e1d134 100644 --- a/config.d/asm.m4 +++ b/config.d/asm.m4 @@ -5,9 +5,11 @@ case "${host}" in AC_MSG_RESULT(yes) AC_MSG_CHECKING(to see if we should disable asm optimizations) AC_ARG_ENABLE(asmopt, - [ --disable-asmopt disable assembler optimization], + AS_HELP_STRING([--disable-asmopt], + [disable assembler optimization]), AC_MSG_RESULT(yes), - AC_DEFINE(USE_INTEL_ASM, 1, [Define this if you want to use Intel assembly optimizations]) + AC_DEFINE(USE_INTEL_ASM, 1, + [Define this if you want to use Intel assembly optimizations]) ASM_ARCH=yes AC_MSG_RESULT(no) ) @@ -19,6 +21,8 @@ AM_CONDITIONAL(ASM_ARCH, test "x$ASM_ARCH" = "xyes") AC_MSG_CHECKING(for underscore prefix in names) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[asm(".long _bar"); int bar;]], [[]])], - [AC_DEFINE(HAVE_SYM_PREFIX_UNDERSCORE, 1, Define this if C symbols are prefixed with an underscore) AC_MSG_RESULT(yes)], + [AC_DEFINE(HAVE_SYM_PREFIX_UNDERSCORE, 1, + [Define this if C symbols are prefixed with an underscore]) + AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) ]) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 275cac8a9..ce6dfdda2 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -4,17 +4,17 @@ dnl ================================================================== QF_WITH_TARGETS( clients, - [ --with-clients= compile clients in :], + [compile clients], [fbdev,sdl,svga,win,x11],dummy ) QF_WITH_TARGETS( servers, - [ --with-servers= compile dedicated server:], + [compile dedicated servers], [master,nq,qw,qtv],dummy ) QF_WITH_TARGETS( tools, - [ --with-tools= compile qf tools:], + [compile qf tools], [bsp2img,carne,gsc,pak,qfbsp,qfcc,qflight,qflmp,qfmodelgen,qfspritegen,qfvis,qwaq,wad,wav],dummy ) @@ -390,7 +390,8 @@ QF_SUBST(PREFER_NON_PIC) QF_SUBST(STATIC) AC_ARG_WITH(static-plugins, -[ --with-static-plugins build plugins into executable rather than separate], + AS_HELP_STRING([--with-static-plugins], + [build plugins into executable rather than separate]), static_plugins="$withval", static_plugins=auto) if test "x$static_plugins" = xauto; then if test "x$enable_shared" = xno -o "x$SYSTYPE" = xWIN32; then diff --git a/config.d/cdrom.m4 b/config.d/cdrom.m4 index 38e407669..5b50743d5 100644 --- a/config.d/cdrom.m4 +++ b/config.d/cdrom.m4 @@ -4,7 +4,7 @@ dnl ================================================================== dnl XMMS Checks AC_ARG_ENABLE(xmms, -[ --enable-xmms enable checking for XMMS], + AS_HELP_STRING([--enable-xmms], [enable checking for XMMS]) ) if test "x$mingw" != xyes -a "x$enable_xmms" == xyes; then AM_PATH_XMMS(0.9.5.1, HAVE_XMMS=yes, HAVE_XMMS=no) @@ -78,8 +78,8 @@ AC_SUBST(CD_LIBS) AC_ARG_WITH([cd-default], AS_HELP_STRING([--with-cd-default=...], - [Plugin to use for the default cd driver.] - [Defaults to File.] + [plugin to use for the default cd driver.] + [Defaults to file.] [[file linux xmms sdl sgi win32]]), [cd_default="$withval"] ) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 5fc0ea03e..1cd08dfa4 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -53,7 +53,7 @@ if test "x$GCC" = xyes; then fi AC_ARG_ENABLE(debug, - [ --disable-debug compile without debugging], + AS_HELP_STRING([--disable-debug], [compile without debugging]), debug=$enable_debug ) @@ -77,13 +77,15 @@ else fi AC_ARG_ENABLE(optimize, - [ --disable-optimize compile without optimizations (for development)], + AS_HELP_STRING([--disable-optimize], + [compile without optimizations (for development)]), optimize=$enable_optimize, optimize=yes ) AC_ARG_ENABLE(simd, - [ --enable-simd[=arg] Enable SIMD support (default auto)], + AS_HELP_STRING([--enable-simd@<:@=arg@:.@], + [enable SIMD support (default auto)]), [], [enable_simd=yes] ) @@ -123,7 +125,8 @@ if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then CFLAGS="$saved_cflags" light="-O2" AC_ARG_ENABLE(strict-aliasing, - [ --enable-strict-aliasing enable the -fstrict-aliasing option of gcc]) + AS_HELP_STRING([--enable-strict-aliasing], + [enable the -fstrict-aliasing option of gcc])) if test "x$enable_strict_aliasing" = "xyes"; then heavy="$heavy -fstrict-aliasing" light="$light -fstrict-aliasing" @@ -144,7 +147,8 @@ if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then fi AC_MSG_CHECKING(for special compiler settings) AC_ARG_WITH(arch, - [ --with-arch=ARCH control compiler architecture directly], + AS_HELP_STRING([--with-arch=ARCH], + [control compiler architecture directly]), arch="$withval", arch=auto ) case "$arch" in @@ -195,7 +199,8 @@ fi dnl CFLAGS for release and devel versions AC_ARG_ENABLE(profile, - [ --enable-profile compile with profiling (for development)], + AS_HELP_STRING([--enable-profile], + [compile with profiling (for development)]), profile=$enable_profile ) if test "x$profile" = xyes; then @@ -213,7 +218,7 @@ if test "x$GCC" = xyes; then dnl Check for -pipe vs -save-temps. AC_MSG_CHECKING(for -pipe vs -save-temps) AC_ARG_ENABLE(save-temps, - [ --enable-save-temps save temporary files], + AS_HELP_STRING([--enable-save-temps], [save temporary files]), AC_MSG_RESULT(-save-temps) CFLAGS="$CFLAGS -save-temps" BUILD_TYPE="$BUILD_TYPE Save-temps" @@ -238,7 +243,7 @@ QF_CC_OPTION(-Wsuggest-attribute=format) QF_CC_OPTION(-Wformat-nonliteral) AC_ARG_ENABLE(coverage, -[ --enable-coverage Enable generation of data for gcov]) + AS_HELP_STRING([--enable-coverage], [enable generation of data for gcov])) if test "x$enable_coverage" = xyes; then QF_CC_OPTION(-fprofile-arcs -ftest-coverage) fi @@ -270,7 +275,7 @@ if test "x$GCC" != xyes; then fi AC_ARG_ENABLE(Werror, -[ --disable-Werror Do not treat warnings as errors]) + AS_HELP_STRING([--disable-Werror], [do not treat warnings as errors])) dnl We want warnings, lots of warnings... dnl The help text should be INVERTED before release! dnl when in git, this test defaults to ENABLED. diff --git a/config.d/compression.m4 b/config.d/compression.m4 index bdc0309f2..2c3f8d4fe 100644 --- a/config.d/compression.m4 +++ b/config.d/compression.m4 @@ -1,6 +1,4 @@ -AC_ARG_ENABLE(flac, -[ --disable-flac disable flac support], -) +AC_ARG_ENABLE(flac, AS_HELP_STRING([--disable-flac], [disable flac support])) HAVE_FLAC=no if test "x$enable_flac" != "xno"; then if test "x$PKG_CONFIG" != "x"; then @@ -15,8 +13,7 @@ fi AM_CONDITIONAL(HAVE_FLAC, test "x$HAVE_FLAC" = "xyes") AC_ARG_ENABLE(wildmidi, -[ --disable-wildmidi disable libWildMidi support], -) + AS_HELP_STRING([--disable-wildmidi], disable libWildMidi support])) HAVE_WILDMIDI=no WM_LIBS= if test "x$enable_wildmidi" != "xno"; then @@ -33,8 +30,7 @@ AC_SUBST(WM_LIBS) AM_CONDITIONAL(HAVE_MIDI, test "x$HAVE_WILDMIDI" = "xyes") AC_ARG_ENABLE(vorbis, -[ --disable-vorbis disable ogg vorbis support], -) + AS_HELP_STRING([--disable-vorbis], [disable ogg vorbis support])) HAVE_VORBIS=no if test "x$enable_vorbis" != "xno"; then if test "x$PKG_CONFIG" != "x"; then @@ -59,7 +55,7 @@ fi AM_CONDITIONAL(HAVE_VORBIS, test "x$HAVE_VORBIS" = "xyes") -AC_ARG_ENABLE(zlib, [ --disable-zlib disable zlib support]) +AC_ARG_ENABLE(zlib, AS_HELP_STRING([--disable-zlib], [disable zlib support])) HAVE_ZLIB=no Z_LIBS="" if test "x$enable_zlib" != "xno"; then @@ -83,9 +79,7 @@ if test "x$HAVE_ZLIB" = "xyes"; then AC_DEFINE(HAVE_ZLIB, 1, [Define if you have zlib]) fi -AC_ARG_ENABLE(png, -[ --disable-png disable png support], -) +AC_ARG_ENABLE(png, AS_HELP_STRING([--disable-png], [disable png support])) HAVE_PNG=no PNG_LIBS="" if test "x$enable_png" != "xno"; then diff --git a/config.d/cross_compile.m4 b/config.d/cross_compile.m4 index 66ca372a3..6992a6f90 100644 --- a/config.d/cross_compile.m4 +++ b/config.d/cross_compile.m4 @@ -1,8 +1,9 @@ if test "x$cross_compiling" = xyes; then AC_MSG_CHECKING(whether byte ordering is bigendian) AC_ARG_WITH(endian, -[ --with-endian=TYPE set endian of target system for - cross-compiling. TYPE = little or big.], + AS_HELP_STRING([--with-endian=TYPE], + [set endian of target system for cross-compiling.] + [TYPE = little or big.]), endian="$withval", ) case "x$endian" in diff --git a/config.d/curses.m4 b/config.d/curses.m4 index 2e24c0d84..ea4b5e3b0 100644 --- a/config.d/curses.m4 +++ b/config.d/curses.m4 @@ -1,6 +1,5 @@ AC_ARG_ENABLE(curses, -[ --disable-curses disable curses support] -) + AS_HELP_STRING([--disable-curses], [disable curses support])) if test "x$enable_curses" != "xno"; then if test "x$PKG_CONFIG" != "x"; then PKG_CHECK_MODULES([NCURSES], [ncurses], HAVE_NCURSES=yes, HAVE_NCURSES=no) diff --git a/config.d/fbdev.m4 b/config.d/fbdev.m4 index 8af090ab1..335658eb4 100644 --- a/config.d/fbdev.m4 +++ b/config.d/fbdev.m4 @@ -1,7 +1,8 @@ dnl Checks for Linux FBDev support AC_ARG_WITH(fbdev, -[ --with-fbdev use Linux framebuffer device], -HAVE_FBDEV=$withval, HAVE_FBDEV=no) + AS_HELP_STRING([--with-fbdev], [use Linux framebuffer device]), + HAVE_FBDEV=$withval, + HAVE_FBDEV=no) if test "x$HAVE_FBDEV" != xno; then dnl We should still be able to compile it even if dnl there is no fbdev support in the running kernel diff --git a/config.d/networking.m4 b/config.d/networking.m4 index 74c214c83..443f663f9 100644 --- a/config.d/networking.m4 +++ b/config.d/networking.m4 @@ -16,8 +16,8 @@ else fi AC_ARG_WITH(ipv6, - AS_HELP_STRING([--with-ipv6=DIR], - [Enable IPv6 support.] + AS_HELP_STRING([--with-ipv6@<:@=DIR@:>@], + [enable IPv6 support.] [Optional argument specifies location of inet6 libraries.]), [ if test "x$withval" = xno ; then diff --git a/config.d/paths.m4 b/config.d/paths.m4 index c5ce432ce..b71607a7a 100644 --- a/config.d/paths.m4 +++ b/config.d/paths.m4 @@ -1,9 +1,7 @@ dnl Whether to enable XDG support or not -AC_ARG_ENABLE(xdg, -[ --enable-xdg enable XDG support], +AC_ARG_ENABLE(xdg, AS_HELP_STRING([--enable-xdg], [enable XDG support]), xdg=$enable_xdg, - xdg=no -) + xdg=no) if test "x$xdg" != xno; then HAVE_XDG=yes else @@ -36,10 +34,10 @@ else fi AC_ARG_WITH(global-cfg, -[ --with-global-cfg=FILE If set will change the name and location of the - global config file used by QuakeForge. Defaults to - /etc/quakeforge.conf.], -globalconf="$withval", globalconf="auto") + AS_HELP_STRING([--with-global-cfg=FILE], + [if set will change the name and location of the global config file] + [used by QuakeForge. Defaults to /etc/quakeforge.conf.]), + globalconf="$withval", globalconf="auto") if test "x$globalconf" = "xauto" || test "x$globalconf" = "xyes" || \ test "x$globalconf" = "xno"; then dnl yes/no sanity checks globalconf="$default_globalconf" @@ -47,10 +45,10 @@ fi AC_DEFINE_UNQUOTED(FS_GLOBALCFG, "$globalconf", [Define this to the location of the global config file]) AC_ARG_WITH(user-cfg, -[ --with-user-cfg=FILE If set will change the name and location of the - user-specific config file used by QuakeForge. - Defaults to ~/.quakeforgerc.], -userconf="$withval", userconf="auto") + AS_HELP_STRING([--with-user-cfg=FILE], + [if set will change the name and location of the user-specific config] + [file used by QuakeForge. Defaults to ~/.quakeforgerc.]), + userconf="$withval", userconf="auto") if test "x$userconf" = "xauto" || test "x$userconf" = "xyes" || \ test "x$userconf" = "xno"; then dnl yes/no sanity checks userconf="$default_userconf" @@ -58,9 +56,10 @@ fi AC_DEFINE_UNQUOTED(FS_USERCFG, "$userconf", [Define this to the location of the user config file]) AC_ARG_WITH(sharepath, -[ --with-sharepath=DIR Use DIR for shared game data, defaults to - '.' or \${datarootdir}/games/quakeforge (if new style)], -sharepath=$withval, sharepath="auto") + AS_HELP_STRING([--with-sharepath=DIR], + [use DIR for shared game data, defaults to '.' or] + [${datarootdir}/games/quakeforge (if new style)]), + sharepath=$withval, sharepath="auto") if test "x$sharepath" = "xauto" -o "x$sharepath" = "xyes" -o "x$sharepath" = "x"; then sharepath="$default_sharepath" elif test "x$sharepath" = xno; then @@ -70,9 +69,10 @@ AC_DEFINE_UNQUOTED(FS_SHAREPATH, "$sharepath", [Define this to the shared game d QF_SUBST(sharepath) AC_ARG_WITH(userpath, -[ --with-userpath=DIR Use DIR for unshared game data, defaults to - '.' or ~/.quakeforge (if new style)], -userpath=$withval, userpath="auto") + AS_HELP_STRING([--with-userpath=DIR], + [use DIR for unshared game data, defaults to '.' or ~/.quakeforge] + [(if new style)]), + userpath=$withval, userpath="auto") if test "x$userpath" = "xauto" -o "x$userpath" = "xyes" -o "x$userpath" = "x"; then userpath="$default_userpath" elif test "x$userpath" = xno; then @@ -81,9 +81,9 @@ fi AC_DEFINE_UNQUOTED(FS_USERPATH, "$userpath", [Define this to the unshared game directory root]) AC_ARG_WITH(plugin-path, -[ --with-plugin-path=DIR Use DIR for loading plugins, defaults to - \${libdir}/quakeforge], -plugindir=$withval, plugindir="auto") + AS_HELP_STRING([--with-plugin-path=DIR], + [use DIR for loading plugins, defaults to ${libdir}/quakeforge]), + plugindir=$withval, plugindir="auto") PLUGINDIR="\${libdir}/quakeforge/plugins" if test "x$plugindir" = "xauto" -o "x$plugindir" = "xyes" -o "x$plugindir" = "x"; then @@ -112,7 +112,7 @@ AC_DEFINE_UNQUOTED(FS_SHADERPATH, "$expanded_shaderdir", [Define this to the pat AC_SUBST(plugindir) AC_ARG_WITH(gl-driver, - [ --with-gl-driver=NAME Name of OpenGL driver DLL/DSO], + AS_HELP_STRING([--with-gl-driver=NAME], [name of OpenGL driver DLL/DSO]), gl_driver=$withval, gl_driver=auto ) diff --git a/config.d/qfcc.m4 b/config.d/qfcc.m4 index 380e6a31c..55477fe81 100644 --- a/config.d/qfcc.m4 +++ b/config.d/qfcc.m4 @@ -3,9 +3,8 @@ F77=touch AC_SUBST(F77) AC_ARG_WITH(cpp, -[ --with-cpp=CPP how qfcc should invoke cpp], - cpp_name="$withval", cpp_name=auto -) + AS_HELP_STRING([--with-cpp=CPP], [how qfcc should invoke cpp]), + cpp_name="$withval", cpp_name=auto) if test "x$cpp_name" != xauto; then CPP_NAME="$cpp_name" else diff --git a/config.d/sdl.m4 b/config.d/sdl.m4 index 044faa513..2b32572a2 100644 --- a/config.d/sdl.m4 +++ b/config.d/sdl.m4 @@ -1,7 +1,5 @@ dnl SDL/SDL-GL checks -AC_ARG_ENABLE(sdl, -[ --enable-sdl enable checking for SDL], -) +AC_ARG_ENABLE(sdl, AS_HELP_STRING([--enable-sdl], [enable checking for SDL])) if test "x$enable_sdl" = xyes; then if test "x$PKG_CONFIG" != "x"; then @@ -24,8 +22,7 @@ fi dnl SDL-AUDIO checks AC_ARG_ENABLE(sdl-audio, -[ --disable-sdl-audio disable checking for SDL-AUDIO], -) + AS_HELP_STRING([ --disable-sdl-audio], [disable checking for SDL-AUDIO])) if test "x$enable_sdl_audio" != xno; then if test "x$HAVE_SDL" = "xyes"; then @@ -35,8 +32,7 @@ fi dnl SDL-CD checks AC_ARG_ENABLE(sdl-cd, -[ --disable-sdl-cd disable checking for SDL-CD], -) + AS_HELP_STRING([--disable-sdl-cd], [disable checking for SDL-CD])) if test "x$enable_sdl_cd" != xno; then if test "x$HAVE_SDL" = "xyes"; then HAVE_SDL_CD=yes diff --git a/config.d/sound.m4 b/config.d/sound.m4 index a720b88a2..e2cd663d2 100644 --- a/config.d/sound.m4 +++ b/config.d/sound.m4 @@ -2,9 +2,6 @@ dnl ================================================================== dnl Checks for sound dnl ================================================================== -dnl AC_ARG_ENABLE(samplerate, -dnl [ --disable-samplerate disable libsamplerate support], -dnl ) HAVE_SAMPLERATE=no SAMPLERATE_LIBS="" if test "x$enable_samplerate" != "xno"; then @@ -40,16 +37,16 @@ if test "x$enable_sound" != "xno"; then AC_CHECK_LIB(mme, waveOutOpen, HAVE_LIBMME=yes) AC_ARG_ENABLE(alsa, - [ --disable-alsa disable checks for ALSA support]) + AS_HELP_STRING([--disable-alsa], [disable checks for ALSA support])) AC_ARG_ENABLE(oss, - [ --disable-oss disable checks for OSS support]) + AS_HELP_STRING([--disable-oss], [disable checks for OSS support])) AC_ARG_ENABLE(sun, - [ --disable-sun disable checks for Sun audio support]) + AS_HELP_STRING([--disable-sun], [disable checks for Sun audio support])) AC_ARG_ENABLE(sound, - [ --disable-sound disable sound outright]) + AS_HELP_STRING([--disable-sound], [disable sound outright])) unset SOUND_TYPES @@ -96,8 +93,7 @@ QF_maGiC_VALUE AC_SUBST(ALSA_LIBS) AC_ARG_ENABLE(jack, - [ --disable-jack disable jack support], - ) + AS_HELP_STRING([--disable-jack], [disable jack support])) HAVE_JACK=no JACK_LIBS="" if test "x$enable_jack" != "xno"; then diff --git a/config.d/svga.m4 b/config.d/svga.m4 index 7fc66aa90..fd52fda3f 100644 --- a/config.d/svga.m4 +++ b/config.d/svga.m4 @@ -1,7 +1,7 @@ dnl Checks for SVGALib support AC_ARG_WITH(svga, -[ --with-svga=DIR use SVGALib found in DIR], -HAVE_SVGA=$withval, HAVE_SVGA=auto) + AS_HELP_STRING([--with-svga@<:@=DIR@:>@], [use SVGALib found in DIR]), + HAVE_SVGA=$withval, HAVE_SVGA=auto) if test "x$HAVE_SVGA" != xno -a "x$HAVE_SVGA" != xauto; then if test "x$HAVE_SVGA" != xauto; then SVGA_CFLAGS="$SVGA_CFLAGS -I$withval/include" diff --git a/config.d/versions.m4 b/config.d/versions.m4 index 32d6f85ae..91297048f 100644 --- a/config.d/versions.m4 +++ b/config.d/versions.m4 @@ -15,8 +15,9 @@ AC_DEFINE_UNQUOTED(QW_VERSION, "$QW_VERSION", AC_DEFINE_UNQUOTED(QW_QSG_VERSION, "$QW_QSG_VERSION", [Define this to the QSG standard version you support in QuakeWorld]) -AC_ARG_ENABLE([version-info], AS_HELP_STRING([--enable-version-info=CURRENT:REVISION:AGE], - [Override the value passed to libtool -version-info.]), +AC_ARG_ENABLE([version-info], + AS_HELP_STRING([--enable-version-info=CURRENT:REVISION:AGE], + [override the value passed to libtool -version-info.]), [], [enable_version_info=1:0:0]) QUAKE_LIBRARY_VERSION_INFO=$enable_version_info AC_SUBST([QUAKE_LIBRARY_VERSION_INFO]) diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index a13da8f78..e4a26581b 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -1,6 +1,6 @@ dnl Check for vulkan support AC_ARG_ENABLE(vulkan, -[ --disable-vulkan do not use Vulkan], + AS_HELP_STRING([--disable-vulkan], [do not use Vulkan]), HAVE_VULKAN=$enable_vulkan, HAVE_VULKAN=auto) if test "x$HAVE_VULKAN" != xno; then save_CPPFLAGS="$CPPFLAGS" diff --git a/config.d/x11.m4 b/config.d/x11.m4 index 00903aa72..b8a780ee4 100644 --- a/config.d/x11.m4 +++ b/config.d/x11.m4 @@ -14,7 +14,8 @@ fi dnl Check for XFree86-VidMode support AC_ARG_ENABLE(vidmode, -[ --disable-vidmode do not use XFree86 VidMode extension], + AS_HELP_STRING([--disable-vidmode], + [do not use XFree86 VidMode extension]), HAVE_VIDMODE=$enable_vidmode, HAVE_VIDMODE=auto) if test "x$HAVE_VIDMODE" != xno; then save_CPPFLAGS="$CPPFLAGS" @@ -35,8 +36,8 @@ AC_SUBST(VIDMODE_LIBS) dnl Check for XInput2 support AC_ARG_ENABLE(xi2, -[ --disable-xi2 do not use Xorg XInput2 extension], -HAVE_XI2=$enable_xi2, HAVE_XI2=auto) + AS_HELP_STRING([--disable-xi2], [do not use Xorg XInput2 extension]), + HAVE_XI2=$enable_xi2, HAVE_XI2=auto) if test "x$HAVE_XI2" != xno; then save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$X_CFLAGS $CPPFLAGS" @@ -55,8 +56,8 @@ AC_SUBST(XI2_LIBS) dnl Check for XInput2 support AC_ARG_ENABLE(xfixes, -[ --disable-xfixes do not use Xorg Xfixes extension], -HAVE_XFIXES=$enable_xfixes, HAVE_XFIXES=auto) + AS_HELP_STRING([--disable-xfixes], [do not use Xorg Xfixes extension]), + HAVE_XFIXES=$enable_xfixes, HAVE_XFIXES=auto) if test "x$HAVE_XFIXES" != xno; then save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$X_CFLAGS $CPPFLAGS" @@ -75,8 +76,8 @@ AC_SUBST(XFIXES_LIBS) dnl Check for DGA support AC_ARG_ENABLE(dga, -[ --disable-dga do not use XFree86 DGA extension], -HAVE_DGA=$enable_dga, HAVE_DGA=auto) + AS_HELP_STRING([--disable-dga], [do not use XFree86 DGA extension]), + HAVE_DGA=$enable_dga, HAVE_DGA=auto) if test "x$HAVE_DGA" != xno; then save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$X_CFLAGS $CPPFLAGS" diff --git a/configure.ac b/configure.ac index dc4839e7e..17c225b2e 100644 --- a/configure.ac +++ b/configure.ac @@ -123,8 +123,8 @@ m4_include(config.d/qfcc.m4) m4_include(config.d/compiling.m4) AC_ARG_ENABLE(static-doc, - [ --enable-static-doc Enable generation of doxygen docs for static] - [ functions.]) + AS_HELP_STRING([--enable-static-doc], + [enable generation of doxygen docs for static functions.])) STATIC_DOC=NO if test "x$enable_static_doc" = xyes; then STATIC_DOC=YES @@ -132,7 +132,8 @@ fi AC_SUBST(STATIC_DOC) AC_ARG_ENABLE(typecheck-progs, - [ --enable-typecheck-progs Enable type checking on progs field access]) + AS_HELP_STRING([--enable-typecheck-progs], + [enable type checking on progs field access])) if test "x$enable_typecheck_progs" = xyes; then AC_DEFINE(TYPECHECK_PROGS, 1, [Define this if you want progs typechecking]) fi diff --git a/m4/libFLAC.m4 b/m4/libFLAC.m4 index c43a0caa6..0db77857e 100644 --- a/m4/libFLAC.m4 +++ b/m4/libFLAC.m4 @@ -8,10 +8,10 @@ AC_DEFUN([AM_PATH_LIBFLAC], [dnl dnl Get the cflags and libraries dnl -AC_ARG_WITH(libFLAC,[ --with-libFLAC=PFX Prefix where libFLAC is installed (optional)], libFLAC_prefix="$withval", libFLAC_prefix="") -AC_ARG_WITH(libFLAC-libraries,[ --with-libFLAC-libraries=DIR Directory where libFLAC library is installed (optional)], libFLAC_libraries="$withval", libFLAC_libraries="") -AC_ARG_WITH(libFLAC-includes,[ --with-libFLAC-includes=DIR Directory where libFLAC header files are installed (optional)], libFLAC_includes="$withval", libFLAC_includes="") -AC_ARG_ENABLE(libFLACtest, [ --disable-libFLACtest Do not try to compile and run a test libFLAC program],, enable_libFLACtest=yes) +AC_ARG_WITH(libFLAC,AS_HELP_STRING([--with-libFLAC=PFX], [prefix where libFLAC is installed (optional)]), libFLAC_prefix="$withval", libFLAC_prefix="") +AC_ARG_WITH(libFLAC-libraries,AS_HELP_STRING([--with-libFLAC-libraries=DIR], [directory where libFLAC library is installed (optional)]), libFLAC_libraries="$withval", libFLAC_libraries="") +AC_ARG_WITH(libFLAC-includes,AS_HELP_STRING([--with-libFLAC-includes=DIR], [directory where libFLAC header files are installed (optional)]), libFLAC_includes="$withval", libFLAC_includes="") +AC_ARG_ENABLE(libFLACtest, AS_HELP_STRING([--disable-libFLACtest], [do not try to compile and run a test libFLAC program]),, enable_libFLACtest=yes) if test "x$libFLAC_libraries" != "x" ; then LIBFLAC_LIBS="-L$libFLAC_libraries" diff --git a/m4/libOggFLAC.m4 b/m4/libOggFLAC.m4 index eefc77b6a..673f737da 100644 --- a/m4/libOggFLAC.m4 +++ b/m4/libOggFLAC.m4 @@ -8,10 +8,10 @@ AC_DEFUN([AM_PATH_LIBOGGFLAC], [dnl dnl Get the cflags and libraries dnl -AC_ARG_WITH(libOggFLAC,[ --with-libOggFLAC=PFX Prefix where libOggFLAC is installed (optional)], libOggFLAC_prefix="$withval", libOggFLAC_prefix="") -AC_ARG_WITH(libOggFLAC-libraries,[ --with-libOggFLAC-libraries=DIR Directory where libOggFLAC library is installed (optional)], libOggFLAC_libraries="$withval", libOggFLAC_libraries="") -AC_ARG_WITH(libOggFLAC-includes,[ --with-libOggFLAC-includes=DIR Directory where libOggFLAC header files are installed (optional)], libOggFLAC_includes="$withval", libOggFLAC_includes="") -AC_ARG_ENABLE(libOggFLACtest, [ --disable-libOggFLACtest Do not try to compile and run a test libOggFLAC program],, enable_libOggFLACtest=yes) +AC_ARG_WITH(libOggFLAC,AS_HELP_STRING([--with-libOggFLAC=PFX], [prefix where libOggFLAC is installed (optional)]), libOggFLAC_prefix="$withval", libOggFLAC_prefix="") +AC_ARG_WITH(libOggFLAC-libraries,AS_HELP_STRING([--with-libOggFLAC-libraries=DIR], [directory where libOggFLAC library is installed (optional)]), libOggFLAC_libraries="$withval", libOggFLAC_libraries="") +AC_ARG_WITH(libOggFLAC-includes,AS_HELP_STRING([--with-libOggFLAC-includes=DIR], [directory where libOggFLAC header files are installed (optional)]), libOggFLAC_includes="$withval", libOggFLAC_includes="") +AC_ARG_ENABLE(libOggFLACtest, AS_HELP_STRING([--disable-libOggFLACtest] ,[do not try to compile and run a test libOggFLAC program]),, enable_libOggFLACtest=yes) if test "x$libOggFLAC_libraries" != "x" ; then LIBOGGFLAC_LIBS="-L$libOggFLAC_libraries" diff --git a/m4/ogg.m4 b/m4/ogg.m4 index 87b018508..3dca22e83 100644 --- a/m4/ogg.m4 +++ b/m4/ogg.m4 @@ -9,10 +9,10 @@ AC_DEFUN([XIPH_PATH_OGG], [dnl dnl Get the cflags and libraries dnl -AC_ARG_WITH(ogg,[ --with-ogg=PFX Prefix where libogg is installed (optional)], ogg_prefix="$withval", ogg_prefix="") -AC_ARG_WITH(ogg-libraries,[ --with-ogg-libraries=DIR Directory where libogg library is installed (optional)], ogg_libraries="$withval", ogg_libraries="") -AC_ARG_WITH(ogg-includes,[ --with-ogg-includes=DIR Directory where libogg header files are installed (optional)], ogg_includes="$withval", ogg_includes="") -AC_ARG_ENABLE(oggtest, [ --disable-oggtest Do not try to compile and run a test Ogg program],, enable_oggtest=yes) +AC_ARG_WITH(ogg,AS_HELP_STRING([--with-ogg=PFX], [prefix where libogg is installed (optional)]), ogg_prefix="$withval", ogg_prefix="") +AC_ARG_WITH(ogg-libraries,AS_HELP_STRING([--with-ogg-libraries=DIR], [directory where libogg library is installed (optional)]), ogg_libraries="$withval", ogg_libraries="") +AC_ARG_WITH(ogg-includes,AS_HELP_STRING([--with-ogg-includes=DIR], [directory where libogg header files are installed (optional)]), ogg_includes="$withval", ogg_includes="") +AC_ARG_ENABLE(oggtest, AS_HELP_STRING([--disable-oggtest], [do not try to compile and run a test Ogg program]),, enable_oggtest=yes) if test "x$ogg_libraries" != "x" ; then OGG_LIBS="-L$ogg_libraries" diff --git a/m4/quakeforge.m4 b/m4/quakeforge.m4 index ce2d9b38b..ea0d3eae9 100644 --- a/m4/quakeforge.m4 +++ b/m4/quakeforge.m4 @@ -144,10 +144,8 @@ QF_STATIC_PLUGIN_PROTOS(m4_default($4,$1),[$1],[$2]) QF_STATIC_PLUGIN_LIST(m4_default($4,$1),[$1],[$2])]) AC_DEFUN([QF_WITH_TARGETS], [ -AC_ARG_WITH($1, - [$2] - [$3], $1="$withval", $1=all -) +AC_ARG_WITH($1, AS_HELP_STRING([--with-$1=], [$2:] [$3]), + $1="$withval", $1=all) if test "x${$1}" = "xall"; then for qf_t in `echo '$3' | sed -e "s/,/ /g"`''; do eval ENABLE_$1_${qf_t}=yes diff --git a/m4/sdl.m4 b/m4/sdl.m4 index 9018ad5e8..6b7117e2e 100644 --- a/m4/sdl.m4 +++ b/m4/sdl.m4 @@ -12,11 +12,11 @@ AC_DEFUN([AM_PATH_SDL], [dnl dnl Get the cflags and libraries from the sdl-config script dnl -AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], +AC_ARG_WITH(sdl-prefix,AS_HELP_STRING([--with-sdl-prefix=PFX], [prefix where SDL is installed (optional)]), sdl_prefix="$withval", sdl_prefix="") -AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], +AC_ARG_WITH(sdl-exec-prefix,AS_HELP_STRING([--with-sdl-exec-prefix=PFX], [exec prefix where SDL is installed (optional)]), sdl_exec_prefix="$withval", sdl_exec_prefix="") -AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], +AC_ARG_ENABLE(sdltest, AS_HELP_STRING([--disable-sdltest] ,[do not try to compile and run a test SDL program]), , enable_sdltest=yes) if test x$sdl_exec_prefix != x ; then diff --git a/m4/vorbis.m4 b/m4/vorbis.m4 index 8071ab886..b504b5d4c 100644 --- a/m4/vorbis.m4 +++ b/m4/vorbis.m4 @@ -10,10 +10,10 @@ AC_DEFUN([XIPH_PATH_VORBIS], [dnl dnl Get the cflags and libraries dnl -AC_ARG_WITH(vorbis,[ --with-vorbis=PFX Prefix where libvorbis is installed (optional)], vorbis_prefix="$withval", vorbis_prefix="") -AC_ARG_WITH(vorbis-libraries,[ --with-vorbis-libraries=DIR Directory where libvorbis library is installed (optional)], vorbis_libraries="$withval", vorbis_libraries="") -AC_ARG_WITH(vorbis-includes,[ --with-vorbis-includes=DIR Directory where libvorbis header files are installed (optional)], vorbis_includes="$withval", vorbis_includes="") -AC_ARG_ENABLE(vorbistest, [ --disable-vorbistest Do not try to compile and run a test Vorbis program],, enable_vorbistest=yes) +AC_ARG_WITH(vorbis,AS_HELP_STRING([--with-vorbis=PFX], [prefix where libvorbis is installed (optional)]), vorbis_prefix="$withval", vorbis_prefix="") +AC_ARG_WITH(vorbis-libraries, AS_HELP_STRING([--with-vorbis-libraries=DIR]. [directory where libvorbis library is installed (optional)]), vorbis_libraries="$withval", vorbis_libraries="") +AC_ARG_WITH(vorbis-includes,AS_HELP_STRING([--with-vorbis-includes=DIR], [directory where libvorbis header files are installed (optional)]), vorbis_includes="$withval", vorbis_includes="") +AC_ARG_ENABLE(vorbistest, AS_HELP_STRING([--disable-vorbistest], [do not try to compile and run a test Vorbis program]),, enable_vorbistest=yes) if test "x$vorbis_libraries" != "x" ; then VORBIS_LIBS="-L$vorbis_libraries" diff --git a/m4/xmms.m4 b/m4/xmms.m4 index f4c03a73b..2f52673f2 100644 --- a/m4/xmms.m4 +++ b/m4/xmms.m4 @@ -61,9 +61,9 @@ function vercmp(ver1, ver2, ver1arr, ver2arr, \ AC_DEFUN([AM_PATH_XMMS], [ -AC_ARG_WITH(xmms-prefix,[ --with-xmms-prefix=PFX Prefix where XMMS is installed (optional)], +AC_ARG_WITH(xmms-prefix,AS_HELP_STRING([--with-xmms-prefix=PFX], [prefix where XMMS is installed (optional)]), xmms_config_prefix="$withval", xmms_config_prefix="") -AC_ARG_WITH(xmms-exec-prefix,[ --with-xmms-exec-prefix=PFX Exec prefix where XMMS is installed (optional)], +AC_ARG_WITH(xmms-exec-prefix,AS_HELP_STRING([--with-xmms-exec-prefix=PFX], [exec prefix where XMMS is installed (optional)]), xmms_config_exec_prefix="$withval", xmms_config_exec_prefix="") if test x$xmms_config_exec_prefix != x; then From 7892382639918216dc78492e2ab2f9d3f815b238 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Dec 2021 15:11:45 +0900 Subject: [PATCH 1995/3664] [qwaq] Remove obsolete file I don't remember when it was last used, and deleting it saves me the hassle of sorting out its header :P --- ruamoko/qwaq/builtins/builtins.c | 170 ------------------------------- 1 file changed, 170 deletions(-) delete mode 100644 ruamoko/qwaq/builtins/builtins.c diff --git a/ruamoko/qwaq/builtins/builtins.c b/ruamoko/qwaq/builtins/builtins.c deleted file mode 100644 index 9528636b9..000000000 --- a/ruamoko/qwaq/builtins/builtins.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - #FILENAME# - - #DESCRIPTION# - - Copyright (C) 2001 #AUTHOR# - - Author: #AUTHOR# - Date: #DATE# - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ruamoko/qwaq/qwaq.h" - -static void -bi_print (progs_t *pr) -{ - const char *str; - - str = P_GSTRING (pr, 0); - fprintf (stdout, "%s", str); -} - -static void -bi_errno (progs_t *pr) -{ - R_INT (pr) = errno; -} - -static void -bi_strerror (progs_t *pr) -{ - int err = P_INT (pr, 0); - RETURN_STRING (pr, strerror (err)); -} - -static void -bi_open (progs_t *pr) -{ - const char *path = P_GSTRING (pr, 0); - int flags = P_INT (pr, 1); - int mode = P_INT (pr, 2); - R_INT (pr) = open (path, flags, mode); -} - -static void -bi_close (progs_t *pr) -{ - int handle = P_INT (pr, 0); - R_INT (pr) = close (handle); -} - -static void -bi_read (progs_t *pr) -{ - int handle = P_INT (pr, 0); - int count = P_INT (pr, 1); - int *read_result = (int *)P_GPOINTER (pr, 2); - int res; - char *buffer; - - buffer = Hunk_TempAlloc (0, count); - if (!buffer) - PR_Error (pr, "%s: couldn't allocate %d bytes", "bi_read", count); - res = read (handle, buffer, count); - if (res != -1) - RETURN_STRING (pr, buffer); - *read_result = res; -} - -static void -bi_write (progs_t *pr) -{ - int handle = P_INT (pr, 0); - const char *buffer = P_GSTRING (pr, 1); - int count = P_INT (pr, 2); - - R_INT (pr) = write (handle, buffer, count); -} - -static void -bi_seek (progs_t *pr) -{ - int handle = P_INT (pr, 0); - int pos = P_INT (pr, 1); - int whence = P_INT (pr, 2); - - R_INT (pr) = lseek (handle, pos, whence); -} - -/* -static void -bi_traceon (progs_t *pr) -{ - pr->pr_trace = true; - pr->pr_trace_depth = pr->pr_depth; -} - -static void -bi_traceoff (progs_t *pr) -{ - pr->pr_trace = false; -} -*/ -static void -bi_printf (progs_t *pr) -{ - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; - dstring_t *dstr = dstring_new (); - - PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); - if (dstr->str) - fputs (dstr->str, stdout); - dstring_delete (dstr); -} - -static builtin_t builtins[] = { - {"print", bi_print, -1}, - {"errno", bi_errno, -1}, - {"strerror", bi_strerror, -1}, - {"open", bi_open, -1}, - {"close", bi_close, -1}, - {"read", bi_read, -1}, - {"write", bi_write, -1}, - {"seek", bi_seek, -1}, -// {"traceon", bi_traceon, -1}, -// {"traceoff", bi_traceoff, -1}, - {"printf", bi_printf, -1}, - {0} -}; - -void -BI_Init (progs_t *pr) -{ - PR_RegisterBuiltins (pr, builtins); -} From 97c3cbf7191119d629e9000f44e8add3d8e02f12 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Dec 2021 15:15:18 +0900 Subject: [PATCH 1996/3664] [qwaq] Rename input.c It's very specialized toward terminal input (ie, for qwaq-curses). --- ruamoko/qwaq/Makemodule.am | 2 +- ruamoko/qwaq/builtins/qwaq-curses.c | 2 +- ruamoko/qwaq/builtins/{input.c => term-input.c} | 4 ++-- ruamoko/qwaq/qwaq.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename ruamoko/qwaq/builtins/{input.c => term-input.c} (99%) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 12b71d6bd..f43748910 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -73,8 +73,8 @@ ruamoko_qwaq_qwaq_curses_SOURCES= \ ruamoko/qwaq/builtins/curses.c \ ruamoko/qwaq/builtins/debug.c \ ruamoko/qwaq/builtins/editbuffer.c \ - ruamoko/qwaq/builtins/input.c \ ruamoko/qwaq/builtins/qwaq-curses.c \ + ruamoko/qwaq/builtins/term-input.c \ ruamoko/qwaq/builtins/threading.c ruamoko_qwaq_qwaq_curses_LDADD= $(qwaq_curses_libs) $(QWAQ_LIBS) \ diff --git a/ruamoko/qwaq/builtins/qwaq-curses.c b/ruamoko/qwaq/builtins/qwaq-curses.c index b2aab8f94..e7193b274 100644 --- a/ruamoko/qwaq/builtins/qwaq-curses.c +++ b/ruamoko/qwaq/builtins/qwaq-curses.c @@ -60,7 +60,7 @@ static progsinit_f main_app[] = { BI_Curses_Init, - BI_Input_Init, + BI_TermInput_Init, QWAQ_EditBuffer_Init, QWAQ_Debug_Init, 0 diff --git a/ruamoko/qwaq/builtins/input.c b/ruamoko/qwaq/builtins/term-input.c similarity index 99% rename from ruamoko/qwaq/builtins/input.c rename to ruamoko/qwaq/builtins/term-input.c index 3c2d7a694..7ebbde1d2 100644 --- a/ruamoko/qwaq/builtins/input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -1,5 +1,5 @@ /* - input.c + term-input.c Input handling @@ -891,7 +891,7 @@ bi_input_shutdown (void *_pr) } void -BI_Input_Init (progs_t *pr) +BI_TermInput_Init (progs_t *pr) { qwaq_input_resources_t *res = calloc (sizeof (*res), 1); res->pr = pr; diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 0a919a0c8..d580dada0 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -26,7 +26,7 @@ typedef struct qwaq_thread_set_s DARRAY_TYPE(qwaq_thread_t *) qwaq_thread_set_t; struct memhunk_s; void BI_Init (struct memhunk_s *hunk, progs_t *pr); void BI_Curses_Init (progs_t *pr); -void BI_Input_Init (progs_t *pr); +void BI_TermInput_Init (progs_t *pr); void QWAQ_EditBuffer_Init (progs_t *pr); extern struct cbuf_s *qwaq_cbuf; qwaq_thread_t *create_thread (void *(*thread_func) (qwaq_thread_t *), void *); From 0e7e88815cb6c4fcf70c0e5a7ee5f8fe6dca8c03 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Dec 2021 16:09:45 +0900 Subject: [PATCH 1997/3664] [qwaq] Fix up file headers --- ruamoko/qwaq/builtins/editbuffer.c | 29 +++++++++++++++++++++++++++++ ruamoko/qwaq/builtins/main.c | 2 +- ruamoko/qwaq/builtins/qwaq-bi.c | 10 +++++----- ruamoko/qwaq/builtins/qwaq-cmd.c | 8 ++++---- ruamoko/qwaq/builtins/qwaq-curses.c | 8 ++++---- ruamoko/qwaq/builtins/qwaq.c | 10 +++++----- 6 files changed, 48 insertions(+), 19 deletions(-) diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index 4b276f248..cea68c941 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -1,3 +1,32 @@ +/* + editbuffer.c + + High level wrapper for TextBuffer_Destroy + + Copyright (C) 2020 Bill Currie + + Author: Bill Currie + Date: 2020/03/22 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ #ifdef HAVE_CONFIG_H # include "config.h" #endif diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 3a1329720..d23a029db 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -1,5 +1,5 @@ /* - #FILENAME# + main.c Qwaq diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/qwaq-bi.c index 8c30dd47c..f00f1eaa8 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/qwaq-bi.c @@ -1,12 +1,12 @@ /* - #FILENAME# + qwaq-bi.c - #DESCRIPTION# + Basic game engine builtins - Copyright (C) 2001 #AUTHOR# + Copyright (C) 2012 Bill Currie - Author: #AUTHOR# - Date: #DATE# + Author: Bill Currie + Date: 2012/7/24 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/ruamoko/qwaq/builtins/qwaq-cmd.c b/ruamoko/qwaq/builtins/qwaq-cmd.c index 0f31f362e..c248d5ff7 100644 --- a/ruamoko/qwaq/builtins/qwaq-cmd.c +++ b/ruamoko/qwaq/builtins/qwaq-cmd.c @@ -1,12 +1,12 @@ /* - #FILENAME# + qwaq-cmd.c - Qwaq + Qwaq command-line tool initialization - Copyright (C) 2001 Bill Currie + Copyright (C) 2021 Bill Currie Author: Bill Currie - Date: 2001/06/01 + Date: 2021/07/06 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/ruamoko/qwaq/builtins/qwaq-curses.c b/ruamoko/qwaq/builtins/qwaq-curses.c index e7193b274..0e4f2aaaa 100644 --- a/ruamoko/qwaq/builtins/qwaq-curses.c +++ b/ruamoko/qwaq/builtins/qwaq-curses.c @@ -1,12 +1,12 @@ /* - #FILENAME# + qwaq-curses.c - Qwaq + Qwaq curses initialization - Copyright (C) 2001 Bill Currie + Copyright (C) 2021 Bill Currie Author: Bill Currie - Date: 2001/06/01 + Date: 2021/07/06 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/ruamoko/qwaq/builtins/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c index b23f1c632..47cd5b588 100644 --- a/ruamoko/qwaq/builtins/qwaq.c +++ b/ruamoko/qwaq/builtins/qwaq.c @@ -1,12 +1,12 @@ /* - #FILENAME# + qwaq.c - #DESCRIPTION# + Qwaq - Copyright (C) 2001 #AUTHOR# + Copyright (C) 2001 Bill Currie - Author: #AUTHOR# - Date: #DATE# + Author: Bill Currie + Date: 2001/6/1 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License From d3853a24301fba9daf0dadf2636165a3af01ba43 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Dec 2021 16:45:22 +0900 Subject: [PATCH 1998/3664] [qwaq] Update qwaq-x11's initialization It now uses the advanced command line parsing used by qwaq-curses and qwaq-cmd, but currently disables multi-threading (I don't want to deal with threading in the engine just yet). The int file is -graphics because qwaq-x11 is really just the X11 target, qwaq-win is built for windows, but they use the same basic startup (I hope). --- ruamoko/qwaq/Makemodule.am | 7 +- .../qwaq/builtins/{qwaq-bi.c => graphics.c} | 22 +- ruamoko/qwaq/builtins/qwaq-graphics.c | 106 ++++++++++ ruamoko/qwaq/builtins/qwaq.c | 197 ------------------ ruamoko/qwaq/qwaq.h | 3 +- 5 files changed, 116 insertions(+), 219 deletions(-) rename ruamoko/qwaq/builtins/{qwaq-bi.c => graphics.c} (90%) create mode 100644 ruamoko/qwaq/builtins/qwaq-graphics.c delete mode 100644 ruamoko/qwaq/builtins/qwaq.c diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index f43748910..d776820df 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -113,10 +113,13 @@ qwaq_x11_libs= \ $(top_builddir)/libs/models/libQFmodels.la \ $(top_builddir)/libs/video/targets/libQFx11.la \ $(qwaq_client_libs) -ruamoko_qwaq_qwaq_x11_SOURCES=ruamoko/qwaq/builtins/qwaq.c ruamoko/qwaq/builtins/qwaq-bi.c +ruamoko_qwaq_qwaq_x11_SOURCES= \ + ruamoko/qwaq/builtins/main.c \ + ruamoko/qwaq/builtins/qwaq-graphics.c \ + ruamoko/qwaq/builtins/graphics.c ruamoko_qwaq_qwaq_x11_LDADD= $(qwaq_x11_libs) $(QWAQ_LIBS) \ $(VIDMODE_LIBS) $(DGA_LIBS) ${XFIXES_LIBS} $(XI2_LIBS) $(X_LIBS) \ - -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(DL_LIBS) + -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) $(PTHREAD_LDFLAGS) $(DL_LIBS) ruamoko_qwaq_qwaq_x11_LDFLAGS= ruamoko_qwaq_qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) diff --git a/ruamoko/qwaq/builtins/qwaq-bi.c b/ruamoko/qwaq/builtins/graphics.c similarity index 90% rename from ruamoko/qwaq/builtins/qwaq-bi.c rename to ruamoko/qwaq/builtins/graphics.c index f00f1eaa8..57d9c76ee 100644 --- a/ruamoko/qwaq/builtins/qwaq-bi.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -1,5 +1,5 @@ /* - qwaq-bi.c + graphics.c Basic game engine builtins @@ -80,21 +80,6 @@ quit_f (void) Sys_Quit (); } -static void -bi_printf (progs_t *pr) -{ - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; - dstring_t *dstr = dstring_new (); - - PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); - if (dstr->str) { - Con_Printf ("%s", dstr->str); - } - dstring_delete (dstr); -} - static progs_t *bi_rprogs; static func_t qc2d; @@ -138,7 +123,6 @@ bi_shutdown_ (progs_t *pr) } static builtin_t builtins[] = { - {"printf", bi_printf, -1}, {"refresh", bi_refresh, -1}, {"refresh_2d", bi_refresh_2d, -1}, {"shutdown", bi_shutdown_, -1}, @@ -151,9 +135,11 @@ bi_shutdown (void *data) } void -BI_Init (memhunk_t *hunk, progs_t *pr) +BI_Graphics_Init (progs_t *pr) { byte *basepal, *colormap; + size_t memsize = 8 * 1024 * 1024; + memhunk_t *hunk = Memory_Init (Sys_Alloc (memsize), memsize); PR_RegisterBuiltins (pr, builtins); diff --git a/ruamoko/qwaq/builtins/qwaq-graphics.c b/ruamoko/qwaq/builtins/qwaq-graphics.c new file mode 100644 index 000000000..9cb56b15e --- /dev/null +++ b/ruamoko/qwaq/builtins/qwaq-graphics.c @@ -0,0 +1,106 @@ +/* + qwaq-graphics.c + + Qwaq graphics initialization + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/12/20 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +//#include "QF/cbuf.h" +//#include "QF/cmd.h" +//#include "QF/cvar.h" +//#include "QF/gib.h" +//#include "QF/idparse.h" +#include "QF/input.h" +//#include "QF/keys.h" +//#include "QF/progs.h" +//#include "QF/qargs.h" +//#include "QF/quakefs.h" +//#include "QF/ruamoko.h" +//#include "QF/sys.h" +//#include "QF/va.h" +//#include "QF/zone.h" + +//#include "compat.h" + +#include "ruamoko/qwaq/qwaq.h" + +static progsinit_f main_app[] = { + BI_Graphics_Init, + 0 +}; +#if 0// FIXME no multi-thread support yet +static progsinit_f secondary_app[] = { + 0 +}; +#endif +static FILE *logfile; + +static __attribute__((format(PRINTF, 1, 0))) void +qwaq_print (const char *fmt, va_list args) +{ + vfprintf (logfile, fmt, args); + fflush (logfile); +} + +int +qwaq_init_threads (qwaq_thread_set_t *thread_data) +{ + int main_ind = -1; + + logfile = fopen ("qwaq-graphics.log", "wt"); + Sys_SetStdPrintf (qwaq_print); + + IN_Init_Cvars (); + //IN_Init (); + + for (size_t i = 1, thread_ind = 0; i < thread_data->size; i++) { + qwaq_thread_t *thread = thread_data->a[i]; + progsinit_f *app_funcs = 0;//secondary_app; + + if (thread->args.size && thread->args.a[0] + && strcmp (thread->args.a[0], "--qargs")) { + // skip the args set that's passed to qargs + continue; + } + if (thread_ind < thread_data->a[0]->args.size) { + thread->args.a[0] = thread_data->a[0]->args.a[thread_ind++]; + } else { + printf ("ignoring extra arg sets\n"); + break; + } + if (main_ind < 0) { + main_ind = i; + app_funcs = main_app; + } + thread->progsinit = app_funcs; + } + return main_ind; +} diff --git a/ruamoko/qwaq/builtins/qwaq.c b/ruamoko/qwaq/builtins/qwaq.c deleted file mode 100644 index 47cd5b588..000000000 --- a/ruamoko/qwaq/builtins/qwaq.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - qwaq.c - - Qwaq - - Copyright (C) 2001 Bill Currie - - Author: Bill Currie - Date: 2001/6/1 - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "QF/cbuf.h" -#include "QF/cmd.h" -#include "QF/cvar.h" -#include "QF/gib.h" -#include "QF/idparse.h" -#include "QF/progs.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/ruamoko.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/zone.h" - -#include "ruamoko/qwaq/qwaq.h" - -#define MAX_EDICTS 1024 - -static edict_t *edicts; -static int num_edicts; -static int reserved_edicts; -static progs_t pr; - -cbuf_t *qwaq_cbuf; - -static QFile * -open_file (const char *path, int *len) -{ - QFile *file = Qopen (path, "rbz"); - - if (!file) { - perror (path); - return 0; - } - *len = Qfilesize (file); - return file; -} - -static void * -load_file (progs_t *pr, const char *name, off_t *_size) -{ - QFile *file; - int size; - char *sym; - - file = open_file (name, &size); - if (!file) { - file = open_file (va (0, "%s.gz", name), &size); - if (!file) { - return 0; - } - } - sym = malloc (size + 1); - sym[size] = 0; - Qread (file, sym, size); - *_size = size; - return sym; -} - -static void * -allocate_progs_mem (progs_t *pr, int size) -{ - return malloc (size); -} - -static void -free_progs_mem (progs_t *pr, void *mem) -{ - free (mem); -} - -static void -init_qf (void) -{ - qwaq_cbuf = Cbuf_New (&id_interp); - - Sys_Init (); - GIB_Init (true); - COM_ParseConfig (qwaq_cbuf); - - //Cvar_Set (developer, "1"); - - size_t memsize = 8 * 1024 * 1024; - memhunk_t *hunk = Memory_Init (Sys_Alloc (memsize), memsize); - - Cvar_Get ("pr_debug", "2", 0, 0, 0); - Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); - - pr.pr_edicts = &edicts; - pr.num_edicts = &num_edicts; - pr.reserved_edicts = &reserved_edicts; - pr.load_file = load_file; - pr.allocate_progs_mem = allocate_progs_mem; - pr.free_progs_mem = free_progs_mem; - pr.no_exec_limit = 1; - - PR_Init_Cvars (); - PR_Init (&pr); - RUA_Init (&pr, 0); - PR_Cmds_Init (&pr); - BI_Init (hunk, &pr); -} - -static int -load_progs (const char *name) -{ - QFile *file; - int size; - - file = open_file (name, &size); - if (!file) { - return 0; - } - pr.progs_name = name; - pr.max_edicts = 1; - pr.zone_size = 1024*1024; - PR_LoadProgsFile (&pr, file, size); - Qclose (file); - if (!PR_RunLoadFuncs (&pr) || !PR_RunPostLoadFuncs (&pr)) - PR_Error (&pr, "unable to load %s", pr.progs_name); - return 1; -} - -int -main (int argc, const char **argv) -{ - dfunction_t *dfunc; - func_t main_func = 0; - const char *name = "qwaq.dat"; - string_t *pr_argv; - int pr_argc = 1, i; - - COM_InitArgv (argc, argv); - init_qf (); - - if (argc > 1) - name = argv[1]; - - if (!load_progs (name)) - Sys_Error ("couldn't load %s", name); - - PR_PushFrame (&pr); - if (argc > 2) - pr_argc = argc - 1; - pr_argv = PR_Zone_Malloc (&pr, (pr_argc + 1) * 4); - pr_argv[0] = PR_SetTempString (&pr, name); - for (i = 1; i < pr_argc; i++) - pr_argv[i] = PR_SetTempString (&pr, argv[1 + i]); - pr_argv[i] = 0; - - if ((dfunc = PR_FindFunction (&pr, ".main")) - || (dfunc = PR_FindFunction (&pr, "main"))) - main_func = dfunc - pr.pr_functions; - else - PR_Undefined (&pr, "function", "main"); - PR_RESET_PARAMS (&pr); - P_INT (&pr, 0) = pr_argc; - P_POINTER (&pr, 1) = PR_SetPointer (&pr, pr_argv); - pr.pr_argc = 2; - PR_ExecuteProgram (&pr, main_func); - PR_PopFrame (&pr); - return R_INT (&pr); -} diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index d580dada0..005704d86 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -23,8 +23,7 @@ typedef struct qwaq_thread_s { typedef struct qwaq_thread_set_s DARRAY_TYPE(qwaq_thread_t *) qwaq_thread_set_t; -struct memhunk_s; -void BI_Init (struct memhunk_s *hunk, progs_t *pr); +void BI_Graphics_Init (progs_t *pr); void BI_Curses_Init (progs_t *pr); void BI_TermInput_Init (progs_t *pr); void QWAQ_EditBuffer_Init (progs_t *pr); From ad83422c563a72e8f20f3c99537cf911b1e59ffb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Dec 2021 20:13:21 +0900 Subject: [PATCH 1999/3664] [qwaq] Adapt startup code for use in a game engine Until now, the new qwaq startup was used only in command-line tools and console applications where things like Ruamoko security and having a hunk were not an issue. Now the start up code (qwaq-*.c) can specify that Ruamoko is to be secured and provide a hunk on a per-thread basis, and the thread data is passed into the progs code via a progs resource. --- ruamoko/qwaq/builtins/graphics.c | 8 +++----- ruamoko/qwaq/builtins/main.c | 8 +++++++- ruamoko/qwaq/builtins/qwaq-graphics.c | 24 +++++------------------- ruamoko/qwaq/qwaq.h | 2 ++ 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 57d9c76ee..8966668cd 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -55,7 +55,6 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/sound.h" #include "QF/sys.h" #include "QF/vid.h" -#include "QF/zone.h" #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" @@ -137,17 +136,16 @@ bi_shutdown (void *data) void BI_Graphics_Init (progs_t *pr) { + qwaq_thread_t *thread = PR_Resources_Find (pr, "qwaq_thread"); byte *basepal, *colormap; - size_t memsize = 8 * 1024 * 1024; - memhunk_t *hunk = Memory_Init (Sys_Alloc (memsize), memsize); PR_RegisterBuiltins (pr, builtins); - QFS_Init (hunk, "nq"); + QFS_Init (thread->hunk, "nq"); PI_Init (); PI_RegisterPlugins (client_plugin_list); - Sys_RegisterShutdown (bi_shutdown, 0); + Sys_RegisterShutdown (bi_shutdown, pr); VID_Init_Cvars (); IN_Init_Cvars (); diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index d23a029db..3b79f6e5d 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -189,6 +189,11 @@ common_builtins_init (progs_t *pr) PR_RegisterBuiltins (pr, common_builtins); } +static void +qwaq_thread_clear (progs_t *pr, void *_thread) +{ +} + static progs_t * create_progs (qwaq_thread_t *thread) { @@ -203,7 +208,8 @@ create_progs (qwaq_thread_t *thread) PR_Init_Cvars (); PR_Init (pr); - RUA_Init (pr, 0); + PR_Resources_Register (pr, "qwaq_thread", thread, qwaq_thread_clear); + RUA_Init (pr, thread->rua_security); common_builtins_init (pr); while (*funcs) { (*funcs++) (pr); diff --git a/ruamoko/qwaq/builtins/qwaq-graphics.c b/ruamoko/qwaq/builtins/qwaq-graphics.c index 9cb56b15e..bd2769cf6 100644 --- a/ruamoko/qwaq/builtins/qwaq-graphics.c +++ b/ruamoko/qwaq/builtins/qwaq-graphics.c @@ -33,22 +33,7 @@ #include -//#include "QF/cbuf.h" -//#include "QF/cmd.h" -//#include "QF/cvar.h" -//#include "QF/gib.h" -//#include "QF/idparse.h" -#include "QF/input.h" -//#include "QF/keys.h" -//#include "QF/progs.h" -//#include "QF/qargs.h" -//#include "QF/quakefs.h" -//#include "QF/ruamoko.h" -//#include "QF/sys.h" -//#include "QF/va.h" -//#include "QF/zone.h" - -//#include "compat.h" +#include "QF/zone.h" #include "ruamoko/qwaq/qwaq.h" @@ -74,13 +59,12 @@ int qwaq_init_threads (qwaq_thread_set_t *thread_data) { int main_ind = -1; + size_t memsize = 8 * 1024 * 1024; + memhunk_t *hunk = Memory_Init (Sys_Alloc (memsize), memsize); logfile = fopen ("qwaq-graphics.log", "wt"); Sys_SetStdPrintf (qwaq_print); - IN_Init_Cvars (); - //IN_Init (); - for (size_t i = 1, thread_ind = 0; i < thread_data->size; i++) { qwaq_thread_t *thread = thread_data->a[i]; progsinit_f *app_funcs = 0;//secondary_app; @@ -101,6 +85,8 @@ qwaq_init_threads (qwaq_thread_set_t *thread_data) app_funcs = main_app; } thread->progsinit = app_funcs; + thread->rua_security = 1; + thread->hunk = hunk; //FIXME shared (but currently only one thread) } return main_ind; } diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 005704d86..4bdc09435 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -16,6 +16,8 @@ typedef struct qwaq_thread_s { sys_printf_t sys_printf; progsinit_f*progsinit; progs_t *pr; + int rua_security; + struct memhunk_s *hunk; struct hashlink_s *hashlink_freelist; func_t main_func; void *data; From 194f958666b315678b58773a1afd3d6282a570ea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Dec 2021 21:03:40 +0900 Subject: [PATCH 2000/3664] [console] Add a comment about skipping the first char I had to dig through logs of deleted files to find out what was going on. Forget six months later, twenty years... --- libs/console/client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/console/client.c b/libs/console/client.c index 7bf1493d0..ae3d0649a 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -456,6 +456,7 @@ C_Print (const char *fmt, va_list args) } // echo to debugging console + // but don't print the highchars flag (leading \x01) if ((byte)buffer->str[0] > 2) fputs (buffer->str, stdout); else if ((byte)buffer->str[0]) From 2d109e615b3ce9edb2c527593bed8c78ab3f2eb1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Dec 2021 00:36:42 +0900 Subject: [PATCH 2001/3664] [client] Clean up a stray reference to the renderer Reaching into the renderer internals for r_worldmodel doesn't work when the plugins are not static. --- include/client/particles.h | 3 +++ libs/client/cl_particles.c | 8 +++----- nq/source/cl_main.c | 8 ++++++++ qw/source/cl_main.c | 8 ++++++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/include/client/particles.h b/include/client/particles.h index 0e499f53b..a56762bd8 100644 --- a/include/client/particles.h +++ b/include/client/particles.h @@ -71,4 +71,7 @@ extern float cl_realtime; void CL_Particles_Init (void); +struct model_s; +void CL_LoadPointFile (const struct model_s *model); + #endif // __client_particles_h_ diff --git a/libs/client/cl_particles.c b/libs/client/cl_particles.c index 5f92df3bc..e43a028c2 100644 --- a/libs/client/cl_particles.c +++ b/libs/client/cl_particles.c @@ -222,15 +222,15 @@ add_particle (ptype_t type, vec4f_t pos, vec4f_t vel, float live, int color, particle_new (type, part_tex_dot, pos, 1, vel, live, color, 1, ramp); } -static void -pointfile_f (void) +void +CL_LoadPointFile (const model_t *model) { const char *name; char *mapname; int c; QFile *f; - mapname = strdup (r_worldentity.renderer.model->path); + mapname = strdup (model->path); if (!mapname) Sys_Error ("Can't duplicate mapname!"); QFS_StripExtension (mapname, mapname); @@ -1272,8 +1272,6 @@ CL_Particles_Init (void) { mtwist_seed (&mt, 0xdeadbeef); cl_psystem = r_funcs->ParticleSystem (); - Cmd_AddCommand ("pointfile", pointfile_f, - "Load a pointfile to determine map leaks."); easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, easter_eggs_f, "Enables easter eggs."); particles_style = Cvar_Get ("particles_style", "1", CVAR_ARCHIVE, diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index d7b474171..cd5ab5730 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -424,6 +424,12 @@ CL_NextDemo (void) cls.demonum++; } +static void +pointfile_f (void) +{ + CL_LoadPointFile (cl.worldmodel); +} + static void CL_PrintEntities_f (void) { @@ -604,6 +610,8 @@ CL_Init (cbuf_t *cbuf) V_Init (); + Cmd_AddCommand ("pointfile", pointfile_f, + "Load a pointfile to determine map leaks."); Cmd_AddCommand ("entities", CL_PrintEntities_f, "No Description"); Cmd_AddCommand ("disconnect", CL_Disconnect_f, "No Description"); Cmd_AddCommand ("maplist", Con_Maplist_f, "List available maps"); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index a5b462735..98ed535a5 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -237,6 +237,12 @@ CL_Quit_f (void) Sys_Quit (); } +static void +pointfile_f (void) +{ + CL_LoadPointFile (cl.worldmodel); +} + static void CL_Version_f (void) { @@ -1229,6 +1235,8 @@ CL_Init (void) cl.players = calloc (MAX_CLIENTS, sizeof (player_info_t)); // register our commands + Cmd_AddCommand ("pointfile", pointfile_f, + "Load a pointfile to determine map leaks."); Cmd_AddCommand ("version", CL_Version_f, "Report version information"); Cmd_AddCommand ("changing", CL_Changing_f, "Used when maps are changing"); Cmd_AddCommand ("disconnect", CL_Disconnect_f, "Disconnect from server"); From 2cb987fdb5a938c51e253993a76695afd63c2259 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Dec 2021 00:40:47 +0900 Subject: [PATCH 2002/3664] [build] Clean up a pile of distcheck issues --- include/Makemodule.am | 4 ++++ include/QF/Makemodule.am | 10 +++++++--- libs/client/Makemodule.am | 5 +++++ libs/video/renderer/Makemodule.am | 9 +++++++++ ruamoko/qwaq/Makemodule.am | 11 +++++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/include/Makemodule.am b/include/Makemodule.am index 5c9db840e..d405b745c 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -40,6 +40,7 @@ EXTRA_DIST += \ include/gib_vars.h \ include/gl_warp_sin.h \ include/in_win.h \ + include/in_x11.h \ include/logos.h \ include/mod_internal.h \ include/net_dgrm.h \ @@ -54,6 +55,7 @@ EXTRA_DIST += \ include/ops.h \ include/pstdint.h \ include/qfalloca.h \ + include/qfselect.h \ include/qstring.h \ include/quakeasm.h \ include/quicksort.h \ @@ -81,8 +83,10 @@ EXTRA_DIST += \ include/world.h \ include/client/effects.h \ include/client/entities.h \ + include/client/input.h \ include/client/temp_entities.h \ include/client/locs.h \ + include/client/particles.h \ include/client/state.h \ include/client/view.h \ include/evdev/hotplug.h \ diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 939878f42..6089cb432 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -27,6 +27,7 @@ include_qf = \ include/QF/joystick.h \ include/QF/keys.h \ include/QF/link.h \ + include/QF/listener.h \ include/QF/llist.h \ include/QF/mathlib.h \ include/QF/mdfour.h \ @@ -112,9 +113,10 @@ include_qf_glsl = \ include/QF/GLSL/types.h include_qf_input = \ - include/QF/binding.h \ - include/QF/event.h - include/QF/imt.h + include/QF/input/binding.h \ + include/QF/input/event.h \ + include/QF/input/event_names.h \ + include/QF/input/imt.h include_qf_math = \ include/QF/math/dual.h \ @@ -175,8 +177,10 @@ include_qf_vulkan = \ include/QF/Vulkan/qf_lighting.h \ include/QF/Vulkan/qf_lightmap.h \ include/QF/Vulkan/qf_main.h \ + include/QF/Vulkan/qf_matrices.h \ include/QF/Vulkan/qf_model.h \ include/QF/Vulkan/qf_particles.h \ + include/QF/Vulkan/qf_sprite.h \ include/QF/Vulkan/qf_texture.h \ include/QF/Vulkan/qf_vid.h \ include/QF/Vulkan/renderpass.h \ diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 0d926b242..2cd5a80af 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -15,3 +15,8 @@ default_input_src = libs/client/default_input.plist default_input_gen = libs/client/default_input.plc libs/client/cl_input.lo: libs/client/cl_input.c $(default_input_gen) + +EXTRA_DIST += \ + libs/client/default_input.plist +CLEANFILES += \ + libs/client/*.plc diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index db58b894c..0a676497c 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -488,9 +488,18 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/compose.frag \ libs/video/renderer/vulkan/shader/lighting.frag \ libs/video/renderer/vulkan/shader/passthrough.vert \ + libs/video/renderer/vulkan/shader/partphysics.comp \ + libs/video/renderer/vulkan/shader/partupdate.comp \ + libs/video/renderer/vulkan/shader/particle.vert \ + libs/video/renderer/vulkan/shader/particle.geom \ + libs/video/renderer/vulkan/shader/particle.frag \ libs/video/renderer/vulkan/shader/pushcolor.frag \ libs/video/renderer/vulkan/shader/quakebsp.frag \ libs/video/renderer/vulkan/shader/quakebsp.vert \ libs/video/renderer/vulkan/shader/shadow.geom \ + libs/video/renderer/vulkan/shader/sprite_depth.vert \ + libs/video/renderer/vulkan/shader/sprite_depth.frag \ + libs/video/renderer/vulkan/shader/sprite_gbuf.vert \ + libs/video/renderer/vulkan/shader/sprite_gbuf.frag \ libs/video/renderer/vulkan/shader/twod.frag \ libs/video/renderer/vulkan/shader/twod.vert diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index d776820df..6cbf62829 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -166,6 +166,7 @@ EXTRA_DIST += \ ruamoko/qwaq/debugger/debugger.h \ ruamoko/qwaq/debugger/localsdata.h \ ruamoko/qwaq/debugger/typeencodings.h \ + ruamoko/qwaq/debugger/views/arrayview.h \ ruamoko/qwaq/debugger/views/basicview.h \ ruamoko/qwaq/debugger/views/defview.h \ ruamoko/qwaq/debugger/views/doubleview.h \ @@ -173,19 +174,28 @@ EXTRA_DIST += \ ruamoko/qwaq/debugger/views/fieldview.h \ ruamoko/qwaq/debugger/views/floatview.h \ ruamoko/qwaq/debugger/views/funcview.h \ + ruamoko/qwaq/debugger/views/indexview.h \ ruamoko/qwaq/debugger/views/intview.h \ ruamoko/qwaq/debugger/views/nameview.h \ ruamoko/qwaq/debugger/views/pointerview.h \ ruamoko/qwaq/debugger/views/quatview.h \ ruamoko/qwaq/debugger/views/stringview.h \ + ruamoko/qwaq/debugger/views/structview.h \ ruamoko/qwaq/debugger/views/uintview.h \ ruamoko/qwaq/debugger/views/vectorview.h \ ruamoko/qwaq/debugger/views/voidview.h \ + ruamoko/qwaq/device/axisdata.h \ + ruamoko/qwaq/device/axisview.h \ + ruamoko/qwaq/device/nameview.h \ + ruamoko/qwaq/device/device.h \ ruamoko/qwaq/editor/editbuffer.h \ ruamoko/qwaq/editor/editor.h \ ruamoko/qwaq/editor/status.h \ + ruamoko/qwaq/input-app.h \ ruamoko/qwaq/qwaq-app.h \ + ruamoko/qwaq/qwaq-input.h \ ruamoko/qwaq/qwaq.h \ + ruamoko/qwaq/threading.h \ ruamoko/qwaq/ui/button.h \ ruamoko/qwaq/ui/color.h \ ruamoko/qwaq/ui/curses.h \ @@ -197,6 +207,7 @@ EXTRA_DIST += \ ruamoko/qwaq/ui/proxyview.h \ ruamoko/qwaq/ui/rect.h \ ruamoko/qwaq/ui/scrollbar.h \ + ruamoko/qwaq/ui/stringview.h \ ruamoko/qwaq/ui/tableview.h \ ruamoko/qwaq/ui/textcontext.h \ ruamoko/qwaq/ui/titlebar.h \ From 8e08f5f84eacf17ce5e3dcdf16d8839fa12897fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Dec 2021 00:43:30 +0900 Subject: [PATCH 2003/3664] [qwaq] Drop qwaq-graphics.log For now, at least. The client console takes over Sys_Printf and breaks the logging. --- ruamoko/qwaq/builtins/qwaq-graphics.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/ruamoko/qwaq/builtins/qwaq-graphics.c b/ruamoko/qwaq/builtins/qwaq-graphics.c index bd2769cf6..d66ecc3cd 100644 --- a/ruamoko/qwaq/builtins/qwaq-graphics.c +++ b/ruamoko/qwaq/builtins/qwaq-graphics.c @@ -46,14 +46,6 @@ static progsinit_f secondary_app[] = { 0 }; #endif -static FILE *logfile; - -static __attribute__((format(PRINTF, 1, 0))) void -qwaq_print (const char *fmt, va_list args) -{ - vfprintf (logfile, fmt, args); - fflush (logfile); -} int qwaq_init_threads (qwaq_thread_set_t *thread_data) @@ -62,9 +54,6 @@ qwaq_init_threads (qwaq_thread_set_t *thread_data) size_t memsize = 8 * 1024 * 1024; memhunk_t *hunk = Memory_Init (Sys_Alloc (memsize), memsize); - logfile = fopen ("qwaq-graphics.log", "wt"); - Sys_SetStdPrintf (qwaq_print); - for (size_t i = 1, thread_ind = 0; i < thread_data->size; i++) { qwaq_thread_t *thread = thread_data->a[i]; progsinit_f *app_funcs = 0;//secondary_app; From 33e48025dd8b5b9d367186ab881d0ae0cf93f4c8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Dec 2021 00:47:13 +0900 Subject: [PATCH 2004/3664] [ruamoko] Replace rua_key with rua_input And create rua_game to coordinate other game builtins. Menus are broken for key handling, but have been since the input rewrite anyway. rua_input adds the ability to create buttons and axes (but not destroy them). More work needs to be done to flesh things out, though. --- config.d/build_control.m4 | 4 + include/QF/Makemodule.am | 8 +- include/QF/input.h | 1 + include/QF/input/binding.h | 9 +- include/QF/ruamoko.h | 5 +- include/rua_internal.h | 17 +-- libs/console/menu.c | 4 +- libs/input/in_common.c | 11 ++ libs/ruamoko/Makemodule.am | 3 +- libs/ruamoko/rua_game_init.c | 47 +++++++ libs/ruamoko/rua_input.c | 205 +++++++++++++++++++++++++++++++ ruamoko/qwaq/builtins/graphics.c | 3 +- 12 files changed, 296 insertions(+), 21 deletions(-) create mode 100644 libs/ruamoko/rua_game_init.c create mode 100644 libs/ruamoko/rua_input.c diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index ce6dfdda2..f55045a58 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -315,13 +315,16 @@ QF_PROCESS_NEED_LIST(ruamoko,[qwaq]) if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) qfac_qfcc_include_qf="\$(qfcc_include_qf)" + qfac_qfcc_include_qf_input="\$(qfcc_include_qf_input)" fi QF_SUBST(qfac_qfcc_include_qf) +QF_SUBST(qfac_qfcc_include_qf_input) if test x"${top_need_libs}" = xyes; then qfac_include_qf="\$(include_qf)" qfac_include_qf_gl="\$(include_qf_gl)" qfac_include_qf_glsl="\$(include_qf_glsl)" + qfac_include_qf_input="\$(include_qf_input)" qfac_include_qf_math="\$(include_qf_math)" qfac_include_qf_plugin="\$(include_qf_plugin)" qfac_include_qf_scene="\$(include_qf_scene)" @@ -332,6 +335,7 @@ fi QF_SUBST(qfac_include_qf) QF_SUBST(qfac_include_qf_gl) QF_SUBST(qfac_include_qf_glsl) +QF_SUBST(qfac_include_qf_input) QF_SUBST(qfac_include_qf_math) QF_SUBST(qfac_include_qf_plugin) QF_SUBST(qfac_include_qf_scene) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 6089cb432..4fadd6bfe 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -191,10 +191,12 @@ include_qf_vulkan = \ # headers shared with ruamoko qfcc_include_qf = include/QF/keys.h +qfcc_include_qf_input = include/QF/input/binding.h qf_includedir = $(includedir)/QF qf_gl_includedir = $(includedir)/QF/GL qf_glsl_includedir = $(includedir)/QF/GLSL +qf_input_includedir = $(includedir)/QF/input qf_math_includedir = $(includedir)/QF/math qf_plugin_includedir = $(includedir)/QF/plugin qf_scene_includedir = $(includedir)/QF/scene @@ -204,6 +206,7 @@ qf_vulkan_includedir = $(includedir)/QF/Vulkan qf_include_HEADERS = @qfac_include_qf@ qf_gl_include_HEADERS = @qfac_include_qf_gl@ qf_glsl_include_HEADERS = @qfac_include_qf_glsl@ +qf_input_include_HEADERS = @qfac_include_qf_input@ qf_math_include_HEADERS = @qfac_include_qf_math@ qf_plugin_include_HEADERS = @qfac_include_qf_plugin@ qf_scene_include_HEADERS = @qfac_include_qf_scene@ @@ -212,7 +215,9 @@ qf_ui_include_HEADERS = @qfac_include_qf_ui@ qf_vulkan_include_HEADERS = @qfac_include_qf_vulkan@ ruamoko_qf_includedir = $(ruamoko_includedir)/QF +ruamoko_qf_input_includedir = $(ruamoko_includedir)/QF/input ruamoko_qf_include_HEADERS = @qfac_qfcc_include_qf@ +ruamoko_qf_input_include_HEADERS = @qfac_qfcc_include_qf_input@ EXTRA_HEADERS += \ $(include_qf) \ @@ -225,4 +230,5 @@ EXTRA_HEADERS += \ $(include_qf_simd) \ $(include_qf_ui) \ $(include_qf_vulkan) \ - $(qfcc_include_qf) + $(qfcc_include_qf) \ + $(qfcc_include_qf_input) diff --git a/include/QF/input.h b/include/QF/input.h index 1c492efec..97eaa0a22 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -105,6 +105,7 @@ int IN_AddDevice (int driver, void *device, const char *name, const char *id); void IN_RemoveDevice (int devid); void IN_SendConnectedDevices (void); +int IN_FindDeviceId (const char *id) __attribute__((pure)); const char *IN_GetDeviceName (int devid) __attribute__((pure)); const char *IN_GetDeviceId (int devid) __attribute__((pure)); void IN_SetDeviceEventData (int devid, void *data); diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 9e70f3240..3570c42e4 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -30,9 +30,9 @@ #define __QF_input_binding_h #ifndef __QFCC__ - #include "QF/listener.h" #include "QF/mathlib.h" +#endif /*** Recipe for converting an axis to a floating point value. @@ -86,17 +86,21 @@ typedef struct in_axis_s { in_axis_mode mode; ///< method used for updating the destination float abs_input; ///< input from an absolute axis (eg, joystick) float rel_input; ///< input from a relative axis (eg, mouse) +#ifndef __QFCC__ struct axis_listener_set_s *listeners; const char *name; const char *description; +#endif } in_axis_t; +#ifndef __QFCC__ typedef struct axis_listener_set_s LISTENER_SET_TYPE (in_axis_t) axis_listener_set_t; /*** Function type for axis listeners. */ typedef void (*axis_listener_t) (void *data, const in_axis_t *axis); +#endif /*** Current state of the logical button. @@ -123,11 +127,14 @@ typedef enum { typedef struct in_button_s { int down[2]; ///< button ids holding this button down int state; ///< in_button_state +#ifndef __QFCC__ struct button_listener_set_s *listeners; const char *name; const char *description; +#endif } in_button_t; +#ifndef __QFCC__ typedef struct button_listener_set_s LISTENER_SET_TYPE (in_button_t) button_listener_set_t; diff --git a/include/QF/ruamoko.h b/include/QF/ruamoko.h index 956465268..ba1531485 100644 --- a/include/QF/ruamoko.h +++ b/include/QF/ruamoko.h @@ -38,7 +38,10 @@ struct cbuf_s; void RUA_Init (struct progs_s *pr, int secure); void RUA_Cbuf_SetCbuf (struct progs_s *pr, struct cbuf_s *cbuf); -func_t RUA_Obj_msg_lookup (struct progs_s *pr, pointer_t _self, pointer_t __cmd); +func_t RUA_Obj_msg_lookup (struct progs_s *pr, pointer_t _self, + pointer_t __cmd); + +void RUA_Game_Init (struct progs_s *pr, int secure); // self is expected in param 0 int RUA_obj_increment_retaincount (struct progs_s *pr); diff --git a/include/rua_internal.h b/include/rua_internal.h index c5aba3569..ea5079397 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -34,35 +34,24 @@ #include "QF/quakeio.h" void RUA_Cbuf_Init (struct progs_s *pr, int secure); - void RUA_Cmd_Init (struct progs_s *pr, int secure); - void RUA_Cvar_Init (struct progs_s *pr, int secure); - void RUA_Hash_Init (struct progs_s *pr, int secure); - void RUA_Math_Init (struct progs_s *pr, int secure); - void RUA_MsgBuf_Init (struct progs_s *pr, int secure); - void RUA_Obj_Init (struct progs_s *pr, int secure); - void RUA_Plist_Init (struct progs_s *pr, int secure); - void RUA_Runtime_Init (struct progs_s *pr, int secure); - void RUA_Script_Init (progs_t *pr, int secure); - void RUA_Set_Init (progs_t *pr, int secure); - void RUA_Stdlib_Init (struct progs_s *pr, int secure); - void RUA_String_Init (struct progs_s *pr, int secure); - void RUA_QFile_Init (struct progs_s *pr, int secure); +void RUA_QFS_Init (struct progs_s *pr, int secure); + int QFile_AllocHandle (struct progs_s *pr, QFile *file); QFile *QFile_GetFile (struct progs_s *pr, int handle); -void RUA_QFS_Init (struct progs_s *pr, int secure); +void RUA_Input_Init (struct progs_s *pr, int secure); #endif//__rua_internal_h diff --git a/libs/console/menu.c b/libs/console/menu.c index 1288b1bab..e6dcc72a4 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -597,10 +597,10 @@ Menu_Init (void) PR_RegisterBuiltins (&menu_pr_state, builtins); - RUA_Init (&menu_pr_state, 1); + RUA_Init (&menu_pr_state, 3); InputLine_Progs_Init (&menu_pr_state); - RUA_Key_Init (&menu_pr_state); + RUA_Game_Init (&menu_pr_state, 1); GIB_Progs_Init (&menu_pr_state); PR_Cmds_Init (&menu_pr_state); R_Progs_Init (&menu_pr_state); diff --git a/libs/input/in_common.c b/libs/input/in_common.c index f9d18a07c..6049b50aa 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -174,6 +174,17 @@ IN_SendConnectedDevices (void) } } +int +IN_FindDeviceId (const char *id) +{ + for (size_t i = 0; i < in_devices.size; i++) { + if (strcmp (id, in_devices.a[i].id) == 0) { + return i; + } + } + return -1; +} + const char * IN_GetDeviceName (int devid) { diff --git a/libs/ruamoko/Makemodule.am b/libs/ruamoko/Makemodule.am index 6274c75e7..cc45944b9 100644 --- a/libs/ruamoko/Makemodule.am +++ b/libs/ruamoko/Makemodule.am @@ -35,4 +35,5 @@ libs_ruamoko_libQFruamoko_client_la_DEPENDENCIES= \ libs/ruamoko/libQFruamoko.la \ $(ruamoko_rua_libs) libs_ruamoko_libQFruamoko_client_la_SOURCES= \ - libs/ruamoko/rua_keys.c + libs/ruamoko/rua_game_init.c \ + libs/ruamoko/rua_input.c diff --git a/libs/ruamoko/rua_game_init.c b/libs/ruamoko/rua_game_init.c new file mode 100644 index 000000000..ba2cb2565 --- /dev/null +++ b/libs/ruamoko/rua_game_init.c @@ -0,0 +1,47 @@ +/* + bi_game_init.c + + CSQC builtins init + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/progs.h" +#include "QF/ruamoko.h" + +#include "rua_internal.h" + +static void (*init_funcs[])(progs_t *, int) = { + RUA_Input_Init, +}; + +VISIBLE void +RUA_Game_Init (progs_t *pr, int secure) +{ + size_t i; + + for (i = 0; i < sizeof (init_funcs) / sizeof (init_funcs[0]); i++) + init_funcs[i] (pr, secure); +} diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c new file mode 100644 index 000000000..8d89948bf --- /dev/null +++ b/libs/ruamoko/rua_input.c @@ -0,0 +1,205 @@ +/* + bi_input.c + + CSQC file builtins + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/input.h" +#include "QF/progs.h" + +#include "rua_internal.h" + +//typedef struct input_resources_s { +//} input_resources_t; + +static void +bi_IN_FindDeviceId (progs_t *pr) +{ + const char *id = P_GSTRING (pr, 0); + + R_INT (pr) = IN_FindDeviceId (id); +} + +static void +bi_IN_GetDeviceName (progs_t *pr) +{ + int devid = P_INT (pr, 0); + + RETURN_STRING (pr, IN_GetDeviceName (devid)); +} + +static void +bi_IN_GetDeviceId (progs_t *pr) +{ + int devid = P_INT (pr, 0); + + RETURN_STRING (pr, IN_GetDeviceId (devid)); +} + +static void +bi_IN_AxisInfo (progs_t *pr) +{ +} + +static void +bi_IN_ButtonInfo (progs_t *pr) +{ +} + +static void +bi_IN_GetAxisName (progs_t *pr) +{ + int devid = P_INT (pr, 0); + int axis = P_INT (pr, 1); + + RETURN_STRING (pr, IN_GetAxisName (devid, axis)); +} + +static void +bi_IN_GetButtonName (progs_t *pr) +{ + int devid = P_INT (pr, 0); + int button = P_INT (pr, 1); + + RETURN_STRING (pr, IN_GetButtonName (devid, button)); +} + +static void +bi_IN_GetAxisNumber (progs_t *pr) +{ + int devid = P_INT (pr, 0); + const char *axis_name = P_GSTRING (pr, 1); + + R_INT (pr) = IN_GetAxisNumber (devid, axis_name); +} + +static void +bi_IN_GetButtonNumber (progs_t *pr) +{ + int devid = P_INT (pr, 0); + const char *button_name = P_GSTRING (pr, 1); + + R_INT (pr) = IN_GetButtonNumber (devid, button_name); +} + +static void +bi_IN_ProcessEvents (progs_t *pr) +{ + IN_ProcessEvents (); +} + +static void +bi_IN_ClearStates (progs_t *pr) +{ + IN_ClearStates (); +} + +static void +bi_IN_CreateButton (progs_t *pr) +{ + const char *name = P_GSTRING (pr, 0); + const char *desc = P_GSTRING (pr, 1); + in_button_t *button = PR_Zone_Malloc (pr, sizeof (in_button_t)); + button->name = name; + button->description = desc; + IN_RegisterButton (button); + RETURN_POINTER (pr, button); +} + +static void +bi_IN_CreateAxis (progs_t *pr) +{ + const char *name = P_GSTRING (pr, 0); + const char *desc = P_GSTRING (pr, 1); + in_axis_t *axis = PR_Zone_Malloc (pr, sizeof (in_axis_t)); + axis->name = name; + axis->description = desc; + IN_RegisterAxis (axis); + RETURN_POINTER (pr, axis); +} + +static void +secured (progs_t *pr) +{ + PR_RunError (pr, "Secured function called"); +} + +#define bi(x) {#x, secured, -1} +static builtin_t secure_builtins[] = { + bi(IN_CreateButton), + bi(IN_CreateAxis), + {0} +}; + +#undef bi +#define bi(x) {#x, bi_##x, -1} +static builtin_t insecure_builtins[] = { + bi(IN_CreateButton), + bi(IN_CreateAxis), + {0} +}; +static builtin_t builtins[] = { + bi(IN_FindDeviceId), + bi(IN_GetDeviceName), + bi(IN_GetDeviceId), + bi(IN_AxisInfo), + bi(IN_ButtonInfo), + bi(IN_GetAxisName), + bi(IN_GetButtonName), + bi(IN_GetAxisNumber), + bi(IN_GetButtonNumber), + bi(IN_ProcessEvents), + bi(IN_ClearStates), + {0} +}; + +//static void +//bi_input_clear (progs_t *pr, void *_res) +//{ +//} + +void +RUA_Input_Init (progs_t *pr, int secure) +{ + //input_resources_t *res = calloc (sizeof (input_resources_t), 1); + //PR_Resources_Register (pr, "input", res, bi_input_clear); + + if (secure & 2) { + PR_RegisterBuiltins (pr, secure_builtins); + } else { + PR_RegisterBuiltins (pr, insecure_builtins); + } + PR_RegisterBuiltins (pr, builtins); +} diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 8966668cd..b7d4f7351 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -51,6 +51,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/progs.h" #include "QF/quakefs.h" #include "QF/render.h" +#include "QF/ruamoko.h" #include "QF/screen.h" #include "QF/sound.h" #include "QF/sys.h" @@ -165,7 +166,7 @@ BI_Graphics_Init (progs_t *pr) Mod_Init (); R_Init (); R_Progs_Init (pr); - RUA_Key_Init (pr); + RUA_Game_Init (pr, thread->rua_security); S_Progs_Init (pr); Con_Init ("client"); From 803c9defae0db04ccc1081d02aa41e2d65aee92e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Dec 2021 17:40:42 +0900 Subject: [PATCH 2005/3664] [input] Clean out more keys.h refs --- include/QF/Makemodule.am | 6 ++++-- include/QF/input.h | 2 -- libs/gib/gib_keys.c | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 4fadd6bfe..ff47836db 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -190,8 +190,10 @@ include_qf_vulkan = \ include/QF/Vulkan/swapchain.h # headers shared with ruamoko -qfcc_include_qf = include/QF/keys.h -qfcc_include_qf_input = include/QF/input/binding.h +qfcc_include_qf = include/QF/input.h +qfcc_include_qf_input = \ + include/QF/input/binding.h \ + include/QF/input/imt.h qf_includedir = $(includedir)/QF qf_gl_includedir = $(includedir)/QF/GL diff --git a/include/QF/input.h b/include/QF/input.h index 97eaa0a22..671a3474d 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -28,8 +28,6 @@ #ifndef __QF_input_h #define __QF_input_h -#include "QF/keys.h" - typedef struct in_axisinfo_s { int deviceid; int axis; diff --git a/libs/gib/gib_keys.c b/libs/gib/gib_keys.c index a45428acd..ae5aea823 100644 --- a/libs/gib/gib_keys.c +++ b/libs/gib/gib_keys.c @@ -40,6 +40,7 @@ #include "QF/input.h" #include "QF/sys.h" #include "QF/gib.h" +#include "QF/keys.h" #include "compat.h" #include "old_keys.h" From 3cb93d4cbe604a0c4dc197acfe1e08fda63d932b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Dec 2021 17:42:38 +0900 Subject: [PATCH 2006/3664] [input] Add functions to get single axis/button info Handy for retrieving the current state (raw) of a single axis or button. --- include/QF/input.h | 7 +++++++ libs/input/in_common.c | 38 +++++++++++++++++++++++++++++++++++++ libs/input/in_evdev.c | 33 +++++++++++++++++++++++++++++++- libs/video/targets/in_x11.c | 28 +++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) diff --git a/include/QF/input.h b/include/QF/input.h index 671a3474d..d467017b4 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -77,6 +77,11 @@ typedef struct in_driver_s { // -1 for invalid name int (*get_axis_num) (void *data, void *device, const char *axis_name); int (*get_button_num) (void *data, void *device, const char *button_name); + // null means invalid number + int (*get_axis_info) (void *data, void *device, int axis_num, + in_axisinfo_t *info); + int (*get_button_info) (void *data, void *device, int button_num, + in_buttoninfo_t *info); } in_driver_t; typedef struct in_device_s { @@ -114,6 +119,8 @@ const char *IN_GetAxisName (int devid, int axis_num); const char *IN_GetButtonName (int devid, int button_num); int IN_GetAxisNumber (int devid, const char *axis_name); int IN_GetButtonNumber (int devid, const char *button_name); +int IN_GetAxisInfo (int devid, int axis_num, in_axisinfo_t *info); +int IN_GetButtonInfo (int devid, int button_num, in_buttoninfo_t *info); void IN_ProcessEvents (void); diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 6049b50aa..ad69ee3a4 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -356,6 +356,44 @@ IN_GetButtonNumber (int devid, const char *button_name) button_name); } +int +IN_GetAxisInfo (int devid, int axis_num, in_axisinfo_t *info) +{ + if ((size_t) devid >= in_devices.size) { + return 0; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return 0; + } + int driver = in_devices.a[devid].driverid; + in_regdriver_t *rd = &in_drivers.a[driver]; + if (rd->driver.get_axis_info (rd->data, in_devices.a[devid].device, + axis_num, info)) { + info->deviceid = devid; + return 1; + } + return 0; +} + +int +IN_GetButtonInfo (int devid, int button_num, in_buttoninfo_t *info) +{ + if ((size_t) devid >= in_devices.size) { + return 0; + } + if (!in_devices.a[devid].device || in_devices.a[devid].driverid == -1) { + return 0; + } + int driver = in_devices.a[devid].driverid; + in_regdriver_t *rd = &in_drivers.a[driver]; + if (rd->driver.get_button_info (rd->data, in_devices.a[devid].device, + button_num, info)) { + info->deviceid = devid; + return 1; + } + return 0; +} + void IN_UpdateGrab (cvar_t *var) // called from context_*.c { diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 6666cedd7..73f6cfe77 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -232,7 +232,7 @@ in_evdev_axis_info (void *data, void *device, in_axisinfo_t *axes, static void in_evdev_button_info (void *data, void *device, in_buttoninfo_t *buttons, - int *numbuttons) + int *numbuttons) { device_t *dev = device; if (!buttons) { @@ -248,6 +248,34 @@ in_evdev_button_info (void *data, void *device, in_buttoninfo_t *buttons, } } +static int +in_evdev_get_axis_info (void *data, void *device, int axis_num, + in_axisinfo_t *info) +{ + device_t *dev = device; + if (axis_num < 0 || axis_num > dev->num_axes) { + return 0; + } + info->axis = dev->axes[axis_num].num; + info->value = dev->axes[axis_num].value; + info->min = dev->axes[axis_num].min; + info->max = dev->axes[axis_num].max; + return 1; +} + +static int +in_evdev_get_button_info (void *data, void *device, int button_num, + in_buttoninfo_t *info) +{ + device_t *dev = device; + if (button_num < 0 || button_num > dev->num_buttons) { + return 0; + } + info->button = dev->buttons[button_num].num; + info->state = dev->buttons[button_num].state; + return 1; +} + static in_driver_t in_evdev_driver = { .init = in_evdev_init, .shutdown = in_evdev_shutdown, @@ -259,6 +287,9 @@ static in_driver_t in_evdev_driver = { .axis_info = in_evdev_axis_info, .button_info = in_evdev_button_info, + + .get_axis_info = in_evdev_get_axis_info, + .get_button_info = in_evdev_get_button_info, }; static int diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 51acca70e..3f7685fb1 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -1260,6 +1260,30 @@ in_x11_get_button_name (void *data, void *device, int button_num) return name; } +static int +in_x11_get_axis_info (void *data, void *device, int axis_num, + in_axisinfo_t *info) +{ + x11_device_t *dev = device; + if (axis_num < 0 || axis_num > dev->num_axes) { + return 0; + } + *info = dev->axes[axis_num]; + return 1; +} + +static int +in_x11_get_button_info (void *data, void *device, int button_num, + in_buttoninfo_t *info) +{ + x11_device_t *dev = device; + if (button_num < 0 || button_num > dev->num_buttons) { + return 0; + } + *info = dev->buttons[button_num]; + return 1; +} + static int in_x11_get_axis_num (void *data, void *device, const char *axis_name) { @@ -1568,8 +1592,12 @@ static in_driver_t in_x11_driver = { .get_axis_name = in_x11_get_axis_name, .get_button_name = in_x11_get_button_name, + .get_axis_num = in_x11_get_axis_num, .get_button_num = in_x11_get_button_num, + + .get_axis_info = in_x11_get_axis_info, + .get_button_info = in_x11_get_button_info, }; static void __attribute__((constructor)) From 9571fb83ee4190788247dbf84b4ea35d9f23d540 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Dec 2021 17:44:27 +0900 Subject: [PATCH 2007/3664] [input] Move freelook macro deffiniton It belongs quite solidly in the client code since it's the client that's defining the concept. --- include/QF/input.h | 2 -- include/client/input.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index d467017b4..ade3b97d0 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -92,8 +92,6 @@ typedef struct in_device_s { void *event_data; } in_device_t; -#define freelook (in_mlook.state & 1 || in_freelook->int_val) - struct cvar_s; int IN_RegisterDriver (in_driver_t *driver, void *data); diff --git a/include/client/input.h b/include/client/input.h index fad8a5092..89dc9cbc6 100644 --- a/include/client/input.h +++ b/include/client/input.h @@ -29,4 +29,6 @@ void CL_Legacy_Init (void); +#define freelook (in_mlook.state & 1 || in_freelook->int_val) + #endif // __client_input_h_ From 64115186036eac93d145a20bce13b3db3231d06c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Dec 2021 17:45:48 +0900 Subject: [PATCH 2008/3664] [ruamoko] Make some progress on the input bindings --- libs/ruamoko/rua_input.c | 269 +++++++++++++++++++++++++++++++++- ruamoko/include/Makemodule.am | 5 +- ruamoko/include/input.h | 39 +++++ ruamoko/lib/Makemodule.am | 6 +- ruamoko/lib/input.r | 37 +++++ 5 files changed, 346 insertions(+), 10 deletions(-) create mode 100644 ruamoko/include/input.h create mode 100644 ruamoko/lib/input.r diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 8d89948bf..e53f6b0db 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -36,13 +36,25 @@ # include #endif +#include "QF/cmem.h" +#include "QF/hash.h" #include "QF/input.h" #include "QF/progs.h" #include "rua_internal.h" -//typedef struct input_resources_s { -//} input_resources_t; +typedef struct rua_in_cookie_s { + size_t users; + progs_t *pr; + func_t func; + pointer_t data; +} rua_in_cookie_t; + +typedef struct input_resources_s { + hashlink_t *hash_links; + hashtab_t *cookies; + memsuper_t *cookie_super; +} input_resources_t; static void bi_IN_FindDeviceId (progs_t *pr) @@ -150,6 +162,199 @@ bi_IN_CreateAxis (progs_t *pr) RETURN_POINTER (pr, axis); } +static void +bi_IN_GetAxisInfo (progs_t *pr) +{ + int devid = P_INT (pr, 0); + int axis = P_INT (pr, 1); + + R_INT (pr) = 0; + + in_axisinfo_t info; + if (IN_GetAxisInfo (devid, axis, &info)) { + P_STRUCT (pr, in_axisinfo_t, 2) = info; + R_INT (pr) = 1; + } +} + +static void +bi_IN_GetButtonInfo (progs_t *pr) +{ + int devid = P_INT (pr, 0); + int button = P_INT (pr, 1); + + R_INT (pr) = 0; + + in_buttoninfo_t info; + if (IN_GetButtonInfo (devid, button, &info)) { + P_STRUCT (pr, in_buttoninfo_t, 2) = info; + R_INT (pr) = 1; + } +} + +static void +rua_add_axis_listener (progs_t *pr, axis_listener_t listener) +{ + input_resources_t *res = PR_Resources_Find (pr, "input"); + in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); + rua_in_cookie_t search = { + .func = P_FUNCTION (pr, 1), + .data = P_POINTER (pr, 2), + }; + rua_in_cookie_t *cookie = Hash_FindElement (res->cookies, &search); + if (cookie) { + cookie = cmemalloc (res->cookie_super, sizeof (rua_in_cookie_t)); + *cookie = search; + } + cookie->users++; + IN_AxisAddListener (axis, listener, cookie); +} + +static void +rua_remove_axis_listener (progs_t *pr, axis_listener_t listener) +{ + input_resources_t *res = PR_Resources_Find (pr, "input"); + in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); + rua_in_cookie_t search = { + .func = P_FUNCTION (pr, 1), + .data = P_POINTER (pr, 2), + }; + rua_in_cookie_t *cookie = Hash_FindElement (res->cookies, &search); + if (cookie) { + IN_AxisRemoveListener (axis, listener, cookie); + } +} + +static void +rua_add_button_listener (progs_t *pr, button_listener_t listener) +{ + input_resources_t *res = PR_Resources_Find (pr, "input"); + in_button_t *button = &P_STRUCT (pr, in_button_t, 0); + rua_in_cookie_t search = { + .func = P_FUNCTION (pr, 1), + .data = P_POINTER (pr, 2), + }; + rua_in_cookie_t *cookie = Hash_FindElement (res->cookies, &search); + if (cookie) { + cookie = cmemalloc (res->cookie_super, sizeof (rua_in_cookie_t)); + *cookie = search; + } + cookie->users++; + IN_ButtonAddListener (button, listener, cookie); +} + +static void +rua_remove_button_listener (progs_t *pr, button_listener_t listener) +{ + input_resources_t *res = PR_Resources_Find (pr, "input"); + in_button_t *button = &P_STRUCT (pr, in_button_t, 0); + rua_in_cookie_t search = { + .func = P_FUNCTION (pr, 1), + .data = P_POINTER (pr, 2), + }; + rua_in_cookie_t *cookie = Hash_FindElement (res->cookies, &search); + if (cookie) { + IN_ButtonRemoveListener (button, listener, cookie); + } +} + +static void +rua_listener_func (rua_in_cookie_t *cookie, const void *input) +{ + progs_t *pr = cookie->pr; + PR_PushFrame (pr); + P_POINTER (pr, 0) = cookie->data; + P_POINTER (pr, 1) = PR_SetPointer (pr, input);//FIXME check input + pr->pr_argc = 2; + PR_ExecuteProgram (pr, cookie->func); + PR_PopFrame (pr); +} + +static void +rua_listener_method (rua_in_cookie_t *cookie, const void *input) +{ + progs_t *pr = cookie->pr; + PR_PushFrame (pr); + P_POINTER (pr, 0) = cookie->data; + P_POINTER (pr, 1) = 0; // don't know the method name (selector) + P_POINTER (pr, 2) = PR_SetPointer (pr, input);//FIXME check input + pr->pr_argc = 3; + PR_ExecuteProgram (pr, cookie->func); + PR_PopFrame (pr); +} + +static void +rua_axis_listener_func (void *data, const in_axis_t *axis) +{ + rua_listener_func (data, axis); +} + +static void +rua_axis_listener_method (void *data, const in_axis_t *axis) +{ + rua_listener_method (data, axis); +} + +static void +rua_button_listener_func (void *data, const in_button_t *button) +{ + rua_listener_func (data, button); +} + +static void +rua_button_listener_method (void *data, const in_button_t *button) +{ + rua_listener_method (data, button); +} + +static void +rua_IN_ButtonAddListener_func (progs_t *pr) +{ + rua_add_button_listener (pr, rua_button_listener_func); +} + +static void +rua_IN_ButtonRemoveListener_func (progs_t *pr) +{ + rua_remove_button_listener (pr, rua_button_listener_func); +} + +static void +rua_IN_AxisAddListener_func (progs_t *pr) +{ + rua_add_axis_listener (pr, rua_axis_listener_func); +} + +static void +rua_IN_AxisRemoveListener_func (progs_t *pr) +{ + rua_remove_axis_listener (pr, rua_axis_listener_func); +} + +static void +rua_IN_ButtonAddListener_method (progs_t *pr) +{ + rua_add_button_listener (pr, rua_button_listener_method); +} + +static void +rua_IN_ButtonRemoveListener_method (progs_t *pr) +{ + rua_remove_button_listener (pr, rua_button_listener_method); +} + +static void +rua_IN_AxisAddListener_method (progs_t *pr) +{ + rua_add_axis_listener (pr, rua_axis_listener_method); +} + +static void +rua_IN_AxisRemoveListener_method (progs_t *pr) +{ + rua_remove_axis_listener (pr, rua_axis_listener_method); +} + static void secured (progs_t *pr) { @@ -182,19 +387,67 @@ static builtin_t builtins[] = { bi(IN_GetButtonNumber), bi(IN_ProcessEvents), bi(IN_ClearStates), + bi(IN_GetAxisInfo), + bi(IN_GetButtonInfo), + {"IN_ButtonAddListener|^{tag in_button_s=}^(v^v^{tag in_button_s=})^v", + rua_IN_ButtonAddListener_func, -1}, + {"IN_ButtonRemoveListener|^{tag in_button_s=}^(v^v^{tag in_button_s=})^v", + rua_IN_ButtonRemoveListener_func, -1}, + {"IN_AxisAddListener|^{tag in_axis_s=}^(v^v^{tag in_axis_s=})^v", + rua_IN_AxisAddListener_func, -1}, + {"IN_AxisRemoveListener|^{tag in_axis_s=}^(v^v^{tag in_axis_s=})^v", + rua_IN_AxisRemoveListener_func, -1}, + {"IN_ButtonAddListener|^{tag in_button_s=}(@@:.)@", + rua_IN_ButtonAddListener_method, -1}, + {"IN_ButtonRemoveListener|^{tag in_button_s=}(@@:.)@", + rua_IN_ButtonRemoveListener_method, -1}, + {"IN_AxisAddListener|^{tag in_axis_s=}(@@:.)@", + rua_IN_AxisAddListener_method, -1}, + {"IN_AxisRemoveListener|^{tag in_axis_s=}(@@:.)@", + rua_IN_AxisRemoveListener_method, -1}, {0} }; -//static void -//bi_input_clear (progs_t *pr, void *_res) -//{ -//} +static void +bi_input_clear (progs_t *pr, void *_res) +{ + input_resources_t *res = _res; + Hash_FlushTable (res->cookies); +} + +static uintptr_t +rua_in_hash_cookie (const void *_cookie, void *_res) +{ + const rua_in_cookie_t *cookie = _cookie; + return cookie->func + cookie->data; +} + +static int +rua_in_cmp_cookies (const void *_a, const void *_b, void *_res) +{ + const rua_in_cookie_t *a = _a; + const rua_in_cookie_t *b = _b; + return a->func == b->func && a->data == b->data; +} + +static void +rua_in_free_cookie (void *_cookie, void *_res) +{ + input_resources_t *res = _res; + rua_in_cookie_t *cookie = _cookie; + cmemfree (res->cookie_super, cookie); +} void RUA_Input_Init (progs_t *pr, int secure) { - //input_resources_t *res = calloc (sizeof (input_resources_t), 1); - //PR_Resources_Register (pr, "input", res, bi_input_clear); + input_resources_t *res = calloc (sizeof (input_resources_t), 1); + PR_Resources_Register (pr, "input", res, bi_input_clear); + + res->cookie_super = new_memsuper (); + res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, + &res->hash_links); + Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies); if (secure & 2) { PR_RegisterBuiltins (pr, secure_builtins); diff --git a/ruamoko/include/Makemodule.am b/ruamoko/include/Makemodule.am index 8324491d3..2920ed408 100644 --- a/ruamoko/include/Makemodule.am +++ b/ruamoko/include/Makemodule.am @@ -3,6 +3,7 @@ ruamoko_include = \ ruamoko/include/debug.h \ ruamoko/include/entities.h \ ruamoko/include/infokey.h \ + ruamoko/include/input.h \ ruamoko/include/math.h \ ruamoko/include/message.h \ ruamoko/include/nq_message.h \ @@ -23,7 +24,6 @@ ruamoko_include = \ ruamoko/include/types.h \ ruamoko/include/legacy_string.h \ ruamoko/include/draw.h \ - ruamoko/include/key.h \ ruamoko/include/cbuf.h \ ruamoko/include/cmd.h \ ruamoko/include/cvar.h \ @@ -55,3 +55,6 @@ ruamoko_gui_includedir = $(datarootdir)/qfcc/include/gui ruamoko_include_HEADERS = $(ruamoko_include) ruamoko_gui_include_HEADERS = $(ruamoko_gui_include) + +EXTRA_DIST += \ + ruamoko/include/key.h diff --git a/ruamoko/include/input.h b/ruamoko/include/input.h new file mode 100644 index 000000000..ebbb970d6 --- /dev/null +++ b/ruamoko/include/input.h @@ -0,0 +1,39 @@ +#ifndef __ruamoko_input_h +#define __ruamoko_input_h + +#include + +in_button_t *IN_CreateButton (string name, string description); +in_axis_t *IN_CreateAxis (string name, string description); +int IN_FindDeviceId (string _id); +string IN_GetDeviceName (int devid); +string IN_GetDeviceId (int devid); +//IN_AxisInfo (); +//IN_ButtonInfo (); +string IN_GetAxisName (int devid, int axis); +string IN_GetButtonName (int devid, int axis); +int IN_GetAxisNumber (int devid, string axis); +int IN_GetButtonNumber (int devid, string axis); +void IN_ProcessEvents (void); +void IN_ClearStates (void); +int IN_GetAxisInfo (int devid, int axis, in_axisinfo_t *info); +int IN_GetButtonInfo (int devid, int button, in_buttoninfo_t *info); +typedef void (*button_listener_t) (void *data, in_button_t *button);//FIXME const +@overload void IN_ButtonAddListener (in_button_t *button, + button_listener_t listener, void *data); +@overload void IN_ButtonRemoveListener (in_button_t *button, + button_listener_t listener, + void *data); +typedef void (*axis_listener_t) (void *data, in_axis_t *axis);//FIXME const +@overload void IN_AxisAddListener (in_axis_t *axis, axis_listener_t listener, + void *data); +@overload void IN_AxisRemoveListener (in_axis_t *axis, + axis_listener_t listener, void *data); +@overload void IN_ButtonAddListener (in_button_t *button, IMP listener, + id obj); +@overload void IN_ButtonRemoveListener (in_button_t *button, IMP listener, + id obj); +@overload void IN_AxisAddListener (in_axis_t *axis, IMP listener, id obj); +@overload void IN_AxisRemoveListener (in_axis_t *axis, IMP listener, id obj); + +#endif//__ruamoko_input_h diff --git a/ruamoko/lib/Makemodule.am b/ruamoko/lib/Makemodule.am index 5711a0b24..e5218d298 100644 --- a/ruamoko/lib/Makemodule.am +++ b/ruamoko/lib/Makemodule.am @@ -45,7 +45,11 @@ ruamoko_lib_libqw_a_src= \ ruamoko/lib/qw_message.r ruamoko/lib/qw_physics.r ruamoko/lib/qw_sys.r ruamoko_lib_libnq_a_src= \ ruamoko/lib/nq_message.r -ruamoko_lib_libcsqc_a_src= ruamoko/lib/draw.r ruamoko/lib/gib.r ruamoko/lib/key.r +ruamoko_lib_libcsqc_a_src= \ + ruamoko/lib/draw.r \ + ruamoko/lib/gib.r \ + ruamoko/lib/input.r \ + ruamoko/lib/key.r ruamoko_lib_common_dep=$(call qcautodep,$(ruamoko_lib_common_src)) include $(ruamoko_lib_common_dep) # am--include-marker diff --git a/ruamoko/lib/input.r b/ruamoko/lib/input.r new file mode 100644 index 000000000..74ee30e89 --- /dev/null +++ b/ruamoko/lib/input.r @@ -0,0 +1,37 @@ +#include "input.h" + +in_button_t *IN_CreateButton (string name, string description) = #0; +in_axis_t *IN_CreateAxis (string name, string description) = #0; +int IN_FindDeviceId (string _id) = #0; +string IN_GetDeviceName (int devid) = #0; +string IN_GetDeviceId (int devid) = #0; +//IN_AxisInfo () = #0; +//IN_ButtonInfo () = #0; +string IN_GetAxisName (int devid, int axis) = #0; +string IN_GetButtonName (int devid, int axis) = #0; +int IN_GetAxisNumber (int devid, string axis) = #0; +int IN_GetButtonNumber (int devid, string axis) = #0; +void IN_ProcessEvents (void) = #0; +void IN_ClearStates (void) = #0; +int IN_GetAxisInfo (int devid, int axis, in_axisinfo_t *info) = #0; +int IN_GetButtonInfo (int devid, int button, in_buttoninfo_t *info) = #0; +@overload +void IN_ButtonAddListener (in_button_t *button, button_listener_t listener, + void *data) = #0; +@overload +void IN_ButtonRemoveListener (in_button_t *button, button_listener_t listener, + void *data) = #0; +@overload +void IN_AxisAddListener (in_axis_t *axis, axis_listener_t listener, + void *data) = #0; +@overload +void IN_AxisRemoveListener (in_axis_t *axis, axis_listener_t listener, + void *data) = #0; +@overload +void IN_ButtonAddListener (in_button_t *button, IMP listener, id obj) = #0; +@overload +void IN_ButtonRemoveListener (in_button_t *button, IMP listener, id obj) = #0; +@overload +void IN_AxisAddListener (in_axis_t *axis, IMP listener, id obj) = #0; +@overload +void IN_AxisRemoveListener (in_axis_t *axis, IMP listener, id obj) = #0; From 91a686d1f5fac8b0992eba17db94d3c8f76cdc65 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 00:01:26 +0900 Subject: [PATCH 2009/3664] [util] Add mtwist float random number functions mtwist_rand_0_1 produces numbers in the range [0, 1) and mtwist_rand_m1_1 produces numbers in the range (-1, 1). The numbers will not be denormal, so the distribution should be fairly uniform (as much as Mersenne Twister itself is), but this needs proper testing. 0 is included for the mtwist_rand_0_1 as it seems useful, but -1 is not included in mtwist_rand_m1_1 in order to keep the extremes of the distribution balanced around 0. --- include/QF/mersenne.h | 40 ++++++++++++++++++++++++++++++++++++++++ libs/util/mersenne.c | 1 + 2 files changed, 41 insertions(+) diff --git a/include/QF/mersenne.h b/include/QF/mersenne.h index 197ded28d..d80b53e43 100644 --- a/include/QF/mersenne.h +++ b/include/QF/mersenne.h @@ -42,5 +42,45 @@ typedef struct { void mtwist_seed (mtstate_t *state, uint32_t seed); uint32_t mtwist_rand (mtstate_t *state); +GNU89INLINE inline float mtwist_rand_0_1 (mtstate_t *state); +GNU89INLINE inline float mtwist_rand_m1_1 (mtstate_t *state); + +#ifndef IMPLEMENT_MTWIST_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +float +mtwist_rand_0_1 (mtstate_t *state) +{ + union { + uint32_t u; + float f; + } uf; + + uf.u = mtwist_rand (state) & 0x007fffff; + uf.u |= 0x3f800000; + return uf.f - 1.0; +} + +#ifndef IMPLEMENT_MTWIST_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +float +mtwist_rand_m1_1 (mtstate_t *state) +{ + union { + uint32_t u; + float f; + } uf; + + do { + uf.u = mtwist_rand (state) & 0x007fffff; + } while (!uf.u); + uf.u |= 0x40000000; + return uf.f - 3.0; +} #endif//__QF_mersenne_h diff --git a/libs/util/mersenne.c b/libs/util/mersenne.c index 35794932b..5c0cbacbc 100644 --- a/libs/util/mersenne.c +++ b/libs/util/mersenne.c @@ -48,6 +48,7 @@ There were no differences. */ +#define IMPLEMENT_MTWIST_Funcs #include "QF/mersenne.h" #define KNUTH_MULT 1812433253ul // 0x6c078965 From f1d097c0c4699c977956c7ae059dd10477fe2537 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 00:18:25 +0900 Subject: [PATCH 2010/3664] [ruamoko] Add bindings for Mercenne Twister --- include/rua_internal.h | 1 + libs/ruamoko/Makemodule.am | 3 +- libs/ruamoko/rua_game_init.c | 1 + libs/ruamoko/rua_mersenne.c | 166 ++++++++++++++++++++++++++++++++++ ruamoko/include/Makemodule.am | 1 + ruamoko/include/mersenne.h | 15 +++ ruamoko/lib/Makemodule.am | 1 + ruamoko/lib/mersenne.r | 8 ++ 8 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 libs/ruamoko/rua_mersenne.c create mode 100644 ruamoko/include/mersenne.h create mode 100644 ruamoko/lib/mersenne.r diff --git a/include/rua_internal.h b/include/rua_internal.h index ea5079397..d2119157a 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -53,5 +53,6 @@ int QFile_AllocHandle (struct progs_s *pr, QFile *file); QFile *QFile_GetFile (struct progs_s *pr, int handle); void RUA_Input_Init (struct progs_s *pr, int secure); +void RUA_Mersenne_Init (struct progs_s *pr, int secure); #endif//__rua_internal_h diff --git a/libs/ruamoko/Makemodule.am b/libs/ruamoko/Makemodule.am index cc45944b9..08749dfef 100644 --- a/libs/ruamoko/Makemodule.am +++ b/libs/ruamoko/Makemodule.am @@ -36,4 +36,5 @@ libs_ruamoko_libQFruamoko_client_la_DEPENDENCIES= \ $(ruamoko_rua_libs) libs_ruamoko_libQFruamoko_client_la_SOURCES= \ libs/ruamoko/rua_game_init.c \ - libs/ruamoko/rua_input.c + libs/ruamoko/rua_input.c \ + libs/ruamoko/rua_mersenne.c diff --git a/libs/ruamoko/rua_game_init.c b/libs/ruamoko/rua_game_init.c index ba2cb2565..d0b239ddd 100644 --- a/libs/ruamoko/rua_game_init.c +++ b/libs/ruamoko/rua_game_init.c @@ -35,6 +35,7 @@ static void (*init_funcs[])(progs_t *, int) = { RUA_Input_Init, + RUA_Mersenne_Init, }; VISIBLE void diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c new file mode 100644 index 000000000..6c503914f --- /dev/null +++ b/libs/ruamoko/rua_mersenne.c @@ -0,0 +1,166 @@ +/* + bi_mersenne.c + + Ruamoko Mersenne Twister api + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/12/21 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/mersenne.h" +#include "QF/progs.h" + +#include "rua_internal.h" + +typedef struct { + //FIXME each mtstate_t is 2500 bytes and the map has 1024 elements + //per row, so having only one mtstate_t has an overhead of about 2.5MB + PR_RESMAP (mtstate_t) state_map; +} mtwist_resources_t; + +static mtstate_t * +state_new (mtwist_resources_t *res) +{ + return PR_RESNEW (res->state_map); +} + +static void +state_free (mtwist_resources_t *res, mtstate_t *state) +{ + PR_RESFREE (res->state_map, state); +} + +static void +state_reset (mtwist_resources_t *res) +{ + PR_RESRESET (res->state_map); +} + +static inline mtstate_t * +state_get (mtwist_resources_t *res, int index) +{ + return PR_RESGET(res->state_map, index); +} + +static inline int __attribute__((pure)) +state_index (mtwist_resources_t *res, mtstate_t *state) +{ + return PR_RESINDEX(res->state_map, state); +} + +static void +bi_mtwist_new (progs_t *pr) +{ + mtwist_resources_t *res = PR_Resources_Find (pr, "Mersenne Twister"); + + mtstate_t *mt = state_new (res); + mtwist_seed (mt, P_INT (pr, 0)); + R_INT (pr) = state_index (res, mt); +} + +static mtstate_t * +get_state (progs_t *pr, const char *name, int index) +{ + mtwist_resources_t *res = PR_Resources_Find (pr, "Mersenne Twister"); + mtstate_t *mt = state_get (res, index); + + if (!mt) + PR_RunError (pr, "invalid Mersenne Twister state index passed to %s", + name + 3); + return mt; +} + +static void +bi_mtwist_delete (progs_t *pr) +{ + mtwist_resources_t *res = PR_Resources_Find (pr, "Mersenne Twister"); + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + state_free (res, mt); +} + +static void +bi_mtwist_seed (progs_t *pr) +{ + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + mtwist_seed (mt, P_INT (pr, 1)); +} + +static void +bi_mtwist_rand (progs_t *pr) +{ + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + R_INT (pr) = mtwist_rand (mt); +} + +static void +bi_mtwist_rand_0_1 (progs_t *pr) +{ + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + R_FLOAT (pr) = mtwist_rand_0_1 (mt); +} + +static void +bi_mtwist_rand_m1_1 (progs_t *pr) +{ + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + R_FLOAT (pr) = mtwist_rand_m1_1 (mt); +} + +static void +bi_mtwist_clear (progs_t *pr, void *data) +{ + mtwist_resources_t *res = (mtwist_resources_t *) data; + state_reset (res); +} + +#define bi(x) {#x, bi_##x, -1} +static builtin_t builtins[] = { + bi(mtwist_new), + bi(mtwist_delete), + bi(mtwist_seed), + bi(mtwist_rand), + bi(mtwist_rand_0_1), + bi(mtwist_rand_m1_1), + {0} +}; + +void +RUA_Mersenne_Init (progs_t *pr, int secure) +{ + mtwist_resources_t *res = calloc (1, sizeof (mtwist_resources_t)); + + PR_Resources_Register (pr, "Mersenne Twister", res, bi_mtwist_clear); + PR_RegisterBuiltins (pr, builtins); +} diff --git a/ruamoko/include/Makemodule.am b/ruamoko/include/Makemodule.am index 2920ed408..800c8ba89 100644 --- a/ruamoko/include/Makemodule.am +++ b/ruamoko/include/Makemodule.am @@ -5,6 +5,7 @@ ruamoko_include = \ ruamoko/include/infokey.h \ ruamoko/include/input.h \ ruamoko/include/math.h \ + ruamoko/include/mersenne.h \ ruamoko/include/message.h \ ruamoko/include/nq_message.h \ ruamoko/include/physics.h \ diff --git a/ruamoko/include/mersenne.h b/ruamoko/include/mersenne.h new file mode 100644 index 000000000..6f77cd7f5 --- /dev/null +++ b/ruamoko/include/mersenne.h @@ -0,0 +1,15 @@ +#ifndef __ruamoko_mersenne_h +#define __ruamoko_mersenne_h + +typedef struct _mtwist_t mtwist_t; + +mtwist_t *mtwist_new (int seed); +void mtwist_delete (mtwist_t *state); +void mtwist_seed (mtwist_t *state, int seed); +int mtwist_rand (mtwist_t *state); +// includes 0, does not include 1 +float mtwist_rand_0_1 (mtwist_t *state); +// does not include either -1 or 1 +float mtwist_rand_m1_1 (mtwist_t *state); + +#endif//__ruamoko_mersenne_h diff --git a/ruamoko/lib/Makemodule.am b/ruamoko/lib/Makemodule.am index e5218d298..17c657b17 100644 --- a/ruamoko/lib/Makemodule.am +++ b/ruamoko/lib/Makemodule.am @@ -49,6 +49,7 @@ ruamoko_lib_libcsqc_a_src= \ ruamoko/lib/draw.r \ ruamoko/lib/gib.r \ ruamoko/lib/input.r \ + ruamoko/lib/mersenne.r \ ruamoko/lib/key.r ruamoko_lib_common_dep=$(call qcautodep,$(ruamoko_lib_common_src)) diff --git a/ruamoko/lib/mersenne.r b/ruamoko/lib/mersenne.r new file mode 100644 index 000000000..26c217f9b --- /dev/null +++ b/ruamoko/lib/mersenne.r @@ -0,0 +1,8 @@ +#include "mersenne.h" + +mtwist_t *mtwist_new (int seed) = #0; +void mtwist_delete (mtwist_t *state) = #0; +void mtwist_seed (mtwist_t *state, int seed) = #0; +int mtwist_rand (mtwist_t *state) = #0; +float mtwist_rand_0_1 (mtwist_t *state) = #0; +float mtwist_rand_m1_1 (mtwist_t *state) = #0; From bdc9e9c39f065b72bf29416f0147af450e878d5c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 00:19:36 +0900 Subject: [PATCH 2011/3664] [qfcc] Unalias types before checking for equality Fixes a bogus redefinition when going from struct declaration to typedef. --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/def.c | 2 +- tools/qfcc/source/type.c | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 41e2eef3e..ca079eb01 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -181,6 +181,7 @@ int is_func (const type_t *type) __attribute__((pure)); int is_string (const type_t *type) __attribute__((pure)); int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); +int type_same (const type_t *dst, const type_t *src) __attribute__((pure)); int type_size (const type_t *type) __attribute__((pure)); void init_types (void); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 37a06c84e..df1d36b94 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -529,7 +529,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, reloc_t *relocs = 0; if (check && check->table == current_symtab) { - if (check->sy_type != sy_var || check->type != sym->type) { + if (check->sy_type != sy_var || !type_same (check->type, sym->type)) { error (0, "%s redefined", sym->name); } else { // is var and same type diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index bb211267a..3c6a4a683 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -1066,6 +1066,15 @@ type_assignable (const type_t *dst, const type_t *src) return 0; } +int +type_same (const type_t *dst, const type_t *src) +{ + dst = unalias_type (dst); + src = unalias_type (src); + + return dst == src; +} + int type_size (const type_t *type) { From 5e273a36932ea3318f9e26a263631c60f0e3c5c0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 00:21:27 +0900 Subject: [PATCH 2012/3664] [ruamoko] Make plitem_t easier to use Or more accurately, struct plitem_s. Including the pointer in the typedef made things a little awkward. --- ruamoko/include/PropertyList.h | 6 ++--- ruamoko/include/plist.h | 44 +++++++++++++++++----------------- ruamoko/lib/Entity.r | 8 +++---- ruamoko/lib/PropertyList.r | 6 ++--- ruamoko/lib/plist.r | 42 ++++++++++++++++---------------- 5 files changed, 53 insertions(+), 53 deletions(-) diff --git a/ruamoko/include/PropertyList.h b/ruamoko/include/PropertyList.h index d2494a94a..051fc98dd 100644 --- a/ruamoko/include/PropertyList.h +++ b/ruamoko/include/PropertyList.h @@ -28,7 +28,7 @@ @interface PLItem: Object { - plitem_t item; + plitem_t *item; int own; } + (PLItem *) newDictionary; @@ -38,8 +38,8 @@ + (PLItem *) fromString:(string) str; + (PLItem *) fromFile:(QFile) file; -- initWithItem:(plitem_t) item; -- initWithOwnItem:(plitem_t) item; +- initWithItem:(plitem_t *) item; +- initWithOwnItem:(plitem_t *) item; - (string) write; - (pltype_t) type; - (int) line; diff --git a/ruamoko/include/plist.h b/ruamoko/include/plist.h index bfaa25516..b99e1d19f 100644 --- a/ruamoko/include/plist.h +++ b/ruamoko/include/plist.h @@ -3,29 +3,29 @@ #include -typedef struct plitem_s *plitem_t; +typedef struct plitem_s plitem_t; typedef enum {QFDictionary, QFArray, QFBinary, QFString} pltype_t; // possible types -@extern plitem_t PL_GetFromFile (QFile file); -@extern plitem_t PL_GetPropertyList (string str); -@extern string PL_WritePropertyList (plitem_t pl); -@extern pltype_t PL_Type (plitem_t str); -@extern int PL_Line (plitem_t str); -@extern string PL_String (plitem_t str); -@extern plitem_t PL_ObjectForKey (plitem_t item, string key); -@extern plitem_t PL_RemoveObjectForKey (plitem_t item, string key); -@extern plitem_t PL_ObjectAtIndex (plitem_t item, int index); -@extern plitem_t PL_D_AllKeys (plitem_t item); -@extern int PL_D_NumKeys (plitem_t item); -@extern int PL_D_AddObject (plitem_t dict, string key, plitem_t value); -@extern int PL_A_AddObject (plitem_t array_item, plitem_t item); -@extern int PL_A_NumObjects (plitem_t item); -@extern int PL_A_InsertObjectAtIndex (plitem_t array_item, plitem_t item, int index); -@extern plitem_t PL_RemoveObjectAtIndex (plitem_t array_item, int index); -@extern plitem_t PL_NewDictionary (); -@extern plitem_t PL_NewArray (); -@extern plitem_t PL_NewData (void *data, int len); -@extern plitem_t PL_NewString (string str); -@extern void PL_Free (plitem_t pl); +@extern plitem_t *PL_GetFromFile (QFile file); +@extern plitem_t *PL_GetPropertyList (string str); +@extern string PL_WritePropertyList (plitem_t *pl); +@extern pltype_t PL_Type (plitem_t *str); +@extern int PL_Line (plitem_t *str); +@extern string PL_String (plitem_t *str); +@extern plitem_t *PL_ObjectForKey (plitem_t *item, string key); +@extern plitem_t *PL_RemoveObjectForKey (plitem_t *item, string key); +@extern plitem_t *PL_ObjectAtIndex (plitem_t *item, int index); +@extern plitem_t *PL_D_AllKeys (plitem_t *item); +@extern int PL_D_NumKeys (plitem_t *item); +@extern int PL_D_AddObject (plitem_t *dict, string key, plitem_t *value); +@extern int PL_A_AddObject (plitem_t *array_item, plitem_t *item); +@extern int PL_A_NumObjects (plitem_t *item); +@extern int PL_A_InsertObjectAtIndex (plitem_t *array_item, plitem_t *item, int index); +@extern plitem_t *PL_RemoveObjectAtIndex (plitem_t *array_item, int index); +@extern plitem_t *PL_NewDictionary (); +@extern plitem_t *PL_NewArray (); +@extern plitem_t *PL_NewData (void *data, int len); +@extern plitem_t *PL_NewString (string str); +@extern void PL_Free (plitem_t *pl); #endif//__ruamoko_plist_h diff --git a/ruamoko/lib/Entity.r b/ruamoko/lib/Entity.r index e2ea25000..3018e5a16 100644 --- a/ruamoko/lib/Entity.r +++ b/ruamoko/lib/Entity.r @@ -35,7 +35,7 @@ int PR_SetField (entity ent, string field, string value) = #0; return self; } -- (id) initWithEntity: (entity)e fromPlist: (plitem_t) dict +- (id) initWithEntity: (entity)e fromPlist: (plitem_t *) dict { self = [self initWithEntity: e]; return self; @@ -58,14 +58,14 @@ int PR_SetField (entity ent, string field, string value) = #0; //XXX EntityParseFunction (ParseEntities); } -+ createFromPlist:(plitem_t) dict ++ createFromPlist:(plitem_t *) dict { local string classname; local id class; local entity ent; local int count; local string field, value; - local plitem_t keys; + local plitem_t *keys; local @function func; local Entity *e; @@ -104,7 +104,7 @@ int PR_SetField (entity ent, string field, string value) = #0; @static void ParseEntities (string ent_data) { local script_t script; - local plitem_t plist, ent, key, value; + local plitem_t *plist, *ent, *key, *value; local string token; local int anglehack, i, count; diff --git a/ruamoko/lib/PropertyList.r b/ruamoko/lib/PropertyList.r index c6df13070..6e7eccb4c 100644 --- a/ruamoko/lib/PropertyList.r +++ b/ruamoko/lib/PropertyList.r @@ -22,7 +22,7 @@ return [PLString new:str]; } -+ itemClass:(plitem_t) item ++ itemClass:(plitem_t *) item { local string classname = nil; local id class; @@ -59,7 +59,7 @@ return [[PLItem itemClass: PL_GetFromFile (file)] autorelease]; } -- initWithItem:(plitem_t) item +- initWithItem:(plitem_t *) item { if (!(self = [super init])) return self; @@ -68,7 +68,7 @@ return self; } --initWithOwnItem:(plitem_t) item +-initWithOwnItem:(plitem_t *) item { if (!(self = [super init])) return self; diff --git a/ruamoko/lib/plist.r b/ruamoko/lib/plist.r index 34f0ce6c1..d1c0838bc 100644 --- a/ruamoko/lib/plist.r +++ b/ruamoko/lib/plist.r @@ -1,23 +1,23 @@ #include -plitem_t PL_GetFromFile (QFile file) = #0; -plitem_t PL_GetPropertyList (string str) = #0; -string PL_WritePropertyList (plitem_t pl) = #0; -pltype_t PL_Type (plitem_t str) = #0; -int PL_Line (plitem_t str) = #0; -string PL_String (plitem_t str) = #0; -plitem_t PL_ObjectForKey (plitem_t item, string key) = #0; -plitem_t PL_RemoveObjectForKey (plitem_t item, string key) = #0; -plitem_t PL_ObjectAtIndex (plitem_t item, int index) = #0; -plitem_t PL_D_AllKeys (plitem_t item) = #0; -int PL_D_NumKeys (plitem_t item) = #0; -int PL_D_AddObject (plitem_t dict, string key, plitem_t value) = #0; -int PL_A_AddObject (plitem_t array_item, plitem_t item) = #0; -int PL_A_NumObjects (plitem_t item) = #0; -int PL_A_InsertObjectAtIndex (plitem_t array_item, plitem_t item, int index) = #0; -plitem_t PL_RemoveObjectAtIndex (plitem_t array_item, int index) = #0; -plitem_t PL_NewDictionary (void) = #0; -plitem_t PL_NewArray (void) = #0; -plitem_t PL_NewData (void *data, int len) = #0; -plitem_t PL_NewString (string str) = #0; -void PL_Free (plitem_t pl) = #0; +plitem_t *PL_GetFromFile (QFile file) = #0; +plitem_t *PL_GetPropertyList (string str) = #0; +string PL_WritePropertyList (plitem_t *pl) = #0; +pltype_t PL_Type (plitem_t *str) = #0; +int PL_Line (plitem_t *str) = #0; +string PL_String (plitem_t *str) = #0; +plitem_t *PL_ObjectForKey (plitem_t *item, string key) = #0; +plitem_t *PL_RemoveObjectForKey (plitem_t *item, string key) = #0; +plitem_t *PL_ObjectAtIndex (plitem_t *item, int index) = #0; +plitem_t *PL_D_AllKeys (plitem_t *item) = #0; +int PL_D_NumKeys (plitem_t *item) = #0; +int PL_D_AddObject (plitem_t *dict, string key, plitem_t *value) = #0; +int PL_A_AddObject (plitem_t *array_item, plitem_t *item) = #0; +int PL_A_NumObjects (plitem_t *item) = #0; +int PL_A_InsertObjectAtIndex (plitem_t *array_item, plitem_t *item, int index) = #0; +plitem_t *PL_RemoveObjectAtIndex (plitem_t *array_item, int index) = #0; +plitem_t *PL_NewDictionary (void) = #0; +plitem_t *PL_NewArray (void) = #0; +plitem_t *PL_NewData (void *data, int len) = #0; +plitem_t *PL_NewString (string str) = #0; +void PL_Free (plitem_t *pl) = #0; From 23e3b4c2e5fcb994951eda95d3870dcf96d5f412 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 00:24:14 +0900 Subject: [PATCH 2013/3664] [ruamoko] Retrieve a plitem_t from PropertyList And also internally for cross-builtin use. --- include/rua_internal.h | 1 + libs/ruamoko/rua_plist.c | 7 +++++++ ruamoko/include/PropertyList.h | 1 + ruamoko/lib/PropertyList.r | 5 +++++ 4 files changed, 14 insertions(+) diff --git a/include/rua_internal.h b/include/rua_internal.h index d2119157a..24e16cc6e 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -51,6 +51,7 @@ void RUA_QFS_Init (struct progs_s *pr, int secure); int QFile_AllocHandle (struct progs_s *pr, QFile *file); QFile *QFile_GetFile (struct progs_s *pr, int handle); +struct plitem_s *Plist_GetItem (struct progs_s *pr, int handle); void RUA_Input_Init (struct progs_s *pr, int secure); void RUA_Mersenne_Init (struct progs_s *pr, int secure); diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index afccba62e..2899eec5f 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -422,6 +422,13 @@ bi_PL_Free (progs_t *pr) plist_free_handle (res, plist); } +plitem_t * +Plist_GetItem (progs_t *pr, int handle) +{ + bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + return plist->plitem; +} + static uintptr_t plist_get_hash (const void *key, void *unused) { diff --git a/ruamoko/include/PropertyList.h b/ruamoko/include/PropertyList.h index 051fc98dd..c61b16ef6 100644 --- a/ruamoko/include/PropertyList.h +++ b/ruamoko/include/PropertyList.h @@ -40,6 +40,7 @@ - initWithItem:(plitem_t *) item; - initWithOwnItem:(plitem_t *) item; +- (plitem_t *) item; - (string) write; - (pltype_t) type; - (int) line; diff --git a/ruamoko/lib/PropertyList.r b/ruamoko/lib/PropertyList.r index 6e7eccb4c..6197ec325 100644 --- a/ruamoko/lib/PropertyList.r +++ b/ruamoko/lib/PropertyList.r @@ -84,6 +84,11 @@ [super dealloc]; } +- (plitem_t *) item +{ + return item; +} + - (string) write { return PL_WritePropertyList (item); From dcd1fa28ba6cf64d1d0ccc5a74d78ef0b58207cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 00:27:16 +0900 Subject: [PATCH 2014/3664] [ruamoko] Get the input bindings working With some hacks that are not included (plan on handling events and contexts properly), button inputs, including using listeners, are working nicely: my little game is working again. While the trampoline code was a bit repetitive (and I do want to clean that up), connecting button listeners directly to Ruamoko instance methods proved to be quite nice. --- libs/ruamoko/rua_input.c | 12 +++++++++++- ruamoko/include/input.h | 2 ++ ruamoko/lib/input.r | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index e53f6b0db..e4377f91c 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -205,6 +205,7 @@ rua_add_axis_listener (progs_t *pr, axis_listener_t listener) if (cookie) { cookie = cmemalloc (res->cookie_super, sizeof (rua_in_cookie_t)); *cookie = search; + cookie->pr = pr; } cookie->users++; IN_AxisAddListener (axis, listener, cookie); @@ -235,9 +236,10 @@ rua_add_button_listener (progs_t *pr, button_listener_t listener) .data = P_POINTER (pr, 2), }; rua_in_cookie_t *cookie = Hash_FindElement (res->cookies, &search); - if (cookie) { + if (!cookie) { cookie = cmemalloc (res->cookie_super, sizeof (rua_in_cookie_t)); *cookie = search; + cookie->pr = pr; } cookie->users++; IN_ButtonAddListener (button, listener, cookie); @@ -355,6 +357,12 @@ rua_IN_AxisRemoveListener_method (progs_t *pr) rua_remove_axis_listener (pr, rua_axis_listener_method); } +static void +bi_IN_LoadConfig (progs_t *pr) +{ + IN_LoadConfig (Plist_GetItem (pr, P_INT (pr, 0))); +} + static void secured (progs_t *pr) { @@ -365,6 +373,7 @@ secured (progs_t *pr) static builtin_t secure_builtins[] = { bi(IN_CreateButton), bi(IN_CreateAxis), + bi(IN_LoadConfig), {0} }; @@ -373,6 +382,7 @@ static builtin_t secure_builtins[] = { static builtin_t insecure_builtins[] = { bi(IN_CreateButton), bi(IN_CreateAxis), + bi(IN_LoadConfig), {0} }; static builtin_t builtins[] = { diff --git a/ruamoko/include/input.h b/ruamoko/include/input.h index ebbb970d6..9363cee69 100644 --- a/ruamoko/include/input.h +++ b/ruamoko/include/input.h @@ -3,6 +3,8 @@ #include +struct plitem_s; +void IN_LoadConfig (struct plitem_s *config); in_button_t *IN_CreateButton (string name, string description); in_axis_t *IN_CreateAxis (string name, string description); int IN_FindDeviceId (string _id); diff --git a/ruamoko/lib/input.r b/ruamoko/lib/input.r index 74ee30e89..ce31f46ba 100644 --- a/ruamoko/lib/input.r +++ b/ruamoko/lib/input.r @@ -1,5 +1,6 @@ #include "input.h" +void IN_LoadConfig (struct plitem_s *config) = #0; in_button_t *IN_CreateButton (string name, string description) = #0; in_axis_t *IN_CreateAxis (string name, string description) = #0; int IN_FindDeviceId (string _id) = #0; From a89aa7fc33a337100d42e18beca60b7ccfda8813 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 00:33:38 +0900 Subject: [PATCH 2015/3664] [ruamoko] Clean up ruamoko/lib rules They were ok before the update to non-recursive make, but with the extra bits of path, the rules got very hard to read. --- ruamoko/lib/Makemodule.am | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/ruamoko/lib/Makemodule.am b/ruamoko/lib/Makemodule.am index 17c657b17..92f7b91e4 100644 --- a/ruamoko/lib/Makemodule.am +++ b/ruamoko/lib/Makemodule.am @@ -37,14 +37,27 @@ EXTRA_ruamoko_lib_libr_a_DEPENDENCIES=pak include $(ruamoko_lib_libr_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_lib_libr_a_dep) -ruamoko_lib_common_src=ruamoko/lib/debug.r ruamoko/lib/system.r ruamoko/lib/legacy_string.r +ruamoko_lib_common_src= \ + ruamoko/lib/debug.r \ + ruamoko/lib/system.r \ + ruamoko/lib/legacy_string.r ruamoko_lib_server_src= \ - ruamoko/lib/crudefile.r ruamoko/lib/entities.r ruamoko/lib/infokey.r ruamoko/lib/message.r \ - ruamoko/lib/physics.r ruamoko/lib/server.r ruamoko/lib/sv_sound.r + ruamoko/lib/crudefile.r \ + ruamoko/lib/entities.r \ + ruamoko/lib/infokey.r \ + ruamoko/lib/message.r \ + ruamoko/lib/physics.r \ + ruamoko/lib/server.r \ + ruamoko/lib/sv_sound.r + ruamoko_lib_libqw_a_src= \ - ruamoko/lib/qw_message.r ruamoko/lib/qw_physics.r ruamoko/lib/qw_sys.r + ruamoko/lib/qw_message.r \ + ruamoko/lib/qw_physics.r \ + ruamoko/lib/qw_sys.r + ruamoko_lib_libnq_a_src= \ ruamoko/lib/nq_message.r + ruamoko_lib_libcsqc_a_src= \ ruamoko/lib/draw.r \ ruamoko/lib/gib.r \ @@ -60,21 +73,31 @@ ruamoko_lib_server_dep=$(call qcautodep,$(ruamoko_lib_server_src)) include $(ruamoko_lib_server_dep) # am--include-marker r_depfiles_remade += $(ruamoko_lib_server_dep) -ruamoko_lib_libqw_a_SOURCES=$(ruamoko_lib_libqw_a_src) $(ruamoko_lib_common_src) $(ruamoko_lib_server_src) ruamoko/lib/math.r +ruamoko_lib_libqw_a_SOURCES= \ + $(ruamoko_lib_libqw_a_src) \ + $(ruamoko_lib_common_src) \ + $(ruamoko_lib_server_src) \ + ruamoko/lib/math.r ruamoko_lib_libqw_a_dep=$(call qcautodep,$(ruamoko_lib_libqw_a_src)) ruamoko_lib_libqw_a_AR=$(PAK) -cf EXTRA_ruamoko_lib_libqw_a_DEPENDENCIES=pak include $(ruamoko_lib_libqw_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_lib_libqw_a_dep) -ruamoko_lib_libnq_a_SOURCES=$(ruamoko_lib_libnq_a_src) $(ruamoko_lib_common_src) $(ruamoko_lib_server_src) ruamoko/lib/math.r +ruamoko_lib_libnq_a_SOURCES=\ + $(ruamoko_lib_libnq_a_src) \ + $(ruamoko_lib_common_src) \ + $(ruamoko_lib_server_src) \ + ruamoko/lib/math.r ruamoko_lib_libnq_a_dep=$(call qcautodep,$(ruamoko_lib_libnq_a_src)) ruamoko_lib_libnq_a_AR=$(PAK) -cf EXTRA_ruamoko_lib_libnq_a_DEPENDENCIES=pak include $(ruamoko_lib_libnq_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_lib_libnq_a_dep) -ruamoko_lib_libcsqc_a_SOURCES=$(ruamoko_lib_libcsqc_a_src) $(ruamoko_lib_common_src) +ruamoko_lib_libcsqc_a_SOURCES=\ + $(ruamoko_lib_libcsqc_a_src) \ + $(ruamoko_lib_common_src) ruamoko_lib_libcsqc_a_dep=$(call qcautodep,$(ruamoko_lib_libcsqc_a_src)) ruamoko_lib_libcsqc_a_AR= $(PAK) -cf EXTRA_ruamoko_lib_libcsqc_a_DEPENDENCIES=pak From a4c4155a5104cd5c8e75f7cada577d167651c199 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 06:47:35 +0900 Subject: [PATCH 2016/3664] [vulkan] Clean up packet submission In the end, there's no need for the two paths and I want to be able to submit empty packets with semaphores. --- libs/video/renderer/vulkan/staging.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 6de9ba21e..60c617b7d 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -275,25 +275,10 @@ QFV_PacketSubmit (qfv_packet_t *packet) qfv_device_t *device = stage->device; qfv_devfuncs_t *dfunc = device->funcs; - if (!packet->length) { - // XXX at this stage, this looks the same as below, I think a queue - // completing is the only way to set a fence (other than creation), - // so submit the (hopefully) empty command buffer so the fence becomes - // set, but without waiting on or triggering any semaphores. - dfunc->vkEndCommandBuffer (packet->cmd); - VkSubmitInfo submitInfo = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 0, 0, 0, - 1, &packet->cmd, - 0, 0, - }; - dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, - packet->fence); - return; + if (packet->length) { + QFV_FlushStagingBuffer (stage, packet->offset, packet->length); } - QFV_FlushStagingBuffer (stage, packet->offset, packet->length); - dfunc->vkEndCommandBuffer (packet->cmd); //XXX it may become necessary to pass in semaphores etc (maybe add to //packet?) From 6d64b2c47ce95fd4e83d480cd9e7cfd4a4eea07d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 06:54:23 +0900 Subject: [PATCH 2017/3664] [vulkan] Build particle buffers --- include/QF/Vulkan/qf_particles.h | 11 ++++ libs/video/renderer/vulkan/deferred.plist | 8 +++ libs/video/renderer/vulkan/vulkan_particles.c | 65 ++++++++++++++++++- 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index 4e2c7f0b6..26feb51fb 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -21,6 +21,14 @@ typedef struct qfv_parameters_s { vec4f_t ramp; } qfv_parameters_t; +// Doubles as VkDrawIndirectCommand +typedef struct qfv_particle_system_s { + uint32_t vertexCount; // always 1 + uint32_t particleCount; + uint32_t firstVertex; // always 0 + uint32_t firstInstance; // always 0 +} qfv_particle_system_t; + typedef enum { QFV_particleTranslucent, @@ -50,6 +58,9 @@ typedef struct particlectx_s { VkPipeline update; VkPipeline draw; + VkDeviceMemory memory; + struct qfv_stagebuf_s *stage; + VkDescriptorPool pool; VkDescriptorSetLayout setLayout; VkPipelineLayout physics_layout; diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 087710d8c..1eade9e2e 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -432,6 +432,14 @@ dstAccessMask = input_attachment_read|depth_stencil_attachment_read; dependencyFlags = by_region; }, + { + srcSubpass = ~0u; // external + dstSubpass = 1; // translucent + srcStageMask = compute_shader; + dstStageMask = vertex_input|draw_indirect; + srcAccessMask = shader_write; + dstAccessMask = vertex_attribute_read|indirect_command_read; + }, { srcSubpass = 0; // depth dstSubpass = 2; // g-buffer diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 14a98df44..461c01c91 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -44,14 +44,20 @@ #include "QF/plugin/vid_render.h" +#include "QF/Vulkan/qf_vid.h" //FIXME header issues +#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/staging.h" #include "QF/Vulkan/qf_particles.h" #include "r_internal.h" #include "vid_vulkan.h" +//FIXME make dynamic +#define MaxParticles 2048 + static const char * __attribute__((used)) particle_pass_names[] = { "draw", }; @@ -61,6 +67,57 @@ Vulkan_DrawParticles (vulkan_ctx_t *ctx) { } +static void +create_buffers (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + particlectx_t *pctx = ctx->particle_context; + size_t size = 0; + size_t mp = MaxParticles; + + VkMemoryRequirements stReq, parmReq, sysReq; + for (size_t i = 0; i < pctx->frames.size; i++) { + __auto_type pframe = &pctx->frames.a[i]; + pframe->state + = QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + pframe->params + = QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); + pframe->system + = QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); + dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->state, + &stReq); + dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->params, + &parmReq); + dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->system, + &sysReq); + size = QFV_NextOffset (size + stReq.size, &stReq); + size = QFV_NextOffset (size + parmReq.size, &parmReq); + size = QFV_NextOffset (size + sysReq.size, &sysReq); + } + size_t stageSize = (size / pctx->frames.size)*(pctx->frames.size + 1); + pctx->stage = QFV_CreateStagingBuffer (device, "particles", stageSize, + ctx->cmdpool); + pctx->memory = QFV_AllocBufferMemory (device, pctx->frames.a[0].state, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + size, 0); + size_t offset = 0; + for (size_t i = 0; i < pctx->frames.size; i++) { + __auto_type pframe = &pctx->frames.a[i]; + QFV_BindBufferMemory (device, pframe->state, pctx->memory, offset); + offset = QFV_NextOffset (offset + stReq.size, &parmReq); + QFV_BindBufferMemory (device, pframe->params, pctx->memory, offset); + offset = QFV_NextOffset (offset + parmReq.size, &sysReq); + QFV_BindBufferMemory (device, pframe->system, pctx->memory, offset); + offset = QFV_NextOffset (offset + sysReq.size, &stReq); + } +} + void Vulkan_Particles_Init (vulkan_ctx_t *ctx) { @@ -83,7 +140,7 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) "partphysics_layout"); pctx->update_layout = Vulkan_CreatePipelineLayout (ctx, "partupdate_layout"); - pctx->draw_layout = Vulkan_CreatePipelineLayout (ctx, "draw_layout"); + pctx->draw_layout = Vulkan_CreatePipelineLayout (ctx, "partdraw_layout"); pctx->pool = Vulkan_CreateDescriptorPool (ctx, "particle_pool"); pctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "particle_set"); @@ -104,6 +161,7 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) particle_pass_names[j])); } } + create_buffers (ctx); qfvPopDebug (ctx); } @@ -117,7 +175,12 @@ Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx) for (size_t i = 0; i < pctx->frames.size; i++) { __auto_type pframe = &pctx->frames.a[i]; free (pframe->cmdSet.a); + dfunc->vkDestroyBuffer (device->dev, pframe->state, 0); + dfunc->vkDestroyBuffer (device->dev, pframe->params, 0); + dfunc->vkDestroyBuffer (device->dev, pframe->system, 0); } + dfunc->vkFreeMemory (device->dev, pctx->memory, 0); + QFV_DestroyStagingBuffer (pctx->stage); dfunc->vkDestroyPipeline (device->dev, pctx->physics, 0); dfunc->vkDestroyPipeline (device->dev, pctx->update, 0); From 0c41c11f1d1ded3658a48f2ded559ce496c20938 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 06:55:30 +0900 Subject: [PATCH 2018/3664] [gamecode] Use a new developer flag for builtin debug rua_resolve works for now --- include/QF/sys_developer.h | 1 + libs/gamecode/pr_builtins.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/QF/sys_developer.h b/include/QF/sys_developer.h index 46b36a1fd..3dd3ba303 100644 --- a/include/QF/sys_developer.h +++ b/include/QF/sys_developer.h @@ -36,6 +36,7 @@ SYS_DEVELOPER (fs_nf) SYS_DEVELOPER (fs_f) SYS_DEVELOPER (fs) SYS_DEVELOPER (net) +SYS_DEVELOPER (rua_resolve) SYS_DEVELOPER (rua_obj) SYS_DEVELOPER (rua_msg) SYS_DEVELOPER (snd) diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index b5c9ae0a0..b5332db7f 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -220,7 +220,7 @@ PR_RelocateBuiltins (progs_t *pr) ind = pr->bi_map (pr, ind); bi = PR_FindBuiltinNum (pr, ind); if (!bi || !(proc = bi->proc)) { - Sys_MaskPrintf (SYS_dev, + Sys_MaskPrintf (SYS_rua_resolve, "WARNING: Bad builtin call number: %s = #%d\n", bi_name, -desc->first_statement); proc = bi_no_function; From 241785e9527ae6ca13cfd2778c559eedeaf69042 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 14:00:31 +0900 Subject: [PATCH 2019/3664] [ruamoko] Move older math functions The old math functions from quake and quakeworld don't belong with the newer ones as their presence in the same object file causes invalid builtin warnings when pr_cmds isn't present. --- ruamoko/lib/Makemodule.am | 2 ++ ruamoko/lib/legacy_math.r | 15 +++++++++++++++ ruamoko/lib/math.r | 14 -------------- 3 files changed, 17 insertions(+), 14 deletions(-) create mode 100644 ruamoko/lib/legacy_math.r diff --git a/ruamoko/lib/Makemodule.am b/ruamoko/lib/Makemodule.am index 92f7b91e4..3f879d6e9 100644 --- a/ruamoko/lib/Makemodule.am +++ b/ruamoko/lib/Makemodule.am @@ -40,7 +40,9 @@ r_depfiles_remade += $(ruamoko_lib_libr_a_dep) ruamoko_lib_common_src= \ ruamoko/lib/debug.r \ ruamoko/lib/system.r \ + ruamoko/lib/legacy_math.r \ ruamoko/lib/legacy_string.r + ruamoko_lib_server_src= \ ruamoko/lib/crudefile.r \ ruamoko/lib/entities.r \ diff --git a/ruamoko/lib/legacy_math.r b/ruamoko/lib/legacy_math.r new file mode 100644 index 000000000..41457de83 --- /dev/null +++ b/ruamoko/lib/legacy_math.r @@ -0,0 +1,15 @@ +#include + +vector v_forward, v_up, v_right; + +float () random = #7; +int (float f) ftoi = #0x000f0000 + 110; +float (int i) itof = #0x000f0000 + 111; +vector (vector v) normalize = #9; +float (vector v) vlen = #12; +float (vector v) vectoyaw = #13; +float (float v) rint = #36; +float (float v) floor = #37; +float (float v) ceil = #38; +float (float f) fabs = #43; +vector (vector v) vectoangles = #51; diff --git a/ruamoko/lib/math.r b/ruamoko/lib/math.r index 13b206602..e6743781c 100644 --- a/ruamoko/lib/math.r +++ b/ruamoko/lib/math.r @@ -1,19 +1,5 @@ #include -vector v_forward, v_up, v_right; - -float () random = #7; -int (float f) ftoi = #0x000f0000 + 110; -float (int i) itof = #0x000f0000 + 111; -vector (vector v) normalize = #9; -float (vector v) vlen = #12; -float (vector v) vectoyaw = #13; -float (float v) rint = #36; -float (float v) floor = #37; -float (float v) ceil = #38; -float (float f) fabs = #43; -vector (vector v) vectoangles = #51; - float (float x) sin = #0; float (float x) cos = #0; float (float x) tan = #0; From f3918471d55d2a3c4a16fd3d61f18bd5a245c29a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 15:03:26 +0900 Subject: [PATCH 2020/3664] [ruamoko] Add bindings for the main IMT functions IMT_SetContextCbuf is not bound as that requires cbuf to be bound. However, imt contexts can be created, fetched and set. --- libs/ruamoko/rua_input.c | 24 ++++++++++++++++++++++++ ruamoko/include/input.h | 4 ++++ ruamoko/lib/input.r | 4 ++++ 3 files changed, 32 insertions(+) diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index e4377f91c..5eab4b635 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -363,6 +363,25 @@ bi_IN_LoadConfig (progs_t *pr) IN_LoadConfig (Plist_GetItem (pr, P_INT (pr, 0))); } +static void +bi_IMT_CreateContext (progs_t *pr) +{ + const char *name = P_GSTRING (pr, 0); + R_INT (pr) = IMT_CreateContext (name); +} + +static void +bi_IMT_GetContext (progs_t *pr) +{ + R_INT (pr) = IMT_GetContext (); +} + +static void +bi_IMT_SetContext (progs_t *pr) +{ + IMT_SetContext (P_INT (pr, 0)); +} + static void secured (progs_t *pr) { @@ -415,6 +434,11 @@ static builtin_t builtins[] = { rua_IN_AxisAddListener_method, -1}, {"IN_AxisRemoveListener|^{tag in_axis_s=}(@@:.)@", rua_IN_AxisRemoveListener_method, -1}, + + bi(IMT_CreateContext), + bi(IMT_GetContext), + bi(IMT_SetContext), + {0} }; diff --git a/ruamoko/include/input.h b/ruamoko/include/input.h index 9363cee69..31408cfc9 100644 --- a/ruamoko/include/input.h +++ b/ruamoko/include/input.h @@ -38,4 +38,8 @@ typedef void (*axis_listener_t) (void *data, in_axis_t *axis);//FIXME const @overload void IN_AxisAddListener (in_axis_t *axis, IMP listener, id obj); @overload void IN_AxisRemoveListener (in_axis_t *axis, IMP listener, id obj); +int IMT_CreateContext (string name); +int IMT_GetContext (void); +void IMT_SetContext (int ctx); + #endif//__ruamoko_input_h diff --git a/ruamoko/lib/input.r b/ruamoko/lib/input.r index ce31f46ba..34059f853 100644 --- a/ruamoko/lib/input.r +++ b/ruamoko/lib/input.r @@ -36,3 +36,7 @@ void IN_ButtonRemoveListener (in_button_t *button, IMP listener, id obj) = #0; void IN_AxisAddListener (in_axis_t *axis, IMP listener, id obj) = #0; @overload void IN_AxisRemoveListener (in_axis_t *axis, IMP listener, id obj) = #0; + +int IMT_CreateContext (string name) = #0; +int IMT_GetContext (void) = #0; +void IMT_SetContext (int ctx) = #0; From 3ffdaccd50d57c022ee27c4f0c9e7ab47aaf2d93 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 15:06:17 +0900 Subject: [PATCH 2021/3664] [qwaq] Add an event handler for graphics It's very much a hack, but it will do for now until I can rewrite the whole thing: it's not at all thread safe, but it is over eight years old and has survived a lot of bit-rot. --- ruamoko/qwaq/builtins/graphics.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index b7d4f7351..44426ae4a 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -57,6 +57,8 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/sys.h" #include "QF/vid.h" +#include "QF/input/event.h" + #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" @@ -82,6 +84,7 @@ quit_f (void) static progs_t *bi_rprogs; static func_t qc2d; +static int event_handler_id; static void bi_2d (void) @@ -129,6 +132,12 @@ static builtin_t builtins[] = { {0} }; +static int +event_handler (const IE_event_t *ie_event, void *_pr) +{ + return IN_Binding_HandleEvent (ie_event); +} + static void bi_shutdown (void *data) { @@ -169,6 +178,9 @@ BI_Graphics_Init (progs_t *pr) RUA_Game_Init (pr, thread->rua_security); S_Progs_Init (pr); + event_handler_id = IE_Add_Handler (event_handler, pr); + IE_Set_Focus (event_handler_id); + Con_Init ("client"); if (con_module) { con_module->data->console->realtime = &con_realtime; From dad19aa2ade8baad22f312cbea7f25047aa2e943 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Dec 2021 23:43:03 +0900 Subject: [PATCH 2022/3664] [input] Correct balanced range calculation Fixes axis inputs being half what they should be. Can't quite get +1, though (need to figure something out for the positive axis range being slightly smaller than the negative range). --- libs/input/in_imt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index d64fc7a1d..2d1d1f5b3 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -588,8 +588,8 @@ IMT_ProcessAxis (int axis, int value) if (recipe->deadzone >= 0) { // balanced axis: -1..1 int center = (recipe->min + recipe->max + 1) / 2; - minval += deadzone - center; - maxval -= deadzone + center; + minval += deadzone; + maxval -= deadzone; input -= center; if (input < -deadzone) { input += deadzone; From b726c24b05d8194e3b1db9be426ac0d5f4f117ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Dec 2021 11:17:51 +0900 Subject: [PATCH 2023/3664] [ruamoko] Reset parameters before setting in listener It's right there in the docs, even (though only on the macro, which I'd forgotten about). Fixes some nasty corruption. --- libs/ruamoko/rua_input.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 5eab4b635..dec753b34 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -277,6 +277,7 @@ rua_listener_method (rua_in_cookie_t *cookie, const void *input) { progs_t *pr = cookie->pr; PR_PushFrame (pr); + PR_RESET_PARAMS (pr); P_POINTER (pr, 0) = cookie->data; P_POINTER (pr, 1) = 0; // don't know the method name (selector) P_POINTER (pr, 2) = PR_SetPointer (pr, input);//FIXME check input From f77da210ff38c83e17d2d3df024cb34345a683ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Dec 2021 11:22:32 +0900 Subject: [PATCH 2024/3664] [ruamoko] Merge listener cookie code I know that duplication would turn around and bite me :P --- libs/ruamoko/rua_input.c | 107 +++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 45 deletions(-) diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index dec753b34..0b74d1367 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -192,48 +192,13 @@ bi_IN_GetButtonInfo (progs_t *pr) } } -static void -rua_add_axis_listener (progs_t *pr, axis_listener_t listener) +static rua_in_cookie_t * +make_cookie (progs_t *pr, func_t func, pointer_t data) { input_resources_t *res = PR_Resources_Find (pr, "input"); - in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); rua_in_cookie_t search = { - .func = P_FUNCTION (pr, 1), - .data = P_POINTER (pr, 2), - }; - rua_in_cookie_t *cookie = Hash_FindElement (res->cookies, &search); - if (cookie) { - cookie = cmemalloc (res->cookie_super, sizeof (rua_in_cookie_t)); - *cookie = search; - cookie->pr = pr; - } - cookie->users++; - IN_AxisAddListener (axis, listener, cookie); -} - -static void -rua_remove_axis_listener (progs_t *pr, axis_listener_t listener) -{ - input_resources_t *res = PR_Resources_Find (pr, "input"); - in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); - rua_in_cookie_t search = { - .func = P_FUNCTION (pr, 1), - .data = P_POINTER (pr, 2), - }; - rua_in_cookie_t *cookie = Hash_FindElement (res->cookies, &search); - if (cookie) { - IN_AxisRemoveListener (axis, listener, cookie); - } -} - -static void -rua_add_button_listener (progs_t *pr, button_listener_t listener) -{ - input_resources_t *res = PR_Resources_Find (pr, "input"); - in_button_t *button = &P_STRUCT (pr, in_button_t, 0); - rua_in_cookie_t search = { - .func = P_FUNCTION (pr, 1), - .data = P_POINTER (pr, 2), + .func = func, + .data = data, }; rua_in_cookie_t *cookie = Hash_FindElement (res->cookies, &search); if (!cookie) { @@ -242,21 +207,73 @@ rua_add_button_listener (progs_t *pr, button_listener_t listener) cookie->pr = pr; } cookie->users++; + return cookie; +} + +static rua_in_cookie_t * +find_cookie (progs_t *pr, func_t func, pointer_t data) +{ + input_resources_t *res = PR_Resources_Find (pr, "input"); + rua_in_cookie_t search = { + .func = func, + .data = data, + }; + return Hash_FindElement (res->cookies, &search); +} + +static void +release_cookie (progs_t *pr, rua_in_cookie_t *cookie) +{ + if (!--cookie->users) { + input_resources_t *res = PR_Resources_Find (pr, "input"); + Hash_DelElement (res->cookies, cookie); + Hash_Free (res->cookies, cookie); + } +} + +static void +rua_add_axis_listener (progs_t *pr, axis_listener_t listener) +{ + in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); + func_t func = P_FUNCTION (pr, 1); + func_t data = P_POINTER (pr, 2); + rua_in_cookie_t *cookie = make_cookie (pr, func, data); + IN_AxisAddListener (axis, listener, cookie); +} + +static void +rua_remove_axis_listener (progs_t *pr, axis_listener_t listener) +{ + in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); + func_t func = P_FUNCTION (pr, 1); + func_t data = P_POINTER (pr, 2); + rua_in_cookie_t *cookie = find_cookie (pr, func, data); + if (cookie) { + IN_AxisRemoveListener (axis, listener, cookie); + release_cookie (pr, cookie); + } +} + +static void +rua_add_button_listener (progs_t *pr, button_listener_t listener) +{ + in_button_t *button = &P_STRUCT (pr, in_button_t, 0); + func_t func = P_FUNCTION (pr, 1); + func_t data = P_POINTER (pr, 2); + rua_in_cookie_t *cookie = make_cookie (pr, func, data); IN_ButtonAddListener (button, listener, cookie); } static void rua_remove_button_listener (progs_t *pr, button_listener_t listener) { - input_resources_t *res = PR_Resources_Find (pr, "input"); in_button_t *button = &P_STRUCT (pr, in_button_t, 0); - rua_in_cookie_t search = { - .func = P_FUNCTION (pr, 1), - .data = P_POINTER (pr, 2), - }; - rua_in_cookie_t *cookie = Hash_FindElement (res->cookies, &search); + func_t func = P_FUNCTION (pr, 1); + func_t data = P_POINTER (pr, 2); + rua_in_cookie_t *cookie = find_cookie (pr, func, data); if (cookie) { IN_ButtonRemoveListener (button, listener, cookie); + release_cookie (pr, cookie); } } From 2e3e9ea7c0043dae02b14c7d9e396f153b334345 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Dec 2021 11:23:39 +0900 Subject: [PATCH 2025/3664] [ruamoko] Actually save the cooke This fixes the listener leak. --- libs/ruamoko/rua_input.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 0b74d1367..3cd3156a2 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -205,6 +205,7 @@ make_cookie (progs_t *pr, func_t func, pointer_t data) cookie = cmemalloc (res->cookie_super, sizeof (rua_in_cookie_t)); *cookie = search; cookie->pr = pr; + Hash_AddElement (res->cookies, cookie); } cookie->users++; return cookie; From 757123110008bd86ca2c0250ec30520184e1004d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Dec 2021 13:55:52 +0900 Subject: [PATCH 2026/3664] [input] Get single axis info for unbound devices This doesn't fix the problem of keyhelp not working for axes belonging to unbound devices, but may be a step in the right direction. --- libs/input/in_binding.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 061ece4de..acc80601a 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -298,13 +298,9 @@ in_keyhelp_event_handler (const IE_event_t *ie_event, void *unused) if (db) { ai = &db->axis_info[axis]; } else { - //FIXME set single axis info entry - int num_axes; - in_axisinfo_t *axis_info; - IN_AxisInfo (devid, 0, &num_axes); - axis_info = alloca (num_axes * sizeof (in_axisinfo_t)); - IN_AxisInfo (devid, axis_info, &num_axes); - ai = &axis_info[axis]; + in_axisinfo_t axis_info; + IN_GetAxisInfo (devid, axis, &axis_info); + ai = &axis_info; } if (!ai->min && !ai->max) { if (abs (value) > keyhelp_axis_threshold) { From 2b25748cc40a910c0a8a651f655757e48b3e690a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Dec 2021 19:43:27 +0900 Subject: [PATCH 2027/3664] [ruamoko] Correct SetIterator memory handling This makes SetIterator more compatible with autorelease. --- libs/ruamoko/rua_set.c | 1 + ruamoko/include/Set.h | 7 +++++-- ruamoko/lib/Set.r | 18 +++++++++++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 8bc1915a9..4e8b752b5 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -52,6 +52,7 @@ typedef struct { typedef struct { pr_id_t obj; + pr_int_t set; pr_int_t iter; } pr_set_iter_t; diff --git a/ruamoko/include/Set.h b/ruamoko/include/Set.h index 1f7c39177..2e020755b 100644 --- a/ruamoko/include/Set.h +++ b/ruamoko/include/Set.h @@ -1,8 +1,8 @@ #ifndef __ruamoko_Set_h #define __ruamoko_Set_h -typedef struct set_s *set_t; -typedef struct set_iter_s *set_iter_t; +typedef struct set_s set_t; +typedef struct set_iter_s set_iter_t; @extern void set_del_iter (set_iter_t *set_iter); @extern unsigned set_iter_element (set_iter_t *set_iter); @@ -32,8 +32,11 @@ typedef struct set_iter_s *set_iter_t; #include +@class Set; + @interface SetIterator: Object { + Set *set; set_iter_t *iter; } - (SetIterator *) next; diff --git a/ruamoko/lib/Set.r b/ruamoko/lib/Set.r index 393bb31ac..7afc13361 100644 --- a/ruamoko/lib/Set.r +++ b/ruamoko/lib/Set.r @@ -27,20 +27,32 @@ string set_as_string (set_t *set) = #0; @implementation SetIterator: Object -- initWithIterator: (set_iter_t *) iter + +- initWithSet: (Set *)set iterator:(set_iter_t *) iter { if (!(self = [super init])) { return nil; } + self.set = [set retain]; self.iter = iter; return self; } ++ (id) withSet: (Set *)set iterator:(set_iter_t *) iter +{ + return [[[self alloc] initWithSet: set iterator: iter] autorelease]; +} + +- (void) dealloc +{ + [set release]; + [super dealloc]; +} + - (SetIterator *) next { if ((iter = set_next (iter))) return self; - [self dealloc]; return nil; } @@ -93,7 +105,7 @@ string set_as_string (set_t *set) = #0; if (!iter) return nil; - iterator = [[SetIterator alloc] initWithIterator: iter]; + iterator = [SetIterator withSet: self iterator: iter]; return iterator; } From bcf80650f33fcb8fda022bde7b7a1e1059069fb5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 23 Dec 2021 21:38:05 +0900 Subject: [PATCH 2028/3664] [ruamoko] Use the right index in disabled code I have no idea why the code is disabled (especially considering the comment), so leaving it that way for now, but this makes the code compile when enabled. --- ruamoko/lib/Array.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/lib/Array.r b/ruamoko/lib/Array.r index 5fbaa9e56..aa0f82082 100644 --- a/ruamoko/lib/Array.r +++ b/ruamoko/lib/Array.r @@ -323,7 +323,7 @@ cause something else to happen). */ tmp = _objs[--count]; - _objs[i] = nil; + _objs[count] = nil; [tmp release]; } #else From 5bfe0e5d341c0aeeaa27e2b02f9eb52d91a28c25 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 24 Dec 2021 19:32:25 +0900 Subject: [PATCH 2029/3664] [sw] Update for changed particle field names Fixes 32-bit x86 target builds. --- libs/video/renderer/sw/d_parta.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/sw/d_parta.S b/libs/video/renderer/sw/d_parta.S index 30cede548..a7b9a8543 100644 --- a/libs/video/renderer/sw/d_parta.S +++ b/libs/video/renderer/sw/d_parta.S @@ -68,10 +68,10 @@ C(D_DrawParticle): // transform point // VectorSubtract (p->org, r_origin, local); flds C(r_origin) - fsubrs pt_org(%edi) - flds pt_org+4(%edi) + fsubrs pt_pos(%edi) + flds pt_pos+4(%edi) fsubs C(r_origin)+4 - flds pt_org+8(%edi) + flds pt_pos+8(%edi) fsubs C(r_origin)+8 fxch %st(2) // local[0] | local[1] | local[2] From bdd3870d2f86ab280ffa4a49710758f85929d1c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 24 Dec 2021 09:53:58 +0900 Subject: [PATCH 2030/3664] [qfcc] Add failing test for dealloc warning I have gotten tired of chasing memory leaks caused by me forgetting to add [super dealloc] to my dealloc methods, so getting qfcc to chew me out when I do seems to be a good idea (having such a warning would have saved me many hours, just as missing return warnings have). --- tools/qfcc/test/Makemodule.am | 15 +++++++++++++ tools/qfcc/test/dealloc-nowarn.r | 36 ++++++++++++++++++++++++++++++++ tools/qfcc/test/dealloc-warn.r | 35 +++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 tools/qfcc/test/dealloc-nowarn.r create mode 100644 tools/qfcc/test/dealloc-warn.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index af16e954b..e20ed87ea 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -17,6 +17,7 @@ test_progs_dat=\ tools/qfcc/test/comma-expr.dat \ tools/qfcc/test/compound.dat \ tools/qfcc/test/deadbool.dat \ + tools/qfcc/test/dealloc-nowarn.dat \ tools/qfcc/test/double.dat \ tools/qfcc/test/double-alias.dat \ tools/qfcc/test/enum.dat \ @@ -63,6 +64,7 @@ fail_progs_dat= test_build_errors=\ tools/qfcc/test/classarray.r \ + tools/qfcc/test/dealloc-warn.r \ tools/qfcc/test/double-demote-float.r \ tools/qfcc/test/double-demote-float-ainit.r \ tools/qfcc/test/double-demote-float-ginit.r \ @@ -193,6 +195,16 @@ tools/qfcc/test/deadbool.run: $(qfcc_test_run_deps) include $(deadbool_dep) # am--include-marker r_depfiles_remade += $(deadbool_dep) +tools_qfcc_test_dealloc_nowarn_dat_SOURCES=tools/qfcc/test/dealloc-nowarn.r +dealloc_nowarn_obj=$(tools_qfcc_test_dealloc_nowarn_dat_SOURCES:.r=.o) +dealloc_nowarn_dep=$(call qcautodep,$(tools_qfcc_test_dealloc_nowarn_dat_SOURCES)) +tools/qfcc/test/dealloc-nowarn.dat$(EXEEXT): $(dealloc_nowarn_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(dealloc_nowarn_obj) +tools/qfcc/test/dealloc-nowarn.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(dealloc_nowarn_dep) # am--include-marker +r_depfiles_remade += $(dealloc_nowarn_dep) + tools_qfcc_test_double_dat_SOURCES=tools/qfcc/test/double.r double_obj=$(tools_qfcc_test_double_dat_SOURCES:.r=.o) double_dep=$(call qcautodep,$(tools_qfcc_test_double_dat_SOURCES)) @@ -216,6 +228,9 @@ r_depfiles_remade += $(double_alias_dep) tools/qfcc/test/classarray.run$(EXEEXT): tools/qfcc/test/classarray.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< +tools/qfcc/test/dealloc-warn.run$(EXEEXT): tools/qfcc/test/dealloc-warn.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + tools/qfcc/test/double-demote-int.run$(EXEEXT): tools/qfcc/test/double-demote-int.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/dealloc-nowarn.r b/tools/qfcc/test/dealloc-nowarn.r new file mode 100644 index 000000000..f4bc3bcc4 --- /dev/null +++ b/tools/qfcc/test/dealloc-nowarn.r @@ -0,0 +1,36 @@ +@interface Object +{ + Class isa; +} +-(void)dealloc; +@end + +@interface derived : Object +@end + +@implementation Object +-(void) dealloc +{ + // this is the root of the hierarchy, so no super to call, thus + // must not check for [super dealloc] +} +@end + +void __obj_exec_class (struct obj_module *msg) = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; + +@implementation derived +-(void) dealloc +{ + // as this is a derived class, failure to call [super dealloc] will + // result in a memory leak (yes, there could be special allocators + // involved, in which case something will be needed to inform the + // compiler) + [super dealloc]; +} +@end + +int main () +{ + return 0; // test passes if compile succeeds (with -Werror) +} diff --git a/tools/qfcc/test/dealloc-warn.r b/tools/qfcc/test/dealloc-warn.r new file mode 100644 index 000000000..bf218ca9c --- /dev/null +++ b/tools/qfcc/test/dealloc-warn.r @@ -0,0 +1,35 @@ +@interface Object +{ + Class isa; +} +-(void)dealloc; +@end + +@interface derived : Object +@end + +@implementation Object +-(void) dealloc +{ + // this is the root of the hierarchy, so no super to call, thus + // must not check for [super dealloc] +} +@end + +@implementation derived +-(void) dealloc +{ + // as this is a derived class, failure to call [super dealloc] will + // result in a memory leak (yes, there could be special allocators + // involved, in which case something will be needed to inform the + // compiler) +} +@end + +void __obj_exec_class (struct obj_module *msg) = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; + +int main () +{ + return 1; // test fails if compile succeeds (with -Werror) +} From ff1cdb6f89eb354622a136b32b522b7394b35180 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 24 Dec 2021 13:22:01 +0900 Subject: [PATCH 2031/3664] [qfcc] Give select expressions their own type While get_selector does the job of getting a selector from a selector reference expression, I have long considered lumping various expression types under ex_expr to be a mistake. Not only is this a step towards sorting that out, it will make working on #24 easier. --- tools/qfcc/include/expr.h | 7 +++++++ tools/qfcc/source/dot_expr.c | 11 +++++++++++ tools/qfcc/source/expr.c | 10 ++++++++++ tools/qfcc/source/expr_assign.c | 1 + tools/qfcc/source/expr_obj.c | 13 +++++++++---- tools/qfcc/source/method.c | 3 +++ tools/qfcc/source/statements.c | 8 ++++++++ 7 files changed, 49 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 843c1baf6..99584d435 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -53,6 +53,7 @@ typedef enum { ex_symbol, ///< non-temporary variable (::symbol_t) ex_temp, ///< temporary variable (::ex_temp_t) ex_vector, ///< "vector" expression (::ex_vector_t) + ex_selector, ///< selector expression (::ex_selector_t) ex_nil, ///< umm, nil, null. nuff said (0 of any type) ex_value, ///< constant value (::ex_value_t) @@ -121,6 +122,11 @@ typedef struct { struct expr_s *list; ///< Linked list of element expressions. } ex_vector_t; +typedef struct { + struct expr_s *sel_ref; ///< Reference to selector in selector table + struct selector_s *sel; ///< selector +} ex_selector_t; + /** Pointer constant expression. Represent a pointer to an absolute address in data space. @@ -237,6 +243,7 @@ typedef struct expr_s { struct symbol_s *symbol; ///< symbol reference expression ex_temp_t temp; ///< temporary variable expression ex_vector_t vector; ///< vector expression list + ex_selector_t selector; ///< selector ref and name ex_value_t *value; ///< constant value element_chain_t compound; ///< compound initializer ex_memset_t memset; ///< memset expr params diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index f8c5464a9..cde32c8fd 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -47,6 +47,7 @@ #include "qfalloca.h" #include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/method.h" #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" #include "tools/qfcc/include/strpool.h" @@ -426,6 +427,15 @@ print_vector (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->line); } +static void +print_selector (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + dasprintf (dstr, "%*se_%p [label=\"%s\"];\n", indent, "", e, + e->e.selector.sel->name); +} + static void print_nil (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -564,6 +574,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_symbol] = print_symbol, [ex_temp] = print_temp, [ex_vector] = print_vector, + [ex_selector] = print_selector, [ex_nil] = print_nil, [ex_value] = print_value, [ex_compound] = print_compound, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index fc26a78bd..b6104e508 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -256,6 +256,8 @@ get_type (expr_t *e) break; case ex_vector: return e->e.vector.type; + case ex_selector: + return &type_SEL; case ex_count: internal_error (e, "invalid expression"); } @@ -448,6 +450,11 @@ copy_expr (expr_t *e) t = t->next; } return n; + case ex_selector: + n = new_expr (); + *n = *e; + n->e.selector.sel_ref = copy_expr (e->e.selector.sel_ref); + return n; case ex_compound: n = new_expr (); *n = *e; @@ -1641,6 +1648,7 @@ unary_expr (int op, expr_t *e) case ex_state: case ex_compound: case ex_memset: + case ex_selector: internal_error (e, 0); case ex_uexpr: if (e->e.expr.op == '-') { @@ -1732,6 +1740,7 @@ unary_expr (int op, expr_t *e) case ex_state: case ex_compound: case ex_memset: + case ex_selector: internal_error (e, 0); case ex_bool: return new_bool_expr (e->e.bool.false_list, @@ -1802,6 +1811,7 @@ unary_expr (int op, expr_t *e) case ex_state: case ex_compound: case ex_memset: + case ex_selector: internal_error (e, 0); case ex_uexpr: if (e->e.expr.op == '~') diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 9ae27b146..7126b5545 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -135,6 +135,7 @@ is_lvalue (const expr_t *expr) case ex_nil: case ex_value: case ex_error: + case ex_selector: break; case ex_count: internal_error (expr, "invalid expression"); diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index 17d53dfdb..9c3984055 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -90,7 +90,7 @@ expr_t * selector_expr (keywordarg_t *selector) { dstring_t *sel_id = dstring_newstr (); - expr_t *sel; + expr_t *sel_ref; symbol_t *sel_sym; symbol_t *sel_table; int index; @@ -111,10 +111,15 @@ selector_expr (keywordarg_t *selector) symtab_addsymbol (pr.symtab, sel_table); reloc_def_def (sel_table->s.def, sel_sym->s.def); } - sel = new_symbol_expr (sel_sym); + sel_ref = new_symbol_expr (sel_sym); + sel_ref = new_binary_expr ('&', sel_ref, new_short_expr (index)); + sel_ref->e.expr.type = &type_SEL; + + expr_t *sel = new_expr (); + sel->type = ex_selector; + sel->e.selector.sel_ref = sel_ref; + sel->e.selector.sel = get_selector (sel_ref); dstring_delete (sel_id); - sel = new_binary_expr ('&', sel, new_short_expr (index)); - sel->e.expr.type = &type_SEL; return sel; } diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index a1d05ce9d..55a4f2344 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -483,6 +483,9 @@ get_selector (expr_t *sel) { selector_t _sel = {0, 0, 0}; + if (sel->type == ex_selector) { + return sel->e.selector.sel; + } if (sel->type != ex_expr && sel->e.expr.op != '&' && !is_SEL(sel->e.expr.type)) { error (sel, "not a selector"); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 959f0f3c6..152ac81c3 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -50,6 +50,7 @@ #include "tools/qfcc/include/dot.h" #include "tools/qfcc/include/expr.h" #include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/method.h" #include "tools/qfcc/include/options.h" #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/reloc.h" @@ -1450,6 +1451,12 @@ expr_value (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_selector (sblock_t *sblock, expr_t *e, operand_t **op) +{ + return statement_subexpr (sblock, e->e.selector.sel_ref, op); +} + static sblock_t * statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1463,6 +1470,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_vector] = expr_vector_e, [ex_nil] = expr_nil, [ex_value] = expr_value, + [ex_selector] = expr_selector, }; if (!e) { *op = 0; From 8385046486daee9a4a6da8901ee75b4c31a6cafe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 24 Dec 2021 13:58:16 +0900 Subject: [PATCH 2032/3664] [qfcc] Warn when super dealloc invocation is missing Forgetting to invoke [super dealloc] in a derived class's -dealloc method has caused me to waste far too much time chasing down the resulting memory leaks and crashes. This is actually the main focus of issue #24, but I want to take care of multiple paths before I consider the issue to be done. However, as a bonus, four cases were found :) --- .../renderer/vulkan/vkgen/vkfieldcustom.r | 1 + libs/video/renderer/vulkan/vkgen/vkfielddef.r | 1 + .../video/renderer/vulkan/vkgen/vkfieldtype.r | 1 + ruamoko/cl_menu/CvarObject.r | 1 + tools/qfcc/include/expr.h | 7 +++ tools/qfcc/source/expr.c | 6 +++ tools/qfcc/source/statements.c | 49 +++++++++++++++++++ tools/qfcc/test/Makemodule.am | 4 ++ tools/qfcc/test/dealloc-warn2.r | 44 +++++++++++++++++ 9 files changed, 114 insertions(+) create mode 100644 tools/qfcc/test/dealloc-warn2.r diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r index 57d8fa54e..2f11e0987 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r @@ -27,6 +27,7 @@ { str_free (pltype); str_free (parser); + [super dealloc]; } -writeParseData diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.r b/libs/video/renderer/vulkan/vkgen/vkfielddef.r index b3c81096f..edf1e8a31 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfielddef.r +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.r @@ -68,6 +68,7 @@ { str_free (struct_name); str_free (field_name); + [super dealloc]; } -writeParseData diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r index 5f9429a20..53e75b476 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r @@ -32,6 +32,7 @@ parseItemType (PLItem *item) str_free (type); str_free (parser); str_free (parse_type); + [super dealloc]; } -initWithItem:(PLItem *)item diff --git a/ruamoko/cl_menu/CvarObject.r b/ruamoko/cl_menu/CvarObject.r index fab57fe28..f7d1c1ce2 100644 --- a/ruamoko/cl_menu/CvarObject.r +++ b/ruamoko/cl_menu/CvarObject.r @@ -20,5 +20,6 @@ -(void)dealloc { str_free (name); + [super dealloc]; } @end diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 99584d435..6b8fa8034 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -586,6 +586,13 @@ int expr_integral (expr_t *e) __attribute__((pure)); */ int is_constant (expr_t *e) __attribute__((pure)); +/** Check if the expression refers to a selector + + \param e The expression to check. + \return True if the expression is a selector. +*/ +int is_selector (expr_t *e) __attribute__((pure)); + /** Return a value expression representing the constant stored in \a e. If \a e does not represent a constant, or \a e is already a value or diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index b6104e508..26d892c60 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -887,6 +887,12 @@ is_constant (expr_t *e) return 0; } +int +is_selector (expr_t *e) +{ + return e->type == ex_selector; +} + expr_t * constant_expr (expr_t *e) { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 152ac81c3..7e93658f8 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -45,6 +45,7 @@ #include "QF/mathlib.h" #include "QF/va.h" +#include "tools/qfcc/include/class.h" #include "tools/qfcc/include/dags.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/dot.h" @@ -1002,6 +1003,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) const char *pref = ""; statement_t *s; + // function arguments are in reverse order for (a = args; a; a = a->next) count++; ind = count; @@ -2027,6 +2029,42 @@ remove_dead_blocks (sblock_t *blocks) return did_anything; } +static void +search_for_super_dealloc (sblock_t *sblock) +{ + while (sblock) { + for (statement_t *st = sblock->statements; st; st = st->next) { + if (!statement_is_call (st)) { + continue; + } + if (st->opa->op_type != op_def + || strcmp (st->opa->o.def->name, "obj_msgSend_super") != 0) { + continue; + } + // FIXME this is messy (calls should have their own expression + // type) + // have effectively checked e1 above + if (st->expr->type != ex_expr) { + continue; + } + // function arguments are in reverse order, and the selector + // is the second argument (or second last in the list) + expr_t *arg; + for (arg = st->expr->e.expr.e2; + arg && arg->next && arg->next->next; arg = arg->next) { + } + if (arg && arg->next && is_selector (arg)) { + selector_t *sel = get_selector (st->expr->e.expr.e2); + if (sel && strcmp (sel->name, "dealloc") == 0) { + return; + } + } + } + sblock = sblock->next; + } + warning (0, "Derived class -dealloc does not call [super dealloc]"); +} + static void check_final_block (sblock_t *sblock) { @@ -2071,6 +2109,7 @@ make_statements (expr_t *e) sblock_t *sblock = new_sblock (); int did_something; int pass = 0; + class_t *class; if (options.block_dot.expr) dump_dot ("expr", e, dump_dot_expr); @@ -2088,6 +2127,16 @@ make_statements (expr_t *e) pass++; } while (did_something); check_final_block (sblock); + if (current_class && (class = extract_class (current_class))) { + // If the class is a root class, then it is not possible for there + // to be a call to [super dealloc] so do not check. However, any + // derived class implementeing -dealloc must call [super dealloc] + // (or some other deallocator (FIXME: later)) + // FIXME better check for dealloc? + if (class->super_class && !strcmp (current_func->name, "-dealloc")) { + search_for_super_dealloc (sblock); + } + } if (options.block_dot.final) dump_dot ("final", sblock, dump_dot_sblock); diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index e20ed87ea..1b3919e80 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -65,6 +65,7 @@ fail_progs_dat= test_build_errors=\ tools/qfcc/test/classarray.r \ tools/qfcc/test/dealloc-warn.r \ + tools/qfcc/test/dealloc-warn2.r \ tools/qfcc/test/double-demote-float.r \ tools/qfcc/test/double-demote-float-ainit.r \ tools/qfcc/test/double-demote-float-ginit.r \ @@ -231,6 +232,9 @@ tools/qfcc/test/classarray.run$(EXEEXT): tools/qfcc/test/classarray.r $(qfcc_fai tools/qfcc/test/dealloc-warn.run$(EXEEXT): tools/qfcc/test/dealloc-warn.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< +tools/qfcc/test/dealloc-warn2.run$(EXEEXT): tools/qfcc/test/dealloc-warn2.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + tools/qfcc/test/double-demote-int.run$(EXEEXT): tools/qfcc/test/double-demote-int.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/dealloc-warn2.r b/tools/qfcc/test/dealloc-warn2.r new file mode 100644 index 000000000..0cd10d3ef --- /dev/null +++ b/tools/qfcc/test/dealloc-warn2.r @@ -0,0 +1,44 @@ +@interface Object +{ + Class isa; +} +-(void)dealloc; +-(void)release; +@end + +@interface derived : Object +{ + id something; +} +@end + +@implementation Object +-(void) dealloc +{ + // this is the root of the hierarchy, so no super to call, thus + // must not check for [super dealloc] +} +-(void) release +{ +} +@end + +@implementation derived +-(void) dealloc +{ + // as this is a derived class, failure to call [super dealloc] will + // result in a memory leak (yes, there could be special allocators + // involved, in which case something will be needed to inform the + // compiler) + [super release]; + [something dealloc]; +} +@end + +void __obj_exec_class (struct obj_module *msg) = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; + +int main () +{ + return 1; // test fails if compile succeeds (with -Werror) +} From 79b760b1d0ccb6d3df5364c7a059d64f1c6e05db Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 24 Dec 2021 14:20:40 +0900 Subject: [PATCH 2033/3664] [qfcc] Add failing test for multi-path dealloc This test checks for control reaching the end of the function without invoking [super dealloc] in all paths. --- tools/qfcc/test/Makemodule.am | 15 +++++++++++ tools/qfcc/test/dealloc-nowarn2.r | 43 ++++++++++++++++++++++++++++++ tools/qfcc/test/dealloc-warn3.r | 44 +++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 tools/qfcc/test/dealloc-nowarn2.r create mode 100644 tools/qfcc/test/dealloc-warn3.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 1b3919e80..057382f75 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -18,6 +18,7 @@ test_progs_dat=\ tools/qfcc/test/compound.dat \ tools/qfcc/test/deadbool.dat \ tools/qfcc/test/dealloc-nowarn.dat \ + tools/qfcc/test/dealloc-nowarn2.dat \ tools/qfcc/test/double.dat \ tools/qfcc/test/double-alias.dat \ tools/qfcc/test/enum.dat \ @@ -66,6 +67,7 @@ test_build_errors=\ tools/qfcc/test/classarray.r \ tools/qfcc/test/dealloc-warn.r \ tools/qfcc/test/dealloc-warn2.r \ + tools/qfcc/test/dealloc-warn3.r \ tools/qfcc/test/double-demote-float.r \ tools/qfcc/test/double-demote-float-ainit.r \ tools/qfcc/test/double-demote-float-ginit.r \ @@ -206,6 +208,16 @@ tools/qfcc/test/dealloc-nowarn.run: $(qfcc_test_run_deps) include $(dealloc_nowarn_dep) # am--include-marker r_depfiles_remade += $(dealloc_nowarn_dep) +tools_qfcc_test_dealloc_nowarn2_dat_SOURCES=tools/qfcc/test/dealloc-nowarn2.r +dealloc_nowarn2_obj=$(tools_qfcc_test_dealloc_nowarn2_dat_SOURCES:.r=.o) +dealloc_nowarn2_dep=$(call qcautodep,$(tools_qfcc_test_dealloc_nowarn2_dat_SOURCES)) +tools/qfcc/test/dealloc-nowarn2.dat$(EXEEXT): $(dealloc_nowarn2_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(dealloc_nowarn2_obj) +tools/qfcc/test/dealloc-nowarn2.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(dealloc_nowarn2_dep) # am--include-marker +r_depfiles_remade += $(dealloc_nowarn2_dep) + tools_qfcc_test_double_dat_SOURCES=tools/qfcc/test/double.r double_obj=$(tools_qfcc_test_double_dat_SOURCES:.r=.o) double_dep=$(call qcautodep,$(tools_qfcc_test_double_dat_SOURCES)) @@ -235,6 +247,9 @@ tools/qfcc/test/dealloc-warn.run$(EXEEXT): tools/qfcc/test/dealloc-warn.r $(qfcc tools/qfcc/test/dealloc-warn2.run$(EXEEXT): tools/qfcc/test/dealloc-warn2.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< +tools/qfcc/test/dealloc-warn3.run$(EXEEXT): tools/qfcc/test/dealloc-warn3.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + tools/qfcc/test/double-demote-int.run$(EXEEXT): tools/qfcc/test/double-demote-int.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/dealloc-nowarn2.r b/tools/qfcc/test/dealloc-nowarn2.r new file mode 100644 index 000000000..1443be8e2 --- /dev/null +++ b/tools/qfcc/test/dealloc-nowarn2.r @@ -0,0 +1,43 @@ +@interface Object +{ + Class isa; +} +-(void)dealloc; +@end + +@interface derived : Object +{ + int free; +} +@end + +@implementation Object +-(void) dealloc +{ + // this is the root of the hierarchy, so no super to call, thus + // must not check for [super dealloc] +} +@end + +void __obj_exec_class (struct obj_module *msg) = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; + +@implementation derived +-(void) dealloc +{ + // as this is a derived class, failure to call [super dealloc] will + // result in a memory leak (yes, there could be special allocators + // involved, in which case something will be needed to inform the + // compiler) + if (free) { + [super dealloc]; + } else { + [super dealloc]; + } +} +@end + +int main () +{ + return 0; // test passes if compile succeeds (with -Werror) +} diff --git a/tools/qfcc/test/dealloc-warn3.r b/tools/qfcc/test/dealloc-warn3.r new file mode 100644 index 000000000..3d505c987 --- /dev/null +++ b/tools/qfcc/test/dealloc-warn3.r @@ -0,0 +1,44 @@ +@interface Object +{ + Class isa; +} +-(void)dealloc; +@end + +@interface derived : Object +{ + int free; +} +@end + +@implementation Object +-(void) dealloc +{ + // this is the root of the hierarchy, so no super to call, thus + // must not check for [super dealloc] +} +-(void) release +{ +} +@end + +@implementation derived +-(void) dealloc +{ + // as this is a derived class, failure to call [super dealloc] will + // result in a memory leak (yes, there could be special allocators + // involved, in which case something will be needed to inform the + // compiler) + if (free) { + [super dealloc]; + } +} +@end + +void __obj_exec_class (struct obj_module *msg) = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; + +int main () +{ + return 1; // test fails if compile succeeds (with -Werror) +} From c87be87741cd5c682a7738a09e63d885b962eb2e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Dec 2021 11:17:33 +0900 Subject: [PATCH 2034/3664] Fix some doxygen warnings --- include/QF/input/imt.h | 2 +- include/QF/progs.h | 2 +- include/snd_internal.h | 19 ++++++++++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 7eeed7aa9..e3777e8ea 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -92,7 +92,7 @@ void IMT_SetContextCbuf (int ctx, struct cbuf_s *cbuf); Searches through all contexts for the named imt. The search is case insensitive. - \param imt_name The name of the imt to find. Case insensitive. + \param name The name of the imt to find. Case insensitive. \return The named imt, or null if not found. */ imt_t *IMT_FindIMT (const char *name) __attribute__ ((pure)); diff --git a/include/QF/progs.h b/include/QF/progs.h index d9c3aebf0..734fb192b 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1637,7 +1637,7 @@ void *PR_Resources_Find (progs_t *pr, const char *name); /** Retrieve a resource from the resource map using a handle. \param map The resource map. - \param col The handle. + \param ind The handle. \return A pointer to the resource, or NULL if the handle is invalid. */ diff --git a/include/snd_internal.h b/include/snd_internal.h index 5690b98fb..1d7479096 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -68,7 +68,7 @@ struct portable_samplepair_s { float right; //!< right sample }; -/** communication structure between output drivers and renderer +/** Sound system state */ struct snd_s { int speed; //!< sample rate @@ -280,16 +280,19 @@ sfx_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file, void SND_SFX_StreamClose (sfx_t *sfx); /** Pre-load a sound into the cache. + \param snd sound system state \param sample name of sound to precache */ sfx_t *SND_PrecacheSound (snd_t *snd, const char *sample); /** Pre-load a sound. + \param snd sound system state \param name name of sound to load */ sfx_t *SND_LoadSound (snd_t *snd, const char *name); /** Initialize the sfx sub-subsystem + \param snd sound system state */ void SND_SFX_Init (snd_t *snd); @@ -314,10 +317,12 @@ extern channel_t snd_channels[MAX_CHANNELS]; //!< pool of available channels extern int snd_total_channels; //!< number of active channels /** Allocate a sound channel that can be used for playing sounds. + \param snd sound system state */ struct channel_s *SND_AllocChannel (snd_t *snd); /** Stop a channel from playing. + \param snd sound system state \param chan the channel to stop */ void SND_ChannelStop (snd_t *snd, channel_t *chan); @@ -329,6 +334,7 @@ void SND_ChannelStop (snd_t *snd, channel_t *chan); void SND_FinishChannels (void); /** Scan channels looking for stopped channels. + \param snd sound system state \param wait if true, wait for the channels to be done. if false, force the channels to be done. true is for threaded, false for non-threaded. @@ -336,17 +342,20 @@ void SND_FinishChannels (void); void SND_ScanChannels (snd_t *snd, int wait); /** Disable ambient sounds. + \param snd sound system state \todo not used, remove? */ void SND_AmbientOff (snd_t *snd); /** Enable ambient sounds. + \param snd sound system state \todo not used, remove? */ void SND_AmbientOn (snd_t *snd); /** Update the sound engine with the client's position and orientation and render some sound. + \param snd sound system state \param origin 3d coords of the client \param v_forward 3d vector of the client's facing direction \param v_right 3d vector of the client's rightward direction @@ -359,14 +368,17 @@ void SND_SetListener (snd_t *snd, const vec3_t origin, const vec3_t v_forward, const byte *ambient_sound_level); /** Stop all sounds from playing. + \param snd sound system state */ void SND_StopAllSounds (snd_t *snd); /** Initialize the channels sub-subsystem + \param snd sound system state */ void SND_Channels_Init (snd_t *snd); /** Start a sound playing. + \param snd sound system state \param entnum index of entity the sound is associated with. \param entchannel 0-7 - 0 auto (never willingly overrides) @@ -383,6 +395,7 @@ void SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, float fvol, float attenuation); /** Create a sound generated by the world. + \param snd sound system state \param sfx sound to play \param origin 3d coords of where the sound originates \param vol absolute volume of the sound @@ -391,12 +404,14 @@ void SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, void SND_StaticSound (snd_t *snd, sfx_t *sfx, const vec3_t origin, float vol, float attenuation); /** Stop an entity's sound. + \param snd sound system state \param entnum index of entity the sound is associated with. \param entchannel channel to silence */ void SND_StopSound (snd_t *snd, int entnum, int entchannel); /** Start a sound local to the client view. + \param snd sound system state \param s name of sound to play */ void SND_LocalSound (snd_t *snd, const char *s); @@ -409,11 +424,13 @@ void SND_LocalSound (snd_t *snd, const char *s); ///@{ /** Mix all active channels into the output buffer. + \param snd sound system state \param endtime sample time until when to mix */ void SND_PaintChannels(snd_t *snd, unsigned int endtime); /** Initialize the scale table for painting of 8 bit samples. + \param snd sound system state */ void SND_InitScaletable (snd_t *snd); From 7c24f116b4fefeb5f254498e4cf3bf60bcea6d83 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Dec 2021 12:21:59 +0900 Subject: [PATCH 2035/3664] [qfcc] Rename tmpaddr to pseudo_addr I want to use the function's pseudo address that was used for managing aliased temporary variables for other pseudo operands as well. The new name seems to better reflect the variable's purpose even without the other pseudo operands as temporary variables are, effectively, pseudo operands until they are properly allocated. --- tools/qfcc/include/function.h | 2 +- tools/qfcc/source/flow.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 355edea37..947e4f3b5 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -96,7 +96,7 @@ typedef struct function_s { struct set_s *global_vars;///< set indicating which vars are global struct statement_s **statements; int num_statements; - int tmpaddr; ///< tmp var "address" for flow analysis + int pseudo_addr;///< pseudo address space for flow analysis } function_t; extern function_t *current_func; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 3128fa686..f981f7c51 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -248,7 +248,7 @@ flowvar_is_param (flowvar_t *var) return 1; } -/** Check if the flowvar refers to a function parameter. +/** Check if the flowvar refers to a local variable. * * As this is simply "neither global nor pamam", all other flowvars are * considered local, in particular actual non-staic function scope variables @@ -376,8 +376,8 @@ get_temp_address (function_t *func, operand_t *op) top = top->o.tempop.alias; } if (!top->o.tempop.flowaddr) { - top->o.tempop.flowaddr = func->tmpaddr; - func->tmpaddr += top->size; + top->o.tempop.flowaddr = func->pseudo_addr; + func->pseudo_addr += top->size; } if (top->o.tempop.offset) { internal_error (top->expr, "real tempop with a non-zero offset"); @@ -509,7 +509,7 @@ static int flow_def_clear_flowvars (def_t *def, void *data) * recycled. Thus, give temp vars a pseudo address space just past the * address space used for source-defined local variables. As each temp * var is added to the analyzer, get_temp_address() assigns the temp var - * an address using function_t::tmpaddr as a starting point. + * an address using function_t::pseudo_addr as a starting point. * * add_operand() takes care of setting flowvar_t::flowaddr for both locals * and temps. @@ -567,7 +567,7 @@ flow_build_vars (function_t *func) // set up pseudo address space for temp vars so accessing tmp vars // though aliases analyses correctly - func->tmpaddr = func->num_statements + func->symtab->space->size; + func->pseudo_addr = func->num_statements + func->symtab->space->size; func->num_vars = 0; // incremented by add_operand // first, add .return and .param_[0-7] as they are always needed From f9032113620b9a8e82381aad621f4dd7d1d47c89 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Dec 2021 12:40:24 +0900 Subject: [PATCH 2036/3664] [qfcc] Make operand union anonymous This one was easy enough and gets rid of that little o. wart. --- tools/qfcc/include/statements.h | 2 +- tools/qfcc/source/dags.c | 106 +++++++++---------- tools/qfcc/source/emit.c | 22 ++-- tools/qfcc/source/flow.c | 70 ++++++------ tools/qfcc/source/statements.c | 182 ++++++++++++++++---------------- 5 files changed, 191 insertions(+), 191 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 829723729..d87f4fce5 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -66,7 +66,7 @@ typedef struct operand_s { struct ex_label_s *label; tempop_t tempop; struct operand_s *alias; - } o; + }; } operand_t; /** Overall type of statement. diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 974a917f0..fea637564 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -74,13 +74,13 @@ flush_daglabels (void) if ((op = daglabel_chain->op)) { if (op->op_type == op_def) - op->o.def->daglabel = 0; + op->def->daglabel = 0; else if (op->op_type == op_temp) - op->o.tempop.daglabel = 0; + op->tempop.daglabel = 0; else if (op->op_type == op_value) - op->o.value->daglabel = 0; + op->value->daglabel = 0; else if (op->op_type == op_label) - op->o.label->daglabel = 0; + op->label->daglabel = 0; else internal_error (op->expr, "unexpected operand type"); } @@ -166,33 +166,33 @@ operand_label (dag_t *dag, operand_t *op) return 0; if (op->op_type == op_temp) { - //while (op->o.tempop.alias) - // op = op->o.tempop.alias; - if (op->o.tempop.daglabel) - return op->o.tempop.daglabel; + //while (op->tempop.alias) + // op = op->tempop.alias; + if (op->tempop.daglabel) + return op->tempop.daglabel; label = new_label (dag); label->op = op; - op->o.tempop.daglabel = label; + op->tempop.daglabel = label; } else if (op->op_type == op_def) { - def = op->o.def; + def = op->def; if (def->daglabel) return def->daglabel; label = new_label (dag); label->op = op; def->daglabel = label; } else if (op->op_type == op_value) { - val = op->o.value; + val = op->value; if (val->daglabel) return val->daglabel; label = new_label (dag); label->op = op; val->daglabel = label; } else if (op->op_type == op_label) { - if (op->o.label->daglabel) - return op->o.label->daglabel; + if (op->label->daglabel) + return op->label->daglabel; label = new_label (dag); label->op = op; - op->o.label->daglabel = label; + op->label->daglabel = label; } else { internal_error (op->expr, "unexpected operand type: %d", op->op_type); } @@ -225,20 +225,20 @@ dag_node (operand_t *op) if (!op) return 0; if (op->op_type == op_def) { - def = op->o.def; + def = op->def; if (def->daglabel) node = def->daglabel->dagnode; } else if (op->op_type == op_temp) { - while (op->o.tempop.alias) - op = op->o.tempop.alias; - if (op->o.tempop.daglabel) - node = op->o.tempop.daglabel->dagnode; + while (op->tempop.alias) + op = op->tempop.alias; + if (op->tempop.daglabel) + node = op->tempop.daglabel->dagnode; } else if (op->op_type == op_value) { - if (op->o.value->daglabel) - node = op->o.value->daglabel->dagnode; + if (op->value->daglabel) + node = op->value->daglabel->dagnode; } else if (op->op_type == op_label) { - if (op->o.label->daglabel) - node = op->o.label->daglabel->dagnode; + if (op->label->daglabel) + node = op->label->daglabel->dagnode; } return node; } @@ -427,19 +427,19 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) set_add (node->edges, n->number); } if (op->op_type == op_value - && op->o.value->lltype == ev_pointer - && op->o.value->v.pointer.def) { - def_visit_all (op->o.value->v.pointer.def, 1, + && op->value->lltype == ev_pointer + && op->value->v.pointer.def) { + def_visit_all (op->value->v.pointer.def, 1, dagnode_def_set_edges_visit, n); } if (op->op_type == op_def - && (op->o.def->alias || op->o.def->alias_defs)) { - def_visit_all (op->o.def, 1, + && (op->def->alias || op->def->alias_defs)) { + def_visit_all (op->def, 1, dagnode_def_set_edges_visit, n); } if (op->op_type == op_temp - && (op->o.tempop.alias || op->o.tempop.alias_ops)) { - tempop_visit_all (&op->o.tempop, 1, + && (op->tempop.alias || op->tempop.alias_ops)) { + tempop_visit_all (&op->tempop, 1, dagnode_tempop_set_edges_visit, n); } } @@ -471,7 +471,7 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) if (num_params && isdigit (*num_params)) { for (i = first_param; i < *num_params - '0'; i++) { flowvar_t *var = flowvars[i + 1]; - def_t *param_def = var->op->o.def; + def_t *param_def = var->op->def; daglabel_t *daglabel; int param_node; @@ -516,7 +516,7 @@ op_is_constant (operand_t *op) if (op->op_type == op_value) return 1; if (op->op_type == op_label) - return op->o.def->constant; + return op->def->constant; return 0; } @@ -535,7 +535,7 @@ dag_tempop_kill_aliases_visit (tempop_t *tempop, void *_l) dagnode_t *node = l->dagnode; daglabel_t *label; - if (tempop == &l->op->o.tempop) + if (tempop == &l->op->tempop) return 0; label = tempop->daglabel; if (label && label->dagnode && !label->dagnode->killed) { @@ -553,7 +553,7 @@ dag_def_kill_aliases_visit (def_t *def, void *_l) dagnode_t *node = l->dagnode; daglabel_t *label; - if (def == l->op->o.def) + if (def == l->op->def) return 0; label = def->daglabel; if (label && label->dagnode && !label->dagnode->killed) { @@ -570,13 +570,13 @@ dag_kill_aliases (daglabel_t *l) operand_t *op = l->op; if (op->op_type == op_temp) { - if (op->o.tempop.alias || op->o.tempop.alias_ops) { - tempop_visit_all (&op->o.tempop, 1, + if (op->tempop.alias || op->tempop.alias_ops) { + tempop_visit_all (&op->tempop, 1, dag_tempop_kill_aliases_visit, l); } } else if (op->op_type == op_def) { - if (op->o.def->alias || op->o.def->alias_defs) { - def_visit_all (op->o.def, 1, dag_def_kill_aliases_visit, l); + if (op->def->alias || op->def->alias_defs) { + def_visit_all (op->def, 1, dag_def_kill_aliases_visit, l); } } else { internal_error (op->expr, "rvalue assignment?"); @@ -606,13 +606,13 @@ dag_live_aliases(operand_t *op) { // FIXME it would be better to propogate the aliasing if (op->op_type == op_temp - && (op->o.tempop.alias || op->o.tempop.alias_ops)) { - tempop_visit_all (&op->o.tempop, 1, dag_tempop_live_aliases, - &op->o.tempop); + && (op->tempop.alias || op->tempop.alias_ops)) { + tempop_visit_all (&op->tempop, 1, dag_tempop_live_aliases, + &op->tempop); } if (op->op_type == op_def - && (op->o.def->alias || op->o.def->alias_defs)) { - def_visit_all (op->o.def, 1, dag_def_live_aliases, op->o.def); + && (op->def->alias || op->def->alias_defs)) { + def_visit_all (op->def, 1, dag_def_live_aliases, op->def); } } @@ -695,10 +695,10 @@ dag_remove_dead_vars (dag_t *dag, set_t *live_vars) if (set_is_member (dag->flownode->global_vars, var->number)) continue; if (l->op->op_type == op_def - && def_visit_all (l->op->o.def, 1, dag_def_alias_live, live_vars)) + && def_visit_all (l->op->def, 1, dag_def_alias_live, live_vars)) continue; if (l->op->op_type == op_temp - && tempop_visit_all (&l->op->o.tempop, 1, dag_tempop_alias_live, + && tempop_visit_all (&l->op->tempop, 1, dag_tempop_alias_live, live_vars)) continue; if (!set_is_member (live_vars, var->number)) @@ -898,11 +898,11 @@ build_statement (const char *opcode, operand_t **operands, expr_t *expr) for (i = 0; i < 3; i++) { if ((op = operands[i])) { while (op->op_type == op_alias) - op = op->o.alias; + op = op->alias; if (op->op_type == op_temp) { - while (op->o.tempop.alias) - op = op->o.tempop.alias; - op->o.tempop.users++; + while (op->tempop.alias) + op = op->tempop.alias; + op->tempop.users++; } } } @@ -1014,8 +1014,8 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) var_iter = set_next (var_iter)) { var = dag->labels[var_iter->element]; dst = var->op; - type = dst->o.def->type; - dstDef = dst->o.def; + type = dst->def->type; + dstDef = dst->def; if (dstDef->alias) { offset = dstDef->offset; dstDef = dstDef->alias; @@ -1075,8 +1075,8 @@ generate_memsetps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) var_iter = set_next (var_iter)) { var = dag->labels[var_iter->element]; dst = var->op; - type = dst->o.def->type; - dstDef = dst->o.def; + type = dst->def->type; + dstDef = dst->def; if (dstDef->alias) { offset = dstDef->offset; dstDef = dstDef->alias; diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index f61151da3..bec1d9320 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -65,7 +65,7 @@ static def_t *get_operand_def (expr_t *expr, operand_t *op); static def_t * get_tempop_def (expr_t *expr, operand_t *tmpop, type_t *type) { - tempop_t *tempop = &tmpop->o.tempop; + tempop_t *tempop = &tmpop->tempop; if (tempop->def) { return tempop->def; } @@ -108,9 +108,9 @@ get_operand_def (expr_t *expr, operand_t *op) return 0; switch (op->op_type) { case op_def: - return op->o.def; + return op->def; case op_value: - return get_value_def (expr, op->o.value, op->type); + return get_value_def (expr, op->value, op->type); case op_label: op->type = &type_short; zero_def.type = &type_short; @@ -118,7 +118,7 @@ get_operand_def (expr_t *expr, operand_t *op) case op_temp: return get_tempop_def (expr, op, op->type); case op_alias: - return get_operand_def (expr, op->o.alias); + return get_operand_def (expr, op->alias); case op_nil: internal_error (expr, "unexpected nil operand"); } @@ -160,8 +160,8 @@ add_statement_op_ref (operand_t *op, dstatement_t *st, int field) int st_ofs = st - pr.code->code; reloc_t *reloc = new_reloc (0, st_ofs, rel_op_a_op + field); - reloc->next = op->o.label->dest->relocs; - op->o.label->dest->relocs = reloc; + reloc->next = op->label->dest->relocs; + op->label->dest->relocs = reloc; } } @@ -170,11 +170,11 @@ use_tempop (operand_t *op, expr_t *expr) { if (!op || op->op_type != op_temp) return; - while (op->o.tempop.alias) - op = op->o.tempop.alias; - if (--op->o.tempop.users == 0) - free_temp_def (op->o.tempop.def); - if (op->o.tempop.users <= -1) + while (op->tempop.alias) + op = op->tempop.alias; + if (--op->tempop.users == 0) + free_temp_def (op->tempop.def); + if (op->tempop.users <= -1) bug (expr, "temp users went negative: %s", operand_string (op)); } diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index f981f7c51..4c4e6dedb 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -215,7 +215,7 @@ flowvar_is_global (flowvar_t *var) if (var->op->op_type != op_def) return 0; - def = var->op->o.def; + def = var->op->def; if (def->alias) def = def->alias; if (def->local) @@ -238,7 +238,7 @@ flowvar_is_param (flowvar_t *var) if (var->op->op_type != op_def) return 0; - def = var->op->o.def; + def = var->op->def; if (def->alias) def = def->alias; if (!def->local) @@ -273,12 +273,12 @@ flowvar_get_def (flowvar_t *var) switch (op->op_type) { case op_def: - return op->o.def; + return op->def; case op_value: case op_label: return 0; case op_temp: - return op->o.tempop.def; + return op->tempop.def; case op_alias: internal_error (op->expr, "unexpected alias operand"); case op_nil: @@ -302,14 +302,14 @@ flow_get_var (operand_t *op) return 0; if (op->op_type == op_temp) { - if (!op->o.tempop.flowvar) - op->o.tempop.flowvar = new_flowvar (); - return op->o.tempop.flowvar; + if (!op->tempop.flowvar) + op->tempop.flowvar = new_flowvar (); + return op->tempop.flowvar; } if (op->op_type == op_def) { - if (!op->o.def->flowvar) - op->o.def->flowvar = new_flowvar (); - return op->o.def->flowvar; + if (!op->def->flowvar) + op->def->flowvar = new_flowvar (); + return op->def->flowvar; } return 0; } @@ -369,21 +369,21 @@ static int get_temp_address (function_t *func, operand_t *op) { operand_t *top = op; - if (op->o.tempop.flowaddr) { - return op->o.tempop.flowaddr; + if (op->tempop.flowaddr) { + return op->tempop.flowaddr; } - while (top->o.tempop.alias) { - top = top->o.tempop.alias; + while (top->tempop.alias) { + top = top->tempop.alias; } - if (!top->o.tempop.flowaddr) { - top->o.tempop.flowaddr = func->pseudo_addr; + if (!top->tempop.flowaddr) { + top->tempop.flowaddr = func->pseudo_addr; func->pseudo_addr += top->size; } - if (top->o.tempop.offset) { + if (top->tempop.offset) { internal_error (top->expr, "real tempop with a non-zero offset"); } - op->o.tempop.flowaddr = top->o.tempop.flowaddr + op->o.tempop.offset; - return op->o.tempop.flowaddr; + op->tempop.flowaddr = top->tempop.flowaddr + op->tempop.offset; + return op->tempop.flowaddr; } /** Add an operand's flowvar to the function's list of variables. @@ -415,7 +415,7 @@ add_operand (function_t *func, operand_t *op) if (op->op_type == op_temp) { var->flowaddr = get_temp_address (func, op); } else if (flowvar_is_local (var)) { - var->flowaddr = func->num_statements + def_offset (var->op->o.def); + var->flowaddr = func->num_statements + def_offset (var->op->def); } } } @@ -537,7 +537,7 @@ flow_build_vars (function_t *func) flow_analyze_statement (s, 0, 0, 0, operands); for (j = 0; j < FLOW_OPERANDS; j++) { if (operands[j] && operands[j]->op_type == op_def) { - def_visit_all (operands[j]->o.def, 0, + def_visit_all (operands[j]->def, 0, flow_def_clear_flowvars, 0); } } @@ -546,7 +546,7 @@ flow_build_vars (function_t *func) for (i = 0; i < num_flow_params; i++) { def_t *def = param_symbol (flow_params[i].name)->s.def; def_visit_all (def, 0, flow_def_clear_flowvars, 0); - flow_params[i].op.o.def = def; + flow_params[i].op.def = def; num_vars += count_operand (&flow_params[i].op); } // then run through the statements in the function looking for accessed @@ -664,9 +664,9 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) tmp = set_new (); // collect the kill sets from any aliases if (op->op_type == op_temp) { - tempop_visit_all (&op->o.tempop, 1, flow_tempop_kill_aliases, tmp); + tempop_visit_all (&op->tempop, 1, flow_tempop_kill_aliases, tmp); } else if (op->op_type == op_def) { - def_visit_all (op->o.def, 1, flow_def_kill_aliases, tmp); + def_visit_all (op->def, 1, flow_def_kill_aliases, tmp); } // don't allow aliases to kill definitions in the entry dummy block if (uninit) { @@ -912,13 +912,13 @@ flow_uninit_scan_statements (flownode_t *node, set_t *defs, set_t *uninit) set_difference (defs, var->define); if (var->op->op_type == op_temp) { op = var->op; - if (op->o.tempop.alias) { - var = op->o.tempop.alias->o.tempop.flowvar; + if (op->tempop.alias) { + var = op->tempop.alias->tempop.flowvar; if (var) set_difference (defs, var->define); } - for (op = op->o.tempop.alias_ops; op; op = op->next) { - var = op->o.tempop.flowvar; + for (op = op->tempop.alias_ops; op; op = op->next) { + var = op->tempop.flowvar; if (var) set_difference (defs, var->define); } @@ -1062,9 +1062,9 @@ flow_add_op_var (set_t *set, operand_t *op, int is_use) // var is being treated as assigned as well. Want to handle partial // defs properly, but I am as yet uncertain of how. if (op->op_type == op_temp) { - tempop_visit_all (&op->o.tempop, ol, flow_tempop_add_aliases, set); + tempop_visit_all (&op->tempop, ol, flow_tempop_add_aliases, set); } else { - def_visit_all (op->o.def, ol, flow_def_add_aliases, set); + def_visit_all (op->def, ol, flow_def_add_aliases, set); } } @@ -1073,15 +1073,15 @@ flow_analyze_pointer_operand (operand_t *ptrop, set_t *def) { operand_t *op = 0; - if (ptrop->op_type == op_value && ptrop->o.value->lltype == ev_pointer) { - ex_pointer_t *ptr = &ptrop->o.value->v.pointer; - if (ptrop->o.value->v.pointer.def) { + if (ptrop->op_type == op_value && ptrop->value->lltype == ev_pointer) { + ex_pointer_t *ptr = &ptrop->value->v.pointer; + if (ptrop->value->v.pointer.def) { def_t *alias; alias = alias_def (ptr->def, ptr->type, ptr->val); op = def_operand (alias, ptr->type, ptrop->expr); } - if (ptrop->o.value->v.pointer.tempop) { - op = ptrop->o.value->v.pointer.tempop; + if (ptrop->value->v.pointer.tempop) { + op = ptrop->value->v.pointer.tempop; } if (op) { flow_add_op_var (def, op, 0); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 7e93658f8..efc9ce2b0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -97,14 +97,14 @@ optype_str (op_type_e type) static const char * tempop_string (operand_t *tmpop) { - tempop_t *tempop = &tmpop->o.tempop; + tempop_t *tempop = &tmpop->tempop; if (tempop->alias) { return va (0, "", pr_type_name[tempop->type->type], tmpop, tempop->users, tempop->alias, tempop->offset, - tempop->alias->o.tempop.users); + tempop->alias->tempop.users); } return va (0, "", pr_type_name[tempop->type->type], tmpop, tempop->users); @@ -117,51 +117,51 @@ operand_string (operand_t *op) return ""; switch (op->op_type) { case op_def: - return op->o.def->name; + return op->def->name; case op_value: - switch (op->o.value->lltype) { + switch (op->value->lltype) { case ev_string: return va (0, "\"%s\"", - quote_string (op->o.value->v.string_val)); + quote_string (op->value->v.string_val)); case ev_double: - return va (0, "%g", op->o.value->v.double_val); + return va (0, "%g", op->value->v.double_val); case ev_float: - return va (0, "%g", op->o.value->v.float_val); + return va (0, "%g", op->value->v.float_val); case ev_vector: return va (0, "'%g %g %g'", - op->o.value->v.vector_val[0], - op->o.value->v.vector_val[1], - op->o.value->v.vector_val[2]); + op->value->v.vector_val[0], + op->value->v.vector_val[1], + op->value->v.vector_val[2]); case ev_quat: return va (0, "'%g %g %g %g'", - op->o.value->v.quaternion_val[0], - op->o.value->v.quaternion_val[1], - op->o.value->v.quaternion_val[2], - op->o.value->v.quaternion_val[3]); + op->value->v.quaternion_val[0], + op->value->v.quaternion_val[1], + op->value->v.quaternion_val[2], + op->value->v.quaternion_val[3]); case ev_pointer: - if (op->o.value->v.pointer.def) { + if (op->value->v.pointer.def) { return va (0, "ptr %s+%d", - op->o.value->v.pointer.def->name, - op->o.value->v.pointer.val); - } else if(op->o.value->v.pointer.tempop) { - operand_t *tempop = op->o.value->v.pointer.tempop; + op->value->v.pointer.def->name, + op->value->v.pointer.val); + } else if(op->value->v.pointer.tempop) { + operand_t *tempop = op->value->v.pointer.tempop; return va (0, "ptr %s+%d", tempop_string (tempop), - op->o.value->v.pointer.val); + op->value->v.pointer.val); } else { - return va (0, "ptr %d", op->o.value->v.pointer.val); + return va (0, "ptr %d", op->value->v.pointer.val); } case ev_field: - return va (0, "field %d", op->o.value->v.pointer.val); + return va (0, "field %d", op->value->v.pointer.val); case ev_entity: - return va (0, "ent %d", op->o.value->v.integer_val); + return va (0, "ent %d", op->value->v.integer_val); case ev_func: - return va (0, "func %d", op->o.value->v.integer_val); + return va (0, "func %d", op->value->v.integer_val); case ev_integer: - return va (0, "int %d", op->o.value->v.integer_val); + return va (0, "int %d", op->value->v.integer_val); case ev_uinteger: - return va (0, "uint %u", op->o.value->v.uinteger_val); + return va (0, "uint %u", op->value->v.uinteger_val); case ev_short: - return va (0, "short %d", op->o.value->v.short_val); + return va (0, "short %d", op->value->v.short_val); case ev_void: return "(void)"; case ev_invalid: @@ -171,12 +171,12 @@ operand_string (operand_t *op) } break; case op_label: - return op->o.label->name; + return op->label->name; case op_temp: return tempop_string (op); case op_alias: { - const char *alias = operand_string (op->o.alias); + const char *alias = operand_string (op->alias); char *buf = alloca (strlen (alias) + 1); strcpy (buf, alias); return va (0, "alias(%s,%s)", pr_type_name[op->type->type], @@ -194,49 +194,49 @@ _print_operand (operand_t *op) switch (op->op_type) { case op_def: printf ("(%s) ", pr_type_name[op->type->type]); - printf ("%s", op->o.def->name); + printf ("%s", op->def->name); break; case op_value: printf ("(%s) ", pr_type_name[op->type->type]); - switch (op->o.value->lltype) { + switch (op->value->lltype) { case ev_string: - printf ("\"%s\"", op->o.value->v.string_val); + printf ("\"%s\"", op->value->v.string_val); break; case ev_double: - printf ("%g", op->o.value->v.double_val); + printf ("%g", op->value->v.double_val); break; case ev_float: - printf ("%g", op->o.value->v.float_val); + printf ("%g", op->value->v.float_val); break; case ev_vector: - printf ("'%g", op->o.value->v.vector_val[0]); - printf (" %g", op->o.value->v.vector_val[1]); - printf (" %g'", op->o.value->v.vector_val[2]); + printf ("'%g", op->value->v.vector_val[0]); + printf (" %g", op->value->v.vector_val[1]); + printf (" %g'", op->value->v.vector_val[2]); break; case ev_quat: - printf ("'%g", op->o.value->v.quaternion_val[0]); - printf (" %g", op->o.value->v.quaternion_val[1]); - printf (" %g", op->o.value->v.quaternion_val[2]); - printf (" %g'", op->o.value->v.quaternion_val[3]); + printf ("'%g", op->value->v.quaternion_val[0]); + printf (" %g", op->value->v.quaternion_val[1]); + printf (" %g", op->value->v.quaternion_val[2]); + printf (" %g'", op->value->v.quaternion_val[3]); break; case ev_pointer: printf ("(%s)[%d]", - pr_type_name[op->o.value->v.pointer.type->type], - op->o.value->v.pointer.val); + pr_type_name[op->value->v.pointer.type->type], + op->value->v.pointer.val); break; case ev_field: - printf ("%d", op->o.value->v.pointer.val); + printf ("%d", op->value->v.pointer.val); break; case ev_entity: case ev_func: case ev_integer: - printf ("%d", op->o.value->v.integer_val); + printf ("%d", op->value->v.integer_val); break; case ev_uinteger: - printf ("%u", op->o.value->v.uinteger_val); + printf ("%u", op->value->v.uinteger_val); break; case ev_short: - printf ("%d", op->o.value->v.short_val); + printf ("%d", op->value->v.short_val); break; case ev_void: case ev_invalid: @@ -245,16 +245,16 @@ _print_operand (operand_t *op) } break; case op_label: - printf ("block %p", op->o.label->dest); + printf ("block %p", op->label->dest); break; case op_temp: printf ("tmp (%s) %p", pr_type_name[op->type->type], op); - if (op->o.tempop.def) - printf (" %s", op->o.tempop.def->name); + if (op->tempop.def) + printf (" %s", op->tempop.def->name); break; case op_alias: printf ("alias(%s,", pr_type_name[op->type->type]); - _print_operand (op->o.alias); + _print_operand (op->alias); printf (")"); break; case op_nil: @@ -379,7 +379,7 @@ def_operand (def_t *def, type_t *type, expr_t *expr) op = new_operand (op_def, expr, __builtin_return_address (0)); op->type = type; op->size = type_size (type); - op->o.def = def; + op->def = def; return op; } @@ -398,7 +398,7 @@ value_operand (ex_value_t *value, expr_t *expr) operand_t *op; op = new_operand (op_value, expr, __builtin_return_address (0)); op->type = value->type; - op->o.value = value; + op->value = value; return op; } @@ -407,7 +407,7 @@ temp_operand (type_t *type, expr_t *expr) { operand_t *op = new_operand (op_temp, expr, __builtin_return_address (0)); - op->o.tempop.type = type; + op->tempop.type = type; op->type = type; op->size = type_size (type); return op; @@ -422,10 +422,10 @@ tempop_overlap (tempop_t *t1, tempop_t *t2) int size2 = type_size (t2->type); if (t1->alias) { - offs1 += t1->alias->o.tempop.offset; + offs1 += t1->alias->tempop.offset; } if (t2->alias) { - offs2 += t2->alias->o.tempop.offset; + offs2 += t2->alias->tempop.offset; } if (offs1 <= offs2 && offs1 + size1 >= offs2 + size2) return 2; // t1 fully overlaps t2 @@ -449,7 +449,7 @@ tempop_visit_all (tempop_t *tempop, int overlap, if (top->op_type != op_temp) { internal_error (top->expr, "temp alias of non-temp operand"); } - tempop = &top->o.tempop; + tempop = &top->tempop; if ((ret = visit (tempop, data))) return ret; } else { @@ -459,7 +459,7 @@ tempop_visit_all (tempop_t *tempop, int overlap, if (top->op_type != op_temp) { internal_error (top->expr, "temp alias of non-temp operand"); } - tempop = &top->o.tempop; + tempop = &top->tempop; if (tempop == start_tempop) continue; if (overlap && tempop_overlap (tempop, start_tempop) < overlap) @@ -481,7 +481,7 @@ alias_operand (type_t *type, operand_t *op, expr_t *expr) type_size (type), type_size (op->type)); } aop = new_operand (op_alias, expr, __builtin_return_address (0)); - aop->o.alias = op; + aop->alias = op; aop->type = type; aop->size = type_size (type); return aop; @@ -496,7 +496,7 @@ label_operand (expr_t *label) internal_error (label, "not a label expression"); } lop = new_operand (op_label, label, __builtin_return_address (0)); - lop->o.label = &label->e.label; + lop->label = &label->e.label; return lop; } @@ -595,9 +595,9 @@ sblock_t * statement_get_target (statement_t *s) { if (statement_is_cond (s)) - return s->opb->o.label->dest; + return s->opb->label->dest; if (statement_is_goto (s)) - return s->opa->o.label->dest; + return s->opa->label->dest; return 0; } @@ -614,7 +614,7 @@ statement_get_targetlist (statement_t *s) } else if (statement_is_goto (s)) { count = 1; } else if (statement_is_jumpb (s)) { - table = s->opa->o.def; + table = s->opa->def; count = table->type->t.array.size; } target_list = malloc ((count + 1) * sizeof (sblock_t *)); @@ -708,7 +708,7 @@ operand_address (operand_t *reference, expr_t *e) case op_def: // assumes aliasing is only one level deep which should be the // case - def = reference->o.def; + def = reference->def; if (def->alias) { offset = def->offset; def = def->alias; @@ -717,9 +717,9 @@ operand_address (operand_t *reference, expr_t *e) case op_temp: // assumes aliasing is only one level deep which should be the // case - if (reference->o.tempop.alias) { - offset = reference->o.tempop.offset; - reference = reference->o.tempop.alias; + if (reference->tempop.alias) { + offset = reference->tempop.offset; + reference = reference->tempop.alias; } return value_operand (new_pointer_val (offset, type, 0, reference), e); @@ -1160,33 +1160,33 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } if (aop->op_type == op_temp) { - while (aop->o.tempop.alias) { - aop = aop->o.tempop.alias; + while (aop->tempop.alias) { + aop = aop->tempop.alias; if (aop->op_type != op_temp) internal_error (e, "temp alias of non-temp var"); - if (aop->o.tempop.alias) + if (aop->tempop.alias) bug (e, "aliased temp alias"); } - for (top = aop->o.tempop.alias_ops; top; top = top->next) { - if (top->type == type && top->o.tempop.offset == offset) { + for (top = aop->tempop.alias_ops; top; top = top->next) { + if (top->type == type && top->tempop.offset == offset) { break; } } if (!top) { top = temp_operand (type, e); - top->o.tempop.alias = aop; - top->o.tempop.offset = offset; - top->next = aop->o.tempop.alias_ops; - aop->o.tempop.alias_ops = top; + top->tempop.alias = aop; + top->tempop.offset = offset; + top->next = aop->tempop.alias_ops; + aop->tempop.alias_ops = top; } *op = top; } else if (aop->op_type == op_def) { - def = aop->o.def; + def = aop->def; while (def->alias) def = def->alias; *op = def_operand (alias_def (def, type, offset), 0, e); } else if (aop->op_type == op_value) { - *op = value_operand (aop->o.value, e); + *op = value_operand (aop->value, e); (*op)->type = type; } else { internal_error (e, "invalid alias target: %s: %s", @@ -1919,21 +1919,21 @@ thread_jumps (sblock_t *blocks) continue; s = (statement_t *) sblock->tail; if (statement_is_goto (s)) { - label = &s->opa->o.label; + label = &s->opa->label; if (!(*label)->dest && (*label)->symbol) { error (s->opa->expr, "undefined label `%s'", (*label)->symbol->name); (*label)->symbol = 0; } } else if (statement_is_cond (s)) { - label = &s->opb->o.label; + label = &s->opb->label; } else { continue; } for (l = *label; l->dest && l->dest->statements && statement_is_goto (l->dest->statements); - l = l->dest->statements->opa->o.label) { + l = l->dest->statements->opa->label) { } if (l != *label) { unuse_label (*label); @@ -1986,11 +1986,11 @@ remove_dead_blocks (sblock_t *blocks) s = (statement_t *) sblock->tail; if (statement_is_cond (s) && sb->statements && statement_is_goto (sb->statements) - && s->opb->o.label->dest == sb->next) { + && s->opb->label->dest == sb->next) { debug (0, "merging if/goto %p %p", sblock, sb); - unuse_label (s->opb->o.label); - s->opb->o.label = sb->statements->opa->o.label; - s->opb->o.label->used++; + unuse_label (s->opb->label); + s->opb->label = sb->statements->opa->label; + s->opb->label->used++; invert_conditional (s); sb->reachable = 0; for (sb = sb->next; sb; sb = sb->next) @@ -2013,9 +2013,9 @@ remove_dead_blocks (sblock_t *blocks) if (sb->statements) { s = (statement_t *) sb->tail; if (statement_is_goto (s)) - label = s->opa->o.label; + label = s->opa->label; else if (statement_is_cond (s)) - label = s->opb->o.label; + label = s->opb->label; } unuse_label (label); did_something = 1; @@ -2038,7 +2038,7 @@ search_for_super_dealloc (sblock_t *sblock) continue; } if (st->opa->op_type != op_def - || strcmp (st->opa->o.def->name, "obj_msgSend_super") != 0) { + || strcmp (st->opa->def->name, "obj_msgSend_super") != 0) { continue; } // FIXME this is messy (calls should have their own expression @@ -2149,9 +2149,9 @@ count_temp (operand_t *op) if (!op) return; if (op->op_type == op_temp) { - while (op->o.tempop.alias) - op = op->o.tempop.alias; - op->o.tempop.users++; + while (op->tempop.alias) + op = op->tempop.alias; + op->tempop.users++; } } From 22c67fc268f3363ecea63133484238d3a8d38fe0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Dec 2021 12:42:15 +0900 Subject: [PATCH 2037/3664] [qfcc] Use flow analysis for dealloc check I decided that the check for whether control reaches the end of the function without performing some necessary action (eg, invoking [super dealoc] in a derived -dealoc) is conceptually the return statement using a pseudo operand and the necessary action defining that pseudo operand and thus is the same as checking for uninitialised variables. Thus, add a pseudo operand type and use one to represent the invocation of [super alloc], with a special function to call when the "used" pseudo operand is "uninitialised". While I currently don't know what else pseudo operands could be used for, the system should be flexible enough to add any check. Fixes #24 --- tools/qfcc/include/function.h | 1 + tools/qfcc/include/statements.h | 14 +++++ tools/qfcc/source/emit.c | 2 + tools/qfcc/source/flow.c | 96 +++++++++++++++++++++++++++------ tools/qfcc/source/statements.c | 78 +++++++++++++++++++++++++-- 5 files changed, 173 insertions(+), 18 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 947e4f3b5..48a82f9e9 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -97,6 +97,7 @@ typedef struct function_s { struct statement_s **statements; int num_statements; int pseudo_addr;///< pseudo address space for flow analysis + struct pseudoop_s *pseudo_ops;///< pseudo operands used by this function } function_t; extern function_t *current_func; diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index d87f4fce5..bc15244c6 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -39,8 +39,11 @@ typedef enum { op_temp, op_alias, op_nil, + op_pseudo, } op_type_e; +struct expr_s; + typedef struct tempop_s { struct def_s *def; int offset; @@ -53,6 +56,13 @@ typedef struct tempop_s { int flowaddr; ///< "address" of temp in flow analysis, != 0 } tempop_t; +typedef struct pseudoop_s { + struct pseudoop_s *next; + const char *name; + struct flowvar_s *flowvar; + void (*uninitialized) (struct expr_s *expr, struct pseudoop_s *op); +} pseudoop_t; + typedef struct operand_s { struct operand_s *next; op_type_e op_type; @@ -66,6 +76,7 @@ typedef struct operand_s { struct ex_label_s *label; tempop_t tempop; struct operand_s *alias; + pseudoop_t *pseudoop; }; } operand_t; @@ -101,6 +112,9 @@ typedef struct statement_s { operand_t *opc; struct expr_s *expr; ///< source expression for this statement int number; ///< number of this statement in function + operand_t *use; ///< list of pseudo operands used + operand_t *def; ///< list of pseudo operands defined + operand_t *kill; ///< list of pseudo operands killed } statement_t; typedef struct sblock_s { diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index bec1d9320..5a7dd129a 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -121,6 +121,8 @@ get_operand_def (expr_t *expr, operand_t *op) return get_operand_def (expr, op->alias); case op_nil: internal_error (expr, "unexpected nil operand"); + case op_pseudo: + internal_error (expr, "unexpected pseudo operand"); } internal_error (expr, "unexpected operand"); return 0; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 4c4e6dedb..37d0c1814 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -283,6 +283,8 @@ flowvar_get_def (flowvar_t *var) internal_error (op->expr, "unexpected alias operand"); case op_nil: internal_error (op->expr, "unexpected nil operand"); + case op_pseudo: + internal_error (op->expr, "unexpected pseudo operand"); } internal_error (op->expr, "oops, blue pill"); return 0; @@ -311,6 +313,11 @@ flow_get_var (operand_t *op) op->def->flowvar = new_flowvar (); return op->def->flowvar; } + if (op->op_type == op_pseudo) { + if (!op->pseudoop->flowvar) + op->pseudoop->flowvar = new_flowvar (); + return op->pseudoop->flowvar; + } return 0; } @@ -349,6 +356,27 @@ count_operand (operand_t *op) return 0; } +static int +count_operand_chain (operand_t *op) +{ + int count = 0; + while (op) { + count += count_operand (op); + op = op->next; + } + return count; +} + +/** Allocate flow analysis pseudo address space. + */ +static int +get_pseudo_address (function_t *func, int size) +{ + int addr = func->pseudo_addr; + func->pseudo_addr += size; + return addr; +} + /** Allocate flow analysis pseudo address space to a temporary variable. * * If the operand already has an address allocated (flowvar_t::flowaddr is @@ -376,8 +404,7 @@ get_temp_address (function_t *func, operand_t *op) top = top->tempop.alias; } if (!top->tempop.flowaddr) { - top->tempop.flowaddr = func->pseudo_addr; - func->pseudo_addr += top->size; + top->tempop.flowaddr = get_pseudo_address (func, top->size); } if (top->tempop.offset) { internal_error (top->expr, "real tempop with a non-zero offset"); @@ -412,7 +439,9 @@ add_operand (function_t *func, operand_t *op) var->number = func->num_vars++; var->op = op; func->vars[var->number] = var; - if (op->op_type == op_temp) { + if (op->op_type == op_pseudo) { + var->flowaddr = get_pseudo_address (func, 1); + } else if (op->op_type == op_temp) { var->flowaddr = get_temp_address (func, op); } else if (flowvar_is_local (var)) { var->flowaddr = func->num_statements + def_offset (var->op->def); @@ -420,6 +449,15 @@ add_operand (function_t *func, operand_t *op) } } +static void +add_operand_chain (function_t *func, operand_t *op) +{ + while (op) { + add_operand (func, op); + op = op->next; + } +} + /** Create symbols and defs for params/return if not already available. */ static symbol_t * @@ -528,7 +566,7 @@ flow_build_vars (function_t *func) // First, run through the statements making sure any accessed variables // have their flowvars reset. Local variables will be fine, but global - // variables make have had flowvars added in a previous function, and it's + // variables may have had flowvars added in a previous function, and it's // easier to just clear them all. // This is done before .return and .param so they won't get reset just // after being counted @@ -556,6 +594,10 @@ flow_build_vars (function_t *func) flow_analyze_statement (s, 0, 0, 0, operands); for (j = 0; j < 4; j++) num_vars += count_operand (operands[j]); + // count any pseudo operands referenced by the statement + num_vars += count_operand_chain (s->use); + num_vars += count_operand_chain (s->def); + num_vars += count_operand_chain (s->kill); } if (!num_vars) return; @@ -580,6 +622,9 @@ flow_build_vars (function_t *func) flow_analyze_statement (s, 0, 0, 0, operands); for (j = 0; j < 4; j++) add_operand (func, operands[j]); + add_operand_chain (func, s->use); + add_operand_chain (func, s->def); + add_operand_chain (func, s->kill); } // and set the use/def sets for the vars (has to be a separate pass // because the allias handling reqruires the flow address to be valid @@ -892,15 +937,24 @@ flow_uninit_scan_statements (flownode_t *node, set_t *defs, set_t *uninit) for (var_i = set_first (stuse); var_i; var_i = set_next (var_i)) { var = node->graph->func->vars[var_i->element]; if (set_is_intersecting (defs, var->define)) { - def_t *def = flowvar_get_def (var); - if (def) { - if (options.warnings.uninited_variable) { - warning (st->expr, "%s may be used uninitialized", - def->name); + if (var->op->op_type == op_pseudo) { + pseudoop_t *op = var->op->pseudoop; + if (op->uninitialized) { + op->uninitialized (st->expr, op); + } else { + internal_error (0, "pseudoop uninitialized not set"); } } else { - bug (st->expr, "st %d, uninitialized temp %s", - st->number, operand_string (var->op)); + def_t *def = flowvar_get_def (var); + if (def) { + if (options.warnings.uninited_variable) { + warning (st->expr, "%s may be used uninitialized", + def->name); + } + } else { + bug (st->expr, "st %d, uninitialized temp %s", + st->number, operand_string (var->op)); + } } } // avoid repeat warnings in this node @@ -1063,7 +1117,7 @@ flow_add_op_var (set_t *set, operand_t *op, int is_use) // defs properly, but I am as yet uncertain of how. if (op->op_type == op_temp) { tempop_visit_all (&op->tempop, ol, flow_tempop_add_aliases, set); - } else { + } else if (op->op_type == op_def) { def_visit_all (op->def, ol, flow_def_add_aliases, set); } } @@ -1099,12 +1153,24 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, operand_t *aux_op1 = 0; operand_t *aux_op2 = 0; - if (use) + if (use) { set_empty (use); - if (def) + for (operand_t *op = s->use; op; op = op->next) { + flow_add_op_var (use, op, 1); + } + } + if (def) { set_empty (def); - if (kill) + for (operand_t *op = s->def; op; op = op->next) { + flow_add_op_var (def, op, 0); + } + } + if (kill) { set_empty (kill); + for (operand_t *op = s->kill; op; op = op->next) { + flow_add_op_var (kill, op, 0); + } + } if (operands) { for (i = 0; i < FLOW_OPERANDS; i++) operands[i] = 0; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index efc9ce2b0..ecd759818 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -70,6 +70,7 @@ const char *op_type_names[] = { "op_temp", "op_alias", "op_nil", + "op_pseudo", }; const char *st_type_names[] = { @@ -183,7 +184,9 @@ operand_string (operand_t *op) buf); } case op_nil: - return va (0, "nil"); + return "nil"; + case op_pseudo: + return va (0, "pseudo: %s", op->pseudoop->name); } return ("??"); } @@ -260,6 +263,9 @@ _print_operand (operand_t *op) case op_nil: printf ("nil"); break; + case op_pseudo: + printf ("pseudo: %s", op->pseudoop->name); + break; } } @@ -270,6 +276,20 @@ print_operand (operand_t *op) puts (""); } +static void +print_operand_chain (const char *name, operand_t *op) +{ + if (op) { + printf (" %s:", name); + while (op) { + printf (" "); + _print_operand (op); + op = op->next; + } + printf ("\n"); + } +} + void print_statement (statement_t *s) { @@ -283,8 +303,12 @@ print_statement (statement_t *s) if (s->opc) _print_operand (s->opc); printf (")\n"); + print_operand_chain ("use", s->use); + print_operand_chain ("def", s->def); + print_operand_chain ("kill", s->kill); } +static pseudoop_t *pseudoops_freelist; static sblock_t *sblocks_freelist; static statement_t *statements_freelist; static operand_t *operands_freelist; @@ -319,6 +343,16 @@ new_statement (st_type_t type, const char *opcode, expr_t *expr) return statement; } +static pseudoop_t * +new_pseudoop (const char *name) +{ + pseudoop_t *pseudoop; + ALLOC (256, pseudoop_t, pseudoops, pseudoop); + pseudoop->name = save_string (name); + return pseudoop; + +} + static operand_t * new_operand (op_type_e op, expr_t *expr, void *return_addr) { @@ -359,6 +393,16 @@ free_sblock (sblock_t *sblock) FREE (sblocks, sblock); } +static operand_t * +pseudo_operand (pseudoop_t *pseudoop, expr_t *expr) +{ + operand_t *op; + op = new_operand (op_pseudo, expr, __builtin_return_address (0)); + op->pseudoop = pseudoop; + op->size = 1; + return op; +} + operand_t * nil_operand (type_t *type, expr_t *expr) { @@ -729,6 +773,7 @@ operand_address (operand_t *reference, expr_t *e) case op_value: case op_label: case op_nil: + case op_pseudo: break; } internal_error (e, "invalid operand type for operand address: %s", @@ -2029,11 +2074,31 @@ remove_dead_blocks (sblock_t *blocks) return did_anything; } +static void +super_dealloc_warning (expr_t *expr, pseudoop_t *op) +{ + warning (expr, + "control may reach end of derived -dealloc without invoking %s", + op->name); +} + static void search_for_super_dealloc (sblock_t *sblock) { + operand_t *op; + pseudoop_t *super_dealloc = new_pseudoop ("[super dealloc]"); + int super_dealloc_found = 0; + super_dealloc->next = current_func->pseudo_ops; + current_func->pseudo_ops = super_dealloc; + super_dealloc->uninitialized = super_dealloc_warning; while (sblock) { for (statement_t *st = sblock->statements; st; st = st->next) { + if (statement_is_return (st)) { + op = pseudo_operand (super_dealloc, st->expr); + op->next = st->use; + st->use = op; + continue; + } if (!statement_is_call (st)) { continue; } @@ -2056,13 +2121,20 @@ search_for_super_dealloc (sblock_t *sblock) if (arg && arg->next && is_selector (arg)) { selector_t *sel = get_selector (st->expr->e.expr.e2); if (sel && strcmp (sel->name, "dealloc") == 0) { - return; + op = pseudo_operand (super_dealloc, st->expr); + op->next = st->use; + st->def = op; + super_dealloc_found++; } } } sblock = sblock->next; } - warning (0, "Derived class -dealloc does not call [super dealloc]"); + // warn only when NOT optimizing because flow analysis will catch the + // missed invokation + if (!super_dealloc_found && !options.code.optimize) { + warning (0, "Derived class -dealloc does not call [super dealloc]"); + } } static void From c11a930436c411153b16f49be23d904b16cd5136 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Dec 2021 12:22:46 +0900 Subject: [PATCH 2038/3664] [simd] Set the homogeneous coord in the csvf test The homogeneous coord was not being initialized and thus was picking up rubbish from the stack. This is why the test would succeed in some circumstances but fail in others. --- libs/util/test/test-csvf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/util/test/test-csvf.c b/libs/util/test/test-csvf.c index 5f56f18c0..305b103ac 100644 --- a/libs/util/test/test-csvf.c +++ b/libs/util/test/test-csvf.c @@ -103,6 +103,7 @@ main (int argc, const char **argv) for (j = 0; j < 4; j++) { VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), cloud[j]); + cloud[j][3] = 1; } cc = CircumSphere_vf (cloud, 4); if (cc.radius < 0) { From e062163aa4356c1f5b242fc242f4740f5d17b95c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Dec 2021 12:50:46 +0900 Subject: [PATCH 2039/3664] [simd] Remove some intrinsics dependencies Not sure why I used intrinsics at the time. Probably wasn't comfortable getting gcc to do what I wanted. --- include/QF/simd/vec4f.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 4cf370101..6bb0ae4ec 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -110,11 +110,7 @@ vabsf (vec4f_t v) { const uint32_t nan = ~0u >> 1; const vec4i_t abs = { nan, nan, nan, nan }; -#ifndef __SSE__ return (vec4f_t) ((vec4i_t) v & abs); -#else - return _mm_and_ps (v, (__m128) abs); -#endif } #ifndef IMPLEMENT_VEC4F_Funcs @@ -319,11 +315,7 @@ vec4f_t qconjf (vec4f_t q) { const vec4i_t neg = { 1u << 31, 1u << 31, 1u << 31, 0 }; -#ifndef __SSE__ return (vec4f_t) ((vec4i_t) q ^ neg); -#else - return _mm_xor_ps (q, (__m128) neg); -#endif } #ifndef IMPLEMENT_VEC4F_Funcs From 88249a2e3342575dfa57979efce1ce983f9169a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Aug 2010 10:00:56 +0900 Subject: [PATCH 2040/3664] add pvs culling --- qtv/include/server.h | 1 + qtv/source/client.c | 58 +++++++++++++++++++++++++++++++++++++------ qtv/source/sv_parse.c | 1 + 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/qtv/include/server.h b/qtv/include/server.h index 7752228a1..96b67426d 100644 --- a/qtv/include/server.h +++ b/qtv/include/server.h @@ -84,6 +84,7 @@ typedef struct server_s { char *soundlist[MAX_SOUNDS + 1]; char *modellist[MAX_MODELS + 1]; char *lightstyles[MAX_LIGHTSTYLES]; + struct model_s *worldmodel; int playermodel; int num_signon_buffers; int signon_buffer_size[MAX_SIGNON_BUFFERS]; diff --git a/qtv/source/client.c b/qtv/source/client.c index 5e28eafa6..0d39e6c95 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -976,13 +976,57 @@ emit_entities (client_t *client, packet_entities_t *to, sizebuf_t *msg) MSG_WriteShort (msg, 0); // end of packetentities } +static byte fatpvs[MAX_MAP_LEAFS / 8]; +int fatbytes; + +static void +add_to_fat_pvs (vec3_t org, mnode_t *node, server_t *sv) +{ + byte *pvs; + int i; + float d; + mplane_t *plane; + + while (1) { + // if this is a leaf, accumulate the pvs bits + if (node->contents < 0) { + if (node->contents != CONTENTS_SOLID) { + pvs = Mod_LeafPVS ((mleaf_t *) node, sv->worldmodel); + for (i = 0; i < fatbytes; i++) + fatpvs[i] |= pvs[i]; + } + return; + } + + plane = node->plane; + d = DotProduct (org, plane->normal) - plane->dist; + if (d > 8) + node = node->children[0]; + else if (d < -8) + node = node->children[1]; + else { // go down both + add_to_fat_pvs (org, node->children[0], sv); + node = node->children[1]; + } + } +} + +static byte * +fat_pvs (vec3_t org, server_t *sv) +{ + fatbytes = (sv->worldmodel->numleafs + 31) >> 3; + memset (fatpvs, 0, fatbytes); + add_to_fat_pvs (org, sv->worldmodel->nodes, sv); + return fatpvs; +} + static void write_entities (client_t *client, sizebuf_t *msg) { - //byte *pvs = 0; - //int i; + byte *pvs = 0; + int i; int e; - //vec3_t org; + vec3_t org; frame_t *frame; entity_state_t *ent; entity_state_t *state; @@ -993,9 +1037,9 @@ write_entities (client_t *client, sizebuf_t *msg) frame = &client->frames[client->netchan.incoming_sequence & UPDATE_MASK]; // find the client's PVS - //clent = client->edict; - //VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org); - //pvs = SV_FatPVS (org); + VectorCopy (client->state.origin, org); + org[2] += 22; //XXX standard spectator view offset + pvs = fat_pvs (org, sv); // put other visible entities into either a packet_entities or a nails // message @@ -1010,7 +1054,6 @@ write_entities (client_t *client, sizebuf_t *msg) continue; if (ent->number && ent->number != e) qtv_printf ("%d %d\n", e, ent->number); -#if 0 if (pvs) { // ignore if not touching a PV leaf for (i = 0; i < ent->num_leafs; i++) @@ -1020,7 +1063,6 @@ write_entities (client_t *client, sizebuf_t *msg) if (i == ent->num_leafs) continue; // not visible } -#endif // if (SV_AddNailUpdate (ent)) // continue; // added to the special update list diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index fcf5c3616..53419b61a 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -214,6 +214,7 @@ sv_skins_f (server_t *sv) // actual in-game update messages MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); MSG_WriteString (&sv->netchan.message, va (0, "begin %d", sv->spawncount)); + sv->worldmodel = Mod_ForName (sv->modelllist[1], false); sv->next_run = realtime; sv->connected = 2; sv->delta = -1; From 7694ae29ccea15b19601fba56e7b5eb20329b739 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 30 Jun 2012 21:44:43 +0900 Subject: [PATCH 2041/3664] a compile fix --- qtv/source/sv_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index 53419b61a..37162cdc8 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -214,7 +214,7 @@ sv_skins_f (server_t *sv) // actual in-game update messages MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); MSG_WriteString (&sv->netchan.message, va (0, "begin %d", sv->spawncount)); - sv->worldmodel = Mod_ForName (sv->modelllist[1], false); + sv->worldmodel = Mod_ForName (sv->modellist[1], false); sv->next_run = realtime; sv->connected = 2; sv->delta = -1; From 0ba00652a1646230e587415cf21e4e37cff2a7c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 Jul 2012 09:00:01 +0900 Subject: [PATCH 2042/3664] some work on getting pvs compiling --- qtv/include/server.h | 12 +++++++++- qtv/source/client.c | 2 +- qtv/source/sv_parse.c | 56 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/qtv/include/server.h b/qtv/include/server.h index 96b67426d..5e74de519 100644 --- a/qtv/include/server.h +++ b/qtv/include/server.h @@ -57,6 +57,16 @@ typedef struct frame_s { packet_entities_t entities; } frame_t; +typedef struct qtv_leaf_s { + struct qtv_leaf_s *next; + int num; +} qtv_leaf_t; + +typedef struct { + entity_state_t e; + qtv_leaf_t *leafs; +} qtv_entity_t; + #define MAX_SV_PLAYERS 32 #define MAX_SV_ENTITIES 512 #define MAX_SIGNON_BUFFERS 8 @@ -96,7 +106,7 @@ typedef struct server_s { int validsequence; frame_t frames[UPDATE_BACKUP]; - entity_state_t entities[MAX_SV_ENTITIES]; + qtv_entity_t entities[MAX_SV_ENTITIES]; byte ent_valid[MAX_SV_ENTITIES]; entity_state_t baselines[MAX_SV_ENTITIES]; player_t players[MAX_SV_PLAYERS]; diff --git a/qtv/source/client.c b/qtv/source/client.c index 0d39e6c95..2ee08a3df 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -985,7 +985,7 @@ add_to_fat_pvs (vec3_t org, mnode_t *node, server_t *sv) byte *pvs; int i; float d; - mplane_t *plane; + plane_t *plane; while (1) { // if this is a leaf, accumulate the pvs bits diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index 37162cdc8..08c97588a 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -61,6 +61,54 @@ #include "qtv/include/qtv.h" #include "qtv/include/server.h" +#define QTV_LEAFS 32 +typedef struct qtv_leaf_bucket_s { + struct qtv_leaf_bucket_s *next; + qtv_leaf_t qtv_leafs[QTV_LEAFS]; +} qtv_leaf_bucket_t; + +static qtv_leaf_bucket_t *qtv_leaf_buckets; +static qtv_leaf_bucket_t **qtv_leaf_bucket_tail = &qtv_leaf_buckets; +static qtv_leaf_t *free_qtv_leaf_list; + +static qtv_leaf_t * +alloc_qtv_leaf (void) +{ + qtv_leaf_bucket_t *bucket; + qtv_leaf_t *leaf; + int i; + + if ((leaf = free_qtv_leaf_list)) { + free_qtv_leaf_list = leaf->next; + leaf->next = 0; + return leaf; + } + + bucket = malloc (sizeof (qtv_leaf_bucket_t)); + bucket->next = 0; + *qtv_leaf_bucket_tail = bucket; + qtv_leaf_bucket_tail = &bucket->next; + + for (leaf = bucket->qtv_leafs, i = 0; i < QTV_LEAFS - 1; i++, leaf++) + leaf->next = leaf + 1; + leaf->next = 0; + free_qtv_leaf_list = bucket->qtv_leafs; + + return alloc_qtv_leaf (); +} + +static void +free_qtv_leafs (qtv_leaf_t **leafs) +{ + qtv_leaf_t **l; + + for (l = leafs; *l; l = &(*l)->next) + ; + *l = free_qtv_leaf_list; + free_qtv_leaf_list = *leafs; + *leafs = 0; +} + static void sv_serverdata (server_t *sv, qmsg_t *msg) { @@ -430,7 +478,7 @@ sv_packetentities (server_t *sv, qmsg_t *msg, int delta) } newp->entities[newindex] = oldp->entities[oldindex]; num = newp->entities[newindex].number; - sv->entities[num] = newp->entities[newindex]; + sv->entities[num].e = newp->entities[newindex]; sv->ent_valid[num] = 1; newindex++; oldindex++; @@ -457,7 +505,7 @@ sv_packetentities (server_t *sv, qmsg_t *msg, int delta) } newp->entities[newindex] = oldp->entities[oldindex]; num = newp->entities[newindex].number; - sv->entities[num] = newp->entities[newindex]; + sv->entities[num].e = newp->entities[newindex]; sv->ent_valid[num] = 1; newindex++; oldindex++; @@ -484,7 +532,7 @@ sv_packetentities (server_t *sv, qmsg_t *msg, int delta) } newp->entities[newindex] = sv->baselines[newnum]; sv_parse_delta (msg, word, &newp->entities[newindex]); - sv->entities[newnum] = newp->entities[newindex]; + sv->entities[newnum].e = newp->entities[newindex]; newindex++; continue; } @@ -500,7 +548,7 @@ sv_packetentities (server_t *sv, qmsg_t *msg, int delta) } newp->entities[newindex] = oldp->entities[oldindex]; sv_parse_delta (msg, word, &newp->entities[newindex]); - sv->entities[newnum] = newp->entities[newindex]; + sv->entities[newnum].e = newp->entities[newindex]; sv->ent_valid[newnum] = 1; newindex++; oldindex++; From 046b9600d52b8e11c6dc123e219964af3b788266 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Dec 2021 14:45:32 +0900 Subject: [PATCH 2043/3664] [qtv] Fix a pile of bit-rot qtv compiles again after rebasing. I doubt the changes actually work. --- qtv/include/server.h | 1 + qtv/source/Makemodule.am | 1 + qtv/source/client.c | 52 ++++++++++++++++++++-------------------- qtv/source/sv_parse.c | 48 +++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 26 deletions(-) diff --git a/qtv/include/server.h b/qtv/include/server.h index 5e74de519..e4a6f8915 100644 --- a/qtv/include/server.h +++ b/qtv/include/server.h @@ -95,6 +95,7 @@ typedef struct server_s { char *modellist[MAX_MODELS + 1]; char *lightstyles[MAX_LIGHTSTYLES]; struct model_s *worldmodel; + struct set_s *fatpvs; int playermodel; int num_signon_buffers; int signon_buffer_size[MAX_SIGNON_BUFFERS]; diff --git a/qtv/source/Makemodule.am b/qtv/source/Makemodule.am index 07af0ad6f..5997596fe 100644 --- a/qtv/source/Makemodule.am +++ b/qtv/source/Makemodule.am @@ -35,6 +35,7 @@ qtv_LIBS= \ @server_static_plugin_libs@ \ libs/qw/libqw.a \ libs/net/libnet_chan.la \ + libs/models/libQFmodels.la \ libs/console/libQFconsole.la \ libs/ui/libQFui.la \ libs/util/libQFutil.la diff --git a/qtv/source/client.c b/qtv/source/client.c index 2ee08a3df..5feee07d7 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -48,6 +48,7 @@ #include "QF/hash.h" #include "QF/idparse.h" #include "QF/info.h" +#include "QF/set.h" #include "QF/sys.h" #include "QF/va.h" @@ -976,14 +977,9 @@ emit_entities (client_t *client, packet_entities_t *to, sizebuf_t *msg) MSG_WriteShort (msg, 0); // end of packetentities } -static byte fatpvs[MAX_MAP_LEAFS / 8]; -int fatbytes; - static void -add_to_fat_pvs (vec3_t org, mnode_t *node, server_t *sv) +add_to_fat_pvs (vec4f_t org, mnode_t *node, server_t *sv) { - byte *pvs; - int i; float d; plane_t *plane; @@ -991,9 +987,8 @@ add_to_fat_pvs (vec3_t org, mnode_t *node, server_t *sv) // if this is a leaf, accumulate the pvs bits if (node->contents < 0) { if (node->contents != CONTENTS_SOLID) { - pvs = Mod_LeafPVS ((mleaf_t *) node, sv->worldmodel); - for (i = 0; i < fatbytes; i++) - fatpvs[i] |= pvs[i]; + set_union (sv->fatpvs, Mod_LeafPVS ((mleaf_t *) node, + sv->worldmodel)); } return; } @@ -1011,24 +1006,28 @@ add_to_fat_pvs (vec3_t org, mnode_t *node, server_t *sv) } } -static byte * -fat_pvs (vec3_t org, server_t *sv) +static set_t * +fat_pvs (vec4f_t org, server_t *sv) { - fatbytes = (sv->worldmodel->numleafs + 31) >> 3; - memset (fatpvs, 0, fatbytes); - add_to_fat_pvs (org, sv->worldmodel->nodes, sv); - return fatpvs; + if (!sv->fatpvs) { + sv->fatpvs = set_new_size (sv->worldmodel->brush.visleafs); + } + set_expand (sv->fatpvs, sv->worldmodel->brush.visleafs); + set_empty (sv->fatpvs); + + add_to_fat_pvs (org, sv->worldmodel->brush.nodes, sv); + return sv->fatpvs; } static void write_entities (client_t *client, sizebuf_t *msg) { - byte *pvs = 0; - int i; + set_t *pvs = 0; int e; - vec3_t org; + vec4f_t org; frame_t *frame; - entity_state_t *ent; + qtv_entity_t *ent; + qtv_leaf_t *el; entity_state_t *state; packet_entities_t *pack; server_t *sv = client->server; @@ -1037,7 +1036,7 @@ write_entities (client_t *client, sizebuf_t *msg) frame = &client->frames[client->netchan.incoming_sequence & UPDATE_MASK]; // find the client's PVS - VectorCopy (client->state.origin, org); + org = client->state.es.origin; org[2] += 22; //XXX standard spectator view offset pvs = fat_pvs (org, sv); @@ -1052,15 +1051,16 @@ write_entities (client_t *client, sizebuf_t *msg) e++, ent++) { if (!sv->ent_valid[e]) continue; - if (ent->number && ent->number != e) - qtv_printf ("%d %d\n", e, ent->number); + if (ent->e.number && ent->e.number != e) + qtv_printf ("%d %d\n", e, ent->e.number); if (pvs) { // ignore if not touching a PV leaf - for (i = 0; i < ent->num_leafs; i++) - if (pvs[ent->leafnums[i] >> 3] & (1 << (ent->leafnums[i] & 7))) + for (el = ent->leafs; el; el = el->next) { + if (set_is_member (pvs, el->num)) break; + } - if (i == ent->num_leafs) + if (!el) continue; // not visible } // if (SV_AddNailUpdate (ent)) @@ -1074,7 +1074,7 @@ write_entities (client_t *client, sizebuf_t *msg) state = &pack->entities[pack->num_entities]; pack->num_entities++; - *state = *ent; + *state = ent->e; state->flags = 0; } // encode the packet entities as a delta from the diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index 08c97588a..f95c484b5 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -109,6 +109,50 @@ free_qtv_leafs (qtv_leaf_t **leafs) *leafs = 0; } +static void +sv_unlink_entity (server_t *sv, qtv_entity_t *ent) +{ + free_qtv_leafs (&ent->leafs); +} + +static void +sv_find_touched_leafs (server_t *sv, qtv_entity_t *ent, mnode_t *node) +{ + if (node->contents == CONTENTS_SOLID) { + return; + } + // add an efrag if the node is a leaf + if (node->contents < 0) { + qtv_leaf_t *ent_leaf = alloc_qtv_leaf (); + ent_leaf->num = (mleaf_t *) node - sv->worldmodel->brush.leafs - 1; + ent_leaf->next = ent->leafs; + ent->leafs = ent_leaf; + return; + } + + vec3_t emins, emaxs; + vec4f_t mins = {-64, -64, -64, 0};//FIXME + vec4f_t maxs = {64, 64, 64, 0}; + VectorAdd (ent->e.origin, mins, emins); + VectorAdd (ent->e.origin, maxs, emaxs); + + plane_t *splitplane = node->plane; + int sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane); + if (sides & 1) { + sv_find_touched_leafs (sv, ent, node->children[0]); + } + if (sides & 2) { + sv_find_touched_leafs (sv, ent, node->children[1]); + } +} + +static void +sv_link_entity (server_t *sv, qtv_entity_t *ent) +{ + sv_unlink_entity (sv, ent); + sv_find_touched_leafs (sv, ent, sv->worldmodel->brush.nodes); +} + static void sv_serverdata (server_t *sv, qmsg_t *msg) { @@ -479,6 +523,7 @@ sv_packetentities (server_t *sv, qmsg_t *msg, int delta) newp->entities[newindex] = oldp->entities[oldindex]; num = newp->entities[newindex].number; sv->entities[num].e = newp->entities[newindex]; + sv_link_entity (sv, &sv->entities[num]); sv->ent_valid[num] = 1; newindex++; oldindex++; @@ -506,6 +551,7 @@ sv_packetentities (server_t *sv, qmsg_t *msg, int delta) newp->entities[newindex] = oldp->entities[oldindex]; num = newp->entities[newindex].number; sv->entities[num].e = newp->entities[newindex]; + sv_link_entity (sv, &sv->entities[num]); sv->ent_valid[num] = 1; newindex++; oldindex++; @@ -533,6 +579,7 @@ sv_packetentities (server_t *sv, qmsg_t *msg, int delta) newp->entities[newindex] = sv->baselines[newnum]; sv_parse_delta (msg, word, &newp->entities[newindex]); sv->entities[newnum].e = newp->entities[newindex]; + sv_link_entity (sv, &sv->entities[newnum]); newindex++; continue; } @@ -549,6 +596,7 @@ sv_packetentities (server_t *sv, qmsg_t *msg, int delta) newp->entities[newindex] = oldp->entities[oldindex]; sv_parse_delta (msg, word, &newp->entities[newindex]); sv->entities[newnum].e = newp->entities[newindex]; + sv_link_entity (sv, &sv->entities[newnum]); sv->ent_valid[newnum] = 1; newindex++; oldindex++; From 1d3970bc38b558875f22206f52b029d04c437330 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Dec 2021 15:01:38 +0900 Subject: [PATCH 2044/3664] [qfcc] Allow extern builtin function declarations build_builtin_function does the right thing, and it was only legacy syntax functions that were affected anyway. Certainly, external variables should not be initialized, but klik uses @extern { } wrapped around several builtin functions and I had added the feature to allow just this as it is rather convenient. --- tools/qfcc/source/qc-parse.y | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 89a7a2405..f75621a17 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1093,9 +1093,6 @@ overloaded_identifier non_code_func : '=' '#' expr { - if ($-1.storage == sc_extern) { - error (0, "initializing external variable"); - } build_builtin_function ($0, $3, 0, $-1.storage); } | '=' expr From c163b311d022e69a1fbc38c11d736eb221ad9c51 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Dec 2021 20:33:37 +0900 Subject: [PATCH 2045/3664] [gamecode] Create hash tables in PR_Init This makes much more sense than in PR_LoadProgsFile (and simplifies the latter, too). --- libs/gamecode/pr_load.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 955242085..55c556aac 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -230,24 +230,9 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) PR_Zone_Init (pr); } - if (pr->function_hash) { - Hash_FlushTable (pr->function_hash); - } else { - pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr, - pr->hashlink_freelist); - } - if (pr->global_hash) { - Hash_FlushTable (pr->global_hash); - } else { - pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr, - pr->hashlink_freelist); - } - if (pr->field_hash) { - Hash_FlushTable (pr->field_hash); - } else { - pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr, - pr->hashlink_freelist); - } + Hash_FlushTable (pr->function_hash); + Hash_FlushTable (pr->global_hash); + Hash_FlushTable (pr->field_hash); // byte swap the lumps for (i = 0; i < pr->progs->numstatements; i++) { @@ -497,6 +482,12 @@ PR_Init (progs_t *pr) PR_Resources_Init (pr); PR_Strings_Init (pr); PR_Debug_Init (pr); + pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr, + pr->hashlink_freelist); + pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr, + pr->hashlink_freelist); + pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr, + pr->hashlink_freelist); } VISIBLE void From c9f372fa385c72fa2f0540b1b843970a0a209195 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Dec 2021 20:35:09 +0900 Subject: [PATCH 2046/3664] [gamecode] Set pr_debug_resources in PR_Debug_Init And use the cached value in PR_LoadDebug. --- libs/gamecode/pr_debug.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 535bcab5b..fa14b9bd7 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -394,7 +394,6 @@ pr_debug_clear (progs_t *pr, void *data) res->linenos = 0; res->local_defs = 0; - pr->pr_debug_resources = res; pr->watch = 0; pr->wp_conditional = 0; pr->wp_val.integer_var = 0; @@ -530,7 +529,7 @@ func_compare_search (const void *_key, const void *_f, void *_res) VISIBLE int PR_LoadDebug (progs_t *pr) { - prdeb_resources_t *res = PR_Resources_Find (pr, "PR_Debug"); + prdeb_resources_t *res = pr->pr_debug_resources; char *sym_path; const char *path_end, *sym_file; off_t debug_size; @@ -543,7 +542,6 @@ PR_LoadDebug (progs_t *pr) qfot_type_t *type; string_t compunit_str; - pr->pr_debug_resources = res; if (!pr_debug->int_val) return 1; @@ -1816,6 +1814,7 @@ PR_Debug_Init (progs_t *pr) pr->hashlink_freelist); PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); + pr->pr_debug_resources = res; } void From dcf8beeccc7539ecd8786fb43947f1b0d40aaaa6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Dec 2021 20:37:01 +0900 Subject: [PATCH 2047/3664] [qfcc] Remove a union wart from qfo_mspace_t --- tools/qfcc/include/obj_file.h | 12 ++--- tools/qfcc/source/dump_globals.c | 10 ++-- tools/qfcc/source/dump_strings.c | 2 +- tools/qfcc/source/linker.c | 46 +++++++++---------- tools/qfcc/source/obj_file.c | 78 ++++++++++++++++---------------- 5 files changed, 74 insertions(+), 74 deletions(-) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 55a93542b..b6ce9653f 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -254,7 +254,7 @@ typedef struct qfo_mspace_s { dstatement_t *code; pr_type_t *data; char *strings; - } d; + }; unsigned data_size; unsigned id; } qfo_mspace_t; @@ -305,7 +305,7 @@ enum { \hideinitializer */ -#define QFO_var(q, s, t, o) ((q)->spaces[s].d.data[o].t##_var) +#define QFO_var(q, s, t, o) ((q)->spaces[s].data[o].t##_var) /** Access a double variable in the object file. Can be assigned to. @@ -318,7 +318,7 @@ enum { \hideinitializer */ -#define QFO_DOUBLE(q, s, o) (*(double *) ((q)->spaces[s].d.data + o)) +#define QFO_DOUBLE(q, s, o) (*(double *) ((q)->spaces[s].data + o)) /** Access a float variable in the object file. Can be assigned to. @@ -380,10 +380,10 @@ enum { \hideinitializer */ -#define QFO_GETSTR(q, s) ((q)->spaces[qfo_strings_space].d.strings + (s)) +#define QFO_GETSTR(q, s) ((q)->spaces[qfo_strings_space].strings + (s)) #define QFO_TYPE(q, t) ((qfot_type_t *) (char *) \ - ((q)->spaces[qfo_type_space].d.data + (t))) + ((q)->spaces[qfo_type_space].data + (t))) /** Retrieve a type string from the object file, converting it to a C string. @@ -399,7 +399,7 @@ enum { #define QFO_TYPEMETA(q, t) QFO_INT (q, qfo_type_space, (t) + 0) #define QFO_TYPETYPE(q, t) QFO_INT (q, qfo_type_space, (t) + 3) -#define QFO_STATEMENT(q, s) ((q)->spaces[qfo_code_space].d.code + (s)) +#define QFO_STATEMENT(q, s) ((q)->spaces[qfo_code_space].code + (s)) /** Access a string global, converting it to a C string. diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 317e70c03..e01005a47 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -325,9 +325,9 @@ qfo_globals (qfo_t *qfo) QFO_GETSTR (qfo, def->name), def->type, QFO_TYPESTR (qfo, def->type)); - if (!(def->flags & QFOD_EXTERNAL) && qfo->spaces[space].d.data) + if (!(def->flags & QFOD_EXTERNAL) && qfo->spaces[space].data) printf (" %d", - qfo->spaces[space].d.data[def->offset].integer_var); + qfo->spaces[space].data[def->offset].integer_var); puts (""); } } @@ -481,7 +481,7 @@ qfo_functions (qfo_t *qfo) locals = &qfo->spaces[func->locals_space]; printf ("%*s%d %p %d %p %d %d\n", 16, "", locals->type, locals->defs, locals->num_defs, - locals->d.data, locals->data_size, locals->id); + locals->data, locals->data_size, locals->id); for (j = 0; j < locals->num_defs; j++) { qfo_def_t *def = locals->defs + j; int offset; @@ -627,10 +627,10 @@ dump_types (progs_t *pr) } memset (spaces, 0, sizeof (spaces)); spaces[qfo_strings_space].type = qfos_string; - spaces[qfo_strings_space].d.strings = pr->pr_strings; + spaces[qfo_strings_space].strings = pr->pr_strings; spaces[qfo_strings_space].data_size = pr->pr_stringsize; spaces[qfo_type_space].type = qfos_type; - spaces[qfo_type_space].d.data = pr->pr_globals + encodings->types; + spaces[qfo_type_space].data = pr->pr_globals + encodings->types; spaces[qfo_type_space].data_size = encodings->size; memset (&qfo, 0, sizeof (qfo)); qfo.spaces = spaces; diff --git a/tools/qfcc/source/dump_strings.c b/tools/qfcc/source/dump_strings.c index ae32856e7..c8507011e 100644 --- a/tools/qfcc/source/dump_strings.c +++ b/tools/qfcc/source/dump_strings.c @@ -94,5 +94,5 @@ qfo_strings (qfo_t *qfo) printf ("no strings\n"); return; } - dump_string_block (space->d.strings, space->data_size); + dump_string_block (space->strings, space->data_size); } diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index d93b1ea60..4b0fb7d74 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -172,7 +172,7 @@ static dstring_t *linker_current_file; #define QFOSTR(q,s) QFO_GETSTR (q, s) #define WORKSTR(s) QFOSTR (work, s) #define QFOTYPE(t) ((qfot_type_t *) (char *) \ - (qfo_type_defs->d.data + (t))) + (qfo_type_defs->data + (t))) #define WORKTYPE(t) ((qfot_type_t *) (char *) \ (work_type_data->data + (t))) @@ -247,7 +247,7 @@ linker_add_string (const char *str) { string_t new; new = strpool_addstr (work_strings, str); - work->spaces[qfo_strings_space].d.strings = work_strings->strings; + work->spaces[qfo_strings_space].strings = work_strings->strings; work->spaces[qfo_strings_space].data_size = work_strings->size; return new; } @@ -268,7 +268,7 @@ alloc_data (int space, int size) if (size <= 0) linker_internal_error ("bad size for alloc_data (): %d", space); offset = defspace_alloc_loc (*work_spaces[space], size); - work->spaces[space].d.data = (*work_spaces[space])->data; + work->spaces[space].data = (*work_spaces[space])->data; work->spaces[space].data_size = (*work_spaces[space])->size; return offset; } @@ -536,11 +536,11 @@ add_defs (qfo_t *qfo, qfo_mspace_t *space, qfo_mspace_t *dest_space, static void add_qfo_strings (qfo_mspace_t *strings) { - const char *str = strings->d.strings; + const char *str = strings->strings; - while ((pr_uint_t) (str - strings->d.strings) < strings->data_size) { + while ((pr_uint_t) (str - strings->strings) < strings->data_size) { linker_add_string (str); - while ((pr_uint_t) (str - strings->d.strings) < strings->data_size + while ((pr_uint_t) (str - strings->strings) < strings->data_size && *str) str++; str++; // advance past the terminating nul @@ -554,8 +554,8 @@ add_qfo_strings (qfo_mspace_t *strings) static void add_code (qfo_mspace_t *code) { - codespace_addcode (work_code, code->d.code, code->data_size); - work->spaces[qfo_code_space].d.code = work_code->code; + codespace_addcode (work_code, code->code, code->data_size); + work->spaces[qfo_code_space].code = work_code->code; work->spaces[qfo_code_space].data_size = work_code->size; } @@ -570,8 +570,8 @@ add_data (int space, qfo_mspace_t *data) if (space < 0 || space >= qfo_num_spaces || !work_spaces[space]) linker_internal_error ("bad space for add_data (): %d", space); if (data->data_size) - defspace_add_data (*work_spaces[space], data->d.data, data->data_size); - work->spaces[space].d.data = (*work_spaces[space])->data; + defspace_add_data (*work_spaces[space], data->data, data->data_size); + work->spaces[space].data = (*work_spaces[space])->data; work->spaces[space].data_size = (*work_spaces[space])->size; } @@ -596,10 +596,10 @@ add_data_space (qfo_t *qfo, qfo_mspace_t *space) ws->type = space->type; if (space->num_defs) add_defs (qfo, space, ws, process_data_def); - if (space->d.data) { + if (space->data) { int size = space->data_size * sizeof (pr_type_t); - ws->d.data = malloc (size); - memcpy (ws->d.data, space->d.data, size); + ws->data = malloc (size); + memcpy (ws->data, space->data, size); } ws->data_size = space->data_size; ws->id = space->id; @@ -630,7 +630,7 @@ make_def (int s, const char *name, type_t *type, unsigned flags, void *val) if (val) memcpy (&def_space->data[def->offset], val, type_size (type) * sizeof (pr_type_t)); - space->d.data = def_space->data; + space->data = def_space->data; space->data_size = def_space->size; ref = get_defref (def, space); @@ -695,25 +695,25 @@ linker_begin (void) work->num_spaces = qfo_num_spaces; work->spaces[qfo_null_space].type = qfos_null; work->spaces[qfo_strings_space].type = qfos_string; - work->spaces[qfo_strings_space].d.strings = work_strings->strings; + work->spaces[qfo_strings_space].strings = work_strings->strings; work->spaces[qfo_strings_space].data_size = work_strings->size; work->spaces[qfo_code_space].type = qfos_code; - work->spaces[qfo_code_space].d.code = work_code->code; + work->spaces[qfo_code_space].code = work_code->code; work->spaces[qfo_code_space].data_size = work_code->size; work->spaces[qfo_near_data_space].type = qfos_data; - work->spaces[qfo_near_data_space].d.data = work_near_data->data; + work->spaces[qfo_near_data_space].data = work_near_data->data; work->spaces[qfo_near_data_space].data_size = work_near_data->size; work->spaces[qfo_far_data_space].type = qfos_data; - work->spaces[qfo_far_data_space].d.data = work_far_data->data; + work->spaces[qfo_far_data_space].data = work_far_data->data; work->spaces[qfo_far_data_space].data_size = work_far_data->size; work->spaces[qfo_entity_space].type = qfos_entity; - work->spaces[qfo_entity_space].d.data = work_entity_data->data; + work->spaces[qfo_entity_space].data = work_entity_data->data; work->spaces[qfo_entity_space].data_size = work_entity_data->size; work->spaces[qfo_type_space].type = qfos_type; - work->spaces[qfo_type_space].d.data = work_type_data->data; + work->spaces[qfo_type_space].data = work_type_data->data; work->spaces[qfo_type_space].data_size = work_type_data->size; work->spaces[qfo_debug_space].type = qfos_debug; - work->spaces[qfo_debug_space].d.data = work_type_data->data; + work->spaces[qfo_debug_space].data = work_type_data->data; work->spaces[qfo_debug_space].data_size = work_type_data->size; for (i = 0; i < qfo_num_spaces; i++) work->spaces[i].id = i; @@ -739,7 +739,7 @@ process_null_space (qfo_t *qfo, qfo_mspace_t *space, int pass) { if (pass != 0) return 0; - if (space->defs || space->num_defs || space->d.data || space->data_size + if (space->defs || space->num_defs || space->data || space->data_size || space->id) { linker_error ("non-null null space"); return 1; @@ -1279,7 +1279,7 @@ build_qfo (void) for (i = 0; i < work->num_spaces; i++) { qfo->spaces[i].type = work->spaces[i].type; qfo->spaces[i].id = work->spaces[i].id; - qfo->spaces[i].d = work->spaces[i].d; + qfo->spaces[i].data = work->spaces[i].data; qfo->spaces[i].data_size = work->spaces[i].data_size; } // allocate space for all relocs and copy in the loose relocs. bound diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 0380d1fbb..43e4e776a 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -198,10 +198,10 @@ qfo_init_string_space (qfo_t *qfo, qfo_mspace_t *space, strpool_t *strings) space->type = qfos_string; space->num_defs = 0; space->defs = 0; - space->d.strings = 0; + space->strings = 0; if (strings->strings) { - space->d.strings = malloc (size); - memcpy (space->d.strings, strings->strings, size); + space->strings = malloc (size); + memcpy (space->strings, strings->strings, size); } space->data_size = strings->size; space->id = qfo_strings_space; @@ -215,10 +215,10 @@ qfo_init_code_space (qfo_t *qfo, qfo_mspace_t *space, codespace_t *code) space->type = qfos_code; space->num_defs = 0; space->defs = 0; - space->d.code = 0; + space->code = 0; if (code->code) { - space->d.code = malloc (size); - memcpy (space->d.code, code->code, size); + space->code = malloc (size); + memcpy (space->code, code->code, size); } space->data_size = code->size; space->id = qfo_code_space; @@ -233,10 +233,10 @@ qfo_init_data_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_data; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = 0; + space->data = 0; if (data->data) { - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); + space->data = malloc (size); + memcpy (space->data, data->data, size); } space->data_size = data->size; } @@ -249,7 +249,7 @@ qfo_init_entity_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_entity; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = 0; + space->data = 0; space->data_size = data->size; space->id = qfo_entity_space; } @@ -263,10 +263,10 @@ qfo_init_type_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_type; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = 0; + space->data = 0; if (data->data) { - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); + space->data = malloc (size); + memcpy (space->data, data->data, size); } space->data_size = data->size; space->id = qfo_type_space; @@ -281,10 +281,10 @@ qfo_init_debug_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->type = qfos_debug; space->defs = *defs; space->num_defs = qfo_encode_defs (qfo, data->defs, defs, relocs); - space->d.data = 0; + space->data = 0; if (data->data) { - space->d.data = malloc (size); - memcpy (space->d.data, data->data, size); + space->data = malloc (size); + memcpy (space->data, data->data, size); } space->data_size = data->size; space->id = qfo_debug_space; @@ -393,20 +393,20 @@ qfo_space_size (qfo_mspace_t *space) case qfos_null: return 0; case qfos_code: - return space->data_size * sizeof (*space->d.code); + return space->data_size * sizeof (*space->code); case qfos_data: - // data size > 0 but d.data == null -> all data is zero - if (!space->d.data) + // data size > 0 but data == null -> all data is zero + if (!space->data) return 0; - return space->data_size * sizeof (*space->d.data); + return space->data_size * sizeof (*space->data); case qfos_string: - return space->data_size * sizeof (*space->d.strings); + return space->data_size * sizeof (*space->strings); case qfos_entity: return 0; case qfos_type: - return space->data_size * sizeof (*space->d.data); + return space->data_size * sizeof (*space->data); case qfos_debug: - return space->data_size * sizeof (*space->d.data); + return space->data_size * sizeof (*space->data); } return 0; } @@ -491,10 +491,10 @@ qfo_write (qfo_t *qfo, const char *filename) if (qfo->spaces[i].defs) spaces[i].defs = LittleLong (qfo->spaces[i].defs - qfo->defs); spaces[i].num_defs = LittleLong (qfo->spaces[i].num_defs); - if (qfo->spaces[i].d.data) { + if (qfo->spaces[i].data) { int space_size = qfo_space_size (qfo->spaces + i); spaces[i].data = LittleLong (space_data - data); - memcpy (space_data, qfo->spaces[i].d.data, space_size); + memcpy (space_data, qfo->spaces[i].data, space_size); qfo_byteswap_space (space_data, qfo->spaces[i].data_size, qfo->spaces[i].type); space_data += RUP (space_size, 16); @@ -586,8 +586,8 @@ qfo_read (QFile *file) qfo->spaces[i].defs = qfo->defs + LittleLong (spaces[i].defs); qfo->spaces[i].data_size = LittleLong (spaces[i].data_size); if (spaces[i].data) { - qfo->spaces[i].d.strings = data + LittleLong (spaces[i].data); - qfo_byteswap_space (qfo->spaces[i].d.data, + qfo->spaces[i].strings = data + LittleLong (spaces[i].data); + qfo_byteswap_space (qfo->spaces[i].data, qfo->spaces[i].data_size, qfo->spaces[i].type); } qfo->spaces[i].id = LittleLong (spaces[i].id); @@ -657,7 +657,7 @@ qfo_delete (qfo_t *qfo) } else { unsigned i; for (i = 0; i < qfo->num_spaces; i++) - free (qfo->spaces[i].d.data); + free (qfo->spaces[i].data); free (qfo->relocs); free (qfo->defs); free (qfo->funcs); @@ -1049,13 +1049,13 @@ qfo_to_progs (qfo_t *qfo, int *size) type_data = globals + type_encodings_start; xdef_data = globals + xdefs_start; - memcpy (strings, qfo->spaces[qfo_strings_space].d.strings, + memcpy (strings, qfo->spaces[qfo_strings_space].strings, qfo->spaces[qfo_strings_space].data_size * sizeof (char)); - qfo->spaces[qfo_strings_space].d.strings = strings; + qfo->spaces[qfo_strings_space].strings = strings; - memcpy (statements, qfo->spaces[qfo_code_space].d.code, + memcpy (statements, qfo->spaces[qfo_code_space].code, qfo->spaces[qfo_code_space].data_size * sizeof (dstatement_t)); - qfo->spaces[qfo_code_space].d.code = statements; + qfo->spaces[qfo_code_space].code = statements; for (i = 0; i < qfo->num_funcs; i++) { dfunction_t *df = functions + i; @@ -1108,19 +1108,19 @@ qfo_to_progs (qfo_t *qfo, int *size) } // copy near data - memcpy (globals, qfo->spaces[qfo_near_data_space].d.data, + memcpy (globals, qfo->spaces[qfo_near_data_space].data, qfo->spaces[qfo_near_data_space].data_size * sizeof (pr_type_t)); - qfo->spaces[qfo_near_data_space].d.data = globals; + qfo->spaces[qfo_near_data_space].data = globals; // clear locals data memset (locals, 0, locals_size * sizeof (pr_type_t)); // copy far data - memcpy (far_data, qfo->spaces[qfo_far_data_space].d.data, + memcpy (far_data, qfo->spaces[qfo_far_data_space].data, qfo->spaces[qfo_far_data_space].data_size * sizeof (pr_type_t)); - qfo->spaces[qfo_far_data_space].d.data = far_data; + qfo->spaces[qfo_far_data_space].data = far_data; // copy type data - memcpy (type_data, qfo->spaces[qfo_type_space].d.data, + memcpy (type_data, qfo->spaces[qfo_type_space].data, qfo->spaces[qfo_type_space].data_size * sizeof (pr_type_t)); - qfo->spaces[qfo_type_space].d.data = type_data; + qfo->spaces[qfo_type_space].data = type_data; qfo_relocate_refs (qfo); if (types_def) { @@ -1287,7 +1287,7 @@ qfo_to_sym (qfo_t *qfo, int *size) pr_def_t *prdef = &debug_defs[i]; qfo_def_to_prdef (qfo, def, prdef); } - memcpy (debug_data, qfo->spaces[qfo_debug_space].d.data, + memcpy (debug_data, qfo->spaces[qfo_debug_space].data, sym->debug_data_size * sizeof (*debug_data)); return sym; } From 5588d0de604fb8d279ab3c86ffa8595448d457b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Dec 2021 22:39:37 +0900 Subject: [PATCH 2048/3664] [gamecode] Separate debug byte-swap and pointer init PR_LoadDebug now does only the initial version and crc checks, and the byte-swapping of the loaded symbols file. PR_DebugSetSym sets up all the pointers. --- include/QF/progs.h | 1 + libs/gamecode/pr_debug.c | 219 +++++++++++++++++++++------------------ 2 files changed, 120 insertions(+), 100 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 734fb192b..28e62fbe2 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1743,6 +1743,7 @@ typedef struct type_view_s { void PR_Debug_Init (progs_t *pr); void PR_Debug_Init_Cvars (void); +void PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug); int PR_LoadDebug (progs_t *pr); const char *PR_Debug_GetBaseDirectory (progs_t *pr, const char *file); void PR_Debug_Watch (progs_t *pr, const char *expr); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index fa14b9bd7..c65760f08 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -526,6 +526,80 @@ func_compare_search (const void *_key, const void *_f, void *_res) return key->line - f_line; } +VISIBLE void +PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) +{ + prdeb_resources_t *res = pr->pr_debug_resources; + + res->auxfunctions = (pr_auxfunction_t*)((char*)debug + debug->auxfunctions); + res->linenos = (pr_lineno_t*)((char*)debug + debug->linenos); + res->local_defs = (pr_def_t*)((char*)debug + debug->locals); + res->debug_defs = (pr_def_t*)((char*)debug + debug->debug_defs); + res->debug_data = (pr_type_t*)((char*)debug + debug->debug_data); + + size_t size; + size = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); + res->auxfunction_map = pr->allocate_progs_mem (pr, size); + size = pr->progs->numfunctions * sizeof (func_t); + res->sorted_functions = pr->allocate_progs_mem (pr, size); + + for (pr_uint_t i = 0; i < pr->progs->numfunctions; i++) { + res->auxfunction_map[i] = 0; + res->sorted_functions[i] = i; + } + + qfot_type_encodings_t *encodings = 0; + pointer_t type_encodings = 0; + res->type_encodings_def = PR_FindGlobal (pr, ".type_encodings"); + if (res->type_encodings_def) { + encodings = &G_STRUCT (pr, qfot_type_encodings_t, + res->type_encodings_def->ofs); + type_encodings = encodings->types; + } + + for (pr_uint_t i = 0; i < debug->num_auxfunctions; i++) { + if (type_encodings) { + res->auxfunctions[i].return_type += type_encodings; + } + res->auxfunction_map[res->auxfunctions[i].function] = + &res->auxfunctions[i]; + } + qsort_r (res->sorted_functions, pr->progs->numfunctions, sizeof (func_t), + func_compare_sort, res); + + for (pr_uint_t i = 0; i < debug->num_locals; i++) { + if (type_encodings) { + res->local_defs[i].type_encoding += type_encodings; + } + } + + string_t compunit_str = PR_FindString (pr, ".compile_unit"); + for (pr_uint_t i = 0; i < debug->num_debug_defs; i++) { + pr_def_t *def = &res->debug_defs[i]; + if (type_encodings) { + def->type_encoding += type_encodings; + } + Hash_Add (res->debug_syms, def); + if (def->name == compunit_str) { + process_compunit (res, def); + } + } + + if (encodings) { + qfot_type_t *type; + for (pointer_t type_ptr = 4; type_ptr < encodings->size; + type_ptr += type->size) { + type = &G_STRUCT (pr, qfot_type_t, type_encodings + type_ptr); + if (type->meta == ty_basic + && type->type >= 0 && type->type < ev_type_count) { + res->type_encodings[type->type] = type; + } + } + } + + res->debug = debug; +} + VISIBLE int PR_LoadDebug (progs_t *pr) { @@ -536,11 +610,9 @@ PR_LoadDebug (progs_t *pr) pr_uint_t i; pr_def_t *def; pr_type_t *str = 0; - qfot_type_encodings_t *encodings = 0; - pointer_t type_encodings = 0; - pointer_t type_ptr; - qfot_type_t *type; - string_t compunit_str; + pr_debug_header_t *debug; + + res->debug = 0; if (!pr_debug->int_val) return 1; @@ -557,123 +629,70 @@ PR_LoadDebug (progs_t *pr) sym_path = malloc (strlen (sym_file) + (path_end - pr->progs_name) + 1); strncpy (sym_path, pr->progs_name, path_end - pr->progs_name); strcpy (sym_path + (path_end - pr->progs_name), sym_file); - res->debug = pr->load_file (pr, sym_path, &debug_size); - if (!res->debug) { + debug = pr->load_file (pr, sym_path, &debug_size); + if (!debug) { Sys_Printf ("can't load %s for debug info\n", sym_path); free (sym_path); return 1; } - res->debug->version = LittleLong (res->debug->version); - if (res->debug->version != PROG_DEBUG_VERSION) { + debug->version = LittleLong (debug->version); + if (debug->version != PROG_DEBUG_VERSION) { Sys_Printf ("ignoring %s with unsupported version %x.%03x.%03x\n", sym_path, - (res->debug->version >> 24) & 0xff, - (res->debug->version >> 12) & 0xfff, - res->debug->version & 0xfff); - res->debug = 0; + (debug->version >> 24) & 0xff, + (debug->version >> 12) & 0xfff, + debug->version & 0xfff); free (sym_path); return 1; } - res->debug->crc = LittleShort (res->debug->crc); - if (res->debug->crc != pr->crc) { + debug->crc = LittleShort (debug->crc); + if (debug->crc != pr->crc) { Sys_Printf ("ignoring %s that doesn't match %s. (CRCs: " "sym:%d dat:%d)\n", - sym_path, - pr->progs_name, - res->debug->crc, - pr->crc); - res->debug = 0; + sym_path, pr->progs_name, debug->crc, pr->crc); free (sym_path); return 1; } free (sym_path); - res->debug->you_tell_me_and_we_will_both_know = LittleShort - (res->debug->you_tell_me_and_we_will_both_know); - res->debug->auxfunctions = LittleLong (res->debug->auxfunctions); - res->debug->num_auxfunctions = LittleLong (res->debug->num_auxfunctions); - res->debug->linenos = LittleLong (res->debug->linenos); - res->debug->num_linenos = LittleLong (res->debug->num_linenos); - res->debug->locals = LittleLong (res->debug->locals); - res->debug->num_locals = LittleLong (res->debug->num_locals); - res->debug->debug_defs = LittleLong (res->debug->debug_defs); - res->debug->num_debug_defs = LittleLong (res->debug->num_debug_defs); - res->debug->debug_data = LittleLong (res->debug->debug_data); - res->debug->debug_data_size = LittleLong (res->debug->debug_data_size); + debug->you_tell_me_and_we_will_both_know = LittleShort + (debug->you_tell_me_and_we_will_both_know); + debug->auxfunctions = LittleLong (debug->auxfunctions); + debug->num_auxfunctions = LittleLong (debug->num_auxfunctions); + debug->linenos = LittleLong (debug->linenos); + debug->num_linenos = LittleLong (debug->num_linenos); + debug->locals = LittleLong (debug->locals); + debug->num_locals = LittleLong (debug->num_locals); + debug->debug_defs = LittleLong (debug->debug_defs); + debug->num_debug_defs = LittleLong (debug->num_debug_defs); + debug->debug_data = LittleLong (debug->debug_data); + debug->debug_data_size = LittleLong (debug->debug_data_size); - res->auxfunctions = (pr_auxfunction_t*)((char*)res->debug + - res->debug->auxfunctions); - res->linenos = (pr_lineno_t*)((char*)res->debug + res->debug->linenos); - res->local_defs = (pr_def_t*)((char*)res->debug + res->debug->locals); - res->debug_defs = (pr_def_t*)((char*)res->debug + res->debug->debug_defs); - res->debug_data = (pr_type_t*)((char*)res->debug + res->debug->debug_data); - - i = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); - res->auxfunction_map = pr->allocate_progs_mem (pr, i); - i = pr->progs->numfunctions * sizeof (func_t); - res->sorted_functions = pr->allocate_progs_mem (pr, i); - for (i = 0; i < pr->progs->numfunctions; i++) { - res->auxfunction_map[i] = 0; - res->sorted_functions[i] = i; + __auto_type auxfuncs = (pr_auxfunction_t*)((char*)debug + + debug->auxfunctions); + for (i = 0; i < debug->num_auxfunctions; i++) { + auxfuncs[i].function = LittleLong (auxfuncs[i].function); + auxfuncs[i].source_line = LittleLong (auxfuncs[i].source_line); + auxfuncs[i].line_info = LittleLong (auxfuncs[i].line_info); + auxfuncs[i].local_defs = LittleLong (auxfuncs[i].local_defs); + auxfuncs[i].num_locals = LittleLong (auxfuncs[i].num_locals); } - res->type_encodings_def = PR_FindGlobal (pr, ".type_encodings"); - if (res->type_encodings_def) { - encodings = &G_STRUCT (pr, qfot_type_encodings_t, - res->type_encodings_def->ofs); - type_encodings = encodings->types; + __auto_type linenos = (pr_lineno_t*)((char*)debug + debug->linenos); + for (i = 0; i < debug->num_linenos; i++) { + linenos[i].fa.func = LittleLong (linenos[i].fa.func); + linenos[i].line = LittleLong (linenos[i].line); } - for (i = 0; i < res->debug->num_auxfunctions; i++) { - res->auxfunctions[i].function = LittleLong - (res->auxfunctions[i].function); - res->auxfunctions[i].source_line = LittleLong - (res->auxfunctions[i].source_line); - res->auxfunctions[i].line_info = LittleLong - (res->auxfunctions[i].line_info); - res->auxfunctions[i].local_defs = LittleLong - (res->auxfunctions[i].local_defs); - res->auxfunctions[i].num_locals = LittleLong - (res->auxfunctions[i].num_locals); - if (type_encodings) { - res->auxfunctions[i].return_type += type_encodings; - } - res->auxfunction_map[res->auxfunctions[i].function] = - &res->auxfunctions[i]; + __auto_type local_defs = (pr_def_t*)((char*)debug + debug->locals); + for (i = 0; i < debug->num_locals; i++) { + byteswap_def (&local_defs[i]); } - for (i = 0; i < res->debug->num_linenos; i++) { - res->linenos[i].fa.func = LittleLong (res->linenos[i].fa.func); - res->linenos[i].line = LittleLong (res->linenos[i].line); - } - qsort_r (res->sorted_functions, pr->progs->numfunctions, sizeof (func_t), - func_compare_sort, res); - for (i = 0; i < res->debug->num_locals; i++) { - byteswap_def (&res->local_defs[i]); - if (type_encodings) { - res->local_defs[i].type_encoding += type_encodings; - } - } - compunit_str = PR_FindString (pr, ".compile_unit"); - for (i = 0; i < res->debug->num_debug_defs; i++) { - pr_def_t *def = &res->debug_defs[i]; - byteswap_def (def); - if (type_encodings) { - def->type_encoding += type_encodings; - } - Hash_Add (res->debug_syms, def); - if (def->name == compunit_str) { - process_compunit (res, def); - } - } - if (encodings) { - for (type_ptr = 4; type_ptr < encodings->size; - type_ptr += type->size) { - type = &G_STRUCT (pr, qfot_type_t, type_encodings + type_ptr); - if (type->meta == ty_basic - && type->type >= 0 && type->type < ev_type_count) { - res->type_encodings[type->type] = type; - } - } + __auto_type debug_defs = (pr_def_t*)((char*)debug + debug->locals); + for (i = 0; i < debug->num_debug_defs; i++) { + byteswap_def (&debug_defs[i]); } + + PR_DebugSetSym (pr, debug); return 1; } From f373192a023eaaa2ba49e59987dbc09b6ec10cf1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Dec 2021 22:46:07 +0900 Subject: [PATCH 2049/3664] [gamecode] Set pr_string_resources in PR_Strings_Init Like for debug, this is the most sensible place as the pointer will never change. --- libs/gamecode/pr_strings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index d1093c455..ba53acac8 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -226,7 +226,6 @@ pr_strings_clear (progs_t *pr, void *data) res->rs_slot = rs; } - pr->pr_string_resources = res; pr->pr_xtstr = 0; } @@ -1227,4 +1226,5 @@ PR_Strings_Init (progs_t *pr) res->print_str = dstring_new (); PR_Resources_Register (pr, "Strings", res, pr_strings_clear); + pr->pr_string_resources = res; } From 3059aa797904bfb70372446d6124dd330b1f5b4d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 00:25:08 +0900 Subject: [PATCH 2050/3664] [qfcc] Preserve input qfo data in qfo_to_progs qfo_to_progs was modifying the space data pointers in the input qfo, making it impossible to reuse the qfo. However, qfo_relocate_refs needs the updated pointers, thus do a shallow copy of the qfo and its spaces (but not any of the data) --- tools/qfcc/include/obj_file.h | 2 +- tools/qfcc/source/obj_file.c | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index b6ce9653f..630659276 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -486,7 +486,7 @@ qfo_t *qfo_read (QFile *file); */ qfo_t *qfo_open (const char *filename); -dprograms_t *qfo_to_progs (qfo_t *qfo, int *size); +dprograms_t *qfo_to_progs (qfo_t *in_qfo, int *size); pr_debug_header_t *qfo_to_sym (qfo_t *qfo, int *size); /** Create a new ::qfo_t struct diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 43e4e776a..afe295961 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -919,7 +919,7 @@ qfo_def_compare (const void *i1, const void *i2, void *d) } dprograms_t * -qfo_to_progs (qfo_t *qfo, int *size) +qfo_to_progs (qfo_t *in_qfo, int *size) { byte *data; char *strings; @@ -949,6 +949,14 @@ qfo_to_progs (qfo_t *qfo, int *size) unsigned *far_def_indices; unsigned *field_def_indices; + qfo_t *qfo = alloca (sizeof (qfo_t) + + in_qfo->num_spaces * sizeof (qfo_mspace_t)); + *qfo = *in_qfo; + qfo->spaces = (qfo_mspace_t *) (qfo + 1); + for (i = 0; i < qfo->num_spaces; i++) { + qfo->spaces[i] = in_qfo->spaces[i]; + } + *size = RUP (sizeof (dprograms_t), 16); progs = calloc (1, *size); progs->version = options.code.progsversion; From 95991e0d77cf7368fb58993f15f9d6b4f7867b18 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 00:47:35 +0900 Subject: [PATCH 2051/3664] [qfcc] Check switch test expression early Avoids a segfault when the test expression has errors. --- tools/qfcc/source/switch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 77f490c76..e1b6d4aa7 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -395,6 +395,10 @@ struct expr_s * switch_expr (switch_block_t *switch_block, expr_t *break_label, expr_t *statements) { + if (switch_block->test->type == ex_error) { + return switch_block->test; + } + case_label_t **labels, **l; case_label_t _default_label; case_label_t *default_label = &_default_label; @@ -406,10 +410,6 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, int saved_line = pr.source_line; string_t saved_file = pr.source_file; - if (switch_block->test->type == ex_error) { - return switch_block->test; - } - pr.source_line = sw_val->line = switch_block->test->line; pr.source_file = sw_val->file = switch_block->test->file; From 6368791d2b7a8881f6f67569a97c6a22f19d4262 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 13:47:55 +0900 Subject: [PATCH 2052/3664] [gamecode] Check entity_var is valid before display Even NUM_FOR_BAD_EDICT will have a bad day if the edict pointer is invalid, so make sure that the entity pointer is valid (within the edict area AND a multiple of edict size). --- libs/gamecode/pr_debug.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index c65760f08..dc7fb401f 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1252,7 +1252,9 @@ pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, void *_data) progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - if (pr->pr_edicts) { + if (pr->pr_edicts && value->entity_var >= 0 + && value->entity_var < pr->max_edicts + && !(value->entity_var % pr->pr_edict_size)) { edict_t *edict = PROG_TO_EDICT (pr, value->entity_var); if (edict) { dasprintf (dstr, "entity %d", NUM_FOR_BAD_EDICT (pr, edict)); From cafc6a541f11c96cb704571ff58e459211b82843 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 13:50:49 +0900 Subject: [PATCH 2053/3664] [gamecode] Get PR_Profile working The switch from using pr_functions (dfunction_t) to function_table (bfunction_t) for keeping track of the current function (and thus profiling data) broke PR_Profile as it never saw anything but 0. --- include/QF/progs.h | 2 +- libs/gamecode/pr_debug.c | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 28e62fbe2..3f6ad6ae3 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1196,7 +1196,7 @@ typedef struct { pr_int_t first_statement; pr_int_t parm_start; pr_int_t locals; - pr_int_t profile; + pr_uint_t profile; pr_int_t numparms; dparmsize_t parm_size[MAX_PARMS]; dfunction_t *descriptor; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index dc7fb401f..22c8e8e5b 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1712,23 +1712,26 @@ VISIBLE void PR_Profile (progs_t * pr) { pr_uint_t max, num, i; - dfunction_t *best, *f; + dfunction_t *f; + bfunction_t *best, *bf; num = 0; do { max = 0; best = NULL; for (i = 0; i < pr->progs->numfunctions; i++) { - f = &pr->pr_functions[i]; - if (f->profile > max) { - max = f->profile; - best = f; + bf = &pr->function_table[i]; + if (bf->profile > max) { + max = bf->profile; + best = bf; } } if (best) { - if (num < 10) + if (num < 10) { + f = pr->pr_functions + (best - pr->function_table); Sys_Printf ("%7i %s\n", best->profile, - PR_GetString (pr, best->s_name)); + PR_GetString (pr, f->s_name)); + } num++; best->profile = 0; } From 44dd183d554c68946f417e2c0a8dea60a7648658 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 14:15:51 +0900 Subject: [PATCH 2054/3664] [qfcc] Make it a little easier to see extra info instead of having to find an #if 0, just uncomment the define. --- tools/qfcc/source/dot_sblock.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_sblock.c b/tools/qfcc/source/dot_sblock.c index 80f292e61..eaca92300 100644 --- a/tools/qfcc/source/dot_sblock.c +++ b/tools/qfcc/source/dot_sblock.c @@ -54,6 +54,8 @@ #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" +//#define SHOW_SETS + static void flow_statement (dstring_t *dstr, statement_t *s) { @@ -63,7 +65,7 @@ flow_statement (dstring_t *dstr, statement_t *s) dasprintf (dstr, "%s", html_string(operand_string (s->opa))); dasprintf (dstr, "%s", html_string(operand_string (s->opb))); dasprintf (dstr, "%s", html_string(operand_string (s->opc))); -#if 0 +#ifdef SHOW_SETS if (s->number >= 0) { set_t *use = set_new (); set_t *def = set_new (); @@ -106,6 +108,12 @@ dot_sblock (dstring_t *dstr, sblock_t *sblock, int blockno) for (l = sblock->labels; l; l = l->next) dasprintf (dstr, " %s(%d)\n", l->name, l->used); dasprintf (dstr, " \n"); +#ifdef SHOW_SETS + dasprintf (dstr, " use\n"); + dasprintf (dstr, " def\n"); + dasprintf (dstr, " kill\n"); + dasprintf (dstr, " ops\n"); +#endif dasprintf (dstr, " \n"); for (s = sblock->statements; s; s = s->next) flow_statement (dstr, s); From 4ad84b3786c918044314a0f5d0a62cef23adde7d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 14:17:12 +0900 Subject: [PATCH 2055/3664] [qfcc] Add a test for use/write dependencies I ran into this with frikbot causing an infinite loop due to incorrectly linked objects. --- tools/qfcc/test/Makemodule.am | 11 +++++++++ tools/qfcc/test/link_order.r | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tools/qfcc/test/link_order.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 057382f75..d5929e0a6 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -30,6 +30,7 @@ test_progs_dat=\ tools/qfcc/test/gcd.dat \ tools/qfcc/test/infloop.dat \ tools/qfcc/test/ivar-struct-return.dat \ + tools/qfcc/test/link_order.dat \ tools/qfcc/test/methodparams.dat \ tools/qfcc/test/modulo.dat \ tools/qfcc/test/nilparamret.dat \ @@ -370,6 +371,16 @@ tools/qfcc/test/ivar-struct-return.run: $(qfcc_test_run_deps) include $(ivar_struct_return_dep) # am--include-marker r_depfiles_remade += $(ivar_struct_return_dep) +tools_qfcc_test_link_order_dat_SOURCES=tools/qfcc/test/link_order.r +link_order_obj=$(tools_qfcc_test_link_order_dat_SOURCES:.r=.o) +link_order_dep=$(call qcautodep,$(tools_qfcc_test_link_order_dat_SOURCES)) +tools/qfcc/test/link_order.dat$(EXEEXT): $(link_order_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(link_order_obj) +tools/qfcc/test/link_order.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(link_order_dep) # am--include-marker +r_depfiles_remade += $(link_order_dep) + tools_qfcc_test_methodparams_dat_SOURCES=tools/qfcc/test/methodparams.r methodparams_obj=$(tools_qfcc_test_methodparams_dat_SOURCES:.r=.o) methodparams_dep=$(call qcautodep,$(tools_qfcc_test_methodparams_dat_SOURCES)) diff --git a/tools/qfcc/test/link_order.r b/tools/qfcc/test/link_order.r new file mode 100644 index 000000000..9b0cdc73b --- /dev/null +++ b/tools/qfcc/test/link_order.r @@ -0,0 +1,44 @@ +#pragma bug die +#include "test-harness.h" + +typedef struct link_s { + int something; + struct link_s *next; +} link_t; + +link_t * +link_objs(link_t **array, int count) +{ + link_t *obj = nil, *o; + while (count-- > 0) { + o = array[count]; + o.next = obj; + obj = o; + } + return obj; +} + +link_t link_a; +link_t link_b; +link_t *links[2]; + +int +main () +{ + links[0] = &link_a; + links[1] = &link_b; + link_t *chain = link_objs (links, 2); + if (chain != &link_a) { + printf ("chain doesn't point to link_a\n"); + return 1; + } + if (chain.next != &link_b) { + printf ("chain.next doesn't point to link_b\n"); + return 1; + } + if (chain.next.next != nil) { + printf ("chain.next.next isn't nil\n"); + return 1; + } + return 0; +} From 843390501529299ef7d227f2e32b74e939f0cc99 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 14:25:55 +0900 Subject: [PATCH 2056/3664] [qfcc] Extend reachable to the label node's parents While using just the label node's reachable set was sufficient for a simple swap (t = a; a = b; b = t;), it is not sufficient for read-before-write dependencies such as found in linked-list building: { o = array[ind]; o.next = obj; obj = o; } The assignment to o.next uses obj, but that use is hidden because obj's reachable nodes does not include o thus assigning o to obj causes the array dereference to be assigned directly to obj and thus o.next winds up pointing to o instead of whatever obj was. The parent nodes of obj's node are its users, so any new assigned to obj must come after those parents as well as any node reachable by obj's node. Fixes a runaway loop error when adding a frikbot to the server. --- tools/qfcc/source/dags.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index fea637564..202c9a51a 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -642,9 +642,23 @@ dagnode_attach_label (dag_t *dag, dagnode_t *n, daglabel_t *l) if (l->dagnode) { dagnode_t *node = l->dagnode; set_remove (node->identifiers, l->number); - if (set_is_member (node->reachable, n->number)) { + + // If the target node (n) is reachable by the label's node or its + // parents, then attaching the label's node to the target node would + // cause the label's node to be written before it used. + set_t *reachable = set_new (); + set_assign (reachable, node->reachable); + for (set_iter_t *node_iter = set_first (node->parents); node_iter; + node_iter = set_next (node_iter)) { + dagnode_t *p = dag->nodes[node_iter->element]; + set_union (reachable, p->reachable); + } + int is_reachable = set_is_member (reachable, n->number); + set_delete (reachable); + if (is_reachable) { return 0; } + set_add (n->edges, node->number); dagnode_set_reachable (dag, n); } From 57dbd7ed72bf188f9be7009c62526e0caef70d1d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 16:59:21 +0900 Subject: [PATCH 2057/3664] [qtv] Load the right model for world For whatever reason, the client puts the models offset by one, but qtv does not. It's much easier to find dm6.bsp than *1 :P --- qtv/source/sv_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index f95c484b5..dc6e5dd12 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -306,7 +306,7 @@ sv_skins_f (server_t *sv) // actual in-game update messages MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); MSG_WriteString (&sv->netchan.message, va (0, "begin %d", sv->spawncount)); - sv->worldmodel = Mod_ForName (sv->modellist[1], false); + sv->worldmodel = Mod_ForName (sv->modellist[0], false); sv->next_run = realtime; sv->connected = 2; sv->delta = -1; From 58bbed722a33eb5068de929a4cba8252b99d8cb4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 17:00:43 +0900 Subject: [PATCH 2058/3664] [qtv] Handle time a little more correctly realtime needs to be set before any other part of qtv runs. Fixes the instant timeouts. --- qtv/source/qtv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index e00bbaf31..7d720ce0a 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -366,10 +366,10 @@ main (int argc, const char *argv[]) Sys_Printf ("Ohayou gozaimasu\n"); while (1) { + realtime = Sys_DoubleTime () + 1; Cbuf_Execute_Stack (qtv_cbuf); Sys_CheckInput (1, net_socket); - realtime = Sys_DoubleTime () + 1; qtv_read_packets (); From 94871671d245890b4ab75baf3e6d5b170540e660 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 17:54:58 +0900 Subject: [PATCH 2059/3664] [qw] Use a callback for netchan logging This gets outgoing packet logging working again. Yay, fill my hard-drive faster ;) --- include/netchan.h | 4 +++ libs/net/net_chan.c | 8 ++--- qw/include/server.h | 5 +++ qw/source/net_packetlog.c | 8 +++++ qw/source/sv_main.c | 73 ++++++++++++++++++++++++++------------- qw/source/sv_qtv.c | 4 +-- 6 files changed, 72 insertions(+), 30 deletions(-) diff --git a/include/netchan.h b/include/netchan.h index f90e4f170..2ef30d896 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -297,6 +297,10 @@ extern int net_blocksend; */ extern double *net_realtime; +/** Callback to log outgoing packets +*/ +extern void (*net_log_packet) (int length, const void *data, netadr_t to); + /** Initialize the netchan system. Currently only sets the qport cvar default to a random value. diff --git a/libs/net/net_chan.c b/libs/net/net_chan.c index 1289866d7..58da40169 100644 --- a/libs/net/net_chan.c +++ b/libs/net/net_chan.c @@ -57,6 +57,7 @@ double *net_realtime; cvar_t *showpackets; cvar_t *showdrop; cvar_t *qport; +void (*net_log_packet) (int length, const void *data, netadr_t to); void @@ -375,9 +376,8 @@ Netchan_Process (netchan_t *chan) void Netchan_SendPacket (int length, const void *data, netadr_t to) { -#if 0 - if (net_packetlog->int_val) - Log_Outgoing_Packet (data, length, 1); -#endif + if (net_log_packet) { + net_log_packet (length, data, to); + } NET_SendPacket (length, data, to); } diff --git a/qw/include/server.h b/qw/include/server.h index c75cfa659..ebe9cf2ce 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -483,6 +483,11 @@ extern struct clip_hull_s *pf_hull_list[]; // sv_main.c // +void SV_OutOfBand (netadr_t adr, unsigned length, byte *data); +void SV_OutOfBandPrint (netadr_t adr, const char *format, ...) + __attribute__ ((format (PRINTF,2,3))); + + client_t *SV_AllocClient (int spectator, int server); void SV_SavePenaltyFilter (client_t *cl, filtertype_t type, double pentime); diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index 3d2c58dc8..72dbe22d0 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -949,13 +949,21 @@ Analyze_Client_Packet (const byte * data, int len, int has_sequence) Net_PacketLog = NULL; } +static void +net_packet_log_f (int length, const void *data, netadr_t to) +{ + Log_Outgoing_Packet (data, length, 1, 1); +} + static void Net_PacketLog_f (cvar_t *var) { if (var->int_val) { Net_LogStart ("qfpacket.log"); + net_log_packet = net_packet_log_f; } else { Net_LogStop (0); + net_log_packet = 0; } } diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 915ea58ea..c97fc8647 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -701,8 +701,8 @@ SVC_GetChallenge (void) } // send it to the client - Netchan_OutOfBandPrint (net_from, "%c%i%s", S2C_CHALLENGE, - svs.challenges[i].challenge, extended); + SV_OutOfBandPrint (net_from, "%c%i%s", S2C_CHALLENGE, + svs.challenges[i].challenge, extended); } client_t * @@ -776,8 +776,8 @@ SVC_DirectConnect (void) } else { version = atoi (s); if (version != PROTOCOL_VERSION) { - Netchan_OutOfBandPrint (net_from, "%c\nServer is version %s.\n", - A2C_PRINT, QW_VERSION); + SV_OutOfBandPrint (net_from, "%c\nServer is version %s.\n", + A2C_PRINT, QW_VERSION); SV_Printf ("* rejected connect from version %i\n", version); return; } @@ -793,8 +793,8 @@ SVC_DirectConnect (void) // Validate the userinfo string. if (!userinfo) { - Netchan_OutOfBandPrint (net_from, "%c\nInvalid userinfo string.\n", - A2C_PRINT); + SV_OutOfBandPrint (net_from, "%c\nInvalid userinfo string.\n", + A2C_PRINT); return; } @@ -803,14 +803,13 @@ SVC_DirectConnect (void) if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr)) { if (challenge == svs.challenges[i].challenge) break; // good - Netchan_OutOfBandPrint (net_from, "%c\nBad challenge.\n", - A2C_PRINT); + SV_OutOfBandPrint (net_from, "%c\nBad challenge.\n", A2C_PRINT); return; } } if (i == MAX_CHALLENGES) { - Netchan_OutOfBandPrint (net_from, "%c\nNo challenge for address.\n", - A2C_PRINT); + SV_OutOfBandPrint (net_from, "%c\nNo challenge for address.\n", + A2C_PRINT); return; } @@ -826,10 +825,10 @@ SVC_DirectConnect (void) NET_AdrToString (net_from), s, sv_minqfversion->string); - Netchan_OutOfBandPrint (net_from, "%c\nserver requires QuakeForge " - "v%s or greater. Get it from " - "http://www.quakeforge.net/\n", A2C_PRINT, - sv_minqfversion->string); + SV_OutOfBandPrint (net_from, "%c\nserver requires QuakeForge " + "v%s or greater. Get it from " + "http://www.quakeforge.net/\n", A2C_PRINT, + sv_minqfversion->string); return; } } @@ -841,9 +840,9 @@ SVC_DirectConnect (void) !strequal (spectator_password->string, s)) { // failed SV_Printf ("%s: spectator password failed\n", NET_AdrToString (net_from)); - Netchan_OutOfBandPrint (net_from, - "%c\nrequires a spectator password\n\n", - A2C_PRINT); + SV_OutOfBandPrint (net_from, + "%c\nrequires a spectator password\n\n", + A2C_PRINT); return; } Info_RemoveKey (userinfo, "spectator"); // remove passwd @@ -856,9 +855,9 @@ SVC_DirectConnect (void) && !strcaseequal (password->string, "none") && !strequal (password->string, s)) { SV_Printf ("%s:password failed\n", NET_AdrToString (net_from)); - Netchan_OutOfBandPrint (net_from, - "%c\nserver requires a password\n\n", - A2C_PRINT); + SV_OutOfBandPrint (net_from, + "%c\nserver requires a password\n\n", + A2C_PRINT); return; } spectator = false; @@ -886,7 +885,7 @@ SVC_DirectConnect (void) } if (!(newcl = SV_AllocClient (spectator, 0))) { SV_Printf ("%s:full connect\n", NET_AdrToString (adr)); - Netchan_OutOfBandPrint (adr, "%c\nserver is full\n\n", A2C_PRINT); + SV_OutOfBandPrint (adr, "%c\nserver is full\n\n", A2C_PRINT); return; } newcl->userinfo = userinfo; @@ -901,7 +900,7 @@ SVC_DirectConnect (void) } newcl->delta.client = newcl; - Netchan_OutOfBandPrint (adr, "%c", S2C_CONNECTION); + SV_OutOfBandPrint (adr, "%c", S2C_CONNECTION); Netchan_Setup (&newcl->netchan, adr, qport, NC_QPORT_READ); newcl->backbuf.netchan = &newcl->netchan; @@ -1744,6 +1743,32 @@ SV_RestorePenaltyFilter (client_t *cl, filtertype_t type) return 0.0; } +void +SV_OutOfBand (netadr_t adr, unsigned length, byte *data) +{ + if (net_packetlog->int_val) { + Log_Outgoing_Packet (data, length, 0, 1); + } + Netchan_OutOfBand (adr, length, data); +} + +void +SV_OutOfBandPrint (netadr_t adr, const char *format, ...) +{ + static dstring_t *string; + va_list argptr; + + if (!string) { + string = dstring_new (); + } + + va_start (argptr, format); + dvsprintf (string, format, argptr); + va_end (argptr); + + SV_OutOfBand (adr, string->size - 1, (byte *) string->str); +} + static void SV_ReadPackets (void) { @@ -2368,8 +2393,8 @@ SV_ExtractFromUserinfo (client_t *cl) // If the new name was not set (due to the info string being too // long), drop the client. if (strcmp (val, newname)) { - Netchan_OutOfBandPrint (net_from, "%c\nPlease choose a " - "different name.\n", A2C_PRINT); + SV_OutOfBandPrint (net_from, "%c\nPlease choose a " + "different name.\n", A2C_PRINT); SV_ClientPrintf (1, cl, PRINT_HIGH, "Please choose a " "different name.\n"); SV_Printf ("Client %d kicked for having a invalid name\n", diff --git a/qw/source/sv_qtv.c b/qw/source/sv_qtv.c index 91e310114..3b9069ea9 100644 --- a/qw/source/sv_qtv.c +++ b/qw/source/sv_qtv.c @@ -404,7 +404,7 @@ SV_qtvConnect (int qport, info_t *info) if (!(proxy = alloc_proxy ())) { SV_Printf ("%s:full proxy connect\n", NET_AdrToString (net_from)); - Netchan_OutOfBandPrint (net_from, "%c\nserver is full\n\n", A2C_PRINT); + SV_OutOfBandPrint (net_from, "%c\nserver is full\n\n", A2C_PRINT); return; } proxy->info = info; @@ -418,7 +418,7 @@ SV_qtvConnect (int qport, info_t *info) proxy->datagram.maxsize = sizeof (proxy->datagram_buf); proxy->begun = 0; - Netchan_OutOfBandPrint (net_from, "%c", S2C_CONNECTION); + SV_OutOfBandPrint (net_from, "%c", S2C_CONNECTION); } int From 78220ff42054d2afa48038ed473edd2edf9615de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 18:13:44 +0900 Subject: [PATCH 2060/3664] [netchan] Correct type of last_received Storing a double in a float does not go well when that double starts at 4294967296. Fixes the delayed timeouts in qtv. --- include/netchan.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/netchan.h b/include/netchan.h index 2ef30d896..a71902f64 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -229,7 +229,7 @@ typedef enum { typedef struct netchan_s { qboolean fatal_error; ///< True if the message overflowed - float last_received; ///< Time the last packet was received. + double last_received; ///< Time the last packet was received. /// \name statistics /// the statistics are cleared at each client begin, because From 65f78b43acc1b7a4649964383edd2fddbdaccc26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 19:02:39 +0900 Subject: [PATCH 2061/3664] [gamecode] Try to set field def size This fixes the edicts command not printing anything useful. --- libs/gamecode/pr_debug.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 22c8e8e5b..f80913137 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1800,6 +1800,8 @@ ED_Print (progs_t *pr, edict_t *ed, const char *fieldname) if (l >= 2 && name[l - 2] == '_' && strchr ("xyz", name[l - 1])) continue; // skip _x, _y, _z vars + qfot_type_t dummy_type = { }; + get_def_type (pr, d, &dummy_type); for (j = 0; j < d->size; j++) { if (E_INT (ed, d->ofs + j)) { break; From 06d14eb411eea81ee630bb0a70f8656c6de270ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 19:39:34 +0900 Subject: [PATCH 2062/3664] [qtv] Get entity bounds from the model This gets culling working nicely --- qtv/include/server.h | 2 ++ qtv/source/sv_parse.c | 16 ++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/qtv/include/server.h b/qtv/include/server.h index e4a6f8915..624fa82cf 100644 --- a/qtv/include/server.h +++ b/qtv/include/server.h @@ -64,6 +64,8 @@ typedef struct qtv_leaf_s { typedef struct { entity_state_t e; + int model_index; // 1-based + struct model_s *model; qtv_leaf_t *leafs; } qtv_entity_t; diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index dc6e5dd12..2bd8b4cd7 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -131,10 +131,8 @@ sv_find_touched_leafs (server_t *sv, qtv_entity_t *ent, mnode_t *node) } vec3_t emins, emaxs; - vec4f_t mins = {-64, -64, -64, 0};//FIXME - vec4f_t maxs = {64, 64, 64, 0}; - VectorAdd (ent->e.origin, mins, emins); - VectorAdd (ent->e.origin, maxs, emaxs); + VectorAdd (ent->e.origin, ent->model->mins, emins); + VectorAdd (ent->e.origin, ent->model->maxs, emaxs); plane_t *splitplane = node->plane; int sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane); @@ -150,7 +148,13 @@ static void sv_link_entity (server_t *sv, qtv_entity_t *ent) { sv_unlink_entity (sv, ent); - sv_find_touched_leafs (sv, ent, sv->worldmodel->brush.nodes); + if (ent->model_index != ent->e.modelindex) { + ent->model_index = ent->e.modelindex; + ent->model = Mod_ForName (sv->modellist[ent->model_index - 1], false); + } + if (ent->model) { + sv_find_touched_leafs (sv, ent, sv->worldmodel->brush.nodes); + } } static void @@ -269,7 +273,7 @@ sv_modellist (server_t *sv, qmsg_t *msg) } sv->modellist[n] = strdup (str); if (!strcmp (sv->modellist[n], "progs/player.mdl")) - sv->playermodel = n; + sv->playermodel = n + 1; } n = MSG_ReadByte (msg); if (n) { From 1be220559a15bd5b57ec3cb287f49a3c3b0e4e0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 20:12:03 +0900 Subject: [PATCH 2063/3664] [zone] Add function to retrieve memory usage --- include/QF/zone.h | 1 + libs/util/zone.c | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/QF/zone.h b/include/QF/zone.h index 56dbbcc8f..00ff536ab 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -99,6 +99,7 @@ memhunk_t *Memory_Init (void *buf, size_t size); void Z_ClearZone (memzone_t *zone, size_t size, size_t zone_offset, size_t ele_size); +void Z_MemInfo (const memzone_t *zone, size_t *used, size_t *size); void Z_Free (memzone_t *zone, void *ptr); void *Z_Malloc (memzone_t *zone, size_t size); // returns 0 filled memory void *Z_TagMalloc (memzone_t *zone, size_t size, int tag); diff --git a/libs/util/zone.c b/libs/util/zone.c index 98e4febfb..88b3e7ecd 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -382,7 +382,7 @@ Z_SetError (memzone_t *zone, void (*err) (void *, const char *), void *data) zone->data = data; } -void +VISIBLE void Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size) { const memblock_t *block; @@ -405,6 +405,13 @@ Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size) } } +VISIBLE void +Z_MemInfo (const memzone_t *zone, size_t *used, size_t *size) +{ + *used = zone->used; + *size = zone->size; +} + //============================================================================ typedef struct cache_system_s cache_system_t; From 6d6440457a485e0b943a38349217e5992b3799cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 20:25:22 +0900 Subject: [PATCH 2064/3664] [qw] Add progs memory display to server status bar This makes it easy to check for memory leaks before they crash the server. --- qw/source/sv_progs.c | 2 +- qw/source/sv_sbar.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 124a78dd3..84873b352 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -608,7 +608,7 @@ SV_Progs_Init_Cvars (void) sv_progs = Cvar_Get ("sv_progs", "", CVAR_NONE, NULL, "Override the default game progs."); sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL, - "size of the zone for progs in kb"); + "size of the zone for progs in kB"); sv_progs_ext = Cvar_Get ("sv_progs_ext", "qf", CVAR_NONE, NULL, "extention mapping to use: " "none, id, qf, qwe, ktpro, cpqw"); diff --git a/qw/source/sv_sbar.c b/qw/source/sv_sbar.c index 81523ee33..e742b1c35 100644 --- a/qw/source/sv_sbar.c +++ b/qw/source/sv_sbar.c @@ -41,6 +41,7 @@ #include "sv_console.h" #include "qw/include/server.h" +#include "qw/include/sv_progs.h" #include "qw/include/sv_recorder.h" static void @@ -80,6 +81,26 @@ draw_rec (view_t *view) *d++ = *s; } +static void +draw_mem (view_t *view) +{ + sv_view_t *sv_view = view->data; + sv_sbar_t *sb = sv_view->obj; + const char *str; + const char *s; + char *d; + size_t used, size; + byte mask = 0; + + Z_MemInfo (sv_pr_state.zone, &used, &size); + str = va (0, "[mem: %4zd / %-4zd]", used / 1024, size / 1024); + if (used / (size / 256) >= 192) { + mask = 0x80; + } + for (s = str, d = sb->text + view->xrel; *s; s++) + *d++ = *s | mask; +} + void SV_Sbar_Init (void) { @@ -99,4 +120,9 @@ SV_Sbar_Init (void) view->draw = draw_rec; view->data = status->data; view_add (status, view); + + view = view_new (19, 0, 18, 1, grav_northwest); + view->draw = draw_mem; + view->data = status->data; + view_add (status, view); } From 2aae757effc3f2b817a66f5fe5d44163aa9a8955 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 22:54:22 +0900 Subject: [PATCH 2065/3664] [qtv] Set worldmodel just after svc_modellist Not sure why I thought skins_f was a good place. This seems to be much more reliable. --- qtv/source/sv_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index 2bd8b4cd7..ba31950dc 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -310,7 +310,6 @@ sv_skins_f (server_t *sv) // actual in-game update messages MSG_WriteByte (&sv->netchan.message, qtv_stringcmd); MSG_WriteString (&sv->netchan.message, va (0, "begin %d", sv->spawncount)); - sv->worldmodel = Mod_ForName (sv->modellist[0], false); sv->next_run = realtime; sv->connected = 2; sv->delta = -1; @@ -1157,6 +1156,7 @@ sv_parse (server_t *sv, qmsg_t *msg, int reliable) break; case svc_modellist: sv_modellist (sv, msg); + sv->worldmodel = Mod_ForName (sv->modellist[0], false); send = 0; break; From dd17e8120df3b96ceee60633b5696f8f6917f542 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Dec 2021 22:55:29 +0900 Subject: [PATCH 2066/3664] [qw] Clear qtv message buf before writing I'm not sure this is the right place, but it prevents the packet overflowing when a qtv proxy connects to a busy server (12+ bots). --- qw/source/sv_qtv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qw/source/sv_qtv.c b/qw/source/sv_qtv.c index 3b9069ea9..1daf1926d 100644 --- a/qw/source/sv_qtv.c +++ b/qw/source/sv_qtv.c @@ -381,6 +381,7 @@ qtv_reliable_send (sv_qtv_t *proxy) byte *buf = 0; SV_Printf ("proxy->begun: %d\n", proxy->begun); + SZ_Clear (&proxy->netchan.message); if (!proxy->begun) { MSG_WriteByte (&proxy->netchan.message, qtv_packet); pos = proxy->netchan.message.cursize; From 5f4a330b02cf489515cf1d3ae3c6bbc009106e03 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Dec 2021 00:06:12 +0900 Subject: [PATCH 2067/3664] [console] Tweak the server status bar colors Now the yellow stands out nicely. --- libs/console/server.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libs/console/server.c b/libs/console/server.c index 9f7ff0cc1..f553fa67a 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -121,6 +121,7 @@ static int view_offset; #define CP_RED_BLUE (8) #define CP_CYAN_BLUE (9) #define CP_MAGENTA_BLUE (10) +#define CP_WHITE_BLUE (11) static chtype attr_table[16] = { A_NORMAL, @@ -131,13 +132,13 @@ static chtype attr_table[16] = { COLOR_PAIR (CP_CYAN_BLACK), COLOR_PAIR (CP_MAGENTA_BLACK), 0, - A_NORMAL, - COLOR_PAIR (CP_GREEN_BLUE), - COLOR_PAIR (CP_RED_BLUE), + COLOR_PAIR(CP_WHITE_BLUE), + A_BOLD | COLOR_PAIR (CP_GREEN_BLUE), + A_BOLD | COLOR_PAIR (CP_RED_BLUE), 0, - COLOR_PAIR (CP_YELLOW_BLUE), - COLOR_PAIR (CP_CYAN_BLUE), - COLOR_PAIR (CP_MAGENTA_BLUE), + A_BOLD | COLOR_PAIR (CP_YELLOW_BLUE), + A_BOLD | COLOR_PAIR (CP_CYAN_BLUE), + A_BOLD | COLOR_PAIR (CP_MAGENTA_BLUE), 0, }; @@ -276,7 +277,7 @@ draw_status (view_t *view) memset (sb->text, ' ', sb->width); view_draw (view); if (memcmp (old, sb->text, sb->width)) { - wbkgdset (win, COLOR_PAIR (CP_YELLOW_BLUE)); + wbkgdset (win, COLOR_PAIR (CP_WHITE_BLUE)); wmove (win, 0, 0); for (i = 0; i < sb->width; i++) draw_fun_char (win, sb->text[i], 1); @@ -620,6 +621,7 @@ init (void) init_pair (CP_RED_BLUE, COLOR_RED, COLOR_BLUE); init_pair (CP_CYAN_BLUE, COLOR_CYAN, COLOR_BLUE); init_pair (CP_MAGENTA_BLUE, COLOR_MAGENTA, COLOR_BLUE); + init_pair (CP_WHITE_BLUE, COLOR_WHITE, COLOR_BLUE); con_linewidth = screen_x; From 44c48feb56ad5b4facad32d643f132a5e154a0ed Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Dec 2021 09:23:14 +0900 Subject: [PATCH 2068/3664] [qfcc] Add attached node's parents to source edges The assignment to the node's variable must come after any uses of that node, which the node's parent set indicates. In the swap test, this was not a problem as the node had no parents, and in the link order test, it just happened(?) to work. --- tools/qfcc/source/dags.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 202c9a51a..9e3b1cdab 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -659,7 +659,10 @@ dagnode_attach_label (dag_t *dag, dagnode_t *n, daglabel_t *l) return 0; } + // this assignment to the variable must come after any previous uses, + // which includes itself and its parents set_add (n->edges, node->number); + set_union (n->edges, node->parents); dagnode_set_reachable (dag, n); } l->live = 0; // remove live forcing on assignment From 760256c99e85416fcd8414a999f20c5eff790bc1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 29 Dec 2021 21:21:08 +0900 Subject: [PATCH 2069/3664] [qw] Add SV_ClientNumber builtin This is a quick way to find the client number for an entity. It returns -1 if the entity is not a valid client (either outside the client block, or not currently in use by a client). --- qw/source/sv_pr_cmds.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 563e74591..36498b8bd 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -1829,6 +1829,21 @@ PF_sv_cvar (progs_t *pr) } } +// int () SV_ClientNumber +// returns -1 if the entity is not a client (either not in the client range +// or the entity is not in use by a client) +static void +PF_SV_ClientNumber (progs_t *pr) +{ + int entnum = P_EDICTNUM (pr, 0); + client_t *cl = svs.clients + entnum - 1; + + if (entnum < 1 || entnum > MAX_CLIENTS || cl->state != cs_server) { + entnum = 0; // nil entity + } + R_INT (pr) = entnum - 1; +} + // entity () SV_AllocClient static void PF_SV_AllocClient (progs_t *pr) @@ -2017,6 +2032,7 @@ static builtin_t builtins[] = { {"cfeof", PF_cfeof, QF 107}, {"cfquota", PF_cfquota, QF 108}, + {"SV_ClientNumber", PF_SV_ClientNumber, -1}, {"SV_AllocClient", PF_SV_AllocClient, -1}, {"SV_FreeClient", PF_SV_FreeClient, -1}, {"SV_SetUserinfo", PF_SV_SetUserinfo, -1}, From 3c17efe91bbb417b7742fe6b877dca01bea5b878 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 29 Dec 2021 21:50:38 +0900 Subject: [PATCH 2070/3664] [console] Unhook hooked functions on shutdown Forgetting to unhook the functions (Sys_Printf and the client console's input event handler) was not a problem for static builds because the functions were always present, but in builds with dynamic plugins, the client console's code got ripped away and thus Sys_Printf and the event hander were being sent into invalid memory. Too much work, not enough play (with a fully installed client). --- libs/console/client.c | 1 + libs/console/console.c | 7 ++++++- libs/util/sys.c | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libs/console/client.c b/libs/console/client.c index ae3d0649a..c1a9f60ac 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -952,6 +952,7 @@ C_Init (void) static void C_shutdown (void) { + IE_Remove_Handler (con_event_id); } static general_funcs_t plugin_info_general_funcs = { diff --git a/libs/console/console.c b/libs/console/console.c index 5c7323fb0..b75884e71 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -57,6 +57,7 @@ static U void (*const display)(const char **, int) = Con_DisplayList; #undef U static cvar_t *con_interpreter; +static sys_printf_t saved_sys_printf; static void Con_Interp_f (cvar_t *var) @@ -89,6 +90,9 @@ Con_Interp_f (cvar_t *var) static void Con_shutdown (void *data) { + if (saved_sys_printf) { + Sys_SetStdPrintf (saved_sys_printf); + } if (con_module) { con_module->functions->general->shutdown (); PI_UnloadPlugin (con_module); @@ -102,7 +106,8 @@ Con_Init (const char *plugin_name) con_module = PI_LoadPlugin ("console", plugin_name); if (con_module) { - Sys_SetStdPrintf (con_module->functions->console->print); + __auto_type funcs = con_module->functions->console; + saved_sys_printf = Sys_SetStdPrintf (funcs->print); } else { setvbuf (stdout, 0, _IOLBF, BUFSIZ); } diff --git a/libs/util/sys.c b/libs/util/sys.c index 07ed52d05..25120aed2 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -247,6 +247,9 @@ VISIBLE sys_printf_t Sys_SetStdPrintf (sys_printf_t func) { sys_printf_t prev = sys_std_printf_function; + if (!func) { + func = Sys_StdPrintf; + } sys_std_printf_function = func; return prev; } @@ -255,6 +258,9 @@ VISIBLE sys_printf_t Sys_SetErrPrintf (sys_printf_t func) { sys_printf_t prev = sys_err_printf_function; + if (!func) { + func = Sys_ErrPrintf; + } sys_err_printf_function = func; return prev; } From 70aaafda1072caf2a14994d94083191bb359e561 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 30 Dec 2021 00:21:29 +0900 Subject: [PATCH 2071/3664] [ruamoko] Clear dtable list on reset The list of all allocated dispatch tables is used to free all the tables when the progs are reloaded. Not clearing the list meant that the next instance (second map change) corrupted the list. --- libs/ruamoko/rua_obj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index ca81790ac..4bed1de5d 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -110,6 +110,7 @@ static void dtable_reset (probj_t *probj) { PR_RESRESET (probj->dtables); + probj->dtable_list = 0; } static inline dtable_t * From 7a481039f84a302fd9acb991b8520abcfa636328 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 30 Dec 2021 02:02:22 +0900 Subject: [PATCH 2072/3664] [qw] Check tracked player name before printing The server switching levels while the client is tracking a player (at least a server client) seems to at least temporarily clear the player slot and thus the name value pointer becomes null. This fixes the resulting segfault. --- qw/source/sbar.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/qw/source/sbar.c b/qw/source/sbar.c index ecf74c3e3..d8dde4f52 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -829,8 +829,12 @@ draw_spectator (view_t *view) "Press [ATTACK] for AutoCamera"); } else { // Sbar_DrawString (160-14*8+4,4, "SPECTATOR MODE - TRACK CAMERA"); - snprintf (st, sizeof (st), "Tracking %-.13s, [JUMP] for next", - cl.players[spec_track].name->value); + if (cl.players[spec_track].name) { + snprintf (st, sizeof (st), "Tracking %-.13s, [JUMP] for next", + cl.players[spec_track].name->value); + } else { + snprintf (st, sizeof (st), "Lost player, [JUMP] for next"); + } draw_string (view, 0, -8, st); } } From 2dc806cff5cddee716ae4be2f8bb999568a00ebd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 30 Dec 2021 13:26:36 +0900 Subject: [PATCH 2073/3664] [ruamoko] Clean up Entity a little Hide own, and add some class spawn methods. --- ruamoko/include/Entity.h | 6 ++++-- ruamoko/lib/Entity.r | 32 +++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/ruamoko/include/Entity.h b/ruamoko/include/Entity.h index 8ff0f568c..a870e987f 100644 --- a/ruamoko/include/Entity.h +++ b/ruamoko/include/Entity.h @@ -34,10 +34,12 @@ @interface Entity: Object { + int own; @public - entity ent; - int own; + entity ent; } ++(Entity *) spawn; ++(Entity *) withEntity: (entity) e; - (id) init; - (id) initWithEntity: (entity) e; diff --git a/ruamoko/lib/Entity.r b/ruamoko/lib/Entity.r index 3018e5a16..12c465df8 100644 --- a/ruamoko/lib/Entity.r +++ b/ruamoko/lib/Entity.r @@ -15,21 +15,20 @@ int PR_SetField (entity ent, string field, string value) = #0; @implementation Entity -- (void) own -{ - own = 1; -} - - (id) init { - self = [self initWithEntity: spawn ()]; - [self own]; + if (!(self = [self initWithEntity: spawn ()])) { + return nil; + } + own = 1; return self; } - (id) initWithEntity: (entity)e { - self = [super init]; + if (!(self = [super init])) { + return nil; + } ent = e; ent.@this = self; return self; @@ -41,6 +40,21 @@ int PR_SetField (entity ent, string field, string value) = #0; return self; } ++(Entity *) spawn +{ + return [[[self alloc] init] autorelease]; +} + ++(Entity *) withEntity: (entity) e +{ + return [[[self alloc] initWithEntity: e] autorelease]; +} + ++(Entity *) withEntity: (entity) e fromPlist: (plitem_t *) dict +{ + return [[[self alloc] initWithEntity: e fromPlist: dict] autorelease]; +} + - (void) dealloc { if (own && ent) @@ -95,7 +109,7 @@ int PR_SetField (entity ent, string field, string value) = #0; } } if (ent) - [e own]; + e.own = 1; return e; } From 6990bd5752099d1158ed2c30940ffcaf61e33f56 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 31 Dec 2021 14:48:52 +0900 Subject: [PATCH 2074/3664] [gamecode] Add some more comments to dfunction_t --- include/QF/pr_comp.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 0cd65d7e5..9072ea643 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -457,15 +457,15 @@ typedef struct dparmsize_s { typedef struct dfunction_s { pr_int_t first_statement; // negative numbers are builtins - pr_uint_t parm_start; + pr_uint_t parm_start; // beginning of locals data space pr_uint_t locals; // total ints of parms + locals pr_uint_t profile; // runtime - string_t s_name; + string_t s_name; // source function name string_t s_file; // source file defined in - pr_int_t numparms; + pr_int_t numparms; // -ve is varargs (1s comp of real count) dparmsize_t parm_size[MAX_PARMS]; } dfunction_t; From be474d9937ff2a28f141e342fa8b19dd893d9e2c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 31 Dec 2021 15:02:31 +0900 Subject: [PATCH 2075/3664] [gamecode] Remove the wart from def and function names I never liked the leading s_ (though I guess it means one is supposed to interpret the int as a string pointer, but meh). --- include/QF/pr_comp.h | 6 +++--- libs/gamecode/pr_builtins.c | 8 ++++---- libs/gamecode/pr_debug.c | 26 +++++++++++++------------- libs/gamecode/pr_exec.c | 10 +++++----- libs/gamecode/pr_load.c | 18 +++++++++--------- libs/gamecode/pr_parse.c | 2 +- nq/source/sv_pr_cmds.c | 4 ++-- qw/source/sv_pr_cmds.c | 4 ++-- ruamoko/qwaq/builtins/debug.c | 4 ++-- tools/qfcc/source/def.c | 2 +- tools/qfcc/source/disassemble.c | 2 +- tools/qfcc/source/dump_globals.c | 4 ++-- tools/qfcc/source/dump_lines.c | 4 ++-- tools/qfcc/source/idstuff.c | 6 +++--- tools/qfcc/source/obj_file.c | 6 +++--- tools/qfcc/source/qfcc.c | 8 ++++---- 16 files changed, 57 insertions(+), 57 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 9072ea643..ff71cd6fc 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -425,7 +425,7 @@ typedef struct ddef_s { pr_ushort_t type; // if DEF_SAVEGLOBAL bit is set // the variable needs to be saved in savegames pr_ushort_t ofs; - string_t s_name; + string_t name; } ddef_t; typedef struct xdef_s { @@ -462,8 +462,8 @@ typedef struct dfunction_s { pr_uint_t profile; // runtime - string_t s_name; // source function name - string_t s_file; // source file defined in + string_t name; // source function name + string_t file; // source file defined in pr_int_t numparms; // -ve is varargs (1s comp of real count) dparmsize_t parm_size[MAX_PARMS]; diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index b5332db7f..150b43932 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -95,7 +95,7 @@ bi_no_function (progs_t *pr) // descriptor with a bad builtin number dstatement_t *st = pr->pr_statements + pr->pr_xstatement; dfunction_t *desc = pr->pr_functions + G_FUNCTION (pr, st->a); - const char *bi_name = PR_GetString (pr, desc->s_name); + const char *bi_name = PR_GetString (pr, desc->name); int ind = -desc->first_statement; PR_RunError (pr, "Bad builtin called: %s = #%d", bi_name, ind); @@ -201,7 +201,7 @@ PR_RelocateBuiltins (progs_t *pr) if (desc->first_statement > 0) continue; - bi_name = PR_GetString (pr, desc->s_name); + bi_name = PR_GetString (pr, desc->name); if (!desc->first_statement) { bi = PR_FindBuiltin (pr, bi_name); @@ -225,8 +225,8 @@ PR_RelocateBuiltins (progs_t *pr) bi_name, -desc->first_statement); proc = bi_no_function; } - if (!desc->s_name && bi) { - desc->s_name = PR_SetString (pr, bi->name); + if (!desc->name && bi) { + desc->name = PR_SetString (pr, bi->name); Hash_Add (pr->function_hash, &pr->pr_functions[i]); } func->first_statement = desc->first_statement; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index f80913137..f9f743e0d 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -496,8 +496,8 @@ func_compare_sort (const void *_fa, const void *_fb, void *_res) progs_t *pr = res->pr; func_t fa = *(const func_t *)_fa; func_t fb = *(const func_t *)_fb; - const char *fa_file = PR_GetString (pr, pr->pr_functions[fa].s_file); - const char *fb_file = PR_GetString (pr, pr->pr_functions[fb].s_file); + const char *fa_file = PR_GetString (pr, pr->pr_functions[fa].file); + const char *fb_file = PR_GetString (pr, pr->pr_functions[fb].file); int cmp = strcmp (fa_file, fb_file); if (cmp) { return cmp; @@ -516,7 +516,7 @@ func_compare_search (const void *_key, const void *_f, void *_res) progs_t *pr = res->pr; const func_key_t *key = _key; func_t f = *(const func_t *)_f; - const char *f_file = PR_GetString (pr, pr->pr_functions[f].s_file); + const char *f_file = PR_GetString (pr, pr->pr_functions[f].file); int cmp = strcmp (key->file, f_file); if (cmp) { return cmp; @@ -837,7 +837,7 @@ PR_FindSourceLineAddr (progs_t *pr, const char *file, pr_uint_t line) } dfunction_t *func = &pr->pr_functions[*f]; if (func->first_statement <= 0 - || strcmp (file, PR_GetString (pr, func->s_file)) != 0) { + || strcmp (file, PR_GetString (pr, func->file)) != 0) { return 0; } pr_auxfunction_t *aux = res->auxfunction_map[*f]; @@ -869,7 +869,7 @@ PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) f = PR_Get_Lineno_Func (pr, lineno); if (f->function >= (unsigned) pr->progs->numfunctions) return 0; - return PR_GetString(pr, pr->pr_functions[f->function].s_file); + return PR_GetString(pr, pr->pr_functions[f->function].file); } const char * @@ -1292,7 +1292,7 @@ pr_debug_func_view (qfot_type_t *type, pr_type_t *value, void *_data) dstring_appendstr (dstr, "NULL"); } else { dfunction_t *f = pr->pr_functions + value->func_var; - dasprintf (dstr, "%s()", PR_GetString (pr, f->s_name)); + dasprintf (dstr, "%s()", PR_GetString (pr, f->name)); } } @@ -1673,20 +1673,20 @@ dump_frame (progs_t *pr, prstack_t *frame) line += func->source_line; if (addr == frame->staddr) { Sys_Printf ("%12s:%u : %s: %x\n", - PR_GetString (pr, f->s_file), + PR_GetString (pr, f->file), line, - PR_GetString (pr, f->s_name), + PR_GetString (pr, f->name), frame->staddr); } else { Sys_Printf ("%12s:%u+%d : %s: %x\n", - PR_GetString (pr, f->s_file), + PR_GetString (pr, f->file), line, frame->staddr - addr, - PR_GetString (pr, f->s_name), + PR_GetString (pr, f->name), frame->staddr); } } else { - Sys_Printf ("%12s : %s: %x\n", PR_GetString (pr, f->s_file), - PR_GetString (pr, f->s_name), frame->staddr); + Sys_Printf ("%12s : %s: %x\n", PR_GetString (pr, f->file), + PR_GetString (pr, f->name), frame->staddr); } } @@ -1730,7 +1730,7 @@ PR_Profile (progs_t * pr) if (num < 10) { f = pr->pr_functions + (best - pr->function_table); Sys_Printf ("%7i %s\n", best->profile, - PR_GetString (pr, f->s_name)); + PR_GetString (pr, f->name)); } num++; best->profile = 0; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 09d8b9fc8..af7517a92 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -195,7 +195,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Entering function %s\n", - PR_GetString (pr, f->descriptor->s_name)); + PR_GetString (pr, f->descriptor->name)); } PR_PushFrame (pr); @@ -238,7 +238,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) } } - //Sys_Printf("%s:\n", PR_GetString(pr,f->s_name)); + //Sys_Printf("%s:\n", PR_GetString(pr,f->name)); pr->pr_xfunction = f; pr->pr_xstatement = f->first_statement - 1; // offset the st++ @@ -286,14 +286,14 @@ PR_LeaveFunction (progs_t *pr, int to_engine) if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Leaving function %s\n", - PR_GetString (pr, f->descriptor->s_name)); + PR_GetString (pr, f->descriptor->name)); if (to_engine) { Sys_Printf ("Returning to engine\n"); } else { bfunction_t *rf = pr->pr_xfunction; if (rf) { Sys_Printf ("Returning to function %s\n", - PR_GetString (pr, rf->descriptor->s_name)); + PR_GetString (pr, rf->descriptor->name)); } } } @@ -407,7 +407,7 @@ PR_CallFunction (progs_t *pr, func_t fnum) // negative statements are built in functions if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Calling builtin %s @ %p\n", - PR_GetString (pr, f->descriptor->s_name), f->func); + PR_GetString (pr, f->descriptor->name), f->func); } f->func (pr); return 0; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 55c556aac..40f99dd84 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -58,7 +58,7 @@ function_get_key (const void *f, void *_pr) { progs_t *pr = (progs_t*)_pr; dfunction_t *func = (dfunction_t*)f; - return PR_GetString (pr, func->s_name); + return PR_GetString (pr, func->name); } static const char * @@ -247,12 +247,12 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) LittleLong (pr->pr_functions[i].first_statement); pr->pr_functions[i].parm_start = LittleLong (pr->pr_functions[i].parm_start); - pr->pr_functions[i].s_name = LittleLong (pr->pr_functions[i].s_name); - pr->pr_functions[i].s_file = LittleLong (pr->pr_functions[i].s_file); + pr->pr_functions[i].name = LittleLong (pr->pr_functions[i].name); + pr->pr_functions[i].file = LittleLong (pr->pr_functions[i].file); pr->pr_functions[i].numparms = LittleLong (pr->pr_functions[i].numparms); pr->pr_functions[i].locals = LittleLong (pr->pr_functions[i].locals); - if (pr->pr_functions[i].s_name) + if (pr->pr_functions[i].name) Hash_Add (pr->function_hash, &pr->pr_functions[i]); } @@ -265,12 +265,12 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr_ushort_t safe_type = global_ddefs[i].type & ~DEF_SAVEGLOBAL; global_ddefs[i].type = LittleShort (global_ddefs[i].type); global_ddefs[i].ofs = LittleShort (global_ddefs[i].ofs); - global_ddefs[i].s_name = LittleLong (global_ddefs[i].s_name); + global_ddefs[i].name = LittleLong (global_ddefs[i].name); pr->pr_globaldefs[i].type = global_ddefs[i].type; pr->pr_globaldefs[i].size = pr_type_size[safe_type]; pr->pr_globaldefs[i].ofs = global_ddefs[i].ofs; - pr->pr_globaldefs[i].name = global_ddefs[i].s_name; + pr->pr_globaldefs[i].name = global_ddefs[i].name; Hash_Add (pr->global_hash, &pr->pr_globaldefs[i]); } @@ -283,11 +283,11 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) if (field_ddefs[i].type & DEF_SAVEGLOBAL) PR_Error (pr, "PR_LoadProgs: DEF_SAVEGLOBAL on field def %zd", i); field_ddefs[i].ofs = LittleShort (field_ddefs[i].ofs); - field_ddefs[i].s_name = LittleLong (field_ddefs[i].s_name); + field_ddefs[i].name = LittleLong (field_ddefs[i].name); pr->pr_fielddefs[i].type = field_ddefs[i].type; pr->pr_fielddefs[i].ofs = field_ddefs[i].ofs; - pr->pr_fielddefs[i].name = field_ddefs[i].s_name; + pr->pr_fielddefs[i].name = field_ddefs[i].name; Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]); } @@ -365,7 +365,7 @@ pr_run_ctors (progs_t *pr) for (fnum = 0; fnum < pr->progs->numfunctions; fnum++) { func = pr->pr_functions + fnum; - if (strequal (PR_GetString (pr, func->s_name), ".ctor")) + if (strequal (PR_GetString (pr, func->name), ".ctor")) PR_ExecuteProgram (pr, fnum); } return 1; diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index cfc170815..8b4c2d728 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -76,7 +76,7 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) break; case ev_func: f = pr->pr_functions + val->func_var; - dsprintf (line, "%s", PR_GetString (pr, f->s_name)); + dsprintf (line, "%s", PR_GetString (pr, f->name)); break; case ev_field: def = PR_FieldAtOfs (pr, val->integer_var); diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 466fa92cb..8f2262078 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -73,7 +73,7 @@ PF_error (progs_t *pr) s = PF_VarString (pr, 0); Sys_Printf ("======SERVER ERROR in %s:\n%s\n", - PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); + PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); ED_Print (pr, ed, 0); @@ -97,7 +97,7 @@ PF_objerror (progs_t *pr) s = PF_VarString (pr, 0); Sys_Printf ("======OBJECT ERROR in %s:\n%s\n", - PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); + PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); ED_Print (pr, ed, 0); ED_Free (pr, ed); diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 36498b8bd..2e1144780 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -75,7 +75,7 @@ PF_error (progs_t *pr) s = PF_VarString (pr, 0); Sys_Printf ("======SERVER ERROR in %s:\n%s\n", - PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); + PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); ED_Print (pr, ed, 0); @@ -99,7 +99,7 @@ PF_objerror (progs_t *pr) s = PF_VarString (pr, 0); Sys_Printf ("======OBJECT ERROR in %s:\n%s\n", - PR_GetString (pr, pr->pr_xfunction->descriptor->s_name), s); + PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); ED_Print (pr, ed, 0); ED_Free (pr, ed); diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 4826c4166..56aaa818c 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -525,8 +525,8 @@ return_function (progs_t *pr, dfunction_t *func) f->local_data = func->parm_start; f->local_size = func->locals; f->profile = func->profile; - f->name = func->s_name; - f->file = func->s_file; + f->name = func->name; + f->file = func->file; f->num_params = func->numparms; R_POINTER (pr) = PR_SetPointer (pr, f); } diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index df1d36b94..216497a73 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -284,7 +284,7 @@ def_to_ddef (def_t *def, ddef_t *ddef, int aux) type = type->t.fldptr.type; // aux is true only for fields ddef->type = type->type; ddef->ofs = def->offset; - ddef->s_name = ReuseString (def->name); + ddef->name = ReuseString (def->name); } static int diff --git a/tools/qfcc/source/disassemble.c b/tools/qfcc/source/disassemble.c index 7002510bc..60e4765bc 100644 --- a/tools/qfcc/source/disassemble.c +++ b/tools/qfcc/source/disassemble.c @@ -76,7 +76,7 @@ disassemble_progs (progs_t *pr) memcpy (func.parm_size, desc->parm_size, sizeof (func.parm_size)); func.descriptor = desc; - Sys_Printf ("%s:\n", PR_GetString (pr, desc->s_name)); + Sys_Printf ("%s:\n", PR_GetString (pr, desc->name)); pr->pr_xfunction = &func; } PR_PrintStatement (pr, &pr->pr_statements[i], 2 | (verbosity > 1)); diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index e01005a47..ff8f6d32f 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -251,7 +251,7 @@ dump_functions (progs_t *pr) for (i = 0; i < pr->progs->numfunctions; i++) { dfunction_t *func = &pr->pr_functions[i]; - name = PR_GetString (pr, func->s_name); + name = PR_GetString (pr, func->name); start = func->first_statement; if (start > 0) @@ -275,7 +275,7 @@ dump_functions (progs_t *pr) continue; } printf (" %d %s:%d %d %d %d %x\n", aux->function, - PR_GetString (pr, func->s_file), aux->source_line, + PR_GetString (pr, func->file), aux->source_line, aux->line_info, aux->local_defs, aux->num_locals, aux->return_type); diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index 044c7fdc7..bfaffdc6e 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -79,8 +79,8 @@ progs_get_func_data (unsigned func_index, void *data) func_data.function = aux_func->function; if (aux_func->function < (unsigned int) pr->progs->numfunctions) { func = pr->pr_functions + aux_func->function; - func_data.source_file = pr->pr_strings + func->s_file; - func_data.source_name = pr->pr_strings + func->s_name; + func_data.source_file = pr->pr_strings + func->file; + func_data.source_name = pr->pr_strings + func->name; func_data.first_statement = func->first_statement; } return &func_data; diff --git a/tools/qfcc/source/idstuff.c b/tools/qfcc/source/idstuff.c index 1bc222f49..f78658247 100644 --- a/tools/qfcc/source/idstuff.c +++ b/tools/qfcc/source/idstuff.c @@ -215,7 +215,7 @@ WriteProgdefs (dprograms_t *progs, const char *filename) strings = (char *) progs + progs->ofs_strings; for (i = 0; i < progs->numglobaldefs; i++) { def = (ddef_t *) ((char *) progs + progs->ofs_globaldefs) + i; - name = strings + def->s_name; + name = strings + def->name; if (!strcmp (name, "end_sys_globals")) break; if (!def->ofs) @@ -253,7 +253,7 @@ WriteProgdefs (dprograms_t *progs, const char *filename) dasprintf (dstr, "typedef struct\n{\n"); for (i = 0, j = 0; i < progs->numglobaldefs; i++) { def = (ddef_t *) ((char *) progs + progs->ofs_globaldefs) + i; - name = strings + def->s_name; + name = strings + def->name; if (!strcmp (name, "end_sys_fields")) break; @@ -265,7 +265,7 @@ WriteProgdefs (dprograms_t *progs, const char *filename) continue; fdef = (ddef_t *) ((char *) progs + progs->ofs_fielddefs) + j++; - if (fdef->s_name != def->s_name) + if (fdef->name != def->name) internal_error (0, "def and field order messup"); switch (fdef->type) { diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index afe295961..22403f7ae 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -819,7 +819,7 @@ qfo_def_to_ddef (qfo_t *qfo, const qfo_def_t *def, ddef_t *ddef) { ddef->type = get_def_type (qfo, def->type); ddef->ofs = def->offset; - ddef->s_name = def->name; + ddef->name = def->name; if (!(def->flags & QFOD_NOSAVE) && !(def->flags & QFOD_CONSTANT) && (def->flags & QFOD_GLOBAL) @@ -1079,8 +1079,8 @@ qfo_to_progs (qfo_t *in_qfo, int *size) if (!options.code.local_merging) locals_start += align_globals_size (df->locals); df->profile = 0; - df->s_name = qf->name; - df->s_file = qf->file; + df->name = qf->name; + df->file = qf->file; function_params (qfo, qf, df); } diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 1a8406186..2e656a21e 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -231,19 +231,19 @@ WriteProgs (dprograms_t *progs, int size) func->parm_start = LittleLong (func->parm_start); func->locals = LittleLong (func->locals); func->profile = LittleLong (func->profile); - func->s_name = LittleLong (func->s_name); - func->s_file = LittleLong (func->s_file); + func->name = LittleLong (func->name); + func->file = LittleLong (func->file); func->numparms = LittleLong (func->numparms); } for (i = 0; i < progs->numglobaldefs; i++) { globaldefs[i].type = LittleShort (globaldefs[i].type); globaldefs[i].ofs = LittleShort (globaldefs[i].ofs); - globaldefs[i].s_name = LittleLong (globaldefs[i].s_name); + globaldefs[i].name = LittleLong (globaldefs[i].name); } for (i = 0; i < progs->numfielddefs; i++) { fielddefs[i].type = LittleShort (fielddefs[i].type); fielddefs[i].ofs = LittleShort (fielddefs[i].ofs); - fielddefs[i].s_name = LittleLong (fielddefs[i].s_name); + fielddefs[i].name = LittleLong (fielddefs[i].name); } for (i = 0; i < progs->numglobals; i++) globals[i].integer_var = LittleLong (globals[i].integer_var); From 365762b8a6b7b87e50b1ee17c2e0d2decba40ba3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 31 Dec 2021 19:16:02 +0900 Subject: [PATCH 2076/3664] [gamecode] Switch to using indexed initializers The opcode table is a nightmare to maintain, but this does clean it up and speed up opcode lookups since they can now be indexed. Of course, it turns out I had missed adding several instructions, so had to fix that, and qfcc needed a bit of a re-jigger to get the opcode out of the table. --- include/QF/pr_comp.h | 13 +- libs/gamecode/pr_debug.c | 2 +- libs/gamecode/pr_opcode.c | 657 ++++++++++++++++++----------------- tools/qfcc/include/opcodes.h | 2 + tools/qfcc/source/emit.c | 2 +- tools/qfcc/source/opcodes.c | 22 +- 6 files changed, 354 insertions(+), 344 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index ff71cd6fc..5d5efe942 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -403,17 +403,16 @@ typedef enum { #define OP_BREAK 0x8000 typedef struct opcode_s { - const char *name; - const char *opname; - pr_opcode_e opcode; - qboolean right_associative; - etype_t type_a, type_b, type_c; + const char *name; + const char *opname; + qboolean right_associative; + etype_t type_a, type_b, type_c; unsigned int min_version; - const char *fmt; + const char *fmt; } opcode_t; extern const opcode_t pr_opcodes[]; -opcode_t *PR_Opcode (pr_short_t opcode); +const opcode_t *PR_Opcode (pr_short_t opcode) __attribute__((const)); void PR_Opcode_Init (void); // idempotent typedef struct dstatement_s { diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index f9f743e0d..55cca36d0 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1482,7 +1482,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) int addr = s - pr->pr_statements; int dump_code = contents & 2; const char *fmt; - opcode_t *op; + const opcode_t *op; dfunction_t *call_func = 0; pr_def_t *parm_def = 0; pr_auxfunction_t *aux_func = 0; diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 2c893b39f..62239c561 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -39,15 +39,12 @@ #endif #include "QF/cvar.h" -#include "QF/hash.h" #include "QF/pr_comp.h" #include "QF/progs.h" #include "QF/sys.h" #include "compat.h" -static hashtab_t *opcode_table; - VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { 1, // ev_void 1, // ev_string @@ -99,1430 +96,1438 @@ VISIBLE const char * const pr_type_name[ev_type_count] = { // x place holder for P (padding) // 0-7 parameter index (for P) VISIBLE const opcode_t pr_opcodes[] = { - {"", "done", OP_DONE, false, // OP_DONE is actually the same as + [OP_DONE] = {"", "done", false, // OP_DONE is actually the same as ev_entity, ev_field, ev_void, // OP_RETURN, the types are bogus PROG_ID_VERSION, "%Va", }, - {"*", "mul.d", OP_MUL_D, false, + [OP_MUL_D] = {"*", "mul.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"*", "mul.f", OP_MUL_F, false, + [OP_MUL_F] = {"*", "mul.f", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"*", "mul.v", OP_MUL_V, false, + [OP_MUL_V] = {"*", "mul.v", false, ev_vector, ev_vector, ev_float, PROG_ID_VERSION, }, - {"*", "mul.fv", OP_MUL_FV, false, + [OP_MUL_FV] = {"*", "mul.fv", false, ev_float, ev_vector, ev_vector, PROG_ID_VERSION, }, - {"*", "mul.vf", OP_MUL_VF, false, + [OP_MUL_VF] = {"*", "mul.vf", false, ev_vector, ev_float, ev_vector, PROG_ID_VERSION, }, - {"*", "mul.dv", OP_MUL_DV, false, + [OP_MUL_DV] = {"*", "mul.dv", false, ev_double, ev_vector, ev_vector, PROG_ID_VERSION, }, - {"*", "mul.vd", OP_MUL_VD, false, + [OP_MUL_VD] = {"*", "mul.vd", false, ev_vector, ev_double, ev_vector, PROG_ID_VERSION, }, - {"*", "mul.q", OP_MUL_Q, false, + [OP_MUL_Q] = {"*", "mul.q", false, ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - {"*", "mul.fq", OP_MUL_FQ, false, + [OP_MUL_FQ] = {"*", "mul.fq", false, ev_float, ev_quat, ev_quat, PROG_VERSION, }, - {"*", "mul.qf", OP_MUL_QF, false, + [OP_MUL_QF] = {"*", "mul.qf", false, ev_quat, ev_float, ev_quat, PROG_VERSION, }, - {"*", "mul.dq", OP_MUL_DQ, false, + [OP_MUL_DQ] = {"*", "mul.dq", false, ev_double, ev_quat, ev_quat, PROG_VERSION, }, - {"*", "mul.qd", OP_MUL_QD, false, + [OP_MUL_QD] = {"*", "mul.qd", false, ev_quat, ev_double, ev_quat, PROG_VERSION, }, - {"*", "mul.qv", OP_MUL_QV, false, + [OP_MUL_QV] = {"*", "mul.qv", false, ev_quat, ev_vector, ev_vector, PROG_VERSION, }, - {"~", "conj.q", OP_CONJ_Q, false, + [OP_CONJ_Q] = {"~", "conj.q", false, ev_quat, ev_invalid, ev_quat, PROG_VERSION, "%Ga, %gc", }, - {"/", "div.f", OP_DIV_F, false, + [OP_DIV_F] = {"/", "div.f", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"/", "div.d", OP_DIV_D, false, + [OP_DIV_D] = {"/", "div.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"%", "rem.d", OP_REM_D, false, + [OP_REM_D] = {"%", "rem.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"%%", "mod.d", OP_MOD_D, false, + [OP_MOD_D] = {"%%", "mod.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"+", "add.d", OP_ADD_D, false, + [OP_ADD_D] = {"+", "add.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"+", "add.f", OP_ADD_F, false, + [OP_ADD_F] = {"+", "add.f", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"+", "add.v", OP_ADD_V, false, + [OP_ADD_V] = {"+", "add.v", false, ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - {"+", "add.q", OP_ADD_Q, false, + [OP_ADD_Q] = {"+", "add.q", false, ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - {"+", "add.s", OP_ADD_S, false, + [OP_ADD_S] = {"+", "add.s", false, ev_string, ev_string, ev_string, PROG_VERSION, }, - {"-", "sub.d", OP_SUB_D, false, + [OP_SUB_D] = {"-", "sub.d", false, ev_double, ev_double, ev_double, PROG_VERSION, }, - {"-", "sub.f", OP_SUB_F, false, + [OP_SUB_F] = {"-", "sub.f", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"-", "sub.v", OP_SUB_V, false, + [OP_SUB_V] = {"-", "sub.v", false, ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - {"-", "sub.q", OP_SUB_Q, false, + [OP_SUB_Q] = {"-", "sub.q", false, ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - {"==", "eq.d", OP_EQ_D, false, + [OP_EQ_D] = {"==", "eq.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {"==", "eq.f", OP_EQ_F, false, + [OP_EQ_F] = {"==", "eq.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"==", "eq.v", OP_EQ_V, false, + [OP_EQ_V] = {"==", "eq.v", false, ev_vector, ev_vector, ev_integer, PROG_ID_VERSION, }, - {"==", "eq.q", OP_EQ_Q, false, + [OP_EQ_Q] = {"==", "eq.q", false, ev_quat, ev_quat, ev_integer, PROG_VERSION, }, - {"==", "eq.s", OP_EQ_S, false, + [OP_EQ_S] = {"==", "eq.s", false, ev_string, ev_string, ev_integer, PROG_ID_VERSION, }, - {"==", "eq.e", OP_EQ_E, false, + [OP_EQ_E] = {"==", "eq.e", false, ev_entity, ev_entity, ev_integer, PROG_ID_VERSION, }, - {"==", "eq.fn", OP_EQ_FN, false, + [OP_EQ_FN] = {"==", "eq.fn", false, ev_func, ev_func, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.d", OP_NE_D, false, + [OP_NE_D] = {"!=", "ne.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {"!=", "ne.f", OP_NE_F, false, + [OP_NE_F] = {"!=", "ne.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.v", OP_NE_V, false, + [OP_NE_V] = {"!=", "ne.v", false, ev_vector, ev_vector, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.q", OP_NE_Q, false, + [OP_NE_Q] = {"!=", "ne.q", false, ev_quat, ev_quat, ev_integer, PROG_VERSION, }, - {"!=", "ne.s", OP_NE_S, false, + [OP_NE_S] = {"!=", "ne.s", false, ev_string, ev_string, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.e", OP_NE_E, false, + [OP_NE_E] = {"!=", "ne.e", false, ev_entity, ev_entity, ev_integer, PROG_ID_VERSION, }, - {"!=", "ne.fn", OP_NE_FN, false, + [OP_NE_FN] = {"!=", "ne.fn", false, ev_func, ev_func, ev_integer, PROG_ID_VERSION, }, - {"<=", "le.d", OP_LE_D, false, + [OP_LE_D] = {"<=", "le.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {"<=", "le.f", OP_LE_F, false, + [OP_LE_F] = {"<=", "le.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {">=", "ge.d", OP_GE_D, false, + [OP_GE_D] = {">=", "ge.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {">=", "ge.f", OP_GE_F, false, + [OP_GE_F] = {">=", "ge.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"<=", "le.s", OP_LE_S, false, + [OP_LE_S] = {"<=", "le.s", false, ev_string, ev_string, ev_integer, PROG_VERSION, }, - {">=", "ge.s", OP_GE_S, false, + [OP_GE_S] = {">=", "ge.s", false, ev_string, ev_string, ev_integer, PROG_VERSION, }, - {"<", "lt.d", OP_LT_D, false, + [OP_LT_D] = {"<", "lt.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {"<", "lt.f", OP_LT_F, false, + [OP_LT_F] = {"<", "lt.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {">", "gt.d", OP_GT_D, false, + [OP_GT_D] = {">", "gt.d", false, ev_double, ev_double, ev_integer, PROG_VERSION, }, - {">", "gt.f", OP_GT_F, false, + [OP_GT_F] = {">", "gt.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"<", "lt.s", OP_LT_S, false, + [OP_LT_S] = {"<", "lt.s", false, ev_string, ev_string, ev_integer, PROG_VERSION, }, - {">", "gt.s", OP_GT_S, false, + [OP_GT_S] = {">", "gt.s", false, ev_string, ev_string, ev_integer, PROG_VERSION, }, - {".", "load.f", OP_LOAD_F, false, + [OP_LOAD_F] = {".", "load.f", false, ev_entity, ev_field, ev_float, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible? }, - {".", "load.d", OP_LOAD_D, false, + [OP_LOAD_D] = {".", "load.d", false, ev_entity, ev_field, ev_double, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.v", OP_LOAD_V, false, + [OP_LOAD_V] = {".", "load.v", false, ev_entity, ev_field, ev_vector, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.q", OP_LOAD_Q, false, + [OP_LOAD_Q] = {".", "load.q", false, ev_entity, ev_field, ev_quat, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.s", OP_LOAD_S, false, + [OP_LOAD_S] = {".", "load.s", false, ev_entity, ev_field, ev_string, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.ent", OP_LOAD_ENT, false, + [OP_LOAD_ENT] = {".", "load.ent", false, ev_entity, ev_field, ev_entity, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.fld", OP_LOAD_FLD, false, + [OP_LOAD_FLD] = {".", "load.fld", false, ev_entity, ev_field, ev_field, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.fn", OP_LOAD_FN, false, + [OP_LOAD_FN] = {".", "load.fn", false, ev_entity, ev_field, ev_func, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.i", OP_LOAD_I, false, + [OP_LOAD_I] = {".", "load.i", false, ev_entity, ev_field, ev_integer, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "load.p", OP_LOAD_P, false, + [OP_LOAD_P] = {".", "load.p", false, ev_entity, ev_field, ev_pointer, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {".", "loadb.d", OP_LOADB_D, false, + [OP_LOADB_D] = {".", "loadb.d", false, ev_pointer, ev_integer, ev_double, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.f", OP_LOADB_F, false, + [OP_LOADB_F] = {".", "loadb.f", false, ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.v", OP_LOADB_V, false, + [OP_LOADB_V] = {".", "loadb.v", false, ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.q", OP_LOADB_Q, false, + [OP_LOADB_Q] = {".", "loadb.q", false, ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.s", OP_LOADB_S, false, + [OP_LOADB_S] = {".", "loadb.s", false, ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.ent", OP_LOADB_ENT, false, + [OP_LOADB_ENT] = {".", "loadb.ent", false, ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.fld", OP_LOADB_FLD, false, + [OP_LOADB_FLD] = {".", "loadb.fld", false, ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.fn", OP_LOADB_FN, false, + [OP_LOADB_FN] = {".", "loadb.fn", false, ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.i", OP_LOADB_I, false, + [OP_LOADB_I] = {".", "loadb.i", false, ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadb.p", OP_LOADB_P, false, + [OP_LOADB_P] = {".", "loadb.p", false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - {".", "loadbi.d", OP_LOADBI_D, false, + [OP_LOADBI_D] = {".", "loadbi.d", false, ev_pointer, ev_short, ev_double, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.f", OP_LOADBI_F, false, + [OP_LOADBI_F] = {".", "loadbi.f", false, ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.v", OP_LOADBI_V, false, + [OP_LOADBI_V] = {".", "loadbi.v", false, ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.q", OP_LOADBI_Q, false, + [OP_LOADBI_Q] = {".", "loadbi.q", false, ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.s", OP_LOADBI_S, false, + [OP_LOADBI_S] = {".", "loadbi.s", false, ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.ent", OP_LOADBI_ENT, false, + [OP_LOADBI_ENT] = {".", "loadbi.ent", false, ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.fld", OP_LOADBI_FLD, false, + [OP_LOADBI_FLD] = {".", "loadbi.fld", false, ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.fn", OP_LOADBI_FN, false, + [OP_LOADBI_FN] = {".", "loadbi.fn", false, ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.i", OP_LOADBI_I, false, + [OP_LOADBI_I] = {".", "loadbi.i", false, ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {".", "loadbi.p", OP_LOADBI_P, false, + [OP_LOADBI_P] = {".", "loadbi.p", false, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb), %gc", }, - {"&", "address", OP_ADDRESS, false, + [OP_ADDRESS] = {"&", "address", false, ev_entity, ev_field, ev_pointer, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - {"&", "address", OP_ADDRESS_VOID, false, + [OP_ADDRESS_VOID] = {"&", "address", false, ev_void, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.d", OP_ADDRESS_D, false, + [OP_ADDRESS_D] = {"&", "address.d", false, ev_double, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.f", OP_ADDRESS_F, false, + [OP_ADDRESS_F] = {"&", "address.f", false, ev_float, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.v", OP_ADDRESS_V, false, + [OP_ADDRESS_V] = {"&", "address.v", false, ev_vector, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.q", OP_ADDRESS_Q, false, + [OP_ADDRESS_Q] = {"&", "address.q", false, ev_quat, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.s", OP_ADDRESS_S, false, + [OP_ADDRESS_S] = {"&", "address.s", false, ev_string, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.ent", OP_ADDRESS_ENT, false, + [OP_ADDRESS_ENT] = {"&", "address.ent", false, ev_entity, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.fld", OP_ADDRESS_FLD, false, + [OP_ADDRESS_FLD] = {"&", "address.fld", false, ev_field, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.fn", OP_ADDRESS_FN, false, + [OP_ADDRESS_FN] = {"&", "address.fn", false, ev_func, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.i", OP_ADDRESS_I, false, + [OP_ADDRESS_I] = {"&", "address.i", false, ev_integer, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "address.p", OP_ADDRESS_P, false, + [OP_ADDRESS_P] = {"&", "address.p", false, ev_pointer, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - {"&", "lea", OP_LEA, false, + [OP_LEA] = {"&", "lea", false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "(%Ga + %Gb), %gc", }, - {"&", "leai", OP_LEAI, false, + [OP_LEAI] = {"&", "leai", false, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "(%Ga + %sb), %gc", }, - {"", "conv.if", OP_CONV_IF, false, + [OP_CONV_IF] = {"", "conv.if", false, ev_integer, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.fi", OP_CONV_FI, false, + [OP_CONV_FI] = {"", "conv.fi", false, ev_float, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.id", OP_CONV_ID, false, + [OP_CONV_ID] = {"", "conv.id", false, ev_integer, ev_invalid, ev_double, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.di", OP_CONV_DI, false, + [OP_CONV_DI] = {"", "conv.di", false, ev_double, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.fd", OP_CONV_FD, false, + [OP_CONV_FD] = {"", "conv.fd", false, ev_float, ev_invalid, ev_double, PROG_VERSION, "%Ga, %gc", }, - {"", "conv.df", OP_CONV_DF, false, + [OP_CONV_DF] = {"", "conv.df", false, ev_double, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - {"=", "store.d", OP_STORE_D, true, + [OP_STORE_D] = {"=", "store.d", true, ev_double, ev_double, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - {"=", "store.f", OP_STORE_F, true, + [OP_STORE_F] = {"=", "store.f", true, ev_float, ev_float, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.v", OP_STORE_V, true, + [OP_STORE_V] = {"=", "store.v", true, ev_vector, ev_vector, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.q", OP_STORE_Q, true, + [OP_STORE_Q] = {"=", "store.q", true, ev_quat, ev_quat, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - {"=", "store.s", OP_STORE_S, true, + [OP_STORE_S] = {"=", "store.s", true, ev_string, ev_string, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.ent", OP_STORE_ENT, true, + [OP_STORE_ENT] = {"=", "store.ent", true, ev_entity, ev_entity, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.fld", OP_STORE_FLD, true, + [OP_STORE_FLD] = {"=", "store.fld", true, ev_field, ev_field, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.fn", OP_STORE_FN, true, + [OP_STORE_FN] = {"=", "store.fn", true, ev_func, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - {"=", "store.i", OP_STORE_I, true, + [OP_STORE_I] = {"=", "store.i", true, ev_integer, ev_integer, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - {"=", "store.p", OP_STORE_P, true, + [OP_STORE_P] = {"=", "store.p", true, ev_pointer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - {".=", "storep.d", OP_STOREP_D, true, + [OP_STOREP_D] = {".=", "storep.d", true, ev_double, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.f", OP_STOREP_F, true, + [OP_STOREP_F] = {".=", "storep.f", true, ev_float, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.v", OP_STOREP_V, true, + [OP_STOREP_V] = {".=", "storep.v", true, ev_vector, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.q", OP_STOREP_Q, true, + [OP_STOREP_Q] = {".=", "storep.q", true, ev_quat, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - {".=", "storep.s", OP_STOREP_S, true, + [OP_STOREP_S] = {".=", "storep.s", true, ev_string, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.ent", OP_STOREP_ENT, true, + [OP_STOREP_ENT] = {".=", "storep.ent", true, ev_entity, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.fld", OP_STOREP_FLD, true, + [OP_STOREP_FLD] = {".=", "storep.fld", true, ev_field, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.fn", OP_STOREP_FN, true, + [OP_STOREP_FN] = {".=", "storep.fn", true, ev_func, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - {".=", "storep.i", OP_STOREP_I, true, + [OP_STOREP_I] = {".=", "storep.i", true, ev_integer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - {".=", "storep.p", OP_STOREP_P, true, + [OP_STOREP_P] = {".=", "storep.p", true, ev_pointer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - {".=", "storeb.d", OP_STOREB_D, true, + [OP_STOREB_D] = {".=", "storeb.d", true, ev_double, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.f", OP_STOREB_F, true, + [OP_STOREB_F] = {".=", "storeb.f", true, ev_float, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.v", OP_STOREB_V, true, + [OP_STOREB_V] = {".=", "storeb.v", true, ev_vector, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.q", OP_STOREB_Q, true, + [OP_STOREB_Q] = {".=", "storeb.q", true, ev_quat, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.s", OP_STOREB_S, true, + [OP_STOREB_S] = {".=", "storeb.s", true, ev_string, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.ent", OP_STOREB_ENT, true, + [OP_STOREB_ENT] = {".=", "storeb.ent", true, ev_entity, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.fld", OP_STOREB_FLD, true, + [OP_STOREB_FLD] = {".=", "storeb.fld", true, ev_field, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.fn", OP_STOREB_FN, true, + [OP_STOREB_FN] = {".=", "storeb.fn", true, ev_func, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.i", OP_STOREB_I, true, + [OP_STOREB_I] = {".=", "storeb.i", true, ev_integer, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storeb.p", OP_STOREB_P, true, + [OP_STOREB_P] = {".=", "storeb.p", true, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - {".=", "storebi.d", OP_STOREBI_D, true, + [OP_STOREBI_D] = {".=", "storebi.d", true, ev_double, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.f", OP_STOREBI_F, true, + [OP_STOREBI_F] = {".=", "storebi.f", true, ev_float, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.v", OP_STOREBI_V, true, + [OP_STOREBI_V] = {".=", "storebi.v", true, ev_vector, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.q", OP_STOREBI_Q, true, + [OP_STOREBI_Q] = {".=", "storebi.q", true, ev_quat, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.s", OP_STOREBI_S, true, + [OP_STOREBI_S] = {".=", "storebi.s", true, ev_string, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.ent", OP_STOREBI_ENT, true, + [OP_STOREBI_ENT] = {".=", "storebi.ent", true, ev_entity, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.fld", OP_STOREBI_FLD, true, + [OP_STOREBI_FLD] = {".=", "storebi.fld", true, ev_field, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.fn", OP_STOREBI_FN, true, + [OP_STOREBI_FN] = {".=", "storebi.fn", true, ev_func, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.i", OP_STOREBI_I, true, + [OP_STOREBI_I] = {".=", "storebi.i", true, ev_integer, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {".=", "storebi.p", OP_STOREBI_P, true, + [OP_STOREBI_P] = {".=", "storebi.p", true, ev_pointer, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - {"", "return", OP_RETURN, false, + [OP_RETURN] = {"", "return", false, ev_void, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Ra", }, - {"", "return", OP_RETURN_V, false, + [OP_RETURN_V] = {"", "return", false, ev_invalid, ev_invalid, ev_invalid, PROG_VERSION, "", }, - {"!", "not.d", OP_NOT_D, false, + [OP_NOT_D] = {"!", "not.d", false, ev_double, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"!", "not.f", OP_NOT_F, false, + [OP_NOT_F] = {"!", "not.f", false, ev_float, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.v", OP_NOT_V, false, + [OP_NOT_V] = {"!", "not.v", false, ev_vector, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.q", OP_NOT_Q, false, + [OP_NOT_Q] = {"!", "not.q", false, ev_quat, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"!", "not.s", OP_NOT_S, false, + [OP_NOT_S] = {"!", "not.s", false, ev_string, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.ent", OP_NOT_ENT, false, + [OP_NOT_ENT] = {"!", "not.ent", false, ev_entity, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.fn", OP_NOT_FN, false, + [OP_NOT_FN] = {"!", "not.fn", false, ev_func, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - {"!", "not.p", OP_NOT_P, false, + [OP_NOT_P] = {"!", "not.p", false, ev_pointer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"", "if", OP_IF, false, + [OP_IF] = {"", "if", false, ev_integer, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifnot", OP_IFNOT, false, + [OP_IFNOT] = {"", "ifnot", false, ev_integer, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifbe", OP_IFBE, true, + [OP_IFBE] = {"", "ifbe", true, ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifb", OP_IFB, true, + [OP_IFB] = {"", "ifb", true, ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifae", OP_IFAE, true, + [OP_IFAE] = {"", "ifae", true, ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - {"", "ifa", OP_IFA, true, + [OP_IFA] = {"", "ifa", true, ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, // calls returns REG_RETURN - {"", "call0", OP_CALL0, false, + [OP_CALL0] = {"", "call0", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa ()", }, - {"", "call1", OP_CALL1, false, + [OP_CALL1] = {"", "call1", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x)", }, - {"", "call2", OP_CALL2, false, + [OP_CALL2] = {"", "call2", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x)", }, - {"", "call3", OP_CALL3, false, + [OP_CALL3] = {"", "call3", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x)", }, - {"", "call4", OP_CALL4, false, + [OP_CALL4] = {"", "call4", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x)", }, - {"", "call5", OP_CALL5, false, + [OP_CALL5] = {"", "call5", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x)", }, - {"", "call6", OP_CALL6, false, + [OP_CALL6] = {"", "call6", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x)", }, - {"", "call7", OP_CALL7, false, + [OP_CALL7] = {"", "call7", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - {"", "call8", OP_CALL8, false, + [OP_CALL8] = {"", "call8", false, ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - {"", "rcall1", OP_RCALL1, false, + [OP_RCALL0] = {"", 0, false, + ev_invalid, ev_invalid, ev_invalid, + ~0, // not a valid instruction + 0, + }, + [OP_RCALL1] = {"", "rcall1", false, ev_func, ev_void, ev_invalid, PROG_VERSION, "%Fa (%P0b)", }, - {"", "rcall2", OP_RCALL2, false, + [OP_RCALL2] = {"", "rcall2", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c)", }, - {"", "rcall3", OP_RCALL3, false, + [OP_RCALL3] = {"", "rcall3", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x)", }, - {"", "rcall4", OP_RCALL4, false, + [OP_RCALL4] = {"", "rcall4", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x)", }, - {"", "rcall5", OP_RCALL5, false, + [OP_RCALL5] = {"", "rcall5", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", }, - {"", "rcall6", OP_RCALL6, false, + [OP_RCALL6] = {"", "rcall6", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", }, - {"", "rcall7", OP_RCALL7, false, + [OP_RCALL7] = {"", "rcall7", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - {"", "rcall8", OP_RCALL8, false, + [OP_RCALL8] = {"", "rcall8", false, ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - {"", "state", OP_STATE, false, + [OP_STATE] = {"", "state", false, ev_float, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %Gb", }, - {"", "state.f", OP_STATE_F, false, + [OP_STATE_F] = {"", "state.f", false, ev_float, ev_func, ev_float, PROG_VERSION, "%Ga, %Gb, %Gc", }, - {"", "goto", OP_GOTO, false, + [OP_GOTO] = {"", "goto", false, ev_short, ev_invalid, ev_invalid, PROG_ID_VERSION, "branch %sa (%Oa)", }, - {"", "jump", OP_JUMP, false, + [OP_JUMP] = {"", "jump", false, ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "jumpb", OP_JUMPB, false, + [OP_JUMPB] = {"", "jumpb", false, ev_void, ev_integer, ev_invalid, PROG_VERSION, "%Ga[%Gb]", }, - {"&&", "and.f", OP_AND, false, + [OP_AND] = {"&&", "and.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"||", "or.f", OP_OR, false, + [OP_OR] = {"||", "or.f", false, ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - {"<<", "shl.f", OP_SHL_F, false, + [OP_SHL_F] = {"<<", "shl.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {">>", "shr.f", OP_SHR_F, false, + [OP_SHR_F] = {">>", "shr.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {"<<", "shl.i", OP_SHL_I, false, + [OP_SHL_I] = {"<<", "shl.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {">>", "shr.i", OP_SHR_I, false, + [OP_SHR_I] = {">>", "shr.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {">>", "shr.u", OP_SHR_U, false, + [OP_SHR_U] = {">>", "shr.u", false, ev_uinteger, ev_integer, ev_uinteger, PROG_VERSION, }, - {"&", "bitand", OP_BITAND, false, + [OP_BITAND] = {"&", "bitand", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"|", "bitor", OP_BITOR, false, + [OP_BITOR] = {"|", "bitor", false, ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - {"+", "add.i", OP_ADD_I, false, + [OP_ADD_I] = {"+", "add.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"-", "sub.i", OP_SUB_I, false, + [OP_SUB_I] = {"-", "sub.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"*", "mul.i", OP_MUL_I, false, + [OP_MUL_I] = {"*", "mul.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"/", "div.i", OP_DIV_I, false, + [OP_DIV_I] = {"/", "div.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"%", "rem.i", OP_REM_I, false, + [OP_REM_I] = {"%", "rem.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"%%", "mod.i", OP_MOD_I, false, + [OP_MOD_I] = {"%%", "mod.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"&", "bitand.i", OP_BITAND_I, false, + [OP_BITAND_I] = {"&", "bitand.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"|", "bitor.i", OP_BITOR_I, false, + [OP_BITOR_I] = {"|", "bitor.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"%", "rem.f", OP_REM_F, false, + [OP_REM_F] = {"%", "rem.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {"%%", "mod.f", OP_MOD_F, false, + [OP_MOD_F] = {"%%", "mod.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {">=", "ge.i", OP_GE_I, false, + [OP_GE_I] = {">=", "ge.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"<=", "le.i", OP_LE_I, false, + [OP_LE_I] = {"<=", "le.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {">", "gt.i", OP_GT_I, false, + [OP_GT_I] = {">", "gt.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"<", "lt.i", OP_LT_I, false, + [OP_LT_I] = {"<", "lt.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"&&", "and.i", OP_AND_I, false, + [OP_AND_I] = {"&&", "and.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"||", "or.i", OP_OR_I, false, + [OP_OR_I] = {"||", "or.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"!", "not.i", OP_NOT_I, false, + [OP_NOT_I] = {"!", "not.i", false, ev_integer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {"==", "eq.i", OP_EQ_I, false, + [OP_EQ_I] = {"==", "eq.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"!=", "ne.i", OP_NE_I, false, + [OP_NE_I] = {"!=", "ne.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {">=", "ge.u", OP_GE_U, false, + [OP_GE_U] = {">=", "ge.u", false, ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - {"<=", "le.u", OP_LE_U, false, + [OP_LE_U] = {"<=", "le.u", false, ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - {">", "gt.u", OP_GT_U, false, + [OP_GT_U] = {">", "gt.u", false, ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - {"<", "lt.u", OP_LT_U, false, + [OP_LT_U] = {"<", "lt.u", false, ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - {"^", "bitxor.f", OP_BITXOR_F, false, + [OP_BITXOR_F] = {"^", "bitxor.f", false, ev_float, ev_float, ev_float, PROG_VERSION, }, - {"~", "bitnot.f", OP_BITNOT_F, false, + [OP_BITNOT_F] = {"~", "bitnot.f", false, ev_float, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - {"^", "bitxor.i", OP_BITXOR_I, false, + [OP_BITXOR_I] = {"^", "bitxor.i", false, ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - {"~", "bitnot.i", OP_BITNOT_I, false, + [OP_BITNOT_I] = {"~", "bitnot.i", false, ev_integer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - {">=", "ge.p", OP_GE_P, false, + [OP_GE_P] = {">=", "ge.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"<=", "le.p", OP_LE_P, false, + [OP_LE_P] = {"<=", "le.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {">", "gt.p", OP_GT_P, false, + [OP_GT_P] = {">", "gt.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"<", "lt.p", OP_LT_P, false, + [OP_LT_P] = {"<", "lt.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"==", "eq.p", OP_EQ_P, false, + [OP_EQ_P] = {"==", "eq.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"!=", "ne.p", OP_NE_P, false, + [OP_NE_P] = {"!=", "ne.p", false, ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - {"", "movei", OP_MOVEI, true, + [OP_MOVEI] = {"", "movei", true, ev_void, ev_short, ev_void, PROG_VERSION, "%Ga, %sb, %gc", }, - {"", "movep", OP_MOVEP, true, + [OP_MOVEP] = {"", "movep", true, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "%Ga, %Gb, %Gc", }, - {"", "movepi", OP_MOVEPI, true, + [OP_MOVEPI] = {"", "movepi", true, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "%Ga, %sb, %Gc", }, - {"", "memseti", OP_MEMSETI, true, + [OP_MEMSETI] = {"", "memseti", true, ev_integer, ev_short, ev_void, PROG_VERSION, "%Ga, %sb, %gc", }, - {"", "memsetp", OP_MEMSETP, true, + [OP_MEMSETP] = {"", "memsetp", true, ev_integer, ev_integer, ev_pointer, PROG_VERSION, "%Ga, %Gb, %Gc", }, - {"", "memsetpi", OP_MEMSETPI, true, + [OP_MEMSETPI] = {"", "memsetpi", true, ev_integer, ev_short, ev_pointer, PROG_VERSION, "%Ga, %sb, %Gc", }, - {"", "push.s", OP_PUSH_S, false, + [OP_PUSH_S] = {"", "push.s", false, ev_string, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.f", OP_PUSH_F, false, + [OP_PUSH_F] = {"", "push.f", false, ev_float, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.v", OP_PUSH_V, false, + [OP_PUSH_V] = {"", "push.v", false, ev_vector, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.ent", OP_PUSH_ENT, false, + [OP_PUSH_ENT] = {"", "push.ent", false, ev_entity, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.fld", OP_PUSH_FLD, false, + [OP_PUSH_FLD] = {"", "push.fld", false, ev_field, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.fn", OP_PUSH_FN, false, + [OP_PUSH_FN] = {"", "push.fn", false, ev_func, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.p", OP_PUSH_P, false, + [OP_PUSH_P] = {"", "push.p", false, ev_pointer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.q", OP_PUSH_Q, false, + [OP_PUSH_Q] = {"", "push.q", false, ev_quat, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - {"", "push.i", OP_PUSH_I, false, + [OP_PUSH_I] = {"", "push.i", false, ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, + [OP_PUSH_D] = {"", "push.d", false, + ev_double, ev_invalid, ev_invalid, + PROG_VERSION, + "%Ga", + }, - {"", "pushb.s", OP_PUSHB_S, false, + [OP_PUSHB_S] = {"", "pushb.s", false, ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.f", OP_PUSHB_F, false, + [OP_PUSHB_F] = {"", "pushb.f", false, ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.v", OP_PUSHB_V, false, + [OP_PUSHB_V] = {"", "pushb.v", false, ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.ent", OP_PUSHB_ENT, false, + [OP_PUSHB_ENT] = {"", "pushb.ent", false, ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.fld", OP_PUSHB_FLD, false, + [OP_PUSHB_FLD] = {"", "pushb.fld", false, ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.fn", OP_PUSHB_FN, false, + [OP_PUSHB_FN] = {"", "pushb.fn", false, ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.p", OP_PUSHB_P, false, + [OP_PUSHB_P] = {"", "pushb.p", false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.q", OP_PUSHB_Q, false, + [OP_PUSHB_Q] = {"", "pushb.q", false, ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "pushb.i", OP_PUSHB_I, false, + [OP_PUSHB_I] = {"", "pushb.i", false, ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb)", }, + [OP_PUSHB_D] = {"", "pushb.d", false, + ev_pointer, ev_integer, ev_double, + PROG_VERSION, + "*(%Ga + %Gb)", + }, - {"", "pushbi.s", OP_PUSHBI_S, false, + [OP_PUSHBI_S] = {"", "pushbi.s", false, ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.f", OP_PUSHBI_F, false, + [OP_PUSHBI_F] = {"", "pushbi.f", false, ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.v", OP_PUSHBI_V, false, + [OP_PUSHBI_V] = {"", "pushbi.v", false, ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.ent", OP_PUSHBI_ENT, false, + [OP_PUSHBI_ENT] = {"", "pushbi.ent", false, ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.fld", OP_PUSHBI_FLD, false, + [OP_PUSHBI_FLD] = {"", "pushbi.fld", false, ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.fn", OP_PUSHBI_FN, false, + [OP_PUSHBI_FN] = {"", "pushbi.fn", false, ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.p", OP_PUSHBI_P, false, + [OP_PUSHBI_P] = {"", "pushbi.p", false, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.q", OP_PUSHBI_Q, false, + [OP_PUSHBI_Q] = {"", "pushbi.q", false, ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "pushbi.i", OP_PUSHBI_I, false, + [OP_PUSHBI_I] = {"", "pushbi.i", false, ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb)", }, + [OP_PUSHBI_D] = {"", "pushbi.d", false, + ev_pointer, ev_short, ev_double, + PROG_VERSION, + "*(%Ga + %sb)", + }, - {"", "pop.s", OP_POP_S, false, + [OP_POP_S] = {"", "pop.s", false, ev_string, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.f", OP_POP_F, false, + [OP_POP_F] = {"", "pop.f", false, ev_float, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.v", OP_POP_V, false, + [OP_POP_V] = {"", "pop.v", false, ev_vector, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.ent", OP_POP_ENT, false, + [OP_POP_ENT] = {"", "pop.ent", false, ev_entity, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.fld", OP_POP_FLD, false, + [OP_POP_FLD] = {"", "pop.fld", false, ev_field, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.fn", OP_POP_FN, false, + [OP_POP_FN] = {"", "pop.fn", false, ev_func, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.p", OP_POP_P, false, + [OP_POP_P] = {"", "pop.p", false, ev_pointer, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.q", OP_POP_Q, false, + [OP_POP_Q] = {"", "pop.q", false, ev_quat, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - {"", "pop.i", OP_POP_I, false, + [OP_POP_I] = {"", "pop.i", false, ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, + [OP_POP_D] = {"", "pop.d", false, + ev_double, ev_invalid, ev_invalid, + PROG_VERSION, + "%ga", + }, - {"", "popb.s", OP_POPB_S, false, + [OP_POPB_S] = {"", "popb.s", false, ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.f", OP_POPB_F, false, + [OP_POPB_F] = {"", "popb.f", false, ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.v", OP_POPB_V, false, + [OP_POPB_V] = {"", "popb.v", false, ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.ent", OP_POPB_ENT, false, + [OP_POPB_ENT] = {"", "popb.ent", false, ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.fld", OP_POPB_FLD, false, + [OP_POPB_FLD] = {"", "popb.fld", false, ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.fn", OP_POPB_FN, false, + [OP_POPB_FN] = {"", "popb.fn", false, ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.p", OP_POPB_P, false, + [OP_POPB_P] = {"", "popb.p", false, ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.q", OP_POPB_Q, false, + [OP_POPB_Q] = {"", "popb.q", false, ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb)", }, - {"", "popb.i", OP_POPB_I, false, + [OP_POPB_I] = {"", "popb.i", false, ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb)", }, + [OP_POPB_D] = {"", "popb.d", false, + ev_pointer, ev_integer, ev_double, + PROG_VERSION, + "*(%Ga + %Gb)", + }, - {"", "popbi.s", OP_POPBI_S, false, + [OP_POPBI_S] = {"", "popbi.s", false, ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.f", OP_POPBI_F, false, + [OP_POPBI_F] = {"", "popbi.f", false, ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.v", OP_POPBI_V, false, + [OP_POPBI_V] = {"", "popbi.v", false, ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.ent", OP_POPBI_ENT, false, + [OP_POPBI_ENT] = {"", "popbi.ent", false, ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.fld", OP_POPBI_FLD, false, + [OP_POPBI_FLD] = {"", "popbi.fld", false, ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.fn", OP_POPBI_FN, false, + [OP_POPBI_FN] = {"", "popbi.fn", false, ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.p", OP_POPBI_P, false, + [OP_POPBI_P] = {"", "popbi.p", false, ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.q", OP_POPBI_Q, false, + [OP_POPBI_Q] = {"", "popbi.q", false, ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb)", }, - {"", "popbi.i", OP_POPBI_I, false, + [OP_POPBI_I] = {"", "popbi.i", false, ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb)", }, + [OP_POPBI_D] = {"", "popbi.d", false, + ev_pointer, ev_short, ev_double, + PROG_VERSION, + "*(%Ga + %sb)", + }, // end of table - {0}, + [OP_MEMSETPI+1] = {0}, //XXX FIXME relies on OP_MEMSETPI being last }; - -static uintptr_t -opcode_get_hash (const void *op, void *unused) -{ - return ((opcode_t *)op)->opcode; -} - -static int -opcode_compare (const void *_opa, const void *_opb, void *unused) -{ - opcode_t *opa = (opcode_t *)_opa; - opcode_t *opb = (opcode_t *)_opb; - - return opa->opcode == opb->opcode; -} - -opcode_t * +const opcode_t * PR_Opcode (pr_short_t opcode) { - opcode_t op; - - op.opcode = opcode; - return Hash_FindElement (opcode_table, &op); + if (opcode < 0 + || opcode >= (int) (sizeof (pr_opcodes) / sizeof (pr_opcodes[0])) - 1) { + return 0; + } + return &pr_opcodes[opcode]; } VISIBLE void PR_Opcode_Init (void) { - const opcode_t *op; - - if (opcode_table) { - // already initialized - return; - } - opcode_table = Hash_NewTable (1021, 0, 0, 0, 0); - Hash_SetHashCompare (opcode_table, opcode_get_hash, opcode_compare); - - for (op = pr_opcodes; op->name; op++) { - Hash_AddElement (opcode_table, (void *) op); - } } static inline void -check_branch (progs_t *pr, dstatement_t *st, opcode_t *op, short offset) +check_branch (progs_t *pr, dstatement_t *st, const opcode_t *op, short offset) { pr_int_t address = st - pr->pr_statements; @@ -1551,7 +1556,7 @@ is_vector_parameter_store (progs_t *pr, dstatement_t *st, #define ISDENORM(x) ((x) && !((x) & 0x7f800000)) static inline void -check_global (progs_t *pr, dstatement_t *st, opcode_t *op, etype_t type, +check_global (progs_t *pr, dstatement_t *st, const opcode_t *op, etype_t type, unsigned short operand, int check_denorm) { const char *msg; @@ -1609,7 +1614,7 @@ error: } static void -check_global_size (progs_t *pr, dstatement_t *st, opcode_t *op, +check_global_size (progs_t *pr, dstatement_t *st, const opcode_t *op, unsigned short size, unsigned short operand) { const char *msg; @@ -1627,7 +1632,7 @@ error: int PR_Check_Opcodes (progs_t *pr) { - opcode_t *op; + const opcode_t *op; dstatement_t *st; int state_ok = 0; int pushpop_ok = 0; @@ -1784,7 +1789,7 @@ PR_Check_Opcodes (progs_t *pr) default: check_global (pr, st, op, op->type_a, st->a, 1); check_global (pr, st, op, op->type_b, st->b, - op->opcode != OP_STORE_F); + (op - pr_opcodes) != OP_STORE_F); check_global (pr, st, op, op->type_c, st->c, 0); break; } diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index 779370340..2ffbe04c8 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -48,6 +48,8 @@ extern struct opcode_s *op_jumpb; struct operand_s; +extern struct opcode_s *opcode_map; + struct opcode_s *opcode_find (const char *name, struct operand_s *op_a, struct operand_s *op_b, struct operand_s *op_c); void opcode_init (void); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 5a7dd129a..c2dac98ec 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -213,7 +213,7 @@ emit_statement (statement_t *statement) } } s = codespace_newstatement (pr.code); - s->op = op->opcode; + s->op = op - opcode_map; s->a = def_a ? def_a->offset : 0; s->b = def_b ? def_b->offset : 0; s->c = def_c ? def_c->offset : 0; diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index a9bda7a3c..bf962ec96 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -49,6 +49,7 @@ hashtab_t *opcode_type_table; hashtab_t *opcode_void_table; +opcode_t *opcode_map; #define ROTL(x,n) ((((unsigned)(x))<<(n))|((unsigned)(x))>>(32-n)) @@ -95,7 +96,7 @@ opcode_t * opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) { - opcode_t search_op; + opcode_t search_op = {}; opcode_t *op; opcode_t *sop; void **op_list; @@ -122,12 +123,6 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b, return op; } -static void -opcode_free (void *_op, void *unused) -{ - free (_op); -} - void opcode_init (void) { @@ -139,14 +134,23 @@ opcode_init (void) Hash_FlushTable (opcode_type_table); } else { PR_Opcode_Init (); - opcode_type_table = Hash_NewTable (1021, 0, opcode_free, 0, 0); + opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0); Hash_SetHashCompare (opcode_type_table, get_hash, compare); opcode_void_table = Hash_NewTable (1021, get_key, 0, 0, 0); } + + int num_opcodes = 0; for (op = pr_opcodes; op->name; op++) { + num_opcodes++; + } + if (!opcode_map) { + opcode_map = calloc (num_opcodes, sizeof (opcode_t)); + } + for (int i = 0; i < num_opcodes; i++) { + op = pr_opcodes + i; if (op->min_version > options.code.progsversion) continue; - mop = malloc (sizeof (opcode_t)); + mop = opcode_map + i; *mop = *op; if (options.code.progsversion == PROG_ID_VERSION) { // v6 progs have no concept of integer, but the QF engine From 97034d9dde9dae7aa95412f543366e0d80f0c2f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 00:57:55 +0900 Subject: [PATCH 2077/3664] [simd] Add 2d vector types For int, long, float and double. I've been meaning to add them for a while, and they're part of the new Ruamoko instructions set (which is progressing nicely). --- include/QF/simd/types.h | 22 +++-- include/QF/simd/vec2d.h | 115 +++++++++++++++++++++++++ include/QF/simd/vec2f.h | 166 +++++++++++++++++++++++++++++++++++++ include/QF/simd/vec4d.h | 49 ++++++++--- include/QF/simd/vec4f.h | 59 +++++++++---- libs/util/cexpr-type.c | 4 +- libs/util/simd.c | 4 + libs/util/test/test-simd.c | 16 ++-- tools/qfvis/source/flow.c | 4 +- 9 files changed, 395 insertions(+), 44 deletions(-) create mode 100644 include/QF/simd/vec2d.h create mode 100644 include/QF/simd/vec2f.h diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index 5764fe085..ad8345f44 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -30,7 +30,8 @@ #include -#define VEC_TYPE(t,n) typedef t n __attribute__ ((vector_size (4*sizeof (t)))) +#define VEC_TYPE(t,n,s) \ + typedef t n __attribute__ ((vector_size (s*sizeof (t)))) /** Three element vector type for interfacing with compact data. * @@ -39,6 +40,9 @@ */ typedef double vec3d_t[3]; +VEC_TYPE (double, vec2d_t, 2); +VEC_TYPE (int64_t, vec2l_t, 2); + #ifdef __AVX2__ /** Four element vector type for horizontal (AOS) vector data. * @@ -49,11 +53,11 @@ typedef double vec3d_t[3]; * a single component from four vectors, or a single row/column (depending on * context) of an Nx4 or 4xN matrix. */ -VEC_TYPE (double, vec4d_t); +VEC_TYPE (double, vec4d_t, 4); /** Used mostly for __builtin_shuffle. */ -VEC_TYPE (int64_t, vec4l_t); +VEC_TYPE (int64_t, vec4l_t, 4); #endif /** Three element vector type for interfacing with compact data. @@ -63,6 +67,9 @@ VEC_TYPE (int64_t, vec4l_t); */ typedef float vec3f_t[3]; +VEC_TYPE (float, vec2f_t, 2); +VEC_TYPE (int, vec2i_t, 2); + /** Four element vector type for horizontal (AOS) vector data. * * This is used for both vectors (3D and 4D) and quaternions. 3D vectors @@ -72,20 +79,25 @@ typedef float vec3f_t[3]; * a single component from four vectors, or a single row/column (depending on * context) of an Nx4 or 4xN matrix. */ -VEC_TYPE (float, vec4f_t); +VEC_TYPE (float, vec4f_t, 4); /** Used mostly for __builtin_shuffle. */ -VEC_TYPE (int, vec4i_t); +VEC_TYPE (int, vec4i_t, 4); +#define VEC2D_FMT "[%.17g, %.17g]" +#define VEC2L_FMT "[%ld, %ld]" #define VEC4D_FMT "[%.17g, %.17g, %.17g, %.17g]" #if __WORDSIZE == 64 #define VEC4L_FMT "[%ld, %ld, %ld, %ld]" #else #define VEC4L_FMT "[%lld, %lld, %lld, %lld]" #endif +#define VEC2F_FMT "[%.9g, %.9g]" +#define VEC2I_FMT "[%d, %d]" #define VEC4F_FMT "[%.9g, %.9g, %.9g, %.9g]" #define VEC4I_FMT "[%d, %d, %d, %d]" +#define VEC2_EXP(v) (v)[0], (v)[1] #define VEC4_EXP(v) (v)[0], (v)[1], (v)[2], (v)[3] #define MAT4_ROW(m, r) (m)[0][r], (m)[1][r], (m)[2][r], (m)[3][r] diff --git a/include/QF/simd/vec2d.h b/include/QF/simd/vec2d.h new file mode 100644 index 000000000..6b50ea6b4 --- /dev/null +++ b/include/QF/simd/vec2d.h @@ -0,0 +1,115 @@ +/* + QF/simd/vec2d.h + + Vector functions for vec2d_t (ie, double precision) + + Copyright (C) 2020 Bill Currie + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec2d_h +#define __QF_simd_vec2d_h + +#include + +#include "QF/simd/types.h" + +GNU89INLINE inline vec2d_t vsqrt2d (vec2d_t v) __attribute__((const)); +GNU89INLINE inline vec2d_t vceil2d (vec2d_t v) __attribute__((const)); +GNU89INLINE inline vec2d_t vfloor2d (vec2d_t v) __attribute__((const)); +GNU89INLINE inline vec2d_t vtrunc2d (vec2d_t v) __attribute__((const)); +/** 2D vector dot product. + */ +GNU89INLINE inline vec2d_t dot2d (vec2d_t a, vec2d_t b) __attribute__((const)); +GNU89INLINE inline vec2d_t cmuld (vec2d_t a, vec2d_t b) __attribute__((const)); + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +vsqrt2d (vec2d_t v) +{ + return _mm_sqrt_pd (v); +} + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +vceil2d (vec2d_t v) +{ + return _mm_ceil_pd (v); +} + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +vfloor2d (vec2d_t v) +{ + return _mm_floor_pd (v); +} + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +vtrunc2d (vec2d_t v) +{ + return _mm_round_pd (v, _MM_FROUND_TRUNC); +} + +#ifndef IMPLEMENT_VEC2D_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +dot2d (vec2d_t a, vec2d_t b) +{ + vec2d_t c = a * b; + c = _mm_hadd_pd (c, c); + return c; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2d_t +cmuld (vec2d_t a, vec2d_t b) +{ + vec2d_t c = a * b[0]; + c = _mm_addsub_pd (c, (vec2d_t) { c[1], c[0] }); + return c; +} + +#endif//__QF_simd_vec2d_h diff --git a/include/QF/simd/vec2f.h b/include/QF/simd/vec2f.h new file mode 100644 index 000000000..ffa403ad4 --- /dev/null +++ b/include/QF/simd/vec2f.h @@ -0,0 +1,166 @@ +/* + QF/simd/vec2f.h + + Vector functions for vec2f_t (ie, float precision) + + Copyright (C) 2020 Bill Currie + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec2f_h +#define __QF_simd_vec2f_h + +#include +#include + +#include "QF/simd/types.h" + +GNU89INLINE inline vec2f_t vabs2f (vec2f_t v) __attribute__((const)); +GNU89INLINE inline vec2f_t vsqrt2f (vec2f_t v) __attribute__((const)); +GNU89INLINE inline vec2f_t vceil2f (vec2f_t v) __attribute__((const)); +GNU89INLINE inline vec2f_t vfloor2f (vec2f_t v) __attribute__((const)); +GNU89INLINE inline vec2f_t vtrunc2f (vec2f_t v) __attribute__((const)); +/** 2D vector dot product. + */ +GNU89INLINE inline vec2f_t dot2f (vec2f_t a, vec2f_t b) __attribute__((const)); +GNU89INLINE inline vec2f_t cmulf (vec2f_t a, vec2f_t b) __attribute__((const)); +GNU89INLINE inline vec2f_t normal2f (vec2f_t v) __attribute__((pure)); +GNU89INLINE inline vec2f_t magnitude2f (vec2f_t v) __attribute__((pure)); + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vabs2f (vec2f_t v) +{ + const uint32_t nan = ~0u >> 1; + const vec2i_t abs = { nan, nan }; + return (vec2f_t) ((vec2i_t) v & abs); +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vsqrt2f (vec2f_t v) +{ + vec4f_t t = { v[0], v[1], 0, 0 }; + t = _mm_sqrt_ps (t); + return (vec2f_t) { t[0], t[1] }; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vceil2f (vec2f_t v) +{ + vec4f_t t = { v[0], v[1], 0, 0 }; + t = _mm_ceil_ps (t); + return (vec2f_t) { t[0], t[1] }; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vfloor2f (vec2f_t v) +{ + vec4f_t t = { v[0], v[1], 0, 0 }; + t = _mm_floor_ps (t); + return (vec2f_t) { t[0], t[1] }; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +vtrunc2f (vec2f_t v) +{ + vec4f_t t = { v[0], v[1], 0, 0 }; + t = _mm_round_ps (t, _MM_FROUND_TRUNC); + return (vec2f_t) { t[0], t[1] }; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +dot2f (vec2f_t a, vec2f_t b) +{ + vec2f_t c = a * b; + vec4f_t t = { c[0], c[1], 0, 0 }; + t = _mm_hadd_ps (t, t); + return (vec2f_t) { t[0], t[1] }; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +cmulf (vec2f_t a, vec2f_t b) +{ + vec2f_t c1 = a * b[0]; + vec2f_t c2 = a * b[1]; + vec4f_t c14 ={ c1[0], c1[1], 0, 0 }; + vec4f_t c24 ={ c2[1], c2[0], 0, 0 }; + vec4f_t c = _mm_addsub_ps (c14, c24); + return (vec2f_t) { c[0], c[1] }; +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +normal2f (vec2f_t v) +{ + return v / vsqrt2f (dot2f (v, v)); +} + +#ifndef IMPLEMENT_VEC2F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2f_t +magnitude2f (vec2f_t v) +{ + return vsqrt2f (dot2f (v, v)); +} + +#endif//__QF_simd_vec2f_h diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 058635dd7..3b87eb14a 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -33,10 +33,10 @@ #include "QF/simd/types.h" -GNU89INLINE inline vec4d_t vsqrtd (vec4d_t v) __attribute__((const)); -GNU89INLINE inline vec4d_t vceild (vec4d_t v) __attribute__((const)); -GNU89INLINE inline vec4d_t vfloord (vec4d_t v) __attribute__((const)); -GNU89INLINE inline vec4d_t vtruncd (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vsqrt4d (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vceil4d (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vfloor4d (vec4d_t v) __attribute__((const)); +GNU89INLINE inline vec4d_t vtrunc4d (vec4d_t v) __attribute__((const)); /** 3D vector cross product. * * The w (4th) component can be any value on input, and is guaranteed to be 0 @@ -96,6 +96,8 @@ GNU89INLINE inline vec4d_t qrotd (vec4d_t a, vec4d_t b) __attribute__((const)); GNU89INLINE inline vec4d_t qconjd (vec4d_t q) __attribute__((const)); GNU89INLINE inline vec4d_t loadvec3d (const double v3[]) __attribute__((pure)); GNU89INLINE inline void storevec3d (double v3[3], vec4d_t v4); +GNU89INLINE inline vec4l_t loadvec3l (const long *v3) __attribute__((pure)); +GNU89INLINE inline void storevec3l (long *v3, vec4l_t v4); #ifndef IMPLEMENT_VEC4D_Funcs GNU89INLINE inline @@ -103,7 +105,7 @@ GNU89INLINE inline VISIBLE #endif vec4d_t -vsqrtd (vec4d_t v) +vsqrt4d (vec4d_t v) { return _mm256_sqrt_pd (v); } @@ -114,7 +116,7 @@ GNU89INLINE inline VISIBLE #endif vec4d_t -vceild (vec4d_t v) +vceil4d (vec4d_t v) { return _mm256_ceil_pd (v); } @@ -125,7 +127,7 @@ GNU89INLINE inline VISIBLE #endif vec4d_t -vfloord (vec4d_t v) +vfloor4d (vec4d_t v) { return _mm256_floor_pd (v); } @@ -136,7 +138,7 @@ GNU89INLINE inline VISIBLE #endif vec4d_t -vtruncd (vec4d_t v) +vtrunc4d (vec4d_t v) { return _mm256_round_pd (v, _MM_FROUND_TRUNC); } @@ -241,11 +243,11 @@ VISIBLE vec4d_t qrotd (vec4d_t a, vec4d_t b) { - vec4d_t ma = vsqrtd (dotd (a, a)); - vec4d_t mb = vsqrtd (dotd (b, b)); + vec4d_t ma = vsqrt4d (dotd (a, a)); + vec4d_t mb = vsqrt4d (dotd (b, b)); vec4d_t den = 2 * ma * mb; vec4d_t t = mb * a + ma * b; - vec4d_t mba_mab = vsqrtd (dotd (t, t)); + vec4d_t mba_mab = vsqrt4d (dotd (t, t)); vec4d_t q = crossd (a, b) / mba_mab; q[3] = (mba_mab / den)[0]; return q; @@ -293,6 +295,31 @@ storevec3d (double v3[3], vec4d_t v4) v3[2] = v4[2]; } +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4l_t +loadvec3l (const long *v3) +{ + vec4l_t v4 = { v3[0], v3[1], v3[2], 0 }; + return v4; +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +storevec3l (long *v3, vec4l_t v4) +{ + v3[0] = v4[0]; + v3[1] = v4[1]; + v3[2] = v4[2]; +} + #endif #endif//__QF_simd_vec4d_h diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 6bb0ae4ec..9105e7952 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -33,11 +33,11 @@ #include "QF/simd/types.h" -GNU89INLINE inline vec4f_t vabsf (vec4f_t v) __attribute__((const)); -GNU89INLINE inline vec4f_t vsqrtf (vec4f_t v) __attribute__((const)); -GNU89INLINE inline vec4f_t vceilf (vec4f_t v) __attribute__((const)); -GNU89INLINE inline vec4f_t vfloorf (vec4f_t v) __attribute__((const)); -GNU89INLINE inline vec4f_t vtruncf (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vabs4f (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vsqrt4f (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vceil4f (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vfloor4f (vec4f_t v) __attribute__((const)); +GNU89INLINE inline vec4f_t vtrunc4f (vec4f_t v) __attribute__((const)); /** 3D vector cross product. * * The w (4th) component can be any value on input, and is guaranteed to be 0 @@ -99,6 +99,8 @@ GNU89INLINE inline void storevec3f (float *v3, vec4f_t v4); GNU89INLINE inline vec4f_t normalf (vec4f_t v) __attribute__((pure)); GNU89INLINE inline vec4f_t magnitudef (vec4f_t v) __attribute__((pure)); GNU89INLINE inline vec4f_t magnitude3f (vec4f_t v) __attribute__((pure)); +GNU89INLINE inline vec4i_t loadvec3i (const int *v3) __attribute__((pure)); +GNU89INLINE inline void storevec3i (int *v3, vec4i_t v4); #ifndef IMPLEMENT_VEC4F_Funcs GNU89INLINE inline @@ -106,7 +108,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vabsf (vec4f_t v) +vabs4f (vec4f_t v) { const uint32_t nan = ~0u >> 1; const vec4i_t abs = { nan, nan, nan, nan }; @@ -119,7 +121,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vsqrtf (vec4f_t v) +vsqrt4f (vec4f_t v) { #ifndef __SSE__ vec4f_t r = { sqrtf (v[0]), sqrtf (v[1]), sqrtf (v[2]), sqrtf (v[3]) }; @@ -135,7 +137,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vceilf (vec4f_t v) +vceil4f (vec4f_t v) { #ifndef __SSE4_1__ return (vec4f_t) { @@ -155,7 +157,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vfloorf (vec4f_t v) +vfloor4f (vec4f_t v) { #ifndef __SSE4_1__ return (vec4f_t) { @@ -175,7 +177,7 @@ GNU89INLINE inline VISIBLE #endif vec4f_t -vtruncf (vec4f_t v) +vtrunc4f (vec4f_t v) { #ifndef __SSE4_1__ return (vec4f_t) { @@ -296,11 +298,11 @@ VISIBLE vec4f_t qrotf (vec4f_t a, vec4f_t b) { - vec4f_t ma = vsqrtf (dotf (a, a)); - vec4f_t mb = vsqrtf (dotf (b, b)); + vec4f_t ma = vsqrt4f (dotf (a, a)); + vec4f_t mb = vsqrt4f (dotf (b, b)); vec4f_t den = 2 * ma * mb; vec4f_t t = mb * a + ma * b; - vec4f_t mba_mab = vsqrtf (dotf (t, t)); + vec4f_t mba_mab = vsqrt4f (dotf (t, t)); vec4f_t q = crossf (a, b) / mba_mab; q[3] = (mba_mab / den)[0]; return q; @@ -388,7 +390,7 @@ VISIBLE vec4f_t normalf (vec4f_t v) { - return v / vsqrtf (dotf (v, v)); + return v / vsqrt4f (dotf (v, v)); } #ifndef IMPLEMENT_VEC4F_Funcs @@ -399,7 +401,7 @@ VISIBLE vec4f_t magnitudef (vec4f_t v) { - return vsqrtf (dotf (v, v)); + return vsqrt4f (dotf (v, v)); } #ifndef IMPLEMENT_VEC4F_Funcs @@ -411,7 +413,7 @@ vec4f_t magnitude3f (vec4f_t v) { v[3] = 0; - return vsqrtf (dotf (v, v)); + return vsqrt4f (dotf (v, v)); } vec4f_t __attribute__((pure)) @@ -422,4 +424,29 @@ CircumSphere_vf (const vec4f_t *points, int num_points); vspheref_t SmallestEnclosingBall_vf (const vec4f_t *points, int num_points); +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4i_t +loadvec3i (const int *v3) +{ + vec4i_t v4 = { v3[0], v3[1], v3[2], 0 }; + return v4; +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +storevec3i (int *v3, vec4i_t v4) +{ + v3[0] = v4[0]; + v3[1] = v4[1]; + v3[2] = v4[2]; +} + #endif//__QF_simd_vec4f_h diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 9ecba1804..b5260203e 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -425,7 +425,7 @@ vector_rem (const exprval_t *val1, const exprval_t *val2, exprval_t *result, vec4f_t a = *(vec4f_t *) val1->value; vec4f_t b = *(vec4f_t *) val2->value; __auto_type c = (vec4f_t *) result->value; - *c = a - b * vtruncf (a / b); + *c = a - b * vtrunc4f (a / b); } static void @@ -440,7 +440,7 @@ vector_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, vec4f_t a = *(vec4f_t *) val1->value; vec4f_t b = *(vec4f_t *) val2->value; __auto_type c = (vec4f_t *) result->value; - *c = a - b * vfloorf (a / b); + *c = a - b * vfloor4f (a / b); } static void diff --git a/libs/util/simd.c b/libs/util/simd.c index f10c97acd..c6cedf222 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -32,11 +32,15 @@ #include +#define IMPLEMENT_VEC2F_Funcs +#define IMPLEMENT_VEC2D_Funcs #define IMPLEMENT_VEC4F_Funcs #define IMPLEMENT_VEC4D_Funcs #define IMPLEMENT_MAT4F_Funcs #include "QF/mathlib.h" +#include "QF/simd/vec2d.h" +#include "QF/simd/vec2f.h" #include "QF/simd/vec4d.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index ae2fd6547..d1b4bf286 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -97,17 +97,17 @@ typedef struct { #ifdef __AVX2__ static vec4d_t tvtruncd (vec4d_t v, vec4d_t ignore) { - return vtruncd (v); + return vtrunc4d (v); } static vec4d_t tvceild (vec4d_t v, vec4d_t ignore) { - return vceild (v); + return vceil4d (v); } static vec4d_t tvfloord (vec4d_t v, vec4d_t ignore) { - return vfloord (v); + return vfloor4d (v); } static vec4d_t tqconjd (vec4d_t v, vec4d_t ignore) @@ -118,17 +118,17 @@ static vec4d_t tqconjd (vec4d_t v, vec4d_t ignore) static vec4f_t tvtruncf (vec4f_t v, vec4f_t ignore) { - return vtruncf (v); + return vtrunc4f (v); } static vec4f_t tvceilf (vec4f_t v, vec4f_t ignore) { - return vceilf (v); + return vceil4f (v); } static vec4f_t tvfloorf (vec4f_t v, vec4f_t ignore) { - return vfloorf (v); + return vfloor4f (v); } static vec4f_t tqconjf (vec4f_t v, vec4f_t ignore) @@ -138,12 +138,12 @@ static vec4f_t tqconjf (vec4f_t v, vec4f_t ignore) static vec4f_t tvabsf (vec4f_t v, vec4f_t ignore) { - return vabsf (v); + return vabs4f (v); } static vec4f_t tvsqrtf (vec4f_t v, vec4f_t ignore) { - return vsqrtf (v); + return vsqrt4f (v); } static vec4f_t tmagnitudef (vec4f_t v, vec4f_t ignore) diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 27399eead..93ee0ec96 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -156,7 +156,7 @@ calc_plane (vec4f_t v1, vec4f_t v2, int flip, vec4f_t p, vec4f_t *plane) if (length[0] < ON_EPSILON) return 0; - *plane /= vsqrtf (length); + *plane /= vsqrt4f (length); (*plane)[3] = -dotf (p, *plane)[0]; return 1; } @@ -371,7 +371,7 @@ RecursiveClusterFlow (int clusternum, threaddata_t *thread, pstack_t *prevstack) // get plane of target_portal, point normal into the neighbor cluster backplane = -target_portal->plane; - vec4f_t diff = vabsf (pass_plane - backplane); + vec4f_t diff = vabs4f (pass_plane - backplane); vec4i_t cmp = diff > (vec4f_t) {0.001, 0.001, 0.001, 0.001}; if (!(cmp[0] || cmp[1] || cmp[2])) { // dist isn't interesting continue; // can't go out a coplanar face From 9aa8f18d73155f781aaf9907af6a8774a665e586 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 01:06:22 +0900 Subject: [PATCH 2078/3664] [math] Split out Quat/Vector compare implementations This renames existing VectorCompCompare (and quaternion equivalent) to VectorCompCompareAll and makes VectorCompCompare produce a vector of results with optional negation (converting 0,1 to 0,-1 for compatibility with simd semantics). --- include/QF/math/quaternion.h | 11 +++++++++-- include/QF/math/vector.h | 10 ++++++++-- nq/source/sv_phys.c | 4 ++-- qw/source/sv_phys.c | 4 ++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/include/QF/math/quaternion.h b/include/QF/math/quaternion.h index da39b7734..60245ad77 100644 --- a/include/QF/math/quaternion.h +++ b/include/QF/math/quaternion.h @@ -115,10 +115,17 @@ extern const vec_t *const quat_origin; (c)[2] = (a)[2] / (b)[2]; \ (c)[3] = (a)[3] / (b)[3]; \ } while (0) -#define QuatCompCompare(x, op, y) \ +#define QuatCompCompare(m, a, op, b, c) \ + do { \ + (c)[0] = m((a)[0] op (b)[0]); \ + (c)[1] = m((a)[1] op (b)[1]); \ + (c)[2] = m((a)[2] op (b)[2]); \ + (c)[3] = m((a)[3] op (b)[3]); \ + } while (0) +#define QuatCompCompareAll(x, op, y) \ (((x)[0] op (y)[0]) && ((x)[1] op (y)[1]) \ && ((x)[2] op (y)[2]) && ((x)[3] op (y)[3])) -#define QuatCompare(x, y) QuatCompCompare (x, ==, y) +#define QuatCompare(x, y) QuatCompCompareAll (x, ==, y) #define QuatCompMin(a, b, c) \ do { \ (c)[0] = min ((a)[0], (b)[0]); \ diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 6189d002c..100a98bd0 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -131,9 +131,15 @@ extern const vec_t *const vec3_origin; (c)[1] = (a)[1] / (b)[1]; \ (c)[2] = (a)[2] / (b)[2]; \ } while (0) -#define VectorCompCompare(x, op, y) \ +#define VectorCompCompare(c, m, a, op, b) \ + do { \ + (c)[0] = m((a)[0] op (b)[0]); \ + (c)[1] = m((a)[1] op (b)[1]); \ + (c)[2] = m((a)[2] op (b)[2]); \ + } while (0) +#define VectorCompCompareAll(x, op, y) \ (((x)[0] op (y)[0]) && ((x)[1] op (y)[1]) && ((x)[2] op (y)[2])) -#define VectorCompare(x, y) VectorCompCompare (x, ==, y) +#define VectorCompare(x, y) VectorCompCompareAll (x, ==, y) #define VectorCompMin(a, b, c) \ do { \ (c)[0] = min ((a)[0], (b)[0]); \ diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index ffaf35ae1..e017039a6 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -484,8 +484,8 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) // entity? c_absmin = SVvector (check, absmin); c_absmax = SVvector (check, absmax); - if (VectorCompCompare (c_absmin, >=, maxs) - || VectorCompCompare (c_absmax, <=, mins)) + if (VectorCompCompareAll (c_absmin, >=, maxs) + || VectorCompCompareAll (c_absmax, <=, mins)) continue; if (!SV_TestEntityPosition (check)) diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index 41ae45ccd..79047699e 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -487,8 +487,8 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) // entity? c_absmin = SVvector (check, absmin); c_absmax = SVvector (check, absmax); - if (VectorCompCompare (c_absmin, >=, maxs) - || VectorCompCompare (c_absmax, <=, mins)) + if (VectorCompCompareAll (c_absmin, >=, maxs) + || VectorCompCompareAll (c_absmax, <=, mins)) continue; if (!SV_TestEntityPosition (check)) From 937f36384b8c42fc46c8b5a8e470b70c7d023cdb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 01:13:17 +0900 Subject: [PATCH 2079/3664] [cexpr] Use correct functions for double trunc/floor Found while sorting out the changes for the new 2d vectors. --- libs/util/cexpr-type.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index b5260203e..1efbb2f2a 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -350,7 +350,7 @@ double_rem (const exprval_t *val1, const exprval_t *val2, exprval_t *result, { double a = *(double *) val1->value; double b = *(double *) val2->value; - *(double *) result->value = a - b * truncf (a / b); + *(double *) result->value = a - b * trunc (a / b); } static void @@ -364,7 +364,7 @@ double_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, // -5 mod -3 = -2 double a = *(double *) val1->value; double b = *(double *) val2->value; - *(double *) result->value = a - b * floorf (a / b); + *(double *) result->value = a - b * floor (a / b); } CASTOP (double, int) From 5fb28d7c38106a45894659b84cf6c34717066e17 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 01:15:17 +0900 Subject: [PATCH 2080/3664] [math] Clean up vector component operations And add a unary op macro. Having VectorCompOp makes it easy to write macros that work for multiple data widths, which is why it and its users now use (dst, ...) instead of (..., dst) as in the past. I'll sort out the other macros later now that I know the compiler handily gives messages about the switched order (uninitialized vars etc). --- include/QF/math/vector.h | 50 +++++++++++++++----------------------- libs/models/trace.c | 22 ++++++++--------- libs/util/test/test-mat3.c | 6 ++--- libs/util/test/test-mat4.c | 6 ++--- 4 files changed, 37 insertions(+), 47 deletions(-) diff --git a/include/QF/math/vector.h b/include/QF/math/vector.h index 100a98bd0..f45893f50 100644 --- a/include/QF/math/vector.h +++ b/include/QF/math/vector.h @@ -37,25 +37,27 @@ extern const vec_t *const vec3_origin; +#define VectorCompUop(b, op, a) \ + do { \ + (b)[0] = op ((a)[0]); \ + (b)[1] = op ((a)[1]); \ + (b)[2] = op ((a)[2]); \ + } while (0) +#define VectorCompOp(c, a, op, b) \ + do { \ + (c)[0] = (a)[0] op (b)[0]; \ + (c)[1] = (a)[1] op (b)[1]; \ + (c)[2] = (a)[2] op (b)[2]; \ + } while (0) +#define VectorCompAdd(c,a,b) VectorCompOp (c, a, +, b) +#define VectorCompSub(c,a,b) VectorCompOp (c, a, -, b) +#define VectorCompMult(c,a,b) VectorCompOp (c, a, *, b) +#define VectorCompDiv(c,a,b) VectorCompOp (c, a, /, b) + #define DotProduct(a,b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2]) -#define VectorSubtract(a,b,c) \ - do { \ - (c)[0] = (a)[0] - (b)[0]; \ - (c)[1] = (a)[1] - (b)[1]; \ - (c)[2] = (a)[2] - (b)[2]; \ - } while (0) -#define VectorNegate(a,b) \ - do { \ - (b)[0] = -(a)[0]; \ - (b)[1] = -(a)[1]; \ - (b)[2] = -(a)[2]; \ - } while (0) -#define VectorAdd(a,b,c) \ - do { \ - (c)[0] = (a)[0] + (b)[0]; \ - (c)[1] = (a)[1] + (b)[1]; \ - (c)[2] = (a)[2] + (b)[2]; \ - } while (0) +#define VectorSubtract(a,b,c) VectorCompSub (c, a, b) +#define VectorNegate(a,b) VectorCompUop (b, -, a) +#define VectorAdd(a,b,c) VectorCompAdd (c, a, b) #define VectorCopy(a,b) \ do { \ (b)[0] = (a)[0]; \ @@ -119,18 +121,6 @@ extern const vec_t *const vec3_origin; (c)[1] = (b)[1] - (b)[0] * (a)[0]; \ (c)[0] = (b)[0]; \ } while (0) -#define VectorCompMult(a,b,c) \ - do { \ - (c)[0] = (a)[0] * (b)[0]; \ - (c)[1] = (a)[1] * (b)[1]; \ - (c)[2] = (a)[2] * (b)[2]; \ - } while (0) -#define VectorCompDiv(a,b,c) \ - do { \ - (c)[0] = (a)[0] / (b)[0]; \ - (c)[1] = (a)[1] / (b)[1]; \ - (c)[2] = (a)[2] / (b)[2]; \ - } while (0) #define VectorCompCompare(c, m, a, op, b) \ do { \ (c)[0] = m((a)[0] op (b)[0]); \ diff --git a/libs/models/trace.c b/libs/models/trace.c index 1fcecb47b..d65a06c9a 100644 --- a/libs/models/trace.c +++ b/libs/models/trace.c @@ -120,7 +120,7 @@ init_box (const trace_t *trace, clipbox_t *box, const vec3_t vel) //FIXME rotated box for (i = 0; i < 3; i++) u[i] = (vel[i] >= 0 ? 1 : -1); - VectorCompMult (u, trace->extents, p); + VectorCompMult (p, u, trace->extents); for (i = 0; i < 3; i++) { box->portals[i].planenum = i; box->portals[i].next[0] = 0; @@ -153,17 +153,17 @@ init_box (const trace_t *trace, clipbox_t *box, const vec3_t vel) box->edges[i].points[j][a] = s[k] * u[i] * box->edges[i].points[j - 1][b]; } - VectorCompMult (box->points[i].points[j - 1], trace->extents, - box->points[i].points[j - 1]); - VectorCompMult (box->edges[i].points[j - 1], trace->extents, - box->edges[i].points[j - 1]); + VectorCompMult (box->points[i].points[j - 1], + box->points[i].points[j - 1], trace->extents); + VectorCompMult (box->edges[i].points[j - 1], + box->edges[i].points[j - 1], trace->extents); VectorScale (box->edges[i].points[j - 1], 2, box->edges[i].points[j - 1]); } - VectorCompMult (box->points[i].points[3], trace->extents, - box->points[i].points[3]); - VectorCompMult (box->edges[i].points[3], trace->extents, - box->edges[i].points[3]); + VectorCompMult (box->points[i].points[3], + box->points[i].points[3], trace->extents); + VectorCompMult (box->edges[i].points[3], + box->edges[i].points[3], trace->extents); VectorScale (box->edges[i].points[3], 2, box->edges[i].points[3]); } @@ -566,8 +566,8 @@ portal_intersect (trace_t *trace, clipport_t *portal, plane_t *plane, vec3_t p1, p2, imp, dist; vec_t t1, t2, frac; - VectorCompMult (trace->extents, verts[i][0], p1); - VectorCompMult (trace->extents, verts[i][1], p2); + VectorCompMult (p1, trace->extents, verts[i][0]); + VectorCompMult (p2, trace->extents, verts[i][1]); t1 = PlaneDiff (p1, plane) + o_n; t2 = PlaneDiff (p2, plane) + o_n; // if both ends of the box edge are on the same side (or touching) the diff --git a/libs/util/test/test-mat3.c b/libs/util/test/test-mat3.c index 903c4de9f..9134fb9c2 100644 --- a/libs/util/test/test-mat3.c +++ b/libs/util/test/test-mat3.c @@ -99,7 +99,7 @@ test_transform (const vec3_t angles, const vec3_t scale) VectorCopy (v, x); AngleQuat (angles, rotation); - VectorCompMult (scale, x, x); + VectorCompMult (x, scale, x); QuatMultVec (rotation, x, x); Mat3Init (rotation, scale, mat); @@ -132,7 +132,7 @@ test_transform2 (const vec3_t angles, const vec3_t scale) VectorCopy (v, x); AngleQuat (angles, rotation); - VectorCompMult (scale, x, x); + VectorCompMult (x, scale, x); QuatMultVec (rotation, x, x); Mat3Init (rotation, scale, mat); @@ -141,7 +141,7 @@ test_transform2 (const vec3_t angles, const vec3_t scale) VectorCopy (v, y); QuatMultVec (rot, y, y); VectorShear (sh, y, y); - VectorCompMult (sc, y, y);//scale + VectorCompMult (y, sc, y);//scale for (i = 0; i < 3; i++) if (!compare (x[i], y[i])) diff --git a/libs/util/test/test-mat4.c b/libs/util/test/test-mat4.c index 1bd7afcc9..cd30c0990 100644 --- a/libs/util/test/test-mat4.c +++ b/libs/util/test/test-mat4.c @@ -114,7 +114,7 @@ test_transform (const vec3_t angles, const vec3_t scale, VectorCopy (v, x); AngleQuat (angles, rotation); - VectorCompMult (scale, x, x); + VectorCompMult (x, scale, x); QuatMultVec (rotation, x, x); VectorAdd (x, translation, x); @@ -148,7 +148,7 @@ test_transform2 (const vec3_t angles, const vec3_t scale, VectorCopy (v, x); AngleQuat (angles, rotation); - VectorCompMult (scale, x, x); + VectorCompMult (x, scale, x); QuatMultVec (rotation, x, x); VectorAdd (translation, x, x); @@ -158,7 +158,7 @@ test_transform2 (const vec3_t angles, const vec3_t scale, VectorCopy (v, y); QuatMultVec (rot, y, y); VectorShear (sh, y, y); - VectorCompMult (sc, y, y);//scale + VectorCompMult (y, sc, y);//scale VectorAdd (tr, y, y); for (i = 0; i < 3; i++) From f56fd6ffb6bac7af3cf68c467b6efd3ac85d9068 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 11:42:27 +0900 Subject: [PATCH 2081/3664] [qfcc] Preserve requested alignment if larger build_struct was unconditionally setting the type's alignment. This was not a problem before because no types were requesting alignments larger than those requested by their members (for structs). However, with the upcoming new instruction set, quaternions need to be 4-word aligned. --- tools/qfcc/source/struct.c | 4 +++- tools/qfcc/source/type.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index ef9bd7389..4bd82130c 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -171,7 +171,9 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) if (!type) sym->type = find_type (sym->type); // checks the tag, not the symtab sym->type->t.symtab = symtab; - sym->type->alignment = alignment; + if (alignment > sym->type->alignment) { + sym->type->alignment = alignment; + } if (!type && sym->type->type_def->external) //FIXME should not be necessary sym->type->type_def = qfo_encode_type (sym->type, pr.type_data); return sym; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 3c6a4a683..bccf431b7 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -74,7 +74,7 @@ type_t type_function = { ev_func, "function", 1, ty_basic, {{&type_void}} }; type_t type_pointer = { ev_pointer, "pointer", 1, ty_basic, {{&type_void}} }; -type_t type_quaternion = { ev_quat, "quaternion", 1 }; +type_t type_quaternion = { ev_quat, "quaternion", 4 }; type_t type_integer = { ev_integer, "int", 1 }; type_t type_uinteger = { ev_uinteger, "uint", 1 }; type_t type_short = { ev_short, "short", 1 }; From 0e1964bf74987f882260d4b9ed44007e4e484971 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 16:02:57 +0900 Subject: [PATCH 2082/3664] [simd] Split out the ivec implementations And add any/all/none functions. --- include/QF/simd/vec2i.h | 90 +++++++++++++++++++++++++++++ include/QF/simd/vec4f.h | 27 --------- include/QF/simd/vec4i.h | 123 ++++++++++++++++++++++++++++++++++++++++ libs/util/simd.c | 4 ++ 4 files changed, 217 insertions(+), 27 deletions(-) create mode 100644 include/QF/simd/vec2i.h create mode 100644 include/QF/simd/vec4i.h diff --git a/include/QF/simd/vec2i.h b/include/QF/simd/vec2i.h new file mode 100644 index 000000000..694d5fa7b --- /dev/null +++ b/include/QF/simd/vec2i.h @@ -0,0 +1,90 @@ +/* + QF/simd/vec2i.h + + Vector functions for vec2i_t (ie, int) + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec2i_h +#define __QF_simd_vec2i_h + +#include +#include + +#include "QF/simd/types.h" + +GNU89INLINE inline vec2i_t vabs2i (vec2i_t v) __attribute__((const)); +GNU89INLINE inline int any2i (vec2i_t v) __attribute__((const)); +GNU89INLINE inline int all2i (vec2i_t v) __attribute__((const)); +GNU89INLINE inline int none2i (vec2i_t v) __attribute__((const)); + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec2i_t +vabs2i (vec2i_t v) +{ + const uint32_t nan = ~0u >> 1; + const vec2i_t abs = { nan, nan }; + return (vec2i_t) ((vec2i_t) v & abs); +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +any2i (vec2i_t v) +{ + vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); + return _mm_hadd_pi32 (t, t)[0] > -2; +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +all2i (vec2i_t v) +{ + vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); + return _mm_hadd_pi32 (t, t)[0] == 0; +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +none2i (vec2i_t v) +{ + vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); + return _mm_hadd_pi32 (t, t)[0] == -2; +} + +#endif//__QF_simd_vec2i_h diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 9105e7952..7b7c8429d 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -99,8 +99,6 @@ GNU89INLINE inline void storevec3f (float *v3, vec4f_t v4); GNU89INLINE inline vec4f_t normalf (vec4f_t v) __attribute__((pure)); GNU89INLINE inline vec4f_t magnitudef (vec4f_t v) __attribute__((pure)); GNU89INLINE inline vec4f_t magnitude3f (vec4f_t v) __attribute__((pure)); -GNU89INLINE inline vec4i_t loadvec3i (const int *v3) __attribute__((pure)); -GNU89INLINE inline void storevec3i (int *v3, vec4i_t v4); #ifndef IMPLEMENT_VEC4F_Funcs GNU89INLINE inline @@ -424,29 +422,4 @@ CircumSphere_vf (const vec4f_t *points, int num_points); vspheref_t SmallestEnclosingBall_vf (const vec4f_t *points, int num_points); -#ifndef IMPLEMENT_VEC4F_Funcs -GNU89INLINE inline -#else -VISIBLE -#endif -vec4i_t -loadvec3i (const int *v3) -{ - vec4i_t v4 = { v3[0], v3[1], v3[2], 0 }; - return v4; -} - -#ifndef IMPLEMENT_VEC4F_Funcs -GNU89INLINE inline -#else -VISIBLE -#endif -void -storevec3i (int *v3, vec4i_t v4) -{ - v3[0] = v4[0]; - v3[1] = v4[1]; - v3[2] = v4[2]; -} - #endif//__QF_simd_vec4f_h diff --git a/include/QF/simd/vec4i.h b/include/QF/simd/vec4i.h new file mode 100644 index 000000000..6320cd83a --- /dev/null +++ b/include/QF/simd/vec4i.h @@ -0,0 +1,123 @@ +/* + QF/simd/vec4i.h + + Vector functions for vec4i_t (ie, int) + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_simd_vec4i_h +#define __QF_simd_vec4i_h + +#include +#include + +#include "QF/simd/types.h" + +GNU89INLINE inline vec4i_t vabs4i (vec4i_t v) __attribute__((const)); +GNU89INLINE inline int any4i (vec4i_t v) __attribute__((const)); +GNU89INLINE inline int all4i (vec4i_t v) __attribute__((const)); +GNU89INLINE inline int none4i (vec4i_t v) __attribute__((const)); +GNU89INLINE inline vec4i_t loadvec3i (const int *v3) __attribute__((pure)); +GNU89INLINE inline void storevec3i (int *v3, vec4i_t v4); + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4i_t +vabs4i (vec4i_t v) +{ + const uint32_t nan = ~0u >> 1; + const vec4i_t abs = { nan, nan, nan, nan }; + return (vec4i_t) ((vec4i_t) v & abs); +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +any4i (vec4i_t v) +{ + return !__builtin_ia32_ptestz128 ((__v2di)v, (__v2di)v); + /*vec4i_t t = (v != (vec4i_t) {}); + t = __builtin_ia32_phaddd128 (t, t); + return __builtin_ia32_phaddd128 (t, t)[0] != 0;*/ +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +all4i (vec4i_t v) +{ + vec4i_t t = (v == (vec4i_t) {}); + return __builtin_ia32_ptestz128 ((__v2di)t, (__v2di)t); + /*t = __builtin_ia32_phaddd128 (t, t); + return __builtin_ia32_phaddd128 (t, t)[0] == 0;*/ +} + +#ifndef IMPLEMENT_VEC2I_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +int +none4i (vec4i_t v) +{ + return __builtin_ia32_ptestz128 ((__v2di)v, (__v2di)v); + /*vec4i_t t = (v != (vec4i_t) {}); + t = __builtin_ia32_phaddd128 (t, t); + return __builtin_ia32_phaddd128 (t, t)[0] == 0;*/ +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4i_t +loadvec3i (const int *v3) +{ + vec4i_t v4 = { v3[0], v3[1], v3[2], 0 }; + return v4; +} + +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +void +storevec3i (int *v3, vec4i_t v4) +{ + v3[0] = v4[0]; + v3[1] = v4[1]; + v3[2] = v4[2]; +} + +#endif//__QF_simd_vec4i_h diff --git a/libs/util/simd.c b/libs/util/simd.c index c6cedf222..352a4169a 100644 --- a/libs/util/simd.c +++ b/libs/util/simd.c @@ -34,15 +34,19 @@ #define IMPLEMENT_VEC2F_Funcs #define IMPLEMENT_VEC2D_Funcs +#define IMPLEMENT_VEC2I_Funcs #define IMPLEMENT_VEC4F_Funcs #define IMPLEMENT_VEC4D_Funcs +#define IMPLEMENT_VEC4I_Funcs #define IMPLEMENT_MAT4F_Funcs #include "QF/mathlib.h" #include "QF/simd/vec2d.h" #include "QF/simd/vec2f.h" +#include "QF/simd/vec2i.h" #include "QF/simd/vec4d.h" #include "QF/simd/vec4f.h" +#include "QF/simd/vec4i.h" #include "QF/simd/mat4f.h" #include "QF/set.h" #include "QF/sys.h" From 63442895fcdfba70fd7a5107f4bcbf26192b6bfc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 16:10:37 +0900 Subject: [PATCH 2083/3664] [simd] Add the new headers to dist --- include/QF/Makemodule.am | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index ff47836db..77f56e29b 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -145,8 +145,12 @@ include_qf_scene = \ include_qf_simd = \ include/QF/simd/mat4f.h \ include/QF/simd/types.h \ + include/QF/simd/vec2d.h \ + include/QF/simd/vec2f.h \ + include/QF/simd/vec2i.h \ include/QF/simd/vec4d.h \ - include/QF/simd/vec4f.h + include/QF/simd/vec4f.h \ + include/QF/simd/vec4i.h include_qf_ui = \ include/QF/ui/inputline.h \ From c42043ced408e3861a7ccf68abe493d2fad72d36 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 17:48:43 +0900 Subject: [PATCH 2084/3664] [gamecode] Add types needed for new instruction set In particular, the various 2d and 4d vector types, and 64-bit types. Also, some aliases to make instruction implementation macros workable. --- include/QF/pr_comp.h | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 5d5efe942..1303fb2c5 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -23,13 +23,35 @@ #include "QF/qtypes.h" +typedef double pr_double_t; +typedef float pr_float_t; typedef int16_t pr_short_t; typedef uint16_t pr_ushort_t; typedef int32_t pr_int_t; typedef uint32_t pr_uint_t; +typedef int64_t pr_long_t; +typedef uint64_t pr_ulong_t; typedef pr_uint_t func_t; -typedef pr_int_t string_t; -typedef pr_uint_t pointer_t; +typedef pr_int_t pr_string_t; +typedef pr_string_t string_t;//FIXME +typedef pr_uint_t pr_pointer_t; +typedef pr_pointer_t pointer_t;//FIXME + +#define PR_VEC_TYPE(t,n,s) \ + typedef t n __attribute__ ((vector_size (s*sizeof (t)))) + +PR_VEC_TYPE (pr_int_t, pr_ivec2_t, 2); +PR_VEC_TYPE (pr_int_t, pr_ivec4_t, 4); +PR_VEC_TYPE (pr_uint_t, pr_uivec2_t, 2); +PR_VEC_TYPE (pr_uint_t, pr_uivec4_t, 4); +PR_VEC_TYPE (float, pr_vec2_t, 2); +PR_VEC_TYPE (float, pr_vec4_t, 4); +PR_VEC_TYPE (pr_long_t, pr_lvec2_t, 2); +PR_VEC_TYPE (pr_long_t, pr_lvec4_t, 4); +PR_VEC_TYPE (pr_ulong_t, pr_ulvec2_t, 2); +PR_VEC_TYPE (pr_ulong_t, pr_ulvec4_t, 4); +PR_VEC_TYPE (double, pr_dvec2_t, 2); +PR_VEC_TYPE (double, pr_dvec4_t, 4); typedef enum { ev_void, From ba5f6d97c680b8e40f86f4b6f1bd371c9147e110 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 19:02:48 +0900 Subject: [PATCH 2085/3664] [gamecode] Remove the right_associative field It has been useless pretty much since I switched to using bison for the parser. --- include/QF/pr_comp.h | 1 - libs/gamecode/pr_opcode.c | 585 +++++++++++++++++++------------------- 2 files changed, 293 insertions(+), 293 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 1303fb2c5..971584070 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -427,7 +427,6 @@ typedef enum { typedef struct opcode_s { const char *name; const char *opname; - qboolean right_associative; etype_t type_a, type_b, type_c; unsigned int min_version; const char *fmt; diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 62239c561..955cc0796 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -96,1412 +96,1413 @@ VISIBLE const char * const pr_type_name[ev_type_count] = { // x place holder for P (padding) // 0-7 parameter index (for P) VISIBLE const opcode_t pr_opcodes[] = { - [OP_DONE] = {"", "done", false, // OP_DONE is actually the same as - ev_entity, ev_field, ev_void, // OP_RETURN, the types are bogus + // OP_DONE is actually the same as OP_RETURN, the types are bogus + [OP_DONE] = {"", "done", + ev_entity, ev_field, ev_void, PROG_ID_VERSION, "%Va", }, - [OP_MUL_D] = {"*", "mul.d", false, + [OP_MUL_D] = {"*", "mul.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_MUL_F] = {"*", "mul.f", false, + [OP_MUL_F] = {"*", "mul.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_MUL_V] = {"*", "mul.v", false, + [OP_MUL_V] = {"*", "mul.v", ev_vector, ev_vector, ev_float, PROG_ID_VERSION, }, - [OP_MUL_FV] = {"*", "mul.fv", false, + [OP_MUL_FV] = {"*", "mul.fv", ev_float, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_VF] = {"*", "mul.vf", false, + [OP_MUL_VF] = {"*", "mul.vf", ev_vector, ev_float, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_DV] = {"*", "mul.dv", false, + [OP_MUL_DV] = {"*", "mul.dv", ev_double, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_VD] = {"*", "mul.vd", false, + [OP_MUL_VD] = {"*", "mul.vd", ev_vector, ev_double, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_Q] = {"*", "mul.q", false, + [OP_MUL_Q] = {"*", "mul.q", ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - [OP_MUL_FQ] = {"*", "mul.fq", false, + [OP_MUL_FQ] = {"*", "mul.fq", ev_float, ev_quat, ev_quat, PROG_VERSION, }, - [OP_MUL_QF] = {"*", "mul.qf", false, + [OP_MUL_QF] = {"*", "mul.qf", ev_quat, ev_float, ev_quat, PROG_VERSION, }, - [OP_MUL_DQ] = {"*", "mul.dq", false, + [OP_MUL_DQ] = {"*", "mul.dq", ev_double, ev_quat, ev_quat, PROG_VERSION, }, - [OP_MUL_QD] = {"*", "mul.qd", false, + [OP_MUL_QD] = {"*", "mul.qd", ev_quat, ev_double, ev_quat, PROG_VERSION, }, - [OP_MUL_QV] = {"*", "mul.qv", false, + [OP_MUL_QV] = {"*", "mul.qv", ev_quat, ev_vector, ev_vector, PROG_VERSION, }, - [OP_CONJ_Q] = {"~", "conj.q", false, + [OP_CONJ_Q] = {"~", "conj.q", ev_quat, ev_invalid, ev_quat, PROG_VERSION, "%Ga, %gc", }, - [OP_DIV_F] = {"/", "div.f", false, + [OP_DIV_F] = {"/", "div.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_DIV_D] = {"/", "div.d", false, + [OP_DIV_D] = {"/", "div.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_REM_D] = {"%", "rem.d", false, + [OP_REM_D] = {"%", "rem.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_MOD_D] = {"%%", "mod.d", false, + [OP_MOD_D] = {"%%", "mod.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_ADD_D] = {"+", "add.d", false, + [OP_ADD_D] = {"+", "add.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_ADD_F] = {"+", "add.f", false, + [OP_ADD_F] = {"+", "add.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_ADD_V] = {"+", "add.v", false, + [OP_ADD_V] = {"+", "add.v", ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_ADD_Q] = {"+", "add.q", false, + [OP_ADD_Q] = {"+", "add.q", ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - [OP_ADD_S] = {"+", "add.s", false, + [OP_ADD_S] = {"+", "add.s", ev_string, ev_string, ev_string, PROG_VERSION, }, - [OP_SUB_D] = {"-", "sub.d", false, + [OP_SUB_D] = {"-", "sub.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_SUB_F] = {"-", "sub.f", false, + [OP_SUB_F] = {"-", "sub.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_SUB_V] = {"-", "sub.v", false, + [OP_SUB_V] = {"-", "sub.v", ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_SUB_Q] = {"-", "sub.q", false, + [OP_SUB_Q] = {"-", "sub.q", ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - [OP_EQ_D] = {"==", "eq.d", false, + [OP_EQ_D] = {"==", "eq.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_EQ_F] = {"==", "eq.f", false, + [OP_EQ_F] = {"==", "eq.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_EQ_V] = {"==", "eq.v", false, + [OP_EQ_V] = {"==", "eq.v", ev_vector, ev_vector, ev_integer, PROG_ID_VERSION, }, - [OP_EQ_Q] = {"==", "eq.q", false, + [OP_EQ_Q] = {"==", "eq.q", ev_quat, ev_quat, ev_integer, PROG_VERSION, }, - [OP_EQ_S] = {"==", "eq.s", false, + [OP_EQ_S] = {"==", "eq.s", ev_string, ev_string, ev_integer, PROG_ID_VERSION, }, - [OP_EQ_E] = {"==", "eq.e", false, + [OP_EQ_E] = {"==", "eq.e", ev_entity, ev_entity, ev_integer, PROG_ID_VERSION, }, - [OP_EQ_FN] = {"==", "eq.fn", false, + [OP_EQ_FN] = {"==", "eq.fn", ev_func, ev_func, ev_integer, PROG_ID_VERSION, }, - [OP_NE_D] = {"!=", "ne.d", false, + [OP_NE_D] = {"!=", "ne.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_NE_F] = {"!=", "ne.f", false, + [OP_NE_F] = {"!=", "ne.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_NE_V] = {"!=", "ne.v", false, + [OP_NE_V] = {"!=", "ne.v", ev_vector, ev_vector, ev_integer, PROG_ID_VERSION, }, - [OP_NE_Q] = {"!=", "ne.q", false, + [OP_NE_Q] = {"!=", "ne.q", ev_quat, ev_quat, ev_integer, PROG_VERSION, }, - [OP_NE_S] = {"!=", "ne.s", false, + [OP_NE_S] = {"!=", "ne.s", ev_string, ev_string, ev_integer, PROG_ID_VERSION, }, - [OP_NE_E] = {"!=", "ne.e", false, + [OP_NE_E] = {"!=", "ne.e", ev_entity, ev_entity, ev_integer, PROG_ID_VERSION, }, - [OP_NE_FN] = {"!=", "ne.fn", false, + [OP_NE_FN] = {"!=", "ne.fn", ev_func, ev_func, ev_integer, PROG_ID_VERSION, }, - [OP_LE_D] = {"<=", "le.d", false, + [OP_LE_D] = {"<=", "le.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_LE_F] = {"<=", "le.f", false, + [OP_LE_F] = {"<=", "le.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_GE_D] = {">=", "ge.d", false, + [OP_GE_D] = {">=", "ge.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_GE_F] = {">=", "ge.f", false, + [OP_GE_F] = {">=", "ge.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_LE_S] = {"<=", "le.s", false, + [OP_LE_S] = {"<=", "le.s", ev_string, ev_string, ev_integer, PROG_VERSION, }, - [OP_GE_S] = {">=", "ge.s", false, + [OP_GE_S] = {">=", "ge.s", ev_string, ev_string, ev_integer, PROG_VERSION, }, - [OP_LT_D] = {"<", "lt.d", false, + [OP_LT_D] = {"<", "lt.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_LT_F] = {"<", "lt.f", false, + [OP_LT_F] = {"<", "lt.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_GT_D] = {">", "gt.d", false, + [OP_GT_D] = {">", "gt.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_GT_F] = {">", "gt.f", false, + [OP_GT_F] = {">", "gt.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_LT_S] = {"<", "lt.s", false, + [OP_LT_S] = {"<", "lt.s", ev_string, ev_string, ev_integer, PROG_VERSION, }, - [OP_GT_S] = {">", "gt.s", false, + [OP_GT_S] = {">", "gt.s", ev_string, ev_string, ev_integer, PROG_VERSION, }, - [OP_LOAD_F] = {".", "load.f", false, + [OP_LOAD_F] = {".", "load.f", ev_entity, ev_field, ev_float, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible? }, - [OP_LOAD_D] = {".", "load.d", false, + [OP_LOAD_D] = {".", "load.d", ev_entity, ev_field, ev_double, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_V] = {".", "load.v", false, + [OP_LOAD_V] = {".", "load.v", ev_entity, ev_field, ev_vector, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_Q] = {".", "load.q", false, + [OP_LOAD_Q] = {".", "load.q", ev_entity, ev_field, ev_quat, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_S] = {".", "load.s", false, + [OP_LOAD_S] = {".", "load.s", ev_entity, ev_field, ev_string, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_ENT] = {".", "load.ent", false, + [OP_LOAD_ENT] = {".", "load.ent", ev_entity, ev_field, ev_entity, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_FLD] = {".", "load.fld", false, + [OP_LOAD_FLD] = {".", "load.fld", ev_entity, ev_field, ev_field, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_FN] = {".", "load.fn", false, + [OP_LOAD_FN] = {".", "load.fn", ev_entity, ev_field, ev_func, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_I] = {".", "load.i", false, + [OP_LOAD_I] = {".", "load.i", ev_entity, ev_field, ev_integer, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_P] = {".", "load.p", false, + [OP_LOAD_P] = {".", "load.p", ev_entity, ev_field, ev_pointer, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOADB_D] = {".", "loadb.d", false, + [OP_LOADB_D] = {".", "loadb.d", ev_pointer, ev_integer, ev_double, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_F] = {".", "loadb.f", false, + [OP_LOADB_F] = {".", "loadb.f", ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_V] = {".", "loadb.v", false, + [OP_LOADB_V] = {".", "loadb.v", ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_Q] = {".", "loadb.q", false, + [OP_LOADB_Q] = {".", "loadb.q", ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_S] = {".", "loadb.s", false, + [OP_LOADB_S] = {".", "loadb.s", ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_ENT] = {".", "loadb.ent", false, + [OP_LOADB_ENT] = {".", "loadb.ent", ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_FLD] = {".", "loadb.fld", false, + [OP_LOADB_FLD] = {".", "loadb.fld", ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_FN] = {".", "loadb.fn", false, + [OP_LOADB_FN] = {".", "loadb.fn", ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_I] = {".", "loadb.i", false, + [OP_LOADB_I] = {".", "loadb.i", ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_P] = {".", "loadb.p", false, + [OP_LOADB_P] = {".", "loadb.p", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADBI_D] = {".", "loadbi.d", false, + [OP_LOADBI_D] = {".", "loadbi.d", ev_pointer, ev_short, ev_double, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_F] = {".", "loadbi.f", false, + [OP_LOADBI_F] = {".", "loadbi.f", ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_V] = {".", "loadbi.v", false, + [OP_LOADBI_V] = {".", "loadbi.v", ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_Q] = {".", "loadbi.q", false, + [OP_LOADBI_Q] = {".", "loadbi.q", ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_S] = {".", "loadbi.s", false, + [OP_LOADBI_S] = {".", "loadbi.s", ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_ENT] = {".", "loadbi.ent", false, + [OP_LOADBI_ENT] = {".", "loadbi.ent", ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_FLD] = {".", "loadbi.fld", false, + [OP_LOADBI_FLD] = {".", "loadbi.fld", ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_FN] = {".", "loadbi.fn", false, + [OP_LOADBI_FN] = {".", "loadbi.fn", ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_I] = {".", "loadbi.i", false, + [OP_LOADBI_I] = {".", "loadbi.i", ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_P] = {".", "loadbi.p", false, + [OP_LOADBI_P] = {".", "loadbi.p", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_ADDRESS] = {"&", "address", false, + [OP_ADDRESS] = {"&", "address", ev_entity, ev_field, ev_pointer, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_ADDRESS_VOID] = {"&", "address", false, + [OP_ADDRESS_VOID] = {"&", "address", ev_void, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_D] = {"&", "address.d", false, + [OP_ADDRESS_D] = {"&", "address.d", ev_double, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_F] = {"&", "address.f", false, + [OP_ADDRESS_F] = {"&", "address.f", ev_float, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_V] = {"&", "address.v", false, + [OP_ADDRESS_V] = {"&", "address.v", ev_vector, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_Q] = {"&", "address.q", false, + [OP_ADDRESS_Q] = {"&", "address.q", ev_quat, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_S] = {"&", "address.s", false, + [OP_ADDRESS_S] = {"&", "address.s", ev_string, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_ENT] = {"&", "address.ent", false, + [OP_ADDRESS_ENT] = {"&", "address.ent", ev_entity, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_FLD] = {"&", "address.fld", false, + [OP_ADDRESS_FLD] = {"&", "address.fld", ev_field, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_FN] = {"&", "address.fn", false, + [OP_ADDRESS_FN] = {"&", "address.fn", ev_func, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_I] = {"&", "address.i", false, + [OP_ADDRESS_I] = {"&", "address.i", ev_integer, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_P] = {"&", "address.p", false, + [OP_ADDRESS_P] = {"&", "address.p", ev_pointer, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_LEA] = {"&", "lea", false, + [OP_LEA] = {"&", "lea", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "(%Ga + %Gb), %gc", }, - [OP_LEAI] = {"&", "leai", false, + [OP_LEAI] = {"&", "leai", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "(%Ga + %sb), %gc", }, - [OP_CONV_IF] = {"", "conv.if", false, + [OP_CONV_IF] = {"", "conv.if", ev_integer, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_FI] = {"", "conv.fi", false, + [OP_CONV_FI] = {"", "conv.fi", ev_float, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_ID] = {"", "conv.id", false, + [OP_CONV_ID] = {"", "conv.id", ev_integer, ev_invalid, ev_double, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_DI] = {"", "conv.di", false, + [OP_CONV_DI] = {"", "conv.di", ev_double, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_FD] = {"", "conv.fd", false, + [OP_CONV_FD] = {"", "conv.fd", ev_float, ev_invalid, ev_double, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_DF] = {"", "conv.df", false, + [OP_CONV_DF] = {"", "conv.df", ev_double, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - [OP_STORE_D] = {"=", "store.d", true, + [OP_STORE_D] = {"=", "store.d", ev_double, ev_double, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - [OP_STORE_F] = {"=", "store.f", true, + [OP_STORE_F] = {"=", "store.f", ev_float, ev_float, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_V] = {"=", "store.v", true, + [OP_STORE_V] = {"=", "store.v", ev_vector, ev_vector, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_Q] = {"=", "store.q", true, + [OP_STORE_Q] = {"=", "store.q", ev_quat, ev_quat, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - [OP_STORE_S] = {"=", "store.s", true, + [OP_STORE_S] = {"=", "store.s", ev_string, ev_string, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_ENT] = {"=", "store.ent", true, + [OP_STORE_ENT] = {"=", "store.ent", ev_entity, ev_entity, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_FLD] = {"=", "store.fld", true, + [OP_STORE_FLD] = {"=", "store.fld", ev_field, ev_field, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_FN] = {"=", "store.fn", true, + [OP_STORE_FN] = {"=", "store.fn", ev_func, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_I] = {"=", "store.i", true, + [OP_STORE_I] = {"=", "store.i", ev_integer, ev_integer, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - [OP_STORE_P] = {"=", "store.p", true, + [OP_STORE_P] = {"=", "store.p", ev_pointer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - [OP_STOREP_D] = {".=", "storep.d", true, + [OP_STOREP_D] = {".=", "storep.d", ev_double, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_F] = {".=", "storep.f", true, + [OP_STOREP_F] = {".=", "storep.f", ev_float, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_V] = {".=", "storep.v", true, + [OP_STOREP_V] = {".=", "storep.v", ev_vector, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_Q] = {".=", "storep.q", true, + [OP_STOREP_Q] = {".=", "storep.q", ev_quat, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_S] = {".=", "storep.s", true, + [OP_STOREP_S] = {".=", "storep.s", ev_string, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_ENT] = {".=", "storep.ent", true, + [OP_STOREP_ENT] = {".=", "storep.ent", ev_entity, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_FLD] = {".=", "storep.fld", true, + [OP_STOREP_FLD] = {".=", "storep.fld", ev_field, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_FN] = {".=", "storep.fn", true, + [OP_STOREP_FN] = {".=", "storep.fn", ev_func, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_I] = {".=", "storep.i", true, + [OP_STOREP_I] = {".=", "storep.i", ev_integer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_P] = {".=", "storep.p", true, + [OP_STOREP_P] = {".=", "storep.p", ev_pointer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - [OP_STOREB_D] = {".=", "storeb.d", true, + [OP_STOREB_D] = {".=", "storeb.d", ev_double, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_F] = {".=", "storeb.f", true, + [OP_STOREB_F] = {".=", "storeb.f", ev_float, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_V] = {".=", "storeb.v", true, + [OP_STOREB_V] = {".=", "storeb.v", ev_vector, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_Q] = {".=", "storeb.q", true, + [OP_STOREB_Q] = {".=", "storeb.q", ev_quat, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_S] = {".=", "storeb.s", true, + [OP_STOREB_S] = {".=", "storeb.s", ev_string, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_ENT] = {".=", "storeb.ent", true, + [OP_STOREB_ENT] = {".=", "storeb.ent", ev_entity, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_FLD] = {".=", "storeb.fld", true, + [OP_STOREB_FLD] = {".=", "storeb.fld", ev_field, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_FN] = {".=", "storeb.fn", true, + [OP_STOREB_FN] = {".=", "storeb.fn", ev_func, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_I] = {".=", "storeb.i", true, + [OP_STOREB_I] = {".=", "storeb.i", ev_integer, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_P] = {".=", "storeb.p", true, + [OP_STOREB_P] = {".=", "storeb.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREBI_D] = {".=", "storebi.d", true, + [OP_STOREBI_D] = {".=", "storebi.d", ev_double, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_F] = {".=", "storebi.f", true, + [OP_STOREBI_F] = {".=", "storebi.f", ev_float, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_V] = {".=", "storebi.v", true, + [OP_STOREBI_V] = {".=", "storebi.v", ev_vector, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_Q] = {".=", "storebi.q", true, + [OP_STOREBI_Q] = {".=", "storebi.q", ev_quat, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_S] = {".=", "storebi.s", true, + [OP_STOREBI_S] = {".=", "storebi.s", ev_string, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_ENT] = {".=", "storebi.ent", true, + [OP_STOREBI_ENT] = {".=", "storebi.ent", ev_entity, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_FLD] = {".=", "storebi.fld", true, + [OP_STOREBI_FLD] = {".=", "storebi.fld", ev_field, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_FN] = {".=", "storebi.fn", true, + [OP_STOREBI_FN] = {".=", "storebi.fn", ev_func, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_I] = {".=", "storebi.i", true, + [OP_STOREBI_I] = {".=", "storebi.i", ev_integer, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_P] = {".=", "storebi.p", true, + [OP_STOREBI_P] = {".=", "storebi.p", ev_pointer, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_RETURN] = {"", "return", false, + [OP_RETURN] = {"", "return", ev_void, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Ra", }, - [OP_RETURN_V] = {"", "return", false, + [OP_RETURN_V] = {"", "return", ev_invalid, ev_invalid, ev_invalid, PROG_VERSION, "", }, - [OP_NOT_D] = {"!", "not.d", false, + [OP_NOT_D] = {"!", "not.d", ev_double, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_NOT_F] = {"!", "not.f", false, + [OP_NOT_F] = {"!", "not.f", ev_float, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_V] = {"!", "not.v", false, + [OP_NOT_V] = {"!", "not.v", ev_vector, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_Q] = {"!", "not.q", false, + [OP_NOT_Q] = {"!", "not.q", ev_quat, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_NOT_S] = {"!", "not.s", false, + [OP_NOT_S] = {"!", "not.s", ev_string, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_ENT] = {"!", "not.ent", false, + [OP_NOT_ENT] = {"!", "not.ent", ev_entity, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_FN] = {"!", "not.fn", false, + [OP_NOT_FN] = {"!", "not.fn", ev_func, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_P] = {"!", "not.p", false, + [OP_NOT_P] = {"!", "not.p", ev_pointer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_IF] = {"", "if", false, + [OP_IF] = {"", "if", ev_integer, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFNOT] = {"", "ifnot", false, + [OP_IFNOT] = {"", "ifnot", ev_integer, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFBE] = {"", "ifbe", true, + [OP_IFBE] = {"", "ifbe", ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFB] = {"", "ifb", true, + [OP_IFB] = {"", "ifb", ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFAE] = {"", "ifae", true, + [OP_IFAE] = {"", "ifae", ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFA] = {"", "ifa", true, + [OP_IFA] = {"", "ifa", ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, // calls returns REG_RETURN - [OP_CALL0] = {"", "call0", false, + [OP_CALL0] = {"", "call0", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa ()", }, - [OP_CALL1] = {"", "call1", false, + [OP_CALL1] = {"", "call1", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x)", }, - [OP_CALL2] = {"", "call2", false, + [OP_CALL2] = {"", "call2", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x)", }, - [OP_CALL3] = {"", "call3", false, + [OP_CALL3] = {"", "call3", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x)", }, - [OP_CALL4] = {"", "call4", false, + [OP_CALL4] = {"", "call4", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x)", }, - [OP_CALL5] = {"", "call5", false, + [OP_CALL5] = {"", "call5", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x)", }, - [OP_CALL6] = {"", "call6", false, + [OP_CALL6] = {"", "call6", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x)", }, - [OP_CALL7] = {"", "call7", false, + [OP_CALL7] = {"", "call7", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - [OP_CALL8] = {"", "call8", false, + [OP_CALL8] = {"", "call8", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - [OP_RCALL0] = {"", 0, false, + [OP_RCALL0] = {"", 0, ev_invalid, ev_invalid, ev_invalid, ~0, // not a valid instruction 0, }, - [OP_RCALL1] = {"", "rcall1", false, + [OP_RCALL1] = {"", "rcall1", ev_func, ev_void, ev_invalid, PROG_VERSION, "%Fa (%P0b)", }, - [OP_RCALL2] = {"", "rcall2", false, + [OP_RCALL2] = {"", "rcall2", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c)", }, - [OP_RCALL3] = {"", "rcall3", false, + [OP_RCALL3] = {"", "rcall3", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x)", }, - [OP_RCALL4] = {"", "rcall4", false, + [OP_RCALL4] = {"", "rcall4", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x)", }, - [OP_RCALL5] = {"", "rcall5", false, + [OP_RCALL5] = {"", "rcall5", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", }, - [OP_RCALL6] = {"", "rcall6", false, + [OP_RCALL6] = {"", "rcall6", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", }, - [OP_RCALL7] = {"", "rcall7", false, + [OP_RCALL7] = {"", "rcall7", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - [OP_RCALL8] = {"", "rcall8", false, + [OP_RCALL8] = {"", "rcall8", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - [OP_STATE] = {"", "state", false, + [OP_STATE] = {"", "state", ev_float, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %Gb", }, - [OP_STATE_F] = {"", "state.f", false, + [OP_STATE_F] = {"", "state.f", ev_float, ev_func, ev_float, PROG_VERSION, "%Ga, %Gb, %Gc", }, - [OP_GOTO] = {"", "goto", false, + [OP_GOTO] = {"", "goto", ev_short, ev_invalid, ev_invalid, PROG_ID_VERSION, "branch %sa (%Oa)", }, - [OP_JUMP] = {"", "jump", false, + [OP_JUMP] = {"", "jump", ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_JUMPB] = {"", "jumpb", false, + [OP_JUMPB] = {"", "jumpb", ev_void, ev_integer, ev_invalid, PROG_VERSION, "%Ga[%Gb]", }, - [OP_AND] = {"&&", "and.f", false, + [OP_AND] = {"&&", "and.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_OR] = {"||", "or.f", false, + [OP_OR] = {"||", "or.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_SHL_F] = {"<<", "shl.f", false, + [OP_SHL_F] = {"<<", "shl.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_SHR_F] = {">>", "shr.f", false, + [OP_SHR_F] = {">>", "shr.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_SHL_I] = {"<<", "shl.i", false, + [OP_SHL_I] = {"<<", "shl.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_SHR_I] = {">>", "shr.i", false, + [OP_SHR_I] = {">>", "shr.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_SHR_U] = {">>", "shr.u", false, + [OP_SHR_U] = {">>", "shr.u", ev_uinteger, ev_integer, ev_uinteger, PROG_VERSION, }, - [OP_BITAND] = {"&", "bitand", false, + [OP_BITAND] = {"&", "bitand", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_BITOR] = {"|", "bitor", false, + [OP_BITOR] = {"|", "bitor", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_ADD_I] = {"+", "add.i", false, + [OP_ADD_I] = {"+", "add.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_SUB_I] = {"-", "sub.i", false, + [OP_SUB_I] = {"-", "sub.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_MUL_I] = {"*", "mul.i", false, + [OP_MUL_I] = {"*", "mul.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_DIV_I] = {"/", "div.i", false, + [OP_DIV_I] = {"/", "div.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_REM_I] = {"%", "rem.i", false, + [OP_REM_I] = {"%", "rem.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_MOD_I] = {"%%", "mod.i", false, + [OP_MOD_I] = {"%%", "mod.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_BITAND_I] = {"&", "bitand.i", false, + [OP_BITAND_I] = {"&", "bitand.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_BITOR_I] = {"|", "bitor.i", false, + [OP_BITOR_I] = {"|", "bitor.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_REM_F] = {"%", "rem.f", false, + [OP_REM_F] = {"%", "rem.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_MOD_F] = {"%%", "mod.f", false, + [OP_MOD_F] = {"%%", "mod.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_GE_I] = {">=", "ge.i", false, + [OP_GE_I] = {">=", "ge.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_LE_I] = {"<=", "le.i", false, + [OP_LE_I] = {"<=", "le.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_GT_I] = {">", "gt.i", false, + [OP_GT_I] = {">", "gt.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_LT_I] = {"<", "lt.i", false, + [OP_LT_I] = {"<", "lt.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_AND_I] = {"&&", "and.i", false, + [OP_AND_I] = {"&&", "and.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_OR_I] = {"||", "or.i", false, + [OP_OR_I] = {"||", "or.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_NOT_I] = {"!", "not.i", false, + [OP_NOT_I] = {"!", "not.i", ev_integer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_EQ_I] = {"==", "eq.i", false, + [OP_EQ_I] = {"==", "eq.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_NE_I] = {"!=", "ne.i", false, + [OP_NE_I] = {"!=", "ne.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_GE_U] = {">=", "ge.u", false, + [OP_GE_U] = {">=", "ge.u", ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - [OP_LE_U] = {"<=", "le.u", false, + [OP_LE_U] = {"<=", "le.u", ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - [OP_GT_U] = {">", "gt.u", false, + [OP_GT_U] = {">", "gt.u", ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - [OP_LT_U] = {"<", "lt.u", false, + [OP_LT_U] = {"<", "lt.u", ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - [OP_BITXOR_F] = {"^", "bitxor.f", false, + [OP_BITXOR_F] = {"^", "bitxor.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_BITNOT_F] = {"~", "bitnot.f", false, + [OP_BITNOT_F] = {"~", "bitnot.f", ev_float, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - [OP_BITXOR_I] = {"^", "bitxor.i", false, + [OP_BITXOR_I] = {"^", "bitxor.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_BITNOT_I] = {"~", "bitnot.i", false, + [OP_BITNOT_I] = {"~", "bitnot.i", ev_integer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_GE_P] = {">=", "ge.p", false, + [OP_GE_P] = {">=", "ge.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_LE_P] = {"<=", "le.p", false, + [OP_LE_P] = {"<=", "le.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_GT_P] = {">", "gt.p", false, + [OP_GT_P] = {">", "gt.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_LT_P] = {"<", "lt.p", false, + [OP_LT_P] = {"<", "lt.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_EQ_P] = {"==", "eq.p", false, + [OP_EQ_P] = {"==", "eq.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_NE_P] = {"!=", "ne.p", false, + [OP_NE_P] = {"!=", "ne.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_MOVEI] = {"", "movei", true, + [OP_MOVEI] = {"", "movei", ev_void, ev_short, ev_void, PROG_VERSION, "%Ga, %sb, %gc", }, - [OP_MOVEP] = {"", "movep", true, + [OP_MOVEP] = {"", "movep", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "%Ga, %Gb, %Gc", }, - [OP_MOVEPI] = {"", "movepi", true, + [OP_MOVEPI] = {"", "movepi", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "%Ga, %sb, %Gc", }, - [OP_MEMSETI] = {"", "memseti", true, + [OP_MEMSETI] = {"", "memseti", ev_integer, ev_short, ev_void, PROG_VERSION, "%Ga, %sb, %gc", }, - [OP_MEMSETP] = {"", "memsetp", true, + [OP_MEMSETP] = {"", "memsetp", ev_integer, ev_integer, ev_pointer, PROG_VERSION, "%Ga, %Gb, %Gc", }, - [OP_MEMSETPI] = {"", "memsetpi", true, + [OP_MEMSETPI] = {"", "memsetpi", ev_integer, ev_short, ev_pointer, PROG_VERSION, "%Ga, %sb, %Gc", }, - [OP_PUSH_S] = {"", "push.s", false, + [OP_PUSH_S] = {"", "push.s", ev_string, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_F] = {"", "push.f", false, + [OP_PUSH_F] = {"", "push.f", ev_float, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_V] = {"", "push.v", false, + [OP_PUSH_V] = {"", "push.v", ev_vector, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_ENT] = {"", "push.ent", false, + [OP_PUSH_ENT] = {"", "push.ent", ev_entity, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_FLD] = {"", "push.fld", false, + [OP_PUSH_FLD] = {"", "push.fld", ev_field, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_FN] = {"", "push.fn", false, + [OP_PUSH_FN] = {"", "push.fn", ev_func, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_P] = {"", "push.p", false, + [OP_PUSH_P] = {"", "push.p", ev_pointer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_Q] = {"", "push.q", false, + [OP_PUSH_Q] = {"", "push.q", ev_quat, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_I] = {"", "push.i", false, + [OP_PUSH_I] = {"", "push.i", ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_D] = {"", "push.d", false, + [OP_PUSH_D] = {"", "push.d", ev_double, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSHB_S] = {"", "pushb.s", false, + [OP_PUSHB_S] = {"", "pushb.s", ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_F] = {"", "pushb.f", false, + [OP_PUSHB_F] = {"", "pushb.f", ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_V] = {"", "pushb.v", false, + [OP_PUSHB_V] = {"", "pushb.v", ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_ENT] = {"", "pushb.ent", false, + [OP_PUSHB_ENT] = {"", "pushb.ent", ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_FLD] = {"", "pushb.fld", false, + [OP_PUSHB_FLD] = {"", "pushb.fld", ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_FN] = {"", "pushb.fn", false, + [OP_PUSHB_FN] = {"", "pushb.fn", ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_P] = {"", "pushb.p", false, + [OP_PUSHB_P] = {"", "pushb.p", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_Q] = {"", "pushb.q", false, + [OP_PUSHB_Q] = {"", "pushb.q", ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_I] = {"", "pushb.i", false, + [OP_PUSHB_I] = {"", "pushb.i", ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_D] = {"", "pushb.d", false, + [OP_PUSHB_D] = {"", "pushb.d", ev_pointer, ev_integer, ev_double, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHBI_S] = {"", "pushbi.s", false, + [OP_PUSHBI_S] = {"", "pushbi.s", ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_F] = {"", "pushbi.f", false, + [OP_PUSHBI_F] = {"", "pushbi.f", ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_V] = {"", "pushbi.v", false, + [OP_PUSHBI_V] = {"", "pushbi.v", ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_ENT] = {"", "pushbi.ent", false, + [OP_PUSHBI_ENT] = {"", "pushbi.ent", ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_FLD] = {"", "pushbi.fld", false, + [OP_PUSHBI_FLD] = {"", "pushbi.fld", ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_FN] = {"", "pushbi.fn", false, + [OP_PUSHBI_FN] = {"", "pushbi.fn", ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_P] = {"", "pushbi.p", false, + [OP_PUSHBI_P] = {"", "pushbi.p", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_Q] = {"", "pushbi.q", false, + [OP_PUSHBI_Q] = {"", "pushbi.q", ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_I] = {"", "pushbi.i", false, + [OP_PUSHBI_I] = {"", "pushbi.i", ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_D] = {"", "pushbi.d", false, + [OP_PUSHBI_D] = {"", "pushbi.d", ev_pointer, ev_short, ev_double, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POP_S] = {"", "pop.s", false, + [OP_POP_S] = {"", "pop.s", ev_string, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_F] = {"", "pop.f", false, + [OP_POP_F] = {"", "pop.f", ev_float, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_V] = {"", "pop.v", false, + [OP_POP_V] = {"", "pop.v", ev_vector, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_ENT] = {"", "pop.ent", false, + [OP_POP_ENT] = {"", "pop.ent", ev_entity, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_FLD] = {"", "pop.fld", false, + [OP_POP_FLD] = {"", "pop.fld", ev_field, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_FN] = {"", "pop.fn", false, + [OP_POP_FN] = {"", "pop.fn", ev_func, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_P] = {"", "pop.p", false, + [OP_POP_P] = {"", "pop.p", ev_pointer, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_Q] = {"", "pop.q", false, + [OP_POP_Q] = {"", "pop.q", ev_quat, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_I] = {"", "pop.i", false, + [OP_POP_I] = {"", "pop.i", ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_D] = {"", "pop.d", false, + [OP_POP_D] = {"", "pop.d", ev_double, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POPB_S] = {"", "popb.s", false, + [OP_POPB_S] = {"", "popb.s", ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_F] = {"", "popb.f", false, + [OP_POPB_F] = {"", "popb.f", ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_V] = {"", "popb.v", false, + [OP_POPB_V] = {"", "popb.v", ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_ENT] = {"", "popb.ent", false, + [OP_POPB_ENT] = {"", "popb.ent", ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_FLD] = {"", "popb.fld", false, + [OP_POPB_FLD] = {"", "popb.fld", ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_FN] = {"", "popb.fn", false, + [OP_POPB_FN] = {"", "popb.fn", ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_P] = {"", "popb.p", false, + [OP_POPB_P] = {"", "popb.p", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_Q] = {"", "popb.q", false, + [OP_POPB_Q] = {"", "popb.q", ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_I] = {"", "popb.i", false, + [OP_POPB_I] = {"", "popb.i", ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_D] = {"", "popb.d", false, + [OP_POPB_D] = {"", "popb.d", ev_pointer, ev_integer, ev_double, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPBI_S] = {"", "popbi.s", false, + [OP_POPBI_S] = {"", "popbi.s", ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_F] = {"", "popbi.f", false, + [OP_POPBI_F] = {"", "popbi.f", ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_V] = {"", "popbi.v", false, + [OP_POPBI_V] = {"", "popbi.v", ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_ENT] = {"", "popbi.ent", false, + [OP_POPBI_ENT] = {"", "popbi.ent", ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_FLD] = {"", "popbi.fld", false, + [OP_POPBI_FLD] = {"", "popbi.fld", ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_FN] = {"", "popbi.fn", false, + [OP_POPBI_FN] = {"", "popbi.fn", ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_P] = {"", "popbi.p", false, + [OP_POPBI_P] = {"", "popbi.p", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_Q] = {"", "popbi.q", false, + [OP_POPBI_Q] = {"", "popbi.q", ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_I] = {"", "popbi.i", false, + [OP_POPBI_I] = {"", "popbi.i", ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_D] = {"", "popbi.d", false, + [OP_POPBI_D] = {"", "popbi.d", ev_pointer, ev_short, ev_double, PROG_VERSION, "*(%Ga + %sb)", From 7b0eceda326f40fae2ee6813e7d395875f47f260 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 20:16:45 +0900 Subject: [PATCH 2086/3664] [gamecode] Split out the old quake c execution loop There is no reasonable way (due to hardware-enforced alignment issues) to simply convert old bytecode to new (probably best done with an off-line tool, preferably just recompiling when I get qfcc up to the job), so both loops will need to be present. This just moves the original loop into its own function in order to make it easy to bring in the new (and iron out integration issues). --- libs/gamecode/pr_exec.c | 50 ++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index af7517a92..b9367b74c 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -436,15 +436,10 @@ pr_memset (pr_type_t *dst, int val, int count) } } -/* - PR_ExecuteProgram - - The interpretation main loop -*/ -VISIBLE void -PR_ExecuteProgram (progs_t *pr, func_t fnum) +static void +pr_exec_quakec (progs_t *pr, int exitdepth) { - int exitdepth, profile, startprofile; + int profile, startprofile; int fldofs; pr_uint_t pointer; dstatement_t *st; @@ -452,26 +447,13 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) pr_type_t old_val = {0}; // make a stack frame - exitdepth = pr->pr_depth; startprofile = profile = 0; - Sys_PushSignalHook (signal_hook, pr); - Sys_PushErrorHandler (error_handler, pr); - - if (pr->debug_handler) { - pr->debug_handler (prd_subenter, &fnum, pr->debug_data); - } - - if (!PR_CallFunction (pr, fnum)) { - // called a builtin instead of progs code - goto exit_program; - } st = pr->pr_statements + pr->pr_xstatement; if (pr->watch) { old_val = *pr->watch; } - while (1) { pr_type_t *op_a, *op_b, *op_c; @@ -1737,6 +1719,32 @@ op_call: old_val.integer_var = pr->watch->integer_var; } } +exit_program: +} + +/* + PR_ExecuteProgram + + The interpretation main loop +*/ +VISIBLE void +PR_ExecuteProgram (progs_t *pr, func_t fnum) +{ + Sys_PushSignalHook (signal_hook, pr); + Sys_PushErrorHandler (error_handler, pr); + + if (pr->debug_handler) { + pr->debug_handler (prd_subenter, &fnum, pr->debug_data); + } + + int exitdepth = pr->pr_depth; + if (!PR_CallFunction (pr, fnum)) { + // called a builtin instead of progs code + goto exit_program; + } + if (1) { + pr_exec_quakec (pr, exitdepth); + } exit_program: if (pr->debug_handler) { pr->debug_handler (prd_subexit, 0, pr->debug_data); From bc0a09f452019e3f3f4a86941ea93c67a1e265e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 20:46:32 +0900 Subject: [PATCH 2087/3664] [gamecode] Switch to using type parameter op macros I wish I'd done it this way years ago (but maybe gcc 2.95 couldn't hack the casts, I do know there were aliasing problems in the past). Anyway, this makes operand access much more consistent for variable sized operands (eg float vs double vs vec4), and is a big part of the new instruction set implementation. --- include/QF/progs.h | 4 +- libs/gamecode/pr_debug.c | 2 +- libs/gamecode/pr_edict.c | 4 +- libs/gamecode/pr_exec.c | 531 +++++++++++++++++++-------------------- 4 files changed, 266 insertions(+), 275 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 3f6ad6ae3..8d32e2074 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -289,7 +289,7 @@ void ED_Free (progs_t *pr, edict_t *ed); edict_t *ED_EdictNum(progs_t *pr, pr_int_t n) __attribute__((pure)); pr_int_t ED_NumForEdict(progs_t *pr, edict_t *e) __attribute__((pure)); void ED_Count (progs_t *pr); -qboolean PR_EdictValid (progs_t *pr, pr_int_t e) __attribute__((pure)); +qboolean PR_EdictValid (progs_t *pr, pr_uint_t e) __attribute__((pure)); // pr_debug.c void ED_Print (progs_t *pr, edict_t *ed, const char *fieldname); @@ -1900,7 +1900,7 @@ struct progs_s { void (*free_edict) (progs_t *pr, edict_t *ent); pr_type_t *pr_edict_area; int pr_edict_size; ///< # of pr_type_t slots - int pr_edict_area_size; ///< for bounds checking, starts at 0 + pr_uint_t pr_edict_area_size; ///< for bounds checking, starts at 0 func_t edict_parse; ///@} diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 55cca36d0..a720a863d 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1536,7 +1536,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) const char *str; char mode = fmt[1], opchar = fmt[2]; unsigned parm_ind = 0; - pr_int_t opval; + pr_uint_t opval; qfot_type_t *optype = &res->void_type; func_t func; diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 60233a0ce..f16c2bd41 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -241,12 +241,12 @@ ED_NumForEdict (progs_t *pr, edict_t *e) } qboolean -PR_EdictValid (progs_t *pr, pr_int_t e) +PR_EdictValid (progs_t *pr, pr_uint_t e) { if (!pr->num_edicts) { return false; } - if (e < 0 || e >= pr->pr_edict_area_size) + if (e >= pr->pr_edict_area_size) return false; if (e % pr->pr_edict_size) return false; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index b9367b74c..fa226a417 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -330,19 +330,15 @@ PR_BoundsCheck (progs_t *pr, int addr, etype_t type) PR_BoundsCheckSize (pr, addr, pr_type_size[type]); } -#define OPA (*op_a) -#define OPB (*op_b) -#define OPC (*op_c) - -#define OPA_double_var (*((double *) (op_a))) -#define OPB_double_var (*((double *) (op_b))) -#define OPC_double_var (*((double *) (op_c))) +#define OPA(type) (*((pr_##type##_t *) (op_a))) +#define OPB(type) (*((pr_##type##_t *) (op_b))) +#define OPC(type) (*((pr_##type##_t *) (op_c))) /* This gets around the problem of needing to test for -0.0 but denormals causing exceptions (or wrong results for what we need) on the alpha. */ -#define FNZ(x) ((x).uinteger_var & ~0x80000000u) +#define FNZ(x) ((x) & ~0x80000000u) static int signal_hook (int sig, void *data) @@ -360,23 +356,23 @@ signal_hook (int sig, void *data) switch (st->op) { case OP_DIV_F: - if ((OPA.integer_var & 0x80000000) - ^ (OPB.integer_var & 0x80000000)) - OPC.integer_var = 0xff7fffff; + if ((OPA(int) & 0x80000000) + ^ (OPB(int) & 0x80000000)) + OPC(int) = 0xff7fffff; else - OPC.integer_var = 0x7f7fffff; + OPC(int) = 0x7f7fffff; return 1; case OP_DIV_I: - if (OPA.integer_var & 0x80000000) - OPC.integer_var = -0x80000000; + if (OPA(int) & 0x80000000) + OPC(int) = -0x80000000; else - OPC.integer_var = 0x7fffffff; + OPC(int) = 0x7fffffff; return 1; case OP_MOD_I: case OP_MOD_F: case OP_REM_I: case OP_REM_F: - OPC.integer_var = 0x00000000; + OPC(int) = 0x00000000; return 1; default: break; @@ -488,214 +484,214 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_opcode_e op = st->op & ~OP_BREAK; switch (op) { case OP_ADD_D: - OPC_double_var = OPA_double_var + OPB_double_var; + OPC(double) = OPA(double) + OPB(double); break; case OP_ADD_F: - OPC.float_var = OPA.float_var + OPB.float_var; + OPC(float) = OPA(float) + OPB(float); break; case OP_ADD_V: - VectorAdd (&OPA.vector_var, &OPB.vector_var, &OPC.vector_var); + VectorAdd (&OPA(float), &OPB(float), &OPC(float)); break; case OP_ADD_Q: - QuatAdd (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); + QuatAdd (&OPA(float), &OPB(float), &OPC(float)); break; case OP_ADD_S: - OPC.string_var = PR_CatStrings (pr, + OPC(string) = PR_CatStrings (pr, PR_GetString (pr, - OPA.string_var), + OPA(string)), PR_GetString (pr, - OPB.string_var)); + OPB(string))); break; case OP_SUB_D: - OPC_double_var = OPA_double_var - OPB_double_var; + OPC(double) = OPA(double) - OPB(double); break; case OP_SUB_F: - OPC.float_var = OPA.float_var - OPB.float_var; + OPC(float) = OPA(float) - OPB(float); break; case OP_SUB_V: - VectorSubtract (&OPA.vector_var, &OPB.vector_var, - &OPC.vector_var); + VectorSubtract (&OPA(float), &OPB(float), + &OPC(float)); break; case OP_SUB_Q: - QuatSubtract (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); + QuatSubtract (&OPA(float), &OPB(float), &OPC(float)); break; case OP_MUL_D: - OPC_double_var = OPA_double_var * OPB_double_var; + OPC(double) = OPA(double) * OPB(double); break; case OP_MUL_F: - OPC.float_var = OPA.float_var * OPB.float_var; + OPC(float) = OPA(float) * OPB(float); break; case OP_MUL_V: - OPC.float_var = DotProduct (&OPA.vector_var, &OPB.vector_var); + OPC(float) = DotProduct (&OPA(float), &OPB(float)); break; case OP_MUL_DV: { // avoid issues with the likes of x = x.x * x; // makes for faster code, too - double scale = OPA_double_var; - VectorScale (&OPB.vector_var, scale, &OPC.vector_var); + double scale = OPA(double); + VectorScale (&OPB(float), scale, &OPC(float)); } break; case OP_MUL_VD: { // avoid issues with the likes of x = x * x.x; // makes for faster code, too - double scale = OPB_double_var; - VectorScale (&OPA.vector_var, scale, &OPC.vector_var); + double scale = OPB(double); + VectorScale (&OPA(float), scale, &OPC(float)); } break; case OP_MUL_FV: { // avoid issues with the likes of x = x.x * x; // makes for faster code, too - float scale = OPA.float_var; - VectorScale (&OPB.vector_var, scale, &OPC.vector_var); + float scale = OPA(float); + VectorScale (&OPB(float), scale, &OPC(float)); } break; case OP_MUL_VF: { // avoid issues with the likes of x = x * x.x; // makes for faster code, too - float scale = OPB.float_var; - VectorScale (&OPA.vector_var, scale, &OPC.vector_var); + float scale = OPB(float); + VectorScale (&OPA(float), scale, &OPC(float)); } break; case OP_MUL_Q: - QuatMult (&OPA.quat_var, &OPB.quat_var, &OPC.quat_var); + QuatMult (&OPA(float), &OPB(float), &OPC(float)); break; case OP_MUL_QV: - QuatMultVec (&OPA.quat_var, &OPB.vector_var, &OPC.vector_var); + QuatMultVec (&OPA(float), &OPB(float), &OPC(float)); break; case OP_MUL_DQ: { // avoid issues with the likes of x = x.s * x; // makes for faster code, too - double scale = OPA_double_var; - QuatScale (&OPB.quat_var, scale, &OPC.quat_var); + double scale = OPA(double); + QuatScale (&OPB(float), scale, &OPC(float)); } break; case OP_MUL_QD: { // avoid issues with the likes of x = x * x.s; // makes for faster code, too - double scale = OPB_double_var; - QuatScale (&OPA.quat_var, scale, &OPC.quat_var); + double scale = OPB(double); + QuatScale (&OPA(float), scale, &OPC(float)); } break; case OP_MUL_FQ: { // avoid issues with the likes of x = x.s * x; // makes for faster code, too - float scale = OPA.float_var; - QuatScale (&OPB.quat_var, scale, &OPC.quat_var); + float scale = OPA(float); + QuatScale (&OPB(float), scale, &OPC(float)); } break; case OP_MUL_QF: { // avoid issues with the likes of x = x * x.s; // makes for faster code, too - float scale = OPB.float_var; - QuatScale (&OPA.quat_var, scale, &OPC.quat_var); + float scale = OPB(float); + QuatScale (&OPA(float), scale, &OPC(float)); } break; case OP_CONJ_Q: - QuatConj (&OPA.quat_var, &OPC.quat_var); + QuatConj (&OPA(float), &OPC(float)); break; case OP_DIV_D: - OPC_double_var = OPA_double_var / OPB_double_var; + OPC(double) = OPA(double) / OPB(double); break; case OP_DIV_F: - OPC.float_var = OPA.float_var / OPB.float_var; + OPC(float) = OPA(float) / OPB(float); break; case OP_BITAND: - OPC.float_var = (int) OPA.float_var & (int) OPB.float_var; + OPC(float) = (int) OPA(float) & (int) OPB(float); break; case OP_BITOR: - OPC.float_var = (int) OPA.float_var | (int) OPB.float_var; + OPC(float) = (int) OPA(float) | (int) OPB(float); break; case OP_BITXOR_F: - OPC.float_var = (int) OPA.float_var ^ (int) OPB.float_var; + OPC(float) = (int) OPA(float) ^ (int) OPB(float); break; case OP_BITNOT_F: - OPC.float_var = ~ (int) OPA.float_var; + OPC(float) = ~ (int) OPA(float); break; case OP_SHL_F: - OPC.float_var = (int) OPA.float_var << (int) OPB.float_var; + OPC(float) = (int) OPA(float) << (int) OPB(float); break; case OP_SHR_F: - OPC.float_var = (int) OPA.float_var >> (int) OPB.float_var; + OPC(float) = (int) OPA(float) >> (int) OPB(float); break; case OP_SHL_I: - OPC.integer_var = OPA.integer_var << OPB.integer_var; + OPC(int) = OPA(int) << OPB(int); break; case OP_SHR_I: - OPC.integer_var = OPA.integer_var >> OPB.integer_var; + OPC(int) = OPA(int) >> OPB(int); break; case OP_SHR_U: - OPC.uinteger_var = OPA.uinteger_var >> OPB.integer_var; + OPC(uint) = OPA(uint) >> OPB(int); break; case OP_GE_F: - OPC.float_var = OPA.float_var >= OPB.float_var; + OPC(float) = OPA(float) >= OPB(float); break; case OP_LE_F: - OPC.float_var = OPA.float_var <= OPB.float_var; + OPC(float) = OPA(float) <= OPB(float); break; case OP_GT_F: - OPC.float_var = OPA.float_var > OPB.float_var; + OPC(float) = OPA(float) > OPB(float); break; case OP_LT_F: - OPC.float_var = OPA.float_var < OPB.float_var; + OPC(float) = OPA(float) < OPB(float); break; case OP_AND: // OPA and OPB have to be float for -0.0 - OPC.integer_var = FNZ (OPA) && FNZ (OPB); + OPC(int) = FNZ (OPA(uint)) && FNZ (OPB(uint)); break; case OP_OR: // OPA and OPB have to be float for -0.0 - OPC.integer_var = FNZ (OPA) || FNZ (OPB); + OPC(int) = FNZ (OPA(uint)) || FNZ (OPB(uint)); break; case OP_NOT_F: - OPC.integer_var = !FNZ (OPA); + OPC(int) = !FNZ (OPA(uint)); break; case OP_NOT_V: - OPC.integer_var = VectorIsZero (&OPA.vector_var); + OPC(int) = VectorIsZero (&OPA(float)); break; case OP_NOT_Q: - OPC.integer_var = QuatIsZero (&OPA.quat_var); + OPC(int) = QuatIsZero (&OPA(float)); break; case OP_NOT_S: - OPC.integer_var = !OPA.string_var || - !*PR_GetString (pr, OPA.string_var); + OPC(int) = !OPA(string) || + !*PR_GetString (pr, OPA(string)); break; case OP_NOT_FN: - OPC.integer_var = !OPA.func_var; + OPC(int) = !OPA(uint); break; case OP_NOT_ENT: - OPC.integer_var = !OPA.entity_var; + OPC(int) = !OPA(uint); break; case OP_EQ_F: - OPC.integer_var = OPA.float_var == OPB.float_var; + OPC(int) = OPA(float) == OPB(float); break; case OP_EQ_V: - OPC.integer_var = VectorCompare (&OPA.vector_var, - &OPB.vector_var); + OPC(int) = VectorCompare (&OPA(float), + &OPB(float)); break; case OP_EQ_Q: - OPC.integer_var = QuatCompare (&OPA.quat_var, &OPB.quat_var); + OPC(int) = QuatCompare (&OPA(float), &OPB(float)); break; case OP_EQ_E: - OPC.integer_var = OPA.integer_var == OPB.integer_var; + OPC(int) = OPA(int) == OPB(int); break; case OP_EQ_FN: - OPC.integer_var = OPA.func_var == OPB.func_var; + OPC(int) = OPA(uint) == OPB(uint); break; case OP_NE_F: - OPC.integer_var = OPA.float_var != OPB.float_var; + OPC(int) = OPA(float) != OPB(float); break; case OP_NE_V: - OPC.integer_var = !VectorCompare (&OPA.vector_var, - &OPB.vector_var); + OPC(int) = !VectorCompare (&OPA(float), + &OPB(float)); break; case OP_NE_Q: - OPC.integer_var = !QuatCompare (&OPA.quat_var, &OPB.quat_var); + OPC(int) = !QuatCompare (&OPA(float), &OPB(float)); break; case OP_LE_S: case OP_GE_S: @@ -704,8 +700,8 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_NE_S: case OP_EQ_S: { - int cmp = strcmp (PR_GetString (pr, OPA.string_var), - PR_GetString (pr, OPB.string_var)); + int cmp = strcmp (PR_GetString (pr, OPA(string)), + PR_GetString (pr, OPB(string))); switch (st->op) { case OP_LE_S: cmp = (cmp <= 0); break; case OP_GE_S: cmp = (cmp >= 0); break; @@ -715,14 +711,14 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_EQ_S: cmp = !cmp; break; default: break; } - OPC.integer_var = cmp; + OPC(int) = cmp; } break; case OP_NE_E: - OPC.integer_var = OPA.integer_var != OPB.integer_var; + OPC(int) = OPA(int) != OPB(int); break; case OP_NE_FN: - OPC.integer_var = OPA.func_var != OPB.func_var; + OPC(int) = OPA(uint) != OPB(uint); break; // ================== @@ -733,16 +729,16 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STORE_FN: // pointers case OP_STORE_I: case OP_STORE_P: - OPB.integer_var = OPA.integer_var; + OPB(int) = OPA(int); break; case OP_STORE_V: - VectorCopy (&OPA.vector_var, &OPB.vector_var); + VectorCopy (&OPA(float), &OPB(float)); break; case OP_STORE_Q: - QuatCopy (&OPA.quat_var, &OPB.quat_var); + QuatCopy (&OPA(float), &OPB(float)); break; case OP_STORE_D: - OPB_double_var = OPA_double_var; + OPB(double) = OPA(double); break; case OP_STOREP_F: @@ -752,52 +748,51 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREP_FN: // pointers case OP_STOREP_I: case OP_STOREP_P: - pointer = OPB.integer_var; + pointer = OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); } ptr = pr->pr_globals + pointer; - ptr->integer_var = OPA.integer_var; + ptr->integer_var = OPA(int); break; case OP_STOREP_V: - pointer = OPB.integer_var; + pointer = OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA.vector_var, &ptr->vector_var); + VectorCopy (&OPA(float), &ptr->vector_var); break; case OP_STOREP_Q: - pointer = OPB.integer_var; + pointer = OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA.quat_var, &ptr->quat_var); + QuatCopy (&OPA(float), &ptr->quat_var); break; case OP_STOREP_D: - pointer = OPB.integer_var; + pointer = OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_double); } ptr = pr->pr_globals + pointer; - *(double *) ptr = OPA_double_var; + *(double *) ptr = OPA(double); break; case OP_ADDRESS: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to address an out " "of bounds edict"); - if (OPA.entity_var == 0 && pr->null_bad) + if (OPA(uint) == 0 && pr->null_bad) PR_RunError (pr, "assignment to world entity"); - if (OPB.uinteger_var >= pr->progs->entityfields) + if (OPB(uint) >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to address an " "invalid field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - OPC.integer_var = &pr->pr_edict_area[fldofs] - pr->pr_globals; + fldofs = OPA(uint) + OPB(int); + OPC(int) = &pr->pr_edict_area[fldofs] - pr->pr_globals; break; case OP_ADDRESS_VOID: case OP_ADDRESS_F: @@ -810,7 +805,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_ADDRESS_I: case OP_ADDRESS_P: case OP_ADDRESS_D: - OPC.integer_var = st->a; + OPC(int) = st->a; break; case OP_LOAD_F: @@ -821,55 +816,51 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOAD_I: case OP_LOAD_P: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB.uinteger_var >= pr->progs->entityfields) + if (OPB(uint) >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - OPC.integer_var = pr->pr_edict_area[fldofs].integer_var; + fldofs = OPA(uint) + OPB(int); + OPC(int) = pr->pr_edict_area[fldofs].integer_var; break; case OP_LOAD_V: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB.uinteger_var + 2 >= pr->progs->entityfields) + if (OPB(uint) + 2 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - memcpy (&OPC, &pr->pr_edict_area[fldofs], 3 * sizeof (OPC)); + fldofs = OPA(uint) + OPB(int); + memcpy (op_c, &pr->pr_edict_area[fldofs], 3 * sizeof (*op_c)); break; case OP_LOAD_Q: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB.uinteger_var + 3 >= pr->progs->entityfields) + if (OPB(uint) + 3 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - memcpy (&OPC, &pr->pr_edict_area[fldofs], 4 * sizeof (OPC)); + fldofs = OPA(uint) + OPB(int); + memcpy (op_c, &pr->pr_edict_area[fldofs], 4 * sizeof (*op_c)); break; case OP_LOAD_D: if (pr_boundscheck->int_val) { - if (OPA.entity_var < 0 - || OPA.entity_var >= pr->pr_edict_area_size) + if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB.uinteger_var + 1 >= pr->progs->entityfields) + if (OPB(uint) + 1 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA.entity_var + OPB.integer_var; - memcpy (&OPC, &pr->pr_edict_area[fldofs], sizeof (double)); + fldofs = OPA(uint) + OPB(int); + memcpy (op_c, &pr->pr_edict_area[fldofs], sizeof (double)); break; case OP_LOADB_F: @@ -879,36 +870,36 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADB_FN: case OP_LOADB_I: case OP_LOADB_P: - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); } ptr = pr->pr_globals + pointer; - OPC.integer_var = ptr->integer_var; + OPC(int) = ptr->integer_var; break; case OP_LOADB_V: - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&ptr->vector_var, &OPC.vector_var); + VectorCopy (&ptr->vector_var, &OPC(float)); break; case OP_LOADB_Q: - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (&ptr->quat_var, &OPC.quat_var); + QuatCopy (&ptr->quat_var, &OPC(float)); break; case OP_LOADB_D: - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_double); } ptr = pr->pr_globals + pointer; - OPC_double_var = *(double *) ptr; + OPC(double) = *(double *) ptr; break; case OP_LOADBI_F: @@ -918,46 +909,46 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADBI_FN: case OP_LOADBI_I: case OP_LOADBI_P: - pointer = OPA.integer_var + (short) st->b; + pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); } ptr = pr->pr_globals + pointer; - OPC.integer_var = ptr->integer_var; + OPC(int) = ptr->integer_var; break; case OP_LOADBI_V: - pointer = OPA.integer_var + (short) st->b; + pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&ptr->vector_var, &OPC.vector_var); + VectorCopy (&ptr->vector_var, &OPC(float)); break; case OP_LOADBI_Q: - pointer = OPA.integer_var + (short) st->b; + pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (&ptr->quat_var, &OPC.quat_var); + QuatCopy (&ptr->quat_var, &OPC(float)); break; case OP_LOADBI_D: - pointer = OPA.integer_var + (short) st->b; + pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - OPC_double_var = *(double *) ptr; + OPC(double) = *(double *) ptr; break; case OP_LEA: - pointer = OPA.integer_var + OPB.integer_var; - OPC.integer_var = pointer; + pointer = OPA(int) + OPB(int); + OPC(int) = pointer; break; case OP_LEAI: - pointer = OPA.integer_var + (short) st->b; - OPC.integer_var = pointer; + pointer = OPA(int) + (short) st->b; + OPC(int) = pointer; break; case OP_STOREB_F: @@ -967,36 +958,36 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREB_FN: case OP_STOREB_I: case OP_STOREB_P: - pointer = OPB.integer_var + OPC.integer_var; + pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); } ptr = pr->pr_globals + pointer; - ptr->integer_var = OPA.integer_var; + ptr->integer_var = OPA(int); break; case OP_STOREB_V: - pointer = OPB.integer_var + OPC.integer_var; + pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA.vector_var, &ptr->vector_var); + VectorCopy (&OPA(float), &ptr->vector_var); break; case OP_STOREB_Q: - pointer = OPB.integer_var + OPC.integer_var; + pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA.quat_var, &ptr->quat_var); + QuatCopy (&OPA(float), &ptr->quat_var); break; case OP_STOREB_D: - pointer = OPB.integer_var + OPC.integer_var; + pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - *(double *) ptr = OPA_double_var; + *(double *) ptr = OPA(double); break; case OP_STOREBI_F: @@ -1006,36 +997,36 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREBI_FN: case OP_STOREBI_I: case OP_STOREBI_P: - pointer = OPB.integer_var + (short) st->c; + pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); } ptr = pr->pr_globals + pointer; - ptr->integer_var = OPA.integer_var; + ptr->integer_var = OPA(int); break; case OP_STOREBI_V: - pointer = OPB.integer_var + (short) st->c; + pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA.vector_var, &ptr->vector_var); + VectorCopy (&OPA(float), &ptr->vector_var); break; case OP_STOREBI_Q: - pointer = OPB.integer_var + (short) st->c; + pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA.quat_var, &ptr->quat_var); + QuatCopy (&OPA(float), &ptr->quat_var); break; case OP_STOREBI_D: - pointer = OPB.integer_var + (short) st->c; + pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); } ptr = pr->pr_globals + pointer; - *(double *) ptr = OPA_double_var; + *(double *) ptr = OPA(double); break; case OP_PUSH_F: @@ -1051,7 +1042,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); } - stk->integer_var = OPA.integer_var; + stk->integer_var = OPA(int); *pr->globals.stack = stack; } break; @@ -1062,7 +1053,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); } - memcpy (stk, &OPA, 3 * sizeof (OPC)); + memcpy (stk, op_a, 3 * sizeof (*op_c)); *pr->globals.stack = stack; } break; @@ -1073,7 +1064,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); } - memcpy (stk, &OPA, 4 * sizeof (OPC)); + memcpy (stk, op_a, 4 * sizeof (*op_c)); *pr->globals.stack = stack; } break; @@ -1089,7 +1080,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1106,7 +1097,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1123,7 +1114,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1147,7 +1138,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(int) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1164,7 +1155,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(int) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1181,7 +1172,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(int) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1207,7 +1198,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); } - OPA.integer_var = stk->integer_var; + OPA(int) = stk->integer_var; *pr->globals.stack = stack + 1; } break; @@ -1218,7 +1209,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); } - memcpy (&OPA, stk, 3 * sizeof (OPC)); + memcpy (op_a, stk, 3 * sizeof (*op_c)); *pr->globals.stack = stack + 3; } break; @@ -1229,7 +1220,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); } - memcpy (&OPA, stk, 4 * sizeof (OPC)); + memcpy (op_a, stk, 4 * sizeof (*op_c)); *pr->globals.stack = stack + 4; } break; @@ -1245,7 +1236,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1262,7 +1253,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1279,7 +1270,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + OPB.integer_var; + pointer = OPA(int) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1303,7 +1294,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(int) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1320,7 +1311,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(int) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1337,7 +1328,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA.integer_var + st->b; + pointer = OPA(int) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1352,37 +1343,37 @@ pr_exec_quakec (progs_t *pr, int exitdepth) // ================== case OP_IFNOT: - if (!OPA.integer_var) { + if (!OPA(int)) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; case OP_IF: - if (OPA.integer_var) { + if (OPA(int)) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; case OP_IFBE: - if (OPA.integer_var <= 0) { + if (OPA(int) <= 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; case OP_IFB: - if (OPA.integer_var < 0) { + if (OPA(int) < 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; case OP_IFAE: - if (OPA.integer_var >= 0) { + if (OPA(int) >= 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; case OP_IFA: - if (OPA.integer_var > 0) { + if (OPA(int) > 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } @@ -1393,14 +1384,14 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_JUMP: if (pr_boundscheck->int_val - && (OPA.uinteger_var >= pr->progs->numstatements)) { + && (OPA(uint) >= pr->progs->numstatements)) { PR_RunError (pr, "Invalid jump destination"); } - pr->pr_xstatement = OPA.uinteger_var - 1; // offset the st++ + pr->pr_xstatement = OPA(uint) - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; break; case OP_JUMPB: - pointer = st->a + OPB.integer_var; + pointer = st->a + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); } @@ -1421,12 +1412,12 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_RCALL6: case OP_RCALL7: case OP_RCALL8: - pr->pr_params[1] = &OPC; + pr->pr_params[1] = op_c; goto op_rcall; case OP_RCALL1: pr->pr_params[1] = pr->pr_real_params[1]; op_rcall: - pr->pr_params[0] = &OPB; + pr->pr_params[0] = op_b; pr->pr_argc = st->op - OP_RCALL1 + 1; goto op_call; case OP_CALL0: @@ -1443,17 +1434,17 @@ op_rcall: op_call: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; - PR_CallFunction (pr, OPA.func_var); + PR_CallFunction (pr, OPA(uint)); st = pr->pr_statements + pr->pr_xstatement; break; case OP_DONE: case OP_RETURN: if (!st->a) memset (&R_INT (pr), 0, - pr->pr_param_size * sizeof (OPA)); - else if (&R_INT (pr) != &OPA.integer_var) - memcpy (&R_INT (pr), &OPA, - pr->pr_param_size * sizeof (OPA)); + pr->pr_param_size * sizeof (*op_a)); + else if (&R_INT (pr) != &OPA(int)) + memcpy (&R_INT (pr), op_a, + pr->pr_param_size * sizeof (*op_a)); // fallthrough case OP_RETURN_V: pr->pr_xfunction->profile += profile - startprofile; @@ -1475,8 +1466,8 @@ op_call: int think = pr->fields.think + self; float time = *pr->globals.time + 0.1; pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA.float_var; - pr->pr_edict_area[think].func_var = OPB.func_var; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = OPB(uint); } break; case OP_STATE_F: @@ -1485,23 +1476,23 @@ op_call: int nextthink = pr->fields.nextthink + self; int frame = pr->fields.frame + self; int think = pr->fields.think + self; - float time = *pr->globals.time + OPC.float_var; + float time = *pr->globals.time + OPC(float); pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA.float_var; - pr->pr_edict_area[think].func_var = OPB.func_var; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = OPB(uint); } break; case OP_ADD_I: - OPC.integer_var = OPA.integer_var + OPB.integer_var; + OPC(int) = OPA(int) + OPB(int); break; case OP_SUB_I: - OPC.integer_var = OPA.integer_var - OPB.integer_var; + OPC(int) = OPA(int) - OPB(int); break; case OP_MUL_I: - OPC.integer_var = OPA.integer_var * OPB.integer_var; + OPC(int) = OPA(int) * OPB(int); break; case OP_DIV_I: - OPC.integer_var = OPA.integer_var / OPB.integer_var; + OPC(int) = OPA(int) / OPB(int); break; case OP_MOD_I: { @@ -1510,193 +1501,193 @@ op_call: // -5 mod 3 = 1 // 5 mod -3 = -1 // -5 mod -3 = -2 - int a = OPA.integer_var; - int b = OPB.integer_var; + int a = OPA(int); + int b = OPB(int); int c = a % b; // % is really remainder and so has the same sign rules // as division: -5 % 3 = -2, so need to add b (3 here) // if c's sign is incorrect, but only if c is non-zero int mask = (a ^ b) >> 31; mask &= ~(!!c + 0) + 1; // +0 to convert bool to int (gcc) - OPC.integer_var = c + (mask & b); + OPC(int) = c + (mask & b); } break; case OP_REM_I: - OPC.integer_var = OPA.integer_var % OPB.integer_var; + OPC(int) = OPA(int) % OPB(int); break; case OP_MOD_D: { - double a = OPA_double_var; - double b = OPB_double_var; + double a = OPA(double); + double b = OPB(double); // floating point modulo is so much easier :P - OPC_double_var = a - b * floor (a / b); + OPC(double) = a - b * floor (a / b); } break; case OP_REM_D: { - double a = OPA_double_var; - double b = OPB_double_var; - OPC_double_var = a - b * trunc (a / b); + double a = OPA(double); + double b = OPB(double); + OPC(double) = a - b * trunc (a / b); } break; case OP_MOD_F: { - float a = OPA.float_var; - float b = OPB.float_var; - OPC.float_var = a - b * floorf (a / b); + float a = OPA(float); + float b = OPB(float); + OPC(float) = a - b * floorf (a / b); } break; case OP_REM_F: { - float a = OPA.float_var; - float b = OPB.float_var; - OPC.float_var = a - b * truncf (a / b); + float a = OPA(float); + float b = OPB(float); + OPC(float) = a - b * truncf (a / b); } break; case OP_CONV_IF: - OPC.float_var = OPA.integer_var; + OPC(float) = OPA(int); break; case OP_CONV_FI: - OPC.integer_var = OPA.float_var; + OPC(int) = OPA(float); break; case OP_BITAND_I: - OPC.integer_var = OPA.integer_var & OPB.integer_var; + OPC(int) = OPA(int) & OPB(int); break; case OP_BITOR_I: - OPC.integer_var = OPA.integer_var | OPB.integer_var; + OPC(int) = OPA(int) | OPB(int); break; case OP_BITXOR_I: - OPC.integer_var = OPA.integer_var ^ OPB.integer_var; + OPC(int) = OPA(int) ^ OPB(int); break; case OP_BITNOT_I: - OPC.integer_var = ~OPA.integer_var; + OPC(int) = ~OPA(int); break; case OP_GE_I: case OP_GE_P: - OPC.integer_var = OPA.integer_var >= OPB.integer_var; + OPC(int) = OPA(int) >= OPB(int); break; case OP_GE_U: - OPC.integer_var = OPA.uinteger_var >= OPB.uinteger_var; + OPC(int) = OPA(uint) >= OPB(uint); break; case OP_LE_I: case OP_LE_P: - OPC.integer_var = OPA.integer_var <= OPB.integer_var; + OPC(int) = OPA(int) <= OPB(int); break; case OP_LE_U: - OPC.integer_var = OPA.uinteger_var <= OPB.uinteger_var; + OPC(int) = OPA(uint) <= OPB(uint); break; case OP_GT_I: case OP_GT_P: - OPC.integer_var = OPA.integer_var > OPB.integer_var; + OPC(int) = OPA(int) > OPB(int); break; case OP_GT_U: - OPC.integer_var = OPA.uinteger_var > OPB.uinteger_var; + OPC(int) = OPA(uint) > OPB(uint); break; case OP_LT_I: case OP_LT_P: - OPC.integer_var = OPA.integer_var < OPB.integer_var; + OPC(int) = OPA(int) < OPB(int); break; case OP_LT_U: - OPC.integer_var = OPA.uinteger_var < OPB.uinteger_var; + OPC(int) = OPA(uint) < OPB(uint); break; case OP_AND_I: - OPC.integer_var = OPA.integer_var && OPB.integer_var; + OPC(int) = OPA(int) && OPB(int); break; case OP_OR_I: - OPC.integer_var = OPA.integer_var || OPB.integer_var; + OPC(int) = OPA(int) || OPB(int); break; case OP_NOT_I: case OP_NOT_P: - OPC.integer_var = !OPA.integer_var; + OPC(int) = !OPA(int); break; case OP_EQ_I: case OP_EQ_P: - OPC.integer_var = OPA.integer_var == OPB.integer_var; + OPC(int) = OPA(int) == OPB(int); break; case OP_NE_I: case OP_NE_P: - OPC.integer_var = OPA.integer_var != OPB.integer_var; + OPC(int) = OPA(int) != OPB(int); break; case OP_MOVEI: - memmove (&OPC, &OPA, st->b * 4); + memmove (op_c, op_a, st->b * 4); break; case OP_MOVEP: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC.integer_var, OPB.uinteger_var); - PR_BoundsCheckSize (pr, OPA.integer_var, OPB.uinteger_var); + PR_BoundsCheckSize (pr, OPC(int), OPB(uint)); + PR_BoundsCheckSize (pr, OPA(int), OPB(uint)); } - memmove (pr->pr_globals + OPC.integer_var, - pr->pr_globals + OPA.integer_var, - OPB.uinteger_var * 4); + memmove (pr->pr_globals + OPC(int), + pr->pr_globals + OPA(int), + OPB(uint) * 4); break; case OP_MOVEPI: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC.integer_var, st->b); - PR_BoundsCheckSize (pr, OPA.integer_var, st->b); + PR_BoundsCheckSize (pr, OPC(int), st->b); + PR_BoundsCheckSize (pr, OPA(int), st->b); } - memmove (pr->pr_globals + OPC.integer_var, - pr->pr_globals + OPA.integer_var, + memmove (pr->pr_globals + OPC(int), + pr->pr_globals + OPA(int), st->b * 4); break; case OP_MEMSETI: - pr_memset (&OPC, OPA.integer_var, st->b); + pr_memset (op_c, OPA(int), st->b); break; case OP_MEMSETP: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC.pointer_var, OPB.integer_var); + PR_BoundsCheckSize (pr, OPC(pointer), OPB(int)); } - pr_memset (pr->pr_globals + OPC.pointer_var, OPA.integer_var, - OPB.integer_var); + pr_memset (pr->pr_globals + OPC(pointer), OPA(int), + OPB(int)); break; case OP_MEMSETPI: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC.pointer_var, st->b); + PR_BoundsCheckSize (pr, OPC(pointer), st->b); } - pr_memset (pr->pr_globals + OPC.pointer_var, OPA.integer_var, + pr_memset (pr->pr_globals + OPC(pointer), OPA(int), st->b); break; case OP_GE_D: - OPC.float_var = OPA_double_var >= OPB_double_var; + OPC(float) = OPA(double) >= OPB(double); break; case OP_LE_D: - OPC.float_var = OPA_double_var <= OPB_double_var; + OPC(float) = OPA(double) <= OPB(double); break; case OP_GT_D: - OPC.float_var = OPA_double_var > OPB_double_var; + OPC(float) = OPA(double) > OPB(double); break; case OP_LT_D: - OPC.float_var = OPA_double_var < OPB_double_var; + OPC(float) = OPA(double) < OPB(double); break; case OP_NOT_D: - OPC.integer_var = (op_a[0].integer_var + OPC(int) = (op_a[0].integer_var || (op_a[1].integer_var & ~0x80000000u)); break; case OP_EQ_D: - OPC.integer_var = OPA_double_var == OPB_double_var; + OPC(int) = OPA(double) == OPB(double); break; case OP_NE_D: - OPC.integer_var = OPA_double_var != OPB_double_var; + OPC(int) = OPA(double) != OPB(double); break; case OP_CONV_ID: - OPC_double_var = OPA.integer_var; + OPC(double) = OPA(int); break; case OP_CONV_DI: - OPC.integer_var = OPA_double_var; + OPC(int) = OPA(double); break; case OP_CONV_FD: - OPC_double_var = OPA.float_var; + OPC(double) = OPA(float); break; case OP_CONV_DF: - OPC.float_var = OPA_double_var; + OPC(float) = OPA(double); break; // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized /* case OP_BOUNDCHECK: - if (OPA.integer_var < 0 || OPA.integer_var >= st->b) { + if (OPA(int) < 0 || OPA(int) >= st->b) { PR_RunError (pr, "Progs boundcheck failed at line number " "%d, value is < 0 or >= %d", st->b, st->c); } From 0c17c6dc24fa1dc38ee5c61a78b59e40174aa1ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 21:06:14 +0900 Subject: [PATCH 2088/3664] [gamecode] Rename the old opcodes To reflect their basis on v6 progs instructions, they sport the v6p tag where the p is for "plus" due to the QuakeForge extensions. --- include/QF/pr_comp.h | 594 ++++++++++++++-------------- libs/gamecode/pr_debug.c | 4 +- libs/gamecode/pr_exec.c | 600 ++++++++++++++-------------- libs/gamecode/pr_opcode.c | 744 +++++++++++++++++------------------ tools/qfcc/include/opcodes.h | 35 +- tools/qfcc/source/emit.c | 2 +- tools/qfcc/source/opcodes.c | 28 +- 7 files changed, 1004 insertions(+), 1003 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 971584070..f51ce2693 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -89,355 +89,355 @@ extern const char * const pr_type_name[ev_type_count]; typedef enum { - OP_DONE, - OP_MUL_F, - OP_MUL_V, - OP_MUL_FV, - OP_MUL_VF, - OP_DIV_F, - OP_ADD_F, - OP_ADD_V, - OP_SUB_F, - OP_SUB_V, + OP_DONE_v6p, + OP_MUL_F_v6p, + OP_MUL_V_v6p, + OP_MUL_FV_v6p, + OP_MUL_VF_v6p, + OP_DIV_F_v6p, + OP_ADD_F_v6p, + OP_ADD_V_v6p, + OP_SUB_F_v6p, + OP_SUB_V_v6p, - OP_EQ_F, - OP_EQ_V, - OP_EQ_S, - OP_EQ_E, - OP_EQ_FN, + OP_EQ_F_v6p, + OP_EQ_V_v6p, + OP_EQ_S_v6p, + OP_EQ_E_v6p, + OP_EQ_FN_v6p, - OP_NE_F, - OP_NE_V, - OP_NE_S, - OP_NE_E, - OP_NE_FN, + OP_NE_F_v6p, + OP_NE_V_v6p, + OP_NE_S_v6p, + OP_NE_E_v6p, + OP_NE_FN_v6p, - OP_LE_F, - OP_GE_F, - OP_LT_F, - OP_GT_F, + OP_LE_F_v6p, + OP_GE_F_v6p, + OP_LT_F_v6p, + OP_GT_F_v6p, - OP_LOAD_F, - OP_LOAD_V, - OP_LOAD_S, - OP_LOAD_ENT, - OP_LOAD_FLD, - OP_LOAD_FN, + OP_LOAD_F_v6p, + OP_LOAD_V_v6p, + OP_LOAD_S_v6p, + OP_LOAD_ENT_v6p, + OP_LOAD_FLD_v6p, + OP_LOAD_FN_v6p, - OP_ADDRESS, + OP_ADDRESS_v6p, - OP_STORE_F, - OP_STORE_V, - OP_STORE_S, - OP_STORE_ENT, - OP_STORE_FLD, - OP_STORE_FN, + OP_STORE_F_v6p, + OP_STORE_V_v6p, + OP_STORE_S_v6p, + OP_STORE_ENT_v6p, + OP_STORE_FLD_v6p, + OP_STORE_FN_v6p, - OP_STOREP_F, - OP_STOREP_V, - OP_STOREP_S, - OP_STOREP_ENT, - OP_STOREP_FLD, - OP_STOREP_FN, + OP_STOREP_F_v6p, + OP_STOREP_V_v6p, + OP_STOREP_S_v6p, + OP_STOREP_ENT_v6p, + OP_STOREP_FLD_v6p, + OP_STOREP_FN_v6p, - OP_RETURN, - OP_NOT_F, - OP_NOT_V, - OP_NOT_S, - OP_NOT_ENT, - OP_NOT_FN, - OP_IF, - OP_IFNOT, - OP_CALL0, - OP_CALL1, - OP_CALL2, - OP_CALL3, - OP_CALL4, - OP_CALL5, - OP_CALL6, - OP_CALL7, - OP_CALL8, - OP_STATE, - OP_GOTO, - OP_AND, - OP_OR, + OP_RETURN_v6p, + OP_NOT_F_v6p, + OP_NOT_V_v6p, + OP_NOT_S_v6p, + OP_NOT_ENT_v6p, + OP_NOT_FN_v6p, + OP_IF_v6p, + OP_IFNOT_v6p, + OP_CALL0_v6p, + OP_CALL1_v6p, + OP_CALL2_v6p, + OP_CALL3_v6p, + OP_CALL4_v6p, + OP_CALL5_v6p, + OP_CALL6_v6p, + OP_CALL7_v6p, + OP_CALL8_v6p, + OP_STATE_v6p, + OP_GOTO_v6p, + OP_AND_v6p, + OP_OR_v6p, - OP_BITAND, - OP_BITOR, // end of v6 opcodes + OP_BITAND_v6p, + OP_BITOR_v6p, // end of v6 opcodes - OP_ADD_S, - OP_LE_S, - OP_GE_S, - OP_LT_S, - OP_GT_S, + OP_ADD_S_v6p, + OP_LE_S_v6p, + OP_GE_S_v6p, + OP_LT_S_v6p, + OP_GT_S_v6p, - OP_ADD_I, - OP_SUB_I, - OP_MUL_I, - OP_DIV_I, - OP_BITAND_I, - OP_BITOR_I, - OP_GE_I, - OP_LE_I, - OP_GT_I, - OP_LT_I, - OP_AND_I, - OP_OR_I, - OP_NOT_I, - OP_EQ_I, - OP_NE_I, - OP_STORE_I, - OP_STOREP_I, - OP_LOAD_I, + OP_ADD_I_v6p, + OP_SUB_I_v6p, + OP_MUL_I_v6p, + OP_DIV_I_v6p, + OP_BITAND_I_v6p, + OP_BITOR_I_v6p, + OP_GE_I_v6p, + OP_LE_I_v6p, + OP_GT_I_v6p, + OP_LT_I_v6p, + OP_AND_I_v6p, + OP_OR_I_v6p, + OP_NOT_I_v6p, + OP_EQ_I_v6p, + OP_NE_I_v6p, + OP_STORE_I_v6p, + OP_STOREP_I_v6p, + OP_LOAD_I_v6p, - OP_CONV_IF, - OP_CONV_FI, + OP_CONV_IF_v6p, + OP_CONV_FI_v6p, - OP_BITXOR_F, - OP_BITXOR_I, - OP_BITNOT_F, - OP_BITNOT_I, + OP_BITXOR_F_v6p, + OP_BITXOR_I_v6p, + OP_BITNOT_F_v6p, + OP_BITNOT_I_v6p, - OP_SHL_F, - OP_SHR_F, - OP_SHL_I, - OP_SHR_I, + OP_SHL_F_v6p, + OP_SHR_F_v6p, + OP_SHL_I_v6p, + OP_SHR_I_v6p, - OP_REM_F, - OP_REM_I, + OP_REM_F_v6p, + OP_REM_I_v6p, - OP_LOADB_F, - OP_LOADB_V, - OP_LOADB_S, - OP_LOADB_ENT, - OP_LOADB_FLD, - OP_LOADB_FN, - OP_LOADB_I, - OP_LOADB_P, + OP_LOADB_F_v6p, + OP_LOADB_V_v6p, + OP_LOADB_S_v6p, + OP_LOADB_ENT_v6p, + OP_LOADB_FLD_v6p, + OP_LOADB_FN_v6p, + OP_LOADB_I_v6p, + OP_LOADB_P_v6p, - OP_STOREB_F, - OP_STOREB_V, - OP_STOREB_S, - OP_STOREB_ENT, - OP_STOREB_FLD, - OP_STOREB_FN, - OP_STOREB_I, - OP_STOREB_P, + OP_STOREB_F_v6p, + OP_STOREB_V_v6p, + OP_STOREB_S_v6p, + OP_STOREB_ENT_v6p, + OP_STOREB_FLD_v6p, + OP_STOREB_FN_v6p, + OP_STOREB_I_v6p, + OP_STOREB_P_v6p, - OP_ADDRESS_VOID, - OP_ADDRESS_F, - OP_ADDRESS_V, - OP_ADDRESS_S, - OP_ADDRESS_ENT, - OP_ADDRESS_FLD, - OP_ADDRESS_FN, - OP_ADDRESS_I, - OP_ADDRESS_P, + OP_ADDRESS_VOID_v6p, + OP_ADDRESS_F_v6p, + OP_ADDRESS_V_v6p, + OP_ADDRESS_S_v6p, + OP_ADDRESS_ENT_v6p, + OP_ADDRESS_FLD_v6p, + OP_ADDRESS_FN_v6p, + OP_ADDRESS_I_v6p, + OP_ADDRESS_P_v6p, - OP_LEA, + OP_LEA_v6p, - OP_IFBE, - OP_IFB, - OP_IFAE, - OP_IFA, + OP_IFBE_v6p, + OP_IFB_v6p, + OP_IFAE_v6p, + OP_IFA_v6p, - OP_JUMP, - OP_JUMPB, + OP_JUMP_v6p, + OP_JUMPB_v6p, - OP_LT_U, - OP_GT_U, - OP_LE_U, - OP_GE_U, + OP_LT_U_v6p, + OP_GT_U_v6p, + OP_LE_U_v6p, + OP_GE_U_v6p, - OP_LOADBI_F, - OP_LOADBI_V, - OP_LOADBI_S, - OP_LOADBI_ENT, - OP_LOADBI_FLD, - OP_LOADBI_FN, - OP_LOADBI_I, - OP_LOADBI_P, + OP_LOADBI_F_v6p, + OP_LOADBI_V_v6p, + OP_LOADBI_S_v6p, + OP_LOADBI_ENT_v6p, + OP_LOADBI_FLD_v6p, + OP_LOADBI_FN_v6p, + OP_LOADBI_I_v6p, + OP_LOADBI_P_v6p, - OP_STOREBI_F, - OP_STOREBI_V, - OP_STOREBI_S, - OP_STOREBI_ENT, - OP_STOREBI_FLD, - OP_STOREBI_FN, - OP_STOREBI_I, - OP_STOREBI_P, + OP_STOREBI_F_v6p, + OP_STOREBI_V_v6p, + OP_STOREBI_S_v6p, + OP_STOREBI_ENT_v6p, + OP_STOREBI_FLD_v6p, + OP_STOREBI_FN_v6p, + OP_STOREBI_I_v6p, + OP_STOREBI_P_v6p, - OP_LEAI, + OP_LEAI_v6p, - OP_LOAD_P, - OP_STORE_P, - OP_STOREP_P, - OP_NOT_P, - OP_EQ_P, - OP_NE_P, - OP_LE_P, - OP_GE_P, - OP_LT_P, - OP_GT_P, + OP_LOAD_P_v6p, + OP_STORE_P_v6p, + OP_STOREP_P_v6p, + OP_NOT_P_v6p, + OP_EQ_P_v6p, + OP_NE_P_v6p, + OP_LE_P_v6p, + OP_GE_P_v6p, + OP_LT_P_v6p, + OP_GT_P_v6p, - OP_MOVEI, - OP_MOVEP, - OP_MOVEPI, + OP_MOVEI_v6p, + OP_MOVEP_v6p, + OP_MOVEPI_v6p, - OP_SHR_U, + OP_SHR_U_v6p, - OP_STATE_F, + OP_STATE_F_v6p, - OP_ADD_Q, - OP_SUB_Q, - OP_MUL_Q, - OP_MUL_QF, - OP_MUL_FQ, - OP_MUL_QV, - OP_CONJ_Q, - OP_NOT_Q, - OP_EQ_Q, - OP_NE_Q, - OP_STORE_Q, - OP_STOREB_Q, - OP_STOREBI_Q, - OP_STOREP_Q, - OP_LOAD_Q, - OP_LOADB_Q, - OP_LOADBI_Q, - OP_ADDRESS_Q, + OP_ADD_Q_v6p, + OP_SUB_Q_v6p, + OP_MUL_Q_v6p, + OP_MUL_QF_v6p, + OP_MUL_FQ_v6p, + OP_MUL_QV_v6p, + OP_CONJ_Q_v6p, + OP_NOT_Q_v6p, + OP_EQ_Q_v6p, + OP_NE_Q_v6p, + OP_STORE_Q_v6p, + OP_STOREB_Q_v6p, + OP_STOREBI_Q_v6p, + OP_STOREP_Q_v6p, + OP_LOAD_Q_v6p, + OP_LOADB_Q_v6p, + OP_LOADBI_Q_v6p, + OP_ADDRESS_Q_v6p, - OP_RCALL0, - OP_RCALL1, - OP_RCALL2, - OP_RCALL3, - OP_RCALL4, - OP_RCALL5, - OP_RCALL6, - OP_RCALL7, - OP_RCALL8, + OP_RCALL0_v6p, + OP_RCALL1_v6p, + OP_RCALL2_v6p, + OP_RCALL3_v6p, + OP_RCALL4_v6p, + OP_RCALL5_v6p, + OP_RCALL6_v6p, + OP_RCALL7_v6p, + OP_RCALL8_v6p, - OP_RETURN_V, + OP_RETURN_V_v6p, - OP_PUSH_S, - OP_PUSH_F, - OP_PUSH_V, - OP_PUSH_ENT, - OP_PUSH_FLD, - OP_PUSH_FN, - OP_PUSH_P, - OP_PUSH_Q, - OP_PUSH_I, - OP_PUSH_D, + OP_PUSH_S_v6p, + OP_PUSH_F_v6p, + OP_PUSH_V_v6p, + OP_PUSH_ENT_v6p, + OP_PUSH_FLD_v6p, + OP_PUSH_FN_v6p, + OP_PUSH_P_v6p, + OP_PUSH_Q_v6p, + OP_PUSH_I_v6p, + OP_PUSH_D_v6p, - OP_PUSHB_S, - OP_PUSHB_F, - OP_PUSHB_V, - OP_PUSHB_ENT, - OP_PUSHB_FLD, - OP_PUSHB_FN, - OP_PUSHB_P, - OP_PUSHB_Q, - OP_PUSHB_I, - OP_PUSHB_D, + OP_PUSHB_S_v6p, + OP_PUSHB_F_v6p, + OP_PUSHB_V_v6p, + OP_PUSHB_ENT_v6p, + OP_PUSHB_FLD_v6p, + OP_PUSHB_FN_v6p, + OP_PUSHB_P_v6p, + OP_PUSHB_Q_v6p, + OP_PUSHB_I_v6p, + OP_PUSHB_D_v6p, - OP_PUSHBI_S, - OP_PUSHBI_F, - OP_PUSHBI_V, - OP_PUSHBI_ENT, - OP_PUSHBI_FLD, - OP_PUSHBI_FN, - OP_PUSHBI_P, - OP_PUSHBI_Q, - OP_PUSHBI_I, - OP_PUSHBI_D, + OP_PUSHBI_S_v6p, + OP_PUSHBI_F_v6p, + OP_PUSHBI_V_v6p, + OP_PUSHBI_ENT_v6p, + OP_PUSHBI_FLD_v6p, + OP_PUSHBI_FN_v6p, + OP_PUSHBI_P_v6p, + OP_PUSHBI_Q_v6p, + OP_PUSHBI_I_v6p, + OP_PUSHBI_D_v6p, - OP_POP_S, - OP_POP_F, - OP_POP_V, - OP_POP_ENT, - OP_POP_FLD, - OP_POP_FN, - OP_POP_P, - OP_POP_Q, - OP_POP_I, - OP_POP_D, + OP_POP_S_v6p, + OP_POP_F_v6p, + OP_POP_V_v6p, + OP_POP_ENT_v6p, + OP_POP_FLD_v6p, + OP_POP_FN_v6p, + OP_POP_P_v6p, + OP_POP_Q_v6p, + OP_POP_I_v6p, + OP_POP_D_v6p, - OP_POPB_S, - OP_POPB_F, - OP_POPB_V, - OP_POPB_ENT, - OP_POPB_FLD, - OP_POPB_FN, - OP_POPB_P, - OP_POPB_Q, - OP_POPB_I, - OP_POPB_D, + OP_POPB_S_v6p, + OP_POPB_F_v6p, + OP_POPB_V_v6p, + OP_POPB_ENT_v6p, + OP_POPB_FLD_v6p, + OP_POPB_FN_v6p, + OP_POPB_P_v6p, + OP_POPB_Q_v6p, + OP_POPB_I_v6p, + OP_POPB_D_v6p, - OP_POPBI_S, - OP_POPBI_F, - OP_POPBI_V, - OP_POPBI_ENT, - OP_POPBI_FLD, - OP_POPBI_FN, - OP_POPBI_P, - OP_POPBI_Q, - OP_POPBI_I, - OP_POPBI_D, + OP_POPBI_S_v6p, + OP_POPBI_F_v6p, + OP_POPBI_V_v6p, + OP_POPBI_ENT_v6p, + OP_POPBI_FLD_v6p, + OP_POPBI_FN_v6p, + OP_POPBI_P_v6p, + OP_POPBI_Q_v6p, + OP_POPBI_I_v6p, + OP_POPBI_D_v6p, - OP_ADD_D, - OP_SUB_D, - OP_MUL_D, - OP_MUL_QD, - OP_MUL_DQ, - OP_MUL_VD, - OP_MUL_DV, - OP_DIV_D, - OP_REM_D, - OP_GE_D, - OP_LE_D, - OP_GT_D, - OP_LT_D, - OP_NOT_D, - OP_EQ_D, - OP_NE_D, - OP_CONV_FD, - OP_CONV_DF, - OP_CONV_ID, - OP_CONV_DI, - OP_STORE_D, - OP_STOREB_D, - OP_STOREBI_D, - OP_STOREP_D, - OP_LOAD_D, - OP_LOADB_D, - OP_LOADBI_D, - OP_ADDRESS_D, + OP_ADD_D_v6p, + OP_SUB_D_v6p, + OP_MUL_D_v6p, + OP_MUL_QD_v6p, + OP_MUL_DQ_v6p, + OP_MUL_VD_v6p, + OP_MUL_DV_v6p, + OP_DIV_D_v6p, + OP_REM_D_v6p, + OP_GE_D_v6p, + OP_LE_D_v6p, + OP_GT_D_v6p, + OP_LT_D_v6p, + OP_NOT_D_v6p, + OP_EQ_D_v6p, + OP_NE_D_v6p, + OP_CONV_FD_v6p, + OP_CONV_DF_v6p, + OP_CONV_ID_v6p, + OP_CONV_DI_v6p, + OP_STORE_D_v6p, + OP_STOREB_D_v6p, + OP_STOREBI_D_v6p, + OP_STOREP_D_v6p, + OP_LOAD_D_v6p, + OP_LOADB_D_v6p, + OP_LOADBI_D_v6p, + OP_ADDRESS_D_v6p, - OP_MOD_I, - OP_MOD_F, - OP_MOD_D, + OP_MOD_I_v6p, + OP_MOD_F_v6p, + OP_MOD_D_v6p, - OP_MEMSETI, - OP_MEMSETP, - OP_MEMSETPI, -} pr_opcode_e; + OP_MEMSETI_v6p, + OP_MEMSETP_v6p, + OP_MEMSETPI_v6p, +} pr_opcode_v6p_e; #define OP_BREAK 0x8000 -typedef struct opcode_s { +typedef struct v6p_opcode_s { const char *name; const char *opname; etype_t type_a, type_b, type_c; unsigned int min_version; const char *fmt; -} opcode_t; +} v6p_opcode_t; -extern const opcode_t pr_opcodes[]; -const opcode_t *PR_Opcode (pr_short_t opcode) __attribute__((const)); +extern const v6p_opcode_t pr_v6p_opcodes[]; +const v6p_opcode_t *PR_v6p_Opcode (pr_ushort_t opcode) __attribute__((const)); void PR_Opcode_Init (void); // idempotent typedef struct dstatement_s { - pr_opcode_e op:16; + pr_opcode_v6p_e op:16; pr_ushort_t a,b,c; } GCC_STRUCT dstatement_t; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index a720a863d..9b8d11fde 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1482,7 +1482,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) int addr = s - pr->pr_statements; int dump_code = contents & 2; const char *fmt; - const opcode_t *op; + const v6p_opcode_t *op; dfunction_t *call_func = 0; pr_def_t *parm_def = 0; pr_auxfunction_t *aux_func = 0; @@ -1508,7 +1508,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) return; } - op = PR_Opcode (s->op); + op = PR_v6p_Opcode (s->op); if (!op) { Sys_Printf ("%sUnknown instruction %d\n", res->line->str, s->op); return; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index fa226a417..ae6b3df4e 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -355,23 +355,23 @@ signal_hook (int sig, void *data) op_c = pr->pr_globals + st->c; switch (st->op) { - case OP_DIV_F: + case OP_DIV_F_v6p: if ((OPA(int) & 0x80000000) ^ (OPB(int) & 0x80000000)) OPC(int) = 0xff7fffff; else OPC(int) = 0x7f7fffff; return 1; - case OP_DIV_I: + case OP_DIV_I_v6p: if (OPA(int) & 0x80000000) OPC(int) = -0x80000000; else OPC(int) = 0x7fffffff; return 1; - case OP_MOD_I: - case OP_MOD_F: - case OP_REM_I: - case OP_REM_F: + case OP_MOD_I_v6p: + case OP_MOD_F_v6p: + case OP_REM_I_v6p: + case OP_REM_F_v6p: OPC(int) = 0x00000000; return 1; default: @@ -481,50 +481,50 @@ pr_exec_quakec (progs_t *pr, int exitdepth) } } - pr_opcode_e op = st->op & ~OP_BREAK; + pr_opcode_v6p_e op = st->op & ~OP_BREAK; switch (op) { - case OP_ADD_D: + case OP_ADD_D_v6p: OPC(double) = OPA(double) + OPB(double); break; - case OP_ADD_F: + case OP_ADD_F_v6p: OPC(float) = OPA(float) + OPB(float); break; - case OP_ADD_V: + case OP_ADD_V_v6p: VectorAdd (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_ADD_Q: + case OP_ADD_Q_v6p: QuatAdd (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_ADD_S: + case OP_ADD_S_v6p: OPC(string) = PR_CatStrings (pr, PR_GetString (pr, OPA(string)), PR_GetString (pr, OPB(string))); break; - case OP_SUB_D: + case OP_SUB_D_v6p: OPC(double) = OPA(double) - OPB(double); break; - case OP_SUB_F: + case OP_SUB_F_v6p: OPC(float) = OPA(float) - OPB(float); break; - case OP_SUB_V: + case OP_SUB_V_v6p: VectorSubtract (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_SUB_Q: + case OP_SUB_Q_v6p: QuatSubtract (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_MUL_D: + case OP_MUL_D_v6p: OPC(double) = OPA(double) * OPB(double); break; - case OP_MUL_F: + case OP_MUL_F_v6p: OPC(float) = OPA(float) * OPB(float); break; - case OP_MUL_V: + case OP_MUL_V_v6p: OPC(float) = DotProduct (&OPA(float), &OPB(float)); break; - case OP_MUL_DV: + case OP_MUL_DV_v6p: { // avoid issues with the likes of x = x.x * x; // makes for faster code, too @@ -532,7 +532,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) VectorScale (&OPB(float), scale, &OPC(float)); } break; - case OP_MUL_VD: + case OP_MUL_VD_v6p: { // avoid issues with the likes of x = x * x.x; // makes for faster code, too @@ -540,7 +540,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) VectorScale (&OPA(float), scale, &OPC(float)); } break; - case OP_MUL_FV: + case OP_MUL_FV_v6p: { // avoid issues with the likes of x = x.x * x; // makes for faster code, too @@ -548,7 +548,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) VectorScale (&OPB(float), scale, &OPC(float)); } break; - case OP_MUL_VF: + case OP_MUL_VF_v6p: { // avoid issues with the likes of x = x * x.x; // makes for faster code, too @@ -556,13 +556,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) VectorScale (&OPA(float), scale, &OPC(float)); } break; - case OP_MUL_Q: + case OP_MUL_Q_v6p: QuatMult (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_MUL_QV: + case OP_MUL_QV_v6p: QuatMultVec (&OPA(float), &OPB(float), &OPC(float)); break; - case OP_MUL_DQ: + case OP_MUL_DQ_v6p: { // avoid issues with the likes of x = x.s * x; // makes for faster code, too @@ -570,7 +570,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) QuatScale (&OPB(float), scale, &OPC(float)); } break; - case OP_MUL_QD: + case OP_MUL_QD_v6p: { // avoid issues with the likes of x = x * x.s; // makes for faster code, too @@ -578,7 +578,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) QuatScale (&OPA(float), scale, &OPC(float)); } break; - case OP_MUL_FQ: + case OP_MUL_FQ_v6p: { // avoid issues with the likes of x = x.s * x; // makes for faster code, too @@ -586,7 +586,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) QuatScale (&OPB(float), scale, &OPC(float)); } break; - case OP_MUL_QF: + case OP_MUL_QF_v6p: { // avoid issues with the likes of x = x * x.s; // makes for faster code, too @@ -594,160 +594,160 @@ pr_exec_quakec (progs_t *pr, int exitdepth) QuatScale (&OPA(float), scale, &OPC(float)); } break; - case OP_CONJ_Q: + case OP_CONJ_Q_v6p: QuatConj (&OPA(float), &OPC(float)); break; - case OP_DIV_D: + case OP_DIV_D_v6p: OPC(double) = OPA(double) / OPB(double); break; - case OP_DIV_F: + case OP_DIV_F_v6p: OPC(float) = OPA(float) / OPB(float); break; - case OP_BITAND: + case OP_BITAND_v6p: OPC(float) = (int) OPA(float) & (int) OPB(float); break; - case OP_BITOR: + case OP_BITOR_v6p: OPC(float) = (int) OPA(float) | (int) OPB(float); break; - case OP_BITXOR_F: + case OP_BITXOR_F_v6p: OPC(float) = (int) OPA(float) ^ (int) OPB(float); break; - case OP_BITNOT_F: + case OP_BITNOT_F_v6p: OPC(float) = ~ (int) OPA(float); break; - case OP_SHL_F: + case OP_SHL_F_v6p: OPC(float) = (int) OPA(float) << (int) OPB(float); break; - case OP_SHR_F: + case OP_SHR_F_v6p: OPC(float) = (int) OPA(float) >> (int) OPB(float); break; - case OP_SHL_I: + case OP_SHL_I_v6p: OPC(int) = OPA(int) << OPB(int); break; - case OP_SHR_I: + case OP_SHR_I_v6p: OPC(int) = OPA(int) >> OPB(int); break; - case OP_SHR_U: + case OP_SHR_U_v6p: OPC(uint) = OPA(uint) >> OPB(int); break; - case OP_GE_F: + case OP_GE_F_v6p: OPC(float) = OPA(float) >= OPB(float); break; - case OP_LE_F: + case OP_LE_F_v6p: OPC(float) = OPA(float) <= OPB(float); break; - case OP_GT_F: + case OP_GT_F_v6p: OPC(float) = OPA(float) > OPB(float); break; - case OP_LT_F: + case OP_LT_F_v6p: OPC(float) = OPA(float) < OPB(float); break; - case OP_AND: // OPA and OPB have to be float for -0.0 + case OP_AND_v6p: // OPA and OPB have to be float for -0.0 OPC(int) = FNZ (OPA(uint)) && FNZ (OPB(uint)); break; - case OP_OR: // OPA and OPB have to be float for -0.0 + case OP_OR_v6p: // OPA and OPB have to be float for -0.0 OPC(int) = FNZ (OPA(uint)) || FNZ (OPB(uint)); break; - case OP_NOT_F: + case OP_NOT_F_v6p: OPC(int) = !FNZ (OPA(uint)); break; - case OP_NOT_V: + case OP_NOT_V_v6p: OPC(int) = VectorIsZero (&OPA(float)); break; - case OP_NOT_Q: + case OP_NOT_Q_v6p: OPC(int) = QuatIsZero (&OPA(float)); break; - case OP_NOT_S: + case OP_NOT_S_v6p: OPC(int) = !OPA(string) || !*PR_GetString (pr, OPA(string)); break; - case OP_NOT_FN: + case OP_NOT_FN_v6p: OPC(int) = !OPA(uint); break; - case OP_NOT_ENT: + case OP_NOT_ENT_v6p: OPC(int) = !OPA(uint); break; - case OP_EQ_F: + case OP_EQ_F_v6p: OPC(int) = OPA(float) == OPB(float); break; - case OP_EQ_V: + case OP_EQ_V_v6p: OPC(int) = VectorCompare (&OPA(float), &OPB(float)); break; - case OP_EQ_Q: + case OP_EQ_Q_v6p: OPC(int) = QuatCompare (&OPA(float), &OPB(float)); break; - case OP_EQ_E: + case OP_EQ_E_v6p: OPC(int) = OPA(int) == OPB(int); break; - case OP_EQ_FN: + case OP_EQ_FN_v6p: OPC(int) = OPA(uint) == OPB(uint); break; - case OP_NE_F: + case OP_NE_F_v6p: OPC(int) = OPA(float) != OPB(float); break; - case OP_NE_V: + case OP_NE_V_v6p: OPC(int) = !VectorCompare (&OPA(float), &OPB(float)); break; - case OP_NE_Q: + case OP_NE_Q_v6p: OPC(int) = !QuatCompare (&OPA(float), &OPB(float)); break; - case OP_LE_S: - case OP_GE_S: - case OP_LT_S: - case OP_GT_S: - case OP_NE_S: - case OP_EQ_S: + case OP_LE_S_v6p: + case OP_GE_S_v6p: + case OP_LT_S_v6p: + case OP_GT_S_v6p: + case OP_NE_S_v6p: + case OP_EQ_S_v6p: { int cmp = strcmp (PR_GetString (pr, OPA(string)), PR_GetString (pr, OPB(string))); switch (st->op) { - case OP_LE_S: cmp = (cmp <= 0); break; - case OP_GE_S: cmp = (cmp >= 0); break; - case OP_LT_S: cmp = (cmp < 0); break; - case OP_GT_S: cmp = (cmp > 0); break; - case OP_NE_S: break; - case OP_EQ_S: cmp = !cmp; break; + case OP_LE_S_v6p: cmp = (cmp <= 0); break; + case OP_GE_S_v6p: cmp = (cmp >= 0); break; + case OP_LT_S_v6p: cmp = (cmp < 0); break; + case OP_GT_S_v6p: cmp = (cmp > 0); break; + case OP_NE_S_v6p: break; + case OP_EQ_S_v6p: cmp = !cmp; break; default: break; } OPC(int) = cmp; } break; - case OP_NE_E: + case OP_NE_E_v6p: OPC(int) = OPA(int) != OPB(int); break; - case OP_NE_FN: + case OP_NE_FN_v6p: OPC(int) = OPA(uint) != OPB(uint); break; // ================== - case OP_STORE_F: - case OP_STORE_ENT: - case OP_STORE_FLD: // integers - case OP_STORE_S: - case OP_STORE_FN: // pointers - case OP_STORE_I: - case OP_STORE_P: + case OP_STORE_F_v6p: + case OP_STORE_ENT_v6p: + case OP_STORE_FLD_v6p: // integers + case OP_STORE_S_v6p: + case OP_STORE_FN_v6p: // pointers + case OP_STORE_I_v6p: + case OP_STORE_P_v6p: OPB(int) = OPA(int); break; - case OP_STORE_V: + case OP_STORE_V_v6p: VectorCopy (&OPA(float), &OPB(float)); break; - case OP_STORE_Q: + case OP_STORE_Q_v6p: QuatCopy (&OPA(float), &OPB(float)); break; - case OP_STORE_D: + case OP_STORE_D_v6p: OPB(double) = OPA(double); break; - case OP_STOREP_F: - case OP_STOREP_ENT: - case OP_STOREP_FLD: // integers - case OP_STOREP_S: - case OP_STOREP_FN: // pointers - case OP_STOREP_I: - case OP_STOREP_P: + case OP_STOREP_F_v6p: + case OP_STOREP_ENT_v6p: + case OP_STOREP_FLD_v6p: // integers + case OP_STOREP_S_v6p: + case OP_STOREP_FN_v6p: // pointers + case OP_STOREP_I_v6p: + case OP_STOREP_P_v6p: pointer = OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); @@ -755,7 +755,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; ptr->integer_var = OPA(int); break; - case OP_STOREP_V: + case OP_STOREP_V_v6p: pointer = OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); @@ -763,7 +763,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; VectorCopy (&OPA(float), &ptr->vector_var); break; - case OP_STOREP_Q: + case OP_STOREP_Q_v6p: pointer = OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); @@ -771,7 +771,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; QuatCopy (&OPA(float), &ptr->quat_var); break; - case OP_STOREP_D: + case OP_STOREP_D_v6p: pointer = OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_double); @@ -780,7 +780,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *(double *) ptr = OPA(double); break; - case OP_ADDRESS: + case OP_ADDRESS_v6p: if (pr_boundscheck->int_val) { if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to address an out " @@ -794,27 +794,27 @@ pr_exec_quakec (progs_t *pr, int exitdepth) fldofs = OPA(uint) + OPB(int); OPC(int) = &pr->pr_edict_area[fldofs] - pr->pr_globals; break; - case OP_ADDRESS_VOID: - case OP_ADDRESS_F: - case OP_ADDRESS_V: - case OP_ADDRESS_Q: - case OP_ADDRESS_S: - case OP_ADDRESS_ENT: - case OP_ADDRESS_FLD: - case OP_ADDRESS_FN: - case OP_ADDRESS_I: - case OP_ADDRESS_P: - case OP_ADDRESS_D: + case OP_ADDRESS_VOID_v6p: + case OP_ADDRESS_F_v6p: + case OP_ADDRESS_V_v6p: + case OP_ADDRESS_Q_v6p: + case OP_ADDRESS_S_v6p: + case OP_ADDRESS_ENT_v6p: + case OP_ADDRESS_FLD_v6p: + case OP_ADDRESS_FN_v6p: + case OP_ADDRESS_I_v6p: + case OP_ADDRESS_P_v6p: + case OP_ADDRESS_D_v6p: OPC(int) = st->a; break; - case OP_LOAD_F: - case OP_LOAD_FLD: - case OP_LOAD_ENT: - case OP_LOAD_S: - case OP_LOAD_FN: - case OP_LOAD_I: - case OP_LOAD_P: + case OP_LOAD_F_v6p: + case OP_LOAD_FLD_v6p: + case OP_LOAD_ENT_v6p: + case OP_LOAD_S_v6p: + case OP_LOAD_FN_v6p: + case OP_LOAD_I_v6p: + case OP_LOAD_P_v6p: if (pr_boundscheck->int_val) { if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " @@ -826,7 +826,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) fldofs = OPA(uint) + OPB(int); OPC(int) = pr->pr_edict_area[fldofs].integer_var; break; - case OP_LOAD_V: + case OP_LOAD_V_v6p: if (pr_boundscheck->int_val) { if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " @@ -838,7 +838,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) fldofs = OPA(uint) + OPB(int); memcpy (op_c, &pr->pr_edict_area[fldofs], 3 * sizeof (*op_c)); break; - case OP_LOAD_Q: + case OP_LOAD_Q_v6p: if (pr_boundscheck->int_val) { if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " @@ -850,7 +850,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) fldofs = OPA(uint) + OPB(int); memcpy (op_c, &pr->pr_edict_area[fldofs], 4 * sizeof (*op_c)); break; - case OP_LOAD_D: + case OP_LOAD_D_v6p: if (pr_boundscheck->int_val) { if (OPA(uint) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " @@ -863,13 +863,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) memcpy (op_c, &pr->pr_edict_area[fldofs], sizeof (double)); break; - case OP_LOADB_F: - case OP_LOADB_S: - case OP_LOADB_ENT: - case OP_LOADB_FLD: - case OP_LOADB_FN: - case OP_LOADB_I: - case OP_LOADB_P: + case OP_LOADB_F_v6p: + case OP_LOADB_S_v6p: + case OP_LOADB_ENT_v6p: + case OP_LOADB_FLD_v6p: + case OP_LOADB_FN_v6p: + case OP_LOADB_I_v6p: + case OP_LOADB_P_v6p: pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); @@ -877,7 +877,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; OPC(int) = ptr->integer_var; break; - case OP_LOADB_V: + case OP_LOADB_V_v6p: pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); @@ -885,7 +885,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; VectorCopy (&ptr->vector_var, &OPC(float)); break; - case OP_LOADB_Q: + case OP_LOADB_Q_v6p: pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); @@ -893,7 +893,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; QuatCopy (&ptr->quat_var, &OPC(float)); break; - case OP_LOADB_D: + case OP_LOADB_D_v6p: pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_double); @@ -902,13 +902,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) OPC(double) = *(double *) ptr; break; - case OP_LOADBI_F: - case OP_LOADBI_S: - case OP_LOADBI_ENT: - case OP_LOADBI_FLD: - case OP_LOADBI_FN: - case OP_LOADBI_I: - case OP_LOADBI_P: + case OP_LOADBI_F_v6p: + case OP_LOADBI_S_v6p: + case OP_LOADBI_ENT_v6p: + case OP_LOADBI_FLD_v6p: + case OP_LOADBI_FN_v6p: + case OP_LOADBI_I_v6p: + case OP_LOADBI_P_v6p: pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); @@ -916,7 +916,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; OPC(int) = ptr->integer_var; break; - case OP_LOADBI_V: + case OP_LOADBI_V_v6p: pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); @@ -924,7 +924,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; VectorCopy (&ptr->vector_var, &OPC(float)); break; - case OP_LOADBI_Q: + case OP_LOADBI_Q_v6p: pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); @@ -932,7 +932,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; QuatCopy (&ptr->quat_var, &OPC(float)); break; - case OP_LOADBI_D: + case OP_LOADBI_D_v6p: pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); @@ -941,23 +941,23 @@ pr_exec_quakec (progs_t *pr, int exitdepth) OPC(double) = *(double *) ptr; break; - case OP_LEA: + case OP_LEA_v6p: pointer = OPA(int) + OPB(int); OPC(int) = pointer; break; - case OP_LEAI: + case OP_LEAI_v6p: pointer = OPA(int) + (short) st->b; OPC(int) = pointer; break; - case OP_STOREB_F: - case OP_STOREB_S: - case OP_STOREB_ENT: - case OP_STOREB_FLD: - case OP_STOREB_FN: - case OP_STOREB_I: - case OP_STOREB_P: + case OP_STOREB_F_v6p: + case OP_STOREB_S_v6p: + case OP_STOREB_ENT_v6p: + case OP_STOREB_FLD_v6p: + case OP_STOREB_FN_v6p: + case OP_STOREB_I_v6p: + case OP_STOREB_P_v6p: pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); @@ -965,7 +965,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; ptr->integer_var = OPA(int); break; - case OP_STOREB_V: + case OP_STOREB_V_v6p: pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); @@ -973,7 +973,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; VectorCopy (&OPA(float), &ptr->vector_var); break; - case OP_STOREB_Q: + case OP_STOREB_Q_v6p: pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); @@ -981,7 +981,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; QuatCopy (&OPA(float), &ptr->quat_var); break; - case OP_STOREB_D: + case OP_STOREB_D_v6p: pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); @@ -990,13 +990,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *(double *) ptr = OPA(double); break; - case OP_STOREBI_F: - case OP_STOREBI_S: - case OP_STOREBI_ENT: - case OP_STOREBI_FLD: - case OP_STOREBI_FN: - case OP_STOREBI_I: - case OP_STOREBI_P: + case OP_STOREBI_F_v6p: + case OP_STOREBI_S_v6p: + case OP_STOREBI_ENT_v6p: + case OP_STOREBI_FLD_v6p: + case OP_STOREBI_FN_v6p: + case OP_STOREBI_I_v6p: + case OP_STOREBI_P_v6p: pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); @@ -1004,7 +1004,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; ptr->integer_var = OPA(int); break; - case OP_STOREBI_V: + case OP_STOREBI_V_v6p: pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); @@ -1012,7 +1012,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; VectorCopy (&OPA(float), &ptr->vector_var); break; - case OP_STOREBI_Q: + case OP_STOREBI_Q_v6p: pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); @@ -1020,7 +1020,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; QuatCopy (&OPA(float), &ptr->quat_var); break; - case OP_STOREBI_D: + case OP_STOREBI_D_v6p: pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quat); @@ -1029,13 +1029,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *(double *) ptr = OPA(double); break; - case OP_PUSH_F: - case OP_PUSH_FLD: - case OP_PUSH_ENT: - case OP_PUSH_S: - case OP_PUSH_FN: - case OP_PUSH_I: - case OP_PUSH_P: + case OP_PUSH_F_v6p: + case OP_PUSH_FLD_v6p: + case OP_PUSH_ENT_v6p: + case OP_PUSH_S_v6p: + case OP_PUSH_FN_v6p: + case OP_PUSH_I_v6p: + case OP_PUSH_P_v6p: { pointer_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; @@ -1046,7 +1046,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack; } break; - case OP_PUSH_V: + case OP_PUSH_V_v6p: { pointer_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; @@ -1057,7 +1057,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack; } break; - case OP_PUSH_Q: + case OP_PUSH_Q_v6p: { pointer_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; @@ -1069,13 +1069,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) } break; - case OP_PUSHB_F: - case OP_PUSHB_S: - case OP_PUSHB_ENT: - case OP_PUSHB_FLD: - case OP_PUSHB_FN: - case OP_PUSHB_I: - case OP_PUSHB_P: + case OP_PUSHB_F_v6p: + case OP_PUSHB_S_v6p: + case OP_PUSHB_ENT_v6p: + case OP_PUSHB_FLD_v6p: + case OP_PUSHB_FN_v6p: + case OP_PUSHB_I_v6p: + case OP_PUSHB_P_v6p: { pointer_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; @@ -1092,7 +1092,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack; } break; - case OP_PUSHB_V: + case OP_PUSHB_V_v6p: { pointer_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; @@ -1109,7 +1109,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack; } break; - case OP_PUSHB_Q: + case OP_PUSHB_Q_v6p: { pointer_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; @@ -1127,13 +1127,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) } break; - case OP_PUSHBI_F: - case OP_PUSHBI_S: - case OP_PUSHBI_ENT: - case OP_PUSHBI_FLD: - case OP_PUSHBI_FN: - case OP_PUSHBI_I: - case OP_PUSHBI_P: + case OP_PUSHBI_F_v6p: + case OP_PUSHBI_S_v6p: + case OP_PUSHBI_ENT_v6p: + case OP_PUSHBI_FLD_v6p: + case OP_PUSHBI_FN_v6p: + case OP_PUSHBI_I_v6p: + case OP_PUSHBI_P_v6p: { pointer_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; @@ -1150,7 +1150,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack; } break; - case OP_PUSHBI_V: + case OP_PUSHBI_V_v6p: { pointer_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; @@ -1167,7 +1167,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack; } break; - case OP_PUSHBI_Q: + case OP_PUSHBI_Q_v6p: { pointer_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; @@ -1185,13 +1185,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) } break; - case OP_POP_F: - case OP_POP_FLD: - case OP_POP_ENT: - case OP_POP_S: - case OP_POP_FN: - case OP_POP_I: - case OP_POP_P: + case OP_POP_F_v6p: + case OP_POP_FLD_v6p: + case OP_POP_ENT_v6p: + case OP_POP_S_v6p: + case OP_POP_FN_v6p: + case OP_POP_I_v6p: + case OP_POP_P_v6p: { pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; @@ -1202,7 +1202,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack + 1; } break; - case OP_POP_V: + case OP_POP_V_v6p: { pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; @@ -1213,7 +1213,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack + 3; } break; - case OP_POP_Q: + case OP_POP_Q_v6p: { pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; @@ -1225,13 +1225,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) } break; - case OP_POPB_F: - case OP_POPB_S: - case OP_POPB_ENT: - case OP_POPB_FLD: - case OP_POPB_FN: - case OP_POPB_I: - case OP_POPB_P: + case OP_POPB_F_v6p: + case OP_POPB_S_v6p: + case OP_POPB_ENT_v6p: + case OP_POPB_FLD_v6p: + case OP_POPB_FN_v6p: + case OP_POPB_I_v6p: + case OP_POPB_P_v6p: { pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; @@ -1248,7 +1248,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack + 1; } break; - case OP_POPB_V: + case OP_POPB_V_v6p: { pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; @@ -1265,7 +1265,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack + 3; } break; - case OP_POPB_Q: + case OP_POPB_Q_v6p: { pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; @@ -1283,13 +1283,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) } break; - case OP_POPBI_F: - case OP_POPBI_S: - case OP_POPBI_ENT: - case OP_POPBI_FLD: - case OP_POPBI_FN: - case OP_POPBI_I: - case OP_POPBI_P: + case OP_POPBI_F_v6p: + case OP_POPBI_S_v6p: + case OP_POPBI_ENT_v6p: + case OP_POPBI_FLD_v6p: + case OP_POPBI_FN_v6p: + case OP_POPBI_I_v6p: + case OP_POPBI_P_v6p: { pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; @@ -1306,7 +1306,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack + 1; } break; - case OP_POPBI_V: + case OP_POPBI_V_v6p: { pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; @@ -1323,7 +1323,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) *pr->globals.stack = stack + 3; } break; - case OP_POPBI_Q: + case OP_POPBI_Q_v6p: { pointer_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; @@ -1342,47 +1342,47 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; // ================== - case OP_IFNOT: + case OP_IFNOT_v6p: if (!OPA(int)) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IF: + case OP_IF_v6p: if (OPA(int)) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IFBE: + case OP_IFBE_v6p: if (OPA(int) <= 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IFB: + case OP_IFB_v6p: if (OPA(int) < 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IFAE: + case OP_IFAE_v6p: if (OPA(int) >= 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IFA: + case OP_IFA_v6p: if (OPA(int) > 0) { pr->pr_xstatement += (short)st->b - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_GOTO: + case OP_GOTO_v6p: pr->pr_xstatement += (short)st->a - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; break; - case OP_JUMP: + case OP_JUMP_v6p: if (pr_boundscheck->int_val && (OPA(uint) >= pr->progs->numstatements)) { PR_RunError (pr, "Invalid jump destination"); @@ -1390,7 +1390,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr->pr_xstatement = OPA(uint) - 1; // offset the st++ st = pr->pr_statements + pr->pr_xstatement; break; - case OP_JUMPB: + case OP_JUMPB_v6p: pointer = st->a + OPB(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_integer); @@ -1405,40 +1405,40 @@ pr_exec_quakec (progs_t *pr, int exitdepth) st = pr->pr_statements + pr->pr_xstatement; break; - case OP_RCALL2: - case OP_RCALL3: - case OP_RCALL4: - case OP_RCALL5: - case OP_RCALL6: - case OP_RCALL7: - case OP_RCALL8: + case OP_RCALL2_v6p: + case OP_RCALL3_v6p: + case OP_RCALL4_v6p: + case OP_RCALL5_v6p: + case OP_RCALL6_v6p: + case OP_RCALL7_v6p: + case OP_RCALL8_v6p: pr->pr_params[1] = op_c; goto op_rcall; - case OP_RCALL1: + case OP_RCALL1_v6p: pr->pr_params[1] = pr->pr_real_params[1]; op_rcall: pr->pr_params[0] = op_b; - pr->pr_argc = st->op - OP_RCALL1 + 1; + pr->pr_argc = st->op - OP_RCALL1_v6p + 1; goto op_call; - case OP_CALL0: - case OP_CALL1: - case OP_CALL2: - case OP_CALL3: - case OP_CALL4: - case OP_CALL5: - case OP_CALL6: - case OP_CALL7: - case OP_CALL8: + case OP_CALL0_v6p: + case OP_CALL1_v6p: + case OP_CALL2_v6p: + case OP_CALL3_v6p: + case OP_CALL4_v6p: + case OP_CALL5_v6p: + case OP_CALL6_v6p: + case OP_CALL7_v6p: + case OP_CALL8_v6p: PR_RESET_PARAMS (pr); - pr->pr_argc = st->op - OP_CALL0; + pr->pr_argc = st->op - OP_CALL0_v6p; op_call: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; PR_CallFunction (pr, OPA(uint)); st = pr->pr_statements + pr->pr_xstatement; break; - case OP_DONE: - case OP_RETURN: + case OP_DONE_v6p: + case OP_RETURN_v6p: if (!st->a) memset (&R_INT (pr), 0, pr->pr_param_size * sizeof (*op_a)); @@ -1446,7 +1446,7 @@ op_call: memcpy (&R_INT (pr), op_a, pr->pr_param_size * sizeof (*op_a)); // fallthrough - case OP_RETURN_V: + case OP_RETURN_V_v6p: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; PR_LeaveFunction (pr, pr->pr_depth == exitdepth); @@ -1458,7 +1458,7 @@ op_call: goto exit_program; } break; - case OP_STATE: + case OP_STATE_v6p: { int self = *pr->globals.self; int nextthink = pr->fields.nextthink + self; @@ -1470,7 +1470,7 @@ op_call: pr->pr_edict_area[think].func_var = OPB(uint); } break; - case OP_STATE_F: + case OP_STATE_F_v6p: { int self = *pr->globals.self; int nextthink = pr->fields.nextthink + self; @@ -1482,19 +1482,19 @@ op_call: pr->pr_edict_area[think].func_var = OPB(uint); } break; - case OP_ADD_I: + case OP_ADD_I_v6p: OPC(int) = OPA(int) + OPB(int); break; - case OP_SUB_I: + case OP_SUB_I_v6p: OPC(int) = OPA(int) - OPB(int); break; - case OP_MUL_I: + case OP_MUL_I_v6p: OPC(int) = OPA(int) * OPB(int); break; - case OP_DIV_I: + case OP_DIV_I_v6p: OPC(int) = OPA(int) / OPB(int); break; - case OP_MOD_I: + case OP_MOD_I_v6p: { // implement true modulo for integers: // 5 mod 3 = 2 @@ -1512,10 +1512,10 @@ op_call: OPC(int) = c + (mask & b); } break; - case OP_REM_I: + case OP_REM_I_v6p: OPC(int) = OPA(int) % OPB(int); break; - case OP_MOD_D: + case OP_MOD_D_v6p: { double a = OPA(double); double b = OPB(double); @@ -1523,98 +1523,98 @@ op_call: OPC(double) = a - b * floor (a / b); } break; - case OP_REM_D: + case OP_REM_D_v6p: { double a = OPA(double); double b = OPB(double); OPC(double) = a - b * trunc (a / b); } break; - case OP_MOD_F: + case OP_MOD_F_v6p: { float a = OPA(float); float b = OPB(float); OPC(float) = a - b * floorf (a / b); } break; - case OP_REM_F: + case OP_REM_F_v6p: { float a = OPA(float); float b = OPB(float); OPC(float) = a - b * truncf (a / b); } break; - case OP_CONV_IF: + case OP_CONV_IF_v6p: OPC(float) = OPA(int); break; - case OP_CONV_FI: + case OP_CONV_FI_v6p: OPC(int) = OPA(float); break; - case OP_BITAND_I: + case OP_BITAND_I_v6p: OPC(int) = OPA(int) & OPB(int); break; - case OP_BITOR_I: + case OP_BITOR_I_v6p: OPC(int) = OPA(int) | OPB(int); break; - case OP_BITXOR_I: + case OP_BITXOR_I_v6p: OPC(int) = OPA(int) ^ OPB(int); break; - case OP_BITNOT_I: + case OP_BITNOT_I_v6p: OPC(int) = ~OPA(int); break; - case OP_GE_I: - case OP_GE_P: + case OP_GE_I_v6p: + case OP_GE_P_v6p: OPC(int) = OPA(int) >= OPB(int); break; - case OP_GE_U: + case OP_GE_U_v6p: OPC(int) = OPA(uint) >= OPB(uint); break; - case OP_LE_I: - case OP_LE_P: + case OP_LE_I_v6p: + case OP_LE_P_v6p: OPC(int) = OPA(int) <= OPB(int); break; - case OP_LE_U: + case OP_LE_U_v6p: OPC(int) = OPA(uint) <= OPB(uint); break; - case OP_GT_I: - case OP_GT_P: + case OP_GT_I_v6p: + case OP_GT_P_v6p: OPC(int) = OPA(int) > OPB(int); break; - case OP_GT_U: + case OP_GT_U_v6p: OPC(int) = OPA(uint) > OPB(uint); break; - case OP_LT_I: - case OP_LT_P: + case OP_LT_I_v6p: + case OP_LT_P_v6p: OPC(int) = OPA(int) < OPB(int); break; - case OP_LT_U: + case OP_LT_U_v6p: OPC(int) = OPA(uint) < OPB(uint); break; - case OP_AND_I: + case OP_AND_I_v6p: OPC(int) = OPA(int) && OPB(int); break; - case OP_OR_I: + case OP_OR_I_v6p: OPC(int) = OPA(int) || OPB(int); break; - case OP_NOT_I: - case OP_NOT_P: + case OP_NOT_I_v6p: + case OP_NOT_P_v6p: OPC(int) = !OPA(int); break; - case OP_EQ_I: - case OP_EQ_P: + case OP_EQ_I_v6p: + case OP_EQ_P_v6p: OPC(int) = OPA(int) == OPB(int); break; - case OP_NE_I: - case OP_NE_P: + case OP_NE_I_v6p: + case OP_NE_P_v6p: OPC(int) = OPA(int) != OPB(int); break; - case OP_MOVEI: + case OP_MOVEI_v6p: memmove (op_c, op_a, st->b * 4); break; - case OP_MOVEP: + case OP_MOVEP_v6p: if (pr_boundscheck->int_val) { PR_BoundsCheckSize (pr, OPC(int), OPB(uint)); PR_BoundsCheckSize (pr, OPA(int), OPB(uint)); @@ -1623,7 +1623,7 @@ op_call: pr->pr_globals + OPA(int), OPB(uint) * 4); break; - case OP_MOVEPI: + case OP_MOVEPI_v6p: if (pr_boundscheck->int_val) { PR_BoundsCheckSize (pr, OPC(int), st->b); PR_BoundsCheckSize (pr, OPA(int), st->b); @@ -1632,61 +1632,61 @@ op_call: pr->pr_globals + OPA(int), st->b * 4); break; - case OP_MEMSETI: + case OP_MEMSETI_v6p: pr_memset (op_c, OPA(int), st->b); break; - case OP_MEMSETP: + case OP_MEMSETP_v6p: if (pr_boundscheck->int_val) { PR_BoundsCheckSize (pr, OPC(pointer), OPB(int)); } pr_memset (pr->pr_globals + OPC(pointer), OPA(int), OPB(int)); break; - case OP_MEMSETPI: + case OP_MEMSETPI_v6p: if (pr_boundscheck->int_val) { PR_BoundsCheckSize (pr, OPC(pointer), st->b); } pr_memset (pr->pr_globals + OPC(pointer), OPA(int), st->b); break; - case OP_GE_D: + case OP_GE_D_v6p: OPC(float) = OPA(double) >= OPB(double); break; - case OP_LE_D: + case OP_LE_D_v6p: OPC(float) = OPA(double) <= OPB(double); break; - case OP_GT_D: + case OP_GT_D_v6p: OPC(float) = OPA(double) > OPB(double); break; - case OP_LT_D: + case OP_LT_D_v6p: OPC(float) = OPA(double) < OPB(double); break; - case OP_NOT_D: + case OP_NOT_D_v6p: OPC(int) = (op_a[0].integer_var || (op_a[1].integer_var & ~0x80000000u)); break; - case OP_EQ_D: + case OP_EQ_D_v6p: OPC(int) = OPA(double) == OPB(double); break; - case OP_NE_D: + case OP_NE_D_v6p: OPC(int) = OPA(double) != OPB(double); break; - case OP_CONV_ID: + case OP_CONV_ID_v6p: OPC(double) = OPA(int); break; - case OP_CONV_DI: + case OP_CONV_DI_v6p: OPC(int) = OPA(double); break; - case OP_CONV_FD: + case OP_CONV_FD_v6p: OPC(double) = OPA(float); break; - case OP_CONV_DF: + case OP_CONV_DF_v6p: OPC(float) = OPA(double); break; // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized /* - case OP_BOUNDCHECK: + case OP_BOUNDCHECK_v6p: if (OPA(int) < 0 || OPA(int) >= st->b) { PR_RunError (pr, "Progs boundcheck failed at line number " "%d, value is < 0 or >= %d", st->b, st->c); diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 955cc0796..17d640575 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -95,1431 +95,1431 @@ VISIBLE const char * const pr_type_name[ev_type_count] = { // c operand c // x place holder for P (padding) // 0-7 parameter index (for P) -VISIBLE const opcode_t pr_opcodes[] = { - // OP_DONE is actually the same as OP_RETURN, the types are bogus - [OP_DONE] = {"", "done", +VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { + // OP_DONE_v6p is actually the same as OP_RETURN_v6p, the types are bogus + [OP_DONE_v6p] = {"", "done", ev_entity, ev_field, ev_void, PROG_ID_VERSION, "%Va", }, - [OP_MUL_D] = {"*", "mul.d", + [OP_MUL_D_v6p] = {"*", "mul.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_MUL_F] = {"*", "mul.f", + [OP_MUL_F_v6p] = {"*", "mul.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_MUL_V] = {"*", "mul.v", + [OP_MUL_V_v6p] = {"*", "mul.v", ev_vector, ev_vector, ev_float, PROG_ID_VERSION, }, - [OP_MUL_FV] = {"*", "mul.fv", + [OP_MUL_FV_v6p] = {"*", "mul.fv", ev_float, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_VF] = {"*", "mul.vf", + [OP_MUL_VF_v6p] = {"*", "mul.vf", ev_vector, ev_float, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_DV] = {"*", "mul.dv", + [OP_MUL_DV_v6p] = {"*", "mul.dv", ev_double, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_VD] = {"*", "mul.vd", + [OP_MUL_VD_v6p] = {"*", "mul.vd", ev_vector, ev_double, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_Q] = {"*", "mul.q", + [OP_MUL_Q_v6p] = {"*", "mul.q", ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - [OP_MUL_FQ] = {"*", "mul.fq", + [OP_MUL_FQ_v6p] = {"*", "mul.fq", ev_float, ev_quat, ev_quat, PROG_VERSION, }, - [OP_MUL_QF] = {"*", "mul.qf", + [OP_MUL_QF_v6p] = {"*", "mul.qf", ev_quat, ev_float, ev_quat, PROG_VERSION, }, - [OP_MUL_DQ] = {"*", "mul.dq", + [OP_MUL_DQ_v6p] = {"*", "mul.dq", ev_double, ev_quat, ev_quat, PROG_VERSION, }, - [OP_MUL_QD] = {"*", "mul.qd", + [OP_MUL_QD_v6p] = {"*", "mul.qd", ev_quat, ev_double, ev_quat, PROG_VERSION, }, - [OP_MUL_QV] = {"*", "mul.qv", + [OP_MUL_QV_v6p] = {"*", "mul.qv", ev_quat, ev_vector, ev_vector, PROG_VERSION, }, - [OP_CONJ_Q] = {"~", "conj.q", + [OP_CONJ_Q_v6p] = {"~", "conj.q", ev_quat, ev_invalid, ev_quat, PROG_VERSION, "%Ga, %gc", }, - [OP_DIV_F] = {"/", "div.f", + [OP_DIV_F_v6p] = {"/", "div.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_DIV_D] = {"/", "div.d", + [OP_DIV_D_v6p] = {"/", "div.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_REM_D] = {"%", "rem.d", + [OP_REM_D_v6p] = {"%", "rem.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_MOD_D] = {"%%", "mod.d", + [OP_MOD_D_v6p] = {"%%", "mod.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_ADD_D] = {"+", "add.d", + [OP_ADD_D_v6p] = {"+", "add.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_ADD_F] = {"+", "add.f", + [OP_ADD_F_v6p] = {"+", "add.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_ADD_V] = {"+", "add.v", + [OP_ADD_V_v6p] = {"+", "add.v", ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_ADD_Q] = {"+", "add.q", + [OP_ADD_Q_v6p] = {"+", "add.q", ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - [OP_ADD_S] = {"+", "add.s", + [OP_ADD_S_v6p] = {"+", "add.s", ev_string, ev_string, ev_string, PROG_VERSION, }, - [OP_SUB_D] = {"-", "sub.d", + [OP_SUB_D_v6p] = {"-", "sub.d", ev_double, ev_double, ev_double, PROG_VERSION, }, - [OP_SUB_F] = {"-", "sub.f", + [OP_SUB_F_v6p] = {"-", "sub.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_SUB_V] = {"-", "sub.v", + [OP_SUB_V_v6p] = {"-", "sub.v", ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_SUB_Q] = {"-", "sub.q", + [OP_SUB_Q_v6p] = {"-", "sub.q", ev_quat, ev_quat, ev_quat, PROG_VERSION, }, - [OP_EQ_D] = {"==", "eq.d", + [OP_EQ_D_v6p] = {"==", "eq.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_EQ_F] = {"==", "eq.f", + [OP_EQ_F_v6p] = {"==", "eq.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_EQ_V] = {"==", "eq.v", + [OP_EQ_V_v6p] = {"==", "eq.v", ev_vector, ev_vector, ev_integer, PROG_ID_VERSION, }, - [OP_EQ_Q] = {"==", "eq.q", + [OP_EQ_Q_v6p] = {"==", "eq.q", ev_quat, ev_quat, ev_integer, PROG_VERSION, }, - [OP_EQ_S] = {"==", "eq.s", + [OP_EQ_S_v6p] = {"==", "eq.s", ev_string, ev_string, ev_integer, PROG_ID_VERSION, }, - [OP_EQ_E] = {"==", "eq.e", + [OP_EQ_E_v6p] = {"==", "eq.e", ev_entity, ev_entity, ev_integer, PROG_ID_VERSION, }, - [OP_EQ_FN] = {"==", "eq.fn", + [OP_EQ_FN_v6p] = {"==", "eq.fn", ev_func, ev_func, ev_integer, PROG_ID_VERSION, }, - [OP_NE_D] = {"!=", "ne.d", + [OP_NE_D_v6p] = {"!=", "ne.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_NE_F] = {"!=", "ne.f", + [OP_NE_F_v6p] = {"!=", "ne.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_NE_V] = {"!=", "ne.v", + [OP_NE_V_v6p] = {"!=", "ne.v", ev_vector, ev_vector, ev_integer, PROG_ID_VERSION, }, - [OP_NE_Q] = {"!=", "ne.q", + [OP_NE_Q_v6p] = {"!=", "ne.q", ev_quat, ev_quat, ev_integer, PROG_VERSION, }, - [OP_NE_S] = {"!=", "ne.s", + [OP_NE_S_v6p] = {"!=", "ne.s", ev_string, ev_string, ev_integer, PROG_ID_VERSION, }, - [OP_NE_E] = {"!=", "ne.e", + [OP_NE_E_v6p] = {"!=", "ne.e", ev_entity, ev_entity, ev_integer, PROG_ID_VERSION, }, - [OP_NE_FN] = {"!=", "ne.fn", + [OP_NE_FN_v6p] = {"!=", "ne.fn", ev_func, ev_func, ev_integer, PROG_ID_VERSION, }, - [OP_LE_D] = {"<=", "le.d", + [OP_LE_D_v6p] = {"<=", "le.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_LE_F] = {"<=", "le.f", + [OP_LE_F_v6p] = {"<=", "le.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_GE_D] = {">=", "ge.d", + [OP_GE_D_v6p] = {">=", "ge.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_GE_F] = {">=", "ge.f", + [OP_GE_F_v6p] = {">=", "ge.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_LE_S] = {"<=", "le.s", + [OP_LE_S_v6p] = {"<=", "le.s", ev_string, ev_string, ev_integer, PROG_VERSION, }, - [OP_GE_S] = {">=", "ge.s", + [OP_GE_S_v6p] = {">=", "ge.s", ev_string, ev_string, ev_integer, PROG_VERSION, }, - [OP_LT_D] = {"<", "lt.d", + [OP_LT_D_v6p] = {"<", "lt.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_LT_F] = {"<", "lt.f", + [OP_LT_F_v6p] = {"<", "lt.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_GT_D] = {">", "gt.d", + [OP_GT_D_v6p] = {">", "gt.d", ev_double, ev_double, ev_integer, PROG_VERSION, }, - [OP_GT_F] = {">", "gt.f", + [OP_GT_F_v6p] = {">", "gt.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_LT_S] = {"<", "lt.s", + [OP_LT_S_v6p] = {"<", "lt.s", ev_string, ev_string, ev_integer, PROG_VERSION, }, - [OP_GT_S] = {">", "gt.s", + [OP_GT_S_v6p] = {">", "gt.s", ev_string, ev_string, ev_integer, PROG_VERSION, }, - [OP_LOAD_F] = {".", "load.f", + [OP_LOAD_F_v6p] = {".", "load.f", ev_entity, ev_field, ev_float, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible? }, - [OP_LOAD_D] = {".", "load.d", + [OP_LOAD_D_v6p] = {".", "load.d", ev_entity, ev_field, ev_double, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_V] = {".", "load.v", + [OP_LOAD_V_v6p] = {".", "load.v", ev_entity, ev_field, ev_vector, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_Q] = {".", "load.q", + [OP_LOAD_Q_v6p] = {".", "load.q", ev_entity, ev_field, ev_quat, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_S] = {".", "load.s", + [OP_LOAD_S_v6p] = {".", "load.s", ev_entity, ev_field, ev_string, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_ENT] = {".", "load.ent", + [OP_LOAD_ENT_v6p] = {".", "load.ent", ev_entity, ev_field, ev_entity, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_FLD] = {".", "load.fld", + [OP_LOAD_FLD_v6p] = {".", "load.fld", ev_entity, ev_field, ev_field, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_FN] = {".", "load.fn", + [OP_LOAD_FN_v6p] = {".", "load.fn", ev_entity, ev_field, ev_func, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_I] = {".", "load.i", + [OP_LOAD_I_v6p] = {".", "load.i", ev_entity, ev_field, ev_integer, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_P] = {".", "load.p", + [OP_LOAD_P_v6p] = {".", "load.p", ev_entity, ev_field, ev_pointer, PROG_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOADB_D] = {".", "loadb.d", + [OP_LOADB_D_v6p] = {".", "loadb.d", ev_pointer, ev_integer, ev_double, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_F] = {".", "loadb.f", + [OP_LOADB_F_v6p] = {".", "loadb.f", ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_V] = {".", "loadb.v", + [OP_LOADB_V_v6p] = {".", "loadb.v", ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_Q] = {".", "loadb.q", + [OP_LOADB_Q_v6p] = {".", "loadb.q", ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_S] = {".", "loadb.s", + [OP_LOADB_S_v6p] = {".", "loadb.s", ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_ENT] = {".", "loadb.ent", + [OP_LOADB_ENT_v6p] = {".", "loadb.ent", ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_FLD] = {".", "loadb.fld", + [OP_LOADB_FLD_v6p] = {".", "loadb.fld", ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_FN] = {".", "loadb.fn", + [OP_LOADB_FN_v6p] = {".", "loadb.fn", ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_I] = {".", "loadb.i", + [OP_LOADB_I_v6p] = {".", "loadb.i", ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_P] = {".", "loadb.p", + [OP_LOADB_P_v6p] = {".", "loadb.p", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADBI_D] = {".", "loadbi.d", + [OP_LOADBI_D_v6p] = {".", "loadbi.d", ev_pointer, ev_short, ev_double, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_F] = {".", "loadbi.f", + [OP_LOADBI_F_v6p] = {".", "loadbi.f", ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_V] = {".", "loadbi.v", + [OP_LOADBI_V_v6p] = {".", "loadbi.v", ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_Q] = {".", "loadbi.q", + [OP_LOADBI_Q_v6p] = {".", "loadbi.q", ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_S] = {".", "loadbi.s", + [OP_LOADBI_S_v6p] = {".", "loadbi.s", ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_ENT] = {".", "loadbi.ent", + [OP_LOADBI_ENT_v6p] = {".", "loadbi.ent", ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_FLD] = {".", "loadbi.fld", + [OP_LOADBI_FLD_v6p] = {".", "loadbi.fld", ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_FN] = {".", "loadbi.fn", + [OP_LOADBI_FN_v6p] = {".", "loadbi.fn", ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_I] = {".", "loadbi.i", + [OP_LOADBI_I_v6p] = {".", "loadbi.i", ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_P] = {".", "loadbi.p", + [OP_LOADBI_P_v6p] = {".", "loadbi.p", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb), %gc", }, - [OP_ADDRESS] = {"&", "address", + [OP_ADDRESS_v6p] = {"&", "address", ev_entity, ev_field, ev_pointer, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_ADDRESS_VOID] = {"&", "address", + [OP_ADDRESS_VOID_v6p] = {"&", "address", ev_void, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_D] = {"&", "address.d", + [OP_ADDRESS_D_v6p] = {"&", "address.d", ev_double, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_F] = {"&", "address.f", + [OP_ADDRESS_F_v6p] = {"&", "address.f", ev_float, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_V] = {"&", "address.v", + [OP_ADDRESS_V_v6p] = {"&", "address.v", ev_vector, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_Q] = {"&", "address.q", + [OP_ADDRESS_Q_v6p] = {"&", "address.q", ev_quat, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_S] = {"&", "address.s", + [OP_ADDRESS_S_v6p] = {"&", "address.s", ev_string, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_ENT] = {"&", "address.ent", + [OP_ADDRESS_ENT_v6p] = {"&", "address.ent", ev_entity, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_FLD] = {"&", "address.fld", + [OP_ADDRESS_FLD_v6p] = {"&", "address.fld", ev_field, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_FN] = {"&", "address.fn", + [OP_ADDRESS_FN_v6p] = {"&", "address.fn", ev_func, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_I] = {"&", "address.i", + [OP_ADDRESS_I_v6p] = {"&", "address.i", ev_integer, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_P] = {"&", "address.p", + [OP_ADDRESS_P_v6p] = {"&", "address.p", ev_pointer, ev_invalid, ev_pointer, PROG_VERSION, "%Ga, %gc", }, - [OP_LEA] = {"&", "lea", + [OP_LEA_v6p] = {"&", "lea", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "(%Ga + %Gb), %gc", }, - [OP_LEAI] = {"&", "leai", + [OP_LEAI_v6p] = {"&", "leai", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "(%Ga + %sb), %gc", }, - [OP_CONV_IF] = {"", "conv.if", + [OP_CONV_IF_v6p] = {"", "conv.if", ev_integer, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_FI] = {"", "conv.fi", + [OP_CONV_FI_v6p] = {"", "conv.fi", ev_float, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_ID] = {"", "conv.id", + [OP_CONV_ID_v6p] = {"", "conv.id", ev_integer, ev_invalid, ev_double, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_DI] = {"", "conv.di", + [OP_CONV_DI_v6p] = {"", "conv.di", ev_double, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_FD] = {"", "conv.fd", + [OP_CONV_FD_v6p] = {"", "conv.fd", ev_float, ev_invalid, ev_double, PROG_VERSION, "%Ga, %gc", }, - [OP_CONV_DF] = {"", "conv.df", + [OP_CONV_DF_v6p] = {"", "conv.df", ev_double, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - [OP_STORE_D] = {"=", "store.d", + [OP_STORE_D_v6p] = {"=", "store.d", ev_double, ev_double, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - [OP_STORE_F] = {"=", "store.f", + [OP_STORE_F_v6p] = {"=", "store.f", ev_float, ev_float, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_V] = {"=", "store.v", + [OP_STORE_V_v6p] = {"=", "store.v", ev_vector, ev_vector, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_Q] = {"=", "store.q", + [OP_STORE_Q_v6p] = {"=", "store.q", ev_quat, ev_quat, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - [OP_STORE_S] = {"=", "store.s", + [OP_STORE_S_v6p] = {"=", "store.s", ev_string, ev_string, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_ENT] = {"=", "store.ent", + [OP_STORE_ENT_v6p] = {"=", "store.ent", ev_entity, ev_entity, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_FLD] = {"=", "store.fld", + [OP_STORE_FLD_v6p] = {"=", "store.fld", ev_field, ev_field, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_FN] = {"=", "store.fn", + [OP_STORE_FN_v6p] = {"=", "store.fn", ev_func, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_I] = {"=", "store.i", + [OP_STORE_I_v6p] = {"=", "store.i", ev_integer, ev_integer, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - [OP_STORE_P] = {"=", "store.p", + [OP_STORE_P_v6p] = {"=", "store.p", ev_pointer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, %gb", }, - [OP_STOREP_D] = {".=", "storep.d", + [OP_STOREP_D_v6p] = {".=", "storep.d", ev_double, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_F] = {".=", "storep.f", + [OP_STOREP_F_v6p] = {".=", "storep.f", ev_float, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_V] = {".=", "storep.v", + [OP_STOREP_V_v6p] = {".=", "storep.v", ev_vector, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_Q] = {".=", "storep.q", + [OP_STOREP_Q_v6p] = {".=", "storep.q", ev_quat, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_S] = {".=", "storep.s", + [OP_STOREP_S_v6p] = {".=", "storep.s", ev_string, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_ENT] = {".=", "storep.ent", + [OP_STOREP_ENT_v6p] = {".=", "storep.ent", ev_entity, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_FLD] = {".=", "storep.fld", + [OP_STOREP_FLD_v6p] = {".=", "storep.fld", ev_field, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_FN] = {".=", "storep.fn", + [OP_STOREP_FN_v6p] = {".=", "storep.fn", ev_func, ev_pointer, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_I] = {".=", "storep.i", + [OP_STOREP_I_v6p] = {".=", "storep.i", ev_integer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_P] = {".=", "storep.p", + [OP_STOREP_P_v6p] = {".=", "storep.p", ev_pointer, ev_pointer, ev_invalid, PROG_VERSION, "%Ga, *%Gb", }, - [OP_STOREB_D] = {".=", "storeb.d", + [OP_STOREB_D_v6p] = {".=", "storeb.d", ev_double, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_F] = {".=", "storeb.f", + [OP_STOREB_F_v6p] = {".=", "storeb.f", ev_float, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_V] = {".=", "storeb.v", + [OP_STOREB_V_v6p] = {".=", "storeb.v", ev_vector, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_Q] = {".=", "storeb.q", + [OP_STOREB_Q_v6p] = {".=", "storeb.q", ev_quat, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_S] = {".=", "storeb.s", + [OP_STOREB_S_v6p] = {".=", "storeb.s", ev_string, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_ENT] = {".=", "storeb.ent", + [OP_STOREB_ENT_v6p] = {".=", "storeb.ent", ev_entity, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_FLD] = {".=", "storeb.fld", + [OP_STOREB_FLD_v6p] = {".=", "storeb.fld", ev_field, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_FN] = {".=", "storeb.fn", + [OP_STOREB_FN_v6p] = {".=", "storeb.fn", ev_func, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_I] = {".=", "storeb.i", + [OP_STOREB_I_v6p] = {".=", "storeb.i", ev_integer, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_P] = {".=", "storeb.p", + [OP_STOREB_P_v6p] = {".=", "storeb.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREBI_D] = {".=", "storebi.d", + [OP_STOREBI_D_v6p] = {".=", "storebi.d", ev_double, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_F] = {".=", "storebi.f", + [OP_STOREBI_F_v6p] = {".=", "storebi.f", ev_float, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_V] = {".=", "storebi.v", + [OP_STOREBI_V_v6p] = {".=", "storebi.v", ev_vector, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_Q] = {".=", "storebi.q", + [OP_STOREBI_Q_v6p] = {".=", "storebi.q", ev_quat, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_S] = {".=", "storebi.s", + [OP_STOREBI_S_v6p] = {".=", "storebi.s", ev_string, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_ENT] = {".=", "storebi.ent", + [OP_STOREBI_ENT_v6p] = {".=", "storebi.ent", ev_entity, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_FLD] = {".=", "storebi.fld", + [OP_STOREBI_FLD_v6p] = {".=", "storebi.fld", ev_field, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_FN] = {".=", "storebi.fn", + [OP_STOREBI_FN_v6p] = {".=", "storebi.fn", ev_func, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_I] = {".=", "storebi.i", + [OP_STOREBI_I_v6p] = {".=", "storebi.i", ev_integer, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_P] = {".=", "storebi.p", + [OP_STOREBI_P_v6p] = {".=", "storebi.p", ev_pointer, ev_pointer, ev_short, PROG_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_RETURN] = {"", "return", + [OP_RETURN_v6p] = {"", "return", ev_void, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Ra", }, - [OP_RETURN_V] = {"", "return", + [OP_RETURN_V_v6p] = {"", "return", ev_invalid, ev_invalid, ev_invalid, PROG_VERSION, "", }, - [OP_NOT_D] = {"!", "not.d", + [OP_NOT_D_v6p] = {"!", "not.d", ev_double, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_NOT_F] = {"!", "not.f", + [OP_NOT_F_v6p] = {"!", "not.f", ev_float, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_V] = {"!", "not.v", + [OP_NOT_V_v6p] = {"!", "not.v", ev_vector, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_Q] = {"!", "not.q", + [OP_NOT_Q_v6p] = {"!", "not.q", ev_quat, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_NOT_S] = {"!", "not.s", + [OP_NOT_S_v6p] = {"!", "not.s", ev_string, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_ENT] = {"!", "not.ent", + [OP_NOT_ENT_v6p] = {"!", "not.ent", ev_entity, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_FN] = {"!", "not.fn", + [OP_NOT_FN_v6p] = {"!", "not.fn", ev_func, ev_invalid, ev_integer, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_P] = {"!", "not.p", + [OP_NOT_P_v6p] = {"!", "not.p", ev_pointer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_IF] = {"", "if", + [OP_IF_v6p] = {"", "if", ev_integer, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFNOT] = {"", "ifnot", + [OP_IFNOT_v6p] = {"", "ifnot", ev_integer, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFBE] = {"", "ifbe", + [OP_IFBE_v6p] = {"", "ifbe", ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFB] = {"", "ifb", + [OP_IFB_v6p] = {"", "ifb", ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFAE] = {"", "ifae", + [OP_IFAE_v6p] = {"", "ifae", ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFA] = {"", "ifa", + [OP_IFA_v6p] = {"", "ifa", ev_integer, ev_short, ev_invalid, PROG_VERSION, "%Ga branch %sb (%Ob)", }, // calls returns REG_RETURN - [OP_CALL0] = {"", "call0", + [OP_CALL0_v6p] = {"", "call0", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa ()", }, - [OP_CALL1] = {"", "call1", + [OP_CALL1_v6p] = {"", "call1", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x)", }, - [OP_CALL2] = {"", "call2", + [OP_CALL2_v6p] = {"", "call2", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x)", }, - [OP_CALL3] = {"", "call3", + [OP_CALL3_v6p] = {"", "call3", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x)", }, - [OP_CALL4] = {"", "call4", + [OP_CALL4_v6p] = {"", "call4", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x)", }, - [OP_CALL5] = {"", "call5", + [OP_CALL5_v6p] = {"", "call5", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x)", }, - [OP_CALL6] = {"", "call6", + [OP_CALL6_v6p] = {"", "call6", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x)", }, - [OP_CALL7] = {"", "call7", + [OP_CALL7_v6p] = {"", "call7", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - [OP_CALL8] = {"", "call8", + [OP_CALL8_v6p] = {"", "call8", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - [OP_RCALL0] = {"", 0, + [OP_RCALL0_v6p] = {"", 0, ev_invalid, ev_invalid, ev_invalid, ~0, // not a valid instruction 0, }, - [OP_RCALL1] = {"", "rcall1", + [OP_RCALL1_v6p] = {"", "rcall1", ev_func, ev_void, ev_invalid, PROG_VERSION, "%Fa (%P0b)", }, - [OP_RCALL2] = {"", "rcall2", + [OP_RCALL2_v6p] = {"", "rcall2", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c)", }, - [OP_RCALL3] = {"", "rcall3", + [OP_RCALL3_v6p] = {"", "rcall3", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x)", }, - [OP_RCALL4] = {"", "rcall4", + [OP_RCALL4_v6p] = {"", "rcall4", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x)", }, - [OP_RCALL5] = {"", "rcall5", + [OP_RCALL5_v6p] = {"", "rcall5", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", }, - [OP_RCALL6] = {"", "rcall6", + [OP_RCALL6_v6p] = {"", "rcall6", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", }, - [OP_RCALL7] = {"", "rcall7", + [OP_RCALL7_v6p] = {"", "rcall7", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - [OP_RCALL8] = {"", "rcall8", + [OP_RCALL8_v6p] = {"", "rcall8", ev_func, ev_void, ev_void, PROG_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - [OP_STATE] = {"", "state", + [OP_STATE_v6p] = {"", "state", ev_float, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %Gb", }, - [OP_STATE_F] = {"", "state.f", + [OP_STATE_F_v6p] = {"", "state.f", ev_float, ev_func, ev_float, PROG_VERSION, "%Ga, %Gb, %Gc", }, - [OP_GOTO] = {"", "goto", + [OP_GOTO_v6p] = {"", "goto", ev_short, ev_invalid, ev_invalid, PROG_ID_VERSION, "branch %sa (%Oa)", }, - [OP_JUMP] = {"", "jump", + [OP_JUMP_v6p] = {"", "jump", ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_JUMPB] = {"", "jumpb", + [OP_JUMPB_v6p] = {"", "jumpb", ev_void, ev_integer, ev_invalid, PROG_VERSION, "%Ga[%Gb]", }, - [OP_AND] = {"&&", "and.f", + [OP_AND_v6p] = {"&&", "and.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_OR] = {"||", "or.f", + [OP_OR_v6p] = {"||", "or.f", ev_float, ev_float, ev_integer, PROG_ID_VERSION, }, - [OP_SHL_F] = {"<<", "shl.f", + [OP_SHL_F_v6p] = {"<<", "shl.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_SHR_F] = {">>", "shr.f", + [OP_SHR_F_v6p] = {">>", "shr.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_SHL_I] = {"<<", "shl.i", + [OP_SHL_I_v6p] = {"<<", "shl.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_SHR_I] = {">>", "shr.i", + [OP_SHR_I_v6p] = {">>", "shr.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_SHR_U] = {">>", "shr.u", + [OP_SHR_U_v6p] = {">>", "shr.u", ev_uinteger, ev_integer, ev_uinteger, PROG_VERSION, }, - [OP_BITAND] = {"&", "bitand", + [OP_BITAND_v6p] = {"&", "bitand", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_BITOR] = {"|", "bitor", + [OP_BITOR_v6p] = {"|", "bitor", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_ADD_I] = {"+", "add.i", + [OP_ADD_I_v6p] = {"+", "add.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_SUB_I] = {"-", "sub.i", + [OP_SUB_I_v6p] = {"-", "sub.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_MUL_I] = {"*", "mul.i", + [OP_MUL_I_v6p] = {"*", "mul.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_DIV_I] = {"/", "div.i", + [OP_DIV_I_v6p] = {"/", "div.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_REM_I] = {"%", "rem.i", + [OP_REM_I_v6p] = {"%", "rem.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_MOD_I] = {"%%", "mod.i", + [OP_MOD_I_v6p] = {"%%", "mod.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_BITAND_I] = {"&", "bitand.i", + [OP_BITAND_I_v6p] = {"&", "bitand.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_BITOR_I] = {"|", "bitor.i", + [OP_BITOR_I_v6p] = {"|", "bitor.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_REM_F] = {"%", "rem.f", + [OP_REM_F_v6p] = {"%", "rem.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_MOD_F] = {"%%", "mod.f", + [OP_MOD_F_v6p] = {"%%", "mod.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_GE_I] = {">=", "ge.i", + [OP_GE_I_v6p] = {">=", "ge.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_LE_I] = {"<=", "le.i", + [OP_LE_I_v6p] = {"<=", "le.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_GT_I] = {">", "gt.i", + [OP_GT_I_v6p] = {">", "gt.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_LT_I] = {"<", "lt.i", + [OP_LT_I_v6p] = {"<", "lt.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_AND_I] = {"&&", "and.i", + [OP_AND_I_v6p] = {"&&", "and.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_OR_I] = {"||", "or.i", + [OP_OR_I_v6p] = {"||", "or.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_NOT_I] = {"!", "not.i", + [OP_NOT_I_v6p] = {"!", "not.i", ev_integer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_EQ_I] = {"==", "eq.i", + [OP_EQ_I_v6p] = {"==", "eq.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_NE_I] = {"!=", "ne.i", + [OP_NE_I_v6p] = {"!=", "ne.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_GE_U] = {">=", "ge.u", + [OP_GE_U_v6p] = {">=", "ge.u", ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - [OP_LE_U] = {"<=", "le.u", + [OP_LE_U_v6p] = {"<=", "le.u", ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - [OP_GT_U] = {">", "gt.u", + [OP_GT_U_v6p] = {">", "gt.u", ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - [OP_LT_U] = {"<", "lt.u", + [OP_LT_U_v6p] = {"<", "lt.u", ev_uinteger, ev_uinteger, ev_integer, PROG_VERSION, }, - [OP_BITXOR_F] = {"^", "bitxor.f", + [OP_BITXOR_F_v6p] = {"^", "bitxor.f", ev_float, ev_float, ev_float, PROG_VERSION, }, - [OP_BITNOT_F] = {"~", "bitnot.f", + [OP_BITNOT_F_v6p] = {"~", "bitnot.f", ev_float, ev_invalid, ev_float, PROG_VERSION, "%Ga, %gc", }, - [OP_BITXOR_I] = {"^", "bitxor.i", + [OP_BITXOR_I_v6p] = {"^", "bitxor.i", ev_integer, ev_integer, ev_integer, PROG_VERSION, }, - [OP_BITNOT_I] = {"~", "bitnot.i", + [OP_BITNOT_I_v6p] = {"~", "bitnot.i", ev_integer, ev_invalid, ev_integer, PROG_VERSION, "%Ga, %gc", }, - [OP_GE_P] = {">=", "ge.p", + [OP_GE_P_v6p] = {">=", "ge.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_LE_P] = {"<=", "le.p", + [OP_LE_P_v6p] = {"<=", "le.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_GT_P] = {">", "gt.p", + [OP_GT_P_v6p] = {">", "gt.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_LT_P] = {"<", "lt.p", + [OP_LT_P_v6p] = {"<", "lt.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_EQ_P] = {"==", "eq.p", + [OP_EQ_P_v6p] = {"==", "eq.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_NE_P] = {"!=", "ne.p", + [OP_NE_P_v6p] = {"!=", "ne.p", ev_pointer, ev_pointer, ev_integer, PROG_VERSION, }, - [OP_MOVEI] = {"", "movei", + [OP_MOVEI_v6p] = {"", "movei", ev_void, ev_short, ev_void, PROG_VERSION, "%Ga, %sb, %gc", }, - [OP_MOVEP] = {"", "movep", + [OP_MOVEP_v6p] = {"", "movep", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "%Ga, %Gb, %Gc", }, - [OP_MOVEPI] = {"", "movepi", + [OP_MOVEPI_v6p] = {"", "movepi", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "%Ga, %sb, %Gc", }, - [OP_MEMSETI] = {"", "memseti", + [OP_MEMSETI_v6p] = {"", "memseti", ev_integer, ev_short, ev_void, PROG_VERSION, "%Ga, %sb, %gc", }, - [OP_MEMSETP] = {"", "memsetp", + [OP_MEMSETP_v6p] = {"", "memsetp", ev_integer, ev_integer, ev_pointer, PROG_VERSION, "%Ga, %Gb, %Gc", }, - [OP_MEMSETPI] = {"", "memsetpi", + [OP_MEMSETPI_v6p] = {"", "memsetpi", ev_integer, ev_short, ev_pointer, PROG_VERSION, "%Ga, %sb, %Gc", }, - [OP_PUSH_S] = {"", "push.s", + [OP_PUSH_S_v6p] = {"", "push.s", ev_string, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_F] = {"", "push.f", + [OP_PUSH_F_v6p] = {"", "push.f", ev_float, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_V] = {"", "push.v", + [OP_PUSH_V_v6p] = {"", "push.v", ev_vector, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_ENT] = {"", "push.ent", + [OP_PUSH_ENT_v6p] = {"", "push.ent", ev_entity, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_FLD] = {"", "push.fld", + [OP_PUSH_FLD_v6p] = {"", "push.fld", ev_field, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_FN] = {"", "push.fn", + [OP_PUSH_FN_v6p] = {"", "push.fn", ev_func, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_P] = {"", "push.p", + [OP_PUSH_P_v6p] = {"", "push.p", ev_pointer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_Q] = {"", "push.q", + [OP_PUSH_Q_v6p] = {"", "push.q", ev_quat, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_I] = {"", "push.i", + [OP_PUSH_I_v6p] = {"", "push.i", ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSH_D] = {"", "push.d", + [OP_PUSH_D_v6p] = {"", "push.d", ev_double, ev_invalid, ev_invalid, PROG_VERSION, "%Ga", }, - [OP_PUSHB_S] = {"", "pushb.s", + [OP_PUSHB_S_v6p] = {"", "pushb.s", ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_F] = {"", "pushb.f", + [OP_PUSHB_F_v6p] = {"", "pushb.f", ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_V] = {"", "pushb.v", + [OP_PUSHB_V_v6p] = {"", "pushb.v", ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_ENT] = {"", "pushb.ent", + [OP_PUSHB_ENT_v6p] = {"", "pushb.ent", ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_FLD] = {"", "pushb.fld", + [OP_PUSHB_FLD_v6p] = {"", "pushb.fld", ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_FN] = {"", "pushb.fn", + [OP_PUSHB_FN_v6p] = {"", "pushb.fn", ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_P] = {"", "pushb.p", + [OP_PUSHB_P_v6p] = {"", "pushb.p", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_Q] = {"", "pushb.q", + [OP_PUSHB_Q_v6p] = {"", "pushb.q", ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_I] = {"", "pushb.i", + [OP_PUSHB_I_v6p] = {"", "pushb.i", ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_D] = {"", "pushb.d", + [OP_PUSHB_D_v6p] = {"", "pushb.d", ev_pointer, ev_integer, ev_double, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHBI_S] = {"", "pushbi.s", + [OP_PUSHBI_S_v6p] = {"", "pushbi.s", ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_F] = {"", "pushbi.f", + [OP_PUSHBI_F_v6p] = {"", "pushbi.f", ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_V] = {"", "pushbi.v", + [OP_PUSHBI_V_v6p] = {"", "pushbi.v", ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_ENT] = {"", "pushbi.ent", + [OP_PUSHBI_ENT_v6p] = {"", "pushbi.ent", ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_FLD] = {"", "pushbi.fld", + [OP_PUSHBI_FLD_v6p] = {"", "pushbi.fld", ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_FN] = {"", "pushbi.fn", + [OP_PUSHBI_FN_v6p] = {"", "pushbi.fn", ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_P] = {"", "pushbi.p", + [OP_PUSHBI_P_v6p] = {"", "pushbi.p", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_Q] = {"", "pushbi.q", + [OP_PUSHBI_Q_v6p] = {"", "pushbi.q", ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_I] = {"", "pushbi.i", + [OP_PUSHBI_I_v6p] = {"", "pushbi.i", ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_D] = {"", "pushbi.d", + [OP_PUSHBI_D_v6p] = {"", "pushbi.d", ev_pointer, ev_short, ev_double, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POP_S] = {"", "pop.s", + [OP_POP_S_v6p] = {"", "pop.s", ev_string, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_F] = {"", "pop.f", + [OP_POP_F_v6p] = {"", "pop.f", ev_float, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_V] = {"", "pop.v", + [OP_POP_V_v6p] = {"", "pop.v", ev_vector, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_ENT] = {"", "pop.ent", + [OP_POP_ENT_v6p] = {"", "pop.ent", ev_entity, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_FLD] = {"", "pop.fld", + [OP_POP_FLD_v6p] = {"", "pop.fld", ev_field, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_FN] = {"", "pop.fn", + [OP_POP_FN_v6p] = {"", "pop.fn", ev_func, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_P] = {"", "pop.p", + [OP_POP_P_v6p] = {"", "pop.p", ev_pointer, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_Q] = {"", "pop.q", + [OP_POP_Q_v6p] = {"", "pop.q", ev_quat, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_I] = {"", "pop.i", + [OP_POP_I_v6p] = {"", "pop.i", ev_integer, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POP_D] = {"", "pop.d", + [OP_POP_D_v6p] = {"", "pop.d", ev_double, ev_invalid, ev_invalid, PROG_VERSION, "%ga", }, - [OP_POPB_S] = {"", "popb.s", + [OP_POPB_S_v6p] = {"", "popb.s", ev_pointer, ev_integer, ev_string, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_F] = {"", "popb.f", + [OP_POPB_F_v6p] = {"", "popb.f", ev_pointer, ev_integer, ev_float, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_V] = {"", "popb.v", + [OP_POPB_V_v6p] = {"", "popb.v", ev_pointer, ev_integer, ev_vector, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_ENT] = {"", "popb.ent", + [OP_POPB_ENT_v6p] = {"", "popb.ent", ev_pointer, ev_integer, ev_entity, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_FLD] = {"", "popb.fld", + [OP_POPB_FLD_v6p] = {"", "popb.fld", ev_pointer, ev_integer, ev_field, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_FN] = {"", "popb.fn", + [OP_POPB_FN_v6p] = {"", "popb.fn", ev_pointer, ev_integer, ev_func, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_P] = {"", "popb.p", + [OP_POPB_P_v6p] = {"", "popb.p", ev_pointer, ev_integer, ev_pointer, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_Q] = {"", "popb.q", + [OP_POPB_Q_v6p] = {"", "popb.q", ev_pointer, ev_integer, ev_quat, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_I] = {"", "popb.i", + [OP_POPB_I_v6p] = {"", "popb.i", ev_pointer, ev_integer, ev_integer, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_D] = {"", "popb.d", + [OP_POPB_D_v6p] = {"", "popb.d", ev_pointer, ev_integer, ev_double, PROG_VERSION, "*(%Ga + %Gb)", }, - [OP_POPBI_S] = {"", "popbi.s", + [OP_POPBI_S_v6p] = {"", "popbi.s", ev_pointer, ev_short, ev_string, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_F] = {"", "popbi.f", + [OP_POPBI_F_v6p] = {"", "popbi.f", ev_pointer, ev_short, ev_float, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_V] = {"", "popbi.v", + [OP_POPBI_V_v6p] = {"", "popbi.v", ev_pointer, ev_short, ev_vector, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_ENT] = {"", "popbi.ent", + [OP_POPBI_ENT_v6p] = {"", "popbi.ent", ev_pointer, ev_short, ev_entity, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_FLD] = {"", "popbi.fld", + [OP_POPBI_FLD_v6p] = {"", "popbi.fld", ev_pointer, ev_short, ev_field, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_FN] = {"", "popbi.fn", + [OP_POPBI_FN_v6p] = {"", "popbi.fn", ev_pointer, ev_short, ev_func, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_P] = {"", "popbi.p", + [OP_POPBI_P_v6p] = {"", "popbi.p", ev_pointer, ev_short, ev_pointer, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_Q] = {"", "popbi.q", + [OP_POPBI_Q_v6p] = {"", "popbi.q", ev_pointer, ev_short, ev_quat, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_I] = {"", "popbi.i", + [OP_POPBI_I_v6p] = {"", "popbi.i", ev_pointer, ev_short, ev_integer, PROG_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_D] = {"", "popbi.d", + [OP_POPBI_D_v6p] = {"", "popbi.d", ev_pointer, ev_short, ev_double, PROG_VERSION, "*(%Ga + %sb)", }, // end of table - [OP_MEMSETPI+1] = {0}, //XXX FIXME relies on OP_MEMSETPI being last + [OP_MEMSETPI_v6p+1] = {0}, //XXX FIXME relies on OP_MEMSETPI_v6p being last }; -const opcode_t * -PR_Opcode (pr_short_t opcode) +const v6p_opcode_t * +PR_v6p_Opcode (pr_ushort_t opcode) { - if (opcode < 0 - || opcode >= (int) (sizeof (pr_opcodes) / sizeof (pr_opcodes[0])) - 1) { + size_t opcode_count = sizeof (pr_v6p_opcodes) / sizeof (pr_v6p_opcodes[0]); + if (opcode >= opcode_count - 1) { return 0; } - return &pr_opcodes[opcode]; + return &pr_v6p_opcodes[opcode]; } VISIBLE void @@ -1528,7 +1528,7 @@ PR_Opcode_Init (void) } static inline void -check_branch (progs_t *pr, dstatement_t *st, const opcode_t *op, short offset) +check_branch (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, short offset) { pr_int_t address = st - pr->pr_statements; @@ -1544,7 +1544,7 @@ is_vector_parameter_store (progs_t *pr, dstatement_t *st, { int i; - if (st->op != OP_STORE_V) + if (st->op != OP_STORE_V_v6p) return 0; if (operand != st->a) return 0; @@ -1557,7 +1557,7 @@ is_vector_parameter_store (progs_t *pr, dstatement_t *st, #define ISDENORM(x) ((x) && !((x) & 0x7f800000)) static inline void -check_global (progs_t *pr, dstatement_t *st, const opcode_t *op, etype_t type, +check_global (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, etype_t type, unsigned short operand, int check_denorm) { const char *msg; @@ -1615,7 +1615,7 @@ error: } static void -check_global_size (progs_t *pr, dstatement_t *st, const opcode_t *op, +check_global_size (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, unsigned short size, unsigned short operand) { const char *msg; @@ -1633,7 +1633,7 @@ error: int PR_Check_Opcodes (progs_t *pr) { - const opcode_t *op; + const v6p_opcode_t *op; dstatement_t *st; int state_ok = 0; int pushpop_ok = 0; @@ -1653,13 +1653,13 @@ PR_Check_Opcodes (progs_t *pr) if (0 && !pr_boundscheck->int_val) { for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; st++, i++) { - op = PR_Opcode (st->op); + op = PR_v6p_Opcode (st->op); if (!op) { PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " "statement %ld", st->op, (long)(st - pr->pr_statements)); } - if ((st->op == OP_STATE || st->op == OP_STATE_F) && !state_ok) { + if ((st->op == OP_STATE_v6p || st->op == OP_STATE_F_v6p) && !state_ok) { PR_Error (pr, "PR_Check_Opcodes: %s used with missing fields " "or globals", op->opname); } @@ -1672,43 +1672,43 @@ PR_Check_Opcodes (progs_t *pr) } else { for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; st++, i++) { - op = PR_Opcode (st->op); + op = PR_v6p_Opcode (st->op); if (!op) { PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " "statement %ld", st->op, (long)(st - pr->pr_statements)); } switch (st->op) { - case OP_IF: - case OP_IFNOT: + case OP_IF_v6p: + case OP_IFNOT_v6p: check_global (pr, st, op, op->type_a, st->a, 1); check_branch (pr, st, op, st->b); break; - case OP_GOTO: + case OP_GOTO_v6p: check_branch (pr, st, op, st->a); break; - case OP_DONE: - case OP_RETURN: + case OP_DONE_v6p: + case OP_RETURN_v6p: check_global (pr, st, op, ev_integer, st->a, 1); check_global (pr, st, op, ev_void, st->b, 0); check_global (pr, st, op, ev_void, st->c, 0); break; - case OP_RCALL1: + case OP_RCALL1_v6p: check_global (pr, st, op, ev_void, st->c, 1); - case OP_RCALL2: - case OP_RCALL3: - case OP_RCALL4: - case OP_RCALL5: - case OP_RCALL6: - case OP_RCALL7: - case OP_RCALL8: - if (st->op > OP_RCALL1) + case OP_RCALL2_v6p: + case OP_RCALL3_v6p: + case OP_RCALL4_v6p: + case OP_RCALL5_v6p: + case OP_RCALL6_v6p: + case OP_RCALL7_v6p: + case OP_RCALL8_v6p: + if (st->op > OP_RCALL1_v6p) check_global (pr, st, op, ev_integer, st->c, 1); check_global (pr, st, op, ev_integer, st->b, 1); check_global (pr, st, op, ev_func, st->a, 1); break; - case OP_STATE: - case OP_STATE_F: + case OP_STATE_v6p: + case OP_STATE_F_v6p: if (!state_ok) { PR_Error (pr, "PR_Check_Opcodes: %s used with missing " "fields or globals", op->opname); @@ -1717,70 +1717,70 @@ PR_Check_Opcodes (progs_t *pr) check_global (pr, st, op, op->type_b, st->b, 1); check_global (pr, st, op, op->type_c, st->c, 1); break; - case OP_MOVEI: + case OP_MOVEI_v6p: check_global_size (pr, st, op, st->b, st->a); check_global_size (pr, st, op, st->b, st->c); break; - case OP_MEMSETI: + case OP_MEMSETI_v6p: check_global_size (pr, st, op, st->b, st->c); break; - case OP_PUSHB_F: - case OP_PUSHB_S: - case OP_PUSHB_ENT: - case OP_PUSHB_FLD: - case OP_PUSHB_FN: - case OP_PUSHB_I: - case OP_PUSHB_P: - case OP_PUSHB_V: - case OP_PUSHB_Q: - case OP_PUSHBI_F: - case OP_PUSHBI_S: - case OP_PUSHBI_ENT: - case OP_PUSHBI_FLD: - case OP_PUSHBI_FN: - case OP_PUSHBI_I: - case OP_PUSHBI_P: - case OP_PUSHBI_V: - case OP_PUSHBI_Q: + case OP_PUSHB_F_v6p: + case OP_PUSHB_S_v6p: + case OP_PUSHB_ENT_v6p: + case OP_PUSHB_FLD_v6p: + case OP_PUSHB_FN_v6p: + case OP_PUSHB_I_v6p: + case OP_PUSHB_P_v6p: + case OP_PUSHB_V_v6p: + case OP_PUSHB_Q_v6p: + case OP_PUSHBI_F_v6p: + case OP_PUSHBI_S_v6p: + case OP_PUSHBI_ENT_v6p: + case OP_PUSHBI_FLD_v6p: + case OP_PUSHBI_FN_v6p: + case OP_PUSHBI_I_v6p: + case OP_PUSHBI_P_v6p: + case OP_PUSHBI_V_v6p: + case OP_PUSHBI_Q_v6p: // op->type_c is used for selecting the operator during // compilation, but is invalid when running check_global (pr, st, op, op->type_a, st->a, 1); check_global (pr, st, op, op->type_b, st->b, 1); check_global (pr, st, op, ev_invalid, st->c, 1); break; - case OP_POP_F: - case OP_POP_FLD: - case OP_POP_ENT: - case OP_POP_S: - case OP_POP_FN: - case OP_POP_I: - case OP_POP_P: - case OP_POP_V: - case OP_POP_Q: + case OP_POP_F_v6p: + case OP_POP_FLD_v6p: + case OP_POP_ENT_v6p: + case OP_POP_S_v6p: + case OP_POP_FN_v6p: + case OP_POP_I_v6p: + case OP_POP_P_v6p: + case OP_POP_V_v6p: + case OP_POP_Q_v6p: // don't want to check for denormal floats, otherwise - // OP_POP_* could use the defualt rule + // OP_POP__v6p* could use the defualt rule check_global (pr, st, op, op->type_a, st->a, 0); check_global (pr, st, op, ev_invalid, st->b, 1); check_global (pr, st, op, ev_invalid, st->c, 1); break; - case OP_POPB_F: - case OP_POPB_S: - case OP_POPB_ENT: - case OP_POPB_FLD: - case OP_POPB_FN: - case OP_POPB_I: - case OP_POPB_P: - case OP_POPB_V: - case OP_POPB_Q: - case OP_POPBI_F: - case OP_POPBI_S: - case OP_POPBI_ENT: - case OP_POPBI_FLD: - case OP_POPBI_FN: - case OP_POPBI_I: - case OP_POPBI_P: - case OP_POPBI_V: - case OP_POPBI_Q: + case OP_POPB_F_v6p: + case OP_POPB_S_v6p: + case OP_POPB_ENT_v6p: + case OP_POPB_FLD_v6p: + case OP_POPB_FN_v6p: + case OP_POPB_I_v6p: + case OP_POPB_P_v6p: + case OP_POPB_V_v6p: + case OP_POPB_Q_v6p: + case OP_POPBI_F_v6p: + case OP_POPBI_S_v6p: + case OP_POPBI_ENT_v6p: + case OP_POPBI_FLD_v6p: + case OP_POPBI_FN_v6p: + case OP_POPBI_I_v6p: + case OP_POPBI_P_v6p: + case OP_POPBI_V_v6p: + case OP_POPBI_Q_v6p: // op->type_c is used for selecting the operator during // compilation, but is invalid when running check_global (pr, st, op, op->type_a, st->a, 1); @@ -1790,7 +1790,7 @@ PR_Check_Opcodes (progs_t *pr) default: check_global (pr, st, op, op->type_a, st->a, 1); check_global (pr, st, op, op->type_b, st->b, - (op - pr_opcodes) != OP_STORE_F); + (op - pr_v6p_opcodes) != OP_STORE_F_v6p); check_global (pr, st, op, op->type_c, st->c, 0); break; } diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index 2ffbe04c8..f6a95f75a 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -31,27 +31,28 @@ #ifndef __opcodes_h #define __opcodes_h -extern struct opcode_s *op_done; -extern struct opcode_s *op_return; -extern struct opcode_s *op_return_v; -extern struct opcode_s *op_if; -extern struct opcode_s *op_ifnot; -extern struct opcode_s *op_ifbe; -extern struct opcode_s *op_ifb; -extern struct opcode_s *op_ifae; -extern struct opcode_s *op_ifa; -extern struct opcode_s *op_state; -extern struct opcode_s *op_state_f; -extern struct opcode_s *op_goto; -extern struct opcode_s *op_jump; -extern struct opcode_s *op_jumpb; +extern struct v6p_opcode_s *op_done; +extern struct v6p_opcode_s *op_return; +extern struct v6p_opcode_s *op_return_v; +extern struct v6p_opcode_s *op_if; +extern struct v6p_opcode_s *op_ifnot; +extern struct v6p_opcode_s *op_ifbe; +extern struct v6p_opcode_s *op_ifb; +extern struct v6p_opcode_s *op_ifae; +extern struct v6p_opcode_s *op_ifa; +extern struct v6p_opcode_s *op_state; +extern struct v6p_opcode_s *op_state_f; +extern struct v6p_opcode_s *op_goto; +extern struct v6p_opcode_s *op_jump; +extern struct v6p_opcode_s *op_jumpb; struct operand_s; -extern struct opcode_s *opcode_map; +extern struct v6p_opcode_s *opcode_map; -struct opcode_s *opcode_find (const char *name, struct operand_s *op_a, - struct operand_s *op_b, struct operand_s *op_c); +struct v6p_opcode_s *opcode_find (const char *name, struct operand_s *op_a, + struct operand_s *op_b, + struct operand_s *op_c); void opcode_init (void); #endif//__opcodes_h diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index c2dac98ec..48e89b422 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -185,7 +185,7 @@ emit_statement (statement_t *statement) { const char *opcode = statement->opcode; def_t *def_a, *def_b, *def_c; - opcode_t *op; + v6p_opcode_t *op; dstatement_t *s; def_a = get_operand_def (statement->expr, statement->opa); diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index bf962ec96..8ad5358d9 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -49,14 +49,14 @@ hashtab_t *opcode_type_table; hashtab_t *opcode_void_table; -opcode_t *opcode_map; +v6p_opcode_t *opcode_map; #define ROTL(x,n) ((((unsigned)(x))<<(n))|((unsigned)(x))>>(32-n)) static uintptr_t get_hash (const void *_op, void *_tab) { - opcode_t *op = (opcode_t *) _op; + v6p_opcode_t *op = (v6p_opcode_t *) _op; uintptr_t hash; hash = ROTL (~op->type_a, 8) + ROTL (~op->type_b, 16) @@ -67,8 +67,8 @@ get_hash (const void *_op, void *_tab) static int compare (const void *_opa, const void *_opb, void *unused) { - opcode_t *opa = (opcode_t *) _opa; - opcode_t *opb = (opcode_t *) _opb; + v6p_opcode_t *opa = (v6p_opcode_t *) _opa; + v6p_opcode_t *opb = (v6p_opcode_t *) _opb; int cmp; cmp = (opa->type_a == opb->type_a) @@ -80,7 +80,7 @@ compare (const void *_opa, const void *_opb, void *unused) static const char * get_key (const void *op, void *unused) { - return ((opcode_t *) op)->name; + return ((v6p_opcode_t *) op)->name; } static int @@ -92,13 +92,13 @@ check_operand_type (etype_t ot1, etype_t ot2) return 0; } -opcode_t * +v6p_opcode_t * opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) { - opcode_t search_op = {}; - opcode_t *op; - opcode_t *sop; + v6p_opcode_t search_op = {}; + v6p_opcode_t *op; + v6p_opcode_t *sop; void **op_list; int i; @@ -126,8 +126,8 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b, void opcode_init (void) { - const opcode_t *op; - opcode_t *mop; + const v6p_opcode_t *op; + v6p_opcode_t *mop; if (opcode_type_table) { Hash_FlushTable (opcode_void_table); @@ -140,14 +140,14 @@ opcode_init (void) } int num_opcodes = 0; - for (op = pr_opcodes; op->name; op++) { + for (op = pr_v6p_opcodes; op->name; op++) { num_opcodes++; } if (!opcode_map) { - opcode_map = calloc (num_opcodes, sizeof (opcode_t)); + opcode_map = calloc (num_opcodes, sizeof (v6p_opcode_t)); } for (int i = 0; i < num_opcodes; i++) { - op = pr_opcodes + i; + op = pr_v6p_opcodes + i; if (op->min_version > options.code.progsversion) continue; mop = opcode_map + i; From 925797b1d459e5ac3ad67c7f92f7cac91c2cc677 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Jan 2022 23:15:15 +0900 Subject: [PATCH 2089/3664] [gamecode] Add a new Ruamoko instruction set When it's finalized (most of the conversion operations will go, probably the float bit ops, maybe (very undecided) the 3-component vector ops, and likely the CALLN ops), this will be the actual instruction set for Ruamoko. Main features: - Significant reduction in redundant instructions: no more multiple opcodes to move the one operand size. - load, store, push, and pop share unified addressing mode encoding (with the exception of mode 0 for load as that is redundant with mode 0 for store, thus load mode 0 gives quick access to entity.field). - Full support for both 32 and 64 bit signed integer, unsigned integer, and floating point values. - SIMD for 1, 2, (currently) 3, and 4 components. Transfers support up to 128-bit wide operations (need two operations to transfer a full 4-component double/long vector), but all math operations support both 128-bit (32-bit components) and 256-bit (64-bit components) vectors. - "Interpreted" operations for the various vector sizes: complex dot and multiplication, 3d vector dot and cross product, quaternion dot and multiplication, along with qv and vq shortcuts. - 4-component swizzles for both sizes (not yet implemented, but the instructions are allocated), with the option to zero or negate (thus conjugates for complex and quaternion values) individual components. - "Based offsets": all relevant instructions include base register indices for all three operands allowing for direct access to any of four areas (eg, current entity, current stack frame, Objective-QC self, ...) instructions to set a register and push/pop the four registers to/from the stack. Remaining work: - Implement swizzle operations and a few other stragglers. = Make a decision about conversion operations (if any instructions remain, they'll be just single-component (at 14 meaningful pairs, that's a lot of instructions to waste on SIMD versions). - Decide whether to keep CALL1-CALL8: probably little point in supporting two different calling conventions, and it would free up another eight instructions. - Unit tests for the instructions. - Teach qfcc to generate code for the new instruction set (hah, biggest job, I'm sure, though hopefully not as crazy as the rewrite eleven years ago). --- include/QF/pr_comp.h | 184 +++++++- include/QF/progs.h | 3 + libs/gamecode/pr_exec.c | 919 ++++++++++++++++++++++++++++++++++++++ libs/gamecode/pr_opcode.c | 19 +- 4 files changed, 1116 insertions(+), 9 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index f51ce2693..84cc7e755 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -424,6 +424,188 @@ typedef enum { } pr_opcode_v6p_e; #define OP_BREAK 0x8000 +typedef enum { + // 0 0000 load from [a,b] -> c + OP_LOAD_E_1, OP_LOAD_E_2, OP_LOAD_E_3, OP_LOAD_E_4, + OP_LOAD_B_1, OP_LOAD_B_2, OP_LOAD_B_3, OP_LOAD_B_4, + OP_LOAD_C_1, OP_LOAD_C_2, OP_LOAD_C_3, OP_LOAD_C_4, + OP_LOAD_D_1, OP_LOAD_D_2, OP_LOAD_D_3, OP_LOAD_D_4, + // 0 0001 store from c -> [a, b] + OP_STORE_A_1, OP_STORE_A_2, OP_STORE_A_3, OP_STORE_A_4, // redundant? + OP_STORE_B_1, OP_STORE_B_2, OP_STORE_B_3, OP_STORE_B_4, + OP_STORE_C_1, OP_STORE_C_2, OP_STORE_C_3, OP_STORE_C_4, + OP_STORE_D_1, OP_STORE_D_2, OP_STORE_D_3, OP_STORE_D_4, + // 0 0010 push from [a,b] to the stack + OP_PUSH_A_1, OP_PUSH_A_2, OP_PUSH_A_3, OP_PUSH_A_4, + OP_PUSH_B_1, OP_PUSH_B_2, OP_PUSH_B_3, OP_PUSH_B_4, + OP_PUSH_C_1, OP_PUSH_C_2, OP_PUSH_C_3, OP_PUSH_C_4, + OP_PUSH_D_1, OP_PUSH_D_2, OP_PUSH_D_3, OP_PUSH_D_4, + // 0 0011 pop from the stack to [a,b] + OP_POP_A_1, OP_POP_A_2, OP_POP_A_3, OP_POP_A_4, + OP_POP_B_1, OP_POP_B_2, OP_POP_B_3, OP_POP_B_4, + OP_POP_C_1, OP_POP_C_2, OP_POP_C_3, OP_POP_C_4, + OP_POP_D_1, OP_POP_D_2, OP_POP_D_3, OP_POP_D_4, + // 0 0100 flow control + OP_IFNOT_A, OP_IFNOT_B, OP_IFNOT_C, OP_IFNOT_D, + OP_IF_A, OP_IF_B, OP_IF_C, OP_IF_D, + OP_JUMP_A, OP_JUMP_B, OP_JUMP_C, OP_JUMP_D, + OP_CALL_A, OP_CALL_B, OP_CALL_C, OP_CALL_D, + // 0 0101 calls + OP_CALL_1, OP_CALL_2, OP_CALL_3, OP_CALL_4, + OP_CALL_5, OP_CALL_6, OP_CALL_7, OP_CALL_8, + OP_RETURN_1, OP_RETURN_2, OP_RETURN_3, OP_RETURN_4, + OP_RETURN_0, OP_WITH, OP_STATE_ft, OP_STATE_ftt, + // 0 0110 flow control 2 + OP_IFA_A, OP_IFA_B, OP_IFA_C, OP_IFA_D, + OP_IFBE_A, OP_IFBE_B, OP_IFBE_C, OP_IFBE_D, + OP_IFB_A, OP_IFB_B, OP_IFB_C, OP_IFB_D, + OP_IFAE_A, OP_IFAE_B, OP_IFAE_C, OP_IFAE_D, + // 0 0111 interpreted vector multiplication + // C complex + // V vector (3d) + // Q quaternion + OP_DOT_CC_F, OP_DOT_VV_F, OP_DOT_QQ_F, OP_CROSS_VV_F, + OP_MUL_CC_F, OP_MUL_QV_F, OP_MUL_VQ_F, OP_MUL_QQ_F, + OP_DOT_CC_D, OP_DOT_VV_D, OP_DOT_QQ_D, OP_CROSS_VV_D, + OP_MUL_CC_D, OP_MUL_QV_D, OP_MUL_VQ_D, OP_MUL_QQ_D, + // comparison + // 0 1000 == + OP_EQ_I_1, OP_EQ_I_2, OP_EQ_I_3, OP_EQ_I_4, + OP_EQ_F_1, OP_EQ_F_2, OP_EQ_F_3, OP_EQ_F_4, + OP_EQ_L_1, OP_EQ_L_2, OP_EQ_L_3, OP_EQ_L_4, + OP_EQ_D_1, OP_EQ_D_2, OP_EQ_D_3, OP_EQ_D_4, + // 0 1001 < + OP_LT_I_1, OP_LT_I_2, OP_LT_I_3, OP_LT_I_4, + OP_LT_F_1, OP_LT_F_2, OP_LT_F_3, OP_LT_F_4, + OP_LT_L_1, OP_LT_L_2, OP_LT_L_3, OP_LT_L_4, + OP_LT_D_1, OP_LT_D_2, OP_LT_D_3, OP_LT_D_4, + // 0 1010 > + OP_GT_I_1, OP_GT_I_2, OP_GT_I_3, OP_GT_I_4, + OP_GT_F_1, OP_GT_F_2, OP_GT_F_3, OP_GT_F_4, + OP_GT_L_1, OP_GT_L_2, OP_GT_L_3, OP_GT_L_4, + OP_GT_D_1, OP_GT_D_2, OP_GT_D_3, OP_GT_D_4, + // 0 1011 convert between signed integral and double(XXX how useful as vec?) + OP_CONV_ID_1, OP_CONV_ID_2, OP_CONV_ID_3, OP_CONV_ID_4, + OP_CONV_DI_1, OP_CONV_DI_2, OP_CONV_DI_3, OP_CONV_DI_4, + OP_CONV_LD_1, OP_CONV_LD_2, OP_CONV_LD_3, OP_CONV_LD_4, + OP_CONV_DL_1, OP_CONV_DL_2, OP_CONV_DL_3, OP_CONV_DL_4, + // comparison + // 0 1100 != + OP_NE_I_1, OP_NE_I_2, OP_NE_I_3, OP_NE_I_4, + OP_NE_F_1, OP_NE_F_2, OP_NE_F_3, OP_NE_F_4, + OP_NE_L_1, OP_NE_L_2, OP_NE_L_3, OP_NE_L_4, + OP_NE_D_1, OP_NE_D_2, OP_NE_D_3, OP_NE_D_4, + // 0 1101 >= + OP_GE_I_1, OP_GE_I_2, OP_GE_I_3, OP_GE_I_4, + OP_GE_F_1, OP_GE_F_2, OP_GE_F_3, OP_GE_F_4, + OP_GE_L_1, OP_GE_L_2, OP_GE_L_3, OP_GE_L_4, + OP_GE_D_1, OP_GE_D_2, OP_GE_D_3, OP_GE_D_4, + // 0 1110 <= + OP_LE_I_1, OP_LE_I_2, OP_LE_I_3, OP_LE_I_4, + OP_LE_F_1, OP_LE_F_2, OP_LE_F_3, OP_LE_F_4, + OP_LE_L_1, OP_LE_L_2, OP_LE_L_3, OP_LE_L_4, + OP_LE_D_1, OP_LE_D_2, OP_LE_D_3, OP_LE_D_4, + // 0 1111 convert between signed integral sizes (XXX how useful as vec?) + OP_CONV_IL_1, OP_CONV_IL_2, OP_CONV_IL_3, OP_CONV_IL_4, + OP_CONV_LI_1, OP_CONV_LI_2, OP_CONV_LI_3, OP_CONV_LI_4, + OP_CONV_uU_1, OP_CONV_uU_2, OP_CONV_uU_3, OP_CONV_uU_4, + OP_CONV_Uu_1, OP_CONV_Uu_2, OP_CONV_Uu_3, OP_CONV_Uu_4, + + // 1 0000 c = a * b + OP_MUL_I_1, OP_MUL_I_2, OP_MUL_I_3, OP_MUL_I_4, + OP_MUL_F_1, OP_MUL_F_2, OP_MUL_F_3, OP_MUL_F_4, + OP_MUL_L_1, OP_MUL_L_2, OP_MUL_L_3, OP_MUL_L_4, + OP_MUL_D_1, OP_MUL_D_2, OP_MUL_D_3, OP_MUL_D_4, + // 1 0001 c = a / b + OP_DIV_I_1, OP_DIV_I_2, OP_DIV_I_3, OP_DIV_I_4, + OP_DIV_F_1, OP_DIV_F_2, OP_DIV_F_3, OP_DIV_F_4, + OP_DIV_L_1, OP_DIV_L_2, OP_DIV_L_3, OP_DIV_L_4, + OP_DIV_D_1, OP_DIV_D_2, OP_DIV_D_3, OP_DIV_D_4, + // 1 0010 c = a % b (remainder, C %) + OP_REM_I_1, OP_REM_I_2, OP_REM_I_3, OP_REM_I_4, + OP_REM_F_1, OP_REM_F_2, OP_REM_F_3, OP_REM_F_4, + OP_REM_L_1, OP_REM_L_2, OP_REM_L_3, OP_REM_L_4, + OP_REM_D_1, OP_REM_D_2, OP_REM_D_3, OP_REM_D_4, + // 1 0011 c = a %% b (true modulo, python %) + OP_MOD_I_1, OP_MOD_I_2, OP_MOD_I_3, OP_MOD_I_4, + OP_MOD_F_1, OP_MOD_F_2, OP_MOD_F_3, OP_MOD_F_4, + OP_MOD_L_1, OP_MOD_L_2, OP_MOD_L_3, OP_MOD_L_4, + OP_MOD_D_1, OP_MOD_D_2, OP_MOD_D_3, OP_MOD_D_4, + // 1 0100 c = a + b + OP_ADD_I_1, OP_ADD_I_2, OP_ADD_I_3, OP_ADD_I_4, + OP_ADD_F_1, OP_ADD_F_2, OP_ADD_F_3, OP_ADD_F_4, + OP_ADD_L_1, OP_ADD_L_2, OP_ADD_L_3, OP_ADD_L_4, + OP_ADD_D_1, OP_ADD_D_2, OP_ADD_D_3, OP_ADD_D_4, + // 1 0101 c = a - b + OP_SUB_I_1, OP_SUB_I_2, OP_SUB_I_3, OP_SUB_I_4, + OP_SUB_F_1, OP_SUB_F_2, OP_SUB_F_3, OP_SUB_F_4, + OP_SUB_L_1, OP_SUB_L_2, OP_SUB_L_3, OP_SUB_L_4, + OP_SUB_D_1, OP_SUB_D_2, OP_SUB_D_3, OP_SUB_D_4, + // 1 0110 c = a << b (string ops mixed in) + OP_SHL_I_1, OP_SHL_I_2, OP_SHL_I_3, OP_SHL_I_4, + OP_EQ_S, OP_LT_S, OP_GT_S, OP_ADD_S, + OP_SHL_L_1, OP_SHL_L_2, OP_SHL_L_3, OP_SHL_L_4, + OP_CMP_S, OP_GE_S, OP_LE_S, OP_NOT_S, //OP_CMP_S doubles as NE + // 1 0111 c = a >> b + OP_SHR_I_1, OP_SHR_I_2, OP_SHR_I_3, OP_SHR_I_4, + OP_SHR_u_1, OP_SHR_u_2, OP_SHR_u_3, OP_SHR_u_4, + OP_SHR_L_1, OP_SHR_L_2, OP_SHR_L_3, OP_SHR_L_4, + OP_SHR_U_1, OP_SHR_U_2, OP_SHR_U_3, OP_SHR_U_4, + // 1 1000 c = a (& | ^) b or ~a (bitwise ops) + OP_BITAND_I_1, OP_BITAND_I_2, OP_BITAND_I_3, OP_BITAND_I_4, + OP_BITOR_I_1, OP_BITOR_I_2, OP_BITOR_I_3, OP_BITOR_I_4, + OP_BITXOR_I_1, OP_BITXOR_I_2, OP_BITXOR_I_3, OP_BITXOR_I_4, + OP_BITNOT_I_1, OP_BITNOT_I_2, OP_BITNOT_I_3, OP_BITNOT_I_4, + // 1 1001 < unsigned (float logic and bit ops mixed in) + OP_LT_u_1, OP_LT_u_2, OP_LT_u_3, OP_LT_u_4, + OP_BITAND_F, OP_BITOR_F, OP_BITXOR_F, OP_BITNOT_F, + OP_LT_U_1, OP_LT_U_2, OP_LT_U_3, OP_LT_U_4, + OP_AND_F, OP_OR_F, OP_XOR_F, OP_NOT_F, + // 1 1010 > unsigned + OP_GT_u_1, OP_GT_u_2, OP_GT_u_3, OP_GT_u_4, + OP_spare, OP_NOT_D, OP_NOT_V, OP_NOT_Q, + OP_GT_U_1, OP_GT_U_2, OP_GT_U_3, OP_GT_U_4, + OP_EQ_V, OP_EQ_Q, OP_NE_V, OP_NE_Q, + // 1 1011 lea, with, etc + OP_LEA_A, OP_LEA_B, OP_LEA_C, OP_LEA_D, + OP_LEA_E, OP_ANY_2, OP_ANY_3, OP_ANY_4, + OP_PUSHREG, OP_ALL_2, OP_ALL_3, OP_ALL_4, + OP_POPREG, OP_NONE_2, OP_NONE_3, OP_NONE_4, + // 1 1100 c = a (&& || ^^) b or !a (logical ops (no short circuit)) + OP_AND_I_1, OP_AND_I_2, OP_AND_I_3, OP_AND_I_4, + OP_OR_I_1, OP_OR_I_2, OP_OR_I_3, OP_OR_I_4, + OP_XOR_I_1, OP_XOR_I_2, OP_XOR_I_3, OP_XOR_I_4, + OP_NOT_I_1, OP_NOT_I_2, OP_NOT_I_3, OP_NOT_I_4, + // 1 1101 >= unsigned with float shifts and moves mixed in + OP_GE_u_1, OP_GE_u_2, OP_GE_u_3, OP_GE_u_4, + OP_SHL_F, OP_MOVE_I, OP_MOVE_P, OP_MOVE_PI, + OP_GE_U_1, OP_GE_U_2, OP_GE_U_3, OP_GE_U_4, + OP_SHR_F, OP_MEMSET_I, OP_MEMSET_P, OP_MEMSET_PI, + // 1 1110 <= unsigned with scale and swizzle mixed in + OP_LE_u_1, OP_LE_u_2, OP_LE_u_3, OP_LE_u_4, + OP_SWIZZLE_F, OP_SCALE_F_2, OP_SCALE_F_3, OP_SCALE_F_4, + OP_LE_U_1, OP_LE_U_2, OP_LE_U_3, OP_LE_U_4, + OP_SWIZZLE_D, OP_SCALE_D_2, OP_SCALE_D_3, OP_SCALE_D_4, + // 1 1111 convert between integral and float (XXX how useful as vec?) + OP_CONV_IF_1, OP_CONV_IF_2, OP_CONV_IF_3, OP_CONV_IF_4, + OP_CONV_FI_1, OP_CONV_FI_2, OP_CONV_FI_3, OP_CONV_FI_4, + OP_CONV_FD_1, OP_CONV_FD_2, OP_CONV_FD_3, OP_CONV_FD_4, + OP_CONV_DF_1, OP_CONV_DF_2, OP_CONV_DF_3, OP_CONV_DF_4, +} pr_opcode_e; +#define OP_A_SHIFT (9) +#define OP_B_SHIFT (11) +#define OP_C_SHIFT (13) +#define OP_A_BASE (3 << OP_A_SHIFT) +#define OP_B_BASE (3 << OP_B_SHIFT) +#define OP_C_BASE (3 << OP_C_SHIFT) + +typedef enum { + OP_with_zero, + OP_with_base, + OP_with_stack, + OP_with_entity, +} pr_with_e; + typedef struct v6p_opcode_s { const char *name; const char *opname; @@ -437,7 +619,7 @@ const v6p_opcode_t *PR_v6p_Opcode (pr_ushort_t opcode) __attribute__((const)); void PR_Opcode_Init (void); // idempotent typedef struct dstatement_s { - pr_opcode_v6p_e op:16; + pr_opcode_e op:16; // will be pr_opcode_v6p_e for older progs pr_ushort_t a,b,c; } GCC_STRUCT dstatement_t; diff --git a/include/QF/progs.h b/include/QF/progs.h index 8d32e2074..6f3866ee1 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1793,6 +1793,8 @@ extern const char *pr_gametype; #define MAX_STACK_DEPTH 64 #define LOCALSTACK_SIZE 4096 #define PR_RS_SLOTS 16 +#define PR_BASE_IND(o, b) (((o) & OP_##b##_BASE) >> OP_##b##_SHIFT) +#define PR_BASE(p, s, b) (p->pr_bases[PR_BASE_IND(s->op, b)]) typedef struct strref_s strref_t; @@ -1876,6 +1878,7 @@ struct progs_s { dstatement_t *pr_statements; pr_type_t *pr_globals; unsigned globals_size; + pr_uivec4_t pr_bases; ///< base registers (index in opcode) ///@} /// \name parameter block diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index ae6b3df4e..3aa973620 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -44,6 +44,12 @@ #include "QF/sys.h" #include "QF/zone.h" +#include "QF/simd/vec2d.h" +#include "QF/simd/vec2f.h" +#include "QF/simd/vec2i.h" +#include "QF/simd/vec4d.h" +#include "QF/simd/vec4f.h" +#include "QF/simd/vec4i.h" #include "compat.h" @@ -1713,6 +1719,917 @@ op_call: exit_program: } +#define MM(type) (*((pr_##type##_t *) (mm))) +#define STK(type) (*((pr_##type##_t *) (stk))) + +static pr_type_t * +pr_entity_mode (progs_t *pr, const dstatement_t *st, int shift) +{ + pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, A); + int mm_ind = (st->op >> shift) & 3; + pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + pointer_t mm_offs = 0; + + switch (mm_ind) { + case 0: + // entity.field (equivalent to OP_LOAD_t_v6p) + mm_offs = edict_area + OPA(uint) + OPB(uint); + break; + case 1: + // simple pointer dereference: *a + mm_offs = OPA(uint); + break; + case 2: + // constant indexed pointer: *a + b + mm_offs = OPA(uint) + st->b; + break; + case 3: + // verible indexed pointer: *a + *b (supports -ve offset) + mm_offs = OPA(uint) + OPB(int); + break; + } + return pr->pr_globals + mm_offs; +} + +static pr_type_t * +pr_address_mode (progs_t *pr, const dstatement_t *st, int shift) +{ + pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, A); + int mm_ind = (st->op >> shift) & 3; + pointer_t mm_offs = 0; + + switch (mm_ind) { + case 0: + // regular global access + mm_offs = op_a - pr->pr_globals; + break; + case 1: + // simple pointer dereference: *a + mm_offs = OPA(uint); + break; + case 2: + // constant indexed pointer: *a + b + mm_offs = OPA(uint) + st->b; + break; + case 3: + // verible indexed pointer: *a + *b (supports -ve offset) + mm_offs = OPA(uint) + OPB(int); + break; + } + return pr->pr_globals + mm_offs; +} + +static pr_pointer_t +pr_jump_mode (progs_t *pr, const dstatement_t *st) +{ + pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, A); + int jump_ind = st->op & 3; + pointer_t jump_offs = pr->pr_xstatement; + + switch (jump_ind) { + case 0: + // instruction relative offset + jump_offs = jump_offs + st->a; + break; + case 1: + // simple pointer dereference: *a + jump_offs = OPA(uint); + break; + case 2: + // constant indexed pointer: *a + b + jump_offs = OPA(uint) + st->b; + break; + case 3: + // verible indexed pointer: *a + *b (supports -ve offset) + jump_offs = OPA(uint) + OPB(int); + break; + } + return jump_offs - 1; // for st++ +} + +static pr_pointer_t __attribute__((pure)) +pr_with (progs_t *pr, const dstatement_t *st) +{ + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, A); + pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + switch (st->a) { + case 0: + // hard-0 base + return st->b; + case 1: + // relative to current base + return op_b - pr->pr_globals; + case 2: + // relative to stack (-ve offset) + return *pr->globals.stack + (pr_short_t) st->b; + case 3: + // relative to edict_area (+ve only) + return edict_area + st->b; + } + PR_RunError (pr, "Invalid with index: %u", st->a); +} + +static pr_type_t * +pr_stack_push (progs_t *pr) +{ + // keep the stack 16-byte aligned + pointer_t stack = *pr->globals.stack - 4; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + } + *pr->globals.stack = stack; + return stk; +} + +static pr_type_t * +pr_stack_pop (progs_t *pr) +{ + pointer_t stack = *pr->globals.stack; + pr_type_t *stk = pr->pr_globals + stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 4); + } + // keep the stack 16-byte aligned + *pr->globals.stack = stack + 4; + return stk; +} + +static void +pr_exec_ruamoko (progs_t *pr, int exitdepth) +{ + int profile, startprofile; + dstatement_t *st; + pr_type_t old_val = {0}; + + // make a stack frame + startprofile = profile = 0; + + st = pr->pr_statements + pr->pr_xstatement; + + if (pr->watch) { + old_val = *pr->watch; + } + + while (1) { + st++; + ++pr->pr_xstatement; + if (pr->pr_xstatement != st - pr->pr_statements) + PR_RunError (pr, "internal error"); + if (++profile > 1000000 && !pr->no_exec_limit) { + PR_RunError (pr, "runaway loop error"); + } + + if (pr->pr_trace) { + if (pr->debug_handler) { + pr->debug_handler (prd_trace, 0, pr->debug_data); + } else { + PR_PrintStatement (pr, st, 1); + } + } + + if (st->op & OP_BREAK) { + if (pr->debug_handler) { + pr->debug_handler (prd_breakpoint, 0, pr->debug_data); + } else { + PR_RunError (pr, "breakpoint hit"); + } + } + + pointer_t st_a = st->a + PR_BASE (pr, st, A); + pointer_t st_b = st->b + PR_BASE (pr, st, A); + pointer_t st_c = st->c + PR_BASE (pr, st, A); + + + pr_type_t *op_a = pr->pr_globals + st_a; + pr_type_t *op_b = pr->pr_globals + st_b; + pr_type_t *op_c = pr->pr_globals + st_c; + + pr_type_t *stk; + pr_type_t *mm; + func_t function; + pr_opcode_e st_op = st->op & ~(OP_BREAK|OP_A_BASE|OP_B_BASE|OP_C_BASE); + switch (st_op) { + // 0 0000 + case OP_LOAD_E_1: + case OP_LOAD_B_1: + case OP_LOAD_C_1: + case OP_LOAD_D_1: + mm = pr_entity_mode (pr, st, 2); + OPC(int) = MM(int); + break; + case OP_LOAD_E_2: + case OP_LOAD_B_2: + case OP_LOAD_C_2: + case OP_LOAD_D_2: + mm = pr_entity_mode (pr, st, 2); + OPC(ivec2) = MM(ivec2); + break; + case OP_LOAD_E_3: + case OP_LOAD_B_3: + case OP_LOAD_C_3: + case OP_LOAD_D_3: + mm = pr_entity_mode (pr, st, 2); + VectorCopy (&MM(int), &OPC(int)); + break; + case OP_LOAD_E_4: + case OP_LOAD_B_4: + case OP_LOAD_C_4: + case OP_LOAD_D_4: + mm = pr_entity_mode (pr, st, 2); + OPC(ivec4) = MM(ivec4); + break; + // 0 0001 + case OP_STORE_A_1: + case OP_STORE_B_1: + case OP_STORE_C_1: + case OP_STORE_D_1: + mm = pr_address_mode (pr, st, 2); + MM(int) = OPC(int); + break; + case OP_STORE_A_2: + case OP_STORE_B_2: + case OP_STORE_C_2: + case OP_STORE_D_2: + mm = pr_address_mode (pr, st, 2); + MM(ivec2) = OPC(ivec2); + break; + case OP_STORE_A_3: + case OP_STORE_B_3: + case OP_STORE_C_3: + case OP_STORE_D_3: + mm = pr_address_mode (pr, st, 2); + VectorCopy (&OPC(int), &MM(int)); + break; + case OP_STORE_A_4: + case OP_STORE_B_4: + case OP_STORE_C_4: + case OP_STORE_D_4: + mm = pr_address_mode (pr, st, 2); + MM(ivec4) = OPC(ivec4); + break; + // 0 0010 + case OP_PUSH_A_1: + case OP_PUSH_B_1: + case OP_PUSH_C_1: + case OP_PUSH_D_1: + mm = pr_address_mode (pr, st, 2); + stk = pr_stack_push (pr); + STK(int) = MM(int); + break; + case OP_PUSH_A_2: + case OP_PUSH_B_2: + case OP_PUSH_C_2: + case OP_PUSH_D_2: + mm = pr_address_mode (pr, st, 2); + stk = pr_stack_push (pr); + STK(ivec2) = MM(ivec2); + break; + case OP_PUSH_A_3: + case OP_PUSH_B_3: + case OP_PUSH_C_3: + case OP_PUSH_D_3: + mm = pr_address_mode (pr, st, 2); + stk = pr_stack_push (pr); + VectorCopy (&MM(int), &STK(int)); + break; + case OP_PUSH_A_4: + case OP_PUSH_B_4: + case OP_PUSH_C_4: + case OP_PUSH_D_4: + mm = pr_address_mode (pr, st, 2); + stk = pr_stack_push (pr); + STK(ivec4) = MM(ivec4); + break; + // 0 0011 + case OP_POP_A_1: + case OP_POP_B_1: + case OP_POP_C_1: + case OP_POP_D_1: + mm = pr_address_mode (pr, st, 2); + stk = pr_stack_pop (pr); + MM(int) = STK(int); + break; + case OP_POP_A_2: + case OP_POP_B_2: + case OP_POP_C_2: + case OP_POP_D_2: + mm = pr_address_mode (pr, st, 2); + stk = pr_stack_pop (pr); + MM(ivec2) = STK(ivec2); + break; + case OP_POP_A_3: + case OP_POP_B_3: + case OP_POP_C_3: + case OP_POP_D_3: + mm = pr_address_mode (pr, st, 2); + stk = pr_stack_pop (pr); + VectorCopy (&STK(int), &MM(int)); + break; + case OP_POP_A_4: + case OP_POP_B_4: + case OP_POP_C_4: + case OP_POP_D_4: + mm = pr_address_mode (pr, st, 2); + stk = pr_stack_pop (pr); + MM(ivec4) = STK(ivec4); + break; + // 0 0100 + case OP_IFNOT_A: + case OP_IFNOT_B: + case OP_IFNOT_C: + case OP_IFNOT_D: + if (!OPC(int)) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IF_A: + case OP_IF_B: + case OP_IF_C: + case OP_IF_D: + if (OPC(int)) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_JUMP_A: + case OP_JUMP_B: + case OP_JUMP_C: + case OP_JUMP_D: + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + break; + case OP_CALL_A: + case OP_CALL_B: + case OP_CALL_C: + case OP_CALL_D: + mm = pr_address_mode (pr, st, 0); + function = mm->func_var; + pr->pr_argc = 0; + op_call: + pr->pr_xfunction->profile += profile - startprofile; + startprofile = profile; + PR_CallFunction (pr, function); + st = pr->pr_statements + pr->pr_xstatement; + break; + // 0 0101 + case OP_CALL_2: case OP_CALL_3: case OP_CALL_4: + case OP_CALL_5: case OP_CALL_6: case OP_CALL_7: case OP_CALL_8: + pr->pr_params[1] = op_c; + goto op_call_n; + case OP_CALL_1: + pr->pr_params[1] = pr->pr_real_params[1]; + op_call_n: + pr->pr_params[0] = op_b; + function = op_a->func_var; + pr->pr_argc = st->op - OP_CALL_1 + 1; + goto op_call; + case OP_RETURN_4: + memcpy (&R_INT (pr), op_a, 4 * sizeof (*op_a)); + goto op_return; + case OP_RETURN_3: + memcpy (&R_INT (pr), op_a, 3 * sizeof (*op_a)); + goto op_return; + case OP_RETURN_2: + memcpy (&R_INT (pr), op_a, 2 * sizeof (*op_a)); + goto op_return; + case OP_RETURN_1: + memcpy (&R_INT (pr), op_a, 1 * sizeof (*op_a)); + goto op_return; + case OP_RETURN_0: + op_return: + pr->pr_xfunction->profile += profile - startprofile; + startprofile = profile; + PR_LeaveFunction (pr, pr->pr_depth == exitdepth); + st = pr->pr_statements + pr->pr_xstatement; + if (pr->pr_depth== exitdepth) { + if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth) { + pr->pr_trace = false; + } + goto exit_program; + } + break; + case OP_WITH: + pr->pr_bases[st->c] = pr_with (pr, st); + break; + case OP_STATE_ft: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.time + 0.1; + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = op_b->func_var; + } + break; + case OP_STATE_ftt: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.time + OPC(float); + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = op_b->func_var; + } + break; + // 0 0110 + case OP_IFA_A: + case OP_IFA_B: + case OP_IFA_C: + case OP_IFA_D: + if (OPC(int) > 0) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFBE_A: + case OP_IFBE_B: + case OP_IFBE_C: + case OP_IFBE_D: + if (OPC(int) <= 0) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFB_A: + case OP_IFB_B: + case OP_IFB_C: + case OP_IFB_D: + if (OPC(int) < 0) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFAE_A: + case OP_IFAE_B: + case OP_IFAE_C: + case OP_IFAE_D: + if (OPC(int) >= 0) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + // 0 0111 + case OP_DOT_CC_F: + OPC(vec2) = dot2f (OPA(vec2), OPB(vec2)); + break; + case OP_DOT_VV_F: + { + vec_t d = DotProduct (&OPA(float), + &OPB(float)); + VectorSet (d, d, d, &OPC(float)); + } + break; + case OP_DOT_QQ_F: + OPC(vec4) = dotf (OPA(vec4), OPB(vec4)); + break; + case OP_CROSS_VV_F: + { + pr_vec4_t a = loadvec3f (&OPA(float)); + pr_vec4_t b = loadvec3f (&OPB(float)); + pr_vec4_t c = crossf (a, b); + storevec3f (&OPC(float), c); + } + break; + case OP_MUL_CC_F: + OPC(vec2) = cmulf (OPA(vec2), OPB(vec2)); + break; + case OP_MUL_QV_F: + { + pr_vec4_t v = loadvec3f (&OPB(float)); + v = qvmulf (OPA(vec4), v); + storevec3f (&OPC(float), v); + } + break; + case OP_MUL_VQ_F: + { + pr_vec4_t v = loadvec3f (&OPA(float)); + v = vqmulf (v, OPB(vec4)); + storevec3f (&OPC(float), v); + } + break; + case OP_MUL_QQ_F: + OPC(vec4) = qmulf (OPA(vec4), OPB(vec4)); + break; + case OP_DOT_CC_D: + OPC(dvec2) = dot2d (OPA(dvec2), OPB(dvec2)); + break; + case OP_DOT_VV_D: + { + double d = DotProduct (&OPA(double), + &OPB(double)); + VectorSet (d, d, d, &OPC(double)); + } + break; + case OP_DOT_QQ_D: + OPC(dvec4) = dotd (OPA(dvec4), OPB(dvec4)); + break; + case OP_CROSS_VV_D: + { + pr_dvec4_t a = loadvec3d (&OPA(double)); + pr_dvec4_t b = loadvec3d (&OPB(double)); + pr_dvec4_t c = crossd (a, b); + storevec3d (&OPC(double), c); + } + break; + case OP_MUL_CC_D: + OPC(dvec2) = cmuld (OPA(dvec2), OPB(dvec2)); + break; + case OP_MUL_QV_D: + { + pr_dvec4_t v = loadvec3d (&OPB(double)); + v = qvmuld (OPA(dvec4), v); + storevec3d (&OPC(double), v); + } + break; + case OP_MUL_VQ_D: + { + pr_dvec4_t v = loadvec3d (&OPA(double)); + v = vqmuld (v, OPB(dvec4)); + storevec3d (&OPC(double), v); + } + break; + case OP_MUL_QQ_D: + OPC(dvec4) = qmuld (OPA(dvec4), OPB(dvec4)); + break; + +#define OP_cmp_1(OP, T, rt, cmp, ct) \ + case OP_##OP##_##T##_1: \ + OPC(rt) = -(OPA(ct) cmp OPB(ct)); \ + break +#define OP_cmp_2(OP, T, rt, cmp, ct) \ + case OP_##OP##_##T##_2: \ + OPC(rt) = (OPA(ct) cmp OPB(ct)); \ + break +#define OP_cmp_3(OP, T, rt, cmp, ct) \ + case OP_##OP##_##T##_3: \ + VectorCompCompare (&OPC(rt), -, &OPA(ct), cmp, &OPB(ct)); \ + break; +#define OP_cmp_4(OP, T, rt, cmp, ct) \ + case OP_##OP##_##T##_4: \ + OPC(rt) = (OPA(ct) cmp OPB(ct)); \ + break +#define OP_cmp_T(OP, T, rt1, rt2, rt4, cmp, ct1, ct2, ct4) \ + OP_cmp_1 (OP, T, rt1, cmp, ct1); \ + OP_cmp_2 (OP, T, rt2, cmp, ct2); \ + OP_cmp_3 (OP, T, rt1, cmp, ct1); \ + OP_cmp_4 (OP, T, rt4, cmp, ct4) +#define OP_cmp(OP, cmp) \ + OP_cmp_T (OP, I, int, ivec2, ivec4, cmp, int, ivec2, ivec4); \ + OP_cmp_T (OP, F, int, ivec2, ivec4, cmp, float, vec2, vec4); \ + OP_cmp_T (OP, L, long, lvec2, lvec4, cmp, long, lvec2, lvec4); \ + OP_cmp_T (OP, D, long, lvec2, lvec4, cmp, double, dvec2, dvec4) + + // 0 1000 + OP_cmp(EQ, ==); + // 0 1001 + OP_cmp(LT, <); + // 0 1010 + OP_cmp(GT, >); + // 0 1011 + //FIXME conversion 1 + // 0 1100 + OP_cmp(NE, !=); + // 0 1101 + OP_cmp(GE, >=); + // 0 1110 + OP_cmp(LE, <=); + // 0 1011 + //FIXME conversion 2 + +#define OP_op_1(OP, T, t, op) \ + case OP_##OP##_##T##_1: \ + OPC(t) = (OPA(t) op OPB(t)); \ + break +#define OP_op_2(OP, T, t, op) \ + case OP_##OP##_##T##_2: \ + OPC(t) = (OPA(t) op OPB(t)); \ + break +#define OP_op_3(OP, T, t, op) \ + case OP_##OP##_##T##_3: \ + VectorCompOp (&OPC(t), &OPA(t), op, &OPB(t)); \ + break; +#define OP_op_4(OP, T, t, op) \ + case OP_##OP##_##T##_4: \ + OPC(t) = (OPA(t) op OPB(t)); \ + break +#define OP_op_T(OP, T, t1, t2, t4, op) \ + OP_op_1 (OP, T, t1, op); \ + OP_op_2 (OP, T, t2, op); \ + OP_op_3 (OP, T, t1, op); \ + OP_op_4 (OP, T, t4, op) +#define OP_op(OP, op) \ + OP_op_T (OP, I, int, ivec2, ivec4, op); \ + OP_op_T (OP, F, float, vec2, vec4, op); \ + OP_op_T (OP, L, long, lvec2, lvec4, op); \ + OP_op_T (OP, D, double, dvec2, dvec4, op) +#define OP_uop_1(OP, T, t, op) \ + case OP_##OP##_##T##_1: \ + OPC(t) = op (OPA(t)); \ + break +#define OP_uop_2(OP, T, t, op) \ + case OP_##OP##_##T##_2: \ + OPC(t) = op (OPA(t)); \ + break +#define OP_uop_3(OP, T, t, op) \ + case OP_##OP##_##T##_3: \ + VectorCompUop (&OPC(t), op, &OPA(t)); \ + break; +#define OP_uop_4(OP, T, t, op) \ + case OP_##OP##_##T##_4: \ + OPC(t) = op (OPA(t)); \ + break +#define OP_uop_T(OP, T, t1, t2, t4, op) \ + OP_uop_1 (OP, T, t1, op); \ + OP_uop_2 (OP, T, t2, op); \ + OP_uop_3 (OP, T, t1, op); \ + OP_uop_4 (OP, T, t4, op) + + // 1 0000 + OP_op(MUL, *); + // 1 0001 + OP_op(DIV, /); + +#define OP_store(d, s) *(d) = s +#define OP_remmod_T(OP, T, n, t, l, f, s) \ + case OP_##OP##_##T##_##n: \ + { \ + __auto_type a = l (&OPA(t)); \ + __auto_type b = l (&OPB(t)); \ + s (&OPC(t), a - b * f(a / b)); \ + } \ + break +#define OP_rem_T(T, n, t, l, f, s) \ + OP_remmod_T(REM, T, n, t, l, f, s) + + // 1 0010 + OP_op_T (REM, I, int, ivec2, ivec4, %); + OP_rem_T (F, 1, float, *, truncf, OP_store); + OP_rem_T (F, 2, vec2, *, vtrunc2f, OP_store); + OP_rem_T (F, 3, float, loadvec3f, vtrunc4f, storevec3f); + OP_rem_T (F, 4, vec4, *, vtrunc4f, OP_store); + OP_op_T (REM, L, long, lvec2, lvec4, %); + OP_rem_T (D, 1, double, *, trunc, OP_store); + OP_rem_T (D, 2, dvec2, *, vtrunc2d, OP_store); + OP_rem_T (D, 3, double, loadvec3d, vtrunc4d, storevec3d); + OP_rem_T (D, 4, dvec4, *, vtrunc4d, OP_store); + +// implement true modulo for integers: +// 5 mod 3 = 2 +// -5 mod 3 = 1 +// 5 mod -3 = -1 +// -5 mod -3 = -2 +#define OP_mod_Ti(T, n, t, l, m, s) \ + case OP_MOD_##T##_##n: \ + { \ + __auto_type a = l(&OPA(t)); \ + __auto_type b = l(&OPB(t)); \ + __auto_type c = a % b; \ + /* % is really remainder and so has the same sign rules */\ + /* as division: -5 % 3 = -2, so need to add b (3 here) */\ + /* if c's sign is incorrect, but only if c is non-zero */\ + __auto_type mask = m((a ^ b) < 0); \ + mask &= m(c != 0); \ + s(&OPC(t), c + (mask & b)); \ + } \ + break +// floating point modulo is so much easier :P (just use floor instead of trunc) +#define OP_mod_Tf(T, n, t, l, f, s) \ + OP_remmod_T(MOD, T, n, t, l, f, s) + + // 1 0011 + OP_mod_Ti (I, 1, int, *, -, OP_store); + OP_mod_Ti (I, 2, ivec2, *, +, OP_store); + OP_mod_Ti (I, 3, int, loadvec3i, +, storevec3i); + OP_mod_Ti (I, 4, ivec4, *, +, OP_store); + OP_mod_Tf (F, 1, float, *, floorf, OP_store); + OP_mod_Tf (F, 2, vec2, *, vfloor2f, OP_store); + OP_mod_Tf (F, 3, float, loadvec3f, vfloor4f, storevec3f); + OP_mod_Tf (F, 4, vec4, *, vfloor4f, OP_store); + OP_mod_Ti (L, 1, long, *, -, OP_store); + OP_mod_Ti (L, 2, ivec2, *, +, OP_store); + OP_mod_Ti (L, 3, long, loadvec3l, +, storevec3l); + OP_mod_Ti (L, 4, ivec4, *, +, OP_store); + OP_mod_Tf (D, 1, double, *, floor, OP_store); + OP_mod_Tf (D, 2, dvec2, *, vfloor2d, OP_store); + OP_mod_Tf (D, 3, double, loadvec3d, vfloor4d, storevec3d); + OP_mod_Tf (D, 4, dvec4, *, vfloor4d, OP_store); + + // 1 0100 + OP_op(ADD, +); + // 1 0101 + OP_op(SUB, -); + // 1 0110 + OP_op_T (SHL, I, int, ivec2, ivec4, <<); + OP_op_T (SHL, L, long, lvec2, lvec4, <<); + case OP_EQ_S: + case OP_LT_S: + case OP_GT_S: + case OP_CMP_S: + case OP_GE_S: + case OP_LE_S: + { + int cmp = strcmp (PR_GetString (pr, OPA(string)), + PR_GetString (pr, OPB(string))); + switch (st_op) { + case OP_EQ_S: cmp = (cmp == 0); break; + case OP_LT_S: cmp = (cmp < 0); break; + case OP_GT_S: cmp = (cmp > 0); break; + case OP_GE_S: cmp = (cmp >= 0); break; + case OP_LE_S: cmp = (cmp <= 0); break; + case OP_NOT_S: break; + default: break; + } + OPC(int) = cmp; + } + break; + case OP_ADD_S: + OPC(string) = PR_CatStrings(pr, PR_GetString (pr, OPA(string)), + PR_GetString (pr, OPB(string))); + break; + case OP_NOT_S: + OPC(int) = !OPA(string) || !*PR_GetString (pr, OPA(string)); + break; + // 1 0111 + OP_op_T (SHR, I, int, ivec2, ivec4, >>); + OP_op_T (SHR, u, uint, uivec2, uivec4, >>); + OP_op_T (SHR, L, long, lvec2, lvec4, >>); + OP_op_T (SHR, U, ulong, ulvec2, ulvec4, >>); + // 1 1000 + OP_op_T (BITAND, I, int, ivec2, ivec4, &); + OP_op_T (BITOR, I, int, ivec2, ivec4, |); + OP_op_T (BITXOR, I, int, ivec2, ivec4, ^); + OP_uop_T (BITNOT, I, int, ivec2, ivec4, ~); + // 1 1001 + OP_op_T (LT, u, uint, uivec2, uivec4, <); + //FIXME float ops + OP_op_T (LT, U, ulong, ulvec2, ulvec4, <); + //FIXME float ops + // 1 1010 + OP_op_T (GT, u, uint, uivec2, uivec4, >); + //FIXME misc ops + OP_op_T (GT, U, ulong, ulvec2, ulvec4, >); + //FIXME misc ops + // 1 1011 + case OP_LEA_A: + case OP_LEA_B: + case OP_LEA_C: + case OP_LEA_D: + mm = pr_address_mode (pr, st, 0); + op_c->pointer_var = mm - pr->pr_globals; + break; + case OP_LEA_E: + // ensures OP_LEA_E is compatible with OP_LOAD_E_n and thus + // with pr_entity_mode + mm = __builtin_choose_expr ( + (OP_LEA_E & 3) == 0, + pr_entity_mode (pr, st, 0), + (void) 0); + op_c->pointer_var = mm - pr->pr_globals; + break; + case OP_ANY_2: + OPC(int) = any2i (OPA(ivec2)); + break; + case OP_ANY_3: + { + __auto_type v = loadvec3i (&OPA(int)); + OPC(int) = any4i (v); + } + break; + case OP_ANY_4: + OPC(int) = any4i (OPA(ivec4)); + break; + case OP_PUSHREG: + stk = pr_stack_push (pr); + STK(uivec4) = pr->pr_bases; + break; + case OP_ALL_2: + OPC(int) = all2i (OPA(ivec2)); + break; + case OP_ALL_3: + { + __auto_type v = loadvec3i (&OPA(int)); + v[3] = -1; + OPC(int) = all4i (v); + } + break; + case OP_ALL_4: + OPC(int) = all4i (OPA(ivec4)); + break; + case OP_POPREG: + stk = pr_stack_pop (pr); + pr->pr_bases = STK(uivec4); + break; + case OP_NONE_2: + OPC(int) = none2i (OPA(ivec2)); + break; + case OP_NONE_3: + { + __auto_type v = loadvec3i (&OPA(int)); + OPC(int) = none4i (v); + } + break; + case OP_NONE_4: + OPC(int) = none4i (OPA(ivec4)); + break; + +#define OP_bool_n(OP, t, n, op, m) \ + case OP_##OP##_I_##n: \ + OPC(t) = m((OPA(t) != 0) op (OPB(t) != 0)); \ + break +#define OP_bool_3(OP, t, n, op, m) \ + case OP_##OP##_I_##n: \ + { \ + __auto_type a = loadvec3i (&OPA(int)); \ + __auto_type b = loadvec3i (&OPB(int)); \ + storevec3i (&OPC(int), (a != 0) op (b != 0)); \ + } \ + break +#define OP_bool(OP, op) \ + OP_bool_n (OP, int, 1, op, -); \ + OP_bool_n (OP, ivec2, 2, op, +); \ + OP_bool_3 (OP, int, 3, op, +); \ + OP_bool_n (OP, ivec4, 4, op, +) +#define OP_not_n(OP, t, n, m) \ + case OP_##OP##_I_##n: \ + OPC(t) = m((OPA(t) == 0)); \ + break +#define OP_not_3(OP, t, n, m) \ + case OP_##OP##_I_##n: \ + { \ + __auto_type a = loadvec3i (&OPA(int)); \ + storevec3i (&OPC(int), (a == 0)); \ + } \ + break + // 1 1100 + OP_bool (AND, &); + OP_bool (OR, |); + OP_bool (XOR, ^); + OP_not_n (NOT, int, 1, -); + OP_not_n (NOT, ivec2, 2, +); + OP_not_3 (NOT, int, 3, +); + OP_not_n (NOT, ivec4, 4, +); + // 1 1101 + OP_op_T (GE, u, uint, uivec2, uivec4, >=); + //FIXME float shift + case OP_MOVE_I: + memmove (op_c, op_a, st->b * sizeof (pr_type_t)); + break; + case OP_MOVE_P: + memmove (pr->pr_globals + OPC(int), pr->pr_globals + OPA(int), + OPB(uint) * sizeof (pr_type_t)); + break; + case OP_MOVE_PI: + memmove (pr->pr_globals + OPC(int), pr->pr_globals + OPA(int), + st->b * sizeof (pr_type_t)); + break; + OP_op_T (GE, U, ulong, ulvec2, ulvec4, >=); + //FIXME float shift + case OP_MEMSET_I: + memset (op_c, OPA(int), st->b * sizeof (pr_type_t)); + break; + case OP_MEMSET_P: + memset (pr->pr_globals + OPC(int), OPA(int), + OPB(uint) * sizeof (pr_type_t)); + break; + case OP_MEMSET_PI: + memset (pr->pr_globals + OPC(int), OPA(int), + st->b * sizeof (pr_type_t)); + break; + // 1 1110 + OP_op_T (LE, u, uint, uivec2, uivec4, <=); + //FIXME misc ops + OP_op_T (LE, U, ulong, ulvec2, ulvec4, <=); + //FIXME misc ops + // 1 1111 + //FIXME conversion 3 + + default: + PR_RunError (pr, "Bad opcode %i", st->op); + } + if (pr->watch && pr->watch->integer_var != old_val.integer_var) { + if (!pr->wp_conditional + || pr->watch->integer_var == pr->wp_val.integer_var) { + if (pr->debug_handler) { + pr->debug_handler (prd_watchpoint, 0, pr->debug_data); + } else { + PR_RunError (pr, "watchpoint hit: %d -> %d", + old_val.integer_var, pr->watch->integer_var); + } + } + old_val.integer_var = pr->watch->integer_var; + } + } +exit_program: +} /* PR_ExecuteProgram @@ -1735,6 +2652,8 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) } if (1) { pr_exec_quakec (pr, exitdepth); + } else { + pr_exec_ruamoko (pr, exitdepth); } exit_program: if (pr->debug_handler) { diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 17d640575..f2710d446 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -1544,7 +1544,7 @@ is_vector_parameter_store (progs_t *pr, dstatement_t *st, { int i; - if (st->op != OP_STORE_V_v6p) + if ((pr_opcode_v6p_e) st->op != OP_STORE_V_v6p) return 0; if (operand != st->a) return 0; @@ -1653,13 +1653,15 @@ PR_Check_Opcodes (progs_t *pr) if (0 && !pr_boundscheck->int_val) { for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; st++, i++) { - op = PR_v6p_Opcode (st->op); + pr_opcode_v6p_e st_op = st->op; + op = PR_v6p_Opcode (st_op); if (!op) { PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " - "statement %ld", st->op, + "statement %ld", st_op, (long)(st - pr->pr_statements)); } - if ((st->op == OP_STATE_v6p || st->op == OP_STATE_F_v6p) && !state_ok) { + if ((st_op == OP_STATE_v6p || st_op == OP_STATE_F_v6p) + && !state_ok) { PR_Error (pr, "PR_Check_Opcodes: %s used with missing fields " "or globals", op->opname); } @@ -1672,13 +1674,14 @@ PR_Check_Opcodes (progs_t *pr) } else { for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; st++, i++) { - op = PR_v6p_Opcode (st->op); + pr_opcode_v6p_e st_op = st->op; + op = PR_v6p_Opcode (st_op); if (!op) { PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " - "statement %ld", st->op, + "statement %ld", st_op, (long)(st - pr->pr_statements)); } - switch (st->op) { + switch (st_op) { case OP_IF_v6p: case OP_IFNOT_v6p: check_global (pr, st, op, op->type_a, st->a, 1); @@ -1702,7 +1705,7 @@ PR_Check_Opcodes (progs_t *pr) case OP_RCALL6_v6p: case OP_RCALL7_v6p: case OP_RCALL8_v6p: - if (st->op > OP_RCALL1_v6p) + if (st_op > OP_RCALL1_v6p) check_global (pr, st, op, ev_integer, st->c, 1); check_global (pr, st, op, ev_integer, st->b, 1); check_global (pr, st, op, ev_func, st->a, 1); From 8a2788c267ca76eb31d1f76bc0181d27ed560b26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 13:56:43 +0900 Subject: [PATCH 2090/3664] [gamecode] Add PROG_V6P_VERSION and bump PROG_VERSION This allows the VM to select the right execution loop and qfcc currently still produces only the old IS (it doesn't know how to deal with the new IS yet) --- include/QF/pr_comp.h | 3 +- libs/gamecode/pr_exec.c | 2 +- libs/gamecode/pr_load.c | 1 + libs/gamecode/pr_opcode.c | 442 ++++++++++++++++++------------------ libs/gamecode/pr_strings.c | 5 +- tools/qfcc/source/options.c | 6 +- tools/qfcc/source/pragma.c | 2 +- 7 files changed, 233 insertions(+), 228 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 84cc7e755..df81d606f 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -693,7 +693,8 @@ typedef struct pr_va_list_s { |(((0x##b) & 0xfff) << 12) \ |(((0x##c) & 0xfff) << 0) ) #define PROG_ID_VERSION 6 -#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,00a) +#define PROG_V6P_VERSION PROG_VERSION_ENCODE(0,fff,00a) +#define PROG_VERSION PROG_VERSION_ENCODE(0,fff,010) typedef struct dprograms_s { pr_uint_t version; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 3aa973620..ad5808107 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2650,7 +2650,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) // called a builtin instead of progs code goto exit_program; } - if (1) { + if (pr->progs->version < PROG_VERSION) { pr_exec_quakec (pr, exitdepth); } else { pr_exec_ruamoko (pr, exitdepth); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 40f99dd84..95626fc22 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -145,6 +145,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) ((int *) &progs)[i] = LittleLong (((int *) &progs)[i]); if (progs.version != PROG_VERSION + && progs.version != PROG_V6P_VERSION && progs.version != PROG_ID_VERSION) { if (progs.version < 0x00fff000) { PR_Error (pr, "%s has unrecognised version number (%u)", diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index f2710d446..aff4784de 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -105,7 +105,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { [OP_MUL_D_v6p] = {"*", "mul.d", ev_double, ev_double, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MUL_F_v6p] = {"*", "mul.f", ev_float, ev_float, ev_float, @@ -133,32 +133,32 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_MUL_Q_v6p] = {"*", "mul.q", ev_quat, ev_quat, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MUL_FQ_v6p] = {"*", "mul.fq", ev_float, ev_quat, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MUL_QF_v6p] = {"*", "mul.qf", ev_quat, ev_float, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MUL_DQ_v6p] = {"*", "mul.dq", ev_double, ev_quat, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MUL_QD_v6p] = {"*", "mul.qd", ev_quat, ev_double, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MUL_QV_v6p] = {"*", "mul.qv", ev_quat, ev_vector, ev_vector, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_CONJ_Q_v6p] = {"~", "conj.q", ev_quat, ev_invalid, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, @@ -168,20 +168,20 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_DIV_D_v6p] = {"/", "div.d", ev_double, ev_double, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_REM_D_v6p] = {"%", "rem.d", ev_double, ev_double, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MOD_D_v6p] = {"%%", "mod.d", ev_double, ev_double, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_ADD_D_v6p] = {"+", "add.d", ev_double, ev_double, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_ADD_F_v6p] = {"+", "add.f", ev_float, ev_float, ev_float, @@ -193,16 +193,16 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_ADD_Q_v6p] = {"+", "add.q", ev_quat, ev_quat, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_ADD_S_v6p] = {"+", "add.s", ev_string, ev_string, ev_string, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_SUB_D_v6p] = {"-", "sub.d", ev_double, ev_double, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_SUB_F_v6p] = {"-", "sub.f", ev_float, ev_float, ev_float, @@ -214,12 +214,12 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_SUB_Q_v6p] = {"-", "sub.q", ev_quat, ev_quat, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_EQ_D_v6p] = {"==", "eq.d", ev_double, ev_double, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_EQ_F_v6p] = {"==", "eq.f", ev_float, ev_float, ev_integer, @@ -231,7 +231,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_EQ_Q_v6p] = {"==", "eq.q", ev_quat, ev_quat, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_EQ_S_v6p] = {"==", "eq.s", ev_string, ev_string, ev_integer, @@ -248,7 +248,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { [OP_NE_D_v6p] = {"!=", "ne.d", ev_double, ev_double, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_NE_F_v6p] = {"!=", "ne.f", ev_float, ev_float, ev_integer, @@ -260,7 +260,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_NE_Q_v6p] = {"!=", "ne.q", ev_quat, ev_quat, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_NE_S_v6p] = {"!=", "ne.s", ev_string, ev_string, ev_integer, @@ -277,7 +277,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { [OP_LE_D_v6p] = {"<=", "le.d", ev_double, ev_double, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LE_F_v6p] = {"<=", "le.f", ev_float, ev_float, ev_integer, @@ -285,7 +285,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_GE_D_v6p] = {">=", "ge.d", ev_double, ev_double, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_GE_F_v6p] = {">=", "ge.f", ev_float, ev_float, ev_integer, @@ -293,15 +293,15 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_LE_S_v6p] = {"<=", "le.s", ev_string, ev_string, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_GE_S_v6p] = {">=", "ge.s", ev_string, ev_string, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LT_D_v6p] = {"<", "lt.d", ev_double, ev_double, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LT_F_v6p] = {"<", "lt.f", ev_float, ev_float, ev_integer, @@ -309,7 +309,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_GT_D_v6p] = {">", "gt.d", ev_double, ev_double, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_GT_F_v6p] = {">", "gt.f", ev_float, ev_float, ev_integer, @@ -317,11 +317,11 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_LT_S_v6p] = {"<", "lt.s", ev_string, ev_string, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_GT_S_v6p] = {">", "gt.s", ev_string, ev_string, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LOAD_F_v6p] = {".", "load.f", @@ -331,7 +331,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_LOAD_D_v6p] = {".", "load.d", ev_entity, ev_field, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, [OP_LOAD_V_v6p] = {".", "load.v", @@ -341,7 +341,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_LOAD_Q_v6p] = {".", "load.q", ev_entity, ev_field, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, [OP_LOAD_S_v6p] = {".", "load.s", @@ -366,114 +366,114 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_LOAD_I_v6p] = {".", "load.i", ev_entity, ev_field, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, [OP_LOAD_P_v6p] = {".", "load.p", ev_entity, ev_field, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, [OP_LOADB_D_v6p] = {".", "loadb.d", ev_pointer, ev_integer, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_F_v6p] = {".", "loadb.f", ev_pointer, ev_integer, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_V_v6p] = {".", "loadb.v", ev_pointer, ev_integer, ev_vector, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_Q_v6p] = {".", "loadb.q", ev_pointer, ev_integer, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_S_v6p] = {".", "loadb.s", ev_pointer, ev_integer, ev_string, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_ENT_v6p] = {".", "loadb.ent", ev_pointer, ev_integer, ev_entity, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_FLD_v6p] = {".", "loadb.fld", ev_pointer, ev_integer, ev_field, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_FN_v6p] = {".", "loadb.fn", ev_pointer, ev_integer, ev_func, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_I_v6p] = {".", "loadb.i", ev_pointer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_P_v6p] = {".", "loadb.p", ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADBI_D_v6p] = {".", "loadbi.d", ev_pointer, ev_short, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_F_v6p] = {".", "loadbi.f", ev_pointer, ev_short, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_V_v6p] = {".", "loadbi.v", ev_pointer, ev_short, ev_vector, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_Q_v6p] = {".", "loadbi.q", ev_pointer, ev_short, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_S_v6p] = {".", "loadbi.s", ev_pointer, ev_short, ev_string, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_ENT_v6p] = {".", "loadbi.ent", ev_pointer, ev_short, ev_entity, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_FLD_v6p] = {".", "loadbi.fld", ev_pointer, ev_short, ev_field, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_FN_v6p] = {".", "loadbi.fn", ev_pointer, ev_short, ev_func, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_I_v6p] = {".", "loadbi.i", ev_pointer, ev_short, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_P_v6p] = {".", "loadbi.p", ev_pointer, ev_short, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, @@ -485,105 +485,105 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { [OP_ADDRESS_VOID_v6p] = {"&", "address", ev_void, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_D_v6p] = {"&", "address.d", ev_double, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_F_v6p] = {"&", "address.f", ev_float, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_V_v6p] = {"&", "address.v", ev_vector, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_Q_v6p] = {"&", "address.q", ev_quat, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_S_v6p] = {"&", "address.s", ev_string, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_ENT_v6p] = {"&", "address.ent", ev_entity, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_FLD_v6p] = {"&", "address.fld", ev_field, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_FN_v6p] = {"&", "address.fn", ev_func, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_I_v6p] = {"&", "address.i", ev_integer, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_P_v6p] = {"&", "address.p", ev_pointer, ev_invalid, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_LEA_v6p] = {"&", "lea", ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "(%Ga + %Gb), %gc", }, [OP_LEAI_v6p] = {"&", "leai", ev_pointer, ev_short, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "(%Ga + %sb), %gc", }, [OP_CONV_IF_v6p] = {"", "conv.if", ev_integer, ev_invalid, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_CONV_FI_v6p] = {"", "conv.fi", ev_float, ev_invalid, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_CONV_ID_v6p] = {"", "conv.id", ev_integer, ev_invalid, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_CONV_DI_v6p] = {"", "conv.di", ev_double, ev_invalid, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_CONV_FD_v6p] = {"", "conv.fd", ev_float, ev_invalid, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_CONV_DF_v6p] = {"", "conv.df", ev_double, ev_invalid, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_STORE_D_v6p] = {"=", "store.d", ev_double, ev_double, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gb", }, [OP_STORE_F_v6p] = {"=", "store.f", @@ -598,7 +598,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_STORE_Q_v6p] = {"=", "store.q", ev_quat, ev_quat, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gb", }, [OP_STORE_S_v6p] = {"=", "store.s", @@ -623,12 +623,12 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_STORE_I_v6p] = {"=", "store.i", ev_integer, ev_integer, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gb", }, [OP_STORE_P_v6p] = {"=", "store.p", ev_pointer, ev_pointer, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gb", }, @@ -649,7 +649,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_STOREP_Q_v6p] = {".=", "storep.q", ev_quat, ev_pointer, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *%Gb", }, [OP_STOREP_S_v6p] = {".=", "storep.s", @@ -674,114 +674,114 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_STOREP_I_v6p] = {".=", "storep.i", ev_integer, ev_pointer, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *%Gb", }, [OP_STOREP_P_v6p] = {".=", "storep.p", ev_pointer, ev_pointer, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *%Gb", }, [OP_STOREB_D_v6p] = {".=", "storeb.d", ev_double, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_F_v6p] = {".=", "storeb.f", ev_float, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_V_v6p] = {".=", "storeb.v", ev_vector, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_Q_v6p] = {".=", "storeb.q", ev_quat, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_S_v6p] = {".=", "storeb.s", ev_string, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_ENT_v6p] = {".=", "storeb.ent", ev_entity, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_FLD_v6p] = {".=", "storeb.fld", ev_field, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_FN_v6p] = {".=", "storeb.fn", ev_func, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_I_v6p] = {".=", "storeb.i", ev_integer, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_P_v6p] = {".=", "storeb.p", ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREBI_D_v6p] = {".=", "storebi.d", ev_double, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_F_v6p] = {".=", "storebi.f", ev_float, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_V_v6p] = {".=", "storebi.v", ev_vector, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_Q_v6p] = {".=", "storebi.q", ev_quat, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_S_v6p] = {".=", "storebi.s", ev_string, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_ENT_v6p] = {".=", "storebi.ent", ev_entity, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_FLD_v6p] = {".=", "storebi.fld", ev_field, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_FN_v6p] = {".=", "storebi.fn", ev_func, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_I_v6p] = {".=", "storebi.i", ev_integer, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_P_v6p] = {".=", "storebi.p", ev_pointer, ev_pointer, ev_short, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, @@ -793,13 +793,13 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { [OP_RETURN_V_v6p] = {"", "return", ev_invalid, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "", }, [OP_NOT_D_v6p] = {"!", "not.d", ev_double, ev_invalid, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_NOT_F_v6p] = {"!", "not.f", @@ -814,7 +814,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_NOT_Q_v6p] = {"!", "not.q", ev_quat, ev_invalid, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_NOT_S_v6p] = {"!", "not.s", @@ -834,7 +834,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_NOT_P_v6p] = {"!", "not.p", ev_pointer, ev_invalid, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, @@ -850,22 +850,22 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_IFBE_v6p] = {"", "ifbe", ev_integer, ev_short, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, [OP_IFB_v6p] = {"", "ifb", ev_integer, ev_short, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, [OP_IFAE_v6p] = {"", "ifae", ev_integer, ev_short, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, [OP_IFA_v6p] = {"", "ifa", ev_integer, ev_short, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, @@ -922,42 +922,42 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_RCALL1_v6p] = {"", "rcall1", ev_func, ev_void, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Fa (%P0b)", }, [OP_RCALL2_v6p] = {"", "rcall2", ev_func, ev_void, ev_void, - PROG_VERSION, + PROG_V6P_VERSION, "%Fa (%P0b, %P1c)", }, [OP_RCALL3_v6p] = {"", "rcall3", ev_func, ev_void, ev_void, - PROG_VERSION, + PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x)", }, [OP_RCALL4_v6p] = {"", "rcall4", ev_func, ev_void, ev_void, - PROG_VERSION, + PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x)", }, [OP_RCALL5_v6p] = {"", "rcall5", ev_func, ev_void, ev_void, - PROG_VERSION, + PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", }, [OP_RCALL6_v6p] = {"", "rcall6", ev_func, ev_void, ev_void, - PROG_VERSION, + PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", }, [OP_RCALL7_v6p] = {"", "rcall7", ev_func, ev_void, ev_void, - PROG_VERSION, + PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", }, [OP_RCALL8_v6p] = {"", "rcall8", ev_func, ev_void, ev_void, - PROG_VERSION, + PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, @@ -969,7 +969,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { [OP_STATE_F_v6p] = {"", "state.f", ev_float, ev_func, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, @@ -980,12 +980,12 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_JUMP_v6p] = {"", "jump", ev_integer, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_JUMPB_v6p] = {"", "jumpb", ev_void, ev_integer, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga[%Gb]", }, @@ -1000,23 +1000,23 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { [OP_SHL_F_v6p] = {"<<", "shl.f", ev_float, ev_float, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_SHR_F_v6p] = {">>", "shr.f", ev_float, ev_float, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_SHL_I_v6p] = {"<<", "shl.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_SHR_I_v6p] = {">>", "shr.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_SHR_U_v6p] = {">>", "shr.u", ev_uinteger, ev_integer, ev_uinteger, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_BITAND_v6p] = {"&", "bitand", @@ -1030,481 +1030,481 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { [OP_ADD_I_v6p] = {"+", "add.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_SUB_I_v6p] = {"-", "sub.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MUL_I_v6p] = {"*", "mul.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_DIV_I_v6p] = {"/", "div.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_REM_I_v6p] = {"%", "rem.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MOD_I_v6p] = {"%%", "mod.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_BITAND_I_v6p] = {"&", "bitand.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_BITOR_I_v6p] = {"|", "bitor.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_REM_F_v6p] = {"%", "rem.f", ev_float, ev_float, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MOD_F_v6p] = {"%%", "mod.f", ev_float, ev_float, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_GE_I_v6p] = {">=", "ge.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LE_I_v6p] = {"<=", "le.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_GT_I_v6p] = {">", "gt.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LT_I_v6p] = {"<", "lt.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_AND_I_v6p] = {"&&", "and.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_OR_I_v6p] = {"||", "or.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_NOT_I_v6p] = {"!", "not.i", ev_integer, ev_invalid, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_EQ_I_v6p] = {"==", "eq.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_NE_I_v6p] = {"!=", "ne.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_GE_U_v6p] = {">=", "ge.u", ev_uinteger, ev_uinteger, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LE_U_v6p] = {"<=", "le.u", ev_uinteger, ev_uinteger, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_GT_U_v6p] = {">", "gt.u", ev_uinteger, ev_uinteger, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LT_U_v6p] = {"<", "lt.u", ev_uinteger, ev_uinteger, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_BITXOR_F_v6p] = {"^", "bitxor.f", ev_float, ev_float, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_BITNOT_F_v6p] = {"~", "bitnot.f", ev_float, ev_invalid, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_BITXOR_I_v6p] = {"^", "bitxor.i", ev_integer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_BITNOT_I_v6p] = {"~", "bitnot.i", ev_integer, ev_invalid, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %gc", }, [OP_GE_P_v6p] = {">=", "ge.p", ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LE_P_v6p] = {"<=", "le.p", ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_GT_P_v6p] = {">", "gt.p", ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_LT_P_v6p] = {"<", "lt.p", ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_EQ_P_v6p] = {"==", "eq.p", ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_NE_P_v6p] = {"!=", "ne.p", ev_pointer, ev_pointer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, }, [OP_MOVEI_v6p] = {"", "movei", ev_void, ev_short, ev_void, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %sb, %gc", }, [OP_MOVEP_v6p] = {"", "movep", ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, [OP_MOVEPI_v6p] = {"", "movepi", ev_pointer, ev_short, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %sb, %Gc", }, [OP_MEMSETI_v6p] = {"", "memseti", ev_integer, ev_short, ev_void, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %sb, %gc", }, [OP_MEMSETP_v6p] = {"", "memsetp", ev_integer, ev_integer, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, [OP_MEMSETPI_v6p] = {"", "memsetpi", ev_integer, ev_short, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga, %sb, %Gc", }, [OP_PUSH_S_v6p] = {"", "push.s", ev_string, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSH_F_v6p] = {"", "push.f", ev_float, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSH_V_v6p] = {"", "push.v", ev_vector, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSH_ENT_v6p] = {"", "push.ent", ev_entity, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSH_FLD_v6p] = {"", "push.fld", ev_field, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSH_FN_v6p] = {"", "push.fn", ev_func, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSH_P_v6p] = {"", "push.p", ev_pointer, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSH_Q_v6p] = {"", "push.q", ev_quat, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSH_I_v6p] = {"", "push.i", ev_integer, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSH_D_v6p] = {"", "push.d", ev_double, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%Ga", }, [OP_PUSHB_S_v6p] = {"", "pushb.s", ev_pointer, ev_integer, ev_string, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_F_v6p] = {"", "pushb.f", ev_pointer, ev_integer, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_V_v6p] = {"", "pushb.v", ev_pointer, ev_integer, ev_vector, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_ENT_v6p] = {"", "pushb.ent", ev_pointer, ev_integer, ev_entity, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_FLD_v6p] = {"", "pushb.fld", ev_pointer, ev_integer, ev_field, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_FN_v6p] = {"", "pushb.fn", ev_pointer, ev_integer, ev_func, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_P_v6p] = {"", "pushb.p", ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_Q_v6p] = {"", "pushb.q", ev_pointer, ev_integer, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_I_v6p] = {"", "pushb.i", ev_pointer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_D_v6p] = {"", "pushb.d", ev_pointer, ev_integer, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHBI_S_v6p] = {"", "pushbi.s", ev_pointer, ev_short, ev_string, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_F_v6p] = {"", "pushbi.f", ev_pointer, ev_short, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_V_v6p] = {"", "pushbi.v", ev_pointer, ev_short, ev_vector, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_ENT_v6p] = {"", "pushbi.ent", ev_pointer, ev_short, ev_entity, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_FLD_v6p] = {"", "pushbi.fld", ev_pointer, ev_short, ev_field, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_FN_v6p] = {"", "pushbi.fn", ev_pointer, ev_short, ev_func, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_P_v6p] = {"", "pushbi.p", ev_pointer, ev_short, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_Q_v6p] = {"", "pushbi.q", ev_pointer, ev_short, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_I_v6p] = {"", "pushbi.i", ev_pointer, ev_short, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_D_v6p] = {"", "pushbi.d", ev_pointer, ev_short, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POP_S_v6p] = {"", "pop.s", ev_string, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POP_F_v6p] = {"", "pop.f", ev_float, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POP_V_v6p] = {"", "pop.v", ev_vector, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POP_ENT_v6p] = {"", "pop.ent", ev_entity, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POP_FLD_v6p] = {"", "pop.fld", ev_field, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POP_FN_v6p] = {"", "pop.fn", ev_func, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POP_P_v6p] = {"", "pop.p", ev_pointer, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POP_Q_v6p] = {"", "pop.q", ev_quat, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POP_I_v6p] = {"", "pop.i", ev_integer, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POP_D_v6p] = {"", "pop.d", ev_double, ev_invalid, ev_invalid, - PROG_VERSION, + PROG_V6P_VERSION, "%ga", }, [OP_POPB_S_v6p] = {"", "popb.s", ev_pointer, ev_integer, ev_string, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_F_v6p] = {"", "popb.f", ev_pointer, ev_integer, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_V_v6p] = {"", "popb.v", ev_pointer, ev_integer, ev_vector, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_ENT_v6p] = {"", "popb.ent", ev_pointer, ev_integer, ev_entity, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_FLD_v6p] = {"", "popb.fld", ev_pointer, ev_integer, ev_field, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_FN_v6p] = {"", "popb.fn", ev_pointer, ev_integer, ev_func, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_P_v6p] = {"", "popb.p", ev_pointer, ev_integer, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_Q_v6p] = {"", "popb.q", ev_pointer, ev_integer, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_I_v6p] = {"", "popb.i", ev_pointer, ev_integer, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_D_v6p] = {"", "popb.d", ev_pointer, ev_integer, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPBI_S_v6p] = {"", "popbi.s", ev_pointer, ev_short, ev_string, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_F_v6p] = {"", "popbi.f", ev_pointer, ev_short, ev_float, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_V_v6p] = {"", "popbi.v", ev_pointer, ev_short, ev_vector, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_ENT_v6p] = {"", "popbi.ent", ev_pointer, ev_short, ev_entity, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_FLD_v6p] = {"", "popbi.fld", ev_pointer, ev_short, ev_field, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_FN_v6p] = {"", "popbi.fn", ev_pointer, ev_short, ev_func, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_P_v6p] = {"", "popbi.p", ev_pointer, ev_short, ev_pointer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_Q_v6p] = {"", "popbi.q", ev_pointer, ev_short, ev_quat, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_I_v6p] = {"", "popbi.i", ev_pointer, ev_short, ev_integer, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_D_v6p] = {"", "popbi.d", ev_pointer, ev_short, ev_double, - PROG_VERSION, + PROG_V6P_VERSION, "*(%Ga + %sb)", }, diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index ba53acac8..f2e5237a6 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -242,13 +242,16 @@ PR_LoadStrings (progs_t *pr) while (str < end) { count++; - if (*str == '@' && pr->progs->version == PROG_VERSION) { + if (*str == '@' && pr->progs->version == PROG_V6P_VERSION) { if (!strcmp (str, "@float_promoted@")) { pr->float_promoted = 1; } } str += strlen (str) + 1; } + if (pr->progs->version == PROG_VERSION) { + pr->float_promoted = 1; + } res->ds_mem.alloc = pr_strings_alloc; res->ds_mem.free = pr_strings_free; diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 09989684c..671d3aa85 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -398,7 +398,7 @@ DecodeArgs (int argc, char **argv) case OPT_ADVANCED: options.traditional = 0; options.advanced = true; - options.code.progsversion = PROG_VERSION; + options.code.progsversion = PROG_V6P_VERSION; options.code.const_initializers = false; break; case OPT_BLOCK_DOT: @@ -505,7 +505,7 @@ DecodeArgs (int argc, char **argv) if (flag) options.code.progsversion = PROG_ID_VERSION; else - options.code.progsversion = PROG_VERSION; + options.code.progsversion = PROG_V6P_VERSION; } else if (!(strcasecmp (temp, "const-initializers"))) { options.code.const_initializers = flag; } @@ -699,7 +699,7 @@ DecodeArgs (int argc, char **argv) options.code.vector_components = true; } if (!options.code.progsversion) - options.code.progsversion = PROG_VERSION; + options.code.progsversion = PROG_V6P_VERSION; if (!options.traditional) { options.advanced = true; add_cpp_def ("-D__RUAMOKO__=1"); diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index d82f2aef4..edabcaaf4 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -65,7 +65,7 @@ set_traditional (int traditional) case 0: options.traditional = 0; options.advanced = true; - options.code.progsversion = PROG_VERSION; + options.code.progsversion = PROG_V6P_VERSION; type_default = &type_integer; break; case 1: From 920c5fd99b2226f2c7bf7126ffc0386e90447cc9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 14:39:32 +0900 Subject: [PATCH 2091/3664] [gamecode] Add debug event name strings Makes it easier to print nice debug event messages. --- include/QF/pr_debug.h | 2 ++ libs/gamecode/pr_exec.c | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/QF/pr_debug.h b/include/QF/pr_debug.h index 4015f6f65..94c164fe5 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/pr_debug.h @@ -75,6 +75,8 @@ typedef struct pr_debug_header_s { pr_uint_t debug_data; pr_uint_t debug_data_size; } pr_debug_header_t; + +extern const char *prdebug_names[]; #endif typedef enum prdebug_e { diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index ad5808107..8a014b469 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -52,6 +52,18 @@ #include "QF/simd/vec4i.h" #include "compat.h" +const char *prdebug_names[] = { + [prd_none] = "none", + [prd_trace] = "trace", + [prd_breakpoint] = "breakpoint", + [prd_watchpoint] = "watchpoint", + [prd_subenter] = "subenter", + [prd_subexit] = "subexit", + [prd_begin] = "begin", + [prd_terminate] = "terminate", + [prd_runerror] = "runerror", + [prd_error] = "error", +}; /* PR_RunError From bf604b99b39aaa281a696184f8241cd524b1bed6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 14:41:29 +0900 Subject: [PATCH 2092/3664] [gamecode] Add automated tests for store ops They even found a bug in the addressing mode functions :) (I'd forgotten that I wanted signed offsets from the pointer and thus forgot to cast st->b to short in order to get the sign extension) --- libs/gamecode/Makemodule.am | 2 + libs/gamecode/pr_exec.c | 18 ++-- libs/gamecode/test/Makemodule.am | 17 ++++ libs/gamecode/test/main.c | 166 +++++++++++++++++++++++++++++++ libs/gamecode/test/test-store.c | 132 ++++++++++++++++++++++++ 5 files changed, 326 insertions(+), 9 deletions(-) create mode 100644 libs/gamecode/test/Makemodule.am create mode 100644 libs/gamecode/test/main.c create mode 100644 libs/gamecode/test/test-store.c diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index dfae7c388..b962f60ad 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -1,3 +1,5 @@ +include libs/gamecode/test/Makemodule.am + gc_deps=libs/util/libQFutil.la noinst_LTLIBRARIES += libs/gamecode/libQFgamecode.la diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 8a014b469..e8c186505 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1753,11 +1753,11 @@ pr_entity_mode (progs_t *pr, const dstatement_t *st, int shift) mm_offs = OPA(uint); break; case 2: - // constant indexed pointer: *a + b - mm_offs = OPA(uint) + st->b; + // constant indexed pointer: *a + b (supports -ve offset) + mm_offs = OPA(uint) + (short) st->b; break; case 3: - // verible indexed pointer: *a + *b (supports -ve offset) + // variable indexed pointer: *a + *b (supports -ve offset) mm_offs = OPA(uint) + OPB(int); break; } @@ -1782,11 +1782,11 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int shift) mm_offs = OPA(uint); break; case 2: - // constant indexed pointer: *a + b - mm_offs = OPA(uint) + st->b; + // constant indexed pointer: *a + b (supports -ve offset) + mm_offs = OPA(uint) + (short) st->b; break; case 3: - // verible indexed pointer: *a + *b (supports -ve offset) + // variable indexed pointer: *a + *b (supports -ve offset) mm_offs = OPA(uint) + OPB(int); break; } @@ -1811,11 +1811,11 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st) jump_offs = OPA(uint); break; case 2: - // constant indexed pointer: *a + b - jump_offs = OPA(uint) + st->b; + // constant indexed pointer: *a + b (supports -ve offset) + jump_offs = OPA(uint) + (short) st->b; break; case 3: - // verible indexed pointer: *a + *b (supports -ve offset) + // variable indexed pointer: *a + *b (supports -ve offset) jump_offs = OPA(uint) + OPB(int); break; } diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am new file mode 100644 index 000000000..9a0bac68a --- /dev/null +++ b/libs/gamecode/test/Makemodule.am @@ -0,0 +1,17 @@ +libs_gamecode_tests = \ + libs/gamecode/test/test-store + +TESTS += $(libs_gamecode_tests) + +check_PROGRAMS += $(libs_gamecode_tests) + +EXTRA_DIST += main.c + +test_gamecode_libs= \ + libs/gamecode/libQFgamecode.la \ + libs/util/libQFutil.la + +libs_gamecode_test_test_store_SOURCES= \ + libs/gamecode/test/test-store.c +libs_gamecode_test_test_store_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_store_DEPENDENCIES= $(test_gamecode_libs) diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c new file mode 100644 index 000000000..e861d6e46 --- /dev/null +++ b/libs/gamecode/test/main.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include + +#include "QF/va.h" + +#define num_tests (sizeof (tests) / sizeof (tests[0])) +static int test_enabled[num_tests] = { 0 }; + +#include "getopt.h" + +#include "QF/cmd.h" +#include "QF/cvar.h" + +static bfunction_t test_functions[] = { + {}, // null function + { .first_statement = 0 } +}; +static dprograms_t test_progs = { + .version = PROG_VERSION, +}; +static progs_t test_pr; + +static jmp_buf jump_buffer; + +static void +test_debug_handler (prdebug_t event, void *param, void *data) +{ + switch (event) { + case prd_breakpoint: + if (verbose > 0) { + printf ("debug: %s\n", prdebug_names[event]); + } + longjmp (jump_buffer, 1); + case prd_subenter: + if (verbose > 0) { + printf ("debug: subenter %d\n", *(func_t *) param); + } + case prd_subexit: + break; + case prd_trace: + dstatement_t *st = test_pr.pr_statements + test_pr.pr_xstatement; + if (verbose > 0) { + printf ("debug: trace %05x %04x %04x %04x %04x\n", + test_pr.pr_xstatement, st->op, st->a, st->b, st->c); + } + break; + case prd_runerror: + printf ("debug: %s: %s\n", prdebug_names[event], (char *)param); + longjmp (jump_buffer, 3); + case prd_watchpoint: + case prd_begin: + case prd_terminate: + case prd_error: + case prd_none: + printf ("debug: unexpected:%s %p\n", prdebug_names[event], param); + longjmp (jump_buffer, 2); + } +} + +static void +setup_test (test_t *test) +{ + memset (&test_pr, 0, sizeof (test_pr)); + test_pr.progs = &test_progs; + test_pr.debug_handler = test_debug_handler; + test_pr.pr_trace = 1; + test_pr.pr_trace_depth = -1; + test_pr.function_table = test_functions; + test_pr.globals_size = test->num_globals; + pr_uint_t num_globals = test->num_globals + test->extra_globals; + test_pr.pr_globals = malloc (num_globals * sizeof (pr_type_t)); + memcpy (test_pr.pr_globals, test->init_globals, + test->num_globals * sizeof (pr_type_t)); + memset (test_pr.pr_globals + test->num_globals, 0, + test->extra_globals * sizeof (pr_type_t)); + test_pr.pr_statements + = malloc ((test->num_statements + 1) * sizeof (dstatement_t)); + memcpy (test_pr.pr_statements, test->statements, + (test->num_statements + 1) * sizeof (dstatement_t)); + test_pr.pr_statements[test->num_statements] = + (dstatement_t) { OP_BREAK, 0, 0, 0 }; +} + +static int +run_test (test_t *test) +{ + int jump_ret; + int ret = 0; + + setup_test (test); + + if (!(jump_ret = setjmp (jump_buffer))) { + PR_ExecuteProgram (&test_pr, 1); + printf ("returned from progs\n"); + } + if (jump_ret == 1) { + if (memcmp (test_pr.pr_globals, test->expect_globals, + test->num_globals * sizeof (pr_int_t)) == 0) { + ret = 1; + printf ("test #%zd: %s: OK\n", test - tests, test->desc); + } else { + printf ("test #%zd: %s: bytes differ\n", test - tests, test->desc); + } + } else { + printf ("test #%zd: %s: critical failure\n", test - tests, test->desc); + } + free (test_pr.pr_globals); + free (test_pr.pr_statements); + return ret; +} + +int +main (int argc, char **argv) +{ + int c; + size_t i, test; + int pass = 1; + + Cmd_Init_Hash (); + Cvar_Init_Hash (); + Cmd_Init (); + Cvar_Init (); + PR_Init_Cvars (); + + while ((c = getopt (argc, argv, "qvt:")) != EOF) { + switch (c) { + case 'q': + verbose--; + break; + case 'v': + verbose++; + break; + case 't': + test = atoi (optarg); + if (test < num_tests) { + test_enabled[test] = 1; + } else { + fprintf (stderr, "Bad test number (0 - %zd)\n", num_tests); + return 1; + } + break; + default: + fprintf (stderr, "-q (quiet) -v (verbose) and/or -t TEST " + "(test number)\n"); + return 1; + } + } + + for (i = 0; i < num_tests; i++) + if (test_enabled[i]) + break; + if (i == num_tests) { + for (i = 0; i < num_tests; i++) + test_enabled[i] = 1; + } + + for (i = 0; i < num_tests; i++) { + if (!test_enabled[i]) + continue; + pass &= run_test (&tests[i]); + } + + return !pass; +} diff --git a/libs/gamecode/test/test-store.c b/libs/gamecode/test/test-store.c new file mode 100644 index 000000000..aacddc4e8 --- /dev/null +++ b/libs/gamecode/test/test-store.c @@ -0,0 +1,132 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/progs.h" + +static int verbose = 0; + +// both calculates the number of globals in the test, and ensures that both +// init and expect are the same size (will product a "void value not ignored" +// error if the sizes differ) +#define num_globals(init, expect) \ + __builtin_choose_expr ( \ + sizeof (init) == sizeof (expect), sizeof (init) / sizeof (init[0]), \ + (void) 0\ + ) + +// calculate the numver of statements in the test +#define num_statements(statements) \ + (sizeof (statements) / sizeof (statements[0])) + +typedef struct { + const char *desc; + pr_uint_t extra_globals; + pr_uint_t num_globals; + pr_uint_t num_statements; + dstatement_t *statements; + pr_int_t *init_globals; + pr_int_t *expect_globals; +} test_t; + +static pr_int_t test_globals_init[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // source data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // destination data + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +static pr_int_t test_globals_expect[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // source data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // destination data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +#define BASE(b, base) (((base) & 3) << OP_##b##_SHIFT) +#define OP(a, b, c, op) ((op) | BASE(A, a) | BASE(B, b) | BASE(C, c)) + +static dstatement_t store_A_statements[] = { + {OP(0, 0, 0, OP_STORE_A_4), 32, 0, 12}, + {OP(0, 0, 0, OP_STORE_A_3), 29, 0, 16}, + {OP(0, 0, 0, OP_STORE_A_1), 28, 0, 19}, + {OP(0, 0, 0, OP_STORE_A_2), 26, 0, 20}, + {OP(0, 0, 0, OP_STORE_A_2), 24, 0, 22}, +}; + +static dstatement_t store_B_statements[] = { + {OP(0, 0, 0, OP_STORE_B_4), 4, 0, 12}, + {OP(0, 0, 0, OP_STORE_B_3), 3, 0, 16}, + {OP(0, 0, 0, OP_STORE_B_1), 2, 0, 19}, + {OP(0, 0, 0, OP_STORE_B_2), 1, 0, 20}, + {OP(0, 0, 0, OP_STORE_B_2), 0, 0, 22}, +}; + +static dstatement_t store_C_statements[] = { + {OP(0, 0, 0, OP_STORE_C_4), 2, 4, 12}, + {OP(0, 0, 0, OP_STORE_C_3), 2, 1, 16}, + {OP(0, 0, 0, OP_STORE_C_1), 2, 0, 19}, + {OP(0, 0, 0, OP_STORE_C_2), 2, -2, 20}, + {OP(0, 0, 0, OP_STORE_C_2), 2, -4, 22}, +}; + +static dstatement_t store_D_statements[] = { + {OP(0, 0, 0, OP_STORE_D_4), 2, 9, 12}, + {OP(0, 0, 0, OP_STORE_D_3), 2, 8, 16}, + {OP(0, 0, 0, OP_STORE_D_1), 2, 7, 19}, + {OP(0, 0, 0, OP_STORE_D_2), 2, 6, 20}, + {OP(0, 0, 0, OP_STORE_D_2), 2, 5, 22}, +}; + +test_t tests[] = { + { + .desc = "store A", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store_A_statements), + .statements = store_A_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "store B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store_B_statements), + .statements = store_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "store C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store_C_statements), + .statements = store_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "store D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store_D_statements), + .statements = store_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" From 28df32eb0d77ddae0810b62f0c3e4ee3495f75c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 14:45:12 +0900 Subject: [PATCH 2093/3664] [gamecode] Use pr_memset instead of memset This keeps things inline and matches the quakec exec loop. Also removes the need to calculate the size. --- libs/gamecode/pr_exec.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index e8c186505..1543d9c59 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2606,15 +2606,13 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_op_T (GE, U, ulong, ulvec2, ulvec4, >=); //FIXME float shift case OP_MEMSET_I: - memset (op_c, OPA(int), st->b * sizeof (pr_type_t)); + pr_memset (op_c, OPA(int), st->b); break; case OP_MEMSET_P: - memset (pr->pr_globals + OPC(int), OPA(int), - OPB(uint) * sizeof (pr_type_t)); + pr_memset (pr->pr_globals + OPC(int), OPA(int), OPB(uint)); break; case OP_MEMSET_PI: - memset (pr->pr_globals + OPC(int), OPA(int), - st->b * sizeof (pr_type_t)); + pr_memset (pr->pr_globals + OPC(int), OPA(int), st->b); break; // 1 1110 OP_op_T (LE, u, uint, uivec2, uivec4, <=); From c86f1f671b400f6acaa32185354b176d5c85dcd6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 15:22:34 +0900 Subject: [PATCH 2094/3664] [gamecode] Add tests for load instructions This needed the test struct declaration to be moved out to a head file so it can be shared with other tests. --- libs/gamecode/test/Makemodule.am | 8 ++- libs/gamecode/test/head.c | 31 +++++++++ libs/gamecode/test/main.c | 7 +- libs/gamecode/test/test-load.c | 106 +++++++++++++++++++++++++++++++ libs/gamecode/test/test-store.c | 31 +-------- 5 files changed, 151 insertions(+), 32 deletions(-) create mode 100644 libs/gamecode/test/head.c create mode 100644 libs/gamecode/test/test-load.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 9a0bac68a..e8a21ee58 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,16 +1,22 @@ libs_gamecode_tests = \ + libs/gamecode/test/test-load \ libs/gamecode/test/test-store TESTS += $(libs_gamecode_tests) check_PROGRAMS += $(libs_gamecode_tests) -EXTRA_DIST += main.c +EXTRA_DIST += head.c main.c test_gamecode_libs= \ libs/gamecode/libQFgamecode.la \ libs/util/libQFutil.la +libs_gamecode_test_test_load_SOURCES= \ + libs/gamecode/test/test-load.c +libs_gamecode_test_test_load_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_load_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_store_SOURCES= \ libs/gamecode/test/test-store.c libs_gamecode_test_test_store_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/head.c b/libs/gamecode/test/head.c new file mode 100644 index 000000000..c4e099c78 --- /dev/null +++ b/libs/gamecode/test/head.c @@ -0,0 +1,31 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/progs.h" + +static int verbose = 0; + +// both calculates the number of globals in the test, and ensures that both +// init and expect are the same size (will product a "void value not ignored" +// error if the sizes differ) +#define num_globals(init, expect) \ + __builtin_choose_expr ( \ + sizeof (init) == sizeof (expect), sizeof (init) / sizeof (init[0]), \ + (void) 0\ + ) + +// calculate the numver of statements in the test +#define num_statements(statements) \ + (sizeof (statements) / sizeof (statements[0])) + +typedef struct { + const char *desc; + pr_uint_t edict_area; + pr_uint_t extra_globals; + pr_uint_t num_globals; + pr_uint_t num_statements; + dstatement_t *statements; + pr_int_t *init_globals; + pr_int_t *expect_globals; +} test_t; diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index e861d6e46..184db9cf4 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -68,6 +68,7 @@ setup_test (test_t *test) test_pr.pr_trace = 1; test_pr.pr_trace_depth = -1; test_pr.function_table = test_functions; + test_pr.globals_size = test->num_globals; pr_uint_t num_globals = test->num_globals + test->extra_globals; test_pr.pr_globals = malloc (num_globals * sizeof (pr_type_t)); @@ -75,6 +76,10 @@ setup_test (test_t *test) test->num_globals * sizeof (pr_type_t)); memset (test_pr.pr_globals + test->num_globals, 0, test->extra_globals * sizeof (pr_type_t)); + if (test->edict_area) { + test_pr.pr_edict_area = test_pr.pr_globals + test->edict_area; + } + test_pr.pr_statements = malloc ((test->num_statements + 1) * sizeof (dstatement_t)); memcpy (test_pr.pr_statements, test->statements, @@ -101,7 +106,7 @@ run_test (test_t *test) ret = 1; printf ("test #%zd: %s: OK\n", test - tests, test->desc); } else { - printf ("test #%zd: %s: bytes differ\n", test - tests, test->desc); + printf ("test #%zd: %s: words differ\n", test - tests, test->desc); } } else { printf ("test #%zd: %s: critical failure\n", test - tests, test->desc); diff --git a/libs/gamecode/test/test-load.c b/libs/gamecode/test/test-load.c new file mode 100644 index 000000000..212aaa49b --- /dev/null +++ b/libs/gamecode/test/test-load.c @@ -0,0 +1,106 @@ +#include "head.c" + +static pr_int_t test_globals_init[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // destination data + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + // source data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static pr_int_t test_globals_expect[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // destination data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // source data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +#define BASE(b, base) (((base) & 3) << OP_##b##_SHIFT) +#define OP(a, b, c, op) ((op) | BASE(A, a) | BASE(B, b) | BASE(C, c)) + +static dstatement_t load_E_statements[] = { + {OP(0, 0, 0, OP_LOAD_E_4), 7, 9, 12}, + {OP(0, 0, 0, OP_LOAD_E_3), 7, 8, 16}, + {OP(0, 0, 0, OP_LOAD_E_1), 7, 7, 19}, + {OP(0, 0, 0, OP_LOAD_E_2), 7, 6, 20}, + {OP(0, 0, 0, OP_LOAD_E_2), 7, 5, 22}, +}; + +static dstatement_t load_B_statements[] = { + {OP(0, 0, 0, OP_LOAD_B_4), 4, 0, 12}, + {OP(0, 0, 0, OP_LOAD_B_3), 3, 0, 16}, + {OP(0, 0, 0, OP_LOAD_B_1), 2, 0, 19}, + {OP(0, 0, 0, OP_LOAD_B_2), 1, 0, 20}, + {OP(0, 0, 0, OP_LOAD_B_2), 0, 0, 22}, +}; + +static dstatement_t load_C_statements[] = { + {OP(0, 0, 0, OP_LOAD_C_4), 2, 4, 12}, + {OP(0, 0, 0, OP_LOAD_C_3), 2, 1, 16}, + {OP(0, 0, 0, OP_LOAD_C_1), 2, 0, 19}, + {OP(0, 0, 0, OP_LOAD_C_2), 2, -2, 20}, + {OP(0, 0, 0, OP_LOAD_C_2), 2, -4, 22}, +}; + +static dstatement_t load_D_statements[] = { + {OP(0, 0, 0, OP_LOAD_D_4), 2, 9, 12}, + {OP(0, 0, 0, OP_LOAD_D_3), 2, 8, 16}, + {OP(0, 0, 0, OP_LOAD_D_1), 2, 7, 19}, + {OP(0, 0, 0, OP_LOAD_D_2), 2, 6, 20}, + {OP(0, 0, 0, OP_LOAD_D_2), 2, 5, 22}, +}; + +test_t tests[] = { + { + .desc = "load E", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load_E_statements), + .statements = load_E_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 28, + }, + { + .desc = "load B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load_B_statements), + .statements = load_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "load C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load_C_statements), + .statements = load_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "load D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load_D_statements), + .statements = load_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-store.c b/libs/gamecode/test/test-store.c index aacddc4e8..dee244485 100644 --- a/libs/gamecode/test/test-store.c +++ b/libs/gamecode/test/test-store.c @@ -1,33 +1,4 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "QF/progs.h" - -static int verbose = 0; - -// both calculates the number of globals in the test, and ensures that both -// init and expect are the same size (will product a "void value not ignored" -// error if the sizes differ) -#define num_globals(init, expect) \ - __builtin_choose_expr ( \ - sizeof (init) == sizeof (expect), sizeof (init) / sizeof (init[0]), \ - (void) 0\ - ) - -// calculate the numver of statements in the test -#define num_statements(statements) \ - (sizeof (statements) / sizeof (statements[0])) - -typedef struct { - const char *desc; - pr_uint_t extra_globals; - pr_uint_t num_globals; - pr_uint_t num_statements; - dstatement_t *statements; - pr_int_t *init_globals; - pr_int_t *expect_globals; -} test_t; +#include "head.c" static pr_int_t test_globals_init[] = { // pointers From ffbb6122b9f485edaf31cc0d44713b8ead88cc78 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 16:29:42 +0900 Subject: [PATCH 2095/3664] [gamecode] Add tests for push and pop --- libs/gamecode/test/Makemodule.am | 6 + libs/gamecode/test/head.c | 6 +- libs/gamecode/test/main.c | 28 +++- libs/gamecode/test/test-load.c | 3 - libs/gamecode/test/test-stack.c | 227 +++++++++++++++++++++++++++++++ libs/gamecode/test/test-store.c | 3 - 6 files changed, 262 insertions(+), 11 deletions(-) create mode 100644 libs/gamecode/test/test-stack.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index e8a21ee58..b06e1c9fa 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,5 +1,6 @@ libs_gamecode_tests = \ libs/gamecode/test/test-load \ + libs/gamecode/test/test-stack \ libs/gamecode/test/test-store TESTS += $(libs_gamecode_tests) @@ -17,6 +18,11 @@ libs_gamecode_test_test_load_SOURCES= \ libs_gamecode_test_test_load_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_load_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_stack_SOURCES= \ + libs/gamecode/test/test-stack.c +libs_gamecode_test_test_stack_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_stack_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_store_SOURCES= \ libs/gamecode/test/test-store.c libs_gamecode_test_test_store_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/head.c b/libs/gamecode/test/head.c index c4e099c78..c7db8fb26 100644 --- a/libs/gamecode/test/head.c +++ b/libs/gamecode/test/head.c @@ -19,9 +19,13 @@ static int verbose = 0; #define num_statements(statements) \ (sizeof (statements) / sizeof (statements[0])) +#define BASE(b, base) (((base) & 3) << OP_##b##_SHIFT) +#define OP(a, b, c, op) ((op) | BASE(A, a) | BASE(B, b) | BASE(C, c)) + typedef struct { const char *desc; - pr_uint_t edict_area; + pointer_t edict_area; + pointer_t stack_size; pr_uint_t extra_globals; pr_uint_t num_globals; pr_uint_t num_statements; diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 184db9cf4..4e231b5e0 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -27,6 +27,8 @@ static jmp_buf jump_buffer; static void test_debug_handler (prdebug_t event, void *param, void *data) { + progs_t *pr = data; + switch (event) { case prd_breakpoint: if (verbose > 0) { @@ -42,8 +44,16 @@ test_debug_handler (prdebug_t event, void *param, void *data) case prd_trace: dstatement_t *st = test_pr.pr_statements + test_pr.pr_xstatement; if (verbose > 0) { - printf ("debug: trace %05x %04x %04x %04x %04x\n", - test_pr.pr_xstatement, st->op, st->a, st->b, st->c); + printf ("debug: trace %05x %04x %04x %04x %04x%s\n", + test_pr.pr_xstatement, st->op, st->a, st->b, st->c, + pr->globals.stack ? va (0, " %05x", *pr->globals.stack) + : ""); + } + if (pr->globals.stack) { + if (*pr->globals.stack & 3) { + printf ("stack not aligned: %d\n", *pr->globals.stack); + longjmp (jump_buffer, 3); + } } break; case prd_runerror: @@ -65,17 +75,26 @@ setup_test (test_t *test) memset (&test_pr, 0, sizeof (test_pr)); test_pr.progs = &test_progs; test_pr.debug_handler = test_debug_handler; + test_pr.debug_data = &test_pr; test_pr.pr_trace = 1; test_pr.pr_trace_depth = -1; test_pr.function_table = test_functions; - test_pr.globals_size = test->num_globals; - pr_uint_t num_globals = test->num_globals + test->extra_globals; + pr_uint_t num_globals = test->num_globals; + num_globals += test->extra_globals + test->stack_size; + + test_pr.globals_size = num_globals; test_pr.pr_globals = malloc (num_globals * sizeof (pr_type_t)); memcpy (test_pr.pr_globals, test->init_globals, test->num_globals * sizeof (pr_type_t)); memset (test_pr.pr_globals + test->num_globals, 0, test->extra_globals * sizeof (pr_type_t)); + if (test->stack_size) { + pointer_t stack = num_globals - test->stack_size; + test_pr.stack_bottom = stack + 4; + test_pr.globals.stack = (pointer_t *) (test_pr.pr_globals + stack); + *test_pr.globals.stack = num_globals; + } if (test->edict_area) { test_pr.pr_edict_area = test_pr.pr_globals + test->edict_area; } @@ -128,6 +147,7 @@ main (int argc, char **argv) Cmd_Init (); Cvar_Init (); PR_Init_Cvars (); + pr_boundscheck->int_val = 1; while ((c = getopt (argc, argv, "qvt:")) != EOF) { switch (c) { diff --git a/libs/gamecode/test/test-load.c b/libs/gamecode/test/test-load.c index 212aaa49b..e283ced38 100644 --- a/libs/gamecode/test/test-load.c +++ b/libs/gamecode/test/test-load.c @@ -30,9 +30,6 @@ static pr_int_t test_globals_expect[] = { 1, 2, 3, 4, }; -#define BASE(b, base) (((base) & 3) << OP_##b##_SHIFT) -#define OP(a, b, c, op) ((op) | BASE(A, a) | BASE(B, b) | BASE(C, c)) - static dstatement_t load_E_statements[] = { {OP(0, 0, 0, OP_LOAD_E_4), 7, 9, 12}, {OP(0, 0, 0, OP_LOAD_E_3), 7, 8, 16}, diff --git a/libs/gamecode/test/test-stack.c b/libs/gamecode/test/test-stack.c new file mode 100644 index 000000000..183e33694 --- /dev/null +++ b/libs/gamecode/test/test-stack.c @@ -0,0 +1,227 @@ +#include "head.c" + +static pr_int_t test_globals_init1[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // source data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // destination data + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, +}; + +static pr_int_t test_globals_expect1[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // source data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // destination data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static pr_int_t test_globals_init2[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // destination data + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + // source data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static pr_int_t test_globals_expect2[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + // destination data + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + // source data + 11, 12, 9, 10, + 8, 5, 6, 7, + 1, 2, 3, 4, +}; + +static dstatement_t stack_AA_statements[] = { + {OP(0, 0, 0, OP_PUSH_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0}, + + {OP(0, 0, 0, OP_POP_A_2), 24, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 26, 0, 0}, + {OP(0, 0, 0, OP_POP_A_1), 28, 0, 0}, + {OP(0, 0, 0, OP_POP_A_3), 29, 0, 0}, + {OP(0, 0, 0, OP_POP_A_4), 32, 0, 0}, +}; + +static dstatement_t stack_AB_statements[] = { + {OP(0, 0, 0, OP_PUSH_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0}, + + {OP(0, 0, 0, OP_POP_B_2), 0, 0, 0}, + {OP(0, 0, 0, OP_POP_B_2), 1, 0, 0}, + {OP(0, 0, 0, OP_POP_B_1), 2, 0, 0}, + {OP(0, 0, 0, OP_POP_B_3), 3, 0, 0}, + {OP(0, 0, 0, OP_POP_B_4), 4, 0, 0}, +}; + +static dstatement_t stack_AC_statements[] = { + {OP(0, 0, 0, OP_PUSH_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0}, + + {OP(0, 0, 0, OP_POP_C_2), 2, -4, 0}, + {OP(0, 0, 0, OP_POP_C_2), 2, -2, 0}, + {OP(0, 0, 0, OP_POP_C_1), 2, 0, 0}, + {OP(0, 0, 0, OP_POP_C_3), 2, 1, 0}, + {OP(0, 0, 0, OP_POP_C_4), 2, 4, 0}, +}; + +static dstatement_t stack_AD_statements[] = { + {OP(0, 0, 0, OP_PUSH_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0}, + + {OP(0, 0, 0, OP_POP_D_2), 2, 5, 0}, + {OP(0, 0, 0, OP_POP_D_2), 2, 6, 0}, + {OP(0, 0, 0, OP_POP_D_1), 2, 7, 0}, + {OP(0, 0, 0, OP_POP_D_3), 2, 8, 0}, + {OP(0, 0, 0, OP_POP_D_4), 2, 9, 0}, +}; + +static dstatement_t stack_BA_statements[] = { + {OP(0, 0, 0, OP_PUSH_B_2), 0, 0, 0}, + {OP(0, 0, 0, OP_PUSH_B_2), 1, 0, 0}, + {OP(0, 0, 0, OP_PUSH_B_1), 2, 0, 0}, + {OP(0, 0, 0, OP_PUSH_B_3), 3, 0, 0}, + {OP(0, 0, 0, OP_PUSH_B_4), 4, 0, 0}, + + {OP(0, 0, 0, OP_POP_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_POP_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_POP_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 22, 0, 0}, +}; + +static dstatement_t stack_CA_statements[] = { + {OP(0, 0, 0, OP_PUSH_C_2), 2, -4, 0}, + {OP(0, 0, 0, OP_PUSH_C_2), 2, -2, 0}, + {OP(0, 0, 0, OP_PUSH_C_1), 2, 0, 0}, + {OP(0, 0, 0, OP_PUSH_C_3), 2, 1, 0}, + {OP(0, 0, 0, OP_PUSH_C_4), 2, 4, 0}, + + {OP(0, 0, 0, OP_POP_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_POP_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_POP_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 22, 0, 0}, +}; + +static dstatement_t stack_DA_statements[] = { + {OP(0, 0, 0, OP_PUSH_D_2), 2, 5, 0}, + {OP(0, 0, 0, OP_PUSH_D_2), 2, 6, 0}, + {OP(0, 0, 0, OP_PUSH_D_1), 2, 7, 0}, + {OP(0, 0, 0, OP_PUSH_D_3), 2, 8, 0}, + {OP(0, 0, 0, OP_PUSH_D_4), 2, 9, 0}, + + {OP(0, 0, 0, OP_POP_A_4), 12, 0, 0}, + {OP(0, 0, 0, OP_POP_A_3), 16, 0, 0}, + {OP(0, 0, 0, OP_POP_A_1), 19, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 20, 0, 0}, + {OP(0, 0, 0, OP_POP_A_2), 22, 0, 0}, +}; + +test_t tests[] = { + { + .desc = "stack push A pop A", + .stack_size = 32, + .num_globals = num_globals (test_globals_init1, test_globals_expect1), + .num_statements = num_statements (stack_AA_statements), + .statements = stack_AA_statements, + .init_globals = test_globals_init1, + .expect_globals = test_globals_expect1, + }, + { + .desc = "stack push A pop B", + .stack_size = 32, + .num_globals = num_globals (test_globals_init1, test_globals_expect1), + .num_statements = num_statements (stack_AB_statements), + .statements = stack_AB_statements, + .init_globals = test_globals_init1, + .expect_globals = test_globals_expect1, + }, + { + .desc = "stack push A pop C", + .stack_size = 32, + .num_globals = num_globals (test_globals_init1, test_globals_expect1), + .num_statements = num_statements (stack_AC_statements), + .statements = stack_AC_statements, + .init_globals = test_globals_init1, + .expect_globals = test_globals_expect1, + }, + { + .desc = "stack push A pop D", + .stack_size = 32, + .num_globals = num_globals (test_globals_init1, test_globals_expect1), + .num_statements = num_statements (stack_AD_statements), + .statements = stack_AD_statements, + .init_globals = test_globals_init1, + .expect_globals = test_globals_expect1, + }, + { + .desc = "stack push B pop A", + .stack_size = 32, + .num_globals = num_globals (test_globals_init2, test_globals_expect2), + .num_statements = num_statements (stack_BA_statements), + .statements = stack_BA_statements, + .init_globals = test_globals_init2, + .expect_globals = test_globals_expect2, + }, + { + .desc = "stack push C pop A", + .stack_size = 32, + .num_globals = num_globals (test_globals_init2, test_globals_expect2), + .num_statements = num_statements (stack_CA_statements), + .statements = stack_CA_statements, + .init_globals = test_globals_init2, + .expect_globals = test_globals_expect2, + }, + { + .desc = "stack push D pop A", + .stack_size = 32, + .num_globals = num_globals (test_globals_init2, test_globals_expect2), + .num_statements = num_statements (stack_DA_statements), + .statements = stack_DA_statements, + .init_globals = test_globals_init2, + .expect_globals = test_globals_expect2, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-store.c b/libs/gamecode/test/test-store.c index dee244485..dc580f028 100644 --- a/libs/gamecode/test/test-store.c +++ b/libs/gamecode/test/test-store.c @@ -30,9 +30,6 @@ static pr_int_t test_globals_expect[] = { 1, 2, 3, 4, }; -#define BASE(b, base) (((base) & 3) << OP_##b##_SHIFT) -#define OP(a, b, c, op) ((op) | BASE(A, a) | BASE(B, b) | BASE(C, c)) - static dstatement_t store_A_statements[] = { {OP(0, 0, 0, OP_STORE_A_4), 32, 0, 12}, {OP(0, 0, 0, OP_STORE_A_3), 29, 0, 16}, From fd298f360159b9066c3eb993948535d2c1a72ae1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 17:54:54 +0900 Subject: [PATCH 2096/3664] [gamecode] Create a mask for extracting the opcode Got tired of copying the full thing around. --- include/QF/pr_comp.h | 1 + libs/gamecode/pr_exec.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index df81d606f..541c69978 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -598,6 +598,7 @@ typedef enum { #define OP_A_BASE (3 << OP_A_SHIFT) #define OP_B_BASE (3 << OP_B_SHIFT) #define OP_C_BASE (3 << OP_C_SHIFT) +#define OP_MASK (~(OP_BREAK|OP_A_BASE|OP_B_BASE|OP_C_BASE)) typedef enum { OP_with_zero, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 1543d9c59..1e41cbe30 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1713,7 +1713,7 @@ op_call: */ default: - PR_RunError (pr, "Bad opcode %i", st->op); + PR_RunError (pr, "Bad opcode %i", st->op & ~OP_BREAK); } if (pr->watch && pr->watch->integer_var != old_val.integer_var) { if (!pr->wp_conditional @@ -1923,7 +1923,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) pr_type_t *stk; pr_type_t *mm; func_t function; - pr_opcode_e st_op = st->op & ~(OP_BREAK|OP_A_BASE|OP_B_BASE|OP_C_BASE); + pr_opcode_e st_op = st->op & OP_MASK; switch (st_op) { // 0 0000 case OP_LOAD_E_1: @@ -2623,7 +2623,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) //FIXME conversion 3 default: - PR_RunError (pr, "Bad opcode %i", st->op); + PR_RunError (pr, "Bad opcode o%03o", st->op & OP_MASK); } if (pr->watch && pr->watch->integer_var != old_val.integer_var) { if (!pr->wp_conditional From 9084121ad28528ab2dff42fb26e7db2b11217409 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 17:55:45 +0900 Subject: [PATCH 2097/3664] [simd] Correct result for dot2f It turns out gcc optimizes the obvious code nicely. It doesn't do so well for cmul, but I decided to use obvious code anyway (the instruction counts were the same, so maybe it doesn't get better for a single pair of operands). --- include/QF/simd/vec2f.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/include/QF/simd/vec2f.h b/include/QF/simd/vec2f.h index ffa403ad4..b75efcd8e 100644 --- a/include/QF/simd/vec2f.h +++ b/include/QF/simd/vec2f.h @@ -120,9 +120,7 @@ vec2f_t dot2f (vec2f_t a, vec2f_t b) { vec2f_t c = a * b; - vec4f_t t = { c[0], c[1], 0, 0 }; - t = _mm_hadd_ps (t, t); - return (vec2f_t) { t[0], t[1] }; + return (vec2f_t) { c[0] + c[1], c[0] + c[1] }; } #ifndef IMPLEMENT_VEC2F_Funcs @@ -135,10 +133,7 @@ cmulf (vec2f_t a, vec2f_t b) { vec2f_t c1 = a * b[0]; vec2f_t c2 = a * b[1]; - vec4f_t c14 ={ c1[0], c1[1], 0, 0 }; - vec4f_t c24 ={ c2[1], c2[0], 0, 0 }; - vec4f_t c = _mm_addsub_ps (c14, c24); - return (vec2f_t) { c[0], c[1] }; + return (vec2f_t) { c1[0] - c2[1], c1[1] + c2[0] }; } #ifndef IMPLEMENT_VEC2F_Funcs From b8d04874c34c0a1a3e6e6ff401f6db61498e3431 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 17:58:16 +0900 Subject: [PATCH 2098/3664] [gamecode] Add some math tests Hit a show stopper when it came to swizzle (not implemented yet). I guess I know what I need to do next :P. --- libs/gamecode/test/Makemodule.am | 6 +++ libs/gamecode/test/main.c | 23 +++++++--- libs/gamecode/test/test-math.c | 77 ++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 libs/gamecode/test/test-math.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index b06e1c9fa..433fad58f 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,5 +1,6 @@ libs_gamecode_tests = \ libs/gamecode/test/test-load \ + libs/gamecode/test/test-math \ libs/gamecode/test/test-stack \ libs/gamecode/test/test-store @@ -18,6 +19,11 @@ libs_gamecode_test_test_load_SOURCES= \ libs_gamecode_test_test_load_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_load_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_math_SOURCES= \ + libs/gamecode/test/test-math.c +libs_gamecode_test_test_math_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_math_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_stack_SOURCES= \ libs/gamecode/test/test-stack.c libs_gamecode_test_test_stack_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 4e231b5e0..e9256dcec 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -107,6 +107,21 @@ setup_test (test_t *test) (dstatement_t) { OP_BREAK, 0, 0, 0 }; } +static int +check_result (test_t *test) +{ + int ret = 0; + + if (memcmp (test_pr.pr_globals, test->expect_globals, + test->num_globals * sizeof (pr_int_t)) == 0) { + ret = 1; + printf ("test #%zd: %s: OK\n", test - tests, test->desc); + } else { + printf ("test #%zd: %s: words differ\n", test - tests, test->desc); + } + return ret; +} + static int run_test (test_t *test) { @@ -120,13 +135,7 @@ run_test (test_t *test) printf ("returned from progs\n"); } if (jump_ret == 1) { - if (memcmp (test_pr.pr_globals, test->expect_globals, - test->num_globals * sizeof (pr_int_t)) == 0) { - ret = 1; - printf ("test #%zd: %s: OK\n", test - tests, test->desc); - } else { - printf ("test #%zd: %s: words differ\n", test - tests, test->desc); - } + ret = check_result (test); } else { printf ("test #%zd: %s: critical failure\n", test - tests, test->desc); } diff --git a/libs/gamecode/test/test-math.c b/libs/gamecode/test/test-math.c new file mode 100644 index 000000000..b5daab225 --- /dev/null +++ b/libs/gamecode/test/test-math.c @@ -0,0 +1,77 @@ +#include "head.c" + +static pr_vec4_t float_globals_init[] = { + {3, 4, 5, 12}, + {0, 0, 0, 0}, + {1, 2, 3, 8}, + {4, 5, 6, 8}, + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {1, 2, 3, 4}, + {5, 6, 7, 8}, + {2, 3, 4, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, +}; + +static pr_vec4_t float_globals_expect[] = { + {3, 4, 5, 12}, + {63, 63, -33, 56}, + {1, 2, 3, 8}, + {4, 5, 6, 8}, + + {32, 32, 32, 7}, + {-3, 6, -3, 7}, + {1, 2, 3, 4}, + {5, 6, 7, 8}, + + {2, 3, 4, 0}, + {70, 70, 70, 70}, + {24, 48, 48, -6}, + {36, 102, 120, 7}, + + {52, 70, 136, 7}, + {160, 160, 160, 160}, + {9, 10, 17, 20}, + {-1, -2, -3, 4}, + + {-1, -2, -3, 4}, +}; + +static dstatement_t store_A_statements[] = { + { OP(0, 0, 0, OP_DOT_CC_F), 0, 2, 4 }, + { OP(0, 0, 0, OP_MUL_CC_F), 0, 2, 6 }, + { OP(0, 0, 0, OP_DOT_VV_F), 8, 12, 16 }, + { OP(0, 0, 0, OP_CROSS_VV_F), 8, 12, 20 }, + { OP(0, 0, 0, OP_DOT_QQ_F), 24, 28, 36 }, + { OP(0, 0, 0, OP_MUL_QQ_F), 24, 28, 40 }, + { OP(0, 0, 0, OP_MUL_QV_F), 24, 32, 44 }, + { OP(0, 0, 0, OP_MUL_VQ_F), 32, 24, 48 }, + + { OP(0, 0, 0, OP_DOT_QQ_F), 24, 32, 52 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 24, 0x07e4, 60 }, + { OP(0, 0, 0, OP_DOT_QQ_F), 52, 60, 52 }, + + { OP(0, 0, 0, OP_SWIZZLE_F), 24, 0x07e4, 64 }, + { OP(0, 0, 0, OP_MUL_QQ_F), 60, 32, 56 }, + { OP(0, 0, 0, OP_DOT_QQ_F), 56, 24, 52 }, +}; + +test_t tests[] = { + { + .desc = "float vector", + .num_globals = 4*num_globals(float_globals_init, float_globals_expect), + .num_statements = num_statements (store_A_statements), + .statements = store_A_statements, + .init_globals = (pr_int_t *) float_globals_init, + .expect_globals = (pr_int_t *) float_globals_expect, + }, +}; + +#include "main.c" From bebc811f11dd8a8f6477eefb32075a346185f07b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 19:30:32 +0900 Subject: [PATCH 2099/3664] [gamecode] Implement 4-component 32-bit swizzle The swizzle instruction is very powerful in that in can do any of the 256 permutations of xyzw, optionally negate any combination of the resulting components, and zero any combination of the result components (even all). This means the one instruction can take care of any actual swizzles, conjugation for complex and quaternion values, zeroing vectors (not that it's the only way), and probably other weird things. The python file was used to generate the jump table and actual swizzle code. --- libs/gamecode/pr_exec.c | 376 +++++++++++++++++++++++++++++++++++++++ libs/gamecode/swizzle.py | 21 +++ 2 files changed, 397 insertions(+) create mode 100644 libs/gamecode/swizzle.py diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 1e41cbe30..040d18b1d 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1870,6 +1870,379 @@ pr_stack_pop (progs_t *pr) return stk; } +static pr_ivec4_t +pr_swizzle_f (pr_ivec4_t vec, pr_ushort_t swiz) +{ + goto do_swizzle; +#define swizzle __builtin_shuffle + swizzle_xxxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 0 }); goto negate; + swizzle_yxxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 0 }); goto negate; + swizzle_zxxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 0 }); goto negate; + swizzle_wxxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 0 }); goto negate; + swizzle_xyxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 0 }); goto negate; + swizzle_yyxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 0 }); goto negate; + swizzle_zyxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 0 }); goto negate; + swizzle_wyxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 0 }); goto negate; + swizzle_xzxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 0 }); goto negate; + swizzle_yzxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 0 }); goto negate; + swizzle_zzxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 0 }); goto negate; + swizzle_wzxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 0 }); goto negate; + swizzle_xwxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 0 }); goto negate; + swizzle_ywxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 0 }); goto negate; + swizzle_zwxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 0 }); goto negate; + swizzle_wwxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 0 }); goto negate; + swizzle_xxyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 0 }); goto negate; + swizzle_yxyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 0 }); goto negate; + swizzle_zxyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 0 }); goto negate; + swizzle_wxyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 0 }); goto negate; + swizzle_xyyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 0 }); goto negate; + swizzle_yyyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 0 }); goto negate; + swizzle_zyyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 0 }); goto negate; + swizzle_wyyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 0 }); goto negate; + swizzle_xzyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 0 }); goto negate; + swizzle_yzyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 0 }); goto negate; + swizzle_zzyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 0 }); goto negate; + swizzle_wzyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 0 }); goto negate; + swizzle_xwyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 0 }); goto negate; + swizzle_ywyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 0 }); goto negate; + swizzle_zwyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 0 }); goto negate; + swizzle_wwyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 0 }); goto negate; + swizzle_xxzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 0 }); goto negate; + swizzle_yxzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 0 }); goto negate; + swizzle_zxzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 0 }); goto negate; + swizzle_wxzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 0 }); goto negate; + swizzle_xyzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 0 }); goto negate; + swizzle_yyzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 0 }); goto negate; + swizzle_zyzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 0 }); goto negate; + swizzle_wyzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 0 }); goto negate; + swizzle_xzzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 0 }); goto negate; + swizzle_yzzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 0 }); goto negate; + swizzle_zzzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 0 }); goto negate; + swizzle_wzzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 0 }); goto negate; + swizzle_xwzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 0 }); goto negate; + swizzle_ywzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 0 }); goto negate; + swizzle_zwzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 0 }); goto negate; + swizzle_wwzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 0 }); goto negate; + swizzle_xxwx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 0 }); goto negate; + swizzle_yxwx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 0 }); goto negate; + swizzle_zxwx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 0 }); goto negate; + swizzle_wxwx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 0 }); goto negate; + swizzle_xywx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 0 }); goto negate; + swizzle_yywx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 0 }); goto negate; + swizzle_zywx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 0 }); goto negate; + swizzle_wywx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 0 }); goto negate; + swizzle_xzwx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 0 }); goto negate; + swizzle_yzwx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 0 }); goto negate; + swizzle_zzwx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 0 }); goto negate; + swizzle_wzwx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 0 }); goto negate; + swizzle_xwwx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 0 }); goto negate; + swizzle_ywwx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 0 }); goto negate; + swizzle_zwwx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 0 }); goto negate; + swizzle_wwwx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 0 }); goto negate; + swizzle_xxxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 1 }); goto negate; + swizzle_yxxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 1 }); goto negate; + swizzle_zxxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 1 }); goto negate; + swizzle_wxxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 1 }); goto negate; + swizzle_xyxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 1 }); goto negate; + swizzle_yyxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 1 }); goto negate; + swizzle_zyxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 1 }); goto negate; + swizzle_wyxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 1 }); goto negate; + swizzle_xzxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 1 }); goto negate; + swizzle_yzxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 1 }); goto negate; + swizzle_zzxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 1 }); goto negate; + swizzle_wzxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 1 }); goto negate; + swizzle_xwxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 1 }); goto negate; + swizzle_ywxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 1 }); goto negate; + swizzle_zwxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 1 }); goto negate; + swizzle_wwxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 1 }); goto negate; + swizzle_xxyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 1 }); goto negate; + swizzle_yxyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 1 }); goto negate; + swizzle_zxyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 1 }); goto negate; + swizzle_wxyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 1 }); goto negate; + swizzle_xyyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 1 }); goto negate; + swizzle_yyyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 1 }); goto negate; + swizzle_zyyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 1 }); goto negate; + swizzle_wyyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 1 }); goto negate; + swizzle_xzyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 1 }); goto negate; + swizzle_yzyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 1 }); goto negate; + swizzle_zzyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 1 }); goto negate; + swizzle_wzyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 1 }); goto negate; + swizzle_xwyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 1 }); goto negate; + swizzle_ywyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 1 }); goto negate; + swizzle_zwyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 1 }); goto negate; + swizzle_wwyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 1 }); goto negate; + swizzle_xxzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 1 }); goto negate; + swizzle_yxzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 1 }); goto negate; + swizzle_zxzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 1 }); goto negate; + swizzle_wxzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 1 }); goto negate; + swizzle_xyzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 1 }); goto negate; + swizzle_yyzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 1 }); goto negate; + swizzle_zyzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 1 }); goto negate; + swizzle_wyzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 1 }); goto negate; + swizzle_xzzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 1 }); goto negate; + swizzle_yzzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 1 }); goto negate; + swizzle_zzzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 1 }); goto negate; + swizzle_wzzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 1 }); goto negate; + swizzle_xwzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 1 }); goto negate; + swizzle_ywzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 1 }); goto negate; + swizzle_zwzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 1 }); goto negate; + swizzle_wwzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 1 }); goto negate; + swizzle_xxwy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 1 }); goto negate; + swizzle_yxwy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 1 }); goto negate; + swizzle_zxwy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 1 }); goto negate; + swizzle_wxwy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 1 }); goto negate; + swizzle_xywy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 1 }); goto negate; + swizzle_yywy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 1 }); goto negate; + swizzle_zywy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 1 }); goto negate; + swizzle_wywy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 1 }); goto negate; + swizzle_xzwy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 1 }); goto negate; + swizzle_yzwy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 1 }); goto negate; + swizzle_zzwy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 1 }); goto negate; + swizzle_wzwy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 1 }); goto negate; + swizzle_xwwy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 1 }); goto negate; + swizzle_ywwy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 1 }); goto negate; + swizzle_zwwy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 1 }); goto negate; + swizzle_wwwy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 1 }); goto negate; + swizzle_xxxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 2 }); goto negate; + swizzle_yxxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 2 }); goto negate; + swizzle_zxxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 2 }); goto negate; + swizzle_wxxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 2 }); goto negate; + swizzle_xyxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 2 }); goto negate; + swizzle_yyxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 2 }); goto negate; + swizzle_zyxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 2 }); goto negate; + swizzle_wyxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 2 }); goto negate; + swizzle_xzxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 2 }); goto negate; + swizzle_yzxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 2 }); goto negate; + swizzle_zzxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 2 }); goto negate; + swizzle_wzxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 2 }); goto negate; + swizzle_xwxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 2 }); goto negate; + swizzle_ywxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 2 }); goto negate; + swizzle_zwxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 2 }); goto negate; + swizzle_wwxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 2 }); goto negate; + swizzle_xxyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 2 }); goto negate; + swizzle_yxyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 2 }); goto negate; + swizzle_zxyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 2 }); goto negate; + swizzle_wxyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 2 }); goto negate; + swizzle_xyyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 2 }); goto negate; + swizzle_yyyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 2 }); goto negate; + swizzle_zyyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 2 }); goto negate; + swizzle_wyyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 2 }); goto negate; + swizzle_xzyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 2 }); goto negate; + swizzle_yzyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 2 }); goto negate; + swizzle_zzyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 2 }); goto negate; + swizzle_wzyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 2 }); goto negate; + swizzle_xwyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 2 }); goto negate; + swizzle_ywyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 2 }); goto negate; + swizzle_zwyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 2 }); goto negate; + swizzle_wwyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 2 }); goto negate; + swizzle_xxzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 2 }); goto negate; + swizzle_yxzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 2 }); goto negate; + swizzle_zxzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 2 }); goto negate; + swizzle_wxzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 2 }); goto negate; + swizzle_xyzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 2 }); goto negate; + swizzle_yyzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 2 }); goto negate; + swizzle_zyzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 2 }); goto negate; + swizzle_wyzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 2 }); goto negate; + swizzle_xzzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 2 }); goto negate; + swizzle_yzzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 2 }); goto negate; + swizzle_zzzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 2 }); goto negate; + swizzle_wzzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 2 }); goto negate; + swizzle_xwzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 2 }); goto negate; + swizzle_ywzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 2 }); goto negate; + swizzle_zwzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 2 }); goto negate; + swizzle_wwzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 2 }); goto negate; + swizzle_xxwz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 2 }); goto negate; + swizzle_yxwz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 2 }); goto negate; + swizzle_zxwz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 2 }); goto negate; + swizzle_wxwz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 2 }); goto negate; + swizzle_xywz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 2 }); goto negate; + swizzle_yywz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 2 }); goto negate; + swizzle_zywz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 2 }); goto negate; + swizzle_wywz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 2 }); goto negate; + swizzle_xzwz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 2 }); goto negate; + swizzle_yzwz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 2 }); goto negate; + swizzle_zzwz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 2 }); goto negate; + swizzle_wzwz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 2 }); goto negate; + swizzle_xwwz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 2 }); goto negate; + swizzle_ywwz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 2 }); goto negate; + swizzle_zwwz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 2 }); goto negate; + swizzle_wwwz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 2 }); goto negate; + swizzle_xxxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 3 }); goto negate; + swizzle_yxxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 3 }); goto negate; + swizzle_zxxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 3 }); goto negate; + swizzle_wxxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 3 }); goto negate; + swizzle_xyxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 3 }); goto negate; + swizzle_yyxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 3 }); goto negate; + swizzle_zyxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 3 }); goto negate; + swizzle_wyxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 3 }); goto negate; + swizzle_xzxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 3 }); goto negate; + swizzle_yzxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 3 }); goto negate; + swizzle_zzxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 3 }); goto negate; + swizzle_wzxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 3 }); goto negate; + swizzle_xwxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 3 }); goto negate; + swizzle_ywxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 3 }); goto negate; + swizzle_zwxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 3 }); goto negate; + swizzle_wwxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 3 }); goto negate; + swizzle_xxyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 3 }); goto negate; + swizzle_yxyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 3 }); goto negate; + swizzle_zxyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 3 }); goto negate; + swizzle_wxyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 3 }); goto negate; + swizzle_xyyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 3 }); goto negate; + swizzle_yyyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 3 }); goto negate; + swizzle_zyyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 3 }); goto negate; + swizzle_wyyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 3 }); goto negate; + swizzle_xzyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 3 }); goto negate; + swizzle_yzyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 3 }); goto negate; + swizzle_zzyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 3 }); goto negate; + swizzle_wzyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 3 }); goto negate; + swizzle_xwyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 3 }); goto negate; + swizzle_ywyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 3 }); goto negate; + swizzle_zwyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 3 }); goto negate; + swizzle_wwyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 3 }); goto negate; + swizzle_xxzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 3 }); goto negate; + swizzle_yxzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 3 }); goto negate; + swizzle_zxzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 3 }); goto negate; + swizzle_wxzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 3 }); goto negate; + swizzle_xyzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 3 }); goto negate; + swizzle_yyzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 3 }); goto negate; + swizzle_zyzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 3 }); goto negate; + swizzle_wyzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 3 }); goto negate; + swizzle_xzzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 3 }); goto negate; + swizzle_yzzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 3 }); goto negate; + swizzle_zzzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 3 }); goto negate; + swizzle_wzzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 3 }); goto negate; + swizzle_xwzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 3 }); goto negate; + swizzle_ywzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 3 }); goto negate; + swizzle_zwzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 3 }); goto negate; + swizzle_wwzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 3 }); goto negate; + swizzle_xxww: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 3 }); goto negate; + swizzle_yxww: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 3 }); goto negate; + swizzle_zxww: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 3 }); goto negate; + swizzle_wxww: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 3 }); goto negate; + swizzle_xyww: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 3 }); goto negate; + swizzle_yyww: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 3 }); goto negate; + swizzle_zyww: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 3 }); goto negate; + swizzle_wyww: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 3 }); goto negate; + swizzle_xzww: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 3 }); goto negate; + swizzle_yzww: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 3 }); goto negate; + swizzle_zzww: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 3 }); goto negate; + swizzle_wzww: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 3 }); goto negate; + swizzle_xwww: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 3 }); goto negate; + swizzle_ywww: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 3 }); goto negate; + swizzle_zwww: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 3 }); goto negate; + swizzle_wwww: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 3 }); goto negate; + static void *swizzle_table[256] = { + &&swizzle_xxxx, &&swizzle_yxxx, &&swizzle_zxxx, &&swizzle_wxxx, + &&swizzle_xyxx, &&swizzle_yyxx, &&swizzle_zyxx, &&swizzle_wyxx, + &&swizzle_xzxx, &&swizzle_yzxx, &&swizzle_zzxx, &&swizzle_wzxx, + &&swizzle_xwxx, &&swizzle_ywxx, &&swizzle_zwxx, &&swizzle_wwxx, + &&swizzle_xxyx, &&swizzle_yxyx, &&swizzle_zxyx, &&swizzle_wxyx, + &&swizzle_xyyx, &&swizzle_yyyx, &&swizzle_zyyx, &&swizzle_wyyx, + &&swizzle_xzyx, &&swizzle_yzyx, &&swizzle_zzyx, &&swizzle_wzyx, + &&swizzle_xwyx, &&swizzle_ywyx, &&swizzle_zwyx, &&swizzle_wwyx, + &&swizzle_xxzx, &&swizzle_yxzx, &&swizzle_zxzx, &&swizzle_wxzx, + &&swizzle_xyzx, &&swizzle_yyzx, &&swizzle_zyzx, &&swizzle_wyzx, + &&swizzle_xzzx, &&swizzle_yzzx, &&swizzle_zzzx, &&swizzle_wzzx, + &&swizzle_xwzx, &&swizzle_ywzx, &&swizzle_zwzx, &&swizzle_wwzx, + &&swizzle_xxwx, &&swizzle_yxwx, &&swizzle_zxwx, &&swizzle_wxwx, + &&swizzle_xywx, &&swizzle_yywx, &&swizzle_zywx, &&swizzle_wywx, + &&swizzle_xzwx, &&swizzle_yzwx, &&swizzle_zzwx, &&swizzle_wzwx, + &&swizzle_xwwx, &&swizzle_ywwx, &&swizzle_zwwx, &&swizzle_wwwx, + &&swizzle_xxxy, &&swizzle_yxxy, &&swizzle_zxxy, &&swizzle_wxxy, + &&swizzle_xyxy, &&swizzle_yyxy, &&swizzle_zyxy, &&swizzle_wyxy, + &&swizzle_xzxy, &&swizzle_yzxy, &&swizzle_zzxy, &&swizzle_wzxy, + &&swizzle_xwxy, &&swizzle_ywxy, &&swizzle_zwxy, &&swizzle_wwxy, + &&swizzle_xxyy, &&swizzle_yxyy, &&swizzle_zxyy, &&swizzle_wxyy, + &&swizzle_xyyy, &&swizzle_yyyy, &&swizzle_zyyy, &&swizzle_wyyy, + &&swizzle_xzyy, &&swizzle_yzyy, &&swizzle_zzyy, &&swizzle_wzyy, + &&swizzle_xwyy, &&swizzle_ywyy, &&swizzle_zwyy, &&swizzle_wwyy, + &&swizzle_xxzy, &&swizzle_yxzy, &&swizzle_zxzy, &&swizzle_wxzy, + &&swizzle_xyzy, &&swizzle_yyzy, &&swizzle_zyzy, &&swizzle_wyzy, + &&swizzle_xzzy, &&swizzle_yzzy, &&swizzle_zzzy, &&swizzle_wzzy, + &&swizzle_xwzy, &&swizzle_ywzy, &&swizzle_zwzy, &&swizzle_wwzy, + &&swizzle_xxwy, &&swizzle_yxwy, &&swizzle_zxwy, &&swizzle_wxwy, + &&swizzle_xywy, &&swizzle_yywy, &&swizzle_zywy, &&swizzle_wywy, + &&swizzle_xzwy, &&swizzle_yzwy, &&swizzle_zzwy, &&swizzle_wzwy, + &&swizzle_xwwy, &&swizzle_ywwy, &&swizzle_zwwy, &&swizzle_wwwy, + &&swizzle_xxxz, &&swizzle_yxxz, &&swizzle_zxxz, &&swizzle_wxxz, + &&swizzle_xyxz, &&swizzle_yyxz, &&swizzle_zyxz, &&swizzle_wyxz, + &&swizzle_xzxz, &&swizzle_yzxz, &&swizzle_zzxz, &&swizzle_wzxz, + &&swizzle_xwxz, &&swizzle_ywxz, &&swizzle_zwxz, &&swizzle_wwxz, + &&swizzle_xxyz, &&swizzle_yxyz, &&swizzle_zxyz, &&swizzle_wxyz, + &&swizzle_xyyz, &&swizzle_yyyz, &&swizzle_zyyz, &&swizzle_wyyz, + &&swizzle_xzyz, &&swizzle_yzyz, &&swizzle_zzyz, &&swizzle_wzyz, + &&swizzle_xwyz, &&swizzle_ywyz, &&swizzle_zwyz, &&swizzle_wwyz, + &&swizzle_xxzz, &&swizzle_yxzz, &&swizzle_zxzz, &&swizzle_wxzz, + &&swizzle_xyzz, &&swizzle_yyzz, &&swizzle_zyzz, &&swizzle_wyzz, + &&swizzle_xzzz, &&swizzle_yzzz, &&swizzle_zzzz, &&swizzle_wzzz, + &&swizzle_xwzz, &&swizzle_ywzz, &&swizzle_zwzz, &&swizzle_wwzz, + &&swizzle_xxwz, &&swizzle_yxwz, &&swizzle_zxwz, &&swizzle_wxwz, + &&swizzle_xywz, &&swizzle_yywz, &&swizzle_zywz, &&swizzle_wywz, + &&swizzle_xzwz, &&swizzle_yzwz, &&swizzle_zzwz, &&swizzle_wzwz, + &&swizzle_xwwz, &&swizzle_ywwz, &&swizzle_zwwz, &&swizzle_wwwz, + &&swizzle_xxxw, &&swizzle_yxxw, &&swizzle_zxxw, &&swizzle_wxxw, + &&swizzle_xyxw, &&swizzle_yyxw, &&swizzle_zyxw, &&swizzle_wyxw, + &&swizzle_xzxw, &&swizzle_yzxw, &&swizzle_zzxw, &&swizzle_wzxw, + &&swizzle_xwxw, &&swizzle_ywxw, &&swizzle_zwxw, &&swizzle_wwxw, + &&swizzle_xxyw, &&swizzle_yxyw, &&swizzle_zxyw, &&swizzle_wxyw, + &&swizzle_xyyw, &&swizzle_yyyw, &&swizzle_zyyw, &&swizzle_wyyw, + &&swizzle_xzyw, &&swizzle_yzyw, &&swizzle_zzyw, &&swizzle_wzyw, + &&swizzle_xwyw, &&swizzle_ywyw, &&swizzle_zwyw, &&swizzle_wwyw, + &&swizzle_xxzw, &&swizzle_yxzw, &&swizzle_zxzw, &&swizzle_wxzw, + &&swizzle_xyzw, &&swizzle_yyzw, &&swizzle_zyzw, &&swizzle_wyzw, + &&swizzle_xzzw, &&swizzle_yzzw, &&swizzle_zzzw, &&swizzle_wzzw, + &&swizzle_xwzw, &&swizzle_ywzw, &&swizzle_zwzw, &&swizzle_wwzw, + &&swizzle_xxww, &&swizzle_yxww, &&swizzle_zxww, &&swizzle_wxww, + &&swizzle_xyww, &&swizzle_yyww, &&swizzle_zyww, &&swizzle_wyww, + &&swizzle_xzww, &&swizzle_yzww, &&swizzle_zzww, &&swizzle_wzww, + &&swizzle_xwww, &&swizzle_ywww, &&swizzle_zwww, &&swizzle_wwww, + }; +#undef swizzle + static const pr_ivec4_t neg[16] = { + { 0, 0, 0, 0 }, + { 1<<31, 0, 0, 0 }, + { 0, 1<<31, 0, 0 }, + { 1<<31, 1<<31, 0, 0 }, + { 0, 0, 1<<31, 0 }, + { 1<<31, 0, 1<<31, 0 }, + { 0, 1<<31, 1<<31, 0 }, + { 1<<31, 1<<31, 1<<31, 0 }, + { 0, 0, 0, 1<<31 }, + { 1<<31, 0, 0, 1<<31 }, + { 0, 1<<31, 0, 1<<31 }, + { 1<<31, 1<<31, 0, 1<<31 }, + { 0, 0, 1<<31, 1<<31 }, + { 1<<31, 0, 1<<31, 1<<31 }, + { 0, 1<<31, 1<<31, 1<<31 }, + { 1<<31, 1<<31, 1<<31, 1<<31 }, + }; + static const pr_ivec4_t zero[16] = { + { ~0, ~0, ~0, ~0 }, + { 0, ~0, ~0, ~0 }, + { ~0, 0, ~0, ~0 }, + { 0, 0, ~0, ~0 }, + { ~0, ~0, 0, ~0 }, + { 0, ~0, 0, ~0 }, + { ~0, 0, 0, ~0 }, + { 0, 0, 0, ~0 }, + { ~0, ~0, ~0, 0 }, + { 0, ~0, ~0, 0 }, + { ~0, 0, ~0, 0 }, + { 0, 0, ~0, 0 }, + { ~0, ~0, 0, 0 }, + { 0, ~0, 0, 0 }, + { ~0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + }; + +do_swizzle: + goto *swizzle_table[swiz & 0xff]; +negate: + vec ^= neg[(swiz >> 8) & 0xf]; + vec &= zero[(swiz >> 12) & 0xf]; + return vec; +} + static void pr_exec_ruamoko (progs_t *pr, int exitdepth) { @@ -2616,6 +2989,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; // 1 1110 OP_op_T (LE, u, uint, uivec2, uivec4, <=); + case OP_SWIZZLE_F: + OPC(ivec4) = pr_swizzle_f (OPA(ivec4), st->b); + break; //FIXME misc ops OP_op_T (LE, U, ulong, ulvec2, ulvec4, <=); //FIXME misc ops diff --git a/libs/gamecode/swizzle.py b/libs/gamecode/swizzle.py new file mode 100644 index 000000000..673f5aec4 --- /dev/null +++ b/libs/gamecode/swizzle.py @@ -0,0 +1,21 @@ +def iter(func): + for i in range(4): + for j in range(4): + for k in range(4): + for l in range(4): + func(i, j, k, l) + +coord=['x', 'y', 'z', 'w'] +def label(i, j, k, l): + return f"swizzle_{coord[l]}{coord[k]}{coord[j]}{coord[i]}" + +def print_ref(i, j, k, l): + print(f"\t\t&&{label(i, j, k, l)},") + +def print_op(i, j, k, l): + print(f"\t{label(i, j, k, l)}: vec = swizzle (vec, (pr_ivec4_t) {{ {l}, {k}, {j}, {i} }}); goto negate;") + +iter(print_op) +print("\tstatic void *swizzle_table[256] = {") +iter(print_ref) +print("\t};") From b6f9b6843472ae97daac2e6e20e4e64ef4d09095 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 19:55:27 +0900 Subject: [PATCH 2100/3664] [gamecode] Implement 64-bit swizzles See commit for 32-bit swizzles. --- libs/gamecode/pr_exec.c | 376 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 040d18b1d..1f8541ed8 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2243,6 +2243,379 @@ negate: return vec; } +static pr_lvec4_t +pr_swizzle_d (pr_lvec4_t vec, pr_ushort_t swiz) +{ + goto do_swizzle; +#define swizzle __builtin_shuffle + swizzle_xxxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 0 }); goto negate; + swizzle_yxxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 0 }); goto negate; + swizzle_zxxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 0 }); goto negate; + swizzle_wxxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 0 }); goto negate; + swizzle_xyxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 0 }); goto negate; + swizzle_yyxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 0 }); goto negate; + swizzle_zyxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 0 }); goto negate; + swizzle_wyxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 0 }); goto negate; + swizzle_xzxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 0 }); goto negate; + swizzle_yzxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 0 }); goto negate; + swizzle_zzxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 0 }); goto negate; + swizzle_wzxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 0 }); goto negate; + swizzle_xwxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 0 }); goto negate; + swizzle_ywxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 0 }); goto negate; + swizzle_zwxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 0 }); goto negate; + swizzle_wwxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 0 }); goto negate; + swizzle_xxyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 0 }); goto negate; + swizzle_yxyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 0 }); goto negate; + swizzle_zxyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 0 }); goto negate; + swizzle_wxyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 0 }); goto negate; + swizzle_xyyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 0 }); goto negate; + swizzle_yyyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 0 }); goto negate; + swizzle_zyyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 0 }); goto negate; + swizzle_wyyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 0 }); goto negate; + swizzle_xzyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 0 }); goto negate; + swizzle_yzyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 0 }); goto negate; + swizzle_zzyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 0 }); goto negate; + swizzle_wzyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 0 }); goto negate; + swizzle_xwyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 0 }); goto negate; + swizzle_ywyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 0 }); goto negate; + swizzle_zwyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 0 }); goto negate; + swizzle_wwyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 0 }); goto negate; + swizzle_xxzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 0 }); goto negate; + swizzle_yxzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 0 }); goto negate; + swizzle_zxzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 0 }); goto negate; + swizzle_wxzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 0 }); goto negate; + swizzle_xyzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 0 }); goto negate; + swizzle_yyzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 0 }); goto negate; + swizzle_zyzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 0 }); goto negate; + swizzle_wyzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 0 }); goto negate; + swizzle_xzzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 0 }); goto negate; + swizzle_yzzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 0 }); goto negate; + swizzle_zzzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 0 }); goto negate; + swizzle_wzzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 0 }); goto negate; + swizzle_xwzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 0 }); goto negate; + swizzle_ywzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 0 }); goto negate; + swizzle_zwzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 0 }); goto negate; + swizzle_wwzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 0 }); goto negate; + swizzle_xxwx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 0 }); goto negate; + swizzle_yxwx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 0 }); goto negate; + swizzle_zxwx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 0 }); goto negate; + swizzle_wxwx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 0 }); goto negate; + swizzle_xywx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 0 }); goto negate; + swizzle_yywx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 0 }); goto negate; + swizzle_zywx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 0 }); goto negate; + swizzle_wywx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 0 }); goto negate; + swizzle_xzwx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 0 }); goto negate; + swizzle_yzwx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 0 }); goto negate; + swizzle_zzwx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 0 }); goto negate; + swizzle_wzwx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 0 }); goto negate; + swizzle_xwwx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 0 }); goto negate; + swizzle_ywwx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 0 }); goto negate; + swizzle_zwwx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 0 }); goto negate; + swizzle_wwwx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 0 }); goto negate; + swizzle_xxxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 1 }); goto negate; + swizzle_yxxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 1 }); goto negate; + swizzle_zxxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 1 }); goto negate; + swizzle_wxxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 1 }); goto negate; + swizzle_xyxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 1 }); goto negate; + swizzle_yyxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 1 }); goto negate; + swizzle_zyxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 1 }); goto negate; + swizzle_wyxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 1 }); goto negate; + swizzle_xzxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 1 }); goto negate; + swizzle_yzxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 1 }); goto negate; + swizzle_zzxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 1 }); goto negate; + swizzle_wzxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 1 }); goto negate; + swizzle_xwxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 1 }); goto negate; + swizzle_ywxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 1 }); goto negate; + swizzle_zwxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 1 }); goto negate; + swizzle_wwxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 1 }); goto negate; + swizzle_xxyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 1 }); goto negate; + swizzle_yxyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 1 }); goto negate; + swizzle_zxyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 1 }); goto negate; + swizzle_wxyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 1 }); goto negate; + swizzle_xyyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 1 }); goto negate; + swizzle_yyyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 1 }); goto negate; + swizzle_zyyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 1 }); goto negate; + swizzle_wyyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 1 }); goto negate; + swizzle_xzyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 1 }); goto negate; + swizzle_yzyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 1 }); goto negate; + swizzle_zzyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 1 }); goto negate; + swizzle_wzyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 1 }); goto negate; + swizzle_xwyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 1 }); goto negate; + swizzle_ywyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 1 }); goto negate; + swizzle_zwyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 1 }); goto negate; + swizzle_wwyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 1 }); goto negate; + swizzle_xxzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 1 }); goto negate; + swizzle_yxzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 1 }); goto negate; + swizzle_zxzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 1 }); goto negate; + swizzle_wxzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 1 }); goto negate; + swizzle_xyzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 1 }); goto negate; + swizzle_yyzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 1 }); goto negate; + swizzle_zyzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 1 }); goto negate; + swizzle_wyzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 1 }); goto negate; + swizzle_xzzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 1 }); goto negate; + swizzle_yzzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 1 }); goto negate; + swizzle_zzzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 1 }); goto negate; + swizzle_wzzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 1 }); goto negate; + swizzle_xwzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 1 }); goto negate; + swizzle_ywzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 1 }); goto negate; + swizzle_zwzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 1 }); goto negate; + swizzle_wwzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 1 }); goto negate; + swizzle_xxwy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 1 }); goto negate; + swizzle_yxwy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 1 }); goto negate; + swizzle_zxwy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 1 }); goto negate; + swizzle_wxwy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 1 }); goto negate; + swizzle_xywy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 1 }); goto negate; + swizzle_yywy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 1 }); goto negate; + swizzle_zywy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 1 }); goto negate; + swizzle_wywy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 1 }); goto negate; + swizzle_xzwy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 1 }); goto negate; + swizzle_yzwy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 1 }); goto negate; + swizzle_zzwy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 1 }); goto negate; + swizzle_wzwy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 1 }); goto negate; + swizzle_xwwy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 1 }); goto negate; + swizzle_ywwy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 1 }); goto negate; + swizzle_zwwy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 1 }); goto negate; + swizzle_wwwy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 1 }); goto negate; + swizzle_xxxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 2 }); goto negate; + swizzle_yxxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 2 }); goto negate; + swizzle_zxxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 2 }); goto negate; + swizzle_wxxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 2 }); goto negate; + swizzle_xyxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 2 }); goto negate; + swizzle_yyxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 2 }); goto negate; + swizzle_zyxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 2 }); goto negate; + swizzle_wyxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 2 }); goto negate; + swizzle_xzxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 2 }); goto negate; + swizzle_yzxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 2 }); goto negate; + swizzle_zzxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 2 }); goto negate; + swizzle_wzxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 2 }); goto negate; + swizzle_xwxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 2 }); goto negate; + swizzle_ywxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 2 }); goto negate; + swizzle_zwxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 2 }); goto negate; + swizzle_wwxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 2 }); goto negate; + swizzle_xxyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 2 }); goto negate; + swizzle_yxyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 2 }); goto negate; + swizzle_zxyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 2 }); goto negate; + swizzle_wxyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 2 }); goto negate; + swizzle_xyyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 2 }); goto negate; + swizzle_yyyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 2 }); goto negate; + swizzle_zyyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 2 }); goto negate; + swizzle_wyyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 2 }); goto negate; + swizzle_xzyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 2 }); goto negate; + swizzle_yzyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 2 }); goto negate; + swizzle_zzyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 2 }); goto negate; + swizzle_wzyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 2 }); goto negate; + swizzle_xwyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 2 }); goto negate; + swizzle_ywyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 2 }); goto negate; + swizzle_zwyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 2 }); goto negate; + swizzle_wwyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 2 }); goto negate; + swizzle_xxzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 2 }); goto negate; + swizzle_yxzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 2 }); goto negate; + swizzle_zxzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 2 }); goto negate; + swizzle_wxzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 2 }); goto negate; + swizzle_xyzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 2 }); goto negate; + swizzle_yyzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 2 }); goto negate; + swizzle_zyzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 2 }); goto negate; + swizzle_wyzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 2 }); goto negate; + swizzle_xzzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 2 }); goto negate; + swizzle_yzzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 2 }); goto negate; + swizzle_zzzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 2 }); goto negate; + swizzle_wzzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 2 }); goto negate; + swizzle_xwzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 2 }); goto negate; + swizzle_ywzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 2 }); goto negate; + swizzle_zwzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 2 }); goto negate; + swizzle_wwzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 2 }); goto negate; + swizzle_xxwz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 2 }); goto negate; + swizzle_yxwz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 2 }); goto negate; + swizzle_zxwz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 2 }); goto negate; + swizzle_wxwz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 2 }); goto negate; + swizzle_xywz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 2 }); goto negate; + swizzle_yywz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 2 }); goto negate; + swizzle_zywz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 2 }); goto negate; + swizzle_wywz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 2 }); goto negate; + swizzle_xzwz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 2 }); goto negate; + swizzle_yzwz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 2 }); goto negate; + swizzle_zzwz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 2 }); goto negate; + swizzle_wzwz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 2 }); goto negate; + swizzle_xwwz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 2 }); goto negate; + swizzle_ywwz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 2 }); goto negate; + swizzle_zwwz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 2 }); goto negate; + swizzle_wwwz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 2 }); goto negate; + swizzle_xxxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 3 }); goto negate; + swizzle_yxxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 3 }); goto negate; + swizzle_zxxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 3 }); goto negate; + swizzle_wxxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 3 }); goto negate; + swizzle_xyxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 3 }); goto negate; + swizzle_yyxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 3 }); goto negate; + swizzle_zyxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 3 }); goto negate; + swizzle_wyxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 3 }); goto negate; + swizzle_xzxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 3 }); goto negate; + swizzle_yzxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 3 }); goto negate; + swizzle_zzxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 3 }); goto negate; + swizzle_wzxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 3 }); goto negate; + swizzle_xwxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 3 }); goto negate; + swizzle_ywxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 3 }); goto negate; + swizzle_zwxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 3 }); goto negate; + swizzle_wwxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 3 }); goto negate; + swizzle_xxyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 3 }); goto negate; + swizzle_yxyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 3 }); goto negate; + swizzle_zxyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 3 }); goto negate; + swizzle_wxyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 3 }); goto negate; + swizzle_xyyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 3 }); goto negate; + swizzle_yyyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 3 }); goto negate; + swizzle_zyyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 3 }); goto negate; + swizzle_wyyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 3 }); goto negate; + swizzle_xzyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 3 }); goto negate; + swizzle_yzyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 3 }); goto negate; + swizzle_zzyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 3 }); goto negate; + swizzle_wzyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 3 }); goto negate; + swizzle_xwyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 3 }); goto negate; + swizzle_ywyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 3 }); goto negate; + swizzle_zwyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 3 }); goto negate; + swizzle_wwyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 3 }); goto negate; + swizzle_xxzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 3 }); goto negate; + swizzle_yxzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 3 }); goto negate; + swizzle_zxzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 3 }); goto negate; + swizzle_wxzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 3 }); goto negate; + swizzle_xyzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 3 }); goto negate; + swizzle_yyzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 3 }); goto negate; + swizzle_zyzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 3 }); goto negate; + swizzle_wyzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 3 }); goto negate; + swizzle_xzzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 3 }); goto negate; + swizzle_yzzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 3 }); goto negate; + swizzle_zzzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 3 }); goto negate; + swizzle_wzzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 3 }); goto negate; + swizzle_xwzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 3 }); goto negate; + swizzle_ywzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 3 }); goto negate; + swizzle_zwzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 3 }); goto negate; + swizzle_wwzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 3 }); goto negate; + swizzle_xxww: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 3 }); goto negate; + swizzle_yxww: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 3 }); goto negate; + swizzle_zxww: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 3 }); goto negate; + swizzle_wxww: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 3 }); goto negate; + swizzle_xyww: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 3 }); goto negate; + swizzle_yyww: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 3 }); goto negate; + swizzle_zyww: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 3 }); goto negate; + swizzle_wyww: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 3 }); goto negate; + swizzle_xzww: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 3 }); goto negate; + swizzle_yzww: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 3 }); goto negate; + swizzle_zzww: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 3 }); goto negate; + swizzle_wzww: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 3 }); goto negate; + swizzle_xwww: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 3 }); goto negate; + swizzle_ywww: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 3 }); goto negate; + swizzle_zwww: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 3 }); goto negate; + swizzle_wwww: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 3 }); goto negate; + static void *swizzle_table[256] = { + &&swizzle_xxxx, &&swizzle_yxxx, &&swizzle_zxxx, &&swizzle_wxxx, + &&swizzle_xyxx, &&swizzle_yyxx, &&swizzle_zyxx, &&swizzle_wyxx, + &&swizzle_xzxx, &&swizzle_yzxx, &&swizzle_zzxx, &&swizzle_wzxx, + &&swizzle_xwxx, &&swizzle_ywxx, &&swizzle_zwxx, &&swizzle_wwxx, + &&swizzle_xxyx, &&swizzle_yxyx, &&swizzle_zxyx, &&swizzle_wxyx, + &&swizzle_xyyx, &&swizzle_yyyx, &&swizzle_zyyx, &&swizzle_wyyx, + &&swizzle_xzyx, &&swizzle_yzyx, &&swizzle_zzyx, &&swizzle_wzyx, + &&swizzle_xwyx, &&swizzle_ywyx, &&swizzle_zwyx, &&swizzle_wwyx, + &&swizzle_xxzx, &&swizzle_yxzx, &&swizzle_zxzx, &&swizzle_wxzx, + &&swizzle_xyzx, &&swizzle_yyzx, &&swizzle_zyzx, &&swizzle_wyzx, + &&swizzle_xzzx, &&swizzle_yzzx, &&swizzle_zzzx, &&swizzle_wzzx, + &&swizzle_xwzx, &&swizzle_ywzx, &&swizzle_zwzx, &&swizzle_wwzx, + &&swizzle_xxwx, &&swizzle_yxwx, &&swizzle_zxwx, &&swizzle_wxwx, + &&swizzle_xywx, &&swizzle_yywx, &&swizzle_zywx, &&swizzle_wywx, + &&swizzle_xzwx, &&swizzle_yzwx, &&swizzle_zzwx, &&swizzle_wzwx, + &&swizzle_xwwx, &&swizzle_ywwx, &&swizzle_zwwx, &&swizzle_wwwx, + &&swizzle_xxxy, &&swizzle_yxxy, &&swizzle_zxxy, &&swizzle_wxxy, + &&swizzle_xyxy, &&swizzle_yyxy, &&swizzle_zyxy, &&swizzle_wyxy, + &&swizzle_xzxy, &&swizzle_yzxy, &&swizzle_zzxy, &&swizzle_wzxy, + &&swizzle_xwxy, &&swizzle_ywxy, &&swizzle_zwxy, &&swizzle_wwxy, + &&swizzle_xxyy, &&swizzle_yxyy, &&swizzle_zxyy, &&swizzle_wxyy, + &&swizzle_xyyy, &&swizzle_yyyy, &&swizzle_zyyy, &&swizzle_wyyy, + &&swizzle_xzyy, &&swizzle_yzyy, &&swizzle_zzyy, &&swizzle_wzyy, + &&swizzle_xwyy, &&swizzle_ywyy, &&swizzle_zwyy, &&swizzle_wwyy, + &&swizzle_xxzy, &&swizzle_yxzy, &&swizzle_zxzy, &&swizzle_wxzy, + &&swizzle_xyzy, &&swizzle_yyzy, &&swizzle_zyzy, &&swizzle_wyzy, + &&swizzle_xzzy, &&swizzle_yzzy, &&swizzle_zzzy, &&swizzle_wzzy, + &&swizzle_xwzy, &&swizzle_ywzy, &&swizzle_zwzy, &&swizzle_wwzy, + &&swizzle_xxwy, &&swizzle_yxwy, &&swizzle_zxwy, &&swizzle_wxwy, + &&swizzle_xywy, &&swizzle_yywy, &&swizzle_zywy, &&swizzle_wywy, + &&swizzle_xzwy, &&swizzle_yzwy, &&swizzle_zzwy, &&swizzle_wzwy, + &&swizzle_xwwy, &&swizzle_ywwy, &&swizzle_zwwy, &&swizzle_wwwy, + &&swizzle_xxxz, &&swizzle_yxxz, &&swizzle_zxxz, &&swizzle_wxxz, + &&swizzle_xyxz, &&swizzle_yyxz, &&swizzle_zyxz, &&swizzle_wyxz, + &&swizzle_xzxz, &&swizzle_yzxz, &&swizzle_zzxz, &&swizzle_wzxz, + &&swizzle_xwxz, &&swizzle_ywxz, &&swizzle_zwxz, &&swizzle_wwxz, + &&swizzle_xxyz, &&swizzle_yxyz, &&swizzle_zxyz, &&swizzle_wxyz, + &&swizzle_xyyz, &&swizzle_yyyz, &&swizzle_zyyz, &&swizzle_wyyz, + &&swizzle_xzyz, &&swizzle_yzyz, &&swizzle_zzyz, &&swizzle_wzyz, + &&swizzle_xwyz, &&swizzle_ywyz, &&swizzle_zwyz, &&swizzle_wwyz, + &&swizzle_xxzz, &&swizzle_yxzz, &&swizzle_zxzz, &&swizzle_wxzz, + &&swizzle_xyzz, &&swizzle_yyzz, &&swizzle_zyzz, &&swizzle_wyzz, + &&swizzle_xzzz, &&swizzle_yzzz, &&swizzle_zzzz, &&swizzle_wzzz, + &&swizzle_xwzz, &&swizzle_ywzz, &&swizzle_zwzz, &&swizzle_wwzz, + &&swizzle_xxwz, &&swizzle_yxwz, &&swizzle_zxwz, &&swizzle_wxwz, + &&swizzle_xywz, &&swizzle_yywz, &&swizzle_zywz, &&swizzle_wywz, + &&swizzle_xzwz, &&swizzle_yzwz, &&swizzle_zzwz, &&swizzle_wzwz, + &&swizzle_xwwz, &&swizzle_ywwz, &&swizzle_zwwz, &&swizzle_wwwz, + &&swizzle_xxxw, &&swizzle_yxxw, &&swizzle_zxxw, &&swizzle_wxxw, + &&swizzle_xyxw, &&swizzle_yyxw, &&swizzle_zyxw, &&swizzle_wyxw, + &&swizzle_xzxw, &&swizzle_yzxw, &&swizzle_zzxw, &&swizzle_wzxw, + &&swizzle_xwxw, &&swizzle_ywxw, &&swizzle_zwxw, &&swizzle_wwxw, + &&swizzle_xxyw, &&swizzle_yxyw, &&swizzle_zxyw, &&swizzle_wxyw, + &&swizzle_xyyw, &&swizzle_yyyw, &&swizzle_zyyw, &&swizzle_wyyw, + &&swizzle_xzyw, &&swizzle_yzyw, &&swizzle_zzyw, &&swizzle_wzyw, + &&swizzle_xwyw, &&swizzle_ywyw, &&swizzle_zwyw, &&swizzle_wwyw, + &&swizzle_xxzw, &&swizzle_yxzw, &&swizzle_zxzw, &&swizzle_wxzw, + &&swizzle_xyzw, &&swizzle_yyzw, &&swizzle_zyzw, &&swizzle_wyzw, + &&swizzle_xzzw, &&swizzle_yzzw, &&swizzle_zzzw, &&swizzle_wzzw, + &&swizzle_xwzw, &&swizzle_ywzw, &&swizzle_zwzw, &&swizzle_wwzw, + &&swizzle_xxww, &&swizzle_yxww, &&swizzle_zxww, &&swizzle_wxww, + &&swizzle_xyww, &&swizzle_yyww, &&swizzle_zyww, &&swizzle_wyww, + &&swizzle_xzww, &&swizzle_yzww, &&swizzle_zzww, &&swizzle_wzww, + &&swizzle_xwww, &&swizzle_ywww, &&swizzle_zwww, &&swizzle_wwww, + }; +#undef swizzle + static const pr_lvec4_t neg[16] = { + { 0l, 0l, 0l, 0l }, + { 1l<<63, 0l, 0l, 0l }, + { 0l, 1l<<63, 0l, 0l }, + { 1l<<63, 1l<<63, 0l, 0l }, + { 0l, 0l, 1l<<63, 0l }, + { 1l<<63, 0l, 1l<<63, 0l }, + { 0l, 1l<<63, 1l<<63, 0l }, + { 1l<<63, 1l<<63, 1l<<63, 0l }, + { 0l, 0l, 0l, 1l<<63 }, + { 1l<<63, 0l, 0l, 1l<<63 }, + { 0l, 1l<<63, 0l, 1l<<63 }, + { 1l<<63, 1l<<63, 0l, 1l<<63 }, + { 0l, 0l, 1l<<63, 1l<<63 }, + { 1l<<63, 0l, 1l<<63, 1l<<63 }, + { 0l, 1l<<63, 1l<<63, 1l<<63 }, + { 1l<<63, 1l<<63, 1l<<63, 1l<<63 }, + }; + static const pr_lvec4_t zero[16] = { + { ~0l, ~0l, ~0l, ~0l }, + { 0l, ~0l, ~0l, ~0l }, + { ~0l, 0l, ~0l, ~0l }, + { 0l, 0l, ~0l, ~0l }, + { ~0l, ~0l, 0l, ~0l }, + { 0l, ~0l, 0l, ~0l }, + { ~0l, 0l, 0l, ~0l }, + { 0l, 0l, 0l, ~0l }, + { ~0l, ~0l, ~0l, 0l }, + { 0l, ~0l, ~0l, 0l }, + { ~0l, 0l, ~0l, 0l }, + { 0l, 0l, ~0l, 0l }, + { ~0l, ~0l, 0l, 0l }, + { 0l, ~0l, 0l, 0l }, + { ~0l, 0l, 0l, 0l }, + { 0l, 0l, 0l, 0l }, + }; + +do_swizzle: + goto *swizzle_table[swiz & 0xff]; +negate: + vec ^= neg[(swiz >> 8) & 0xf]; + vec &= zero[(swiz >> 12) & 0xf]; + return vec; +} + static void pr_exec_ruamoko (progs_t *pr, int exitdepth) { @@ -2994,6 +3367,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; //FIXME misc ops OP_op_T (LE, U, ulong, ulvec2, ulvec4, <=); + case OP_SWIZZLE_D: + OPC(lvec4) = pr_swizzle_d (OPA(lvec4), st->b); + break; //FIXME misc ops // 1 1111 //FIXME conversion 3 From 6de1ba690131c0f351f6a821912b445e038c6956 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 22:54:34 +0900 Subject: [PATCH 2101/3664] [gamecode] Clean up the conversion instructions Float bit-ops as well. Also, add q*v4 and v4*q instructions. There are currently 48 free opcodes, and I might remove the scale instructions, but they could be useful as expanding a single float to a vector would take 3 instructions (copy to temp, swizzle-expand temp, multiply, vs just scale). --- include/QF/pr_comp.h | 60 +++++++++++++++++++++-------------------- libs/gamecode/pr_exec.c | 35 +++++++++++++++--------- 2 files changed, 53 insertions(+), 42 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 541c69978..d72ced1ca 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -484,11 +484,11 @@ typedef enum { OP_GT_F_1, OP_GT_F_2, OP_GT_F_3, OP_GT_F_4, OP_GT_L_1, OP_GT_L_2, OP_GT_L_3, OP_GT_L_4, OP_GT_D_1, OP_GT_D_2, OP_GT_D_3, OP_GT_D_4, - // 0 1011 convert between signed integral and double(XXX how useful as vec?) - OP_CONV_ID_1, OP_CONV_ID_2, OP_CONV_ID_3, OP_CONV_ID_4, - OP_CONV_DI_1, OP_CONV_DI_2, OP_CONV_DI_3, OP_CONV_DI_4, - OP_CONV_LD_1, OP_CONV_LD_2, OP_CONV_LD_3, OP_CONV_LD_4, - OP_CONV_DL_1, OP_CONV_DL_2, OP_CONV_DL_3, OP_CONV_DL_4, + // 0 1011 + OP_spare_1, OP_spare_2, OP_spare_3, OP_spare_4, + OP_spare_5, OP_spare_6, OP_spare_7, OP_spare_8, + OP_spare_9, OP_spare_10, OP_spare_11, OP_spare_12, + OP_spare_13, OP_spare_14, OP_spare_15, OP_spare_16, // comparison // 0 1100 != OP_NE_I_1, OP_NE_I_2, OP_NE_I_3, OP_NE_I_4, @@ -505,11 +505,11 @@ typedef enum { OP_LE_F_1, OP_LE_F_2, OP_LE_F_3, OP_LE_F_4, OP_LE_L_1, OP_LE_L_2, OP_LE_L_3, OP_LE_L_4, OP_LE_D_1, OP_LE_D_2, OP_LE_D_3, OP_LE_D_4, - // 0 1111 convert between signed integral sizes (XXX how useful as vec?) - OP_CONV_IL_1, OP_CONV_IL_2, OP_CONV_IL_3, OP_CONV_IL_4, - OP_CONV_LI_1, OP_CONV_LI_2, OP_CONV_LI_3, OP_CONV_LI_4, - OP_CONV_uU_1, OP_CONV_uU_2, OP_CONV_uU_3, OP_CONV_uU_4, - OP_CONV_Uu_1, OP_CONV_Uu_2, OP_CONV_Uu_3, OP_CONV_Uu_4, + // 0 1111 + OP_spare_17, OP_spare_18, OP_spare_19, OP_spare_20, + OP_spare_21, OP_spare_22, OP_spare_23, OP_spare_24, + OP_spare_25, OP_spare_26, OP_spare_27, OP_spare_28, + OP_spare_29, OP_spare_30, OP_spare_31, OP_spare_32, // 1 0000 c = a * b OP_MUL_I_1, OP_MUL_I_2, OP_MUL_I_3, OP_MUL_I_4, @@ -556,16 +556,16 @@ typedef enum { OP_BITOR_I_1, OP_BITOR_I_2, OP_BITOR_I_3, OP_BITOR_I_4, OP_BITXOR_I_1, OP_BITXOR_I_2, OP_BITXOR_I_3, OP_BITXOR_I_4, OP_BITNOT_I_1, OP_BITNOT_I_2, OP_BITNOT_I_3, OP_BITNOT_I_4, - // 1 1001 < unsigned (float logic and bit ops mixed in) + // 1 1001 < unsigned with swizzle and scale mixed in OP_LT_u_1, OP_LT_u_2, OP_LT_u_3, OP_LT_u_4, - OP_BITAND_F, OP_BITOR_F, OP_BITXOR_F, OP_BITNOT_F, + OP_SWIZZLE_F, OP_SCALE_F_2, OP_SCALE_F_3, OP_SCALE_F_4, OP_LT_U_1, OP_LT_U_2, OP_LT_U_3, OP_LT_U_4, - OP_AND_F, OP_OR_F, OP_XOR_F, OP_NOT_F, - // 1 1010 > unsigned + OP_SWIZZLE_D, OP_SCALE_D_2, OP_SCALE_D_3, OP_SCALE_D_4, + // 1 1010 > unsigned and conversions OP_GT_u_1, OP_GT_u_2, OP_GT_u_3, OP_GT_u_4, - OP_spare, OP_NOT_D, OP_NOT_V, OP_NOT_Q, + OP_CONV_IF_1, OP_CONV_LD_1, OP_CONV_uF_1, OP_CONV_UD_1, OP_GT_U_1, OP_GT_U_2, OP_GT_U_3, OP_GT_U_4, - OP_EQ_V, OP_EQ_Q, OP_NE_V, OP_NE_Q, + OP_CONV_FI_1, OP_CONV_DL_1, OP_CONV_Fu_1, OP_CONV_DU_1, // 1 1011 lea, with, etc OP_LEA_A, OP_LEA_B, OP_LEA_C, OP_LEA_D, OP_LEA_E, OP_ANY_2, OP_ANY_3, OP_ANY_4, @@ -576,21 +576,23 @@ typedef enum { OP_OR_I_1, OP_OR_I_2, OP_OR_I_3, OP_OR_I_4, OP_XOR_I_1, OP_XOR_I_2, OP_XOR_I_3, OP_XOR_I_4, OP_NOT_I_1, OP_NOT_I_2, OP_NOT_I_3, OP_NOT_I_4, - // 1 1101 >= unsigned with float shifts and moves mixed in - OP_GE_u_1, OP_GE_u_2, OP_GE_u_3, OP_GE_u_4, - OP_SHL_F, OP_MOVE_I, OP_MOVE_P, OP_MOVE_PI, - OP_GE_U_1, OP_GE_U_2, OP_GE_U_3, OP_GE_U_4, - OP_SHR_F, OP_MEMSET_I, OP_MEMSET_P, OP_MEMSET_PI, - // 1 1110 <= unsigned with scale and swizzle mixed in + // 1 1101 >= unsigned with q v4 mul and moves mixed in + OP_GE_u_1, OP_GE_u_2, OP_GE_u_3, OP_GE_u_4, + OP_MUL_QV4_F, OP_MOVE_I, OP_MOVE_P, OP_MOVE_PI, + OP_GE_U_1, OP_GE_U_2, OP_GE_U_3, OP_GE_U_4, + OP_MUL_QV4_D, OP_MEMSET_I, OP_MEMSET_P, OP_MEMSET_PI, + // 1 1110 <= unsigned with v4 q mul and conversion mixed in OP_LE_u_1, OP_LE_u_2, OP_LE_u_3, OP_LE_u_4, - OP_SWIZZLE_F, OP_SCALE_F_2, OP_SCALE_F_3, OP_SCALE_F_4, + OP_MUL_V4Q_F, OP_CONV_IL_1, OP_CONV_uU_1, OP_CONV_FD_1, OP_LE_U_1, OP_LE_U_2, OP_LE_U_3, OP_LE_U_4, - OP_SWIZZLE_D, OP_SCALE_D_2, OP_SCALE_D_3, OP_SCALE_D_4, - // 1 1111 convert between integral and float (XXX how useful as vec?) - OP_CONV_IF_1, OP_CONV_IF_2, OP_CONV_IF_3, OP_CONV_IF_4, - OP_CONV_FI_1, OP_CONV_FI_2, OP_CONV_FI_3, OP_CONV_FI_4, - OP_CONV_FD_1, OP_CONV_FD_2, OP_CONV_FD_3, OP_CONV_FD_4, - OP_CONV_DF_1, OP_CONV_DF_2, OP_CONV_DF_3, OP_CONV_DF_4, + OP_MUL_V4Q_D, OP_CONV_LI_1, OP_CONV_Uu_1, OP_CONV_DF_1, + // 1 1111 + OP_spare_33, OP_spare_34, OP_spare_35, OP_spare_36, + OP_spare_37, OP_spare_38, OP_spare_39, OP_spare_40, + OP_spare_41, OP_spare_42, OP_spare_43, OP_spare_44, + OP_spare_45, OP_spare_46, OP_spare_47, OP_spare_48, + + } pr_opcode_e; #define OP_A_SHIFT (9) #define OP_B_SHIFT (11) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 1f8541ed8..9fdb6853e 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3228,14 +3228,20 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_uop_T (BITNOT, I, int, ivec2, ivec4, ~); // 1 1001 OP_op_T (LT, u, uint, uivec2, uivec4, <); - //FIXME float ops + case OP_SWIZZLE_F: + OPC(ivec4) = pr_swizzle_f (OPA(ivec4), st->b); + break; + //FIXME scale ops OP_op_T (LT, U, ulong, ulvec2, ulvec4, <); - //FIXME float ops + case OP_SWIZZLE_D: + OPC(lvec4) = pr_swizzle_d (OPA(lvec4), st->b); + break; + //FIXME scale ops // 1 1010 OP_op_T (GT, u, uint, uivec2, uivec4, >); - //FIXME misc ops + //FIXME conversion ops OP_op_T (GT, U, ulong, ulvec2, ulvec4, >); - //FIXME misc ops + //FIXME conversion ops // 1 1011 case OP_LEA_A: case OP_LEA_B: @@ -3337,7 +3343,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_not_n (NOT, ivec4, 4, +); // 1 1101 OP_op_T (GE, u, uint, uivec2, uivec4, >=); - //FIXME float shift + case OP_MUL_QV4_F: + OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); + break; case OP_MOVE_I: memmove (op_c, op_a, st->b * sizeof (pr_type_t)); break; @@ -3350,7 +3358,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) st->b * sizeof (pr_type_t)); break; OP_op_T (GE, U, ulong, ulvec2, ulvec4, >=); - //FIXME float shift + case OP_MUL_QV4_D: + OPC(dvec4) = qvmuld (OPA(dvec4), OPB(dvec4)); + break; case OP_MEMSET_I: pr_memset (op_c, OPA(int), st->b); break; @@ -3362,17 +3372,16 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; // 1 1110 OP_op_T (LE, u, uint, uivec2, uivec4, <=); - case OP_SWIZZLE_F: - OPC(ivec4) = pr_swizzle_f (OPA(ivec4), st->b); + case OP_MUL_V4Q_F: + OPC(vec4) = vqmulf (OPA(vec4), OPB(vec4)); break; - //FIXME misc ops + OP_op_T (LE, U, ulong, ulvec2, ulvec4, <=); - case OP_SWIZZLE_D: - OPC(lvec4) = pr_swizzle_d (OPA(lvec4), st->b); + case OP_MUL_V4Q_D: + OPC(dvec4) = vqmuld (OPA(dvec4), OPB(dvec4)); break; - //FIXME misc ops + // 1 1111 - //FIXME conversion 3 default: PR_RunError (pr, "Bad opcode o%03o", st->op & OP_MASK); From 09b029d82ca1118a5637f8f723491048ebdb6bb6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 23:00:22 +0900 Subject: [PATCH 2102/3664] [simd] Correct result for cmuld I must have had quite the brain-fart when I wrote that. Yay for tests :) --- include/QF/simd/vec2d.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/QF/simd/vec2d.h b/include/QF/simd/vec2d.h index 6b50ea6b4..206e7f18b 100644 --- a/include/QF/simd/vec2d.h +++ b/include/QF/simd/vec2d.h @@ -107,9 +107,9 @@ VISIBLE vec2d_t cmuld (vec2d_t a, vec2d_t b) { - vec2d_t c = a * b[0]; - c = _mm_addsub_pd (c, (vec2d_t) { c[1], c[0] }); - return c; + vec2d_t c1 = a * b[0]; + vec2d_t c2 = a * b[1]; + return _mm_addsub_pd (c1, (vec2d_t) { c2[1], c2[0] }); } #endif//__QF_simd_vec2d_h From a6badaa05d017a980d6a2682cce7dc90110aa8e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 23:01:47 +0900 Subject: [PATCH 2103/3664] [gamecode] Complete the vector instruction tests Finish up the float tests and add double tests. --- libs/gamecode/test/test-math.c | 111 ++++++++++++++++++++++++++++++--- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/libs/gamecode/test/test-math.c b/libs/gamecode/test/test-math.c index b5daab225..61d8852e9 100644 --- a/libs/gamecode/test/test-math.c +++ b/libs/gamecode/test/test-math.c @@ -5,18 +5,24 @@ static pr_vec4_t float_globals_init[] = { {0, 0, 0, 0}, {1, 2, 3, 8}, {4, 5, 6, 8}, + {0, 0, 0, 7}, {0, 0, 0, 7}, {1, 2, 3, 4}, {5, 6, 7, 8}, + {2, 3, 4, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 7}, + {0, 0, 0, 7}, {0, 0, 0, 7}, {0, 0, 0, 7}, {0, 0, 0, 0}, + + {0, 0, 0, 0}, + {0, 0, 0, 0}, {0, 0, 0, 0}, }; @@ -37,14 +43,16 @@ static pr_vec4_t float_globals_expect[] = { {36, 102, 120, 7}, {52, 70, 136, 7}, - {160, 160, 160, 160}, - {9, 10, 17, 20}, + {36, 102, 120, 0}, + {52, 70, 136, 0}, {-1, -2, -3, 4}, {-1, -2, -3, 4}, + {36, 102, 120, 0}, + {52, 70, 136, 0}, }; -static dstatement_t store_A_statements[] = { +static dstatement_t float_vector_statements[] = { { OP(0, 0, 0, OP_DOT_CC_F), 0, 2, 4 }, { OP(0, 0, 0, OP_MUL_CC_F), 0, 2, 6 }, { OP(0, 0, 0, OP_DOT_VV_F), 8, 12, 16 }, @@ -54,24 +62,109 @@ static dstatement_t store_A_statements[] = { { OP(0, 0, 0, OP_MUL_QV_F), 24, 32, 44 }, { OP(0, 0, 0, OP_MUL_VQ_F), 32, 24, 48 }, - { OP(0, 0, 0, OP_DOT_QQ_F), 24, 32, 52 }, + { OP(0, 0, 0, OP_MUL_QQ_F), 24, 32, 52 }, { OP(0, 0, 0, OP_SWIZZLE_F), 24, 0x07e4, 60 }, - { OP(0, 0, 0, OP_DOT_QQ_F), 52, 60, 52 }, + { OP(0, 0, 0, OP_MUL_QQ_F), 52, 60, 52 }, { OP(0, 0, 0, OP_SWIZZLE_F), 24, 0x07e4, 64 }, - { OP(0, 0, 0, OP_MUL_QQ_F), 60, 32, 56 }, - { OP(0, 0, 0, OP_DOT_QQ_F), 56, 24, 52 }, + { OP(0, 0, 0, OP_MUL_QQ_F), 64, 32, 56 }, + { OP(0, 0, 0, OP_MUL_QQ_F), 56, 24, 56 }, + + { OP(0, 0, 0, OP_MUL_QV4_F), 24, 32, 68 }, + { OP(0, 0, 0, OP_MUL_V4Q_F), 32, 24, 72 }, +}; + +static pr_dvec4_t double_globals_init[] = { + {3, 4, 5, 12}, + {0, 0, 0, 0}, + {1, 2, 3, 8}, + {4, 5, 6, 8}, + + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {1, 2, 3, 4}, + {5, 6, 7, 8}, + + {2, 3, 4, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 7}, + + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {0, 0, 0, 7}, + {0, 0, 0, 0}, + + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, +}; + +static pr_dvec4_t double_globals_expect[] = { + {3, 4, 5, 12}, + {63, 63, -33, 56}, + {1, 2, 3, 8}, + {4, 5, 6, 8}, + + {32, 32, 32, 7}, + {-3, 6, -3, 7}, + {1, 2, 3, 4}, + {5, 6, 7, 8}, + + {2, 3, 4, 0}, + {70, 70, 70, 70}, + {24, 48, 48, -6}, + {36, 102, 120, 7}, + + {52, 70, 136, 7}, + {36, 102, 120, 0}, + {52, 70, 136, 0}, + {-1, -2, -3, 4}, + + {-1, -2, -3, 4}, + {36, 102, 120, 0}, + {52, 70, 136, 0}, +}; + +static dstatement_t double_vector_statements[] = { + { OP(0, 0, 0, OP_DOT_CC_D), 0, 4, 8 }, + { OP(0, 0, 0, OP_MUL_CC_D), 0, 4, 12 }, + { OP(0, 0, 0, OP_DOT_VV_D), 16, 24, 32 }, + { OP(0, 0, 0, OP_CROSS_VV_D), 16, 24, 40 }, + { OP(0, 0, 0, OP_DOT_QQ_D), 48, 56, 72 }, + { OP(0, 0, 0, OP_MUL_QQ_D), 48, 56, 80 }, + { OP(0, 0, 0, OP_MUL_QV_D), 48, 64, 88 }, + { OP(0, 0, 0, OP_MUL_VQ_D), 64, 48, 96 }, + + { OP(0, 0, 0, OP_MUL_QQ_D), 48, 64, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 48, 0x07e4, 120 }, + { OP(0, 0, 0, OP_MUL_QQ_D), 104, 120, 104 }, + + { OP(0, 0, 0, OP_SWIZZLE_D), 48, 0x07e4, 128 }, + { OP(0, 0, 0, OP_MUL_QQ_D), 128, 64, 112 }, + { OP(0, 0, 0, OP_MUL_QQ_D), 112, 48, 112 }, + + { OP(0, 0, 0, OP_MUL_QV4_D), 48, 64, 136 }, + { OP(0, 0, 0, OP_MUL_V4Q_D), 64, 48, 144 }, }; test_t tests[] = { { .desc = "float vector", .num_globals = 4*num_globals(float_globals_init, float_globals_expect), - .num_statements = num_statements (store_A_statements), - .statements = store_A_statements, + .num_statements = num_statements (float_vector_statements), + .statements = float_vector_statements, .init_globals = (pr_int_t *) float_globals_init, .expect_globals = (pr_int_t *) float_globals_expect, }, + { + .desc = "double vector", + .num_globals = 8*num_globals(double_globals_init,double_globals_expect), + .num_statements = num_statements (double_vector_statements), + .statements = double_vector_statements, + .init_globals = (pr_int_t *) double_globals_init, + .expect_globals = (pr_int_t *) double_globals_expect, + }, }; #include "main.c" From 4777f44ba1558a0b0c0024876e60e54c5c4ccccb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Jan 2022 23:50:38 +0900 Subject: [PATCH 2104/3664] [gamecode] Rename test-math to test-vector I decided to stick with the minimal tests per test program rather than try to cram all the math operator tests into the one program. --- libs/gamecode/test/Makemodule.am | 12 ++++++------ libs/gamecode/test/{test-math.c => test-vector.c} | 0 2 files changed, 6 insertions(+), 6 deletions(-) rename libs/gamecode/test/{test-math.c => test-vector.c} (100%) diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 433fad58f..191470c74 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,6 +1,6 @@ libs_gamecode_tests = \ libs/gamecode/test/test-load \ - libs/gamecode/test/test-math \ + libs/gamecode/test/test-vector \ libs/gamecode/test/test-stack \ libs/gamecode/test/test-store @@ -19,11 +19,6 @@ libs_gamecode_test_test_load_SOURCES= \ libs_gamecode_test_test_load_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_load_DEPENDENCIES= $(test_gamecode_libs) -libs_gamecode_test_test_math_SOURCES= \ - libs/gamecode/test/test-math.c -libs_gamecode_test_test_math_LDADD= $(test_gamecode_libs) -libs_gamecode_test_test_math_DEPENDENCIES= $(test_gamecode_libs) - libs_gamecode_test_test_stack_SOURCES= \ libs/gamecode/test/test-stack.c libs_gamecode_test_test_stack_LDADD= $(test_gamecode_libs) @@ -33,3 +28,8 @@ libs_gamecode_test_test_store_SOURCES= \ libs/gamecode/test/test-store.c libs_gamecode_test_test_store_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_store_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_vector_SOURCES= \ + libs/gamecode/test/test-vector.c +libs_gamecode_test_test_vector_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_vector_DEPENDENCIES= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-math.c b/libs/gamecode/test/test-vector.c similarity index 100% rename from libs/gamecode/test/test-math.c rename to libs/gamecode/test/test-vector.c From 5de4c21557a8372828c27b5443febfabc25566b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 4 Jan 2022 14:30:20 +0900 Subject: [PATCH 2105/3664] [gamecode] Fix relative offset jumps Yet another missed sign extension. --- libs/gamecode/pr_exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 9fdb6853e..764b844ce 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1804,7 +1804,7 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st) switch (jump_ind) { case 0: // instruction relative offset - jump_offs = jump_offs + st->a; + jump_offs = jump_offs + (short) st->a; break; case 1: // simple pointer dereference: *a From 9d74fcc181320ef98dc3e218fbd7da4c6ed04d0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 4 Jan 2022 17:50:49 +0900 Subject: [PATCH 2106/3664] [gamecode] Add tests for the basic math ops * / % %% + - As a bonus, includes partial tests for a few extra operators. Several things are broken at this stage, but uncommitted code is already working. --- libs/gamecode/test/Makemodule.am | 24 ++++ libs/gamecode/test/main.c | 9 +- libs/gamecode/test/test-double.c | 192 +++++++++++++++++++++++++++++++ libs/gamecode/test/test-float.c | 192 +++++++++++++++++++++++++++++++ libs/gamecode/test/test-int.c | 146 +++++++++++++++++++++++ libs/gamecode/test/test-long.c | 148 ++++++++++++++++++++++++ 6 files changed, 709 insertions(+), 2 deletions(-) create mode 100644 libs/gamecode/test/test-double.c create mode 100644 libs/gamecode/test/test-float.c create mode 100644 libs/gamecode/test/test-int.c create mode 100644 libs/gamecode/test/test-long.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 191470c74..2df9ef114 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,5 +1,9 @@ libs_gamecode_tests = \ + libs/gamecode/test/test-double \ + libs/gamecode/test/test-float \ + libs/gamecode/test/test-int \ libs/gamecode/test/test-load \ + libs/gamecode/test/test-long \ libs/gamecode/test/test-vector \ libs/gamecode/test/test-stack \ libs/gamecode/test/test-store @@ -14,11 +18,31 @@ test_gamecode_libs= \ libs/gamecode/libQFgamecode.la \ libs/util/libQFutil.la +libs_gamecode_test_test_double_SOURCES= \ + libs/gamecode/test/test-double.c +libs_gamecode_test_test_double_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_double_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_float_SOURCES= \ + libs/gamecode/test/test-float.c +libs_gamecode_test_test_float_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_float_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_int_SOURCES= \ + libs/gamecode/test/test-int.c +libs_gamecode_test_test_int_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_int_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_load_SOURCES= \ libs/gamecode/test/test-load.c libs_gamecode_test_test_load_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_load_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_long_SOURCES= \ + libs/gamecode/test/test-long.c +libs_gamecode_test_test_long_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_long_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_stack_SOURCES= \ libs/gamecode/test/test-stack.c libs_gamecode_test_test_stack_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index e9256dcec..44e91167e 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -84,7 +84,7 @@ setup_test (test_t *test) num_globals += test->extra_globals + test->stack_size; test_pr.globals_size = num_globals; - test_pr.pr_globals = malloc (num_globals * sizeof (pr_type_t)); + test_pr.pr_globals = Sys_Alloc (num_globals * sizeof (pr_type_t)); memcpy (test_pr.pr_globals, test->init_globals, test->num_globals * sizeof (pr_type_t)); memset (test_pr.pr_globals + test->num_globals, 0, @@ -99,6 +99,7 @@ setup_test (test_t *test) test_pr.pr_edict_area = test_pr.pr_globals + test->edict_area; } + test_progs.numstatements = test->num_statements + 1; test_pr.pr_statements = malloc ((test->num_statements + 1) * sizeof (dstatement_t)); memcpy (test_pr.pr_statements, test->statements, @@ -139,7 +140,11 @@ run_test (test_t *test) } else { printf ("test #%zd: %s: critical failure\n", test - tests, test->desc); } - free (test_pr.pr_globals); + + pr_uint_t num_globals = test->num_globals; + num_globals += test->extra_globals + test->stack_size; + Sys_Free (test_pr.pr_globals, num_globals * sizeof (pr_type_t)); + free (test_pr.pr_statements); return ret; } diff --git a/libs/gamecode/test/test-double.c b/libs/gamecode/test/test-double.c new file mode 100644 index 000000000..230ba69ee --- /dev/null +++ b/libs/gamecode/test/test-double.c @@ -0,0 +1,192 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define sq(x) ((x)*(x)) + +static pr_dvec4_t double_binop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_dvec4_t double_binop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 15, -15, -15, 15}, + { 5.0/3, -5.0/3, -5.0/3, 5.0/3}, + { 2, -2, 2, -2}, + { 2, 1, -1, -2}, + { 8, -2, 2, -8}, + { 2, -8, 8, -2}, +}; + +static dstatement_t double_binop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_MUL_D_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_D_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_D_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_D_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_D_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_D_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t double_binop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_MUL_D_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_D_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_D_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_D_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_D_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_D_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t double_binop_3a_statements[] = { + { OP(1, 1, 1, OP_MUL_D_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_MUL_D_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_DIV_D_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_DIV_D_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_REM_D_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_REM_D_1), 6, 14, 38 }, + { OP(1, 1, 1, OP_MOD_D_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_MOD_D_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_ADD_D_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_ADD_D_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_SUB_D_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_SUB_D_1), 6, 14, 62 }, +}; + +static dstatement_t double_binop_3b_statements[] = { + { OP(1, 1, 1, OP_MUL_D_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_MUL_D_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_DIV_D_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_DIV_D_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_REM_D_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_REM_D_3), 2, 10, 34 }, + { OP(1, 1, 1, OP_MOD_D_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_MOD_D_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_ADD_D_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_ADD_D_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_SUB_D_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_SUB_D_3), 2, 10, 58 }, +}; + +static dstatement_t double_binop_4_statements[] = { + { OP(1, 1, 1, OP_MUL_D_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_D_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_D_4), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_D_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_D_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_D_4), 0, 8, 56 }, +}; + +static pr_dvec4_t double_cossin_init[] = { + { 1, 2, 3, 4 }, // 0: output + { M_PI/6, 0, 0, 0 }, // 4: x + { 1, 2, 0, 0 }, // 8: f + { 1, 1, 0, 25 }, // 12: f inc and f0 max + { 0, 0, 0, 0 }, // 16: x2 -> [xx, xx] + // { } // 20: xn +}; + +static pr_dvec4_t double_cossin_expect[] = { + { 0.8660254037844386, 0.49999999999999994, 0, 0 }, // 0: output + { M_PI/6, 0, 0, 0 }, // 4: x + { 25, 26, 0, 0 }, // 8: f + { 1, 1, 0, 25 }, // 12: f inc and f0 max + { -sq(M_PI/6), -sq(M_PI/6), 0, 0 }, // 16: x2 -> [xx, xx] +}; + +static dstatement_t double_cossin_statements[] = { + { OP(0, 0, 0, OP_STORE_A_2), 42, 0, 8 }, // init xn -> [?, x] + { OP(0, 0, 0, OP_STORE_A_2), 40, 0, 16 }, // init xn -> [1, x] + { OP(0, 0, 0, OP_SWIZZLE_D), 8,0xc000, 32 }, // init x2 -> [x, x, 0, 0] + { OP(0, 0, 0, OP_MUL_D_2), 32, 32, 32 }, // x2 -> [x*x, x*x, 0, 0] + { OP(0, 0, 0, OP_SWIZZLE_D), 32,0xc3e4, 32 }, // init x2 -> -x2 + { OP(0, 0, 0, OP_SUB_D_4), 0, 0, 0 }, // init acc (output) to 0 +// loop: + { OP(0, 0, 0, OP_ADD_D_2), 0, 40, 0 }, // acc += xn + { OP(0, 0, 0, OP_MUL_D_2), 40, 32, 40 }, // xn *= x2 + { OP(0, 0, 0, OP_DIV_D_2), 40, 16, 40 }, // xn /= f + { OP(0, 0, 0, OP_ADD_D_2), 16, 24, 16 }, // f += inc + { OP(0, 0, 0, OP_DIV_D_2), 40, 16, 40 }, // xn /= f + { OP(0, 0, 0, OP_ADD_D_2), 16, 24, 16 }, // f += inc + { OP(0, 0, 0, OP_LT_D_1), 16, 30, 46 }, // f0 < fmax + { OP(0, 0, 0, OP_IF_A), -7, 0, 46 }, // f0 < fmax +}; + +test_t tests[] = { + { + .desc = "double binop 1", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_1_statements), + .statements = double_binop_1_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double binop 2", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_2_statements), + .statements = double_binop_2_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double binop 3a", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_3a_statements), + .statements = double_binop_3a_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double binop 3b", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_3b_statements), + .statements = double_binop_3b_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double binop 4", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_statements = num_statements (double_binop_4_statements), + .statements = double_binop_4_statements, + .init_globals = (pr_int_t *) double_binop_init, + .expect_globals = (pr_int_t *) double_binop_expect, + }, + { + .desc = "double cos sin", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(double_cossin_init,double_cossin_expect), + .num_statements = num_statements (double_cossin_statements), + .statements = double_cossin_statements, + .init_globals = (pr_int_t *) double_cossin_init, + .expect_globals = (pr_int_t *) double_cossin_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-float.c b/libs/gamecode/test/test-float.c new file mode 100644 index 000000000..d974931bb --- /dev/null +++ b/libs/gamecode/test/test-float.c @@ -0,0 +1,192 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define sq(x) ((float)(x)*(float)(x)) + +static pr_vec4_t float_binop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_vec4_t float_binop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 15, -15, -15, 15}, + { 1.666666627, -1.666666627, -1.666666627, 1.666666627}, + { 2, -2, 2, -2}, + { 2, 1, -1, -2}, + { 8, -2, 2, -8}, + { 2, -8, 8, -2}, +}; + +static dstatement_t float_binop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_MUL_F_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_F_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_F_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_F_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_F_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_F_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t float_binop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_MUL_F_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_F_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_F_2), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_F_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_F_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_F_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t float_binop_3a_statements[] = { + { OP(1, 1, 1, OP_MUL_F_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_MUL_F_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_DIV_F_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_DIV_F_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_REM_F_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_REM_F_1), 3, 7, 19 }, + { OP(1, 1, 1, OP_MOD_F_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_MOD_F_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_ADD_F_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_ADD_F_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_SUB_F_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_SUB_F_1), 3, 7, 31 }, +}; + +static dstatement_t float_binop_3b_statements[] = { + { OP(1, 1, 1, OP_MUL_F_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_MUL_F_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_DIV_F_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_DIV_F_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_REM_F_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_REM_F_3), 1, 5, 17 }, + { OP(1, 1, 1, OP_MOD_F_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_MOD_F_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_ADD_F_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_ADD_F_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_SUB_F_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_SUB_F_3), 1, 5, 29 }, +}; + +static dstatement_t float_binop_4_statements[] = { + { OP(1, 1, 1, OP_MUL_F_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_F_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_F_4), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_F_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_F_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_F_4), 0, 4, 28 }, +}; + +static pr_vec4_t float_cossin_init[] = { + { 1, 2, 3, 4 }, // 0: output + { M_PI/6, 0, 0, 0 }, // 4: x + { 1, 2, 0, 0 }, // 8: f + { 1, 1, 0, 25 }, // 12: f inc and f0 max + { 0, 0, 0, 0 }, // 16: x2 -> [xx, xx] + // { } // 20: xn +}; + +static pr_vec4_t float_cossin_expect[] = { + { 0.866025388, 0.5, 0, 0 }, // 0: output + { M_PI/6, 0, 0, 0 }, // 4: x + { 25, 26, 0, 0 }, // 8: f + { 1, 1, 0, 25 }, // 12: f inc and f0 max + { -sq(M_PI/6), -sq(M_PI/6), 0, 0 }, // 16: x2 -> [xx, xx] +}; + +static dstatement_t float_cossin_statements[] = { + { OP(0, 0, 0, OP_STORE_A_1), 21, 0, 4 }, // init xn -> [?, x] + { OP(0, 0, 0, OP_STORE_A_1), 20, 0, 8 }, // init xn -> [1, x] + { OP(0, 0, 0, OP_SWIZZLE_F), 4, 0xc000, 16 },// init x2 -> [x, x, 0, 0] + { OP(0, 0, 0, OP_MUL_F_2), 16, 16, 16 }, // x2 -> [x*x, x*x, 0, 0] + { OP(0, 0, 0, OP_SWIZZLE_F), 16, 0xc3e4, 16 },// init x2 -> -x2 + { OP(0, 0, 0, OP_SUB_F_4), 0, 0, 0 }, // init acc (output) to 0 +// loop: + { OP(0, 0, 0, OP_ADD_F_2), 0, 20, 0 }, // acc += xn + { OP(0, 0, 0, OP_MUL_F_2), 20, 16, 20 }, // xn *= x2 + { OP(0, 0, 0, OP_DIV_F_2), 20, 8, 20 }, // xn /= f + { OP(0, 0, 0, OP_ADD_F_2), 8, 12, 8 }, // f += inc + { OP(0, 0, 0, OP_DIV_F_2), 20, 8, 20 }, // xn /= f + { OP(0, 0, 0, OP_ADD_F_2), 8, 12, 8 }, // f += inc + { OP(0, 0, 0, OP_LT_F_1), 8, 15, 23 }, // f0 < fmax + { OP(0, 0, 0, OP_IF_A), -7, 0, 23 }, // f0 < fmax +}; + +test_t tests[] = { + { + .desc = "float binop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_1_statements), + .statements = float_binop_1_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float binop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_2_statements), + .statements = float_binop_2_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float binop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_3a_statements), + .statements = float_binop_3a_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float binop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_3b_statements), + .statements = float_binop_3b_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float binop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_statements = num_statements (float_binop_4_statements), + .statements = float_binop_4_statements, + .init_globals = (pr_int_t *) float_binop_init, + .expect_globals = (pr_int_t *) float_binop_expect, + }, + { + .desc = "float cos sin", + .extra_globals = 4 * 1, + .num_globals = 4 * num_globals (float_cossin_init, float_cossin_expect), + .num_statements = num_statements (float_cossin_statements), + .statements = float_cossin_statements, + .init_globals = (pr_int_t *) float_cossin_init, + .expect_globals = (pr_int_t *) float_cossin_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-int.c b/libs/gamecode/test/test-int.c new file mode 100644 index 000000000..08cfe3596 --- /dev/null +++ b/libs/gamecode/test/test-int.c @@ -0,0 +1,146 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t int_binop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t int_binop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 15, -15, -15, 15}, + { 1, -1, -1, 1}, + { 2, -2, 2, -2}, + { 2, 1, -1, -2}, + { 8, -2, 2, -8}, + { 2, -8, 8, -2}, +}; + +static dstatement_t int_binop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_MUL_I_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_I_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_I_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_I_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t int_binop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_MUL_I_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_I_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_I_2), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_I_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_I_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_I_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t int_binop_3a_statements[] = { + { OP(1, 1, 1, OP_MUL_I_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_MUL_I_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_DIV_I_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_DIV_I_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_REM_I_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_REM_I_1), 3, 7, 19 }, + { OP(1, 1, 1, OP_MOD_I_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_MOD_I_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_ADD_I_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_ADD_I_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_SUB_I_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_SUB_I_1), 3, 7, 31 }, +}; + +static dstatement_t int_binop_3b_statements[] = { + { OP(1, 1, 1, OP_MUL_I_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_MUL_I_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_DIV_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_DIV_I_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_REM_I_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_REM_I_3), 1, 5, 17 }, + { OP(1, 1, 1, OP_MOD_I_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_MOD_I_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_ADD_I_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_ADD_I_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_SUB_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_SUB_I_3), 1, 5, 29 }, +}; + +static dstatement_t int_binop_4_statements[] = { + { OP(1, 1, 1, OP_MUL_I_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_I_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_I_4), 0, 4, 16 }, + { OP(1, 1, 1, OP_MOD_I_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_ADD_I_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_SUB_I_4), 0, 4, 28 }, +}; + +test_t tests[] = { + { + .desc = "int binop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_1_statements), + .statements = int_binop_1_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, + { + .desc = "int binop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_2_statements), + .statements = int_binop_2_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, + { + .desc = "int binop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_3a_statements), + .statements = int_binop_3a_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, + { + .desc = "int binop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_3b_statements), + .statements = int_binop_3b_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, + { + .desc = "int binop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_statements = num_statements (int_binop_4_statements), + .statements = int_binop_4_statements, + .init_globals = (pr_int_t *) int_binop_init, + .expect_globals = (pr_int_t *) int_binop_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-long.c b/libs/gamecode/test/test-long.c new file mode 100644 index 000000000..7777b38e0 --- /dev/null +++ b/libs/gamecode/test/test-long.c @@ -0,0 +1,148 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define sq(x) ((x)*(x)) + +static pr_lvec4_t long_binop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_lvec4_t long_binop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 15, -15, -15, 15}, + { 5.0/3, -5.0/3, -5.0/3, 5.0/3}, + { 2, -2, 2, -2}, + { 2, 1, -1, -2}, + { 8, -2, 2, -8}, + { 2, -8, 8, -2}, +}; + +static dstatement_t long_binop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_MUL_L_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_L_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_L_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_L_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t long_binop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_MUL_L_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_L_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_L_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_L_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_L_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_L_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t long_binop_3a_statements[] = { + { OP(1, 1, 1, OP_MUL_L_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_MUL_L_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_DIV_L_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_DIV_L_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_REM_L_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_REM_L_1), 6, 14, 38 }, + { OP(1, 1, 1, OP_MOD_L_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_MOD_L_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_ADD_L_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_ADD_L_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_SUB_L_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_SUB_L_1), 6, 14, 62 }, +}; + +static dstatement_t long_binop_3b_statements[] = { + { OP(1, 1, 1, OP_MUL_L_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_MUL_L_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_DIV_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_DIV_L_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_REM_L_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_REM_L_3), 2, 10, 34 }, + { OP(1, 1, 1, OP_MOD_L_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_MOD_L_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_ADD_L_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_ADD_L_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_SUB_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_SUB_L_3), 2, 10, 58 }, +}; + +static dstatement_t long_binop_4_statements[] = { + { OP(1, 1, 1, OP_MUL_L_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_L_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_L_4), 0, 8, 32 }, + { OP(1, 1, 1, OP_MOD_L_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_ADD_L_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_SUB_L_4), 0, 8, 56 }, +}; + +test_t tests[] = { + { + .desc = "long binop 1", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_1_statements), + .statements = long_binop_1_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, + { + .desc = "long binop 2", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_2_statements), + .statements = long_binop_2_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, + { + .desc = "long binop 3a", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_3a_statements), + .statements = long_binop_3a_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, + { + .desc = "long binop 3b", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_3b_statements), + .statements = long_binop_3b_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, + { + .desc = "long binop 4", + .extra_globals = 8 * 1, + .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_statements = num_statements (long_binop_4_statements), + .statements = long_binop_4_statements, + .init_globals = (pr_int_t *) long_binop_init, + .expect_globals = (pr_int_t *) long_binop_expect, + }, +}; + +#include "main.c" From f2b258ba7602a41cdb9a99eadf5b55e18e495b74 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 4 Jan 2022 17:53:10 +0900 Subject: [PATCH 2107/3664] [gamecode] Add statement bounds checking Statements can be bounds checked in the one place (jump calculation), but memory accesses cannot as they can be used in lea instructions which should never cause an exception (unless one of lea's operands is OOB). --- libs/gamecode/pr_exec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 764b844ce..4ed1be891 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1819,6 +1819,9 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st) jump_offs = OPA(uint) + OPB(int); break; } + if (pr_boundscheck->int_val && jump_offs >= pr->progs->numstatements) { + PR_RunError (pr, "out of bounds: %x", jump_offs); + } return jump_offs - 1; // for st++ } From 2f09ece65bc2889e2a41b2a9ca6d6877ff31aa88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 4 Jan 2022 17:55:20 +0900 Subject: [PATCH 2108/3664] [gamecode] Add more modes to WITH It turned out I had no way of using a pointer or field as the value to load, so all 4 modes are duplicated with loads from where operand b points, but the loaded value interpreted the same way. Also, fixed an error in the calculation of op-b offsets. --- libs/gamecode/pr_exec.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 4ed1be891..6ceebfca0 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1828,21 +1828,35 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st) static pr_pointer_t __attribute__((pure)) pr_with (progs_t *pr, const dstatement_t *st) { - pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, A); pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + pr_type_t *op_b = pr->pr_globals + PR_BASE (pr, st, B) + st->b; + switch (st->a) { + // fixed offset case 0: // hard-0 base return st->b; case 1: // relative to current base - return op_b - pr->pr_globals; + return PR_BASE (pr, st, B) + st->b; case 2: // relative to stack (-ve offset) return *pr->globals.stack + (pr_short_t) st->b; case 3: // relative to edict_area (+ve only) return edict_area + st->b; + + case 4: + // hard-0 base + return pr->pr_globals[st->b].pointer_var; + case 5: + return OPB(pointer); + case 6: + // relative to stack (-ve offset) + return *pr->globals.stack + OPB(int); + case 7: + // relative to edict_area (+ve only) + return edict_area + OPB(uint); } PR_RunError (pr, "Invalid with index: %u", st->a); } @@ -2875,7 +2889,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) } break; case OP_WITH: - pr->pr_bases[st->c] = pr_with (pr, st); + pr->pr_bases[st->c & 3] = pr_with (pr, st); break; case OP_STATE_ft: { From 63db48bf426515e5f1d5a8fcea814fd744216806 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 4 Jan 2022 18:23:32 +0900 Subject: [PATCH 2109/3664] [simd] Add integral loadvec3 versions that set w to 1 Always setting w to 0 made it impossible to use the resulting 4d vectors in division-based operations as they would result in divide-by-zero and thus an unavoidable exception (CPUs don't like integer div-by-zero). I'll probably add similar for float and double, but they're not as critical as they'll just give inf or nan. This also increases my doubts about the value of keeping 3d vector operations. --- include/QF/simd/vec4d.h | 13 +++++++++++++ include/QF/simd/vec4i.h | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 3b87eb14a..d0e3f19bc 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -97,6 +97,7 @@ GNU89INLINE inline vec4d_t qconjd (vec4d_t q) __attribute__((const)); GNU89INLINE inline vec4d_t loadvec3d (const double v3[]) __attribute__((pure)); GNU89INLINE inline void storevec3d (double v3[3], vec4d_t v4); GNU89INLINE inline vec4l_t loadvec3l (const long *v3) __attribute__((pure)); +GNU89INLINE inline vec4l_t loadvec3l1 (const long *v3) __attribute__((pure)); GNU89INLINE inline void storevec3l (long *v3, vec4l_t v4); #ifndef IMPLEMENT_VEC4D_Funcs @@ -307,6 +308,18 @@ loadvec3l (const long *v3) return v4; } +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4l_t +loadvec3l1 (const long *v3) +{ + vec4l_t v4 = { v3[0], v3[1], v3[2], 1 }; + return v4; +} + #ifndef IMPLEMENT_VEC4F_Funcs GNU89INLINE inline #else diff --git a/include/QF/simd/vec4i.h b/include/QF/simd/vec4i.h index 6320cd83a..db303e610 100644 --- a/include/QF/simd/vec4i.h +++ b/include/QF/simd/vec4i.h @@ -38,6 +38,7 @@ GNU89INLINE inline int any4i (vec4i_t v) __attribute__((const)); GNU89INLINE inline int all4i (vec4i_t v) __attribute__((const)); GNU89INLINE inline int none4i (vec4i_t v) __attribute__((const)); GNU89INLINE inline vec4i_t loadvec3i (const int *v3) __attribute__((pure)); +GNU89INLINE inline vec4i_t loadvec3i1 (const int *v3) __attribute__((pure)); GNU89INLINE inline void storevec3i (int *v3, vec4i_t v4); #ifndef IMPLEMENT_VEC4F_Funcs @@ -107,6 +108,18 @@ loadvec3i (const int *v3) return v4; } +#ifndef IMPLEMENT_VEC4F_Funcs +GNU89INLINE inline +#else +VISIBLE +#endif +vec4i_t +loadvec3i1 (const int *v3) +{ + vec4i_t v4 = { v3[0], v3[1], v3[2], 1 }; + return v4; +} + #ifndef IMPLEMENT_VEC4F_Funcs GNU89INLINE inline #else From 59292393e6964e1da3dc3aa065b57d6749df7ab4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 4 Jan 2022 18:36:13 +0900 Subject: [PATCH 2110/3664] [gamecode] Fix up MOD (%%) for integral types Use the new "1" versions of loadvec3 to get a 1 in w to avoid divide-by-zero errors, and use the correct type for longs (forgot to change i to l on the vector types). --- libs/gamecode/pr_exec.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 6ceebfca0..851c24a49 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3133,6 +3133,11 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) // 1 0001 OP_op(DIV, /); +// implement remainder (c %) for integers: +// 5 rem 3 = 2 +// -5 rem 3 = -2 +// 5 rem -3 = 2 +// -5 rem -3 = -2 #define OP_store(d, s) *(d) = s #define OP_remmod_T(OP, T, n, t, l, f, s) \ case OP_##OP##_##T##_##n: \ @@ -3157,9 +3162,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_rem_T (D, 3, double, loadvec3d, vtrunc4d, storevec3d); OP_rem_T (D, 4, dvec4, *, vtrunc4d, OP_store); -// implement true modulo for integers: -// 5 mod 3 = 2 -// -5 mod 3 = 1 +// implement true modulo (python %) for integers: +// 5 mod 3 = 2 +// -5 mod 3 = 1 // 5 mod -3 = -1 // -5 mod -3 = -2 #define OP_mod_Ti(T, n, t, l, m, s) \ @@ -3183,16 +3188,16 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) // 1 0011 OP_mod_Ti (I, 1, int, *, -, OP_store); OP_mod_Ti (I, 2, ivec2, *, +, OP_store); - OP_mod_Ti (I, 3, int, loadvec3i, +, storevec3i); + OP_mod_Ti (I, 3, int, loadvec3i1, +, storevec3i); OP_mod_Ti (I, 4, ivec4, *, +, OP_store); OP_mod_Tf (F, 1, float, *, floorf, OP_store); OP_mod_Tf (F, 2, vec2, *, vfloor2f, OP_store); OP_mod_Tf (F, 3, float, loadvec3f, vfloor4f, storevec3f); OP_mod_Tf (F, 4, vec4, *, vfloor4f, OP_store); OP_mod_Ti (L, 1, long, *, -, OP_store); - OP_mod_Ti (L, 2, ivec2, *, +, OP_store); - OP_mod_Ti (L, 3, long, loadvec3l, +, storevec3l); - OP_mod_Ti (L, 4, ivec4, *, +, OP_store); + OP_mod_Ti (L, 2, lvec2, *, +, OP_store); + OP_mod_Ti (L, 3, long, loadvec3l1, +, storevec3l); + OP_mod_Ti (L, 4, lvec4, *, +, OP_store); OP_mod_Tf (D, 1, double, *, floor, OP_store); OP_mod_Tf (D, 2, dvec2, *, vfloor2d, OP_store); OP_mod_Tf (D, 3, double, loadvec3d, vfloor4d, storevec3d); From 35387b5450da4045f0d70319f29c8996f4cd14b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 4 Jan 2022 19:01:05 +0900 Subject: [PATCH 2111/3664] [gamecode] Fix a pile of incorrect base register refs The problem with copying code is it's all to easy to forget to make all necessary edits. --- libs/gamecode/pr_exec.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 851c24a49..80373aaf3 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1738,7 +1738,7 @@ static pr_type_t * pr_entity_mode (progs_t *pr, const dstatement_t *st, int shift) { pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); - pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); int mm_ind = (st->op >> shift) & 3; pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; pointer_t mm_offs = 0; @@ -1768,7 +1768,7 @@ static pr_type_t * pr_address_mode (progs_t *pr, const dstatement_t *st, int shift) { pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); - pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); int mm_ind = (st->op >> shift) & 3; pointer_t mm_offs = 0; @@ -1793,11 +1793,11 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int shift) return pr->pr_globals + mm_offs; } -static pr_pointer_t +static pr_pointer_t __attribute__((pure)) pr_jump_mode (progs_t *pr, const dstatement_t *st) { pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); - pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); int jump_ind = st->op & 3; pointer_t jump_offs = pr->pr_xstatement; @@ -2675,8 +2675,8 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) } pointer_t st_a = st->a + PR_BASE (pr, st, A); - pointer_t st_b = st->b + PR_BASE (pr, st, A); - pointer_t st_c = st->c + PR_BASE (pr, st, A); + pointer_t st_b = st->b + PR_BASE (pr, st, B); + pointer_t st_c = st->c + PR_BASE (pr, st, C); pr_type_t *op_a = pr->pr_globals + st_a; From 6d9c63999ca1353ffeee85ed99356f5e115c0132 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 4 Jan 2022 20:45:45 +0900 Subject: [PATCH 2112/3664] [gamecode] Rename pr_opcode.c Just to make way for new tables :) --- libs/gamecode/Makemodule.am | 2 +- libs/gamecode/{pr_opcode.c => pr_v6p_opcode.c} | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) rename libs/gamecode/{pr_opcode.c => pr_v6p_opcode.c} (99%) diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index b962f60ad..af7a3d5a2 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -14,8 +14,8 @@ libs_gamecode_libQFgamecode_la_SOURCES= \ libs/gamecode/pr_exec.c \ libs/gamecode/pr_load.c \ libs/gamecode/pr_parse.c \ - libs/gamecode/pr_opcode.c \ libs/gamecode/pr_resolve.c \ libs/gamecode/pr_resource.c \ libs/gamecode/pr_strings.c \ + libs/gamecode/pr_v6p_opcode.c \ libs/gamecode/pr_zone.c diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_v6p_opcode.c similarity index 99% rename from libs/gamecode/pr_opcode.c rename to libs/gamecode/pr_v6p_opcode.c index aff4784de..a4ed63d44 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -1,12 +1,10 @@ /* - #FILENAME# + pr_v6p_opcodes.c - #DESCRIPTION# + Opcode table and checking for v6+ progs. - Copyright (C) 2001 #AUTHOR# - - Author: #AUTHOR# - Date: #DATE# + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2001 Bill Currie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License From 0b674f5ed4e31adad6a5217eb07c4d616e37717d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 5 Jan 2022 19:04:43 +0900 Subject: [PATCH 2113/3664] [gamecode] Clean up some opcode names While working on the new opcode table, I decided a lot of the names were not to my liking. Part of the problem was the earlier clash with the v6p opcode names, but that has been resolved via the v6p tag. --- include/QF/pr_comp.h | 36 ++++++++++---------- libs/gamecode/pr_exec.c | 48 +++++++++++++-------------- libs/gamecode/test/test-vector.c | 56 ++++++++++++++++---------------- 3 files changed, 70 insertions(+), 70 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index d72ced1ca..2785d6913 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -464,10 +464,10 @@ typedef enum { // C complex // V vector (3d) // Q quaternion - OP_DOT_CC_F, OP_DOT_VV_F, OP_DOT_QQ_F, OP_CROSS_VV_F, - OP_MUL_CC_F, OP_MUL_QV_F, OP_MUL_VQ_F, OP_MUL_QQ_F, - OP_DOT_CC_D, OP_DOT_VV_D, OP_DOT_QQ_D, OP_CROSS_VV_D, - OP_MUL_CC_D, OP_MUL_QV_D, OP_MUL_VQ_D, OP_MUL_QQ_D, + OP_CDOT_F, OP_VDOT_F, OP_QDOT_F, OP_CROSS_F, + OP_CMUL_F, OP_QVMUL_F, OP_VQMUL_F, OP_QMUL_F, + OP_CDOT_D, OP_VDOT_D, OP_QDOT_D, OP_CROSS_D, + OP_CMUL_D, OP_QVMUL_D, OP_VQMUL_D, OP_QMUL_D, // comparison // 0 1000 == OP_EQ_I_1, OP_EQ_I_2, OP_EQ_I_3, OP_EQ_I_4, @@ -547,9 +547,9 @@ typedef enum { OP_SHL_L_1, OP_SHL_L_2, OP_SHL_L_3, OP_SHL_L_4, OP_CMP_S, OP_GE_S, OP_LE_S, OP_NOT_S, //OP_CMP_S doubles as NE // 1 0111 c = a >> b - OP_SHR_I_1, OP_SHR_I_2, OP_SHR_I_3, OP_SHR_I_4, + OP_ASR_I_1, OP_ASR_I_2, OP_ASR_I_3, OP_ASR_I_4, OP_SHR_u_1, OP_SHR_u_2, OP_SHR_u_3, OP_SHR_u_4, - OP_SHR_L_1, OP_SHR_L_2, OP_SHR_L_3, OP_SHR_L_4, + OP_ASR_L_1, OP_ASR_L_2, OP_ASR_L_3, OP_ASR_L_4, OP_SHR_U_1, OP_SHR_U_2, OP_SHR_U_3, OP_SHR_U_4, // 1 1000 c = a (& | ^) b or ~a (bitwise ops) OP_BITAND_I_1, OP_BITAND_I_2, OP_BITAND_I_3, OP_BITAND_I_4, @@ -563,29 +563,29 @@ typedef enum { OP_SWIZZLE_D, OP_SCALE_D_2, OP_SCALE_D_3, OP_SCALE_D_4, // 1 1010 > unsigned and conversions OP_GT_u_1, OP_GT_u_2, OP_GT_u_3, OP_GT_u_4, - OP_CONV_IF_1, OP_CONV_LD_1, OP_CONV_uF_1, OP_CONV_UD_1, + OP_CONV_IF, OP_CONV_LD, OP_CONV_uF, OP_CONV_UD, OP_GT_U_1, OP_GT_U_2, OP_GT_U_3, OP_GT_U_4, - OP_CONV_FI_1, OP_CONV_DL_1, OP_CONV_Fu_1, OP_CONV_DU_1, + OP_CONV_FI, OP_CONV_DL, OP_CONV_Fu, OP_CONV_DU, // 1 1011 lea, with, etc - OP_LEA_A, OP_LEA_B, OP_LEA_C, OP_LEA_D, - OP_LEA_E, OP_ANY_2, OP_ANY_3, OP_ANY_4, - OP_PUSHREG, OP_ALL_2, OP_ALL_3, OP_ALL_4, - OP_POPREG, OP_NONE_2, OP_NONE_3, OP_NONE_4, + OP_LEA_A, OP_LEA_B, OP_LEA_C, OP_LEA_D, + OP_LEA_E, OP_ANY_2, OP_ANY_3, OP_ANY_4, + OP_PUSHREGS, OP_ALL_2, OP_ALL_3, OP_ALL_4, + OP_POPREGS, OP_NONE_2, OP_NONE_3, OP_NONE_4, // 1 1100 c = a (&& || ^^) b or !a (logical ops (no short circuit)) OP_AND_I_1, OP_AND_I_2, OP_AND_I_3, OP_AND_I_4, OP_OR_I_1, OP_OR_I_2, OP_OR_I_3, OP_OR_I_4, OP_XOR_I_1, OP_XOR_I_2, OP_XOR_I_3, OP_XOR_I_4, OP_NOT_I_1, OP_NOT_I_2, OP_NOT_I_3, OP_NOT_I_4, // 1 1101 >= unsigned with q v4 mul and moves mixed in - OP_GE_u_1, OP_GE_u_2, OP_GE_u_3, OP_GE_u_4, - OP_MUL_QV4_F, OP_MOVE_I, OP_MOVE_P, OP_MOVE_PI, - OP_GE_U_1, OP_GE_U_2, OP_GE_U_3, OP_GE_U_4, - OP_MUL_QV4_D, OP_MEMSET_I, OP_MEMSET_P, OP_MEMSET_PI, + OP_GE_u_1, OP_GE_u_2, OP_GE_u_3, OP_GE_u_4, + OP_QV4MUL_F, OP_MOVE_I, OP_MOVE_P, OP_MOVE_PI, + OP_GE_U_1, OP_GE_U_2, OP_GE_U_3, OP_GE_U_4, + OP_QV4MUL_D, OP_MEMSET_I, OP_MEMSET_P, OP_MEMSET_PI, // 1 1110 <= unsigned with v4 q mul and conversion mixed in OP_LE_u_1, OP_LE_u_2, OP_LE_u_3, OP_LE_u_4, - OP_MUL_V4Q_F, OP_CONV_IL_1, OP_CONV_uU_1, OP_CONV_FD_1, + OP_V4QMUL_F, OP_CONV_IL_1, OP_CONV_uU_1, OP_CONV_FD_1, OP_LE_U_1, OP_LE_U_2, OP_LE_U_3, OP_LE_U_4, - OP_MUL_V4Q_D, OP_CONV_LI_1, OP_CONV_Uu_1, OP_CONV_DF_1, + OP_V4QMUL_D, OP_CONV_LI_1, OP_CONV_Uu_1, OP_CONV_DF_1, // 1 1111 OP_spare_33, OP_spare_34, OP_spare_35, OP_spare_36, OP_spare_37, OP_spare_38, OP_spare_39, OP_spare_40, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 80373aaf3..717364ea3 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2953,20 +2953,20 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) } break; // 0 0111 - case OP_DOT_CC_F: + case OP_CDOT_F: OPC(vec2) = dot2f (OPA(vec2), OPB(vec2)); break; - case OP_DOT_VV_F: + case OP_VDOT_F: { vec_t d = DotProduct (&OPA(float), &OPB(float)); VectorSet (d, d, d, &OPC(float)); } break; - case OP_DOT_QQ_F: + case OP_QDOT_F: OPC(vec4) = dotf (OPA(vec4), OPB(vec4)); break; - case OP_CROSS_VV_F: + case OP_CROSS_F: { pr_vec4_t a = loadvec3f (&OPA(float)); pr_vec4_t b = loadvec3f (&OPB(float)); @@ -2974,40 +2974,40 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) storevec3f (&OPC(float), c); } break; - case OP_MUL_CC_F: + case OP_CMUL_F: OPC(vec2) = cmulf (OPA(vec2), OPB(vec2)); break; - case OP_MUL_QV_F: + case OP_QVMUL_F: { pr_vec4_t v = loadvec3f (&OPB(float)); v = qvmulf (OPA(vec4), v); storevec3f (&OPC(float), v); } break; - case OP_MUL_VQ_F: + case OP_VQMUL_F: { pr_vec4_t v = loadvec3f (&OPA(float)); v = vqmulf (v, OPB(vec4)); storevec3f (&OPC(float), v); } break; - case OP_MUL_QQ_F: + case OP_QMUL_F: OPC(vec4) = qmulf (OPA(vec4), OPB(vec4)); break; - case OP_DOT_CC_D: + case OP_CDOT_D: OPC(dvec2) = dot2d (OPA(dvec2), OPB(dvec2)); break; - case OP_DOT_VV_D: + case OP_VDOT_D: { double d = DotProduct (&OPA(double), &OPB(double)); VectorSet (d, d, d, &OPC(double)); } break; - case OP_DOT_QQ_D: + case OP_QDOT_D: OPC(dvec4) = dotd (OPA(dvec4), OPB(dvec4)); break; - case OP_CROSS_VV_D: + case OP_CROSS_D: { pr_dvec4_t a = loadvec3d (&OPA(double)); pr_dvec4_t b = loadvec3d (&OPB(double)); @@ -3015,24 +3015,24 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) storevec3d (&OPC(double), c); } break; - case OP_MUL_CC_D: + case OP_CMUL_D: OPC(dvec2) = cmuld (OPA(dvec2), OPB(dvec2)); break; - case OP_MUL_QV_D: + case OP_QVMUL_D: { pr_dvec4_t v = loadvec3d (&OPB(double)); v = qvmuld (OPA(dvec4), v); storevec3d (&OPC(double), v); } break; - case OP_MUL_VQ_D: + case OP_VQMUL_D: { pr_dvec4_t v = loadvec3d (&OPA(double)); v = vqmuld (v, OPB(dvec4)); storevec3d (&OPC(double), v); } break; - case OP_MUL_QQ_D: + case OP_QMUL_D: OPC(dvec4) = qmuld (OPA(dvec4), OPB(dvec4)); break; @@ -3239,9 +3239,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OPC(int) = !OPA(string) || !*PR_GetString (pr, OPA(string)); break; // 1 0111 - OP_op_T (SHR, I, int, ivec2, ivec4, >>); + OP_op_T (ASR, I, int, ivec2, ivec4, >>); OP_op_T (SHR, u, uint, uivec2, uivec4, >>); - OP_op_T (SHR, L, long, lvec2, lvec4, >>); + OP_op_T (ASR, L, long, lvec2, lvec4, >>); OP_op_T (SHR, U, ulong, ulvec2, ulvec4, >>); // 1 1000 OP_op_T (BITAND, I, int, ivec2, ivec4, &); @@ -3293,7 +3293,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_ANY_4: OPC(int) = any4i (OPA(ivec4)); break; - case OP_PUSHREG: + case OP_PUSHREGS: stk = pr_stack_push (pr); STK(uivec4) = pr->pr_bases; break; @@ -3310,7 +3310,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_ALL_4: OPC(int) = all4i (OPA(ivec4)); break; - case OP_POPREG: + case OP_POPREGS: stk = pr_stack_pop (pr); pr->pr_bases = STK(uivec4); break; @@ -3365,7 +3365,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_not_n (NOT, ivec4, 4, +); // 1 1101 OP_op_T (GE, u, uint, uivec2, uivec4, >=); - case OP_MUL_QV4_F: + case OP_QV4MUL_F: OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); break; case OP_MOVE_I: @@ -3380,7 +3380,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) st->b * sizeof (pr_type_t)); break; OP_op_T (GE, U, ulong, ulvec2, ulvec4, >=); - case OP_MUL_QV4_D: + case OP_QV4MUL_D: OPC(dvec4) = qvmuld (OPA(dvec4), OPB(dvec4)); break; case OP_MEMSET_I: @@ -3394,12 +3394,12 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; // 1 1110 OP_op_T (LE, u, uint, uivec2, uivec4, <=); - case OP_MUL_V4Q_F: + case OP_V4QMUL_F: OPC(vec4) = vqmulf (OPA(vec4), OPB(vec4)); break; OP_op_T (LE, U, ulong, ulvec2, ulvec4, <=); - case OP_MUL_V4Q_D: + case OP_V4QMUL_D: OPC(dvec4) = vqmuld (OPA(dvec4), OPB(dvec4)); break; diff --git a/libs/gamecode/test/test-vector.c b/libs/gamecode/test/test-vector.c index 61d8852e9..814893f86 100644 --- a/libs/gamecode/test/test-vector.c +++ b/libs/gamecode/test/test-vector.c @@ -53,25 +53,25 @@ static pr_vec4_t float_globals_expect[] = { }; static dstatement_t float_vector_statements[] = { - { OP(0, 0, 0, OP_DOT_CC_F), 0, 2, 4 }, - { OP(0, 0, 0, OP_MUL_CC_F), 0, 2, 6 }, - { OP(0, 0, 0, OP_DOT_VV_F), 8, 12, 16 }, - { OP(0, 0, 0, OP_CROSS_VV_F), 8, 12, 20 }, - { OP(0, 0, 0, OP_DOT_QQ_F), 24, 28, 36 }, - { OP(0, 0, 0, OP_MUL_QQ_F), 24, 28, 40 }, - { OP(0, 0, 0, OP_MUL_QV_F), 24, 32, 44 }, - { OP(0, 0, 0, OP_MUL_VQ_F), 32, 24, 48 }, + { OP(0, 0, 0, OP_CDOT_F), 0, 2, 4 }, + { OP(0, 0, 0, OP_CMUL_F), 0, 2, 6 }, + { OP(0, 0, 0, OP_VDOT_F), 8, 12, 16 }, + { OP(0, 0, 0, OP_CROSS_F), 8, 12, 20 }, + { OP(0, 0, 0, OP_QDOT_F), 24, 28, 36 }, + { OP(0, 0, 0, OP_QMUL_F), 24, 28, 40 }, + { OP(0, 0, 0, OP_QVMUL_F), 24, 32, 44 }, + { OP(0, 0, 0, OP_VQMUL_F), 32, 24, 48 }, - { OP(0, 0, 0, OP_MUL_QQ_F), 24, 32, 52 }, + { OP(0, 0, 0, OP_QMUL_F), 24, 32, 52 }, { OP(0, 0, 0, OP_SWIZZLE_F), 24, 0x07e4, 60 }, - { OP(0, 0, 0, OP_MUL_QQ_F), 52, 60, 52 }, + { OP(0, 0, 0, OP_QMUL_F), 52, 60, 52 }, { OP(0, 0, 0, OP_SWIZZLE_F), 24, 0x07e4, 64 }, - { OP(0, 0, 0, OP_MUL_QQ_F), 64, 32, 56 }, - { OP(0, 0, 0, OP_MUL_QQ_F), 56, 24, 56 }, + { OP(0, 0, 0, OP_QMUL_F), 64, 32, 56 }, + { OP(0, 0, 0, OP_QMUL_F), 56, 24, 56 }, - { OP(0, 0, 0, OP_MUL_QV4_F), 24, 32, 68 }, - { OP(0, 0, 0, OP_MUL_V4Q_F), 32, 24, 72 }, + { OP(0, 0, 0, OP_QV4MUL_F), 24, 32, 68 }, + { OP(0, 0, 0, OP_V4QMUL_F), 32, 24, 72 }, }; static pr_dvec4_t double_globals_init[] = { @@ -127,25 +127,25 @@ static pr_dvec4_t double_globals_expect[] = { }; static dstatement_t double_vector_statements[] = { - { OP(0, 0, 0, OP_DOT_CC_D), 0, 4, 8 }, - { OP(0, 0, 0, OP_MUL_CC_D), 0, 4, 12 }, - { OP(0, 0, 0, OP_DOT_VV_D), 16, 24, 32 }, - { OP(0, 0, 0, OP_CROSS_VV_D), 16, 24, 40 }, - { OP(0, 0, 0, OP_DOT_QQ_D), 48, 56, 72 }, - { OP(0, 0, 0, OP_MUL_QQ_D), 48, 56, 80 }, - { OP(0, 0, 0, OP_MUL_QV_D), 48, 64, 88 }, - { OP(0, 0, 0, OP_MUL_VQ_D), 64, 48, 96 }, + { OP(0, 0, 0, OP_CDOT_D), 0, 4, 8 }, + { OP(0, 0, 0, OP_CMUL_D), 0, 4, 12 }, + { OP(0, 0, 0, OP_VDOT_D), 16, 24, 32 }, + { OP(0, 0, 0, OP_CROSS_D), 16, 24, 40 }, + { OP(0, 0, 0, OP_QDOT_D), 48, 56, 72 }, + { OP(0, 0, 0, OP_QMUL_D), 48, 56, 80 }, + { OP(0, 0, 0, OP_QVMUL_D), 48, 64, 88 }, + { OP(0, 0, 0, OP_VQMUL_D), 64, 48, 96 }, - { OP(0, 0, 0, OP_MUL_QQ_D), 48, 64, 104 }, + { OP(0, 0, 0, OP_QMUL_D), 48, 64, 104 }, { OP(0, 0, 0, OP_SWIZZLE_D), 48, 0x07e4, 120 }, - { OP(0, 0, 0, OP_MUL_QQ_D), 104, 120, 104 }, + { OP(0, 0, 0, OP_QMUL_D), 104, 120, 104 }, { OP(0, 0, 0, OP_SWIZZLE_D), 48, 0x07e4, 128 }, - { OP(0, 0, 0, OP_MUL_QQ_D), 128, 64, 112 }, - { OP(0, 0, 0, OP_MUL_QQ_D), 112, 48, 112 }, + { OP(0, 0, 0, OP_QMUL_D), 128, 64, 112 }, + { OP(0, 0, 0, OP_QMUL_D), 112, 48, 112 }, - { OP(0, 0, 0, OP_MUL_QV4_D), 48, 64, 136 }, - { OP(0, 0, 0, OP_MUL_V4Q_D), 64, 48, 144 }, + { OP(0, 0, 0, OP_QV4MUL_D), 48, 64, 136 }, + { OP(0, 0, 0, OP_V4QMUL_D), 64, 48, 144 }, }; test_t tests[] = { From 0b92cd3a884b7d4dba788760660bbf0aa5a0661f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 5 Jan 2022 19:09:07 +0900 Subject: [PATCH 2114/3664] [gamecode] Generate the new opcode table As I expect to be tweaking things for a while, it's part of the build process. This will make it a lot easier to adjust mnemonics and argument formats (tweaking the old table was a pain when conventions changed). It's not quite done as it still needs arg widths and types. --- .gitignore | 1 + Makefile.am | 6 + config.d/programs.m4 | 1 + include/QF/pr_comp.h | 11 + libs/gamecode/Makemodule.am | 13 + libs/gamecode/opcodes.py | 503 ++++++++++++++++++++++++++++++++++++ libs/gamecode/pr_opcode.c | 38 +++ 7 files changed, 573 insertions(+) create mode 100644 libs/gamecode/opcodes.py create mode 100644 libs/gamecode/pr_opcode.c diff --git a/.gitignore b/.gitignore index 25d1878ed..a3e375bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ core /ltmain.sh /missing /mkinstalldirs +/py-compile /quakeforge-config /quakeforge.lsm /test-driver diff --git a/Makefile.am b/Makefile.am index dbc83cea2..33aa5b689 100644 --- a/Makefile.am +++ b/Makefile.am @@ -42,6 +42,7 @@ noinst_LTLIBRARIES = noinst_LIBRARIES = noinst_PROGRAMS = noinst_HEADERS = +noinst_PYTHON = plugin_LTLIBRARIES = RANLIB=touch @@ -110,6 +111,11 @@ qcautodep = $(join $(addsuffix $(DEPDIR)/,$(dir $(basename $(1)))),$(addsuffix . r_depfiles_remade= pas_depfiles_remade= +V_PY = $(V_PY_@AM_V@) +V_PY_ = $(V_PY_@AM_DEFAULT_V@) +V_PY_0 = @echo " PY " $@; +V_PY_1 = + V_GLSLANG = $(V_GLSLANG_@AM_V@) V_GLSLANG_ = $(V_GLSLANG_@AM_DEFAULT_V@) V_GLSLANG_0 = @echo " GLSLANG " $@; diff --git a/config.d/programs.m4 b/config.d/programs.m4 index bcff065c5..bb8ac5e9d 100644 --- a/config.d/programs.m4 +++ b/config.d/programs.m4 @@ -8,6 +8,7 @@ AC_PROG_CPP AC_PROG_LN_S AC_PROG_RANLIB AM_PROG_AS +AM_PATH_PYTHON([3]) PKG_PROG_PKG_CONFIG diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 2785d6913..252bb0c18 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -619,6 +619,17 @@ typedef struct v6p_opcode_s { extern const v6p_opcode_t pr_v6p_opcodes[]; const v6p_opcode_t *PR_v6p_Opcode (pr_ushort_t opcode) __attribute__((const)); + +typedef struct opcode_s { + const char *opname; + const char *mnemonic; + int width; ///< number of components (1-4) + int size; ///< component size in words (1-2) + const char *fmt; +} opcode_t; +extern const opcode_t pr_opcodes[512]; +const opcode_t *PR_Opcode (pr_ushort_t opcode) __attribute__((const)); + void PR_Opcode_Init (void); // idempotent typedef struct dstatement_s { diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index af7a3d5a2..620edc7ee 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -13,9 +13,22 @@ libs_gamecode_libQFgamecode_la_SOURCES= \ libs/gamecode/pr_debug.c \ libs/gamecode/pr_exec.c \ libs/gamecode/pr_load.c \ + libs/gamecode/pr_opcode.c \ libs/gamecode/pr_parse.c \ libs/gamecode/pr_resolve.c \ libs/gamecode/pr_resource.c \ libs/gamecode/pr_strings.c \ libs/gamecode/pr_v6p_opcode.c \ libs/gamecode/pr_zone.c + +noinst_PYTHON += $(opcodes_py) + +opcodes_py = $(srcdir)/libs/gamecode/opcodes.py +pr_opcode_cinc = $(top_builddir)/libs/gamecode/pr_opcode.cinc +pr_opcode_src = \ + ${pr_opcode_cinc} +libs/gamecode/pr_opcode.lo: libs/gamecode/pr_opcode.c ${pr_opcode_src} + +$(pr_opcode_cinc): $(opcodes_py) + $(V_PY)$(PYTHON) $(opcodes_py) > $(pr_opcode_cinc).t && \ + $(am__mv) $(pr_opcode_cinc).t $(pr_opcode_cinc) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py new file mode 100644 index 000000000..105f37668 --- /dev/null +++ b/libs/gamecode/opcodes.py @@ -0,0 +1,503 @@ +bitmap_txt = """ +0 0000 mmss load +0 0001 mmss store +0 0010 mmss push +0 0011 mmss pop +0 0100 ccmm branch +0 0101 0nnn rcall 1-8 (0 0100 11mm with 0 params for [r]call0) +0 0101 10ss return +0 0101 1100 returnv +0 0101 1101 with (reg encoded in st->c) +0 0101 111t state +0 0110 ccmm branch2 +0 0111 tooo vecops +0 1ccc ttss compare +1 0ooo ttss mathops +1 011r tuss shiftops +1 0110 o1oo string +1 1ccc t0ss compare2 +1 1000 ooss bitops +1 1001 t1ss scale +1 1001 t100 swizzle +1 1010 d1xx convert +1 1011 00mm lea +1 1011 01ss any +1 1011 0100 lea_e +1 1011 10ss all +1 1011 1000 pushregs +1 1011 11ss none +1 1011 1100 popregs +1 1101 01oo move +1 1101 11oo memset +1 1110 d1xx convert2 +1 11dd t100 vecops2 +1 1100 ooss boolops +n 1111 nnnn +0 1011 nnnn +""" + +branch_fmt=[ + "branch %sa (%Ob)", + "*%Ga", + "%Ga[%sb]", + "%Ga[%Gb]", +] +compare_ccc=[ "eq", "lt", "gt", None, "ne", "ge", "le", None] +type_tt=['I', 'F', 'L', 'D'] +all_formats = { + "opcode": "OP_ALL_{ss+1}", + "mnemonic": "all", + "opname": "all", + "format": "%Ga, %gc", +} +any_formats = { + "opcode": "OP_ANY_{ss+1}", + "mnemonic": "any", + "opname": "any", + "format": "%Ga, %gc", +} +bitops_formats = { + "opcode": "OP_{op_bit[oo].upper()}_I_{ss+1}", + "mnemonic": "{op_bit[oo]}", + "opname": "{op_bit[oo]}", + "format": "{bit_fmt[oo]}", + "args": { + "op_bit":["bitand", "bitor", "bitxor", "bitnot"], + "bit_fmt": [ + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %gc", + ], + }, +} +boolops_formats = { + "opcode": "OP_{op_bool[oo].upper()}_I_{ss+1}", + "mnemonic": "{op_bool[oo]}", + "opname": "{op_bool[oo]}", + "format": "{bool_fmt[oo]}", + "args": { + "op_bool":["and", "or", "xor", "not"], + "bool_fmt": [ + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %gc", + ], + }, +} +branch_formats = { + "opcode": "OP_{op_cond[cc].upper()}_{op_mode[mm]}", + "mnemonic": "{op_cond[cc]}", + "opname": "{op_cond[cc]}", + "format": "{cond_fmt[cc]}{branch_fmt[mm]}", + "args": { + "op_mode": "ABCD", + "op_cond": ["ifnot", "if", "jump", "call"], + "branch_fmt": branch_fmt, + "cond_fmt": ["%Gc ", "%Gc ", "", ""], + }, +} +branch2_formats = { + "opcode": "OP_{op_cond[cc].upper()}_{op_mode[mm]}", + "mnemonic": "{op_cond[cc]}", + "opname": "{op_cond[cc]}", + "format": "%Gc {branch_fmt[mm]}", + "args": { + "op_mode": "ABCD", + "op_cond": ["ifa", "ifbe", "ifb", "ifae"], + "branch_fmt": branch_fmt, + }, +} +compare_formats = { + "opcode": "OP_{op_cmp[ccc].upper()}_{cmp_type[tt]}_{ss+1}", + "mnemonic": "{op_cmp[ccc]}.{cmp_type[tt]}", + "opname": "{op_cmp[ccc]}", + "args": { + "op_cmp": compare_ccc, + "cmp_type":type_tt, + }, +} +compare2_formats = { + "opcode": "OP_{op_cmp[ccc].upper()}_{cmp_type[t]}_{ss+1}", + "mnemonic": "{op_cmp[ccc]}.{cmp_type[t]}", + "opname": "{op_cmp[ccc]}", + "args": { + "op_cmp": compare_ccc, + "cmp_type":['u', 'U'], + }, +} +convert_formats = { + "opcode": "OP_CONV_{op_conv[d*4+xx]}", + "mnemonic": "conv.{op_conv[d*4+xx]}", + "opname": "conv", + "format": "%Ga %gc", + "args": { + "op_conv": ["IF", "LD", "uF", "UD", "FI", "DL", "Fu", "DU"], + }, +} +lea_formats = { + "opcode": "OP_LEA_{op_mode[mm]}", + "mnemonic": "lea", + "opname": "lea", + "format": "{lea_fmt[mm]}", + "args": { + "op_mode": "ABCD", + "lea_fmt": [ + "%ga, %gc", + "*%Ga, %gc", + "*(%Ga + %sb), %gc", + "*(%Ga + %Gb), %gc", + ], + }, +} +lea_e_formats = { + "opcode": "OP_LEA_E", + "mnemonic": "lea", + "opname": "lea", + "format": "%Ga.%Gb(%Ec), %gc", +} +load_formats = { + "opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}", + "mnemonic": "load", + "opname": "load", + "format": "{load_fmt[mm]}", + "args": { + "op_mode": "EBCD", + "load_fmt": [ + "%Ga.%Gb(%Ex), %gc", + "*%Ga, %gc", + "*(%Ga + %sb), %gc", + "*(%Ga + %Gb), %gc", + ], + }, +} +mathops_formats = { + "opcode": "OP_{op_math[ooo].upper()}_{math_type[tt]}_{ss+1}", + "mnemonic": "{op_math[ooo]}.{math_type[tt]}", + "opname": "{op_math[ooo]}", + "args": { + "op_math": ["mul", "div", "rem", "mod", "add", "sub", None, None], + "math_type":type_tt, + }, +} +memset_formats = { + "opcode": "OP_MEMSET_{op_memset[oo].upper()}", + "mnemonic": "memset.{op_memset[oo]}", + "opname": "memset", + "format": "{memset_fmt[oo]}", + "args": { + "op_memset": [None, "i", "p", "pi"], + "memset_fmt": [None, "%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc"], + }, +} +move_formats = { + "opcode": "OP_MOVE_{op_move[oo].upper()}", + "mnemonic": "memset.{op_move[oo]}", + "opname": "memset", + "format": "{move_fmt[oo]}", + "args": { + "op_move": [None, "i", "p", "pi"], + "move_fmt": [None, "%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc"], + }, +} +none_formats = { + "opcode": "OP_NONE_{ss+1}", + "mnemonic": "none", + "opname": "none", + "format": "%Ga, %gc", +} +push_formats = { + "opcode": "OP_PUSH_{op_mode[mm]}_{ss+1}", + "mnemonic": "push", + "opname": "push", + "format": "{push_fmt[mm]}", + "args": { + "op_mode": "ABCD", + "push_fmt": [ + "%Ga", + "*%Ga", + "*(%Ga + %sb)", + "*(%Ga + %Gb)", + ], + }, +} +pushregs_formats = { + "opcode": "OP_PUSHREGS", + "mnemonic": "pushregs", + "opname": "pushregs", + "format": None, +} +pop_formats = { + "opcode": "OP_POP_{op_mode[mm]}_{ss+1}", + "mnemonic": "pop", + "opname": "pop", + "format": "{pop_fmt[mm]}", + "args": { + "op_mode": "ABCD", + "pop_fmt": [ + "%ga", + "*%Ga", + "*(%Ga + %sb)", + "*(%Ga + %Gb)", + ], + }, +} +popregs_formats = { + "opcode": "OP_POPREGS", + "mnemonic": "popregs", + "opname": "popregs", + "format": None, +} +scale_formats = { + "opcode": "OP_SCALE_{scale_type[t]}_{ss+1}", + "mnemonic": "scale.{scale_type[t]}", + "opname": "scale", + "args": { + "scale_type":['F', 'D'], + }, +} +shiftops_formats = { + "opcode": "OP_{op_shift[u*2+r].upper()}_{shift_type[u*2+t]}_{ss+1}", + "mnemonic": "{op_shift[u*2+r]}.{shift_type[u*2+t]}", + "opname": "{op_shift[u*2+r]}", + "args": { + "op_shift": ["shl", "asr", "shl", "shr"], + "shift_type":['I', 'L', 'u', 'U'], + }, +} +state_formats = { + "opcode": "OP_STATE_{state[t]}", + "mnemonic": "state.{state[t]}", + "opname": "state", + "format": "{state_fmt[t]}", + "args": { + "state": ["ft", "ftt"], + "state_fmt": ["%Ga, %Gb", "%Ga, %Gb, %Gc"], + }, +} +store_formats = { + "opcode": "OP_STORE_{op_mode[mm]}_{ss+1}", + "mnemonic": "store", + "opname": "store", + "format": "{store_fmt[mm]}", + "args": { + "op_mode": "ABCD", + "store_fmt": [ + "%Gc, %ga", + "%Gc, *%Ga", + "%Gc, *(%Ga + %sb)", + "%Gc, *(%Ga + %Gb)", + ], + }, +} +string_formats = { + "opcode": "OP_{op_str[o*4+oo].upper()}_S", + "mnemonic": "{op_str[o*4+oo]}.s", + "opname": "{op_str[o*4+oo]}", + "format": "{str_fmt[o*4+oo]}", + "args": { + "op_str": ["eq", "lt", "gt", "add", "cmp", "ge", "le", "not"], + "str_fmt": [ + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %gc", + ], + }, +} +swizzle_formats = { + "opcode": "OP_SWIZZLE_{swiz_type[t]}", + "mnemonic": "swizzle.{swiz_type[t]}", + "opname": "swizzle", + "format": "%Ga %sb %gc", + "args": { + "swiz_type":['F', 'D'], + }, +} +rcall_formats = { + "opcode": "OP_CALL_{nnn+1}", + "mnemonic": "rcall{nnn+1}", + "opname": "rcall{nnn+1}", + "format": "{rcall_fmt[nnn]}", + "args": { + "rcall_fmt": [ + "%Fa (%P0b)", + "%Fa (%P0b, %P1c)", + "%Fa (%P0b, %P1c, %P2x)", + "%Fa (%P0b, %P1c, %P2x, %P3x)", + "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", + "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", + "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", + "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", + ], + }, +} +return_formats = { + "opcode": "OP_RETURN_{ss+1}", + "mnemonic": "return{ss+1}", + "opname": "return{ss+1}", + "format": "%Ra", +} +returnv_formats = { + "opcode": "OP_RETURN_0", + "mnemonic": "return", + "opname": "return", + "format": None, +} +vecops_formats = { + "opcode": "OP_{op_vop[ooo].upper()}_{vop_type[t]}", + "mnemonic": "{op_vop[ooo]}.{vop_type[t]}", + "opname": "{op_vop[ooo]}", + "args": { + "op_vop": ["cdot", "vdot", "qdot", "cross", + "cmul", "qvmul", "vqmul", "qmul"], + "vop_type": ['F', 'D'], + }, +} +vecops2_formats = { + "opcode": "OP_{op_vop[dd].upper()}_{vop_type[t]}", + "mnemonic": "{op_vop[dd]}.{vop_type[t]}", + "opname": "{op_vop[dd]}", + "args": { + "op_vop": [None, "qv4mul", "v4qmul", None], + "vop_type": ['F', 'D'], + }, +} +with_formats = { + "opcode": "OP_WITH", + "mnemonic": "with", + "opname": "with", + "format": "%sa, %sb, $sc", +} + +group_map = { + "all": all_formats, + "any": any_formats, + "bitops": bitops_formats, + "boolops": boolops_formats, + "branch": branch_formats, + "branch2": branch2_formats, + "compare": compare_formats, + "compare2": compare2_formats, + "convert": convert_formats, + "convert2": convert_formats, + "lea": lea_formats, + "lea_e": lea_e_formats, + "load": load_formats, + "mathops": mathops_formats, + "memset": memset_formats, + "move": move_formats, + "none": none_formats, + "push": push_formats, + "pushregs": pushregs_formats, + "pop": pop_formats, + "popregs": popregs_formats, + "scale": scale_formats, + "shiftops": shiftops_formats, + "state": state_formats, + "store": store_formats, + "string": string_formats, + "swizzle": swizzle_formats, + "rcall": rcall_formats, + "return": return_formats, + "returnv": returnv_formats, + "vecops": vecops_formats, + "vecops2": vecops2_formats, + "with": with_formats, +} + +def parse_bits(bit_string): + bits = [""] + isbit = bit_string[0] in ['0', '1'] + lastbit = bit_string[0] + while bit_string: + bit = bit_string[0] + bit_string = bit_string[1:] + if isbit and bit in ['0', '1']: + bits[-1] = bits[-1] + bit + elif lastbit == bit: + bits[-1] = bits[-1] + bit + else: + bits.append(bit) + lastbit = bit + isbit = bit in ['0', '1'] + return bits + +opcodes = [None] * 512 + +def expand_opcodes(bits, group, num=0): + if not bits: + opcodes[num] = group + return + block = bits[0] + bits = bits[1:] + num <<= len(block) + if block[0] in ['0', '1']: + num |= int(block, 2) + expand_opcodes(bits, group, num) + else: + for n in range(1< + + Author: Bill Currie + Date: 2022/1/4 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/progs.h" + +const opcode_t pr_opcodes[512] = { +#include "libs/gamecode/pr_opcode.cinc" +}; From c9b2a740a0233903a0909b04da0c82e245af6b6a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 5 Jan 2022 22:32:07 +0900 Subject: [PATCH 2115/3664] [gamecode] Add etypes for long and ulong And partial implementations in qfcc (most places will generate an internal error (not implemented) or segfault, but some low-hanging fruit has already been implemented). --- include/QF/pr_comp.h | 2 ++ include/QF/progs.h | 2 ++ libs/gamecode/pr_debug.c | 31 +++++++++++++++++++++++++++++++ nq/source/sv_progs.c | 6 +++++- qw/source/sv_progs.c | 6 +++++- tools/qfcc/include/expr.h | 2 ++ tools/qfcc/source/constfold.c | 30 ++++++++++++++++++++++++++++++ tools/qfcc/source/dot_expr.c | 7 +++++++ tools/qfcc/source/expr.c | 9 +++++++++ tools/qfcc/source/expr_bool.c | 3 +++ tools/qfcc/source/statements.c | 11 +++++++++++ tools/qfcc/source/type.c | 14 ++++++++++++++ 12 files changed, 121 insertions(+), 2 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 252bb0c18..abaa4160d 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -67,6 +67,8 @@ typedef enum { ev_uinteger, ev_short, // value is embedded in the opcode ev_double, + ev_long, + ev_ulong, ev_invalid, // invalid type. used for instruction checking ev_type_count // not a type, gives number of types diff --git a/include/QF/progs.h b/include/QF/progs.h index 6f3866ee1..c4b2ef070 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1733,6 +1733,8 @@ typedef struct type_view_s { type_view_func uinteger_view; type_view_func short_view; type_view_func double_view; + type_view_func long_view; + type_view_func ulong_view; type_view_func struct_view; type_view_func union_view; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 9b8d11fde..7e3090a76 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "QF/fbsearch.h" #include "QF/cvar.h" @@ -143,6 +144,10 @@ static void pr_debug_short_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_double_view (qfot_type_t *type, pr_type_t *value, void *_data); +static void pr_debug_long_view (qfot_type_t *type, pr_type_t *value, + void *_data); +static void pr_debug_ulong_view (qfot_type_t *type, pr_type_t *value, + void *_data); static void pr_debug_struct_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_union_view (qfot_type_t *type, pr_type_t *value, @@ -168,6 +173,8 @@ static type_view_t raw_type_view = { pr_debug_uinteger_view, pr_debug_short_view, pr_debug_double_view, + pr_debug_long_view, + pr_debug_ulong_view, pr_debug_struct_view, pr_debug_union_view, pr_debug_enum_view, @@ -1060,6 +1067,12 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) case ev_double: raw_type_view.double_view (type, value, data); break; + case ev_long: + raw_type_view.long_view (type, value, data); + break; + case ev_ulong: + raw_type_view.ulong_view (type, value, data); + break; case ev_invalid: case ev_type_count: dstring_appendstr (data->dstr, ""); @@ -1363,6 +1376,24 @@ pr_debug_double_view (qfot_type_t *type, pr_type_t *value, void *_data) dasprintf (dstr, "%.17g", *(double *)value); } +static void +pr_debug_long_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "%" PRIi64, *(int64_t *)value); +} + +static void +pr_debug_ulong_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "%" PRIu64, *(uint64_t *)value); +} + static void pr_dump_struct (qfot_type_t *type, pr_type_t *value, void *_data, const char *struct_type) diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 58f79bc7e..2c9d82836 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -357,7 +357,11 @@ set_address (sv_def_t *def, void *address) case ev_pointer: case ev_integer: case ev_uinteger: - *(int **)def->field = (int *) address; + *(pr_int_t **)def->field = (pr_int_t *) address; + break; + case ev_long: + case ev_ulong: + *(pr_long_t **)def->field = (pr_long_t *) address; break; } } diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 84873b352..93f6042a0 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -390,7 +390,11 @@ set_address (sv_def_t *def, void *address) case ev_pointer: case ev_integer: case ev_uinteger: - *(int **)def->field = (int *) address; + *(pr_int_t **)def->field = (pr_int_t *) address; + break; + case ev_long: + case ev_ulong: + *(pr_long_t **)def->field = (pr_long_t *) address; break; } } diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 6b8fa8034..5d05f2a40 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -209,6 +209,8 @@ typedef struct ex_value_s { union { const char *string_val; ///< string constant double double_val; ///< double constant + int64_t long_val; ///< signed 64-bit constant + uint64_t ulong_val; ///< unsigned 64-bit constant float float_val; ///< float constant float vector_val[3]; ///< vector constant int entity_val; ///< entity constant diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 2d2c1400d..2459b392f 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1104,6 +1104,8 @@ static operation_t op_void[ev_type_count] = { do_op_invalid, // ev_uinteger do_op_invalid, // ev_short do_op_invalid, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1121,6 +1123,8 @@ static operation_t op_string[ev_type_count] = { do_op_invalid, // ev_uinteger do_op_invalid, // ev_short do_op_invalid, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1138,6 +1142,8 @@ static operation_t op_float[ev_type_count] = { do_op_float, // ev_uinteger do_op_float, // ev_short do_op_double, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1155,6 +1161,8 @@ static operation_t op_vector[ev_type_count] = { do_op_vector, // ev_uinteger do_op_vector, // ev_short do_op_vector, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1172,6 +1180,8 @@ static operation_t op_entity[ev_type_count] = { do_op_invalid, // ev_uinteger do_op_invalid, // ev_short do_op_invalid, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1189,6 +1199,8 @@ static operation_t op_field[ev_type_count] = { do_op_invalid, // ev_uinteger do_op_invalid, // ev_short do_op_invalid, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1206,6 +1218,8 @@ static operation_t op_func[ev_type_count] = { do_op_func, // ev_uinteger do_op_func, // ev_short do_op_func, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_func, // ev_invalid }; @@ -1223,6 +1237,8 @@ static operation_t op_pointer[ev_type_count] = { do_op_pointer, // ev_uinteger do_op_pointer, // ev_short do_op_pointer, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_pointer, // ev_invalid }; @@ -1240,6 +1256,8 @@ static operation_t op_quaternion[ev_type_count] = { do_op_quaternion, // ev_uinteger do_op_quaternion, // ev_short do_op_quaternion, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1257,6 +1275,8 @@ static operation_t op_integer[ev_type_count] = { do_op_uinteger, // ev_uinteger do_op_integer, // ev_short do_op_double, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1274,6 +1294,8 @@ static operation_t op_uinteger[ev_type_count] = { do_op_uinteger, // ev_uinteger do_op_uinteger, // ev_short do_op_double, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1291,6 +1313,8 @@ static operation_t op_short[ev_type_count] = { do_op_uinteger, // ev_uinteger do_op_short, // ev_short do_op_double, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1308,6 +1332,8 @@ static operation_t op_double[ev_type_count] = { do_op_uinteger, // ev_uinteger do_op_short, // ev_short do_op_double, // ev_double + 0, // ev_long + 0, // ev_ulong do_op_invalid, // ev_invalid }; @@ -1325,6 +1351,8 @@ static operation_t op_compound[ev_type_count] = { do_op_compound, // ev_uinteger do_op_compound, // ev_short do_op_compound, // ev_double + do_op_compound, // ev_long + do_op_compound, // ev_ulong do_op_compound, // ev_invalid }; @@ -1342,6 +1370,8 @@ static operation_t *do_op[ev_type_count] = { op_uinteger, // ev_uinteger op_short, // ev_short op_double, // ev_double + 0, // ev_long + 0, // ev_ulong op_compound, // ev_invalid }; diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index cde32c8fd..edd1739a9 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -38,6 +38,7 @@ # include #endif #include +#include #include #include @@ -518,6 +519,12 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) case ev_uinteger: label = va (0, "u %u", e->e.value->v.uinteger_val); break; + case ev_long: + label = va (0, "i %"PRIi64, e->e.value->v.long_val); + break; + case ev_ulong: + label = va (0, "u %"PRIu64, e->e.value->v.ulong_val); + break; case ev_short: label = va (0, "s %d", e->e.value->v.short_val); break; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 26d892c60..d4f36d306 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1633,6 +1633,9 @@ unary_expr (int op, expr_t *e) case ev_quat: QuatNegate (expr_vector (e), q); return new_vector_expr (q); + case ev_long: + case ev_ulong: + internal_error (e, "long not implemented"); case ev_integer: return new_integer_expr (-expr_integer (e)); case ev_uinteger: @@ -1725,6 +1728,9 @@ unary_expr (int op, expr_t *e) return new_integer_expr (!VectorIsZero (expr_vector (e))); case ev_quat: return new_integer_expr (!QuatIsZero (expr_quaternion (e))); + case ev_long: + case ev_ulong: + internal_error (e, "long not implemented"); case ev_integer: return new_integer_expr (!expr_integer (e)); case ev_uinteger: @@ -1791,6 +1797,9 @@ unary_expr (int op, expr_t *e) case ev_quat: QuatConj (expr_vector (e), q); return new_vector_expr (q); + case ev_long: + case ev_ulong: + internal_error (e, "long not implemented"); case ev_integer: return new_integer_expr (~expr_integer (e)); case ev_uinteger: diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index fd21de053..83c202692 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -94,6 +94,9 @@ test_expr (expr_t *e) return new_alias_expr (type_default, e); new = new_string_expr (0); break; + case ev_long: + case ev_ulong: + internal_error (e, "long not implemented"); case ev_uinteger: case ev_integer: case ev_short: diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ecd759818..0dfcebe88 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -38,6 +38,7 @@ #endif #include +#include #include "qfalloca.h" @@ -161,6 +162,10 @@ operand_string (operand_t *op) return va (0, "int %d", op->value->v.integer_val); case ev_uinteger: return va (0, "uint %u", op->value->v.uinteger_val); + case ev_long: + return va (0, "long %"PRIi64, op->value->v.long_val); + case ev_ulong: + return va (0, "ulong %"PRIu64, op->value->v.ulong_val); case ev_short: return va (0, "short %d", op->value->v.short_val); case ev_void: @@ -238,6 +243,12 @@ _print_operand (operand_t *op) case ev_uinteger: printf ("%u", op->value->v.uinteger_val); break; + case ev_long: + printf ("%"PRIu64, op->value->v.long_val); + break; + case ev_ulong: + printf ("%"PRIu64, op->value->v.ulong_val); + break; case ev_short: printf ("%d", op->value->v.short_val); break; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index bccf431b7..17dd74571 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -188,6 +188,8 @@ free_type (type_t *type) case ev_quat: case ev_integer: case ev_uinteger: + case ev_long: + case ev_ulong: case ev_short: case ev_double: break; @@ -228,6 +230,8 @@ copy_chain (type_t *type, type_t *append) case ev_quat: case ev_integer: case ev_uinteger: + case ev_long: + case ev_ulong: case ev_short: case ev_double: internal_error (0, "copy basic type"); @@ -279,6 +283,8 @@ append_type (type_t *type, type_t *new) case ev_quat: case ev_integer: case ev_uinteger: + case ev_long: + case ev_ulong: case ev_short: case ev_double: internal_error (0, "append to basic type"); @@ -656,6 +662,8 @@ print_type_str (dstring_t *str, const type_t *type) case ev_quat: case ev_integer: case ev_uinteger: + case ev_long: + case ev_ulong: case ev_short: case ev_double: dasprintf (str, " %s", pr_type_name[type->type]); @@ -820,6 +828,12 @@ encode_type (dstring_t *encoding, const type_t *type) case ev_uinteger: dasprintf (encoding, "I"); return; + case ev_long: + dasprintf (encoding, "l"); + return; + case ev_ulong: + dasprintf (encoding, "L"); + return; case ev_short: dasprintf (encoding, "s"); return; From c74cfb9bf6953b5c85ef56d1eede603d332e2970 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 5 Jan 2022 22:33:59 +0900 Subject: [PATCH 2116/3664] [gamecode] Generate instruction widths and types Not everything is correct, but this is enough to get started on supporting disassembly in the various tools and code generation in qfcc. --- include/QF/pr_comp.h | 4 +- libs/gamecode/opcodes.py | 131 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 128 insertions(+), 7 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index abaa4160d..26f0f07e3 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -625,8 +625,8 @@ const v6p_opcode_t *PR_v6p_Opcode (pr_ushort_t opcode) __attribute__((const)); typedef struct opcode_s { const char *opname; const char *mnemonic; - int width; ///< number of components (1-4) - int size; ///< component size in words (1-2) + int widths[3]; ///< component count for each argument (1-4) + etype_t types[3]; ///< component type for each argument const char *fmt; } opcode_t; extern const opcode_t pr_opcodes[512]; diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 105f37668..dbb315009 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -42,25 +42,34 @@ branch_fmt=[ "%Ga[%sb]", "%Ga[%Gb]", ] -compare_ccc=[ "eq", "lt", "gt", None, "ne", "ge", "le", None] -type_tt=['I', 'F', 'L', 'D'] +compare_ccc = [ "eq", "lt", "gt", None, "ne", "ge", "le", None] +type_tt = ['I', 'F', 'L', 'D'] +etype_tt = ["ev_integer", "ev_float", "ev_long", "ev_double"] +unsigned_t = ["ev_uinteger", "ev_ulong"] +float_t = ["ev_float", "ev_double"] all_formats = { "opcode": "OP_ALL_{ss+1}", "mnemonic": "all", "opname": "all", "format": "%Ga, %gc", + "widths": "{ss+1}, 0, 1", + "types": "ev_integer, ev_integer, ev_integer", } any_formats = { "opcode": "OP_ANY_{ss+1}", "mnemonic": "any", "opname": "any", "format": "%Ga, %gc", + "widths": "{ss+1}, 0, 1", + "types": "ev_integer, ev_integer, ev_integer", } bitops_formats = { "opcode": "OP_{op_bit[oo].upper()}_I_{ss+1}", "mnemonic": "{op_bit[oo]}", "opname": "{op_bit[oo]}", "format": "{bit_fmt[oo]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "ev_integer, ev_integer, ev_integer", "args": { "op_bit":["bitand", "bitor", "bitxor", "bitnot"], "bit_fmt": [ @@ -76,6 +85,8 @@ boolops_formats = { "mnemonic": "{op_bool[oo]}", "opname": "{op_bool[oo]}", "format": "{bool_fmt[oo]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "ev_integer, ev_integer, ev_integer", "args": { "op_bool":["and", "or", "xor", "not"], "bool_fmt": [ @@ -91,11 +102,19 @@ branch_formats = { "mnemonic": "{op_cond[cc]}", "opname": "{op_cond[cc]}", "format": "{cond_fmt[cc]}{branch_fmt[mm]}", + "widths": "{cond_widths[cc]}", + "types": "ev_void, ev_void, ev_integer", "args": { "op_mode": "ABCD", "op_cond": ["ifnot", "if", "jump", "call"], "branch_fmt": branch_fmt, "cond_fmt": ["%Gc ", "%Gc ", "", ""], + "cond_widths": [ + "0, 0, 1", + "0, 0, 1", + "0, 0, 0", + "0, 0, 0", + ], }, } branch2_formats = { @@ -103,28 +122,42 @@ branch2_formats = { "mnemonic": "{op_cond[cc]}", "opname": "{op_cond[cc]}", "format": "%Gc {branch_fmt[mm]}", + "widths": "{cond_widths[cc]}", + "types": "ev_void, ev_void, ev_integer", "args": { "op_mode": "ABCD", "op_cond": ["ifa", "ifbe", "ifb", "ifae"], "branch_fmt": branch_fmt, + "cond_widths": [ + "0, 0, 1", + "0, 0, 1", + "0, 0, 1", + "0, 0, 1", + ], }, } compare_formats = { "opcode": "OP_{op_cmp[ccc].upper()}_{cmp_type[tt]}_{ss+1}", "mnemonic": "{op_cmp[ccc]}.{cmp_type[tt]}", "opname": "{op_cmp[ccc]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{cmp_types[tt]}, {cmp_types[tt]}, ev_integer", "args": { "op_cmp": compare_ccc, "cmp_type":type_tt, + "cmp_types":etype_tt, }, } compare2_formats = { "opcode": "OP_{op_cmp[ccc].upper()}_{cmp_type[t]}_{ss+1}", "mnemonic": "{op_cmp[ccc]}.{cmp_type[t]}", "opname": "{op_cmp[ccc]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{cmp_types[t]}, {cmp_types[t]}, ev_integer", "args": { "op_cmp": compare_ccc, "cmp_type":['u', 'U'], + "cmp_types":unsigned_t, }, } convert_formats = { @@ -132,8 +165,16 @@ convert_formats = { "mnemonic": "conv.{op_conv[d*4+xx]}", "opname": "conv", "format": "%Ga %gc", + "widths": "1, 0, 1", + "types": "{cnv_types[xx][d]}, ev_invalid, {cnv_types[xx][1-d]}", "args": { "op_conv": ["IF", "LD", "uF", "UD", "FI", "DL", "Fu", "DU"], + "cnv_types": [ + ["ev_integer", "ev_float"], + ["ev_long", "ev_double"], + ["ev_uinteger", "ev_float"], + ["ev_ulong", "ev_double"], + ], }, } lea_formats = { @@ -141,6 +182,8 @@ lea_formats = { "mnemonic": "lea", "opname": "lea", "format": "{lea_fmt[mm]}", + "widths": "0, 0, 1", + "types": "ev_pointer, ev_pointer, ev_pointer", "args": { "op_mode": "ABCD", "lea_fmt": [ @@ -156,12 +199,16 @@ lea_e_formats = { "mnemonic": "lea", "opname": "lea", "format": "%Ga.%Gb(%Ec), %gc", + "types": "ev_entity, ev_field, ev_pointer", + "widths": "0, 0, 1", } load_formats = { "opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}", "mnemonic": "load", "opname": "load", "format": "{load_fmt[mm]}", + "widths": "0, 0, {ss+1}", + "types": "ev_void, ev_void, ev_void", "args": { "op_mode": "EBCD", "load_fmt": [ @@ -176,9 +223,12 @@ mathops_formats = { "opcode": "OP_{op_math[ooo].upper()}_{math_type[tt]}_{ss+1}", "mnemonic": "{op_math[ooo]}.{math_type[tt]}", "opname": "{op_math[ooo]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{math_types[tt]}, {math_types[tt]}, {math_types[tt]}", "args": { "op_math": ["mul", "div", "rem", "mod", "add", "sub", None, None], "math_type":type_tt, + "math_types": etype_tt, }, } memset_formats = { @@ -186,6 +236,8 @@ memset_formats = { "mnemonic": "memset.{op_memset[oo]}", "opname": "memset", "format": "{memset_fmt[oo]}", + "widths": "0, 0, 0", + "types": "ev_integer, ev_void, ev_void", "args": { "op_memset": [None, "i", "p", "pi"], "memset_fmt": [None, "%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc"], @@ -196,6 +248,8 @@ move_formats = { "mnemonic": "memset.{op_move[oo]}", "opname": "memset", "format": "{move_fmt[oo]}", + "widths": "0, 0, 0", + "types": "ev_integer, ev_void, ev_void", "args": { "op_move": [None, "i", "p", "pi"], "move_fmt": [None, "%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc"], @@ -206,12 +260,16 @@ none_formats = { "mnemonic": "none", "opname": "none", "format": "%Ga, %gc", + "widths": "{ss+1}, 0, 1", + "types": "ev_integer, ev_invalid, ev_integer", } push_formats = { "opcode": "OP_PUSH_{op_mode[mm]}_{ss+1}", "mnemonic": "push", "opname": "push", "format": "{push_fmt[mm]}", + "widths": "{ss+1}, 0, 0", + "types": "ev_void, ev_void, ev_invalid", "args": { "op_mode": "ABCD", "push_fmt": [ @@ -226,6 +284,8 @@ pushregs_formats = { "opcode": "OP_PUSHREGS", "mnemonic": "pushregs", "opname": "pushregs", + "widths": "0, 0, 0", + "types": "ev_invalid, ev_invalid, ev_invalid", "format": None, } pop_formats = { @@ -233,6 +293,8 @@ pop_formats = { "mnemonic": "pop", "opname": "pop", "format": "{pop_fmt[mm]}", + "widths": "{ss+1}, 0, 0", + "types": "ev_void, ev_void, ev_invalid", "args": { "op_mode": "ABCD", "pop_fmt": [ @@ -247,23 +309,34 @@ popregs_formats = { "opcode": "OP_POPREGS", "mnemonic": "popregs", "opname": "popregs", + "widths": "0, 0, 0", "format": None, + "types": "ev_invalid, ev_invalid, ev_invalid", } scale_formats = { "opcode": "OP_SCALE_{scale_type[t]}_{ss+1}", "mnemonic": "scale.{scale_type[t]}", "opname": "scale", + "widths": "{ss+1}, 1, {ss+1}", + "types": "{scale_types[t]}, {scale_types[t]}, {scale_types[t]}", "args": { - "scale_type":['F', 'D'], + "scale_type": ['F', 'D'], + "scale_types": float_t, }, } shiftops_formats = { "opcode": "OP_{op_shift[u*2+r].upper()}_{shift_type[u*2+t]}_{ss+1}", "mnemonic": "{op_shift[u*2+r]}.{shift_type[u*2+t]}", "opname": "{op_shift[u*2+r]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{shift_types[t][u]}, {shift_types[t][0]}, {shift_types[t][u]}", "args": { "op_shift": ["shl", "asr", "shl", "shr"], - "shift_type":['I', 'L', 'u', 'U'], + "shift_type": ['I', 'L', 'u', 'U'], + "shift_types": [ + ["ev_integer", "ev_uinteger"], + ["ev_long", "ev_ulong"], + ], }, } state_formats = { @@ -271,9 +344,12 @@ state_formats = { "mnemonic": "state.{state[t]}", "opname": "state", "format": "{state_fmt[t]}", + "widths": "1, 1, 1", + "types": "ev_float, ev_func, {state_types[t]}", "args": { "state": ["ft", "ftt"], "state_fmt": ["%Ga, %Gb", "%Ga, %Gb, %Gc"], + "state_types": ["ev_invalid", "ev_float"], }, } store_formats = { @@ -281,6 +357,8 @@ store_formats = { "mnemonic": "store", "opname": "store", "format": "{store_fmt[mm]}", + "widths": "{ss+1}, 0, {ss+1}", + "types": "ev_void, ev_void, ev_void", "args": { "op_mode": "ABCD", "store_fmt": [ @@ -296,6 +374,8 @@ string_formats = { "mnemonic": "{op_str[o*4+oo]}.s", "opname": "{op_str[o*4+oo]}", "format": "{str_fmt[o*4+oo]}", + "widths": "1, 1, 1", + "types": "{str_types[o*4+oo]}", "args": { "op_str": ["eq", "lt", "gt", "add", "cmp", "ge", "le", "not"], "str_fmt": [ @@ -308,6 +388,16 @@ string_formats = { "%Ga, %Gb, %gc", "%Ga, %gc", ], + "str_types": [ + "ev_string, ev_string, ev_integer", + "ev_string, ev_string, ev_integer", + "ev_string, ev_string, ev_integer", + "ev_string, ev_string, ev_string", + "ev_string, ev_string, ev_integer", + "ev_string, ev_string, ev_integer", + "ev_string, ev_string, ev_integer", + "ev_string, ev_invalid, ev_integer", + ], }, } swizzle_formats = { @@ -315,8 +405,11 @@ swizzle_formats = { "mnemonic": "swizzle.{swiz_type[t]}", "opname": "swizzle", "format": "%Ga %sb %gc", + "widths": "4, 0, 4", + "types": "{swizzle_types[t]}", "args": { - "swiz_type":['F', 'D'], + "swiz_type": ['F', 'D'], + "swizzle_types": float_t, }, } rcall_formats = { @@ -324,6 +417,8 @@ rcall_formats = { "mnemonic": "rcall{nnn+1}", "opname": "rcall{nnn+1}", "format": "{rcall_fmt[nnn]}", + "widths": "0, 0, 0", + "types": "ev_func, ev_void, ev_void", "args": { "rcall_fmt": [ "%Fa (%P0b)", @@ -341,31 +436,51 @@ return_formats = { "opcode": "OP_RETURN_{ss+1}", "mnemonic": "return{ss+1}", "opname": "return{ss+1}", + "widths": "0, 0, 0", "format": "%Ra", + "types": "ev_void, ev_invalid, ev_invalid", } returnv_formats = { "opcode": "OP_RETURN_0", "mnemonic": "return", "opname": "return", + "widths": "0, 0, 0", "format": None, + "types": "ev_invalid, ev_invalid, ev_invalid", } vecops_formats = { "opcode": "OP_{op_vop[ooo].upper()}_{vop_type[t]}", "mnemonic": "{op_vop[ooo]}.{vop_type[t]}", "opname": "{op_vop[ooo]}", + "widths": "{vec_widths[ooo]}", + "types": "{vec_types[t]}, {vec_types[t]}, {vec_types[t]}", "args": { "op_vop": ["cdot", "vdot", "qdot", "cross", "cmul", "qvmul", "vqmul", "qmul"], "vop_type": ['F', 'D'], + "vec_widths": [ + "2, 2, 2", + "3, 3, 3", + "4, 4, 4", + "3, 3, 3", + "2, 2, 2", + "4, 3, 3", + "3, 4, 3", + "4, 4, 4", + ], + "vec_types": float_t, }, } vecops2_formats = { "opcode": "OP_{op_vop[dd].upper()}_{vop_type[t]}", "mnemonic": "{op_vop[dd]}.{vop_type[t]}", "opname": "{op_vop[dd]}", + "widths": "4, 4, 4", + "types": "{vec_types[t]}, {vec_types[t]}, {vec_types[t]}", "args": { "op_vop": [None, "qv4mul", "v4qmul", None], "vop_type": ['F', 'D'], + "vec_types": float_t, }, } with_formats = { @@ -373,6 +488,8 @@ with_formats = { "mnemonic": "with", "opname": "with", "format": "%sa, %sb, $sc", + "widths": "0, 0, 0", + "types": "ev_void, ev_void, ev_void", } group_map = { @@ -475,6 +592,8 @@ def process_opcode(opcode, group): else: fmt = f'"{fmt}"' inst["fmt"] = fmt + inst["wd"] = "{%s}" % eval(f'''f"{gm['widths']}"''', params) + inst["ty"] = "{%s}" % eval(f'''f"{gm['types']}"''', params) lines = bitmap_txt.split('\n') for l in lines: @@ -499,5 +618,7 @@ for i, group in enumerate(opcodes): print(eval('f"[{op}] = {{\\n' '\\t.opname = {on},\\n' '\\t.mnemonic = {mn},\\n' + '\\t.widths = {wd},\\n' + '\\t.types = {ty},\\n' '\\t.fmt = {fmt},\\n' '}},"', group)) From d9d37fda4763219243cbb9af3188fb359c3d1372 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jan 2022 11:47:05 +0900 Subject: [PATCH 2117/3664] [gamecode] Implement ruamoko opcode lookup And get the debugger working with the new instruction set. --- libs/gamecode/pr_debug.c | 51 +++++++++++++++++++++++++++------------ libs/gamecode/pr_opcode.c | 7 ++++++ libs/gamecode/test/main.c | 7 +++++- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 7e3090a76..98c5d0e59 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1513,11 +1513,13 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) int addr = s - pr->pr_statements; int dump_code = contents & 2; const char *fmt; - const v6p_opcode_t *op; + const char *mnemonic; dfunction_t *call_func = 0; pr_def_t *parm_def = 0; pr_auxfunction_t *aux_func = 0; pr_debug_data_t data; + etype_t op_type[3]; + int op_width[3]; dstring_clearstr (res->line); @@ -1539,24 +1541,43 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) return; } - op = PR_v6p_Opcode (s->op); - if (!op) { - Sys_Printf ("%sUnknown instruction %d\n", res->line->str, s->op); - return; + if (pr->progs->version < PROG_VERSION) { + const v6p_opcode_t *op = PR_v6p_Opcode (s->op); + if (!op) { + Sys_Printf ("%sUnknown instruction %d\n", res->line->str, s->op); + return; + } + VectorSet (op->type_a, op->type_b, op->type_c, op_type); + VectorSet (1, 1, 1, op_width); + fmt = op->fmt; + mnemonic = op->opname; + } else { + const opcode_t *op = PR_Opcode (s->op); + if (!op) { + Sys_Printf ("%sUnknown instruction %d\n", res->line->str, s->op); + return; + } + VectorCopy (op->widths, op_width); + VectorCopy (op->types, op_type); + fmt = op->fmt; + mnemonic = op->mnemonic; } - if (!(fmt = op->fmt)) + if (!fmt) { fmt = "%Ga, %Gb, %gc"; + } dasprintf (res->line, "%04x ", addr); - if (pr_debug->int_val > 2) - dasprintf (res->line, "%02x %04x(%8s) %04x(%8s) %04x(%8s)\t", + if (pr_debug->int_val > 2) { + dasprintf (res->line, + "%02x %04x(%8s)[%d] %04x(%8s)[%d] %04x(%8s)[%d]\t", s->op, - s->a, pr_type_name[op->type_a], - s->b, pr_type_name[op->type_b], - s->c, pr_type_name[op->type_c]); + s->a, pr_type_name[op_type[0]], op_width[0], + s->b, pr_type_name[op_type[1]], op_width[1], + s->c, pr_type_name[op_type[2]], op_width[2]); + } - dasprintf (res->line, "%s ", op->opname); + dasprintf (res->line, "%s ", mnemonic); while (*fmt) { if (*fmt == '%') { @@ -1582,15 +1603,15 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) switch (opchar) { case 'a': opval = s->a; - optype = res->type_encodings[op->type_a]; + optype = res->type_encodings[op_type[0]]; break; case 'b': opval = s->b; - optype = res->type_encodings[op->type_b]; + optype = res->type_encodings[op_type[1]]; break; case 'c': opval = s->c; - optype = res->type_encodings[op->type_c]; + optype = res->type_encodings[op_type[2]]; break; case 'x': if (mode == 'P') { diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index e2bebf46c..add538502 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -36,3 +36,10 @@ const opcode_t pr_opcodes[512] = { #include "libs/gamecode/pr_opcode.cinc" }; + +const opcode_t * +PR_Opcode (pr_ushort_t opcode) +{ + opcode &= OP_MASK; + return &pr_opcodes[opcode]; +} diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 44e91167e..0579463b2 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -43,12 +43,15 @@ test_debug_handler (prdebug_t event, void *param, void *data) break; case prd_trace: dstatement_t *st = test_pr.pr_statements + test_pr.pr_xstatement; - if (verbose > 0) { + if (verbose > 1) { printf ("debug: trace %05x %04x %04x %04x %04x%s\n", test_pr.pr_xstatement, st->op, st->a, st->b, st->c, pr->globals.stack ? va (0, " %05x", *pr->globals.stack) : ""); } + if (verbose > 0) { + PR_PrintStatement (&test_pr, st, 0); + } if (pr->globals.stack) { if (*pr->globals.stack & 3) { printf ("stack not aligned: %d\n", *pr->globals.stack); @@ -73,6 +76,8 @@ static void setup_test (test_t *test) { memset (&test_pr, 0, sizeof (test_pr)); + PR_Init (&test_pr); + PR_Debug_Init (&test_pr); test_pr.progs = &test_progs; test_pr.debug_handler = test_debug_handler; test_pr.debug_data = &test_pr; From c0277c0b0350a6b1ea19729f0ff0715570948110 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jan 2022 11:51:38 +0900 Subject: [PATCH 2118/3664] [gamecode] Fix incorrect entity load format Had a typo in load and forgot to edit lea, but now they share the formats (like they should have in the first place). --- libs/gamecode/opcodes.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index dbb315009..81bbb7e29 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -36,7 +36,13 @@ n 1111 nnnn 0 1011 nnnn """ -branch_fmt=[ +load_fmt = [ + "%Ga.%Gb(%Ea), %gc", + "*%Ga, %gc", + "*(%Ga + %sb), %gc", + "*(%Ga + %Gb), %gc", +] +branch_fmt = [ "branch %sa (%Ob)", "*%Ga", "%Ga[%sb]", @@ -47,6 +53,7 @@ type_tt = ['I', 'F', 'L', 'D'] etype_tt = ["ev_integer", "ev_float", "ev_long", "ev_double"] unsigned_t = ["ev_uinteger", "ev_ulong"] float_t = ["ev_float", "ev_double"] + all_formats = { "opcode": "OP_ALL_{ss+1}", "mnemonic": "all", @@ -198,7 +205,8 @@ lea_e_formats = { "opcode": "OP_LEA_E", "mnemonic": "lea", "opname": "lea", - "format": "%Ga.%Gb(%Ec), %gc", + "format": "{load_fmt[0]}", + "format": "%Ga.%Gb(%Ea), %gc", "types": "ev_entity, ev_field, ev_pointer", "widths": "0, 0, 1", } @@ -211,12 +219,7 @@ load_formats = { "types": "ev_void, ev_void, ev_void", "args": { "op_mode": "EBCD", - "load_fmt": [ - "%Ga.%Gb(%Ex), %gc", - "*%Ga, %gc", - "*(%Ga + %sb), %gc", - "*(%Ga + %Gb), %gc", - ], + "load_fmt": load_fmt, }, } mathops_formats = { From 80c5e2c3f63cd0872c299cb2153e0531898bee3a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jan 2022 18:06:56 +0900 Subject: [PATCH 2119/3664] [simd] Remove requirements for AVX2 for vec4d It seems gcc-11 does a pretty good job of emulating the instructions (it no longer requires avx2 for 256-bit wide vectors). --- include/QF/simd/types.h | 2 -- include/QF/simd/vec4d.h | 18 +++++++----------- libs/util/test/test-simd.c | 10 ---------- 3 files changed, 7 insertions(+), 23 deletions(-) diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index ad8345f44..1f2a511c1 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -43,7 +43,6 @@ typedef double vec3d_t[3]; VEC_TYPE (double, vec2d_t, 2); VEC_TYPE (int64_t, vec2l_t, 2); -#ifdef __AVX2__ /** Four element vector type for horizontal (AOS) vector data. * * This is used for both vectors (3D and 4D) and quaternions. 3D vectors @@ -58,7 +57,6 @@ VEC_TYPE (double, vec4d_t, 4); /** Used mostly for __builtin_shuffle. */ VEC_TYPE (int64_t, vec4l_t, 4); -#endif /** Three element vector type for interfacing with compact data. * diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index d0e3f19bc..1e1d7bb89 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -28,7 +28,6 @@ #ifndef __QF_simd_vec4d_h #define __QF_simd_vec4d_h -#ifdef __AVX2__ #include #include "QF/simd/types.h" @@ -96,9 +95,9 @@ GNU89INLINE inline vec4d_t qrotd (vec4d_t a, vec4d_t b) __attribute__((const)); GNU89INLINE inline vec4d_t qconjd (vec4d_t q) __attribute__((const)); GNU89INLINE inline vec4d_t loadvec3d (const double v3[]) __attribute__((pure)); GNU89INLINE inline void storevec3d (double v3[3], vec4d_t v4); -GNU89INLINE inline vec4l_t loadvec3l (const long *v3) __attribute__((pure)); -GNU89INLINE inline vec4l_t loadvec3l1 (const long *v3) __attribute__((pure)); -GNU89INLINE inline void storevec3l (long *v3, vec4l_t v4); +GNU89INLINE inline vec4l_t loadvec3l (const int64_t *v3) __attribute__((pure)); +GNU89INLINE inline vec4l_t loadvec3l1 (const int64_t *v3) __attribute__((pure)); +GNU89INLINE inline void storevec3l (int64_t *v3, vec4l_t v4); #ifndef IMPLEMENT_VEC4D_Funcs GNU89INLINE inline @@ -187,8 +186,7 @@ qmuld (vec4d_t a, vec4d_t b) vec4d_t c = crossd (a, b) + a * b[3] + a[3] * b; vec4d_t d = dotd (a, b); // zero out the vector component of dot product so only the scalar remains - d = _mm256_permute2f128_pd (d, d, 0x18); - d = _mm256_permute4x64_pd (d, 0xc0); + d = (vec4d_t) { 0, 0, 0, d[3] }; return c - d; } @@ -302,7 +300,7 @@ GNU89INLINE inline VISIBLE #endif vec4l_t -loadvec3l (const long *v3) +loadvec3l (const int64_t *v3) { vec4l_t v4 = { v3[0], v3[1], v3[2], 0 }; return v4; @@ -314,7 +312,7 @@ GNU89INLINE inline VISIBLE #endif vec4l_t -loadvec3l1 (const long *v3) +loadvec3l1 (const int64_t *v3) { vec4l_t v4 = { v3[0], v3[1], v3[2], 1 }; return v4; @@ -326,13 +324,11 @@ GNU89INLINE inline VISIBLE #endif void -storevec3l (long *v3, vec4l_t v4) +storevec3l (int64_t *v3, vec4l_t v4) { v3[0] = v4[0]; v3[1] = v4[1]; v3[2] = v4[2]; } -#endif - #endif//__QF_simd_vec4d_h diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index d1b4bf286..7cba48f3b 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -48,7 +48,6 @@ #define s05 0.70710678118654757 -#ifdef __AVX2__ typedef struct { int line; vec4d_t (*op) (vec4d_t a, vec4d_t b); @@ -57,7 +56,6 @@ typedef struct { vec4d_t expect; vec4d_t ulp_errors; } vec4d_test_t; -#endif typedef struct { int line; @@ -94,7 +92,6 @@ typedef struct { mat4f_t ulp_errors; } mq4f_test_t; -#ifdef __AVX2__ static vec4d_t tvtruncd (vec4d_t v, vec4d_t ignore) { return vtrunc4d (v); @@ -114,7 +111,6 @@ static vec4d_t tqconjd (vec4d_t v, vec4d_t ignore) { return qconjd (v); } -#endif static vec4f_t tvtruncf (vec4f_t v, vec4f_t ignore) { @@ -158,7 +154,6 @@ static vec4f_t tmagnitude3f (vec4f_t v, vec4f_t ignore) #define T(t...) { __LINE__, t } -#ifdef __AVX2__ static vec4d_test_t vec4d_tests[] = { // 3D dot products T(dotd, right, right, one ), @@ -285,7 +280,6 @@ static vec4d_test_t vec4d_tests[] = { T(tqconjd, one, {}, { -1, -1, -1, 1 } ), }; #define num_vec4d_tests (sizeof (vec4d_tests) / (sizeof (vec4d_tests[0]))) -#endif static vec4f_test_t vec4f_tests[] = { // 3D dot products @@ -487,7 +481,6 @@ static mq4f_test_t mq4f_tests[] = { }; #define num_mq4f_tests (sizeof (mq4f_tests) / (sizeof (mq4f_tests[0]))) -#ifdef __AVX2__ static int run_vec4d_tests (void) { @@ -512,7 +505,6 @@ run_vec4d_tests (void) } return ret; } -#endif static int run_vec4f_tests (void) @@ -684,9 +676,7 @@ int main (void) { int ret = 0; -#ifdef __AVX2__ ret |= run_vec4d_tests (); -#endif ret |= run_vec4f_tests (); ret |= run_mat4f_tests (); ret |= run_mv4f_tests (); From c3317f8e5e8c3db1f1b10fc2c081402bf5e67b1e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jan 2022 22:20:16 +0900 Subject: [PATCH 2120/3664] [gamecode] use INT64_C instead of l-suffix Once again, I had forgotten that long is not always 64-bits. --- libs/gamecode/pr_exec.c | 65 +++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 717364ea3..fc0344578 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2588,41 +2588,42 @@ pr_swizzle_d (pr_lvec4_t vec, pr_ushort_t swiz) &&swizzle_xwww, &&swizzle_ywww, &&swizzle_zwww, &&swizzle_wwww, }; #undef swizzle +#define L(x) UINT64_C(x) static const pr_lvec4_t neg[16] = { - { 0l, 0l, 0l, 0l }, - { 1l<<63, 0l, 0l, 0l }, - { 0l, 1l<<63, 0l, 0l }, - { 1l<<63, 1l<<63, 0l, 0l }, - { 0l, 0l, 1l<<63, 0l }, - { 1l<<63, 0l, 1l<<63, 0l }, - { 0l, 1l<<63, 1l<<63, 0l }, - { 1l<<63, 1l<<63, 1l<<63, 0l }, - { 0l, 0l, 0l, 1l<<63 }, - { 1l<<63, 0l, 0l, 1l<<63 }, - { 0l, 1l<<63, 0l, 1l<<63 }, - { 1l<<63, 1l<<63, 0l, 1l<<63 }, - { 0l, 0l, 1l<<63, 1l<<63 }, - { 1l<<63, 0l, 1l<<63, 1l<<63 }, - { 0l, 1l<<63, 1l<<63, 1l<<63 }, - { 1l<<63, 1l<<63, 1l<<63, 1l<<63 }, + { INT64_C(0), INT64_C(0), INT64_C(0), INT64_C(0) }, + { INT64_C(1)<<63, INT64_C(0), INT64_C(0), INT64_C(0) }, + { INT64_C(0), INT64_C(1)<<63, INT64_C(0), INT64_C(0) }, + { INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(0), INT64_C(0) }, + { INT64_C(0), INT64_C(0), INT64_C(1)<<63, INT64_C(0) }, + { INT64_C(1)<<63, INT64_C(0), INT64_C(1)<<63, INT64_C(0) }, + { INT64_C(0), INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(0) }, + { INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(0) }, + { INT64_C(0), INT64_C(0), INT64_C(0), INT64_C(1)<<63 }, + { INT64_C(1)<<63, INT64_C(0), INT64_C(0), INT64_C(1)<<63 }, + { INT64_C(0), INT64_C(1)<<63, INT64_C(0), INT64_C(1)<<63 }, + { INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(0), INT64_C(1)<<63 }, + { INT64_C(0), INT64_C(0), INT64_C(1)<<63, INT64_C(1)<<63 }, + { INT64_C(1)<<63, INT64_C(0), INT64_C(1)<<63, INT64_C(1)<<63 }, + { INT64_C(0), INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(1)<<63 }, + { INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(1)<<63, INT64_C(1)<<63 }, }; static const pr_lvec4_t zero[16] = { - { ~0l, ~0l, ~0l, ~0l }, - { 0l, ~0l, ~0l, ~0l }, - { ~0l, 0l, ~0l, ~0l }, - { 0l, 0l, ~0l, ~0l }, - { ~0l, ~0l, 0l, ~0l }, - { 0l, ~0l, 0l, ~0l }, - { ~0l, 0l, 0l, ~0l }, - { 0l, 0l, 0l, ~0l }, - { ~0l, ~0l, ~0l, 0l }, - { 0l, ~0l, ~0l, 0l }, - { ~0l, 0l, ~0l, 0l }, - { 0l, 0l, ~0l, 0l }, - { ~0l, ~0l, 0l, 0l }, - { 0l, ~0l, 0l, 0l }, - { ~0l, 0l, 0l, 0l }, - { 0l, 0l, 0l, 0l }, + { ~INT64_C(0), ~INT64_C(0), ~INT64_C(0), ~INT64_C(0) }, + { INT64_C(0), ~INT64_C(0), ~INT64_C(0), ~INT64_C(0) }, + { ~INT64_C(0), INT64_C(0), ~INT64_C(0), ~INT64_C(0) }, + { INT64_C(0), INT64_C(0), ~INT64_C(0), ~INT64_C(0) }, + { ~INT64_C(0), ~INT64_C(0), INT64_C(0), ~INT64_C(0) }, + { INT64_C(0), ~INT64_C(0), INT64_C(0), ~INT64_C(0) }, + { ~INT64_C(0), INT64_C(0), INT64_C(0), ~INT64_C(0) }, + { INT64_C(0), INT64_C(0), INT64_C(0), ~INT64_C(0) }, + { ~INT64_C(0), ~INT64_C(0), ~INT64_C(0), INT64_C(0) }, + { INT64_C(0), ~INT64_C(0), ~INT64_C(0), INT64_C(0) }, + { ~INT64_C(0), INT64_C(0), ~INT64_C(0), INT64_C(0) }, + { INT64_C(0), INT64_C(0), ~INT64_C(0), INT64_C(0) }, + { ~INT64_C(0), ~INT64_C(0), INT64_C(0), INT64_C(0) }, + { INT64_C(0), ~INT64_C(0), INT64_C(0), INT64_C(0) }, + { ~INT64_C(0), INT64_C(0), INT64_C(0), INT64_C(0) }, + { INT64_C(0), INT64_C(0), INT64_C(0), INT64_C(0) }, }; do_swizzle: From 0d9294d541ac60eadbf38d2a90cb641c346672a6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jan 2022 22:21:24 +0900 Subject: [PATCH 2121/3664] [gamesource] Work around a windows gcc bug The bug (alignment issues with AVX on windows) seems to have in gcc from the 4.x days, and is still present in 11.2: it does not ensure stack parameters that need 32 byte alignment are aligned. Telling gcc to use the sysv abi (safe on a static function) lets gcc do what it does for linux (usually pass the parameters in registers, which it seems to have done). --- libs/gamecode/pr_exec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index fc0344578..f43011a79 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2261,6 +2261,11 @@ negate: } static pr_lvec4_t +#ifdef _WIN64 +//force gcc to use registers for the parameters to avoid alignment issues +//on the stack (gcc bug as of 11.2) +__attribute__((sysv_abi)) +#endif pr_swizzle_d (pr_lvec4_t vec, pr_ushort_t swiz) { goto do_swizzle; From 1cb35b1fe399149ba83d38bb0f48e67cf11ad67d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jan 2022 22:27:09 +0900 Subject: [PATCH 2122/3664] [gamecode] Fix some more operand formats With and relative branches. --- libs/gamecode/opcodes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 81bbb7e29..f0f2a1c26 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -43,7 +43,7 @@ load_fmt = [ "*(%Ga + %Gb), %gc", ] branch_fmt = [ - "branch %sa (%Ob)", + "branch %sa (%Oa)", "*%Ga", "%Ga[%sb]", "%Ga[%Gb]", @@ -490,7 +490,7 @@ with_formats = { "opcode": "OP_WITH", "mnemonic": "with", "opname": "with", - "format": "%sa, %sb, $sc", + "format": "%sa, %sb, %sc", "widths": "0, 0, 0", "types": "ev_void, ev_void, ev_void", } From aee31a8be514847166a6a34f0d29237e926a1e6b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 6 Jan 2022 22:27:42 +0900 Subject: [PATCH 2123/3664] [sys] Use tailless INT64_C macro I guess I missed the non-internal version when searching for it before. --- libs/util/sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/sys.c b/libs/util/sys.c index 25120aed2..bd985428f 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -431,7 +431,7 @@ Sys_LongTime (void) VISIBLE int64_t Sys_TimeBase (void) { - return __INT64_C (4294967296000000); + return INT64_C (4294967296000000); } VISIBLE double From 23613ca985b40701e3378589f6e98fd2849aa627 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 11:46:45 +0900 Subject: [PATCH 2124/3664] [simd] Get the new functions working on older hardware In some cases, gcc-11 does a good enough job translating normal looking C expressions so use just those, but other times need to dig around for an appropriate intrinsic. Also, now need to disable psapi warnings when compiling for anything less than avx. --- config.d/compiling.m4 | 8 ++++++- include/QF/simd/vec2d.h | 28 +++++++++++++++++++++++- include/QF/simd/vec2f.h | 21 ++++++++++++++++++ include/QF/simd/vec2i.h | 12 +++++++++++ include/QF/simd/vec4d.h | 47 ++++++++++++++++++++++++++++++++++++++++- include/QF/simd/vec4i.h | 22 ++++++++++++------- 6 files changed, 127 insertions(+), 11 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 1cd08dfa4..7fd5bd6c2 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -92,7 +92,6 @@ AC_ARG_ENABLE(simd, case "$enable_simd" in no) - QF_CC_OPTION(-Wno-psabi) simd=no ;; sse|sse2|avx|avx2) @@ -108,6 +107,13 @@ case "$enable_simd" in done ;; esac +case "$simd" in + avx*) + ;; + *) + QF_CC_OPTION(-Wno-psabi) + ;; +esac AC_MSG_CHECKING(for optimization) if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then diff --git a/include/QF/simd/vec2d.h b/include/QF/simd/vec2d.h index 206e7f18b..86be9302b 100644 --- a/include/QF/simd/vec2d.h +++ b/include/QF/simd/vec2d.h @@ -61,7 +61,14 @@ VISIBLE vec2d_t vceil2d (vec2d_t v) { +#ifndef __SSE4_1__ + return (vec2d_t) { + ceil (v[0]), + ceil (v[1]), + }; +#else return _mm_ceil_pd (v); +#endif } #ifndef IMPLEMENT_VEC2D_Funcs @@ -72,7 +79,14 @@ VISIBLE vec2d_t vfloor2d (vec2d_t v) { +#ifndef __SSE4_1__ + return (vec2d_t) { + floor (v[0]), + floor (v[1]), + }; +#else return _mm_floor_pd (v); +#endif } #ifndef IMPLEMENT_VEC2D_Funcs @@ -83,7 +97,14 @@ VISIBLE vec2d_t vtrunc2d (vec2d_t v) { +#ifndef __SSE4_1__ + return (vec2d_t) { + trunc (v[0]), + trunc (v[1]), + }; +#else return _mm_round_pd (v, _MM_FROUND_TRUNC); +#endif } #ifndef IMPLEMENT_VEC2D_Funcs @@ -95,7 +116,8 @@ vec2d_t dot2d (vec2d_t a, vec2d_t b) { vec2d_t c = a * b; - c = _mm_hadd_pd (c, c); + // gcc-11 does a good job with hadd + c = (vec2d_t) { c[0] + c[1], c[0] + c[1] }; return c; } @@ -109,7 +131,11 @@ cmuld (vec2d_t a, vec2d_t b) { vec2d_t c1 = a * b[0]; vec2d_t c2 = a * b[1]; +#ifndef __SSE3__ + return (vec2d_t) { c1[0] - c2[1], c1[1] + c2[0] }; +#else return _mm_addsub_pd (c1, (vec2d_t) { c2[1], c2[0] }); +#endif } #endif//__QF_simd_vec2d_h diff --git a/include/QF/simd/vec2f.h b/include/QF/simd/vec2f.h index b75efcd8e..1459dd37b 100644 --- a/include/QF/simd/vec2f.h +++ b/include/QF/simd/vec2f.h @@ -80,9 +80,16 @@ VISIBLE vec2f_t vceil2f (vec2f_t v) { +#ifndef __SSE4_1__ + return (vec2f_t) { + ceilf (v[0]), + ceilf (v[1]), + }; +#else vec4f_t t = { v[0], v[1], 0, 0 }; t = _mm_ceil_ps (t); return (vec2f_t) { t[0], t[1] }; +#endif } #ifndef IMPLEMENT_VEC2F_Funcs @@ -93,9 +100,16 @@ VISIBLE vec2f_t vfloor2f (vec2f_t v) { +#ifndef __SSE4_1__ + return (vec2f_t) { + floorf (v[0]), + floorf (v[1]), + }; +#else vec4f_t t = { v[0], v[1], 0, 0 }; t = _mm_floor_ps (t); return (vec2f_t) { t[0], t[1] }; +#endif } #ifndef IMPLEMENT_VEC2F_Funcs @@ -106,9 +120,16 @@ VISIBLE vec2f_t vtrunc2f (vec2f_t v) { +#ifndef __SSE4_1__ + return (vec2f_t) { + truncf (v[0]), + truncf (v[1]), + }; +#else vec4f_t t = { v[0], v[1], 0, 0 }; t = _mm_round_ps (t, _MM_FROUND_TRUNC); return (vec2f_t) { t[0], t[1] }; +#endif } #ifndef IMPLEMENT_VEC2F_Funcs diff --git a/include/QF/simd/vec2i.h b/include/QF/simd/vec2i.h index 694d5fa7b..29f2cc57c 100644 --- a/include/QF/simd/vec2i.h +++ b/include/QF/simd/vec2i.h @@ -60,7 +60,11 @@ int any2i (vec2i_t v) { vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); +#ifndef __SSSE3__ + return (t[0] + t[1]) > -2; +#else return _mm_hadd_pi32 (t, t)[0] > -2; +#endif } #ifndef IMPLEMENT_VEC2I_Funcs @@ -72,7 +76,11 @@ int all2i (vec2i_t v) { vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); +#ifndef __SSSE3__ + return (t[0] + t[1]) == 0; +#else return _mm_hadd_pi32 (t, t)[0] == 0; +#endif } #ifndef IMPLEMENT_VEC2I_Funcs @@ -84,7 +92,11 @@ int none2i (vec2i_t v) { vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); +#ifndef __SSSE3__ + return (t[0] + t[1]) == -2; +#else return _mm_hadd_pi32 (t, t)[0] == -2; +#endif } #endif//__QF_simd_vec2i_h diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 1e1d7bb89..791c48dde 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -31,6 +31,7 @@ #include #include "QF/simd/types.h" +#include "QF/simd/vec2d.h" GNU89INLINE inline vec4d_t vsqrt4d (vec4d_t v) __attribute__((const)); GNU89INLINE inline vec4d_t vceil4d (vec4d_t v) __attribute__((const)); @@ -107,7 +108,15 @@ VISIBLE vec4d_t vsqrt4d (vec4d_t v) { +#ifndef __AVX__ + vec2d_t xy = { v[0], v[1] }; + vec2d_t zw = { v[2], v[3] }; + xy = vsqrt2d (xy); + zw = vsqrt2d (zw); + return (vec4d_t) { xy[0], xy[1], zw[0], zw[1] }; +#else return _mm256_sqrt_pd (v); +#endif } #ifndef IMPLEMENT_VEC4D_Funcs @@ -118,7 +127,15 @@ VISIBLE vec4d_t vceil4d (vec4d_t v) { +#ifndef __AVX__ + vec2d_t xy = { v[0], v[1] }; + vec2d_t zw = { v[2], v[3] }; + xy = vceil2d (xy); + zw = vceil2d (zw); + return (vec4d_t) { xy[0], xy[1], zw[0], zw[1] }; +#else return _mm256_ceil_pd (v); +#endif } #ifndef IMPLEMENT_VEC4D_Funcs @@ -129,7 +146,15 @@ VISIBLE vec4d_t vfloor4d (vec4d_t v) { +#ifndef __AVX__ + vec2d_t xy = { v[0], v[1] }; + vec2d_t zw = { v[2], v[3] }; + xy = vfloor2d (xy); + zw = vfloor2d (zw); + return (vec4d_t) { xy[0], xy[1], zw[0], zw[1] }; +#else return _mm256_floor_pd (v); +#endif } #ifndef IMPLEMENT_VEC4D_Funcs @@ -140,7 +165,15 @@ VISIBLE vec4d_t vtrunc4d (vec4d_t v) { +#ifndef __AVX__ + vec2d_t xy = { v[0], v[1] }; + vec2d_t zw = { v[2], v[3] }; + xy = vtrunc2d (xy); + zw = vtrunc2d (zw); + return (vec4d_t) { xy[0], xy[1], zw[0], zw[1] }; +#else return _mm256_round_pd (v, _MM_FROUND_TRUNC); +#endif } #ifndef IMPLEMENT_VEC4D_Funcs @@ -167,7 +200,11 @@ vec4d_t dotd (vec4d_t a, vec4d_t b) { vec4d_t c = a * b; +#ifndef __AVX__ + c = (vec4d_t) { c[0] + c[1], c[0] + c[1], c[2] + c[3], c[2] + c[3] }; +#else c = _mm256_hadd_pd (c, c); +#endif static const vec4l_t A = {2, 3, 0, 1}; c += __builtin_shuffle(c, A); return c; @@ -202,8 +239,12 @@ qvmuld (vec4d_t q, vec4d_t v) double s = q[3]; // zero the scalar of the quaternion. Results in an extra operation, but // avoids adding precision issues. +#ifndef __AVX__ + q = (vec4d_t) { q[0], q[1], q[2], 0 }; +#else vec4d_t z = {}; q = _mm256_blend_pd (q, z, 0x08); +#endif vec4d_t c = crossd (q, v); vec4d_t qv = dotd (q, v); // q.w is 0 so v.w is irrelevant vec4d_t qq = dotd (q, q); @@ -224,8 +265,12 @@ vqmuld (vec4d_t v, vec4d_t q) double s = q[3]; // zero the scalar of the quaternion. Results in an extra operation, but // avoids adding precision issues. +#ifndef __AVX__ + q = (vec4d_t) { q[0], q[1], q[2], 0 }; +#else vec4d_t z = {}; q = _mm256_blend_pd (q, z, 0x08); +#endif vec4d_t c = crossd (q, v); vec4d_t qv = dotd (q, v); // q.w is 0 so v.w is irrelevant vec4d_t qq = dotd (q, q); @@ -262,7 +307,7 @@ qconjd (vec4d_t q) { const uint64_t sign = UINT64_C(1) << 63; const vec4l_t neg = { sign, sign, sign, 0 }; - return _mm256_xor_pd (q, (__m256d) neg); + return (vec4d_t) ((vec4l_t) q ^ neg); } #ifndef IMPLEMENT_VEC4D_Funcs diff --git a/include/QF/simd/vec4i.h b/include/QF/simd/vec4i.h index db303e610..d3e4ac5dc 100644 --- a/include/QF/simd/vec4i.h +++ b/include/QF/simd/vec4i.h @@ -62,10 +62,12 @@ VISIBLE int any4i (vec4i_t v) { +#ifndef __SSE4_1__ + vec4i_t t = (v != (vec4i_t) {}); + return (t[0] + t[1] + t[2] + t[3]) != 0; +#else return !__builtin_ia32_ptestz128 ((__v2di)v, (__v2di)v); - /*vec4i_t t = (v != (vec4i_t) {}); - t = __builtin_ia32_phaddd128 (t, t); - return __builtin_ia32_phaddd128 (t, t)[0] != 0;*/ +#endif } #ifndef IMPLEMENT_VEC2I_Funcs @@ -77,9 +79,11 @@ int all4i (vec4i_t v) { vec4i_t t = (v == (vec4i_t) {}); +#ifndef __SSE4_1__ + return (t[0] + t[1] + t[2] + t[3]) == 0; +#else return __builtin_ia32_ptestz128 ((__v2di)t, (__v2di)t); - /*t = __builtin_ia32_phaddd128 (t, t); - return __builtin_ia32_phaddd128 (t, t)[0] == 0;*/ +#endif } #ifndef IMPLEMENT_VEC2I_Funcs @@ -90,10 +94,12 @@ VISIBLE int none4i (vec4i_t v) { +#ifndef __SSE4_1__ + vec4i_t t = (v != (vec4i_t) {}); + return (t[0] + t[1] + t[2] + t[3]) == 0; +#else return __builtin_ia32_ptestz128 ((__v2di)v, (__v2di)v); - /*vec4i_t t = (v != (vec4i_t) {}); - t = __builtin_ia32_phaddd128 (t, t); - return __builtin_ia32_phaddd128 (t, t)[0] == 0;*/ +#endif } #ifndef IMPLEMENT_VEC4F_Funcs From c96cb1f3027a3354f68c25653329a6a5d6c9aa26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 15:59:06 +0900 Subject: [PATCH 2125/3664] [qfcc] Fix some stale documentation comments It does little good for documentation to refer to fields that don't exist (because a certain someone forgot to change the docs when changing the field names, I wonder who :P). --- tools/qfcc/include/obj_file.h | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 630659276..7fdee6030 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -218,23 +218,21 @@ typedef struct qfo_func_s { referenced relocs unreferenced relocs - For \c ref_op_* relocation types, \c ofs is the code section address of the - statement that needs to be adjusted. + For \c ref_op_* relocation types, \c offset is the code section address + of the statement that needs to be adjusted. - For \c rel_def_* relocation types, - \c ofs refers to the data section address of the word that needs to be - adjusted. + For \c rel_def_* relocation types, \c offset refers to the data section + address of the word that needs to be adjusted. - For \c ref_*_def(_ofs) relocation types, \c def is the index of the + For \c ref_*_def(_ofs) relocation types, \c target is the index of the referenced def. - For \c ref_*_op relocation types, \c def is the address of - the referenced statement. + For \c ref_*_op relocation types, \c target is the address of the + referenced statement. - For \c ref_*_string relocation types, \c def is - always 0. + For \c ref_*_string relocation types, \c target is always 0. - For \c ref_*_field(_ofs) relocation types, \c def is the index of + For \c ref_*_field(_ofs) relocation types, \c target is the index of the referenced field def. */ typedef struct qfo_reloc_s { From fe153b5b22289ddfad811e7771828ba8c04e24c5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 17:56:05 +0900 Subject: [PATCH 2126/3664] [qfcc] Add progs version to qfo and check in linker While qfcc dealing sensibly with mixed target VMs in the object files has always been an outstanding issue, with the new instruction set it has become a priority. Most importantly, this should allow QF to continue building while I work on qfcc targeting the new IS. --- tools/qfcc/include/obj_file.h | 5 ++++- tools/qfcc/source/linker.c | 4 ++++ tools/qfcc/source/obj_file.c | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 7fdee6030..f49688f0f 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -49,7 +49,7 @@ \hideinitializer */ -#define QFO_VERSION 0x00001006 +#define QFO_VERSION 0x00001007 /** Header block of QFO object files. The sections of the object file come immediately after the header, and are always in the order given by @@ -68,6 +68,8 @@ typedef struct qfo_header_s { pr_uint_t num_lines; ///< number of line records pr_uint_t num_loose_relocs; ///< number of loose relocation records ///< (included in num_relocs) + pr_uint_t progs_version; ///< version of compatible VM + pr_uint_t reserved[3]; } qfo_header_t; typedef enum qfos_type_e { @@ -260,6 +262,7 @@ typedef struct qfo_mspace_s { /** In-memory representation of a QFO object file. */ typedef struct qfo_s { + pr_uint_t progs_version; ///< version of compatible VM void *data; ///< data buffer holding qfo file when read qfo_mspace_t *spaces; unsigned num_spaces; diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 4b0fb7d74..948ac084f 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -1148,6 +1148,10 @@ linker_add_lib (const char *libname) linker_error ("error opening"); return 1; } + if (qfo->progs_version != options.code.progsversion) { + linker_error ("qfo progs version does not match target"); + return 1; + } for (j = 0; j < qfo->num_defs; j++) { qfo_def_t *def = qfo->defs + j; diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 22403f7ae..2082fe8ca 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -480,6 +480,7 @@ qfo_write (qfo_t *qfo, const char *filename) header->num_funcs = LittleLong (qfo->num_funcs); header->num_lines = LittleLong (qfo->num_lines); header->num_loose_relocs = LittleLong (qfo->num_loose_relocs); + header->progs_version = LittleLong (options.code.progsversion); spaces = (qfo_space_t *) &header[1]; relocs = (qfo_reloc_t *) &spaces[qfo->num_spaces]; defs = (qfo_def_t *) &relocs[qfo->num_relocs]; @@ -562,6 +563,14 @@ qfo_read (QFile *file) free (data); return 0; } + header->progs_version = LittleLong (header->progs_version); + if (header->progs_version != PROG_ID_VERSION + && header->progs_version != PROG_V6P_VERSION + && header->progs_version != PROG_VERSION) { + fprintf (stderr, "not a compatible qfo file\n"); + free (data); + return 0; + } qfo = calloc (1, sizeof (qfo_t)); qfo->num_spaces = LittleLong (header->num_spaces); @@ -570,6 +579,7 @@ qfo_read (QFile *file) qfo->num_funcs = LittleLong (header->num_funcs); qfo->num_lines = LittleLong (header->num_lines); qfo->num_loose_relocs = LittleLong (header->num_loose_relocs); + qfo->progs_version = header->progs_version; //already swapped spaces = (qfo_space_t *) &header[1]; qfo->data = data; From 2d245b8cdc2790cb0e5b18522bf6a2a3063eabdd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 18:34:05 +0900 Subject: [PATCH 2127/3664] [qfcc] Replace [no-]v6only with target= This allows v6, v6p (older QF VM) or ruamoko (new QF VM) to be targeted. Currently defaults to v6p to allow QF to continue building without too much hassle. --- tools/qfcc/doc/man/qfcc.1 | 37 ++++++++++++++++++++++++++----------- tools/qfcc/source/options.c | 24 +++++++++++++++++------- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index 5d49b816a..893070824 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -190,7 +190,7 @@ Look for \*[progs.src] in \fBDIR\fP instead of the current directory. .TP .B \-\-traditional Use traditional QuakeC syntax, semantics and \*(lqbugs\*(rq. -Also implies the \fBv6only\fP, \fBno-short-circuit\fP, +Also implies the \fBtarget=v6\fP, \fBno-short-circuit\fP, \fBconst-initializers\fP and \fBno-local-merging\fP code generation options (see \fBCODE GENERATION OPTIONS\fP). This is the default when using \fBprogs.src\fP mode. @@ -271,8 +271,8 @@ output file is \*(lqprogs.dat\*(rq, the symbol file will be .B fast\-float Use float values directly in \*(lqif\*(rq statements. Defaults to on. -This option is always enabled when using version 6 progs (\fBv6only\fP is in -effect). +This option is always enabled when targeting v6 progs (\fBtarget=v6\fP is +in effect). .TP .B local-merging @@ -289,8 +289,9 @@ Defaults to off for traditional mode, and on for advanced mode. .TP .B promote\-float Promote float when passed to a function that takes a variable number of -arguements. Defaults to enabled for advanced code, is forced off for -traditional or v6only code (mostly because such code does not have doubles). +arguements. Defaults to enabled for advanced code (v6p or ruamoko), is forced +off for traditional or v6 code (mostly because such code does not have +doubles). .TP .B short\-circuit @@ -329,18 +330,32 @@ Create extra symbols for accessing the components of a vector variable or field. For example, \fBvector vel\fP will also create \fBvel_x\fP, \fBvel_y\fP, and \fBvel_z\fP. Defaults to on for traditional code and off for advanced. +.PP +Any of the above can be prefixed with \fBno\-\fP to negate its meaning. .TP -.B v6only -Restrict the compiler to produce only version 6 progs (original -Quake/QuakeWorld) features. +.B target=v6|v6p|ruamoko +Specify the target for which the compiler is to produce code. +.RS +.TP +.B v6 +Standard Quake VM (qcc compatible). This means that the compiled data file should be able to run on older servers, as long as you have not used any QuakeForge-specific built-in functions. Also disables compiler features (such as integers and string manipulation support) that require extensions. -Defaults to on for traditional mode and off for advanced mode. -.PP -Any of the above can be prefixed with \fBno\-\fP to negate its meaning. +.TP +.B v6p +Quakeforge extended v6 instructions. +This is not compatible with older server, nor with most (any?) other Quake +engine. It adds a variety of instructions and types, including integers, +quaternions, pointers, doubles, structs, arrays and Objective-C style classes. +.TP +.B ruamoko +Quakeforge SIMD instructions. This is currently under development +and thus not the default. +.RE +Defaults to v6 for traditional mode and v6p for advanced mode. .SH "WARNING OPTIONS" diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 671d3aa85..2e701c403 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -207,8 +207,10 @@ code_usage (void) " passing\n" " vectors to functiosn.\n" " [no-]vector-components Create *_[xyz] symbols for vector variables.\n" -" [no-]v6only Restrict output code to version 6 progs\n" -" features.\n" +" target=v6|v6p|ruamoko Generate code for the specified target VM\n" +" v6 Standard Quake VM (qcc compatible)\n" +" v6p *QuakeForge extended v6 instructions\n" +" ruamoko QuakeForge SIMD instructions\n" "\n" "For details, see the qfcc(1) manual page\n" ); @@ -469,6 +471,19 @@ DecodeArgs (int argc, char **argv) while (temp) { qboolean flag = true; + if (!(strncasecmp (temp, "target=", 7))) { + const char *tgt = temp + 7; + if (!strcasecmp (tgt, "v6")) { + options.code.progsversion = PROG_ID_VERSION; + } else if (!strcasecmp (tgt, "v6p")) { + options.code.progsversion = PROG_V6P_VERSION; + } else if (!strcasecmp (tgt, "ruamoko")) { + options.code.progsversion = PROG_VERSION; + } else { + fprintf (stderr, "unknown target: %s\n", tgt); + exit (1); + } + } if (!strncasecmp (temp, "no-", 3)) { flag = false; temp += 3; @@ -501,11 +516,6 @@ DecodeArgs (int argc, char **argv) options.code.vector_calls = flag; } else if (!(strcasecmp (temp, "vector-components"))) { options.code.vector_components = flag; - } else if (!(strcasecmp (temp, "v6only"))) { - if (flag) - options.code.progsversion = PROG_ID_VERSION; - else - options.code.progsversion = PROG_V6P_VERSION; } else if (!(strcasecmp (temp, "const-initializers"))) { options.code.const_initializers = flag; } From d9ccf3a3945788b3b6068c9fe619005fb6bad062 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 18:54:59 +0900 Subject: [PATCH 2128/3664] [qfcc] Remove a pile of stale externs Those opcode pointers haven't been used for years. --- tools/qfcc/include/opcodes.h | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index f6a95f75a..077d26e1e 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -31,21 +31,6 @@ #ifndef __opcodes_h #define __opcodes_h -extern struct v6p_opcode_s *op_done; -extern struct v6p_opcode_s *op_return; -extern struct v6p_opcode_s *op_return_v; -extern struct v6p_opcode_s *op_if; -extern struct v6p_opcode_s *op_ifnot; -extern struct v6p_opcode_s *op_ifbe; -extern struct v6p_opcode_s *op_ifb; -extern struct v6p_opcode_s *op_ifae; -extern struct v6p_opcode_s *op_ifa; -extern struct v6p_opcode_s *op_state; -extern struct v6p_opcode_s *op_state_f; -extern struct v6p_opcode_s *op_goto; -extern struct v6p_opcode_s *op_jump; -extern struct v6p_opcode_s *op_jumpb; - struct operand_s; extern struct v6p_opcode_s *opcode_map; From 7e303a11519edfff074f1e08476494ee386b9c49 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 19:05:26 +0900 Subject: [PATCH 2129/3664] [qfcc] Hide details about instruction type At this stage, I doubt emit.c will need to know the details of the target (v6, v6p, ruamoko) since the instruction formats are identical, just different meanings for the opcode itself. --- tools/qfcc/include/opcodes.h | 13 +++++++------ tools/qfcc/source/emit.c | 8 ++++---- tools/qfcc/source/opcodes.c | 20 +++++++++++++------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index 077d26e1e..d8aa393ea 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -31,13 +31,14 @@ #ifndef __opcodes_h #define __opcodes_h +#include "QF/pr_comp.h" + +typedef struct instruction_s instruction_t; + struct operand_s; - -extern struct v6p_opcode_s *opcode_map; - -struct v6p_opcode_s *opcode_find (const char *name, struct operand_s *op_a, - struct operand_s *op_b, - struct operand_s *op_c); +pr_ushort_t opcode_get (instruction_t *inst); +instruction_t *opcode_find (const char *name, struct operand_s *op_a, + struct operand_s *op_b, struct operand_s *op_c); void opcode_init (void); #endif//__opcodes_h diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 48e89b422..10c7054f9 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -185,7 +185,7 @@ emit_statement (statement_t *statement) { const char *opcode = statement->opcode; def_t *def_a, *def_b, *def_c; - v6p_opcode_t *op; + instruction_t *inst; dstatement_t *s; def_a = get_operand_def (statement->expr, statement->opa); @@ -194,9 +194,9 @@ emit_statement (statement_t *statement) use_tempop (statement->opb, statement->expr); def_c = get_operand_def (statement->expr, statement->opc); use_tempop (statement->opc, statement->expr); - op = opcode_find (opcode, statement->opa, statement->opb, statement->opc); + inst = opcode_find (opcode, statement->opa, statement->opb, statement->opc); - if (!op) { + if (!inst) { print_expr (statement->expr); print_statement (statement); internal_error (statement->expr, "ice ice baby"); @@ -213,7 +213,7 @@ emit_statement (statement_t *statement) } } s = codespace_newstatement (pr.code); - s->op = op - opcode_map; + s->op = opcode_get (inst); s->a = def_a ? def_a->offset : 0; s->b = def_b ? def_b->offset : 0; s->c = def_c ? def_c->offset : 0; diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 8ad5358d9..7060aa35d 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -47,9 +47,9 @@ #include "tools/qfcc/include/statements.h" #include "tools/qfcc/include/type.h" -hashtab_t *opcode_type_table; -hashtab_t *opcode_void_table; -v6p_opcode_t *opcode_map; +static hashtab_t *opcode_type_table; +static hashtab_t *opcode_void_table; +static v6p_opcode_t *opcode_map; #define ROTL(x,n) ((((unsigned)(x))<<(n))|((unsigned)(x))>>(32-n)) @@ -92,7 +92,13 @@ check_operand_type (etype_t ot1, etype_t ot2) return 0; } -v6p_opcode_t * +pr_ushort_t +opcode_get (instruction_t *op) +{ + return (v6p_opcode_t *) op - opcode_map; +} + +instruction_t * opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) { @@ -108,10 +114,10 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b, search_op.type_c = op_c ? low_level_type (op_c->type) : ev_invalid; op = Hash_FindElement (opcode_type_table, &search_op); if (op) - return op; + return (instruction_t *) op; op_list = Hash_FindList (opcode_void_table, name); if (!op_list) - return op; + return (instruction_t *) op; for (i = 0; !op && op_list[i]; i++) { sop = op_list[i]; if (check_operand_type (sop->type_a, search_op.type_a) @@ -120,7 +126,7 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b, op = sop; } free (op_list); - return op; + return (instruction_t *) op; } void From 14d95f81d1ce4170caffca44af8bd01032228953 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 19:25:34 +0900 Subject: [PATCH 2130/3664] [gamecode] Remove PR_Opcode_Init It was idempotent, then it became impotent. Now it's just not needed. --- include/QF/pr_comp.h | 2 -- libs/gamecode/pr_load.c | 1 - libs/gamecode/pr_v6p_opcode.c | 5 ----- ruamoko/qwaq/builtins/main.c | 4 ---- tools/qfcc/source/opcodes.c | 1 - 5 files changed, 13 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 26f0f07e3..9e819ad38 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -632,8 +632,6 @@ typedef struct opcode_s { extern const opcode_t pr_opcodes[512]; const opcode_t *PR_Opcode (pr_ushort_t opcode) __attribute__((const)); -void PR_Opcode_Init (void); // idempotent - typedef struct dstatement_s { pr_opcode_e op:16; // will be pr_opcode_v6p_e for older progs pr_ushort_t a,b,c; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 95626fc22..9770bc786 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -479,7 +479,6 @@ PR_Init_Cvars (void) VISIBLE void PR_Init (progs_t *pr) { - PR_Opcode_Init (); // idempotent PR_Resources_Init (pr); PR_Strings_Init (pr); PR_Debug_Init (pr); diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index a4ed63d44..012f23e4a 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -1520,11 +1520,6 @@ PR_v6p_Opcode (pr_ushort_t opcode) return &pr_v6p_opcodes[opcode]; } -VISIBLE void -PR_Opcode_Init (void) -{ -} - static inline void check_branch (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, short offset) { diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 3b79f6e5d..f8d4c3a62 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -142,10 +142,6 @@ init_qf (void) Cvar_Get ("pr_debug", "2", 0, 0, 0); Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); - - // Normally, this is done by PR_Init, but PR_Init is not called in the main - // thread. However, PR_Opcode_Init() is idempotent. - PR_Opcode_Init (); } static void diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 7060aa35d..09ec39909 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -139,7 +139,6 @@ opcode_init (void) Hash_FlushTable (opcode_void_table); Hash_FlushTable (opcode_type_table); } else { - PR_Opcode_Init (); opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0); Hash_SetHashCompare (opcode_type_table, get_hash, compare); opcode_void_table = Hash_NewTable (1021, get_key, 0, 0, 0); From 479d82f38013c283d3a1a8362b4ae32ad8cc73e2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 19:56:15 +0900 Subject: [PATCH 2131/3664] [qfcc] Create separate instruction init and lookup v6 vs v6p are more or less as before, with ruamoko added in. qfcc will now try (and fail, due to the opcode table opnames being wrong) to create ruamoko progs when given the ruamoko target option. --- tools/qfcc/source/opcodes.c | 170 ++++++++++++++++++++++++++++++------ 1 file changed, 142 insertions(+), 28 deletions(-) diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 09ec39909..ee9722a2a 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -47,14 +47,17 @@ #include "tools/qfcc/include/statements.h" #include "tools/qfcc/include/type.h" -static hashtab_t *opcode_type_table; -static hashtab_t *opcode_void_table; -static v6p_opcode_t *opcode_map; +static hashtab_t *v6p_opcode_type_table; +static hashtab_t *v6p_opcode_void_table; +static v6p_opcode_t *v6p_opcode_map; + +static hashtab_t *rua_opcode_type_table; +static hashtab_t *rua_opcode_void_table; #define ROTL(x,n) ((((unsigned)(x))<<(n))|((unsigned)(x))>>(32-n)) static uintptr_t -get_hash (const void *_op, void *_tab) +v6p_get_hash (const void *_op, void *_tab) { v6p_opcode_t *op = (v6p_opcode_t *) _op; uintptr_t hash; @@ -65,7 +68,7 @@ get_hash (const void *_op, void *_tab) } static int -compare (const void *_opa, const void *_opb, void *unused) +v6p_compare (const void *_opa, const void *_opb, void *unused) { v6p_opcode_t *opa = (v6p_opcode_t *) _opa; v6p_opcode_t *opb = (v6p_opcode_t *) _opb; @@ -78,11 +81,41 @@ compare (const void *_opa, const void *_opb, void *unused) } static const char * -get_key (const void *op, void *unused) +v6p_get_key (const void *op, void *unused) { return ((v6p_opcode_t *) op)->name; } +static uintptr_t +rua_get_hash (const void *_op, void *_tab) +{ + opcode_t *op = (opcode_t *) _op; + uintptr_t hash; + + hash = ROTL (~op->types[0], 8) + ROTL (~op->types[1], 16) + + ROTL (~op->types[2], 24); + return hash + Hash_String (op->opname); +} + +static int +rua_compare (const void *_opa, const void *_opb, void *unused) +{ + opcode_t *opa = (opcode_t *) _opa; + opcode_t *opb = (opcode_t *) _opb; + int cmp; + + cmp = (opa->types[0] == opb->types[0]) + && (opa->types[1] == opb->types[1]) + && (opa->types[2] == opb->types[2]); + return cmp && !strcmp (opa->opname, opb->opname); +} + +static const char * +rua_get_key (const void *op, void *unused) +{ + return ((opcode_t *) op)->opname; +} + static int check_operand_type (etype_t ot1, etype_t ot2) { @@ -95,12 +128,16 @@ check_operand_type (etype_t ot1, etype_t ot2) pr_ushort_t opcode_get (instruction_t *op) { - return (v6p_opcode_t *) op - opcode_map; + if (options.code.progsversion < PROG_VERSION) { + return (v6p_opcode_t *) op - v6p_opcode_map; + } else { + return (opcode_t *) op - pr_opcodes; + } } -instruction_t * -opcode_find (const char *name, operand_t *op_a, operand_t *op_b, - operand_t *op_c) +static v6p_opcode_t * +v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, + operand_t *op_c) { v6p_opcode_t search_op = {}; v6p_opcode_t *op; @@ -112,12 +149,12 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b, search_op.type_a = op_a ? low_level_type (op_a->type) : ev_invalid; search_op.type_b = op_b ? low_level_type (op_b->type) : ev_invalid; search_op.type_c = op_c ? low_level_type (op_c->type) : ev_invalid; - op = Hash_FindElement (opcode_type_table, &search_op); + op = Hash_FindElement (v6p_opcode_type_table, &search_op); if (op) - return (instruction_t *) op; - op_list = Hash_FindList (opcode_void_table, name); + return op; + op_list = Hash_FindList (v6p_opcode_void_table, name); if (!op_list) - return (instruction_t *) op; + return op; for (i = 0; !op && op_list[i]; i++) { sop = op_list[i]; if (check_operand_type (sop->type_a, search_op.type_a) @@ -126,36 +163,78 @@ opcode_find (const char *name, operand_t *op_a, operand_t *op_b, op = sop; } free (op_list); - return (instruction_t *) op; + return op; } -void -opcode_init (void) +static opcode_t * +rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, + operand_t *op_c) +{ + opcode_t search_op = {}; + opcode_t *op; + opcode_t *sop; + void **op_list; + int i; + + search_op.opname = name; + search_op.types[0] = op_a ? low_level_type (op_a->type) : ev_invalid; + search_op.types[1] = op_b ? low_level_type (op_b->type) : ev_invalid; + search_op.types[2] = op_c ? low_level_type (op_c->type) : ev_invalid; + op = Hash_FindElement (rua_opcode_type_table, &search_op); + if (op) + return op; + op_list = Hash_FindList (rua_opcode_void_table, name); + if (!op_list) + return op; + for (i = 0; !op && op_list[i]; i++) { + sop = op_list[i]; + if (check_operand_type (sop->types[0], search_op.types[0]) + && check_operand_type (sop->types[1], search_op.types[1]) + && check_operand_type (sop->types[2], search_op.types[2])) + op = sop; + } + free (op_list); + return op; +} + +instruction_t * +opcode_find (const char *name, operand_t *op_a, operand_t *op_b, + operand_t *op_c) +{ + if (options.code.progsversion < PROG_VERSION) { + return (instruction_t *) v6p_opcode_find (name, op_a, op_b, op_c); + } else { + return (instruction_t *) rua_opcode_find (name, op_a, op_b, op_c); + } +} + +static void +v6p_opcode_init (void) { const v6p_opcode_t *op; v6p_opcode_t *mop; - if (opcode_type_table) { - Hash_FlushTable (opcode_void_table); - Hash_FlushTable (opcode_type_table); + if (v6p_opcode_type_table) { + Hash_FlushTable (v6p_opcode_void_table); + Hash_FlushTable (v6p_opcode_type_table); } else { - opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0); - Hash_SetHashCompare (opcode_type_table, get_hash, compare); - opcode_void_table = Hash_NewTable (1021, get_key, 0, 0, 0); + v6p_opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0); + Hash_SetHashCompare (v6p_opcode_type_table, v6p_get_hash, v6p_compare); + v6p_opcode_void_table = Hash_NewTable (1021, v6p_get_key, 0, 0, 0); } int num_opcodes = 0; for (op = pr_v6p_opcodes; op->name; op++) { num_opcodes++; } - if (!opcode_map) { - opcode_map = calloc (num_opcodes, sizeof (v6p_opcode_t)); + if (!v6p_opcode_map) { + v6p_opcode_map = calloc (num_opcodes, sizeof (v6p_opcode_t)); } for (int i = 0; i < num_opcodes; i++) { op = pr_v6p_opcodes + i; if (op->min_version > options.code.progsversion) continue; - mop = opcode_map + i; + mop = v6p_opcode_map + i; *mop = *op; if (options.code.progsversion == PROG_ID_VERSION) { // v6 progs have no concept of integer, but the QF engine @@ -169,9 +248,44 @@ opcode_init (void) if (mop->type_c == ev_integer) mop->type_c = ev_float; } - Hash_AddElement (opcode_type_table, mop); + Hash_AddElement (v6p_opcode_type_table, mop); if (mop->type_a == ev_void || mop->type_b == ev_void || mop->type_c == ev_void) - Hash_Add (opcode_void_table, mop); + Hash_Add (v6p_opcode_void_table, mop); + } +} + +static void +rua_opcode_init (void) +{ + if (rua_opcode_type_table) { + return; + } + + rua_opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0); + Hash_SetHashCompare (rua_opcode_type_table, rua_get_hash, rua_compare); + rua_opcode_void_table = Hash_NewTable (1021, rua_get_key, 0, 0, 0); + + int num_opcodes = sizeof (pr_opcodes) / sizeof (pr_opcodes[0]); + for (int i = 0; i < num_opcodes; i++) { + const opcode_t *op = pr_opcodes + i; + if (!op->opname) { + continue; + } + Hash_AddElement (rua_opcode_type_table, (opcode_t *) op); + if (op->types[0] == ev_void || op->types[1] == ev_void + || op->types[2] == ev_void) { + Hash_Add (rua_opcode_void_table, (opcode_t *) op); + } + } +} + +void +opcode_init (void) +{ + if (options.code.progsversion < PROG_VERSION) { + v6p_opcode_init (); + } else { + rua_opcode_init (); } } From 8559a4fe2dc896c411401d669792c8f4408ffffb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 21:48:02 +0900 Subject: [PATCH 2132/3664] whitespace --- libs/gamecode/opcodes.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index f0f2a1c26..4c0ea838b 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -78,7 +78,7 @@ bitops_formats = { "widths": "{ss+1}, {ss+1}, {ss+1}", "types": "ev_integer, ev_integer, ev_integer", "args": { - "op_bit":["bitand", "bitor", "bitxor", "bitnot"], + "op_bit": ["bitand", "bitor", "bitxor", "bitnot"], "bit_fmt": [ "%Ga, %Gb, %gc", "%Ga, %Gb, %gc", @@ -95,7 +95,7 @@ boolops_formats = { "widths": "{ss+1}, {ss+1}, {ss+1}", "types": "ev_integer, ev_integer, ev_integer", "args": { - "op_bool":["and", "or", "xor", "not"], + "op_bool": ["and", "or", "xor", "not"], "bool_fmt": [ "%Ga, %Gb, %gc", "%Ga, %Gb, %gc", @@ -151,8 +151,8 @@ compare_formats = { "types": "{cmp_types[tt]}, {cmp_types[tt]}, ev_integer", "args": { "op_cmp": compare_ccc, - "cmp_type":type_tt, - "cmp_types":etype_tt, + "cmp_type": type_tt, + "cmp_types": etype_tt, }, } compare2_formats = { @@ -163,8 +163,8 @@ compare2_formats = { "types": "{cmp_types[t]}, {cmp_types[t]}, ev_integer", "args": { "op_cmp": compare_ccc, - "cmp_type":['u', 'U'], - "cmp_types":unsigned_t, + "cmp_type": ['u', 'U'], + "cmp_types": unsigned_t, }, } convert_formats = { @@ -230,7 +230,7 @@ mathops_formats = { "types": "{math_types[tt]}, {math_types[tt]}, {math_types[tt]}", "args": { "op_math": ["mul", "div", "rem", "mod", "add", "sub", None, None], - "math_type":type_tt, + "math_type": type_tt, "math_types": etype_tt, }, } From e186d5064d946c1f90793784d283c8d83f5b54fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 21:48:19 +0900 Subject: [PATCH 2133/3664] [gamecode] Correct return's opname Not meant to have the size in it. --- libs/gamecode/opcodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 4c0ea838b..b38763156 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -438,7 +438,7 @@ rcall_formats = { return_formats = { "opcode": "OP_RETURN_{ss+1}", "mnemonic": "return{ss+1}", - "opname": "return{ss+1}", + "opname": "return", "widths": "0, 0, 0", "format": "%Ra", "types": "ev_void, ev_invalid, ev_invalid", From f5be54b6d24ddcc288e2f7b0406f871b172a62e4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Jan 2022 23:12:20 +0900 Subject: [PATCH 2134/3664] [qfcc] Sanitize expr type enum Got tired of dealing with out of date string tables. --- tools/qfcc/include/expr.h | 22 ++----------- tools/qfcc/include/expr_names.h | 58 +++++++++++++++++++++++++++++++++ tools/qfcc/source/dot_expr.c | 20 +++--------- 3 files changed, 65 insertions(+), 35 deletions(-) create mode 100644 tools/qfcc/include/expr_names.h diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5d05f2a40..c9d325e43 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -40,28 +40,12 @@ /** Type of the exression node in an expression tree. */ +#define EX_EXPR(expr) ex_##expr, typedef enum { - ex_error, ///< error expression. used to signal an error - ex_state, ///< state expression (::ex_state_t) - ex_bool, ///< short circuit boolean logic expression (::ex_bool_t) - ex_label, ///< goto/branch label (::ex_label_t) - ex_labelref, ///< label reference (::ex_labelref_t) - ex_block, ///< statement block expression (::ex_block_t) - ex_expr, ///< binary expression (::ex_expr_t) - ex_uexpr, ///< unary expression (::ex_expr_t) - ex_def, ///< non-temporary variable (::def_t) - ex_symbol, ///< non-temporary variable (::symbol_t) - ex_temp, ///< temporary variable (::ex_temp_t) - ex_vector, ///< "vector" expression (::ex_vector_t) - ex_selector, ///< selector expression (::ex_selector_t) - - ex_nil, ///< umm, nil, null. nuff said (0 of any type) - ex_value, ///< constant value (::ex_value_t) - ex_compound, ///< compound initializer - ex_memset, ///< memset needs three params... - +#include "tools/qfcc/include/expr_names.h" ex_count, ///< number of valid expression types } expr_type; +#undef EX_EXPR /** Binary and unary expressions. diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h new file mode 100644 index 000000000..d29345833 --- /dev/null +++ b/tools/qfcc/include/expr_names.h @@ -0,0 +1,58 @@ +/* + expr.h + + expression construction and manipulations + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/01/7 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +/** \defgroup qfcc_expr Expressions + \ingroup qfcc +*/ +///@{ + +#ifndef EX_EXPR +#define EX_EXPR(expr) +#endif + +EX_EXPR(error) ///< error expression. used to signal an error +EX_EXPR(state) ///< state expression (::ex_state_t) +EX_EXPR(bool) ///< short circuit boolean logic expression (::ex_bool_t) +EX_EXPR(label) ///< goto/branch label (::ex_label_t) +EX_EXPR(labelref) ///< label reference (::ex_labelref_t) +EX_EXPR(block) ///< statement block expression (::ex_block_t) +EX_EXPR(expr) ///< binary expression (::ex_expr_t) +EX_EXPR(uexpr) ///< unary expression (::ex_expr_t) +EX_EXPR(def) ///< non-temporary variable (::def_t) +EX_EXPR(symbol) ///< non-temporary variable (::symbol_t) +EX_EXPR(temp) ///< temporary variable (::ex_temp_t) +EX_EXPR(vector) ///< "vector" expression (::ex_vector_t) +EX_EXPR(selector) ///< selector expression (::ex_selector_t) +EX_EXPR(nil) ///< umm, nil, null. nuff said (0 of any type) +EX_EXPR(value) ///< constant value (::ex_value_t) +EX_EXPR(compound) ///< compound initializer +EX_EXPR(memset) ///< memset needs three params... + +///@} diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index edd1739a9..724213bc1 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -55,25 +55,13 @@ #include "tools/qfcc/source/qc-parse.h" +#define EX_EXPR(expr) #expr, const char *expr_names[] = { - "error", - "state", - "bool", - "label", - "labelref", - "block", - "expr", - "uexpr", - "def", - "symbol", - "temp", - "vector", - "nil", - "value", - "compound", - "memset", +#include "tools/qfcc/include/expr_names.h" + 0 }; +#undef EX_EXPR const char * get_op_string (int op) From ed6b84fbde9d91b47b74d9e2853a7457a933c88c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 03:07:17 +0900 Subject: [PATCH 2135/3664] [gamecode] Add missed long and ulong info Both pr_type_size and pr_type_name. I want to macroize the enum, but need to sort out the clutter of headers first, just need to decide on naming. This at least sorts out the missed values for now. --- libs/gamecode/pr_v6p_opcode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 012f23e4a..421159648 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -57,6 +57,8 @@ VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { 1, // ev_uinteger 0, // ev_short value in opcode 2, // ev_double + 2, // ev_long + 2, // ev_ulong 0, // ev_invalid not a valid/simple type }; @@ -74,6 +76,8 @@ VISIBLE const char * const pr_type_name[ev_type_count] = { "uinteger", "short", "double", + "long", + "ulong", "invalid", }; From 420d55406f166046e4dd3c2c7daee7d5dfb2b60b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 03:09:15 +0900 Subject: [PATCH 2136/3664] [qfcc] Add a rule to build the qfcc tests This makes it easier to build and run (by hand) the tests when things aren't working. --- tools/qfcc/test/Makemodule.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index d5929e0a6..5d58abb99 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -99,6 +99,8 @@ check_PROGRAMS += \ $(test_progs_dat) \ $(test_bins) +qfcc-tests: tools/qfcc/test/test-harness $(test_progs_dat) $(test_bins) + tools_qfcc_test_test_defspace_SOURCES= tools/qfcc/test/test-defspace.c $(test_defspace_src) tools_qfcc_test_test_defspace_LDADD= $(QFCC_LIBS) tools_qfcc_test_test_defspace_DEPENDENCIES= $(QFCC_DEPS) From 23c9a317f82c4b5fd509d8f34c97190add22f39a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 12:06:52 +0900 Subject: [PATCH 2137/3664] [qfcc] Give alias expressions their own type While this was a pain to get working, that pain only went to prove the value of using proper "types" (even if only an enum) for different expression types: just finding all the places to edit was a chore, and easy to make mistakes (forgetting bits here and there). Strangely enough, this exposed a pile of *type* aliasing bugs (next commit). --- tools/qfcc/include/expr.h | 7 +++ tools/qfcc/include/expr_names.h | 1 + tools/qfcc/source/constfold.c | 4 +- tools/qfcc/source/def.c | 9 ++- tools/qfcc/source/dot_expr.c | 45 ++++++++------ tools/qfcc/source/expr.c | 103 +++++++++++++++++++++----------- tools/qfcc/source/expr_assign.c | 8 +-- tools/qfcc/source/expr_binary.c | 7 +-- tools/qfcc/source/statements.c | 15 ++--- 9 files changed, 118 insertions(+), 81 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index c9d325e43..817c82e7b 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -207,6 +207,12 @@ typedef struct ex_value_s { } v; } ex_value_t; +typedef struct { + struct type_s *type; ///< type to view the expression + struct expr_s *expr; ///< the expression to alias + struct expr_s *offset; ///< offset for alias +} ex_alias_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -233,6 +239,7 @@ typedef struct expr_s { ex_value_t *value; ///< constant value element_chain_t compound; ///< compound initializer ex_memset_t memset; ///< memset expr params + ex_alias_t alias; ///< alias expr params struct type_s *nil; ///< type for nil if known } e; } expr_t; diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index d29345833..a37355bcc 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -54,5 +54,6 @@ EX_EXPR(nil) ///< umm, nil, null. nuff said (0 of any type) EX_EXPR(value) ///< constant value (::ex_value_t) EX_EXPR(compound) ///< compound initializer EX_EXPR(memset) ///< memset needs three params... +EX_EXPR(alias) ///< view expression as different type (::ex_alias_t) ///@} diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 2459b392f..497f51642 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1718,7 +1718,7 @@ fold_constants (expr_t *e) return e; } op = e->e.expr.op; - if (op == 'A' || op == 'g' || op == 'r') + if (op == 'g' || op == 'r') return e; t1 = extract_type (e1); if (t1 >= ev_type_count || !do_unary_op[t1]) { @@ -1734,7 +1734,7 @@ fold_constants (expr_t *e) } op = e->e.expr.op; - if (op == 'A' || op == 'i' || op == 'n' || op == 'c' || op == 's') { + if (op == 'i' || op == 'n' || op == 'c' || op == 's') { return e; } diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 216497a73..94cc49ce1 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -608,12 +608,11 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, error (init, "non-constant initializier"); return; } - while ((init->type == ex_uexpr || init->type == ex_expr) - && init->e.expr.op == 'A') { - if (init->type == ex_expr) { - offset += expr_integer (init->e.expr.e2); + while (init->type == ex_alias) { + if (init->e.alias.offset) { + offset += expr_integer (init->e.alias.offset); } - init = init->e.expr.e1; + init = init->e.alias.expr; } if (init->type != ex_value) { //FIXME enum etc internal_error (0, "initializier not a value"); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 724213bc1..feaf3defd 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -100,7 +100,6 @@ get_op_string (int op) case 'r': return ""; case 's': return ""; case 'c': return ""; - case 'A': return ""; case 'C': return ""; case 'M': return ""; case 'm': return ""; @@ -314,36 +313,43 @@ print_subexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"r\"];\n", indent, "", e, e->e.expr.e2); } - if (e->e.expr.op == 'A') { - dstring_t *typestr = dstring_newstr(); - print_type_str (typestr, e->e.expr.type); - dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e, - get_op_string (e->e.expr.op), typestr->str, e->line); - dstring_delete (typestr); - } else { - dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, - get_op_string (e->e.expr.op), e->line); + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + get_op_string (e->e.expr.op), e->line); +} + +static void +print_alias (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.alias.expr, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"a\"];\n", indent, "", e, + e->e.alias.expr); + if (e->e.alias.offset) { + _print_expr (dstr, e->e.alias.offset, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"o\"];\n", indent, "", e, + e->e.alias.offset); } + + dstring_t *typestr = dstring_newstr(); + print_type_str (typestr, e->e.alias.type); + dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e, + "", typestr->str, e->line); + dstring_delete (typestr); } static void print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - dstring_t *typestr = dstring_newstr(); if (e->e.expr.op != 'g' && e->e.expr.e1) _print_expr (dstr, e->e.expr.e1, level, id, next); - if (e->e.expr.op == 'A') { - dstring_copystr (typestr, "\\n"); - print_type_str (typestr, e->e.expr.type); - } if (e->e.expr.op != 'r' || e->e.expr.e1) dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, e->e.expr.e1); - dasprintf (dstr, "%*se_%p [label=\"%s%s\\n%d\"];\n", indent, "", e, - get_op_string (e->e.expr.op), typestr->str, e->line); - dstring_delete (typestr); + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + get_op_string (e->e.expr.op), e->line); } static void @@ -574,6 +580,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_value] = print_value, [ex_compound] = print_compound, [ex_memset] = print_memset, + [ex_alias] = print_alias, }; int indent = level * 2 + 2; @@ -585,7 +592,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) return; e->printid = id; - if ((int) e->type < 0 || e->type > ex_memset || !print_funcs[e->type]) { + if ((int) e->type < 0 || e->type >= ex_count || !print_funcs[e->type]) { dasprintf (dstr, "%*se_%p [label=\"(bad expr type)\\n%d\"];\n", indent, "", e, e->line); return; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index d4f36d306..cb6e7585d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -258,6 +258,8 @@ get_type (expr_t *e) return e->e.vector.type; case ex_selector: return &type_SEL; + case ex_alias: + return e->e.alias.type; case ex_count: internal_error (e, "invalid expression"); } @@ -315,7 +317,7 @@ cast_error (expr_t *e, type_t *t1, type_t *t2) print_type_str (s1, t1); print_type_str (s2, t2); - e = error (e, "cannot cast from %s to %s", s1->str, s2->str); + e = error (e, "cannot cast from %s to %s", s1->str, s2->str); dstring_delete (s1); dstring_delete (s2); return e; @@ -469,6 +471,12 @@ copy_expr (expr_t *e) n->e.memset.val = copy_expr (e->e.memset.val); n->e.memset.count = copy_expr (e->e.memset.count); return n; + case ex_alias: + n = new_expr (); + *n = *e; + n->e.alias.expr = copy_expr (e->e.alias.expr); + n->e.alias.offset = copy_expr (e->e.alias.offset); + return n; case ex_count: break; } @@ -875,9 +883,8 @@ new_short_expr (short short_val) int is_constant (expr_t *e) { - while ((e->type == ex_uexpr || e->type == ex_expr) - && e->e.expr.op == 'A') { - e = e->e.expr.e1; + while (e->type == ex_alias) { + e = e->e.alias.expr; } if (e->type == ex_nil || e->type == ex_value || e->type == ex_labelref || (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) @@ -1231,15 +1238,14 @@ is_pointer_val (expr_t *e) expr_t * new_alias_expr (type_t *type, expr_t *expr) { - expr_t *alias; - - alias = new_unary_expr ('A', expr); - alias->e.expr.type = type; - //if (expr->type == ex_uexpr && expr->e.expr.op == 'A') - // bug (alias, "aliasing an alias expression"); - if (expr->type == ex_expr && expr->e.expr.op == 'A') { + if (expr->type == ex_alias) { return new_offset_alias_expr (type, expr, 0); } + + expr_t *alias = new_expr (); + alias->type = ex_alias; + alias->e.alias.type = type; + alias->e.alias.expr = expr; alias->file = expr->file; alias->line = expr->line; return alias; @@ -1248,18 +1254,24 @@ new_alias_expr (type_t *type, expr_t *expr) expr_t * new_offset_alias_expr (type_t *type, expr_t *expr, int offset) { - expr_t *alias; - - if (expr->type == ex_expr && expr->e.expr.op == 'A') { - expr_t *ofs_expr = expr->e.expr.e2; - expr = expr->e.expr.e1; + if (expr->type == ex_alias && expr->e.alias.offset) { + expr_t *ofs_expr = expr->e.alias.offset; if (!is_constant (ofs_expr)) { internal_error (ofs_expr, "non-constant offset for alias expr"); } offset += expr_integer (ofs_expr); + + if (expr->e.alias.expr->type == ex_alias) { + internal_error (expr, "alias expr of alias expr"); + } + expr = expr->e.alias.expr; } - alias = new_binary_expr ('A', expr, new_integer_expr (offset)); - alias->e.expr.type = type; + + expr_t *alias = new_expr (); + alias->type = ex_alias; + alias->e.alias.type = type; + alias->e.alias.expr = expr; + alias->e.alias.offset = new_integer_expr (offset); alias->file = expr->file; alias->line = expr->line; return alias; @@ -1576,9 +1588,27 @@ has_function_call (expr_t *e) case ex_uexpr: if (e->e.expr.op != 'g') return has_function_call (e->e.expr.e1); - default: return 0; + case ex_alias: + return has_function_call (e->e.alias.expr); + case ex_error: + case ex_state: + case ex_label: + case ex_labelref: + case ex_def: + case ex_symbol: + case ex_temp: + case ex_vector: + case ex_selector: + case ex_nil: + case ex_value: + case ex_compound: + case ex_memset: + return 0; + case ex_count: + break; } + internal_error (e, "invalid expression type"); } expr_t * @@ -1683,6 +1713,7 @@ unary_expr (int op, expr_t *e) case ex_bool: case ex_temp: case ex_vector: + case ex_alias: { expr_t *n = new_unary_expr (op, e); @@ -1766,6 +1797,7 @@ unary_expr (int op, expr_t *e) case ex_symbol: case ex_temp: case ex_vector: + case ex_alias: { expr_t *n = new_unary_expr (op, e); @@ -1842,6 +1874,7 @@ unary_expr (int op, expr_t *e) case ex_symbol: case ex_temp: case ex_vector: + case ex_alias: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { expr_t *n1 = new_integer_expr (-1); @@ -2364,16 +2397,6 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) e = e1->e.expr.e2; break; } - if (e1->e.expr.op == 'A') { - if (!t) - t = e1->e.expr.type; - if (e2) { - e2 = binary_expr ('+', e1->e.expr.e2, e2); - } else { - e2 = e1->e.expr.e2; - } - return address_expr (e1->e.expr.e1, e2, t); - } return error (e1, "invalid type for unary &"); case ex_uexpr: if (e1->e.expr.op == '.') { @@ -2384,11 +2407,6 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) } break; } - if (e1->e.expr.op == 'A') { - if (!t) - t = e1->e.expr.type; - return address_expr (e1->e.expr.e1, e2, t); - } return error (e1, "invalid type for unary &"); case ex_label: return new_label_ref (&e1->e.label); @@ -2396,6 +2414,18 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) e = new_unary_expr ('&', e1); e->e.expr.type = pointer_type (t); break; + case ex_alias: + if (!t) { + t = e1->e.alias.type; + } + if (e1->e.alias.offset) { + if (e2) { + e2 = binary_expr ('+', e1->e.alias.offset, e2); + } else { + e2 = e1->e.alias.offset; + } + } + return address_expr (e1->e.alias.expr, e2, t); default: return error (e1, "invalid type for unary &"); } @@ -2416,8 +2446,11 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) e = new_binary_expr ('&', e, e2); } } - if (e->type == ex_expr || e->type == ex_uexpr) + if (e->type == ex_expr || e->type == ex_uexpr) { e->e.expr.type = pointer_type (t); + } else if (e->type == ex_alias) { + e->e.alias.type = pointer_type (t); + } } } return e; diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 7126b5545..80c95d1dc 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -112,17 +112,13 @@ is_lvalue (const expr_t *expr) if (expr->e.expr.op == '.') { return 1; } - if (expr->e.expr.op == 'A') { - return is_lvalue (expr->e.expr.e1); - } break; + case ex_alias: + return is_lvalue (expr->e.alias.expr); case ex_uexpr: if (expr->e.expr.op == '.') { return 1; } - if (expr->e.expr.op == 'A') { - return is_lvalue (expr->e.expr.e1); - } break; case ex_memset: case ex_compound: diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 616dc7ac4..eeb310c59 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -970,12 +970,11 @@ binary_expr (int op, expr_t *e1, expr_t *e2) e1 = convert_vector (e1); // FIXME this is target-specific info and should not be in the // expression tree - if ((e1->type == ex_expr || e1->type == ex_uexpr) && e1->e.expr.op == 'A' - && is_call (e1->e.expr.e1)) { + if (e1->type == ex_alias && is_call (e1->e.alias.expr)) { // move the alias expression inside the block so the following check // can detect the call and move the temp assignment into the block - expr_t *block = e1->e.expr.e1; - e1->e.expr.e1 = block->e.block.result; + expr_t *block = e1->e.alias.expr; + e1->e.alias.expr = block->e.block.result; block->e.block.result = e1; e1 = block; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 0dfcebe88..b34b201f0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1202,11 +1202,11 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) def_t *def; int offset = 0; - if (e->type == ex_expr) { - offset = expr_integer (e->e.expr.e2); + if (e->e.alias.offset) { + offset = expr_integer (e->e.alias.offset); } - type = e->e.expr.type; - sblock = statement_subexpr (sblock, e->e.expr.e1, &aop); + type = e->e.alias.type; + sblock = statement_subexpr (sblock, e->e.alias.expr, &aop); if (type_compatible (aop->type, type)) { //FIXME type_compatible??? shouldn't that be type_size ==? if (offset) { @@ -1268,9 +1268,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) case 'M': sblock = expr_move (sblock, e, op); break; - case 'A': - sblock = expr_alias (sblock, e, op); - break; default: opcode = convert_op (e->e.expr.op); if (!opcode) @@ -1338,9 +1335,6 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) case '.': sblock = expr_deref (sblock, e, op); break; - case 'A': - sblock = expr_alias (sblock, e, op); - break; case 'C': sblock = expr_cast (sblock, e, op); break; @@ -1529,6 +1523,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_nil] = expr_nil, [ex_value] = expr_value, [ex_selector] = expr_selector, + [ex_alias] = expr_alias, }; if (!e) { *op = 0; From da210db7207abc62de40bb4bb4f22c9c8ca3f4e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 12:10:30 +0900 Subject: [PATCH 2138/3664] [qfcc] Fix some type aliasing bugs I have no idea why sorting out expression aliasing exposed these type aliasing bugs, but it did. All tests *build* again (and pass). --- tools/qfcc/source/expr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index cb6e7585d..7f1424cb0 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1350,7 +1350,7 @@ append_expr (expr_t *block, expr_t *e) static symbol_t * get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2) { - symtab_t *strct = t1->t.symtab; + symtab_t *strct = unalias_type(t1)->t.symtab; symbol_t *sym = e2->e.symbol;//FIXME need to check symbol_t *field; @@ -1375,7 +1375,7 @@ field_expr (expr_t *e1, expr_t *e2) t1 = get_type (e1); if (e1->type == ex_error) return e1; - if (t1->type == ev_entity) { + if (is_entity (t1)) { symbol_t *field = 0; if (e2->type == ex_symbol) @@ -1395,7 +1395,8 @@ field_expr (expr_t *e1, expr_t *e2) return e; } } - } else if (t1->type == ev_pointer) { + } else if (is_pointer (t1)) { + t1 = unalias_type (t1); if (is_struct (t1->t.fldptr.type)) { symbol_t *field; @@ -1423,8 +1424,7 @@ field_expr (expr_t *e1, expr_t *e2) e->e.expr.type = pointer_type (ivar->type); return unary_expr ('.', e); } - } else if (t1->type == ev_vector || t1->type == ev_quat - || is_struct (t1)) { + } else if (is_vector (t1) || is_quaternion(t1) || is_struct (t1)) { symbol_t *field; field = get_struct_field (t1, e1, e2); @@ -2292,7 +2292,7 @@ array_expr (expr_t *array, expr_t *index) ind = expr_short (index); if (is_integer_val (index)) ind = expr_integer (index); - if (array_type->t.func.num_params + if (is_array (array_type) && is_constant (index) && (ind < array_type->t.array.base || ind - array_type->t.array.base >= array_type->t.array.size)) @@ -2715,7 +2715,7 @@ cast_expr (type_t *dstType, expr_t *e) dstType = (type_t *) unalias_type (dstType); //FIXME cast srcType = get_type (e); - if (dstType == srcType) + if (dstType == unalias_type(srcType)) return e; if ((dstType == type_default && is_enum (srcType)) From cf8061c4d36e99f82bae7ff8d062a04ff975a78c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 12:14:27 +0900 Subject: [PATCH 2139/3664] [qfcc] Mark opcode_get as pure Because gcc told me to :P --- tools/qfcc/include/opcodes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index d8aa393ea..2966235e6 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -36,7 +36,7 @@ typedef struct instruction_s instruction_t; struct operand_s; -pr_ushort_t opcode_get (instruction_t *inst); +pr_ushort_t opcode_get (instruction_t *inst) __attribute__((pure)); instruction_t *opcode_find (const char *name, struct operand_s *op_a, struct operand_s *op_b, struct operand_s *op_c); void opcode_init (void); From fa482e8ee5a8bd5e2e6bc03062bc801b51dd9dbf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 16:52:24 +0900 Subject: [PATCH 2140/3664] [qfcc] Give address expressions their own type Definitely a pain to get working after the switch, but definitely worth the effort. Still exposing type aliasing bugs. --- tools/qfcc/include/expr.h | 10 +++++ tools/qfcc/include/expr_names.h | 3 +- tools/qfcc/source/constfold.c | 8 ++-- tools/qfcc/source/dot_expr.c | 22 +++++++++++ tools/qfcc/source/expr.c | 65 ++++++++++++++++++++------------- tools/qfcc/source/expr_assign.c | 2 + tools/qfcc/source/method.c | 4 +- tools/qfcc/source/statements.c | 30 ++++++++------- 8 files changed, 99 insertions(+), 45 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 817c82e7b..5debb0058 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -213,6 +213,12 @@ typedef struct { struct expr_s *offset; ///< offset for alias } ex_alias_t; +typedef struct { + struct type_s *type; ///< pointer type + struct expr_s *lvalue; ///< the lvalue being addressed + struct expr_s *offset; ///< offset from the address +} ex_address_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -240,6 +246,7 @@ typedef struct expr_s { element_chain_t compound; ///< compound initializer ex_memset_t memset; ///< memset expr params ex_alias_t alias; ///< alias expr params + ex_address_t address; ///< alias expr params struct type_s *nil; ///< type for nil if known } e; } expr_t; @@ -654,6 +661,9 @@ expr_t *new_ret_expr (struct type_s *type); expr_t *new_alias_expr (struct type_s *type, expr_t *expr); expr_t *new_offset_alias_expr (struct type_s *type, expr_t *expr, int offset); +expr_t *new_address_expr (struct type_s *lvtype, expr_t *lvalue, + expr_t *offset); + /** Create an expression of the correct type that references the specified parameter slot. diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index a37355bcc..0842c2b2b 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -1,5 +1,5 @@ /* - expr.h + expr_names.h expression construction and manipulations @@ -55,5 +55,6 @@ EX_EXPR(value) ///< constant value (::ex_value_t) EX_EXPR(compound) ///< compound initializer EX_EXPR(memset) ///< memset needs three params... EX_EXPR(alias) ///< view expression as different type (::ex_alias_t) +EX_EXPR(address) ///< address of an lvalue expression (::ex_address_t) ///@} diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 497f51642..76c8c74fc 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -568,7 +568,7 @@ do_op_entity (int op, expr_t *e, expr_t *e1, expr_t *e2) { type_t *type = get_type (e2); - if ((op == '.' || op == '&') && type->type == ev_field) { + if (op == '.' && type->type == ev_field) { return e; } if (op == EQ || op == NE) { @@ -617,7 +617,7 @@ static expr_t * do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) { type_t *type; - static int valid[] = {'=', '-', '&', 'M', '.', EQ, NE, 0}; + static int valid[] = {'=', '-', 'M', '.', EQ, NE, 0}; if (is_integral (type = get_type (e2)) && (op == '-' || op == '+')) { // pointer arithmetic @@ -647,10 +647,10 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) else e->e.expr.type = &type_float; } - if (op != '.' && op != '&' && op != 'M' + if (op != '.' && op != 'M' && extract_type (e1) != extract_type (e2)) return type_mismatch (e1, e2, op); - if ((op == '.' || op == '&') && is_uinteger(get_type (e2))) + if (op == '.' && is_uinteger(get_type (e2))) e->e.expr.e2 = cf_cast_expr (&type_integer, e2); return e; } diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index feaf3defd..32ceea58c 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -338,6 +338,27 @@ print_alias (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) dstring_delete (typestr); } +static void +print_address (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.alias.expr, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"&\"];\n", indent, "", e, + e->e.alias.expr); + if (e->e.alias.offset) { + _print_expr (dstr, e->e.alias.offset, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"+\"];\n", indent, "", e, + e->e.alias.offset); + } + + dstring_t *typestr = dstring_newstr(); + print_type_str (typestr, e->e.alias.type); + dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e, + "&", typestr->str, e->line); + dstring_delete (typestr); +} + static void print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -581,6 +602,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_compound] = print_compound, [ex_memset] = print_memset, [ex_alias] = print_alias, + [ex_address] = print_address, }; int indent = level * 2 + 2; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 7f1424cb0..257eeed17 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -260,6 +260,8 @@ get_type (expr_t *e) return &type_SEL; case ex_alias: return e->e.alias.type; + case ex_address: + return e->e.address.type; case ex_count: internal_error (e, "invalid expression"); } @@ -477,6 +479,12 @@ copy_expr (expr_t *e) n->e.alias.expr = copy_expr (e->e.alias.expr); n->e.alias.offset = copy_expr (e->e.alias.offset); return n; + case ex_address: + n = new_expr (); + *n = *e; + n->e.address.lvalue = copy_expr (e->e.address.lvalue); + n->e.address.offset = copy_expr (e->e.address.offset); + return n; case ex_count: break; } @@ -1277,6 +1285,17 @@ new_offset_alias_expr (type_t *type, expr_t *expr, int offset) return alias; } +expr_t * +new_address_expr (type_t *lvtype, expr_t *lvalue, expr_t *offset) +{ + expr_t *addr = new_expr (); + addr->type = ex_address; + addr->e.address.type = pointer_type (lvtype); + addr->e.address.lvalue = lvalue; + addr->e.address.offset = offset; + return addr; +} + static expr_t * param_expr (const char *name, type_t *type) { @@ -1406,8 +1425,7 @@ field_expr (expr_t *e1, expr_t *e2) e2->type = ex_value; e2->e.value = new_short_val (field->s.offset); - e = new_binary_expr ('&', e1, e2); - e->e.expr.type = pointer_type (field->type); + e = new_address_expr (field->type, e1, e2); return unary_expr ('.', e); } else if (is_class (t1->t.fldptr.type)) { class_t *class = t1->t.fldptr.type->t.class; @@ -1420,8 +1438,7 @@ field_expr (expr_t *e1, expr_t *e2) return new_error_expr (); e2->type = ex_value; e2->e.value = new_short_val (ivar->s.offset); - e = new_binary_expr ('&', e1, e2); - e->e.expr.type = pointer_type (ivar->type); + e = new_address_expr (ivar->type, e1, e2); return unary_expr ('.', e); } } else if (is_vector (t1) || is_quaternion(t1) || is_struct (t1)) { @@ -1591,6 +1608,8 @@ has_function_call (expr_t *e) return 0; case ex_alias: return has_function_call (e->e.alias.expr); + case ex_address: + return has_function_call (e->e.address.lvalue); case ex_error: case ex_state: case ex_label: @@ -1735,6 +1754,7 @@ unary_expr (int op, expr_t *e) return n; } case ex_nil: + case ex_address: return error (e, "invalid type for unary -"); case ex_count: internal_error (e, "invalid expression"); @@ -1798,6 +1818,7 @@ unary_expr (int op, expr_t *e) case ex_temp: case ex_vector: case ex_alias: + case ex_address: { expr_t *n = new_unary_expr (op, e); @@ -1890,6 +1911,7 @@ bitnot_expr: return n; } case ex_nil: + case ex_address: return error (e, "invalid type for unary ~"); case ex_count: internal_error (e, "invalid expression"); @@ -2312,9 +2334,7 @@ array_expr (expr_t *array, expr_t *index) e = address_expr (array, index, array_type->t.array.type); } else { if (!is_short_val (index) || expr_short (index)) { - e = new_binary_expr ('&', array, index); - //e->e.expr.type = array_type->aux_type; - e->e.expr.type = array_type; + e = new_address_expr (array_type->t.array.type, array, index); } else { e = array; } @@ -2382,9 +2402,8 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) return error (e1, "invalid type for unary &"); case ex_expr: if (e1->e.expr.op == '.') { - e = e1; - e->e.expr.op = '&'; - e->e.expr.type = pointer_type (e->e.expr.type); + e = new_address_expr (e1->e.expr.type, + e1->e.expr.e1, e1->e.expr.e2); break; } if (e1->e.expr.op == 'm') { @@ -2402,8 +2421,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) if (e1->e.expr.op == '.') { e = e1->e.expr.e1; if (e->type == ex_expr && e->e.expr.op == '.') { - e->e.expr.type = pointer_type (e->e.expr.type); - e->e.expr.op = '&'; + e = new_address_expr (e->e.expr.type, e->e.expr.e1, e->e.expr.e2); } break; } @@ -2411,8 +2429,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) case ex_label: return new_label_ref (&e1->e.label); case ex_temp: - e = new_unary_expr ('&', e1); - e->e.expr.type = pointer_type (t); + e = new_address_expr (t, e1, 0); break; case ex_alias: if (!t) { @@ -2438,19 +2455,17 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) def_t *def = e->e.value->v.pointer.def; e->e.value = new_pointer_val (base + offset, t, def, 0); } else { - if (!is_short_val (e2) || expr_short (e2)) { - if (e->type == ex_expr && e->e.expr.op == '&') { - e = new_binary_expr ('&', e->e.expr.e1, - binary_expr ('+', e->e.expr.e2, e2)); - } else { - e = new_binary_expr ('&', e, e2); - } + expr_t *offset = 0; + if (e->type == ex_address) { + offset = e->e.address.offset; + e1 = e->e.address.lvalue; + } else { + e1 = e; } - if (e->type == ex_expr || e->type == ex_uexpr) { - e->e.expr.type = pointer_type (t); - } else if (e->type == ex_alias) { - e->e.alias.type = pointer_type (t); + if (offset) { + e2 = binary_expr ('+', offset, e2); } + e = new_address_expr (t, e1, e2); } } return e; diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 80c95d1dc..eae003bc9 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -115,6 +115,8 @@ is_lvalue (const expr_t *expr) break; case ex_alias: return is_lvalue (expr->e.alias.expr); + case ex_address: + return 0; case ex_uexpr: if (expr->e.expr.op == '.') { return 1; diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 55a4f2344..134f1cc64 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -486,8 +486,8 @@ get_selector (expr_t *sel) if (sel->type == ex_selector) { return sel->e.selector.sel; } - if (sel->type != ex_expr && sel->e.expr.op != '&' - && !is_SEL(sel->e.expr.type)) { + if (sel->type != ex_address && !sel->e.address.offset + && !is_SEL(sel->e.address.type)) { error (sel, "not a selector"); return 0; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index b34b201f0..205c22c3e 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -744,8 +744,11 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op) { statement_t *s; s = new_statement (st_expr, "&", e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - s->opc = temp_operand (e->e.expr.type, e); + sblock = statement_subexpr (sblock, e->e.address.lvalue, &s->opa); + if (e->e.address.offset) { + sblock = statement_subexpr (sblock, e->e.address.offset, &s->opb); + } + s->opc = temp_operand (e->e.address.type, e); sblock_add_statement (sblock, s); *(op) = s->opc; return sblock; @@ -960,9 +963,12 @@ dereference_dst: // to get the pointer and switch to storep instructions. dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); opcode = ".="; // FIXME find a nicer representation (lose strings?) - if (dst_expr->type == ex_expr && !is_const_ptr (dst_expr->e.expr.e1)) { - sblock = statement_subexpr (sblock, dst_expr->e.expr.e1, &dst); - sblock = statement_subexpr (sblock, dst_expr->e.expr.e2, &ofs); + if (dst_expr->type == ex_address && dst_expr->e.address.offset + && !is_const_ptr (dst_expr->e.address.lvalue)) { + sblock = statement_subexpr (sblock, + dst_expr->e.address.lvalue, &dst); + sblock = statement_subexpr (sblock, + dst_expr->e.address.offset, &ofs); } else { sblock = statement_subexpr (sblock, dst_expr, &dst); ofs = 0; @@ -1127,17 +1133,17 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) expr_t *e; e = deref->e.expr.e1; - if (e->type == ex_uexpr && e->e.expr.op == '&' - && e->e.expr.e1->type == ex_symbol) { + if (e->type == ex_address && !e->e.address.offset + && e->e.address.lvalue->type == ex_symbol) { if (e->e.expr.e1->e.symbol->sy_type != sy_var) internal_error (e, "address of non-var"); *op = def_operand (e->e.expr.e1->e.symbol->s.def, type, e); - } else if (e->type == ex_expr && e->e.expr.op == '&') { + } else if (e->type == ex_address && e->e.address.offset) { statement_t *s; operand_t *ptr = 0; operand_t *offs = 0; - sblock = statement_subexpr (sblock, e->e.expr.e1, &ptr); - sblock = statement_subexpr (sblock, e->e.expr.e2, &offs); + sblock = statement_subexpr (sblock, e->e.address.lvalue, &ptr); + sblock = statement_subexpr (sblock, e->e.address.offset, &offs); if (!*op) *op = temp_operand (type, e); if (low_level_type (type) == ev_void) { @@ -1329,9 +1335,6 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) statement_t *s; switch (e->e.expr.op) { - case '&': - sblock = expr_address (sblock, e, op); - break; case '.': sblock = expr_deref (sblock, e, op); break; @@ -1524,6 +1527,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_value] = expr_value, [ex_selector] = expr_selector, [ex_alias] = expr_alias, + [ex_address] = expr_address, }; if (!e) { *op = 0; From d14f695c68c54e3683dec1de5cbb29d0005059fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 16:54:08 +0900 Subject: [PATCH 2141/3664] [qfcc] Fix another type aliasing bug This one exposed by the address expression cleanup. --- tools/qfcc/source/expr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 257eeed17..f8adf1351 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1921,7 +1921,8 @@ bitnot_expr: if (extract_type (e) != ev_pointer) return error (e, "invalid type for unary ."); e = new_unary_expr ('.', e); - e->e.expr.type = get_type (e->e.expr.e1)->t.fldptr.type; + const type_t *t = unalias_type (get_type (e->e.expr.e1)); + e->e.expr.type = t->t.fldptr.type; return e; case '+': if (!is_math (get_type (e))) From 65b6c366c33533213fcf6fbad67df8b0847f8a03 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 18:44:29 +0900 Subject: [PATCH 2142/3664] [qfcc] Give assignment expressions their own type This is getting easier (know where to look, I guess). Nicely, I found the source of those weird type aliasing bugs :) --- tools/qfcc/include/expr.h | 7 +++ tools/qfcc/include/expr_names.h | 1 + tools/qfcc/source/constfold.c | 82 ++++++++++++--------------------- tools/qfcc/source/dot_expr.c | 30 +++++++++--- tools/qfcc/source/expr.c | 24 ++++++++++ tools/qfcc/source/expr_assign.c | 6 +-- tools/qfcc/source/expr_bool.c | 8 ++-- tools/qfcc/source/statements.c | 31 +++++++------ 8 files changed, 109 insertions(+), 80 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5debb0058..5773d834e 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -219,6 +219,11 @@ typedef struct { struct expr_s *offset; ///< offset from the address } ex_address_t; +typedef struct { + struct expr_s *dst; ///< destination of assignment + struct expr_s *src; ///< source of assignment +} ex_assign_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -247,6 +252,7 @@ typedef struct expr_s { ex_memset_t memset; ///< memset expr params ex_alias_t alias; ///< alias expr params ex_address_t address; ///< alias expr params + ex_assign_t assign; ///< assignment expr params struct type_s *nil; ///< type for nil if known } e; } expr_t; @@ -663,6 +669,7 @@ expr_t *new_offset_alias_expr (struct type_s *type, expr_t *expr, int offset); expr_t *new_address_expr (struct type_s *lvtype, expr_t *lvalue, expr_t *offset); +expr_t *new_assign_expr (expr_t *dst, expr_t *src); /** Create an expression of the correct type that references the specified parameter slot. diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index 0842c2b2b..25ebfe07c 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -56,5 +56,6 @@ EX_EXPR(compound) ///< compound initializer EX_EXPR(memset) ///< memset needs three params... EX_EXPR(alias) ///< view expression as different type (::ex_alias_t) EX_EXPR(address) ///< address of an lvalue expression (::ex_address_t) +EX_EXPR(assign) ///< assignment of src expr to dst expr ///@} diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 76c8c74fc..6bc564e4a 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -85,7 +85,7 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) { const char *s1, *s2; static dstring_t *temp_str; - static int valid[] = {'=', '+', LT, GT, LE, GE, EQ, NE, 0}; + static int valid[] = {'+', LT, GT, LE, GE, EQ, NE, 0}; if (!valid_op (op, valid)) return error (e1, "invalid operand for string"); @@ -99,7 +99,7 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_string; } - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; s1 = expr_string (e1); @@ -220,27 +220,18 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) expr_t *conv; type_t *type = &type_float; static int valid[] = { - '=', '+', '-', '*', '/', '&', '|', '^', '%', + '+', '-', '*', '/', '&', '|', '^', '%', SHL, SHR, AND, OR, LT, GT, LE, GE, EQ, NE, 0 }; if (!valid_op (op, valid)) return error (e1, "invalid operator for float"); - if (op == '=') { - if (!is_float(type = get_type (e1))) { - //FIXME optimize casting a constant - e->e.expr.e2 = e2 = cf_cast_expr (type, e2); - } else if ((conv = convert_to_float (e2)) != e2) { - e->e.expr.e2 = e2 = conv; - } - } else { - if ((conv = convert_to_float (e1)) != e1) { - e->e.expr.e1 = e1 = conv; - } - if ((conv = convert_to_float (e2)) != e2) { - e->e.expr.e2 = e2 = conv; - } + if ((conv = convert_to_float (e1)) != e1) { + e->e.expr.e1 = e1 = conv; + } + if ((conv = convert_to_float (e2)) != e2) { + e->e.expr.e2 = e2 = conv; } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) @@ -271,7 +262,7 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && is_constant (e2) && expr_float (e2) == 0) return e1; - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; f1 = expr_float (e1); @@ -349,27 +340,18 @@ do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2) expr_t *conv; type_t *type = &type_double; static int valid[] = { - '=', '+', '-', '*', '/', '%', + '+', '-', '*', '/', '%', LT, GT, LE, GE, EQ, NE, 0 }; if (!valid_op (op, valid)) return error (e1, "invalid operator for double"); - if (op == '=') { - if (!is_double(type = get_type (e1))) { - //FIXME optimize casting a constant - e->e.expr.e2 = e2 = cf_cast_expr (type, e2); - } else if ((conv = convert_to_double (e2)) != e2) { - e->e.expr.e2 = e2 = conv; - } - } else { - if ((conv = convert_to_double (e1)) != e1) { - e->e.expr.e1 = e1 = conv; - } - if ((conv = convert_to_double (e2)) != e2) { - e->e.expr.e2 = e2 = conv; - } + if ((conv = convert_to_double (e1)) != e1) { + e->e.expr.e1 = e1 = conv; + } + if ((conv = convert_to_double (e2)) != e2) { + e->e.expr.e2 = e2 = conv; } if (is_compare (op) || is_logic (op)) { type = &type_integer; @@ -397,7 +379,7 @@ do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && is_constant (e2) && expr_double (e2) == 0) return e1; - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; d1 = expr_double (e1); @@ -452,7 +434,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) { const float *v1, *v2; vec3_t v, float_vec; - static int valid[] = {'=', '+', '-', '*', EQ, NE, 0}; + static int valid[] = {'+', '-', '*', EQ, NE, 0}; expr_t *t; if (!is_vector(get_type (e1))) { @@ -510,7 +492,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && is_constant (e2) && VectorIsZero (expr_vector (e2))) return e1; - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; if (is_float_val (e1)) { @@ -578,7 +560,7 @@ do_op_entity (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_float; return e; } - if (op != '=' || !is_entity(type)) + if (!is_entity(type)) return error (e1, "invalid operator for entity"); e->e.expr.type = &type_entity; return e; @@ -587,10 +569,7 @@ do_op_entity (int op, expr_t *e, expr_t *e1, expr_t *e2) static expr_t * do_op_field (int op, expr_t *e, expr_t *e1, expr_t *e2) { - if (op != '=') - return error (e1, "invalid operator for field"); - e->e.expr.type = &type_field; - return e; + return error (e1, "invalid operator for field"); } static expr_t * @@ -607,17 +586,14 @@ do_op_func (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_float; return e; } - if (op != '=') - return error (e1, "invalid operator for func"); - e->e.expr.type = &type_function; - return e; + return error (e1, "invalid operator for func"); } static expr_t * do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) { type_t *type; - static int valid[] = {'=', '-', 'M', '.', EQ, NE, 0}; + static int valid[] = {'-', 'M', '.', EQ, NE, 0}; if (is_integral (type = get_type (e2)) && (op == '-' || op == '+')) { // pointer arithmetic @@ -682,7 +658,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) { const float *q1, *q2; quat_t q, float_quat; - static int valid[] = {'=', '+', '-', '*', EQ, NE, 0}; + static int valid[] = {'+', '-', '*', EQ, NE, 0}; expr_t *t; if (!is_quaternion(get_type (e1))) { @@ -731,7 +707,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && is_constant (e2) && QuatIsZero (expr_quaternion (e2))) return e1; - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; if (is_float_val (e1)) { @@ -793,7 +769,7 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) int isval1 = 0, isval2 = 0; int val1 = 0, val2 = 0; static int valid[] = { - '=', '+', '-', '*', '/', '&', '|', '^', '%', + '+', '-', '*', '/', '&', '|', '^', '%', SHL, SHR, AND, OR, LT, GT, LE, GE, EQ, NE, 0 }; @@ -848,7 +824,7 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && isval2 && val2 == 0) return e1; - if (op == '=' || !isval1 || !isval2) + if (!isval1 || !isval2) return e; switch (op) { @@ -927,7 +903,7 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) { short i1, i2; static int valid[] = { - '=', '+', '-', '*', '/', '&', '|', '^', '%', + '+', '-', '*', '/', '&', '|', '^', '%', SHL, SHR, AND, OR, LT, GT, LE, GE, EQ, NE, 0 }; @@ -943,7 +919,7 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_short; } - if (op == '=' || !is_constant (e1) || !is_constant (e2)) + if (!is_constant (e1) || !is_constant (e2)) return e; i1 = expr_short (e1); @@ -1019,7 +995,7 @@ do_op_struct (int op, expr_t *e, expr_t *e1, expr_t *e2) { type_t *type; - if (op != '=' && op != 'm') + if (op != 'm') return error (e1, "invalid operator for struct"); if ((type = get_type (e1)) != get_type (e2)) return type_mismatch (e1, e2, op); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 32ceea58c..008c99651 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -75,7 +75,6 @@ get_op_string (int op) case GE: return ">="; case LT: return "<"; case GT: return ">"; - case '=': return "="; case '+': return "+"; case '-': return "-"; case '*': return "*"; @@ -343,22 +342,38 @@ print_address (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - _print_expr (dstr, e->e.alias.expr, level, id, next); + _print_expr (dstr, e->e.address.lvalue, level, id, next); dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"&\"];\n", indent, "", e, - e->e.alias.expr); - if (e->e.alias.offset) { - _print_expr (dstr, e->e.alias.offset, level, id, next); + e->e.address.lvalue); + if (e->e.address.offset) { + _print_expr (dstr, e->e.address.offset, level, id, next); dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"+\"];\n", indent, "", e, - e->e.alias.offset); + e->e.address.offset); } dstring_t *typestr = dstring_newstr(); - print_type_str (typestr, e->e.alias.type); + print_type_str (typestr, e->e.address.type); dasprintf (dstr, "%*se_%p [label=\"%s (%s)\\n%d\"];\n", indent, "", e, "&", typestr->str, e->line); dstring_delete (typestr); } +static void +print_assign (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.assign.dst, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"lval\"];\n", indent, "", e, + e->e.assign.dst); + _print_expr (dstr, e->e.assign.src, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"rval\"];\n", indent, "", e, + e->e.assign.src); + + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + "=", e->line); +} + static void print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -603,6 +618,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_memset] = print_memset, [ex_alias] = print_alias, [ex_address] = print_address, + [ex_assign] = print_assign, }; int indent = level * 2 + 2; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index f8adf1351..a67b1e3f1 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -262,6 +262,8 @@ get_type (expr_t *e) return e->e.alias.type; case ex_address: return e->e.address.type; + case ex_assign: + return get_type (e->e.assign.dst); case ex_count: internal_error (e, "invalid expression"); } @@ -485,6 +487,12 @@ copy_expr (expr_t *e) n->e.address.lvalue = copy_expr (e->e.address.lvalue); n->e.address.offset = copy_expr (e->e.address.offset); return n; + case ex_assign: + n = new_expr (); + *n = *e; + n->e.assign.dst = copy_expr (e->e.assign.dst); + n->e.assign.src = copy_expr (e->e.assign.src); + return n; case ex_count: break; } @@ -1296,6 +1304,16 @@ new_address_expr (type_t *lvtype, expr_t *lvalue, expr_t *offset) return addr; } +expr_t * +new_assign_expr (expr_t *dst, expr_t *src) +{ + expr_t *addr = new_expr (); + addr->type = ex_assign; + addr->e.assign.dst = dst; + addr->e.assign.src = src; + return addr; +} + static expr_t * param_expr (const char *name, type_t *type) { @@ -1610,6 +1628,9 @@ has_function_call (expr_t *e) return has_function_call (e->e.alias.expr); case ex_address: return has_function_call (e->e.address.lvalue); + case ex_assign: + return (has_function_call (e->e.assign.dst) + || has_function_call (e->e.assign.src)); case ex_error: case ex_state: case ex_label: @@ -1733,6 +1754,7 @@ unary_expr (int op, expr_t *e) case ex_temp: case ex_vector: case ex_alias: + case ex_assign: { expr_t *n = new_unary_expr (op, e); @@ -1819,6 +1841,7 @@ unary_expr (int op, expr_t *e) case ex_vector: case ex_alias: case ex_address: + case ex_assign: { expr_t *n = new_unary_expr (op, e); @@ -1896,6 +1919,7 @@ unary_expr (int op, expr_t *e) case ex_temp: case ex_vector: case ex_alias: + case ex_assign: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { expr_t *n1 = new_integer_expr (-1); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index eae003bc9..24ce2e349 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -117,6 +117,8 @@ is_lvalue (const expr_t *expr) return is_lvalue (expr->e.alias.expr); case ex_address: return 0; + case ex_assign: + return 0; case ex_uexpr: if (expr->e.expr.op == '.') { return 1; @@ -283,7 +285,6 @@ is_memset (expr_t *e) expr_t * assign_expr (expr_t *dst, expr_t *src) { - int op = '='; expr_t *expr; type_t *dst_type, *src_type; @@ -355,7 +356,6 @@ assign_expr (expr_t *dst, expr_t *src) convert_nil (src, dst_type); } - expr = new_binary_expr (op, dst, src); - expr->e.expr.type = dst_type; + expr = new_assign_expr (dst, src); return expr; } diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 83c202692..3861951db 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -249,16 +249,16 @@ convert_bool (expr_t *e, int block) { expr_t *b; - if (e->type == ex_expr && e->e.expr.op == '=') { + if (e->type == ex_assign) { expr_t *src; if (!e->paren && options.warnings.precedence) warning (e, "suggest parentheses around assignment " "used as truth value"); - src = e->e.expr.e2; + src = e->e.assign.src; if (src->type == ex_block) { src = new_temp_def_expr (get_type (src)); - e = new_binary_expr (e->e.expr.op, e->e.expr.e1, - assign_expr (src, e->e.expr.e2)); + e = new_assign_expr (e->e.assign.dst, + assign_expr (src, e->e.assign.src)); } b = convert_bool (src, 1); if (b->type == ex_error) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 205c22c3e..7180dc205 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -574,7 +574,6 @@ convert_op (int op) case GE: return ">="; case LT: return "<"; case GT: return ">"; - case '=': return "="; case '+': return "+"; case '-': return "-"; case '*': return "*"; @@ -819,8 +818,8 @@ static sblock_t * expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) { statement_t *s; - expr_t *dst_expr = e->e.expr.e1; - expr_t *src_expr = e->e.expr.e2; + expr_t *dst_expr = e->e.assign.dst; + expr_t *src_expr = e->e.assign.src; type_t *dst_type = get_type (dst_expr); type_t *src_type = get_type (src_expr); unsigned count; @@ -912,16 +911,16 @@ static sblock_t * expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) { statement_t *s; - expr_t *src_expr = e->e.expr.e2; - expr_t *dst_expr = e->e.expr.e1; + expr_t *src_expr = e->e.assign.src; + expr_t *dst_expr = e->e.assign.dst; type_t *dst_type = get_type (dst_expr); operand_t *src = 0; operand_t *dst = 0; operand_t *ofs = 0; - const char *opcode = convert_op (e->e.expr.op); + const char *opcode = "="; st_type_t type; - if (src_expr->type == ex_expr && src_expr->e.expr.op == '=') { + if (src_expr->type == ex_assign) { sblock = statement_subexpr (sblock, src_expr, &src); if (is_structural (dst_type)) { return expr_assign_copy (sblock, e, op, src); @@ -1267,9 +1266,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) case 'c': sblock = expr_call (sblock, e, op); break; - case '=': - sblock = expr_assign (sblock, e, op); - break; case 'm': case 'M': sblock = expr_move (sblock, e, op); @@ -1528,6 +1524,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_selector] = expr_selector, [ex_alias] = expr_alias, [ex_address] = expr_address, + [ex_assign] = expr_assign, }; if (!e) { *op = 0; @@ -1574,6 +1571,10 @@ build_bool_block (expr_t *block, expr_t *e) e->next = 0; append_expr (block, e); return; + case ex_assign: + e->next = 0; + append_expr (block, e); + return; case ex_expr: if (e->e.expr.op == OR || e->e.expr.op == AND) { build_bool_block (block, e->e.expr.e1); @@ -1735,9 +1736,6 @@ statement_expr (sblock_t *sblock, expr_t *e) case IFA: sblock = statement_branch (sblock, e); break; - case '=': - sblock = expr_assign (sblock, e, 0); - break; case 'm': case 'M': sblock = expr_move (sblock, e, 0); @@ -1818,6 +1816,12 @@ statement_memset (sblock_t *sblock, expr_t *e) return sblock; } +static sblock_t * +statement_assign (sblock_t *sblock, expr_t *e) +{ + return expr_assign (sblock, e, 0); +} + static sblock_t * statement_nonexec (sblock_t *sblock, expr_t *e) { @@ -1844,6 +1848,7 @@ statement_slist (sblock_t *sblock, expr_t *e) [ex_nil] = statement_nonexec, [ex_value] = statement_nonexec, [ex_memset] = statement_memset, + [ex_assign] = statement_assign, }; for (/**/; e; e = e->next) { From 134f5ca6a48134b372563fee93e61a986fb0c99f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 18:48:23 +0900 Subject: [PATCH 2143/3664] Revert "[qfcc] Fix some type aliasing bugs" This reverts commit da210db7207abc62de40bb4bb4f22c9c8ca3f4e7. Found the cause: revered to wrong case for template code --- tools/qfcc/source/expr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index a67b1e3f1..a7c71bff3 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1387,7 +1387,7 @@ append_expr (expr_t *block, expr_t *e) static symbol_t * get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2) { - symtab_t *strct = unalias_type(t1)->t.symtab; + symtab_t *strct = t1->t.symtab; symbol_t *sym = e2->e.symbol;//FIXME need to check symbol_t *field; @@ -1412,7 +1412,7 @@ field_expr (expr_t *e1, expr_t *e2) t1 = get_type (e1); if (e1->type == ex_error) return e1; - if (is_entity (t1)) { + if (t1->type == ev_entity) { symbol_t *field = 0; if (e2->type == ex_symbol) @@ -1432,8 +1432,7 @@ field_expr (expr_t *e1, expr_t *e2) return e; } } - } else if (is_pointer (t1)) { - t1 = unalias_type (t1); + } else if (t1->type == ev_pointer) { if (is_struct (t1->t.fldptr.type)) { symbol_t *field; @@ -1459,7 +1458,8 @@ field_expr (expr_t *e1, expr_t *e2) e = new_address_expr (ivar->type, e1, e2); return unary_expr ('.', e); } - } else if (is_vector (t1) || is_quaternion(t1) || is_struct (t1)) { + } else if (t1->type == ev_vector || t1->type == ev_quat + || is_struct (t1)) { symbol_t *field; field = get_struct_field (t1, e1, e2); @@ -2339,7 +2339,7 @@ array_expr (expr_t *array, expr_t *index) ind = expr_short (index); if (is_integer_val (index)) ind = expr_integer (index); - if (is_array (array_type) + if (array_type->t.func.num_params && is_constant (index) && (ind < array_type->t.array.base || ind - array_type->t.array.base >= array_type->t.array.size)) @@ -2755,7 +2755,7 @@ cast_expr (type_t *dstType, expr_t *e) dstType = (type_t *) unalias_type (dstType); //FIXME cast srcType = get_type (e); - if (dstType == unalias_type(srcType)) + if (dstType == srcType) return e; if ((dstType == type_default && is_enum (srcType)) From 62d58a2255479fc583bff918df041a510137d3f1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 18:48:54 +0900 Subject: [PATCH 2144/3664] Revert "[qfcc] Fix another type aliasing bug" This reverts commit d14f695c68c54e3683dec1de5cbb29d0005059fe. Found the cause: revered to wrong case for template code --- tools/qfcc/source/expr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index a7c71bff3..682a9ed0e 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1945,8 +1945,7 @@ bitnot_expr: if (extract_type (e) != ev_pointer) return error (e, "invalid type for unary ."); e = new_unary_expr ('.', e); - const type_t *t = unalias_type (get_type (e->e.expr.e1)); - e->e.expr.type = t->t.fldptr.type; + e->e.expr.type = get_type (e->e.expr.e1)->t.fldptr.type; return e; case '+': if (!is_math (get_type (e))) From 14352ea65a8cd5f08cc1e8881b8c4d89a53f71f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 18:49:35 +0900 Subject: [PATCH 2145/3664] [qfcc] Really fix those type aliasing bugs Found the cause: revered to wrong case for template code :/ --- tools/qfcc/source/expr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 682a9ed0e..39b703f0d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -259,9 +259,11 @@ get_type (expr_t *e) case ex_selector: return &type_SEL; case ex_alias: - return e->e.alias.type; + type = e->e.alias.type; + break; case ex_address: - return e->e.address.type; + type = e->e.address.type; + break; case ex_assign: return get_type (e->e.assign.dst); case ex_count: From 63795e790bef3b202c3c1baa3174c3c0d42821ea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 8 Jan 2022 20:55:20 +0900 Subject: [PATCH 2146/3664] [qfcc] Clean out some old code The move operator names are definitely obsolete (due to dropping the expressions a year or two ago) and the precedence checks seem to be handled elsewhere. Memset and state expressions went away a while back too. --- tools/qfcc/include/expr.h | 16 ---------------- tools/qfcc/source/constfold.c | 2 +- tools/qfcc/source/dot_expr.c | 1 - tools/qfcc/source/expr.c | 27 --------------------------- tools/qfcc/source/expr_binary.c | 8 +++----- tools/qfcc/source/statements.c | 2 -- 6 files changed, 4 insertions(+), 52 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5773d834e..47d382929 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -680,22 +680,6 @@ expr_t *new_assign_expr (expr_t *dst, expr_t *src); */ expr_t *new_param_expr (struct type_s *type, int num); -/** Create an expression representing a block copy. - - This is used for structure assignments. - - \param e1 Destination of move. - \param e2 Source of move. - \param type type giving size of move. - \param indirect Move uses dereferenced pointers. - \return A new expression representing the move. -*/ -expr_t *new_move_expr (expr_t *e1, expr_t *e2, struct type_s *type, - int indirect); - -expr_t *new_memset_expr (expr_t *dst, expr_t *val, struct type_s *type); - - /** Convert a name to an expression of the appropriate type. Converts the expression in-place. If the exprssion is not a name diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 6bc564e4a..520693b01 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1710,7 +1710,7 @@ fold_constants (expr_t *e) } op = e->e.expr.op; - if (op == 'i' || op == 'n' || op == 'c' || op == 's') { + if (op == 'i' || op == 'n' || op == 'c') { return e; } diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 008c99651..95c6807f1 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -97,7 +97,6 @@ get_op_string (int op) case IFA: return ""; case 'g': return ""; case 'r': return ""; - case 's': return ""; case 'c': return ""; case 'C': return ""; case 'M': return ""; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 39b703f0d..6749422c0 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1341,33 +1341,6 @@ new_param_expr (type_t *type, int num) return param_expr (va (0, ".param_%d", num), type); } -expr_t * -new_move_expr (expr_t *e1, expr_t *e2, type_t *type, int indirect) -{ - expr_t *e = new_binary_expr (indirect ? 'M' : 'm', e1, e2); - e->e.expr.type = type; - return e; -} - -expr_t * -new_memset_expr (expr_t *dst, expr_t *val, type_t *type) -{ - expr_t *e; - if (!is_pointer (get_type (dst))) { - return error (dst, "incorrect destination type for memset"); - } - if (!is_scalar (get_type (val))) { - return error (val, "memset value must be a scalar"); - } - e = new_expr (); - e->type = ex_memset; - e->e.memset.dst = dst; - e->e.memset.val = val; - e->e.memset.count = new_integer_expr (type_size (type)); - e->e.memset.type = type; - return e; -} - expr_t * append_expr (expr_t *block, expr_t *e) { diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index eeb310c59..df304f119 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -873,7 +873,7 @@ check_precedence (int op, expr_t *e1, expr_t *e2) { if (e1->type == ex_uexpr && e1->e.expr.op == '!' && !e1->paren) { if (options.traditional) { - if (op != AND && op != OR && op != '=') { + if (op != AND && op != OR) { notice (e1, "precedence of `!' and `%s' inverted for " "traditional code", get_op_string (op)); e1->e.expr.e1->paren = 1; @@ -890,8 +890,7 @@ check_precedence (int op, expr_t *e1, expr_t *e2) if (e2->type == ex_expr && !e2->paren) { if (((op == '&' || op == '|') && (is_math_op (e2->e.expr.op) || is_compare (e2->e.expr.op))) - || (op == '=' - && (e2->e.expr.op == OR || e2->e.expr.op == AND))) { + || (e2->e.expr.op == OR || e2->e.expr.op == AND)) { notice (e1, "precedence of `%s' and `%s' inverted for " "traditional code", get_op_string (op), get_op_string (e2->e.expr.op)); @@ -912,8 +911,7 @@ check_precedence (int op, expr_t *e1, expr_t *e2) } else if (e1->type == ex_expr && !e1->paren) { if (((op == '&' || op == '|') && (is_math_op (e1->e.expr.op) || is_compare (e1->e.expr.op))) - || (op == '=' - && (e1->e.expr.op == OR || e1->e.expr.op == AND))) { + || (e1->e.expr.op == OR || e1->e.expr.op == AND)) { notice (e1, "precedence of `%s' and `%s' inverted for " "traditional code", get_op_string (op), get_op_string (e1->e.expr.op)); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 7180dc205..a4cfe4626 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -594,8 +594,6 @@ convert_op (int op) case IFB: return ""; case IFAE: return ""; case IFA: return ""; - case 'm': return ""; - case 'M': return ""; default: return 0; } From 4111d44dcc646c306a6d70b277f27d685a8a8517 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jan 2022 00:26:52 +0900 Subject: [PATCH 2147/3664] [gamecode] Move progs auxiliary headers into a subdirectory Just another step along the road of tidying up the QF include directory (and desirable for generated data). --- include/QF/Makemodule.am | 11 +++++++---- include/QF/progs.h | 4 ++-- include/QF/{ => progs}/pr_comp.h | 0 include/QF/{ => progs}/pr_debug.h | 2 +- include/QF/{ => progs}/pr_obj.h | 4 ++-- include/QF/{ => progs}/pr_type.h | 2 +- include/QF/ruamoko.h | 2 +- libs/gamecode/pr_debug.c | 5 +++-- libs/gamecode/pr_v6p_opcode.c | 3 ++- libs/ruamoko/rua_obj.c | 3 ++- libs/ruamoko/rua_set.c | 3 ++- ruamoko/qwaq/debugger/debug.h | 2 +- ruamoko/qwaq/editor/editbuffer.h | 2 +- ruamoko/qwaq/ui/textcontext.h | 2 +- tools/qfcc/include/dags.h | 2 +- tools/qfcc/include/debug.h | 2 +- tools/qfcc/include/def.h | 4 ++-- tools/qfcc/include/defspace.h | 4 ++-- tools/qfcc/include/diagnostic.h | 2 -- tools/qfcc/include/expr.h | 2 +- tools/qfcc/include/function.h | 4 ++-- tools/qfcc/include/idstuff.h | 2 +- tools/qfcc/include/obj_file.h | 4 ++-- tools/qfcc/include/obj_type.h | 2 +- tools/qfcc/include/opcodes.h | 2 +- tools/qfcc/include/qfcc.h | 2 +- tools/qfcc/include/statements.h | 2 +- tools/qfcc/include/type.h | 2 +- tools/qfcc/source/class.c | 3 ++- tools/qfcc/source/codespace.c | 2 +- tools/qfcc/source/debug.c | 2 +- tools/qfcc/source/dump_lines.c | 3 ++- tools/qfcc/source/dump_modules.c | 3 ++- tools/qfcc/source/method.c | 3 ++- tools/qfcc/source/options.c | 3 ++- tools/qfcc/source/pragma.c | 3 ++- tools/qfcc/source/qfprogs.c | 3 ++- tools/qfcc/source/struct.c | 3 ++- 38 files changed, 61 insertions(+), 48 deletions(-) rename include/QF/{ => progs}/pr_comp.h (100%) rename include/QF/{ => progs}/pr_debug.h (98%) rename include/QF/{ => progs}/pr_obj.h (98%) rename include/QF/{ => progs}/pr_type.h (99%) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 77f56e29b..4f5aa35c9 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -43,10 +43,6 @@ include_qf = \ include/QF/plist.h \ include/QF/plugin.h \ include/QF/pqueue.h \ - include/QF/pr_comp.h \ - include/QF/pr_debug.h \ - include/QF/pr_obj.h \ - include/QF/pr_type.h \ include/QF/progs.h \ include/QF/pvsfile.h \ include/QF/qargs.h \ @@ -135,6 +131,12 @@ include_qf_plugin = \ include/QF/plugin/snd_render.h \ include/QF/plugin/vid_render.h +include_qf_progs = \ + include/QF/pr_comp.h \ + include/QF/pr_debug.h \ + include/QF/pr_obj.h \ + include/QF/pr_type.h + include_qf_scene = \ include/QF/scene/entity.h \ include/QF/scene/hierarchy.h \ @@ -232,6 +234,7 @@ EXTRA_HEADERS += \ $(include_qf_input) \ $(include_qf_math) \ $(include_qf_plugin) \ + $(include_qf_progs) \ $(include_qf_scene) \ $(include_qf_simd) \ $(include_qf_ui) \ diff --git a/include/QF/progs.h b/include/QF/progs.h index c4b2ef070..572528891 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -33,8 +33,8 @@ \image latex vm-mem.eps "VM memory map" */ -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" struct QFile_s; diff --git a/include/QF/pr_comp.h b/include/QF/progs/pr_comp.h similarity index 100% rename from include/QF/pr_comp.h rename to include/QF/progs/pr_comp.h diff --git a/include/QF/pr_debug.h b/include/QF/progs/pr_debug.h similarity index 98% rename from include/QF/pr_debug.h rename to include/QF/progs/pr_debug.h index 94c164fe5..20b65c25c 100644 --- a/include/QF/pr_debug.h +++ b/include/QF/progs/pr_debug.h @@ -32,7 +32,7 @@ #define __QF_pr_debug_h #ifndef __QFCC__ -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" typedef struct pr_compunit_s { pr_uint_t unit_name; diff --git a/include/QF/pr_obj.h b/include/QF/progs/pr_obj.h similarity index 98% rename from include/QF/pr_obj.h rename to include/QF/progs/pr_obj.h index 52f05aa16..ea8f6a052 100644 --- a/include/QF/pr_obj.h +++ b/include/QF/progs/pr_obj.h @@ -31,7 +31,7 @@ #ifndef __QF_pr_obj_h #define __QF_pr_obj_h -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" #define PR_BITS_PER_INT (sizeof (pr_int_t) * 8) @@ -74,7 +74,7 @@ #define PR_CLS_GETNUMBER(cls) (__CLS_INFO (cls) >> (PR_BITS_PER_INT / 2)) #define PR_CLS_SETNUMBER(cls, num) \ (__PR_CLS_INFO (cls) = __PR_CLS_INFO (cls) & (~0U >> (PR_BITS_PER_INT / 2)) \ - | (num) << (PR_BITS_PER_INT / 2)) + | (num) << (PR_BITS_PER_INT / 2)) typedef struct pr_sel_s { pointer_t sel_id; diff --git a/include/QF/pr_type.h b/include/QF/progs/pr_type.h similarity index 99% rename from include/QF/pr_type.h rename to include/QF/progs/pr_type.h index 56915724b..04a3266f6 100644 --- a/include/QF/pr_type.h +++ b/include/QF/progs/pr_type.h @@ -38,7 +38,7 @@ */ ///@{ -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" typedef enum { ty_basic, ///< VM type (float, int, pointer, field, etc) diff --git a/include/QF/ruamoko.h b/include/QF/ruamoko.h index ba1531485..b6f82ff31 100644 --- a/include/QF/ruamoko.h +++ b/include/QF/ruamoko.h @@ -31,7 +31,7 @@ #ifndef __QF_ruamoko_h #define __QF_ruamoko_h -#include "QF/pr_obj.h" +#include "QF/progs/pr_obj.h" struct progs_s; struct cbuf_s; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 98c5d0e59..b77dc940a 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -49,8 +49,6 @@ #include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" -#include "QF/pr_debug.h" -#include "QF/pr_type.h" #include "QF/progs.h" #include "QF/qendian.h" #include "QF/quakefs.h" @@ -58,6 +56,9 @@ #include "QF/sys.h" #include "QF/zone.h" +#include "QF/progs/pr_debug.h" +#include "QF/progs/pr_type.h" + #include "compat.h" typedef struct { diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 421159648..5ded2c764 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -37,10 +37,11 @@ #endif #include "QF/cvar.h" -#include "QF/pr_comp.h" #include "QF/progs.h" #include "QF/sys.h" +#include "QF/progs/pr_comp.h" + #include "compat.h" VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 4bed1de5d..aab7b4c0f 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -48,11 +48,12 @@ #include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" -#include "QF/pr_obj.h" #include "QF/progs.h" #include "QF/ruamoko.h" #include "QF/sys.h" +#include "QF/progs/pr_obj.h" + #include "compat.h" #include "rua_internal.h" diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 4e8b752b5..cc7ce9735 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -40,9 +40,10 @@ #include #include "QF/progs.h" -#include "QF/pr_obj.h" #include "QF/set.h" +#include "QF/progs/pr_obj.h" + #include "rua_internal.h" typedef struct { diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index 93ef60f3b..e9c1cedcf 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -9,7 +9,7 @@ typedef enum { #ifdef __QFCC__ -#include +#include //FIXME finish unsigned in qfcc #ifndef umax diff --git a/ruamoko/qwaq/editor/editbuffer.h b/ruamoko/qwaq/editor/editbuffer.h index fe8a15829..8d42c6038 100644 --- a/ruamoko/qwaq/editor/editbuffer.h +++ b/ruamoko/qwaq/editor/editbuffer.h @@ -77,7 +77,7 @@ typedef struct eb_color_s { @end #else//__QFCC__ -#include "QF/pr_obj.h" +#include "QF/progs/pr_obj.h" typedef struct qwaq_editbuffer_s { pr_id_t isa; diff --git a/ruamoko/qwaq/ui/textcontext.h b/ruamoko/qwaq/ui/textcontext.h index 21f21b5ae..d73a9895c 100644 --- a/ruamoko/qwaq/ui/textcontext.h +++ b/ruamoko/qwaq/ui/textcontext.h @@ -61,7 +61,7 @@ #else -#include "QF/pr_obj.h" +#include "QF/progs/pr_obj.h" typedef struct qwaq_textcontext_s { pr_id_t isa; diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index 6addafcd2..66fbece40 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -35,7 +35,7 @@ */ ///@{ -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" #include "statements.h" diff --git a/tools/qfcc/include/debug.h b/tools/qfcc/include/debug.h index af5f322b7..6e7d6f477 100644 --- a/tools/qfcc/include/debug.h +++ b/tools/qfcc/include/debug.h @@ -31,7 +31,7 @@ #ifndef __debug_h #define __debug_h -#include "QF/pr_debug.h" +#include "QF/progs/pr_debug.h" void line_info (char *text); pr_lineno_t *new_lineno (void); diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 691c5d602..c03b221ef 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -31,8 +31,8 @@ #ifndef __def_h #define __def_h -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" /** \defgroup qfcc_def Def handling \ingroup qfcc diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index e0414f1c9..6e839ce67 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -31,8 +31,8 @@ #ifndef __defspace_h #define __defspace_h -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" /** \defgroup qfcc_defspace Defspace handling \ingroup qfcc diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index 958b44d66..8adec809c 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -31,8 +31,6 @@ #ifndef __diagnostic_h #define __diagnostic_h -#include "QF/pr_comp.h" - /** \defgroup qfcc_diagnostic Diagnostic Messages \ingroup qfcc */ diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 47d382929..6293a8103 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -31,7 +31,7 @@ #ifndef __expr_h #define __expr_h -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" /** \defgroup qfcc_expr Expressions \ingroup qfcc diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 48a82f9e9..986f513eb 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -36,8 +36,8 @@ */ ///@{ -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" #include "def.h" diff --git a/tools/qfcc/include/idstuff.h b/tools/qfcc/include/idstuff.h index 82ef617f8..2eadb691b 100644 --- a/tools/qfcc/include/idstuff.h +++ b/tools/qfcc/include/idstuff.h @@ -31,7 +31,7 @@ #ifndef __idstuff_h #define __idstuff_h -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" //XXX eww :/ void PrecacheSound (const char *, int ch); diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index f49688f0f..8d6c40a22 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -36,8 +36,8 @@ */ ///@{ -#include "QF/pr_comp.h" -#include "QF/pr_debug.h" +#include "QF/progs/pr_comp.h" +#include "QF/progs/pr_debug.h" #include "QF/quakeio.h" /** Identifier string for qfo object files (includes terminating nul) diff --git a/tools/qfcc/include/obj_type.h b/tools/qfcc/include/obj_type.h index a8c546703..c3d9cb6e7 100644 --- a/tools/qfcc/include/obj_type.h +++ b/tools/qfcc/include/obj_type.h @@ -31,7 +31,7 @@ #ifndef __obj_type_h #define __obj_type_h -#include "QF/pr_type.h" +#include "QF/progs/pr_type.h" #include "type.h" diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index 2966235e6..fa100fb6b 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -31,7 +31,7 @@ #ifndef __opcodes_h #define __opcodes_h -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" typedef struct instruction_s instruction_t; diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 9d552ab3e..4ac5e0ddb 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -35,7 +35,7 @@ #include #include "QF/darray.h" -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" /** \defgroup qfcc_general General functions \ingroup qfcc diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index bc15244c6..386dad198 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -30,7 +30,7 @@ #ifndef statement_h #define statement_h -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" typedef enum { op_def, diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index ca079eb01..f985ea826 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -31,7 +31,7 @@ #ifndef __type_h #define __type_h -#include "QF/pr_type.h" +#include "QF/progs/pr_type.h" #include "def.h" diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index dfaf638c8..7858f82fa 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -41,9 +41,10 @@ #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/pr_obj.h" #include "QF/va.h" +#include "QF/progs/pr_obj.h" + #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/codespace.h" diff --git a/tools/qfcc/source/codespace.c b/tools/qfcc/source/codespace.c index b7cd56bcc..5d6aee439 100644 --- a/tools/qfcc/source/codespace.c +++ b/tools/qfcc/source/codespace.c @@ -39,7 +39,7 @@ #endif #include -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" #include "tools/qfcc/include/codespace.h" diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index ec0367fa0..644ee31d9 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -41,7 +41,7 @@ #include #include "QF/alloc.h" -#include "QF/pr_comp.h" +#include "QF/progs/pr_comp.h" #include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/def.h" diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index bfaffdc6e..7ff66fabb 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -41,7 +41,8 @@ #include #include "QF/progs.h" -#include "QF/pr_type.h" + +#include "QF/progs/pr_type.h" #include "tools/qfcc/include/obj_file.h" #include "tools/qfcc/include/qfprogs.h" diff --git a/tools/qfcc/source/dump_modules.c b/tools/qfcc/source/dump_modules.c index 0fcda6e50..3897610b7 100644 --- a/tools/qfcc/source/dump_modules.c +++ b/tools/qfcc/source/dump_modules.c @@ -40,10 +40,11 @@ #include -#include "QF/pr_obj.h" #include "QF/progs.h" #include "QF/va.h" +#include "QF/progs/pr_obj.h" + #include "tools/qfcc/include/qfprogs.h" static void diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 134f1cc64..9c82f89d5 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -41,9 +41,10 @@ #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/pr_obj.h" #include "QF/va.h" +#include "QF/progs/pr_obj.h" + #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/expr.h" diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 2e701c403..7283ba9f7 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -42,9 +42,10 @@ #include -#include "QF/pr_comp.h" #include "QF/va.h" +#include "QF/progs/pr_comp.h" + #include "tools/qfcc/include/cpp.h" #include "tools/qfcc/include/linker.h" #include "tools/qfcc/include/options.h" diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index edabcaaf4..60448815e 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -40,7 +40,8 @@ #include #include "QF/alloc.h" -#include "QF/pr_comp.h" + +#include "QF/progs/pr_comp.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/opcodes.h" diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index eea6aa7e8..19c7ed873 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -56,13 +56,14 @@ #include "QF/cvar.h" #include "QF/hash.h" #include "QF/mathlib.h" -#include "QF/pr_comp.h" #include "QF/progs.h" #include "QF/quakeio.h" #include "QF/sys.h" #include "QF/va.h" #include "QF/zone.h" +#include "QF/progs/pr_comp.h" + #include "tools/qfcc/include/obj_file.h" #include "tools/qfcc/include/obj_type.h" #include "tools/qfcc/include/qfprogs.h" diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 4bd82130c..164a491a2 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -43,10 +43,11 @@ #include #include -#include #include #include +#include + #include "tools/qfcc/include/class.h" #include "tools/qfcc/include/def.h" #include "tools/qfcc/include/defspace.h" From 7d5c692313a70bfd6aa2f51d9ed6069def2d4ee2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jan 2022 01:04:51 +0900 Subject: [PATCH 2148/3664] [gamecode] Generate the new opcodes enum too It turns out I'll be tweaking it more than I expected. --- include/QF/progs/pr_comp.h | 170 +----------------------------------- libs/gamecode/Makemodule.am | 13 ++- libs/gamecode/opcodes.py | 55 +++++++++--- 3 files changed, 54 insertions(+), 184 deletions(-) diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 9e819ad38..9b30bf170 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -427,175 +427,9 @@ typedef enum { #define OP_BREAK 0x8000 typedef enum { - // 0 0000 load from [a,b] -> c - OP_LOAD_E_1, OP_LOAD_E_2, OP_LOAD_E_3, OP_LOAD_E_4, - OP_LOAD_B_1, OP_LOAD_B_2, OP_LOAD_B_3, OP_LOAD_B_4, - OP_LOAD_C_1, OP_LOAD_C_2, OP_LOAD_C_3, OP_LOAD_C_4, - OP_LOAD_D_1, OP_LOAD_D_2, OP_LOAD_D_3, OP_LOAD_D_4, - // 0 0001 store from c -> [a, b] - OP_STORE_A_1, OP_STORE_A_2, OP_STORE_A_3, OP_STORE_A_4, // redundant? - OP_STORE_B_1, OP_STORE_B_2, OP_STORE_B_3, OP_STORE_B_4, - OP_STORE_C_1, OP_STORE_C_2, OP_STORE_C_3, OP_STORE_C_4, - OP_STORE_D_1, OP_STORE_D_2, OP_STORE_D_3, OP_STORE_D_4, - // 0 0010 push from [a,b] to the stack - OP_PUSH_A_1, OP_PUSH_A_2, OP_PUSH_A_3, OP_PUSH_A_4, - OP_PUSH_B_1, OP_PUSH_B_2, OP_PUSH_B_3, OP_PUSH_B_4, - OP_PUSH_C_1, OP_PUSH_C_2, OP_PUSH_C_3, OP_PUSH_C_4, - OP_PUSH_D_1, OP_PUSH_D_2, OP_PUSH_D_3, OP_PUSH_D_4, - // 0 0011 pop from the stack to [a,b] - OP_POP_A_1, OP_POP_A_2, OP_POP_A_3, OP_POP_A_4, - OP_POP_B_1, OP_POP_B_2, OP_POP_B_3, OP_POP_B_4, - OP_POP_C_1, OP_POP_C_2, OP_POP_C_3, OP_POP_C_4, - OP_POP_D_1, OP_POP_D_2, OP_POP_D_3, OP_POP_D_4, - // 0 0100 flow control - OP_IFNOT_A, OP_IFNOT_B, OP_IFNOT_C, OP_IFNOT_D, - OP_IF_A, OP_IF_B, OP_IF_C, OP_IF_D, - OP_JUMP_A, OP_JUMP_B, OP_JUMP_C, OP_JUMP_D, - OP_CALL_A, OP_CALL_B, OP_CALL_C, OP_CALL_D, - // 0 0101 calls - OP_CALL_1, OP_CALL_2, OP_CALL_3, OP_CALL_4, - OP_CALL_5, OP_CALL_6, OP_CALL_7, OP_CALL_8, - OP_RETURN_1, OP_RETURN_2, OP_RETURN_3, OP_RETURN_4, - OP_RETURN_0, OP_WITH, OP_STATE_ft, OP_STATE_ftt, - // 0 0110 flow control 2 - OP_IFA_A, OP_IFA_B, OP_IFA_C, OP_IFA_D, - OP_IFBE_A, OP_IFBE_B, OP_IFBE_C, OP_IFBE_D, - OP_IFB_A, OP_IFB_B, OP_IFB_C, OP_IFB_D, - OP_IFAE_A, OP_IFAE_B, OP_IFAE_C, OP_IFAE_D, - // 0 0111 interpreted vector multiplication - // C complex - // V vector (3d) - // Q quaternion - OP_CDOT_F, OP_VDOT_F, OP_QDOT_F, OP_CROSS_F, - OP_CMUL_F, OP_QVMUL_F, OP_VQMUL_F, OP_QMUL_F, - OP_CDOT_D, OP_VDOT_D, OP_QDOT_D, OP_CROSS_D, - OP_CMUL_D, OP_QVMUL_D, OP_VQMUL_D, OP_QMUL_D, - // comparison - // 0 1000 == - OP_EQ_I_1, OP_EQ_I_2, OP_EQ_I_3, OP_EQ_I_4, - OP_EQ_F_1, OP_EQ_F_2, OP_EQ_F_3, OP_EQ_F_4, - OP_EQ_L_1, OP_EQ_L_2, OP_EQ_L_3, OP_EQ_L_4, - OP_EQ_D_1, OP_EQ_D_2, OP_EQ_D_3, OP_EQ_D_4, - // 0 1001 < - OP_LT_I_1, OP_LT_I_2, OP_LT_I_3, OP_LT_I_4, - OP_LT_F_1, OP_LT_F_2, OP_LT_F_3, OP_LT_F_4, - OP_LT_L_1, OP_LT_L_2, OP_LT_L_3, OP_LT_L_4, - OP_LT_D_1, OP_LT_D_2, OP_LT_D_3, OP_LT_D_4, - // 0 1010 > - OP_GT_I_1, OP_GT_I_2, OP_GT_I_3, OP_GT_I_4, - OP_GT_F_1, OP_GT_F_2, OP_GT_F_3, OP_GT_F_4, - OP_GT_L_1, OP_GT_L_2, OP_GT_L_3, OP_GT_L_4, - OP_GT_D_1, OP_GT_D_2, OP_GT_D_3, OP_GT_D_4, - // 0 1011 - OP_spare_1, OP_spare_2, OP_spare_3, OP_spare_4, - OP_spare_5, OP_spare_6, OP_spare_7, OP_spare_8, - OP_spare_9, OP_spare_10, OP_spare_11, OP_spare_12, - OP_spare_13, OP_spare_14, OP_spare_15, OP_spare_16, - // comparison - // 0 1100 != - OP_NE_I_1, OP_NE_I_2, OP_NE_I_3, OP_NE_I_4, - OP_NE_F_1, OP_NE_F_2, OP_NE_F_3, OP_NE_F_4, - OP_NE_L_1, OP_NE_L_2, OP_NE_L_3, OP_NE_L_4, - OP_NE_D_1, OP_NE_D_2, OP_NE_D_3, OP_NE_D_4, - // 0 1101 >= - OP_GE_I_1, OP_GE_I_2, OP_GE_I_3, OP_GE_I_4, - OP_GE_F_1, OP_GE_F_2, OP_GE_F_3, OP_GE_F_4, - OP_GE_L_1, OP_GE_L_2, OP_GE_L_3, OP_GE_L_4, - OP_GE_D_1, OP_GE_D_2, OP_GE_D_3, OP_GE_D_4, - // 0 1110 <= - OP_LE_I_1, OP_LE_I_2, OP_LE_I_3, OP_LE_I_4, - OP_LE_F_1, OP_LE_F_2, OP_LE_F_3, OP_LE_F_4, - OP_LE_L_1, OP_LE_L_2, OP_LE_L_3, OP_LE_L_4, - OP_LE_D_1, OP_LE_D_2, OP_LE_D_3, OP_LE_D_4, - // 0 1111 - OP_spare_17, OP_spare_18, OP_spare_19, OP_spare_20, - OP_spare_21, OP_spare_22, OP_spare_23, OP_spare_24, - OP_spare_25, OP_spare_26, OP_spare_27, OP_spare_28, - OP_spare_29, OP_spare_30, OP_spare_31, OP_spare_32, - - // 1 0000 c = a * b - OP_MUL_I_1, OP_MUL_I_2, OP_MUL_I_3, OP_MUL_I_4, - OP_MUL_F_1, OP_MUL_F_2, OP_MUL_F_3, OP_MUL_F_4, - OP_MUL_L_1, OP_MUL_L_2, OP_MUL_L_3, OP_MUL_L_4, - OP_MUL_D_1, OP_MUL_D_2, OP_MUL_D_3, OP_MUL_D_4, - // 1 0001 c = a / b - OP_DIV_I_1, OP_DIV_I_2, OP_DIV_I_3, OP_DIV_I_4, - OP_DIV_F_1, OP_DIV_F_2, OP_DIV_F_3, OP_DIV_F_4, - OP_DIV_L_1, OP_DIV_L_2, OP_DIV_L_3, OP_DIV_L_4, - OP_DIV_D_1, OP_DIV_D_2, OP_DIV_D_3, OP_DIV_D_4, - // 1 0010 c = a % b (remainder, C %) - OP_REM_I_1, OP_REM_I_2, OP_REM_I_3, OP_REM_I_4, - OP_REM_F_1, OP_REM_F_2, OP_REM_F_3, OP_REM_F_4, - OP_REM_L_1, OP_REM_L_2, OP_REM_L_3, OP_REM_L_4, - OP_REM_D_1, OP_REM_D_2, OP_REM_D_3, OP_REM_D_4, - // 1 0011 c = a %% b (true modulo, python %) - OP_MOD_I_1, OP_MOD_I_2, OP_MOD_I_3, OP_MOD_I_4, - OP_MOD_F_1, OP_MOD_F_2, OP_MOD_F_3, OP_MOD_F_4, - OP_MOD_L_1, OP_MOD_L_2, OP_MOD_L_3, OP_MOD_L_4, - OP_MOD_D_1, OP_MOD_D_2, OP_MOD_D_3, OP_MOD_D_4, - // 1 0100 c = a + b - OP_ADD_I_1, OP_ADD_I_2, OP_ADD_I_3, OP_ADD_I_4, - OP_ADD_F_1, OP_ADD_F_2, OP_ADD_F_3, OP_ADD_F_4, - OP_ADD_L_1, OP_ADD_L_2, OP_ADD_L_3, OP_ADD_L_4, - OP_ADD_D_1, OP_ADD_D_2, OP_ADD_D_3, OP_ADD_D_4, - // 1 0101 c = a - b - OP_SUB_I_1, OP_SUB_I_2, OP_SUB_I_3, OP_SUB_I_4, - OP_SUB_F_1, OP_SUB_F_2, OP_SUB_F_3, OP_SUB_F_4, - OP_SUB_L_1, OP_SUB_L_2, OP_SUB_L_3, OP_SUB_L_4, - OP_SUB_D_1, OP_SUB_D_2, OP_SUB_D_3, OP_SUB_D_4, - // 1 0110 c = a << b (string ops mixed in) - OP_SHL_I_1, OP_SHL_I_2, OP_SHL_I_3, OP_SHL_I_4, - OP_EQ_S, OP_LT_S, OP_GT_S, OP_ADD_S, - OP_SHL_L_1, OP_SHL_L_2, OP_SHL_L_3, OP_SHL_L_4, - OP_CMP_S, OP_GE_S, OP_LE_S, OP_NOT_S, //OP_CMP_S doubles as NE - // 1 0111 c = a >> b - OP_ASR_I_1, OP_ASR_I_2, OP_ASR_I_3, OP_ASR_I_4, - OP_SHR_u_1, OP_SHR_u_2, OP_SHR_u_3, OP_SHR_u_4, - OP_ASR_L_1, OP_ASR_L_2, OP_ASR_L_3, OP_ASR_L_4, - OP_SHR_U_1, OP_SHR_U_2, OP_SHR_U_3, OP_SHR_U_4, - // 1 1000 c = a (& | ^) b or ~a (bitwise ops) - OP_BITAND_I_1, OP_BITAND_I_2, OP_BITAND_I_3, OP_BITAND_I_4, - OP_BITOR_I_1, OP_BITOR_I_2, OP_BITOR_I_3, OP_BITOR_I_4, - OP_BITXOR_I_1, OP_BITXOR_I_2, OP_BITXOR_I_3, OP_BITXOR_I_4, - OP_BITNOT_I_1, OP_BITNOT_I_2, OP_BITNOT_I_3, OP_BITNOT_I_4, - // 1 1001 < unsigned with swizzle and scale mixed in - OP_LT_u_1, OP_LT_u_2, OP_LT_u_3, OP_LT_u_4, - OP_SWIZZLE_F, OP_SCALE_F_2, OP_SCALE_F_3, OP_SCALE_F_4, - OP_LT_U_1, OP_LT_U_2, OP_LT_U_3, OP_LT_U_4, - OP_SWIZZLE_D, OP_SCALE_D_2, OP_SCALE_D_3, OP_SCALE_D_4, - // 1 1010 > unsigned and conversions - OP_GT_u_1, OP_GT_u_2, OP_GT_u_3, OP_GT_u_4, - OP_CONV_IF, OP_CONV_LD, OP_CONV_uF, OP_CONV_UD, - OP_GT_U_1, OP_GT_U_2, OP_GT_U_3, OP_GT_U_4, - OP_CONV_FI, OP_CONV_DL, OP_CONV_Fu, OP_CONV_DU, - // 1 1011 lea, with, etc - OP_LEA_A, OP_LEA_B, OP_LEA_C, OP_LEA_D, - OP_LEA_E, OP_ANY_2, OP_ANY_3, OP_ANY_4, - OP_PUSHREGS, OP_ALL_2, OP_ALL_3, OP_ALL_4, - OP_POPREGS, OP_NONE_2, OP_NONE_3, OP_NONE_4, - // 1 1100 c = a (&& || ^^) b or !a (logical ops (no short circuit)) - OP_AND_I_1, OP_AND_I_2, OP_AND_I_3, OP_AND_I_4, - OP_OR_I_1, OP_OR_I_2, OP_OR_I_3, OP_OR_I_4, - OP_XOR_I_1, OP_XOR_I_2, OP_XOR_I_3, OP_XOR_I_4, - OP_NOT_I_1, OP_NOT_I_2, OP_NOT_I_3, OP_NOT_I_4, - // 1 1101 >= unsigned with q v4 mul and moves mixed in - OP_GE_u_1, OP_GE_u_2, OP_GE_u_3, OP_GE_u_4, - OP_QV4MUL_F, OP_MOVE_I, OP_MOVE_P, OP_MOVE_PI, - OP_GE_U_1, OP_GE_U_2, OP_GE_U_3, OP_GE_U_4, - OP_QV4MUL_D, OP_MEMSET_I, OP_MEMSET_P, OP_MEMSET_PI, - // 1 1110 <= unsigned with v4 q mul and conversion mixed in - OP_LE_u_1, OP_LE_u_2, OP_LE_u_3, OP_LE_u_4, - OP_V4QMUL_F, OP_CONV_IL_1, OP_CONV_uU_1, OP_CONV_FD_1, - OP_LE_U_1, OP_LE_U_2, OP_LE_U_3, OP_LE_U_4, - OP_V4QMUL_D, OP_CONV_LI_1, OP_CONV_Uu_1, OP_CONV_DF_1, - // 1 1111 - OP_spare_33, OP_spare_34, OP_spare_35, OP_spare_36, - OP_spare_37, OP_spare_38, OP_spare_39, OP_spare_40, - OP_spare_41, OP_spare_42, OP_spare_43, OP_spare_44, - OP_spare_45, OP_spare_46, OP_spare_47, OP_spare_48, - - +#include "QF/progs/pr_opcode.hinc" } pr_opcode_e; + #define OP_A_SHIFT (9) #define OP_B_SHIFT (11) #define OP_C_SHIFT (13) diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index 620edc7ee..e3c9b5441 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -25,10 +25,19 @@ noinst_PYTHON += $(opcodes_py) opcodes_py = $(srcdir)/libs/gamecode/opcodes.py pr_opcode_cinc = $(top_builddir)/libs/gamecode/pr_opcode.cinc +pr_opcode_hinc = $(top_builddir)/include/QF/progs/pr_opcode.hinc pr_opcode_src = \ - ${pr_opcode_cinc} + ${pr_opcode_cinc} \ + ${pr_opcode_hinc} libs/gamecode/pr_opcode.lo: libs/gamecode/pr_opcode.c ${pr_opcode_src} +BUILT_SOURCES += $(pr_opcode_cinc) $(pr_opcode_hinc) + $(pr_opcode_cinc): $(opcodes_py) - $(V_PY)$(PYTHON) $(opcodes_py) > $(pr_opcode_cinc).t && \ + $(V_PY)$(PYTHON) $(opcodes_py) table > $(pr_opcode_cinc).t && \ $(am__mv) $(pr_opcode_cinc).t $(pr_opcode_cinc) + +$(pr_opcode_hinc): $(opcodes_py) + $(V_PY) mkdir -p `dirname $(pr_opcode_hinc)` &&\ + $(PYTHON) $(opcodes_py) enum > $(pr_opcode_hinc).t && \ + $(am__mv) $(pr_opcode_hinc).t $(pr_opcode_hinc) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index b38763156..0c18dafe6 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -36,6 +36,8 @@ n 1111 nnnn 0 1011 nnnn """ +import copy + load_fmt = [ "%Ga.%Gb(%Ea), %gc", "*%Ga, %gc", @@ -184,6 +186,15 @@ convert_formats = { ], }, } +convert2_formats = copy.deepcopy (convert_formats) +convert2_formats["args"]["op_conv"] = [None, "IL", "uU", "FD", + None, "LI", "Uu", "DF"] +convert2_formats["args"]["cnv_types"] = [ + [None, None], + ["ev_integer", "ev_long"], + ["ev_uinteger", "ev_ulong"], + ["ev_float", "ev_double"], +] lea_formats = { "opcode": "OP_LEA_{op_mode[mm]}", "mnemonic": "lea", @@ -505,7 +516,7 @@ group_map = { "compare": compare_formats, "compare2": compare2_formats, "convert": convert_formats, - "convert2": convert_formats, + "convert2": convert2_formats, "lea": lea_formats, "lea_e": lea_e_formats, "load": load_formats, @@ -598,6 +609,12 @@ def process_opcode(opcode, group): inst["wd"] = "{%s}" % eval(f'''f"{gm['widths']}"''', params) inst["ty"] = "{%s}" % eval(f'''f"{gm['types']}"''', params) +import sys + +if len (sys.argv) < 2 or sys.argv[1] not in ["enum", "table"]: + sys.stderr.write ("specify output type: enum or table\n") + sys.exit(1) + lines = bitmap_txt.split('\n') for l in lines: if not l: @@ -612,16 +629,26 @@ for l in lines: for i, group in enumerate(opcodes): if group is not None: process_opcode (i, group) -N = 8 -W = 9 -#for i in range(len(opcodes)//N): -# print("%03x" % (i << 3), " ".join(map(lambda op: "%-*.*s" % (W, W, op and op["op"] or None), opcodes[i*N:i*N+N]))) -for i, group in enumerate(opcodes): - if group is not None: - print(eval('f"[{op}] = {{\\n' - '\\t.opname = {on},\\n' - '\\t.mnemonic = {mn},\\n' - '\\t.widths = {wd},\\n' - '\\t.types = {ty},\\n' - '\\t.fmt = {fmt},\\n' - '}},"', group)) +if sys.argv[1] == "enum": + N = 4 + W = 15 + for i in range(len(opcodes)//N): + row = opcodes[i * N:i * N + N] + #row = map(lambda op: (op and op["op"] or f"OP_spare_{i}"), row) + row = [(op and op["op"] or f"OP_spare_{i*N+x}") + for x, op in enumerate(row)] + row = map(lambda op: f"%-{W}.{W}s" % (op + ','), row) + if sys.argv[2:3] == ["debug"]: + print("%03x" % (i << 3), " ".join(row)) + else: + print(" ".join(row)) +elif sys.argv[1] == "table": + for i, group in enumerate(opcodes): + if group is not None: + print(eval('f"[{op}] = {{\\n' + '\\t.opname = {on},\\n' + '\\t.mnemonic = {mn},\\n' + '\\t.widths = {wd},\\n' + '\\t.types = {ty},\\n' + '\\t.fmt = {fmt},\\n' + '}},"', group)) From 86e81ba250ead6666085bb0b6e88f4d8ff2838d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jan 2022 01:07:23 +0900 Subject: [PATCH 2149/3664] [gamecode] Rearrange the branch instructions Now they're in a much more consistent arrangement, in particular with the comparison opcodes if the conditional branch instructions are considered to be fast comparisons with zero (ifnot -> ifeq, if -> ifne, etc). Unconditional jump and call fill in the gaps. The goal was to get them all in an arrangement that would work as a small enum for qfcc: it can use the enum directly for the ruamoko IS, and a small map array for v6p (except for call). --- libs/gamecode/opcodes.py | 52 ++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 0c18dafe6..9d71b94e5 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -3,13 +3,12 @@ bitmap_txt = """ 0 0001 mmss store 0 0010 mmss push 0 0011 mmss pop -0 0100 ccmm branch -0 0101 0nnn rcall 1-8 (0 0100 11mm with 0 params for [r]call0) -0 0101 10ss return -0 0101 1100 returnv -0 0101 1101 with (reg encoded in st->c) -0 0101 111t state -0 0110 ccmm branch2 +0 010c ccmm branch +0 0110 0nnn rcall 1-8 (0 0100 11mm with 0 params for [r]call0) +0 0110 10ss return +0 0110 1100 returnv +0 0110 1101 with (reg encoded in st->c) +0 0110 111t state 0 0111 tooo vecops 0 1ccc ttss compare 1 0ooo ttss mathops @@ -107,41 +106,27 @@ boolops_formats = { }, } branch_formats = { - "opcode": "OP_{op_cond[cc].upper()}_{op_mode[mm]}", - "mnemonic": "{op_cond[cc]}", - "opname": "{op_cond[cc]}", - "format": "{cond_fmt[cc]}{branch_fmt[mm]}", - "widths": "{cond_widths[cc]}", + "opcode": "OP_{op_cond[ccc].upper()}_{op_mode[mm]}", + "mnemonic": "{op_cond[ccc]}", + "opname": "{op_cond[ccc]}", + "format": "{cond_fmt[ccc]}{branch_fmt[mm]}", + "widths": "{cond_widths[ccc]}", "types": "ev_void, ev_void, ev_integer", "args": { "op_mode": "ABCD", - "op_cond": ["ifnot", "if", "jump", "call"], - "branch_fmt": branch_fmt, - "cond_fmt": ["%Gc ", "%Gc ", "", ""], - "cond_widths": [ - "0, 0, 1", - "0, 0, 1", - "0, 0, 0", - "0, 0, 0", - ], - }, -} -branch2_formats = { - "opcode": "OP_{op_cond[cc].upper()}_{op_mode[mm]}", - "mnemonic": "{op_cond[cc]}", - "opname": "{op_cond[cc]}", - "format": "%Gc {branch_fmt[mm]}", - "widths": "{cond_widths[cc]}", - "types": "ev_void, ev_void, ev_integer", - "args": { - "op_mode": "ABCD", - "op_cond": ["ifa", "ifbe", "ifb", "ifae"], + "op_cond": ["ifnot", "ifb", "ifa", "jump", + "if", "ifae", "ifbe", "call"], "branch_fmt": branch_fmt, + "cond_fmt": ["%Gc ", "%Gc ", "%Gc ", "", "%Gc ", "%Gc ", "%Gc ", ""], "cond_widths": [ "0, 0, 1", "0, 0, 1", "0, 0, 1", + "0, 0, 0", "0, 0, 1", + "0, 0, 1", + "0, 0, 1", + "0, 0, 0", ], }, } @@ -512,7 +497,6 @@ group_map = { "bitops": bitops_formats, "boolops": boolops_formats, "branch": branch_formats, - "branch2": branch2_formats, "compare": compare_formats, "compare2": compare2_formats, "convert": convert_formats, From 09002c17e65f739115fdfc40179a09c20d26b119 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jan 2022 13:56:09 +0900 Subject: [PATCH 2150/3664] [gamecode] Add an enum for the different branch types While it doesn't cover the addressing modes, it does match the bit pattern used in the Ruamoko instruction set. It will make selecting branch instructions easier (especially for Ruamoko). --- include/QF/progs/pr_comp.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 9b30bf170..8ce204613 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -430,6 +430,20 @@ typedef enum { #include "QF/progs/pr_opcode.hinc" } pr_opcode_e; +// Used for both branch and comparison, with jump and call being ignored for +// comparison. For branches, the test is against zero, while for comparison, +// it's a cmp b (where cmp takes the place of "branch" in the enum names). +typedef enum { + pr_branch_eq, + pr_branch_lt, + pr_branch_gt, + pr_branch_jump, + pr_branch_ne, + pr_branch_ge, + pr_branch_le, + pr_branch_call, +} pr_branch_e; + #define OP_A_SHIFT (9) #define OP_B_SHIFT (11) #define OP_C_SHIFT (13) From 563de2020879bee717316350e41317571fe08e59 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jan 2022 14:02:16 +0900 Subject: [PATCH 2151/3664] [qfcc] Give branch expressions their own type This includes calls and unconditional jumps, relative and through a table. The parameters are all lumped into the one object, with some being unused by the different types (eg, args and ret_type used only by call expressions). Just having nice names for the parameters (instead of e1 and e2) makes it nice, even with all the sub-types lumped together. No mysterious type aliasing bugs this time ;) --- tools/qfcc/include/expr.h | 12 +++ tools/qfcc/include/expr_names.h | 3 +- tools/qfcc/source/constfold.c | 25 +----- tools/qfcc/source/dot_expr.c | 153 +++++++++++++++++++------------- tools/qfcc/source/expr.c | 94 +++++++++++++++++--- tools/qfcc/source/expr_assign.c | 1 + tools/qfcc/source/expr_bool.c | 11 +-- tools/qfcc/source/qc-parse.y | 4 +- tools/qfcc/source/qp-parse.y | 2 +- tools/qfcc/source/statements.c | 144 +++++++++++++----------------- tools/qfcc/source/switch.c | 12 +-- 11 files changed, 263 insertions(+), 198 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 6293a8103..ff8c25cf7 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -224,6 +224,15 @@ typedef struct { struct expr_s *src; ///< source of assignment } ex_assign_t; +typedef struct { + pr_branch_e type; ///< type of branch + struct expr_s *target; ///< destination of branch + struct expr_s *index; ///< index for indirect branches + struct expr_s *test; ///< test expression (null for jump/call) + struct expr_s *args; ///< only for call + struct type_s *ret_type; ///< void for non-call +} ex_branch_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -253,6 +262,7 @@ typedef struct expr_s { ex_alias_t alias; ///< alias expr params ex_address_t address; ///< alias expr params ex_assign_t assign; ///< assignment expr params + ex_branch_t branch; ///< branch expr params struct type_s *nil; ///< type for nil if known } e; } expr_t; @@ -718,6 +728,8 @@ expr_t *function_expr (expr_t *e1, expr_t *e2); struct function_s; expr_t *branch_expr (int op, expr_t *test, expr_t *label); expr_t *goto_expr (expr_t *label); +expr_t *jump_table_expr (expr_t *table, expr_t *index); +expr_t *call_expr (expr_t *func, expr_t *args, struct type_s *ret_type); expr_t *return_expr (struct function_s *f, expr_t *e); expr_t *conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2); expr_t *incop_expr (int op, expr_t *e, int postop); diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index 25ebfe07c..fab5c0fdb 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -56,6 +56,7 @@ EX_EXPR(compound) ///< compound initializer EX_EXPR(memset) ///< memset needs three params... EX_EXPR(alias) ///< view expression as different type (::ex_alias_t) EX_EXPR(address) ///< address of an lvalue expression (::ex_address_t) -EX_EXPR(assign) ///< assignment of src expr to dst expr +EX_EXPR(assign) ///< assignment of src expr to dst expr (::ex_assing_t) +EX_EXPR(branch) ///< branch expression (::ex_branch_t) ///@} diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 520693b01..92ae4c330 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -575,10 +575,6 @@ do_op_field (int op, expr_t *e, expr_t *e1, expr_t *e2) static expr_t * do_op_func (int op, expr_t *e, expr_t *e1, expr_t *e2) { - if (op == 'c') { - e->e.expr.type = get_type (e1)->t.func.type; - return e; - } if (op == EQ || op == NE) { if (options.code.progsversion > PROG_ID_VERSION) e->e.expr.type = &type_integer; @@ -593,7 +589,7 @@ static expr_t * do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) { type_t *type; - static int valid[] = {'-', 'M', '.', EQ, NE, 0}; + static int valid[] = {'-', '.', EQ, NE, 0}; if (is_integral (type = get_type (e2)) && (op == '-' || op == '+')) { // pointer arithmetic @@ -623,8 +619,7 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) else e->e.expr.type = &type_float; } - if (op != '.' && op != 'M' - && extract_type (e1) != extract_type (e2)) + if (op != '.' && extract_type (e1) != extract_type (e2)) return type_mismatch (e1, e2, op); if (op == '.' && is_uinteger(get_type (e2))) e->e.expr.e2 = cf_cast_expr (&type_integer, e2); @@ -993,14 +988,7 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) static expr_t * do_op_struct (int op, expr_t *e, expr_t *e1, expr_t *e2) { - type_t *type; - - if (op != 'm') - return error (e1, "invalid operator for struct"); - if ((type = get_type (e1)) != get_type (e2)) - return type_mismatch (e1, e2, op); - e->e.expr.type = type; - return e; + return error (e1, "invalid operator for struct"); } static expr_t * @@ -1036,8 +1024,6 @@ do_op_invalid (int op, expr_t *e, expr_t *e1, expr_t *e2) type_t *t1 = get_type (e1); type_t *t2 = get_type (e2); - if (e->e.expr.op == 'm') - return e; // assume the rest of the compiler got it right if (is_scalar (t1) && is_scalar (t2)) { // one or both expressions are an enum, and the other is one of // int, float or short. Treat the enum as the other type, or as @@ -1694,7 +1680,7 @@ fold_constants (expr_t *e) return e; } op = e->e.expr.op; - if (op == 'g' || op == 'r') + if (op == 'r') return e; t1 = extract_type (e1); if (t1 >= ev_type_count || !do_unary_op[t1]) { @@ -1710,9 +1696,6 @@ fold_constants (expr_t *e) } op = e->e.expr.op; - if (op == 'i' || op == 'n' || op == 'c') { - return e; - } t1 = extract_type (e1); t2 = extract_type (e2); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 95c6807f1..a29920881 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -89,18 +89,8 @@ get_op_string (int op) case SHL: return "<<"; case SHR: return ">>"; case '.': return "."; - case 'i': return ""; - case 'n': return ""; - case IFBE: return ""; - case IFB: return ""; - case IFAE: return ""; - case IFA: return ""; - case 'g': return ""; case 'r': return ""; - case 'c': return ""; case 'C': return ""; - case 'M': return ""; - case 'm': return ""; default: return "unknown"; } @@ -255,62 +245,17 @@ print_block (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) } } -static void -print_call (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) -{ - int indent = level * 2 + 2; - expr_t *p; - int i, count; - expr_t **args; - - for (count = 0, p = e->e.expr.e2; p; p = p->next) - count++; - args = alloca (count * sizeof (expr_t *)); - for (i = 0, p = e->e.expr.e2; p; p = p->next, i++) - args[count - 1 - i] = p; - - _print_expr (dstr, e->e.expr.e1, level, id, next); - dasprintf (dstr, "%*se_%p [label=\"call", indent, "", e); - for (i = 0; i < count; i++) - dasprintf (dstr, "|p%d", i, i); - dasprintf (dstr, "\",shape=record];\n"); - for (i = 0; i < count; i++) { - _print_expr (dstr, args[i], level + 1, id, next); - dasprintf (dstr, "%*se_%p:p%d -> e_%p;\n", indent + 2, "", e, i, - args[i]); - } - dasprintf (dstr, "%*se_%p:c -> e_%p;\n", indent, "", e, e->e.expr.e1); -} - static void print_subexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - if (e->e.expr.op == 'c') { - print_call (dstr, e, level, id, next); - return; - } else if (e->e.expr.op == 'i' || e->e.expr.op == 'n' - || e->e.expr.op == IFB || e->e.expr.op ==IFBE - || e->e.expr.op == IFA || e->e.expr.op ==IFAE) { - _print_expr (dstr, e->e.expr.e1, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"t\"];\n", indent, "", e, - e->e.expr.e1); - dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"g\"];\n", indent, "", e, - e->e.expr.e2); - if (e->next) - next = e->next; - if (next) - dasprintf (dstr, "%*se_%p -> e_%p [constraint=true," - "style=dashed];\n", indent, "", e, next); - } else { - _print_expr (dstr, e->e.expr.e1, level, id, next); - _print_expr (dstr, e->e.expr.e2, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"l\"];\n", indent, "", e, - e->e.expr.e1); - dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"r\"];\n", indent, "", e, - e->e.expr.e2); - } + _print_expr (dstr, e->e.expr.e1, level, id, next); + _print_expr (dstr, e->e.expr.e2, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"l\"];\n", indent, "", e, + e->e.expr.e1); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"r\"];\n", indent, "", e, + e->e.expr.e2); dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, get_op_string (e->e.expr.op), e->line); } @@ -373,13 +318,94 @@ print_assign (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) "=", e->line); } +static void +print_conditional (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + static const char *condition[] = { + "ifz", "ifb", "ifa", 0, "ifnz", "ifnb", "ifna", 0 + }; + + _print_expr (dstr, e->e.branch.test, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"t\"];\n", indent, "", e, + e->e.branch.test); + dasprintf (dstr, "%*se_%p -> \"e_%p\" [label=\"g\"];\n", indent, "", e, + e->e.branch.target); + if (e->next) { + next = e->next; + } + if (next) { + dasprintf (dstr, "%*se_%p -> e_%p [constraint=true," + "style=dashed];\n", indent, "", e, next); + } + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + condition [e->e.branch.type], e->line); +} + +static void +print_jump (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.branch.target, level, id, next); + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + "jump", e->line); +} + +static void +print_call (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + expr_t *p; + int i, count; + expr_t **args; + + for (count = 0, p = e->e.branch.args; p; p = p->next) + count++; + args = alloca (count * sizeof (expr_t *)); + for (i = 0, p = e->e.branch.args; p; p = p->next, i++) + args[count - 1 - i] = p; + + _print_expr (dstr, e->e.branch.target, level, id, next); + dasprintf (dstr, "%*se_%p [label=\"call", indent, "", e); + for (i = 0; i < count; i++) + dasprintf (dstr, "|p%d", i, i); + dasprintf (dstr, "\",shape=record];\n"); + for (i = 0; i < count; i++) { + _print_expr (dstr, args[i], level + 1, id, next); + dasprintf (dstr, "%*se_%p:p%d -> e_%p;\n", indent + 2, "", e, i, + args[i]); + } + dasprintf (dstr, "%*se_%p:c -> e_%p;\n", indent, "", e, + e->e.branch.target); +} + +static void +print_branch (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + switch (e->e.branch.type) { + case pr_branch_eq: + case pr_branch_lt: + case pr_branch_gt: + case pr_branch_ne: + case pr_branch_ge: + case pr_branch_le: + print_conditional (dstr, e, level, id, next); + break; + case pr_branch_jump: + print_jump (dstr, e, level, id, next); + break; + case pr_branch_call: + print_call (dstr, e, level, id, next); + break; + } +} + static void print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - if (e->e.expr.op != 'g' && e->e.expr.e1) - _print_expr (dstr, e->e.expr.e1, level, id, next); if (e->e.expr.op != 'r' || e->e.expr.e1) dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, e->e.expr.e1); @@ -618,6 +644,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_alias] = print_alias, [ex_address] = print_address, [ex_assign] = print_assign, + [ex_branch] = print_branch, }; int indent = level * 2 + 2; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 6749422c0..06f4ba944 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -215,8 +215,10 @@ get_type (expr_t *e) const type_t *type = 0; convert_name (e); switch (e->type) { + case ex_branch: case ex_labelref: - return &type_void; + type = e->e.branch.ret_type; + break; case ex_memset: return e->e.memset.type; case ex_label: @@ -495,6 +497,13 @@ copy_expr (expr_t *e) n->e.assign.dst = copy_expr (e->e.assign.dst); n->e.assign.src = copy_expr (e->e.assign.src); return n; + case ex_branch: + n = new_expr (); + *n = *e; + n->e.branch.target = copy_expr (e->e.branch.target); + n->e.branch.test = copy_expr (e->e.branch.test); + n->e.branch.args = copy_expr (e->e.branch.args); + return n; case ex_count: break; } @@ -1591,14 +1600,10 @@ has_function_call (expr_t *e) return 1; return 0; case ex_expr: - if (e->e.expr.op == 'c') - return 1; return (has_function_call (e->e.expr.e1) || has_function_call (e->e.expr.e2)); case ex_uexpr: - if (e->e.expr.op != 'g') - return has_function_call (e->e.expr.e1); - return 0; + return has_function_call (e->e.expr.e1); case ex_alias: return has_function_call (e->e.alias.expr); case ex_address: @@ -1606,6 +1611,14 @@ has_function_call (expr_t *e) case ex_assign: return (has_function_call (e->e.assign.dst) || has_function_call (e->e.assign.src)); + case ex_branch: + if (e->e.branch.type == pr_branch_call) { + return 1; + } + if (e->e.branch.type == pr_branch_jump) { + return 0; + } + return has_function_call (e->e.branch.test); case ex_error: case ex_state: case ex_label: @@ -1724,6 +1737,8 @@ unary_expr (int op, expr_t *e) n->e.expr.type = get_type (e); return n; } + case ex_branch: + return error (e, "invalid type for unary -"); case ex_expr: case ex_bool: case ex_temp: @@ -1826,6 +1841,7 @@ unary_expr (int op, expr_t *e) n->e.expr.type = &type_float; return n; } + case ex_branch: case ex_nil: return error (e, "invalid type for unary !"); case ex_count: @@ -1887,6 +1903,8 @@ unary_expr (int op, expr_t *e) if (!e->e.block.result) return error (e, "invalid type for unary ~"); goto bitnot_expr; + case ex_branch: + return error (e, "invalid type for unary ~"); case ex_expr: case ex_bool: case ex_def: @@ -2072,8 +2090,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) e = expr_file_line (e, arg_exprs[arg_expr_count - 1][0]); append_expr (call, e); } - e = expr_file_line (new_binary_expr ('c', fexpr, args), fexpr); - e->e.expr.type = ftype->t.func.type; + e = expr_file_line (call_expr (fexpr, args, ftype->t.func.type), fexpr); append_expr (call, e); if (!is_void(ftype->t.func.type)) { call->e.block.result = new_ret_expr (ftype->t.func.type); @@ -2118,21 +2135,70 @@ function_expr (expr_t *fexpr, expr_t *params) expr_t * branch_expr (int op, expr_t *test, expr_t *label) { - if (label && label->type != ex_label) + // need to translated op due to precedence rules dictating the layout + // of the token ids + static pr_branch_e branch_type [] = { + pr_branch_eq, + pr_branch_ne, + pr_branch_lt, + pr_branch_gt, + pr_branch_le, + pr_branch_ge, + }; + if (op < EQ || op > LE) { + internal_error (label, "invalid op: %d", op); + } + if (label && label->type != ex_label) { internal_error (label, "not a label"); - if (label) + } + if (label) { label->e.label.used++; - return new_binary_expr (op, test, label); + } + expr_t *branch = new_expr (); + branch->type = ex_branch; + branch->e.branch.type = branch_type[op - EQ]; + branch->e.branch.target = label; + branch->e.branch.test = test; + return branch; } expr_t * goto_expr (expr_t *label) { - if (label && label->type != ex_label) + if (label && label->type != ex_label) { internal_error (label, "not a label"); - if (label) + } + if (label) { label->e.label.used++; - return new_unary_expr ('g', label); + } + expr_t *branch = new_expr (); + branch->type = ex_branch; + branch->e.branch.type = pr_branch_jump; + branch->e.branch.target = label; + return branch; +} + +expr_t * +jump_table_expr (expr_t *table, expr_t *index) +{ + expr_t *branch = new_expr (); + branch->type = ex_branch; + branch->e.branch.type = pr_branch_jump; + branch->e.branch.target = table;//FIXME separate? all branch types can + branch->e.branch.index = index; + return branch; +} + +expr_t * +call_expr (expr_t *func, expr_t *args, type_t *ret_type) +{ + expr_t *branch = new_expr (); + branch->type = ex_branch; + branch->e.branch.type = pr_branch_call; + branch->e.branch.target = func; + branch->e.branch.args = args; + branch->e.branch.ret_type = ret_type; + return branch; } expr_t * diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 24ce2e349..ed23270c1 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -124,6 +124,7 @@ is_lvalue (const expr_t *expr) return 1; } break; + case ex_branch: case ex_memset: case ex_compound: case ex_state: diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 3861951db..9f7b0e1e4 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -165,12 +165,9 @@ backpatch (ex_list_t *list, expr_t *label) for (i = 0; i < list->size; i++) { e = list->e[i]; - if (e->type == ex_uexpr && e->e.expr.op == 'g') - e->e.expr.e1 = label; - else if (e->type == ex_expr && (e->e.expr.op == 'i' - || e->e.expr.op == 'n')) - e->e.expr.e2 = label; - else { + if (e->type == ex_branch && e->e.branch.type < pr_branch_call) { + e->e.branch.target = label; + } else { internal_error (e, 0); } label->e.label.used++; @@ -299,7 +296,7 @@ convert_bool (expr_t *e, int block) e = new_bool_expr (0, make_list (b), b); } else { b = new_block_expr (); - append_expr (b, branch_expr ('i', e, 0)); + append_expr (b, branch_expr (NE, e, 0)); append_expr (b, goto_expr (0)); e = new_bool_expr (make_list (b->e.block.head), make_list (b->e.block.head->next), b); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index f75621a17..9c56a5790 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -132,7 +132,7 @@ int yylex (void); %left '^' %left '&' %left EQ NE -%left LE GE LT GT +%left LT GT GE LE // end of tokens common between qc and qp %left SHL SHR @@ -146,7 +146,7 @@ int yylex (void); %token VALUE STRING %token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS -%token NIL IFBE IFB IFAE IFA GOTO SWITCH CASE DEFAULT ENUM +%token NIL GOTO SWITCH CASE DEFAULT ENUM %token ARGS TYPEDEF EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT %token STRUCT %token TYPE diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 28f54bb87..59ddaceec 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -113,7 +113,7 @@ int yylex (void); %left '^' %left '&' %left EQ NE -%left LE GE LT GT +%left LT GT GE LE // end of tokens common between qc and qp %left RELOP diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index a4cfe4626..76caa4eaf 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -588,12 +588,6 @@ convert_op (int op) case SHL: return "<<"; case SHR: return ">>"; case '.': return "."; - case 'i': return ""; - case 'n': return ""; - case IFBE: return ""; - case IFB: return ""; - case IFAE: return ""; - case IFA: return ""; default: return 0; } @@ -709,33 +703,6 @@ static sblock_t *statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op); static sblock_t *statement_slist (sblock_t *sblock, expr_t *e); -static sblock_t * -statement_branch (sblock_t *sblock, expr_t *e) -{ - statement_t *s = 0; - const char *opcode; - - if (e->type == ex_uexpr && e->e.expr.op == 'g') { - s = new_statement (st_flow, "", e); - s->opa = label_operand (e->e.expr.e1); - } else { - if (e->e.expr.op == 'g') { - s = new_statement (st_flow, "", e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); - } else { - opcode = convert_op (e->e.expr.op); - s = new_statement (st_flow, opcode, e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - s->opb = label_operand (e->e.expr.e2); - } - } - - sblock_add_statement (sblock, s); - sblock->next = new_sblock (); - return sblock->next; -} - static sblock_t * expr_address (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1047,12 +1014,11 @@ vector_call (sblock_t *sblock, expr_t *earg, expr_t *param, int ind, return sblock; } - static sblock_t * expr_call (sblock_t *sblock, expr_t *call, operand_t **op) { - expr_t *func = call->e.expr.e1; - expr_t *args = call->e.expr.e2; + expr_t *func = call->e.branch.target; + expr_t *args = call->e.branch.args; expr_t *a; expr_t *param; operand_t *arguments[2] = {0, 0}; @@ -1113,6 +1079,46 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) return sblock->next; } +static sblock_t * +statement_branch (sblock_t *sblock, expr_t *e) +{ + static const char *opcodes[] = { + "", + "", + "", + 0, // special handling + "", + "", + "", + 0, // not used here + }; + statement_t *s = 0; + const char *opcode; + + if (e->e.branch.type == pr_branch_call) { + return expr_call (sblock, e, 0); + } + if (e->e.branch.type == pr_branch_jump) { + if (e->e.branch.index) { + s = new_statement (st_flow, "", e); + sblock = statement_subexpr (sblock, e->e.branch.target, &s->opa); + sblock = statement_subexpr (sblock, e->e.branch.index, &s->opb); + } else { + s = new_statement (st_flow, "", e); + s->opa = label_operand (e->e.branch.target); + } + } else { + opcode = opcodes [e->e.branch.type]; + s = new_statement (st_flow, opcode, e); + sblock = statement_subexpr (sblock, e->e.branch.test, &s->opa); + s->opb = label_operand (e->e.branch.target); + } + + sblock_add_statement (sblock, s); + sblock->next = new_sblock (); + return sblock->next; +} + static statement_t * lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) { @@ -1261,9 +1267,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) statement_t *s; switch (e->e.expr.op) { - case 'c': - sblock = expr_call (sblock, e, op); - break; case 'm': case 'M': sblock = expr_move (sblock, e, op); @@ -1573,27 +1576,20 @@ build_bool_block (expr_t *block, expr_t *e) e->next = 0; append_expr (block, e); return; + case ex_branch: + e->next = 0; + append_expr (block, e); + return; case ex_expr: if (e->e.expr.op == OR || e->e.expr.op == AND) { build_bool_block (block, e->e.expr.e1); build_bool_block (block, e->e.expr.e2); - } else if (e->e.expr.op == 'i') { - e->next = 0; - append_expr (block, e); - } else if (e->e.expr.op == 'n') { - e->next = 0; - append_expr (block, e); } else { e->next = 0; append_expr (block, e); } return; case ex_uexpr: - if (e->e.expr.op == 'g') { - e->next = 0; - append_expr (block, e); - return; - } break; case ex_block: if (!e->e.block.result) { @@ -1614,19 +1610,20 @@ build_bool_block (expr_t *block, expr_t *e) static int is_goto_expr (expr_t *e) { - return e && e->type == ex_uexpr && e->e.expr.op == 'g'; + return e && e->type == ex_branch && e->e.branch.type == pr_branch_jump + && !e->e.branch.index; } static int is_if_expr (expr_t *e) { - return e && e->type == ex_expr && e->e.expr.op == 'i'; + return e && e->type == ex_branch && e->e.branch.type == pr_branch_ne; } static int is_ifnot_expr (expr_t *e) { - return e && e->type == ex_expr && e->e.expr.op == 'n'; + return e && e->type == ex_branch && e->e.branch.type == pr_branch_eq; } static sblock_t * @@ -1641,33 +1638,33 @@ statement_bool (sblock_t *sblock, expr_t *e) s = &block->e.block.head; while (*s) { if (is_if_expr (*s) && is_goto_expr ((*s)->next)) { - l = (*s)->e.expr.e2; + l = (*s)->e.branch.target; for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) { if (e == l) { l->e.label.used--; e = *s; - e->e.expr.op = 'n'; - e->e.expr.e2 = e->next->e.expr.e1; + e->e.branch.type = pr_branch_eq; + e->e.branch.target = e->next->e.branch.target; e->next = e->next->next; break; } } s = &(*s)->next; } else if (is_ifnot_expr (*s) && is_goto_expr ((*s)->next)) { - l = (*s)->e.expr.e2; + l = (*s)->e.branch.target; for (e = (*s)->next->next; e && e->type == ex_label; e = e->next) { if (e == l) { l->e.label.used--; e = *s; - e->e.expr.op = 'i'; - e->e.expr.e2 = e->next->e.expr.e1; + e->e.branch.type = pr_branch_ne; + e->e.branch.target = e->next->e.branch.target; e->next = e->next->next; break; } } s = &(*s)->next; } else if (is_goto_expr (*s)) { - l = (*s)->e.expr.e1; + l = (*s)->e.branch.target; for (e = (*s)->next; e && e->type == ex_label; e = e->next) { if (e == l) { l->e.label.used--; @@ -1722,18 +1719,6 @@ static sblock_t * statement_expr (sblock_t *sblock, expr_t *e) { switch (e->e.expr.op) { - case 'c': - sblock = expr_call (sblock, e, 0); - break; - case 'g': - case 'i': - case 'n': - case IFBE: - case IFB: - case IFAE: - case IFA: - sblock = statement_branch (sblock, e); - break; case 'm': case 'M': sblock = expr_move (sblock, e, 0); @@ -1776,9 +1761,6 @@ statement_uexpr (sblock_t *sblock, expr_t *e) sblock->next = new_sblock (); sblock = sblock->next; break; - case 'g': - sblock = statement_branch (sblock, e); - break; default: debug (e, "e ue %d", e->e.expr.op); if (options.warnings.executable) @@ -1847,6 +1829,7 @@ statement_slist (sblock_t *sblock, expr_t *e) [ex_value] = statement_nonexec, [ex_memset] = statement_memset, [ex_assign] = statement_assign, + [ex_branch] = statement_branch, }; for (/**/; e; e = e->next) { @@ -2115,24 +2098,19 @@ search_for_super_dealloc (sblock_t *sblock) if (!statement_is_call (st)) { continue; } + // effectively checks target if (st->opa->op_type != op_def || strcmp (st->opa->def->name, "obj_msgSend_super") != 0) { continue; } - // FIXME this is messy (calls should have their own expression - // type) - // have effectively checked e1 above - if (st->expr->type != ex_expr) { - continue; - } // function arguments are in reverse order, and the selector // is the second argument (or second last in the list) expr_t *arg; - for (arg = st->expr->e.expr.e2; + for (arg = st->expr->e.branch.args; arg && arg->next && arg->next->next; arg = arg->next) { } if (arg && arg->next && is_selector (arg)) { - selector_t *sel = get_selector (st->expr->e.expr.e2); + selector_t *sel = get_selector (st->expr->e.branch.args); if (sel && strcmp (sel->name, "dealloc") == 0) { op = pseudo_operand (super_dealloc, st->expr); op->next = st->use; diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index e1b6d4aa7..190d92a1b 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -311,12 +311,12 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, append_expr (sw, test); if (tree->low == tree->high) { - branch = branch_expr ('n', new_alias_expr (&type_integer, temp), + branch = branch_expr (EQ, new_alias_expr (&type_integer, temp), tree->labels[0]); append_expr (sw, branch); if (tree->left) { - branch = branch_expr (IFA, new_alias_expr (&type_integer, temp), + branch = branch_expr (GT, new_alias_expr (&type_integer, temp), high_label); append_expr (sw, branch); @@ -352,14 +352,14 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, table_expr = new_symbol_expr (table_sym); if (tree->left) { - branch = branch_expr (IFB, temp, low_label); + branch = branch_expr (LT, temp, low_label); append_expr (sw, branch); } test = binary_expr (GT, cast_expr (&type_uinteger, temp), cast_expr (&type_uinteger, range)); - branch = branch_expr ('i', test, high_label); + branch = branch_expr (NE, test, high_label); append_expr (sw, branch); - branch = new_binary_expr ('g', table_expr, temp); + branch = jump_table_expr (table_expr, temp); append_expr (sw, branch); debug (sw, "switch using jump table"); if (tree->left) { @@ -433,7 +433,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, || num_labels < 8) { for (l = labels; *l; l++) { expr_t *cmp = binary_expr (EQ, sw_val, (*l)->value); - expr_t *test = branch_expr ('i', test_expr (cmp), + expr_t *test = branch_expr (NE, test_expr (cmp), (*l)->label); append_expr (sw, test); From 66528e34fc9dcbf2220ad8a3754a9cb9dd1e264a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Jan 2022 16:28:08 +0900 Subject: [PATCH 2152/3664] [qfcc] Give return expressions their own type Very simple for now (just the return value if not a void return), but that's the last of the statements masquerading as expressions. --- tools/qfcc/include/expr.h | 6 ++ tools/qfcc/include/expr_names.h | 1 + tools/qfcc/source/constfold.c | 2 - tools/qfcc/source/dot_expr.c | 19 ++++- tools/qfcc/source/expr.c | 45 +++++++---- tools/qfcc/source/expr_assign.c | 1 + tools/qfcc/source/qp-parse.y | 2 +- tools/qfcc/source/statements.c | 138 +++++++++++--------------------- 8 files changed, 100 insertions(+), 114 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index ff8c25cf7..59ac358e4 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -233,6 +233,10 @@ typedef struct { struct type_s *ret_type; ///< void for non-call } ex_branch_t; +typedef struct { + struct expr_s *ret_val; +} ex_return_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -263,6 +267,7 @@ typedef struct expr_s { ex_address_t address; ///< alias expr params ex_assign_t assign; ///< assignment expr params ex_branch_t branch; ///< branch expr params + ex_return_t retrn; ///< return expr params struct type_s *nil; ///< type for nil if known } e; } expr_t; @@ -680,6 +685,7 @@ expr_t *new_offset_alias_expr (struct type_s *type, expr_t *expr, int offset); expr_t *new_address_expr (struct type_s *lvtype, expr_t *lvalue, expr_t *offset); expr_t *new_assign_expr (expr_t *dst, expr_t *src); +expr_t *new_return_expr (expr_t *ret_val); /** Create an expression of the correct type that references the specified parameter slot. diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index fab5c0fdb..08285c94a 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -58,5 +58,6 @@ EX_EXPR(alias) ///< view expression as different type (::ex_alias_t) EX_EXPR(address) ///< address of an lvalue expression (::ex_address_t) EX_EXPR(assign) ///< assignment of src expr to dst expr (::ex_assing_t) EX_EXPR(branch) ///< branch expression (::ex_branch_t) +EX_EXPR(return) ///< return expression (::ex_return_t) ///@} diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 92ae4c330..6ee98f70e 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1680,8 +1680,6 @@ fold_constants (expr_t *e) return e; } op = e->e.expr.op; - if (op == 'r') - return e; t1 = extract_type (e1); if (t1 >= ev_type_count || !do_unary_op[t1]) { print_expr (e); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index a29920881..a66009bd5 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -89,7 +89,6 @@ get_op_string (int op) case SHL: return "<<"; case SHR: return ">>"; case '.': return "."; - case 'r': return ""; case 'C': return ""; default: return "unknown"; @@ -401,14 +400,25 @@ print_branch (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) } } +static void +print_return (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + if (e->e.retrn.ret_val) { + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, + e->e.retrn.ret_val); + } + dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, + "return", e->line); +} + static void print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - if (e->e.expr.op != 'r' || e->e.expr.e1) - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, - e->e.expr.e1); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, e->e.expr.e1); dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, get_op_string (e->e.expr.op), e->line); } @@ -645,6 +655,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_address] = print_address, [ex_assign] = print_assign, [ex_branch] = print_branch, + [ex_return] = print_return, }; int indent = level * 2 + 2; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 06f4ba944..ae3f919dc 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -221,10 +221,12 @@ get_type (expr_t *e) break; case ex_memset: return e->e.memset.type; - case ex_label: case ex_error: + case ex_return: + internal_error (e, "unexpected expression type"); + case ex_label: case ex_compound: - return 0; // something went very wrong + return 0; case ex_bool: if (options.code.progsversion == PROG_ID_VERSION) return &type_float; @@ -504,6 +506,11 @@ copy_expr (expr_t *e) n->e.branch.test = copy_expr (e->e.branch.test); n->e.branch.args = copy_expr (e->e.branch.args); return n; + case ex_return: + n = new_expr (); + *n = *e; + n->e.retrn.ret_val = copy_expr (n->e.retrn.ret_val); + return n; case ex_count: break; } @@ -1325,6 +1332,15 @@ new_assign_expr (expr_t *dst, expr_t *src) return addr; } +expr_t * +new_return_expr (expr_t *ret_val) +{ + expr_t *retrn = new_expr (); + retrn->type = ex_return; + retrn->e.retrn.ret_val = ret_val; + return retrn; +} + static expr_t * param_expr (const char *name, type_t *type) { @@ -1619,6 +1635,8 @@ has_function_call (expr_t *e) return 0; } return has_function_call (e->e.branch.test); + case ex_return: + return has_function_call (e->e.retrn.ret_val); case ex_error: case ex_state: case ex_label: @@ -1716,7 +1734,8 @@ unary_expr (int op, expr_t *e) case ex_compound: case ex_memset: case ex_selector: - internal_error (e, 0); + case ex_return: + internal_error (e, "unexpected expression type"); case ex_uexpr: if (e->e.expr.op == '-') { return e->e.expr.e1; @@ -1816,7 +1835,8 @@ unary_expr (int op, expr_t *e) case ex_compound: case ex_memset: case ex_selector: - internal_error (e, 0); + case ex_return: + internal_error (e, "unexpected expression type"); case ex_bool: return new_bool_expr (e->e.bool.false_list, e->e.bool.true_list, e); @@ -1894,7 +1914,8 @@ unary_expr (int op, expr_t *e) case ex_compound: case ex_memset: case ex_selector: - internal_error (e, 0); + case ex_return: + internal_error (e, "unexpected expression type"); case ex_uexpr: if (e->e.expr.op == '~') return e->e.expr.e1; @@ -2222,7 +2243,7 @@ return_expr (function_t *f, expr_t *e) } // the traditional check above may have set e if (!e) { - return new_unary_expr ('r', 0); + return new_return_expr (0); } } @@ -2279,7 +2300,7 @@ return_expr (function_t *f, expr_t *e) if (e->type == ex_block) { e->e.block.result->rvalue = 1; } - return new_unary_expr ('r', e); + return new_return_expr (e); } expr_t * @@ -2471,16 +2492,6 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) e1->e.expr.e1, e1->e.expr.e2); break; } - if (e1->e.expr.op == 'm') { - // direct move, so obtain the address of the source - e = address_expr (e1->e.expr.e2, 0, t); - break; - } - if (e1->e.expr.op == 'M') { - // indirect move, so we already have the address of the source - e = e1->e.expr.e2; - break; - } return error (e1, "invalid type for unary &"); case ex_uexpr: if (e1->e.expr.op == '.') { diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index ed23270c1..a961e113d 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -137,6 +137,7 @@ is_lvalue (const expr_t *expr) case ex_value: case ex_error: case ex_selector: + case ex_return: break; case ex_count: internal_error (expr, "invalid expression"); diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 59ddaceec..b45e6d0ee 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -270,7 +270,7 @@ subprogram_declaration } declarations compound_statement ';' { - append_expr ($5, new_unary_expr ('r', 0)); + append_expr ($5, new_return_expr (0)); build_code_function ($1, 0, $5); current_symtab = current_symtab->parent; current_storage = $3; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 76caa4eaf..1c2cbc965 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -963,35 +963,6 @@ dereference_dst: return sblock; } -static sblock_t * -expr_move (sblock_t *sblock, expr_t *e, operand_t **op) -{ - statement_t *s; - type_t *type = e->e.expr.type; - expr_t *dst_expr = e->e.expr.e1; - expr_t *src_expr = e->e.expr.e2; - expr_t *size_expr; - operand_t *dst = 0; - operand_t *src = 0; - operand_t *size = 0; - - if (!op) - op = &dst; - size_expr = new_short_expr (type_size (type)); - sblock = statement_subexpr (sblock, dst_expr, op); - dst = *op; - sblock = statement_subexpr (sblock, src_expr, &src); - sblock = statement_subexpr (sblock, size_expr, &size); - s = new_statement (e->e.expr.op == 'm' ? st_move : st_ptrmove, - convert_op (e->e.expr.op), e); - s->opa = src; - s->opb = size; - s->opc = dst; - sblock_add_statement (sblock, s); - - return sblock; -} - static sblock_t * vector_call (sblock_t *sblock, expr_t *earg, expr_t *param, int ind, operand_t **op) @@ -1119,6 +1090,33 @@ statement_branch (sblock_t *sblock, expr_t *e) return sblock->next; } +static sblock_t * +statement_return (sblock_t *sblock, expr_t *e) +{ + const char *opcode; + statement_t *s; + + debug (e, "RETURN"); + opcode = ""; + if (!e->e.retrn.ret_val) { + if (options.code.progsversion != PROG_ID_VERSION) { + opcode = ""; + } else { + e->e.retrn.ret_val = new_float_expr (0); + } + } + s = new_statement (st_func, opcode, e); + if (e->e.retrn.ret_val) { + s->opa = return_operand (get_type (e->e.retrn.ret_val), e); + sblock = statement_subexpr (sblock, e->e.retrn.ret_val, &s->opa); + } + sblock_add_statement (sblock, s); + sblock->next = new_sblock (); + sblock = sblock->next; + + return sblock; +} + static statement_t * lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) { @@ -1266,24 +1264,17 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) const char *opcode; statement_t *s; - switch (e->e.expr.op) { - case 'm': - case 'M': - sblock = expr_move (sblock, e, op); - break; - default: - opcode = convert_op (e->e.expr.op); - if (!opcode) - internal_error (e, "ice ice baby"); - s = new_statement (st_expr, opcode, e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); - if (!*op) - *op = temp_operand (e->e.expr.type, e); - s->opc = *op; - sblock_add_statement (sblock, s); - break; - } + opcode = convert_op (e->e.expr.op); + if (!opcode) + internal_error (e, "ice ice baby"); + s = new_statement (st_expr, opcode, e); + sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); + sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); + if (!*op) + *op = temp_operand (e->e.expr.type, e); + s->opc = *op; + sblock_add_statement (sblock, s); + return sblock; } @@ -1718,55 +1709,21 @@ statement_block (sblock_t *sblock, expr_t *e) static sblock_t * statement_expr (sblock_t *sblock, expr_t *e) { - switch (e->e.expr.op) { - case 'm': - case 'M': - sblock = expr_move (sblock, e, 0); - break; - default: - if (e->e.expr.op < 256) - debug (e, "e %c", e->e.expr.op); - else - debug (e, "e %d", e->e.expr.op); - if (options.warnings.executable) - warning (e, "Non-executable statement;" - " executing programmer instead."); - } + if (e->e.expr.op < 256) + debug (e, "e %c", e->e.expr.op); + else + debug (e, "e %d", e->e.expr.op); + if (options.warnings.executable) + warning (e, "Non-executable statement; executing programmer instead."); return sblock; } static sblock_t * statement_uexpr (sblock_t *sblock, expr_t *e) { - const char *opcode; - statement_t *s; - - switch (e->e.expr.op) { - case 'r': - debug (e, "RETURN"); - opcode = ""; - if (!e->e.expr.e1) { - if (options.code.progsversion != PROG_ID_VERSION) { - opcode = ""; - } else { - e->e.expr.e1 = new_float_expr (0); - } - } - s = new_statement (st_func, opcode, e); - if (e->e.expr.e1) { - s->opa = return_operand (get_type (e->e.expr.e1), e); - sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); - } - sblock_add_statement (sblock, s); - sblock->next = new_sblock (); - sblock = sblock->next; - break; - default: - debug (e, "e ue %d", e->e.expr.op); - if (options.warnings.executable) - warning (e, "Non-executable statement;" - " executing programmer instead."); - } + debug (e, "e ue %d", e->e.expr.op); + if (options.warnings.executable) + warning (e, "Non-executable statement; executing programmer instead."); return sblock; } @@ -1830,6 +1787,7 @@ statement_slist (sblock_t *sblock, expr_t *e) [ex_memset] = statement_memset, [ex_assign] = statement_assign, [ex_branch] = statement_branch, + [ex_return] = statement_return, }; for (/**/; e; e = e->next) { From 494a6908bbc5728f028b40a2b9b5d8bb77d25cef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jan 2022 11:04:43 +0900 Subject: [PATCH 2153/3664] [gamecode] Improve with's comment --- libs/gamecode/opcodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 9d71b94e5..5821aa1a1 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -7,7 +7,7 @@ bitmap_txt = """ 0 0110 0nnn rcall 1-8 (0 0100 11mm with 0 params for [r]call0) 0 0110 10ss return 0 0110 1100 returnv -0 0110 1101 with (reg encoded in st->c) +0 0110 1101 with (mode in st->a, value in st->b, reg in st->c) 0 0110 111t state 0 0111 tooo vecops 0 1ccc ttss compare From db7a67e5b78665865e9702d18c3fe4a1ed07a356 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jan 2022 11:16:55 +0900 Subject: [PATCH 2154/3664] [gamecode] Rearrange vector instructions This allows the dot products to be consistent with their sizes: cdot is really dot_2, vdot dot_3, and qdot dot_4. --- libs/gamecode/opcodes.py | 2 +- libs/gamecode/pr_exec.c | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 5821aa1a1..2c4410eb7 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -454,7 +454,7 @@ vecops_formats = { "widths": "{vec_widths[ooo]}", "types": "{vec_types[t]}, {vec_types[t]}, {vec_types[t]}", "args": { - "op_vop": ["cdot", "vdot", "qdot", "cross", + "op_vop": ["cross", "cdot", "vdot", "qdot", "cmul", "qvmul", "vqmul", "qmul"], "vop_type": ['F', 'D'], "vec_widths": [ diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index f43011a79..d5be92743 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2959,6 +2959,14 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) } break; // 0 0111 + case OP_CROSS_F: + { + pr_vec4_t a = loadvec3f (&OPA(float)); + pr_vec4_t b = loadvec3f (&OPB(float)); + pr_vec4_t c = crossf (a, b); + storevec3f (&OPC(float), c); + } + break; case OP_CDOT_F: OPC(vec2) = dot2f (OPA(vec2), OPB(vec2)); break; @@ -2972,14 +2980,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_QDOT_F: OPC(vec4) = dotf (OPA(vec4), OPB(vec4)); break; - case OP_CROSS_F: - { - pr_vec4_t a = loadvec3f (&OPA(float)); - pr_vec4_t b = loadvec3f (&OPB(float)); - pr_vec4_t c = crossf (a, b); - storevec3f (&OPC(float), c); - } - break; case OP_CMUL_F: OPC(vec2) = cmulf (OPA(vec2), OPB(vec2)); break; @@ -3000,6 +3000,14 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_QMUL_F: OPC(vec4) = qmulf (OPA(vec4), OPB(vec4)); break; + case OP_CROSS_D: + { + pr_dvec4_t a = loadvec3d (&OPA(double)); + pr_dvec4_t b = loadvec3d (&OPB(double)); + pr_dvec4_t c = crossd (a, b); + storevec3d (&OPC(double), c); + } + break; case OP_CDOT_D: OPC(dvec2) = dot2d (OPA(dvec2), OPB(dvec2)); break; @@ -3013,14 +3021,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_QDOT_D: OPC(dvec4) = dotd (OPA(dvec4), OPB(dvec4)); break; - case OP_CROSS_D: - { - pr_dvec4_t a = loadvec3d (&OPA(double)); - pr_dvec4_t b = loadvec3d (&OPB(double)); - pr_dvec4_t c = crossd (a, b); - storevec3d (&OPC(double), c); - } - break; case OP_CMUL_D: OPC(dvec2) = cmuld (OPA(dvec2), OPB(dvec2)); break; From ba29be3f82a56a1215511740ee3ad1999b12ca30 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jan 2022 11:27:57 +0900 Subject: [PATCH 2155/3664] [gamecode] Rename ifnot and if to be less confusing I think :) anyway, now they're ifz and ifnz, making them consistent with the rest of the if instructions. --- libs/gamecode/opcodes.py | 4 +- libs/gamecode/pr_exec.c | 90 ++++++++++++++++---------------- libs/gamecode/test/test-double.c | 2 +- libs/gamecode/test/test-float.c | 2 +- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 2c4410eb7..319859f1d 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -114,8 +114,8 @@ branch_formats = { "types": "ev_void, ev_void, ev_integer", "args": { "op_mode": "ABCD", - "op_cond": ["ifnot", "ifb", "ifa", "jump", - "if", "ifae", "ifbe", "call"], + "op_cond": ["ifz", "ifb", "ifa", "jump", + "ifnz", "ifae", "ifbe", "call"], "branch_fmt": branch_fmt, "cond_fmt": ["%Gc ", "%Gc ", "%Gc ", "", "%Gc ", "%Gc ", "%Gc ", ""], "cond_widths": [ diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index d5be92743..3d179c869 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2819,20 +2819,29 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) MM(ivec4) = STK(ivec4); break; // 0 0100 - case OP_IFNOT_A: - case OP_IFNOT_B: - case OP_IFNOT_C: - case OP_IFNOT_D: + case OP_IFZ_A: + case OP_IFZ_B: + case OP_IFZ_C: + case OP_IFZ_D: if (!OPC(int)) { pr->pr_xstatement = pr_jump_mode (pr, st); st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_IF_A: - case OP_IF_B: - case OP_IF_C: - case OP_IF_D: - if (OPC(int)) { + case OP_IFB_A: + case OP_IFB_B: + case OP_IFB_C: + case OP_IFB_D: + if (OPC(int) < 0) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFA_A: + case OP_IFA_B: + case OP_IFA_C: + case OP_IFA_D: + if (OPC(int) > 0) { pr->pr_xstatement = pr_jump_mode (pr, st); st = pr->pr_statements + pr->pr_xstatement; } @@ -2844,6 +2853,33 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) pr->pr_xstatement = pr_jump_mode (pr, st); st = pr->pr_statements + pr->pr_xstatement; break; + case OP_IFNZ_A: + case OP_IFNZ_B: + case OP_IFNZ_C: + case OP_IFNZ_D: + if (OPC(int)) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFAE_A: + case OP_IFAE_B: + case OP_IFAE_C: + case OP_IFAE_D: + if (OPC(int) >= 0) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFBE_A: + case OP_IFBE_B: + case OP_IFBE_C: + case OP_IFBE_D: + if (OPC(int) <= 0) { + pr->pr_xstatement = pr_jump_mode (pr, st); + st = pr->pr_statements + pr->pr_xstatement; + } + break; case OP_CALL_A: case OP_CALL_B: case OP_CALL_C: @@ -2922,42 +2958,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) } break; // 0 0110 - case OP_IFA_A: - case OP_IFA_B: - case OP_IFA_C: - case OP_IFA_D: - if (OPC(int) > 0) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; - case OP_IFBE_A: - case OP_IFBE_B: - case OP_IFBE_C: - case OP_IFBE_D: - if (OPC(int) <= 0) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; - case OP_IFB_A: - case OP_IFB_B: - case OP_IFB_C: - case OP_IFB_D: - if (OPC(int) < 0) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; - case OP_IFAE_A: - case OP_IFAE_B: - case OP_IFAE_C: - case OP_IFAE_D: - if (OPC(int) >= 0) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; // 0 0111 case OP_CROSS_F: { diff --git a/libs/gamecode/test/test-double.c b/libs/gamecode/test/test-double.c index 230ba69ee..8e11359ee 100644 --- a/libs/gamecode/test/test-double.c +++ b/libs/gamecode/test/test-double.c @@ -129,7 +129,7 @@ static dstatement_t double_cossin_statements[] = { { OP(0, 0, 0, OP_DIV_D_2), 40, 16, 40 }, // xn /= f { OP(0, 0, 0, OP_ADD_D_2), 16, 24, 16 }, // f += inc { OP(0, 0, 0, OP_LT_D_1), 16, 30, 46 }, // f0 < fmax - { OP(0, 0, 0, OP_IF_A), -7, 0, 46 }, // f0 < fmax + { OP(0, 0, 0, OP_IFNZ_A), -7, 0, 46 }, // f0 < fmax }; test_t tests[] = { diff --git a/libs/gamecode/test/test-float.c b/libs/gamecode/test/test-float.c index d974931bb..8f5794c3d 100644 --- a/libs/gamecode/test/test-float.c +++ b/libs/gamecode/test/test-float.c @@ -129,7 +129,7 @@ static dstatement_t float_cossin_statements[] = { { OP(0, 0, 0, OP_DIV_F_2), 20, 8, 20 }, // xn /= f { OP(0, 0, 0, OP_ADD_F_2), 8, 12, 8 }, // f += inc { OP(0, 0, 0, OP_LT_F_1), 8, 15, 23 }, // f0 < fmax - { OP(0, 0, 0, OP_IF_A), -7, 0, 23 }, // f0 < fmax + { OP(0, 0, 0, OP_IFNZ_A), -7, 0, 23 }, // f0 < fmax }; test_t tests[] = { From b9e32ee2f5058b42631bbe376ee412cf31cf26e2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jan 2022 11:38:21 +0900 Subject: [PATCH 2156/3664] [gamecode] Rework call and return instructions The call1-8 instructions have been removed as they are really not needed (they were put in when I had plans of simple translation of v6p progs to ruamoko, but they joined the dinosaurs). The call instruction lost mode A (that is now return) and its mode B is just the regular function access. The important thing is op_c (with support for with-bases) specifies the location of the return def. The return instruction packs both its addressing mode and return value size into st->c as a 3.5 value: 3 bits for the mode (it supports all five addressing modes with entity.field being mode 4) and 5 for the size, limiting return sizes to 32 words, which is enough for one 4x4 double matrix. This, especially with the following convert patch, frees up a lot of instructions. --- libs/gamecode/opcodes.py | 71 ++++++++++------------ libs/gamecode/pr_exec.c | 123 ++++++++++++++++++++++++++------------- 2 files changed, 116 insertions(+), 78 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 319859f1d..f7745c76c 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -4,9 +4,13 @@ bitmap_txt = """ 0 0010 mmss push 0 0011 mmss pop 0 010c ccmm branch -0 0110 0nnn rcall 1-8 (0 0100 11mm with 0 params for [r]call0) -0 0110 10ss return -0 0110 1100 returnv + +# while call and return are part of the branch block, they have different +# handling for addressing and formatting +0 0101 11mm call (return specified st->c) +0 0101 1100 return (size in st->c) + +0 0110 0nnn 0 0110 1101 with (mode in st->a, value in st->b, reg in st->c) 0 0110 111t state 0 0111 tooo vecops @@ -115,7 +119,7 @@ branch_formats = { "args": { "op_mode": "ABCD", "op_cond": ["ifz", "ifb", "ifa", "jump", - "ifnz", "ifae", "ifbe", "call"], + "ifnz", "ifae", "ifbe", None], #call and return seprate "branch_fmt": branch_fmt, "cond_fmt": ["%Gc ", "%Gc ", "%Gc ", "", "%Gc ", "%Gc ", "%Gc ", ""], "cond_widths": [ @@ -130,6 +134,23 @@ branch_formats = { ], }, } +call_formats = { + "opcode": "OP_CALL_{op_mode[mm]}", + "mnemonic": "call", + "opname": "call", + "format": "{call_fmt[mm]}", + "widths": "0, 0, 0", + "types": "ev_void, ev_void, ev_void", + "args": { + "op_mode": ".BCD", + "call_fmt": [ + None, # return handled seprately + "%Ga, %gc", + "%Ga[%sb], %gc", + "%Ga[%Gb], %gc", + ], + }, +} compare_formats = { "opcode": "OP_{op_cmp[ccc].upper()}_{cmp_type[tt]}_{ss+1}", "mnemonic": "{op_cmp[ccc]}.{cmp_type[tt]}", @@ -411,41 +432,13 @@ swizzle_formats = { "swizzle_types": float_t, }, } -rcall_formats = { - "opcode": "OP_CALL_{nnn+1}", - "mnemonic": "rcall{nnn+1}", - "opname": "rcall{nnn+1}", - "format": "{rcall_fmt[nnn]}", - "widths": "0, 0, 0", - "types": "ev_func, ev_void, ev_void", - "args": { - "rcall_fmt": [ - "%Fa (%P0b)", - "%Fa (%P0b, %P1c)", - "%Fa (%P0b, %P1c, %P2x)", - "%Fa (%P0b, %P1c, %P2x, %P3x)", - "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", - "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", - "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", - "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", - ], - }, -} return_formats = { - "opcode": "OP_RETURN_{ss+1}", - "mnemonic": "return{ss+1}", - "opname": "return", - "widths": "0, 0, 0", - "format": "%Ra", - "types": "ev_void, ev_invalid, ev_invalid", -} -returnv_formats = { - "opcode": "OP_RETURN_0", + "opcode": "OP_RETURN", "mnemonic": "return", "opname": "return", - "widths": "0, 0, 0", - "format": None, - "types": "ev_invalid, ev_invalid, ev_invalid", + "widths": "0, 0, 0", # width specified by st->c + "format": "FIXME", + "types": "ev_void, ev_void, ev_void", } vecops_formats = { "opcode": "OP_{op_vop[ooo].upper()}_{vop_type[t]}", @@ -497,6 +490,7 @@ group_map = { "bitops": bitops_formats, "boolops": boolops_formats, "branch": branch_formats, + "call": call_formats, "compare": compare_formats, "compare2": compare2_formats, "convert": convert_formats, @@ -518,9 +512,7 @@ group_map = { "store": store_formats, "string": string_formats, "swizzle": swizzle_formats, - "rcall": rcall_formats, "return": return_formats, - "returnv": returnv_formats, "vecops": vecops_formats, "vecops2": vecops2_formats, "with": with_formats, @@ -601,7 +593,8 @@ if len (sys.argv) < 2 or sys.argv[1] not in ["enum", "table"]: lines = bitmap_txt.split('\n') for l in lines: - if not l: + l = l.strip() + if not l or l[0] == '#': continue c = l.split(' ') bits = "".join(c[0:3]) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 3d179c869..66b1f3818 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1793,6 +1793,68 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int shift) return pr->pr_globals + mm_offs; } +static pr_type_t * +pr_return_mode (progs_t *pr, const dstatement_t *st, int mm_ind) +{ + pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); + pointer_t mm_offs = 0; + + switch (mm_ind) { + case 0: + // regular global access + mm_offs = op_a - pr->pr_globals; + break; + case 1: + // simple pointer dereference: *a + mm_offs = OPA(uint); + break; + case 2: + // constant indexed pointer: *a + b (supports -ve offset) + mm_offs = OPA(uint) + (short) st->b; + break; + case 3: + // variable indexed pointer: *a + *b (supports -ve offset) + mm_offs = OPA(uint) + OPB(int); + break; + case 4: + // entity.field (equivalent to OP_LOAD_t_v6p) + pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + mm_offs = edict_area + OPA(uint) + OPB(uint); + break; + } + return pr->pr_globals + mm_offs; +} + +static pr_type_t * +pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind) +{ + pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); + pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); + pointer_t mm_offs = 0; + + switch (mm_ind) { + case 1: + // regular global access + mm_offs = op_a - pr->pr_globals; + break; + case 2: + // constant indexed pointer: *a + b (supports -ve offset) + mm_offs = OPA(uint) + (short) st->b; + break; + case 3: + // variable indexed pointer: *a + *b (supports -ve offset) + mm_offs = OPA(uint) + OPB(int); + break; + case 4: + // entity.field (equivalent to OP_LOAD_t_v6p) + pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + mm_offs = edict_area + OPA(uint) + OPB(uint); + break; + } + return pr->pr_globals + mm_offs; +} + static pr_pointer_t __attribute__((pure)) pr_jump_mode (progs_t *pr, const dstatement_t *st) { @@ -2880,45 +2942,12 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_CALL_A: - case OP_CALL_B: - case OP_CALL_C: - case OP_CALL_D: - mm = pr_address_mode (pr, st, 0); - function = mm->func_var; - pr->pr_argc = 0; - op_call: - pr->pr_xfunction->profile += profile - startprofile; - startprofile = profile; - PR_CallFunction (pr, function); - st = pr->pr_statements + pr->pr_xstatement; - break; - // 0 0101 - case OP_CALL_2: case OP_CALL_3: case OP_CALL_4: - case OP_CALL_5: case OP_CALL_6: case OP_CALL_7: case OP_CALL_8: - pr->pr_params[1] = op_c; - goto op_call_n; - case OP_CALL_1: - pr->pr_params[1] = pr->pr_real_params[1]; - op_call_n: - pr->pr_params[0] = op_b; - function = op_a->func_var; - pr->pr_argc = st->op - OP_CALL_1 + 1; - goto op_call; - case OP_RETURN_4: - memcpy (&R_INT (pr), op_a, 4 * sizeof (*op_a)); - goto op_return; - case OP_RETURN_3: - memcpy (&R_INT (pr), op_a, 3 * sizeof (*op_a)); - goto op_return; - case OP_RETURN_2: - memcpy (&R_INT (pr), op_a, 2 * sizeof (*op_a)); - goto op_return; - case OP_RETURN_1: - memcpy (&R_INT (pr), op_a, 1 * sizeof (*op_a)); - goto op_return; - case OP_RETURN_0: - op_return: + case OP_RETURN: + int ret_size = st->c & 0x1f; // up to 32 words + if (ret_size) { + mm = pr_return_mode (pr, st, (st->c >> 5) & 7); + memcpy (&R_INT (pr), mm, ret_size * sizeof (*op_a)); + } pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; PR_LeaveFunction (pr, pr->pr_depth == exitdepth); @@ -2930,6 +2959,22 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) goto exit_program; } break; + case OP_CALL_B: + case OP_CALL_C: + case OP_CALL_D: + mm = pr_call_mode (pr, st, st->c & 3); + function = mm->func_var; + pr->pr_argc = 0; + // op_c specifies the location for the return value if any + pr->pr_return = op_c; + pr->pr_xfunction->profile += profile - startprofile; + startprofile = profile; + PR_CallFunction (pr, function); + st = pr->pr_statements + pr->pr_xstatement; + break; + // 0 0101 + // nnn spare + //OP_CONV case OP_WITH: pr->pr_bases[st->c & 3] = pr_with (pr, st); break; From 0fb661958516db7ae2b10b168d1c935e9fca0f11 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jan 2022 11:53:57 +0900 Subject: [PATCH 2157/3664] [gamecode] Compact the convert instructions into one Thanks to Deek for the suggestion: the mode (ie, src and dst types) are encoded in st->b. Actual code not written yet, but this frees up 13 instructions: now have 74 available for really interesting stuff :) --- libs/gamecode/opcodes.py | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index f7745c76c..94c115492 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -11,6 +11,7 @@ bitmap_txt = """ 0 0101 1100 return (size in st->c) 0 0110 0nnn +0 0110 1100 convert (conversion mode in st->b) 0 0110 1101 with (mode in st->a, value in st->b, reg in st->c) 0 0110 111t state 0 0111 tooo vecops @@ -22,7 +23,7 @@ bitmap_txt = """ 1 1000 ooss bitops 1 1001 t1ss scale 1 1001 t100 swizzle -1 1010 d1xx convert +1 1010 d1xx 1 1011 00mm lea 1 1011 01ss any 1 1011 0100 lea_e @@ -32,7 +33,7 @@ bitmap_txt = """ 1 1011 1100 popregs 1 1101 01oo move 1 1101 11oo memset -1 1110 d1xx convert2 +1 1110 d1xx 1 11dd t100 vecops2 1 1100 ooss boolops n 1111 nnnn @@ -176,31 +177,13 @@ compare2_formats = { }, } convert_formats = { - "opcode": "OP_CONV_{op_conv[d*4+xx]}", - "mnemonic": "conv.{op_conv[d*4+xx]}", + "opcode": "OP_CONV", + "mnemonic": "conv", "opname": "conv", - "format": "%Ga %gc", + "format": "%Ga %Cb %gc", "widths": "1, 0, 1", - "types": "{cnv_types[xx][d]}, ev_invalid, {cnv_types[xx][1-d]}", - "args": { - "op_conv": ["IF", "LD", "uF", "UD", "FI", "DL", "Fu", "DU"], - "cnv_types": [ - ["ev_integer", "ev_float"], - ["ev_long", "ev_double"], - ["ev_uinteger", "ev_float"], - ["ev_ulong", "ev_double"], - ], - }, + "types": "ev_void, ev_short, ev_void", } -convert2_formats = copy.deepcopy (convert_formats) -convert2_formats["args"]["op_conv"] = [None, "IL", "uU", "FD", - None, "LI", "Uu", "DF"] -convert2_formats["args"]["cnv_types"] = [ - [None, None], - ["ev_integer", "ev_long"], - ["ev_uinteger", "ev_ulong"], - ["ev_float", "ev_double"], -] lea_formats = { "opcode": "OP_LEA_{op_mode[mm]}", "mnemonic": "lea", @@ -494,7 +477,6 @@ group_map = { "compare": compare_formats, "compare2": compare2_formats, "convert": convert_formats, - "convert2": convert2_formats, "lea": lea_formats, "lea_e": lea_e_formats, "load": load_formats, From e7d7ec19893e6bc928b106d0e0cede9df800da40 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Jan 2022 09:37:38 +0900 Subject: [PATCH 2158/3664] [gamecode] Add tests for signed comparison ops Fortunately, they all pass without issues. --- libs/gamecode/test/test-double.c | 141 +++++++++++++++++++++++++++++++ libs/gamecode/test/test-float.c | 141 +++++++++++++++++++++++++++++++ libs/gamecode/test/test-int.c | 138 ++++++++++++++++++++++++++++++ libs/gamecode/test/test-long.c | 138 ++++++++++++++++++++++++++++++ 4 files changed, 558 insertions(+) diff --git a/libs/gamecode/test/test-double.c b/libs/gamecode/test/test-double.c index 8e11359ee..317e18df4 100644 --- a/libs/gamecode/test/test-double.c +++ b/libs/gamecode/test/test-double.c @@ -132,6 +132,102 @@ static dstatement_t double_cossin_statements[] = { { OP(0, 0, 0, OP_IFNZ_A), -7, 0, 46 }, // f0 < fmax }; +static pr_dvec4_t double_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +// 5.0 as 64-bit int +#define F 0x4014000000000000l +#define mF 0xc014000000000000l +static pr_lvec4_t double_cmpop_expect[] = { + { F, mF, F, mF}, + { F, F, mF, mF}, + { -1, 0, 0, -1}, + { 0, -1, 0, 0}, + { 0, 0, -1, 0}, + { 0, -1, -1, 0}, + { -1, 0, -1, -1}, + { -1, -1, 0, -1}, +}; + +static dstatement_t double_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_EQ_D_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_D_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_D_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_D_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_D_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_D_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t double_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_EQ_D_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_D_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_D_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_D_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_D_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_D_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t double_cmpop_3a_statements[] = { + { OP(1, 1, 1, OP_EQ_D_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_EQ_D_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_LT_D_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_D_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_GT_D_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_D_1), 6, 14, 38 }, + { OP(1, 1, 1, OP_NE_D_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_NE_D_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_GE_D_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_D_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_LE_D_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_D_1), 6, 14, 62 }, +}; + +static dstatement_t double_cmpop_3b_statements[] = { + { OP(1, 1, 1, OP_EQ_D_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_EQ_D_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_LT_D_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_D_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_GT_D_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_D_3), 2, 10, 34 }, + { OP(1, 1, 1, OP_NE_D_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_NE_D_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_GE_D_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_D_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_LE_D_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_D_3), 2, 10, 58 }, +}; + +static dstatement_t double_cmpop_4_statements[] = { + { OP(1, 1, 1, OP_EQ_D_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_D_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_D_4), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_D_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_D_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_D_4), 0, 8, 56 }, +}; + test_t tests[] = { { .desc = "double binop 1", @@ -187,6 +283,51 @@ test_t tests[] = { .init_globals = (pr_int_t *) double_cossin_init, .expect_globals = (pr_int_t *) double_cossin_expect, }, + { + .desc = "double cmpop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_1_statements), + .statements = double_cmpop_1_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, + { + .desc = "double cmpop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_2_statements), + .statements = double_cmpop_2_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, + { + .desc = "double cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_3a_statements), + .statements = double_cmpop_3a_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, + { + .desc = "double cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_3b_statements), + .statements = double_cmpop_3b_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, + { + .desc = "double cmpop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_statements = num_statements (double_cmpop_4_statements), + .statements = double_cmpop_4_statements, + .init_globals = (pr_int_t *) double_cmpop_init, + .expect_globals = (pr_int_t *) double_cmpop_expect, + }, }; #include "main.c" diff --git a/libs/gamecode/test/test-float.c b/libs/gamecode/test/test-float.c index 8f5794c3d..d01e90518 100644 --- a/libs/gamecode/test/test-float.c +++ b/libs/gamecode/test/test-float.c @@ -132,6 +132,102 @@ static dstatement_t float_cossin_statements[] = { { OP(0, 0, 0, OP_IFNZ_A), -7, 0, 23 }, // f0 < fmax }; +static pr_vec4_t float_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +// 5.0 as 32-bit int +#define F 0x40a00000 +#define mF 0xc0a00000 +static pr_ivec4_t float_cmpop_expect[] = { + { F, mF, F, mF}, + { F, F, mF, mF}, + { -1, 0, 0, -1}, + { 0, -1, 0, 0}, + { 0, 0, -1, 0}, + { 0, -1, -1, 0}, + { -1, 0, -1, -1}, + { -1, -1, 0, -1}, +}; + +static dstatement_t float_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_EQ_F_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_F_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_F_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_F_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_F_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_F_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t float_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_EQ_F_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_F_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_F_2), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_F_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_F_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_F_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t float_cmpop_3a_statements[] = { + { OP(1, 1, 1, OP_EQ_F_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_EQ_F_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_LT_F_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_F_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_GT_F_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_F_1), 3, 7, 19 }, + { OP(1, 1, 1, OP_NE_F_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_NE_F_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_GE_F_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_F_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_LE_F_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_F_1), 3, 7, 31 }, +}; + +static dstatement_t float_cmpop_3b_statements[] = { + { OP(1, 1, 1, OP_EQ_F_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_EQ_F_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_LT_F_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_F_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_GT_F_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_F_3), 1, 5, 17 }, + { OP(1, 1, 1, OP_NE_F_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_NE_F_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_GE_F_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_F_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_LE_F_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_F_3), 1, 5, 29 }, +}; + +static dstatement_t float_cmpop_4_statements[] = { + { OP(1, 1, 1, OP_EQ_F_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_F_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_F_4), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_F_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_F_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_F_4), 0, 4, 28 }, +}; + test_t tests[] = { { .desc = "float binop 1", @@ -187,6 +283,51 @@ test_t tests[] = { .init_globals = (pr_int_t *) float_cossin_init, .expect_globals = (pr_int_t *) float_cossin_expect, }, + { + .desc = "float cmpop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_1_statements), + .statements = float_cmpop_1_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, + { + .desc = "float cmpop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_2_statements), + .statements = float_cmpop_2_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, + { + .desc = "float cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_3a_statements), + .statements = float_cmpop_3a_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, + { + .desc = "float cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_3b_statements), + .statements = float_cmpop_3b_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, + { + .desc = "float cmpop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_statements = num_statements (float_cmpop_4_statements), + .statements = float_cmpop_4_statements, + .init_globals = (pr_int_t *) float_cmpop_init, + .expect_globals = (pr_int_t *) float_cmpop_expect, + }, }; #include "main.c" diff --git a/libs/gamecode/test/test-int.c b/libs/gamecode/test/test-int.c index 08cfe3596..fd5d25af8 100644 --- a/libs/gamecode/test/test-int.c +++ b/libs/gamecode/test/test-int.c @@ -95,6 +95,99 @@ static dstatement_t int_binop_4_statements[] = { { OP(1, 1, 1, OP_SUB_I_4), 0, 4, 28 }, }; +static pr_ivec4_t int_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t int_cmpop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { -1, 0, 0, -1}, + { 0, -1, 0, 0}, + { 0, 0, -1, 0}, + { 0, -1, -1, 0}, + { -1, 0, -1, -1}, + { -1, -1, 0, -1}, +}; + +static dstatement_t int_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_EQ_I_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_I_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_I_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_I_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t int_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_EQ_I_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_I_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_I_2), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_I_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_I_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_I_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t int_cmpop_3a_statements[] = { + { OP(1, 1, 1, OP_EQ_I_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_EQ_I_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_LT_I_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_I_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_GT_I_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_I_1), 3, 7, 19 }, + { OP(1, 1, 1, OP_NE_I_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_NE_I_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_GE_I_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_I_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_LE_I_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_I_1), 3, 7, 31 }, +}; + +static dstatement_t int_cmpop_3b_statements[] = { + { OP(1, 1, 1, OP_EQ_I_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_EQ_I_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_LT_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_I_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_GT_I_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_I_3), 1, 5, 17 }, + { OP(1, 1, 1, OP_NE_I_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_NE_I_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_GE_I_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_I_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_LE_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_I_3), 1, 5, 29 }, +}; + +static dstatement_t int_cmpop_4_statements[] = { + { OP(1, 1, 1, OP_EQ_I_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_LT_I_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_I_4), 0, 4, 16 }, + { OP(1, 1, 1, OP_NE_I_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_GE_I_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_I_4), 0, 4, 28 }, +}; + test_t tests[] = { { .desc = "int binop 1", @@ -141,6 +234,51 @@ test_t tests[] = { .init_globals = (pr_int_t *) int_binop_init, .expect_globals = (pr_int_t *) int_binop_expect, }, + { + .desc = "int cmpop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_1_statements), + .statements = int_cmpop_1_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, + { + .desc = "int cmpop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_2_statements), + .statements = int_cmpop_2_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, + { + .desc = "int cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_3a_statements), + .statements = int_cmpop_3a_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, + { + .desc = "int cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_3b_statements), + .statements = int_cmpop_3b_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, + { + .desc = "int cmpop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_statements = num_statements (int_cmpop_4_statements), + .statements = int_cmpop_4_statements, + .init_globals = (pr_int_t *) int_cmpop_init, + .expect_globals = (pr_int_t *) int_cmpop_expect, + }, }; #include "main.c" diff --git a/libs/gamecode/test/test-long.c b/libs/gamecode/test/test-long.c index 7777b38e0..fc1851151 100644 --- a/libs/gamecode/test/test-long.c +++ b/libs/gamecode/test/test-long.c @@ -97,6 +97,99 @@ static dstatement_t long_binop_4_statements[] = { { OP(1, 1, 1, OP_SUB_L_4), 0, 8, 56 }, }; +static pr_lvec4_t long_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_lvec4_t long_cmpop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { -1, 0, 0, -1}, + { 0, -1, 0, 0}, + { 0, 0, -1, 0}, + { 0, -1, -1, 0}, + { -1, 0, -1, -1}, + { -1, -1, 0, -1}, +}; + +static dstatement_t long_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_EQ_L_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_L_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_L_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_L_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t long_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_EQ_L_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_L_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_L_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_L_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_L_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_L_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t long_cmpop_3a_statements[] = { + { OP(1, 1, 1, OP_EQ_L_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_EQ_L_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_LT_L_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_L_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_GT_L_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_L_1), 6, 14, 38 }, + { OP(1, 1, 1, OP_NE_L_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_NE_L_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_GE_L_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_L_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_LE_L_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_L_1), 6, 14, 62 }, +}; + +static dstatement_t long_cmpop_3b_statements[] = { + { OP(1, 1, 1, OP_EQ_L_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_EQ_L_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_LT_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_L_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_GT_L_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_L_3), 2, 10, 34 }, + { OP(1, 1, 1, OP_NE_L_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_NE_L_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_GE_L_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_L_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_LE_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_L_3), 2, 10, 58 }, +}; + +static dstatement_t long_cmpop_4_statements[] = { + { OP(1, 1, 1, OP_EQ_L_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_LT_L_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_L_4), 0, 8, 32 }, + { OP(1, 1, 1, OP_NE_L_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_GE_L_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_L_4), 0, 8, 56 }, +}; + test_t tests[] = { { .desc = "long binop 1", @@ -143,6 +236,51 @@ test_t tests[] = { .init_globals = (pr_int_t *) long_binop_init, .expect_globals = (pr_int_t *) long_binop_expect, }, + { + .desc = "long cmpop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_1_statements), + .statements = long_cmpop_1_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, + { + .desc = "long cmpop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_2_statements), + .statements = long_cmpop_2_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, + { + .desc = "long cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_3a_statements), + .statements = long_cmpop_3a_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, + { + .desc = "long cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_3b_statements), + .statements = long_cmpop_3b_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, + { + .desc = "long cmpop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_statements = num_statements (long_cmpop_4_statements), + .statements = long_cmpop_4_statements, + .init_globals = (pr_int_t *) long_cmpop_init, + .expect_globals = (pr_int_t *) long_cmpop_expect, + }, }; #include "main.c" From 6229ae8ecc20c387a8214332dfd88a9f463c8e16 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 11 Jan 2022 13:00:54 +0900 Subject: [PATCH 2159/3664] [gamecode] Add tests for unsigned comparisons And fix the implementation: I had used the wrong macro. --- libs/gamecode/pr_exec.c | 17 +- libs/gamecode/test/Makemodule.am | 10 +- libs/gamecode/test/test-unsigned.c | 284 +++++++++++++++++++++++++++++ 3 files changed, 300 insertions(+), 11 deletions(-) create mode 100644 libs/gamecode/test/test-unsigned.c diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 66b1f3818..852f8f980 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3121,7 +3121,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) // 0 1010 OP_cmp(GT, >); // 0 1011 - //FIXME conversion 1 // 0 1100 OP_cmp(NE, !=); // 0 1101 @@ -3300,20 +3299,20 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_op_T (BITXOR, I, int, ivec2, ivec4, ^); OP_uop_T (BITNOT, I, int, ivec2, ivec4, ~); // 1 1001 - OP_op_T (LT, u, uint, uivec2, uivec4, <); + OP_cmp_T (LT, u, int, ivec2, ivec4, <, uint, uivec2, uivec4); case OP_SWIZZLE_F: OPC(ivec4) = pr_swizzle_f (OPA(ivec4), st->b); break; //FIXME scale ops - OP_op_T (LT, U, ulong, ulvec2, ulvec4, <); + OP_cmp_T (LT, U, long, lvec2, lvec4, <, ulong, ulvec2, ulvec4); case OP_SWIZZLE_D: OPC(lvec4) = pr_swizzle_d (OPA(lvec4), st->b); break; //FIXME scale ops // 1 1010 - OP_op_T (GT, u, uint, uivec2, uivec4, >); + OP_cmp_T (GT, u, int, ivec2, ivec4, >, uint, uivec2, uivec4); //FIXME conversion ops - OP_op_T (GT, U, ulong, ulvec2, ulvec4, >); + OP_cmp_T (GT, U, long, lvec2, lvec4, >, ulong, ulvec2, ulvec4); //FIXME conversion ops // 1 1011 case OP_LEA_A: @@ -3415,7 +3414,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_not_3 (NOT, int, 3, +); OP_not_n (NOT, ivec4, 4, +); // 1 1101 - OP_op_T (GE, u, uint, uivec2, uivec4, >=); + OP_cmp_T (GE, u, int, ivec2, ivec4, >=, uint, uivec2, uivec4); case OP_QV4MUL_F: OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); break; @@ -3430,7 +3429,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) memmove (pr->pr_globals + OPC(int), pr->pr_globals + OPA(int), st->b * sizeof (pr_type_t)); break; - OP_op_T (GE, U, ulong, ulvec2, ulvec4, >=); + OP_cmp_T (GE, U, long, lvec2, lvec4, >=, ulong, ulvec2, ulvec4); case OP_QV4MUL_D: OPC(dvec4) = qvmuld (OPA(dvec4), OPB(dvec4)); break; @@ -3444,12 +3443,12 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) pr_memset (pr->pr_globals + OPC(int), OPA(int), st->b); break; // 1 1110 - OP_op_T (LE, u, uint, uivec2, uivec4, <=); + OP_cmp_T (LE, u, int, ivec2, ivec4, <=, uint, uivec2, uivec4); case OP_V4QMUL_F: OPC(vec4) = vqmulf (OPA(vec4), OPB(vec4)); break; - OP_op_T (LE, U, ulong, ulvec2, ulvec4, <=); + OP_cmp_T (LE, U, long, lvec2, lvec4, <=, ulong, ulvec2, ulvec4); case OP_V4QMUL_D: OPC(dvec4) = vqmuld (OPA(dvec4), OPB(dvec4)); break; diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 2df9ef114..af16fe67f 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -4,9 +4,10 @@ libs_gamecode_tests = \ libs/gamecode/test/test-int \ libs/gamecode/test/test-load \ libs/gamecode/test/test-long \ - libs/gamecode/test/test-vector \ libs/gamecode/test/test-stack \ - libs/gamecode/test/test-store + libs/gamecode/test/test-store \ + libs/gamecode/test/test-unsigned \ + libs/gamecode/test/test-vector TESTS += $(libs_gamecode_tests) @@ -57,3 +58,8 @@ libs_gamecode_test_test_vector_SOURCES= \ libs/gamecode/test/test-vector.c libs_gamecode_test_test_vector_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_vector_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_unsigned_SOURCES= \ + libs/gamecode/test/test-unsigned.c +libs_gamecode_test_test_unsigned_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_unsigned_DEPENDENCIES= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-unsigned.c b/libs/gamecode/test/test-unsigned.c new file mode 100644 index 000000000..ffd3959eb --- /dev/null +++ b/libs/gamecode/test/test-unsigned.c @@ -0,0 +1,284 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_uivec4_t uint_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_uivec4_t uint_cmpop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, // no unsigned EQ (redundant) + { 0, 0, -1, 0}, + { 0, -1, 0, 0}, + { 0, 0, 0, 0}, // no unsigned NE (redundant) + { -1, -1, 0, -1}, + { -1, 0, -1, -1}, +}; + +static dstatement_t uint_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_u_1), 0, 4, 16 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_u_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t uint_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_u_2), 0, 4, 16 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_2), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_u_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t uint_cmpop_3a_statements[] = { + // no unsigned EQ (redundant) + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_u_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_GT_u_3), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_u_1), 3, 7, 19 }, + // no unsigned NE (redundant) + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_3), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_u_1), 3, 7, 27 }, + { OP(1, 1, 1, OP_LE_u_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_u_1), 3, 7, 31 }, +}; + +static dstatement_t uint_cmpop_3b_statements[] = { + // no unsigned EQ (redundant) + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_LT_u_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_GT_u_1), 0, 4, 16 }, + { OP(1, 1, 1, OP_GT_u_3), 1, 5, 17 }, + // no unsigned NE (redundant) + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_1), 0, 4, 24 }, + { OP(1, 1, 1, OP_GE_u_3), 1, 5, 25 }, + { OP(1, 1, 1, OP_LE_u_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_LE_u_3), 1, 5, 29 }, +}; + +static dstatement_t uint_cmpop_4_statements[] = { + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_u_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_GT_u_4), 0, 4, 16 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_u_4), 0, 4, 24 }, + { OP(1, 1, 1, OP_LE_u_4), 0, 4, 28 }, +}; + +static pr_ulvec4_t ulong_cmpop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ulvec4_t ulong_cmpop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + { 0, 0, 0, 0}, // no unsigned EQ (redundant) + { 0, 0, -1, 0}, + { 0, -1, 0, 0}, + { 0, 0, 0, 0}, // no unsigned NE (redundant) + { -1, -1, 0, -1}, + { -1, 0, -1, -1}, +}; + +static dstatement_t ulong_cmpop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_U_1), 0, 8, 32 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_U_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t ulong_cmpop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_U_2), 0, 8, 32 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_2), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_U_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t ulong_cmpop_3a_statements[] = { + // no unsigned EQ (redundant) + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_U_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_GT_U_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_U_1), 6, 14, 38 }, + // no unsigned NE (redundant) + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_3), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_U_1), 6, 14, 54 }, + { OP(1, 1, 1, OP_LE_U_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_U_1), 6, 14, 62 }, +}; + +static dstatement_t ulong_cmpop_3b_statements[] = { + // no unsigned EQ (redundant) + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_LT_U_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_GT_U_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_GT_U_3), 2, 10, 34 }, + // no unsigned NE (redundant) + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_1), 0, 8, 48 }, + { OP(1, 1, 1, OP_GE_U_3), 2, 10, 50 }, + { OP(1, 1, 1, OP_LE_U_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_LE_U_3), 2, 10, 58 }, +}; + +static dstatement_t ulong_cmpop_4_statements[] = { + // no unsigned EQ (redundant) + { OP(1, 1, 1, OP_LT_U_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_GT_U_4), 0, 8, 32 }, + // no unsigned NE (redundant) + { OP(1, 1, 1, OP_GE_U_4), 0, 8, 48 }, + { OP(1, 1, 1, OP_LE_U_4), 0, 8, 56 }, +}; + +test_t tests[] = { + { + .desc = "uint cmpop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_1_statements), + .statements = uint_cmpop_1_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "uint cmpop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_2_statements), + .statements = uint_cmpop_2_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "uint cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_3a_statements), + .statements = uint_cmpop_3a_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "uint cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_3b_statements), + .statements = uint_cmpop_3b_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "uint cmpop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_statements = num_statements (uint_cmpop_4_statements), + .statements = uint_cmpop_4_statements, + .init_globals = (pr_int_t *) uint_cmpop_init, + .expect_globals = (pr_int_t *) uint_cmpop_expect, + }, + { + .desc = "ulong cmpop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_1_statements), + .statements = ulong_cmpop_1_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, + { + .desc = "ulong cmpop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_2_statements), + .statements = ulong_cmpop_2_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, + { + .desc = "ulong cmpop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_3a_statements), + .statements = ulong_cmpop_3a_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, + { + .desc = "ulong cmpop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_3b_statements), + .statements = ulong_cmpop_3b_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, + { + .desc = "ulong cmpop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_statements = num_statements (ulong_cmpop_4_statements), + .statements = ulong_cmpop_4_statements, + .init_globals = (pr_int_t *) ulong_cmpop_init, + .expect_globals = (pr_int_t *) ulong_cmpop_expect, + }, +}; + +#include "main.c" From f7181a09b439cb9f9acb20d87e4e9ef4d37e3c37 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Jan 2022 10:24:59 +0900 Subject: [PATCH 2160/3664] [gamecode] Add tests for shiftops They're in test-unsigned because 2/3 of them are unsigned. --- libs/gamecode/test/test-unsigned.c | 288 +++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) diff --git a/libs/gamecode/test/test-unsigned.c b/libs/gamecode/test/test-unsigned.c index ffd3959eb..298ed5c26 100644 --- a/libs/gamecode/test/test-unsigned.c +++ b/libs/gamecode/test/test-unsigned.c @@ -188,6 +188,204 @@ static dstatement_t ulong_cmpop_4_statements[] = { { OP(1, 1, 1, OP_LE_U_4), 0, 8, 56 }, }; +static pr_uivec4_t uint_shiftop_init[] = { + { 0x12345678, 0x9abcdef0, 0x80000001, 0xaaaa5555 }, + { 12, 16, 9, 1 }, + { 20, 16, 23, 31 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +static pr_uivec4_t uint_shiftop_expect[] = { + { 0x12345678, 0x9abcdef0, 0x80000001, 0xaaaa5555 }, + { 12, 16, 9, 1 },//a + { 20, 16, 23, 31 },//b + { 0x45678000, 0xdef00000, 0x00000200, 0x5554aaaa },//shl a + { 0x67800000, 0xdef00000, 0x00800000, 0x80000000 },//shl b + { 0x00012345, 0x00009abc, 0x00400000, 0x55552aaa },//shr a + { 0x00000123, 0x00009abc, 0x00000100, 0x00000001 },//shr b + { 0x00012345, 0xffff9abc, 0xffc00000, 0xd5552aaa },//asr a + { 0x00000123, 0xffff9abc, 0xffffff00, 0xffffffff },//asr b +}; + +static dstatement_t uint_shiftop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 36 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 36, -1, 36 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 36 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 36, 1 }, + { OP(1, 1, 1, OP_SHL_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHR_u_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_ASR_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t uint_shiftop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 36 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 36, -2, 36 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 36 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 36, 1 }, + { OP(1, 1, 1, OP_SHL_I_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHR_u_2), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_ASR_I_2), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_2), 0, 8, 32 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t uint_shiftop_3a_statements[] = { + { OP(1, 1, 1, OP_SHL_I_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_1), 3, 7, 15 }, + { OP(1, 1, 1, OP_SHL_I_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHL_I_1), 3, 11, 19 }, + { OP(1, 1, 1, OP_SHR_u_3), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_1), 3, 7, 23 }, + { OP(1, 1, 1, OP_SHR_u_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHR_u_1), 3, 11, 27 }, + { OP(1, 1, 1, OP_ASR_I_3), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_1), 3, 7, 31 }, + { OP(1, 1, 1, OP_ASR_I_3), 0, 8, 32 }, + { OP(1, 1, 1, OP_ASR_I_1), 3, 11, 35 }, +}; + +static dstatement_t uint_shiftop_3b_statements[] = { + { OP(1, 1, 1, OP_SHL_I_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_3), 1, 5, 13 }, + { OP(1, 1, 1, OP_SHL_I_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHL_I_3), 1, 9, 17 }, + { OP(1, 1, 1, OP_SHR_u_1), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_3), 1, 5, 21 }, + { OP(1, 1, 1, OP_SHR_u_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHR_u_3), 1, 9, 25 }, + { OP(1, 1, 1, OP_ASR_I_1), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_3), 1, 5, 29 }, + { OP(1, 1, 1, OP_ASR_I_1), 0, 8, 32 }, + { OP(1, 1, 1, OP_ASR_I_3), 1, 9, 33 }, +}; + +static dstatement_t uint_shiftop_4_statements[] = { + { OP(1, 1, 1, OP_SHL_I_4), 0, 4, 12 }, + { OP(1, 1, 1, OP_SHL_I_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_SHR_u_4), 0, 4, 20 }, + { OP(1, 1, 1, OP_SHR_u_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_ASR_I_4), 0, 4, 28 }, + { OP(1, 1, 1, OP_ASR_I_4), 0, 8, 32 }, +}; + +static pr_ulvec4_t ulong_shiftop_init[] = { + { UINT64_C(0x123456789abcdef0), UINT64_C(0x9abcdef012345678), + UINT64_C(0x8000000180000001), UINT64_C(0xaaaa5555aaaa5555) }, + { 12, 16, 9, 1 }, + { 52, 48, 55, 63 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +static pr_ulvec4_t ulong_shiftop_expect[] = { + { UINT64_C(0x123456789abcdef0), UINT64_C(0x9abcdef012345678), + UINT64_C(0x8000000180000001), UINT64_C(0xaaaa5555aaaa5555) }, + { 12, 16, 9, 1 },//a + { 52, 48, 55, 63 },//b + { UINT64_C(0x456789abcdef0000), UINT64_C(0xdef0123456780000), + UINT64_C(0x0000030000000200), UINT64_C(0x5554aaab5554aaaa) },//shl a + { UINT64_C(0xef00000000000000), UINT64_C(0x5678000000000000), + UINT64_C(0x0020000000000000), UINT64_C(0x8000000000000000) },//shl b + { UINT64_C(0x000123456789abcd), UINT64_C(0x00009abcdef01234), + UINT64_C(0x0040000000c00000), UINT64_C(0x55552aaad5552aaa) },//shr a + { UINT64_C(0x0000000000000123), UINT64_C(0x0000000000009abc), + UINT64_C(0x0000000000000100), UINT64_C(0x0000000000000001) },//shr b + { UINT64_C(0x000123456789abcd), UINT64_C(0xffff9abcdef01234), + UINT64_C(0xffc0000000c00000), UINT64_C(0xd5552aaad5552aaa) },//asr a + { UINT64_C(0x0000000000000123), UINT64_C(0xffffffffffff9abc), + UINT64_C(0xffffffffffffff00), UINT64_C(0xffffffffffffffff) },//asr b +}; + +static dstatement_t ulong_shiftop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 72 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 72, -2, 72 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 72 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 72, 1 }, + { OP(1, 1, 1, OP_SHL_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_1), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHR_U_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_1), 0, 16, 48 }, + { OP(1, 1, 1, OP_ASR_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_1), 0, 16, 64 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t ulong_shiftop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 72 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 72, -4, 72 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 72 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 72, 1 }, + { OP(1, 1, 1, OP_SHL_L_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_2), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHR_U_2), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_2), 0, 16, 48 }, + { OP(1, 1, 1, OP_ASR_L_2), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_2), 0, 16, 64 }, + { OP(1, 1, 1, OP_JUMP_A), -10, 0, 0 }, +}; + +static dstatement_t ulong_shiftop_3a_statements[] = { + { OP(1, 1, 1, OP_SHL_L_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_1), 6, 14, 30 }, + { OP(1, 1, 1, OP_SHL_L_3), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHL_L_1), 6, 22, 38 }, + { OP(1, 1, 1, OP_SHR_U_3), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_1), 6, 14, 46 }, + { OP(1, 1, 1, OP_SHR_U_3), 0, 16, 48 }, + { OP(1, 1, 1, OP_SHR_U_1), 6, 22, 54 }, + { OP(1, 1, 1, OP_ASR_L_3), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_1), 6, 14, 62 }, + { OP(1, 1, 1, OP_ASR_L_3), 0, 16, 64 }, + { OP(1, 1, 1, OP_ASR_L_1), 6, 22, 70 }, +}; + +static dstatement_t ulong_shiftop_3b_statements[] = { + { OP(1, 1, 1, OP_SHL_L_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_3), 2, 10, 26 }, + { OP(1, 1, 1, OP_SHL_L_1), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHL_L_3), 2, 18, 34 }, + { OP(1, 1, 1, OP_SHR_U_1), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_3), 2, 10, 42 }, + { OP(1, 1, 1, OP_SHR_U_1), 0, 16, 48 }, + { OP(1, 1, 1, OP_SHR_U_3), 2, 18, 50 }, + { OP(1, 1, 1, OP_ASR_L_1), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_3), 2, 10, 58 }, + { OP(1, 1, 1, OP_ASR_L_1), 0, 16, 64 }, + { OP(1, 1, 1, OP_ASR_L_3), 2, 18, 66 }, +}; + +static dstatement_t ulong_shiftop_4_statements[] = { + { OP(1, 1, 1, OP_SHL_L_4), 0, 8, 24 }, + { OP(1, 1, 1, OP_SHL_L_4), 0, 16, 32 }, + { OP(1, 1, 1, OP_SHR_U_4), 0, 8, 40 }, + { OP(1, 1, 1, OP_SHR_U_4), 0, 16, 48 }, + { OP(1, 1, 1, OP_ASR_L_4), 0, 8, 56 }, + { OP(1, 1, 1, OP_ASR_L_4), 0, 16, 64 }, +}; + test_t tests[] = { { .desc = "uint cmpop 1", @@ -279,6 +477,96 @@ test_t tests[] = { .init_globals = (pr_int_t *) ulong_cmpop_init, .expect_globals = (pr_int_t *) ulong_cmpop_expect, }, + { + .desc = "uint shiftop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_1_statements), + .statements = uint_shiftop_1_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "uint shiftop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_2_statements), + .statements = uint_shiftop_2_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "uint shiftop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_3a_statements), + .statements = uint_shiftop_3a_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "uint shiftop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_3b_statements), + .statements = uint_shiftop_3b_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "uint shiftop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_statements = num_statements (uint_shiftop_4_statements), + .statements = uint_shiftop_4_statements, + .init_globals = (pr_int_t *) uint_shiftop_init, + .expect_globals = (pr_int_t *) uint_shiftop_expect, + }, + { + .desc = "ulong shiftop 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_1_statements), + .statements = ulong_shiftop_1_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, + { + .desc = "ulong shiftop 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_2_statements), + .statements = ulong_shiftop_2_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, + { + .desc = "ulong shiftop 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_3a_statements), + .statements = ulong_shiftop_3a_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, + { + .desc = "ulong shiftop 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_3b_statements), + .statements = ulong_shiftop_3b_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, + { + .desc = "ulong shiftop 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_statements = num_statements (ulong_shiftop_4_statements), + .statements = ulong_shiftop_4_statements, + .init_globals = (pr_int_t *) ulong_shiftop_init, + .expect_globals = (pr_int_t *) ulong_shiftop_expect, + }, }; #include "main.c" From 3587b13a4037694166025a81c66dec7122a5fe56 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jan 2022 17:01:14 +0900 Subject: [PATCH 2161/3664] [gamecode] Implement the conversion instructions Not all possibilities are supported because converting between int and uint, and long and ulong is essentially a no-op. However, thanks to Deek's suggestion, not only are all reasonable conversions available, conversions for all widths are available, so vector conversions are supported. The code for the conversions is generated. --- libs/gamecode/Makemodule.am | 9 ++++- libs/gamecode/convert.py | 66 +++++++++++++++++++++++++++++++++++++ libs/gamecode/pr_exec.c | 32 +++++++++++------- 3 files changed, 95 insertions(+), 12 deletions(-) create mode 100644 libs/gamecode/convert.py diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index e3c9b5441..ea9ae11b1 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -31,7 +31,10 @@ pr_opcode_src = \ ${pr_opcode_hinc} libs/gamecode/pr_opcode.lo: libs/gamecode/pr_opcode.c ${pr_opcode_src} -BUILT_SOURCES += $(pr_opcode_cinc) $(pr_opcode_hinc) +convert_py = $(srcdir)/libs/gamecode/convert.py +pr_convert_cinc = $(top_builddir)/libs/gamecode/pr_convert.cinc + +BUILT_SOURCES += $(pr_opcode_cinc) $(pr_opcode_hinc) $(pr_convert_cinc) $(pr_opcode_cinc): $(opcodes_py) $(V_PY)$(PYTHON) $(opcodes_py) table > $(pr_opcode_cinc).t && \ @@ -41,3 +44,7 @@ $(pr_opcode_hinc): $(opcodes_py) $(V_PY) mkdir -p `dirname $(pr_opcode_hinc)` &&\ $(PYTHON) $(opcodes_py) enum > $(pr_opcode_hinc).t && \ $(am__mv) $(pr_opcode_hinc).t $(pr_opcode_hinc) + +$(pr_convert_cinc): $(convert_py) + $(V_PY)$(PYTHON) $(convert_py) table > $(pr_convert_cinc).t && \ + $(am__mv) $(pr_convert_cinc).t $(pr_convert_cinc) diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py new file mode 100644 index 000000000..380a5526e --- /dev/null +++ b/libs/gamecode/convert.py @@ -0,0 +1,66 @@ +print("""// types are encoded as ubf where: +// u = 0: signed, u = 1: unsigned +// b = 0: 32-bit, b = 1: 64-bit +// f = 0: int, f = 1: float/double +// width is ww where: +// ww = 00: 1 component +// ww = 01: 2 components +// ww = 10: 3 components +// ww = 11: 4 components +// full conversion code is wwsssddd where: +// ww = width +// sss = src type +// ddd = dst type +// case values are in octal +""") +types = [ + "int", + "float", + "long", + "double", + "uint", + None, # no such thing as unsigned float + "ulong", + None, # no such thing as unsigned double +] +#does not include size (2 or 4, 3 is special) +vec_types = [ + "ivec", + "vec", + "lvec", + "dvec", + "uivec", + None, # no such thing as unsigned float + "ulvec", + None, # no such thing as unsigned double +] +skip_matrix = [ + #i f l d ui X ul X + [1, 0, 0, 0, 1, 1, 0, 1], # i + [0, 1, 0, 0, 0, 1, 0, 1], # f + [0, 0, 1, 0, 0, 1, 1, 1], # l + [0, 0, 0, 1, 0, 1, 0, 1], # d + + [1, 0, 0, 0, 1, 1, 0, 1], # ui + [1, 1, 1, 1, 1, 1, 1, 1], # X + [0, 0, 1, 0, 0, 1, 1, 1], # ul + [1, 1, 1, 1, 1, 1, 1, 1], # X +] +for width in range(4): + for src_type in range(8): + for dst_type in range(8): + if skip_matrix[src_type][dst_type]: + continue + case = (width << 6) | (src_type << 3) | (dst_type) + if width == 0: + print(f"case {case:04o}: OPC({types[dst_type]}) = (pr_{types[dst_type]}_t) OPA({types[src_type]}); break;") + elif width == 2: + print(f"case {case:04o}: VectorCompUop(&OPC({types[dst_type]}), (pr_{types[dst_type]}_t), &OPA({types[src_type]})); break;") + else: + if (src_type & 2) == (dst_type & 2): + print(f"case {case:04o}: OPC({vec_types[dst_type]}{width+1}) = (pr_{vec_types[dst_type]}{width+1}_t) OPA({vec_types[src_type]}{width+1}); break;") + else: + print(f"case {case:04o}:") + for i in range(width + 1): + print(f"\t(&OPC({types[dst_type]}))[{i}] = (pr_{types[dst_type]}_t) (&OPA({types[src_type]}))[{i}];") + print(f"\tbreak;") diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 852f8f980..684205b80 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2915,6 +2915,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) pr->pr_xstatement = pr_jump_mode (pr, st); st = pr->pr_statements + pr->pr_xstatement; break; + // 0 0101 case OP_IFNZ_A: case OP_IFNZ_B: case OP_IFNZ_C: @@ -2972,9 +2973,17 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) PR_CallFunction (pr, function); st = pr->pr_statements + pr->pr_xstatement; break; - // 0 0101 - // nnn spare - //OP_CONV + // 0 0110 + // 0nnn spare + // 10nn spare + case OP_CONV: + switch (st->b) { +#include "libs/gamecode/pr_convert.cinc" + default: + PR_RunError (pr, "invalid conversion code: %04o", + st->b); + } + break; case OP_WITH: pr->pr_bases[st->c & 3] = pr_with (pr, st); break; @@ -3002,7 +3011,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) pr->pr_edict_area[think].func_var = op_b->func_var; } break; - // 0 0110 // 0 0111 case OP_CROSS_F: { @@ -3121,14 +3129,16 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) // 0 1010 OP_cmp(GT, >); // 0 1011 + // spare // 0 1100 OP_cmp(NE, !=); // 0 1101 OP_cmp(GE, >=); // 0 1110 OP_cmp(LE, <=); - // 0 1011 - //FIXME conversion 2 + + // 0 1111 + // spare #define OP_op_1(OP, T, t, op) \ case OP_##OP##_##T##_1: \ @@ -3311,9 +3321,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) //FIXME scale ops // 1 1010 OP_cmp_T (GT, u, int, ivec2, ivec4, >, uint, uivec2, uivec4); - //FIXME conversion ops + // spare OP_cmp_T (GT, U, long, lvec2, lvec4, >, ulong, ulvec2, ulvec4); - //FIXME conversion ops + // spare // 1 1011 case OP_LEA_A: case OP_LEA_B: @@ -3447,14 +3457,14 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_V4QMUL_F: OPC(vec4) = vqmulf (OPA(vec4), OPB(vec4)); break; - + // spare OP_cmp_T (LE, U, long, lvec2, lvec4, <=, ulong, ulvec2, ulvec4); case OP_V4QMUL_D: OPC(dvec4) = vqmuld (OPA(dvec4), OPB(dvec4)); break; - + // spare // 1 1111 - + // spare default: PR_RunError (pr, "Bad opcode o%03o", st->op & OP_MASK); } From 424bdcbf96481b9ee8980e5aa7b558f5608f9441 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Jan 2022 17:05:57 +0900 Subject: [PATCH 2162/3664] [gamecode] Implement the scale instructions Both float 2,3,4 vectors and double 2,3,4 vectors (1 would be just a copy of the mul instructions). This completes the currently planned instructions. Now for testing. --- libs/gamecode/pr_exec.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 684205b80..fda0763d9 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3313,12 +3313,28 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_SWIZZLE_F: OPC(ivec4) = pr_swizzle_f (OPA(ivec4), st->b); break; - //FIXME scale ops + case OP_SCALE_F_2: + OPC(vec2) = OPA(vec2) * OPB(float); + break; + case OP_SCALE_F_3: + VectorScale (&OPA(float), OPB(float), &OPC(float)); + break; + case OP_SCALE_F_4: + OPC(vec4) = OPA(vec4) * OPB(float); + break; OP_cmp_T (LT, U, long, lvec2, lvec4, <, ulong, ulvec2, ulvec4); case OP_SWIZZLE_D: OPC(lvec4) = pr_swizzle_d (OPA(lvec4), st->b); break; - //FIXME scale ops + case OP_SCALE_D_2: + OPC(dvec2) = OPA(dvec2) * OPB(double); + break; + case OP_SCALE_D_3: + VectorScale (&OPA(double), OPB(double), &OPC(double)); + break; + case OP_SCALE_D_4: + OPC(dvec4) = OPA(dvec4) * OPB(double); + break; // 1 1010 OP_cmp_T (GT, u, int, ivec2, ivec4, >, uint, uivec2, uivec4); // spare From 6f6f47e27e1454116398430e3b25c8a86690eec9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 13 Jan 2022 14:24:11 +0900 Subject: [PATCH 2163/3664] [gamecode] Drop bool ops in favor of long bit ops I realized that being able to do bit-wise operations with 64-bit values (and 256-bit vectors) is far more important than some convenient boolean logic operators. The logic ops can be handled via the bit-wise ops so long as the values are all properly boolean, and I plan on adding some boolean conversion ope, so no real loss. --- libs/gamecode/opcodes.py | 27 +++++---------------------- libs/gamecode/pr_exec.c | 39 ++++----------------------------------- 2 files changed, 9 insertions(+), 57 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 94c115492..0596636c7 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -20,7 +20,6 @@ bitmap_txt = """ 1 011r tuss shiftops 1 0110 o1oo string 1 1ccc t0ss compare2 -1 1000 ooss bitops 1 1001 t1ss scale 1 1001 t100 swizzle 1 1010 d1xx @@ -35,7 +34,7 @@ bitmap_txt = """ 1 1101 11oo memset 1 1110 d1xx 1 11dd t100 vecops2 -1 1100 ooss boolops +1 1t00 ooss bitops n 1111 nnnn 0 1011 nnnn """ @@ -77,14 +76,16 @@ any_formats = { "types": "ev_integer, ev_integer, ev_integer", } bitops_formats = { - "opcode": "OP_{op_bit[oo].upper()}_I_{ss+1}", + "opcode": "OP_{op_bit[oo].upper()}_{bit_type[t]}_{ss+1}", "mnemonic": "{op_bit[oo]}", "opname": "{op_bit[oo]}", "format": "{bit_fmt[oo]}", "widths": "{ss+1}, {ss+1}, {ss+1}", - "types": "ev_integer, ev_integer, ev_integer", + "types": "{bit_types[t]}, {bit_types[t]}, {bit_types[t]}", "args": { "op_bit": ["bitand", "bitor", "bitxor", "bitnot"], + "bit_type": ["I", "L"], + "bit_types": ["ev_integer", "ev_long"], "bit_fmt": [ "%Ga, %Gb, %gc", "%Ga, %Gb, %gc", @@ -93,23 +94,6 @@ bitops_formats = { ], }, } -boolops_formats = { - "opcode": "OP_{op_bool[oo].upper()}_I_{ss+1}", - "mnemonic": "{op_bool[oo]}", - "opname": "{op_bool[oo]}", - "format": "{bool_fmt[oo]}", - "widths": "{ss+1}, {ss+1}, {ss+1}", - "types": "ev_integer, ev_integer, ev_integer", - "args": { - "op_bool": ["and", "or", "xor", "not"], - "bool_fmt": [ - "%Ga, %Gb, %gc", - "%Ga, %Gb, %gc", - "%Ga, %Gb, %gc", - "%Ga, %gc", - ], - }, -} branch_formats = { "opcode": "OP_{op_cond[ccc].upper()}_{op_mode[mm]}", "mnemonic": "{op_cond[ccc]}", @@ -471,7 +455,6 @@ group_map = { "all": all_formats, "any": any_formats, "bitops": bitops_formats, - "boolops": boolops_formats, "branch": branch_formats, "call": call_formats, "compare": compare_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index fda0763d9..86903f7eb 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3403,42 +3403,11 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OPC(int) = none4i (OPA(ivec4)); break; -#define OP_bool_n(OP, t, n, op, m) \ - case OP_##OP##_I_##n: \ - OPC(t) = m((OPA(t) != 0) op (OPB(t) != 0)); \ - break -#define OP_bool_3(OP, t, n, op, m) \ - case OP_##OP##_I_##n: \ - { \ - __auto_type a = loadvec3i (&OPA(int)); \ - __auto_type b = loadvec3i (&OPB(int)); \ - storevec3i (&OPC(int), (a != 0) op (b != 0)); \ - } \ - break -#define OP_bool(OP, op) \ - OP_bool_n (OP, int, 1, op, -); \ - OP_bool_n (OP, ivec2, 2, op, +); \ - OP_bool_3 (OP, int, 3, op, +); \ - OP_bool_n (OP, ivec4, 4, op, +) -#define OP_not_n(OP, t, n, m) \ - case OP_##OP##_I_##n: \ - OPC(t) = m((OPA(t) == 0)); \ - break -#define OP_not_3(OP, t, n, m) \ - case OP_##OP##_I_##n: \ - { \ - __auto_type a = loadvec3i (&OPA(int)); \ - storevec3i (&OPC(int), (a == 0)); \ - } \ - break // 1 1100 - OP_bool (AND, &); - OP_bool (OR, |); - OP_bool (XOR, ^); - OP_not_n (NOT, int, 1, -); - OP_not_n (NOT, ivec2, 2, +); - OP_not_3 (NOT, int, 3, +); - OP_not_n (NOT, ivec4, 4, +); + OP_op_T (BITAND, L, long, lvec2, lvec4, &); + OP_op_T (BITOR, L, long, lvec2, lvec4, |); + OP_op_T (BITXOR, L, long, lvec2, lvec4, ^); + OP_uop_T (BITNOT, L, long, lvec2, lvec4, ~); // 1 1101 OP_cmp_T (GE, u, int, ivec2, ivec4, >=, uint, uivec2, uivec4); case OP_QV4MUL_F: From 3eb2194343a69f7010c985df74bbc821745d04d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 13 Jan 2022 15:58:12 +0900 Subject: [PATCH 2164/3664] [gamecode] Invert the meaning of the skip matrix Rather than specifying that the conversion should be skipped, it now specifies the mode of the conversions (with 0 being no conversion). This is in preparation for boolean conversion. --- libs/gamecode/convert.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index 380a5526e..c3bade9f3 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -34,22 +34,23 @@ vec_types = [ "ulvec", None, # no such thing as unsigned double ] -skip_matrix = [ +convert_matrix = [ #i f l d ui X ul X - [1, 0, 0, 0, 1, 1, 0, 1], # i - [0, 1, 0, 0, 0, 1, 0, 1], # f - [0, 0, 1, 0, 0, 1, 1, 1], # l - [0, 0, 0, 1, 0, 1, 0, 1], # d + [0, 1, 1, 1, 0, 0, 1, 0], # i + [1, 0, 1, 1, 1, 0, 1, 0], # f + [1, 1, 0, 1, 1, 0, 0, 0], # l + [1, 1, 1, 0, 1, 0, 1, 0], # d - [1, 0, 0, 0, 1, 1, 0, 1], # ui - [1, 1, 1, 1, 1, 1, 1, 1], # X - [0, 0, 1, 0, 0, 1, 1, 1], # ul - [1, 1, 1, 1, 1, 1, 1, 1], # X + [0, 1, 1, 1, 0, 0, 1, 0], # ui + [0, 0, 0, 0, 0, 0, 0, 0], # X + [1, 1, 0, 1, 1, 0, 0, 0], # ul + [0, 0, 0, 0, 0, 0, 0, 0], # X ] for width in range(4): for src_type in range(8): for dst_type in range(8): - if skip_matrix[src_type][dst_type]: + mode = convert_matrix[src_type][dst_type] + if not mode: continue case = (width << 6) | (src_type << 3) | (dst_type) if width == 0: From ba1d73200fb0c1d795de3c699b954be779a7786f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 13 Jan 2022 16:10:06 +0900 Subject: [PATCH 2165/3664] [gamecode] Clean up a pile of duplicate code All those duplicated formats were getting unwieldy, especially as I want to add more conversion modes. --- libs/gamecode/convert.py | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index c3bade9f3..f3ef5375a 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -46,22 +46,48 @@ convert_matrix = [ [1, 1, 0, 1, 1, 0, 0, 0], # ul [0, 0, 0, 0, 0, 0, 0, 0], # X ] + +def case_str(width, src_type, dst_type): + case = (width << 6) | (src_type << 3) | (dst_type) + return f"case {case:04o}:" + +def cast_str(width, src_type, dst_type): + if width & 1 and (src_type & 2) == (dst_type & 2): + return f"(pr_{vec_types[dst_type]}{width+1}_t)" + else: + return f"(pr_{types[dst_type]}_t)" + +def src_str(width, src_type, dst_type): + if width & 1 and (src_type & 2) == (dst_type & 2): + return f"OPA({vec_types[src_type]}{width+1})" + else: + return f"OPA({types[src_type]})" + +def dst_str(width, src_type, dst_type): + if width & 1 and (src_type & 2) == (dst_type & 2): + return f"OPC({vec_types[dst_type]}{width+1})" + else: + return f"OPC({types[dst_type]})" + for width in range(4): for src_type in range(8): for dst_type in range(8): mode = convert_matrix[src_type][dst_type] if not mode: continue - case = (width << 6) | (src_type << 3) | (dst_type) + case = case_str(width, src_type, dst_type) + cast = cast_str(width, src_type, dst_type) + src = src_str(width, src_type, dst_type) + dst = dst_str(width, src_type, dst_type) if width == 0: - print(f"case {case:04o}: OPC({types[dst_type]}) = (pr_{types[dst_type]}_t) OPA({types[src_type]}); break;") + print(f"{case} {dst} = {cast} {src}; break;") elif width == 2: - print(f"case {case:04o}: VectorCompUop(&OPC({types[dst_type]}), (pr_{types[dst_type]}_t), &OPA({types[src_type]})); break;") + print(f"{case} VectorCompUop(&{dst}, {cast}, &{src}); break;") else: if (src_type & 2) == (dst_type & 2): - print(f"case {case:04o}: OPC({vec_types[dst_type]}{width+1}) = (pr_{vec_types[dst_type]}{width+1}_t) OPA({vec_types[src_type]}{width+1}); break;") + print(f"{case} {dst} = {cast} {src}; break;") else: - print(f"case {case:04o}:") + print(f"{case}") for i in range(width + 1): - print(f"\t(&OPC({types[dst_type]}))[{i}] = (pr_{types[dst_type]}_t) (&OPA({types[src_type]}))[{i}];") + print(f"\t(&{dst})[{i}] = {cast} (&{src})[{i}];") print(f"\tbreak;") From e8e0a6962873c285b05e196c8f52c9b4b64ea642 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 13 Jan 2022 17:37:44 +0900 Subject: [PATCH 2166/3664] [gamecode] Add conversions to/from bool For now, from bool results in 0/1, but conversion to bool guarantees 0/-1 and correct interpretations for floating point types. --- libs/gamecode/convert.py | 84 +++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 23 deletions(-) diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index f3ef5375a..eb8fd2c39 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -2,6 +2,7 @@ print("""// types are encoded as ubf where: // u = 0: signed, u = 1: unsigned // b = 0: 32-bit, b = 1: 64-bit // f = 0: int, f = 1: float/double +// unsigned float/double is interpreted as bool // width is ww where: // ww = 00: 1 component // ww = 01: 2 components @@ -19,9 +20,9 @@ types = [ "long", "double", "uint", - None, # no such thing as unsigned float + "int", # 32-bit bool "ulong", - None, # no such thing as unsigned double + "long", # 64-bit bool ] #does not include size (2 or 4, 3 is special) vec_types = [ @@ -30,21 +31,21 @@ vec_types = [ "lvec", "dvec", "uivec", - None, # no such thing as unsigned float + "ivec", # 32-bit bool "ulvec", - None, # no such thing as unsigned double + "lvec", # 64-bit bool ] convert_matrix = [ - #i f l d ui X ul X - [0, 1, 1, 1, 0, 0, 1, 0], # i - [1, 0, 1, 1, 1, 0, 1, 0], # f - [1, 1, 0, 1, 1, 0, 0, 0], # l - [1, 1, 1, 0, 1, 0, 1, 0], # d + #i f l d ui b ul B + [0, 1, 1, 1, 0, 3, 1, 3], # i + [1, 0, 1, 1, 1, 3, 1, 3], # f + [1, 1, 0, 1, 1, 3, 0, 3], # l + [1, 1, 1, 0, 1, 3, 1, 3], # d - [0, 1, 1, 1, 0, 0, 1, 0], # ui - [0, 0, 0, 0, 0, 0, 0, 0], # X - [1, 1, 0, 1, 1, 0, 0, 0], # ul - [0, 0, 0, 0, 0, 0, 0, 0], # X + [0, 1, 1, 1, 0, 3, 1, 3], # ui + [2, 2, 2, 2, 2, 0, 2, 1], # 32-bit bool + [1, 1, 0, 1, 1, 3, 0, 3], # ul + [2, 2, 2, 2, 2, 1, 2, 0], # 64-bit bool ] def case_str(width, src_type, dst_type): @@ -69,6 +70,14 @@ def dst_str(width, src_type, dst_type): else: return f"OPC({types[dst_type]})" +def zero_str(width, src_type): + ones = "{%s}" % (", ".join(["0"] * (width + 1))) + return f"{cast_str(width, src_type, src_type)} {ones}" + +def one_str(width, src_type): + ones = "{%s}" % (", ".join(["1"] * (width + 1))) + return f"{cast_str(width, src_type, src_type)} {ones}" + for width in range(4): for src_type in range(8): for dst_type in range(8): @@ -79,15 +88,44 @@ for width in range(4): cast = cast_str(width, src_type, dst_type) src = src_str(width, src_type, dst_type) dst = dst_str(width, src_type, dst_type) - if width == 0: - print(f"{case} {dst} = {cast} {src}; break;") - elif width == 2: - print(f"{case} VectorCompUop(&{dst}, {cast}, &{src}); break;") - else: - if (src_type & 2) == (dst_type & 2): + if mode == 1: + if width == 0: print(f"{case} {dst} = {cast} {src}; break;") + elif width == 2: + print(f"{case} VectorCompUop(&{dst},{cast},&{src}); break;") else: - print(f"{case}") - for i in range(width + 1): - print(f"\t(&{dst})[{i}] = {cast} (&{src})[{i}];") - print(f"\tbreak;") + if (src_type & 2) == (dst_type & 2): + print(f"{case} {dst} = {cast} {src}; break;") + else: + print(f"{case}") + for i in range(width + 1): + print(f"\t(&{dst})[{i}] = {cast} (&{src})[{i}];") + print(f"\tbreak;") + elif mode == 2: + one = one_str(width, src_type) + if width == 0: + print(f"{case} {dst} = !!{src}; break;") + elif width == 2: + print(f"{case} VectorCompUop(&{dst},!!,&{src}); break;") + else: + if (src_type & 2) == (dst_type & 2): + print(f"{case} {dst} = {cast} ({src} & {one}); break;") + else: + print(f"{case}") + for i in range(width + 1): + print(f"\t(&{dst})[{i}] = !!(&{src})[{i}];") + print(f"\tbreak;") + elif mode == 3: + zero = zero_str(width, src_type) + if width == 0: + print(f"{case} {dst} = -!!{src}; break;") + elif width == 2: + print(f"{case} VectorCompUop(&{dst},-!!,&{src}); break;") + else: + if (src_type & 2) == (dst_type & 2): + print(f"{case} {dst} = {src} != {zero}; break;") + else: + print(f"{case}") + for i in range(width + 1): + print(f"\t(&{dst})[{i}] = -!!(&{src})[{i}];") + print(f"\tbreak;") From cd68455e469ce7155acb3d500f69b773a7249e9f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 11:24:01 +0900 Subject: [PATCH 2167/3664] [gamecode] Add tests for converting to int They currently fail because for vector values, gcc casts the view, not the value, so vec4 cast to ivec4 simply views the bits as int rather than doing the actual conversion. --- libs/gamecode/test/Makemodule.am | 6 ++ libs/gamecode/test/test-conv0.c | 176 +++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 libs/gamecode/test/test-conv0.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index af16fe67f..dc5e6dabd 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,4 +1,5 @@ libs_gamecode_tests = \ + libs/gamecode/test/test-conv0 \ libs/gamecode/test/test-double \ libs/gamecode/test/test-float \ libs/gamecode/test/test-int \ @@ -19,6 +20,11 @@ test_gamecode_libs= \ libs/gamecode/libQFgamecode.la \ libs/util/libQFutil.la +libs_gamecode_test_test_conv0_SOURCES= \ + libs/gamecode/test/test-conv0.c +libs_gamecode_test_test_conv0_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv0_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_double_SOURCES= \ libs/gamecode/test/test-double.c libs_gamecode_test_test_double_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-conv0.c b/libs/gamecode/test/test-conv0.c new file mode 100644 index 000000000..e6d6b6ad7 --- /dev/null +++ b/libs/gamecode/test/test-conv0.c @@ -0,0 +1,176 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t int_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t int_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, // int + { 1, -1, 0x80000000, 0x80000000}, // float + { 99, 0x80000000, 256, 0x7fffffff}, // long + { 0x80000000, 0x80000000, 1, -1}, // double + { 0, 0, 0, 0}, // uint + { 1, 1, 1, 0}, // bool32 + { 99, 0x80000000, 256, 0x7fffffff}, // ulong + { 1, 1, 1, 0}, // bool64 +}; + +static dstatement_t int_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 4, 0010, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0020, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0030, 60 }, + { OP(1, 1, 1, OP_CONV), 28, 0050, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0060, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0070, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -12, 0, 0 }, +}; + +static dstatement_t int_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 4, 0110, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0120, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0130, 60 }, + { OP(1, 1, 1, OP_CONV), 28, 0150, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0160, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0170, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -12, 0, 0 }, +}; + +static dstatement_t int_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 4, 0210, 52 }, + { OP(1, 1, 1, OP_CONV), 7, 0010, 55 }, + { OP(2, 1, 1, OP_CONV), 8, 0220, 56 }, + { OP(2, 1, 1, OP_CONV), 14, 0020, 59 }, + { OP(2, 1, 1, OP_CONV), 16, 0230, 60 }, + { OP(2, 1, 1, OP_CONV), 22, 0030, 63 }, + { OP(1, 1, 1, OP_CONV), 28, 0250, 68 }, + { OP(1, 1, 1, OP_CONV), 31, 0050, 71 }, + { OP(2, 1, 1, OP_CONV), 32, 0260, 72 }, + { OP(2, 1, 1, OP_CONV), 38, 0060, 75 }, + { OP(2, 1, 1, OP_CONV), 40, 0270, 76 }, + { OP(2, 1, 1, OP_CONV), 46, 0070, 79 }, +}; + +static dstatement_t int_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 4, 0010, 52 }, + { OP(1, 1, 1, OP_CONV), 5, 0210, 53 }, + { OP(2, 1, 1, OP_CONV), 8, 0020, 56 }, + { OP(2, 1, 1, OP_CONV), 10, 0220, 57 }, + { OP(2, 1, 1, OP_CONV), 16, 0030, 60 }, + { OP(2, 1, 1, OP_CONV), 18, 0230, 61 }, + { OP(1, 1, 1, OP_CONV), 28, 0050, 68 }, + { OP(1, 1, 1, OP_CONV), 29, 0250, 69 }, + { OP(2, 1, 1, OP_CONV), 32, 0060, 72 }, + { OP(2, 1, 1, OP_CONV), 34, 0260, 73 }, + { OP(2, 1, 1, OP_CONV), 40, 0070, 76 }, + { OP(2, 1, 1, OP_CONV), 42, 0270, 77 }, +}; + +static dstatement_t int_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 4, 0310, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0320, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0330, 60 }, + { OP(1, 1, 1, OP_CONV), 28, 0350, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0360, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0370, 76 }, +}; + +test_t tests[] = { + { + .desc = "int conv 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_1_statements), + .statements = int_conv_1_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, + { + .desc = "int conv 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_2_statements), + .statements = int_conv_2_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, + { + .desc = "int conv 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_3a_statements), + .statements = int_conv_3a_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, + { + .desc = "int conv 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_3b_statements), + .statements = int_conv_3b_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, + { + .desc = "int conv 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_statements = num_statements (int_conv_4_statements), + .statements = int_conv_4_statements, + .init_globals = (pr_int_t *) int_conv_init, + .expect_globals = (pr_int_t *) int_conv_expect, + }, +}; + +#include "main.c" From e26fb49df73e867fcac32de7957603ca9a6464bb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 11:57:43 +0900 Subject: [PATCH 2168/3664] [gamecode] Get conversion to int working for all types Bools turned out to be a problem to due to me wanting any non-zero value to be treated as true thus had to expand them out as well as the floating point <-> integral conversions. --- libs/gamecode/convert.py | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index eb8fd2c39..1a050b6a9 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -53,19 +53,19 @@ def case_str(width, src_type, dst_type): return f"case {case:04o}:" def cast_str(width, src_type, dst_type): - if width & 1 and (src_type & 2) == (dst_type & 2): + if width & 1: return f"(pr_{vec_types[dst_type]}{width+1}_t)" else: return f"(pr_{types[dst_type]}_t)" def src_str(width, src_type, dst_type): - if width & 1 and (src_type & 2) == (dst_type & 2): + if width & 1: return f"OPA({vec_types[src_type]}{width+1})" else: return f"OPA({types[src_type]})" def dst_str(width, src_type, dst_type): - if width & 1 and (src_type & 2) == (dst_type & 2): + if width & 1: return f"OPC({vec_types[dst_type]}{width+1})" else: return f"OPC({types[dst_type]})" @@ -78,6 +78,10 @@ def one_str(width, src_type): ones = "{%s}" % (", ".join(["1"] * (width + 1))) return f"{cast_str(width, src_type, src_type)} {ones}" +def expand_str(width, src, pref=""): + src = [f"{pref}{src}[{i}]" for i in range(width + 1)] + return "{%s}" % (", ".join(src)); + for width in range(4): for src_type in range(8): for dst_type in range(8): @@ -94,13 +98,8 @@ for width in range(4): elif width == 2: print(f"{case} VectorCompUop(&{dst},{cast},&{src}); break;") else: - if (src_type & 2) == (dst_type & 2): - print(f"{case} {dst} = {cast} {src}; break;") - else: - print(f"{case}") - for i in range(width + 1): - print(f"\t(&{dst})[{i}] = {cast} (&{src})[{i}];") - print(f"\tbreak;") + expand = expand_str(width, src) + print(f"{case} {dst} = {cast} {expand}; break;") elif mode == 2: one = one_str(width, src_type) if width == 0: @@ -108,13 +107,8 @@ for width in range(4): elif width == 2: print(f"{case} VectorCompUop(&{dst},!!,&{src}); break;") else: - if (src_type & 2) == (dst_type & 2): - print(f"{case} {dst} = {cast} ({src} & {one}); break;") - else: - print(f"{case}") - for i in range(width + 1): - print(f"\t(&{dst})[{i}] = !!(&{src})[{i}];") - print(f"\tbreak;") + expand = expand_str(width, src, "!!") + print(f"{case} {dst} = {cast} {expand}; break;") elif mode == 3: zero = zero_str(width, src_type) if width == 0: @@ -122,10 +116,5 @@ for width in range(4): elif width == 2: print(f"{case} VectorCompUop(&{dst},-!!,&{src}); break;") else: - if (src_type & 2) == (dst_type & 2): - print(f"{case} {dst} = {src} != {zero}; break;") - else: - print(f"{case}") - for i in range(width + 1): - print(f"\t(&{dst})[{i}] = -!!(&{src})[{i}];") - print(f"\tbreak;") + expand = expand_str(width, src, "-!!") + print(f"{case} {dst} = {cast} {expand}; break;") From 4bf934e6b965b3bcea59e577a8ac5a1d082ada2d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 13:38:05 +0900 Subject: [PATCH 2169/3664] [gamecode] Correct incorrect bool64-bool32 conversion And add tests for float, uint and bool32 conversions. --- libs/gamecode/convert.py | 2 +- libs/gamecode/test/Makemodule.am | 18 +++ libs/gamecode/test/test-conv1.c | 183 +++++++++++++++++++++++++++++++ libs/gamecode/test/test-conv4.c | 178 ++++++++++++++++++++++++++++++ libs/gamecode/test/test-conv5.c | 183 +++++++++++++++++++++++++++++++ 5 files changed, 563 insertions(+), 1 deletion(-) create mode 100644 libs/gamecode/test/test-conv1.c create mode 100644 libs/gamecode/test/test-conv4.c create mode 100644 libs/gamecode/test/test-conv5.c diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index 1a050b6a9..39b407d17 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -45,7 +45,7 @@ convert_matrix = [ [0, 1, 1, 1, 0, 3, 1, 3], # ui [2, 2, 2, 2, 2, 0, 2, 1], # 32-bit bool [1, 1, 0, 1, 1, 3, 0, 3], # ul - [2, 2, 2, 2, 2, 1, 2, 0], # 64-bit bool + [2, 2, 2, 2, 2, 3, 2, 0], # 64-bit bool ] def case_str(width, src_type, dst_type): diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index dc5e6dabd..100873937 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,5 +1,8 @@ libs_gamecode_tests = \ libs/gamecode/test/test-conv0 \ + libs/gamecode/test/test-conv1 \ + libs/gamecode/test/test-conv4 \ + libs/gamecode/test/test-conv5 \ libs/gamecode/test/test-double \ libs/gamecode/test/test-float \ libs/gamecode/test/test-int \ @@ -25,6 +28,21 @@ libs_gamecode_test_test_conv0_SOURCES= \ libs_gamecode_test_test_conv0_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_conv0_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_conv1_SOURCES= \ + libs/gamecode/test/test-conv1.c +libs_gamecode_test_test_conv1_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv1_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv4_SOURCES= \ + libs/gamecode/test/test-conv4.c +libs_gamecode_test_test_conv4_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv4_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv5_SOURCES= \ + libs/gamecode/test/test-conv5.c +libs_gamecode_test_test_conv5_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv5_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_double_SOURCES= \ libs/gamecode/test/test-double.c libs_gamecode_test_test_double_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-conv1.c b/libs/gamecode/test/test-conv1.c new file mode 100644 index 000000000..541aa6788 --- /dev/null +++ b/libs/gamecode/test/test-conv1.c @@ -0,0 +1,183 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t float_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t float_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0x40a00000, 0xc0a00000, 0xcf000000, 0x4f000000}, // int + { 0, 0, 0, 0}, // float + { 0xdf000000, 0x52c70000, 0x43800000, 0x4f000000}, // long + { 0x7149f2ca, 0xf149f2ca, 0x3fc00000, 0xbfc00000}, // double + { 0x40a00000, 0x4f800000, 0x4f000000, 0x4f000000}, // uint + { 0x3f800000, 0x3f800000, 0x3f800000, 0}, // bool32 + { 0x5f000000, 0x52c70000, 0x43800000, 0x4f000000}, // ulong + { 0x3f800000, 0x3f800000, 0x3f800000, 0}, // bool64 +}; + +static dstatement_t float_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0001, 48 }, + { OP(2, 1, 1, OP_CONV), 8, 0021, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0031, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0041, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0051, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0061, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0071, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -13, 0, 0 }, +}; + +static dstatement_t float_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0101, 48 }, + { OP(2, 1, 1, OP_CONV), 8, 0121, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0131, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0141, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0151, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0161, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0171, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -13, 0, 0 }, +}; + +static dstatement_t float_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0201, 48 }, + { OP(1, 1, 1, OP_CONV), 3, 0001, 51 }, + { OP(2, 1, 1, OP_CONV), 8, 0221, 56 }, + { OP(2, 1, 1, OP_CONV), 14, 0021, 59 }, + { OP(2, 1, 1, OP_CONV), 16, 0231, 60 }, + { OP(2, 1, 1, OP_CONV), 22, 0031, 63 }, + { OP(1, 1, 1, OP_CONV), 24, 0241, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0041, 67 }, + { OP(1, 1, 1, OP_CONV), 28, 0251, 68 }, + { OP(1, 1, 1, OP_CONV), 31, 0051, 71 }, + { OP(2, 1, 1, OP_CONV), 32, 0261, 72 }, + { OP(2, 1, 1, OP_CONV), 38, 0061, 75 }, + { OP(2, 1, 1, OP_CONV), 40, 0271, 76 }, + { OP(2, 1, 1, OP_CONV), 46, 0071, 79 }, +}; + +static dstatement_t float_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0001, 48 }, + { OP(1, 1, 1, OP_CONV), 1, 0201, 49 }, + { OP(2, 1, 1, OP_CONV), 8, 0021, 56 }, + { OP(2, 1, 1, OP_CONV), 10, 0221, 57 }, + { OP(2, 1, 1, OP_CONV), 16, 0031, 60 }, + { OP(2, 1, 1, OP_CONV), 18, 0231, 61 }, + { OP(1, 1, 1, OP_CONV), 24, 0241, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0041, 67 }, + { OP(1, 1, 1, OP_CONV), 28, 0051, 68 }, + { OP(1, 1, 1, OP_CONV), 29, 0251, 69 }, + { OP(2, 1, 1, OP_CONV), 32, 0061, 72 }, + { OP(2, 1, 1, OP_CONV), 34, 0261, 73 }, + { OP(2, 1, 1, OP_CONV), 40, 0071, 76 }, + { OP(2, 1, 1, OP_CONV), 42, 0271, 77 }, +}; + +static dstatement_t float_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0301, 48 }, + { OP(2, 1, 1, OP_CONV), 8, 0321, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0331, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0341, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0351, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0361, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0371, 76 }, +}; + +test_t tests[] = { + { + .desc = "float conv 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_1_statements), + .statements = float_conv_1_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, + { + .desc = "float conv 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_2_statements), + .statements = float_conv_2_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, + { + .desc = "float conv 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_3a_statements), + .statements = float_conv_3a_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, + { + .desc = "float conv 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_3b_statements), + .statements = float_conv_3b_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, + { + .desc = "float conv 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_statements = num_statements (float_conv_4_statements), + .statements = float_conv_4_statements, + .init_globals = (pr_int_t *) float_conv_init, + .expect_globals = (pr_int_t *) float_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c new file mode 100644 index 000000000..4accd2ee8 --- /dev/null +++ b/libs/gamecode/test/test-conv4.c @@ -0,0 +1,178 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t uint_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t uint_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, // int + // why 0? expected 0xfffffff. vv gcc bug? + { 1, 0xffffffff, 0, 0}, // float + { 99, 0x80000000, 256, 0x7fffffff}, // long + // why 0? vv expected 0xfffffff. gcc bug? + { 0, 0, 1, 0xffffffff}, // double + { 0, 0, 0, 0}, // uint + { 1, 1, 1, 0}, // bool32 + { 99, 0x80000000, 256, 0x7fffffff}, // ulong + { 1, 1, 1, 0}, // bool64 +}; + +static dstatement_t uint_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 4, 0014, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0024, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0034, 60 }, + { OP(1, 1, 1, OP_CONV), 28, 0054, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0064, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0074, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -12, 0, 0 }, +}; + +static dstatement_t uint_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 4, 0114, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0124, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0134, 60 }, + { OP(1, 1, 1, OP_CONV), 28, 0154, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0164, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0174, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -12, 0, 0 }, +}; + +static dstatement_t uint_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 4, 0214, 52 }, + { OP(1, 1, 1, OP_CONV), 7, 0014, 55 }, + { OP(2, 1, 1, OP_CONV), 8, 0224, 56 }, + { OP(2, 1, 1, OP_CONV), 14, 0024, 59 }, + { OP(2, 1, 1, OP_CONV), 16, 0234, 60 }, + { OP(2, 1, 1, OP_CONV), 22, 0034, 63 }, + { OP(1, 1, 1, OP_CONV), 28, 0254, 68 }, + { OP(1, 1, 1, OP_CONV), 31, 0054, 71 }, + { OP(2, 1, 1, OP_CONV), 32, 0264, 72 }, + { OP(2, 1, 1, OP_CONV), 38, 0064, 75 }, + { OP(2, 1, 1, OP_CONV), 40, 0274, 76 }, + { OP(2, 1, 1, OP_CONV), 46, 0074, 79 }, +}; + +static dstatement_t uint_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 4, 0014, 52 }, + { OP(1, 1, 1, OP_CONV), 5, 0214, 53 }, + { OP(2, 1, 1, OP_CONV), 8, 0024, 56 }, + { OP(2, 1, 1, OP_CONV), 10, 0224, 57 }, + { OP(2, 1, 1, OP_CONV), 16, 0034, 60 }, + { OP(2, 1, 1, OP_CONV), 18, 0234, 61 }, + { OP(1, 1, 1, OP_CONV), 28, 0054, 68 }, + { OP(1, 1, 1, OP_CONV), 29, 0254, 69 }, + { OP(2, 1, 1, OP_CONV), 32, 0064, 72 }, + { OP(2, 1, 1, OP_CONV), 34, 0264, 73 }, + { OP(2, 1, 1, OP_CONV), 40, 0074, 76 }, + { OP(2, 1, 1, OP_CONV), 42, 0274, 77 }, +}; + +static dstatement_t uint_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 4, 0314, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0324, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0334, 60 }, + { OP(1, 1, 1, OP_CONV), 28, 0354, 68 }, + { OP(2, 1, 1, OP_CONV), 32, 0364, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0374, 76 }, +}; + +test_t tests[] = { + { + .desc = "uint conv 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_1_statements), + .statements = uint_conv_1_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, + { + .desc = "uint conv 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_2_statements), + .statements = uint_conv_2_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, + { + .desc = "uint conv 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_3a_statements), + .statements = uint_conv_3a_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, + { + .desc = "uint conv 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_3b_statements), + .statements = uint_conv_3b_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, + { + .desc = "uint conv 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_statements = num_statements (uint_conv_4_statements), + .statements = uint_conv_4_statements, + .init_globals = (pr_int_t *) uint_conv_init, + .expect_globals = (pr_int_t *) uint_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv5.c b/libs/gamecode/test/test-conv5.c new file mode 100644 index 000000000..2a1d92a46 --- /dev/null +++ b/libs/gamecode/test/test-conv5.c @@ -0,0 +1,183 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t bool32_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t bool32_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { -1, -1, -1, -1}, // int + { -1, -1, -1, -1}, // float + { -1, -1, -1, -1}, // long + { -1, -1, -1, -1}, // double + { -1, -1, -1, -1}, // uint + { 0, 0, 0, 0}, // bool32 + { -1, -1, -1, -1}, // ulong + { -1, -1, -1, 0}, // bool64 +}; + +static dstatement_t bool32_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0005, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0015, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0025, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0035, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0045, 64 }, + { OP(2, 1, 1, OP_CONV), 32, 0065, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0075, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -13, 0, 0 }, +}; + +static dstatement_t bool32_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 80 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 81 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0105, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0115, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0125, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0135, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0145, 64 }, + { OP(2, 1, 1, OP_CONV), 32, 0165, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0175, 76 }, + { OP(1, 1, 1, OP_JUMP_A), -13, 0, 0 }, +}; + +static dstatement_t bool32_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0205, 48 }, + { OP(1, 1, 1, OP_CONV), 3, 0005, 51 }, + { OP(1, 1, 1, OP_CONV), 4, 0215, 52 }, + { OP(1, 1, 1, OP_CONV), 7, 0015, 55 }, + { OP(2, 1, 1, OP_CONV), 8, 0225, 56 }, + { OP(2, 1, 1, OP_CONV), 14, 0025, 59 }, + { OP(2, 1, 1, OP_CONV), 16, 0235, 60 }, + { OP(2, 1, 1, OP_CONV), 22, 0035, 63 }, + { OP(1, 1, 1, OP_CONV), 24, 0245, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0045, 67 }, + { OP(2, 1, 1, OP_CONV), 32, 0265, 72 }, + { OP(2, 1, 1, OP_CONV), 38, 0065, 75 }, + { OP(2, 1, 1, OP_CONV), 40, 0275, 76 }, + { OP(2, 1, 1, OP_CONV), 46, 0075, 79 }, +}; + +static dstatement_t bool32_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0005, 48 }, + { OP(1, 1, 1, OP_CONV), 1, 0205, 49 }, + { OP(1, 1, 1, OP_CONV), 4, 0015, 52 }, + { OP(1, 1, 1, OP_CONV), 5, 0215, 53 }, + { OP(2, 1, 1, OP_CONV), 8, 0025, 56 }, + { OP(2, 1, 1, OP_CONV), 10, 0225, 57 }, + { OP(2, 1, 1, OP_CONV), 16, 0035, 60 }, + { OP(2, 1, 1, OP_CONV), 18, 0235, 61 }, + { OP(1, 1, 1, OP_CONV), 24, 0045, 64 }, + { OP(1, 1, 1, OP_CONV), 25, 0245, 65 }, + { OP(2, 1, 1, OP_CONV), 32, 0065, 72 }, + { OP(2, 1, 1, OP_CONV), 34, 0265, 73 }, + { OP(2, 1, 1, OP_CONV), 40, 0075, 76 }, + { OP(2, 1, 1, OP_CONV), 42, 0275, 77 }, +}; + +static dstatement_t bool32_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0305, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0315, 52 }, + { OP(2, 1, 1, OP_CONV), 8, 0325, 56 }, + { OP(2, 1, 1, OP_CONV), 16, 0335, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0345, 64 }, + { OP(2, 1, 1, OP_CONV), 32, 0365, 72 }, + { OP(2, 1, 1, OP_CONV), 40, 0375, 76 }, +}; + +test_t tests[] = { + { + .desc = "bool32 conv 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_1_statements), + .statements = bool32_conv_1_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, + { + .desc = "bool32 conv 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_2_statements), + .statements = bool32_conv_2_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, + { + .desc = "bool32 conv 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_3a_statements), + .statements = bool32_conv_3a_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, + { + .desc = "bool32 conv 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_3b_statements), + .statements = bool32_conv_3b_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, + { + .desc = "bool32 conv 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_statements = num_statements (bool32_conv_4_statements), + .statements = bool32_conv_4_statements, + .init_globals = (pr_int_t *) bool32_conv_init, + .expect_globals = (pr_int_t *) bool32_conv_expect, + }, +}; + +#include "main.c" From 1f73b26d24b07c3bf7fb950ffaf5399ca0ce947a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 14:54:35 +0900 Subject: [PATCH 2170/3664] [gamecode] Correct incorrect bool32-bool64 conversion And add tests for long, ulong and bool64 conversions. --- libs/gamecode/convert.py | 2 +- libs/gamecode/test/Makemodule.am | 18 +++ libs/gamecode/test/test-conv2.c | 192 +++++++++++++++++++++++++++++ libs/gamecode/test/test-conv6.c | 192 +++++++++++++++++++++++++++++ libs/gamecode/test/test-conv7.c | 199 +++++++++++++++++++++++++++++++ 5 files changed, 602 insertions(+), 1 deletion(-) create mode 100644 libs/gamecode/test/test-conv2.c create mode 100644 libs/gamecode/test/test-conv6.c create mode 100644 libs/gamecode/test/test-conv7.c diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index 39b407d17..dc4b36674 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -43,7 +43,7 @@ convert_matrix = [ [1, 1, 1, 0, 1, 3, 1, 3], # d [0, 1, 1, 1, 0, 3, 1, 3], # ui - [2, 2, 2, 2, 2, 0, 2, 1], # 32-bit bool + [2, 2, 2, 2, 2, 0, 2, 3], # 32-bit bool [1, 1, 0, 1, 1, 3, 0, 3], # ul [2, 2, 2, 2, 2, 3, 2, 0], # 64-bit bool ] diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 100873937..560425a5e 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,8 +1,11 @@ libs_gamecode_tests = \ libs/gamecode/test/test-conv0 \ libs/gamecode/test/test-conv1 \ + libs/gamecode/test/test-conv2 \ libs/gamecode/test/test-conv4 \ libs/gamecode/test/test-conv5 \ + libs/gamecode/test/test-conv6 \ + libs/gamecode/test/test-conv7 \ libs/gamecode/test/test-double \ libs/gamecode/test/test-float \ libs/gamecode/test/test-int \ @@ -33,6 +36,11 @@ libs_gamecode_test_test_conv1_SOURCES= \ libs_gamecode_test_test_conv1_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_conv1_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_conv2_SOURCES= \ + libs/gamecode/test/test-conv2.c +libs_gamecode_test_test_conv2_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv2_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_conv4_SOURCES= \ libs/gamecode/test/test-conv4.c libs_gamecode_test_test_conv4_LDADD= $(test_gamecode_libs) @@ -43,6 +51,16 @@ libs_gamecode_test_test_conv5_SOURCES= \ libs_gamecode_test_test_conv5_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_conv5_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_conv6_SOURCES= \ + libs/gamecode/test/test-conv6.c +libs_gamecode_test_test_conv6_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv6_DEPENDENCIES= $(test_gamecode_libs) + +libs_gamecode_test_test_conv7_SOURCES= \ + libs/gamecode/test/test-conv7.c +libs_gamecode_test_test_conv7_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv7_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_double_SOURCES= \ libs/gamecode/test/test-double.c libs_gamecode_test_test_double_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-conv2.c b/libs/gamecode/test/test-conv2.c new file mode 100644 index 000000000..654dd4c90 --- /dev/null +++ b/libs/gamecode/test/test-conv2.c @@ -0,0 +1,192 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t long_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t long_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 5, 0, -5, 0xffffffff}, // int + { 0x80000000, 0xffffffff, 0x7fffffff, 0}, + { 1, 0, -1, -1}, // float + { 0, 0x80000000, 0, 0x80000000}, + { 0, 0, 0, 0}, // long + { 0, 0, 0, 0}, + { 0, 0x80000000, 0, 0x80000000}, // double + { 1, 0, -1, -1}, + { 5, 0, -5, 0}, // uint + { 0x80000000, 0, 0x7fffffff, 0}, + { 1, 0, 1, 0}, // bool32 + { 1, 0, 0, 0}, + { 0, 0, 0, 0}, // ulong + { 0, 0, 0, 0}, + { 1, 0, 1, 0}, // bool64 + { 1, 0, 0, 0}, +}; + +static dstatement_t long_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0002, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0012, 56 }, + { OP(2, 1, 2, OP_CONV), 16, 0032, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0042, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0052, 88 }, + { OP(2, 1, 2, OP_CONV), 40, 0072, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -12, 0, 0 }, +}; + +static dstatement_t long_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0102, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0112, 56 }, + { OP(2, 1, 2, OP_CONV), 16, 0132, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0142, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0152, 88 }, + { OP(2, 1, 2, OP_CONV), 40, 0172, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -12, 0, 0 }, +}; + +static dstatement_t long_conv_3a_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0202, 48 }, + { OP(1, 1, 2, OP_CONV), 3, 0002, 54 }, + { OP(1, 1, 2, OP_CONV), 4, 0212, 56 }, + { OP(1, 1, 2, OP_CONV), 7, 0012, 62 }, + { OP(2, 1, 2, OP_CONV), 16, 0232, 72 }, + { OP(2, 1, 2, OP_CONV), 22, 0032, 78 }, + { OP(1, 1, 2, OP_CONV), 24, 0242, 80 }, + { OP(1, 1, 2, OP_CONV), 27, 0042, 86 }, + { OP(1, 1, 2, OP_CONV), 28, 0252, 88 }, + { OP(1, 1, 2, OP_CONV), 31, 0052, 94 }, + { OP(2, 1, 2, OP_CONV), 40, 0272, 104 }, + { OP(2, 1, 2, OP_CONV), 46, 0072, 110 }, +}; + +static dstatement_t long_conv_3b_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0002, 48 }, + { OP(1, 1, 2, OP_CONV), 1, 0202, 50 }, + { OP(1, 1, 2, OP_CONV), 4, 0012, 56 }, + { OP(1, 1, 2, OP_CONV), 5, 0212, 58 }, + { OP(2, 1, 2, OP_CONV), 16, 0032, 72 }, + { OP(2, 1, 2, OP_CONV), 18, 0232, 74 }, + { OP(1, 1, 2, OP_CONV), 24, 0042, 80 }, + { OP(1, 1, 2, OP_CONV), 25, 0242, 82 }, + { OP(1, 1, 2, OP_CONV), 28, 0052, 88 }, + { OP(1, 1, 2, OP_CONV), 29, 0252, 90 }, + { OP(2, 1, 2, OP_CONV), 40, 0072, 104 }, + { OP(2, 1, 2, OP_CONV), 42, 0272, 106 }, +}; + +static dstatement_t long_conv_4_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0302, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0312, 56 }, + { OP(2, 1, 2, OP_CONV), 16, 0332, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0342, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0352, 88 }, + { OP(2, 1, 2, OP_CONV), 40, 0372, 104 }, +}; + +test_t tests[] = { + { + .desc = "long conv 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_1_statements), + .statements = long_conv_1_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, + { + .desc = "long conv 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_2_statements), + .statements = long_conv_2_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, + { + .desc = "long conv 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_3a_statements), + .statements = long_conv_3a_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, + { + .desc = "long conv 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_3b_statements), + .statements = long_conv_3b_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, + { + .desc = "long conv 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_statements = num_statements (long_conv_4_statements), + .statements = long_conv_4_statements, + .init_globals = (pr_int_t *) long_conv_init, + .expect_globals = (pr_int_t *) long_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c new file mode 100644 index 000000000..a5d4f7881 --- /dev/null +++ b/libs/gamecode/test/test-conv6.c @@ -0,0 +1,192 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t ulong_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t ulong_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 5, 0, -5, 0xffffffff}, // int + { 0x80000000, 0xffffffff, 0x7fffffff, 0}, + { 1, 0, -1, -1}, // float + { 0, 0, 0, 0x80000000}, + { 0, 0, 0, 0}, // long + { 0, 0, 0, 0}, + { 0, 0, 0, 0x80000000}, // double + { 1, 0, -1, -1}, + { 5, 0, -5, 0}, // uint + { 0x80000000, 0, 0x7fffffff, 0}, + { 1, 0, 1, 0}, // bool32 + { 1, 0, 0, 0}, + { 0, 0, 0, 0}, // ulong + { 0, 0, 0, 0}, + { 1, 0, 1, 0}, // bool64 + { 1, 0, 0, 0}, +}; + +static dstatement_t ulong_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0006, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0016, 56 }, + { OP(2, 1, 2, OP_CONV), 16, 0036, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0046, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0056, 88 }, + { OP(2, 1, 2, OP_CONV), 40, 0076, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -12, 0, 0 }, +}; + +static dstatement_t ulong_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0106, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0116, 56 }, + { OP(2, 1, 2, OP_CONV), 16, 0136, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0146, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0156, 88 }, + { OP(2, 1, 2, OP_CONV), 40, 0176, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -12, 0, 0 }, +}; + +static dstatement_t ulong_conv_3a_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0206, 48 }, + { OP(1, 1, 2, OP_CONV), 3, 0006, 54 }, + { OP(1, 1, 2, OP_CONV), 4, 0216, 56 }, + { OP(1, 1, 2, OP_CONV), 7, 0016, 62 }, + { OP(2, 1, 2, OP_CONV), 16, 0236, 72 }, + { OP(2, 1, 2, OP_CONV), 22, 0036, 78 }, + { OP(1, 1, 2, OP_CONV), 24, 0246, 80 }, + { OP(1, 1, 2, OP_CONV), 27, 0046, 86 }, + { OP(1, 1, 2, OP_CONV), 28, 0256, 88 }, + { OP(1, 1, 2, OP_CONV), 31, 0056, 94 }, + { OP(2, 1, 2, OP_CONV), 40, 0276, 104 }, + { OP(2, 1, 2, OP_CONV), 46, 0076, 110 }, +}; + +static dstatement_t ulong_conv_3b_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0006, 48 }, + { OP(1, 1, 2, OP_CONV), 1, 0206, 50 }, + { OP(1, 1, 2, OP_CONV), 4, 0016, 56 }, + { OP(1, 1, 2, OP_CONV), 5, 0216, 58 }, + { OP(2, 1, 2, OP_CONV), 16, 0036, 72 }, + { OP(2, 1, 2, OP_CONV), 18, 0236, 74 }, + { OP(1, 1, 2, OP_CONV), 24, 0046, 80 }, + { OP(1, 1, 2, OP_CONV), 25, 0246, 82 }, + { OP(1, 1, 2, OP_CONV), 28, 0056, 88 }, + { OP(1, 1, 2, OP_CONV), 29, 0256, 90 }, + { OP(2, 1, 2, OP_CONV), 40, 0076, 104 }, + { OP(2, 1, 2, OP_CONV), 42, 0276, 106 }, +}; + +static dstatement_t ulong_conv_4_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0306, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0316, 56 }, + { OP(2, 1, 2, OP_CONV), 16, 0336, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0346, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0356, 88 }, + { OP(2, 1, 2, OP_CONV), 40, 0376, 104 }, +}; + +test_t tests[] = { + { + .desc = "ulong conv 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_1_statements), + .statements = ulong_conv_1_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, + { + .desc = "ulong conv 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_2_statements), + .statements = ulong_conv_2_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, + { + .desc = "ulong conv 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_3a_statements), + .statements = ulong_conv_3a_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, + { + .desc = "ulong conv 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_3b_statements), + .statements = ulong_conv_3b_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, + { + .desc = "ulong conv 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_statements = num_statements (ulong_conv_4_statements), + .statements = ulong_conv_4_statements, + .init_globals = (pr_int_t *) ulong_conv_init, + .expect_globals = (pr_int_t *) ulong_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv7.c b/libs/gamecode/test/test-conv7.c new file mode 100644 index 000000000..78e3a44df --- /dev/null +++ b/libs/gamecode/test/test-conv7.c @@ -0,0 +1,199 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t bool64_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t bool64_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // int + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // float + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // long + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // double + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // uint + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // bool32 + { 0xffffffff, 0xffffffff, 0, 0}, + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // ulong + { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, + { 0, 0, 0, 0}, // bool64 + { 0, 0, 0, 0}, +}; + +static dstatement_t bool64_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0007, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0017, 56 }, + { OP(1, 1, 2, OP_CONV), 8, 0027, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0037, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0047, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0057, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0067, 96 }, + { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, +}; + +static dstatement_t bool64_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0107, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0117, 56 }, + { OP(1, 1, 2, OP_CONV), 8, 0127, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0137, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0147, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0157, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0167, 96 }, + { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, +}; + +static dstatement_t bool64_conv_3a_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0207, 48 }, + { OP(1, 1, 2, OP_CONV), 3, 0007, 54 }, + { OP(1, 1, 2, OP_CONV), 4, 0217, 56 }, + { OP(1, 1, 2, OP_CONV), 7, 0017, 62 }, + { OP(1, 1, 2, OP_CONV), 8, 0227, 64 }, + { OP(1, 1, 2, OP_CONV), 14, 0027, 70 }, + { OP(2, 1, 2, OP_CONV), 16, 0237, 72 }, + { OP(2, 1, 2, OP_CONV), 22, 0037, 78 }, + { OP(1, 1, 2, OP_CONV), 24, 0247, 80 }, + { OP(1, 1, 2, OP_CONV), 27, 0047, 86 }, + { OP(1, 1, 2, OP_CONV), 28, 0257, 88 }, + { OP(1, 1, 2, OP_CONV), 31, 0057, 94 }, + { OP(2, 1, 2, OP_CONV), 32, 0267, 96 }, + { OP(2, 1, 2, OP_CONV), 38, 0067, 102 }, +}; + +static dstatement_t bool64_conv_3b_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0007, 48 }, + { OP(1, 1, 2, OP_CONV), 1, 0207, 50 }, + { OP(1, 1, 2, OP_CONV), 4, 0017, 56 }, + { OP(1, 1, 2, OP_CONV), 5, 0217, 58 }, + { OP(1, 1, 2, OP_CONV), 8, 0027, 64 }, + { OP(1, 1, 2, OP_CONV), 10, 0227, 66 }, + { OP(2, 1, 2, OP_CONV), 16, 0037, 72 }, + { OP(2, 1, 2, OP_CONV), 18, 0237, 74 }, + { OP(1, 1, 2, OP_CONV), 24, 0047, 80 }, + { OP(1, 1, 2, OP_CONV), 25, 0247, 82 }, + { OP(1, 1, 2, OP_CONV), 28, 0057, 88 }, + { OP(1, 1, 2, OP_CONV), 29, 0257, 90 }, + { OP(2, 1, 2, OP_CONV), 32, 0067, 96 }, + { OP(2, 1, 2, OP_CONV), 34, 0267, 98 }, +}; + +static dstatement_t bool64_conv_4_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0307, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0317, 56 }, + { OP(1, 1, 2, OP_CONV), 8, 0327, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0337, 72 }, + { OP(1, 1, 2, OP_CONV), 24, 0347, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0357, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0367, 96 }, +}; + +test_t tests[] = { + { + .desc = "bool64 conv 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_1_statements), + .statements = bool64_conv_1_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, + { + .desc = "bool64 conv 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_2_statements), + .statements = bool64_conv_2_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, + { + .desc = "bool64 conv 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_3a_statements), + .statements = bool64_conv_3a_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, + { + .desc = "bool64 conv 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_3b_statements), + .statements = bool64_conv_3b_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, + { + .desc = "bool64 conv 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_statements = num_statements (bool64_conv_4_statements), + .statements = bool64_conv_4_statements, + .init_globals = (pr_int_t *) bool64_conv_init, + .expect_globals = (pr_int_t *) bool64_conv_expect, + }, +}; + +#include "main.c" From a1c1c9fcf0043048e6b53d4b0ab37100ec6537ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 15:51:49 +0900 Subject: [PATCH 2171/3664] [gamecode] Add test for conversions to double And fix an incorrect base index in the bool64 tests. --- libs/gamecode/test/Makemodule.am | 6 + libs/gamecode/test/test-conv3.c | 199 +++++++++++++++++++++++++++++++ libs/gamecode/test/test-conv7.c | 14 +-- 3 files changed, 212 insertions(+), 7 deletions(-) create mode 100644 libs/gamecode/test/test-conv3.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 560425a5e..a878155d1 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -2,6 +2,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-conv0 \ libs/gamecode/test/test-conv1 \ libs/gamecode/test/test-conv2 \ + libs/gamecode/test/test-conv3 \ libs/gamecode/test/test-conv4 \ libs/gamecode/test/test-conv5 \ libs/gamecode/test/test-conv6 \ @@ -41,6 +42,11 @@ libs_gamecode_test_test_conv2_SOURCES= \ libs_gamecode_test_test_conv2_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_conv2_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_conv3_SOURCES= \ + libs/gamecode/test/test-conv3.c +libs_gamecode_test_test_conv3_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_conv3_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_conv4_SOURCES= \ libs/gamecode/test/test-conv4.c libs_gamecode_test_test_conv4_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-conv3.c b/libs/gamecode/test/test-conv3.c new file mode 100644 index 000000000..e4fb1f03d --- /dev/null +++ b/libs/gamecode/test/test-conv3.c @@ -0,0 +1,199 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t double_conv_init[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t double_conv_expect[] = { + { 5, -5, 0x80000000, 0x7fffffff}, //int + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 99, 0x80000000, 0x80000000, 99}, //long + { 256, 0, 0x7fffffff, 0}, //long + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 5, -5, 0x80000000, 0x7fffffff}, //uint + { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong + { 256, 0, 0x7fffffff, 0}, //ulong + { ~0, ~0, ~0, 0}, //bool64 + { 0, ~0, 0, 0}, //bool64 + { 0x00000000, 0x40140000, 0x00000000, 0xc0140000}, // int + { 0x00000000, 0xc1e00000, 0xffc00000, 0x41dfffff}, + { 0x00000000, 0x3ff80000, 0x00000000, 0xbff80000}, // float + { 0x40000000, 0x46293e59, 0x40000000, 0xc6293e59}, + { 0x00000000, 0xc3e00000, 0x00000000, 0x4258e000}, // long + { 0x00000000, 0x40700000, 0xffc00000, 0x41dfffff}, + { 0, 0, 0, 0}, // double + { 0, 0, 0, 0}, + { 0x00000000, 0x40140000, 0xff600000, 0x41efffff}, // uint + { 0x00000000, 0x41e00000, 0xffc00000, 0x41dfffff}, + { 0x00000000, 0x3ff00000, 0x00000000, 0x3ff00000}, // bool32 + { 0x00000000, 0x3ff00000, 0x00000000, 0x00000000}, + { 0x00000000, 0x43e00000, 0x00000000, 0x4258e000}, // long + { 0x00000000, 0x40700000, 0xffc00000, 0x41dfffff}, + { 0x00000000, 0x3ff00000, 0x00000000, 0x3ff00000}, // bool64 + { 0x00000000, 0x3ff00000, 0x00000000, 0x00000000}, +}; + +static dstatement_t double_conv_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // init index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0003, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0013, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0023, 64 }, + { OP(1, 1, 2, OP_CONV), 24, 0043, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0053, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0063, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0073, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, +}; + +static dstatement_t double_conv_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 112 }, // index + { OP(0, 0, 0, OP_LEA_A), 8, 0, 113 }, // init index for 64-bits +//loop: + { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index + { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, + { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, + { OP(1, 1, 2, OP_CONV), 0, 0103, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0113, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0123, 64 }, + { OP(1, 1, 2, OP_CONV), 24, 0143, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0153, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0163, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0173, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, +}; + +static dstatement_t double_conv_3a_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0203, 48 }, + { OP(1, 1, 2, OP_CONV), 3, 0003, 54 }, + { OP(1, 1, 2, OP_CONV), 4, 0213, 56 }, + { OP(1, 1, 2, OP_CONV), 7, 0013, 62 }, + { OP(2, 1, 2, OP_CONV), 8, 0223, 64 }, + { OP(2, 1, 2, OP_CONV), 14, 0023, 70 }, + { OP(1, 1, 2, OP_CONV), 24, 0243, 80 }, + { OP(1, 1, 2, OP_CONV), 27, 0043, 86 }, + { OP(1, 1, 2, OP_CONV), 28, 0253, 88 }, + { OP(1, 1, 2, OP_CONV), 31, 0053, 94 }, + { OP(2, 1, 2, OP_CONV), 32, 0263, 96 }, + { OP(2, 1, 2, OP_CONV), 38, 0063, 102 }, + { OP(2, 1, 2, OP_CONV), 40, 0273, 104 }, + { OP(2, 1, 2, OP_CONV), 46, 0073, 110 }, +}; + +static dstatement_t double_conv_3b_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0003, 48 }, + { OP(1, 1, 2, OP_CONV), 1, 0203, 50 }, + { OP(1, 1, 2, OP_CONV), 4, 0013, 56 }, + { OP(1, 1, 2, OP_CONV), 5, 0213, 58 }, + { OP(2, 1, 2, OP_CONV), 8, 0023, 64 }, + { OP(2, 1, 2, OP_CONV), 10, 0223, 66 }, + { OP(1, 1, 2, OP_CONV), 24, 0043, 80 }, + { OP(1, 1, 2, OP_CONV), 25, 0243, 82 }, + { OP(1, 1, 2, OP_CONV), 28, 0053, 88 }, + { OP(1, 1, 2, OP_CONV), 29, 0253, 90 }, + { OP(2, 1, 2, OP_CONV), 32, 0063, 96 }, + { OP(2, 1, 2, OP_CONV), 34, 0263, 98 }, + { OP(2, 1, 2, OP_CONV), 40, 0073, 104 }, + { OP(2, 1, 2, OP_CONV), 42, 0273, 106 }, +}; + +static dstatement_t double_conv_4_statements[] = { + { OP(1, 1, 2, OP_CONV), 0, 0303, 48 }, + { OP(1, 1, 2, OP_CONV), 4, 0313, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0323, 64 }, + { OP(1, 1, 2, OP_CONV), 24, 0343, 80 }, + { OP(1, 1, 2, OP_CONV), 28, 0353, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0363, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0373, 104 }, +}; + +test_t tests[] = { + { + .desc = "double conv 1", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_1_statements), + .statements = double_conv_1_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, + { + .desc = "double conv 2", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_2_statements), + .statements = double_conv_2_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, + { + .desc = "double conv 3a", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_3a_statements), + .statements = double_conv_3a_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, + { + .desc = "double conv 3b", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_3b_statements), + .statements = double_conv_3b_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, + { + .desc = "double conv 4", + .extra_globals = 4 * 1, + .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_statements = num_statements (double_conv_4_statements), + .statements = double_conv_4_statements, + .init_globals = (pr_int_t *) double_conv_init, + .expect_globals = (pr_int_t *) double_conv_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-conv7.c b/libs/gamecode/test/test-conv7.c index 78e3a44df..1c6171db9 100644 --- a/libs/gamecode/test/test-conv7.c +++ b/libs/gamecode/test/test-conv7.c @@ -76,7 +76,7 @@ static dstatement_t bool64_conv_1_statements[] = { { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, { OP(1, 1, 2, OP_CONV), 0, 0007, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0017, 56 }, - { OP(1, 1, 2, OP_CONV), 8, 0027, 64 }, + { OP(2, 1, 2, OP_CONV), 8, 0027, 64 }, { OP(2, 1, 2, OP_CONV), 16, 0037, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0047, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0057, 88 }, @@ -96,7 +96,7 @@ static dstatement_t bool64_conv_2_statements[] = { { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, { OP(1, 1, 2, OP_CONV), 0, 0107, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0117, 56 }, - { OP(1, 1, 2, OP_CONV), 8, 0127, 64 }, + { OP(2, 1, 2, OP_CONV), 8, 0127, 64 }, { OP(2, 1, 2, OP_CONV), 16, 0137, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0147, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0157, 88 }, @@ -109,8 +109,8 @@ static dstatement_t bool64_conv_3a_statements[] = { { OP(1, 1, 2, OP_CONV), 3, 0007, 54 }, { OP(1, 1, 2, OP_CONV), 4, 0217, 56 }, { OP(1, 1, 2, OP_CONV), 7, 0017, 62 }, - { OP(1, 1, 2, OP_CONV), 8, 0227, 64 }, - { OP(1, 1, 2, OP_CONV), 14, 0027, 70 }, + { OP(2, 1, 2, OP_CONV), 8, 0227, 64 }, + { OP(2, 1, 2, OP_CONV), 14, 0027, 70 }, { OP(2, 1, 2, OP_CONV), 16, 0237, 72 }, { OP(2, 1, 2, OP_CONV), 22, 0037, 78 }, { OP(1, 1, 2, OP_CONV), 24, 0247, 80 }, @@ -126,8 +126,8 @@ static dstatement_t bool64_conv_3b_statements[] = { { OP(1, 1, 2, OP_CONV), 1, 0207, 50 }, { OP(1, 1, 2, OP_CONV), 4, 0017, 56 }, { OP(1, 1, 2, OP_CONV), 5, 0217, 58 }, - { OP(1, 1, 2, OP_CONV), 8, 0027, 64 }, - { OP(1, 1, 2, OP_CONV), 10, 0227, 66 }, + { OP(2, 1, 2, OP_CONV), 8, 0027, 64 }, + { OP(2, 1, 2, OP_CONV), 10, 0227, 66 }, { OP(2, 1, 2, OP_CONV), 16, 0037, 72 }, { OP(2, 1, 2, OP_CONV), 18, 0237, 74 }, { OP(1, 1, 2, OP_CONV), 24, 0047, 80 }, @@ -141,7 +141,7 @@ static dstatement_t bool64_conv_3b_statements[] = { static dstatement_t bool64_conv_4_statements[] = { { OP(1, 1, 2, OP_CONV), 0, 0307, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0317, 56 }, - { OP(1, 1, 2, OP_CONV), 8, 0327, 64 }, + { OP(2, 1, 2, OP_CONV), 8, 0327, 64 }, { OP(2, 1, 2, OP_CONV), 16, 0337, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0347, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0357, 88 }, From a81067603cde72701569d42c48efe3cda1e0594a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 16:52:44 +0900 Subject: [PATCH 2172/3664] [gamecode] Mention possibly undefined behavior It seems casting from float/double to [unsigned] int/long when the value doesn't fit is undefined (which would explain the inconsistent results). Mentioning the possibility seems like a good idea should the results for such casts change and cause the tests to fail. --- libs/gamecode/test/test-conv0.c | 4 ++-- libs/gamecode/test/test-conv2.c | 4 ++-- libs/gamecode/test/test-conv4.c | 6 ++---- libs/gamecode/test/test-conv6.c | 4 ++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libs/gamecode/test/test-conv0.c b/libs/gamecode/test/test-conv0.c index e6d6b6ad7..f8b0e7b03 100644 --- a/libs/gamecode/test/test-conv0.c +++ b/libs/gamecode/test/test-conv0.c @@ -39,9 +39,9 @@ static pr_ivec4_t int_conv_expect[] = { { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 { 0, 0, 0, 0}, // int - { 1, -1, 0x80000000, 0x80000000}, // float + { 1, -1, 0x80000000, 0x80000000}, // float undef? { 99, 0x80000000, 256, 0x7fffffff}, // long - { 0x80000000, 0x80000000, 1, -1}, // double + { 0x80000000, 0x80000000, 1, -1}, // double undef? { 0, 0, 0, 0}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong diff --git a/libs/gamecode/test/test-conv2.c b/libs/gamecode/test/test-conv2.c index 654dd4c90..ee87f7531 100644 --- a/libs/gamecode/test/test-conv2.c +++ b/libs/gamecode/test/test-conv2.c @@ -49,10 +49,10 @@ static pr_ivec4_t long_conv_expect[] = { { 5, 0, -5, 0xffffffff}, // int { 0x80000000, 0xffffffff, 0x7fffffff, 0}, { 1, 0, -1, -1}, // float - { 0, 0x80000000, 0, 0x80000000}, + { 0, 0x80000000, 0, 0x80000000}, // undef? { 0, 0, 0, 0}, // long { 0, 0, 0, 0}, - { 0, 0x80000000, 0, 0x80000000}, // double + { 0, 0x80000000, 0, 0x80000000}, // double undef? { 1, 0, -1, -1}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c index 4accd2ee8..8fc1ec846 100644 --- a/libs/gamecode/test/test-conv4.c +++ b/libs/gamecode/test/test-conv4.c @@ -39,11 +39,9 @@ static pr_ivec4_t uint_conv_expect[] = { { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 { 0, 0, 0, 0}, // int - // why 0? expected 0xfffffff. vv gcc bug? - { 1, 0xffffffff, 0, 0}, // float + { 1, 0xffffffff, 0, 0}, // float undef? { 99, 0x80000000, 256, 0x7fffffff}, // long - // why 0? vv expected 0xfffffff. gcc bug? - { 0, 0, 1, 0xffffffff}, // double + { 0, 0, 1, 0xffffffff}, // double undef? { 0, 0, 0, 0}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c index a5d4f7881..3e84eeb03 100644 --- a/libs/gamecode/test/test-conv6.c +++ b/libs/gamecode/test/test-conv6.c @@ -49,10 +49,10 @@ static pr_ivec4_t ulong_conv_expect[] = { { 5, 0, -5, 0xffffffff}, // int { 0x80000000, 0xffffffff, 0x7fffffff, 0}, { 1, 0, -1, -1}, // float - { 0, 0, 0, 0x80000000}, + { 0, 0, 0, 0x80000000}, // undef? { 0, 0, 0, 0}, // long { 0, 0, 0, 0}, - { 0, 0, 0, 0x80000000}, // double + { 0, 0, 0, 0x80000000}, // double undef? { 1, 0, -1, -1}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, From 1a2ac24d8db1a0e23478ac8fc313824e9e5cbe19 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 19:43:34 +0900 Subject: [PATCH 2173/3664] [gamecode] Make num_globals() calculate actual globals It calculating only the size of the array (which was often 4 or 8 globals per element) proved to be a pain when I forgot to alter the size for the new scale tests. Fixing the size calculation even found a bug in the shiftop tests. --- libs/gamecode/test/head.c | 4 ++- libs/gamecode/test/test-conv0.c | 10 +++---- libs/gamecode/test/test-conv1.c | 10 +++---- libs/gamecode/test/test-conv2.c | 10 +++---- libs/gamecode/test/test-conv3.c | 10 +++---- libs/gamecode/test/test-conv4.c | 10 +++---- libs/gamecode/test/test-conv5.c | 10 +++---- libs/gamecode/test/test-conv6.c | 10 +++---- libs/gamecode/test/test-conv7.c | 10 +++---- libs/gamecode/test/test-double.c | 22 ++++++++-------- libs/gamecode/test/test-float.c | 22 ++++++++-------- libs/gamecode/test/test-int.c | 20 +++++++------- libs/gamecode/test/test-long.c | 20 +++++++------- libs/gamecode/test/test-unsigned.c | 42 +++++++++++++++--------------- libs/gamecode/test/test-vector.c | 4 +-- 15 files changed, 108 insertions(+), 106 deletions(-) diff --git a/libs/gamecode/test/head.c b/libs/gamecode/test/head.c index c7db8fb26..36985c821 100644 --- a/libs/gamecode/test/head.c +++ b/libs/gamecode/test/head.c @@ -11,7 +11,9 @@ static int verbose = 0; // error if the sizes differ) #define num_globals(init, expect) \ __builtin_choose_expr ( \ - sizeof (init) == sizeof (expect), sizeof (init) / sizeof (init[0]), \ + sizeof (init) == sizeof (expect), \ + (sizeof (init) / sizeof (init[0])) \ + * (sizeof (init[0]) / sizeof (pr_type_t)), \ (void) 0\ ) diff --git a/libs/gamecode/test/test-conv0.c b/libs/gamecode/test/test-conv0.c index f8b0e7b03..bfa492225 100644 --- a/libs/gamecode/test/test-conv0.c +++ b/libs/gamecode/test/test-conv0.c @@ -129,7 +129,7 @@ test_t tests[] = { { .desc = "int conv 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_globals = num_globals(int_conv_init,int_conv_expect), .num_statements = num_statements (int_conv_1_statements), .statements = int_conv_1_statements, .init_globals = (pr_int_t *) int_conv_init, @@ -138,7 +138,7 @@ test_t tests[] = { { .desc = "int conv 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_globals = num_globals(int_conv_init,int_conv_expect), .num_statements = num_statements (int_conv_2_statements), .statements = int_conv_2_statements, .init_globals = (pr_int_t *) int_conv_init, @@ -147,7 +147,7 @@ test_t tests[] = { { .desc = "int conv 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_globals = num_globals(int_conv_init,int_conv_expect), .num_statements = num_statements (int_conv_3a_statements), .statements = int_conv_3a_statements, .init_globals = (pr_int_t *) int_conv_init, @@ -156,7 +156,7 @@ test_t tests[] = { { .desc = "int conv 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_globals = num_globals(int_conv_init,int_conv_expect), .num_statements = num_statements (int_conv_3b_statements), .statements = int_conv_3b_statements, .init_globals = (pr_int_t *) int_conv_init, @@ -165,7 +165,7 @@ test_t tests[] = { { .desc = "int conv 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_conv_init,int_conv_expect), + .num_globals = num_globals(int_conv_init,int_conv_expect), .num_statements = num_statements (int_conv_4_statements), .statements = int_conv_4_statements, .init_globals = (pr_int_t *) int_conv_init, diff --git a/libs/gamecode/test/test-conv1.c b/libs/gamecode/test/test-conv1.c index 541aa6788..97c9735fe 100644 --- a/libs/gamecode/test/test-conv1.c +++ b/libs/gamecode/test/test-conv1.c @@ -136,7 +136,7 @@ test_t tests[] = { { .desc = "float conv 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_globals = num_globals(float_conv_init,float_conv_expect), .num_statements = num_statements (float_conv_1_statements), .statements = float_conv_1_statements, .init_globals = (pr_int_t *) float_conv_init, @@ -145,7 +145,7 @@ test_t tests[] = { { .desc = "float conv 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_globals = num_globals(float_conv_init,float_conv_expect), .num_statements = num_statements (float_conv_2_statements), .statements = float_conv_2_statements, .init_globals = (pr_int_t *) float_conv_init, @@ -154,7 +154,7 @@ test_t tests[] = { { .desc = "float conv 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_globals = num_globals(float_conv_init,float_conv_expect), .num_statements = num_statements (float_conv_3a_statements), .statements = float_conv_3a_statements, .init_globals = (pr_int_t *) float_conv_init, @@ -163,7 +163,7 @@ test_t tests[] = { { .desc = "float conv 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_globals = num_globals(float_conv_init,float_conv_expect), .num_statements = num_statements (float_conv_3b_statements), .statements = float_conv_3b_statements, .init_globals = (pr_int_t *) float_conv_init, @@ -172,7 +172,7 @@ test_t tests[] = { { .desc = "float conv 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_conv_init,float_conv_expect), + .num_globals = num_globals(float_conv_init,float_conv_expect), .num_statements = num_statements (float_conv_4_statements), .statements = float_conv_4_statements, .init_globals = (pr_int_t *) float_conv_init, diff --git a/libs/gamecode/test/test-conv2.c b/libs/gamecode/test/test-conv2.c index ee87f7531..668f00724 100644 --- a/libs/gamecode/test/test-conv2.c +++ b/libs/gamecode/test/test-conv2.c @@ -145,7 +145,7 @@ test_t tests[] = { { .desc = "long conv 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_globals = num_globals(long_conv_init,long_conv_expect), .num_statements = num_statements (long_conv_1_statements), .statements = long_conv_1_statements, .init_globals = (pr_int_t *) long_conv_init, @@ -154,7 +154,7 @@ test_t tests[] = { { .desc = "long conv 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_globals = num_globals(long_conv_init,long_conv_expect), .num_statements = num_statements (long_conv_2_statements), .statements = long_conv_2_statements, .init_globals = (pr_int_t *) long_conv_init, @@ -163,7 +163,7 @@ test_t tests[] = { { .desc = "long conv 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_globals = num_globals(long_conv_init,long_conv_expect), .num_statements = num_statements (long_conv_3a_statements), .statements = long_conv_3a_statements, .init_globals = (pr_int_t *) long_conv_init, @@ -172,7 +172,7 @@ test_t tests[] = { { .desc = "long conv 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_globals = num_globals(long_conv_init,long_conv_expect), .num_statements = num_statements (long_conv_3b_statements), .statements = long_conv_3b_statements, .init_globals = (pr_int_t *) long_conv_init, @@ -181,7 +181,7 @@ test_t tests[] = { { .desc = "long conv 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_conv_init,long_conv_expect), + .num_globals = num_globals(long_conv_init,long_conv_expect), .num_statements = num_statements (long_conv_4_statements), .statements = long_conv_4_statements, .init_globals = (pr_int_t *) long_conv_init, diff --git a/libs/gamecode/test/test-conv3.c b/libs/gamecode/test/test-conv3.c index e4fb1f03d..038b20689 100644 --- a/libs/gamecode/test/test-conv3.c +++ b/libs/gamecode/test/test-conv3.c @@ -152,7 +152,7 @@ test_t tests[] = { { .desc = "double conv 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_globals = num_globals(double_conv_init,double_conv_expect), .num_statements = num_statements (double_conv_1_statements), .statements = double_conv_1_statements, .init_globals = (pr_int_t *) double_conv_init, @@ -161,7 +161,7 @@ test_t tests[] = { { .desc = "double conv 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_globals = num_globals(double_conv_init,double_conv_expect), .num_statements = num_statements (double_conv_2_statements), .statements = double_conv_2_statements, .init_globals = (pr_int_t *) double_conv_init, @@ -170,7 +170,7 @@ test_t tests[] = { { .desc = "double conv 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_globals = num_globals(double_conv_init,double_conv_expect), .num_statements = num_statements (double_conv_3a_statements), .statements = double_conv_3a_statements, .init_globals = (pr_int_t *) double_conv_init, @@ -179,7 +179,7 @@ test_t tests[] = { { .desc = "double conv 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_globals = num_globals(double_conv_init,double_conv_expect), .num_statements = num_statements (double_conv_3b_statements), .statements = double_conv_3b_statements, .init_globals = (pr_int_t *) double_conv_init, @@ -188,7 +188,7 @@ test_t tests[] = { { .desc = "double conv 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_conv_init,double_conv_expect), + .num_globals = num_globals(double_conv_init,double_conv_expect), .num_statements = num_statements (double_conv_4_statements), .statements = double_conv_4_statements, .init_globals = (pr_int_t *) double_conv_init, diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c index 8fc1ec846..28f151339 100644 --- a/libs/gamecode/test/test-conv4.c +++ b/libs/gamecode/test/test-conv4.c @@ -129,7 +129,7 @@ test_t tests[] = { { .desc = "uint conv 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_globals = num_globals(uint_conv_init,uint_conv_expect), .num_statements = num_statements (uint_conv_1_statements), .statements = uint_conv_1_statements, .init_globals = (pr_int_t *) uint_conv_init, @@ -138,7 +138,7 @@ test_t tests[] = { { .desc = "uint conv 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_globals = num_globals(uint_conv_init,uint_conv_expect), .num_statements = num_statements (uint_conv_2_statements), .statements = uint_conv_2_statements, .init_globals = (pr_int_t *) uint_conv_init, @@ -147,7 +147,7 @@ test_t tests[] = { { .desc = "uint conv 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_globals = num_globals(uint_conv_init,uint_conv_expect), .num_statements = num_statements (uint_conv_3a_statements), .statements = uint_conv_3a_statements, .init_globals = (pr_int_t *) uint_conv_init, @@ -156,7 +156,7 @@ test_t tests[] = { { .desc = "uint conv 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_globals = num_globals(uint_conv_init,uint_conv_expect), .num_statements = num_statements (uint_conv_3b_statements), .statements = uint_conv_3b_statements, .init_globals = (pr_int_t *) uint_conv_init, @@ -165,7 +165,7 @@ test_t tests[] = { { .desc = "uint conv 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_conv_init,uint_conv_expect), + .num_globals = num_globals(uint_conv_init,uint_conv_expect), .num_statements = num_statements (uint_conv_4_statements), .statements = uint_conv_4_statements, .init_globals = (pr_int_t *) uint_conv_init, diff --git a/libs/gamecode/test/test-conv5.c b/libs/gamecode/test/test-conv5.c index 2a1d92a46..796bd9cf6 100644 --- a/libs/gamecode/test/test-conv5.c +++ b/libs/gamecode/test/test-conv5.c @@ -136,7 +136,7 @@ test_t tests[] = { { .desc = "bool32 conv 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), .num_statements = num_statements (bool32_conv_1_statements), .statements = bool32_conv_1_statements, .init_globals = (pr_int_t *) bool32_conv_init, @@ -145,7 +145,7 @@ test_t tests[] = { { .desc = "bool32 conv 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), .num_statements = num_statements (bool32_conv_2_statements), .statements = bool32_conv_2_statements, .init_globals = (pr_int_t *) bool32_conv_init, @@ -154,7 +154,7 @@ test_t tests[] = { { .desc = "bool32 conv 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), .num_statements = num_statements (bool32_conv_3a_statements), .statements = bool32_conv_3a_statements, .init_globals = (pr_int_t *) bool32_conv_init, @@ -163,7 +163,7 @@ test_t tests[] = { { .desc = "bool32 conv 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), .num_statements = num_statements (bool32_conv_3b_statements), .statements = bool32_conv_3b_statements, .init_globals = (pr_int_t *) bool32_conv_init, @@ -172,7 +172,7 @@ test_t tests[] = { { .desc = "bool32 conv 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool32_conv_init,bool32_conv_expect), + .num_globals = num_globals(bool32_conv_init,bool32_conv_expect), .num_statements = num_statements (bool32_conv_4_statements), .statements = bool32_conv_4_statements, .init_globals = (pr_int_t *) bool32_conv_init, diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c index 3e84eeb03..58bafe43c 100644 --- a/libs/gamecode/test/test-conv6.c +++ b/libs/gamecode/test/test-conv6.c @@ -145,7 +145,7 @@ test_t tests[] = { { .desc = "ulong conv 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), .num_statements = num_statements (ulong_conv_1_statements), .statements = ulong_conv_1_statements, .init_globals = (pr_int_t *) ulong_conv_init, @@ -154,7 +154,7 @@ test_t tests[] = { { .desc = "ulong conv 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), .num_statements = num_statements (ulong_conv_2_statements), .statements = ulong_conv_2_statements, .init_globals = (pr_int_t *) ulong_conv_init, @@ -163,7 +163,7 @@ test_t tests[] = { { .desc = "ulong conv 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), .num_statements = num_statements (ulong_conv_3a_statements), .statements = ulong_conv_3a_statements, .init_globals = (pr_int_t *) ulong_conv_init, @@ -172,7 +172,7 @@ test_t tests[] = { { .desc = "ulong conv 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), .num_statements = num_statements (ulong_conv_3b_statements), .statements = ulong_conv_3b_statements, .init_globals = (pr_int_t *) ulong_conv_init, @@ -181,7 +181,7 @@ test_t tests[] = { { .desc = "ulong conv 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_conv_init,ulong_conv_expect), + .num_globals = num_globals(ulong_conv_init,ulong_conv_expect), .num_statements = num_statements (ulong_conv_4_statements), .statements = ulong_conv_4_statements, .init_globals = (pr_int_t *) ulong_conv_init, diff --git a/libs/gamecode/test/test-conv7.c b/libs/gamecode/test/test-conv7.c index 1c6171db9..9612b1ee0 100644 --- a/libs/gamecode/test/test-conv7.c +++ b/libs/gamecode/test/test-conv7.c @@ -152,7 +152,7 @@ test_t tests[] = { { .desc = "bool64 conv 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), .num_statements = num_statements (bool64_conv_1_statements), .statements = bool64_conv_1_statements, .init_globals = (pr_int_t *) bool64_conv_init, @@ -161,7 +161,7 @@ test_t tests[] = { { .desc = "bool64 conv 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), .num_statements = num_statements (bool64_conv_2_statements), .statements = bool64_conv_2_statements, .init_globals = (pr_int_t *) bool64_conv_init, @@ -170,7 +170,7 @@ test_t tests[] = { { .desc = "bool64 conv 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), .num_statements = num_statements (bool64_conv_3a_statements), .statements = bool64_conv_3a_statements, .init_globals = (pr_int_t *) bool64_conv_init, @@ -179,7 +179,7 @@ test_t tests[] = { { .desc = "bool64 conv 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), .num_statements = num_statements (bool64_conv_3b_statements), .statements = bool64_conv_3b_statements, .init_globals = (pr_int_t *) bool64_conv_init, @@ -188,7 +188,7 @@ test_t tests[] = { { .desc = "bool64 conv 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(bool64_conv_init,bool64_conv_expect), + .num_globals = num_globals(bool64_conv_init,bool64_conv_expect), .num_statements = num_statements (bool64_conv_4_statements), .statements = bool64_conv_4_statements, .init_globals = (pr_int_t *) bool64_conv_init, diff --git a/libs/gamecode/test/test-double.c b/libs/gamecode/test/test-double.c index 317e18df4..239630034 100644 --- a/libs/gamecode/test/test-double.c +++ b/libs/gamecode/test/test-double.c @@ -232,7 +232,7 @@ test_t tests[] = { { .desc = "double binop 1", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_globals = num_globals(double_binop_init,double_binop_expect), .num_statements = num_statements (double_binop_1_statements), .statements = double_binop_1_statements, .init_globals = (pr_int_t *) double_binop_init, @@ -241,7 +241,7 @@ test_t tests[] = { { .desc = "double binop 2", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_globals = num_globals(double_binop_init,double_binop_expect), .num_statements = num_statements (double_binop_2_statements), .statements = double_binop_2_statements, .init_globals = (pr_int_t *) double_binop_init, @@ -250,7 +250,7 @@ test_t tests[] = { { .desc = "double binop 3a", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_globals = num_globals(double_binop_init,double_binop_expect), .num_statements = num_statements (double_binop_3a_statements), .statements = double_binop_3a_statements, .init_globals = (pr_int_t *) double_binop_init, @@ -259,7 +259,7 @@ test_t tests[] = { { .desc = "double binop 3b", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_globals = num_globals(double_binop_init,double_binop_expect), .num_statements = num_statements (double_binop_3b_statements), .statements = double_binop_3b_statements, .init_globals = (pr_int_t *) double_binop_init, @@ -268,7 +268,7 @@ test_t tests[] = { { .desc = "double binop 4", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(double_binop_init,double_binop_expect), + .num_globals = num_globals(double_binop_init,double_binop_expect), .num_statements = num_statements (double_binop_4_statements), .statements = double_binop_4_statements, .init_globals = (pr_int_t *) double_binop_init, @@ -277,7 +277,7 @@ test_t tests[] = { { .desc = "double cos sin", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(double_cossin_init,double_cossin_expect), + .num_globals = num_globals(double_cossin_init,double_cossin_expect), .num_statements = num_statements (double_cossin_statements), .statements = double_cossin_statements, .init_globals = (pr_int_t *) double_cossin_init, @@ -286,7 +286,7 @@ test_t tests[] = { { .desc = "double cmpop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), .num_statements = num_statements (double_cmpop_1_statements), .statements = double_cmpop_1_statements, .init_globals = (pr_int_t *) double_cmpop_init, @@ -295,7 +295,7 @@ test_t tests[] = { { .desc = "double cmpop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), .num_statements = num_statements (double_cmpop_2_statements), .statements = double_cmpop_2_statements, .init_globals = (pr_int_t *) double_cmpop_init, @@ -304,7 +304,7 @@ test_t tests[] = { { .desc = "double cmpop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), .num_statements = num_statements (double_cmpop_3a_statements), .statements = double_cmpop_3a_statements, .init_globals = (pr_int_t *) double_cmpop_init, @@ -313,7 +313,7 @@ test_t tests[] = { { .desc = "double cmpop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), .num_statements = num_statements (double_cmpop_3b_statements), .statements = double_cmpop_3b_statements, .init_globals = (pr_int_t *) double_cmpop_init, @@ -322,7 +322,7 @@ test_t tests[] = { { .desc = "double cmpop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(double_cmpop_init,double_cmpop_expect), + .num_globals = num_globals(double_cmpop_init,double_cmpop_expect), .num_statements = num_statements (double_cmpop_4_statements), .statements = double_cmpop_4_statements, .init_globals = (pr_int_t *) double_cmpop_init, diff --git a/libs/gamecode/test/test-float.c b/libs/gamecode/test/test-float.c index d01e90518..626f4aaa0 100644 --- a/libs/gamecode/test/test-float.c +++ b/libs/gamecode/test/test-float.c @@ -232,7 +232,7 @@ test_t tests[] = { { .desc = "float binop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_globals = num_globals(float_binop_init,float_binop_expect), .num_statements = num_statements (float_binop_1_statements), .statements = float_binop_1_statements, .init_globals = (pr_int_t *) float_binop_init, @@ -241,7 +241,7 @@ test_t tests[] = { { .desc = "float binop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_globals = num_globals(float_binop_init,float_binop_expect), .num_statements = num_statements (float_binop_2_statements), .statements = float_binop_2_statements, .init_globals = (pr_int_t *) float_binop_init, @@ -250,7 +250,7 @@ test_t tests[] = { { .desc = "float binop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_globals = num_globals(float_binop_init,float_binop_expect), .num_statements = num_statements (float_binop_3a_statements), .statements = float_binop_3a_statements, .init_globals = (pr_int_t *) float_binop_init, @@ -259,7 +259,7 @@ test_t tests[] = { { .desc = "float binop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_globals = num_globals(float_binop_init,float_binop_expect), .num_statements = num_statements (float_binop_3b_statements), .statements = float_binop_3b_statements, .init_globals = (pr_int_t *) float_binop_init, @@ -268,7 +268,7 @@ test_t tests[] = { { .desc = "float binop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_binop_init,float_binop_expect), + .num_globals = num_globals(float_binop_init,float_binop_expect), .num_statements = num_statements (float_binop_4_statements), .statements = float_binop_4_statements, .init_globals = (pr_int_t *) float_binop_init, @@ -277,7 +277,7 @@ test_t tests[] = { { .desc = "float cos sin", .extra_globals = 4 * 1, - .num_globals = 4 * num_globals (float_cossin_init, float_cossin_expect), + .num_globals = num_globals (float_cossin_init, float_cossin_expect), .num_statements = num_statements (float_cossin_statements), .statements = float_cossin_statements, .init_globals = (pr_int_t *) float_cossin_init, @@ -286,7 +286,7 @@ test_t tests[] = { { .desc = "float cmpop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), .num_statements = num_statements (float_cmpop_1_statements), .statements = float_cmpop_1_statements, .init_globals = (pr_int_t *) float_cmpop_init, @@ -295,7 +295,7 @@ test_t tests[] = { { .desc = "float cmpop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), .num_statements = num_statements (float_cmpop_2_statements), .statements = float_cmpop_2_statements, .init_globals = (pr_int_t *) float_cmpop_init, @@ -304,7 +304,7 @@ test_t tests[] = { { .desc = "float cmpop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), .num_statements = num_statements (float_cmpop_3a_statements), .statements = float_cmpop_3a_statements, .init_globals = (pr_int_t *) float_cmpop_init, @@ -313,7 +313,7 @@ test_t tests[] = { { .desc = "float cmpop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), .num_statements = num_statements (float_cmpop_3b_statements), .statements = float_cmpop_3b_statements, .init_globals = (pr_int_t *) float_cmpop_init, @@ -322,7 +322,7 @@ test_t tests[] = { { .desc = "float cmpop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(float_cmpop_init,float_cmpop_expect), + .num_globals = num_globals(float_cmpop_init,float_cmpop_expect), .num_statements = num_statements (float_cmpop_4_statements), .statements = float_cmpop_4_statements, .init_globals = (pr_int_t *) float_cmpop_init, diff --git a/libs/gamecode/test/test-int.c b/libs/gamecode/test/test-int.c index fd5d25af8..f8b4a6a5e 100644 --- a/libs/gamecode/test/test-int.c +++ b/libs/gamecode/test/test-int.c @@ -192,7 +192,7 @@ test_t tests[] = { { .desc = "int binop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_globals = num_globals(int_binop_init,int_binop_expect), .num_statements = num_statements (int_binop_1_statements), .statements = int_binop_1_statements, .init_globals = (pr_int_t *) int_binop_init, @@ -201,7 +201,7 @@ test_t tests[] = { { .desc = "int binop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_globals = num_globals(int_binop_init,int_binop_expect), .num_statements = num_statements (int_binop_2_statements), .statements = int_binop_2_statements, .init_globals = (pr_int_t *) int_binop_init, @@ -210,7 +210,7 @@ test_t tests[] = { { .desc = "int binop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_globals = num_globals(int_binop_init,int_binop_expect), .num_statements = num_statements (int_binop_3a_statements), .statements = int_binop_3a_statements, .init_globals = (pr_int_t *) int_binop_init, @@ -219,7 +219,7 @@ test_t tests[] = { { .desc = "int binop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_globals = num_globals(int_binop_init,int_binop_expect), .num_statements = num_statements (int_binop_3b_statements), .statements = int_binop_3b_statements, .init_globals = (pr_int_t *) int_binop_init, @@ -228,7 +228,7 @@ test_t tests[] = { { .desc = "int binop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_binop_init,int_binop_expect), + .num_globals = num_globals(int_binop_init,int_binop_expect), .num_statements = num_statements (int_binop_4_statements), .statements = int_binop_4_statements, .init_globals = (pr_int_t *) int_binop_init, @@ -237,7 +237,7 @@ test_t tests[] = { { .desc = "int cmpop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), .num_statements = num_statements (int_cmpop_1_statements), .statements = int_cmpop_1_statements, .init_globals = (pr_int_t *) int_cmpop_init, @@ -246,7 +246,7 @@ test_t tests[] = { { .desc = "int cmpop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), .num_statements = num_statements (int_cmpop_2_statements), .statements = int_cmpop_2_statements, .init_globals = (pr_int_t *) int_cmpop_init, @@ -255,7 +255,7 @@ test_t tests[] = { { .desc = "int cmpop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), .num_statements = num_statements (int_cmpop_3a_statements), .statements = int_cmpop_3a_statements, .init_globals = (pr_int_t *) int_cmpop_init, @@ -264,7 +264,7 @@ test_t tests[] = { { .desc = "int cmpop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), .num_statements = num_statements (int_cmpop_3b_statements), .statements = int_cmpop_3b_statements, .init_globals = (pr_int_t *) int_cmpop_init, @@ -273,7 +273,7 @@ test_t tests[] = { { .desc = "int cmpop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(int_cmpop_init,int_cmpop_expect), + .num_globals = num_globals(int_cmpop_init,int_cmpop_expect), .num_statements = num_statements (int_cmpop_4_statements), .statements = int_cmpop_4_statements, .init_globals = (pr_int_t *) int_cmpop_init, diff --git a/libs/gamecode/test/test-long.c b/libs/gamecode/test/test-long.c index fc1851151..36d62845e 100644 --- a/libs/gamecode/test/test-long.c +++ b/libs/gamecode/test/test-long.c @@ -194,7 +194,7 @@ test_t tests[] = { { .desc = "long binop 1", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_globals = num_globals(long_binop_init,long_binop_expect), .num_statements = num_statements (long_binop_1_statements), .statements = long_binop_1_statements, .init_globals = (pr_int_t *) long_binop_init, @@ -203,7 +203,7 @@ test_t tests[] = { { .desc = "long binop 2", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_globals = num_globals(long_binop_init,long_binop_expect), .num_statements = num_statements (long_binop_2_statements), .statements = long_binop_2_statements, .init_globals = (pr_int_t *) long_binop_init, @@ -212,7 +212,7 @@ test_t tests[] = { { .desc = "long binop 3a", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_globals = num_globals(long_binop_init,long_binop_expect), .num_statements = num_statements (long_binop_3a_statements), .statements = long_binop_3a_statements, .init_globals = (pr_int_t *) long_binop_init, @@ -221,7 +221,7 @@ test_t tests[] = { { .desc = "long binop 3b", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_globals = num_globals(long_binop_init,long_binop_expect), .num_statements = num_statements (long_binop_3b_statements), .statements = long_binop_3b_statements, .init_globals = (pr_int_t *) long_binop_init, @@ -230,7 +230,7 @@ test_t tests[] = { { .desc = "long binop 4", .extra_globals = 8 * 1, - .num_globals = 8*num_globals(long_binop_init,long_binop_expect), + .num_globals = num_globals(long_binop_init,long_binop_expect), .num_statements = num_statements (long_binop_4_statements), .statements = long_binop_4_statements, .init_globals = (pr_int_t *) long_binop_init, @@ -239,7 +239,7 @@ test_t tests[] = { { .desc = "long cmpop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), .num_statements = num_statements (long_cmpop_1_statements), .statements = long_cmpop_1_statements, .init_globals = (pr_int_t *) long_cmpop_init, @@ -248,7 +248,7 @@ test_t tests[] = { { .desc = "long cmpop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), .num_statements = num_statements (long_cmpop_2_statements), .statements = long_cmpop_2_statements, .init_globals = (pr_int_t *) long_cmpop_init, @@ -257,7 +257,7 @@ test_t tests[] = { { .desc = "long cmpop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), .num_statements = num_statements (long_cmpop_3a_statements), .statements = long_cmpop_3a_statements, .init_globals = (pr_int_t *) long_cmpop_init, @@ -266,7 +266,7 @@ test_t tests[] = { { .desc = "long cmpop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), .num_statements = num_statements (long_cmpop_3b_statements), .statements = long_cmpop_3b_statements, .init_globals = (pr_int_t *) long_cmpop_init, @@ -275,7 +275,7 @@ test_t tests[] = { { .desc = "long cmpop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(long_cmpop_init,long_cmpop_expect), + .num_globals = num_globals(long_cmpop_init,long_cmpop_expect), .num_statements = num_statements (long_cmpop_4_statements), .statements = long_cmpop_4_statements, .init_globals = (pr_int_t *) long_cmpop_init, diff --git a/libs/gamecode/test/test-unsigned.c b/libs/gamecode/test/test-unsigned.c index 298ed5c26..de9fd3bfa 100644 --- a/libs/gamecode/test/test-unsigned.c +++ b/libs/gamecode/test/test-unsigned.c @@ -304,7 +304,7 @@ static pr_ulvec4_t ulong_shiftop_expect[] = { { UINT64_C(0x456789abcdef0000), UINT64_C(0xdef0123456780000), UINT64_C(0x0000030000000200), UINT64_C(0x5554aaab5554aaaa) },//shl a { UINT64_C(0xef00000000000000), UINT64_C(0x5678000000000000), - UINT64_C(0x0020000000000000), UINT64_C(0x8000000000000000) },//shl b + UINT64_C(0x0080000000000000), UINT64_C(0x8000000000000000) },//shl b { UINT64_C(0x000123456789abcd), UINT64_C(0x00009abcdef01234), UINT64_C(0x0040000000c00000), UINT64_C(0x55552aaad5552aaa) },//shr a { UINT64_C(0x0000000000000123), UINT64_C(0x0000000000009abc), @@ -390,7 +390,7 @@ test_t tests[] = { { .desc = "uint cmpop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), .num_statements = num_statements (uint_cmpop_1_statements), .statements = uint_cmpop_1_statements, .init_globals = (pr_int_t *) uint_cmpop_init, @@ -399,7 +399,7 @@ test_t tests[] = { { .desc = "uint cmpop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), .num_statements = num_statements (uint_cmpop_2_statements), .statements = uint_cmpop_2_statements, .init_globals = (pr_int_t *) uint_cmpop_init, @@ -408,7 +408,7 @@ test_t tests[] = { { .desc = "uint cmpop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), .num_statements = num_statements (uint_cmpop_3a_statements), .statements = uint_cmpop_3a_statements, .init_globals = (pr_int_t *) uint_cmpop_init, @@ -417,7 +417,7 @@ test_t tests[] = { { .desc = "uint cmpop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), .num_statements = num_statements (uint_cmpop_3b_statements), .statements = uint_cmpop_3b_statements, .init_globals = (pr_int_t *) uint_cmpop_init, @@ -426,7 +426,7 @@ test_t tests[] = { { .desc = "uint cmpop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_cmpop_init,uint_cmpop_expect), + .num_globals = num_globals(uint_cmpop_init,uint_cmpop_expect), .num_statements = num_statements (uint_cmpop_4_statements), .statements = uint_cmpop_4_statements, .init_globals = (pr_int_t *) uint_cmpop_init, @@ -435,7 +435,7 @@ test_t tests[] = { { .desc = "ulong cmpop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), .num_statements = num_statements (ulong_cmpop_1_statements), .statements = ulong_cmpop_1_statements, .init_globals = (pr_int_t *) ulong_cmpop_init, @@ -444,7 +444,7 @@ test_t tests[] = { { .desc = "ulong cmpop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), .num_statements = num_statements (ulong_cmpop_2_statements), .statements = ulong_cmpop_2_statements, .init_globals = (pr_int_t *) ulong_cmpop_init, @@ -453,7 +453,7 @@ test_t tests[] = { { .desc = "ulong cmpop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), .num_statements = num_statements (ulong_cmpop_3a_statements), .statements = ulong_cmpop_3a_statements, .init_globals = (pr_int_t *) ulong_cmpop_init, @@ -462,7 +462,7 @@ test_t tests[] = { { .desc = "ulong cmpop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), .num_statements = num_statements (ulong_cmpop_3b_statements), .statements = ulong_cmpop_3b_statements, .init_globals = (pr_int_t *) ulong_cmpop_init, @@ -471,7 +471,7 @@ test_t tests[] = { { .desc = "ulong cmpop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_cmpop_init,ulong_cmpop_expect), + .num_globals = num_globals(ulong_cmpop_init,ulong_cmpop_expect), .num_statements = num_statements (ulong_cmpop_4_statements), .statements = ulong_cmpop_4_statements, .init_globals = (pr_int_t *) ulong_cmpop_init, @@ -480,7 +480,7 @@ test_t tests[] = { { .desc = "uint shiftop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), .num_statements = num_statements (uint_shiftop_1_statements), .statements = uint_shiftop_1_statements, .init_globals = (pr_int_t *) uint_shiftop_init, @@ -489,7 +489,7 @@ test_t tests[] = { { .desc = "uint shiftop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), .num_statements = num_statements (uint_shiftop_2_statements), .statements = uint_shiftop_2_statements, .init_globals = (pr_int_t *) uint_shiftop_init, @@ -498,7 +498,7 @@ test_t tests[] = { { .desc = "uint shiftop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), .num_statements = num_statements (uint_shiftop_3a_statements), .statements = uint_shiftop_3a_statements, .init_globals = (pr_int_t *) uint_shiftop_init, @@ -507,7 +507,7 @@ test_t tests[] = { { .desc = "uint shiftop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), .num_statements = num_statements (uint_shiftop_3b_statements), .statements = uint_shiftop_3b_statements, .init_globals = (pr_int_t *) uint_shiftop_init, @@ -516,7 +516,7 @@ test_t tests[] = { { .desc = "uint shiftop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(uint_shiftop_init,uint_shiftop_expect), + .num_globals = num_globals(uint_shiftop_init,uint_shiftop_expect), .num_statements = num_statements (uint_shiftop_4_statements), .statements = uint_shiftop_4_statements, .init_globals = (pr_int_t *) uint_shiftop_init, @@ -525,7 +525,7 @@ test_t tests[] = { { .desc = "ulong shiftop 1", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), .num_statements = num_statements (ulong_shiftop_1_statements), .statements = ulong_shiftop_1_statements, .init_globals = (pr_int_t *) ulong_shiftop_init, @@ -534,7 +534,7 @@ test_t tests[] = { { .desc = "ulong shiftop 2", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), .num_statements = num_statements (ulong_shiftop_2_statements), .statements = ulong_shiftop_2_statements, .init_globals = (pr_int_t *) ulong_shiftop_init, @@ -543,7 +543,7 @@ test_t tests[] = { { .desc = "ulong shiftop 3a", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), .num_statements = num_statements (ulong_shiftop_3a_statements), .statements = ulong_shiftop_3a_statements, .init_globals = (pr_int_t *) ulong_shiftop_init, @@ -552,7 +552,7 @@ test_t tests[] = { { .desc = "ulong shiftop 3b", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), .num_statements = num_statements (ulong_shiftop_3b_statements), .statements = ulong_shiftop_3b_statements, .init_globals = (pr_int_t *) ulong_shiftop_init, @@ -561,7 +561,7 @@ test_t tests[] = { { .desc = "ulong shiftop 4", .extra_globals = 4 * 1, - .num_globals = 4*num_globals(ulong_shiftop_init,ulong_shiftop_expect), + .num_globals = num_globals(ulong_shiftop_init,ulong_shiftop_expect), .num_statements = num_statements (ulong_shiftop_4_statements), .statements = ulong_shiftop_4_statements, .init_globals = (pr_int_t *) ulong_shiftop_init, diff --git a/libs/gamecode/test/test-vector.c b/libs/gamecode/test/test-vector.c index 814893f86..f80253886 100644 --- a/libs/gamecode/test/test-vector.c +++ b/libs/gamecode/test/test-vector.c @@ -151,7 +151,7 @@ static dstatement_t double_vector_statements[] = { test_t tests[] = { { .desc = "float vector", - .num_globals = 4*num_globals(float_globals_init, float_globals_expect), + .num_globals = num_globals(float_globals_init, float_globals_expect), .num_statements = num_statements (float_vector_statements), .statements = float_vector_statements, .init_globals = (pr_int_t *) float_globals_init, @@ -159,7 +159,7 @@ test_t tests[] = { }, { .desc = "double vector", - .num_globals = 8*num_globals(double_globals_init,double_globals_expect), + .num_globals = num_globals(double_globals_init,double_globals_expect), .num_statements = num_statements (double_vector_statements), .statements = double_vector_statements, .init_globals = (pr_int_t *) double_globals_init, From f4eeed36b7331aa61c54337f8c006e97d04cdf96 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 19:46:35 +0900 Subject: [PATCH 2174/3664] [gamecode] Add tests for the scale instructions --- libs/gamecode/test/Makemodule.am | 6 +++ libs/gamecode/test/test-scale.c | 68 ++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 libs/gamecode/test/test-scale.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index a878155d1..8bb1e3772 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -12,6 +12,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-int \ libs/gamecode/test/test-load \ libs/gamecode/test/test-long \ + libs/gamecode/test/test-scale \ libs/gamecode/test/test-stack \ libs/gamecode/test/test-store \ libs/gamecode/test/test-unsigned \ @@ -92,6 +93,11 @@ libs_gamecode_test_test_long_SOURCES= \ libs_gamecode_test_test_long_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_long_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_scale_SOURCES= \ + libs/gamecode/test/test-scale.c +libs_gamecode_test_test_scale_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_scale_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_stack_SOURCES= \ libs/gamecode/test/test-stack.c libs_gamecode_test_test_stack_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-scale.c b/libs/gamecode/test/test-scale.c new file mode 100644 index 000000000..4117fd718 --- /dev/null +++ b/libs/gamecode/test/test-scale.c @@ -0,0 +1,68 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_vec4_t float_scale_init[] = { + { 5, 0, 0, 0}, + { 3, 4, 13, 85}, + { 0, 0, -1, -2}, + { 0, 0, 0, -3}, + { 0, 0, 0, 0}, +}; + +static pr_vec4_t float_scale_expect[] = { + { 5, 0, 0, 0}, + { 3, 4, 13, 85}, + { 15, 20, -1, -2}, + { 15, 20, 65, -3}, + { 15, 20, 65, 425}, +}; + +static dstatement_t float_scale_statements[] = { + { OP(1, 1, 1, OP_SCALE_F_2), 4, 0, 8 }, + { OP(1, 1, 1, OP_SCALE_F_3), 4, 0, 12 }, + { OP(1, 1, 1, OP_SCALE_F_4), 4, 0, 16 }, +}; + +static pr_dvec4_t double_scale_init[] = { + { 5, 0, 0, 0}, + { 3, 4, 13, 85}, + { 0, 0, -1, -2}, + { 0, 0, 0, -3}, + { 0, 0, 0, 0}, +}; + +static pr_dvec4_t double_scale_expect[] = { + { 5, 0, 0, 0}, + { 3, 4, 13, 85}, + { 15, 20, -1, -2}, + { 15, 20, 65, -3}, + { 15, 20, 65, 425}, +}; + +static dstatement_t double_scale_statements[] = { + { OP(1, 1, 1, OP_SCALE_D_2), 8, 0, 16 }, + { OP(1, 1, 1, OP_SCALE_D_3), 8, 0, 24 }, + { OP(1, 1, 1, OP_SCALE_D_4), 8, 0, 32 }, +}; + +test_t tests[] = { + { + .desc = "float scale", + .num_globals = num_globals(float_scale_init,float_scale_expect), + .num_statements = num_statements (float_scale_statements), + .statements = float_scale_statements, + .init_globals = (pr_int_t *) float_scale_init, + .expect_globals = (pr_int_t *) float_scale_expect, + }, + { + .desc = "double scale", + .num_globals = num_globals(double_scale_init,double_scale_expect), + .num_statements = num_statements (double_scale_statements), + .statements = double_scale_statements, + .init_globals = (pr_int_t *) double_scale_init, + .expect_globals = (pr_int_t *) double_scale_expect, + }, +}; + +#include "main.c" From c8362c28fec60038246b1be24d19c65732695779 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 22:42:56 +0900 Subject: [PATCH 2175/3664] [gamecode] Add tests for string ops Does not include string concatenation because I don't feel like messing with zone init, but all the other operators are tested (currently failing due to bool convention) --- libs/gamecode/test/Makemodule.am | 6 +++ libs/gamecode/test/head.c | 2 + libs/gamecode/test/main.c | 8 ++++ libs/gamecode/test/test-string.c | 82 ++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 libs/gamecode/test/test-string.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 8bb1e3772..ba3bc174a 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -15,6 +15,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-scale \ libs/gamecode/test/test-stack \ libs/gamecode/test/test-store \ + libs/gamecode/test/test-string \ libs/gamecode/test/test-unsigned \ libs/gamecode/test/test-vector @@ -108,6 +109,11 @@ libs_gamecode_test_test_store_SOURCES= \ libs_gamecode_test_test_store_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_store_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_string_SOURCES= \ + libs/gamecode/test/test-string.c +libs_gamecode_test_test_string_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_string_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_vector_SOURCES= \ libs/gamecode/test/test-vector.c libs_gamecode_test_test_vector_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/head.c b/libs/gamecode/test/head.c index 36985c821..478a74f09 100644 --- a/libs/gamecode/test/head.c +++ b/libs/gamecode/test/head.c @@ -34,4 +34,6 @@ typedef struct { dstatement_t *statements; pr_int_t *init_globals; pr_int_t *expect_globals; + const char *strings; + pr_uint_t string_size; } test_t; diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 0579463b2..8f433225c 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -44,10 +44,15 @@ test_debug_handler (prdebug_t event, void *param, void *data) case prd_trace: dstatement_t *st = test_pr.pr_statements + test_pr.pr_xstatement; if (verbose > 1) { + printf ("---\n"); printf ("debug: trace %05x %04x %04x %04x %04x%s\n", test_pr.pr_xstatement, st->op, st->a, st->b, st->c, pr->globals.stack ? va (0, " %05x", *pr->globals.stack) : ""); + printf (" %04x %04x %04x\n", + st->a + PR_BASE (pr, st, A), + st->b + PR_BASE (pr, st, B), + st->c + PR_BASE (pr, st, C)); } if (verbose > 0) { PR_PrintStatement (&test_pr, st, 0); @@ -111,6 +116,9 @@ setup_test (test_t *test) (test->num_statements + 1) * sizeof (dstatement_t)); test_pr.pr_statements[test->num_statements] = (dstatement_t) { OP_BREAK, 0, 0, 0 }; + + test_pr.pr_strings = (char *) test->strings; + test_pr.pr_stringsize = test->string_size; } static int diff --git a/libs/gamecode/test/test-string.c b/libs/gamecode/test/test-string.c new file mode 100644 index 000000000..4e2e7faad --- /dev/null +++ b/libs/gamecode/test/test-string.c @@ -0,0 +1,82 @@ +#include "head.c" + +const char test_strings[] = + "\0" + "abc\0" + "def\0" + "abc\0"; + +static pr_int_t string_globals_init[] = { + 0, 1, 5, 9, // string pointers + 0, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +static pr_int_t string_globals_expect[] = { + 0, 1, 5, 9, // string pointers + 0, 0, 8, 0, + +// "\0" "abc" "def" "abc" + -1, 0, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, // eq + 0, -1, -1, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, // lt + 0, 0, 0, 0, -1, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, 0, // gt + 0,-97,-100,-97, 97, 0, -3, 0, 100, 3, 0, 3, 97, 0, -3, 0, // cmp + -1, 0, 0, 0, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, // ge + -1, -1, -1, -1, 0, -1, -1, -1, 0, 0, -1, 0, 0, -1, -1, -1, // le + -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // not +}; + +static dstatement_t string_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 24, 0, 6 }, // init k +// for (i = 4; i-- > 0; ) { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 4 }, + { OP(0, 0, 0, OP_IFA_A), 2, 0, 4 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_LEA_C), 4, -1, 4 }, // dec i + + { OP(0, 0, 0, OP_WITH), 4, 4, 1 }, // load i + +// for (j = 4; j-- > 0; ) { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 5 }, // init j + + { OP(0, 0, 0, OP_IFA_A), 2, 0, 5 }, + { OP(0, 0, 0, OP_JUMP_A), -6, 0, 0 }, + { OP(0, 0, 0, OP_LEA_C), 5, -1, 5 }, // dec j + + { OP(0, 0, 0, OP_WITH), 4, 5, 2 }, // load j + + { OP(0, 0, 0, OP_LEA_C), 6, -1, 6 }, // dec k + { OP(0, 0, 0, OP_WITH), 4, 6, 3 }, // load k + + // i j k + { OP(1, 2, 3, OP_EQ_S), 0, 0, 0 }, + { OP(1, 2, 3, OP_LT_S), 0, 0, 16 }, + { OP(1, 2, 3, OP_GT_S), 0, 0, 32 }, + { OP(1, 2, 3, OP_CMP_S), 0, 0, 48 }, + { OP(1, 2, 3, OP_GE_S), 0, 0, 64 }, + { OP(1, 2, 3, OP_LE_S), 0, 0, 80 }, + { OP(1, 2, 3, OP_NOT_S), 0, 0, 96 }, + + { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, +}; + +test_t tests[] = { + { + .desc = "string", + .num_globals = num_globals (string_globals_init, string_globals_expect), + .num_statements = num_statements (string_statements), + .statements = string_statements, + .init_globals = string_globals_init, + .expect_globals = string_globals_expect, + .strings = test_strings, + .string_size = sizeof (test_strings), + }, +}; + +#include "main.c" From 1aa4844bf63147010345d75169e5de93d97da6f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 22:44:08 +0900 Subject: [PATCH 2176/3664] [gamecode] Make string ops mostly conform with bools The compare/ne operator returns "random" -ve, 0, +ve values (really, just the numerical difference between the chars of the strings), but all the rest return -1 for true and 0 for false, as with the rest of the comparison operators. --- libs/gamecode/pr_exec.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 86903f7eb..abe934815 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3280,12 +3280,12 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int cmp = strcmp (PR_GetString (pr, OPA(string)), PR_GetString (pr, OPB(string))); switch (st_op) { - case OP_EQ_S: cmp = (cmp == 0); break; - case OP_LT_S: cmp = (cmp < 0); break; - case OP_GT_S: cmp = (cmp > 0); break; - case OP_GE_S: cmp = (cmp >= 0); break; - case OP_LE_S: cmp = (cmp <= 0); break; - case OP_NOT_S: break; + case OP_EQ_S: cmp = -(cmp == 0); break; + case OP_LT_S: cmp = -(cmp < 0); break; + case OP_GT_S: cmp = -(cmp > 0); break; + case OP_GE_S: cmp = -(cmp >= 0); break; + case OP_LE_S: cmp = -(cmp <= 0); break; + case OP_CMP_S: break; default: break; } OPC(int) = cmp; @@ -3296,7 +3296,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) PR_GetString (pr, OPB(string))); break; case OP_NOT_S: - OPC(int) = !OPA(string) || !*PR_GetString (pr, OPA(string)); + OPC(int) = -(!OPA(string) || !*PR_GetString (pr, OPA(string))); break; // 1 0111 OP_op_T (ASR, I, int, ivec2, ivec4, >>); From 6f1f56aea75ba9158f5c4b0cfe5e0ff1af2875e2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Jan 2022 22:51:18 +0900 Subject: [PATCH 2177/3664] [gamecode] Make commented braces match They annoyed me --- libs/gamecode/test/test-string.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/gamecode/test/test-string.c b/libs/gamecode/test/test-string.c index 4e2e7faad..a723eebb7 100644 --- a/libs/gamecode/test/test-string.c +++ b/libs/gamecode/test/test-string.c @@ -63,7 +63,9 @@ static dstatement_t string_statements[] = { { OP(1, 2, 3, OP_LE_S), 0, 0, 80 }, { OP(1, 2, 3, OP_NOT_S), 0, 0, 96 }, +// } { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, +// } }; test_t tests[] = { From 7cd398d4a752ee953aee56318cfd9a11522db88d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Jan 2022 13:20:33 +0900 Subject: [PATCH 2178/3664] [gamecodee] Add tests for move and memset --- libs/gamecode/test/Makemodule.am | 6 ++++ libs/gamecode/test/test-mem.c | 51 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 libs/gamecode/test/test-mem.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index ba3bc174a..58552d1b9 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -12,6 +12,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-int \ libs/gamecode/test/test-load \ libs/gamecode/test/test-long \ + libs/gamecode/test/test-mem \ libs/gamecode/test/test-scale \ libs/gamecode/test/test-stack \ libs/gamecode/test/test-store \ @@ -94,6 +95,11 @@ libs_gamecode_test_test_long_SOURCES= \ libs_gamecode_test_test_long_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_long_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_mem_SOURCES= \ + libs/gamecode/test/test-mem.c +libs_gamecode_test_test_mem_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_mem_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_scale_SOURCES= \ libs/gamecode/test/test-scale.c libs_gamecode_test_test_scale_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-mem.c b/libs/gamecode/test/test-mem.c new file mode 100644 index 000000000..1bba532e8 --- /dev/null +++ b/libs/gamecode/test/test-mem.c @@ -0,0 +1,51 @@ +#include "head.c" + +#define DB 0xdeadbeef + +static pr_int_t mem_globals_init[] = { + 0, 8, 68, 9, 80, 112, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 0, 0, 68, 6, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 + + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, +}; + +static pr_int_t mem_globals_expect[] = { + 0, 8, 68, 9, 80, 112, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, // 0 + 0, 0, 68, 6, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 + + DB, 0, 0, 0, 0, 0, DB, DB, 9, 9, DB, DB, DB, DB, DB, DB, // 32 + 1, 2, 3, 4, 5, 6, 7, 8, DB, DB, DB, DB, 5, 6, 7, 8, // 48 + DB, DB, DB, DB, 1, 2, 1, 2, 3, 4, 5, 6, DB, DB, DB, DB, // 64 + 68, 68, 68, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, // 80 + DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, DB, // 96 + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, DB, // 112 +}; + +static dstatement_t mem_statements[] = { + {OP(0, 0, 0, OP_MEMSET_I), 0, 5, 33}, + {OP(0, 0, 0, OP_MEMSET_I), 3, 2, 40}, + {OP(0, 0, 0, OP_MOVE_I), 8, 8, 48}, + {OP(0, 0, 0, OP_MOVE_I), 12, 4, 60}, + {OP(0, 0, 0, OP_MOVE_PI), 1, 8, 2}, + {OP(0, 0, 0, OP_MEMSET_P), 2, 10, 4}, + {OP(0, 0, 0, OP_MEMSET_PI), 1, 15, 5}, + {OP(0, 0, 0, OP_MOVE_P), 18, 19, 20}, +}; + +test_t tests[] = { + { + .desc = "mem", + .num_globals = num_globals (mem_globals_init, mem_globals_expect), + .num_statements = num_statements (mem_statements), + .statements = mem_statements, + .init_globals = mem_globals_init, + .expect_globals = mem_globals_expect, + }, +}; + +#include "main.c" From bffcbfc9fcd4829d40910c0a8efff2e2ee587580 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Jan 2022 13:59:03 +0900 Subject: [PATCH 2179/3664] [gamecode] Add tests for bitops --- libs/gamecode/test/Makemodule.am | 6 + libs/gamecode/test/test-bitops.c | 260 +++++++++++++++++++++++++++++++ 2 files changed, 266 insertions(+) create mode 100644 libs/gamecode/test/test-bitops.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 58552d1b9..cdc0824a6 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,4 +1,5 @@ libs_gamecode_tests = \ + libs/gamecode/test/test-bitops \ libs/gamecode/test/test-conv0 \ libs/gamecode/test/test-conv1 \ libs/gamecode/test/test-conv2 \ @@ -30,6 +31,11 @@ test_gamecode_libs= \ libs/gamecode/libQFgamecode.la \ libs/util/libQFutil.la +libs_gamecode_test_test_bitops_SOURCES= \ + libs/gamecode/test/test-bitops.c +libs_gamecode_test_test_bitops_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_bitops_DEPENDENCIES=$(test_gamecode_libs) + libs_gamecode_test_test_conv0_SOURCES= \ libs/gamecode/test/test-conv0.c libs_gamecode_test_test_conv0_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-bitops.c b/libs/gamecode/test/test-bitops.c new file mode 100644 index 000000000..a3121eb46 --- /dev/null +++ b/libs/gamecode/test/test-bitops.c @@ -0,0 +1,260 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_ivec4_t int_bitop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ivec4_t int_bitop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + + { 5, 1, 1, -5}, + { 5, -1, -1, -5}, + { 0, -2, -2, 0}, + { -6, 4, -6, 4}, +}; + +static dstatement_t int_bitop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 24 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 24, -1, 24 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 24 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 24, 1 }, + + { OP(1, 1, 1, OP_BITAND_I_1), 0, 4, 8}, + { OP(1, 1, 1, OP_BITOR_I_1), 0, 4, 12}, + { OP(1, 1, 1, OP_BITXOR_I_1), 0, 4, 16}, + { OP(1, 1, 1, OP_BITNOT_I_1), 0, 4, 20}, + + { OP(0, 0, 0, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t int_bitop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 24 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 24, -2, 24 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 24 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 24, 1 }, + + { OP(1, 1, 1, OP_BITAND_I_2), 0, 4, 8}, + { OP(1, 1, 1, OP_BITOR_I_2), 0, 4, 12}, + { OP(1, 1, 1, OP_BITXOR_I_2), 0, 4, 16}, + { OP(1, 1, 1, OP_BITNOT_I_2), 0, 4, 20}, + + { OP(0, 0, 0, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t int_bitop_3a_statements[] = { + { OP(1, 1, 1, OP_BITAND_I_3), 0, 4, 8}, + { OP(1, 1, 1, OP_BITAND_I_1), 3, 7, 11}, + { OP(1, 1, 1, OP_BITOR_I_3), 0, 4, 12}, + { OP(1, 1, 1, OP_BITOR_I_1), 3, 7, 15}, + { OP(1, 1, 1, OP_BITXOR_I_3), 0, 4, 16}, + { OP(1, 1, 1, OP_BITXOR_I_1), 3, 7, 19}, + { OP(1, 1, 1, OP_BITNOT_I_3), 0, 4, 20}, + { OP(1, 1, 1, OP_BITNOT_I_1), 3, 7, 23}, +}; + +static dstatement_t int_bitop_3b_statements[] = { + { OP(1, 1, 1, OP_BITAND_I_1), 0, 4, 8}, + { OP(1, 1, 1, OP_BITAND_I_3), 1, 5, 9}, + { OP(1, 1, 1, OP_BITOR_I_1), 0, 4, 12}, + { OP(1, 1, 1, OP_BITOR_I_3), 1, 5, 13}, + { OP(1, 1, 1, OP_BITXOR_I_1), 0, 4, 16}, + { OP(1, 1, 1, OP_BITXOR_I_3), 1, 5, 17}, + { OP(1, 1, 1, OP_BITNOT_I_1), 0, 4, 20}, + { OP(1, 1, 1, OP_BITNOT_I_3), 1, 5, 21}, +}; + +static dstatement_t int_bitop_4_statements[] = { + { OP(1, 1, 1, OP_BITAND_I_4), 0, 4, 8}, + { OP(1, 1, 1, OP_BITOR_I_4), 0, 4, 12}, + { OP(1, 1, 1, OP_BITXOR_I_4), 0, 4, 16}, + { OP(1, 1, 1, OP_BITNOT_I_4), 0, 4, 20}, +}; + +static pr_lvec4_t long_bitop_init[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_lvec4_t long_bitop_expect[] = { + { 5, -5, 5, -5}, + { 5, 5, -5, -5}, + + { 5, 1, 1, -5}, + { 5, -1, -1, -5}, + { 0, -2, -2, 0}, + { -6, 4, -6, 4}, +}; + +static dstatement_t long_bitop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 48 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 48, -2, 48 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 48 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 48, 1 }, + + { OP(1, 1, 1, OP_BITAND_L_1), 0, 8, 16}, + { OP(1, 1, 1, OP_BITOR_L_1), 0, 8, 24}, + { OP(1, 1, 1, OP_BITXOR_L_1), 0, 8, 32}, + { OP(1, 1, 1, OP_BITNOT_L_1), 0, 8, 40}, + + { OP(0, 0, 0, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t long_bitop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 48 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 48, -4, 48 }, // dec index + { OP(0, 0, 0, OP_IFAE_A), 2, 0, 48 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 48, 1 }, + + { OP(1, 1, 1, OP_BITAND_L_2), 0, 8, 16}, + { OP(1, 1, 1, OP_BITOR_L_2), 0, 8, 24}, + { OP(1, 1, 1, OP_BITXOR_L_2), 0, 8, 32}, + { OP(1, 1, 1, OP_BITNOT_L_2), 0, 8, 40}, + + { OP(0, 0, 0, OP_JUMP_A), -8, 0, 0 }, +}; + +static dstatement_t long_bitop_3a_statements[] = { + { OP(1, 1, 1, OP_BITAND_L_3), 0, 8, 16}, + { OP(1, 1, 1, OP_BITAND_L_1), 6, 14, 22}, + { OP(1, 1, 1, OP_BITOR_L_3), 0, 8, 24}, + { OP(1, 1, 1, OP_BITOR_L_1), 6, 14, 30}, + { OP(1, 1, 1, OP_BITXOR_L_3), 0, 8, 32}, + { OP(1, 1, 1, OP_BITXOR_L_1), 6, 14, 38}, + { OP(1, 1, 1, OP_BITNOT_L_3), 0, 8, 40}, + { OP(1, 1, 1, OP_BITNOT_L_1), 6, 14, 46}, +}; + +static dstatement_t long_bitop_3b_statements[] = { + { OP(1, 1, 1, OP_BITAND_L_1), 0, 8, 16}, + { OP(1, 1, 1, OP_BITAND_L_3), 2, 10, 18}, + { OP(1, 1, 1, OP_BITOR_L_1), 0, 8, 24}, + { OP(1, 1, 1, OP_BITOR_L_3), 2, 10, 26}, + { OP(1, 1, 1, OP_BITXOR_L_1), 0, 8, 32}, + { OP(1, 1, 1, OP_BITXOR_L_3), 2, 10, 34}, + { OP(1, 1, 1, OP_BITNOT_L_1), 0, 8, 40}, + { OP(1, 1, 1, OP_BITNOT_L_3), 2, 10, 42}, +}; + +static dstatement_t long_bitop_4_statements[] = { + { OP(1, 1, 1, OP_BITAND_L_4), 0, 8, 16}, + { OP(1, 1, 1, OP_BITOR_L_4), 0, 8, 24}, + { OP(1, 1, 1, OP_BITXOR_L_4), 0, 8, 32}, + { OP(1, 1, 1, OP_BITNOT_L_4), 0, 8, 40}, +}; + +test_t tests[] = { + { + .desc = "int bitop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_1_statements), + .statements = int_bitop_1_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "int bitop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_2_statements), + .statements = int_bitop_2_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "int bitop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_3a_statements), + .statements = int_bitop_3a_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "int bitop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_3b_statements), + .statements = int_bitop_3b_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "int bitop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(int_bitop_init,int_bitop_expect), + .num_statements = num_statements (int_bitop_4_statements), + .statements = int_bitop_4_statements, + .init_globals = (pr_int_t *) int_bitop_init, + .expect_globals = (pr_int_t *) int_bitop_expect, + }, + { + .desc = "long bitop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_1_statements), + .statements = long_bitop_1_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, + { + .desc = "long bitop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_2_statements), + .statements = long_bitop_2_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, + { + .desc = "long bitop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_3a_statements), + .statements = long_bitop_3a_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, + { + .desc = "long bitop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_3b_statements), + .statements = long_bitop_3b_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, + { + .desc = "long bitop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(long_bitop_init,long_bitop_expect), + .num_statements = num_statements (long_bitop_4_statements), + .statements = long_bitop_4_statements, + .init_globals = (pr_int_t *) long_bitop_init, + .expect_globals = (pr_int_t *) long_bitop_expect, + }, +}; + +#include "main.c" From fae432f46e23de7b123c38c9aed9285ca874f3cf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Jan 2022 15:44:53 +0900 Subject: [PATCH 2180/3664] [gamecode] Make no-op conversions simple copies Most useful for 64-bit values as only one instruction is needed to move the data around rather than two, but could be slightly faster for 32-bit as the addressing is simpler (needs profiling). --- libs/gamecode/convert.py | 19 +++++++++++++++---- libs/gamecode/test/test-conv0.c | 22 ++++++++++++++++++---- libs/gamecode/test/test-conv1.c | 13 ++++++++++--- libs/gamecode/test/test-conv2.c | 26 ++++++++++++++++++++------ libs/gamecode/test/test-conv3.c | 15 +++++++++++---- libs/gamecode/test/test-conv4.c | 22 ++++++++++++++++++---- libs/gamecode/test/test-conv5.c | 13 ++++++++++--- libs/gamecode/test/test-conv6.c | 26 ++++++++++++++++++++------ libs/gamecode/test/test-conv7.c | 15 +++++++++++---- 9 files changed, 133 insertions(+), 38 deletions(-) diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index dc4b36674..0474fbd8f 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -85,14 +85,25 @@ def expand_str(width, src, pref=""): for width in range(4): for src_type in range(8): for dst_type in range(8): - mode = convert_matrix[src_type][dst_type] - if not mode: - continue case = case_str(width, src_type, dst_type) cast = cast_str(width, src_type, dst_type) src = src_str(width, src_type, dst_type) dst = dst_str(width, src_type, dst_type) - if mode == 1: + mode = convert_matrix[src_type][dst_type] + if mode == 0: + if dst_type & 2 != src_type & 2: + continue + if dst_type & 2: + src = src_str(width, 2, 2) + dst = dst_str(width, 2, 2) + else: + src = src_str(width, 0, 0) + dst = dst_str(width, 0, 0) + if width == 2: + print(f"{case} VectorCopy(&{src},&{dst}); break;") + else: + print(f"{case} {dst} = {src}; break;") + elif mode == 1: if width == 0: print(f"{case} {dst} = {cast} {src}; break;") elif width == 2: diff --git a/libs/gamecode/test/test-conv0.c b/libs/gamecode/test/test-conv0.c index bfa492225..2f0533361 100644 --- a/libs/gamecode/test/test-conv0.c +++ b/libs/gamecode/test/test-conv0.c @@ -38,11 +38,11 @@ static pr_ivec4_t int_conv_expect[] = { { 256, 0, 0x7fffffff, 0}, //ulong { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 - { 0, 0, 0, 0}, // int + { 5, -5, 0x80000000, 0x7fffffff}, // int { 1, -1, 0x80000000, 0x80000000}, // float undef? { 99, 0x80000000, 256, 0x7fffffff}, // long { 0x80000000, 0x80000000, 1, -1}, // double undef? - { 0, 0, 0, 0}, // uint + { 5, -5, 0x80000000, 0x7fffffff}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong { 1, 1, 1, 0}, // bool64 @@ -58,13 +58,15 @@ static dstatement_t int_conv_1_statements[] = { { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0000, 48 }, { OP(1, 1, 1, OP_CONV), 4, 0010, 52 }, { OP(2, 1, 1, OP_CONV), 8, 0020, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0030, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0040, 64 }, { OP(1, 1, 1, OP_CONV), 28, 0050, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0060, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0070, 76 }, - { OP(1, 1, 1, OP_JUMP_A), -12, 0, 0 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t int_conv_2_statements[] = { @@ -77,22 +79,28 @@ static dstatement_t int_conv_2_statements[] = { { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0100, 48 }, { OP(1, 1, 1, OP_CONV), 4, 0110, 52 }, { OP(2, 1, 1, OP_CONV), 8, 0120, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0130, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0140, 64 }, { OP(1, 1, 1, OP_CONV), 28, 0150, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0160, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0170, 76 }, - { OP(1, 1, 1, OP_JUMP_A), -12, 0, 0 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t int_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0200, 48 }, + { OP(1, 1, 1, OP_CONV), 3, 0200, 51 }, { OP(1, 1, 1, OP_CONV), 4, 0210, 52 }, { OP(1, 1, 1, OP_CONV), 7, 0010, 55 }, { OP(2, 1, 1, OP_CONV), 8, 0220, 56 }, { OP(2, 1, 1, OP_CONV), 14, 0020, 59 }, { OP(2, 1, 1, OP_CONV), 16, 0230, 60 }, { OP(2, 1, 1, OP_CONV), 22, 0030, 63 }, + { OP(1, 1, 1, OP_CONV), 24, 0240, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0240, 67 }, { OP(1, 1, 1, OP_CONV), 28, 0250, 68 }, { OP(1, 1, 1, OP_CONV), 31, 0050, 71 }, { OP(2, 1, 1, OP_CONV), 32, 0260, 72 }, @@ -102,12 +110,16 @@ static dstatement_t int_conv_3a_statements[] = { }; static dstatement_t int_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0200, 48 }, + { OP(1, 1, 1, OP_CONV), 1, 0200, 49 }, { OP(1, 1, 1, OP_CONV), 4, 0010, 52 }, { OP(1, 1, 1, OP_CONV), 5, 0210, 53 }, { OP(2, 1, 1, OP_CONV), 8, 0020, 56 }, { OP(2, 1, 1, OP_CONV), 10, 0220, 57 }, { OP(2, 1, 1, OP_CONV), 16, 0030, 60 }, { OP(2, 1, 1, OP_CONV), 18, 0230, 61 }, + { OP(1, 1, 1, OP_CONV), 24, 0240, 64 }, + { OP(1, 1, 1, OP_CONV), 25, 0240, 65 }, { OP(1, 1, 1, OP_CONV), 28, 0050, 68 }, { OP(1, 1, 1, OP_CONV), 29, 0250, 69 }, { OP(2, 1, 1, OP_CONV), 32, 0060, 72 }, @@ -117,12 +129,14 @@ static dstatement_t int_conv_3b_statements[] = { }; static dstatement_t int_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0300, 48 }, { OP(1, 1, 1, OP_CONV), 4, 0310, 52 }, { OP(2, 1, 1, OP_CONV), 8, 0320, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0330, 60 }, { OP(1, 1, 1, OP_CONV), 28, 0350, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0360, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0370, 76 }, + { OP(1, 1, 1, OP_CONV), 24, 0340, 64 }, }; test_t tests[] = { diff --git a/libs/gamecode/test/test-conv1.c b/libs/gamecode/test/test-conv1.c index 97c9735fe..6233b83f3 100644 --- a/libs/gamecode/test/test-conv1.c +++ b/libs/gamecode/test/test-conv1.c @@ -39,7 +39,7 @@ static pr_ivec4_t float_conv_expect[] = { { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 { 0x40a00000, 0xc0a00000, 0xcf000000, 0x4f000000}, // int - { 0, 0, 0, 0}, // float + { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, // float { 0xdf000000, 0x52c70000, 0x43800000, 0x4f000000}, // long { 0x7149f2ca, 0xf149f2ca, 0x3fc00000, 0xbfc00000}, // double { 0x40a00000, 0x4f800000, 0x4f000000, 0x4f000000}, // uint @@ -59,13 +59,14 @@ static dstatement_t float_conv_1_statements[] = { { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, { OP(1, 1, 1, OP_CONV), 0, 0001, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0011, 52 }, { OP(2, 1, 1, OP_CONV), 8, 0021, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0031, 60 }, { OP(1, 1, 1, OP_CONV), 24, 0041, 64 }, { OP(1, 1, 1, OP_CONV), 28, 0051, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0061, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0071, 76 }, - { OP(1, 1, 1, OP_JUMP_A), -13, 0, 0 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t float_conv_2_statements[] = { @@ -79,18 +80,21 @@ static dstatement_t float_conv_2_statements[] = { { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, { OP(1, 1, 1, OP_CONV), 0, 0101, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0111, 52 }, { OP(2, 1, 1, OP_CONV), 8, 0121, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0131, 60 }, { OP(1, 1, 1, OP_CONV), 24, 0141, 64 }, { OP(1, 1, 1, OP_CONV), 28, 0151, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0161, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0171, 76 }, - { OP(1, 1, 1, OP_JUMP_A), -13, 0, 0 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t float_conv_3a_statements[] = { { OP(1, 1, 1, OP_CONV), 0, 0201, 48 }, { OP(1, 1, 1, OP_CONV), 3, 0001, 51 }, + { OP(1, 1, 1, OP_CONV), 4, 0211, 52 }, + { OP(1, 1, 1, OP_CONV), 7, 0011, 55 }, { OP(2, 1, 1, OP_CONV), 8, 0221, 56 }, { OP(2, 1, 1, OP_CONV), 14, 0021, 59 }, { OP(2, 1, 1, OP_CONV), 16, 0231, 60 }, @@ -108,6 +112,8 @@ static dstatement_t float_conv_3a_statements[] = { static dstatement_t float_conv_3b_statements[] = { { OP(1, 1, 1, OP_CONV), 0, 0001, 48 }, { OP(1, 1, 1, OP_CONV), 1, 0201, 49 }, + { OP(1, 1, 1, OP_CONV), 4, 0011, 52 }, + { OP(1, 1, 1, OP_CONV), 5, 0211, 53 }, { OP(2, 1, 1, OP_CONV), 8, 0021, 56 }, { OP(2, 1, 1, OP_CONV), 10, 0221, 57 }, { OP(2, 1, 1, OP_CONV), 16, 0031, 60 }, @@ -124,6 +130,7 @@ static dstatement_t float_conv_3b_statements[] = { static dstatement_t float_conv_4_statements[] = { { OP(1, 1, 1, OP_CONV), 0, 0301, 48 }, + { OP(1, 1, 1, OP_CONV), 4, 0311, 52 }, { OP(2, 1, 1, OP_CONV), 8, 0321, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0331, 60 }, { OP(1, 1, 1, OP_CONV), 24, 0341, 64 }, diff --git a/libs/gamecode/test/test-conv2.c b/libs/gamecode/test/test-conv2.c index 668f00724..f3a81a6ad 100644 --- a/libs/gamecode/test/test-conv2.c +++ b/libs/gamecode/test/test-conv2.c @@ -50,16 +50,16 @@ static pr_ivec4_t long_conv_expect[] = { { 0x80000000, 0xffffffff, 0x7fffffff, 0}, { 1, 0, -1, -1}, // float { 0, 0x80000000, 0, 0x80000000}, // undef? - { 0, 0, 0, 0}, // long - { 0, 0, 0, 0}, + { 99, 0x80000000, 0x80000000, 99}, // long + { 256, 0, 0x7fffffff, 0}, { 0, 0x80000000, 0, 0x80000000}, // double undef? { 1, 0, -1, -1}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool32 { 1, 0, 0, 0}, - { 0, 0, 0, 0}, // ulong - { 0, 0, 0, 0}, + { 99, 0x80000000, 0x80000000, 99}, // ulong + { 256, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool64 { 1, 0, 0, 0}, }; @@ -76,11 +76,13 @@ static dstatement_t long_conv_1_statements[] = { { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, { OP(1, 1, 2, OP_CONV), 0, 0002, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0012, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0022, 64 }, { OP(2, 1, 2, OP_CONV), 16, 0032, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0042, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0052, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0062, 96 }, { OP(2, 1, 2, OP_CONV), 40, 0072, 104 }, - { OP(0, 0, 0, OP_JUMP_A), -12, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t long_conv_2_statements[] = { @@ -95,11 +97,13 @@ static dstatement_t long_conv_2_statements[] = { { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, { OP(1, 1, 2, OP_CONV), 0, 0102, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0112, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0122, 64 }, { OP(2, 1, 2, OP_CONV), 16, 0132, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0142, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0152, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0162, 96 }, { OP(2, 1, 2, OP_CONV), 40, 0172, 104 }, - { OP(0, 0, 0, OP_JUMP_A), -12, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t long_conv_3a_statements[] = { @@ -107,12 +111,16 @@ static dstatement_t long_conv_3a_statements[] = { { OP(1, 1, 2, OP_CONV), 3, 0002, 54 }, { OP(1, 1, 2, OP_CONV), 4, 0212, 56 }, { OP(1, 1, 2, OP_CONV), 7, 0012, 62 }, + { OP(2, 1, 2, OP_CONV), 8, 0222, 64 }, + { OP(2, 1, 2, OP_CONV), 14, 0022, 70 }, { OP(2, 1, 2, OP_CONV), 16, 0232, 72 }, { OP(2, 1, 2, OP_CONV), 22, 0032, 78 }, { OP(1, 1, 2, OP_CONV), 24, 0242, 80 }, { OP(1, 1, 2, OP_CONV), 27, 0042, 86 }, { OP(1, 1, 2, OP_CONV), 28, 0252, 88 }, { OP(1, 1, 2, OP_CONV), 31, 0052, 94 }, + { OP(2, 1, 2, OP_CONV), 32, 0262, 96 }, + { OP(2, 1, 2, OP_CONV), 38, 0062, 102 }, { OP(2, 1, 2, OP_CONV), 40, 0272, 104 }, { OP(2, 1, 2, OP_CONV), 46, 0072, 110 }, }; @@ -122,12 +130,16 @@ static dstatement_t long_conv_3b_statements[] = { { OP(1, 1, 2, OP_CONV), 1, 0202, 50 }, { OP(1, 1, 2, OP_CONV), 4, 0012, 56 }, { OP(1, 1, 2, OP_CONV), 5, 0212, 58 }, + { OP(2, 1, 2, OP_CONV), 8, 0022, 64 }, + { OP(2, 1, 2, OP_CONV), 10, 0222, 66 }, { OP(2, 1, 2, OP_CONV), 16, 0032, 72 }, { OP(2, 1, 2, OP_CONV), 18, 0232, 74 }, { OP(1, 1, 2, OP_CONV), 24, 0042, 80 }, { OP(1, 1, 2, OP_CONV), 25, 0242, 82 }, { OP(1, 1, 2, OP_CONV), 28, 0052, 88 }, { OP(1, 1, 2, OP_CONV), 29, 0252, 90 }, + { OP(2, 1, 2, OP_CONV), 32, 0062, 96 }, + { OP(2, 1, 2, OP_CONV), 34, 0262, 98 }, { OP(2, 1, 2, OP_CONV), 40, 0072, 104 }, { OP(2, 1, 2, OP_CONV), 42, 0272, 106 }, }; @@ -135,9 +147,11 @@ static dstatement_t long_conv_3b_statements[] = { static dstatement_t long_conv_4_statements[] = { { OP(1, 1, 2, OP_CONV), 0, 0302, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0312, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0322, 64 }, { OP(2, 1, 2, OP_CONV), 16, 0332, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0342, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0352, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0362, 96 }, { OP(2, 1, 2, OP_CONV), 40, 0372, 104 }, }; diff --git a/libs/gamecode/test/test-conv3.c b/libs/gamecode/test/test-conv3.c index 038b20689..ea6989dda 100644 --- a/libs/gamecode/test/test-conv3.c +++ b/libs/gamecode/test/test-conv3.c @@ -52,8 +52,8 @@ static pr_ivec4_t double_conv_expect[] = { { 0x40000000, 0x46293e59, 0x40000000, 0xc6293e59}, { 0x00000000, 0xc3e00000, 0x00000000, 0x4258e000}, // long { 0x00000000, 0x40700000, 0xffc00000, 0x41dfffff}, - { 0, 0, 0, 0}, // double - { 0, 0, 0, 0}, + { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, // double + { 0, 0x3ff80000, 0, 0xbff80000}, { 0x00000000, 0x40140000, 0xff600000, 0x41efffff}, // uint { 0x00000000, 0x41e00000, 0xffc00000, 0x41dfffff}, { 0x00000000, 0x3ff00000, 0x00000000, 0x3ff00000}, // bool32 @@ -77,11 +77,12 @@ static dstatement_t double_conv_1_statements[] = { { OP(1, 1, 2, OP_CONV), 0, 0003, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0013, 56 }, { OP(2, 1, 2, OP_CONV), 8, 0023, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0033, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0043, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0053, 88 }, { OP(2, 1, 2, OP_CONV), 32, 0063, 96 }, { OP(2, 1, 2, OP_CONV), 40, 0073, 104 }, - { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t double_conv_2_statements[] = { @@ -97,11 +98,12 @@ static dstatement_t double_conv_2_statements[] = { { OP(1, 1, 2, OP_CONV), 0, 0103, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0113, 56 }, { OP(2, 1, 2, OP_CONV), 8, 0123, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0133, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0143, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0153, 88 }, { OP(2, 1, 2, OP_CONV), 32, 0163, 96 }, { OP(2, 1, 2, OP_CONV), 40, 0173, 104 }, - { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t double_conv_3a_statements[] = { @@ -111,6 +113,8 @@ static dstatement_t double_conv_3a_statements[] = { { OP(1, 1, 2, OP_CONV), 7, 0013, 62 }, { OP(2, 1, 2, OP_CONV), 8, 0223, 64 }, { OP(2, 1, 2, OP_CONV), 14, 0023, 70 }, + { OP(2, 1, 2, OP_CONV), 16, 0233, 72 }, + { OP(2, 1, 2, OP_CONV), 22, 0033, 78 }, { OP(1, 1, 2, OP_CONV), 24, 0243, 80 }, { OP(1, 1, 2, OP_CONV), 27, 0043, 86 }, { OP(1, 1, 2, OP_CONV), 28, 0253, 88 }, @@ -128,6 +132,8 @@ static dstatement_t double_conv_3b_statements[] = { { OP(1, 1, 2, OP_CONV), 5, 0213, 58 }, { OP(2, 1, 2, OP_CONV), 8, 0023, 64 }, { OP(2, 1, 2, OP_CONV), 10, 0223, 66 }, + { OP(2, 1, 2, OP_CONV), 16, 0033, 72 }, + { OP(2, 1, 2, OP_CONV), 18, 0233, 74 }, { OP(1, 1, 2, OP_CONV), 24, 0043, 80 }, { OP(1, 1, 2, OP_CONV), 25, 0243, 82 }, { OP(1, 1, 2, OP_CONV), 28, 0053, 88 }, @@ -142,6 +148,7 @@ static dstatement_t double_conv_4_statements[] = { { OP(1, 1, 2, OP_CONV), 0, 0303, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0313, 56 }, { OP(2, 1, 2, OP_CONV), 8, 0323, 64 }, + { OP(2, 1, 2, OP_CONV), 16, 0333, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0343, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0353, 88 }, { OP(2, 1, 2, OP_CONV), 32, 0363, 96 }, diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c index 28f151339..0f7460a6a 100644 --- a/libs/gamecode/test/test-conv4.c +++ b/libs/gamecode/test/test-conv4.c @@ -38,11 +38,11 @@ static pr_ivec4_t uint_conv_expect[] = { { 256, 0, 0x7fffffff, 0}, //ulong { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 - { 0, 0, 0, 0}, // int + { 5, -5, 0x80000000, 0x7fffffff}, // int { 1, 0xffffffff, 0, 0}, // float undef? { 99, 0x80000000, 256, 0x7fffffff}, // long { 0, 0, 1, 0xffffffff}, // double undef? - { 0, 0, 0, 0}, // uint + { 5, -5, 0x80000000, 0x7fffffff}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong { 1, 1, 1, 0}, // bool64 @@ -58,13 +58,15 @@ static dstatement_t uint_conv_1_statements[] = { { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0004, 48 }, { OP(1, 1, 1, OP_CONV), 4, 0014, 52 }, { OP(2, 1, 1, OP_CONV), 8, 0024, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0034, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0044, 64 }, { OP(1, 1, 1, OP_CONV), 28, 0054, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0064, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0074, 76 }, - { OP(1, 1, 1, OP_JUMP_A), -12, 0, 0 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t uint_conv_2_statements[] = { @@ -77,22 +79,28 @@ static dstatement_t uint_conv_2_statements[] = { { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, + { OP(1, 1, 1, OP_CONV), 0, 0104, 48 }, { OP(1, 1, 1, OP_CONV), 4, 0114, 52 }, { OP(2, 1, 1, OP_CONV), 8, 0124, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0134, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0144, 64 }, { OP(1, 1, 1, OP_CONV), 28, 0154, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0164, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0174, 76 }, - { OP(1, 1, 1, OP_JUMP_A), -12, 0, 0 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t uint_conv_3a_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0204, 48 }, + { OP(1, 1, 1, OP_CONV), 3, 0004, 51 }, { OP(1, 1, 1, OP_CONV), 4, 0214, 52 }, { OP(1, 1, 1, OP_CONV), 7, 0014, 55 }, { OP(2, 1, 1, OP_CONV), 8, 0224, 56 }, { OP(2, 1, 1, OP_CONV), 14, 0024, 59 }, { OP(2, 1, 1, OP_CONV), 16, 0234, 60 }, { OP(2, 1, 1, OP_CONV), 22, 0034, 63 }, + { OP(1, 1, 1, OP_CONV), 24, 0244, 64 }, + { OP(1, 1, 1, OP_CONV), 27, 0044, 67 }, { OP(1, 1, 1, OP_CONV), 28, 0254, 68 }, { OP(1, 1, 1, OP_CONV), 31, 0054, 71 }, { OP(2, 1, 1, OP_CONV), 32, 0264, 72 }, @@ -102,12 +110,16 @@ static dstatement_t uint_conv_3a_statements[] = { }; static dstatement_t uint_conv_3b_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0004, 48 }, + { OP(1, 1, 1, OP_CONV), 1, 0204, 49 }, { OP(1, 1, 1, OP_CONV), 4, 0014, 52 }, { OP(1, 1, 1, OP_CONV), 5, 0214, 53 }, { OP(2, 1, 1, OP_CONV), 8, 0024, 56 }, { OP(2, 1, 1, OP_CONV), 10, 0224, 57 }, { OP(2, 1, 1, OP_CONV), 16, 0034, 60 }, { OP(2, 1, 1, OP_CONV), 18, 0234, 61 }, + { OP(1, 1, 1, OP_CONV), 24, 0044, 64 }, + { OP(1, 1, 1, OP_CONV), 25, 0244, 65 }, { OP(1, 1, 1, OP_CONV), 28, 0054, 68 }, { OP(1, 1, 1, OP_CONV), 29, 0254, 69 }, { OP(2, 1, 1, OP_CONV), 32, 0064, 72 }, @@ -117,9 +129,11 @@ static dstatement_t uint_conv_3b_statements[] = { }; static dstatement_t uint_conv_4_statements[] = { + { OP(1, 1, 1, OP_CONV), 0, 0304, 48 }, { OP(1, 1, 1, OP_CONV), 4, 0314, 52 }, { OP(2, 1, 1, OP_CONV), 8, 0324, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0334, 60 }, + { OP(1, 1, 1, OP_CONV), 24, 0344, 64 }, { OP(1, 1, 1, OP_CONV), 28, 0354, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0364, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0374, 76 }, diff --git a/libs/gamecode/test/test-conv5.c b/libs/gamecode/test/test-conv5.c index 796bd9cf6..3713cd159 100644 --- a/libs/gamecode/test/test-conv5.c +++ b/libs/gamecode/test/test-conv5.c @@ -43,7 +43,7 @@ static pr_ivec4_t bool32_conv_expect[] = { { -1, -1, -1, -1}, // long { -1, -1, -1, -1}, // double { -1, -1, -1, -1}, // uint - { 0, 0, 0, 0}, // bool32 + { ~0, 1, 0x80000000, 0}, // bool32 { -1, -1, -1, -1}, // ulong { -1, -1, -1, 0}, // bool64 }; @@ -63,9 +63,10 @@ static dstatement_t bool32_conv_1_statements[] = { { OP(2, 1, 1, OP_CONV), 8, 0025, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0035, 60 }, { OP(1, 1, 1, OP_CONV), 24, 0045, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0055, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0065, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0075, 76 }, - { OP(1, 1, 1, OP_JUMP_A), -13, 0, 0 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t bool32_conv_2_statements[] = { @@ -83,9 +84,10 @@ static dstatement_t bool32_conv_2_statements[] = { { OP(2, 1, 1, OP_CONV), 8, 0125, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0135, 60 }, { OP(1, 1, 1, OP_CONV), 24, 0145, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0155, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0165, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0175, 76 }, - { OP(1, 1, 1, OP_JUMP_A), -13, 0, 0 }, + { OP(1, 1, 1, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t bool32_conv_3a_statements[] = { @@ -99,6 +101,8 @@ static dstatement_t bool32_conv_3a_statements[] = { { OP(2, 1, 1, OP_CONV), 22, 0035, 63 }, { OP(1, 1, 1, OP_CONV), 24, 0245, 64 }, { OP(1, 1, 1, OP_CONV), 27, 0045, 67 }, + { OP(1, 1, 1, OP_CONV), 28, 0255, 68 }, + { OP(1, 1, 1, OP_CONV), 31, 0055, 71 }, { OP(2, 1, 1, OP_CONV), 32, 0265, 72 }, { OP(2, 1, 1, OP_CONV), 38, 0065, 75 }, { OP(2, 1, 1, OP_CONV), 40, 0275, 76 }, @@ -116,6 +120,8 @@ static dstatement_t bool32_conv_3b_statements[] = { { OP(2, 1, 1, OP_CONV), 18, 0235, 61 }, { OP(1, 1, 1, OP_CONV), 24, 0045, 64 }, { OP(1, 1, 1, OP_CONV), 25, 0245, 65 }, + { OP(1, 1, 1, OP_CONV), 28, 0055, 68 }, + { OP(1, 1, 1, OP_CONV), 29, 0255, 69 }, { OP(2, 1, 1, OP_CONV), 32, 0065, 72 }, { OP(2, 1, 1, OP_CONV), 34, 0265, 73 }, { OP(2, 1, 1, OP_CONV), 40, 0075, 76 }, @@ -128,6 +134,7 @@ static dstatement_t bool32_conv_4_statements[] = { { OP(2, 1, 1, OP_CONV), 8, 0325, 56 }, { OP(2, 1, 1, OP_CONV), 16, 0335, 60 }, { OP(1, 1, 1, OP_CONV), 24, 0345, 64 }, + { OP(1, 1, 1, OP_CONV), 28, 0355, 68 }, { OP(2, 1, 1, OP_CONV), 32, 0365, 72 }, { OP(2, 1, 1, OP_CONV), 40, 0375, 76 }, }; diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c index 58bafe43c..7fd62c1ac 100644 --- a/libs/gamecode/test/test-conv6.c +++ b/libs/gamecode/test/test-conv6.c @@ -50,16 +50,16 @@ static pr_ivec4_t ulong_conv_expect[] = { { 0x80000000, 0xffffffff, 0x7fffffff, 0}, { 1, 0, -1, -1}, // float { 0, 0, 0, 0x80000000}, // undef? - { 0, 0, 0, 0}, // long - { 0, 0, 0, 0}, + { 99, 0x80000000, 0x80000000, 99}, // long + { 256, 0, 0x7fffffff, 0}, { 0, 0, 0, 0x80000000}, // double undef? { 1, 0, -1, -1}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool32 { 1, 0, 0, 0}, - { 0, 0, 0, 0}, // ulong - { 0, 0, 0, 0}, + { 99, 0x80000000, 0x80000000, 99}, // ulong + { 256, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool64 { 1, 0, 0, 0}, }; @@ -76,11 +76,13 @@ static dstatement_t ulong_conv_1_statements[] = { { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, { OP(1, 1, 2, OP_CONV), 0, 0006, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0016, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0026, 64 }, { OP(2, 1, 2, OP_CONV), 16, 0036, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0046, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0056, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0066, 96 }, { OP(2, 1, 2, OP_CONV), 40, 0076, 104 }, - { OP(0, 0, 0, OP_JUMP_A), -12, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t ulong_conv_2_statements[] = { @@ -95,11 +97,13 @@ static dstatement_t ulong_conv_2_statements[] = { { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, { OP(1, 1, 2, OP_CONV), 0, 0106, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0116, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0126, 64 }, { OP(2, 1, 2, OP_CONV), 16, 0136, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0146, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0156, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0166, 96 }, { OP(2, 1, 2, OP_CONV), 40, 0176, 104 }, - { OP(0, 0, 0, OP_JUMP_A), -12, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t ulong_conv_3a_statements[] = { @@ -107,12 +111,16 @@ static dstatement_t ulong_conv_3a_statements[] = { { OP(1, 1, 2, OP_CONV), 3, 0006, 54 }, { OP(1, 1, 2, OP_CONV), 4, 0216, 56 }, { OP(1, 1, 2, OP_CONV), 7, 0016, 62 }, + { OP(2, 1, 2, OP_CONV), 8, 0226, 64 }, + { OP(2, 1, 2, OP_CONV), 14, 0026, 70 }, { OP(2, 1, 2, OP_CONV), 16, 0236, 72 }, { OP(2, 1, 2, OP_CONV), 22, 0036, 78 }, { OP(1, 1, 2, OP_CONV), 24, 0246, 80 }, { OP(1, 1, 2, OP_CONV), 27, 0046, 86 }, { OP(1, 1, 2, OP_CONV), 28, 0256, 88 }, { OP(1, 1, 2, OP_CONV), 31, 0056, 94 }, + { OP(2, 1, 2, OP_CONV), 32, 0266, 96 }, + { OP(2, 1, 2, OP_CONV), 38, 0066, 102 }, { OP(2, 1, 2, OP_CONV), 40, 0276, 104 }, { OP(2, 1, 2, OP_CONV), 46, 0076, 110 }, }; @@ -122,12 +130,16 @@ static dstatement_t ulong_conv_3b_statements[] = { { OP(1, 1, 2, OP_CONV), 1, 0206, 50 }, { OP(1, 1, 2, OP_CONV), 4, 0016, 56 }, { OP(1, 1, 2, OP_CONV), 5, 0216, 58 }, + { OP(2, 1, 2, OP_CONV), 8, 0026, 64 }, + { OP(2, 1, 2, OP_CONV), 10, 0226, 66 }, { OP(2, 1, 2, OP_CONV), 16, 0036, 72 }, { OP(2, 1, 2, OP_CONV), 18, 0236, 74 }, { OP(1, 1, 2, OP_CONV), 24, 0046, 80 }, { OP(1, 1, 2, OP_CONV), 25, 0246, 82 }, { OP(1, 1, 2, OP_CONV), 28, 0056, 88 }, { OP(1, 1, 2, OP_CONV), 29, 0256, 90 }, + { OP(2, 1, 2, OP_CONV), 32, 0066, 96 }, + { OP(2, 1, 2, OP_CONV), 34, 0266, 98 }, { OP(2, 1, 2, OP_CONV), 40, 0076, 104 }, { OP(2, 1, 2, OP_CONV), 42, 0276, 106 }, }; @@ -135,9 +147,11 @@ static dstatement_t ulong_conv_3b_statements[] = { static dstatement_t ulong_conv_4_statements[] = { { OP(1, 1, 2, OP_CONV), 0, 0306, 48 }, { OP(1, 1, 2, OP_CONV), 4, 0316, 56 }, + { OP(2, 1, 2, OP_CONV), 8, 0326, 64 }, { OP(2, 1, 2, OP_CONV), 16, 0336, 72 }, { OP(1, 1, 2, OP_CONV), 24, 0346, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0356, 88 }, + { OP(2, 1, 2, OP_CONV), 32, 0366, 96 }, { OP(2, 1, 2, OP_CONV), 40, 0376, 104 }, }; diff --git a/libs/gamecode/test/test-conv7.c b/libs/gamecode/test/test-conv7.c index 9612b1ee0..c8f9354c0 100644 --- a/libs/gamecode/test/test-conv7.c +++ b/libs/gamecode/test/test-conv7.c @@ -60,8 +60,8 @@ static pr_ivec4_t bool64_conv_expect[] = { { 0xffffffff, 0xffffffff, 0, 0}, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, // ulong { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}, - { 0, 0, 0, 0}, // bool64 - { 0, 0, 0, 0}, + { ~0, ~0, ~0, 0}, // bool64 + { 0, ~0, 0, 0}, }; static dstatement_t bool64_conv_1_statements[] = { @@ -81,7 +81,8 @@ static dstatement_t bool64_conv_1_statements[] = { { OP(1, 1, 2, OP_CONV), 24, 0047, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0057, 88 }, { OP(2, 1, 2, OP_CONV), 32, 0067, 96 }, - { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, + { OP(2, 1, 2, OP_CONV), 40, 0077, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t bool64_conv_2_statements[] = { @@ -101,7 +102,8 @@ static dstatement_t bool64_conv_2_statements[] = { { OP(1, 1, 2, OP_CONV), 24, 0147, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0157, 88 }, { OP(2, 1, 2, OP_CONV), 32, 0167, 96 }, - { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, + { OP(2, 1, 2, OP_CONV), 40, 0177, 104 }, + { OP(0, 0, 0, OP_JUMP_A), -14, 0, 0 }, }; static dstatement_t bool64_conv_3a_statements[] = { @@ -119,6 +121,8 @@ static dstatement_t bool64_conv_3a_statements[] = { { OP(1, 1, 2, OP_CONV), 31, 0057, 94 }, { OP(2, 1, 2, OP_CONV), 32, 0267, 96 }, { OP(2, 1, 2, OP_CONV), 38, 0067, 102 }, + { OP(2, 1, 2, OP_CONV), 40, 0277, 104 }, + { OP(2, 1, 2, OP_CONV), 46, 0077, 110 }, }; static dstatement_t bool64_conv_3b_statements[] = { @@ -136,6 +140,8 @@ static dstatement_t bool64_conv_3b_statements[] = { { OP(1, 1, 2, OP_CONV), 29, 0257, 90 }, { OP(2, 1, 2, OP_CONV), 32, 0067, 96 }, { OP(2, 1, 2, OP_CONV), 34, 0267, 98 }, + { OP(2, 1, 2, OP_CONV), 40, 0077, 104 }, + { OP(2, 1, 2, OP_CONV), 42, 0277, 106 }, }; static dstatement_t bool64_conv_4_statements[] = { @@ -146,6 +152,7 @@ static dstatement_t bool64_conv_4_statements[] = { { OP(1, 1, 2, OP_CONV), 24, 0347, 80 }, { OP(1, 1, 2, OP_CONV), 28, 0357, 88 }, { OP(2, 1, 2, OP_CONV), 32, 0367, 96 }, + { OP(2, 1, 2, OP_CONV), 40, 0377, 104 }, }; test_t tests[] = { From 11e89c8c97769f984a305f096622045d16b08f6d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Jan 2022 16:07:11 +0900 Subject: [PATCH 2181/3664] [gamecode] Add tests for lea --- libs/gamecode/test/Makemodule.am | 6 +++++ libs/gamecode/test/test-lea.c | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 libs/gamecode/test/test-lea.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index cdc0824a6..364ebfea6 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -11,6 +11,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-double \ libs/gamecode/test/test-float \ libs/gamecode/test/test-int \ + libs/gamecode/test/test-lea \ libs/gamecode/test/test-load \ libs/gamecode/test/test-long \ libs/gamecode/test/test-mem \ @@ -91,6 +92,11 @@ libs_gamecode_test_test_int_SOURCES= \ libs_gamecode_test_test_int_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_int_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_lea_SOURCES= \ + libs/gamecode/test/test-lea.c +libs_gamecode_test_test_lea_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_lea_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_load_SOURCES= \ libs/gamecode/test/test-load.c libs_gamecode_test_test_load_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-lea.c b/libs/gamecode/test/test-lea.c new file mode 100644 index 000000000..36de277ff --- /dev/null +++ b/libs/gamecode/test/test-lea.c @@ -0,0 +1,41 @@ +#include "head.c" + +static pr_int_t lea_globals_init[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + + 0, 0, 0, 0, 0, +}; + +static pr_int_t lea_globals_expect[] = { + // pointers + 24, 26, 28, 29, + 32, -4, -2, 0, + 1, 4, 0xdeadbeef, 0xfeedf00d, + + 7, 29, 34, 26, 88, +}; + +static dstatement_t lea_statements[] = { + {OP(0, 0, 0, OP_LEA_A), 7, 9, 12}, + {OP(0, 0, 0, OP_LEA_B), 3, 8, 13}, + {OP(0, 0, 0, OP_LEA_C), 2, 6, 14}, + {OP(0, 0, 0, OP_LEA_D), 2, 6, 15}, + {OP(0, 0, 0, OP_LEA_E), 4, 2, 16}, +}; + +test_t tests[] = { + { + .desc = "lea", + .num_globals = num_globals (lea_globals_init, lea_globals_expect), + .num_statements = num_statements (lea_statements), + .statements = lea_statements, + .init_globals = lea_globals_init, + .expect_globals = lea_globals_expect, + .edict_area = 28, + }, +}; + +#include "main.c" From e133de8c89a3245a2164bc2da0b8779c60bd6d96 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Jan 2022 16:27:46 +0900 Subject: [PATCH 2182/3664] [gamecode] Drop B addressing for lea When creating the tests for lea, I noticed that B was yet another simple assign, so I decided it was best to drop it and move E into its place (freeing up another instruction). --- libs/gamecode/opcodes.py | 16 ++---- libs/gamecode/pr_exec.c | 92 ++++++++++++++--------------------- libs/gamecode/test/test-lea.c | 11 ++--- 3 files changed, 44 insertions(+), 75 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 0596636c7..3c8e85cd0 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -25,7 +25,7 @@ bitmap_txt = """ 1 1010 d1xx 1 1011 00mm lea 1 1011 01ss any -1 1011 0100 lea_e +1 1011 0100 1 1011 10ss all 1 1011 1000 pushregs 1 1011 11ss none @@ -176,24 +176,15 @@ lea_formats = { "widths": "0, 0, 1", "types": "ev_pointer, ev_pointer, ev_pointer", "args": { - "op_mode": "ABCD", + "op_mode": "AECD", "lea_fmt": [ "%ga, %gc", - "*%Ga, %gc", + "%Ga.%Gb(%Ea), %gc", "*(%Ga + %sb), %gc", "*(%Ga + %Gb), %gc", ], }, } -lea_e_formats = { - "opcode": "OP_LEA_E", - "mnemonic": "lea", - "opname": "lea", - "format": "{load_fmt[0]}", - "format": "%Ga.%Gb(%Ea), %gc", - "types": "ev_entity, ev_field, ev_pointer", - "widths": "0, 0, 1", -} load_formats = { "opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}", "mnemonic": "load", @@ -461,7 +452,6 @@ group_map = { "compare2": compare2_formats, "convert": convert_formats, "lea": lea_formats, - "lea_e": lea_e_formats, "load": load_formats, "mathops": mathops_formats, "memset": memset_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index abe934815..f8d31a6ec 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1735,41 +1735,10 @@ exit_program: #define STK(type) (*((pr_##type##_t *) (stk))) static pr_type_t * -pr_entity_mode (progs_t *pr, const dstatement_t *st, int shift) +pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) { pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); - int mm_ind = (st->op >> shift) & 3; - pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; - pointer_t mm_offs = 0; - - switch (mm_ind) { - case 0: - // entity.field (equivalent to OP_LOAD_t_v6p) - mm_offs = edict_area + OPA(uint) + OPB(uint); - break; - case 1: - // simple pointer dereference: *a - mm_offs = OPA(uint); - break; - case 2: - // constant indexed pointer: *a + b (supports -ve offset) - mm_offs = OPA(uint) + (short) st->b; - break; - case 3: - // variable indexed pointer: *a + *b (supports -ve offset) - mm_offs = OPA(uint) + OPB(int); - break; - } - return pr->pr_globals + mm_offs; -} - -static pr_type_t * -pr_address_mode (progs_t *pr, const dstatement_t *st, int shift) -{ - pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); - pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); - int mm_ind = (st->op >> shift) & 3; pointer_t mm_offs = 0; switch (mm_ind) { @@ -1789,6 +1758,11 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int shift) // variable indexed pointer: *a + *b (supports -ve offset) mm_offs = OPA(uint) + OPB(int); break; + case 4: + // entity.field (equivalent to OP_LOAD_t_v6p) + pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + mm_offs = edict_area + OPA(uint) + OPB(uint); + break; } return pr->pr_globals + mm_offs; } @@ -2758,31 +2732,43 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) switch (st_op) { // 0 0000 case OP_LOAD_E_1: + mm = pr_address_mode (pr, st, 4); + OPC(int) = MM(int); + break; case OP_LOAD_B_1: case OP_LOAD_C_1: case OP_LOAD_D_1: - mm = pr_entity_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_1) >> 2); OPC(int) = MM(int); break; case OP_LOAD_E_2: + mm = pr_address_mode (pr, st, 4); + OPC(ivec2) = MM(ivec2); + break; case OP_LOAD_B_2: case OP_LOAD_C_2: case OP_LOAD_D_2: - mm = pr_entity_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_2) >> 2); OPC(ivec2) = MM(ivec2); break; case OP_LOAD_E_3: + mm = pr_address_mode (pr, st, 4); + VectorCopy (&MM(int), &OPC(int)); + break; case OP_LOAD_B_3: case OP_LOAD_C_3: case OP_LOAD_D_3: - mm = pr_entity_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_3) >> 2); VectorCopy (&MM(int), &OPC(int)); break; case OP_LOAD_E_4: + mm = pr_address_mode (pr, st, 4); + OPC(ivec4) = MM(ivec4); + break; case OP_LOAD_B_4: case OP_LOAD_C_4: case OP_LOAD_D_4: - mm = pr_entity_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_4) >> 2); OPC(ivec4) = MM(ivec4); break; // 0 0001 @@ -2790,28 +2776,28 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_STORE_B_1: case OP_STORE_C_1: case OP_STORE_D_1: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_STORE_A_1) >> 2); MM(int) = OPC(int); break; case OP_STORE_A_2: case OP_STORE_B_2: case OP_STORE_C_2: case OP_STORE_D_2: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_STORE_A_2) >> 2); MM(ivec2) = OPC(ivec2); break; case OP_STORE_A_3: case OP_STORE_B_3: case OP_STORE_C_3: case OP_STORE_D_3: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_STORE_A_3) >> 2); VectorCopy (&OPC(int), &MM(int)); break; case OP_STORE_A_4: case OP_STORE_B_4: case OP_STORE_C_4: case OP_STORE_D_4: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_STORE_A_4) >> 2); MM(ivec4) = OPC(ivec4); break; // 0 0010 @@ -2819,7 +2805,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_PUSH_B_1: case OP_PUSH_C_1: case OP_PUSH_D_1: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_PUSH_A_1) >> 2); stk = pr_stack_push (pr); STK(int) = MM(int); break; @@ -2827,7 +2813,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_PUSH_B_2: case OP_PUSH_C_2: case OP_PUSH_D_2: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_PUSH_A_2) >> 2); stk = pr_stack_push (pr); STK(ivec2) = MM(ivec2); break; @@ -2835,7 +2821,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_PUSH_B_3: case OP_PUSH_C_3: case OP_PUSH_D_3: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_PUSH_A_3) >> 2); stk = pr_stack_push (pr); VectorCopy (&MM(int), &STK(int)); break; @@ -2843,7 +2829,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_PUSH_B_4: case OP_PUSH_C_4: case OP_PUSH_D_4: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_PUSH_A_4) >> 2); stk = pr_stack_push (pr); STK(ivec4) = MM(ivec4); break; @@ -2852,7 +2838,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_POP_B_1: case OP_POP_C_1: case OP_POP_D_1: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_POP_A_1) >> 2); stk = pr_stack_pop (pr); MM(int) = STK(int); break; @@ -2860,7 +2846,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_POP_B_2: case OP_POP_C_2: case OP_POP_D_2: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_POP_A_2) >> 2); stk = pr_stack_pop (pr); MM(ivec2) = STK(ivec2); break; @@ -2868,7 +2854,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_POP_B_3: case OP_POP_C_3: case OP_POP_D_3: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_POP_A_3) >> 2); stk = pr_stack_pop (pr); VectorCopy (&STK(int), &MM(int)); break; @@ -2876,7 +2862,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_POP_B_4: case OP_POP_C_4: case OP_POP_D_4: - mm = pr_address_mode (pr, st, 2); + mm = pr_address_mode (pr, st, (st_op - OP_POP_A_4) >> 2); stk = pr_stack_pop (pr); MM(ivec4) = STK(ivec4); break; @@ -3342,19 +3328,13 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) // spare // 1 1011 case OP_LEA_A: - case OP_LEA_B: case OP_LEA_C: case OP_LEA_D: - mm = pr_address_mode (pr, st, 0); + mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); op_c->pointer_var = mm - pr->pr_globals; break; case OP_LEA_E: - // ensures OP_LEA_E is compatible with OP_LOAD_E_n and thus - // with pr_entity_mode - mm = __builtin_choose_expr ( - (OP_LEA_E & 3) == 0, - pr_entity_mode (pr, st, 0), - (void) 0); + mm = pr_address_mode (pr, st, 4); op_c->pointer_var = mm - pr->pr_globals; break; case OP_ANY_2: diff --git a/libs/gamecode/test/test-lea.c b/libs/gamecode/test/test-lea.c index 36de277ff..1a4f159f7 100644 --- a/libs/gamecode/test/test-lea.c +++ b/libs/gamecode/test/test-lea.c @@ -6,7 +6,7 @@ static pr_int_t lea_globals_init[] = { 32, -4, -2, 0, 1, 4, 0xdeadbeef, 0xfeedf00d, - 0, 0, 0, 0, 0, + 0, 0, 0, 0, }; static pr_int_t lea_globals_expect[] = { @@ -15,15 +15,14 @@ static pr_int_t lea_globals_expect[] = { 32, -4, -2, 0, 1, 4, 0xdeadbeef, 0xfeedf00d, - 7, 29, 34, 26, 88, + 7, 34, 26, 88, }; static dstatement_t lea_statements[] = { {OP(0, 0, 0, OP_LEA_A), 7, 9, 12}, - {OP(0, 0, 0, OP_LEA_B), 3, 8, 13}, - {OP(0, 0, 0, OP_LEA_C), 2, 6, 14}, - {OP(0, 0, 0, OP_LEA_D), 2, 6, 15}, - {OP(0, 0, 0, OP_LEA_E), 4, 2, 16}, + {OP(0, 0, 0, OP_LEA_C), 2, 6, 13}, + {OP(0, 0, 0, OP_LEA_D), 2, 6, 14}, + {OP(0, 0, 0, OP_LEA_E), 4, 2, 15}, }; test_t tests[] = { From a14b9f8252068b606f66ea39b2cdfec23bf2a6fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Jan 2022 16:39:52 +0900 Subject: [PATCH 2183/3664] [gamecode] Move the lea block It just feels better with it being close the load/store etc --- libs/gamecode/opcodes.py | 3 ++- libs/gamecode/pr_exec.c | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 3c8e85cd0..5e491510b 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -11,6 +11,7 @@ bitmap_txt = """ 0 0101 1100 return (size in st->c) 0 0110 0nnn +0 0110 10mm lea 0 0110 1100 convert (conversion mode in st->b) 0 0110 1101 with (mode in st->a, value in st->b, reg in st->c) 0 0110 111t state @@ -23,7 +24,7 @@ bitmap_txt = """ 1 1001 t1ss scale 1 1001 t100 swizzle 1 1010 d1xx -1 1011 00mm lea +1 1011 00nn 1 1011 01ss any 1 1011 0100 1 1011 10ss all diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index f8d31a6ec..80f9161af 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2961,7 +2961,16 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; // 0 0110 // 0nnn spare - // 10nn spare + case OP_LEA_A: + case OP_LEA_C: + case OP_LEA_D: + mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); + op_c->pointer_var = mm - pr->pr_globals; + break; + case OP_LEA_E: + mm = pr_address_mode (pr, st, 4); + op_c->pointer_var = mm - pr->pr_globals; + break; case OP_CONV: switch (st->b) { #include "libs/gamecode/pr_convert.cinc" @@ -3327,16 +3336,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_cmp_T (GT, U, long, lvec2, lvec4, >, ulong, ulvec2, ulvec4); // spare // 1 1011 - case OP_LEA_A: - case OP_LEA_C: - case OP_LEA_D: - mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); - op_c->pointer_var = mm - pr->pr_globals; - break; - case OP_LEA_E: - mm = pr_address_mode (pr, st, 4); - op_c->pointer_var = mm - pr->pr_globals; - break; + // 00nn spare case OP_ANY_2: OPC(int) = any2i (OPA(ivec2)); break; From 38ab0f0243b754e8a7d94e4f9aeea8aae6e794a4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Jan 2022 16:51:59 +0900 Subject: [PATCH 2184/3664] [gamecode] Move pushregs and popregs into with This frees up another two instructions. --- libs/gamecode/opcodes.py | 4 +- libs/gamecode/pr_exec.c | 101 ++++++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 47 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 5e491510b..ceccba4a7 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -28,9 +28,9 @@ bitmap_txt = """ 1 1011 01ss any 1 1011 0100 1 1011 10ss all -1 1011 1000 pushregs +1 1011 1000 1 1011 11ss none -1 1011 1100 popregs +1 1011 1100 1 1101 01oo move 1 1101 11oo memset 1 1110 d1xx diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 80f9161af..b3a4afae9 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1861,42 +1861,6 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st) return jump_offs - 1; // for st++ } -static pr_pointer_t __attribute__((pure)) -pr_with (progs_t *pr, const dstatement_t *st) -{ - pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; - pr_type_t *op_b = pr->pr_globals + PR_BASE (pr, st, B) + st->b; - - switch (st->a) { - // fixed offset - case 0: - // hard-0 base - return st->b; - case 1: - // relative to current base - return PR_BASE (pr, st, B) + st->b; - case 2: - // relative to stack (-ve offset) - return *pr->globals.stack + (pr_short_t) st->b; - case 3: - // relative to edict_area (+ve only) - return edict_area + st->b; - - case 4: - // hard-0 base - return pr->pr_globals[st->b].pointer_var; - case 5: - return OPB(pointer); - case 6: - // relative to stack (-ve offset) - return *pr->globals.stack + OPB(int); - case 7: - // relative to edict_area (+ve only) - return edict_area + OPB(uint); - } - PR_RunError (pr, "Invalid with index: %u", st->a); -} - static pr_type_t * pr_stack_push (progs_t *pr) { @@ -1923,6 +1887,59 @@ pr_stack_pop (progs_t *pr) return stk; } +static void +pr_with (progs_t *pr, const dstatement_t *st) +{ + pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + pr_type_t *op_b = pr->pr_globals + PR_BASE (pr, st, B) + st->b; + pr_type_t *stk; + + switch (st->a) { + // fixed offset + case 0: + // hard-0 base + pr->pr_bases[st->c & 3] = st->b; + return; + case 1: + // relative to current base + pr->pr_bases[st->c & 3] = PR_BASE (pr, st, B) + st->b; + return; + case 2: + // relative to stack (-ve offset) + pr->pr_bases[st->c & 3] = *pr->globals.stack + (pr_short_t) st->b; + return; + case 3: + // relative to edict_area (+ve only) + pr->pr_bases[st->c & 3] = edict_area + st->b; + return; + + case 4: + // hard-0 base + pr->pr_bases[st->c & 3] = pr->pr_globals[st->b].pointer_var; + return; + case 5: + pr->pr_bases[st->c & 3] = OPB(pointer); + return; + case 6: + // relative to stack (-ve offset) + pr->pr_bases[st->c & 3] = *pr->globals.stack + OPB(int); + return; + case 7: + // relative to edict_area (+ve only) + pr->pr_bases[st->c & 3] = edict_area + OPB(uint); + return; + case 8: + stk = pr_stack_push (pr); + STK(uivec4) = pr->pr_bases; + return; + case 9: + stk = pr_stack_pop (pr); + pr->pr_bases = STK(uivec4); + return; + } + PR_RunError (pr, "Invalid with index: %u", st->a); +} + static pr_ivec4_t pr_swizzle_f (pr_ivec4_t vec, pr_ushort_t swiz) { @@ -2980,7 +2997,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) } break; case OP_WITH: - pr->pr_bases[st->c & 3] = pr_with (pr, st); + pr_with (pr, st); break; case OP_STATE_ft: { @@ -3349,10 +3366,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_ANY_4: OPC(int) = any4i (OPA(ivec4)); break; - case OP_PUSHREGS: - stk = pr_stack_push (pr); - STK(uivec4) = pr->pr_bases; - break; + // spare case OP_ALL_2: OPC(int) = all2i (OPA(ivec2)); break; @@ -3366,10 +3380,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_ALL_4: OPC(int) = all4i (OPA(ivec4)); break; - case OP_POPREGS: - stk = pr_stack_pop (pr); - pr->pr_bases = STK(uivec4); - break; + // spare case OP_NONE_2: OPC(int) = none2i (OPA(ivec2)); break; From 49dcd5ef4092a08753e785ec08345cb59fddd7a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Jan 2022 18:44:11 +0900 Subject: [PATCH 2185/3664] [gamecode] Add tests for the with instruction(s) While mode 4 was tested a lot, none of the rest were. Also added a full reset instruction. --- libs/gamecode/pr_exec.c | 30 +-- libs/gamecode/test/Makemodule.am | 16 +- libs/gamecode/test/test-with.c | 307 +++++++++++++++++++++++++++++++ 3 files changed, 337 insertions(+), 16 deletions(-) create mode 100644 libs/gamecode/test/test-with.c diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index b3a4afae9..69d9c0f6f 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1893,49 +1893,57 @@ pr_with (progs_t *pr, const dstatement_t *st) pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; pr_type_t *op_b = pr->pr_globals + PR_BASE (pr, st, B) + st->b; pr_type_t *stk; + pr_uint_t *base = &pr->pr_bases[st->c & 3]; switch (st->a) { // fixed offset case 0: // hard-0 base - pr->pr_bases[st->c & 3] = st->b; + *base = st->b; return; case 1: - // relative to current base - pr->pr_bases[st->c & 3] = PR_BASE (pr, st, B) + st->b; + // relative to current base (-ve offset) + *base = PR_BASE (pr, st, B) + (pr_short_t) st->b; return; case 2: // relative to stack (-ve offset) - pr->pr_bases[st->c & 3] = *pr->globals.stack + (pr_short_t) st->b; + *base = *pr->globals.stack + (pr_short_t) st->b; return; case 3: - // relative to edict_area (+ve only) - pr->pr_bases[st->c & 3] = edict_area + st->b; + // relative to edict_area (only +ve) + *base = edict_area + st->b; return; case 4: // hard-0 base - pr->pr_bases[st->c & 3] = pr->pr_globals[st->b].pointer_var; + *base = pr->pr_globals[st->b].pointer_var; return; case 5: - pr->pr_bases[st->c & 3] = OPB(pointer); + *base = OPB(pointer); return; case 6: // relative to stack (-ve offset) - pr->pr_bases[st->c & 3] = *pr->globals.stack + OPB(int); + *base = *pr->globals.stack + OPB(int); return; case 7: - // relative to edict_area (+ve only) - pr->pr_bases[st->c & 3] = edict_area + OPB(uint); + // relative to edict_area (only +ve) + *base = edict_area + OPB(uint); return; + case 8: + // pushregs stk = pr_stack_push (pr); STK(uivec4) = pr->pr_bases; return; case 9: + // popregs stk = pr_stack_pop (pr); pr->pr_bases = STK(uivec4); return; + case 10: + // reset + pr->pr_bases = (pr_uivec4_t) {}; + return; } PR_RunError (pr, "Invalid with index: %u", st->a); } diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 364ebfea6..8fc813622 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -20,7 +20,8 @@ libs_gamecode_tests = \ libs/gamecode/test/test-store \ libs/gamecode/test/test-string \ libs/gamecode/test/test-unsigned \ - libs/gamecode/test/test-vector + libs/gamecode/test/test-vector \ + libs/gamecode/test/test-with TESTS += $(libs_gamecode_tests) @@ -132,12 +133,17 @@ libs_gamecode_test_test_string_SOURCES= \ libs_gamecode_test_test_string_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_string_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_unsigned_SOURCES= \ + libs/gamecode/test/test-unsigned.c +libs_gamecode_test_test_unsigned_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_unsigned_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_vector_SOURCES= \ libs/gamecode/test/test-vector.c libs_gamecode_test_test_vector_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_vector_DEPENDENCIES= $(test_gamecode_libs) -libs_gamecode_test_test_unsigned_SOURCES= \ - libs/gamecode/test/test-unsigned.c -libs_gamecode_test_test_unsigned_LDADD= $(test_gamecode_libs) -libs_gamecode_test_test_unsigned_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_with_SOURCES= \ + libs/gamecode/test/test-with.c +libs_gamecode_test_test_with_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_with_DEPENDENCIES= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-with.c b/libs/gamecode/test/test-with.c new file mode 100644 index 000000000..f86637360 --- /dev/null +++ b/libs/gamecode/test/test-with.c @@ -0,0 +1,307 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define DB 0xdeadbeef + +static pr_ivec4_t pushregs_init[] = { + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t pushregs_expect[] = { + { 0, 0, 0, 0}, // initial base regs should all be 0 +}; + +static dstatement_t pushregs_statements[] = { + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 0, 0, 0 }, +}; + +static pr_ivec4_t popregs_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t popregs_expect[] = { + { 4, 5, 6, 7}, + { 7, 6, 5, 4}, +}; + +static dstatement_t popregs_statements[] = { + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 9, 0, 0 }, // popregs + { OP(3, 0, 0, OP_LEA_A), 0, 0, 0 }, + { OP(2, 0, 1, OP_LEA_A), 0, 0, 0 }, + { OP(1, 0, 2, OP_LEA_A), 0, 0, 0 }, + { OP(0, 0, 3, OP_LEA_A), 0, 0, 0 }, +}; + +static pr_ivec4_t with_0_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_0_expect[] = { + { 4, 5, 6, 7}, + { 0, 1, 6, 7}, + { 4, 5, 0, 1}, + { 0, 0, 0, 0}, +}; + +static dstatement_t with_0_statements[] = { + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 9, 0, 0 }, // popregs + { OP(0, 0, 0, OP_WITH), 0, 0, 0 }, // set reg 0 to 0 + { OP(0, 0, 0, OP_WITH), 0, 1, 1 }, // set reg 1 to 1 + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 9, 0, 0 }, // popregs + { OP(0, 0, 0, OP_WITH), 0, 0, 2 }, // set reg 2 to 0 + { OP(0, 0, 0, OP_WITH), 0, 1, 3 }, // set reg 3 to 1 + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(2, 0, 0, OP_POP_A_4), 8, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 10, 0, 0 }, // reset + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(2, 0, 0, OP_POP_A_4), 12, 0, 0 }, +}; + +static pr_ivec4_t with_1_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_1_expect[] = { + { 4, 5, 6, 7}, + { 0, 4, 6, 2}, +}; + +static dstatement_t with_1_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 4, 1 }, + { OP(0, 1, 0, OP_WITH), 1, 2, 2 }, + { OP(0, 1, 0, OP_WITH), 1, -2, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_2_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_2_expect[] = { + { 4, 5, 6, 7}, + { 0, 44, 48, 40}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static dstatement_t with_2_statements[] = { + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, // so something is on the stack + { OP(0, 0, 0, OP_WITH), 2, 0, 1 }, + { OP(0, 1, 0, OP_WITH), 2, 4, 2 }, + { OP(0, 1, 0, OP_WITH), 2, -4, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_3_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_3_expect[] = { + { 4, 5, 6, 7}, + { 0, 64, 68, 65596}, // edict-area relative is only +ve +}; + +static dstatement_t with_3_statements[] = { + { OP(0, 0, 0, OP_WITH), 3, 0, 1 }, + { OP(0, 1, 0, OP_WITH), 3, 4, 2 }, + { OP(0, 1, 0, OP_WITH), 3, -4, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_4_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_4_expect[] = { + { 4, 5, 6, 7}, + { 0, 4, 5, 6}, +}; + +static dstatement_t with_4_statements[] = { + { OP(0, 0, 0, OP_WITH), 4, 0, 1 }, + { OP(0, 1, 0, OP_WITH), 4, 1, 2 }, + { OP(0, 1, 0, OP_WITH), 4, 2, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_5_init[] = { + { 4, 5, 6, 7}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_5_expect[] = { + { 4, 5, 6, 7}, + { 0, 2, 6, 7}, +}; + +static dstatement_t with_5_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 2, 1 }, + { OP(0, 1, 0, OP_WITH), 5, 0, 2 }, + { OP(0, 1, 0, OP_WITH), 5, 1, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_6_init[] = { + { 4, 5, 6, -4}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_6_expect[] = { + { 4, 5, 6, -4}, + { 0, 44, 48, 40}, + { DB, DB, DB, DB}, + { DB, DB, DB, DB}, +}; + +static dstatement_t with_6_statements[] = { + { OP(0, 0, 0, OP_PUSH_A_4), 0, 0, 0 }, // so something is on the stack + { OP(0, 0, 0, OP_WITH), 2, 0, 1 }, + { OP(0, 1, 0, OP_WITH), 6, 0, 2 }, + { OP(0, 1, 0, OP_WITH), 6, 3, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +static pr_ivec4_t with_7_init[] = { + { 4, 5, 6, -4}, + { DB, DB, DB, DB}, +}; + +static pr_ivec4_t with_7_expect[] = { + { 4, 5, 6, -4}, + { 0, 2, 70, 60}, // edict-area relative is only +ve, but 32-bit wrap +}; + +static dstatement_t with_7_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 2, 1 }, + { OP(0, 1, 0, OP_WITH), 7, 0, 2 }, + { OP(0, 1, 0, OP_WITH), 7, 1, 3 }, + { OP(0, 0, 0, OP_WITH), 8, 0, 0 }, // pushregs + { OP(0, 0, 0, OP_POP_A_4), 4, 0, 0 }, +}; + +test_t tests[] = { + { + .desc = "pushregs", + .num_globals = num_globals(pushregs_init,pushregs_expect), + .num_statements = num_statements (pushregs_statements), + .statements = pushregs_statements, + .init_globals = (pr_int_t *) pushregs_init, + .expect_globals = (pr_int_t *) pushregs_expect, + .stack_size = 32, + }, + { + .desc = "popregs", + .num_globals = num_globals(popregs_init,popregs_expect), + .num_statements = num_statements (popregs_statements), + .statements = popregs_statements, + .init_globals = (pr_int_t *) popregs_init, + .expect_globals = (pr_int_t *) popregs_expect, + .stack_size = 32, + }, + { + .desc = "with 0", + .num_globals = num_globals(with_0_init,with_0_expect), + .num_statements = num_statements (with_0_statements), + .statements = with_0_statements, + .init_globals = (pr_int_t *) with_0_init, + .expect_globals = (pr_int_t *) with_0_expect, + .stack_size = 32, + }, + { + .desc = "with 1", + .num_globals = num_globals(with_1_init,with_1_expect), + .num_statements = num_statements (with_1_statements), + .statements = with_1_statements, + .init_globals = (pr_int_t *) with_1_init, + .expect_globals = (pr_int_t *) with_1_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 2", + .num_globals = num_globals(with_2_init,with_2_expect), + .num_statements = num_statements (with_2_statements), + .statements = with_2_statements, + .init_globals = (pr_int_t *) with_2_init, + .expect_globals = (pr_int_t *) with_2_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 3", + .num_globals = num_globals(with_3_init,with_3_expect), + .num_statements = num_statements (with_3_statements), + .statements = with_3_statements, + .init_globals = (pr_int_t *) with_3_init, + .expect_globals = (pr_int_t *) with_3_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 4", + .num_globals = num_globals(with_4_init,with_4_expect), + .num_statements = num_statements (with_4_statements), + .statements = with_4_statements, + .init_globals = (pr_int_t *) with_4_init, + .expect_globals = (pr_int_t *) with_4_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 5", + .num_globals = num_globals(with_5_init,with_5_expect), + .num_statements = num_statements (with_5_statements), + .statements = with_5_statements, + .init_globals = (pr_int_t *) with_5_init, + .expect_globals = (pr_int_t *) with_5_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 6", + .num_globals = num_globals(with_6_init,with_6_expect), + .num_statements = num_statements (with_6_statements), + .statements = with_6_statements, + .init_globals = (pr_int_t *) with_6_init, + .expect_globals = (pr_int_t *) with_6_expect, + .stack_size = 32, + .edict_area = 64, + }, + { + .desc = "with 7", + .num_globals = num_globals(with_7_init,with_7_expect), + .num_statements = num_statements (with_7_statements), + .statements = with_7_statements, + .init_globals = (pr_int_t *) with_7_init, + .expect_globals = (pr_int_t *) with_7_expect, + .stack_size = 32, + .edict_area = 64, + }, +}; + +#include "main.c" From dc4df49fff85a6dd2b096abecbc8816d34c447bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Jan 2022 22:44:58 +0900 Subject: [PATCH 2186/3664] [gamecode] Add tests for the swizzle instructions While not always generated (yet?) the tests are at least in. Just not sure about auto-generated tests that can't be hand-edited. --- libs/gamecode/swizzle.py | 170 ++- libs/gamecode/test/Makemodule.am | 6 + libs/gamecode/test/test-swizzle.c | 1846 +++++++++++++++++++++++++++++ 3 files changed, 2018 insertions(+), 4 deletions(-) create mode 100644 libs/gamecode/test/test-swizzle.c diff --git a/libs/gamecode/swizzle.py b/libs/gamecode/swizzle.py index 673f5aec4..f61d50de5 100644 --- a/libs/gamecode/swizzle.py +++ b/libs/gamecode/swizzle.py @@ -5,6 +5,12 @@ def iter(func): for l in range(4): func(i, j, k, l) +def iter16(func): + for i in range(16): + func(i) + +import sys + coord=['x', 'y', 'z', 'w'] def label(i, j, k, l): return f"swizzle_{coord[l]}{coord[k]}{coord[j]}{coord[i]}" @@ -15,7 +21,163 @@ def print_ref(i, j, k, l): def print_op(i, j, k, l): print(f"\t{label(i, j, k, l)}: vec = swizzle (vec, (pr_ivec4_t) {{ {l}, {k}, {j}, {i} }}); goto negate;") -iter(print_op) -print("\tstatic void *swizzle_table[256] = {") -iter(print_ref) -print("\t};") +def print_data(i, j, k, l): + print(f"\t{{ {l+1:2}, {k+1:2}, {j+1:2}, {i+1:2} }},") + +def print_swizzle_f(i, j, k, l): + swiz = i * 64 + j * 16 + k * 4 + l + addr = (swiz + 1) * 4 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x{swiz:04x}, {addr} }},") + +def print_neg_f(i): + swiz = i * 0x100 + 0xe4 + addr = (i + 1) * 4 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x{swiz:04x}, {addr} }},") + +def print_zero_f(i): + swiz = i * 0x1000 + 0xe4 + addr = (i + 1) * 4 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x{swiz:04x}, {addr} }},") + +def print_swizzle_d(i, j, k, l): + swiz = i * 64 + j * 16 + k * 4 + l + addr = (swiz + 1) * 8 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x{swiz:04x}, {addr} }},") + +def print_neg_d(i): + swiz = i * 0x100 + 0xe4 + addr = (i + 1) * 8 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x{swiz:04x}, {addr} }},") + +def print_zero_d(i): + swiz = i * 0x1000 + 0xe4 + addr = (i + 1) * 8 + print(f"\t{{ OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x{swiz:04x}, {addr} }},") + +def print_eights(i, j, k, l): + print(f"\t{{ {8:2}, {8:2}, {8:2}, {8:2} }},") + +def print_nines(i): + print(f"\t{{ {9:2}, {9:2}, {9:2}, {9:2} }},") + +def print_neg(n): + x = [1, 2, 3, 4] + for i in range(4): + if n & (1<< i): + x[i] = -x[i] + print(f"\t{{ {x[0]:2}, {x[1]:2}, {x[2]:2}, {x[3]:2} }},") + +def print_zero(z): + x = [1, 2, 3, 4] + for i in range(4): + if z & (1<< i): + x[i] = 0 + print(f"\t{{ {x[0]:2}, {x[1]:2}, {x[2]:2}, {x[3]:2} }},") + +types = ["f", "d"] +tests = ["swizzle", "neg", "zero"] + +if sys.argv[1] == "case": + iter(print_op) + print("\tstatic void *swizzle_table[256] = {") + iter(print_ref) + print("\t};") +elif sys.argv[1] == "test": + print('#include "head.c"') + print() + print("static pr_vec4_t swizzle_f_init[] = {") + print_data(3, 2, 1, 0) + iter(print_eights) + print("};") + print("static pr_vec4_t swizzle_f_expect[] = {") + print_data(3, 2, 1, 0) + iter(print_data) + print("};") + print() + print("static dstatement_t swizzle_f_statements[] = {") + iter(print_swizzle_f) + print("};") + print() + print("static pr_vec4_t neg_f_init[] = {") + print_neg(0) + iter16(print_nines) + print("};") + print() + print("static pr_vec4_t neg_f_expect[] = {") + print_neg(0) + iter16(print_neg) + print("};") + print() + print("static dstatement_t neg_f_statements[] = {") + iter16(print_neg_f) + print("};") + print() + print("static pr_vec4_t zero_f_init[] = {") + print_zero(0) + iter16(print_nines) + print("};") + print() + print("static pr_vec4_t zero_f_expect[] = {") + print_zero(0) + iter16(print_zero) + print("};") + print() + print("static dstatement_t zero_f_statements[] = {") + iter16(print_zero_f) + print("};") + print() + print("static pr_dvec4_t swizzle_d_init[] = {") + print_data(3, 2, 1, 0) + iter(print_eights) + print("};") + print("static pr_dvec4_t swizzle_d_expect[] = {") + print_data(3, 2, 1, 0) + iter(print_data) + print("};") + print() + print("static dstatement_t swizzle_d_statements[] = {") + iter(print_swizzle_d) + print("};") + print() + print("static pr_dvec4_t neg_d_init[] = {") + print_neg(0) + iter16(print_nines) + print("};") + print() + print("static pr_dvec4_t neg_d_expect[] = {") + print_neg(0) + iter16(print_neg) + print("};") + print() + print("static dstatement_t neg_d_statements[] = {") + iter16(print_neg_d) + print("};") + print() + print("static pr_dvec4_t zero_d_init[] = {") + print_zero(0) + iter16(print_nines) + print("};") + print() + print("static pr_dvec4_t zero_d_expect[] = {") + print_zero(0) + iter16(print_zero) + print("};") + print() + print("static dstatement_t zero_d_statements[] = {") + iter16(print_zero_d) + print("};") + print() + print("test_t tests[] = {") + for t in types: + for o in tests: + print("\t{") + print(f'\t\t.desc = "{o} {t}",') + print(f"\t\t.num_globals = num_globals({o}_{t}_init,{o}_{t}_expect),") + print(f"\t\t.num_statements = num_statements({o}_{t}_statements),") + print(f"\t\t.statements = {o}_{t}_statements,") + print(f"\t\t.init_globals = (pr_int_t *) {o}_{t}_init,") + print(f"\t\t.expect_globals = (pr_int_t *) {o}_{t}_expect,") + print("\t},") + print("};") + print() + print('#include "main.c"') diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 8fc813622..0788861f8 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -19,6 +19,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-stack \ libs/gamecode/test/test-store \ libs/gamecode/test/test-string \ + libs/gamecode/test/test-swizzle \ libs/gamecode/test/test-unsigned \ libs/gamecode/test/test-vector \ libs/gamecode/test/test-with @@ -133,6 +134,11 @@ libs_gamecode_test_test_string_SOURCES= \ libs_gamecode_test_test_string_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_string_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_swizzle_SOURCES= \ + libs/gamecode/test/test-swizzle.c +libs_gamecode_test_test_swizzle_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_swizzle_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_unsigned_SOURCES= \ libs/gamecode/test/test-unsigned.c libs_gamecode_test_test_unsigned_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-swizzle.c b/libs/gamecode/test/test-swizzle.c new file mode 100644 index 000000000..c47acbb5c --- /dev/null +++ b/libs/gamecode/test/test-swizzle.c @@ -0,0 +1,1846 @@ +#include "head.c" + +static pr_vec4_t swizzle_f_init[] = { + { 1, 2, 3, 4 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, +}; +static pr_vec4_t swizzle_f_expect[] = { + { 1, 2, 3, 4 }, + { 1, 1, 1, 1 }, + { 2, 1, 1, 1 }, + { 3, 1, 1, 1 }, + { 4, 1, 1, 1 }, + { 1, 2, 1, 1 }, + { 2, 2, 1, 1 }, + { 3, 2, 1, 1 }, + { 4, 2, 1, 1 }, + { 1, 3, 1, 1 }, + { 2, 3, 1, 1 }, + { 3, 3, 1, 1 }, + { 4, 3, 1, 1 }, + { 1, 4, 1, 1 }, + { 2, 4, 1, 1 }, + { 3, 4, 1, 1 }, + { 4, 4, 1, 1 }, + { 1, 1, 2, 1 }, + { 2, 1, 2, 1 }, + { 3, 1, 2, 1 }, + { 4, 1, 2, 1 }, + { 1, 2, 2, 1 }, + { 2, 2, 2, 1 }, + { 3, 2, 2, 1 }, + { 4, 2, 2, 1 }, + { 1, 3, 2, 1 }, + { 2, 3, 2, 1 }, + { 3, 3, 2, 1 }, + { 4, 3, 2, 1 }, + { 1, 4, 2, 1 }, + { 2, 4, 2, 1 }, + { 3, 4, 2, 1 }, + { 4, 4, 2, 1 }, + { 1, 1, 3, 1 }, + { 2, 1, 3, 1 }, + { 3, 1, 3, 1 }, + { 4, 1, 3, 1 }, + { 1, 2, 3, 1 }, + { 2, 2, 3, 1 }, + { 3, 2, 3, 1 }, + { 4, 2, 3, 1 }, + { 1, 3, 3, 1 }, + { 2, 3, 3, 1 }, + { 3, 3, 3, 1 }, + { 4, 3, 3, 1 }, + { 1, 4, 3, 1 }, + { 2, 4, 3, 1 }, + { 3, 4, 3, 1 }, + { 4, 4, 3, 1 }, + { 1, 1, 4, 1 }, + { 2, 1, 4, 1 }, + { 3, 1, 4, 1 }, + { 4, 1, 4, 1 }, + { 1, 2, 4, 1 }, + { 2, 2, 4, 1 }, + { 3, 2, 4, 1 }, + { 4, 2, 4, 1 }, + { 1, 3, 4, 1 }, + { 2, 3, 4, 1 }, + { 3, 3, 4, 1 }, + { 4, 3, 4, 1 }, + { 1, 4, 4, 1 }, + { 2, 4, 4, 1 }, + { 3, 4, 4, 1 }, + { 4, 4, 4, 1 }, + { 1, 1, 1, 2 }, + { 2, 1, 1, 2 }, + { 3, 1, 1, 2 }, + { 4, 1, 1, 2 }, + { 1, 2, 1, 2 }, + { 2, 2, 1, 2 }, + { 3, 2, 1, 2 }, + { 4, 2, 1, 2 }, + { 1, 3, 1, 2 }, + { 2, 3, 1, 2 }, + { 3, 3, 1, 2 }, + { 4, 3, 1, 2 }, + { 1, 4, 1, 2 }, + { 2, 4, 1, 2 }, + { 3, 4, 1, 2 }, + { 4, 4, 1, 2 }, + { 1, 1, 2, 2 }, + { 2, 1, 2, 2 }, + { 3, 1, 2, 2 }, + { 4, 1, 2, 2 }, + { 1, 2, 2, 2 }, + { 2, 2, 2, 2 }, + { 3, 2, 2, 2 }, + { 4, 2, 2, 2 }, + { 1, 3, 2, 2 }, + { 2, 3, 2, 2 }, + { 3, 3, 2, 2 }, + { 4, 3, 2, 2 }, + { 1, 4, 2, 2 }, + { 2, 4, 2, 2 }, + { 3, 4, 2, 2 }, + { 4, 4, 2, 2 }, + { 1, 1, 3, 2 }, + { 2, 1, 3, 2 }, + { 3, 1, 3, 2 }, + { 4, 1, 3, 2 }, + { 1, 2, 3, 2 }, + { 2, 2, 3, 2 }, + { 3, 2, 3, 2 }, + { 4, 2, 3, 2 }, + { 1, 3, 3, 2 }, + { 2, 3, 3, 2 }, + { 3, 3, 3, 2 }, + { 4, 3, 3, 2 }, + { 1, 4, 3, 2 }, + { 2, 4, 3, 2 }, + { 3, 4, 3, 2 }, + { 4, 4, 3, 2 }, + { 1, 1, 4, 2 }, + { 2, 1, 4, 2 }, + { 3, 1, 4, 2 }, + { 4, 1, 4, 2 }, + { 1, 2, 4, 2 }, + { 2, 2, 4, 2 }, + { 3, 2, 4, 2 }, + { 4, 2, 4, 2 }, + { 1, 3, 4, 2 }, + { 2, 3, 4, 2 }, + { 3, 3, 4, 2 }, + { 4, 3, 4, 2 }, + { 1, 4, 4, 2 }, + { 2, 4, 4, 2 }, + { 3, 4, 4, 2 }, + { 4, 4, 4, 2 }, + { 1, 1, 1, 3 }, + { 2, 1, 1, 3 }, + { 3, 1, 1, 3 }, + { 4, 1, 1, 3 }, + { 1, 2, 1, 3 }, + { 2, 2, 1, 3 }, + { 3, 2, 1, 3 }, + { 4, 2, 1, 3 }, + { 1, 3, 1, 3 }, + { 2, 3, 1, 3 }, + { 3, 3, 1, 3 }, + { 4, 3, 1, 3 }, + { 1, 4, 1, 3 }, + { 2, 4, 1, 3 }, + { 3, 4, 1, 3 }, + { 4, 4, 1, 3 }, + { 1, 1, 2, 3 }, + { 2, 1, 2, 3 }, + { 3, 1, 2, 3 }, + { 4, 1, 2, 3 }, + { 1, 2, 2, 3 }, + { 2, 2, 2, 3 }, + { 3, 2, 2, 3 }, + { 4, 2, 2, 3 }, + { 1, 3, 2, 3 }, + { 2, 3, 2, 3 }, + { 3, 3, 2, 3 }, + { 4, 3, 2, 3 }, + { 1, 4, 2, 3 }, + { 2, 4, 2, 3 }, + { 3, 4, 2, 3 }, + { 4, 4, 2, 3 }, + { 1, 1, 3, 3 }, + { 2, 1, 3, 3 }, + { 3, 1, 3, 3 }, + { 4, 1, 3, 3 }, + { 1, 2, 3, 3 }, + { 2, 2, 3, 3 }, + { 3, 2, 3, 3 }, + { 4, 2, 3, 3 }, + { 1, 3, 3, 3 }, + { 2, 3, 3, 3 }, + { 3, 3, 3, 3 }, + { 4, 3, 3, 3 }, + { 1, 4, 3, 3 }, + { 2, 4, 3, 3 }, + { 3, 4, 3, 3 }, + { 4, 4, 3, 3 }, + { 1, 1, 4, 3 }, + { 2, 1, 4, 3 }, + { 3, 1, 4, 3 }, + { 4, 1, 4, 3 }, + { 1, 2, 4, 3 }, + { 2, 2, 4, 3 }, + { 3, 2, 4, 3 }, + { 4, 2, 4, 3 }, + { 1, 3, 4, 3 }, + { 2, 3, 4, 3 }, + { 3, 3, 4, 3 }, + { 4, 3, 4, 3 }, + { 1, 4, 4, 3 }, + { 2, 4, 4, 3 }, + { 3, 4, 4, 3 }, + { 4, 4, 4, 3 }, + { 1, 1, 1, 4 }, + { 2, 1, 1, 4 }, + { 3, 1, 1, 4 }, + { 4, 1, 1, 4 }, + { 1, 2, 1, 4 }, + { 2, 2, 1, 4 }, + { 3, 2, 1, 4 }, + { 4, 2, 1, 4 }, + { 1, 3, 1, 4 }, + { 2, 3, 1, 4 }, + { 3, 3, 1, 4 }, + { 4, 3, 1, 4 }, + { 1, 4, 1, 4 }, + { 2, 4, 1, 4 }, + { 3, 4, 1, 4 }, + { 4, 4, 1, 4 }, + { 1, 1, 2, 4 }, + { 2, 1, 2, 4 }, + { 3, 1, 2, 4 }, + { 4, 1, 2, 4 }, + { 1, 2, 2, 4 }, + { 2, 2, 2, 4 }, + { 3, 2, 2, 4 }, + { 4, 2, 2, 4 }, + { 1, 3, 2, 4 }, + { 2, 3, 2, 4 }, + { 3, 3, 2, 4 }, + { 4, 3, 2, 4 }, + { 1, 4, 2, 4 }, + { 2, 4, 2, 4 }, + { 3, 4, 2, 4 }, + { 4, 4, 2, 4 }, + { 1, 1, 3, 4 }, + { 2, 1, 3, 4 }, + { 3, 1, 3, 4 }, + { 4, 1, 3, 4 }, + { 1, 2, 3, 4 }, + { 2, 2, 3, 4 }, + { 3, 2, 3, 4 }, + { 4, 2, 3, 4 }, + { 1, 3, 3, 4 }, + { 2, 3, 3, 4 }, + { 3, 3, 3, 4 }, + { 4, 3, 3, 4 }, + { 1, 4, 3, 4 }, + { 2, 4, 3, 4 }, + { 3, 4, 3, 4 }, + { 4, 4, 3, 4 }, + { 1, 1, 4, 4 }, + { 2, 1, 4, 4 }, + { 3, 1, 4, 4 }, + { 4, 1, 4, 4 }, + { 1, 2, 4, 4 }, + { 2, 2, 4, 4 }, + { 3, 2, 4, 4 }, + { 4, 2, 4, 4 }, + { 1, 3, 4, 4 }, + { 2, 3, 4, 4 }, + { 3, 3, 4, 4 }, + { 4, 3, 4, 4 }, + { 1, 4, 4, 4 }, + { 2, 4, 4, 4 }, + { 3, 4, 4, 4 }, + { 4, 4, 4, 4 }, +}; + +static dstatement_t swizzle_f_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0000, 4 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0001, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0002, 12 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0003, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0004, 20 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0005, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0006, 28 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0007, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0008, 36 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0009, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000a, 44 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000b, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000c, 52 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000d, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000e, 60 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x000f, 64 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0010, 68 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0011, 72 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0012, 76 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0013, 80 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0014, 84 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0015, 88 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0016, 92 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0017, 96 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0018, 100 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0019, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001a, 108 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001b, 112 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001c, 116 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001d, 120 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001e, 124 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x001f, 128 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0020, 132 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0021, 136 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0022, 140 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0023, 144 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0024, 148 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0025, 152 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0026, 156 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0027, 160 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0028, 164 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0029, 168 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002a, 172 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002b, 176 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002c, 180 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002d, 184 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002e, 188 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x002f, 192 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0030, 196 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0031, 200 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0032, 204 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0033, 208 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0034, 212 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0035, 216 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0036, 220 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0037, 224 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0038, 228 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0039, 232 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003a, 236 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003b, 240 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003c, 244 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003d, 248 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003e, 252 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x003f, 256 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0040, 260 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0041, 264 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0042, 268 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0043, 272 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0044, 276 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0045, 280 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0046, 284 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0047, 288 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0048, 292 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0049, 296 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004a, 300 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004b, 304 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004c, 308 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004d, 312 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004e, 316 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x004f, 320 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0050, 324 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0051, 328 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0052, 332 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0053, 336 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0054, 340 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0055, 344 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0056, 348 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0057, 352 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0058, 356 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0059, 360 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005a, 364 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005b, 368 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005c, 372 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005d, 376 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005e, 380 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x005f, 384 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0060, 388 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0061, 392 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0062, 396 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0063, 400 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0064, 404 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0065, 408 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0066, 412 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0067, 416 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0068, 420 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0069, 424 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006a, 428 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006b, 432 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006c, 436 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006d, 440 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006e, 444 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x006f, 448 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0070, 452 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0071, 456 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0072, 460 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0073, 464 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0074, 468 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0075, 472 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0076, 476 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0077, 480 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0078, 484 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0079, 488 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007a, 492 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007b, 496 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007c, 500 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007d, 504 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007e, 508 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x007f, 512 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0080, 516 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0081, 520 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0082, 524 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0083, 528 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0084, 532 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0085, 536 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0086, 540 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0087, 544 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0088, 548 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0089, 552 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008a, 556 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008b, 560 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008c, 564 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008d, 568 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008e, 572 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x008f, 576 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0090, 580 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0091, 584 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0092, 588 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0093, 592 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0094, 596 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0095, 600 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0096, 604 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0097, 608 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0098, 612 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0099, 616 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009a, 620 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009b, 624 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009c, 628 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009d, 632 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009e, 636 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x009f, 640 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a0, 644 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a1, 648 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a2, 652 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a3, 656 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a4, 660 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a5, 664 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a6, 668 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a7, 672 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a8, 676 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00a9, 680 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00aa, 684 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ab, 688 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ac, 692 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ad, 696 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ae, 700 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00af, 704 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b0, 708 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b1, 712 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b2, 716 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b3, 720 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b4, 724 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b5, 728 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b6, 732 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b7, 736 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b8, 740 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00b9, 744 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ba, 748 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00bb, 752 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00bc, 756 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00bd, 760 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00be, 764 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00bf, 768 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c0, 772 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c1, 776 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c2, 780 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c3, 784 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c4, 788 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c5, 792 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c6, 796 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c7, 800 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c8, 804 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00c9, 808 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ca, 812 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00cb, 816 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00cc, 820 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00cd, 824 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ce, 828 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00cf, 832 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d0, 836 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d1, 840 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d2, 844 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d3, 848 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d4, 852 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d5, 856 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d6, 860 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d7, 864 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d8, 868 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00d9, 872 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00da, 876 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00db, 880 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00dc, 884 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00dd, 888 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00de, 892 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00df, 896 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e0, 900 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e1, 904 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e2, 908 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e3, 912 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e4, 916 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e5, 920 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e6, 924 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e7, 928 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e8, 932 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e9, 936 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ea, 940 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00eb, 944 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ec, 948 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ed, 952 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ee, 956 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ef, 960 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f0, 964 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f1, 968 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f2, 972 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f3, 976 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f4, 980 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f5, 984 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f6, 988 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f7, 992 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f8, 996 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00f9, 1000 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fa, 1004 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fb, 1008 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fc, 1012 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fd, 1016 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00fe, 1020 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00ff, 1024 }, +}; + +static pr_vec4_t neg_f_init[] = { + { 1, 2, 3, 4 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, +}; + +static pr_vec4_t neg_f_expect[] = { + { 1, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { -1, 2, 3, 4 }, + { 1, -2, 3, 4 }, + { -1, -2, 3, 4 }, + { 1, 2, -3, 4 }, + { -1, 2, -3, 4 }, + { 1, -2, -3, 4 }, + { -1, -2, -3, 4 }, + { 1, 2, 3, -4 }, + { -1, 2, 3, -4 }, + { 1, -2, 3, -4 }, + { -1, -2, 3, -4 }, + { 1, 2, -3, -4 }, + { -1, 2, -3, -4 }, + { 1, -2, -3, -4 }, + { -1, -2, -3, -4 }, +}; + +static dstatement_t neg_f_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e4, 4 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x01e4, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x02e4, 12 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x03e4, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x04e4, 20 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x05e4, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x06e4, 28 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x07e4, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x08e4, 36 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x09e4, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0ae4, 44 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0be4, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0ce4, 52 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0de4, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0ee4, 60 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x0fe4, 64 }, +}; + +static pr_vec4_t zero_f_init[] = { + { 1, 2, 3, 4 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, +}; + +static pr_vec4_t zero_f_expect[] = { + { 1, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { 0, 2, 3, 4 }, + { 1, 0, 3, 4 }, + { 0, 0, 3, 4 }, + { 1, 2, 0, 4 }, + { 0, 2, 0, 4 }, + { 1, 0, 0, 4 }, + { 0, 0, 0, 4 }, + { 1, 2, 3, 0 }, + { 0, 2, 3, 0 }, + { 1, 0, 3, 0 }, + { 0, 0, 3, 0 }, + { 1, 2, 0, 0 }, + { 0, 2, 0, 0 }, + { 1, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +static dstatement_t zero_f_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x00e4, 4 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x10e4, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x20e4, 12 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x30e4, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x40e4, 20 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x50e4, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x60e4, 28 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x70e4, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x80e4, 36 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0x90e4, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xa0e4, 44 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xb0e4, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xc0e4, 52 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xd0e4, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xe0e4, 60 }, + { OP(0, 0, 0, OP_SWIZZLE_F), 0, 0xf0e4, 64 }, +}; + +static pr_dvec4_t swizzle_d_init[] = { + { 1, 2, 3, 4 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, + { 8, 8, 8, 8 }, +}; +static pr_dvec4_t swizzle_d_expect[] = { + { 1, 2, 3, 4 }, + { 1, 1, 1, 1 }, + { 2, 1, 1, 1 }, + { 3, 1, 1, 1 }, + { 4, 1, 1, 1 }, + { 1, 2, 1, 1 }, + { 2, 2, 1, 1 }, + { 3, 2, 1, 1 }, + { 4, 2, 1, 1 }, + { 1, 3, 1, 1 }, + { 2, 3, 1, 1 }, + { 3, 3, 1, 1 }, + { 4, 3, 1, 1 }, + { 1, 4, 1, 1 }, + { 2, 4, 1, 1 }, + { 3, 4, 1, 1 }, + { 4, 4, 1, 1 }, + { 1, 1, 2, 1 }, + { 2, 1, 2, 1 }, + { 3, 1, 2, 1 }, + { 4, 1, 2, 1 }, + { 1, 2, 2, 1 }, + { 2, 2, 2, 1 }, + { 3, 2, 2, 1 }, + { 4, 2, 2, 1 }, + { 1, 3, 2, 1 }, + { 2, 3, 2, 1 }, + { 3, 3, 2, 1 }, + { 4, 3, 2, 1 }, + { 1, 4, 2, 1 }, + { 2, 4, 2, 1 }, + { 3, 4, 2, 1 }, + { 4, 4, 2, 1 }, + { 1, 1, 3, 1 }, + { 2, 1, 3, 1 }, + { 3, 1, 3, 1 }, + { 4, 1, 3, 1 }, + { 1, 2, 3, 1 }, + { 2, 2, 3, 1 }, + { 3, 2, 3, 1 }, + { 4, 2, 3, 1 }, + { 1, 3, 3, 1 }, + { 2, 3, 3, 1 }, + { 3, 3, 3, 1 }, + { 4, 3, 3, 1 }, + { 1, 4, 3, 1 }, + { 2, 4, 3, 1 }, + { 3, 4, 3, 1 }, + { 4, 4, 3, 1 }, + { 1, 1, 4, 1 }, + { 2, 1, 4, 1 }, + { 3, 1, 4, 1 }, + { 4, 1, 4, 1 }, + { 1, 2, 4, 1 }, + { 2, 2, 4, 1 }, + { 3, 2, 4, 1 }, + { 4, 2, 4, 1 }, + { 1, 3, 4, 1 }, + { 2, 3, 4, 1 }, + { 3, 3, 4, 1 }, + { 4, 3, 4, 1 }, + { 1, 4, 4, 1 }, + { 2, 4, 4, 1 }, + { 3, 4, 4, 1 }, + { 4, 4, 4, 1 }, + { 1, 1, 1, 2 }, + { 2, 1, 1, 2 }, + { 3, 1, 1, 2 }, + { 4, 1, 1, 2 }, + { 1, 2, 1, 2 }, + { 2, 2, 1, 2 }, + { 3, 2, 1, 2 }, + { 4, 2, 1, 2 }, + { 1, 3, 1, 2 }, + { 2, 3, 1, 2 }, + { 3, 3, 1, 2 }, + { 4, 3, 1, 2 }, + { 1, 4, 1, 2 }, + { 2, 4, 1, 2 }, + { 3, 4, 1, 2 }, + { 4, 4, 1, 2 }, + { 1, 1, 2, 2 }, + { 2, 1, 2, 2 }, + { 3, 1, 2, 2 }, + { 4, 1, 2, 2 }, + { 1, 2, 2, 2 }, + { 2, 2, 2, 2 }, + { 3, 2, 2, 2 }, + { 4, 2, 2, 2 }, + { 1, 3, 2, 2 }, + { 2, 3, 2, 2 }, + { 3, 3, 2, 2 }, + { 4, 3, 2, 2 }, + { 1, 4, 2, 2 }, + { 2, 4, 2, 2 }, + { 3, 4, 2, 2 }, + { 4, 4, 2, 2 }, + { 1, 1, 3, 2 }, + { 2, 1, 3, 2 }, + { 3, 1, 3, 2 }, + { 4, 1, 3, 2 }, + { 1, 2, 3, 2 }, + { 2, 2, 3, 2 }, + { 3, 2, 3, 2 }, + { 4, 2, 3, 2 }, + { 1, 3, 3, 2 }, + { 2, 3, 3, 2 }, + { 3, 3, 3, 2 }, + { 4, 3, 3, 2 }, + { 1, 4, 3, 2 }, + { 2, 4, 3, 2 }, + { 3, 4, 3, 2 }, + { 4, 4, 3, 2 }, + { 1, 1, 4, 2 }, + { 2, 1, 4, 2 }, + { 3, 1, 4, 2 }, + { 4, 1, 4, 2 }, + { 1, 2, 4, 2 }, + { 2, 2, 4, 2 }, + { 3, 2, 4, 2 }, + { 4, 2, 4, 2 }, + { 1, 3, 4, 2 }, + { 2, 3, 4, 2 }, + { 3, 3, 4, 2 }, + { 4, 3, 4, 2 }, + { 1, 4, 4, 2 }, + { 2, 4, 4, 2 }, + { 3, 4, 4, 2 }, + { 4, 4, 4, 2 }, + { 1, 1, 1, 3 }, + { 2, 1, 1, 3 }, + { 3, 1, 1, 3 }, + { 4, 1, 1, 3 }, + { 1, 2, 1, 3 }, + { 2, 2, 1, 3 }, + { 3, 2, 1, 3 }, + { 4, 2, 1, 3 }, + { 1, 3, 1, 3 }, + { 2, 3, 1, 3 }, + { 3, 3, 1, 3 }, + { 4, 3, 1, 3 }, + { 1, 4, 1, 3 }, + { 2, 4, 1, 3 }, + { 3, 4, 1, 3 }, + { 4, 4, 1, 3 }, + { 1, 1, 2, 3 }, + { 2, 1, 2, 3 }, + { 3, 1, 2, 3 }, + { 4, 1, 2, 3 }, + { 1, 2, 2, 3 }, + { 2, 2, 2, 3 }, + { 3, 2, 2, 3 }, + { 4, 2, 2, 3 }, + { 1, 3, 2, 3 }, + { 2, 3, 2, 3 }, + { 3, 3, 2, 3 }, + { 4, 3, 2, 3 }, + { 1, 4, 2, 3 }, + { 2, 4, 2, 3 }, + { 3, 4, 2, 3 }, + { 4, 4, 2, 3 }, + { 1, 1, 3, 3 }, + { 2, 1, 3, 3 }, + { 3, 1, 3, 3 }, + { 4, 1, 3, 3 }, + { 1, 2, 3, 3 }, + { 2, 2, 3, 3 }, + { 3, 2, 3, 3 }, + { 4, 2, 3, 3 }, + { 1, 3, 3, 3 }, + { 2, 3, 3, 3 }, + { 3, 3, 3, 3 }, + { 4, 3, 3, 3 }, + { 1, 4, 3, 3 }, + { 2, 4, 3, 3 }, + { 3, 4, 3, 3 }, + { 4, 4, 3, 3 }, + { 1, 1, 4, 3 }, + { 2, 1, 4, 3 }, + { 3, 1, 4, 3 }, + { 4, 1, 4, 3 }, + { 1, 2, 4, 3 }, + { 2, 2, 4, 3 }, + { 3, 2, 4, 3 }, + { 4, 2, 4, 3 }, + { 1, 3, 4, 3 }, + { 2, 3, 4, 3 }, + { 3, 3, 4, 3 }, + { 4, 3, 4, 3 }, + { 1, 4, 4, 3 }, + { 2, 4, 4, 3 }, + { 3, 4, 4, 3 }, + { 4, 4, 4, 3 }, + { 1, 1, 1, 4 }, + { 2, 1, 1, 4 }, + { 3, 1, 1, 4 }, + { 4, 1, 1, 4 }, + { 1, 2, 1, 4 }, + { 2, 2, 1, 4 }, + { 3, 2, 1, 4 }, + { 4, 2, 1, 4 }, + { 1, 3, 1, 4 }, + { 2, 3, 1, 4 }, + { 3, 3, 1, 4 }, + { 4, 3, 1, 4 }, + { 1, 4, 1, 4 }, + { 2, 4, 1, 4 }, + { 3, 4, 1, 4 }, + { 4, 4, 1, 4 }, + { 1, 1, 2, 4 }, + { 2, 1, 2, 4 }, + { 3, 1, 2, 4 }, + { 4, 1, 2, 4 }, + { 1, 2, 2, 4 }, + { 2, 2, 2, 4 }, + { 3, 2, 2, 4 }, + { 4, 2, 2, 4 }, + { 1, 3, 2, 4 }, + { 2, 3, 2, 4 }, + { 3, 3, 2, 4 }, + { 4, 3, 2, 4 }, + { 1, 4, 2, 4 }, + { 2, 4, 2, 4 }, + { 3, 4, 2, 4 }, + { 4, 4, 2, 4 }, + { 1, 1, 3, 4 }, + { 2, 1, 3, 4 }, + { 3, 1, 3, 4 }, + { 4, 1, 3, 4 }, + { 1, 2, 3, 4 }, + { 2, 2, 3, 4 }, + { 3, 2, 3, 4 }, + { 4, 2, 3, 4 }, + { 1, 3, 3, 4 }, + { 2, 3, 3, 4 }, + { 3, 3, 3, 4 }, + { 4, 3, 3, 4 }, + { 1, 4, 3, 4 }, + { 2, 4, 3, 4 }, + { 3, 4, 3, 4 }, + { 4, 4, 3, 4 }, + { 1, 1, 4, 4 }, + { 2, 1, 4, 4 }, + { 3, 1, 4, 4 }, + { 4, 1, 4, 4 }, + { 1, 2, 4, 4 }, + { 2, 2, 4, 4 }, + { 3, 2, 4, 4 }, + { 4, 2, 4, 4 }, + { 1, 3, 4, 4 }, + { 2, 3, 4, 4 }, + { 3, 3, 4, 4 }, + { 4, 3, 4, 4 }, + { 1, 4, 4, 4 }, + { 2, 4, 4, 4 }, + { 3, 4, 4, 4 }, + { 4, 4, 4, 4 }, +}; + +static dstatement_t swizzle_d_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0000, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0001, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0002, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0003, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0004, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0005, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0006, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0007, 64 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0008, 72 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0009, 80 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000a, 88 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000b, 96 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000c, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000d, 112 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000e, 120 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x000f, 128 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0010, 136 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0011, 144 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0012, 152 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0013, 160 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0014, 168 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0015, 176 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0016, 184 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0017, 192 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0018, 200 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0019, 208 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001a, 216 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001b, 224 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001c, 232 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001d, 240 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001e, 248 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x001f, 256 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0020, 264 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0021, 272 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0022, 280 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0023, 288 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0024, 296 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0025, 304 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0026, 312 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0027, 320 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0028, 328 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0029, 336 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002a, 344 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002b, 352 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002c, 360 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002d, 368 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002e, 376 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x002f, 384 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0030, 392 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0031, 400 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0032, 408 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0033, 416 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0034, 424 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0035, 432 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0036, 440 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0037, 448 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0038, 456 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0039, 464 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003a, 472 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003b, 480 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003c, 488 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003d, 496 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003e, 504 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x003f, 512 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0040, 520 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0041, 528 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0042, 536 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0043, 544 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0044, 552 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0045, 560 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0046, 568 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0047, 576 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0048, 584 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0049, 592 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004a, 600 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004b, 608 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004c, 616 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004d, 624 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004e, 632 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x004f, 640 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0050, 648 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0051, 656 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0052, 664 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0053, 672 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0054, 680 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0055, 688 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0056, 696 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0057, 704 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0058, 712 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0059, 720 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005a, 728 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005b, 736 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005c, 744 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005d, 752 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005e, 760 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x005f, 768 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0060, 776 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0061, 784 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0062, 792 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0063, 800 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0064, 808 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0065, 816 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0066, 824 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0067, 832 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0068, 840 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0069, 848 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006a, 856 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006b, 864 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006c, 872 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006d, 880 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006e, 888 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x006f, 896 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0070, 904 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0071, 912 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0072, 920 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0073, 928 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0074, 936 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0075, 944 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0076, 952 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0077, 960 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0078, 968 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0079, 976 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007a, 984 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007b, 992 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007c, 1000 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007d, 1008 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007e, 1016 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x007f, 1024 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0080, 1032 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0081, 1040 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0082, 1048 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0083, 1056 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0084, 1064 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0085, 1072 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0086, 1080 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0087, 1088 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0088, 1096 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0089, 1104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008a, 1112 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008b, 1120 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008c, 1128 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008d, 1136 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008e, 1144 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x008f, 1152 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0090, 1160 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0091, 1168 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0092, 1176 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0093, 1184 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0094, 1192 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0095, 1200 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0096, 1208 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0097, 1216 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0098, 1224 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0099, 1232 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009a, 1240 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009b, 1248 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009c, 1256 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009d, 1264 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009e, 1272 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x009f, 1280 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a0, 1288 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a1, 1296 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a2, 1304 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a3, 1312 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a4, 1320 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a5, 1328 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a6, 1336 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a7, 1344 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a8, 1352 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00a9, 1360 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00aa, 1368 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ab, 1376 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ac, 1384 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ad, 1392 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ae, 1400 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00af, 1408 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b0, 1416 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b1, 1424 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b2, 1432 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b3, 1440 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b4, 1448 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b5, 1456 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b6, 1464 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b7, 1472 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b8, 1480 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00b9, 1488 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ba, 1496 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00bb, 1504 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00bc, 1512 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00bd, 1520 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00be, 1528 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00bf, 1536 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c0, 1544 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c1, 1552 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c2, 1560 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c3, 1568 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c4, 1576 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c5, 1584 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c6, 1592 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c7, 1600 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c8, 1608 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00c9, 1616 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ca, 1624 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00cb, 1632 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00cc, 1640 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00cd, 1648 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ce, 1656 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00cf, 1664 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d0, 1672 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d1, 1680 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d2, 1688 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d3, 1696 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d4, 1704 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d5, 1712 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d6, 1720 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d7, 1728 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d8, 1736 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00d9, 1744 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00da, 1752 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00db, 1760 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00dc, 1768 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00dd, 1776 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00de, 1784 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00df, 1792 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e0, 1800 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e1, 1808 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e2, 1816 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e3, 1824 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e4, 1832 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e5, 1840 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e6, 1848 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e7, 1856 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e8, 1864 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e9, 1872 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ea, 1880 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00eb, 1888 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ec, 1896 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ed, 1904 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ee, 1912 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ef, 1920 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f0, 1928 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f1, 1936 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f2, 1944 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f3, 1952 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f4, 1960 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f5, 1968 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f6, 1976 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f7, 1984 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f8, 1992 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00f9, 2000 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fa, 2008 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fb, 2016 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fc, 2024 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fd, 2032 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00fe, 2040 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00ff, 2048 }, +}; + +static pr_dvec4_t neg_d_init[] = { + { 1, 2, 3, 4 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, +}; + +static pr_dvec4_t neg_d_expect[] = { + { 1, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { -1, 2, 3, 4 }, + { 1, -2, 3, 4 }, + { -1, -2, 3, 4 }, + { 1, 2, -3, 4 }, + { -1, 2, -3, 4 }, + { 1, -2, -3, 4 }, + { -1, -2, -3, 4 }, + { 1, 2, 3, -4 }, + { -1, 2, 3, -4 }, + { 1, -2, 3, -4 }, + { -1, -2, 3, -4 }, + { 1, 2, -3, -4 }, + { -1, 2, -3, -4 }, + { 1, -2, -3, -4 }, + { -1, -2, -3, -4 }, +}; + +static dstatement_t neg_d_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e4, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x01e4, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x02e4, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x03e4, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x04e4, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x05e4, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x06e4, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x07e4, 64 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x08e4, 72 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x09e4, 80 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0ae4, 88 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0be4, 96 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0ce4, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0de4, 112 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0ee4, 120 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x0fe4, 128 }, +}; + +static pr_dvec4_t zero_d_init[] = { + { 1, 2, 3, 4 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, + { 9, 9, 9, 9 }, +}; + +static pr_dvec4_t zero_d_expect[] = { + { 1, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { 0, 2, 3, 4 }, + { 1, 0, 3, 4 }, + { 0, 0, 3, 4 }, + { 1, 2, 0, 4 }, + { 0, 2, 0, 4 }, + { 1, 0, 0, 4 }, + { 0, 0, 0, 4 }, + { 1, 2, 3, 0 }, + { 0, 2, 3, 0 }, + { 1, 0, 3, 0 }, + { 0, 0, 3, 0 }, + { 1, 2, 0, 0 }, + { 0, 2, 0, 0 }, + { 1, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +static dstatement_t zero_d_statements[] = { + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x00e4, 8 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x10e4, 16 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x20e4, 24 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x30e4, 32 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x40e4, 40 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x50e4, 48 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x60e4, 56 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x70e4, 64 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x80e4, 72 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0x90e4, 80 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xa0e4, 88 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xb0e4, 96 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xc0e4, 104 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xd0e4, 112 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xe0e4, 120 }, + { OP(0, 0, 0, OP_SWIZZLE_D), 0, 0xf0e4, 128 }, +}; + +test_t tests[] = { + { + .desc = "swizzle f", + .num_globals = num_globals(swizzle_f_init,swizzle_f_expect), + .num_statements = num_statements(swizzle_f_statements), + .statements = swizzle_f_statements, + .init_globals = (pr_int_t *) swizzle_f_init, + .expect_globals = (pr_int_t *) swizzle_f_expect, + }, + { + .desc = "neg f", + .num_globals = num_globals(neg_f_init,neg_f_expect), + .num_statements = num_statements(neg_f_statements), + .statements = neg_f_statements, + .init_globals = (pr_int_t *) neg_f_init, + .expect_globals = (pr_int_t *) neg_f_expect, + }, + { + .desc = "zero f", + .num_globals = num_globals(zero_f_init,zero_f_expect), + .num_statements = num_statements(zero_f_statements), + .statements = zero_f_statements, + .init_globals = (pr_int_t *) zero_f_init, + .expect_globals = (pr_int_t *) zero_f_expect, + }, + { + .desc = "swizzle d", + .num_globals = num_globals(swizzle_d_init,swizzle_d_expect), + .num_statements = num_statements(swizzle_d_statements), + .statements = swizzle_d_statements, + .init_globals = (pr_int_t *) swizzle_d_init, + .expect_globals = (pr_int_t *) swizzle_d_expect, + }, + { + .desc = "neg d", + .num_globals = num_globals(neg_d_init,neg_d_expect), + .num_statements = num_statements(neg_d_statements), + .statements = neg_d_statements, + .init_globals = (pr_int_t *) neg_d_init, + .expect_globals = (pr_int_t *) neg_d_expect, + }, + { + .desc = "zero d", + .num_globals = num_globals(zero_d_init,zero_d_expect), + .num_statements = num_statements(zero_d_statements), + .statements = zero_d_statements, + .init_globals = (pr_int_t *) zero_d_init, + .expect_globals = (pr_int_t *) zero_d_expect, + }, +}; + +#include "main.c" From 8050c7bd77e80fdcbef18f4e97f3771eb1dbcf86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jan 2022 14:22:04 +0900 Subject: [PATCH 2187/3664] [gamecode] Rearrange several instructions ANY/ALL/NONE have been temporarily removed until I implement the HOPS (horizontal operations) sub-instructions, which will all both 32-bit and 64-bit operands and several other operations (eg, horizontal add). All the fancy addressing modes for the conditional branch instructions have been permanently removed: I decided the gain was too little for the cost (24 instructions vs 6). JUMP and CALL retain their addressing modes, though. Other instructions have been shuffled around a little to fill most of the holes in the upper block of 256 instructions: just a single small 7-instruction hole. Rearrangements in the actual engine are mostly just to keep the code organized. The only real changes were the various IF statements and dealing with the resulting changes in their addressing. --- libs/gamecode/opcodes.py | 101 +++--- libs/gamecode/pr_exec.c | 477 +++++++++++++---------------- libs/gamecode/test/test-bitops.c | 8 +- libs/gamecode/test/test-conv0.c | 4 +- libs/gamecode/test/test-conv1.c | 4 +- libs/gamecode/test/test-conv2.c | 4 +- libs/gamecode/test/test-conv3.c | 4 +- libs/gamecode/test/test-conv4.c | 4 +- libs/gamecode/test/test-conv5.c | 4 +- libs/gamecode/test/test-conv6.c | 4 +- libs/gamecode/test/test-conv7.c | 4 +- libs/gamecode/test/test-double.c | 10 +- libs/gamecode/test/test-float.c | 10 +- libs/gamecode/test/test-int.c | 8 +- libs/gamecode/test/test-long.c | 8 +- libs/gamecode/test/test-string.c | 4 +- libs/gamecode/test/test-unsigned.c | 16 +- 17 files changed, 316 insertions(+), 358 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index ceccba4a7..db39a5621 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -3,41 +3,31 @@ bitmap_txt = """ 0 0001 mmss store 0 0010 mmss push 0 0011 mmss pop -0 010c ccmm branch - -# while call and return are part of the branch block, they have different -# handling for addressing and formatting -0 0101 11mm call (return specified st->c) -0 0101 1100 return (size in st->c) - -0 0110 0nnn -0 0110 10mm lea -0 0110 1100 convert (conversion mode in st->b) -0 0110 1101 with (mode in st->a, value in st->b, reg in st->c) -0 0110 111t state -0 0111 tooo vecops 0 1ccc ttss compare +0 1011 nnnn +0 1111 nnnn + 1 0ooo ttss mathops 1 011r tuss shiftops 1 0110 o1oo string 1 1ccc t0ss compare2 -1 1001 t1ss scale -1 1001 t100 swizzle -1 1010 d1xx -1 1011 00nn -1 1011 01ss any -1 1011 0100 -1 1011 10ss all -1 1011 1000 -1 1011 11ss none -1 1011 1100 -1 1101 01oo move -1 1101 11oo memset -1 1110 d1xx -1 11dd t100 vecops2 1 1t00 ooss bitops -n 1111 nnnn -0 1011 nnnn +1 1001 01mm jump +1 1001 11mm call (return specified st->c) +1 1001 1100 return (size in st->c) +1 1010 t1ss scale +1 1010 t100 swizzle +1 1011 tooo vecops +1 1101 01oo move +1 1101 0111 convert (conversion mode in st->b) +1 1101 11oo memset +1 1101 1111 with (mode in st->a, value in st->b, reg in st->c) +1 1110 c1cc branch +1 1110 t111 state +1 1111 00mm lea +1 1111 01td vecops2 +1 1111 1nnn +1 1111 1111 hops """ import copy @@ -96,16 +86,16 @@ bitops_formats = { }, } branch_formats = { - "opcode": "OP_{op_cond[ccc].upper()}_{op_mode[mm]}", - "mnemonic": "{op_cond[ccc]}", - "opname": "{op_cond[ccc]}", - "format": "{cond_fmt[ccc]}{branch_fmt[mm]}", - "widths": "{cond_widths[ccc]}", + "opcode": "OP_{op_cond[c*4+cc].upper()}", + "mnemonic": "{op_cond[c*4+cc]}", + "opname": "{op_cond[c*4+cc]}", + "format": "{cond_fmt[c*4+cc]}{branch_fmt[0]}", + "widths": "{cond_widths[c*4+cc]}", "types": "ev_void, ev_void, ev_integer", "args": { "op_mode": "ABCD", - "op_cond": ["ifz", "ifb", "ifa", "jump", - "ifnz", "ifae", "ifbe", None], #call and return seprate + "op_cond": ["ifz", "ifb", "ifa", None, + "ifnz", "ifae", "ifbe", None], "branch_fmt": branch_fmt, "cond_fmt": ["%Gc ", "%Gc ", "%Gc ", "", "%Gc ", "%Gc ", "%Gc ", ""], "cond_widths": [ @@ -169,6 +159,26 @@ convert_formats = { "widths": "1, 0, 1", "types": "ev_void, ev_short, ev_void", } +hops_formats = { + "opcode": "OP_HOPS", + "mnemonic": "hops", + "opname": "hops", + "format": "%Ga %Hb %gc", + "widths": "1, 0, 1", + "types": "ev_void, ev_short, ev_void", +} +jump_formats = { + "opcode": "OP_JUMP_{op_mode[mm]}", + "mnemonic": "jump", + "opname": "jump", + "format": "{branch_fmt[mm]}", + "widths": "0, 0, 0", + "types": "ev_void, ev_void, ev_invalid", + "args": { + "op_mode": "ABCD", + "branch_fmt": branch_fmt, + }, +} lea_formats = { "opcode": "OP_LEA_{op_mode[mm]}", "mnemonic": "lea", @@ -218,8 +228,8 @@ memset_formats = { "widths": "0, 0, 0", "types": "ev_integer, ev_void, ev_void", "args": { - "op_memset": [None, "i", "p", "pi"], - "memset_fmt": [None, "%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc"], + "op_memset": ["i", "p", "pi", None], + "memset_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], }, } move_formats = { @@ -230,8 +240,8 @@ move_formats = { "widths": "0, 0, 0", "types": "ev_integer, ev_void, ev_void", "args": { - "op_move": [None, "i", "p", "pi"], - "move_fmt": [None, "%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc"], + "op_move": ["i", "p", "pi", None], + "move_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], }, } none_formats = { @@ -423,13 +433,13 @@ vecops_formats = { }, } vecops2_formats = { - "opcode": "OP_{op_vop[dd].upper()}_{vop_type[t]}", - "mnemonic": "{op_vop[dd]}.{vop_type[t]}", - "opname": "{op_vop[dd]}", + "opcode": "OP_{op_vop[d].upper()}_{vop_type[t]}", + "mnemonic": "{op_vop[d]}.{vop_type[t]}", + "opname": "{op_vop[d]}", "widths": "4, 4, 4", "types": "{vec_types[t]}, {vec_types[t]}, {vec_types[t]}", "args": { - "op_vop": [None, "qv4mul", "v4qmul", None], + "op_vop": ["qv4mul", "v4qmul"], "vop_type": ['F', 'D'], "vec_types": float_t, }, @@ -452,6 +462,8 @@ group_map = { "compare": compare_formats, "compare2": compare2_formats, "convert": convert_formats, + "hops": hops_formats, + "jump": jump_formats, "lea": lea_formats, "load": load_formats, "mathops": mathops_formats, @@ -522,6 +534,7 @@ def process_opcode(opcode, group): params.update(gm["args"]) inst = {} opcodes[opcode] = inst + #print(f"{opcode:03x}", group) inst["op"] = eval(f'''f"{gm['opcode']}"''', params) mn = eval(f'''f"{gm['mnemonic']}"''', params) inst["mn"] = f'"{mn}"' diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 69d9c0f6f..3f8b9f365 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1830,11 +1830,10 @@ pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind) } static pr_pointer_t __attribute__((pure)) -pr_jump_mode (progs_t *pr, const dstatement_t *st) +pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind) { pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); - int jump_ind = st->op & 3; pointer_t jump_offs = pr->pr_xstatement; switch (jump_ind) { @@ -2892,228 +2891,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) MM(ivec4) = STK(ivec4); break; // 0 0100 - case OP_IFZ_A: - case OP_IFZ_B: - case OP_IFZ_C: - case OP_IFZ_D: - if (!OPC(int)) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; - case OP_IFB_A: - case OP_IFB_B: - case OP_IFB_C: - case OP_IFB_D: - if (OPC(int) < 0) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; - case OP_IFA_A: - case OP_IFA_B: - case OP_IFA_C: - case OP_IFA_D: - if (OPC(int) > 0) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; - case OP_JUMP_A: - case OP_JUMP_B: - case OP_JUMP_C: - case OP_JUMP_D: - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - break; // 0 0101 - case OP_IFNZ_A: - case OP_IFNZ_B: - case OP_IFNZ_C: - case OP_IFNZ_D: - if (OPC(int)) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; - case OP_IFAE_A: - case OP_IFAE_B: - case OP_IFAE_C: - case OP_IFAE_D: - if (OPC(int) >= 0) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; - case OP_IFBE_A: - case OP_IFBE_B: - case OP_IFBE_C: - case OP_IFBE_D: - if (OPC(int) <= 0) { - pr->pr_xstatement = pr_jump_mode (pr, st); - st = pr->pr_statements + pr->pr_xstatement; - } - break; - case OP_RETURN: - int ret_size = st->c & 0x1f; // up to 32 words - if (ret_size) { - mm = pr_return_mode (pr, st, (st->c >> 5) & 7); - memcpy (&R_INT (pr), mm, ret_size * sizeof (*op_a)); - } - pr->pr_xfunction->profile += profile - startprofile; - startprofile = profile; - PR_LeaveFunction (pr, pr->pr_depth == exitdepth); - st = pr->pr_statements + pr->pr_xstatement; - if (pr->pr_depth== exitdepth) { - if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth) { - pr->pr_trace = false; - } - goto exit_program; - } - break; - case OP_CALL_B: - case OP_CALL_C: - case OP_CALL_D: - mm = pr_call_mode (pr, st, st->c & 3); - function = mm->func_var; - pr->pr_argc = 0; - // op_c specifies the location for the return value if any - pr->pr_return = op_c; - pr->pr_xfunction->profile += profile - startprofile; - startprofile = profile; - PR_CallFunction (pr, function); - st = pr->pr_statements + pr->pr_xstatement; - break; // 0 0110 - // 0nnn spare - case OP_LEA_A: - case OP_LEA_C: - case OP_LEA_D: - mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); - op_c->pointer_var = mm - pr->pr_globals; - break; - case OP_LEA_E: - mm = pr_address_mode (pr, st, 4); - op_c->pointer_var = mm - pr->pr_globals; - break; - case OP_CONV: - switch (st->b) { -#include "libs/gamecode/pr_convert.cinc" - default: - PR_RunError (pr, "invalid conversion code: %04o", - st->b); - } - break; - case OP_WITH: - pr_with (pr, st); - break; - case OP_STATE_ft: - { - int self = *pr->globals.self; - int nextthink = pr->fields.nextthink + self; - int frame = pr->fields.frame + self; - int think = pr->fields.think + self; - float time = *pr->globals.time + 0.1; - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = op_b->func_var; - } - break; - case OP_STATE_ftt: - { - int self = *pr->globals.self; - int nextthink = pr->fields.nextthink + self; - int frame = pr->fields.frame + self; - int think = pr->fields.think + self; - float time = *pr->globals.time + OPC(float); - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = op_b->func_var; - } - break; // 0 0111 - case OP_CROSS_F: - { - pr_vec4_t a = loadvec3f (&OPA(float)); - pr_vec4_t b = loadvec3f (&OPB(float)); - pr_vec4_t c = crossf (a, b); - storevec3f (&OPC(float), c); - } - break; - case OP_CDOT_F: - OPC(vec2) = dot2f (OPA(vec2), OPB(vec2)); - break; - case OP_VDOT_F: - { - vec_t d = DotProduct (&OPA(float), - &OPB(float)); - VectorSet (d, d, d, &OPC(float)); - } - break; - case OP_QDOT_F: - OPC(vec4) = dotf (OPA(vec4), OPB(vec4)); - break; - case OP_CMUL_F: - OPC(vec2) = cmulf (OPA(vec2), OPB(vec2)); - break; - case OP_QVMUL_F: - { - pr_vec4_t v = loadvec3f (&OPB(float)); - v = qvmulf (OPA(vec4), v); - storevec3f (&OPC(float), v); - } - break; - case OP_VQMUL_F: - { - pr_vec4_t v = loadvec3f (&OPA(float)); - v = vqmulf (v, OPB(vec4)); - storevec3f (&OPC(float), v); - } - break; - case OP_QMUL_F: - OPC(vec4) = qmulf (OPA(vec4), OPB(vec4)); - break; - case OP_CROSS_D: - { - pr_dvec4_t a = loadvec3d (&OPA(double)); - pr_dvec4_t b = loadvec3d (&OPB(double)); - pr_dvec4_t c = crossd (a, b); - storevec3d (&OPC(double), c); - } - break; - case OP_CDOT_D: - OPC(dvec2) = dot2d (OPA(dvec2), OPB(dvec2)); - break; - case OP_VDOT_D: - { - double d = DotProduct (&OPA(double), - &OPB(double)); - VectorSet (d, d, d, &OPC(double)); - } - break; - case OP_QDOT_D: - OPC(dvec4) = dotd (OPA(dvec4), OPB(dvec4)); - break; - case OP_CMUL_D: - OPC(dvec2) = cmuld (OPA(dvec2), OPB(dvec2)); - break; - case OP_QVMUL_D: - { - pr_dvec4_t v = loadvec3d (&OPB(double)); - v = qvmuld (OPA(dvec4), v); - storevec3d (&OPC(double), v); - } - break; - case OP_VQMUL_D: - { - pr_dvec4_t v = loadvec3d (&OPA(double)); - v = vqmuld (v, OPB(dvec4)); - storevec3d (&OPC(double), v); - } - break; - case OP_QMUL_D: - OPC(dvec4) = qmuld (OPA(dvec4), OPB(dvec4)); - break; #define OP_cmp_1(OP, T, rt, cmp, ct) \ case OP_##OP##_##T##_1: \ @@ -3330,6 +3110,46 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_uop_T (BITNOT, I, int, ivec2, ivec4, ~); // 1 1001 OP_cmp_T (LT, u, int, ivec2, ivec4, <, uint, uivec2, uivec4); + case OP_JUMP_A: + case OP_JUMP_B: + case OP_JUMP_C: + case OP_JUMP_D: + pr->pr_xstatement = pr_jump_mode (pr, st, st_op - OP_JUMP_A); + st = pr->pr_statements + pr->pr_xstatement; + break; + OP_cmp_T (LT, U, long, lvec2, lvec4, <, ulong, ulvec2, ulvec4); + case OP_RETURN: + int ret_size = st->c & 0x1f; // up to 32 words + if (ret_size) { + mm = pr_return_mode (pr, st, (st->c >> 5) & 7); + memcpy (&R_INT (pr), mm, ret_size * sizeof (*op_a)); + } + pr->pr_xfunction->profile += profile - startprofile; + startprofile = profile; + PR_LeaveFunction (pr, pr->pr_depth == exitdepth); + st = pr->pr_statements + pr->pr_xstatement; + if (pr->pr_depth== exitdepth) { + if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth) { + pr->pr_trace = false; + } + goto exit_program; + } + break; + case OP_CALL_B: + case OP_CALL_C: + case OP_CALL_D: + mm = pr_call_mode (pr, st, st->c & 3); + function = mm->func_var; + pr->pr_argc = 0; + // op_c specifies the location for the return value if any + pr->pr_return = op_c; + pr->pr_xfunction->profile += profile - startprofile; + startprofile = profile; + PR_CallFunction (pr, function); + st = pr->pr_statements + pr->pr_xstatement; + break; + // 1 1010 + OP_cmp_T (GT, u, int, ivec2, ivec4, >, uint, uivec2, uivec4); case OP_SWIZZLE_F: OPC(ivec4) = pr_swizzle_f (OPA(ivec4), st->b); break; @@ -3342,7 +3162,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_SCALE_F_4: OPC(vec4) = OPA(vec4) * OPB(float); break; - OP_cmp_T (LT, U, long, lvec2, lvec4, <, ulong, ulvec2, ulvec4); + OP_cmp_T (GT, U, long, lvec2, lvec4, >, ulong, ulvec2, ulvec4); case OP_SWIZZLE_D: OPC(lvec4) = pr_swizzle_d (OPA(lvec4), st->b); break; @@ -3355,53 +3175,89 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_SCALE_D_4: OPC(dvec4) = OPA(dvec4) * OPB(double); break; - // 1 1010 - OP_cmp_T (GT, u, int, ivec2, ivec4, >, uint, uivec2, uivec4); - // spare - OP_cmp_T (GT, U, long, lvec2, lvec4, >, ulong, ulvec2, ulvec4); - // spare // 1 1011 - // 00nn spare - case OP_ANY_2: - OPC(int) = any2i (OPA(ivec2)); - break; - case OP_ANY_3: + case OP_CROSS_F: { - __auto_type v = loadvec3i (&OPA(int)); - OPC(int) = any4i (v); + pr_vec4_t a = loadvec3f (&OPA(float)); + pr_vec4_t b = loadvec3f (&OPB(float)); + pr_vec4_t c = crossf (a, b); + storevec3f (&OPC(float), c); } break; - case OP_ANY_4: - OPC(int) = any4i (OPA(ivec4)); + case OP_CDOT_F: + OPC(vec2) = dot2f (OPA(vec2), OPB(vec2)); break; - // spare - case OP_ALL_2: - OPC(int) = all2i (OPA(ivec2)); - break; - case OP_ALL_3: + case OP_VDOT_F: { - __auto_type v = loadvec3i (&OPA(int)); - v[3] = -1; - OPC(int) = all4i (v); + vec_t d = DotProduct (&OPA(float), + &OPB(float)); + VectorSet (d, d, d, &OPC(float)); } break; - case OP_ALL_4: - OPC(int) = all4i (OPA(ivec4)); + case OP_QDOT_F: + OPC(vec4) = dotf (OPA(vec4), OPB(vec4)); break; - // spare - case OP_NONE_2: - OPC(int) = none2i (OPA(ivec2)); + case OP_CMUL_F: + OPC(vec2) = cmulf (OPA(vec2), OPB(vec2)); break; - case OP_NONE_3: + case OP_QVMUL_F: { - __auto_type v = loadvec3i (&OPA(int)); - OPC(int) = none4i (v); + pr_vec4_t v = loadvec3f (&OPB(float)); + v = qvmulf (OPA(vec4), v); + storevec3f (&OPC(float), v); } break; - case OP_NONE_4: - OPC(int) = none4i (OPA(ivec4)); + case OP_VQMUL_F: + { + pr_vec4_t v = loadvec3f (&OPA(float)); + v = vqmulf (v, OPB(vec4)); + storevec3f (&OPC(float), v); + } + break; + case OP_QMUL_F: + OPC(vec4) = qmulf (OPA(vec4), OPB(vec4)); + break; + case OP_CROSS_D: + { + pr_dvec4_t a = loadvec3d (&OPA(double)); + pr_dvec4_t b = loadvec3d (&OPB(double)); + pr_dvec4_t c = crossd (a, b); + storevec3d (&OPC(double), c); + } + break; + case OP_CDOT_D: + OPC(dvec2) = dot2d (OPA(dvec2), OPB(dvec2)); + break; + case OP_VDOT_D: + { + double d = DotProduct (&OPA(double), + &OPB(double)); + VectorSet (d, d, d, &OPC(double)); + } + break; + case OP_QDOT_D: + OPC(dvec4) = dotd (OPA(dvec4), OPB(dvec4)); + break; + case OP_CMUL_D: + OPC(dvec2) = cmuld (OPA(dvec2), OPB(dvec2)); + break; + case OP_QVMUL_D: + { + pr_dvec4_t v = loadvec3d (&OPB(double)); + v = qvmuld (OPA(dvec4), v); + storevec3d (&OPC(double), v); + } + break; + case OP_VQMUL_D: + { + pr_dvec4_t v = loadvec3d (&OPA(double)); + v = vqmuld (v, OPB(dvec4)); + storevec3d (&OPC(double), v); + } + break; + case OP_QMUL_D: + OPC(dvec4) = qmuld (OPA(dvec4), OPB(dvec4)); break; - // 1 1100 OP_op_T (BITAND, L, long, lvec2, lvec4, &); OP_op_T (BITOR, L, long, lvec2, lvec4, |); @@ -3409,9 +3265,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_uop_T (BITNOT, L, long, lvec2, lvec4, ~); // 1 1101 OP_cmp_T (GE, u, int, ivec2, ivec4, >=, uint, uivec2, uivec4); - case OP_QV4MUL_F: - OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); - break; case OP_MOVE_I: memmove (op_c, op_a, st->b * sizeof (pr_type_t)); break; @@ -3423,10 +3276,15 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) memmove (pr->pr_globals + OPC(int), pr->pr_globals + OPA(int), st->b * sizeof (pr_type_t)); break; - OP_cmp_T (GE, U, long, lvec2, lvec4, >=, ulong, ulvec2, ulvec4); - case OP_QV4MUL_D: - OPC(dvec4) = qvmuld (OPA(dvec4), OPB(dvec4)); + case OP_CONV: + switch (st->b) { +#include "libs/gamecode/pr_convert.cinc" + default: + PR_RunError (pr, "invalid conversion code: %04o", + st->b); + } break; + OP_cmp_T (GE, U, long, lvec2, lvec4, >=, ulong, ulvec2, ulvec4); case OP_MEMSET_I: pr_memset (op_c, OPA(int), st->b); break; @@ -3436,19 +3294,106 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_MEMSET_PI: pr_memset (pr->pr_globals + OPC(int), OPA(int), st->b); break; + case OP_WITH: + pr_with (pr, st); + break; // 1 1110 OP_cmp_T (LE, u, int, ivec2, ivec4, <=, uint, uivec2, uivec4); + case OP_IFZ: + if (!OPC(int)) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFB: + if (OPC(int) < 0) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFA: + if (OPC(int) > 0) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_STATE_ft: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.time + 0.1; + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = op_b->func_var; + } + break; + OP_cmp_T (LE, U, long, lvec2, lvec4, <=, ulong, ulvec2, ulvec4); + case OP_IFNZ: + if (OPC(int)) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFAE: + if (OPC(int) >= 0) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_IFBE: + if (OPC(int) <= 0) { + pr->pr_xstatement = pr_jump_mode (pr, st, 0); + st = pr->pr_statements + pr->pr_xstatement; + } + break; + case OP_STATE_ftt: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.time + OPC(float); + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = op_b->func_var; + } + break; + // 1 1111 + case OP_LEA_A: + case OP_LEA_C: + case OP_LEA_D: + mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); + op_c->pointer_var = mm - pr->pr_globals; + break; + case OP_LEA_E: + mm = pr_address_mode (pr, st, 4); + op_c->pointer_var = mm - pr->pr_globals; + break; + case OP_QV4MUL_F: + OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); + break; case OP_V4QMUL_F: OPC(vec4) = vqmulf (OPA(vec4), OPB(vec4)); break; - // spare - OP_cmp_T (LE, U, long, lvec2, lvec4, <=, ulong, ulvec2, ulvec4); + case OP_QV4MUL_D: + OPC(dvec4) = qvmuld (OPA(dvec4), OPB(dvec4)); + break; case OP_V4QMUL_D: OPC(dvec4) = vqmuld (OPA(dvec4), OPB(dvec4)); break; - // spare - // 1 1111 - // spare + // 10nn spare + // 1100 spare + // 1101 spare + // 1110 spare + case OP_HOPS: + switch (st->b) { + default: + PR_RunError (pr, "invalid hops code: %04o", + st->b); + } + break; default: PR_RunError (pr, "Bad opcode o%03o", st->op & OP_MASK); } diff --git a/libs/gamecode/test/test-bitops.c b/libs/gamecode/test/test-bitops.c index a3121eb46..b692223d7 100644 --- a/libs/gamecode/test/test-bitops.c +++ b/libs/gamecode/test/test-bitops.c @@ -26,7 +26,7 @@ static dstatement_t int_bitop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 24 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 24, -1, 24 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 24 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 24 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 24, 1 }, @@ -42,7 +42,7 @@ static dstatement_t int_bitop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 24 }, // index //loop: { OP(0, 0, 0, OP_LEA_C), 24, -2, 24 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 24 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 24 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 24, 1 }, @@ -107,7 +107,7 @@ static dstatement_t long_bitop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 48 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 48, -2, 48 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 48 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 48 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 48, 1 }, @@ -123,7 +123,7 @@ static dstatement_t long_bitop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 48 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 48, -4, 48 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 48 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 48 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 48, 1 }, diff --git a/libs/gamecode/test/test-conv0.c b/libs/gamecode/test/test-conv0.c index 2f0533361..3b6e06359 100644 --- a/libs/gamecode/test/test-conv0.c +++ b/libs/gamecode/test/test-conv0.c @@ -54,7 +54,7 @@ static dstatement_t int_conv_1_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, @@ -75,7 +75,7 @@ static dstatement_t int_conv_2_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, diff --git a/libs/gamecode/test/test-conv1.c b/libs/gamecode/test/test-conv1.c index 6233b83f3..663604205 100644 --- a/libs/gamecode/test/test-conv1.c +++ b/libs/gamecode/test/test-conv1.c @@ -54,7 +54,7 @@ static dstatement_t float_conv_1_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, @@ -75,7 +75,7 @@ static dstatement_t float_conv_2_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, diff --git a/libs/gamecode/test/test-conv2.c b/libs/gamecode/test/test-conv2.c index f3a81a6ad..0dd4f5d41 100644 --- a/libs/gamecode/test/test-conv2.c +++ b/libs/gamecode/test/test-conv2.c @@ -70,7 +70,7 @@ static dstatement_t long_conv_1_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, @@ -91,7 +91,7 @@ static dstatement_t long_conv_2_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, diff --git a/libs/gamecode/test/test-conv3.c b/libs/gamecode/test/test-conv3.c index ea6989dda..7ea316d8b 100644 --- a/libs/gamecode/test/test-conv3.c +++ b/libs/gamecode/test/test-conv3.c @@ -70,7 +70,7 @@ static dstatement_t double_conv_1_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, @@ -91,7 +91,7 @@ static dstatement_t double_conv_2_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c index 0f7460a6a..246b4bec3 100644 --- a/libs/gamecode/test/test-conv4.c +++ b/libs/gamecode/test/test-conv4.c @@ -54,7 +54,7 @@ static dstatement_t uint_conv_1_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, @@ -75,7 +75,7 @@ static dstatement_t uint_conv_2_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, diff --git a/libs/gamecode/test/test-conv5.c b/libs/gamecode/test/test-conv5.c index 3713cd159..fe75e0ff2 100644 --- a/libs/gamecode/test/test-conv5.c +++ b/libs/gamecode/test/test-conv5.c @@ -54,7 +54,7 @@ static dstatement_t bool32_conv_1_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 80, -1, 80 }, // dec index { OP(0, 0, 0, OP_LEA_C), 81, -2, 81 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, @@ -75,7 +75,7 @@ static dstatement_t bool32_conv_2_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 80, -2, 80 }, // dec index { OP(0, 0, 0, OP_LEA_C), 81, -4, 81 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 80 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 80 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 80, 1 }, { OP(0, 0, 0, OP_WITH), 4, 81, 2 }, diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c index 7fd62c1ac..b32cfc537 100644 --- a/libs/gamecode/test/test-conv6.c +++ b/libs/gamecode/test/test-conv6.c @@ -70,7 +70,7 @@ static dstatement_t ulong_conv_1_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, @@ -91,7 +91,7 @@ static dstatement_t ulong_conv_2_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, diff --git a/libs/gamecode/test/test-conv7.c b/libs/gamecode/test/test-conv7.c index c8f9354c0..cbc2306e0 100644 --- a/libs/gamecode/test/test-conv7.c +++ b/libs/gamecode/test/test-conv7.c @@ -70,7 +70,7 @@ static dstatement_t bool64_conv_1_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 112, -1, 112 }, // dec index { OP(0, 0, 0, OP_LEA_C), 113, -2, 113 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, @@ -91,7 +91,7 @@ static dstatement_t bool64_conv_2_statements[] = { //loop: { OP(0, 0, 0, OP_LEA_C), 112, -2, 112 }, // dec index { OP(0, 0, 0, OP_LEA_C), 113, -4, 113 }, // dec index for 64-bits - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 112 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 112 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 112, 1 }, { OP(0, 0, 0, OP_WITH), 4, 113, 2 }, diff --git a/libs/gamecode/test/test-double.c b/libs/gamecode/test/test-double.c index 239630034..33bd4ff7a 100644 --- a/libs/gamecode/test/test-double.c +++ b/libs/gamecode/test/test-double.c @@ -30,7 +30,7 @@ static dstatement_t double_binop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, { OP(1, 1, 1, OP_MUL_D_1), 0, 8, 16 }, @@ -46,7 +46,7 @@ static dstatement_t double_binop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, { OP(1, 1, 1, OP_MUL_D_2), 0, 8, 16 }, @@ -129,7 +129,7 @@ static dstatement_t double_cossin_statements[] = { { OP(0, 0, 0, OP_DIV_D_2), 40, 16, 40 }, // xn /= f { OP(0, 0, 0, OP_ADD_D_2), 16, 24, 16 }, // f += inc { OP(0, 0, 0, OP_LT_D_1), 16, 30, 46 }, // f0 < fmax - { OP(0, 0, 0, OP_IFNZ_A), -7, 0, 46 }, // f0 < fmax + { OP(0, 0, 0, OP_IFNZ), -7, 0, 46 }, // f0 < fmax }; static pr_dvec4_t double_cmpop_init[] = { @@ -161,7 +161,7 @@ static dstatement_t double_cmpop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, { OP(1, 1, 1, OP_EQ_D_1), 0, 8, 16 }, @@ -177,7 +177,7 @@ static dstatement_t double_cmpop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, { OP(1, 1, 1, OP_EQ_D_2), 0, 8, 16 }, diff --git a/libs/gamecode/test/test-float.c b/libs/gamecode/test/test-float.c index 626f4aaa0..576518128 100644 --- a/libs/gamecode/test/test-float.c +++ b/libs/gamecode/test/test-float.c @@ -30,7 +30,7 @@ static dstatement_t float_binop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, { OP(1, 1, 1, OP_MUL_F_1), 0, 4, 8 }, @@ -46,7 +46,7 @@ static dstatement_t float_binop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, { OP(1, 1, 1, OP_MUL_F_2), 0, 4, 8 }, @@ -129,7 +129,7 @@ static dstatement_t float_cossin_statements[] = { { OP(0, 0, 0, OP_DIV_F_2), 20, 8, 20 }, // xn /= f { OP(0, 0, 0, OP_ADD_F_2), 8, 12, 8 }, // f += inc { OP(0, 0, 0, OP_LT_F_1), 8, 15, 23 }, // f0 < fmax - { OP(0, 0, 0, OP_IFNZ_A), -7, 0, 23 }, // f0 < fmax + { OP(0, 0, 0, OP_IFNZ), -7, 0, 23 }, // f0 < fmax }; static pr_vec4_t float_cmpop_init[] = { @@ -161,7 +161,7 @@ static dstatement_t float_cmpop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, { OP(1, 1, 1, OP_EQ_F_1), 0, 4, 8 }, @@ -177,7 +177,7 @@ static dstatement_t float_cmpop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, { OP(1, 1, 1, OP_EQ_F_2), 0, 4, 8 }, diff --git a/libs/gamecode/test/test-int.c b/libs/gamecode/test/test-int.c index f8b4a6a5e..6ca0dc928 100644 --- a/libs/gamecode/test/test-int.c +++ b/libs/gamecode/test/test-int.c @@ -28,7 +28,7 @@ static dstatement_t int_binop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, { OP(1, 1, 1, OP_MUL_I_1), 0, 4, 8 }, @@ -44,7 +44,7 @@ static dstatement_t int_binop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, { OP(1, 1, 1, OP_MUL_I_2), 0, 4, 8 }, @@ -121,7 +121,7 @@ static dstatement_t int_cmpop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, { OP(1, 1, 1, OP_EQ_I_1), 0, 4, 8 }, @@ -137,7 +137,7 @@ static dstatement_t int_cmpop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, { OP(1, 1, 1, OP_EQ_I_2), 0, 4, 8 }, diff --git a/libs/gamecode/test/test-long.c b/libs/gamecode/test/test-long.c index 36d62845e..b5b021e17 100644 --- a/libs/gamecode/test/test-long.c +++ b/libs/gamecode/test/test-long.c @@ -30,7 +30,7 @@ static dstatement_t long_binop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, { OP(1, 1, 1, OP_MUL_L_1), 0, 8, 16 }, @@ -46,7 +46,7 @@ static dstatement_t long_binop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, { OP(1, 1, 1, OP_MUL_L_2), 0, 8, 16 }, @@ -123,7 +123,7 @@ static dstatement_t long_cmpop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, { OP(1, 1, 1, OP_EQ_L_1), 0, 8, 16 }, @@ -139,7 +139,7 @@ static dstatement_t long_cmpop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, { OP(1, 1, 1, OP_EQ_L_2), 0, 8, 16 }, diff --git a/libs/gamecode/test/test-string.c b/libs/gamecode/test/test-string.c index a723eebb7..ceb716570 100644 --- a/libs/gamecode/test/test-string.c +++ b/libs/gamecode/test/test-string.c @@ -36,7 +36,7 @@ static dstatement_t string_statements[] = { { OP(0, 0, 0, OP_LEA_A), 24, 0, 6 }, // init k // for (i = 4; i-- > 0; ) { { OP(0, 0, 0, OP_LEA_A), 4, 0, 4 }, - { OP(0, 0, 0, OP_IFA_A), 2, 0, 4 }, + { OP(0, 0, 0, OP_IFA), 2, 0, 4 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_LEA_C), 4, -1, 4 }, // dec i @@ -45,7 +45,7 @@ static dstatement_t string_statements[] = { // for (j = 4; j-- > 0; ) { { OP(0, 0, 0, OP_LEA_A), 4, 0, 5 }, // init j - { OP(0, 0, 0, OP_IFA_A), 2, 0, 5 }, + { OP(0, 0, 0, OP_IFA), 2, 0, 5 }, { OP(0, 0, 0, OP_JUMP_A), -6, 0, 0 }, { OP(0, 0, 0, OP_LEA_C), 5, -1, 5 }, // dec j diff --git a/libs/gamecode/test/test-unsigned.c b/libs/gamecode/test/test-unsigned.c index de9fd3bfa..e37a84d94 100644 --- a/libs/gamecode/test/test-unsigned.c +++ b/libs/gamecode/test/test-unsigned.c @@ -28,7 +28,7 @@ static dstatement_t uint_cmpop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, // no unsigned EQ (redundant) @@ -44,7 +44,7 @@ static dstatement_t uint_cmpop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index //loop: { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 32 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, // no unsigned EQ (redundant) @@ -121,7 +121,7 @@ static dstatement_t ulong_cmpop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, // no unsigned EQ (redundant) @@ -137,7 +137,7 @@ static dstatement_t ulong_cmpop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 64 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, // no unsigned EQ (redundant) @@ -216,7 +216,7 @@ static dstatement_t uint_shiftop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 36 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 36, -1, 36 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 36 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 36 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 36, 1 }, { OP(1, 1, 1, OP_SHL_I_1), 0, 4, 12 }, @@ -232,7 +232,7 @@ static dstatement_t uint_shiftop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 4, 0, 36 }, // index //loop: { OP(0, 0, 0, OP_LEA_C), 36, -2, 36 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 36 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 36 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 36, 1 }, { OP(1, 1, 1, OP_SHL_I_2), 0, 4, 12 }, @@ -319,7 +319,7 @@ static dstatement_t ulong_shiftop_1_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 72 }, // init index //loop: { OP(0, 0, 0, OP_LEA_C), 72, -2, 72 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 72 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 72 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 72, 1 }, { OP(1, 1, 1, OP_SHL_L_1), 0, 8, 24 }, @@ -335,7 +335,7 @@ static dstatement_t ulong_shiftop_2_statements[] = { { OP(0, 0, 0, OP_LEA_A), 8, 0, 72 }, // index //loop: { OP(0, 0, 0, OP_LEA_C), 72, -4, 72 }, // dec index - { OP(0, 0, 0, OP_IFAE_A), 2, 0, 72 }, + { OP(0, 0, 0, OP_IFAE), 2, 0, 72 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_WITH), 4, 72, 1 }, { OP(1, 1, 1, OP_SHL_L_2), 0, 8, 24 }, From 7ea12b3ff993cf65c4c0e838848b72dd8ae4bcff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jan 2022 16:27:33 +0900 Subject: [PATCH 2188/3664] [gamecode] Implement the HOPS sub-instructions In the end, I decided any/all/none should be separate from the other horizontal ops, if I even do them (can be implemented by first converting to bool, then using the appropriate horizontal operation (& | etc). --- libs/gamecode/Makemodule.am | 13 ++++++++- libs/gamecode/hops.py | 55 +++++++++++++++++++++++++++++++++++++ libs/gamecode/pr_exec.c | 4 +++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 libs/gamecode/hops.py diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index ea9ae11b1..dbffb47b3 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -34,7 +34,14 @@ libs/gamecode/pr_opcode.lo: libs/gamecode/pr_opcode.c ${pr_opcode_src} convert_py = $(srcdir)/libs/gamecode/convert.py pr_convert_cinc = $(top_builddir)/libs/gamecode/pr_convert.cinc -BUILT_SOURCES += $(pr_opcode_cinc) $(pr_opcode_hinc) $(pr_convert_cinc) +hops_py = $(srcdir)/libs/gamecode/hops.py +pr_hops_cinc = $(top_builddir)/libs/gamecode/pr_hops.cinc + +BUILT_SOURCES += \ + $(pr_opcode_cinc) \ + $(pr_opcode_hinc) \ + $(pr_convert_cinc) \ + $(pr_hops_cinc) $(pr_opcode_cinc): $(opcodes_py) $(V_PY)$(PYTHON) $(opcodes_py) table > $(pr_opcode_cinc).t && \ @@ -48,3 +55,7 @@ $(pr_opcode_hinc): $(opcodes_py) $(pr_convert_cinc): $(convert_py) $(V_PY)$(PYTHON) $(convert_py) table > $(pr_convert_cinc).t && \ $(am__mv) $(pr_convert_cinc).t $(pr_convert_cinc) + +$(pr_hops_cinc): $(hops_py) + $(V_PY)$(PYTHON) $(hops_py) table > $(pr_hops_cinc).t && \ + $(am__mv) $(pr_hops_cinc).t $(pr_hops_cinc) diff --git a/libs/gamecode/hops.py b/libs/gamecode/hops.py new file mode 100644 index 000000000..04891036b --- /dev/null +++ b/libs/gamecode/hops.py @@ -0,0 +1,55 @@ +print("""// encoding is tssooo +// t = 0: 32-bit, t = 1: 64-bit +// ss = 00: reserved +// ss = 01: 2 components +// ss = 10: 3 components +// ss = 11: 4 components +// ooo = 000: and +// ooo = 001: or +// ooo = 010: xor +// ooo = 011: add.i +// ooo = 100: nand +// ooo = 101: nor +// ooo = 110: xnor +// ooo = 111: add.f +""") +#for vec3 +types = [ + ["int", "int", "int", "int", "int", "int", "int", "float"], + ["long", "long", "long", "long", "long", "long", "long", "double"] +] +#does not include size (2 or 4, 3 is special) +vec_types = [ + ["ivec", "ivec", "ivec", "ivec", "ivec", "ivec", "ivec", "vec"], + ["lvec", "lvec", "lvec", "lvec", "lvec", "lvec", "lvec", "dvec"] +] +operators = ["&", "|", "^", "+"] + +def case_str(type, width, op): + case = (type << 5) | (width << 3) | (op) + return f"case {case:03o}:" + +def src_str(type, width, op): + if width & 1: + return f"OPA({vec_types[type][op]}{width+1})" + else: + return f"OPA({types[type][op]})" + +def dst_str(type, width, op): + return f"OPC({types[type][op]})" + +def hop_str(type, width, op): + return f"OP_hop{width+1}" + +for type in range(2): + for width in range(1, 4): # 0 is reserved + for opcode in range(8): + case = case_str(type, width, opcode) + src = src_str(type, width, opcode) + dst = dst_str(type, width, opcode) + hop = hop_str(type, width, opcode) + op = operators[opcode & 3] + if width == 2: + print(f"{case} {dst} = {hop} (&{src}, {op}); break;") + else: + print(f"{case} {dst} = {hop} ({src}, {op}); break;") diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 3f8b9f365..8a0429807 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3387,8 +3387,12 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) // 1100 spare // 1101 spare // 1110 spare +#define OP_hop2(vec, op) ((vec)[0] op (vec)[1]) +#define OP_hop3(vec, op) ((vec)[0] op (vec)[1] op (vec)[2]) +#define OP_hop4(vec, op) ((vec)[0] op (vec)[1] op (vec)[2] op (vec)[3]) case OP_HOPS: switch (st->b) { +#include "libs/gamecode/pr_hops.cinc" default: PR_RunError (pr, "invalid hops code: %04o", st->b); From d57712975e644d662623e5cdfd78466b477a83f7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jan 2022 18:46:29 +0900 Subject: [PATCH 2189/3664] [gamecode] Add tests for the hops instructions And, of course, fix a bug in the inverted hops (yay for tests). --- libs/gamecode/hops.py | 2 +- libs/gamecode/test/Makemodule.am | 8 +- libs/gamecode/test/test-hops.c | 166 +++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 libs/gamecode/test/test-hops.c diff --git a/libs/gamecode/hops.py b/libs/gamecode/hops.py index 04891036b..634decc47 100644 --- a/libs/gamecode/hops.py +++ b/libs/gamecode/hops.py @@ -39,7 +39,7 @@ def dst_str(type, width, op): return f"OPC({types[type][op]})" def hop_str(type, width, op): - return f"OP_hop{width+1}" + return f"{'~' if op & 4 and op != 7 else ''}OP_hop{width+1}" for type in range(2): for width in range(1, 4): # 0 is reserved diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 0788861f8..d63023468 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -10,6 +10,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-conv7 \ libs/gamecode/test/test-double \ libs/gamecode/test/test-float \ + libs/gamecode/test/test-hops \ libs/gamecode/test/test-int \ libs/gamecode/test/test-lea \ libs/gamecode/test/test-load \ @@ -82,13 +83,18 @@ libs_gamecode_test_test_conv7_DEPENDENCIES= $(test_gamecode_libs) libs_gamecode_test_test_double_SOURCES= \ libs/gamecode/test/test-double.c libs_gamecode_test_test_double_LDADD= $(test_gamecode_libs) -libs_gamecode_test_test_double_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_double_DEPENDENCIES=$(test_gamecode_libs) libs_gamecode_test_test_float_SOURCES= \ libs/gamecode/test/test-float.c libs_gamecode_test_test_float_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_float_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_hops_SOURCES= \ + libs/gamecode/test/test-hops.c +libs_gamecode_test_test_hops_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_hops_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_int_SOURCES= \ libs/gamecode/test/test-int.c libs_gamecode_test_test_int_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-hops.c b/libs/gamecode/test/test-hops.c new file mode 100644 index 000000000..34d14fe2d --- /dev/null +++ b/libs/gamecode/test/test-hops.c @@ -0,0 +1,166 @@ +#include "head.c" + +#include "QF/mathlib.h" + +static pr_uivec4_t uint_hop_init[7] = { + { 0x0000ff00, 0x0000f0f0, 0x0000cccc, 0x0000aaaa }, +}; + +static pr_uivec4_t uint_hop_expect[] = { + { 0x0000ff00, 0x0000f0f0, 0x0000cccc, 0x0000aaaa }, + { 0x00008888, 0x0000eeee, 0x00006666, 0x00017776 }, + { 0xffff7777, 0xffff1111, 0xffff9999, 0 }, + { 0x00008080, 0x0000fefe, 0x00009696, 0x00026866 }, + { 0xffff7f7f, 0xffff0101, 0xffff6969, 0 }, + { 0x00008000, 0x0000fffe, 0x00006996, 0x00036766 }, + { 0xffff7fff, 0xffff0001, 0xffff9669, 0 }, +}; + +static dstatement_t uint_hop_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 4, 1 }, + { OP(0, 0, 0, OP_WITH), 0, 12, 2 }, + { OP(0, 0, 0, OP_WITH), 0, 20, 3 }, + + { OP(0, 0, 1, OP_HOPS), 2, 010, 0 }, + { OP(0, 0, 1, OP_HOPS), 2, 011, 1 }, + { OP(0, 0, 1, OP_HOPS), 2, 012, 2 }, + { OP(0, 0, 1, OP_HOPS), 2, 013, 3 }, + { OP(0, 0, 1, OP_HOPS), 2, 014, 4 }, + { OP(0, 0, 1, OP_HOPS), 2, 015, 5 }, + { OP(0, 0, 1, OP_HOPS), 2, 016, 6 }, + + { OP(0, 0, 2, OP_HOPS), 1, 020, 0 }, + { OP(0, 0, 2, OP_HOPS), 1, 021, 1 }, + { OP(0, 0, 2, OP_HOPS), 1, 022, 2 }, + { OP(0, 0, 2, OP_HOPS), 1, 023, 3 }, + { OP(0, 0, 2, OP_HOPS), 1, 024, 4 }, + { OP(0, 0, 2, OP_HOPS), 1, 025, 5 }, + { OP(0, 0, 2, OP_HOPS), 1, 026, 6 }, + + { OP(0, 0, 3, OP_HOPS), 0, 030, 0 }, + { OP(0, 0, 3, OP_HOPS), 0, 031, 1 }, + { OP(0, 0, 3, OP_HOPS), 0, 032, 2 }, + { OP(0, 0, 3, OP_HOPS), 0, 033, 3 }, + { OP(0, 0, 3, OP_HOPS), 0, 034, 4 }, + { OP(0, 0, 3, OP_HOPS), 0, 035, 5 }, + { OP(0, 0, 3, OP_HOPS), 0, 036, 6 }, +}; + +static pr_ulvec4_t ulong_hop_init[7] = { + { UINT64_C(0x00ff00000000), UINT64_C(0x0f0f00000000), + UINT64_C(0x333300000000), UINT64_C(0x555500000000) }, +}; + +static pr_ulvec4_t ulong_hop_expect[] = { + { UINT64_C(0x000000ff00000000), UINT64_C(0x00000f0f00000000), + UINT64_C(0x0000333300000000), UINT64_C(0x0000555500000000) }, + { UINT64_C(0x0000111100000000), UINT64_C(0x0000777700000000), + UINT64_C(0x0000666600000000), UINT64_C(0x0000888800000000) }, + { UINT64_C(0xffffeeeeffffffff), UINT64_C(0xffff8888ffffffff), + UINT64_C(0xffff9999ffffffff), 0 }, + { UINT64_C(0x0000010100000000), UINT64_C(0x00007f7f00000000), + UINT64_C(0x0000696900000000), UINT64_C(0x0000979700000000) }, + { UINT64_C(0xfffffefeffffffff), UINT64_C(0xffff8080ffffffff), + UINT64_C(0xffff9696ffffffff), 0 }, + { UINT64_C(0x0000000100000000), UINT64_C(0x00007fff00000000), + UINT64_C(0x0000699600000000), UINT64_C(0x0000989600000000) }, + { UINT64_C(0xfffffffeffffffff), UINT64_C(0xffff8000ffffffff), + UINT64_C(0xffff9669ffffffff), 0 }, +}; + +static dstatement_t ulong_hop_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 8, 1 }, + { OP(0, 0, 0, OP_WITH), 0, 24, 2 }, + { OP(0, 0, 0, OP_WITH), 0, 40, 3 }, + + { OP(0, 0, 1, OP_HOPS), 4, 050, 0 }, + { OP(0, 0, 1, OP_HOPS), 4, 051, 2 }, + { OP(0, 0, 1, OP_HOPS), 4, 052, 4 }, + { OP(0, 0, 1, OP_HOPS), 4, 053, 6 }, + { OP(0, 0, 1, OP_HOPS), 4, 054, 8 }, + { OP(0, 0, 1, OP_HOPS), 4, 055, 10 }, + { OP(0, 0, 1, OP_HOPS), 4, 056, 12 }, + + { OP(0, 0, 2, OP_HOPS), 2, 060, 0 }, + { OP(0, 0, 2, OP_HOPS), 2, 061, 2 }, + { OP(0, 0, 2, OP_HOPS), 2, 062, 4 }, + { OP(0, 0, 2, OP_HOPS), 2, 063, 6 }, + { OP(0, 0, 2, OP_HOPS), 2, 064, 8 }, + { OP(0, 0, 2, OP_HOPS), 2, 065, 10 }, + { OP(0, 0, 2, OP_HOPS), 2, 066, 12 }, + + { OP(0, 0, 3, OP_HOPS), 0, 070, 0 }, + { OP(0, 0, 3, OP_HOPS), 0, 071, 2 }, + { OP(0, 0, 3, OP_HOPS), 0, 072, 4 }, + { OP(0, 0, 3, OP_HOPS), 0, 073, 6 }, + { OP(0, 0, 3, OP_HOPS), 0, 074, 8 }, + { OP(0, 0, 3, OP_HOPS), 0, 075, 10 }, + { OP(0, 0, 3, OP_HOPS), 0, 076, 12 }, +}; + +static pr_vec4_t float_hop_init[2] = { + { 1, 2, 3, 4 }, +}; + +static pr_vec4_t float_hop_expect[] = { + { 1, 2, 3, 4 }, + { 3, 6, 10, 0 }, +}; + +static dstatement_t float_hop_statements[] = { + { OP(0, 0, 0, OP_HOPS), 0, 017, 4 }, + { OP(0, 0, 0, OP_HOPS), 0, 027, 5 }, + { OP(0, 0, 0, OP_HOPS), 0, 037, 6 }, +}; + +static pr_dvec4_t double_hop_init[2] = { + { 1, 2, 3, 4 }, +}; + +static pr_dvec4_t double_hop_expect[] = { + { 1, 2, 3, 4 }, + { 3, 6, 10, 0 }, +}; + +static dstatement_t double_hop_statements[] = { + { OP(0, 0, 0, OP_HOPS), 0, 057, 8 }, + { OP(0, 0, 0, OP_HOPS), 0, 067, 10 }, + { OP(0, 0, 0, OP_HOPS), 0, 077, 12 }, +}; + +test_t tests[] = { + { + .desc = "uint hops", + .num_globals = num_globals(uint_hop_init,uint_hop_expect), + .num_statements = num_statements (uint_hop_statements), + .statements = uint_hop_statements, + .init_globals = (pr_int_t *) uint_hop_init, + .expect_globals = (pr_int_t *) uint_hop_expect, + }, + { + .desc = "ulong hops", + .num_globals = num_globals(ulong_hop_init,ulong_hop_expect), + .num_statements = num_statements (ulong_hop_statements), + .statements = ulong_hop_statements, + .init_globals = (pr_int_t *) ulong_hop_init, + .expect_globals = (pr_int_t *) ulong_hop_expect, + }, + { + .desc = "float hops", + .num_globals = num_globals(float_hop_init,float_hop_expect), + .num_statements = num_statements (float_hop_statements), + .statements = float_hop_statements, + .init_globals = (pr_int_t *) float_hop_init, + .expect_globals = (pr_int_t *) float_hop_expect, + }, + { + .desc = "double hops", + .num_globals = num_globals(double_hop_init,double_hop_expect), + .num_statements = num_statements (double_hop_statements), + .statements = double_hop_statements, + .init_globals = (pr_int_t *) double_hop_init, + .expect_globals = (pr_int_t *) double_hop_expect, + }, +}; + +#include "main.c" From 2b8253352699e0bc6b26423f4295b021b7c2b6bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jan 2022 19:32:47 +0900 Subject: [PATCH 2190/3664] [gamecode] Add double time state instructions This has been a long-held wishlist item, really, and I thought I might as well take the opportunity to add the instructions. The double versions of STATE require both the nextthink field and time global to be double (but they're not resolved properly yet: marked with "FIXME double time" comments). Also, the frame number for double time state is integer rather than float. --- include/QF/progs.h | 3 +- libs/console/menu.c | 6 ++-- libs/gamecode/opcodes.py | 36 +++++++++++++------ libs/gamecode/pr_edict.c | 10 +++--- libs/gamecode/pr_exec.c | 67 ++++++++++++++++++++++++----------- libs/gamecode/pr_resolve.c | 4 +-- libs/gamecode/pr_v6p_opcode.c | 2 +- nq/source/sv_progs.c | 2 +- qw/source/sv_progs.c | 2 +- 9 files changed, 87 insertions(+), 45 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 572528891..798806de5 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1962,7 +1962,8 @@ struct progs_s { /// \name globals and fields needed by the VM ///@{ struct { - float *time; ///< required for OP_STATE + double *dtime; ///< required for OP_STATE d + float *ftime; ///< required for OP_STATE f pr_int_t *self; ///< required for OP_STATE pointer_t *stack; ///< required for OP_(PUSH|POP)* } globals; diff --git a/libs/console/menu.c b/libs/console/menu.c index e6dcc72a4..a98c2d71a 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -134,7 +134,7 @@ menu_resolve_globals (progs_t *pr) if (!(def = PR_FindGlobal (pr, sym = "time"))) goto error; - menu_pr_state.globals.time = &G_FLOAT (pr, def->ofs); + menu_pr_state.globals.ftime = &G_FLOAT (pr, def->ofs);//FIXME double time return 1; error: Sys_Printf ("%s: undefined symbol %s\n", pr->progs_name, sym); @@ -672,7 +672,7 @@ Menu_Draw (view_t *view) if (menu->fadescreen) r_funcs->Draw_FadeScreen (); - *menu_pr_state.globals.time = *con_data.realtime; + *menu_pr_state.globals.ftime = *con_data.realtime;//FIXME double time if (menu->draw) { int ret; @@ -729,7 +729,7 @@ void Menu_Draw_Hud (view_t *view) { run_menu_pre (); - *menu_pr_state.globals.time = *con_data.realtime; + *menu_pr_state.globals.ftime = *con_data.realtime;//FIXME double time PR_ExecuteProgram (&menu_pr_state, menu_draw_hud); run_menu_post (); diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index db39a5621..4b123ce19 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -19,14 +19,16 @@ bitmap_txt = """ 1 1010 t100 swizzle 1 1011 tooo vecops 1 1101 01oo move -1 1101 0111 convert (conversion mode in st->b) 1 1101 11oo memset -1 1101 1111 with (mode in st->a, value in st->b, reg in st->c) +1 1101 c111 statef 1 1110 c1cc branch -1 1110 t111 state +1 1110 c111 stated 1 1111 00mm lea 1 1111 01td vecops2 -1 1111 1nnn +1 1111 10nn +1 1111 1100 convert (conversion mode in st->b) +1 1111 1101 with (mode in st->a, value in st->b, reg in st->c) +1 1111 1110 1 1111 1111 hops """ @@ -328,19 +330,32 @@ shiftops_formats = { ], }, } -state_formats = { - "opcode": "OP_STATE_{state[t]}", - "mnemonic": "state.{state[t]}", +statef_formats = { + "opcode": "OP_STATE_{state[c]}", + "mnemonic": "state.{state[c]}", "opname": "state", - "format": "{state_fmt[t]}", + "format": "{state_fmt[c]}", "widths": "1, 1, 1", - "types": "ev_float, ev_func, {state_types[t]}", + "types": "ev_float, ev_func, {state_types[c]}", "args": { "state": ["ft", "ftt"], "state_fmt": ["%Ga, %Gb", "%Ga, %Gb, %Gc"], "state_types": ["ev_invalid", "ev_float"], }, } +stated_formats = { + "opcode": "OP_STATE_{state[c]}", + "mnemonic": "state.{state[c]}", + "opname": "state", + "format": "{state_fmt[c]}", + "widths": "1, 1, 1", + "types": "ev_float, ev_func, {state_types[c]}", + "args": { + "state": ["dt", "dtt"], + "state_fmt": ["%Ga, %Gb", "%Ga, %Gb, %Gc"], + "state_types": ["ev_invalid", "ev_double"], + }, +} store_formats = { "opcode": "OP_STORE_{op_mode[mm]}_{ss+1}", "mnemonic": "store", @@ -476,7 +491,8 @@ group_map = { "popregs": popregs_formats, "scale": scale_formats, "shiftops": shiftops_formats, - "state": state_formats, + "statef": statef_formats, + "stated": stated_formats, "store": store_formats, "string": string_formats, "swizzle": swizzle_formats, diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index f16c2bd41..c766c0861 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -79,9 +79,9 @@ ED_Alloc (progs_t *pr) e = EDICT_NUM (pr, i); // the first couple seconds of server time can involve a lot of // freeing and allocating, so relax the replacement policy - if (e->free && (!pr->globals.time + if (e->free && (!pr->globals.ftime//FIXME double time || e->freetime < 2 - || *pr->globals.time - e->freetime > 0.5)) { + || *pr->globals.ftime - e->freetime > 0.5)) { ED_ClearEdict (pr, e, 0); return e; } @@ -123,8 +123,8 @@ ED_Free (progs_t *pr, edict_t *ed) ED_ClearEdict (pr, ed, 0); } ed->free = true; - if (pr->globals.time) - ed->freetime = *pr->globals.time; + if (pr->globals.ftime)//FIXME double time + ed->freetime = *pr->globals.ftime; } //=========================================================================== @@ -199,7 +199,7 @@ ED_Count (progs_t *pr) for (i = 0; i < *pr->num_edicts; i++) { ent = EDICT_NUM (pr, i); if (ent->free) { - if (pr->globals.time && *pr->globals.time - ent->freetime <= 0.5) + if (pr->globals.ftime && *pr->globals.ftime - ent->freetime <= 0.5)//FIXME double time zombie++; continue; } diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 8a0429807..adf9cf515 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1482,7 +1482,7 @@ op_call: int nextthink = pr->fields.nextthink + self; int frame = pr->fields.frame + self; int think = pr->fields.think + self; - float time = *pr->globals.time + 0.1; + float time = *pr->globals.ftime + 0.1; pr->pr_edict_area[nextthink].float_var = time; pr->pr_edict_area[frame].float_var = OPA(float); pr->pr_edict_area[think].func_var = OPB(uint); @@ -1494,7 +1494,7 @@ op_call: int nextthink = pr->fields.nextthink + self; int frame = pr->fields.frame + self; int think = pr->fields.think + self; - float time = *pr->globals.time + OPC(float); + float time = *pr->globals.ftime + OPC(float); pr->pr_edict_area[nextthink].float_var = time; pr->pr_edict_area[frame].float_var = OPA(float); pr->pr_edict_area[think].func_var = OPB(uint); @@ -2891,9 +2891,13 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) MM(ivec4) = STK(ivec4); break; // 0 0100 + // spare // 0 0101 + // spare // 0 0110 + // spare // 0 0111 + // spare #define OP_cmp_1(OP, T, rt, cmp, ct) \ case OP_##OP##_##T##_1: \ @@ -2936,7 +2940,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_cmp(GE, >=); // 0 1110 OP_cmp(LE, <=); - // 0 1111 // spare @@ -3276,12 +3279,16 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) memmove (pr->pr_globals + OPC(int), pr->pr_globals + OPA(int), st->b * sizeof (pr_type_t)); break; - case OP_CONV: - switch (st->b) { -#include "libs/gamecode/pr_convert.cinc" - default: - PR_RunError (pr, "invalid conversion code: %04o", - st->b); + case OP_STATE_ft: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.ftime + 0.1; + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = op_b->func_var; } break; OP_cmp_T (GE, U, long, lvec2, lvec4, >=, ulong, ulvec2, ulvec4); @@ -3294,8 +3301,17 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_MEMSET_PI: pr_memset (pr->pr_globals + OPC(int), OPA(int), st->b); break; - case OP_WITH: - pr_with (pr, st); + case OP_STATE_ftt: + { + int self = *pr->globals.self; + int nextthink = pr->fields.nextthink + self; + int frame = pr->fields.frame + self; + int think = pr->fields.think + self; + float time = *pr->globals.ftime + OPC(float); + pr->pr_edict_area[nextthink].float_var = time; + pr->pr_edict_area[frame].float_var = OPA(float); + pr->pr_edict_area[think].func_var = op_b->func_var; + } break; // 1 1110 OP_cmp_T (LE, u, int, ivec2, ivec4, <=, uint, uivec2, uivec4); @@ -3317,15 +3333,15 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_STATE_ft: + case OP_STATE_dt: { int self = *pr->globals.self; int nextthink = pr->fields.nextthink + self; int frame = pr->fields.frame + self; int think = pr->fields.think + self; - float time = *pr->globals.time + 0.1; - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); + double time = *pr->globals.dtime + 0.1; + *(double *) (&pr->pr_edict_area[nextthink]) = time; + pr->pr_edict_area[frame].integer_var = OPA(int); pr->pr_edict_area[think].func_var = op_b->func_var; } break; @@ -3348,15 +3364,15 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) st = pr->pr_statements + pr->pr_xstatement; } break; - case OP_STATE_ftt: + case OP_STATE_dtt: { int self = *pr->globals.self; int nextthink = pr->fields.nextthink + self; int frame = pr->fields.frame + self; int think = pr->fields.think + self; - float time = *pr->globals.time + OPC(float); - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); + double time = *pr->globals.dtime + OPC(double); + *(double *) (&pr->pr_edict_area[nextthink]) = time; + pr->pr_edict_area[frame].integer_var = OPA(int); pr->pr_edict_area[think].func_var = op_b->func_var; } break; @@ -3384,8 +3400,17 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OPC(dvec4) = vqmuld (OPA(dvec4), OPB(dvec4)); break; // 10nn spare - // 1100 spare - // 1101 spare + case OP_CONV: + switch (st->b) { +#include "libs/gamecode/pr_convert.cinc" + default: + PR_RunError (pr, "invalid conversion code: %04o", + st->b); + } + break; + case OP_WITH: + pr_with (pr, st); + break; // 1110 spare #define OP_hop2(vec, op) ((vec)[0] op (vec)[1]) #define OP_hop3(vec, op) ((vec)[0] op (vec)[1] op (vec)[2]) diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 6270653d2..c62a8e9cb 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -143,9 +143,9 @@ PR_ResolveGlobals (progs_t *pr) pr->pr_param_alignment = G_INT (pr, def->ofs); } memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params)); - if (!pr->globals.time) { + if (!pr->globals.ftime) {//FIXME double time if ((def = PR_FindGlobal (pr, "time"))) - pr->globals.time = &G_FLOAT (pr, def->ofs); + pr->globals.ftime = &G_FLOAT (pr, def->ofs); } if (!pr->globals.self) { if ((def = PR_FindGlobal (pr, ".self")) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 5ded2c764..6163050eb 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -1637,7 +1637,7 @@ PR_Check_Opcodes (progs_t *pr) int pushpop_ok = 0; pr_uint_t i; - if (pr->globals.time && pr->globals.self && pr->fields.nextthink != -1 + if (pr->globals.ftime && pr->globals.self && pr->fields.nextthink != -1 && pr->fields.think != -1 && pr->fields.frame != -1) { state_ok = 1; } diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 2c9d82836..3a8c44dd2 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -460,7 +460,7 @@ resolve (progs_t *pr) resolve_fields (pr, nq_opt_fields, 0); // progs engine needs these globals anyway sv_pr_state.globals.self = sv_globals.self; - sv_pr_state.globals.time = sv_globals.time; + sv_pr_state.globals.ftime = sv_globals.time;//FIXME double time return ret; } diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 93f6042a0..6351317e8 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -493,7 +493,7 @@ resolve (progs_t *pr) resolve_fields (pr, qw_opt_fields, 0); // progs engine needs these globals anyway sv_pr_state.globals.self = sv_globals.self; - sv_pr_state.globals.time = sv_globals.time; + sv_pr_state.globals.ftime = sv_globals.time;//FIXME double time return ret; } From 0bd05c71ac7e68b9982ffe373c87c3cc1b3038cf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jan 2022 22:15:18 +0900 Subject: [PATCH 2191/3664] [gamecode] Use unsigned for entity values I don't know why they were ever signed (oversight at id and just propagated?). Anyway, this resulted in "unsigned" spreading a bit, but all to reasonable places. --- include/QF/progs.h | 16 ++++++++-------- include/QF/progs/pr_comp.h | 2 +- include/netmain.h | 2 +- libs/gamecode/pr_debug.c | 2 +- libs/gamecode/pr_edict.c | 17 ++++++++--------- libs/gamecode/pr_resolve.c | 2 +- libs/net/net_main.c | 6 +++--- libs/net/nm/net_dgrm.c | 2 +- libs/ruamoko/pr_cmds.c | 4 ++-- nq/include/server.h | 6 +++--- nq/include/sv_progs.h | 12 ++++++------ nq/source/host.c | 15 ++++++++------- nq/source/host_cmd.c | 27 +++++++++++++-------------- nq/source/sv_main.c | 20 ++++++++++---------- nq/source/sv_phys.c | 8 ++++---- nq/source/sv_pr_cmds.c | 27 ++++++++++++++------------- nq/source/sv_user.c | 2 +- nq/source/world.c | 8 +++----- qw/include/server.h | 6 +++--- qw/include/sv_progs.h | 12 ++++++------ qw/source/sv_init.c | 7 ++----- qw/source/sv_phys.c | 8 ++++---- qw/source/sv_pr_cmds.c | 7 +++---- qw/source/sv_progs.c | 2 +- qw/source/sv_user.c | 9 +++------ qw/source/world.c | 8 +++----- tools/qfcc/source/qfprogs.c | 4 ++-- tools/qfcc/test/test-harness.c | 4 ++-- 28 files changed, 117 insertions(+), 128 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 798806de5..e8b4136dc 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -276,8 +276,8 @@ void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); struct edict_s { qboolean free; progs_t *pr; ///< progs owning this edict - int entnum; ///< number of this entity - int edict; ///< offset of this entity in pr_edict_area + pr_uint_t entnum; ///< number of this entity + pr_uint_t edict; ///< offset of this entity in pr_edict_area float freetime; ///< sv.time when the object was freed void *edata; ///< external per-edict data }; @@ -286,8 +286,8 @@ struct edict_s { void ED_ClearEdict (progs_t *pr, edict_t *e, int val); edict_t *ED_Alloc (progs_t *pr); void ED_Free (progs_t *pr, edict_t *ed); -edict_t *ED_EdictNum(progs_t *pr, pr_int_t n) __attribute__((pure)); -pr_int_t ED_NumForEdict(progs_t *pr, edict_t *e) __attribute__((pure)); +edict_t *ED_EdictNum(progs_t *pr, pr_uint_t n) __attribute__((pure)); +pr_uint_t ED_NumForEdict(progs_t *pr, edict_t *e) __attribute__((pure)); void ED_Count (progs_t *pr); qboolean PR_EdictValid (progs_t *pr, pr_uint_t e) __attribute__((pure)); @@ -1896,9 +1896,9 @@ struct progs_s { /// \todo FIXME should this be outside the VM? ///@{ edict_t **pr_edicts; - int max_edicts; ///< set by user - int *num_edicts; - int *reserved_edicts; ///< alloc will start at reserved_edicts+1 + pr_uint_t max_edicts; ///< set by user + pr_uint_t *num_edicts; + pr_uint_t *reserved_edicts; ///< alloc will start at reserved_edicts+1 void (*unlink) (edict_t *ent); void (*flush) (void); int (*prune_edict) (progs_t *pr, edict_t *ent); @@ -1964,7 +1964,7 @@ struct progs_s { struct { double *dtime; ///< required for OP_STATE d float *ftime; ///< required for OP_STATE f - pr_int_t *self; ///< required for OP_STATE + pr_uint_t *self; ///< required for OP_STATE pointer_t *stack; ///< required for OP_(PUSH|POP)* } globals; struct { diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 8ce204613..2b5c0ad79 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -537,7 +537,7 @@ typedef union pr_type_u { float float_var; string_t string_var; func_t func_var; - pr_int_t entity_var; + pr_uint_t entity_var; float vector_var; // really [3], but this structure must be 32 bits float quat_var; // really [4], but this structure must be 32 bits pr_int_t integer_var; diff --git a/include/netmain.h b/include/netmain.h index 43b947aa7..0a4587b26 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -268,7 +268,7 @@ void NET_AddCachedHost (const char *name, const char *map, const char *cname, extern double net_time; extern struct msg_s *net_message; -extern int net_activeconnections; +extern unsigned net_activeconnections; /** Initialize the networking sub-system. */ diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index b77dc940a..1034c7b95 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1266,7 +1266,7 @@ pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, void *_data) progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - if (pr->pr_edicts && value->entity_var >= 0 + if (pr->pr_edicts && value->entity_var < pr->max_edicts && !(value->entity_var % pr->pr_edict_size)) { edict_t *edict = PROG_TO_EDICT (pr, value->entity_var); diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index c766c0861..34c132b20 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -68,7 +68,7 @@ ED_ClearEdict (progs_t *pr, edict_t *e, int val) VISIBLE edict_t * ED_Alloc (progs_t *pr) { - pr_int_t i; + pr_uint_t i; edict_t *e; int start = pr->reserved_edicts ? *pr->reserved_edicts : 0; @@ -149,7 +149,7 @@ ED_PrintNum (progs_t *pr, pr_int_t ent, const char *fieldname) VISIBLE void ED_PrintEdicts (progs_t *pr, const char *fieldval) { - pr_int_t i; + pr_uint_t i; int count; pr_def_t *def; @@ -183,7 +183,6 @@ ED_PrintEdicts (progs_t *pr, const char *fieldval) VISIBLE void ED_Count (progs_t *pr) { - pr_int_t i; int active, models, solid, step, zombie; pr_def_t *solid_def; pr_def_t *model_def; @@ -196,7 +195,7 @@ ED_Count (progs_t *pr) solid_def = PR_FindField (pr, "solid"); model_def = PR_FindField (pr, "model"); active = models = solid = step = zombie = 0; - for (i = 0; i < *pr->num_edicts; i++) { + for (pr_uint_t i = 0; i < *pr->num_edicts; i++) { ent = EDICT_NUM (pr, i); if (ent->free) { if (pr->globals.ftime && *pr->globals.ftime - ent->freetime <= 0.5)//FIXME double time @@ -218,22 +217,22 @@ ED_Count (progs_t *pr) } edict_t * -ED_EdictNum (progs_t *pr, pr_int_t n) +ED_EdictNum (progs_t *pr, pr_uint_t n) { - if (n < 0 || n >= *pr->num_edicts) + if (n >= *pr->num_edicts) PR_RunError (pr, "EDICT_NUM: bad number %d", n); return PR_edicts(pr) + n; } -pr_int_t +pr_uint_t ED_NumForEdict (progs_t *pr, edict_t *e) { - pr_int_t b; + pr_uint_t b; b = NUM_FOR_BAD_EDICT (pr, e); - if (b && (b < 0 || b >= *pr->num_edicts)) + if (b && b >= *pr->num_edicts) PR_RunError (pr, "NUM_FOR_EDICT: bad pointer %d %p %p", b, e, pr->pr_edicts); diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index c62a8e9cb..c0c090016 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -150,7 +150,7 @@ PR_ResolveGlobals (progs_t *pr) if (!pr->globals.self) { if ((def = PR_FindGlobal (pr, ".self")) || (def = PR_FindGlobal (pr, "self"))) - pr->globals.self = &G_INT (pr, def->ofs); + pr->globals.self = &G_UINT (pr, def->ofs); } if (!pr->globals.stack) { if ((def = PR_FindGlobal (pr, ".stack")) diff --git a/libs/net/net_main.c b/libs/net/net_main.c index 9d8a34e09..e534c4156 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -78,7 +78,7 @@ PollProcedure slistPollProcedure = { NULL, 0.0, Slist_Poll }; static sizebuf_t _net_message_message; static qmsg_t _net_message = { 0, 0, &_net_message_message }; qmsg_t *net_message = &_net_message; -int net_activeconnections = 0; +unsigned net_activeconnections = 0; int messagesSent = 0; int messagesReceived = 0; @@ -197,7 +197,7 @@ NET_Listen_f (void) static void MaxPlayers_f (void) { - int n; + unsigned n; if (Cmd_Argc () != 2) { Sys_Printf ("\"maxplayers\" is \"%u\"\n", svs.maxclients); @@ -710,7 +710,7 @@ int NET_SendToAll (sizebuf_t *data, double blocktime) { double start; - int i; + unsigned i; int count = 0; qboolean state1[MAX_SCOREBOARD]; /* can we send */ qboolean state2[MAX_SCOREBOARD]; /* did we send */ diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 3f9cf50b1..9aa10ef31 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -652,7 +652,7 @@ _Datagram_CheckNewConnections (void) if (command == CCREQ_PLAYER_INFO) { int playerNumber; int activeNumber; - int clientNumber; + unsigned clientNumber; client_t *client; playerNumber = MSG_ReadByte (net_message); diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index cc7a7d8b9..36827ad4e 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -253,7 +253,7 @@ PF_Find (progs_t *pr) { const char *s = 0, *t; // ev_string int i; // ev_vector - int e, f; + pr_uint_t e, f; etype_t type; pr_def_t *field_def; edict_t *ed; @@ -394,7 +394,7 @@ PF_ceil (progs_t *pr) static void PF_nextent (progs_t *pr) { - int i; + pr_uint_t i; edict_t *ent; i = P_EDICTNUM (pr, 0); diff --git a/nq/include/server.h b/nq/include/server.h index 7e78394ce..5af088cc8 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -44,8 +44,8 @@ extern progs_t sv_pr_state; typedef struct { - int maxclients; - int maxclientslimit; + unsigned maxclients; + unsigned maxclientslimit; struct client_s *clients; // [maxclients] void (*phys_client) (struct edict_s *ent, int num); int serverflags; // episode completion information @@ -75,7 +75,7 @@ typedef struct struct model_s *models[MAX_MODELS]; const char *sound_precache[MAX_SOUNDS]; // NULL terminated const char *lightstyles[MAX_LIGHTSTYLES]; - int num_edicts; + unsigned num_edicts; int max_edicts; edict_t *edicts; // can NOT be array indexed, because // edict_t is variable sized, but can diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 71a371f48..0d0ea9635 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -38,9 +38,9 @@ #include "sv_pr_cmds.h" typedef struct { - pr_int_t *self; - pr_int_t *other; - pr_int_t *world; + pr_uint_t *self; + pr_uint_t *other; + pr_uint_t *world; float *time; float *frametime; float *force_retouch; @@ -64,13 +64,13 @@ typedef struct { vec3_t *trace_endpos; vec3_t *trace_plane_normal; float *trace_plane_dist; - pr_int_t *trace_ent; + pr_uint_t *trace_ent; float *trace_inopen; float *trace_inwater; - pr_int_t *msg_entity; + pr_uint_t *msg_entity; string_t *null; - pr_int_t *newmis; + pr_uint_t *newmis; } sv_globals_t; extern sv_globals_t sv_globals; diff --git a/nq/source/host.c b/nq/source/host.c index be2b2d232..907250a5c 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -323,7 +323,6 @@ void SV_BroadcastPrintf (const char *fmt, ...) { static dstring_t *str; - int i; va_list argptr; if (!str) @@ -333,7 +332,7 @@ SV_BroadcastPrintf (const char *fmt, ...) dvsprintf (str, fmt, argptr); va_end (argptr); - for (i = 0; i < svs.maxclients; i++) + for (unsigned i = 0; i < svs.maxclients; i++) if (svs.clients[i].active && svs.clients[i].spawned) { MSG_WriteByte (&svs.clients[i].message, svc_print); MSG_WriteString (&svs.clients[i].message, str->str); @@ -372,7 +371,8 @@ void SV_DropClient (qboolean crash) { client_t *client; - int saveSelf, i; + unsigned i; + pr_uint_t saveSelf; if (!crash) { // send any final messages (don't check for errors) @@ -406,7 +406,8 @@ SV_DropClient (qboolean crash) net_activeconnections--; // send notification to all clients - for (i = 0, client = svs.clients; i < svs.maxclients; i++, client++) { + for (i = 0, client = svs.clients; i < svs.maxclients; + i++, client++) { if (!client->active) continue; MSG_WriteByte (&client->message, svc_updatename); @@ -431,7 +432,7 @@ Host_ShutdownServer (qboolean crash) { byte message[4]; double start; - int count, i; + unsigned count, i; sizebuf_t buf; if (!sv.active) @@ -711,7 +712,7 @@ Host_Frame (float time) { double time1, time2; static double timetotal; - int i, c, m; + int c, m; static int timecount; if (!serverprofile->int_val) { @@ -733,7 +734,7 @@ Host_Frame (float time) timecount = 0; timetotal = 0; c = 0; - for (i = 0; i < svs.maxclients; i++) { + for (unsigned i = 0; i < svs.maxclients; i++) { if (svs.clients[i].active) c++; } diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 9f10ed8e9..3c51cb894 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -78,7 +78,7 @@ Host_Status_f (void) int seconds; int minutes; int hours = 0; - int j; + unsigned j; __attribute__((format(PRINTF, 1, 2))) void (*print) (const char *fmt, ...); if (cmd_source == src_command) { @@ -210,7 +210,7 @@ Host_Fly_f (void) static void Host_Ping_f (void) { - int i, j; + unsigned i, j; float total; client_t *client; @@ -421,7 +421,7 @@ static plitem_t * entities_array (void) { plitem_t *entities = PL_NewArray (); - int i; + pr_uint_t i; for (i = 0; i < sv.num_edicts; i++) { PL_A_AddObject (entities, @@ -517,7 +517,6 @@ Host_Savegame_f (void) const char *save_name; char *save_text; QFile *f; - int i; char *bup1, *bup2 = 0; @@ -549,7 +548,7 @@ Host_Savegame_f (void) return; } - for (i = 0; i < svs.maxclients; i++) { + for (unsigned i = 0; i < svs.maxclients; i++) { if (svs.clients[i].active && (SVfloat (svs.clients[i].edict, health) <= 0)) { Sys_Printf ("Can't savegame with a dead player\n"); @@ -562,7 +561,7 @@ Host_Savegame_f (void) if (strcmp (save_name, "quick") == 0) { bup2 = nva ("%s/%s%d.sav", qfs_gamedir->dir.def, save_name, MAX_QUICK); QFS_Remove (bup2); - for (i = MAX_QUICK - 1; i > 0; i--) { + for (int i = MAX_QUICK - 1; i > 0; i--) { bup1 = nva ("%s/%s%d.sav", qfs_gamedir->dir.def, save_name, i); QFS_Rename (bup1, bup2); free (bup2); @@ -783,7 +782,7 @@ Host_Say (qboolean teamonly) { client_t *client; client_t *save; - int j; + unsigned j; char *p; char text[64]; qboolean fromServer = false; @@ -817,7 +816,7 @@ Host_Say (qboolean teamonly) snprintf (text, sizeof (text), "%c<%s> ", 1, hostname->string); j = sizeof (text) - 2 - strlen (text); // -2 for /n and null terminator - if ((int) strlen (p) > j) + if (strlen (p) > j) p[j] = 0; strcat (text, p); @@ -854,7 +853,7 @@ Host_Tell_f (void) { client_t *client; client_t *save; - int j; + unsigned j; char *p; char text[64]; @@ -879,7 +878,7 @@ Host_Tell_f (void) } // check length & truncate if necessary j = sizeof (text) - 2 - strlen (text); // -2 for /n and null terminator - if ((int) strlen (p) > j) + if (strlen (p) > j) p[j] = 0; strcat (text, p); @@ -969,7 +968,7 @@ Host_PreSpawn_f (void) static void Host_Spawn_f (void) { - int i; + unsigned i; client_t *client; edict_t *ent; float *sendangles; @@ -1099,7 +1098,7 @@ Host_Kick_f (void) const char *who; const char *message = NULL; client_t *save; - int i; + unsigned i; qboolean byNumber = false; if (cmd_source == src_command) { @@ -1115,7 +1114,7 @@ Host_Kick_f (void) if (Cmd_Argc () > 2 && strcmp (Cmd_Argv (1), "#") == 0) { i = atof (Cmd_Argv (2)) - 1; - if (i < 0 || i >= svs.maxclients) + if (i >= svs.maxclients) return; if (!svs.clients[i].active) return; @@ -1291,7 +1290,7 @@ Host_Give_f (void) static edict_t * FindViewthing (void) { - int i; + pr_uint_t i; edict_t *e; for (i = 0; i < sv.num_edicts; i++) { diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 3f5e248e2..f11f1389d 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -351,7 +351,7 @@ SV_ConnectClient (int clientnum) void SV_CheckForNewClients (void) { - int i; + unsigned i; struct qsocket_s *ret; // check for new connections @@ -443,7 +443,7 @@ SV_FatPVS (vec3_t org) static void SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) { - int bits, e, i; + pr_uint_t bits, e; set_t *pvs; float miss; vec3_t org; @@ -489,7 +489,7 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) bits = 0; - for (i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { miss = SVvector (ent, origin)[i] - baseline->origin[i]; if (miss < -0.1 || miss > 0.1) bits |= U_ORIGIN1 << i; @@ -603,7 +603,7 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) static void SV_CleanupEnts (void) { - int e; + pr_uint_t e; edict_t *ent; ent = NEXT_EDICT (&sv_pr_state, sv.edicts); @@ -826,7 +826,7 @@ SV_SendClientDatagram (client_t *client) static void SV_UpdateToReliableMessages (void) { - int i, j; + unsigned i, j; client_t *client; // check for changes to be sent over the reliable streams @@ -884,7 +884,7 @@ SV_SendNop (client_t *client) void SV_SendClientMessages (void) { - int i; + unsigned i; // update frags, names, etc SV_UpdateToReliableMessages (); @@ -964,7 +964,7 @@ SV_ModelIndex (const char *name) static void SV_CreateBaseline (void) { - int entnum; + pr_uint_t entnum; edict_t *svent; entity_state_t *baseline; int bits; @@ -1077,7 +1077,7 @@ SV_SendReconnect (void) void SV_SaveSpawnparms (void) { - int i, j; + unsigned i, j; svs.serverflags = *sv_globals.serverflags; @@ -1161,7 +1161,7 @@ SV_SpawnServer (const char *server) // leave slots at start for only clients sv.num_edicts = svs.maxclients + 1; - for (int i = 0; i < svs.maxclients; i++) { + for (unsigned i = 0; i < svs.maxclients; i++) { ent = EDICT_NUM (&sv_pr_state, i + 1); svs.clients[i].edict = ent; } @@ -1243,7 +1243,7 @@ SV_SpawnServer (const char *server) sv.signon.cursize); // send serverinfo to all connected clients - for (int i = 0; i < svs.maxclients; i++) { + for (unsigned i = 0; i < svs.maxclients; i++) { host_client = svs.clients + i; if (host_client->active) { SV_SendServerinfo (host_client); diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index e017039a6..ab2b4f966 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -414,7 +414,7 @@ static qboolean SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) { float solid_save; - int num_moved, i, e; + int num_moved, i; edict_t *check, *block; edict_t **moved_edict; vec3_t move, org, org2; @@ -455,7 +455,7 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (e = 1; e < sv.num_edicts; + for (unsigned e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, check)) { if (check->free) continue; @@ -854,14 +854,14 @@ void SV_Physics (void) { edict_t *ent; - int i; SV_ProgStartFrame (); // treat each object in turn // even the world gets a chance to think ent = sv.edicts; - for (i = 0; i < sv.num_edicts; i++, ent = NEXT_EDICT (&sv_pr_state, ent)) { + for (unsigned i = 0; i < sv.num_edicts; + i++, ent = NEXT_EDICT (&sv_pr_state, ent)) { if (ent->free) continue; diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 8f2262078..71a6d03f3 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -304,7 +304,7 @@ PF_sprint (progs_t *pr) { const char *s; client_t *client; - int entnum; + unsigned entnum; entnum = P_EDICTNUM (pr, 0); s = PF_VarString (pr, 1); @@ -333,7 +333,7 @@ PF_centerprint (progs_t *pr) { const char *s; client_t *cl; - int entnum; + unsigned entnum; entnum = P_EDICTNUM (pr, 0); s = PF_VarString (pr, 1); @@ -542,11 +542,11 @@ PF_checkpos (progs_t *pr) static set_t *checkpvs; -static int -PF_newcheckclient (progs_t *pr, int check) +static unsigned +PF_newcheckclient (progs_t *pr, unsigned check) { edict_t *ent; - int i; + unsigned i; mleaf_t *leaf; vec3_t org; @@ -656,7 +656,7 @@ PF_stuffcmd (progs_t *pr) { const char *str; client_t *old; - int entnum; + pr_uint_t entnum; entnum = P_EDICTNUM (pr, 0); if (entnum < 1 || entnum > svs.maxclients) @@ -700,7 +700,7 @@ PF_findradius (progs_t *pr) edict_t *ent, *chain; float rsqr; vec_t *emins, *emaxs, *org; - int i, j; + pr_uint_t i; vec3_t eorg; chain = (edict_t *) sv.edicts; @@ -717,7 +717,7 @@ PF_findradius (progs_t *pr) continue; emins = SVvector (ent, absmin); emaxs = SVvector (ent, absmax); - for (j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) eorg[j] = org[j] - 0.5 * (emins[j] + emaxs[j]); if (DotProduct (eorg, eorg) > rsqr) continue; @@ -903,7 +903,8 @@ PF_lightstyle (progs_t *pr) { const char *val; client_t *cl; - int style, j; + int style; + unsigned j; style = P_FLOAT (pr, 0); val = P_GSTRING (pr, 1); @@ -960,7 +961,7 @@ PF_aim (progs_t *pr) edict_t *ent, *check, *bestent; float dist, bestdist, speed; float *mins, *maxs, *org; - int i, j; + pr_uint_t i; trace_t tr; vec3_t start, dir, end, bestdir; @@ -1000,7 +1001,7 @@ PF_aim (progs_t *pr) mins = SVvector (check, mins); maxs = SVvector (check, maxs); org = SVvector (check, origin); - for (j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) end[j] = org[j] + 0.5 * (mins[j] + maxs[j]); VectorSubtract (end, start, dir); VectorNormalize (dir); @@ -1075,7 +1076,7 @@ PF_changeyaw (progs_t *pr) static __attribute__((pure)) sizebuf_t * WriteDest (progs_t *pr) { - int entnum; + pr_uint_t entnum; int dest; edict_t *ent; @@ -1256,7 +1257,7 @@ PF_setspawnparms (progs_t *pr) { client_t *client; edict_t *ent; - int i; + unsigned i; ent = P_EDICT (pr, 0); i = NUM_FOR_EDICT (pr, ent); diff --git a/nq/source/sv_user.c b/nq/source/sv_user.c index 0475efc0a..87623e7d6 100644 --- a/nq/source/sv_user.c +++ b/nq/source/sv_user.c @@ -584,7 +584,7 @@ SV_ReadClientMessage (void) void SV_RunClients (void) { - int i; + unsigned i; for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++) { diff --git a/nq/source/world.c b/nq/source/world.c index 5f8bce898..a73e7c498 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -780,11 +780,10 @@ SV_ClipToLinks (areanode_t *node, moveclip_t *clip) edict_t *touch; link_t *l, *next; trace_t trace; - int i; if (clip->type == TL_EVERYTHING) { touch = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (i = 1; i < sv.num_edicts; i++, + for (unsigned i = 1; i < sv.num_edicts; i++, touch = NEXT_EDICT (&sv_pr_state, touch)) { if (clip->trace.allsolid) return; @@ -897,7 +896,6 @@ SV_Move (const vec3_t start, const vec3_t mins, const vec3_t maxs, edict_t * SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) { - int e; edict_t *check; hull_t *hull; vec3_t boxmins, boxmaxs, offset; @@ -912,8 +910,8 @@ SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) VectorAdd (origin, SVvector (ent, maxs), boxmaxs); check = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, - check)) { + for (unsigned e = 1; e < sv.num_edicts; + e++, check = NEXT_EDICT (&sv_pr_state, check)) { if (check->free) continue; if (check == ent) diff --git a/qw/include/server.h b/qw/include/server.h index ebe9cf2ce..bd7fb8062 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -81,7 +81,7 @@ typedef struct { const char *lightstyles[MAX_LIGHTSTYLES]; struct model_s *models[MAX_MODELS]; - int num_edicts; // increases towards MAX_EDICTS + unsigned num_edicts; // increases towards MAX_EDICTS struct edict_s *edicts; // can NOT be array indexed, because // struct edict_s is variable sized, but can // be used to reference the world ent @@ -304,8 +304,8 @@ typedef struct { int spawncount; // number of servers spawned since start, // used to check late spawns client_t clients[MAX_CLIENTS]; - int maxclients; - int num_clients; + unsigned maxclients; + unsigned num_clients; int serverflags; // episode completion information void (*phys_client) (struct edict_s *ent, int num); diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index 88fe18c24..d0c04e2e0 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -38,12 +38,12 @@ #include "sv_pr_cmds.h" typedef struct { - pr_int_t *self; - pr_int_t *other; - pr_int_t *world; + pr_uint_t *self; + pr_uint_t *other; + pr_uint_t *world; float *time; float *frametime; - pr_int_t *newmis; + pr_uint_t *newmis; float *force_retouch; string_t *mapname; float *serverflags; @@ -61,10 +61,10 @@ typedef struct { vec3_t *trace_endpos; vec3_t *trace_plane_normal; float *trace_plane_dist; - pr_int_t *trace_ent; + pr_uint_t *trace_ent; float *trace_inopen; float *trace_inwater; - pr_int_t *msg_entity; + pr_uint_t *msg_entity; float *skill; } sv_globals_t; diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 30a0a12d2..929cd4853 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -122,11 +122,8 @@ SV_FlushSignon (void) static void SV_CreateBaseline (void) { - int entnum; - edict_t *svent; - - for (entnum = 0; entnum < sv.num_edicts; entnum++) { - svent = EDICT_NUM (&sv_pr_state, entnum); + for (unsigned entnum = 0; entnum < sv.num_edicts; entnum++) { + edict_t *svent = EDICT_NUM (&sv_pr_state, entnum); if (svent->free) continue; // create baselines for all player slots, diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index 79047699e..856a5ef16 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -417,7 +417,7 @@ static qboolean SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) { float solid_save; - int num_moved, i, e; + int num_moved, i; edict_t *check, *block; edict_t **moved_edict; vec3_t move, org, org2; @@ -458,7 +458,7 @@ SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) // see if any solid entities are inside the final position num_moved = 0; check = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (e = 1; e < sv.num_edicts; + for (unsigned e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, check)) { if (check->free) continue; @@ -862,14 +862,14 @@ void SV_Physics (void) { edict_t *ent; - int i; SV_ProgStartFrame (); // treat each object in turn // even the world gets a chance to think ent = sv.edicts; - for (i = 0; i < sv.num_edicts; i++, ent = NEXT_EDICT (&sv_pr_state, ent)) { + for (unsigned i = 0; i < sv.num_edicts; + i++, ent = NEXT_EDICT (&sv_pr_state, ent)) { if (ent->free) continue; diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 2e1144780..1431729ee 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -653,7 +653,6 @@ PF_findradius (progs_t *pr) edict_t *ent, *chain; float rsqr; vec_t *emins, *emaxs, *org; - int i, j; vec3_t eorg; chain = (edict_t *) sv.edicts; @@ -663,7 +662,7 @@ PF_findradius (progs_t *pr) rsqr *= rsqr; // Square early, sqrt never ent = NEXT_EDICT (pr, sv.edicts); - for (i = 1; i < sv.num_edicts; i++, ent = NEXT_EDICT (pr, ent)) { + for (unsigned i = 1; i < sv.num_edicts; i++, ent = NEXT_EDICT (pr, ent)) { if (ent->free) continue; if (SVfloat (ent, solid) == SOLID_NOT @@ -671,7 +670,7 @@ PF_findradius (progs_t *pr) continue; emins = SVvector (ent, absmin); emaxs = SVvector (ent, absmax); - for (j = 0; j < 3; j++) + for (int j = 0; j < 3; j++) eorg[j] = org[j] - 0.5 * (emins[j] + emaxs[j]); if (DotProduct (eorg, eorg) > rsqr) continue; @@ -936,7 +935,7 @@ PF_aim (progs_t *pr) edict_t *ent, *check, *bestent; float dist, bestdist, speed; float *mins, *maxs, *org; - int i, j; + unsigned i, j; trace_t tr; vec3_t start, dir, end, bestdir; diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 6351317e8..87b871ec9 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -65,7 +65,7 @@ cvar_t *pr_checkextensions; cvar_t *sv_old_entity_free; cvar_t *sv_hide_version_info; -static int reserved_edicts = MAX_CLIENTS; +static pr_uint_t reserved_edicts = MAX_CLIENTS; static int sv_range; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index e73835a39..490127b33 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -491,16 +491,13 @@ SV_Spawn_f (void *unused) static void SV_SpawnSpectator (void) { - int i; - edict_t *e; - VectorZero (SVvector (sv_player, origin)); VectorZero (SVvector (sv_player, view_ofs)); SVvector (sv_player, view_ofs)[2] = 22; // search for an info_playerstart to spawn the spectator at - for (i = MAX_CLIENTS - 1; i < sv.num_edicts; i++) { - e = EDICT_NUM (&sv_pr_state, i); + for (unsigned i = MAX_CLIENTS - 1; i < sv.num_edicts; i++) { + edict_t *e = EDICT_NUM (&sv_pr_state, i); if (!strcmp (PR_GetString (&sv_pr_state, SVstring (e, classname)), "info_player_start")) { VectorCopy (SVvector (e, origin), SVvector (sv_player, origin)); @@ -1516,7 +1513,7 @@ static void AddLinksToPmove (areanode_t *node) { edict_t *check; - int pl, i; + pr_uint_t pl, i; link_t *l, *next; physent_t *pe; diff --git a/qw/source/world.c b/qw/source/world.c index 393daaf6f..877db0f38 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -818,11 +818,10 @@ SV_ClipToLinks (areanode_t *node, moveclip_t *clip) edict_t *touch; link_t *l, *next; trace_t trace; - int i; if (clip->type & MOVE_EVERYTHING) { touch = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (i = 1; i < sv.num_edicts; i++, + for (unsigned i = 1; i < sv.num_edicts; i++, touch = NEXT_EDICT (&sv_pr_state, touch)) { if (clip->trace.allsolid) return; @@ -985,7 +984,6 @@ SV_Move (const vec3_t start, const vec3_t mins, const vec3_t maxs, edict_t * SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) { - int e; edict_t *check; hull_t *hull; vec3_t boxmins, boxmaxs, offset; @@ -1000,8 +998,8 @@ SV_TestPlayerPosition (edict_t *ent, const vec3_t origin) VectorAdd (origin, SVvector (ent, maxs), boxmaxs); check = NEXT_EDICT (&sv_pr_state, sv.edicts); - for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, - check)) { + for (unsigned e = 1; e < sv.num_edicts; + e++, check = NEXT_EDICT (&sv_pr_state, check)) { if (check->free) continue; if (check == ent) diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 19c7ed873..1d60336a4 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -126,8 +126,8 @@ static const char *short_options = ; static edict_t *edicts; -static int num_edicts; -static int reserved_edicts = 1; +static pr_uint_t num_edicts; +static pr_uint_t reserved_edicts = 1; static progs_t pr; static qfo_t *qfo; diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 5b0199317..42b6a9935 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -75,8 +75,8 @@ static const char *short_options = static edict_t test_edicts[MAX_EDICTS]; static edict_t *edicts; -static int num_edicts; -static int reserved_edicts; +static pr_uint_t num_edicts; +static pr_uint_t reserved_edicts; static progs_t test_pr; static const char *this_program; From 1397c94ef54c4a4ee98594df02cf80d769ed662a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Jan 2022 22:17:17 +0900 Subject: [PATCH 2192/3664] [gamecode] Add tests for the state instructions --- libs/gamecode/test/Makemodule.am | 5 ++ libs/gamecode/test/head.c | 10 ++++ libs/gamecode/test/main.c | 14 +++++ libs/gamecode/test/test-state.c | 99 ++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 libs/gamecode/test/test-state.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index d63023468..e0d60336d 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -18,6 +18,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-mem \ libs/gamecode/test/test-scale \ libs/gamecode/test/test-stack \ + libs/gamecode/test/test-state \ libs/gamecode/test/test-store \ libs/gamecode/test/test-string \ libs/gamecode/test/test-swizzle \ @@ -130,6 +131,10 @@ libs_gamecode_test_test_stack_SOURCES= \ libs_gamecode_test_test_stack_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_stack_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_state_SOURCES= \ + libs/gamecode/test/test-state.c +libs_gamecode_test_test_state_LDADD= $(test_gamecode_libs) + libs_gamecode_test_test_store_SOURCES= \ libs/gamecode/test/test-store.c libs_gamecode_test_test_store_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/head.c b/libs/gamecode/test/head.c index 478a74f09..9116bb695 100644 --- a/libs/gamecode/test/head.c +++ b/libs/gamecode/test/head.c @@ -36,4 +36,14 @@ typedef struct { pr_int_t *expect_globals; const char *strings; pr_uint_t string_size; + // pointers/globals for state + double *double_time; + pr_uint_t dtime; + float *float_time; + pr_uint_t ftime; + pr_uint_t self; + // fields for state + pr_uint_t think; + pr_uint_t nextthink; + pr_uint_t frame; } test_t; diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 8f433225c..ddae815dd 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -108,6 +108,20 @@ setup_test (test_t *test) if (test->edict_area) { test_pr.pr_edict_area = test_pr.pr_globals + test->edict_area; } + if (test->double_time || test->float_time) { + test_pr.fields.nextthink = test->nextthink; + test_pr.fields.frame = test->frame; + test_pr.fields.think = test->think; + test_pr.globals.self = (pr_uint_t *) &test_pr.pr_globals[test->self]; + if (test->double_time) { + test_pr.globals.dtime = (double *)&test_pr.pr_globals[test->dtime]; + *test_pr.globals.dtime = *test->double_time; + } + if (test->float_time) { + test_pr.globals.ftime = (float *) &test_pr.pr_globals[test->ftime]; + *test_pr.globals.ftime = *test->float_time; + } + } test_progs.numstatements = test->num_statements + 1; test_pr.pr_statements diff --git a/libs/gamecode/test/test-state.c b/libs/gamecode/test/test-state.c new file mode 100644 index 000000000..f7a45076d --- /dev/null +++ b/libs/gamecode/test/test-state.c @@ -0,0 +1,99 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define DB 0xdeadbeef + +static float float_time = 1; + +static pr_ivec4_t float_state_init[] = { + { 0, 0, DB, DB }, + { 10, 11, 20, 21 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +#define f1 0x3f800000 +#define f11 0x3f8ccccd +#define f2 0x40000000 +static pr_ivec4_t float_state_expect[] = { + { 0, 8, f1, DB }, + { 10, 11, 20, 21 }, + { 0, 0, 0, 0 }, + { 10, 20, f11, 0 }, + { 11, 21, f2, 0 }, +}; + +static dstatement_t float_state_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 1 }, + { OP(0, 0, 0, OP_STATE_ft), 4, 6, 0 }, + { OP(0, 0, 0, OP_LEA_A), 8, 0, 1 }, + { OP(0, 0, 0, OP_STATE_ftt), 5, 7, 2 }, +}; + +static double double_time = 1; + +static pr_ivec4_t double_state_init[] = { + { 0, 0, DB, DB }, + { 10, 11, 20, 21 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, + { 0, 0, 0, 0 }, +}; + +#define d1l 0x00000000 +#define d1h 0x3ff00000 +#define d11l 0x9999999a +#define d11h 0x3ff19999 +#define d2l 0x00000000 +#define d2h 0x40000000 +static pr_ivec4_t double_state_expect[] = { + { 0, 8, d1l, d1h }, + { 10, 11, 20, 21 }, + { 0, 0, 0, 0 }, + { 10, 20, d11l, d11h }, + { 11, 21, d2l, d2h }, +}; + +static dstatement_t double_state_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 1 }, + { OP(0, 0, 0, OP_STATE_dt), 4, 6, 0 }, + { OP(0, 0, 0, OP_LEA_A), 8, 0, 1 }, + { OP(0, 0, 0, OP_STATE_dtt), 5, 7, 2 }, +}; + +test_t tests[] = { + { + .desc = "float state", + .num_globals = num_globals(float_state_init,float_state_expect), + .num_statements = num_statements (float_state_statements), + .statements = float_state_statements, + .init_globals = (pr_int_t *) float_state_init, + .expect_globals = (pr_int_t *) float_state_expect, + .self = 1, + .ftime = 2, + .float_time = &float_time, + .edict_area = 8, + .frame = 0, + .think = 1, + .nextthink = 2, + }, + { + .desc = "double state", + .num_globals = num_globals(double_state_init,double_state_expect), + .num_statements = num_statements (double_state_statements), + .statements = double_state_statements, + .init_globals = (pr_int_t *) double_state_init, + .expect_globals = (pr_int_t *) double_state_expect, + .self = 1, + .dtime = 2, + .double_time = &double_time, + .edict_area = 8, + .frame = 0, + .think = 1, + .nextthink = 2, + }, +}; + +#include "main.c" From 1baf17b780a9dca371f1955f07da038d80f407d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 09:34:16 +0900 Subject: [PATCH 2193/3664] [gamecode] Add tests for the jump instructions --- libs/gamecode/test/Makemodule.am | 6 +++ libs/gamecode/test/test-jump.c | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 libs/gamecode/test/test-jump.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index e0d60336d..9a5b9bf04 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -12,6 +12,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-float \ libs/gamecode/test/test-hops \ libs/gamecode/test/test-int \ + libs/gamecode/test/test-jump \ libs/gamecode/test/test-lea \ libs/gamecode/test/test-load \ libs/gamecode/test/test-long \ @@ -101,6 +102,11 @@ libs_gamecode_test_test_int_SOURCES= \ libs_gamecode_test_test_int_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_int_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_jump_SOURCES= \ + libs/gamecode/test/test-jump.c +libs_gamecode_test_test_jump_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_jump_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_lea_SOURCES= \ libs/gamecode/test/test-lea.c libs_gamecode_test_test_lea_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-jump.c b/libs/gamecode/test/test-jump.c new file mode 100644 index 000000000..59e40554d --- /dev/null +++ b/libs/gamecode/test/test-jump.c @@ -0,0 +1,77 @@ +#include "head.c" + +#define DB 0xdeadbeef + +static pr_int_t test_globals_init[] = { + DB, 1, 2, 3, DB, +}; + +static pr_int_t test_globals_expect[] = { + DB, 1, 2, 3, 1, +}; + +static dstatement_t jump_A_statements[] = { + { OP(0, 0, 0, OP_JUMP_A), 4, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 4 }, + { OP(0, 0, 0, OP_JUMP_A), 2, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -2, 0, 0 }, +}; + +static dstatement_t jump_B_statements[] = { + { OP(0, 0, 0, OP_JUMP_B), 3, 0, 0 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 4 }, +}; + +static dstatement_t jump_C_statements[] = { + { OP(0, 0, 0, OP_JUMP_C), 1, 2, 0 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 4 }, +}; + +static dstatement_t jump_D_statements[] = { + { OP(0, 0, 0, OP_JUMP_D), 1, 2, 0 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 0 }, + { OP(0, 0, 0, OP_LEA_A), 1, 0, 4 }, +}; + +test_t tests[] = { + { + .desc = "jump A", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (jump_A_statements), + .statements = jump_A_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "jump B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (jump_B_statements), + .statements = jump_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "jump C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (jump_C_statements), + .statements = jump_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "jump D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (jump_D_statements), + .statements = jump_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" From 1beadbf871244917a4b875bc3c91b4a22c78d6e0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 09:57:54 +0900 Subject: [PATCH 2194/3664] [gamecode] Add tests for the branch instructions --- libs/gamecode/test/Makemodule.am | 6 + libs/gamecode/test/test-branch.c | 193 +++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 libs/gamecode/test/test-branch.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 9a5b9bf04..b70014d48 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,4 +1,5 @@ libs_gamecode_tests = \ + libs/gamecode/test/test-branch \ libs/gamecode/test/test-bitops \ libs/gamecode/test/test-conv0 \ libs/gamecode/test/test-conv1 \ @@ -37,6 +38,11 @@ test_gamecode_libs= \ libs/gamecode/libQFgamecode.la \ libs/util/libQFutil.la +libs_gamecode_test_test_branch_SOURCES= \ + libs/gamecode/test/test-branch.c +libs_gamecode_test_test_branch_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_branch_DEPENDENCIES=$(test_gamecode_libs) + libs_gamecode_test_test_bitops_SOURCES= \ libs/gamecode/test/test-bitops.c libs_gamecode_test_test_bitops_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-branch.c b/libs/gamecode/test/test-branch.c new file mode 100644 index 000000000..e02f229ba --- /dev/null +++ b/libs/gamecode/test/test-branch.c @@ -0,0 +1,193 @@ +#include "head.c" + +#define DB 0xdeadbeef + +static pr_int_t test_globals_init[] = { + -1, 1, 0, DB, DB, +}; + +static pr_int_t test_globals_expect[] = { + -1, 1, 0, DB, 1, +}; + +static dstatement_t ifz_taken_statements[] = { + { OP_IFZ, 4, 0, 2 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFZ, -2, 0, 2 }, +}; + +static dstatement_t ifb_taken_statements[] = { + { OP_IFB, 4, 0, 0 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFB, -2, 0, 0 }, +}; + +static dstatement_t ifa_taken_statements[] = { + { OP_IFA, 4, 0, 1 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFA, -2, 0, 1 }, +}; + +static dstatement_t ifnz_taken_statements[] = { + { OP_IFNZ, 4, 0, 0 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFNZ, -2, 0, 1 }, +}; + +static dstatement_t ifae_taken_statements[] = { + { OP_IFAE, 4, 0, 1 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFAE, -2, 0, 2 }, +}; + +static dstatement_t ifbe_taken_statements[] = { + { OP_IFBE, 4, 0, 0 }, + { OP_LEA_A, 1, 0, 3 }, + { OP_LEA_A, 1, 0, 4 }, + { OP_BREAK }, + { OP_IFBE, -2, 0, 2 }, +}; + +static dstatement_t ifz_not_taken_statements[] = { + { OP_IFZ, 3, 0, 0 }, + { OP_IFZ, 2, 0, 1 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifb_not_taken_statements[] = { + { OP_IFB, 3, 0, 2 }, + { OP_IFB, 2, 0, 1 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifa_not_taken_statements[] = { + { OP_IFA, 3, 0, 2 }, + { OP_IFA, 2, 0, 0 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifnz_not_taken_statements[] = { + { OP_IFNZ, 3, 0, 2 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifae_not_taken_statements[] = { + { OP_IFAE, 2, 0, 0 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +static dstatement_t ifbe_not_taken_statements[] = { + { OP_IFBE, 2, 0, 1 }, + { OP_LEA_A, 1, 0, 4 }, +}; + +test_t tests[] = { + { + .desc = "ifz taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifz_taken_statements), + .statements = ifz_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifb taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifb_taken_statements), + .statements = ifb_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifa taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifa_taken_statements), + .statements = ifa_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifnz taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifnz_taken_statements), + .statements = ifnz_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifae taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifae_taken_statements), + .statements = ifae_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifbe taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifbe_taken_statements), + .statements = ifbe_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifz not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifz_not_taken_statements), + .statements = ifz_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifb not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifb_not_taken_statements), + .statements = ifb_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifa not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifa_not_taken_statements), + .statements = ifa_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifnz not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifnz_not_taken_statements), + .statements = ifnz_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifae not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifae_not_taken_statements), + .statements = ifae_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "ifbe not taken", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (ifbe_not_taken_statements), + .statements = ifbe_not_taken_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" From 56d8bdee825b4febc51d11bb82b8bc492cc2d008 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 10:32:19 +0900 Subject: [PATCH 2195/3664] [gamecode] Add a fixme about using gcc's vec convert It might produce better code than the way I'm currently doing it. --- libs/gamecode/convert.py | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index 0474fbd8f..333846c66 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -52,6 +52,7 @@ def case_str(width, src_type, dst_type): case = (width << 6) | (src_type << 3) | (dst_type) return f"case {case:04o}:" +#FIXME look into using gcc's __builtin_convertvector def cast_str(width, src_type, dst_type): if width & 1: return f"(pr_{vec_types[dst_type]}{width+1}_t)" From b3909dbe4c473aee202c2462f32f849801f665c0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 14:26:12 +0900 Subject: [PATCH 2196/3664] [gamecode] Add a test for call and return It currently fails for two reasons: - call's mode selection is incorrect (never updated from when there was only the one call instruction and the mode was encoded in operand c) - return should automatically restore the stack pointer to the value it had on entry to the function, thus allowing local values stored on the stack to be safely returned. --- libs/gamecode/test/Makemodule.am | 6 ++ libs/gamecode/test/head.c | 5 ++ libs/gamecode/test/main.c | 14 ++++- libs/gamecode/test/test-callret.c | 96 +++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 libs/gamecode/test/test-callret.c diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index b70014d48..1fd3353bf 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -1,6 +1,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-branch \ libs/gamecode/test/test-bitops \ + libs/gamecode/test/test-callret \ libs/gamecode/test/test-conv0 \ libs/gamecode/test/test-conv1 \ libs/gamecode/test/test-conv2 \ @@ -48,6 +49,11 @@ libs_gamecode_test_test_bitops_SOURCES= \ libs_gamecode_test_test_bitops_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_bitops_DEPENDENCIES=$(test_gamecode_libs) +libs_gamecode_test_test_callret_SOURCES= \ + libs/gamecode/test/test-callret.c +libs_gamecode_test_test_callret_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_callret_DEPENDENCIES=$(test_gamecode_libs) + libs_gamecode_test_test_conv0_SOURCES= \ libs/gamecode/test/test-conv0.c libs_gamecode_test_test_conv0_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/head.c b/libs/gamecode/test/head.c index 9116bb695..07921d847 100644 --- a/libs/gamecode/test/head.c +++ b/libs/gamecode/test/head.c @@ -21,6 +21,9 @@ static int verbose = 0; #define num_statements(statements) \ (sizeof (statements) / sizeof (statements[0])) +#define num_functions(functions) \ + (sizeof (functions) / sizeof (functions[0])) + #define BASE(b, base) (((base) & 3) << OP_##b##_SHIFT) #define OP(a, b, c, op) ((op) | BASE(A, a) | BASE(B, b) | BASE(C, c)) @@ -46,4 +49,6 @@ typedef struct { pr_uint_t think; pr_uint_t nextthink; pr_uint_t frame; + bfunction_t *functions; + pr_uint_t num_functions; } test_t; diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index ddae815dd..7a565dece 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -88,7 +88,16 @@ setup_test (test_t *test) test_pr.debug_data = &test_pr; test_pr.pr_trace = 1; test_pr.pr_trace_depth = -1; - test_pr.function_table = test_functions; + if (test->num_functions && test->functions) { + test_pr.function_table = calloc ((test->num_functions + 2), + sizeof (bfunction_t)); + memcpy (test_pr.function_table, test_functions, + 2 * sizeof (bfunction_t)); + memcpy (test_pr.function_table + 2, test->functions, + test->num_functions * sizeof (bfunction_t)); + } else { + test_pr.function_table = test_functions; + } pr_uint_t num_globals = test->num_globals; num_globals += test->extra_globals + test->stack_size; @@ -170,6 +179,9 @@ run_test (test_t *test) pr_uint_t num_globals = test->num_globals; num_globals += test->extra_globals + test->stack_size; + if (test->num_functions && test->functions) { + free (test_pr.function_table); + } Sys_Free (test_pr.pr_globals, num_globals * sizeof (pr_type_t)); free (test_pr.pr_statements); diff --git a/libs/gamecode/test/test-callret.c b/libs/gamecode/test/test-callret.c new file mode 100644 index 000000000..988f27936 --- /dev/null +++ b/libs/gamecode/test/test-callret.c @@ -0,0 +1,96 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define sq(x) ((float)(x)*(float)(x)) +#define pi_6 0x3f060a92 // pi/6 +#define r3_2 0x3f5db3d7 // sqrt(3)/2 +#define f1_2 0x3f000000 // 1/2 +#define f1 0x3f800000 // 1 +#define f2 0x40000000 // 2 +#define shx 0x3f0c4020 // sinh(pi/6) +#define chx 0x3f91f354 // cosh(pi/6) + +#define STK (32 * 4) // stack ptr just after globals + +static pr_ivec4_t float_callret_init[32] = { + { 0, pi_6, 2, 0}, + { f1, f2, 0, 0}, +}; + +static pr_ivec4_t float_callret_expect[32] = { + // constants + { 0, pi_6, 2, 0}, + { f1, f2, 0, 0}, + // result + { r3_2, f1_2, chx, shx }, +}; + +static dstatement_t float_callret_statements[] = { + { OP_STORE_A_1, 7, 0, STK }, // save stack pointer for check + { OP_PUSH_A_1, 1, 0, 0 }, + { OP_CALL_B, 2, 0, 8 }, + { OP_LEA_C, STK, 4, STK }, // discard param + { OP_SUB_I_1, 7, STK, 7 }, // check stack restored + { OP_BREAK }, +// cos_sin_cosh_sinh: +// calculate cos(x), sin(x), cosh(x) and sinh(x) simultaneously + { OP_WITH, 2, 0, 1 }, // put params into reg 1 + { OP_LEA_C, STK, -24, STK }, // reserve 24 words on the stack + { OP_WITH, 2, 0, 2 }, // put locals into reg 2 +#define x 0 // in parameters float +#define xn 0 // in locals vec4 +#define x2 4 // in locals vec4 +#define ac 8 // in locals vec4 +#define fa 12 // in locals vec4 +#define fi 16 // in locals vec4 +#define c 20 // in locals int + { OP(2, 0, 1, OP_STORE_A_1), xn+1,0, x }, // init xn to [1, x, 0, 0] + { OP(2, 0, 0, OP_STORE_A_1), xn, 0, 4 }, + { OP(2, 0, 2, OP_SWIZZLE_F), xn, 0x0044, xn }, // xn -> [1, x, 1, x] + { OP(1, 1, 2, OP_MUL_F_1), x, x, x2 }, // x2 -> [x*x, 0, 0, 0] + { OP(2, 0, 2, OP_SWIZZLE_F), x2, 0x0300, x2},//x2 -> [-x*x, -x*x, x*x, x*x] + { OP(2, 0, 0, OP_STORE_A_1), fa, 0, 4 }, // init factorial + { OP(2, 0, 0, OP_STORE_A_1), fa+1,0, 5 }, + { OP(2, 0, 2, OP_SWIZZLE_F), fa, 0x0044, fa }, // fa -> [1, 2, 1, 2] + { OP(0, 0, 2, OP_SWIZZLE_F), 4, 0x0000, fi }, // init fi -> [1, 1, 1, 1] + { OP(2, 2, 2, OP_SUB_F_4), ac, ac, ac }, // init acc (output) to 0 + { OP(0, 0, 2, OP_LEA_A), 25, 0, c }, // init count +// loop: + { OP(2, 2, 2, OP_ADD_F_4), ac, xn, ac }, // acc += xn + { OP(2, 2, 2, OP_MUL_F_4), xn, x2, xn }, // xn *= x2 + { OP(2, 2, 2, OP_DIV_F_4), xn, fa, xn }, // xn /= f + { OP(2, 2, 2, OP_ADD_F_4), fa, fi, fa }, // f += inc + { OP(2, 2, 2, OP_DIV_F_4), xn, fa, xn }, // xn /= f + { OP(2, 2, 2, OP_ADD_F_4), fa, fi, fa }, // f += inc + { OP(2, 0, 2, OP_LEA_C), c, -1, c }, // dec count + { OP(0, 0, 2, OP_IFA), -7, 0, c }, // count > 0 + { OP(2, 0, 0, OP_RETURN), ac, 0, 4 }, +}; +#undef x +#undef xn +#undef x2 +#undef ac +#undef fa +#undef fi +#undef c + +static bfunction_t callret_functions[] = { + { .first_statement = 6 }, +}; + +test_t tests[] = { + { + .desc = "callret", + .num_globals = num_globals(float_callret_init,float_callret_expect), + .num_statements = num_statements (float_callret_statements), + .statements = float_callret_statements, + .init_globals = (pr_int_t *) float_callret_init, + .expect_globals = (pr_int_t *) float_callret_expect, + .functions = callret_functions, + .num_functions = num_functions(callret_functions), + .stack_size = 128, + }, +}; + +#include "main.c" From cf3106ce28c92b85d4bbc590968e022eafd7ea05 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 14:29:14 +0900 Subject: [PATCH 2197/3664] [gamecode] Correct call's mode selection Call's operand c is used to specify where the return value of the function is to be stored. This gets both the correct function being called, and the value being returned correctly. Test still fails due to the stack restoration issue. --- libs/gamecode/pr_exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index adf9cf515..d2f55dbd7 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3141,7 +3141,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_CALL_B: case OP_CALL_C: case OP_CALL_D: - mm = pr_call_mode (pr, st, st->c & 3); + mm = pr_call_mode (pr, st, st_op - OP_CALL_B + 1); function = mm->func_var; pr->pr_argc = 0; // op_c specifies the location for the return value if any From 8e5c2c65348e46e9f40bd6b2e0ce5119239fffde Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 14:43:43 +0900 Subject: [PATCH 2198/3664] [gamecode] Correct type of return address in stack This is another one of those "why signed?" things: can't have negative return addresses. --- include/QF/progs.h | 2 +- libs/gamecode/pr_debug.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index e8b4136dc..55ac37b69 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1801,7 +1801,7 @@ extern const char *pr_gametype; typedef struct strref_s strref_t; typedef struct { - pr_int_t staddr; ///< Return statement. + pr_uint_t staddr; ///< Return statement. bfunction_t *func; ///< Calling function. strref_t *tstr; ///< Linked list of temporary strings. } prstack_t; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 1034c7b95..e4268eef5 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1721,7 +1721,7 @@ dump_frame (progs_t *pr, prstack_t *frame) pr_lineno_t *lineno = PR_Find_Lineno (pr, frame->staddr); pr_auxfunction_t *func = PR_Get_Lineno_Func (pr, lineno); pr_uint_t line = PR_Get_Lineno_Line (pr, lineno); - pr_int_t addr = PR_Get_Lineno_Addr (pr, lineno); + pr_uint_t addr = PR_Get_Lineno_Addr (pr, lineno); line += func->source_line; if (addr == frame->staddr) { From 213434b7054d3f4991a52ea0b4346a7c15d94aec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 14:45:14 +0900 Subject: [PATCH 2199/3664] [gamecode] Save and restore data stack in call stack This fixes the issue of the data stack not being restored properly because the returning function needs to return a value from its local variables (stored on the stack) and accessing stack data below the stack pointer is a bad idea (sure, no interrupts yet, but who knows...). --- include/QF/progs.h | 1 + libs/gamecode/pr_exec.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 55ac37b69..1597c97df 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1802,6 +1802,7 @@ typedef struct strref_s strref_t; typedef struct { pr_uint_t staddr; ///< Return statement. + pr_uint_t stack_ptr; ///< data stack on entry to function bfunction_t *func; ///< Calling function. strref_t *tstr; ///< Linked list of temporary strings. } prstack_t; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index d2f55dbd7..cf01b0e8a 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -143,6 +143,9 @@ PR_PushFrame (progs_t *pr) frame = pr->pr_stack + pr->pr_depth++; frame->staddr = pr->pr_xstatement; + if (pr->globals.stack) { + frame->stack_ptr = *pr->globals.stack; + } frame->func = pr->pr_xfunction; frame->tstr = pr->pr_xtstr; @@ -179,6 +182,10 @@ PR_PopFrame (progs_t *pr) pr->pr_xfunction = frame->func; pr->pr_xstatement = frame->staddr; pr->pr_xtstr = frame->tstr; + // restore data stack (discard any locals) + if (pr->globals.stack) { + *pr->globals.stack = frame->stack_ptr; + } } static __attribute__((pure)) long From 8da1163a82247bc580c24f57a77a21d805c55230 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 14:59:17 +0900 Subject: [PATCH 2200/3664] [gamecode] Add bases check to callret test The base registers must be preserved across a function call and they currently are not, thus the updated test fails again. --- libs/gamecode/test/test-callret.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/test/test-callret.c b/libs/gamecode/test/test-callret.c index 988f27936..269ff61a9 100644 --- a/libs/gamecode/test/test-callret.c +++ b/libs/gamecode/test/test-callret.c @@ -11,27 +11,46 @@ #define shx 0x3f0c4020 // sinh(pi/6) #define chx 0x3f91f354 // cosh(pi/6) +#define DB 0xdeadbeef + #define STK (32 * 4) // stack ptr just after globals static pr_ivec4_t float_callret_init[32] = { - { 0, pi_6, 2, 0}, - { f1, f2, 0, 0}, + { 0, pi_6, 2, 0}, + { f1, f2, 0, 0}, + // result + { DB, DB, DB, DB }, + // pre-call with + { DB, DB, DB, DB }, + // post-call with + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, }; static pr_ivec4_t float_callret_expect[32] = { // constants - { 0, pi_6, 2, 0}, - { f1, f2, 0, 0}, + { 0, pi_6, 2, 0 }, + { f1, f2, 0, 0 }, // result { r3_2, f1_2, chx, shx }, + // pre-call with: should be all 0 on progs init + { 0, 0, 0, 0 }, + // post-call with; should be restored to pre-call values (in this case, + // progs init) + { 0, 0, 0, 0 }, + { DB, DB, DB, DB }, }; static dstatement_t float_callret_statements[] = { + { OP_WITH, 8, 0, 0 }, // pushregs + { OP_POP_A_4, 12, 0, 0 }, { OP_STORE_A_1, 7, 0, STK }, // save stack pointer for check { OP_PUSH_A_1, 1, 0, 0 }, { OP_CALL_B, 2, 0, 8 }, { OP_LEA_C, STK, 4, STK }, // discard param { OP_SUB_I_1, 7, STK, 7 }, // check stack restored + { OP_WITH, 8, 0, 0 }, // pushregs + { OP_POP_A_4, 16, 0, 0 }, { OP_BREAK }, // cos_sin_cosh_sinh: // calculate cos(x), sin(x), cosh(x) and sinh(x) simultaneously @@ -76,7 +95,7 @@ static dstatement_t float_callret_statements[] = { #undef c static bfunction_t callret_functions[] = { - { .first_statement = 6 }, + { .first_statement = 10 }, }; test_t tests[] = { From 736387bc888331b9c044ad845705a2b7db96548f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 15:08:58 +0900 Subject: [PATCH 2201/3664] [gamecode] Preserve base registers across calls With this, functions can call other functions without having to worry about whether the base registers they set up are still valid. --- include/QF/progs.h | 1 + libs/gamecode/pr_exec.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 1597c97df..d2a923743 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1801,6 +1801,7 @@ extern const char *pr_gametype; typedef struct strref_s strref_t; typedef struct { + pr_uivec4_t bases; ///< base registers on entry to function pr_uint_t staddr; ///< Return statement. pr_uint_t stack_ptr; ///< data stack on entry to function bfunction_t *func; ///< Calling function. diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index cf01b0e8a..46d474a7b 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -146,6 +146,7 @@ PR_PushFrame (progs_t *pr) if (pr->globals.stack) { frame->stack_ptr = *pr->globals.stack; } + frame->bases = pr->pr_bases; frame->func = pr->pr_xfunction; frame->tstr = pr->pr_xtstr; @@ -182,6 +183,7 @@ PR_PopFrame (progs_t *pr) pr->pr_xfunction = frame->func; pr->pr_xstatement = frame->staddr; pr->pr_xtstr = frame->tstr; + pr->pr_bases = frame->bases; // restore data stack (discard any locals) if (pr->globals.stack) { *pr->globals.stack = frame->stack_ptr; From 94ef9931a571f5488a9c6d2d69f2cb6c99d0b20c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 16:27:50 +0900 Subject: [PATCH 2202/3664] [gamecode] Add two more call/return tests The two tests check that 32 words can be returned (fails) and that function calls can be nested and their values returned properly (also fails). --- libs/gamecode/test/test-callret.c | 113 ++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 12 deletions(-) diff --git a/libs/gamecode/test/test-callret.c b/libs/gamecode/test/test-callret.c index 269ff61a9..64a597ce7 100644 --- a/libs/gamecode/test/test-callret.c +++ b/libs/gamecode/test/test-callret.c @@ -15,7 +15,7 @@ #define STK (32 * 4) // stack ptr just after globals -static pr_ivec4_t float_callret_init[32] = { +static pr_ivec4_t callret_init[32] = { { 0, pi_6, 2, 0}, { f1, f2, 0, 0}, // result @@ -27,7 +27,7 @@ static pr_ivec4_t float_callret_init[32] = { { DB, DB, DB, DB }, }; -static pr_ivec4_t float_callret_expect[32] = { +static pr_ivec4_t callret_expect[32] = { // constants { 0, pi_6, 2, 0 }, { f1, f2, 0, 0 }, @@ -41,7 +41,7 @@ static pr_ivec4_t float_callret_expect[32] = { { DB, DB, DB, DB }, }; -static dstatement_t float_callret_statements[] = { +static dstatement_t callret_statements[] = { { OP_WITH, 8, 0, 0 }, // pushregs { OP_POP_A_4, 12, 0, 0 }, { OP_STORE_A_1, 7, 0, STK }, // save stack pointer for check @@ -54,6 +54,7 @@ static dstatement_t float_callret_statements[] = { { OP_BREAK }, // cos_sin_cosh_sinh: // calculate cos(x), sin(x), cosh(x) and sinh(x) simultaneously +[32]= { OP_WITH, 2, 0, 1 }, // put params into reg 1 { OP_LEA_C, STK, -24, STK }, // reserve 24 words on the stack { OP_WITH, 2, 0, 2 }, // put locals into reg 2 @@ -67,12 +68,12 @@ static dstatement_t float_callret_statements[] = { { OP(2, 0, 1, OP_STORE_A_1), xn+1,0, x }, // init xn to [1, x, 0, 0] { OP(2, 0, 0, OP_STORE_A_1), xn, 0, 4 }, { OP(2, 0, 2, OP_SWIZZLE_F), xn, 0x0044, xn }, // xn -> [1, x, 1, x] - { OP(1, 1, 2, OP_MUL_F_1), x, x, x2 }, // x2 -> [x*x, 0, 0, 0] + { OP(1, 1, 2, OP_MUL_F_1), x, x, x2 }, // x2 -> [x*x, ?, ?, ?] { OP(2, 0, 2, OP_SWIZZLE_F), x2, 0x0300, x2},//x2 -> [-x*x, -x*x, x*x, x*x] { OP(2, 0, 0, OP_STORE_A_1), fa, 0, 4 }, // init factorial { OP(2, 0, 0, OP_STORE_A_1), fa+1,0, 5 }, { OP(2, 0, 2, OP_SWIZZLE_F), fa, 0x0044, fa }, // fa -> [1, 2, 1, 2] - { OP(0, 0, 2, OP_SWIZZLE_F), 4, 0x0000, fi }, // init fi -> [1, 1, 1, 1] + { OP(2, 0, 2, OP_SWIZZLE_F), fa, 0x0000, fi }, // init fi -> [1, 1, 1, 1] { OP(2, 2, 2, OP_SUB_F_4), ac, ac, ac }, // init acc (output) to 0 { OP(0, 0, 2, OP_LEA_A), 25, 0, c }, // init count // loop: @@ -85,7 +86,6 @@ static dstatement_t float_callret_statements[] = { { OP(2, 0, 2, OP_LEA_C), c, -1, c }, // dec count { OP(0, 0, 2, OP_IFA), -7, 0, c }, // count > 0 { OP(2, 0, 0, OP_RETURN), ac, 0, 4 }, -}; #undef x #undef xn #undef x2 @@ -93,19 +93,108 @@ static dstatement_t float_callret_statements[] = { #undef fa #undef fi #undef c +}; + +static pr_ivec4_t call32_init[32] = { + { 0, 2, 0, 0 }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, + { DB, DB, DB, DB }, +}; + +static pr_ivec4_t call32_expect[32] = { + { 0, 2, 0, 0 }, + { 0, 1, 2, 3 }, + { 4, 5, 6, 7 }, + { 8, 9, 10, 11 }, + { 12, 13, 14, 15 }, + { 16, 17, 18, 19 }, + { 20, 21, 22, 23 }, + { 24, 25, 26, 27 }, + { 28, 29, 30, 31 }, +}; + +static dstatement_t call32_statements[] = { + { OP_CALL_B, 1, 0, 4 }, + { OP_BREAK }, +[32]= + { OP_LEA_C, STK, -36, STK }, // reserve 36 words on the stack + { OP_WITH, 2, 0, 2 }, // put locals into reg 2 + { OP(0, 0, 2, OP_LEA_A), 32, 0, 32 }, // init index + { OP(2, 0, 2, OP_LEA_A), 0, 0, 33 }, // init base to array +//loop: + { OP(0, 0, 2, OP_IFBE), 4, 0, 32 }, // if index-- > 0 + { OP(2, 0, 2, OP_LEA_C), 32, -1, 32 }, + { OP(2, 2, 2, OP_STORE_D_1), 33, 32, 32 }, // array[index] = index + { OP(0, 0, 0, OP_JUMP_A), -3, 0, 0 }, + { OP(2, 0, 0, OP_RETURN), 0, 0, 32 }, +}; + +static pr_ivec4_t callchain_init[32] = { + { 0, 2, 3, 0 }, + { DB, DB, DB, DB }, +}; + +static pr_ivec4_t callchain_expect[32] = { + { 0, 2, 3, 0 }, + { 42, DB, DB, DB }, +}; + +static dstatement_t callchain_statements[] = { + { OP_CALL_B, 1, 0, 4 }, + { OP_BREAK }, +[32]= + { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack + { OP_WITH, 2, 0, 2 }, // put locals into reg 2 + { OP(0, 0, 2, OP_CALL_B), 2, 0, 0 }, + { OP(2, 0, 0, OP_RETURN), 0, 0, 1 }, +[64]= + { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack + { OP_WITH, 2, 0, 2 }, // put locals into reg 2 + { OP(0, 0, 2, OP_LEA_A), 42, 0, 0 }, // init value + { OP(2, 0, 0, OP_RETURN), 0, 0, 1 }, // return value +}; static bfunction_t callret_functions[] = { - { .first_statement = 10 }, + { .first_statement = 32 }, + { .first_statement = 64 }, }; test_t tests[] = { { .desc = "callret", - .num_globals = num_globals(float_callret_init,float_callret_expect), - .num_statements = num_statements (float_callret_statements), - .statements = float_callret_statements, - .init_globals = (pr_int_t *) float_callret_init, - .expect_globals = (pr_int_t *) float_callret_expect, + .num_globals = num_globals(callret_init,callret_expect), + .num_statements = num_statements (callret_statements), + .statements = callret_statements, + .init_globals = (pr_int_t *) callret_init, + .expect_globals = (pr_int_t *) callret_expect, + .functions = callret_functions, + .num_functions = num_functions(callret_functions), + .stack_size = 128, + }, + { + .desc = "call32", + .num_globals = num_globals(call32_init,call32_expect), + .num_statements = num_statements (call32_statements), + .statements = call32_statements, + .init_globals = (pr_int_t *) call32_init, + .expect_globals = (pr_int_t *) call32_expect, + .functions = callret_functions, + .num_functions = num_functions(callret_functions), + .stack_size = 128, + }, + { + .desc = "callchain", + .num_globals = num_globals(callchain_init,callchain_expect), + .num_statements = num_statements (callchain_statements), + .statements = callchain_statements, + .init_globals = (pr_int_t *) callchain_init, + .expect_globals = (pr_int_t *) callchain_expect, .functions = callret_functions, .num_functions = num_functions(callret_functions), .stack_size = 128, From 89e120ba3436f3916822dc09d32001fd53beff14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 16:54:27 +0900 Subject: [PATCH 2203/3664] [gamecode] Make return support 32 words This took interpreting the lower 5 bits of operand c as size - 1, and 0xffff as void (0 words). --- libs/gamecode/pr_exec.c | 6 +++--- libs/gamecode/test/test-callret.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 46d474a7b..90296c153 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3131,9 +3131,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; OP_cmp_T (LT, U, long, lvec2, lvec4, <, ulong, ulvec2, ulvec4); case OP_RETURN: - int ret_size = st->c & 0x1f; // up to 32 words - if (ret_size) { - mm = pr_return_mode (pr, st, (st->c >> 5) & 7); + int ret_size = (st->c & 0x1f) + 1; // up to 32 words + if (st->c != 0xffff) { + mm = pr_return_mode (pr, st, st->c >> 5); memcpy (&R_INT (pr), mm, ret_size * sizeof (*op_a)); } pr->pr_xfunction->profile += profile - startprofile; diff --git a/libs/gamecode/test/test-callret.c b/libs/gamecode/test/test-callret.c index 64a597ce7..9bf96fa54 100644 --- a/libs/gamecode/test/test-callret.c +++ b/libs/gamecode/test/test-callret.c @@ -85,7 +85,7 @@ static dstatement_t callret_statements[] = { { OP(2, 2, 2, OP_ADD_F_4), fa, fi, fa }, // f += inc { OP(2, 0, 2, OP_LEA_C), c, -1, c }, // dec count { OP(0, 0, 2, OP_IFA), -7, 0, c }, // count > 0 - { OP(2, 0, 0, OP_RETURN), ac, 0, 4 }, + { OP(2, 0, 0, OP_RETURN), ac, 0, 3 }, // size is (c&31)+1 #undef x #undef xn #undef x2 @@ -132,7 +132,7 @@ static dstatement_t call32_statements[] = { { OP(2, 0, 2, OP_LEA_C), 32, -1, 32 }, { OP(2, 2, 2, OP_STORE_D_1), 33, 32, 32 }, // array[index] = index { OP(0, 0, 0, OP_JUMP_A), -3, 0, 0 }, - { OP(2, 0, 0, OP_RETURN), 0, 0, 32 }, + { OP(2, 0, 0, OP_RETURN), 0, 0, 0x1f }, // only bits 0-5 are size }; static pr_ivec4_t callchain_init[32] = { @@ -152,12 +152,12 @@ static dstatement_t callchain_statements[] = { { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack { OP_WITH, 2, 0, 2 }, // put locals into reg 2 { OP(0, 0, 2, OP_CALL_B), 2, 0, 0 }, - { OP(2, 0, 0, OP_RETURN), 0, 0, 1 }, + { OP(2, 0, 0, OP_RETURN), 0, 0, 0 }, [64]= { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack { OP_WITH, 2, 0, 2 }, // put locals into reg 2 { OP(0, 0, 2, OP_LEA_A), 42, 0, 0 }, // init value - { OP(2, 0, 0, OP_RETURN), 0, 0, 1 }, // return value + { OP(2, 0, 0, OP_RETURN), 0, 0, 0 }, // return value }; static bfunction_t callret_functions[] = { From 306fcbfbd0261f6e4e1e0e565f3d1442cc14eda9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 16:55:39 +0900 Subject: [PATCH 2204/3664] [gamecode] Improve callchain test Add another function call to further mess up the return value address and verify just where it is pointing. --- libs/gamecode/test/test-callret.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/test/test-callret.c b/libs/gamecode/test/test-callret.c index 9bf96fa54..5fd48d2c7 100644 --- a/libs/gamecode/test/test-callret.c +++ b/libs/gamecode/test/test-callret.c @@ -136,7 +136,7 @@ static dstatement_t call32_statements[] = { }; static pr_ivec4_t callchain_init[32] = { - { 0, 2, 3, 0 }, + { 0, 2, 3, 4 }, { DB, DB, DB, DB }, }; @@ -152,17 +152,21 @@ static dstatement_t callchain_statements[] = { { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack { OP_WITH, 2, 0, 2 }, // put locals into reg 2 { OP(0, 0, 2, OP_CALL_B), 2, 0, 0 }, + { OP(0, 0, 2, OP_CALL_B), 2, 0, 1 }, { OP(2, 0, 0, OP_RETURN), 0, 0, 0 }, [64]= { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack { OP_WITH, 2, 0, 2 }, // put locals into reg 2 { OP(0, 0, 2, OP_LEA_A), 42, 0, 0 }, // init value { OP(2, 0, 0, OP_RETURN), 0, 0, 0 }, // return value +[96]= + { OP_RETURN, 0, 0, -1 } // void return }; static bfunction_t callret_functions[] = { { .first_statement = 32 }, { .first_statement = 64 }, + { .first_statement = 96 }, }; test_t tests[] = { From e9af5491956a078039bfb3a7a52af176046ee89d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 18:51:50 +0900 Subject: [PATCH 2205/3664] [gamecode] Fix some goofs in the callchain test They made it difficult to tell when I got things working :P --- libs/gamecode/test/test-callret.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/test/test-callret.c b/libs/gamecode/test/test-callret.c index 5fd48d2c7..d90b95efa 100644 --- a/libs/gamecode/test/test-callret.c +++ b/libs/gamecode/test/test-callret.c @@ -141,7 +141,7 @@ static pr_ivec4_t callchain_init[32] = { }; static pr_ivec4_t callchain_expect[32] = { - { 0, 2, 3, 0 }, + { 0, 2, 3, 4 }, { 42, DB, DB, DB }, }; @@ -152,7 +152,7 @@ static dstatement_t callchain_statements[] = { { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack { OP_WITH, 2, 0, 2 }, // put locals into reg 2 { OP(0, 0, 2, OP_CALL_B), 2, 0, 0 }, - { OP(0, 0, 2, OP_CALL_B), 2, 0, 1 }, + { OP(0, 0, 2, OP_CALL_B), 3, 0, 1 }, { OP(2, 0, 0, OP_RETURN), 0, 0, 0 }, [64]= { OP_LEA_C, STK, -4, STK }, // reserve 4 words on the stack From 9348f7b89ca30bc7441ad8c5d19b53ebd7d7a51b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 17 Jan 2022 19:12:28 +0900 Subject: [PATCH 2206/3664] [gamecode] Preserve the return pointer across calls This required delaying the setting of the return pointer by call until after the current pointer had been saved, and thus passing the desired pointer into PR_CallFunction (which does have some advantages for C functions calling progs functions, but some dangers too (should ensure a 128 byte (32 word) buffer when calling untrusted code (which is any, really)). --- include/QF/progs.h | 5 ++++- libs/gamecode/pr_exec.c | 15 ++++++++++----- libs/ruamoko/rua_obj.c | 12 ++++++------ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index d2a923743..634eb38a0 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -175,10 +175,12 @@ void PR_ExecuteProgram (progs_t *pr, func_t fnum); execute upon return of control to PR_ExecuteProgram(). \param pr pointer to ::progs_t VM struct \param fnum number of the function to call + \param return_ptr pointer to location in which return values will be + written \return true if \p fnum was a progs function, false if \p fnum was a builtin */ -int PR_CallFunction (progs_t *pr, func_t fnum); +int PR_CallFunction (progs_t *pr, func_t fnum, pr_type_t *return_ptr); ///@} @@ -1806,6 +1808,7 @@ typedef struct { pr_uint_t stack_ptr; ///< data stack on entry to function bfunction_t *func; ///< Calling function. strref_t *tstr; ///< Linked list of temporary strings. + pr_type_t *return_ptr; ///< Saved return address } prstack_t; struct progs_s { diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 90296c153..a8585fc2b 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -149,6 +149,7 @@ PR_PushFrame (progs_t *pr) frame->bases = pr->pr_bases; frame->func = pr->pr_xfunction; frame->tstr = pr->pr_xtstr; + frame->return_ptr = pr->pr_return; pr->pr_xtstr = pr->pr_pushtstr; pr->pr_pushtstr = 0; @@ -180,6 +181,7 @@ PR_PopFrame (progs_t *pr) // up stack frame = pr->pr_stack + --pr->pr_depth; + pr->pr_return = frame->return_ptr; pr->pr_xfunction = frame->func; pr->pr_xstatement = frame->staddr; pr->pr_xtstr = frame->tstr; @@ -419,7 +421,7 @@ error_handler (void *data) } VISIBLE int -PR_CallFunction (progs_t *pr, func_t fnum) +PR_CallFunction (progs_t *pr, func_t fnum, pr_type_t *return_ptr) { bfunction_t *f; @@ -432,10 +434,14 @@ PR_CallFunction (progs_t *pr, func_t fnum) Sys_Printf ("Calling builtin %s @ %p\n", PR_GetString (pr, f->descriptor->name), f->func); } + pr_type_t *saved_return = pr->pr_return; + pr->pr_return = return_ptr; f->func (pr); + pr->pr_return = saved_return; return 0; } else { PR_EnterFunction (pr, f); + pr->pr_return = return_ptr; return 1; } } @@ -1461,7 +1467,7 @@ op_rcall: op_call: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; - PR_CallFunction (pr, OPA(uint)); + PR_CallFunction (pr, OPA(uint), pr->pr_return); st = pr->pr_statements + pr->pr_xstatement; break; case OP_DONE_v6p: @@ -3154,10 +3160,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) function = mm->func_var; pr->pr_argc = 0; // op_c specifies the location for the return value if any - pr->pr_return = op_c; pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; - PR_CallFunction (pr, function); + PR_CallFunction (pr, function, op_c); st = pr->pr_statements + pr->pr_xstatement; break; // 1 1010 @@ -3466,7 +3471,7 @@ PR_ExecuteProgram (progs_t *pr, func_t fnum) } int exitdepth = pr->pr_depth; - if (!PR_CallFunction (pr, fnum)) { + if (!PR_CallFunction (pr, fnum, pr->pr_return)) { // called a builtin instead of progs code goto exit_program; } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index aab7b4c0f..22a8b98e7 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1291,7 +1291,7 @@ rua___obj_forward (progs_t *pr) P_PACKED (pr, pr_va_list_t, 3).count = argc; P_PACKED (pr, pr_va_list_t, 3).list = PR_SetPointer (pr, argv); PR_PushTempString (pr, args_block); - PR_CallFunction (pr, imp); + PR_CallFunction (pr, imp, pr->pr_return); return; } //FIXME ditto @@ -1303,7 +1303,7 @@ rua___obj_forward (progs_t *pr) P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); P_POINTER (pr, 2) = PR_SetPointer (pr, sel); pr->pr_argc = 3; - PR_CallFunction (pr, imp); + PR_CallFunction (pr, imp, pr->pr_return); return; } @@ -1321,7 +1321,7 @@ rua___obj_forward (progs_t *pr) P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); P_POINTER (pr, 2) = PR_SetTempString (pr, probj->msg->str); pr->pr_argc = 3; - PR_CallFunction (pr, imp); + PR_CallFunction (pr, imp, pr->pr_return); return; } @@ -1437,7 +1437,7 @@ rua_obj_msg_sendv (progs_t *pr) memcpy (&P_INT (pr, 2), params, count * sizeof (pr_type_t) * pr->pr_param_size); } - PR_CallFunction (pr, imp); + PR_CallFunction (pr, imp, pr->pr_return); } static void @@ -1544,7 +1544,7 @@ rua_obj_msgSend (progs_t *pr) PR_GetString (pr, object_get_class_name (probj, self)), PR_GetString (pr, probj->selector_names[_cmd->sel_id])); - PR_CallFunction (pr, imp); + PR_CallFunction (pr, imp, pr->pr_return); } static void @@ -1564,7 +1564,7 @@ rua_obj_msgSend_super (progs_t *pr) } pr->pr_params[0] = pr->pr_real_params[0]; P_POINTER (pr, 0) = super->self; - PR_CallFunction (pr, imp); + PR_CallFunction (pr, imp, pr->pr_return); } static void From 2df64384c1476a6428bb37f9c6be0127cbe88bc7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 12:11:14 +0900 Subject: [PATCH 2207/3664] [gamecode] Clean up string_t and pointer_t They are both gone, and pr_pointer_t is now pr_ptr_t (pointer may be a little clearer than ptr, but ptr is consistent with things like intptr, and keeps the type name short). --- include/QF/progs.h | 70 +++++++++++++-------------- include/QF/progs/pr_comp.h | 28 +++++------ include/QF/progs/pr_obj.h | 80 +++++++++++++++---------------- include/QF/progs/pr_type.h | 28 +++++------ include/QF/ruamoko.h | 4 +- libs/console/bi_inputline.c | 2 +- libs/gamecode/pr_debug.c | 22 ++++----- libs/gamecode/pr_exec.c | 82 ++++++++++++++++---------------- libs/gamecode/pr_resolve.c | 6 +-- libs/gamecode/pr_strings.c | 40 ++++++++-------- libs/gamecode/test/head.c | 4 +- libs/gamecode/test/main.c | 4 +- libs/ruamoko/rua_hash.c | 2 +- libs/ruamoko/rua_input.c | 6 +-- libs/ruamoko/rua_obj.c | 36 +++++++------- libs/ruamoko/rua_qfile.c | 2 +- libs/ruamoko/rua_qfs.c | 8 ++-- libs/ruamoko/rua_runtime.c | 2 +- libs/ruamoko/rua_script.c | 2 +- libs/ruamoko/rua_set.c | 48 +++++++++---------- libs/ruamoko/rua_string.c | 2 +- nq/include/sv_progs.h | 16 +++---- qw/include/sv_progs.h | 12 ++--- qw/source/sv_pr_cpqw.c | 2 +- ruamoko/qwaq/builtins/debug.c | 56 +++++++++++----------- ruamoko/qwaq/builtins/main.c | 2 +- ruamoko/qwaq/debugger/debug.h | 6 +-- ruamoko/qwaq/editor/editbuffer.h | 2 +- ruamoko/qwaq/qwaq-input.h | 8 ++-- ruamoko/qwaq/ui/event.h | 4 +- ruamoko/qwaq/ui/textcontext.h | 2 +- tools/qfcc/include/def.h | 2 +- tools/qfcc/include/expr.h | 2 +- tools/qfcc/include/function.h | 6 +-- tools/qfcc/include/obj_file.h | 16 +++---- tools/qfcc/include/qfcc.h | 4 +- tools/qfcc/include/reloc.h | 2 +- tools/qfcc/source/class.c | 4 +- tools/qfcc/source/diagnostic.c | 6 +-- tools/qfcc/source/dump_globals.c | 8 ++-- tools/qfcc/source/dump_lines.c | 2 +- tools/qfcc/source/dump_modules.c | 8 ++-- tools/qfcc/source/expr.c | 8 ++-- tools/qfcc/source/linker.c | 4 +- tools/qfcc/source/obj_file.c | 8 ++-- tools/qfcc/source/obj_type.c | 2 +- tools/qfcc/source/stub.c | 2 +- tools/qfcc/source/switch.c | 2 +- tools/qfcc/source/value.c | 2 +- tools/qfcc/test/test-harness.c | 2 +- 50 files changed, 338 insertions(+), 340 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 634eb38a0..f8c8d42b0 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -265,7 +265,7 @@ int PR_RunPostLoadFuncs (progs_t *pr); */ int PR_Check_Opcodes (progs_t *pr); -void PR_BoundsCheckSize (progs_t *pr, pointer_t addr, unsigned size); +void PR_BoundsCheckSize (progs_t *pr, pr_ptr_t addr, unsigned size); void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); ///@} @@ -336,10 +336,10 @@ void ED_EntityParseFunction (progs_t *pr); */ ///@{ -pr_def_t *PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset) +pr_def_t *PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pr_ptr_t offset) __attribute__((pure)); -pr_def_t *PR_FieldAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure)); -pr_def_t *PR_GlobalAtOfs (progs_t *pr, pointer_t ofs) __attribute__((pure)); +pr_def_t *PR_FieldAtOfs (progs_t *pr, pr_ptr_t ofs) __attribute__((pure)); +pr_def_t *PR_GlobalAtOfs (progs_t *pr, pr_ptr_t ofs) __attribute__((pure)); pr_def_t *PR_FindField (progs_t *pr, const char *name); pr_def_t *PR_FindGlobal (progs_t *pr, const char *name); @@ -470,7 +470,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c string \param p pointer to ::progs_t VM struct \param o offset into global data space - \return string_t lvalue + \return pr_string_t lvalue \hideinitializer */ @@ -494,7 +494,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void * \param p pointer to ::progs_t VM struct \param o offset into global data space - \return pointer_t lvalue + \return pr_ptr_t lvalue \hideinitializer */ @@ -686,7 +686,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c string \param p pointer to ::progs_t VM struct \param n parameter number (0-7) - \return string_t lvalue + \return pr_string_t lvalue \hideinitializer */ @@ -710,7 +710,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void * \param p pointer to ::progs_t VM struct \param n parameter number (0-7) - \return pointer_t lvalue + \return pr_ptr_t lvalue \hideinitializer */ @@ -891,12 +891,12 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_QUAT(p) (&R_var (p, quat)) -/** Access the VM function return value as a ::string_t (a VM string reference). +/** Access the VM function return value as a ::pr_string_t (a VM string reference). \par QC type: \c string \param p pointer to ::progs_t VM struct - \return ::string_t lvalue + \return ::pr_string_t lvalue \hideinitializer */ @@ -913,12 +913,12 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_FUNCTION(p) R_var (p, func) -/** Access the VM function return value as a ::pointer_t (a VM "pointer") +/** Access the VM function return value as a ::pr_ptr_t (a VM "pointer") \par QC type: \c void * \param p pointer to ::progs_t VM struct - \return ::pointer_t lvalue + \return ::pr_ptr_t lvalue \hideinitializer */ @@ -1091,7 +1091,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c string \param e pointer to the entity \param o field offset into entity data space - \return string_t lvalue + \return pr_string_t lvalue \hideinitializer */ @@ -1115,7 +1115,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void * \param e pointer to the entity \param o field offset into entity data space - \return pointer_t lvalue + \return pr_ptr_t lvalue \hideinitializer */ @@ -1282,28 +1282,28 @@ int PR_LoadStrings (progs_t *pr); \param num string index to be validated \return true if the index is valid, false otherwise */ -qboolean PR_StringValid (progs_t *pr, string_t num) __attribute__((pure)); +qboolean PR_StringValid (progs_t *pr, pr_string_t num) __attribute__((pure)); /** Check if a string is valid and mutable. \param pr pointer to ::progs_t VM struct \param num string index to be checked \return true if the string is valid and mutable, false otherwise */ -qboolean PR_StringMutable (progs_t *pr, string_t num) __attribute__((pure)); +qboolean PR_StringMutable (progs_t *pr, pr_string_t num) __attribute__((pure)); /** Convert a string index to a C string. \param pr pointer to ::progs_t VM struct \param num string index to be converted \return C pointer to the string. */ -const char *PR_GetString(progs_t *pr, string_t num) __attribute__((pure)); +const char *PR_GetString(progs_t *pr, pr_string_t num) __attribute__((pure)); /** Retrieve the dstring_t associated with a mutable string. \param pr pointer to ::progs_t VM struct \param num string index of the mutable string \return the dstring implementing the mutable string */ -struct dstring_s *PR_GetMutableString(progs_t *pr, string_t num) __attribute__((pure)); +struct dstring_s *PR_GetMutableString(progs_t *pr, pr_string_t num) __attribute__((pure)); /** Make a permanent progs string from the given C string. Will not create a duplicate permanent string (temporary and mutable strings are not checked). @@ -1311,7 +1311,7 @@ struct dstring_s *PR_GetMutableString(progs_t *pr, string_t num) __attribute__(( \param s C string to be made into a permanent progs string \return string index of the progs string */ -string_t PR_SetString(progs_t *pr, const char *s); +pr_string_t PR_SetString(progs_t *pr, const char *s); /** Get the progs string if it exists. Only static strings are searched. @@ -1320,7 +1320,7 @@ string_t PR_SetString(progs_t *pr, const char *s); \return string index of the progs string if it exists, otherwise 0 (ambiguous with ""). */ -string_t PR_FindString(progs_t *pr, const char *s); +pr_string_t PR_FindString(progs_t *pr, const char *s); /** Make a temporary progs string that will survive across function returns. Will not duplicate a permanent string. If a new progs string is created, @@ -1330,7 +1330,7 @@ string_t PR_FindString(progs_t *pr, const char *s); \param s C string to be returned to the progs code \return string index of the progs string */ -string_t PR_SetReturnString(progs_t *pr, const char *s); +pr_string_t PR_SetReturnString(progs_t *pr, const char *s); /** Make a temporary progs string that will be freed when the current progs stack frame is exited. Will not duplicate a permantent string. @@ -1338,7 +1338,7 @@ string_t PR_SetReturnString(progs_t *pr, const char *s); \param s C string \return string index of the progs string */ -string_t PR_SetTempString(progs_t *pr, const char *s); +pr_string_t PR_SetTempString(progs_t *pr, const char *s); /** Make a temporary memory block that will be freed when the current progs stack frame is exited. The contents may be anything and a new block is @@ -1350,7 +1350,7 @@ string_t PR_SetTempString(progs_t *pr, const char *s); \param size size of block in bytes \return string index of the block */ -string_t PR_AllocTempBlock (progs_t *pr, size_t size); +pr_string_t PR_AllocTempBlock (progs_t *pr, size_t size); /** Push a temporary string to the callee stack frame @@ -1361,7 +1361,7 @@ string_t PR_AllocTempBlock (progs_t *pr, size_t size); \param pr pointer to ::progs_t VM struct \param num string index of the temp string */ -void PR_PushTempString (progs_t *pr, string_t num); +void PR_PushTempString (progs_t *pr, pr_string_t num); /** Make a temporary progs string that is the concatenation of two C strings. \param pr pointer to ::progs_t VM struct @@ -1370,19 +1370,19 @@ void PR_PushTempString (progs_t *pr, string_t num); \return string index of the progs string that represents the concatenation of strings a and b */ -string_t PR_CatStrings (progs_t *pr, const char *a, const char *b); +pr_string_t PR_CatStrings (progs_t *pr, const char *a, const char *b); /** Convert a mutable string to a temporary string. \param pr pointer to ::progs_t VM struct \param str string index of the mutable string to be converted */ -void PR_MakeTempString(progs_t *pr, string_t str); +void PR_MakeTempString(progs_t *pr, pr_string_t str); /** Create a new mutable string. \param pr pointer to ::progs_t VM struct \return string index of the newly created mutable string */ -string_t PR_NewMutableString (progs_t *pr); +pr_string_t PR_NewMutableString (progs_t *pr); /** Make a dynamic progs string from the given C string. Will not create a duplicate permanent string (temporary, dynamic and mutable strings are @@ -1391,7 +1391,7 @@ string_t PR_NewMutableString (progs_t *pr); \param s C string to be made into a permanent progs string \return string index of the progs string */ -string_t PR_SetDynamicString (progs_t *pr, const char *s); +pr_string_t PR_SetDynamicString (progs_t *pr, const char *s); /** Convert an ephemeral string to a dynamic string. @@ -1403,13 +1403,13 @@ string_t PR_SetDynamicString (progs_t *pr, const char *s); \param str The string to be "held" (made non-ephemeral). Safe to call on any valid string, but affects only ephemeral strings. */ -void PR_HoldString (progs_t *pr, string_t str); +void PR_HoldString (progs_t *pr, pr_string_t str); /** Destroy a mutable, dynamic or temporary string. \param pr pointer to ::progs_t VM struct \param str string index of the string to be destroyed */ -void PR_FreeString (progs_t *pr, string_t str); +void PR_FreeString (progs_t *pr, pr_string_t str); /** Free all the temporary strings allocated in the current stack frame. \param pr pointer to ::progs_t VM struct @@ -1765,7 +1765,7 @@ pr_uint_t PR_FindSourceLineAddr (progs_t *pr, const char *file, pr_uint_t line) const char *PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) __attribute__((pure)); const char *PR_Get_Source_Line (progs_t *pr, pr_uint_t addr); pr_def_t *PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) __attribute__((pure)); -pr_def_t *PR_Get_Local_Def (progs_t *pr, pointer_t *offs) __attribute__((pure)); +pr_def_t *PR_Get_Local_Def (progs_t *pr, pr_ptr_t *offs) __attribute__((pure)); void PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents); void PR_DumpState (progs_t *pr); void PR_StackTrace (progs_t *pr); @@ -1935,7 +1935,7 @@ struct progs_s { /// stack. ///@{ pr_type_t *stack; - pointer_t stack_bottom; + pr_ptr_t stack_bottom; int stack_size; ///< set by user ///@} @@ -1970,7 +1970,7 @@ struct progs_s { double *dtime; ///< required for OP_STATE d float *ftime; ///< required for OP_STATE f pr_uint_t *self; ///< required for OP_STATE - pointer_t *stack; ///< required for OP_(PUSH|POP)* + pr_ptr_t *stack; ///< required for OP_(PUSH|POP)* } globals; struct { pr_int_t nextthink; ///< required for OP_STATE @@ -1991,7 +1991,7 @@ struct progs_s { \return C pointer represented by the parameter. 0 offset -> NULL */ static inline pr_type_t * -PR_GetPointer (const progs_t *pr, pointer_t o) +PR_GetPointer (const progs_t *pr, pr_ptr_t o) { return o ? pr->pr_globals + o : 0; } @@ -2001,7 +2001,7 @@ PR_GetPointer (const progs_t *pr, pointer_t o) \param p C pointer to be converted. \return Progs offset/pointer represented by \c p. NULL -> 0 offset */ -static inline pointer_t +static inline pr_ptr_t PR_SetPointer (const progs_t *pr, const void *p) { return p ? (const pr_type_t *) p - pr->pr_globals : 0; diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 2b5c0ad79..7b097cda1 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -33,9 +33,7 @@ typedef int64_t pr_long_t; typedef uint64_t pr_ulong_t; typedef pr_uint_t func_t; typedef pr_int_t pr_string_t; -typedef pr_string_t string_t;//FIXME -typedef pr_uint_t pr_pointer_t; -typedef pr_pointer_t pointer_t;//FIXME +typedef pr_uint_t pr_ptr_t; #define PR_VEC_TYPE(t,n,s) \ typedef t n __attribute__ ((vector_size (s*sizeof (t)))) @@ -489,25 +487,25 @@ typedef struct ddef_s { pr_ushort_t type; // if DEF_SAVEGLOBAL bit is set // the variable needs to be saved in savegames pr_ushort_t ofs; - string_t name; + pr_string_t name; } ddef_t; typedef struct xdef_s { - pointer_t type; ///< pointer to type definition - pointer_t ofs; ///< 32-bit version of ddef_t.ofs + pr_ptr_t type; ///< pointer to type definition + pr_ptr_t ofs; ///< 32-bit version of ddef_t.ofs } xdef_t; typedef struct pr_xdefs_s { - pointer_t xdefs; + pr_ptr_t xdefs; pr_int_t num_xdefs; } pr_xdefs_t; typedef struct pr_def_s { pr_ushort_t type; pr_ushort_t size; ///< may not be correct - pointer_t ofs; - string_t name; - pointer_t type_encoding; + pr_ptr_t ofs; + pr_string_t name; + pr_ptr_t type_encoding; } pr_def_t; typedef struct dparmsize_s { @@ -526,8 +524,8 @@ typedef struct dfunction_s { pr_uint_t profile; // runtime - string_t name; // source function name - string_t file; // source file defined in + pr_string_t name; // source function name + pr_string_t file; // source file defined in pr_int_t numparms; // -ve is varargs (1s comp of real count) dparmsize_t parm_size[MAX_PARMS]; @@ -535,19 +533,19 @@ typedef struct dfunction_s { typedef union pr_type_u { float float_var; - string_t string_var; + pr_string_t string_var; func_t func_var; pr_uint_t entity_var; float vector_var; // really [3], but this structure must be 32 bits float quat_var; // really [4], but this structure must be 32 bits pr_int_t integer_var; - pointer_t pointer_var; + pr_ptr_t pointer_var; pr_uint_t uinteger_var; } pr_type_t; typedef struct pr_va_list_s { pr_int_t count; - pointer_t list; // pr_type_t + pr_ptr_t list; // pr_type_t } pr_va_list_t; #define PROG_VERSION_ENCODE(a,b,c) \ diff --git a/include/QF/progs/pr_obj.h b/include/QF/progs/pr_obj.h index ea8f6a052..00f493469 100644 --- a/include/QF/progs/pr_obj.h +++ b/include/QF/progs/pr_obj.h @@ -77,58 +77,58 @@ | (num) << (PR_BITS_PER_INT / 2)) typedef struct pr_sel_s { - pointer_t sel_id; - string_t sel_types; + pr_ptr_t sel_id; + pr_string_t sel_types; } pr_sel_t; typedef struct pr_id_s { - pointer_t class_pointer; // pr_class_t + pr_ptr_t class_pointer; // pr_class_t } pr_id_t; typedef struct pr_class_s { - pointer_t class_pointer; // pr_class_t - pointer_t super_class; // pr_class_t - string_t name; + pr_ptr_t class_pointer; // pr_class_t + pr_ptr_t super_class; // pr_class_t + pr_string_t name; pr_int_t version; pr_uint_t info; pr_int_t instance_size; - pointer_t ivars; // pr_ivar_list_t - pointer_t methods; // pr_method_list_t - pointer_t dtable; // resource index - pointer_t subclass_list; // pr_class_t - pointer_t sibling_class; // pr_class_t - pointer_t protocols; // pr_protocol_list_t - pointer_t gc_object_type; + pr_ptr_t ivars; // pr_ivar_list_t + pr_ptr_t methods; // pr_method_list_t + pr_ptr_t dtable; // resource index + pr_ptr_t subclass_list; // pr_class_t + pr_ptr_t sibling_class; // pr_class_t + pr_ptr_t protocols; // pr_protocol_list_t + pr_ptr_t gc_object_type; } pr_class_t; typedef struct pr_protocol_s { - pointer_t class_pointer; // pr_class_t - string_t protocol_name; - pointer_t protocol_list; // pr_protocol_list_t - pointer_t instance_methods; // pr_method_description_list_t - pointer_t class_methods; // pr_method_description_list_t + pr_ptr_t class_pointer; // pr_class_t + pr_string_t protocol_name; + pr_ptr_t protocol_list; // pr_protocol_list_t + pr_ptr_t instance_methods; // pr_method_description_list_t + pr_ptr_t class_methods; // pr_method_description_list_t } pr_protocol_t; typedef struct pr_category_s { - string_t category_name; - string_t class_name; - pointer_t instance_methods; // pr_method_list_t - pointer_t class_methods; // pr_method_list_t - pointer_t protocols; // pr_protocol_list_t + pr_string_t category_name; + pr_string_t class_name; + pr_ptr_t instance_methods; // pr_method_list_t + pr_ptr_t class_methods; // pr_method_list_t + pr_ptr_t protocols; // pr_protocol_list_t } pr_category_t; typedef struct pr_protocol_list_s { - pointer_t next; + pr_ptr_t next; pr_int_t count; - pointer_t list[1]; // pr_protocol_t + pr_ptr_t list[1]; // pr_protocol_t } pr_protocol_list_t; typedef struct pr_method_list_s { - pointer_t method_next; + pr_ptr_t method_next; pr_int_t method_count; struct pr_method_s { - pointer_t method_name; // pr_sel_t - string_t method_types; + pr_ptr_t method_name; // pr_sel_t + pr_string_t method_types; func_t method_imp; // typedef id (id, SEL, ...) IMP } method_list[1]; } pr_method_list_t; @@ -137,8 +137,8 @@ typedef struct pr_method_s pr_method_t; typedef struct pr_method_description_list_s { pr_int_t count; struct pr_method_description_s { - pointer_t name; // pr_sel_t - string_t types; + pr_ptr_t name; // pr_sel_t + pr_string_t types; } list[1]; } pr_method_description_list_t; typedef struct pr_method_description_s pr_method_description_t; @@ -146,8 +146,8 @@ typedef struct pr_method_description_s pr_method_description_t; typedef struct pr_ivar_list_s { pr_int_t ivar_count; struct pr_ivar_s { - string_t ivar_name; - string_t ivar_type; + pr_string_t ivar_name; + pr_string_t ivar_type; pr_int_t ivar_offset; } ivar_list[1]; } pr_ivar_list_t; @@ -157,16 +157,16 @@ typedef struct pr_static_instances_s { // one per staticly instanced class per module (eg, 3 instances of Object // will produce one of these structs with 3 pointers to those instances in // instances[] - string_t class_name; - pointer_t instances[1]; // null terminated array of pr_id_t + pr_string_t class_name; + pr_ptr_t instances[1]; // null terminated array of pr_id_t } pr_static_instances_t; typedef struct pr_symtab_s { pr_int_t sel_ref_cnt; - pointer_t refs; // pr_sel_t + pr_ptr_t refs; // pr_sel_t pr_int_t cls_def_cnt; pr_int_t cat_def_cnt; - pointer_t defs[1]; // variable array of cls_def_cnt class + pr_ptr_t defs[1]; // variable array of cls_def_cnt class // pointers then cat_def_cnt category // pointers followed by a null terminated // array of pr_static_instances (not yet @@ -176,13 +176,13 @@ typedef struct pr_symtab_s { typedef struct pr_module_s { pr_int_t version; pr_int_t size; - string_t name; - pointer_t symtab; // pr_symtab_t + pr_string_t name; + pr_ptr_t symtab; // pr_symtab_t } pr_module_t; typedef struct pr_super_s { - pointer_t self; - pointer_t class; + pr_ptr_t self; + pr_ptr_t class; } pr_super_t; #endif//__QF_pr_obj_h diff --git a/include/QF/progs/pr_type.h b/include/QF/progs/pr_type.h index 04a3266f6..328b2ff3e 100644 --- a/include/QF/progs/pr_type.h +++ b/include/QF/progs/pr_type.h @@ -34,7 +34,7 @@ /** \defgroup qfcc_qfo_type Object file type encoding \ingroup progs - All \c pointer_t \c type fields are pointers within the type qfo_space. + All \c pr_ptr_t \c type fields are pointers within the type qfo_space. */ ///@{ @@ -52,43 +52,43 @@ typedef enum { typedef struct qfot_alias_s { etype_t type; ///< type at end of alias chain - pointer_t aux_type; ///< referenced type: stripped of aliases - pointer_t full_type; ///< includes full alias info - string_t name; ///< alias name, may be null + pr_ptr_t aux_type; ///< referenced type: stripped of aliases + pr_ptr_t full_type; ///< includes full alias info + pr_string_t name; ///< alias name, may be null } qfot_alias_t; typedef struct qfot_fldptr_s { etype_t type; ///< ev_field or ev_pointer - pointer_t aux_type; ///< referenced type + pr_ptr_t aux_type; ///< referenced type } qfot_fldptr_t; typedef struct qfot_func_s { etype_t type; ///< always ev_func - pointer_t return_type; ///< return type of the function + pr_ptr_t return_type; ///< return type of the function pr_int_t num_params; ///< ones compliment count of the ///< parameters. -ve values indicate the ///< number of real parameters before the ///< ellipsis - pointer_t param_types[1]; ///< variable length list of parameter + pr_ptr_t param_types[1]; ///< variable length list of parameter ///< types } qfot_func_t; typedef struct qfot_var_s { - pointer_t type; ///< type of field or self reference for + pr_ptr_t type; ///< type of field or self reference for ///< enum - string_t name; ///< name of field/enumerator + pr_string_t name; ///< name of field/enumerator pr_int_t offset; ///< value for enum, 0 for union } qfot_var_t; typedef struct qfot_struct_s { - string_t tag; ///< struct/union/enum tag + pr_string_t tag; ///< struct/union/enum tag pr_int_t num_fields; ///< number of fields/enumerators qfot_var_t fields[1]; ///< variable length list of ///< fields/enumerators } qfot_struct_t; typedef struct qfot_array_s { - pointer_t type; ///< element type + pr_ptr_t type; ///< element type pr_int_t base; ///< start index of array pr_int_t size; ///< number of elements in array } qfot_array_t; @@ -103,20 +103,20 @@ typedef struct qfot_array_s { typedef struct qfot_type_s { ty_meta_e meta; ///< meta type pr_uint_t size; ///< total word size of this encoding - string_t encoding; ///< Objective-QC encoding + pr_string_t encoding; ///< Objective-QC encoding union { etype_t type; ///< ty_basic: etype_t qfot_fldptr_t fldptr; ///< ty_basic, ev_pointer/ev_field qfot_func_t func; ///< ty_basic, ev_func qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum qfot_array_t array; ///< ty_array - string_t class; ///< ty_class + pr_string_t class; ///< ty_class qfot_alias_t alias; ///< ty_alias }; } qfot_type_t; typedef struct qfot_type_encodings_s { - pointer_t types; + pr_ptr_t types; pr_uint_t size; } qfot_type_encodings_t; diff --git a/include/QF/ruamoko.h b/include/QF/ruamoko.h index b6f82ff31..8ee071632 100644 --- a/include/QF/ruamoko.h +++ b/include/QF/ruamoko.h @@ -38,8 +38,8 @@ struct cbuf_s; void RUA_Init (struct progs_s *pr, int secure); void RUA_Cbuf_SetCbuf (struct progs_s *pr, struct cbuf_s *cbuf); -func_t RUA_Obj_msg_lookup (struct progs_s *pr, pointer_t _self, - pointer_t __cmd); +func_t RUA_Obj_msg_lookup (struct progs_s *pr, pr_ptr_t _self, + pr_ptr_t __cmd); void RUA_Game_Init (struct progs_s *pr, int secure); diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index 76e9b676c..1c63a69a7 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -50,7 +50,7 @@ typedef struct il_data_s { inputline_t *line; progs_t *pr; func_t enter; // enter key callback - pointer_t data[2]; // allow two data params for the callback + pr_ptr_t data[2]; // allow two data params for the callback int method; // true if method rather than function } il_data_t; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index e4268eef5..4b4b23d05 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -557,7 +557,7 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) } qfot_type_encodings_t *encodings = 0; - pointer_t type_encodings = 0; + pr_ptr_t type_encodings = 0; res->type_encodings_def = PR_FindGlobal (pr, ".type_encodings"); if (res->type_encodings_def) { encodings = &G_STRUCT (pr, qfot_type_encodings_t, @@ -581,7 +581,7 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) } } - string_t compunit_str = PR_FindString (pr, ".compile_unit"); + pr_string_t compunit_str = PR_FindString (pr, ".compile_unit"); for (pr_uint_t i = 0; i < debug->num_debug_defs; i++) { pr_def_t *def = &res->debug_defs[i]; if (type_encodings) { @@ -595,7 +595,7 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) if (encodings) { qfot_type_t *type; - for (pointer_t type_ptr = 4; type_ptr < encodings->size; + for (pr_ptr_t type_ptr = 4; type_ptr < encodings->size; type_ptr += type->size) { type = &G_STRUCT (pr, qfot_type_t, type_encodings + type_ptr); if (type->meta == ty_basic @@ -968,12 +968,12 @@ get_type (prdeb_resources_t *res, int typeptr) } pr_def_t * -PR_Get_Local_Def (progs_t *pr, pointer_t *offset) +PR_Get_Local_Def (progs_t *pr, pr_ptr_t *offset) { prdeb_resources_t *res = pr->pr_debug_resources; dfunction_t *func; pr_auxfunction_t *aux_func; - pointer_t offs = *offset; + pr_ptr_t offs = *offset; pr_def_t *def; if (!pr->pr_xfunction) @@ -1102,7 +1102,7 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) } static pr_def_t * -pr_debug_find_def (progs_t *pr, pointer_t *ofs) +pr_debug_find_def (progs_t *pr, pr_ptr_t *ofs) { prdeb_resources_t *res = pr->pr_debug_resources; pr_def_t *def = 0; @@ -1123,7 +1123,7 @@ pr_debug_find_def (progs_t *pr, pointer_t *ofs) } static const char * -global_string (pr_debug_data_t *data, pointer_t offset, qfot_type_t *type, +global_string (pr_debug_data_t *data, pr_ptr_t offset, qfot_type_t *type, int contents) { progs_t *pr = data->pr; @@ -1132,7 +1132,7 @@ global_string (pr_debug_data_t *data, pointer_t offset, qfot_type_t *type, pr_def_t *def = NULL; qfot_type_t dummy_type = { }; const char *name = 0; - pointer_t offs = offset; + pr_ptr_t offs = offset; dstring_clearstr (dstr); @@ -1198,7 +1198,7 @@ pr_debug_string_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - string_t string = value->string_var; + pr_string_t string = value->string_var; if (PR_StringValid (data->pr, string)) { const char *str = PR_GetString (data->pr, string); @@ -1316,8 +1316,8 @@ pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - pointer_t offset = value->integer_var; - pointer_t offs = offset; + pr_ptr_t offset = value->integer_var; + pr_ptr_t offs = offset; pr_def_t *def = 0; def = pr_debug_find_def (pr, &offs); diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index a8585fc2b..53964982f 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -220,7 +220,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) { pr_int_t i; pr_type_t *dstParams[MAX_PARMS]; - pointer_t paramofs = 0; + pr_ptr_t paramofs = 0; if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Entering function %s\n", @@ -338,9 +338,9 @@ PR_LeaveFunction (progs_t *pr, int to_engine) } VISIBLE void -PR_BoundsCheckSize (progs_t *pr, pointer_t addr, unsigned size) +PR_BoundsCheckSize (progs_t *pr, pr_ptr_t addr, unsigned size) { - if (addr < (pointer_t) (pr->pr_return - pr->pr_globals)) + if (addr < (pr_ptr_t) (pr->pr_return - pr->pr_globals)) PR_RunError (pr, "null pointer access"); if (addr >= pr->globals_size || size > (unsigned) (pr->globals_size - addr)) @@ -447,7 +447,7 @@ PR_CallFunction (progs_t *pr, func_t fnum, pr_type_t *return_ptr) } static void -check_stack_pointer (progs_t *pr, pointer_t stack, int size) +check_stack_pointer (progs_t *pr, pr_ptr_t stack, int size) { if (stack < pr->stack_bottom) { PR_RunError (pr, "Progs stack overflow"); @@ -1070,7 +1070,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_PUSH_I_v6p: case OP_PUSH_P_v6p: { - pointer_t stack = *pr->globals.stack - 1; + pr_ptr_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); @@ -1081,7 +1081,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_PUSH_V_v6p: { - pointer_t stack = *pr->globals.stack - 3; + pr_ptr_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); @@ -1092,7 +1092,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_PUSH_Q_v6p: { - pointer_t stack = *pr->globals.stack - 4; + pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); @@ -1110,7 +1110,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_PUSHB_I_v6p: case OP_PUSHB_P_v6p: { - pointer_t stack = *pr->globals.stack - 1; + pr_ptr_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + OPB(int); @@ -1127,7 +1127,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_PUSHB_V_v6p: { - pointer_t stack = *pr->globals.stack - 3; + pr_ptr_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + OPB(int); @@ -1144,7 +1144,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_PUSHB_Q_v6p: { - pointer_t stack = *pr->globals.stack - 4; + pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + OPB(int); @@ -1168,7 +1168,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_PUSHBI_I_v6p: case OP_PUSHBI_P_v6p: { - pointer_t stack = *pr->globals.stack - 1; + pr_ptr_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + st->b; @@ -1185,7 +1185,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_PUSHBI_V_v6p: { - pointer_t stack = *pr->globals.stack - 3; + pr_ptr_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + st->b; @@ -1202,7 +1202,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_PUSHBI_Q_v6p: { - pointer_t stack = *pr->globals.stack - 4; + pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + st->b; @@ -1226,7 +1226,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_POP_I_v6p: case OP_POP_P_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); @@ -1237,7 +1237,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_POP_V_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); @@ -1248,7 +1248,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_POP_Q_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); @@ -1266,7 +1266,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_POPB_I_v6p: case OP_POPB_P_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + OPB(int); @@ -1283,7 +1283,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_POPB_V_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + OPB(int); @@ -1300,7 +1300,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_POPB_Q_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + OPB(int); @@ -1324,7 +1324,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_POPBI_I_v6p: case OP_POPBI_P_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + st->b; @@ -1341,7 +1341,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_POPBI_V_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + st->b; @@ -1358,7 +1358,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_POPBI_Q_v6p: { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(int) + st->b; @@ -1670,16 +1670,16 @@ op_call: break; case OP_MEMSETP_v6p: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC(pointer), OPB(int)); + PR_BoundsCheckSize (pr, OPC(ptr), OPB(int)); } - pr_memset (pr->pr_globals + OPC(pointer), OPA(int), + pr_memset (pr->pr_globals + OPC(ptr), OPA(int), OPB(int)); break; case OP_MEMSETPI_v6p: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC(pointer), st->b); + PR_BoundsCheckSize (pr, OPC(ptr), st->b); } - pr_memset (pr->pr_globals + OPC(pointer), OPA(int), + pr_memset (pr->pr_globals + OPC(ptr), OPA(int), st->b); break; case OP_GE_D_v6p: @@ -1754,7 +1754,7 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) { pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); - pointer_t mm_offs = 0; + pr_ptr_t mm_offs = 0; switch (mm_ind) { case 0: @@ -1775,7 +1775,7 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 4: // entity.field (equivalent to OP_LOAD_t_v6p) - pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; mm_offs = edict_area + OPA(uint) + OPB(uint); break; } @@ -1787,7 +1787,7 @@ pr_return_mode (progs_t *pr, const dstatement_t *st, int mm_ind) { pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); - pointer_t mm_offs = 0; + pr_ptr_t mm_offs = 0; switch (mm_ind) { case 0: @@ -1808,7 +1808,7 @@ pr_return_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 4: // entity.field (equivalent to OP_LOAD_t_v6p) - pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; mm_offs = edict_area + OPA(uint) + OPB(uint); break; } @@ -1820,7 +1820,7 @@ pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind) { pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); - pointer_t mm_offs = 0; + pr_ptr_t mm_offs = 0; switch (mm_ind) { case 1: @@ -1837,19 +1837,19 @@ pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 4: // entity.field (equivalent to OP_LOAD_t_v6p) - pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; mm_offs = edict_area + OPA(uint) + OPB(uint); break; } return pr->pr_globals + mm_offs; } -static pr_pointer_t __attribute__((pure)) +static pr_ptr_t __attribute__((pure)) pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind) { pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); - pointer_t jump_offs = pr->pr_xstatement; + pr_ptr_t jump_offs = pr->pr_xstatement; switch (jump_ind) { case 0: @@ -1879,7 +1879,7 @@ static pr_type_t * pr_stack_push (progs_t *pr) { // keep the stack 16-byte aligned - pointer_t stack = *pr->globals.stack - 4; + pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); @@ -1891,7 +1891,7 @@ pr_stack_push (progs_t *pr) static pr_type_t * pr_stack_pop (progs_t *pr) { - pointer_t stack = *pr->globals.stack; + pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); @@ -1904,7 +1904,7 @@ pr_stack_pop (progs_t *pr) static void pr_with (progs_t *pr, const dstatement_t *st) { - pointer_t edict_area = pr->pr_edict_area - pr->pr_globals; + pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; pr_type_t *op_b = pr->pr_globals + PR_BASE (pr, st, B) + st->b; pr_type_t *stk; pr_uint_t *base = &pr->pr_bases[st->c & 3]; @@ -1933,7 +1933,7 @@ pr_with (progs_t *pr, const dstatement_t *st) *base = pr->pr_globals[st->b].pointer_var; return; case 5: - *base = OPB(pointer); + *base = OPB(ptr); return; case 6: // relative to stack (-ve offset) @@ -2755,9 +2755,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) } } - pointer_t st_a = st->a + PR_BASE (pr, st, A); - pointer_t st_b = st->b + PR_BASE (pr, st, B); - pointer_t st_c = st->c + PR_BASE (pr, st, C); + pr_ptr_t st_a = st->a + PR_BASE (pr, st, A); + pr_ptr_t st_b = st->b + PR_BASE (pr, st, B); + pr_ptr_t st_c = st->c + PR_BASE (pr, st, C); pr_type_t *op_a = pr->pr_globals + st_a; diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index c0c090016..299f8d2ae 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -44,7 +44,7 @@ static const char param_str[] = ".param_0"; pr_def_t * -PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset) +PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pr_ptr_t offset) { // fuzzy bsearh unsigned left = 0; @@ -69,13 +69,13 @@ PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pointer_t offset) } pr_def_t * -PR_GlobalAtOfs (progs_t * pr, pointer_t ofs) +PR_GlobalAtOfs (progs_t * pr, pr_ptr_t ofs) { return PR_SearchDefs (pr->pr_globaldefs, pr->progs->numglobaldefs, ofs); } VISIBLE pr_def_t * -PR_FieldAtOfs (progs_t * pr, pointer_t ofs) +PR_FieldAtOfs (progs_t * pr, pr_ptr_t ofs) { return PR_SearchDefs (pr->pr_fielddefs, pr->progs->numfielddefs, ofs); } diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index f2e5237a6..3c75984d2 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -164,7 +164,7 @@ free_string_ref (prstr_resources_t *res, strref_t *sr) res->free_string_refs = sr; } -static __attribute__((pure)) string_t +static __attribute__((pure)) pr_string_t string_index (prstr_resources_t *res, strref_t *sr) { long o = (long) (sr - res->static_strings); @@ -309,7 +309,7 @@ requeue_strref (prstr_resources_t *res, strref_t *sr) } static inline strref_t * -get_strref (prstr_resources_t *res, string_t num) +get_strref (prstr_resources_t *res, pr_string_t num) { if (num < 0) { strref_t *ref; @@ -328,7 +328,7 @@ get_strref (prstr_resources_t *res, string_t num) } static inline __attribute__((pure)) const char * -get_string (progs_t *pr, string_t num) +get_string (progs_t *pr, pr_string_t num) { __auto_type res = pr->pr_string_resources; if (num < 0) { @@ -356,7 +356,7 @@ get_string (progs_t *pr, string_t num) } VISIBLE qboolean -PR_StringValid (progs_t *pr, string_t num) +PR_StringValid (progs_t *pr, pr_string_t num) { if (num >= 0) { return num < pr->pr_stringsize; @@ -365,7 +365,7 @@ PR_StringValid (progs_t *pr, string_t num) } VISIBLE qboolean -PR_StringMutable (progs_t *pr, string_t num) +PR_StringMutable (progs_t *pr, pr_string_t num) { strref_t *sr; if (num >= 0) { @@ -376,7 +376,7 @@ PR_StringMutable (progs_t *pr, string_t num) } VISIBLE const char * -PR_GetString (progs_t *pr, string_t num) +PR_GetString (progs_t *pr, pr_string_t num) { const char *str; @@ -387,7 +387,7 @@ PR_GetString (progs_t *pr, string_t num) } VISIBLE dstring_t * -PR_GetMutableString (progs_t *pr, string_t num) +PR_GetMutableString (progs_t *pr, pr_string_t num) { strref_t *ref = get_strref (pr->pr_string_resources, num); if (ref) { @@ -424,7 +424,7 @@ pr_strdup (progs_t *pr, const char *s) return new; } -VISIBLE string_t +VISIBLE pr_string_t PR_SetString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -443,7 +443,7 @@ PR_SetString (progs_t *pr, const char *s) return string_index (res, sr); } -VISIBLE string_t +VISIBLE pr_string_t PR_FindString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -459,7 +459,7 @@ PR_FindString (progs_t *pr, const char *s) return 0; } -VISIBLE string_t +VISIBLE pr_string_t PR_SetReturnString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -499,7 +499,7 @@ PR_SetReturnString (progs_t *pr, const char *s) return string_index (res, sr); } -static inline string_t +static inline pr_string_t pr_settempstring (progs_t *pr, prstr_resources_t *res, char *s) { strref_t *sr; @@ -512,7 +512,7 @@ pr_settempstring (progs_t *pr, prstr_resources_t *res, char *s) return string_index (res, sr); } -VISIBLE string_t +VISIBLE pr_string_t PR_CatStrings (progs_t *pr, const char *a, const char *b) { size_t lena; @@ -528,7 +528,7 @@ PR_CatStrings (progs_t *pr, const char *a, const char *b) return pr_settempstring (pr, pr->pr_string_resources, c); } -VISIBLE string_t +VISIBLE pr_string_t PR_SetTempString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -544,7 +544,7 @@ PR_SetTempString (progs_t *pr, const char *s) return pr_settempstring (pr, res, pr_strdup (pr, s)); } -VISIBLE string_t +VISIBLE pr_string_t PR_AllocTempBlock (progs_t *pr, size_t size) { prstr_resources_t *res = pr->pr_string_resources; @@ -552,7 +552,7 @@ PR_AllocTempBlock (progs_t *pr, size_t size) } VISIBLE void -PR_PushTempString (progs_t *pr, string_t num) +PR_PushTempString (progs_t *pr, pr_string_t num) { prstr_resources_t *res = pr->pr_string_resources; strref_t *ref = get_strref (res, num); @@ -572,7 +572,7 @@ PR_PushTempString (progs_t *pr, string_t num) PR_Error (pr, "attempt to push stale temp string"); } -VISIBLE string_t +VISIBLE pr_string_t PR_SetDynamicString (progs_t *pr, const char *s) { prstr_resources_t *res = pr->pr_string_resources; @@ -592,7 +592,7 @@ PR_SetDynamicString (progs_t *pr, const char *s) } VISIBLE void -PR_MakeTempString (progs_t *pr, string_t str) +PR_MakeTempString (progs_t *pr, pr_string_t str) { prstr_resources_t *res = pr->pr_string_resources; strref_t *sr = get_strref (res, str); @@ -613,7 +613,7 @@ PR_MakeTempString (progs_t *pr, string_t str) pr->pr_xtstr = sr; } -VISIBLE string_t +VISIBLE pr_string_t PR_NewMutableString (progs_t *pr) { prstr_resources_t *res = pr->pr_string_resources; @@ -624,7 +624,7 @@ PR_NewMutableString (progs_t *pr) } VISIBLE void -PR_HoldString (progs_t *pr, string_t str) +PR_HoldString (progs_t *pr, pr_string_t str) { prstr_resources_t *res = pr->pr_string_resources; strref_t *sr = get_strref (res, str); @@ -654,7 +654,7 @@ PR_HoldString (progs_t *pr, string_t str) } VISIBLE void -PR_FreeString (progs_t *pr, string_t str) +PR_FreeString (progs_t *pr, pr_string_t str) { prstr_resources_t *res = pr->pr_string_resources; strref_t *sr = get_strref (res, str); diff --git a/libs/gamecode/test/head.c b/libs/gamecode/test/head.c index 07921d847..78410dfe5 100644 --- a/libs/gamecode/test/head.c +++ b/libs/gamecode/test/head.c @@ -29,8 +29,8 @@ static int verbose = 0; typedef struct { const char *desc; - pointer_t edict_area; - pointer_t stack_size; + pr_ptr_t edict_area; + pr_uint_t stack_size; pr_uint_t extra_globals; pr_uint_t num_globals; pr_uint_t num_statements; diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 7a565dece..c9c34be53 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -109,9 +109,9 @@ setup_test (test_t *test) memset (test_pr.pr_globals + test->num_globals, 0, test->extra_globals * sizeof (pr_type_t)); if (test->stack_size) { - pointer_t stack = num_globals - test->stack_size; + pr_ptr_t stack = num_globals - test->stack_size; test_pr.stack_bottom = stack + 4; - test_pr.globals.stack = (pointer_t *) (test_pr.pr_globals + stack); + test_pr.globals.stack = (pr_ptr_t *) (test_pr.pr_globals + stack); *test_pr.globals.stack = num_globals; } if (test->edict_area) { diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 6448e0b1c..4c8b86049 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -53,7 +53,7 @@ typedef struct bi_hashtab_s { func_t gh; func_t cmp; func_t f; - pointer_t ud; + pr_ptr_t ud; } bi_hashtab_t; typedef struct { diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 3cd3156a2..8fefa5fa9 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -47,7 +47,7 @@ typedef struct rua_in_cookie_s { size_t users; progs_t *pr; func_t func; - pointer_t data; + pr_ptr_t data; } rua_in_cookie_t; typedef struct input_resources_s { @@ -193,7 +193,7 @@ bi_IN_GetButtonInfo (progs_t *pr) } static rua_in_cookie_t * -make_cookie (progs_t *pr, func_t func, pointer_t data) +make_cookie (progs_t *pr, func_t func, pr_ptr_t data) { input_resources_t *res = PR_Resources_Find (pr, "input"); rua_in_cookie_t search = { @@ -212,7 +212,7 @@ make_cookie (progs_t *pr, func_t func, pointer_t data) } static rua_in_cookie_t * -find_cookie (progs_t *pr, func_t func, pointer_t data) +find_cookie (progs_t *pr, func_t func, pr_ptr_t data) { input_resources_t *res = PR_Resources_Find (pr, "input"); rua_in_cookie_t search = { diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 22a8b98e7..fafc4fe85 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -76,7 +76,7 @@ typedef struct probj_resources_s { unsigned selector_index; unsigned selector_index_max; obj_list **selector_sels; - string_t *selector_names; + pr_string_t *selector_names; PR_RESMAP (dtable_t) dtables; dtable_t *dtable_list; func_t obj_forward; @@ -423,7 +423,7 @@ object_is_instance (probj_t *probj, pr_id_t *object) return 0; } -static string_t +static pr_string_t object_get_class_name (probj_t *probj, pr_id_t *object) { progs_t *pr = probj->pr; @@ -446,7 +446,7 @@ object_get_class_name (probj_t *probj, pr_id_t *object) //==================================================================== static void -finish_class (probj_t *probj, pr_class_t *class, pointer_t object_ptr) +finish_class (probj_t *probj, pr_class_t *class, pr_ptr_t object_ptr) { progs_t *pr = probj->pr; pr_class_t *meta = &G_STRUCT (pr, pr_class_t, class->class_pointer); @@ -463,7 +463,7 @@ finish_class (probj_t *probj, pr_class_t *class, pointer_t object_ptr) meta->super_class = val->class_pointer; class->super_class = PR_SetPointer (pr, val); } else { - pointer_t *ml = &meta->methods; + pr_ptr_t *ml = &meta->methods; while (*ml) ml = &G_STRUCT (pr, pr_method_list_t, *ml).method_next; *ml = class->methods; @@ -485,7 +485,7 @@ add_sel_name (probj_t *probj, const char *name) probj->selector_sels = realloc (probj->selector_sels, size * sizeof (obj_list *)); probj->selector_names = realloc (probj->selector_names, - size * sizeof (string_t)); + size * sizeof (pr_string_t)); for (i = probj->selector_index_max; i < size; i++) { probj->selector_sels[i] = 0; probj->selector_names[i] = 0; @@ -805,7 +805,7 @@ obj_find_message (probj_t *probj, pr_class_t *class, pr_sel_t *selector) pr_sel_t *sel; int i; int dev = developer->int_val; - string_t *names; + pr_string_t *names; if (dev & SYS_rua_msg) { names = probj->selector_names; @@ -1041,7 +1041,7 @@ obj_verror (probj_t *probj, pr_id_t *object, int code, const char *fmt, int coun } static void -dump_ivars (probj_t *probj, pointer_t _ivars) +dump_ivars (probj_t *probj, pr_ptr_t _ivars) { progs_t *pr = probj->pr; pr_ivar_list_t *ivars; @@ -1063,8 +1063,8 @@ obj_init_statics (probj_t *probj) { progs_t *pr = probj->pr; obj_list **cell = &probj->uninitialized_statics; - pointer_t *ptr; - pointer_t *inst; + pr_ptr_t *ptr; + pr_ptr_t *inst; Sys_MaskPrintf (SYS_rua_obj, "Initializing statics\n"); while (*cell) { @@ -1110,7 +1110,7 @@ rua___obj_exec_class (progs_t *pr) pr_module_t *module = &P_STRUCT (pr, pr_module_t, 0); pr_symtab_t *symtab; pr_sel_t *sel; - pointer_t *ptr; + pr_ptr_t *ptr; int i; obj_list **cell; @@ -1216,7 +1216,7 @@ rua___obj_exec_class (progs_t *pr) if (*ptr) { Sys_MaskPrintf (SYS_rua_obj, "Static instances lists: %x\n", *ptr); probj->uninitialized_statics - = list_cons (&G_STRUCT (pr, pointer_t, *ptr), + = list_cons (&G_STRUCT (pr, pr_ptr_t, *ptr), probj->uninitialized_statics); } if (probj->uninitialized_statics) { @@ -1275,7 +1275,7 @@ rua___obj_forward (progs_t *pr) //FIXME oh for a stack size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); size_t size = pr->pr_argc * parm_size; - string_t args_block = PR_AllocTempBlock (pr, size); + pr_string_t args_block = PR_AllocTempBlock (pr, size); int argc = pr->pr_argc; __auto_type argv = (pr_type_t *) PR_GetString (pr, args_block); @@ -1402,9 +1402,9 @@ static void rua_obj_msg_sendv (progs_t *pr) { probj_t *probj = pr->pr_objective_resources; - pointer_t obj = P_POINTER (pr, 0); + pr_ptr_t obj = P_POINTER (pr, 0); pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0); - pointer_t sel = P_POINTER (pr, 1); + pr_ptr_t sel = P_POINTER (pr, 1); pr_sel_t *op = &P_STRUCT (pr, pr_sel_t, 1); func_t imp = obj_msg_lookup (probj, receiver, op); @@ -1679,12 +1679,12 @@ rua_class_pose_as (progs_t *pr) { pr_class_t *impostor = &P_STRUCT (pr, pr_class_t, 0); pr_class_t *superclass = &P_STRUCT (pr, pr_class_t, 1); - pointer_t *subclass; + pr_ptr_t *subclass; subclass = &superclass->subclass_list; while (*subclass) { pr_class_t *sub = &P_STRUCT (pr, pr_class_t, *subclass); - pointer_t nextSub = sub->sibling_class; + pr_ptr_t nextSub = sub->sibling_class; if (sub != impostor) { sub->sibling_class = impostor->subclass_list; sub->super_class = P_POINTER (pr, 0); // impostor @@ -2157,7 +2157,7 @@ rua_init_finish (progs_t *pr) class_list = (pr_class_t **) Hash_GetList (probj->classes); if (*class_list) { pr_class_t *object_class; - pointer_t object_ptr; + pr_ptr_t object_ptr; object_class = Hash_Find (probj->classes, "Object"); if (object_class && !object_class->super_class) @@ -2249,7 +2249,7 @@ RUA_Obj_Init (progs_t *pr, int secure) } func_t -RUA_Obj_msg_lookup (progs_t *pr, pointer_t _self, pointer_t __cmd) +RUA_Obj_msg_lookup (progs_t *pr, pr_ptr_t _self, pr_ptr_t __cmd) { probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &G_STRUCT (pr, pr_id_t, _self); diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index 8c6c45ef1..55e36acd1 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -213,7 +213,7 @@ bi_Qreadstring (progs_t *pr) int handle = P_INT (pr, 0); int len = P_INT (pr, 1); qfile_t *h = get_handle (pr, __FUNCTION__, handle); - string_t str = PR_NewMutableString (pr); + pr_string_t str = PR_NewMutableString (pr); dstring_t *dstr = PR_GetMutableString (pr, str); dstr->size = len + 1; diff --git a/libs/ruamoko/rua_qfs.c b/libs/ruamoko/rua_qfs.c index 4a3eebb59..c29dc3ec8 100644 --- a/libs/ruamoko/rua_qfs.c +++ b/libs/ruamoko/rua_qfs.c @@ -45,7 +45,7 @@ typedef struct { int count; - pointer_t list; + pr_ptr_t list; } qfslist_t; static void @@ -155,7 +155,7 @@ bi_QFS_Filelist (progs_t *pr) { filelist_t *filelist = QFS_FilelistNew (); qfslist_t *list; - string_t *strings; + pr_string_t *strings; int i; QFS_FilelistFill (filelist, P_GSTRING (pr, 0), P_GSTRING (pr, 1), @@ -163,7 +163,7 @@ bi_QFS_Filelist (progs_t *pr) list = PR_Zone_Malloc (pr, sizeof (list) + filelist->count * 4); list->count = filelist->count; - strings = (string_t *) (list + 1); + strings = (pr_string_t *) (list + 1); list->list = PR_SetPointer (pr, strings); for (i = 0; i < filelist->count; i++) strings[i] = PR_SetDynamicString (pr, filelist->list[i]); @@ -174,7 +174,7 @@ static void bi_QFS_FilelistFree (progs_t *pr) { qfslist_t *list = &P_STRUCT (pr, qfslist_t, 0); - string_t *strings = &G_STRUCT (pr, string_t, list->list); + pr_string_t *strings = &G_STRUCT (pr, pr_string_t, list->list); int i; for (i = 0; i < list->count; i++) diff --git a/libs/ruamoko/rua_runtime.c b/libs/ruamoko/rua_runtime.c index 24a8a894d..3fe21db51 100644 --- a/libs/ruamoko/rua_runtime.c +++ b/libs/ruamoko/rua_runtime.c @@ -56,7 +56,7 @@ bi_va_copy (progs_t *pr) __auto_type src_list = &G_STRUCT (pr, pr_type_t, src_args->list); size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); size_t size = src_args->count * parm_size; - string_t dst_list_block = 0; + pr_string_t dst_list_block = 0; pr_type_t *dst_list = 0; if (size) { diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index 4723bfcbe..cfb9a7e9a 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -46,7 +46,7 @@ typedef struct { script_t script; - string_t dstr; + pr_string_t dstr; progs_t *pr; } rua_script_t; diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index cc7ce9735..632a6a10a 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -432,8 +432,8 @@ bi_i_SetIterator__element (progs_t *pr) static void bi_i_Set__add_ (progs_t *pr) { - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); PR_RESET_PARAMS (pr); P_INT (pr, 0) = set_obj->set; @@ -445,8 +445,8 @@ bi_i_Set__add_ (progs_t *pr) static void bi_i_Set__remove_ (progs_t *pr) { - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); PR_RESET_PARAMS (pr); P_INT (pr, 0) = set_obj->set; @@ -458,8 +458,8 @@ bi_i_Set__remove_ (progs_t *pr) static void bi_i_Set__invert (progs_t *pr) { - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); PR_RESET_PARAMS (pr); P_INT (pr, 0) = set_obj->set; @@ -470,8 +470,8 @@ bi_i_Set__invert (progs_t *pr) static void bi_i_Set__union_ (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); PR_RESET_PARAMS (pr); @@ -484,9 +484,9 @@ bi_i_Set__union_ (progs_t *pr) static void bi_i_Set__intersection_ (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); PR_RESET_PARAMS (pr); P_INT (pr, 0) = dst_obj->set; @@ -498,9 +498,9 @@ bi_i_Set__intersection_ (progs_t *pr) static void bi_i_Set__difference_ (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); PR_RESET_PARAMS (pr); P_INT (pr, 0) = dst_obj->set; @@ -512,9 +512,9 @@ bi_i_Set__difference_ (progs_t *pr) static void bi_i_Set__reverse_difference_ (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); PR_RESET_PARAMS (pr); P_INT (pr, 0) = dst_obj->set; @@ -526,9 +526,9 @@ bi_i_Set__reverse_difference_ (progs_t *pr) static void bi_i_Set__assign_ (progs_t *pr) { - pointer_t dst_ptr = P_POINTER (pr, 0); - pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_ptr_t dst_ptr = P_POINTER (pr, 0); + pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); PR_RESET_PARAMS (pr); P_INT (pr, 0) = dst_obj->set; @@ -540,8 +540,8 @@ bi_i_Set__assign_ (progs_t *pr) static void bi_i_Set__empty (progs_t *pr) { - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); PR_RESET_PARAMS (pr); P_INT (pr, 0) = set_obj->set; @@ -552,8 +552,8 @@ bi_i_Set__empty (progs_t *pr) static void bi_i_Set__everything (progs_t *pr) { - pointer_t set_ptr = P_POINTER (pr, 0); - pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); + pr_ptr_t set_ptr = P_POINTER (pr, 0); + pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); PR_RESET_PARAMS (pr); P_INT (pr, 0) = set_obj->set; diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 754d1627e..c808ae963 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -108,7 +108,7 @@ bi_str_free (progs_t *pr) static void bi_str_hold (progs_t *pr) { - string_t str = P_STRING (pr, 0); + pr_string_t str = P_STRING (pr, 0); PR_HoldString (pr, str); R_STRING (pr) = str; } diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 0d0ea9635..975515eb0 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -44,8 +44,8 @@ typedef struct { float *time; float *frametime; float *force_retouch; - string_t *mapname; - string_t *startspot; + pr_string_t *mapname; + pr_string_t *startspot; float *deathmatch; float *coop; float *teamplay; @@ -68,7 +68,7 @@ typedef struct { float *trace_inopen; float *trace_inwater; pr_uint_t *msg_entity; - string_t *null; + pr_string_t *null; pr_uint_t *newmis; } sv_globals_t; @@ -106,8 +106,8 @@ typedef struct pr_int_t angles; //vec3_t pr_int_t avelocity; //vec3_t pr_int_t punchangle; //vec3_t - pr_int_t classname; //string_t - pr_int_t model; //string_t + pr_int_t classname; //pr_string_t + pr_int_t model; //pr_string_t pr_int_t frame; //float pr_int_t skin; //float pr_int_t effects; //float @@ -123,7 +123,7 @@ typedef struct pr_int_t health; //float pr_int_t frags; //float pr_int_t weapon; //float - pr_int_t weaponmodel; //string_t + pr_int_t weaponmodel; //pr_string_t pr_int_t weaponframe; //float pr_int_t currentammo; //float pr_int_t ammo_shells; //float @@ -142,7 +142,7 @@ typedef struct pr_int_t fixangle; //float pr_int_t v_angle; //vec3_t pr_int_t idealpitch; //float - pr_int_t netname; //string_t + pr_int_t netname; //pr_string_t pr_int_t enemy; //int pr_int_t flags; //float pr_int_t colormap; //float @@ -160,7 +160,7 @@ typedef struct pr_int_t dmg_inflictor; //int pr_int_t owner; //int pr_int_t movedir; //vec3_t - pr_int_t message; //string_t + pr_int_t message; //pr_string_t pr_int_t sounds; //float pr_int_t rotated_bbox; //int diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index d0c04e2e0..c3391e2fb 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -45,7 +45,7 @@ typedef struct { float *frametime; pr_uint_t *newmis; float *force_retouch; - string_t *mapname; + pr_string_t *mapname; float *serverflags; float *total_secrets; float *total_monsters; @@ -108,8 +108,8 @@ typedef struct pr_int_t velocity; //vec3_t pr_int_t angles; //vec3_t pr_int_t avelocity; //vec3_t - pr_int_t classname; //string_t - pr_int_t model; //string_t + pr_int_t classname; //pr_string_t + pr_int_t model; //pr_string_t pr_int_t frame; //float pr_int_t skin; //float pr_int_t effects; //float @@ -124,7 +124,7 @@ typedef struct pr_int_t health; //float pr_int_t frags; //float pr_int_t weapon; //float - pr_int_t weaponmodel; //string_t + pr_int_t weaponmodel; //pr_string_t pr_int_t weaponframe; //float pr_int_t currentammo; //float pr_int_t ammo_shells; //float @@ -141,7 +141,7 @@ typedef struct pr_int_t impulse; //float pr_int_t fixangle; //float pr_int_t v_angle; //vec3_t - pr_int_t netname; //string_t + pr_int_t netname; //pr_string_t pr_int_t enemy; //int pr_int_t flags; //float pr_int_t colormap; //float @@ -158,7 +158,7 @@ typedef struct pr_int_t dmg_save; //float pr_int_t dmg_inflictor; //int pr_int_t owner; //int - pr_int_t message; //string_t + pr_int_t message; //pr_string_t pr_int_t sounds; //float pr_int_t rotated_bbox; //int diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index e2ac3ffd2..19be9ac13 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -446,7 +446,7 @@ PF_putsaytime (progs_t *pr) static void PF_makestr (progs_t *pr) { - string_t res = PR_NewMutableString (pr); + pr_string_t res = PR_NewMutableString (pr); dstring_t *dst = PR_GetMutableString (pr, res); const char *src = P_GSTRING (pr, 0); diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 56aaa818c..4fa0b0c98 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -204,7 +204,7 @@ static void qdb_set_trace (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); int state = P_INT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -216,7 +216,7 @@ static void qdb_set_breakpoint (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); unsigned staddr = P_INT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -234,7 +234,7 @@ static void qdb_clear_breakpoint (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); unsigned staddr = P_UINT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -251,8 +251,8 @@ static void qdb_set_watchpoint (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); - pointer_t offset = P_UINT (pr, 1); + pr_ptr_t handle = P_INT (pr, 0); + pr_ptr_t offset = P_UINT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -268,7 +268,7 @@ static void qdb_clear_watchpoint (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -280,7 +280,7 @@ static void qdb_continue (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); pthread_mutex_lock (&target->run_cond.mut); @@ -293,12 +293,12 @@ static void qdb_get_state (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; pr_lineno_t *lineno; pr_auxfunction_t *f; - string_t file = 0; + pr_string_t file = 0; unsigned line = 0; unsigned staddr = tpr->pr_xstatement; func_t func = 0; @@ -331,7 +331,7 @@ static void qdb_get_stack_depth (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -342,7 +342,7 @@ static void qdb_get_stack (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; int count = tpr->pr_depth; @@ -350,7 +350,7 @@ qdb_get_stack (progs_t *pr) R_POINTER (pr) = 0; if (count > 0) { size_t size = count * sizeof (qdb_stack_t); - string_t stack_block = PR_AllocTempBlock (pr, size); + pr_string_t stack_block = PR_AllocTempBlock (pr, size); __auto_type stack = (qdb_stack_t *) PR_GetString (pr, stack_block); for (int i = 0; i < count; i++) { @@ -366,7 +366,7 @@ static void qdb_get_event (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); __auto_type event = &P_STRUCT (pr, qdb_event_t, 1); @@ -400,12 +400,12 @@ static void qdb_get_data (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; - pointer_t srcoff = P_POINTER (pr, 1); + pr_ptr_t srcoff = P_POINTER (pr, 1); unsigned length = P_UINT (pr, 2); - pointer_t dstoff = P_POINTER(pr, 3); + pr_ptr_t dstoff = P_POINTER(pr, 3); pr_type_t *src = PR_GetPointer(tpr, srcoff); pr_type_t *dst = PR_GetPointer(pr, dstoff); @@ -426,10 +426,10 @@ static void qdb_get_string (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; - string_t string = P_STRING (pr, 1); + pr_string_t string = P_STRING (pr, 1); R_STRING (pr) = 0; if (PR_StringValid (tpr, string)) { @@ -441,7 +441,7 @@ static void qdb_get_file_path (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *file = P_GSTRING (pr, 1); @@ -466,7 +466,7 @@ static void qdb_find_string (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *str = P_GSTRING (pr, 1); @@ -478,7 +478,7 @@ static void qdb_find_global (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *name = P_GSTRING (pr, 1); @@ -498,7 +498,7 @@ static void qdb_find_field (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *name = P_GSTRING (pr, 1); @@ -536,7 +536,7 @@ static void qdb_find_function (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *name = P_GSTRING (pr, 1); @@ -549,7 +549,7 @@ static void qdb_get_function (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; pr_uint_t fnum = P_INT (pr, 1); @@ -583,7 +583,7 @@ static void qdb_find_auxfunction (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *name = P_GSTRING (pr, 1); @@ -601,7 +601,7 @@ static void qdb_get_auxfunction (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; pr_uint_t fnum = P_UINT (pr, 1); @@ -614,7 +614,7 @@ static void qdb_get_local_defs (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; pr_uint_t fnum = P_UINT (pr, 1); @@ -640,7 +640,7 @@ static void qdb_get_source_line_addr (progs_t *pr) { __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); - pointer_t handle = P_INT (pr, 0); + pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; const char *file = P_GSTRING (pr, 1); diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index f8d4c3a62..185998fde 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -239,7 +239,7 @@ spawn_progs (qwaq_thread_t *thread) { dfunction_t *dfunc; const char *name = 0; - string_t *pr_argv; + pr_string_t *pr_argv; int pr_argc = 1, i; progs_t *pr; diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index e9c1cedcf..bfc0d4f88 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -16,14 +16,14 @@ typedef enum { #define umax 0x7fffffff #endif -typedef string string_t; +typedef string pr_string_t; #endif typedef struct qdb_event_s { prdebug_t what; union { - string_t message; + pr_string_t message; unsigned function; int exit_code; }; @@ -32,7 +32,7 @@ typedef struct qdb_event_s { typedef struct qdb_state_s { unsigned staddr; unsigned func; - string_t file; + pr_string_t file; unsigned line; } qdb_state_t; diff --git a/ruamoko/qwaq/editor/editbuffer.h b/ruamoko/qwaq/editor/editbuffer.h index 8d42c6038..08a13d213 100644 --- a/ruamoko/qwaq/editor/editbuffer.h +++ b/ruamoko/qwaq/editor/editbuffer.h @@ -81,7 +81,7 @@ typedef struct eb_color_s { typedef struct qwaq_editbuffer_s { pr_id_t isa; - pointer_t buffer; + pr_ptr_t buffer; } qwaq_editbuffer_t; #endif//!__QFCC__ diff --git a/ruamoko/qwaq/qwaq-input.h b/ruamoko/qwaq/qwaq-input.h index f385917e5..959015a33 100644 --- a/ruamoko/qwaq/qwaq-input.h +++ b/ruamoko/qwaq/qwaq-input.h @@ -9,20 +9,20 @@ typedef struct qwaq_devinfo_s { string name; string id; #else - string_t name; - string_t id; + pr_string_t name; + pr_string_t id; #endif int numaxes; #ifdef __QFCC__ in_axisinfo_t *axes; #else - pointer_t axes; + pr_ptr_t axes; #endif int numbuttons; #ifdef __QFCC__ in_axisinfo_t *buttons; #else - pointer_t buttons; + pr_ptr_t buttons; #endif } qwaq_devinfo_t; diff --git a/ruamoko/qwaq/ui/event.h b/ruamoko/qwaq/ui/event.h index 8a9f3c608..571e256f6 100644 --- a/ruamoko/qwaq/ui/event.h +++ b/ruamoko/qwaq/ui/event.h @@ -74,8 +74,8 @@ typedef union qwaq_message_s { void *pointer_val; string string_val; #else - pointer_t pointer_val; - string_t string_val; + pr_ptr_t pointer_val; + pr_string_t string_val; #endif } qwaq_message_t; diff --git a/ruamoko/qwaq/ui/textcontext.h b/ruamoko/qwaq/ui/textcontext.h index d73a9895c..168a7b9c0 100644 --- a/ruamoko/qwaq/ui/textcontext.h +++ b/ruamoko/qwaq/ui/textcontext.h @@ -65,7 +65,7 @@ typedef struct qwaq_textcontext_s { pr_id_t isa; - pointer_t window; + pr_ptr_t window; union { Rect rect; struct { diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index c03b221ef..f49dd2f8e 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -98,7 +98,7 @@ typedef struct def_s { unsigned system:1; ///< system def unsigned nosave:1; ///< don't set DEF_SAVEGLOBAL - string_t file; ///< declaring/defining source file + pr_string_t file; ///< declaring/defining source file int line; ///< declaring/defining source line int qfo_def; ///< index to def in qfo defs diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 59ac358e4..61ff0b7ca 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -243,7 +243,7 @@ typedef struct expr_s { struct expr_s *next; ///< the next expression in a block expression expr_type type; ///< the type of the result of this expression int line; ///< source line that generated this expression - string_t file; ///< source file that generated this expression + pr_string_t file; ///< source file that generated this expression int printid; ///< avoid duplicate output when printing unsigned paren:1; ///< the expression is enclosed in () unsigned rvalue:1; ///< the expression is on the right side of = diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 986f513eb..4f8fa83e7 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -53,7 +53,7 @@ typedef struct overloaded_function_s { ///< encoding const struct type_s *type; ///< type of this function int overloaded; ///< is this function overloaded - string_t file; ///< source file of the function + pr_string_t file; ///< source file of the function int line; ///< source line of this function } overloaded_function_t; @@ -66,8 +66,8 @@ typedef struct function_s { int function_num; int line_info; int local_defs; - string_t s_file; ///< source file with definition - string_t s_name; ///< name of function in output + pr_string_t s_file; ///< source file with definition + pr_string_t s_name; ///< name of function in output const struct type_s *type; ///< function's type without aliases int temp_num; ///< number for next temp var struct def_s *temp_defs[4]; ///< freed temp vars (by size) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 8d6c40a22..2aec16095 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -97,16 +97,16 @@ typedef struct qfo_space_s { /** Representation of a def in the object file. */ typedef struct qfo_def_s { - pointer_t type; ///< offset in type space - string_t name; ///< def name - pointer_t offset; ///< def offset (address) + pr_ptr_t type; ///< offset in type space + pr_string_t name; ///< def name + pr_ptr_t offset; ///< def offset (address) pr_uint_t relocs; ///< index of first reloc record pr_uint_t num_relocs; ///< number of reloc records pr_uint_t flags; ///< \ref qfcc_qfo_QFOD "QFOD flags" - string_t file; ///< source file name + pr_string_t file; ///< source file name pr_uint_t line; ///< source line number } qfo_def_t; ///@} @@ -180,9 +180,9 @@ typedef struct qfo_def_s { /** Representation of a function in the object file. */ typedef struct qfo_func_s { - string_t name; ///< function name - pointer_t type; ///< function type (in type data space) - string_t file; ///< source file name + pr_string_t name; ///< function name + pr_ptr_t type; ///< function type (in type data space) + pr_string_t file; ///< source file name pr_uint_t line; ///< source line number /** \name Function code location. @@ -367,7 +367,7 @@ enum { \param q pointer to ::qfo_t struct \param s space index \param o offset into object file data space - \return string_t lvalue + \return pr_string_t lvalue \hideinitializer */ diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index 4ac5e0ddb..c129e8271 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -45,7 +45,7 @@ typedef struct srcline_s srcline_t; struct srcline_s { srcline_t *next; - string_t source_file; + pr_string_t source_file; int source_line; }; @@ -79,7 +79,7 @@ typedef struct pr_info_s { struct symtab_s *entity_fields; srcline_t *srcline_stack; - string_t source_file; + pr_string_t source_file; int source_line; int error_count; diff --git a/tools/qfcc/include/reloc.h b/tools/qfcc/include/reloc.h index dc6e802c8..98c828e60 100644 --- a/tools/qfcc/include/reloc.h +++ b/tools/qfcc/include/reloc.h @@ -77,7 +77,7 @@ typedef struct reloc_s { ///< adjustment reloc_type type; ///< type type of relocation to perform int line; ///< current source line when creating reloc - string_t file; ///< current source file when creating reloc + pr_string_t file; ///< current source file when creating reloc const void *return_address; ///< for debugging } reloc_t; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 7858f82fa..99d6fbcb2 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -276,7 +276,7 @@ emit_static_instances_list (void) type_t *instance_lists_type; symbol_t *instance_lists_sym; def_t *instance_lists_def; - pointer_t *list; + pr_ptr_t *list; defspace_t *space; if (!static_instance_classes || !static_instances) { @@ -309,7 +309,7 @@ emit_static_instances_list (void) instance_lists_def->initialized = instance_lists_def->constant = 1; instance_lists_def->nosave = 1; - list = D_POINTER (pointer_t, instance_lists_def); + list = D_POINTER (pr_ptr_t, instance_lists_def); space = instance_lists_def->space; for (int i = 0; i < num_classes; i++, list++) { EMIT_DEF (space, *list, instance_lists[i]); diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 9169b42f9..6410fae1e 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -50,8 +50,8 @@ static void report_function (const expr_t *e) { static function_t *last_func = (function_t *)-1L; - static string_t last_file; - string_t file = pr.source_file; + static pr_string_t last_file; + pr_string_t file = pr.source_file; srcline_t *srcline; if (e) @@ -81,7 +81,7 @@ static __attribute__((format(PRINTF, 4, 0))) void format_message (dstring_t *message, const char *msg_type, const expr_t *e, const char *fmt, va_list args) { - string_t file = pr.source_file; + pr_string_t file = pr.source_file; int line = pr.source_line; const char *colon = fmt ? ": " : ""; diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index ff8f6d32f..f27f33d4b 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -65,7 +65,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) const char *type; pr_uint_t offset; const char *comment; - string_t string; + pr_string_t string; const char *str; int saveglobal; @@ -86,7 +86,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) break; case ev_string: string = G_INT (pr, offset); - // at runtime, strings can be negative (thus string_t is + // at runtime, strings can be negative (thus pr_string_t is // signed), but negative strings means they have been // dynamically allocated, thus a negative string index should // never appear in compiled code @@ -241,7 +241,7 @@ dump_functions (progs_t *pr) int start; const char *comment; pr_def_t *encodings_def; - pointer_t type_encodings = 0; + pr_ptr_t type_encodings = 0; encodings_def = PR_FindGlobal (pr, ".type_encodings"); if (encodings_def) { @@ -516,7 +516,7 @@ static const char *ty_meta_names[] = { static void dump_qfo_types (qfo_t *qfo, int base_address) { - pointer_t type_ptr; + pr_ptr_t type_ptr; qfot_type_t *type; const char *meta; int i, count; diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index 7ff66fabb..f021e48a3 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -52,7 +52,7 @@ typedef struct { const char *source_file; pr_uint_t source_line; pr_int_t first_statement; - pointer_t return_type; + pr_ptr_t return_type; pr_uint_t local_defs; pr_uint_t num_locals; pr_uint_t line_info; diff --git a/tools/qfcc/source/dump_modules.c b/tools/qfcc/source/dump_modules.c index 3897610b7..5f0f590f2 100644 --- a/tools/qfcc/source/dump_modules.c +++ b/tools/qfcc/source/dump_modules.c @@ -130,7 +130,7 @@ dump_protocol (progs_t *pr, pr_protocol_t *proto) { const char *protocol_name = ""; printf (" %x %x ", - (pointer_t) ((pr_int_t *) proto - (pr_int_t *) pr->pr_globals), + (pr_ptr_t) ((pr_int_t *) proto - (pr_int_t *) pr->pr_globals), proto->class_pointer); if (PR_StringValid (pr, proto->protocol_name)) protocol_name = PR_GetString (pr, proto->protocol_name); @@ -216,9 +216,9 @@ dump_category (progs_t *pr, pr_category_t *category) } static void -dump_static_instance_lists (progs_t *pr, pointer_t instance_lists) +dump_static_instance_lists (progs_t *pr, pr_ptr_t instance_lists) { - pointer_t *ptr = &G_STRUCT (pr, pointer_t, instance_lists); + pr_ptr_t *ptr = &G_STRUCT (pr, pr_ptr_t, instance_lists); printf (" static instance lists @ %x\n", instance_lists); while (*ptr) { @@ -245,7 +245,7 @@ static void dump_module (progs_t *pr, pr_module_t *module) { pr_symtab_t *symtab = &G_STRUCT (pr, pr_symtab_t, module->symtab); - pointer_t *ptr = symtab->defs; + pr_ptr_t *ptr = symtab->defs; pr_sel_t *sel = &G_STRUCT (pr, pr_sel_t, symtab->refs); int i; const char *module_name = ""; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index ae3f919dc..0b70c6ae4 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2551,7 +2551,7 @@ expr_t * build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) { int line = pr.source_line; - string_t file = pr.source_file; + pr_string_t file = pr.source_file; expr_t *if_expr; expr_t *tl = new_label_expr (); expr_t *fl = new_label_expr (); @@ -2610,7 +2610,7 @@ build_while_statement (int not, expr_t *test, expr_t *statement, expr_t *break_label, expr_t *continue_label) { int line = pr.source_line; - string_t file = pr.source_file; + pr_string_t file = pr.source_file; expr_t *l1 = new_label_expr (); expr_t *l2 = break_label; expr_t *while_expr; @@ -2650,7 +2650,7 @@ build_do_while_statement (expr_t *statement, int not, expr_t *test, { expr_t *l1 = new_label_expr (); int line = pr.source_line; - string_t file = pr.source_file; + pr_string_t file = pr.source_file; expr_t *do_while_expr; if (!statement) { @@ -2696,7 +2696,7 @@ build_for_statement (expr_t *init, expr_t *test, expr_t *next, expr_t *l1 = 0; expr_t *t; int line = pr.source_line; - string_t file = pr.source_file; + pr_string_t file = pr.source_file; expr_t *for_expr; if (next) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 948ac084f..cc34e79b6 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -245,7 +245,7 @@ defs_get_key (const void *_r, void *unused) int linker_add_string (const char *str) { - string_t new; + pr_string_t new; new = strpool_addstr (work_strings, str); work->spaces[qfo_strings_space].strings = work_strings->strings; work->spaces[qfo_strings_space].data_size = work_strings->size; @@ -875,7 +875,7 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass) // while we're at it, relocate all references in the type encoding // space so the type encodings are always correct. if (reloc->type == rel_def_string) { - string_t str; + pr_string_t str; str = linker_add_string (QFOSTR (qfo, reloc->target)); QFO_STRING (work, reloc->space, reloc->offset) = str; } else if (reloc->type == rel_def_def || reloc->type == -1) { diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 2082fe8ca..eed5de4ce 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -678,7 +678,7 @@ qfo_delete (qfo_t *qfo) } static etype_t -get_def_type (qfo_t *qfo, pointer_t type) +get_def_type (qfo_t *qfo, pr_ptr_t type) { qfot_type_t *type_def; if (type >= qfo->spaces[qfo_type_space].data_size) @@ -705,7 +705,7 @@ get_def_type (qfo_t *qfo, pointer_t type) } static __attribute__((pure)) int -get_type_size (qfo_t *qfo, pointer_t type) +get_type_size (qfo_t *qfo, pr_ptr_t type) { qfot_type_t *type_def; int i, size; @@ -755,7 +755,7 @@ qfo_log2 (unsigned x) } static __attribute__((pure)) int -get_type_alignment_log (qfo_t *qfo, pointer_t type) +get_type_alignment_log (qfo_t *qfo, pr_ptr_t type) { qfot_type_t *type_def; int i, alignment; @@ -791,7 +791,7 @@ get_type_alignment_log (qfo_t *qfo, pointer_t type) } static __attribute__((pure)) dparmsize_t -get_parmsize (qfo_t *qfo, pointer_t type) +get_parmsize (qfo_t *qfo, pr_ptr_t type) { dparmsize_t parmsize = { get_type_size (qfo, type), diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 7f87e43df..09927ecd3 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -65,7 +65,7 @@ typedef def_t *(*encode_f) (type_t *type, defspace_t *space); -static string_t +static pr_string_t encoding_string (const char *string) { int str; diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index 4a0315d4a..12b98e1e6 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -32,7 +32,7 @@ pr_info_t pr; type_t type_Class; type_t type_SEL; type_t type_id; -__attribute__((const)) string_t ReuseString (const char *str) {return 0;} +__attribute__((const)) pr_string_t ReuseString (const char *str) {return 0;} __attribute__((const)) codespace_t *codespace_new (void) {return 0;} void codespace_addcode (codespace_t *codespace, struct dstatement_s *code, int size) {} __attribute__((const)) int function_parms (function_t *f, byte *parm_size) {return 0;} diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 190d92a1b..f40d48d6d 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -408,7 +408,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, expr_t *default_expr; int num_labels = 0; int saved_line = pr.source_line; - string_t saved_file = pr.source_file; + pr_string_t saved_file = pr.source_file; pr.source_line = sw_val->line = switch_block->test->line; pr.source_file = sw_val->file = switch_block->test->file; diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index db98cd60a..cd0af3d54 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -60,7 +60,7 @@ typedef struct { def_t *def; union { - string_t string_val; + pr_string_t string_val; float float_val; float vector_val[3]; int entity_val; diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index 42b6a9935..b73b0916f 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -261,7 +261,7 @@ main (int argc, char **argv) dfunction_t *dfunc; func_t main_func = 0; const char *name = "progs.dat"; - string_t *pr_argv; + pr_string_t *pr_argv; int pr_argc = 1, i; i = parse_options (argc, argv); From 978d6fd3e8957b09e19aa3f5d8ad28573617abeb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 12:24:43 +0900 Subject: [PATCH 2208/3664] [gamecode] Macro-ize the progs type names Now they'll never get out of sync again :) --- include/QF/Makemodule.am | 3 +- include/QF/progs/pr_comp.h | 18 ++---------- include/QF/progs/pr_type_names.h | 49 ++++++++++++++++++++++++++++++++ libs/gamecode/pr_opcode.c | 25 ++++++++++++++++ libs/gamecode/pr_v6p_opcode.c | 38 ------------------------- 5 files changed, 78 insertions(+), 55 deletions(-) create mode 100644 include/QF/progs/pr_type_names.h diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 4f5aa35c9..76265bd70 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -135,7 +135,8 @@ include_qf_progs = \ include/QF/pr_comp.h \ include/QF/pr_debug.h \ include/QF/pr_obj.h \ - include/QF/pr_type.h + include/QF/pr_type.h \ + include/QF/pr_type_names.h include_qf_scene = \ include/QF/scene/entity.h \ diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 7b097cda1..4fffa8792 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -51,23 +51,9 @@ PR_VEC_TYPE (pr_ulong_t, pr_ulvec4_t, 4); PR_VEC_TYPE (double, pr_dvec2_t, 2); PR_VEC_TYPE (double, pr_dvec4_t, 4); +#define EV_TYPE(type) ev_##type, typedef enum { - ev_void, - ev_string, - ev_float, - ev_vector, - ev_entity, - ev_field, - ev_func, - ev_pointer, // end of v6 types - ev_quat, - ev_integer, - ev_uinteger, - ev_short, // value is embedded in the opcode - ev_double, - ev_long, - ev_ulong, - +#include "QF/progs/pr_type_names.h" ev_invalid, // invalid type. used for instruction checking ev_type_count // not a type, gives number of types } etype_t; diff --git a/include/QF/progs/pr_type_names.h b/include/QF/progs/pr_type_names.h new file mode 100644 index 000000000..2e0ae9576 --- /dev/null +++ b/include/QF/progs/pr_type_names.h @@ -0,0 +1,49 @@ +/* + pr_type_names.h + + Progs type names + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef EV_TYPE +#define EV_TYPE(event) +#endif + +EV_TYPE(void) +EV_TYPE(string) +EV_TYPE(float) +EV_TYPE(vector) +EV_TYPE(entity) +EV_TYPE(field) +EV_TYPE(func) +EV_TYPE(pointer) // end of v6 types +EV_TYPE(quat) +EV_TYPE(integer) +EV_TYPE(uinteger) +EV_TYPE(short) // value is embedded in the opcode +EV_TYPE(double) +EV_TYPE(long) +EV_TYPE(ulong) + +#undef EV_TYPE diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index add538502..1d725d21c 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -33,6 +33,31 @@ #include "QF/progs.h" +VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { + 1, // ev_void + 1, // ev_string + 1, // ev_float + 3, // ev_vector + 1, // ev_entity + 1, // ev_field + 1, // ev_func + 1, // ev_pointer + 4, // ev_quat + 1, // ev_integer + 1, // ev_uinteger + 0, // ev_short value in opcode + 2, // ev_double + 2, // ev_long + 2, // ev_ulong + 0, // ev_invalid not a valid/simple type +}; + +#define EV_TYPE(type) #type, +VISIBLE const char * const pr_type_name[ev_type_count] = { +#include "QF/progs/pr_type_names.h" + "invalid", +}; + const opcode_t pr_opcodes[512] = { #include "libs/gamecode/pr_opcode.cinc" }; diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 6163050eb..560d14668 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -44,44 +44,6 @@ #include "compat.h" -VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { - 1, // ev_void - 1, // ev_string - 1, // ev_float - 3, // ev_vector - 1, // ev_entity - 1, // ev_field - 1, // ev_func - 1, // ev_pointer - 4, // ev_quat - 1, // ev_integer - 1, // ev_uinteger - 0, // ev_short value in opcode - 2, // ev_double - 2, // ev_long - 2, // ev_ulong - 0, // ev_invalid not a valid/simple type -}; - -VISIBLE const char * const pr_type_name[ev_type_count] = { - "void", - "string", - "float", - "vector", - "entity", - "field", - "function", - "pointer", - "quaternion", - "integer", - "uinteger", - "short", - "double", - "long", - "ulong", - "invalid", -}; - // default format is "%Ga, %Gb, %gc" // V global_string, contents, void // G global_string, contents From cfe7c44df050018ebc150f5af68b76a2aa417d98 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 13:21:06 +0900 Subject: [PATCH 2209/3664] [gamecode] Rename ev_integer to ev_int And other related fields so integer is now int (and uinteger is uint). I really don't know why I went with integer in the first place, but this will make using macros easier for dealing with types. --- include/QF/progs.h | 54 +-- include/QF/progs/pr_comp.h | 4 +- include/QF/progs/pr_type_names.h | 4 +- libs/gamecode/opcodes.py | 38 +- libs/gamecode/pr_debug.c | 50 +-- libs/gamecode/pr_exec.c | 86 ++-- libs/gamecode/pr_opcode.c | 4 +- libs/gamecode/pr_parse.c | 10 +- libs/gamecode/pr_v6p_opcode.c | 276 ++++++------ libs/gib/bi_gib.c | 2 +- libs/ruamoko/pr_cmds.c | 10 +- libs/ruamoko/rua_hash.c | 6 +- libs/ruamoko/rua_obj.c | 6 +- libs/video/renderer/vulkan/vkgen/vktype.r | 4 +- nq/include/sv_progs.h | 2 +- nq/source/sv_progs.c | 6 +- nq/source/world.c | 6 +- qw/include/sv_progs.h | 2 +- qw/source/sv_progs.c | 6 +- qw/source/sv_user.c | 4 +- qw/source/world.c | 6 +- ruamoko/cl_menu/plistmenu.r | 2 +- ruamoko/include/types.h | 4 +- ruamoko/qwaq/debugger/typeencodings.r | 2 +- tools/qfcc/include/expr.h | 32 +- tools/qfcc/include/obj_file.h | 8 +- tools/qfcc/include/qfcc.h | 2 +- tools/qfcc/include/type.h | 8 +- tools/qfcc/include/value.h | 4 +- tools/qfcc/source/class.c | 48 +- tools/qfcc/source/constfold.c | 186 ++++---- tools/qfcc/source/debug.c | 4 +- tools/qfcc/source/def.c | 5 +- tools/qfcc/source/dot_expr.c | 12 +- tools/qfcc/source/dot_type.c | 2 +- tools/qfcc/source/dump_globals.c | 4 +- tools/qfcc/source/expr.c | 150 +++---- tools/qfcc/source/expr_binary.c | 524 +++++++++++----------- tools/qfcc/source/expr_bool.c | 10 +- tools/qfcc/source/function.c | 6 +- tools/qfcc/source/method.c | 16 +- tools/qfcc/source/obj_file.c | 8 +- tools/qfcc/source/obj_type.c | 2 +- tools/qfcc/source/opcodes.c | 6 +- tools/qfcc/source/pragma.c | 2 +- tools/qfcc/source/qc-lex.l | 12 +- tools/qfcc/source/qc-parse.y | 6 +- tools/qfcc/source/qfcc.c | 8 +- tools/qfcc/source/qp-lex.l | 6 +- tools/qfcc/source/qp-parse.y | 8 +- tools/qfcc/source/reloc.c | 6 +- tools/qfcc/source/shared.c | 2 +- tools/qfcc/source/statements.c | 40 +- tools/qfcc/source/struct.c | 12 +- tools/qfcc/source/switch.c | 42 +- tools/qfcc/source/type.c | 64 ++- tools/qfcc/source/value.c | 90 ++-- tools/qfcc/test/double-alias.r | 10 +- tools/qfcc/test/typedef.r | 2 +- 59 files changed, 969 insertions(+), 972 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index f8c8d42b0..f9ae57c63 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -416,29 +416,29 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define G_DOUBLE(p,o) (*(double *) ((p)->pr_globals + o)) -/** Access an integer global. Can be assigned to. +/** Access an int global. Can be assigned to. \par QC type: - \c integer + \c int \param p pointer to ::progs_t VM struct \param o offset into global data space \return int lvalue \hideinitializer */ -#define G_INT(p,o) G_var (p, o, integer) +#define G_INT(p,o) G_var (p, o, int) -/** Access an unsigned integer global. Can be assigned to. +/** Access an unsigned int global. Can be assigned to. \par QC type: - \c uinteger + \c uint \param p pointer to ::progs_t VM struct \param o offset into global data space \return unsigned int lvalue \hideinitializer */ -#define G_UINT(p,o) G_var (p, o, uinteger) +#define G_UINT(p,o) G_var (p, o, uint) /** Access a vector global. Can be assigned to. @@ -632,29 +632,29 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define P_DOUBLE(p,n) P_PACKED(p, double, n) -/** Access an integer parameter. Can be assigned to. +/** Access an int parameter. Can be assigned to. \par QC type: - \c integer + \c int \param p pointer to ::progs_t VM struct \param n parameter number (0-7) \return int lvalue \hideinitializer */ -#define P_INT(p,n) P_var (p, n, integer) +#define P_INT(p,n) P_var (p, n, int) -/** Access an unsigned integer parameter. Can be assigned to. +/** Access an unsigned int parameter. Can be assigned to. \par QC type: - \c uinteger + \c uint \param p pointer to ::progs_t VM struct \param n parameter number (0-7) \return unsigned int lvalue \hideinitializer */ -#define P_UINT(p,n) P_var (p, n, uinteger) +#define P_UINT(p,n) P_var (p, n, uint) /** Access a vector parameter. Can be used any way a vec3_t variable can. @@ -850,24 +850,24 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ /** Access the VM function return value as a \c ::pr_int_t (AKA int32_t) \par QC type: - \c integer + \c int \param p pointer to ::progs_t VM struct \return ::pr_int_t lvalue \hideinitializer */ -#define R_INT(p) R_var (p, integer) +#define R_INT(p) R_var (p, int) /** Access the VM function return value as a \c ::pr_uint_t (AKA uint32_t) \par QC type: - \c uinteger + \c uint \param p pointer to ::progs_t VM struct \return ::pr_int_t lvalue \hideinitializer */ -#define R_UINT(p) R_var (p, uinteger) +#define R_UINT(p) R_var (p, uint) /** Access the VM function return value as a \c ::vec3_t vector. @@ -1036,29 +1036,29 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define E_DOUBLE(e,o) (*(double *) ((e)->v + o)) -/** Access an integer entity field. Can be assigned to. +/** Access an int entity field. Can be assigned to. \par QC type: - \c integer + \c int \param e pointer to the entity \param o field offset into entity data space \return int lvalue \hideinitializer */ -#define E_INT(e,o) E_var (e, o, integer) +#define E_INT(e,o) E_var (e, o, int) -/** Access an unsigned integer entity field. Can be assigned to. +/** Access an unsigned int entity field. Can be assigned to. \par QC type: - \c uinteger + \c uint \param e pointer to the entity \param o field offset into entity data space \return unsigned int lvalue \hideinitializer */ -#define E_UINT(e,o) E_var (e, o, uinteger) +#define E_UINT(e,o) E_var (e, o, uint) /** Access a vector entity field. Can be used any way a vec3_t variable can. @@ -1452,14 +1452,14 @@ void PR_FreeTempStrings (progs_t *pr);

  • \c '@' \c id Not yet implemented. Silently ignored.
  • \c 'e' \c entity Prints the edict number of the given entity ("%i") -
  • \c 'i' \c integer Print a integer value. ("%i") +
  • \c 'i' \c int Print a int value. ("%i")
  • \c 'f' \c float Print a float value. ("%f")
  • \c 'g' \c float Print a float value. ("%f")
  • \c 'p' \c void * Print a pointer value. ("%#x")
  • \c 's' \c string Print a string value. ("%s")
  • \c 'v' \c vector Print a vector value. ("'%g %g %g'")
  • \c 'q' \c quaternion Print a quaternion value. ("'%g %g %g %g'") -
  • \c 'x' \c uinteger Print an unsigned integer value. ("%x") +
  • \c 'x' \c uint Print an unsigned int value. ("%x")
@@ -1528,7 +1528,7 @@ void *PR_Resources_Find (progs_t *pr, const char *name); /** \name Resource Map support These macros can be used to create functions for mapping C resources - to QuakeC integer handles. + to QuakeC int handles. Valid handles are always negative. @@ -1731,8 +1731,8 @@ typedef struct type_view_s { type_view_func func_view; type_view_func pointer_view; type_view_func quat_view; - type_view_func integer_view; - type_view_func uinteger_view; + type_view_func int_view; + type_view_func uint_view; type_view_func short_view; type_view_func double_view; type_view_func long_view; diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 4fffa8792..9dbaea8db 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -524,9 +524,9 @@ typedef union pr_type_u { pr_uint_t entity_var; float vector_var; // really [3], but this structure must be 32 bits float quat_var; // really [4], but this structure must be 32 bits - pr_int_t integer_var; + pr_int_t int_var; pr_ptr_t pointer_var; - pr_uint_t uinteger_var; + pr_uint_t uint_var; } pr_type_t; typedef struct pr_va_list_s { diff --git a/include/QF/progs/pr_type_names.h b/include/QF/progs/pr_type_names.h index 2e0ae9576..ff190f2cd 100644 --- a/include/QF/progs/pr_type_names.h +++ b/include/QF/progs/pr_type_names.h @@ -39,8 +39,8 @@ EV_TYPE(field) EV_TYPE(func) EV_TYPE(pointer) // end of v6 types EV_TYPE(quat) -EV_TYPE(integer) -EV_TYPE(uinteger) +EV_TYPE(int) +EV_TYPE(uint) EV_TYPE(short) // value is embedded in the opcode EV_TYPE(double) EV_TYPE(long) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 4b123ce19..8734bb03c 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -48,8 +48,8 @@ branch_fmt = [ ] compare_ccc = [ "eq", "lt", "gt", None, "ne", "ge", "le", None] type_tt = ['I', 'F', 'L', 'D'] -etype_tt = ["ev_integer", "ev_float", "ev_long", "ev_double"] -unsigned_t = ["ev_uinteger", "ev_ulong"] +etype_tt = ["ev_int", "ev_float", "ev_long", "ev_double"] +unsigned_t = ["ev_uint", "ev_ulong"] float_t = ["ev_float", "ev_double"] all_formats = { @@ -58,7 +58,7 @@ all_formats = { "opname": "all", "format": "%Ga, %gc", "widths": "{ss+1}, 0, 1", - "types": "ev_integer, ev_integer, ev_integer", + "types": "ev_int, ev_int, ev_int", } any_formats = { "opcode": "OP_ANY_{ss+1}", @@ -66,7 +66,7 @@ any_formats = { "opname": "any", "format": "%Ga, %gc", "widths": "{ss+1}, 0, 1", - "types": "ev_integer, ev_integer, ev_integer", + "types": "ev_int, ev_int, ev_int", } bitops_formats = { "opcode": "OP_{op_bit[oo].upper()}_{bit_type[t]}_{ss+1}", @@ -78,7 +78,7 @@ bitops_formats = { "args": { "op_bit": ["bitand", "bitor", "bitxor", "bitnot"], "bit_type": ["I", "L"], - "bit_types": ["ev_integer", "ev_long"], + "bit_types": ["ev_int", "ev_long"], "bit_fmt": [ "%Ga, %Gb, %gc", "%Ga, %Gb, %gc", @@ -93,7 +93,7 @@ branch_formats = { "opname": "{op_cond[c*4+cc]}", "format": "{cond_fmt[c*4+cc]}{branch_fmt[0]}", "widths": "{cond_widths[c*4+cc]}", - "types": "ev_void, ev_void, ev_integer", + "types": "ev_void, ev_void, ev_int", "args": { "op_mode": "ABCD", "op_cond": ["ifz", "ifb", "ifa", None, @@ -134,7 +134,7 @@ compare_formats = { "mnemonic": "{op_cmp[ccc]}.{cmp_type[tt]}", "opname": "{op_cmp[ccc]}", "widths": "{ss+1}, {ss+1}, {ss+1}", - "types": "{cmp_types[tt]}, {cmp_types[tt]}, ev_integer", + "types": "{cmp_types[tt]}, {cmp_types[tt]}, ev_int", "args": { "op_cmp": compare_ccc, "cmp_type": type_tt, @@ -146,7 +146,7 @@ compare2_formats = { "mnemonic": "{op_cmp[ccc]}.{cmp_type[t]}", "opname": "{op_cmp[ccc]}", "widths": "{ss+1}, {ss+1}, {ss+1}", - "types": "{cmp_types[t]}, {cmp_types[t]}, ev_integer", + "types": "{cmp_types[t]}, {cmp_types[t]}, ev_int", "args": { "op_cmp": compare_ccc, "cmp_type": ['u', 'U'], @@ -228,7 +228,7 @@ memset_formats = { "opname": "memset", "format": "{memset_fmt[oo]}", "widths": "0, 0, 0", - "types": "ev_integer, ev_void, ev_void", + "types": "ev_int, ev_void, ev_void", "args": { "op_memset": ["i", "p", "pi", None], "memset_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], @@ -240,7 +240,7 @@ move_formats = { "opname": "memset", "format": "{move_fmt[oo]}", "widths": "0, 0, 0", - "types": "ev_integer, ev_void, ev_void", + "types": "ev_int, ev_void, ev_void", "args": { "op_move": ["i", "p", "pi", None], "move_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], @@ -252,7 +252,7 @@ none_formats = { "opname": "none", "format": "%Ga, %gc", "widths": "{ss+1}, 0, 1", - "types": "ev_integer, ev_invalid, ev_integer", + "types": "ev_int, ev_invalid, ev_int", } push_formats = { "opcode": "OP_PUSH_{op_mode[mm]}_{ss+1}", @@ -325,7 +325,7 @@ shiftops_formats = { "op_shift": ["shl", "asr", "shl", "shr"], "shift_type": ['I', 'L', 'u', 'U'], "shift_types": [ - ["ev_integer", "ev_uinteger"], + ["ev_int", "ev_uint"], ["ev_long", "ev_ulong"], ], }, @@ -393,14 +393,14 @@ string_formats = { "%Ga, %gc", ], "str_types": [ - "ev_string, ev_string, ev_integer", - "ev_string, ev_string, ev_integer", - "ev_string, ev_string, ev_integer", + "ev_string, ev_string, ev_int", + "ev_string, ev_string, ev_int", + "ev_string, ev_string, ev_int", "ev_string, ev_string, ev_string", - "ev_string, ev_string, ev_integer", - "ev_string, ev_string, ev_integer", - "ev_string, ev_string, ev_integer", - "ev_string, ev_invalid, ev_integer", + "ev_string, ev_string, ev_int", + "ev_string, ev_string, ev_int", + "ev_string, ev_string, ev_int", + "ev_string, ev_invalid, ev_int", ], }, } diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 4b4b23d05..9e0b1b363 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -137,9 +137,9 @@ static void pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data); -static void pr_debug_integer_view (qfot_type_t *type, pr_type_t *value, +static void pr_debug_int_view (qfot_type_t *type, pr_type_t *value, void *_data); -static void pr_debug_uinteger_view (qfot_type_t *type, pr_type_t *value, +static void pr_debug_uint_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_short_view (qfot_type_t *type, pr_type_t *value, void *_data); @@ -170,8 +170,8 @@ static type_view_t raw_type_view = { pr_debug_func_view, pr_debug_pointer_view, pr_debug_quat_view, - pr_debug_integer_view, - pr_debug_uinteger_view, + pr_debug_int_view, + pr_debug_uint_view, pr_debug_short_view, pr_debug_double_view, pr_debug_long_view, @@ -269,7 +269,7 @@ pr_debug_type_size (const progs_t *pr, const qfot_type_t *type) } return size; case ty_enum: - return pr_type_size[ev_integer]; + return pr_type_size[ev_int]; case ty_array: aux_type = &G_STRUCT (pr, qfot_type_t, type->array.type); size = pr_debug_type_size (pr, aux_type); @@ -356,7 +356,7 @@ parse_expression (progs_t *pr, const char *expr, int conditional) goto error; if (!Script_GetToken (es, 1)) goto error; - pr->wp_val.integer_var = strtol (es->token->str, &e, 0); + pr->wp_val.int_var = strtol (es->token->str, &e, 0); if (e == es->token->str) goto error; if (*e == '.' || *e == 'e' || *e == 'E') @@ -404,7 +404,7 @@ pr_debug_clear (progs_t *pr, void *data) pr->watch = 0; pr->wp_conditional = 0; - pr->wp_val.integer_var = 0; + pr->wp_val.int_var = 0; for (int i = 0; i < ev_type_count; i++ ) { res->type_encodings[i] = &res->void_type; @@ -1056,11 +1056,11 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) case ev_quat: raw_type_view.quat_view (type, value, data); break; - case ev_integer: - raw_type_view.integer_view (type, value, data); + case ev_int: + raw_type_view.int_view (type, value, data); break; - case ev_uinteger: - raw_type_view.uinteger_view (type, value, data); + case ev_uint: + raw_type_view.uint_view (type, value, data); break; case ev_short: raw_type_view.short_view (type, value, data); @@ -1242,9 +1242,9 @@ pr_debug_float_view (qfot_type_t *type, pr_type_t *value, void *_data) dstring_t *dstr = data->dstr; if (data->pr->progs->version == PROG_ID_VERSION - && ISDENORM (value->integer_var) - && value->uinteger_var != 0x80000000) { - dasprintf (dstr, "<%08x>", value->integer_var); + && ISDENORM (value->int_var) + && value->uint_var != 0x80000000) { + dasprintf (dstr, "<%08x>", value->int_var); } else { dasprintf (dstr, "%.9g", value->float_var); } @@ -1284,12 +1284,12 @@ pr_debug_field_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - pr_def_t *def = PR_FieldAtOfs (pr, value->integer_var); + pr_def_t *def = PR_FieldAtOfs (pr, value->int_var); if (def) { dasprintf (dstr, ".%s", PR_GetString (pr, def->name)); } else { - dasprintf (dstr, ".<$%04x>", value->integer_var); + dasprintf (dstr, ".<$%04x>", value->int_var); } } @@ -1316,7 +1316,7 @@ pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - pr_ptr_t offset = value->integer_var; + pr_ptr_t offset = value->int_var; pr_ptr_t offs = offset; pr_def_t *def = 0; @@ -1342,21 +1342,21 @@ pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data) } static void -pr_debug_integer_view (qfot_type_t *type, pr_type_t *value, void *_data) +pr_debug_int_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%d", value->integer_var); + dasprintf (dstr, "%d", value->int_var); } static void -pr_debug_uinteger_view (qfot_type_t *type, pr_type_t *value, void *_data) +pr_debug_uint_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "$%08x", value->uinteger_var); + dasprintf (dstr, "$%08x", value->uint_var); } static void @@ -1365,7 +1365,7 @@ pr_debug_short_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%04x", (short)value->integer_var); + dasprintf (dstr, "%04x", (short)value->int_var); } static void @@ -1468,7 +1468,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) (int) (intptr_t) (pr->watch - pr->pr_globals)); if (pr->wp_conditional) Sys_Printf (" if new val == %d\n", - pr->wp_val.integer_var); + pr->wp_val.int_var); } else { Sys_Printf (" none active\n"); } return; @@ -1481,7 +1481,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) if (pr->watch) { Sys_Printf ("watchpoint set to [%d]\n", PR_SetPointer (pr, pr->watch)); if (pr->wp_conditional) - Sys_Printf (" if new val == %d\n", pr->wp_val.integer_var); + Sys_Printf (" if new val == %d\n", pr->wp_val.int_var); } else { Sys_Printf ("watchpoint cleared\n"); } @@ -1672,7 +1672,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) { edict_t *ed = 0; opval = pr->pr_globals[s->a].entity_var; - parm_ind = pr->pr_globals[s->b].uinteger_var; + parm_ind = pr->pr_globals[s->b].uint_var; if (parm_ind < pr->progs->entityfields && opval > 0 && opval < pr->pr_edict_area_size) { diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 53964982f..d0f94d8fb 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -282,7 +282,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) if (pr_deadbeef_locals->int_val) for (i = f->parm_start; i < f->parm_start + f->locals; i++) - pr->pr_globals[i].integer_var = 0xdeadbeef; + pr->pr_globals[i].int_var = 0xdeadbeef; // copy parameters if (f->numparms >= 0) { @@ -297,8 +297,8 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size); } copy_args = pr->pr_argc - i; - argc->integer_var = copy_args; - argv->integer_var = dstParams[i] - pr->pr_globals; + argc->int_var = copy_args; + argv->int_var = dstParams[i] - pr->pr_globals; if (i < MAX_PARMS) { memcpy (dstParams[i], pr->pr_params[i], (copy_args * pr->pr_param_size) * sizeof (pr_type_t)); @@ -461,7 +461,7 @@ static inline void pr_memset (pr_type_t *dst, int val, int count) { while (count-- > 0) { - (*dst++).integer_var = val; + (*dst++).int_var = val; } } @@ -783,10 +783,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREP_P_v6p: pointer = OPB(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->integer_var = OPA(int); + ptr->int_var = OPA(int); break; case OP_STOREP_V_v6p: pointer = OPB(int); @@ -857,7 +857,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) "field in an edict"); } fldofs = OPA(uint) + OPB(int); - OPC(int) = pr->pr_edict_area[fldofs].integer_var; + OPC(int) = pr->pr_edict_area[fldofs].int_var; break; case OP_LOAD_V_v6p: if (pr_boundscheck->int_val) { @@ -905,10 +905,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADB_P_v6p: pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - OPC(int) = ptr->integer_var; + OPC(int) = ptr->int_var; break; case OP_LOADB_V_v6p: pointer = OPA(int) + OPB(int); @@ -944,10 +944,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADBI_P_v6p: pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - OPC(int) = ptr->integer_var; + OPC(int) = ptr->int_var; break; case OP_LOADBI_V_v6p: pointer = OPA(int) + (short) st->b; @@ -993,10 +993,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREB_P_v6p: pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->integer_var = OPA(int); + ptr->int_var = OPA(int); break; case OP_STOREB_V_v6p: pointer = OPB(int) + OPC(int); @@ -1032,10 +1032,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREBI_P_v6p: pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->integer_var = OPA(int); + ptr->int_var = OPA(int); break; case OP_STOREBI_V_v6p: pointer = OPB(int) + (short) st->c; @@ -1075,7 +1075,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); } - stk->integer_var = OPA(int); + stk->int_var = OPA(int); *pr->globals.stack = stack; } break; @@ -1118,10 +1118,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } - stk->integer_var = ptr->integer_var; + stk->int_var = ptr->int_var; *pr->globals.stack = stack; } break; @@ -1135,7 +1135,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } VectorCopy (&ptr->vector_var, &stk->vector_var); @@ -1176,10 +1176,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } - stk->integer_var = ptr->integer_var; + stk->int_var = ptr->int_var; *pr->globals.stack = stack; } break; @@ -1193,7 +1193,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } VectorCopy (&ptr->vector_var, &stk->vector_var); @@ -1231,7 +1231,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); } - OPA(int) = stk->integer_var; + OPA(int) = stk->int_var; *pr->globals.stack = stack + 1; } break; @@ -1274,10 +1274,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } - ptr->integer_var = stk->integer_var; + ptr->int_var = stk->int_var; *pr->globals.stack = stack + 1; } break; @@ -1291,7 +1291,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } VectorCopy (&stk->vector_var, &ptr->vector_var); @@ -1332,10 +1332,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 1); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } - ptr->integer_var = stk->integer_var; + ptr->int_var = stk->int_var; *pr->globals.stack = stack + 1; } break; @@ -1349,7 +1349,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 3); - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } VectorCopy (&stk->vector_var, &ptr->vector_var); @@ -1426,10 +1426,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_JUMPB_v6p: pointer = st->a + OPB(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_integer); + PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - pointer = ptr->integer_var; + pointer = ptr->int_var; if (pr_boundscheck->int_val && (pointer >= pr->progs->numstatements)) { PR_RunError (pr, "Invalid jump destination"); @@ -1695,8 +1695,8 @@ op_call: OPC(float) = OPA(double) < OPB(double); break; case OP_NOT_D_v6p: - OPC(int) = (op_a[0].integer_var - || (op_a[1].integer_var & ~0x80000000u)); + OPC(int) = (op_a[0].int_var + || (op_a[1].int_var & ~0x80000000u)); break; case OP_EQ_D_v6p: OPC(int) = OPA(double) == OPB(double); @@ -1730,17 +1730,17 @@ op_call: default: PR_RunError (pr, "Bad opcode %i", st->op & ~OP_BREAK); } - if (pr->watch && pr->watch->integer_var != old_val.integer_var) { + if (pr->watch && pr->watch->int_var != old_val.int_var) { if (!pr->wp_conditional - || pr->watch->integer_var == pr->wp_val.integer_var) { + || pr->watch->int_var == pr->wp_val.int_var) { if (pr->debug_handler) { pr->debug_handler (prd_watchpoint, 0, pr->debug_data); } else { PR_RunError (pr, "watchpoint hit: %d -> %d", - old_val.integer_var, pr->watch->integer_var); + old_val.int_var, pr->watch->int_var); } } - old_val.integer_var = pr->watch->integer_var; + old_val.int_var = pr->watch->int_var; } } exit_program: @@ -3355,7 +3355,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int think = pr->fields.think + self; double time = *pr->globals.dtime + 0.1; *(double *) (&pr->pr_edict_area[nextthink]) = time; - pr->pr_edict_area[frame].integer_var = OPA(int); + pr->pr_edict_area[frame].int_var = OPA(int); pr->pr_edict_area[think].func_var = op_b->func_var; } break; @@ -3386,7 +3386,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int think = pr->fields.think + self; double time = *pr->globals.dtime + OPC(double); *(double *) (&pr->pr_edict_area[nextthink]) = time; - pr->pr_edict_area[frame].integer_var = OPA(int); + pr->pr_edict_area[frame].int_var = OPA(int); pr->pr_edict_area[think].func_var = op_b->func_var; } break; @@ -3440,17 +3440,17 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) default: PR_RunError (pr, "Bad opcode o%03o", st->op & OP_MASK); } - if (pr->watch && pr->watch->integer_var != old_val.integer_var) { + if (pr->watch && pr->watch->int_var != old_val.int_var) { if (!pr->wp_conditional - || pr->watch->integer_var == pr->wp_val.integer_var) { + || pr->watch->int_var == pr->wp_val.int_var) { if (pr->debug_handler) { pr->debug_handler (prd_watchpoint, 0, pr->debug_data); } else { PR_RunError (pr, "watchpoint hit: %d -> %d", - old_val.integer_var, pr->watch->integer_var); + old_val.int_var, pr->watch->int_var); } } - old_val.integer_var = pr->watch->integer_var; + old_val.int_var = pr->watch->int_var; } } exit_program: diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 1d725d21c..0f1cb1258 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -43,8 +43,8 @@ VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { 1, // ev_func 1, // ev_pointer 4, // ev_quat - 1, // ev_integer - 1, // ev_uinteger + 1, // ev_int + 1, // ev_uint 0, // ev_short value in opcode 2, // ev_double 2, // ev_long diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 8b4c2d728..33ab39d3c 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -79,7 +79,7 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) dsprintf (line, "%s", PR_GetString (pr, f->name)); break; case ev_field: - def = PR_FieldAtOfs (pr, val->integer_var); + def = PR_FieldAtOfs (pr, val->int_var); dsprintf (line, "%s", PR_GetString (pr, def->name)); break; case ev_void: @@ -88,8 +88,8 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) case ev_float: dsprintf (line, "%.9g", val->float_var); break; - case ev_integer: - dsprintf (line, "%d", val->integer_var); + case ev_int: + dsprintf (line, "%d", val->int_var); break; case ev_vector: dsprintf (line, "%.9g %.9g %.9g", VectorExpand (&val->vector_var)); @@ -132,7 +132,7 @@ ED_EntityDict (progs_t *pr, edict_t *ed) // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; for (j = 0; j < pr_type_size[type]; j++) - if (v[j].integer_var) + if (v[j].int_var) break; if (j == pr_type_size[type]) continue; @@ -257,7 +257,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) Sys_Printf ("Can't find field %s\n", s); return false; } - d->integer_var = G_INT (pr, def->ofs); + d->int_var = G_INT (pr, def->ofs); break; case ev_func: diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 560d14668..c61821852 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -183,109 +183,109 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_EQ_D_v6p] = {"==", "eq.d", - ev_double, ev_double, ev_integer, + ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, [OP_EQ_F_v6p] = {"==", "eq.f", - ev_float, ev_float, ev_integer, + ev_float, ev_float, ev_int, PROG_ID_VERSION, }, [OP_EQ_V_v6p] = {"==", "eq.v", - ev_vector, ev_vector, ev_integer, + ev_vector, ev_vector, ev_int, PROG_ID_VERSION, }, [OP_EQ_Q_v6p] = {"==", "eq.q", - ev_quat, ev_quat, ev_integer, + ev_quat, ev_quat, ev_int, PROG_V6P_VERSION, }, [OP_EQ_S_v6p] = {"==", "eq.s", - ev_string, ev_string, ev_integer, + ev_string, ev_string, ev_int, PROG_ID_VERSION, }, [OP_EQ_E_v6p] = {"==", "eq.e", - ev_entity, ev_entity, ev_integer, + ev_entity, ev_entity, ev_int, PROG_ID_VERSION, }, [OP_EQ_FN_v6p] = {"==", "eq.fn", - ev_func, ev_func, ev_integer, + ev_func, ev_func, ev_int, PROG_ID_VERSION, }, [OP_NE_D_v6p] = {"!=", "ne.d", - ev_double, ev_double, ev_integer, + ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, [OP_NE_F_v6p] = {"!=", "ne.f", - ev_float, ev_float, ev_integer, + ev_float, ev_float, ev_int, PROG_ID_VERSION, }, [OP_NE_V_v6p] = {"!=", "ne.v", - ev_vector, ev_vector, ev_integer, + ev_vector, ev_vector, ev_int, PROG_ID_VERSION, }, [OP_NE_Q_v6p] = {"!=", "ne.q", - ev_quat, ev_quat, ev_integer, + ev_quat, ev_quat, ev_int, PROG_V6P_VERSION, }, [OP_NE_S_v6p] = {"!=", "ne.s", - ev_string, ev_string, ev_integer, + ev_string, ev_string, ev_int, PROG_ID_VERSION, }, [OP_NE_E_v6p] = {"!=", "ne.e", - ev_entity, ev_entity, ev_integer, + ev_entity, ev_entity, ev_int, PROG_ID_VERSION, }, [OP_NE_FN_v6p] = {"!=", "ne.fn", - ev_func, ev_func, ev_integer, + ev_func, ev_func, ev_int, PROG_ID_VERSION, }, [OP_LE_D_v6p] = {"<=", "le.d", - ev_double, ev_double, ev_integer, + ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, [OP_LE_F_v6p] = {"<=", "le.f", - ev_float, ev_float, ev_integer, + ev_float, ev_float, ev_int, PROG_ID_VERSION, }, [OP_GE_D_v6p] = {">=", "ge.d", - ev_double, ev_double, ev_integer, + ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, [OP_GE_F_v6p] = {">=", "ge.f", - ev_float, ev_float, ev_integer, + ev_float, ev_float, ev_int, PROG_ID_VERSION, }, [OP_LE_S_v6p] = {"<=", "le.s", - ev_string, ev_string, ev_integer, + ev_string, ev_string, ev_int, PROG_V6P_VERSION, }, [OP_GE_S_v6p] = {">=", "ge.s", - ev_string, ev_string, ev_integer, + ev_string, ev_string, ev_int, PROG_V6P_VERSION, }, [OP_LT_D_v6p] = {"<", "lt.d", - ev_double, ev_double, ev_integer, + ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, [OP_LT_F_v6p] = {"<", "lt.f", - ev_float, ev_float, ev_integer, + ev_float, ev_float, ev_int, PROG_ID_VERSION, }, [OP_GT_D_v6p] = {">", "gt.d", - ev_double, ev_double, ev_integer, + ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, [OP_GT_F_v6p] = {">", "gt.f", - ev_float, ev_float, ev_integer, + ev_float, ev_float, ev_int, PROG_ID_VERSION, }, [OP_LT_S_v6p] = {"<", "lt.s", - ev_string, ev_string, ev_integer, + ev_string, ev_string, ev_int, PROG_V6P_VERSION, }, [OP_GT_S_v6p] = {">", "gt.s", - ev_string, ev_string, ev_integer, + ev_string, ev_string, ev_int, PROG_V6P_VERSION, }, @@ -330,7 +330,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga.%Gb(%Ec), %gc", }, [OP_LOAD_I_v6p] = {".", "load.i", - ev_entity, ev_field, ev_integer, + ev_entity, ev_field, ev_int, PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, @@ -341,52 +341,52 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_LOADB_D_v6p] = {".", "loadb.d", - ev_pointer, ev_integer, ev_double, + ev_pointer, ev_int, ev_double, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_F_v6p] = {".", "loadb.f", - ev_pointer, ev_integer, ev_float, + ev_pointer, ev_int, ev_float, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_V_v6p] = {".", "loadb.v", - ev_pointer, ev_integer, ev_vector, + ev_pointer, ev_int, ev_vector, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_Q_v6p] = {".", "loadb.q", - ev_pointer, ev_integer, ev_quat, + ev_pointer, ev_int, ev_quat, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_S_v6p] = {".", "loadb.s", - ev_pointer, ev_integer, ev_string, + ev_pointer, ev_int, ev_string, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_ENT_v6p] = {".", "loadb.ent", - ev_pointer, ev_integer, ev_entity, + ev_pointer, ev_int, ev_entity, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_FLD_v6p] = {".", "loadb.fld", - ev_pointer, ev_integer, ev_field, + ev_pointer, ev_int, ev_field, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_FN_v6p] = {".", "loadb.fn", - ev_pointer, ev_integer, ev_func, + ev_pointer, ev_int, ev_func, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_I_v6p] = {".", "loadb.i", - ev_pointer, ev_integer, ev_integer, + ev_pointer, ev_int, ev_int, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_P_v6p] = {".", "loadb.p", - ev_pointer, ev_integer, ev_pointer, + ev_pointer, ev_int, ev_pointer, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, @@ -432,7 +432,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "*(%Ga + %sb), %gc", }, [OP_LOADBI_I_v6p] = {".", "loadbi.i", - ev_pointer, ev_short, ev_integer, + ev_pointer, ev_short, ev_int, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, @@ -494,7 +494,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %gc", }, [OP_ADDRESS_I_v6p] = {"&", "address.i", - ev_integer, ev_invalid, ev_pointer, + ev_int, ev_invalid, ev_pointer, PROG_V6P_VERSION, "%Ga, %gc", }, @@ -505,7 +505,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_LEA_v6p] = {"&", "lea", - ev_pointer, ev_integer, ev_pointer, + ev_pointer, ev_int, ev_pointer, PROG_V6P_VERSION, "(%Ga + %Gb), %gc", }, @@ -516,22 +516,22 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_CONV_IF_v6p] = {"", "conv.if", - ev_integer, ev_invalid, ev_float, + ev_int, ev_invalid, ev_float, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_CONV_FI_v6p] = {"", "conv.fi", - ev_float, ev_invalid, ev_integer, + ev_float, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_CONV_ID_v6p] = {"", "conv.id", - ev_integer, ev_invalid, ev_double, + ev_int, ev_invalid, ev_double, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_CONV_DI_v6p] = {"", "conv.di", - ev_double, ev_invalid, ev_integer, + ev_double, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, @@ -587,7 +587,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %gb", }, [OP_STORE_I_v6p] = {"=", "store.i", - ev_integer, ev_integer, ev_invalid, + ev_int, ev_int, ev_invalid, PROG_V6P_VERSION, "%Ga, %gb", }, @@ -638,7 +638,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, *%Gb", }, [OP_STOREP_I_v6p] = {".=", "storep.i", - ev_integer, ev_pointer, ev_invalid, + ev_int, ev_pointer, ev_invalid, PROG_V6P_VERSION, "%Ga, *%Gb", }, @@ -649,52 +649,52 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_STOREB_D_v6p] = {".=", "storeb.d", - ev_double, ev_pointer, ev_integer, + ev_double, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_F_v6p] = {".=", "storeb.f", - ev_float, ev_pointer, ev_integer, + ev_float, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_V_v6p] = {".=", "storeb.v", - ev_vector, ev_pointer, ev_integer, + ev_vector, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_Q_v6p] = {".=", "storeb.q", - ev_quat, ev_pointer, ev_integer, + ev_quat, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_S_v6p] = {".=", "storeb.s", - ev_string, ev_pointer, ev_integer, + ev_string, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_ENT_v6p] = {".=", "storeb.ent", - ev_entity, ev_pointer, ev_integer, + ev_entity, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_FLD_v6p] = {".=", "storeb.fld", - ev_field, ev_pointer, ev_integer, + ev_field, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_FN_v6p] = {".=", "storeb.fn", - ev_func, ev_pointer, ev_integer, + ev_func, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_I_v6p] = {".=", "storeb.i", - ev_integer, ev_pointer, ev_integer, + ev_int, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_P_v6p] = {".=", "storeb.p", - ev_pointer, ev_pointer, ev_integer, + ev_pointer, ev_pointer, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, @@ -740,7 +740,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_I_v6p] = {".=", "storebi.i", - ev_integer, ev_pointer, ev_short, + ev_int, ev_pointer, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, @@ -763,73 +763,73 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_NOT_D_v6p] = {"!", "not.d", - ev_double, ev_invalid, ev_integer, + ev_double, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_NOT_F_v6p] = {"!", "not.f", - ev_float, ev_invalid, ev_integer, + ev_float, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, [OP_NOT_V_v6p] = {"!", "not.v", - ev_vector, ev_invalid, ev_integer, + ev_vector, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, [OP_NOT_Q_v6p] = {"!", "not.q", - ev_quat, ev_invalid, ev_integer, + ev_quat, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_NOT_S_v6p] = {"!", "not.s", - ev_string, ev_invalid, ev_integer, + ev_string, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, [OP_NOT_ENT_v6p] = {"!", "not.ent", - ev_entity, ev_invalid, ev_integer, + ev_entity, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, [OP_NOT_FN_v6p] = {"!", "not.fn", - ev_func, ev_invalid, ev_integer, + ev_func, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, [OP_NOT_P_v6p] = {"!", "not.p", - ev_pointer, ev_invalid, ev_integer, + ev_pointer, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_IF_v6p] = {"", "if", - ev_integer, ev_short, ev_invalid, + ev_int, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, [OP_IFNOT_v6p] = {"", "ifnot", - ev_integer, ev_short, ev_invalid, + ev_int, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, [OP_IFBE_v6p] = {"", "ifbe", - ev_integer, ev_short, ev_invalid, + ev_int, ev_short, ev_invalid, PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, [OP_IFB_v6p] = {"", "ifb", - ev_integer, ev_short, ev_invalid, + ev_int, ev_short, ev_invalid, PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, [OP_IFAE_v6p] = {"", "ifae", - ev_integer, ev_short, ev_invalid, + ev_int, ev_short, ev_invalid, PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, [OP_IFA_v6p] = {"", "ifa", - ev_integer, ev_short, ev_invalid, + ev_int, ev_short, ev_invalid, PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, @@ -944,22 +944,22 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "branch %sa (%Oa)", }, [OP_JUMP_v6p] = {"", "jump", - ev_integer, ev_invalid, ev_invalid, + ev_int, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, [OP_JUMPB_v6p] = {"", "jumpb", - ev_void, ev_integer, ev_invalid, + ev_void, ev_int, ev_invalid, PROG_V6P_VERSION, "%Ga[%Gb]", }, [OP_AND_v6p] = {"&&", "and.f", - ev_float, ev_float, ev_integer, + ev_float, ev_float, ev_int, PROG_ID_VERSION, }, [OP_OR_v6p] = {"||", "or.f", - ev_float, ev_float, ev_integer, + ev_float, ev_float, ev_int, PROG_ID_VERSION, }, @@ -972,15 +972,15 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { PROG_V6P_VERSION, }, [OP_SHL_I_v6p] = {"<<", "shl.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_SHR_I_v6p] = {">>", "shr.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_SHR_U_v6p] = {">>", "shr.u", - ev_uinteger, ev_integer, ev_uinteger, + ev_uint, ev_int, ev_uint, PROG_V6P_VERSION, }, @@ -994,35 +994,35 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_ADD_I_v6p] = {"+", "add.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_SUB_I_v6p] = {"-", "sub.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_MUL_I_v6p] = {"*", "mul.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_DIV_I_v6p] = {"/", "div.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_REM_I_v6p] = {"%", "rem.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_MOD_I_v6p] = {"%%", "mod.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_BITAND_I_v6p] = {"&", "bitand.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_BITOR_I_v6p] = {"|", "bitor.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, @@ -1037,58 +1037,58 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_GE_I_v6p] = {">=", "ge.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_LE_I_v6p] = {"<=", "le.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_GT_I_v6p] = {">", "gt.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_LT_I_v6p] = {"<", "lt.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_AND_I_v6p] = {"&&", "and.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_OR_I_v6p] = {"||", "or.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_NOT_I_v6p] = {"!", "not.i", - ev_integer, ev_invalid, ev_integer, + ev_int, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_EQ_I_v6p] = {"==", "eq.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_NE_I_v6p] = {"!=", "ne.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_GE_U_v6p] = {">=", "ge.u", - ev_uinteger, ev_uinteger, ev_integer, + ev_uint, ev_uint, ev_int, PROG_V6P_VERSION, }, [OP_LE_U_v6p] = {"<=", "le.u", - ev_uinteger, ev_uinteger, ev_integer, + ev_uint, ev_uint, ev_int, PROG_V6P_VERSION, }, [OP_GT_U_v6p] = {">", "gt.u", - ev_uinteger, ev_uinteger, ev_integer, + ev_uint, ev_uint, ev_int, PROG_V6P_VERSION, }, [OP_LT_U_v6p] = {"<", "lt.u", - ev_uinteger, ev_uinteger, ev_integer, + ev_uint, ev_uint, ev_int, PROG_V6P_VERSION, }, @@ -1102,37 +1102,37 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %gc", }, [OP_BITXOR_I_v6p] = {"^", "bitxor.i", - ev_integer, ev_integer, ev_integer, + ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, [OP_BITNOT_I_v6p] = {"~", "bitnot.i", - ev_integer, ev_invalid, ev_integer, + ev_int, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_GE_P_v6p] = {">=", "ge.p", - ev_pointer, ev_pointer, ev_integer, + ev_pointer, ev_pointer, ev_int, PROG_V6P_VERSION, }, [OP_LE_P_v6p] = {"<=", "le.p", - ev_pointer, ev_pointer, ev_integer, + ev_pointer, ev_pointer, ev_int, PROG_V6P_VERSION, }, [OP_GT_P_v6p] = {">", "gt.p", - ev_pointer, ev_pointer, ev_integer, + ev_pointer, ev_pointer, ev_int, PROG_V6P_VERSION, }, [OP_LT_P_v6p] = {"<", "lt.p", - ev_pointer, ev_pointer, ev_integer, + ev_pointer, ev_pointer, ev_int, PROG_V6P_VERSION, }, [OP_EQ_P_v6p] = {"==", "eq.p", - ev_pointer, ev_pointer, ev_integer, + ev_pointer, ev_pointer, ev_int, PROG_V6P_VERSION, }, [OP_NE_P_v6p] = {"!=", "ne.p", - ev_pointer, ev_pointer, ev_integer, + ev_pointer, ev_pointer, ev_int, PROG_V6P_VERSION, }, @@ -1142,7 +1142,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %sb, %gc", }, [OP_MOVEP_v6p] = {"", "movep", - ev_pointer, ev_integer, ev_pointer, + ev_pointer, ev_int, ev_pointer, PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, @@ -1152,17 +1152,17 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %sb, %Gc", }, [OP_MEMSETI_v6p] = {"", "memseti", - ev_integer, ev_short, ev_void, + ev_int, ev_short, ev_void, PROG_V6P_VERSION, "%Ga, %sb, %gc", }, [OP_MEMSETP_v6p] = {"", "memsetp", - ev_integer, ev_integer, ev_pointer, + ev_int, ev_int, ev_pointer, PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, [OP_MEMSETPI_v6p] = {"", "memsetpi", - ev_integer, ev_short, ev_pointer, + ev_int, ev_short, ev_pointer, PROG_V6P_VERSION, "%Ga, %sb, %Gc", }, @@ -1208,7 +1208,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga", }, [OP_PUSH_I_v6p] = {"", "push.i", - ev_integer, ev_invalid, ev_invalid, + ev_int, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, @@ -1219,52 +1219,52 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_PUSHB_S_v6p] = {"", "pushb.s", - ev_pointer, ev_integer, ev_string, + ev_pointer, ev_int, ev_string, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_F_v6p] = {"", "pushb.f", - ev_pointer, ev_integer, ev_float, + ev_pointer, ev_int, ev_float, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_V_v6p] = {"", "pushb.v", - ev_pointer, ev_integer, ev_vector, + ev_pointer, ev_int, ev_vector, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_ENT_v6p] = {"", "pushb.ent", - ev_pointer, ev_integer, ev_entity, + ev_pointer, ev_int, ev_entity, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_FLD_v6p] = {"", "pushb.fld", - ev_pointer, ev_integer, ev_field, + ev_pointer, ev_int, ev_field, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_FN_v6p] = {"", "pushb.fn", - ev_pointer, ev_integer, ev_func, + ev_pointer, ev_int, ev_func, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_P_v6p] = {"", "pushb.p", - ev_pointer, ev_integer, ev_pointer, + ev_pointer, ev_int, ev_pointer, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_Q_v6p] = {"", "pushb.q", - ev_pointer, ev_integer, ev_quat, + ev_pointer, ev_int, ev_quat, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_I_v6p] = {"", "pushb.i", - ev_pointer, ev_integer, ev_integer, + ev_pointer, ev_int, ev_int, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_D_v6p] = {"", "pushb.d", - ev_pointer, ev_integer, ev_double, + ev_pointer, ev_int, ev_double, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, @@ -1310,7 +1310,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "*(%Ga + %sb)", }, [OP_PUSHBI_I_v6p] = {"", "pushbi.i", - ev_pointer, ev_short, ev_integer, + ev_pointer, ev_short, ev_int, PROG_V6P_VERSION, "*(%Ga + %sb)", }, @@ -1361,7 +1361,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%ga", }, [OP_POP_I_v6p] = {"", "pop.i", - ev_integer, ev_invalid, ev_invalid, + ev_int, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, @@ -1372,52 +1372,52 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_POPB_S_v6p] = {"", "popb.s", - ev_pointer, ev_integer, ev_string, + ev_pointer, ev_int, ev_string, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_F_v6p] = {"", "popb.f", - ev_pointer, ev_integer, ev_float, + ev_pointer, ev_int, ev_float, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_V_v6p] = {"", "popb.v", - ev_pointer, ev_integer, ev_vector, + ev_pointer, ev_int, ev_vector, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_ENT_v6p] = {"", "popb.ent", - ev_pointer, ev_integer, ev_entity, + ev_pointer, ev_int, ev_entity, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_FLD_v6p] = {"", "popb.fld", - ev_pointer, ev_integer, ev_field, + ev_pointer, ev_int, ev_field, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_FN_v6p] = {"", "popb.fn", - ev_pointer, ev_integer, ev_func, + ev_pointer, ev_int, ev_func, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_P_v6p] = {"", "popb.p", - ev_pointer, ev_integer, ev_pointer, + ev_pointer, ev_int, ev_pointer, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_Q_v6p] = {"", "popb.q", - ev_pointer, ev_integer, ev_quat, + ev_pointer, ev_int, ev_quat, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_I_v6p] = {"", "popb.i", - ev_pointer, ev_integer, ev_integer, + ev_pointer, ev_int, ev_int, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_D_v6p] = {"", "popb.d", - ev_pointer, ev_integer, ev_double, + ev_pointer, ev_int, ev_double, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, @@ -1463,7 +1463,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "*(%Ga + %sb)", }, [OP_POPBI_I_v6p] = {"", "popbi.i", - ev_pointer, ev_short, ev_integer, + ev_pointer, ev_short, ev_int, PROG_V6P_VERSION, "*(%Ga + %sb)", }, @@ -1652,7 +1652,7 @@ PR_Check_Opcodes (progs_t *pr) break; case OP_DONE_v6p: case OP_RETURN_v6p: - check_global (pr, st, op, ev_integer, st->a, 1); + check_global (pr, st, op, ev_int, st->a, 1); check_global (pr, st, op, ev_void, st->b, 0); check_global (pr, st, op, ev_void, st->c, 0); break; @@ -1666,8 +1666,8 @@ PR_Check_Opcodes (progs_t *pr) case OP_RCALL7_v6p: case OP_RCALL8_v6p: if (st_op > OP_RCALL1_v6p) - check_global (pr, st, op, ev_integer, st->c, 1); - check_global (pr, st, op, ev_integer, st->b, 1); + check_global (pr, st, op, ev_int, st->c, 1); + check_global (pr, st, op, ev_int, st->b, 1); check_global (pr, st, op, ev_func, st->a, 1); break; case OP_STATE_v6p: diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index 2b1c6c5b4..726e18d8b 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -86,7 +86,7 @@ bi_gib_builtin_f (void) pr_list = PR_Zone_Malloc (builtin->pr, GIB_Argc() * sizeof (pr_type_t)); for (i = 0; i < GIB_Argc(); i++) - pr_list[i].integer_var = PR_SetTempString (builtin->pr, GIB_Argv(i)); + pr_list[i].int_var = PR_SetTempString (builtin->pr, GIB_Argv(i)); PR_RESET_PARAMS (builtin->pr); P_INT (builtin->pr, 0) = GIB_Argc(); diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 36827ad4e..5aed0b2a4 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -295,7 +295,7 @@ PF_Find (progs_t *pr) continue; RETURN_EDICT (pr, ed); return; - case ev_integer: + case ev_int: case ev_entity: if (P_INT (pr, 2) != E_INT (ed, f)) continue; @@ -420,7 +420,7 @@ PF_nextent (progs_t *pr) #endif /* - integer (float f) ftoi + int (float f) ftoi */ static void PF_ftoi (progs_t *pr) @@ -453,7 +453,7 @@ PF_ftos (progs_t *pr) } /* - float (integer i) itof + float (int i) itof */ static void PF_itof (progs_t *pr) @@ -462,7 +462,7 @@ PF_itof (progs_t *pr) } /* - string (integer i) itos + string (int i) itos */ static void PF_itos (progs_t *pr) @@ -484,7 +484,7 @@ PF_stof (progs_t *pr) } /* - integer (string s) stoi + int (string s) stoi */ static void PF_stoi (progs_t *pr) diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 4c8b86049..27a40d3d5 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -259,7 +259,7 @@ bi_Hash_FindList (progs_t *pr) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].integer_var = (intptr_t) *l; + pr_list[count++].int_var = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } @@ -278,7 +278,7 @@ bi_Hash_FindElementList (progs_t *pr) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].integer_var = (intptr_t) *l; + pr_list[count++].int_var = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } @@ -334,7 +334,7 @@ bi_Hash_GetList (progs_t *pr) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].integer_var = (intptr_t) *l; + pr_list[count++].int_var = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index fafc4fe85..66994f65c 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1444,21 +1444,21 @@ static void rua_obj_increment_retaincount (progs_t *pr) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = ++(*--obj).integer_var; + R_INT (pr) = ++(*--obj).int_var; } static void rua_obj_decrement_retaincount (progs_t *pr) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = --(*--obj).integer_var; + R_INT (pr) = --(*--obj).int_var; } static void rua_obj_get_retaincount (progs_t *pr) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = (*--obj).integer_var; + R_INT (pr) = (*--obj).int_var; } static void diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index f9776dcd4..aa32f3a41 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -77,7 +77,7 @@ static string get_type_key (void *type, void *unused) -(string) name { if (type.meta == ty_basic) { - if (type.type == ev_integer) { + if (type.type == ev_int) { return "int"; } return pr_type_name[type.type]; @@ -123,7 +123,7 @@ static string get_type_key (void *type, void *unused) -(string) parseData { if (type.meta == ty_basic) { - if (type.type == ev_integer) { + if (type.type == ev_int) { return "&cexpr_int"; } return "&cexpr_" + pr_type_name[type.type]; diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 975515eb0..a660b4e77 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -187,7 +187,7 @@ extern progs_t sv_pr_state; #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) #define SVvector(e,f) (&SVFIELD (e, f, vector)) -#define SVinteger(e,f) SVFIELD (e, f, integer) +#define SVint(e,f) SVFIELD (e, f, int) #if TYPECHECK_PROGS #define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) #else diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 3a8c44dd2..5c94f8080 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -323,7 +323,7 @@ static sv_def_t nq_opt_funcs[] = { }; static sv_def_t nq_opt_fields[] = { - {ev_integer, 0, "rotated_bbox", &sv_fields.rotated_bbox}, + {ev_int, 0, "rotated_bbox", &sv_fields.rotated_bbox}, {ev_float, 0, "alpha", &sv_fields.alpha}, {ev_float, 0, "gravity", &sv_fields.gravity}, {ev_float, 0, "items2", &sv_fields.items2}, @@ -355,8 +355,8 @@ set_address (sv_def_t *def, void *address) case ev_field: case ev_func: case ev_pointer: - case ev_integer: - case ev_uinteger: + case ev_int: + case ev_uint: *(pr_int_t **)def->field = (pr_int_t *) address; break; case ev_long: diff --git a/nq/source/world.c b/nq/source/world.c index a73e7c498..b8b423d83 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -215,7 +215,7 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, vec3_t hullmins, hullmaxs, size; if ((sv_fields.rotated_bbox != -1 - && SVinteger (ent, rotated_bbox)) + && SVint (ent, rotated_bbox)) || SVfloat (ent, solid) == SOLID_BSP) { VectorSubtract (maxs, mins, size); if (size[0] < 3) @@ -226,8 +226,8 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, hull_index = 2; } if (sv_fields.rotated_bbox != -1 - && SVinteger (ent, rotated_bbox)) { - int h = SVinteger (ent, rotated_bbox) - 1; + && SVint (ent, rotated_bbox)) { + int h = SVint (ent, rotated_bbox) - 1; hull_list = pf_hull_list[h]->hulls; } if (SVfloat (ent, solid) == SOLID_BSP) { // explicit hulls in the BSP model diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index c3391e2fb..b4d931c35 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -194,7 +194,7 @@ extern progs_t sv_pr_state; #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) #define SVvector(e,f) (&SVFIELD (e, f, vector)) -#define SVinteger(e,f) SVFIELD (e, f, integer) +#define SVint(e,f) SVFIELD (e, f, int) #if TYPECHECK_PROGS #define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) #else diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 87b871ec9..8937e7fc8 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -352,7 +352,7 @@ static sv_def_t qw_opt_funcs[] = { }; static sv_def_t qw_opt_fields[] = { - {ev_integer, 0, "rotated_bbox", &sv_fields.rotated_bbox}, + {ev_int, 0, "rotated_bbox", &sv_fields.rotated_bbox}, {ev_float, 0, "alpha", &sv_fields.alpha}, {ev_float, 0, "scale", &sv_fields.scale}, {ev_float, 0, "glow_size", &sv_fields.glow_size}, @@ -388,8 +388,8 @@ set_address (sv_def_t *def, void *address) case ev_field: case ev_func: case ev_pointer: - case ev_integer: - case ev_uinteger: + case ev_int: + case ev_uint: *(pr_int_t **)def->field = (pr_int_t *) address; break; case ev_long: diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 490127b33..2f37404b6 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -1548,8 +1548,8 @@ AddLinksToPmove (areanode_t *node) pe->info = NUM_FOR_EDICT (&sv_pr_state, check); if (sv_fields.rotated_bbox != -1 - && SVinteger (check, rotated_bbox)) { - int h = SVinteger (check, rotated_bbox) - 1; + && SVint (check, rotated_bbox)) { + int h = SVint (check, rotated_bbox) - 1; pe->hull = pf_hull_list[h]->hulls[1]; } else { diff --git a/qw/source/world.c b/qw/source/world.c index 877db0f38..7024bca6c 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -215,7 +215,7 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, vec3_t hullmins, hullmaxs, size; if ((sv_fields.rotated_bbox != -1 - && SVinteger (ent, rotated_bbox)) + && SVint (ent, rotated_bbox)) || SVfloat (ent, solid) == SOLID_BSP) { VectorSubtract (maxs, mins, size); if (size[0] < 3) @@ -226,8 +226,8 @@ SV_HullForEntity (edict_t *ent, const vec3_t mins, const vec3_t maxs, hull_index = 2; } if (sv_fields.rotated_bbox != -1 - && SVinteger (ent, rotated_bbox)) { - int h = SVinteger (ent, rotated_bbox) - 1; + && SVint (ent, rotated_bbox)) { + int h = SVint (ent, rotated_bbox) - 1; hull_list = pf_hull_list[h]->hulls; } if (SVfloat (ent, solid) == SOLID_BSP) { // explicit hulls in the BSP model diff --git a/ruamoko/cl_menu/plistmenu.r b/ruamoko/cl_menu/plistmenu.r index f94e6bdfc..2694e48b5 100644 --- a/ruamoko/cl_menu/plistmenu.r +++ b/ruamoko/cl_menu/plistmenu.r @@ -84,7 +84,7 @@ class_from_plist (PLDictionary *pldict) if (str_str (paramstr, ".") >= 0) va_list.list[j].float_val = stof (paramstr); else - va_list.list[j].integer_val = stoi (paramstr); + va_list.list[j].int_val = stoi (paramstr); break; } } diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index 19ec0c736..7054eeead 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -11,8 +11,8 @@ typedef enum { ev_func, ev_pointer, // end of v6 types ev_quat, - ev_integer, - ev_uinteger, + ev_int, + ev_uint, ev_short, // value is embedded in the opcode ev_double, diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index d6246e2ef..64429b273 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -221,7 +221,7 @@ error: break; case ty_enum: // enums are ints - size = pr_type_size[ev_integer]; + size = pr_type_size[ev_int]; break; case ty_class: //FIXME diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 61ff0b7ca..f75fd79ba 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -201,8 +201,8 @@ typedef struct ex_value_s { ex_func_t func_val; ///< function constant ex_pointer_t pointer; ///< pointer constant float quaternion_val[4]; ///< quaternion constant - int integer_val; ///< integer constant - unsigned uinteger_val; ///< unsigned integer constant + int int_val; ///< int constant + unsigned uint_val; ///< unsigned int constant short short_val; ///< short constant } v; } ex_value_t; @@ -571,23 +571,23 @@ expr_t *new_pointer_expr (int val, struct type_s *type, struct def_s *def); expr_t *new_quaternion_expr (const float *quaternion_val); const float *expr_quaternion (expr_t *e) __attribute__((pure)); -/** Create a new integer constant expression node. +/** Create a new itn constant expression node. - \param integer_val The integer constant being represented. - \return The new integer constant expression node - (expr_t::e::integer_val). + \param int_val The int constant being represented. + \return The new int constant expression node + (expr_t::e::int_val). */ -expr_t *new_integer_expr (int integer_val); -int expr_integer (expr_t *e) __attribute__((pure)); +expr_t *new_int_expr (int int_val); +int expr_int (expr_t *e) __attribute__((pure)); -/** Create a new integer constant expression node. +/** Create a new int constant expression node. - \param uinteger_val The integer constant being represented. - \return The new integer constant expression node - (expr_t::e::integer_val). + \param uint_val The int constant being represented. + \return The new int constant expression node + (expr_t::e::int_val). */ -expr_t *new_uinteger_expr (unsigned uinteger_val); -unsigned expr_uinteger (expr_t *e) __attribute__((pure)); +expr_t *new_uint_expr (unsigned uint_val); +unsigned expr_uint (expr_t *e) __attribute__((pure)); /** Create a new short constant expression node. @@ -652,8 +652,8 @@ int is_string_val (expr_t *e) __attribute__((pure)); int is_float_val (expr_t *e) __attribute__((pure)); int is_vector_val (expr_t *e) __attribute__((pure)); int is_quaternion_val (expr_t *e) __attribute__((pure)); -int is_integer_val (expr_t *e) __attribute__((pure)); -int is_uinteger_val (expr_t *e) __attribute__((pure)); +int is_int_val (expr_t *e) __attribute__((pure)); +int is_uint_val (expr_t *e) __attribute__((pure)); int is_short_val (expr_t *e) __attribute__((pure)); int is_integral_val (expr_t *e) __attribute__((pure)); int is_pointer_val (expr_t *e) __attribute__((pure)); diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 2aec16095..aecd3801a 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -334,10 +334,10 @@ enum { */ #define QFO_FLOAT(q, s, o) QFO_var (q, s, float, o) -/** Access a integer variable in the object file. Can be assigned to. +/** Access a int variable in the object file. Can be assigned to. \par QC type: - \c integer + \c int \param q pointer to ::qfo_t struct \param s space index \param o offset into object file data space @@ -345,7 +345,7 @@ enum { \hideinitializer */ -#define QFO_INT(q, s, o) QFO_var (q, s, integer, o) +#define QFO_INT(q, s, o) QFO_var (q, s, int, o) /** Access a vector variable in the object file. Can be assigned to. @@ -438,7 +438,7 @@ enum { \hideinitializer */ -#define QFO_POINTER(q, s, t, o) ((t *)(char *)&QFO_var (q, s, integer, o)) +#define QFO_POINTER(q, s, t, o) ((t *)(char *)&QFO_var (q, s, int, o)) /** Access a structure variable in the object file. Can be assigned to. diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index c129e8271..b678cc5a4 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -100,7 +100,7 @@ extern pr_info_t pr; #define D_var(t, d) ((d)->space->data[(d)->offset].t##_var) #define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset)) #define D_FLOAT(d) D_var (float, d) -#define D_INT(d) D_var (integer, d) +#define D_INT(d) D_var (int, d) #define D_VECTOR(d) (&D_var (vector, d)) #define D_QUAT(d) (&D_var (quat, d)) #define D_STRING(d) D_var (string, d) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index f985ea826..87ca80966 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -108,8 +108,8 @@ extern type_t type_function; extern type_t type_pointer; extern type_t type_floatfield; extern type_t type_quaternion; -extern type_t type_integer; -extern type_t type_uinteger; +extern type_t type_int; +extern type_t type_uint; extern type_t type_short; extern type_t *type_nil; // for passing nil into ... @@ -161,8 +161,8 @@ void encode_type (struct dstring_s *encoding, const type_t *type); const char *type_get_encoding (const type_t *type); int is_void (const type_t *type) __attribute__((pure)); int is_enum (const type_t *type) __attribute__((pure)); -int is_integer (const type_t *type) __attribute__((pure)); -int is_uinteger (const type_t *type) __attribute__((pure)); +int is_int (const type_t *type) __attribute__((pure)); +int is_uint (const type_t *type) __attribute__((pure)); int is_short (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); int is_double (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index a2f13dd67..21e10f43d 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -53,8 +53,8 @@ struct ex_value_s *new_pointer_val (int val, struct type_s *type, struct def_s *def, struct operand_s *tempop); struct ex_value_s *new_quaternion_val (const float *quaternion_val); -struct ex_value_s *new_integer_val (int integer_val); -struct ex_value_s *new_uinteger_val (int uinteger_val); +struct ex_value_s *new_int_val (int int_val); +struct ex_value_s *new_uint_val (int uint_val); struct ex_value_s *new_short_val (short short_val); struct ex_value_s *new_nil_val (struct type_s *type); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 99d6fbcb2..de0d473e6 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -132,7 +132,7 @@ static struct_def_t category_struct[] = { static struct_def_t ivar_struct[] = { {"ivar_name", &type_string}, {"ivar_type", &type_string}, - {"ivar_offset", &type_integer}, + {"ivar_offset", &type_int}, {0, 0} }; @@ -143,8 +143,8 @@ static struct_def_t super_struct[] = { }; static struct_def_t module_struct[] = { - {"version", &type_integer}, - {"size", &type_integer}, + {"version", &type_int}, + {"size", &type_int}, {"name", &type_string}, {"symtab", &type_pointer}, {0, 0} @@ -154,9 +154,9 @@ static struct_def_t class_struct[] = { {"class_pointer", &type_Class}, {"super_class", &type_Class}, {"name", &type_string}, - {"version", &type_integer}, - {"info", &type_integer}, - {"instance_size", &type_integer}, + {"version", &type_int}, + {"info", &type_int}, + {"instance_size", &type_int}, {"ivars", &type_pointer}, {"methods", &type_pointer}, {"dtable", &type_pointer}, @@ -729,8 +729,8 @@ emit_ivar_count (def_t *def, void *data, int index) { ivar_data_t *ivar_data = (ivar_data_t *) data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = ivar_data->count; } @@ -774,8 +774,8 @@ static def_t * emit_ivars (symtab_t *ivars, const char *name) { static struct_def_t ivar_list_struct[] = { - {"ivar_count", &type_integer, emit_ivar_count}, - {"ivar_list", 0, emit_ivar_list_item}, + {"ivar_count", &type_int, emit_ivar_count}, + {"ivar_list", 0, emit_ivar_list_item}, {0, 0} }; ivar_data_t ivar_data = {0, 0, 0}; @@ -1411,8 +1411,8 @@ emit_symtab_ref_cnt (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = 0; if (da->refs) D_INT (def) = da->refs->type->t.array.size; @@ -1435,8 +1435,8 @@ emit_symtab_cls_def_cnt (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = da->cls_def_cnt; } @@ -1445,8 +1445,8 @@ emit_symtab_cat_def_cnt (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = da->cat_def_cnt; } @@ -1489,11 +1489,11 @@ void class_finish_module (void) { static struct_def_t symtab_struct[] = { - {"sel_ref_cnt", &type_integer, emit_symtab_ref_cnt}, - {"refs", &type_SEL, emit_symtab_refs}, - {"cls_def_cnt", &type_integer, emit_symtab_cls_def_cnt}, - {"cat_def_cnt", &type_integer, emit_symtab_cat_def_cnt}, - {"defs", 0, emit_symtab_defs}, + {"sel_ref_cnt", &type_int, emit_symtab_ref_cnt}, + {"refs", &type_SEL, emit_symtab_refs}, + {"cls_def_cnt", &type_int, emit_symtab_cls_def_cnt}, + {"cat_def_cnt", &type_int, emit_symtab_cat_def_cnt}, + {"defs", 0, emit_symtab_defs}, {0, 0} }; @@ -1750,8 +1750,8 @@ emit_protocol_count (def_t *def, void *data, int index) { protocollist_t *protocols = (protocollist_t *) data; - if (!is_integer(def->type)) { - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) { + internal_error (0, "%s: expected int def", __FUNCTION__); } D_INT (def) = protocols->count; } @@ -1777,7 +1777,7 @@ emit_protocol_list (protocollist_t *protocols, const char *name) { static struct_def_t proto_list_struct[] = { {"next", &type_pointer, emit_protocol_next}, - {"count", &type_integer, emit_protocol_count}, + {"count", &type_int, emit_protocol_count}, {"list", 0, emit_protocol_list_item}, {0, 0}, }; diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 6ee98f70e..20a9c5716 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -76,7 +76,7 @@ cmp_result_expr (int result) if (is_float (type_default)) { return new_float_expr (result); } else { - return new_integer_expr(result); + return new_int_expr(result); } } @@ -92,7 +92,7 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else { @@ -153,7 +153,7 @@ convert_to_float (expr_t *e) switch (e->type) { case ex_value: switch (e->e.value->lltype) { - case ev_integer: + case ev_int: convert_int (e); return e; case ev_short: @@ -188,8 +188,8 @@ convert_to_double (expr_t *e) switch (e->type) { case ex_value: switch (e->e.value->lltype) { - case ev_integer: - e->e.value = new_double_val (expr_integer (e)); + case ev_int: + e->e.value = new_double_val (expr_int (e)); return e; case ev_short: e->e.value = new_double_val (expr_short (e)); @@ -235,7 +235,7 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2) } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - type = &type_integer; + type = &type_int; else type = &type_float; } @@ -354,7 +354,7 @@ do_op_double (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.e2 = e2 = conv; } if (is_compare (op) || is_logic (op)) { - type = &type_integer; + type = &type_int; } e->e.expr.type = type; @@ -456,7 +456,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else if (op == '*' && is_vector(get_type (e2))) { @@ -555,7 +555,7 @@ do_op_entity (int op, expr_t *e, expr_t *e1, expr_t *e2) } if (op == EQ || op == NE) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; return e; @@ -577,7 +577,7 @@ do_op_func (int op, expr_t *e, expr_t *e1, expr_t *e2) { if (op == EQ || op == NE) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; return e; @@ -606,23 +606,23 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) type = get_type (e1); if (type != get_type (e2)) return error (e2, "invalid operands to binary -"); - e1 = new_alias_expr (&type_integer, e1); - e2 = new_alias_expr (&type_integer, e2); + e1 = new_alias_expr (&type_int, e1); + e2 = new_alias_expr (&type_int, e2); e = binary_expr ('-', e1, e2); if (type_size (type) != 1) - e = binary_expr ('/', e, new_integer_expr (type_size (type))); + e = binary_expr ('/', e, new_int_expr (type_size (type))); return e; } if (op == EQ || op == NE) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } if (op != '.' && extract_type (e1) != extract_type (e2)) return type_mismatch (e1, e2, op); - if (op == '.' && is_uinteger(get_type (e2))) - e->e.expr.e2 = cf_cast_expr (&type_integer, e2); + if (op == '.' && is_uint(get_type (e2))) + e->e.expr.e2 = cf_cast_expr (&type_int, e2); return e; } @@ -677,7 +677,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else if (op == '/' && !is_constant (e1)) { @@ -759,7 +759,7 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2) } static expr_t * -do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) +do_op_int (int op, expr_t *e, expr_t *e1, expr_t *e2) { int isval1 = 0, isval2 = 0; int val1 = 0, val2 = 0; @@ -769,33 +769,33 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) }; if (!valid_op (op, valid)) - return error (e1, "invalid operator for integer"); + return error (e1, "invalid operator for int"); if (is_short_val (e1)) { isval1 = 1; val1 = expr_short (e1); } - if (is_integer_val (e1)) { + if (is_int_val (e1)) { isval1 = 1; - val1 = expr_integer (e1); + val1 = expr_int (e1); } if (is_short_val (e2)) { isval2 = 1; val2 = expr_short (e2); } - if (is_integer_val (e2)) { + if (is_int_val (e2)) { isval2 = 1; - val2 = expr_integer (e2); + val2 = expr_int (e2); } if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else { - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; } if (op == '*' && isval1 && val1 == 1) @@ -824,36 +824,36 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) switch (op) { case '+': - e = new_integer_expr (val1 + val2); + e = new_int_expr (val1 + val2); break; case '-': - e = new_integer_expr (val1 - val2); + e = new_int_expr (val1 - val2); break; case '*': - e = new_integer_expr (val1 * val2); + e = new_int_expr (val1 * val2); break; case '/': if (options.warnings.integer_divide) warning (e2, "%d / %d == %d", val1, val2, val1 / val2); - e = new_integer_expr (val1 / val2); + e = new_int_expr (val1 / val2); break; case '&': - e = new_integer_expr (val1 & val2); + e = new_int_expr (val1 & val2); break; case '|': - e = new_integer_expr (val1 | val2); + e = new_int_expr (val1 | val2); break; case '^': - e = new_integer_expr (val1 ^ val2); + e = new_int_expr (val1 ^ val2); break; case '%': - e = new_integer_expr (val1 % val2); + e = new_int_expr (val1 % val2); break; case SHL: - e = new_integer_expr (val1 << val2); + e = new_int_expr (val1 << val2); break; case SHR: - e = new_integer_expr (val1 >> val2); + e = new_int_expr (val1 >> val2); break; case AND: e = cmp_result_expr (val1 && val2); @@ -888,7 +888,7 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2) } static expr_t * -do_op_uinteger (int op, expr_t *e, expr_t *e1, expr_t *e2) +do_op_uint (int op, expr_t *e, expr_t *e1, expr_t *e2) { return e; } @@ -907,7 +907,7 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2) if (is_compare (op) || is_logic (op)) { if (options.code.progsversion > PROG_ID_VERSION) - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; else e->e.expr.type = &type_float; } else { @@ -1004,14 +1004,14 @@ do_op_compound (int op, expr_t *e, expr_t *e1, expr_t *e2) return do_op_float (op, e, e1, e2); if (t2->type == ev_double) return do_op_float (op, e, e1, e2); - return do_op_integer (op, e, e1, e2); + return do_op_int (op, e, e1, e2); } if (is_enum (t2)) { if (t1->type == ev_double) return do_op_double (op, e, e1, e2); if (t1->type == ev_float) return do_op_float (op, e, e1, e2); - return do_op_integer (op, e, e1, e2); + return do_op_int (op, e, e1, e2); } } return error (e1, "invalid operator for compound"); @@ -1062,8 +1062,8 @@ static operation_t op_void[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion - do_op_invalid, // ev_integer - do_op_invalid, // ev_uinteger + do_op_invalid, // ev_int + do_op_invalid, // ev_uint do_op_invalid, // ev_short do_op_invalid, // ev_double 0, // ev_long @@ -1081,8 +1081,8 @@ static operation_t op_string[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion - do_op_invalid, // ev_integer - do_op_invalid, // ev_uinteger + do_op_invalid, // ev_int + do_op_invalid, // ev_uint do_op_invalid, // ev_short do_op_invalid, // ev_double 0, // ev_long @@ -1100,8 +1100,8 @@ static operation_t op_float[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion - do_op_float, // ev_integer - do_op_float, // ev_uinteger + do_op_float, // ev_int + do_op_float, // ev_uint do_op_float, // ev_short do_op_double, // ev_double 0, // ev_long @@ -1119,8 +1119,8 @@ static operation_t op_vector[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion - do_op_vector, // ev_integer - do_op_vector, // ev_uinteger + do_op_vector, // ev_int + do_op_vector, // ev_uint do_op_vector, // ev_short do_op_vector, // ev_double 0, // ev_long @@ -1138,8 +1138,8 @@ static operation_t op_entity[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion - do_op_invalid, // ev_integer - do_op_invalid, // ev_uinteger + do_op_invalid, // ev_int + do_op_invalid, // ev_uint do_op_invalid, // ev_short do_op_invalid, // ev_double 0, // ev_long @@ -1157,8 +1157,8 @@ static operation_t op_field[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion - do_op_invalid, // ev_integer - do_op_invalid, // ev_uinteger + do_op_invalid, // ev_int + do_op_invalid, // ev_uint do_op_invalid, // ev_short do_op_invalid, // ev_double 0, // ev_long @@ -1176,8 +1176,8 @@ static operation_t op_func[ev_type_count] = { do_op_func, // ev_func do_op_func, // ev_pointer do_op_func, // ev_quaternion - do_op_func, // ev_integer - do_op_func, // ev_uinteger + do_op_func, // ev_int + do_op_func, // ev_uint do_op_func, // ev_short do_op_func, // ev_double 0, // ev_long @@ -1195,8 +1195,8 @@ static operation_t op_pointer[ev_type_count] = { do_op_pointer, // ev_func do_op_pointer, // ev_pointer do_op_pointer, // ev_quaternion - do_op_pointer, // ev_integer - do_op_pointer, // ev_uinteger + do_op_pointer, // ev_int + do_op_pointer, // ev_uint do_op_pointer, // ev_short do_op_pointer, // ev_double 0, // ev_long @@ -1214,8 +1214,8 @@ static operation_t op_quaternion[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion - do_op_quaternion, // ev_integer - do_op_quaternion, // ev_uinteger + do_op_quaternion, // ev_int + do_op_quaternion, // ev_uint do_op_quaternion, // ev_short do_op_quaternion, // ev_double 0, // ev_long @@ -1223,7 +1223,7 @@ static operation_t op_quaternion[ev_type_count] = { do_op_invalid, // ev_invalid }; -static operation_t op_integer[ev_type_count] = { +static operation_t op_int[ev_type_count] = { do_op_invalid, // ev_void do_op_invalid, // ev_string do_op_float, // ev_float @@ -1233,16 +1233,16 @@ static operation_t op_integer[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion - do_op_integer, // ev_integer - do_op_uinteger, // ev_uinteger - do_op_integer, // ev_short + do_op_int, // ev_int + do_op_uint, // ev_uint + do_op_int, // ev_short do_op_double, // ev_double 0, // ev_long 0, // ev_ulong do_op_invalid, // ev_invalid }; -static operation_t op_uinteger[ev_type_count] = { +static operation_t op_uint[ev_type_count] = { do_op_invalid, // ev_void do_op_invalid, // ev_string do_op_float, // ev_float @@ -1252,9 +1252,9 @@ static operation_t op_uinteger[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion - do_op_uinteger, // ev_integer - do_op_uinteger, // ev_uinteger - do_op_uinteger, // ev_short + do_op_uint, // ev_int + do_op_uint, // ev_uint + do_op_uint, // ev_short do_op_double, // ev_double 0, // ev_long 0, // ev_ulong @@ -1271,8 +1271,8 @@ static operation_t op_short[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion - do_op_integer, // ev_integer - do_op_uinteger, // ev_uinteger + do_op_int, // ev_int + do_op_uint, // ev_uint do_op_short, // ev_short do_op_double, // ev_double 0, // ev_long @@ -1290,8 +1290,8 @@ static operation_t op_double[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_quaternion, // ev_quaternion - do_op_integer, // ev_integer - do_op_uinteger, // ev_uinteger + do_op_int, // ev_int + do_op_uint, // ev_uint do_op_short, // ev_short do_op_double, // ev_double 0, // ev_long @@ -1309,8 +1309,8 @@ static operation_t op_compound[ev_type_count] = { do_op_invalid, // ev_func do_op_invalid, // ev_pointer do_op_invalid, // ev_quaternion - do_op_compound, // ev_integer - do_op_compound, // ev_uinteger + do_op_compound, // ev_int + do_op_compound, // ev_uint do_op_compound, // ev_short do_op_compound, // ev_double do_op_compound, // ev_long @@ -1328,8 +1328,8 @@ static operation_t *do_op[ev_type_count] = { op_func, // ev_func op_pointer, // ev_pointer op_quaternion, // ev_quaternion - op_integer, // ev_integer - op_uinteger, // ev_uinteger + op_int, // ev_int + op_uint, // ev_uint op_short, // ev_short op_double, // ev_double 0, // ev_long @@ -1390,7 +1390,7 @@ uop_float (int op, expr_t *e, expr_t *e1) if (op == '+') return e1; type = get_type (e); - if (op == 'C' && !is_integer(type) && !is_double(type)) + if (op == 'C' && !is_int(type) && !is_double(type)) return error (e1, "invalid cast of float"); if (!is_constant (e1)) return e; @@ -1403,8 +1403,8 @@ uop_float (int op, expr_t *e, expr_t *e1) case '~': return new_float_expr (~(int) expr_float (e1)); case 'C': - if (is_integer(type)) { - return new_integer_expr (expr_float (e1)); + if (is_int(type)) { + return new_int_expr (expr_float (e1)); } else { return new_double_expr (expr_float (e1)); } @@ -1533,7 +1533,7 @@ uop_quaternion (int op, expr_t *e, expr_t *e1) } static expr_t * -uop_integer (int op, expr_t *e, expr_t *e1) +uop_int (int op, expr_t *e, expr_t *e1) { static int valid[] = { '+', '-', '!', '~', 'C', 0 }; @@ -1548,19 +1548,19 @@ uop_integer (int op, expr_t *e, expr_t *e1) return e; switch (op) { case '-': - return new_integer_expr (-expr_integer (e1)); + return new_int_expr (-expr_int (e1)); case '!': - return cmp_result_expr (!expr_integer (e1)); + return cmp_result_expr (!expr_int (e1)); case '~': - return new_integer_expr (~expr_integer (e1)); + return new_int_expr (~expr_int (e1)); case 'C': - return new_float_expr (expr_integer (e1)); + return new_float_expr (expr_int (e1)); } - internal_error (e, "integer unary op blew up"); + internal_error (e, "int unary op blew up"); } static expr_t * -uop_uinteger (int op, expr_t *e, expr_t *e1) +uop_uint (int op, expr_t *e, expr_t *e1) { static int valid[] = { '+', '-', '!', '~', 0 }; @@ -1573,13 +1573,13 @@ uop_uinteger (int op, expr_t *e, expr_t *e1) return e; switch (op) { case '-': - return new_uinteger_expr (-expr_uinteger (e1)); + return new_uint_expr (-expr_uint (e1)); case '!': - return cmp_result_expr (!expr_uinteger (e1)); + return cmp_result_expr (!expr_uint (e1)); case '~': - return new_uinteger_expr (~expr_uinteger (e1)); + return new_uint_expr (~expr_uint (e1)); } - internal_error (e, "uinteger unary op blew up"); + internal_error (e, "uint unary op blew up"); } static expr_t * @@ -1617,7 +1617,7 @@ uop_double (int op, expr_t *e, expr_t *e1) if (op == '+') return e1; type = get_type (e); - if (op == 'C' && !is_integer(type) && !is_float(type)) + if (op == 'C' && !is_int(type) && !is_float(type)) return error (e1, "invalid cast of double"); if (!is_constant (e1)) return e; @@ -1628,8 +1628,8 @@ uop_double (int op, expr_t *e, expr_t *e1) print_type (get_type (e)); return cmp_result_expr (!expr_double (e1)); case 'C': - if (is_integer(type)) { - return new_integer_expr (expr_double (e1)); + if (is_int(type)) { + return new_int_expr (expr_double (e1)); } else { return new_float_expr (expr_double (e1)); } @@ -1644,7 +1644,7 @@ uop_compound (int op, expr_t *e, expr_t *e1) if (is_scalar (t1)) { if (is_enum (t1)) { - return uop_integer (op, e, e1); + return uop_int (op, e, e1); } } return error (e1, "invalid operand for unary %s", get_op_string (op)); @@ -1660,8 +1660,8 @@ static unaryop_t do_unary_op[ev_type_count] = { uop_func, // ev_func uop_pointer, // ev_pointer uop_quaternion, // ev_quaternion - uop_integer, // ev_integer - uop_uinteger, // ev_uinteger + uop_int, // ev_int + uop_uint, // ev_uint uop_short, // ev_short uop_double, // ev_double uop_compound, // ev_invalid diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index 644ee31d9..4afff69ee 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -164,7 +164,7 @@ emit_basedir (def_t *def, void *data, int index) static void emit_num_files (def_t *def, void *data, int index) { - if (!is_integer (def->type)) { + if (!is_int (def->type)) { internal_error (0, "%s: expected int def", __FUNCTION__); } D_INT (def) = pr.comp_files.size; @@ -189,7 +189,7 @@ emit_compunit (const char *modname) static struct_def_t compunit_struct[] = { {"unit_name", &type_string, emit_unit_name}, {"basedir", &type_string, emit_basedir}, - {"num_files", &type_integer, emit_num_files}, + {"num_files", &type_int, emit_num_files}, {"files", 0, emit_files_item}, {0, 0} }; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 94cc49ce1..cf854a1b4 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -378,8 +378,7 @@ init_elements (struct def_s *def, expr_t *eles) reloc_def_op (c->e.labelref.label, &dummy); continue; } else if (c->type == ex_value) { - if (c->e.value->lltype == ev_integer - && is_float (element->type)) { + if (c->e.value->lltype == ev_int && is_float (element->type)) { convert_int (c); } if (is_double (get_type (c)) && is_float (element->type) @@ -610,7 +609,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, } while (init->type == ex_alias) { if (init->e.alias.offset) { - offset += expr_integer (init->e.alias.offset); + offset += expr_int (init->e.alias.offset); } init = init->e.alias.expr; } diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index a66009bd5..d1cbfee26 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -573,16 +573,16 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) } break; case ev_entity: - label = va (0, "ent %d", e->e.value->v.integer_val); + label = va (0, "ent %d", e->e.value->v.int_val); break; case ev_func: - label = va (0, "func %d", e->e.value->v.integer_val); + label = va (0, "func %d", e->e.value->v.int_val); break; - case ev_integer: - label = va (0, "i %d", e->e.value->v.integer_val); + case ev_int: + label = va (0, "i %d", e->e.value->v.int_val); break; - case ev_uinteger: - label = va (0, "u %u", e->e.value->v.uinteger_val); + case ev_uint: + label = va (0, "u %u", e->e.value->v.uint_val); break; case ev_long: label = va (0, "i %"PRIi64, e->e.value->v.long_val); diff --git a/tools/qfcc/source/dot_type.c b/tools/qfcc/source/dot_type.c index 522fa91fb..fa77bbf3d 100644 --- a/tools/qfcc/source/dot_type.c +++ b/tools/qfcc/source/dot_type.c @@ -169,7 +169,7 @@ print_struct (dstring_t *dstr, type_t *t, int level, int id) int val; const char *port = ""; if (sym->sy_type == sy_const) { - val = sym->s.value->v.integer_val; + val = sym->s.value->v.int_val; } else { if (sym->sy_type != sy_var) { continue; diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index f27f33d4b..e55c10104 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -141,7 +141,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) G_QUAT (pr, offset)[2], G_QUAT (pr, offset)[3]); break; - case ev_integer: + case ev_int: comment = va (0, " %d", G_INT (pr, offset)); break; case ev_short: @@ -327,7 +327,7 @@ qfo_globals (qfo_t *qfo) QFO_TYPESTR (qfo, def->type)); if (!(def->flags & QFOD_EXTERNAL) && qfo->spaces[space].data) printf (" %d", - qfo->spaces[space].data[def->offset].integer_var); + qfo->spaces[space].data[def->offset].int_var); puts (""); } } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 0b70c6ae4..47daa1348 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -91,7 +91,7 @@ convert_name (expr_t *e) } if (!strcmp (sym->name, "__LINE__") && current_func) { - new = new_integer_expr (e->line); + new = new_int_expr (e->line); goto convert; } if (!strcmp (sym->name, "__INFINITY__") @@ -230,7 +230,7 @@ get_type (expr_t *e) case ex_bool: if (options.code.progsversion == PROG_ID_VERSION) return &type_float; - return &type_integer; + return &type_int; case ex_nil: if (e->e.nil) { return e->e.nil; @@ -888,20 +888,20 @@ new_quaternion_expr (const float *quaternion_val) } expr_t * -new_integer_expr (int integer_val) +new_int_expr (int int_val) { expr_t *e = new_expr (); e->type = ex_value; - e->e.value = new_integer_val (integer_val); + e->e.value = new_int_val (int_val); return e; } expr_t * -new_uinteger_expr (unsigned uinteger_val) +new_uint_expr (unsigned uint_val) { expr_t *e = new_expr (); e->type = ex_value; - e->e.value = new_uinteger_val (uinteger_val); + e->e.value = new_uint_val (uint_val); return e; } @@ -1104,12 +1104,12 @@ expr_quaternion (expr_t *e) } int -is_integer_val (expr_t *e) +is_int_val (expr_t *e) { if (e->type == ex_nil) { return 1; } - if (e->type == ex_value && e->e.value->lltype == ev_integer) { + if (e->type == ex_value && e->e.value->lltype == ev_int) { return 1; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const @@ -1124,18 +1124,18 @@ is_integer_val (expr_t *e) } int -expr_integer (expr_t *e) +expr_int (expr_t *e) { if (e->type == ex_nil) { return 0; } - if (e->type == ex_value && e->e.value->lltype == ev_integer) { - return e->e.value->v.integer_val; + if (e->type == ex_value && e->e.value->lltype == ev_int) { + return e->e.value->v.int_val; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && (e->e.symbol->type->type == ev_integer + && (e->e.symbol->type->type == ev_int || is_enum (e->e.symbol->type))) { - return e->e.symbol->s.value->v.integer_val; + return e->e.symbol->s.value->v.int_val; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var && e->e.symbol->s.def->constant @@ -1146,16 +1146,16 @@ expr_integer (expr_t *e) && is_integral (e->e.def->type)) { return D_INT (e->e.def); } - internal_error (e, "not an integer constant"); + internal_error (e, "not an int constant"); } int -is_uinteger_val (expr_t *e) +is_uint_val (expr_t *e) { if (e->type == ex_nil) { return 1; } - if (e->type == ex_value && e->e.value->lltype == ev_uinteger) { + if (e->type == ex_value && e->e.value->lltype == ev_uint) { return 1; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const @@ -1170,17 +1170,17 @@ is_uinteger_val (expr_t *e) } unsigned -expr_uinteger (expr_t *e) +expr_uint (expr_t *e) { if (e->type == ex_nil) { return 0; } - if (e->type == ex_value && e->e.value->lltype == ev_uinteger) { - return e->e.value->v.uinteger_val; + if (e->type == ex_value && e->e.value->lltype == ev_uint) { + return e->e.value->v.uint_val; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && e->e.symbol->type->type == ev_uinteger) { - return e->e.symbol->s.value->v.uinteger_val; + && e->e.symbol->type->type == ev_uint) { + return e->e.symbol->s.value->v.uint_val; } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var && e->e.symbol->s.def->constant @@ -1230,10 +1230,10 @@ int is_integral_val (expr_t *e) { if (is_constant (e)) { - if (is_integer_val (e)) { + if (is_int_val (e)) { return 1; } - if (is_uinteger_val (e)) { + if (is_uint_val (e)) { return 1; } if (is_short_val (e)) { @@ -1247,11 +1247,11 @@ int expr_integral (expr_t *e) { if (is_constant (e)) { - if (is_integer_val (e)) { - return expr_integer (e); + if (is_int_val (e)) { + return expr_int (e); } - if (is_uinteger_val (e)) { - return expr_uinteger (e); + if (is_uint_val (e)) { + return expr_uint (e); } if (is_short_val (e)) { return expr_short (e); @@ -1293,7 +1293,7 @@ new_offset_alias_expr (type_t *type, expr_t *expr, int offset) if (!is_constant (ofs_expr)) { internal_error (ofs_expr, "non-constant offset for alias expr"); } - offset += expr_integer (ofs_expr); + offset += expr_int (ofs_expr); if (expr->e.alias.expr->type == ex_alias) { internal_error (expr, "alias expr of alias expr"); @@ -1305,7 +1305,7 @@ new_offset_alias_expr (type_t *type, expr_t *expr, int offset) alias->type = ex_alias; alias->e.alias.type = type; alias->e.alias.expr = expr; - alias->e.alias.offset = new_integer_expr (offset); + alias->e.alias.offset = new_int_expr (offset); alias->file = expr->file; alias->line = expr->line; return alias; @@ -1517,14 +1517,14 @@ convert_from_bool (expr_t *e, type_t *type) if (is_float (type)) { one = new_float_expr (1); zero = new_float_expr (0); - } else if (is_integer (type)) { - one = new_integer_expr (1); - zero = new_integer_expr (0); + } else if (is_int (type)) { + one = new_int_expr (1); + zero = new_int_expr (0); } else if (is_enum (type) && enum_as_bool (type, &zero, &one)) { // don't need to do anything - } else if (is_uinteger (type)) { - one = new_uinteger_expr (1); - zero = new_uinteger_expr (0); + } else if (is_uint (type)) { + one = new_uint_expr (1); + zero = new_uint_expr (0); } else { return error (e, "can't convert from bool value"); } @@ -1541,7 +1541,7 @@ convert_from_bool (expr_t *e, type_t *type) void convert_int (expr_t *e) { - float float_val = expr_integer (e); + float float_val = expr_int (e); e->type = ex_value; e->e.value = new_float_val (float_val); } @@ -1557,9 +1557,9 @@ convert_short (expr_t *e) void convert_short_int (expr_t *e) { - float integer_val = expr_short (e); + float int_val = expr_short (e); e->type = ex_value; - e->e.value = new_integer_val (integer_val); + e->e.value = new_int_val (int_val); } void @@ -1712,10 +1712,10 @@ unary_expr (int op, expr_t *e) case ev_long: case ev_ulong: internal_error (e, "long not implemented"); - case ev_integer: - return new_integer_expr (-expr_integer (e)); - case ev_uinteger: - return new_uinteger_expr (-expr_uinteger (e)); + case ev_int: + return new_int_expr (-expr_int (e)); + case ev_uint: + return new_uint_expr (-expr_uint (e)); case ev_short: return new_short_expr (-expr_short (e)); case ev_invalid: @@ -1801,22 +1801,22 @@ unary_expr (int op, expr_t *e) internal_error (e, 0); case ev_string: s = expr_string (e); - return new_integer_expr (!s || !s[0]); + return new_int_expr (!s || !s[0]); case ev_double: - return new_integer_expr (!expr_double (e)); + return new_int_expr (!expr_double (e)); case ev_float: - return new_integer_expr (!expr_float (e)); + return new_int_expr (!expr_float (e)); case ev_vector: - return new_integer_expr (!VectorIsZero (expr_vector (e))); + return new_int_expr (!VectorIsZero (expr_vector (e))); case ev_quat: - return new_integer_expr (!QuatIsZero (expr_quaternion (e))); + return new_int_expr (!QuatIsZero (expr_quaternion (e))); case ev_long: case ev_ulong: internal_error (e, "long not implemented"); - case ev_integer: - return new_integer_expr (!expr_integer (e)); - case ev_uinteger: - return new_uinteger_expr (!expr_uinteger (e)); + case ev_int: + return new_int_expr (!expr_int (e)); + case ev_uint: + return new_uint_expr (!expr_uint (e)); case ev_short: return new_short_expr (!expr_short (e)); case ev_invalid: @@ -1856,7 +1856,7 @@ unary_expr (int op, expr_t *e) expr_t *n = new_unary_expr (op, e); if (options.code.progsversion > PROG_ID_VERSION) - n->e.expr.type = &type_integer; + n->e.expr.type = &type_int; else n->e.expr.type = &type_float; return n; @@ -1887,16 +1887,16 @@ unary_expr (int op, expr_t *e) case ev_long: case ev_ulong: internal_error (e, "long not implemented"); - case ev_integer: - return new_integer_expr (~expr_integer (e)); - case ev_uinteger: - return new_uinteger_expr (~expr_uinteger (e)); + case ev_int: + return new_int_expr (~expr_int (e)); + case ev_uint: + return new_uint_expr (~expr_uint (e)); case ev_short: return new_short_expr (~expr_short (e)); case ev_invalid: t = get_type (e); if (t->meta == ty_enum) { - return new_integer_expr (~expr_integer (e)); + return new_int_expr (~expr_int (e)); } break; case ev_type_count: @@ -1936,13 +1936,13 @@ unary_expr (int op, expr_t *e) case ex_assign: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { - expr_t *n1 = new_integer_expr (-1); + expr_t *n1 = new_int_expr (-1); return binary_expr ('-', n1, e); } else { expr_t *n = new_unary_expr (op, e); type_t *t = get_type (e); - if (!is_integer(t) && !is_float(t) + if (!is_int(t) && !is_float(t) && !is_quaternion(t)) return error (e, "invalid type for unary ~"); n->e.expr.type = t; @@ -2052,7 +2052,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) convert_nil (e, t = type_nil); if (e->type == ex_bool) convert_from_bool (e, get_type (e)); - if (is_integer_val (e) + if (is_int_val (e) && options.code.progsversion == PROG_ID_VERSION) convert_int (e); if (options.code.promote_float) { @@ -2070,8 +2070,8 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) } } } - if (is_integer_val (e) && options.warnings.vararg_integer) - warning (e, "passing integer constant into ... function"); + if (is_int_val (e) && options.warnings.vararg_integer) + warning (e, "passing int constant into ... function"); } arg_types[arg_count - 1 - i] = t; } @@ -2265,7 +2265,7 @@ return_expr (function_t *f, expr_t *e) if (e->type == ex_bool) { e = convert_from_bool (e, (type_t *) ret_type); //FIXME cast } - if (is_float(ret_type) && is_integer_val (e)) { + if (is_float(ret_type) && is_int_val (e)) { convert_int (e); t = &type_float; } @@ -2352,7 +2352,7 @@ incop_expr (int op, expr_t *e, int postop) if (e->type == ex_error) return e; - one = new_integer_expr (1); // integer constants get auto-cast to float + one = new_int_expr (1); // int constants get auto-cast to float if (postop) { expr_t *t1, *t2; type_t *type = get_type (e); @@ -2398,22 +2398,22 @@ array_expr (expr_t *array, expr_t *index) return error (index, "invalid array index type"); if (is_short_val (index)) ind = expr_short (index); - if (is_integer_val (index)) - ind = expr_integer (index); + if (is_int_val (index)) + ind = expr_int (index); if (array_type->t.func.num_params && is_constant (index) && (ind < array_type->t.array.base || ind - array_type->t.array.base >= array_type->t.array.size)) return error (index, "array index out of bounds"); - scale = new_integer_expr (type_size (array_type->t.array.type)); + scale = new_int_expr (type_size (array_type->t.array.type)); index = binary_expr ('*', index, scale); - base = new_integer_expr (array_type->t.array.base); + base = new_int_expr (array_type->t.array.base); offset = binary_expr ('*', base, scale); index = binary_expr ('-', index, offset); if (is_short_val (index)) ind = expr_short (index); - if (is_integer_val (index)) - ind = expr_integer (index); + if (is_int_val (index)) + ind = expr_int (index); if ((is_constant (index) && ind < 32768 && ind >= -32768)) index = new_short_expr (ind); if (is_array (array_type)) { @@ -2438,7 +2438,7 @@ pointer_expr (expr_t *pointer) return pointer; if (pointer_type->type != ev_pointer) return error (pointer, "not a pointer"); - return array_expr (pointer, new_integer_expr (0)); + return array_expr (pointer, new_int_expr (0)); } expr_t * @@ -2754,7 +2754,7 @@ build_state_expr (expr_t *e) step = think->next; if (think->type == ex_symbol) think = think_expr (think->e.symbol); - if (is_integer_val (frame)) + if (is_int_val (frame)) convert_int (frame); if (!type_assignable (&type_float, get_type (frame))) return error (frame, "invalid type for frame number"); @@ -2763,7 +2763,7 @@ build_state_expr (expr_t *e) if (step) { if (step->next) return error (step->next, "too many state arguments"); - if (is_integer_val (step)) + if (is_int_val (step)) convert_int (step); if (!type_assignable (&type_float, get_type (step))) return error (step, "invalid type for step"); @@ -2843,7 +2843,7 @@ cast_expr (type_t *dstType, expr_t *e) } else if (is_double (def->type)) { val = new_double_val (D_DOUBLE (def)); } else if (is_integral (def->type)) { - val = new_integer_val (D_INT (def)); + val = new_int_val (D_INT (def)); } } else if (e->type == ex_value) { val = e->e.value; @@ -2889,7 +2889,7 @@ sizeof_expr (expr_t *expr, struct type_s *type) internal_error (0, 0); if (!type) type = get_type (expr); - expr = new_integer_expr (type_size (type)); + expr = new_int_expr (type_size (type)); return expr; } diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index df304f119..885f87ef1 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -53,12 +53,12 @@ static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); static expr_type_t string_string[] = { {'+', &type_string}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; @@ -74,14 +74,14 @@ static expr_type_t float_float[] = { {MOD, &type_float}, {SHL, &type_float}, {SHR, &type_float}, - {AND, &type_integer}, - {OR, &type_integer}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {AND, &type_int}, + {OR, &type_int}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; @@ -95,7 +95,7 @@ static expr_type_t float_quat[] = { {0, 0} }; -static expr_type_t float_integer[] = { +static expr_type_t float_int[] = { {'+', &type_float, 0, &type_float}, {'-', &type_float, 0, &type_float}, {'*', &type_float, 0, &type_float}, @@ -107,16 +107,16 @@ static expr_type_t float_integer[] = { {MOD, &type_float, 0, &type_float}, {SHL, &type_float, 0, &type_float}, {SHR, &type_float, 0, &type_float}, - {EQ, &type_integer, 0, &type_float}, - {NE, &type_integer, 0, &type_float}, - {LE, &type_integer, 0, &type_float}, - {GE, &type_integer, 0, &type_float}, - {LT, &type_integer, 0, &type_float}, - {GT, &type_integer, 0, &type_float}, + {EQ, &type_int, 0, &type_float}, + {NE, &type_int, 0, &type_float}, + {LE, &type_int, 0, &type_float}, + {GE, &type_int, 0, &type_float}, + {LT, &type_int, 0, &type_float}, + {GT, &type_int, 0, &type_float}, {0, 0} }; -#define float_uinteger float_integer -#define float_short float_integer +#define float_uint float_int +#define float_short float_int static expr_type_t float_double[] = { {'+', &type_double, &type_double, 0}, @@ -144,13 +144,13 @@ static expr_type_t vector_vector[] = { {'+', &type_vector}, {'-', &type_vector}, {'*', &type_float}, - {EQ, &type_integer}, - {NE, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, {0, 0} }; -#define vector_integer vector_float -#define vector_uinteger vector_float +#define vector_int vector_float +#define vector_uint vector_float #define vector_short vector_float static expr_type_t vector_double[] = { @@ -160,20 +160,20 @@ static expr_type_t vector_double[] = { }; static expr_type_t entity_entity[] = { - {EQ, &type_integer}, - {NE, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, {0, 0} }; static expr_type_t field_field[] = { - {EQ, &type_integer}, - {NE, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, {0, 0} }; static expr_type_t func_func[] = { - {EQ, &type_integer}, - {NE, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, {0, 0} }; @@ -188,13 +188,13 @@ static expr_type_t pointer_pointer[] = { {0, 0} }; -static expr_type_t pointer_integer[] = { +static expr_type_t pointer_int[] = { {'+', 0, 0, 0, pointer_arithmetic}, {'-', 0, 0, 0, pointer_arithmetic}, {0, 0} }; -#define pointer_uinteger pointer_integer -#define pointer_short pointer_integer +#define pointer_uint pointer_int +#define pointer_short pointer_int static expr_type_t quat_float[] = { {'*', &type_quaternion}, @@ -211,18 +211,18 @@ static expr_type_t quat_quat[] = { {'+', &type_quaternion}, {'-', &type_quaternion}, {'*', &type_quaternion}, - {EQ, &type_integer}, - {NE, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, {0, 0} }; -static expr_type_t quat_integer[] = { +static expr_type_t quat_int[] = { {'*', &type_quaternion, 0, &type_float}, {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; -#define quat_uinteger quat_integer -#define quat_short quat_integer +#define quat_uint quat_int +#define quat_short quat_int static expr_type_t quat_double[] = { {'*', &type_quaternion}, @@ -230,7 +230,7 @@ static expr_type_t quat_double[] = { {0, 0} }; -static expr_type_t integer_float[] = { +static expr_type_t int_float[] = { {'+', &type_float, &type_float, 0}, {'-', &type_float, &type_float, 0}, {'*', &type_float, &type_float, 0}, @@ -240,206 +240,206 @@ static expr_type_t integer_float[] = { {'^', &type_float, &type_float, 0}, {'%', &type_float, &type_float, 0}, {MOD, &type_float, &type_float, 0}, - {SHL, &type_integer, 0, &type_integer}, //FIXME? - {SHR, &type_integer, 0, &type_integer}, //FIXME? - {EQ, &type_integer, &type_float, 0}, - {NE, &type_integer, &type_float, 0}, - {LE, &type_integer, &type_float, 0}, - {GE, &type_integer, &type_float, 0}, - {LT, &type_integer, &type_float, 0}, - {GT, &type_integer, &type_float, 0}, + {SHL, &type_int, 0, &type_int}, //FIXME? + {SHR, &type_int, 0, &type_int}, //FIXME? + {EQ, &type_int, &type_float, 0}, + {NE, &type_int, &type_float, 0}, + {LE, &type_int, &type_float, 0}, + {GE, &type_int, &type_float, 0}, + {LT, &type_int, &type_float, 0}, + {GT, &type_int, &type_float, 0}, {0, 0} }; -static expr_type_t integer_vector[] = { +static expr_type_t int_vector[] = { {'*', &type_vector, &type_float, 0}, {0, 0} }; -static expr_type_t integer_pointer[] = { +static expr_type_t int_pointer[] = { {'+', 0, 0, 0, pointer_arithmetic}, {0, 0} }; -static expr_type_t integer_quat[] = { +static expr_type_t int_quat[] = { {'*', &type_quaternion, &type_float, 0}, {0, 0} }; -static expr_type_t integer_integer[] = { - {'+', &type_integer}, - {'-', &type_integer}, - {'*', &type_integer}, - {'/', &type_integer}, - {'&', &type_integer}, - {'|', &type_integer}, - {'^', &type_integer}, - {'%', &type_integer}, - {MOD, &type_integer}, - {SHL, &type_integer}, - {SHR, &type_integer}, - {AND, &type_integer}, - {OR, &type_integer}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, +static expr_type_t int_int[] = { + {'+', &type_int}, + {'-', &type_int}, + {'*', &type_int}, + {'/', &type_int}, + {'&', &type_int}, + {'|', &type_int}, + {'^', &type_int}, + {'%', &type_int}, + {MOD, &type_int}, + {SHL, &type_int}, + {SHR, &type_int}, + {AND, &type_int}, + {OR, &type_int}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; -static expr_type_t integer_uinteger[] = { - {'+', &type_integer}, - {'-', &type_integer}, - {'*', &type_integer}, - {'/', &type_integer}, - {'&', &type_integer}, - {'|', &type_integer}, - {'^', &type_integer}, - {'%', &type_integer}, - {MOD, &type_integer}, - {SHL, &type_integer}, - {SHR, &type_integer}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, +static expr_type_t int_uint[] = { + {'+', &type_int}, + {'-', &type_int}, + {'*', &type_int}, + {'/', &type_int}, + {'&', &type_int}, + {'|', &type_int}, + {'^', &type_int}, + {'%', &type_int}, + {MOD, &type_int}, + {SHL, &type_int}, + {SHR, &type_int}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; -static expr_type_t integer_short[] = { - {'+', &type_integer, 0, &type_integer}, - {'-', &type_integer, 0, &type_integer}, - {'*', &type_integer, 0, &type_integer}, - {'/', &type_integer, 0, &type_integer}, - {'&', &type_integer, 0, &type_integer}, - {'|', &type_integer, 0, &type_integer}, - {'^', &type_integer, 0, &type_integer}, - {'%', &type_integer, 0, &type_integer}, - {MOD, &type_integer, 0, &type_integer}, - {SHL, &type_integer, 0, &type_integer}, - {SHR, &type_integer, 0, &type_integer}, - {EQ, &type_integer, 0, &type_integer}, - {NE, &type_integer, 0, &type_integer}, - {LE, &type_integer, 0, &type_integer}, - {GE, &type_integer, 0, &type_integer}, - {LT, &type_integer, 0, &type_integer}, - {GT, &type_integer, 0, &type_integer}, +static expr_type_t int_short[] = { + {'+', &type_int, 0, &type_int}, + {'-', &type_int, 0, &type_int}, + {'*', &type_int, 0, &type_int}, + {'/', &type_int, 0, &type_int}, + {'&', &type_int, 0, &type_int}, + {'|', &type_int, 0, &type_int}, + {'^', &type_int, 0, &type_int}, + {'%', &type_int, 0, &type_int}, + {MOD, &type_int, 0, &type_int}, + {SHL, &type_int, 0, &type_int}, + {SHR, &type_int, 0, &type_int}, + {EQ, &type_int, 0, &type_int}, + {NE, &type_int, 0, &type_int}, + {LE, &type_int, 0, &type_int}, + {GE, &type_int, 0, &type_int}, + {LT, &type_int, 0, &type_int}, + {GT, &type_int, 0, &type_int}, {0, 0} }; -static expr_type_t integer_double[] = { +static expr_type_t int_double[] = { {'+', &type_double, &type_double, 0}, {'-', &type_double, &type_double, 0}, {'*', &type_double, &type_double, 0}, {'/', &type_double, &type_double, 0}, {'%', &type_double, &type_double, 0}, {MOD, &type_double, &type_double, 0}, - {EQ, &type_integer, &type_double, 0}, - {NE, &type_integer, &type_double, 0}, - {LE, &type_integer, &type_double, 0}, - {GE, &type_integer, &type_double, 0}, - {LT, &type_integer, &type_double, 0}, - {GT, &type_integer, &type_double, 0}, + {EQ, &type_int, &type_double, 0}, + {NE, &type_int, &type_double, 0}, + {LE, &type_int, &type_double, 0}, + {GE, &type_int, &type_double, 0}, + {LT, &type_int, &type_double, 0}, + {GT, &type_int, &type_double, 0}, {0, 0} }; -#define uinteger_float integer_float -#define uinteger_vector integer_vector -#define uinteger_pointer integer_pointer -#define uinteger_quat integer_quat +#define uint_float int_float +#define uint_vector int_vector +#define uint_pointer int_pointer +#define uint_quat int_quat -static expr_type_t uinteger_integer[] = { - {'+', &type_integer}, - {'-', &type_integer}, - {'*', &type_integer}, - {'/', &type_integer}, - {'&', &type_integer}, - {'|', &type_integer}, - {'^', &type_integer}, - {'%', &type_integer}, - {MOD, &type_integer}, - {SHL, &type_uinteger}, - {SHR, &type_uinteger}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, +static expr_type_t uint_int[] = { + {'+', &type_int}, + {'-', &type_int}, + {'*', &type_int}, + {'/', &type_int}, + {'&', &type_int}, + {'|', &type_int}, + {'^', &type_int}, + {'%', &type_int}, + {MOD, &type_int}, + {SHL, &type_uint}, + {SHR, &type_uint}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; -static expr_type_t uinteger_uinteger[] = { - {'+', &type_uinteger}, - {'-', &type_uinteger}, - {'*', &type_uinteger}, - {'/', &type_uinteger}, - {'&', &type_uinteger}, - {'|', &type_uinteger}, - {'^', &type_uinteger}, - {'%', &type_uinteger}, - {MOD, &type_uinteger}, - {SHL, &type_uinteger}, - {SHR, &type_uinteger}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, +static expr_type_t uint_uint[] = { + {'+', &type_uint}, + {'-', &type_uint}, + {'*', &type_uint}, + {'/', &type_uint}, + {'&', &type_uint}, + {'|', &type_uint}, + {'^', &type_uint}, + {'%', &type_uint}, + {MOD, &type_uint}, + {SHL, &type_uint}, + {SHR, &type_uint}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; -#define uinteger_short uinteger_integer -#define uinteger_double integer_double +#define uint_short uint_int +#define uint_double int_double -#define short_float integer_float -#define short_vector integer_vector -#define short_pointer integer_pointer -#define short_quat integer_quat +#define short_float int_float +#define short_vector int_vector +#define short_pointer int_pointer +#define short_quat int_quat -static expr_type_t short_integer[] = { - {'+', &type_integer, &type_integer, 0}, - {'-', &type_integer, &type_integer, 0}, - {'*', &type_integer, &type_integer, 0}, - {'/', &type_integer, &type_integer, 0}, - {'&', &type_integer, &type_integer, 0}, - {'|', &type_integer, &type_integer, 0}, - {'^', &type_integer, &type_integer, 0}, - {'%', &type_integer, &type_integer, 0}, - {MOD, &type_integer, &type_integer, 0}, +static expr_type_t short_int[] = { + {'+', &type_int, &type_int, 0}, + {'-', &type_int, &type_int, 0}, + {'*', &type_int, &type_int, 0}, + {'/', &type_int, &type_int, 0}, + {'&', &type_int, &type_int, 0}, + {'|', &type_int, &type_int, 0}, + {'^', &type_int, &type_int, 0}, + {'%', &type_int, &type_int, 0}, + {MOD, &type_int, &type_int, 0}, {SHL, &type_short}, {SHR, &type_short}, - {EQ, &type_integer, &type_integer, 0}, - {NE, &type_integer, &type_integer, 0}, - {LE, &type_integer, &type_integer, 0}, - {GE, &type_integer, &type_integer, 0}, - {LT, &type_integer, &type_integer, 0}, - {GT, &type_integer, &type_integer, 0}, + {EQ, &type_int, &type_int, 0}, + {NE, &type_int, &type_int, 0}, + {LE, &type_int, &type_int, 0}, + {GE, &type_int, &type_int, 0}, + {LT, &type_int, &type_int, 0}, + {GT, &type_int, &type_int, 0}, {0, 0} }; -static expr_type_t short_uinteger[] = { - {'+', &type_uinteger, &type_uinteger, 0}, - {'-', &type_uinteger, &type_uinteger, 0}, - {'*', &type_uinteger, &type_uinteger, 0}, - {'/', &type_uinteger, &type_uinteger, 0}, - {'&', &type_uinteger, &type_uinteger, 0}, - {'|', &type_uinteger, &type_uinteger, 0}, - {'^', &type_uinteger, &type_uinteger, 0}, - {'%', &type_uinteger, &type_uinteger, 0}, - {MOD, &type_uinteger, &type_uinteger, 0}, +static expr_type_t short_uint[] = { + {'+', &type_uint, &type_uint, 0}, + {'-', &type_uint, &type_uint, 0}, + {'*', &type_uint, &type_uint, 0}, + {'/', &type_uint, &type_uint, 0}, + {'&', &type_uint, &type_uint, 0}, + {'|', &type_uint, &type_uint, 0}, + {'^', &type_uint, &type_uint, 0}, + {'%', &type_uint, &type_uint, 0}, + {MOD, &type_uint, &type_uint, 0}, {SHL, &type_short}, {SHR, &type_short}, - {EQ, &type_integer, &type_uinteger, 0}, - {NE, &type_integer, &type_uinteger, 0}, - {LE, &type_integer, &type_uinteger, 0}, - {GE, &type_integer, &type_uinteger, 0}, - {LT, &type_integer, &type_uinteger, 0}, - {GT, &type_integer, &type_uinteger, 0}, + {EQ, &type_int, &type_uint, 0}, + {NE, &type_int, &type_uint, 0}, + {LE, &type_int, &type_uint, 0}, + {GE, &type_int, &type_uint, 0}, + {LT, &type_int, &type_uint, 0}, + {GT, &type_int, &type_uint, 0}, {0, 0} }; @@ -455,15 +455,15 @@ static expr_type_t short_short[] = { {MOD, &type_short}, {SHL, &type_short}, {SHR, &type_short}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; -#define short_double integer_double +#define short_double int_double static expr_type_t double_float[] = { {'+', &type_double, 0, &type_double}, @@ -491,7 +491,7 @@ static expr_type_t double_quat[] = { {0, 0} }; -static expr_type_t double_integer[] = { +static expr_type_t double_int[] = { {'+', &type_double, 0, &type_double}, {'-', &type_double, 0, &type_double}, {'*', &type_double, 0, &type_double}, @@ -506,8 +506,8 @@ static expr_type_t double_integer[] = { {GT, 0, 0, 0, double_compare}, {0, 0} }; -#define double_uinteger double_integer -#define double_short double_integer +#define double_uint double_int +#define double_short double_int static expr_type_t double_double[] = { {'+', &type_double}, @@ -516,12 +516,12 @@ static expr_type_t double_double[] = { {'/', &type_double}, {'%', &type_double}, {MOD, &type_double}, - {EQ, &type_integer}, - {NE, &type_integer}, - {LE, &type_integer}, - {GE, &type_integer}, - {LT, &type_integer}, - {GT, &type_integer}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, {0, 0} }; @@ -535,8 +535,8 @@ static expr_type_t *string_x[ev_type_count] = { 0, // ev_func 0, // ev_pointer 0, // ev_quat - 0, // ev_integer - 0, // ev_uinteger + 0, // ev_int + 0, // ev_uint 0, // ev_short 0, // ev_double }; @@ -551,8 +551,8 @@ static expr_type_t *float_x[ev_type_count] = { 0, // ev_func 0, // ev_pointer float_quat, - float_integer, - float_uinteger, + float_int, + float_uint, float_short, float_double, }; @@ -567,8 +567,8 @@ static expr_type_t *vector_x[ev_type_count] = { 0, // ev_func 0, // ev_pointer 0, // ev_quaternion - vector_integer, - vector_uinteger, + vector_int, + vector_uint, vector_short, vector_double, }; @@ -583,8 +583,8 @@ static expr_type_t *entity_x[ev_type_count] = { 0, // ev_func 0, // ev_pointer 0, // ev_quaternion - 0, // ev_integer - 0, // ev_uinteger + 0, // ev_int + 0, // ev_uint 0, // ev_short 0, // ev_double }; @@ -599,8 +599,8 @@ static expr_type_t *field_x[ev_type_count] = { 0, // ev_func 0, // ev_pointer 0, // ev_quaternion - 0, // ev_integer - 0, // ev_uinteger + 0, // ev_int + 0, // ev_uint 0, // ev_short 0, // ev_double }; @@ -615,8 +615,8 @@ static expr_type_t *func_x[ev_type_count] = { func_func, // ev_func 0, // ev_pointer 0, // ev_quaternion - 0, // ev_integer - 0, // ev_uinteger + 0, // ev_int + 0, // ev_uint 0, // ev_short 0, // ev_double }; @@ -631,8 +631,8 @@ static expr_type_t *pointer_x[ev_type_count] = { 0, // ev_func pointer_pointer, 0, // ev_quat - pointer_integer, - pointer_uinteger, + pointer_int, + pointer_uint, pointer_short, 0, // ev_double }; @@ -647,42 +647,42 @@ static expr_type_t *quat_x[ev_type_count] = { 0, // ev_func 0, // ev_pointer quat_quat, - quat_integer, - quat_uinteger, + quat_int, + quat_uint, quat_short, quat_double, }; -static expr_type_t *integer_x[ev_type_count] = { +static expr_type_t *int_x[ev_type_count] = { 0, // ev_void 0, // ev_string - integer_float, - integer_vector, + int_float, + int_vector, 0, // ev_entity 0, // ev_field 0, // ev_func - integer_pointer, - integer_quat, - integer_integer, - integer_uinteger, - integer_short, - integer_double, + int_pointer, + int_quat, + int_int, + int_uint, + int_short, + int_double, }; -static expr_type_t *uinteger_x[ev_type_count] = { +static expr_type_t *uint_x[ev_type_count] = { 0, // ev_void 0, // ev_string - uinteger_float, - uinteger_vector, + uint_float, + uint_vector, 0, // ev_entity 0, // ev_field 0, // ev_func - uinteger_pointer, - uinteger_quat, - uinteger_integer, - uinteger_uinteger, - uinteger_short, - uinteger_double, + uint_pointer, + uint_quat, + uint_int, + uint_uint, + uint_short, + uint_double, }; static expr_type_t *short_x[ev_type_count] = { @@ -695,8 +695,8 @@ static expr_type_t *short_x[ev_type_count] = { 0, // ev_func short_pointer, short_quat, - short_integer, - short_uinteger, + short_int, + short_uint, short_short, short_double, }; @@ -711,8 +711,8 @@ static expr_type_t *double_x[ev_type_count] = { 0, // ev_func 0, // ev_pointer double_quat, - double_integer, - double_uinteger, + double_int, + double_uint, double_short, double_double, }; @@ -727,8 +727,8 @@ static expr_type_t **binary_expr_types[ev_type_count] = { func_x, pointer_x, quat_x, - integer_x, - uinteger_x, + int_x, + uint_x, short_x, double_x }; @@ -755,20 +755,20 @@ pointer_arithmetic (int op, expr_t *e1, expr_t *e2) return error (e2, "cannot use %c on pointers of different types", op); } - e1 = cast_expr (&type_integer, e1); - e2 = cast_expr (&type_integer, e2); - psize = new_integer_expr (type_size (t1->t.fldptr.type)); + e1 = cast_expr (&type_int, e1); + e2 = cast_expr (&type_int, e2); + psize = new_int_expr (type_size (t1->t.fldptr.type)); return binary_expr ('/', binary_expr ('-', e1, e2), psize); } else if (is_pointer (t1)) { - offset = cast_expr (&type_integer, e2); - ptr = cast_expr (&type_integer, e1); + offset = cast_expr (&type_int, e2); + ptr = cast_expr (&type_int, e1); ptype = t1; } else if (is_pointer (t2)) { - offset = cast_expr (&type_integer, e1); - ptr = cast_expr (&type_integer, e2); + offset = cast_expr (&type_int, e1); + ptr = cast_expr (&type_int, e2); ptype = t2; } - psize = new_integer_expr (type_size (ptype->t.fldptr.type)); + psize = new_int_expr (type_size (ptype->t.fldptr.type)); e = binary_expr (op, ptr, binary_expr ('*', offset, psize)); return cast_expr (ptype, e); } @@ -785,7 +785,7 @@ pointer_compare (int op, expr_t *e1, expr_t *e2) get_op_string (op)); } e = new_binary_expr (op, e1, e2); - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; return e; } @@ -817,19 +817,19 @@ double_compare (int op, expr_t *e1, expr_t *e2) if (is_float (t2)) { warning (e2, "comparison between double and float"); } else if (!is_constant (e2)) { - warning (e2, "comparison between double and integer"); + warning (e2, "comparison between double and int"); } e2 = cast_expr (&type_double, e2); } else if (is_double (t2)) { if (is_float (t1)) { warning (e1, "comparison between float and double"); } else if (!is_constant (e1)) { - warning (e1, "comparison between integer and double"); + warning (e1, "comparison between int and double"); } e1 = cast_expr (&type_double, e1); } e = new_binary_expr (op, e1, e2); - e->e.expr.type = &type_integer; + e->e.expr.type = &type_int; return e; } diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 9f7b0e1e4..df8e25180 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -97,10 +97,10 @@ test_expr (expr_t *e) case ev_long: case ev_ulong: internal_error (e, "long not implemented"); - case ev_uinteger: - case ev_integer: + case ev_uint: + case ev_int: case ev_short: - if (!is_integer(type_default)) { + if (!is_int(type_default)) { if (is_constant (e)) { return cast_expr (type_default, e); } @@ -285,8 +285,8 @@ convert_bool (expr_t *e, int block) int val; b = goto_expr (0); - if (is_integer_val (e)) { - val = expr_integer (e); + if (is_int_val (e)) { + val = expr_int (e); } else { val = expr_float (e) != 0; } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index e448990b2..08a397651 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -665,7 +665,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far, error (bi_val, "%s redefined", sym->name); return 0; } - if (!is_integer_val (bi_val) && !is_float_val (bi_val)) { + if (!is_int_val (bi_val) && !is_float_val (bi_val)) { error (bi_val, "invalid constant for = #"); return 0; } @@ -681,8 +681,8 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far, sym->s.func->def->nosave = 1; add_function (sym->s.func); - if (is_integer_val (bi_val)) - bi = expr_integer (bi_val); + if (is_int_val (bi_val)) + bi = expr_int (bi_val); else bi = expr_float (bi_val); if (bi < 0) { diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 9c82f89d5..67df1d3fb 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -543,8 +543,8 @@ emit_methods_count (def_t *def, void *data, int index) { methodlist_t *methods = (methodlist_t *) data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = methods->count; } @@ -586,7 +586,7 @@ emit_methods (methodlist_t *methods, const char *name, int instance) { static struct_def_t methods_struct[] = { {"method_next", &type_pointer, emit_methods_next}, - {"method_count", &type_integer, emit_methods_count}, + {"method_count", &type_int, emit_methods_count}, {"method_list", 0, emit_methods_list_item}, {0, 0} }; @@ -622,8 +622,8 @@ emit_method_list_count (def_t *def, void *data, int index) { methodlist_t *methods = (methodlist_t *) data; - if (!is_integer(def->type)) - internal_error (0, "%s: expected integer def", __FUNCTION__); + if (!is_int(def->type)) + internal_error (0, "%s: expected int def", __FUNCTION__); D_INT (def) = methods->count; } @@ -660,7 +660,7 @@ emit_method_descriptions (methodlist_t *methods, const char *name, int instance) { static struct_def_t method_list_struct[] = { - {"count", &type_integer, emit_method_list_count}, + {"count", &type_int, emit_method_list_count}, {"method_list", 0, emit_method_list_item}, {0, 0} }; @@ -746,8 +746,8 @@ method_check_params (method_t *method, expr_t *args) } } } else { - if (is_integer_val (e) && options.warnings.vararg_integer) { - warning (e, "passing integer consant into ... function"); + if (is_int_val (e) && options.warnings.vararg_integer) { + warning (e, "passing int consant into ... function"); } } } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index eed5de4ce..a9f562984 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -434,7 +434,7 @@ qfo_byteswap_space (void *space, int size, qfos_type_t type) case qfos_type: case qfos_debug: for (val = (pr_type_t *) space, c = 0; c < size; c++, val++) - val->integer_var = LittleLong (val->integer_var); + val->int_var = LittleLong (val->int_var); break; } } @@ -696,7 +696,7 @@ get_def_type (qfo_t *qfo, pr_ptr_t type) case ty_enum: if (options.code.progsversion == PROG_ID_VERSION) return ev_float; - return ev_integer; + return ev_int; case ty_array: case ty_class: return ev_invalid; @@ -732,7 +732,7 @@ get_type_size (qfo_t *qfo, pr_ptr_t type) } return size; case ty_enum: - return pr_type_size[ev_integer]; + return pr_type_size[ev_int]; case ty_array: return type_def->array.size * get_type_size (qfo, type_def->array.type); @@ -781,7 +781,7 @@ get_type_alignment_log (qfo_t *qfo, pr_ptr_t type) } return alignment; case ty_enum: - return qfo_log2 (ev_types[ev_integer]->alignment); + return qfo_log2 (ev_types[ev_int]->alignment); case ty_array: return get_type_alignment_log (qfo, type_def->array.type); case ty_class: diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 09927ecd3..d806e6c9b 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -214,7 +214,7 @@ qfo_encode_struct (type_t *type, defspace_t *space) if (i == num_fields) internal_error (0, "whoa, what happened?"); if (sym->sy_type == sy_const) - offset = sym->s.value->v.integer_val; + offset = sym->s.value->v.int_val; else offset = sym->s.offset; ENC_DEF (strct->fields[i].type, field_types[i]); diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index ee9722a2a..47accd2c3 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -241,11 +241,11 @@ v6p_opcode_init (void) // treats the operands of certain operands as integers // irrespective the progs version, so convert the engine's // view of the operands to the prog's view. - if (mop->type_a == ev_integer) + if (mop->type_a == ev_int) mop->type_a = ev_float; - if (mop->type_b == ev_integer) + if (mop->type_b == ev_int) mop->type_b = ev_float; - if (mop->type_c == ev_integer) + if (mop->type_c == ev_int) mop->type_c = ev_float; } Hash_AddElement (v6p_opcode_type_table, mop); diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index 60448815e..616198ab2 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -67,7 +67,7 @@ set_traditional (int traditional) options.traditional = 0; options.advanced = true; options.code.progsversion = PROG_V6P_VERSION; - type_default = &type_integer; + type_default = &type_int; break; case 1: options.traditional = 1; diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 1a3cb9d99..c53965993 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -131,9 +131,9 @@ STRING \"(\\.|[^"\\])*\" else i = strtol (yytext, 0, 0); if (*c == 'u' || *c == 'U') - qc_yylval.expr = new_integer_expr (i);//FIXME + qc_yylval.expr = new_int_expr (i);//FIXME else - qc_yylval.expr = new_integer_expr (i); + qc_yylval.expr = new_int_expr (i); return VALUE; } @@ -208,7 +208,7 @@ STRING \"(\\.|[^"\\])*\" if (str[1]) warning (0, "multibyte char constant"); - qc_yylval.expr = new_integer_expr (*str); + qc_yylval.expr = new_int_expr (*str); return VALUE; } @@ -269,7 +269,7 @@ STRING \"(\\.|[^"\\])*\" "$"{s}*{FRAMEID} { int ret = do_grab (yytext); if (ret >= 0) { - qc_yylval.expr = new_integer_expr (ret); + qc_yylval.expr = new_int_expr (ret); return VALUE; } else { BEGIN (-ret); @@ -376,8 +376,8 @@ static keyword_t at_keywords[] = { static keyword_t qf_keywords[] = { {"quaternion", TYPE, &type_quaternion}, {"double", TYPE, &type_double}, - {"int", TYPE, &type_integer }, - {"unsigned", TYPE, &type_integer },//FIXME + {"int", TYPE, &type_int }, + {"unsigned", TYPE, &type_int },//FIXME {"@function", TYPE, &type_function }, {"@args", ARGS, 0 }, diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 9c56a5790..454c8fcfc 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -969,11 +969,11 @@ abs_decl array_decl : '[' expr ']' { - if (!is_integer_val ($2) || expr_integer ($2) < 1) { + if (!is_int_val ($2) || expr_int ($2) < 1) { error (0, "invalid array size"); $$ = 0; } else { - $$ = expr_integer ($2); + $$ = expr_int ($2); } } | '[' ']' { $$ = 0; } @@ -1104,7 +1104,7 @@ non_code_func if (sym->s.def) sym->s.def->nosave |= spec.nosave; } else { - if (is_integer_val ($2) || is_float_val ($2)) { + if (is_int_val ($2) || is_float_val ($2)) { error (0, "invalid function initializer." " did you forget #?"); } else { diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 2e656a21e..25c1a89c6 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -246,7 +246,7 @@ WriteProgs (dprograms_t *progs, int size) fielddefs[i].name = LittleLong (fielddefs[i].name); } for (i = 0; i < progs->numglobals; i++) - globals[i].integer_var = LittleLong (globals[i].integer_var); + globals[i].int_var = LittleLong (globals[i].int_var); if (!(h = Qopen (options.output_file, "wb"))) Sys_Error ("%s: %s\n", options.output_file, strerror(errno)); @@ -307,7 +307,7 @@ WriteSym (pr_debug_header_t *sym, int size) debug_defs[i].type_encoding = LittleLong (debug_defs[i].type_encoding); } for (i = 0; i < sym->debug_data_size; i++) { - debug_data[i].integer_var = LittleLong (debug_data[i].integer_var); + debug_data[i].int_var = LittleLong (debug_data[i].int_var); } if (!(h = Qopen (options.debug_file, "wb"))) @@ -441,9 +441,9 @@ finish_link (void) if (options.code.progsversion != PROG_ID_VERSION) { pr_int_t param_size = type_size (&type_param); pr_int_t param_alignment = qfo_log2 (type_param.alignment); - linker_add_def (".param_size", &type_integer, flags, + linker_add_def (".param_size", &type_int, flags, ¶m_size); - linker_add_def (".param_alignment", &type_integer, flags, + linker_add_def (".param_alignment", &type_int, flags, ¶m_alignment); linker_add_def (".xdefs", &type_xdefs, flags, 0); } diff --git a/tools/qfcc/source/qp-lex.l b/tools/qfcc/source/qp-lex.l index a57185209..7bb6d160b 100644 --- a/tools/qfcc/source/qp-lex.l +++ b/tools/qfcc/source/qp-lex.l @@ -113,7 +113,7 @@ FRAMEID {ID}(\.{ID})* i = strtol (yytext + 2, 0, 2); else i = strtol (yytext, 0, 0); - qp_yylval.expr = new_integer_expr (i); + qp_yylval.expr = new_int_expr (i); return VALUE; } @@ -170,7 +170,7 @@ FRAMEID {ID}(\.{ID})* "$"{s}*{FRAMEID} { int ret = do_grab (yytext); if (ret >= 0) { - qp_yylval.expr = new_integer_expr (ret); + qp_yylval.expr = new_int_expr (ret); return VALUE; } else { BEGIN (-ret); @@ -209,7 +209,7 @@ static keyword_t keywords[] = { {"vector", TYPE, &type_vector}, {"entity", TYPE, &type_entity}, {"quaternion", TYPE, &type_quaternion}, - {"integer", TYPE, &type_integer}, + {"integer", TYPE, &type_int}, {"program", PROGRAM, 0}, {"var", VAR, 0}, diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index b45e6d0ee..e7bb66647 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -148,7 +148,7 @@ build_dotmain (symbol_t *program) expr_t *exitcode; dotmain->params = 0; - dotmain->type = parse_params (&type_integer, 0); + dotmain->type = parse_params (&type_int, 0); dotmain->type = find_type (dotmain->type); dotmain = function_symbol (dotmain, 0, 1); @@ -198,7 +198,7 @@ program_head // FIXME need units and standard units { symbol_t *sym = new_symbol ("ExitCode"); - sym->type = &type_integer; + sym->type = &type_int; initialize_def (sym, 0, current_symtab->space, sc_global); if (sym->s.def) { sym->s.def->nosave = 1; @@ -245,7 +245,7 @@ type : standard_type | ARRAY '[' VALUE RANGE VALUE ']' OF standard_type { - $$ = based_array_type ($8, expr_integer ($3), expr_integer ($5)); + $$ = based_array_type ($8, expr_int ($3), expr_int ($5)); } ; @@ -480,7 +480,7 @@ name { if (!$1->table) { error (0, "%s undefined", $1->name); - $1->type = &type_integer; + $1->type = &type_int; symtab_addsymbol (current_symtab, $1); } $$ = new_symbol_expr ($1); diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index c1d471d0a..d235008d0 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -73,7 +73,7 @@ static const char *reloc_name[] = { "rel_def_field_ofs", }; -#define RELOC(r) (r)->space->data[(r)->offset].integer_var +#define RELOC(r) (r)->space->data[(r)->offset].int_var void relocate_refs (reloc_t *reloc, int offset) @@ -168,8 +168,8 @@ relocate_refs (reloc_t *reloc, int offset) break; case rel_def_field_ofs: //FIXME what is correct here? - //RELOC (reloc) += pr.data->data[offset].integer_var; - RELOC (reloc) += pr.near_data->data[offset].integer_var; + //RELOC (reloc) += pr.data->data[offset].int_var; + RELOC (reloc) += pr.near_data->data[offset].int_var; break; } reloc = reloc->next; diff --git a/tools/qfcc/source/shared.c b/tools/qfcc/source/shared.c index cee0d06c1..acdbf149f 100644 --- a/tools/qfcc/source/shared.c +++ b/tools/qfcc/source/shared.c @@ -72,7 +72,7 @@ check_undefined (symbol_t *sym) if (options.code.progsversion == PROG_ID_VERSION) sym->type = &type_float; else - sym->type = &type_integer; + sym->type = &type_int; } return sym; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 1c2cbc965..0d52f7c4e 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -155,13 +155,13 @@ operand_string (operand_t *op) case ev_field: return va (0, "field %d", op->value->v.pointer.val); case ev_entity: - return va (0, "ent %d", op->value->v.integer_val); + return va (0, "ent %d", op->value->v.int_val); case ev_func: - return va (0, "func %d", op->value->v.integer_val); - case ev_integer: - return va (0, "int %d", op->value->v.integer_val); - case ev_uinteger: - return va (0, "uint %u", op->value->v.uinteger_val); + return va (0, "func %d", op->value->v.int_val); + case ev_int: + return va (0, "int %d", op->value->v.int_val); + case ev_uint: + return va (0, "uint %u", op->value->v.uint_val); case ev_long: return va (0, "long %"PRIi64, op->value->v.long_val); case ev_ulong: @@ -237,11 +237,11 @@ _print_operand (operand_t *op) break; case ev_entity: case ev_func: - case ev_integer: - printf ("%d", op->value->v.integer_val); + case ev_int: + printf ("%d", op->value->v.int_val); break; - case ev_uinteger: - printf ("%u", op->value->v.uinteger_val); + case ev_uint: + printf ("%u", op->value->v.uint_val); break; case ev_long: printf ("%"PRIu64, op->value->v.long_val); @@ -804,7 +804,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) if ((src && src->op_type == op_nil) || src_expr->type == ex_nil) { // switch to memset because nil is type agnostic 0 and structures // can be any size - src_expr = new_integer_expr (0); + src_expr = new_int_expr (0); sblock = statement_subexpr (sblock, src_expr, &src); opcode_set = opcode_sets[1]; if (op) { @@ -853,7 +853,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) if (count < (1 << 16)) { count_expr = expr_file_line (new_short_expr (count), e); } else { - count_expr = expr_file_line (new_integer_expr (count), e); + count_expr = expr_file_line (new_int_expr (count), e); } sblock = statement_subexpr (sblock, count_expr, &size); @@ -1210,7 +1210,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) int offset = 0; if (e->e.alias.offset) { - offset = expr_integer (e->e.alias.offset); + offset = expr_int (e->e.alias.offset); } type = e->e.alias.type; sblock = statement_subexpr (sblock, e->e.alias.expr, &aop); @@ -1473,9 +1473,9 @@ expr_nil (sblock_t *sblock, expr_t *e, operand_t **op) if (nil_size < 0x10000) { size_expr = new_short_expr (nil_size); } else { - size_expr = new_integer_expr (nil_size); + size_expr = new_int_expr (nil_size); } - sblock = statement_subexpr (sblock, new_integer_expr(0), &zero); + sblock = statement_subexpr (sblock, new_int_expr(0), &zero); sblock = statement_subexpr (sblock, size_expr, &size); s = new_statement (st_memset, "", e); @@ -1737,12 +1737,12 @@ statement_memset (sblock_t *sblock, expr_t *e) statement_t *s; if (is_constant (count)) { - if (is_integer (get_type (count)) - && (unsigned) expr_integer (count) < 0x10000) { - count = new_short_expr (expr_integer (count)); + if (is_int (get_type (count)) + && (unsigned) expr_int (count) < 0x10000) { + count = new_short_expr (expr_int (count)); } - if (is_uinteger (get_type (count)) && expr_integer (count) < 0x10000) { - count = new_short_expr (expr_uinteger (count)); + if (is_uint (get_type (count)) && expr_int (count) < 0x10000) { + count = new_short_expr (expr_uint (count)); } } s = new_statement (st_move, opcode, e); diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 164a491a2..798696ac3 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -235,17 +235,17 @@ add_enum (symbol_t *enm, symbol_t *name, expr_t *val) name->type = enum_type; value = 0; if (enum_tab->symbols) - value = ((symbol_t *)(enum_tab->symtail))->s.value->v.integer_val + 1; + value = ((symbol_t *)(enum_tab->symtail))->s.value->v.int_val + 1; if (val) { convert_name (val); if (!is_constant (val)) error (val, "non-constant initializer"); - else if (!is_integer_val (val)) + else if (!is_int_val (val)) error (val, "invalid initializer type"); else - value = expr_integer (val); + value = expr_int (val); } - name->s.value = new_integer_val (value); + name->s.value = new_int_val (value); symtab_addsymbol (enum_tab, name); } @@ -263,12 +263,12 @@ enum_as_bool (type_t *enm, expr_t **zero, expr_t **one) for (sym = symtab->symbols; sym; sym = sym->next) { if (sym->sy_type != sy_const) continue; - val = sym->s.value->v.integer_val; + val = sym->s.value->v.int_val; if (!val) { zero_sym = sym; } else { if (one_sym) { - v = one_sym->s.value->v.integer_val; + v = one_sym->s.value->v.int_val; if (val * val > v * v) continue; } diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index f40d48d6d..9f245807a 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -136,14 +136,14 @@ case_label_expr (switch_block_t *switch_block, expr_t *value) if (!type_assignable (type, get_type (value))) return error (value, "type mismatch in case label"); if (is_integral (type) && is_integral (val_type)) { - value = new_integer_expr (expr_integer (value)); + value = new_int_expr (expr_int (value)); debug (value, "integeral label used in integral switch"); } else if (is_integral (type) && is_float (val_type)) { warning (value, "float label used in integral switch"); - value = new_integer_expr (expr_float (value)); + value = new_int_expr (expr_float (value)); } else if (is_float (type) && is_integral (val_type)) { debug (value, "integeral label used in float switch"); - value = new_float_expr (expr_integer (value)); + value = new_float_expr (expr_int (value)); } else if (is_float (type) && is_float (val_type)) { value = new_float_expr (expr_float (value)); debug (value, "float label used in float switch"); @@ -189,8 +189,8 @@ label_compare (const void *_a, const void *_b) return strcmp (s1, s2); } else if (is_float_val ((*a)->value)) { return expr_float ((*a)->value) - expr_float ((*b)->value); - } else if (is_integer_val ((*a)->value)) { - return expr_integer ((*a)->value) - expr_integer ((*b)->value); + } else if (is_int_val ((*a)->value)) { + return expr_int ((*a)->value) - expr_int ((*b)->value); } internal_error (0, "in switch"); } @@ -210,9 +210,9 @@ new_case_node (expr_t *low, expr_t *high) } else { int size; - if (!is_integer_val (low)) + if (!is_int_val (low)) internal_error (low, "switch"); - size = expr_integer (high) - expr_integer (low) + 1; + size = expr_int (high) - expr_int (low) + 1; node->labels = calloc (size, sizeof (expr_t *)); } node->left = node->right = 0; @@ -253,18 +253,18 @@ build_case_tree (case_label_t **labels, int count, int range) if (!nodes) Sys_Error ("out of memory"); - if (range && is_integer_val (labels[0]->value)) { + if (range && is_int_val (labels[0]->value)) { for (i = 0; i < count - 1; i = j, num_nodes++) { for (j = i + 1; j < count; j++) { - if (expr_integer (labels[j]->value) - - expr_integer (labels[j - 1]->value) > 1) + if (expr_int (labels[j]->value) + - expr_int (labels[j - 1]->value) > 1) break; } nodes[num_nodes] = new_case_node (labels[i]->value, labels[j - 1]->value); for (k = i; k < j; k++) - nodes[num_nodes]->labels[expr_integer (labels[k]->value) - - expr_integer (labels[i]->value)] + nodes[num_nodes]->labels[expr_int (labels[k]->value) + - expr_int (labels[i]->value)] = labels[k]->label; } if (i < count) { @@ -311,12 +311,12 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, append_expr (sw, test); if (tree->low == tree->high) { - branch = branch_expr (EQ, new_alias_expr (&type_integer, temp), + branch = branch_expr (EQ, new_alias_expr (&type_int, temp), tree->labels[0]); append_expr (sw, branch); if (tree->left) { - branch = branch_expr (GT, new_alias_expr (&type_integer, temp), + branch = branch_expr (GT, new_alias_expr (&type_int, temp), high_label); append_expr (sw, branch); @@ -329,8 +329,8 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, build_switch (sw, tree->right, op, sw_val, temp, default_label); } } else { - int low = expr_integer (tree->low); - int high = expr_integer (tree->high); + int low = expr_int (tree->low); + int high = expr_int (tree->high); symbol_t *table_sym; expr_t *table_expr; expr_t *table_init; @@ -346,7 +346,7 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, append_element (table_init, new_element (label, 0)); } table_sym = new_symbol_type (table_name, - array_type (&type_integer, + array_type (&type_int, high - low + 1)); initialize_def (table_sym, table_init, pr.near_data, sc_static); table_expr = new_symbol_expr (table_sym); @@ -355,8 +355,8 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, branch = branch_expr (LT, temp, low_label); append_expr (sw, branch); } - test = binary_expr (GT, cast_expr (&type_uinteger, temp), - cast_expr (&type_uinteger, range)); + test = binary_expr (GT, cast_expr (&type_uint, temp), + cast_expr (&type_uint, range)); branch = branch_expr (NE, test, high_label); append_expr (sw, branch); branch = jump_table_expr (table_expr, temp); @@ -382,7 +382,7 @@ check_enum_switch (switch_block_t *switch_block) for (enum_val = type->t.symtab->symbols; enum_val; enum_val = enum_val->next) { - cl.value = new_integer_expr (enum_val->s.value->v.integer_val); + cl.value = new_int_expr (enum_val->s.value->v.int_val); if (!Hash_FindElement (switch_block->labels, &cl)) { warning (switch_block->test, "enumeration value `%s' not handled in switch", @@ -446,7 +446,7 @@ switch_expr (switch_block_t *switch_block, expr_t *break_label, case_node_t *case_tree; if (is_string(type)) - temp = new_temp_def_expr (&type_integer); + temp = new_temp_def_expr (&type_int); else temp = new_temp_def_expr (type); case_tree = build_case_tree (labels, num_labels, is_integral (type)); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 17dd74571..81583de9c 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -75,8 +75,8 @@ type_t type_function = { ev_func, "function", 1, ty_basic, type_t type_pointer = { ev_pointer, "pointer", 1, ty_basic, {{&type_void}} }; type_t type_quaternion = { ev_quat, "quaternion", 4 }; -type_t type_integer = { ev_integer, "int", 1 }; -type_t type_uinteger = { ev_uinteger, "uint", 1 }; +type_t type_int = { ev_int, "int", 1 }; +type_t type_uint = { ev_uint, "uint", 1 }; type_t type_short = { ev_short, "short", 1 }; type_t type_double = { ev_double, "double", 2 }; @@ -106,8 +106,8 @@ type_t *ev_types[ev_type_count] = { &type_function, &type_pointer, &type_quaternion, - &type_integer, - &type_uinteger, + &type_int, + &type_uint, &type_short, &type_double, &type_invalid, @@ -186,8 +186,8 @@ free_type (type_t *type) case ev_entity: case ev_type_count: case ev_quat: - case ev_integer: - case ev_uinteger: + case ev_int: + case ev_uint: case ev_long: case ev_ulong: case ev_short: @@ -228,8 +228,8 @@ copy_chain (type_t *type, type_t *append) case ev_entity: case ev_type_count: case ev_quat: - case ev_integer: - case ev_uinteger: + case ev_int: + case ev_uint: case ev_long: case ev_ulong: case ev_short: @@ -281,8 +281,8 @@ append_type (type_t *type, type_t *new) case ev_entity: case ev_type_count: case ev_quat: - case ev_integer: - case ev_uinteger: + case ev_int: + case ev_uint: case ev_long: case ev_ulong: case ev_short: @@ -660,8 +660,8 @@ print_type_str (dstring_t *str, const type_t *type) case ev_vector: case ev_entity: case ev_quat: - case ev_integer: - case ev_uinteger: + case ev_int: + case ev_uint: case ev_long: case ev_ulong: case ev_short: @@ -822,10 +822,10 @@ encode_type (dstring_t *encoding, const type_t *type) case ev_quat: dasprintf (encoding, "Q"); return; - case ev_integer: + case ev_int: dasprintf (encoding, "i"); return; - case ev_uinteger: + case ev_uint: dasprintf (encoding, "I"); return; case ev_long: @@ -863,23 +863,23 @@ is_enum (const type_t *type) } int -is_integer (const type_t *type) +is_int (const type_t *type) { type = unalias_type (type); etype_t t = type->type; - if (t == ev_integer) + if (t == ev_int) return 1; return is_enum (type); } int -is_uinteger (const type_t *type) +is_uint (const type_t *type) { type = unalias_type (type); etype_t t = type->type; - if (t == ev_uinteger) + if (t == ev_uint) return 1; return is_enum (type); } @@ -899,7 +899,7 @@ int is_integral (const type_t *type) { type = unalias_type (type); - if (is_integer (type) || is_uinteger (type) || is_short (type)) + if (is_int (type) || is_uint (type) || is_short (type)) return 1; return is_enum (type); } @@ -1103,7 +1103,7 @@ type_size (const type_t *type) case ty_enum: if (!type->t.symtab) return 0; - return type_size (&type_integer); + return type_size (&type_int); case ty_array: return type->t.array.size * type_size (type->t.array.type); case ty_class: @@ -1138,8 +1138,8 @@ chain_basic_types (void) chain_type (&type_floatfield); if (!options.traditional) { chain_type (&type_quaternion); - chain_type (&type_integer); - chain_type (&type_uinteger); + chain_type (&type_int); + chain_type (&type_uint); chain_type (&type_short); chain_type (&type_double); } @@ -1175,10 +1175,10 @@ init_types (void) {"func_val", &type_function}, {"pointer_val", &type_pointer}, {"vector_val", &type_vector}, - {"int_val", &type_integer}, - {"uint_val", &type_uinteger}, - {"integer_val", &type_integer}, - {"uinteger_val", &type_uinteger}, + {"int_val", &type_int}, + {"uint_val", &type_uint}, + {"int_val", &type_int}, + {"uint_val", &type_uint}, {"quaternion_val", &type_quaternion}, {"double_val", &type_double}, {0, 0} @@ -1191,10 +1191,8 @@ init_types (void) {"field_val", &type_field}, {"func_val", &type_function}, {"pointer_val", &type_pointer}, - {"int_val", &type_integer}, - {"uint_val", &type_uinteger}, - {"integer_val", &type_integer}, - {"uinteger_val", &type_uinteger}, + {"int_val", &type_int}, + {"uint_val", &type_uint}, {"quaternion_val", &type_quaternion}, {"double_val", &type_double}, {0, 0} @@ -1212,7 +1210,7 @@ init_types (void) }; static struct_def_t type_encoding_struct[] = { {"types", &type_pointer}, - {"size", &type_integer}, + {"size", &type_int}, {0, 0} }; static struct_def_t xdef_struct[] = { @@ -1226,7 +1224,7 @@ init_types (void) {0, 0} }; static struct_def_t va_list_struct[] = { - {"count", &type_integer}, + {"count", &type_int}, {"list", 0}, // type will be filled in at runtime {0, 0} }; @@ -1234,7 +1232,7 @@ init_types (void) chain_basic_types (); type_nil = &type_quaternion; - type_default = &type_integer; + type_default = &type_int; if (options.code.progsversion == PROG_ID_VERSION) { // vector can't be part of .zero for v6 progs because for v6 progs, // .zero is only one word wide. diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index cd0af3d54..786a3d2fb 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -68,7 +68,7 @@ typedef struct { int func_val; ex_pointer_t pointer; float quaternion_val[4]; - int integer_val; + int int_val; double double_val; } i; } immediate_t; @@ -224,22 +224,22 @@ new_quaternion_val (const float *quaternion_val) } ex_value_t * -new_integer_val (int integer_val) +new_int_val (int int_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - set_val_type (&val, &type_integer); - val.v.integer_val = integer_val; + set_val_type (&val, &type_int); + val.v.int_val = int_val; return find_value (&val); } ex_value_t * -new_uinteger_val (int uinteger_val) +new_uint_val (int uint_val) { ex_value_t val; memset (&val, 0, sizeof (val)); - set_val_type (&val, &type_uinteger); - val.v.uinteger_val = uinteger_val; + set_val_type (&val, &type_uint); + val.v.uint_val = uint_val; return find_value (&val); } @@ -277,7 +277,7 @@ static hashtab_t *field_imm_defs; static hashtab_t *func_imm_defs; static hashtab_t *pointer_imm_defs; static hashtab_t *quaternion_imm_defs; -static hashtab_t *integer_imm_defs; +static hashtab_t *int_imm_defs; static hashtab_t *double_imm_defs; static void @@ -296,15 +296,15 @@ imm_get_hash (const void *_imm, void *_tab) const char *str = pr.strings->strings + imm->i.string_val; return str ? Hash_String (str) : 0; } else if (tab == &float_imm_defs) { - return imm->i.integer_val; + return imm->i.int_val; } else if (tab == &vector_imm_defs) { return Hash_Buffer (&imm->i.vector_val, sizeof (&imm->i.vector_val)); } else if (tab == &entity_imm_defs) { - return imm->i.integer_val; + return imm->i.int_val; } else if (tab == &field_imm_defs) { return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer)); } else if (tab == &func_imm_defs) { - return imm->i.integer_val; + return imm->i.int_val; } else if (tab == &pointer_imm_defs) { return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer)); } else if (tab == &quaternion_imm_defs) { @@ -312,8 +312,8 @@ imm_get_hash (const void *_imm, void *_tab) sizeof (&imm->i.quaternion_val)); } else if (tab == &double_imm_defs) { return Hash_Buffer (&imm->i.double_val, sizeof (&imm->i.double_val)); - } else if (tab == &integer_imm_defs) { - return imm->i.integer_val; + } else if (tab == &int_imm_defs) { + return imm->i.int_val; } else { internal_error (0, 0); } @@ -348,8 +348,8 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab) return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val); } else if (tab == &double_imm_defs) { return imm1->i.double_val == imm2->i.double_val; - } else if (tab == &integer_imm_defs) { - return imm1->i.integer_val == imm2->i.integer_val; + } else if (tab == &int_imm_defs) { + return imm1->i.int_val == imm2->i.int_val; } else { internal_error (0, 0); } @@ -364,10 +364,10 @@ ReuseString (const char *str) static float value_as_float (ex_value_t *value) { - if (value->lltype == ev_uinteger) - return value->v.uinteger_val; - if (value->lltype == ev_integer) - return value->v.integer_val; + if (value->lltype == ev_uint) + return value->v.uint_val; + if (value->lltype == ev_int) + return value->v.int_val; if (value->lltype == ev_short) return value->v.short_val; if (value->lltype == ev_double) @@ -380,10 +380,10 @@ value_as_float (ex_value_t *value) static double value_as_double (ex_value_t *value) { - if (value->lltype == ev_uinteger) - return value->v.uinteger_val; - if (value->lltype == ev_integer) - return value->v.integer_val; + if (value->lltype == ev_uint) + return value->v.uint_val; + if (value->lltype == ev_int) + return value->v.int_val; if (value->lltype == ev_short) return value->v.short_val; if (value->lltype == ev_double) @@ -396,10 +396,10 @@ value_as_double (ex_value_t *value) static int value_as_int (ex_value_t *value) { - if (value->lltype == ev_uinteger) - return value->v.uinteger_val; - if (value->lltype == ev_integer) - return value->v.integer_val; + if (value->lltype == ev_uint) + return value->v.uint_val; + if (value->lltype == ev_int) + return value->v.int_val; if (value->lltype == ev_short) return value->v.short_val; if (value->lltype == ev_double) @@ -412,10 +412,10 @@ value_as_int (ex_value_t *value) static unsigned value_as_uint (ex_value_t *value) { - if (value->lltype == ev_uinteger) - return value->v.uinteger_val; - if (value->lltype == ev_integer) - return value->v.integer_val; + if (value->lltype == ev_uint) + return value->v.uint_val; + if (value->lltype == ev_int) + return value->v.int_val; if (value->lltype == ev_short) return value->v.short_val; if (value->lltype == ev_double) @@ -441,13 +441,13 @@ convert_value (ex_value_t *value, type_t *type) } else if (type->type == ev_short) { int val = value_as_int (value); return new_short_val (val); - } else if (type->type == ev_uinteger) { + } else if (type->type == ev_uint) { unsigned val = value_as_uint (value); - return new_uinteger_val (val); + return new_uint_val (val); } else { //FIXME handle enums separately? int val = value_as_int (value); - return new_integer_val (val); + return new_int_val (val); } } @@ -511,21 +511,21 @@ emit_value (ex_value_t *value, def_t *def) tab = pointer_imm_defs; type = &type_pointer; break; - case ev_integer: - case ev_uinteger: + case ev_int: + case ev_uint: if (!def || !is_float(def->type)) { - tab = integer_imm_defs; - type = &type_integer; + tab = int_imm_defs; + type = &type_int; break; } - val.v.float_val = val.v.integer_val; + val.v.float_val = val.v.int_val; val.lltype = ev_float; case ev_float: tab = float_imm_defs; type = &type_float; break; case ev_string: - val.v.integer_val = ReuseString (val.v.string_val); + val.v.int_val = ReuseString (val.v.string_val); tab = string_imm_defs; type = &type_string; break; @@ -637,7 +637,7 @@ clear_immediates (void) Hash_FlushTable (func_imm_defs); Hash_FlushTable (pointer_imm_defs); Hash_FlushTable (quaternion_imm_defs); - Hash_FlushTable (integer_imm_defs); + Hash_FlushTable (int_imm_defs); Hash_FlushTable (double_imm_defs); } else { value_table = Hash_NewTable (16381, 0, 0, 0, 0); @@ -675,9 +675,9 @@ clear_immediates (void) &quaternion_imm_defs, 0); Hash_SetHashCompare (quaternion_imm_defs, imm_get_hash, imm_compare); - integer_imm_defs = Hash_NewTable (16381, 0, imm_free, - &integer_imm_defs, 0); - Hash_SetHashCompare (integer_imm_defs, imm_get_hash, imm_compare); + int_imm_defs = Hash_NewTable (16381, 0, imm_free, + &int_imm_defs, 0); + Hash_SetHashCompare (int_imm_defs, imm_get_hash, imm_compare); double_imm_defs = Hash_NewTable (16381, 0, imm_free, &double_imm_defs, 0); @@ -691,5 +691,5 @@ clear_immediates (void) make_def_imm (def, float_imm_defs, &zero_val); make_def_imm (def, entity_imm_defs, &zero_val); make_def_imm (def, pointer_imm_defs, &zero_val); - make_def_imm (def, integer_imm_defs, &zero_val); + make_def_imm (def, int_imm_defs, &zero_val); } diff --git a/tools/qfcc/test/double-alias.r b/tools/qfcc/test/double-alias.r index 6050d2f6d..92eecd9c3 100644 --- a/tools/qfcc/test/double-alias.r +++ b/tools/qfcc/test/double-alias.r @@ -23,12 +23,12 @@ alias_printf (string fmt, ...) { int fail = 0; // this will fail on big-endian systems - fail = (@args.list[2].integer_val != 0x54442d18 - || @args.list[1].integer_val != 0x400921fb); + fail = (@args.list[2].int_val != 0x54442d18 + || @args.list[1].int_val != 0x400921fb); printf ("%g %08x%08x\n", - @args.list[0].integer_val, - @args.list[2].integer_val, - @args.list[1].integer_val); + @args.list[0].int_val, + @args.list[2].int_val, + @args.list[1].int_val); return fail; } diff --git a/tools/qfcc/test/typedef.r b/tools/qfcc/test/typedef.r index 9dbd7f40b..3755f63eb 100644 --- a/tools/qfcc/test/typedef.r +++ b/tools/qfcc/test/typedef.r @@ -26,7 +26,7 @@ check_alias (string name, qfot_type_t *alias) { if (alias.meta != ty_basic || alias.type != ev_pointer || alias.fldptr.aux_type.meta != ty_basic - || alias.fldptr.aux_type.type != ev_integer) { + || alias.fldptr.aux_type.type != ev_int) { printf ("%s is not a *int alias\n", name); return 0; } From 8a9911bf61a26c315207aaa2eb08150f051531f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 14:14:17 +0900 Subject: [PATCH 2210/3664] [build] Fix messed up progs include dir I'd missed adding progs/ to the paths. --- include/QF/Makemodule.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 76265bd70..407d0a358 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -132,11 +132,11 @@ include_qf_plugin = \ include/QF/plugin/vid_render.h include_qf_progs = \ - include/QF/pr_comp.h \ - include/QF/pr_debug.h \ - include/QF/pr_obj.h \ - include/QF/pr_type.h \ - include/QF/pr_type_names.h + include/QF/progs/pr_comp.h \ + include/QF/progs/pr_debug.h \ + include/QF/progs/pr_obj.h \ + include/QF/progs/pr_type.h \ + include/QF/progs/pr_type_names.h include_qf_scene = \ include/QF/scene/entity.h \ From 2f6c3c8ffb7b9e44886dae50e065df7596191dda Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 14:21:09 +0900 Subject: [PATCH 2211/3664] [ruamoko] Use pr_type_names.h for Ruamoko Keeping the two sets of definitions in sync has always been a pain. --- config.d/build_control.m4 | 2 ++ include/QF/Makemodule.am | 3 +++ ruamoko/include/types.h | 16 ++-------------- ruamoko/lib/types.r | 18 +++++------------- 4 files changed, 12 insertions(+), 27 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index f55045a58..f3e59d2d5 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -316,9 +316,11 @@ if test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes"; then QF_NEED(top, [ruamoko]) qfac_qfcc_include_qf="\$(qfcc_include_qf)" qfac_qfcc_include_qf_input="\$(qfcc_include_qf_input)" + qfac_qfcc_include_qf_progs="\$(qfcc_include_qf_progs)" fi QF_SUBST(qfac_qfcc_include_qf) QF_SUBST(qfac_qfcc_include_qf_input) +QF_SUBST(qfac_qfcc_include_qf_progs) if test x"${top_need_libs}" = xyes; then qfac_include_qf="\$(include_qf)" diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 407d0a358..3892a430e 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -198,6 +198,7 @@ include_qf_vulkan = \ # headers shared with ruamoko qfcc_include_qf = include/QF/input.h +qfcc_include_qf_progs = include/QF/progs/pr_type_names.h qfcc_include_qf_input = \ include/QF/input/binding.h \ include/QF/input/imt.h @@ -225,8 +226,10 @@ qf_vulkan_include_HEADERS = @qfac_include_qf_vulkan@ ruamoko_qf_includedir = $(ruamoko_includedir)/QF ruamoko_qf_input_includedir = $(ruamoko_includedir)/QF/input +ruamoko_qf_progs_includedir = $(ruamoko_includedir)/QF/progs ruamoko_qf_include_HEADERS = @qfac_qfcc_include_qf@ ruamoko_qf_input_include_HEADERS = @qfac_qfcc_include_qf_input@ +ruamoko_qf_progs_include_HEADERS = @qfac_qfcc_include_qf_progs@ EXTRA_HEADERS += \ $(include_qf) \ diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index 7054eeead..2ff8a123e 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -1,21 +1,9 @@ #ifndef __types_h #define __types_h +#define EV_TYPE(type) ev_##type, typedef enum { - ev_void, - ev_string, - ev_float, - ev_vector, - ev_entity, - ev_field, - ev_func, - ev_pointer, // end of v6 types - ev_quat, - ev_int, - ev_uint, - ev_short, // value is embedded in the opcode - ev_double, - +#include ev_invalid, // invalid type. used for instruction checking ev_type_count // not a type, gives number of types } etype_t; diff --git a/ruamoko/lib/types.r b/ruamoko/lib/types.r index 45f51c70e..cecbe09bb 100644 --- a/ruamoko/lib/types.r +++ b/ruamoko/lib/types.r @@ -11,6 +11,7 @@ string ty_meta_name[7] = { "alias", }; +//FIXME use pr_type_names.h int pr_type_size[ev_type_count] = { 1, // ev_void 1, // ev_string @@ -25,22 +26,13 @@ int pr_type_size[ev_type_count] = { 1, // ev_uinteger 0, // ev_short value in opcode 2, // ev_double + 2, // ev_long + 2, // ev_ulong 0, // ev_invalid not a valid/simple type }; +#define EV_TYPE(type) #type, string pr_type_name[ev_type_count] = { - "void", - "string", - "float", - "vector", - "entity", - "field", - "function", - "pointer", - "quaternion", - "integer", - "uinteger", - "short", - "double", +#include "invalid", }; From afd1eb775bb9c47338a7b237ecc769b731685b7e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 14:36:06 +0900 Subject: [PATCH 2212/3664] [gamecode] Rename ev_pointer to ev_ptr Rather short (no worse than ev_int, though) but more consistency is usually a good thing. --- include/QF/progs/pr_type.h | 4 +- include/QF/progs/pr_type_names.h | 2 +- libs/gamecode/opcodes.py | 2 +- libs/gamecode/pr_debug.c | 2 +- libs/gamecode/pr_v6p_opcode.c | 238 ++++++++++----------- libs/video/renderer/vulkan/vkgen/vkalias.r | 2 +- libs/video/renderer/vulkan/vkgen/vkgen.r | 2 +- libs/video/renderer/vulkan/vkgen/vktype.r | 8 +- nq/source/sv_progs.c | 2 +- qw/source/sv_progs.c | 2 +- ruamoko/lib/types.r | 2 +- ruamoko/qwaq/debugger/typeencodings.r | 2 +- tools/qfcc/source/class.c | 18 +- tools/qfcc/source/constfold.c | 32 +-- tools/qfcc/source/dags.c | 2 +- tools/qfcc/source/def.c | 2 +- tools/qfcc/source/dot_expr.c | 2 +- tools/qfcc/source/dot_type.c | 4 +- tools/qfcc/source/dump_globals.c | 4 +- tools/qfcc/source/expr.c | 21 +- tools/qfcc/source/expr_binary.c | 16 +- tools/qfcc/source/expr_bool.c | 2 +- tools/qfcc/source/flow.c | 2 +- tools/qfcc/source/obj_type.c | 2 +- tools/qfcc/source/statements.c | 8 +- tools/qfcc/source/type.c | 22 +- tools/qfcc/source/value.c | 6 +- tools/qfcc/test/typedef.r | 2 +- 28 files changed, 208 insertions(+), 205 deletions(-) diff --git a/include/QF/progs/pr_type.h b/include/QF/progs/pr_type.h index 328b2ff3e..02c591dfa 100644 --- a/include/QF/progs/pr_type.h +++ b/include/QF/progs/pr_type.h @@ -58,7 +58,7 @@ typedef struct qfot_alias_s { } qfot_alias_t; typedef struct qfot_fldptr_s { - etype_t type; ///< ev_field or ev_pointer + etype_t type; ///< ev_field or ev_ptr pr_ptr_t aux_type; ///< referenced type } qfot_fldptr_t; @@ -106,7 +106,7 @@ typedef struct qfot_type_s { pr_string_t encoding; ///< Objective-QC encoding union { etype_t type; ///< ty_basic: etype_t - qfot_fldptr_t fldptr; ///< ty_basic, ev_pointer/ev_field + qfot_fldptr_t fldptr; ///< ty_basic, ev_ptr/ev_field qfot_func_t func; ///< ty_basic, ev_func qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum qfot_array_t array; ///< ty_array diff --git a/include/QF/progs/pr_type_names.h b/include/QF/progs/pr_type_names.h index ff190f2cd..712a3c74c 100644 --- a/include/QF/progs/pr_type_names.h +++ b/include/QF/progs/pr_type_names.h @@ -37,7 +37,7 @@ EV_TYPE(vector) EV_TYPE(entity) EV_TYPE(field) EV_TYPE(func) -EV_TYPE(pointer) // end of v6 types +EV_TYPE(ptr) // end of v6 types EV_TYPE(quat) EV_TYPE(int) EV_TYPE(uint) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 8734bb03c..f35067a7e 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -187,7 +187,7 @@ lea_formats = { "opname": "lea", "format": "{lea_fmt[mm]}", "widths": "0, 0, 1", - "types": "ev_pointer, ev_pointer, ev_pointer", + "types": "ev_ptr, ev_ptr, ev_ptr", "args": { "op_mode": "AECD", "lea_fmt": [ diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 9e0b1b363..16d584e88 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1050,7 +1050,7 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) case ev_func: raw_type_view.func_view (type, value, data); break; - case ev_pointer: + case ev_ptr: raw_type_view.pointer_view (type, value, data); break; case ev_quat: diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index c61821852..934a6ed69 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -335,182 +335,182 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga.%Gb(%Ec), %gc", }, [OP_LOAD_P_v6p] = {".", "load.p", - ev_entity, ev_field, ev_pointer, + ev_entity, ev_field, ev_ptr, PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, [OP_LOADB_D_v6p] = {".", "loadb.d", - ev_pointer, ev_int, ev_double, + ev_ptr, ev_int, ev_double, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_F_v6p] = {".", "loadb.f", - ev_pointer, ev_int, ev_float, + ev_ptr, ev_int, ev_float, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_V_v6p] = {".", "loadb.v", - ev_pointer, ev_int, ev_vector, + ev_ptr, ev_int, ev_vector, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_Q_v6p] = {".", "loadb.q", - ev_pointer, ev_int, ev_quat, + ev_ptr, ev_int, ev_quat, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_S_v6p] = {".", "loadb.s", - ev_pointer, ev_int, ev_string, + ev_ptr, ev_int, ev_string, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_ENT_v6p] = {".", "loadb.ent", - ev_pointer, ev_int, ev_entity, + ev_ptr, ev_int, ev_entity, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_FLD_v6p] = {".", "loadb.fld", - ev_pointer, ev_int, ev_field, + ev_ptr, ev_int, ev_field, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_FN_v6p] = {".", "loadb.fn", - ev_pointer, ev_int, ev_func, + ev_ptr, ev_int, ev_func, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_I_v6p] = {".", "loadb.i", - ev_pointer, ev_int, ev_int, + ev_ptr, ev_int, ev_int, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADB_P_v6p] = {".", "loadb.p", - ev_pointer, ev_int, ev_pointer, + ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, [OP_LOADBI_D_v6p] = {".", "loadbi.d", - ev_pointer, ev_short, ev_double, + ev_ptr, ev_short, ev_double, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_F_v6p] = {".", "loadbi.f", - ev_pointer, ev_short, ev_float, + ev_ptr, ev_short, ev_float, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_V_v6p] = {".", "loadbi.v", - ev_pointer, ev_short, ev_vector, + ev_ptr, ev_short, ev_vector, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_Q_v6p] = {".", "loadbi.q", - ev_pointer, ev_short, ev_quat, + ev_ptr, ev_short, ev_quat, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_S_v6p] = {".", "loadbi.s", - ev_pointer, ev_short, ev_string, + ev_ptr, ev_short, ev_string, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_ENT_v6p] = {".", "loadbi.ent", - ev_pointer, ev_short, ev_entity, + ev_ptr, ev_short, ev_entity, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_FLD_v6p] = {".", "loadbi.fld", - ev_pointer, ev_short, ev_field, + ev_ptr, ev_short, ev_field, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_FN_v6p] = {".", "loadbi.fn", - ev_pointer, ev_short, ev_func, + ev_ptr, ev_short, ev_func, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_I_v6p] = {".", "loadbi.i", - ev_pointer, ev_short, ev_int, + ev_ptr, ev_short, ev_int, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_LOADBI_P_v6p] = {".", "loadbi.p", - ev_pointer, ev_short, ev_pointer, + ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, [OP_ADDRESS_v6p] = {"&", "address", - ev_entity, ev_field, ev_pointer, + ev_entity, ev_field, ev_ptr, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, [OP_ADDRESS_VOID_v6p] = {"&", "address", - ev_void, ev_invalid, ev_pointer, + ev_void, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_D_v6p] = {"&", "address.d", - ev_double, ev_invalid, ev_pointer, + ev_double, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_F_v6p] = {"&", "address.f", - ev_float, ev_invalid, ev_pointer, + ev_float, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_V_v6p] = {"&", "address.v", - ev_vector, ev_invalid, ev_pointer, + ev_vector, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_Q_v6p] = {"&", "address.q", - ev_quat, ev_invalid, ev_pointer, + ev_quat, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_S_v6p] = {"&", "address.s", - ev_string, ev_invalid, ev_pointer, + ev_string, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_ENT_v6p] = {"&", "address.ent", - ev_entity, ev_invalid, ev_pointer, + ev_entity, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_FLD_v6p] = {"&", "address.fld", - ev_field, ev_invalid, ev_pointer, + ev_field, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_FN_v6p] = {"&", "address.fn", - ev_func, ev_invalid, ev_pointer, + ev_func, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_I_v6p] = {"&", "address.i", - ev_int, ev_invalid, ev_pointer, + ev_int, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_ADDRESS_P_v6p] = {"&", "address.p", - ev_pointer, ev_invalid, ev_pointer, + ev_ptr, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, [OP_LEA_v6p] = {"&", "lea", - ev_pointer, ev_int, ev_pointer, + ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "(%Ga + %Gb), %gc", }, [OP_LEAI_v6p] = {"&", "leai", - ev_pointer, ev_short, ev_pointer, + ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "(%Ga + %sb), %gc", }, @@ -592,160 +592,160 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %gb", }, [OP_STORE_P_v6p] = {"=", "store.p", - ev_pointer, ev_pointer, ev_invalid, + ev_ptr, ev_ptr, ev_invalid, PROG_V6P_VERSION, "%Ga, %gb", }, [OP_STOREP_D_v6p] = {".=", "storep.d", - ev_double, ev_pointer, ev_invalid, + ev_double, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, [OP_STOREP_F_v6p] = {".=", "storep.f", - ev_float, ev_pointer, ev_invalid, + ev_float, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, [OP_STOREP_V_v6p] = {".=", "storep.v", - ev_vector, ev_pointer, ev_invalid, + ev_vector, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, [OP_STOREP_Q_v6p] = {".=", "storep.q", - ev_quat, ev_pointer, ev_invalid, + ev_quat, ev_ptr, ev_invalid, PROG_V6P_VERSION, "%Ga, *%Gb", }, [OP_STOREP_S_v6p] = {".=", "storep.s", - ev_string, ev_pointer, ev_invalid, + ev_string, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, [OP_STOREP_ENT_v6p] = {".=", "storep.ent", - ev_entity, ev_pointer, ev_invalid, + ev_entity, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, [OP_STOREP_FLD_v6p] = {".=", "storep.fld", - ev_field, ev_pointer, ev_invalid, + ev_field, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, [OP_STOREP_FN_v6p] = {".=", "storep.fn", - ev_func, ev_pointer, ev_invalid, + ev_func, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, [OP_STOREP_I_v6p] = {".=", "storep.i", - ev_int, ev_pointer, ev_invalid, + ev_int, ev_ptr, ev_invalid, PROG_V6P_VERSION, "%Ga, *%Gb", }, [OP_STOREP_P_v6p] = {".=", "storep.p", - ev_pointer, ev_pointer, ev_invalid, + ev_ptr, ev_ptr, ev_invalid, PROG_V6P_VERSION, "%Ga, *%Gb", }, [OP_STOREB_D_v6p] = {".=", "storeb.d", - ev_double, ev_pointer, ev_int, + ev_double, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_F_v6p] = {".=", "storeb.f", - ev_float, ev_pointer, ev_int, + ev_float, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_V_v6p] = {".=", "storeb.v", - ev_vector, ev_pointer, ev_int, + ev_vector, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_Q_v6p] = {".=", "storeb.q", - ev_quat, ev_pointer, ev_int, + ev_quat, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_S_v6p] = {".=", "storeb.s", - ev_string, ev_pointer, ev_int, + ev_string, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_ENT_v6p] = {".=", "storeb.ent", - ev_entity, ev_pointer, ev_int, + ev_entity, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_FLD_v6p] = {".=", "storeb.fld", - ev_field, ev_pointer, ev_int, + ev_field, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_FN_v6p] = {".=", "storeb.fn", - ev_func, ev_pointer, ev_int, + ev_func, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_I_v6p] = {".=", "storeb.i", - ev_int, ev_pointer, ev_int, + ev_int, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_P_v6p] = {".=", "storeb.p", - ev_pointer, ev_pointer, ev_int, + ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, [OP_STOREBI_D_v6p] = {".=", "storebi.d", - ev_double, ev_pointer, ev_short, + ev_double, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_F_v6p] = {".=", "storebi.f", - ev_float, ev_pointer, ev_short, + ev_float, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_V_v6p] = {".=", "storebi.v", - ev_vector, ev_pointer, ev_short, + ev_vector, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_Q_v6p] = {".=", "storebi.q", - ev_quat, ev_pointer, ev_short, + ev_quat, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_S_v6p] = {".=", "storebi.s", - ev_string, ev_pointer, ev_short, + ev_string, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_ENT_v6p] = {".=", "storebi.ent", - ev_entity, ev_pointer, ev_short, + ev_entity, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_FLD_v6p] = {".=", "storebi.fld", - ev_field, ev_pointer, ev_short, + ev_field, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_FN_v6p] = {".=", "storebi.fn", - ev_func, ev_pointer, ev_short, + ev_func, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_I_v6p] = {".=", "storebi.i", - ev_int, ev_pointer, ev_short, + ev_int, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_P_v6p] = {".=", "storebi.p", - ev_pointer, ev_pointer, ev_short, + ev_ptr, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, @@ -798,7 +798,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %gc", }, [OP_NOT_P_v6p] = {"!", "not.p", - ev_pointer, ev_invalid, ev_int, + ev_ptr, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, @@ -1112,27 +1112,27 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_GE_P_v6p] = {">=", "ge.p", - ev_pointer, ev_pointer, ev_int, + ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, [OP_LE_P_v6p] = {"<=", "le.p", - ev_pointer, ev_pointer, ev_int, + ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, [OP_GT_P_v6p] = {">", "gt.p", - ev_pointer, ev_pointer, ev_int, + ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, [OP_LT_P_v6p] = {"<", "lt.p", - ev_pointer, ev_pointer, ev_int, + ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, [OP_EQ_P_v6p] = {"==", "eq.p", - ev_pointer, ev_pointer, ev_int, + ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, [OP_NE_P_v6p] = {"!=", "ne.p", - ev_pointer, ev_pointer, ev_int, + ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, @@ -1142,12 +1142,12 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %sb, %gc", }, [OP_MOVEP_v6p] = {"", "movep", - ev_pointer, ev_int, ev_pointer, + ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, [OP_MOVEPI_v6p] = {"", "movepi", - ev_pointer, ev_short, ev_pointer, + ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "%Ga, %sb, %Gc", }, @@ -1157,12 +1157,12 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %sb, %gc", }, [OP_MEMSETP_v6p] = {"", "memsetp", - ev_int, ev_int, ev_pointer, + ev_int, ev_int, ev_ptr, PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, [OP_MEMSETPI_v6p] = {"", "memsetpi", - ev_int, ev_short, ev_pointer, + ev_int, ev_short, ev_ptr, PROG_V6P_VERSION, "%Ga, %sb, %Gc", }, @@ -1198,7 +1198,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga", }, [OP_PUSH_P_v6p] = {"", "push.p", - ev_pointer, ev_invalid, ev_invalid, + ev_ptr, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, @@ -1219,103 +1219,103 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_PUSHB_S_v6p] = {"", "pushb.s", - ev_pointer, ev_int, ev_string, + ev_ptr, ev_int, ev_string, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_F_v6p] = {"", "pushb.f", - ev_pointer, ev_int, ev_float, + ev_ptr, ev_int, ev_float, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_V_v6p] = {"", "pushb.v", - ev_pointer, ev_int, ev_vector, + ev_ptr, ev_int, ev_vector, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_ENT_v6p] = {"", "pushb.ent", - ev_pointer, ev_int, ev_entity, + ev_ptr, ev_int, ev_entity, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_FLD_v6p] = {"", "pushb.fld", - ev_pointer, ev_int, ev_field, + ev_ptr, ev_int, ev_field, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_FN_v6p] = {"", "pushb.fn", - ev_pointer, ev_int, ev_func, + ev_ptr, ev_int, ev_func, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_P_v6p] = {"", "pushb.p", - ev_pointer, ev_int, ev_pointer, + ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_Q_v6p] = {"", "pushb.q", - ev_pointer, ev_int, ev_quat, + ev_ptr, ev_int, ev_quat, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_I_v6p] = {"", "pushb.i", - ev_pointer, ev_int, ev_int, + ev_ptr, ev_int, ev_int, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHB_D_v6p] = {"", "pushb.d", - ev_pointer, ev_int, ev_double, + ev_ptr, ev_int, ev_double, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_PUSHBI_S_v6p] = {"", "pushbi.s", - ev_pointer, ev_short, ev_string, + ev_ptr, ev_short, ev_string, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_F_v6p] = {"", "pushbi.f", - ev_pointer, ev_short, ev_float, + ev_ptr, ev_short, ev_float, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_V_v6p] = {"", "pushbi.v", - ev_pointer, ev_short, ev_vector, + ev_ptr, ev_short, ev_vector, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_ENT_v6p] = {"", "pushbi.ent", - ev_pointer, ev_short, ev_entity, + ev_ptr, ev_short, ev_entity, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_FLD_v6p] = {"", "pushbi.fld", - ev_pointer, ev_short, ev_field, + ev_ptr, ev_short, ev_field, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_FN_v6p] = {"", "pushbi.fn", - ev_pointer, ev_short, ev_func, + ev_ptr, ev_short, ev_func, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_P_v6p] = {"", "pushbi.p", - ev_pointer, ev_short, ev_pointer, + ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_Q_v6p] = {"", "pushbi.q", - ev_pointer, ev_short, ev_quat, + ev_ptr, ev_short, ev_quat, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_I_v6p] = {"", "pushbi.i", - ev_pointer, ev_short, ev_int, + ev_ptr, ev_short, ev_int, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_PUSHBI_D_v6p] = {"", "pushbi.d", - ev_pointer, ev_short, ev_double, + ev_ptr, ev_short, ev_double, PROG_V6P_VERSION, "*(%Ga + %sb)", }, @@ -1351,7 +1351,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%ga", }, [OP_POP_P_v6p] = {"", "pop.p", - ev_pointer, ev_invalid, ev_invalid, + ev_ptr, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, @@ -1372,103 +1372,103 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { }, [OP_POPB_S_v6p] = {"", "popb.s", - ev_pointer, ev_int, ev_string, + ev_ptr, ev_int, ev_string, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_F_v6p] = {"", "popb.f", - ev_pointer, ev_int, ev_float, + ev_ptr, ev_int, ev_float, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_V_v6p] = {"", "popb.v", - ev_pointer, ev_int, ev_vector, + ev_ptr, ev_int, ev_vector, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_ENT_v6p] = {"", "popb.ent", - ev_pointer, ev_int, ev_entity, + ev_ptr, ev_int, ev_entity, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_FLD_v6p] = {"", "popb.fld", - ev_pointer, ev_int, ev_field, + ev_ptr, ev_int, ev_field, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_FN_v6p] = {"", "popb.fn", - ev_pointer, ev_int, ev_func, + ev_ptr, ev_int, ev_func, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_P_v6p] = {"", "popb.p", - ev_pointer, ev_int, ev_pointer, + ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_Q_v6p] = {"", "popb.q", - ev_pointer, ev_int, ev_quat, + ev_ptr, ev_int, ev_quat, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_I_v6p] = {"", "popb.i", - ev_pointer, ev_int, ev_int, + ev_ptr, ev_int, ev_int, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPB_D_v6p] = {"", "popb.d", - ev_pointer, ev_int, ev_double, + ev_ptr, ev_int, ev_double, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, [OP_POPBI_S_v6p] = {"", "popbi.s", - ev_pointer, ev_short, ev_string, + ev_ptr, ev_short, ev_string, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_F_v6p] = {"", "popbi.f", - ev_pointer, ev_short, ev_float, + ev_ptr, ev_short, ev_float, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_V_v6p] = {"", "popbi.v", - ev_pointer, ev_short, ev_vector, + ev_ptr, ev_short, ev_vector, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_ENT_v6p] = {"", "popbi.ent", - ev_pointer, ev_short, ev_entity, + ev_ptr, ev_short, ev_entity, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_FLD_v6p] = {"", "popbi.fld", - ev_pointer, ev_short, ev_field, + ev_ptr, ev_short, ev_field, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_FN_v6p] = {"", "popbi.fn", - ev_pointer, ev_short, ev_func, + ev_ptr, ev_short, ev_func, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_P_v6p] = {"", "popbi.p", - ev_pointer, ev_short, ev_pointer, + ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_Q_v6p] = {"", "popbi.q", - ev_pointer, ev_short, ev_quat, + ev_ptr, ev_short, ev_quat, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_I_v6p] = {"", "popbi.i", - ev_pointer, ev_short, ev_int, + ev_ptr, ev_short, ev_int, PROG_V6P_VERSION, "*(%Ga + %sb)", }, [OP_POPBI_D_v6p] = {"", "popbi.d", - ev_pointer, ev_short, ev_double, + ev_ptr, ev_short, ev_double, PROG_V6P_VERSION, "*(%Ga + %sb)", }, diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index e0aad2943..bbb7ffb21 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -33,7 +33,7 @@ } else if ([alias class] == [Enum class] || [alias class] == [Struct class]) { [alias addToQueue]; - } else if (alias.type.meta == ty_basic && alias.type.type == ev_pointer) { + } else if (alias.type.meta == ty_basic && alias.type.type == ev_ptr) { Type *type = [Type findType:alias.type.fldptr.aux_type]; if (!type) { // pointer to opaque struct. Probably diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 4bcd74ee4..a3a5e426f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -66,7 +66,7 @@ void print_type (qfot_type_t *type) case ty_basic: //printf (" %d", type.type); switch (type.type) { - case ev_pointer: + case ev_ptr: case ev_field: //printf (" "); print_type (type.fldptr.aux_type); diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index aa32f3a41..70de1fbc7 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -89,7 +89,7 @@ static string get_type_key (void *type, void *unused) -(void) addToQueue { string name = [self name]; - if (type.meta == ty_basic && type.type == ev_pointer) { + if (type.meta == ty_basic && type.type == ev_ptr) { [[Type findType: type.fldptr.aux_type] addToQueue]; } } @@ -134,7 +134,7 @@ static string get_type_key (void *type, void *unused) -(int) isPointer { if ((type.meta == ty_basic || type.meta == ty_alias) - && type.type == ev_pointer) { + && type.type == ev_ptr) { return 1; } return 0; @@ -143,10 +143,10 @@ static string get_type_key (void *type, void *unused) -(Type *) dereference { qfot_type_t *t = type; - if (t.meta == ty_alias && t.type == ev_pointer) { + if (t.meta == ty_alias && t.type == ev_ptr) { t = type.alias.full_type; } - if (t.meta == ty_basic && t.type == ev_pointer) { + if (t.meta == ty_basic && t.type == ev_ptr) { t = type.fldptr.aux_type; } return [Type findType:t]; diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 5c94f8080..65c7ee495 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -354,7 +354,7 @@ set_address (sv_def_t *def, void *address) case ev_entity: case ev_field: case ev_func: - case ev_pointer: + case ev_ptr: case ev_int: case ev_uint: *(pr_int_t **)def->field = (pr_int_t *) address; diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 8937e7fc8..4510ee339 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -387,7 +387,7 @@ set_address (sv_def_t *def, void *address) case ev_entity: case ev_field: case ev_func: - case ev_pointer: + case ev_ptr: case ev_int: case ev_uint: *(pr_int_t **)def->field = (pr_int_t *) address; diff --git a/ruamoko/lib/types.r b/ruamoko/lib/types.r index cecbe09bb..f732cc8d0 100644 --- a/ruamoko/lib/types.r +++ b/ruamoko/lib/types.r @@ -20,7 +20,7 @@ int pr_type_size[ev_type_count] = { 1, // ev_entity 1, // ev_field 1, // ev_func - 1, // ev_pointer + 1, // ev_ptr 4, // ev_quat 1, // ev_integer 1, // ev_uinteger diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index 64429b273..fe296a573 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -106,7 +106,7 @@ static void type_free (void *t, void *unused) } switch (type.meta) { case ty_basic: - if (type.type == ev_pointer || type.type == ev_field) { + if (type.type == ev_ptr || type.type == ev_field) { t = [TypeEncodings getType:(unsigned)type.fldptr.aux_type fromTarget:target]; if (!t) { diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index de0d473e6..b821135a7 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -72,12 +72,12 @@ static hashtab_t *static_instance_classes; // these will be built up further type_t type_selector = { ev_invalid, 0, 0, ty_struct}; -type_t type_SEL = { ev_pointer, "SEL", 1, ty_basic, {{&type_selector}}}; +type_t type_SEL = { ev_ptr, "SEL", 1, ty_basic, {{&type_selector}}}; type_t *IMP_params[] = {&type_id, &type_SEL}; type_t type_IMP = { ev_func, "IMP", 1, ty_basic, {{&type_id, -3, IMP_params}}}; type_t type_super = { ev_invalid, 0, 0 }; -type_t type_SuperPtr = { ev_pointer, 0, 1, ty_basic, {{&type_super}}}; +type_t type_SuperPtr = { ev_ptr, 0, 1, ty_basic, {{&type_super}}}; type_t *supermsg_params[] = {&type_SuperPtr, &type_SEL}; type_t type_supermsg = { ev_func, ".supermsg", 1, ty_basic, {{&type_id, -3, supermsg_params}}}; @@ -86,7 +86,7 @@ type_t type_method_description = { ev_invalid, 0, 0, ty_struct }; type_t type_category = { ev_invalid, 0, 0, ty_struct}; type_t type_ivar = { ev_invalid, 0, 0, ty_struct}; type_t type_module = { ev_invalid, 0, 0, ty_struct}; -type_t type_moduleptr = { ev_pointer, 0, 1, ty_basic, {{&type_module}}}; +type_t type_moduleptr = { ev_ptr, 0, 1, ty_basic, {{&type_module}}}; type_t *obj_exec_class_params[] = { &type_moduleptr }; type_t type_exec_class = { ev_func, 0, 1, ty_basic, {{&type_void, 1, obj_exec_class_params}}}; @@ -94,9 +94,9 @@ type_t type_exec_class = { ev_func, 0, 1, ty_basic, // are never misidentified as id. It will be set to the correct value // when the obj system is initialized. type_t type_object = {ev_invalid, 0, 0, ty_struct, {{(type_t *)1}}}; -type_t type_id = { ev_pointer, "id", 1, ty_basic, {{&type_object}}}; +type_t type_id = { ev_ptr, "id", 1, ty_basic, {{&type_object}}}; type_t type_class = { ev_invalid, 0, 0, ty_struct}; -type_t type_Class = { ev_pointer, 0, 1, ty_basic, {{&type_class}}}; +type_t type_Class = { ev_ptr, 0, 1, ty_basic, {{&type_class}}}; type_t type_protocol = { ev_invalid, 0, 0, ty_struct}; int obj_initialized = 0; @@ -229,7 +229,7 @@ emit_instance_defs (def_t *def, void *data, int index) { obj_static_instances_data_t *da = (obj_static_instances_data_t *)data; - if (!is_array (def->type) || def->type->t.array.type->type != ev_pointer) + if (!is_array (def->type) || def->type->t.array.type->type != ev_ptr) internal_error (0, "%s: expected array of pointers def", __FUNCTION__); if (index < 0 || index >= da->num_instances + 1) internal_error (0, "%s: out of bounds index: %d %d", @@ -325,7 +325,7 @@ is_id (const type_t *type) return 1; // type may be a qualified id, in which case it will be a pointer to // a qualified obj_object struct - if (type->type != ev_pointer) + if (type->type != ev_ptr) return 0; if (!is_struct (type->t.fldptr.type)) return 0; @@ -357,7 +357,7 @@ is_classptr (const type_t *type) // easy cases first :) if (is_id (type) || is_Class (type)) return 1; - if (type->type != ev_pointer) + if (type->type != ev_ptr) return 0; type = type->t.fldptr.type; if (is_class (type)) @@ -1455,7 +1455,7 @@ emit_symtab_defs (def_t *def, void *data, int index) { obj_symtab_data_t *da = (obj_symtab_data_t *)data; - if (!is_array (def->type) || def->type->t.array.type->type != ev_pointer) + if (!is_array (def->type) || def->type->t.array.type->type != ev_ptr) internal_error (0, "%s: expected array of pointers def", __FUNCTION__); if (index < 0 || index >= da->cls_def_cnt + da->cat_def_cnt + 1) internal_error (0, "%s: out of bounds index: %d %d", diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 20a9c5716..8566e00b1 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1060,7 +1060,7 @@ static operation_t op_void[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_invalid, // ev_quaternion do_op_invalid, // ev_int do_op_invalid, // ev_uint @@ -1079,7 +1079,7 @@ static operation_t op_string[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_invalid, // ev_quaternion do_op_invalid, // ev_int do_op_invalid, // ev_uint @@ -1098,7 +1098,7 @@ static operation_t op_float[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_quaternion, // ev_quaternion do_op_float, // ev_int do_op_float, // ev_uint @@ -1117,7 +1117,7 @@ static operation_t op_vector[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_invalid, // ev_quaternion do_op_vector, // ev_int do_op_vector, // ev_uint @@ -1136,7 +1136,7 @@ static operation_t op_entity[ev_type_count] = { do_op_entity, // ev_entity do_op_entity, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_invalid, // ev_quaternion do_op_invalid, // ev_int do_op_invalid, // ev_uint @@ -1155,7 +1155,7 @@ static operation_t op_field[ev_type_count] = { do_op_invalid, // ev_entity do_op_field, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_invalid, // ev_quaternion do_op_invalid, // ev_int do_op_invalid, // ev_uint @@ -1174,7 +1174,7 @@ static operation_t op_func[ev_type_count] = { do_op_func, // ev_entity do_op_func, // ev_field do_op_func, // ev_func - do_op_func, // ev_pointer + do_op_func, // ev_ptr do_op_func, // ev_quaternion do_op_func, // ev_int do_op_func, // ev_uint @@ -1193,7 +1193,7 @@ static operation_t op_pointer[ev_type_count] = { do_op_pointer, // ev_entity do_op_pointer, // ev_field do_op_pointer, // ev_func - do_op_pointer, // ev_pointer + do_op_pointer, // ev_ptr do_op_pointer, // ev_quaternion do_op_pointer, // ev_int do_op_pointer, // ev_uint @@ -1212,7 +1212,7 @@ static operation_t op_quaternion[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_quaternion, // ev_quaternion do_op_quaternion, // ev_int do_op_quaternion, // ev_uint @@ -1231,7 +1231,7 @@ static operation_t op_int[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_quaternion, // ev_quaternion do_op_int, // ev_int do_op_uint, // ev_uint @@ -1250,7 +1250,7 @@ static operation_t op_uint[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_quaternion, // ev_quaternion do_op_uint, // ev_int do_op_uint, // ev_uint @@ -1269,7 +1269,7 @@ static operation_t op_short[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_quaternion, // ev_quaternion do_op_int, // ev_int do_op_uint, // ev_uint @@ -1288,7 +1288,7 @@ static operation_t op_double[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_quaternion, // ev_quaternion do_op_int, // ev_int do_op_uint, // ev_uint @@ -1307,7 +1307,7 @@ static operation_t op_compound[ev_type_count] = { do_op_invalid, // ev_entity do_op_invalid, // ev_field do_op_invalid, // ev_func - do_op_invalid, // ev_pointer + do_op_invalid, // ev_ptr do_op_invalid, // ev_quaternion do_op_compound, // ev_int do_op_compound, // ev_uint @@ -1326,7 +1326,7 @@ static operation_t *do_op[ev_type_count] = { op_entity, // ev_entity op_field, // ev_field op_func, // ev_func - op_pointer, // ev_pointer + op_pointer, // ev_ptr op_quaternion, // ev_quaternion op_int, // ev_int op_uint, // ev_uint @@ -1658,7 +1658,7 @@ static unaryop_t do_unary_op[ev_type_count] = { uop_entity, // ev_entity uop_field, // ev_field uop_func, // ev_func - uop_pointer, // ev_pointer + uop_pointer, // ev_ptr uop_quaternion, // ev_quaternion uop_int, // ev_int uop_uint, // ev_uint diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 9e3b1cdab..9c7746bea 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -427,7 +427,7 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) set_add (node->edges, n->number); } if (op->op_type == op_value - && op->value->lltype == ev_pointer + && op->value->lltype == ev_ptr && op->value->v.pointer.def) { def_visit_all (op->value->v.pointer.def, 1, dagnode_def_set_edges_visit, n); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index cf854a1b4..449db7320 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -617,7 +617,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, internal_error (0, "initializier not a value"); return; } - if (init->e.value->lltype == ev_pointer + if (init->e.value->lltype == ev_ptr || init->e.value->lltype == ev_field) { // FIXME offset pointers D_INT (sym->s.def) = init->e.value->v.pointer.val; diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index d1cbfee26..19081fd48 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -547,7 +547,7 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->e.value->v.quaternion_val[2], e->e.value->v.quaternion_val[3]); break; - case ev_pointer: + case ev_ptr: type = e->e.value->v.pointer.type; dstring_clearstr(type_str); if (type) { diff --git a/tools/qfcc/source/dot_type.c b/tools/qfcc/source/dot_type.c index fa77bbf3d..5f743dae7 100644 --- a/tools/qfcc/source/dot_type.c +++ b/tools/qfcc/source/dot_type.c @@ -61,7 +61,7 @@ print_pointer (dstring_t *dstr, type_t *t, int level, int id) dot_print_type (dstr, aux, level, id); dasprintf (dstr, "%*st_%p -> \"t_%p\";\n", indent, "", t, aux); dasprintf (dstr, "%*st_%p [label=\"%c\"];\n", indent, "", t, - t->type == ev_pointer ? '*' : '.'); + t->type == ev_ptr ? '*' : '.'); } static void @@ -118,7 +118,7 @@ print_function (dstring_t *dstr, type_t *t, int level, int id) static void print_basic (dstring_t *dstr, type_t *t, int level, int id) { - if (t->type == ev_pointer || t->type == ev_field) { + if (t->type == ev_ptr || t->type == ev_field) { print_pointer (dstr, t, level, id); } else if (t->type == ev_func) { print_function (dstr, t, level, id); diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index e55c10104..5bff7e2a0 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -131,7 +131,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) } } break; - case ev_pointer: + case ev_ptr: comment = va (0, " %x", G_INT (pr, offset)); break; case ev_quat: @@ -559,7 +559,7 @@ dump_qfo_types (qfo_t *qfo, int base_address) count = ~count; //ones complement for (i = 0; i < count; i++) printf (" %x", type->func.param_types[i]); - } else if (type->type == ev_pointer + } else if (type->type == ev_ptr || type->type == ev_field) { printf (" %4x", type->fldptr.aux_type); } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 47daa1348..61e42c552 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -222,6 +222,7 @@ get_type (expr_t *e) case ex_memset: return e->e.memset.type; case ex_error: + return 0; case ex_return: internal_error (e, "unexpected expression type"); case ex_label: @@ -1263,7 +1264,7 @@ expr_integral (expr_t *e) int is_pointer_val (expr_t *e) { - if (e->type == ex_value && e->e.value->lltype == ev_pointer) { + if (e->type == ex_value && e->e.value->lltype == ev_ptr) { return 1; } return 0; @@ -1432,7 +1433,7 @@ field_expr (expr_t *e1, expr_t *e2) return e; } } - } else if (t1->type == ev_pointer) { + } else if (t1->type == ev_ptr) { if (is_struct (t1->t.fldptr.type)) { symbol_t *field; @@ -1695,7 +1696,7 @@ unary_expr (int op, expr_t *e) case ev_entity: case ev_field: case ev_func: - case ev_pointer: + case ev_ptr: internal_error (e, "type check failed!"); case ev_double: new = new_double_expr (-expr_double (e)); @@ -1797,7 +1798,7 @@ unary_expr (int op, expr_t *e) case ev_entity: case ev_field: case ev_func: - case ev_pointer: + case ev_ptr: internal_error (e, 0); case ev_string: s = expr_string (e); @@ -1875,7 +1876,7 @@ unary_expr (int op, expr_t *e) case ev_entity: case ev_field: case ev_func: - case ev_pointer: + case ev_ptr: case ev_vector: case ev_double: return error (e, "invalid type for unary ~"); @@ -1956,7 +1957,7 @@ bitnot_expr: } break; case '.': - if (extract_type (e) != ev_pointer) + if (extract_type (e) != ev_ptr) return error (e, "invalid type for unary ."); e = new_unary_expr ('.', e); e->e.expr.type = get_type (e->e.expr.e1)->t.fldptr.type; @@ -2392,7 +2393,7 @@ array_expr (expr_t *array, expr_t *index) if (index->type == ex_error) return index; - if (array_type->type != ev_pointer && !is_array (array_type)) + if (array_type->type != ev_ptr && !is_array (array_type)) return error (array, "not an array"); if (!is_integral (index_type)) return error (index, "invalid array index type"); @@ -2436,7 +2437,7 @@ pointer_expr (expr_t *pointer) if (pointer->type == ex_error) return pointer; - if (pointer_type->type != ev_pointer) + if (pointer_type->type != ev_ptr) return error (pointer, "not a pointer"); return array_expr (pointer, new_int_expr (0)); } @@ -2889,7 +2890,9 @@ sizeof_expr (expr_t *expr, struct type_s *type) internal_error (0, 0); if (!type) type = get_type (expr); - expr = new_int_expr (type_size (type)); + if (type) { + expr = new_int_expr (type_size (type)); + } return expr; } diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 885f87ef1..7610b4542 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -533,7 +533,7 @@ static expr_type_t *string_x[ev_type_count] = { 0, // ev_entity 0, // ev_field 0, // ev_func - 0, // ev_pointer + 0, // ev_ptr 0, // ev_quat 0, // ev_int 0, // ev_uint @@ -549,7 +549,7 @@ static expr_type_t *float_x[ev_type_count] = { 0, // ev_entity 0, // ev_field 0, // ev_func - 0, // ev_pointer + 0, // ev_ptr float_quat, float_int, float_uint, @@ -565,7 +565,7 @@ static expr_type_t *vector_x[ev_type_count] = { 0, // ev_entity 0, // ev_field 0, // ev_func - 0, // ev_pointer + 0, // ev_ptr 0, // ev_quaternion vector_int, vector_uint, @@ -581,7 +581,7 @@ static expr_type_t *entity_x[ev_type_count] = { entity_entity, // ev_entity 0, // ev_field 0, // ev_func - 0, // ev_pointer + 0, // ev_ptr 0, // ev_quaternion 0, // ev_int 0, // ev_uint @@ -597,7 +597,7 @@ static expr_type_t *field_x[ev_type_count] = { 0, // ev_entity field_field, // ev_field 0, // ev_func - 0, // ev_pointer + 0, // ev_ptr 0, // ev_quaternion 0, // ev_int 0, // ev_uint @@ -613,7 +613,7 @@ static expr_type_t *func_x[ev_type_count] = { 0, // ev_entity 0, // ev_field func_func, // ev_func - 0, // ev_pointer + 0, // ev_ptr 0, // ev_quaternion 0, // ev_int 0, // ev_uint @@ -645,7 +645,7 @@ static expr_type_t *quat_x[ev_type_count] = { 0, // ev_entity 0, // ev_field 0, // ev_func - 0, // ev_pointer + 0, // ev_ptr quat_quat, quat_int, quat_uint, @@ -709,7 +709,7 @@ static expr_type_t *double_x[ev_type_count] = { 0, // ev_entity 0, // ev_field 0, // ev_func - 0, // ev_pointer + 0, // ev_ptr double_quat, double_int, double_uint, diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index df8e25180..52b4de683 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -132,7 +132,7 @@ test_expr (expr_t *e) return new_alias_expr (type_default, e); case ev_func: return new_alias_expr (type_default, e); - case ev_pointer: + case ev_ptr: return new_alias_expr (type_default, e); case ev_quat: new = new_quaternion_expr (zero); diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 37d0c1814..8edc44ad1 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1127,7 +1127,7 @@ flow_analyze_pointer_operand (operand_t *ptrop, set_t *def) { operand_t *op = 0; - if (ptrop->op_type == op_value && ptrop->value->lltype == ev_pointer) { + if (ptrop->op_type == op_value && ptrop->value->lltype == ev_ptr) { ex_pointer_t *ptr = &ptrop->value->v.pointer; if (ptrop->value->v.pointer.def) { def_t *alias; diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index d806e6c9b..8d1f5cacf 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -149,7 +149,7 @@ qfo_encode_basic (type_t *type, defspace_t *space) if (type->type == ev_func) return qfo_encode_func (type, space); - else if (type->type == ev_pointer || type->type == ev_field) + else if (type->type == ev_ptr || type->type == ev_field) return qfo_encode_fldptr (type, space); def = qfo_new_encoding (type, sizeof (enc->type), space); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 0d52f7c4e..a0aa7997f 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -140,7 +140,7 @@ operand_string (operand_t *op) op->value->v.quaternion_val[1], op->value->v.quaternion_val[2], op->value->v.quaternion_val[3]); - case ev_pointer: + case ev_ptr: if (op->value->v.pointer.def) { return va (0, "ptr %s+%d", op->value->v.pointer.def->name, @@ -227,7 +227,7 @@ _print_operand (operand_t *op) printf (" %g", op->value->v.quaternion_val[2]); printf (" %g'", op->value->v.quaternion_val[3]); break; - case ev_pointer: + case ev_ptr: printf ("(%s)[%d]", pr_type_name[op->value->v.pointer.type->type], op->value->v.pointer.val); @@ -761,7 +761,7 @@ operand_address (operand_t *reference, expr_t *e) static __attribute__((pure)) int is_const_ptr (expr_t *e) { - if ((e->type != ex_value || e->e.value->lltype != ev_pointer) + if ((e->type != ex_value || e->e.value->lltype != ev_ptr) || !(POINTER_VAL (e->e.value->v.pointer) >= 0 && POINTER_VAL (e->e.value->v.pointer) < 65536)) { return 0; @@ -1170,7 +1170,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) s->opc = *op; sblock_add_statement (sblock, s); } - } else if (e->type == ex_value && e->e.value->lltype == ev_pointer) { + } else if (e->type == ex_value && e->e.value->lltype == ev_ptr) { ex_pointer_t *ptr = &e->e.value->v.pointer; *op = def_operand (alias_def (ptr->def, ptr->type, ptr->val), ptr->type, e); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 81583de9c..de6709c9d 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -72,7 +72,7 @@ type_t type_field = {ev_field, "field", 1, ty_basic, {{&type_void}} }; // type_function is a void() function used for state defs type_t type_function = { ev_func, "function", 1, ty_basic, {{&type_void}} }; -type_t type_pointer = { ev_pointer, "pointer", 1, ty_basic, +type_t type_pointer = { ev_ptr, "pointer", 1, ty_basic, {{&type_void}} }; type_t type_quaternion = { ev_quat, "quaternion", 4 }; type_t type_int = { ev_int, "int", 1 }; @@ -90,7 +90,7 @@ type_t type_zero = { ev_invalid, 0, 0, ty_struct }; type_t type_type_encodings = { ev_invalid, "@type_encodings", 0, ty_struct }; type_t type_xdef = { ev_invalid, "@xdef", 0, ty_struct }; -type_t type_xdef_pointer = { ev_pointer, 0, 1, ty_basic, {{&type_xdef}} }; +type_t type_xdef_pointer = { ev_ptr, 0, 1, ty_basic, {{&type_xdef}} }; type_t type_xdefs = { ev_invalid, "@xdefs", 0, ty_struct }; type_t type_floatfield = { ev_field, ".float", 1, ty_basic, @@ -194,7 +194,7 @@ free_type (type_t *type) case ev_double: break; case ev_field: - case ev_pointer: + case ev_ptr: free_type (type->t.fldptr.type); break; case ev_func: @@ -236,7 +236,7 @@ copy_chain (type_t *type, type_t *append) case ev_double: internal_error (0, "copy basic type"); case ev_field: - case ev_pointer: + case ev_ptr: n = &(*n)->t.fldptr.type; type = type->t.fldptr.type; break; @@ -289,7 +289,7 @@ append_type (type_t *type, type_t *new) case ev_double: internal_error (0, "append to basic type"); case ev_field: - case ev_pointer: + case ev_ptr: t = &(*t)->t.fldptr.type; type->alignment = 1; break; @@ -335,7 +335,7 @@ types_same (type_t *a, type_t *b) case ty_basic: switch (a->type) { case ev_field: - case ev_pointer: + case ev_ptr: if (a->t.fldptr.type != b->t.fldptr.type) return 0; case ev_func: @@ -401,7 +401,7 @@ find_type (type_t *type) case ty_basic: switch (type->type) { case ev_field: - case ev_pointer: + case ev_ptr: type->t.fldptr.type = find_type (type->t.fldptr.type); break; case ev_func: @@ -475,7 +475,7 @@ pointer_type (type_t *aux) memset (&_new, 0, sizeof (_new)); else new = new_type (); - new->type = ev_pointer; + new->type = ev_ptr; new->alignment = 1; if (aux) { new = find_type (append_type (new, aux)); @@ -639,7 +639,7 @@ print_type_str (dstring_t *str, const type_t *type) dasprintf (str, ")"); } return; - case ev_pointer: + case ev_ptr: if (is_id (type)) { dasprintf (str, "id"); if (type->t.fldptr.type->protos) @@ -802,7 +802,7 @@ encode_type (dstring_t *encoding, const type_t *type) encode_type (encoding, type->t.func.type); dasprintf (encoding, "%s)", encode_params (type)); return; - case ev_pointer: + case ev_ptr: if (is_id(type)) { dasprintf (encoding, "@"); return; @@ -962,7 +962,7 @@ int is_pointer (const type_t *type) { type = unalias_type (type); - if (type->type == ev_pointer) + if (type->type == ev_ptr) return 1; return 0; } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 786a3d2fb..73b3b47ab 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -262,7 +262,7 @@ new_nil_val (type_t *type) if (val.lltype == ev_void) { val.lltype = type_nil->type; } - if (val.lltype == ev_pointer || val.lltype == ev_field ) + if (val.lltype == ev_ptr || val.lltype == ev_field ) val.v.pointer.type = type->t.fldptr.type; if (val.lltype == ev_func) val.v.func_val.type = type; @@ -507,7 +507,7 @@ emit_value (ex_value_t *value, def_t *def) tab = func_imm_defs; type = &type_function; break; - case ev_pointer: + case ev_ptr: tab = pointer_imm_defs; type = &type_pointer; break; @@ -604,7 +604,7 @@ emit_value (ex_value_t *value, def_t *def) if (val.v.pointer.def) reloc_def_field_ofs (val.v.pointer.def, cn); break; - case ev_pointer: + case ev_ptr: if (val.v.pointer.def) { EMIT_DEF_OFS (pr.near_data, D_INT (cn), val.v.pointer.def); diff --git a/tools/qfcc/test/typedef.r b/tools/qfcc/test/typedef.r index 3755f63eb..61df8f9b6 100644 --- a/tools/qfcc/test/typedef.r +++ b/tools/qfcc/test/typedef.r @@ -24,7 +24,7 @@ next_type (qfot_type_t *type) int check_alias (string name, qfot_type_t *alias) { - if (alias.meta != ty_basic || alias.type != ev_pointer + if (alias.meta != ty_basic || alias.type != ev_ptr || alias.fldptr.aux_type.meta != ty_basic || alias.fldptr.aux_type.type != ev_int) { printf ("%s is not a *int alias\n", name); From e9e54d08c0383f3fa4e0d78e38c442bb10be9ec2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 15:32:43 +0900 Subject: [PATCH 2213/3664] [gamecode] Rename func_t to pr_func_t Even more consistency. --- doc/progs/vm-exec.c | 2 +- include/QF/progs.h | 16 ++++++------ include/QF/progs/pr_comp.h | 4 +-- include/QF/progs/pr_obj.h | 2 +- include/QF/ruamoko.h | 4 +-- libs/console/bi_inputline.c | 2 +- libs/console/menu.c | 34 +++++++++++++------------- libs/gamecode/pr_debug.c | 20 +++++++-------- libs/gamecode/pr_exec.c | 6 ++--- libs/gamecode/test/main.c | 2 +- libs/gib/bi_gib.c | 6 ++--- libs/ruamoko/rua_cmd.c | 4 +-- libs/ruamoko/rua_hash.c | 8 +++--- libs/ruamoko/rua_input.c | 22 ++++++++--------- libs/ruamoko/rua_obj.c | 30 +++++++++++------------ libs/ruamoko/rua_stdlib.c | 8 +++--- nq/include/sv_progs.h | 28 ++++++++++----------- nq/source/sv_progs.c | 4 +-- qw/include/sv_progs.h | 42 ++++++++++++++++---------------- qw/source/sv_pr_cpqw.c | 6 ++--- qw/source/sv_pr_qwe.c | 12 ++++----- qw/source/sv_progs.c | 4 +-- qw/source/sv_user.c | 2 +- ruamoko/qwaq/builtins/debug.c | 6 ++--- ruamoko/qwaq/builtins/graphics.c | 2 +- ruamoko/qwaq/qwaq.h | 2 +- tools/qfcc/include/obj_file.h | 2 +- tools/qfcc/source/dump_globals.c | 2 +- tools/qfcc/test/test-harness.c | 2 +- 29 files changed, 142 insertions(+), 142 deletions(-) diff --git a/doc/progs/vm-exec.c b/doc/progs/vm-exec.c index 1f9ae4b8e..b250848cd 100644 --- a/doc/progs/vm-exec.c +++ b/doc/progs/vm-exec.c @@ -5,7 +5,7 @@ call_progs_main (progs_t *pr, int argc, const char **argv) { int i; dfunction_t *dfunc; - func_t progs_main = 0; + pr_func_t progs_main = 0; string_t *pr_argv; if ((dfunc = PR_FindFunction (pr, "main"))) { diff --git a/include/QF/progs.h b/include/QF/progs.h index f9ae57c63..d2d32cf51 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -167,7 +167,7 @@ void PR_PopFrame (progs_t *pr); \param pr pointer to ::progs_t VM struct \param fnum number of the function to call */ -void PR_ExecuteProgram (progs_t *pr, func_t fnum); +void PR_ExecuteProgram (progs_t *pr, pr_func_t fnum); /** Setup to call a function. If \p fnum is a builtin rather than a progs function, then the function is called immediately. When called from a @@ -180,7 +180,7 @@ void PR_ExecuteProgram (progs_t *pr, func_t fnum); \return true if \p fnum was a progs function, false if \p fnum was a builtin */ -int PR_CallFunction (progs_t *pr, func_t fnum, pr_type_t *return_ptr); +int PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr); ///@} @@ -482,7 +482,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void() \param p pointer to ::progs_t VM struct \param o offset into global data space - \return func_t lvalue + \return pr_func_t lvalue \hideinitializer */ @@ -698,7 +698,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void() \param p pointer to ::progs_t VM struct \param n parameter number (0-7) - \return func_t lvalue + \return pr_func_t lvalue \hideinitializer */ @@ -902,12 +902,12 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_STRING(p) R_var (p, string) -/** Access the VM function return value as a ::func_t (a VM function reference) +/** Access the VM function return value as a ::pr_func_t (a VM function reference) \par QC type: \c void() \param p pointer to ::progs_t VM struct - \return ::func_t lvalue + \return ::pr_func_t lvalue \hideinitializer */ @@ -1103,7 +1103,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \c void() \param e pointer to the entity \param o field offset into entity data space - \return func_t lvalue + \return pr_func_t lvalue \hideinitializer */ @@ -1911,7 +1911,7 @@ struct progs_s { pr_type_t *pr_edict_area; int pr_edict_size; ///< # of pr_type_t slots pr_uint_t pr_edict_area_size; ///< for bounds checking, starts at 0 - func_t edict_parse; + pr_func_t edict_parse; ///@} /// \name execution state diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 9dbaea8db..fa7348161 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -29,9 +29,9 @@ typedef int16_t pr_short_t; typedef uint16_t pr_ushort_t; typedef int32_t pr_int_t; typedef uint32_t pr_uint_t; +typedef uint32_t pr_func_t; typedef int64_t pr_long_t; typedef uint64_t pr_ulong_t; -typedef pr_uint_t func_t; typedef pr_int_t pr_string_t; typedef pr_uint_t pr_ptr_t; @@ -520,7 +520,7 @@ typedef struct dfunction_s { typedef union pr_type_u { float float_var; pr_string_t string_var; - func_t func_var; + pr_func_t func_var; pr_uint_t entity_var; float vector_var; // really [3], but this structure must be 32 bits float quat_var; // really [4], but this structure must be 32 bits diff --git a/include/QF/progs/pr_obj.h b/include/QF/progs/pr_obj.h index 00f493469..2841f6064 100644 --- a/include/QF/progs/pr_obj.h +++ b/include/QF/progs/pr_obj.h @@ -129,7 +129,7 @@ typedef struct pr_method_list_s { struct pr_method_s { pr_ptr_t method_name; // pr_sel_t pr_string_t method_types; - func_t method_imp; // typedef id (id, SEL, ...) IMP + pr_func_t method_imp; // typedef id (id, SEL, ...) IMP } method_list[1]; } pr_method_list_t; typedef struct pr_method_s pr_method_t; diff --git a/include/QF/ruamoko.h b/include/QF/ruamoko.h index 8ee071632..71c2fe6ee 100644 --- a/include/QF/ruamoko.h +++ b/include/QF/ruamoko.h @@ -38,8 +38,8 @@ struct cbuf_s; void RUA_Init (struct progs_s *pr, int secure); void RUA_Cbuf_SetCbuf (struct progs_s *pr, struct cbuf_s *cbuf); -func_t RUA_Obj_msg_lookup (struct progs_s *pr, pr_ptr_t _self, - pr_ptr_t __cmd); +pr_func_t RUA_Obj_msg_lookup (struct progs_s *pr, pr_ptr_t _self, + pr_ptr_t __cmd); void RUA_Game_Init (struct progs_s *pr, int secure); diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index 1c63a69a7..a2de6285c 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -49,7 +49,7 @@ typedef struct il_data_s { struct il_data_s **prev; inputline_t *line; progs_t *pr; - func_t enter; // enter key callback + pr_func_t enter; // enter key callback pr_ptr_t data[2]; // allow two data params for the callback int method; // true if method rather than function } il_data_t; diff --git a/libs/console/menu.c b/libs/console/menu.c index a98c2d71a..80bcc772e 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -67,12 +67,12 @@ typedef struct menu_item_s { int max_items; int cur_item; int x, y; - func_t func; - func_t cursor; - func_t keyevent; - func_t draw; - func_t enter_hook; - func_t leave_hook; + pr_func_t func; + pr_func_t cursor; + pr_func_t keyevent; + pr_func_t draw; + pr_func_t enter_hook; + pr_func_t leave_hook; unsigned fadescreen:1; unsigned allkeys:1; const char *text; @@ -85,16 +85,16 @@ static progs_t menu_pr_state; static menu_item_t *menu; //static keydest_t menu_keydest; static hashtab_t *menu_hash; -static func_t menu_init; -static func_t menu_quit; -static func_t menu_draw_hud; -static func_t menu_pre; -static func_t menu_post; +static pr_func_t menu_init; +static pr_func_t menu_quit; +static pr_func_t menu_draw_hud; +static pr_func_t menu_pre; +static pr_func_t menu_post; static const char *top_menu; typedef struct menu_func_s { const char *name; - func_t *func; + pr_func_t *func; } menu_func_t; static menu_func_t menu_functions[] = { @@ -129,7 +129,7 @@ menu_resolve_globals (progs_t *pr) sym = menu_functions[i].name; if (!(f = PR_FindFunction (pr, sym))) goto error; - *menu_functions[i].func = (func_t) (f - menu_pr_state.pr_functions); + *menu_functions[i].func = (pr_func_t) (f - menu_pr_state.pr_functions); } if (!(def = PR_FindGlobal (pr, sym = "time"))) @@ -315,7 +315,7 @@ bi_Menu_Item (progs_t *pr) int x = P_INT (pr, 0); int y = P_INT (pr, 1); const char *text = P_GSTRING (pr, 2); - func_t func = P_FUNCTION (pr, 3); + pr_func_t func = P_FUNCTION (pr, 3); int allkeys = P_INT (pr, 4); menu_item_t *mi = calloc (sizeof (menu_item_t), 1); @@ -331,7 +331,7 @@ bi_Menu_Item (progs_t *pr) static void bi_Menu_Cursor (progs_t *pr) { - func_t func = P_FUNCTION (pr, 0); + pr_func_t func = P_FUNCTION (pr, 0); menu->cursor = func; } @@ -339,7 +339,7 @@ bi_Menu_Cursor (progs_t *pr) static void bi_Menu_KeyEvent (progs_t *pr) { - func_t func = P_FUNCTION (pr, 0); + pr_func_t func = P_FUNCTION (pr, 0); menu->keyevent = func; } @@ -385,7 +385,7 @@ bi_Menu_SelectMenu (progs_t *pr) static void bi_Menu_SetQuit (progs_t *pr) { - func_t func = P_FUNCTION (pr, 0); + pr_func_t func = P_FUNCTION (pr, 0); menu_quit = func; } diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 16d584e88..f06fdf39f 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -95,7 +95,7 @@ typedef struct prdeb_resources_s { pr_debug_header_t *debug; pr_auxfunction_t *auxfunctions; pr_auxfunction_t **auxfunction_map; - func_t *sorted_functions; + pr_func_t *sorted_functions; pr_lineno_t *linenos; pr_def_t *local_defs; pr_def_t *type_encodings_def; @@ -502,8 +502,8 @@ func_compare_sort (const void *_fa, const void *_fb, void *_res) { prdeb_resources_t *res = _res; progs_t *pr = res->pr; - func_t fa = *(const func_t *)_fa; - func_t fb = *(const func_t *)_fb; + pr_func_t fa = *(const pr_func_t *)_fa; + pr_func_t fb = *(const pr_func_t *)_fb; const char *fa_file = PR_GetString (pr, pr->pr_functions[fa].file); const char *fb_file = PR_GetString (pr, pr->pr_functions[fb].file); int cmp = strcmp (fa_file, fb_file); @@ -523,7 +523,7 @@ func_compare_search (const void *_key, const void *_f, void *_res) prdeb_resources_t *res = _res; progs_t *pr = res->pr; const func_key_t *key = _key; - func_t f = *(const func_t *)_f; + pr_func_t f = *(const pr_func_t *)_f; const char *f_file = PR_GetString (pr, pr->pr_functions[f].file); int cmp = strcmp (key->file, f_file); if (cmp) { @@ -548,7 +548,7 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) size_t size; size = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); res->auxfunction_map = pr->allocate_progs_mem (pr, size); - size = pr->progs->numfunctions * sizeof (func_t); + size = pr->progs->numfunctions * sizeof (pr_func_t); res->sorted_functions = pr->allocate_progs_mem (pr, size); for (pr_uint_t i = 0; i < pr->progs->numfunctions; i++) { @@ -572,8 +572,8 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) res->auxfunction_map[res->auxfunctions[i].function] = &res->auxfunctions[i]; } - qsort_r (res->sorted_functions, pr->progs->numfunctions, sizeof (func_t), - func_compare_sort, res); + qsort_r (res->sorted_functions, pr->progs->numfunctions, + sizeof (pr_func_t), func_compare_sort, res); for (pr_uint_t i = 0; i < debug->num_locals; i++) { if (type_encodings) { @@ -837,8 +837,8 @@ PR_FindSourceLineAddr (progs_t *pr, const char *file, pr_uint_t line) { prdeb_resources_t *res = pr->pr_debug_resources; func_key_t key = { file, line }; - func_t *f = fbsearch_r (&key, res->sorted_functions, - pr->progs->numfunctions, sizeof (func_t), + pr_func_t *f = fbsearch_r (&key, res->sorted_functions, + pr->progs->numfunctions, sizeof (pr_func_t), func_compare_search, res); if (!f) { return 0; @@ -1591,7 +1591,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) unsigned parm_ind = 0; pr_uint_t opval; qfot_type_t *optype = &res->void_type; - func_t func; + pr_func_t func; if (mode == 'P') { opchar = fmt[3]; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index d0f94d8fb..3b5b8c6f3 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -421,7 +421,7 @@ error_handler (void *data) } VISIBLE int -PR_CallFunction (progs_t *pr, func_t fnum, pr_type_t *return_ptr) +PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr) { bfunction_t *f; @@ -2766,7 +2766,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) pr_type_t *stk; pr_type_t *mm; - func_t function; + pr_func_t function; pr_opcode_e st_op = st->op & OP_MASK; switch (st_op) { // 0 0000 @@ -3461,7 +3461,7 @@ exit_program: The interpretation main loop */ VISIBLE void -PR_ExecuteProgram (progs_t *pr, func_t fnum) +PR_ExecuteProgram (progs_t *pr, pr_func_t fnum) { Sys_PushSignalHook (signal_hook, pr); Sys_PushErrorHandler (error_handler, pr); diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index c9c34be53..9f988fd50 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -37,7 +37,7 @@ test_debug_handler (prdebug_t event, void *param, void *data) longjmp (jump_buffer, 1); case prd_subenter: if (verbose > 0) { - printf ("debug: subenter %d\n", *(func_t *) param); + printf ("debug: subenter %d\n", *(pr_func_t *) param); } case prd_subexit: break; diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index 726e18d8b..f2f9bc671 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -48,8 +48,8 @@ typedef struct bi_gib_builtin_s { struct bi_gib_builtin_s *next; gib_builtin_t *builtin; - progs_t *pr; - func_t func; + progs_t *pr; + pr_func_t func; } bi_gib_builtin_t; typedef struct bi_gib_resources_s { @@ -117,7 +117,7 @@ bi_GIB_Builtin_Add (progs_t *pr) bi_gib_resources_t *res = PR_Resources_Find (pr, "GIB"); bi_gib_builtin_t *builtin; const char *name = P_GSTRING (pr, 0); - func_t func = P_FUNCTION (pr, 1); + pr_func_t func = P_FUNCTION (pr, 1); if (GIB_Builtin_Exists (name)) { R_INT (pr) = 0; diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index 8efcfb2a5..44006b815 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -50,7 +50,7 @@ typedef struct bi_cmd_s { struct bi_cmd_s *next; char *name; progs_t *pr; - func_t func; + pr_func_t func; } bi_cmd_t; typedef struct { @@ -90,7 +90,7 @@ bi_Cmd_AddCommand (progs_t *pr) cmd_resources_t *res = PR_Resources_Find (pr, "Cmd"); bi_cmd_t *cmd = malloc (sizeof (bi_cmd_t)); char *name = strdup (P_GSTRING (pr, 0)); - func_t func = P_FUNCTION (pr, 1); + pr_func_t func = P_FUNCTION (pr, 1); if (!cmd || !name || !Cmd_AddCommand (name, bi_cmd_f, "CSQC command")) { if (name) diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 27a40d3d5..3e9336398 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -49,10 +49,10 @@ typedef struct bi_hashtab_s { struct bi_hashtab_s **prev; progs_t *pr; hashtab_t *tab; - func_t gk; - func_t gh; - func_t cmp; - func_t f; + pr_func_t gk; + pr_func_t gh; + pr_func_t cmp; + pr_func_t f; pr_ptr_t ud; } bi_hashtab_t; diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 8fefa5fa9..b838b3086 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -46,7 +46,7 @@ typedef struct rua_in_cookie_s { size_t users; progs_t *pr; - func_t func; + pr_func_t func; pr_ptr_t data; } rua_in_cookie_t; @@ -193,7 +193,7 @@ bi_IN_GetButtonInfo (progs_t *pr) } static rua_in_cookie_t * -make_cookie (progs_t *pr, func_t func, pr_ptr_t data) +make_cookie (progs_t *pr, pr_func_t func, pr_ptr_t data) { input_resources_t *res = PR_Resources_Find (pr, "input"); rua_in_cookie_t search = { @@ -212,7 +212,7 @@ make_cookie (progs_t *pr, func_t func, pr_ptr_t data) } static rua_in_cookie_t * -find_cookie (progs_t *pr, func_t func, pr_ptr_t data) +find_cookie (progs_t *pr, pr_func_t func, pr_ptr_t data) { input_resources_t *res = PR_Resources_Find (pr, "input"); rua_in_cookie_t search = { @@ -236,8 +236,8 @@ static void rua_add_axis_listener (progs_t *pr, axis_listener_t listener) { in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); - func_t func = P_FUNCTION (pr, 1); - func_t data = P_POINTER (pr, 2); + pr_func_t func = P_FUNCTION (pr, 1); + pr_func_t data = P_POINTER (pr, 2); rua_in_cookie_t *cookie = make_cookie (pr, func, data); IN_AxisAddListener (axis, listener, cookie); } @@ -246,8 +246,8 @@ static void rua_remove_axis_listener (progs_t *pr, axis_listener_t listener) { in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); - func_t func = P_FUNCTION (pr, 1); - func_t data = P_POINTER (pr, 2); + pr_func_t func = P_FUNCTION (pr, 1); + pr_func_t data = P_POINTER (pr, 2); rua_in_cookie_t *cookie = find_cookie (pr, func, data); if (cookie) { IN_AxisRemoveListener (axis, listener, cookie); @@ -259,8 +259,8 @@ static void rua_add_button_listener (progs_t *pr, button_listener_t listener) { in_button_t *button = &P_STRUCT (pr, in_button_t, 0); - func_t func = P_FUNCTION (pr, 1); - func_t data = P_POINTER (pr, 2); + pr_func_t func = P_FUNCTION (pr, 1); + pr_func_t data = P_POINTER (pr, 2); rua_in_cookie_t *cookie = make_cookie (pr, func, data); IN_ButtonAddListener (button, listener, cookie); } @@ -269,8 +269,8 @@ static void rua_remove_button_listener (progs_t *pr, button_listener_t listener) { in_button_t *button = &P_STRUCT (pr, in_button_t, 0); - func_t func = P_FUNCTION (pr, 1); - func_t data = P_POINTER (pr, 2); + pr_func_t func = P_FUNCTION (pr, 1); + pr_func_t data = P_POINTER (pr, 2); rua_in_cookie_t *cookie = find_cookie (pr, func, data); if (cookie) { IN_ButtonRemoveListener (button, listener, cookie); diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 66994f65c..092562d50 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -68,7 +68,7 @@ typedef struct dtable_s { struct dtable_s *next; struct dtable_s **prev; size_t size; - func_t *imp; + pr_func_t *imp; } dtable_t; typedef struct probj_resources_s { @@ -79,7 +79,7 @@ typedef struct probj_resources_s { pr_string_t *selector_names; PR_RESMAP (dtable_t) dtables; dtable_t *dtable_list; - func_t obj_forward; + pr_func_t obj_forward; pr_sel_t *forward_selector; dstring_t *msg; hashtab_t *selector_hash; @@ -936,7 +936,7 @@ obj_install_dispatch_table_for_class (probj_t *probj, pr_class_t *class) dtable = dtable_new (probj); class->dtable = dtable_index (probj, dtable); dtable->size = probj->selector_index + 1; - dtable->imp = calloc (dtable->size, sizeof (func_t)); + dtable->imp = calloc (dtable->size, sizeof (pr_func_t)); if (super) { dtable_t *super_dtable = get_dtable (probj, __FUNCTION__, super->dtable); @@ -957,10 +957,10 @@ obj_check_dtable_installed (probj_t *probj, pr_class_t *class) return get_dtable (probj, __FUNCTION__, class->dtable); } -static func_t +static pr_func_t get_imp (probj_t *probj, pr_class_t *class, pr_sel_t *sel) { - func_t imp = 0; + pr_func_t imp = 0; if (class->dtable) { dtable_t *dtable = get_dtable (probj, __FUNCTION__, class->dtable); @@ -985,7 +985,7 @@ obj_reponds_to (probj_t *probj, pr_id_t *obj, pr_sel_t *sel) progs_t *pr = probj->pr; pr_class_t *class; dtable_t *dtable; - func_t imp = 0; + pr_func_t imp = 0; class = &G_STRUCT (pr, pr_class_t, obj->class_pointer); dtable = obj_check_dtable_installed (probj, class); @@ -996,7 +996,7 @@ obj_reponds_to (probj_t *probj, pr_id_t *obj, pr_sel_t *sel) return imp != 0; } -static func_t +static pr_func_t obj_msg_lookup (probj_t *probj, pr_id_t *receiver, pr_sel_t *op) { progs_t *pr = probj->pr; @@ -1015,7 +1015,7 @@ obj_msg_lookup (probj_t *probj, pr_id_t *receiver, pr_sel_t *op) return get_imp (probj, class, op); } -static func_t +static pr_func_t obj_msg_lookup_super (probj_t *probj, pr_super_t *super, pr_sel_t *op) { progs_t *pr = probj->pr; @@ -1260,7 +1260,7 @@ rua___obj_forward (progs_t *pr) pr_sel_t *fwd_sel = probj->forward_selector; pr_sel_t *err_sel; pr_class_t *class =&G_STRUCT (pr, pr_class_t, obj->class_pointer); - func_t imp; + pr_func_t imp; if (!fwd_sel) { //FIXME sel_register_typed_name is really not the way to go about @@ -1372,7 +1372,7 @@ static void rua_obj_set_error_handler (progs_t *pr) { //probj_t *probj = pr->pr_objective_resources; - //func_t func = P_INT (pr, 0); + //pr_func_t func = P_INT (pr, 0); //arglist //XXX PR_RunError (pr, "%s, not implemented", __FUNCTION__); @@ -1406,7 +1406,7 @@ rua_obj_msg_sendv (progs_t *pr) pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0); pr_ptr_t sel = P_POINTER (pr, 1); pr_sel_t *op = &P_STRUCT (pr, pr_sel_t, 1); - func_t imp = obj_msg_lookup (probj, receiver, op); + pr_func_t imp = obj_msg_lookup (probj, receiver, op); __auto_type args = &P_PACKED (pr, pr_va_list_t, 2); int count = args->count; @@ -1530,7 +1530,7 @@ rua_obj_msgSend (progs_t *pr) probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &P_STRUCT (pr, pr_id_t, 0); pr_sel_t *_cmd = &P_STRUCT (pr, pr_sel_t, 1); - func_t imp; + pr_func_t imp; if (!self) { R_INT (pr) = P_INT (pr, 0); @@ -1553,7 +1553,7 @@ rua_obj_msgSend_super (progs_t *pr) probj_t *probj = pr->pr_objective_resources; pr_super_t *super = &P_STRUCT (pr, pr_super_t, 0); pr_sel_t *_cmd = &P_STRUCT (pr, pr_sel_t, 1); - func_t imp; + pr_func_t imp; imp = obj_msg_lookup_super (probj, super, _cmd); if (!imp) { @@ -2248,13 +2248,13 @@ RUA_Obj_Init (progs_t *pr, int secure) PR_AddLoadFunc (pr, rua_obj_init_runtime); } -func_t +pr_func_t RUA_Obj_msg_lookup (progs_t *pr, pr_ptr_t _self, pr_ptr_t __cmd) { probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &G_STRUCT (pr, pr_id_t, _self); pr_sel_t *_cmd = &G_STRUCT (pr, pr_sel_t, __cmd); - func_t imp; + pr_func_t imp; if (!self) return 0; diff --git a/libs/ruamoko/rua_stdlib.c b/libs/ruamoko/rua_stdlib.c index 8c375e405..2ef4d914a 100644 --- a/libs/ruamoko/rua_stdlib.c +++ b/libs/ruamoko/rua_stdlib.c @@ -56,7 +56,7 @@ typedef struct { progs_t *pr; - func_t func; + pr_func_t func; } function_t; static int @@ -87,7 +87,7 @@ bi_bsearch (progs_t *pr) const void *array = P_GPOINTER (pr, 1); size_t nmemb = P_INT (pr, 2); size_t size = P_INT (pr, 3) * sizeof (pr_int_t); - func_t cmp = P_FUNCTION (pr, 4); + pr_func_t cmp = P_FUNCTION (pr, 4); void *p = 0; if (!cmp) { @@ -106,7 +106,7 @@ bi_fbsearch (progs_t *pr) const void *array = P_GPOINTER (pr, 1); size_t nmemb = P_INT (pr, 2); size_t size = P_INT (pr, 3) * sizeof (pr_int_t); - func_t cmp = P_FUNCTION (pr, 4); + pr_func_t cmp = P_FUNCTION (pr, 4); void *p = 0; if (!cmp) { @@ -124,7 +124,7 @@ bi_qsort (progs_t *pr) void *array = P_GPOINTER (pr, 0); size_t nmemb = P_INT (pr, 1); size_t size = P_INT (pr, 2) * sizeof (pr_int_t); - func_t cmp = P_FUNCTION (pr, 3); + pr_func_t cmp = P_FUNCTION (pr, 3); if (!cmp) { qsort (array, nmemb, size, int_compare); diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index a660b4e77..4a74bfb38 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -76,18 +76,18 @@ typedef struct { extern sv_globals_t sv_globals; typedef struct { - func_t main; - func_t StartFrame; - func_t PlayerPreThink; - func_t PlayerPostThink; - func_t ClientKill; - func_t ClientConnect; - func_t PutClientInServer; - func_t ClientDisconnect; - func_t SetNewParms; - func_t SetChangeParms; + pr_func_t main; + pr_func_t StartFrame; + pr_func_t PlayerPreThink; + pr_func_t PlayerPostThink; + pr_func_t ClientKill; + pr_func_t ClientConnect; + pr_func_t PutClientInServer; + pr_func_t ClientDisconnect; + pr_func_t SetNewParms; + pr_func_t SetChangeParms; - func_t EndFrame; + pr_func_t EndFrame; } sv_funcs_t; extern sv_funcs_t sv_funcs; @@ -115,9 +115,9 @@ typedef struct pr_int_t mins; //vec3_t pr_int_t maxs; //vec3_t pr_int_t size; //vec3_t - pr_int_t touch; //func_t - pr_int_t think; //func_t - pr_int_t blocked; //func_t + pr_int_t touch; //pr_func_t + pr_int_t think; //pr_func_t + pr_int_t blocked; //pr_func_t pr_int_t nextthink; //float pr_int_t groundentity; //int pr_int_t health; //float diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 65c7ee495..69dd7254c 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -397,13 +397,13 @@ resolve_functions (progs_t *pr, sv_def_t *def, int mode) if (mode == 2) { for (; def->name; def++) - *(func_t *) def->field = G_FUNCTION (pr, def->offset); + *(pr_func_t *) def->field = G_FUNCTION (pr, def->offset); return 1; } for (; def->name; def++) { dfunc = PR_FindFunction (pr, def->name); if (dfunc) { - *(func_t *) def->field = dfunc - pr->pr_functions; + *(pr_func_t *) def->field = dfunc - pr->pr_functions; } else if (mode) { PR_Undefined (pr, "function", def->name); ret = 0; diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index b4d931c35..c158461de 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -71,25 +71,25 @@ typedef struct { extern sv_globals_t sv_globals; typedef struct { - func_t main; - func_t StartFrame; - func_t PlayerPreThink; - func_t PlayerPostThink; - func_t ClientKill; - func_t ClientConnect; - func_t PutClientInServer; - func_t ClientDisconnect; - func_t SetNewParms; - func_t SetChangeParms; + pr_func_t main; + pr_func_t StartFrame; + pr_func_t PlayerPreThink; + pr_func_t PlayerPostThink; + pr_func_t ClientKill; + pr_func_t ClientConnect; + pr_func_t PutClientInServer; + pr_func_t ClientDisconnect; + pr_func_t SetNewParms; + pr_func_t SetChangeParms; - func_t EndFrame; - func_t SpectatorConnect; - func_t SpectatorThink; - func_t SpectatorDisconnect; - func_t UserInfoCallback; - func_t UserInfoChanged; - func_t ChatMessage; - func_t LocalinfoChanged; + pr_func_t EndFrame; + pr_func_t SpectatorConnect; + pr_func_t SpectatorThink; + pr_func_t SpectatorDisconnect; + pr_func_t UserInfoCallback; + pr_func_t UserInfoChanged; + pr_func_t ChatMessage; + pr_func_t LocalinfoChanged; } sv_funcs_t; extern sv_funcs_t sv_funcs; @@ -116,9 +116,9 @@ typedef struct pr_int_t mins; //vec3_t pr_int_t maxs; //vec3_t pr_int_t size; //vec3_t - pr_int_t touch; //func_t - pr_int_t think; //func_t - pr_int_t blocked; //func_t + pr_int_t touch; //pr_func_t + pr_int_t think; //pr_func_t + pr_int_t blocked; //pr_func_t pr_int_t nextthink; //float pr_int_t groundentity; //int pr_int_t health; //float diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index 19be9ac13..eebb91ef4 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -45,7 +45,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "world.h" static struct { - func_t ClientCommand; + pr_func_t ClientCommand; } cpqw_funcs; /* @@ -796,7 +796,7 @@ static builtin_t builtins[] = { static struct { const char *name; - func_t *field; + pr_func_t *field; } cpqw_func_list[] = { {"ClientCommand", &cpqw_funcs.ClientCommand}, {"UserInfoChanged", &sv_funcs.UserInfoChanged}, @@ -841,7 +841,7 @@ cpqw_load (progs_t *pr) *cpqw_func_list[i].field = 0; if (f) - *cpqw_func_list[i].field = (func_t) (f - pr->pr_functions); + *cpqw_func_list[i].field = (pr_func_t) (f - pr->pr_functions); } ucmd_unknown = cpqw_user_cmd; return 1; diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index c5e5fb810..6c89a820b 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -56,9 +56,9 @@ #include "qw/include/sv_recorder.h" typedef struct { - func_t timeofday; - func_t ConsoleCmd; - func_t UserCmd; + pr_func_t timeofday; + pr_func_t ConsoleCmd; + pr_func_t UserCmd; } qwe_funcs_t; static qwe_funcs_t qwe_funcs; @@ -354,7 +354,7 @@ PF_calltimeofday (progs_t *pr) P_STRING (pr, 6) = PR_SetReturnString (pr, date.str); pr->pr_argc = 7; - PR_ExecuteProgram (pr, (func_t) (f - sv_pr_state.pr_functions)); + PR_ExecuteProgram (pr, (pr_func_t) (f - sv_pr_state.pr_functions)); PR_PopFrame (&sv_pr_state); } } @@ -508,7 +508,7 @@ static builtin_t builtins[] = { static struct { const char *name; - func_t *field; + pr_func_t *field; } qwe_func_list[] = { {"timeofday", &qwe_funcs.timeofday}, {"ConsoleCmd", &qwe_funcs.ConsoleCmd}, @@ -574,7 +574,7 @@ qwe_load (progs_t *pr) *qwe_func_list[i].field = 0; if (f) - *qwe_func_list[i].field = (func_t) (f - pr->pr_functions); + *qwe_func_list[i].field = (pr_func_t) (f - pr->pr_functions); } sv_cbuf->unknown_command = qwe_console_cmd; diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 4510ee339..dee8842bd 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -430,13 +430,13 @@ resolve_functions (progs_t *pr, sv_def_t *def, int mode) if (mode == 2) { for (; def->name; def++) - *(func_t *) def->field = G_FUNCTION (pr, def->offset); + *(pr_func_t *) def->field = G_FUNCTION (pr, def->offset); return 1; } for (; def->name; def++) { dfunc = PR_FindFunction (pr, def->name); if (dfunc) { - *(func_t *) def->field = dfunc - pr->pr_functions; + *(pr_func_t *) def->field = dfunc - pr->pr_functions; } else if (mode) { PR_Undefined (pr, "function", def->name); ret = 0; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 2f37404b6..0d6ab4c3f 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -1332,7 +1332,7 @@ static void call_qc_hook (void *qc_hook) { *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, sv_player); - PR_ExecuteProgram (&sv_pr_state, (func_t) (intptr_t) qc_hook); + PR_ExecuteProgram (&sv_pr_state, (pr_func_t) (intptr_t) qc_hook); } static const char * diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 4fa0b0c98..ba43ddcb5 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -301,7 +301,7 @@ qdb_get_state (progs_t *pr) pr_string_t file = 0; unsigned line = 0; unsigned staddr = tpr->pr_xstatement; - func_t func = 0; + pr_func_t func = 0; if (tpr->pr_xfunction) { func = tpr->pr_xfunction - tpr->function_table; @@ -374,14 +374,14 @@ qdb_get_event (progs_t *pr) event->what = target->event; switch (event->what) { case prd_subenter: - event->function = *(func_t *) target->param; + event->function = *(pr_func_t *) target->param; break; case prd_runerror: case prd_error: event->message = PR_SetReturnString (pr, *(char **) target->param); break; case prd_begin: - event->function = *(func_t *) target->param; + event->function = *(pr_func_t *) target->param; break; case prd_terminate: event->exit_code = *(int *) target->param; diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 44426ae4a..847a13357 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -83,7 +83,7 @@ quit_f (void) } static progs_t *bi_rprogs; -static func_t qc2d; +static pr_func_t qc2d; static int event_handler_id; static void diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index 4bdc09435..cb16c9af9 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -19,7 +19,7 @@ typedef struct qwaq_thread_s { int rua_security; struct memhunk_s *hunk; struct hashlink_s *hashlink_freelist; - func_t main_func; + pr_func_t main_func; void *data; } qwaq_thread_t; diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index aecd3801a..a4861d29a 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -420,7 +420,7 @@ enum { \param q pointer to ::qfo_t struct \param s space index \param o offset into object file data space - \return func_t lvalue + \return pr_func_t lvalue \hideinitializer */ diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 5bff7e2a0..2f39850e1 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -118,7 +118,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) break; case ev_func: { - func_t func = G_FUNCTION (pr, offset); + pr_func_t func = G_FUNCTION (pr, offset); int start; if (func < pr->progs->numfunctions) { start = pr->pr_functions[func].first_statement; diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index b73b0916f..c0aa96b10 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -259,7 +259,7 @@ int main (int argc, char **argv) { dfunction_t *dfunc; - func_t main_func = 0; + pr_func_t main_func = 0; const char *name = "progs.dat"; pr_string_t *pr_argv; int pr_argc = 1, i; From 0748581cd6b95c89aba8baf413fde5cd7e5e61da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 15:44:49 +0900 Subject: [PATCH 2214/3664] [gamecode] Tidy up progs type definitions A bit of whitespace and put them in order of the types enum --- include/QF/progs/pr_comp.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index fa7348161..aff321ffc 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -23,17 +23,17 @@ #include "QF/qtypes.h" -typedef double pr_double_t; -typedef float pr_float_t; -typedef int16_t pr_short_t; -typedef uint16_t pr_ushort_t; -typedef int32_t pr_int_t; -typedef uint32_t pr_uint_t; -typedef uint32_t pr_func_t; -typedef int64_t pr_long_t; -typedef uint64_t pr_ulong_t; -typedef pr_int_t pr_string_t; -typedef pr_uint_t pr_ptr_t; +typedef int32_t pr_string_t; +typedef float pr_float_t; +typedef uint32_t pr_func_t; +typedef uint32_t pr_ptr_t; +typedef int32_t pr_int_t; +typedef uint32_t pr_uint_t; +typedef int16_t pr_short_t; +typedef double pr_double_t; +typedef int64_t pr_long_t; +typedef uint64_t pr_ulong_t; +typedef uint16_t pr_ushort_t; #define PR_VEC_TYPE(t,n,s) \ typedef t n __attribute__ ((vector_size (s*sizeof (t)))) From cd30408675af68ce06516b8a4398287694e14a67 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 15:48:43 +0900 Subject: [PATCH 2215/3664] [gamecode] Rename ev_quat to ev_quaternion I much prefer the full name, though the short version is easier to type. --- include/QF/progs/pr_type_names.h | 2 +- libs/gamecode/pr_debug.c | 2 +- libs/gamecode/pr_exec.c | 24 +++++++-------- libs/gamecode/pr_parse.c | 2 +- libs/gamecode/pr_v6p_opcode.c | 52 ++++++++++++++++---------------- nq/source/sv_progs.c | 2 +- qw/source/sv_progs.c | 2 +- tools/qfcc/source/dot_expr.c | 2 +- tools/qfcc/source/dump_globals.c | 2 +- tools/qfcc/source/expr.c | 18 +++++------ tools/qfcc/source/expr_binary.c | 4 +-- tools/qfcc/source/expr_bool.c | 2 +- tools/qfcc/source/idstuff.c | 2 +- tools/qfcc/source/statements.c | 4 +-- tools/qfcc/source/type.c | 18 +++++------ tools/qfcc/source/value.c | 2 +- 16 files changed, 70 insertions(+), 70 deletions(-) diff --git a/include/QF/progs/pr_type_names.h b/include/QF/progs/pr_type_names.h index 712a3c74c..79dfaa4ff 100644 --- a/include/QF/progs/pr_type_names.h +++ b/include/QF/progs/pr_type_names.h @@ -38,7 +38,7 @@ EV_TYPE(entity) EV_TYPE(field) EV_TYPE(func) EV_TYPE(ptr) // end of v6 types -EV_TYPE(quat) +EV_TYPE(quaternion) EV_TYPE(int) EV_TYPE(uint) EV_TYPE(short) // value is embedded in the opcode diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index f06fdf39f..1f7e2a651 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1053,7 +1053,7 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) case ev_ptr: raw_type_view.pointer_view (type, value, data); break; - case ev_quat: + case ev_quaternion: raw_type_view.quat_view (type, value, data); break; case ev_int: diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 3b5b8c6f3..65615b7fe 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -799,7 +799,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREP_Q_v6p: pointer = OPB(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; QuatCopy (&OPA(float), &ptr->quat_var); @@ -921,7 +921,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADB_Q_v6p: pointer = OPA(int) + OPB(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; QuatCopy (&ptr->quat_var, &OPC(float)); @@ -960,7 +960,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADBI_Q_v6p: pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; QuatCopy (&ptr->quat_var, &OPC(float)); @@ -968,7 +968,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADBI_D_v6p: pointer = OPA(int) + (short) st->b; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; OPC(double) = *(double *) ptr; @@ -1009,7 +1009,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREB_Q_v6p: pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; QuatCopy (&OPA(float), &ptr->quat_var); @@ -1017,7 +1017,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREB_D_v6p: pointer = OPB(int) + OPC(int); if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; *(double *) ptr = OPA(double); @@ -1048,7 +1048,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREBI_Q_v6p: pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; QuatCopy (&OPA(float), &ptr->quat_var); @@ -1056,7 +1056,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREBI_D_v6p: pointer = OPB(int) + (short) st->c; if (pr_boundscheck->int_val) { - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; *(double *) ptr = OPA(double); @@ -1152,7 +1152,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } QuatCopy (&ptr->quat_var, &stk->quat_var); @@ -1210,7 +1210,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } QuatCopy (&ptr->quat_var, &stk->quat_var); @@ -1308,7 +1308,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } QuatCopy (&stk->quat_var, &ptr->quat_var); @@ -1366,7 +1366,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck->int_val) { check_stack_pointer (pr, stack, 4); - PR_BoundsCheck (pr, pointer, ev_quat); + PR_BoundsCheck (pr, pointer, ev_quaternion); } QuatCopy (&stk->quat_var, &ptr->quat_var); diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 33ab39d3c..5f360c054 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -94,7 +94,7 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) case ev_vector: dsprintf (line, "%.9g %.9g %.9g", VectorExpand (&val->vector_var)); break; - case ev_quat: + case ev_quaternion: dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (&val->quat_var)); break; default: diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 934a6ed69..6b8988474 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -97,32 +97,32 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { PROG_ID_VERSION, }, [OP_MUL_Q_v6p] = {"*", "mul.q", - ev_quat, ev_quat, ev_quat, + ev_quaternion, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, [OP_MUL_FQ_v6p] = {"*", "mul.fq", - ev_float, ev_quat, ev_quat, + ev_float, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, [OP_MUL_QF_v6p] = {"*", "mul.qf", - ev_quat, ev_float, ev_quat, + ev_quaternion, ev_float, ev_quaternion, PROG_V6P_VERSION, }, [OP_MUL_DQ_v6p] = {"*", "mul.dq", - ev_double, ev_quat, ev_quat, + ev_double, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, [OP_MUL_QD_v6p] = {"*", "mul.qd", - ev_quat, ev_double, ev_quat, + ev_quaternion, ev_double, ev_quaternion, PROG_V6P_VERSION, }, [OP_MUL_QV_v6p] = {"*", "mul.qv", - ev_quat, ev_vector, ev_vector, + ev_quaternion, ev_vector, ev_vector, PROG_V6P_VERSION, }, [OP_CONJ_Q_v6p] = {"~", "conj.q", - ev_quat, ev_invalid, ev_quat, + ev_quaternion, ev_invalid, ev_quaternion, PROG_V6P_VERSION, "%Ga, %gc", }, @@ -157,7 +157,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { PROG_ID_VERSION, }, [OP_ADD_Q_v6p] = {"+", "add.q", - ev_quat, ev_quat, ev_quat, + ev_quaternion, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, [OP_ADD_S_v6p] = {"+", "add.s", @@ -178,7 +178,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { PROG_ID_VERSION, }, [OP_SUB_Q_v6p] = {"-", "sub.q", - ev_quat, ev_quat, ev_quat, + ev_quaternion, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, @@ -195,7 +195,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { PROG_ID_VERSION, }, [OP_EQ_Q_v6p] = {"==", "eq.q", - ev_quat, ev_quat, ev_int, + ev_quaternion, ev_quaternion, ev_int, PROG_V6P_VERSION, }, [OP_EQ_S_v6p] = {"==", "eq.s", @@ -224,7 +224,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { PROG_ID_VERSION, }, [OP_NE_Q_v6p] = {"!=", "ne.q", - ev_quat, ev_quat, ev_int, + ev_quaternion, ev_quaternion, ev_int, PROG_V6P_VERSION, }, [OP_NE_S_v6p] = {"!=", "ne.s", @@ -305,7 +305,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga.%Gb(%Ec), %gc", }, [OP_LOAD_Q_v6p] = {".", "load.q", - ev_entity, ev_field, ev_quat, + ev_entity, ev_field, ev_quaternion, PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, @@ -356,7 +356,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "*(%Ga + %Gb), %gc", }, [OP_LOADB_Q_v6p] = {".", "loadb.q", - ev_ptr, ev_int, ev_quat, + ev_ptr, ev_int, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, @@ -407,7 +407,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "*(%Ga + %sb), %gc", }, [OP_LOADBI_Q_v6p] = {".", "loadbi.q", - ev_ptr, ev_short, ev_quat, + ev_ptr, ev_short, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, @@ -469,7 +469,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %gc", }, [OP_ADDRESS_Q_v6p] = {"&", "address.q", - ev_quat, ev_invalid, ev_ptr, + ev_quaternion, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, @@ -562,7 +562,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %gb", }, [OP_STORE_Q_v6p] = {"=", "store.q", - ev_quat, ev_quat, ev_invalid, + ev_quaternion, ev_quaternion, ev_invalid, PROG_V6P_VERSION, "%Ga, %gb", }, @@ -613,7 +613,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, *%Gb", }, [OP_STOREP_Q_v6p] = {".=", "storep.q", - ev_quat, ev_ptr, ev_invalid, + ev_quaternion, ev_ptr, ev_invalid, PROG_V6P_VERSION, "%Ga, *%Gb", }, @@ -664,7 +664,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, *(%Gb + %Gc)", }, [OP_STOREB_Q_v6p] = {".=", "storeb.q", - ev_quat, ev_ptr, ev_int, + ev_quaternion, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, @@ -715,7 +715,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, *(%Gb + %sc)", }, [OP_STOREBI_Q_v6p] = {".=", "storebi.q", - ev_quat, ev_ptr, ev_short, + ev_quaternion, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, @@ -778,7 +778,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %gc", }, [OP_NOT_Q_v6p] = {"!", "not.q", - ev_quat, ev_invalid, ev_int, + ev_quaternion, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, @@ -1203,7 +1203,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga", }, [OP_PUSH_Q_v6p] = {"", "push.q", - ev_quat, ev_invalid, ev_invalid, + ev_quaternion, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, @@ -1254,7 +1254,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "*(%Ga + %Gb)", }, [OP_PUSHB_Q_v6p] = {"", "pushb.q", - ev_ptr, ev_int, ev_quat, + ev_ptr, ev_int, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, @@ -1305,7 +1305,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "*(%Ga + %sb)", }, [OP_PUSHBI_Q_v6p] = {"", "pushbi.q", - ev_ptr, ev_short, ev_quat, + ev_ptr, ev_short, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %sb)", }, @@ -1356,7 +1356,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%ga", }, [OP_POP_Q_v6p] = {"", "pop.q", - ev_quat, ev_invalid, ev_invalid, + ev_quaternion, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, @@ -1407,7 +1407,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "*(%Ga + %Gb)", }, [OP_POPB_Q_v6p] = {"", "popb.q", - ev_ptr, ev_int, ev_quat, + ev_ptr, ev_int, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, @@ -1458,7 +1458,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "*(%Ga + %sb)", }, [OP_POPBI_Q_v6p] = {"", "popbi.q", - ev_ptr, ev_short, ev_quat, + ev_ptr, ev_short, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %sb)", }, diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 69dd7254c..6da6199f2 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -344,7 +344,7 @@ set_address (sv_def_t *def, void *address) break; case ev_float: case ev_vector: - case ev_quat: + case ev_quaternion: *(float **)def->field = (float *) address; break; case ev_double: diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index dee8842bd..d0636718c 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -377,7 +377,7 @@ set_address (sv_def_t *def, void *address) break; case ev_float: case ev_vector: - case ev_quat: + case ev_quaternion: *(float **)def->field = (float *) address; break; case ev_double: diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 19081fd48..84d0acc3f 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -540,7 +540,7 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->e.value->v.vector_val[1], e->e.value->v.vector_val[2]); break; - case ev_quat: + case ev_quaternion: label = va (0, "'%g %g %g %g'", e->e.value->v.quaternion_val[0], e->e.value->v.quaternion_val[1], diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 2f39850e1..69cc1e61a 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -134,7 +134,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) case ev_ptr: comment = va (0, " %x", G_INT (pr, offset)); break; - case ev_quat: + case ev_quaternion: comment = va (0, " '%g %g %g %g'", G_QUAT (pr, offset)[0], G_QUAT (pr, offset)[1], diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 61e42c552..19af1437f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1079,10 +1079,10 @@ is_quaternion_val (expr_t *e) { if (e->type == ex_nil) return 1; - if (e->type == ex_value && e->e.value->lltype == ev_quat) + if (e->type == ex_value && e->e.value->lltype == ev_quaternion) return 1; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && e->e.symbol->type->type == ev_quat) + && e->e.symbol->type->type == ev_quaternion) return 1; return 0; } @@ -1092,14 +1092,14 @@ expr_quaternion (expr_t *e) { if (e->type == ex_nil) return quat_origin; - if (e->type == ex_value && e->e.value->lltype == ev_quat) + if (e->type == ex_value && e->e.value->lltype == ev_quaternion) return e->e.value->v.quaternion_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const - && e->e.symbol->type->type == ev_quat) + && e->e.symbol->type->type == ev_quaternion) return e->e.symbol->s.value->v.quaternion_val; if (e->type == ex_symbol && e->e.symbol->sy_type == sy_var && e->e.symbol->s.def->constant - && e->e.symbol->s.def->type->type == ev_quat) + && e->e.symbol->s.def->type->type == ev_quaternion) return D_QUAT (e->e.symbol->s.def); internal_error (e, "not a quaternion constant"); } @@ -1459,7 +1459,7 @@ field_expr (expr_t *e1, expr_t *e2) e = new_address_expr (ivar->type, e1, e2); return unary_expr ('.', e); } - } else if (t1->type == ev_vector || t1->type == ev_quat + } else if (t1->type == ev_vector || t1->type == ev_quaternion || is_struct (t1)) { symbol_t *field; @@ -1707,7 +1707,7 @@ unary_expr (int op, expr_t *e) case ev_vector: VectorNegate (expr_vector (e), v); return new_vector_expr (v); - case ev_quat: + case ev_quaternion: QuatNegate (expr_vector (e), q); return new_vector_expr (q); case ev_long: @@ -1809,7 +1809,7 @@ unary_expr (int op, expr_t *e) return new_int_expr (!expr_float (e)); case ev_vector: return new_int_expr (!VectorIsZero (expr_vector (e))); - case ev_quat: + case ev_quaternion: return new_int_expr (!QuatIsZero (expr_quaternion (e))); case ev_long: case ev_ulong: @@ -1882,7 +1882,7 @@ unary_expr (int op, expr_t *e) return error (e, "invalid type for unary ~"); case ev_float: return new_float_expr (~(int) expr_float (e)); - case ev_quat: + case ev_quaternion: QuatConj (expr_vector (e), q); return new_vector_expr (q); case ev_long: diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 7610b4542..dfd02b5c8 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -534,7 +534,7 @@ static expr_type_t *string_x[ev_type_count] = { 0, // ev_field 0, // ev_func 0, // ev_ptr - 0, // ev_quat + 0, // ev_quaternion 0, // ev_int 0, // ev_uint 0, // ev_short @@ -630,7 +630,7 @@ static expr_type_t *pointer_x[ev_type_count] = { 0, // ev_field 0, // ev_func pointer_pointer, - 0, // ev_quat + 0, // ev_quaternion pointer_int, pointer_uint, pointer_short, diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 52b4de683..5055d38d5 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -134,7 +134,7 @@ test_expr (expr_t *e) return new_alias_expr (type_default, e); case ev_ptr: return new_alias_expr (type_default, e); - case ev_quat: + case ev_quaternion: new = new_quaternion_expr (zero); break; case ev_invalid: diff --git a/tools/qfcc/source/idstuff.c b/tools/qfcc/source/idstuff.c index f78658247..9fb7f5003 100644 --- a/tools/qfcc/source/idstuff.c +++ b/tools/qfcc/source/idstuff.c @@ -230,7 +230,7 @@ WriteProgdefs (dprograms_t *progs, const char *filename) case ev_vector: dasprintf (dstr, "\tvec3_t\t%s;\n", name); break; - case ev_quat: + case ev_quaternion: dasprintf (dstr, "\tquat_t\t%s;\n", name); break; case ev_string: diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index a0aa7997f..8e6b01232 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -134,7 +134,7 @@ operand_string (operand_t *op) op->value->v.vector_val[0], op->value->v.vector_val[1], op->value->v.vector_val[2]); - case ev_quat: + case ev_quaternion: return va (0, "'%g %g %g %g'", op->value->v.quaternion_val[0], op->value->v.quaternion_val[1], @@ -221,7 +221,7 @@ _print_operand (operand_t *op) printf (" %g", op->value->v.vector_val[1]); printf (" %g'", op->value->v.vector_val[2]); break; - case ev_quat: + case ev_quaternion: printf ("'%g", op->value->v.quaternion_val[0]); printf (" %g", op->value->v.quaternion_val[1]); printf (" %g", op->value->v.quaternion_val[2]); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index de6709c9d..c29c910bc 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -74,7 +74,7 @@ type_t type_function = { ev_func, "function", 1, ty_basic, {{&type_void}} }; type_t type_pointer = { ev_ptr, "pointer", 1, ty_basic, {{&type_void}} }; -type_t type_quaternion = { ev_quat, "quaternion", 4 }; +type_t type_quaternion = { ev_quaternion, "quaternion", 4 }; type_t type_int = { ev_int, "int", 1 }; type_t type_uint = { ev_uint, "uint", 1 }; type_t type_short = { ev_short, "short", 1 }; @@ -185,7 +185,7 @@ free_type (type_t *type) case ev_vector: case ev_entity: case ev_type_count: - case ev_quat: + case ev_quaternion: case ev_int: case ev_uint: case ev_long: @@ -227,7 +227,7 @@ copy_chain (type_t *type, type_t *append) case ev_vector: case ev_entity: case ev_type_count: - case ev_quat: + case ev_quaternion: case ev_int: case ev_uint: case ev_long: @@ -280,7 +280,7 @@ append_type (type_t *type, type_t *new) case ev_vector: case ev_entity: case ev_type_count: - case ev_quat: + case ev_quaternion: case ev_int: case ev_uint: case ev_long: @@ -659,7 +659,7 @@ print_type_str (dstring_t *str, const type_t *type) case ev_float: case ev_vector: case ev_entity: - case ev_quat: + case ev_quaternion: case ev_int: case ev_uint: case ev_long: @@ -819,7 +819,7 @@ encode_type (dstring_t *encoding, const type_t *type) dasprintf (encoding, "^"); encode_type (encoding, type); return; - case ev_quat: + case ev_quaternion: dasprintf (encoding, "Q"); return; case ev_int: @@ -936,7 +936,7 @@ int is_quaternion (const type_t *type) { type = unalias_type (type); - return type->type == ev_quat; + return type->type == ev_quaternion; } int @@ -945,7 +945,7 @@ is_math (const type_t *type) type = unalias_type (type); etype_t t = type->type; - return t == ev_vector || t == ev_quat || is_scalar (type); + return t == ev_vector || t == ev_quaternion || is_scalar (type); } int @@ -1258,7 +1258,7 @@ init_types (void) make_structure ("@va_list", 's', va_list_struct, &type_va_list); make_structure ("@quaternion", 's', quaternion_struct, &type_quaternion); - type_quaternion.type = ev_quat; + type_quaternion.type = ev_quaternion; type_quaternion.meta = ty_basic; { symbol_t *sym; diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 73b3b47ab..7cdc55782 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -533,7 +533,7 @@ emit_value (ex_value_t *value, def_t *def) tab = vector_imm_defs; type = &type_vector; break; - case ev_quat: + case ev_quaternion: tab = quaternion_imm_defs; type = &type_quaternion; break; From 2c52e26d1ad89025dff6749f8a29ce241098dc80 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 15:50:32 +0900 Subject: [PATCH 2216/3664] [gamecode] Be more consistent with access types Eg, pointers via ptr, entities via entity, etc. --- libs/gamecode/pr_exec.c | 197 ++++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 100 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 65615b7fe..7ca7d6ad9 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -458,7 +458,7 @@ check_stack_pointer (progs_t *pr, pr_ptr_t stack, int size) } static inline void -pr_memset (pr_type_t *dst, int val, int count) +pr_memset (pr_type_t *dst, int val, pr_uint_t count) { while (count-- > 0) { (*dst++).int_var = val; @@ -691,37 +691,34 @@ pr_exec_quakec (progs_t *pr, int exitdepth) OPC(int) = QuatIsZero (&OPA(float)); break; case OP_NOT_S_v6p: - OPC(int) = !OPA(string) || - !*PR_GetString (pr, OPA(string)); + OPC(int) = !OPA(string) || !*PR_GetString (pr, OPA(string)); break; case OP_NOT_FN_v6p: - OPC(int) = !OPA(uint); + OPC(int) = !OPA(func); break; case OP_NOT_ENT_v6p: - OPC(int) = !OPA(uint); + OPC(int) = !OPA(entity); break; case OP_EQ_F_v6p: OPC(int) = OPA(float) == OPB(float); break; case OP_EQ_V_v6p: - OPC(int) = VectorCompare (&OPA(float), - &OPB(float)); + OPC(int) = VectorCompare (&OPA(float), &OPB(float)); break; case OP_EQ_Q_v6p: OPC(int) = QuatCompare (&OPA(float), &OPB(float)); break; case OP_EQ_E_v6p: - OPC(int) = OPA(int) == OPB(int); + OPC(int) = OPA(field) == OPB(field); break; case OP_EQ_FN_v6p: - OPC(int) = OPA(uint) == OPB(uint); + OPC(int) = OPA(func) == OPB(func); break; case OP_NE_F_v6p: OPC(int) = OPA(float) != OPB(float); break; case OP_NE_V_v6p: - OPC(int) = !VectorCompare (&OPA(float), - &OPB(float)); + OPC(int) = !VectorCompare (&OPA(float), &OPB(float)); break; case OP_NE_Q_v6p: OPC(int) = !QuatCompare (&OPA(float), &OPB(float)); @@ -748,10 +745,10 @@ pr_exec_quakec (progs_t *pr, int exitdepth) } break; case OP_NE_E_v6p: - OPC(int) = OPA(int) != OPB(int); + OPC(int) = OPA(entity) != OPB(entity); break; case OP_NE_FN_v6p: - OPC(int) = OPA(uint) != OPB(uint); + OPC(int) = OPA(func) != OPB(func); break; // ================== @@ -781,7 +778,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREP_FN_v6p: // pointers case OP_STOREP_I_v6p: case OP_STOREP_P_v6p: - pointer = OPB(int); + pointer = OPB(ptr); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_int); } @@ -789,7 +786,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr->int_var = OPA(int); break; case OP_STOREP_V_v6p: - pointer = OPB(int); + pointer = OPB(ptr); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } @@ -797,7 +794,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) VectorCopy (&OPA(float), &ptr->vector_var); break; case OP_STOREP_Q_v6p: - pointer = OPB(int); + pointer = OPB(ptr); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -805,7 +802,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) QuatCopy (&OPA(float), &ptr->quat_var); break; case OP_STOREP_D_v6p: - pointer = OPB(int); + pointer = OPB(ptr); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_double); } @@ -815,17 +812,17 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_ADDRESS_v6p: if (pr_boundscheck->int_val) { - if (OPA(uint) >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to address an out " "of bounds edict"); - if (OPA(uint) == 0 && pr->null_bad) + if (OPA(entity) == 0 && pr->null_bad) PR_RunError (pr, "assignment to world entity"); - if (OPB(uint) >= pr->progs->entityfields) + if (OPB(field) >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to address an " "invalid field in an edict"); } - fldofs = OPA(uint) + OPB(int); - OPC(int) = &pr->pr_edict_area[fldofs] - pr->pr_globals; + fldofs = OPA(entity) + OPB(field); + OPC(ptr) = &pr->pr_edict_area[fldofs] - pr->pr_globals; break; case OP_ADDRESS_VOID_v6p: case OP_ADDRESS_F_v6p: @@ -849,50 +846,50 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOAD_I_v6p: case OP_LOAD_P_v6p: if (pr_boundscheck->int_val) { - if (OPA(uint) >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB(uint) >= pr->progs->entityfields) + if (OPB(field) >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA(uint) + OPB(int); + fldofs = OPA(entity) + OPB(field); OPC(int) = pr->pr_edict_area[fldofs].int_var; break; case OP_LOAD_V_v6p: if (pr_boundscheck->int_val) { - if (OPA(uint) >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB(uint) + 2 >= pr->progs->entityfields) + if (OPB(field) + 2 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA(uint) + OPB(int); + fldofs = OPA(entity) + OPB(field); memcpy (op_c, &pr->pr_edict_area[fldofs], 3 * sizeof (*op_c)); break; case OP_LOAD_Q_v6p: if (pr_boundscheck->int_val) { - if (OPA(uint) >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB(uint) + 3 >= pr->progs->entityfields) + if (OPB(field) + 3 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA(uint) + OPB(int); + fldofs = OPA(entity) + OPB(field); memcpy (op_c, &pr->pr_edict_area[fldofs], 4 * sizeof (*op_c)); break; case OP_LOAD_D_v6p: if (pr_boundscheck->int_val) { - if (OPA(uint) >= pr->pr_edict_area_size) + if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); - if (OPB(uint) + 1 >= pr->progs->entityfields) + if (OPB(field) + 1 >= pr->progs->entityfields) PR_RunError (pr, "Progs attempted to read an invalid " "field in an edict"); } - fldofs = OPA(uint) + OPB(int); + fldofs = OPA(entity) + OPB(field); memcpy (op_c, &pr->pr_edict_area[fldofs], sizeof (double)); break; @@ -903,7 +900,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADB_FN_v6p: case OP_LOADB_I_v6p: case OP_LOADB_P_v6p: - pointer = OPA(int) + OPB(int); + pointer = OPA(entity) + OPB(field); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_int); } @@ -911,7 +908,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) OPC(int) = ptr->int_var; break; case OP_LOADB_V_v6p: - pointer = OPA(int) + OPB(int); + pointer = OPA(entity) + OPB(field); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } @@ -919,7 +916,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) VectorCopy (&ptr->vector_var, &OPC(float)); break; case OP_LOADB_Q_v6p: - pointer = OPA(int) + OPB(int); + pointer = OPA(entity) + OPB(field); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -927,7 +924,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) QuatCopy (&ptr->quat_var, &OPC(float)); break; case OP_LOADB_D_v6p: - pointer = OPA(int) + OPB(int); + pointer = OPA(entity) + OPB(field); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_double); } @@ -942,7 +939,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADBI_FN_v6p: case OP_LOADBI_I_v6p: case OP_LOADBI_P_v6p: - pointer = OPA(int) + (short) st->b; + pointer = OPA(ptr) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_int); } @@ -950,7 +947,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) OPC(int) = ptr->int_var; break; case OP_LOADBI_V_v6p: - pointer = OPA(int) + (short) st->b; + pointer = OPA(ptr) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } @@ -958,7 +955,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) VectorCopy (&ptr->vector_var, &OPC(float)); break; case OP_LOADBI_Q_v6p: - pointer = OPA(int) + (short) st->b; + pointer = OPA(ptr) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -966,7 +963,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) QuatCopy (&ptr->quat_var, &OPC(float)); break; case OP_LOADBI_D_v6p: - pointer = OPA(int) + (short) st->b; + pointer = OPA(ptr) + (short) st->b; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -975,13 +972,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_LEA_v6p: - pointer = OPA(int) + OPB(int); - OPC(int) = pointer; + pointer = OPA(ptr) + OPB(int); + OPC(ptr) = pointer; break; case OP_LEAI_v6p: - pointer = OPA(int) + (short) st->b; - OPC(int) = pointer; + pointer = OPA(ptr) + (short) st->b; + OPC(ptr) = pointer; break; case OP_STOREB_F_v6p: @@ -991,7 +988,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREB_FN_v6p: case OP_STOREB_I_v6p: case OP_STOREB_P_v6p: - pointer = OPB(int) + OPC(int); + pointer = OPB(ptr) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_int); } @@ -999,7 +996,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr->int_var = OPA(int); break; case OP_STOREB_V_v6p: - pointer = OPB(int) + OPC(int); + pointer = OPB(ptr) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } @@ -1007,7 +1004,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) VectorCopy (&OPA(float), &ptr->vector_var); break; case OP_STOREB_Q_v6p: - pointer = OPB(int) + OPC(int); + pointer = OPB(ptr) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -1015,7 +1012,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) QuatCopy (&OPA(float), &ptr->quat_var); break; case OP_STOREB_D_v6p: - pointer = OPB(int) + OPC(int); + pointer = OPB(ptr) + OPC(int); if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -1030,7 +1027,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREBI_FN_v6p: case OP_STOREBI_I_v6p: case OP_STOREBI_P_v6p: - pointer = OPB(int) + (short) st->c; + pointer = OPB(ptr) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_int); } @@ -1038,7 +1035,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr->int_var = OPA(int); break; case OP_STOREBI_V_v6p: - pointer = OPB(int) + (short) st->c; + pointer = OPB(ptr) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_vector); } @@ -1046,7 +1043,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) VectorCopy (&OPA(float), &ptr->vector_var); break; case OP_STOREBI_Q_v6p: - pointer = OPB(int) + (short) st->c; + pointer = OPB(ptr) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -1054,7 +1051,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) QuatCopy (&OPA(float), &ptr->quat_var); break; case OP_STOREBI_D_v6p: - pointer = OPB(int) + (short) st->c; + pointer = OPB(ptr) + (short) st->c; if (pr_boundscheck->int_val) { PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -1113,7 +1110,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + OPB(int); + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1130,7 +1127,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + OPB(int); + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1147,7 +1144,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + OPB(int); + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1171,7 +1168,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1188,7 +1185,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1205,7 +1202,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1269,7 +1266,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + OPB(int); + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1286,7 +1283,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + OPB(int); + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1303,7 +1300,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + OPB(int); + pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1327,7 +1324,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1344,7 +1341,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1361,7 +1358,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - pointer = OPA(int) + st->b; + pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; if (pr_boundscheck->int_val) { @@ -1467,7 +1464,7 @@ op_rcall: op_call: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; - PR_CallFunction (pr, OPA(uint), pr->pr_return); + PR_CallFunction (pr, OPA(func), pr->pr_return); st = pr->pr_statements + pr->pr_xstatement; break; case OP_DONE_v6p: @@ -1500,7 +1497,7 @@ op_call: float time = *pr->globals.ftime + 0.1; pr->pr_edict_area[nextthink].float_var = time; pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = OPB(uint); + pr->pr_edict_area[think].func_var = OPB(func); } break; case OP_STATE_F_v6p: @@ -1512,7 +1509,7 @@ op_call: float time = *pr->globals.ftime + OPC(float); pr->pr_edict_area[nextthink].float_var = time; pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = OPB(uint); + pr->pr_edict_area[think].func_var = OPB(func); } break; case OP_ADD_I_v6p: @@ -1649,31 +1646,31 @@ op_call: break; case OP_MOVEP_v6p: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC(int), OPB(uint)); - PR_BoundsCheckSize (pr, OPA(int), OPB(uint)); + PR_BoundsCheckSize (pr, OPC(ptr), OPB(uint)); + PR_BoundsCheckSize (pr, OPA(ptr), OPB(uint)); } - memmove (pr->pr_globals + OPC(int), - pr->pr_globals + OPA(int), + memmove (pr->pr_globals + OPC(ptr), + pr->pr_globals + OPA(ptr), OPB(uint) * 4); break; case OP_MOVEPI_v6p: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC(int), st->b); - PR_BoundsCheckSize (pr, OPA(int), st->b); + PR_BoundsCheckSize (pr, OPC(ptr), st->b); + PR_BoundsCheckSize (pr, OPA(ptr), st->b); } - memmove (pr->pr_globals + OPC(int), - pr->pr_globals + OPA(int), + memmove (pr->pr_globals + OPC(ptr), + pr->pr_globals + OPA(ptr), st->b * 4); break; case OP_MEMSETI_v6p: - pr_memset (op_c, OPA(int), st->b); + pr_memset (op_c, OPA(ptr), st->b); break; case OP_MEMSETP_v6p: if (pr_boundscheck->int_val) { - PR_BoundsCheckSize (pr, OPC(ptr), OPB(int)); + PR_BoundsCheckSize (pr, OPC(ptr), OPB(uint)); } pr_memset (pr->pr_globals + OPC(ptr), OPA(int), - OPB(int)); + OPB(uint)); break; case OP_MEMSETPI_v6p: if (pr_boundscheck->int_val) { @@ -1720,7 +1717,7 @@ op_call: // LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized /* case OP_BOUNDCHECK_v6p: - if (OPA(int) < 0 || OPA(int) >= st->b) { + if (OPA(ptr) >= st->b) { PR_RunError (pr, "Progs boundcheck failed at line number " "%d, value is < 0 or >= %d", st->b, st->c); } @@ -1763,20 +1760,20 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 1: // simple pointer dereference: *a - mm_offs = OPA(uint); + mm_offs = OPA(ptr); break; case 2: // constant indexed pointer: *a + b (supports -ve offset) - mm_offs = OPA(uint) + (short) st->b; + mm_offs = OPA(ptr) + (short) st->b; break; case 3: // variable indexed pointer: *a + *b (supports -ve offset) - mm_offs = OPA(uint) + OPB(int); + mm_offs = OPA(ptr) + OPB(int); break; case 4: // entity.field (equivalent to OP_LOAD_t_v6p) pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; - mm_offs = edict_area + OPA(uint) + OPB(uint); + mm_offs = edict_area + OPA(entity) + OPB(field); break; } return pr->pr_globals + mm_offs; @@ -1796,20 +1793,20 @@ pr_return_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 1: // simple pointer dereference: *a - mm_offs = OPA(uint); + mm_offs = OPA(ptr); break; case 2: // constant indexed pointer: *a + b (supports -ve offset) - mm_offs = OPA(uint) + (short) st->b; + mm_offs = OPA(ptr) + (short) st->b; break; case 3: // variable indexed pointer: *a + *b (supports -ve offset) - mm_offs = OPA(uint) + OPB(int); + mm_offs = OPA(ptr) + OPB(int); break; case 4: // entity.field (equivalent to OP_LOAD_t_v6p) pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; - mm_offs = edict_area + OPA(uint) + OPB(uint); + mm_offs = edict_area + OPA(entity) + OPB(field); break; } return pr->pr_globals + mm_offs; @@ -1829,16 +1826,16 @@ pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 2: // constant indexed pointer: *a + b (supports -ve offset) - mm_offs = OPA(uint) + (short) st->b; + mm_offs = OPA(ptr) + (short) st->b; break; case 3: // variable indexed pointer: *a + *b (supports -ve offset) - mm_offs = OPA(uint) + OPB(int); + mm_offs = OPA(ptr) + OPB(int); break; case 4: // entity.field (equivalent to OP_LOAD_t_v6p) pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; - mm_offs = edict_area + OPA(uint) + OPB(uint); + mm_offs = edict_area + OPA(entity) + OPB(field); break; } return pr->pr_globals + mm_offs; @@ -1858,15 +1855,15 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind) break; case 1: // simple pointer dereference: *a - jump_offs = OPA(uint); + jump_offs = OPA(ptr); break; case 2: // constant indexed pointer: *a + b (supports -ve offset) - jump_offs = OPA(uint) + (short) st->b; + jump_offs = OPA(ptr) + (short) st->b; break; case 3: // variable indexed pointer: *a + *b (supports -ve offset) - jump_offs = OPA(uint) + OPB(int); + jump_offs = OPA(ptr) + OPB(int); break; } if (pr_boundscheck->int_val && jump_offs >= pr->progs->numstatements) { @@ -1941,7 +1938,7 @@ pr_with (progs_t *pr, const dstatement_t *st) return; case 7: // relative to edict_area (only +ve) - *base = edict_area + OPB(uint); + *base = edict_area + OPB(field); return; case 8: @@ -3286,11 +3283,11 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) memmove (op_c, op_a, st->b * sizeof (pr_type_t)); break; case OP_MOVE_P: - memmove (pr->pr_globals + OPC(int), pr->pr_globals + OPA(int), + memmove (pr->pr_globals + OPC(ptr), pr->pr_globals + OPA(ptr), OPB(uint) * sizeof (pr_type_t)); break; case OP_MOVE_PI: - memmove (pr->pr_globals + OPC(int), pr->pr_globals + OPA(int), + memmove (pr->pr_globals + OPC(ptr), pr->pr_globals + OPA(ptr), st->b * sizeof (pr_type_t)); break; case OP_STATE_ft: @@ -3310,10 +3307,10 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) pr_memset (op_c, OPA(int), st->b); break; case OP_MEMSET_P: - pr_memset (pr->pr_globals + OPC(int), OPA(int), OPB(uint)); + pr_memset (pr->pr_globals + OPC(ptr), OPA(int), OPB(uint)); break; case OP_MEMSET_PI: - pr_memset (pr->pr_globals + OPC(int), OPA(int), st->b); + pr_memset (pr->pr_globals + OPC(ptr), OPA(int), st->b); break; case OP_STATE_ftt: { From 25f8d3a23def67c00dc6d193476befb84ac035cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 15:53:31 +0900 Subject: [PATCH 2217/3664] [gamecode] Use pr_type_names.h for type sizes The goal of the previous mess of commits. Ruamoko needs to wait until qfcc has the new types. --- include/QF/progs/pr_comp.h | 4 ++++ libs/gamecode/pr_opcode.c | 19 ++++--------------- ruamoko/lib/types.r | 4 +++- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index aff321ffc..7f52cb21d 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -25,8 +25,12 @@ typedef int32_t pr_string_t; typedef float pr_float_t; +typedef float pr_vector_t[3]; +typedef uint32_t pr_entity_t; +typedef uint32_t pr_field_t; typedef uint32_t pr_func_t; typedef uint32_t pr_ptr_t; +typedef float pr_quaternion_t[4]; typedef int32_t pr_int_t; typedef uint32_t pr_uint_t; typedef int16_t pr_short_t; diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 0f1cb1258..8fb79e851 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -33,22 +33,11 @@ #include "QF/progs.h" +typedef pr_type_t pr_void_t; // so size of void is 1 + +#define EV_TYPE(type) (sizeof (pr_##type##_t) / sizeof (pr_int_t)), VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { - 1, // ev_void - 1, // ev_string - 1, // ev_float - 3, // ev_vector - 1, // ev_entity - 1, // ev_field - 1, // ev_func - 1, // ev_pointer - 4, // ev_quat - 1, // ev_int - 1, // ev_uint - 0, // ev_short value in opcode - 2, // ev_double - 2, // ev_long - 2, // ev_ulong +#include "QF/progs/pr_type_names.h" 0, // ev_invalid not a valid/simple type }; diff --git a/ruamoko/lib/types.r b/ruamoko/lib/types.r index f732cc8d0..0445e0510 100644 --- a/ruamoko/lib/types.r +++ b/ruamoko/lib/types.r @@ -11,8 +11,10 @@ string ty_meta_name[7] = { "alias", }; -//FIXME use pr_type_names.h +//FIXME use pr_type_names.h, but need to fix unsigned, and add missing types +//#define EV_TYPE(type) sizeof(type), int pr_type_size[ev_type_count] = { +//#include 1, // ev_void 1, // ev_string 1, // ev_float From ed501b7734ed402f0d296160146af509fe7825f8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 18:41:39 +0900 Subject: [PATCH 2218/3664] [gamecode] Specify the alignment for progs types And provide a table for such for qfcc and the like. With this, using pr_double_t (for example) in C will cause the double value to always be 8-byte aligned and thus structures shared between gcc and qfcc will be consistent (with a little fuss to take care of the warts). --- include/QF/progs/pr_comp.h | 31 ++++++++++++++++--------------- libs/gamecode/pr_opcode.c | 6 ++++++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 7f52cb21d..5d66fc323 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -23,21 +23,21 @@ #include "QF/qtypes.h" -typedef int32_t pr_string_t; -typedef float pr_float_t; -typedef float pr_vector_t[3]; -typedef uint32_t pr_entity_t; -typedef uint32_t pr_field_t; -typedef uint32_t pr_func_t; -typedef uint32_t pr_ptr_t; -typedef float pr_quaternion_t[4]; -typedef int32_t pr_int_t; -typedef uint32_t pr_uint_t; -typedef int16_t pr_short_t; -typedef double pr_double_t; -typedef int64_t pr_long_t; -typedef uint64_t pr_ulong_t; -typedef uint16_t pr_ushort_t; +typedef int32_t pr_string_t __attribute__((aligned(4))); +typedef float pr_float_t __attribute__((aligned(4))); +typedef float pr_vector_t[3] __attribute__((aligned(4))); +typedef uint32_t pr_entity_t __attribute__((aligned(4))); +typedef uint32_t pr_field_t __attribute__((aligned(4))); +typedef uint32_t pr_func_t __attribute__((aligned(4))); +typedef uint32_t pr_ptr_t __attribute__((aligned(4))); +typedef float pr_quaternion_t[4] __attribute__((aligned(4))); +typedef int32_t pr_int_t __attribute__((aligned(4))); +typedef uint32_t pr_uint_t __attribute__((aligned(4))); +typedef int16_t pr_short_t __attribute__((aligned(2))); +typedef double pr_double_t __attribute__((aligned(8))); +typedef int64_t pr_long_t __attribute__((aligned(8))); +typedef uint64_t pr_ulong_t __attribute__((aligned(8))); +typedef uint16_t pr_ushort_t __attribute__((aligned(2)));; #define PR_VEC_TYPE(t,n,s) \ typedef t n __attribute__ ((vector_size (s*sizeof (t)))) @@ -63,6 +63,7 @@ typedef enum { } etype_t; extern const pr_ushort_t pr_type_size[ev_type_count]; +extern const pr_ushort_t pr_type_alignment[ev_type_count]; extern const char * const pr_type_name[ev_type_count]; #define OFS_NULL 0 diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 8fb79e851..c056297a9 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -41,6 +41,12 @@ VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { 0, // ev_invalid not a valid/simple type }; +#define EV_TYPE(type) (__alignof__ (pr_##type##_t) / __alignof__ (pr_int_t)), +VISIBLE const pr_ushort_t pr_type_alignment[ev_type_count] = { +#include "QF/progs/pr_type_names.h" + 0, // ev_invalid not a valid/simple type +}; + #define EV_TYPE(type) #type, VISIBLE const char * const pr_type_name[ev_type_count] = { #include "QF/progs/pr_type_names.h" From 5b97aa38973716999ed64df0d16a4a9c35ed6a0b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 21:22:18 +0900 Subject: [PATCH 2219/3664] [qfcc] Use index labels for the type arrays The one place that needed it most... constfold.c --- tools/qfcc/source/constfold.c | 480 +++++++++++++++++----------------- 1 file changed, 240 insertions(+), 240 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 8566e00b1..c09f82257 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1053,288 +1053,288 @@ do_op_invalid (int op, expr_t *e, expr_t *e1, expr_t *e2) } static operation_t op_void[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_invalid, // ev_float - do_op_invalid, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_invalid, // ev_quaternion - do_op_invalid, // ev_int - do_op_invalid, // ev_uint - do_op_invalid, // ev_short - do_op_invalid, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_invalid, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_invalid, + [ev_uint] = do_op_invalid, + [ev_short] = do_op_invalid, + [ev_double] = do_op_invalid, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_string[ev_type_count] = { - do_op_invalid, // ev_void - do_op_string, // ev_string - do_op_invalid, // ev_float - do_op_invalid, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_invalid, // ev_quaternion - do_op_invalid, // ev_int - do_op_invalid, // ev_uint - do_op_invalid, // ev_short - do_op_invalid, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_string, + [ev_float] = do_op_invalid, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_invalid, + [ev_uint] = do_op_invalid, + [ev_short] = do_op_invalid, + [ev_double] = do_op_invalid, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_float[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_float, // ev_float - do_op_vector, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_quaternion, // ev_quaternion - do_op_float, // ev_int - do_op_float, // ev_uint - do_op_float, // ev_short - do_op_double, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_float, + [ev_uint] = do_op_float, + [ev_short] = do_op_float, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_vector[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_vector, // ev_float - do_op_vector, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_invalid, // ev_quaternion - do_op_vector, // ev_int - do_op_vector, // ev_uint - do_op_vector, // ev_short - do_op_vector, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_vector, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_vector, + [ev_uint] = do_op_vector, + [ev_short] = do_op_vector, + [ev_double] = do_op_vector, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_entity[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_invalid, // ev_float - do_op_invalid, // ev_vector - do_op_entity, // ev_entity - do_op_entity, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_invalid, // ev_quaternion - do_op_invalid, // ev_int - do_op_invalid, // ev_uint - do_op_invalid, // ev_short - do_op_invalid, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_invalid, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_entity, + [ev_field] = do_op_entity, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_invalid, + [ev_uint] = do_op_invalid, + [ev_short] = do_op_invalid, + [ev_double] = do_op_invalid, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_field[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_invalid, // ev_float - do_op_invalid, // ev_vector - do_op_invalid, // ev_entity - do_op_field, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_invalid, // ev_quaternion - do_op_invalid, // ev_int - do_op_invalid, // ev_uint - do_op_invalid, // ev_short - do_op_invalid, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_invalid, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_field, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_invalid, + [ev_uint] = do_op_invalid, + [ev_short] = do_op_invalid, + [ev_double] = do_op_invalid, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_func[ev_type_count] = { - do_op_func, // ev_void - do_op_func, // ev_string - do_op_func, // ev_float - do_op_func, // ev_vector - do_op_func, // ev_entity - do_op_func, // ev_field - do_op_func, // ev_func - do_op_func, // ev_ptr - do_op_func, // ev_quaternion - do_op_func, // ev_int - do_op_func, // ev_uint - do_op_func, // ev_short - do_op_func, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_func, // ev_invalid + [ev_void] = do_op_func, + [ev_string] = do_op_func, + [ev_float] = do_op_func, + [ev_vector] = do_op_func, + [ev_entity] = do_op_func, + [ev_field] = do_op_func, + [ev_func] = do_op_func, + [ev_ptr] = do_op_func, + [ev_quaternion] = do_op_func, + [ev_int] = do_op_func, + [ev_uint] = do_op_func, + [ev_short] = do_op_func, + [ev_double] = do_op_func, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_func, }; static operation_t op_pointer[ev_type_count] = { - do_op_pointer, // ev_void - do_op_pointer, // ev_string - do_op_pointer, // ev_float - do_op_pointer, // ev_vector - do_op_pointer, // ev_entity - do_op_pointer, // ev_field - do_op_pointer, // ev_func - do_op_pointer, // ev_ptr - do_op_pointer, // ev_quaternion - do_op_pointer, // ev_int - do_op_pointer, // ev_uint - do_op_pointer, // ev_short - do_op_pointer, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_pointer, // ev_invalid + [ev_void] = do_op_pointer, + [ev_string] = do_op_pointer, + [ev_float] = do_op_pointer, + [ev_vector] = do_op_pointer, + [ev_entity] = do_op_pointer, + [ev_field] = do_op_pointer, + [ev_func] = do_op_pointer, + [ev_ptr] = do_op_pointer, + [ev_quaternion] = do_op_pointer, + [ev_int] = do_op_pointer, + [ev_uint] = do_op_pointer, + [ev_short] = do_op_pointer, + [ev_double] = do_op_pointer, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_pointer, }; static operation_t op_quaternion[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_quaternion, // ev_float - do_op_quatvect, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_quaternion, // ev_quaternion - do_op_quaternion, // ev_int - do_op_quaternion, // ev_uint - do_op_quaternion, // ev_short - do_op_quaternion, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_quaternion, + [ev_vector] = do_op_quatvect, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_quaternion, + [ev_uint] = do_op_quaternion, + [ev_short] = do_op_quaternion, + [ev_double] = do_op_quaternion, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_int[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_float, // ev_float - do_op_vector, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_quaternion, // ev_quaternion - do_op_int, // ev_int - do_op_uint, // ev_uint - do_op_int, // ev_short - do_op_double, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_int, + [ev_uint] = do_op_uint, + [ev_short] = do_op_int, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_uint[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_float, // ev_float - do_op_vector, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_quaternion, // ev_quaternion - do_op_uint, // ev_int - do_op_uint, // ev_uint - do_op_uint, // ev_short - do_op_double, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_uint, + [ev_uint] = do_op_uint, + [ev_short] = do_op_uint, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_short[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_float, // ev_float - do_op_vector, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_quaternion, // ev_quaternion - do_op_int, // ev_int - do_op_uint, // ev_uint - do_op_short, // ev_short - do_op_double, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_int, + [ev_uint] = do_op_uint, + [ev_short] = do_op_short, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_double[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_float, // ev_float - do_op_vector, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_quaternion, // ev_quaternion - do_op_int, // ev_int - do_op_uint, // ev_uint - do_op_short, // ev_short - do_op_double, // ev_double - 0, // ev_long - 0, // ev_ulong - do_op_invalid, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_float, + [ev_vector] = do_op_vector, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_quaternion, + [ev_int] = do_op_int, + [ev_uint] = do_op_uint, + [ev_short] = do_op_short, + [ev_double] = do_op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = do_op_invalid, }; static operation_t op_compound[ev_type_count] = { - do_op_invalid, // ev_void - do_op_invalid, // ev_string - do_op_compound, // ev_float - do_op_invalid, // ev_vector - do_op_invalid, // ev_entity - do_op_invalid, // ev_field - do_op_invalid, // ev_func - do_op_invalid, // ev_ptr - do_op_invalid, // ev_quaternion - do_op_compound, // ev_int - do_op_compound, // ev_uint - do_op_compound, // ev_short - do_op_compound, // ev_double - do_op_compound, // ev_long - do_op_compound, // ev_ulong - do_op_compound, // ev_invalid + [ev_void] = do_op_invalid, + [ev_string] = do_op_invalid, + [ev_float] = do_op_compound, + [ev_vector] = do_op_invalid, + [ev_entity] = do_op_invalid, + [ev_field] = do_op_invalid, + [ev_func] = do_op_invalid, + [ev_ptr] = do_op_invalid, + [ev_quaternion] = do_op_invalid, + [ev_int] = do_op_compound, + [ev_uint] = do_op_compound, + [ev_short] = do_op_compound, + [ev_double] = do_op_compound, + [ev_long] = do_op_compound, + [ev_ulong] = do_op_compound, + [ev_invalid] = do_op_compound, }; static operation_t *do_op[ev_type_count] = { - op_void, // ev_void - op_string, // ev_string - op_float, // ev_float - op_vector, // ev_vector - op_entity, // ev_entity - op_field, // ev_field - op_func, // ev_func - op_pointer, // ev_ptr - op_quaternion, // ev_quaternion - op_int, // ev_int - op_uint, // ev_uint - op_short, // ev_short - op_double, // ev_double - 0, // ev_long - 0, // ev_ulong - op_compound, // ev_invalid + [ev_void] = op_void, + [ev_string] = op_string, + [ev_float] = op_float, + [ev_vector] = op_vector, + [ev_entity] = op_entity, + [ev_field] = op_field, + [ev_func] = op_func, + [ev_ptr] = op_pointer, + [ev_quaternion] = op_quaternion, + [ev_int] = op_int, + [ev_uint] = op_uint, + [ev_short] = op_short, + [ev_double] = op_double, + [ev_long] = 0, + [ev_ulong] = 0, + [ev_invalid] = op_compound, }; static unaryop_t do_unary_op[ev_type_count]; From 6df79b2b06932a12c7f6a38396cc251ba31eb87e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 21:42:53 +0900 Subject: [PATCH 2220/3664] [qfcc] Correct xdef structures and usage in test Attempting to add ev_ushort caused ptraliasenc to break, but that was because it was already broken: I had implemented the scan of the xdef table incorrectly, thus adding only 1 ev type resulted in the walked pointer being out of phase with its data due to it first passing over the type encodings (which is why adding long and ulong didn't cause any obvious trouble). --- tools/qfcc/source/type.c | 4 ++-- tools/qfcc/test/ptraliasenc.r | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index c29c910bc..1e03bf19d 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -1210,7 +1210,7 @@ init_types (void) }; static struct_def_t type_encoding_struct[] = { {"types", &type_pointer}, - {"size", &type_int}, + {"size", &type_uint}, {0, 0} }; static struct_def_t xdef_struct[] = { @@ -1220,7 +1220,7 @@ init_types (void) }; static struct_def_t xdefs_struct[] = { {"xdefs", &type_xdef_pointer}, - {"num_xdefs", &type_pointer}, + {"num_xdefs", &type_uint}, {0, 0} }; static struct_def_t va_list_struct[] = { diff --git a/tools/qfcc/test/ptraliasenc.r b/tools/qfcc/test/ptraliasenc.r index 2f305617f..8e8a58e9c 100644 --- a/tools/qfcc/test/ptraliasenc.r +++ b/tools/qfcc/test/ptraliasenc.r @@ -10,16 +10,22 @@ typedef struct xdef_s { void *ofs; ///< 32-bit version of ddef_t.ofs } xdef_t; +typedef struct xdefs_s { + xdef_t *xdefs; + unsigned num_xdefs; +} xdefs_t; + void *PR_FindGlobal (string name) = #0; int main (void) { //FIXME need a simple way to get at a def's meta-data - xdef_t *xdefs = PR_FindGlobal (".xdefs"); - while (xdefs.ofs != &int32_ptr) { - xdefs++; + xdefs_t *xdefs = PR_FindGlobal (".xdefs"); + xdef_t *xdef = xdefs.xdefs; + while (xdef - xdefs.xdefs < xdefs.num_xdefs && xdef.ofs != &int32_ptr) { + xdef++; } - printf ("int32_ptr: %s\n", xdefs.type.encoding); - return xdefs.type.encoding != "{>^i}"; + printf ("int32_ptr: %s\n", xdef.type.encoding); + return xdef.type.encoding != "{>^i}"; } From 068c04ece64f14c9c88bcbe55044ac63d0b66de2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 22:08:37 +0900 Subject: [PATCH 2221/3664] [gamecode] Add ev_ushort and partial support Really, only just enough to get everything compiling (which does include vkgen running correctly). --- include/QF/progs.h | 1 + include/QF/progs/pr_type_names.h | 1 + libs/gamecode/pr_debug.c | 15 +++++++++++++++ nq/source/sv_progs.c | 1 + qw/source/sv_progs.c | 1 + tools/qfcc/include/expr.h | 3 ++- tools/qfcc/source/dot_expr.c | 3 +++ tools/qfcc/source/expr.c | 3 +++ tools/qfcc/source/expr_bool.c | 1 + tools/qfcc/source/statements.c | 5 +++++ tools/qfcc/source/type.c | 8 ++++++++ 11 files changed, 41 insertions(+), 1 deletion(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index d2d32cf51..f9cf97b32 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1737,6 +1737,7 @@ typedef struct type_view_s { type_view_func double_view; type_view_func long_view; type_view_func ulong_view; + type_view_func ushort_view; type_view_func struct_view; type_view_func union_view; diff --git a/include/QF/progs/pr_type_names.h b/include/QF/progs/pr_type_names.h index 79dfaa4ff..5e9904b2a 100644 --- a/include/QF/progs/pr_type_names.h +++ b/include/QF/progs/pr_type_names.h @@ -45,5 +45,6 @@ EV_TYPE(short) // value is embedded in the opcode EV_TYPE(double) EV_TYPE(long) EV_TYPE(ulong) +EV_TYPE(ushort) #undef EV_TYPE diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 1f7e2a651..32f6a8dd9 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -149,6 +149,8 @@ static void pr_debug_long_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_ulong_view (qfot_type_t *type, pr_type_t *value, void *_data); +static void pr_debug_ushort_view (qfot_type_t *type, pr_type_t *value, + void *_data); static void pr_debug_struct_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_union_view (qfot_type_t *type, pr_type_t *value, @@ -176,6 +178,7 @@ static type_view_t raw_type_view = { pr_debug_double_view, pr_debug_long_view, pr_debug_ulong_view, + pr_debug_ushort_view, pr_debug_struct_view, pr_debug_union_view, pr_debug_enum_view, @@ -1074,6 +1077,9 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) case ev_ulong: raw_type_view.ulong_view (type, value, data); break; + case ev_ushort: + raw_type_view.ushort_view (type, value, data); + break; case ev_invalid: case ev_type_count: dstring_appendstr (data->dstr, ""); @@ -1395,6 +1401,15 @@ pr_debug_ulong_view (qfot_type_t *type, pr_type_t *value, void *_data) dasprintf (dstr, "%" PRIu64, *(uint64_t *)value); } +static void +pr_debug_ushort_view (qfot_type_t *type, pr_type_t *value, void *_data) +{ + __auto_type data = (pr_debug_data_t *) _data; + dstring_t *dstr = data->dstr; + + dasprintf (dstr, "%04x", (pr_ushort_t)value->int_var); +} + static void pr_dump_struct (qfot_type_t *type, pr_type_t *value, void *_data, const char *struct_type) diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index 6da6199f2..a6cc1cbc7 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -339,6 +339,7 @@ set_address (sv_def_t *def, void *address) switch (def->type) { case ev_void: case ev_short: + case ev_ushort: case ev_invalid: case ev_type_count: break; diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index d0636718c..8c8809c38 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -372,6 +372,7 @@ set_address (sv_def_t *def, void *address) switch (def->type) { case ev_void: case ev_short: + case ev_ushort: case ev_invalid: case ev_type_count: break; diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index f75fd79ba..9d220b804 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -203,7 +203,8 @@ typedef struct ex_value_s { float quaternion_val[4]; ///< quaternion constant int int_val; ///< int constant unsigned uint_val; ///< unsigned int constant - short short_val; ///< short constant + int16_t short_val; ///< short constant + uint16_t ushort_val; ///< unsigned short constant } v; } ex_value_t; diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 84d0acc3f..0074aa328 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -593,6 +593,9 @@ print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) case ev_short: label = va (0, "s %d", e->e.value->v.short_val); break; + case ev_ushort: + label = va (0, "us %d", e->e.value->v.ushort_val); + break; case ev_void: label = ""; break; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 19af1437f..d75d45ab5 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1712,6 +1712,7 @@ unary_expr (int op, expr_t *e) return new_vector_expr (q); case ev_long: case ev_ulong: + case ev_ushort: internal_error (e, "long not implemented"); case ev_int: return new_int_expr (-expr_int (e)); @@ -1813,6 +1814,7 @@ unary_expr (int op, expr_t *e) return new_int_expr (!QuatIsZero (expr_quaternion (e))); case ev_long: case ev_ulong: + case ev_ushort: internal_error (e, "long not implemented"); case ev_int: return new_int_expr (!expr_int (e)); @@ -1887,6 +1889,7 @@ unary_expr (int op, expr_t *e) return new_vector_expr (q); case ev_long: case ev_ulong: + case ev_ushort: internal_error (e, "long not implemented"); case ev_int: return new_int_expr (~expr_int (e)); diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 5055d38d5..5894e1bad 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -96,6 +96,7 @@ test_expr (expr_t *e) break; case ev_long: case ev_ulong: + case ev_ushort: internal_error (e, "long not implemented"); case ev_uint: case ev_int: diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 8e6b01232..9428e64d2 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -168,6 +168,8 @@ operand_string (operand_t *op) return va (0, "ulong %"PRIu64, op->value->v.ulong_val); case ev_short: return va (0, "short %d", op->value->v.short_val); + case ev_ushort: + return va (0, "ushort %d", op->value->v.ushort_val); case ev_void: return "(void)"; case ev_invalid: @@ -252,6 +254,9 @@ _print_operand (operand_t *op) case ev_short: printf ("%d", op->value->v.short_val); break; + case ev_ushort: + printf ("%d", op->value->v.ushort_val); + break; case ev_void: case ev_invalid: case ev_type_count: diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 1e03bf19d..fed6f0e1d 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -110,6 +110,7 @@ type_t *ev_types[ev_type_count] = { &type_uint, &type_short, &type_double, + 0, 0, 0, &type_invalid, }; @@ -191,6 +192,7 @@ free_type (type_t *type) case ev_long: case ev_ulong: case ev_short: + case ev_ushort: case ev_double: break; case ev_field: @@ -233,6 +235,7 @@ copy_chain (type_t *type, type_t *append) case ev_long: case ev_ulong: case ev_short: + case ev_ushort: case ev_double: internal_error (0, "copy basic type"); case ev_field: @@ -286,6 +289,7 @@ append_type (type_t *type, type_t *new) case ev_long: case ev_ulong: case ev_short: + case ev_ushort: case ev_double: internal_error (0, "append to basic type"); case ev_field: @@ -665,6 +669,7 @@ print_type_str (dstring_t *str, const type_t *type) case ev_long: case ev_ulong: case ev_short: + case ev_ushort: case ev_double: dasprintf (str, " %s", pr_type_name[type->type]); return; @@ -837,6 +842,9 @@ encode_type (dstring_t *encoding, const type_t *type) case ev_short: dasprintf (encoding, "s"); return; + case ev_ushort: + dasprintf (encoding, "S"); + return; case ev_invalid: case ev_type_count: break; From 57fe6690991ac2e542c5c40b86b080291a133e5f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 22:34:52 +0900 Subject: [PATCH 2222/3664] [qfcc] Shorten type_function and type_pointer names To type_func and type_ptr to match the ev type names. --- tools/qfcc/source/class.c | 57 +++++++++++++++++----------------- tools/qfcc/source/expr.c | 2 +- tools/qfcc/source/function.c | 2 +- tools/qfcc/source/method.c | 6 ++-- tools/qfcc/source/qc-lex.l | 2 +- tools/qfcc/source/statements.c | 4 +-- tools/qfcc/source/type.c | 26 +++++++--------- tools/qfcc/source/value.c | 4 +-- 8 files changed, 50 insertions(+), 53 deletions(-) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index b821135a7..4f9b2e8fe 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -123,9 +123,9 @@ static struct_def_t method_desc_struct[] = { static struct_def_t category_struct[] = { {"category_name", &type_string}, {"class_name", &type_string}, - {"instance_methods", &type_pointer}, - {"class_methods", &type_pointer}, - {"protocols", &type_pointer}, + {"instance_methods", &type_ptr}, + {"class_methods", &type_ptr}, + {"protocols", &type_ptr}, {0, 0} }; @@ -146,7 +146,7 @@ static struct_def_t module_struct[] = { {"version", &type_int}, {"size", &type_int}, {"name", &type_string}, - {"symtab", &type_pointer}, + {"symtab", &type_ptr}, {0, 0} }; @@ -157,22 +157,22 @@ static struct_def_t class_struct[] = { {"version", &type_int}, {"info", &type_int}, {"instance_size", &type_int}, - {"ivars", &type_pointer}, - {"methods", &type_pointer}, - {"dtable", &type_pointer}, - {"subclass_list", &type_pointer}, - {"sibling_class", &type_pointer}, - {"protocols", &type_pointer}, - {"gc_object_type", &type_pointer}, + {"ivars", &type_ptr}, + {"methods", &type_ptr}, + {"dtable", &type_ptr}, + {"subclass_list", &type_ptr}, + {"sibling_class", &type_ptr}, + {"protocols", &type_ptr}, + {"gc_object_type", &type_ptr}, {0, 0} }; static struct_def_t protocol_struct[] = { {"class_pointer", &type_Class}, {"protocol_name", &type_string}, - {"protocol_list", &type_pointer}, - {"instance_methods", &type_pointer}, - {"class_methods", &type_pointer}, + {"protocol_list", &type_ptr}, + {"instance_methods", &type_ptr}, + {"class_methods", &type_ptr}, {0, 0} }; @@ -257,8 +257,7 @@ emit_static_instances (const char *classname) for (static_instance_t **inst = data.instances; *inst; inst++) { data.num_instances++; } - instances_struct[1].type = array_type (&type_pointer, - data.num_instances + 1); + instances_struct[1].type = array_type (&type_ptr, data.num_instances + 1); instances_def = emit_structure (va (0, "_OBJ_STATIC_INSTANCES_%s", classname), 's', instances_struct, 0, &data, @@ -298,7 +297,7 @@ emit_static_instances_list (void) free (classes); // +1 for terminating null - instance_lists_type = array_type (&type_pointer, num_classes + 1); + instance_lists_type = array_type (&type_ptr, num_classes + 1); instance_lists_sym = make_symbol ("_OBJ_STATIC_INSTANCES", instance_lists_type, pr.far_data, sc_static); @@ -878,7 +877,7 @@ emit_class_ref (const char *class_name) def_t *name_def; ref_sym = make_symbol (va (0, ".obj_class_ref_%s", class_name), - &type_pointer, pr.far_data, sc_static); + &type_ptr, pr.far_data, sc_static); if (!ref_sym->table) symtab_addsymbol (pr.symtab, ref_sym); ref_def = ref_sym->s.def; @@ -886,7 +885,7 @@ emit_class_ref (const char *class_name) return; ref_def->initialized = ref_def->constant = ref_def->nosave = 1; name_sym = make_symbol (va (0, ".obj_class_name_%s", class_name), - &type_pointer, pr.far_data, sc_extern); + &type_ptr, pr.far_data, sc_extern); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); name_def = name_sym->s.def; @@ -902,7 +901,7 @@ emit_class_name (const char *class_name) def_t *name_def; name_sym = make_symbol (va (0, ".obj_class_name_%s", class_name), - &type_pointer, pr.far_data, sc_global); + &type_ptr, pr.far_data, sc_global); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); name_def = name_sym->s.def; @@ -923,7 +922,7 @@ emit_category_ref (const char *class_name, const char *category_name) ref_sym = make_symbol (va (0, ".obj_category_ref_%s_%s", class_name, category_name), - &type_pointer, pr.far_data, sc_static); + &type_ptr, pr.far_data, sc_static); if (!ref_sym->table) symtab_addsymbol (pr.symtab, ref_sym); ref_def = ref_sym->s.def; @@ -933,7 +932,7 @@ emit_category_ref (const char *class_name, const char *category_name) ref_def->nosave = 1; name_sym = make_symbol (va (0, ".obj_category_name_%s_%s", class_name, category_name), - &type_pointer, pr.far_data, sc_extern); + &type_ptr, pr.far_data, sc_extern); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); name_def = name_sym->s.def; @@ -950,7 +949,7 @@ emit_category_name (const char *class_name, const char *category_name) name_sym = make_symbol (va (0, ".obj_category_name_%s_%s", class_name, category_name), - &type_pointer, pr.far_data, sc_global); + &type_ptr, pr.far_data, sc_global); if (!name_sym->table) symtab_addsymbol (pr.symtab, name_sym); name_def = name_sym->s.def; @@ -1526,7 +1525,7 @@ class_finish_module (void) if (!data.refs && !data.cls_def_cnt && !data.cat_def_cnt && !data.instances_list) return; - symtab_struct[4].type = array_type (&type_pointer, + symtab_struct[4].type = array_type (&type_ptr, data.cls_def_cnt + data.cat_def_cnt + 1); @@ -1553,7 +1552,7 @@ class_finish_module (void) sc_extern); } - init_sym = new_symbol_type (".ctor", &type_function); + init_sym = new_symbol_type (".ctor", &type_func); init_sym = function_symbol (init_sym, 0, 1); module_expr = address_expr (new_symbol_expr (module_sym), 0, 0); @@ -1776,15 +1775,15 @@ def_t * emit_protocol_list (protocollist_t *protocols, const char *name) { static struct_def_t proto_list_struct[] = { - {"next", &type_pointer, emit_protocol_next}, - {"count", &type_int, emit_protocol_count}, - {"list", 0, emit_protocol_list_item}, + {"next", &type_ptr, emit_protocol_next}, + {"count", &type_int, emit_protocol_count}, + {"list", 0, emit_protocol_list_item}, {0, 0}, }; if (!protocols) return 0; - proto_list_struct[2].type = array_type (&type_pointer, protocols->count); + proto_list_struct[2].type = array_type (&type_ptr, protocols->count); return emit_structure (va (0, "_OBJ_PROTOCOLS_%s", name), 's', proto_list_struct, 0, protocols, 0, sc_static); } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index d75d45ab5..fe9c2f03f 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2789,7 +2789,7 @@ think_expr (symbol_t *think_sym) && sym->type->t.fldptr.type->type == ev_func) { think_sym->type = sym->type->t.fldptr.type; } else { - think_sym->type = &type_function; + think_sym->type = &type_func; } think_sym = function_symbol (think_sym, 0, 1); make_function (think_sym, 0, current_symtab->space, current_storage); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 08a397651..b20d38cf5 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -590,7 +590,7 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, if (sym->sy_type != sy_func) { error (0, "%s is not a function", sym->name); - sym = new_symbol_type (sym->name, &type_function); + sym = new_symbol_type (sym->name, &type_func); sym = function_symbol (sym, 1, 1); } if (sym->s.func && sym->s.func->def && sym->s.func->def->initialized) { diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 67df1d3fb..6fa038370 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -585,9 +585,9 @@ def_t * emit_methods (methodlist_t *methods, const char *name, int instance) { static struct_def_t methods_struct[] = { - {"method_next", &type_pointer, emit_methods_next}, - {"method_count", &type_int, emit_methods_count}, - {"method_list", 0, emit_methods_list_item}, + {"method_next", &type_ptr, emit_methods_next}, + {"method_count", &type_int, emit_methods_count}, + {"method_list", 0, emit_methods_list_item}, {0, 0} }; const char *type = instance ? "INSTANCE" : "CLASS"; diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index c53965993..ed742fc52 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -379,7 +379,7 @@ static keyword_t qf_keywords[] = { {"int", TYPE, &type_int }, {"unsigned", TYPE, &type_int },//FIXME - {"@function", TYPE, &type_function }, + {"@function", TYPE, &type_func }, {"@args", ARGS, 0 }, {"@va_list", TYPE, &type_va_list }, {"@param", TYPE, &type_param }, diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 9428e64d2..d5b385f14 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -955,7 +955,7 @@ dereference_dst: s = new_statement (st_expr, "&", dst_expr); s->opa = dst; s->opb = ofs; - s->opc = temp_operand (&type_pointer, dst_expr); + s->opc = temp_operand (&type_ptr, dst_expr); sblock_add_statement (sblock, s); dst = s->opc; ofs = 0; @@ -1128,7 +1128,7 @@ lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) statement_t *s = new_statement (st_expr, "&", e); s->opa = pointer; s->opb = offset; - s->opc = temp_operand (&type_pointer, e); + s->opc = temp_operand (&type_ptr, e); return s; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index fed6f0e1d..77e0a1e54 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -69,11 +69,9 @@ type_t type_vector = { ev_vector, "vector", 1 }; type_t type_entity = { ev_entity, "entity", 1 }; type_t type_field = {ev_field, "field", 1, ty_basic, {{&type_void}} }; -// type_function is a void() function used for state defs -type_t type_function = { ev_func, "function", 1, ty_basic, - {{&type_void}} }; -type_t type_pointer = { ev_ptr, "pointer", 1, ty_basic, - {{&type_void}} }; +// type_func is a void() function used for state defs +type_t type_func = { ev_func, "func", 1, ty_basic, {{&type_void}} }; +type_t type_ptr = { ev_ptr, "pointer", 1, ty_basic, {{&type_void}} }; type_t type_quaternion = { ev_quaternion, "quaternion", 4 }; type_t type_int = { ev_int, "int", 1 }; type_t type_uint = { ev_uint, "uint", 1 }; @@ -1141,8 +1139,8 @@ chain_basic_types (void) type_entity.t.symtab = pr.entity_fields; chain_type (&type_entity); chain_type (&type_field); - chain_type (&type_function); - chain_type (&type_pointer); + chain_type (&type_func); + chain_type (&type_ptr); chain_type (&type_floatfield); if (!options.traditional) { chain_type (&type_quaternion); @@ -1180,8 +1178,8 @@ init_types (void) {"float_val", &type_float}, {"entity_val", &type_entity}, {"field_val", &type_field}, - {"func_val", &type_function}, - {"pointer_val", &type_pointer}, + {"func_val", &type_func}, + {"pointer_val", &type_ptr}, {"vector_val", &type_vector}, {"int_val", &type_int}, {"uint_val", &type_uint}, @@ -1197,8 +1195,8 @@ init_types (void) {"vector_val", &type_vector}, {"entity_val", &type_entity}, {"field_val", &type_field}, - {"func_val", &type_function}, - {"pointer_val", &type_pointer}, + {"func_val", &type_func}, + {"pointer_val", &type_ptr}, {"int_val", &type_int}, {"uint_val", &type_uint}, {"quaternion_val", &type_quaternion}, @@ -1217,13 +1215,13 @@ init_types (void) {0, 0} }; static struct_def_t type_encoding_struct[] = { - {"types", &type_pointer}, + {"types", &type_ptr}, {"size", &type_uint}, {0, 0} }; static struct_def_t xdef_struct[] = { - {"types", &type_pointer}, - {"offset", &type_pointer}, + {"types", &type_ptr}, + {"offset", &type_ptr}, {0, 0} }; static struct_def_t xdefs_struct[] = { diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 7cdc55782..f96e5c720 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -505,11 +505,11 @@ emit_value (ex_value_t *value, def_t *def) break; case ev_func: tab = func_imm_defs; - type = &type_function; + type = &type_func; break; case ev_ptr: tab = pointer_imm_defs; - type = &type_pointer; + type = &type_ptr; break; case ev_int: case ev_uint: From 8d20997b2b2b3727e3bff65d6de95eeac66d046b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 22:58:26 +0900 Subject: [PATCH 2223/3664] [gamecode] Move pr_void_t to pr_comp.h I think I had decided to put it there but forgot before committing the size change, but I wound up needing it for qfcc. --- include/QF/progs/pr_comp.h | 2 ++ libs/gamecode/pr_opcode.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 5d66fc323..22d7e0dc8 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -534,6 +534,8 @@ typedef union pr_type_u { pr_uint_t uint_var; } pr_type_t; +typedef pr_type_t pr_void_t; // so size of void is 1 + typedef struct pr_va_list_s { pr_int_t count; pr_ptr_t list; // pr_type_t diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index c056297a9..799066c7c 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -33,8 +33,6 @@ #include "QF/progs.h" -typedef pr_type_t pr_void_t; // so size of void is 1 - #define EV_TYPE(type) (sizeof (pr_##type##_t) / sizeof (pr_int_t)), VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { #include "QF/progs/pr_type_names.h" From 17add5e00f9b091fb89c747e4fbb2885db2c8afc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 18 Jan 2022 22:59:53 +0900 Subject: [PATCH 2224/3664] [qfcc] Use pr_type_names to create basic type defs This takes care of the type structs and the ev_* to type map. --- tools/qfcc/include/type.h | 16 +++----------- tools/qfcc/source/type.c | 44 +++++++++++++-------------------------- 2 files changed, 17 insertions(+), 43 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 87ca80966..a28d729c6 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -96,21 +96,11 @@ typedef struct { unsigned nosave:1; } specifier_t; +#define EV_TYPE(type) extern type_t type_##type; +#include "QF/progs/pr_type_names.h" + extern type_t type_invalid; -extern type_t type_void; -extern type_t type_string; -extern type_t type_double; -extern type_t type_float; -extern type_t type_vector; -extern type_t type_entity; -extern type_t type_field; -extern type_t type_function; -extern type_t type_pointer; extern type_t type_floatfield; -extern type_t type_quaternion; -extern type_t type_int; -extern type_t type_uint; -extern type_t type_short; extern type_t *type_nil; // for passing nil into ... extern type_t *type_default; // default type (float or int) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 77e0a1e54..dcdde6c7b 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -60,23 +60,19 @@ #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" -// simple types. function types are dynamically allocated -type_t type_invalid = { ev_invalid, "invalid" }; -type_t type_void = { ev_void, "void", 1 }; -type_t type_string = { ev_string, "string", 1 }; -type_t type_float = { ev_float, "float", 1 }; -type_t type_vector = { ev_vector, "vector", 1 }; -type_t type_entity = { ev_entity, "entity", 1 }; -type_t type_field = {ev_field, "field", 1, ty_basic, {{&type_void}} }; +#define EV_TYPE(t) \ + type_t type_##t = { \ + .type = ev_##t, \ + .name = #t, \ + .alignment = __alignof__(pr_##t##_t) / __alignof__ (pr_int_t), \ + .meta = ty_basic, \ + {{ __builtin_choose_expr (ev_##t == ev_field \ + || ev_##t == ev_func \ + || ev_##t == ev_ptr, &type_void, 0 ) }}, \ + }; +#include "QF/progs/pr_type_names.h" -// type_func is a void() function used for state defs -type_t type_func = { ev_func, "func", 1, ty_basic, {{&type_void}} }; -type_t type_ptr = { ev_ptr, "pointer", 1, ty_basic, {{&type_void}} }; -type_t type_quaternion = { ev_quaternion, "quaternion", 4 }; -type_t type_int = { ev_int, "int", 1 }; -type_t type_uint = { ev_uint, "uint", 1 }; -type_t type_short = { ev_short, "short", 1 }; -type_t type_double = { ev_double, "double", 2 }; +type_t type_invalid = { ev_invalid, "invalid" }; type_t *type_nil; type_t *type_default; @@ -94,21 +90,9 @@ type_t type_xdefs = { ev_invalid, "@xdefs", 0, ty_struct }; type_t type_floatfield = { ev_field, ".float", 1, ty_basic, {{&type_float}} }; +#define EV_TYPE(type) &type_##type, type_t *ev_types[ev_type_count] = { - &type_void, - &type_string, - &type_float, - &type_vector, - &type_entity, - &type_field, - &type_function, - &type_pointer, - &type_quaternion, - &type_int, - &type_uint, - &type_short, - &type_double, - 0, 0, 0, +#include "QF/progs/pr_type_names.h" &type_invalid, }; From 380cb3ba7f8dd49d30f55af938ebd9730028b8f9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Jan 2022 10:52:07 +0900 Subject: [PATCH 2225/3664] [qfcc] Clean up the type tables for binary expressions More index labels and remove the null entries since they're not needed with the labels. --- tools/qfcc/source/expr_binary.c | 240 ++++++++++---------------------- 1 file changed, 71 insertions(+), 169 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index dfd02b5c8..f551cafc7 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -526,211 +526,113 @@ static expr_type_t double_double[] = { }; static expr_type_t *string_x[ev_type_count] = { - 0, // ev_void - string_string, - 0, // ev_float - 0, // ev_vector - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_ptr - 0, // ev_quaternion - 0, // ev_int - 0, // ev_uint - 0, // ev_short - 0, // ev_double + [ev_string] = string_string, }; static expr_type_t *float_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - float_float, - float_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_ptr - float_quat, - float_int, - float_uint, - float_short, - float_double, + [ev_float] = float_float, + [ev_vector] = float_vector, + [ev_quaternion] = float_quat, + [ev_int] = float_int, + [ev_uint] = float_uint, + [ev_short] = float_short, + [ev_double] = float_double, }; static expr_type_t *vector_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - vector_float, - vector_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_ptr - 0, // ev_quaternion - vector_int, - vector_uint, - vector_short, - vector_double, + [ev_float] = vector_float, + [ev_vector] = vector_vector, + [ev_int] = vector_int, + [ev_uint] = vector_uint, + [ev_short] = vector_short, + [ev_double] = vector_double, }; static expr_type_t *entity_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - 0, // ev_float - 0, // ev_vector - entity_entity, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_ptr - 0, // ev_quaternion - 0, // ev_int - 0, // ev_uint - 0, // ev_short - 0, // ev_double + [ev_entity] = entity_entity, }; static expr_type_t *field_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - 0, // ev_float - 0, // ev_vector - 0, // ev_entity - field_field, // ev_field - 0, // ev_func - 0, // ev_ptr - 0, // ev_quaternion - 0, // ev_int - 0, // ev_uint - 0, // ev_short - 0, // ev_double + [ev_field] = field_field, }; static expr_type_t *func_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - 0, // ev_float - 0, // ev_vector - 0, // ev_entity - 0, // ev_field - func_func, // ev_func - 0, // ev_ptr - 0, // ev_quaternion - 0, // ev_int - 0, // ev_uint - 0, // ev_short - 0, // ev_double + [ev_func] = func_func, }; static expr_type_t *pointer_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - 0, // ev_float - 0, // ev_vector - 0, // ev_entity - 0, // ev_field - 0, // ev_func - pointer_pointer, - 0, // ev_quaternion - pointer_int, - pointer_uint, - pointer_short, - 0, // ev_double + [ev_ptr] = pointer_pointer, + [ev_int] = pointer_int, + [ev_uint] = pointer_uint, + [ev_short] = pointer_short, }; static expr_type_t *quat_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - quat_float, - quat_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_ptr - quat_quat, - quat_int, - quat_uint, - quat_short, - quat_double, + [ev_float] = quat_float, + [ev_vector] = quat_vector, + [ev_quaternion] = quat_quat, + [ev_int] = quat_int, + [ev_uint] = quat_uint, + [ev_short] = quat_short, + [ev_double] = quat_double, }; static expr_type_t *int_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - int_float, - int_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - int_pointer, - int_quat, - int_int, - int_uint, - int_short, - int_double, + [ev_float] = int_float, + [ev_vector] = int_vector, + [ev_ptr] = int_pointer, + [ev_quaternion] = int_quat, + [ev_int] = int_int, + [ev_uint] = int_uint, + [ev_short] = int_short, + [ev_double] = int_double, }; static expr_type_t *uint_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - uint_float, - uint_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - uint_pointer, - uint_quat, - uint_int, - uint_uint, - uint_short, - uint_double, + [ev_float] = uint_float, + [ev_vector] = uint_vector, + [ev_ptr] = uint_pointer, + [ev_quaternion] = uint_quat, + [ev_int] = uint_int, + [ev_uint] = uint_uint, + [ev_short] = uint_short, + [ev_double] = uint_double, }; static expr_type_t *short_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - short_float, - short_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - short_pointer, - short_quat, - short_int, - short_uint, - short_short, - short_double, + [ev_float] = short_float, + [ev_vector] = short_vector, + [ev_ptr] = short_pointer, + [ev_quaternion] = short_quat, + [ev_int] = short_int, + [ev_uint] = short_uint, + [ev_short] = short_short, + [ev_double] = short_double, }; static expr_type_t *double_x[ev_type_count] = { - 0, // ev_void - 0, // ev_string - double_float, - double_vector, - 0, // ev_entity - 0, // ev_field - 0, // ev_func - 0, // ev_ptr - double_quat, - double_int, - double_uint, - double_short, - double_double, + [ev_float] = double_float, + [ev_vector] = double_vector, + [ev_quaternion] = double_quat, + [ev_int] = double_int, + [ev_uint] = double_uint, + [ev_short] = double_short, + [ev_double] = double_double, }; static expr_type_t **binary_expr_types[ev_type_count] = { - 0, // ev_void - string_x, - float_x, - vector_x, - entity_x, - field_x, - func_x, - pointer_x, - quat_x, - int_x, - uint_x, - short_x, - double_x + [ev_string] = string_x, + [ev_float] = float_x, + [ev_vector] = vector_x, + [ev_entity] = entity_x, + [ev_field] = field_x, + [ev_func] = func_x, + [ev_ptr] = pointer_x, + [ev_quaternion] = quat_x, + [ev_int] = int_x, + [ev_uint] = uint_x, + [ev_short] = short_x, + [ev_double] = double_x }; static expr_t * From e11fa77a3475b4d43ef19160898c11f7e56a0029 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Jan 2022 17:48:46 +0900 Subject: [PATCH 2226/3664] [qfcc] Use pr_type_names to generate is_TYPE This means basic types will always have a check function automatically. --- tools/qfcc/include/type.h | 17 +---- tools/qfcc/source/class.c | 12 +-- tools/qfcc/source/emit.c | 3 +- tools/qfcc/source/expr.c | 11 ++- tools/qfcc/source/expr_assign.c | 2 +- tools/qfcc/source/expr_binary.c | 8 +- tools/qfcc/source/method.c | 2 +- tools/qfcc/source/type.c | 125 +++----------------------------- 8 files changed, 32 insertions(+), 148 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index a28d729c6..d6d93ede8 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -149,26 +149,17 @@ void dump_dot_type (void *t, const char *filename); const char *encode_params (const type_t *type); void encode_type (struct dstring_s *encoding, const type_t *type); const char *type_get_encoding (const type_t *type); -int is_void (const type_t *type) __attribute__((pure)); + +#define EV_TYPE(t) int is_##t (const type_t *type) __attribute__((pure)); +#include "QF/progs/pr_type_names.h" + int is_enum (const type_t *type) __attribute__((pure)); -int is_int (const type_t *type) __attribute__((pure)); -int is_uint (const type_t *type) __attribute__((pure)); -int is_short (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); -int is_double (const type_t *type) __attribute__((pure)); -int is_float (const type_t *type) __attribute__((pure)); int is_scalar (const type_t *type) __attribute__((pure)); -int is_vector (const type_t *type) __attribute__((pure)); -int is_quaternion (const type_t *type) __attribute__((pure)); int is_math (const type_t *type) __attribute__((pure)); -int is_pointer (const type_t *type) __attribute__((pure)); -int is_field (const type_t *type) __attribute__((pure)); -int is_entity (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); int is_structural (const type_t *type) __attribute__((pure)); -int is_func (const type_t *type) __attribute__((pure)); -int is_string (const type_t *type) __attribute__((pure)); int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); int type_same (const type_t *dst, const type_t *src) __attribute__((pure)); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 4f9b2e8fe..3f141ede9 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -391,7 +391,7 @@ is_method_description (const type_t *type) static protocollist_t * obj_get_class_protos (const type_t *type) { - if (is_pointer (type)) + if (is_ptr (type)) type = type->t.fldptr.type; if (is_class (type)) return type->t.class->protocols; @@ -401,7 +401,7 @@ obj_get_class_protos (const type_t *type) static protocollist_t * obj_get_protos (const type_t *type) { - if (is_pointer (type)) + if (is_ptr (type)) type = type->t.fldptr.type; return type->protos; } @@ -409,7 +409,7 @@ obj_get_protos (const type_t *type) static category_t * obj_get_categories (const type_t *type) { - if (is_pointer (type)) + if (is_ptr (type)) type = type->t.fldptr.type; if (is_class (type)) return type->t.class->categories; @@ -430,7 +430,7 @@ obj_classname (const type_t *type) } else if (is_Class (type)) { dstring_copystr (str, "Class"); } else { - if (is_pointer (type)) + if (is_ptr (type)) type = type->t.fldptr.type; if (is_class (type)) dstring_copystr (str, type->t.class->name); @@ -1738,7 +1738,7 @@ emit_protocol (protocol_t *protocol) static void emit_protocol_next (def_t *def, void *data, int index) { - if (!is_pointer(def->type)) { + if (!is_ptr(def->type)) { internal_error (0, "%s: expected pointer def", __FUNCTION__); } D_INT (def) = 0; @@ -1761,7 +1761,7 @@ emit_protocol_list_item (def_t *def, void *data, int index) protocollist_t *protocols = (protocollist_t *) data; protocol_t *protocol = protocols->list[index]; - if (!is_array (def->type) || !is_pointer(def->type->t.array.type)) { + if (!is_array (def->type) || !is_ptr(def->type->t.array.type)) { internal_error (0, "%s: expected array of pointer def", __FUNCTION__); } if (index < 0 || index >= protocols->count) { diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 10c7054f9..dc5bb4b2d 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -90,8 +90,7 @@ get_value_def (expr_t *expr, ex_value_t *value, type_t *type) def->offset = value->v.short_val; return def; } - if (is_pointer (type) && value->v.pointer.tempop - && !value->v.pointer.def) { + if (is_ptr (type) && value->v.pointer.tempop && !value->v.pointer.def) { value->v.pointer.def = get_tempop_def (expr, value->v.pointer.tempop, type->t.fldptr.type); } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index fe9c2f03f..df684e288 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2816,15 +2816,14 @@ cast_expr (type_t *dstType, expr_t *e) if ((dstType == type_default && is_enum (srcType)) || (is_enum (dstType) && srcType == type_default)) return e; - if ((is_pointer (dstType) && is_string (srcType)) - || (is_string (dstType) && is_pointer (srcType))) { + if ((is_ptr (dstType) && is_string (srcType)) + || (is_string (dstType) && is_ptr (srcType))) { c = new_alias_expr (dstType, e); return c; } - if (!(is_pointer (dstType) - && (is_pointer (srcType) || is_integral (srcType) - || is_array (srcType))) - && !(is_integral (dstType) && is_pointer (srcType)) + if (!(is_ptr (dstType) && (is_ptr (srcType) || is_integral (srcType) + || is_array (srcType))) + && !(is_integral (dstType) && is_ptr (srcType)) && !(is_func (dstType) && is_func (srcType)) && !(is_scalar (dstType) && is_scalar (srcType))) { return cast_error (e, srcType, dstType); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index a961e113d..4eec4916a 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -329,7 +329,7 @@ assign_expr (expr_t *dst, expr_t *src) internal_error (src, "src_type broke in assign_expr"); } - if (is_pointer (dst_type) && is_array (src_type)) { + if (is_ptr (dst_type) && is_array (src_type)) { // assigning an array to a pointer is the same as taking the address of // the array but using the type of the array elements src = address_expr (src, 0, src_type->t.fldptr.type); diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index f551cafc7..b647db7e6 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -646,10 +646,10 @@ pointer_arithmetic (int op, expr_t *e1, expr_t *e2) expr_t *psize; type_t *ptype; - if (!is_pointer (t1) && !is_pointer (t2)) { + if (!is_ptr (t1) && !is_ptr (t2)) { internal_error (e1, "pointer arithmetic on non-pointers"); } - if (is_pointer (t1) && is_pointer (t2)) { + if (is_ptr (t1) && is_ptr (t2)) { if (op != '-') { return error (e2, "invalid pointer operation"); } @@ -661,11 +661,11 @@ pointer_arithmetic (int op, expr_t *e1, expr_t *e2) e2 = cast_expr (&type_int, e2); psize = new_int_expr (type_size (t1->t.fldptr.type)); return binary_expr ('/', binary_expr ('-', e1, e2), psize); - } else if (is_pointer (t1)) { + } else if (is_ptr (t1)) { offset = cast_expr (&type_int, e2); ptr = cast_expr (&type_int, e1); ptype = t1; - } else if (is_pointer (t2)) { + } else if (is_ptr (t2)) { offset = cast_expr (&type_int, e1); ptr = cast_expr (&type_int, e2); ptype = t2; diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 6fa038370..2cb88ba03 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -533,7 +533,7 @@ emit_selectors (void) static void emit_methods_next (def_t *def, void *data, int index) { - if (!is_pointer(def->type)) + if (!is_ptr(def->type)) internal_error (0, "%s: expected pointer def", __FUNCTION__); D_INT (def) = 0; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index dcdde6c7b..3f4774f30 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -554,7 +554,7 @@ unalias_type (const type_t *type) const type_t * dereference_type (const type_t *type) { - if (!is_pointer (type) && !is_field (type)) { + if (!is_ptr (type) && !is_field (type)) { internal_error (0, "dereference non pointer/field type"); } if (type->meta == ty_alias) { @@ -836,12 +836,13 @@ encode_type (dstring_t *encoding, const type_t *type) internal_error (0, "bad type meta:type %d:%d", type->meta, type->type); } -int -is_void (const type_t *type) -{ - type = unalias_type (type); - return type->type == ev_void; +#define EV_TYPE(t) \ +int is_##t (const type_t *type) \ +{ \ + type = unalias_type (type); \ + return type->type == ev_##t; \ } +#include "QF/progs/pr_type_names.h" int is_enum (const type_t *type) @@ -852,39 +853,6 @@ is_enum (const type_t *type) return 0; } -int -is_int (const type_t *type) -{ - type = unalias_type (type); - etype_t t = type->type; - - if (t == ev_int) - return 1; - return is_enum (type); -} - -int -is_uint (const type_t *type) -{ - type = unalias_type (type); - etype_t t = type->type; - - if (t == ev_uint) - return 1; - return is_enum (type); -} - -int -is_short (const type_t *type) -{ - type = unalias_type (type); - etype_t t = type->type; - - if (t == ev_short) - return 1; - return is_enum (type); -} - int is_integral (const type_t *type) { @@ -894,20 +862,6 @@ is_integral (const type_t *type) return is_enum (type); } -int -is_double (const type_t *type) -{ - type = unalias_type (type); - return type->type == ev_double; -} - -int -is_float (const type_t *type) -{ - type = unalias_type (type); - return type->type == ev_float; -} - int is_scalar (const type_t *type) { @@ -915,20 +869,6 @@ is_scalar (const type_t *type) return is_float (type) || is_integral (type) || is_double (type); } -int -is_vector (const type_t *type) -{ - type = unalias_type (type); - return type->type == ev_vector; -} - -int -is_quaternion (const type_t *type) -{ - type = unalias_type (type); - return type->type == ev_quaternion; -} - int is_math (const type_t *type) { @@ -948,33 +888,6 @@ is_struct (const type_t *type) return 0; } -int -is_pointer (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_ptr) - return 1; - return 0; -} - -int -is_field (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_field) - return 1; - return 0; -} - -int -is_entity (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_entity) - return 1; - return 0; -} - int is_array (const type_t *type) { @@ -984,15 +897,6 @@ is_array (const type_t *type) return 0; } -int -is_func (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_func) - return 1; - return 0; -} - int is_structural (const type_t *type) { @@ -1000,15 +904,6 @@ is_structural (const type_t *type) return is_struct (type) || is_array (type); } -int -is_string (const type_t *type) -{ - type = unalias_type (type); - if (type->type == ev_string) - return 1; - return 0; -} - int type_compatible (const type_t *dst, const type_t *src) { @@ -1022,7 +917,7 @@ type_compatible (const type_t *dst, const type_t *src) if (is_func (dst) && is_func (src)) { return 1; } - if (is_pointer (dst) && is_pointer (src)) { + if (is_ptr (dst) && is_ptr (src)) { return 1; } return 0; @@ -1042,12 +937,12 @@ type_assignable (const type_t *dst, const type_t *src) if (dst->type == ev_field && src->type == ev_field) return 1; // pointer = array - if (is_pointer (dst) && is_array (src)) { + if (is_ptr (dst) && is_array (src)) { if (dst->t.fldptr.type == src->t.array.type) return 1; return 0; } - if (!is_pointer (dst) || !is_pointer (src)) + if (!is_ptr (dst) || !is_ptr (src)) return is_scalar (dst) && is_scalar (src); // pointer = pointer From df890432b730c86125031d35bac3503c982e22a2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Jan 2022 18:08:58 +0900 Subject: [PATCH 2227/3664] [qfcc] Add support for unsigned, long, etc long is ignored for double, and v6p progs are stuck with 32 bits for longs (don't feel like extending v6p any further), but the basics are there for Ruamoko. short is ignored for ints because the minimum size is 32, and signed is just noise for ints anyway (and no chars, so...). unsigned, however, is finally implemented properly (or at least seems to be working correctly: tests pass after getting things compiling again, and lt.u is used where it should be :) --- libs/video/renderer/vulkan/vkgen/stdint.h | 1 - tools/qfcc/include/type.h | 2 + tools/qfcc/source/expr_binary.c | 72 ++++++------- tools/qfcc/source/opcodes.c | 80 +++++++++++++-- tools/qfcc/source/qc-lex.l | 5 +- tools/qfcc/source/qc-parse.y | 119 ++++++++++++++++++---- tools/qfcc/source/type.c | 10 ++ 7 files changed, 225 insertions(+), 64 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/stdint.h b/libs/video/renderer/vulkan/vkgen/stdint.h index 04fc06933..e343a15b5 100644 --- a/libs/video/renderer/vulkan/vkgen/stdint.h +++ b/libs/video/renderer/vulkan/vkgen/stdint.h @@ -7,5 +7,4 @@ typedef int int16_t; typedef int int32_t; typedef int int64_t; typedef int size_t; -typedef int long; typedef int char; diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index d6d93ede8..4a65b3384 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -104,6 +104,8 @@ extern type_t type_floatfield; extern type_t *type_nil; // for passing nil into ... extern type_t *type_default; // default type (float or int) +extern type_t *type_long_int; // supported type for long +extern type_t *type_ulong_uint;// supported type for ulong extern type_t type_va_list; extern type_t type_param; diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index b647db7e6..27e7f1ff8 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -290,23 +290,23 @@ static expr_type_t int_int[] = { }; static expr_type_t int_uint[] = { - {'+', &type_int}, - {'-', &type_int}, - {'*', &type_int}, - {'/', &type_int}, - {'&', &type_int}, - {'|', &type_int}, - {'^', &type_int}, - {'%', &type_int}, - {MOD, &type_int}, - {SHL, &type_int}, - {SHR, &type_int}, - {EQ, &type_int}, - {NE, &type_int}, - {LE, &type_int}, - {GE, &type_int}, - {LT, &type_int}, - {GT, &type_int}, + {'+', &type_int, 0, &type_int}, + {'-', &type_int, 0, &type_int}, + {'*', &type_int, 0, &type_int}, + {'/', &type_int, 0, &type_int}, + {'&', &type_int, 0, &type_int}, + {'|', &type_int, 0, &type_int}, + {'^', &type_int, 0, &type_int}, + {'%', &type_int, 0, &type_int}, + {MOD, &type_int, 0, &type_int}, + {SHL, &type_int, 0, &type_int}, + {SHR, &type_int, 0, &type_int}, + {EQ, &type_int, 0, &type_int}, + {NE, &type_int, 0, &type_int}, + {LE, &type_int, 0, &type_int}, + {GE, &type_int, 0, &type_int}, + {LT, &type_int, 0, &type_int}, + {GT, &type_int, 0, &type_int}, {0, 0} }; @@ -353,23 +353,23 @@ static expr_type_t int_double[] = { #define uint_quat int_quat static expr_type_t uint_int[] = { - {'+', &type_int}, - {'-', &type_int}, - {'*', &type_int}, - {'/', &type_int}, - {'&', &type_int}, - {'|', &type_int}, - {'^', &type_int}, - {'%', &type_int}, - {MOD, &type_int}, - {SHL, &type_uint}, - {SHR, &type_uint}, - {EQ, &type_int}, - {NE, &type_int}, - {LE, &type_int}, - {GE, &type_int}, - {LT, &type_int}, - {GT, &type_int}, + {'+', &type_int, &type_int, &type_int }, + {'-', &type_int, &type_int, &type_int }, + {'*', &type_int, &type_int, &type_int }, + {'/', &type_int, &type_int, &type_int }, + {'&', &type_int, &type_int, &type_int }, + {'|', &type_int, &type_int, &type_int }, + {'^', &type_int, &type_int, &type_int }, + {'%', &type_int, &type_int, &type_int }, + {MOD, &type_int, &type_int, &type_int }, + {SHL, &type_uint, &type_int, &type_int }, + {SHR, &type_uint, 0, &type_int }, + {EQ, &type_int, &type_int, &type_int }, + {NE, &type_int, &type_int, &type_int }, + {LE, &type_int, &type_int, &type_int }, + {GE, &type_int, &type_int, &type_int }, + {LT, &type_int, &type_int, &type_int }, + {GT, &type_int, &type_int, &type_int }, {0, 0} }; @@ -385,8 +385,8 @@ static expr_type_t uint_uint[] = { {MOD, &type_uint}, {SHL, &type_uint}, {SHR, &type_uint}, - {EQ, &type_int}, - {NE, &type_int}, + {EQ, &type_int, &type_int, &type_int}, + {NE, &type_int, &type_int, &type_int}, {LE, &type_int}, {GE, &type_int}, {LT, &type_int}, diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 47accd2c3..9ac87ea10 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -47,8 +47,38 @@ #include "tools/qfcc/include/statements.h" #include "tools/qfcc/include/type.h" +typedef struct v6p_uint_opcode_s { + pr_opcode_v6p_e op; + v6p_opcode_t opcode; +} v6p_uint_opcode_t; + +static v6p_uint_opcode_t v6p_uint_opcodes[] = { + {OP_LOAD_I_v6p, {".", "load.i", ev_entity, ev_field, ev_uint }}, + {OP_LOADBI_I_v6p, {".", "loadbi.i", ev_ptr, ev_short, ev_uint }}, + {OP_ADDRESS_I_v6p, {"&", "address.i", ev_uint, ev_invalid, ev_ptr }}, + {OP_STORE_I_v6p, {"=", "store.i", ev_uint, ev_uint, ev_invalid }}, + {OP_STOREP_I_v6p, {".=", "storep.i", ev_uint, ev_ptr, ev_invalid }}, + {OP_STOREB_I_v6p, {".=", "storeb.i", ev_uint, ev_ptr, ev_int }}, + {OP_STOREBI_I_v6p, {".=", "storebi.i", ev_uint, ev_ptr, ev_short }}, + {OP_IF_v6p, {"", "if", ev_uint, ev_short, ev_invalid }}, + {OP_IFNOT_v6p, {"", "ifnot", ev_uint, ev_short, ev_invalid }}, + {OP_ADD_I_v6p, {"+", "add.i", ev_uint, ev_uint, ev_uint }}, + {OP_SUB_I_v6p, {"-", "sub.i", ev_uint, ev_uint, ev_uint }}, + {OP_MUL_I_v6p, {"*", "mul.i", ev_uint, ev_uint, ev_uint }}, + {OP_DIV_I_v6p, {"/", "div.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITAND_I_v6p, {"&", "bitand.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITOR_I_v6p, {"|", "bitor.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITXOR_I_v6p, {"^", "bitxor.i", ev_uint, ev_uint, ev_uint }}, + {OP_REM_I_v6p, {"%", "rem.i", ev_uint, ev_uint, ev_uint }}, + {OP_MOD_I_v6p, {"%%", "mod.i", ev_uint, ev_uint, ev_uint }}, + {OP_SHL_I_v6p, {"<<", "shl.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITNOT_I_v6p, {"<<", "bitnot.i", ev_uint, ev_invalid, ev_int }}, + {} +}; + static hashtab_t *v6p_opcode_type_table; static hashtab_t *v6p_opcode_void_table; +static hashtab_t *v6p_opcode_uint_table; static v6p_opcode_t *v6p_opcode_map; static hashtab_t *rua_opcode_type_table; @@ -86,6 +116,21 @@ v6p_get_key (const void *op, void *unused) return ((v6p_opcode_t *) op)->name; } +static uintptr_t +v6p_uint_get_hash (const void *_op, void *_tab) +{ + __auto_type uint_op = (v6p_uint_opcode_t *) _op; + return v6p_get_hash (&uint_op->opcode, _tab); +} + +static int +v6p_uint_compare (const void *_opa, const void *_opb, void *data) +{ + __auto_type uint_opa = (v6p_uint_opcode_t *) _opa; + __auto_type uint_opb = (v6p_uint_opcode_t *) _opb; + return v6p_compare (&uint_opa->opcode, &uint_opb->opcode, data); +} + static uintptr_t rua_get_hash (const void *_op, void *_tab) { @@ -139,17 +184,25 @@ static v6p_opcode_t * v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) { - v6p_opcode_t search_op = {}; + v6p_uint_opcode_t search_op = { + .opcode = { + .name = name, + .type_a = op_a ? low_level_type (op_a->type) : ev_invalid, + .type_b = op_b ? low_level_type (op_b->type) : ev_invalid, + .type_c = op_c ? low_level_type (op_c->type) : ev_invalid, + }, + }; + v6p_uint_opcode_t *uint_op; v6p_opcode_t *op; v6p_opcode_t *sop; void **op_list; int i; - search_op.name = name; - search_op.type_a = op_a ? low_level_type (op_a->type) : ev_invalid; - search_op.type_b = op_b ? low_level_type (op_b->type) : ev_invalid; - search_op.type_c = op_c ? low_level_type (op_c->type) : ev_invalid; - op = Hash_FindElement (v6p_opcode_type_table, &search_op); + uint_op = Hash_FindElement (v6p_opcode_uint_table, &search_op); + if (uint_op) { + return v6p_opcode_map + uint_op->op; + } + op = Hash_FindElement (v6p_opcode_type_table, &search_op.opcode); if (op) return op; op_list = Hash_FindList (v6p_opcode_void_table, name); @@ -157,9 +210,9 @@ v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, return op; for (i = 0; !op && op_list[i]; i++) { sop = op_list[i]; - if (check_operand_type (sop->type_a, search_op.type_a) - && check_operand_type (sop->type_b, search_op.type_b) - && check_operand_type (sop->type_c, search_op.type_c)) + if (check_operand_type (sop->type_a, search_op.opcode.type_a) + && check_operand_type (sop->type_b, search_op.opcode.type_b) + && check_operand_type (sop->type_c, search_op.opcode.type_c)) op = sop; } free (op_list); @@ -217,10 +270,14 @@ v6p_opcode_init (void) if (v6p_opcode_type_table) { Hash_FlushTable (v6p_opcode_void_table); Hash_FlushTable (v6p_opcode_type_table); + Hash_FlushTable (v6p_opcode_uint_table); } else { v6p_opcode_type_table = Hash_NewTable (1021, 0, 0, 0, 0); Hash_SetHashCompare (v6p_opcode_type_table, v6p_get_hash, v6p_compare); v6p_opcode_void_table = Hash_NewTable (1021, v6p_get_key, 0, 0, 0); + v6p_opcode_uint_table = Hash_NewTable (1021, 0, 0, 0, 0); + Hash_SetHashCompare (v6p_opcode_uint_table, + v6p_uint_get_hash, v6p_uint_compare); } int num_opcodes = 0; @@ -253,6 +310,11 @@ v6p_opcode_init (void) || mop->type_c == ev_void) Hash_Add (v6p_opcode_void_table, mop); } + if (options.code.progsversion != PROG_ID_VERSION) { + for (__auto_type uiop = &v6p_uint_opcodes[0]; uiop->op; uiop++) { + Hash_AddElement (v6p_opcode_uint_table, uiop); + } + } } static void diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index ed742fc52..6a9121e64 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -377,7 +377,10 @@ static keyword_t qf_keywords[] = { {"quaternion", TYPE, &type_quaternion}, {"double", TYPE, &type_double}, {"int", TYPE, &type_int }, - {"unsigned", TYPE, &type_int },//FIXME + {"unsigned", UNSIGNED, 0 }, + {"signed", SIGNED, 0 }, + {"long", LONG, 0 }, + {"short", SHORT, 0 }, {"@function", TYPE, &type_func }, {"@args", ARGS, 0 }, diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 454c8fcfc..26e6f1f38 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -148,6 +148,7 @@ int yylex (void); %token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS %token NIL GOTO SWITCH CASE DEFAULT ENUM %token ARGS TYPEDEF EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT +%token UNSIGNED SIGNED LONG SHORT %token STRUCT %token TYPE %token OBJECT TYPE_NAME @@ -253,6 +254,23 @@ spec_merge (specifier_t spec, specifier_t new) spec.storage = new.storage; spec.is_typedef = new.is_typedef; } + if ((new.is_unsigned && spec.is_signed) + || (new.is_signed && spec.is_unsigned)) { + if (!spec.multi_type) { + error (0, "both signed and unsigned in declaration specifiers"); + spec.multi_type = 1; + } + } + if ((new.is_long && spec.is_short) || (new.is_short && spec.is_long)) { + if (!spec.multi_store) { + error (0, "both long and short in declaration specifiers"); + spec.multi_store = 1; + } + } + spec.is_signed |= new.is_signed; + spec.is_unsigned |= new.is_unsigned; + spec.is_short |= new.is_short; + spec.is_long |= new.is_long; spec.is_overload |= new.is_overload; spec.nosave |= new.nosave; return spec; @@ -261,6 +279,59 @@ spec_merge (specifier_t spec, specifier_t new) static specifier_t default_type (specifier_t spec, symbol_t *sym) { + if (spec.type) { + if (is_float (spec.type) && !spec.multi_type) { + // no modifieres allowed + if (spec.is_unsigned) { + spec.multi_type = 1; + error (0, "both unsigned and float in declaration specifiers"); + } else if (spec.is_signed) { + spec.multi_type = 1; + error (0, "both signed and float in declaration specifiers"); + } else if (spec.is_short) { + spec.multi_type = 1; + error (0, "both short and float in declaration specifiers"); + } else if (spec.is_long) { + spec.multi_type = 1; + error (0, "both long and float in declaration specifiers"); + } + } + if (is_double (spec.type)) { + // long is allowed but ignored + if (spec.is_unsigned) { + spec.multi_type = 1; + error (0, "both unsigned and double in declaration specifiers"); + } else if (spec.is_signed) { + spec.multi_type = 1; + error (0, "both signed and double in declaration specifiers"); + } else if (spec.is_short) { + spec.multi_type = 1; + error (0, "both short and double in declaration specifiers"); + } + } + if (is_int (spec.type)) { + // signed and short are ignored + if (spec.is_unsigned && spec.is_long) { + spec.type = &type_ulong; + } else if (spec.is_long) { + spec.type = &type_long; + } + } + } else { + if (spec.is_long) { + if (spec.is_unsigned) { + spec.type = type_ulong_uint; + } else { + spec.type = type_long_int; + } + } else { + if (spec.is_unsigned) { + spec.type = &type_uint; + } else if (spec.is_signed) { + spec.type = &type_int; + } + } + } if (!spec.type) { spec.type = type_default; warning (0, "type defaults to '%s' in declaration of '%s'", @@ -414,11 +485,10 @@ function_body : optional_state_expr { symbol_t *sym = $0; + specifier_t spec = default_type ($-1, sym); - if (!$-1.type) - $-1.type = type_default; - sym->type = find_type (append_type (sym->type, $-1.type)); - $$ = function_symbol (sym, $-1.is_overload, 1); + sym->type = find_type (append_type (sym->type, spec.type)); + $$ = function_symbol (sym, spec.is_overload, 1); } save_storage { @@ -438,12 +508,11 @@ function_body | '=' '#' expr ';' { symbol_t *sym = $0; + specifier_t spec = default_type ($-1, sym); - if (!$-1.type) - $-1.type = type_default; - sym->type = find_type (append_type (sym->type, $-1.type)); - sym = function_symbol (sym, $-1.is_overload, 1); - build_builtin_function (sym, $3, 0, $-1.storage); + sym->type = find_type (append_type (sym->type, spec.type)); + sym = function_symbol (sym, spec.is_overload, 1); + build_builtin_function (sym, $3, 0, spec.storage); } ; @@ -556,6 +625,26 @@ type_specifier { $$ = make_spec ($1, 0, 0, 0); } + | UNSIGNED + { + $$ = make_spec (0, current_storage, 0, 0); + $$.is_unsigned = 1; + } + | SIGNED + { + $$ = make_spec (0, current_storage, 0, 0); + $$.is_signed = 1; + } + | LONG + { + $$ = make_spec (0, current_storage, 0, 0); + $$.is_long = 1; + } + | SHORT + { + $$ = make_spec (0, current_storage, 0, 0); + $$.is_short = 1; + } | enum_specifier | struct_specifier | TYPE_NAME @@ -768,8 +857,7 @@ struct_decl_list struct_decl : function_decl { - if (!$0.type) - $0.type = type_default; + $0 = default_type ($-0, $1); $1->type = find_type (append_type ($1->type, $0.type)); $1->sy_type = sy_var; $1->visibility = current_visibility; @@ -780,8 +868,7 @@ struct_decl } | var_decl { - if (!$0.type) - $0.type = type_default; + $0 = default_type ($-0, $1); $1->type = find_type (append_type ($1->type, $0.type)); $1->sy_type = sy_var; $1->visibility = current_visibility; @@ -900,8 +987,7 @@ qc_var_list param_declaration : type var_decl { - if (!$1.type) - $1.type = type_default; + $1 = default_type ($1, $2); $2->type = find_type (append_type ($2->type, $1.type)); $$ = new_param (0, $2->type, $2->name); } @@ -913,8 +999,7 @@ abstract_decl : type abs_decl { $$ = $2; - if (!$1.type) - $1.type = type_default; + $1 = default_type ($1, $2); $$->type = find_type (append_type ($$->type, $1.type)); } | error { $$ = new_symbol (""); } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 3f4774f30..76a8e5976 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -76,6 +76,8 @@ type_t type_invalid = { ev_invalid, "invalid" }; type_t *type_nil; type_t *type_default; +type_t *type_long_int; +type_t *type_ulong_uint; // these will be built up further type_t type_va_list = { ev_invalid, 0, 0, ty_struct }; @@ -1118,6 +1120,14 @@ init_types (void) type_nil = &type_quaternion; type_default = &type_int; + type_long_int = &type_long; + type_ulong_uint = &type_ulong; + if (options.code.progsversion < PROG_VERSION) { + // even v6p doesn't support long, and I don't feel like adding it + // use ruamoko :P + type_long_int = &type_int; + type_ulong_uint = &type_uint; + } if (options.code.progsversion == PROG_ID_VERSION) { // vector can't be part of .zero for v6 progs because for v6 progs, // .zero is only one word wide. From 9f42cf726bb4243f236afb0c2a32290916ad8abd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Jan 2022 21:18:34 +0900 Subject: [PATCH 2228/3664] [qfcc] Clean up duplicate specifier check code I don't like the name, but having two identical copies of code is never a good thing, especially something that big. --- tools/qfcc/source/qc-parse.y | 55 +++++++++++++++--------------------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 26e6f1f38..b087c69df 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -367,6 +367,27 @@ is_null_spec (specifier_t spec) return memcmp (&spec, &null_spec, sizeof (spec)) == 0; } +static void +check_specifiers (specifier_t spec) +{ + if (!is_null_spec (spec)) { + if (!spec.type && !spec.sym) { + warning (0, "useless specifiers"); + } else if (spec.type && !spec.sym) { + if (is_anonymous_struct (spec)){ + warning (0, "unnamed struct/union that defines " + "no instances"); + } else if (!is_enum (spec.type) && !is_struct (spec.type)) { + warning (0, "useless type name in empty declaration"); + } + } else if (!spec.type && spec.sym) { + bug (0, "wha? %p %p", spec.type, spec.sym); + } else { + bug (0, "wha? %p %p", spec.type, spec.sym); + } + } +} + %} %expect 0 @@ -417,22 +438,7 @@ external_def : optional_specifiers external_decl_list ';' { } | optional_specifiers ';' { - if (!is_null_spec ($1)) { - if (!$1.type && !$1.sym) { - warning (0, "useless specifiers"); - } else if ($1.type && !$1.sym) { - if (is_anonymous_struct ($1)){ - warning (0, "unnamed struct/union that defines " - "no instances"); - } else if (!is_enum ($1.type) && !is_struct ($1.type)) { - warning (0, "useless type name in empty declaration"); - } - } else if (!$1.type && $1.sym) { - bug (0, "wha? %p %p", $1.type, $1.sym); - } else { - bug (0, "wha? %p %p", $1.type, $1.sym); - } - } + check_specifiers ($1); } | optional_specifiers qc_func_params { @@ -1329,22 +1335,7 @@ local_def } | specifiers ';' { - if (!is_null_spec ($1)) { - if (!$1.type && !$1.sym) { - warning (0, "useless specifiers"); - } else if ($1.type && !$1.sym) { - if (is_anonymous_struct ($1)){ - warning (0, "unnamed struct/union that defines " - "no instances"); - } else if (!is_enum ($1.type) && !is_struct ($1.type)) { - warning (0, "useless type name in empty declaration"); - } - } else if (!$1.type && $1.sym) { - bug (0, "wha? %p %p", $1.type, $1.sym); - } else { - bug (0, "wha? %p %p", $1.type, $1.sym); - } - } + check_specifiers ($1); $$ = 0; } ; From 07c4d28638ebb93e5601c1513ed1b6f6a731bcc7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Jan 2022 21:21:27 +0900 Subject: [PATCH 2229/3664] [qfcc] Handle bare "short" Missed this case in duplicate_type. Allows "short foo" and "sizeof(short)" (even though qfcc and the engine have two ideas of the size: I expect trouble later). --- tools/qfcc/source/qc-parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index b087c69df..cecf04866 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -327,7 +327,7 @@ default_type (specifier_t spec, symbol_t *sym) } else { if (spec.is_unsigned) { spec.type = &type_uint; - } else if (spec.is_signed) { + } else if (spec.is_signed || spec.is_short) { spec.type = &type_int; } } From 4ae94743968ce3928ced94ebc65a0c1ffb5c9003 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Jan 2022 21:26:44 +0900 Subject: [PATCH 2230/3664] [ruamoko] Use pr_type_names for type sizes short and ushort are "wrong" (1 instead of 0, because qfcc currently uses int for short), but now the array will always be in sync with the enum. --- ruamoko/lib/types.r | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/ruamoko/lib/types.r b/ruamoko/lib/types.r index 0445e0510..7c27914ff 100644 --- a/ruamoko/lib/types.r +++ b/ruamoko/lib/types.r @@ -12,25 +12,15 @@ string ty_meta_name[7] = { }; //FIXME use pr_type_names.h, but need to fix unsigned, and add missing types -//#define EV_TYPE(type) sizeof(type), +#define field .int +#define func void()(void) +#define ptr void * +#define uint unsigned +#define ulong unsigned long +#define ushort unsigned short +#define EV_TYPE(type) sizeof(type), int pr_type_size[ev_type_count] = { -//#include - 1, // ev_void - 1, // ev_string - 1, // ev_float - 3, // ev_vector - 1, // ev_entity - 1, // ev_field - 1, // ev_func - 1, // ev_ptr - 4, // ev_quat - 1, // ev_integer - 1, // ev_uinteger - 0, // ev_short value in opcode - 2, // ev_double - 2, // ev_long - 2, // ev_ulong - 0, // ev_invalid not a valid/simple type +#include }; #define EV_TYPE(type) #type, From 105d57f5e7ec82695a0c47c95f36b1ec3a50baaa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 19 Jan 2022 21:32:01 +0900 Subject: [PATCH 2231/3664] [qfcc] Improve handling of type names as variables This is allowed in C so long as the scopes are different. --- tools/qfcc/source/qc-lex.l | 12 ++++++++++ tools/qfcc/source/qc-parse.y | 43 +++++++++++++++++++++++++++--------- tools/qfcc/source/symtab.c | 4 +++- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 6a9121e64..7ce445539 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -422,6 +422,18 @@ process_keyword (keyword_t *keyword, const char *token) sym = symtab_lookup (current_symtab, token); qc_yylval.symbol = sym; + // the global id symbol is always just a name so attempts to redefine + // it globally can be caught and treated as an error, but it needs to + // be redefinable when in an enclosing scope. + if (sym->sy_type == sy_name) { + // this is the global id (object) + return OBJECT; + } else if (sym->sy_type == sy_type) { + // id has been redeclared via a typedef + return TYPE_NAME; + } + // id has been redelcared as a variable (hopefully) + return NAME; } else { qc_yylval.type = keyword->type; } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index cecf04866..a9c2ea102 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -267,6 +267,7 @@ spec_merge (specifier_t spec, specifier_t new) spec.multi_store = 1; } } + spec.sym = new.sym; spec.is_signed |= new.is_signed; spec.is_unsigned |= new.is_unsigned; spec.is_short |= new.is_short; @@ -367,6 +368,16 @@ is_null_spec (specifier_t spec) return memcmp (&spec, &null_spec, sizeof (spec)) == 0; } +static int +use_type_name (specifier_t spec) +{ + spec.sym = new_symbol (spec.sym->name); + spec.sym->type = spec.type; + spec.sym->sy_type = sy_var; + symtab_addsymbol (current_symtab, spec.sym); + return !!spec.sym->table; +} + static void check_specifiers (specifier_t spec) { @@ -383,7 +394,12 @@ check_specifiers (specifier_t spec) } else if (!spec.type && spec.sym) { bug (0, "wha? %p %p", spec.type, spec.sym); } else { - bug (0, "wha? %p %p", spec.type, spec.sym); + // a type name (id, typedef, etc) was used as a variable name. + // this is allowed in C, so long as it's in a different scope + if (!use_type_name (spec)) { + error (0, "%s redeclared as different kind of symbol", + spec.sym->name); + } } } } @@ -614,7 +630,9 @@ type // deal with eg "int id" $1.sym = $2.sym; - if (!$1.sym) { + if (!$1.sym && !$1.type) { + $1 = spec_merge ($1, $2); + } else if (!$1.sym) { error (0, "two or more data types in declaration specifiers"); } $$ = $1; @@ -827,11 +845,7 @@ struct_def if ($1.sym && $1.sym->type != $1.type) { // a type name (id, typedef, etc) was used as a field name. // this is allowed in C - $1.sym = new_symbol ($1.sym->name); - $1.sym->type = $1.type; - $1.sym->sy_type = sy_var; - symtab_addsymbol (current_symtab, $1.sym); - if (!$1.sym->table) { + if (!use_type_name ($1)) { error (0, "duplicate field `%s'", $1.sym->name); } } else if (is_anonymous_struct ($1)) { @@ -997,18 +1011,27 @@ param_declaration $2->type = find_type (append_type ($2->type, $1.type)); $$ = new_param (0, $2->type, $2->name); } - | abstract_decl { $$ = new_param (0, $1->type, 0); } + | abstract_decl { $$ = new_param (0, $1->type, $1->name); } | ELLIPSIS { $$ = new_param (0, 0, 0); } ; abstract_decl : type abs_decl { + // abs_decl's symbol is just a carrier for the type + if ($2->name) { + bug (0, "unexpected name in abs_decl"); + } + if ($1.sym) { + $1.sym = new_symbol ($1.sym->name); + $1.sym->type = $2->type; + $2 = $1.sym; + } $$ = $2; $1 = default_type ($1, $2); $$->type = find_type (append_type ($$->type, $1.type)); } - | error { $$ = new_symbol (""); } + | error { $$ = new_symbol (0); } ; qc_param_decl @@ -1035,7 +1058,7 @@ qc_param_decl ; abs_decl - : /* empty */ { $$ = new_symbol (""); } + : /* empty */ { $$ = new_symbol (0); } | '(' abs_decl ')' function_params { $$ = $2; diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index ca08069bf..6261b66ee 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -75,7 +75,9 @@ new_symbol (const char *name) { symbol_t *symbol; ALLOC (256, symbol_t, symbols, symbol); - symbol->name = save_string (name); + if (name) { + symbol->name = save_string (name); + } return symbol; } From 30008aeb1370aacb03ef4427176c89e0db46476e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 00:42:29 +0900 Subject: [PATCH 2232/3664] [qfcc] Fix a missed address expression conversion Found while testing operator renaming. --- tools/qfcc/include/class.h | 1 + tools/qfcc/source/expr_obj.c | 4 ++-- tools/qfcc/source/method.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index ec160e1d9..217227a73 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -94,6 +94,7 @@ extern struct type_s type_object; extern struct type_s type_class; extern struct type_s type_Class; extern struct type_s type_protocol; +extern struct type_s type_selector; extern struct type_s type_SEL; extern struct type_s type_IMP; extern struct type_s type_supermsg; diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index 9c3984055..33eadb742 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -112,8 +112,8 @@ selector_expr (keywordarg_t *selector) reloc_def_def (sel_table->s.def, sel_sym->s.def); } sel_ref = new_symbol_expr (sel_sym); - sel_ref = new_binary_expr ('&', sel_ref, new_short_expr (index)); - sel_ref->e.expr.type = &type_SEL; + sel_ref = new_address_expr (&type_selector, sel_ref, + new_short_expr (index)); expr_t *sel = new_expr (); sel->type = ex_selector; diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 2cb88ba03..b4cae8e08 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -492,7 +492,7 @@ get_selector (expr_t *sel) error (sel, "not a selector"); return 0; } - _sel.index = expr_short (sel->e.expr.e2); + _sel.index = expr_short (sel->e.address.offset); _sel.index /= type_size (type_SEL.t.fldptr.type); return (selector_t *) Hash_FindElement (sel_index_hash, &_sel); } From 143030fec4cfd4a3be06bfc83a90b1a6dafde005 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 09:26:01 +0900 Subject: [PATCH 2233/3664] [gamecode] Use text for all v6p opcode names This makes the v6p instruction table consistent with the ruamoko instruction table, and clears up some of the ugliness with the load, store, and assign instructions (. .= and = are now spelled out). I think I'd still prefer an enum code (faster) but at least this is more readable. --- libs/gamecode/pr_v6p_opcode.c | 584 ++++++++++++++++----------------- tools/qfcc/source/dags.c | 24 +- tools/qfcc/source/flow.c | 24 +- tools/qfcc/source/opcodes.c | 40 +-- tools/qfcc/source/statements.c | 138 ++++---- 5 files changed, 405 insertions(+), 405 deletions(-) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 6b8988474..20f717154 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -62,1412 +62,1412 @@ // 0-7 parameter index (for P) VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { // OP_DONE_v6p is actually the same as OP_RETURN_v6p, the types are bogus - [OP_DONE_v6p] = {"", "done", + [OP_DONE_v6p] = {"done", "done", ev_entity, ev_field, ev_void, PROG_ID_VERSION, "%Va", }, - [OP_MUL_D_v6p] = {"*", "mul.d", + [OP_MUL_D_v6p] = {"mul", "mul.d", ev_double, ev_double, ev_double, PROG_V6P_VERSION, }, - [OP_MUL_F_v6p] = {"*", "mul.f", + [OP_MUL_F_v6p] = {"mul", "mul.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_MUL_V_v6p] = {"*", "mul.v", + [OP_MUL_V_v6p] = {"mul", "mul.v", ev_vector, ev_vector, ev_float, PROG_ID_VERSION, }, - [OP_MUL_FV_v6p] = {"*", "mul.fv", + [OP_MUL_FV_v6p] = {"mul", "mul.fv", ev_float, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_VF_v6p] = {"*", "mul.vf", + [OP_MUL_VF_v6p] = {"mul", "mul.vf", ev_vector, ev_float, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_DV_v6p] = {"*", "mul.dv", + [OP_MUL_DV_v6p] = {"mul", "mul.dv", ev_double, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_VD_v6p] = {"*", "mul.vd", + [OP_MUL_VD_v6p] = {"mul", "mul.vd", ev_vector, ev_double, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_Q_v6p] = {"*", "mul.q", + [OP_MUL_Q_v6p] = {"mul", "mul.q", ev_quaternion, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, - [OP_MUL_FQ_v6p] = {"*", "mul.fq", + [OP_MUL_FQ_v6p] = {"mul", "mul.fq", ev_float, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, - [OP_MUL_QF_v6p] = {"*", "mul.qf", + [OP_MUL_QF_v6p] = {"mul", "mul.qf", ev_quaternion, ev_float, ev_quaternion, PROG_V6P_VERSION, }, - [OP_MUL_DQ_v6p] = {"*", "mul.dq", + [OP_MUL_DQ_v6p] = {"mul", "mul.dq", ev_double, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, - [OP_MUL_QD_v6p] = {"*", "mul.qd", + [OP_MUL_QD_v6p] = {"mul", "mul.qd", ev_quaternion, ev_double, ev_quaternion, PROG_V6P_VERSION, }, - [OP_MUL_QV_v6p] = {"*", "mul.qv", + [OP_MUL_QV_v6p] = {"mul", "mul.qv", ev_quaternion, ev_vector, ev_vector, PROG_V6P_VERSION, }, - [OP_CONJ_Q_v6p] = {"~", "conj.q", + [OP_CONJ_Q_v6p] = {"conj", "conj.q", ev_quaternion, ev_invalid, ev_quaternion, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_DIV_F_v6p] = {"/", "div.f", + [OP_DIV_F_v6p] = {"div", "div.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_DIV_D_v6p] = {"/", "div.d", + [OP_DIV_D_v6p] = {"div", "div.d", ev_double, ev_double, ev_double, PROG_V6P_VERSION, }, - [OP_REM_D_v6p] = {"%", "rem.d", + [OP_REM_D_v6p] = {"rem", "rem.d", ev_double, ev_double, ev_double, PROG_V6P_VERSION, }, - [OP_MOD_D_v6p] = {"%%", "mod.d", + [OP_MOD_D_v6p] = {"mod", "mod.d", ev_double, ev_double, ev_double, PROG_V6P_VERSION, }, - [OP_ADD_D_v6p] = {"+", "add.d", + [OP_ADD_D_v6p] = {"add", "add.d", ev_double, ev_double, ev_double, PROG_V6P_VERSION, }, - [OP_ADD_F_v6p] = {"+", "add.f", + [OP_ADD_F_v6p] = {"add", "add.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_ADD_V_v6p] = {"+", "add.v", + [OP_ADD_V_v6p] = {"add", "add.v", ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_ADD_Q_v6p] = {"+", "add.q", + [OP_ADD_Q_v6p] = {"add", "add.q", ev_quaternion, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, - [OP_ADD_S_v6p] = {"+", "add.s", + [OP_ADD_S_v6p] = {"add", "add.s", ev_string, ev_string, ev_string, PROG_V6P_VERSION, }, - [OP_SUB_D_v6p] = {"-", "sub.d", + [OP_SUB_D_v6p] = {"sub", "sub.d", ev_double, ev_double, ev_double, PROG_V6P_VERSION, }, - [OP_SUB_F_v6p] = {"-", "sub.f", + [OP_SUB_F_v6p] = {"sub", "sub.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_SUB_V_v6p] = {"-", "sub.v", + [OP_SUB_V_v6p] = {"sub", "sub.v", ev_vector, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_SUB_Q_v6p] = {"-", "sub.q", + [OP_SUB_Q_v6p] = {"sub", "sub.q", ev_quaternion, ev_quaternion, ev_quaternion, PROG_V6P_VERSION, }, - [OP_EQ_D_v6p] = {"==", "eq.d", + [OP_EQ_D_v6p] = {"eq", "eq.d", ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, - [OP_EQ_F_v6p] = {"==", "eq.f", + [OP_EQ_F_v6p] = {"eq", "eq.f", ev_float, ev_float, ev_int, PROG_ID_VERSION, }, - [OP_EQ_V_v6p] = {"==", "eq.v", + [OP_EQ_V_v6p] = {"eq", "eq.v", ev_vector, ev_vector, ev_int, PROG_ID_VERSION, }, - [OP_EQ_Q_v6p] = {"==", "eq.q", + [OP_EQ_Q_v6p] = {"eq", "eq.q", ev_quaternion, ev_quaternion, ev_int, PROG_V6P_VERSION, }, - [OP_EQ_S_v6p] = {"==", "eq.s", + [OP_EQ_S_v6p] = {"eq", "eq.s", ev_string, ev_string, ev_int, PROG_ID_VERSION, }, - [OP_EQ_E_v6p] = {"==", "eq.e", + [OP_EQ_E_v6p] = {"eq", "eq.e", ev_entity, ev_entity, ev_int, PROG_ID_VERSION, }, - [OP_EQ_FN_v6p] = {"==", "eq.fn", + [OP_EQ_FN_v6p] = {"eq", "eq.fn", ev_func, ev_func, ev_int, PROG_ID_VERSION, }, - [OP_NE_D_v6p] = {"!=", "ne.d", + [OP_NE_D_v6p] = {"ne", "ne.d", ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, - [OP_NE_F_v6p] = {"!=", "ne.f", + [OP_NE_F_v6p] = {"ne", "ne.f", ev_float, ev_float, ev_int, PROG_ID_VERSION, }, - [OP_NE_V_v6p] = {"!=", "ne.v", + [OP_NE_V_v6p] = {"ne", "ne.v", ev_vector, ev_vector, ev_int, PROG_ID_VERSION, }, - [OP_NE_Q_v6p] = {"!=", "ne.q", + [OP_NE_Q_v6p] = {"ne", "ne.q", ev_quaternion, ev_quaternion, ev_int, PROG_V6P_VERSION, }, - [OP_NE_S_v6p] = {"!=", "ne.s", + [OP_NE_S_v6p] = {"ne", "ne.s", ev_string, ev_string, ev_int, PROG_ID_VERSION, }, - [OP_NE_E_v6p] = {"!=", "ne.e", + [OP_NE_E_v6p] = {"ne", "ne.e", ev_entity, ev_entity, ev_int, PROG_ID_VERSION, }, - [OP_NE_FN_v6p] = {"!=", "ne.fn", + [OP_NE_FN_v6p] = {"ne", "ne.fn", ev_func, ev_func, ev_int, PROG_ID_VERSION, }, - [OP_LE_D_v6p] = {"<=", "le.d", + [OP_LE_D_v6p] = {"le", "le.d", ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, - [OP_LE_F_v6p] = {"<=", "le.f", + [OP_LE_F_v6p] = {"le", "le.f", ev_float, ev_float, ev_int, PROG_ID_VERSION, }, - [OP_GE_D_v6p] = {">=", "ge.d", + [OP_GE_D_v6p] = {"ge", "ge.d", ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, - [OP_GE_F_v6p] = {">=", "ge.f", + [OP_GE_F_v6p] = {"ge", "ge.f", ev_float, ev_float, ev_int, PROG_ID_VERSION, }, - [OP_LE_S_v6p] = {"<=", "le.s", + [OP_LE_S_v6p] = {"le", "le.s", ev_string, ev_string, ev_int, PROG_V6P_VERSION, }, - [OP_GE_S_v6p] = {">=", "ge.s", + [OP_GE_S_v6p] = {"ge", "ge.s", ev_string, ev_string, ev_int, PROG_V6P_VERSION, }, - [OP_LT_D_v6p] = {"<", "lt.d", + [OP_LT_D_v6p] = {"lt", "lt.d", ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, - [OP_LT_F_v6p] = {"<", "lt.f", + [OP_LT_F_v6p] = {"lt", "lt.f", ev_float, ev_float, ev_int, PROG_ID_VERSION, }, - [OP_GT_D_v6p] = {">", "gt.d", + [OP_GT_D_v6p] = {"gt", "gt.d", ev_double, ev_double, ev_int, PROG_V6P_VERSION, }, - [OP_GT_F_v6p] = {">", "gt.f", + [OP_GT_F_v6p] = {"gt", "gt.f", ev_float, ev_float, ev_int, PROG_ID_VERSION, }, - [OP_LT_S_v6p] = {"<", "lt.s", + [OP_LT_S_v6p] = {"lt", "lt.s", ev_string, ev_string, ev_int, PROG_V6P_VERSION, }, - [OP_GT_S_v6p] = {">", "gt.s", + [OP_GT_S_v6p] = {"gt", "gt.s", ev_string, ev_string, ev_int, PROG_V6P_VERSION, }, - [OP_LOAD_F_v6p] = {".", "load.f", + [OP_LOAD_F_v6p] = {"load", "load.f", ev_entity, ev_field, ev_float, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc",//FIXME %E more flexible? }, - [OP_LOAD_D_v6p] = {".", "load.d", + [OP_LOAD_D_v6p] = {"load", "load.d", ev_entity, ev_field, ev_double, PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_V_v6p] = {".", "load.v", + [OP_LOAD_V_v6p] = {"load", "load.v", ev_entity, ev_field, ev_vector, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_Q_v6p] = {".", "load.q", + [OP_LOAD_Q_v6p] = {"load", "load.q", ev_entity, ev_field, ev_quaternion, PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_S_v6p] = {".", "load.s", + [OP_LOAD_S_v6p] = {"load", "load.s", ev_entity, ev_field, ev_string, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_ENT_v6p] = {".", "load.ent", + [OP_LOAD_ENT_v6p] = {"load", "load.ent", ev_entity, ev_field, ev_entity, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_FLD_v6p] = {".", "load.fld", + [OP_LOAD_FLD_v6p] = {"load", "load.fld", ev_entity, ev_field, ev_field, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_FN_v6p] = {".", "load.fn", + [OP_LOAD_FN_v6p] = {"load", "load.fn", ev_entity, ev_field, ev_func, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_I_v6p] = {".", "load.i", + [OP_LOAD_I_v6p] = {"load", "load.i", ev_entity, ev_field, ev_int, PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOAD_P_v6p] = {".", "load.p", + [OP_LOAD_P_v6p] = {"load", "load.p", ev_entity, ev_field, ev_ptr, PROG_V6P_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_LOADB_D_v6p] = {".", "loadb.d", + [OP_LOADB_D_v6p] = {"load", "loadb.d", ev_ptr, ev_int, ev_double, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_F_v6p] = {".", "loadb.f", + [OP_LOADB_F_v6p] = {"load", "loadb.f", ev_ptr, ev_int, ev_float, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_V_v6p] = {".", "loadb.v", + [OP_LOADB_V_v6p] = {"load", "loadb.v", ev_ptr, ev_int, ev_vector, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_Q_v6p] = {".", "loadb.q", + [OP_LOADB_Q_v6p] = {"load", "loadb.q", ev_ptr, ev_int, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_S_v6p] = {".", "loadb.s", + [OP_LOADB_S_v6p] = {"load", "loadb.s", ev_ptr, ev_int, ev_string, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_ENT_v6p] = {".", "loadb.ent", + [OP_LOADB_ENT_v6p] = {"load", "loadb.ent", ev_ptr, ev_int, ev_entity, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_FLD_v6p] = {".", "loadb.fld", + [OP_LOADB_FLD_v6p] = {"load", "loadb.fld", ev_ptr, ev_int, ev_field, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_FN_v6p] = {".", "loadb.fn", + [OP_LOADB_FN_v6p] = {"load", "loadb.fn", ev_ptr, ev_int, ev_func, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_I_v6p] = {".", "loadb.i", + [OP_LOADB_I_v6p] = {"load", "loadb.i", ev_ptr, ev_int, ev_int, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADB_P_v6p] = {".", "loadb.p", + [OP_LOADB_P_v6p] = {"load", "loadb.p", ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %Gb), %gc", }, - [OP_LOADBI_D_v6p] = {".", "loadbi.d", + [OP_LOADBI_D_v6p] = {"load", "loadbi.d", ev_ptr, ev_short, ev_double, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_F_v6p] = {".", "loadbi.f", + [OP_LOADBI_F_v6p] = {"load", "loadbi.f", ev_ptr, ev_short, ev_float, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_V_v6p] = {".", "loadbi.v", + [OP_LOADBI_V_v6p] = {"load", "loadbi.v", ev_ptr, ev_short, ev_vector, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_Q_v6p] = {".", "loadbi.q", + [OP_LOADBI_Q_v6p] = {"load", "loadbi.q", ev_ptr, ev_short, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_S_v6p] = {".", "loadbi.s", + [OP_LOADBI_S_v6p] = {"load", "loadbi.s", ev_ptr, ev_short, ev_string, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_ENT_v6p] = {".", "loadbi.ent", + [OP_LOADBI_ENT_v6p] = {"load", "loadbi.ent", ev_ptr, ev_short, ev_entity, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_FLD_v6p] = {".", "loadbi.fld", + [OP_LOADBI_FLD_v6p] = {"load", "loadbi.fld", ev_ptr, ev_short, ev_field, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_FN_v6p] = {".", "loadbi.fn", + [OP_LOADBI_FN_v6p] = {"load", "loadbi.fn", ev_ptr, ev_short, ev_func, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_I_v6p] = {".", "loadbi.i", + [OP_LOADBI_I_v6p] = {"load", "loadbi.i", ev_ptr, ev_short, ev_int, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_LOADBI_P_v6p] = {".", "loadbi.p", + [OP_LOADBI_P_v6p] = {"load", "loadbi.p", ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %sb), %gc", }, - [OP_ADDRESS_v6p] = {"&", "address", + [OP_ADDRESS_v6p] = {"lea", "address", ev_entity, ev_field, ev_ptr, PROG_ID_VERSION, "%Ga.%Gb(%Ec), %gc", }, - [OP_ADDRESS_VOID_v6p] = {"&", "address", + [OP_ADDRESS_VOID_v6p] = {"lea", "address", ev_void, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_D_v6p] = {"&", "address.d", + [OP_ADDRESS_D_v6p] = {"lea", "address.d", ev_double, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_F_v6p] = {"&", "address.f", + [OP_ADDRESS_F_v6p] = {"lea", "address.f", ev_float, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_V_v6p] = {"&", "address.v", + [OP_ADDRESS_V_v6p] = {"lea", "address.v", ev_vector, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_Q_v6p] = {"&", "address.q", + [OP_ADDRESS_Q_v6p] = {"lea", "address.q", ev_quaternion, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_S_v6p] = {"&", "address.s", + [OP_ADDRESS_S_v6p] = {"lea", "address.s", ev_string, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_ENT_v6p] = {"&", "address.ent", + [OP_ADDRESS_ENT_v6p] = {"lea", "address.ent", ev_entity, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_FLD_v6p] = {"&", "address.fld", + [OP_ADDRESS_FLD_v6p] = {"lea", "address.fld", ev_field, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_FN_v6p] = {"&", "address.fn", + [OP_ADDRESS_FN_v6p] = {"lea", "address.fn", ev_func, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_I_v6p] = {"&", "address.i", + [OP_ADDRESS_I_v6p] = {"lea", "address.i", ev_int, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_ADDRESS_P_v6p] = {"&", "address.p", + [OP_ADDRESS_P_v6p] = {"lea", "address.p", ev_ptr, ev_invalid, ev_ptr, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_LEA_v6p] = {"&", "lea", + [OP_LEA_v6p] = {"lea", "lea", ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "(%Ga + %Gb), %gc", }, - [OP_LEAI_v6p] = {"&", "leai", + [OP_LEAI_v6p] = {"lea", "leai", ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "(%Ga + %sb), %gc", }, - [OP_CONV_IF_v6p] = {"", "conv.if", + [OP_CONV_IF_v6p] = {"conv", "conv.if", ev_int, ev_invalid, ev_float, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_CONV_FI_v6p] = {"", "conv.fi", + [OP_CONV_FI_v6p] = {"conv", "conv.fi", ev_float, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_CONV_ID_v6p] = {"", "conv.id", + [OP_CONV_ID_v6p] = {"conv", "conv.id", ev_int, ev_invalid, ev_double, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_CONV_DI_v6p] = {"", "conv.di", + [OP_CONV_DI_v6p] = {"conv", "conv.di", ev_double, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_CONV_FD_v6p] = {"", "conv.fd", + [OP_CONV_FD_v6p] = {"conv", "conv.fd", ev_float, ev_invalid, ev_double, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_CONV_DF_v6p] = {"", "conv.df", + [OP_CONV_DF_v6p] = {"conv", "conv.df", ev_double, ev_invalid, ev_float, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_STORE_D_v6p] = {"=", "store.d", + [OP_STORE_D_v6p] = {"assign", "store.d", ev_double, ev_double, ev_invalid, PROG_V6P_VERSION, "%Ga, %gb", }, - [OP_STORE_F_v6p] = {"=", "store.f", + [OP_STORE_F_v6p] = {"assign", "store.f", ev_float, ev_float, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_V_v6p] = {"=", "store.v", + [OP_STORE_V_v6p] = {"assign", "store.v", ev_vector, ev_vector, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_Q_v6p] = {"=", "store.q", + [OP_STORE_Q_v6p] = {"assign", "store.q", ev_quaternion, ev_quaternion, ev_invalid, PROG_V6P_VERSION, "%Ga, %gb", }, - [OP_STORE_S_v6p] = {"=", "store.s", + [OP_STORE_S_v6p] = {"assign", "store.s", ev_string, ev_string, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_ENT_v6p] = {"=", "store.ent", + [OP_STORE_ENT_v6p] = {"assign", "store.ent", ev_entity, ev_entity, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_FLD_v6p] = {"=", "store.fld", + [OP_STORE_FLD_v6p] = {"assign", "store.fld", ev_field, ev_field, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_FN_v6p] = {"=", "store.fn", + [OP_STORE_FN_v6p] = {"assign", "store.fn", ev_func, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %gb", }, - [OP_STORE_I_v6p] = {"=", "store.i", + [OP_STORE_I_v6p] = {"assign", "store.i", ev_int, ev_int, ev_invalid, PROG_V6P_VERSION, "%Ga, %gb", }, - [OP_STORE_P_v6p] = {"=", "store.p", + [OP_STORE_P_v6p] = {"assign", "store.p", ev_ptr, ev_ptr, ev_invalid, PROG_V6P_VERSION, "%Ga, %gb", }, - [OP_STOREP_D_v6p] = {".=", "storep.d", + [OP_STOREP_D_v6p] = {"store", "storep.d", ev_double, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_F_v6p] = {".=", "storep.f", + [OP_STOREP_F_v6p] = {"store", "storep.f", ev_float, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_V_v6p] = {".=", "storep.v", + [OP_STOREP_V_v6p] = {"store", "storep.v", ev_vector, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_Q_v6p] = {".=", "storep.q", + [OP_STOREP_Q_v6p] = {"store", "storep.q", ev_quaternion, ev_ptr, ev_invalid, PROG_V6P_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_S_v6p] = {".=", "storep.s", + [OP_STOREP_S_v6p] = {"store", "storep.s", ev_string, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_ENT_v6p] = {".=", "storep.ent", + [OP_STOREP_ENT_v6p] = {"store", "storep.ent", ev_entity, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_FLD_v6p] = {".=", "storep.fld", + [OP_STOREP_FLD_v6p] = {"store", "storep.fld", ev_field, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_FN_v6p] = {".=", "storep.fn", + [OP_STOREP_FN_v6p] = {"store", "storep.fn", ev_func, ev_ptr, ev_invalid, PROG_ID_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_I_v6p] = {".=", "storep.i", + [OP_STOREP_I_v6p] = {"store", "storep.i", ev_int, ev_ptr, ev_invalid, PROG_V6P_VERSION, "%Ga, *%Gb", }, - [OP_STOREP_P_v6p] = {".=", "storep.p", + [OP_STOREP_P_v6p] = {"store", "storep.p", ev_ptr, ev_ptr, ev_invalid, PROG_V6P_VERSION, "%Ga, *%Gb", }, - [OP_STOREB_D_v6p] = {".=", "storeb.d", + [OP_STOREB_D_v6p] = {"store", "storeb.d", ev_double, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_F_v6p] = {".=", "storeb.f", + [OP_STOREB_F_v6p] = {"store", "storeb.f", ev_float, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_V_v6p] = {".=", "storeb.v", + [OP_STOREB_V_v6p] = {"store", "storeb.v", ev_vector, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_Q_v6p] = {".=", "storeb.q", + [OP_STOREB_Q_v6p] = {"store", "storeb.q", ev_quaternion, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_S_v6p] = {".=", "storeb.s", + [OP_STOREB_S_v6p] = {"store", "storeb.s", ev_string, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_ENT_v6p] = {".=", "storeb.ent", + [OP_STOREB_ENT_v6p] = {"store", "storeb.ent", ev_entity, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_FLD_v6p] = {".=", "storeb.fld", + [OP_STOREB_FLD_v6p] = {"store", "storeb.fld", ev_field, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_FN_v6p] = {".=", "storeb.fn", + [OP_STOREB_FN_v6p] = {"store", "storeb.fn", ev_func, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_I_v6p] = {".=", "storeb.i", + [OP_STOREB_I_v6p] = {"store", "storeb.i", ev_int, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREB_P_v6p] = {".=", "storeb.p", + [OP_STOREB_P_v6p] = {"store", "storeb.p", ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, "%Ga, *(%Gb + %Gc)", }, - [OP_STOREBI_D_v6p] = {".=", "storebi.d", + [OP_STOREBI_D_v6p] = {"store", "storebi.d", ev_double, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_F_v6p] = {".=", "storebi.f", + [OP_STOREBI_F_v6p] = {"store", "storebi.f", ev_float, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_V_v6p] = {".=", "storebi.v", + [OP_STOREBI_V_v6p] = {"store", "storebi.v", ev_vector, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_Q_v6p] = {".=", "storebi.q", + [OP_STOREBI_Q_v6p] = {"store", "storebi.q", ev_quaternion, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_S_v6p] = {".=", "storebi.s", + [OP_STOREBI_S_v6p] = {"store", "storebi.s", ev_string, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_ENT_v6p] = {".=", "storebi.ent", + [OP_STOREBI_ENT_v6p] = {"store", "storebi.ent", ev_entity, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_FLD_v6p] = {".=", "storebi.fld", + [OP_STOREBI_FLD_v6p] = {"store", "storebi.fld", ev_field, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_FN_v6p] = {".=", "storebi.fn", + [OP_STOREBI_FN_v6p] = {"store", "storebi.fn", ev_func, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_I_v6p] = {".=", "storebi.i", + [OP_STOREBI_I_v6p] = {"store", "storebi.i", ev_int, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_STOREBI_P_v6p] = {".=", "storebi.p", + [OP_STOREBI_P_v6p] = {"store", "storebi.p", ev_ptr, ev_ptr, ev_short, PROG_V6P_VERSION, "%Ga, *(%Gb + %sc)", }, - [OP_RETURN_v6p] = {"", "return", + [OP_RETURN_v6p] = {"return", "return", ev_void, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Ra", }, - [OP_RETURN_V_v6p] = {"", "return", + [OP_RETURN_V_v6p] = {"return_v", "return", ev_invalid, ev_invalid, ev_invalid, PROG_V6P_VERSION, "", }, - [OP_NOT_D_v6p] = {"!", "not.d", + [OP_NOT_D_v6p] = {"not", "not.d", ev_double, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_NOT_F_v6p] = {"!", "not.f", + [OP_NOT_F_v6p] = {"not", "not.f", ev_float, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_V_v6p] = {"!", "not.v", + [OP_NOT_V_v6p] = {"not", "not.v", ev_vector, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_Q_v6p] = {"!", "not.q", + [OP_NOT_Q_v6p] = {"not", "not.q", ev_quaternion, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_NOT_S_v6p] = {"!", "not.s", + [OP_NOT_S_v6p] = {"not", "not.s", ev_string, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_ENT_v6p] = {"!", "not.ent", + [OP_NOT_ENT_v6p] = {"not", "not.ent", ev_entity, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_FN_v6p] = {"!", "not.fn", + [OP_NOT_FN_v6p] = {"not", "not.fn", ev_func, ev_invalid, ev_int, PROG_ID_VERSION, "%Ga, %gc", }, - [OP_NOT_P_v6p] = {"!", "not.p", + [OP_NOT_P_v6p] = {"not", "not.p", ev_ptr, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_IF_v6p] = {"", "if", + [OP_IF_v6p] = {"if", "if", ev_int, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFNOT_v6p] = {"", "ifnot", + [OP_IFNOT_v6p] = {"ifnot", "ifnot", ev_int, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFBE_v6p] = {"", "ifbe", + [OP_IFBE_v6p] = {"ifbe", "ifbe", ev_int, ev_short, ev_invalid, PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFB_v6p] = {"", "ifb", + [OP_IFB_v6p] = {"ifb", "ifb", ev_int, ev_short, ev_invalid, PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFAE_v6p] = {"", "ifae", + [OP_IFAE_v6p] = {"ifae", "ifae", ev_int, ev_short, ev_invalid, PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFA_v6p] = {"", "ifa", + [OP_IFA_v6p] = {"ifa", "ifa", ev_int, ev_short, ev_invalid, PROG_V6P_VERSION, "%Ga branch %sb (%Ob)", }, // calls returns REG_RETURN - [OP_CALL0_v6p] = {"", "call0", + [OP_CALL0_v6p] = {"call0", "call0", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa ()", }, - [OP_CALL1_v6p] = {"", "call1", + [OP_CALL1_v6p] = {"call1", "call1", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x)", }, - [OP_CALL2_v6p] = {"", "call2", + [OP_CALL2_v6p] = {"call2", "call2", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x)", }, - [OP_CALL3_v6p] = {"", "call3", + [OP_CALL3_v6p] = {"call3", "call3", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x)", }, - [OP_CALL4_v6p] = {"", "call4", + [OP_CALL4_v6p] = {"call4", "call4", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x)", }, - [OP_CALL5_v6p] = {"", "call5", + [OP_CALL5_v6p] = {"call5", "call5", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x)", }, - [OP_CALL6_v6p] = {"", "call6", + [OP_CALL6_v6p] = {"call6", "call6", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x)", }, - [OP_CALL7_v6p] = {"", "call7", + [OP_CALL7_v6p] = {"call7", "call7", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - [OP_CALL8_v6p] = {"", "call8", + [OP_CALL8_v6p] = {"call8", "call8", ev_func, ev_invalid, ev_invalid, PROG_ID_VERSION, "%Fa (%P0x, %P1x, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - [OP_RCALL0_v6p] = {"", 0, + [OP_RCALL0_v6p] = {"rcall0", 0, ev_invalid, ev_invalid, ev_invalid, ~0, // not a valid instruction 0, }, - [OP_RCALL1_v6p] = {"", "rcall1", + [OP_RCALL1_v6p] = {"rcall1", "rcall1", ev_func, ev_void, ev_invalid, PROG_V6P_VERSION, "%Fa (%P0b)", }, - [OP_RCALL2_v6p] = {"", "rcall2", + [OP_RCALL2_v6p] = {"rcall2", "rcall2", ev_func, ev_void, ev_void, PROG_V6P_VERSION, "%Fa (%P0b, %P1c)", }, - [OP_RCALL3_v6p] = {"", "rcall3", + [OP_RCALL3_v6p] = {"rcall3", "rcall3", ev_func, ev_void, ev_void, PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x)", }, - [OP_RCALL4_v6p] = {"", "rcall4", + [OP_RCALL4_v6p] = {"rcall4", "rcall4", ev_func, ev_void, ev_void, PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x)", }, - [OP_RCALL5_v6p] = {"", "rcall5", + [OP_RCALL5_v6p] = {"rcall5", "rcall5", ev_func, ev_void, ev_void, PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x)", }, - [OP_RCALL6_v6p] = {"", "rcall6", + [OP_RCALL6_v6p] = {"rcall6", "rcall6", ev_func, ev_void, ev_void, PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x)", }, - [OP_RCALL7_v6p] = {"", "rcall7", + [OP_RCALL7_v6p] = {"rcall7", "rcall7", ev_func, ev_void, ev_void, PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x)", }, - [OP_RCALL8_v6p] = {"", "rcall8", + [OP_RCALL8_v6p] = {"rcall8", "rcall8", ev_func, ev_void, ev_void, PROG_V6P_VERSION, "%Fa (%P0b, %P1c, %P2x, %P3x, %P4x, %P5x, %P6x, %P7x)", }, - [OP_STATE_v6p] = {"", "state", + [OP_STATE_v6p] = {"state", "state", ev_float, ev_func, ev_invalid, PROG_ID_VERSION, "%Ga, %Gb", }, - [OP_STATE_F_v6p] = {"", "state.f", + [OP_STATE_F_v6p] = {"state", "state.f", ev_float, ev_func, ev_float, PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, - [OP_GOTO_v6p] = {"", "goto", + [OP_GOTO_v6p] = {"jump", "goto", ev_short, ev_invalid, ev_invalid, PROG_ID_VERSION, "branch %sa (%Oa)", }, - [OP_JUMP_v6p] = {"", "jump", + [OP_JUMP_v6p] = {"jump", "jump", ev_int, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_JUMPB_v6p] = {"", "jumpb", + [OP_JUMPB_v6p] = {"jumpb", "jumpb", ev_void, ev_int, ev_invalid, PROG_V6P_VERSION, "%Ga[%Gb]", }, - [OP_AND_v6p] = {"&&", "and.f", + [OP_AND_v6p] = {"and", "and.f", ev_float, ev_float, ev_int, PROG_ID_VERSION, }, - [OP_OR_v6p] = {"||", "or.f", + [OP_OR_v6p] = {"or", "or.f", ev_float, ev_float, ev_int, PROG_ID_VERSION, }, - [OP_SHL_F_v6p] = {"<<", "shl.f", + [OP_SHL_F_v6p] = {"shl", "shl.f", ev_float, ev_float, ev_float, PROG_V6P_VERSION, }, - [OP_SHR_F_v6p] = {">>", "shr.f", + [OP_SHR_F_v6p] = {"shr", "shr.f", ev_float, ev_float, ev_float, PROG_V6P_VERSION, }, - [OP_SHL_I_v6p] = {"<<", "shl.i", + [OP_SHL_I_v6p] = {"shl", "shl.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_SHR_I_v6p] = {">>", "shr.i", + [OP_SHR_I_v6p] = {"shr", "shr.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_SHR_U_v6p] = {">>", "shr.u", + [OP_SHR_U_v6p] = {"shr", "shr.u", ev_uint, ev_int, ev_uint, PROG_V6P_VERSION, }, - [OP_BITAND_v6p] = {"&", "bitand", + [OP_BITAND_v6p] = {"bitand", "bitand.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_BITOR_v6p] = {"|", "bitor", + [OP_BITOR_v6p] = {"bitor", "bitor.f", ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_ADD_I_v6p] = {"+", "add.i", + [OP_ADD_I_v6p] = {"add", "add.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_SUB_I_v6p] = {"-", "sub.i", + [OP_SUB_I_v6p] = {"sub", "sub.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_MUL_I_v6p] = {"*", "mul.i", + [OP_MUL_I_v6p] = {"mul", "mul.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_DIV_I_v6p] = {"/", "div.i", + [OP_DIV_I_v6p] = {"div", "div.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_REM_I_v6p] = {"%", "rem.i", + [OP_REM_I_v6p] = {"rem", "rem.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_MOD_I_v6p] = {"%%", "mod.i", + [OP_MOD_I_v6p] = {"mod", "mod.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_BITAND_I_v6p] = {"&", "bitand.i", + [OP_BITAND_I_v6p] = {"bitand", "bitand.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_BITOR_I_v6p] = {"|", "bitor.i", + [OP_BITOR_I_v6p] = {"bitor", "bitor.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_REM_F_v6p] = {"%", "rem.f", + [OP_REM_F_v6p] = {"rem", "rem.f", ev_float, ev_float, ev_float, PROG_V6P_VERSION, }, - [OP_MOD_F_v6p] = {"%%", "mod.f", + [OP_MOD_F_v6p] = {"mod", "mod.f", ev_float, ev_float, ev_float, PROG_V6P_VERSION, }, - [OP_GE_I_v6p] = {">=", "ge.i", + [OP_GE_I_v6p] = {"ge", "ge.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_LE_I_v6p] = {"<=", "le.i", + [OP_LE_I_v6p] = {"le", "le.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_GT_I_v6p] = {">", "gt.i", + [OP_GT_I_v6p] = {"gt", "gt.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_LT_I_v6p] = {"<", "lt.i", + [OP_LT_I_v6p] = {"lt", "lt.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_AND_I_v6p] = {"&&", "and.i", + [OP_AND_I_v6p] = {"and", "and.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_OR_I_v6p] = {"||", "or.i", + [OP_OR_I_v6p] = {"or", "or.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_NOT_I_v6p] = {"!", "not.i", + [OP_NOT_I_v6p] = {"not", "not.i", ev_int, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_EQ_I_v6p] = {"==", "eq.i", + [OP_EQ_I_v6p] = {"eq", "eq.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_NE_I_v6p] = {"!=", "ne.i", + [OP_NE_I_v6p] = {"ne", "ne.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_GE_U_v6p] = {">=", "ge.u", + [OP_GE_U_v6p] = {"ge", "ge.u", ev_uint, ev_uint, ev_int, PROG_V6P_VERSION, }, - [OP_LE_U_v6p] = {"<=", "le.u", + [OP_LE_U_v6p] = {"le", "le.u", ev_uint, ev_uint, ev_int, PROG_V6P_VERSION, }, - [OP_GT_U_v6p] = {">", "gt.u", + [OP_GT_U_v6p] = {"gt", "gt.u", ev_uint, ev_uint, ev_int, PROG_V6P_VERSION, }, - [OP_LT_U_v6p] = {"<", "lt.u", + [OP_LT_U_v6p] = {"lt", "lt.u", ev_uint, ev_uint, ev_int, PROG_V6P_VERSION, }, - [OP_BITXOR_F_v6p] = {"^", "bitxor.f", + [OP_BITXOR_F_v6p] = {"bitxor", "bitxor.f", ev_float, ev_float, ev_float, PROG_V6P_VERSION, }, - [OP_BITNOT_F_v6p] = {"~", "bitnot.f", + [OP_BITNOT_F_v6p] = {"bitnot", "bitnot.f", ev_float, ev_invalid, ev_float, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_BITXOR_I_v6p] = {"^", "bitxor.i", + [OP_BITXOR_I_v6p] = {"bitxor", "bitxor.i", ev_int, ev_int, ev_int, PROG_V6P_VERSION, }, - [OP_BITNOT_I_v6p] = {"~", "bitnot.i", + [OP_BITNOT_I_v6p] = {"bitnot", "bitnot.i", ev_int, ev_invalid, ev_int, PROG_V6P_VERSION, "%Ga, %gc", }, - [OP_GE_P_v6p] = {">=", "ge.p", + [OP_GE_P_v6p] = {"ge", "ge.p", ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, - [OP_LE_P_v6p] = {"<=", "le.p", + [OP_LE_P_v6p] = {"le", "le.p", ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, - [OP_GT_P_v6p] = {">", "gt.p", + [OP_GT_P_v6p] = {"gt", "gt.p", ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, - [OP_LT_P_v6p] = {"<", "lt.p", + [OP_LT_P_v6p] = {"lt", "lt.p", ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, - [OP_EQ_P_v6p] = {"==", "eq.p", + [OP_EQ_P_v6p] = {"eq", "eq.p", ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, - [OP_NE_P_v6p] = {"!=", "ne.p", + [OP_NE_P_v6p] = {"ne", "ne.p", ev_ptr, ev_ptr, ev_int, PROG_V6P_VERSION, }, - [OP_MOVEI_v6p] = {"", "movei", + [OP_MOVEI_v6p] = {"move", "movei", ev_void, ev_short, ev_void, PROG_V6P_VERSION, "%Ga, %sb, %gc", }, - [OP_MOVEP_v6p] = {"", "movep", + [OP_MOVEP_v6p] = {"movep", "movep", ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, - [OP_MOVEPI_v6p] = {"", "movepi", + [OP_MOVEPI_v6p] = {"movep", "movepi", ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "%Ga, %sb, %Gc", }, - [OP_MEMSETI_v6p] = {"", "memseti", + [OP_MEMSETI_v6p] = {"memset", "memseti", ev_int, ev_short, ev_void, PROG_V6P_VERSION, "%Ga, %sb, %gc", }, - [OP_MEMSETP_v6p] = {"", "memsetp", + [OP_MEMSETP_v6p] = {"memsetp", "memsetp", ev_int, ev_int, ev_ptr, PROG_V6P_VERSION, "%Ga, %Gb, %Gc", }, - [OP_MEMSETPI_v6p] = {"", "memsetpi", + [OP_MEMSETPI_v6p] = {"memsetp", "memsetpi", ev_int, ev_short, ev_ptr, PROG_V6P_VERSION, "%Ga, %sb, %Gc", }, - [OP_PUSH_S_v6p] = {"", "push.s", + [OP_PUSH_S_v6p] = {"push", "push.s", ev_string, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSH_F_v6p] = {"", "push.f", + [OP_PUSH_F_v6p] = {"push", "push.f", ev_float, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSH_V_v6p] = {"", "push.v", + [OP_PUSH_V_v6p] = {"push", "push.v", ev_vector, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSH_ENT_v6p] = {"", "push.ent", + [OP_PUSH_ENT_v6p] = {"push", "push.ent", ev_entity, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSH_FLD_v6p] = {"", "push.fld", + [OP_PUSH_FLD_v6p] = {"push", "push.fld", ev_field, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSH_FN_v6p] = {"", "push.fn", + [OP_PUSH_FN_v6p] = {"push", "push.fn", ev_func, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSH_P_v6p] = {"", "push.p", + [OP_PUSH_P_v6p] = {"push", "push.p", ev_ptr, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSH_Q_v6p] = {"", "push.q", + [OP_PUSH_Q_v6p] = {"push", "push.q", ev_quaternion, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSH_I_v6p] = {"", "push.i", + [OP_PUSH_I_v6p] = {"push", "push.i", ev_int, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSH_D_v6p] = {"", "push.d", + [OP_PUSH_D_v6p] = {"push", "push.d", ev_double, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%Ga", }, - [OP_PUSHB_S_v6p] = {"", "pushb.s", + [OP_PUSHB_S_v6p] = {"push", "pushb.s", ev_ptr, ev_int, ev_string, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_F_v6p] = {"", "pushb.f", + [OP_PUSHB_F_v6p] = {"push", "pushb.f", ev_ptr, ev_int, ev_float, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_V_v6p] = {"", "pushb.v", + [OP_PUSHB_V_v6p] = {"push", "pushb.v", ev_ptr, ev_int, ev_vector, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_ENT_v6p] = {"", "pushb.ent", + [OP_PUSHB_ENT_v6p] = {"push", "pushb.ent", ev_ptr, ev_int, ev_entity, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_FLD_v6p] = {"", "pushb.fld", + [OP_PUSHB_FLD_v6p] = {"push", "pushb.fld", ev_ptr, ev_int, ev_field, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_FN_v6p] = {"", "pushb.fn", + [OP_PUSHB_FN_v6p] = {"push", "pushb.fn", ev_ptr, ev_int, ev_func, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_P_v6p] = {"", "pushb.p", + [OP_PUSHB_P_v6p] = {"push", "pushb.p", ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_Q_v6p] = {"", "pushb.q", + [OP_PUSHB_Q_v6p] = {"push", "pushb.q", ev_ptr, ev_int, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_I_v6p] = {"", "pushb.i", + [OP_PUSHB_I_v6p] = {"push", "pushb.i", ev_ptr, ev_int, ev_int, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHB_D_v6p] = {"", "pushb.d", + [OP_PUSHB_D_v6p] = {"push", "pushb.d", ev_ptr, ev_int, ev_double, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_PUSHBI_S_v6p] = {"", "pushbi.s", + [OP_PUSHBI_S_v6p] = {"push", "pushbi.s", ev_ptr, ev_short, ev_string, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_F_v6p] = {"", "pushbi.f", + [OP_PUSHBI_F_v6p] = {"push", "pushbi.f", ev_ptr, ev_short, ev_float, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_V_v6p] = {"", "pushbi.v", + [OP_PUSHBI_V_v6p] = {"push", "pushbi.v", ev_ptr, ev_short, ev_vector, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_ENT_v6p] = {"", "pushbi.ent", + [OP_PUSHBI_ENT_v6p] = {"push", "pushbi.ent", ev_ptr, ev_short, ev_entity, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_FLD_v6p] = {"", "pushbi.fld", + [OP_PUSHBI_FLD_v6p] = {"push", "pushbi.fld", ev_ptr, ev_short, ev_field, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_FN_v6p] = {"", "pushbi.fn", + [OP_PUSHBI_FN_v6p] = {"push", "pushbi.fn", ev_ptr, ev_short, ev_func, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_P_v6p] = {"", "pushbi.p", + [OP_PUSHBI_P_v6p] = {"push", "pushbi.p", ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_Q_v6p] = {"", "pushbi.q", + [OP_PUSHBI_Q_v6p] = {"push", "pushbi.q", ev_ptr, ev_short, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_I_v6p] = {"", "pushbi.i", + [OP_PUSHBI_I_v6p] = {"push", "pushbi.i", ev_ptr, ev_short, ev_int, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_PUSHBI_D_v6p] = {"", "pushbi.d", + [OP_PUSHBI_D_v6p] = {"push", "pushbi.d", ev_ptr, ev_short, ev_double, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POP_S_v6p] = {"", "pop.s", + [OP_POP_S_v6p] = {"pop", "pop.s", ev_string, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POP_F_v6p] = {"", "pop.f", + [OP_POP_F_v6p] = {"pop", "pop.f", ev_float, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POP_V_v6p] = {"", "pop.v", + [OP_POP_V_v6p] = {"pop", "pop.v", ev_vector, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POP_ENT_v6p] = {"", "pop.ent", + [OP_POP_ENT_v6p] = {"pop", "pop.ent", ev_entity, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POP_FLD_v6p] = {"", "pop.fld", + [OP_POP_FLD_v6p] = {"pop", "pop.fld", ev_field, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POP_FN_v6p] = {"", "pop.fn", + [OP_POP_FN_v6p] = {"pop", "pop.fn", ev_func, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POP_P_v6p] = {"", "pop.p", + [OP_POP_P_v6p] = {"pop", "pop.p", ev_ptr, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POP_Q_v6p] = {"", "pop.q", + [OP_POP_Q_v6p] = {"pop", "pop.q", ev_quaternion, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POP_I_v6p] = {"", "pop.i", + [OP_POP_I_v6p] = {"pop", "pop.i", ev_int, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POP_D_v6p] = {"", "pop.d", + [OP_POP_D_v6p] = {"pop", "pop.d", ev_double, ev_invalid, ev_invalid, PROG_V6P_VERSION, "%ga", }, - [OP_POPB_S_v6p] = {"", "popb.s", + [OP_POPB_S_v6p] = {"pop", "popb.s", ev_ptr, ev_int, ev_string, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_F_v6p] = {"", "popb.f", + [OP_POPB_F_v6p] = {"pop", "popb.f", ev_ptr, ev_int, ev_float, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_V_v6p] = {"", "popb.v", + [OP_POPB_V_v6p] = {"pop", "popb.v", ev_ptr, ev_int, ev_vector, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_ENT_v6p] = {"", "popb.ent", + [OP_POPB_ENT_v6p] = {"pop", "popb.ent", ev_ptr, ev_int, ev_entity, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_FLD_v6p] = {"", "popb.fld", + [OP_POPB_FLD_v6p] = {"pop", "popb.fld", ev_ptr, ev_int, ev_field, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_FN_v6p] = {"", "popb.fn", + [OP_POPB_FN_v6p] = {"pop", "popb.fn", ev_ptr, ev_int, ev_func, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_P_v6p] = {"", "popb.p", + [OP_POPB_P_v6p] = {"pop", "popb.p", ev_ptr, ev_int, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_Q_v6p] = {"", "popb.q", + [OP_POPB_Q_v6p] = {"pop", "popb.q", ev_ptr, ev_int, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_I_v6p] = {"", "popb.i", + [OP_POPB_I_v6p] = {"pop", "popb.i", ev_ptr, ev_int, ev_int, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPB_D_v6p] = {"", "popb.d", + [OP_POPB_D_v6p] = {"pop", "popb.d", ev_ptr, ev_int, ev_double, PROG_V6P_VERSION, "*(%Ga + %Gb)", }, - [OP_POPBI_S_v6p] = {"", "popbi.s", + [OP_POPBI_S_v6p] = {"pop", "popbi.s", ev_ptr, ev_short, ev_string, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_F_v6p] = {"", "popbi.f", + [OP_POPBI_F_v6p] = {"pop", "popbi.f", ev_ptr, ev_short, ev_float, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_V_v6p] = {"", "popbi.v", + [OP_POPBI_V_v6p] = {"pop", "popbi.v", ev_ptr, ev_short, ev_vector, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_ENT_v6p] = {"", "popbi.ent", + [OP_POPBI_ENT_v6p] = {"pop", "popbi.ent", ev_ptr, ev_short, ev_entity, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_FLD_v6p] = {"", "popbi.fld", + [OP_POPBI_FLD_v6p] = {"pop", "popbi.fld", ev_ptr, ev_short, ev_field, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_FN_v6p] = {"", "popbi.fn", + [OP_POPBI_FN_v6p] = {"pop", "popbi.fn", ev_ptr, ev_short, ev_func, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_P_v6p] = {"", "popbi.p", + [OP_POPBI_P_v6p] = {"pop", "popbi.p", ev_ptr, ev_short, ev_ptr, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_Q_v6p] = {"", "popbi.q", + [OP_POPBI_Q_v6p] = {"pop", "popbi.q", ev_ptr, ev_short, ev_quaternion, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_I_v6p] = {"", "popbi.i", + [OP_POPBI_I_v6p] = {"pop", "popbi.i", ev_ptr, ev_short, ev_int, PROG_V6P_VERSION, "*(%Ga + %sb)", }, - [OP_POPBI_D_v6p] = {"", "popbi.d", + [OP_POPBI_D_v6p] = {"pop", "popbi.d", ev_ptr, ev_short, ev_double, PROG_V6P_VERSION, "*(%Ga + %sb)", @@ -1625,7 +1625,7 @@ PR_Check_Opcodes (progs_t *pr) PR_Error (pr, "PR_Check_Opcodes: %s used with missing fields " "or globals", op->opname); } - if ((strequal(op->name, "") || strequal(op->name, "")) + if ((strequal(op->name, "push") || strequal(op->name, "pop")) && !pushpop_ok) { PR_Error (pr, "PR_Check_Opcodes: %s used with missing .stack " "globals", op->opname); diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 9c7746bea..3040c5425 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -327,8 +327,8 @@ dagnode_match (const dagnode_t *n, const daglabel_t *op, if (n->killed) return 0; - if (!strcmp (op->opcode, ".") - && n->label->opcode && !strcmp (n->label->opcode, ".=")) + if (!strcmp (op->opcode, "load") + && n->label->opcode && !strcmp (n->label->opcode, "store")) return dagnode_deref_match (n, op, children); if (n->label->opcode != op->opcode) return 0; @@ -452,12 +452,12 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) int first_param = 0; flowvar_t **flowvars = dag->flownode->graph->func->vars; - if (!strncmp (n->label->opcode, "label->opcode, "rcall", 5)) { num_params = n->label->opcode + 6; first_param = 2; - } else if (!strncmp (n->label->opcode, "label->opcode, "call", 4)) { num_params = n->label->opcode + 5; - } else if (!strcmp (n->label->opcode, "")) { + } else if (!strcmp (n->label->opcode, "return")) { daglabel_t *label = n->children[0]->label; if (!label->op) { set_iter_t *lab_i; @@ -997,7 +997,7 @@ generate_moves (dag_t *dag, sblock_t *block, dagnode_t *dagnode) var = dag->labels[var_iter->element]; operands[2] = var->op; dst = operands[2]; - st = build_statement ("", operands, var->expr); + st = build_statement ("move", operands, var->expr); sblock_add_statement (block, st); } return dst; @@ -1019,7 +1019,7 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[1] = make_operand (dag, block, dagnode, 1); if (dagnode->children[2]) { operands[2] = make_operand (dag, block, dagnode, 2); - st = build_statement ("", operands, dagnode->label->expr); + st = build_statement ("movep", operands, dagnode->label->expr); sblock_add_statement (block, st); if ((var_iter = set_first (dagnode->identifiers))) { var = dag->labels[var_iter->element]; @@ -1039,7 +1039,7 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) } operands[2] = value_operand (new_pointer_val (offset, type, dstDef, 0), operands[1]->expr); - st = build_statement ("", operands, var->expr); + st = build_statement ("movep", operands, var->expr); sblock_add_statement (block, st); } } @@ -1063,7 +1063,7 @@ generate_memsets (dag_t *dag, sblock_t *block, dagnode_t *dagnode) var = dag->labels[var_iter->element]; operands[2] = var->op; dst = operands[2]; - st = build_statement ("", operands, var->expr); + st = build_statement ("memset", operands, var->expr); sblock_add_statement (block, st); } return dst; @@ -1085,7 +1085,7 @@ generate_memsetps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[1] = make_operand (dag, block, dagnode, 1); if (dagnode->children[2]) { operands[2] = make_operand (dag, block, dagnode, 2); - st = build_statement ("", operands, dagnode->label->expr); + st = build_statement ("memsetp", operands, dagnode->label->expr); sblock_add_statement (block, st); } else { for (var_iter = set_first (dagnode->identifiers); var_iter; @@ -1100,7 +1100,7 @@ generate_memsetps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) } operands[2] = value_operand (new_pointer_val (offset, type, dstDef, 0), operands[1]->expr); - st = build_statement ("", operands, var->expr); + st = build_statement ("memsetp", operands, var->expr); sblock_add_statement (block, st); } } @@ -1123,7 +1123,7 @@ generate_assignments (dag_t *dag, sblock_t *block, operand_t *src, if (!dst) dst = operands[1]; - st = build_statement ("=", operands, var->expr); + st = build_statement ("assign", operands, var->expr); sblock_add_statement (block, st); } return dst; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 8edc44ad1..d713b1ce8 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1205,20 +1205,20 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, case st_ptrmemset: flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opb, 1); - if (!strcmp (s->opcode, "") - || !strcmp (s->opcode, "")) { + if (!strcmp (s->opcode, "move") + || !strcmp (s->opcode, "memset")) { flow_add_op_var (def, s->opc, 0); res_op = s->opc; - } else if (!strcmp (s->opcode, "")) { + } else if (!strcmp (s->opcode, "movep")) { flow_add_op_var (use, s->opc, 0); aux_op2 = flow_analyze_pointer_operand (s->opa, use); res_op = flow_analyze_pointer_operand (s->opc, def); aux_op1 = s->opc; - } else if (!strcmp (s->opcode, "")) { + } else if (!strcmp (s->opcode, "memsetp")) { flow_add_op_var (use, s->opc, 0); res_op = flow_analyze_pointer_operand (s->opc, def); aux_op1 = s->opc; - } else if (!strcmp (s->opcode, ".=")) { + } else if (!strcmp (s->opcode, "store")) { flow_add_op_var (use, s->opc, 1); res_op = flow_analyze_pointer_operand (s->opb, def); aux_op1 = s->opc; @@ -1250,19 +1250,19 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_func: - if (strcmp (s->opcode, "") == 0 - || strcmp (s->opcode, "") == 0) { + if (strcmp (s->opcode, "return") == 0 + || strcmp (s->opcode, "done") == 0) { flow_add_op_var (use, s->opa, 1); - } else if (strcmp (s->opcode, "") == 0) { + } else if (strcmp (s->opcode, "return_v") == 0) { if (use) { flow_add_op_var (use, &flow_params[0].op, 1); } } - if (strncmp (s->opcode, "opcode, "call", 4) == 0) { start = 0; calln = s->opcode[5] - '0'; flow_add_op_var (use, s->opa, 1); - } else if (strncmp (s->opcode, "opcode, "rcall", 5) == 0) { start = 2; calln = s->opcode[6] - '0'; flow_add_op_var (use, s->opa, 1); @@ -1296,9 +1296,9 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_flow: - if (strcmp (s->opcode, "") != 0) { + if (strcmp (s->opcode, "jump") != 0) { flow_add_op_var (use, s->opa, 1); - if (strcmp (s->opcode, "") == 0) + if (strcmp (s->opcode, "jumpb") == 0) flow_add_op_var (use, s->opb, 1); } if (operands) { diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 9ac87ea10..d0f11684b 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -53,26 +53,26 @@ typedef struct v6p_uint_opcode_s { } v6p_uint_opcode_t; static v6p_uint_opcode_t v6p_uint_opcodes[] = { - {OP_LOAD_I_v6p, {".", "load.i", ev_entity, ev_field, ev_uint }}, - {OP_LOADBI_I_v6p, {".", "loadbi.i", ev_ptr, ev_short, ev_uint }}, - {OP_ADDRESS_I_v6p, {"&", "address.i", ev_uint, ev_invalid, ev_ptr }}, - {OP_STORE_I_v6p, {"=", "store.i", ev_uint, ev_uint, ev_invalid }}, - {OP_STOREP_I_v6p, {".=", "storep.i", ev_uint, ev_ptr, ev_invalid }}, - {OP_STOREB_I_v6p, {".=", "storeb.i", ev_uint, ev_ptr, ev_int }}, - {OP_STOREBI_I_v6p, {".=", "storebi.i", ev_uint, ev_ptr, ev_short }}, - {OP_IF_v6p, {"", "if", ev_uint, ev_short, ev_invalid }}, - {OP_IFNOT_v6p, {"", "ifnot", ev_uint, ev_short, ev_invalid }}, - {OP_ADD_I_v6p, {"+", "add.i", ev_uint, ev_uint, ev_uint }}, - {OP_SUB_I_v6p, {"-", "sub.i", ev_uint, ev_uint, ev_uint }}, - {OP_MUL_I_v6p, {"*", "mul.i", ev_uint, ev_uint, ev_uint }}, - {OP_DIV_I_v6p, {"/", "div.i", ev_uint, ev_uint, ev_uint }}, - {OP_BITAND_I_v6p, {"&", "bitand.i", ev_uint, ev_uint, ev_uint }}, - {OP_BITOR_I_v6p, {"|", "bitor.i", ev_uint, ev_uint, ev_uint }}, - {OP_BITXOR_I_v6p, {"^", "bitxor.i", ev_uint, ev_uint, ev_uint }}, - {OP_REM_I_v6p, {"%", "rem.i", ev_uint, ev_uint, ev_uint }}, - {OP_MOD_I_v6p, {"%%", "mod.i", ev_uint, ev_uint, ev_uint }}, - {OP_SHL_I_v6p, {"<<", "shl.i", ev_uint, ev_uint, ev_uint }}, - {OP_BITNOT_I_v6p, {"<<", "bitnot.i", ev_uint, ev_invalid, ev_int }}, + {OP_LOAD_I_v6p, {"load", "load.i", ev_entity, ev_field, ev_uint }}, + {OP_LOADBI_I_v6p, {"load", "loadbi.i", ev_ptr, ev_short, ev_uint }}, + {OP_ADDRESS_I_v6p, {"lea", "address.i",ev_uint, ev_invalid, ev_ptr }}, + {OP_STORE_I_v6p, {"assign", "store.i", ev_uint, ev_uint, ev_invalid }}, + {OP_STOREP_I_v6p, {"store", "storep.i", ev_uint, ev_ptr, ev_invalid }}, + {OP_STOREB_I_v6p, {"store", "storeb.i", ev_uint, ev_ptr, ev_int }}, + {OP_STOREBI_I_v6p, {"store", "storebi.i",ev_uint, ev_ptr, ev_short }}, + {OP_IF_v6p, {"if", "if", ev_uint, ev_short, ev_invalid }}, + {OP_IFNOT_v6p, {"ifnot", "ifnot", ev_uint, ev_short, ev_invalid }}, + {OP_ADD_I_v6p, {"add", "add.i", ev_uint, ev_uint, ev_uint }}, + {OP_SUB_I_v6p, {"sub", "sub.i", ev_uint, ev_uint, ev_uint }}, + {OP_MUL_I_v6p, {"mul", "mul.i", ev_uint, ev_uint, ev_uint }}, + {OP_DIV_I_v6p, {"div", "div.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITAND_I_v6p, {"bitand", "bitand.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITOR_I_v6p, {"bitor", "bitor.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITXOR_I_v6p, {"bitxor", "bitxor.i", ev_uint, ev_uint, ev_uint }}, + {OP_REM_I_v6p, {"rem", "rem.i", ev_uint, ev_uint, ev_uint }}, + {OP_MOD_I_v6p, {"mod", "mod.i", ev_uint, ev_uint, ev_uint }}, + {OP_SHL_I_v6p, {"shl", "shl.i", ev_uint, ev_uint, ev_uint }}, + {OP_BITNOT_I_v6p, {"bitnot", "bitnot.i", ev_uint, ev_invalid, ev_int }}, {} }; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index d5b385f14..bc7013f91 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -571,28 +571,28 @@ static const char * convert_op (int op) { switch (op) { - case OR: return "||"; - case AND: return "&&"; - case EQ: return "=="; - case NE: return "!="; - case LE: return "<="; - case GE: return ">="; - case LT: return "<"; - case GT: return ">"; - case '+': return "+"; - case '-': return "-"; - case '*': return "*"; - case '/': return "/"; - case '%': return "%"; - case MOD: return "%%"; - case '&': return "&"; - case '|': return "|"; - case '^': return "^"; - case '~': return "~"; - case '!': return "!"; - case SHL: return "<<"; - case SHR: return ">>"; - case '.': return "."; + case OR: return "or"; + case AND: return "and"; + case EQ: return "eq"; + case NE: return "ne"; + case LE: return "le"; + case GE: return "ge"; + case LT: return "lt"; + case GT: return "gt"; + case '+': return "add"; + case '-': return "sub"; + case '*': return "mul"; + case '/': return "div"; + case '%': return "rem"; + case MOD: return "mod"; + case '&': return "bitand"; + case '|': return "bitor"; + case '^': return "bitxor"; + case '~': return "bitnot"; + case '!': return "not"; + case SHL: return "shl"; + case SHR: return "shr"; + case '.': return "load"; default: return 0; } @@ -603,7 +603,7 @@ statement_is_cond (statement_t *s) { if (!s) return 0; - return !strncmp (s->opcode, "opcode, "if", 2); } int @@ -611,7 +611,7 @@ statement_is_goto (statement_t *s) { if (!s) return 0; - return !strcmp (s->opcode, ""); + return !strcmp (s->opcode, "jump"); } int @@ -619,7 +619,7 @@ statement_is_jumpb (statement_t *s) { if (!s) return 0; - return !strcmp (s->opcode, ""); + return !strcmp (s->opcode, "jumpb"); } int @@ -627,9 +627,9 @@ statement_is_call (statement_t *s) { if (!s) return 0; - if (!strncmp (s->opcode, "opcode, "call", 4)) return 1; - if (!strncmp (s->opcode, "opcode, "rcall", 5)) return 2; return 0; } @@ -639,7 +639,7 @@ statement_is_return (statement_t *s) { if (!s) return 0; - return !strncmp (s->opcode, "opcode, "return", 6); } sblock_t * @@ -687,18 +687,18 @@ statement_get_targetlist (statement_t *s) static void invert_conditional (statement_t *s) { - if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; - else if (!strcmp (s->opcode, "")) - s->opcode = ""; + if (!strcmp (s->opcode, "if")) + s->opcode = "ifnot"; + else if (!strcmp (s->opcode, "ifnot")) + s->opcode = "if"; + else if (!strcmp (s->opcode, "ifbe")) + s->opcode = "ifa"; + else if (!strcmp (s->opcode, "ifb")) + s->opcode = "ifae"; + else if (!strcmp (s->opcode, "ifae")) + s->opcode = "ifb"; + else if (!strcmp (s->opcode, "ifa")) + s->opcode = "ifbe"; } typedef sblock_t *(*statement_f) (sblock_t *, expr_t *); @@ -712,7 +712,7 @@ static sblock_t * expr_address (sblock_t *sblock, expr_t *e, operand_t **op) { statement_t *s; - s = new_statement (st_expr, "&", e); + s = new_statement (st_expr, "lea", e); sblock = statement_subexpr (sblock, e->e.address.lvalue, &s->opa); if (e->e.address.offset) { sblock = statement_subexpr (sblock, e->e.address.offset, &s->opb); @@ -797,8 +797,8 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) operand_t *dst = 0; operand_t *size = 0; static const char *opcode_sets[][2] = { - {"", ""}, - {"", ""}, + {"move", "movep"}, + {"memset", "memsetp"}, }; const unsigned max_count = 1 << 16; const char **opcode_set = opcode_sets[0]; @@ -887,7 +887,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) operand_t *src = 0; operand_t *dst = 0; operand_t *ofs = 0; - const char *opcode = "="; + const char *opcode = "assign"; st_type_t type; if (src_expr->type == ex_assign) { @@ -931,7 +931,7 @@ dereference_dst: // dst_expr is a dereferenced pointer, so need to un-dereference it // to get the pointer and switch to storep instructions. dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); - opcode = ".="; // FIXME find a nicer representation (lose strings?) + opcode = "store";// FIXME find a nicer representation (lose strings?) if (dst_expr->type == ex_address && dst_expr->e.address.offset && !is_const_ptr (dst_expr->e.address.lvalue)) { sblock = statement_subexpr (sblock, @@ -952,7 +952,7 @@ dereference_dst: } if (is_entity (dst->type) && ofs && is_field (ofs->type)) { - s = new_statement (st_expr, "&", dst_expr); + s = new_statement (st_expr, "lea", dst_expr); s->opa = dst; s->opb = ofs; s->opc = temp_operand (&type_ptr, dst_expr); @@ -1012,7 +1012,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) ind--; param = new_param_expr (get_type (a), ind); if (count && options.code.progsversion != PROG_ID_VERSION && ind < 2) { - pref = "R"; + pref = "r"; sblock = statement_subexpr (sblock, param, &arguments[ind]); if (options.code.vector_calls && a->type == ex_value && a->e.value->lltype == ev_vector) @@ -1037,7 +1037,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) arg = p; sblock = statement_subexpr (sblock, a, &arg); if (arg != p) { - s = new_statement (st_assign, "=", a); + s = new_statement (st_assign, "assign", a); s->opa = arg; s->opb = p; sblock_add_statement (sblock, s); @@ -1045,7 +1045,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) } } } - opcode = va (0, "<%sCALL%d>", pref, count); + opcode = va (0, "%scall%d", pref, count); s = new_statement (st_func, opcode, call); sblock = statement_subexpr (sblock, func, &s->opa); s->opb = arguments[0]; @@ -1059,13 +1059,13 @@ static sblock_t * statement_branch (sblock_t *sblock, expr_t *e) { static const char *opcodes[] = { - "", - "", - "", + "ifnot", + "ifb", + "ifa", 0, // special handling - "", - "", - "", + "if", + "ifae", + "ifbe", 0, // not used here }; statement_t *s = 0; @@ -1076,11 +1076,11 @@ statement_branch (sblock_t *sblock, expr_t *e) } if (e->e.branch.type == pr_branch_jump) { if (e->e.branch.index) { - s = new_statement (st_flow, "", e); + s = new_statement (st_flow, "jumpb", e); sblock = statement_subexpr (sblock, e->e.branch.target, &s->opa); sblock = statement_subexpr (sblock, e->e.branch.index, &s->opb); } else { - s = new_statement (st_flow, "", e); + s = new_statement (st_flow, "jump", e); s->opa = label_operand (e->e.branch.target); } } else { @@ -1102,10 +1102,10 @@ statement_return (sblock_t *sblock, expr_t *e) statement_t *s; debug (e, "RETURN"); - opcode = ""; + opcode = "return"; if (!e->e.retrn.ret_val) { if (options.code.progsversion != PROG_ID_VERSION) { - opcode = ""; + opcode = "return_v"; } else { e->e.retrn.ret_val = new_float_expr (0); } @@ -1125,7 +1125,7 @@ statement_return (sblock_t *sblock, expr_t *e) static statement_t * lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) { - statement_t *s = new_statement (st_expr, "&", e); + statement_t *s = new_statement (st_expr, "lea", e); s->opa = pointer; s->opb = offset; s->opc = temp_operand (&type_ptr, e); @@ -1162,14 +1162,14 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) dst_addr = operand_address (*op, e); - s = new_statement (st_ptrmove, "", deref); + s = new_statement (st_ptrmove, "movep", deref); s->opa = src_addr; //FIXME large types s->opb = short_operand (type_size (type), e); s->opc = dst_addr; sblock_add_statement (sblock, s); } else { - s = new_statement (st_expr, ".", deref); + s = new_statement (st_expr, "load", deref); s->opa = ptr; s->opb = offs; s->opc = *op; @@ -1186,7 +1186,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) sblock = statement_subexpr (sblock, e, &ptr); if (!*op) *op = temp_operand (type, e); - s = new_statement (st_expr, ".", deref); + s = new_statement (st_expr, "load", deref); s->opa = ptr; s->opb = short_operand (0, e); s->opc = *op; @@ -1295,7 +1295,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) operand_t *src = 0; sblock = statement_subexpr (sblock, e->e.expr.e1, &src); *op = temp_operand (e->e.expr.type, e); - s = new_statement (st_expr, "", e); + s = new_statement (st_expr, "conv", e); s->opa = src; s->opc = *op; sblock_add_statement (sblock, s); @@ -1483,7 +1483,7 @@ expr_nil (sblock_t *sblock, expr_t *e, operand_t **op) sblock = statement_subexpr (sblock, new_int_expr(0), &zero); sblock = statement_subexpr (sblock, size_expr, &size); - s = new_statement (st_memset, "", e); + s = new_statement (st_memset, "memset", e); s->opa = zero; s->opb = size; s->opc = *op; @@ -1549,7 +1549,7 @@ statement_state (sblock_t *sblock, expr_t *e) { statement_t *s; - s = new_statement (st_state, "", e); + s = new_statement (st_state, "state", e); sblock = statement_subexpr (sblock, e->e.state.frame, &s->opa); sblock = statement_subexpr (sblock, e->e.state.think, &s->opb); sblock = statement_subexpr (sblock, e->e.state.step, &s->opc); @@ -1738,7 +1738,7 @@ statement_memset (sblock_t *sblock, expr_t *e) expr_t *dst = e->e.memset.dst; expr_t *val = e->e.memset.val; expr_t *count = e->e.memset.count; - const char *opcode = ""; + const char *opcode = "memset"; statement_t *s; if (is_constant (count)) { @@ -2115,9 +2115,9 @@ check_final_block (sblock_t *sblock) sblock->next = new_sblock (); sblock = sblock->next; } - s = new_statement (st_func, "", 0); + s = new_statement (st_func, "return_v", 0); if (options.traditional || options.code.progsversion == PROG_ID_VERSION) { - s->opcode = save_string (""); + s->opcode = save_string ("return"); s->opa = return_operand (&type_void, 0); } sblock_add_statement (sblock, s); From a4ebd6aa58ed28584631ee7ba3da00d6d92693e1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 12:41:01 +0900 Subject: [PATCH 2234/3664] [gamecode] Fix a few missed opcode renames if and ifnot became ifnz and ifz, and return_v lost its tail (it was always redundant, except in dags, and that's fixed with a pointer check). --- libs/gamecode/pr_v6p_opcode.c | 6 +++--- tools/qfcc/source/dags.c | 2 +- tools/qfcc/source/opcodes.c | 4 ++-- tools/qfcc/source/statements.c | 21 +++++++++------------ 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 20f717154..e9b3a0b7a 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -756,7 +756,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ra", }, - [OP_RETURN_V_v6p] = {"return_v", "return", + [OP_RETURN_V_v6p] = {"return", "return", ev_invalid, ev_invalid, ev_invalid, PROG_V6P_VERSION, "", @@ -803,12 +803,12 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { "%Ga, %gc", }, - [OP_IF_v6p] = {"if", "if", + [OP_IF_v6p] = {"ifnz", "if", ev_int, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", }, - [OP_IFNOT_v6p] = {"ifnot", "ifnot", + [OP_IFNOT_v6p] = {"ifz", "ifnot", ev_int, ev_short, ev_invalid, PROG_ID_VERSION, "%Ga branch %sb (%Ob)", diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 3040c5425..bdfd4ab7d 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -457,7 +457,7 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) first_param = 2; } else if (!strncmp (n->label->opcode, "call", 4)) { num_params = n->label->opcode + 5; - } else if (!strcmp (n->label->opcode, "return")) { + } else if (!strcmp (n->label->opcode, "return") && n->children[0]) { daglabel_t *label = n->children[0]->label; if (!label->op) { set_iter_t *lab_i; diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index d0f11684b..f0cc4e358 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -60,8 +60,8 @@ static v6p_uint_opcode_t v6p_uint_opcodes[] = { {OP_STOREP_I_v6p, {"store", "storep.i", ev_uint, ev_ptr, ev_invalid }}, {OP_STOREB_I_v6p, {"store", "storeb.i", ev_uint, ev_ptr, ev_int }}, {OP_STOREBI_I_v6p, {"store", "storebi.i",ev_uint, ev_ptr, ev_short }}, - {OP_IF_v6p, {"if", "if", ev_uint, ev_short, ev_invalid }}, - {OP_IFNOT_v6p, {"ifnot", "ifnot", ev_uint, ev_short, ev_invalid }}, + {OP_IF_v6p, {"ifnz", "if", ev_uint, ev_short, ev_invalid }}, + {OP_IFNOT_v6p, {"ifz", "ifnot", ev_uint, ev_short, ev_invalid }}, {OP_ADD_I_v6p, {"add", "add.i", ev_uint, ev_uint, ev_uint }}, {OP_SUB_I_v6p, {"sub", "sub.i", ev_uint, ev_uint, ev_uint }}, {OP_MUL_I_v6p, {"mul", "mul.i", ev_uint, ev_uint, ev_uint }}, diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index bc7013f91..48257be54 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -687,10 +687,10 @@ statement_get_targetlist (statement_t *s) static void invert_conditional (statement_t *s) { - if (!strcmp (s->opcode, "if")) - s->opcode = "ifnot"; - else if (!strcmp (s->opcode, "ifnot")) - s->opcode = "if"; + if (!strcmp (s->opcode, "ifnz")) + s->opcode = "ifz"; + else if (!strcmp (s->opcode, "ifz")) + s->opcode = "ifnz"; else if (!strcmp (s->opcode, "ifbe")) s->opcode = "ifa"; else if (!strcmp (s->opcode, "ifb")) @@ -931,7 +931,7 @@ dereference_dst: // dst_expr is a dereferenced pointer, so need to un-dereference it // to get the pointer and switch to storep instructions. dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); - opcode = "store";// FIXME find a nicer representation (lose strings?) + opcode = "store"; if (dst_expr->type == ex_address && dst_expr->e.address.offset && !is_const_ptr (dst_expr->e.address.lvalue)) { sblock = statement_subexpr (sblock, @@ -1059,11 +1059,11 @@ static sblock_t * statement_branch (sblock_t *sblock, expr_t *e) { static const char *opcodes[] = { - "ifnot", + "ifz", "ifb", "ifa", 0, // special handling - "if", + "ifnz", "ifae", "ifbe", 0, // not used here @@ -1104,9 +1104,7 @@ statement_return (sblock_t *sblock, expr_t *e) debug (e, "RETURN"); opcode = "return"; if (!e->e.retrn.ret_val) { - if (options.code.progsversion != PROG_ID_VERSION) { - opcode = "return_v"; - } else { + if (options.code.progsversion == PROG_ID_VERSION) { e->e.retrn.ret_val = new_float_expr (0); } } @@ -2115,9 +2113,8 @@ check_final_block (sblock_t *sblock) sblock->next = new_sblock (); sblock = sblock->next; } - s = new_statement (st_func, "return_v", 0); + s = new_statement (st_func, "return", 0); if (options.traditional || options.code.progsversion == PROG_ID_VERSION) { - s->opcode = save_string ("return"); s->opa = return_operand (&type_void, 0); } sblock_add_statement (sblock, s); From 19baae6969eb1990bb899a34eada2c303bcdfe4e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 12:55:56 +0900 Subject: [PATCH 2235/3664] [qfcc] Dump emitted statements when verbosity >= 2 I wish I had done this years (decades, even!) ago. It makes checking the output so much easier. --- tools/qfcc/include/opcodes.h | 1 + tools/qfcc/source/emit.c | 4 ++++ tools/qfcc/source/opcodes.c | 12 ++++++++++++ 3 files changed, 17 insertions(+) diff --git a/tools/qfcc/include/opcodes.h b/tools/qfcc/include/opcodes.h index fa100fb6b..055066f4b 100644 --- a/tools/qfcc/include/opcodes.h +++ b/tools/qfcc/include/opcodes.h @@ -40,5 +40,6 @@ pr_ushort_t opcode_get (instruction_t *inst) __attribute__((pure)); instruction_t *opcode_find (const char *name, struct operand_s *op_a, struct operand_s *op_b, struct operand_s *op_c); void opcode_init (void); +void opcode_print_statement (pr_uint_t addr, dstatement_t *st); #endif//__opcodes_h diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index dc5bb4b2d..ceb67622a 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -217,6 +217,10 @@ emit_statement (statement_t *statement) s->b = def_b ? def_b->offset : 0; s->c = def_c ? def_c->offset : 0; + if (options.verbosity >= 2) { + opcode_print_statement (pr.code->size - 1, s); + } + add_statement_def_ref (def_a, s, 0); add_statement_def_ref (def_b, s, 1); add_statement_def_ref (def_c, s, 2); diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index f0cc4e358..3815c54e1 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -351,3 +351,15 @@ opcode_init (void) rua_opcode_init (); } } + +void +opcode_print_statement (pr_uint_t addr, dstatement_t *st) +{ + const char *mnemonic; + if (options.code.progsversion < PROG_VERSION) { + mnemonic = v6p_opcode_map[st->op].opname; + } else { + mnemonic = pr_opcodes[st->op].mnemonic; + } + printf ("%04x %8s %04x %04x %04x\n", addr, mnemonic, st->a, st->b, st->c); +} From 875d4dc7cf8bde96a72a7ad3c4cf30c3c803d1a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 13:02:12 +0900 Subject: [PATCH 2236/3664] [gamecode] Correct some ruamoko instruction meta data There were some errors in instruction names and operand types resulting in unsearchable instructions. --- libs/gamecode/opcodes.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index f35067a7e..6ff35e892 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -93,7 +93,7 @@ branch_formats = { "opname": "{op_cond[c*4+cc]}", "format": "{cond_fmt[c*4+cc]}{branch_fmt[0]}", "widths": "{cond_widths[c*4+cc]}", - "types": "ev_void, ev_void, ev_int", + "types": "ev_short, ev_invalid, ev_int", "args": { "op_mode": "ABCD", "op_cond": ["ifz", "ifb", "ifa", None, @@ -173,12 +173,18 @@ jump_formats = { "opcode": "OP_JUMP_{op_mode[mm]}", "mnemonic": "jump", "opname": "jump", - "format": "{branch_fmt[mm]}", + "format": "{jump_fmt[mm]}", "widths": "0, 0, 0", - "types": "ev_void, ev_void, ev_invalid", + "types": "{jump_types[mm]}", "args": { "op_mode": "ABCD", - "branch_fmt": branch_fmt, + "jump_fmt": branch_fmt, + "jump_types": [ + "ev_short, ev_invalid, ev_invalid", + "ev_ptr, ev_invalid, ev_invalid", + "ev_ptr, ev_short, ev_invalid", + "ev_ptr, ev_int, ev_invalid", + ], }, } lea_formats = { @@ -358,11 +364,11 @@ stated_formats = { } store_formats = { "opcode": "OP_STORE_{op_mode[mm]}_{ss+1}", - "mnemonic": "store", - "opname": "store", + "mnemonic": "{store_op[mm]}", + "opname": "{store_op[mm]}", "format": "{store_fmt[mm]}", "widths": "{ss+1}, 0, {ss+1}", - "types": "ev_void, ev_void, ev_void", + "types": "{store_types[mm]}", "args": { "op_mode": "ABCD", "store_fmt": [ @@ -371,6 +377,13 @@ store_formats = { "%Gc, *(%Ga + %sb)", "%Gc, *(%Ga + %Gb)", ], + "store_op": ["assign", "store", "store", "store"], + "store_types": [ + "ev_void, ev_invalid, ev_void", + "ev_ptr, ev_invalid, ev_void", + "ev_ptr, ev_short, ev_void", + "ev_ptr, ev_int, ev_void", + ], }, } string_formats = { From a5a80172202a133c4df4bb06bac62e2d59c5a5eb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 13:05:08 +0900 Subject: [PATCH 2237/3664] [qfcc] Switch internal statement format to ruamoko For the most part, it wasn't too bad as it's just a rotation of the operands for some instructions (store, assign, branch), but dealing with all the direct accesses to specific operands was a small pain. I am very glad I made all those automated tests :) --- tools/qfcc/source/dags.c | 18 ++++++------ tools/qfcc/source/emit.c | 30 +++++++++++++++----- tools/qfcc/source/flow.c | 48 ++++++++++++++++++++----------- tools/qfcc/source/statements.c | 52 ++++++++++++++++++++-------------- 4 files changed, 94 insertions(+), 54 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index bdfd4ab7d..5b3a64b3d 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -1116,12 +1116,12 @@ generate_assignments (dag_t *dag, sblock_t *block, operand_t *src, operand_t *operands[3] = {0, 0, 0}; daglabel_t *var; - operands[0] = fix_op_type (src, type); + operands[2] = fix_op_type (src, type); for ( ; var_iter; var_iter = set_next (var_iter)) { var = dag->labels[var_iter->element]; - operands[1] = fix_op_type (var->op, type); + operands[0] = fix_op_type (var->op, type); if (!dst) - dst = operands[1]; + dst = operands[0]; st = build_statement ("assign", operands, var->expr); sblock_add_statement (block, st); @@ -1172,15 +1172,15 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) case st_assign: internal_error (0, "unexpected assignment node"); case st_ptrassign: - operands[0] = make_operand (dag, block, dagnode, 0); - operands[1] = make_operand (dag, block, dagnode, 1); - if (dagnode->children[2]) - operands[2] = make_operand (dag, block, dagnode, 2); + operands[2] = make_operand (dag, block, dagnode, 0); + operands[0] = make_operand (dag, block, dagnode, 2); + if (dagnode->children[1]) + operands[1] = make_operand (dag, block, dagnode, 1); st = build_statement (dagnode->label->opcode, operands, dagnode->label->expr); sblock_add_statement (block, st); // the source location is suitable for use in other nodes - dst = operands[0]; + dst = operands[2]; break; case st_move: dst = generate_moves (dag, block, dagnode); @@ -1207,6 +1207,8 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[0] = make_operand (dag, block, dagnode, 0); if (dagnode->children[1]) operands[1] = make_operand (dag, block, dagnode, 1); + if (dagnode->children[2]) + operands[2] = make_operand (dag, block, dagnode, 2); st = build_statement (dagnode->label->opcode, operands, dagnode->label->expr); sblock_add_statement (block, st); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index ceb67622a..3ee80df7f 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -183,20 +183,36 @@ static void emit_statement (statement_t *statement) { const char *opcode = statement->opcode; + operand_t *op_a, *op_b, *op_c; def_t *def_a, *def_b, *def_c; instruction_t *inst; dstatement_t *s; - def_a = get_operand_def (statement->expr, statement->opa); + if (options.code.progsversion < PROG_VERSION + && (strcmp (statement->opcode, "store") == 0 + || strcmp (statement->opcode, "assign") == 0 + || statement_is_cond (statement))) { + // the operands for assign, store and branch instructions are rotated + // when comparing v6/v6p and ruamoko + op_a = statement->opc; + op_b = statement->opa; + op_c = statement->opb; + } else { + op_a = statement->opa; + op_b = statement->opb; + op_c = statement->opc; + } + def_a = get_operand_def (statement->expr, op_a); use_tempop (statement->opa, statement->expr); - def_b = get_operand_def (statement->expr, statement->opb); + def_b = get_operand_def (statement->expr, op_b); use_tempop (statement->opb, statement->expr); - def_c = get_operand_def (statement->expr, statement->opc); + def_c = get_operand_def (statement->expr, op_c); use_tempop (statement->opc, statement->expr); - inst = opcode_find (opcode, statement->opa, statement->opb, statement->opc); + inst = opcode_find (opcode, op_a, op_b, op_c); if (!inst) { print_expr (statement->expr); + printf ("%d ", pr.code->size); print_statement (statement); internal_error (statement->expr, "ice ice baby"); } @@ -225,9 +241,9 @@ emit_statement (statement_t *statement) add_statement_def_ref (def_b, s, 1); add_statement_def_ref (def_c, s, 2); - add_statement_op_ref (statement->opa, s, 0); - add_statement_op_ref (statement->opb, s, 1); - add_statement_op_ref (statement->opc, s, 2); + add_statement_op_ref (op_a, s, 0); + add_statement_op_ref (op_b, s, 1); + add_statement_op_ref (op_c, s, 2); } void diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index d713b1ce8..5ed2022da 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1149,9 +1149,11 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, operand_t *operands[FLOW_OPERANDS]) { int i, start, calln = -1; + operand_t *src_op = 0; operand_t *res_op = 0; operand_t *aux_op1 = 0; operand_t *aux_op2 = 0; + operand_t *aux_op3 = 0; if (use) { set_empty (use); @@ -1191,11 +1193,11 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_assign: - flow_add_op_var (def, s->opb, 0); - flow_add_op_var (use, s->opa, 1); + flow_add_op_var (def, s->opa, 0); + flow_add_op_var (use, s->opc, 1); if (operands) { - operands[0] = s->opb; - operands[1] = s->opa; + operands[0] = s->opa; + operands[1] = s->opc; } break; case st_ptrassign: @@ -1205,23 +1207,28 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, case st_ptrmemset: flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opb, 1); + aux_op1 = s->opb; if (!strcmp (s->opcode, "move") || !strcmp (s->opcode, "memset")) { flow_add_op_var (def, s->opc, 0); + src_op = s->opa; res_op = s->opc; } else if (!strcmp (s->opcode, "movep")) { flow_add_op_var (use, s->opc, 0); - aux_op2 = flow_analyze_pointer_operand (s->opa, use); + aux_op3 = flow_analyze_pointer_operand (s->opa, use); res_op = flow_analyze_pointer_operand (s->opc, def); - aux_op1 = s->opc; + src_op = s->opa; + aux_op2 = s->opc; } else if (!strcmp (s->opcode, "memsetp")) { flow_add_op_var (use, s->opc, 0); res_op = flow_analyze_pointer_operand (s->opc, def); - aux_op1 = s->opc; + src_op = s->opa; + aux_op2 = s->opc; } else if (!strcmp (s->opcode, "store")) { - flow_add_op_var (use, s->opc, 1); - res_op = flow_analyze_pointer_operand (s->opb, def); - aux_op1 = s->opc; + flow_add_op_var (use, s->opb, 1); + res_op = flow_analyze_pointer_operand (s->opa, def); + src_op = s->opc; + aux_op2 = s->opa; } else { internal_error (s->expr, "unexpected opcode '%s' for %d", s->opcode, s->type); @@ -1231,10 +1238,10 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } if (operands) { operands[0] = res_op; - operands[1] = s->opa; - operands[2] = s->opb; - operands[3] = aux_op1; - operands[4] = aux_op2; + operands[1] = src_op; + operands[2] = aux_op1; + operands[3] = aux_op2; + operands[4] = aux_op3; } break; case st_state: @@ -1296,14 +1303,21 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_flow: - if (strcmp (s->opcode, "jump") != 0) { + if (statement_is_goto (s)) { + // opa is just a label + } else if (statement_is_jumpb (s)) { flow_add_op_var (use, s->opa, 1); - if (strcmp (s->opcode, "jumpb") == 0) - flow_add_op_var (use, s->opb, 1); + flow_add_op_var (use, s->opb, 1); + } else if (statement_is_cond (s)) { + flow_add_op_var (use, s->opc, 1); + } else { + internal_error (s->expr, "unexpected flow statement: %s", + s->opcode); } if (operands) { operands[1] = s->opa; operands[2] = s->opb; + operands[3] = s->opc; } break; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 48257be54..cd9245a93 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -642,14 +642,22 @@ statement_is_return (statement_t *s) return !strncmp (s->opcode, "return", 6); } +static ex_label_t ** +statement_get_labelref (statement_t *s) +{ + if (statement_is_cond (s) + || statement_is_goto (s) + || statement_is_jumpb (s)) { + return &s->opa->label; + } + return 0; +} + sblock_t * statement_get_target (statement_t *s) { - if (statement_is_cond (s)) - return s->opb->label->dest; - if (statement_is_goto (s)) - return s->opa->label->dest; - return 0; + ex_label_t **label = statement_get_labelref (s); + return label ? (*label)->dest : 0; } sblock_t ** @@ -961,9 +969,9 @@ dereference_dst: ofs = 0; } s = new_statement (type, opcode, e); - s->opa = src; - s->opb = dst; - s->opc = ofs; + s->opa = dst; + s->opb = ofs; + s->opc = src; sblock_add_statement (sblock, s); return sblock; } @@ -1038,8 +1046,8 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) sblock = statement_subexpr (sblock, a, &arg); if (arg != p) { s = new_statement (st_assign, "assign", a); - s->opa = arg; - s->opb = p; + s->opa = p; + s->opc = arg; sblock_add_statement (sblock, s); } } @@ -1086,8 +1094,8 @@ statement_branch (sblock_t *sblock, expr_t *e) } else { opcode = opcodes [e->e.branch.type]; s = new_statement (st_flow, opcode, e); - sblock = statement_subexpr (sblock, e->e.branch.test, &s->opa); - s->opb = label_operand (e->e.branch.target); + sblock = statement_subexpr (sblock, e->e.branch.test, &s->opc); + s->opa = label_operand (e->e.branch.target); } sblock_add_statement (sblock, s); @@ -1928,14 +1936,15 @@ thread_jumps (sblock_t *blocks) (*label)->symbol = 0; } } else if (statement_is_cond (s)) { - label = &s->opb->label; + label = &s->opa->label; } else { continue; } for (l = *label; l->dest && l->dest->statements && statement_is_goto (l->dest->statements); - l = l->dest->statements->opa->label) { + l = *statement_get_labelref (l->dest->statements)) { + // empty loop } if (l != *label) { unuse_label (*label); @@ -1988,11 +1997,12 @@ remove_dead_blocks (sblock_t *blocks) s = (statement_t *) sblock->tail; if (statement_is_cond (s) && sb->statements && statement_is_goto (sb->statements) - && s->opb->label->dest == sb->next) { + && statement_get_target (s) == sb->next) { debug (0, "merging if/goto %p %p", sblock, sb); - unuse_label (s->opb->label); - s->opb->label = sb->statements->opa->label; - s->opb->label->used++; + ex_label_t **labelref = statement_get_labelref(s); + unuse_label (*labelref); + *labelref = *statement_get_labelref (sb->statements); + (*labelref)->used++; invert_conditional (s); sb->reachable = 0; for (sb = sb->next; sb; sb = sb->next) @@ -2014,10 +2024,8 @@ remove_dead_blocks (sblock_t *blocks) if (sb->statements) { s = (statement_t *) sb->tail; - if (statement_is_goto (s)) - label = s->opa->label; - else if (statement_is_cond (s)) - label = s->opb->label; + ex_label_t **labelref = statement_get_labelref (s); + label = labelref ? *labelref : 0; } unuse_label (label); did_something = 1; From 6ae9daf4b7cf89c3a8e22368ac098e1132a37de5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 14:52:59 +0900 Subject: [PATCH 2238/3664] [gamecode] Clean out dead any/all/none data The instructions are gone as hor/hand/hnor take care of them. --- libs/gamecode/opcodes.py | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 6ff35e892..c8316eb16 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -52,22 +52,6 @@ etype_tt = ["ev_int", "ev_float", "ev_long", "ev_double"] unsigned_t = ["ev_uint", "ev_ulong"] float_t = ["ev_float", "ev_double"] -all_formats = { - "opcode": "OP_ALL_{ss+1}", - "mnemonic": "all", - "opname": "all", - "format": "%Ga, %gc", - "widths": "{ss+1}, 0, 1", - "types": "ev_int, ev_int, ev_int", -} -any_formats = { - "opcode": "OP_ANY_{ss+1}", - "mnemonic": "any", - "opname": "any", - "format": "%Ga, %gc", - "widths": "{ss+1}, 0, 1", - "types": "ev_int, ev_int, ev_int", -} bitops_formats = { "opcode": "OP_{op_bit[oo].upper()}_{bit_type[t]}_{ss+1}", "mnemonic": "{op_bit[oo]}", @@ -252,14 +236,6 @@ move_formats = { "move_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], }, } -none_formats = { - "opcode": "OP_NONE_{ss+1}", - "mnemonic": "none", - "opname": "none", - "format": "%Ga, %gc", - "widths": "{ss+1}, 0, 1", - "types": "ev_int, ev_invalid, ev_int", -} push_formats = { "opcode": "OP_PUSH_{op_mode[mm]}_{ss+1}", "mnemonic": "push", @@ -482,8 +458,6 @@ with_formats = { } group_map = { - "all": all_formats, - "any": any_formats, "bitops": bitops_formats, "branch": branch_formats, "call": call_formats, @@ -497,7 +471,6 @@ group_map = { "mathops": mathops_formats, "memset": memset_formats, "move": move_formats, - "none": none_formats, "push": push_formats, "pushregs": pushregs_formats, "pop": pop_formats, From e20aed5c5a2aaea758eb9f14916f4906b4cd32bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 14:55:29 +0900 Subject: [PATCH 2239/3664] [gamecode] Change address mode B to entity.field It turned out that address mode B was redundant as C with 0 offset (immediate) was the same (except for the underlying C code of course, but adding st->b is very cheap). This allowed B to be used for entity.field for all transfer operations. Thus instructions 0-3 are now free as load E became load B, and other than the specifics of format codes for statement printing, transfers+lea are unified. --- libs/gamecode/opcodes.py | 87 ++++++++++++++++----------------- libs/gamecode/pr_exec.c | 39 +++------------ libs/gamecode/test/test-lea.c | 2 +- libs/gamecode/test/test-load.c | 32 +++--------- libs/gamecode/test/test-stack.c | 26 ++++++---- libs/gamecode/test/test-store.c | 13 +++-- 6 files changed, 82 insertions(+), 117 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index c8316eb16..40d84c341 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -4,6 +4,7 @@ bitmap_txt = """ 0 0010 mmss push 0 0011 mmss pop 0 1ccc ttss compare +0 0000 00nn 0 1011 nnnn 0 1111 nnnn @@ -34,11 +35,26 @@ bitmap_txt = """ import copy +address_mode = "ABCD" +address_types = [ + "ev_void, ev_invalid", + "ev_entity, ev_field", + "ev_ptr, ev_short", + "ev_ptr, ev_int", +] +#store, pop and lea +store_fmt = [ + "%ga", + "%Ga.%Gb(%Ea)", + "*(%Ga + %sb)", + "*(%Ga + %Gb)", +] +# load and push load_fmt = [ - "%Ga.%Gb(%Ea), %gc", "*%Ga, %gc", - "*(%Ga + %sb), %gc", - "*(%Ga + %Gb), %gc", + "%Ga.%Gb(%Ea)", + "*(%Ga + %sb)", + "*(%Ga + %Gb)", ] branch_fmt = [ "branch %sa (%Oa)", @@ -175,29 +191,26 @@ lea_formats = { "opcode": "OP_LEA_{op_mode[mm]}", "mnemonic": "lea", "opname": "lea", - "format": "{lea_fmt[mm]}", + "format": "{lea_fmt[mm]}, %gc", "widths": "0, 0, 1", - "types": "ev_ptr, ev_ptr, ev_ptr", + "types": "{lea_types[mm]}, ev_ptr", "args": { - "op_mode": "AECD", - "lea_fmt": [ - "%ga, %gc", - "%Ga.%Gb(%Ea), %gc", - "*(%Ga + %sb), %gc", - "*(%Ga + %Gb), %gc", - ], + "op_mode": address_mode, + "lea_fmt": store_fmt, + "lea_types": address_types, }, } load_formats = { "opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}", "mnemonic": "load", "opname": "load", - "format": "{load_fmt[mm]}", + "format": "{load_fmt[mm]}, %gc", "widths": "0, 0, {ss+1}", - "types": "ev_void, ev_void, ev_void", + "types": "{load_types[mm]}, ev_void", "args": { - "op_mode": "EBCD", + "op_mode": address_mode, "load_fmt": load_fmt, + "load_types": address_types, }, } mathops_formats = { @@ -242,15 +255,11 @@ push_formats = { "opname": "push", "format": "{push_fmt[mm]}", "widths": "{ss+1}, 0, 0", - "types": "ev_void, ev_void, ev_invalid", + "types": "{push_types[mm]}, ev_invalid", "args": { - "op_mode": "ABCD", - "push_fmt": [ - "%Ga", - "*%Ga", - "*(%Ga + %sb)", - "*(%Ga + %Gb)", - ], + "op_mode": address_mode, + "push_fmt": load_fmt, + "push_types": address_types, }, } pushregs_formats = { @@ -267,15 +276,11 @@ pop_formats = { "opname": "pop", "format": "{pop_fmt[mm]}", "widths": "{ss+1}, 0, 0", - "types": "ev_void, ev_void, ev_invalid", + "types": "{pop_types[mm]}, ev_invalid", "args": { - "op_mode": "ABCD", - "pop_fmt": [ - "%ga", - "*%Ga", - "*(%Ga + %sb)", - "*(%Ga + %Gb)", - ], + "op_mode": address_mode, + "pop_fmt": store_fmt, + "pop_types": address_types, }, } popregs_formats = { @@ -342,24 +347,14 @@ store_formats = { "opcode": "OP_STORE_{op_mode[mm]}_{ss+1}", "mnemonic": "{store_op[mm]}", "opname": "{store_op[mm]}", - "format": "{store_fmt[mm]}", + "format": "%Gc, {store_fmt[mm]}", "widths": "{ss+1}, 0, {ss+1}", - "types": "{store_types[mm]}", + "types": "{store_types[mm]}, ev_void", "args": { - "op_mode": "ABCD", - "store_fmt": [ - "%Gc, %ga", - "%Gc, *%Ga", - "%Gc, *(%Ga + %sb)", - "%Gc, *(%Ga + %Gb)", - ], + "op_mode": address_mode, + "store_fmt": store_fmt, "store_op": ["assign", "store", "store", "store"], - "store_types": [ - "ev_void, ev_invalid, ev_void", - "ev_ptr, ev_invalid, ev_void", - "ev_ptr, ev_short, ev_void", - "ev_ptr, ev_int, ev_void", - ], + "store_types": address_types, }, } string_formats = { diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 7ca7d6ad9..1e7f9634c 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1759,8 +1759,9 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) mm_offs = op_a - pr->pr_globals; break; case 1: - // simple pointer dereference: *a - mm_offs = OPA(ptr); + // entity.field (equivalent to OP_LOAD_t_v6p) + pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; + mm_offs = edict_area + OPA(entity) + OPB(field); break; case 2: // constant indexed pointer: *a + b (supports -ve offset) @@ -1770,11 +1771,6 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) // variable indexed pointer: *a + *b (supports -ve offset) mm_offs = OPA(ptr) + OPB(int); break; - case 4: - // entity.field (equivalent to OP_LOAD_t_v6p) - pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; - mm_offs = edict_area + OPA(entity) + OPB(field); - break; } return pr->pr_globals + mm_offs; } @@ -2767,44 +2763,28 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) pr_opcode_e st_op = st->op & OP_MASK; switch (st_op) { // 0 0000 - case OP_LOAD_E_1: - mm = pr_address_mode (pr, st, 4); - OPC(int) = MM(int); - break; case OP_LOAD_B_1: case OP_LOAD_C_1: case OP_LOAD_D_1: - mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_1) >> 2); + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_1 + 4) >> 2); OPC(int) = MM(int); break; - case OP_LOAD_E_2: - mm = pr_address_mode (pr, st, 4); - OPC(ivec2) = MM(ivec2); - break; case OP_LOAD_B_2: case OP_LOAD_C_2: case OP_LOAD_D_2: - mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_2) >> 2); + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_2 + 4) >> 2); OPC(ivec2) = MM(ivec2); break; - case OP_LOAD_E_3: - mm = pr_address_mode (pr, st, 4); - VectorCopy (&MM(int), &OPC(int)); - break; case OP_LOAD_B_3: case OP_LOAD_C_3: case OP_LOAD_D_3: - mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_3) >> 2); + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_3 + 4) >> 2); VectorCopy (&MM(int), &OPC(int)); break; - case OP_LOAD_E_4: - mm = pr_address_mode (pr, st, 4); - OPC(ivec4) = MM(ivec4); - break; case OP_LOAD_B_4: case OP_LOAD_C_4: case OP_LOAD_D_4: - mm = pr_address_mode (pr, st, (st_op - OP_LOAD_E_4) >> 2); + mm = pr_address_mode (pr, st, (st_op - OP_LOAD_B_4 + 4) >> 2); OPC(ivec4) = MM(ivec4); break; // 0 0001 @@ -3389,15 +3369,12 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; // 1 1111 case OP_LEA_A: + case OP_LEA_B: case OP_LEA_C: case OP_LEA_D: mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); op_c->pointer_var = mm - pr->pr_globals; break; - case OP_LEA_E: - mm = pr_address_mode (pr, st, 4); - op_c->pointer_var = mm - pr->pr_globals; - break; case OP_QV4MUL_F: OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); break; diff --git a/libs/gamecode/test/test-lea.c b/libs/gamecode/test/test-lea.c index 1a4f159f7..33e148c16 100644 --- a/libs/gamecode/test/test-lea.c +++ b/libs/gamecode/test/test-lea.c @@ -22,7 +22,7 @@ static dstatement_t lea_statements[] = { {OP(0, 0, 0, OP_LEA_A), 7, 9, 12}, {OP(0, 0, 0, OP_LEA_C), 2, 6, 13}, {OP(0, 0, 0, OP_LEA_D), 2, 6, 14}, - {OP(0, 0, 0, OP_LEA_E), 4, 2, 15}, + {OP(0, 0, 0, OP_LEA_B), 4, 2, 15}, }; test_t tests[] = { diff --git a/libs/gamecode/test/test-load.c b/libs/gamecode/test/test-load.c index e283ced38..986a58163 100644 --- a/libs/gamecode/test/test-load.c +++ b/libs/gamecode/test/test-load.c @@ -30,20 +30,12 @@ static pr_int_t test_globals_expect[] = { 1, 2, 3, 4, }; -static dstatement_t load_E_statements[] = { - {OP(0, 0, 0, OP_LOAD_E_4), 7, 9, 12}, - {OP(0, 0, 0, OP_LOAD_E_3), 7, 8, 16}, - {OP(0, 0, 0, OP_LOAD_E_1), 7, 7, 19}, - {OP(0, 0, 0, OP_LOAD_E_2), 7, 6, 20}, - {OP(0, 0, 0, OP_LOAD_E_2), 7, 5, 22}, -}; - static dstatement_t load_B_statements[] = { - {OP(0, 0, 0, OP_LOAD_B_4), 4, 0, 12}, - {OP(0, 0, 0, OP_LOAD_B_3), 3, 0, 16}, - {OP(0, 0, 0, OP_LOAD_B_1), 2, 0, 19}, - {OP(0, 0, 0, OP_LOAD_B_2), 1, 0, 20}, - {OP(0, 0, 0, OP_LOAD_B_2), 0, 0, 22}, + {OP(0, 0, 0, OP_LOAD_B_4), 7, 9, 12}, + {OP(0, 0, 0, OP_LOAD_B_3), 7, 8, 16}, + {OP(0, 0, 0, OP_LOAD_B_1), 7, 7, 19}, + {OP(0, 0, 0, OP_LOAD_B_2), 7, 6, 20}, + {OP(0, 0, 0, OP_LOAD_B_2), 7, 5, 22}, }; static dstatement_t load_C_statements[] = { @@ -63,17 +55,6 @@ static dstatement_t load_D_statements[] = { }; test_t tests[] = { - { - .desc = "load E", - .num_globals = num_globals (test_globals_init, test_globals_expect), - .num_statements = num_statements (load_E_statements), - .statements = load_E_statements, - .init_globals = test_globals_init, - .expect_globals = test_globals_expect, - // FIXME negative field offsets are not official but work because all - // offset calculations are done in 32-bit and thus wrap anyway - .edict_area = 28, - }, { .desc = "load B", .num_globals = num_globals (test_globals_init, test_globals_expect), @@ -81,6 +62,9 @@ test_t tests[] = { .statements = load_B_statements, .init_globals = test_globals_init, .expect_globals = test_globals_expect, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 28, }, { .desc = "load C", diff --git a/libs/gamecode/test/test-stack.c b/libs/gamecode/test/test-stack.c index 183e33694..eba5a06d8 100644 --- a/libs/gamecode/test/test-stack.c +++ b/libs/gamecode/test/test-stack.c @@ -81,11 +81,11 @@ static dstatement_t stack_AB_statements[] = { {OP(0, 0, 0, OP_PUSH_A_2), 20, 0, 0}, {OP(0, 0, 0, OP_PUSH_A_2), 22, 0, 0}, - {OP(0, 0, 0, OP_POP_B_2), 0, 0, 0}, - {OP(0, 0, 0, OP_POP_B_2), 1, 0, 0}, - {OP(0, 0, 0, OP_POP_B_1), 2, 0, 0}, - {OP(0, 0, 0, OP_POP_B_3), 3, 0, 0}, - {OP(0, 0, 0, OP_POP_B_4), 4, 0, 0}, + {OP(0, 0, 0, OP_POP_B_2), 7, 5, 0}, + {OP(0, 0, 0, OP_POP_B_2), 7, 6, 0}, + {OP(0, 0, 0, OP_POP_B_1), 7, 7, 0}, + {OP(0, 0, 0, OP_POP_B_3), 7, 8, 0}, + {OP(0, 0, 0, OP_POP_B_4), 7, 9, 0}, }; static dstatement_t stack_AC_statements[] = { @@ -117,11 +117,11 @@ static dstatement_t stack_AD_statements[] = { }; static dstatement_t stack_BA_statements[] = { - {OP(0, 0, 0, OP_PUSH_B_2), 0, 0, 0}, - {OP(0, 0, 0, OP_PUSH_B_2), 1, 0, 0}, - {OP(0, 0, 0, OP_PUSH_B_1), 2, 0, 0}, - {OP(0, 0, 0, OP_PUSH_B_3), 3, 0, 0}, - {OP(0, 0, 0, OP_PUSH_B_4), 4, 0, 0}, + {OP(0, 0, 0, OP_PUSH_B_2), 7, 5, 0}, + {OP(0, 0, 0, OP_PUSH_B_2), 7, 6, 0}, + {OP(0, 0, 0, OP_PUSH_B_1), 7, 7, 0}, + {OP(0, 0, 0, OP_PUSH_B_3), 7, 8, 0}, + {OP(0, 0, 0, OP_PUSH_B_4), 7, 9, 0}, {OP(0, 0, 0, OP_POP_A_4), 12, 0, 0}, {OP(0, 0, 0, OP_POP_A_3), 16, 0, 0}, @@ -176,6 +176,9 @@ test_t tests[] = { .statements = stack_AB_statements, .init_globals = test_globals_init1, .expect_globals = test_globals_expect1, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 28, }, { .desc = "stack push A pop C", @@ -203,6 +206,9 @@ test_t tests[] = { .statements = stack_BA_statements, .init_globals = test_globals_init2, .expect_globals = test_globals_expect2, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 28, }, { .desc = "stack push C pop A", diff --git a/libs/gamecode/test/test-store.c b/libs/gamecode/test/test-store.c index dc580f028..5ed5147b8 100644 --- a/libs/gamecode/test/test-store.c +++ b/libs/gamecode/test/test-store.c @@ -39,11 +39,11 @@ static dstatement_t store_A_statements[] = { }; static dstatement_t store_B_statements[] = { - {OP(0, 0, 0, OP_STORE_B_4), 4, 0, 12}, - {OP(0, 0, 0, OP_STORE_B_3), 3, 0, 16}, - {OP(0, 0, 0, OP_STORE_B_1), 2, 0, 19}, - {OP(0, 0, 0, OP_STORE_B_2), 1, 0, 20}, - {OP(0, 0, 0, OP_STORE_B_2), 0, 0, 22}, + {OP(0, 0, 0, OP_STORE_B_4), 7, 9, 12}, + {OP(0, 0, 0, OP_STORE_B_3), 7, 8, 16}, + {OP(0, 0, 0, OP_STORE_B_1), 7, 7, 19}, + {OP(0, 0, 0, OP_STORE_B_2), 7, 6, 20}, + {OP(0, 0, 0, OP_STORE_B_2), 7, 5, 22}, }; static dstatement_t store_C_statements[] = { @@ -78,6 +78,9 @@ test_t tests[] = { .statements = store_B_statements, .init_globals = test_globals_init, .expect_globals = test_globals_expect, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 28, }, { .desc = "store C", From 74d00d0a3c2c963a107015a546a4aef0c4a88b59 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 15:30:37 +0900 Subject: [PATCH 2240/3664] [qfcc] Update store statements for change in B mode Ruamoko store instructions are now always indexed and thus need a 0 for unindexed references, but v6 stores still have no-index addressing. --- tools/qfcc/source/statements.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index cd9245a93..2e01e5a0c 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -948,7 +948,13 @@ dereference_dst: dst_expr->e.address.offset, &ofs); } else { sblock = statement_subexpr (sblock, dst_expr, &dst); - ofs = 0; + if (options.code.progsversion < PROG_VERSION) { + // v6 and v6p stores don't need an index + ofs = 0; + } else { + // ruamoko stores do need an index + ofs = short_operand (0, e); + } } type = st_ptrassign; } From b2ddae46b2f90b8ef7e3d69444a271502612abc9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 15:34:43 +0900 Subject: [PATCH 2241/3664] [qfcc] Show raw opcode when dumping instructions Allows checking the correct instruction has been selected (it's not: getting 4-component instructions instead of 1) --- tools/qfcc/source/opcodes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 3815c54e1..82f7c750c 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -361,5 +361,6 @@ opcode_print_statement (pr_uint_t addr, dstatement_t *st) } else { mnemonic = pr_opcodes[st->op].mnemonic; } - printf ("%04x %8s %04x %04x %04x\n", addr, mnemonic, st->a, st->b, st->c); + printf ("%04x (%03x)%-8s %04x %04x %04x\n", + addr, st->op & 0x1ff, mnemonic, st->a, st->b, st->c); } From 854e45485a3fb24ec109d24e147339a403313550 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 16:33:04 +0900 Subject: [PATCH 2242/3664] [gamecode] Correct the widths for load, store and lea The different addressing modes complicate the width calculations, and lea is particularly fun in that it doesn't care what the width of value is. --- libs/gamecode/opcodes.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 40d84c341..ca2f1d836 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -42,6 +42,13 @@ address_types = [ "ev_ptr, ev_short", "ev_ptr, ev_int", ] +address_widths = [ + [ "1, 0", "1, 1", "1, 0", "1, 1", ], + [ "2, 0", "1, 1", "1, 0", "1, 1", ], + [ "3, 0", "1, 1", "1, 0", "1, 1", ], + [ "4, 0", "1, 1", "1, 0", "1, 1", ], + [ "-1, 0", "1, 1", "1, 0", "1, 1", ], +] #store, pop and lea store_fmt = [ "%ga", @@ -192,12 +199,13 @@ lea_formats = { "mnemonic": "lea", "opname": "lea", "format": "{lea_fmt[mm]}, %gc", - "widths": "0, 0, 1", + "widths": "{lea_widths[mm]}, 1", "types": "{lea_types[mm]}, ev_ptr", "args": { "op_mode": address_mode, "lea_fmt": store_fmt, "lea_types": address_types, + "lea_widths": address_widths[4], }, } load_formats = { @@ -205,12 +213,13 @@ load_formats = { "mnemonic": "load", "opname": "load", "format": "{load_fmt[mm]}, %gc", - "widths": "0, 0, {ss+1}", + "widths": "{load_widths[ss][mm]}, {ss+1}", "types": "{load_types[mm]}, ev_void", "args": { "op_mode": address_mode, "load_fmt": load_fmt, "load_types": address_types, + "load_widths": address_widths, }, } mathops_formats = { @@ -348,13 +357,14 @@ store_formats = { "mnemonic": "{store_op[mm]}", "opname": "{store_op[mm]}", "format": "%Gc, {store_fmt[mm]}", - "widths": "{ss+1}, 0, {ss+1}", + "widths": "{store_widths[ss][mm]}, {ss+1}", "types": "{store_types[mm]}, ev_void", "args": { "op_mode": address_mode, "store_fmt": store_fmt, "store_op": ["assign", "store", "store", "store"], "store_types": address_types, + "store_widths": address_widths, }, } string_formats = { From 54d776f243817fb653d985981f83935f96e4e01c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 16:49:07 +0900 Subject: [PATCH 2243/3664] [qfcc] Take operand width into account Operand width is encoded in the instruction opcode, so the width needs to be accounted for in order to select the correct instruction. With this, my little test generates correct code for the ruamoko ISA (except for return, still fails). --- tools/qfcc/include/statements.h | 1 + tools/qfcc/include/type.h | 1 + tools/qfcc/source/opcodes.c | 65 ++++++++++++++++++++++++++++----- tools/qfcc/source/statements.c | 6 +++ tools/qfcc/source/type.c | 28 +++++++++++++- 5 files changed, 91 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 386dad198..622d7c377 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -68,6 +68,7 @@ typedef struct operand_s { op_type_e op_type; struct type_s *type; ///< possibly override def's/nil's type int size; ///< for structures + int width; ///< for SIMD selection struct expr_s *expr; ///< expression generating this operand void *return_addr; ///< who created this operand union { diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 4a65b3384..b8cff36e5 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -166,6 +166,7 @@ int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)) int type_assignable (const type_t *dst, const type_t *src); int type_same (const type_t *dst, const type_t *src) __attribute__((pure)); int type_size (const type_t *type) __attribute__((pure)); +int type_width (const type_t *type) __attribute__((pure)); void init_types (void); void chain_initial_types (void); diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 82f7c750c..9e98fcd26 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -139,6 +139,8 @@ rua_get_hash (const void *_op, void *_tab) hash = ROTL (~op->types[0], 8) + ROTL (~op->types[1], 16) + ROTL (~op->types[2], 24); + hash += ROTL (~op->widths[0], 12) + ROTL (~op->widths[1], 20) + + ROTL (~op->widths[2], 28); return hash + Hash_String (op->opname); } @@ -152,6 +154,9 @@ rua_compare (const void *_opa, const void *_opb, void *unused) cmp = (opa->types[0] == opb->types[0]) && (opa->types[1] == opb->types[1]) && (opa->types[2] == opb->types[2]); + cmp &= (opa->widths[0] == opb->widths[0]) + && (opa->widths[1] == opb->widths[1]) + && (opa->widths[2] == opb->widths[2]); return cmp && !strcmp (opa->opname, opb->opname); } @@ -170,6 +175,12 @@ check_operand_type (etype_t ot1, etype_t ot2) return 0; } +static int +check_operand_width (int ow1, int ow2) +{ + return ((ow1 == -1 && ow2) || ow1 == ow2); +} + pr_ushort_t opcode_get (instruction_t *op) { @@ -219,20 +230,43 @@ v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, return op; } +static int +operand_width (operand_t *op) +{ + if (!op) { + return 0; + } + return op->width; +} + static opcode_t * rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) { - opcode_t search_op = {}; + opcode_t search_op = { + .opname = name, + .types = { + op_a ? low_level_type (op_a->type) : ev_invalid, + op_b ? low_level_type (op_b->type) : ev_invalid, + op_c ? low_level_type (op_c->type) : ev_invalid, + }, + .widths = { + operand_width (op_a), + operand_width (op_b), + operand_width (op_c), + }, + }; opcode_t *op; opcode_t *sop; void **op_list; int i; - search_op.opname = name; - search_op.types[0] = op_a ? low_level_type (op_a->type) : ev_invalid; - search_op.types[1] = op_b ? low_level_type (op_b->type) : ev_invalid; - search_op.types[2] = op_c ? low_level_type (op_c->type) : ev_invalid; +#if 0 + printf ("%s [%s %d] [%s %d] [%s %d]\n", search_op.opname, + pr_type_name[search_op.types[0]], search_op.widths[0], + pr_type_name[search_op.types[1]], search_op.widths[1], + pr_type_name[search_op.types[2]], search_op.widths[2]); +#endif op = Hash_FindElement (rua_opcode_type_table, &search_op); if (op) return op; @@ -241,10 +275,23 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, return op; for (i = 0; !op && op_list[i]; i++) { sop = op_list[i]; - if (check_operand_type (sop->types[0], search_op.types[0]) - && check_operand_type (sop->types[1], search_op.types[1]) - && check_operand_type (sop->types[2], search_op.types[2])) - op = sop; + if (!(check_operand_type (sop->types[0], search_op.types[0]) + && check_operand_type (sop->types[1], search_op.types[1]) + && check_operand_type (sop->types[2], search_op.types[2]))) { + continue; + } + if (!(check_operand_width (sop->widths[0], search_op.widths[0]) + && check_operand_width (sop->widths[1], search_op.widths[1]) + && check_operand_width (sop->widths[2], search_op.widths[2]))) { +#if 0 + printf ("%s [%s %d] [%s %d] [%s %d]\n", sop->opname, + pr_type_name[sop->types[0]], sop->widths[0], + pr_type_name[sop->types[1]], sop->widths[1], + pr_type_name[sop->types[2]], sop->widths[2]); +#endif + continue; + } + op = sop; } free (op_list); return op; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 2e01e5a0c..79c056251 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -426,6 +426,7 @@ nil_operand (type_t *type, expr_t *expr) op = new_operand (op_nil, expr, __builtin_return_address (0)); op->type = type; op->size = type_size (type); + op->width = type_width (type); return op; } @@ -439,6 +440,7 @@ def_operand (def_t *def, type_t *type, expr_t *expr) op = new_operand (op_def, expr, __builtin_return_address (0)); op->type = type; op->size = type_size (type); + op->width = type_width (type); op->def = def; return op; } @@ -458,6 +460,8 @@ value_operand (ex_value_t *value, expr_t *expr) operand_t *op; op = new_operand (op_value, expr, __builtin_return_address (0)); op->type = value->type; + op->size = type_size (value->type); + op->width = type_width (value->type); op->value = value; return op; } @@ -470,6 +474,7 @@ temp_operand (type_t *type, expr_t *expr) op->tempop.type = type; op->type = type; op->size = type_size (type); + op->width = type_width (type); return op; } @@ -544,6 +549,7 @@ alias_operand (type_t *type, operand_t *op, expr_t *expr) aop->alias = op; aop->type = type; aop->size = type_size (type); + aop->width = type_width (type); return aop; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 76a8e5976..a52594af8 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -1007,7 +1007,33 @@ type_size (const type_t *type) case ty_alias: return type_size (type->t.alias.aux_type); } - return 0; + internal_error (0, "invalid type meta: %d", type->meta); +} + +int +type_width (const type_t *type) +{ + switch (type->meta) { + case ty_basic: + if (type->type == ev_ushort || type->type == ev_short) { + return 0; + } + return 1; //FIXME vector should be 3 + case ty_struct: + case ty_union: + return 1; + case ty_enum: + if (!type->t.symtab) + return 0; + return type_width (&type_int); + case ty_array: + return type_width (type->t.array.type); + case ty_class: + return 1; + case ty_alias: + return type_width (type->t.alias.aux_type); + } + internal_error (0, "invalid type meta: %d", type->meta); } static void From c39558efaa733b4cc088737893b74e32c4dda22c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 17:27:56 +0900 Subject: [PATCH 2244/3664] [gamecode] Audit the widths of rest of the instructions I can't test them properly until I get qfcc up and running with basic ruamoko code, but they are at least more correct than they were. --- libs/gamecode/opcodes.py | 50 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index ca2f1d836..8b800135f 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -99,7 +99,7 @@ branch_formats = { "mnemonic": "{op_cond[c*4+cc]}", "opname": "{op_cond[c*4+cc]}", "format": "{cond_fmt[c*4+cc]}{branch_fmt[0]}", - "widths": "{cond_widths[c*4+cc]}", + "widths": "0, 0, 1", "types": "ev_short, ev_invalid, ev_int", "args": { "op_mode": "ABCD", @@ -107,16 +107,6 @@ branch_formats = { "ifnz", "ifae", "ifbe", None], "branch_fmt": branch_fmt, "cond_fmt": ["%Gc ", "%Gc ", "%Gc ", "", "%Gc ", "%Gc ", "%Gc ", ""], - "cond_widths": [ - "0, 0, 1", - "0, 0, 1", - "0, 0, 1", - "0, 0, 0", - "0, 0, 1", - "0, 0, 1", - "0, 0, 1", - "0, 0, 0", - ], }, } call_formats = { @@ -124,7 +114,7 @@ call_formats = { "mnemonic": "call", "opname": "call", "format": "{call_fmt[mm]}", - "widths": "0, 0, 0", + "widths": "{call_widths[mm]}, 0", "types": "ev_void, ev_void, ev_void", "args": { "op_mode": ".BCD", @@ -134,6 +124,7 @@ call_formats = { "%Ga[%sb], %gc", "%Ga[%Gb], %gc", ], + "call_widths": [ None, "1, 0", "1, 0", "1, 1" ] }, } compare_formats = { @@ -165,7 +156,7 @@ convert_formats = { "mnemonic": "conv", "opname": "conv", "format": "%Ga %Cb %gc", - "widths": "1, 0, 1", + "widths": "-1, 0, -1", "types": "ev_void, ev_short, ev_void", } hops_formats = { @@ -173,7 +164,7 @@ hops_formats = { "mnemonic": "hops", "opname": "hops", "format": "%Ga %Hb %gc", - "widths": "1, 0, 1", + "widths": "-1, 0, 1", "types": "ev_void, ev_short, ev_void", } jump_formats = { @@ -181,7 +172,7 @@ jump_formats = { "mnemonic": "jump", "opname": "jump", "format": "{jump_fmt[mm]}", - "widths": "0, 0, 0", + "widths": "{jump_widths[mm]}, 0", "types": "{jump_types[mm]}", "args": { "op_mode": "ABCD", @@ -192,6 +183,7 @@ jump_formats = { "ev_ptr, ev_short, ev_invalid", "ev_ptr, ev_int, ev_invalid", ], + "jump_widths": [ "0, 0", "1, 0", "1, 0", "1, 1" ] }, } lea_formats = { @@ -239,11 +231,17 @@ memset_formats = { "mnemonic": "memset.{op_memset[oo]}", "opname": "memset", "format": "{memset_fmt[oo]}", - "widths": "0, 0, 0", + "widths": "{memset_widths[oo]}", "types": "ev_int, ev_void, ev_void", "args": { "op_memset": ["i", "p", "pi", None], "memset_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], + "memset_widths": [ + "1, 0, -1", + "1, 1, 1", + "1, 0, 1", + None, + ], }, } move_formats = { @@ -251,11 +249,17 @@ move_formats = { "mnemonic": "memset.{op_move[oo]}", "opname": "memset", "format": "{move_fmt[oo]}", - "widths": "0, 0, 0", + "widths": "{move_widths[oo]}", "types": "ev_int, ev_void, ev_void", "args": { "op_move": ["i", "p", "pi", None], "move_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], + "move_widths": [ + "-1, 0, -1", + "1, 1, 1", + "1, 0, 1", + None, + ], }, } push_formats = { @@ -331,7 +335,7 @@ statef_formats = { "mnemonic": "state.{state[c]}", "opname": "state", "format": "{state_fmt[c]}", - "widths": "1, 1, 1", + "widths": "1, 1, {c}", "types": "ev_float, ev_func, {state_types[c]}", "args": { "state": ["ft", "ftt"], @@ -344,7 +348,7 @@ stated_formats = { "mnemonic": "state.{state[c]}", "opname": "state", "format": "{state_fmt[c]}", - "widths": "1, 1, 1", + "widths": "1, 1, {c}", "types": "ev_float, ev_func, {state_types[c]}", "args": { "state": ["dt", "dtt"], @@ -372,7 +376,7 @@ string_formats = { "mnemonic": "{op_str[o*4+oo]}.s", "opname": "{op_str[o*4+oo]}", "format": "{str_fmt[o*4+oo]}", - "widths": "1, 1, 1", + "widths": "1, {(o*4+oo)<7 and 1 or 0}, 1", "types": "{str_types[o*4+oo]}", "args": { "op_str": ["eq", "lt", "gt", "add", "cmp", "ge", "le", "not"], @@ -414,7 +418,7 @@ return_formats = { "opcode": "OP_RETURN", "mnemonic": "return", "opname": "return", - "widths": "0, 0, 0", # width specified by st->c + "widths": "-1, -1, 0", # width specified by st->c "format": "FIXME", "types": "ev_void, ev_void, ev_void", } @@ -458,8 +462,8 @@ with_formats = { "mnemonic": "with", "opname": "with", "format": "%sa, %sb, %sc", - "widths": "0, 0, 0", - "types": "ev_void, ev_void, ev_void", + "widths": "0, -1, 0", + "types": "ev_short, ev_void, ev_short", } group_map = { From 5f66bfe887342d33e54e4bbe1e19e04bdc3243a7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 18:37:28 +0900 Subject: [PATCH 2245/3664] [gamecode] Update printed opcode width Opcodes now need 3 hex digits (hexits?) to print. --- libs/gamecode/pr_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 32f6a8dd9..794005174 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1586,7 +1586,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) dasprintf (res->line, "%04x ", addr); if (pr_debug->int_val > 2) { dasprintf (res->line, - "%02x %04x(%8s)[%d] %04x(%8s)[%d] %04x(%8s)[%d]\t", + "%03x %04x(%8s)[%d] %04x(%8s)[%d] %04x(%8s)[%d]\t", s->op, s->a, pr_type_name[op_type[0]], op_width[0], s->b, pr_type_name[op_type[1]], op_width[1], From 6487fe7ea74a64940109cdfb039c0ab6ca833f29 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 18:39:06 +0900 Subject: [PATCH 2246/3664] [qfcc] Allow -1 width to match with 0 I initially wanted them to be separate, but return (and other instructions where width is encoded in one of the operands) made that difficult. --- tools/qfcc/source/opcodes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 9e98fcd26..7687851d9 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -178,7 +178,7 @@ check_operand_type (etype_t ot1, etype_t ot2) static int check_operand_width (int ow1, int ow2) { - return ((ow1 == -1 && ow2) || ow1 == ow2); + return (ow1 == -1 || ow1 == ow2); } pr_ushort_t From 2b7a8387e7dc75d7b461c57f8ca1c2c34c960a1d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 18:40:55 +0900 Subject: [PATCH 2247/3664] [qfcc] Get void return statements working My little test program now builds with the Ruamoko ISA :) void cp (int *dst, int *src, int count) { while (count--) { *dst++ = *src++; } } Calls are broken (unimplemented), and non-void returns are not likely to work either (only partially implemented). --- tools/qfcc/source/dags.c | 4 +++- tools/qfcc/source/flow.c | 24 +++++++++++++++++++----- tools/qfcc/source/statements.c | 26 +++++++++++++++++++++----- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 5b3a64b3d..d4a7b4fbe 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -452,7 +452,9 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) int first_param = 0; flowvar_t **flowvars = dag->flownode->graph->func->vars; - if (!strncmp (n->label->opcode, "rcall", 5)) { + if (!strcmp (n->label->opcode, "call")) { + internal_error (0, "not implemented"); + } else if (!strncmp (n->label->opcode, "rcall", 5)) { num_params = n->label->opcode + 6; first_param = 2; } else if (!strncmp (n->label->opcode, "call", 4)) { diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 5ed2022da..1cbf057d8 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1257,15 +1257,29 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_func: - if (strcmp (s->opcode, "return") == 0 - || strcmp (s->opcode, "done") == 0) { - flow_add_op_var (use, s->opa, 1); - } else if (strcmp (s->opcode, "return_v") == 0) { + if (statement_is_return (s)) { + if (s->opc) { + // ruamoko + // opc always short + short ret_mode = s->opc->value->v.short_val; + // -1 is void + // FIXME size and addressing + if (ret_mode >= 0) { + flow_add_op_var (use, s->opa, 1); + } + } else { + // v6/v6p + if (s->opa) { + flow_add_op_var (use, s->opa, 1); + } + } if (use) { flow_add_op_var (use, &flow_params[0].op, 1); } } - if (strncmp (s->opcode, "call", 4) == 0) { + if (strcmp (s->opcode, "call") == 0) { + internal_error (s->expr, "not implemented"); + } else if (strncmp (s->opcode, "call", 4) == 0) { start = 0; calln = s->opcode[5] - '0'; flow_add_op_var (use, s->opa, 1); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 79c056251..354f1d1db 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1129,9 +1129,18 @@ statement_return (sblock_t *sblock, expr_t *e) } } s = new_statement (st_func, opcode, e); - if (e->e.retrn.ret_val) { - s->opa = return_operand (get_type (e->e.retrn.ret_val), e); - sblock = statement_subexpr (sblock, e->e.retrn.ret_val, &s->opa); + if (options.code.progsversion < PROG_VERSION) { + if (e->e.retrn.ret_val) { + s->opa = return_operand (get_type (e->e.retrn.ret_val), e); + sblock = statement_subexpr (sblock, e->e.retrn.ret_val, &s->opa); + } + } else { + if (e->e.retrn.ret_val) { + } else { + s->opa = short_operand (0, e); + s->opb = short_operand (0, e); + s->opc = short_operand (-1, e); + } } sblock_add_statement (sblock, s); sblock->next = new_sblock (); @@ -2134,8 +2143,15 @@ check_final_block (sblock_t *sblock) sblock = sblock->next; } s = new_statement (st_func, "return", 0); - if (options.traditional || options.code.progsversion == PROG_ID_VERSION) { - s->opa = return_operand (&type_void, 0); + if (options.code.progsversion == PROG_VERSION) { + s->opa = short_operand (0, 0); + s->opb = short_operand (0, 0); + s->opc = short_operand (-1, 0); + } else { + if (options.traditional + || options.code.progsversion == PROG_ID_VERSION) { + s->opa = return_operand (&type_void, 0); + } } sblock_add_statement (sblock, s); } From 17dfd1492f4a124cb57194eba2346e3e41960e20 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 20:54:12 +0900 Subject: [PATCH 2248/3664] [qfcc] Make virtual defspaces useful for highwater allocation This seems to be the most reasonable approach to allocating space for function call parameters without using push and pop (or adding to the stack pointer), though it's probably good even when using push and pop to help keep things aligned. --- tools/qfcc/include/defspace.h | 57 ++++++++++++++++++++++++++++++++-- tools/qfcc/source/defspace.c | 55 +++++++++++++++++++++++++++----- tools/qfcc/source/statements.c | 8 +++++ 3 files changed, 110 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index 6e839ce67..eea13bf71 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -43,7 +43,8 @@ typedef enum { ds_backed, ///< data space is globally addressable (near/far/type) and ///< has backing store ds_virtual, ///< data space has no backing store (local vars, entity - ///< fields) + ///< fields) defspace_t::max_size reflects the highest + ///< address allocated } ds_type_t; /** Represent a block of memory in the progs data space. @@ -56,7 +57,8 @@ typedef struct defspace_s { struct def_s **def_tail; ///< for appending to \a defs pr_type_t *data; ///< backing memory for this space int size; ///< current high-water mark for alloced data - int max_size; ///< size of backing memory + int max_size; ///< size of backing memory, or highwater mark + ///< for ds_virtual /** Grow the backing memory of the defspace. This function is called when more memory is needed for the space. @@ -168,6 +170,57 @@ void defspace_free_loc (defspace_t *space, int ofs, int size); */ int defspace_add_data (defspace_t *space, pr_type_t *data, int size); +/** Allocate a block of data from the end of the defspace. + + If memory cannot be allocated (there is no free space in the currently + available memory and defspace_t::grow is null), then an internal error + will be generated. + + \param space The space from which to allocate data. + \param size The amount of pr_type_t words to allocated. int and float + need 1 word, vector 3 words, and quaternion 4. + \return The offset of the first word of the freshly allocated + space. May be 0 if the allocated space is at the beginning + of the defspace. +*/ +int defspace_alloc_highwater (defspace_t *space, int size); + +/** Allocate an aligned block of data from the end of the defspace. + + Any unallocated holes in the defspace are ignored, even if the hole is + at the end of the defspace. However, any holes created by the padding + required for aligning the block will be available to defspace_alloc_loc() + and defspace_alloc_aligned_loc(). + + If memory cannot be allocated (there is no free space in the currently + available memory and defspace_t::grow is null), then an internal error + will be generated. + + \param space The space from which to allocate data. + \param size The amount of pr_type_t words to allocated. int and float + need 1 word, vector 3 words, and quaternion 4. + \param alignment The alignment of the allocated space. + \return The offset of the first word of the freshly allocated + space. May be 0 if the allocated space is at the beginning + of the defspace. +*/ +int defspace_alloc_aligned_highwater (defspace_t *space, int size, + int alignment); +/** Reset a defspace, freeing all allocated memory. + + defspace_t::max_size is not affected. This allows the defspace to be used + to find the larged block of memory required for a set of operations (eg, + the largest parameter block required in a function for all its calls + allowing the stack to remain constant instead of using many push/pop + operations. Note that this works best with ds_virtual defspaces. + + If the defspace has backing memory (ds_backed), the memory is not freed, + but it is zeroed so any new allocations will contain zeroed memory. + + \param space The space to be reset. +*/ +void defspace_reset (defspace_t *space); + ///@} #endif//__defspace_h diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index 1cfe572c3..5bae41bff 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -105,14 +105,9 @@ grow_space_global (defspace_t *space) static int grow_space_virtual (defspace_t *space) { - int size; - - if (space->size <= space->max_size) - return 1; - - size = space->size + GROW; - size -= size % GROW; - space->max_size = size; + if (space->size > space->max_size) { + space->max_size = space->size; + } return 1; } @@ -208,6 +203,7 @@ defspace_alloc_aligned_loc (defspace_t *space, int size, int alignment) internal_error (0, "unable to allocate %d words", size); } if (pad) { + // mark the padding as free *l = new_locref (ofs, pad, 0); } return ofs + pad; @@ -271,3 +267,46 @@ defspace_add_data (defspace_t *space, pr_type_t *data, int size) memcpy (space->data + loc, data, size * sizeof (pr_type_t)); return loc; } + +int +defspace_alloc_highwater (defspace_t *space, int size) +{ + return defspace_alloc_aligned_highwater (space, size, 1); +} + +int +defspace_alloc_aligned_highwater (defspace_t *space, int size, int alignment) +{ + if (size <= 0) + internal_error (0, "invalid number of words requested: %d", size); + if (alignment <= 0) + internal_error (0, "invalid alignment requested: %d", alignment); + + int ofs = space->size; + int pad = alignment * ((ofs + alignment - 1) / alignment) - ofs; + space->size += size + pad; + if (space->size > space->max_size) { + if (!space->grow || !space->grow (space)) + internal_error (0, "unable to allocate %d words", size); + } + locref_t **l = &space->free_locs; + if (pad) { + // mark the padding as free + *l = new_locref (ofs, pad, 0); + } + return ofs + pad; +} + +void +defspace_reset (defspace_t *space) +{ + space->size = 0; + while (space->free_locs) { + locref_t *l = space->free_locs; + space->free_locs = l->next; + del_locref (l); + } + if (space->data) { + memset (space->data, 0, space->max_size * sizeof (pr_type_t)); + } +} diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 354f1d1db..756b38492 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1136,6 +1136,14 @@ statement_return (sblock_t *sblock, expr_t *e) } } else { if (e->e.retrn.ret_val) { + expr_t *ret_val = e->e.retrn.ret_val; + type_t *ret_type = get_type (ret_val); + if (is_indirect (ret_val)) { + } else { + sblock = statement_subexpr (sblock, ret_val, &s->opa); + s->opb = short_operand (0, e); + s->opc = short_operand (type_size (ret_type) - 1, e); + } } else { s->opa = short_operand (0, e); s->opb = short_operand (0, e); From b8b47aaf547e8ea2983e31549ea1719602e54f49 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Jan 2022 22:27:10 +0900 Subject: [PATCH 2249/3664] [qfcc] Give finish_function the finishing blow It's been twitching for over ten years, time to put it out of its misery. --- tools/qfcc/include/function.h | 1 - tools/qfcc/source/function.c | 7 ------- 2 files changed, 8 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 4f8fa83e7..667cfb5ba 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -146,7 +146,6 @@ function_t *build_code_function (struct symbol_s *fsym, function_t *build_builtin_function (struct symbol_s *sym, struct expr_s *bi_val, int far, enum storage_class_e storage); -void finish_function (function_t *f); void emit_function (function_t *f, struct expr_s *e); int function_parms (function_t *f, byte *parm_size); void clear_functions (void); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index b20d38cf5..4840fb41f 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -646,7 +646,6 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) statements = state_expr; } emit_function (fsym->s.func, statements); - finish_function (fsym->s.func); return fsym->s.func; } @@ -692,7 +691,6 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far, sym->s.func->builtin = bi; reloc_def_func (sym->s.func, sym->s.func->def); build_function (sym); - finish_function (sym->s.func); // for debug info build_scope (sym, current_symtab); @@ -700,11 +698,6 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far, return sym->s.func; } -void -finish_function (function_t *f) -{ -} - void emit_function (function_t *f, expr_t *e) { From ac785ca7520ed477ec491db066d112eda55dc2cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 00:44:04 +0900 Subject: [PATCH 2250/3664] [qwaq] Send app focus event on startup Terminal apps effectively always have focus (unless I find a way to know when an xterm loses/gains focus). Fixes input-app not updating on evdev events. --- ruamoko/qwaq/builtins/term-input.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruamoko/qwaq/builtins/term-input.c b/ruamoko/qwaq/builtins/term-input.c index 7ebbde1d2..697cd2e7c 100644 --- a/ruamoko/qwaq/builtins/term-input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -860,6 +860,12 @@ bi_init_input (progs_t *pr) qwaq_input_init (res); res->initialized = 1; create_thread (qwaq_input_thread, res); + + IE_event_t event = { + .type = ie_app_gain_focus, + .when = Sys_LongTime (), + }; + IE_Send_Event (&event); } static builtin_t builtins[] = { From 792e4982e446efc7c89938293d4e75834ad8fbb8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 00:44:04 +0900 Subject: [PATCH 2251/3664] [qwaq] Send app focus event on startup Terminal apps effectively always have focus (unless I find a way to know when an xterm loses/gains focus). Fixes input-app not updating on evdev events. --- ruamoko/qwaq/builtins/term-input.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruamoko/qwaq/builtins/term-input.c b/ruamoko/qwaq/builtins/term-input.c index 7ebbde1d2..697cd2e7c 100644 --- a/ruamoko/qwaq/builtins/term-input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -860,6 +860,12 @@ bi_init_input (progs_t *pr) qwaq_input_init (res); res->initialized = 1; create_thread (qwaq_input_thread, res); + + IE_event_t event = { + .type = ie_app_gain_focus, + .when = Sys_LongTime (), + }; + IE_Send_Event (&event); } static builtin_t builtins[] = { From 4b87d24737843acff65dda9a21a3bef78de5cad5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 10:07:35 +0900 Subject: [PATCH 2252/3664] [gamecode] Correct call's operator types --- libs/gamecode/opcodes.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 8b800135f..37ca5c2e2 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -115,7 +115,7 @@ call_formats = { "opname": "call", "format": "{call_fmt[mm]}", "widths": "{call_widths[mm]}, 0", - "types": "ev_void, ev_void, ev_void", + "types": "{call_types[mm]}, ev_void", "args": { "op_mode": ".BCD", "call_fmt": [ @@ -124,6 +124,12 @@ call_formats = { "%Ga[%sb], %gc", "%Ga[%Gb], %gc", ], + "call_types": [ + None, + "ev_void, ev_invalid", + "ev_ptr, ev_short", + "ev_ptr, ev_int", + ], "call_widths": [ None, "1, 0", "1, 0", "1, 1" ] }, } From 578314c5a3a1ed2b5c899494a79c1b9de23cbf24 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 10:09:02 +0900 Subject: [PATCH 2253/3664] [gamecode] Use a buffer for discarded return values Due to how OP_RETURN works, a destination is required for any function returning data, but the caller may not have allocated any space for the value. Thus the VM maintains a buffer into which the data can be put and ignored. It also makes a good place for return values when the engine calls Ruamoko code as trusting progs code with return sizes seems like a recipe for disaster, especially if the return location is on the C stack. --- include/QF/progs.h | 2 ++ libs/gamecode/pr_exec.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index f9cf97b32..02cbb0229 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1896,6 +1896,8 @@ struct progs_s { pr_type_t *pr_real_params[MAX_PARMS]; int pr_param_size; ///< covers both params and return int pr_param_alignment; ///< covers both params and return + pr_type_t pr_return_buffer[32];///< for discarded return values + ///< or returning values to C ///@} /// \name edicts diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 1e7f9634c..15885244c 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -427,6 +427,9 @@ PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr) if (!fnum) PR_RunError (pr, "NULL function"); + if (!return_ptr || return_ptr == pr->pr_globals) { + return_ptr = pr->pr_return_buffer; + } f = pr->function_table + fnum; if (f->first_statement < 0) { // negative statements are built in functions From 16a203c643b51f8fa3e6dadeceb706c6763c5f0c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 10:12:50 +0900 Subject: [PATCH 2254/3664] [gamecode] Partially implement conversion code debug The code is simply printed in octal for now, but it's better than breaking the rest of the format string. --- libs/gamecode/pr_debug.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 794005174..0a3d00e8b 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1683,6 +1683,9 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) str = dsprintf (res->dva, "%04x", addr + (short) opval); break; + case 'C': + str = dsprintf (res->dva, "%03o", opval); + break; case 'E': { edict_t *ed = 0; From 479ec07fd449d9c0ea27efa186796ef8de8ece3c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 10:14:14 +0900 Subject: [PATCH 2255/3664] [qfcc] Implement ruamoko conversion instructions Thanks to me having done something right 20 years ago, that was pretty easy :). The two boolean types aren't supported yet because I haven't decided on just how to represent their types in qfcc. --- tools/qfcc/source/statements.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 756b38492..bc4cb396b 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1318,6 +1318,17 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static int type_map[ev_type_count] = { + [ev_int] = 0, + [ev_float] = 1, + [ev_long] = 2, + [ev_double] = 3, + [ev_uint] = 4, + //[ev_bool32] = 5, + [ev_ulong] = 6, + //[ev_bool64] = 7, +}; + static sblock_t * expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1332,6 +1343,13 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) *op = temp_operand (e->e.expr.type, e); s = new_statement (st_expr, "conv", e); s->opa = src; + if (options.code.progsversion == PROG_VERSION) { + int from = type_map[src_type->type]; + int to = type_map[type->type]; + int width = type_width (src_type) - 1; + int conv = (width << 6) | (from << 3) | to; + s->opb = short_operand (conv, e); + } s->opc = *op; sblock_add_statement (sblock, s); } else { From a19349b242bf1d698928ba916fd4fa2d5f32baa9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 10:16:54 +0900 Subject: [PATCH 2256/3664] [qfcc] Allow 0 sized highwater allocations in defspaces This turned out to be needed for functions with no parameters (or no locals). --- tools/qfcc/source/defspace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index 5bae41bff..a704b45a3 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -277,7 +277,7 @@ defspace_alloc_highwater (defspace_t *space, int size) int defspace_alloc_aligned_highwater (defspace_t *space, int size, int alignment) { - if (size <= 0) + if (size < 0) internal_error (0, "invalid number of words requested: %d", size); if (alignment <= 0) internal_error (0, "invalid alignment requested: %d", alignment); From 7bc1396358af85c4faef837bfde35863aa9f3fc5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 10:20:02 +0900 Subject: [PATCH 2257/3664] [qfcc] Split the function defspace into three spaces Since Ruamoko now uses the stack for parameters and locals, parameters need to come after locals in the address space (instead of before, as in v6 progs). Thus use separate spaces for parameters and locals regardless of the target, then stitch them together appropriately for the target. The third space is used for allocating stack space for arguments to called functions. It us not used for v6 progs, and comes before locals in Ruamoko progs. Other than the return value, and optimization (ice, not implemented) calls in Ruamoko look like they'll work. --- tools/qfcc/include/function.h | 29 +++++++++-- tools/qfcc/source/def.c | 2 +- tools/qfcc/source/flow.c | 2 +- tools/qfcc/source/function.c | 89 ++++++++++++++++++++++++++++------ tools/qfcc/source/obj_file.c | 12 ++--- tools/qfcc/source/qc-parse.y | 8 +-- tools/qfcc/source/qp-parse.y | 8 +-- tools/qfcc/source/statements.c | 45 ++++++++++++++++- 8 files changed, 157 insertions(+), 38 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 667cfb5ba..3b04bb9e5 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -73,13 +73,32 @@ typedef struct function_s { struct def_s *temp_defs[4]; ///< freed temp vars (by size) struct def_s *def; ///< output def holding function number struct symbol_s *sym; ///< internal symbol for this function - /** Root scope symbol table of the function. + /** \name Local data space - Sub-scope symbol tables are not directly accessible, but all defs - created in the function's local data space are recorded in the root - scope symbol table's defspace. + The function parameters form the root scope for the function. Its + defspace is separate from the locals defspace so that it can be moved + to the beginning of locals space for v6 progs, and too the end (just + above the stack pointer on entry to the function) for Ruamoko progs. + + The locals scope is a direct child of the parameters scope, and any + sub-scope symbol tables are not directly accessible, but all defs + other than function call arugments created in the function's local + data space are recorded in the root local scope symbol table's + defspace. + + The arguments defspace is not used for v6 progs. It is used as a + highwater allocator for the arguments to all calls made by the + funciton, with the arguments to separate functions overlapping each + other. + + Afther the function has been emitted, locals, arguments and possibly + parameters will be merged into the one defspace. */ - struct symtab_s *symtab; + ///@{ + struct symtab_s *parameters; ///< Root scope symbol table + struct symtab_s *locals; ///< Actual local variables + struct defspace_s *arguments; ///< Space for called function arguments + ///@} struct symtab_s *label_scope; struct reloc_s *refs; ///< relocation targets for this function struct expr_s *var_init; diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 449db7320..5f6947c37 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -204,7 +204,7 @@ def_t * temp_def (type_t *type) { def_t *temp; - defspace_t *space = current_func->symtab->space; + defspace_t *space = current_func->locals->space; int size = type_size (type); int alignment = type->alignment; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 1cbf057d8..8bcd4bbeb 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -609,7 +609,7 @@ flow_build_vars (function_t *func) // set up pseudo address space for temp vars so accessing tmp vars // though aliases analyses correctly - func->pseudo_addr = func->num_statements + func->symtab->space->size; + func->pseudo_addr = func->num_statements + func->locals->space->size; func->num_vars = 0; // incremented by add_operand // first, add .return and .param_[0-7] as they are always needed diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 4840fb41f..bfc1da059 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -488,16 +488,23 @@ build_scope (symbol_t *fsym, symtab_t *parent) param_t *p; symbol_t *args = 0; symbol_t *param; - symtab_t *symtab; - symtab_t *cs = current_symtab; + symtab_t *parameters; + symtab_t *locals; + symtab_t *cs = current_symtab;//FIXME check_function (fsym); - symtab = new_symtab (parent, stab_local); - fsym->s.func->symtab = symtab; fsym->s.func->label_scope = new_symtab (0, stab_local); - symtab->space = defspace_new (ds_virtual); - current_symtab = symtab; + + parameters = new_symtab (parent, stab_local); + parameters->space = defspace_new (ds_virtual); + fsym->s.func->parameters = parameters; + + locals = new_symtab (parameters, stab_local); + locals->space = defspace_new (ds_virtual); + fsym->s.func->locals = locals; + + current_symtab = locals;//FIXME if (!fsym->s.func) { internal_error (0, "function %s not defined", fsym->name); @@ -507,7 +514,7 @@ build_scope (symbol_t *fsym, symtab_t *parent) } if (fsym->s.func->type->t.func.num_params < 0) { args = new_symbol_type (".args", &type_va_list); - initialize_def (args, 0, symtab->space, sc_param); + initialize_def (args, 0, parameters->space, sc_param); } for (p = fsym->params, i = 0; p; p = p->next) { @@ -520,14 +527,14 @@ build_scope (symbol_t *fsym, symtab_t *parent) p->name = save_string (""); } param = new_symbol_type (p->name, p->type); - initialize_def (param, 0, symtab->space, sc_param); + initialize_def (param, 0, parameters->space, sc_param); i++; } if (args) { while (i < MAX_PARMS) { param = new_symbol_type (va (0, ".par%d", i), &type_param); - initialize_def (param, 0, symtab->space, sc_param); + initialize_def (param, 0, parameters->space, sc_param); i++; } } @@ -628,11 +635,32 @@ build_function (symbol_t *fsym) if (func_type->t.func.num_params > MAX_PARMS) { error (0, "too many params"); } - // FIXME -// f->def->constant = 1; -// f->def->nosave = 1; -// f->def->initialized = 1; -// G_FUNCTION (f->def->ofs) = f->function_num; +} + +static void +merge_spaces (defspace_t *dst, defspace_t *src, int alignment) +{ + int offset; + + for (def_t *def = src->defs; def; def = def->next) { + if (def->type->alignment > alignment) { + alignment = def->type->alignment; + } + } + offset = defspace_alloc_aligned_highwater (dst, src->size, alignment); + for (def_t *def = src->defs; def; def = def->next) { + def->offset += offset; + def->space = dst; + } + + if (src->defs) { + *dst->def_tail = src->defs; + dst->def_tail = src->def_tail; + src->def_tail = &src->defs; + *src->def_tail = 0; + } + + defspace_delete (src); } function_t * @@ -645,7 +673,35 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) state_expr->next = statements; statements = state_expr; } - emit_function (fsym->s.func, statements); + if (options.code.progsversion == PROG_VERSION) { + } + function_t *func = fsym->s.func; + emit_function (func, statements); + if (options.code.progsversion < PROG_VERSION) { + // stitch parameter and locals data together with parameters coming + // first + defspace_t *space = defspace_new (ds_virtual); + + merge_spaces (space, func->parameters->space, 1); + func->parameters->space = space; + + merge_spaces (space, func->locals->space, 1); + func->locals->space = space; + } else { + defspace_t *space = defspace_new (ds_virtual); + + if (func->arguments) { + func->arguments->size = func->arguments->max_size; + merge_spaces (space, func->arguments, 4); + func->arguments = 0; + } + + merge_spaces (space, func->locals->space, 4); + func->locals->space = space; + + merge_spaces (space, func->parameters->space, 4); + func->parameters->space = space; + } return fsym->s.func; } @@ -694,7 +750,8 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val, int far, // for debug info build_scope (sym, current_symtab); - sym->s.func->symtab->space->size = 0; + sym->s.func->parameters->space->size = 0; + sym->s.func->locals->space = sym->s.func->parameters->space; return sym->s.func; } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index a9f562984..17ba70080 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -171,9 +171,9 @@ qfo_count_function_stuff (qfo_t *qfo, function_t *functions) for (func = functions; func; func = func->next) { qfo->num_funcs++; qfo->num_relocs += count_relocs (func->refs); - if (func->symtab && func->symtab->space) { + if (func->locals && func->locals->space) { qfo->num_spaces++; - qfo_count_space_stuff (qfo, func->symtab->space); + qfo_count_space_stuff (qfo, func->locals->space); } } } @@ -306,10 +306,10 @@ qfo_encode_functions (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, if (f->builtin) // FIXME redundant q->code = -f->builtin; q->def = f->def->qfo_def; - if (f->symtab && f->symtab->space) { - space->id = f->symtab->space->qfo_space; - qfo_init_data_space (qfo, defs, relocs, space++, f->symtab->space); - q->locals_space = f->symtab->space->qfo_space; + if (f->locals && f->locals->space) { + space->id = f->locals->space->qfo_space; + qfo_init_data_space (qfo, defs, relocs, space++, f->locals->space); + q->locals_space = f->locals->space->qfo_space; } q->line_info = f->line_info; q->relocs = *relocs - qfo->relocs; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index a9c2ea102..c0d7d93c0 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -517,7 +517,7 @@ function_body $$ = current_symtab; current_func = begin_function ($2, 0, current_symtab, 0, $-1.storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; current_storage = sc_local; } compound_statement @@ -1249,7 +1249,7 @@ code_func $$ = current_symtab; current_func = begin_function ($0, 0, current_symtab, 0, $-1.storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; current_storage = sc_local; } compound_statement @@ -2066,10 +2066,10 @@ methoddef current_func = begin_function (sym, nicename, ivar_scope, 1, sc_static); class_finish_ivar_scope (current_class, ivar_scope, - current_func->symtab); + current_func->locals); method->func = sym->s.func; method->def = sym->s.func->def; - current_symtab = current_func->symtab; + current_symtab = current_func->locals; current_storage = sc_local; } compound_statement diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index e7bb66647..a36f27910 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -156,7 +156,7 @@ build_dotmain (symbol_t *program) current_func = begin_function (dotmain, 0, current_symtab, 0, current_storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; code = new_block_expr (); append_expr (code, function_expr (new_symbol_expr (program), 0)); append_expr (code, return_expr (current_func, exitcode)); @@ -180,7 +180,7 @@ program current_func = begin_function ($1, 0, current_symtab, 0, current_storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; build_code_function ($1, 0, $4); current_symtab = st; @@ -265,14 +265,14 @@ subprogram_declaration $$ = current_storage; current_func = begin_function ($1, 0, current_symtab, 0, current_storage); - current_symtab = current_func->symtab; + current_symtab = current_func->locals; current_storage = sc_local; } declarations compound_statement ';' { append_expr ($5, new_return_expr (0)); build_code_function ($1, 0, $5); - current_symtab = current_symtab->parent; + current_symtab = current_func->parameters->parent; current_storage = $3; } | subprogram_head ASSIGNOP '#' VALUE ';' diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index bc4cb396b..51a7a4ac9 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -48,6 +48,7 @@ #include "tools/qfcc/include/class.h" #include "tools/qfcc/include/dags.h" +#include "tools/qfcc/include/defspace.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/dot.h" #include "tools/qfcc/include/expr.h" @@ -1011,7 +1012,7 @@ vector_call (sblock_t *sblock, expr_t *earg, expr_t *param, int ind, } static sblock_t * -expr_call (sblock_t *sblock, expr_t *call, operand_t **op) +expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) { expr_t *func = call->e.branch.target; expr_t *args = call->e.branch.args; @@ -1075,6 +1076,48 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) return sblock->next; } +static sblock_t * +expr_call (sblock_t *sblock, expr_t *call, operand_t **op) +{ + if (options.code.progsversion < PROG_VERSION) { + return expr_call_v6p (sblock, call, op); + } + if (!current_func->arguments) { + current_func->arguments = defspace_new (ds_virtual); + } + defspace_t *arg_space = current_func->arguments; + expr_t *func = call->e.branch.target; + expr_t *args = call->e.branch.args; + + defspace_reset (arg_space); + + args = reverse_expr_list (args); + int arg_num = 0; + for (expr_t *a = args; a; a = a->next) { + const char *arg_name = va (0, ".arg%d", arg_num++); + def_t *def = new_def (arg_name, 0, current_func->arguments, + sc_local); + type_t *arg_type = get_type (a); + int size = type_size (arg_type); + int alignment = arg_type->alignment; + if (alignment < 4) { + alignment = 4; + } + def->offset = defspace_alloc_aligned_highwater (arg_space, size, + alignment); + def->type = arg_type; + expr_t *assign = assign_expr (new_def_expr (def), a); + expr_file_line (assign, call); + sblock = statement_slist (sblock, assign); + } + statement_t *s = new_statement (st_func, "call", call); + sblock = statement_subexpr (sblock, func, &s->opa); + s->opc = short_operand (0, call); + sblock_add_statement (sblock, s); + sblock->next = new_sblock (); + return sblock->next; +} + static sblock_t * statement_branch (sblock_t *sblock, expr_t *e) { From 64da1b603a3ccc0cf53657f84b2c131f1bba52a0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 12:05:50 +0900 Subject: [PATCH 2258/3664] [qfcc] Add failing test for return of postop Commit 76b3bedb72a0a1b92e658c733bf6ff079d18ce10 broke more than just the swap test, but at least I know I need to get an edge in the dag. Currently, the following code is generated: return and add are reversed. ../tools/qfcc/test/return-postop.r:8: return counter++; 0001 store.i counter, .tmp0 0002 return .tmp0 0003 add.i .tmp0, (1), counter However, I don't want to deal with it right now, so it's marked XFAIL. --- tools/qfcc/test/Makemodule.am | 14 +++++++++++++- tools/qfcc/test/return-postop.r | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tools/qfcc/test/return-postop.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 5d58abb99..4eb260e81 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -41,6 +41,7 @@ test_progs_dat=\ tools/qfcc/test/ptrstructcast.dat \ tools/qfcc/test/quaternion.dat \ tools/qfcc/test/return-ivar.dat \ + tools/qfcc/test/return-postop.dat \ tools/qfcc/test/sendv.dat \ tools/qfcc/test/state.dat \ tools/qfcc/test/static-init.dat \ @@ -62,7 +63,8 @@ test_progs_dat=\ tools/qfcc/test/while.dat \ tools/qfcc/test/zerolinker.dat -fail_progs_dat= +fail_progs_dat=\ + tools/qfcc/test/return-postop.dat test_build_errors=\ tools/qfcc/test/classarray.r \ @@ -483,6 +485,16 @@ tools/qfcc/test/return-ivar.run: $(qfcc_test_run_deps) include $(return_ivar_dep) # am--include-marker r_depfiles_remade += $(return_ivar_dep) +tools_qfcc_test_return_postop_dat_SOURCES=tools/qfcc/test/return-postop.r +return_postop_obj=$(tools_qfcc_test_return_postop_dat_SOURCES:.r=.o) +return_postop_dep=$(call qcautodep,$(tools_qfcc_test_return_postop_dat_SOURCES)) +tools/qfcc/test/return-postop.dat$(EXEEXT): $(return_postop_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(return_postop_obj) +tools/qfcc/test/return-postop.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(return_postop_dep) # am--include-marker +r_depfiles_remade += $(return_postop_dep) + tools_qfcc_test_sendv_dat_SOURCES=tools/qfcc/test/sendv.r sendv_obj=$(tools_qfcc_test_sendv_dat_SOURCES:.r=.o) sendv_dep=$(call qcautodep,$(tools_qfcc_test_sendv_dat_SOURCES)) diff --git a/tools/qfcc/test/return-postop.r b/tools/qfcc/test/return-postop.r new file mode 100644 index 000000000..5ec27f4a1 --- /dev/null +++ b/tools/qfcc/test/return-postop.r @@ -0,0 +1,22 @@ +#include "test-harness.h" + +int counter; + +int +function (void) +{ + return counter++; +} + +int +main (void) +{ + int ret = 0; + counter = 0; + function (); + if (counter != 1) { + printf ("counter != 1: %d\n", counter); + ret = 1; + } + return ret; +} From 33a3f925033de24cfa34018ddf30df6b6a61c2d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 13:09:23 +0900 Subject: [PATCH 2259/3664] [qfcc] Move .return handling into statements.c The means that the actual call expression is not in the statement lint of the enclosing block expression, but just its result, whether the call is void or not. This actually simplifies several things, but most importantly will make Ruamoko calls easier to implement. The test is because I had some trouble with double-calls, and is how I found the return-postop issue :P --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/expr.c | 17 ++++++++++------- tools/qfcc/source/expr_obj.c | 5 ++++- tools/qfcc/source/statements.c | 19 +++++++++++++++++++ tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/twice-called.r | 28 ++++++++++++++++++++++++++++ 6 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 tools/qfcc/test/twice-called.r diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 9d220b804..30b7cfd88 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -647,6 +647,7 @@ int is_math_op (int op) __attribute__((const)); int is_logic (int op) __attribute__((const)); int has_function_call (expr_t *e) __attribute__((pure)); +int is_function_call (expr_t *e) __attribute__((pure)); int is_nil (expr_t *e) __attribute__((pure)); int is_string_val (expr_t *e) __attribute__((pure)); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index df684e288..92281b3c4 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -216,9 +216,10 @@ get_type (expr_t *e) convert_name (e); switch (e->type) { case ex_branch: - case ex_labelref: type = e->e.branch.ret_type; break; + case ex_labelref: + return &type_void; case ex_memset: return e->e.memset.type; case ex_error: @@ -504,6 +505,7 @@ copy_expr (expr_t *e) n = new_expr (); *n = *e; n->e.branch.target = copy_expr (e->e.branch.target); + n->e.branch.index = copy_expr (e->e.branch.index); n->e.branch.test = copy_expr (e->e.branch.test); n->e.branch.args = copy_expr (e->e.branch.args); return n; @@ -1658,6 +1660,12 @@ has_function_call (expr_t *e) internal_error (e, "invalid expression type"); } +int +is_function_call (expr_t *e) +{ + return e->type == ex_branch && e->e.branch.type == pr_branch_call; +} + expr_t * asx_expr (int op, expr_t *e1, expr_t *e2) { @@ -2116,12 +2124,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) append_expr (call, e); } e = expr_file_line (call_expr (fexpr, args, ftype->t.func.type), fexpr); - append_expr (call, e); - if (!is_void(ftype->t.func.type)) { - call->e.block.result = new_ret_expr (ftype->t.func.type); - } else if (options.traditional) { - call->e.block.result = new_ret_expr (&type_float); - } + call->e.block.result = e; return call; } diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index 33eadb742..0e8a8d53e 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -248,6 +248,9 @@ message_expr (expr_t *receiver, keywordarg_t *message) if (call->type == ex_error) return receiver; - call->e.block.result = new_ret_expr (return_type); + if (!is_function_call (call->e.block.result)) { + internal_error (call, "unexpected block result type"); + } + call->e.block.result->e.branch.ret_type = return_type; return call; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 51a7a4ac9..bfba55950 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1071,6 +1071,9 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) sblock = statement_subexpr (sblock, func, &s->opa); s->opb = arguments[0]; s->opc = arguments[1]; + if (op) { + *op = return_operand (call->e.branch.ret_type, call); + } sblock_add_statement (sblock, s); sblock->next = new_sblock (); return sblock->next; @@ -1118,6 +1121,16 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) return sblock->next; } +static sblock_t * +expr_branch (sblock_t *sblock, expr_t *e, operand_t **op) +{ + if (e->e.branch.type != pr_branch_call) { + internal_error (e, "unexpected branch type in expression: %d", + e->e.branch.type); + } + return expr_call (sblock, e, op); +} + static sblock_t * statement_branch (sblock_t *sblock, expr_t *e) { @@ -1618,6 +1631,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_alias] = expr_alias, [ex_address] = expr_address, [ex_assign] = expr_assign, + [ex_branch] = expr_branch, }; if (!e) { *op = 0; @@ -1804,6 +1818,11 @@ statement_block (sblock_t *sblock, expr_t *e) sblock = sblock->next; } sblock = statement_slist (sblock, e->e.block.head); + if (e->e.block.is_call) { + // for a fuction call, the call expresion is in only the result, not + // the actual block + sblock = statement_slist (sblock, e->e.block.result); + } return sblock; } diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 4eb260e81..1f310048a 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -53,6 +53,7 @@ test_progs_dat=\ tools/qfcc/test/structstruct.dat \ tools/qfcc/test/swap.dat \ tools/qfcc/test/triangle.dat \ + tools/qfcc/test/twice-called.dat \ tools/qfcc/test/typedef.dat \ tools/qfcc/test/typelinker.dat \ tools/qfcc/test/unaryminus.dat \ @@ -605,6 +606,16 @@ tools/qfcc/test/triangle.run: $(qfcc_test_run_deps) include $(triangle_dep) # am--include-marker r_depfiles_remade += $(triangle_dep) +tools_qfcc_test_twice_called_dat_SOURCES=tools/qfcc/test/twice-called.r +twice_called_obj=$(tools_qfcc_test_twice_called_dat_SOURCES:.r=.o) +twice_called_dep=$(call qcautodep,$(tools_qfcc_test_twice_called_dat_SOURCES)) +tools/qfcc/test/twice-called.dat$(EXEEXT): $(twice_called_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(twice_called_obj) +tools/qfcc/test/twice-called.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ 100000 100000 1.00005 50002.4961 +include $(twice_called_dep) # am--include-marker +r_depfiles_remade += $(twice_called_dep) + tools_qfcc_test_typedef_dat_SOURCES=tools/qfcc/test/typedef.r typedef_obj=$(tools_qfcc_test_typedef_dat_SOURCES:.r=.o) typedef_dep=$(call qcautodep,$(tools_qfcc_test_typedef_dat_SOURCES)) diff --git a/tools/qfcc/test/twice-called.r b/tools/qfcc/test/twice-called.r new file mode 100644 index 000000000..9542af0f6 --- /dev/null +++ b/tools/qfcc/test/twice-called.r @@ -0,0 +1,28 @@ +#include "test-harness.h" + +int counter; + +int +function (void) +{ + return ++counter; +} + +int +main (void) +{ + int ret = 0; + counter = 0; + //function (); + //if (counter != 1) { + //printf ("discarded return not called only once\n"); + // ret = 1; + //} + counter = 0; + printf ("function: %d\n", function ()); + if (counter != 1) { + //printf ("used return not called only once\n"); + ret = 1; + } + return ret; +} From c53127707b52a7575d908bf10bfb8d7f1813e6a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 13:50:21 +0900 Subject: [PATCH 2260/3664] [qfcc] Set the return of Ruamoko calls Of course, I had the width of opc wrong :P. But with this, it seems that unoptimized calls should work once I get the stack frame working. --- libs/gamecode/opcodes.py | 2 +- tools/qfcc/source/statements.c | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 37ca5c2e2..ac5aa5e51 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -114,7 +114,7 @@ call_formats = { "mnemonic": "call", "opname": "call", "format": "{call_fmt[mm]}", - "widths": "{call_widths[mm]}, 0", + "widths": "{call_widths[mm]}, -1", "types": "{call_types[mm]}, ev_void", "args": { "op_mode": ".BCD", diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index bfba55950..fc5823395 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1115,7 +1115,14 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) } statement_t *s = new_statement (st_func, "call", call); sblock = statement_subexpr (sblock, func, &s->opa); - s->opc = short_operand (0, call); + if (!op) { + s->opc = short_operand (0, call); + } else { + if (!*op) { + *op = temp_operand (call->e.branch.ret_type, call); + } + s->opc = *op; + } sblock_add_statement (sblock, s); sblock->next = new_sblock (); return sblock->next; From 616a52efb570691ed835c25bc4e276238943043f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 16:19:04 +0900 Subject: [PATCH 2261/3664] [qfcc] Implement flow analysis for Ruamoko calls Thanks to the use/def/kill lists attached to statements for pseudo-ops, it turned out to be a lot easier to implement flow analysis (and thus dags processing) than I expected. I suspect I should go back and make the old call code use them too, and probably several other places, as that will greatly simplify the edge setting. --- tools/qfcc/include/statements.h | 6 +++--- tools/qfcc/source/dags.c | 14 +++++++++++--- tools/qfcc/source/flow.c | 7 ++++++- tools/qfcc/source/statements.c | 15 +++++++++++++++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 622d7c377..3bee3de33 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -113,9 +113,9 @@ typedef struct statement_s { operand_t *opc; struct expr_s *expr; ///< source expression for this statement int number; ///< number of this statement in function - operand_t *use; ///< list of pseudo operands used - operand_t *def; ///< list of pseudo operands defined - operand_t *kill; ///< list of pseudo operands killed + operand_t *use; ///< list of auxiliary operands used + operand_t *def; ///< list of auxiliary operands defined + operand_t *kill; ///< list of auxiliary operands killed } statement_t; typedef struct sblock_s { diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index d4a7b4fbe..a128422cc 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -406,7 +406,7 @@ dag_find_node (def_t *def, void *_daglabel) } static void -dagnode_set_edges (dag_t *dag, dagnode_t *n) +dagnode_set_edges (dag_t *dag, dagnode_t *n, statement_t *s) { int i; @@ -447,13 +447,21 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) set_add (n->edges, child->number); } } + for (operand_t *use = s->use; use; use = use->next) { + if (use->op_type == op_pseudo) { + continue; + } + daglabel_t *label = operand_label (dag, use); + label->live = 1; + set_add (n->edges, label->dagnode->number); + } if (n->type == st_func) { const char *num_params = 0; int first_param = 0; flowvar_t **flowvars = dag->flownode->graph->func->vars; if (!strcmp (n->label->opcode, "call")) { - internal_error (0, "not implemented"); + // nothing to do } else if (!strncmp (n->label->opcode, "rcall", 5)) { num_params = n->label->opcode + 6; first_param = 2; @@ -864,7 +872,7 @@ dag_create (flownode_t *flownode) n->type = s->type; n->label = op; dagnode_add_children (dag, n, operands, children); - dagnode_set_edges (dag, n); + dagnode_set_edges (dag, n, s); dagnode_set_reachable (dag, n); } } diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 8bcd4bbeb..8db692667 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1278,7 +1278,12 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } } if (strcmp (s->opcode, "call") == 0) { - internal_error (s->expr, "not implemented"); + // call uses opc to specify the destination of the return value + // parameter usage is taken care of by the statement's use + // list + flow_add_op_var (def, s->opc, 0); + // don't want old argument processing + calln = -1; } else if (strncmp (s->opcode, "call", 4) == 0) { start = 0; calln = s->opcode[5] - '0'; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index fc5823395..b47dc4a50 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1091,6 +1091,8 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) defspace_t *arg_space = current_func->arguments; expr_t *func = call->e.branch.target; expr_t *args = call->e.branch.args; + operand_t *use = 0; + operand_t *kill = 0; defspace_reset (arg_space); @@ -1112,6 +1114,17 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) expr_t *assign = assign_expr (new_def_expr (def), a); expr_file_line (assign, call); sblock = statement_slist (sblock, assign); + + // The call both uses and kills the arguments: use is obvious, but kill + // is because the callee has direct access to them and might modify + // them + // need two ops for the one def because there's two lists + operand_t *u = def_operand (def, arg_type, call); + operand_t *k = def_operand (def, arg_type, call); + u->next = use; + use = u; + k->next = kill; + kill = k; } statement_t *s = new_statement (st_func, "call", call); sblock = statement_subexpr (sblock, func, &s->opa); @@ -1123,6 +1136,8 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) } s->opc = *op; } + s->use = use; + s->kill = kill; sblock_add_statement (sblock, s); sblock->next = new_sblock (); return sblock->next; From 3df46d197fa33907b5046db0034093178ec3450b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 18:44:51 +0900 Subject: [PATCH 2262/3664] [gamecode] Add instructions for stack adjust, nop, and ldconst ldconst isn't implemented yet but the plan is to load various constants (eg, 0, 1, 2, pi, e, ...). Stack adjust is useful for adding an offset to the stack pointer without having to worry about finding it (and it checks for alignment). nop is just that :) --- libs/gamecode/opcodes.py | 30 ++++++++++++++++++++++++++++++ libs/gamecode/pr_exec.c | 12 ++++++++++++ 2 files changed, 42 insertions(+) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index ac5aa5e51..d6cb80f6f 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -5,6 +5,9 @@ bitmap_txt = """ 0 0011 mmss pop 0 1ccc ttss compare 0 0000 00nn +0 0000 0000 noop +0 0000 0001 adjstk +0 0000 0010 constant 0 1011 nnnn 0 1111 nnnn @@ -75,6 +78,14 @@ etype_tt = ["ev_int", "ev_float", "ev_long", "ev_double"] unsigned_t = ["ev_uint", "ev_ulong"] float_t = ["ev_float", "ev_double"] +adjstk_formats = { + "opcode": "OP_ADJSTK", + "mnemonic": "adjstk", + "opname": "adjstk", + "format": "%sa, %sb", + "widths": "0, 0, 0", + "types": "ev_short, ev_short, ev_invalid", +} bitops_formats = { "opcode": "OP_{op_bit[oo].upper()}_{bit_type[t]}_{ss+1}", "mnemonic": "{op_bit[oo]}", @@ -157,6 +168,14 @@ compare2_formats = { "cmp_types": unsigned_t, }, } +constant_formats = { + "opcode": "OP_LDCONST", + "mnemonic": "ldconst", + "opname": "ldconst", + "format": "%sa, %sb, %gc", + "widths": "0, 0, -1", + "types": "ev_short, ev_short, ev_void", +} convert_formats = { "opcode": "OP_CONV", "mnemonic": "conv", @@ -268,6 +287,14 @@ move_formats = { ], }, } +noop_formats = { + "opcode": "OP_NOP", + "mnemonic": "nop", + "opname": "nop", + "format": "there were plums...", + "widths": "0, 0, 0", + "types": "ev_invalid, ev_invalid, ev_invalid", +} push_formats = { "opcode": "OP_PUSH_{op_mode[mm]}_{ss+1}", "mnemonic": "push", @@ -473,11 +500,13 @@ with_formats = { } group_map = { + "adjstk": adjstk_formats, "bitops": bitops_formats, "branch": branch_formats, "call": call_formats, "compare": compare_formats, "compare2": compare2_formats, + "constant": constant_formats, "convert": convert_formats, "hops": hops_formats, "jump": jump_formats, @@ -486,6 +515,7 @@ group_map = { "mathops": mathops_formats, "memset": memset_formats, "move": move_formats, + "noop": noop_formats, "push": push_formats, "pushregs": pushregs_formats, "pop": pop_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 15885244c..a7581cbc4 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2766,6 +2766,18 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) pr_opcode_e st_op = st->op & OP_MASK; switch (st_op) { // 0 0000 + case OP_NOP: + break; + case OP_ADJSTK: + if (st->a || (st->b & 3)) { + PR_RunError (pr, "invalid stack adjustment: %d, %d", + st->a, (short) st->b); + } + *pr->globals.stack += (short) st->b; + break; + case OP_LDCONST: + PR_RunError (pr, "OP_LDCONST not implemented"); + break; case OP_LOAD_B_1: case OP_LOAD_C_1: case OP_LOAD_D_1: From 79bd4dd7245a491d58c576db2f67b006d4925ea5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 18:47:12 +0900 Subject: [PATCH 2263/3664] [qfcc] Set up the function stack frame Still need to get the base register index into the instructions, but I think this is it for basic code generation. I should be able to start testing Ruamoko properly fairly soon :) --- tools/qfcc/include/expr.h | 15 ++++++++++++ tools/qfcc/include/expr_names.h | 2 ++ tools/qfcc/source/expr.c | 42 ++++++++++++++++++++++++++++++++- tools/qfcc/source/expr_assign.c | 2 ++ tools/qfcc/source/function.c | 23 ++++++++++++++++-- tools/qfcc/source/statements.c | 24 +++++++++++++++++++ 6 files changed, 105 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 30b7cfd88..aeb4e86ff 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -238,6 +238,17 @@ typedef struct { struct expr_s *ret_val; } ex_return_t; +typedef struct { + short mode; ///< currently must be 0 + short offset; ///< amount by which stack will be adjusted +} ex_adjstk_t; + +typedef struct { + short mode; ///< currently must be 0 + short reg; ///< base register to load + struct expr_s *with; ///< value to load +} ex_with_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -269,6 +280,8 @@ typedef struct expr_s { ex_assign_t assign; ///< assignment expr params ex_branch_t branch; ///< branch expr params ex_return_t retrn; ///< return expr params + ex_adjstk_t adjstk; ///< stack adjust param + ex_with_t with; ///< with expr param struct type_s *nil; ///< type for nil if known } e; } expr_t; @@ -688,6 +701,8 @@ expr_t *new_address_expr (struct type_s *lvtype, expr_t *lvalue, expr_t *offset); expr_t *new_assign_expr (expr_t *dst, expr_t *src); expr_t *new_return_expr (expr_t *ret_val); +expr_t *new_adjstk_expr (int mode, int offset); +expr_t *new_with_expr (int mode, int reg, expr_t *val); /** Create an expression of the correct type that references the specified parameter slot. diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index 08285c94a..5af4e739b 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -59,5 +59,7 @@ EX_EXPR(address) ///< address of an lvalue expression (::ex_address_t) EX_EXPR(assign) ///< assignment of src expr to dst expr (::ex_assing_t) EX_EXPR(branch) ///< branch expression (::ex_branch_t) EX_EXPR(return) ///< return expression (::ex_return_t) +EX_EXPR(adjstk) ///< stack adjust expression (::ex_adjstk_t) +EX_EXPR(with) ///< with expression (::ex_with_t) ///@} diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 92281b3c4..9395d699c 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -219,6 +219,8 @@ get_type (expr_t *e) type = e->e.branch.ret_type; break; case ex_labelref: + case ex_adjstk: + case ex_with: return &type_void; case ex_memset: return e->e.memset.type; @@ -512,7 +514,16 @@ copy_expr (expr_t *e) case ex_return: n = new_expr (); *n = *e; - n->e.retrn.ret_val = copy_expr (n->e.retrn.ret_val); + n->e.retrn.ret_val = copy_expr (e->e.retrn.ret_val); + return n; + case ex_adjstk: + n = new_expr (); + *n = *e; + return n; + case ex_with: + n = new_expr (); + *n = *e; + n->e.with.with = copy_expr (e->e.with.with); return n; case ex_count: break; @@ -1344,6 +1355,27 @@ new_return_expr (expr_t *ret_val) return retrn; } +expr_t * +new_adjstk_expr (int mode, int offset) +{ + expr_t *adj = new_expr (); + adj->type = ex_adjstk; + adj->e.adjstk.mode = mode; + adj->e.adjstk.offset = offset; + return adj; +} + +expr_t * +new_with_expr (int mode, int reg, expr_t *val) +{ + expr_t *with = new_expr (); + with->type = ex_with; + with->e.with.mode = mode; + with->e.with.reg = reg; + with->e.with.with = val; + return with; +} + static expr_t * param_expr (const char *name, type_t *type) { @@ -1653,6 +1685,8 @@ has_function_call (expr_t *e) case ex_value: case ex_compound: case ex_memset: + case ex_adjstk: + case ex_with: return 0; case ex_count: break; @@ -1745,6 +1779,8 @@ unary_expr (int op, expr_t *e) case ex_memset: case ex_selector: case ex_return: + case ex_adjstk: + case ex_with: internal_error (e, "unexpected expression type"); case ex_uexpr: if (e->e.expr.op == '-') { @@ -1847,6 +1883,8 @@ unary_expr (int op, expr_t *e) case ex_memset: case ex_selector: case ex_return: + case ex_adjstk: + case ex_with: internal_error (e, "unexpected expression type"); case ex_bool: return new_bool_expr (e->e.bool.false_list, @@ -1927,6 +1965,8 @@ unary_expr (int op, expr_t *e) case ex_memset: case ex_selector: case ex_return: + case ex_adjstk: + case ex_with: internal_error (e, "unexpected expression type"); case ex_uexpr: if (e->e.expr.op == '~') diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 4eec4916a..0926931fb 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -138,6 +138,8 @@ is_lvalue (const expr_t *expr) case ex_error: case ex_selector: case ex_return: + case ex_adjstk: + case ex_with: break; case ex_count: internal_error (expr, "invalid expression"); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index bfc1da059..b4cf2b2c6 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -673,9 +673,21 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) state_expr->next = statements; statements = state_expr; } - if (options.code.progsversion == PROG_VERSION) { - } function_t *func = fsym->s.func; + if (options.code.progsversion == PROG_VERSION) { + expr_t *e; + e = new_with_expr (2, 1, new_short_expr (0)); + e->next = statements; + e->file = func->def->file; + e->line = func->def->line; + statements = e; + + e = new_adjstk_expr (0, 0); + e->next = statements; + e->file = func->def->file; + e->line = func->def->line; + statements = e; + } emit_function (func, statements); if (options.code.progsversion < PROG_VERSION) { // stitch parameter and locals data together with parameters coming @@ -699,6 +711,13 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) merge_spaces (space, func->locals->space, 4); func->locals->space = space; + // allocate 0 words to force alignment + defspace_alloc_aligned_highwater (space, 0, 4); + + dstatement_t *st = &pr.code->code[func->code]; + if (st->op == OP_ADJSTK) { + st->b = -space->size; + } merge_spaces (space, func->parameters->space, 4); func->parameters->space = space; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index b47dc4a50..1168c3fcf 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1235,6 +1235,28 @@ statement_return (sblock_t *sblock, expr_t *e) return sblock; } +static sblock_t * +statement_adjstk (sblock_t *sblock, expr_t *e) +{ + statement_t *s = new_statement (st_func, "adjstk", e); + s->opa = short_operand (e->e.adjstk.mode, e); + s->opb = short_operand (e->e.adjstk.offset, e); + + sblock_add_statement (sblock, s); + return sblock; +} + +static sblock_t * +statement_with (sblock_t *sblock, expr_t *e) +{ + statement_t *s = new_statement (st_func, "with", e); + s->opa = short_operand (e->e.with.mode, e); + s->opc = short_operand (e->e.with.reg, e); + sblock = statement_subexpr (sblock, e->e.with.with, &s->opb); + sblock_add_statement (sblock, s); + return sblock; +} + static statement_t * lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) { @@ -1930,6 +1952,8 @@ statement_slist (sblock_t *sblock, expr_t *e) [ex_assign] = statement_assign, [ex_branch] = statement_branch, [ex_return] = statement_return, + [ex_adjstk] = statement_adjstk, + [ex_with] = statement_with, }; for (/**/; e; e = e->next) { From 9199a0ee54c951368f8b89289ebb93222de14bc6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 20:31:49 +0900 Subject: [PATCH 2264/3664] [gamecode] Don't check v6p progs for Ruamoko progs It doesn't end well. For now, the Ruamoko check is just a stub, but I do plan on doing similar checks. --- include/QF/progs.h | 1 + libs/gamecode/pr_opcode.c | 9 +++++++++ libs/gamecode/pr_v6p_opcode.c | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 02cbb0229..57e88fccd 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -264,6 +264,7 @@ int PR_RunPostLoadFuncs (progs_t *pr); \todo should this be elsewhere? */ int PR_Check_Opcodes (progs_t *pr); +int PR_Check_v6p_Opcodes (progs_t *pr); void PR_BoundsCheckSize (progs_t *pr, pr_ptr_t addr, unsigned size); void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 799066c7c..289f06a1f 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -61,3 +61,12 @@ PR_Opcode (pr_ushort_t opcode) opcode &= OP_MASK; return &pr_opcodes[opcode]; } + +int +PR_Check_Opcodes (progs_t *pr) +{ + if (pr->progs->version < PROG_VERSION) { + return PR_Check_v6p_Opcodes (pr); + } + return 1; +} diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index e9b3a0b7a..2e9514a93 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -1591,7 +1591,7 @@ error: } int -PR_Check_Opcodes (progs_t *pr) +PR_Check_v6p_Opcodes (progs_t *pr) { const v6p_opcode_t *op; dstatement_t *st; From 7a5ee6a55a17f90e801a50487db43acf45143ac5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 20:33:15 +0900 Subject: [PATCH 2265/3664] [gamecode] Initialize .stack if it's available And implement bounds checks for adjstk. --- libs/gamecode/pr_exec.c | 21 ++++++++++++++++----- libs/gamecode/pr_load.c | 3 +++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index a7581cbc4..7802e5e0f 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1897,6 +1897,21 @@ pr_stack_pop (progs_t *pr) return stk; } +static void +pr_stack_adjust (progs_t *pr, int mode, int offset) +{ + // keep the stack 16-byte aligned + if (mode || (offset & 3)) { + PR_RunError (pr, "invalid stack adjustment: %d, %d", mode, offset); + } + + pr_ptr_t stack = *pr->globals.stack; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack + offset, 0); + } + *pr->globals.stack = stack + offset; +} + static void pr_with (progs_t *pr, const dstatement_t *st) { @@ -2769,11 +2784,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_NOP: break; case OP_ADJSTK: - if (st->a || (st->b & 3)) { - PR_RunError (pr, "invalid stack adjustment: %d, %d", - st->a, (short) st->b); - } - *pr->globals.stack += (short) st->b; + pr_stack_adjust (pr, st->a, (short) st->b); break; case OP_LDCONST: PR_RunError (pr, "OP_LDCONST not implemented"); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 9770bc786..e8538d5bd 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -226,6 +226,9 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->stack_bottom = pr->stack - pr->pr_globals; pr->globals_size = (pr_type_t *) ((byte *) pr->stack + pr->stack_size) - pr->pr_globals; + if (pr->globals.stack && pr->stack_bottom) { + *pr->globals.stack = pr->globals_size; + } if (pr->zone) { PR_Zone_Init (pr); From 0a5101f88c34bcb723db26e1bb125d6101de4592 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 20:34:43 +0900 Subject: [PATCH 2266/3664] [qfcc] Specify base register index for local defs While all base registers can be used for any purpose at any time (this is why the with instruction has hard-absolute modes: you can never get permanently lost), qfcc currently uses the convention of register 0 for globals and register 1 for stack locals (params, locals, function args). The register used to access a def is stored in the def and that is used to set the register bits in the instruction opcode. The def code actually doesn't know anything about any conventions: it assumes all defs are global for non-temp defs (the function code updates the defs before emitting code) and the current function provides the register to use for any temp defs allocated while emitting code. Seems to work well, but debug is utterly messed up (not surprised, that will be tricky). --- tools/qfcc/include/def.h | 1 + tools/qfcc/include/function.h | 1 + tools/qfcc/source/def.c | 1 + tools/qfcc/source/emit.c | 16 +++++++++++++--- tools/qfcc/source/function.c | 18 +++++++++++++++++- 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index f49dd2f8e..1477cc7e3 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -60,6 +60,7 @@ typedef struct def_s { const char *name; ///< the def's name struct defspace_s *space; ///< defspace to which this def belongs int offset; ///< address of this def in its defspace + int reg; ///< base register index to access def /** \name Def aliasing. Aliasing a def provides a different view of the def providing access diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 3b04bb9e5..cceef9341 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -69,6 +69,7 @@ typedef struct function_s { pr_string_t s_file; ///< source file with definition pr_string_t s_name; ///< name of function in output const struct type_s *type; ///< function's type without aliases + int temp_reg; ///< base register to use for temp defs int temp_num; ///< number for next temp var struct def_s *temp_defs[4]; ///< freed temp vars (by size) struct def_s *def; ///< output def holding function number diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 5f6947c37..2cc92d4aa 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -230,6 +230,7 @@ temp_def (type_t *type) temp->line = pr.source_line; set_storage_bits (temp, sc_local); temp->space = space; + temp->reg = current_func->temp_reg; return temp; } diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 3ee80df7f..60dd095d2 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -228,10 +228,20 @@ emit_statement (statement_t *statement) } } s = codespace_newstatement (pr.code); + memset (s, 0, sizeof (*s)); s->op = opcode_get (inst); - s->a = def_a ? def_a->offset : 0; - s->b = def_b ? def_b->offset : 0; - s->c = def_c ? def_c->offset : 0; + if (def_a) { + s->a = def_a->offset; + s->op |= ((def_a->reg) << OP_A_SHIFT) & OP_A_BASE; + } + if (def_b) { + s->b = def_b->offset; + s->op |= ((def_b->reg) << OP_B_SHIFT) & OP_B_BASE; + } + if (def_c) { + s->c = def_c->offset; + s->op |= ((def_c->reg) << OP_C_SHIFT) & OP_C_BASE; + } if (options.verbosity >= 2) { opcode_print_statement (pr.code->size - 1, s); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index b4cf2b2c6..a4d785d6d 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -71,6 +71,10 @@ static function_t *functions_freelist; static hashtab_t *overloaded_functions; static hashtab_t *function_map; +// standardized base register to use for all locals (arguments, local defs, +// params) +#define LOCALS_REG 1 + static const char * ol_func_get_key (const void *_f, void *unused) { @@ -676,7 +680,7 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) function_t *func = fsym->s.func; if (options.code.progsversion == PROG_VERSION) { expr_t *e; - e = new_with_expr (2, 1, new_short_expr (0)); + e = new_with_expr (2, LOCALS_REG, new_short_expr (0)); e->next = statements; e->file = func->def->file; e->line = func->def->line; @@ -687,6 +691,18 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) e->file = func->def->file; e->line = func->def->line; statements = e; + + func->temp_reg = LOCALS_REG; + for (def_t *def = func->locals->space->defs; def; def = def->next) { + if (def->local || def->param) { + def->reg = LOCALS_REG; + } + } + for (def_t *def = func->parameters->space->defs; def; def = def->next) { + if (def->local || def->param) { + def->reg = LOCALS_REG; + } + } } emit_function (func, statements); if (options.code.progsversion < PROG_VERSION) { From 2a89a678ec7d957dd9a8610e677d1f9984723803 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 20:46:26 +0900 Subject: [PATCH 2267/3664] [qfcc] Don't allocate local defs for Ruamoko progs They don't need the defs thanks to the stack. --- tools/qfcc/source/obj_file.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 17ba70080..6a53b32ab 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -982,14 +982,16 @@ qfo_to_progs (qfo_t *in_qfo, int *size) progs->numglobals = qfo->spaces[qfo_near_data_space].data_size; progs->numglobals = align_globals_size (progs->numglobals); locals_start = progs->numglobals; - for (i = qfo_num_spaces; i < qfo->num_spaces; i++) { - if (options.code.local_merging) { - if (locals_size < qfo->spaces[i].data_size) { - locals_size = qfo->spaces[i].data_size; - big_locals = i; + if (options.code.progsversion < PROG_VERSION) { + for (i = qfo_num_spaces; i < qfo->num_spaces; i++) { + if (options.code.local_merging) { + if (locals_size < qfo->spaces[i].data_size) { + locals_size = qfo->spaces[i].data_size; + big_locals = i; + } + } else { + locals_size += align_globals_size (qfo->spaces[i].data_size); } - } else { - locals_size += align_globals_size (qfo->spaces[i].data_size); } } progs->numglobals += locals_size; @@ -1081,13 +1083,15 @@ qfo_to_progs (qfo_t *in_qfo, int *size) qfo_mspace_t *space = qfo->spaces + qf->locals_space; df->first_statement = qf->code; - df->parm_start = locals_start; - df->locals = space->data_size; - // finalize the offsets of the local defs - for (j = 0; j < space->num_defs; j++) - space->defs[j].offset += locals_start; - if (!options.code.local_merging) - locals_start += align_globals_size (df->locals); + if (options.code.progsversion < PROG_VERSION) { + df->parm_start = locals_start; + df->locals = space->data_size; + // finalize the offsets of the local defs + for (j = 0; j < space->num_defs; j++) + space->defs[j].offset += locals_start; + if (!options.code.local_merging) + locals_start += align_globals_size (df->locals); + } df->profile = 0; df->name = qf->name; df->file = qf->file; From e6fbe9fdbc9b4ade1ce1fd4a4b2f14fd6fbd2920 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 20:47:35 +0900 Subject: [PATCH 2268/3664] [qfcc] Create .stack for Ruamoko progs It's rather necessary :) --- tools/qfcc/source/qfcc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 25c1a89c6..134890dea 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -447,6 +447,10 @@ finish_link (void) ¶m_alignment); linker_add_def (".xdefs", &type_xdefs, flags, 0); } + if (options.code.progsversion == PROG_VERSION) { + int stk = (QFOD_GLOBAL | QFOD_INITIALIZED | QFOD_NOSAVE); + linker_add_def (".stack", &type_uint, stk, 0); + } if (options.code.debug) { pr_int_t str; From 06b1ea6837a82192d61b283744f1d003e82fc367 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Jan 2022 10:57:26 +0900 Subject: [PATCH 2269/3664] [gamecode] Tweak some docs and macro names And fix an incorrect definition for RETURN_QUAT. Prefixed MAX_STACK_DEPTH and LOCALSTACK_SIZE (and LOCALSTACK_SIZE got an extra _). The rest is just edits to documentation comments. --- include/QF/progs.h | 15 +++++++-------- libs/gamecode/pr_exec.c | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 57e88fccd..0709e4891 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -197,7 +197,7 @@ typedef int pr_load_func_t (progs_t *pr); /** Initialize a ::progs_t VM struct from an already open file. \param pr pointer to ::progs_t VM struct - \param file handle of file to read progs data from + \param file handle of file from which to read progs data \param size bytes of \p file to read \note \e All runtime strings (permanent or temporary) are allocated from @@ -981,7 +981,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define RETURN_QUAT(p,q) VectorCopy (q, R_QUAT (p)) +#define RETURN_QUAT(p,q) QuatCopy (q, R_QUAT (p)) ///@} /** \defgroup prda_entity_fields Entity Fields @@ -1504,7 +1504,6 @@ void PR_Resources_Clear (progs_t *pr); \param name The name of the resource. Used for retrieving the resource. \param data The resource data. - callback. \param clear Callback for performing any necessary cleanup. Called by PR_Resources_Clear(). The parameters are the current VM (\p pr) and \p data. @@ -1796,8 +1795,8 @@ extern const char *pr_gametype; //============================================================================ -#define MAX_STACK_DEPTH 64 -#define LOCALSTACK_SIZE 4096 +#define PR_MAX_STACK_DEPTH 64 +#define PR_LOCAL_STACK_SIZE 4096 #define PR_RS_SLOTS 16 #define PR_BASE_IND(o, b) (((o) & OP_##b##_BASE) >> OP_##b##_SHIFT) #define PR_BASE(p, s, b) (p->pr_bases[PR_BASE_IND(s->op, b)]) @@ -1927,7 +1926,7 @@ struct progs_s { bfunction_t *pr_xfunction; int pr_xstatement; - prstack_t pr_stack[MAX_STACK_DEPTH]; + prstack_t pr_stack[PR_MAX_STACK_DEPTH]; int pr_depth; /// \name progs visible stack @@ -1943,7 +1942,7 @@ struct progs_s { int stack_size; ///< set by user ///@} - int localstack[LOCALSTACK_SIZE]; + int localstack[PR_LOCAL_STACK_SIZE]; int localstack_used; ///@} @@ -1974,7 +1973,7 @@ struct progs_s { double *dtime; ///< required for OP_STATE d float *ftime; ///< required for OP_STATE f pr_uint_t *self; ///< required for OP_STATE - pr_ptr_t *stack; ///< required for OP_(PUSH|POP)* + pr_ptr_t *stack; ///< required for OP_(PUSH|POP)* } globals; struct { pr_int_t nextthink; ///< required for OP_STATE diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 7802e5e0f..9d8469185 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -137,7 +137,7 @@ PR_PushFrame (progs_t *pr) { prstack_t *frame; - if (pr->pr_depth == MAX_STACK_DEPTH) + if (pr->pr_depth == PR_MAX_STACK_DEPTH) PR_RunError (pr, "stack overflow"); frame = pr->pr_stack + pr->pr_depth++; @@ -272,7 +272,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) pr->pr_xstatement = f->first_statement - 1; // offset the st++ // save off any locals that the new function steps on - if (pr->localstack_used + f->locals > LOCALSTACK_SIZE) + if (pr->localstack_used + f->locals > PR_LOCAL_STACK_SIZE) PR_RunError (pr, "PR_EnterFunction: locals stack overflow"); memcpy (&pr->localstack[pr->localstack_used], From 68d87de2516db00c781da0500fb13f2862f1bc38 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Jan 2022 11:38:26 +0900 Subject: [PATCH 2270/3664] [gamecode] Clarify docs for PR_CallFunction I found the docs in PR_ExecuteProgram and PR_CallFunction to be a little confusing, so making it explicit that PR_ExecuteProgram calls PR_CallFunction and that PR_CallFunction should be called only in a builtin seemed like a good idea. --- include/QF/progs.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 0709e4891..3da8bca00 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -166,6 +166,7 @@ void PR_PopFrame (progs_t *pr); return to the caller. Nested calls are fully supported. \param pr pointer to ::progs_t VM struct \param fnum number of the function to call + \note Calls PR_CallFunction() */ void PR_ExecuteProgram (progs_t *pr, pr_func_t fnum); @@ -179,6 +180,9 @@ void PR_ExecuteProgram (progs_t *pr, pr_func_t fnum); written \return true if \p fnum was a progs function, false if \p fnum was a builtin + \note Called by PR_ExecuteProgram, so the only time this should be called + is in a builtin function that calls a progs function and returns + immediately (eg, to implement `return progsfunc();`). */ int PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr); From 9e4ecc14e95393befa21ac47a4b013a417f8fece Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Jan 2022 15:31:26 +0900 Subject: [PATCH 2271/3664] [qfcc] Fix error in handling argc in test-harness There was an out-by-one where attempting to run a program with only one argument would result in the argument not being passed to the program (two worked). This is actually the source of the error fixed in 9347e4f9019c9ad69584a62f14c9fa4cefec293c because test-harness.c was the basis for qwaq's main.c --- tools/qfcc/test/test-harness.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index c0aa96b10..bf51508b9 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -276,24 +276,29 @@ main (int argc, char **argv) if (!load_progs (name)) Sys_Error ("couldn't load %s", name); + if ((dfunc = PR_FindFunction (&test_pr, ".main")) + || (dfunc = PR_FindFunction (&test_pr, "main"))) { + main_func = dfunc - test_pr.pr_functions; + } else { + PR_Undefined (&test_pr, "function", "main"); + } + PR_PushFrame (&test_pr); - if (argc > 2) + if (argc) { pr_argc = argc; + } pr_argv = PR_Zone_Malloc (&test_pr, (pr_argc + 1) * 4); pr_argv[0] = PR_SetTempString (&test_pr, name); - for (i = 1; i < pr_argc; i++) + for (i = 1; i < pr_argc; i++) { pr_argv[i] = PR_SetTempString (&test_pr, argv[i]); + } pr_argv[i] = 0; - if ((dfunc = PR_FindFunction (&test_pr, ".main")) - || (dfunc = PR_FindFunction (&test_pr, "main"))) - main_func = dfunc - test_pr.pr_functions; - else - PR_Undefined (&test_pr, "function", "main"); PR_RESET_PARAMS (&test_pr); P_INT (&test_pr, 0) = pr_argc; P_POINTER (&test_pr, 1) = PR_SetPointer (&test_pr, pr_argv); test_pr.pr_argc = 2; + PR_ExecuteProgram (&test_pr, main_func); PR_PopFrame (&test_pr); if (options.flote) From 234f2212d622f4109dd5340e5776abab1b7a57aa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Jan 2022 16:00:04 +0900 Subject: [PATCH 2272/3664] [gamecode] Run an audit of progs parameter setup nq was just a bit of whitespace, but qw had an actual bug where the parameters were not being reset before writing to them. It really doesn't help that I don't know where to get progs suitable for testing (really don't what to have to write my own). --- nq/source/host.c | 3 +-- nq/source/sv_main.c | 3 +-- qw/source/sv_pr_cpqw.c | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/nq/source/host.c b/nq/source/host.c index 907250a5c..601d5d335 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -386,8 +386,7 @@ SV_DropClient (qboolean crash) // call the prog function for removing a client // this will set the body to a dead frame, among other things saveSelf = *sv_globals.self; - *sv_globals.self = - EDICT_TO_PROG (&sv_pr_state, host_client->edict); + *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, host_client->edict); PR_ExecuteProgram (&sv_pr_state, sv_funcs.ClientDisconnect); *sv_globals.self = saveSelf; } diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index f11f1389d..d1d795de8 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1087,8 +1087,7 @@ SV_SaveSpawnparms (void) continue; // call the progs to get default spawn parms for the new client - *sv_globals.self = - EDICT_TO_PROG (&sv_pr_state, host_client->edict); + *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, host_client->edict); PR_ExecuteProgram (&sv_pr_state, sv_funcs.SetChangeParms); for (j = 0; j < NUM_SPAWN_PARMS; j++) host_client->spawn_parms[j] = sv_globals.parms[j]; diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index eebb91ef4..f331b7e32 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -817,6 +817,7 @@ cpqw_user_cmd (void) *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, sv_player); PR_PushFrame (pr); + PR_RESET_PARAMS (pr); P_FLOAT (pr, 0) = argc; for (i = 1; i < argc + 1; i++) P_STRING (pr, i) = PR_SetTempString (pr, Cmd_Argv (i - 1)); From 861e98725c92e1cdd7f027a02e15c9c07fc44f5d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Jan 2022 21:41:35 +0900 Subject: [PATCH 2273/3664] [gamecode] Return early if the entered function has no locals As even the simplest v6p functions that take parameters but have no local or temporary variables still have locals for the local copy of the parameters, this is a both a good check for for the Ruamoko ISA as its functions never have locals (everything's on the progs data stack), and an optimization for v6p functions that have no params or locals (simple getters (very rare?), most .ctor, etc). --- libs/gamecode/pr_exec.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 9d8469185..a7389f54a 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -229,6 +229,14 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) PR_PushFrame (pr); + //Sys_Printf("%s:\n", PR_GetString(pr,f->name)); + pr->pr_xfunction = f; + pr->pr_xstatement = f->first_statement - 1; // offset the st++ + + if (!f->locals) { + return; + } + if (f->numparms > 0) { paramofs = f->parm_start; for (i = 0; i < f->numparms; i++) { @@ -267,10 +275,6 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) } } - //Sys_Printf("%s:\n", PR_GetString(pr,f->name)); - pr->pr_xfunction = f; - pr->pr_xstatement = f->first_statement - 1; // offset the st++ - // save off any locals that the new function steps on if (pr->localstack_used + f->locals > PR_LOCAL_STACK_SIZE) PR_RunError (pr, "PR_EnterFunction: locals stack overflow"); From ec5830f70b380af3c7390bb5f84c7b55763113a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Jan 2022 00:59:38 +0900 Subject: [PATCH 2274/3664] [qfcc] "Use" the correct operands The problem was a missed change when switching the internal statement format to Ruamoko: I "used" the statement's operands directly rather than the rotated ones when emitting v6p progs. Fixes a compile segfault when NOT optimizing. --- tools/qfcc/source/emit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 60dd095d2..30b2d1b4b 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -203,11 +203,11 @@ emit_statement (statement_t *statement) op_c = statement->opc; } def_a = get_operand_def (statement->expr, op_a); - use_tempop (statement->opa, statement->expr); + use_tempop (op_a, statement->expr); def_b = get_operand_def (statement->expr, op_b); - use_tempop (statement->opb, statement->expr); + use_tempop (op_b, statement->expr); def_c = get_operand_def (statement->expr, op_c); - use_tempop (statement->opc, statement->expr); + use_tempop (op_c, statement->expr); inst = opcode_find (opcode, op_a, op_b, op_c); if (!inst) { From b6093e07282c4ac8cc734301f279377eebb05954 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Jan 2022 01:31:50 +0900 Subject: [PATCH 2275/3664] [qfcc] Add failing test for lost var use Storing a variable into a dereference pointer (*p = x) is not marking the variable as used (due to a mistake while converting to Ruamoko statement format) resulting in assignments to that variable being dropped due to it being a dead assignment as the assignment to the variable and the storing need to be in separate basic blocks (thus the call in the test, though an if would have worked, I think) for the bug to trigger. --- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/lost-use.r | 29 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tools/qfcc/test/lost-use.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 1f310048a..88b9e8480 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -31,6 +31,7 @@ test_progs_dat=\ tools/qfcc/test/infloop.dat \ tools/qfcc/test/ivar-struct-return.dat \ tools/qfcc/test/link_order.dat \ + tools/qfcc/test/lost-use.dat \ tools/qfcc/test/methodparams.dat \ tools/qfcc/test/modulo.dat \ tools/qfcc/test/nilparamret.dat \ @@ -386,6 +387,16 @@ tools/qfcc/test/link_order.run: $(qfcc_test_run_deps) include $(link_order_dep) # am--include-marker r_depfiles_remade += $(link_order_dep) +tools_qfcc_test_lost_use_dat_SOURCES=tools/qfcc/test/lost-use.r +lost_use_obj=$(tools_qfcc_test_lost_use_dat_SOURCES:.r=.o) +lost_use_dep=$(call qcautodep,$(tools_qfcc_test_lost_use_dat_SOURCES)) +tools/qfcc/test/lost-use.dat$(EXEEXT): $(lost_use_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(lost_use_obj) +tools/qfcc/test/lost-use.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(lost_use_dep) # am--include-marker +r_depfiles_remade += $(lost_use_dep) + tools_qfcc_test_methodparams_dat_SOURCES=tools/qfcc/test/methodparams.r methodparams_obj=$(tools_qfcc_test_methodparams_dat_SOURCES:.r=.o) methodparams_dep=$(call qcautodep,$(tools_qfcc_test_methodparams_dat_SOURCES)) diff --git a/tools/qfcc/test/lost-use.r b/tools/qfcc/test/lost-use.r new file mode 100644 index 000000000..dc9d79142 --- /dev/null +++ b/tools/qfcc/test/lost-use.r @@ -0,0 +1,29 @@ +void printf (string fmt, ...) = #0; +int getval(void) +{ + return 42; +} + +void magic (void) +{ +} + +void storeval (int *p) +{ + int x = getval (); + magic (); + *p = x; +} + +int val; + +int +main(void) +{ + storeval (&val); + if (val != 42) { + printf ("val is dead: %d\n", val); + return 1; + } + return 0; +} From adf672e7b17a4e26f13d603be742c5b1b910bc76 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Jan 2022 01:37:57 +0900 Subject: [PATCH 2276/3664] [qfcc] Mark the correct operand as used in stores This fixes the lost-use test, and windows not dragging properly in qwaq-curses. Another single-character bug-fix :P --- tools/qfcc/source/flow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 8db692667..753b15928 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1225,7 +1225,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, src_op = s->opa; aux_op2 = s->opc; } else if (!strcmp (s->opcode, "store")) { - flow_add_op_var (use, s->opb, 1); + flow_add_op_var (use, s->opc, 1); res_op = flow_analyze_pointer_operand (s->opa, def); src_op = s->opc; aux_op2 = s->opa; From f72e8ef551d85e472b83ef5e5ccd1a568d3e96a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Jan 2022 02:04:28 +0900 Subject: [PATCH 2277/3664] [qwaq] Fix a couple of errors in debug Update qdb_get_string's mangling for qfcc's new unsigned int support and fix an incorrect cast of the param pointer passed by prd_runerror that caused a segfault when trying to use the string. Attempting to use qwaq-app (ie, the qc debugger) on Ruamoko ISA progs mostly works, but the defs are decidedly unhappy (due to the base registers). --- ruamoko/qwaq/builtins/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index ba43ddcb5..2738a8589 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -378,7 +378,7 @@ qdb_get_event (progs_t *pr) break; case prd_runerror: case prd_error: - event->message = PR_SetReturnString (pr, *(char **) target->param); + event->message = PR_SetReturnString (pr, (char *) target->param); break; case prd_begin: event->function = *(pr_func_t *) target->param; @@ -661,7 +661,7 @@ static builtin_t builtins[] = { {"qdb_get_stack", qdb_get_stack, -1}, {"qdb_get_event", qdb_get_event, -1}, {"qdb_get_data", qdb_get_data, -1}, - {"qdb_get_string|{tag qdb_target_s=}i", qdb_get_string, -1}, + {"qdb_get_string|{tag qdb_target_s=}I", qdb_get_string, -1}, {"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1}, {"qdb_get_file_path", qdb_get_file_path, -1}, {"qdb_find_string", qdb_find_string, -1}, From cfaf158ebcb68cdc54b039100aa2f7be36e471fc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Jan 2022 13:47:14 +0900 Subject: [PATCH 2278/3664] [math] Add some bit-op functions Just 32-bit rounding to next higher power of two, and base 2 logarithm. Most importantly, they are suitable for use in initializers as they are constant in, constant out. --- include/QF/Makemodule.am | 1 + include/QF/math/bitop.h | 73 ++++++++++++++++++++++++++++++++++++ libs/util/test/Makemodule.am | 5 +++ libs/util/test/test-bitop.c | 55 +++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 include/QF/math/bitop.h create mode 100644 libs/util/test/test-bitop.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 3892a430e..d36dd7ead 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -115,6 +115,7 @@ include_qf_input = \ include/QF/input/imt.h include_qf_math = \ + include/QF/math/bitop.h \ include/QF/math/dual.h \ include/QF/math/half.h \ include/QF/math/matrix3.h \ diff --git a/include/QF/math/bitop.h b/include/QF/math/bitop.h new file mode 100644 index 000000000..ee00ac6ca --- /dev/null +++ b/include/QF/math/bitop.h @@ -0,0 +1,73 @@ +/* + bitop.h + + bit-op functions + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/1/23 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_math_bitop_h +#define __QF_math_bitop_h + +/** \defgroup mathlib_bitop Bit-op functions + \ingroup utils +*/ +///@{ + +#include "QF/qtypes.h" + +#define BITOP_RUP1__(x) ( (x) | ( (x) >> 1)) +#define BITOP_RUP2__(x) (BITOP_RUP1__(x) | (BITOP_RUP1__(x) >> 2)) +#define BITOP_RUP4__(x) (BITOP_RUP2__(x) | (BITOP_RUP2__(x) >> 4)) +#define BITOP_RUP8__(x) (BITOP_RUP4__(x) | (BITOP_RUP4__(x) >> 8)) +#define BITOP_RUP16__(x) (BITOP_RUP8__(x) | (BITOP_RUP8__(x) >> 16)) +/** Round x up to the next power of two. + + Rounds x up to the next power of two leaving exact powers of two + untouched. + + \param x The value to round + \return The next higher power of two or x if it already is a power + of two. +*/ +#define BITOP_RUP(x) (BITOP_RUP16__((uint32_t)(x) - 1) + 1) + +#define BITOP_LOG2__(x) (((((x) & 0xffff0000) != 0) << 4) \ + |((((x) & 0xff00ff00) != 0) << 3) \ + |((((x) & 0xf0f0f0f0) != 0) << 2) \ + |((((x) & 0xcccccccc) != 0) << 1) \ + |((((x) & 0xaaaaaaaa) != 0) << 0)) +/** Log base 2 rounded up. + + Finds the base 2 logarithm of x rounded up (ceil(log2(x))). + + \param x The value for which to find the base 2 logarithm. + \return Log base 2 of x, rounded up (2 -> 1, 3 -> 2, 4 -> 2) +*/ +#define BITOP_LOG2(x) BITOP_LOG2__(BITOP_RUP(x)) + +///@} + +#endif // __QF_math_bitop_h diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 188239e11..7fa5a5f98 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -1,6 +1,7 @@ libs_util_tests = \ libs/util/test/test-bary \ libs/util/test/test-baryvf \ + libs/util/test/test-bitop \ libs/util/test/test-bsearch \ libs/util/test/test-cexpr \ libs/util/test/test-cmem \ @@ -36,6 +37,10 @@ libs_util_test_test_baryvf_SOURCES=libs/util/test/test-baryvf.c libs_util_test_test_baryvf_LDADD=libs/util/libQFutil.la libs_util_test_test_baryvf_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_bitop_SOURCES=libs/util/test/test-bitop.c +libs_util_test_test_bitop_LDADD=libs/util/libQFutil.la +libs_util_test_test_bitop_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_bsearch_SOURCES=libs/util/test/test-bsearch.c libs_util_test_test_bsearch_LDADD=libs/util/libQFutil.la libs_util_test_test_bsearch_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-bitop.c b/libs/util/test/test-bitop.c new file mode 100644 index 000000000..795d023f5 --- /dev/null +++ b/libs/util/test/test-bitop.c @@ -0,0 +1,55 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/math/bitop.h" + +struct { + uint32_t value; + uint32_t expect; +} tests [] = { + {BITOP_RUP(1), 1}, + {BITOP_RUP(2), 2}, + {BITOP_RUP(3), 4}, + {BITOP_RUP(4), 4}, + {BITOP_RUP(5), 8}, + {BITOP_RUP(7), 8}, + {BITOP_RUP(8), 8}, + {BITOP_RUP(0x40000000), 0x40000000}, + {BITOP_RUP(0x40000001), 0x80000000}, + {BITOP_LOG2(1), 0}, + {BITOP_LOG2(2), 1}, + {BITOP_LOG2(3), 2}, + {BITOP_LOG2(4), 2}, + {BITOP_LOG2(5), 3}, + {BITOP_LOG2(7), 3}, + {BITOP_LOG2(8), 3}, + {BITOP_LOG2(9), 4}, + {BITOP_LOG2(15), 4}, + {BITOP_LOG2(16), 4}, + {BITOP_LOG2(17), 5}, + {BITOP_LOG2(31), 5}, + {BITOP_LOG2(32), 5}, + {BITOP_LOG2(33), 6}, + {BITOP_LOG2(0x40000000), 30}, + {BITOP_LOG2(0x40000001), 31}, +}; +#define num_tests (sizeof (tests) / sizeof (tests[0])) + +int +main (int argc, const char **argv) +{ + size_t i; + int res = 0; + + for (i = 0; i < num_tests; i++) { + if (tests[i].value != tests[i].expect) { + res |= 1; + printf ("test %d failed\n", (int) i); + printf ("expect: %8x\n", tests[i].expect); + printf ("got : %8x\n", tests[i].value); + } + } + return res; +} From 3c86660d4a56547830d9cfcae3ab94a721004492 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Jan 2022 14:17:25 +0900 Subject: [PATCH 2279/3664] [gamecode] Rename MAX_PARMS to PR_MAXPARAMS --- include/QF/progs.h | 6 +++--- include/QF/progs/pr_comp.h | 4 ++-- libs/gamecode/pr_debug.c | 2 +- libs/gamecode/pr_exec.c | 6 +++--- libs/gamecode/pr_resolve.c | 2 +- libs/gamecode/pr_v6p_opcode.c | 2 +- libs/ruamoko/rua_obj.c | 2 +- qw/source/sv_pr_cmds.c | 2 +- tools/qfcc/source/expr.c | 8 ++++---- tools/qfcc/source/function.c | 4 ++-- tools/qfcc/source/method.c | 4 ++-- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 3da8bca00..bf96afca0 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1205,7 +1205,7 @@ typedef struct { pr_int_t locals; pr_uint_t profile; pr_int_t numparms; - dparmsize_t parm_size[MAX_PARMS]; + dparmsize_t parm_size[PR_MAX_PARAMS]; dfunction_t *descriptor; builtin_proc func; } bfunction_t; @@ -1896,8 +1896,8 @@ struct progs_s { /// \name parameter block ///@{ pr_type_t *pr_return; - pr_type_t *pr_params[MAX_PARMS]; - pr_type_t *pr_real_params[MAX_PARMS]; + pr_type_t *pr_params[PR_MAX_PARAMS]; + pr_type_t *pr_real_params[PR_MAX_PARAMS]; int pr_param_size; ///< covers both params and return int pr_param_alignment; ///< covers both params and return pr_type_t pr_return_buffer[32];///< for discarded return values diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 22d7e0dc8..98de7cae0 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -506,7 +506,7 @@ typedef struct dparmsize_s { #define DEF_SAVEGLOBAL (1<<15) -#define MAX_PARMS 8 +#define PR_MAX_PARAMS 8 typedef struct dfunction_s { pr_int_t first_statement; // negative numbers are builtins @@ -519,7 +519,7 @@ typedef struct dfunction_s { pr_string_t file; // source file defined in pr_int_t numparms; // -ve is varargs (1s comp of real count) - dparmsize_t parm_size[MAX_PARMS]; + dparmsize_t parm_size[PR_MAX_PARAMS]; } dfunction_t; typedef union pr_type_u { diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 0a3d00e8b..a30aa8c66 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1612,7 +1612,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) opchar = fmt[3]; parm_ind = fmt[2] - '0'; fmt++; // P has one extra item - if (parm_ind >= MAX_PARMS) + if (parm_ind >= PR_MAX_PARAMS) goto err; } diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index a7389f54a..0d8424857 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -219,7 +219,7 @@ static void PR_EnterFunction (progs_t *pr, bfunction_t *f) { pr_int_t i; - pr_type_t *dstParams[MAX_PARMS]; + pr_type_t *dstParams[PR_MAX_PARAMS]; pr_ptr_t paramofs = 0; if (pr->pr_trace && !pr->debug_handler) { @@ -263,7 +263,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) } dparmsize_t parmsize = { pr->pr_param_size, pr->pr_param_alignment }; paramofs = align_offset (paramofs, parmsize ); - if (i < MAX_PARMS) { + if (i < PR_MAX_PARAMS) { dstParams[i] = pr->pr_globals + paramofs; } for (; i < pr->pr_argc; i++) { @@ -303,7 +303,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) copy_args = pr->pr_argc - i; argc->int_var = copy_args; argv->int_var = dstParams[i] - pr->pr_globals; - if (i < MAX_PARMS) { + if (i < PR_MAX_PARAMS) { memcpy (dstParams[i], pr->pr_params[i], (copy_args * pr->pr_param_size) * sizeof (pr_type_t)); } diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 299f8d2ae..992aff74e 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -129,7 +129,7 @@ PR_ResolveGlobals (progs_t *pr) if (!(def = PR_FindGlobal (pr, sym = ".return"))) goto error; pr->pr_return = &pr->pr_globals[def->ofs]; - for (i = 0; i < MAX_PARMS; i++) { + for (i = 0; i < PR_MAX_PARAMS; i++) { param_n[sizeof (param_str) - 2] = i + '0'; if (!(def = PR_FindGlobal (pr, sym = param_n))) goto error; diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 2e9514a93..94da01a4c 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -1508,7 +1508,7 @@ is_vector_parameter_store (progs_t *pr, dstatement_t *st, return 0; if (operand != st->a) return 0; - for (i = 0; i < MAX_PARMS; i++) + for (i = 0; i < PR_MAX_PARAMS; i++) if (st->b == pr->pr_params[i] - pr->pr_globals) return 1; return 0; diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 092562d50..10a5e165d 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1412,7 +1412,7 @@ rua_obj_msg_sendv (progs_t *pr) int count = args->count; pr_type_t *params = G_GPOINTER (pr, args->list); - if (count < 2 || count > MAX_PARMS) { + if (count < 2 || count > PR_MAX_PARAMS) { PR_RunError (pr, "bad args count in obj_msg_sendv: %d", count); } if (pr_boundscheck->int_val) { diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 1431729ee..d6ecf086b 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -1115,7 +1115,7 @@ PF_WriteBytes (progs_t *pr) { int i, p; int count = pr->pr_argc - 1; - byte buf[MAX_PARMS]; + byte buf[PR_MAX_PARAMS]; for (i = 0; i < count; i++) { p = P_FLOAT (pr, i + 1); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 9395d699c..c0b291789 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2029,8 +2029,8 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) int arg_count = 0, parm_count = 0; int i; expr_t *args = 0, **a = &args; - type_t *arg_types[MAX_PARMS]; - expr_t *arg_exprs[MAX_PARMS][2]; + type_t *arg_types[PR_MAX_PARAMS]; + expr_t *arg_exprs[PR_MAX_PARAMS][2]; int arg_expr_count = 0; expr_t *assign; expr_t *call; @@ -2042,8 +2042,8 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) arg_count++; } - if (arg_count > MAX_PARMS) { - return error (fexpr, "more than %d parameters", MAX_PARMS); + if (arg_count > PR_MAX_PARAMS) { + return error (fexpr, "more than %d parameters", PR_MAX_PARAMS); } if (ftype->t.func.num_params < -1) { if (-arg_count > ftype->t.func.num_params + 1) { diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index a4d785d6d..ac148bf74 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -536,7 +536,7 @@ build_scope (symbol_t *fsym, symtab_t *parent) } if (args) { - while (i < MAX_PARMS) { + while (i < PR_MAX_PARAMS) { param = new_symbol_type (va (0, ".par%d", i), &type_param); initialize_def (param, 0, parameters->space, sc_param); i++; @@ -636,7 +636,7 @@ static void build_function (symbol_t *fsym) { const type_t *func_type = fsym->s.func->type; - if (func_type->t.func.num_params > MAX_PARMS) { + if (func_type->t.func.num_params > PR_MAX_PARAMS) { error (0, "too many params"); } } diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index b4cae8e08..f36a1fd20 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -710,8 +710,8 @@ method_check_params (method_t *method, expr_t *args) for (count = 0, a = args; a; a = a->next) count++; - if (count > MAX_PARMS) - return error (args, "more than %d parameters", MAX_PARMS); + if (count > PR_MAX_PARAMS) + return error (args, "more than %d parameters", PR_MAX_PARAMS); if (mtype->t.func.num_params >= 0) param_count = mtype->t.func.num_params; From e746e39738781eac7127da7464480049b95c4405 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Jan 2022 14:27:36 +0900 Subject: [PATCH 2280/3664] [gamecode] Create macros for progs sizeof and alignof I wound up needing the idioms in too many places. --- include/QF/progs/pr_comp.h | 3 +++ libs/gamecode/pr_opcode.c | 4 ++-- tools/qfcc/source/type.c | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 98de7cae0..88a644f62 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -62,6 +62,9 @@ typedef enum { ev_type_count // not a type, gives number of types } etype_t; +#define PR_SIZEOF(type) (sizeof (pr_##type##_t) / sizeof (pr_int_t)) +#define PR_ALIGNOF(type) (__alignof__ (pr_##type##_t) / __alignof__ (pr_int_t)) + extern const pr_ushort_t pr_type_size[ev_type_count]; extern const pr_ushort_t pr_type_alignment[ev_type_count]; extern const char * const pr_type_name[ev_type_count]; diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index 289f06a1f..34a36c242 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -33,13 +33,13 @@ #include "QF/progs.h" -#define EV_TYPE(type) (sizeof (pr_##type##_t) / sizeof (pr_int_t)), +#define EV_TYPE(type) PR_SIZEOF(type), VISIBLE const pr_ushort_t pr_type_size[ev_type_count] = { #include "QF/progs/pr_type_names.h" 0, // ev_invalid not a valid/simple type }; -#define EV_TYPE(type) (__alignof__ (pr_##type##_t) / __alignof__ (pr_int_t)), +#define EV_TYPE(type) PR_ALIGNOF(type), VISIBLE const pr_ushort_t pr_type_alignment[ev_type_count] = { #include "QF/progs/pr_type_names.h" 0, // ev_invalid not a valid/simple type diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index a52594af8..ceb0360a5 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -64,7 +64,7 @@ type_t type_##t = { \ .type = ev_##t, \ .name = #t, \ - .alignment = __alignof__(pr_##t##_t) / __alignof__ (pr_int_t), \ + .alignment = PR_ALIGNOF(t), \ .meta = ty_basic, \ {{ __builtin_choose_expr (ev_##t == ev_field \ || ev_##t == ev_func \ From a6b932025cd5ba37028fcd25a1f166e0d649e7a7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Jan 2022 21:54:03 +0900 Subject: [PATCH 2281/3664] [gamecode] Provide builtins with information about their parameters This will make it possible for the engine to set up their parameter pointers when running Ruamoko progs. At this stage, it doesn't matter *too* much, except for varargs functions, because no builtin yet takes anything larger than a float quaternion, but it will be critical when double or long vec3 and vec4 values are passed. --- include/QF/progs.h | 20 +++ libs/audio/snd_progs.c | 4 +- libs/console/bi_inputline.c | 26 ++-- libs/console/menu.c | 48 ++++--- libs/gib/bi_gib.c | 13 +- libs/ruamoko/pr_cmds.c | 68 +++++----- libs/ruamoko/rua_cbuf.c | 11 +- libs/ruamoko/rua_cmd.c | 10 +- libs/ruamoko/rua_cvar.c | 25 ++-- libs/ruamoko/rua_hash.c | 36 ++--- libs/ruamoko/rua_input.c | 66 ++++----- libs/ruamoko/rua_keys.c | 15 +- libs/ruamoko/rua_math.c | 92 +++++++------ libs/ruamoko/rua_mersenne.c | 15 +- libs/ruamoko/rua_msgbuf.c | 77 ++++++----- libs/ruamoko/rua_obj.c | 119 ++++++++-------- libs/ruamoko/rua_plist.c | 44 +++--- libs/ruamoko/rua_qfile.c | 45 +++--- libs/ruamoko/rua_qfs.c | 20 +-- libs/ruamoko/rua_runtime.c | 5 +- libs/ruamoko/rua_script.c | 18 +-- libs/ruamoko/rua_set.c | 140 ++++++++++--------- libs/ruamoko/rua_stdlib.c | 13 +- libs/ruamoko/rua_string.c | 39 +++--- libs/video/renderer/r_progs.c | 30 ++-- nq/source/sv_pr_cmds.c | 130 +++++++++--------- qw/source/sv_pr_cmds.c | 183 +++++++++++++------------ qw/source/sv_pr_cpqw.c | 38 +++--- qw/source/sv_pr_qwe.c | 45 +++--- qw/source/sv_user.c | 7 +- ruamoko/cl_menu/menu.r | 1 + ruamoko/lib/Object.r | 10 +- ruamoko/lib/Set.r | 1 + ruamoko/lib/key.r | 1 + ruamoko/qwaq/builtins/curses.c | 211 ++++++++++++++++------------- ruamoko/qwaq/builtins/debug.c | 48 +++---- ruamoko/qwaq/builtins/editbuffer.c | 142 +++++++++---------- ruamoko/qwaq/builtins/graphics.c | 14 +- ruamoko/qwaq/builtins/main.c | 8 +- ruamoko/qwaq/builtins/term-input.c | 10 +- tools/qfcc/test/test-bi.c | 14 +- 41 files changed, 1012 insertions(+), 850 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index bf96afca0..25f0d1a4e 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -33,6 +33,7 @@ \image latex vm-mem.eps "VM memory map" */ +#include "QF/math/bitop.h" #include "QF/progs/pr_comp.h" #include "QF/progs/pr_debug.h" @@ -1193,8 +1194,27 @@ typedef struct { /// The number of the builtin for \#N in QC. -1 for automatic allocation. /// 0 or >= ::PR_AUTOBUILTIN is invalid. pr_int_t binum; + /// The number of parameters the builtin takes. Negative numbers mean + /// varargs with ~num_params (-num_params - 1) being the number of real + /// parameters. + pr_int_t num_params; + /// Parameter size specificiation. + /// + /// Up to 8 parameters are supported for automatic parameter setup because + /// that's all that v6p progs can pass. Builtins taking more than 8 + /// parameters are already Ruamoko-only and thus know how to deal with the + /// parameters being on the data stack. + /// + /// The encoding is the same as for progs functions, with 3:5 for + /// alignment:size (size 0 means 32 words). + dparmsize_t params[PR_MAX_PARAMS]; } builtin_t; +#define PR_PARAM(type) { \ + .size = PR_SIZEOF(type) & 0x1f, \ + .alignment = BITOP_LOG2(PR_ALIGNOF(type)), \ +} + /** Duplicate the dfunction_t descriptor with the addition of a pointer to the builtin function. Avoids a level of indirection when calling a builtin function. diff --git a/libs/audio/snd_progs.c b/libs/audio/snd_progs.c index a130fd44c..8e77bdde7 100644 --- a/libs/audio/snd_progs.c +++ b/libs/audio/snd_progs.c @@ -47,8 +47,10 @@ bi_S_LocalSound (progs_t *pr) S_LocalSound (sound); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"S_LocalSound", bi_S_LocalSound, -1}, + bi(S_LocalSound, 1, p(string)), {0} }; diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index a2de6285c..af8fba096 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -302,21 +302,23 @@ bi_InputLine_Draw (progs_t *pr) line->line->draw (line->line); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"InputLine_Create", bi_InputLine_Create, -1}, - {"InputLine_SetPos", bi_InputLine_SetPos, -1}, - {"InputLine_SetCursor", bi_InputLine_SetCursor, -1}, + bi(InputLine_Create, 3, p(int), p(int), p(int)), + bi(InputLine_SetPos, 3, p(ptr), p(int), p(int)), + bi(InputLine_SetCursor, 2, p(ptr), p(int)), {"InputLine_SetEnter|^{tag _inputline_t=}(v*^v)^v", - bi_InputLine_SetEnter, -1}, + bi_InputLine_SetEnter, -1, 3, {p(ptr), p(func), p(ptr)}}, {"InputLine_SetEnter|^{tag _inputline_t=}(@@:.)@:", - bi_InputLine_SetEnter, -1}, - {"InputLine_SetWidth", bi_InputLine_SetWidth, -1}, - {"InputLine_SetText", bi_InputLine_SetText, -1}, - {"InputLine_GetText", bi_InputLine_GetText, -1}, - {"InputLine_Destroy", bi_InputLine_Destroy, -1}, - {"InputLine_Clear", bi_InputLine_Clear, -1}, - {"InputLine_Process", bi_InputLine_Process, -1}, - {"InputLine_Draw", bi_InputLine_Draw, -1}, + bi_InputLine_SetEnter, -1, 4, {p(ptr), p(func), p(ptr), p(ptr)}}, + bi(InputLine_SetWidth, 2, p(ptr), p(int)), + bi(InputLine_SetText, 2, p(ptr), p(string)), + bi(InputLine_GetText, 1, p(ptr)), + bi(InputLine_Destroy, 1, p(ptr)), + bi(InputLine_Clear, 2, p(ptr), p(int)), + bi(InputLine_Process, 2, p(ptr), p(int)), + bi(InputLine_Draw, 1, p(ptr)), {0} }; diff --git a/libs/console/menu.c b/libs/console/menu.c index 80bcc772e..aea52cefc 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -513,29 +513,33 @@ menu_load_file (progs_t *pr, const char *path, off_t *size) return data; } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"Menu_Begin", bi_Menu_Begin, -1}, - {"Menu_FadeScreen", bi_Menu_FadeScreen, -1}, - {"Menu_Draw", bi_Menu_Draw, -1}, - {"Menu_EnterHook", bi_Menu_EnterHook, -1}, - {"Menu_LeaveHook", bi_Menu_LeaveHook, -1}, - {"Menu_Pic", bi_Menu_Pic, -1}, - {"Menu_SubPic", bi_Menu_SubPic, -1}, - {"Menu_CenterPic", bi_Menu_CenterPic, -1}, - {"Menu_CenterSubPic", bi_Menu_CenterSubPic, -1}, - {"Menu_Item", bi_Menu_Item, -1}, - {"Menu_Cursor", bi_Menu_Cursor, -1}, - {"Menu_KeyEvent", bi_Menu_KeyEvent, -1}, - {"Menu_End", bi_Menu_End, -1}, - {"Menu_TopMenu", bi_Menu_TopMenu, -1}, - {"Menu_SelectMenu", bi_Menu_SelectMenu, -1}, - {"Menu_SetQuit", bi_Menu_SetQuit, -1}, - {"Menu_Quit", bi_Menu_Quit, -1}, - {"Menu_GetIndex", bi_Menu_GetIndex, -1}, - {"Menu_Next", bi_Menu_Next, -1}, - {"Menu_Prev", bi_Menu_Prev, -1}, - {"Menu_Enter", bi_Menu_Enter, -1}, - {"Menu_Leave", bi_Menu_Leave, -1}, + bi(Menu_Begin, 3, p(int), p(int), p(string)), + bi(Menu_FadeScreen, 1, p(int)), + bi(Menu_Draw, 2, p(int), p(int)), + bi(Menu_EnterHook, 1, p(func)), + bi(Menu_LeaveHook, 1, p(func)), + bi(Menu_Pic, 3, p(int), p(int), p(string)), + bi(Menu_SubPic, 7, p(int), p(int), p(string), + p(int), p(int), p(int), p(int)), + bi(Menu_CenterPic, 3, p(int), p(int), p(string)), + bi(Menu_CenterSubPic, 7, p(int), p(int), p(string), + p(int), p(int), p(int), p(int)), + bi(Menu_Item, 5, p(int), p(int), p(string), p(func), p(int)), + bi(Menu_Cursor, 1, p(func)), + bi(Menu_KeyEvent, 1, p(func)), + bi(Menu_End, 0), + bi(Menu_TopMenu, 1, p(string)), + bi(Menu_SelectMenu, 1, p(string)), + bi(Menu_SetQuit, 1, p(func)), + bi(Menu_Quit, 0), + bi(Menu_GetIndex, 0), + bi(Menu_Next, 0), + bi(Menu_Prev, 0), + bi(Menu_Enter, 0), + bi(Menu_Leave, 0), {0}, }; diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index f2f9bc671..28d5401c0 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -175,12 +175,15 @@ bi_GIB_Handle_Get (progs_t *pr) // R_INT (pr) = 0; } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"GIB_Builtin_Add", bi_GIB_Builtin_Add, -1}, - {"GIB_Return", bi_GIB_Return, -1}, - {"GIB_Handle_New", bi_GIB_Handle_New, -1}, - {"GIB_Handle_Free", bi_GIB_Handle_Free, -1}, - {"GIB_Handle_Get", bi_GIB_Handle_Get, -1}, + bi(GIB_Builtin_Add, 2, p(string), p(func)), + bi(GIB_Return, 1, p(string)), + bi(GIB_Handle_New, 0),//FIXME + bi(GIB_Handle_Free, 0),//FIXME + bi(GIB_Handle_Get, 0),//FIXME {0} }; diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 5aed0b2a4..7c70b82d6 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -249,7 +249,7 @@ PF_fabs (progs_t *pr) entity (entity start, .(...) fld, ... match) find */ static void -PF_Find (progs_t *pr) +PF_find (progs_t *pr) { const char *s = 0, *t; // ev_string int i; // ev_vector @@ -557,7 +557,7 @@ PF_charcount (progs_t *pr) string () gametype */ static void -PR_gametype (progs_t *pr) +PF_gametype (progs_t *pr) { RETURN_STRING (pr, pr_gametype); } @@ -585,41 +585,43 @@ PF_PR_FindFunction (progs_t *pr) #define QF (PR_RANGE_QF << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"break", PF_break, 6}, - {"random", PF_random, 7}, - {"normalize", PF_normalize, 9}, - {"vlen", PF_vlen, 12}, - {"vectoyaw", PF_vectoyaw, 13}, - {"find", PF_Find, 18}, - {"dprint", PF_dprint, 25}, - {"ftos", PF_ftos, 26}, - {"vtos", PF_vtos, 27}, - {"coredump", PF_coredump, 28}, - {"traceon", PF_traceon, 29}, - {"traceoff", PF_traceoff, 30}, - {"eprint", PF_eprint, 31}, - {"rint", PF_rint, 36}, - {"floor", PF_floor, 37}, - {"ceil", PF_ceil, 38}, - {"fabs", PF_fabs, 43}, - {"cvar", PF_cvar, 45}, - {"nextent", PF_nextent, 47}, - {"vectoangles", PF_vectoangles, 51}, - {"cvar_set", PF_cvar_set, 72}, - {"stof", PF_stof, 81}, + bi(break, 6, 0), + bi(random, 7, 0), + bi(normalize, 9, 1, p(vector)), + bi(vlen, 12, 1, p(vector)), + bi(vectoyaw, 13, 1, p(vector)), + bi(find, 18, -3, p(entity), p(field)), + bi(dprint, 25, -1), + bi(ftos, 26, 1, p(float)), + bi(vtos, 27, 1, p(vector)), + bi(coredump, 28, 0), + bi(traceon, 29, 0), + bi(traceoff, 30, 0), + bi(eprint, 31, 1, p(entity)), + bi(rint, 36, 1, p(float)), + bi(floor, 37, 1, p(float)), + bi(ceil, 38, 1, p(float)), + bi(fabs, 43, 1, p(float)), + bi(cvar, 45, 1, p(string)), + bi(nextent, 47, 1, p(entity)), + bi(vectoangles, 51, 1, p(vector)), + bi(cvar_set, 72, 2, p(string), p(string)), + bi(stof, 81, 1, p(string)), - {"charcount", PF_charcount, QF 101}, - {"ftoi", PF_ftoi, QF 110}, - {"itof", PF_itof, QF 111}, - {"itos", PF_itos, QF 112}, - {"stoi", PF_stoi, QF 113}, - {"stov", PF_stov, QF 114}, - {"gametype", PR_gametype, QF 115}, + bi(charcount, QF 101, 2, p(string), p(string)), + bi(ftoi, QF 110, 1, p(float)), + bi(itof, QF 111, 1, p(int)), + bi(itos, QF 112, 1, p(int)), + bi(stoi, QF 113, 1, p(string)), + bi(stov, QF 114, 1, p(string)), + bi(gametype, QF 115, 0), - {"PR_SetField", PF_PR_SetField, -1}, - {"PR_FindFunction", PF_PR_FindFunction, -1}, + bi(PR_SetField, -1, 3, p(entity), p(string), p(string)), + bi(PR_FindFunction, -1, 1, p(string)), {0} }; diff --git a/libs/ruamoko/rua_cbuf.c b/libs/ruamoko/rua_cbuf.c index 5d1bbc095..0a3870d80 100644 --- a/libs/ruamoko/rua_cbuf.c +++ b/libs/ruamoko/rua_cbuf.c @@ -93,11 +93,14 @@ bi_cbuf_clear (progs_t *pr, void *data) { } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"Cbuf_AddText", bi_Cbuf_AddText, -1}, - {"Cbuf_InsertText", bi_Cbuf_InsertText, -1}, - {"Cbuf_Execute", bi_Cbuf_Execute, -1}, - {"Cbuf_Execute_Sets", bi_Cbuf_Execute_Sets, -1}, + bi(Cbuf_AddText, 1, p(string)), + bi(Cbuf_InsertText, 1, p(string)), + bi(Cbuf_Execute, 0), + bi(Cbuf_Execute_Sets, 0), {0} }; diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index 44006b815..8be474e50 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -145,11 +145,13 @@ bi_Cmd_Args (progs_t *pr) //Cmd_ExecuteString //Cmd_ForwardToServer +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"Cmd_AddCommand", bi_Cmd_AddCommand, -1}, - {"Cmd_Argc", bi_Cmd_Argc, -1}, - {"Cmd_Argv", bi_Cmd_Argv, -1}, - {"Cmd_Args", bi_Cmd_Args, -1}, + bi(Cmd_AddCommand, 2, p(string), p(func)), + bi(Cmd_Argc, 0), + bi(Cmd_Argv, 1, p(int)), + bi(Cmd_Args, 1, p(int)), {0} }; diff --git a/libs/ruamoko/rua_cvar.c b/libs/ruamoko/rua_cvar.c index dbb652817..4cf68ee4f 100644 --- a/libs/ruamoko/rua_cvar.c +++ b/libs/ruamoko/rua_cvar.c @@ -232,18 +232,21 @@ bi_Cvar_Toggle (progs_t *pr) Cvar_Set (var, var->int_val ? "0" : "1"); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"Cvar_MakeAlias", bi_Cvar_MakeAlias, -1}, - {"Cvar_RemoveAlias", bi_Cvar_RemoveAlias, -1}, - {"Cvar_SetFloat", bi_Cvar_SetFloat, -1}, - {"Cvar_SetInteger", bi_Cvar_SetInteger, -1}, - {"Cvar_SetVector", bi_Cvar_SetVector, -1}, - {"Cvar_SetString", bi_Cvar_SetString, -1}, - {"Cvar_GetFloat", bi_Cvar_GetFloat, -1}, - {"Cvar_GetInteger", bi_Cvar_GetInteger, -1}, - {"Cvar_GetVector", bi_Cvar_GetVector, -1}, - {"Cvar_GetString", bi_Cvar_GetString, -1}, - {"Cvar_Toggle", bi_Cvar_Toggle, -1}, + bi(Cvar_MakeAlias, 2, p(string), p(string)), + bi(Cvar_RemoveAlias, 1, p(string)), + bi(Cvar_SetFloat, 2, p(string), p(float)), + bi(Cvar_SetInteger, 2, p(string), p(int)), + bi(Cvar_SetVector, 2, p(string), p(vector)), + bi(Cvar_SetString, 2, p(string), p(string)), + bi(Cvar_GetFloat, 1, p(string)), + bi(Cvar_GetInteger, 1, p(string)), + bi(Cvar_GetVector, 1, p(string)), + bi(Cvar_GetString, 1, p(string)), + bi(Cvar_Toggle, 1, p(string)), {0} }; diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 3e9336398..a1b277706 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -359,24 +359,26 @@ bi_hash_clear (progs_t *pr, void *data) table_reset (res); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"Hash_NewTable", bi_Hash_NewTable, -1}, - {"Hash_SetHashCompare", bi_Hash_SetHashCompare, -1}, - {"Hash_DelTable", bi_Hash_DelTable, -1}, - {"Hash_FlushTable", bi_Hash_FlushTable, -1}, - {"Hash_Add", bi_Hash_Add, -1}, - {"Hash_AddElement", bi_Hash_AddElement, -1}, - {"Hash_Find", bi_Hash_Find, -1}, - {"Hash_FindElement", bi_Hash_FindElement, -1}, - {"Hash_FindList", bi_Hash_FindList, -1}, - {"Hash_FindElementList", bi_Hash_FindElementList, -1}, - {"Hash_Del", bi_Hash_Del, -1}, - {"Hash_DelElement", bi_Hash_DelElement, -1}, - {"Hash_Free", bi_Hash_Free, -1}, - {"Hash_String", bi_Hash_String, -1}, - {"Hash_Buffer", bi_Hash_Buffer, -1}, - {"Hash_GetList", bi_Hash_GetList, -1}, - {"Hash_Stats", bi_Hash_Stats, -1}, + bi(Hash_NewTable, 4, p(int), p(func), p(func), p(ptr)), + bi(Hash_SetHashCompare, 3, p(ptr), p(func), p(func)), + bi(Hash_DelTable, 1, p(ptr)), + bi(Hash_FlushTable, 1, p(ptr)), + bi(Hash_Add, 2, p(ptr), p(ptr)), + bi(Hash_AddElement, 2, p(ptr), p(ptr)), + bi(Hash_Find, 2, p(ptr), p(string)), + bi(Hash_FindElement, 2, p(ptr), p(ptr)), + bi(Hash_FindList, 2, p(ptr), p(string)), + bi(Hash_FindElementList, 2, p(ptr), p(ptr)), + bi(Hash_Del, 2, p(ptr), p(string)), + bi(Hash_DelElement, 2, p(ptr), p(ptr)), + bi(Hash_Free, 2, p(ptr), p(ptr)), + bi(Hash_String, 1, p(string)), + bi(Hash_Buffer, 2, p(ptr), p(int)), + bi(Hash_GetList, 1, p(ptr)), + bi(Hash_Stats, 1, p(ptr)), {0} }; diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index b838b3086..e93d88085 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -407,56 +407,58 @@ secured (progs_t *pr) PR_RunError (pr, "Secured function called"); } -#define bi(x) {#x, secured, -1} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } +#define bi(x,np,params...) {#x, secured, -1, np, {params}} static builtin_t secure_builtins[] = { - bi(IN_CreateButton), - bi(IN_CreateAxis), - bi(IN_LoadConfig), + bi(IN_CreateButton, 2, p(string), p(string)), + bi(IN_CreateAxis, 2, p(string), p(string)), + bi(IN_LoadConfig, 1, p(ptr)), {0} }; #undef bi -#define bi(x) {#x, bi_##x, -1} +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} static builtin_t insecure_builtins[] = { - bi(IN_CreateButton), - bi(IN_CreateAxis), - bi(IN_LoadConfig), + bi(IN_CreateButton, 2, p(string), p(string)), + bi(IN_CreateAxis, 2, p(string), p(string)), + bi(IN_LoadConfig, 1, p(ptr)), {0} }; static builtin_t builtins[] = { - bi(IN_FindDeviceId), - bi(IN_GetDeviceName), - bi(IN_GetDeviceId), - bi(IN_AxisInfo), - bi(IN_ButtonInfo), - bi(IN_GetAxisName), - bi(IN_GetButtonName), - bi(IN_GetAxisNumber), - bi(IN_GetButtonNumber), - bi(IN_ProcessEvents), - bi(IN_ClearStates), - bi(IN_GetAxisInfo), - bi(IN_GetButtonInfo), + bi(IN_FindDeviceId, 1, p(string)), + bi(IN_GetDeviceName, 1, p(int)), + bi(IN_GetDeviceId, 1, p(int)), + bi(IN_AxisInfo, 0), //FIXME + bi(IN_ButtonInfo, 0), //FIXME + bi(IN_GetAxisName, 2, p(int), p(int)), + bi(IN_GetButtonName, 2, p(int), p(int)), + bi(IN_GetAxisNumber, 2, p(int), p(string)), + bi(IN_GetButtonNumber, 2, p(int), p(string)), + bi(IN_ProcessEvents, 0), + bi(IN_ClearStates, 0), + bi(IN_GetAxisInfo, 3, p(int), p(int), p(ptr)), + bi(IN_GetButtonInfo, 3, p(int), p(int), p(ptr)), {"IN_ButtonAddListener|^{tag in_button_s=}^(v^v^{tag in_button_s=})^v", - rua_IN_ButtonAddListener_func, -1}, + rua_IN_ButtonAddListener_func, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_ButtonRemoveListener|^{tag in_button_s=}^(v^v^{tag in_button_s=})^v", - rua_IN_ButtonRemoveListener_func, -1}, + rua_IN_ButtonRemoveListener_func, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_AxisAddListener|^{tag in_axis_s=}^(v^v^{tag in_axis_s=})^v", - rua_IN_AxisAddListener_func, -1}, + rua_IN_AxisAddListener_func, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_AxisRemoveListener|^{tag in_axis_s=}^(v^v^{tag in_axis_s=})^v", - rua_IN_AxisRemoveListener_func, -1}, + rua_IN_AxisRemoveListener_func, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_ButtonAddListener|^{tag in_button_s=}(@@:.)@", - rua_IN_ButtonAddListener_method, -1}, + rua_IN_ButtonAddListener_method, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_ButtonRemoveListener|^{tag in_button_s=}(@@:.)@", - rua_IN_ButtonRemoveListener_method, -1}, + rua_IN_ButtonRemoveListener_method, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_AxisAddListener|^{tag in_axis_s=}(@@:.)@", - rua_IN_AxisAddListener_method, -1}, + rua_IN_AxisAddListener_method, -1, 3, {p(ptr), p(func), p(ptr)}}, {"IN_AxisRemoveListener|^{tag in_axis_s=}(@@:.)@", - rua_IN_AxisRemoveListener_method, -1}, + rua_IN_AxisRemoveListener_method, -1, 3, {p(ptr), p(func), p(ptr)}}, - bi(IMT_CreateContext), - bi(IMT_GetContext), - bi(IMT_SetContext), + bi(IMT_CreateContext, 1, p(string)), + bi(IMT_GetContext, 0), + bi(IMT_SetContext, 1, p(int)), {0} }; diff --git a/libs/ruamoko/rua_keys.c b/libs/ruamoko/rua_keys.c index 11747304e..2f09ae227 100644 --- a/libs/ruamoko/rua_keys.c +++ b/libs/ruamoko/rua_keys.c @@ -165,13 +165,16 @@ bi_Key_StringToKeynum (progs_t *pr) R_INT (pr) = Key_StringToKeynum (keyname); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"Key_keydown", bi_Key_keydown, -1}, - {"Key_SetBinding", bi_Key_SetBinding, -1}, - {"Key_LookupBinding", bi_Key_LookupBinding, -1}, - {"Key_CountBinding", bi_Key_CountBinding, -1}, - {"Key_KeynumToString", bi_Key_KeynumToString, -1}, - {"Key_StringToKeynum", bi_Key_StringToKeynum, -1}, + bi(Key_keydown, 1, p(int)), + bi(Key_SetBinding, 3, p(string), p(int), p(string)), + bi(Key_LookupBinding, 3, p(string), p(int), p(string)), + bi(Key_CountBinding, 2, p(string), p(string)), + bi(Key_KeynumToString, 1, p(int)), + bi(Key_StringToKeynum, 1, p(string)), {0} }; diff --git a/libs/ruamoko/rua_math.c b/libs/ruamoko/rua_math.c index f6926fa65..21d96fb6d 100644 --- a/libs/ruamoko/rua_math.c +++ b/libs/ruamoko/rua_math.c @@ -321,52 +321,54 @@ bi_atanh (progs_t *pr) R_DOUBLE (pr) = log ((1 + y) / (1 - y)) / 2; } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"sin|f", bi_sinf, -1}, - {"cos|f", bi_cosf, -1}, - {"tan|f", bi_tanf, -1}, - {"asin|f", bi_asinf, -1}, - {"acos|f", bi_acosf, -1}, - {"atan|f", bi_atanf, -1}, - {"atan2|ff",bi_atan2f, -1}, - {"exp|f", bi_expf, -1}, - {"log|f", bi_logf, -1}, - {"log2|f", bi_log2f, -1}, - {"log10|f", bi_log10f, -1}, - {"pow|ff", bi_powf, -1}, - {"sqrt|f", bi_sqrtf, -1}, - {"cbrt|f", bi_cbrtf, -1}, - {"hypot|ff",bi_hypotf, -1}, - {"sinh|f", bi_sinhf, -1}, - {"cosh|f", bi_coshf, -1}, - {"tanh|f", bi_tanhf, -1}, - {"asinh|f", bi_asinhf, -1}, - {"acosh|f", bi_acoshf, -1}, - {"atanh|f", bi_atanhf, -1}, - {"floor|d", bi_floor, -1}, // float version in pr_cmds - {"ceil|d", bi_ceil, -1}, // float version in pr_cmds - {"fabs|d", bi_fabs, -1}, // float version in pr_cmds - {"sin|d", bi_sin, -1}, - {"cos|d", bi_cos, -1}, - {"tan|d", bi_tan, -1}, - {"asin|d", bi_asin, -1}, - {"acos|d", bi_acos, -1}, - {"atan|d", bi_atan, -1}, - {"atan2|dd",bi_atan2, -1}, - {"exp|d", bi_exp, -1}, - {"log|d", bi_log, -1}, - {"log2|d", bi_log2, -1}, - {"log10|d", bi_log10, -1}, - {"pow|dd", bi_pow, -1}, - {"sqrt|d", bi_sqrt, -1}, - {"cbrt|d", bi_cbrt, -1}, - {"hypot|dd",bi_hypot, -1}, - {"sinh|d", bi_sinh, -1}, - {"cosh|d", bi_cosh, -1}, - {"tanh|d", bi_tanh, -1}, - {"asinh|d", bi_asinh, -1}, - {"acosh|d", bi_acosh, -1}, - {"atanh|d", bi_atanh, -1}, + {"sin|f", bi_sinf, -1, 1, {p(float)}}, + {"cos|f", bi_cosf, -1, 1, {p(float)}}, + {"tan|f", bi_tanf, -1, 1, {p(float)}}, + {"asin|f", bi_asinf, -1, 1, {p(float)}}, + {"acos|f", bi_acosf, -1, 1, {p(float)}}, + {"atan|f", bi_atanf, -1, 1, {p(float)}}, + {"atan2|ff",bi_atan2f, -1, 2, {p(float), p(float)}}, + {"exp|f", bi_expf, -1, 1, {p(float)}}, + {"log|f", bi_logf, -1, 1, {p(float)}}, + {"log2|f", bi_log2f, -1, 1, {p(float)}}, + {"log10|f", bi_log10f, -1, 1, {p(float)}}, + {"pow|ff", bi_powf, -1, 2, {p(float), p(float)}}, + {"sqrt|f", bi_sqrtf, -1, 1, {p(float)}}, + {"cbrt|f", bi_cbrtf, -1, 1, {p(float)}}, + {"hypot|ff",bi_hypotf, -1, 2, {p(float), p(float)}}, + {"sinh|f", bi_sinhf, -1, 1, {p(float)}}, + {"cosh|f", bi_coshf, -1, 1, {p(float)}}, + {"tanh|f", bi_tanhf, -1, 1, {p(float)}}, + {"asinh|f", bi_asinhf, -1, 1, {p(float)}}, + {"acosh|f", bi_acoshf, -1, 1, {p(float)}}, + {"atanh|f", bi_atanhf, -1, 1, {p(float)}}, + {"floor|d", bi_floor, -1, 1, {p(double)}}, // float version in pr_cmds + {"ceil|d", bi_ceil, -1, 1, {p(double)}}, // float version in pr_cmds + {"fabs|d", bi_fabs, -1, 1, {p(double)}}, // float version in pr_cmds + {"sin|d", bi_sin, -1, 1, {p(double)}}, + {"cos|d", bi_cos, -1, 1, {p(double)}}, + {"tan|d", bi_tan, -1, 1, {p(double)}}, + {"asin|d", bi_asin, -1, 1, {p(double)}}, + {"acos|d", bi_acos, -1, 1, {p(double)}}, + {"atan|d", bi_atan, -1, 1, {p(double)}}, + {"atan2|dd",bi_atan2, -1, 2, {p(double), p(double)}}, + {"exp|d", bi_exp, -1, 1, {p(double)}}, + {"log|d", bi_log, -1, 1, {p(double)}}, + {"log2|d", bi_log2, -1, 1, {p(double)}}, + {"log10|d", bi_log10, -1, 1, {p(double)}}, + {"pow|dd", bi_pow, -1, 2, {p(double), p(double)}}, + {"sqrt|d", bi_sqrt, -1, 1, {p(double)}}, + {"cbrt|d", bi_cbrt, -1, 1, {p(double)}}, + {"hypot|dd",bi_hypot, -1, 2, {p(double), p(double)}}, + {"sinh|d", bi_sinh, -1, 1, {p(double)}}, + {"cosh|d", bi_cosh, -1, 1, {p(double)}}, + {"tanh|d", bi_tanh, -1, 1, {p(double)}}, + {"asinh|d", bi_asinh, -1, 1, {p(double)}}, + {"acosh|d", bi_acosh, -1, 1, {p(double)}}, + {"atanh|d", bi_atanh, -1, 1, {p(double)}}, {0} }; diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c index 6c503914f..200b56785 100644 --- a/libs/ruamoko/rua_mersenne.c +++ b/libs/ruamoko/rua_mersenne.c @@ -145,14 +145,15 @@ bi_mtwist_clear (progs_t *pr, void *data) state_reset (res); } -#define bi(x) {#x, bi_##x, -1} +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - bi(mtwist_new), - bi(mtwist_delete), - bi(mtwist_seed), - bi(mtwist_rand), - bi(mtwist_rand_0_1), - bi(mtwist_rand_m1_1), + bi(mtwist_new, 1, p(int)), + bi(mtwist_delete, 1, p(ptr)), + bi(mtwist_seed, 2, p(ptr), p(int)), + bi(mtwist_rand, 1, p(ptr)), + bi(mtwist_rand_0_1, 1, p(ptr)), + bi(mtwist_rand_m1_1, 1, p(ptr)), {0} }; diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index e16525053..5d28bf53c 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -396,46 +396,49 @@ bi_MsgBuf_ReadUTF8 (progs_t *pr) R_INT (pr) = MSG_ReadUTF8 (&mb->msg); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"MsgBuf_New", bi_MsgBuf_New, -1}, - {"MsgBuf_Delete", bi_MsgBuf_Delete, -1}, - {"MsgBuf_FromFile", bi_MsgBuf_FromFile, -1}, - {"MsgBuf_MaxSize", bi_MsgBuf_MaxSize, -1}, - {"MsgBuf_CurSize", bi_MsgBuf_CurSize, -1}, - {"MsgBuf_ReadCount", bi_MsgBuf_ReadCount, -1}, - {"MsgBuf_DataPtr", bi_MsgBuf_DataPtr, -1}, + bi(MsgBuf_New, 1, p(int)), + bi(MsgBuf_Delete, 1, p(ptr)), + bi(MsgBuf_FromFile, 2, p(ptr), p(ptr)), + bi(MsgBuf_MaxSize, 1, p(ptr)), + bi(MsgBuf_CurSize, 1, p(ptr)), + bi(MsgBuf_ReadCount, 1, p(ptr)), + bi(MsgBuf_DataPtr, 1, p(ptr)), - {"MsgBuf_Clear", bi_MsgBuf_Clear, -1}, - {"MsgBuf_WriteByte", bi_MsgBuf_WriteByte, -1}, - {"MsgBuf_WriteShort", bi_MsgBuf_WriteShort, -1}, - {"MsgBuf_WriteLong", bi_MsgBuf_WriteLong, -1}, - {"MsgBuf_WriteFloat", bi_MsgBuf_WriteFloat, -1}, - {"MsgBuf_WriteString", bi_MsgBuf_WriteString, -1}, -// {"MsgBuf_WriteBytes", bi_MsgBuf_WriteBytes, -1}, - {"MsgBuf_WriteCoord", bi_MsgBuf_WriteCoord, -1}, - {"MsgBuf_WriteCoordV", bi_MsgBuf_WriteCoordV, -1}, - {"MsgBuf_WriteCoordAngleV", bi_MsgBuf_WriteCoordAngleV, -1}, - {"MsgBuf_WriteAngle", bi_MsgBuf_WriteAngle, -1}, - {"MsgBuf_WriteAngleV", bi_MsgBuf_WriteAngleV, -1}, - {"MsgBuf_WriteAngle16", bi_MsgBuf_WriteAngle16, -1}, - {"MsgBuf_WriteAngle16V", bi_MsgBuf_WriteAngle16V, -1}, - {"MsgBuf_WriteUTF8", bi_MsgBuf_WriteUTF8, -1}, + bi(MsgBuf_Clear, 1, p(ptr)), + bi(MsgBuf_WriteByte, 2, p(ptr), p(int)), + bi(MsgBuf_WriteShort, 2, p(ptr), p(int)), + bi(MsgBuf_WriteLong, 2, p(ptr), p(int)), + bi(MsgBuf_WriteFloat, 2, p(ptr), p(float)), + bi(MsgBuf_WriteString, 2, p(ptr), p(string)), +// bi(MsgBuf_WriteBytes, _, _), + bi(MsgBuf_WriteCoord, 2, p(ptr), p(float)), + bi(MsgBuf_WriteCoordV, 2, p(ptr), p(vector)), + bi(MsgBuf_WriteCoordAngleV, 2, p(ptr), p(vector)), + bi(MsgBuf_WriteAngle, 2, p(ptr), p(float)), + bi(MsgBuf_WriteAngleV, 2, p(ptr), p(vector)), + bi(MsgBuf_WriteAngle16, 2, p(ptr), p(float)), + bi(MsgBuf_WriteAngle16V, 2, p(ptr), p(vector)), + bi(MsgBuf_WriteUTF8, 2, p(ptr), p(int)), - {"MsgBuf_BeginReading", bi_MsgBuf_BeginReading, -1}, - {"MsgBuf_ReadByte", bi_MsgBuf_ReadByte, -1}, - {"MsgBuf_ReadShort", bi_MsgBuf_ReadShort, -1}, - {"MsgBuf_ReadLong", bi_MsgBuf_ReadLong, -1}, - {"MsgBuf_ReadFloat", bi_MsgBuf_ReadFloat, -1}, - {"MsgBuf_ReadString", bi_MsgBuf_ReadString, -1}, -// {"MsgBuf_ReadBytes", bi_MsgBuf_ReadBytes, -1}, - {"MsgBuf_ReadCoord", bi_MsgBuf_ReadCoord, -1}, - {"MsgBuf_ReadCoordV", bi_MsgBuf_ReadCoordV, -1}, - {"MsgBuf_ReadCoordAngleV", bi_MsgBuf_ReadCoordAngleV, -1}, - {"MsgBuf_ReadAngle", bi_MsgBuf_ReadAngle, -1}, - {"MsgBuf_ReadAngleV", bi_MsgBuf_ReadAngleV, -1}, - {"MsgBuf_ReadAngle16", bi_MsgBuf_ReadAngle16, -1}, - {"MsgBuf_ReadAngle16V", bi_MsgBuf_ReadAngle16V, -1}, - {"MsgBuf_ReadUTF8", bi_MsgBuf_ReadUTF8, -1}, + bi(MsgBuf_BeginReading, 1, p(ptr)), + bi(MsgBuf_ReadByte, 1, p(ptr)), + bi(MsgBuf_ReadShort, 1, p(ptr)), + bi(MsgBuf_ReadLong, 1, p(ptr)), + bi(MsgBuf_ReadFloat, 1, p(ptr)), + bi(MsgBuf_ReadString, 1, p(ptr)), +// bi(MsgBuf_ReadBytes, _, _), + bi(MsgBuf_ReadCoord, 1, p(ptr)), + bi(MsgBuf_ReadCoordV, 1, p(ptr)), + bi(MsgBuf_ReadCoordAngleV, 2, p(ptr), p(ptr)), + bi(MsgBuf_ReadAngle, 1, p(ptr)), + bi(MsgBuf_ReadAngleV, 1, p(ptr)), + bi(MsgBuf_ReadAngle16, 1, p(ptr)), + bi(MsgBuf_ReadAngle16V, 1, p(ptr)), + bi(MsgBuf_ReadUTF8, 1, p(ptr)), {0} }; diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 10a5e165d..819f9c3c8 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -2078,73 +2078,76 @@ rua_PR_FindGlobal (progs_t *pr) //==================================================================== +#define bi(x,np,params...) {#x, rua_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t obj_methods [] = { - {"__obj_exec_class", rua___obj_exec_class, -1}, - {"__obj_forward", rua___obj_forward, -1}, - {"__obj_responds_to", rua___obj_responds_to, -1}, + bi(__obj_exec_class, 1, p(ptr)), + bi(__obj_forward, -3, p(ptr), p(ptr)), + bi(__obj_responds_to, 2, p(ptr), p(ptr)), - {"obj_error", rua_obj_error, -1}, - {"obj_verror", rua_obj_verror, -1}, - {"obj_set_error_handler", rua_obj_set_error_handler, -1}, - {"obj_msg_lookup", rua_obj_msg_lookup, -1}, - {"obj_msg_lookup_super", rua_obj_msg_lookup_super, -1}, - {"obj_msg_sendv", rua_obj_msg_sendv, -1}, - {"obj_increment_retaincount", rua_obj_increment_retaincount, -1}, - {"obj_decrement_retaincount", rua_obj_decrement_retaincount, -1}, - {"obj_get_retaincount", rua_obj_get_retaincount, -1}, - {"obj_malloc", rua_obj_malloc, -1}, - {"obj_atomic_malloc", rua_obj_atomic_malloc, -1}, - {"obj_valloc", rua_obj_valloc, -1}, - {"obj_realloc", rua_obj_realloc, -1}, - {"obj_calloc", rua_obj_calloc, -1}, - {"obj_free", rua_obj_free, -1}, - {"obj_get_uninstalled_dtable", rua_obj_get_uninstalled_dtable, -1}, - {"obj_msgSend", rua_obj_msgSend, -1}, - {"obj_msgSend_super", rua_obj_msgSend_super, -1}, + bi(obj_error, -4, p(ptr), p(int), p(string)), + bi(obj_verror, 4, p(ptr), p(int), p(string), P(1, 2)), + bi(obj_set_error_handler, 1, p(func)), + bi(obj_msg_lookup, 2, p(ptr), p(ptr)), + bi(obj_msg_lookup_super, 2, p(ptr), p(ptr)), + bi(obj_msg_sendv, 3, p(ptr), p(ptr), P(1, 2)), + bi(obj_increment_retaincount, 1, p(ptr)), + bi(obj_decrement_retaincount, 1, p(ptr)), + bi(obj_get_retaincount, 1, p(ptr)), + bi(obj_malloc, 1, p(int)), + bi(obj_atomic_malloc, 1, p(int)), + bi(obj_valloc, 1, p(int)), + bi(obj_realloc, 2, p(ptr), p(int)), + bi(obj_calloc, 2, p(int), p(int)), + bi(obj_free, 1, p(ptr)), + bi(obj_get_uninstalled_dtable, 0), + bi(obj_msgSend, 2, p(ptr), p(ptr)),//magic + bi(obj_msgSend_super, 2, p(ptr), p(ptr)),//magic - {"obj_get_class", rua_obj_get_class, -1}, - {"obj_lookup_class", rua_obj_lookup_class, -1}, - {"obj_next_class", rua_obj_next_class, -1}, + bi(obj_get_class, 1, p(string)), + bi(obj_lookup_class, 1, p(string)), + bi(obj_next_class, 1, p(ptr)), - {"sel_get_name", rua_sel_get_name, -1}, - {"sel_get_type", rua_sel_get_type, -1}, - {"sel_get_uid", rua_sel_get_uid, -1}, - {"sel_register_name", rua_sel_register_name, -1}, - {"sel_is_mapped", rua_sel_is_mapped, -1}, + bi(sel_get_name, 1, p(ptr)), + bi(sel_get_type, 1, p(ptr)), + bi(sel_get_uid, 1, p(string)), + bi(sel_register_name, 1, p(string)), + bi(sel_is_mapped, 1, p(ptr)), - {"class_get_class_method", rua_class_get_class_method, -1}, - {"class_get_instance_method", rua_class_get_instance_method, -1}, - {"class_pose_as", rua_class_pose_as, -1}, - {"class_create_instance", rua_class_create_instance, -1}, - {"class_get_class_name", rua_class_get_class_name, -1}, - {"class_get_instance_size", rua_class_get_instance_size, -1}, - {"class_get_meta_class", rua_class_get_meta_class, -1}, - {"class_get_super_class", rua_class_get_super_class, -1}, - {"class_get_version", rua_class_get_version, -1}, - {"class_is_class", rua_class_is_class, -1}, - {"class_is_meta_class", rua_class_is_meta_class, -1}, - {"class_set_version", rua_class_set_version, -1}, - {"class_get_gc_object_type", rua_class_get_gc_object_type, -1}, - {"class_ivar_set_gcinvisible", rua_class_ivar_set_gcinvisible, -1}, + bi(class_get_class_method, 2, p(ptr), p(ptr)), + bi(class_get_instance_method, 2, p(ptr), p(ptr)), + bi(class_pose_as, 2, p(ptr), p(ptr)), + bi(class_create_instance, 1, p(ptr)), + bi(class_get_class_name, 1, p(ptr)), + bi(class_get_instance_size, 1, p(ptr)), + bi(class_get_meta_class, 1, p(ptr)), + bi(class_get_super_class, 1, p(ptr)), + bi(class_get_version, 1, p(ptr)), + bi(class_is_class, 1, p(ptr)), + bi(class_is_meta_class, 1, p(ptr)), + bi(class_set_version, 2, p(ptr), p(int)), + bi(class_get_gc_object_type, 1, p(ptr)), + bi(class_ivar_set_gcinvisible, 3, p(ptr), p(string), p(int)), - {"method_get_imp", rua_method_get_imp, -1}, - {"get_imp", rua_get_imp, -1}, + bi(method_get_imp, 1, p(ptr)), + bi(get_imp, 1, p(ptr), p(ptr)), - {"object_copy", rua_object_copy, -1}, - {"object_dispose", rua_object_dispose, -1}, - {"object_get_class", rua_object_get_class, -1}, - {"object_get_class_name", rua_object_get_class_name, -1}, - {"object_get_meta_class", rua_object_get_meta_class, -1}, - {"object_get_super_class", rua_object_get_super_class, -1}, - {"object_is_class", rua_object_is_class, -1}, - {"object_is_instance", rua_object_is_instance, -1}, - {"object_is_meta_class", rua_object_is_meta_class, -1}, + bi(object_copy, 1, p(ptr)), + bi(object_dispose, 1, p(ptr)), + bi(object_get_class, 1, p(ptr)), + bi(object_get_class_name, 1, p(ptr)), + bi(object_get_meta_class, 1, p(ptr)), + bi(object_get_super_class, 1, p(ptr)), + bi(object_is_class, 1, p(ptr)), + bi(object_is_instance, 1, p(ptr)), + bi(object_is_meta_class, 1, p(ptr)), - {"_i_Object__hash", rua__i_Object__hash, -1}, - {"_i_Object_error_error_", rua__i_Object_error_error_, -1}, - {"_c_Object__conformsToProtocol_", rua__c_Object__conformsToProtocol_, -1}, + bi(_i_Object__hash, 2, p(ptr), p(ptr)), + bi(_i_Object_error_error_, -4, p(ptr), p(ptr), p(string)), + bi(_c_Object__conformsToProtocol_, 3, p(ptr), p(ptr), p(ptr)), - {"PR_FindGlobal", rua_PR_FindGlobal, -1},//FIXME + bi(PR_FindGlobal, 1, p(string)),//FIXME {0} }; diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 2899eec5f..1f27c6b74 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -444,28 +444,30 @@ plist_compare (const void *k1, const void *k2, void *unused) return pl1->plitem == pl2->plitem; } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"PL_GetFromFile", bi_PL_GetFromFile, -1}, - {"PL_GetPropertyList", bi_PL_GetPropertyList, -1}, - {"PL_WritePropertyList", bi_PL_WritePropertyList, -1}, - {"PL_Type", bi_PL_Type, -1}, - {"PL_Line", bi_PL_Line, -1}, - {"PL_String", bi_PL_String, -1}, - {"PL_ObjectForKey", bi_PL_ObjectForKey, -1}, - {"PL_RemoveObjectForKey", bi_PL_RemoveObjectForKey, -1}, - {"PL_ObjectAtIndex", bi_PL_ObjectAtIndex, -1}, - {"PL_D_AllKeys", bi_PL_D_AllKeys, -1}, - {"PL_D_NumKeys", bi_PL_D_NumKeys, -1}, - {"PL_D_AddObject", bi_PL_D_AddObject, -1}, - {"PL_A_AddObject", bi_PL_A_AddObject, -1}, - {"PL_A_NumObjects", bi_PL_A_NumObjects, -1}, - {"PL_A_InsertObjectAtIndex", bi_PL_A_InsertObjectAtIndex, -1}, - {"PL_RemoveObjectAtIndex", bi_PL_RemoveObjectAtIndex, -1}, - {"PL_NewDictionary", bi_PL_NewDictionary, -1}, - {"PL_NewArray", bi_PL_NewArray, -1}, - {"PL_NewData", bi_PL_NewData, -1}, - {"PL_NewString", bi_PL_NewString, -1}, - {"PL_Free", bi_PL_Free, -1}, + bi(PL_GetFromFile, 1, p(ptr)), + bi(PL_GetPropertyList, 1, p(string)), + bi(PL_WritePropertyList, 1, p(ptr)), + bi(PL_Type, 1, p(ptr)), + bi(PL_Line, 1, p(ptr)), + bi(PL_String, 1, p(ptr)), + bi(PL_ObjectForKey, 2, p(ptr), p(string)), + bi(PL_RemoveObjectForKey, 2, p(ptr), p(string)), + bi(PL_ObjectAtIndex, 2, p(ptr), p(int)), + bi(PL_D_AllKeys, 1, p(ptr)), + bi(PL_D_NumKeys, 1, p(ptr)), + bi(PL_D_AddObject, 3, p(ptr), p(string), p(ptr)), + bi(PL_A_AddObject, 2, p(ptr), p(ptr)), + bi(PL_A_NumObjects, 1, p(ptr)), + bi(PL_A_InsertObjectAtIndex, 3, p(ptr), p(ptr), p(int)), + bi(PL_RemoveObjectAtIndex, 2, p(ptr), p(int)), + bi(PL_NewDictionary, 0), + bi(PL_NewArray, 0), + bi(PL_NewData, 2, p(ptr), p(int)), + bi(PL_NewString, 1, p(string)), + bi(PL_Free, 1, p(ptr)), {0} }; diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index 55e36acd1..afe23a4e7 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -346,35 +346,40 @@ bi_Qfilesize (progs_t *pr) R_INT (pr) = Qfilesize (h->file); } +#define bi(x,np,params...) {#x, secured, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t secure_builtins[] = { - {"Qrename", secured, -1}, - {"Qremove", secured, -1}, - {"Qopen", secured, -1}, + bi(Qrename, 2, p(string), p(string)), + bi(Qremove, 1, p(string)), + bi(Qopen, 2, p(string), p(string)), {0} }; +#undef bi +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} static builtin_t insecure_builtins[] = { - {"Qrename", bi_Qrename, -1}, - {"Qremove", bi_Qremove, -1}, - {"Qopen", bi_Qopen, -1}, + bi(Qrename, 2, p(string), p(string)), + bi(Qremove, 1, p(string)), + bi(Qopen, 2, p(string), p(string)), {0} }; static builtin_t builtins[] = { - {"Qclose", bi_Qclose, -1}, - {"Qgetline", bi_Qgetline, -1}, - {"Qreadstring", bi_Qreadstring, -1}, - {"Qread", bi_Qread, -1}, - {"Qwrite", bi_Qwrite, -1}, - {"Qputs", bi_Qputs, -1}, -// {"Qgets", bi_Qgets, -1}, - {"Qgetc", bi_Qgetc, -1}, - {"Qputc", bi_Qputc, -1}, - {"Qseek", bi_Qseek, -1}, - {"Qtell", bi_Qtell, -1}, - {"Qflush", bi_Qflush, -1}, - {"Qeof", bi_Qeof, -1}, - {"Qfilesize", bi_Qfilesize, -1}, + bi(Qclose, 1, p(ptr)), + bi(Qgetline, 1, p(ptr)), + bi(Qreadstring, 2, p(ptr), p(int)), + bi(Qread, 3, p(ptr), p(ptr), p(int)), + bi(Qwrite, 3, p(ptr), p(ptr), p(int)), + bi(Qputs, 2, p(ptr), p(string)), +// bi(Qgets, _, _), + bi(Qgetc, 1, p(ptr)), + bi(Qputc, 2, p(ptr), p(int)), + bi(Qseek, 3, p(ptr), p(int), p(int)), + bi(Qtell, 1, p(ptr)), + bi(Qflush, 1, p(ptr)), + bi(Qeof, 1, p(ptr)), + bi(Qfilesize, 1, p(ptr)), {0} }; diff --git a/libs/ruamoko/rua_qfs.c b/libs/ruamoko/rua_qfs.c index c29dc3ec8..9c34d6abe 100644 --- a/libs/ruamoko/rua_qfs.c +++ b/libs/ruamoko/rua_qfs.c @@ -188,16 +188,18 @@ bi_QFS_GetDirectory (progs_t *pr) RETURN_STRING (pr, qfs_gamedir->dir.def); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"QFS_Open", bi_QFS_Open, -1}, - {"QFS_WOpen", bi_QFS_WOpen, -1}, - {"QFS_Rename", bi_QFS_Rename, -1}, - {"QFS_LoadFile", bi_QFS_LoadFile, -1}, - {"QFS_OpenFile", bi_QFS_OpenFile, -1}, - {"QFS_WriteFile", bi_QFS_WriteFile, -1}, - {"QFS_Filelist", bi_QFS_Filelist, -1}, - {"QFS_FilelistFree", bi_QFS_FilelistFree, -1}, - {"QFS_GetDirectory", bi_QFS_GetDirectory, -1}, + bi(QFS_Open, 2, p(string), p(string)), + bi(QFS_WOpen, 2, p(string), p(int)), + bi(QFS_Rename, 2, p(string), p(string)), + bi(QFS_LoadFile, 1, p(string)), + bi(QFS_OpenFile, 1, p(string)), + bi(QFS_WriteFile, 3, p(string), p(ptr), p(int)), + bi(QFS_Filelist, 3, p(string), p(string), p(int)), + bi(QFS_FilelistFree, 1, p(ptr)), + bi(QFS_GetDirectory, 0), {0} }; diff --git a/libs/ruamoko/rua_runtime.c b/libs/ruamoko/rua_runtime.c index 3fe21db51..54b67b205 100644 --- a/libs/ruamoko/rua_runtime.c +++ b/libs/ruamoko/rua_runtime.c @@ -69,8 +69,11 @@ bi_va_copy (progs_t *pr) R_PACKED (pr, pr_va_list_t).list = PR_SetPointer (pr, dst_list); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"va_copy", bi_va_copy, -1}, + bi(va_copy, 1, P(1, 2)), {0} }; diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index cfb9a7e9a..4a90a99e3 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -187,15 +187,17 @@ bi_Script_NoQuoteLines (progs_t *pr) script->script.no_quote_lines = P_INT (pr, 1); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"Script_New", bi_Script_New, -1}, - {"Script_Delete", bi_Script_Delete, -1}, - {"Script_Start", bi_Script_Start, -1}, - {"Script_TokenAvailable", bi_Script_TokenAvailable, -1}, - {"Script_GetToken", bi_Script_GetToken, -1}, - {"Script_UngetToken", bi_Script_UngetToken, -1}, - {"Script_Error", bi_Script_Error, -1}, - {"Script_NoQuoteLines", bi_Script_NoQuoteLines, -1}, + bi(Script_New, 0), + bi(Script_Delete, 1, p(ptr)), + bi(Script_Start, 3, p(ptr), p(string), p(string)), + bi(Script_TokenAvailable, 2, p(ptr), p(int)), + bi(Script_GetToken, 2, p(ptr), p(int)), + bi(Script_UngetToken, 1, p(ptr)), + bi(Script_Error, 1, p(ptr)), + bi(Script_NoQuoteLines, 1, p(ptr)), {0} }; diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 632a6a10a..647f7716b 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -178,6 +178,15 @@ bi_set_del_iter (progs_t *pr) del_set_iter (pr, set_iter); } +static void +bi_set_iter_element (progs_t *pr) +{ + bi_set_iter_t *set_iter = get_set_iter (pr, __FUNCTION__, P_INT (pr, 0)); + + R_INT (pr) = set_iter->iter->element; + +} + static void bi_set_new (progs_t *pr) { @@ -421,7 +430,7 @@ bi_set_as_string (progs_t *pr) } static void -bi_i_SetIterator__element (progs_t *pr) +bi__i_SetIterator__element (progs_t *pr) { pr_set_iter_t *iter_obj = &P_STRUCT (pr, pr_set_iter_t, 0); bi_set_iter_t *set_iter = get_set_iter (pr, __FUNCTION__, iter_obj->iter); @@ -430,7 +439,7 @@ bi_i_SetIterator__element (progs_t *pr) } static void -bi_i_Set__add_ (progs_t *pr) +bi__i_Set__add_ (progs_t *pr) { pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); @@ -443,7 +452,7 @@ bi_i_Set__add_ (progs_t *pr) } static void -bi_i_Set__remove_ (progs_t *pr) +bi__i_Set__remove_ (progs_t *pr) { pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); @@ -456,7 +465,7 @@ bi_i_Set__remove_ (progs_t *pr) } static void -bi_i_Set__invert (progs_t *pr) +bi__i_Set__invert (progs_t *pr) { pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); @@ -468,7 +477,7 @@ bi_i_Set__invert (progs_t *pr) } static void -bi_i_Set__union_ (progs_t *pr) +bi__i_Set__union_ (progs_t *pr) { pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); @@ -482,7 +491,7 @@ bi_i_Set__union_ (progs_t *pr) } static void -bi_i_Set__intersection_ (progs_t *pr) +bi__i_Set__intersection_ (progs_t *pr) { pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); @@ -496,7 +505,7 @@ bi_i_Set__intersection_ (progs_t *pr) } static void -bi_i_Set__difference_ (progs_t *pr) +bi__i_Set__difference_ (progs_t *pr) { pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); @@ -510,7 +519,7 @@ bi_i_Set__difference_ (progs_t *pr) } static void -bi_i_Set__reverse_difference_ (progs_t *pr) +bi__i_Set__reverse_difference_ (progs_t *pr) { pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); @@ -524,7 +533,7 @@ bi_i_Set__reverse_difference_ (progs_t *pr) } static void -bi_i_Set__assign_ (progs_t *pr) +bi__i_Set__assign_ (progs_t *pr) { pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); @@ -538,7 +547,7 @@ bi_i_Set__assign_ (progs_t *pr) } static void -bi_i_Set__empty (progs_t *pr) +bi__i_Set__empty (progs_t *pr) { pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); @@ -550,7 +559,7 @@ bi_i_Set__empty (progs_t *pr) } static void -bi_i_Set__everything (progs_t *pr) +bi__i_Set__everything (progs_t *pr) { pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); @@ -562,7 +571,7 @@ bi_i_Set__everything (progs_t *pr) } static void -bi_i_Set__is_empty (progs_t *pr) +bi__i_Set__is_empty (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); @@ -572,7 +581,7 @@ bi_i_Set__is_empty (progs_t *pr) } static void -bi_i_Set__is_everything (progs_t *pr) +bi__i_Set__is_everything (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); @@ -582,7 +591,7 @@ bi_i_Set__is_everything (progs_t *pr) } static void -bi_i_Set__is_disjoint_ (progs_t *pr) +bi__i_Set__is_disjoint_ (progs_t *pr) { pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); @@ -594,7 +603,7 @@ bi_i_Set__is_disjoint_ (progs_t *pr) } static void -bi_i_Set__is_intersecting_ (progs_t *pr) +bi__i_Set__is_intersecting_ (progs_t *pr) { pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); @@ -606,7 +615,7 @@ bi_i_Set__is_intersecting_ (progs_t *pr) } static void -bi_i_Set__is_equivalent_ (progs_t *pr) +bi__i_Set__is_equivalent_ (progs_t *pr) { pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); @@ -618,7 +627,7 @@ bi_i_Set__is_equivalent_ (progs_t *pr) } static void -bi_i_Set__is_subset_ (progs_t *pr) +bi__i_Set__is_subset_ (progs_t *pr) { pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); @@ -630,7 +639,7 @@ bi_i_Set__is_subset_ (progs_t *pr) } static void -bi_i_Set__is_member_ (progs_t *pr) +bi__i_Set__is_member_ (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); @@ -641,7 +650,7 @@ bi_i_Set__is_member_ (progs_t *pr) } static void -bi_i_Set__size (progs_t *pr) +bi__i_Set__size (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); @@ -651,7 +660,7 @@ bi_i_Set__size (progs_t *pr) } static void -bi_i_Set__as_string (progs_t *pr) +bi__i_Set__as_string (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); @@ -677,53 +686,56 @@ res_set_clear (progs_t *pr, void *data) res_set_iter_reset (res); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"set_del_iter", bi_set_del_iter, -1}, - {"set_new", bi_set_new, -1}, - {"set_delete", bi_set_delete, -1}, - {"set_add", bi_set_add, -1}, - {"set_remove", bi_set_remove, -1}, - {"set_invert", bi_set_invert, -1}, - {"set_union", bi_set_union, -1}, - {"set_intersection", bi_set_intersection, -1}, - {"set_difference", bi_set_difference, -1}, - {"set_reverse_difference", bi_set_reverse_difference, -1}, - {"set_assign", bi_set_assign, -1}, - {"set_empty", bi_set_empty, -1}, - {"set_everything", bi_set_everything, -1}, - {"set_is_empty", bi_set_is_empty, -1}, - {"set_is_everything", bi_set_is_everything, -1}, - {"set_is_disjoint", bi_set_is_disjoint, -1}, - {"set_is_intersecting", bi_set_is_intersecting, -1}, - {"set_is_equivalent", bi_set_is_equivalent, -1}, - {"set_is_subset", bi_set_is_subset, -1}, - {"set_is_member", bi_set_is_member, -1}, - {"set_count", bi_set_count, -1}, - {"set_first", bi_set_first, -1}, - {"set_next", bi_set_next, -1}, - {"set_as_string", bi_set_as_string, -1}, + bi(set_del_iter, 1, p(ptr)), + bi(set_iter_element, 1, p(ptr)), + bi(set_new, 0), + bi(set_delete, 1, p(ptr)), + bi(set_add, 2, p(ptr), p(uint)), + bi(set_remove, 2, p(ptr), p(uint)), + bi(set_invert, 1, p(ptr)), + bi(set_union, 2, p(ptr), p(ptr)), + bi(set_intersection, 2, p(ptr), p(ptr)), + bi(set_difference, 2, p(ptr), p(ptr)), + bi(set_reverse_difference, 2, p(ptr), p(ptr)), + bi(set_assign, 2, p(ptr), p(ptr)), + bi(set_empty, 1, p(ptr)), + bi(set_everything, 1, p(ptr)), + bi(set_is_empty, 1, p(ptr)), + bi(set_is_everything, 1, p(ptr)), + bi(set_is_disjoint, 2, p(ptr), p(ptr)), + bi(set_is_intersecting, 2, p(ptr), p(ptr)), + bi(set_is_equivalent, 2, p(ptr), p(ptr)), + bi(set_is_subset, 2, p(ptr), p(ptr)), + bi(set_is_member, 2, p(ptr), p(uint)), + bi(set_count, 1, p(ptr)), + bi(set_first, 1, p(ptr)), + bi(set_next, 1, p(ptr)), + bi(set_as_string, 1, p(ptr)), - {"_i_SetIterator__element", bi_i_SetIterator__element, -1}, + bi(_i_SetIterator__element, 2, p(ptr), p(ptr)), - {"_i_Set__add_", bi_i_Set__add_, -1}, - {"_i_Set__remove_", bi_i_Set__remove_, -1}, - {"_i_Set__invert", bi_i_Set__invert, -1}, - {"_i_Set__union_", bi_i_Set__union_, -1}, - {"_i_Set__intersection_", bi_i_Set__intersection_, -1}, - {"_i_Set__difference_", bi_i_Set__difference_, -1}, - {"_i_Set__reverse_difference_", bi_i_Set__reverse_difference_, -1}, - {"_i_Set__assign_", bi_i_Set__assign_, -1}, - {"_i_Set__empty", bi_i_Set__empty, -1}, - {"_i_Set__everything", bi_i_Set__everything, -1}, - {"_i_Set__is_empty", bi_i_Set__is_empty, -1}, - {"_i_Set__is_everything", bi_i_Set__is_everything, -1}, - {"_i_Set__is_disjoint_", bi_i_Set__is_disjoint_, -1}, - {"_i_Set__is_intersecting_", bi_i_Set__is_intersecting_, -1}, - {"_i_Set__is_equivalent_", bi_i_Set__is_equivalent_, -1}, - {"_i_Set__is_subset_", bi_i_Set__is_subset_, -1}, - {"_i_Set__is_member_", bi_i_Set__is_member_, -1}, - {"_i_Set__size", bi_i_Set__size, -1}, - {"_i_Set__as_string", bi_i_Set__as_string, -1}, + bi(_i_Set__add_, 3, p(ptr), p(ptr), p(uint)), + bi(_i_Set__remove_, 3, p(ptr), p(ptr), p(uint)), + bi(_i_Set__invert, 2, p(ptr), p(ptr)), + bi(_i_Set__union_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__intersection_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__difference_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__reverse_difference_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__assign_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__empty, 2, p(ptr), p(ptr)), + bi(_i_Set__everything, 2, p(ptr), p(ptr)), + bi(_i_Set__is_empty, 2, p(ptr), p(ptr)), + bi(_i_Set__is_everything, 2, p(ptr), p(ptr)), + bi(_i_Set__is_disjoint_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__is_intersecting_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__is_equivalent_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__is_subset_, 3, p(ptr), p(ptr), p(ptr)), + bi(_i_Set__is_member_, 3, p(ptr), p(ptr), p(uint)), + bi(_i_Set__size, 2, p(ptr), p(ptr)), + bi(_i_Set__as_string, 2, p(ptr), p(ptr)), {0} }; diff --git a/libs/ruamoko/rua_stdlib.c b/libs/ruamoko/rua_stdlib.c index 2ef4d914a..19dd7bc7e 100644 --- a/libs/ruamoko/rua_stdlib.c +++ b/libs/ruamoko/rua_stdlib.c @@ -156,12 +156,15 @@ bi_prefixsumf (progs_t *pr) } } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"bsearch", bi_bsearch, -1}, - {"fbsearch", bi_fbsearch, -1}, - {"qsort", bi_qsort, -1}, - {"prefixsum|^ii", bi_prefixsumi, -1}, - {"prefixsum|^fi", bi_prefixsumf, -1}, + bi(bsearch, 4, p(ptr), p(ptr), p(int), p(int), p(func)), + bi(fbsearch, 4, p(ptr), p(ptr), p(int), p(int), p(func)), + bi(qsort, 3, p(ptr), p(int), p(int), p(func)), + {"prefixsum|^ii", bi_prefixsumi, -1, 2, {p(ptr), p(int)}}, + {"prefixsum|^fi", bi_prefixsumf, -1, 2, {p(ptr), p(int)}}, {0} }; diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index c808ae963..21006ac42 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -281,25 +281,28 @@ bi_str_upper (progs_t *pr) RETURN_STRING (pr, upper); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"strlen", bi_strlen, -1}, - {"sprintf", bi_sprintf, -1}, - {"vsprintf", bi_vsprintf, -1}, - {"str_new", bi_str_new, -1}, - {"str_free", bi_str_free, -1}, - {"str_hold", bi_str_hold, -1}, - {"str_valid", bi_str_valid, -1}, - {"str_mutable", bi_str_mutable, -1}, - {"str_copy", bi_str_copy, -1}, - {"str_cat", bi_str_cat, -1}, - {"str_clear", bi_str_clear, -1}, - {"str_mid|*i", bi_str_mid, -1}, - {"str_mid|*ii", bi_str_mid, -1}, - {"str_str", bi_str_str, -1}, - {"str_char", bi_str_char, -1}, - {"str_quote", bi_str_quote, -1}, - {"str_lower", bi_str_lower, -1}, - {"str_upper", bi_str_upper, -1}, + bi(strlen, 1, p(string)), + bi(sprintf, -2, p(string)), + bi(vsprintf, 2, p(string), P(1, 2)), + bi(str_new, 0), + bi(str_free, 1, p(string)), + bi(str_hold, 1, p(string)), + bi(str_valid, 1, p(string)), + bi(str_mutable, 1, p(string)), + bi(str_copy, 2, p(string), p(string)), + bi(str_cat, 2, p(string), p(string)), + bi(str_clear, 1, p(string)), + {"str_mid|*i", bi_str_mid, -1, 2, {p(string), p(int)}}, + {"str_mid|*ii", bi_str_mid, -1, 3, {p(string), p(int), p(int)}}, + bi(str_str, 2, p(string), p(string)), + bi(str_char, 2, p(string), p(int)), + bi(str_quote, 1, p(string)), + bi(str_lower, 1, p(string)), + bi(str_upper, 1, p(string)), {0} }; diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index c09569c56..2fbaa6e28 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -324,20 +324,24 @@ bi_draw_clear (progs_t *pr, void *data) Hash_FlushTable (res->pic_hash); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"Draw_FreePic", bi_Draw_FreePic, -1}, - {"Draw_MakePic", bi_Draw_MakePic, -1}, - {"Draw_CachePic", bi_Draw_CachePic, -1}, - {"Draw_Pic", bi_Draw_Pic, -1}, - {"Draw_Picf", bi_Draw_Picf, -1}, - {"Draw_SubPic", bi_Draw_SubPic, -1}, - {"Draw_CenterPic", bi_Draw_CenterPic, -1}, - {"Draw_Character", bi_Draw_Character, -1}, - {"Draw_String", bi_Draw_String, -1}, - {"Draw_nString", bi_Draw_nString, -1}, - {"Draw_AltString", bi_Draw_AltString, -1}, - {"Draw_Fill", bi_Draw_Fill, -1}, - {"Draw_Crosshair", bi_Draw_Crosshair, -1}, + bi(Draw_FreePic, 1, p(ptr)), + bi(Draw_MakePic, 3, p(int), p(int), p(string)), + bi(Draw_CachePic, 2, p(string), p(int)), + bi(Draw_Pic, 3, p(int), p(int), p(ptr)), + bi(Draw_Picf, 3, p(float), p(float), p(ptr)), + bi(Draw_SubPic, 7, p(int), p(int), p(ptr), + p(int), p(int), p(int), p(int)), + bi(Draw_CenterPic, 3, p(int), p(int), p(ptr)), + bi(Draw_Character, 3, p(int), p(int), p(int)), + bi(Draw_String, 3, p(int), p(int), p(string)), + bi(Draw_nString, 4, p(int), p(int), p(string), p(int)), + bi(Draw_AltString, 3, p(int), p(int), p(string)), + bi(Draw_Fill, 5, p(int), p(int), p(int), p(int), p(int)), + bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)), {0} }; diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 71a6d03f3..5c98aa5d9 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -731,7 +731,7 @@ PF_findradius (progs_t *pr) // entity () spawn static void -PF_Spawn (progs_t *pr) +PF_spawn (progs_t *pr) { edict_t *ed; @@ -741,7 +741,7 @@ PF_Spawn (progs_t *pr) // void (entity e) remove static void -PF_Remove (progs_t *pr) +PF_remove (progs_t *pr) { edict_t *ed; @@ -798,6 +798,7 @@ PF_precache_file (progs_t *pr) // precache_file is used only to copy files with qcc, it does nothing R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_file2 PF_precache_file // void (string s) precache_sound // string (string s) precache_sound2 @@ -808,6 +809,7 @@ PF_precache_sound (progs_t *pr) "precache_sound"); R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_sound2 PF_precache_sound // void (string s) precache_model // string (string s) precache_model2 @@ -821,6 +823,7 @@ PF_precache_model (progs_t *pr) sv.models[ind] = Mod_ForName (mod, true); R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_model2 PF_precache_model /* PF_walkmove @@ -1474,78 +1477,83 @@ PF_checkextension (progs_t *pr) #define QF (PR_RANGE_QF << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"makevectors", PF_makevectors, 1}, - {"setorigin", PF_setorigin, 2}, - {"setmodel", PF_setmodel, 3}, - {"setsize", PF_setsize, 4}, + bi(makevectors, 1, 1, p(vector)), + bi(setorigin, 2, 2, p(entity), p(vector)), + bi(setmodel, 3, 2, p(entity), p(string)), + bi(setsize, 4, 3, p(entity), p(vector), p(vector)), - {"sound", PF_sound, 8}, + bi(sound, 8, 3, p(entity), p(float), p(string)), - {"error", PF_error, 10}, - {"objerror", PF_objerror, 11}, - {"spawn", PF_Spawn, 14}, - {"remove", PF_Remove, 15}, - {"traceline", PF_traceline, 16}, - {"checkclient", PF_checkclient, 17}, + bi(error, 10, -1), // (...) + bi(objerror, 11, -1), // (...) + bi(spawn, 14, 0), // (void) + bi(remove, 15, 1, p(entity)), + bi(traceline, 16, 3, p(vector), p(vector), p(float)), + bi(checkclient, 17, 0), // (void) - {"precache_sound", PF_precache_sound, 19}, - {"precache_model", PF_precache_model, 20}, - {"stuffcmd", PF_stuffcmd, 21}, - {"findradius", PF_findradius, 22}, - {"bprint", PF_bprint, 23}, - {"sprint", PF_sprint, 24}, + bi(precache_sound, 19, 1, p(string)), + bi(precache_model, 20, 1, p(string)), + bi(stuffcmd, 21, 2, p(entity), p(string)), + bi(findradius, 22, 2, p(vector), p(float)), + bi(bprint, 23, -1), // (...) + bi(sprint, 24, -2, p(entity)), // (entity, string...) - {"walkmove", PF_walkmove, 32}, + bi(walkmove, 32, 2, p(float), p(float)), - {"droptofloor", PF_droptofloor, 34}, - {"lightstyle", PF_lightstyle, 35}, + bi(droptofloor, 34, 0), // (void) + bi(lightstyle, 35, 2, p(float), p(string)), - {"checkbottom", PF_checkbottom, 40}, - {"pointcontents", PF_pointcontents, 41}, + bi(checkbottom, 40, 1, p(entity)), + bi(pointcontents, 41, 1, p(vector)), - {"aim", PF_aim, 44}, + bi(aim, 44, 2, p(entity), p(float)), - {"localcmd", PF_localcmd, 46}, + bi(localcmd, 46, 1, p(string)), - {"particle", PF_particle, 48}, - {"changeyaw", PF_changeyaw, 49}, + bi(particle, 48, 4, p(vector), p(vector), p(float), p(float)), + bi(changeyaw, 49, 0), // (void) - {"writebyte", PF_WriteByte, 52}, - {"WriteBytes", PF_WriteBytes, -1}, - {"writechar", PF_WriteChar, 53}, - {"writeshort", PF_WriteShort, 54}, - {"writelong", PF_WriteLong, 55}, - {"writecoord", PF_WriteCoord, 56}, - {"writeangle", PF_WriteAngle, 57}, - {"WriteCoordV", PF_WriteCoordV, -1}, - {"WriteAngleV", PF_WriteAngleV, -1}, - {"writestring", PF_WriteString, 58}, - {"writeentity", PF_WriteEntity, 59}, + bi(WriteByte, 52, 2, p(float), p(float)), + bi(WriteBytes, -1, -2, p(float)), // (float, float...) + bi(WriteChar, 53, 2, p(float), p(float)), + bi(WriteShort, 54, 2, p(float), p(float)), + bi(WriteLong, 55, 2, p(float), p(float)), + bi(WriteCoord, 56, 2, p(float), p(float)), + bi(WriteAngle, 57, 2, p(float), p(float)), + bi(WriteCoordV, -1, 2, p(float), p(vector)), + bi(WriteAngleV, -1, 2, p(float), p(vector)), + bi(WriteString, 58, 2, p(float), p(string)), + bi(WriteEntity, 59, 2, p(float), p(entity)), +#define PF_movetogoal SV_MoveToGoal + bi(movetogoal, 67, 0), // (void) +#undef PF_movetogoal + bi(precache_file, 68, 1, p(string)), + bi(makestatic, 69, 1, p(entity)), + bi(changelevel, 70, 1, p(string)), - {"movetogoal", SV_MoveToGoal, 67}, - {"precache_file", PF_precache_file, 68}, - {"makestatic", PF_makestatic, 69}, - {"changelevel", PF_changelevel, 70}, - - {"centerprint", PF_centerprint, 73}, - {"ambientsound", PF_ambientsound, 74}, - {"precache_model2", PF_precache_model, 75}, - {"precache_sound2", PF_precache_sound, 76}, - {"precache_file2", PF_precache_file, 77}, - {"setspawnparms", PF_setspawnparms, 78}, - - {"testentitypos", PF_testentitypos, QF 92}, - {"hullpointcontents", PF_hullpointcontents, QF 93}, - {"getboxbounds", PF_getboxbounds, QF 94}, - {"getboxhull", PF_getboxhull, QF 95}, - {"freeboxhull", PF_freeboxhull, QF 96}, - {"rotate_bbox", PF_rotate_bbox, QF 97}, - {"tracebox", PF_tracebox, QF 98}, - {"checkextension", PF_checkextension, QF 99}, - - {"EntityParseFunction", ED_EntityParseFunction, -1}, + bi(centerprint, 73, -1), // (...) + bi(ambientsound, 74, 4, p(vector), p(string), p(float), p(float)), + bi(precache_model2, 75, 1, p(string)), + bi(precache_sound2, 76, 1, p(string)), + bi(precache_file2, 77, 1, p(string)), + bi(setspawnparms, 78, 1, p(entity)), + bi(testentitypos, QF 92, 1, p(entity)), + bi(hullpointcontents, QF 93, 2, p(entity), p(vector)), + bi(getboxbounds, QF 94, 2, p(int), p(int)), + bi(getboxhull, QF 95, 0), // (void) + bi(freeboxhull, QF 96, 1, p(int)), + bi(rotate_bbox, QF 97, 6, p(int), p(vector), p(vector), p(vector), + p(vector), p(vector)), + bi(tracebox, QF 98, 6, p(vector), p(vector), p(vector), p(vector), + p(float), p(entity)), + bi(checkextension, QF 99, -1, {}), //FIXME correct params? +#define PF_EntityParseFunction ED_EntityParseFunction + bi(EntityParseFunction, -1, 1, p(func)), +#undef PF_EntityParseFunction {0} }; diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index d6ecf086b..fd4841d7a 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -684,7 +684,7 @@ PF_findradius (progs_t *pr) // entity () spawn static void -PF_Spawn (progs_t *pr) +PF_spawn (progs_t *pr) { edict_t *ed; @@ -696,7 +696,7 @@ cvar_t *pr_double_remove; // void (entity e) remove static void -PF_Remove (progs_t *pr) +PF_remove (progs_t *pr) { edict_t *ed; @@ -767,6 +767,7 @@ PF_precache_file (progs_t *pr) // precache_file is used only to copy files with qcc, it does nothing R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_file2 PF_precache_file // void (string s) precache_sound // string (string s) precache_sound2 @@ -777,6 +778,7 @@ PF_precache_sound (progs_t *pr) "precache_sound"); R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_sound2 PF_precache_sound // void (string s) precache_model // string (string s) precache_model2 @@ -787,6 +789,7 @@ PF_precache_model (progs_t *pr) "precache_model"); R_INT (pr) = P_INT (pr, 0); } +#define PF_precache_model2 PF_precache_model /* PF_walkmove @@ -1639,7 +1642,7 @@ PF_testentitypos (progs_t *pr) #define MAX_PF_HULLS 64 // FIXME make dynamic? clip_hull_t *pf_hull_list[MAX_PF_HULLS]; -// integer (entity ent, vector point) hullpointcontents +// int (entity ent, vector point) hullpointcontents static void PF_hullpointcontents (progs_t *pr) { @@ -1655,7 +1658,7 @@ PF_hullpointcontents (progs_t *pr) R_INT (pr) = SV_HullPointContents (hull, 0, offset); } -// vector (integer hull, integer max) getboxbounds +// vector (int hull, int max) getboxbounds static void PF_getboxbounds (progs_t *pr) { @@ -1672,7 +1675,7 @@ PF_getboxbounds (progs_t *pr) } } -// integer () getboxhull +// int () getboxhull static void PF_getboxhull (progs_t *pr) { @@ -1697,7 +1700,7 @@ PF_getboxhull (progs_t *pr) } } -// void (integer hull) freeboxhull +// void (int hull) freeboxhull static void PF_freeboxhull (progs_t *pr) { @@ -1727,7 +1730,7 @@ calc_dist (vec3_t p, vec3_t n, vec3_t *offsets) return DotProduct (v, n); } -// void (integer hull, vector right, vector forward, vector up, vector mins, vector maxs) rotate_bbox +// void (int hull, vector right, vector forward, vector up, vector mins, vector maxs) rotate_bbox static void PF_rotate_bbox (progs_t *pr) { @@ -1828,7 +1831,7 @@ PF_sv_cvar (progs_t *pr) } } -// int () SV_ClientNumber +// int (entity) SV_ClientNumber // returns -1 if the entity is not a client (either not in the client range // or the entity is not in use by a client) static void @@ -1898,9 +1901,9 @@ PF_SV_SetUserinfo (progs_t *pr) SV_ExtractFromUserinfo (cl); } -// void (entity cl, integer ping) SV_SetPing +// void (entity cl, int ping) SV_SetPing static void -PR_SV_SetPing (progs_t *pr) +PF_SV_SetPing (progs_t *pr) { int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; @@ -1910,9 +1913,9 @@ PR_SV_SetPing (progs_t *pr) cl->ping = P_INT (pr, 1); } -// void (entity cl, float secs, vector angles, vector move, integer buttons, integer impulse) SV_UserCmd +// void (entity cl, float secs, vector angles, vector move, int buttons, int impulse) SV_UserCmd static void -PR_SV_UserCmd (progs_t *pr) +PF_SV_UserCmd (progs_t *pr) { usercmd_t ucmd; int entnum = P_EDICTNUM (pr, 0); @@ -1938,7 +1941,7 @@ PR_SV_UserCmd (progs_t *pr) // void (entity cl) SV_Spawn static void -PR_SV_Spawn (progs_t *pr) +PF_SV_Spawn (progs_t *pr) { int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; @@ -1951,96 +1954,106 @@ PR_SV_Spawn (progs_t *pr) #define QF (PR_RANGE_QF << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"makevectors", PF_makevectors, 1}, - {"setorigin", PF_setorigin, 2}, - {"setmodel", PF_setmodel, 3}, - {"setsize", PF_setsize, 4}, + bi(makevectors, 1, 1, p(vector)), + bi(setorigin, 2, 2, p(entity), p(vector)), + bi(setmodel, 3, 2, p(entity), p(string)), + bi(setsize, 4, 3, p(entity), p(vector), p(vector)), - {"sound", PF_sound, 8}, + bi(sound, 8, 3, p(entity), p(float), p(string)), - {"error", PF_error, 10}, - {"objerror", PF_objerror, 11}, - {"spawn", PF_Spawn, 14}, - {"remove", PF_Remove, 15}, - {"traceline", PF_traceline, 16}, - {"checkclient", PF_checkclient, 17}, + bi(error, 10, -1), // (...) + bi(objerror, 11, -1), // (...) + bi(spawn, 14, 0), // (void) + bi(remove, 15, 1, p(entity)), + bi(traceline, 16, 3, p(vector), p(vector), p(float)), + bi(checkclient, 17, 0), // (void) - {"precache_sound", PF_precache_sound, 19}, - {"precache_model", PF_precache_model, 20}, - {"stuffcmd", PF_stuffcmd, 21}, - {"findradius", PF_findradius, 22}, - {"bprint", PF_bprint, 23}, - {"sprint", PF_sprint, 24}, + bi(precache_sound, 19, 1, p(string)), + bi(precache_model, 20, 1, p(string)), + bi(stuffcmd, 21, 2, p(entity), p(string)), + bi(findradius, 22, 2, p(vector), p(float)), + bi(bprint, 23, -1), // (...) + bi(sprint, 24, -2, p(entity)), // (entity, string...) - {"walkmove", PF_walkmove, 32}, + bi(walkmove, 32, 2, p(float), p(float)), - {"droptofloor", PF_droptofloor, 34}, - {"lightstyle", PF_lightstyle, 35}, + bi(droptofloor, 34, 0), // (void) + bi(lightstyle, 35, 2, p(float), p(string)), - {"checkbottom", PF_checkbottom, 40}, - {"pointcontents", PF_pointcontents, 41}, + bi(checkbottom, 40, 1, p(entity)), + bi(pointcontents, 41, 1, p(vector)), - {"aim", PF_aim, 44}, + bi(aim, 44, 2, p(entity), p(float)), - {"localcmd", PF_localcmd, 46}, + bi(localcmd, 46, 1, p(string)), - {"changeyaw", PF_changeyaw, 49}, +// bi(particle, 48, 4, p(vector), p(vector), p(float), p(float)), + bi(changeyaw, 49, 0), // (void) - {"writebyte", PF_WriteByte, 52}, - {"WriteBytes", PF_WriteBytes, -1}, - {"writechar", PF_WriteChar, 53}, - {"writeshort", PF_WriteShort, 54}, - {"writelong", PF_WriteLong, 55}, - {"writecoord", PF_WriteCoord, 56}, - {"writeangle", PF_WriteAngle, 57}, - {"WriteCoordV", PF_WriteCoordV, -1}, - {"WriteAngleV", PF_WriteAngleV, -1}, - {"writestring", PF_WriteString, 58}, - {"writeentity", PF_WriteEntity, 59}, + bi(WriteByte, 52, 2, p(float), p(float)), + bi(WriteBytes, -1, -2, p(float)), // (float, float...) + bi(WriteChar, 53, 2, p(float), p(float)), + bi(WriteShort, 54, 2, p(float), p(float)), + bi(WriteLong, 55, 2, p(float), p(float)), + bi(WriteCoord, 56, 2, p(float), p(float)), + bi(WriteAngle, 57, 2, p(float), p(float)), + bi(WriteCoordV, -1, 2, p(float), p(vector)), + bi(WriteAngleV, -1, 2, p(float), p(vector)), + bi(WriteString, 58, 2, p(float), p(string)), + bi(WriteEntity, 59, 2, p(float), p(entity)), +#define PF_movetogoal SV_MoveToGoal + bi(movetogoal, 67, 0), // (void) +#undef PF_movetogoal + bi(precache_file, 68, 1, p(string)), + bi(makestatic, 69, 1, p(entity)), + bi(changelevel, 70, 1, p(string)), - {"movetogoal", SV_MoveToGoal, 67}, - {"precache_file", PF_precache_file, 68}, - {"makestatic", PF_makestatic, 69}, - {"changelevel", PF_changelevel, 70}, + bi(centerprint, 73, -1), // (...) + bi(ambientsound, 74, 4, p(vector), p(string), p(float), p(float)), + bi(precache_model2, 75, 1, p(string)), + bi(precache_sound2, 76, 1, p(string)), + bi(precache_file2, 77, 1, p(string)), + bi(setspawnparms, 78, 1, p(entity)), - {"centerprint", PF_centerprint, 73}, - {"ambientsound", PF_ambientsound, 74}, - {"precache_model2", PF_precache_model, 75}, - {"precache_sound2", PF_precache_sound, 76}, - {"precache_file2", PF_precache_file, 77}, - {"setspawnparms", PF_setspawnparms, 78}, + bi(logfrag, 79, 2, p(entity), p(entity)), + bi(infokey, 80, 2, p(entity), p(string)), + bi(multicast, 81, 2, p(vector), p(float)), - {"logfrag", PF_logfrag, 79}, - {"infokey", PF_infokey, 80}, - {"multicast", PF_multicast, 82}, + bi(testentitypos, QF 92, 1, p(entity)), + bi(hullpointcontents, QF 93, 2, p(entity), p(vector)), + bi(getboxbounds, QF 94, 2, p(int), p(int)), + bi(getboxhull, QF 95, 0), // (void) + bi(freeboxhull, QF 96, 1, p(int)), + bi(rotate_bbox, QF 97, 6, p(int), p(vector), p(vector), p(vector), + p(vector), p(vector)), + bi(tracebox, QF 98, 6, p(vector), p(vector), p(vector), p(vector), + p(float), p(entity)), + bi(checkextension, QF 99, -1, {}), //FIXME correct params? - {"testentitypos", PF_testentitypos, QF 92}, - {"hullpointcontents", PF_hullpointcontents, QF 93}, - {"getboxbounds", PF_getboxbounds, QF 94}, - {"getboxhull", PF_getboxhull, QF 95}, - {"freeboxhull", PF_freeboxhull, QF 96}, - {"rotate_bbox", PF_rotate_bbox, QF 97}, - {"tracebox", PF_tracebox, QF 98}, - {"checkextension", PF_checkextension, QF 99}, - {"setinfokey", PF_setinfokey, QF 102}, - {"cfopen", PF_cfopen, QF 103}, - {"cfclose", PF_cfclose, QF 104}, - {"cfread", PF_cfread, QF 105}, - {"cfwrite", PF_cfwrite, QF 106}, - {"cfeof", PF_cfeof, QF 107}, - {"cfquota", PF_cfquota, QF 108}, + bi(setinfokey, QF 102, 3, p(entity), p(string), p(string)), + bi(cfopen, QF 103, 2, p(string), p(string)), + bi(cfclose, QF 104, 1, p(float)), + bi(cfread, QF 105, 1, p(float)), + bi(cfwrite, QF 106, 2, p(float), p(string)), + bi(cfeof, QF 107, 1, p(float)), + bi(cfquota, QF 108, 0), // (void) - {"SV_ClientNumber", PF_SV_ClientNumber, -1}, - {"SV_AllocClient", PF_SV_AllocClient, -1}, - {"SV_FreeClient", PF_SV_FreeClient, -1}, - {"SV_SetUserinfo", PF_SV_SetUserinfo, -1}, - {"SV_SetPing", PR_SV_SetPing, -1}, - {"SV_UserCmd", PR_SV_UserCmd, -1}, - {"SV_Spawn", PR_SV_Spawn, -1}, + bi(SV_ClientNumber, -1, 1, p(entity)), + bi(SV_AllocClient, -1, 0), // (void) + bi(SV_FreeClient, -1, 1, p(entity)), + bi(SV_SetUserinfo, -1, 2, p(entity), p(string)), + bi(SV_SetPing, -1, 2, p(entity), p(int)), + bi(SV_UserCmd, -1, 6, p(entity), p(float), p(vector), p(vector), + p(int), p(int)), + bi(SV_Spawn, -1, 1, p(entity)), - {"EntityParseFunction", ED_EntityParseFunction, -1}, +#define PF_EntityParseFunction ED_EntityParseFunction + bi(EntityParseFunction, -1, 1, p(func)), +#undef PF_EntityParseFunction {0} }; diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index f331b7e32..160fb090c 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -729,7 +729,7 @@ PF_touchworld (progs_t *pr) #define TL_EVERYTHING 4 // scan for anything static void -CPQW_traceline (progs_t *pr) +PF_traceline (progs_t *pr) { float *v1, *v2; edict_t *ent; @@ -774,23 +774,27 @@ CPQW_traceline (progs_t *pr) #define CPQW (PR_RANGE_CPQW << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {"CPCW:"#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"CPCW:traceline", CPQW_traceline, CPQW 16}, - {"CPQW:getuid", PF_getuid, CPQW 83}, - {"CPQW:strcat", PF_strcat, CPQW 84}, - {"CPQW:padstr", PF_padstr, CPQW 85}, - {"CPQW:colstr", PF_colstr, CPQW 86}, - {"CPQW:strcasecmp", PF_strcasecmp, CPQW 87}, - {"CPQW:strlen", PF_strlen, CPQW 88}, - {"CPQW:getclient", PF_getclient, CPQW 89}, - {"CPQW:mutedtime", PF_mutedtime, CPQW 90}, - {"CPQW:validatefile", PF_validatefile, CPQW 91}, - {"CPQW:putsaytime", PF_putsaytime, CPQW 92}, - {"CPQW:makestr", PF_makestr, CPQW 93}, - {"CPQW:delstr", PF_delstr, CPQW 94}, - {"CPQW:getwave", PF_getwave, CPQW 95}, - {"CPQW:clientsound", PF_clientsound, CPQW 96}, - {"CPQW:touchworld", PF_touchworld, CPQW 97}, + bi(traceline, CPQW 16, 3, p(vector), p(vector), p(float)), + bi(getuid, CPQW 83, 1, p(entity)), + bi(strcat, CPQW 84, 2, p(string), p(string)), + bi(padstr, CPQW 85, 2, p(string), p(float)), + bi(colstr, CPQW 86, 2, p(string), p(float)), + bi(strcasecmp, CPQW 87, 2, p(string), p(string)), + bi(strlen, CPQW 88, 1, p(string)), + bi(getclient, CPQW 89, 1, p(string)), + bi(mutedtime, CPQW 90, 1, p(entity)), + bi(validatefile, CPQW 91, 1, p(string)), + bi(putsaytime, CPQW 92, 1, p(entity)), + bi(makestr, CPQW 93, 1, p(string)), + bi(delstr, CPQW 94, 1, p(string)), + bi(getwave, CPQW 95, 7, p(float), p(float), p(float), p(float), + p(float), p(float), p(float)), + bi(clientsound, CPQW 96, 1, p(entity)), + bi(touchworld, CPQW 97, 0), {0} }; diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index 6c89a820b..521bb721d 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -480,28 +480,31 @@ PF_conprint (progs_t *pr) #define QWE (PR_RANGE_QWE << PR_RANGE_SHIFT) | +#define bi(x,n,np,params...) {"QWE:"#x, PF_##x, n, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"QWE:executecmd", PF_executecmd, QWE 83}, - {"QWE:tokanize" /* sic */, PF_tokanize, QWE 84}, - {"QWE:argc", PF_argc, QWE 85}, - {"QWE:argv", PF_argv, QWE 86}, - {"QWE:teamfield", PF_teamfield, QWE 87}, - {"QWE:substr", PF_substr, QWE 88}, - {"QWE:strcat", PF_strcat, QWE 89}, - {"QWE:strlen", PF_strlen, QWE 90}, - {"QWE:str2byte", PF_str2byte, QWE 91}, - {"QWE:str2short", PF_str2short, QWE 92}, - {"QWE:newstr", PF_newstr, QWE 93}, - {"QWE:freestr", PF_freestr, QWE 94}, - {"QWE:conprint", PF_conprint, QWE 95}, - {"QWE:readcmd", PF_readcmd, QWE 96}, - {"QWE:strcpy", PF_strcpy, QWE 97}, - {"QWE:strstr", PF_strstr, QWE 98}, - {"QWE:strncpy", PF_strncpy, QWE 99}, - {"QWE:log", PF_log, QWE 100}, - {"QWE:redirectcmd", PF_redirectcmd, QWE 101}, - {"QWE:calltimeofday", PF_calltimeofday, QWE 102}, - {"QWE:forceddemoframe", PF_forcedemoframe, QWE 103}, + bi(executecmd, QWE 83, 0), + bi(tokanize, QWE 84, 1, p(string)), /* sic */ + bi(argc, QWE 85, 0), + bi(argv, QWE 86, 1, p(float)), + bi(teamfield, QWE 87, 1, p(field)), + bi(substr, QWE 88, 3, p(string), p(float), p(float)), + bi(strcat, QWE 89, -1), + bi(strlen, QWE 90, 1, p(string)), + bi(str2byte, QWE 91, 1, p(string)), + bi(str2short, QWE 92, 1, p(string)), + bi(newstr, QWE 93, 2, p(string), p(float)), + bi(freestr, QWE 94, 1, p(string)), + bi(conprint, QWE 95, -1), + bi(readcmd, QWE 96, 1, p(string)), + bi(strcpy, QWE 97, 2, p(string), p(string)), + bi(strstr, QWE 98, 2, p(string), p(string)), + bi(strncpy, QWE 99, 3, p(string), p(string), p(float)), + bi(log, QWE 100, 3, p(string), p(float), p(string)), + bi(redirectcmd, QWE 101, 2, p(entity), p(string)), + bi(calltimeofday, QWE 102, 0), + bi(forcedemoframe, QWE 103, 1, p(float)), {0} }; #define LAST_QWE_BUILTIN 103 diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 0d6ab4c3f..1160f673a 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -1422,7 +1422,7 @@ SV_RemoveUserCommand (void *cmd) } static void -PF_AddUserCommand (progs_t *pr) +PF_SV_AddUserCommand (progs_t *pr) { const char *name = P_GSTRING (pr, 0); ucmd_t *cmd; @@ -1999,8 +1999,11 @@ SV_ExecuteClientMessage (client_t *cl) } } +#define bi(x,np,params...) {#x, PF_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"SV_AddUserCommand", PF_AddUserCommand, -1}, + bi(SV_AddUserCommand, 3, p(string), p(func), p(int)), {0} }; diff --git a/ruamoko/cl_menu/menu.r b/ruamoko/cl_menu/menu.r index 748bd35ed..a47650a42 100644 --- a/ruamoko/cl_menu/menu.r +++ b/ruamoko/cl_menu/menu.r @@ -21,3 +21,4 @@ int () Menu_GetIndex = #0; void (void) Menu_Next = #0; void (void) Menu_Prev = #0; void (void) Menu_Enter = #0; +void (void) Menu_Leave = #0; diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index 6c7e0e6f4..bccea1de4 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -12,7 +12,7 @@ void __obj_exec_class (struct obj_module *msg) = #0; BOOL __obj_responds_to(id obj, SEL sel) = #0; void (id object, int code, string fmt, ...) obj_error = #0; void (id object, int code, string fmt, @va_list args) obj_verror = #0; -//obj_error_handler (objc_error_handler func) obj_set_error_handler = #0; +//obj_error_handler obj_set_error_handler (objc_error_handler func) = #0; IMP (id receiver, SEL op) obj_msg_lookup = #0; IMP (Super class, SEL op) obj_msg_lookup_super = #0; id (id receiver, SEL op, ...) obj_msgSend = #0; @@ -27,11 +27,11 @@ void *obj_valloc (int size) = #0; void *obj_realloc (void *mem, int size) = #0; void *obj_calloc (int nelem, int size) = #0; void obj_free (void *mem) = #0; -//(void *) (void) obj_get_uninstalled_dtable = #0; +void *obj_get_uninstalled_dtable (void) = #0; -Class (string name) obj_get_class = #0; -Class (string name) obj_lookup_class = #0; -//Class (void **enum_stage) obj_next_class = #0; +Class obj_get_class (string name) = #0; +Class obj_lookup_class (string name) = #0; +Class obj_next_class (void **enum_stage) = #0; string (SEL selector) sel_get_name = #0; string (SEL selector) sel_get_type = #0; diff --git a/ruamoko/lib/Set.r b/ruamoko/lib/Set.r index 7afc13361..4786b71a7 100644 --- a/ruamoko/lib/Set.r +++ b/ruamoko/lib/Set.r @@ -1,6 +1,7 @@ #include void set_del_iter (set_iter_t *set_iter) = #0; +unsigned set_iter_element (set_iter_t *set_iter) = #0; set_t *set_new (void) = #0; void set_delete (set_t *set) = #0; set_t *set_add (set_t *set, unsigned x) = #0; diff --git a/ruamoko/lib/key.r b/ruamoko/lib/key.r index 4b8c1a09a..812800128 100644 --- a/ruamoko/lib/key.r +++ b/ruamoko/lib/key.r @@ -5,3 +5,4 @@ string (string imt, int keynum, string binding) Key_SetBinding = #0; int (string imt, int bindnum, string binding) Key_LookupBinding = #0; int (string imt, string binding) Key_CountBinding = #0; string (int keynum) Key_KeynumToString = #0; +int (string keyname) Key_StringToKeynum = #0; diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 1e7c7d58c..a3f83fceb 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -779,7 +779,7 @@ bi_syncprintf (progs_t *pr) } static void -bi_newwin (progs_t *pr) +bi_create_window (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int xpos = P_INT (pr, 0); @@ -800,7 +800,7 @@ bi_newwin (progs_t *pr) } static void -bi_delwin (progs_t *pr) +bi_destroy_window (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int window_id = P_INT (pr, 0); @@ -839,7 +839,7 @@ bi_getwrect (progs_t *pr) } static void -bi_new_panel (progs_t *pr) +bi_create_panel (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int window_id = P_INT (pr, 0); @@ -870,7 +870,7 @@ panel_command (progs_t *pr, qwaq_commands cmd) } static void -bi_del_panel (progs_t *pr) +bi_destroy_panel (progs_t *pr) { panel_command (pr, qwaq_cmd_del_panel); } @@ -1604,26 +1604,26 @@ bi_initialize (progs_t *pr) } static void -bi_c_TextContext__is_initialized (progs_t *pr) +bi__c_TextContext__is_initialized (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); R_INT (pr) = res->initialized; } static void -bi_c_TextContext__max_colors (progs_t *pr) +bi__c_TextContext__max_colors (progs_t *pr) { bi_max_colors (pr); } static void -bi_c_TextContext__max_color_pairs (progs_t *pr) +bi__c_TextContext__max_color_pairs (progs_t *pr) { bi_max_color_pairs (pr); } static void -bi_c_TextContext__init_pair_ (progs_t *pr) +bi__c_TextContext__init_pair_ (progs_t *pr) { int pair = P_INT (pr, 2); int f = P_INT (pr, 3); @@ -1633,7 +1633,7 @@ bi_c_TextContext__init_pair_ (progs_t *pr) } static void -bi_c_TextContext__acs_char_ (progs_t *pr) +bi__c_TextContext__acs_char_ (progs_t *pr) { int acs = P_INT (pr, 2); @@ -1641,7 +1641,7 @@ bi_c_TextContext__acs_char_ (progs_t *pr) } static void -bi_c_TextContext__move_ (progs_t *pr) +bi__c_TextContext__move_ (progs_t *pr) { Point *pos = &P_PACKED (pr, Point, 2); @@ -1649,7 +1649,7 @@ bi_c_TextContext__move_ (progs_t *pr) } static void -bi_c_TextContext__curs_set_ (progs_t *pr) +bi__c_TextContext__curs_set_ (progs_t *pr) { int visibility = P_INT (pr, 2); @@ -1657,13 +1657,13 @@ bi_c_TextContext__curs_set_ (progs_t *pr) } static void -bi_c_TextContext__doupdate (progs_t *pr) +bi__c_TextContext__doupdate (progs_t *pr) { bi_doupdate (pr); } static void -bi_i_TextContext__mvprintf_ (progs_t *pr) +bi__i_TextContext__mvprintf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); @@ -1675,7 +1675,7 @@ bi_i_TextContext__mvprintf_ (progs_t *pr) } static void -bi_i_TextContext__printf_ (progs_t *pr) +bi__i_TextContext__printf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; const char *fmt = P_GSTRING (pr, 2); @@ -1686,7 +1686,7 @@ bi_i_TextContext__printf_ (progs_t *pr) } static void -bi_i_TextContext__vprintf_ (progs_t *pr) +bi__i_TextContext__vprintf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; const char *fmt = P_GSTRING (pr, 2); @@ -1696,7 +1696,7 @@ bi_i_TextContext__vprintf_ (progs_t *pr) } static void -bi_i_TextContext__addch_ (progs_t *pr) +bi__i_TextContext__addch_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int ch = P_INT (pr, 2); @@ -1705,7 +1705,7 @@ bi_i_TextContext__addch_ (progs_t *pr) } static void -bi_i_TextContext__addstr_ (progs_t *pr) +bi__i_TextContext__addstr_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; const char *str = P_GSTRING (pr, 2); @@ -1714,7 +1714,7 @@ bi_i_TextContext__addstr_ (progs_t *pr) } static void -bi_i_TextContext__mvvprintf_ (progs_t *pr) +bi__i_TextContext__mvvprintf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); @@ -1725,7 +1725,7 @@ bi_i_TextContext__mvvprintf_ (progs_t *pr) } static void -bi_i_TextContext__resizeTo_ (progs_t *pr) +bi__i_TextContext__resizeTo_ (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1738,14 +1738,14 @@ bi_i_TextContext__resizeTo_ (progs_t *pr) } static void -bi_c_TextContext__refresh (progs_t *pr) +bi__c_TextContext__refresh (progs_t *pr) { qwaq_update_panels (pr); qwaq_doupdate (pr); } static void -bi_i_TextContext__refresh (progs_t *pr) +bi__i_TextContext__refresh (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; @@ -1757,7 +1757,7 @@ bi_i_TextContext__refresh (progs_t *pr) } static void -bi_i_TextContext__mvaddch_ (progs_t *pr) +bi__i_TextContext__mvaddch_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); @@ -1767,7 +1767,7 @@ bi_i_TextContext__mvaddch_ (progs_t *pr) } static void -bi_i_TextContext__mvaddstr_ (progs_t *pr) +bi__i_TextContext__mvaddstr_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); @@ -1777,7 +1777,7 @@ bi_i_TextContext__mvaddstr_ (progs_t *pr) } static void -bi_i_TextContext__bkgd_ (progs_t *pr) +bi__i_TextContext__bkgd_ (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1788,7 +1788,7 @@ bi_i_TextContext__bkgd_ (progs_t *pr) } static void -bi_i_TextContext__clear (progs_t *pr) +bi__i_TextContext__clear (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1798,7 +1798,7 @@ bi_i_TextContext__clear (progs_t *pr) } static void -bi_i_TextContext__scrollok_ (progs_t *pr) +bi__i_TextContext__scrollok_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int flag = P_INT (pr, 2); @@ -1807,7 +1807,7 @@ bi_i_TextContext__scrollok_ (progs_t *pr) } static void -bi_i_TextContext__border_ (progs_t *pr) +bi__i_TextContext__border_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; __auto_type sides = P_PACKED (pr, box_sides_t, 2); @@ -1817,7 +1817,7 @@ bi_i_TextContext__border_ (progs_t *pr) } static void -bi_i_TextContext__mvhline_ (progs_t *pr) +bi__i_TextContext__mvhline_ (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1829,7 +1829,7 @@ bi_i_TextContext__mvhline_ (progs_t *pr) } static void -bi_i_TextContext__mvvline_ (progs_t *pr) +bi__i_TextContext__mvvline_ (progs_t *pr) { __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; @@ -1854,74 +1854,95 @@ bi_curses_clear (progs_t *pr, void *data) panel_reset (res); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"initialize", bi_initialize, -1}, - {"syncprintf", bi_syncprintf, -1}, - {"create_window", bi_newwin, -1}, - {"destroy_window", bi_delwin, -1}, - {"getwrect", bi_getwrect, -1}, - {"create_panel", bi_new_panel, -1}, - {"destroy_panel", bi_del_panel, -1}, - {"hide_panel", bi_hide_panel, -1}, - {"show_panel", bi_show_panel, -1}, - {"top_panel", bi_top_panel, -1}, - {"bottom_panel", bi_bottom_panel, -1}, - {"move_panel", bi_move_panel, -1}, - {"panel_window", bi_panel_window, -1}, - {"replace_panel", bi_replace_panel, -1}, - {"update_panels", bi_update_panels, -1}, - {"doupdate", bi_doupdate, -1}, - {"mvwprintf", bi_mvwprintf, -1}, - {"wprintf", bi_wprintf, -1}, - {"wvprintf", bi_wvprintf, -1}, - {"mvwvprintf", bi_mvwvprintf, -1}, - {"mvwaddch", bi_mvwaddch, -1}, - {"waddch", bi_waddch, -1}, - {"mvwaddstr", bi_mvwaddstr, -1}, - {"waddstr", bi_waddstr, -1}, - {"wrefresh", bi_wrefresh, -1}, - {"max_colors", bi_max_colors, -1}, - {"max_color_pairs", bi_max_color_pairs, -1}, - {"init_pair", bi_init_pair, -1}, - {"wbkgd", bi_wbkgd, -1}, - {"werase", bi_werase, -1}, - {"scrollok", bi_scrollok, -1}, - {"wmove", bi_wmove, -1}, - {"acs_char", bi_acs_char, -1}, - {"move", bi_move, -1}, - {"curs_set", bi_curs_set, -1}, - {"wborder", bi_wborder, -1}, - {"mvwblit_line", bi_mvwblit_line, -1}, - {"wresize", bi_wresize, -1}, - {"resizeterm", bi_resizeterm, -1}, - {"mvwhline", bi_mvwhline, -1}, - {"mvwvline", bi_mvwvline, -1}, + bi(initialize, 0), + bi(syncprintf, -2, p(string)), + bi(create_window, 4, p(int), p(int), p(int), p(int)), + bi(destroy_window, 1, p(ptr)), + bi(getwrect, 1, p(ptr)), + bi(create_panel, 1, p(ptr)), + bi(destroy_panel, 1, p(ptr)), + bi(hide_panel, 1, p(ptr)), + bi(show_panel, 1, p(ptr)), + bi(top_panel, 1, p(ptr)), + bi(bottom_panel, 1, p(ptr)), + bi(move_panel, 3, p(ptr), p(int), p(int)), + bi(panel_window, 1, p(ptr)), + bi(replace_panel, 2, p(ptr), p(ptr)), + bi(update_panels, 0), + bi(doupdate, 0), + bi(mvwprintf, -5, p(ptr), p(int), p(int), p(string)), + bi(wprintf, -3, p(ptr), p(string)), + bi(wvprintf, 3, p(ptr), p(string), P(1, 2)), + bi(mvwvprintf, 5, p(ptr), p(int), p(int), p(string), P(1, 2)), + bi(mvwaddch, 4, p(ptr), p(int), p(int), p(int)), + bi(waddch, 2, p(ptr), p(int)), + bi(mvwaddstr, 4, p(ptr), p(int), p(int), p(string)), + bi(waddstr, 2, p(ptr), p(string)), + bi(wrefresh, 1, p(ptr)), + bi(max_colors, 0), + bi(max_color_pairs, 0), + bi(init_pair, 3, p(int), p(int), p(int)), + bi(wbkgd, 2, p(ptr), p(int)), + bi(werase, 1, p(ptr)), + bi(scrollok, 2, p(ptr), p(int)), + bi(wmove, 3, p(ptr), p(int), p(int), p(int)), + bi(acs_char, 1, p(int)), + bi(move, 2, p(int), p(int)), + bi(curs_set, 1, p(int)), + bi(wborder, 3, p(ptr), P(1, 4), P(1, 4)), + bi(mvwblit_line, 5, p(ptr), p(int), p(int), p(ptr), p(int)), + bi(wresize, 3, p(ptr), p(int), p(int)), + bi(resizeterm, 2, p(int), p(int)), + bi(mvwhline, 5, p(ptr), p(int), p(int), p(int), p(int)), + bi(mvwvline, 5, p(ptr), p(int), p(int), p(int), p(int)), - {"_c_TextContext__is_initialized", bi_c_TextContext__is_initialized, -1}, - {"_c_TextContext__max_colors", bi_c_TextContext__max_colors, -1}, - {"_c_TextContext__max_color_pairs", bi_c_TextContext__max_color_pairs, -1}, - {"_c_TextContext__init_pair_", bi_c_TextContext__init_pair_, -1}, - {"_c_TextContext__acs_char_", bi_c_TextContext__acs_char_, -1}, - {"_c_TextContext__move_", bi_c_TextContext__move_, -1}, - {"_c_TextContext__curs_set_", bi_c_TextContext__curs_set_, -1}, - {"_c_TextContext__doupdate", bi_c_TextContext__doupdate, -1}, - {"_i_TextContext__mvprintf_", bi_i_TextContext__mvprintf_, -1}, - {"_i_TextContext__printf_", bi_i_TextContext__printf_, -1}, - {"_i_TextContext__vprintf_", bi_i_TextContext__vprintf_, -1}, - {"_i_TextContext__addch_", bi_i_TextContext__addch_, -1}, - {"_i_TextContext__addstr_", bi_i_TextContext__addstr_, -1}, - {"_i_TextContext__mvvprintf_", bi_i_TextContext__mvvprintf_, -1}, - {"_i_TextContext__resizeTo_", bi_i_TextContext__resizeTo_, -1}, - {"_c_TextContext__refresh", bi_c_TextContext__refresh, -1}, - {"_i_TextContext__refresh", bi_i_TextContext__refresh, -1}, - {"_i_TextContext__mvaddch_", bi_i_TextContext__mvaddch_, -1}, - {"_i_TextContext__mvaddstr_", bi_i_TextContext__mvaddstr_, -1}, - {"_i_TextContext__bkgd_", bi_i_TextContext__bkgd_, -1}, - {"_i_TextContext__clear", bi_i_TextContext__clear, -1}, - {"_i_TextContext__scrollok_", bi_i_TextContext__scrollok_, -1}, - {"_i_TextContext__border_", bi_i_TextContext__border_, -1}, - {"_i_TextContext__mvhline_", bi_i_TextContext__mvhline_, -1}, - {"_i_TextContext__mvvline_", bi_i_TextContext__mvvline_, -1}, + bi(_c_TextContext__is_initialized, 2, p(ptr), p(ptr)), + bi(_c_TextContext__max_colors, 2, p(ptr), p(ptr)), + bi(_c_TextContext__max_color_pairs, 2, p(ptr), p(ptr)), + bi(_c_TextContext__init_pair_, 5, p(ptr), p(ptr), + p(int), p(int), p(int)), + bi(_c_TextContext__acs_char_, 3, p(ptr), p(ptr), + p(int)), + bi(_c_TextContext__move_, 3, p(ptr), p(ptr), + P(1, 2)), + bi(_c_TextContext__curs_set_, 3, p(ptr), p(ptr), + p(int)), + bi(_c_TextContext__doupdate, 2, p(ptr), p(ptr)), + bi(_i_TextContext__mvprintf_, -5, p(ptr), p(ptr), + P(1, 2), p(string)), + bi(_i_TextContext__printf_, -4, p(ptr), p(ptr), + p(string)), + bi(_i_TextContext__vprintf_, 4, p(ptr), p(ptr), + p(string), P(1, 2)), + bi(_i_TextContext__addch_, 3, p(ptr), p(ptr), + p(int)), + bi(_i_TextContext__addstr_, 3, p(ptr), p(ptr), + p(string)), + bi(_i_TextContext__mvvprintf_, 5, p(ptr), p(ptr), + P(1, 2), p(string), P(1, 2)), + bi(_i_TextContext__resizeTo_, 3, p(ptr), p(ptr), + P(1, 2)), + bi(_c_TextContext__refresh, 2, p(ptr), p(ptr)), + bi(_i_TextContext__refresh, 2, p(ptr), p(ptr)), + bi(_i_TextContext__mvaddch_, 4, p(ptr), p(ptr), + P(1, 2), p(int)), + bi(_i_TextContext__mvaddstr_, 4, p(ptr), p(ptr), + P(1, 2), p(string)), + bi(_i_TextContext__bkgd_, 3, p(ptr), p(ptr), + p(int)), + bi(_i_TextContext__clear, 2, p(ptr), p(ptr)), + bi(_i_TextContext__scrollok_, 3, p(ptr), p(ptr), + p(int)), + bi(_i_TextContext__border_, 4, p(ptr), p(ptr), + P(1, 4), P(1, 4)), + bi(_i_TextContext__mvhline_, 5, p(ptr), p(ptr), + P(1, 2), p(int), p(int)), + bi(_i_TextContext__mvvline_, 5, p(ptr), p(ptr), + P(1, 2), p(int), p(int)), {0} }; diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 2738a8589..98c7294c7 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -649,30 +649,32 @@ qdb_get_source_line_addr (progs_t *pr) R_UINT (pr) = PR_FindSourceLineAddr (tpr, file, line); } +#define bi(x,np,params...) {#x, x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"qdb_set_trace", qdb_set_trace, -1}, - {"qdb_set_breakpoint", qdb_set_breakpoint, -1}, - {"qdb_clear_breakpoint", qdb_clear_breakpoint, -1}, - {"qdb_set_watchpoint", qdb_set_watchpoint, -1}, - {"qdb_clear_watchpoint", qdb_clear_watchpoint, -1}, - {"qdb_continue", qdb_continue, -1}, - {"qdb_get_state", qdb_get_state, -1}, - {"qdb_get_stack_depth", qdb_get_stack_depth, -1}, - {"qdb_get_stack", qdb_get_stack, -1}, - {"qdb_get_event", qdb_get_event, -1}, - {"qdb_get_data", qdb_get_data, -1}, - {"qdb_get_string|{tag qdb_target_s=}I", qdb_get_string, -1}, - {"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1}, - {"qdb_get_file_path", qdb_get_file_path, -1}, - {"qdb_find_string", qdb_find_string, -1}, - {"qdb_find_global", qdb_find_global, -1}, - {"qdb_find_field", qdb_find_field, -1}, - {"qdb_find_function", qdb_find_function, -1}, - {"qdb_get_function", qdb_get_function, -1}, - {"qdb_find_auxfunction", qdb_find_auxfunction, -1}, - {"qdb_get_auxfunction", qdb_get_auxfunction, -1}, - {"qdb_get_local_defs", qdb_get_local_defs, -1}, - {"qdb_get_source_line_addr", qdb_get_source_line_addr, -1}, + bi(qdb_set_trace, 2, p(int), p(int)), + bi(qdb_set_breakpoint, 2, p(int), p(uint)), + bi(qdb_clear_breakpoint, 2, p(int), p(uint)), + bi(qdb_set_watchpoint, 2, p(int), p(uint)), + bi(qdb_clear_watchpoint, 1, p(int)), + bi(qdb_continue, 1, p(int)), + bi(qdb_get_state, 1, p(int)), + bi(qdb_get_stack_depth, 1, p(int)), + bi(qdb_get_stack, 1, p(int)), + bi(qdb_get_event, 2, p(int), p(ptr)), + bi(qdb_get_data, 4, p(int), p(uint), p(uint), p(ptr)), + {"qdb_get_string|{tag qdb_target_s=}I", qdb_get_string, -1, 1, {p(uint)}}, + {"qdb_get_string|{tag qdb_target_s=}*", qdb_get_string, -1, 1, {p(string)}}, + bi(qdb_get_file_path, 2, p(int), p(string)), + bi(qdb_find_string, 2, p(int), p(string)), + bi(qdb_find_global, 2, p(int), p(string)), + bi(qdb_find_field, 2, p(int), p(string)), + bi(qdb_find_function, 2, p(int), p(string)), + bi(qdb_get_function, 2, p(int), p(uint)), + bi(qdb_find_auxfunction, 2, p(int), p(string)), + bi(qdb_get_auxfunction, 2, p(int), p(uint)), + bi(qdb_get_local_defs, 2, p(int), p(uint)), + bi(qdb_get_source_line_addr, 3, p(int), p(string), p(uint)), {} }; diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index cea68c941..db3237a2e 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -575,7 +575,7 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, //=== static void -bi_i_EditBuffer__init (progs_t *pr) +bi__i_EditBuffer__init (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); @@ -591,7 +591,7 @@ bi_i_EditBuffer__init (progs_t *pr) } static void -bi_i_EditBuffer__initWithFile_ (progs_t *pr) +bi__i_EditBuffer__initWithFile_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); @@ -610,7 +610,7 @@ bi_i_EditBuffer__initWithFile_ (progs_t *pr) } static void -bi_i_EditBuffer__dealloc (progs_t *pr) +bi__i_EditBuffer__dealloc (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); @@ -622,7 +622,7 @@ bi_i_EditBuffer__dealloc (progs_t *pr) } static void -bi_i_EditBuffer__nextChar_ (progs_t *pr) +bi__i_EditBuffer__nextChar_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -633,7 +633,7 @@ bi_i_EditBuffer__nextChar_ (progs_t *pr) } static void -bi_i_EditBuffer__prevChar_ (progs_t *pr) +bi__i_EditBuffer__prevChar_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -644,7 +644,7 @@ bi_i_EditBuffer__prevChar_ (progs_t *pr) } static void -bi_i_EditBuffer__nextNonSpace_ (progs_t *pr) +bi__i_EditBuffer__nextNonSpace_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -655,7 +655,7 @@ bi_i_EditBuffer__nextNonSpace_ (progs_t *pr) } static void -bi_i_EditBuffer__prevNonSpace_ (progs_t *pr) +bi__i_EditBuffer__prevNonSpace_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -666,7 +666,7 @@ bi_i_EditBuffer__prevNonSpace_ (progs_t *pr) } static void -bi_i_EditBuffer__isWord_ (progs_t *pr) +bi__i_EditBuffer__isWord_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -677,7 +677,7 @@ bi_i_EditBuffer__isWord_ (progs_t *pr) } static void -bi_i_EditBuffer__nextWord_ (progs_t *pr) +bi__i_EditBuffer__nextWord_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -688,7 +688,7 @@ bi_i_EditBuffer__nextWord_ (progs_t *pr) } static void -bi_i_EditBuffer__prevWord_ (progs_t *pr) +bi__i_EditBuffer__prevWord_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -699,7 +699,7 @@ bi_i_EditBuffer__prevWord_ (progs_t *pr) } static void -bi_i_EditBuffer__nextLine_ (progs_t *pr) +bi__i_EditBuffer__nextLine_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -710,7 +710,7 @@ bi_i_EditBuffer__nextLine_ (progs_t *pr) } static void -bi_i_EditBuffer__prevLine_ (progs_t *pr) +bi__i_EditBuffer__prevLine_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -721,7 +721,7 @@ bi_i_EditBuffer__prevLine_ (progs_t *pr) } static void -bi_i_EditBuffer__nextLine__ (progs_t *pr) +bi__i_EditBuffer__nextLine__ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -742,7 +742,7 @@ bi_i_EditBuffer__nextLine__ (progs_t *pr) } static void -bi_i_EditBuffer__prevLine__ (progs_t *pr) +bi__i_EditBuffer__prevLine__ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -757,7 +757,7 @@ bi_i_EditBuffer__prevLine__ (progs_t *pr) } static void -bi_i_EditBuffer__charPos_at_ (progs_t *pr) +bi__i_EditBuffer__charPos_at_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -770,7 +770,7 @@ bi_i_EditBuffer__charPos_at_ (progs_t *pr) } static void -bi_i_EditBuffer__charPtr_at_ (progs_t *pr) +bi__i_EditBuffer__charPtr_at_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -783,7 +783,7 @@ bi_i_EditBuffer__charPtr_at_ (progs_t *pr) } static void -bi_i_EditBuffer__getWord_ (progs_t *pr) +bi__i_EditBuffer__getWord_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -797,7 +797,7 @@ bi_i_EditBuffer__getWord_ (progs_t *pr) } static void -bi_i_EditBuffer__getLine_ (progs_t *pr) +bi__i_EditBuffer__getLine_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -811,7 +811,7 @@ bi_i_EditBuffer__getLine_ (progs_t *pr) } static void -bi_i_EditBuffer__getBOL_ (progs_t *pr) +bi__i_EditBuffer__getBOL_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -822,7 +822,7 @@ bi_i_EditBuffer__getBOL_ (progs_t *pr) } static void -bi_i_EditBuffer__getEOL_ (progs_t *pr) +bi__i_EditBuffer__getEOL_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -833,7 +833,7 @@ bi_i_EditBuffer__getEOL_ (progs_t *pr) } static void -bi_i_EditBuffer__getBOT (progs_t *pr) +bi__i_EditBuffer__getBOT (progs_t *pr) { //qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); //int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -843,7 +843,7 @@ bi_i_EditBuffer__getBOT (progs_t *pr) } static void -bi_i_EditBuffer__getEOT (progs_t *pr) +bi__i_EditBuffer__getEOT (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -853,7 +853,7 @@ bi_i_EditBuffer__getEOT (progs_t *pr) } static void -bi_i_EditBuffer__readString_ (progs_t *pr) +bi__i_EditBuffer__readString_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -868,7 +868,7 @@ bi_i_EditBuffer__readString_ (progs_t *pr) } static void -bi_i_EditBuffer__getChar_ (progs_t *pr) +bi__i_EditBuffer__getChar_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -882,7 +882,7 @@ bi_i_EditBuffer__getChar_ (progs_t *pr) } static void -bi_i_EditBuffer__putChar_at_ (progs_t *pr) +bi__i_EditBuffer__putChar_at_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -897,7 +897,7 @@ bi_i_EditBuffer__putChar_at_ (progs_t *pr) } static void -bi_i_EditBuffer__insertChar_at_ (progs_t *pr) +bi__i_EditBuffer__insertChar_at_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -912,7 +912,7 @@ bi_i_EditBuffer__insertChar_at_ (progs_t *pr) } static void -bi_i_EditBuffer__countLines_ (progs_t *pr) +bi__i_EditBuffer__countLines_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -924,7 +924,7 @@ bi_i_EditBuffer__countLines_ (progs_t *pr) } static void -bi_i_EditBuffer__search_for_direction_ (progs_t *pr) +bi__i_EditBuffer__search_for_direction_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -938,7 +938,7 @@ bi_i_EditBuffer__search_for_direction_ (progs_t *pr) } static void -bi_i_EditBuffer__isearch_for_direction_ (progs_t *pr) +bi__i_EditBuffer__isearch_for_direction_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -952,7 +952,7 @@ bi_i_EditBuffer__isearch_for_direction_ (progs_t *pr) } static void -bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) +bi__i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -972,7 +972,7 @@ bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) } static void -bi_i_EditBuffer__modified (progs_t *pr) +bi__i_EditBuffer__modified (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -981,7 +981,7 @@ bi_i_EditBuffer__modified (progs_t *pr) } static void -bi_i_EditBuffer__textSize (progs_t *pr) +bi__i_EditBuffer__textSize (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -990,7 +990,7 @@ bi_i_EditBuffer__textSize (progs_t *pr) } static void -bi_i_EditBuffer__saveFile_ (progs_t *pr) +bi__i_EditBuffer__saveFile_ (progs_t *pr) { qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; @@ -1015,43 +1015,47 @@ qwaq_ebresources_clear (progs_t *pr, void *data) editbuffer_reset (res); } +#define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - {"_i_EditBuffer__init", bi_i_EditBuffer__init, -1}, - {"_i_EditBuffer__initWithFile_", bi_i_EditBuffer__initWithFile_, -1}, - {"_i_EditBuffer__dealloc", bi_i_EditBuffer__dealloc, -1}, - {"_i_EditBuffer__nextChar_", bi_i_EditBuffer__nextChar_, -1}, - {"_i_EditBuffer__prevChar_", bi_i_EditBuffer__prevChar_, -1}, - {"_i_EditBuffer__nextNonSpace_", bi_i_EditBuffer__nextNonSpace_, -1}, - {"_i_EditBuffer__prevNonSpace_", bi_i_EditBuffer__prevNonSpace_, -1}, - {"_i_EditBuffer__isWord_", bi_i_EditBuffer__isWord_, -1}, - {"_i_EditBuffer__nextWord_", bi_i_EditBuffer__nextWord_, -1}, - {"_i_EditBuffer__prevWord_", bi_i_EditBuffer__prevWord_, -1}, - {"_i_EditBuffer__nextLine_", bi_i_EditBuffer__nextLine_, -1}, - {"_i_EditBuffer__prevLine_", bi_i_EditBuffer__prevLine_, -1}, - {"_i_EditBuffer__nextLine__", bi_i_EditBuffer__nextLine__, -1}, - {"_i_EditBuffer__prevLine__", bi_i_EditBuffer__prevLine__, -1}, - {"_i_EditBuffer__charPos_at_", bi_i_EditBuffer__charPos_at_, -1}, - {"_i_EditBuffer__charPtr_at_", bi_i_EditBuffer__charPtr_at_, -1}, - {"_i_EditBuffer__getWord_", bi_i_EditBuffer__getWord_, -1}, - {"_i_EditBuffer__getLine_", bi_i_EditBuffer__getLine_, -1}, - {"_i_EditBuffer__getBOL_", bi_i_EditBuffer__getBOL_, -1}, - {"_i_EditBuffer__getEOL_", bi_i_EditBuffer__getEOL_, -1}, - {"_i_EditBuffer__getBOT", bi_i_EditBuffer__getBOT, -1}, - {"_i_EditBuffer__getEOT", bi_i_EditBuffer__getEOT, -1}, - {"_i_EditBuffer__readString_", bi_i_EditBuffer__readString_, -1}, - {"_i_EditBuffer__getChar_", bi_i_EditBuffer__getChar_, -1}, - {"_i_EditBuffer__putChar_at_", bi_i_EditBuffer__putChar_at_, -1}, - {"_i_EditBuffer__insertChar_at_", bi_i_EditBuffer__insertChar_at_,-1}, - {"_i_EditBuffer__countLines_", bi_i_EditBuffer__countLines_, -1}, - {"_i_EditBuffer__search_for_direction_", - bi_i_EditBuffer__search_for_direction_, -1}, - {"_i_EditBuffer__isearch_for_direction_", - bi_i_EditBuffer__isearch_for_direction_,-1}, - {"_i_EditBuffer__formatLine_from_into_width_highlight_colors_", - bi_i_EditBuffer__formatLine_from_into_width_highlight_colors_, -1}, - {"_i_EditBuffer__modified", bi_i_EditBuffer__modified, -1}, - {"_i_EditBuffer__textSize", bi_i_EditBuffer__textSize, -1}, - {"_i_EditBuffer__saveFile_", bi_i_EditBuffer__saveFile_, -1}, + bi(_i_EditBuffer__init, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__initWithFile_, -1, 3, p(ptr), p(ptr), p(string)), + bi(_i_EditBuffer__dealloc, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__nextChar_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__prevChar_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__nextNonSpace_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__prevNonSpace_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__isWord_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__nextWord_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__prevWord_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__nextLine_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__prevLine_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__nextLine__, -1, 4, p(ptr), p(ptr), p(uint), p(uint)), + bi(_i_EditBuffer__prevLine__, -1, 4, p(ptr), p(ptr), p(uint), p(uint)), + bi(_i_EditBuffer__charPos_at_, -1, 4, p(ptr), p(ptr), p(uint), p(uint)), + bi(_i_EditBuffer__charPtr_at_, -1, 4, p(ptr), p(ptr), p(uint), p(uint)), + bi(_i_EditBuffer__getWord_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__getLine_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__getBOL_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__getEOL_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__getBOT, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__getEOT, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__readString_, -1, 3, p(ptr), p(ptr), P(1, 2)), + bi(_i_EditBuffer__getChar_, -1, 3, p(ptr), p(ptr), p(uint)), + bi(_i_EditBuffer__putChar_at_, -1, 4, p(ptr), p(ptr), p(int), p(uint)), + bi(_i_EditBuffer__insertChar_at_, -1, 4, p(ptr), p(ptr), p(int), p(uint)), + bi(_i_EditBuffer__countLines_, -1, 3, p(ptr), p(ptr), P(1, 2)), + bi(_i_EditBuffer__search_for_direction_, -1, + 5, p(ptr), p(ptr), P(1, 2), p(string), p(int)), + bi(_i_EditBuffer__isearch_for_direction_,-1, + 5, p(ptr), p(ptr), P(1, 2), p(string), p(int)), + bi(_i_EditBuffer__formatLine_from_into_width_highlight_colors_, -1, + 8, p(ptr), p(ptr), + p(uint), p(uint), p(ptr), p(uint), P(1, 2), P(1, 2)), + bi(_i_EditBuffer__modified, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__textSize, -1, 2, p(ptr), p(ptr)), + bi(_i_EditBuffer__saveFile_, -1, 3, p(ptr), p(ptr), p(string)), {} }; diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 847a13357..cd523b20a 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -120,15 +120,17 @@ bi_refresh_2d (progs_t *pr) } static void -bi_shutdown_ (progs_t *pr) +bi_shutdown (progs_t *pr) { Sys_Shutdown (); } +#define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"refresh", bi_refresh, -1}, - {"refresh_2d", bi_refresh_2d, -1}, - {"shutdown", bi_shutdown_, -1}, + bi(refresh, -1, 0), + bi(refresh_2d, -1, 1, p(func)), + bi(shutdown, -1, 0), {0} }; @@ -139,7 +141,7 @@ event_handler (const IE_event_t *ie_event, void *_pr) } static void -bi_shutdown (void *data) +BI_shutdown (void *data) { } @@ -155,7 +157,7 @@ BI_Graphics_Init (progs_t *pr) PI_Init (); PI_RegisterPlugins (client_plugin_list); - Sys_RegisterShutdown (bi_shutdown, pr); + Sys_RegisterShutdown (BI_shutdown, pr); VID_Init_Cvars (); IN_Init_Cvars (); diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 185998fde..955195b65 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -172,10 +172,12 @@ bi_traceoff (progs_t *pr) pr->pr_trace = false; } +#define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t common_builtins[] = { - {"printf", bi_printf, -1}, - {"traceon", bi_traceon, -1}, - {"traceoff", bi_traceoff, -1}, + bi(printf, -1, -2, p(string)), + bi(traceon, -1, 0), + bi(traceoff, -1, 0), {}, }; diff --git a/ruamoko/qwaq/builtins/term-input.c b/ruamoko/qwaq/builtins/term-input.c index 697cd2e7c..e8d136855 100644 --- a/ruamoko/qwaq/builtins/term-input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -868,11 +868,13 @@ bi_init_input (progs_t *pr) IE_Send_Event (&event); } +#define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"send_connected_devices", bi_send_connected_devices, -1}, - {"get_device_info", bi_get_device_info, -1}, - {"get_event", bi_get_event, -1}, - {"init_input", bi_init_input, -1}, + bi(send_connected_devices, -1, 0), + bi(get_device_info, -1, 1, p(int)), + bi(get_event, -1, 1, p(ptr)), + bi(init_input, -1, 0), {0} }; diff --git a/tools/qfcc/test/test-bi.c b/tools/qfcc/test/test-bi.c index bec2b247e..58b1e28d2 100644 --- a/tools/qfcc/test/test-bi.c +++ b/tools/qfcc/test/test-bi.c @@ -95,13 +95,15 @@ bi_remove (progs_t *pr) ED_Free (pr, ed); } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) static builtin_t builtins[] = { - {"printf", bi_printf, -1}, - {"errno", bi_errno, -1}, - {"strerror", bi_strerror, -1}, - {"exit", bi_exit, -1}, - {"spawn", bi_spawn, -1}, - {"remove", bi_remove, -1}, + bi(printf, -2, p(string)), + bi(errno, 0), + bi(strerror, 1, p(int)), + bi(exit, 1, p(int)), + bi(spawn, 0), + bi(remove, 1, p(entity)), {0} }; From a818fa4b8e9637d5124c918fdef2e02c2a80ab2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 00:13:44 +0900 Subject: [PATCH 2282/3664] [gamecode] Rearrange bfunction_t in preparation for param offsets The builtin and progs function data is overlaid so the extra data doesn't cause too much memory to be used (it's actually 8 bytes smaller now). The plan is to pre-compute the offsets based on the parameter size and alignment data. --- include/QF/progs.h | 24 ++++++++++++++++++------ libs/gamecode/pr_exec.c | 6 ++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 25f0d1a4e..bac575b87 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1221,13 +1221,25 @@ typedef struct { */ typedef struct { pr_int_t first_statement; - pr_int_t parm_start; - pr_int_t locals; - pr_uint_t profile; pr_int_t numparms; - dparmsize_t parm_size[PR_MAX_PARAMS]; - dfunction_t *descriptor; - builtin_proc func; + union { + struct { + dparmsize_t parm_size[PR_MAX_PARAMS]; + dfunction_t *descriptor; + pr_uint_t parm_start; + pr_uint_t locals; + pr_uint_t profile; + }; + struct { + // although Ruamoko progs support more than PR_MAX_PARAMS + // arguments, only the first PR_MAX_PARAMS parameter pointers + // are initialized. This keeps builtins meant for both ISAs + // simple as they either will never accept more tha PR_MAX_PARAMS + // arugments, or they'll be modified to do the right thing. + pr_ushort_t param_offsets[PR_MAX_PARAMS]; + builtin_proc func; + }; + }; } bfunction_t; /** Register a set of builtin functions with the VM. Different VMs within the diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 0d8424857..19507665c 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -284,9 +284,11 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) sizeof (pr_type_t) * f->locals); pr->localstack_used += f->locals; - if (pr_deadbeef_locals->int_val) - for (i = f->parm_start; i < f->parm_start + f->locals; i++) + if (pr_deadbeef_locals->int_val) { + for (pr_uint_t i = f->parm_start; i < f->parm_start + f->locals; i++) { pr->pr_globals[i].int_var = 0xdeadbeef; + } + } // copy parameters if (f->numparms >= 0) { From 9c51c3d2e1d0719906dc7d8ef26ac11b9a29815b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 00:20:05 +0900 Subject: [PATCH 2283/3664] [gamecode] Add a data pointer passed to builtin functions This is part of the work for #26 (Record resource pointer with builtin function data). Currently, the data pointer gets as far as the per-instance VM function table (I don't feel like tackling the job of converting all the builtin functions tonight). All the builtin modules that register a resources data block pass that block on to PR_RegisterBuiltins. --- include/QF/progs.h | 8 +++++++- libs/audio/snd_progs.c | 2 +- libs/console/bi_inputline.c | 2 +- libs/console/menu.c | 2 +- libs/gamecode/pr_builtins.c | 15 +++++++++++---- libs/gib/bi_gib.c | 5 ++--- libs/ruamoko/pr_cmds.c | 2 +- libs/ruamoko/rua_cbuf.c | 2 +- libs/ruamoko/rua_cmd.c | 4 ++-- libs/ruamoko/rua_cvar.c | 3 +-- libs/ruamoko/rua_hash.c | 2 +- libs/ruamoko/rua_input.c | 8 ++++---- libs/ruamoko/rua_keys.c | 2 +- libs/ruamoko/rua_math.c | 2 +- libs/ruamoko/rua_mersenne.c | 2 +- libs/ruamoko/rua_msgbuf.c | 2 +- libs/ruamoko/rua_obj.c | 3 +-- libs/ruamoko/rua_plist.c | 2 +- libs/ruamoko/rua_qfile.c | 6 +++--- libs/ruamoko/rua_qfs.c | 2 +- libs/ruamoko/rua_runtime.c | 2 +- libs/ruamoko/rua_script.c | 3 +-- libs/ruamoko/rua_set.c | 2 +- libs/ruamoko/rua_stdlib.c | 2 +- libs/ruamoko/rua_string.c | 2 +- libs/video/renderer/r_progs.c | 2 +- nq/source/sv_pr_cmds.c | 2 +- qw/source/sv_pr_cmds.c | 2 +- qw/source/sv_pr_cpqw.c | 2 +- qw/source/sv_pr_qwe.c | 2 +- qw/source/sv_user.c | 2 +- ruamoko/qwaq/builtins/curses.c | 2 +- ruamoko/qwaq/builtins/debug.c | 2 +- ruamoko/qwaq/builtins/editbuffer.c | 2 +- ruamoko/qwaq/builtins/graphics.c | 2 +- ruamoko/qwaq/builtins/main.c | 2 +- ruamoko/qwaq/builtins/term-input.c | 2 +- tools/qfcc/test/test-bi.c | 2 +- 38 files changed, 61 insertions(+), 52 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index bac575b87..066a479af 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1208,6 +1208,9 @@ typedef struct { /// The encoding is the same as for progs functions, with 3:5 for /// alignment:size (size 0 means 32 words). dparmsize_t params[PR_MAX_PARAMS]; + + /// Data passed to builtin functions. Set by PR_RegisterBuiltins + void *data; } builtin_t; #define PR_PARAM(type) { \ @@ -1238,6 +1241,7 @@ typedef struct { // arugments, or they'll be modified to do the right thing. pr_ushort_t param_offsets[PR_MAX_PARAMS]; builtin_proc func; + void *data; ///< extra data passed to the builtin }; }; } bfunction_t; @@ -1247,8 +1251,10 @@ typedef struct { for the same VM, but redefining a builtin is an error. \param pr pointer to ::progs_t VM struct \param builtins array of builtin_t builtins + \param data pointer to builtin-specific data. Usually the resources + struct registered with PR_Resources_Register */ -void PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins); +void PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins, void *data); /** Lookup a builtin function referred by name. \param pr pointer to ::progs_t VM struct diff --git a/libs/audio/snd_progs.c b/libs/audio/snd_progs.c index 8e77bdde7..912686412 100644 --- a/libs/audio/snd_progs.c +++ b/libs/audio/snd_progs.c @@ -57,5 +57,5 @@ static builtin_t builtins[] = { VISIBLE void S_Progs_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index af8fba096..69494450f 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -328,7 +328,7 @@ InputLine_Progs_Init (progs_t *pr) il_resources_t *res = calloc (1, sizeof (il_resources_t)); PR_Resources_Register (pr, "InputLine", res, bi_il_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } VISIBLE void diff --git a/libs/console/menu.c b/libs/console/menu.c index aea52cefc..fd34f6a68 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -599,7 +599,7 @@ Menu_Init (void) menu_hash = Hash_NewTable (61, menu_get_key, menu_free, 0, 0); - PR_RegisterBuiltins (&menu_pr_state, builtins); + PR_RegisterBuiltins (&menu_pr_state, builtins, 0); RUA_Init (&menu_pr_state, 3); diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index 150b43932..ab5088b9b 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -102,7 +102,7 @@ bi_no_function (progs_t *pr) } VISIBLE void -PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins) +PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins, void *data) { builtin_t *bi; int count; @@ -135,21 +135,25 @@ PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins) builtins = bi; while (builtins->name) { - if (builtins->binum == 0 || builtins->binum >= PR_AUTOBUILTIN) + if (builtins->binum == 0 || builtins->binum >= PR_AUTOBUILTIN) { PR_Error (pr, "bad builtin number: %s = #%d", builtins->name, builtins->binum); + } - if (builtins->binum < 0) + if (builtins->binum < 0) { builtins->binum = builtin_next (pr); + } if ((bi = Hash_Find (pr->builtin_hash, builtins->name)) - || (bi = Hash_FindElement (pr->builtin_num_hash, builtins))) + || (bi = Hash_FindElement (pr->builtin_num_hash, builtins))) { PR_Error (pr, "builtin %s = #%d already defined (%s = #%d)", builtins->name, builtins->binum, bi->name, bi->binum); + } Hash_Add (pr->builtin_hash, builtins); Hash_AddElement (pr->builtin_num_hash, builtins); + builtins->data = data; builtins++; } @@ -231,6 +235,9 @@ PR_RelocateBuiltins (progs_t *pr) } func->first_statement = desc->first_statement; func->func = proc; + if (bi) { + func->data = bi->data; + } } if (bad) { Sys_Printf ("PR_RelocateBuiltins: %s: progs may not work due to " diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index 28d5401c0..8c0deb4e8 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -193,11 +193,10 @@ GIB_Progs_Init (progs_t *pr) bi_gib_resources_t *res = malloc (sizeof (bi_gib_resources_t)); res->builtins = 0; - PR_Resources_Register (pr, "GIB", res, bi_gib_builtin_clear); - bi_gib_builtins = Hash_NewTable (1021, bi_gib_builtin_get_key, bi_gib_builtin_free, 0, pr->hashlink_freelist); - PR_RegisterBuiltins (pr, builtins); + PR_Resources_Register (pr, "GIB", res, bi_gib_builtin_clear); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 7c70b82d6..24d3f6294 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -628,5 +628,5 @@ static builtin_t builtins[] = { VISIBLE void PR_Cmds_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_cbuf.c b/libs/ruamoko/rua_cbuf.c index 0a3870d80..7f96f4783 100644 --- a/libs/ruamoko/rua_cbuf.c +++ b/libs/ruamoko/rua_cbuf.c @@ -109,7 +109,7 @@ RUA_Cbuf_Init (progs_t *pr, int secure) { cbuf_resources_t *res = calloc (sizeof (cbuf_resources_t), 1); PR_Resources_Register (pr, "Cbuf", res, bi_cbuf_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } VISIBLE void diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index 8be474e50..c325e3c3a 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -161,11 +161,11 @@ RUA_Cmd_Init (progs_t *pr, int secure) cmd_resources_t *res = calloc (1, sizeof (cmd_resources_t)); res->cmds = 0; - PR_Resources_Register (pr, "Cmd", res, bi_cmd_clear); if (!bi_cmds) bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0, pr->hashlink_freelist); - PR_RegisterBuiltins (pr, builtins); + PR_Resources_Register (pr, "Cmd", res, bi_cmd_clear); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_cvar.c b/libs/ruamoko/rua_cvar.c index 4cf68ee4f..12cc3fca1 100644 --- a/libs/ruamoko/rua_cvar.c +++ b/libs/ruamoko/rua_cvar.c @@ -257,6 +257,5 @@ RUA_Cvar_Init (progs_t *pr, int secure) res->aliases = 0; PR_Resources_Register (pr, "Cvar", res, bi_cvar_clear); - - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index a1b277706..c2cf1f8f7 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -389,5 +389,5 @@ RUA_Hash_Init (progs_t *pr, int secure) res->tabs = 0; PR_Resources_Register (pr, "Hash", res, bi_hash_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index e93d88085..e54dc73e2 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -497,17 +497,17 @@ void RUA_Input_Init (progs_t *pr, int secure) { input_resources_t *res = calloc (sizeof (input_resources_t), 1); - PR_Resources_Register (pr, "input", res, bi_input_clear); res->cookie_super = new_memsuper (); res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, &res->hash_links); Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies); + PR_Resources_Register (pr, "input", res, bi_input_clear); if (secure & 2) { - PR_RegisterBuiltins (pr, secure_builtins); + PR_RegisterBuiltins (pr, secure_builtins, res); } else { - PR_RegisterBuiltins (pr, insecure_builtins); + PR_RegisterBuiltins (pr, insecure_builtins, res); } - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_keys.c b/libs/ruamoko/rua_keys.c index 2f09ae227..d6e9acaa8 100644 --- a/libs/ruamoko/rua_keys.c +++ b/libs/ruamoko/rua_keys.c @@ -181,5 +181,5 @@ static builtin_t builtins[] = { void RUA_Key_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_math.c b/libs/ruamoko/rua_math.c index 21d96fb6d..2d7e09398 100644 --- a/libs/ruamoko/rua_math.c +++ b/libs/ruamoko/rua_math.c @@ -375,5 +375,5 @@ static builtin_t builtins[] = { void RUA_Math_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c index 200b56785..c55c495c1 100644 --- a/libs/ruamoko/rua_mersenne.c +++ b/libs/ruamoko/rua_mersenne.c @@ -163,5 +163,5 @@ RUA_Mersenne_Init (progs_t *pr, int secure) mtwist_resources_t *res = calloc (1, sizeof (mtwist_resources_t)); PR_Resources_Register (pr, "Mersenne Twister", res, bi_mtwist_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index 5d28bf53c..c2420ed99 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -448,5 +448,5 @@ RUA_MsgBuf_Init (progs_t *pr, int secure) msgbuf_resources_t *res = calloc (sizeof (msgbuf_resources_t), 1); PR_Resources_Register (pr, "MsgBuf", res, bi_msgbuf_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 819f9c3c8..2fe0b85f7 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -2245,8 +2245,7 @@ RUA_Obj_Init (progs_t *pr, int secure) load_methods_compare); PR_Resources_Register (pr, "RUA_ObjectiveQuakeC", probj, rua_obj_cleanup); - - PR_RegisterBuiltins (pr, obj_methods); + PR_RegisterBuiltins (pr, obj_methods, probj); PR_AddLoadFunc (pr, rua_obj_init_runtime); } diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 1f27c6b74..4aae2db06 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -479,5 +479,5 @@ RUA_Plist_Init (progs_t *pr, int secure) Hash_SetHashCompare (res->plist_tab, plist_get_hash, plist_compare); PR_Resources_Register (pr, "plist", res, bi_plist_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index afe23a4e7..1fee454dc 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -390,9 +390,9 @@ RUA_QFile_Init (progs_t *pr, int secure) PR_Resources_Register (pr, "QFile", res, bi_qfile_clear); if (secure) { - PR_RegisterBuiltins (pr, secure_builtins); + PR_RegisterBuiltins (pr, secure_builtins, res); } else { - PR_RegisterBuiltins (pr, insecure_builtins); + PR_RegisterBuiltins (pr, insecure_builtins, res); } - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_qfs.c b/libs/ruamoko/rua_qfs.c index 9c34d6abe..8f36c4528 100644 --- a/libs/ruamoko/rua_qfs.c +++ b/libs/ruamoko/rua_qfs.c @@ -206,5 +206,5 @@ static builtin_t builtins[] = { void RUA_QFS_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_runtime.c b/libs/ruamoko/rua_runtime.c index 54b67b205..5a1c906ad 100644 --- a/libs/ruamoko/rua_runtime.c +++ b/libs/ruamoko/rua_runtime.c @@ -80,5 +80,5 @@ static builtin_t builtins[] = { void RUA_Runtime_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index 4a90a99e3..8cafdb387 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -207,6 +207,5 @@ RUA_Script_Init (progs_t *pr, int secure) script_resources_t *res = calloc (1, sizeof (script_resources_t)); PR_Resources_Register (pr, "Script", res, bi_script_clear); - - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 647f7716b..b1b3a7dee 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -747,5 +747,5 @@ RUA_Set_Init (progs_t *pr, int secure) res->sets = 0; PR_Resources_Register (pr, "Set", res, res_set_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_stdlib.c b/libs/ruamoko/rua_stdlib.c index 19dd7bc7e..fa8489d1c 100644 --- a/libs/ruamoko/rua_stdlib.c +++ b/libs/ruamoko/rua_stdlib.c @@ -171,5 +171,5 @@ static builtin_t builtins[] = { void RUA_Stdlib_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 21006ac42..e01ab9716 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -309,5 +309,5 @@ static builtin_t builtins[] = { void RUA_String_Init (progs_t *pr, int secure) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 2fbaa6e28..87cd3e513 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -353,5 +353,5 @@ R_Progs_Init (progs_t *pr) pr->hashlink_freelist); PR_Resources_Register (pr, "Draw", res, bi_draw_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 5c98aa5d9..38755c8f9 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -1564,5 +1564,5 @@ SV_PR_Cmds_Init () PR_Cmds_Init (&sv_pr_state); - PR_RegisterBuiltins (&sv_pr_state, builtins); + PR_RegisterBuiltins (&sv_pr_state, builtins, 0); } diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index fd4841d7a..9e3ffac8f 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -2070,5 +2070,5 @@ SV_PR_Cmds_Init () bi = PR_FindBuiltin (&sv_pr_state, "cvar"); bi->proc = PF_sv_cvar; - PR_RegisterBuiltins (&sv_pr_state, builtins); + PR_RegisterBuiltins (&sv_pr_state, builtins, 0); } diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index 160fb090c..32e82e7b9 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -855,6 +855,6 @@ cpqw_load (progs_t *pr) void SV_PR_CPQW_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); PR_AddLoadFunc (pr, cpqw_load); } diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index 521bb721d..c67f695fc 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -589,6 +589,6 @@ qwe_load (progs_t *pr) void SV_PR_QWE_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); PR_AddLoadFunc (pr, qwe_load); } diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 1160f673a..126c84ef8 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -2012,7 +2012,7 @@ SV_UserInit (void) { ucmd_table = Hash_NewTable (251, ucmds_getkey, ucmds_free, 0, 0); Hash_SetHashCompare (ucmd_table, ucmd_get_hash, ucmd_compare); - PR_RegisterBuiltins (&sv_pr_state, builtins); + PR_RegisterBuiltins (&sv_pr_state, builtins, 0); cl_rollspeed = Cvar_Get ("cl_rollspeed", "200", CVAR_NONE, NULL, "How quickly a player straightens out after " "strafing"); diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index a3f83fceb..dfd3d1e40 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -1957,6 +1957,6 @@ BI_Curses_Init (progs_t *pr) qwaq_init_pipe (&res->results); PR_Resources_Register (pr, "curses", res, bi_curses_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); Sys_RegisterShutdown (bi_shutdown, pr); } diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 98c7294c7..c9da1e923 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -688,7 +688,7 @@ QWAQ_Debug_Init (progs_t *pr) PR_AddLoadFunc (pr, qwaq_debug_load); PR_Resources_Register (pr, "qwaq-debug", debug, qwaq_debug_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, debug); } void diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index db3237a2e..3a8fbdf3a 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -1066,5 +1066,5 @@ QWAQ_EditBuffer_Init (progs_t *pr) res->pr = pr; PR_Resources_Register (pr, "qwaq-editbuffer", res, qwaq_ebresources_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); } diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index cd523b20a..746332cc4 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -151,7 +151,7 @@ BI_Graphics_Init (progs_t *pr) qwaq_thread_t *thread = PR_Resources_Find (pr, "qwaq_thread"); byte *basepal, *colormap; - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); QFS_Init (thread->hunk, "nq"); PI_Init (); diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 955195b65..0215ced3f 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -184,7 +184,7 @@ static builtin_t common_builtins[] = { static void common_builtins_init (progs_t *pr) { - PR_RegisterBuiltins (pr, common_builtins); + PR_RegisterBuiltins (pr, common_builtins, 0); } static void diff --git a/ruamoko/qwaq/builtins/term-input.c b/ruamoko/qwaq/builtins/term-input.c index e8d136855..8b34a22e5 100644 --- a/ruamoko/qwaq/builtins/term-input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -916,6 +916,6 @@ BI_TermInput_Init (progs_t *pr) qwaq_init_cond (&res->events.cond); PR_Resources_Register (pr, "input", res, bi_input_clear); - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, res); Sys_RegisterShutdown (bi_input_shutdown, pr); } diff --git a/tools/qfcc/test/test-bi.c b/tools/qfcc/test/test-bi.c index 58b1e28d2..5e6a093ef 100644 --- a/tools/qfcc/test/test-bi.c +++ b/tools/qfcc/test/test-bi.c @@ -110,5 +110,5 @@ static builtin_t builtins[] = { void BI_Init (progs_t *pr) { - PR_RegisterBuiltins (pr, builtins); + PR_RegisterBuiltins (pr, builtins, 0); } From 1f802716e1685467d1451920241b580f36cd6426 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 12:48:02 +0900 Subject: [PATCH 2284/3664] [qfcc] Pass initialize_def the symtab to use as a parameter This takes care of an old FIXME. --- tools/qfcc/include/def.h | 4 +++- tools/qfcc/source/def.c | 25 +++++++++++++------------ tools/qfcc/source/expr_obj.c | 3 ++- tools/qfcc/source/function.c | 10 +++------- tools/qfcc/source/qc-parse.y | 17 +++++++++++------ tools/qfcc/source/qp-parse.y | 6 ++++-- tools/qfcc/source/switch.c | 4 +++- 7 files changed, 39 insertions(+), 30 deletions(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 1477cc7e3..6ecb5aae8 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -40,6 +40,7 @@ ///@{ struct symbol_s; +struct symtab_s; struct expr_s; /** Represent a memory location that holds a QuakeC/Ruamoko object. @@ -242,10 +243,11 @@ void def_to_ddef (def_t *def, ddef_t *ddef, int aux); \param init If not null, the expressions to use to initialize the def. \param space The space from which to allocate space for the def. \param storage The storage class of the def. + \param symtab The symbol table into which the def will be placed. */ void initialize_def (struct symbol_s *sym, struct expr_s *init, struct defspace_s *space, - storage_class_t storage); + storage_class_t storage, struct symtab_s *symtab); /** Determine if two defs overlap. diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 2cc92d4aa..8472e1df4 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -412,7 +412,7 @@ init_elements (struct def_s *def, expr_t *eles) } static void -init_vector_components (symbol_t *vector_sym, int is_field) +init_vector_components (symbol_t *vector_sym, int is_field, symtab_t *symtab) { expr_t *vector_expr; int i; @@ -425,9 +425,9 @@ init_vector_components (symbol_t *vector_sym, int is_field) const char *name; name = va (0, "%s_%s", vector_sym->name, fields[i]); - sym = symtab_lookup (current_symtab, name); + sym = symtab_lookup (symtab, name); if (sym) { - if (sym->table == current_symtab) { + if (sym->table == symtab) { if (sym->sy_type != sy_expr) { error (0, "%s redefined", name); sym = 0; @@ -461,12 +461,13 @@ init_vector_components (symbol_t *vector_sym, int is_field) sym->sy_type = sy_expr; sym->s.expr = expr; if (!sym->table) - symtab_addsymbol (current_symtab, sym); + symtab_addsymbol (symtab, sym); } } static void -init_field_def (def_t *def, expr_t *init, storage_class_t storage) +init_field_def (def_t *def, expr_t *init, storage_class_t storage, + symtab_t *symtab) { type_t *type = (type_t *) dereference_type (def->type);//FIXME cast def_t *field_def; @@ -499,7 +500,7 @@ init_field_def (def_t *def, expr_t *init, storage_class_t storage) } // no support for initialized field vector componets (yet?) if (is_vector(type) && options.code.vector_components) - init_vector_components (field_sym, 1); + init_vector_components (field_sym, 1, symtab); } else if (init->type == ex_symbol) { symbol_t *sym = init->e.symbol; symbol_t *field = symtab_lookup (pr.entity_fields, sym->name); @@ -523,12 +524,12 @@ num_elements (expr_t *e) void initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, - storage_class_t storage) + storage_class_t storage, symtab_t *symtab) { - symbol_t *check = symtab_lookup (current_symtab, sym->name); + symbol_t *check = symtab_lookup (symtab, sym->name); reloc_t *relocs = 0; - if (check && check->table == current_symtab) { + if (check && check->table == symtab) { if (check->sy_type != sy_var || !type_same (check->type, sym->type)) { error (0, "%s redefined", sym->name); } else { @@ -549,7 +550,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, } sym->sy_type = sy_var; if (!sym->table) - symtab_addsymbol (current_symtab, sym); + symtab_addsymbol (symtab, sym); if (sym->s.def && sym->s.def->external) { //FIXME this really is not the right way @@ -567,10 +568,10 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, reloc_attach_relocs (relocs, &sym->s.def->relocs); } if (is_vector(sym->type) && options.code.vector_components) - init_vector_components (sym, 0); + init_vector_components (sym, 0, symtab); if (sym->type->type == ev_field && storage != sc_local && storage != sc_param) - init_field_def (sym->s.def, init, storage); + init_field_def (sym->s.def, init, storage, symtab); if (storage == sc_extern) { if (init) error (0, "initializing external variable"); diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index 0e8a8d53e..6a8bedebf 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -156,7 +156,8 @@ super_expr (class_type_t *class_type) sym = symtab_lookup (current_symtab, ".super"); if (!sym || sym->table != current_symtab) { sym = new_symbol_type (".super", &type_super); - initialize_def (sym, 0, current_symtab->space, sc_local); + initialize_def (sym, 0, current_symtab->space, sc_local, + current_symtab); } super = new_symbol_expr (sym); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index ac148bf74..189f6cf90 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -494,7 +494,6 @@ build_scope (symbol_t *fsym, symtab_t *parent) symbol_t *param; symtab_t *parameters; symtab_t *locals; - symtab_t *cs = current_symtab;//FIXME check_function (fsym); @@ -508,8 +507,6 @@ build_scope (symbol_t *fsym, symtab_t *parent) locals->space = defspace_new (ds_virtual); fsym->s.func->locals = locals; - current_symtab = locals;//FIXME - if (!fsym->s.func) { internal_error (0, "function %s not defined", fsym->name); } @@ -518,7 +515,7 @@ build_scope (symbol_t *fsym, symtab_t *parent) } if (fsym->s.func->type->t.func.num_params < 0) { args = new_symbol_type (".args", &type_va_list); - initialize_def (args, 0, parameters->space, sc_param); + initialize_def (args, 0, parameters->space, sc_param, locals); } for (p = fsym->params, i = 0; p; p = p->next) { @@ -531,18 +528,17 @@ build_scope (symbol_t *fsym, symtab_t *parent) p->name = save_string (""); } param = new_symbol_type (p->name, p->type); - initialize_def (param, 0, parameters->space, sc_param); + initialize_def (param, 0, parameters->space, sc_param, locals); i++; } if (args) { while (i < PR_MAX_PARAMS) { param = new_symbol_type (va (0, ".par%d", i), &type_param); - initialize_def (param, 0, parameters->space, sc_param); + initialize_def (param, 0, parameters->space, sc_param, locals); i++; } } - current_symtab = cs; } function_t * diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index c0d7d93c0..709470e0c 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -554,7 +554,8 @@ external_decl $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { - initialize_def ($1, 0, current_symtab->space, spec.storage); + initialize_def ($1, 0, current_symtab->space, spec.storage, + current_symtab); if ($1->s.def) $1->s.def->nosave |= spec.nosave; } @@ -570,7 +571,8 @@ external_decl $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); symtab_addsymbol (current_symtab, $1); } else { - initialize_def ($1, $2, current_symtab->space, spec.storage); + initialize_def ($1, $2, current_symtab->space, spec.storage, + current_symtab); if ($1->s.def) $1->s.def->nosave |= spec.nosave; } @@ -1152,7 +1154,7 @@ decl if (sc == sc_static) space = pr.near_data; $1->type = find_type (append_type ($1->type, spec.type)); - initialize_def ($1, $2, space, sc); + initialize_def ($1, $2, space, sc, current_symtab); if ($1->s.def) $1->s.def->nosave |= spec.nosave; } @@ -1214,7 +1216,8 @@ non_code_func if (local_expr) { symbol_t *sym = $0; specifier_t spec = $-1; - initialize_def (sym, $2, current_symtab->space, spec.storage); + initialize_def (sym, $2, current_symtab->space, spec.storage, + current_symtab); if (sym->s.def) sym->s.def->nosave |= spec.nosave; } else { @@ -1235,7 +1238,8 @@ non_code_func if (sym->sy_type == sy_func) make_function (sym, 0, sym->table->space, spec.storage); } else { - initialize_def (sym, 0, current_symtab->space, spec.storage); + initialize_def (sym, 0, current_symtab->space, spec.storage, + current_symtab); if (sym->s.def) sym->s.def->nosave |= spec.nosave; } @@ -1524,7 +1528,8 @@ init_var_decl specifier_t spec = $0; $1->type = find_type (append_type ($1->type, spec.type)); $1->sy_type = sy_var; - initialize_def ($1, 0, current_symtab->space, spec.storage); + initialize_def ($1, 0, current_symtab->space, spec.storage, + current_symtab); $$ = assign_expr (new_symbol_expr ($1), $2); } ; diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index a36f27910..db0274ce4 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -199,7 +199,8 @@ program_head { symbol_t *sym = new_symbol ("ExitCode"); sym->type = &type_int; - initialize_def (sym, 0, current_symtab->space, sc_global); + initialize_def (sym, 0, current_symtab->space, sc_global, + current_symtab); if (sym->s.def) { sym->s.def->nosave = 1; } @@ -234,7 +235,8 @@ declarations while ($3) { symbol_t *next = $3->next; $3->type = $5; - initialize_def ($3, 0, current_symtab->space, current_storage); + initialize_def ($3, 0, current_symtab->space, current_storage, + current_symtab); $3 = next; } } diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 9f245807a..10b8dc342 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -49,6 +49,7 @@ #include "tools/qfcc/include/options.h" #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" #include "tools/qfcc/include/switch.h" #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" @@ -348,7 +349,8 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, table_sym = new_symbol_type (table_name, array_type (&type_int, high - low + 1)); - initialize_def (table_sym, table_init, pr.near_data, sc_static); + initialize_def (table_sym, table_init, pr.near_data, sc_static, + current_symtab); table_expr = new_symbol_expr (table_sym); if (tree->left) { From 00b7bced7f5d5c869e0064245e08dc730ff4b3c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 12:50:15 +0900 Subject: [PATCH 2285/3664] [gamecode] Rework PR_RESET_PARAMS to use PR_SetupParams PR_SetupParams is new and sets up the parameter pointers so older code that expects only up to 8 parameter will work with both v6p and Ruamoko progs without having to check what progs are running. PR_SetupParams is useful even when Ruamoko progs are expected as it reserves the required space (respecting alignment) on the stack and returns a pointer to the top (bottom? confusing) of the stack. PR_PushFrame and PR_PopFrame need to be used around PR_SetupParams, regardless of using temp strings, to avoid a stack leak (need to do an audit). --- include/QF/progs.h | 42 +++++++++++++++++++++++++++++++++++------ libs/gamecode/pr_exec.c | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 066a479af..78e9913c9 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -82,15 +82,13 @@ void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(PRI \warning Failure to use this macro before assigning to the P_* macros can cause corruption of the VM data due to "register" based calling. Can be safely ignored for parameterless functions, or forwarding parameters - though a builtin. + though a builtin. However, it is ok (and encouraged) to call + PR_SetupParams instead, as this macro calls PR_SetupParams with + PR_MAX_PARAMS and 1 for the alignment. \hideinitializer */ -#define PR_RESET_PARAMS(pr) \ - do { \ - (pr)->pr_params[0] = (pr)->pr_real_params[0]; \ - (pr)->pr_params[1] = (pr)->pr_real_params[1]; \ - } while (0) +#define PR_RESET_PARAMS(pr) PR_SetupParams (pr, PR_MAX_PARAMS, 1) /** \name Detouring Function Calls @@ -155,6 +153,38 @@ void PR_RestoreParams (progs_t *pr, pr_stashed_params_t *params); */ void PR_PushFrame (progs_t *pr); +/** Reserve space on the data stack and set up the param pointers. + + For v6p progs, this only sets up the param pointers as v6p progs do not + have a data stack. + + For Ruamoko progs, space for at least \a num_params (each being 4 words) + is created on the stack, with a minimum alignment of min_alignment words, + or 4, whichever is larger. + + \param pr pointer to ::progs_t VM struct + \param num_params Number of parameter slots needed for the function call. + Each slot is 4 words. dvec4 and lvec4 parameters require + 8 words and must be 8-word aligned. dvec3 and lvec3 + also require 8 words due to the minimum 4 word alignment, + but have no alignment requirements themselves. Be sure to + take this into account in size calculations. + \param min_alignment Minimum number of words to which the stack will be + aligned. Must be a power of two. Note that when passing + dvec4 or lvec4 parameters, they have a hardware-enforced + requirement of 8 word alignment. This means that for + something like (int, lvec4), there will be an unused + parameter slot between the int and the lvec4. + Ignored for v6p progs. + \return Pointer to the base of the created parameter area. For + v6p progs, this is just .param_0, but for Ruamoko progs + this will be the current top of the the data stack after + adjustment for the parameter space. + \note Attempting to pass more than PR_MAX_PARAMS parameters to v6p progs + is a hard error. +*/ +pr_type_t *PR_SetupParams (progs_t *pr, int num_params, int min_alignment); + /** Pop an execution frame from the VM stack. Restores execution state. Also frees any temporary strings allocated in this frame (via PR_FreeTempStrings()). diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 19507665c..a78b01f9a 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -458,6 +458,9 @@ PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr) static void check_stack_pointer (progs_t *pr, pr_ptr_t stack, int size) { + if (stack & 3) { + PR_RunError (pr, "Progs stack not aligned"); + } if (stack < pr->stack_bottom) { PR_RunError (pr, "Progs stack overflow"); } @@ -466,6 +469,36 @@ check_stack_pointer (progs_t *pr, pr_ptr_t stack, int size) } } +VISIBLE pr_type_t * +PR_SetupParams (progs_t *pr, int num_params, int min_alignment) +{ + if (pr->progs->version < PROG_VERSION) { + if (num_params > PR_MAX_PARAMS) { + PR_Error (pr, "attempt to settup more than %d params", + PR_MAX_PARAMS); + } + pr->pr_params[0] = pr->pr_real_params[0]; + pr->pr_params[1] = pr->pr_real_params[1]; + return pr->pr_real_params[0]; + } + int offset = num_params * 4; + if (min_alignment < 4) { + min_alignment = 4; + } + pr_ptr_t mask = ~(min_alignment - 1); + pr_ptr_t stack = (*pr->globals.stack - offset) & mask; + if (pr_boundscheck->int_val) { + check_stack_pointer (pr, stack, 0); + } + *pr->globals.stack = stack; + pr->pr_params[0] = pr->pr_globals + stack; + num_params = min (num_params, PR_MAX_PARAMS); + for (int i = 1; i < num_params; i++) { + pr->pr_params[i] = pr->pr_params[0] + i * 4; + } + return pr->pr_params[0]; +} + static inline void pr_memset (pr_type_t *dst, int val, pr_uint_t count) { From 739c98fe213734a6711cb10165c30ba8b50c035b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 16:42:13 +0900 Subject: [PATCH 2286/3664] [qfcc] Add adjstk and with to dot_expr And be more informative with "bad" expression types (print the name if it's just that I haven't added a printer for a valid type). --- tools/qfcc/source/dot_expr.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 0074aa328..3b918ca12 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -633,6 +633,27 @@ print_memset (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) dasprintf (dstr, "%*se_%p [label=\"memset\"];\n", indent, "", e); } +static void +print_adjstk (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + dasprintf (dstr, "%*se_%p [label=\"adjstk %d:%d\\n%d\"];\n", indent, "", e, + e->e.adjstk.mode, e->e.adjstk.offset, e->line); +} + +static void +print_with (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + expr_t *with = e->e.with.with; + + _print_expr (dstr, with, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, with); + dasprintf (dstr, "%*se_%p [label=\"with %d:%d\\n%d\"];\n", indent, "", e, + e->e.with.mode, e->e.with.reg, e->line); +} + static void _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -659,6 +680,8 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_assign] = print_assign, [ex_branch] = print_branch, [ex_return] = print_return, + [ex_adjstk] = print_adjstk, + [ex_with] = print_with, }; int indent = level * 2 + 2; @@ -671,8 +694,12 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->printid = id; if ((int) e->type < 0 || e->type >= ex_count || !print_funcs[e->type]) { - dasprintf (dstr, "%*se_%p [label=\"(bad expr type)\\n%d\"];\n", - indent, "", e, e->line); + const char *type = va (0, "%d", e->type); + if (e->type >= 0 && e->type < ex_count) { + type = expr_names[e->type]; + } + dasprintf (dstr, "%*se_%p [label=\"(bad expr type: %s)\\n%d\"];\n", + indent, "", e, type, e->line); return; } print_funcs[e->type] (dstr, e, level, id, next); From 9fc8f14be6677fdb2179ee71759cdb031e54666c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 16:44:48 +0900 Subject: [PATCH 2287/3664] [qfcc] Put the stack frame exprs into the statements block dot_expr doesn't follow an expression's next pointer on its own. make_statements was fine, which is why I didn't notice the mistake until now. --- tools/qfcc/source/expr.c | 22 ++++++++++++++++++++++ tools/qfcc/source/function.c | 6 ++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c0b291789..48476ab89 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1419,6 +1419,28 @@ append_expr (expr_t *block, expr_t *e) return block; } +expr_t * +prepend_expr (expr_t *block, expr_t *e) +{ + if (block->type != ex_block) + internal_error (block, "not a block expression"); + + if (!e || e->type == ex_error) + return block; + + if (e->next) + internal_error (e, "append_expr: expr loop detected"); + + e->next = block->e.block.head; + block->e.block.head = e; + + if (block->e.block.tail == &block->e.block.head) { + block->e.block.tail = &e->next; + } + + return block; +} + static symbol_t * get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2) { diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 189f6cf90..82982b955 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -677,16 +677,14 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) if (options.code.progsversion == PROG_VERSION) { expr_t *e; e = new_with_expr (2, LOCALS_REG, new_short_expr (0)); - e->next = statements; e->file = func->def->file; e->line = func->def->line; - statements = e; + prepend_expr (statements, e); e = new_adjstk_expr (0, 0); - e->next = statements; e->file = func->def->file; e->line = func->def->line; - statements = e; + prepend_expr (statements, e); func->temp_reg = LOCALS_REG; for (def_t *def = func->locals->space->defs; def; def = def->next) { From b663fecd4ea5f4dcfe79af38625247f0329efacb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 16:46:49 +0900 Subject: [PATCH 2288/3664] [gamecode] Use PR_SetupParameters for rua called builtins It's a bit heavy-handed as it sets all the param pointers, but simple (no varargs) functions are working nicely in Ruamoko. --- libs/gamecode/pr_exec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index a78b01f9a..519808418 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -439,6 +439,9 @@ PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr) f = pr->function_table + fnum; if (f->first_statement < 0) { // negative statements are built in functions + if (pr->progs->version == PROG_VERSION) { + PR_SetupParams (pr, 0, 0); + } if (pr->pr_trace && !pr->debug_handler) { Sys_Printf ("Calling builtin %s @ %p\n", PR_GetString (pr, f->descriptor->name), f->func); From 5cf79243529ea770d5ee465f6baa026786e76a94 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 16:50:15 +0900 Subject: [PATCH 2289/3664] [qfcc] Improve dags handling of auxiliary use ops The aux use ops need to be counted and given nodes explicitly as they may refer to defs that are not accessed by other statements other than by aliases, and those aliases need to be marked live as well as the used def. --- tools/qfcc/source/dags.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index a128422cc..ac3a36a63 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -66,6 +66,8 @@ static dag_t *dags_freelist; static daglabel_t *daglabel_chain; +static void dag_live_aliases(operand_t *op); + static void flush_daglabels (void) { @@ -453,6 +455,7 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n, statement_t *s) } daglabel_t *label = operand_label (dag, use); label->live = 1; + dag_live_aliases (use); set_add (n->edges, label->dagnode->number); } if (n->type == st_func) { @@ -815,6 +818,7 @@ dag_create (flownode_t *flownode) dagnode_t **nodes; daglabel_t **labels; int num_statements = 0; + int num_use = 0; int num_nodes; int num_lables; set_t *live_vars = set_new (); @@ -823,18 +827,25 @@ dag_create (flownode_t *flownode) // count the number of statements so the number of nodes and labels can be // guessed - for (s = block->statements; s; s = s->next) + for (s = block->statements; s; s = s->next) { num_statements++; + for (operand_t *use = s->use; use; use = use->next) { + if (use->op_type == op_pseudo) { + continue; + } + num_use++; + } + } set_assign (live_vars, flownode->live_vars.out); dag = new_dag (); dag->flownode = flownode; - // at most FLOW_OPERANDS per statement - num_nodes = num_statements * FLOW_OPERANDS; + // at most FLOW_OPERANDS per statement + use + num_nodes = num_statements * FLOW_OPERANDS + num_use; dag->nodes = alloca (num_nodes * sizeof (dagnode_t)); - // at most FLOW_OPERANDS per statement, + return + params - num_lables = num_statements * (FLOW_OPERANDS + 1 + 8); + // at most FLOW_OPERANDS per statement, + return + params + use + num_lables = num_statements * (FLOW_OPERANDS + 1 + 8) + num_use; dag->labels = alloca (num_lables * sizeof (daglabel_t)); dag->roots = set_new (); @@ -843,6 +854,15 @@ dag_create (flownode_t *flownode) for (s = block->statements; s; s = s->next) { operand_t *operands[FLOW_OPERANDS]; dag_make_leafs (dag, s, operands); + // make sure any auxiliary operands are given nodes, too + for (operand_t *use = s->use; use; use = use->next) { + if (use->op_type == op_pseudo) { + continue; + } + if (!dag_node (use)) { + leaf_node (dag, use, s->expr); + } + } } // actual dag creation for (s = block->statements; s; s = s->next) { From 7e147e703c9eb18ab72d20a66be361264341ec91 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 18:31:53 +0900 Subject: [PATCH 2290/3664] [qfcc] Copy def reg into alias def This fixes incorrect local struct member access in Ruamoko progs. --- tools/qfcc/source/def.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 8472e1df4..44c3d74c6 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -196,6 +196,7 @@ alias_def (def_t *def, type_t *type, int offset) alias->line = pr.source_line; alias->file = pr.source_file; alias->next = def->alias_defs; + alias->reg = def->reg; def->alias_defs = alias; return alias; } From 37f08f9d4f34decd77b6a07449afe11cee4a5c54 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 24 Jan 2022 18:35:16 +0900 Subject: [PATCH 2291/3664] [qfcc] Build the Ruamoko function parameters The parameter defs are allocated from the parameter space using a minimum alignment of 4, and varargs functions get a va_list struct in place of the ... An "args" expression is unconditionally injected into the call arguments list at the place where ... is in the list, with arguments passed through ... coming after the ... Arguments get through to functions now, but there's problems with taking the address of local variables: currently done using constant pointer defs, which can't work for the base register addressing used in Ruamoko progs. With the update to test-bi's printf (and a hack to qfcc for lea), triangle.r actually works, printing the expected results (but -1 instead of 1 for equality, though that too is actually expected). qfcc will take a bit longer because it seems there are some design issues in address expressions (ambiguity, and a few other things) that have pretty much always been there. --- libs/gamecode/pr_exec.c | 2 +- tools/qfcc/include/expr.h | 9 ++++ tools/qfcc/include/expr_names.h | 1 + tools/qfcc/source/dot_expr.c | 10 ++++ tools/qfcc/source/expr.c | 42 +++++++++++++-- tools/qfcc/source/expr_assign.c | 1 + tools/qfcc/source/function.c | 96 +++++++++++++++++++++++++-------- tools/qfcc/source/statements.c | 57 ++++++++++++++++++-- tools/qfcc/test/test-bi.c | 13 +++++ 9 files changed, 200 insertions(+), 31 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 519808418..80df7c310 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -495,7 +495,7 @@ PR_SetupParams (progs_t *pr, int num_params, int min_alignment) } *pr->globals.stack = stack; pr->pr_params[0] = pr->pr_globals + stack; - num_params = min (num_params, PR_MAX_PARAMS); + num_params = max (num_params, PR_MAX_PARAMS); for (int i = 1; i < num_params; i++) { pr->pr_params[i] = pr->pr_params[0] + i * 4; } diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index aeb4e86ff..7783a572d 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -488,6 +488,14 @@ expr_t *new_temp_def_expr (const struct type_s *type); */ expr_t *new_nil_expr (void); +/** Create a new args expression node + + Marker between real parameters and those passed through ... + + \return The new args expression node. +*/ +expr_t *new_args_expr (void); + /** Create a new value expression node. \param value The value to put in the expression node. @@ -725,6 +733,7 @@ void convert_name (expr_t *e); expr_t *convert_vector (expr_t *e); expr_t *append_expr (expr_t *block, expr_t *e); +expr_t *prepend_expr (expr_t *block, expr_t *e); expr_t *reverse_expr_list (expr_t *e); void print_expr (expr_t *e); diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index 5af4e739b..820ba9826 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -61,5 +61,6 @@ EX_EXPR(branch) ///< branch expression (::ex_branch_t) EX_EXPR(return) ///< return expression (::ex_return_t) EX_EXPR(adjstk) ///< stack adjust expression (::ex_adjstk_t) EX_EXPR(with) ///< with expression (::ex_with_t) +EX_EXPR(args) ///< @args marker in parameter list. no data ///@} diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 3b918ca12..687cfb868 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -654,6 +654,15 @@ print_with (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->e.with.mode, e->e.with.reg, e->line); } +static void +print_args (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + dasprintf (dstr, "%*se_%p [label=\"...\\n%d\"];\n", indent, "", e, + e->line); +} + static void _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -682,6 +691,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_return] = print_return, [ex_adjstk] = print_adjstk, [ex_with] = print_with, + [ex_args] = print_args, }; int indent = level * 2 + 2; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 48476ab89..a5740700e 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -274,6 +274,8 @@ get_type (expr_t *e) break; case ex_assign: return get_type (e->e.assign.dst); + case ex_args: + return &type_va_list; case ex_count: internal_error (e, "invalid expression"); } @@ -525,6 +527,10 @@ copy_expr (expr_t *e) *n = *e; n->e.with.with = copy_expr (e->e.with.with); return n; + case ex_args: + n = new_expr (); + *n = *e; + return n; case ex_count: break; } @@ -725,6 +731,14 @@ new_nil_expr (void) return e; } +expr_t * +new_args_expr (void) +{ + expr_t *e = new_expr (); + e->type = ex_args; + return e; +} + expr_t * new_value_expr (ex_value_t *value) { @@ -1709,6 +1723,7 @@ has_function_call (expr_t *e) case ex_memset: case ex_adjstk: case ex_with: + case ex_args: return 0; case ex_count: break; @@ -1803,6 +1818,7 @@ unary_expr (int op, expr_t *e) case ex_return: case ex_adjstk: case ex_with: + case ex_args: internal_error (e, "unexpected expression type"); case ex_uexpr: if (e->e.expr.op == '-') { @@ -1907,6 +1923,7 @@ unary_expr (int op, expr_t *e) case ex_return: case ex_adjstk: case ex_with: + case ex_args: internal_error (e, "unexpected expression type"); case ex_bool: return new_bool_expr (e->e.bool.false_list, @@ -1989,6 +2006,7 @@ unary_expr (int op, expr_t *e) case ex_return: case ex_adjstk: case ex_with: + case ex_args: internal_error (e, "unexpected expression type"); case ex_uexpr: if (e->e.expr.op == '~') @@ -2048,12 +2066,13 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) { expr_t *e; expr_t *p; - int arg_count = 0, parm_count = 0; + int arg_count = 0, param_count = 0; int i; expr_t *args = 0, **a = &args; type_t *arg_types[PR_MAX_PARAMS]; expr_t *arg_exprs[PR_MAX_PARAMS][2]; int arg_expr_count = 0; + int emit_args = 0; expr_t *assign; expr_t *call; expr_t *err = 0; @@ -2074,7 +2093,8 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (options.warnings.traditional) warning (fexpr, "too few arguments"); } - parm_count = -ftype->t.func.num_params - 1; + param_count = -ftype->t.func.num_params - 1; + emit_args = 1; } else if (ftype->t.func.num_params >= 0) { if (arg_count > ftype->t.func.num_params) { return error (fexpr, "too many arguments"); @@ -2084,13 +2104,14 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (options.warnings.traditional) warning (fexpr, "too few arguments"); } - parm_count = ftype->t.func.num_params; + param_count = ftype->t.func.num_params; } + // params is reversed (a, b, c) -> c, b, a for (i = arg_count - 1, e = params; i >= 0; i--, e = e->next) { type_t *t; if (e->type == ex_compound) { - if (i < parm_count) { + if (i < param_count) { t = ftype->t.func.param_types[i]; } else { return error (e, "cannot pass compound initializer " @@ -2109,7 +2130,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) if (type_size (t) > type_size (&type_param)) err = error (e, "formal parameter %d is too large to be passed by" " value", i + 1); - if (i < parm_count) { + if (i < param_count) { if (e->type == ex_nil) convert_nil (e, t = ftype->t.func.param_types[i]); if (e->type == ex_bool) @@ -2154,7 +2175,13 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) call = expr_file_line (new_block_expr (), fexpr); call->e.block.is_call = 1; + // args is built in reverse order so it matches params for (p = params, i = 0; p; p = p->next, i++) { + if (emit_args && arg_count - i == param_count) { + emit_args = 0; + *a = new_args_expr (); + a = &(*a)->next; + } expr_t *e = p; if (e->type == ex_compound) { e = expr_file_line (initialized_temp_expr (arg_types[i], e), e); @@ -2175,6 +2202,11 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) } a = &(*a)->next; } + if (emit_args) { + emit_args = 0; + *a = new_args_expr (); + a = &(*a)->next; + } for (i = 0; i < arg_expr_count - 1; i++) { assign = assign_expr (arg_exprs[i][1], arg_exprs[i][0]); append_expr (call, expr_file_line (assign, arg_exprs[i][0])); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 0926931fb..9aa1f2784 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -140,6 +140,7 @@ is_lvalue (const expr_t *expr) case ex_return: case ex_adjstk: case ex_with: + case ex_args: break; case ex_count: internal_error (expr, "invalid expression"); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 82982b955..81a20af46 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -486,33 +486,15 @@ check_function (symbol_t *fsym) } static void -build_scope (symbol_t *fsym, symtab_t *parent) +build_v6p_scope (symbol_t *fsym) { int i; param_t *p; symbol_t *args = 0; symbol_t *param; - symtab_t *parameters; - symtab_t *locals; + symtab_t *parameters = fsym->s.func->parameters; + symtab_t *locals = fsym->s.func->locals; - check_function (fsym); - - fsym->s.func->label_scope = new_symtab (0, stab_local); - - parameters = new_symtab (parent, stab_local); - parameters->space = defspace_new (ds_virtual); - fsym->s.func->parameters = parameters; - - locals = new_symtab (parameters, stab_local); - locals->space = defspace_new (ds_virtual); - fsym->s.func->locals = locals; - - if (!fsym->s.func) { - internal_error (0, "function %s not defined", fsym->name); - } - if (!is_func (fsym->s.func->type)) { - internal_error (0, "function type %s not a funciton", fsym->name); - } if (fsym->s.func->type->t.func.num_params < 0) { args = new_symbol_type (".args", &type_va_list); initialize_def (args, 0, parameters->space, sc_param, locals); @@ -541,6 +523,78 @@ build_scope (symbol_t *fsym, symtab_t *parent) } } +static void +create_param (symtab_t *parameters, symbol_t *param) +{ + defspace_t *space = parameters->space; + def_t *def = new_def (param->name, 0, space, sc_param); + int size = type_size (param->type); + int alignment = param->type->alignment; + if (alignment < 4) { + alignment = 4; + } + def->offset = defspace_alloc_aligned_highwater (space, size, alignment); + def->type = param->type; + param->s.def = def; + param->sy_type = sy_var; + symtab_addsymbol (parameters, param); +} + +static void +build_rua_scope (symbol_t *fsym) +{ + for (param_t *p = fsym->params; p; p = p->next) { + symbol_t *param; + if (!p->selector && !p->type && !p->name) { + // ellipsis marker + param = new_symbol_type (".args", &type_va_list); + } else { + if (!p->type) { + continue; // non-param selector + } + if (!p->name) { + error (0, "parameter name omitted"); + p->name = save_string (""); + } + param = new_symbol_type (p->name, p->type); + } + create_param (fsym->s.func->parameters, param); + param->s.def->reg = fsym->s.func->temp_reg;; + } +} + +static void +build_scope (symbol_t *fsym, symtab_t *parent) +{ + symtab_t *parameters; + symtab_t *locals; + + if (!fsym->s.func) { + internal_error (0, "function %s not defined", fsym->name); + } + if (!is_func (fsym->s.func->type)) { + internal_error (0, "function type %s not a funciton", fsym->name); + } + + check_function (fsym); + + fsym->s.func->label_scope = new_symtab (0, stab_local); + + parameters = new_symtab (parent, stab_local); + parameters->space = defspace_new (ds_virtual); + fsym->s.func->parameters = parameters; + + locals = new_symtab (parameters, stab_local); + locals->space = defspace_new (ds_virtual); + fsym->s.func->locals = locals; + + if (options.code.progsversion == PROG_VERSION) { + build_rua_scope (fsym); + } else { + build_v6p_scope (fsym); + } +} + function_t * new_function (const char *name, const char *nice_name) { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 1168c3fcf..028ec9e96 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1026,10 +1026,19 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) statement_t *s; // function arguments are in reverse order - for (a = args; a; a = a->next) + for (a = args; a; a = a->next) { + if (a->type == ex_args) { + // v6p uses callN and pr_argc + continue; + } count++; + } ind = count; for (a = args; a; a = a->next) { + if (a->type == ex_args) { + // v6p uses callN and pr_argc + continue; + } ind--; param = new_param_expr (get_type (a), ind); if (count && options.code.progsversion != PROG_ID_VERSION && ind < 2) { @@ -1091,8 +1100,11 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) defspace_t *arg_space = current_func->arguments; expr_t *func = call->e.branch.target; expr_t *args = call->e.branch.args; + expr_t *args_va_list = 0; // .args (...) parameter + expr_t *args_params = 0; // first arg in ... operand_t *use = 0; operand_t *kill = 0; + int num_params = 0; defspace_reset (arg_space); @@ -1111,9 +1123,21 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) def->offset = defspace_alloc_aligned_highwater (arg_space, size, alignment); def->type = arg_type; - expr_t *assign = assign_expr (new_def_expr (def), a); - expr_file_line (assign, call); - sblock = statement_slist (sblock, assign); + def->reg = current_func->temp_reg; + expr_t *def_expr = expr_file_line (new_def_expr (def), call); + if (a->type == ex_args) { + args_va_list = def_expr; + } else { + if (args_va_list && !args_params) { + args_params = def_expr; + } + if (args_va_list) { + num_params++; + } + expr_t *assign = assign_expr (def_expr, a); + expr_file_line (assign, call); + sblock = statement_slist (sblock, assign); + } // The call both uses and kills the arguments: use is obvious, but kill // is because the callee has direct access to them and might modify @@ -1126,6 +1150,31 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) k->next = kill; kill = k; } + if (args_va_list) { + expr_t *assign; + expr_t *count; + expr_t *list; + expr_t *args_count = field_expr (args_va_list, + new_name_expr ("count")); + expr_t *args_list = field_expr (args_va_list, + new_name_expr ("list")); + expr_file_line (args_count, call); + expr_file_line (args_list, call); + + count = new_short_expr (num_params); + assign = assign_expr (args_count, count); + expr_file_line (assign, call); + sblock = statement_slist (sblock, assign); + + if (args_params) { + list = address_expr (args_params, 0, &type_param); + } else { + list = new_nil_expr (); + } + assign = assign_expr (args_list, list); + expr_file_line (assign, call); + sblock = statement_slist (sblock, assign); + } statement_t *s = new_statement (st_func, "call", call); sblock = statement_subexpr (sblock, func, &s->opa); if (!op) { diff --git a/tools/qfcc/test/test-bi.c b/tools/qfcc/test/test-bi.c index 5e6a093ef..412a341bf 100644 --- a/tools/qfcc/test/test-bi.c +++ b/tools/qfcc/test/test-bi.c @@ -55,6 +55,19 @@ bi_printf (progs_t *pr) else dstring_clear (dstr); + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); + count = va_list->count; + if (count) { + args = alloca (count * sizeof (pr_type_t *)); + for (int i = 0; i < count; i++) { + args[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + args = 0; + } + } + PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); if (dstr->str) fputs (dstr->str, stdout); From fc73cfc1e0b7d61fd7373e668d57977dc5d33c0b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jan 2022 12:28:53 +0900 Subject: [PATCH 2292/3664] [qfcc] Rename pointer_expr to deref_pointer_expr This reflects what it actually does (usually, "pointer_expr" type naming is creating an expression that represents a pointer). --- tools/qfcc/include/expr.h | 2 +- tools/qfcc/source/expr.c | 4 ++-- tools/qfcc/source/qc-parse.y | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 7783a572d..977a018ff 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -766,7 +766,7 @@ expr_t *return_expr (struct function_s *f, expr_t *e); expr_t *conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2); expr_t *incop_expr (int op, expr_t *e, int postop); expr_t *array_expr (expr_t *array, expr_t *index); -expr_t *pointer_expr (expr_t *pointer); +expr_t *deref_pointer_expr (expr_t *pointer); expr_t *address_expr (expr_t *e1, expr_t *e2, struct type_s *t); expr_t *build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index a5740700e..52b0fbe84 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2468,7 +2468,7 @@ incop_expr (int op, expr_t *e, int postop) append_expr (block, assign_expr (t2, binary_expr (op, t1, one))); res = copy_expr (e); if (res->type == ex_uexpr && res->e.expr.op == '.') - res = pointer_expr (address_expr (res, 0, 0)); + res = deref_pointer_expr (address_expr (res, 0, 0)); append_expr (block, assign_expr (res, t2)); block->e.block.result = t1; return block; @@ -2531,7 +2531,7 @@ array_expr (expr_t *array, expr_t *index) } expr_t * -pointer_expr (expr_t *pointer) +deref_pointer_expr (expr_t *pointer) { type_t *pointer_type = get_type (pointer); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 709470e0c..399f91b1e 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1560,7 +1560,7 @@ unary_expr | '!' cast_expr %prec UNARY { $$ = unary_expr ('!', $2); } | '~' cast_expr %prec UNARY { $$ = unary_expr ('~', $2); } | '&' cast_expr %prec UNARY { $$ = address_expr ($2, 0, 0); } - | '*' cast_expr %prec UNARY { $$ = pointer_expr ($2); } + | '*' cast_expr %prec UNARY { $$ = deref_pointer_expr ($2); } | SIZEOF unary_expr %prec UNARY { $$ = sizeof_expr ($2, 0); } | SIZEOF '(' abstract_decl ')' %prec HYPERUNARY { From a1acdb895153410567d1b8efc43bb9f37b4bb4c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jan 2022 12:29:15 +0900 Subject: [PATCH 2293/3664] [qfcc] Print children of uexpr and return expressions It's possible I lost the child printing when creating the return expressions, but dot diagrams are much more useful when they don't have nodes with just pointer values. --- tools/qfcc/source/dot_expr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 687cfb868..e5b5e87ea 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -406,6 +406,7 @@ print_return (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) int indent = level * 2 + 2; if (e->e.retrn.ret_val) { + _print_expr (dstr, e->e.retrn.ret_val, level, id, next); dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, e->e.retrn.ret_val); } @@ -418,6 +419,7 @@ print_uexpr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; + _print_expr (dstr, e->e.expr.e1, level, id, next); dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, e->e.expr.e1); dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, get_op_string (e->e.expr.op), e->line); From 8d435040e66880cdb56824a7c9ef7c56164ce288 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jan 2022 12:46:14 +0900 Subject: [PATCH 2294/3664] [qfcc] Clean up some type checkes Using the functions keeps the code a little easier to read. --- tools/qfcc/source/expr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 52b0fbe84..73f23c172 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1483,7 +1483,7 @@ field_expr (expr_t *e1, expr_t *e2) t1 = get_type (e1); if (e1->type == ex_error) return e1; - if (t1->type == ev_entity) { + if (is_entity (t1)) { symbol_t *field = 0; if (e2->type == ex_symbol) @@ -1503,7 +1503,7 @@ field_expr (expr_t *e1, expr_t *e2) return e; } } - } else if (t1->type == ev_ptr) { + } else if (is_ptr (t1)) { if (is_struct (t1->t.fldptr.type)) { symbol_t *field; @@ -1529,8 +1529,7 @@ field_expr (expr_t *e1, expr_t *e2) e = new_address_expr (ivar->type, e1, e2); return unary_expr ('.', e); } - } else if (t1->type == ev_vector || t1->type == ev_quaternion - || is_struct (t1)) { + } else if (is_vector (t1) || is_quaternion (t1) || is_struct (t1)) { symbol_t *field; field = get_struct_field (t1, e1, e2); From 40f5b8a482cc67bd1f47535b5b49f20afffcc2dc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jan 2022 12:47:12 +0900 Subject: [PATCH 2295/3664] [qfcc] Allow short constants in expr_int No point in generating an internal error when the value can be converted to an int. --- tools/qfcc/source/expr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 73f23c172..de12be36d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1160,6 +1160,9 @@ expr_int (expr_t *e) if (e->type == ex_value && e->e.value->lltype == ev_int) { return e->e.value->v.int_val; } + if (e->type == ex_value && e->e.value->lltype == ev_short) { + return e->e.value->v.short_val; + } if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const && (e->e.symbol->type->type == ev_int || is_enum (e->e.symbol->type))) { From e4bb5c804852749af8a18b5177cbeb7af86a93dd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jan 2022 22:14:12 +0900 Subject: [PATCH 2296/3664] [qfcc] Add pragma to control warning promotion This allows me to disable -Werror in the Makefile but still have the build tests work properly and not fail when they shouldn't. --- tools/qfcc/source/pragma.c | 20 ++++++++++++++++++++ tools/qfcc/test/classarray.r | 2 ++ tools/qfcc/test/dealloc-warn.r | 2 ++ tools/qfcc/test/dealloc-warn2.r | 2 ++ tools/qfcc/test/dealloc-warn3.r | 2 ++ tools/qfcc/test/double-demote-float-ainit.r | 2 ++ tools/qfcc/test/double-demote-float-ginit.r | 2 ++ tools/qfcc/test/double-demote-float-linit.r | 2 ++ tools/qfcc/test/double-demote-float.r | 2 ++ tools/qfcc/test/double-demote-int-ainit.r | 2 ++ tools/qfcc/test/double-demote-int-ginit.r | 2 ++ tools/qfcc/test/double-demote-int-linit.r | 2 ++ tools/qfcc/test/double-demote-int.r | 2 ++ tools/qfcc/test/double-float-compare.r | 2 ++ tools/qfcc/test/double-int-compare.r | 2 ++ 15 files changed, 48 insertions(+) diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index 616198ab2..9e3a393aa 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -107,6 +107,24 @@ set_bug (pragma_arg_t *args) } } +static void +set_warn (pragma_arg_t *args) +{ + if (!args) { + warning (0, "missing warn flag"); + return; + } + const char *flag = args->arg; + if (!strcmp (flag, "error")) { + options.warnings.promote = true; + } else if (!strcmp (flag, "!error")) { + options.warnings.promote = false; + } + if (args->next) { + warning (0, "pragma warn: ignoring extra arguments"); + } +} + void pragma_process () { @@ -123,6 +141,8 @@ pragma_process () set_traditional (0); } else if (!strcmp (id, "bug")) { set_bug (pragma_args->next); + } else if (!strcmp (id, "warn")) { + set_warn (pragma_args->next); } else { warning (0, "unknown pragma: '%s'", id); } diff --git a/tools/qfcc/test/classarray.r b/tools/qfcc/test/classarray.r index fa33d8264..972c1c3d7 100644 --- a/tools/qfcc/test/classarray.r +++ b/tools/qfcc/test/classarray.r @@ -1,3 +1,5 @@ +#pragma warn error + @interface foo { id isa; diff --git a/tools/qfcc/test/dealloc-warn.r b/tools/qfcc/test/dealloc-warn.r index bf218ca9c..86dd53a75 100644 --- a/tools/qfcc/test/dealloc-warn.r +++ b/tools/qfcc/test/dealloc-warn.r @@ -1,3 +1,5 @@ +#pragma warn error + @interface Object { Class isa; diff --git a/tools/qfcc/test/dealloc-warn2.r b/tools/qfcc/test/dealloc-warn2.r index 0cd10d3ef..921db1566 100644 --- a/tools/qfcc/test/dealloc-warn2.r +++ b/tools/qfcc/test/dealloc-warn2.r @@ -1,3 +1,5 @@ +#pragma warn error + @interface Object { Class isa; diff --git a/tools/qfcc/test/dealloc-warn3.r b/tools/qfcc/test/dealloc-warn3.r index 3d505c987..32427e2ff 100644 --- a/tools/qfcc/test/dealloc-warn3.r +++ b/tools/qfcc/test/dealloc-warn3.r @@ -1,3 +1,5 @@ +#pragma warn error + @interface Object { Class isa; diff --git a/tools/qfcc/test/double-demote-float-ainit.r b/tools/qfcc/test/double-demote-float-ainit.r index 6d380447d..7ebbb1467 100644 --- a/tools/qfcc/test/double-demote-float-ainit.r +++ b/tools/qfcc/test/double-demote-float-ainit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b[] = {1.0d}; int main () diff --git a/tools/qfcc/test/double-demote-float-ginit.r b/tools/qfcc/test/double-demote-float-ginit.r index c88b5e987..a23f98939 100644 --- a/tools/qfcc/test/double-demote-float-ginit.r +++ b/tools/qfcc/test/double-demote-float-ginit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; float b = 1.0d; int main () diff --git a/tools/qfcc/test/double-demote-float-linit.r b/tools/qfcc/test/double-demote-float-linit.r index 796b2040f..2eba60432 100644 --- a/tools/qfcc/test/double-demote-float-linit.r +++ b/tools/qfcc/test/double-demote-float-linit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int main () { diff --git a/tools/qfcc/test/double-demote-float.r b/tools/qfcc/test/double-demote-float.r index 330a0bdef..f38db3a96 100644 --- a/tools/qfcc/test/double-demote-float.r +++ b/tools/qfcc/test/double-demote-float.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; float b; int main () diff --git a/tools/qfcc/test/double-demote-int-ainit.r b/tools/qfcc/test/double-demote-int-ainit.r index 6d380447d..7ebbb1467 100644 --- a/tools/qfcc/test/double-demote-int-ainit.r +++ b/tools/qfcc/test/double-demote-int-ainit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b[] = {1.0d}; int main () diff --git a/tools/qfcc/test/double-demote-int-ginit.r b/tools/qfcc/test/double-demote-int-ginit.r index 767328715..80fa7857a 100644 --- a/tools/qfcc/test/double-demote-int-ginit.r +++ b/tools/qfcc/test/double-demote-int-ginit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b = 1.0d; int main () diff --git a/tools/qfcc/test/double-demote-int-linit.r b/tools/qfcc/test/double-demote-int-linit.r index 3a206f4b5..523cca503 100644 --- a/tools/qfcc/test/double-demote-int-linit.r +++ b/tools/qfcc/test/double-demote-int-linit.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int main () { diff --git a/tools/qfcc/test/double-demote-int.r b/tools/qfcc/test/double-demote-int.r index bebef5436..dd921215f 100644 --- a/tools/qfcc/test/double-demote-int.r +++ b/tools/qfcc/test/double-demote-int.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b; int main () diff --git a/tools/qfcc/test/double-float-compare.r b/tools/qfcc/test/double-float-compare.r index a219b0d4a..37a4bfb03 100644 --- a/tools/qfcc/test/double-float-compare.r +++ b/tools/qfcc/test/double-float-compare.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; float b; int main () diff --git a/tools/qfcc/test/double-int-compare.r b/tools/qfcc/test/double-int-compare.r index 221516ed8..374b32edc 100644 --- a/tools/qfcc/test/double-int-compare.r +++ b/tools/qfcc/test/double-int-compare.r @@ -1,3 +1,5 @@ +#pragma warn error + double a; int b; int main () From 06d70a32db2c51dd672b2d6bed2112c50d520316 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Jan 2022 23:39:17 +0900 Subject: [PATCH 2297/3664] [qfcc] Rework the functionality of address expressions The goal was to get lea being used for locals in ruamoko progs because lea takes the base registers into account while the constant pointer defs used by v6p cannot. Pointer defs are still used for gobals as they may be out of reach of 16-bit addressing. address_expr() has been simplified in that it no longer takes an offset: the vast majority of the callers never passed one, and the few that did have been reworked to use other mechanisms. In particular, offset_pointer_expr does the manipulations needed to add an offset (unscaled by type size) to a pointer. High-level pointer offsets still apply a scale, though. Alias expressions now do a better job of hanling aliasing of aliases by simply replacing the target type when possible. --- tools/qfcc/include/expr.h | 3 +- tools/qfcc/source/class.c | 2 +- tools/qfcc/source/expr.c | 117 ++++++++++++++++++-------------- tools/qfcc/source/expr_assign.c | 2 +- tools/qfcc/source/expr_binary.c | 10 +-- tools/qfcc/source/expr_obj.c | 2 +- tools/qfcc/source/flow.c | 8 ++- tools/qfcc/source/qc-parse.y | 2 +- tools/qfcc/source/statements.c | 81 ++++++++++++++-------- tools/qfcc/source/switch.c | 2 +- 10 files changed, 136 insertions(+), 93 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 977a018ff..641b04246 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -767,7 +767,8 @@ expr_t *conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2); expr_t *incop_expr (int op, expr_t *e, int postop); expr_t *array_expr (expr_t *array, expr_t *index); expr_t *deref_pointer_expr (expr_t *pointer); -expr_t *address_expr (expr_t *e1, expr_t *e2, struct type_s *t); +expr_t *offset_pointer_expr (expr_t *pointer, expr_t *offset); +expr_t *address_expr (expr_t *e1, struct type_s *t); expr_t *build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2); expr_t *build_while_statement (int not, expr_t *test, expr_t *statement, diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 3f141ede9..ce4499fdc 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1555,7 +1555,7 @@ class_finish_module (void) init_sym = new_symbol_type (".ctor", &type_func); init_sym = function_symbol (init_sym, 0, 1); - module_expr = address_expr (new_symbol_expr (module_sym), 0, 0); + module_expr = address_expr (new_symbol_expr (module_sym), 0); init_expr = new_block_expr (); append_expr (init_expr, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index de12be36d..497de95c6 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1304,7 +1304,10 @@ expr_t * new_alias_expr (type_t *type, expr_t *expr) { if (expr->type == ex_alias) { - return new_offset_alias_expr (type, expr, 0); + if (expr->e.alias.offset) { + return new_offset_alias_expr (type, expr, 0); + } + expr = expr->e.alias.expr; } expr_t *alias = new_expr (); @@ -1527,10 +1530,10 @@ field_expr (expr_t *e1, expr_t *e2) ivar = class_find_ivar (class, protected, sym->name); if (!ivar) return new_error_expr (); - e2->type = ex_value; - e2->e.value = new_short_val (ivar->s.offset); - e = new_address_expr (ivar->type, e1, e2); - return unary_expr ('.', e); + expr_t *offset = new_short_expr (ivar->s.offset); + e1 = offset_pointer_expr (e1, offset); + e1 = cast_expr (pointer_type (ivar->type), e1); + return unary_expr ('.', e1); } } else if (is_vector (t1) || is_quaternion (t1) || is_struct (t1)) { symbol_t *field; @@ -1564,10 +1567,10 @@ field_expr (expr_t *e1, expr_t *e2) return field_expr (e1, e2); } else { if (e1->type == ex_uexpr && e1->e.expr.op == '.') { - e2->type = ex_value; - e2->e.value = new_short_val (field->s.offset); - e = address_expr (e1, e2, field->type); - return unary_expr ('.', e); + expr_t *offset = new_short_expr (field->s.offset); + e1 = offset_pointer_expr (e1->e.expr.e1, offset); + e1 = cast_expr (pointer_type (field->type), e1); + return unary_expr ('.', e1); } else { return new_offset_alias_expr (field->type, e1, field->s.offset); } @@ -2470,7 +2473,7 @@ incop_expr (int op, expr_t *e, int postop) append_expr (block, assign_expr (t2, binary_expr (op, t1, one))); res = copy_expr (e); if (res->type == ex_uexpr && res->e.expr.op == '.') - res = deref_pointer_expr (address_expr (res, 0, 0)); + res = deref_pointer_expr (address_expr (res, 0)); append_expr (block, assign_expr (res, t2)); block->e.block.result = t1; return block; @@ -2487,6 +2490,7 @@ array_expr (expr_t *array, expr_t *index) expr_t *scale; expr_t *offset; expr_t *base; + expr_t *ptr; expr_t *e; int ind = 0; @@ -2495,7 +2499,7 @@ array_expr (expr_t *array, expr_t *index) if (index->type == ex_error) return index; - if (array_type->type != ev_ptr && !is_array (array_type)) + if (!is_ptr (array_type) && !is_array (array_type)) return error (array, "not an array"); if (!is_integral (index_type)) return error (index, "invalid array index type"); @@ -2503,7 +2507,8 @@ array_expr (expr_t *array, expr_t *index) ind = expr_short (index); if (is_int_val (index)) ind = expr_int (index); - if (array_type->t.func.num_params + if (is_array (array_type) + && array_type->t.array.size && is_constant (index) && (ind < array_type->t.array.base || ind - array_type->t.array.base >= array_type->t.array.size)) @@ -2517,18 +2522,21 @@ array_expr (expr_t *array, expr_t *index) ind = expr_short (index); if (is_int_val (index)) ind = expr_int (index); - if ((is_constant (index) && ind < 32768 && ind >= -32768)) - index = new_short_expr (ind); if (is_array (array_type)) { - e = address_expr (array, index, array_type->t.array.type); - } else { - if (!is_short_val (index) || expr_short (index)) { - e = new_address_expr (array_type->t.array.type, array, index); + type_t *element_type = array_type->t.array.type; + if (array->type == ex_uexpr && array->e.expr.op == '.') { + ptr = array->e.expr.e1; } else { - e = array; + expr_t *alias = new_offset_alias_expr (element_type, array, 0); + ptr = new_address_expr (element_type, alias, 0); } + } else { + ptr = array; } - e = unary_expr ('.', e); + ptr = offset_pointer_expr (ptr, index); + ptr = cast_expr (pointer_type (array_type->t.array.type), ptr); + + e = unary_expr ('.', ptr); return e; } @@ -2545,7 +2553,28 @@ deref_pointer_expr (expr_t *pointer) } expr_t * -address_expr (expr_t *e1, expr_t *e2, type_t *t) +offset_pointer_expr (expr_t *pointer, expr_t *offset) +{ + type_t *ptr_type = get_type (pointer); + if (!is_ptr (ptr_type)) { + internal_error (pointer, "not a pointer"); + } + if (!is_integral (get_type (offset))) { + internal_error (offset, "pointer offset is not an integer type"); + } + expr_t *ptr; + if (pointer->type == ex_alias && !pointer->e.alias.offset + && is_integral (get_type (pointer->e.alias.expr))) { + ptr = pointer->e.alias.expr; + } else { + ptr = cast_expr (&type_int, pointer); + } + ptr = binary_expr ('+', ptr, offset); + return cast_expr (ptr_type, ptr); +} + +expr_t * +address_expr (expr_t *e1, type_t *t) { expr_t *e; @@ -2561,6 +2590,12 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) def_t *def = e1->e.def; type_t *type = def->type; + //FIXME this test should be in statements.c + if (options.code.progsversion == PROG_VERSION + && (def->local || def->param)) { + e = new_address_expr (t, e1, 0); + return e; + } if (is_array (type)) { e = e1; e->type = ex_value; @@ -2577,6 +2612,13 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) def_t *def = e1->e.symbol->s.def; type_t *type = def->type; + //FIXME this test should be in statements.c + if (options.code.progsversion == PROG_VERSION + && (def->local || def->param)) { + e = new_address_expr (t, e1, 0); + return e; + } + if (is_array (type)) { e = e1; e->type = ex_value; @@ -2614,39 +2656,10 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) if (!t) { t = e1->e.alias.type; } - if (e1->e.alias.offset) { - if (e2) { - e2 = binary_expr ('+', e1->e.alias.offset, e2); - } else { - e2 = e1->e.alias.offset; - } - } - return address_expr (e1->e.alias.expr, e2, t); + return new_address_expr (t, e1, 0); default: return error (e1, "invalid type for unary &"); } - if (e2) { - if (e2->type == ex_error) - return e2; - if (is_pointer_val (e) && is_integral_val (e2)) { - int base = e->e.value->v.pointer.val; - int offset = expr_integral (e2); - def_t *def = e->e.value->v.pointer.def; - e->e.value = new_pointer_val (base + offset, t, def, 0); - } else { - expr_t *offset = 0; - if (e->type == ex_address) { - offset = e->e.address.offset; - e1 = e->e.address.lvalue; - } else { - e1 = e; - } - if (offset) { - e2 = binary_expr ('+', offset, e2); - } - e = new_address_expr (t, e1, e2); - } - } return e; } @@ -2928,7 +2941,7 @@ cast_expr (type_t *dstType, expr_t *e) return cast_error (e, srcType, dstType); } if (is_array (srcType)) { - return address_expr (e, 0, dstType->t.fldptr.type); + return address_expr (e, dstType->t.fldptr.type); } if (is_constant (e) && is_scalar (dstType) && is_scalar (srcType)) { ex_value_t *val = 0; diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 9aa1f2784..f9a66b1be 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -335,7 +335,7 @@ assign_expr (expr_t *dst, expr_t *src) if (is_ptr (dst_type) && is_array (src_type)) { // assigning an array to a pointer is the same as taking the address of // the array but using the type of the array elements - src = address_expr (src, 0, src_type->t.fldptr.type); + src = address_expr (src, src_type->t.fldptr.type); src_type = get_type (src); } if (src->type == ex_bool) { diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 27e7f1ff8..22d4b8a5a 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -638,7 +638,6 @@ static expr_type_t **binary_expr_types[ev_type_count] = { static expr_t * pointer_arithmetic (int op, expr_t *e1, expr_t *e2) { - expr_t *e; type_t *t1 = get_type (e1); type_t *t2 = get_type (e2); expr_t *ptr; @@ -663,16 +662,17 @@ pointer_arithmetic (int op, expr_t *e1, expr_t *e2) return binary_expr ('/', binary_expr ('-', e1, e2), psize); } else if (is_ptr (t1)) { offset = cast_expr (&type_int, e2); - ptr = cast_expr (&type_int, e1); + ptr = e1; ptype = t1; } else if (is_ptr (t2)) { offset = cast_expr (&type_int, e1); - ptr = cast_expr (&type_int, e2); + ptr = e2; ptype = t2; } + // op is known to be + or - psize = new_int_expr (type_size (ptype->t.fldptr.type)); - e = binary_expr (op, ptr, binary_expr ('*', offset, psize)); - return cast_expr (ptype, e); + offset = unary_expr (op, binary_expr ('*', offset, psize)); + return offset_pointer_expr (ptr, offset); } static expr_t * diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index 6a8bedebf..41405c1e4 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -172,7 +172,7 @@ super_expr (class_type_t *class_type) field_expr (e, new_name_expr ("super_class"))); append_expr (super_block, e); - e = address_expr (super, 0, 0); + e = address_expr (super, 0); super_block->e.block.result = e; return super_block; } diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 753b15928..4b501c027 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1183,7 +1183,13 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, internal_error (s->expr, "not a statement"); case st_expr: flow_add_op_var (def, s->opc, 0); - flow_add_op_var (use, s->opa, 1); + if (strcmp (s->opcode, "lea") == 0) { + if (s->opb) { + flow_add_op_var (use, s->opa, 1); + } + } else { + flow_add_op_var (use, s->opa, 1); + } if (s->opb) flow_add_op_var (use, s->opb, 1); if (operands) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 399f91b1e..282f501ae 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1559,7 +1559,7 @@ unary_expr | '-' cast_expr %prec UNARY { $$ = unary_expr ('-', $2); } | '!' cast_expr %prec UNARY { $$ = unary_expr ('!', $2); } | '~' cast_expr %prec UNARY { $$ = unary_expr ('~', $2); } - | '&' cast_expr %prec UNARY { $$ = address_expr ($2, 0, 0); } + | '&' cast_expr %prec UNARY { $$ = address_expr ($2, 0); } | '*' cast_expr %prec UNARY { $$ = deref_pointer_expr ($2); } | SIZEOF unary_expr %prec UNARY { $$ = sizeof_expr ($2, 0); } | SIZEOF '(' abstract_decl ')' %prec HYPERUNARY diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 028ec9e96..3ff6df7bd 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -727,10 +727,20 @@ static sblock_t * expr_address (sblock_t *sblock, expr_t *e, operand_t **op) { statement_t *s; + expr_t *lvalue = e->e.address.lvalue; + expr_t *offset = e->e.address.offset; + + if (lvalue->type == ex_alias && offset && is_constant (offset)) { + lvalue = new_offset_alias_expr (lvalue->e.alias.type, + lvalue->e.alias.expr, + expr_int (offset)); + offset = 0; + } + s = new_statement (st_expr, "lea", e); - sblock = statement_subexpr (sblock, e->e.address.lvalue, &s->opa); - if (e->e.address.offset) { - sblock = statement_subexpr (sblock, e->e.address.offset, &s->opb); + sblock = statement_subexpr (sblock, lvalue, &s->opa); + if (offset) { + sblock = statement_subexpr (sblock, offset, &s->opb); } s->opc = temp_operand (e->e.address.type, e); sblock_add_statement (sblock, s); @@ -836,7 +846,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) } } else { if (is_indirect (src_expr)) { - src_expr = expr_file_line (address_expr (src_expr, 0, 0), e); + src_expr = expr_file_line (address_expr (src_expr, 0), e); need_ptr = 1; } if (!src) { @@ -860,7 +870,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) // dst_expr and/or src_expr are dereferenced pointers, so need to // un-dereference dst_expr to get the pointer and switch to movep // or memsetp instructions. - dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); + dst_expr = expr_file_line (address_expr (dst_expr, 0), e); need_ptr = 1; } sblock = statement_subexpr (sblock, dst_expr, &dst); @@ -945,7 +955,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) dereference_dst: // dst_expr is a dereferenced pointer, so need to un-dereference it // to get the pointer and switch to storep instructions. - dst_expr = expr_file_line (address_expr (dst_expr, 0, 0), e); + dst_expr = expr_file_line (address_expr (dst_expr, 0), e); opcode = "store"; if (dst_expr->type == ex_address && dst_expr->e.address.offset && !is_const_ptr (dst_expr->e.address.lvalue)) { @@ -1167,7 +1177,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) sblock = statement_slist (sblock, assign); if (args_params) { - list = address_expr (args_params, 0, &type_param); + list = address_expr (args_params, &type_param); } else { list = new_nil_expr (); } @@ -1258,8 +1268,10 @@ statement_return (sblock_t *sblock, expr_t *e) s = new_statement (st_func, opcode, e); if (options.code.progsversion < PROG_VERSION) { if (e->e.retrn.ret_val) { - s->opa = return_operand (get_type (e->e.retrn.ret_val), e); - sblock = statement_subexpr (sblock, e->e.retrn.ret_val, &s->opa); + expr_t *ret_val = e->e.retrn.ret_val; + type_t *ret_type = get_type (ret_val); + s->opa = return_operand (ret_type, e); + sblock = statement_subexpr (sblock, ret_val, &s->opa); } } else { if (e->e.retrn.ret_val) { @@ -1316,6 +1328,28 @@ lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) return s; } +static statement_t * +movep_statement (operand_t *dst, operand_t *src, type_t *type, expr_t *e) +{ + operand_t *dst_addr = operand_address (dst, e); + statement_t *s = new_statement (st_ptrmove, "movep", e); + s->opa = src; + //FIXME large types + s->opb = short_operand (type_size (type), e); + s->opc = dst_addr; + return s; +} + +static statement_t * +load_statement (operand_t *ptr, operand_t *offs, operand_t *op, expr_t *e) +{ + statement_t *s = new_statement (st_expr, "load", e); + s->opa = ptr; + s->opb = offs; + s->opc = op; + return s; +} + static sblock_t * expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) { @@ -1337,26 +1371,13 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) if (!*op) *op = temp_operand (type, e); if (low_level_type (type) == ev_void) { - operand_t *src_addr; - operand_t *dst_addr; - s = lea_statement (ptr, offs, e); - src_addr = s->opc; sblock_add_statement (sblock, s); - dst_addr = operand_address (*op, e); - - s = new_statement (st_ptrmove, "movep", deref); - s->opa = src_addr; - //FIXME large types - s->opb = short_operand (type_size (type), e); - s->opc = dst_addr; + s = movep_statement (*op, s->opc, type, deref); sblock_add_statement (sblock, s); } else { - s = new_statement (st_expr, "load", deref); - s->opa = ptr; - s->opb = offs; - s->opc = *op; + s = load_statement (ptr, offs, *op, deref); sblock_add_statement (sblock, s); } } else if (e->type == ex_value && e->e.value->lltype == ev_ptr) { @@ -1370,11 +1391,13 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) sblock = statement_subexpr (sblock, e, &ptr); if (!*op) *op = temp_operand (type, e); - s = new_statement (st_expr, "load", deref); - s->opa = ptr; - s->opb = short_operand (0, e); - s->opc = *op; - sblock_add_statement (sblock, s); + if (low_level_type (type) == ev_void) { + s = movep_statement (*op, ptr, type, deref); + sblock_add_statement (sblock, s); + } else { + s = load_statement (ptr, short_operand (0, e), *op, deref); + sblock_add_statement (sblock, s); + } } return sblock; } diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 10b8dc342..f275af673 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -343,7 +343,7 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val, table_init = new_compound_init (); for (i = 0; i <= high - low; i++) { tree->labels[i]->e.label.used++; - label = address_expr (tree->labels[i], 0, 0); + label = address_expr (tree->labels[i], 0); append_element (table_init, new_element (label, 0)); } table_sym = new_symbol_type (table_name, From 6bc6db471dd3457e4206c2d384baa4873585626c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jan 2022 09:51:11 +0900 Subject: [PATCH 2298/3664] [gamecode] Make return use same addressing as other ops This makes return consistent with load, store, etc, though its addressing mode is encoded in bits 5 and 6 of c rather than the opcode. It turns out I had no tests for any of return's addressing modes other than basic def references, so no tests needed changing. --- libs/gamecode/pr_exec.c | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 80df7c310..b0a81c376 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1820,39 +1820,6 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) return pr->pr_globals + mm_offs; } -static pr_type_t * -pr_return_mode (progs_t *pr, const dstatement_t *st, int mm_ind) -{ - pr_type_t *op_a = pr->pr_globals + st->a + PR_BASE (pr, st, A); - pr_type_t *op_b = pr->pr_globals + st->b + PR_BASE (pr, st, B); - pr_ptr_t mm_offs = 0; - - switch (mm_ind) { - case 0: - // regular global access - mm_offs = op_a - pr->pr_globals; - break; - case 1: - // simple pointer dereference: *a - mm_offs = OPA(ptr); - break; - case 2: - // constant indexed pointer: *a + b (supports -ve offset) - mm_offs = OPA(ptr) + (short) st->b; - break; - case 3: - // variable indexed pointer: *a + *b (supports -ve offset) - mm_offs = OPA(ptr) + OPB(int); - break; - case 4: - // entity.field (equivalent to OP_LOAD_t_v6p) - pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; - mm_offs = edict_area + OPA(entity) + OPB(field); - break; - } - return pr->pr_globals + mm_offs; -} - static pr_type_t * pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind) { @@ -3184,7 +3151,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_RETURN: int ret_size = (st->c & 0x1f) + 1; // up to 32 words if (st->c != 0xffff) { - mm = pr_return_mode (pr, st, st->c >> 5); + mm = pr_address_mode (pr, st, st->c >> 5); memcpy (&R_INT (pr), mm, ret_size * sizeof (*op_a)); } pr->pr_xfunction->profile += profile - startprofile; From ee4eecc7414f82fe55f5ae5743487fdca895111e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jan 2022 12:26:12 +0900 Subject: [PATCH 2299/3664] [gamecode] Correct types and opname for memset and move --- libs/gamecode/opcodes.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index d6cb80f6f..d8b9ed711 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -254,10 +254,10 @@ mathops_formats = { memset_formats = { "opcode": "OP_MEMSET_{op_memset[oo].upper()}", "mnemonic": "memset.{op_memset[oo]}", - "opname": "memset", + "opname": "memset{op_memset[oo]}", "format": "{memset_fmt[oo]}", "widths": "{memset_widths[oo]}", - "types": "ev_int, ev_void, ev_void", + "types": "{memset_types[oo]}", "args": { "op_memset": ["i", "p", "pi", None], "memset_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], @@ -267,17 +267,23 @@ memset_formats = { "1, 0, 1", None, ], + "memset_types": [ + "ev_void, ev_short, ev_void", + "ev_ptr, ev_int, ev_ptr", + "ev_ptr, ev_short, ev_ptr", + ], }, } move_formats = { "opcode": "OP_MOVE_{op_move[oo].upper()}", - "mnemonic": "memset.{op_move[oo]}", - "opname": "memset", + "mnemonic": "move.{op_move[oo]}", + "opname": "move{suff_move[oo]}", "format": "{move_fmt[oo]}", "widths": "{move_widths[oo]}", - "types": "ev_int, ev_void, ev_void", + "types": "{move_types[oo]}", "args": { "op_move": ["i", "p", "pi", None], + "suff_move": ["", "p", "p", None], "move_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], "move_widths": [ "-1, 0, -1", @@ -285,6 +291,11 @@ move_formats = { "1, 0, 1", None, ], + "move_types": [ + "ev_void, ev_short, ev_void", + "ev_ptr, ev_int, ev_ptr", + "ev_ptr, ev_short, ev_ptr", + ], }, } noop_formats = { From 982a090143779076e44b24373e1dc94eaac8d77f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jan 2022 12:26:50 +0900 Subject: [PATCH 2300/3664] [qfcc] Mask off base register bits when printing statements Fixes a segfault when compiling Ruamoko progs with debug output. --- tools/qfcc/source/opcodes.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 7687851d9..51c7ce26d 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -403,11 +403,14 @@ void opcode_print_statement (pr_uint_t addr, dstatement_t *st) { const char *mnemonic; + // this is ok because v6p has < 300 instructions + int st_op = st->op & 0x1ff; + if (options.code.progsversion < PROG_VERSION) { - mnemonic = v6p_opcode_map[st->op].opname; + mnemonic = v6p_opcode_map[st_op].opname; } else { - mnemonic = pr_opcodes[st->op].mnemonic; + mnemonic = pr_opcodes[st_op].mnemonic; } printf ("%04x (%03x)%-8s %04x %04x %04x\n", - addr, st->op & 0x1ff, mnemonic, st->a, st->b, st->c); + addr, st_op & 0x1ff, mnemonic, st->a, st->b, st->c); } From 0b9b6955aa656327b8cf3137deeeb3f4f6c66950 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jan 2022 12:28:05 +0900 Subject: [PATCH 2301/3664] [qfcc] Implement addressing modes for return There's still entity.field to go, but basic def and ptr + const offset seem to work. --- tools/qfcc/source/statements.c | 77 ++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 3ff6df7bd..e0ef25160 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1252,6 +1252,70 @@ statement_branch (sblock_t *sblock, expr_t *e) return sblock->next; } +static sblock_t * +addressing_mode (sblock_t *sblock, expr_t *ref, + operand_t **base, operand_t **offset, pr_ushort_t *mode) +{ + if (is_indirect (ref)) { + // ref is known to be either ex_expr or ex_uexpr, with '.' for + // the operator + if (ref->type == ex_expr) { + internal_error (ref, "not implemented"); + } else if (ref->type == ex_uexpr) { + ref = ref->e.expr.e1; + if (!is_ptr (get_type (ref))) { + internal_error (ref, "expected pointer in ref"); + } + if (ref->type != ex_alias || ref->e.alias.offset) { + // probably just a pointer + sblock = statement_subexpr (sblock, ref, base); + *offset = short_operand (0, ref); + *mode = 2; // mode C: ptr + constant index + } else { + // alias with no offset + if (!is_integral (get_type (ref->e.alias.expr))) { + internal_error (ref, "expected integer expr in ref"); + } + expr_t *intptr = ref->e.alias.expr; + if (intptr->type != ex_expr + || (intptr->e.expr.op != '+' + && intptr->e.expr.op != '-')) { + // treat ref as simple pointer + sblock = statement_subexpr (sblock, ref, base); + *offset = short_operand (0, ref); + *mode = 2; // mode C: ptr + constant index + } else { + expr_t *ptr = intptr->e.expr.e1; + expr_t *offs = intptr->e.expr.e2; + int const_offs; + // move the +/- to the offset + offs = unary_expr (intptr->e.expr.op, offs); + // make the base a pointer again + ptr = new_alias_expr (ref->e.alias.type, ptr); + sblock = statement_subexpr (sblock, ptr, base); + if (is_constant (offs) + && (const_offs = expr_int (offs)) < 32768 + && const_offs >= -32768) { + *mode = 2; + *offset = short_operand (const_offs, ref); + } else { + *mode = 3; + sblock = statement_subexpr (sblock, offs, offset); + } + } + } + } else { + internal_error (ref, "unexpected expression type for indirect: %s", + expr_names[ref->type]); + } + } else { + sblock = statement_subexpr (sblock, ref, base); + *offset = short_operand (0, ref); + *mode = 0; + } + return sblock; +} + static sblock_t * statement_return (sblock_t *sblock, expr_t *e) { @@ -1277,16 +1341,15 @@ statement_return (sblock_t *sblock, expr_t *e) if (e->e.retrn.ret_val) { expr_t *ret_val = e->e.retrn.ret_val; type_t *ret_type = get_type (ret_val); - if (is_indirect (ret_val)) { - } else { - sblock = statement_subexpr (sblock, ret_val, &s->opa); - s->opb = short_operand (0, e); - s->opc = short_operand (type_size (ret_type) - 1, e); - } + pr_ushort_t ret_crtl = type_size (ret_type) - 1; + pr_ushort_t mode = 0; + sblock = addressing_mode (sblock, ret_val, &s->opa, &s->opb, &mode); + ret_crtl |= mode << 5; + s->opc = short_operand (ret_crtl, e); } else { s->opa = short_operand (0, e); s->opb = short_operand (0, e); - s->opc = short_operand (-1, e); + s->opc = short_operand (-1, e); // void return } } sblock_add_statement (sblock, s); From 90b40e7e52d6d8c81e3bd2a85ed9acf46cd62b97 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jan 2022 12:56:15 +0900 Subject: [PATCH 2302/3664] [qfcc] Ensure adjstk and with always come first While I think the reason the dags code moved an instruction before adjstk and with was they shared a constant with that instruction (which is a different bug), this ensures other instructions cannot get reordered in front of adjstk and with, as doing so would cause any such instructions to access incorrect data. --- tools/qfcc/source/function.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 81a20af46..d094fc152 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -729,17 +729,32 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) } function_t *func = fsym->s.func; if (options.code.progsversion == PROG_VERSION) { + /* Create a function entry block to set up the stack frame and add the + * actual function code to that block. This ensure that the adjstk and + * with statements always come first, regardless of what ideas the + * optimizer gets. + */ expr_t *e; - e = new_with_expr (2, LOCALS_REG, new_short_expr (0)); - e->file = func->def->file; - e->line = func->def->line; - prepend_expr (statements, e); + expr_t *entry = new_block_expr (); + entry->file = func->def->file; + entry->line = func->def->line; e = new_adjstk_expr (0, 0); e->file = func->def->file; e->line = func->def->line; - prepend_expr (statements, e); + append_expr (entry, e); + e = new_with_expr (2, LOCALS_REG, new_short_expr (0)); + e->file = func->def->file; + e->line = func->def->line; + append_expr (entry, e); + + append_expr (entry, statements); + statements = entry; + + /* Mark all local defs as using the base register used for stack + * references. + */ func->temp_reg = LOCALS_REG; for (def_t *def = func->locals->space->defs; def; def = def->next) { if (def->local || def->param) { From a2f4522e76442a3711d54e5fd5babdb7c9b0052a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jan 2022 16:55:14 +0900 Subject: [PATCH 2303/3664] [gamecode] Align Ruamoko progs to 32 bytes. Intel hardware requires 32-byte alignment for lvec4 and dvec4. Unfortunately, it turns out that my attempts to align progs data in qfcc went awry do to the order block sizes are calculated when writing the progs. --- libs/gamecode/pr_load.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index e8538d5bd..6d7116856 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -95,13 +95,10 @@ free_progs_mem (progs_t *pr, void *mem) } static int -align_size (int size) +align_size (int size, int align) { - // round off to next highest whole word address (esp for Alpha) - // this ensures that pointers in the engine data area are always - // properly aligned - size += sizeof (void*) - 1; - size &= ~(sizeof (void*) - 1); + size += align - 1; + size &= ~(align - 1); return size; } @@ -117,6 +114,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr_def_t *xdefs_def = 0; ddef_t *global_ddefs; ddef_t *field_ddefs; + // absolute minimum alignment is 4 bytes + int alignment = sizeof (void *); if (!pr->file_error) pr->file_error = file_error; @@ -163,6 +162,12 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) PROG_VERSION & 0xfff); } } + if (progs.version == PROG_VERSION) { + // ensure SIMD types can be aligned (qfcc will align them within + // the progs memory map, so the engine needs to ensure the progs memory + // is aligned) + alignment = __alignof__(pr_lvec4_t); + } // Some compilers (eg, FTE) put extra data between the header and the // strings section. What's worse, they de-align the data. @@ -173,17 +178,14 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->progs_size = size + offset_tweak; Sys_MaskPrintf (SYS_dev, "Programs occupy %iK.\n", size / 1024); - pr->progs_size = align_size (pr->progs_size); - pr->zone_size = align_size (pr->zone_size); - pr->stack_size = align_size (pr->stack_size); + pr->progs_size = align_size (pr->progs_size, alignment); + pr->zone_size = align_size (pr->zone_size, alignment); + pr->stack_size = align_size (pr->stack_size, alignment); // size of edict asked for by progs, but at least 1 pr->pr_edict_size = max (1, progs.entityfields); - // round off to next highest multiple of 4 words - // this ensures that progs that try to align vectors and quaternions - // get what they want - pr->pr_edict_size += (4 - 1); - pr->pr_edict_size &= ~(4 - 1); + // edict size is in words + pr->pr_edict_size = align_size (pr->pr_edict_size, alignment / 4); pr->pr_edict_area_size = pr->max_edicts * pr->pr_edict_size; mem_size = pr->pr_edict_area_size * sizeof (pr_type_t); From a2fd42f174e8ec61f3d40c930f813d6042dac2ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jan 2022 16:57:34 +0900 Subject: [PATCH 2304/3664] [qfcc] Align progs memory to 32 bytes in the test harness This ensures the engine can align everything to 32 bytes. --- tools/qfcc/test/test-harness.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index bf51508b9..a0a4bfd0c 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -120,10 +120,14 @@ load_file (progs_t *pr, const char *name, off_t *_size) return sym; } +#define ALIGN 32 + static void * allocate_progs_mem (progs_t *pr, int size) { - return malloc (size); + intptr_t mem = (intptr_t) malloc (size + ALIGN); + mem = (mem + ALIGN - 1) & ~(ALIGN - 1); + return (void *) mem; } static void From faa98d81985773fa86f4508e6b8875b5c45990da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jan 2022 19:30:25 +0900 Subject: [PATCH 2305/3664] [gamecode] Use a struct for offset/count pairs This cleans up dprograms_t, making it easier to read and see what chunks are in it (I was surprised to see only 6, the explicit pairs made it seem to have more). --- include/QF/progs/pr_comp.h | 30 +++++------ libs/gamecode/pr_builtins.c | 4 +- libs/gamecode/pr_debug.c | 24 ++++----- libs/gamecode/pr_exec.c | 6 +-- libs/gamecode/pr_load.c | 38 ++++++------- libs/gamecode/pr_parse.c | 4 +- libs/gamecode/pr_resolve.c | 4 +- libs/gamecode/pr_strings.c | 2 +- libs/gamecode/pr_v6p_opcode.c | 12 ++--- libs/gamecode/test/main.c | 2 +- ruamoko/qwaq/builtins/debug.c | 8 +-- tools/qfcc/source/disassemble.c | 2 +- tools/qfcc/source/dump_globals.c | 18 +++---- tools/qfcc/source/dump_lines.c | 2 +- tools/qfcc/source/dump_modules.c | 2 +- tools/qfcc/source/dump_strings.c | 2 +- tools/qfcc/source/idstuff.c | 12 ++--- tools/qfcc/source/obj_file.c | 92 ++++++++++++++++---------------- tools/qfcc/source/qfcc.c | 20 +++---- tools/qfcc/source/qfprogs.c | 2 +- 20 files changed, 140 insertions(+), 146 deletions(-) diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 88a644f62..4ae88e18e 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -552,27 +552,21 @@ typedef struct pr_va_list_s { #define PROG_V6P_VERSION PROG_VERSION_ENCODE(0,fff,00a) #define PROG_VERSION PROG_VERSION_ENCODE(0,fff,010) +typedef struct pr_chunk_s { + pr_uint_t offset; + pr_uint_t count; +} pr_chunk_t; + typedef struct dprograms_s { pr_uint_t version; - pr_uint_t crc; // check of header file + pr_uint_t crc; // checksum of header file - pr_uint_t ofs_statements; - pr_uint_t numstatements; // statement 0 is an error - - pr_uint_t ofs_globaldefs; - pr_uint_t numglobaldefs; - - pr_uint_t ofs_fielddefs; - pr_uint_t numfielddefs; - - pr_uint_t ofs_functions; - pr_uint_t numfunctions; // function 0 is an empty - - pr_uint_t ofs_strings; - pr_uint_t numstrings; // first string is a null string - - pr_uint_t ofs_globals; - pr_uint_t numglobals; + pr_chunk_t statements; // statement 0 is an error + pr_chunk_t globaldefs; + pr_chunk_t fielddefs; + pr_chunk_t functions; // function 0 is an empty + pr_chunk_t strings; // first string is a null string, count is bytes + pr_chunk_t globals; pr_uint_t entityfields; } dprograms_t; diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index ab5088b9b..fcccb57a4 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -188,10 +188,10 @@ PR_RelocateBuiltins (progs_t *pr) if (pr->function_table) free (pr->function_table); - pr->function_table = calloc (pr->progs->numfunctions, + pr->function_table = calloc (pr->progs->functions.count, sizeof (bfunction_t)); - for (i = 1; i < pr->progs->numfunctions; i++) { + for (i = 1; i < pr->progs->functions.count; i++) { desc = pr->pr_functions + i; func = pr->function_table + i; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index a30aa8c66..9eff304dd 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -549,12 +549,12 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) res->debug_data = (pr_type_t*)((char*)debug + debug->debug_data); size_t size; - size = pr->progs->numfunctions * sizeof (pr_auxfunction_t *); + size = pr->progs->functions.count * sizeof (pr_auxfunction_t *); res->auxfunction_map = pr->allocate_progs_mem (pr, size); - size = pr->progs->numfunctions * sizeof (pr_func_t); + size = pr->progs->functions.count * sizeof (pr_func_t); res->sorted_functions = pr->allocate_progs_mem (pr, size); - for (pr_uint_t i = 0; i < pr->progs->numfunctions; i++) { + for (pr_uint_t i = 0; i < pr->progs->functions.count; i++) { res->auxfunction_map[i] = 0; res->sorted_functions[i] = i; } @@ -575,7 +575,7 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) res->auxfunction_map[res->auxfunctions[i].function] = &res->auxfunctions[i]; } - qsort_r (res->sorted_functions, pr->progs->numfunctions, + qsort_r (res->sorted_functions, pr->progs->functions.count, sizeof (pr_func_t), func_compare_sort, res); for (pr_uint_t i = 0; i < debug->num_locals; i++) { @@ -733,7 +733,7 @@ VISIBLE pr_auxfunction_t * PR_Debug_MappedAuxFunction (progs_t *pr, pr_uint_t func) { prdeb_resources_t *res = pr->pr_debug_resources; - if (!res->debug || func >= pr->progs->numfunctions) { + if (!res->debug || func >= pr->progs->functions.count) { return 0; } return res->auxfunction_map[func]; @@ -841,7 +841,7 @@ PR_FindSourceLineAddr (progs_t *pr, const char *file, pr_uint_t line) prdeb_resources_t *res = pr->pr_debug_resources; func_key_t key = { file, line }; pr_func_t *f = fbsearch_r (&key, res->sorted_functions, - pr->progs->numfunctions, sizeof (pr_func_t), + pr->progs->functions.count, sizeof (pr_func_t), func_compare_search, res); if (!f) { return 0; @@ -878,7 +878,7 @@ PR_Get_Source_File (progs_t *pr, pr_lineno_t *lineno) pr_auxfunction_t *f; f = PR_Get_Lineno_Func (pr, lineno); - if (f->function >= (unsigned) pr->progs->numfunctions) + if (f->function >= (unsigned) pr->progs->functions.count) return 0; return PR_GetString(pr, pr->pr_functions[f->function].file); } @@ -1113,7 +1113,7 @@ pr_debug_find_def (progs_t *pr, pr_ptr_t *ofs) prdeb_resources_t *res = pr->pr_debug_resources; pr_def_t *def = 0; - if (*ofs >= pr->progs->numglobals) { + if (*ofs >= pr->progs->globals.count) { return 0; } if (pr_debug->int_val && res->debug) { @@ -1306,7 +1306,7 @@ pr_debug_func_view (qfot_type_t *type, pr_type_t *value, void *_data) progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - if (value->func_var >= pr->progs->numfunctions) { + if (value->func_var >= pr->progs->functions.count) { dasprintf (dstr, "INVALID:%d", value->func_var); } else if (!value->func_var) { dstring_appendstr (dstr, "NULL"); @@ -1652,7 +1652,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) str = global_string (&data, opval, optype, contents & 1); func = G_FUNCTION (pr, opval); - if (func < pr->progs->numfunctions) { + if (func < pr->progs->functions.count) { call_func = pr->pr_functions + func; } break; @@ -1790,7 +1790,7 @@ PR_Profile (progs_t * pr) do { max = 0; best = NULL; - for (i = 0; i < pr->progs->numfunctions; i++) { + for (i = 0; i < pr->progs->functions.count; i++) { bf = &pr->function_table[i]; if (bf->profile > max) { max = bf->profile; @@ -1862,7 +1862,7 @@ ED_Print (progs_t *pr, edict_t *ed, const char *fieldname) } return; } - for (i = 0; i < pr->progs->numfielddefs; i++) { + for (i = 0; i < pr->progs->fielddefs.count; i++) { d = &pr->pr_fielddefs[i]; if (!d->name) // null field def (probably 1st) continue; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index b0a81c376..3c0734617 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1459,7 +1459,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_JUMP_v6p: if (pr_boundscheck->int_val - && (OPA(uint) >= pr->progs->numstatements)) { + && (OPA(uint) >= pr->progs->statements.count)) { PR_RunError (pr, "Invalid jump destination"); } pr->pr_xstatement = OPA(uint) - 1; // offset the st++ @@ -1473,7 +1473,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) ptr = pr->pr_globals + pointer; pointer = ptr->int_var; if (pr_boundscheck->int_val - && (pointer >= pr->progs->numstatements)) { + && (pointer >= pr->progs->statements.count)) { PR_RunError (pr, "Invalid jump destination"); } pr->pr_xstatement = pointer - 1; // offset the st++ @@ -1874,7 +1874,7 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind) jump_offs = OPA(ptr) + OPB(int); break; } - if (pr_boundscheck->int_val && jump_offs >= pr->progs->numstatements) { + if (pr_boundscheck->int_val && jump_offs >= pr->progs->statements.count) { PR_RunError (pr, "out of bounds: %x", jump_offs); } return jump_offs - 1; // for st++ diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 6d7116856..165ca789b 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -171,7 +171,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) // Some compilers (eg, FTE) put extra data between the header and the // strings section. What's worse, they de-align the data. - offset_tweak = progs.ofs_strings % sizeof (pr_int_t); + offset_tweak = progs.strings.offset % sizeof (pr_int_t); offset_tweak = (sizeof (pr_int_t) - offset_tweak) % sizeof (pr_int_t); // size of progs themselves @@ -216,14 +216,14 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->zone = (memzone_t *) heap; } - pr->pr_functions = (dfunction_t *) (base + pr->progs->ofs_functions); - pr->pr_strings = (char *) base + pr->progs->ofs_strings; + pr->pr_functions = (dfunction_t *) (base + pr->progs->functions.offset); + pr->pr_strings = (char *) base + pr->progs->strings.offset; pr->pr_stringsize = (heap - base) + pr->zone_size; - global_ddefs = (ddef_t *) (base + pr->progs->ofs_globaldefs); - field_ddefs = (ddef_t *) (base + pr->progs->ofs_fielddefs); - pr->pr_statements = (dstatement_t *) (base + pr->progs->ofs_statements); + global_ddefs = (ddef_t *) (base + pr->progs->globaldefs.offset); + field_ddefs = (ddef_t *) (base + pr->progs->fielddefs.offset); + pr->pr_statements = (dstatement_t *) (base + pr->progs->statements.offset); - pr->pr_globals = (pr_type_t *) (base + pr->progs->ofs_globals); + pr->pr_globals = (pr_type_t *) (base + pr->progs->globals.offset); pr->stack = (pr_type_t *) ((byte *) pr->zone + pr->zone_size); pr->stack_bottom = pr->stack - pr->pr_globals; pr->globals_size = (pr_type_t *) ((byte *) pr->stack + pr->stack_size) @@ -241,14 +241,14 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) Hash_FlushTable (pr->field_hash); // byte swap the lumps - for (i = 0; i < pr->progs->numstatements; i++) { + for (i = 0; i < pr->progs->statements.count; i++) { pr->pr_statements[i].op = LittleShort (pr->pr_statements[i].op); pr->pr_statements[i].a = LittleShort (pr->pr_statements[i].a); pr->pr_statements[i].b = LittleShort (pr->pr_statements[i].b); pr->pr_statements[i].c = LittleShort (pr->pr_statements[i].c); } - for (i = 0; i < pr->progs->numfunctions; i++) { + for (i = 0; i < pr->progs->functions.count; i++) { pr->pr_functions[i].first_statement = LittleLong (pr->pr_functions[i].first_statement); pr->pr_functions[i].parm_start = @@ -265,9 +265,9 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) if (pr->pr_globaldefs) { free (pr->pr_globaldefs); } - pr->pr_globaldefs = calloc (pr->progs->numglobaldefs, sizeof (pr_def_t)); + pr->pr_globaldefs = calloc (pr->progs->globaldefs.count, sizeof (pr_def_t)); - for (i = 0; i < pr->progs->numglobaldefs; i++) { + for (i = 0; i < pr->progs->globaldefs.count; i++) { pr_ushort_t safe_type = global_ddefs[i].type & ~DEF_SAVEGLOBAL; global_ddefs[i].type = LittleShort (global_ddefs[i].type); global_ddefs[i].ofs = LittleShort (global_ddefs[i].ofs); @@ -283,8 +283,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) if (pr->pr_fielddefs) { free (pr->pr_fielddefs); } - pr->pr_fielddefs = calloc (pr->progs->numfielddefs, sizeof (pr_def_t)); - for (i = 0; i < pr->progs->numfielddefs; i++) { + pr->pr_fielddefs = calloc (pr->progs->fielddefs.count, sizeof (pr_def_t)); + for (i = 0; i < pr->progs->fielddefs.count; i++) { field_ddefs[i].type = LittleShort (field_ddefs[i].type); if (field_ddefs[i].type & DEF_SAVEGLOBAL) PR_Error (pr, "PR_LoadProgs: DEF_SAVEGLOBAL on field def %zd", i); @@ -297,7 +297,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) Hash_Add (pr->field_hash, &pr->pr_fielddefs[i]); } - for (i = 0; i < pr->progs->numglobals; i++) + for (i = 0; i < pr->progs->globals.count; i++) ((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]); xdefs_def = PR_FindGlobal (pr, ".xdefs"); @@ -305,23 +305,23 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr_xdefs_t *xdefs = &G_STRUCT (pr, pr_xdefs_t, xdefs_def->ofs); xdef_t *xdef = &G_STRUCT (pr, xdef_t, xdefs->xdefs); pr_def_t *def; - for (def = pr->pr_globaldefs, i = 0; i < pr->progs->numglobaldefs; + for (def = pr->pr_globaldefs, i = 0; i < pr->progs->globaldefs.count; i++, xdef++, def++) { def->ofs = xdef->ofs; def->type_encoding = xdef->type; } - for (def = pr->pr_fielddefs, i = 0; i < pr->progs->numfielddefs; + for (def = pr->pr_fielddefs, i = 0; i < pr->progs->fielddefs.count; i++, xdef++, def++) { def->ofs = xdef->ofs; def->type_encoding = xdef->type; } } else { pr_def_t *def; - for (def = pr->pr_globaldefs, i = 0; i < pr->progs->numglobaldefs; + for (def = pr->pr_globaldefs, i = 0; i < pr->progs->globaldefs.count; i++, def++) { def->size = pr_type_size[def->type & ~DEF_SAVEGLOBAL]; } - for (def = pr->pr_fielddefs, i = 0; i < pr->progs->numfielddefs; + for (def = pr->pr_fielddefs, i = 0; i < pr->progs->fielddefs.count; i++, def++) { def->size = pr_type_size[def->type & ~DEF_SAVEGLOBAL]; } @@ -369,7 +369,7 @@ pr_run_ctors (progs_t *pr) pr_uint_t fnum; dfunction_t *func; - for (fnum = 0; fnum < pr->progs->numfunctions; fnum++) { + for (fnum = 0; fnum < pr->progs->functions.count; fnum++) { func = pr->pr_functions + fnum; if (strequal (PR_GetString (pr, func->name), ".ctor")) PR_ExecuteProgram (pr, fnum); diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 5f360c054..182146261 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -118,7 +118,7 @@ ED_EntityDict (progs_t *pr, edict_t *ed) pr_type_t *v; if (!ed->free) { - for (i = 0; i < pr->progs->numfielddefs; i++) { + for (i = 0; i < pr->progs->fielddefs.count; i++) { pr_def_t *d = &pr->pr_fielddefs[i]; name = PR_GetString (pr, d->name); @@ -162,7 +162,7 @@ ED_GlobalsDict (progs_t *pr) pr_def_t *def; int type; - for (i = 0; i < pr->progs->numglobaldefs; i++) { + for (i = 0; i < pr->progs->globaldefs.count; i++) { def = &pr->pr_globaldefs[i]; type = def->type; if (!(def->type & DEF_SAVEGLOBAL)) diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 992aff74e..864baa443 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -71,13 +71,13 @@ PR_SearchDefs (pr_def_t *defs, unsigned num_defs, pr_ptr_t offset) pr_def_t * PR_GlobalAtOfs (progs_t * pr, pr_ptr_t ofs) { - return PR_SearchDefs (pr->pr_globaldefs, pr->progs->numglobaldefs, ofs); + return PR_SearchDefs (pr->pr_globaldefs, pr->progs->globaldefs.count, ofs); } VISIBLE pr_def_t * PR_FieldAtOfs (progs_t * pr, pr_ptr_t ofs) { - return PR_SearchDefs (pr->pr_fielddefs, pr->progs->numfielddefs, ofs); + return PR_SearchDefs (pr->pr_fielddefs, pr->progs->fielddefs.count, ofs); } VISIBLE pr_def_t * diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 3c75984d2..b8364d89c 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -234,7 +234,7 @@ PR_LoadStrings (progs_t *pr) { prstr_resources_t *res = PR_Resources_Find (pr, "Strings"); - char *end = pr->pr_strings + pr->progs->numstrings; + char *end = pr->pr_strings + pr->progs->strings.count; char *str = pr->pr_strings; int count = 0; diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 94da01a4c..13f129553 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -1493,7 +1493,7 @@ check_branch (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, short offse pr_int_t address = st - pr->pr_statements; address += offset; - if (address < 0 || (pr_uint_t) address >= pr->progs->numstatements) + if (address < 0 || (pr_uint_t) address >= pr->progs->statements.count) PR_Error (pr, "PR_Check_Opcodes: invalid branch (statement %ld: %s)", (long)(st - pr->pr_statements), op->opname); } @@ -1534,8 +1534,8 @@ check_global (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, etype_t typ break; default: if (operand + (unsigned) pr_type_size[type] - > pr->progs->numglobals) { - if (operand >= pr->progs->numglobals + > pr->progs->globals.count) { + if (operand >= pr->progs->globals.count || !is_vector_parameter_store (pr, st, operand)) { msg = "out of bounds global index"; goto error; @@ -1579,7 +1579,7 @@ check_global_size (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, unsigned short size, unsigned short operand) { const char *msg; - if (operand + size > pr->progs->numglobals) { + if (operand + size > pr->progs->globals.count) { msg = "out of bounds global index"; goto error; } @@ -1611,7 +1611,7 @@ PR_Check_v6p_Opcodes (progs_t *pr) // the only problem is that it slows progs load a little, but it's the only // way to check for qccx' evil if (0 && !pr_boundscheck->int_val) { - for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; + for (i = 0, st = pr->pr_statements; i < pr->progs->statements.count; st++, i++) { pr_opcode_v6p_e st_op = st->op; op = PR_v6p_Opcode (st_op); @@ -1632,7 +1632,7 @@ PR_Check_v6p_Opcodes (progs_t *pr) } } } else { - for (i = 0, st = pr->pr_statements; i < pr->progs->numstatements; + for (i = 0, st = pr->pr_statements; i < pr->progs->statements.count; st++, i++) { pr_opcode_v6p_e st_op = st->op; op = PR_v6p_Opcode (st_op); diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 9f988fd50..bb0efb2fd 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -132,7 +132,7 @@ setup_test (test_t *test) } } - test_progs.numstatements = test->num_statements + 1; + test_progs.statements.count = test->num_statements + 1; test_pr.pr_statements = malloc ((test->num_statements + 1) * sizeof (dstatement_t)); memcpy (test_pr.pr_statements, test->statements, diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index c9da1e923..10c09c136 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -221,7 +221,7 @@ qdb_set_breakpoint (progs_t *pr) qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; - if (staddr >= tpr->progs->numstatements) { + if (staddr >= tpr->progs->statements.count) { R_INT (pr) = -1; return; } @@ -239,7 +239,7 @@ qdb_clear_breakpoint (progs_t *pr) qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; - if (staddr >= tpr->progs->numstatements) { + if (staddr >= tpr->progs->statements.count) { R_INT (pr) = -1; return; } @@ -555,7 +555,7 @@ qdb_get_function (progs_t *pr) pr_uint_t fnum = P_INT (pr, 1); dfunction_t *func = tpr->pr_functions + fnum; - if (fnum >= tpr->progs->numfunctions) { + if (fnum >= tpr->progs->functions.count) { func = 0; } return_function (pr, func); @@ -591,7 +591,7 @@ qdb_find_auxfunction (progs_t *pr) pr_uint_t fnum = func - tpr->pr_functions; pr_auxfunction_t *auxfunc = PR_Debug_MappedAuxFunction (tpr, fnum); - if (fnum >= tpr->progs->numfunctions) { + if (fnum >= tpr->progs->functions.count) { func = 0; } return_auxfunction (pr, auxfunc); diff --git a/tools/qfcc/source/disassemble.c b/tools/qfcc/source/disassemble.c index 60e4765bc..953ab8143 100644 --- a/tools/qfcc/source/disassemble.c +++ b/tools/qfcc/source/disassemble.c @@ -63,7 +63,7 @@ disassemble_progs (progs_t *pr) { unsigned int i; - for (i = 0; i < pr->progs->numstatements; i++) { + for (i = 0; i < pr->progs->statements.count; i++) { dfunction_t *desc = func_find (i); if (desc) { diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 69cc1e61a..256c5e9d6 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -79,7 +79,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) comment = " invalid offset"; - if (offset < pr->progs->numglobals) { + if (offset < pr->progs->globals.count) { comment = ""; switch (def->type & ~DEF_SAVEGLOBAL) { case ev_void: @@ -91,7 +91,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) // dynamically allocated, thus a negative string index should // never appear in compiled code if (string < 0 - || (pr_uint_t) string >= pr->progs->numstrings) { + || (pr_uint_t) string >= pr->progs->strings.count) { str = "invalid string offset"; comment = va (0, " %d %s", string, str); } else { @@ -120,7 +120,7 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) { pr_func_t func = G_FUNCTION (pr, offset); int start; - if (func < pr->progs->numfunctions) { + if (func < pr->progs->functions.count) { start = pr->pr_functions[func].first_statement; if (start > 0) comment = va (0, " %d @ %x", func, start); @@ -165,12 +165,12 @@ dump_globals (progs_t *pr) pr_def_t *global_defs = pr->pr_globaldefs; if (sorted) { - global_defs = malloc (pr->progs->numglobaldefs * sizeof (ddef_t)); + global_defs = malloc (pr->progs->globaldefs.count * sizeof (ddef_t)); memcpy (global_defs, pr->pr_globaldefs, - pr->progs->numglobaldefs * sizeof (ddef_t)); - qsort (global_defs, pr->progs->numglobaldefs, sizeof (ddef_t), cmp); + pr->progs->globaldefs.count * sizeof (ddef_t)); + qsort (global_defs, pr->progs->globaldefs.count, sizeof (ddef_t), cmp); } - for (i = 0; i < pr->progs->numglobaldefs; i++) { + for (i = 0; i < pr->progs->globaldefs.count; i++) { pr_def_t *def = &global_defs[i]; dump_def (pr, def, 0); } @@ -185,7 +185,7 @@ dump_fields (progs_t *pr) int offset; const char *comment; - for (i = 0; i < pr->progs->numfielddefs; i++) { + for (i = 0; i < pr->progs->fielddefs.count; i++) { pr_def_t *def = &pr->pr_fielddefs[i]; name = PR_GetString (pr, def->name); @@ -248,7 +248,7 @@ dump_functions (progs_t *pr) type_encodings = encodings_def->ofs; } - for (i = 0; i < pr->progs->numfunctions; i++) { + for (i = 0; i < pr->progs->functions.count; i++) { dfunction_t *func = &pr->pr_functions[i]; name = PR_GetString (pr, func->name); diff --git a/tools/qfcc/source/dump_lines.c b/tools/qfcc/source/dump_lines.c index f021e48a3..4b95b3ad3 100644 --- a/tools/qfcc/source/dump_lines.c +++ b/tools/qfcc/source/dump_lines.c @@ -78,7 +78,7 @@ progs_get_func_data (unsigned func_index, void *data) func_data.local_defs = aux_func->local_defs; func_data.line_info = aux_func->line_info; func_data.function = aux_func->function; - if (aux_func->function < (unsigned int) pr->progs->numfunctions) { + if (aux_func->function < (unsigned int) pr->progs->functions.count) { func = pr->pr_functions + aux_func->function; func_data.source_file = pr->pr_strings + func->file; func_data.source_name = pr->pr_strings + func->name; diff --git a/tools/qfcc/source/dump_modules.c b/tools/qfcc/source/dump_modules.c index 5f0f590f2..70dfe35c0 100644 --- a/tools/qfcc/source/dump_modules.c +++ b/tools/qfcc/source/dump_modules.c @@ -277,7 +277,7 @@ dump_modules (progs_t *pr) { unsigned int i; - for (i = 0; i < pr->progs->numglobaldefs; i++) { + for (i = 0; i < pr->progs->globaldefs.count; i++) { pr_def_t *def = &pr->pr_globaldefs[i]; const char *name = ""; diff --git a/tools/qfcc/source/dump_strings.c b/tools/qfcc/source/dump_strings.c index c8507011e..df4ca1b04 100644 --- a/tools/qfcc/source/dump_strings.c +++ b/tools/qfcc/source/dump_strings.c @@ -78,7 +78,7 @@ dump_string_block (const char *strblock, size_t size) void dump_strings (progs_t *pr) { - dump_string_block (pr->pr_strings, pr->progs->numstrings); + dump_string_block (pr->pr_strings, pr->progs->strings.count); } void diff --git a/tools/qfcc/source/idstuff.c b/tools/qfcc/source/idstuff.c index 9fb7f5003..34e9c4d7b 100644 --- a/tools/qfcc/source/idstuff.c +++ b/tools/qfcc/source/idstuff.c @@ -212,9 +212,9 @@ WriteProgdefs (dprograms_t *progs, const char *filename) "\n\ntypedef struct\n{\tint\tpad[%i];\n", RESERVED_OFS); - strings = (char *) progs + progs->ofs_strings; - for (i = 0; i < progs->numglobaldefs; i++) { - def = (ddef_t *) ((char *) progs + progs->ofs_globaldefs) + i; + strings = (char *) progs + progs->strings.offset; + for (i = 0; i < progs->globaldefs.count; i++) { + def = (ddef_t *) ((char *) progs + progs->globaldefs.offset) + i; name = strings + def->name; if (!strcmp (name, "end_sys_globals")) break; @@ -251,8 +251,8 @@ WriteProgdefs (dprograms_t *progs, const char *filename) // print all fields dasprintf (dstr, "typedef struct\n{\n"); - for (i = 0, j = 0; i < progs->numglobaldefs; i++) { - def = (ddef_t *) ((char *) progs + progs->ofs_globaldefs) + i; + for (i = 0, j = 0; i < progs->globaldefs.count; i++) { + def = (ddef_t *) ((char *) progs + progs->globaldefs.offset) + i; name = strings + def->name; if (!strcmp (name, "end_sys_fields")) break; @@ -264,7 +264,7 @@ WriteProgdefs (dprograms_t *progs, const char *filename) if (!strcmp (name, ".imm")) continue; - fdef = (ddef_t *) ((char *) progs + progs->ofs_fielddefs) + j++; + fdef = (ddef_t *) ((char *) progs + progs->fielddefs.offset) + j++; if (fdef->name != def->name) internal_error (0, "def and field order messup"); diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 6a53b32ab..fa650a822 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -970,18 +970,18 @@ qfo_to_progs (qfo_t *in_qfo, int *size) *size = RUP (sizeof (dprograms_t), 16); progs = calloc (1, *size); progs->version = options.code.progsversion; - progs->numstatements = qfo->spaces[qfo_code_space].data_size; - progs->numglobaldefs = qfo->spaces[qfo_near_data_space].num_defs; + progs->statements.count = qfo->spaces[qfo_code_space].data_size; + progs->globaldefs.count = qfo->spaces[qfo_near_data_space].num_defs; //ddef offsets are 16 bits so the ddef ofs will likely be invalid //thus it will be forced invalid and the true offset written to the //.xdefs array in the progs file - progs->numglobaldefs += qfo->spaces[qfo_far_data_space].num_defs; - progs->numfielddefs = qfo->spaces[qfo_entity_space].num_defs; - progs->numfunctions = qfo->num_funcs + 1; - progs->numstrings = qfo->spaces[qfo_strings_space].data_size; - progs->numglobals = qfo->spaces[qfo_near_data_space].data_size; - progs->numglobals = align_globals_size (progs->numglobals); - locals_start = progs->numglobals; + progs->globaldefs.count += qfo->spaces[qfo_far_data_space].num_defs; + progs->fielddefs.count = qfo->spaces[qfo_entity_space].num_defs; + progs->functions.count = qfo->num_funcs + 1; + progs->strings.count = qfo->spaces[qfo_strings_space].data_size; + progs->globals.count = qfo->spaces[qfo_near_data_space].data_size; + progs->globals.count = align_globals_size (progs->globals.count); + locals_start = progs->globals.count; if (options.code.progsversion < PROG_VERSION) { for (i = qfo_num_spaces; i < qfo->num_spaces; i++) { if (options.code.local_merging) { @@ -994,34 +994,34 @@ qfo_to_progs (qfo_t *in_qfo, int *size) } } } - progs->numglobals += locals_size; - near_data_size = progs->numglobals; - progs->numglobals = RUP (progs->numglobals, 16 / sizeof (pr_type_t)); - progs->numglobals += qfo->spaces[qfo_far_data_space].data_size; - type_encodings_start = progs->numglobals; - progs->numglobals += qfo->spaces[qfo_type_space].data_size; - progs->numglobals = RUP (progs->numglobals, type_xdef.alignment); - xdefs_start = progs->numglobals; - progs->numglobals += progs->numglobaldefs * type_size (&type_xdef); - progs->numglobals += progs->numfielddefs * type_size (&type_xdef); + progs->globals.count += locals_size; + near_data_size = progs->globals.count; + progs->globals.count = RUP (progs->globals.count, 16 / sizeof (pr_type_t)); + progs->globals.count += qfo->spaces[qfo_far_data_space].data_size; + type_encodings_start = progs->globals.count; + progs->globals.count += qfo->spaces[qfo_type_space].data_size; + progs->globals.count = RUP (progs->globals.count, type_xdef.alignment); + xdefs_start = progs->globals.count; + progs->globals.count += progs->globaldefs.count * type_size (&type_xdef); + progs->globals.count += progs->fielddefs.count * type_size (&type_xdef); progs->entityfields = qfo->spaces[qfo_entity_space].data_size; // qfo_debug_space does not go in the progs file - *size += progs->numstatements * sizeof (dstatement_t); - *size += progs->numglobaldefs * sizeof (ddef_t); - *size += progs->numfielddefs * sizeof (ddef_t); - *size += progs->numfunctions * sizeof (dfunction_t); - *size += RUP (progs->numstrings * sizeof (char), 16); - *size += progs->numglobals * sizeof (pr_type_t); + *size += progs->statements.count * sizeof (dstatement_t); + *size += progs->globaldefs.count * sizeof (ddef_t); + *size += progs->fielddefs.count * sizeof (ddef_t); + *size += progs->functions.count * sizeof (dfunction_t); + *size += RUP (progs->strings.count * sizeof (char), 16); + *size += progs->globals.count * sizeof (pr_type_t); progs = realloc (progs, *size); data = (byte *) progs; memset (progs + 1, 0, *size - sizeof (dprograms_t)); data += RUP (sizeof (dprograms_t), 16); - def_indices = alloca ((progs->numglobaldefs + progs->numfielddefs) + def_indices = alloca ((progs->globaldefs.count + progs->fielddefs.count) * sizeof (*def_indices)); far_def_indices = def_indices + qfo->spaces[qfo_near_data_space].num_defs; - field_def_indices = def_indices + progs->numglobaldefs; + field_def_indices = def_indices + progs->globaldefs.count; for (unsigned i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { def_indices[i] = i; } @@ -1041,28 +1041,28 @@ qfo_to_progs (qfo_t *in_qfo, int *size) sizeof (unsigned), qfo_def_compare, qfo->spaces[qfo_entity_space].defs); - progs->ofs_strings = data - (byte *) progs; + progs->strings.offset = data - (byte *) progs; strings = (char *) data; - data += RUP (progs->numstrings * sizeof (char), 16); + data += RUP (progs->strings.count * sizeof (char), 16); - progs->ofs_statements = data - (byte *) progs; + progs->statements.offset = data - (byte *) progs; statements = (dstatement_t *) data; - data += progs->numstatements * sizeof (dstatement_t); + data += progs->statements.count * sizeof (dstatement_t); - progs->ofs_functions = data - (byte *) progs; + progs->functions.offset = data - (byte *) progs; functions = (dfunction_t *) data; functions++; // skip over null function - data += progs->numfunctions * sizeof (dfunction_t); + data += progs->functions.count * sizeof (dfunction_t); - progs->ofs_globaldefs = data - (byte *) progs; + progs->globaldefs.offset = data - (byte *) progs; globaldefs = (ddef_t *) data; - data += progs->numglobaldefs * sizeof (ddef_t); + data += progs->globaldefs.count * sizeof (ddef_t); - progs->ofs_fielddefs = data - (byte *) progs; - fielddefs = (ddef_t *) (globaldefs + progs->numglobaldefs); - data += progs->numfielddefs * sizeof (ddef_t); + progs->fielddefs.offset = data - (byte *) progs; + fielddefs = (ddef_t *) (globaldefs + progs->globaldefs.count); + data += progs->fielddefs.count * sizeof (ddef_t); - progs->ofs_globals = data - (byte *) progs; + progs->globals.offset = data - (byte *) progs; globals = (pr_type_t*) data; locals = globals + locals_start; far_data = globals + near_data_size; @@ -1155,7 +1155,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) xdefs = (pr_xdefs_t *) &globals[xdefs_def->offset]; xdef = (xdef_t *) xdef_data; xdefs->xdefs = xdefs_start; - xdefs->num_xdefs = progs->numglobaldefs + progs->numfielddefs; + xdefs->num_xdefs = progs->globaldefs.count + progs->fielddefs.count; for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++, xdef++) { qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; @@ -1193,12 +1193,12 @@ qfo_to_progs (qfo_t *in_qfo, int *size) const char *big_function = ""; if (big_func) big_function = va (0, " (%s)", strings + qfo->funcs[big_func].name); - printf ("%6i strofs\n", progs->numstrings); - printf ("%6i statements\n", progs->numstatements); - printf ("%6i functions\n", progs->numfunctions); - printf ("%6i global defs\n", progs->numglobaldefs); - printf ("%6i field defs\n", progs->numfielddefs); - printf ("%6i globals\n", progs->numglobals); + printf ("%6i strofs\n", progs->strings.count); + printf ("%6i statements\n", progs->statements.count); + printf ("%6i functions\n", progs->functions.count); + printf ("%6i global defs\n", progs->globaldefs.count); + printf ("%6i field defs\n", progs->fielddefs.count); + printf ("%6i globals\n", progs->globals.count); printf (" %6i near globals\n", near_data_size); printf (" %6i locals size%s\n", locals_size, big_function); printf (" %6i far globals\n", diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 134890dea..ae256c8cf 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -212,20 +212,20 @@ WriteProgs (dprograms_t *progs, int size) pr_type_t *globals; #define P(t,o) ((t *)((char *)progs + progs->o)) - statements = P (dstatement_t, ofs_statements); - functions = P (dfunction_t, ofs_functions); - globaldefs = P (ddef_t, ofs_globaldefs); - fielddefs = P (ddef_t, ofs_fielddefs); - globals = P (pr_type_t, ofs_globals); + statements = P (dstatement_t, statements.offset); + functions = P (dfunction_t, functions.offset); + globaldefs = P (ddef_t, globaldefs.offset); + fielddefs = P (ddef_t, fielddefs.offset); + globals = P (pr_type_t, globals.offset); #undef P - for (i = 0; i < progs->numstatements; i++) { + for (i = 0; i < progs->statements.count; i++) { statements[i].op = LittleShort (statements[i].op); statements[i].a = LittleShort (statements[i].a); statements[i].b = LittleShort (statements[i].b); statements[i].c = LittleShort (statements[i].c); } - for (i = 0; i < (unsigned) progs->numfunctions; i++) { + for (i = 0; i < (unsigned) progs->functions.count; i++) { dfunction_t *func = functions + i; func->first_statement = LittleLong (func->first_statement); func->parm_start = LittleLong (func->parm_start); @@ -235,17 +235,17 @@ WriteProgs (dprograms_t *progs, int size) func->file = LittleLong (func->file); func->numparms = LittleLong (func->numparms); } - for (i = 0; i < progs->numglobaldefs; i++) { + for (i = 0; i < progs->globaldefs.count; i++) { globaldefs[i].type = LittleShort (globaldefs[i].type); globaldefs[i].ofs = LittleShort (globaldefs[i].ofs); globaldefs[i].name = LittleLong (globaldefs[i].name); } - for (i = 0; i < progs->numfielddefs; i++) { + for (i = 0; i < progs->fielddefs.count; i++) { fielddefs[i].type = LittleShort (fielddefs[i].type); fielddefs[i].ofs = LittleShort (fielddefs[i].ofs); fielddefs[i].name = LittleLong (fielddefs[i].name); } - for (i = 0; i < progs->numglobals; i++) + for (i = 0; i < progs->globals.count; i++) globals[i].int_var = LittleLong (globals[i].int_var); if (!(h = Qopen (options.output_file, "wb"))) diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 1d60336a4..b468cc5b3 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -293,7 +293,7 @@ load_progs (const char *name) PR_LoadStrings (&pr); PR_LoadDebug (&pr); } - for (i = 0; i < pr.progs->numfunctions; i++) { + for (i = 0; i < pr.progs->functions.count; i++) { // don't bother with builtins if (pr.pr_functions[i].first_statement > 0) Hash_AddElement (func_tab, &pr.pr_functions[i]); From 169b8cc398b8082af5464fb725f56d0cabbdd034 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Jan 2022 23:18:15 +0900 Subject: [PATCH 2306/3664] [qfcc] Rewrite qfo_to_progs offset/size calculation This gets all the sections of the progs file nicely aligned and the code easier to read with the offset and size calculations not being spread through the function. ivar-struct-return now works when compiled for Ruamoko. --- tools/qfcc/include/obj_file.h | 20 +-- tools/qfcc/source/obj_file.c | 228 +++++++++++++++++++++------------- 2 files changed, 153 insertions(+), 95 deletions(-) diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index a4861d29a..b827d58a1 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -249,14 +249,14 @@ typedef struct qfo_reloc_s { typedef struct qfo_mspace_s { qfos_type_t type; qfo_def_t *defs; - unsigned num_defs; + pr_uint_t num_defs; union { dstatement_t *code; pr_type_t *data; char *strings; }; - unsigned data_size; - unsigned id; + pr_uint_t data_size; + pr_uint_t id; } qfo_mspace_t; /** In-memory representation of a QFO object file. @@ -265,16 +265,16 @@ typedef struct qfo_s { pr_uint_t progs_version; ///< version of compatible VM void *data; ///< data buffer holding qfo file when read qfo_mspace_t *spaces; - unsigned num_spaces; + pr_uint_t num_spaces; qfo_reloc_t *relocs; - unsigned num_relocs; // includes num_loose_relocs + pr_uint_t num_relocs; // includes num_loose_relocs qfo_def_t *defs; - unsigned num_defs; + pr_uint_t num_defs; qfo_func_t *funcs; - unsigned num_funcs; + pr_uint_t num_funcs; pr_lineno_t *lines; - unsigned num_lines; - unsigned num_loose_relocs; // included in num_relocs + pr_uint_t num_lines; + pr_uint_t num_loose_relocs; // included in num_relocs } qfo_t; enum { @@ -500,7 +500,7 @@ qfo_t *qfo_new (void); */ void qfo_delete (qfo_t *qfo); -__attribute__((const)) int qfo_log2 (unsigned x); +__attribute__((const)) int qfo_log2 (pr_uint_t x); ///@} diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index fa650a822..a672a41fa 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -918,7 +918,7 @@ align_globals_size (unsigned size) } static int -qfo_def_compare (const void *i1, const void *i2, void *d) +qfo_def_offset_compare (const void *i1, const void *i2, void *d) { __auto_type defs = (const qfo_def_t *) d; unsigned ind1 = *(unsigned *) i1; @@ -928,10 +928,79 @@ qfo_def_compare (const void *i1, const void *i2, void *d) return def1->offset - def2->offset; } +static pr_uint_t +qfo_count_locals (const qfo_t *qfo, pr_uint_t *big_locals) +{ + if (options.code.progsversion == PROG_VERSION) { + // Ruamoko progs keep their locals on the stack rather than a + // "protected" area in the globals + *big_locals = 0; + return 0; + } + + pr_uint_t locals_size = 0; + for (pr_uint_t i = qfo_num_spaces; i < qfo->num_spaces; i++) { + if (options.code.local_merging) { + if (locals_size < qfo->spaces[i].data_size) { + locals_size = qfo->spaces[i].data_size; + *big_locals = i; + } + } else { + locals_size += align_globals_size (qfo->spaces[i].data_size); + } + } + return locals_size; +} + +typedef struct globals_info_s { + pr_uint_t locals_start; + pr_uint_t locals_size; + pr_uint_t big_locals; + pr_uint_t near_data_size; + pr_uint_t type_encodings_start; + pr_uint_t xdefs_start; + pr_uint_t xdefs_size; + pr_uint_t globals_size; +} globals_info_t; + + +static globals_info_t +qfo_count_globals (qfo_t *qfo, dprograms_t *progs, int word_align) +{ + globals_info_t info = {}; + info.globals_size = qfo->spaces[qfo_near_data_space].data_size; + info.globals_size = RUP (info.globals_size, word_align); + + info.locals_start = info.globals_size; + info.locals_size = qfo_count_locals (qfo, &info.big_locals); + info.globals_size += info.locals_size; + info.near_data_size = info.globals_size; + + info.globals_size = RUP (info.globals_size, word_align); + info.globals_size += qfo->spaces[qfo_far_data_space].data_size; + + info.type_encodings_start = info.globals_size; + info.globals_size += qfo->spaces[qfo_type_space].data_size; + info.globals_size = RUP (info.globals_size, type_xdef.alignment); + + info.xdefs_start = info.globals_size; + info.xdefs_size = progs->globaldefs.count + progs->fielddefs.count; + info.xdefs_size *= type_size (&type_xdef); + info.globals_size += info.xdefs_size; + + return info; +} + +static pr_uint_t +qfo_next_offset (pr_chunk_t chunk, pr_uint_t size, pr_uint_t align) +{ + size *= chunk.count; + return RUP (chunk.offset + size, align); +} + dprograms_t * qfo_to_progs (qfo_t *in_qfo, int *size) { - byte *data; char *strings; dstatement_t *statements; dfunction_t *functions; @@ -946,12 +1015,6 @@ qfo_to_progs (qfo_t *in_qfo, int *size) qfo_def_t *types_def = 0; qfo_def_t *xdefs_def = 0; unsigned i, j; - unsigned near_data_size = 0; - unsigned locals_size = 0; - int locals_start; - int type_encodings_start; - int xdefs_start; - unsigned big_locals = 0; int big_func = 0; pr_xdefs_t *xdefs = 0; xdef_t *xdef; @@ -959,6 +1022,16 @@ qfo_to_progs (qfo_t *in_qfo, int *size) unsigned *far_def_indices; unsigned *field_def_indices; + // id progs were aligned to only 4 bytes, but 8 is much more reasonable + pr_uint_t byte_align = 8; + if (options.code.progsversion == PROG_VERSION) { + byte_align = __alignof__ (pr_lvec4_t); + } else if (options.code.progsversion == PROG_V6P_VERSION) { + byte_align = 16; + } + pr_uint_t word_align = byte_align / sizeof (pr_int_t); + + qfo_t *qfo = alloca (sizeof (qfo_t) + in_qfo->num_spaces * sizeof (qfo_mspace_t)); *qfo = *in_qfo; @@ -970,53 +1043,52 @@ qfo_to_progs (qfo_t *in_qfo, int *size) *size = RUP (sizeof (dprograms_t), 16); progs = calloc (1, *size); progs->version = options.code.progsversion; + // crc is set in qfcc.c if enabled + + // these are in order in which they usually appear in the file rather + // than the order they appear in the struct, though with the offsets + // it doesn't matter too much. However, as people expect a certain + // layout, ti does matter enough to preserve the traditional file order. + progs->strings.offset = *size; + progs->strings.count = qfo->spaces[qfo_strings_space].data_size; + + progs->statements.offset = qfo_next_offset (progs->strings, + sizeof (char), + byte_align); progs->statements.count = qfo->spaces[qfo_code_space].data_size; + + progs->functions.offset = qfo_next_offset (progs->statements, + sizeof (dstatement_t), + byte_align); + progs->functions.count = qfo->num_funcs + 1; + + progs->globaldefs.offset = qfo_next_offset (progs->functions, + sizeof (dfunction_t), + byte_align); progs->globaldefs.count = qfo->spaces[qfo_near_data_space].num_defs; //ddef offsets are 16 bits so the ddef ofs will likely be invalid //thus it will be forced invalid and the true offset written to the //.xdefs array in the progs file progs->globaldefs.count += qfo->spaces[qfo_far_data_space].num_defs; + + progs->fielddefs.offset = qfo_next_offset (progs->globaldefs, + sizeof (ddef_t), + byte_align); progs->fielddefs.count = qfo->spaces[qfo_entity_space].num_defs; - progs->functions.count = qfo->num_funcs + 1; - progs->strings.count = qfo->spaces[qfo_strings_space].data_size; - progs->globals.count = qfo->spaces[qfo_near_data_space].data_size; - progs->globals.count = align_globals_size (progs->globals.count); - locals_start = progs->globals.count; - if (options.code.progsversion < PROG_VERSION) { - for (i = qfo_num_spaces; i < qfo->num_spaces; i++) { - if (options.code.local_merging) { - if (locals_size < qfo->spaces[i].data_size) { - locals_size = qfo->spaces[i].data_size; - big_locals = i; - } - } else { - locals_size += align_globals_size (qfo->spaces[i].data_size); - } - } - } - progs->globals.count += locals_size; - near_data_size = progs->globals.count; - progs->globals.count = RUP (progs->globals.count, 16 / sizeof (pr_type_t)); - progs->globals.count += qfo->spaces[qfo_far_data_space].data_size; - type_encodings_start = progs->globals.count; - progs->globals.count += qfo->spaces[qfo_type_space].data_size; - progs->globals.count = RUP (progs->globals.count, type_xdef.alignment); - xdefs_start = progs->globals.count; - progs->globals.count += progs->globaldefs.count * type_size (&type_xdef); - progs->globals.count += progs->fielddefs.count * type_size (&type_xdef); + + progs->globals.offset = qfo_next_offset (progs->fielddefs, + sizeof (ddef_t), + byte_align); + globals_info_t globals_info = qfo_count_globals (qfo, progs, word_align); + progs->globals.count = globals_info.globals_size; + progs->entityfields = qfo->spaces[qfo_entity_space].data_size; // qfo_debug_space does not go in the progs file - *size += progs->statements.count * sizeof (dstatement_t); - *size += progs->globaldefs.count * sizeof (ddef_t); - *size += progs->fielddefs.count * sizeof (ddef_t); - *size += progs->functions.count * sizeof (dfunction_t); - *size += RUP (progs->strings.count * sizeof (char), 16); - *size += progs->globals.count * sizeof (pr_type_t); + + *size = qfo_next_offset (progs->globals, sizeof (pr_type_t), 1); progs = realloc (progs, *size); - data = (byte *) progs; memset (progs + 1, 0, *size - sizeof (dprograms_t)); - data += RUP (sizeof (dprograms_t), 16); def_indices = alloca ((progs->globaldefs.count + progs->fielddefs.count) * sizeof (*def_indices)); @@ -1032,42 +1104,27 @@ qfo_to_progs (qfo_t *in_qfo, int *size) field_def_indices[i] = i; } qsort_r (def_indices, qfo->spaces[qfo_near_data_space].num_defs, - sizeof (unsigned), qfo_def_compare, + sizeof (unsigned), qfo_def_offset_compare, qfo->spaces[qfo_near_data_space].defs); qsort_r (far_def_indices, qfo->spaces[qfo_far_data_space].num_defs, - sizeof (unsigned), qfo_def_compare, + sizeof (unsigned), qfo_def_offset_compare, qfo->spaces[qfo_far_data_space].defs); qsort_r (field_def_indices, qfo->spaces[qfo_entity_space].num_defs, - sizeof (unsigned), qfo_def_compare, + sizeof (unsigned), qfo_def_offset_compare, qfo->spaces[qfo_entity_space].defs); - progs->strings.offset = data - (byte *) progs; - strings = (char *) data; - data += RUP (progs->strings.count * sizeof (char), 16); - - progs->statements.offset = data - (byte *) progs; - statements = (dstatement_t *) data; - data += progs->statements.count * sizeof (dstatement_t); - - progs->functions.offset = data - (byte *) progs; - functions = (dfunction_t *) data; +#define qfo_block(t,b) (t *) ((byte *) progs + progs->b.offset) + strings = qfo_block (char, strings); + statements = qfo_block (dstatement_t, statements); + functions = qfo_block (dfunction_t, functions); functions++; // skip over null function - data += progs->functions.count * sizeof (dfunction_t); - - progs->globaldefs.offset = data - (byte *) progs; - globaldefs = (ddef_t *) data; - data += progs->globaldefs.count * sizeof (ddef_t); - - progs->fielddefs.offset = data - (byte *) progs; - fielddefs = (ddef_t *) (globaldefs + progs->globaldefs.count); - data += progs->fielddefs.count * sizeof (ddef_t); - - progs->globals.offset = data - (byte *) progs; - globals = (pr_type_t*) data; - locals = globals + locals_start; - far_data = globals + near_data_size; - type_data = globals + type_encodings_start; - xdef_data = globals + xdefs_start; + globaldefs = qfo_block (ddef_t, globaldefs); + fielddefs = qfo_block (ddef_t, fielddefs); + globals = qfo_block (pr_type_t, globals); + locals = globals + globals_info.locals_start; + far_data = globals + globals_info.near_data_size; + type_data = globals + globals_info.type_encodings_start; + xdef_data = globals + globals_info.xdefs_start; memcpy (strings, qfo->spaces[qfo_strings_space].strings, qfo->spaces[qfo_strings_space].data_size * sizeof (char)); @@ -1084,13 +1141,13 @@ qfo_to_progs (qfo_t *in_qfo, int *size) df->first_statement = qf->code; if (options.code.progsversion < PROG_VERSION) { - df->parm_start = locals_start; + df->parm_start = globals_info.locals_start; df->locals = space->data_size; // finalize the offsets of the local defs for (j = 0; j < space->num_defs; j++) - space->defs[j].offset += locals_start; + space->defs[j].offset += globals_info.locals_start; if (!options.code.local_merging) - locals_start += align_globals_size (df->locals); + globals_info.locals_start += align_globals_size (df->locals); } df->profile = 0; df->name = qf->name; @@ -1120,7 +1177,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) } for (i = 0; i < qfo->spaces[qfo_type_space].num_defs; i++) { - qfo->spaces[qfo_type_space].defs[i].offset += type_encodings_start; + qfo->spaces[qfo_type_space].defs[i].offset += globals_info.type_encodings_start; } for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { @@ -1134,7 +1191,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) qfo->spaces[qfo_near_data_space].data_size * sizeof (pr_type_t)); qfo->spaces[qfo_near_data_space].data = globals; // clear locals data - memset (locals, 0, locals_size * sizeof (pr_type_t)); + memset (locals, 0, globals_info.locals_size * sizeof (pr_type_t)); // copy far data memcpy (far_data, qfo->spaces[qfo_far_data_space].data, qfo->spaces[qfo_far_data_space].data_size * sizeof (pr_type_t)); @@ -1148,30 +1205,30 @@ qfo_to_progs (qfo_t *in_qfo, int *size) if (types_def) { qfot_type_encodings_t *encodings; encodings = (qfot_type_encodings_t *) &globals[types_def->offset]; - encodings->types = type_encodings_start; + encodings->types = globals_info.type_encodings_start; encodings->size = qfo->spaces[qfo_type_space].data_size; } if (xdefs_def) { xdefs = (pr_xdefs_t *) &globals[xdefs_def->offset]; xdef = (xdef_t *) xdef_data; - xdefs->xdefs = xdefs_start; + xdefs->xdefs = globals_info.xdefs_start; xdefs->num_xdefs = progs->globaldefs.count + progs->fielddefs.count; for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++, xdef++) { qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; - xdef->type = def->type + type_encodings_start; + xdef->type = def->type + globals_info.type_encodings_start; xdef->ofs = def->offset; } for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++, xdef++) { qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + i; - xdef->type = def->type + type_encodings_start; + xdef->type = def->type + globals_info.type_encodings_start; xdef->ofs = def->offset; } for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++, xdef++) { qfo_def_t *def = qfo->spaces[qfo_entity_space].defs + i; - xdef->type = def->type + type_encodings_start; + xdef->type = def->type + globals_info.type_encodings_start; xdef->ofs = def->offset; } } @@ -1183,7 +1240,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) qfo_func_t *qf = qfo->funcs + i; qfo_mspace_t *space = qfo->spaces + qf->locals_space; - if (qf->locals_space == big_locals) + if (qf->locals_space == globals_info.big_locals) big_func = i; for (j = 0; j < space->num_defs; j++) space->defs[j].offset -= df->parm_start; @@ -1199,8 +1256,9 @@ qfo_to_progs (qfo_t *in_qfo, int *size) printf ("%6i global defs\n", progs->globaldefs.count); printf ("%6i field defs\n", progs->fielddefs.count); printf ("%6i globals\n", progs->globals.count); - printf (" %6i near globals\n", near_data_size); - printf (" %6i locals size%s\n", locals_size, big_function); + printf (" %6i near globals\n", globals_info.near_data_size); + printf (" %6i locals size%s\n", + globals_info.locals_size, big_function); printf (" %6i far globals\n", qfo->spaces[qfo_far_data_space].data_size); printf (" %6i type globals\n", From e9dff4ff9c21d4c543aa014291b99a70c8397c98 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 10:21:48 +0900 Subject: [PATCH 2307/3664] [gamecode] Correct types and widths for bitnot bitnot is the only unary operator in the bitops group and thus needs special handling. --- libs/gamecode/opcodes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index d8b9ed711..eda713a31 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -91,8 +91,8 @@ bitops_formats = { "mnemonic": "{op_bit[oo]}", "opname": "{op_bit[oo]}", "format": "{bit_fmt[oo]}", - "widths": "{ss+1}, {ss+1}, {ss+1}", - "types": "{bit_types[t]}, {bit_types[t]}, {bit_types[t]}", + "widths": "{ss+1}, { oo < 3 and ss+1 or 0}, {ss+1}", + "types": "{bit_types[t]}, {oo < 3 and bit_types[t] or 'ev_invalid'}, {bit_types[t]}", "args": { "op_bit": ["bitand", "bitor", "bitxor", "bitnot"], "bit_type": ["I", "L"], From 59ee72320105a41354d1b66b1a9bfb603760f382 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 10:55:06 +0900 Subject: [PATCH 2308/3664] [gamecode] Rename parm to param That misspelling bothered me from the very beginning, I'd always have trouble getting the name right when trying to access one of those fields. --- include/QF/progs.h | 6 ++-- include/QF/progs/pr_comp.h | 8 ++--- libs/gamecode/pr_builtins.c | 6 ++-- libs/gamecode/pr_debug.c | 32 +++++++++---------- libs/gamecode/pr_exec.c | 55 ++++++++++++++++---------------- libs/gamecode/pr_load.c | 8 ++--- ruamoko/qwaq/builtins/debug.c | 4 +-- tools/qfcc/source/disassemble.c | 7 ++-- tools/qfcc/source/dump_globals.c | 17 +++++----- tools/qfcc/source/obj_file.c | 16 +++++----- tools/qfcc/source/qfcc.c | 4 +-- 11 files changed, 83 insertions(+), 80 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 78e9913c9..f8ef4abfd 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1254,12 +1254,12 @@ typedef struct { */ typedef struct { pr_int_t first_statement; - pr_int_t numparms; + pr_int_t numparams; union { struct { - dparmsize_t parm_size[PR_MAX_PARAMS]; + dparmsize_t param_size[PR_MAX_PARAMS]; dfunction_t *descriptor; - pr_uint_t parm_start; + pr_uint_t params_start; pr_uint_t locals; pr_uint_t profile; }; diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 4ae88e18e..d201bff87 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -513,16 +513,16 @@ typedef struct dparmsize_s { typedef struct dfunction_s { pr_int_t first_statement; // negative numbers are builtins - pr_uint_t parm_start; // beginning of locals data space - pr_uint_t locals; // total ints of parms + locals + pr_uint_t params_start; // beginning of locals data space + pr_uint_t locals; // total ints of params + locals pr_uint_t profile; // runtime pr_string_t name; // source function name pr_string_t file; // source file defined in - pr_int_t numparms; // -ve is varargs (1s comp of real count) - dparmsize_t parm_size[PR_MAX_PARAMS]; + pr_int_t numparams; // -ve is varargs (1s comp of real count) + dparmsize_t param_size[PR_MAX_PARAMS]; } dfunction_t; typedef union pr_type_u { diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index fcccb57a4..eaec8b148 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -196,10 +196,10 @@ PR_RelocateBuiltins (progs_t *pr) func = pr->function_table + i; func->first_statement = desc->first_statement; - func->parm_start = desc->parm_start; + func->params_start = desc->params_start; func->locals = desc->locals; - func->numparms = desc->numparms; - memcpy (func->parm_size, desc->parm_size, sizeof (func->parm_size)); + func->numparams = desc->numparams; + memcpy (func->param_size, desc->param_size, sizeof (func->param_size)); func->descriptor = desc; if (desc->first_statement > 0) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 9eff304dd..b9832389a 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -914,7 +914,7 @@ PR_Get_Source_Line (progs_t *pr, pr_uint_t addr) } pr_def_t * -PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) +PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned param) { prdeb_resources_t *res = pr->pr_debug_resources; pr_uint_t i; @@ -928,12 +928,12 @@ PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) if (!func) return 0; - num_params = func->numparms; + num_params = func->numparams; if (num_params < 0) { num_params = ~num_params; // one's compliment param_offs = 1; // skip over @args def } - if (parm >= (unsigned) num_params) + if (param >= (unsigned) num_params) return 0; aux_func = res->auxfunction_map[func - pr->pr_functions]; @@ -942,7 +942,7 @@ PR_Get_Param_Def (progs_t *pr, dfunction_t *func, unsigned parm) for (i = 0; i < aux_func->num_locals; i++) { ddef = &res->local_defs[aux_func->local_defs + param_offs + i]; - if (!parm--) + if (!param--) break; } return ddef; @@ -987,7 +987,7 @@ PR_Get_Local_Def (progs_t *pr, pr_ptr_t *offset) aux_func = res->auxfunction_map[func - pr->pr_functions]; if (!aux_func) return 0; - offs -= func->parm_start; + offs -= func->params_start; if (offs >= func->locals) return 0; if ((def = PR_SearchDefs (res->local_defs + aux_func->local_defs, @@ -1531,7 +1531,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) const char *fmt; const char *mnemonic; dfunction_t *call_func = 0; - pr_def_t *parm_def = 0; + pr_def_t *param_def = 0; pr_auxfunction_t *aux_func = 0; pr_debug_data_t data; etype_t op_type[3]; @@ -1603,16 +1603,16 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) } else { const char *str; char mode = fmt[1], opchar = fmt[2]; - unsigned parm_ind = 0; + unsigned param_ind = 0; pr_uint_t opval; qfot_type_t *optype = &res->void_type; pr_func_t func; if (mode == 'P') { opchar = fmt[3]; - parm_ind = fmt[2] - '0'; + param_ind = fmt[2] - '0'; fmt++; // P has one extra item - if (parm_ind >= PR_MAX_PARAMS) + if (param_ind >= PR_MAX_PARAMS) goto err; } @@ -1631,7 +1631,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) break; case 'x': if (mode == 'P') { - opval = pr->pr_real_params[parm_ind] + opval = pr->pr_real_params[param_ind] - pr->pr_globals; break; } @@ -1657,10 +1657,10 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) } break; case 'P': - parm_def = PR_Get_Param_Def (pr, call_func, parm_ind); + param_def = PR_Get_Param_Def (pr, call_func, param_ind); optype = &res->void_type; - if (parm_def) { - optype = get_type (res, parm_def->type_encoding); + if (param_def) { + optype = get_type (res, param_def->type_encoding); } str = global_string (&data, opval, optype, contents & 1); @@ -1690,12 +1690,12 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) { edict_t *ed = 0; opval = pr->pr_globals[s->a].entity_var; - parm_ind = pr->pr_globals[s->b].uint_var; - if (parm_ind < pr->progs->entityfields + param_ind = pr->pr_globals[s->b].uint_var; + if (param_ind < pr->progs->entityfields && opval > 0 && opval < pr->pr_edict_area_size) { ed = PROG_TO_EDICT (pr, opval); - opval = &E_fld(ed, parm_ind) - pr->pr_globals; + opval = &E_fld(ed, param_ind) - pr->pr_globals; } if (!ed) { str = "bad entity.field"; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 3c0734617..43bd1ff9b 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -193,9 +193,9 @@ PR_PopFrame (progs_t *pr) } static __attribute__((pure)) long -align_offset (long offset, dparmsize_t parmsize) +align_offset (long offset, dparmsize_t paramsize) { - int mask = (1 << parmsize.alignment) - 1; + int mask = (1 << paramsize.alignment) - 1; return (offset + mask) & ~mask; } @@ -237,39 +237,39 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) return; } - if (f->numparms > 0) { - paramofs = f->parm_start; - for (i = 0; i < f->numparms; i++) { - paramofs = align_offset (paramofs, f->parm_size[i]); + if (f->numparams > 0) { + paramofs = f->params_start; + for (i = 0; i < f->numparams; i++) { + paramofs = align_offset (paramofs, f->param_size[i]); dstParams[i] = pr->pr_globals + paramofs; - paramofs += f->parm_size[i].size; + paramofs += f->param_size[i].size; if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], - f->parm_size[i].size); + f->param_size[i].size); pr->pr_params[i] = pr->pr_real_params[i]; } } - } else if (f->numparms < 0) { - paramofs = f->parm_start + 2; // argc and argv - for (i = 0; i < -f->numparms - 1; i++) { - paramofs = align_offset (paramofs, f->parm_size[i]); + } else if (f->numparams < 0) { + paramofs = f->params_start + 2; // argc and argv + for (i = 0; i < -f->numparams - 1; i++) { + paramofs = align_offset (paramofs, f->param_size[i]); dstParams[i] = pr->pr_globals + paramofs; - paramofs += f->parm_size[i].size; + paramofs += f->param_size[i].size; if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], - f->parm_size[i].size); + f->param_size[i].size); pr->pr_params[i] = pr->pr_real_params[i]; } } - dparmsize_t parmsize = { pr->pr_param_size, pr->pr_param_alignment }; - paramofs = align_offset (paramofs, parmsize ); + dparmsize_t paramsize = { pr->pr_param_size, pr->pr_param_alignment }; + paramofs = align_offset (paramofs, paramsize ); if (i < PR_MAX_PARAMS) { dstParams[i] = pr->pr_globals + paramofs; } for (; i < pr->pr_argc; i++) { if (pr->pr_params[i] != pr->pr_real_params[i]) { copy_param (pr->pr_real_params[i], pr->pr_params[i], - parmsize.size); + paramsize.size); pr->pr_params[i] = pr->pr_real_params[i]; } } @@ -280,27 +280,28 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) PR_RunError (pr, "PR_EnterFunction: locals stack overflow"); memcpy (&pr->localstack[pr->localstack_used], - &pr->pr_globals[f->parm_start], + &pr->pr_globals[f->params_start], sizeof (pr_type_t) * f->locals); pr->localstack_used += f->locals; if (pr_deadbeef_locals->int_val) { - for (pr_uint_t i = f->parm_start; i < f->parm_start + f->locals; i++) { + for (pr_uint_t i = f->params_start; + i < f->params_start + f->locals; i++) { pr->pr_globals[i].int_var = 0xdeadbeef; } } // copy parameters - if (f->numparms >= 0) { - for (i = 0; i < f->numparms; i++) { - copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size); + if (f->numparams >= 0) { + for (i = 0; i < f->numparams; i++) { + copy_param (dstParams[i], pr->pr_params[i], f->param_size[i].size); } } else { int copy_args; - pr_type_t *argc = &pr->pr_globals[f->parm_start + 0]; - pr_type_t *argv = &pr->pr_globals[f->parm_start + 1]; - for (i = 0; i < -f->numparms - 1; i++) { - copy_param (dstParams[i], pr->pr_params[i], f->parm_size[i].size); + pr_type_t *argc = &pr->pr_globals[f->params_start + 0]; + pr_type_t *argv = &pr->pr_globals[f->params_start + 1]; + for (i = 0; i < -f->numparams - 1; i++) { + copy_param (dstParams[i], pr->pr_params[i], f->param_size[i].size); } copy_args = pr->pr_argc - i; argc->int_var = copy_args; @@ -338,7 +339,7 @@ PR_LeaveFunction (progs_t *pr, int to_engine) if (pr->localstack_used < 0) PR_RunError (pr, "PR_LeaveFunction: locals stack underflow"); - memcpy (&pr->pr_globals[f->parm_start], + memcpy (&pr->pr_globals[f->params_start], &pr->localstack[pr->localstack_used], sizeof (pr_type_t) * f->locals); } diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 165ca789b..1443d1a12 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -251,12 +251,12 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) for (i = 0; i < pr->progs->functions.count; i++) { pr->pr_functions[i].first_statement = LittleLong (pr->pr_functions[i].first_statement); - pr->pr_functions[i].parm_start = - LittleLong (pr->pr_functions[i].parm_start); + pr->pr_functions[i].params_start = + LittleLong (pr->pr_functions[i].params_start); pr->pr_functions[i].name = LittleLong (pr->pr_functions[i].name); pr->pr_functions[i].file = LittleLong (pr->pr_functions[i].file); - pr->pr_functions[i].numparms = - LittleLong (pr->pr_functions[i].numparms); + pr->pr_functions[i].numparams = + LittleLong (pr->pr_functions[i].numparams); pr->pr_functions[i].locals = LittleLong (pr->pr_functions[i].locals); if (pr->pr_functions[i].name) Hash_Add (pr->function_hash, &pr->pr_functions[i]); diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 10c09c136..73eb5972f 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -522,12 +522,12 @@ return_function (progs_t *pr, dfunction_t *func) __auto_type f = (qdb_function_t *) PR_Zone_Malloc (pr, sizeof (qdb_function_t)); f->staddr = func->first_statement; - f->local_data = func->parm_start; + f->local_data = func->params_start; f->local_size = func->locals; f->profile = func->profile; f->name = func->name; f->file = func->file; - f->num_params = func->numparms; + f->num_params = func->numparams; R_POINTER (pr) = PR_SetPointer (pr, f); } } diff --git a/tools/qfcc/source/disassemble.c b/tools/qfcc/source/disassemble.c index 953ab8143..5b8ec9735 100644 --- a/tools/qfcc/source/disassemble.c +++ b/tools/qfcc/source/disassemble.c @@ -70,10 +70,11 @@ disassemble_progs (progs_t *pr) bfunction_t func; func.first_statement = desc->first_statement; - func.parm_start = desc->parm_start; + func.params_start = desc->params_start; func.locals = desc->locals; - func.numparms = desc->numparms; - memcpy (func.parm_size, desc->parm_size, sizeof (func.parm_size)); + func.numparams = desc->numparams; + memcpy (func.param_size, desc->param_size, + sizeof (func.param_size)); func.descriptor = desc; Sys_Printf ("%s:\n", PR_GetString (pr, desc->name)); diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 256c5e9d6..3f1b412cd 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -259,15 +259,15 @@ dump_functions (progs_t *pr) else comment = va (0, " = #%d", -start); - printf ("%-5d %s%s: %d (", i, name, comment, func->numparms); - if (func->numparms < 0) - count = -func->numparms - 1; + printf ("%-5d %s%s: %d (", i, name, comment, func->numparams); + if (func->numparams < 0) + count = -func->numparams - 1; else - count = func->numparms; + count = func->numparams; for (j = 0; j < count; j++) - printf (" %d:%d", func->parm_size[j].alignment, - func->parm_size[j].size); - printf (") %d @ %x", func->locals, func->parm_start); + printf (" %d:%d", func->param_size[j].alignment, + func->param_size[j].size); + printf (") %d @ %x", func->locals, func->params_start); puts (""); if (type_encodings) { pr_auxfunction_t *aux = PR_Debug_MappedAuxFunction (pr, i); @@ -476,7 +476,8 @@ qfo_functions (qfo_t *qfo) printf (" @ %x", func->code); else printf (" = #%d", -func->code); - printf (" loc: %d\n", func->locals_space); + printf (" loc: %d params: %d\n", + func->locals_space, func->params_start); if (func->locals_space) { locals = &qfo->spaces[func->locals_space]; printf ("%*s%d %p %d %p %d %d\n", 16, "", locals->type, diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index a672a41fa..8f3dac1d6 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -791,13 +791,13 @@ get_type_alignment_log (qfo_t *qfo, pr_ptr_t type) } static __attribute__((pure)) dparmsize_t -get_parmsize (qfo_t *qfo, pr_ptr_t type) +get_paramsize (qfo_t *qfo, pr_ptr_t type) { - dparmsize_t parmsize = { + dparmsize_t paramsize = { get_type_size (qfo, type), get_type_alignment_log (qfo, type), }; - return parmsize; + return paramsize; } static void @@ -816,11 +816,11 @@ function_params (qfo_t *qfo, qfo_func_t *func, dfunction_t *df) } if (type->meta != ty_basic || type->type != ev_func) return; - df->numparms = num_params = type->func.num_params; + df->numparams = num_params = type->func.num_params; if (num_params < 0) num_params = ~num_params; for (i = 0; i < num_params; i++) { - df->parm_size[i] = get_parmsize (qfo, type->func.param_types[i]); + df->param_size[i] = get_paramsize (qfo, type->func.param_types[i]); } } @@ -1140,9 +1140,9 @@ qfo_to_progs (qfo_t *in_qfo, int *size) qfo_mspace_t *space = qfo->spaces + qf->locals_space; df->first_statement = qf->code; + df->locals = space->data_size; if (options.code.progsversion < PROG_VERSION) { - df->parm_start = globals_info.locals_start; - df->locals = space->data_size; + df->params_start = globals_info.locals_start; // finalize the offsets of the local defs for (j = 0; j < space->num_defs; j++) space->defs[j].offset += globals_info.locals_start; @@ -1243,7 +1243,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) if (qf->locals_space == globals_info.big_locals) big_func = i; for (j = 0; j < space->num_defs; j++) - space->defs[j].offset -= df->parm_start; + space->defs[j].offset -= df->params_start; } if (options.verbosity >= 0) { diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index ae256c8cf..5cc8c7aa4 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -228,12 +228,12 @@ WriteProgs (dprograms_t *progs, int size) for (i = 0; i < (unsigned) progs->functions.count; i++) { dfunction_t *func = functions + i; func->first_statement = LittleLong (func->first_statement); - func->parm_start = LittleLong (func->parm_start); + func->params_start = LittleLong (func->params_start); func->locals = LittleLong (func->locals); func->profile = LittleLong (func->profile); func->name = LittleLong (func->name); func->file = LittleLong (func->file); - func->numparms = LittleLong (func->numparms); + func->numparams = LittleLong (func->numparams); } for (i = 0; i < progs->globaldefs.count; i++) { globaldefs[i].type = LittleShort (globaldefs[i].type); From a0d9cf8d8e67097b1fd2967b68df3a1a35fa2e21 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 10:56:57 +0900 Subject: [PATCH 2309/3664] [gamecode] Improve verbose statement prints for Ruamoko They now include base register index and effective address of the operands (though it may be wrong for instructions that don't use a base register for that operand). --- libs/gamecode/pr_debug.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index b9832389a..f53f13ba6 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -54,6 +54,7 @@ #include "QF/quakefs.h" #include "QF/script.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/zone.h" #include "QF/progs/pr_debug.h" @@ -91,6 +92,7 @@ typedef struct prdeb_resources_s { dstring_t *dva; dstring_t *line; dstring_t *dstr; + va_ctx_t *va; const char *debugfile; pr_debug_header_t *debug; pr_auxfunction_t *auxfunctions; @@ -1522,6 +1524,18 @@ PR_Debug_Print (progs_t *pr, const char *expr) } } +static const char * +print_raw_op (progs_t *pr, pr_ushort_t op, pr_ushort_t base_ind, + etype_t op_type, int op_width) +{ + prdeb_resources_t *res = pr->pr_debug_resources; + const char *width = va (res->va, "%d", op_width); + return va (res->va, "%d:%04x<%08x>%s:%-8s", + base_ind, op, op + pr->pr_bases[base_ind], + op_width > 0 ? width : op_width < 0 ? "X" : "?", + pr_type_name[op_type]); +} + VISIBLE void PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) { @@ -1585,12 +1599,23 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) dasprintf (res->line, "%04x ", addr); if (pr_debug->int_val > 2) { - dasprintf (res->line, - "%03x %04x(%8s)[%d] %04x(%8s)[%d] %04x(%8s)[%d]\t", - s->op, - s->a, pr_type_name[op_type[0]], op_width[0], - s->b, pr_type_name[op_type[1]], op_width[1], - s->c, pr_type_name[op_type[2]], op_width[2]); + if (pr->progs->version < PROG_VERSION) { + dasprintf (res->line, + "%03x %04x(%8s) %04x(%8s) %04x(%8s)\t", + s->op, + s->a, pr_type_name[op_type[0]], + s->b, pr_type_name[op_type[1]], + s->c, pr_type_name[op_type[2]]); + } else { + dasprintf (res->line, "%04x %s %s %s\t", + s->op, + print_raw_op (pr, s->a, PR_BASE_IND (s->op, A), + op_type[0], op_width[0]), + print_raw_op (pr, s->b, PR_BASE_IND (s->op, B), + op_type[0], op_width[0]), + print_raw_op (pr, s->c, PR_BASE_IND (s->op, C), + op_type[0], op_width[0])); + } } dasprintf (res->line, "%s ", mnemonic); @@ -1895,6 +1920,7 @@ PR_Debug_Init (progs_t *pr) res->dva = dstring_newstr (); res->line = dstring_newstr (); res->dstr = dstring_newstr (); + res->va = va_create_context (8); res->void_type.meta = ty_basic; res->void_type.size = 4; From 42db8514ae1e6513a165be129c7ea9230adebb2f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 11:24:00 +0900 Subject: [PATCH 2310/3664] [gamecode] Use version instead of locals count It turned out I need locals count and params_start for debugging, so use the progs version instead to bail early from PR_EnterFunction and PR_LeaveFunction (which I had forgotten anyway, oops). --- libs/gamecode/pr_exec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 43bd1ff9b..9801d9936 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -233,7 +233,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) pr->pr_xfunction = f; pr->pr_xstatement = f->first_statement - 1; // offset the st++ - if (!f->locals) { + if (pr->progs->version == PROG_VERSION) { return; } @@ -334,6 +334,10 @@ PR_LeaveFunction (progs_t *pr, int to_engine) } } + if (pr->progs->version == PROG_VERSION) { + return; + } + // restore locals from the stack pr->localstack_used -= f->locals; if (pr->localstack_used < 0) From 0123e123042da39b4097db624128319cd8f353fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 11:25:50 +0900 Subject: [PATCH 2311/3664] [qfcc] Use locals and params_start to describe stack frame This is necessary to get statement disassembly working, and likely debugging in general. locals is the total size of the stack frame and thus reaches above the function-entry stack pointer, and params_start is the local space relative start of the parameters. Thus, knowing the function-entry stack pointer, the bottom of the locals space can be found by subtracting params_start, and the top of the locals space by adding (locals - params_start). --- tools/qfcc/include/function.h | 2 +- tools/qfcc/include/obj_file.h | 4 +++- tools/qfcc/source/function.c | 12 +++++++++--- tools/qfcc/source/obj_file.c | 5 +++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index cceef9341..3a089a4c2 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -65,7 +65,7 @@ typedef struct function_s { int code; ///< first statement int function_num; int line_info; - int local_defs; + int params_start;///< relative to locals space. 0 for v6p pr_string_t s_file; ///< source file with definition pr_string_t s_name; ///< name of function in output const struct type_s *type; ///< function's type without aliases diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index b827d58a1..e93c3013a 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -211,7 +211,9 @@ typedef struct qfo_func_s { pr_uint_t relocs; ///< Index to first ::qfo_reloc_t reloc record. pr_uint_t num_relocs; ///< Number of reloc records. //@} - pr_int_t reserved[2]; + pr_uint_t params_start; ///< locals_space relative start of parameters + ///< always 0 for v6/v6p progs + pr_int_t reserved; } qfo_func_t; /** Evil source of many headaches. The whole reason I've started writing this diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index d094fc152..97481dee8 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -773,6 +773,8 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) // first defspace_t *space = defspace_new (ds_virtual); + func->params_start = 0; + merge_spaces (space, func->parameters->space, 1); func->parameters->space = space; @@ -790,15 +792,19 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) merge_spaces (space, func->locals->space, 4); func->locals->space = space; - // allocate 0 words to force alignment - defspace_alloc_aligned_highwater (space, 0, 4); + // allocate 0 words to force alignment and get the address + func->params_start = defspace_alloc_aligned_highwater (space, 0, 4); dstatement_t *st = &pr.code->code[func->code]; if (st->op == OP_ADJSTK) { - st->b = -space->size; + st->b = -func->params_start; } merge_spaces (space, func->parameters->space, 4); func->parameters->space = space; + + // force the alignment again so the full stack slot is counted when + // the final parameter is smaller than 4 words + defspace_alloc_aligned_highwater (space, 0, 4); } return fsym->s.func; } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 8f3dac1d6..ce84d06c3 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -314,6 +314,7 @@ qfo_encode_functions (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, q->line_info = f->line_info; q->relocs = *relocs - qfo->relocs; q->num_relocs = qfo_encode_relocs (f->refs, relocs, q - qfo->funcs); + q->params_start = f->params_start; } } @@ -530,6 +531,7 @@ qfo_write (qfo_t *qfo, const char *filename) funcs[i].line_info = LittleLong (qfo->funcs[i].line_info); funcs[i].relocs = LittleLong (qfo->funcs[i].relocs); funcs[i].num_relocs = LittleLong (qfo->funcs[i].num_relocs); + funcs[i].params_start = LittleLong (qfo->funcs[i].params_start); } for (i = 0; i < qfo->num_lines; i++) { lines[i].fa.addr = LittleLong (qfo->lines[i].fa.addr); @@ -1148,6 +1150,9 @@ qfo_to_progs (qfo_t *in_qfo, int *size) space->defs[j].offset += globals_info.locals_start; if (!options.code.local_merging) globals_info.locals_start += align_globals_size (df->locals); + } else { + // relative to start of locals for Ruamoko progs + df->params_start = qf->params_start; } df->profile = 0; df->name = qf->name; From 4b4cb60c65596c32707fc8303bf072c1e44d2226 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 11:42:23 +0900 Subject: [PATCH 2312/3664] [qfcc] Check qfo target matches compile target Linking mixed target VMs is unlikely to end well. --- tools/qfcc/source/obj_file.c | 7 +++++++ tools/qfcc/test/Makemodule.am | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index ce84d06c3..3d5f064c3 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -573,6 +573,13 @@ qfo_read (QFile *file) free (data); return 0; } + // qfprogs leaves progsversion as 0 + if (options.code.progsversion + && header->progs_version != options.code.progsversion) { + fprintf (stderr, "qfo file target VM does not match current target\n"); + free (data); + return 0; + } qfo = calloc (1, sizeof (qfo_t)); qfo->num_spaces = LittleLong (header->num_spaces); diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 88b9e8480..f555e89f1 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -169,7 +169,7 @@ tools_qfcc_test_chewed_return_dat_SOURCES=tools/qfcc/test/chewed-return.r chewed_return_obj=$(tools_qfcc_test_chewed_return_dat_SOURCES:.r=.o) chewed_return_dep=$(call qcautodep,$(tools_qfcc_test_chewed_return_dat_SOURCES)) tools/qfcc/test/chewed-return.dat$(EXEEXT): $(chewed_return_obj) $(QFCC_DEP) - $(V_QFCCLD)$(QLINK) -o $@ $(chewed_return_obj) + $(V_QFCCLD)$(QLINK) -Ctarget=v6 -o $@ $(chewed_return_obj) tools/qfcc/test/chewed-return.run: $(qfcc_test_run_deps) @TEST_HARNESS_OPTS=--float $(top_srcdir)/tools/qfcc/test/build-run $@ include $(chewed_return_dep) # am--include-marker From de974fdd3f9cfb527753c18528b7289e0d73092d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 13:29:38 +0900 Subject: [PATCH 2313/3664] [gamecode] Add format for addressing modes and use in return This fixes Ruamoko's return format string. It looks like it's producing the correct address (but doesn't show all the information it should), but the rest of the debug code needs work locals. --- libs/gamecode/opcodes.py | 2 +- libs/gamecode/pr_debug.c | 38 +++++++++++++++++++++++++++++++++++ libs/gamecode/pr_v6p_opcode.c | 9 +++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index eda713a31..a7fc99a22 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -463,7 +463,7 @@ return_formats = { "mnemonic": "return", "opname": "return", "widths": "-1, -1, 0", # width specified by st->c - "format": "FIXME", + "format": "%Mc5", "types": "ev_void, ev_void, ev_void", } vecops_formats = { diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index f53f13ba6..ea854efcf 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1629,6 +1629,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) const char *str; char mode = fmt[1], opchar = fmt[2]; unsigned param_ind = 0; + pr_uint_t shift = 0; pr_uint_t opval; qfot_type_t *optype = &res->void_type; pr_func_t func; @@ -1640,6 +1641,15 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) if (param_ind >= PR_MAX_PARAMS) goto err; } + if (mode == 'M' || mode == 'm') { + if (!isxdigit (fmt[3])) { + goto err; + } + shift = fmt[3]; + shift = (shift & 0xf) + + (((shift & 0x40) >> 3) | ((shift & 0x40) >> 5)); + fmt++; // M/m have one extra item + } switch (opchar) { case 'a': @@ -1732,6 +1742,34 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) s->a, s->b, str); } break; + case 'M': + case 'm': + { + pr_ptr_t ptr = 0; + pr_int_t offs = 0; + switch ((opval >> shift) & 3) { + case 0: + ptr = s->a + PR_BASE (pr, s, A); + break; + case 1: + break; + case 2: + ptr = s->a + PR_BASE (pr, s, A); + ptr = G_POINTER (pr, ptr); + offs = (short) s->b; + break; + case 3: + ptr = s->a + PR_BASE (pr, s, A); + ptr = G_POINTER (pr, ptr); + offs = s->b + PR_BASE (pr, s, B); + offs = G_INT (pr, offs); + break; + } + ptr += offs; + str = global_string (&data, ptr, optype, + mode == 'M'); + } + break; default: goto err; } diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 13f129553..cb11c9eca 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -54,10 +54,19 @@ // F function (must come before any P) // R return value // E entity + field (%Eab) +// M addressing mode, contents +// m addressing mode, no contents +// takes operand (a,b,c,o (opcode)) and right shift(hex). always masked +// by 3 +// %Mc5 -> contents, operand c, shift right 5 bits +// %mo2 -> no contents, opcode, shift right 2 bits +// %mo0 -> no contents, opcode, no shift +// always uses a and b for the address calculation (Ruamoko convention)) // // a operand a // b operand b // c operand c +// o opcode // x place holder for P (padding) // 0-7 parameter index (for P) VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { From 5c222530956eb3a0e9b4e8a63b4f259cfd0460ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 14:16:05 +0900 Subject: [PATCH 2314/3664] [gamecode] Use the stack frame to find local defs Of course, only in Ruamoko progs, but it works quite nicely. global_string is now passed the absolute address of the referenced operand. With a little groveling through the progs stack, it should be possible to resolve pointers to locals in functions further up the stack. --- libs/gamecode/pr_debug.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index ea854efcf..b9c3862c5 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -989,7 +989,19 @@ PR_Get_Local_Def (progs_t *pr, pr_ptr_t *offset) aux_func = res->auxfunction_map[func - pr->pr_functions]; if (!aux_func) return 0; - offs -= func->params_start; + + pr_ptr_t locals_start; + if (pr->progs->version == PROG_VERSION) { + if (pr->pr_depth) { + prstack_t *frame = pr->pr_stack + pr->pr_depth - 1; + locals_start = frame->stack_ptr - func->params_start; + } else { + locals_start = 0; //FIXME ? when disassembling in qfprogs + } + } else { + locals_start = func->params_start; + } + offs -= locals_start; if (offs >= func->locals) return 0; if ((def = PR_SearchDefs (res->local_defs + aux_func->local_defs, @@ -1115,12 +1127,12 @@ pr_debug_find_def (progs_t *pr, pr_ptr_t *ofs) prdeb_resources_t *res = pr->pr_debug_resources; pr_def_t *def = 0; - if (*ofs >= pr->progs->globals.count) { - return 0; - } if (pr_debug->int_val && res->debug) { def = PR_Get_Local_Def (pr, ofs); } + if (*ofs >= pr->progs->globals.count) { + return 0; + } if (!def) { def = PR_GlobalAtOfs (pr, *ofs); if (def) { @@ -1630,6 +1642,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) char mode = fmt[1], opchar = fmt[2]; unsigned param_ind = 0; pr_uint_t shift = 0; + pr_uint_t opreg; pr_uint_t opval; qfot_type_t *optype = &res->void_type; pr_func_t func; @@ -1653,23 +1666,31 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) switch (opchar) { case 'a': + opreg = PR_BASE_IND (s->op, A); opval = s->a; optype = res->type_encodings[op_type[0]]; break; case 'b': + opreg = PR_BASE_IND (s->op, B); opval = s->b; optype = res->type_encodings[op_type[1]]; break; case 'c': + opreg = PR_BASE_IND (s->op, C); opval = s->c; optype = res->type_encodings[op_type[2]]; break; + case 'o': + opreg = 0; + opval = s->op; + break; case 'x': if (mode == 'P') { opval = pr->pr_real_params[param_ind] - pr->pr_globals; break; } + goto err; default: goto err; } @@ -1701,14 +1722,17 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) contents & 1); break; case 'V': + opval += pr->pr_bases[opreg]; str = global_string (&data, opval, ev_void, contents & 1); break; case 'G': + opval += pr->pr_bases[opreg]; str = global_string (&data, opval, optype, contents & 1); break; case 'g': + opval += pr->pr_bases[opreg]; str = global_string (&data, opval, optype, 0); break; case 's': From 82166406df9ad196fb598fe83d76f0f338b03f9d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 16:43:43 +0900 Subject: [PATCH 2315/3664] [qfcc] Remove the def sorting (reverts 9a08a51ebd) It turns out the sorting wasn't working properly and I've decided that anything that actually needs the defs to be sorted by address (such as a debugger searching for defs by address) can do the sorting itself. Fixes a weird swapping of def names. --- tools/qfcc/source/obj_file.c | 50 +++--------------------------------- 1 file changed, 4 insertions(+), 46 deletions(-) diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 3d5f064c3..d7144ae27 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -31,8 +31,6 @@ # include "config.h" #endif -#define _GNU_SOURCE // for qsort_r - #ifdef HAVE_STRING_H # include #endif @@ -926,17 +924,6 @@ align_globals_size (unsigned size) return RUP (size, 16 / sizeof (pr_type_t)); } -static int -qfo_def_offset_compare (const void *i1, const void *i2, void *d) -{ - __auto_type defs = (const qfo_def_t *) d; - unsigned ind1 = *(unsigned *) i1; - unsigned ind2 = *(unsigned *) i2; - const qfo_def_t *def1 = defs + ind1; - const qfo_def_t *def2 = defs + ind2; - return def1->offset - def2->offset; -} - static pr_uint_t qfo_count_locals (const qfo_t *qfo, pr_uint_t *big_locals) { @@ -1027,9 +1014,6 @@ qfo_to_progs (qfo_t *in_qfo, int *size) int big_func = 0; pr_xdefs_t *xdefs = 0; xdef_t *xdef; - unsigned *def_indices; - unsigned *far_def_indices; - unsigned *field_def_indices; // id progs were aligned to only 4 bytes, but 8 is much more reasonable pr_uint_t byte_align = 8; @@ -1099,29 +1083,6 @@ qfo_to_progs (qfo_t *in_qfo, int *size) progs = realloc (progs, *size); memset (progs + 1, 0, *size - sizeof (dprograms_t)); - def_indices = alloca ((progs->globaldefs.count + progs->fielddefs.count) - * sizeof (*def_indices)); - far_def_indices = def_indices + qfo->spaces[qfo_near_data_space].num_defs; - field_def_indices = def_indices + progs->globaldefs.count; - for (unsigned i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { - def_indices[i] = i; - } - for (unsigned i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { - far_def_indices[i] = i; - } - for (unsigned i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { - field_def_indices[i] = i; - } - qsort_r (def_indices, qfo->spaces[qfo_near_data_space].num_defs, - sizeof (unsigned), qfo_def_offset_compare, - qfo->spaces[qfo_near_data_space].defs); - qsort_r (far_def_indices, qfo->spaces[qfo_far_data_space].num_defs, - sizeof (unsigned), qfo_def_offset_compare, - qfo->spaces[qfo_far_data_space].defs); - qsort_r (field_def_indices, qfo->spaces[qfo_entity_space].num_defs, - sizeof (unsigned), qfo_def_offset_compare, - qfo->spaces[qfo_entity_space].defs); - #define qfo_block(t,b) (t *) ((byte *) progs + progs->b.offset) strings = qfo_block (char, strings); statements = qfo_block (dstatement_t, statements); @@ -1168,8 +1129,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) } for (i = 0; i < qfo->spaces[qfo_near_data_space].num_defs; i++) { - unsigned ind = def_indices[i]; - qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + ind; + qfo_def_t *def = qfo->spaces[qfo_near_data_space].defs + i; const char *defname = QFO_GETSTR (qfo, def->name); if (!strcmp (defname, ".type_encodings")) types_def = def; @@ -1179,8 +1139,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) } for (i = 0; i < qfo->spaces[qfo_far_data_space].num_defs; i++) { - unsigned ind = far_def_indices[i]; - qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + ind; + qfo_def_t *def = qfo->spaces[qfo_far_data_space].defs + i; def->offset += far_data - globals; qfo_def_to_ddef (qfo, def, globaldefs); // the correct offset will be written to the far data space @@ -1193,9 +1152,8 @@ qfo_to_progs (qfo_t *in_qfo, int *size) } for (i = 0; i < qfo->spaces[qfo_entity_space].num_defs; i++) { - unsigned ind = field_def_indices[i]; - qfo_def_to_ddef (qfo, qfo->spaces[qfo_entity_space].defs + ind, - fielddefs + i); + qfo_def_to_ddef (qfo, qfo->spaces[qfo_entity_space].defs + i, + fielddefs + i); } // copy near data From f57aa82c4b8fce295abd20c972e288c390bd8bf8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 23:24:43 +0900 Subject: [PATCH 2316/3664] [qfcc] Use an alias op for return_operand This is what using new_ret_expr would result in, but new_ret_expr is no longer used for referencing .return (except in pascal, but I haven't gotten around to sorting that out) due to the recent changes for Ruamoko progs. Fixes an ICE when compiling (with optimization) something like the following (dir is a vector): dir /= sqrt (dir * dir); return dir * speed; --- tools/qfcc/source/statements.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e0ef25160..88763e01d 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -452,7 +452,11 @@ return_operand (type_t *type, expr_t *expr) symbol_t *return_symbol; return_symbol = make_symbol (".return", &type_param, pr.symtab->space, sc_extern); - return def_operand (return_symbol->s.def, type, expr); + if (!return_symbol->table) { + symtab_addsymbol (pr.symtab, return_symbol); + } + def_t *return_def = return_symbol->s.def; + return def_operand (alias_def (return_def, type, 0), 0, expr); } operand_t * From 7877168e93d1736e3fb0fffcca538d82add6320b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Jan 2022 23:29:32 +0900 Subject: [PATCH 2317/3664] [qfcc] Make a field name more clear Just "type" isn't very informative, but "result_type" is at least a fair bit better. --- tools/qfcc/source/expr_binary.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 22d4b8a5a..06fdb6668 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -40,7 +40,7 @@ typedef struct { int op; - type_t *type; + type_t *result_type; type_t *a_cast; type_t *b_cast; expr_t *(*process)(int op, expr_t *e1, expr_t *e2); @@ -952,7 +952,7 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return fold_constants (e); e = new_binary_expr (op, e1, e2); - e->e.expr.type = expr_type->type; + e->e.expr.type = expr_type->result_type; if (is_compare (op) || is_logic (op)) { if (options.code.progsversion == PROG_ID_VERSION) { e->e.expr.type = &type_float; From 8d873a891f6251e84bb51e5459a060d8701c9be0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Jan 2022 09:17:10 +0900 Subject: [PATCH 2318/3664] [qfcc] Make struct ptr access consistent with class ivar access While this does make the generated code a little worse, load is behaving nicely), the two are at least consistent with each other and when I fix one, I'll fix both. I missed this change the other day when I did the address_expr cleanup. Yay near-duplicate code :P --- tools/qfcc/source/expr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 497de95c6..54ac5780c 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1517,10 +1517,10 @@ field_expr (expr_t *e1, expr_t *e2) if (!field) return e1; - e2->type = ex_value; - e2->e.value = new_short_val (field->s.offset); - e = new_address_expr (field->type, e1, e2); - return unary_expr ('.', e); + expr_t *offset = new_short_expr (field->s.offset); + e1 = offset_pointer_expr (e1, offset); + e1 = cast_expr (pointer_type (field->type), e1); + return unary_expr ('.', e1); } else if (is_class (t1->t.fldptr.type)) { class_t *class = t1->t.fldptr.type->t.class; symbol_t *sym = e2->e.symbol;//FIXME need to check From ec9fa3fee84000d8bc65e5a0689ee83b358e60b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Jan 2022 15:26:47 +0900 Subject: [PATCH 2319/3664] [qfcc] Clean up an unnecessary use of array_expr Simply dereferencing a pointer does not need to go through array_expr and thus collect a 0 offset that will only be constant-folded out again. Really just a minor optimization in qfcc, but at one stage in today's modification, it resulted in some unwanted aliasing chains. --- tools/qfcc/source/expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 54ac5780c..742a8d26d 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2549,7 +2549,7 @@ deref_pointer_expr (expr_t *pointer) return pointer; if (pointer_type->type != ev_ptr) return error (pointer, "not a pointer"); - return array_expr (pointer, new_int_expr (0)); + return unary_expr ('.', pointer); } expr_t * From d28507eacf194ace90874e514c5342063487827c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Jan 2022 15:29:40 +0900 Subject: [PATCH 2320/3664] [qfcc] Reduce some alias chaining Aliasing an alias expression to the same type as the original aliased expression is a no-op, so drop the alias entirely in order to simplify code generation. --- tools/qfcc/source/expr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 742a8d26d..c9e36c7b2 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1309,6 +1309,12 @@ new_alias_expr (type_t *type, expr_t *expr) } expr = expr->e.alias.expr; } + // this can happen when constant folding an offset pointer results in + // a noop due to the offset being 0 and thus casting back to the original + // type + if (type == get_type (expr)) { + return expr; + } expr_t *alias = new_expr (); alias->type = ex_alias; From e298f0d993a889d7f3c0e56dadcffbfe1670674e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Jan 2022 15:37:08 +0900 Subject: [PATCH 2321/3664] [qfcc] Break out pointer addressing This allows the code handling simple pointer dereferences to recurse along an alias chain that resulted from casting between different pointer types (such chains could probably be eliminated by replacing the type in the original pointer expression, but it wasn't worth it at this stage). --- tools/qfcc/source/statements.c | 96 +++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 88763e01d..91afd76d5 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1256,6 +1256,58 @@ statement_branch (sblock_t *sblock, expr_t *e) return sblock->next; } +static sblock_t * +ptr_addressing_mode (sblock_t *sblock, expr_t *ref, + operand_t **base, operand_t **offset, pr_ushort_t *mode) +{ + if (!is_ptr (get_type (ref))) { + internal_error (ref, "expected pointer in ref"); + } + if (ref->type != ex_alias || ref->e.alias.offset) { + // probably just a pointer + sblock = statement_subexpr (sblock, ref, base); + *offset = short_operand (0, ref); + *mode = 2; // mode C: ptr + constant index + } else if (is_ptr (get_type (ref->e.alias.expr))) { + // cast of one pointer type to another + return ptr_addressing_mode (sblock, ref->e.alias.expr, base, offset, + mode); + } else { + // alias with no offset + if (!is_integral (get_type (ref->e.alias.expr))) { + internal_error (ref, "expected integer expr in ref"); + } + expr_t *intptr = ref->e.alias.expr; + if (intptr->type != ex_expr + || (intptr->e.expr.op != '+' + && intptr->e.expr.op != '-')) { + // treat ref as simple pointer + sblock = statement_subexpr (sblock, ref, base); + *offset = short_operand (0, ref); + *mode = 2; // mode C: ptr + constant index + } else { + expr_t *ptr = intptr->e.expr.e1; + expr_t *offs = intptr->e.expr.e2; + int const_offs; + // move the +/- to the offset + offs = unary_expr (intptr->e.expr.op, offs); + // make the base a pointer again + ptr = new_alias_expr (ref->e.alias.type, ptr); + sblock = statement_subexpr (sblock, ptr, base); + if (is_constant (offs) + && (const_offs = expr_int (offs)) < 32768 + && const_offs >= -32768) { + *mode = 2; + *offset = short_operand (const_offs, ref); + } else { + *mode = 3; + sblock = statement_subexpr (sblock, offs, offset); + } + } + } + return sblock; +} + static sblock_t * addressing_mode (sblock_t *sblock, expr_t *ref, operand_t **base, operand_t **offset, pr_ushort_t *mode) @@ -1266,48 +1318,8 @@ addressing_mode (sblock_t *sblock, expr_t *ref, if (ref->type == ex_expr) { internal_error (ref, "not implemented"); } else if (ref->type == ex_uexpr) { - ref = ref->e.expr.e1; - if (!is_ptr (get_type (ref))) { - internal_error (ref, "expected pointer in ref"); - } - if (ref->type != ex_alias || ref->e.alias.offset) { - // probably just a pointer - sblock = statement_subexpr (sblock, ref, base); - *offset = short_operand (0, ref); - *mode = 2; // mode C: ptr + constant index - } else { - // alias with no offset - if (!is_integral (get_type (ref->e.alias.expr))) { - internal_error (ref, "expected integer expr in ref"); - } - expr_t *intptr = ref->e.alias.expr; - if (intptr->type != ex_expr - || (intptr->e.expr.op != '+' - && intptr->e.expr.op != '-')) { - // treat ref as simple pointer - sblock = statement_subexpr (sblock, ref, base); - *offset = short_operand (0, ref); - *mode = 2; // mode C: ptr + constant index - } else { - expr_t *ptr = intptr->e.expr.e1; - expr_t *offs = intptr->e.expr.e2; - int const_offs; - // move the +/- to the offset - offs = unary_expr (intptr->e.expr.op, offs); - // make the base a pointer again - ptr = new_alias_expr (ref->e.alias.type, ptr); - sblock = statement_subexpr (sblock, ptr, base); - if (is_constant (offs) - && (const_offs = expr_int (offs)) < 32768 - && const_offs >= -32768) { - *mode = 2; - *offset = short_operand (const_offs, ref); - } else { - *mode = 3; - sblock = statement_subexpr (sblock, offs, offset); - } - } - } + sblock = ptr_addressing_mode (sblock, ref->e.expr.e1, base, offset, + mode); } else { internal_error (ref, "unexpected expression type for indirect: %s", expr_names[ref->type]); From d3764c108a006068b9dcd2e924a9f9142f621095 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Jan 2022 15:42:06 +0900 Subject: [PATCH 2322/3664] [qfcc] Rewrite expr_deref to use addressing_mode This cleans up the generation of load instructions such that they use ptr+offset addressing instead of lea;load ptr. --- tools/qfcc/source/statements.c | 73 ++++++++++++++-------------------- 1 file changed, 30 insertions(+), 43 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 91afd76d5..4685dede6 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1432,52 +1432,39 @@ load_statement (operand_t *ptr, operand_t *offs, operand_t *op, expr_t *e) static sblock_t * expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) { - type_t *type = deref->e.expr.type; - expr_t *e; + type_t *load_type = deref->e.expr.type; + expr_t *ptr_expr = deref->e.expr.e1; + operand_t *base = 0; + operand_t *offset = 0; + pr_ushort_t mode; - e = deref->e.expr.e1; - if (e->type == ex_address && !e->e.address.offset - && e->e.address.lvalue->type == ex_symbol) { - if (e->e.expr.e1->e.symbol->sy_type != sy_var) - internal_error (e, "address of non-var"); - *op = def_operand (e->e.expr.e1->e.symbol->s.def, type, e); - } else if (e->type == ex_address && e->e.address.offset) { - statement_t *s; - operand_t *ptr = 0; - operand_t *offs = 0; - sblock = statement_subexpr (sblock, e->e.address.lvalue, &ptr); - sblock = statement_subexpr (sblock, e->e.address.offset, &offs); - if (!*op) - *op = temp_operand (type, e); - if (low_level_type (type) == ev_void) { - s = lea_statement (ptr, offs, e); - sblock_add_statement (sblock, s); + sblock = addressing_mode (sblock, deref, &base, &offset, &mode); - s = movep_statement (*op, s->opc, type, deref); - sblock_add_statement (sblock, s); - } else { - s = load_statement (ptr, offs, *op, deref); - sblock_add_statement (sblock, s); - } - } else if (e->type == ex_value && e->e.value->lltype == ev_ptr) { - ex_pointer_t *ptr = &e->e.value->v.pointer; - *op = def_operand (alias_def (ptr->def, ptr->type, ptr->val), - ptr->type, e); - } else { - statement_t *s; - operand_t *ptr = 0; - - sblock = statement_subexpr (sblock, e, &ptr); - if (!*op) - *op = temp_operand (type, e); - if (low_level_type (type) == ev_void) { - s = movep_statement (*op, ptr, type, deref); - sblock_add_statement (sblock, s); - } else { - s = load_statement (ptr, short_operand (0, e), *op, deref); - sblock_add_statement (sblock, s); - } + switch (mode) { + case 1://entity.field + case 2://const indexed pointer + case 3://var indexed pointer + break; + default: + internal_error (deref, "unexpected addressing mode: %d", mode); } + + if (!*op) { + *op = temp_operand (load_type, deref); + } + + statement_t *s; + if (low_level_type (load_type) == ev_void) { + s = lea_statement (base, offset, ptr_expr); + sblock_add_statement (sblock, s); + + s = movep_statement (*op, s->opc, load_type, deref); + sblock_add_statement (sblock, s); + } else { + s = load_statement (base, offset, *op, deref); + sblock_add_statement (sblock, s); + } + return sblock; } From 284fcd312d78baaa4b26f22865e19ce354848de6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Jan 2022 15:46:29 +0900 Subject: [PATCH 2323/3664] [qfcc] Rewrite assignment destination addressing It now addressing_mode cleaning up store instructions to use ptr+offset instead of lea;store ptr... Entity.field addressing has been impelmented as well. Move instructions still generate sub-optimal code in that they use an add instruction instead of lea. --- tools/qfcc/source/statements.c | 53 ++++++++++++++-------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 4685dede6..064e25cb5 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -792,17 +792,6 @@ operand_address (operand_t *reference, expr_t *e) op_type_names[reference->op_type]); } -static __attribute__((pure)) int -is_const_ptr (expr_t *e) -{ - if ((e->type != ex_value || e->e.value->lltype != ev_ptr) - || !(POINTER_VAL (e->e.value->v.pointer) >= 0 - && POINTER_VAL (e->e.value->v.pointer) < 65536)) { - return 0; - } - return 1; -} - static __attribute__((pure)) int is_indirect (expr_t *e) { @@ -813,6 +802,10 @@ is_indirect (expr_t *e) return 0; } +static sblock_t *addressing_mode (sblock_t *sblock, expr_t *ref, + operand_t **base, operand_t **offset, + pr_ushort_t *mode); + static sblock_t * expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) { @@ -916,6 +909,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) operand_t *src = 0; operand_t *dst = 0; operand_t *ofs = 0; + pr_ushort_t mode = 0; // assign const char *opcode = "assign"; st_type_t type; @@ -957,26 +951,10 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) if (0) { dereference_dst: - // dst_expr is a dereferenced pointer, so need to un-dereference it - // to get the pointer and switch to storep instructions. - dst_expr = expr_file_line (address_expr (dst_expr, 0), e); + // dst_expr is a dereferenced pointer, so need to get its addressing + // parameters (base and offset) and switch to storep instructions. + sblock = addressing_mode (sblock, dst_expr, &dst, &ofs, &mode); opcode = "store"; - if (dst_expr->type == ex_address && dst_expr->e.address.offset - && !is_const_ptr (dst_expr->e.address.lvalue)) { - sblock = statement_subexpr (sblock, - dst_expr->e.address.lvalue, &dst); - sblock = statement_subexpr (sblock, - dst_expr->e.address.offset, &ofs); - } else { - sblock = statement_subexpr (sblock, dst_expr, &dst); - if (options.code.progsversion < PROG_VERSION) { - // v6 and v6p stores don't need an index - ofs = 0; - } else { - // ruamoko stores do need an index - ofs = short_operand (0, e); - } - } type = st_ptrassign; } if (op) { @@ -987,6 +965,10 @@ dereference_dst: } if (is_entity (dst->type) && ofs && is_field (ofs->type)) { + // need to get a pointer type, entity.field expressions do not provide + // one directly. FIXME it was probably a mistake extracting the operand + // type from the statement expression in dags + dst_expr = expr_file_line (address_expr (dst_expr, 0), dst_expr); s = new_statement (st_expr, "lea", dst_expr); s->opa = dst; s->opb = ofs; @@ -1316,7 +1298,16 @@ addressing_mode (sblock_t *sblock, expr_t *ref, // ref is known to be either ex_expr or ex_uexpr, with '.' for // the operator if (ref->type == ex_expr) { - internal_error (ref, "not implemented"); + expr_t *ent_expr = ref->e.expr.e1; + expr_t *fld_expr = ref->e.expr.e2; + if (!is_entity (get_type (ent_expr)) + || !is_field (get_type (fld_expr))) { + print_expr (ref); + internal_error (ref, "expected entity.field"); + } + sblock = statement_subexpr (sblock, ent_expr, base); + sblock = statement_subexpr (sblock, fld_expr, offset); + *mode = 1;//entity.field } else if (ref->type == ex_uexpr) { sblock = ptr_addressing_mode (sblock, ref->e.expr.e1, base, offset, mode); From 54e079ab754e74dd95258e99d7116a17ed9cf471 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 15:38:39 +0900 Subject: [PATCH 2324/3664] [qfcc] Fold int constants more aggressively This code now reaches into one level of the expression tree and rearranges the nodes to allow the constant folder to do its things, but only for ints, and only when the folding is trivially correct (* and *, +/- and +/-). There may be more opportunities, but these cover what I needed for now and anything more will need code generation or smarter tree manipulation as things are getting out of hand. --- tools/qfcc/source/constfold.c | 66 +++++++++++++++++++++++++++ tools/qfcc/test/Makemodule.am | 11 +++++ tools/qfcc/test/const-fold-int.r | 76 ++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 tools/qfcc/test/const-fold-int.r diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index c09f82257..ae36079b3 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -80,6 +80,18 @@ cmp_result_expr (int result) } } +static int +is_addsub (int op) +{ + return op == '+' || op == '-'; +} + +static int +inv_addsub (int op) +{ + return op == '+' ? '-' : '+'; +} + static expr_t * do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2) { @@ -819,6 +831,60 @@ do_op_int (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op == '-' && isval2 && val2 == 0) return e1; + if (!isval1) { + if (e1->type == ex_expr) { + // at most one of the two sub-expressions is constant otherwise + // e1 would be a constant + if (is_constant (e1->e.expr.e1)) { + if ((op == '*' && e1->e.expr.op == '*') + || (is_addsub (op) && is_addsub (e1->e.expr.op))) { + expr_t *c = binary_expr (op, e1->e.expr.e1, e2); + e = binary_expr (e1->e.expr.op, c, e1->e.expr.e2); + } + } else if (is_constant (e1->e.expr.e2)) { + if ((op == '*' && e1->e.expr.op == '*') + || (is_addsub (op) && e1->e.expr.op == '+')) { + expr_t *c = binary_expr (op, e1->e.expr.e2, e2); + e = binary_expr (e1->e.expr.op, e1->e.expr.e1, c); + } else if (is_addsub (op) && e1->e.expr.op == '-') { + // must ivert op + expr_t *c = binary_expr (inv_addsub (op), + e1->e.expr.e2, e2); + e = binary_expr (e1->e.expr.op, e1->e.expr.e1, c); + } + } + } + return e; + } else if (!isval2) { + if (e2->type == ex_expr) { + // at most one of the two sub-expressions is constant otherwise + // e2 would be a constant + if (is_constant (e2->e.expr.e1)) { + if ((op == '*' && e2->e.expr.op == '*') + || (op == '+' && is_addsub (e2->e.expr.op))) { + expr_t *c = binary_expr (op, e1, e2->e.expr.e1); + e = binary_expr (e2->e.expr.op, c, e2->e.expr.e2); + } else if (op == '-' && is_addsub (e2->e.expr.op)) { + expr_t *c = binary_expr (op, e1, e2->e.expr.e1); + c = fold_constants (c); + e = binary_expr (inv_addsub (e2->e.expr.op), + c, e2->e.expr.e2); + } + } else if (is_constant (e2->e.expr.e2)) { + if ((op == '*' && e2->e.expr.op == '*') + || (op == '+' && is_addsub (e2->e.expr.op))) { + expr_t *c = binary_expr (e2->e.expr.op, + e1, e2->e.expr.e2); + e = binary_expr (op, c, e2->e.expr.e1); + } else if (op == '-' && is_addsub (e2->e.expr.op)) { + expr_t *c = binary_expr (inv_addsub (e2->e.expr.op), + e1, e2->e.expr.e2); + e = binary_expr (op, c, e2->e.expr.e1); + } + } + } + return e; + } if (!isval1 || !isval2) return e; diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index f555e89f1..acfa99873 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -16,6 +16,7 @@ test_progs_dat=\ tools/qfcc/test/chewed-return.dat \ tools/qfcc/test/comma-expr.dat \ tools/qfcc/test/compound.dat \ + tools/qfcc/test/const-fold-int.dat \ tools/qfcc/test/deadbool.dat \ tools/qfcc/test/dealloc-nowarn.dat \ tools/qfcc/test/dealloc-nowarn2.dat \ @@ -195,6 +196,16 @@ tools/qfcc/test/compound.run: $(qfcc_test_run_deps) include $(compound_dep) # am--include-marker r_depfiles_remade += $(compound_dep) +tools_qfcc_test_const_fold_int_dat_SOURCES=tools/qfcc/test/const-fold-int.r +const_fold_int_obj=$(tools_qfcc_test_const_fold_int_dat_SOURCES:.r=.o) +const_fold_int_dep=$(call qcautodep,$(tools_qfcc_test_const_fold_int_dat_SOURCES)) +tools/qfcc/test/const-fold-int.dat$(EXEEXT): $(const_fold_int_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(const_fold_int_obj) +tools/qfcc/test/const-fold-int.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(const_fold_int_dep) # am--include-marker +r_depfiles_remade += $(const_fold_int_dep) + tools_qfcc_test_deadbool_dat_SOURCES=tools/qfcc/test/deadbool.r deadbool_obj=$(tools_qfcc_test_deadbool_dat_SOURCES:.r=.o) deadbool_dep=$(call qcautodep,$(tools_qfcc_test_deadbool_dat_SOURCES)) diff --git a/tools/qfcc/test/const-fold-int.r b/tools/qfcc/test/const-fold-int.r new file mode 100644 index 000000000..d7fa31920 --- /dev/null +++ b/tools/qfcc/test/const-fold-int.r @@ -0,0 +1,76 @@ +int mul_e_c_t_c (int x) { return x * 6 * 7; } +int mul_c_e_t_c (int x) { return 6 * x * 7; } +int mul_c_c_t_e (int x) { return 6 * 7 * x; } +int mul_e_t_c_c (int x) { return x * (6 * 7); } +int mul_c_t_e_c (int x) { return 6 * (x * 7); } +int mul_c_t_c_e (int x) { return 6 * (7 * x); } + +int addadd_e_c_t_c (int x) { return x + 6 + 7; } +int addadd_c_e_t_c (int x) { return 6 + x + 7; } +int addadd_c_c_t_e (int x) { return 6 + 7 + x; } +int addadd_e_t_c_c (int x) { return x + (6 + 7); } +int addadd_c_t_e_c (int x) { return 6 + (x + 7); } +int addadd_c_t_c_e (int x) { return 6 + (7 + x); } + +int addsub_e_c_t_c (int x) { return x + 6 - 7; } +int addsub_c_e_t_c (int x) { return 6 + x - 7; } +int addsub_c_c_t_e (int x) { return 6 + 7 - x; } +int addsub_e_t_c_c (int x) { return x + (6 - 7); } +int addsub_c_t_e_c (int x) { return 6 + (x - 7); } +int addsub_c_t_c_e (int x) { return 6 + (7 - x); } + +int subadd_e_c_t_c (int x) { return x - 6 + 7; } +int subadd_c_e_t_c (int x) { return 6 - x + 7; } +int subadd_c_c_t_e (int x) { return 6 - 7 + x; } +int subadd_e_t_c_c (int x) { return x - (6 + 7); } +int subadd_c_t_e_c (int x) { return 6 - (x + 7); } +int subadd_c_t_c_e (int x) { return 6 - (7 + x); } + +int subsub_e_c_t_c (int x) { return x - 6 - 7; } +int subsub_c_e_t_c (int x) { return 6 - x - 7; } +int subsub_c_c_t_e (int x) { return 6 - 7 - x; } +int subsub_e_t_c_c (int x) { return x - (6 - 7); } +int subsub_c_t_e_c (int x) { return 6 - (x - 7); } +int subsub_c_t_c_e (int x) { return 6 - (7 - x); } + +int +main () +{ + int fail = 0; + + fail |= mul_e_c_t_c (10) != 420; + fail |= mul_c_e_t_c (10) != 420; + fail |= mul_c_c_t_e (10) != 420; + fail |= mul_e_t_c_c (10) != 420; + fail |= mul_c_t_e_c (10) != 420; + fail |= mul_c_t_c_e (10) != 420; + + fail |= addadd_e_c_t_c (29) != 42; + fail |= addadd_c_e_t_c (29) != 42; + fail |= addadd_c_c_t_e (29) != 42; + fail |= addadd_e_t_c_c (29) != 42; + fail |= addadd_c_t_e_c (29) != 42; + fail |= addadd_c_t_c_e (29) != 42; + + fail |= addsub_e_c_t_c (43) != 42; + fail |= addsub_c_e_t_c (43) != 42; + fail |= addsub_c_c_t_e (-29) != 42; + fail |= addsub_e_t_c_c (43) != 42; + fail |= addsub_c_t_e_c (43) != 42; + fail |= addsub_c_t_c_e (-29) != 42; + + fail |= subadd_e_c_t_c (41) != 42; + fail |= subadd_c_e_t_c (-29) != 42; + fail |= subadd_c_c_t_e (43) != 42; + fail |= subadd_e_t_c_c (55) != 42; + fail |= subadd_c_t_e_c (-43) != 42; + fail |= subadd_c_t_c_e (-43) != 42; + + fail |= subsub_e_c_t_c (55) != 42; + fail |= subsub_c_e_t_c (-43) != 42; + fail |= subsub_c_c_t_e (-43) != 42; + fail |= subsub_e_t_c_c (41) != 42; + fail |= subsub_c_t_e_c (-29) != 42; + fail |= subsub_c_t_c_e (43) != 42; + return fail; +} From 10843fe340835f168f57383b588ce5546d552cdb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 17:05:10 +0900 Subject: [PATCH 2325/3664] [gamecode] Correct memset opname and types --- libs/gamecode/opcodes.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index a7fc99a22..703baf183 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -254,12 +254,13 @@ mathops_formats = { memset_formats = { "opcode": "OP_MEMSET_{op_memset[oo].upper()}", "mnemonic": "memset.{op_memset[oo]}", - "opname": "memset{op_memset[oo]}", + "opname": "memset{suff_memset[oo]}", "format": "{memset_fmt[oo]}", "widths": "{memset_widths[oo]}", "types": "{memset_types[oo]}", "args": { "op_memset": ["i", "p", "pi", None], + "suff_memset": ["", "p", "p", None], "memset_fmt": ["%Ga, %sb, %gc", "%Ga, %Gb, %Gc", "%Ga, %sb, %Gc", None], "memset_widths": [ "1, 0, -1", @@ -268,9 +269,9 @@ memset_formats = { None, ], "memset_types": [ - "ev_void, ev_short, ev_void", - "ev_ptr, ev_int, ev_ptr", - "ev_ptr, ev_short, ev_ptr", + "ev_int, ev_short, ev_void", + "ev_int, ev_int, ev_ptr", + "ev_int, ev_short, ev_ptr", ], }, } From d61e906cb9caa16d73fc6273a4dd670aecdbee3b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 17:05:50 +0900 Subject: [PATCH 2326/3664] [qfcc] Don't use v6p store for assinging to entity.field Ruamoko has a native addressing mode just for entities. --- tools/qfcc/source/statements.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 064e25cb5..aa70b2713 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -964,7 +964,8 @@ dereference_dst: return sblock; } - if (is_entity (dst->type) && ofs && is_field (ofs->type)) { + if (options.code.progsversion < PROG_VERSION + && is_entity (dst->type) && ofs && is_field (ofs->type)) { // need to get a pointer type, entity.field expressions do not provide // one directly. FIXME it was probably a mistake extracting the operand // type from the statement expression in dags From baca7cbb4c5790a906a186dc3f07280fbed64452 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 17:07:19 +0900 Subject: [PATCH 2327/3664] [qfcc] Do not reverse function args in ruamoko call It messed up the later check for calls to i[super dealloc]. --- tools/qfcc/source/statements.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index aa70b2713..c2387cec8 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1096,7 +1096,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) } defspace_t *arg_space = current_func->arguments; expr_t *func = call->e.branch.target; - expr_t *args = call->e.branch.args; + expr_t **args = 0; expr_t *args_va_list = 0; // .args (...) parameter expr_t *args_params = 0; // first arg in ... operand_t *use = 0; @@ -1105,9 +1105,20 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) defspace_reset (arg_space); - args = reverse_expr_list (args); + int num_args = 0; + for (expr_t *a = call->e.branch.args; a; a = a->next) { + num_args++; + } + if (num_args) { + int i = num_args; + args = alloca (num_args * sizeof (expr_t *)); + for (expr_t *a = call->e.branch.args; a; a = a->next) { + args[--i] = a; + } + } int arg_num = 0; - for (expr_t *a = args; a; a = a->next) { + for (int i = 0; i < num_args; i++) { + expr_t *a = args[i]; const char *arg_name = va (0, ".arg%d", arg_num++); def_t *def = new_def (arg_name, 0, current_func->arguments, sc_local); From 7e9cf76cfefafb00f5f69d9318554d2d556afa1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 18:18:33 +0900 Subject: [PATCH 2328/3664] [qfcc] Change ne to cmp for v6 string inequality check Since it's really strcmp in disguise (makes the instruction consistent across all targets). --- libs/gamecode/pr_v6p_opcode.c | 2 +- tools/qfcc/source/statements.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index cb11c9eca..c99ef1580 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -236,7 +236,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { ev_quaternion, ev_quaternion, ev_int, PROG_V6P_VERSION, }, - [OP_NE_S_v6p] = {"ne", "ne.s", + [OP_NE_S_v6p] = {"cmp", "ne.s", ev_string, ev_string, ev_int, PROG_ID_VERSION, }, diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index c2387cec8..f81807a82 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1548,6 +1548,9 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) opcode = convert_op (e->e.expr.op); if (!opcode) internal_error (e, "ice ice baby"); + if (strcmp (opcode, "ne") == 0 && is_string (get_type (e->e.expr.e1))) { + opcode = "cmp"; + } s = new_statement (st_expr, opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); From 501dd7db76dc9b4a2a4a43158f30f315220291b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 18:22:41 +0900 Subject: [PATCH 2329/3664] [qfcc] Use != nil for unary ! for Ruamoko progs Ruamoko has no explicit ! instruction. --- tools/qfcc/source/expr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c9e36c7b2..0b67687e1 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1951,7 +1951,9 @@ unary_expr (int op, expr_t *e) case ex_alias: case ex_address: case ex_assign: - { + if (options.code.progsversion == PROG_VERSION) { + return binary_expr (EQ, e, new_nil_expr ()); + } else { expr_t *n = new_unary_expr (op, e); if (options.code.progsversion > PROG_ID_VERSION) From f853a449b8cc2ead617472582d88ac890dc97c29 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 18:23:07 +0900 Subject: [PATCH 2330/3664] [qfcc] Cast pointers to ints for comparison Ruamoko doesn't wast instructions on otherwise compatible low-level types. --- tools/qfcc/source/expr_binary.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 06fdb6668..1e82916f8 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -686,7 +686,12 @@ pointer_compare (int op, expr_t *e1, expr_t *e2) return error (e2, "cannot use %s on pointers of different types", get_op_string (op)); } - e = new_binary_expr (op, e1, e2); + if (options.code.progsversion < PROG_VERSION) { + e = new_binary_expr (op, e1, e2); + } else { + e = new_binary_expr (op, cast_expr (&type_int, e1), + cast_expr (&type_int, e2)); + } e->e.expr.type = &type_int; return e; } From fbaf1456feb53e57cd3fc8bc433c7019050b5e9b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 18:24:16 +0900 Subject: [PATCH 2331/3664] [qfcc] Use auxiliary operands for move instructions Since Ruamoko progs must use lea to get the address of a local variable, add use/def/kill references to the move instruction in order to inform flow analysis of the variable since it is otherwise lost via the resulting pointer (not an issue when direct var reference move can be used). The test and digging for the def can probably do with being more aggressive, but this did nicely as a proof of concept. --- tools/qfcc/include/expr.h | 8 ++++++++ tools/qfcc/source/expr.c | 14 ++++++++++++++ tools/qfcc/source/statements.c | 17 +++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 641b04246..f2b934324 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -629,6 +629,14 @@ int expr_integral (expr_t *e) __attribute__((pure)); */ int is_constant (expr_t *e) __attribute__((pure)); +/** Check if the expression refers to a variable. + + \param e The expression to check. + \return True if the expression refers to a variable (def + expression, var symbol expression, or temp expression). +*/ +int is_variable (expr_t *e) __attribute__((pure)); + /** Check if the expression refers to a selector \param e The expression to check. diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 0b67687e1..66140bc52 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -956,6 +956,20 @@ is_constant (expr_t *e) return 0; } +int +is_variable (expr_t *e) +{ + while (e->type == ex_alias) { + e = e->e.alias.expr; + } + if (e->type == ex_def + || (e->type == ex_symbol && e->e.symbol->sy_type == sy_var) + || e->type == ex_temp) { + return 1; + } + return 0; +} + int is_selector (expr_t *e) { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index f81807a82..2ade73a9f 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -827,6 +827,9 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) const char *opcode; int need_ptr = 0; st_type_t type = st_move; + operand_t *use = 0; + operand_t *def = 0; + operand_t *kill = 0; if ((src && src->op_type == op_nil) || src_expr->type == ex_nil) { // switch to memset because nil is type agnostic 0 and structures @@ -859,6 +862,11 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) *op = src; } if (is_indirect (dst_expr)) { + if (is_variable (src_expr)) { + // FIXME this probably needs to be more agressive + // shouldn't emit code... + sblock = statement_subexpr (sblock, src_expr, &use); + } src = operand_address (src, src_expr); need_ptr = 1; } @@ -867,6 +875,12 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) // dst_expr and/or src_expr are dereferenced pointers, so need to // un-dereference dst_expr to get the pointer and switch to movep // or memsetp instructions. + if (is_variable (dst_expr)) { + // FIXME this probably needs to be more agressive + // shouldn't emit code... + sblock = statement_subexpr (sblock, dst_expr, &def); + sblock = statement_subexpr (sblock, dst_expr, &kill); + } dst_expr = expr_file_line (address_expr (dst_expr, 0), e); need_ptr = 1; } @@ -895,6 +909,9 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) s->opa = src; s->opb = size; s->opc = dst; + s->use = use; + s->def = def; + s->kill = kill; sblock_add_statement (sblock, s); return sblock; } From 49395b3ba1b05a049883cc40c8fae9902bb3c10a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 18:48:05 +0900 Subject: [PATCH 2332/3664] [gamecode] Correct state's types for double time It takes int for the frame rather than float. --- libs/gamecode/opcodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 703baf183..d2da04ed7 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -394,7 +394,7 @@ stated_formats = { "opname": "state", "format": "{state_fmt[c]}", "widths": "1, 1, {c}", - "types": "ev_float, ev_func, {state_types[c]}", + "types": "ev_int, ev_func, {state_types[c]}", "args": { "state": ["dt", "dtt"], "state_fmt": ["%Ga, %Gb", "%Ga, %Gb, %Gc"], From 61727941fda04f802aa3cc4562d737d2934498cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 18:57:48 +0900 Subject: [PATCH 2333/3664] [qfcc] Prepend state epxression instead of just linking This fixes an expression loop ICE when building for Ruamoko (not that there actually was a loop, but the test is rather simplistic). --- tools/qfcc/source/function.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 97481dee8..aa4f79134 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -724,8 +724,7 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) return 0; build_function (fsym); if (state_expr) { - state_expr->next = statements; - statements = state_expr; + prepend_expr (statements, state_expr); } function_t *func = fsym->s.func; if (options.code.progsversion == PROG_VERSION) { From 5ba6bf02e8e0666e5d2b444bd3a658f636109ece Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 29 Jan 2022 18:59:38 +0900 Subject: [PATCH 2334/3664] [qfcc] Cast functions to ints for comparison Yet more (non-)wasted instructions. --- tools/qfcc/source/expr_binary.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 1e82916f8..c2acf4028 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -48,6 +48,7 @@ typedef struct { static expr_t *pointer_arithmetic (int op, expr_t *e1, expr_t *e2); static expr_t *pointer_compare (int op, expr_t *e1, expr_t *e2); +static expr_t *func_compare (int op, expr_t *e1, expr_t *e2); static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2); static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); @@ -172,8 +173,8 @@ static expr_type_t field_field[] = { }; static expr_type_t func_func[] = { - {EQ, &type_int}, - {NE, &type_int}, + {EQ, 0, 0, 0, func_compare}, + {NE, 0, 0, 0, func_compare}, {0, 0} }; @@ -696,6 +697,21 @@ pointer_compare (int op, expr_t *e1, expr_t *e2) return e; } +static expr_t * +func_compare (int op, expr_t *e1, expr_t *e2) +{ + expr_t *e; + + if (options.code.progsversion < PROG_VERSION) { + e = new_binary_expr (op, e1, e2); + } else { + e = new_binary_expr (op, new_alias_expr (&type_int, e1), + new_alias_expr (&type_int, e2)); + } + e->e.expr.type = &type_int; + return e; +} + static expr_t * inverse_multiply (int op, expr_t *e1, expr_t *e2) { From 728c42e921aeb34620b06fea23db97609cbafee0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 10:47:37 +0900 Subject: [PATCH 2335/3664] [gamecode] Use pr_type_names for debug views I abandoned the reason for doing it (adding a pile of vector types), but I liked the cleanup. All the implementations are hand-written still, but at least the boilerplate stuff is automated. --- include/QF/progs.h | 19 +---- include/QF/progs/pr_comp.h | 14 +++- include/QF/progs/pr_type_names.h | 2 +- libs/gamecode/pr_debug.c | 118 +++++-------------------------- 4 files changed, 34 insertions(+), 119 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index f8ef4abfd..769fdb533 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1794,28 +1794,13 @@ typedef void (*type_view_func) (struct qfot_type_s *type, pr_type_t *value, the entire contents of the data. */ typedef struct type_view_s { - type_view_func void_view; - type_view_func string_view; - type_view_func float_view; - type_view_func vector_view; - type_view_func entity_view; - type_view_func field_view; - type_view_func func_view; - type_view_func pointer_view; - type_view_func quat_view; - type_view_func int_view; - type_view_func uint_view; - type_view_func short_view; - type_view_func double_view; - type_view_func long_view; - type_view_func ulong_view; - type_view_func ushort_view; - type_view_func struct_view; type_view_func union_view; type_view_func enum_view; type_view_func array_view; type_view_func class_view; +#define EV_TYPE(type) type_view_func type##_view; +#include "QF/progs/pr_type_names.h" } type_view_t; void PR_Debug_Init (progs_t *pr); diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index d201bff87..1012f320d 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -43,18 +43,30 @@ typedef uint16_t pr_ushort_t __attribute__((aligned(2)));; typedef t n __attribute__ ((vector_size (s*sizeof (t)))) PR_VEC_TYPE (pr_int_t, pr_ivec2_t, 2); +typedef pr_int_t pr_ivec3_t[3]; PR_VEC_TYPE (pr_int_t, pr_ivec4_t, 4); + PR_VEC_TYPE (pr_uint_t, pr_uivec2_t, 2); +typedef pr_uint_t pr_uivec3_t[3]; PR_VEC_TYPE (pr_uint_t, pr_uivec4_t, 4); + PR_VEC_TYPE (float, pr_vec2_t, 2); +typedef pr_float_t pr_vec3_t[3]; PR_VEC_TYPE (float, pr_vec4_t, 4); + PR_VEC_TYPE (pr_long_t, pr_lvec2_t, 2); +typedef pr_long_t pr_lvec3_t[3]; PR_VEC_TYPE (pr_long_t, pr_lvec4_t, 4); + PR_VEC_TYPE (pr_ulong_t, pr_ulvec2_t, 2); +typedef pr_ulong_t pr_ulvec3_t[3]; PR_VEC_TYPE (pr_ulong_t, pr_ulvec4_t, 4); + PR_VEC_TYPE (double, pr_dvec2_t, 2); +typedef pr_double_t pr_dvec3_t[3]; PR_VEC_TYPE (double, pr_dvec4_t, 4); + #define EV_TYPE(type) ev_##type, typedef enum { #include "QF/progs/pr_type_names.h" @@ -62,7 +74,7 @@ typedef enum { ev_type_count // not a type, gives number of types } etype_t; -#define PR_SIZEOF(type) (sizeof (pr_##type##_t) / sizeof (pr_int_t)) +#define PR_SIZEOF(type) (sizeof (pr_##type##_t) / (sizeof (pr_int_t))) #define PR_ALIGNOF(type) (__alignof__ (pr_##type##_t) / __alignof__ (pr_int_t)) extern const pr_ushort_t pr_type_size[ev_type_count]; diff --git a/include/QF/progs/pr_type_names.h b/include/QF/progs/pr_type_names.h index 5e9904b2a..3e0daf10a 100644 --- a/include/QF/progs/pr_type_names.h +++ b/include/QF/progs/pr_type_names.h @@ -45,6 +45,6 @@ EV_TYPE(short) // value is embedded in the opcode EV_TYPE(double) EV_TYPE(long) EV_TYPE(ulong) -EV_TYPE(ushort) +EV_TYPE(ushort) // value is embedded in the opcode #undef EV_TYPE diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index b9c3862c5..041963233 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -59,6 +59,7 @@ #include "QF/progs/pr_debug.h" #include "QF/progs/pr_type.h" +#include "QF/simd/types.h" #include "compat.h" @@ -121,38 +122,6 @@ cvar_t *pr_source_path; static char *source_path_string; static char **source_paths; -static void pr_debug_void_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_string_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_float_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_field_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_func_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_int_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_uint_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_short_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_double_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_long_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_ulong_view (qfot_type_t *type, pr_type_t *value, - void *_data); -static void pr_debug_ushort_view (qfot_type_t *type, pr_type_t *value, - void *_data); static void pr_debug_struct_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_union_view (qfot_type_t *type, pr_type_t *value, @@ -163,29 +132,20 @@ static void pr_debug_array_view (qfot_type_t *type, pr_type_t *value, void *_data); static void pr_debug_class_view (qfot_type_t *type, pr_type_t *value, void *_data); +#define EV_TYPE(t) \ + static void pr_debug_##t##_view (qfot_type_t *type, pr_type_t *value, \ + void *_data); +#include "QF/progs/pr_type_names.h" static type_view_t raw_type_view = { - pr_debug_void_view, - pr_debug_string_view, - pr_debug_float_view, - pr_debug_vector_view, - pr_debug_entity_view, - pr_debug_field_view, - pr_debug_func_view, - pr_debug_pointer_view, - pr_debug_quat_view, - pr_debug_int_view, - pr_debug_uint_view, - pr_debug_short_view, - pr_debug_double_view, - pr_debug_long_view, - pr_debug_ulong_view, - pr_debug_ushort_view, pr_debug_struct_view, pr_debug_union_view, pr_debug_enum_view, pr_debug_array_view, pr_debug_class_view, +#define EV_TYPE(t) \ + pr_debug_##t##_view, +#include "QF/progs/pr_type_names.h" }; static const char * @@ -1040,60 +1000,18 @@ PR_DumpState (progs_t *pr) #define ISDENORM(x) ((x) && !((x) & 0x7f800000)) -static const char * +static void value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) { switch (type->meta) { case ty_basic: switch (type->type) { - case ev_void: - raw_type_view.void_view (type, value, data); - break; - case ev_string: - raw_type_view.string_view (type, value, data); - break; - case ev_float: - raw_type_view.float_view (type, value, data); - break; - case ev_vector: - raw_type_view.vector_view (type, value, data); - break; - case ev_entity: - raw_type_view.entity_view (type, value, data); - break; - case ev_field: - raw_type_view.field_view (type, value, data); - break; - case ev_func: - raw_type_view.func_view (type, value, data); - break; - case ev_ptr: - raw_type_view.pointer_view (type, value, data); - break; - case ev_quaternion: - raw_type_view.quat_view (type, value, data); - break; - case ev_int: - raw_type_view.int_view (type, value, data); - break; - case ev_uint: - raw_type_view.uint_view (type, value, data); - break; - case ev_short: - raw_type_view.short_view (type, value, data); - break; - case ev_double: - raw_type_view.double_view (type, value, data); - break; - case ev_long: - raw_type_view.long_view (type, value, data); - break; - case ev_ulong: - raw_type_view.ulong_view (type, value, data); - break; - case ev_ushort: - raw_type_view.ushort_view (type, value, data); +#define EV_TYPE(t) \ + case ev_##t: \ + raw_type_view.t##_view (type, value, data); \ break; +#include "QF/progs/pr_type_names.h" + case ev_invalid: case ev_type_count: dstring_appendstr (data->dstr, ""); @@ -1116,9 +1034,9 @@ value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) break; case ty_alias://XXX type = &G_STRUCT (data->pr, qfot_type_t, type->alias.aux_type); - return value_string (data, type, value); + value_string (data, type, value); + break; } - return data->dstr->str; } static pr_def_t * @@ -1331,7 +1249,7 @@ pr_debug_func_view (qfot_type_t *type, pr_type_t *value, void *_data) } static void -pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) +pr_debug_ptr_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; @@ -1353,7 +1271,7 @@ pr_debug_pointer_view (qfot_type_t *type, pr_type_t *value, void *_data) } static void -pr_debug_quat_view (qfot_type_t *type, pr_type_t *value, void *_data) +pr_debug_quaternion_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; From c467217b4bac02305f2378ef8cef2ca6d490f2c3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 10:50:14 +0900 Subject: [PATCH 2336/3664] [simd] Use inttypes.h for long vector formats Much nicer than cluttering up the headers with word-size checks. --- include/QF/simd/types.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index 1f2a511c1..43d564745 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -29,6 +29,7 @@ #define __QF_simd_types_h #include +#include #define VEC_TYPE(t,n,s) \ typedef t n __attribute__ ((vector_size (s*sizeof (t)))) @@ -84,13 +85,9 @@ VEC_TYPE (float, vec4f_t, 4); VEC_TYPE (int, vec4i_t, 4); #define VEC2D_FMT "[%.17g, %.17g]" -#define VEC2L_FMT "[%ld, %ld]" +#define VEC2L_FMT "[%"PRIi64", %"PRIi64"]" #define VEC4D_FMT "[%.17g, %.17g, %.17g, %.17g]" -#if __WORDSIZE == 64 -#define VEC4L_FMT "[%ld, %ld, %ld, %ld]" -#else -#define VEC4L_FMT "[%lld, %lld, %lld, %lld]" -#endif +#define VEC4L_FMT "[%"PRIi64", %"PRIi64", %"PRIi64", %"PRIi64"]" #define VEC2F_FMT "[%.9g, %.9g]" #define VEC2I_FMT "[%d, %d]" #define VEC4F_FMT "[%.9g, %.9g, %.9g, %.9g]" From feb3be4e6b1878828cf2978b8ee84a93cd2d1235 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 10:54:07 +0900 Subject: [PATCH 2337/3664] [qfcc] Add types for ivec3/4 and vec3/4 Needed to get quaternions and vectors going. I'll add more later. --- tools/qfcc/include/type.h | 9 +++ tools/qfcc/source/class.c | 129 ++++++++++++++++++++++++++++------- tools/qfcc/source/function.c | 1 + tools/qfcc/source/opcodes.c | 26 ++++++- tools/qfcc/source/struct.c | 3 +- tools/qfcc/source/type.c | 126 +++++++++++++++++++++++++++++----- 6 files changed, 248 insertions(+), 46 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index b8cff36e5..2062933d6 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -60,6 +60,9 @@ typedef struct type_s { etype_t type; ///< ev_invalid means structure/array etc const char *name; int alignment; ///< required alignment for instances + int width; ///< components in vector types, otherwise 1 + ///< vector and quaternion are 1 (separate from + ///< vec3 and vec4) /// function/pointer/array/struct types are more complex ty_meta_e meta; union { @@ -99,6 +102,11 @@ typedef struct { #define EV_TYPE(type) extern type_t type_##type; #include "QF/progs/pr_type_names.h" +extern type_t type_ivec3; +extern type_t type_ivec4; +extern type_t type_vec3; +extern type_t type_vec4; + extern type_t type_invalid; extern type_t type_floatfield; @@ -158,6 +166,7 @@ const char *type_get_encoding (const type_t *type); int is_enum (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); int is_scalar (const type_t *type) __attribute__((pure)); +int is_nonscalar (const type_t *type) __attribute__((pure)); int is_math (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index ce4499fdc..d90ecc062 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -71,33 +71,114 @@ static hashtab_t *static_instances; static hashtab_t *static_instance_classes; // these will be built up further -type_t type_selector = { ev_invalid, 0, 0, ty_struct}; -type_t type_SEL = { ev_ptr, "SEL", 1, ty_basic, {{&type_selector}}}; -type_t *IMP_params[] = {&type_id, &type_SEL}; -type_t type_IMP = { ev_func, "IMP", 1, ty_basic, - {{&type_id, -3, IMP_params}}}; -type_t type_super = { ev_invalid, 0, 0 }; -type_t type_SuperPtr = { ev_ptr, 0, 1, ty_basic, {{&type_super}}}; -type_t *supermsg_params[] = {&type_SuperPtr, &type_SEL}; -type_t type_supermsg = { ev_func, ".supermsg", 1, ty_basic, - {{&type_id, -3, supermsg_params}}}; -type_t type_method = { ev_invalid, 0, 0, ty_struct }; -type_t type_method_description = { ev_invalid, 0, 0, ty_struct }; -type_t type_category = { ev_invalid, 0, 0, ty_struct}; -type_t type_ivar = { ev_invalid, 0, 0, ty_struct}; -type_t type_module = { ev_invalid, 0, 0, ty_struct}; -type_t type_moduleptr = { ev_ptr, 0, 1, ty_basic, {{&type_module}}}; -type_t *obj_exec_class_params[] = { &type_moduleptr }; -type_t type_exec_class = { ev_func, 0, 1, ty_basic, - {{&type_void, 1, obj_exec_class_params}}}; +type_t type_selector = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_SEL = { + .type = ev_ptr, + .name = "SEL", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_selector}}, +}; +type_t *IMP_params[] = { &type_id, &type_SEL }; +type_t type_IMP = { + .type = ev_func, + .name = "IMP", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_id, -3, IMP_params}}, +}; +type_t type_super = { + .type = ev_invalid, +}; +type_t type_SuperPtr = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_super}}, +}; +type_t *supermsg_params[] = { &type_SuperPtr, &type_SEL }; +type_t type_supermsg = { + .type = ev_func, + .name = ".supermsg", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_id, -3, supermsg_params}}, +}; +type_t type_method = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_method_description = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_category = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_ivar = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_module = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_moduleptr = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_module}}, +}; +type_t *obj_exec_class_params[] = { + &type_moduleptr, +}; +type_t type_exec_class = { + .type = ev_func, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_void, 1, obj_exec_class_params}}, +}; // the cast of 1 in the init is to ensure pointers to incomplete types // are never misidentified as id. It will be set to the correct value // when the obj system is initialized. -type_t type_object = {ev_invalid, 0, 0, ty_struct, {{(type_t *)1}}}; -type_t type_id = { ev_ptr, "id", 1, ty_basic, {{&type_object}}}; -type_t type_class = { ev_invalid, 0, 0, ty_struct}; -type_t type_Class = { ev_ptr, 0, 1, ty_basic, {{&type_class}}}; -type_t type_protocol = { ev_invalid, 0, 0, ty_struct}; +type_t type_object = { + .type = ev_invalid, + .meta = ty_struct, + {{(type_t *)1}}, +}; +type_t type_id = { + .type = ev_ptr, + .name = "id", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_object}}, +}; +type_t type_class = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_Class = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_class}}, +}; +type_t type_protocol = { + .type = ev_invalid, + .meta = ty_struct, +}; int obj_initialized = 0; diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index aa4f79134..c85b68edf 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -185,6 +185,7 @@ parse_params (type_t *type, param_t *parms) new = new_type (); new->type = ev_func; new->alignment = 1; + new->width = 1; new->t.func.type = type; new->t.func.num_params = 0; diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 51c7ce26d..79cc48943 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -230,12 +230,32 @@ v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, return op; } +static etype_t +operand_type (operand_t *op) +{ + if (!op) { + return ev_invalid; + } + etype_t type = low_level_type (op->type); + if (type == ev_vector || type == ev_quaternion) { + return ev_float; + } + return type; +} + static int operand_width (operand_t *op) { if (!op) { return 0; } + etype_t type = low_level_type (op->type); + if (type == ev_vector) { + return 3; + } + if (type == ev_quaternion) { + return 4; + } return op->width; } @@ -246,9 +266,9 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, opcode_t search_op = { .opname = name, .types = { - op_a ? low_level_type (op_a->type) : ev_invalid, - op_b ? low_level_type (op_b->type) : ev_invalid, - op_c ? low_level_type (op_c->type) : ev_invalid, + operand_type (op_a), + operand_type (op_b), + operand_type (op_c), }, .widths = { operand_width (op_a), diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 798696ac3..4a9f64bce 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -194,6 +194,8 @@ start_enum (symbol_t *sym) sym = find_enum (0); } sym->type->t.symtab = new_symtab (current_symtab, stab_local); + sym->type->alignment = 1; + sym->type->width = 1; return sym->type->t.symtab; } @@ -207,7 +209,6 @@ finish_enum (symbol_t *sym) enum_type = sym->type = find_type (sym->type); enum_tab = enum_type->t.symtab; - enum_type->alignment = 1; for (name = enum_tab->symbols; name; name = name->next) { name->type = sym->type; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index ceb0360a5..94bf6aed0 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -65,6 +65,8 @@ .type = ev_##t, \ .name = #t, \ .alignment = PR_ALIGNOF(t), \ + .width = __builtin_choose_expr (ev_##t == ev_short \ + || ev_##t == ev_ushort, 0, 1), \ .meta = ty_basic, \ {{ __builtin_choose_expr (ev_##t == ev_field \ || ev_##t == ev_func \ @@ -72,7 +74,23 @@ }; #include "QF/progs/pr_type_names.h" -type_t type_invalid = { ev_invalid, "invalid" }; +type_t type_invalid = { + .type = ev_invalid, + .name = "invalid", +}; + +#define VTYPE(t, b) \ + type_t type_##t = { \ + .type = ev_##b, \ + .name = #t, \ + .alignment = PR_ALIGNOF(t), \ + .width = PR_SIZEOF(t) / PR_SIZEOF (b), \ + .meta = ty_basic, \ + }; +VTYPE(ivec3, int) +VTYPE(ivec4, int) +VTYPE(vec3, float) +VTYPE(vec4, float) type_t *type_nil; type_t *type_default; @@ -80,17 +98,49 @@ type_t *type_long_int; type_t *type_ulong_uint; // these will be built up further -type_t type_va_list = { ev_invalid, 0, 0, ty_struct }; -type_t type_param = { ev_invalid, 0, 0, ty_struct }; -type_t type_zero = { ev_invalid, 0, 0, ty_struct }; -type_t type_type_encodings = { ev_invalid, "@type_encodings", 0, - ty_struct }; -type_t type_xdef = { ev_invalid, "@xdef", 0, ty_struct }; -type_t type_xdef_pointer = { ev_ptr, 0, 1, ty_basic, {{&type_xdef}} }; -type_t type_xdefs = { ev_invalid, "@xdefs", 0, ty_struct }; +type_t type_va_list = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_param = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_zero = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_type_encodings = { + .type = ev_invalid, + .name = "@type_encodings", + .meta = ty_struct, +}; +type_t type_xdef = { + .type = ev_invalid, + .name = "@xdef", + .meta = ty_struct, +}; +type_t type_xdef_pointer = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_xdef}}, +}; +type_t type_xdefs = { + .type = ev_invalid, + .name = "@xdefs", + .meta = ty_struct, +}; -type_t type_floatfield = { ev_field, ".float", 1, ty_basic, - {{&type_float}} }; +type_t type_floatfield = { + .type = ev_field, + .name = ".float", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_float}}, +}; #define EV_TYPE(type) &type_##type, type_t *ev_types[ev_type_count] = { @@ -280,10 +330,12 @@ append_type (type_t *type, type_t *new) case ev_ptr: t = &(*t)->t.fldptr.type; type->alignment = 1; + type->width = 1; break; case ev_func: t = &(*t)->t.func.type; type->alignment = 1; + type->width = 1; break; case ev_invalid: internal_error (0, "invalid basic type"); @@ -293,6 +345,7 @@ append_type (type_t *type, type_t *new) case ty_array: t = &(*t)->t.array.type; type->alignment = new->alignment; + type->width = new->width; break; case ty_struct: case ty_union: @@ -339,7 +392,7 @@ types_same (type_t *a, type_t *b) return 0; return 1; default: // other types don't have aux data - return 1; + return a->width == b->width; } break; case ty_struct: @@ -447,6 +500,7 @@ field_type (type_t *aux) new = new_type (); new->type = ev_field; new->alignment = 1; + new->width = 1; if (aux) { new = find_type (append_type (new, aux)); } @@ -465,6 +519,7 @@ pointer_type (type_t *aux) new = new_type (); new->type = ev_ptr; new->alignment = 1; + new->width = 1; if (aux) { new = find_type (append_type (new, aux)); } @@ -485,6 +540,7 @@ array_type (type_t *aux, int size) new->type = ev_invalid; if (aux) { new->alignment = aux->alignment; + new->width = aux->width; } new->t.array.size = size; if (aux) { @@ -506,6 +562,7 @@ based_array_type (type_t *aux, int base, int top) new->type = ev_invalid; if (aux) { new->alignment = aux->alignment; + new->width = aux->width; } new->meta = ty_array; new->t.array.type = aux; @@ -523,6 +580,7 @@ alias_type (type_t *type, type_t *alias_chain, const char *name) alias->meta = ty_alias; alias->type = type->type; alias->alignment = type->alignment; + alias->width = type->width; if (type == alias_chain && type->meta == ty_alias) { // typedef of a type that contains a typedef somewhere // grab the alias-free branch for type @@ -868,6 +926,23 @@ int is_scalar (const type_t *type) { type = unalias_type (type); + if (is_short (type) || is_ushort (type)) { + // shorts have width 0 + return 1; + } + if (type->width != 1) { + return 0; + } + return is_float (type) || is_integral (type) || is_double (type); +} + +int +is_nonscalar (const type_t *type) +{ + type = unalias_type (type); + if (type->width < 2) { + return 0; + } return is_float (type) || is_integral (type) || is_double (type); } @@ -875,9 +950,11 @@ int is_math (const type_t *type) { type = unalias_type (type); - etype_t t = type->type; - return t == ev_vector || t == ev_quaternion || is_scalar (type); + if (is_vector (type) || is_quaternion (type)) { + return 1; + } + return is_scalar (type) || is_nonscalar (type); } int @@ -981,7 +1058,7 @@ type_size (const type_t *type) { switch (type->meta) { case ty_basic: - return pr_type_size[type->type]; + return pr_type_size[type->type] * type->width; case ty_struct: case ty_union: if (!type->t.symtab) @@ -1015,10 +1092,13 @@ type_width (const type_t *type) { switch (type->meta) { case ty_basic: - if (type->type == ev_ushort || type->type == ev_short) { - return 0; + if (type->type == ev_vector) { + return 3; } - return 1; //FIXME vector should be 3 + if (type->type == ev_quaternion) { + return 4; + } + return type->width; case ty_struct: case ty_union: return 1; @@ -1050,11 +1130,21 @@ chain_basic_types (void) chain_type (&type_ptr); chain_type (&type_floatfield); if (!options.traditional) { + if (options.code.progsversion == PROG_VERSION) { + type_quaternion.alignment = 4; + } chain_type (&type_quaternion); chain_type (&type_int); chain_type (&type_uint); chain_type (&type_short); chain_type (&type_double); + + if (options.code.progsversion == PROG_VERSION) { + chain_type (&type_ivec3); + chain_type (&type_ivec4); + chain_type (&type_vec3); + chain_type (&type_vec4); + } } } From 3f389b602a4b987dfb2b8b68f26be323c7f3e919 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 10:56:15 +0900 Subject: [PATCH 2338/3664] [qfcc] Add support for horizontal vector ops And reimplement vector comparison for Ruamoko. --- tools/qfcc/include/expr.h | 24 ++++++++++++-- tools/qfcc/include/expr_names.h | 1 + tools/qfcc/source/expr.c | 34 ++++++++++++++++++++ tools/qfcc/source/expr_assign.c | 1 + tools/qfcc/source/expr_binary.c | 21 +++++++++++-- tools/qfcc/source/qc-parse.y | 1 + tools/qfcc/source/qp-parse.y | 1 + tools/qfcc/source/statements.c | 56 ++++++++++++++++++++++++++++++++- 8 files changed, 134 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index f2b934324..5181dfbc6 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -249,6 +249,12 @@ typedef struct { struct expr_s *with; ///< value to load } ex_with_t; +typedef struct { + int op; ///< operation to perform + struct expr_s *vec; ///< vector expression on which to operate + struct type_s *type; ///< result type +} ex_horizontal_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -283,6 +289,7 @@ typedef struct expr_s { ex_adjstk_t adjstk; ///< stack adjust param ex_with_t with; ///< with expr param struct type_s *nil; ///< type for nil if known + ex_horizontal_t hop; ///< horizontal vector operation } e; } expr_t; @@ -432,7 +439,7 @@ void build_element_chain (element_chain_t *element_chain, expr_t *eles, int base_offset); void free_element_chain (element_chain_t *element_chain); -/** Create a new binary expression node node. +/** Create a new binary expression node. If either \a e1 or \a e2 are error expressions, then that expression will be returned instead of a new binary expression. @@ -446,7 +453,7 @@ void free_element_chain (element_chain_t *element_chain); */ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2); -/** Create a new unary expression node node. +/** Create a new unary expression node. If \a e1 is an error expression, then it will be returned instead of a new unary expression. @@ -458,6 +465,19 @@ expr_t *new_binary_expr (int op, expr_t *e1, expr_t *e2); */ expr_t *new_unary_expr (int op, expr_t *e1); +/** Create a new horizontal vector operantion node. + + If \a vec is an error expression, then it will be returned instead of a + new unary expression. + + \param op The op-code of the horizontal operation. + \param vec The expression (must be a vector type) on which to operate. + \param type The result type (must be scalar type) + \return The new unary expression node (::ex_expr_t) if \a e1 + is not an error expression, otherwise \a e1. +*/ +expr_t *new_horizontal_expr (int op, expr_t *vec, struct type_s *type); + /** Create a new def reference (non-temporary variable) expression node. \return The new def reference expression node (::def_t). diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index 820ba9826..05d1f197a 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -62,5 +62,6 @@ EX_EXPR(return) ///< return expression (::ex_return_t) EX_EXPR(adjstk) ///< stack adjust expression (::ex_adjstk_t) EX_EXPR(with) ///< with expression (::ex_with_t) EX_EXPR(args) ///< @args marker in parameter list. no data +EX_EXPR(horizontal) ///< horizontal vector operation (::ex_horzontal_t) ///@} diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 66140bc52..7af72d5a1 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -276,6 +276,8 @@ get_type (expr_t *e) return get_type (e->e.assign.dst); case ex_args: return &type_va_list; + case ex_horizontal: + return e->e.hop.type; case ex_count: internal_error (e, "invalid expression"); } @@ -531,6 +533,11 @@ copy_expr (expr_t *e) n = new_expr (); *n = *e; return n; + case ex_horizontal: + n = new_expr (); + *n = *e; + e->e.hop.vec = copy_expr (e->e.hop.vec); + return n; case ex_count: break; } @@ -695,6 +702,28 @@ new_unary_expr (int op, expr_t *e1) return e; } +expr_t * +new_horizontal_expr (int op, expr_t *vec, type_t *type) +{ + type_t *vec_type = get_type (vec); + if (!vec_type) { + return vec; + } + if (!is_math (vec_type) || is_scalar (vec_type)) { + internal_error (vec, "horizontal operand not a vector type"); + } + if (!is_scalar (type)) { + internal_error (vec, "horizontal result not a scalar type"); + } + + expr_t *e = new_expr (); + e->type = ex_horizontal; + e->e.hop.op = op; + e->e.hop.vec = vec; + e->e.hop.type = type; + return e; +} + expr_t * new_def_expr (def_t *def) { @@ -1733,6 +1762,8 @@ has_function_call (expr_t *e) return has_function_call (e->e.branch.test); case ex_return: return has_function_call (e->e.retrn.ret_val); + case ex_horizontal: + return has_function_call (e->e.hop.vec); case ex_error: case ex_state: case ex_label: @@ -1873,6 +1904,7 @@ unary_expr (int op, expr_t *e) case ex_vector: case ex_alias: case ex_assign: + case ex_horizontal: { expr_t *n = new_unary_expr (op, e); @@ -1965,6 +1997,7 @@ unary_expr (int op, expr_t *e) case ex_alias: case ex_address: case ex_assign: + case ex_horizontal: if (options.code.progsversion == PROG_VERSION) { return binary_expr (EQ, e, new_nil_expr ()); } else { @@ -2053,6 +2086,7 @@ unary_expr (int op, expr_t *e) case ex_vector: case ex_alias: case ex_assign: + case ex_horizontal: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { expr_t *n1 = new_int_expr (-1); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index f9a66b1be..e193de6aa 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -141,6 +141,7 @@ is_lvalue (const expr_t *expr) case ex_adjstk: case ex_with: case ex_args: + case ex_horizontal: break; case ex_count: internal_error (expr, "invalid expression"); diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index c2acf4028..f533b38cd 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -51,6 +51,7 @@ static expr_t *pointer_compare (int op, expr_t *e1, expr_t *e2); static expr_t *func_compare (int op, expr_t *e1, expr_t *e2); static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2); static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); +static expr_t *vector_compare (int op, expr_t *e1, expr_t *e2); static expr_type_t string_string[] = { {'+', &type_string}, @@ -145,8 +146,8 @@ static expr_type_t vector_vector[] = { {'+', &type_vector}, {'-', &type_vector}, {'*', &type_float}, - {EQ, &type_int}, - {NE, &type_int}, + {EQ, 0, 0, 0, vector_compare}, + {NE, 0, 0, 0, vector_compare}, {0, 0} }; @@ -721,6 +722,22 @@ inverse_multiply (int op, expr_t *e1, expr_t *e2) return binary_expr ('*', e1, binary_expr ('/', one, e2)); } +static expr_t * +vector_compare (int op, expr_t *e1, expr_t *e2) +{ + if (options.code.progsversion < PROG_VERSION) { + expr_t *e = new_binary_expr (op, e1, e2); + e->e.expr.type = &type_int; + return e; + } + int hop = op == EQ ? '&' : '|'; + e1 = new_alias_expr (&type_vec3, e1); + e2 = new_alias_expr (&type_vec3, e2); + expr_t *e = new_binary_expr (op, e1, e2); + e->e.expr.type = &type_ivec3; + return new_horizontal_expr (hop, e, &type_int); +} + static expr_t * double_compare (int op, expr_t *e1, expr_t *e2) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 282f501ae..0e23c1eb2 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -133,6 +133,7 @@ int yylex (void); %left '&' %left EQ NE %left LT GT GE LE +%token NAND NOR XNOR // end of tokens common between qc and qp %left SHL SHR diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index db0274ce4..550f8e3f8 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -114,6 +114,7 @@ int yylex (void); %left '&' %left EQ NE %left LT GT GE LE +%token NAND NOR XNOR // end of tokens common between qc and qp %left RELOP diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 2ade73a9f..3de08e449 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1666,6 +1666,59 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_horizontal (sblock_t *sblock, expr_t *e, operand_t **op) +{ + const char *opcode = "hops"; + statement_t *s; + int hop; + type_t *res_type = e->e.hop.type; + type_t *vec_type = get_type (e->e.hop.vec); + + switch (e->e.hop.op) { + case '&': + hop = 0; + break; + case '|': + hop = 1; + break; + case '^': + hop = 2; + break; + case '+': + if (is_integral (vec_type)) { + hop = 3; + } else { + hop = 7; + } + break; + case NAND: + hop = 4; + break; + case NOR: + hop = 5; + break; + case XNOR: + hop = 6; + break; + default: + internal_error (e, "invalid horizontal op"); + } + hop |= (type_width (vec_type) - 1) << 3; + hop |= (pr_type_size[vec_type->type] - 1) << 5; + + s = new_statement (st_expr, opcode, e); + sblock = statement_subexpr (sblock, e->e.hop.vec, &s->opa); + s->opb = short_operand (hop, e); + if (!*op) { + *op = temp_operand (res_type, e); + } + s->opc = *op; + sblock_add_statement (sblock, s); + + return sblock; +} + static sblock_t * expr_def (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1826,6 +1879,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_block] = expr_block, [ex_expr] = expr_expr, [ex_uexpr] = expr_uexpr, + [ex_horizontal] = expr_horizontal, [ex_def] = expr_def, [ex_symbol] = expr_symbol, [ex_temp] = expr_temp, @@ -1844,7 +1898,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) } if (e->type >= ex_count) - internal_error (e, "bad sub-expression type"); + internal_error (e, "bad sub-expression type: %d", e->type); if (!sfuncs[e->type]) internal_error (e, "unexpected sub-expression type: %s", expr_names[e->type]); From 218481764b5817f623bb17a22532a5ba46654228 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 13:57:41 +0900 Subject: [PATCH 2339/3664] [qfcc] Add failing test for temp.component While it specifically checks vectors, I'm pretty sure it applies to structs, too. Also, it's a little redundant with vecaddr.r, but is much more specific and far less evil in what it does (no horrible pointer shenanigans): just something that is fairly common practice. --- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/temp-component.r | 13 +++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tools/qfcc/test/temp-component.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index acfa99873..eaa3d673c 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -54,6 +54,7 @@ test_progs_dat=\ tools/qfcc/test/structptr.dat \ tools/qfcc/test/structstruct.dat \ tools/qfcc/test/swap.dat \ + tools/qfcc/test/temp-component.dat \ tools/qfcc/test/triangle.dat \ tools/qfcc/test/twice-called.dat \ tools/qfcc/test/typedef.dat \ @@ -618,6 +619,16 @@ tools/qfcc/test/swap.run: $(qfcc_test_run_deps) include $(swap_dep) # am--include-marker r_depfiles_remade += $(swap_dep) +tools_qfcc_test_temp_component_dat_SOURCES=tools/qfcc/test/temp-component.r +temp_component_obj=$(tools_qfcc_test_temp_component_dat_SOURCES:.r=.o) +temp_component_dep=$(call qcautodep,$(tools_qfcc_test_temp_component_dat_SOURCES)) +tools/qfcc/test/temp-component.dat$(EXEEXT): $(temp_component_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(temp_component_obj) +tools/qfcc/test/temp-component.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(temp_component_dep) # am--include-marker +r_depfiles_remade += $(temp_component_dep) + tools_qfcc_test_triangle_dat_SOURCES=tools/qfcc/test/triangle.r triangle_obj=$(tools_qfcc_test_triangle_dat_SOURCES:.r=.o) triangle_dep=$(call qcautodep,$(tools_qfcc_test_triangle_dat_SOURCES)) diff --git a/tools/qfcc/test/temp-component.r b/tools/qfcc/test/temp-component.r new file mode 100644 index 000000000..2db18a401 --- /dev/null +++ b/tools/qfcc/test/temp-component.r @@ -0,0 +1,13 @@ +float +gety(vector v, vector z) +{ + return (v + z).y; +} + +int +main () +{ + vector a = [1, 2, 3]; + vector b = [1, 2, 6]; + return gety (a, b) != 4; +} From e195dba6264682c0aac7ff31776c3413df855f8a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 14:02:13 +0900 Subject: [PATCH 2340/3664] [qfcc] Do not unalias temporary operands I don't remember why I did this originally, but it causes the dags code to lose the offset temp alias when accessing fields on structural temps (known to be the case for vectors (temp-component.r), and I seem to remember having problems with structs). --- tools/qfcc/source/dags.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index ac3a36a63..7a52a4f6b 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -231,8 +231,6 @@ dag_node (operand_t *op) if (def->daglabel) node = def->daglabel->dagnode; } else if (op->op_type == op_temp) { - while (op->tempop.alias) - op = op->tempop.alias; if (op->tempop.daglabel) node = op->tempop.daglabel->dagnode; } else if (op->op_type == op_value) { From 46ce37160bb38d42cd77f6aef05dc6295ec48a25 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 14:11:41 +0900 Subject: [PATCH 2341/3664] [gamecode] Correct vecops widths I had forgotten to update the widths when I moved cross product's position. --- libs/gamecode/opcodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index d2da04ed7..61e65f136 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -478,10 +478,10 @@ vecops_formats = { "cmul", "qvmul", "vqmul", "qmul"], "vop_type": ['F', 'D'], "vec_widths": [ + "3, 3, 3", "2, 2, 2", "3, 3, 3", "4, 4, 4", - "3, 3, 3", "2, 2, 2", "4, 3, 3", "3, 4, 3", From d8f6a9445e5874271ccf21a708cf691878301d3a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 14:14:15 +0900 Subject: [PATCH 2342/3664] [qfcc] Implement dot and cross product for Ruamoko With explicit operators, even. While they're a tad verbose, they're at least unambiguous and most importantly have the right precedence (or at least adjustable precedence if I got it wrong, but vector ops having high precedence than scalar or component seems reasonable to me). --- tools/qfcc/source/dot_expr.c | 2 ++ tools/qfcc/source/expr_binary.c | 19 ++++++++++++++++++- tools/qfcc/source/qc-lex.l | 3 +++ tools/qfcc/source/qc-parse.y | 3 +++ tools/qfcc/source/statements.c | 10 ++++++++++ 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index e5b5e87ea..04784856a 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -90,6 +90,8 @@ get_op_string (int op) case SHR: return ">>"; case '.': return "."; case 'C': return ""; + case CROSS: return "@cross"; + case DOT: return "@dot"; default: return "unknown"; } diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index f533b38cd..47dc3ae5c 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -52,6 +52,7 @@ static expr_t *func_compare (int op, expr_t *e1, expr_t *e2); static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2); static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); static expr_t *vector_compare (int op, expr_t *e1, expr_t *e2); +static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2); static expr_type_t string_string[] = { {'+', &type_string}, @@ -145,7 +146,9 @@ static expr_type_t vector_float[] = { static expr_type_t vector_vector[] = { {'+', &type_vector}, {'-', &type_vector}, - {'*', &type_float}, + {DOT, &type_vector}, + {CROSS, &type_vector}, + {'*', 0, 0, 0, vector_multiply}, {EQ, 0, 0, 0, vector_compare}, {NE, 0, 0, 0, vector_compare}, {0, 0} @@ -738,6 +741,20 @@ vector_compare (int op, expr_t *e1, expr_t *e2) return new_horizontal_expr (hop, e, &type_int); } +static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2) +{ + expr_t *e = new_binary_expr ('*', e1, e2); + if (options.code.progsversion < PROG_VERSION) { + // vector * vector is dot product in v6 progs (ick) + e->e.expr.type = &type_float; + } else { + // component-wise multiplication + e->e.expr.type = &type_vector; + } + + return e; +} + static expr_t * double_compare (int op, expr_t *e1, expr_t *e2) { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 7ce445539..c2db6db0c 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -386,6 +386,9 @@ static keyword_t qf_keywords[] = { {"@args", ARGS, 0 }, {"@va_list", TYPE, &type_va_list }, {"@param", TYPE, &type_param }, + + {"@cross", CROSS, 0 }, + {"@dot", DOT, 0 }, }; // These keywors are always available. Other than @system and @overload, they diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 0e23c1eb2..7d294db13 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -139,6 +139,7 @@ int yylex (void); %left SHL SHR %left '+' '-' %left '*' '/' '%' MOD +%left CROSS DOT %right SIZEOF UNARY INCOP %left HYPERUNARY %left '.' '(' '[' @@ -1621,6 +1622,8 @@ expr | expr '^' expr { $$ = binary_expr ('^', $1, $3); } | expr '%' expr { $$ = binary_expr ('%', $1, $3); } | expr MOD expr { $$ = binary_expr (MOD, $1, $3); } + | expr CROSS expr { $$ = binary_expr (CROSS, $1, $3); } + | expr DOT expr { $$ = binary_expr (DOT, $1, $3); } ; texpr diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 3de08e449..bce46f8cd 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -604,6 +604,8 @@ convert_op (int op) case SHL: return "shl"; case SHR: return "shr"; case '.': return "load"; + case CROSS: return "cross"; + case DOT: return "dot"; default: return 0; } @@ -1568,6 +1570,14 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) if (strcmp (opcode, "ne") == 0 && is_string (get_type (e->e.expr.e1))) { opcode = "cmp"; } + if (strcmp (opcode, "dot") == 0) { + if (is_vector (get_type (e->e.expr.e1))) { + opcode = "vdot"; + } + if (is_quaternion (get_type (e->e.expr.e1))) { + opcode = "qdot"; + } + } s = new_statement (st_expr, opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); From 09eef8a07bc5ae2b2651a6d2bf2be2dc7187fa08 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 14:21:07 +0900 Subject: [PATCH 2343/3664] [qfcc] Define __RUAMOKO__ as 2 for Ruamoko ISA and __RAUMOKO__ as well. --- tools/qfcc/source/options.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 7283ba9f7..573730986 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -713,8 +713,13 @@ DecodeArgs (int argc, char **argv) options.code.progsversion = PROG_V6P_VERSION; if (!options.traditional) { options.advanced = true; - add_cpp_def ("-D__RUAMOKO__=1"); - add_cpp_def ("-D__RAUMOKO__=1"); + if (options.code.progsversion < PROG_VERSION) { + add_cpp_def ("-D__RUAMOKO__=1"); + add_cpp_def ("-D__RAUMOKO__=1"); + } else { + add_cpp_def ("-D__RUAMOKO__=2"); + add_cpp_def ("-D__RAUMOKO__=2"); + } if (options.code.ifstring == (qboolean) -1) options.code.ifstring = false; if (options.code.short_circuit == (qboolean) -1) From d18ee8dd86a77fb98f1be2ce12efa8fdb8c81041 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 14:17:52 +0900 Subject: [PATCH 2344/3664] [qfcc] Make vecaddr work in both v6p and Ruamoko It's full of evil hacks, but has always been an evil hack relying on undefined behavior. The weird shenanigans with local variables are because Ruamoko doesn't copy the parameters like v6p does and thus v and z are NOT adjacent as parameters. Worse, the padding is uninitialized and thus should not be relied upon to be any particular value. Still does a nice job of testing dot products, though. --- tools/qfcc/test/vecaddr.r | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/test/vecaddr.r b/tools/qfcc/test/vecaddr.r index 323d9205c..6bd407d9b 100644 --- a/tools/qfcc/test/vecaddr.r +++ b/tools/qfcc/test/vecaddr.r @@ -1,8 +1,25 @@ void printf (string fmt, ...) = #0; -float foo (vector v, float z) +#if __RUAMOKO__ > 1 +#define dot @dot +#define X .y +#else +#define dot * +#define X +#endif + +void forcelive (float z) { - return v * *(vector*)(&v.y); +} + +float foo (vector _v, float _z) +{ + vector v = _v; + float z = _z; + _v = nil; + _z = _z - _z; + forcelive (z); + return (v dot *(vector*)(&v.y))X; } int @@ -11,6 +28,6 @@ main (int argc, string *argv) vector v = [1, 2, 3]; vector w = [2, 3, 4]; float f; - printf ("%v %g %g %g\n", v, v*v, v*w, f=foo (v, 4)); - return f != v*w; + printf ("%v %g %g %g\n", v, v dot v, v dot w, f=foo (v, 4)); + return f != (v dot w)X; } From 4871717faec50611f9ebdcae2e2ba31075c8b485 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 14:47:26 +0900 Subject: [PATCH 2345/3664] [gamecode] Rename v6 vector-scalar multiply to scale Makes it easier to get Ruamoko scaling implemented if they both use the same opname. --- libs/gamecode/pr_v6p_opcode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index c99ef1580..a76dfe06e 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -89,11 +89,11 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { ev_vector, ev_vector, ev_float, PROG_ID_VERSION, }, - [OP_MUL_FV_v6p] = {"mul", "mul.fv", + [OP_MUL_FV_v6p] = {"scale", "mul.fv", ev_float, ev_vector, ev_vector, PROG_ID_VERSION, }, - [OP_MUL_VF_v6p] = {"mul", "mul.vf", + [OP_MUL_VF_v6p] = {"scale", "mul.vf", ev_vector, ev_float, ev_vector, PROG_ID_VERSION, }, From 4b8fdf36968adbd50d61e3abae867238bb94d57b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 14:48:49 +0900 Subject: [PATCH 2346/3664] [qfcc] Implement vector scaling for Ruamoko With this, qfcc-tests builds (can't run yet due to unsigned not having any tests and thus the rest the Ruamoko code in QF not building yet). --- tools/qfcc/source/constfold.c | 4 ++-- tools/qfcc/source/expr_binary.c | 20 ++++++++++++++++++-- tools/qfcc/source/qc-parse.y | 2 +- tools/qfcc/source/statements.c | 1 + 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index ae36079b3..6b01bc7f4 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -446,7 +446,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) { const float *v1, *v2; vec3_t v, float_vec; - static int valid[] = {'+', '-', '*', EQ, NE, 0}; + static int valid[] = {'+', '-', '*', SCALE, EQ, NE, 0}; expr_t *t; if (!is_vector(get_type (e1))) { @@ -460,7 +460,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) } if (!is_vector(get_type (e2))) { e->e.expr.e2 = e2 = convert_to_float (e2); - if (op != '*' && op != '/') + if (op != SCALE && op != '/') return error (e1, "invalid operator for vector"); } else { if (!valid_op (op, valid)) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 47dc3ae5c..5bd004d42 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -53,6 +53,7 @@ static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2); static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); static expr_t *vector_compare (int op, expr_t *e1, expr_t *e2); static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2); +static expr_t *vector_scale (int op, expr_t *e1, expr_t *e2); static expr_type_t string_string[] = { {'+', &type_string}, @@ -89,7 +90,7 @@ static expr_type_t float_float[] = { }; static expr_type_t float_vector[] = { - {'*', &type_vector}, + {'*', .process = vector_scale }, {0, 0} }; @@ -138,7 +139,7 @@ static expr_type_t float_double[] = { }; static expr_type_t vector_float[] = { - {'*', &type_vector}, + {'*', .process = vector_scale }, {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; @@ -755,6 +756,21 @@ static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2) return e; } +static expr_t *vector_scale (int op, expr_t *e1, expr_t *e2) +{ + // Ensure the expression is always vector * scalar. The operation is + // always commutative, and the Ruamoko ISA supports only vector * scalar + // (though v6 does support scalar * vector, one less if). + if (is_scalar (get_type (e1))) { + expr_t *t = e1; + e1 = e2; + e2 = t; + } + expr_t *e = new_binary_expr (SCALE, e1, e2); + e->e.expr.type = get_type (e1); + return e; +} + static expr_t * double_compare (int op, expr_t *e1, expr_t *e2) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 7d294db13..3ab14cbe2 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -138,7 +138,7 @@ int yylex (void); %left SHL SHR %left '+' '-' -%left '*' '/' '%' MOD +%left '*' '/' '%' MOD SCALE %left CROSS DOT %right SIZEOF UNARY INCOP %left HYPERUNARY diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index bce46f8cd..e9b375aba 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -606,6 +606,7 @@ convert_op (int op) case '.': return "load"; case CROSS: return "cross"; case DOT: return "dot"; + case SCALE: return "scale"; default: return 0; } From e1a0c31e3f5ba832f8787bcd4048d1551fce84d7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 16:00:49 +0900 Subject: [PATCH 2347/3664] [qfcc] Encode the new vector types Thanks to the size of the type encoding being explicit in the encoding, anything that tries to read the encodings without expecting the width will simply skip over the width, as it is placed after the ev type in the encoding. Any code that needs to read both the old encodings and the new can check the size of the basic encodings to see if the width field is present. --- include/QF/progs/pr_type.h | 7 +++++++ tools/qfcc/source/dump_globals.c | 9 ++++++++ tools/qfcc/source/obj_type.c | 5 +++-- tools/qfcc/source/type.c | 36 ++++++++++++++++++++++++++------ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/include/QF/progs/pr_type.h b/include/QF/progs/pr_type.h index 02c591dfa..7f117e7a3 100644 --- a/include/QF/progs/pr_type.h +++ b/include/QF/progs/pr_type.h @@ -62,6 +62,12 @@ typedef struct qfot_fldptr_s { pr_ptr_t aux_type; ///< referenced type } qfot_fldptr_t; +typedef struct qfot_basic_s { + etype_t type; ///< integral and fp scalar types + pr_int_t width; ///< components in vector (1 for vector or + ///< quaternion) +} qfot_basic_t; + typedef struct qfot_func_s { etype_t type; ///< always ev_func pr_ptr_t return_type; ///< return type of the function @@ -106,6 +112,7 @@ typedef struct qfot_type_s { pr_string_t encoding; ///< Objective-QC encoding union { etype_t type; ///< ty_basic: etype_t + qfot_basic_t basic; ///< ty_basic: int/float/double/long etc qfot_fldptr_t fldptr; ///< ty_basic, ev_ptr/ev_field qfot_func_t func; ///< ty_basic, ev_func qfot_struct_t strct; ///< ty_struct/ty_union/ty_enum diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 3f1b412cd..c0ade919b 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -513,6 +513,12 @@ static const char *ty_meta_names[] = { "ty_alias", }; #define NUM_META ((int)(sizeof (ty_meta_names) / sizeof (ty_meta_names[0]))) +const int vector_types = (1 << ev_float) + | (1 << ev_int) + | (1 << ev_uint) + | (1 << ev_double) + | (1 << ev_long) + | (1 << ev_ulong); static void dump_qfo_types (qfo_t *qfo, int base_address) @@ -563,6 +569,9 @@ dump_qfo_types (qfo_t *qfo, int base_address) } else if (type->type == ev_ptr || type->type == ev_field) { printf (" %4x", type->fldptr.aux_type); + } else if ((1 << type->type) & vector_types + && type->basic.width > 1) { + printf ("[%d]", type->basic.width); } printf ("\n"); break; diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index 8d1f5cacf..c00f2f43e 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -152,9 +152,10 @@ qfo_encode_basic (type_t *type, defspace_t *space) else if (type->type == ev_ptr || type->type == ev_field) return qfo_encode_fldptr (type, space); - def = qfo_new_encoding (type, sizeof (enc->type), space); + def = qfo_new_encoding (type, sizeof (enc->basic), space); enc = D_POINTER (qfot_type_t, def); - enc->type = type->type; + enc->basic.type = type->type; + enc->basic.width = type->width; return def; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 94bf6aed0..7e73fc99d 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -829,10 +829,18 @@ encode_type (dstring_t *encoding, const type_t *type) dasprintf (encoding, "*"); return; case ev_double: - dasprintf (encoding, "d"); + if (type->width > 1) { + dasprintf (encoding, "d%d", type->width); + } else { + dasprintf (encoding, "d"); + } return; case ev_float: - dasprintf (encoding, "f"); + if (type->width > 1) { + dasprintf (encoding, "f%d", type->width); + } else { + dasprintf (encoding, "f"); + } return; case ev_vector: dasprintf (encoding, "V"); @@ -870,16 +878,32 @@ encode_type (dstring_t *encoding, const type_t *type) dasprintf (encoding, "Q"); return; case ev_int: - dasprintf (encoding, "i"); + if (type->width > 1) { + dasprintf (encoding, "i%d", type->width); + } else { + dasprintf (encoding, "i"); + } return; case ev_uint: - dasprintf (encoding, "I"); + if (type->width > 1) { + dasprintf (encoding, "I%d", type->width); + } else { + dasprintf (encoding, "I"); + } return; case ev_long: - dasprintf (encoding, "l"); + if (type->width > 1) { + dasprintf (encoding, "l%d", type->width); + } else { + dasprintf (encoding, "l"); + } return; case ev_ulong: - dasprintf (encoding, "L"); + if (type->width > 1) { + dasprintf (encoding, "L%d", type->width); + } else { + dasprintf (encoding, "L"); + } return; case ev_short: dasprintf (encoding, "s"); From b8df11b2cbedab8499e47f44c3922820456a531f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 20:01:32 +0900 Subject: [PATCH 2348/3664] [qfcc] Really get vecaddr.r working on both ISAs Deliberately defeating an optimiser is not so easy (but I really needed that variable to be set). --- tools/qfcc/test/vecaddr.r | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/test/vecaddr.r b/tools/qfcc/test/vecaddr.r index 6bd407d9b..965fbf716 100644 --- a/tools/qfcc/test/vecaddr.r +++ b/tools/qfcc/test/vecaddr.r @@ -17,7 +17,8 @@ float foo (vector _v, float _z) vector v = _v; float z = _z; _v = nil; - _z = _z - _z; + _z = 0; + forcelive (_z); forcelive (z); return (v dot *(vector*)(&v.y))X; } From 766bf758ab557daeaf5a5d51c7bee2d01bcda64d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 22:34:40 +0900 Subject: [PATCH 2349/3664] [gamecode] Redesign jump's B addressing Yet another redundant addressing mode (since ptr + 0 can be used), so replace it with a variable-indexed array (same as in v6p). Was forced into noticing the problem when trying to compile Machine.r. --- libs/gamecode/opcodes.py | 4 ++-- libs/gamecode/pr_exec.c | 4 ++-- libs/gamecode/test/test-jump.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 61e65f136..a07714d88 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -204,11 +204,11 @@ jump_formats = { "jump_fmt": branch_fmt, "jump_types": [ "ev_short, ev_invalid, ev_invalid", - "ev_ptr, ev_invalid, ev_invalid", + "ev_void, ev_int, ev_invalid", "ev_ptr, ev_short, ev_invalid", "ev_ptr, ev_int, ev_invalid", ], - "jump_widths": [ "0, 0", "1, 0", "1, 0", "1, 1" ] + "jump_widths": [ "0, 0", "1, 1", "1, 0", "1, 1" ] }, } lea_formats = { diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 9801d9936..15c63d0a4 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1867,8 +1867,8 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind) jump_offs = jump_offs + (short) st->a; break; case 1: - // simple pointer dereference: *a - jump_offs = OPA(ptr); + // variable indexed array: a + *b (only +ve) + jump_offs = (op_a + OPB(uint))->uint_var; break; case 2: // constant indexed pointer: *a + b (supports -ve offset) diff --git a/libs/gamecode/test/test-jump.c b/libs/gamecode/test/test-jump.c index 59e40554d..d05d6b92b 100644 --- a/libs/gamecode/test/test-jump.c +++ b/libs/gamecode/test/test-jump.c @@ -19,7 +19,7 @@ static dstatement_t jump_A_statements[] = { }; static dstatement_t jump_B_statements[] = { - { OP(0, 0, 0, OP_JUMP_B), 3, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_B), 1, 2, 0 }, { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, { OP(0, 0, 0, OP_LEA_A), 1, 0, 0 }, { OP(0, 0, 0, OP_LEA_A), 1, 0, 4 }, From 7971bcd91c9cadb752e03c09436e9f76e9db9605 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 22:37:03 +0900 Subject: [PATCH 2350/3664] [gamecode] Sort out shr's opname for easier searching Since the operand types sort out the difference between asr and shr, no need to give them different opnames. Means qfcc doesn't need to worry about which one it's searching for. --- libs/gamecode/opcodes.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index a07714d88..7c0758a64 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -361,13 +361,14 @@ scale_formats = { }, } shiftops_formats = { - "opcode": "OP_{op_shift[u*2+r].upper()}_{shift_type[u*2+t]}_{ss+1}", - "mnemonic": "{op_shift[u*2+r]}.{shift_type[u*2+t]}", + "opcode": "OP_{mn_shift[u*2+r].upper()}_{shift_type[u*2+t]}_{ss+1}", + "mnemonic": "{mn_shift[u*2+r]}.{shift_type[u*2+t]}", "opname": "{op_shift[u*2+r]}", "widths": "{ss+1}, {ss+1}, {ss+1}", "types": "{shift_types[t][u]}, {shift_types[t][0]}, {shift_types[t][u]}", "args": { - "op_shift": ["shl", "asr", "shl", "shr"], + "mn_shift": ["shl", "asr", "shl", "shr"], + "op_shift": ["shl", "shr", "shl", "shr"], "shift_type": ['I', 'L', 'u', 'U'], "shift_types": [ ["ev_int", "ev_uint"], From 8dc4a0ea80d615a0287a88fee46f13260902dd87 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 22:39:21 +0900 Subject: [PATCH 2351/3664] [qfcc] Change v6p's jumpb opname to jump More ease of searching, since the operand types help greatly. --- libs/gamecode/pr_v6p_opcode.c | 2 +- tools/qfcc/source/statements.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index a76dfe06e..bc3848de1 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -957,7 +957,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { PROG_V6P_VERSION, "%Ga", }, - [OP_JUMPB_v6p] = {"jumpb", "jumpb", + [OP_JUMPB_v6p] = {"jump", "jump", ev_void, ev_int, ev_invalid, PROG_V6P_VERSION, "%Ga[%Gb]", diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e9b375aba..0428204d0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -625,7 +625,7 @@ statement_is_goto (statement_t *s) { if (!s) return 0; - return !strcmp (s->opcode, "jump"); + return !strcmp (s->opcode, "jump") && !s->opb; } int @@ -633,7 +633,7 @@ statement_is_jumpb (statement_t *s) { if (!s) return 0; - return !strcmp (s->opcode, "jumpb"); + return !strcmp (s->opcode, "jump") && s->opb; } int @@ -1251,7 +1251,7 @@ statement_branch (sblock_t *sblock, expr_t *e) } if (e->e.branch.type == pr_branch_jump) { if (e->e.branch.index) { - s = new_statement (st_flow, "jumpb", e); + s = new_statement (st_flow, "jump", e); sblock = statement_subexpr (sblock, e->e.branch.target, &s->opa); sblock = statement_subexpr (sblock, e->e.branch.index, &s->opb); } else { From edf7a781fd0dcadb597e9320d3fcf331d79991c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Jan 2022 22:40:37 +0900 Subject: [PATCH 2352/3664] [qfcc] Map uint to int for some intructions Many math instructions don't care about the difference between signed and unsigned operands and are thus specified using int, but need to be usable with uint. div is NOT mapped because there is a difference: 0x8000 / 2 (16-bit) is 0x4000 unsigned but 0xc000 signed, and 0x8000 / 0xfffe is 0 unsigned and 0x4000 signed. This means I'll need to add some more instructions. Not sure what to do about % and %% though as that's a lot of instructions (12). --- tools/qfcc/source/opcodes.c | 46 +++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 79cc48943..dcb6342cc 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -230,8 +230,30 @@ v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, return op; } -static etype_t -operand_type (operand_t *op) +static const char *unsigned_demote_ops[] = { + "add", + "bitand", + "bitnot", + "bitor", + "bitxor", + "eq", + "ifnz", + "ifz", + "mul", + "ne", + "sub", +}; + +static int +ud_compare (const void *_a, const void *_b) +{ + const char *a = _a; + const char *b = *(const char **)_b; + return strcmp (a, b); +} + +static etype_t __attribute__((pure)) +operand_type (const operand_t *op, const char *name) { if (!op) { return ev_invalid; @@ -240,6 +262,20 @@ operand_type (operand_t *op) if (type == ev_vector || type == ev_quaternion) { return ev_float; } + if (type == ev_uint || type == ev_ulong) { + if (bsearch (name, unsigned_demote_ops, + sizeof (unsigned_demote_ops) + / sizeof (unsigned_demote_ops[0]), + sizeof (unsigned_demote_ops[0]), + ud_compare)) { + if (type == ev_uint) { + type = ev_int; + } + if (type == ev_ulong) { + type = ev_long; + } + } + } return type; } @@ -266,9 +302,9 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, opcode_t search_op = { .opname = name, .types = { - operand_type (op_a), - operand_type (op_b), - operand_type (op_c), + operand_type (op_a, name), + operand_type (op_b, name), + operand_type (op_c, name), }, .widths = { operand_width (op_a), From c5ae1ae13c0da975b021e337267acad99734ac14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Jan 2022 14:03:36 +0900 Subject: [PATCH 2353/3664] [ruamoko] Check self is within progs memory Changes a segfault to a runtime error, which beats the risk of self pointing somewhere that doesn't segrault. --- libs/ruamoko/rua_obj.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 2fe0b85f7..3bbb974a5 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1536,6 +1536,9 @@ rua_obj_msgSend (progs_t *pr) R_INT (pr) = P_INT (pr, 0); return; } + if (P_UINT (pr, 0) >= pr->globals_size) { + PR_RunError (pr, "invalid self: %x", P_UINT (pr, 0)); + } if (!_cmd) PR_RunError (pr, "null selector"); imp = obj_msg_lookup (probj, self, _cmd); From cabb53e693b2d182be3b71e047639ff4fbce20da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Jan 2022 16:51:46 +0900 Subject: [PATCH 2354/3664] [gamecode] Skip return ptr restore if depth changed When calling a builtin, normally the return pointer needs to be restored, but if the builtin changes the call depth (usually by effecting "return foo()" as in support for objects, but possibly setjmp/longjmp when they are implemented), then the return pointer must not be restored. This gets vkgen past object allocation, but it dies when trying to send messages to super. This appears to be a compiler bug. --- libs/gamecode/pr_exec.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 15c63d0a4..cd493bea8 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -452,9 +452,12 @@ PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr) PR_GetString (pr, f->descriptor->name), f->func); } pr_type_t *saved_return = pr->pr_return; + int builtin_depth = pr->pr_depth; pr->pr_return = return_ptr; f->func (pr); - pr->pr_return = saved_return; + if (builtin_depth == pr->pr_depth) { + pr->pr_return = saved_return; + } return 0; } else { PR_EnterFunction (pr, f); From 92711e778ce87c73864c7a083eb0a13ce093efab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Jan 2022 19:04:18 +0900 Subject: [PATCH 2355/3664] [ruamoko] Set params in obj_msgSend_super only for v6p progs In Ruamoko ISA progs, the param pointers point to the stack and generally must most be manipulated by builtins, and there is no need anyway as Ruamoko doesn't have RCALL. Fixes the mangling of .super. --- libs/ruamoko/rua_obj.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 3bbb974a5..971ba55b8 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1565,7 +1565,9 @@ rua_obj_msgSend_super (progs_t *pr) PR_GetString (pr, object_get_class_name (probj, self)), PR_GetString (pr, probj->selector_names[_cmd->sel_id])); } - pr->pr_params[0] = pr->pr_real_params[0]; + if (pr->progs->version < PROG_VERSION) { + pr->pr_params[0] = pr->pr_real_params[0]; + } P_POINTER (pr, 0) = super->self; PR_CallFunction (pr, imp, pr->pr_return); } From 712d800491566c880b6b565dfb40d36fbefc2365 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Jan 2022 23:32:38 +0900 Subject: [PATCH 2356/3664] [gamecode] Save return ptr for chained calls It turns out the return pointer still needs to be saved even when a builtin sets up a chain call to progs, but rather than the pointer being simply restored, it needs to be saved in the call stack exactly as if the function was called directly by progs. This fixes the invalid self issue quite thoroughly: parameter state seems to be correct across all calls now. I should set up an automated test now that I know and understand the situation. --- libs/gamecode/pr_exec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index cd493bea8..200e0c0d8 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -457,6 +457,8 @@ PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr) f->func (pr); if (builtin_depth == pr->pr_depth) { pr->pr_return = saved_return; + } else if (builtin_depth < pr->pr_depth) { + pr->pr_stack[builtin_depth].return_ptr = saved_return; } return 0; } else { From 98215b46ad3cbf9074b669776bf438d3ecc61f89 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Jan 2022 23:37:03 +0900 Subject: [PATCH 2357/3664] [ruamoko] Cast autoreleaseIMP to avoid ... The ABI for the Ruamoko ISA set currently puts va_list into the parameter stream whenever a varargs function is called. Unfortunately, IMP is declared with ... and thus cannot be used directly unless all methods become varargs, but I think that would cause even more headaches. --- ruamoko/lib/Object.r | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index bccea1de4..03a1519ad 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -77,10 +77,12 @@ BOOL (id object) object_is_meta_class = #0; @end +typedef void arIMP(id, SEL, id); + @static BOOL allocDebug; @static Class autoreleaseClass; @static SEL autoreleaseSelector; -@static IMP autoreleaseIMP; +@static arIMP autoreleaseIMP; @implementation Object @@ -89,7 +91,7 @@ BOOL (id object) object_is_meta_class = #0; //allocDebug = localinfo ("AllocDebug"); autoreleaseClass = [AutoreleasePool class]; autoreleaseSelector = @selector(addObject:); - autoreleaseIMP = [autoreleaseClass methodForSelector: autoreleaseSelector]; + autoreleaseIMP = (arIMP)[autoreleaseClass methodForSelector: autoreleaseSelector]; return; } From e3f88b2b9c7a5178fda413e5278271387a773e5a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Jan 2022 23:40:21 +0900 Subject: [PATCH 2358/3664] [qwaq] Align progs memory to 64 bytes It doesn't do much good for dynamic progs memory because zone currently aligns to 8 bytes (oops, forgot to fix that), but at least the stack and globals are properly aligned. --- ruamoko/qwaq/builtins/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 0215ced3f..7d34e1785 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -119,7 +119,7 @@ load_file (progs_t *pr, const char *name, off_t *_size) static void * allocate_progs_mem (progs_t *pr, int size) { - return malloc (size); + return aligned_alloc (64, size); } static void From 175cc408d8ae28e4865bd6805dbc60fbb9b43bb3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Jan 2022 23:44:09 +0900 Subject: [PATCH 2359/3664] [qwaq] Update bi_printf to work with Ruamoko's va_list Same deal as for test_bi in qfcc's test harness. I really need to consolidate all these little functions. --- ruamoko/qwaq/builtins/main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 7d34e1785..670515fc0 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -152,6 +152,19 @@ bi_printf (progs_t *pr) pr_type_t **args = pr->pr_params + 1; dstring_t *dstr = dstring_new (); + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); + count = va_list->count; + if (count) { + args = alloca (count * sizeof (pr_type_t *)); + for (int i = 0; i < count; i++) { + args[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + args = 0; + } + } + PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); if (dstr->str) { Sys_Printf ("%s", dstr->str); From e7ac6376876591b361151d069a98abb1b258977d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Jan 2022 23:45:29 +0900 Subject: [PATCH 2360/3664] [ruamoko] Wrap hash table callbacks with push/pop frame Builtins that call progs with parameters now must always wrap the call to PR_ExecuteProgram so that the data stack is properly preserved across the call. I need to do an audit of all the calls to PR_ExecuteProgram. --- libs/ruamoko/rua_hash.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index c2cf1f8f7..c4939e1e7 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -95,48 +95,59 @@ static const char * bi_get_key (const void *key, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_PushFrame (ht->pr); PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key); P_INT (ht->pr, 1) = ht->ud; ht->pr->pr_argc = 2; PR_ExecuteProgram (ht->pr, ht->gk); - return PR_GetString (ht->pr, R_STRING (ht->pr)); + pr_string_t string = R_STRING (ht->pr); + PR_PopFrame (ht->pr); + return PR_GetString (ht->pr, string); } static uintptr_t bi_get_hash (const void *key, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_PushFrame (ht->pr); PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key); P_INT (ht->pr, 1) = ht->ud; ht->pr->pr_argc = 2; PR_ExecuteProgram (ht->pr, ht->gh); - return R_INT (ht->pr); + int hash = R_INT (ht->pr); + PR_PopFrame (ht->pr); + return hash; } static int bi_compare (const void *key1, const void *key2, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_PushFrame (ht->pr); PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key1); P_INT (ht->pr, 1) = (intptr_t) (key2); P_INT (ht->pr, 2) = ht->ud; ht->pr->pr_argc = 3; PR_ExecuteProgram (ht->pr, ht->cmp); - return R_INT (ht->pr); + int cmp = R_INT (ht->pr); + PR_PopFrame (ht->pr); + return cmp; } static void bi_free (void *key, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_PushFrame (ht->pr); PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (intptr_t) (key); P_INT (ht->pr, 1) = ht->ud; ht->pr->pr_argc = 2; PR_ExecuteProgram (ht->pr, ht->f); + PR_PopFrame (ht->pr); } static void From 5d41e90cc708efe2d899aacafc863a04c20876dc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Jan 2022 23:47:47 +0900 Subject: [PATCH 2361/3664] [gamecode] Remove pushregs and popregs specs They have been redundant since the operations were moved into with. --- libs/gamecode/opcodes.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 7c0758a64..61ad591ab 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -320,14 +320,6 @@ push_formats = { "push_types": address_types, }, } -pushregs_formats = { - "opcode": "OP_PUSHREGS", - "mnemonic": "pushregs", - "opname": "pushregs", - "widths": "0, 0, 0", - "types": "ev_invalid, ev_invalid, ev_invalid", - "format": None, -} pop_formats = { "opcode": "OP_POP_{op_mode[mm]}_{ss+1}", "mnemonic": "pop", @@ -341,14 +333,6 @@ pop_formats = { "pop_types": address_types, }, } -popregs_formats = { - "opcode": "OP_POPREGS", - "mnemonic": "popregs", - "opname": "popregs", - "widths": "0, 0, 0", - "format": None, - "types": "ev_invalid, ev_invalid, ev_invalid", -} scale_formats = { "opcode": "OP_SCALE_{scale_type[t]}_{ss+1}", "mnemonic": "scale.{scale_type[t]}", @@ -530,9 +514,7 @@ group_map = { "move": move_formats, "noop": noop_formats, "push": push_formats, - "pushregs": pushregs_formats, "pop": pop_formats, - "popregs": popregs_formats, "scale": scale_formats, "shiftops": shiftops_formats, "statef": statef_formats, From b8c2b7f8565ca4a5c99a295d8fec3f981c07fde5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 09:24:02 +0900 Subject: [PATCH 2362/3664] [ruamoko] Make a common sprintf wrapper function This takes care of converting from progs varargs to what PR_Sprintf expects. I got tired of modifying the wrappers when I found a third one. --- include/rua_internal.h | 5 +++++ libs/ruamoko/rua_string.c | 26 +++++++++++++++++++++++--- ruamoko/qwaq/builtins/main.c | 19 ++----------------- tools/qfcc/test/test-bi.c | 26 +++++++------------------- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/include/rua_internal.h b/include/rua_internal.h index 24e16cc6e..a41177bae 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -33,6 +33,9 @@ #include "QF/quakeio.h" +struct progs_s; +struct dstring_s; + void RUA_Cbuf_Init (struct progs_s *pr, int secure); void RUA_Cmd_Init (struct progs_s *pr, int secure); void RUA_Cvar_Init (struct progs_s *pr, int secure); @@ -49,6 +52,8 @@ void RUA_String_Init (struct progs_s *pr, int secure); void RUA_QFile_Init (struct progs_s *pr, int secure); void RUA_QFS_Init (struct progs_s *pr, int secure); +void RUA_Sprintf (struct progs_s *pr, struct dstring_s *dstr); + int QFile_AllocHandle (struct progs_s *pr, QFile *file); QFile *QFile_GetFile (struct progs_s *pr, int handle); struct plitem_s *Plist_GetItem (struct progs_s *pr, int handle); diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index e01ab9716..4fdbab706 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -60,16 +60,36 @@ bi_strlen (progs_t *pr) R_INT (pr) = strlen(s); } -static void -bi_sprintf (progs_t *pr) +void +RUA_Sprintf (progs_t *pr, dstring_t *dstr) { const char *fmt = P_GSTRING (pr, 0); int count = pr->pr_argc - 1; pr_type_t **args = pr->pr_params + 1; + + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); + count = va_list->count; + if (count) { + args = alloca (count * sizeof (pr_type_t *)); + for (int i = 0; i < count; i++) { + args[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + args = 0; + } + } + + PR_Sprintf (pr, dstr, "bi_sprintf", fmt, count, args); +} + +static void +bi_sprintf (progs_t *pr) +{ dstring_t *dstr; dstr = dstring_newstr (); - PR_Sprintf (pr, dstr, "bi_sprintf", fmt, count, args); + RUA_Sprintf (pr, dstr); RETURN_STRING (pr, dstr->str); dstring_delete (dstr); } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 670515fc0..8e9449d40 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -53,6 +53,7 @@ #include "QF/zone.h" #include "compat.h" +#include "rua_internal.h" #include "ruamoko/qwaq/qwaq.h" #include "ruamoko/qwaq/debugger/debug.h" @@ -147,25 +148,9 @@ init_qf (void) static void bi_printf (progs_t *pr) { - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; dstring_t *dstr = dstring_new (); - if (pr->progs->version == PROG_VERSION) { - __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); - count = va_list->count; - if (count) { - args = alloca (count * sizeof (pr_type_t *)); - for (int i = 0; i < count; i++) { - args[i] = &pr->pr_globals[va_list->list + i * 4]; - } - } else { - args = 0; - } - } - - PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); + RUA_Sprintf (pr, dstr); if (dstr->str) { Sys_Printf ("%s", dstr->str); } diff --git a/tools/qfcc/test/test-bi.c b/tools/qfcc/test/test-bi.c index 412a341bf..e12220f8f 100644 --- a/tools/qfcc/test/test-bi.c +++ b/tools/qfcc/test/test-bi.c @@ -40,37 +40,25 @@ #include "QF/dstring.h" #include "QF/progs.h" +#include "rua_internal.h" #include "test-bi.h" static void bi_printf (progs_t *pr) { - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; static dstring_t *dstr; - if (!dstr) + if (!dstr) { dstr = dstring_new (); - else + } else { dstring_clear (dstr); - - if (pr->progs->version == PROG_VERSION) { - __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); - count = va_list->count; - if (count) { - args = alloca (count * sizeof (pr_type_t *)); - for (int i = 0; i < count; i++) { - args[i] = &pr->pr_globals[va_list->list + i * 4]; - } - } else { - args = 0; - } } - PR_Sprintf (pr, dstr, "bi_printf", fmt, count, args); - if (dstr->str) + RUA_Sprintf (pr, dstr); + + if (dstr->str) { fputs (dstr->str, stdout); + } } static void From 2fcec6e5cb693200b2ef6f1157c6589dfbcc3f4b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 11:56:45 +0900 Subject: [PATCH 2363/3664] [zone] Move heap check to Z_TagMalloc Since Z_Malloc uses Z_TagMalloc to do the work, this ensures the check is always run. Also, add the check to Z_Realloc when it needs to adjust an existing block. --- libs/util/zone.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index 88b3e7ecd..ce02fa76c 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -202,8 +202,6 @@ Z_Malloc (memzone_t *zone, size_t size) { void *buf; - if (!developer || developer->int_val & SYS_dev) - Z_CheckHeap (zone); // DEBUG buf = Z_TagMalloc (zone, size, 1); if (!buf) { const char *msg; @@ -224,6 +222,9 @@ Z_TagMalloc (memzone_t *zone, size_t size, int tag) int requested_size = size; memblock_t *start, *rover, *new, *base; + if (!developer || developer->int_val & SYS_dev) + Z_CheckHeap (zone); // DEBUG + if (!tag) { if (zone->error) zone->error (zone->data, "Z_TagMalloc: tried to use a 0 tag"); @@ -290,6 +291,9 @@ Z_Realloc (memzone_t *zone, void *ptr, size_t size) if (!ptr) return Z_Malloc (zone, size); + if (!developer || developer->int_val & SYS_dev) + Z_CheckHeap (zone); // DEBUG + block = (memblock_t *) ((byte *) ptr - sizeof (memblock_t)); if (block->id != ZONEID/* || block->id2 != ZONEID*/) { if (zone->error) From bea1155e9e551e7d5797b844b1122006c054bdd4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 12:24:46 +0900 Subject: [PATCH 2364/3664] [qwaq] Give qwaq progs a stack of 64kB 16kW should be enough as a default (when I get around to making it configurable). Stops vkgen from trashing its heap with the stack. --- ruamoko/qwaq/builtins/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 8e9449d40..59080dd17 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -227,6 +227,7 @@ load_progs (progs_t *pr, const char *name) pr->progs_name = name; pr->max_edicts = 1; pr->zone_size = 1024*1024; + pr->stack_size = 64*1024; PR_LoadProgsFile (pr, file, size); Qclose (file); if (!PR_RunLoadFuncs (pr)) From f714b6fbea441f94af304153c64aafeedeb5bc32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 12:45:18 +0900 Subject: [PATCH 2365/3664] [qwaq] Up qwaq progs heap to 2MB or 512kW (kilowatts? :P). Barely enough for vkgen to run (it runs out if auto release is run during scan_types, probably due to fragmentation). I imagine I need to look into better memory management schemes, especially since I want to make zone allocations 64-byte aligned (instead of the current 8). And it doesn't help that 16 words per allocation are dedicated to the zone management. Anyway, with this, vgken runs and produces sufficiently correct results for the rest of QF to build, so long as qfcc is not optimizing. --- ruamoko/qwaq/builtins/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 59080dd17..3a0561035 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -226,7 +226,7 @@ load_progs (progs_t *pr, const char *name) } pr->progs_name = name; pr->max_edicts = 1; - pr->zone_size = 1024*1024; + pr->zone_size = 2*1024*1024; pr->stack_size = 64*1024; PR_LoadProgsFile (pr, file, size); Qclose (file); From 64c8c02eacfee5f90804464a786ffc7bedbeb3d2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 13:24:27 +0900 Subject: [PATCH 2366/3664] [qfcc] Add pragma to control optimization And force a couple of tests to be built with optimization. I'll probably add it to most, if not all, but for now I'm clearing up tests as I go. --- tools/qfcc/source/pragma.c | 20 ++++++++++++++++++++ tools/qfcc/test/dealloc-warn3.r | 1 + tools/qfcc/test/return-postop.r | 1 + 3 files changed, 22 insertions(+) diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index 9e3a393aa..fb72130f4 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -125,6 +125,24 @@ set_warn (pragma_arg_t *args) } } +static void +set_optimize (pragma_arg_t *args) +{ + if (!args) { + warning (0, "missing warn flag"); + return; + } + const char *flag = args->arg; + if (!strcmp (flag, "on") || !strcmp (flag, "!off")) { + options.code.optimize = true; + } else if (!strcmp (flag, "!on") || !strcmp (flag, "off")) { + options.code.optimize = false; + } + if (args->next) { + warning (0, "pragma optimize: ignoring extra arguments"); + } +} + void pragma_process () { @@ -143,6 +161,8 @@ pragma_process () set_bug (pragma_args->next); } else if (!strcmp (id, "warn")) { set_warn (pragma_args->next); + } else if (!strcmp (id, "optimize")) { + set_optimize (pragma_args->next); } else { warning (0, "unknown pragma: '%s'", id); } diff --git a/tools/qfcc/test/dealloc-warn3.r b/tools/qfcc/test/dealloc-warn3.r index 32427e2ff..a8dd2d2b4 100644 --- a/tools/qfcc/test/dealloc-warn3.r +++ b/tools/qfcc/test/dealloc-warn3.r @@ -1,4 +1,5 @@ #pragma warn error +#pragma optimize on @interface Object { diff --git a/tools/qfcc/test/return-postop.r b/tools/qfcc/test/return-postop.r index 5ec27f4a1..bdf244f98 100644 --- a/tools/qfcc/test/return-postop.r +++ b/tools/qfcc/test/return-postop.r @@ -1,3 +1,4 @@ +#pragma optimize on #include "test-harness.h" int counter; From e0c5c475ea257278380923a88a506373969d06ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 13:26:01 +0900 Subject: [PATCH 2367/3664] [qfcc] Modify the modulo tests to be compatible with Ruamoko ISA Surprisingly, it passes (I didn't expect it to due to the doubles). I'll look into to it further later on. --- tools/qfcc/test/modulo.r | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/test/modulo.r b/tools/qfcc/test/modulo.r index 2d31a69a2..6fb69490c 100644 --- a/tools/qfcc/test/modulo.r +++ b/tools/qfcc/test/modulo.r @@ -1,3 +1,7 @@ +#if !defined(__RUAMOKO__) || __RUAMOKO__ < 2 +# define test_traditional +#endif + void printf (string ftm, ...) = #0; float snafu (float a, float b) @@ -21,6 +25,7 @@ double dmodulo (double a, double b) return a %% b; } +#ifdef test_traditional #pragma traditional float foo (float a, float b) { @@ -45,6 +50,7 @@ float baz (float a, float b) return c; } #pragma advanced +#endif @overload int test (string name, string op, int (func)(int a, int b), int a, int b, int c) @@ -53,10 +59,12 @@ test (string name, string op, int (func)(int a, int b), int a, int b, int c) ret = func (a, b); if (ret != c) { +#ifdef test_traditional if (func == baz) printf ("%s: (%d + %d) %% (%d - %d): %d != %d\n", name, a, b, a, b, ret, c); else +#endif printf ("%s: %d %s %d: %d != %d\n", name, a, op, b, ret, c); return 1; @@ -72,10 +80,12 @@ test (string name, string op, float (func)(float a, float b), ret = func (a, b); if (ret != c) { +#ifdef test_traditional if (func == baz) printf ("%s: (%g + %g) %% (%g - %g): %g != %g\n", name, a, b, a, b, ret, c); else +#endif printf ("%s: %g %s %g: %g != %g\n", name, a, op, b, ret, c); return 1; @@ -91,42 +101,55 @@ test (string name, string op, double (func)(double a, double b), ret = func (a, b); if (ret != c) { +#ifdef test_traditional if (func == baz) printf ("%s: (%g + %g) %% (%g - %g): %g != %g\n", name, a, b, a, b, ret, c); else +#endif printf ("%s: %g %s %g: %g != %g\n", name, a, op, b, ret, c); return 1; } return 0; } +#ifdef test_traditional +typedef float restype; +#else +typedef int restype; +#endif -float main (void) +restype main (void) { - float res = 0; + restype res = 0; +#ifdef test_traditional res |= test ("foo", "%", foo, 5, 3, 2); res |= test ("bar", "%", bar, 5, 3, 2); res |= test ("baz", "%", baz, 5, 3, 0); +#endif res |= test ("snafu", "%", snafu, 5, 3, 2); - +#ifdef test_traditional res |= test ("foo", "%", foo, -5, 3, -2); res |= test ("bar", "%", bar, -5, 3, -2); res |= test ("baz", "%", baz, -5, 3, -2); +#endif res |= test ("snafu", "%", snafu, -5, 3, -2); - +#ifdef test_traditional res |= test ("foo", "%", foo, 5, -3, 2); res |= test ("bar", "%", bar, 5, -3, 2); res |= test ("baz", "%", baz, 5, -3, 2); +#endif res |= test ("snafu", "%", snafu, 5, -3, 2); - +#ifdef test_traditional res |= test ("foo", "%", foo, -5, -3, -2); res |= test ("bar", "%", bar, -5, -3, -2); res |= test ("baz", "%", baz, -5, -3, 0); +#endif res |= test ("snafu", "%", snafu, -5, -3, -2); - +#ifdef test_traditional res |= test ("foo", "%", foo, 5, 3.5, 1.5); res |= test ("foo", "%", foo, -5, 3.5, -1.5); +#endif res |= test ("snafu", "%", snafu, 5, 3.5, 1.5); res |= test ("snafu", "%", snafu, -5, 3.5, -1.5); From fc56d1c6e29326f0b811ff12256cfe6d041567c3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 14:54:22 +0900 Subject: [PATCH 2368/3664] [qfcc] Use dynamic addressing for Ruamoko move source This fixes the incorrect pointer being used in movep instructions in Ruamoko progs, as well as 3 of the test cases. --- tools/qfcc/source/statements.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 0428204d0..3f60f15fa 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -808,6 +808,8 @@ is_indirect (expr_t *e) static sblock_t *addressing_mode (sblock_t *sblock, expr_t *ref, operand_t **base, operand_t **offset, pr_ushort_t *mode); +static statement_t *lea_statement (operand_t *pointer, operand_t *offset, + expr_t *e); static sblock_t * expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) @@ -870,7 +872,13 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) // shouldn't emit code... sblock = statement_subexpr (sblock, src_expr, &use); } - src = operand_address (src, src_expr); + if (options.code.progsversion == PROG_VERSION) { + s = lea_statement (src, 0, src_expr); + sblock_add_statement (sblock, s); + src = s->opc; + } else { + src = operand_address (src, src_expr); + } need_ptr = 1; } } From c84fb3e6d360ad92f99b0ede6c8740adda45bf62 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 16:08:58 +0900 Subject: [PATCH 2369/3664] [qfcc] Use a hidden local variable for pascal functions This gets gcd.pas working nicely with the Ruamoko ISA, and keeps things reasonably nice vor v6p (it will likely do better with global CSE). --- tools/qfcc/source/qp-parse.y | 45 ++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/qp-parse.y b/tools/qfcc/source/qp-parse.y index 550f8e3f8..8a809bacb 100644 --- a/tools/qfcc/source/qp-parse.y +++ b/tools/qfcc/source/qp-parse.y @@ -164,6 +164,32 @@ build_dotmain (symbol_t *program) build_code_function (dotmain, 0, code); } +static symbol_t * +function_value (function_t *func) +{ + symbol_t *ret = 0; + if (func->type->t.func.type) { + ret = symtab_lookup (func->locals, ".ret"); + if (!ret || ret->table != func->locals) { + ret = new_symbol_type (".ret", func->type->t.func.type); + initialize_def (ret, 0, func->locals->space, sc_local, + func->locals); + } + } + return ret; +} + +static expr_t * +function_return (function_t *func) +{ + symbol_t *ret = function_value (func); + expr_t *ret_val = 0; + if (ret) { + ret_val = new_symbol_expr (ret); + } + return ret_val; +} + %} %% @@ -270,10 +296,11 @@ subprogram_declaration current_storage); current_symtab = current_func->locals; current_storage = sc_local; + function_value (current_func); } declarations compound_statement ';' { - append_expr ($5, new_return_expr (0)); + append_expr ($5, new_return_expr (function_return (current_func))); build_code_function ($1, 0, $5); current_symtab = current_func->parameters->parent; current_storage = $3; @@ -376,8 +403,18 @@ statement : variable ASSIGNOP expression { $$ = $1; - if ($$->type == ex_symbol && extract_type ($$) == ev_func) - $$ = new_ret_expr ($$->e.symbol->type->t.func.type); + if ($$->type == ex_symbol && $$->e.symbol->sy_type == sy_func) { + if ($$->e.symbol->s.func != current_func) { + $$ = error ($$, "cannot assign to other function"); + } else { + symbol_t *ret = function_value (current_func); + if (!ret) { + $$ = error ($$, "cannot assign to procedure"); + } else { + $$ = new_symbol_expr (ret); + } + } + } $$ = assign_expr ($$, $3); } | procedure_statement @@ -398,7 +435,7 @@ statement } | RETURN { - $$ = return_expr (current_func, 0); + $$ = return_expr (current_func, function_return (current_func)); } ; From 6514e09e7cfbffff5e9485ebe80d009d165677e0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 16:43:29 +0900 Subject: [PATCH 2370/3664] [gamecode] Use an explicit size for the null page It's currently only 4 (or even 3 for v6) words, but this fixes false positives when checking for null pointers in Ruamoko progs due to pr_return pointing to the return buffer and thus outside the progs memory map resulting in an impossible to exceed value. --- include/QF/progs.h | 3 ++- libs/gamecode/pr_exec.c | 2 +- libs/gamecode/pr_resolve.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 769fdb533..5a00afd46 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1942,7 +1942,8 @@ struct progs_s { pr_def_t *pr_fielddefs; dstatement_t *pr_statements; pr_type_t *pr_globals; - unsigned globals_size; + pr_uint_t globals_size; + pr_uint_t null_size; ///< size of block considered null page pr_uivec4_t pr_bases; ///< base registers (index in opcode) ///@} diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 200e0c0d8..89890908f 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -351,7 +351,7 @@ PR_LeaveFunction (progs_t *pr, int to_engine) VISIBLE void PR_BoundsCheckSize (progs_t *pr, pr_ptr_t addr, unsigned size) { - if (addr < (pr_ptr_t) (pr->pr_return - pr->pr_globals)) + if (addr < pr->null_size) PR_RunError (pr, "null pointer access"); if (addr >= pr->globals_size || size > (unsigned) (pr->globals_size - addr)) diff --git a/libs/gamecode/pr_resolve.c b/libs/gamecode/pr_resolve.c index 864baa443..008c1abed 100644 --- a/libs/gamecode/pr_resolve.c +++ b/libs/gamecode/pr_resolve.c @@ -142,6 +142,7 @@ PR_ResolveGlobals (progs_t *pr) goto error; pr->pr_param_alignment = G_INT (pr, def->ofs); } + pr->null_size = pr->pr_return - pr->pr_globals; memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params)); if (!pr->globals.ftime) {//FIXME double time if ((def = PR_FindGlobal (pr, "time"))) From 4ec3486a4b8ee049ae1a756da2ad7463bf271056 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 20:01:13 +0900 Subject: [PATCH 2371/3664] [qfcc] Make lea generate a pointer operand I really need to come up with a better way to get the result type into the flow analyser. However, this fixes the aliasing ICE when optimizing Ruamoko code that uses struct assignment. --- tools/qfcc/source/statements.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 3f60f15fa..bfa782205 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -873,6 +873,13 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) sblock = statement_subexpr (sblock, src_expr, &use); } if (options.code.progsversion == PROG_VERSION) { + // FIXME it was probably a mistake extracting the operand + // type from the statement expression in dags. Also, can't + // use address_expr() because src_expr may be a function call + // and unary_expr doesn't like that + src_expr = expr_file_line ( + new_address_expr (get_type (src_expr), src_expr, 0), + src_expr); s = lea_statement (src, 0, src_expr); sblock_add_statement (sblock, s); src = s->opc; From 9b81d27f1a1ff3af92c911250f5187934f1f097f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 21:40:59 +0900 Subject: [PATCH 2372/3664] [qfcc] Add test for var = func(var) That is, updating a variable using a function that takes the same variable, probably very common in iterators, thus the name. It happens to be the first qfcc test specific to Ruamoko. It's really just the typedef, zerolinker, and vkgen type encoding loop stripped down for ease of debugging. Of course, it fails :) --- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/iterfunc.r | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tools/qfcc/test/iterfunc.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index eaa3d673c..c82d750c4 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -30,6 +30,7 @@ test_progs_dat=\ tools/qfcc/test/func-static.dat \ tools/qfcc/test/gcd.dat \ tools/qfcc/test/infloop.dat \ + tools/qfcc/test/iterfunc.dat \ tools/qfcc/test/ivar-struct-return.dat \ tools/qfcc/test/link_order.dat \ tools/qfcc/test/lost-use.dat \ @@ -379,6 +380,16 @@ tools/qfcc/test/infloop.run: $(qfcc_test_run_deps) include $(infloop_dep) # am--include-marker r_depfiles_remade += $(infloop_dep) +tools_qfcc_test_iterfunc_dat_SOURCES=tools/qfcc/test/iterfunc.r +iterfunc_obj=$(tools_qfcc_test_iterfunc_dat_SOURCES:.r=.o) +iterfunc_dep=$(call qcautodep,$(tools_qfcc_test_iterfunc_dat_SOURCES)) +tools/qfcc/test/iterfunc.dat$(EXEEXT): $(iterfunc_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(iterfunc_obj) +tools/qfcc/test/iterfunc.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(iterfunc_dep) # am--include-marker +r_depfiles_remade += $(iterfunc_dep) + tools_qfcc_test_ivar_struct_return_dat_SOURCES=tools/qfcc/test/ivar-struct-return.r ivar_struct_return_obj=$(tools_qfcc_test_ivar_struct_return_dat_SOURCES:.r=.o) ivar_struct_return_dep=$(call qcautodep,$(tools_qfcc_test_ivar_struct_return_dat_SOURCES)) diff --git a/tools/qfcc/test/iterfunc.r b/tools/qfcc/test/iterfunc.r new file mode 100644 index 000000000..803b6a6f6 --- /dev/null +++ b/tools/qfcc/test/iterfunc.r @@ -0,0 +1,33 @@ +#include + +// can't link against libr.a (may not be built) +void *PR_FindGlobal (string name) = #0; +void printf (string fmt, ...) = #0; + +qfot_type_encodings_t *encodings; +qfot_type_t *next_type (qfot_type_t *type); + +int +main (void) +{ + int found_param = 0; + int found_zero = 0; + qfot_type_t *type; + + encodings = PR_FindGlobal (".type_encodings"); + + for (type = encodings.types; + ((int *)type - (int *) encodings.types) < encodings.size; + type = next_type (type)) { + } + return 0; +} + +qfot_type_t * +next_type (qfot_type_t *type) +{ + int size = type.size; + if (!size) + size = 4; + return (qfot_type_t *) ((int *) type + size); +} From 93840d98922db9fc838ada24fabf49d016285007 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Feb 2022 21:46:28 +0900 Subject: [PATCH 2373/3664] [qfcc] Handle Ruamoko's call return destination Since the call instruction in the Ruamoko ISA specifies the destination of the return value of the called function, it is much like any expression type instruction in that the def referenced by its c operand is both defined and killed by the instruction. However, unlike other instructions, it really has many pseudo-operands: the arguments placed on the stack. The problem is that when one of the arguments is also the destination of the return value, the dags code wants to use the stack argument as it was the last use of the real argument. Thus, instead of using the value of the child node for the result, use the value label attached to the call node (there should be only one such label). This fixes iterfunc, typedef, zerolinker and vkgen when optimizing. Now all but the double tests and return postop tests pass (and the retun postop test is not related to the Ruamoko ISA, so fails either way). --- tools/qfcc/source/dags.c | 44 +++++++++++++++++++++++++++++++++++++++- tools/qfcc/source/flow.c | 3 +++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 7a52a4f6b..e55688ff4 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -1135,6 +1135,43 @@ generate_memsetps (dag_t *dag, sblock_t *block, dagnode_t *dagnode) return dst; } +static operand_t * +generate_call (dag_t *dag, sblock_t *block, dagnode_t *dagnode) +{ + set_iter_t *var_iter; + daglabel_t *var = 0; + operand_t *operands[3] = {0, 0, 0}; + statement_t *st; + operand_t *dst; + + operands[0] = make_operand (dag, block, dagnode, 0); + if (dagnode->children[1]) { + operands[1] = make_operand (dag, block, dagnode, 1); + } + dst = operands[0]; + for (var_iter = set_first (dagnode->identifiers); var_iter; + var_iter = set_next (var_iter)) { + if (var) { + internal_error (var->expr, "more than one return value for call"); + } + var = dag->labels[var_iter->element]; + operands[2] = var->op; + dst = operands[2]; + st = build_statement ("call", operands, var->expr); + sblock_add_statement (block, st); + } + if (var_iter) { + set_del_iter (var_iter); + } + if (!var) { + // void call or return value ignored, still have to call + operands[2] = make_operand (dag, block, dagnode, 2); + st = build_statement ("call", operands, dagnode->label->expr); + sblock_add_statement (block, st); + } + return dst; +} + static operand_t * generate_assignments (dag_t *dag, sblock_t *block, operand_t *src, set_iter_t *var_iter, type_t *type) @@ -1222,8 +1259,13 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) case st_ptrmemset: dst = generate_memsetps (dag, block, dagnode); break; - case st_state: case st_func: + if (!strcmp (dagnode->label->opcode, "call")) { + dst = generate_call (dag, block, dagnode); + break; + } + // fallthrough + case st_state: for (i = 0; i < 3; i++) if (dagnode->children[i]) operands[i] = make_operand (dag, block, dagnode, i); diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 4b501c027..4592ae8b6 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1290,6 +1290,9 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, flow_add_op_var (def, s->opc, 0); // don't want old argument processing calln = -1; + if (operands && s->opc->op_type != op_value) { + operands[0] = s->opc; + } } else if (strncmp (s->opcode, "call", 4) == 0) { start = 0; calln = s->opcode[5] - '0'; From 0211b6ec5b19ece03a7a71fb0cfabb103e09a32f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Feb 2022 14:47:36 +0900 Subject: [PATCH 2374/3664] [gamecode] Add 64-bit load/store instructions Only widths 3 and 4 have been added because widths 1 and 2 can be implemented by widths 2 and 4 of the 32-bit load/store instructions. --- libs/gamecode/opcodes.py | 35 +++++++++- libs/gamecode/pr_exec.c | 26 ++++++++ libs/gamecode/test/Makemodule.am | 12 ++++ libs/gamecode/test/test-load64.c | 89 +++++++++++++++++++++++++ libs/gamecode/test/test-store64.c | 105 ++++++++++++++++++++++++++++++ 5 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 libs/gamecode/test/test-load64.c create mode 100644 libs/gamecode/test/test-store64.c diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 61ad591ab..3aa2ec324 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -9,7 +9,9 @@ bitmap_txt = """ 0 0000 0001 adjstk 0 0000 0010 constant 0 1011 nnnn -0 1111 nnnn +0 1111 s0mm load64 +0 1111 s1mm store64 +0 1111 n000 1 0ooo ttss mathops 1 011r tuss shiftops @@ -211,6 +213,20 @@ jump_formats = { "jump_widths": [ "0, 0", "1, 1", "1, 0", "1, 1" ] }, } +load64_formats = { + "opcode": "OP_LOAD64_{op_mode[mm]}_{s+3}", + "mnemonic": "load64", + "opname": "load64", + "format": "{load_fmt[mm]}, %gc", + "widths": "{load_widths[s+2][mm]}, {s+3}", + "types": "{load_types[mm]}, ev_void", + "args": { + "op_mode": address_mode, + "load_fmt": load_fmt, + "load_types": address_types, + "load_widths": address_widths, + }, +} lea_formats = { "opcode": "OP_LEA_{op_mode[mm]}", "mnemonic": "lea", @@ -401,6 +417,21 @@ store_formats = { "store_widths": address_widths, }, } +store64_formats = { + "opcode": "OP_STORE64_{op_mode[mm]}_{s+3}", + "mnemonic": "{store_op[mm]}64", + "opname": "{store_op[mm]}64", + "format": "%Gc, {store_fmt[mm]}", + "widths": "{store_widths[s+2][mm]}, {s+3}", + "types": "{store_types[mm]}, ev_void", + "args": { + "op_mode": address_mode, + "store_fmt": store_fmt, + "store_op": ["assign", "store", "store", "store"], + "store_types": address_types, + "store_widths": address_widths, + }, +} string_formats = { "opcode": "OP_{op_str[o*4+oo].upper()}_S", "mnemonic": "{op_str[o*4+oo]}.s", @@ -509,6 +540,7 @@ group_map = { "jump": jump_formats, "lea": lea_formats, "load": load_formats, + "load64": load64_formats, "mathops": mathops_formats, "memset": memset_formats, "move": move_formats, @@ -520,6 +552,7 @@ group_map = { "statef": statef_formats, "stated": stated_formats, "store": store_formats, + "store64": store64_formats, "string": string_formats, "swizzle": swizzle_formats, "return": return_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 89890908f..febb93266 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2978,6 +2978,32 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) // 0 1110 OP_cmp(LE, <=); // 0 1111 + case OP_LOAD64_B_3: + case OP_LOAD64_C_3: + case OP_LOAD64_D_3: + mm = pr_address_mode (pr, st, (st_op - OP_LOAD64_B_3 + 1)); + VectorCopy (&MM(long), &OPC(long)); + break; + case OP_STORE64_A_3: + case OP_STORE64_B_3: + case OP_STORE64_C_3: + case OP_STORE64_D_3: + mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_3)); + VectorCopy (&OPC(long), &MM(long)); + break; + case OP_LOAD64_B_4: + case OP_LOAD64_C_4: + case OP_LOAD64_D_4: + mm = pr_address_mode (pr, st, (st_op - OP_LOAD64_B_4 + 1)); + OPC(lvec4) = MM(lvec4); + break; + case OP_STORE64_A_4: + case OP_STORE64_B_4: + case OP_STORE64_C_4: + case OP_STORE64_D_4: + mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_4)); + MM(lvec4) = OPC(lvec4); + break; // spare #define OP_op_1(OP, T, t, op) \ diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 1fd3353bf..57793aa4f 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -17,12 +17,14 @@ libs_gamecode_tests = \ libs/gamecode/test/test-jump \ libs/gamecode/test/test-lea \ libs/gamecode/test/test-load \ + libs/gamecode/test/test-load64 \ libs/gamecode/test/test-long \ libs/gamecode/test/test-mem \ libs/gamecode/test/test-scale \ libs/gamecode/test/test-stack \ libs/gamecode/test/test-state \ libs/gamecode/test/test-store \ + libs/gamecode/test/test-store64 \ libs/gamecode/test/test-string \ libs/gamecode/test/test-swizzle \ libs/gamecode/test/test-unsigned \ @@ -129,6 +131,11 @@ libs_gamecode_test_test_load_SOURCES= \ libs_gamecode_test_test_load_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_load_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_load64_SOURCES= \ + libs/gamecode/test/test-load64.c +libs_gamecode_test_test_load64_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_load64_DEPENDENCIES=$(test_gamecode_libs) + libs_gamecode_test_test_long_SOURCES= \ libs/gamecode/test/test-long.c libs_gamecode_test_test_long_LDADD= $(test_gamecode_libs) @@ -158,6 +165,11 @@ libs_gamecode_test_test_store_SOURCES= \ libs_gamecode_test_test_store_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_store_DEPENDENCIES= $(test_gamecode_libs) +libs_gamecode_test_test_store64_SOURCES= \ + libs/gamecode/test/test-store64.c +libs_gamecode_test_test_store64_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_store64_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_string_SOURCES= \ libs/gamecode/test/test-string.c libs_gamecode_test_test_string_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-load64.c b/libs/gamecode/test/test-load64.c new file mode 100644 index 000000000..abb6052eb --- /dev/null +++ b/libs/gamecode/test/test-load64.c @@ -0,0 +1,89 @@ +#include "head.c" + +static pr_int_t test_globals_init[] = { + // pointers + 24, 26, 48, 29, + 32, -8, -4, 0, + 2, 8, 0xdeadbeef, 0xfeedf00d, + 0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d, + // destination data + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + // source data + 21, 22, 23, 24, 17, 18, 19, 20, + 15, 16, 9, 10, 11, 12, 13, 14, + 1, 2, 3, 4, 5, 6, 7, 8, +}; + +static pr_int_t test_globals_expect[] = { + // pointers + 24, 26, 48, 29, + 32, -8, -4, 0, + 2, 8, 0xdeadbeef, 0xfeedf00d, + 0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d, + // destination data +/*16*/ 1, 2, 3, 4, 5, 6, 7, 8, +/*24*/ 9, 10, 11, 12, 13, 14, 15, 16, +/*32*/ 17, 18, 19, 20, 21, 22, 23, 24, + // source data +/*40*/ 21, 22, 23, 24, 17, 18, 19, 20, +/*48*/ 15, 16, 9, 10, 11, 12, 13, 14, +/*56*/ 1, 2, 3, 4, 5, 6, 7, 8, +}; + +static dstatement_t load64_B_statements[] = { + {OP(0, 0, 0, OP_LOAD64_B_4), 7, 9, 16}, + {OP(0, 0, 0, OP_LOAD64_B_3), 7, 8, 24}, + {OP(0, 0, 0, OP_LOAD_B_2), 7, 7, 30}, + {OP(0, 0, 0, OP_LOAD_B_4), 7, 6, 32}, + {OP(0, 0, 0, OP_LOAD_B_4), 7, 5, 36}, +}; + +static dstatement_t load64_C_statements[] = { + {OP(0, 0, 0, OP_LOAD64_C_4), 2, 8, 16}, + {OP(0, 0, 0, OP_LOAD64_C_3), 2, 2, 24}, + {OP(0, 0, 0, OP_LOAD_C_2), 2, 0, 30}, + {OP(0, 0, 0, OP_LOAD_C_4), 2, -4, 32}, + {OP(0, 0, 0, OP_LOAD_C_4), 2, -8, 36}, +}; + +static dstatement_t load64_D_statements[] = { + {OP(0, 0, 0, OP_LOAD64_D_4), 2, 9, 16}, + {OP(0, 0, 0, OP_LOAD64_D_3), 2, 8, 24}, + {OP(0, 0, 0, OP_LOAD_D_2), 2, 7, 30}, + {OP(0, 0, 0, OP_LOAD_D_4), 2, 6, 32}, + {OP(0, 0, 0, OP_LOAD_D_4), 2, 5, 36}, +}; + +test_t tests[] = { + { + .desc = "load64 B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load64_B_statements), + .statements = load64_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 48, + }, + { + .desc = "load64 C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load64_C_statements), + .statements = load64_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "load64 D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (load64_D_statements), + .statements = load64_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" diff --git a/libs/gamecode/test/test-store64.c b/libs/gamecode/test/test-store64.c new file mode 100644 index 000000000..d8dfd2018 --- /dev/null +++ b/libs/gamecode/test/test-store64.c @@ -0,0 +1,105 @@ +#include "head.c" + +static pr_int_t test_globals_init[] = { + // pointers + 24, 26, 48, 29, + 32, -8, -4, 0, + 2, 8, 0xdeadbeef, 0xfeedf00d, + 0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d, + // source data +/*16*/ 1, 2, 3, 4, 5, 6, 7, 8, +/*24*/ 9, 10, 11, 12, 13, 14, 15, 16, +/*32*/ 17, 18, 19, 20, 21, 22, 23, 24, + // destination data + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static pr_int_t test_globals_expect[] = { + // pointers + 24, 26, 48, 29, + 32, -8, -4, 0, + 2, 8, 0xdeadbeef, 0xfeedf00d, + 0xdeadbeef, 0xfeedf00d, 0xdeadbeef, 0xfeedf00d, + // source data +/*16*/ 1, 2, 3, 4, 5, 6, 7, 8, +/*24*/ 9, 10, 11, 12, 13, 14, 15, 16, +/*32*/ 17, 18, 19, 20, 21, 22, 23, 24, + // destination data +/*40*/ 21, 22, 23, 24, 17, 18, 19, 20, +/*48*/ 15, 16, 9, 10, 11, 12, 13, 14, +/*56*/ 1, 2, 3, 4, 5, 6, 7, 8, +}; + +static dstatement_t store64_A_statements[] = { + {OP(0, 0, 0, OP_STORE64_A_4), 56, 0, 16}, + {OP(0, 0, 0, OP_STORE64_A_3), 50, 0, 24}, + {OP(0, 0, 0, OP_STORE_A_2), 48, 0, 30}, + {OP(0, 0, 0, OP_STORE_A_4), 44, 0, 32}, + {OP(0, 0, 0, OP_STORE_A_4), 40, 0, 36}, +}; + +static dstatement_t store64_B_statements[] = { + {OP(0, 0, 0, OP_STORE64_B_4), 7, 9, 16}, + {OP(0, 0, 0, OP_STORE64_B_3), 7, 8, 24}, + {OP(0, 0, 0, OP_STORE_B_2), 7, 7, 30}, + {OP(0, 0, 0, OP_STORE_B_4), 7, 6, 32}, + {OP(0, 0, 0, OP_STORE_B_4), 7, 5, 36}, +}; + +static dstatement_t store64_C_statements[] = { + {OP(0, 0, 0, OP_STORE64_C_4), 2, 8, 16}, + {OP(0, 0, 0, OP_STORE64_C_3), 2, 2, 24}, + {OP(0, 0, 0, OP_STORE_C_2), 2, 0, 30}, + {OP(0, 0, 0, OP_STORE_C_4), 2, -4, 32}, + {OP(0, 0, 0, OP_STORE_C_4), 2, -8, 36}, +}; + +static dstatement_t store64_D_statements[] = { + {OP(0, 0, 0, OP_STORE64_D_4), 2, 9, 16}, + {OP(0, 0, 0, OP_STORE64_D_3), 2, 8, 24}, + {OP(0, 0, 0, OP_STORE_D_2), 2, 7, 30}, + {OP(0, 0, 0, OP_STORE_D_4), 2, 6, 32}, + {OP(0, 0, 0, OP_STORE_D_4), 2, 5, 36}, +}; + +test_t tests[] = { + { + .desc = "store64 A", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store64_A_statements), + .statements = store64_A_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "store64 B", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store64_B_statements), + .statements = store64_B_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + // FIXME negative field offsets are not official but work because all + // offset calculations are done in 32-bit and thus wrap anyway + .edict_area = 48, + }, + { + .desc = "store64 C", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store64_C_statements), + .statements = store64_C_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, + { + .desc = "store64 D", + .num_globals = num_globals (test_globals_init, test_globals_expect), + .num_statements = num_statements (store64_D_statements), + .statements = store64_D_statements, + .init_globals = test_globals_init, + .expect_globals = test_globals_expect, + }, +}; + +#include "main.c" From 38550922cc4e980427be8339354d1b9193318065 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Feb 2022 16:06:15 +0900 Subject: [PATCH 2375/3664] [qfcc] Map 64-bit load/store/assign instructions In order to not waste instructions, the Ruamoko ISA does not provide 1 and 2 component 64-bit load/store instructions since they can be implemented using 2 and 4 component 32-bit instructions (load and store are independent of the interpretation of the data). This fixes the double test, and technically the double-alias test, but it fails due to a problem with the optimizer causing lea to use the wrong reference for the address. It also breaks the quaternion test due to what seems to be a type error that may have been lurking for a while, further investigation is needed there. --- tools/qfcc/source/opcodes.c | 45 +++++++++++++++++++++++++++++++++---- tools/qfcc/test/double.r | 2 +- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index dcb6342cc..4be436c1b 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -280,7 +280,7 @@ operand_type (const operand_t *op, const char *name) } static int -operand_width (operand_t *op) +operand_width (const char *opname, operand_t *op) { if (!op) { return 0; @@ -292,6 +292,14 @@ operand_width (operand_t *op) if (type == ev_quaternion) { return 4; } + // FIXME see FIXME in rua_opcode_find + if ((type == ev_long || type == ev_ulong || type == ev_double) + && (!strcmp (opname, "load") || !strcmp (opname, "store") + || !strcmp (opname, "assign"))) { + if (op->width < 3) { + return op->width * 2; + } + } return op->width; } @@ -299,6 +307,35 @@ static opcode_t * rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) { + // FIXME this is a bit of an ugly hack to map 64-bit load and store/assign + // instructions: 1 and 2 component instructions become 2 and 4 components + // using the 32-bit instructions, while 3 and 4 remain unchanged but use + // the 64-bit versions of the instructs (of which there are only 3 and 4 + // component versions). That bit of fun can't be helped without wasting a + // lot of instructions, but this mapping scheme leaves a lot to be desired. + const char *opname_a = ""; + const char *opname_c = ""; + if (!strcmp (name, "load") || !strcmp (name, "store") + || !strcmp (name, "assign")) { + opname_c = name; + if (!strcmp (name, "assign")) { + opname_a = name; + if (op_c->width > 2) { + name = "assign64"; + } + } + if (!strcmp (name, "load")) { + if (op_c->width > 2) { + name = "load64"; + } + } + if (!strcmp (name, "store")) { + if (op_c->width > 2) { + name = "store64"; + } + } + } + opcode_t search_op = { .opname = name, .types = { @@ -307,9 +344,9 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_type (op_c, name), }, .widths = { - operand_width (op_a), - operand_width (op_b), - operand_width (op_c), + operand_width (opname_a, op_a), + operand_width ("", op_b), + operand_width (opname_c, op_c), }, }; opcode_t *op; diff --git a/tools/qfcc/test/double.r b/tools/qfcc/test/double.r index 326ccf906..de0649b19 100644 --- a/tools/qfcc/test/double.r +++ b/tools/qfcc/test/double.r @@ -11,7 +11,7 @@ test_format () { int fail = 0; type_pun.d = M_PI; - printf ("%g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]); + printf ("%.17g %08x%08x\n", type_pun.d, type_pun.i[1], type_pun.i[0]); // this will fail on big-endian systems fail = type_pun.i[0] != 0x54442d18 || type_pun.i[1] != 0x400921fb; return fail; From a64f91129f4a87a340bf27963fc0e8920c982d4c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Feb 2022 18:55:01 +0900 Subject: [PATCH 2376/3664] [qfcc] Give lea its own statement type This makes it much easier to check (and more robust to name changes), allowing for effectively killing the node to which the variable being addressed is attached. This fixes the incorrect address being used for va_list, which is what caused double-alias to fail. --- tools/qfcc/include/statements.h | 1 + tools/qfcc/source/dags.c | 6 +++++- tools/qfcc/source/flow.c | 20 +++++++++++++------- tools/qfcc/source/statements.c | 7 ++++--- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 3bee3de33..a1fc6914e 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -102,6 +102,7 @@ typedef enum { st_state, ///< state (a, b); or state (a, b, c) st_func, ///< call, rcall or return/done st_flow, ///< if/ifa/ifae/ifb/ifbe/ifnot or goto or jump/jumpb + st_address, ///< lea } st_type_t; typedef struct statement_s { diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index e55688ff4..d2f746962 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -282,8 +282,11 @@ dag_make_children (dag_t *dag, statement_t *s, dagnode_t *node = dag_node (operands[i + 1]); dagnode_t *killer = 0; - if (node && node->killed) { + if (node && (node->killed || s->type == st_address)) { // If the node has been killed, then a new node is needed + // taking the address of a variable effectively kills the node it's + // attached to. FIXME should this be for only when the variable is + // in the attached identifiers list and is not the node's label? killer = node->killed; node = 0; } @@ -1214,6 +1217,7 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) dst = generate_assignments (dag, block, dst, var_iter, type); } break; + case st_address: case st_expr: operands[0] = make_operand (dag, block, dagnode, 0); if (dagnode->children[1]) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 4592ae8b6..4e86fc0c3 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1181,15 +1181,21 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, switch (s->type) { case st_none: internal_error (s->expr, "not a statement"); + case st_address: + if (s->opb) { + flow_add_op_var (use, s->opa, 1); + flow_add_op_var (use, s->opb, 1); + } + flow_add_op_var (def, s->opc, 0); + if (operands) { + operands[0] = s->opc; + operands[1] = s->opa; + operands[2] = s->opb; + } + break; case st_expr: flow_add_op_var (def, s->opc, 0); - if (strcmp (s->opcode, "lea") == 0) { - if (s->opb) { - flow_add_op_var (use, s->opa, 1); - } - } else { - flow_add_op_var (use, s->opa, 1); - } + flow_add_op_var (use, s->opa, 1); if (s->opb) flow_add_op_var (use, s->opb, 1); if (operands) { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index bfa782205..e75d4c676 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -87,6 +87,7 @@ const char *st_type_names[] = { "st_state", "st_func", "st_flow", + "st_address", }; const char * @@ -744,7 +745,7 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op) offset = 0; } - s = new_statement (st_expr, "lea", e); + s = new_statement (st_address, "lea", e); sblock = statement_subexpr (sblock, lvalue, &s->opa); if (offset) { sblock = statement_subexpr (sblock, offset, &s->opb); @@ -1005,7 +1006,7 @@ dereference_dst: // one directly. FIXME it was probably a mistake extracting the operand // type from the statement expression in dags dst_expr = expr_file_line (address_expr (dst_expr, 0), dst_expr); - s = new_statement (st_expr, "lea", dst_expr); + s = new_statement (st_address, "lea", dst_expr); s->opa = dst; s->opb = ofs; s->opc = temp_operand (&type_ptr, dst_expr); @@ -1438,7 +1439,7 @@ statement_with (sblock_t *sblock, expr_t *e) static statement_t * lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) { - statement_t *s = new_statement (st_expr, "lea", e); + statement_t *s = new_statement (st_address, "lea", e); s->opa = pointer; s->opb = offset; s->opc = temp_operand (&type_ptr, e); From 0fa9d0d256d3f24bdf87bec07b6cb848da24b7a2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Feb 2022 19:04:43 +0900 Subject: [PATCH 2377/3664] [qfcc] Tweak the printf to make more sense Though I'm sure I had a good reason at the time, seeing 6.98487e-315 when expecting pi is a bit disconcerting. --- tools/qfcc/test/double-alias.r | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/test/double-alias.r b/tools/qfcc/test/double-alias.r index 92eecd9c3..5df0d3398 100644 --- a/tools/qfcc/test/double-alias.r +++ b/tools/qfcc/test/double-alias.r @@ -25,8 +25,8 @@ alias_printf (string fmt, ...) // this will fail on big-endian systems fail = (@args.list[2].int_val != 0x54442d18 || @args.list[1].int_val != 0x400921fb); - printf ("%g %08x%08x\n", - @args.list[0].int_val, + printf ("%.17g %08x%08x\n", + @args.list[0].double_val, @args.list[2].int_val, @args.list[1].int_val); return fail; From 6fe72b0420d2b45a2119c21e919c134db6b9d94f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Feb 2022 19:14:22 +0900 Subject: [PATCH 2378/3664] [qfcc] Check load/store operand type before mangling This fixes the incorrect use of assign64 for quaternions. All tests except return-postop pass \o/. --- tools/qfcc/source/opcodes.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 4be436c1b..5c97f780c 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -315,8 +315,11 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, // lot of instructions, but this mapping scheme leaves a lot to be desired. const char *opname_a = ""; const char *opname_c = ""; - if (!strcmp (name, "load") || !strcmp (name, "store") - || !strcmp (name, "assign")) { + etype_t type; + if ((!strcmp (name, "load") || !strcmp (name, "store") + || !strcmp (name, "assign")) + && ((type = low_level_type (op_c->type)) == ev_long + || type == ev_ulong || type == ev_double)) { opname_c = name; if (!strcmp (name, "assign")) { opname_a = name; From b668759b7dee16a88e53441d43b7a1142f6d568b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Feb 2022 23:51:37 +0900 Subject: [PATCH 2379/3664] [qfcc] Add a very basic attribute system Ruamoko passes va_list (@args) through the ... parameter (as such), but IMP uses ... to defeat parameter type and count checking and doesn't want va_list. While possibly not the best solution, adding a no_va_list flag to function types and skipping ex_args entirely does take care of the problem without hard-coding anything specific to IMP. The system currently just sets some bits in the type specifier (the attribute list should probably be carried around with the specifier), but it gets the job done for now, and at least gets things started. --- tools/qfcc/include/Makemodule.am | 1 + tools/qfcc/include/attribute.h | 43 +++++++++++++++++++++++++ tools/qfcc/include/type.h | 2 ++ tools/qfcc/source/Makemodule.am | 1 + tools/qfcc/source/attribute.c | 55 ++++++++++++++++++++++++++++++++ tools/qfcc/source/class.c | 2 +- tools/qfcc/source/expr.c | 2 +- tools/qfcc/source/qc-lex.l | 4 +-- tools/qfcc/source/qc-parse.y | 52 +++++++++++++++++++++++++++--- tools/qfcc/source/type.c | 3 +- tools/qfcc/test/chewed-alias.r | 2 +- tools/qfcc/test/methodparams.r | 2 +- tools/qfcc/test/sendv.r | 2 +- 13 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 tools/qfcc/include/attribute.h create mode 100644 tools/qfcc/source/attribute.c diff --git a/tools/qfcc/include/Makemodule.am b/tools/qfcc/include/Makemodule.am index 689ebad68..f6158b5c4 100644 --- a/tools/qfcc/include/Makemodule.am +++ b/tools/qfcc/include/Makemodule.am @@ -1,4 +1,5 @@ EXTRA_DIST += \ + tools/qfcc/include/attribute.h \ tools/qfcc/include/class.h \ tools/qfcc/include/codespace.h \ tools/qfcc/include/cpp.h \ diff --git a/tools/qfcc/include/attribute.h b/tools/qfcc/include/attribute.h new file mode 100644 index 000000000..2f47642e6 --- /dev/null +++ b/tools/qfcc/include/attribute.h @@ -0,0 +1,43 @@ +/* + attribute.h + + Attribute list handling + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/02/02 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef attribute_h +#define attribute_h + +typedef struct attribute_s { + struct attribute_s *next; + const char *name; + struct ex_value_s *value; +} attribute_t; + +struct expr_s; +attribute_t *new_attribute(const char *name, struct expr_s *value); + +#endif//attribute_h diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 2062933d6..7a213dd98 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -39,6 +39,7 @@ typedef struct ty_func_s { struct type_s *type; int num_params; struct type_s **param_types; + int no_va_list; ///< don't inject va_list for ... function } ty_func_t; typedef struct ty_fldptr_s { @@ -97,6 +98,7 @@ typedef struct { unsigned is_typedef:1; unsigned is_overload:1; unsigned nosave:1; + unsigned no_va_list:1; } specifier_t; #define EV_TYPE(type) extern type_t type_##type; diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index 76e3f73d8..d7d85e597 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -7,6 +7,7 @@ bin_PROGRAMS += @QFCC_TARGETS@ bin_SCRIPTS += tools/qfcc/source/qfpreqcc qfcc_SOURCES = \ + tools/qfcc/source/attribute.c \ tools/qfcc/source/class.c \ tools/qfcc/source/codespace.c \ tools/qfcc/source/constfold.c \ diff --git a/tools/qfcc/source/attribute.c b/tools/qfcc/source/attribute.c new file mode 100644 index 000000000..b821124c1 --- /dev/null +++ b/tools/qfcc/source/attribute.c @@ -0,0 +1,55 @@ +/* + attribute.c + + Attribute list handling + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/02/02 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/alloc.h" + +#include "tools/qfcc/include/attribute.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/strpool.h" + +static attribute_t *attributes_freelist; + +attribute_t *new_attribute(const char *name, expr_t *value) +{ + if (value && value->type != ex_value) { + error (value, "not a literal constant"); + return 0; + } + + attribute_t *attr; + ALLOC (16384, attribute_t, attributes, attr); + attr->name = save_string (name); + attr->value = value ? value->e.value : 0; + return attr; +} diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index d90ecc062..42f613c9e 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -90,7 +90,7 @@ type_t type_IMP = { .alignment = 1, .width = 1, .meta = ty_basic, - {{&type_id, -3, IMP_params}}, + {{&type_id, -3, IMP_params, 1}}, }; type_t type_super = { .type = ev_invalid, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 7af72d5a1..3364bedbf 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2155,7 +2155,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) warning (fexpr, "too few arguments"); } param_count = -ftype->t.func.num_params - 1; - emit_args = 1; + emit_args = !ftype->t.func.no_va_list; } else if (ftype->t.func.num_params >= 0) { if (arg_count > ftype->t.func.num_params) { return error (fexpr, "too many arguments"); diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index c2db6db0c..3c8e28ec9 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -367,7 +367,6 @@ static keyword_t at_keywords[] = { {"extern", EXTERN }, {"static", STATIC }, {"sizeof", SIZEOF }, - {"nosave", NOSAVE }, {"not", NOT }, }; @@ -391,7 +390,7 @@ static keyword_t qf_keywords[] = { {"@dot", DOT, 0 }, }; -// These keywors are always available. Other than @system and @overload, they +// These keywors are always available. Other than the @ keywords, they // form traditional QuakeC. static keyword_t keywords[] = { {"void", TYPE, &type_void }, @@ -407,6 +406,7 @@ static keyword_t keywords[] = { {"else", ELSE, 0 }, {"@system", SYSTEM, 0 }, {"@overload", OVERLOAD, 0 }, + {"@attribute", ATTRIBUTE, 0 }, }; static const char * diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 3ab14cbe2..99006c68e 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -44,6 +44,7 @@ #include #include +#include "tools/qfcc/include/attribute.h" #include "tools/qfcc/include/class.h" #include "tools/qfcc/include/debug.h" #include "tools/qfcc/include/def.h" @@ -112,6 +113,7 @@ int yylex (void); struct methodlist_s *methodlist; struct symbol_s *symbol; struct symtab_s *symtab; + struct attribute_s *attribute; } // these tokens are common between qc and qp @@ -149,7 +151,7 @@ int yylex (void); %token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS %token NIL GOTO SWITCH CASE DEFAULT ENUM -%token ARGS TYPEDEF EXTERN STATIC SYSTEM NOSAVE OVERLOAD NOT +%token ARGS TYPEDEF EXTERN STATIC SYSTEM OVERLOAD NOT ATTRIBUTE %token UNSIGNED SIGNED LONG SHORT %token STRUCT %token TYPE @@ -162,6 +164,8 @@ int yylex (void); %type type_specifier type_specifier_or_storage_class %type type +%type attribute_list attribute + %type function_params var_list param_declaration %type qc_func_params qc_var_list qc_param_decl %type new_name @@ -238,6 +242,22 @@ make_spec (type_t *type, storage_class_t storage, int is_typedef, return spec; } +static specifier_t +parse_attributes (attribute_t *attr_list) +{ + specifier_t spec = {}; + for (attribute_t *attr = attr_list; attr; attr = attr->next) { + if (!strcmp (attr->name, "no_va_list")) { + spec.no_va_list = 1; + } else if (!strcmp (attr->name, "nosave")) { + spec.nosave = 1; + } else { + warning (0, "skipping unknown attribute '%s'", attr->name); + } + } + return spec; +} + static specifier_t spec_merge (specifier_t spec, specifier_t new) { @@ -276,6 +296,7 @@ spec_merge (specifier_t spec, specifier_t new) spec.is_long |= new.is_long; spec.is_overload |= new.is_overload; spec.nosave |= new.nosave; + spec.no_va_list |= new.no_va_list; return spec; } @@ -471,6 +492,7 @@ external_def ret_type = *type; *type = 0; *type = parse_params (0, $2); + (*type)->t.func.no_va_list = $1.no_va_list; $$.type = find_type (append_type ($1.type, ret_type)); if ($$.type->type != ev_field) $$.params = $2; @@ -511,6 +533,7 @@ function_body symbol_t *sym = $0; specifier_t spec = default_type ($-1, sym); + sym->type->t.func.no_va_list = spec.no_va_list; sym->type = find_type (append_type (sym->type, spec.type)); $$ = function_symbol (sym, spec.is_overload, 1); } @@ -534,6 +557,7 @@ function_body symbol_t *sym = $0; specifier_t spec = default_type ($-1, sym); + sym->type->t.func.no_va_list = spec.no_va_list; sym->type = find_type (append_type (sym->type, spec.type)); sym = function_symbol (sym, spec.is_overload, 1); build_builtin_function (sym, $3, 0, spec.storage); @@ -582,6 +606,7 @@ external_decl | function_decl { specifier_t spec = default_type ($0, $1); + $1->type->t.func.no_va_list = spec.no_va_list; $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; @@ -599,13 +624,30 @@ storage_class | SYSTEM { $$ = make_spec (0, sc_system, 0, 0); } | TYPEDEF { $$ = make_spec (0, sc_global, 1, 0); } | OVERLOAD { $$ = make_spec (0, current_storage, 0, 1); } - | NOSAVE + | ATTRIBUTE '(' attribute_list ')' { - $$ = make_spec (0, current_storage, 0, 0); - $$.nosave = 1; + $$ = parse_attributes ($3); } ; +attribute_list + : attribute + | attribute_list ',' attribute + { + if ($3) { + $3->next = $1; + $$ = $3; + } else { + $$ = $1; + } + } + ; + +attribute + : NAME { $$ = new_attribute ($1->name, 0); } + | NAME '(' expr_list ')' { $$ = new_attribute ($1->name, $3); } + ; + optional_specifiers : specifiers { @@ -1053,6 +1095,7 @@ qc_param_decl type = &(*type)->t.fldptr.type) ; *type = parse_params (*type, $2); + (*type)->t.func.no_va_list = $1.no_va_list; $3->type = find_type ($1.type); if ($3->type->type != ev_field) $3->params = $2; @@ -1131,6 +1174,7 @@ local_decl_list type = &(*type)->t.fldptr.type) ; *type = parse_params (*type, $1); + (*type)->t.func.no_va_list = spec.no_va_list; spec.type = find_type (spec.type); $$ = spec; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 7e73fc99d..9f94affae 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -381,7 +381,8 @@ types_same (type_t *a, type_t *b) return 0; case ev_func: if (a->t.func.type != b->t.func.type - || a->t.func.num_params != b->t.func.num_params) + || a->t.func.num_params != b->t.func.num_params + || a->t.func.no_va_list != b->t.func.no_va_list) return 0; count = a->t.func.num_params; if (count < 0) diff --git a/tools/qfcc/test/chewed-alias.r b/tools/qfcc/test/chewed-alias.r index 08c060534..409254c39 100644 --- a/tools/qfcc/test/chewed-alias.r +++ b/tools/qfcc/test/chewed-alias.r @@ -18,7 +18,7 @@ int main () { return 0; // test succeeds if compile succeeds } -id obj_msgSend (id receiver, SEL op, ...) = #0; +@attribute(no_va_list) id obj_msgSend (id receiver, SEL op, ...) = #0; void __obj_exec_class (struct obj_module *msg) = #0; @implementation Object @end diff --git a/tools/qfcc/test/methodparams.r b/tools/qfcc/test/methodparams.r index b29e6954b..d2e71591b 100644 --- a/tools/qfcc/test/methodparams.r +++ b/tools/qfcc/test/methodparams.r @@ -15,7 +15,7 @@ typedef struct { int x, y; } Point; [textContext mvvprintf: pos, fmt, @args]; } @end -id obj_msgSend (id receiver, SEL op, ...) = #0; +@attribute(no_va_list) id obj_msgSend (id receiver, SEL op, ...) = #0; void __obj_exec_class (struct obj_module *msg) = #0; @interface Object @end diff --git a/tools/qfcc/test/sendv.r b/tools/qfcc/test/sendv.r index aa2cb6665..24929992a 100644 --- a/tools/qfcc/test/sendv.r +++ b/tools/qfcc/test/sendv.r @@ -54,5 +54,5 @@ main () } @end -id (id receiver, SEL op, ...) obj_msgSend = #0; +@attribute(no_va_list) id (id receiver, SEL op, ...) obj_msgSend = #0; void __obj_exec_class (struct obj_module *msg) = #0; From 6f49b919eca12be0a1606949786c290f08923835 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Feb 2022 10:55:37 +0900 Subject: [PATCH 2380/3664] [qfcc] Move constant pointer offset into address expr This is the intended purpose of the offset field in address expressions, and will make struct and array accesses more efficient when I sort out the code generation side. --- tools/qfcc/source/expr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 3364bedbf..7b1d76372 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2622,6 +2622,12 @@ offset_pointer_expr (expr_t *pointer, expr_t *offset) if (pointer->type == ex_alias && !pointer->e.alias.offset && is_integral (get_type (pointer->e.alias.expr))) { ptr = pointer->e.alias.expr; + } else if (pointer->type == ex_address && is_constant (offset)) { + if (pointer->e.address.offset) { + offset = binary_expr ('+', pointer->e.address.offset, offset); + } + pointer->e.address.offset = offset; + return pointer; } else { ptr = cast_expr (&type_int, pointer); } From 80c643154475d78621a0f676fdeba81f46eb44cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Feb 2022 14:15:20 +0900 Subject: [PATCH 2381/3664] [qfcc] Clear up a FIXME The FIXME was there because I couldn't remember why the test was type_compatible but the internal error complains about the types being the same size. The compatibility check is to see if the op can be used directly or whether a temp is required. The offset check is because types that are the same size (which they must be if they are compatible) is because it is not possible to create an offset alias def that escapes the bounds of the real def, which any non-zero offset will do if the types are the same size. --- tools/qfcc/source/statements.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e75d4c676..7fed3cef0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1532,8 +1532,9 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op) type = e->e.alias.type; sblock = statement_subexpr (sblock, e->e.alias.expr, &aop); if (type_compatible (aop->type, type)) { - //FIXME type_compatible??? shouldn't that be type_size ==? if (offset) { + //For types to be compatible, they must be the same size, thus this + //seemingly mismatched error internal_error (e, "offset alias of same size type"); } *op = aop; From 008359862b0bb4ab6bf68ab402e8eb6472f56bae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Feb 2022 14:35:43 +0900 Subject: [PATCH 2382/3664] [qfcc] Avoid pointer alias of address expressions Since address expressions always product a pointer type, aliasing one to another pointer type is redundant. Instead, simply return an address expression with the desired type. --- tools/qfcc/source/expr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 7b1d76372..341f6d7a9 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1346,6 +1346,12 @@ is_pointer_val (expr_t *e) expr_t * new_alias_expr (type_t *type, expr_t *expr) { + if (is_ptr (type) && expr->type == ex_address) { + // avoid aliasing a pointer to a pointer (redundant) + expr = copy_expr (expr); + expr->e.address.type = type; + return expr; + } if (expr->type == ex_alias) { if (expr->e.alias.offset) { return new_offset_alias_expr (type, expr, 0); From a3c37201b2d493873578540965844323785ca467 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Feb 2022 14:41:46 +0900 Subject: [PATCH 2383/3664] [qfcc] Emit constant pointers as direct def references When possible, of course. However, this tightens up struct and constant index array accesses, and avoids issues with flow analysis losing track of the def (such trucking is something I want to do, but haven't decided out to get the information out to the right statements). --- tools/qfcc/source/statements.c | 74 +++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 7fed3cef0..aaba453ff 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -947,7 +947,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) operand_t *ofs = 0; pr_ushort_t mode = 0; // assign const char *opcode = "assign"; - st_type_t type; + st_type_t type = st_assign; if (src_expr->type == ex_assign) { sblock = statement_subexpr (sblock, src_expr, &src); @@ -983,15 +983,18 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) sblock = statement_subexpr (sblock, src_expr, &src); } } - type = st_assign; if (0) { dereference_dst: // dst_expr is a dereferenced pointer, so need to get its addressing // parameters (base and offset) and switch to storep instructions. sblock = addressing_mode (sblock, dst_expr, &dst, &ofs, &mode); - opcode = "store"; - type = st_ptrassign; + if (mode != 0) { + opcode = "store"; + type = st_ptrassign; + } else { + ofs = 0; + } } if (op) { *op = src; @@ -1290,11 +1293,45 @@ static sblock_t * ptr_addressing_mode (sblock_t *sblock, expr_t *ref, operand_t **base, operand_t **offset, pr_ushort_t *mode) { - if (!is_ptr (get_type (ref))) { + type_t *type = get_type (ref); + if (!is_ptr (type)) { internal_error (ref, "expected pointer in ref"); } - if (ref->type != ex_alias || ref->e.alias.offset) { + if (ref->type == ex_address + && (!ref->e.address.offset || is_constant (ref->e.address.offset)) + && ref->e.address.lvalue->type == ex_alias + && (!ref->e.address.lvalue->e.alias.offset + || is_constant (ref->e.address.lvalue->e.alias.offset))) { + expr_t *lvalue = ref->e.address.lvalue; + expr_t *offs = ref->e.address.offset; + expr_t *alias; + if (lvalue->e.alias.offset) { + if (offs) { + offs = binary_expr ('+', offs, lvalue->e.alias.offset); + } else { + offs = lvalue->e.alias.offset; + } + } + type = type->t.fldptr.type; + if (offs) { + expr_t *lv = lvalue->e.alias.expr; + type_t *lvtype = get_type (lv); + int o = expr_int (offs); + if (o < 0 || o + type_size (type) > type_size (lvtype)) { + // not a valid offset for the type, which technically should + // be an error, but there may be legitimate reasons for doing + // such pointer shenanigans + goto just_a_pointer; + } + alias = new_offset_alias_expr (type, lv, expr_int (offs)); + } else { + alias = new_alias_expr (type, lvalue->e.alias.expr); + } + expr_file_line (alias, ref); + return addressing_mode (sblock, alias, base, offset, mode); + } else if (ref->type != ex_alias || ref->e.alias.offset) { // probably just a pointer +just_a_pointer: sblock = statement_subexpr (sblock, ref, base); *offset = short_operand (0, ref); *mode = 2; // mode C: ptr + constant index @@ -1468,6 +1505,15 @@ load_statement (operand_t *ptr, operand_t *offs, operand_t *op, expr_t *e) return s; } +static statement_t * +assign_statement (operand_t *dst, operand_t *src, expr_t *e) +{ + statement_t *s = new_statement (st_assign, "assign", e); + s->opa = dst; + s->opc = src; + return s; +} + static sblock_t * expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) { @@ -1476,10 +1522,21 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) operand_t *base = 0; operand_t *offset = 0; pr_ushort_t mode; + statement_t *s; sblock = addressing_mode (sblock, deref, &base, &offset, &mode); + if (!*op) { + *op = temp_operand (load_type, deref); + } + switch (mode) { + case 0://direct def access + // FIXME should check that offset is 0, but currently, + // addressing_mode always sets offset to 0 for mode 0 + s = assign_statement (*op, base, deref); + sblock_add_statement (sblock, s); + return sblock; case 1://entity.field case 2://const indexed pointer case 3://var indexed pointer @@ -1488,11 +1545,6 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) internal_error (deref, "unexpected addressing mode: %d", mode); } - if (!*op) { - *op = temp_operand (load_type, deref); - } - - statement_t *s; if (low_level_type (load_type) == ev_void) { s = lea_statement (base, offset, ptr_expr); sblock_add_statement (sblock, s); From 3d8ee5df438afb41b5a71739d5c8eb3cb4bf97a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Feb 2022 16:33:42 +0900 Subject: [PATCH 2384/3664] [qfcc] Ensure ops on globals occur before return This fixes the return-postop test, and covers calls, too. --- tools/qfcc/source/dags.c | 14 +++++++++++++- tools/qfcc/test/Makemodule.am | 3 +-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index d2f746962..6c787fdc6 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -462,7 +462,8 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n, statement_t *s) if (n->type == st_func) { const char *num_params = 0; int first_param = 0; - flowvar_t **flowvars = dag->flownode->graph->func->vars; + function_t *func = dag->flownode->graph->func; + flowvar_t **flowvars = func->vars; if (!strcmp (n->label->opcode, "call")) { // nothing to do @@ -482,6 +483,17 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n, statement_t *s) } label->live = 1; } + // ensure all operantions on global variables are completed before + // the st_func statement executes + for (set_iter_t *g = set_first (func->global_vars); g; + g = set_next (g)) { + flowvar_t *var = flowvars[g->element]; + dagnode_t *gn = dag_node (var->op); + if (gn) { + set_add (n->edges, gn->number); + set_remove (gn->edges, n->number); + } + } if (num_params && isdigit (*num_params)) { for (i = first_param; i < *num_params - '0'; i++) { flowvar_t *var = flowvars[i + 1]; diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index c82d750c4..f5111177e 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -68,8 +68,7 @@ test_progs_dat=\ tools/qfcc/test/while.dat \ tools/qfcc/test/zerolinker.dat -fail_progs_dat=\ - tools/qfcc/test/return-postop.dat +fail_progs_dat= test_build_errors=\ tools/qfcc/test/classarray.r \ From bbac02de24b2064e80c66c5cf1cdee88f39c5df4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Jan 2022 12:05:50 +0900 Subject: [PATCH 2385/3664] [qfcc] Add failing test for return of postop Commit 76b3bedb72a0a1b92e658c733bf6ff079d18ce10 broke more than just the swap test, but at least I know I need to get an edge in the dag. Currently, the following code is generated: return and add are reversed. ../tools/qfcc/test/return-postop.r:8: return counter++; 0001 store.i counter, .tmp0 0002 return .tmp0 0003 add.i .tmp0, (1), counter However, I don't want to deal with it right now, so it's marked XFAIL. --- tools/qfcc/test/Makemodule.am | 14 +++++++++++++- tools/qfcc/test/return-postop.r | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tools/qfcc/test/return-postop.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index d5929e0a6..9f4caac0a 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -41,6 +41,7 @@ test_progs_dat=\ tools/qfcc/test/ptrstructcast.dat \ tools/qfcc/test/quaternion.dat \ tools/qfcc/test/return-ivar.dat \ + tools/qfcc/test/return-postop.dat \ tools/qfcc/test/sendv.dat \ tools/qfcc/test/state.dat \ tools/qfcc/test/static-init.dat \ @@ -62,7 +63,8 @@ test_progs_dat=\ tools/qfcc/test/while.dat \ tools/qfcc/test/zerolinker.dat -fail_progs_dat= +fail_progs_dat=\ + tools/qfcc/test/return-postop.dat test_build_errors=\ tools/qfcc/test/classarray.r \ @@ -481,6 +483,16 @@ tools/qfcc/test/return-ivar.run: $(qfcc_test_run_deps) include $(return_ivar_dep) # am--include-marker r_depfiles_remade += $(return_ivar_dep) +tools_qfcc_test_return_postop_dat_SOURCES=tools/qfcc/test/return-postop.r +return_postop_obj=$(tools_qfcc_test_return_postop_dat_SOURCES:.r=.o) +return_postop_dep=$(call qcautodep,$(tools_qfcc_test_return_postop_dat_SOURCES)) +tools/qfcc/test/return-postop.dat$(EXEEXT): $(return_postop_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(return_postop_obj) +tools/qfcc/test/return-postop.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(return_postop_dep) # am--include-marker +r_depfiles_remade += $(return_postop_dep) + tools_qfcc_test_sendv_dat_SOURCES=tools/qfcc/test/sendv.r sendv_obj=$(tools_qfcc_test_sendv_dat_SOURCES:.r=.o) sendv_dep=$(call qcautodep,$(tools_qfcc_test_sendv_dat_SOURCES)) diff --git a/tools/qfcc/test/return-postop.r b/tools/qfcc/test/return-postop.r new file mode 100644 index 000000000..5ec27f4a1 --- /dev/null +++ b/tools/qfcc/test/return-postop.r @@ -0,0 +1,22 @@ +#include "test-harness.h" + +int counter; + +int +function (void) +{ + return counter++; +} + +int +main (void) +{ + int ret = 0; + counter = 0; + function (); + if (counter != 1) { + printf ("counter != 1: %d\n", counter); + ret = 1; + } + return ret; +} From ca818eaff8047986df33ba80ec7bc0d0a1104228 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Feb 2022 16:33:42 +0900 Subject: [PATCH 2386/3664] [qfcc] Ensure ops on globals occur before return This fixes the return-postop test, and covers calls, too. --- tools/qfcc/source/dags.c | 14 +++++++++++++- tools/qfcc/test/Makemodule.am | 3 +-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 9e3b1cdab..57ed83545 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -450,7 +450,8 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) if (n->type == st_func) { const char *num_params = 0; int first_param = 0; - flowvar_t **flowvars = dag->flownode->graph->func->vars; + function_t *func = dag->flownode->graph->func; + flowvar_t **flowvars = func->vars; if (!strncmp (n->label->opcode, "label->opcode + 6; @@ -468,6 +469,17 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n) } label->live = 1; } + // ensure all operantions on global variables are completed before + // the st_func statement executes + for (set_iter_t *g = set_first (func->global_vars); g; + g = set_next (g)) { + flowvar_t *var = flowvars[g->element]; + dagnode_t *gn = dag_node (var->op); + if (gn) { + set_add (n->edges, gn->number); + set_remove (gn->edges, n->number); + } + } if (num_params && isdigit (*num_params)) { for (i = first_param; i < *num_params - '0'; i++) { flowvar_t *var = flowvars[i + 1]; diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 9f4caac0a..08137d7e3 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -63,8 +63,7 @@ test_progs_dat=\ tools/qfcc/test/while.dat \ tools/qfcc/test/zerolinker.dat -fail_progs_dat=\ - tools/qfcc/test/return-postop.dat +fail_progs_dat= test_build_errors=\ tools/qfcc/test/classarray.r \ From 1487fa6b5058562ec3d7cbee6cb87070949fc45c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 00:25:31 +0900 Subject: [PATCH 2387/3664] [qfcc] Implement some basics for the vector types They're now properly part of the type system and can be used for declaring variables, initialized (using {} block initializers), operated on (=, *, + tested) though much work needs to be done on binary expressions, and indexed. So far, only ivec2 has been tested. --- tools/qfcc/include/type.h | 7 ++-- tools/qfcc/include/vec_types.h | 24 ++++++++++++++ tools/qfcc/source/def.c | 2 +- tools/qfcc/source/expr.c | 37 +++++++++++++++------ tools/qfcc/source/expr_binary.c | 10 ++++++ tools/qfcc/source/expr_compound.c | 53 ++++++++++++++++++++----------- tools/qfcc/source/qc-lex.l | 24 +++++++++++--- tools/qfcc/source/type.c | 46 +++++++++++++++------------ 8 files changed, 146 insertions(+), 57 deletions(-) create mode 100644 tools/qfcc/include/vec_types.h diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 7a213dd98..cafa1da91 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -104,10 +104,8 @@ typedef struct { #define EV_TYPE(type) extern type_t type_##type; #include "QF/progs/pr_type_names.h" -extern type_t type_ivec3; -extern type_t type_ivec4; -extern type_t type_vec3; -extern type_t type_vec4; +#define VEC_TYPE(type_name, base_type) extern type_t type_##type_name; +#include "tools/qfcc/include/vec_types.h" extern type_t type_invalid; extern type_t type_floatfield; @@ -167,6 +165,7 @@ const char *type_get_encoding (const type_t *type); int is_enum (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); +int is_real (const type_t *type) __attribute__((pure)); int is_scalar (const type_t *type) __attribute__((pure)); int is_nonscalar (const type_t *type) __attribute__((pure)); int is_math (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/include/vec_types.h b/tools/qfcc/include/vec_types.h new file mode 100644 index 000000000..4931c8d09 --- /dev/null +++ b/tools/qfcc/include/vec_types.h @@ -0,0 +1,24 @@ +#ifndef VEC_TYPE +#define VEC_TYPE(type_name, base_type) +#endif + +VEC_TYPE(ivec2, int) +VEC_TYPE(ivec3, int) +VEC_TYPE(ivec4, int) +VEC_TYPE(vec2, float) +VEC_TYPE(vec3, float) +VEC_TYPE(vec4, float) +VEC_TYPE(lvec2, long) +VEC_TYPE(lvec3, long) +VEC_TYPE(lvec4, long) +VEC_TYPE(dvec2, double) +VEC_TYPE(dvec3, double) +VEC_TYPE(dvec4, double) +VEC_TYPE(uivec2, uint) +VEC_TYPE(uivec3, uint) +VEC_TYPE(uivec4, uint) +VEC_TYPE(ulvec2, ulong) +VEC_TYPE(ulvec3, ulong) +VEC_TYPE(ulvec4, ulong) + +#undef VEC_TYPE diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 44c3d74c6..cf2a70c10 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -584,7 +584,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, if (init->type == ex_error) return; if ((is_array (sym->type) || is_struct (sym->type) - || is_vector(sym->type) || is_quaternion(sym->type)) + || is_nonscalar (sym->type)) && ((init->type == ex_compound) || init->type == ex_nil)) { init_elements (sym->s.def, init); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 341f6d7a9..21951799c 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2549,6 +2549,7 @@ array_expr (expr_t *array, expr_t *index) { type_t *array_type = get_type (array); type_t *index_type = get_type (index); + type_t *ele_type; expr_t *scale; expr_t *offset; expr_t *base; @@ -2561,7 +2562,8 @@ array_expr (expr_t *array, expr_t *index) if (index->type == ex_error) return index; - if (!is_ptr (array_type) && !is_array (array_type)) + if (!is_ptr (array_type) && !is_array (array_type) + && !is_nonscalar (array_type)) return error (array, "not an array"); if (!is_integral (index_type)) return error (index, "invalid array index type"); @@ -2573,11 +2575,26 @@ array_expr (expr_t *array, expr_t *index) && array_type->t.array.size && is_constant (index) && (ind < array_type->t.array.base - || ind - array_type->t.array.base >= array_type->t.array.size)) - return error (index, "array index out of bounds"); - scale = new_int_expr (type_size (array_type->t.array.type)); + || ind - array_type->t.array.base >= array_type->t.array.size)) { + return error (index, "array index out of bounds"); + } + if (is_nonscalar (array_type) + && is_constant (index) + && (ind < 0 || ind >= array_type->width)) { + return error (index, "array index out of bounds"); + } + if (is_array (array_type)) { + ele_type = array_type->t.array.type; + base = new_int_expr (array_type->t.array.base); + } else if (is_ptr (array_type)) { + ele_type = array_type->t.fldptr.type; + base = new_int_expr (0); + } else { + ele_type = ev_types[array_type->type]; + base = new_int_expr (0); + } + scale = new_int_expr (type_size (ele_type)); index = binary_expr ('*', index, scale); - base = new_int_expr (array_type->t.array.base); offset = binary_expr ('*', base, scale); index = binary_expr ('-', index, offset); if (is_short_val (index)) @@ -2585,18 +2602,20 @@ array_expr (expr_t *array, expr_t *index) if (is_int_val (index)) ind = expr_int (index); if (is_array (array_type)) { - type_t *element_type = array_type->t.array.type; if (array->type == ex_uexpr && array->e.expr.op == '.') { ptr = array->e.expr.e1; } else { - expr_t *alias = new_offset_alias_expr (element_type, array, 0); - ptr = new_address_expr (element_type, alias, 0); + expr_t *alias = new_offset_alias_expr (ele_type, array, 0); + ptr = new_address_expr (ele_type, alias, 0); } + } else if (is_nonscalar (array_type)) { + expr_t *alias = new_offset_alias_expr (ele_type, array, 0); + ptr = new_address_expr (ele_type, alias, 0); } else { ptr = array; } ptr = offset_pointer_expr (ptr, index); - ptr = cast_expr (pointer_type (array_type->t.array.type), ptr); + ptr = cast_expr (pointer_type (ele_type), ptr); e = unary_expr ('.', ptr); return e; diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 5bd004d42..162a15147 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -1005,6 +1005,16 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return invalid_binary_expr(op, e1, e2); if (et2 >= ev_type_count || !binary_expr_types[et1][et2]) return invalid_binary_expr(op, e1, e2); + + if ((t1->width > 1 || t2->width > 1)) { + if (t1 != t2) { + return invalid_binary_expr (op, e1, e2); + } + e = new_binary_expr (op, e1, e2); + e->e.expr.type = t1; + return e; + } + expr_type = binary_expr_types[et1][et2]; while (expr_type->op && expr_type->op != op) expr_type++; diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c index e75bb5b70..e8b81747d 100644 --- a/tools/qfcc/source/expr_compound.c +++ b/tools/qfcc/source/expr_compound.c @@ -82,6 +82,31 @@ new_compound_init (void) return c; } +static element_t * +build_array_element_chain(element_chain_t *element_chain, + int array_size, type_t *array_type, + element_t *ele, + int base_offset) +{ + for (int i = 0; i < array_size; i++) { + int offset = base_offset + i * type_size (array_type); + if (ele && ele->expr && ele->expr->type == ex_compound) { + build_element_chain (element_chain, array_type, + ele->expr, offset); + } else { + element_t *element = new_element (0, 0); + element->type = array_type; + element->offset = offset; + element->expr = ele ? ele->expr : 0; // null -> nil + append_init_element (element_chain, element); + } + if (ele) { + ele = ele->next; + } + } + return ele; +} + void build_element_chain (element_chain_t *element_chain, const type_t *type, expr_t *eles, int base_offset) @@ -93,25 +118,9 @@ build_element_chain (element_chain_t *element_chain, const type_t *type, if (is_array (type)) { type_t *array_type = type->t.array.type; int array_size = type->t.array.size; - int i; - - for (i = 0; i < array_size; i++) { - int offset = base_offset + i * type_size (array_type); - if (ele && ele->expr && ele->expr->type == ex_compound) { - build_element_chain (element_chain, array_type, - ele->expr, offset); - } else { - element_t *element = new_element (0, 0); - element->type = array_type; - element->offset = offset; - element->expr = ele ? ele->expr : 0; // null -> nil - append_init_element (element_chain, element); - } - if (ele) { - ele = ele->next; - } - } - } else if (is_struct (type) || is_vector (type) || is_quaternion (type)) { + ele = build_array_element_chain (element_chain, array_size, array_type, + ele, base_offset); + } else if (is_struct (type) || (is_nonscalar (type) && type->t.symtab)) { symtab_t *symtab = type->t.symtab; symbol_t *field; @@ -135,6 +144,12 @@ build_element_chain (element_chain_t *element_chain, const type_t *type, ele = ele->next; } } + } else if (is_nonscalar (type)) { + // vector type with unnamed components + int vec_width = type_width (type); + type_t *vec_type = ev_types[type->type]; + ele = build_array_element_chain (element_chain, vec_width, vec_type, + ele, base_offset); } else { error (eles, "invalid initializer"); } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 3c8e28ec9..e0467f1ef 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -311,6 +311,13 @@ typedef struct { type_t *type; } keyword_t; +// These keywords are part of the Ruamoko language and require the QuakeForge +// Ruamoko VM. +static keyword_t rua_keywords[] = { +#define VEC_TYPE(type_name, base_type) { #type_name, TYPE, &type_##type_name }, +#include "tools/qfcc/include/vec_types.h" +}; + // These keywords are all part of the Ruamoko (Objective-QC) language. // The first time any one of them is encountered, the class system will be // initialized. @@ -450,6 +457,7 @@ keyword_or_id (char *token) static hashtab_t *qf_keyword_tab; static hashtab_t *at_keyword_tab; static hashtab_t *obj_keyword_tab; + static hashtab_t *rua_keyword_tab; keyword_t *keyword = 0; symbol_t *sym; @@ -461,6 +469,7 @@ keyword_or_id (char *token) qf_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); at_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); obj_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); + rua_keyword_tab = Hash_NewTable (253, keyword_get_key, 0, 0, 0); #define NUMKEYS(_k) (sizeof (_k) / sizeof (_k[0])) @@ -472,12 +481,19 @@ keyword_or_id (char *token) Hash_Add (at_keyword_tab, &at_keywords[i]); for (i = 0; i < NUMKEYS(obj_keywords); i++) Hash_Add (obj_keyword_tab, &obj_keywords[i]); + for (i = 0; i < NUMKEYS(rua_keywords); i++) + Hash_Add (rua_keyword_tab, &rua_keywords[i]); } if (options.traditional < 1) { - keyword = Hash_Find (obj_keyword_tab, token); - if (keyword) { - if (!obj_initialized) - class_init (); + if (options.code.progsversion == PROG_VERSION) { + keyword = Hash_Find (rua_keyword_tab, token); + } + if (!keyword) { + keyword = Hash_Find (obj_keyword_tab, token); + if (keyword) { + if (!obj_initialized) + class_init (); + } } if (!keyword) keyword = Hash_Find (qf_keyword_tab, token); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 9f94affae..b0882519c 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -79,18 +79,15 @@ type_t type_invalid = { .name = "invalid", }; -#define VTYPE(t, b) \ - type_t type_##t = { \ - .type = ev_##b, \ - .name = #t, \ - .alignment = PR_ALIGNOF(t), \ - .width = PR_SIZEOF(t) / PR_SIZEOF (b), \ +#define VEC_TYPE(type_name, base_type) \ + type_t type_##type_name = { \ + .type = ev_##base_type, \ + .name = #type_name, \ + .alignment = PR_ALIGNOF(type_name), \ + .width = PR_SIZEOF(type_name) / PR_SIZEOF (base_type), \ .meta = ty_basic, \ }; -VTYPE(ivec3, int) -VTYPE(ivec4, int) -VTYPE(vec3, float) -VTYPE(vec4, float) +#include "tools/qfcc/include/vec_types.h" type_t *type_nil; type_t *type_default; @@ -947,6 +944,13 @@ is_integral (const type_t *type) return is_enum (type); } +int +is_real (const type_t *type) +{ + type = unalias_type (type); + return is_float (type) || is_double (type); +} + int is_scalar (const type_t *type) { @@ -958,7 +962,7 @@ is_scalar (const type_t *type) if (type->width != 1) { return 0; } - return is_float (type) || is_integral (type) || is_double (type); + return is_real (type) || is_integral (type); } int @@ -968,7 +972,7 @@ is_nonscalar (const type_t *type) if (type->width < 2) { return 0; } - return is_float (type) || is_integral (type) || is_double (type); + return is_real (type) || is_integral (type); } int @@ -1144,20 +1148,21 @@ type_width (const type_t *type) static void chain_basic_types (void) { + type_entity.t.symtab = pr.entity_fields; + if (options.code.progsversion == PROG_VERSION) { + type_quaternion.alignment = 4; + } + chain_type (&type_void); chain_type (&type_string); chain_type (&type_float); chain_type (&type_vector); - type_entity.t.symtab = pr.entity_fields; chain_type (&type_entity); chain_type (&type_field); chain_type (&type_func); chain_type (&type_ptr); chain_type (&type_floatfield); if (!options.traditional) { - if (options.code.progsversion == PROG_VERSION) { - type_quaternion.alignment = 4; - } chain_type (&type_quaternion); chain_type (&type_int); chain_type (&type_uint); @@ -1165,10 +1170,11 @@ chain_basic_types (void) chain_type (&type_double); if (options.code.progsversion == PROG_VERSION) { - chain_type (&type_ivec3); - chain_type (&type_ivec4); - chain_type (&type_vec3); - chain_type (&type_vec4); + chain_type (&type_long); + chain_type (&type_ulong); + chain_type (&type_ushort); +#define VEC_TYPE(name, type) chain_type (&type_##name); +#include "tools/qfcc/include/vec_types.h" } } } From 52a399daeb8e80f76882aee0e13d469ac35be837 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 08:46:58 +0900 Subject: [PATCH 2388/3664] [qfcc] Update sizes and alignments for dvec4 and friends dvec4, lvec4 and ulvec4 need to be aligned to 8 words (32 bytes) in order to avoid hardware exceptions. Rather than dealing with possibly mixed alignment when a function has 8-word aligned locals but only 4-word aligned parameters, simply keep the stack frame 8-word aligned at all times. As for sizes, the temp def recycler was written before the Ruamoko ISA was even a pipe dream and thus never expected temp def sizes over 4. At least now any future adjustments can be done in one place. My quick and dirty test program works :) dvec4 xy = {1d, 2d, 0d, 0.5}; void printf(string fmt, ...) = #0; int main() { dvec4 u = {3, 4, 3.14}; dvec4 v = {3, 4, 0, 1}; dvec4 w = v * xy + u; printf ("[%g, %g, %g, %g]\n", w[0], w[1], w[2], w[3]); return 0; } --- tools/qfcc/include/function.h | 4 +++- tools/qfcc/source/def.c | 2 +- tools/qfcc/source/function.c | 16 ++++++++++------ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 3a089a4c2..83b455555 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -41,6 +41,8 @@ #include "def.h" +#define MAX_DEF_SIZE ((int)PR_SIZEOF(lvec4)) + /** Represent an overloading of a function. Every function, whether overloaded or not, has an entry in the overloaded @@ -71,7 +73,7 @@ typedef struct function_s { const struct type_s *type; ///< function's type without aliases int temp_reg; ///< base register to use for temp defs int temp_num; ///< number for next temp var - struct def_s *temp_defs[4]; ///< freed temp vars (by size) + struct def_s *temp_defs[MAX_DEF_SIZE];///< freed temp vars (by size) struct def_s *def; ///< output def holding function number struct symbol_s *sym; ///< internal symbol for this function /** \name Local data space diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index cf2a70c10..849723a44 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -209,7 +209,7 @@ temp_def (type_t *type) int size = type_size (type); int alignment = type->alignment; - if (size < 1 || size > 4) { + if (size < 1 || size > MAX_DEF_SIZE) { internal_error (0, "%d invalid size for temp def", size); } if (alignment < 1) { diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index c85b68edf..42f757b9e 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -74,6 +74,9 @@ static hashtab_t *function_map; // standardized base register to use for all locals (arguments, local defs, // params) #define LOCALS_REG 1 +// keep the stack aligned to 8 words (32 bytes) so lvec etc can be used without +// having to do shenanigans with mixed-alignment stack frames +#define STACK_ALIGN 8 static const char * ol_func_get_key (const void *_f, void *unused) @@ -785,26 +788,27 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) if (func->arguments) { func->arguments->size = func->arguments->max_size; - merge_spaces (space, func->arguments, 4); + merge_spaces (space, func->arguments, STACK_ALIGN); func->arguments = 0; } - merge_spaces (space, func->locals->space, 4); + merge_spaces (space, func->locals->space, STACK_ALIGN); func->locals->space = space; // allocate 0 words to force alignment and get the address - func->params_start = defspace_alloc_aligned_highwater (space, 0, 4); + func->params_start = defspace_alloc_aligned_highwater (space, 0, + STACK_ALIGN); dstatement_t *st = &pr.code->code[func->code]; if (st->op == OP_ADJSTK) { st->b = -func->params_start; } - merge_spaces (space, func->parameters->space, 4); + merge_spaces (space, func->parameters->space, STACK_ALIGN); func->parameters->space = space; // force the alignment again so the full stack slot is counted when - // the final parameter is smaller than 4 words - defspace_alloc_aligned_highwater (space, 0, 4); + // the final parameter is smaller than STACK_ALIGN words + defspace_alloc_aligned_highwater (space, 0, STACK_ALIGN); } return fsym->s.func; } From f3770cc64757f60bdcda39487cc48df608b27bd4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 09:27:07 +0900 Subject: [PATCH 2389/3664] [qfcc] Add --ruamoko command line option and pragma The command line option works the same way as --advanced/traditional/extended, as does the pragma. As well, raumoko (alternative spelling) can be used because both are legitimate and some people may prefer one spelling over the other. As always, use of the pragma is at one's own risk: its intended use is forcing the target in the unit tests. --- tools/qfcc/include/options.h | 2 +- tools/qfcc/source/options.c | 34 +++++++++++++++++++++++----------- tools/qfcc/source/pragma.c | 18 +++++++++++++++--- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index 580f97370..0c274bf7c 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -109,7 +109,7 @@ typedef struct { qboolean progdefs_h; // generate progdefs.h qboolean qccx_escapes; // use qccx escapes instead of standard C int traditional; // behave more like qcc - qboolean advanced; // behold the power of Ruamoko + int advanced; // behold the power of Ruamoko qboolean compile; // serparate compilation mode qboolean partial_link; // partial linking qboolean preprocess_only;// run only cpp, don't compile diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 573730986..e5ccf0805 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -69,6 +69,7 @@ enum { OPT_NO_DEFAULT_PATHS, OPT_PROGDEFS, OPT_QCCX_ESCAPES, + OPT_RUAMOKO, OPT_TRADITIONAL, OPT_BUG, }; @@ -92,7 +93,9 @@ static struct option const long_options[] = { {"progs-src", required_argument, 0, 'P'}, {"qccx-escapes", no_argument, 0, OPT_QCCX_ESCAPES}, {"quiet", no_argument, 0, 'q'}, + {"raumoko", no_argument, 0, OPT_RUAMOKO}, {"relocatable", no_argument, 0, 'r'}, + {"ruamoko", no_argument, 0, OPT_RUAMOKO}, {"save-temps", no_argument, 0, 'S'}, {"source", required_argument, 0, 's'}, {"traditional", no_argument, 0, OPT_TRADITIONAL}, @@ -394,16 +397,22 @@ DecodeArgs (int argc, char **argv) break; case OPT_TRADITIONAL: options.traditional = 2; - options.advanced = false; + options.advanced = 0; options.code.progsversion = PROG_ID_VERSION; options.code.const_initializers = true; break; case OPT_ADVANCED: options.traditional = 0; - options.advanced = true; + options.advanced = 1; options.code.progsversion = PROG_V6P_VERSION; options.code.const_initializers = false; break; + case OPT_RUAMOKO: + options.traditional = 0; + options.advanced = 2; + options.code.progsversion = PROG_VERSION; + options.code.const_initializers = false; + break; case OPT_BLOCK_DOT: if (optarg) { char *opts = strdup (optarg); @@ -693,7 +702,7 @@ DecodeArgs (int argc, char **argv) if (saw_MD) options.preprocess_only = 0; if (!source_files && !options.advanced) { - // progs.src mode without --advanced implies --traditional + // progs.src mode without --advanced or --ruamoko implies --traditional // but --extended overrides if (!options.traditional) options.traditional = 2; @@ -712,14 +721,10 @@ DecodeArgs (int argc, char **argv) if (!options.code.progsversion) options.code.progsversion = PROG_V6P_VERSION; if (!options.traditional) { - options.advanced = true; - if (options.code.progsversion < PROG_VERSION) { - add_cpp_def ("-D__RUAMOKO__=1"); - add_cpp_def ("-D__RAUMOKO__=1"); - } else { - add_cpp_def ("-D__RUAMOKO__=2"); - add_cpp_def ("-D__RAUMOKO__=2"); - } + // avanced=2 requires the Ruamoko ISA + options.advanced = 2 - (options.code.progsversion < PROG_VERSION); + const char *ruamoko = va (0, "-D__RUAMOKO__=%d", options.advanced); + add_cpp_def (save_string (ruamoko)); if (options.code.ifstring == (qboolean) -1) options.code.ifstring = false; if (options.code.short_circuit == (qboolean) -1) @@ -741,6 +746,13 @@ DecodeArgs (int argc, char **argv) options.code.crc = false; } + if (options.traditional && options.advanced) { + fprintf (stderr, + "%s: internal error: traditional and advanced twisted\n", + this_program); + abort (); + } + // add the default paths if (!options.no_default_paths) { add_cpp_sysinc ("-isystem"); diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index fb72130f4..9d107edab 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -63,21 +63,31 @@ static void set_traditional (int traditional) { switch (traditional) { + case -1: + options.traditional = 0; + options.advanced = 2; + options.code.progsversion = PROG_VERSION; + type_default = &type_int; + type_long_int = &type_long; + type_ulong_uint = &type_ulong; + break; case 0: options.traditional = 0; - options.advanced = true; + options.advanced = 1; options.code.progsversion = PROG_V6P_VERSION; type_default = &type_int; + type_long_int = &type_int; + type_ulong_uint = &type_uint; break; case 1: options.traditional = 1; - options.advanced = false; + options.advanced = 0; options.code.progsversion = PROG_ID_VERSION; type_default = &type_float; break; case 2: options.traditional = 2; - options.advanced = false; + options.advanced = 0; options.code.progsversion = PROG_ID_VERSION; type_default = &type_float; break; @@ -157,6 +167,8 @@ pragma_process () set_traditional (1); } else if (!strcmp (id, "advanced")) { set_traditional (0); + } else if (!strcmp (id, "ruamoko") || !strcmp (id, "raumoko")) { + set_traditional (-1); } else if (!strcmp (id, "bug")) { set_bug (pragma_args->next); } else if (!strcmp (id, "warn")) { From 26fca581fca7bf4ec2e7a3d4baa94f61e2d4f0fa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 10:46:31 +0900 Subject: [PATCH 2390/3664] [qfcc] Make ruamoko the default and update the docs It's time to do the dog-food. --- tools/qfcc/doc/man/qfcc.1 | 69 ++++++++++++++++++++++++++----------- tools/qfcc/source/options.c | 7 ++-- 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/tools/qfcc/doc/man/qfcc.1 b/tools/qfcc/doc/man/qfcc.1 index 893070824..0541458dd 100644 --- a/tools/qfcc/doc/man/qfcc.1 +++ b/tools/qfcc/doc/man/qfcc.1 @@ -56,8 +56,10 @@ understand. .TP .B \-\-advanced -Use advanced Ruamoko features. -This is the default when using separate compilation. +Use advanced Ruamoko language features limited to the v6p ISA. This +provides access to structs, arrays, pointers, integers, quaternions, +doubles and object-oriented features mostly compatible with Objective-C +(ie, Objective-QuakeC). For access to SIMD vector types, see --ruamoko. .TP .B \-C, \-\-code OPTION,... @@ -179,6 +181,15 @@ Counteracts the effects of \fB-v\fP. Incremental linking. Generate a larger object file from other object files and libraries. +.TP +.B \-\-raumoko, \-\-ruamoko +In addition to the Ruamoko language features added by --advanced, this +option provides access to SIMD vector types (and instructions), a data +stack for local variables and parameters (allowing pointers to local +variables to be passed to other functions!), and other features still +under development. +This is the default when using separate compilation. + .TP .B \-S, \-\-save\-temps Do not delete temporary files. @@ -346,16 +357,17 @@ Also disables compiler features (such as integers and string manipulation support) that require extensions. .TP .B v6p -Quakeforge extended v6 instructions. -This is not compatible with older server, nor with most (any?) other Quake -engine. It adds a variety of instructions and types, including integers, +QuakeForge extended v6 instructions. +This is not compatible with older servers, nor with most (any?) other Quake +engines. It adds a variety of instructions and types, including integers, quaternions, pointers, doubles, structs, arrays and Objective-C style classes. .TP .B ruamoko -Quakeforge SIMD instructions. This is currently under development -and thus not the default. +QuakeForge SIMD and stack instructions. .RE -Defaults to v6 for traditional mode and v6p for advanced mode. +Defaults to v6 for traditional mode, v6p for advanced mode, and ruamoko +for Ruamoko mode (actually, trying to take Ruamoko's power after +granting it may not end well). .SH "WARNING OPTIONS" @@ -718,13 +730,13 @@ gold digits. \fB\-\-qccx\-escapes\fP has no effect on sequences that do not conflict. -.SH TRADITIONAL VS ADVANCED -Compared to \fBqcc\fP, \*[qfcc] has many advanced features and is much stricter -about type checking. +.SH TRADITIONAL VS ADVANCED VS RUAMOKO +Compared to \fBqcc\fP, \*[qfcc] has many advanced features and is much +stricter about type checking. \*[qfcc] also uses the same operator semantics and precedence rules as standard \fBC\fP. -Unfortunately, this means that most older QuakeC code will not compile, or even -worse, will compile incorrectly. +Unfortunately, this means that most older QuakeC code will not compile, +or even worse, will compile incorrectly. .P To address this situation, \*[qfcc] has a \*(lqtraditional\*(rq mode for compiling old progs. @@ -732,20 +744,32 @@ This mode, enabled with \fB--traditional\fP or by default in \fBprogs.src\fP mode, removes the new keywords required by \*[qfcc]'s advanced features, converts new errors to warnings, some warnings to notices and inverts precedence order where required (eg, (!var & flag)). -Traditional mode also affects several code generation options (as always, this -can be overridden): +Traditional mode also affects several code generation options (as +always, this can be overridden): .IP \(bu 4 code output is restricted to version 6 progs instructions .IP \(bu 4 short circuit boolean logic is disabled .IP \(bu 4 -each function has a private area of data for its local variables (this wastes -a lot of data space). +each function has a private area of data for its local variables (this +wastes a lot of data space). .P -Advanced mode is simply \*[qfcc] in its natural state. -Using \fB--advanced\fP, \*[qfcc] can be put in to advanced mode while using the -\fBprogs.src\fP compilation mode. +Advanced mode is \*[qfcc] in what was its natural state until the +introduction of Ruamoko mode. Advanced mode adds several data types and +Objective-C object oriented programming. +Using \fB--advanced\fP, \*[qfcc] can be put in to advanced mode while +using the \fBprogs.src\fP compilation mode. +.P +Ruamoko mode is \*[qfcc] in its natural state. On top of the features +added by Advanced mode, Ruamoko mode adds SIMD types and instructions, +and a data stack for locals and parameters. +.SH RUAMOKO PROGRAMMING LANGUAGE +Ruamoko evolved from the original QuakeC language, gaining standard C +syntax and most features (the char type is not supported, and function +pointers are a little weird (design bug?)), Objective-C object oriented +extensions, and (with the Ruamoko ISA) SIMD vectors and the ability to +pass pointers to local variables to other functions. .SH "FAQ" @@ -756,6 +780,11 @@ Sky-father, and Papatuanuku, the Earth-mother. Ruamoko is the god of volcanoes and earthquakes. For more information, see the Web site at <\fBhttp://maori.com/kmst1.htm\fP>. +.TP +.B Why both Ruamoko and Raumoko? +They are alternative spellings and pronunciations. Use whichever one you +prefer. + .TP .B qfcc hangs This is almost always caused by qfcc incorrectly invoking \*[cpp]. diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index e5ccf0805..c8a0a7ff0 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -142,7 +142,6 @@ usage (int status) printf ( "Options:\n" " --advanced Advanced Ruamoko mode\n" -" default for separate compilation mode\n" " --bug OPTION,... Set bug options\n" " -C, --code OPTION,... Set code generation options\n" " -c Only compile, don't link\n" @@ -172,6 +171,10 @@ usage (int status) " C/QuakeForge sequences.\n" " -q, --quiet Inhibit usual output\n" " -r, --relocatable Incremental linking\n" +" --raumoko Use both Ruamoko language features and the\n" +" --ruamoko Ruamoko ISA, providing access to SIMD types\n" +" and a stack for locals.\n" +" default for separate compilation mode\n" " -S, --save-temps Do not delete temporary files\n" " -s, --source DIR Look for progs.src in DIR instead of \".\"\n" " --traditional Traditional QuakeC mode: implies v6only\n" @@ -719,7 +722,7 @@ DecodeArgs (int argc, char **argv) options.code.vector_components = true; } if (!options.code.progsversion) - options.code.progsversion = PROG_V6P_VERSION; + options.code.progsversion = PROG_VERSION; if (!options.traditional) { // avanced=2 requires the Ruamoko ISA options.advanced = 2 - (options.code.progsversion < PROG_VERSION); From b425f449b62c708e053e6d4ec812ac02440b4c46 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 11:38:36 +0900 Subject: [PATCH 2391/3664] [ruamoko] Separate the two str_mid builtins pr_argc cannot be used in Ruamoko progs because nothing sets it. This fixes the parse errors and resulting segfault when trying to parse the Vulkan pipeline config. --- libs/ruamoko/rua_string.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 4fdbab706..314c6d099 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -175,17 +175,10 @@ bi_str_clear (progs_t *pr) } static void -bi_str_mid (progs_t *pr) +str_mid (progs_t *pr, const char *str, int pos, int end, int size) { - const char *str = P_GSTRING (pr, 0); - int pos = P_INT (pr, 1); - int end = P_INT (pr, 2); - int size = strlen (str); char *temp; - if (pr->pr_argc == 2) - end = size; - R_STRING (pr) = 0; if (pos < 0) pos += size; @@ -205,6 +198,27 @@ bi_str_mid (progs_t *pr) RETURN_STRING (pr, temp); } +static void +bi_str_mid_2 (progs_t *pr) +{ + const char *str = P_GSTRING (pr, 0); + int pos = P_INT (pr, 1); + int size = strlen (str); + + str_mid (pr, str, pos, size, size); +} + +static void +bi_str_mid_3 (progs_t *pr) +{ + const char *str = P_GSTRING (pr, 0); + int pos = P_INT (pr, 1); + int end = P_INT (pr, 2); + int size = strlen (str); + + str_mid (pr, str, pos, end, size); +} + static void bi_str_str (progs_t *pr) { @@ -316,8 +330,8 @@ static builtin_t builtins[] = { bi(str_copy, 2, p(string), p(string)), bi(str_cat, 2, p(string), p(string)), bi(str_clear, 1, p(string)), - {"str_mid|*i", bi_str_mid, -1, 2, {p(string), p(int)}}, - {"str_mid|*ii", bi_str_mid, -1, 3, {p(string), p(int), p(int)}}, + {"str_mid|*i", bi_str_mid_2, -1, 2, {p(string), p(int)}}, + {"str_mid|*ii", bi_str_mid_3, -1, 3, {p(string), p(int), p(int)}}, bi(str_str, 2, p(string), p(string)), bi(str_char, 2, p(string), p(int)), bi(str_quote, 1, p(string)), From 974af36d138e2b494a980defcfddcc6ec7da349b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 21:46:40 +0900 Subject: [PATCH 2392/3664] [gamecode] Move profile out of the union It happens to sit over the builtin data pointer and thus messes up PR_Profile (any attempt to count calls to builtins). --- include/QF/progs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 5a00afd46..f5ffb1a94 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1255,13 +1255,13 @@ typedef struct { typedef struct { pr_int_t first_statement; pr_int_t numparams; + pr_ulong_t profile; union { struct { dparmsize_t param_size[PR_MAX_PARAMS]; dfunction_t *descriptor; pr_uint_t params_start; pr_uint_t locals; - pr_uint_t profile; }; struct { // although Ruamoko progs support more than PR_MAX_PARAMS From 7731c469e23217419301262a5c94fef8ec67ffb6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 21:49:59 +0900 Subject: [PATCH 2393/3664] [gamecode] Count calls to builtins in profile It's a bit disconcerting seeing a builtin in the top 10 when builtins are counted by call while progs functions are counted by instruction. Also, show the total profile after the function top-10 list. --- libs/gamecode/pr_debug.c | 14 +++++++++++--- libs/gamecode/pr_exec.c | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 041963233..67f6b981e 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1787,11 +1787,17 @@ PR_StackTrace (progs_t *pr) VISIBLE void PR_Profile (progs_t * pr) { - pr_uint_t max, num, i; + pr_ulong_t max, num, i; + pr_ulong_t total; dfunction_t *f; bfunction_t *best, *bf; num = 0; + total = 0; + for (i = 0; i < pr->progs->functions.count; i++) { + bf = &pr->function_table[i]; + total += bf->profile; + } do { max = 0; best = NULL; @@ -1805,13 +1811,15 @@ PR_Profile (progs_t * pr) if (best) { if (num < 10) { f = pr->pr_functions + (best - pr->function_table); - Sys_Printf ("%7i %s\n", best->profile, - PR_GetString (pr, f->name)); + Sys_Printf ("%7"PRIu64" %s%s\n", best->profile, + PR_GetString (pr, f->name), + f->first_statement < 0 ? " (builtin)" : ""); } num++; best->profile = 0; } } while (best); + Sys_Printf ("total: %7"PRIu64"\n", total); } static void diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index febb93266..4bbf3ca81 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -455,6 +455,7 @@ PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr) int builtin_depth = pr->pr_depth; pr->pr_return = return_ptr; f->func (pr); + f->profile++; // to show number times the builtin is called if (builtin_depth == pr->pr_depth) { pr->pr_return = saved_return; } else if (builtin_depth < pr->pr_depth) { From 2a8fca80a09f2b126e1ba0dbb35c4214522feb0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 21:53:37 +0900 Subject: [PATCH 2394/3664] [nq,qw] Give the menu and server progs stacks They're going to need them :P --- libs/console/menu.c | 1 + nq/source/sv_progs.c | 4 ++++ qw/source/sv_progs.c | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/libs/console/menu.c b/libs/console/menu.c index fd34f6a68..b8e9ccaf7 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -594,6 +594,7 @@ Menu_Init (void) menu_pr_state.max_edicts = 0; menu_pr_state.zone_size = 1024 * 1024; + menu_pr_state.stack_size = 64 * 1024; PR_Init (&menu_pr_state); diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index a6cc1cbc7..a0235e108 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -57,6 +57,7 @@ sv_data_t sv_data[MAX_EDICTS]; cvar_t *sv_progs; cvar_t *sv_progs_zone; +cvar_t *sv_progs_stack; cvar_t *sv_progs_ext; cvar_t *pr_checkextensions; @@ -514,6 +515,7 @@ SV_LoadProgs (void) sv_pr_state.max_edicts = sv.max_edicts; sv_pr_state.zone_size = sv_progs_zone->int_val * 1024; + sv_pr_state.stack_size = sv_progs_stack->int_val * 1024; sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name); @@ -561,6 +563,8 @@ SV_Progs_Init_Cvars (void) "Override the default game progs."); sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL, "size of the zone for progs in kb"); + sv_progs_stack = Cvar_Get ("sv_progs_stack", "256", CVAR_NONE, NULL, + "size of the stack for progs in kb"); sv_progs_ext = Cvar_Get ("sv_progs_ext", "qf", CVAR_NONE, NULL, "extention mapping to use: " "none, id, qf"); diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 8c8809c38..77d7898ff 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -60,6 +60,7 @@ sv_data_t sv_data[MAX_EDICTS]; cvar_t *r_skyname; cvar_t *sv_progs; cvar_t *sv_progs_zone; +cvar_t *sv_progs_stack; cvar_t *sv_progs_ext; cvar_t *pr_checkextensions; cvar_t *sv_old_entity_free; @@ -560,6 +561,7 @@ SV_LoadProgs (void) sv_pr_state.max_edicts = MAX_EDICTS; sv_pr_state.zone_size = sv_progs_zone->int_val * 1024; + sv_pr_state.stack_size = sv_progs_stack->int_val * 1024; sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name); @@ -614,6 +616,8 @@ SV_Progs_Init_Cvars (void) "Override the default game progs."); sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL, "size of the zone for progs in kB"); + sv_progs_stack = Cvar_Get ("sv_progs_stack", "64", CVAR_NONE, NULL, + "size of the stack for progs in kB"); sv_progs_ext = Cvar_Get ("sv_progs_ext", "qf", CVAR_NONE, NULL, "extention mapping to use: " "none, id, qf, qwe, ktpro, cpqw"); From 1b40cdbab6ee5aae420094ece56d81ff381e1c55 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 21:57:41 +0900 Subject: [PATCH 2395/3664] [qfcc] Handle vector scaling by ints I missed a change when implementing support for the scale instructions. --- tools/qfcc/source/dot_expr.c | 2 ++ tools/qfcc/source/expr_binary.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 04784856a..52db56ca9 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -75,6 +75,7 @@ get_op_string (int op) case GE: return ">="; case LT: return "<"; case GT: return ">"; + case '=': return "="; case '+': return "+"; case '-': return "-"; case '*': return "*"; @@ -92,6 +93,7 @@ get_op_string (int op) case 'C': return ""; case CROSS: return "@cross"; case DOT: return "@dot"; + case SCALE: return "@scale"; default: return "unknown"; } diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 162a15147..8c2881a64 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -258,7 +258,7 @@ static expr_type_t int_float[] = { }; static expr_type_t int_vector[] = { - {'*', &type_vector, &type_float, 0}, + {'*', &type_vector, &type_float, 0, vector_scale}, {0, 0} }; From 24a42dc064335d9c96b7e0c8b0df1afa2d6df5fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 22:00:18 +0900 Subject: [PATCH 2396/3664] [qfcc] Emit args for ... functions with no other parameters I missed that the block was < -1, ie at least one real parameters. --- tools/qfcc/source/expr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 21951799c..1efde4579 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2161,7 +2161,6 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) warning (fexpr, "too few arguments"); } param_count = -ftype->t.func.num_params - 1; - emit_args = !ftype->t.func.no_va_list; } else if (ftype->t.func.num_params >= 0) { if (arg_count > ftype->t.func.num_params) { return error (fexpr, "too many arguments"); @@ -2173,6 +2172,9 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) } param_count = ftype->t.func.num_params; } + if (ftype->t.func.num_params < 0) { + emit_args = !ftype->t.func.no_va_list; + } // params is reversed (a, b, c) -> c, b, a for (i = arg_count - 1, e = params; i >= 0; i--, e = e->next) { type_t *t; From 6988752dea3d0b37e810cce3401410b52c7365b4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 22:02:05 +0900 Subject: [PATCH 2397/3664] [qfcc] Clean up line numbers in varargs setup It's never nice getting the end-of-function line in the middle of some code. --- tools/qfcc/source/statements.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index aaba453ff..6fdefa80b 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1218,6 +1218,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) } else { list = new_nil_expr (); } + expr_file_line (list, call); assign = assign_expr (args_list, list); expr_file_line (assign, call); sblock = statement_slist (sblock, assign); From b6a8a93cc319b2252ac86a1d3bcad9b77ddea155 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 22:03:26 +0900 Subject: [PATCH 2398/3664] [qfcc] Treat vectors and quaternions as non-scalars Fixes a segfault when initializing vectors thai was caused by the earlier block init fix. --- tools/qfcc/source/type.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index b0882519c..c9a3c6d75 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -969,6 +969,9 @@ int is_nonscalar (const type_t *type) { type = unalias_type (type); + if (is_vector (type) || is_quaternion (type)) { + return 1; + } if (type->width < 2) { return 0; } From cdc3c9822d4f37f2767fbe0fc360315ec265e91f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 22:09:38 +0900 Subject: [PATCH 2399/3664] [ruamoko] Preserve the stack in obj_msg_sendv obj_msg_sendv needs to push the parameters onto the stack for Ruamoko progs, but this causes problems because PR_CallFunction winds up recording the wrong stack pointer for progs functions, and nothing restores the stack for builtins. The handling is basically the same as for the return pointer. --- libs/ruamoko/rua_obj.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 971ba55b8..a4fc74f9e 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1430,6 +1430,11 @@ rua_obj_msg_sendv (progs_t *pr) // replace them count -= 2; params += 2 * pr->pr_param_size; + pr_ptr_t saved_stack = 0; + int sendv_depth = pr->pr_depth; + if (pr->globals.stack) { + saved_stack = *pr->globals.stack; + } PR_RESET_PARAMS (pr); P_POINTER (pr, 0) = obj; P_POINTER (pr, 1) = sel; @@ -1437,7 +1442,15 @@ rua_obj_msg_sendv (progs_t *pr) memcpy (&P_INT (pr, 2), params, count * sizeof (pr_type_t) * pr->pr_param_size); } - PR_CallFunction (pr, imp, pr->pr_return); + if (PR_CallFunction (pr, imp, pr->pr_return)) { + // the call is to a progs function so a frame was pushed, ensure + // the stack pointer is restored on return + // if there's no stack, then the following is effectively a noop + pr->pr_stack[sendv_depth].stack_ptr = saved_stack; + } else if (pr->globals.stack) { + // the call was to a builtin, restore the stack + *pr->globals.stack = saved_stack; + } } static void From 5f684b2f81e312c3e91b5ad381859dba7a324766 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 22:15:24 +0900 Subject: [PATCH 2400/3664] [ruamoko] Rework PF_VarString to work with Ruamoko progs It's a rather core function used by the game code, though it is rather horrid. --- libs/ruamoko/pr_cmds.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 24d3f6294..93cec016e 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -59,12 +59,27 @@ PF_VarString (progs_t *pr, int first) char *out, *dst; const char *src; int len, i; + int argc = pr->pr_argc; + pr_type_t **argv = pr->pr_params; - for (len = 0, i = first; i < pr->pr_argc; i++) - len += strlen (P_GSTRING (pr, i)); + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 0); + argc = va_list->count; + if (argc) { + argv = alloca (argc * sizeof (pr_type_t *)); + for (int i = 0; i < argc; i++) { + argv[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + argv = 0; + } + } + + for (len = 0, i = first; i < argc; i++) + len += strlen (PR_GetString (pr, argv[i]->string_var)); dst = out = Hunk_TempAlloc (0, len + 1); - for (i = first; i < pr->pr_argc; i++) { - src = P_GSTRING (pr, i); + for (i = first; i < argc; i++) { + src = PR_GetString (pr, argv[i]->string_var); while (*src) *dst++ = *src++; } From 2fc35b39b0cc35dd339ed56eeaa36a3bcd712d63 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 22:19:05 +0900 Subject: [PATCH 2401/3664] [ruamoko] Use a shared implementation for set functions I suppose having one builtin call another was a neat idea at the time, and really could have been fixed by simply wrapping the calls with push/pop frame, but this is probably faster. --- libs/ruamoko/rua_set.c | 323 ++++++++++++++++++++++++----------------- 1 file changed, 193 insertions(+), 130 deletions(-) diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index b1b3a7dee..c8a0f2672 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -219,111 +219,177 @@ bi_set_delete (progs_t *pr) res_set_free (res, set); } +static void +rua_set_add (progs_t *pr, pr_int_t setid, pr_uint_t element) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_add (set->set, element); +} + static void bi_set_add (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_add (set->set, P_UINT (pr, 1)); + rua_set_add (pr, P_INT (pr, 0), P_UINT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_remove (progs_t *pr, pr_int_t setid, pr_uint_t element) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_remove (set->set, element); +} + static void bi_set_remove (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_remove (set->set, P_UINT (pr, 1)); + rua_set_remove (pr, P_INT (pr, 0), P_UINT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_invert (progs_t *pr, pr_int_t setid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_invert (set->set); +} + static void bi_set_invert (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_invert (set->set); + rua_set_invert (pr, P_INT (pr, 0)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_union (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_union (dst->set, src->set); +} + static void bi_set_union (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_union (set1->set, set2->set); + rua_set_union (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_intersection (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_intersection (dst->set, src->set); +} + static void bi_set_intersection (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_intersection (set1->set, set2->set); + rua_set_intersection (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_difference (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_difference (dst->set, src->set); +} + static void bi_set_difference (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_difference (set1->set, set2->set); + rua_set_difference (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_reverse_difference (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_reverse_difference (dst->set, src->set); +} + static void bi_set_reverse_difference (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_reverse_difference (set1->set, set2->set); + rua_set_reverse_difference (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_assign (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +{ + bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + + set_assign (dst->set, src->set); +} + static void bi_set_assign (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); - - set_assign (set1->set, set2->set); + rua_set_assign (pr, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_empty (progs_t *pr, pr_int_t setid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_empty (set->set); +} + static void bi_set_empty (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_empty (set->set); + rua_set_empty (pr, P_INT (pr, 0)); R_INT (pr) = P_INT (pr, 0); } +static void +rua_set_everything (progs_t *pr, pr_int_t setid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + set_everything (set->set); +} + static void bi_set_everything (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - set_everything (set->set); + rua_set_everything (pr, P_INT (pr, 0)); R_INT (pr) = P_INT (pr, 0); } static void -bi_set_is_empty (progs_t *pr) +rua_set_is_empty (progs_t *pr, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); + bi_set_t *set = get_set (pr, __FUNCTION__, setid); R_INT (pr) = set_is_empty (set->set); } static void -bi_set_is_everything (progs_t *pr) +bi_set_is_empty (progs_t *pr) +{ + rua_set_is_empty (pr, P_INT (pr, 0)); +} + +static void +rua_set_is_everything (progs_t *pr, pr_int_t setid) { bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); @@ -331,55 +397,97 @@ bi_set_is_everything (progs_t *pr) } static void -bi_set_is_disjoint (progs_t *pr) +bi_set_is_everything (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); + rua_set_is_everything (pr, P_INT (pr, 0)); +} + +static void +rua_set_is_disjoint (progs_t *pr, pr_int_t sid1, pr_int_t sid2) +{ + bi_set_t *set1 = get_set (pr, __FUNCTION__, sid1); + bi_set_t *set2 = get_set (pr, __FUNCTION__, sid2); R_INT (pr) = set_is_disjoint (set1->set, set2->set); } static void -bi_set_is_intersecting (progs_t *pr) +bi_set_is_disjoint (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); + rua_set_is_disjoint (pr, P_INT (pr, 0), P_INT (pr, 1)); +} + +static void +rua_set_is_intersecting (progs_t *pr, pr_int_t sid1, pr_int_t sid2) +{ + bi_set_t *set1 = get_set (pr, __FUNCTION__, sid1); + bi_set_t *set2 = get_set (pr, __FUNCTION__, sid2); R_INT (pr) = set_is_intersecting (set1->set, set2->set); } static void -bi_set_is_equivalent (progs_t *pr) +bi_set_is_intersecting (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); + rua_set_is_intersecting (pr, P_INT (pr, 0), P_INT (pr, 1)); +} + +static void +rua_set_is_equivalent (progs_t *pr, pr_int_t sid1, pr_int_t sid2) +{ + bi_set_t *set1 = get_set (pr, __FUNCTION__, sid1); + bi_set_t *set2 = get_set (pr, __FUNCTION__, sid2); R_INT (pr) = set_is_equivalent (set1->set, set2->set); } +static void +bi_set_is_equivalent (progs_t *pr) +{ + rua_set_is_equivalent (pr, P_INT (pr, 0), P_INT (pr, 1)); +} + +static void +rua_set_is_subset (progs_t *pr, pr_int_t setid, pr_int_t subid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *sub = get_set (pr, __FUNCTION__, subid); + + R_INT (pr) = set_is_subset (set->set, sub->set); +} + static void bi_set_is_subset (progs_t *pr) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - bi_set_t *set2 = get_set (pr, __FUNCTION__, P_INT (pr, 1)); + rua_set_is_subset (pr, P_INT (pr, 0), P_INT (pr, 1)); +} - R_INT (pr) = set_is_subset (set1->set, set2->set); +static void +rua_set_is_member (progs_t *pr, pr_int_t setid, pr_uint_t element) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + R_INT (pr) = set_is_member (set->set, element); } static void bi_set_is_member (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); + rua_set_is_member (pr, P_INT (pr, 0), P_UINT (pr, 1)); +} - R_INT (pr) = set_is_member (set->set, P_UINT (pr, 1)); +static void +rua_set_count (progs_t *pr, pr_int_t setid) +{ + bi_set_t *set = get_set (pr, __FUNCTION__, setid); + + R_INT (pr) = set_count (set->set); } static void bi_set_count (progs_t *pr) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); - - R_INT (pr) = set_count (set->set); + rua_set_count (pr, P_INT (pr, 0)); } static void @@ -422,13 +530,19 @@ bi_set_next (progs_t *pr) } static void -bi_set_as_string (progs_t *pr) +rua_set_as_string (progs_t *pr, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); + bi_set_t *set = get_set (pr, __FUNCTION__, setid); RETURN_STRING (pr, set_as_string (set->set)); } +static void +bi_set_as_string (progs_t *pr) +{ + rua_set_as_string (pr, P_INT (pr, 0)); +} + static void bi__i_SetIterator__element (progs_t *pr) { @@ -444,10 +558,7 @@ bi__i_Set__add_ (progs_t *pr) pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - P_INT (pr, 1) = P_INT (pr, 2); - bi_set_add (pr); + rua_set_add (pr, set_obj->set, P_UINT (pr, 2)); R_INT (pr) = set_ptr; } @@ -457,10 +568,7 @@ bi__i_Set__remove_ (progs_t *pr) pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - P_INT (pr, 1) = P_INT (pr, 2); - bi_set_remove (pr); + rua_set_remove (pr, set_obj->set, P_UINT (pr, 2)); R_INT (pr) = set_ptr; } @@ -470,9 +578,7 @@ bi__i_Set__invert (progs_t *pr) pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_invert (pr); + rua_set_invert (pr, set_obj->set); R_INT (pr) = set_ptr; } @@ -481,13 +587,9 @@ bi__i_Set__union_ (progs_t *pr) { pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); - pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_union (pr); - R_INT (pr) = dst_ptr; + rua_set_union (pr, dst_obj->set, src_obj->set); } static void @@ -497,10 +599,7 @@ bi__i_Set__intersection_ (progs_t *pr) pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_intersection (pr); + rua_set_intersection (pr, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } @@ -511,10 +610,7 @@ bi__i_Set__difference_ (progs_t *pr) pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_difference (pr); + rua_set_difference (pr, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } @@ -525,10 +621,7 @@ bi__i_Set__reverse_difference_ (progs_t *pr) pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_reverse_difference (pr); + rua_set_reverse_difference (pr, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } @@ -539,10 +632,7 @@ bi__i_Set__assign_ (progs_t *pr) pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = dst_obj->set; - P_INT (pr, 1) = src_obj->set; - bi_set_assign (pr); + rua_set_assign (pr, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } @@ -552,9 +642,7 @@ bi__i_Set__empty (progs_t *pr) pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_empty (pr); + rua_set_empty (pr, set_obj->set); R_INT (pr) = set_ptr; } @@ -564,9 +652,7 @@ bi__i_Set__everything (progs_t *pr) pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_everything (pr); + rua_set_everything (pr, set_obj->set); R_INT (pr) = set_ptr; } @@ -575,9 +661,7 @@ bi__i_Set__is_empty (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_is_empty (pr); + rua_set_is_empty (pr, set_obj->set); } static void @@ -585,9 +669,7 @@ bi__i_Set__is_everything (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_is_everything (pr); + rua_set_is_everything (pr, set_obj->set); } static void @@ -596,10 +678,7 @@ bi__i_Set__is_disjoint_ (progs_t *pr) pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = s1_obj->set; - P_INT (pr, 1) = s2_obj->set; - bi_set_is_disjoint (pr); + rua_set_is_disjoint (pr, s1_obj->set, s2_obj->set); } static void @@ -608,10 +687,7 @@ bi__i_Set__is_intersecting_ (progs_t *pr) pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = s1_obj->set; - P_INT (pr, 1) = s2_obj->set; - bi_set_is_intersecting (pr); + rua_set_is_intersecting (pr, s1_obj->set, s2_obj->set); } static void @@ -620,22 +696,16 @@ bi__i_Set__is_equivalent_ (progs_t *pr) pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = s1_obj->set; - P_INT (pr, 1) = s2_obj->set; - bi_set_is_equivalent (pr); + rua_set_is_equivalent (pr, s1_obj->set, s2_obj->set); } static void bi__i_Set__is_subset_ (progs_t *pr) { - pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); - pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); + pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); + pr_set_t *sub_obj = &P_STRUCT (pr, pr_set_t, 2); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = s1_obj->set; - P_INT (pr, 1) = s2_obj->set; - bi_set_is_subset (pr); + rua_set_is_subset (pr, set_obj->set, sub_obj->set); } static void @@ -643,10 +713,7 @@ bi__i_Set__is_member_ (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - P_UINT (pr, 1) = P_UINT (pr, 2); - bi_set_is_member (pr); + rua_set_is_member (pr, set_obj->set, P_UINT (pr, 2)); } static void @@ -654,9 +721,7 @@ bi__i_Set__size (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_count (pr); + rua_set_count (pr, set_obj->set); } static void @@ -664,9 +729,7 @@ bi__i_Set__as_string (progs_t *pr) { pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - PR_RESET_PARAMS (pr); - P_INT (pr, 0) = set_obj->set; - bi_set_as_string (pr); + rua_set_as_string (pr, set_obj->set); } static void From f94d5e9fdbe6c9e1f1f77e9e246a5ee1f3d5e5c4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Feb 2022 22:31:36 +0900 Subject: [PATCH 2402/3664] [ruamoko] Correct decls for functions using PF_VarString Need to ensure va_list gets into the arguments so PF_VarString can work with Ruamoko progs. --- ruamoko/include/debug.h | 6 +++--- ruamoko/include/message.h | 2 +- ruamoko/lib/debug.r | 6 +++--- ruamoko/lib/message.r | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ruamoko/include/debug.h b/ruamoko/include/debug.h index 017ca1858..9ea089de0 100644 --- a/ruamoko/include/debug.h +++ b/ruamoko/include/debug.h @@ -62,18 +62,18 @@ /** Print a string to the console if the "developer" Cvar is nonzero. */ -@extern void dprint (string str); +@extern void dprint (.../*string str*/); /** Abort (crash) the server. "str" is the message the server crashes with. */ -@extern void error (string str); +@extern void error (.../*string str*/); /** Prints info on the "self" ENTITY (not object), and error message "e". The entity is freed. */ -@extern void objerror (string e); +@extern void objerror (.../*string e*/); //\} #endif //__ruamoko_debug_h diff --git a/ruamoko/include/message.h b/ruamoko/include/message.h index 7d37e91f5..f0cf5c140 100644 --- a/ruamoko/include/message.h +++ b/ruamoko/include/message.h @@ -35,7 +35,7 @@ #define MULTICAST_PVS_R 5 @extern void bprint (...); -@extern void sprint (entity client, string s); +@extern void sprint (.../*entity client, string s*/); @extern void WriteBytes (float to, ...); @extern void WriteByte (float to, float f); @extern void WriteChar (float to, float f); diff --git a/ruamoko/lib/debug.r b/ruamoko/lib/debug.r index 7cf9c8895..0f2f09375 100644 --- a/ruamoko/lib/debug.r +++ b/ruamoko/lib/debug.r @@ -5,6 +5,6 @@ void coredump (void) = #28; void traceon (void) = #29; void traceoff (void) = #30; void eprint (entity e) = #31; -void dprint (string str) = #25; -void error (string str) = #10; -void objerror (string e) = #11; +void dprint (.../*string str*/) = #25; +void error (.../*string str*/) = #10; +void objerror (.../*string e*/) = #11; diff --git a/ruamoko/lib/message.r b/ruamoko/lib/message.r index 4ddb31571..d01c641e5 100644 --- a/ruamoko/lib/message.r +++ b/ruamoko/lib/message.r @@ -1,7 +1,7 @@ #include void (...) bprint = #23; -void (entity client, string s) sprint = #24; +void (.../*entity client, string s*/) sprint = #24; void (float to, float f) WriteByte = #52; void (float to, float f) WriteChar = #53; void (float to, float f) WriteShort = #54; From 529253e6d9596d865152005aeb0941dc9a4c7e0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 10:17:57 +0900 Subject: [PATCH 2403/3664] [gamecode] Make edict macros more robust to null A null edict pointer should product a null entity, not a segfault. --- include/QF/progs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index f5ffb1a94..317a1ae19 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -352,10 +352,10 @@ void ED_EntityParseFunction (progs_t *pr); #define PR_edicts(p) (*(p)->pr_edicts) -#define NEXT_EDICT(p,e) ((e) + 1) -#define EDICT_TO_PROG(p,e) ((e)->entnum * (p)->pr_edict_size) +#define NEXT_EDICT(p,e) ((e) ? (e) + 1 : 0) +#define EDICT_TO_PROG(p,e) ((e) ? (e)->entnum * (p)->pr_edict_size : 0) #define PROG_TO_EDICT(p,e) (&PR_edicts(p)[(e) / (p)->pr_edict_size]) -#define NUM_FOR_BAD_EDICT(p,e) ((e)->entnum) +#define NUM_FOR_BAD_EDICT(p,e) ((e) ? (e)->entnum : 0) #ifndef PR_PARANOID_PROGS # define EDICT_NUM(p,n) (PR_edicts (p) + (n)) # define NUM_FOR_EDICT(p,e) NUM_FOR_BAD_EDICT ((p), (e)) From 01345ba6759daabf9d247e9c38ed5e8efb0f401f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 10:24:02 +0900 Subject: [PATCH 2404/3664] [gamecode] Wrap most uses of PR_RESET_PARAMS with push/pop frame rua_obj was skipped because that looks to be a bit more work and should be a separate commit. This is to avoid the stack getting mangled when calling progs functions with parameters. --- libs/console/menu.c | 8 +++++++- libs/ruamoko/rua_input.c | 1 + libs/ruamoko/rua_stdlib.c | 5 ++++- nq/include/sv_progs.h | 38 ++++++++++++++------------------------ qw/include/sv_progs.h | 38 ++++++++++++++------------------------ 5 files changed, 40 insertions(+), 50 deletions(-) diff --git a/libs/console/menu.c b/libs/console/menu.c index b8e9ccaf7..171de8084 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -683,12 +683,14 @@ Menu_Draw (view_t *view) int ret; run_menu_pre (); + PR_PushFrame (&menu_pr_state); PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = x; P_INT (&menu_pr_state, 1) = y; menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, menu->draw); ret = R_INT (&menu_pr_state); + PR_PopFrame (&menu_pr_state); run_menu_post (); if (!ret) return; @@ -718,11 +720,13 @@ Menu_Draw (view_t *view) item = menu->items[menu->cur_item]; if (menu->cursor) { run_menu_pre (); + PR_PushFrame (&menu_pr_state); PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = x + item->x; P_INT (&menu_pr_state, 1) = y + item->y; menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, menu->cursor); + PR_PopFrame (&menu_pr_state); run_menu_post (); } else { r_funcs->Draw_Character (x + item->x, y + item->y, @@ -751,6 +755,7 @@ menu_key_event (const IE_event_t *ie_event) return 0; if (menu->keyevent) { run_menu_pre (); + PR_PushFrame (&menu_pr_state); PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = key.code; P_INT (&menu_pr_state, 1) = key.unicode; @@ -758,6 +763,7 @@ menu_key_event (const IE_event_t *ie_event) menu_pr_state.pr_argc = 3; PR_ExecuteProgram (&menu_pr_state, menu->keyevent); ret = R_INT (&menu_pr_state); + PR_PopFrame (&menu_pr_state); run_menu_post (); if (ret) return 1; @@ -772,8 +778,8 @@ menu_key_event (const IE_event_t *ie_event) P_INT (&menu_pr_state, 1) = key.code; menu_pr_state.pr_argc = 2; PR_ExecuteProgram (&menu_pr_state, item->func); - PR_PopFrame (&menu_pr_state); ret = R_INT (&menu_pr_state); + PR_PopFrame (&menu_pr_state); run_menu_post (); if (ret) return 1; diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index e54dc73e2..406ce18bc 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -283,6 +283,7 @@ rua_listener_func (rua_in_cookie_t *cookie, const void *input) { progs_t *pr = cookie->pr; PR_PushFrame (pr); + PR_RESET_PARAMS (pr); P_POINTER (pr, 0) = cookie->data; P_POINTER (pr, 1) = PR_SetPointer (pr, input);//FIXME check input pr->pr_argc = 2; diff --git a/libs/ruamoko/rua_stdlib.c b/libs/ruamoko/rua_stdlib.c index fa8489d1c..50fd1cc04 100644 --- a/libs/ruamoko/rua_stdlib.c +++ b/libs/ruamoko/rua_stdlib.c @@ -72,12 +72,15 @@ rua_compare (const void *a, const void *b, void *_f) { function_t *f = _f; + PR_PushFrame (f->pr); PR_RESET_PARAMS (f->pr); P_POINTER (f->pr, 0) = PR_SetPointer (f->pr, a); P_POINTER (f->pr, 1) = PR_SetPointer (f->pr, b); f->pr->pr_argc = 2; PR_ExecuteProgram (f->pr, f->func); - return R_INT (f->pr); + int cmp = R_INT (f->pr); + PR_PopFrame (f->pr); + return cmp; } static void diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 4a74bfb38..79622a1fb 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -213,19 +213,29 @@ typedef struct sv_data_s { #define EDICT_FROM_AREA(l) (STRUCT_FROM_LINK(l,sv_data_t,area)->edict) static inline void -sv_pr_touch (edict_t *self, edict_t *other) +sv_pr_exec (edict_t *self, edict_t *other, pr_func_t func) { pr_int_t this; *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, other); if ((this = sv_pr_state.fields.this) != -1) { + PR_PushFrame (&sv_pr_state); PR_RESET_PARAMS (&sv_pr_state); P_INT (&sv_pr_state, 0) = E_POINTER (self, this); P_INT (&sv_pr_state, 1) = 0; P_INT (&sv_pr_state, 2) = E_POINTER (other, this); } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, touch)); + PR_ExecuteProgram (&sv_pr_state, func); + if ((this = sv_pr_state.fields.this) != -1) { + PR_PopFrame (&sv_pr_state); + } +} + +static inline void +sv_pr_touch (edict_t *self, edict_t *other) +{ + sv_pr_exec (self, other, SVfunc (self, touch)); } static inline void @@ -236,33 +246,13 @@ sv_pr_use (edict_t *self, edict_t *other) static inline void sv_pr_think (edict_t *self) { - pr_int_t this; - - *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); - *sv_globals.other = 0; - if ((this = sv_pr_state.fields.this) != -1) { - PR_RESET_PARAMS (&sv_pr_state); - P_INT (&sv_pr_state, 0) = E_POINTER (self, this); - P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = 0; - } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, think)); + sv_pr_exec (self, 0, SVfunc (self, think)); } static inline void sv_pr_blocked (edict_t *self, edict_t *other) { - pr_int_t this; - - *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); - *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, other); - if ((this = sv_pr_state.fields.this) != -1) { - PR_RESET_PARAMS (&sv_pr_state); - P_INT (&sv_pr_state, 0) = E_POINTER (self, this); - P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = E_POINTER (other, this); - } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, blocked)); + sv_pr_exec (self, other, SVfunc (self, blocked)); } #endif // __sv_progs_h diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index c158461de..e3ebc6b70 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -218,19 +218,29 @@ typedef struct sv_data_s { #define EDICT_FROM_AREA(l) (STRUCT_FROM_LINK(l,sv_data_t,area)->edict) static inline void -sv_pr_touch (edict_t *self, edict_t *other) +sv_pr_exec (edict_t *self, edict_t *other, pr_func_t func) { pr_int_t this; *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, other); if ((this = sv_pr_state.fields.this) != -1) { + PR_PushFrame (&sv_pr_state); PR_RESET_PARAMS (&sv_pr_state); P_INT (&sv_pr_state, 0) = E_POINTER (self, this); P_INT (&sv_pr_state, 1) = 0; P_INT (&sv_pr_state, 2) = E_POINTER (other, this); } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, touch)); + PR_ExecuteProgram (&sv_pr_state, func); + if ((this = sv_pr_state.fields.this) != -1) { + PR_PopFrame (&sv_pr_state); + } +} + +static inline void +sv_pr_touch (edict_t *self, edict_t *other) +{ + sv_pr_exec (self, other, SVfunc (self, touch)); } static inline void @@ -241,33 +251,13 @@ sv_pr_use (edict_t *self, edict_t *other) static inline void sv_pr_think (edict_t *self) { - pr_int_t this; - - *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); - *sv_globals.other = 0; - if ((this = sv_pr_state.fields.this) != -1) { - PR_RESET_PARAMS (&sv_pr_state); - P_INT (&sv_pr_state, 0) = E_POINTER (self, this); - P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = 0; - } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, think)); + sv_pr_exec (self, 0, SVfunc (self, think)); } static inline void sv_pr_blocked (edict_t *self, edict_t *other) { - pr_int_t this; - - *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, self); - *sv_globals.other = EDICT_TO_PROG (&sv_pr_state, other); - if ((this = sv_pr_state.fields.this) != -1) { - PR_RESET_PARAMS (&sv_pr_state); - P_INT (&sv_pr_state, 0) = E_POINTER (self, this); - P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = E_POINTER (other, this); - } - PR_ExecuteProgram (&sv_pr_state, SVfunc (self, blocked)); + sv_pr_exec (self, other, SVfunc (self, blocked)); } #endif // __sv_progs_h From 5500d835fed0f78bb9902fd74cd8eaf8c0a00e40 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 10:29:20 +0900 Subject: [PATCH 2405/3664] [qw] Fix a mangled builtin number When doing the builtin params data change, I had somehow switch multicast's number from 82 to 81. Fortunately, another builtin is also 81, so the VM told me off when I tried to run qw-server :) --- qw/source/sv_pr_cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 9e3ffac8f..e01448de6 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -2020,7 +2020,7 @@ static builtin_t builtins[] = { bi(logfrag, 79, 2, p(entity), p(entity)), bi(infokey, 80, 2, p(entity), p(string)), - bi(multicast, 81, 2, p(vector), p(float)), + bi(multicast, 82, 2, p(vector), p(float)), bi(testentitypos, QF 92, 1, p(entity)), bi(hullpointcontents, QF 93, 2, p(entity), p(vector)), From 2c0969f9884aef397ef08c72bf6ec4b584eaf61c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 13:01:44 +0900 Subject: [PATCH 2406/3664] [ruamoko] Rework method call hand-off to preserve the stack This takes care of the problems with PR_RESET_PARAMS (which has recently become just a wrapper for PR_SetupParams) changing the stack and causing PR_CallFunction to save the wrong stack pointer. Message forwarding is currently broken for Ruamoko ISA progs, but that is due to not having a valid pr_argc. However, I do have a plan involving extracting the parameter count from the selector, but that's something for a later commit. Everything else seems to be ok (my little game is working nicely). --- libs/ruamoko/rua_obj.c | 101 +++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index a4fc74f9e..bf421ff46 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -59,6 +59,37 @@ #define always_inline inline __attribute__((__always_inline__)) +/* Macros to help with setting up to call a function, and cleaning up + * afterwards. The problem is that PR_CallFunction saves the CURRENT stack + * pointer, which has been adjusted by PR_SetupParams in order to push + * the function arguments. + * + * RUA_CALL_BEGIN and RUA_CALL_END must be used in pairs and this is enforced + * by the unbalanced {}s in the macros. + */ +#define RUA_CALL_BEGIN(pr, argc) \ + { \ + pr_ptr_t saved_stack = 0; \ + int call_depth = (pr)->pr_depth; \ + if ((pr)->globals.stack) { \ + saved_stack = *(pr)->globals.stack; \ + } \ + PR_SetupParams (pr, argc, 1); \ + (pr)->pr_argc = argc; + +#define RUA_CALL_END(pr, imp) \ + if (PR_CallFunction ((pr), (imp), (pr)->pr_return)) { \ + /* the call is to a progs function so a frame was pushed, */ \ + /* ensure the stack pointer is restored on return */ \ + /* if there's no stack, then the following is effectively a */ \ + /* noop */ \ + (pr)->pr_stack[call_depth].stack_ptr = saved_stack; \ + } else if ((pr)->globals.stack) { \ + /* the call was to a builtin, restore the stack */ \ + *(pr)->globals.stack = saved_stack; \ + } \ + } + typedef struct obj_list_s { struct obj_list_s *next; void *data; @@ -1271,39 +1302,45 @@ rua___obj_forward (progs_t *pr) if (obj_reponds_to (probj, obj, fwd_sel)) { imp = get_imp (probj, class, fwd_sel); // forward:(SEL) sel :(@va_list) args - // args is full param list - //FIXME oh for a stack - size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); - size_t size = pr->pr_argc * parm_size; - pr_string_t args_block = PR_AllocTempBlock (pr, size); + // args is full param list as a va_list + pr_string_t args_block = 0; + int argc; + pr_type_t *argv; + if (pr->globals.stack) { + argv = pr->pr_params[0]; + argc = 0; //FIXME extract from sel + } else { + size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); + size_t size = pr->pr_argc * parm_size; + args_block = PR_AllocTempBlock (pr, size); - int argc = pr->pr_argc; - __auto_type argv = (pr_type_t *) PR_GetString (pr, args_block); - // can't memcpy all params because 0 and 1 could be anywhere - memcpy (argv + 0, &P_INT (pr, 0), 4 * sizeof (pr_type_t)); - memcpy (argv + 4, &P_INT (pr, 1), 4 * sizeof (pr_type_t)); - memcpy (argv + 8, &P_INT (pr, 2), (argc - 2) * parm_size); + argc = pr->pr_argc; + argv = (pr_type_t *) PR_GetString (pr, args_block); + // can't memcpy all params because 0 and 1 could be anywhere + memcpy (argv + 0, &P_INT (pr, 0), 4 * sizeof (pr_type_t)); + memcpy (argv + 4, &P_INT (pr, 1), 4 * sizeof (pr_type_t)); + memcpy (argv + 8, &P_INT (pr, 2), (argc - 2) * parm_size); + } - PR_RESET_PARAMS (pr); + RUA_CALL_BEGIN (pr, 4); P_POINTER (pr, 0) = PR_SetPointer (pr, obj); P_POINTER (pr, 1) = PR_SetPointer (pr, fwd_sel); P_POINTER (pr, 2) = PR_SetPointer (pr, sel); P_PACKED (pr, pr_va_list_t, 3).count = argc; P_PACKED (pr, pr_va_list_t, 3).list = PR_SetPointer (pr, argv); - PR_PushTempString (pr, args_block); - PR_CallFunction (pr, imp, pr->pr_return); + if (args_block) { + PR_PushTempString (pr, args_block); + } + RUA_CALL_END (pr, imp); return; } - //FIXME ditto err_sel = sel_register_typed_name (probj, "doesNotRecognize:", "", 0); if (obj_reponds_to (probj, obj, err_sel)) { - imp = get_imp (probj, class, err_sel); - PR_RESET_PARAMS (pr); + RUA_CALL_BEGIN (pr, 3) P_POINTER (pr, 0) = PR_SetPointer (pr, obj); P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); P_POINTER (pr, 2) = PR_SetPointer (pr, sel); - pr->pr_argc = 3; - PR_CallFunction (pr, imp, pr->pr_return); + RUA_CALL_END (pr, get_imp (probj, class, err_sel)) return; } @@ -1312,16 +1349,13 @@ rua___obj_forward (progs_t *pr) PR_GetString (pr, class->name), PR_GetString (pr, probj->selector_names[sel->sel_id])); - //FIXME ditto err_sel = sel_register_typed_name (probj, "error:", "", 0); if (obj_reponds_to (probj, obj, err_sel)) { - imp = get_imp (probj, class, err_sel); - PR_RESET_PARAMS (pr); + RUA_CALL_BEGIN (pr, 3) P_POINTER (pr, 0) = PR_SetPointer (pr, obj); P_POINTER (pr, 1) = PR_SetPointer (pr, err_sel); P_POINTER (pr, 2) = PR_SetTempString (pr, probj->msg->str); - pr->pr_argc = 3; - PR_CallFunction (pr, imp, pr->pr_return); + RUA_CALL_END (pr, get_imp (probj, class, err_sel)) return; } @@ -1425,32 +1459,19 @@ rua_obj_msg_sendv (progs_t *pr) PR_GetString (pr, probj->selector_names[op->sel_id])); } - pr->pr_argc = count; + RUA_CALL_BEGIN (pr, count) // skip over the first two parameters because receiver and op will // replace them count -= 2; params += 2 * pr->pr_param_size; - pr_ptr_t saved_stack = 0; - int sendv_depth = pr->pr_depth; - if (pr->globals.stack) { - saved_stack = *pr->globals.stack; - } - PR_RESET_PARAMS (pr); + P_POINTER (pr, 0) = obj; P_POINTER (pr, 1) = sel; if (count) { memcpy (&P_INT (pr, 2), params, count * sizeof (pr_type_t) * pr->pr_param_size); } - if (PR_CallFunction (pr, imp, pr->pr_return)) { - // the call is to a progs function so a frame was pushed, ensure - // the stack pointer is restored on return - // if there's no stack, then the following is effectively a noop - pr->pr_stack[sendv_depth].stack_ptr = saved_stack; - } else if (pr->globals.stack) { - // the call was to a builtin, restore the stack - *pr->globals.stack = saved_stack; - } + RUA_CALL_END (pr, imp) } static void From 9cf2740cb4abdf3619843b7fc218abe4a87d4bfb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 14:07:45 +0900 Subject: [PATCH 2407/3664] [gamecode] Create a globally accessible hash of type encodings The plan is to use the types to extract the number of parameters for a selector when it is necessary to know the count. However, it'll probably become useful for something else alter (these things seem to always do so). --- include/QF/progs.h | 6 ++++++ libs/gamecode/pr_load.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 317a1ae19..cd40e92b7 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1910,6 +1910,12 @@ struct progs_s { struct hashtab_s *field_hash; ///@} + /// \name type encodings + ///@{ + struct hashtab_s *type_hash; + pr_ptr_t type_encodings; + ///@} + /// \name load hooks ///@{ int num_load_funcs; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 1443d1a12..82d07829a 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -46,6 +46,8 @@ #include "QF/sys.h" #include "QF/zone.h" +#include "QF/progs/pr_type.h" + #include "compat.h" VISIBLE cvar_t *pr_boundscheck; @@ -69,6 +71,14 @@ var_get_key (const void *d, void *_pr) return PR_GetString (pr, def->name); } +static const char * +type_get_key (const void *t, void *_pr) +{ + progs_t *pr = (progs_t *) _pr; + __auto_type type = (qfot_type_t *) t; + return PR_GetString (pr, type->encoding); +} + static void file_error (progs_t *pr, const char *path) { @@ -111,7 +121,6 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) dprograms_t progs; byte *base; byte *heap; - pr_def_t *xdefs_def = 0; ddef_t *global_ddefs; ddef_t *field_ddefs; // absolute minimum alignment is 4 bytes @@ -239,6 +248,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) Hash_FlushTable (pr->function_hash); Hash_FlushTable (pr->global_hash); Hash_FlushTable (pr->field_hash); + Hash_FlushTable (pr->type_hash); // byte swap the lumps for (i = 0; i < pr->progs->statements.count; i++) { @@ -300,7 +310,22 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) for (i = 0; i < pr->progs->globals.count; i++) ((int *) pr->pr_globals)[i] = LittleLong (((int *) pr->pr_globals)[i]); - xdefs_def = PR_FindGlobal (pr, ".xdefs"); + pr_def_t *types_def = PR_FindGlobal (pr, ".type_encodings"); + if (types_def) { + __auto_type encodings = &G_STRUCT (pr, qfot_type_encodings_t, + types_def->ofs); + pr->type_encodings = encodings->types; + qfot_type_t *type; + for (pr_ptr_t type_ptr = 4; type_ptr < encodings->size; + type_ptr += type->size) { + type = &G_STRUCT (pr, qfot_type_t, pr->type_encodings + type_ptr); + Hash_Add (pr->type_hash, type); + } + } else { + pr->type_encodings = 0; + } + + pr_def_t *xdefs_def = PR_FindGlobal (pr, ".xdefs"); if (xdefs_def) { pr_xdefs_t *xdefs = &G_STRUCT (pr, pr_xdefs_t, xdefs_def->ofs); xdef_t *xdef = &G_STRUCT (pr, xdef_t, xdefs->xdefs); @@ -493,6 +518,8 @@ PR_Init (progs_t *pr) pr->hashlink_freelist); pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr, pr->hashlink_freelist); + pr->type_hash = Hash_NewTable (1021, type_get_key, 0, pr, + pr->hashlink_freelist); } VISIBLE void From b0810958e73fa8b20be77ff387726bb3f757d0d3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 14:24:12 +0900 Subject: [PATCH 2408/3664] [ruamoko] Use encoded selector param count when forwarding This gets message forwarding apparently working, though something isn't quite right as qwaq-app doesn't update properly when I try to step through the program, but that could be an error elsewhere. --- libs/ruamoko/rua_obj.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index bf421ff46..8f2601066 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -53,6 +53,7 @@ #include "QF/sys.h" #include "QF/progs/pr_obj.h" +#include "QF/progs/pr_type.h" #include "compat.h" #include "rua_internal.h" @@ -108,6 +109,7 @@ typedef struct probj_resources_s { unsigned selector_index_max; obj_list **selector_sels; pr_string_t *selector_names; + pr_int_t *selector_argc; PR_RESMAP (dtable_t) dtables; dtable_t *dtable_list; pr_func_t obj_forward; @@ -517,9 +519,12 @@ add_sel_name (probj_t *probj, const char *name) size * sizeof (obj_list *)); probj->selector_names = realloc (probj->selector_names, size * sizeof (pr_string_t)); + probj->selector_argc = realloc (probj->selector_argc, + size * sizeof (pr_int_t)); for (i = probj->selector_index_max; i < size; i++) { probj->selector_sels[i] = 0; probj->selector_names[i] = 0; + probj->selector_argc[i] = 0; } probj->selector_index_max = size; } @@ -573,6 +578,15 @@ sel_register_typed_name (probj_t *probj, const char *name, const char *types, l->next = probj->selector_sels[index]; probj->selector_sels[index] = l; + if (sel->sel_types && pr->type_encodings) { + const char *enc = PR_GetString (pr, sel->sel_types); + __auto_type type = (qfot_type_t *) Hash_Find (pr->type_hash, enc); + if (type->meta != ty_basic || type->type != ev_func) { + PR_RunError (pr, "selector type encoing is not a function"); + } + probj->selector_argc[index] = type->func.num_params; + } + if (is_new) Hash_Add (probj->selector_hash, (void *) index); done: @@ -1308,7 +1322,15 @@ rua___obj_forward (progs_t *pr) pr_type_t *argv; if (pr->globals.stack) { argv = pr->pr_params[0]; - argc = 0; //FIXME extract from sel + argc = probj->selector_argc[sel->sel_id]; + if (argc < 0) { + // -ve values indicate varargs functions and is the ones + // complement of the number of real parameters before the + // ellipsis. However, Ruamoko ISA progs pass va_list through + // ... so in the end, a -ve value indicates the total number + // of arguments (including va_list) passed to the function. + argc = -argc; + } } else { size_t parm_size = pr->pr_param_size * sizeof(pr_type_t); size_t size = pr->pr_argc * parm_size; From 208cba85ebc461483b8c8478bd40a24fcbc22775 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 18:37:23 +0900 Subject: [PATCH 2409/3664] [gamecode] Move return buffer to end of progs memory map With the return buffer in progs_t, it could not be addressed by the progs on 64-bit machines (this was intentional, actually), but in order to get obj_msg_sendv working properly, I needed a way to "bounce" the return address of a calling function to the called function. The cleanest solution I could think of was to add a mode to the with instruction allowing the return pointer to be loaded into a register and then calling the function with a 0 offset for the return value but using the relevant register (next few commits). Testing promptly segfaulted due to the 64-bit offset not fitting into a 32-bit value. --- include/QF/progs.h | 4 ++-- include/QF/progs/pr_comp.h | 1 + libs/gamecode/pr_load.c | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index cd40e92b7..85b720bbf 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1960,8 +1960,8 @@ struct progs_s { pr_type_t *pr_real_params[PR_MAX_PARAMS]; int pr_param_size; ///< covers both params and return int pr_param_alignment; ///< covers both params and return - pr_type_t pr_return_buffer[32];///< for discarded return values - ///< or returning values to C + pr_type_t *pr_return_buffer; ///< for discarded return values + ///< or returning values to C ///@} /// \name edicts diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index 1012f320d..bc0c1030e 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -522,6 +522,7 @@ typedef struct dparmsize_s { #define DEF_SAVEGLOBAL (1<<15) #define PR_MAX_PARAMS 8 +#define PR_MAX_RETURN 32 // maximum size of return value typedef struct dfunction_s { pr_int_t first_statement; // negative numbers are builtins diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 82d07829a..c2c3c31d1 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -199,6 +199,8 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) mem_size = pr->pr_edict_area_size * sizeof (pr_type_t); mem_size += pr->progs_size + pr->zone_size + pr->stack_size; + // space for return buffer + mem_size += PR_MAX_RETURN * sizeof (pr_type_t); // +1 for a nul terminator pr->progs = pr->allocate_progs_mem (pr, mem_size + 1); @@ -240,6 +242,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) if (pr->globals.stack && pr->stack_bottom) { *pr->globals.stack = pr->globals_size; } + pr->pr_return_buffer = pr->pr_globals + pr->globals_size; if (pr->zone) { PR_Zone_Init (pr); From 078f36a871a0cd244681aded6d48f848ad0d33c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 18:42:54 +0900 Subject: [PATCH 2410/3664] [gamecode] Add "return pointer" mode to with instruction This loads the current return pointer into the specified register. No offset is used (should make that an error, but for now any offset is simply ignored). This is part of the fix for getting obj_msg_sendv to work with return values. --- libs/gamecode/pr_exec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 4bbf3ca81..bd3879431 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1989,6 +1989,10 @@ pr_with (progs_t *pr, const dstatement_t *st) // reset pr->pr_bases = (pr_uivec4_t) {}; return; + case 11: + // return pointer + *base = pr->pr_return - pr->pr_globals; + return; } PR_RunError (pr, "Invalid with index: %u", st->a); } From f153e87daac0fbe375c02e7bd5c316b97025853a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 18:45:54 +0900 Subject: [PATCH 2411/3664] [qfcc] Use a union to manage specifier bits Having to remember to copy yet another specifier bit was getting tedious, so use a union of a struct with the bitfields and an unsigned int to access them in parallel. Makes for a tidier spec_merge, and one less headache. --- tools/qfcc/include/type.h | 25 +++++++++++++++---------- tools/qfcc/source/qc-parse.y | 8 +------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index cafa1da91..6c80f9f6d 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -89,16 +89,21 @@ typedef struct { struct param_s *params; struct symbol_s *sym; ///< for dealing with "int id" etc storage_class_t storage; - unsigned multi_type:1; - unsigned multi_store:1; - unsigned is_signed:1; - unsigned is_unsigned:1; - unsigned is_short:1; - unsigned is_long:1; - unsigned is_typedef:1; - unsigned is_overload:1; - unsigned nosave:1; - unsigned no_va_list:1; + union { + struct { + unsigned multi_type:1; + unsigned multi_store:1; + unsigned is_signed:1; + unsigned is_unsigned:1; + unsigned is_short:1; + unsigned is_long:1; + unsigned is_typedef:1; + unsigned is_overload:1; + unsigned nosave:1; + unsigned no_va_list:1; + }; + unsigned spec_bits; + }; } specifier_t; #define EV_TYPE(type) extern type_t type_##type; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 99006c68e..7e7eb9b3a 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -290,13 +290,7 @@ spec_merge (specifier_t spec, specifier_t new) } } spec.sym = new.sym; - spec.is_signed |= new.is_signed; - spec.is_unsigned |= new.is_unsigned; - spec.is_short |= new.is_short; - spec.is_long |= new.is_long; - spec.is_overload |= new.is_overload; - spec.nosave |= new.nosave; - spec.no_va_list |= new.no_va_list; + spec.spec_bits |= new.spec_bits; return spec; } From 8cc6cbc1572fe8fd5c58e2165ba26cb15fe3f9f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 18:49:40 +0900 Subject: [PATCH 2412/3664] [qfcc] Use a union to manage function attributes Same idea as the specifiers, but makes checking function types are the same much easier. --- tools/qfcc/include/type.h | 7 ++++++- tools/qfcc/source/class.c | 2 +- tools/qfcc/source/type.c | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 6c80f9f6d..1c4f9223d 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -39,7 +39,12 @@ typedef struct ty_func_s { struct type_s *type; int num_params; struct type_s **param_types; - int no_va_list; ///< don't inject va_list for ... function + union { + struct { + unsigned no_va_list:1;///< don't inject va_list for ... function + }; + unsigned attribute_bits; + }; } ty_func_t; typedef struct ty_fldptr_s { diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 42f613c9e..c19f2dd01 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -90,7 +90,7 @@ type_t type_IMP = { .alignment = 1, .width = 1, .meta = ty_basic, - {{&type_id, -3, IMP_params, 1}}, + {{&type_id, -3, IMP_params, .no_va_list = 1}}, }; type_t type_super = { .type = ev_invalid, diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index c9a3c6d75..a695e9f50 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -379,7 +379,7 @@ types_same (type_t *a, type_t *b) case ev_func: if (a->t.func.type != b->t.func.type || a->t.func.num_params != b->t.func.num_params - || a->t.func.no_va_list != b->t.func.no_va_list) + || a->t.func.attribute_bits != b->t.func.attribute_bits) return 0; count = a->t.func.num_params; if (count < 0) From eee6744656ba016b02fa25fd4942c0770cd9c9ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 18:52:02 +0900 Subject: [PATCH 2413/3664] [qfcc] Use a function to apply function attributes There are too may places where they need to be applied, so making them all use a function will keep things manageable in the future. --- tools/qfcc/source/qc-parse.y | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 7e7eb9b3a..7fd7d658d 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -421,6 +421,12 @@ check_specifiers (specifier_t spec) } } +static void +set_func_type_attrs (type_t *func, specifier_t spec) +{ + func->t.func.no_va_list = spec.no_va_list; +} + %} %expect 0 @@ -486,7 +492,7 @@ external_def ret_type = *type; *type = 0; *type = parse_params (0, $2); - (*type)->t.func.no_va_list = $1.no_va_list; + set_func_type_attrs ((*type), $1); $$.type = find_type (append_type ($1.type, ret_type)); if ($$.type->type != ev_field) $$.params = $2; @@ -527,7 +533,7 @@ function_body symbol_t *sym = $0; specifier_t spec = default_type ($-1, sym); - sym->type->t.func.no_va_list = spec.no_va_list; + set_func_type_attrs (sym->type, spec); sym->type = find_type (append_type (sym->type, spec.type)); $$ = function_symbol (sym, spec.is_overload, 1); } @@ -551,7 +557,7 @@ function_body symbol_t *sym = $0; specifier_t spec = default_type ($-1, sym); - sym->type->t.func.no_va_list = spec.no_va_list; + set_func_type_attrs (sym->type, spec); sym->type = find_type (append_type (sym->type, spec.type)); sym = function_symbol (sym, spec.is_overload, 1); build_builtin_function (sym, $3, 0, spec.storage); @@ -600,7 +606,7 @@ external_decl | function_decl { specifier_t spec = default_type ($0, $1); - $1->type->t.func.no_va_list = spec.no_va_list; + set_func_type_attrs ($1->type, spec); $1->type = find_type (append_type ($1->type, spec.type)); if (spec.is_typedef) { $1->sy_type = sy_type; @@ -1089,7 +1095,7 @@ qc_param_decl type = &(*type)->t.fldptr.type) ; *type = parse_params (*type, $2); - (*type)->t.func.no_va_list = $1.no_va_list; + set_func_type_attrs ((*type), $1); $3->type = find_type ($1.type); if ($3->type->type != ev_field) $3->params = $2; @@ -1168,7 +1174,7 @@ local_decl_list type = &(*type)->t.fldptr.type) ; *type = parse_params (*type, $1); - (*type)->t.func.no_va_list = spec.no_va_list; + set_func_type_attrs ((*type), spec); spec.type = find_type (spec.type); $$ = spec; } From 084c2ccb1f5a775f0f1cf526de4346b23a6f91f9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 18:55:36 +0900 Subject: [PATCH 2414/3664] [qfcc] Make is_function_call a little more useful It can (and must) be used one level higher as it checks that the expression is a block and that its result expression is call branch expression. --- tools/qfcc/source/expr.c | 4 ++++ tools/qfcc/source/expr_obj.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 1efde4579..0d96f4fcf 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1796,6 +1796,10 @@ has_function_call (expr_t *e) int is_function_call (expr_t *e) { + if (e->type != ex_block || !e->e.block.is_call) { + return 0; + } + e = e->e.block.result; return e->type == ex_branch && e->e.branch.type == pr_branch_call; } diff --git a/tools/qfcc/source/expr_obj.c b/tools/qfcc/source/expr_obj.c index 41405c1e4..b2463e4d1 100644 --- a/tools/qfcc/source/expr_obj.c +++ b/tools/qfcc/source/expr_obj.c @@ -249,8 +249,8 @@ message_expr (expr_t *receiver, keywordarg_t *message) if (call->type == ex_error) return receiver; - if (!is_function_call (call->e.block.result)) { - internal_error (call, "unexpected block result type"); + if (!is_function_call (call)) { + internal_error (call, "unexpected call expression type"); } call->e.block.result->e.branch.ret_type = return_type; return call; From 1ce026d16846603894a05b6101af729a963aa720 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 18:58:42 +0900 Subject: [PATCH 2415/3664] [qfcc] Implement bounced return pointer calls This is achieved by marking a void function with the void_return attribute and then calling that function in an @return expression. @return can be used only inside a void function and only with void functions marked with the void_return attribute. As this is intended for Objective-QC message forwarding, it is deliberately "difficult" to use as returning a larger than expected value is unlikely to end well for the calling function. However, as a convenience, "@return nil" is allowed (in a void function). It always returns an integer (which, of course,can be interpreted as a pointer). This is safe because if the return value is ignored, it will go into the progs return buffer, and if it is not ignored, it is the smallest value that can be returned. --- tools/qfcc/include/expr.h | 4 +++- tools/qfcc/include/type.h | 2 ++ tools/qfcc/source/expr.c | 24 ++++++++++++++++++++++++ tools/qfcc/source/qc-lex.l | 1 + tools/qfcc/source/qc-parse.y | 7 ++++++- tools/qfcc/source/statements.c | 26 ++++++++++++++++++++++++-- 6 files changed, 60 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5181dfbc6..2b3887ae1 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -236,6 +236,7 @@ typedef struct { typedef struct { struct expr_s *ret_val; + int at_return; ///< return void_return call through void } ex_return_t; typedef struct { @@ -244,7 +245,7 @@ typedef struct { } ex_adjstk_t; typedef struct { - short mode; ///< currently must be 0 + short mode; short reg; ///< base register to load struct expr_s *with; ///< value to load } ex_with_t; @@ -791,6 +792,7 @@ expr_t *goto_expr (expr_t *label); expr_t *jump_table_expr (expr_t *table, expr_t *index); expr_t *call_expr (expr_t *func, expr_t *args, struct type_s *ret_type); expr_t *return_expr (struct function_s *f, expr_t *e); +expr_t *at_return_expr (struct function_s *f, expr_t *e); expr_t *conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2); expr_t *incop_expr (int op, expr_t *e, int postop); expr_t *array_expr (expr_t *array, expr_t *index); diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 1c4f9223d..63fb194e3 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -42,6 +42,7 @@ typedef struct ty_func_s { union { struct { unsigned no_va_list:1;///< don't inject va_list for ... function + unsigned void_return:1;///< special handling for return value }; unsigned attribute_bits; }; @@ -106,6 +107,7 @@ typedef struct { unsigned is_overload:1; unsigned nosave:1; unsigned no_va_list:1; + unsigned void_return:1; }; unsigned spec_bits; }; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 0d96f4fcf..65eeb2468 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2477,6 +2477,30 @@ return_expr (function_t *f, expr_t *e) return new_return_expr (e); } +expr_t * +at_return_expr (function_t *f, expr_t *e) +{ + const type_t *ret_type = unalias_type (f->type->t.func.type); + + if (!is_void(ret_type)) { + return error (e, "use of @return in non-void function"); + } + if (is_nil (e)) { + // int or pointer 0 seems reasonable + return new_return_expr (new_int_expr (0)); + } else if (!is_function_call (e)) { + return error (e, "@return value not a function"); + } + expr_t *call_expr = e->e.block.result->e.branch.target; + const type_t *call_type = get_type (call_expr); + if (!is_func (call_type) && !call_type->t.func.void_return) { + return error (e, "@return function not void_return"); + } + expr_t *ret_expr = new_return_expr (e); + ret_expr->e.retrn.at_return = 1; + return ret_expr; +} + expr_t * conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2) { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index e0467f1ef..dc30f7748 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -392,6 +392,7 @@ static keyword_t qf_keywords[] = { {"@args", ARGS, 0 }, {"@va_list", TYPE, &type_va_list }, {"@param", TYPE, &type_param }, + {"@return", AT_RETURN, 0 }, {"@cross", CROSS, 0 }, {"@dot", DOT, 0 }, diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 7fd7d658d..2874965a2 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -149,7 +149,8 @@ int yylex (void); %token CLASS_NAME NAME %token VALUE STRING -%token LOCAL RETURN WHILE DO IF ELSE FOR BREAK CONTINUE ELLIPSIS +%token LOCAL WHILE DO IF ELSE FOR BREAK CONTINUE +%token RETURN AT_RETURN ELLIPSIS %token NIL GOTO SWITCH CASE DEFAULT ENUM %token ARGS TYPEDEF EXTERN STATIC SYSTEM OVERLOAD NOT ATTRIBUTE %token UNSIGNED SIGNED LONG SHORT @@ -251,6 +252,8 @@ parse_attributes (attribute_t *attr_list) spec.no_va_list = 1; } else if (!strcmp (attr->name, "nosave")) { spec.nosave = 1; + } else if (!strcmp (attr->name, "void_return")) { + spec.void_return = 1; } else { warning (0, "skipping unknown attribute '%s'", attr->name); } @@ -425,6 +428,7 @@ static void set_func_type_attrs (type_t *func, specifier_t spec) { func->t.func.no_va_list = spec.no_va_list; + func->t.func.void_return = spec.void_return; } %} @@ -1420,6 +1424,7 @@ statement | local_def { $$ = $1; } | RETURN opt_expr ';' { $$ = return_expr (current_func, $2); } | RETURN compound_init ';' { $$ = return_expr (current_func, $2); } + | AT_RETURN expr ';' { $$ = at_return_expr (current_func, $2); } | BREAK ';' { $$ = 0; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 6fdefa80b..78a4eb469 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1427,11 +1427,18 @@ statement_return (sblock_t *sblock, expr_t *e) if (e->e.retrn.ret_val) { expr_t *ret_val = e->e.retrn.ret_val; type_t *ret_type = get_type (ret_val); - s->opa = return_operand (ret_type, e); + + // at_return is used for passing the result of a void_return + // function through void. v6 progs always use .return for the + // return value, so don't need to do anything special: just call + // the function and do a normal void return + if (!e->e.retrn.at_return) { + s->opa = return_operand (ret_type, e); + } sblock = statement_subexpr (sblock, ret_val, &s->opa); } } else { - if (e->e.retrn.ret_val) { + if (!e->e.retrn.at_return && e->e.retrn.ret_val) { expr_t *ret_val = e->e.retrn.ret_val; type_t *ret_type = get_type (ret_val); pr_ushort_t ret_crtl = type_size (ret_type) - 1; @@ -1440,6 +1447,21 @@ statement_return (sblock_t *sblock, expr_t *e) ret_crtl |= mode << 5; s->opc = short_operand (ret_crtl, e); } else { + if (e->e.retrn.at_return) { + expr_t *call = e->e.retrn.ret_val; + if (!call || !is_function_call (call)) { + internal_error (e, "@return with no call"); + } + // FIXME hard-coded reg, and assumes 3 is free + #define REG 3 + expr_t *with = new_with_expr (11, REG, new_short_expr (0)); + def_t *ret_ptr = new_def (0, 0, 0, sc_local); + operand_t *ret_op = def_operand (ret_ptr, &type_void, e); + ret_ptr->reg = REG; + expr_file_line (with, e); + sblock = statement_slist (sblock, with); + sblock = statement_subexpr (sblock, call, &ret_op); + } s->opa = short_operand (0, e); s->opb = short_operand (0, e); s->opc = short_operand (-1, e); // void return From 1fa3acf2d761c64db3a17ef363d50510926ed7e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 19:13:46 +0900 Subject: [PATCH 2416/3664] [ruamoko] Support return values in message forwarding This is the libr side of the return pointer bouncing. --- ruamoko/include/runtime.h | 2 +- ruamoko/lib/Object.r | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/include/runtime.h b/ruamoko/include/runtime.h index 276d270fb..849b9be1e 100644 --- a/ruamoko/include/runtime.h +++ b/ruamoko/include/runtime.h @@ -45,7 +45,7 @@ typedef enum { //obj_error_handler obj_set_error_handler (objc_error_handler func); @extern IMP obj_msg_lookup (id receiver, SEL op); @extern IMP obj_msg_lookup_super (Super class, SEL op); -@extern @param obj_msg_sendv (id receiver, SEL op, @va_list args); +@extern @attribute(void_return) void obj_msg_sendv (id receiver, SEL op, @va_list args); @extern BOOL obj_decrement_ref_was_zero (id object); @extern BOOL obj_increment_ref_was_zero (id object); @extern void *obj_malloc (int size); diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index 03a1519ad..711721d1d 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -17,7 +17,7 @@ IMP (id receiver, SEL op) obj_msg_lookup = #0; IMP (Super class, SEL op) obj_msg_lookup_super = #0; id (id receiver, SEL op, ...) obj_msgSend = #0; id obj_msgSend_super (Super *class, SEL op, ...) = #0; -@param (id receiver, SEL op, @va_list args) obj_msg_sendv = #0; +@attribute(void_return) void obj_msg_sendv (id receiver, SEL op, @va_list args) = #0; int obj_decrement_retaincount (id object) = #0; int obj_increment_retaincount (id object) = #0; int obj_get_retaincount (id object) = #0; From 6f4bb0df2cd83327a058b038c84dbe84ec23d37c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 19:14:07 +0900 Subject: [PATCH 2417/3664] [qfcc] Update sendv test to use @return The return value can't be checked in the test, but it was useful for getting everything actually working. --- tools/qfcc/test/sendv.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/test/sendv.r b/tools/qfcc/test/sendv.r index 24929992a..aaf7e19cd 100644 --- a/tools/qfcc/test/sendv.r +++ b/tools/qfcc/test/sendv.r @@ -15,7 +15,7 @@ send (id obj, string cmd, string str) params[0].pointer_val = obj; params[1].pointer_val = sel; params[2].string_val = str; - obj_msg_sendv (obj, sel, va_list); + @return obj_msg_sendv (obj, sel, va_list); } @interface Object //just so the runtime doesn't complain From ab8692bd96bb6a1a74dd2201616d5cc6b78fb1d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 19:16:06 +0900 Subject: [PATCH 2418/3664] [qwaq] Allow return values through forwarded messages This was easy to achieve in v6p progs because all return values passed through .return and thus could not be lost. However, Ruamoko progs use a return pointer which can wind up pointed into the void (the return buffer) and thus cause the return value to be lost. Using @return on obj_msg_sendv bounces the return pointer through to the called function. In addition, nil is returned when the forwarding target is nil. --- ruamoko/qwaq/ui/proxyview.r | 4 ++-- ruamoko/qwaq/ui/view.r | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/ui/proxyview.r b/ruamoko/qwaq/ui/proxyview.r index 714b3fd9d..c39358092 100644 --- a/ruamoko/qwaq/ui/proxyview.r +++ b/ruamoko/qwaq/ui/proxyview.r @@ -10,9 +10,9 @@ - (void) forward: (SEL) sel : (@va_list) args { if (!view) { - return; + @return nil; } - obj_msg_sendv (view, sel, args); + @return obj_msg_sendv (view, sel, args); } -initWithView:(View *) view diff --git a/ruamoko/qwaq/ui/view.r b/ruamoko/qwaq/ui/view.r index c7fbe58c8..1b7fb4c06 100644 --- a/ruamoko/qwaq/ui/view.r +++ b/ruamoko/qwaq/ui/view.r @@ -264,12 +264,12 @@ updateScreenCursor (View *view) - (void) forward: (SEL) sel : (@va_list) args { if (!textContext) { - return; + @return nil; } if (!__obj_responds_to (textContext, sel)) { [self error: "no implementation for %s", sel_get_name (sel)]; } - obj_msg_sendv (textContext, sel, args); + @return obj_msg_sendv (textContext, sel, args); } - (void) refresh From f4b81d30b04498523dbcf54e609987b3651799b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 19:22:08 +0900 Subject: [PATCH 2419/3664] [qwaq] Pass the correct selector when listeners respond This is actually an old bug in qwaq that was masked by v6p progs parameter passing: it was just luck that event got put in the correct parameter and not trampled until the responder saw it. Ruamoko progs, however, simply lost the event entirely because it never got explicitly passed by the listener implementation. --- ruamoko/qwaq/ui/listener.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/ui/listener.r b/ruamoko/qwaq/ui/listener.r index 8fa43b01f..1776e9ffe 100644 --- a/ruamoko/qwaq/ui/listener.r +++ b/ruamoko/qwaq/ui/listener.r @@ -90,7 +90,7 @@ -(void)respond: (void *) caller_data withObject:(void *)anObject { - [listeners makeObjectsPerformSelector: @selector (respond:) + [listeners makeObjectsPerformSelector: @selector (respond:withObject:) withObject: caller_data withObject: anObject]; } From c10b09d41b1d197684c463f68e1104497b89fa6b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 20:24:17 +0900 Subject: [PATCH 2420/3664] [ruamoko] Make RUA_Sprintf more generally useful It now takes the function name to print in error message (passed on to PR_Sprintf) and the argument number of the format string. The variable arguments (in ...) are assumed to be immediately after the format argument. --- include/rua_internal.h | 4 +++- libs/ruamoko/rua_string.c | 14 +++++++------- ruamoko/qwaq/builtins/main.c | 2 +- tools/qfcc/test/test-bi.c | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/rua_internal.h b/include/rua_internal.h index a41177bae..955e6d5e6 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -52,7 +52,9 @@ void RUA_String_Init (struct progs_s *pr, int secure); void RUA_QFile_Init (struct progs_s *pr, int secure); void RUA_QFS_Init (struct progs_s *pr, int secure); -void RUA_Sprintf (struct progs_s *pr, struct dstring_s *dstr); +// the variable args are assumed to come immediately after fmt_arg +void RUA_Sprintf (struct progs_s *pr, struct dstring_s *dstr, const char *func, + int fmt_arg); int QFile_AllocHandle (struct progs_s *pr, QFile *file); QFile *QFile_GetFile (struct progs_s *pr, int handle); diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 314c6d099..f5ccd6d86 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -61,14 +61,14 @@ bi_strlen (progs_t *pr) } void -RUA_Sprintf (progs_t *pr, dstring_t *dstr) +RUA_Sprintf (progs_t *pr, dstring_t *dstr, const char *func, int fmt_arg) { - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; + const char *fmt = P_GSTRING (pr, fmt_arg); + int count = pr->pr_argc - (fmt_arg + 1); + pr_type_t **args = pr->pr_params + (fmt_arg + 1); if (pr->progs->version == PROG_VERSION) { - __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, (fmt_arg + 1)); count = va_list->count; if (count) { args = alloca (count * sizeof (pr_type_t *)); @@ -80,7 +80,7 @@ RUA_Sprintf (progs_t *pr, dstring_t *dstr) } } - PR_Sprintf (pr, dstr, "bi_sprintf", fmt, count, args); + PR_Sprintf (pr, dstr, func, fmt, count, args); } static void @@ -89,7 +89,7 @@ bi_sprintf (progs_t *pr) dstring_t *dstr; dstr = dstring_newstr (); - RUA_Sprintf (pr, dstr); + RUA_Sprintf (pr, dstr, "sprintf", 0); RETURN_STRING (pr, dstr->str); dstring_delete (dstr); } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 3a0561035..9bb4d838f 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -150,7 +150,7 @@ bi_printf (progs_t *pr) { dstring_t *dstr = dstring_new (); - RUA_Sprintf (pr, dstr); + RUA_Sprintf (pr, dstr, "printf", 0); if (dstr->str) { Sys_Printf ("%s", dstr->str); } diff --git a/tools/qfcc/test/test-bi.c b/tools/qfcc/test/test-bi.c index e12220f8f..1965db082 100644 --- a/tools/qfcc/test/test-bi.c +++ b/tools/qfcc/test/test-bi.c @@ -54,7 +54,7 @@ bi_printf (progs_t *pr) dstring_clear (dstr); } - RUA_Sprintf (pr, dstr); + RUA_Sprintf (pr, dstr, "printf", 0); if (dstr->str) { fputs (dstr->str, stdout); From fbb67419f294226962d0941970277cfefd0f77cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 20:26:06 +0900 Subject: [PATCH 2421/3664] [qwaq] Use RUA_Sprintf for non-va_list printers This fixes the runtime error when the debugger gets to the end of the gcd test program. --- ruamoko/qwaq/builtins/curses.c | 41 +++++++++++----------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index dfd3d1e40..504939543 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -46,6 +46,8 @@ #include "QF/ringbuffer.h" #include "QF/sys.h" +#include "rua_internal.h" + #include "ruamoko/qwaq/qwaq.h" #include "ruamoko/qwaq/ui/curses.h" #include "ruamoko/qwaq/ui/rect.h" @@ -763,9 +765,6 @@ static void bi_syncprintf (progs_t *pr) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - const char *fmt = P_GSTRING (pr, 0); - int count = pr->pr_argc - 1; - pr_type_t **args = pr->pr_params + 1; int string_id = qwaq_pipe_acquire_string (&res->commands); dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_syncprint, 0, string_id }; @@ -773,7 +772,7 @@ bi_syncprintf (progs_t *pr) command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "mvwaddstr", fmt, count, args); + RUA_Sprintf (pr, print_buffer, "syncprintf", 0); qwaq_pipe_submit (&res->commands, command, command[1]); } @@ -1135,8 +1134,7 @@ bi_mvwaddstr (progs_t *pr) } static void -qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, - int count, pr_type_t **args) +qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, int fmt_arg) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); @@ -1151,7 +1149,7 @@ qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, const char *fmt, command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "mvwaddstr", fmt, count, args); + RUA_Sprintf (pr, print_buffer, "mvwaddstr", fmt_arg); qwaq_pipe_submit (&res->commands, command, command[1]); } @@ -1162,16 +1160,12 @@ bi_mvwprintf (progs_t *pr) int window_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); - const char *fmt = P_GSTRING (pr, 3); - int count = pr->pr_argc - 4; - pr_type_t **args = pr->pr_params + 4; - qwaq_mvwprintf (pr, window_id, x, y, fmt, count, args); + qwaq_mvwprintf (pr, window_id, x, y, 3); } static void -qwaq_wprintf (progs_t *pr, int window_id, const char *fmt, - int count, pr_type_t **args) +qwaq_wprintf (progs_t *pr, int window_id, int fmt_arg) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); @@ -1186,7 +1180,7 @@ qwaq_wprintf (progs_t *pr, int window_id, const char *fmt, command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "waddstr", fmt, count, args); + RUA_Sprintf (pr, print_buffer, "wprintf", fmt_arg); qwaq_pipe_submit (&res->commands, command, command[1]); } @@ -1195,11 +1189,8 @@ static void bi_wprintf (progs_t *pr) { int window_id = P_INT (pr, 0); - const char *fmt = P_GSTRING (pr, 1); - int count = pr->pr_argc - 2; - pr_type_t **args = pr->pr_params + 2; - qwaq_wprintf (pr, window_id, fmt, count, args); + qwaq_wprintf (pr, window_id, 1); } static void @@ -1224,7 +1215,7 @@ qwaq_wvprintf (progs_t *pr, int window_id, const char *fmt, pr_va_list_t *args) command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "waddstr", fmt, args->count, list); + PR_Sprintf (pr, print_buffer, "wvprintf", fmt, args->count, list); qwaq_pipe_submit (&res->commands, command, command[1]); } @@ -1283,7 +1274,7 @@ qwaq_mvwvprintf (progs_t *pr, int window_id, int x, int y, command[1] = CMD_SIZE(command); dstring_clearstr (print_buffer); - PR_Sprintf (pr, print_buffer, "waddstr", fmt, args->count, list); + PR_Sprintf (pr, print_buffer, "mvwvprintf", fmt, args->count, list); qwaq_pipe_submit (&res->commands, command, command[1]); } @@ -1667,22 +1658,16 @@ bi__i_TextContext__mvprintf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); - const char *fmt = P_GSTRING (pr, 3); - int count = pr->pr_argc - 4; - pr_type_t **args = pr->pr_params + 4; - qwaq_mvwprintf (pr, window_id, pos->x, pos->y, fmt, count, args); + qwaq_mvwprintf (pr, window_id, pos->x, pos->y, 3); } static void bi__i_TextContext__printf_ (progs_t *pr) { int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; - const char *fmt = P_GSTRING (pr, 2); - int count = pr->pr_argc - 3; - pr_type_t **args = pr->pr_params + 3; - qwaq_wprintf (pr, window_id, fmt, count, args); + qwaq_wprintf (pr, window_id, 2); } static void From 5f2fd3cac0befa927a6c212450acd15afe686747 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Feb 2022 20:36:38 +0900 Subject: [PATCH 2422/3664] [qfcc] Skip over zero stack adjustment This is a very tiny optimization, but there's no point in adjust the stack if there's no actual adjustment. I didn't bother with it initially because I thought it wouldn't happen (and I was more interested in getting things working first), but it turns out that simple getters that result in a zero adjustment are quite common (70/535 in qwaq-app.dat). --- tools/qfcc/source/function.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 42f757b9e..c2381d93b 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -801,7 +801,12 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements) dstatement_t *st = &pr.code->code[func->code]; if (st->op == OP_ADJSTK) { - st->b = -func->params_start; + if (func->params_start) { + st->b = -func->params_start; + } else { + // skip over adjstk so a zero adjustment doesn't get executed + func->code += 1; + } } merge_spaces (space, func->parameters->space, STACK_ALIGN); func->parameters->space = space; From e1ecda9221f143c91f5dd5969581a9691bc59ec4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 12:20:17 +0900 Subject: [PATCH 2423/3664] [gamecode] Add unsigned divide and remainder instructions I had forgotten that unsigned division was different from signed division (rather silly of me). However, with some testing and analysis, unsigned true modulo is not needed as it's not possible to have negative inputs and thus it's the same as remainder. --- libs/gamecode/opcodes.py | 15 ++- libs/gamecode/pr_exec.c | 48 +++---- libs/gamecode/test/test-unsigned.c | 204 +++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 23 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 3aa2ec324..4bb1b5704 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -8,7 +8,7 @@ bitmap_txt = """ 0 0000 0000 noop 0 0000 0001 adjstk 0 0000 0010 constant -0 1011 nnnn +0 1011 otss udivops 0 1111 s0mm load64 0 1111 s1mm store64 0 1111 n000 @@ -483,6 +483,18 @@ return_formats = { "format": "%Mc5", "types": "ev_void, ev_void, ev_void", } +udivops_formats = { + "opcode": "OP_{op_udiv[o].upper()}_{udiv_type[t]}_{ss+1}", + "mnemonic": "{op_udiv[o]}.{udiv_type[t]}", + "opname": "{op_udiv[o]}", + "widths": "{ss+1}, {ss+1}, {ss+1}", + "types": "{udiv_types[t]}, {udiv_types[t]}, {udiv_types[t]}", + "args": { + "op_udiv": ["div", "rem"], + "udiv_type": ['u', 'U'], + "udiv_types": ["ev_uint", "ev_ulong"], + }, +} vecops_formats = { "opcode": "OP_{op_vop[ooo].upper()}_{vop_type[t]}", "mnemonic": "{op_vop[ooo]}.{vop_type[t]}", @@ -556,6 +568,7 @@ group_map = { "string": string_formats, "swizzle": swizzle_formats, "return": return_formats, + "udivops": udivops_formats, "vecops": vecops_formats, "vecops2": vecops2_formats, "with": with_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index bd3879431..387ddc28d 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2974,8 +2974,33 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) OP_cmp(LT, <); // 0 1010 OP_cmp(GT, >); + +#define OP_op_1(OP, T, t, op) \ + case OP_##OP##_##T##_1: \ + OPC(t) = (OPA(t) op OPB(t)); \ + break +#define OP_op_2(OP, T, t, op) \ + case OP_##OP##_##T##_2: \ + OPC(t) = (OPA(t) op OPB(t)); \ + break +#define OP_op_3(OP, T, t, op) \ + case OP_##OP##_##T##_3: \ + VectorCompOp (&OPC(t), &OPA(t), op, &OPB(t)); \ + break; +#define OP_op_4(OP, T, t, op) \ + case OP_##OP##_##T##_4: \ + OPC(t) = (OPA(t) op OPB(t)); \ + break +#define OP_op_T(OP, T, t1, t2, t4, op) \ + OP_op_1 (OP, T, t1, op); \ + OP_op_2 (OP, T, t2, op); \ + OP_op_3 (OP, T, t1, op); \ + OP_op_4 (OP, T, t4, op) // 0 1011 - // spare + OP_op_T (DIV, u, uint, uivec2, uivec4, /); + OP_op_T (DIV, U, ulong, ulvec2, ulvec4, /); + OP_op_T (REM, u, uint, uivec2, uivec4, %); + OP_op_T (REM, U, ulong, ulvec2, ulvec4, %); // 0 1100 OP_cmp(NE, !=); // 0 1101 @@ -3011,27 +3036,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; // spare -#define OP_op_1(OP, T, t, op) \ - case OP_##OP##_##T##_1: \ - OPC(t) = (OPA(t) op OPB(t)); \ - break -#define OP_op_2(OP, T, t, op) \ - case OP_##OP##_##T##_2: \ - OPC(t) = (OPA(t) op OPB(t)); \ - break -#define OP_op_3(OP, T, t, op) \ - case OP_##OP##_##T##_3: \ - VectorCompOp (&OPC(t), &OPA(t), op, &OPB(t)); \ - break; -#define OP_op_4(OP, T, t, op) \ - case OP_##OP##_##T##_4: \ - OPC(t) = (OPA(t) op OPB(t)); \ - break -#define OP_op_T(OP, T, t1, t2, t4, op) \ - OP_op_1 (OP, T, t1, op); \ - OP_op_2 (OP, T, t2, op); \ - OP_op_3 (OP, T, t1, op); \ - OP_op_4 (OP, T, t4, op) #define OP_op(OP, op) \ OP_op_T (OP, I, int, ivec2, ivec4, op); \ OP_op_T (OP, F, float, vec2, vec4, op); \ diff --git a/libs/gamecode/test/test-unsigned.c b/libs/gamecode/test/test-unsigned.c index e37a84d94..66f68e482 100644 --- a/libs/gamecode/test/test-unsigned.c +++ b/libs/gamecode/test/test-unsigned.c @@ -2,6 +2,63 @@ #include "QF/mathlib.h" +static pr_uivec4_t uint_divop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_uivec4_t uint_divop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 1, 0x55555553, 0, 0}, + { 2, 2, 5, -5}, +}; + +static dstatement_t uint_divop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -1, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_DIV_u_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_REM_u_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_JUMP_A), -6, 0, 0 }, +}; + +static dstatement_t uint_divop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 4, 0, 32 }, // index +//loop: + { OP(0, 0, 0, OP_LEA_C), 32, -2, 32 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 32 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 32, 1 }, + { OP(1, 1, 1, OP_DIV_u_2), 0, 4, 8 }, + { OP(1, 1, 1, OP_REM_u_2), 0, 4, 12 }, + { OP(1, 1, 1, OP_JUMP_A), -6, 0, 0 }, +}; + +static dstatement_t uint_divop_3a_statements[] = { + { OP(1, 1, 1, OP_DIV_u_3), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_u_1), 3, 7, 11 }, + { OP(1, 1, 1, OP_REM_u_3), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_u_1), 3, 7, 15 }, +}; + +static dstatement_t uint_divop_3b_statements[] = { + { OP(1, 1, 1, OP_DIV_u_1), 0, 4, 8 }, + { OP(1, 1, 1, OP_DIV_u_3), 1, 5, 9 }, + { OP(1, 1, 1, OP_REM_u_1), 0, 4, 12 }, + { OP(1, 1, 1, OP_REM_u_3), 1, 5, 13 }, +}; + +static dstatement_t uint_divop_4_statements[] = { + { OP(1, 1, 1, OP_DIV_u_4), 0, 4, 8 }, + { OP(1, 1, 1, OP_REM_u_4), 0, 4, 12 }, +}; + static pr_uivec4_t uint_cmpop_init[] = { { 5, -5, 5, -5}, { 5, 5, -5, -5}, @@ -95,6 +152,63 @@ static dstatement_t uint_cmpop_4_statements[] = { { OP(1, 1, 1, OP_LE_u_4), 0, 4, 28 }, }; +static pr_ulvec4_t ulong_divop_init[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, +}; + +static pr_ulvec4_t ulong_divop_expect[] = { + { 5, -5, 5, -5}, + { 3, 3, -3, -3}, + { 1, UINT64_C(0x5555555555555553), 0, 0}, + { 2, 2, 5, -5}, +}; + +static dstatement_t ulong_divop_1_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -2, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_DIV_U_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_REM_U_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_JUMP_A), -6, 0, 0 }, +}; + +static dstatement_t ulong_divop_2_statements[] = { + { OP(0, 0, 0, OP_LEA_A), 8, 0, 64 }, // init index +//loop: + { OP(0, 0, 0, OP_LEA_C), 64, -4, 64 }, // dec index + { OP(0, 0, 0, OP_IFAE), 2, 0, 64 }, + { OP(0, 0, 0, OP_BREAK), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 4, 64, 1 }, + { OP(1, 1, 1, OP_DIV_U_2), 0, 8, 16 }, + { OP(1, 1, 1, OP_REM_U_2), 0, 8, 24 }, + { OP(1, 1, 1, OP_JUMP_A), -6, 0, 0 }, +}; + +static dstatement_t ulong_divop_3a_statements[] = { + { OP(1, 1, 1, OP_DIV_U_3), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_U_1), 6, 14, 22 }, + { OP(1, 1, 1, OP_REM_U_3), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_U_1), 6, 14, 30 }, +}; + +static dstatement_t ulong_divop_3b_statements[] = { + { OP(1, 1, 1, OP_DIV_U_1), 0, 8, 16 }, + { OP(1, 1, 1, OP_DIV_U_3), 2, 10, 18 }, + { OP(1, 1, 1, OP_REM_U_1), 0, 8, 24 }, + { OP(1, 1, 1, OP_REM_U_3), 2, 10, 26 }, +}; + +static dstatement_t ulong_divop_4_statements[] = { + { OP(1, 1, 1, OP_DIV_U_4), 0, 8, 16 }, + { OP(1, 1, 1, OP_REM_U_4), 0, 8, 24 }, +}; + static pr_ulvec4_t ulong_cmpop_init[] = { { 5, -5, 5, -5}, { 5, 5, -5, -5}, @@ -387,6 +501,51 @@ static dstatement_t ulong_shiftop_4_statements[] = { }; test_t tests[] = { + { + .desc = "uint divop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_1_statements), + .statements = uint_divop_1_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, + { + .desc = "uint divop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_2_statements), + .statements = uint_divop_2_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, + { + .desc = "uint divop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_3a_statements), + .statements = uint_divop_3a_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, + { + .desc = "uint divop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_3b_statements), + .statements = uint_divop_3b_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, + { + .desc = "uint divop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(uint_divop_init,uint_divop_expect), + .num_statements = num_statements (uint_divop_4_statements), + .statements = uint_divop_4_statements, + .init_globals = (pr_int_t *) uint_divop_init, + .expect_globals = (pr_int_t *) uint_divop_expect, + }, { .desc = "uint cmpop 1", .extra_globals = 4 * 1, @@ -432,6 +591,51 @@ test_t tests[] = { .init_globals = (pr_int_t *) uint_cmpop_init, .expect_globals = (pr_int_t *) uint_cmpop_expect, }, + { + .desc = "ulong divop 1", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_1_statements), + .statements = ulong_divop_1_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, + { + .desc = "ulong divop 2", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_2_statements), + .statements = ulong_divop_2_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, + { + .desc = "ulong divop 3a", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_3a_statements), + .statements = ulong_divop_3a_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, + { + .desc = "ulong divop 3b", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_3b_statements), + .statements = ulong_divop_3b_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, + { + .desc = "ulong divop 4", + .extra_globals = 4 * 1, + .num_globals = num_globals(ulong_divop_init,ulong_divop_expect), + .num_statements = num_statements (ulong_divop_4_statements), + .statements = ulong_divop_4_statements, + .init_globals = (pr_int_t *) ulong_divop_init, + .expect_globals = (pr_int_t *) ulong_divop_expect, + }, { .desc = "ulong cmpop 1", .extra_globals = 4 * 1, From 95c4cdd1b0f8fe107a1df21dbc5596173e259be8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 13:12:16 +0900 Subject: [PATCH 2424/3664] [vulkan] Set frame buffer before calling draw functions This lets them set up their subpass inherit info correctly. QF now renders correctly, albeit painfully slowly, on my VersaPro. --- libs/video/renderer/vid_render_vulkan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 2d7c5bf97..ef35d022a 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -147,6 +147,7 @@ vulkan_R_RenderFrame (SCR_Func *scr_funcs) for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { __auto_type rp = vulkan_ctx->renderPasses.a[i]; __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + frame->framebuffer = rp->framebuffers->a[imageIndex]; rp->draw (rpFrame); } @@ -164,7 +165,6 @@ vulkan_R_RenderFrame (SCR_Func *scr_funcs) __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; if (rpFrame->renderpass) { - frame->framebuffer = rp->framebuffers->a[imageIndex]; renderPassInfo.framebuffer = frame->framebuffer, renderPassInfo.renderPass = rp->renderpass; renderPassInfo.clearValueCount = rp->clearValues->size; From 7c6ef06dfb821b21abb89904c1c3cf04f1fbc398 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 19:34:46 +0900 Subject: [PATCH 2425/3664] [gamecode] Make PF_VarString v6p-only It's not enforced a this stage, and it would be easy enough to handle, but it turns out all the standard quake and quakeworld progs never used ... for the print functions: the behavior of PF_VarString was undocumented and so... tough :P. --- include/QF/progs.h | 2 +- libs/ruamoko/pr_cmds.c | 18 ++---------------- nq/source/sv_pr_cmds.c | 10 +++++----- qw/source/sv_pr_cmds.c | 10 +++++----- qw/source/sv_pr_qwe.c | 6 +++--- 5 files changed, 16 insertions(+), 30 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 85b720bbf..0fd8efdfc 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1843,7 +1843,7 @@ extern struct cvar_s *pr_faultchecks; */ ///@{ -char *PF_VarString (progs_t *pr, int first); +char *PF_VarString (progs_t *pr, int first, int count); void PR_Cmds_Init (progs_t *pr); extern const char *pr_gametype; diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 93cec016e..1b03f1bad 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -54,27 +54,13 @@ VISIBLE const char *pr_gametype = ""; /* BUILT-IN FUNCTIONS */ VISIBLE char * -PF_VarString (progs_t *pr, int first) +PF_VarString (progs_t *pr, int first, int argc) { char *out, *dst; const char *src; int len, i; - int argc = pr->pr_argc; pr_type_t **argv = pr->pr_params; - if (pr->progs->version == PROG_VERSION) { - __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 0); - argc = va_list->count; - if (argc) { - argv = alloca (argc * sizeof (pr_type_t *)); - for (int i = 0; i < argc; i++) { - argv[i] = &pr->pr_globals[va_list->list + i * 4]; - } - } else { - argv = 0; - } - } - for (len = 0, i = first; i < argc; i++) len += strlen (PR_GetString (pr, argv[i]->string_var)); dst = out = Hunk_TempAlloc (0, len + 1); @@ -367,7 +353,7 @@ PF_eprint (progs_t *pr) static void PF_dprint (progs_t *pr) { - Sys_Printf ("%s", PF_VarString (pr, 0)); + Sys_Printf ("%s", PF_VarString (pr, 0, 1)); } /* diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 38755c8f9..40bd9e72a 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -71,7 +71,7 @@ PF_error (progs_t *pr) const char *s; edict_t *ed; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); Sys_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); @@ -95,7 +95,7 @@ PF_objerror (progs_t *pr) const char *s; edict_t *ed; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); Sys_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); @@ -287,7 +287,7 @@ PF_bprint (progs_t *pr) { const char *s; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); SV_BroadcastPrintf ("%s", s); } @@ -307,7 +307,7 @@ PF_sprint (progs_t *pr) unsigned entnum; entnum = P_EDICTNUM (pr, 0); - s = PF_VarString (pr, 1); + s = PF_VarString (pr, 1, 2); if (entnum < 1 || entnum > svs.maxclients) { Sys_Printf ("tried to sprint to a non-client\n"); @@ -336,7 +336,7 @@ PF_centerprint (progs_t *pr) unsigned entnum; entnum = P_EDICTNUM (pr, 0); - s = PF_VarString (pr, 1); + s = PF_VarString (pr, 1, 2); if (entnum < 1 || entnum > svs.maxclients) { Sys_Printf ("tried to sprint to a non-client\n"); diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index e01448de6..f05d3a4cf 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -73,7 +73,7 @@ PF_error (progs_t *pr) const char *s; edict_t *ed; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); Sys_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); @@ -97,7 +97,7 @@ PF_objerror (progs_t *pr) const char *s; edict_t *ed; - s = PF_VarString (pr, 0); + s = PF_VarString (pr, 0, 1); Sys_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString (pr, pr->pr_xfunction->descriptor->name), s); ed = PROG_TO_EDICT (pr, *sv_globals.self); @@ -222,7 +222,7 @@ PF_bprint (progs_t *pr) level = P_FLOAT (pr, 0); - s = PF_VarString (pr, 1); + s = PF_VarString (pr, 1, 2); SV_BroadcastPrintf (level, "%s", s); } @@ -254,7 +254,7 @@ PF_sprint (progs_t *pr) if (client->state == cs_server) //FIXME record to mvd? return; - s = PF_VarString (pr, 2); + s = PF_VarString (pr, 2, 3); SV_ClientPrintf (1, client, level, "%s", s); } @@ -286,7 +286,7 @@ PF_centerprint (progs_t *pr) if (cl->state == cs_server) //FIXME record to mvd? return; - s = PF_VarString (pr, 1); + s = PF_VarString (pr, 1, 2); MSG_ReliableWrite_Begin (&cl->backbuf, svc_centerprint, 2 + strlen (s)); MSG_ReliableWrite_String (&cl->backbuf, s); diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index c67f695fc..eb7322800 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -190,7 +190,7 @@ PF_substr (progs_t *pr) static void PF_strcat (progs_t *pr) { - RETURN_STRING (pr, PF_VarString (pr, 0)); + RETURN_STRING (pr, PF_VarString (pr, 0, pr->pr_argc)); } /* @@ -454,7 +454,7 @@ PF_log (progs_t *pr) name = va (0, "%s/%s.log", qfs_gamedir->dir.def, P_GSTRING (pr, 0)); file = QFS_Open (name, "a"); - text = PF_VarString (pr, 2); + text = PF_VarString (pr, 2, pr->pr_argc); clean_text (text); if (P_FLOAT (pr, 1)) @@ -475,7 +475,7 @@ PF_log (progs_t *pr) static void PF_conprint (progs_t *pr) { - Sys_Printf ("%s", PF_VarString (pr, 0)); + Sys_Printf ("%s", PF_VarString (pr, 0, pr->pr_argc)); } #define QWE (PR_RANGE_QWE << PR_RANGE_SHIFT) | From eba614336da7fbd06e56a7eb37005e22e1ab2de0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 19:40:16 +0900 Subject: [PATCH 2426/3664] [gamecode] Add single-component float bitop instructions These add legacy support for basic float bitops (& | ^ ~). Avoiding the instructions would require tot only the source to be converted, but also the servers (as they do access those fields), and this seemed to be too much. --- libs/gamecode/opcodes.py | 21 ++++++++++++++++++++- libs/gamecode/pr_exec.c | 13 ++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 4bb1b5704..4ec39a71f 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -31,7 +31,7 @@ bitmap_txt = """ 1 1110 c111 stated 1 1111 00mm lea 1 1111 01td vecops2 -1 1111 10nn +1 1111 10oo fbitops 1 1111 1100 convert (conversion mode in st->b) 1 1111 1101 with (mode in st->a, value in st->b, reg in st->c) 1 1111 1110 @@ -186,6 +186,24 @@ convert_formats = { "widths": "-1, 0, -1", "types": "ev_void, ev_short, ev_void", } +fbitops_formats = { + "opcode": "OP_{op_fbit[oo].upper()}_F", + "mnemonic": "{op_fbit[oo]}.f", + "opname": "{op_fbit[oo]}", + "format": "{fbit_fmt[oo]}", + "widths": "1, 1, 1", + "types": "{fbit_types[0]}, {fbit_types[oo==3]}, {fbit_types[0]}", + "args": { + "op_fbit": ["bitand", "bitor", "bitxor", "bitnot"], + "fbit_types": ["ev_float", "ev_invalid"], + "fbit_fmt": [ + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %Gb, %gc", + "%Ga, %gc", + ], + }, +} hops_formats = { "opcode": "OP_HOPS", "mnemonic": "hops", @@ -548,6 +566,7 @@ group_map = { "compare2": compare2_formats, "constant": constant_formats, "convert": convert_formats, + "fbitops": fbitops_formats, "hops": hops_formats, "jump": jump_formats, "lea": lea_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 387ddc28d..c24d35bcf 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -3467,7 +3467,18 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_V4QMUL_D: OPC(dvec4) = vqmuld (OPA(dvec4), OPB(dvec4)); break; - // 10nn spare + case OP_BITAND_F: + OPC(float) = (int) OPA(float) & (int) OPB(float); + break; + case OP_BITOR_F: + OPC(float) = (int) OPA(float) | (int) OPB(float); + break; + case OP_BITXOR_F: + OPC(float) = (int) OPA(float) ^ (int) OPB(float); + break; + case OP_BITNOT_F: + OPC(float) = ~ (int) OPA(float); + break; case OP_CONV: switch (st->b) { #include "libs/gamecode/pr_convert.cinc" From 748f578856c9c2c66c9c9bab0fcb11429d9365d7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 19:47:22 +0900 Subject: [PATCH 2427/3664] [qw] Fix incorrect "server to client" log messages It's not very helpful thinking all the packets are incoming to the client. --- include/netchan.h | 8 +++----- qw/source/cl_demo.c | 2 +- qw/source/cl_main.c | 4 ++-- qw/source/net_packetlog.c | 10 ++++++---- qw/source/sv_main.c | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/netchan.h b/include/netchan.h index a71902f64..5fe10eb81 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -64,12 +64,10 @@ extern struct msg_s *net_message; extern struct cvar_s *qport; -int Net_Log_Init (const char **sound_precache); +int Net_Log_Init (const char **sound_precache, int server); void Net_LogPrintf (const char *fmt, ...) __attribute__ ((format (PRINTF, 1, 2))); -void Log_Incoming_Packet (const byte *p, int len, int has_sequence, - int is_server); -void Log_Outgoing_Packet (const byte *p, int len, int has_sequence, - int is_server); +void Log_Incoming_Packet (const byte *p, int len, int has_sequence); +void Log_Outgoing_Packet (const byte *p, int len, int has_sequence); void Net_LogStop (void *data); void Analyze_Client_Packet (const byte * data, int len, int has_sequence); void Analyze_Server_Packet (const byte * data, int len, int has_sequence); diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 39d27b249..e82e45d10 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -422,7 +422,7 @@ CL_GetMessage (void) if (net_packetlog->int_val) Log_Incoming_Packet (net_message->message->data, - net_message->message->cursize, 1, 0); + net_message->message->cursize, 1); if (cls.demorecording) diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 98ed535a5..bfd520246 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1027,7 +1027,7 @@ CL_ReadPackets (void) if (cls.demoplayback && net_packetlog->int_val) Log_Incoming_Packet (net_message->message->data, - net_message->message->cursize, 0, 0); + net_message->message->cursize, 0); // remote command packet if (*(int *) net_message->message->data == -1) { @@ -1863,7 +1863,7 @@ Host_Init (void) for (i = 0; i < MAX_MODELS; i++) sound_precache[i] = cl.sound_name[i]; - Net_Log_Init (sound_precache); + Net_Log_Init (sound_precache, 0); } CL_HTTP_Init (); diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index 72dbe22d0..19314f089 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -166,6 +166,7 @@ static QFile *Net_PacketLog; static const char **Net_sound_precache; static sizebuf_t _packet; static qmsg_t packet = {0, 0, &_packet}; +static int is_server = 0; static int Net_LogStart (const char *fname) @@ -224,7 +225,7 @@ ascii_dump_buf (unsigned char *buf, int len) } */ void -Log_Incoming_Packet (const byte *p, int len, int has_sequence, int is_server) +Log_Incoming_Packet (const byte *p, int len, int has_sequence) { if (!net_loglevel->int_val) return; @@ -248,7 +249,7 @@ Log_Incoming_Packet (const byte *p, int len, int has_sequence, int is_server) } void -Log_Outgoing_Packet (const byte *p, int len, int has_sequence, int is_server) +Log_Outgoing_Packet (const byte *p, int len, int has_sequence) { if (!net_loglevel->int_val) return; @@ -952,7 +953,7 @@ Analyze_Client_Packet (const byte * data, int len, int has_sequence) static void net_packet_log_f (int length, const void *data, netadr_t to) { - Log_Outgoing_Packet (data, length, 1, 1); + Log_Outgoing_Packet (data, length, 1); } static void @@ -981,8 +982,9 @@ Net_PacketLog_Zap_f (void) } int -Net_Log_Init (const char **sound_precache) +Net_Log_Init (const char **sound_precache, int server) { + is_server = server; Net_sound_precache = sound_precache; _stdout = Qdopen (1, "wt"); // create a QFile of stdout diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index c97fc8647..1d81ff1af 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -1747,7 +1747,7 @@ void SV_OutOfBand (netadr_t adr, unsigned length, byte *data) { if (net_packetlog->int_val) { - Log_Outgoing_Packet (data, length, 0, 1); + Log_Outgoing_Packet (data, length, 0); } Netchan_OutOfBand (adr, length, data); } @@ -1781,7 +1781,7 @@ SV_ReadPackets (void) while (NET_GetPacket ()) { if (net_packetlog->int_val) Log_Incoming_Packet (net_message->message->data, - net_message->message->cursize, 1, 1); + net_message->message->cursize, 1); if (SV_FilterIP (net_from.ip, &until)) { SV_SendBan (until); // tell them we aren't listening... continue; @@ -2465,7 +2465,7 @@ SV_InitNet (void) Netchan_Init (); net_realtime = &realtime; - Net_Log_Init (sv.sound_precache); + Net_Log_Init (sv.sound_precache, 1); svs.last_heartbeat = -99999; // send immediately sv_net_initialized = 1; From ff08ef3fa3750816dc567dc2fb3907413b978d60 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 19:48:59 +0900 Subject: [PATCH 2428/3664] [nq,qw] Fix segfault when calling think Think has no "other", and E_POINTER doesn't check for null (by design: it's meant to be as fast as possible). --- nq/include/sv_progs.h | 2 +- qw/include/sv_progs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 79622a1fb..4a09f1c5a 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -224,7 +224,7 @@ sv_pr_exec (edict_t *self, edict_t *other, pr_func_t func) PR_RESET_PARAMS (&sv_pr_state); P_INT (&sv_pr_state, 0) = E_POINTER (self, this); P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = E_POINTER (other, this); + P_INT (&sv_pr_state, 2) = other ? E_POINTER (other, this) : 0; } PR_ExecuteProgram (&sv_pr_state, func); if ((this = sv_pr_state.fields.this) != -1) { diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index e3ebc6b70..701475b7e 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -229,7 +229,7 @@ sv_pr_exec (edict_t *self, edict_t *other, pr_func_t func) PR_RESET_PARAMS (&sv_pr_state); P_INT (&sv_pr_state, 0) = E_POINTER (self, this); P_INT (&sv_pr_state, 1) = 0; - P_INT (&sv_pr_state, 2) = E_POINTER (other, this); + P_INT (&sv_pr_state, 2) = other ? E_POINTER (other, this) : 0; } PR_ExecuteProgram (&sv_pr_state, func); if ((this = sv_pr_state.fields.this) != -1) { From 5f6e0767d7475c14d115bd27a2b9f7d67e9faffb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 20:05:35 +0900 Subject: [PATCH 2429/3664] [qfcc] Make the meaning of vec * vec selectable Currently only via pragma (not command line options), but I needed to test the concept. Converting legacy code is just too error prone. Telling the compiler how to treat the operator makes more sense. When * acts as @dot with Ruamoko progs, the result is automatically aliased as a float as this is the legacy meaning (ie, float result for dot product). --- tools/qfcc/include/options.h | 5 +++++ tools/qfcc/source/expr_binary.c | 10 +++++++-- tools/qfcc/source/options.c | 7 +++++++ tools/qfcc/source/pragma.c | 37 ++++++++++++++++++++++++++++++++- tools/qfcc/source/qc-lex.l | 1 + 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index 0c274bf7c..42b95c257 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -49,6 +49,10 @@ typedef struct { qboolean promote_float; // promote float through ... } code_options_t; +typedef struct { + int vector_mult; // operation for vector * vector +} math_options_t; + typedef struct { qboolean promote; // Promote warnings to errors qboolean cow; // Warn on copy-on-write detection @@ -93,6 +97,7 @@ typedef struct { typedef struct { code_options_t code; // Code generation options + math_options_t math; // Various math options warn_options_t warnings; // Warning options notice_options_t notices; // Notice options bug_options_t bug; // Bug options diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 8c2881a64..8077eb372 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -745,9 +745,15 @@ vector_compare (int op, expr_t *e1, expr_t *e2) static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2) { expr_t *e = new_binary_expr ('*', e1, e2); - if (options.code.progsversion < PROG_VERSION) { + if (options.math.vector_mult == DOT) { // vector * vector is dot product in v6 progs (ick) - e->e.expr.type = &type_float; + e->e.expr.op = DOT; + if (options.code.progsversion == PROG_VERSION) { + e->e.expr.type = &type_vector; + e = new_alias_expr (&type_float, e); + } else { + e->e.expr.type = &type_float; + } } else { // component-wise multiplication e->e.expr.type = &type_vector; diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index c8a0a7ff0..c9cec0127 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -51,6 +51,9 @@ #include "tools/qfcc/include/options.h" #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/type.h" + +#include "tools/qfcc/source/qc-parse.h" const char *this_program; const char **source_files; @@ -720,6 +723,8 @@ DecodeArgs (int argc, char **argv) options.code.local_merging = false; if (options.code.vector_components == (qboolean) -1) options.code.vector_components = true; + if (options.math.vector_mult == 0) + options.math.vector_mult = DOT; } if (!options.code.progsversion) options.code.progsversion = PROG_VERSION; @@ -736,6 +741,8 @@ DecodeArgs (int argc, char **argv) options.code.local_merging = true; if (options.code.vector_components == (qboolean) -1) options.code.vector_components = false; + if (options.math.vector_mult == 0) + options.math.vector_mult = options.advanced == 1 ? DOT : '*'; } else { options.code.promote_float = 0; } diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index 9d107edab..2ee208ca5 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -50,6 +50,8 @@ #include "tools/qfcc/include/strpool.h" #include "tools/qfcc/include/type.h" +#include "tools/qfcc/source/qc-parse.h" + typedef struct pragma_arg_s { struct pragma_arg_s *next; const char *arg; @@ -139,7 +141,7 @@ static void set_optimize (pragma_arg_t *args) { if (!args) { - warning (0, "missing warn flag"); + warning (0, "missing optimize flag"); return; } const char *flag = args->arg; @@ -153,6 +155,37 @@ set_optimize (pragma_arg_t *args) } } +static pragma_arg_t * +set_vector_mult (pragma_arg_t *args) +{ + if (!args) { + warning (0, "missing vector_mult arg"); + return args; + } + const char *op = args->arg; + if (!strcmp (op, "@dot")) { + options.math.vector_mult = DOT; + } else { + warning (0, "unknown vector_mult arg: %s", op); + } + return args->next; +} + +static void +set_math (pragma_arg_t *args) +{ + if (!args) { + warning (0, "missing math arg"); + return; + } + while (args) { + const char *a = args->arg; + if (!strcmp (a, "vector_mult")) { + args = set_vector_mult (args->next); + } + } +} + void pragma_process () { @@ -175,6 +208,8 @@ pragma_process () set_warn (pragma_args->next); } else if (!strcmp (id, "optimize")) { set_optimize (pragma_args->next); + } else if (!strcmp (id, "math")) { + set_math (pragma_args->next); } else { warning (0, "unknown pragma: '%s'", id); } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index dc30f7748..c74dcea4a 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -284,6 +284,7 @@ STRING \"(\\.|[^"\\])*\" BEGIN (GRAB_OTHER); // ignore rest of line } {ID} { pragma_add_arg (yytext); } +@{ID} { pragma_add_arg (yytext); } <*>\r*\n { if (YY_START == PRAGMA) { From afe8c8fca5707e43e9be2b8747865231999c2d0f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 20:10:47 +0900 Subject: [PATCH 2430/3664] [qfcc] Auto-demote double for vector scaling This was missed in the switch to an explicit scale instruction. --- tools/qfcc/source/expr_binary.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 8077eb372..e32e26ead 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -160,7 +160,7 @@ static expr_type_t vector_vector[] = { #define vector_short vector_float static expr_type_t vector_double[] = { - {'*', &type_vector}, + {'*', &type_vector, 0, &type_float, vector_scale}, {'/', 0, 0, 0, inverse_multiply}, {0, 0} }; @@ -488,7 +488,7 @@ static expr_type_t double_float[] = { }; static expr_type_t double_vector[] = { - {'*', &type_vector}, + {'*', &type_vector, &type_float, 0, vector_scale}, {0, 0} }; From 211cd657e0a69fd2bae965ad2bba051bdbcdb1c2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 20:12:22 +0900 Subject: [PATCH 2431/3664] [qfcc] Alias entity to int for comparison The ruamoko ISA has no entity comparison operators because an entity is just an int in disguise. --- tools/qfcc/source/expr_binary.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index e32e26ead..832abdc09 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -54,6 +54,7 @@ static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); static expr_t *vector_compare (int op, expr_t *e1, expr_t *e2); static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2); static expr_t *vector_scale (int op, expr_t *e1, expr_t *e2); +static expr_t *entity_compare (int op, expr_t *e1, expr_t *e2); static expr_type_t string_string[] = { {'+', &type_string}, @@ -166,8 +167,8 @@ static expr_type_t vector_double[] = { }; static expr_type_t entity_entity[] = { - {EQ, &type_int}, - {NE, &type_int}, + {EQ, &type_int, 0, 0, entity_compare}, + {NE, &type_int, 0, 0, entity_compare}, {0, 0} }; @@ -812,6 +813,18 @@ double_compare (int op, expr_t *e1, expr_t *e2) return e; } +static expr_t * +entity_compare (int op, expr_t *e1, expr_t *e2) +{ + if (options.code.progsversion == PROG_VERSION) { + e1 = new_alias_expr (&type_int, e1); + e2 = new_alias_expr (&type_int, e2); + } + expr_t *e = new_binary_expr (op, e1, e2); + e->e.expr.type = &type_int; + return e; +} + static expr_t * invalid_binary_expr (int op, expr_t *e1, expr_t *e2) { From abe43584ffb7d9c58444268fe052f7f3165d5303 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 20:13:59 +0900 Subject: [PATCH 2432/3664] [qfcc] Create vector component symbols for parameters This got lost when the stack frame setup was converted for Ruamoko. --- tools/qfcc/include/def.h | 3 +++ tools/qfcc/source/def.c | 2 +- tools/qfcc/source/function.c | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 6ecb5aae8..6892b5d8a 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -221,6 +221,9 @@ void free_temp_def (def_t *temp); */ void def_to_ddef (def_t *def, ddef_t *ddef, int aux); +void init_vector_components (struct symbol_s *vector_sym, int is_field, + struct symtab_s *symtab); + /** Initialize a def referenced by the given symbol. The symbol is checked for redefinition. A symbol is considered to be diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 849723a44..29214b5c3 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -412,7 +412,7 @@ init_elements (struct def_s *def, expr_t *eles) free_element_chain (&element_chain); } -static void +void init_vector_components (symbol_t *vector_sym, int is_field, symtab_t *symtab) { expr_t *vector_expr; diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index c2381d93b..0c1d8b680 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -542,6 +542,8 @@ create_param (symtab_t *parameters, symbol_t *param) param->s.def = def; param->sy_type = sy_var; symtab_addsymbol (parameters, param); + if (is_vector(param->type) && options.code.vector_components) + init_vector_components (param, 0, parameters); } static void From 548b7fe75359031784c53319a612457356707670 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 20:14:52 +0900 Subject: [PATCH 2433/3664] [qfcc] Set function file and line when building code I suspect this is an ancient bug that wasn't noticed due to not looking at progs.src compiled code enough, but it makes the first statements of the function point to the correct line instead of a forward declaration. --- tools/qfcc/source/function.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 0c1d8b680..e9371ea81 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -675,6 +675,9 @@ begin_function (symbol_t *sym, const char *nicename, symtab_t *parent, sym->s.func->def->nosave = 1; add_function (sym->s.func); reloc_def_func (sym->s.func, sym->s.func->def); + + sym->s.func->def->file = pr.source_file; + sym->s.func->def->line = pr.source_line; } sym->s.func->code = pr.code->size; From ab4c950c34821ba196939840633d3a5fa5b3d7b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 20:46:06 +0900 Subject: [PATCH 2434/3664] [qw] Print temp entity type number More net_packetlog improvements --- qw/source/net_packetlog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index 19314f089..92cddcb38 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -521,6 +521,7 @@ Parse_Server_Packet (int has_sequence) break; case svc_temp_entity: i = MSG_ReadByte (&packet); + Net_LogPrintf (" type %d", i); switch (i) { case 0: case 1: From 622a2e84f4063dae5a2bef8bc4463b8fabfc0a55 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 20:51:28 +0900 Subject: [PATCH 2435/3664] [nq,qw] Update WriteBytes for the Ruamoko ISA More va_list shenanigans. --- nq/source/sv_pr_cmds.c | 18 ++++++++++++++++-- qw/source/sv_pr_cmds.c | 32 +++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 40bd9e72a..eee7778a1 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -1114,10 +1114,24 @@ static void PF_WriteBytes (progs_t *pr) { int i, p; + int argc = pr->pr_argc - 1; + pr_type_t **argv = pr->pr_params + 1; sizebuf_t *msg = WriteDest (pr); - for (i = 1; i < pr->pr_argc; i++) { - p = P_FLOAT (pr, i); + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); + argc = va_list->count; + if (argc) { + argv = alloca (argc * sizeof (pr_type_t *)); + for (int i = 0; i < argc; i++) { + argv[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + argv = 0; + } + } + for (i = 0; i < argc; i++) { + p = argv[i]->float_var; MSG_WriteByte (msg, p); } } diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index f05d3a4cf..f2e9b8a37 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -1117,11 +1117,24 @@ static void PF_WriteBytes (progs_t *pr) { int i, p; - int count = pr->pr_argc - 1; byte buf[PR_MAX_PARAMS]; + int argc = pr->pr_argc - 1; + pr_type_t **argv = pr->pr_params + 1; - for (i = 0; i < count; i++) { - p = P_FLOAT (pr, i + 1); + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 1); + argc = va_list->count; + if (argc) { + argv = alloca (argc * sizeof (pr_type_t *)); + for (int i = 0; i < argc; i++) { + argv[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + argv = 0; + } + } + for (i = 0; i < argc; i++) { + p = argv[i]->float_var; buf[i] = p; } @@ -1129,17 +1142,17 @@ PF_WriteBytes (progs_t *pr) client_t *cl = Write_GetClient (pr); if (cl->state != cs_server) { - MSG_ReliableCheckBlock (&cl->backbuf, count); - MSG_ReliableWrite_SZ (&cl->backbuf, buf, count); + MSG_ReliableCheckBlock (&cl->backbuf, argc); + MSG_ReliableWrite_SZ (&cl->backbuf, buf, argc); } if (sv.recorders) { sizebuf_t *dbuf; - dbuf = SVR_WriteBegin (dem_single, cl - svs.clients, count); - SZ_Write (dbuf, buf, count); + dbuf = SVR_WriteBegin (dem_single, cl - svs.clients, argc); + SZ_Write (dbuf, buf, argc); } } else { sizebuf_t *msg = WriteDest (pr); - SZ_Write (msg, buf, count); + SZ_Write (msg, buf, argc); } } @@ -1840,7 +1853,8 @@ PF_SV_ClientNumber (progs_t *pr) int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; - if (entnum < 1 || entnum > MAX_CLIENTS || cl->state != cs_server) { + if (entnum < 1 || entnum > MAX_CLIENTS + || cl->state == cs_free || cl->state == cs_zombie) { entnum = 0; // nil entity } R_INT (pr) = entnum - 1; From 76a35c035238c8a0bbe8f9804fb71562ed45db0c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Feb 2022 20:59:49 +0900 Subject: [PATCH 2436/3664] [qfcc] Always test float against 0 for Ruamoko Float is not int, and Ruamoko has only int ifz/ifnz, which will fail for -0.0 (0x80000000 when viewed as an int). And then there's nan, but I haven't seen too many of those in quake. --- tools/qfcc/source/expr_bool.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 5894e1bad..4d3431769 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -109,8 +109,9 @@ test_expr (expr_t *e) } return e; case ev_float: - if (options.code.fast_float - || options.code.progsversion == PROG_ID_VERSION) { + if (options.code.progsversion < PROG_VERSION + && (options.code.fast_float + || options.code.progsversion == PROG_ID_VERSION)) { if (!is_float(type_default)) { if (is_constant (e)) { return cast_expr (type_default, e); From 246518f4873a5def626dbf7501d75621863c4582 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Feb 2022 10:40:26 +0900 Subject: [PATCH 2437/3664] [qfcc] Get reused type names working for local variables This allows the likes of "id id;" or typedef int foo; ... { double foo; } So long as the redeclaration is in a sub-scope. --- tools/qfcc/source/qc-parse.y | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 2874965a2..29029e543 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -265,11 +265,16 @@ static specifier_t spec_merge (specifier_t spec, specifier_t new) { if (new.type) { - if (spec.type && !spec.multi_type) { + // deal with "type " + if (!spec.type || new.sym) { + spec.sym = new.sym; + if (!spec.type) { + spec.type = new.type; + } + } else if (!spec.multi_type) { error (0, "two or more data types in declaration specifiers"); spec.multi_type = 1; } - spec.type = new.type; } if (new.is_typedef || new.storage) { if ((spec.is_typedef || spec.storage) && !spec.multi_store) { @@ -677,15 +682,7 @@ type : type_specifier | type type_specifier { - // deal with eg "int id" - $1.sym = $2.sym; - - if (!$1.sym && !$1.type) { - $1 = spec_merge ($1, $2); - } else if (!$1.sym) { - error (0, "two or more data types in declaration specifiers"); - } - $$ = $1; + $$ = spec_merge ($1, $2); } ; @@ -1410,7 +1407,7 @@ local_def local_expr = 0; (void) ($2); } - | specifiers ';' + | specifiers opt_initializer ';' { check_specifiers ($1); $$ = 0; From 2f117dd12e9e50fde23524a8bda39a65e04da2f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Feb 2022 19:29:33 +0900 Subject: [PATCH 2438/3664] [qfcc] Record referenced def in pointer dereferences When the def can be found. This fixes direct assignments to arrays (and probably structs) getting lost when the array is later read using a variable index. --- tools/qfcc/source/statements.c | 98 ++++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 78a4eb469..fda9e9a2e 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -361,6 +361,33 @@ new_statement (st_type_t type, const char *opcode, expr_t *expr) return statement; } +static void +statement_add_use (statement_t *s, operand_t *use) +{ + if (use) { + use->next = s->use; + s->use = use; + } +} + +static void +statement_add_def (statement_t *s, operand_t *def) +{ + if (def) { + def->next = s->def; + s->def = def; + } +} + +static void +statement_add_kill (statement_t *s, operand_t *kill) +{ + if (kill) { + kill->next = s->kill; + s->kill = kill; + } +} + static pseudoop_t * new_pseudoop (const char *name) { @@ -382,6 +409,18 @@ new_operand (op_type_e op, expr_t *expr, void *return_addr) return operand; } +static operand_t * +copy_operand (operand_t *src) +{ + if (!src) { + return 0; + } + operand_t *cpy = new_operand (src->op_type, src->expr, 0); + *cpy = *src; + cpy->return_addr = __builtin_return_address (0); + return cpy; +} + void free_operand (operand_t *op) { @@ -730,6 +769,8 @@ typedef sblock_t *(*expr_f) (sblock_t *, expr_t *, operand_t **); static sblock_t *statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op); static sblock_t *statement_slist (sblock_t *sblock, expr_t *e); +static sblock_t *expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op); +static sblock_t *expr_def (sblock_t *sblock, expr_t *e, operand_t **op); static sblock_t * expr_address (sblock_t *sblock, expr_t *e, operand_t **op) @@ -808,7 +849,7 @@ is_indirect (expr_t *e) static sblock_t *addressing_mode (sblock_t *sblock, expr_t *ref, operand_t **base, operand_t **offset, - pr_ushort_t *mode); + pr_ushort_t *mode, operand_t **target); static statement_t *lea_statement (operand_t *pointer, operand_t *offset, expr_t *e); @@ -945,6 +986,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) operand_t *src = 0; operand_t *dst = 0; operand_t *ofs = 0; + operand_t *target = 0; pr_ushort_t mode = 0; // assign const char *opcode = "assign"; st_type_t type = st_assign; @@ -987,8 +1029,8 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) if (0) { dereference_dst: // dst_expr is a dereferenced pointer, so need to get its addressing - // parameters (base and offset) and switch to storep instructions. - sblock = addressing_mode (sblock, dst_expr, &dst, &ofs, &mode); + // parameters (base and offset) and switch to store instructions. + sblock = addressing_mode (sblock, dst_expr, &dst, &ofs, &mode, &target); if (mode != 0) { opcode = "store"; type = st_ptrassign; @@ -1021,6 +1063,8 @@ dereference_dst: s->opa = dst; s->opb = ofs; s->opc = src; + statement_add_def (s, copy_operand (target)); + statement_add_kill (s, target); sblock_add_statement (sblock, s); return sblock; } @@ -1290,9 +1334,29 @@ statement_branch (sblock_t *sblock, expr_t *e) return sblock->next; } +static operand_t * +find_def_operand (expr_t *ref) +{ + operand_t *op = 0; + if (ref->type == ex_alias) { + return find_def_operand (ref->e.alias.expr); + } else if (ref->type == ex_address) { + return find_def_operand (ref->e.address.lvalue); + } else if (ref->type == ex_symbol) { + expr_symbol (0, ref, &op); + } else if (ref->type == ex_def) { + expr_def (0, ref, &op); + } else { + internal_error (ref, "unexpected expr type: %s", + expr_names[ref->type]); + } + return op; +} + static sblock_t * ptr_addressing_mode (sblock_t *sblock, expr_t *ref, - operand_t **base, operand_t **offset, pr_ushort_t *mode) + operand_t **base, operand_t **offset, pr_ushort_t *mode, + operand_t **target) { type_t *type = get_type (ref); if (!is_ptr (type)) { @@ -1329,7 +1393,7 @@ ptr_addressing_mode (sblock_t *sblock, expr_t *ref, alias = new_alias_expr (type, lvalue->e.alias.expr); } expr_file_line (alias, ref); - return addressing_mode (sblock, alias, base, offset, mode); + return addressing_mode (sblock, alias, base, offset, mode, target); } else if (ref->type != ex_alias || ref->e.alias.offset) { // probably just a pointer just_a_pointer: @@ -1339,7 +1403,7 @@ just_a_pointer: } else if (is_ptr (get_type (ref->e.alias.expr))) { // cast of one pointer type to another return ptr_addressing_mode (sblock, ref->e.alias.expr, base, offset, - mode); + mode, target); } else { // alias with no offset if (!is_integral (get_type (ref->e.alias.expr))) { @@ -1357,6 +1421,12 @@ just_a_pointer: expr_t *ptr = intptr->e.expr.e1; expr_t *offs = intptr->e.expr.e2; int const_offs; + if (target) { + if (ptr->type == ex_alias + && is_ptr (get_type (ptr->e.alias.expr))) { + *target = find_def_operand (ptr->e.alias.expr); + } + } // move the +/- to the offset offs = unary_expr (intptr->e.expr.op, offs); // make the base a pointer again @@ -1378,7 +1448,8 @@ just_a_pointer: static sblock_t * addressing_mode (sblock_t *sblock, expr_t *ref, - operand_t **base, operand_t **offset, pr_ushort_t *mode) + operand_t **base, operand_t **offset, pr_ushort_t *mode, + operand_t **target) { if (is_indirect (ref)) { // ref is known to be either ex_expr or ex_uexpr, with '.' for @@ -1396,7 +1467,7 @@ addressing_mode (sblock_t *sblock, expr_t *ref, *mode = 1;//entity.field } else if (ref->type == ex_uexpr) { sblock = ptr_addressing_mode (sblock, ref->e.expr.e1, base, offset, - mode); + mode, target); } else { internal_error (ref, "unexpected expression type for indirect: %s", expr_names[ref->type]); @@ -1405,6 +1476,7 @@ addressing_mode (sblock_t *sblock, expr_t *ref, sblock = statement_subexpr (sblock, ref, base); *offset = short_operand (0, ref); *mode = 0; + *target = 0; } return sblock; } @@ -1441,11 +1513,14 @@ statement_return (sblock_t *sblock, expr_t *e) if (!e->e.retrn.at_return && e->e.retrn.ret_val) { expr_t *ret_val = e->e.retrn.ret_val; type_t *ret_type = get_type (ret_val); + operand_t *target = 0; pr_ushort_t ret_crtl = type_size (ret_type) - 1; pr_ushort_t mode = 0; - sblock = addressing_mode (sblock, ret_val, &s->opa, &s->opb, &mode); + sblock = addressing_mode (sblock, ret_val, &s->opa, &s->opb, &mode, + &target); ret_crtl |= mode << 5; s->opc = short_operand (ret_crtl, e); + statement_add_use (s, target); } else { if (e->e.retrn.at_return) { expr_t *call = e->e.retrn.ret_val; @@ -1544,10 +1619,11 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) expr_t *ptr_expr = deref->e.expr.e1; operand_t *base = 0; operand_t *offset = 0; + operand_t *target = 0; pr_ushort_t mode; statement_t *s; - sblock = addressing_mode (sblock, deref, &base, &offset, &mode); + sblock = addressing_mode (sblock, deref, &base, &offset, &mode, &target); if (!*op) { *op = temp_operand (load_type, deref); @@ -1559,6 +1635,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) // addressing_mode always sets offset to 0 for mode 0 s = assign_statement (*op, base, deref); sblock_add_statement (sblock, s); + statement_add_use (s, target); return sblock; case 1://entity.field case 2://const indexed pointer @@ -1578,6 +1655,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) s = load_statement (base, offset, *op, deref); sblock_add_statement (sblock, s); } + statement_add_use (s, target); return sblock; } From 1d26c727a32ea4a4024fd5c5e237c93c0af22817 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Feb 2022 01:52:35 +0900 Subject: [PATCH 2439/3664] [ruamoko] Allocate selectors in large blocks The zone memory block header is 64 bytes, so allocating a single 8 byte selector is rather wasteful. Instead, allocate selectors in large chunks (currently 64) and divvy them out as needed. Significantly reduces memory pressure in large Ruamoko progs. --- libs/ruamoko/rua_obj.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 8f2601066..992d659a5 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -91,6 +91,9 @@ } \ } +// number of selectors to allocate at once (to minimize memory waste) +#define SELECTOR_BLOCK 64 + typedef struct obj_list_s { struct obj_list_s *next; void *data; @@ -107,6 +110,8 @@ typedef struct probj_resources_s { progs_t *pr; unsigned selector_index; unsigned selector_index_max; + pr_sel_t *selector_block; + int available_selectors; obj_list **selector_sels; pr_string_t *selector_names; pr_int_t *selector_argc; @@ -567,8 +572,14 @@ sel_register_typed_name (probj_t *probj, const char *name, const char *types, index = add_sel_name (probj, name); is_new = 1; } - if (!sel) - sel = PR_Zone_Malloc (pr, sizeof (pr_sel_t)); + if (!sel) { + if (!probj->available_selectors) { + probj->available_selectors = SELECTOR_BLOCK; + sel = PR_Zone_Malloc (pr, SELECTOR_BLOCK*sizeof (pr_sel_t)); + probj->selector_block = sel; + } + sel = &probj->selector_block[--probj->available_selectors]; + } sel->sel_id = index; sel->sel_types = PR_SetString (pr, types); @@ -2265,6 +2276,8 @@ rua_obj_cleanup (progs_t *pr, void *data) Hash_FlushTable (probj->selector_hash); probj->selector_index = 0; + probj->available_selectors = 0; + probj->selector_block = 0; for (i = 0; i < probj->selector_index_max; i++) { obj_list_free (probj->selector_sels[i]); probj->selector_sels[i] = 0; From fc8cc0b7037b692860219d8bd921a7d713d2ffc2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Feb 2022 01:57:03 +0900 Subject: [PATCH 2440/3664] [zone] Be more informative when catching memory errors The registered error handler is given a chance to report the error, and the corrupted id is printed. --- libs/util/zone.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index ce02fa76c..cfde5a3dd 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -353,13 +353,22 @@ Z_Print (memzone_t *zone) Sys_Printf ("ERROR: next block doesn't have proper back link\n"); if (!block->tag && !block->next->tag) Sys_Printf ("ERROR: two consecutive free blocks\n"); - if (block->tag - && (*(int *) ((byte *) block + block->block_size - 4) != ZONEID)) - Sys_Printf ("ERROR: memory trashed in block\n"); + int id = *(int *) ((byte *) block + block->block_size - 4); + if (block->tag && (id != ZONEID)) + Sys_Printf ("ERROR: memory trashed in block %x != %x\n", + id, ZONEID); fflush (stdout); } } +static void +z_error (memzone_t *zone, const char *msg) +{ + if (zone->error) + zone->error (zone->data, msg); + Sys_Error ("%s", msg); +} + void Z_CheckHeap (memzone_t *zone) { @@ -369,13 +378,24 @@ Z_CheckHeap (memzone_t *zone) if (block->next == &zone->blocklist) break; // all blocks have been hit if ((byte *) block + block->block_size != (byte *) block->next) - Sys_Error ("Z_CheckHeap: block size does not touch the next " - "block\n"); + z_error (zone, + "Z_CheckHeap: block size does not touch the next block"); if (block->next->prev != block) - Sys_Error ("Z_CheckHeap: next block doesn't have proper back " - "link\n"); + z_error (zone, + "Z_CheckHeap: next block doesn't have proper back link"); if (!block->tag && !block->next->tag) - Sys_Error ("Z_CheckHeap: two consecutive free blocks\n"); + z_error (zone, "Z_CheckHeap: two consecutive free blocks"); + if (block->id != ZONEID/* || block->id2 != ZONEID*/) + z_error (zone, "ERROR: block ids incorrect"); + if ((byte *) block + block->block_size != (byte *) block->next) + z_error (zone, "ERROR: block size does not touch the next block"); + if (block->next->prev != block) + z_error (zone, "ERROR: next block doesn't have proper back link"); + if (!block->tag && !block->next->tag) + z_error (zone, "ERROR: two consecutive free blocks"); + if (block->tag + && (*(int *) ((byte *) block + block->block_size - 4) != ZONEID)) + z_error (zone, "ERROR: memory trashed in block"); } } From 944a9253e9de87ab6bace57f5189594e8ecb3e6f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Feb 2022 01:58:38 +0900 Subject: [PATCH 2441/3664] [gamecode] Support %u format in PR_Sprintf Not sure why it was missed as it would have been useful even before unsigned was properly supported by qfcc. --- libs/gamecode/pr_strings.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index b8364d89c..eb0fcc6ab 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -1132,8 +1132,9 @@ fmt_state_conversion (fmt_state_t *state) state->fmt_count++; fmt_append_item (state); break; + case 'u': case 'x': - // integer, hex notation + // integer, unsigned or hex notation (*state->fi)->type = conv; (*state->fi)->data.uinteger_var = P_UINT (pr, state->fmt_count); From 39583a959e4a9d6967d99eb3f03af48f5c95f587 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Feb 2022 09:28:22 +0900 Subject: [PATCH 2442/3664] [qwaq] Show only user local defs While the .tmp defs weren't too much clutter in v6p progs, the .arg defs in Ruamoko progs make for a lot of noise. Showing only user defs (those without a leading .) makes for a much more usable locals display. --- ruamoko/qwaq/debugger/localsdata.h | 1 + ruamoko/qwaq/debugger/localsdata.r | 42 +++++++++++++++++++----------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/ruamoko/qwaq/debugger/localsdata.h b/ruamoko/qwaq/debugger/localsdata.h index bdc6ea342..70ca87a26 100644 --- a/ruamoko/qwaq/debugger/localsdata.h +++ b/ruamoko/qwaq/debugger/localsdata.h @@ -17,6 +17,7 @@ qdb_function_t *func; qdb_auxfunction_t *aux_func; qdb_def_t *defs; + int num_user_defs; DefView **def_views; int *def_rows; void *data; diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index 8fb34b601..68f9cc560 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -33,7 +33,7 @@ free_defs (LocalsData *self) { obj_free (self.defs); self.defs = nil; - for (int i = 0; i < self.aux_func.num_locals; i++) { + for (int i = 0; i < self.num_user_defs; i++) { [self.def_views[i] release]; } obj_free (self.def_views); @@ -74,17 +74,29 @@ free_defs (LocalsData *self) data = obj_malloc (func.local_size); } aux_func = qdb_get_auxfunction (target, fnum); + num_user_defs = 0; if (aux_func) { defs = qdb_get_local_defs (target, fnum); - def_views = obj_malloc (aux_func.num_locals); - def_rows = obj_malloc (aux_func.num_locals + 1); - def_rows[0] = 0; for (int i = 0; i < aux_func.num_locals; i++) { - def_views[i] = [[DefView withDef:defs[i] in:data target:target] - retain]; - def_rows[i + 1] = [def_views[i] rows]; + string def_name = qdb_get_string (target, defs[i].name); + if (str_mid (def_name, 0, 1) != ".") { + num_user_defs++; + } } - prefixsum (def_rows, aux_func.num_locals + 1); + def_views = obj_malloc (num_user_defs); + def_rows = obj_malloc (num_user_defs + 1); + def_rows[0] = 0; + for (int i = 0, j = 0; i < aux_func.num_locals; i++) { + string def_name = qdb_get_string (target, defs[i].name); + if (str_mid (def_name, 0, 1) == ".") { + continue; + } + def_views[j] = [[DefView withDef:defs[i] in:data target:target] + retain]; + def_rows[j + 1] = [def_views[j] rows]; + j++; + } + prefixsum (def_rows, num_user_defs + 1); } [onRowCountChanged respond:self]; return self; @@ -95,16 +107,16 @@ free_defs (LocalsData *self) if (data && func.local_size && func.local_data) { qdb_get_data (target, func.local_data, func.local_size, data); } - int rowCount = def_rows[aux_func.num_locals]; + int rowCount = def_rows[num_user_defs]; if (aux_func) { def_rows[0] = 0; - for (int i = 0; i < aux_func.num_locals; i++) { + for (int i = 0; i < num_user_defs; i++) { [def_views[i] fetchData]; def_rows[i + 1] = [def_views[i] rows]; } - prefixsum (def_rows, aux_func.num_locals + 1); + prefixsum (def_rows, num_user_defs + 1); } - if (rowCount != def_rows[aux_func.num_locals]) { + if (rowCount != def_rows[num_user_defs]) { [onRowCountChanged respond:self]; } return self; @@ -118,10 +130,10 @@ free_defs (LocalsData *self) -(int)numberOfRows:(TableView *)tableview { if (aux_func) { - if (!aux_func.num_locals) { + if (!num_user_defs) { return 0; } - return def_rows[aux_func.num_locals]; + return def_rows[num_user_defs]; } else if (func) { return (func.local_size + 3) / 4; } @@ -133,7 +145,7 @@ free_defs (LocalsData *self) row:(int)row { View *view = nil; - int *index = fbsearch (&row, def_rows, aux_func.num_locals, 1, nil); + int *index = fbsearch (&row, def_rows, num_user_defs, 1, nil); if (index) { DefView *dv = def_views[index - def_rows]; From c6aa061229b8a9cf8f293727b5d27f4c549e546f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Feb 2022 10:19:45 +0900 Subject: [PATCH 2443/3664] [qwaq] Fetch Ruamoko progs locals from the stack frame Now that the data is fetched from the correct location, the locals view is useful again :). However, there seems to be a problem with array views: not sure they're showing the correct data as I was getting unexpected values in the display but normal vars seem to be ok. --- ruamoko/qwaq/builtins/debug.c | 31 ++++++++++++++++++++++++++++++ ruamoko/qwaq/debugger/debug.h | 2 ++ ruamoko/qwaq/debugger/debug.r | 2 ++ ruamoko/qwaq/debugger/localsdata.h | 1 + ruamoko/qwaq/debugger/localsdata.r | 16 +++++++++++++-- 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 73eb5972f..9b1d2b45e 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -649,6 +649,35 @@ qdb_get_source_line_addr (progs_t *pr) R_UINT (pr) = PR_FindSourceLineAddr (tpr, file, line); } +static void +qdb_has_data_stack (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pr_ptr_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + + R_INT (pr) = tpr->progs->version == PROG_VERSION; +} + +static void +qdb_get_frame_addr (progs_t *pr) +{ + __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + pr_ptr_t handle = P_INT (pr, 0); + qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); + progs_t *tpr = target->pr; + + R_UINT (pr) = 0; + + if (tpr->progs->version == PROG_VERSION) { + if (tpr->pr_depth) { + prstack_t *frame = tpr->pr_stack + tpr->pr_depth - 1; + R_UINT (pr) = frame->stack_ptr; + } + } +} + #define bi(x,np,params...) {#x, x, -1, np, {params}} #define p(type) PR_PARAM(type) static builtin_t builtins[] = { @@ -675,6 +704,8 @@ static builtin_t builtins[] = { bi(qdb_get_auxfunction, 2, p(int), p(uint)), bi(qdb_get_local_defs, 2, p(int), p(uint)), bi(qdb_get_source_line_addr, 3, p(int), p(string), p(uint)), + bi(qdb_has_data_stack, 1, p(int)), + bi(qdb_get_frame_addr, 1, p(int)), {} }; diff --git a/ruamoko/qwaq/debugger/debug.h b/ruamoko/qwaq/debugger/debug.h index bfc0d4f88..788c3aff7 100644 --- a/ruamoko/qwaq/debugger/debug.h +++ b/ruamoko/qwaq/debugger/debug.h @@ -98,6 +98,8 @@ qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, unsigned fnum); qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum); unsigned qdb_get_source_line_addr(qdb_target_t target, string file, unsigned line); +int qdb_has_data_stack (qdb_target_t target); +unsigned qdb_get_frame_addr (qdb_target_t target); void traceon(); void traceoff(); diff --git a/ruamoko/qwaq/debugger/debug.r b/ruamoko/qwaq/debugger/debug.r index 3b6d25efe..523476275 100644 --- a/ruamoko/qwaq/debugger/debug.r +++ b/ruamoko/qwaq/debugger/debug.r @@ -30,3 +30,5 @@ qdb_auxfunction_t *qdb_get_auxfunction (qdb_target_t target, qdb_def_t *qdb_get_local_defs (qdb_target_t target, unsigned fnum) = #0; unsigned qdb_get_source_line_addr(qdb_target_t target, string file, unsigned line) = #0; +int qdb_has_data_stack (qdb_target_t target) = #0; +unsigned qdb_get_frame_addr (qdb_target_t target) = #0; diff --git a/ruamoko/qwaq/debugger/localsdata.h b/ruamoko/qwaq/debugger/localsdata.h index 70ca87a26..3d4080998 100644 --- a/ruamoko/qwaq/debugger/localsdata.h +++ b/ruamoko/qwaq/debugger/localsdata.h @@ -12,6 +12,7 @@ { ListenerGroup *onRowCountChanged; qdb_target_t target; + int has_stack; qfot_type_encodings_t target_encodings; unsigned current_fnum; qdb_function_t *func; diff --git a/ruamoko/qwaq/debugger/localsdata.r b/ruamoko/qwaq/debugger/localsdata.r index 68f9cc560..73b0f51cc 100644 --- a/ruamoko/qwaq/debugger/localsdata.r +++ b/ruamoko/qwaq/debugger/localsdata.r @@ -19,6 +19,8 @@ qdb_get_data (target, encodings_def.offset, sizeof(target_encodings), &target_encodings); + self.has_stack = qdb_has_data_stack (target); + self.onRowCountChanged = [[ListenerGroup listener] retain]; return self; } @@ -104,8 +106,18 @@ free_defs (LocalsData *self) -fetchData { - if (data && func.local_size && func.local_data) { - qdb_get_data (target, func.local_data, func.local_size, data); + if (data && func.local_size) { + unsigned local_data = func.local_data; + if (has_stack) { + unsigned stack_ptr = qdb_get_frame_addr (target); + local_data = 0; + if (stack_ptr) { + local_data = stack_ptr - func.local_data; + } + } + if (local_data) { + qdb_get_data (target, local_data, func.local_size, data); + } } int rowCount = def_rows[num_user_defs]; if (aux_func) { From db8cf68ef33c190d59f9a35fb7c3c5482997a899 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 12:28:38 +0900 Subject: [PATCH 2444/3664] [gamecode] Pass registered data pointer to builtins This is the bulk of the work for recording the resource pointer with with builtin data. I don't know how much of a difference it makes for most things, but it's probably pretty big for qwaq-curses due to the very high number of calls to the curses builtins. Closes #26 --- include/QF/progs.h | 4 +- include/QF/ruamoko.h | 4 +- libs/audio/snd_progs.c | 2 +- libs/console/bi_inputline.c | 68 +++-- libs/console/menu.c | 52 ++-- libs/gamecode/pr_builtins.c | 2 +- libs/gamecode/pr_exec.c | 2 +- libs/gamecode/pr_parse.c | 2 +- libs/gib/bi_gib.c | 16 +- libs/ruamoko/pr_cmds.c | 62 ++--- libs/ruamoko/rua_cbuf.c | 8 +- libs/ruamoko/rua_cmd.c | 10 +- libs/ruamoko/rua_cvar.c | 30 +- libs/ruamoko/rua_hash.c | 86 +++--- libs/ruamoko/rua_input.c | 113 ++++---- libs/ruamoko/rua_keys.c | 14 +- libs/ruamoko/rua_math.c | 90 +++--- libs/ruamoko/rua_mersenne.c | 38 +-- libs/ruamoko/rua_msgbuf.c | 184 ++++++++----- libs/ruamoko/rua_obj.c | 124 ++++----- libs/ruamoko/rua_plist.c | 121 ++++---- libs/ruamoko/rua_qfile.c | 89 +++--- libs/ruamoko/rua_qfs.c | 18 +- libs/ruamoko/rua_runtime.c | 2 +- libs/ruamoko/rua_script.c | 36 +-- libs/ruamoko/rua_set.c | 354 ++++++++++++++---------- libs/ruamoko/rua_stdlib.c | 10 +- libs/ruamoko/rua_string.c | 36 +-- libs/video/renderer/r_progs.c | 53 ++-- nq/include/server.h | 2 +- nq/include/sv_pr_cmds.h | 2 +- nq/source/sv_move.c | 4 +- nq/source/sv_pr_cmds.c | 104 +++---- qw/include/server.h | 2 +- qw/include/sv_pr_cmds.h | 2 +- qw/source/sv_move.c | 4 +- qw/source/sv_pr_cmds.c | 138 +++++----- qw/source/sv_pr_cpqw.c | 32 +-- qw/source/sv_pr_qwe.c | 42 +-- qw/source/sv_user.c | 2 +- ruamoko/qwaq/builtins/curses.c | 426 +++++++++++++++-------------- ruamoko/qwaq/builtins/debug.c | 104 +++---- ruamoko/qwaq/builtins/editbuffer.c | 142 +++++----- ruamoko/qwaq/builtins/graphics.c | 6 +- ruamoko/qwaq/builtins/main.c | 6 +- ruamoko/qwaq/builtins/term-input.c | 20 +- tools/qfcc/test/test-bi.c | 12 +- 47 files changed, 1427 insertions(+), 1253 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 0fd8efdfc..12d96f009 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -348,7 +348,7 @@ struct plitem_s *ED_ConvertToPlist (struct script_s *script, int nohack, struct hashlink_s **hashlinks); struct plitem_s *ED_Parse (progs_t *pr, const char *data); void ED_LoadFromFile (progs_t *pr, const char *data); -void ED_EntityParseFunction (progs_t *pr); +void ED_EntityParseFunction (progs_t *pr, void *data); #define PR_edicts(p) (*(p)->pr_edicts) @@ -1209,7 +1209,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ #define PR_RANGE_NONE 0xffff #define PR_AUTOBUILTIN (PR_RANGE_AUTO << PR_RANGE_SHIFT) -typedef void (*builtin_proc) (progs_t *pr); +typedef void (*builtin_proc) (progs_t *pr, void *data); /** Create a static array of these and pass the array to PR_RegisterBuiltins() to register the module's QC builtin functions. diff --git a/include/QF/ruamoko.h b/include/QF/ruamoko.h index 71c2fe6ee..7af3ff57f 100644 --- a/include/QF/ruamoko.h +++ b/include/QF/ruamoko.h @@ -44,8 +44,8 @@ pr_func_t RUA_Obj_msg_lookup (struct progs_s *pr, pr_ptr_t _self, void RUA_Game_Init (struct progs_s *pr, int secure); // self is expected in param 0 -int RUA_obj_increment_retaincount (struct progs_s *pr); +int RUA_obj_increment_retaincount (struct progs_s *pr, void *data); // self is expected in param 0 -int RUA_obj_decrement_retaincount (struct progs_s *pr); +int RUA_obj_decrement_retaincount (struct progs_s *pr, void *data); #endif//__QF_ruamoko_h diff --git a/libs/audio/snd_progs.c b/libs/audio/snd_progs.c index 912686412..52eeb945d 100644 --- a/libs/audio/snd_progs.c +++ b/libs/audio/snd_progs.c @@ -40,7 +40,7 @@ #include "QF/sound.h" static void -bi_S_LocalSound (progs_t *pr) +bi_S_LocalSound (progs_t *pr, void *data) { const char *sound = P_GSTRING (pr, 0); diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index 69494450f..1399319e5 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -91,9 +91,9 @@ il_data_index (il_resources_t *res, il_data_t *line) } static void -bi_il_clear (progs_t *pr, void *data) +bi_il_clear (progs_t *pr, void *_res) { - il_resources_t *res = (il_resources_t *)data; + il_resources_t *res = (il_resources_t *)_res; il_data_t *line; for (line = res->lines; line; line = line->next) @@ -103,9 +103,8 @@ bi_il_clear (progs_t *pr, void *data) } static il_data_t * -get_inputline (progs_t *pr, int arg, const char *func) +get_inputline (progs_t *pr, il_resources_t *res, int arg, const char *func) { - il_resources_t *res = PR_Resources_Find (pr, "InputLine"); il_data_t *line = il_data_get (res, arg); // line->prev will be null if the handle is unallocated @@ -142,9 +141,9 @@ bi_inputline_enter (inputline_t *il) } static void -bi_InputLine_Create (progs_t *pr) +bi_InputLine_Create (progs_t *pr, void *_res) { - il_resources_t *res = PR_Resources_Find (pr, "InputLine"); + il_resources_t *res = _res; il_data_t *data; inputline_t *line; int lines = P_INT (pr, 0); @@ -182,26 +181,29 @@ bi_InputLine_Create (progs_t *pr) } static void -bi_InputLine_SetPos (progs_t *pr) +bi_InputLine_SetPos (progs_t *pr, void *_res) { - il_data_t *line = get_inputline (pr, P_INT (pr, 0), + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), "InputLine_SetPos"); line->line->x = P_INT (pr, 1); line->line->y = P_INT (pr, 2); } static void -bi_InputLine_SetCursor (progs_t *pr) +bi_InputLine_SetCursor (progs_t *pr, void *_res) { - il_data_t *line = get_inputline (pr, P_INT (pr, 0), + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), "InputLine_SetCursor"); line->line->cursor = P_INT (pr, 1); } static void -bi_InputLine_SetEnter (progs_t *pr) +bi_InputLine_SetEnter (progs_t *pr, void *_res) { - il_data_t *line = get_inputline (pr, P_INT (pr, 0), + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), "InputLine_SetEnter"); line->data[1] = 0; @@ -221,9 +223,10 @@ bi_InputLine_SetEnter (progs_t *pr) } static void -bi_InputLine_SetWidth (progs_t *pr) +bi_InputLine_SetWidth (progs_t *pr, void *_res) { - il_data_t *line = get_inputline (pr, P_INT (pr, 0), + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), "InputLine_SetWidth"); int width = P_INT (pr, 1); @@ -231,10 +234,11 @@ bi_InputLine_SetWidth (progs_t *pr) } static void -bi_InputLine_Destroy (progs_t *pr) +bi_InputLine_Destroy (progs_t *pr, void *_res) { - il_resources_t *res = PR_Resources_Find (pr, "InputLine"); - il_data_t *line = get_inputline (pr, P_INT (pr, 0), "InputLine_Destroy"); + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), + "InputLine_Destroy"); Con_DestroyInputLine (line->line); *line->prev = line->next; @@ -244,18 +248,22 @@ bi_InputLine_Destroy (progs_t *pr) } static void -bi_InputLine_Clear (progs_t *pr) +bi_InputLine_Clear (progs_t *pr, void *_res) { - il_data_t *line = get_inputline (pr, P_INT (pr, 0), "InputLine_Clear"); + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), + "InputLine_Clear"); int save = P_INT (pr, 1); Con_ClearTyping (line->line, save); } static void -bi_InputLine_Process (progs_t *pr) +bi_InputLine_Process (progs_t *pr, void *_res) { - il_data_t *line = get_inputline (pr, P_INT (pr, 0), "InputLine_Process"); + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), + "InputLine_Process"); int ch = P_INT (pr, 1); Con_ProcessInputLine (line->line, ch); @@ -267,9 +275,11 @@ bi_InputLine_Process (progs_t *pr) Sets the inputline to a specified text */ static void -bi_InputLine_SetText (progs_t *pr) +bi_InputLine_SetText (progs_t *pr, void *_res) { - il_data_t *line = get_inputline (pr, P_INT (pr, 0), "InputLine_SetText"); + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), + "InputLine_SetText"); const char *str = P_GSTRING (pr, 1); inputline_t *il = line->line; @@ -286,18 +296,22 @@ bi_InputLine_SetText (progs_t *pr) Gets the text from a inputline */ static void -bi_InputLine_GetText (progs_t *pr) +bi_InputLine_GetText (progs_t *pr, void *_res) { - il_data_t *line = get_inputline (pr, P_INT (pr, 0), "InputLine_GetText"); + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), + "InputLine_GetText"); inputline_t *il = line->line; RETURN_STRING(pr, il->lines[il->edit_line]+1); } static void -bi_InputLine_Draw (progs_t *pr) +bi_InputLine_Draw (progs_t *pr, void *_res) { - il_data_t *line = get_inputline (pr, P_INT (pr, 0), "InputLine_Draw"); + il_resources_t *res = _res; + il_data_t *line = get_inputline (pr, res, P_INT (pr, 0), + "InputLine_Draw"); line->line->draw (line->line); } diff --git a/libs/console/menu.c b/libs/console/menu.c index 171de8084..896ab7b82 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -212,7 +212,7 @@ menu_pic (int x, int y, const char *name, } static void -bi_Menu_Begin (progs_t *pr) +bi_Menu_Begin (progs_t *pr, void *data) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -230,31 +230,31 @@ bi_Menu_Begin (progs_t *pr) } static void -bi_Menu_FadeScreen (progs_t *pr) +bi_Menu_FadeScreen (progs_t *pr, void *data) { menu->fadescreen = P_INT (pr, 0); } static void -bi_Menu_Draw (progs_t *pr) +bi_Menu_Draw (progs_t *pr, void *data) { menu->draw = P_FUNCTION (pr, 0); } static void -bi_Menu_EnterHook (progs_t *pr) +bi_Menu_EnterHook (progs_t *pr, void *data) { menu->enter_hook = P_FUNCTION (pr, 0); } static void -bi_Menu_LeaveHook (progs_t *pr) +bi_Menu_LeaveHook (progs_t *pr, void *data) { menu->leave_hook = P_FUNCTION (pr, 0); } static void -bi_Menu_Pic (progs_t *pr) +bi_Menu_Pic (progs_t *pr, void *data) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -264,7 +264,7 @@ bi_Menu_Pic (progs_t *pr) } static void -bi_Menu_SubPic (progs_t *pr) +bi_Menu_SubPic (progs_t *pr, void *data) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -278,7 +278,7 @@ bi_Menu_SubPic (progs_t *pr) } static void -bi_Menu_CenterPic (progs_t *pr) +bi_Menu_CenterPic (progs_t *pr, void *data) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -292,7 +292,7 @@ bi_Menu_CenterPic (progs_t *pr) } static void -bi_Menu_CenterSubPic (progs_t *pr) +bi_Menu_CenterSubPic (progs_t *pr, void *data) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -310,7 +310,7 @@ bi_Menu_CenterSubPic (progs_t *pr) } static void -bi_Menu_Item (progs_t *pr) +bi_Menu_Item (progs_t *pr, void *data) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -329,7 +329,7 @@ bi_Menu_Item (progs_t *pr) } static void -bi_Menu_Cursor (progs_t *pr) +bi_Menu_Cursor (progs_t *pr, void *data) { pr_func_t func = P_FUNCTION (pr, 0); @@ -337,7 +337,7 @@ bi_Menu_Cursor (progs_t *pr) } static void -bi_Menu_KeyEvent (progs_t *pr) +bi_Menu_KeyEvent (progs_t *pr, void *data) { pr_func_t func = P_FUNCTION (pr, 0); @@ -345,13 +345,13 @@ bi_Menu_KeyEvent (progs_t *pr) } static void -bi_Menu_End (progs_t *pr) +bi_Menu_End (progs_t *pr, void *data) { menu = menu->parent; } static void -bi_Menu_TopMenu (progs_t *pr) +bi_Menu_TopMenu (progs_t *pr, void *data) { const char *name = P_GSTRING (pr, 0); @@ -361,7 +361,7 @@ bi_Menu_TopMenu (progs_t *pr) } static void -bi_Menu_SelectMenu (progs_t *pr) +bi_Menu_SelectMenu (progs_t *pr, void *data) { const char *name = P_GSTRING (pr, 0); @@ -383,7 +383,7 @@ bi_Menu_SelectMenu (progs_t *pr) } static void -bi_Menu_SetQuit (progs_t *pr) +bi_Menu_SetQuit (progs_t *pr, void *data) { pr_func_t func = P_FUNCTION (pr, 0); @@ -391,7 +391,7 @@ bi_Menu_SetQuit (progs_t *pr) } static void -bi_Menu_Quit (progs_t *pr) +bi_Menu_Quit (progs_t *pr, void *data) { if (con_data.quit) con_data.quit (); @@ -399,7 +399,7 @@ bi_Menu_Quit (progs_t *pr) } static void -bi_Menu_GetIndex (progs_t *pr) +bi_Menu_GetIndex (progs_t *pr, void *data) { if (menu) { R_INT (pr) = menu->cur_item; @@ -409,21 +409,21 @@ bi_Menu_GetIndex (progs_t *pr) } static void -bi_Menu_Next (progs_t *pr) +bi_Menu_Next (progs_t *pr, void *data) { menu->cur_item++; menu->cur_item %= menu->num_items; } static void -bi_Menu_Prev (progs_t *pr) +bi_Menu_Prev (progs_t *pr, void *data) { menu->cur_item += menu->num_items - 1; menu->cur_item %= menu->num_items; } static void -bi_Menu_Enter (progs_t *pr) +bi_Menu_Enter (progs_t *pr, void *data) { menu_item_t *item; @@ -453,7 +453,7 @@ bi_Menu_Enter (progs_t *pr) } static void -bi_Menu_Leave (progs_t *pr) +bi_Menu_Leave (progs_t *pr, void *data) { if (menu) { if (menu->leave_hook) { @@ -490,7 +490,7 @@ quit_f (void) if (!ret) return; } - bi_Menu_Quit (&menu_pr_state); + bi_Menu_Quit (&menu_pr_state, 0); } static void * @@ -795,15 +795,15 @@ menu_key_event (const IE_event_t *ie_event) break; case QFK_DOWN: // case QFM_WHEEL_DOWN: - bi_Menu_Next (&menu_pr_state); + bi_Menu_Next (&menu_pr_state, 0); break; case QFK_UP: // case QFM_WHEEL_UP: - bi_Menu_Prev (&menu_pr_state); + bi_Menu_Prev (&menu_pr_state, 0); break; case QFK_RETURN: // case QFM_BUTTON1: - bi_Menu_Enter (&menu_pr_state); + bi_Menu_Enter (&menu_pr_state, 0); break; default: break; diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index eaec8b148..cb0a5a694 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -89,7 +89,7 @@ builtin_next (progs_t *pr) } static void -bi_no_function (progs_t *pr) +bi_no_function (progs_t *pr, void *data) { // no need for checking: the /only/ way to get here is via a function // descriptor with a bad builtin number diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index c24d35bcf..ea819c6e9 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -454,7 +454,7 @@ PR_CallFunction (progs_t *pr, pr_func_t fnum, pr_type_t *return_ptr) pr_type_t *saved_return = pr->pr_return; int builtin_depth = pr->pr_depth; pr->pr_return = return_ptr; - f->func (pr); + f->func (pr, f->data); f->profile++; // to show number times the builtin is called if (builtin_depth == pr->pr_depth) { pr->pr_return = saved_return; diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 182146261..a1c198192 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -532,7 +532,7 @@ ED_LoadFromFile (progs_t *pr, const char *data) } VISIBLE void -ED_EntityParseFunction (progs_t *pr) +ED_EntityParseFunction (progs_t *pr, void *data) { pr->edict_parse = P_FUNCTION (pr, 0); } diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index 8c0deb4e8..c0a59178c 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -98,9 +98,9 @@ bi_gib_builtin_f (void) } static void -bi_gib_builtin_clear (progs_t *progs, void *data) +bi_gib_builtin_clear (progs_t *progs, void *_res) { - bi_gib_resources_t *res = (bi_gib_resources_t *) data; + bi_gib_resources_t *res = (bi_gib_resources_t *) _res; bi_gib_builtin_t *cur; while ((cur = res->builtins)) { @@ -112,9 +112,9 @@ bi_gib_builtin_clear (progs_t *progs, void *data) } static void -bi_GIB_Builtin_Add (progs_t *pr) +bi_GIB_Builtin_Add (progs_t *pr, void *_res) { - bi_gib_resources_t *res = PR_Resources_Find (pr, "GIB"); + bi_gib_resources_t *res = _res; bi_gib_builtin_t *builtin; const char *name = P_GSTRING (pr, 0); pr_func_t func = P_FUNCTION (pr, 1); @@ -138,7 +138,7 @@ bi_GIB_Builtin_Add (progs_t *pr) } static void -bi_GIB_Return (progs_t *pr) +bi_GIB_Return (progs_t *pr, void *_res) { const char *str = P_GSTRING(pr, 0); @@ -148,7 +148,7 @@ bi_GIB_Return (progs_t *pr) } static void -bi_GIB_Handle_New (progs_t *pr) +bi_GIB_Handle_New (progs_t *pr, void *_res) { //long *qcptr = malloc (sizeof (long)); //*qcptr = P_POINTER (pr, 0); @@ -156,7 +156,7 @@ bi_GIB_Handle_New (progs_t *pr) } static void -bi_GIB_Handle_Free (progs_t *pr) +bi_GIB_Handle_Free (progs_t *pr, void *_res) { //unsigned long int hand = P_INT (pr, 0); //long *qcptr = GIB_Handle_Get (hand); @@ -166,7 +166,7 @@ bi_GIB_Handle_Free (progs_t *pr) } static void -bi_GIB_Handle_Get (progs_t *pr) +bi_GIB_Handle_Get (progs_t *pr, void *_res) { //long *hand = GIB_Handle_Get (P_INT (pr, 0)); //if (hand) diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 1b03f1bad..8e38ac948 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -77,7 +77,7 @@ PF_VarString (progs_t *pr, int first, int argc) vector (vector v) normalize */ static void -PF_normalize (progs_t *pr) +PF_normalize (progs_t *pr, void *data) { float new; float *value1; @@ -105,7 +105,7 @@ PF_normalize (progs_t *pr) float (vector v) vlen */ static void -PF_vlen (progs_t *pr) +PF_vlen (progs_t *pr, void *data) { float new; float *value1; @@ -123,7 +123,7 @@ PF_vlen (progs_t *pr) float (vector v) vectoyaw */ static void -PF_vectoyaw (progs_t *pr) +PF_vectoyaw (progs_t *pr, void *data) { float yaw; float *value1; @@ -145,7 +145,7 @@ PF_vectoyaw (progs_t *pr) vector (vector v) vectoangles */ static void -PF_vectoangles (progs_t *pr) +PF_vectoangles (progs_t *pr, void *data) { float forward, pitch, yaw; float *value1; @@ -180,7 +180,7 @@ PF_vectoangles (progs_t *pr) Returns a number from 0<= num < 1 */ static void -PF_random (progs_t *pr) +PF_random (progs_t *pr, void *data) { float num; @@ -193,7 +193,7 @@ PF_random (progs_t *pr) void () break */ static void -PF_break (progs_t *pr) +PF_break (progs_t *pr, void *data) { Sys_Printf ("break statement\n"); PR_DumpState (pr); @@ -203,7 +203,7 @@ PF_break (progs_t *pr) float (string s) cvar */ static void -PF_cvar (progs_t *pr) +PF_cvar (progs_t *pr, void *data) { const char *str; @@ -216,7 +216,7 @@ PF_cvar (progs_t *pr) void (string var, string val) cvar_set */ static void -PF_cvar_set (progs_t *pr) +PF_cvar_set (progs_t *pr, void *data) { const char *var_name, *val; cvar_t *var; @@ -238,7 +238,7 @@ PF_cvar_set (progs_t *pr) float (float f) fabs */ static void -PF_fabs (progs_t *pr) +PF_fabs (progs_t *pr, void *data) { float v; @@ -250,7 +250,7 @@ PF_fabs (progs_t *pr) entity (entity start, .(...) fld, ... match) find */ static void -PF_find (progs_t *pr) +PF_find (progs_t *pr, void *data) { const char *s = 0, *t; // ev_string int i; // ev_vector @@ -314,7 +314,7 @@ PF_find (progs_t *pr) void () coredump */ static void -PF_coredump (progs_t *pr) +PF_coredump (progs_t *pr, void *data) { ED_PrintEdicts (pr, ""); } @@ -323,7 +323,7 @@ PF_coredump (progs_t *pr) void () traceon */ static void -PF_traceon (progs_t *pr) +PF_traceon (progs_t *pr, void *data) { pr->pr_trace = true; pr->pr_trace_depth = pr->pr_depth; @@ -333,7 +333,7 @@ PF_traceon (progs_t *pr) void () traceoff */ static void -PF_traceoff (progs_t *pr) +PF_traceoff (progs_t *pr, void *data) { pr->pr_trace = false; } @@ -342,7 +342,7 @@ PF_traceoff (progs_t *pr) void (entity e) eprint */ static void -PF_eprint (progs_t *pr) +PF_eprint (progs_t *pr, void *data) { ED_PrintNum (pr, P_EDICTNUM (pr, 0), 0); } @@ -351,7 +351,7 @@ PF_eprint (progs_t *pr) void (string s) dprint */ static void -PF_dprint (progs_t *pr) +PF_dprint (progs_t *pr, void *data) { Sys_Printf ("%s", PF_VarString (pr, 0, 1)); } @@ -360,7 +360,7 @@ PF_dprint (progs_t *pr) float (float v) rint */ static void -PF_rint (progs_t *pr) +PF_rint (progs_t *pr, void *data) { float f; @@ -375,7 +375,7 @@ PF_rint (progs_t *pr) float (float v) floor */ static void -PF_floor (progs_t *pr) +PF_floor (progs_t *pr, void *data) { R_FLOAT (pr) = floor (P_FLOAT (pr, 0)); } @@ -384,7 +384,7 @@ PF_floor (progs_t *pr) float (float v) ceil */ static void -PF_ceil (progs_t *pr) +PF_ceil (progs_t *pr, void *data) { R_FLOAT (pr) = ceil (P_FLOAT (pr, 0)); } @@ -393,7 +393,7 @@ PF_ceil (progs_t *pr) entity (entity e) nextent */ static void -PF_nextent (progs_t *pr) +PF_nextent (progs_t *pr, void *data) { pr_uint_t i; edict_t *ent; @@ -424,7 +424,7 @@ PF_nextent (progs_t *pr) int (float f) ftoi */ static void -PF_ftoi (progs_t *pr) +PF_ftoi (progs_t *pr, void *data) { R_INT (pr) = P_FLOAT (pr, 0); } @@ -433,7 +433,7 @@ PF_ftoi (progs_t *pr) string (float f) ftos */ static void -PF_ftos (progs_t *pr) +PF_ftos (progs_t *pr, void *data) { char string[STRING_BUF]; int i; @@ -457,7 +457,7 @@ PF_ftos (progs_t *pr) float (int i) itof */ static void -PF_itof (progs_t *pr) +PF_itof (progs_t *pr, void *data) { R_FLOAT (pr) = P_INT (pr, 0); } @@ -466,7 +466,7 @@ PF_itof (progs_t *pr) string (int i) itos */ static void -PF_itos (progs_t *pr) +PF_itos (progs_t *pr, void *data) { char string[STRING_BUF]; @@ -479,7 +479,7 @@ PF_itos (progs_t *pr) float (string s) stof */ static void -PF_stof (progs_t *pr) +PF_stof (progs_t *pr, void *data) { R_FLOAT (pr) = atof (P_GSTRING (pr, 0)); } @@ -488,7 +488,7 @@ PF_stof (progs_t *pr) int (string s) stoi */ static void -PF_stoi (progs_t *pr) +PF_stoi (progs_t *pr, void *data) { R_INT (pr) = atoi (P_GSTRING (pr, 0)); } @@ -497,7 +497,7 @@ PF_stoi (progs_t *pr) vector (string s) stov */ static void -PF_stov (progs_t *pr) +PF_stov (progs_t *pr, void *data) { float v[3] = {0, 0, 0}; @@ -510,7 +510,7 @@ PF_stov (progs_t *pr) string (vector v) vtos */ static void -PF_vtos (progs_t *pr) +PF_vtos (progs_t *pr, void *data) { char string[STRING_BUF * 3 + 5]; @@ -526,7 +526,7 @@ PF_vtos (progs_t *pr) float (string char, string s) charcount */ static void -PF_charcount (progs_t *pr) +PF_charcount (progs_t *pr, void *data) { char goal; const char *s; @@ -558,13 +558,13 @@ PF_charcount (progs_t *pr) string () gametype */ static void -PF_gametype (progs_t *pr) +PF_gametype (progs_t *pr, void *data) { RETURN_STRING (pr, pr_gametype); } static void -PF_PR_SetField (progs_t *pr) +PF_PR_SetField (progs_t *pr, void *data) { edict_t *ent = P_EDICT (pr, 0); pr_def_t *field = PR_FindField (pr, P_GSTRING (pr, 1)); @@ -576,7 +576,7 @@ PF_PR_SetField (progs_t *pr) } static void -PF_PR_FindFunction (progs_t *pr) +PF_PR_FindFunction (progs_t *pr, void *data) { dfunction_t *func = PR_FindFunction (pr, P_GSTRING (pr, 0)); R_FUNCTION (pr) = 0; diff --git a/libs/ruamoko/rua_cbuf.c b/libs/ruamoko/rua_cbuf.c index 7f96f4783..b5689461b 100644 --- a/libs/ruamoko/rua_cbuf.c +++ b/libs/ruamoko/rua_cbuf.c @@ -59,7 +59,7 @@ get_cbuf (progs_t *pr, int arg, const char *func) } static void -bi_Cbuf_AddText (progs_t *pr) +bi_Cbuf_AddText (progs_t *pr, void *data) { const char *text = P_GSTRING (pr, 0); cbuf_t *cbuf = get_cbuf (pr, 0, __FUNCTION__); @@ -67,7 +67,7 @@ bi_Cbuf_AddText (progs_t *pr) } static void -bi_Cbuf_InsertText (progs_t *pr) +bi_Cbuf_InsertText (progs_t *pr, void *data) { const char *text = P_GSTRING (pr, 0); cbuf_t *cbuf = get_cbuf (pr, 0, __FUNCTION__); @@ -75,14 +75,14 @@ bi_Cbuf_InsertText (progs_t *pr) } static void -bi_Cbuf_Execute (progs_t *pr) +bi_Cbuf_Execute (progs_t *pr, void *data) { cbuf_t *cbuf = get_cbuf (pr, 0, __FUNCTION__); Cbuf_Execute (cbuf); } static void -bi_Cbuf_Execute_Sets (progs_t *pr) +bi_Cbuf_Execute_Sets (progs_t *pr, void *data) { cbuf_t *cbuf = get_cbuf (pr, 0, __FUNCTION__); Cbuf_Execute_Sets (cbuf); diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index c325e3c3a..9391da918 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -85,9 +85,9 @@ bi_cmd_f (void) } static void -bi_Cmd_AddCommand (progs_t *pr) +bi_Cmd_AddCommand (progs_t *pr, void *_res) { - cmd_resources_t *res = PR_Resources_Find (pr, "Cmd"); + __auto_type res = (cmd_resources_t *) _res; bi_cmd_t *cmd = malloc (sizeof (bi_cmd_t)); char *name = strdup (P_GSTRING (pr, 0)); pr_func_t func = P_FUNCTION (pr, 1); @@ -124,19 +124,19 @@ bi_cmd_clear (progs_t *pr, void *data) } static void -bi_Cmd_Argc (progs_t *pr) +bi_Cmd_Argc (progs_t *pr, void *data) { R_INT (pr) = Cmd_Argc (); } static void -bi_Cmd_Argv (progs_t *pr) +bi_Cmd_Argv (progs_t *pr, void *data) { RETURN_STRING (pr, Cmd_Argv (P_INT (pr, 0))); } static void -bi_Cmd_Args (progs_t *pr) +bi_Cmd_Args (progs_t *pr, void *data) { RETURN_STRING (pr, Cmd_Args (P_INT (pr, 0))); } diff --git a/libs/ruamoko/rua_cvar.c b/libs/ruamoko/rua_cvar.c index 12cc3fca1..4d953db9c 100644 --- a/libs/ruamoko/rua_cvar.c +++ b/libs/ruamoko/rua_cvar.c @@ -62,9 +62,9 @@ bi_alias_free (void *_a, void *unused) } static void -bi_cvar_clear (progs_t *pr, void *data) +bi_cvar_clear (progs_t *pr, void *_res) { - cvar_resources_t *res = (cvar_resources_t *) data; + cvar_resources_t *res = (cvar_resources_t *) _res; bi_alias_t *alias; while ((alias = res->aliases)) { @@ -75,9 +75,9 @@ bi_cvar_clear (progs_t *pr, void *data) } static void -bi_Cvar_MakeAlias (progs_t *pr) +bi_Cvar_MakeAlias (progs_t *pr, void *_res) { - cvar_resources_t *res = PR_Resources_Find (pr, "Cvar"); + __auto_type res = (cvar_resources_t *) _res; const char *alias_name = P_GSTRING (pr, 0); const char *cvar_name = P_GSTRING (pr, 1); cvar_t *cvar = Cvar_FindVar (cvar_name); @@ -99,9 +99,9 @@ bi_Cvar_MakeAlias (progs_t *pr) } static void -bi_Cvar_RemoveAlias (progs_t *pr) +bi_Cvar_RemoveAlias (progs_t *pr, void *_res) { - cvar_resources_t *res = PR_Resources_Find (pr, "Cvar"); + __auto_type res = (cvar_resources_t *) _res; const char *alias_name = P_GSTRING (pr, 0); bi_alias_t **a; @@ -118,7 +118,7 @@ bi_Cvar_RemoveAlias (progs_t *pr) } static void -bi_Cvar_SetString (progs_t *pr) +bi_Cvar_SetString (progs_t *pr, void *_res) { const char *varname = P_GSTRING (pr, 0); const char *val = P_GSTRING (pr, 1); @@ -131,7 +131,7 @@ bi_Cvar_SetString (progs_t *pr) } static void -bi_Cvar_SetInteger (progs_t *pr) +bi_Cvar_SetInteger (progs_t *pr, void *_res) { const char *varname = P_GSTRING (pr, 0); int val = P_INT (pr, 1); @@ -144,7 +144,7 @@ bi_Cvar_SetInteger (progs_t *pr) } static void -bi_Cvar_SetFloat (progs_t *pr) +bi_Cvar_SetFloat (progs_t *pr, void *_res) { const char *varname = P_GSTRING (pr, 0); float val = P_FLOAT (pr, 1); @@ -157,7 +157,7 @@ bi_Cvar_SetFloat (progs_t *pr) } static void -bi_Cvar_SetVector (progs_t *pr) +bi_Cvar_SetVector (progs_t *pr, void *_res) { const char *varname = P_GSTRING (pr, 0); float *val = P_VECTOR (pr, 1); @@ -170,7 +170,7 @@ bi_Cvar_SetVector (progs_t *pr) } static void -bi_Cvar_GetString (progs_t *pr) +bi_Cvar_GetString (progs_t *pr, void *_res) { const char *varname = P_GSTRING (pr, 0); cvar_t *var = Cvar_FindVar (varname); @@ -184,7 +184,7 @@ bi_Cvar_GetString (progs_t *pr) } static void -bi_Cvar_GetInteger (progs_t *pr) +bi_Cvar_GetInteger (progs_t *pr, void *_res) { const char *varname = P_GSTRING (pr, 0); cvar_t *var = Cvar_FindVar (varname); @@ -195,7 +195,7 @@ bi_Cvar_GetInteger (progs_t *pr) } static void -bi_Cvar_GetFloat (progs_t *pr) +bi_Cvar_GetFloat (progs_t *pr, void *_res) { const char *varname = P_GSTRING (pr, 0); cvar_t *var = Cvar_FindVar (varname); @@ -206,7 +206,7 @@ bi_Cvar_GetFloat (progs_t *pr) } static void -bi_Cvar_GetVector (progs_t *pr) +bi_Cvar_GetVector (progs_t *pr, void *_res) { const char *varname = P_GSTRING (pr, 0); cvar_t *var = Cvar_FindVar (varname); @@ -220,7 +220,7 @@ bi_Cvar_GetVector (progs_t *pr) } static void -bi_Cvar_Toggle (progs_t *pr) +bi_Cvar_Toggle (progs_t *pr, void *_res) { const char *varname = P_GSTRING (pr, 0); cvar_t *var; diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index c4939e1e7..c7ca65322 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -151,9 +151,9 @@ bi_free (void *key, void *_ht) } static void -bi_Hash_NewTable (progs_t *pr) +bi_Hash_NewTable (progs_t *pr, void *_res) { - hash_resources_t *res = PR_Resources_Find (pr, "Hash"); + __auto_type res = (hash_resources_t *) _res; int tsize = P_INT (pr, 0); const char *(*gk)(const void*,void*); void (*f)(void*,void*); @@ -178,9 +178,8 @@ bi_Hash_NewTable (progs_t *pr) } static bi_hashtab_t * -get_table (progs_t *pr, const char *name, int index) +get_table (progs_t *pr, hash_resources_t *res, const char *name, int index) { - hash_resources_t *res = PR_Resources_Find (pr, "Hash"); bi_hashtab_t *ht = table_get (res, index); if (!ht) @@ -189,9 +188,10 @@ get_table (progs_t *pr, const char *name, int index) } static void -bi_Hash_SetHashCompare (progs_t *pr) +bi_Hash_SetHashCompare (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); uintptr_t (*gh)(const void*,void*); int (*cmp)(const void*,const void*,void*); @@ -203,10 +203,10 @@ bi_Hash_SetHashCompare (progs_t *pr) } static void -bi_Hash_DelTable (progs_t *pr) +bi_Hash_DelTable (progs_t *pr, void *_res) { - hash_resources_t *res = PR_Resources_Find (pr, "Hash"); - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); Hash_DelTable (ht->tab); *ht->prev = ht->next; @@ -216,50 +216,56 @@ bi_Hash_DelTable (progs_t *pr) } static void -bi_Hash_FlushTable (progs_t *pr) +bi_Hash_FlushTable (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); Hash_FlushTable (ht->tab); } static void -bi_Hash_Add (progs_t *pr) +bi_Hash_Add (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = Hash_Add (ht->tab, (void *) (intptr_t) P_INT (pr, 1)); } static void -bi_Hash_AddElement (progs_t *pr) +bi_Hash_AddElement (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = Hash_AddElement (ht->tab, (void *) (intptr_t) P_INT (pr, 1)); } static void -bi_Hash_Find (progs_t *pr) +bi_Hash_Find (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = (intptr_t) Hash_Find (ht->tab, P_GSTRING (pr, 1)); } static void -bi_Hash_FindElement (progs_t *pr) +bi_Hash_FindElement (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = (intptr_t) Hash_FindElement (ht->tab, (void *) (intptr_t) P_INT (pr, 1)); } static void -bi_Hash_FindList (progs_t *pr) +bi_Hash_FindList (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); void **list, **l; pr_type_t *pr_list; int count; @@ -276,9 +282,10 @@ bi_Hash_FindList (progs_t *pr) } static void -bi_Hash_FindElementList (progs_t *pr) +bi_Hash_FindElementList (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); void **list, **l; pr_type_t *pr_list; int count; @@ -295,46 +302,50 @@ bi_Hash_FindElementList (progs_t *pr) } static void -bi_Hash_Del (progs_t *pr) +bi_Hash_Del (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = (intptr_t) Hash_Del (ht->tab, P_GSTRING (pr, 1)); } static void -bi_Hash_DelElement (progs_t *pr) +bi_Hash_DelElement (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = (intptr_t) Hash_DelElement (ht->tab, (void *) (intptr_t) P_INT (pr, 1)); } static void -bi_Hash_Free (progs_t *pr) +bi_Hash_Free (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); Hash_Free (ht->tab, (void *) (intptr_t) P_INT (pr, 1)); } static void -bi_Hash_String (progs_t *pr) +bi_Hash_String (progs_t *pr, void *_res) { R_INT (pr) = Hash_String (P_GSTRING (pr, 0)); } static void -bi_Hash_Buffer (progs_t *pr) +bi_Hash_Buffer (progs_t *pr, void *_res) { R_INT (pr) = Hash_Buffer (P_GPOINTER (pr, 0), P_INT (pr, 1)); } static void -bi_Hash_GetList (progs_t *pr) +bi_Hash_GetList (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); void **list, **l; pr_type_t *pr_list; int count; @@ -351,17 +362,18 @@ bi_Hash_GetList (progs_t *pr) } static void -bi_Hash_Stats (progs_t *pr) +bi_Hash_Stats (progs_t *pr, void *_res) { - bi_hashtab_t *ht = get_table (pr, __FUNCTION__, P_INT (pr, 0)); + __auto_type res = (hash_resources_t *) _res; + bi_hashtab_t *ht = get_table (pr, res, __FUNCTION__, P_INT (pr, 0)); Hash_Stats (ht->tab); } static void -bi_hash_clear (progs_t *pr, void *data) +bi_hash_clear (progs_t *pr, void *_res) { - hash_resources_t *res = (hash_resources_t *) data; + hash_resources_t *res = (hash_resources_t *) _res; bi_hashtab_t *ht; for (ht = res->tabs; ht; ht = ht->next) diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 406ce18bc..787fbf66c 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -57,7 +57,7 @@ typedef struct input_resources_s { } input_resources_t; static void -bi_IN_FindDeviceId (progs_t *pr) +bi_IN_FindDeviceId (progs_t *pr, void *_res) { const char *id = P_GSTRING (pr, 0); @@ -65,7 +65,7 @@ bi_IN_FindDeviceId (progs_t *pr) } static void -bi_IN_GetDeviceName (progs_t *pr) +bi_IN_GetDeviceName (progs_t *pr, void *_res) { int devid = P_INT (pr, 0); @@ -73,7 +73,7 @@ bi_IN_GetDeviceName (progs_t *pr) } static void -bi_IN_GetDeviceId (progs_t *pr) +bi_IN_GetDeviceId (progs_t *pr, void *_res) { int devid = P_INT (pr, 0); @@ -81,17 +81,17 @@ bi_IN_GetDeviceId (progs_t *pr) } static void -bi_IN_AxisInfo (progs_t *pr) +bi_IN_AxisInfo (progs_t *pr, void *_res) { } static void -bi_IN_ButtonInfo (progs_t *pr) +bi_IN_ButtonInfo (progs_t *pr, void *_res) { } static void -bi_IN_GetAxisName (progs_t *pr) +bi_IN_GetAxisName (progs_t *pr, void *_res) { int devid = P_INT (pr, 0); int axis = P_INT (pr, 1); @@ -100,7 +100,7 @@ bi_IN_GetAxisName (progs_t *pr) } static void -bi_IN_GetButtonName (progs_t *pr) +bi_IN_GetButtonName (progs_t *pr, void *_res) { int devid = P_INT (pr, 0); int button = P_INT (pr, 1); @@ -109,7 +109,7 @@ bi_IN_GetButtonName (progs_t *pr) } static void -bi_IN_GetAxisNumber (progs_t *pr) +bi_IN_GetAxisNumber (progs_t *pr, void *_res) { int devid = P_INT (pr, 0); const char *axis_name = P_GSTRING (pr, 1); @@ -118,7 +118,7 @@ bi_IN_GetAxisNumber (progs_t *pr) } static void -bi_IN_GetButtonNumber (progs_t *pr) +bi_IN_GetButtonNumber (progs_t *pr, void *_res) { int devid = P_INT (pr, 0); const char *button_name = P_GSTRING (pr, 1); @@ -127,19 +127,19 @@ bi_IN_GetButtonNumber (progs_t *pr) } static void -bi_IN_ProcessEvents (progs_t *pr) +bi_IN_ProcessEvents (progs_t *pr, void *_res) { IN_ProcessEvents (); } static void -bi_IN_ClearStates (progs_t *pr) +bi_IN_ClearStates (progs_t *pr, void *_res) { IN_ClearStates (); } static void -bi_IN_CreateButton (progs_t *pr) +bi_IN_CreateButton (progs_t *pr, void *_res) { const char *name = P_GSTRING (pr, 0); const char *desc = P_GSTRING (pr, 1); @@ -151,7 +151,7 @@ bi_IN_CreateButton (progs_t *pr) } static void -bi_IN_CreateAxis (progs_t *pr) +bi_IN_CreateAxis (progs_t *pr, void *_res) { const char *name = P_GSTRING (pr, 0); const char *desc = P_GSTRING (pr, 1); @@ -163,7 +163,7 @@ bi_IN_CreateAxis (progs_t *pr) } static void -bi_IN_GetAxisInfo (progs_t *pr) +bi_IN_GetAxisInfo (progs_t *pr, void *_res) { int devid = P_INT (pr, 0); int axis = P_INT (pr, 1); @@ -178,7 +178,7 @@ bi_IN_GetAxisInfo (progs_t *pr) } static void -bi_IN_GetButtonInfo (progs_t *pr) +bi_IN_GetButtonInfo (progs_t *pr, void *_res) { int devid = P_INT (pr, 0); int button = P_INT (pr, 1); @@ -193,9 +193,8 @@ bi_IN_GetButtonInfo (progs_t *pr) } static rua_in_cookie_t * -make_cookie (progs_t *pr, pr_func_t func, pr_ptr_t data) +make_cookie (progs_t *pr, input_resources_t *res, pr_func_t func, pr_ptr_t data) { - input_resources_t *res = PR_Resources_Find (pr, "input"); rua_in_cookie_t search = { .func = func, .data = data, @@ -212,9 +211,8 @@ make_cookie (progs_t *pr, pr_func_t func, pr_ptr_t data) } static rua_in_cookie_t * -find_cookie (progs_t *pr, pr_func_t func, pr_ptr_t data) +find_cookie (progs_t *pr, input_resources_t *res, pr_func_t func, pr_ptr_t data) { - input_resources_t *res = PR_Resources_Find (pr, "input"); rua_in_cookie_t search = { .func = func, .data = data, @@ -223,58 +221,61 @@ find_cookie (progs_t *pr, pr_func_t func, pr_ptr_t data) } static void -release_cookie (progs_t *pr, rua_in_cookie_t *cookie) +release_cookie (progs_t *pr, input_resources_t *res, rua_in_cookie_t *cookie) { if (!--cookie->users) { - input_resources_t *res = PR_Resources_Find (pr, "input"); Hash_DelElement (res->cookies, cookie); Hash_Free (res->cookies, cookie); } } static void -rua_add_axis_listener (progs_t *pr, axis_listener_t listener) +rua_add_axis_listener (progs_t *pr, input_resources_t *res, + axis_listener_t listener) { in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); pr_func_t func = P_FUNCTION (pr, 1); pr_func_t data = P_POINTER (pr, 2); - rua_in_cookie_t *cookie = make_cookie (pr, func, data); + rua_in_cookie_t *cookie = make_cookie (pr, res, func, data); IN_AxisAddListener (axis, listener, cookie); } static void -rua_remove_axis_listener (progs_t *pr, axis_listener_t listener) +rua_remove_axis_listener (progs_t *pr, input_resources_t *res, + axis_listener_t listener) { in_axis_t *axis = &P_STRUCT (pr, in_axis_t, 0); pr_func_t func = P_FUNCTION (pr, 1); pr_func_t data = P_POINTER (pr, 2); - rua_in_cookie_t *cookie = find_cookie (pr, func, data); + rua_in_cookie_t *cookie = find_cookie (pr, res, func, data); if (cookie) { IN_AxisRemoveListener (axis, listener, cookie); - release_cookie (pr, cookie); + release_cookie (pr, res, cookie); } } static void -rua_add_button_listener (progs_t *pr, button_listener_t listener) +rua_add_button_listener (progs_t *pr, input_resources_t *res, + button_listener_t listener) { in_button_t *button = &P_STRUCT (pr, in_button_t, 0); pr_func_t func = P_FUNCTION (pr, 1); pr_func_t data = P_POINTER (pr, 2); - rua_in_cookie_t *cookie = make_cookie (pr, func, data); + rua_in_cookie_t *cookie = make_cookie (pr, res, func, data); IN_ButtonAddListener (button, listener, cookie); } static void -rua_remove_button_listener (progs_t *pr, button_listener_t listener) +rua_remove_button_listener (progs_t *pr, input_resources_t *res, + button_listener_t listener) { in_button_t *button = &P_STRUCT (pr, in_button_t, 0); pr_func_t func = P_FUNCTION (pr, 1); pr_func_t data = P_POINTER (pr, 2); - rua_in_cookie_t *cookie = find_cookie (pr, func, data); + rua_in_cookie_t *cookie = find_cookie (pr, res, func, data); if (cookie) { IN_ButtonRemoveListener (button, listener, cookie); - release_cookie (pr, cookie); + release_cookie (pr, res, cookie); } } @@ -330,80 +331,88 @@ rua_button_listener_method (void *data, const in_button_t *button) } static void -rua_IN_ButtonAddListener_func (progs_t *pr) +rua_IN_ButtonAddListener_func (progs_t *pr, void *_res) { - rua_add_button_listener (pr, rua_button_listener_func); + input_resources_t *res = _res; + rua_add_button_listener (pr, res, rua_button_listener_func); } static void -rua_IN_ButtonRemoveListener_func (progs_t *pr) +rua_IN_ButtonRemoveListener_func (progs_t *pr, void *_res) { - rua_remove_button_listener (pr, rua_button_listener_func); + input_resources_t *res = _res; + rua_remove_button_listener (pr, res, rua_button_listener_func); } static void -rua_IN_AxisAddListener_func (progs_t *pr) +rua_IN_AxisAddListener_func (progs_t *pr, void *_res) { - rua_add_axis_listener (pr, rua_axis_listener_func); + input_resources_t *res = _res; + rua_add_axis_listener (pr, res, rua_axis_listener_func); } static void -rua_IN_AxisRemoveListener_func (progs_t *pr) +rua_IN_AxisRemoveListener_func (progs_t *pr, void *_res) { - rua_remove_axis_listener (pr, rua_axis_listener_func); + input_resources_t *res = _res; + rua_remove_axis_listener (pr, res, rua_axis_listener_func); } static void -rua_IN_ButtonAddListener_method (progs_t *pr) +rua_IN_ButtonAddListener_method (progs_t *pr, void *_res) { - rua_add_button_listener (pr, rua_button_listener_method); + input_resources_t *res = _res; + rua_add_button_listener (pr, res, rua_button_listener_method); } static void -rua_IN_ButtonRemoveListener_method (progs_t *pr) +rua_IN_ButtonRemoveListener_method (progs_t *pr, void *_res) { - rua_remove_button_listener (pr, rua_button_listener_method); + input_resources_t *res = _res; + rua_remove_button_listener (pr, res, rua_button_listener_method); } static void -rua_IN_AxisAddListener_method (progs_t *pr) +rua_IN_AxisAddListener_method (progs_t *pr, void *_res) { - rua_add_axis_listener (pr, rua_axis_listener_method); + input_resources_t *res = _res; + rua_add_axis_listener (pr, res, rua_axis_listener_method); } static void -rua_IN_AxisRemoveListener_method (progs_t *pr) +rua_IN_AxisRemoveListener_method (progs_t *pr, void *_res) { - rua_remove_axis_listener (pr, rua_axis_listener_method); + input_resources_t *res = _res; + rua_remove_axis_listener (pr, res, rua_axis_listener_method); } static void -bi_IN_LoadConfig (progs_t *pr) +bi_IN_LoadConfig (progs_t *pr, void *_res) { IN_LoadConfig (Plist_GetItem (pr, P_INT (pr, 0))); } static void -bi_IMT_CreateContext (progs_t *pr) +bi_IMT_CreateContext (progs_t *pr, void *_res) { const char *name = P_GSTRING (pr, 0); R_INT (pr) = IMT_CreateContext (name); } static void -bi_IMT_GetContext (progs_t *pr) +bi_IMT_GetContext (progs_t *pr, void *_res) { R_INT (pr) = IMT_GetContext (); } static void -bi_IMT_SetContext (progs_t *pr) +bi_IMT_SetContext (progs_t *pr, void *_res) { IMT_SetContext (P_INT (pr, 0)); } static void -secured (progs_t *pr) +secured (progs_t *pr, void *_res) { PR_RunError (pr, "Secured function called"); } diff --git a/libs/ruamoko/rua_keys.c b/libs/ruamoko/rua_keys.c index d6e9acaa8..7a0d5d43f 100644 --- a/libs/ruamoko/rua_keys.c +++ b/libs/ruamoko/rua_keys.c @@ -41,7 +41,7 @@ #include "QF/zone.h" static void -bi_Key_keydown (progs_t *pr) +bi_Key_keydown (progs_t *pr, void *data) { #if 0 int keynum = P_INT (pr, 0); @@ -55,7 +55,7 @@ bi_Key_keydown (progs_t *pr) QC-Function for set a binding */ static void -bi_Key_SetBinding (progs_t *pr) +bi_Key_SetBinding (progs_t *pr, void *data) { #if 0 const char *imt_name = P_GSTRING (pr, 0); @@ -80,7 +80,7 @@ bi_Key_SetBinding (progs_t *pr) Perform a reverse-binding-lookup */ static void -bi_Key_LookupBinding (progs_t *pr) +bi_Key_LookupBinding (progs_t *pr, void *data) { #if 0 const char *imt_name = P_GSTRING (pr, 0); @@ -118,7 +118,7 @@ bi_Key_LookupBinding (progs_t *pr) Counts how often a binding is assigned to a key */ static void -bi_Key_CountBinding (progs_t *pr) +bi_Key_CountBinding (progs_t *pr, void *data) { #if 0 const char *imt_name = P_GSTRING (pr, 0); @@ -151,7 +151,7 @@ bi_Key_CountBinding (progs_t *pr) Convertes a keynum to a string */ static void -bi_Key_KeynumToString (progs_t *pr) +bi_Key_KeynumToString (progs_t *pr, void *data) { int keynum = P_INT (pr, 0); @@ -159,7 +159,7 @@ bi_Key_KeynumToString (progs_t *pr) } static void -bi_Key_StringToKeynum (progs_t *pr) +bi_Key_StringToKeynum (progs_t *pr, void *data) { const char *keyname = P_GSTRING (pr, 0); R_INT (pr) = Key_StringToKeynum (keyname); @@ -179,7 +179,7 @@ static builtin_t builtins[] = { }; void -RUA_Key_Init (progs_t *pr) +RUA_Key_Init (progs_t *pr, void *data) { PR_RegisterBuiltins (pr, builtins, 0); } diff --git a/libs/ruamoko/rua_math.c b/libs/ruamoko/rua_math.c index 2d7e09398..cf00b84a3 100644 --- a/libs/ruamoko/rua_math.c +++ b/libs/ruamoko/rua_math.c @@ -42,61 +42,61 @@ #include "rua_internal.h" static void -bi_sinf (progs_t *pr) +bi_sinf (progs_t *pr, void *data) { R_FLOAT (pr) = sinf (P_FLOAT (pr, 0)); } static void -bi_cosf (progs_t *pr) +bi_cosf (progs_t *pr, void *data) { R_FLOAT (pr) = cosf (P_FLOAT (pr, 0)); } static void -bi_tanf (progs_t *pr) +bi_tanf (progs_t *pr, void *data) { R_FLOAT (pr) = tanf (P_FLOAT (pr, 0)); } static void -bi_asinf (progs_t *pr) +bi_asinf (progs_t *pr, void *data) { R_FLOAT (pr) = asinf (P_FLOAT (pr, 0)); } static void -bi_acosf (progs_t *pr) +bi_acosf (progs_t *pr, void *data) { R_FLOAT (pr) = acosf (P_FLOAT (pr, 0)); } static void -bi_atanf (progs_t *pr) +bi_atanf (progs_t *pr, void *data) { R_FLOAT (pr) = atanf (P_FLOAT (pr, 0)); } static void -bi_atan2f (progs_t *pr) +bi_atan2f (progs_t *pr, void *data) { R_FLOAT (pr) = atan2f (P_FLOAT (pr, 0), P_FLOAT (pr, 1)); } static void -bi_expf (progs_t *pr) +bi_expf (progs_t *pr, void *data) { R_FLOAT (pr) = expf (P_FLOAT (pr, 0)); } static void -bi_logf (progs_t *pr) +bi_logf (progs_t *pr, void *data) { R_FLOAT (pr) = logf (P_FLOAT (pr, 0)); } static void -bi_log2f (progs_t *pr) +bi_log2f (progs_t *pr, void *data) { #ifdef HAVE_LOG2F R_FLOAT (pr) = log2f (P_FLOAT (pr, 0)); @@ -106,216 +106,216 @@ bi_log2f (progs_t *pr) } static void -bi_log10f (progs_t *pr) +bi_log10f (progs_t *pr, void *data) { R_FLOAT (pr) = log10f (P_FLOAT (pr, 0)); } static void -bi_powf (progs_t *pr) +bi_powf (progs_t *pr, void *data) { R_FLOAT (pr) = powf (P_FLOAT (pr, 0), P_FLOAT (pr, 1)); } static void -bi_sqrtf (progs_t *pr) +bi_sqrtf (progs_t *pr, void *data) { R_FLOAT (pr) = sqrtf (P_FLOAT (pr, 0)); } static void -bi_cbrtf (progs_t *pr) +bi_cbrtf (progs_t *pr, void *data) { R_FLOAT (pr) = cbrtf (P_FLOAT (pr, 0)); } static void -bi_hypotf (progs_t *pr) +bi_hypotf (progs_t *pr, void *data) { R_FLOAT (pr) = hypotf (P_FLOAT (pr, 0), P_FLOAT (pr, 1)); } static void -bi_sinhf (progs_t *pr) +bi_sinhf (progs_t *pr, void *data) { R_FLOAT (pr) = sinhf (P_FLOAT (pr, 0)); } static void -bi_coshf (progs_t *pr) +bi_coshf (progs_t *pr, void *data) { R_FLOAT (pr) = coshf (P_FLOAT (pr, 0)); } static void -bi_tanhf (progs_t *pr) +bi_tanhf (progs_t *pr, void *data) { R_FLOAT (pr) = tanhf (P_FLOAT (pr, 0)); } static void -bi_asinhf (progs_t *pr) +bi_asinhf (progs_t *pr, void *data) { double y = P_FLOAT (pr, 0); R_FLOAT (pr) = logf (y + sqrtf (y * y + 1)); } static void -bi_acoshf (progs_t *pr) +bi_acoshf (progs_t *pr, void *data) { double y = P_FLOAT (pr, 0); R_FLOAT (pr) = logf (y + sqrtf (y * y - 1)); } static void -bi_atanhf (progs_t *pr) +bi_atanhf (progs_t *pr, void *data) { double y = P_FLOAT (pr, 0); R_FLOAT (pr) = logf ((1 + y) / (1 - y)) / 2; } static void -bi_floor (progs_t *pr) +bi_floor (progs_t *pr, void *data) { R_DOUBLE (pr) = floor (P_DOUBLE (pr, 0)); } static void -bi_ceil (progs_t *pr) +bi_ceil (progs_t *pr, void *data) { R_DOUBLE (pr) = ceil (P_DOUBLE (pr, 0)); } static void -bi_fabs (progs_t *pr) +bi_fabs (progs_t *pr, void *data) { R_DOUBLE (pr) = fabs (P_DOUBLE (pr, 0)); } static void -bi_sin (progs_t *pr) +bi_sin (progs_t *pr, void *data) { R_DOUBLE (pr) = sin (P_DOUBLE (pr, 0)); } static void -bi_cos (progs_t *pr) +bi_cos (progs_t *pr, void *data) { R_DOUBLE (pr) = cos (P_DOUBLE (pr, 0)); } static void -bi_tan (progs_t *pr) +bi_tan (progs_t *pr, void *data) { R_DOUBLE (pr) = tan (P_DOUBLE (pr, 0)); } static void -bi_asin (progs_t *pr) +bi_asin (progs_t *pr, void *data) { R_DOUBLE (pr) = asin (P_DOUBLE (pr, 0)); } static void -bi_acos (progs_t *pr) +bi_acos (progs_t *pr, void *data) { R_DOUBLE (pr) = acos (P_DOUBLE (pr, 0)); } static void -bi_atan (progs_t *pr) +bi_atan (progs_t *pr, void *data) { R_DOUBLE (pr) = atan (P_DOUBLE (pr, 0)); } static void -bi_atan2 (progs_t *pr) +bi_atan2 (progs_t *pr, void *data) { R_DOUBLE (pr) = atan2 (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1)); } static void -bi_exp (progs_t *pr) +bi_exp (progs_t *pr, void *data) { R_DOUBLE (pr) = exp (P_DOUBLE (pr, 0)); } static void -bi_log (progs_t *pr) +bi_log (progs_t *pr, void *data) { R_DOUBLE (pr) = log (P_DOUBLE (pr, 0)); } static void -bi_log2 (progs_t *pr) +bi_log2 (progs_t *pr, void *data) { R_DOUBLE (pr) = log (P_DOUBLE (pr, 0)) / M_LOG2E; } static void -bi_log10 (progs_t *pr) +bi_log10 (progs_t *pr, void *data) { R_DOUBLE (pr) = log10 (P_DOUBLE (pr, 0)); } static void -bi_pow (progs_t *pr) +bi_pow (progs_t *pr, void *data) { R_DOUBLE (pr) = pow (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1)); } static void -bi_sqrt (progs_t *pr) +bi_sqrt (progs_t *pr, void *data) { R_DOUBLE (pr) = sqrt (P_DOUBLE (pr, 0)); } static void -bi_cbrt (progs_t *pr) +bi_cbrt (progs_t *pr, void *data) { R_DOUBLE (pr) = cbrt (P_DOUBLE (pr, 0)); } static void -bi_hypot (progs_t *pr) +bi_hypot (progs_t *pr, void *data) { R_DOUBLE (pr) = hypot (P_DOUBLE (pr, 0), P_DOUBLE (pr, 1)); } static void -bi_sinh (progs_t *pr) +bi_sinh (progs_t *pr, void *data) { R_DOUBLE (pr) = sinh (P_DOUBLE (pr, 0)); } static void -bi_cosh (progs_t *pr) +bi_cosh (progs_t *pr, void *data) { R_DOUBLE (pr) = cosh (P_DOUBLE (pr, 0)); } static void -bi_tanh (progs_t *pr) +bi_tanh (progs_t *pr, void *data) { R_DOUBLE (pr) = tanh (P_DOUBLE (pr, 0)); } static void -bi_asinh (progs_t *pr) +bi_asinh (progs_t *pr, void *data) { double y = P_DOUBLE (pr, 0); R_DOUBLE (pr) = log (y + sqrt (y * y + 1)); } static void -bi_acosh (progs_t *pr) +bi_acosh (progs_t *pr, void *data) { double y = P_DOUBLE (pr, 0); R_DOUBLE (pr) = log (y + sqrt (y * y - 1)); } static void -bi_atanh (progs_t *pr) +bi_atanh (progs_t *pr, void *data) { double y = P_DOUBLE (pr, 0); R_DOUBLE (pr) = log ((1 + y) / (1 - y)) / 2; diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c index c55c495c1..8cb854dc3 100644 --- a/libs/ruamoko/rua_mersenne.c +++ b/libs/ruamoko/rua_mersenne.c @@ -81,19 +81,17 @@ state_index (mtwist_resources_t *res, mtstate_t *state) } static void -bi_mtwist_new (progs_t *pr) +bi_mtwist_new (progs_t *pr, void *_res) { - mtwist_resources_t *res = PR_Resources_Find (pr, "Mersenne Twister"); - + mtwist_resources_t *res = (mtwist_resources_t *) _res; mtstate_t *mt = state_new (res); mtwist_seed (mt, P_INT (pr, 0)); R_INT (pr) = state_index (res, mt); } static mtstate_t * -get_state (progs_t *pr, const char *name, int index) +get_state (progs_t *pr, mtwist_resources_t *res, const char *name, int index) { - mtwist_resources_t *res = PR_Resources_Find (pr, "Mersenne Twister"); mtstate_t *mt = state_get (res, index); if (!mt) @@ -103,45 +101,49 @@ get_state (progs_t *pr, const char *name, int index) } static void -bi_mtwist_delete (progs_t *pr) +bi_mtwist_delete (progs_t *pr, void *_res) { - mtwist_resources_t *res = PR_Resources_Find (pr, "Mersenne Twister"); - mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + mtwist_resources_t *res = _res; + mtstate_t *mt = get_state (pr, res, __FUNCTION__, P_INT (pr, 0)); state_free (res, mt); } static void -bi_mtwist_seed (progs_t *pr) +bi_mtwist_seed (progs_t *pr, void *_res) { - mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + mtwist_resources_t *res = _res; + mtstate_t *mt = get_state (pr, res, __FUNCTION__, P_INT (pr, 0)); mtwist_seed (mt, P_INT (pr, 1)); } static void -bi_mtwist_rand (progs_t *pr) +bi_mtwist_rand (progs_t *pr, void *_res) { - mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + mtwist_resources_t *res = _res; + mtstate_t *mt = get_state (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = mtwist_rand (mt); } static void -bi_mtwist_rand_0_1 (progs_t *pr) +bi_mtwist_rand_0_1 (progs_t *pr, void *_res) { - mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + mtwist_resources_t *res = _res; + mtstate_t *mt = get_state (pr, res, __FUNCTION__, P_INT (pr, 0)); R_FLOAT (pr) = mtwist_rand_0_1 (mt); } static void -bi_mtwist_rand_m1_1 (progs_t *pr) +bi_mtwist_rand_m1_1 (progs_t *pr, void *_res) { - mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + mtwist_resources_t *res = _res; + mtstate_t *mt = get_state (pr, res, __FUNCTION__, P_INT (pr, 0)); R_FLOAT (pr) = mtwist_rand_m1_1 (mt); } static void -bi_mtwist_clear (progs_t *pr, void *data) +bi_mtwist_clear (progs_t *pr, void *_res) { - mtwist_resources_t *res = (mtwist_resources_t *) data; + mtwist_resources_t *res = (mtwist_resources_t *) _res; state_reset (res); } diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index c2420ed99..23959a2cf 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -111,9 +111,8 @@ alloc_msgbuf (msgbuf_resources_t *res, byte *buf, int size) } static msgbuf_t * -get_msgbuf (progs_t *pr, const char *name, int msgbuf) +get_msgbuf (progs_t *pr, msgbuf_resources_t *res, const char *name, int msgbuf) { - msgbuf_resources_t *res = PR_Resources_Find (pr, "MsgBuf"); msgbuf_t *mb = msgbuf_get (res, msgbuf); if (!mb) @@ -122,7 +121,7 @@ get_msgbuf (progs_t *pr, const char *name, int msgbuf) } static void -bi_MsgBuf_New (progs_t *pr) +bi_MsgBuf_New (progs_t *pr, void *_res) { msgbuf_resources_t *res = PR_Resources_Find (pr, "MsgBuf"); int size = P_INT (pr, 0); @@ -133,17 +132,18 @@ bi_MsgBuf_New (progs_t *pr) } static void -bi_MsgBuf_Delete (progs_t *pr) +bi_MsgBuf_Delete (progs_t *pr, void *_res) { msgbuf_resources_t *res = PR_Resources_Find (pr, "MsgBuf"); - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); msgbuf_free (pr, res, mb); } static void -bi_MsgBuf_FromFile (progs_t *pr) +bi_MsgBuf_FromFile (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); QFile *file = QFile_GetFile (pr, P_INT (pr, 1)); int bytes; @@ -154,179 +154,204 @@ bi_MsgBuf_FromFile (progs_t *pr) } static void -bi_MsgBuf_MaxSize (progs_t *pr) +bi_MsgBuf_MaxSize (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = mb->sizebuf.maxsize; } static void -bi_MsgBuf_CurSize (progs_t *pr) +bi_MsgBuf_CurSize (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = mb->sizebuf.cursize; } static void -bi_MsgBuf_ReadCount (progs_t *pr) +bi_MsgBuf_ReadCount (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = mb->msg.readcount; } static void -bi_MsgBuf_DataPtr (progs_t *pr) +bi_MsgBuf_DataPtr (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); byte *ptr = mb->sizebuf.data + mb->msg.readcount; R_INT (pr) = ptr - (byte *) pr->pr_strings; } static void -bi_MsgBuf_Clear (progs_t *pr) +bi_MsgBuf_Clear (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); SZ_Clear (&mb->sizebuf); } static void -bi_MsgBuf_WriteByte (progs_t *pr) +bi_MsgBuf_WriteByte (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteByte (&mb->sizebuf, P_INT (pr, 1)); } static void -bi_MsgBuf_WriteShort (progs_t *pr) +bi_MsgBuf_WriteShort (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteShort (&mb->sizebuf, P_INT (pr, 1)); } static void -bi_MsgBuf_WriteLong (progs_t *pr) +bi_MsgBuf_WriteLong (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteLong (&mb->sizebuf, P_INT (pr, 1)); } static void -bi_MsgBuf_WriteFloat (progs_t *pr) +bi_MsgBuf_WriteFloat (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteFloat (&mb->sizebuf, P_FLOAT (pr, 1)); } static void -bi_MsgBuf_WriteString (progs_t *pr) +bi_MsgBuf_WriteString (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteString (&mb->sizebuf, P_GSTRING (pr, 1)); } #if 0 static void -bi_MsgBuf_WriteBytes (progs_t *pr) +bi_MsgBuf_WriteBytes (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteBytes (&mb->sizebuf, P_INT (pr, 1)); } #endif static void -bi_MsgBuf_WriteCoord (progs_t *pr) +bi_MsgBuf_WriteCoord (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteCoord (&mb->sizebuf, P_FLOAT (pr, 1)); } static void -bi_MsgBuf_WriteCoordV (progs_t *pr) +bi_MsgBuf_WriteCoordV (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteCoordV (&mb->sizebuf, P_VECTOR (pr, 1)); } static void -bi_MsgBuf_WriteCoordAngleV (progs_t *pr) +bi_MsgBuf_WriteCoordAngleV (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteCoordAngleV (&mb->sizebuf, P_VECTOR (pr, 1), P_VECTOR (pr, 2)); } static void -bi_MsgBuf_WriteAngle (progs_t *pr) +bi_MsgBuf_WriteAngle (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteAngle (&mb->sizebuf, P_FLOAT (pr, 1)); } static void -bi_MsgBuf_WriteAngleV (progs_t *pr) +bi_MsgBuf_WriteAngleV (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteAngleV (&mb->sizebuf, P_VECTOR (pr, 1)); } static void -bi_MsgBuf_WriteAngle16 (progs_t *pr) +bi_MsgBuf_WriteAngle16 (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteAngle16 (&mb->sizebuf, P_FLOAT (pr, 1)); } static void -bi_MsgBuf_WriteAngle16V (progs_t *pr) +bi_MsgBuf_WriteAngle16V (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteAngle16V (&mb->sizebuf, P_VECTOR (pr, 1)); } static void -bi_MsgBuf_WriteUTF8 (progs_t *pr) +bi_MsgBuf_WriteUTF8 (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_WriteUTF8 (&mb->sizebuf, P_INT (pr, 1)); } static void -bi_MsgBuf_BeginReading (progs_t *pr) +bi_MsgBuf_BeginReading (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_BeginReading (&mb->msg); } static void -bi_MsgBuf_ReadByte (progs_t *pr) +bi_MsgBuf_ReadByte (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = MSG_ReadByte (&mb->msg); } static void -bi_MsgBuf_ReadShort (progs_t *pr) +bi_MsgBuf_ReadShort (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = MSG_ReadShort (&mb->msg); } static void -bi_MsgBuf_ReadLong (progs_t *pr) +bi_MsgBuf_ReadLong (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = MSG_ReadLong (&mb->msg); } static void -bi_MsgBuf_ReadFloat (progs_t *pr) +bi_MsgBuf_ReadFloat (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_FLOAT (pr) = MSG_ReadFloat (&mb->msg); } static void -bi_MsgBuf_ReadString (progs_t *pr) +bi_MsgBuf_ReadString (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); const char *str; str = MSG_ReadString (&mb->msg); @@ -334,65 +359,74 @@ bi_MsgBuf_ReadString (progs_t *pr) } #if 0 static void -bi_MsgBuf_ReadBytes (progs_t *pr) +bi_MsgBuf_ReadBytes (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_ReadBytes (&mb->msg); } #endif static void -bi_MsgBuf_ReadCoord (progs_t *pr) +bi_MsgBuf_ReadCoord (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_FLOAT (pr) = MSG_ReadCoord (&mb->msg); } static void -bi_MsgBuf_ReadCoordV (progs_t *pr) +bi_MsgBuf_ReadCoordV (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_ReadCoordV (&mb->msg, R_VECTOR (pr)); } static void -bi_MsgBuf_ReadCoordAngleV (progs_t *pr) +bi_MsgBuf_ReadCoordAngleV (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_ReadCoordAngleV (&mb->msg, P_VECTOR (pr, 1), P_VECTOR (pr, 2)); } static void -bi_MsgBuf_ReadAngle (progs_t *pr) +bi_MsgBuf_ReadAngle (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_FLOAT (pr) = MSG_ReadAngle (&mb->msg); } static void -bi_MsgBuf_ReadAngleV (progs_t *pr) +bi_MsgBuf_ReadAngleV (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_ReadAngleV (&mb->msg, R_VECTOR (pr)); } static void -bi_MsgBuf_ReadAngle16 (progs_t *pr) +bi_MsgBuf_ReadAngle16 (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_FLOAT (pr) = MSG_ReadAngle16 (&mb->msg); } static void -bi_MsgBuf_ReadAngle16V (progs_t *pr) +bi_MsgBuf_ReadAngle16V (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); MSG_ReadAngle16V (&mb->msg, R_VECTOR (pr)); } static void -bi_MsgBuf_ReadUTF8 (progs_t *pr) +bi_MsgBuf_ReadUTF8 (progs_t *pr, void *_res) { - msgbuf_t *mb = get_msgbuf (pr, __FUNCTION__, P_INT (pr, 0)); + msgbuf_resources_t *res = _res; + msgbuf_t *mb = get_msgbuf (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = MSG_ReadUTF8 (&mb->msg); } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 992d659a5..65df011d6 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1160,7 +1160,7 @@ obj_init_statics (probj_t *probj) } static void -rua___obj_exec_class (progs_t *pr) +rua___obj_exec_class (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_module_t *module = &P_STRUCT (pr, pr_module_t, 0); @@ -1308,7 +1308,7 @@ rua___obj_exec_class (progs_t *pr) } static void -rua___obj_forward (progs_t *pr) +rua___obj_forward (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_id_t *obj = &P_STRUCT (pr, pr_id_t, 0); @@ -1396,7 +1396,7 @@ rua___obj_forward (progs_t *pr) } static void -rua___obj_responds_to (progs_t *pr) +rua___obj_responds_to (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_id_t *obj = &P_STRUCT (pr, pr_id_t, 0); @@ -1406,7 +1406,7 @@ rua___obj_responds_to (progs_t *pr) } static void -rua_obj_error (progs_t *pr) +rua_obj_error (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); @@ -1419,7 +1419,7 @@ rua_obj_error (progs_t *pr) } static void -rua_obj_verror (progs_t *pr) +rua_obj_verror (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); @@ -1436,7 +1436,7 @@ rua_obj_verror (progs_t *pr) } static void -rua_obj_set_error_handler (progs_t *pr) +rua_obj_set_error_handler (progs_t *pr, void *data) { //probj_t *probj = pr->pr_objective_resources; //pr_func_t func = P_INT (pr, 0); @@ -1446,7 +1446,7 @@ rua_obj_set_error_handler (progs_t *pr) } static void -rua_obj_msg_lookup (progs_t *pr) +rua_obj_msg_lookup (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_id_t *receiver = &P_STRUCT (pr, pr_id_t, 0); @@ -1456,7 +1456,7 @@ rua_obj_msg_lookup (progs_t *pr) } static void -rua_obj_msg_lookup_super (progs_t *pr) +rua_obj_msg_lookup_super (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_super_t *super = &P_STRUCT (pr, pr_super_t, 0); @@ -1466,7 +1466,7 @@ rua_obj_msg_lookup_super (progs_t *pr) } static void -rua_obj_msg_sendv (progs_t *pr) +rua_obj_msg_sendv (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_ptr_t obj = P_POINTER (pr, 0); @@ -1508,28 +1508,28 @@ rua_obj_msg_sendv (progs_t *pr) } static void -rua_obj_increment_retaincount (progs_t *pr) +rua_obj_increment_retaincount (progs_t *pr, void *data) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); R_INT (pr) = ++(*--obj).int_var; } static void -rua_obj_decrement_retaincount (progs_t *pr) +rua_obj_decrement_retaincount (progs_t *pr, void *data) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); R_INT (pr) = --(*--obj).int_var; } static void -rua_obj_get_retaincount (progs_t *pr) +rua_obj_get_retaincount (progs_t *pr, void *data) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); R_INT (pr) = (*--obj).int_var; } static void -rua_obj_malloc (progs_t *pr) +rua_obj_malloc (progs_t *pr, void *data) { int size = P_INT (pr, 0) * sizeof (pr_type_t); void *mem = PR_Zone_Malloc (pr, size); @@ -1538,7 +1538,7 @@ rua_obj_malloc (progs_t *pr) } static void -rua_obj_atomic_malloc (progs_t *pr) +rua_obj_atomic_malloc (progs_t *pr, void *data) { int size = P_INT (pr, 0) * sizeof (pr_type_t); void *mem = PR_Zone_Malloc (pr, size); @@ -1547,7 +1547,7 @@ rua_obj_atomic_malloc (progs_t *pr) } static void -rua_obj_valloc (progs_t *pr) +rua_obj_valloc (progs_t *pr, void *data) { int size = P_INT (pr, 0) * sizeof (pr_type_t); void *mem = PR_Zone_Malloc (pr, size); @@ -1556,7 +1556,7 @@ rua_obj_valloc (progs_t *pr) } static void -rua_obj_realloc (progs_t *pr) +rua_obj_realloc (progs_t *pr, void *data) { void *mem = (void*)P_GPOINTER (pr, 0); int size = P_INT (pr, 1) * sizeof (pr_type_t); @@ -1566,7 +1566,7 @@ rua_obj_realloc (progs_t *pr) } static void -rua_obj_calloc (progs_t *pr) +rua_obj_calloc (progs_t *pr, void *data) { int size = P_INT (pr, 0) * P_INT (pr, 1) * sizeof (pr_type_t); void *mem = PR_Zone_Malloc (pr, size); @@ -1576,7 +1576,7 @@ rua_obj_calloc (progs_t *pr) } static void -rua_obj_free (progs_t *pr) +rua_obj_free (progs_t *pr, void *data) { void *mem = (void*)P_GPOINTER (pr, 0); @@ -1584,7 +1584,7 @@ rua_obj_free (progs_t *pr) } static void -rua_obj_get_uninstalled_dtable (progs_t *pr) +rua_obj_get_uninstalled_dtable (progs_t *pr, void *data) { //probj_t *probj = pr->pr_objective_resources; //XXX @@ -1592,7 +1592,7 @@ rua_obj_get_uninstalled_dtable (progs_t *pr) } static void -rua_obj_msgSend (progs_t *pr) +rua_obj_msgSend (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &P_STRUCT (pr, pr_id_t, 0); @@ -1618,7 +1618,7 @@ rua_obj_msgSend (progs_t *pr) } static void -rua_obj_msgSend_super (progs_t *pr) +rua_obj_msgSend_super (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_super_t *super = &P_STRUCT (pr, pr_super_t, 0); @@ -1640,7 +1640,7 @@ rua_obj_msgSend_super (progs_t *pr) } static void -rua_obj_get_class (progs_t *pr) +rua_obj_get_class (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; const char *name = P_GSTRING (pr, 0); @@ -1653,7 +1653,7 @@ rua_obj_get_class (progs_t *pr) } static void -rua_obj_lookup_class (progs_t *pr) +rua_obj_lookup_class (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; const char *name = P_GSTRING (pr, 0); @@ -1664,7 +1664,7 @@ rua_obj_lookup_class (progs_t *pr) } static void -rua_obj_next_class (progs_t *pr) +rua_obj_next_class (progs_t *pr, void *data) { //probj_t *probj = pr->pr_objective_resources; //XXX @@ -1674,7 +1674,7 @@ rua_obj_next_class (progs_t *pr) //==================================================================== static void -rua_sel_get_name (progs_t *pr) +rua_sel_get_name (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 0); @@ -1686,7 +1686,7 @@ rua_sel_get_name (progs_t *pr) } static void -rua_sel_get_type (progs_t *pr) +rua_sel_get_type (progs_t *pr, void *data) { pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 0); @@ -1694,7 +1694,7 @@ rua_sel_get_type (progs_t *pr) } static void -rua_sel_get_uid (progs_t *pr) +rua_sel_get_uid (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; const char *name = P_GSTRING (pr, 0); @@ -1703,7 +1703,7 @@ rua_sel_get_uid (progs_t *pr) } static void -rua_sel_register_name (progs_t *pr) +rua_sel_register_name (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; const char *name = P_GSTRING (pr, 0); @@ -1712,7 +1712,7 @@ rua_sel_register_name (progs_t *pr) } static void -rua_sel_is_mapped (progs_t *pr) +rua_sel_is_mapped (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; // FIXME might correspond to a string @@ -1723,7 +1723,7 @@ rua_sel_is_mapped (progs_t *pr) //==================================================================== static void -rua_class_get_class_method (progs_t *pr) +rua_class_get_class_method (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); @@ -1735,7 +1735,7 @@ rua_class_get_class_method (progs_t *pr) } static void -rua_class_get_instance_method (progs_t *pr) +rua_class_get_instance_method (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); @@ -1747,7 +1747,7 @@ rua_class_get_instance_method (progs_t *pr) #define CLASSOF(x) (&G_STRUCT (pr, pr_class_t, (x)->class_pointer)) static void -rua_class_pose_as (progs_t *pr) +rua_class_pose_as (progs_t *pr, void *data) { pr_class_t *impostor = &P_STRUCT (pr, pr_class_t, 0); pr_class_t *superclass = &P_STRUCT (pr, pr_class_t, 1); @@ -1796,7 +1796,7 @@ class_create_instance (progs_t *pr, pr_class_t *class) } static void -rua_class_create_instance (progs_t *pr) +rua_class_create_instance (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); pr_id_t *id = class_create_instance (pr, class); @@ -1805,7 +1805,7 @@ rua_class_create_instance (progs_t *pr) } static void -rua_class_get_class_name (progs_t *pr) +rua_class_get_class_name (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); R_INT (pr) = PR_CLS_ISCLASS (class) ? class->name @@ -1813,49 +1813,49 @@ rua_class_get_class_name (progs_t *pr) } static void -rua_class_get_instance_size (progs_t *pr) +rua_class_get_instance_size (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); R_INT (pr) = PR_CLS_ISCLASS (class) ? class->instance_size : 0; } static void -rua_class_get_meta_class (progs_t *pr) +rua_class_get_meta_class (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); R_INT (pr) = PR_CLS_ISCLASS (class) ? class->class_pointer : 0; } static void -rua_class_get_super_class (progs_t *pr) +rua_class_get_super_class (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); R_INT (pr) = PR_CLS_ISCLASS (class) ? class->super_class : 0; } static void -rua_class_get_version (progs_t *pr) +rua_class_get_version (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); R_INT (pr) = PR_CLS_ISCLASS (class) ? class->version : -1; } static void -rua_class_is_class (progs_t *pr) +rua_class_is_class (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); R_INT (pr) = PR_CLS_ISCLASS (class); } static void -rua_class_is_meta_class (progs_t *pr) +rua_class_is_meta_class (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); R_INT (pr) = PR_CLS_ISMETA (class); } static void -rua_class_set_version (progs_t *pr) +rua_class_set_version (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); if (PR_CLS_ISCLASS (class)) @@ -1863,14 +1863,14 @@ rua_class_set_version (progs_t *pr) } static void -rua_class_get_gc_object_type (progs_t *pr) +rua_class_get_gc_object_type (progs_t *pr, void *data) { pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); R_INT (pr) = PR_CLS_ISCLASS (class) ? class->gc_object_type : 0; } static void -rua_class_ivar_set_gcinvisible (progs_t *pr) +rua_class_ivar_set_gcinvisible (progs_t *pr, void *data) { //probj_t *probj = pr->pr_objective_resources; //pr_class_t *impostor = &P_STRUCT (pr, pr_class_t, 0); @@ -1883,7 +1883,7 @@ rua_class_ivar_set_gcinvisible (progs_t *pr) //==================================================================== static void -rua_method_get_imp (progs_t *pr) +rua_method_get_imp (progs_t *pr, void *data) { pr_method_t *method = &P_STRUCT (pr, pr_method_t, 0); @@ -1891,7 +1891,7 @@ rua_method_get_imp (progs_t *pr) } static void -rua_get_imp (progs_t *pr) +rua_get_imp (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_class_t *class = &P_STRUCT (pr, pr_class_t, 0); @@ -1903,7 +1903,7 @@ rua_get_imp (progs_t *pr) //==================================================================== static void -rua_object_dispose (progs_t *pr) +rua_object_dispose (progs_t *pr, void *data) { pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); pr_type_t *mem = (pr_type_t *) object; @@ -1911,7 +1911,7 @@ rua_object_dispose (progs_t *pr) } static void -rua_object_copy (progs_t *pr) +rua_object_copy (progs_t *pr, void *data) { pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); pr_class_t *class = &G_STRUCT (pr, pr_class_t, object->class_pointer); @@ -1927,7 +1927,7 @@ rua_object_copy (progs_t *pr) } static void -rua_object_get_class (progs_t *pr) +rua_object_get_class (progs_t *pr, void *data) { pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); pr_class_t *class; @@ -1947,7 +1947,7 @@ rua_object_get_class (progs_t *pr) } static void -rua_object_get_super_class (progs_t *pr) +rua_object_get_super_class (progs_t *pr, void *data) { pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); pr_class_t *class; @@ -1967,7 +1967,7 @@ rua_object_get_super_class (progs_t *pr) } static void -rua_object_get_meta_class (progs_t *pr) +rua_object_get_meta_class (progs_t *pr, void *data) { pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); pr_class_t *class; @@ -1987,7 +1987,7 @@ rua_object_get_meta_class (progs_t *pr) } static void -rua_object_get_class_name (progs_t *pr) +rua_object_get_class_name (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); @@ -1996,7 +1996,7 @@ rua_object_get_class_name (progs_t *pr) } static void -rua_object_is_class (progs_t *pr) +rua_object_is_class (progs_t *pr, void *data) { pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); @@ -2008,7 +2008,7 @@ rua_object_is_class (progs_t *pr) } static void -rua_object_is_instance (progs_t *pr) +rua_object_is_instance (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); @@ -2017,7 +2017,7 @@ rua_object_is_instance (progs_t *pr) } static void -rua_object_is_meta_class (progs_t *pr) +rua_object_is_meta_class (progs_t *pr, void *data) { pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); @@ -2031,13 +2031,13 @@ rua_object_is_meta_class (progs_t *pr) //==================================================================== static void -rua__i_Object__hash (progs_t *pr) +rua__i_Object__hash (progs_t *pr, void *data) { R_INT (pr) = P_INT (pr, 0); } static void -rua__i_Object_error_error_ (progs_t *pr) +rua__i_Object_error_error_ (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &P_STRUCT (pr, pr_id_t, 0); @@ -2090,7 +2090,7 @@ obj_protocol_conformsToProtocol (probj_t *probj, pr_protocol_t *proto, } static void -rua__c_Object__conformsToProtocol_ (progs_t *pr) +rua__c_Object__conformsToProtocol_ (progs_t *pr, void *data) { probj_t *probj = pr->pr_objective_resources; // class points to _OBJ_CLASS_foo, and class->class_pointer points to @@ -2137,7 +2137,7 @@ conforms: } static void -rua_PR_FindGlobal (progs_t *pr) +rua_PR_FindGlobal (progs_t *pr, void *data) { const char *name = P_GSTRING (pr, 0); pr_def_t *def; @@ -2346,15 +2346,15 @@ RUA_Obj_msg_lookup (progs_t *pr, pr_ptr_t _self, pr_ptr_t __cmd) } int -RUA_obj_increment_retaincount (progs_t *pr) +RUA_obj_increment_retaincount (progs_t *pr, void *data) { - rua_obj_increment_retaincount (pr); + rua_obj_increment_retaincount (pr, data); return R_INT (pr); } int -RUA_obj_decrement_retaincount (progs_t *pr) +RUA_obj_decrement_retaincount (progs_t *pr, void *data) { - rua_obj_decrement_retaincount (pr); + rua_obj_decrement_retaincount (pr, data); return R_INT (pr); } diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 4aae2db06..b07e365a6 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -91,9 +91,9 @@ plist_index (plist_resources_t *res, bi_plist_t *plist) } static void -bi_plist_clear (progs_t *pr, void *data) +bi_plist_clear (progs_t *pr, void *_res) { - plist_resources_t *res = (plist_resources_t *) data; + plist_resources_t *res = (plist_resources_t *) _res; bi_plist_t *plist; for (plist = res->plists; plist; plist = plist->next) { @@ -143,9 +143,8 @@ plist_free_handle (plist_resources_t *res, bi_plist_t *plist) } static always_inline bi_plist_t * -get_plist (progs_t *pr, const char *name, int handle) +get_plist (progs_t *pr, plist_resources_t *res, const char *name, int handle) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); bi_plist_t *plist = plist_get (res, handle); // plist->prev will be null if the handle is unallocated @@ -178,9 +177,9 @@ plist_retain (plist_resources_t *res, plitem_t *plitem) } static void -bi_PL_GetFromFile (progs_t *pr) +bi_PL_GetFromFile (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; QFile *file = QFile_GetFile (pr, P_INT (pr, 0)); plitem_t *plitem; long offset; @@ -201,9 +200,9 @@ bi_PL_GetFromFile (progs_t *pr) } static void -bi_PL_GetPropertyList (progs_t *pr) +bi_PL_GetPropertyList (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; plitem_t *plitem = PL_GetPropertyList (P_GSTRING (pr, 0), pr->hashlink_freelist); @@ -211,10 +210,11 @@ bi_PL_GetPropertyList (progs_t *pr) } static void -bi_PL_WritePropertyList (progs_t *pr) +bi_PL_WritePropertyList (progs_t *pr, void *_res) { + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); char *pl = PL_WritePropertyList (plist->plitem); R_STRING (pr) = PR_SetDynamicString (pr, pl); @@ -222,39 +222,42 @@ bi_PL_WritePropertyList (progs_t *pr) } static void -bi_PL_Type (progs_t *pr) +bi_PL_Type (progs_t *pr, void *_res) { + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); R_INT (pr) = PL_Type (plist->plitem); } static void -bi_PL_Line (progs_t *pr) +bi_PL_Line (progs_t *pr, void *_res) { + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); R_INT (pr) = PL_Line (plist->plitem); } static void -bi_PL_String (progs_t *pr) +bi_PL_String (progs_t *pr, void *_res) { + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); const char *str = PL_String (plist->plitem); RETURN_STRING (pr, str); } static void -bi_PL_ObjectForKey (progs_t *pr) +bi_PL_ObjectForKey (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); const char *key = P_GSTRING (pr, 1); plitem_t *plitem = PL_ObjectForKey (plist->plitem, key); @@ -265,11 +268,11 @@ bi_PL_ObjectForKey (progs_t *pr) } static void -bi_PL_RemoveObjectForKey (progs_t *pr) +bi_PL_RemoveObjectForKey (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); const char *key = P_GSTRING (pr, 1); plitem_t *plitem = PL_RemoveObjectForKey (plist->plitem, key); @@ -277,11 +280,11 @@ bi_PL_RemoveObjectForKey (progs_t *pr) } static void -bi_PL_ObjectAtIndex (progs_t *pr) +bi_PL_ObjectAtIndex (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); int ind = P_INT (pr, 1); plitem_t *plitem = PL_ObjectAtIndex (plist->plitem, ind); @@ -292,66 +295,71 @@ bi_PL_ObjectAtIndex (progs_t *pr) } static void -bi_PL_D_AllKeys (progs_t *pr) +bi_PL_D_AllKeys (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); plitem_t *plitem = PL_D_AllKeys (plist->plitem); R_INT (pr) = plist_retain (res, plitem); } static void -bi_PL_D_NumKeys (progs_t *pr) +bi_PL_D_NumKeys (progs_t *pr, void *_res) { + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); R_INT (pr) = PL_D_NumKeys (plist->plitem); } static void -bi_PL_D_AddObject (progs_t *pr) +bi_PL_D_AddObject (progs_t *pr, void *_res) { + plist_resources_t *res = _res; int dict_handle = P_INT (pr, 0); int obj_handle = P_INT (pr, 2); - bi_plist_t *dict = get_plist (pr, __FUNCTION__, dict_handle); + bi_plist_t *dict = get_plist (pr, res, __FUNCTION__, dict_handle); const char *key = P_GSTRING (pr, 1); - bi_plist_t *obj = get_plist (pr, __FUNCTION__, obj_handle); + bi_plist_t *obj = get_plist (pr, res, __FUNCTION__, obj_handle); obj->own = 0; R_INT (pr) = PL_D_AddObject (dict->plitem, key, obj->plitem); } static void -bi_PL_A_AddObject (progs_t *pr) +bi_PL_A_AddObject (progs_t *pr, void *_res) { + plist_resources_t *res = _res; int arr_handle = P_INT (pr, 0); int obj_handle = P_INT (pr, 1); - bi_plist_t *arr = get_plist (pr, __FUNCTION__, arr_handle); - bi_plist_t *obj = get_plist (pr, __FUNCTION__, obj_handle); + bi_plist_t *arr = get_plist (pr, res, __FUNCTION__, arr_handle); + bi_plist_t *obj = get_plist (pr, res, __FUNCTION__, obj_handle); obj->own = 0; R_INT (pr) = PL_A_AddObject (arr->plitem, obj->plitem); } static void -bi_PL_A_NumObjects (progs_t *pr) +bi_PL_A_NumObjects (progs_t *pr, void *_res) { + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); R_INT (pr) = PL_A_NumObjects (plist->plitem); } static void -bi_PL_A_InsertObjectAtIndex (progs_t *pr) +bi_PL_A_InsertObjectAtIndex (progs_t *pr, void *_res) { + plist_resources_t *res = _res; int dict_handle = P_INT (pr, 0); int obj_handle = P_INT (pr, 1); - bi_plist_t *arr = get_plist (pr, __FUNCTION__, dict_handle); - bi_plist_t *obj = get_plist (pr, __FUNCTION__, obj_handle); + bi_plist_t *arr = get_plist (pr, res, __FUNCTION__, dict_handle); + bi_plist_t *obj = get_plist (pr, res, __FUNCTION__, obj_handle); int ind = P_INT (pr, 2); obj->own = 0; @@ -359,11 +367,11 @@ bi_PL_A_InsertObjectAtIndex (progs_t *pr) } static void -bi_PL_RemoveObjectAtIndex (progs_t *pr) +bi_PL_RemoveObjectAtIndex (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); int ind = P_INT (pr, 1); plitem_t *plitem = PL_RemoveObjectAtIndex (plist->plitem, ind); @@ -371,48 +379,48 @@ bi_PL_RemoveObjectAtIndex (progs_t *pr) } static void -bi_PL_NewDictionary (progs_t *pr) +bi_PL_NewDictionary (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; plitem_t *plitem = PL_NewDictionary (pr->hashlink_freelist); R_INT (pr) = plist_retain (res, plitem); } static void -bi_PL_NewArray (progs_t *pr) +bi_PL_NewArray (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; plitem_t *plitem = PL_NewArray (); R_INT (pr) = plist_retain (res, plitem); } static void -bi_PL_NewData (progs_t *pr) +bi_PL_NewData (progs_t *pr, void *_res) { //FIXME not safe - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; plitem_t *plitem = PL_NewData (P_GPOINTER (pr, 0), P_INT (pr, 1)); R_INT (pr) = plist_retain (res, plitem); } static void -bi_PL_NewString (progs_t *pr) +bi_PL_NewString (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; plitem_t *plitem = PL_NewString (P_GSTRING (pr, 0)); R_INT (pr) = plist_retain (res, plitem); } static void -bi_PL_Free (progs_t *pr) +bi_PL_Free (progs_t *pr, void *_res) { - plist_resources_t *res = PR_Resources_Find (pr, "plist"); + plist_resources_t *res = _res; int handle = P_INT (pr, 0); - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); if (!plist->own) PR_RunError (pr, "attempt to free unowned plist"); @@ -425,7 +433,8 @@ bi_PL_Free (progs_t *pr) plitem_t * Plist_GetItem (progs_t *pr, int handle) { - bi_plist_t *plist = get_plist (pr, __FUNCTION__, handle); + plist_resources_t *res = PR_Resources_Find (pr, "plist"); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); return plist->plitem; } diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index 1fee454dc..89df29a33 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -84,9 +84,9 @@ handle_index (qfile_resources_t *res, qfile_t *handle) } static void -bi_qfile_clear (progs_t *pr, void *data) +bi_qfile_clear (progs_t *pr, void *_res) { - qfile_resources_t *res = (qfile_resources_t *) data; + qfile_resources_t *res = (qfile_resources_t *) _res; qfile_t *handle; for (handle = res->handles; handle; handle = handle->next) @@ -121,13 +121,13 @@ QFile_AllocHandle (progs_t *pr, QFile *file) } static void -secured (progs_t *pr) +secured (progs_t *pr, void *_res) { PR_RunError (pr, "Secured function called"); } static void -bi_Qrename (progs_t *pr) +bi_Qrename (progs_t *pr, void *_res) { const char *old = P_GSTRING (pr, 0); const char *new = P_GSTRING (pr, 1); @@ -136,7 +136,7 @@ bi_Qrename (progs_t *pr) } static void -bi_Qremove (progs_t *pr) +bi_Qremove (progs_t *pr, void *_res) { const char *path = P_GSTRING (pr, 0); @@ -144,9 +144,9 @@ bi_Qremove (progs_t *pr) } static void -bi_Qopen (progs_t *pr) +bi_Qopen (progs_t *pr, void *_res) { - qfile_resources_t *res = PR_Resources_Find (pr, "QFile"); + __auto_type res = (qfile_resources_t *) _res; const char *path = P_GSTRING (pr, 0); const char *mode = P_GSTRING (pr, 1); QFile *file; @@ -159,9 +159,8 @@ bi_Qopen (progs_t *pr) } static qfile_t * -get_handle (progs_t *pr, const char *name, int handle) +get_handle (progs_t *pr, qfile_resources_t *res, const char *name, int handle) { - qfile_resources_t *res = PR_Resources_Find (pr, "QFile"); qfile_t *h = handle_get (res, handle); if (!h) @@ -172,15 +171,16 @@ get_handle (progs_t *pr, const char *name, int handle) QFile * QFile_GetFile (progs_t *pr, int handle) { - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_resources_t *res = PR_Resources_Find (pr, "QFile"); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); return h->file; } static void -bi_Qclose (progs_t *pr) +bi_Qclose (progs_t *pr, void *_res) { - qfile_resources_t *res = PR_Resources_Find (pr, "QFile"); + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); qfile_t *h = handle_get (res, handle); @@ -194,10 +194,11 @@ bi_Qclose (progs_t *pr) } static void -bi_Qgetline (progs_t *pr) +bi_Qgetline (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); const char *s; s = Qgetline (h->file); @@ -208,11 +209,12 @@ bi_Qgetline (progs_t *pr) } static void -bi_Qreadstring (progs_t *pr) +bi_Qreadstring (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); int len = P_INT (pr, 1); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); pr_string_t str = PR_NewMutableString (pr); dstring_t *dstr = PR_GetMutableString (pr, str); @@ -235,10 +237,11 @@ check_buffer (progs_t *pr, pr_type_t *buf, int count, const char *name) } static void -bi_Qread (progs_t *pr) +bi_Qread (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); pr_type_t *buf = P_GPOINTER (pr, 1); int count = P_INT (pr, 2); @@ -247,10 +250,11 @@ bi_Qread (progs_t *pr) } static void -bi_Qwrite (progs_t *pr) +bi_Qwrite (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); pr_type_t *buf = P_GPOINTER (pr, 1); int count = P_INT (pr, 2); @@ -259,20 +263,22 @@ bi_Qwrite (progs_t *pr) } static void -bi_Qputs (progs_t *pr) +bi_Qputs (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); const char *str = P_GSTRING (pr, 1); R_INT (pr) = Qputs (h->file, str); } #if 0 static void -bi_Qgets (progs_t *pr) +bi_Qgets (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); pr_type_t *buf = P_GPOINTER (pr, 1); int count = P_INT (pr, 2); @@ -281,29 +287,32 @@ bi_Qgets (progs_t *pr) } #endif static void -bi_Qgetc (progs_t *pr) +bi_Qgetc (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); R_INT (pr) = Qgetc (h->file); } static void -bi_Qputc (progs_t *pr) +bi_Qputc (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); int c = P_INT (pr, 1); R_INT (pr) = Qputc (h->file, c); } static void -bi_Qseek (progs_t *pr) +bi_Qseek (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); int offset = P_INT (pr, 1); int whence = P_INT (pr, 2); @@ -311,37 +320,41 @@ bi_Qseek (progs_t *pr) } static void -bi_Qtell (progs_t *pr) +bi_Qtell (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); R_INT (pr) = Qtell (h->file); } static void -bi_Qflush (progs_t *pr) +bi_Qflush (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); R_INT (pr) = Qflush (h->file); } static void -bi_Qeof (progs_t *pr) +bi_Qeof (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); R_INT (pr) = Qeof (h->file); } static void -bi_Qfilesize (progs_t *pr) +bi_Qfilesize (progs_t *pr, void *_res) { + __auto_type res = (qfile_resources_t *) _res; int handle = P_INT (pr, 0); - qfile_t *h = get_handle (pr, __FUNCTION__, handle); + qfile_t *h = get_handle (pr, res, __FUNCTION__, handle); R_INT (pr) = Qfilesize (h->file); } diff --git a/libs/ruamoko/rua_qfs.c b/libs/ruamoko/rua_qfs.c index 8f36c4528..f920678ca 100644 --- a/libs/ruamoko/rua_qfs.c +++ b/libs/ruamoko/rua_qfs.c @@ -60,7 +60,7 @@ check_buffer (progs_t *pr, pr_type_t *buf, int count, const char *name) static void -bi_QFS_Open (progs_t *pr) +bi_QFS_Open (progs_t *pr, void *data) { QFile *file; const char *path = P_GSTRING (pr, 0); @@ -75,7 +75,7 @@ bi_QFS_Open (progs_t *pr) } static void -bi_QFS_WOpen (progs_t *pr) +bi_QFS_WOpen (progs_t *pr, void *data) { QFile *file; const char *path = P_GSTRING (pr, 0); @@ -90,7 +90,7 @@ bi_QFS_WOpen (progs_t *pr) } static void -bi_QFS_Rename (progs_t *pr) +bi_QFS_Rename (progs_t *pr, void *data) { const char *old = P_GSTRING (pr, 0); const char *new = P_GSTRING (pr, 1); @@ -99,7 +99,7 @@ bi_QFS_Rename (progs_t *pr) } static void -bi_QFS_LoadFile (progs_t *pr) +bi_QFS_LoadFile (progs_t *pr, void *data) { const char *filename = P_GSTRING (pr, 0); QFile *file; @@ -124,7 +124,7 @@ bi_QFS_LoadFile (progs_t *pr) } static void -bi_QFS_OpenFile (progs_t *pr) +bi_QFS_OpenFile (progs_t *pr, void *data) { QFile *file; const char *filename = P_GSTRING (pr, 0); @@ -139,7 +139,7 @@ bi_QFS_OpenFile (progs_t *pr) } static void -bi_QFS_WriteFile (progs_t *pr) +bi_QFS_WriteFile (progs_t *pr, void *data) { const char *filename = P_GSTRING (pr, 0); pr_type_t *buf = P_GPOINTER (pr, 1); @@ -151,7 +151,7 @@ bi_QFS_WriteFile (progs_t *pr) } static void -bi_QFS_Filelist (progs_t *pr) +bi_QFS_Filelist (progs_t *pr, void *data) { filelist_t *filelist = QFS_FilelistNew (); qfslist_t *list; @@ -171,7 +171,7 @@ bi_QFS_Filelist (progs_t *pr) } static void -bi_QFS_FilelistFree (progs_t *pr) +bi_QFS_FilelistFree (progs_t *pr, void *data) { qfslist_t *list = &P_STRUCT (pr, qfslist_t, 0); pr_string_t *strings = &G_STRUCT (pr, pr_string_t, list->list); @@ -183,7 +183,7 @@ bi_QFS_FilelistFree (progs_t *pr) } static void -bi_QFS_GetDirectory (progs_t *pr) +bi_QFS_GetDirectory (progs_t *pr, void *data) { RETURN_STRING (pr, qfs_gamedir->dir.def); } diff --git a/libs/ruamoko/rua_runtime.c b/libs/ruamoko/rua_runtime.c index 5a1c906ad..7ea55a68b 100644 --- a/libs/ruamoko/rua_runtime.c +++ b/libs/ruamoko/rua_runtime.c @@ -50,7 +50,7 @@ #include "rua_internal.h" static void -bi_va_copy (progs_t *pr) +bi_va_copy (progs_t *pr, void *data) { __auto_type src_args = (pr_va_list_t *) &P_POINTER (pr, 0); __auto_type src_list = &G_STRUCT (pr, pr_type_t, src_args->list); diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index 8cafdb387..592b412d4 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -85,16 +85,16 @@ script_index (script_resources_t *res, rua_script_t *script) } static void -bi_script_clear (progs_t *pr, void *data) +bi_script_clear (progs_t *pr, void *_res) { - script_resources_t *res = (script_resources_t *) data; + script_resources_t *res = (script_resources_t *) _res; script_reset (res); } static void -bi_Script_New (progs_t *pr) +bi_Script_New (progs_t *pr, void *_res) { - script_resources_t *res = PR_Resources_Find (pr, "Script"); + script_resources_t *res = _res; rua_script_t *script = script_new (res); if (!script) @@ -107,9 +107,9 @@ bi_Script_New (progs_t *pr) } static void -bi_Script_Delete (progs_t *pr) +bi_Script_Delete (progs_t *pr, void *_res) { - script_resources_t *res = PR_Resources_Find (pr, "Script"); + script_resources_t *res = _res; rua_script_t *script = script_get (res, P_INT (pr, 0)); if (!script) @@ -119,9 +119,9 @@ bi_Script_Delete (progs_t *pr) } static void -bi_Script_Start (progs_t *pr) +bi_Script_Start (progs_t *pr, void *_res) { - script_resources_t *res = PR_Resources_Find (pr, "Script"); + script_resources_t *res = _res; rua_script_t *script = script_get (res, P_INT (pr, 0)); if (!script) @@ -131,9 +131,9 @@ bi_Script_Start (progs_t *pr) } static void -bi_Script_TokenAvailable (progs_t *pr) +bi_Script_TokenAvailable (progs_t *pr, void *_res) { - script_resources_t *res = PR_Resources_Find (pr, "Script"); + script_resources_t *res = _res; rua_script_t *script = script_get (res, P_INT (pr, 0)); if (!script) @@ -142,9 +142,9 @@ bi_Script_TokenAvailable (progs_t *pr) } static void -bi_Script_GetToken (progs_t *pr) +bi_Script_GetToken (progs_t *pr, void *_res) { - script_resources_t *res = PR_Resources_Find (pr, "Script"); + script_resources_t *res = _res; rua_script_t *script = script_get (res, P_INT (pr, 0)); if (!script) @@ -153,9 +153,9 @@ bi_Script_GetToken (progs_t *pr) } static void -bi_Script_UngetToken (progs_t *pr) +bi_Script_UngetToken (progs_t *pr, void *_res) { - script_resources_t *res = PR_Resources_Find (pr, "Script"); + script_resources_t *res = _res; rua_script_t *script = script_get (res, P_INT (pr, 0)); if (!script) @@ -164,9 +164,9 @@ bi_Script_UngetToken (progs_t *pr) } static void -bi_Script_Error (progs_t *pr) +bi_Script_Error (progs_t *pr, void *_res) { - script_resources_t *res = PR_Resources_Find (pr, "Script"); + script_resources_t *res = _res; rua_script_t *script = script_get (res, P_INT (pr, 0)); if (!script) @@ -176,9 +176,9 @@ bi_Script_Error (progs_t *pr) } static void -bi_Script_NoQuoteLines (progs_t *pr) +bi_Script_NoQuoteLines (progs_t *pr, void *_res) { - script_resources_t *res = PR_Resources_Find (pr, "Script"); + script_resources_t *res = _res; rua_script_t *script = script_get (res, P_INT (pr, 0)); if (!script) diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index c8a0f2672..b6ee26f4d 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -137,9 +137,8 @@ res_set_iter_index (set_resources_t *res, bi_set_iter_t *set_iter) } static bi_set_t * -get_set (progs_t *pr, const char *name, int index) +get_set (progs_t *pr, set_resources_t *res, const char *name, int index) { - set_resources_t *res = PR_Resources_Find (pr, "Set"); bi_set_t *set = res_set_get (res, index); if (!set) @@ -148,9 +147,8 @@ get_set (progs_t *pr, const char *name, int index) } static bi_set_iter_t * -get_set_iter (progs_t *pr, const char *name, int index) +get_set_iter (progs_t *pr, set_resources_t *res, const char *name, int index) { - set_resources_t *res = PR_Resources_Find (pr, "Set"); bi_set_iter_t *set = res_set_iter_get (res, index); if (!set) @@ -159,10 +157,8 @@ get_set_iter (progs_t *pr, const char *name, int index) } static void -del_set_iter (progs_t *pr, bi_set_iter_t *set_iter) +del_set_iter (progs_t *pr, set_resources_t *res, bi_set_iter_t *set_iter) { - set_resources_t *res = PR_Resources_Find (pr, "Set"); - *set_iter->prev = set_iter->next; if (set_iter->next) set_iter->next->prev = set_iter->prev; @@ -170,27 +166,31 @@ del_set_iter (progs_t *pr, bi_set_iter_t *set_iter) } static void -bi_set_del_iter (progs_t *pr) +bi_set_del_iter (progs_t *pr, void *_res) { - bi_set_iter_t *set_iter = get_set_iter (pr, __FUNCTION__, P_INT (pr, 0)); + set_resources_t *res = _res; + bi_set_iter_t *set_iter = get_set_iter (pr, res, __FUNCTION__, + P_INT (pr, 0)); set_del_iter (set_iter->iter); - del_set_iter (pr, set_iter); + del_set_iter (pr, res, set_iter); } static void -bi_set_iter_element (progs_t *pr) +bi_set_iter_element (progs_t *pr, void *_res) { - bi_set_iter_t *set_iter = get_set_iter (pr, __FUNCTION__, P_INT (pr, 0)); + set_resources_t *res = _res; + bi_set_iter_t *set_iter = get_set_iter (pr, res, __FUNCTION__, + P_INT (pr, 0)); R_INT (pr) = set_iter->iter->element; } static void -bi_set_new (progs_t *pr) +bi_set_new (progs_t *pr, void *_res) { - set_resources_t *res = PR_Resources_Find (pr, "Set"); + set_resources_t *res = _res; bi_set_t *set; set = res_set_new (res); @@ -207,10 +207,10 @@ bi_set_new (progs_t *pr) } static void -bi_set_delete (progs_t *pr) +bi_set_delete (progs_t *pr, void *_res) { - set_resources_t *res = PR_Resources_Find (pr, "Set"); - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); + set_resources_t *res = _res; + bi_set_t *set = get_set (pr, res, __FUNCTION__, P_INT (pr, 0)); set_delete (set->set); *set->prev = set->next; @@ -220,281 +220,311 @@ bi_set_delete (progs_t *pr) } static void -rua_set_add (progs_t *pr, pr_int_t setid, pr_uint_t element) +rua_set_add (progs_t *pr, set_resources_t *res, + pr_int_t setid, pr_uint_t element) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); set_add (set->set, element); } static void -bi_set_add (progs_t *pr) +bi_set_add (progs_t *pr, void *_res) { - rua_set_add (pr, P_INT (pr, 0), P_UINT (pr, 1)); + set_resources_t *res = _res; + rua_set_add (pr, res, P_INT (pr, 0), P_UINT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_remove (progs_t *pr, pr_int_t setid, pr_uint_t element) +rua_set_remove (progs_t *pr, set_resources_t *res, + pr_int_t setid, pr_uint_t element) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); set_remove (set->set, element); } static void -bi_set_remove (progs_t *pr) +bi_set_remove (progs_t *pr, void *_res) { - rua_set_remove (pr, P_INT (pr, 0), P_UINT (pr, 1)); + set_resources_t *res = _res; + rua_set_remove (pr, res, P_INT (pr, 0), P_UINT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_invert (progs_t *pr, pr_int_t setid) +rua_set_invert (progs_t *pr, set_resources_t *res, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); set_invert (set->set); } static void -bi_set_invert (progs_t *pr) +bi_set_invert (progs_t *pr, void *_res) { - rua_set_invert (pr, P_INT (pr, 0)); + set_resources_t *res = _res; + rua_set_invert (pr, res, P_INT (pr, 0)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_union (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +rua_set_union (progs_t *pr, set_resources_t *res, + pr_int_t dstid, pr_int_t srcid) { - bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); - bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + bi_set_t *dst = get_set (pr, res, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, res, __FUNCTION__, srcid); set_union (dst->set, src->set); } static void -bi_set_union (progs_t *pr) +bi_set_union (progs_t *pr, void *_res) { - rua_set_union (pr, P_INT (pr, 0), P_INT (pr, 1)); + set_resources_t *res = _res; + rua_set_union (pr, res, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_intersection (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +rua_set_intersection (progs_t *pr, set_resources_t *res, + pr_int_t dstid, pr_int_t srcid) { - bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); - bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + bi_set_t *dst = get_set (pr, res, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, res, __FUNCTION__, srcid); set_intersection (dst->set, src->set); } static void -bi_set_intersection (progs_t *pr) +bi_set_intersection (progs_t *pr, void *_res) { - rua_set_intersection (pr, P_INT (pr, 0), P_INT (pr, 1)); + set_resources_t *res = _res; + rua_set_intersection (pr, res, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_difference (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +rua_set_difference (progs_t *pr, set_resources_t *res, + pr_int_t dstid, pr_int_t srcid) { - bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); - bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + bi_set_t *dst = get_set (pr, res, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, res, __FUNCTION__, srcid); set_difference (dst->set, src->set); } static void -bi_set_difference (progs_t *pr) +bi_set_difference (progs_t *pr, void *_res) { - rua_set_difference (pr, P_INT (pr, 0), P_INT (pr, 1)); + set_resources_t *res = _res; + rua_set_difference (pr, res, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_reverse_difference (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +rua_set_reverse_difference (progs_t *pr, set_resources_t *res, + pr_int_t dstid, pr_int_t srcid) { - bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); - bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + bi_set_t *dst = get_set (pr, res, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, res, __FUNCTION__, srcid); set_reverse_difference (dst->set, src->set); } static void -bi_set_reverse_difference (progs_t *pr) +bi_set_reverse_difference (progs_t *pr, void *_res) { - rua_set_reverse_difference (pr, P_INT (pr, 0), P_INT (pr, 1)); + set_resources_t *res = _res; + rua_set_reverse_difference (pr, res, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_assign (progs_t *pr, pr_int_t dstid, pr_int_t srcid) +rua_set_assign (progs_t *pr, set_resources_t *res, + pr_int_t dstid, pr_int_t srcid) { - bi_set_t *dst = get_set (pr, __FUNCTION__, dstid); - bi_set_t *src = get_set (pr, __FUNCTION__, srcid); + bi_set_t *dst = get_set (pr, res, __FUNCTION__, dstid); + bi_set_t *src = get_set (pr, res, __FUNCTION__, srcid); set_assign (dst->set, src->set); } static void -bi_set_assign (progs_t *pr) +bi_set_assign (progs_t *pr, void *_res) { - rua_set_assign (pr, P_INT (pr, 0), P_INT (pr, 1)); + set_resources_t *res = _res; + rua_set_assign (pr, res, P_INT (pr, 0), P_INT (pr, 1)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_empty (progs_t *pr, pr_int_t setid) +rua_set_empty (progs_t *pr, set_resources_t *res, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); set_empty (set->set); } static void -bi_set_empty (progs_t *pr) +bi_set_empty (progs_t *pr, void *_res) { - rua_set_empty (pr, P_INT (pr, 0)); + set_resources_t *res = _res; + rua_set_empty (pr, res, P_INT (pr, 0)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_everything (progs_t *pr, pr_int_t setid) +rua_set_everything (progs_t *pr, set_resources_t *res, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); set_everything (set->set); } static void -bi_set_everything (progs_t *pr) +bi_set_everything (progs_t *pr, void *_res) { - rua_set_everything (pr, P_INT (pr, 0)); + set_resources_t *res = _res; + rua_set_everything (pr, res, P_INT (pr, 0)); R_INT (pr) = P_INT (pr, 0); } static void -rua_set_is_empty (progs_t *pr, pr_int_t setid) +rua_set_is_empty (progs_t *pr, set_resources_t *res, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); R_INT (pr) = set_is_empty (set->set); } static void -bi_set_is_empty (progs_t *pr) +bi_set_is_empty (progs_t *pr, void *_res) { - rua_set_is_empty (pr, P_INT (pr, 0)); + set_resources_t *res = _res; + rua_set_is_empty (pr, res, P_INT (pr, 0)); } static void -rua_set_is_everything (progs_t *pr, pr_int_t setid) +rua_set_is_everything (progs_t *pr, set_resources_t *res, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); + bi_set_t *set = get_set (pr, res, __FUNCTION__, P_INT (pr, 0)); R_INT (pr) = set_is_everything (set->set); } static void -bi_set_is_everything (progs_t *pr) +bi_set_is_everything (progs_t *pr, void *_res) { - rua_set_is_everything (pr, P_INT (pr, 0)); + set_resources_t *res = _res; + rua_set_is_everything (pr, res, P_INT (pr, 0)); } static void -rua_set_is_disjoint (progs_t *pr, pr_int_t sid1, pr_int_t sid2) +rua_set_is_disjoint (progs_t *pr, set_resources_t *res, + pr_int_t sid1, pr_int_t sid2) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, sid1); - bi_set_t *set2 = get_set (pr, __FUNCTION__, sid2); + bi_set_t *set1 = get_set (pr, res, __FUNCTION__, sid1); + bi_set_t *set2 = get_set (pr, res, __FUNCTION__, sid2); R_INT (pr) = set_is_disjoint (set1->set, set2->set); } static void -bi_set_is_disjoint (progs_t *pr) +bi_set_is_disjoint (progs_t *pr, void *_res) { - rua_set_is_disjoint (pr, P_INT (pr, 0), P_INT (pr, 1)); + set_resources_t *res = _res; + rua_set_is_disjoint (pr, res, P_INT (pr, 0), P_INT (pr, 1)); } static void -rua_set_is_intersecting (progs_t *pr, pr_int_t sid1, pr_int_t sid2) +rua_set_is_intersecting (progs_t *pr, set_resources_t *res, + pr_int_t sid1, pr_int_t sid2) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, sid1); - bi_set_t *set2 = get_set (pr, __FUNCTION__, sid2); + bi_set_t *set1 = get_set (pr, res, __FUNCTION__, sid1); + bi_set_t *set2 = get_set (pr, res, __FUNCTION__, sid2); R_INT (pr) = set_is_intersecting (set1->set, set2->set); } static void -bi_set_is_intersecting (progs_t *pr) +bi_set_is_intersecting (progs_t *pr, void *_res) { - rua_set_is_intersecting (pr, P_INT (pr, 0), P_INT (pr, 1)); + set_resources_t *res = _res; + rua_set_is_intersecting (pr, res, P_INT (pr, 0), P_INT (pr, 1)); } static void -rua_set_is_equivalent (progs_t *pr, pr_int_t sid1, pr_int_t sid2) +rua_set_is_equivalent (progs_t *pr, set_resources_t *res, + pr_int_t sid1, pr_int_t sid2) { - bi_set_t *set1 = get_set (pr, __FUNCTION__, sid1); - bi_set_t *set2 = get_set (pr, __FUNCTION__, sid2); + bi_set_t *set1 = get_set (pr, res, __FUNCTION__, sid1); + bi_set_t *set2 = get_set (pr, res, __FUNCTION__, sid2); R_INT (pr) = set_is_equivalent (set1->set, set2->set); } static void -bi_set_is_equivalent (progs_t *pr) +bi_set_is_equivalent (progs_t *pr, void *_res) { - rua_set_is_equivalent (pr, P_INT (pr, 0), P_INT (pr, 1)); + set_resources_t *res = _res; + rua_set_is_equivalent (pr, res, P_INT (pr, 0), P_INT (pr, 1)); } static void -rua_set_is_subset (progs_t *pr, pr_int_t setid, pr_int_t subid) +rua_set_is_subset (progs_t *pr, set_resources_t *res, pr_int_t setid, + pr_int_t subid) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); - bi_set_t *sub = get_set (pr, __FUNCTION__, subid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); + bi_set_t *sub = get_set (pr, res, __FUNCTION__, subid); R_INT (pr) = set_is_subset (set->set, sub->set); } static void -bi_set_is_subset (progs_t *pr) +bi_set_is_subset (progs_t *pr, void *_res) { - rua_set_is_subset (pr, P_INT (pr, 0), P_INT (pr, 1)); + set_resources_t *res = _res; + rua_set_is_subset (pr, res, P_INT (pr, 0), P_INT (pr, 1)); } static void -rua_set_is_member (progs_t *pr, pr_int_t setid, pr_uint_t element) +rua_set_is_member (progs_t *pr, set_resources_t *res, pr_int_t setid, + pr_uint_t element) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); R_INT (pr) = set_is_member (set->set, element); } static void -bi_set_is_member (progs_t *pr) +bi_set_is_member (progs_t *pr, void *_res) { - rua_set_is_member (pr, P_INT (pr, 0), P_UINT (pr, 1)); + set_resources_t *res = _res; + rua_set_is_member (pr, res, P_INT (pr, 0), P_UINT (pr, 1)); } static void -rua_set_count (progs_t *pr, pr_int_t setid) +rua_set_count (progs_t *pr, set_resources_t *res, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); R_INT (pr) = set_count (set->set); } static void -bi_set_count (progs_t *pr) +bi_set_count (progs_t *pr, void *_res) { - rua_set_count (pr, P_INT (pr, 0)); + set_resources_t *res = _res; + rua_set_count (pr, res, P_INT (pr, 0)); } static void -bi_set_first (progs_t *pr) +bi_set_first (progs_t *pr, void *_res) { - set_resources_t *res = PR_Resources_Find (pr, "Set"); - bi_set_t *set = get_set (pr, __FUNCTION__, P_INT (pr, 0)); + set_resources_t *res = _res; + bi_set_t *set = get_set (pr, res, __FUNCTION__, P_INT (pr, 0)); set_iter_t *iter; bi_set_iter_t *set_iter; @@ -517,12 +547,14 @@ bi_set_first (progs_t *pr) } static void -bi_set_next (progs_t *pr) +bi_set_next (progs_t *pr, void *_res) { - bi_set_iter_t *set_iter = get_set_iter (pr, __FUNCTION__, P_INT (pr, 0)); + set_resources_t *res = _res; + bi_set_iter_t *set_iter = get_set_iter (pr, res, __FUNCTION__, + P_INT (pr, 0)); if (!set_next (set_iter->iter)) { - del_set_iter (pr, set_iter); + del_set_iter (pr, res, set_iter); R_INT (pr) = 0; return; } @@ -530,212 +562,234 @@ bi_set_next (progs_t *pr) } static void -rua_set_as_string (progs_t *pr, pr_int_t setid) +rua_set_as_string (progs_t *pr, set_resources_t *res, pr_int_t setid) { - bi_set_t *set = get_set (pr, __FUNCTION__, setid); + bi_set_t *set = get_set (pr, res, __FUNCTION__, setid); RETURN_STRING (pr, set_as_string (set->set)); } static void -bi_set_as_string (progs_t *pr) +bi_set_as_string (progs_t *pr, void *_res) { - rua_set_as_string (pr, P_INT (pr, 0)); + set_resources_t *res = _res; + rua_set_as_string (pr, res, P_INT (pr, 0)); } static void -bi__i_SetIterator__element (progs_t *pr) +bi__i_SetIterator__element (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_iter_t *iter_obj = &P_STRUCT (pr, pr_set_iter_t, 0); - bi_set_iter_t *set_iter = get_set_iter (pr, __FUNCTION__, iter_obj->iter); + bi_set_iter_t *set_iter = get_set_iter (pr, res, __FUNCTION__, + iter_obj->iter); R_INT (pr) = set_iter->iter->element; } static void -bi__i_Set__add_ (progs_t *pr) +bi__i_Set__add_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - rua_set_add (pr, set_obj->set, P_UINT (pr, 2)); + rua_set_add (pr, res, set_obj->set, P_UINT (pr, 2)); R_INT (pr) = set_ptr; } static void -bi__i_Set__remove_ (progs_t *pr) +bi__i_Set__remove_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - rua_set_remove (pr, set_obj->set, P_UINT (pr, 2)); + rua_set_remove (pr, res, set_obj->set, P_UINT (pr, 2)); R_INT (pr) = set_ptr; } static void -bi__i_Set__invert (progs_t *pr) +bi__i_Set__invert (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - rua_set_invert (pr, set_obj->set); + rua_set_invert (pr, res, set_obj->set); R_INT (pr) = set_ptr; } static void -bi__i_Set__union_ (progs_t *pr) +bi__i_Set__union_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - rua_set_union (pr, dst_obj->set, src_obj->set); + rua_set_union (pr, res, dst_obj->set, src_obj->set); } static void -bi__i_Set__intersection_ (progs_t *pr) +bi__i_Set__intersection_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - rua_set_intersection (pr, dst_obj->set, src_obj->set); + rua_set_intersection (pr, res, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } static void -bi__i_Set__difference_ (progs_t *pr) +bi__i_Set__difference_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - rua_set_difference (pr, dst_obj->set, src_obj->set); + rua_set_difference (pr, res, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } static void -bi__i_Set__reverse_difference_ (progs_t *pr) +bi__i_Set__reverse_difference_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - rua_set_reverse_difference (pr, dst_obj->set, src_obj->set); + rua_set_reverse_difference (pr, res, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } static void -bi__i_Set__assign_ (progs_t *pr) +bi__i_Set__assign_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t dst_ptr = P_POINTER (pr, 0); pr_set_t *dst_obj = &G_STRUCT (pr, pr_set_t, dst_ptr); pr_set_t *src_obj = &P_STRUCT (pr, pr_set_t, 2); - rua_set_assign (pr, dst_obj->set, src_obj->set); + rua_set_assign (pr, res, dst_obj->set, src_obj->set); R_INT (pr) = dst_ptr; } static void -bi__i_Set__empty (progs_t *pr) +bi__i_Set__empty (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - rua_set_empty (pr, set_obj->set); + rua_set_empty (pr, res, set_obj->set); R_INT (pr) = set_ptr; } static void -bi__i_Set__everything (progs_t *pr) +bi__i_Set__everything (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_ptr_t set_ptr = P_POINTER (pr, 0); pr_set_t *set_obj = &G_STRUCT (pr, pr_set_t, set_ptr); - rua_set_everything (pr, set_obj->set); + rua_set_everything (pr, res, set_obj->set); R_INT (pr) = set_ptr; } static void -bi__i_Set__is_empty (progs_t *pr) +bi__i_Set__is_empty (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - rua_set_is_empty (pr, set_obj->set); + rua_set_is_empty (pr, res, set_obj->set); } static void -bi__i_Set__is_everything (progs_t *pr) +bi__i_Set__is_everything (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - rua_set_is_everything (pr, set_obj->set); + rua_set_is_everything (pr, res, set_obj->set); } static void -bi__i_Set__is_disjoint_ (progs_t *pr) +bi__i_Set__is_disjoint_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); - rua_set_is_disjoint (pr, s1_obj->set, s2_obj->set); + rua_set_is_disjoint (pr, res, s1_obj->set, s2_obj->set); } static void -bi__i_Set__is_intersecting_ (progs_t *pr) +bi__i_Set__is_intersecting_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); - rua_set_is_intersecting (pr, s1_obj->set, s2_obj->set); + rua_set_is_intersecting (pr, res, s1_obj->set, s2_obj->set); } static void -bi__i_Set__is_equivalent_ (progs_t *pr) +bi__i_Set__is_equivalent_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_t *s1_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *s2_obj = &P_STRUCT (pr, pr_set_t, 2); - rua_set_is_equivalent (pr, s1_obj->set, s2_obj->set); + rua_set_is_equivalent (pr, res, s1_obj->set, s2_obj->set); } static void -bi__i_Set__is_subset_ (progs_t *pr) +bi__i_Set__is_subset_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); pr_set_t *sub_obj = &P_STRUCT (pr, pr_set_t, 2); - rua_set_is_subset (pr, set_obj->set, sub_obj->set); + rua_set_is_subset (pr, res, set_obj->set, sub_obj->set); } static void -bi__i_Set__is_member_ (progs_t *pr) +bi__i_Set__is_member_ (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - rua_set_is_member (pr, set_obj->set, P_UINT (pr, 2)); + rua_set_is_member (pr, res, set_obj->set, P_UINT (pr, 2)); } static void -bi__i_Set__size (progs_t *pr) +bi__i_Set__size (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - rua_set_count (pr, set_obj->set); + rua_set_count (pr, res, set_obj->set); } static void -bi__i_Set__as_string (progs_t *pr) +bi__i_Set__as_string (progs_t *pr, void *_res) { + set_resources_t *res = _res; pr_set_t *set_obj = &P_STRUCT (pr, pr_set_t, 0); - rua_set_as_string (pr, set_obj->set); + rua_set_as_string (pr, res, set_obj->set); } static void -res_set_clear (progs_t *pr, void *data) +res_set_clear (progs_t *pr, void *_res) { - set_resources_t *res = (set_resources_t *) data; + set_resources_t *res = (set_resources_t *) _res; bi_set_t *set; bi_set_iter_t *set_iter; diff --git a/libs/ruamoko/rua_stdlib.c b/libs/ruamoko/rua_stdlib.c index 50fd1cc04..d74d6b403 100644 --- a/libs/ruamoko/rua_stdlib.c +++ b/libs/ruamoko/rua_stdlib.c @@ -84,7 +84,7 @@ rua_compare (const void *a, const void *b, void *_f) } static void -bi_bsearch (progs_t *pr) +bi_bsearch (progs_t *pr, void *data) { const void *key = P_GPOINTER (pr, 0); const void *array = P_GPOINTER (pr, 1); @@ -103,7 +103,7 @@ bi_bsearch (progs_t *pr) } static void -bi_fbsearch (progs_t *pr) +bi_fbsearch (progs_t *pr, void *data) { const void *key = P_GPOINTER (pr, 0); const void *array = P_GPOINTER (pr, 1); @@ -122,7 +122,7 @@ bi_fbsearch (progs_t *pr) } static void -bi_qsort (progs_t *pr) +bi_qsort (progs_t *pr, void *data) { void *array = P_GPOINTER (pr, 0); size_t nmemb = P_INT (pr, 1); @@ -138,7 +138,7 @@ bi_qsort (progs_t *pr) } static void -bi_prefixsumi (progs_t *pr) +bi_prefixsumi (progs_t *pr, void *data) { int *array = (int *) P_GPOINTER (pr, 0); int count = P_INT (pr, 1); @@ -149,7 +149,7 @@ bi_prefixsumi (progs_t *pr) } static void -bi_prefixsumf (progs_t *pr) +bi_prefixsumf (progs_t *pr, void *data) { float *array = (float *) P_GPOINTER (pr, 0); int count = P_INT (pr, 1); diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index f5ccd6d86..8977160a7 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -52,7 +52,7 @@ #include "rua_internal.h" static void -bi_strlen (progs_t *pr) +bi_strlen (progs_t *pr, void *data) { const char *s; @@ -84,7 +84,7 @@ RUA_Sprintf (progs_t *pr, dstring_t *dstr, const char *func, int fmt_arg) } static void -bi_sprintf (progs_t *pr) +bi_sprintf (progs_t *pr, void *data) { dstring_t *dstr; @@ -95,7 +95,7 @@ bi_sprintf (progs_t *pr) } static void -bi_vsprintf (progs_t *pr) +bi_vsprintf (progs_t *pr, void *data) { const char *fmt = P_GSTRING (pr, 0); __auto_type args = &P_PACKED (pr, pr_va_list_t, 1); @@ -114,19 +114,19 @@ bi_vsprintf (progs_t *pr) } static void -bi_str_new (progs_t *pr) +bi_str_new (progs_t *pr, void *data) { R_STRING (pr) = PR_NewMutableString (pr); } static void -bi_str_free (progs_t *pr) +bi_str_free (progs_t *pr, void *data) { PR_FreeString (pr, P_STRING (pr, 0)); } static void -bi_str_hold (progs_t *pr) +bi_str_hold (progs_t *pr, void *data) { pr_string_t str = P_STRING (pr, 0); PR_HoldString (pr, str); @@ -134,19 +134,19 @@ bi_str_hold (progs_t *pr) } static void -bi_str_valid (progs_t *pr) +bi_str_valid (progs_t *pr, void *data) { R_INT (pr) = PR_StringValid (pr, P_STRING (pr, 0)); } static void -bi_str_mutable (progs_t *pr) +bi_str_mutable (progs_t *pr, void *data) { R_INT (pr) = PR_StringMutable (pr, P_STRING (pr, 0)); } static void -bi_str_copy (progs_t *pr) +bi_str_copy (progs_t *pr, void *data) { dstring_t *dst = P_DSTRING (pr, 0); const char *src = P_GSTRING (pr, 1); @@ -156,7 +156,7 @@ bi_str_copy (progs_t *pr) } static void -bi_str_cat (progs_t *pr) +bi_str_cat (progs_t *pr, void *data) { dstring_t *dst = P_DSTRING (pr, 0); const char *src = P_GSTRING (pr, 1); @@ -166,7 +166,7 @@ bi_str_cat (progs_t *pr) } static void -bi_str_clear (progs_t *pr) +bi_str_clear (progs_t *pr, void *data) { dstring_t *str = P_DSTRING (pr, 0); @@ -199,7 +199,7 @@ str_mid (progs_t *pr, const char *str, int pos, int end, int size) } static void -bi_str_mid_2 (progs_t *pr) +bi_str_mid_2 (progs_t *pr, void *data) { const char *str = P_GSTRING (pr, 0); int pos = P_INT (pr, 1); @@ -209,7 +209,7 @@ bi_str_mid_2 (progs_t *pr) } static void -bi_str_mid_3 (progs_t *pr) +bi_str_mid_3 (progs_t *pr, void *data) { const char *str = P_GSTRING (pr, 0); int pos = P_INT (pr, 1); @@ -220,7 +220,7 @@ bi_str_mid_3 (progs_t *pr) } static void -bi_str_str (progs_t *pr) +bi_str_str (progs_t *pr, void *data) { const char *haystack = P_GSTRING (pr, 0); const char *needle = P_GSTRING (pr, 1); @@ -233,7 +233,7 @@ bi_str_str (progs_t *pr) } static void -bi_str_char (progs_t *pr) +bi_str_char (progs_t *pr, void *data) { const char *str = P_GSTRING (pr, 0); int ind = P_INT (pr, 1); @@ -245,7 +245,7 @@ bi_str_char (progs_t *pr) } static void -bi_str_quote (progs_t *pr) +bi_str_quote (progs_t *pr, void *data) { const char *str = P_GSTRING (pr, 0); // can have up to 4 chars per char (a -> \x61) @@ -284,7 +284,7 @@ bi_str_quote (progs_t *pr) } static void -bi_str_lower (progs_t *pr) +bi_str_lower (progs_t *pr, void *data) { const char *str = P_GSTRING (pr, 0); char *lower = alloca (strlen (str) + 1); @@ -300,7 +300,7 @@ bi_str_lower (progs_t *pr) } static void -bi_str_upper (progs_t *pr) +bi_str_upper (progs_t *pr, void *data) { const char *str = P_GSTRING (pr, 0); char *upper = alloca (strlen (str) + 1); diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 87cd3e513..ef2e5b403 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -108,9 +108,8 @@ qpic_index (draw_resources_t *res, qpic_res_t *qp) } static qpic_res_t * -get_qpic (progs_t *pr, const char *name, int qpic_handle) +get_qpic (progs_t *pr, draw_resources_t *res, const char *name, int qpic_handle) { - draw_resources_t *res = PR_Resources_Find (pr, "Draw"); qpic_res_t *qp = qpic_get (res, qpic_handle); if (!qp) @@ -119,20 +118,20 @@ get_qpic (progs_t *pr, const char *name, int qpic_handle) } static void -bi_Draw_FreePic (progs_t *pr) +bi_Draw_FreePic (progs_t *pr, void *_res) { - draw_resources_t *res = PR_Resources_Find (pr, "Draw"); + draw_resources_t *res = _res; bi_qpic_t *bq = &P_STRUCT (pr, bi_qpic_t, 0); - qpic_res_t *qp = get_qpic (pr, __FUNCTION__, bq->pic_handle); + qpic_res_t *qp = get_qpic (pr, res, __FUNCTION__, bq->pic_handle); PR_Zone_Free (pr, qp->bq); qpic_free (res, qp); } static void -bi_Draw_MakePic (progs_t *pr) +bi_Draw_MakePic (progs_t *pr, void *_res) { - draw_resources_t *res = PR_Resources_Find (pr, "Draw"); + draw_resources_t *res = _res; int width = P_INT (pr, 0); int height = P_INT (pr, 1); byte *data = (byte *) P_GSTRING (pr, 2); @@ -154,9 +153,9 @@ bi_Draw_MakePic (progs_t *pr) } static void -bi_Draw_CachePic (progs_t *pr) +bi_Draw_CachePic (progs_t *pr, void *_res) { - draw_resources_t *res = PR_Resources_Find (pr, "Draw"); + draw_resources_t *res = _res; const char *name = P_GSTRING (pr, 0); int alpha = P_INT (pr, 1); qpic_t *pic; @@ -183,36 +182,39 @@ bi_Draw_CachePic (progs_t *pr) } static void -bi_Draw_Pic (progs_t *pr) +bi_Draw_Pic (progs_t *pr, void *_res) { + draw_resources_t *res = _res; int x = P_INT (pr, 0); int y = P_INT (pr, 1); bi_qpic_t *bq = &P_STRUCT (pr, bi_qpic_t, 2); - qpic_res_t *qp = get_qpic (pr, __FUNCTION__, bq->pic_handle); + qpic_res_t *qp = get_qpic (pr, res, __FUNCTION__, bq->pic_handle); qpic_t *pic = qp->pic; r_funcs->Draw_Pic (x, y, pic); } static void -bi_Draw_Picf (progs_t *pr) +bi_Draw_Picf (progs_t *pr, void *_res) { + draw_resources_t *res = _res; float x = P_FLOAT (pr, 0); float y = P_FLOAT (pr, 1); bi_qpic_t *bq = &P_STRUCT (pr, bi_qpic_t, 2); - qpic_res_t *qp = get_qpic (pr, __FUNCTION__, bq->pic_handle); + qpic_res_t *qp = get_qpic (pr, res, __FUNCTION__, bq->pic_handle); qpic_t *pic = qp->pic; r_funcs->Draw_Picf (x, y, pic); } static void -bi_Draw_SubPic (progs_t *pr) +bi_Draw_SubPic (progs_t *pr, void *_res) { + draw_resources_t *res = _res; int x = P_INT (pr, 0); int y = P_INT (pr, 1); bi_qpic_t *bq = &P_STRUCT (pr, bi_qpic_t, 2); - qpic_res_t *qp = get_qpic (pr, __FUNCTION__, bq->pic_handle); + qpic_res_t *qp = get_qpic (pr, res, __FUNCTION__, bq->pic_handle); qpic_t *pic = qp->pic; int srcx = P_INT (pr, 3); int srcy = P_INT (pr, 4); @@ -223,19 +225,20 @@ bi_Draw_SubPic (progs_t *pr) } static void -bi_Draw_CenterPic (progs_t *pr) +bi_Draw_CenterPic (progs_t *pr, void *_res) { + draw_resources_t *res = _res; int x = P_INT (pr, 0); int y = P_INT (pr, 1); bi_qpic_t *bq = &P_STRUCT (pr, bi_qpic_t, 2); - qpic_res_t *qp = get_qpic (pr, __FUNCTION__, bq->pic_handle); + qpic_res_t *qp = get_qpic (pr, res, __FUNCTION__, bq->pic_handle); qpic_t *pic = qp->pic; r_funcs->Draw_Pic (x - pic->width / 2, y, pic); } static void -bi_Draw_Character (progs_t *pr) +bi_Draw_Character (progs_t *pr, void *_res) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -245,7 +248,7 @@ bi_Draw_Character (progs_t *pr) } static void -bi_Draw_String (progs_t *pr) +bi_Draw_String (progs_t *pr, void *_res) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -255,7 +258,7 @@ bi_Draw_String (progs_t *pr) } static void -bi_Draw_nString (progs_t *pr) +bi_Draw_nString (progs_t *pr, void *_res) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -266,7 +269,7 @@ bi_Draw_nString (progs_t *pr) } static void -bi_Draw_AltString (progs_t *pr) +bi_Draw_AltString (progs_t *pr, void *_res) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -282,7 +285,7 @@ bi_Draw_AltString (progs_t *pr) (only a wrapper function to original qf-api) */ static void -bi_Draw_Fill (progs_t *pr) +bi_Draw_Fill (progs_t *pr, void *_res) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); @@ -294,7 +297,7 @@ bi_Draw_Fill (progs_t *pr) } static void -bi_Draw_Crosshair (progs_t *pr) +bi_Draw_Crosshair (progs_t *pr, void *_res) { int ch = P_INT (pr, 0); int x = P_INT (pr, 1); @@ -310,9 +313,9 @@ bi_draw_get_key (const void *p, void *unused) } static void -bi_draw_clear (progs_t *pr, void *data) +bi_draw_clear (progs_t *pr, void *_res) { - draw_resources_t *res = (draw_resources_t *) data; + draw_resources_t *res = (draw_resources_t *) _res; qpic_res_t *qp; for (qp = res->qpics; qp; qp = qp->next) { diff --git a/nq/include/server.h b/nq/include/server.h index 5af088cc8..8c43ed2e4 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -285,7 +285,7 @@ qboolean SV_movestep (edict_t *ent, const vec3_t move, qboolean relink); void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg); -void SV_MoveToGoal (progs_t *pr); +void SV_MoveToGoal (progs_t *pr, void *data); void SV_CheckForNewClients (void); void SV_RunClients (void); diff --git a/nq/include/sv_pr_cmds.h b/nq/include/sv_pr_cmds.h index c068a4487..5716e9793 100644 --- a/nq/include/sv_pr_cmds.h +++ b/nq/include/sv_pr_cmds.h @@ -31,6 +31,6 @@ #ifndef __sv_pr_cmds_h #define __sv_pr_cmds_h -void PF_changeyaw (progs_t * pr); +void PF_changeyaw (progs_t * pr, void *data); #endif // __sv_pr_cmds_h diff --git a/nq/source/sv_move.c b/nq/source/sv_move.c index 494fc7083..3970f6d78 100644 --- a/nq/source/sv_move.c +++ b/nq/source/sv_move.c @@ -229,7 +229,7 @@ SV_StepDirection (edict_t *ent, float yaw, float dist) vec3_t move, oldorigin; SVfloat (ent, ideal_yaw) = yaw; - PF_changeyaw (&sv_pr_state); + PF_changeyaw (&sv_pr_state, 0); yaw = yaw * M_PI * 2 / 360; move[0] = cos (yaw) * dist; @@ -346,7 +346,7 @@ SV_CloseEnough (edict_t *ent, edict_t *goal, float dist) } void -SV_MoveToGoal (progs_t *pr) +SV_MoveToGoal (progs_t *pr, void *data) { edict_t *ent, *goal; float dist; diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index eee7778a1..b805a40be 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -66,7 +66,7 @@ // void (string e) error */ static void -PF_error (progs_t *pr) +PF_error (progs_t *pr, void *data) { const char *s; edict_t *ed; @@ -90,7 +90,7 @@ PF_error (progs_t *pr) // void (string e) objerror */ static void -PF_objerror (progs_t *pr) +PF_objerror (progs_t *pr, void *data) { const char *s; edict_t *ed; @@ -112,7 +112,7 @@ PF_objerror (progs_t *pr) void (vector angles) makevectors */ static void -PF_makevectors (progs_t *pr) +PF_makevectors (progs_t *pr, void *data) { AngleVectors (P_VECTOR (pr, 0), *sv_globals.v_forward, *sv_globals.v_right, *sv_globals.v_up); @@ -131,7 +131,7 @@ PF_makevectors (progs_t *pr) // void (entity e, vector o) setorigin */ static void -PF_setorigin (progs_t *pr) +PF_setorigin (progs_t *pr, void *data) { edict_t *e; float *org; @@ -221,7 +221,7 @@ SetMinMaxSize (progs_t *pr, edict_t *e, const vec3_t min, const vec3_t max, // void (entity e, vector min, vector max) setsize */ static void -PF_setsize (progs_t *pr) +PF_setsize (progs_t *pr, void *data) { edict_t *e; float *min, *max; @@ -239,7 +239,7 @@ PF_setsize (progs_t *pr) // void (entity e, string m) setmodel */ static void -PF_setmodel (progs_t *pr) +PF_setmodel (progs_t *pr, void *data) { edict_t *e; const char *m, **check; @@ -283,7 +283,7 @@ PF_setmodel (progs_t *pr) // void (string s) bprint */ static void -PF_bprint (progs_t *pr) +PF_bprint (progs_t *pr, void *data) { const char *s; @@ -300,7 +300,7 @@ PF_bprint (progs_t *pr) // void (entity client, string s) sprint */ static void -PF_sprint (progs_t *pr) +PF_sprint (progs_t *pr, void *data) { const char *s; client_t *client; @@ -329,7 +329,7 @@ PF_sprint (progs_t *pr) // void (...) centerprint */ static void -PF_centerprint (progs_t *pr) +PF_centerprint (progs_t *pr, void *data) { const char *s; client_t *cl; @@ -351,7 +351,7 @@ PF_centerprint (progs_t *pr) // void (vector o, vector d, float color, float count) particle static void -PF_particle (progs_t *pr) +PF_particle (progs_t *pr, void *data) { float *org, *dir; float color; @@ -369,7 +369,7 @@ PF_particle (progs_t *pr) // void (vector pos, string samp, float vol, float atten) ambientsound */ static void -PF_ambientsound (progs_t *pr) +PF_ambientsound (progs_t *pr, void *data) { const char **check; const char *samp; @@ -425,7 +425,7 @@ PF_ambientsound (progs_t *pr) // void (entity e, float chan, string samp) sound */ static void -PF_sound (progs_t *pr) +PF_sound (progs_t *pr, void *data) { const char *sample; edict_t *entity; @@ -459,7 +459,7 @@ PF_sound (progs_t *pr) // float (vector v1, vector v2, float tryents) traceline */ static void -PF_traceline (progs_t *pr) +PF_traceline (progs_t *pr, void *data) { float *v1, *v2; edict_t *ent; @@ -497,7 +497,7 @@ PF_traceline (progs_t *pr) redundant. */ static void -PF_tracebox (progs_t *pr) +PF_tracebox (progs_t *pr, void *data) { edict_t *ent; float *start, *end, *mins, *maxs; @@ -536,7 +536,7 @@ PF_tracebox (progs_t *pr) scalar checkpos (entity, vector) */ static void __attribute__ ((used)) -PF_checkpos (progs_t *pr) +PF_checkpos (progs_t *pr, void *data) { } @@ -610,7 +610,7 @@ int c_invis, c_notvis; // entity () clientlist */ static void -PF_checkclient (progs_t *pr) +PF_checkclient (progs_t *pr, void *data) { edict_t *ent, *self; int l; @@ -652,7 +652,7 @@ PF_checkclient (progs_t *pr) // void (entity client, string s) stuffcmd */ static void -PF_stuffcmd (progs_t *pr) +PF_stuffcmd (progs_t *pr, void *data) { const char *str; client_t *old; @@ -678,7 +678,7 @@ PF_stuffcmd (progs_t *pr) // void (string s) localcmd */ static void -PF_localcmd (progs_t *pr) +PF_localcmd (progs_t *pr, void *data) { const char *str; @@ -695,7 +695,7 @@ PF_localcmd (progs_t *pr) // entity (vector org, float rad) findradius */ static void -PF_findradius (progs_t *pr) +PF_findradius (progs_t *pr, void *data) { edict_t *ent, *chain; float rsqr; @@ -731,7 +731,7 @@ PF_findradius (progs_t *pr) // entity () spawn static void -PF_spawn (progs_t *pr) +PF_spawn (progs_t *pr, void *data) { edict_t *ed; @@ -741,7 +741,7 @@ PF_spawn (progs_t *pr) // void (entity e) remove static void -PF_remove (progs_t *pr) +PF_remove (progs_t *pr, void *data) { edict_t *ed; @@ -793,7 +793,7 @@ do_precache (progs_t *pr, const char **cache, int max, const char *name, // string (string s) precache_file // string (string s) precache_file2 static void -PF_precache_file (progs_t *pr) +PF_precache_file (progs_t *pr, void *data) { // precache_file is used only to copy files with qcc, it does nothing R_INT (pr) = P_INT (pr, 0); @@ -803,7 +803,7 @@ PF_precache_file (progs_t *pr) // void (string s) precache_sound // string (string s) precache_sound2 static void -PF_precache_sound (progs_t *pr) +PF_precache_sound (progs_t *pr, void *data) { do_precache (pr, sv.sound_precache, MAX_SOUNDS, P_GSTRING (pr, 0), "precache_sound"); @@ -814,7 +814,7 @@ PF_precache_sound (progs_t *pr) // void (string s) precache_model // string (string s) precache_model2 static void -PF_precache_model (progs_t *pr) +PF_precache_model (progs_t *pr, void *data) { int ind; const char *mod = P_GSTRING (pr, 0); @@ -832,7 +832,7 @@ PF_precache_model (progs_t *pr) // float (float yaw, float dist) walkmove */ static void -PF_walkmove (progs_t *pr) +PF_walkmove (progs_t *pr, void *data) { edict_t *ent; float yaw, dist; @@ -870,7 +870,7 @@ PF_walkmove (progs_t *pr) // float () droptofloor */ static void -PF_droptofloor (progs_t *pr) +PF_droptofloor (progs_t *pr, void *data) { edict_t *ent; trace_t trace; @@ -902,7 +902,7 @@ PF_droptofloor (progs_t *pr) // void (float style, string value) lightstyle */ static void -PF_lightstyle (progs_t *pr) +PF_lightstyle (progs_t *pr, void *data) { const char *val; client_t *cl; @@ -929,7 +929,7 @@ PF_lightstyle (progs_t *pr) // float (entity e) checkbottom static void -PF_checkbottom (progs_t *pr) +PF_checkbottom (progs_t *pr, void *data) { edict_t *ent; @@ -940,7 +940,7 @@ PF_checkbottom (progs_t *pr) // float (vector v) pointcontents static void -PF_pointcontents (progs_t *pr) +PF_pointcontents (progs_t *pr, void *data) { float *v; @@ -959,7 +959,7 @@ cvar_t *sv_aim; // vector (entity e, float speed) aim */ static void -PF_aim (progs_t *pr) +PF_aim (progs_t *pr, void *data) { edict_t *ent, *check, *bestent; float dist, bestdist, speed; @@ -1038,7 +1038,7 @@ PF_aim (progs_t *pr) // void () ChangeYaw */ void -PF_changeyaw (progs_t *pr) +PF_changeyaw (progs_t *pr, void *data) { edict_t *ent; float ideal, current, move, speed; @@ -1111,7 +1111,7 @@ WriteDest (progs_t *pr) // void (float to, ...) WriteBytes static void -PF_WriteBytes (progs_t *pr) +PF_WriteBytes (progs_t *pr, void *data) { int i, p; int argc = pr->pr_argc - 1; @@ -1138,49 +1138,49 @@ PF_WriteBytes (progs_t *pr) // void (float to, float f) WriteByte static void -PF_WriteByte (progs_t *pr) +PF_WriteByte (progs_t *pr, void *data) { MSG_WriteByte (WriteDest (pr), P_FLOAT (pr, 1)); } // void (float to, float f) WriteChar static void -PF_WriteChar (progs_t *pr) +PF_WriteChar (progs_t *pr, void *data) { MSG_WriteByte (WriteDest (pr), P_FLOAT (pr, 1)); } // void (float to, float f) WriteShort static void -PF_WriteShort (progs_t *pr) +PF_WriteShort (progs_t *pr, void *data) { MSG_WriteShort (WriteDest (pr), P_FLOAT (pr, 1)); } // void (float to, float f) WriteLong static void -PF_WriteLong (progs_t *pr) +PF_WriteLong (progs_t *pr, void *data) { MSG_WriteLong (WriteDest (pr), P_FLOAT (pr, 1)); } // void (float to, float f) WriteAngle static void -PF_WriteAngle (progs_t *pr) +PF_WriteAngle (progs_t *pr, void *data) { MSG_WriteAngle (WriteDest (pr), P_FLOAT (pr, 1)); } // void (float to, float f) WriteCoord static void -PF_WriteCoord (progs_t *pr) +PF_WriteCoord (progs_t *pr, void *data) { MSG_WriteCoord (WriteDest (pr), P_FLOAT (pr, 1)); } // void (float to, vector v) WriteAngleV static void -PF_WriteAngleV (progs_t *pr) +PF_WriteAngleV (progs_t *pr, void *data) { float *ang = P_VECTOR (pr, 1); @@ -1189,7 +1189,7 @@ PF_WriteAngleV (progs_t *pr) // void (float to, vector v) WriteCoordV static void -PF_WriteCoordV (progs_t *pr) +PF_WriteCoordV (progs_t *pr, void *data) { float *coord = P_VECTOR (pr, 1); @@ -1198,21 +1198,21 @@ PF_WriteCoordV (progs_t *pr) // void (float to, string s) WriteString static void -PF_WriteString (progs_t *pr) +PF_WriteString (progs_t *pr, void *data) { MSG_WriteString (WriteDest (pr), P_GSTRING (pr, 1)); } // void (float to, entity s) WriteEntity static void -PF_WriteEntity (progs_t *pr) +PF_WriteEntity (progs_t *pr, void *data) { MSG_WriteShort (WriteDest (pr), P_EDICTNUM (pr, 1)); } // void (entity e) makestatic static void -PF_makestatic (progs_t *pr) +PF_makestatic (progs_t *pr, void *data) { const char *model; edict_t *ent; @@ -1270,7 +1270,7 @@ nosend: // void (entity e) setspawnparms static void -PF_setspawnparms (progs_t *pr) +PF_setspawnparms (progs_t *pr, void *data) { client_t *client; edict_t *ent; @@ -1290,7 +1290,7 @@ PF_setspawnparms (progs_t *pr) // void (string s) changelevel static void -PF_changelevel (progs_t *pr) +PF_changelevel (progs_t *pr, void *data) { const char *s; @@ -1305,7 +1305,7 @@ PF_changelevel (progs_t *pr) // entity (entity ent) testentitypos static void -PF_testentitypos (progs_t *pr) +PF_testentitypos (progs_t *pr, void *data) { edict_t *ent = P_EDICT (pr, 0); ent = SV_TestEntityPosition (ent); @@ -1317,7 +1317,7 @@ clip_hull_t *pf_hull_list[MAX_PF_HULLS]; // integer (entity ent, vector point) hullpointcontents static void -PF_hullpointcontents (progs_t *pr) +PF_hullpointcontents (progs_t *pr, void *data) { edict_t *edict = P_EDICT (pr, 0); float *mins = P_VECTOR (pr, 1); @@ -1333,7 +1333,7 @@ PF_hullpointcontents (progs_t *pr) // vector (integer hull, integer max) getboxbounds static void -PF_getboxbounds (progs_t *pr) +PF_getboxbounds (progs_t *pr, void *data) { clip_hull_t *ch; int h = P_INT (pr, 0) - 1; @@ -1350,7 +1350,7 @@ PF_getboxbounds (progs_t *pr) // integer () getboxhull static void -PF_getboxhull (progs_t *pr) +PF_getboxhull (progs_t *pr, void *data) { clip_hull_t *ch = 0; int i; @@ -1375,7 +1375,7 @@ PF_getboxhull (progs_t *pr) // void (integer hull) freeboxhull static void -PF_freeboxhull (progs_t *pr) +PF_freeboxhull (progs_t *pr, void *data) { int h = P_INT (pr, 0) - 1; clip_hull_t *ch; @@ -1405,7 +1405,7 @@ calc_dist (vec3_t p, vec3_t n, vec3_t *offsets) // void (integer hull, vector right, vector forward, vector up, vector mins, vector maxs) rotate_bbox static void -PF_rotate_bbox (progs_t *pr) +PF_rotate_bbox (progs_t *pr, void *data) { clip_hull_t *ch; float l; @@ -1484,7 +1484,7 @@ PF_rotate_bbox (progs_t *pr) // float () checkextension static void -PF_checkextension (progs_t *pr) +PF_checkextension (progs_t *pr, void *data) { R_FLOAT (pr) = 0; // FIXME: make this function actually useful } diff --git a/qw/include/server.h b/qw/include/server.h index bd7fb8062..be60ccf95 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -510,7 +510,7 @@ qboolean SV_movestep (struct edict_s *ent, const vec3_t move, void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg); struct progs_s; -void SV_MoveToGoal (struct progs_s *pr); +void SV_MoveToGoal (struct progs_s *pr, void *data); void SV_SaveSpawnparms (void); diff --git a/qw/include/sv_pr_cmds.h b/qw/include/sv_pr_cmds.h index 0ef2d00ac..6cfb999d7 100644 --- a/qw/include/sv_pr_cmds.h +++ b/qw/include/sv_pr_cmds.h @@ -28,6 +28,6 @@ #ifndef __sv_pr_cmds_h #define __sv_pr_cmds_h -void PF_changeyaw (progs_t *pr); +void PF_changeyaw (progs_t *pr, void *data); #endif // __sv_pr_cmds_h diff --git a/qw/source/sv_move.c b/qw/source/sv_move.c index 75b4f8e01..c500e30ed 100644 --- a/qw/source/sv_move.c +++ b/qw/source/sv_move.c @@ -228,7 +228,7 @@ SV_StepDirection (edict_t *ent, float yaw, float dist) vec3_t move, oldorigin; SVfloat (ent, ideal_yaw) = yaw; - PF_changeyaw (&sv_pr_state); + PF_changeyaw (&sv_pr_state, 0); yaw = yaw * M_PI * 2 / 360; move[0] = cos (yaw) * dist; @@ -345,7 +345,7 @@ SV_CloseEnough (edict_t *ent, edict_t *goal, float dist) } void -SV_MoveToGoal (progs_t *pr) +SV_MoveToGoal (progs_t *pr, void *data) { edict_t *ent, *goal; float dist; diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index f2e9b8a37..9eb50bca6 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -68,7 +68,7 @@ // void (string e) error */ static void -PF_error (progs_t *pr) +PF_error (progs_t *pr, void *data) { const char *s; edict_t *ed; @@ -92,7 +92,7 @@ PF_error (progs_t *pr) // void (string e) objerror */ static void -PF_objerror (progs_t *pr) +PF_objerror (progs_t *pr, void *data) { const char *s; edict_t *ed; @@ -114,7 +114,7 @@ PF_objerror (progs_t *pr) void (vector angles) makevectors */ static void -PF_makevectors (progs_t *pr) +PF_makevectors (progs_t *pr, void *data) { AngleVectors (P_VECTOR (pr, 0), *sv_globals.v_forward, *sv_globals.v_right, *sv_globals.v_up); @@ -133,7 +133,7 @@ PF_makevectors (progs_t *pr) // void (entity e, vector o) setorigin */ static void -PF_setorigin (progs_t *pr) +PF_setorigin (progs_t *pr, void *data) { edict_t *e; float *org; @@ -153,7 +153,7 @@ PF_setorigin (progs_t *pr) // void (entity e, vector min, vector max) setsize */ static void -PF_setsize (progs_t *pr) +PF_setsize (progs_t *pr, void *data) { edict_t *e; float *min, *max; @@ -175,7 +175,7 @@ PF_setsize (progs_t *pr) Also sets size, mins, and maxs for inline bmodels */ static void -PF_setmodel (progs_t *pr) +PF_setmodel (progs_t *pr, void *data) { edict_t *e; const char *m, **check; @@ -215,7 +215,7 @@ PF_setmodel (progs_t *pr) // void (string s) bprint */ static void -PF_bprint (progs_t *pr) +PF_bprint (progs_t *pr, void *data) { const char *s; int level; @@ -235,7 +235,7 @@ PF_bprint (progs_t *pr) // void (entity client, string s) sprint */ static void -PF_sprint (progs_t *pr) +PF_sprint (progs_t *pr, void *data) { const char *s; client_t *client; @@ -268,7 +268,7 @@ PF_sprint (progs_t *pr) // void (...) centerprint */ static void -PF_centerprint (progs_t *pr) +PF_centerprint (progs_t *pr, void *data) { const char *s; client_t *cl; @@ -304,7 +304,7 @@ PF_centerprint (progs_t *pr) // void (vector pos, string samp, float vol, float atten) ambientsound */ static void -PF_ambientsound (progs_t *pr) +PF_ambientsound (progs_t *pr, void *data) { const char **check; const char *samp; @@ -350,7 +350,7 @@ PF_ambientsound (progs_t *pr) // void (entity e, float chan, string samp) sound */ static void -PF_sound (progs_t *pr) +PF_sound (progs_t *pr, void *data) { const char *sample; edict_t *entity; @@ -377,7 +377,7 @@ PF_sound (progs_t *pr) // float (vector v1, vector v2, float tryents) traceline */ static void -PF_traceline (progs_t *pr) +PF_traceline (progs_t *pr, void *data) { float *v1, *v2; edict_t *ent; @@ -418,7 +418,7 @@ PF_traceline (progs_t *pr) redundant. */ static void -PF_tracebox (progs_t *pr) +PF_tracebox (progs_t *pr, void *data) { edict_t *ent; float *start, *end, *mins, *maxs; @@ -457,7 +457,7 @@ PF_tracebox (progs_t *pr) scalar checkpos (entity, vector) */ static void __attribute__ ((used)) -PF_checkpos (progs_t *pr) +PF_checkpos (progs_t *pr, void *data) { } @@ -531,7 +531,7 @@ int c_invis, c_notvis; // entity () clientlist */ static void -PF_checkclient (progs_t *pr) +PF_checkclient (progs_t *pr, void *data) { edict_t *ent, *self; int l; @@ -573,7 +573,7 @@ PF_checkclient (progs_t *pr) // void (entity client, string s) stuffcmd */ static void -PF_stuffcmd (progs_t *pr) +PF_stuffcmd (progs_t *pr, void *data) { const char *str; char *buf, *p; @@ -631,7 +631,7 @@ PF_stuffcmd (progs_t *pr) // void (string s) localcmd */ static void -PF_localcmd (progs_t *pr) +PF_localcmd (progs_t *pr, void *data) { const char *str; @@ -648,7 +648,7 @@ PF_localcmd (progs_t *pr) // entity (vector org, float rad) findradius */ static void -PF_findradius (progs_t *pr) +PF_findradius (progs_t *pr, void *data) { edict_t *ent, *chain; float rsqr; @@ -684,7 +684,7 @@ PF_findradius (progs_t *pr) // entity () spawn static void -PF_spawn (progs_t *pr) +PF_spawn (progs_t *pr, void *data) { edict_t *ed; @@ -696,7 +696,7 @@ cvar_t *pr_double_remove; // void (entity e) remove static void -PF_remove (progs_t *pr) +PF_remove (progs_t *pr, void *data) { edict_t *ed; @@ -762,7 +762,7 @@ do_precache (progs_t *pr, const char **cache, int max, const char *name, // string (string s) precache_file // string (string s) precache_file2 static void -PF_precache_file (progs_t *pr) +PF_precache_file (progs_t *pr, void *data) { // precache_file is used only to copy files with qcc, it does nothing R_INT (pr) = P_INT (pr, 0); @@ -772,7 +772,7 @@ PF_precache_file (progs_t *pr) // void (string s) precache_sound // string (string s) precache_sound2 static void -PF_precache_sound (progs_t *pr) +PF_precache_sound (progs_t *pr, void *data) { do_precache (pr, sv.sound_precache, MAX_SOUNDS, P_GSTRING (pr, 0), "precache_sound"); @@ -783,7 +783,7 @@ PF_precache_sound (progs_t *pr) // void (string s) precache_model // string (string s) precache_model2 static void -PF_precache_model (progs_t *pr) +PF_precache_model (progs_t *pr, void *data) { do_precache (pr, sv.model_precache, MAX_MODELS, P_GSTRING (pr, 0), "precache_model"); @@ -798,7 +798,7 @@ PF_precache_model (progs_t *pr) // float (float yaw, float dist) walkmove */ static void -PF_walkmove (progs_t *pr) +PF_walkmove (progs_t *pr, void *data) { edict_t *ent; float yaw, dist; @@ -836,7 +836,7 @@ PF_walkmove (progs_t *pr) // float () droptofloor */ static void -PF_droptofloor (progs_t *pr) +PF_droptofloor (progs_t *pr, void *data) { edict_t *ent; trace_t trace; @@ -868,7 +868,7 @@ PF_droptofloor (progs_t *pr) // void (float style, string value) lightstyle */ static void -PF_lightstyle (progs_t *pr) +PF_lightstyle (progs_t *pr, void *data) { const char *val; client_t *cl; @@ -902,7 +902,7 @@ PF_lightstyle (progs_t *pr) // float (entity e) checkbottom static void -PF_checkbottom (progs_t *pr) +PF_checkbottom (progs_t *pr, void *data) { edict_t *ent; @@ -913,7 +913,7 @@ PF_checkbottom (progs_t *pr) // float (vector v) pointcontents static void -PF_pointcontents (progs_t *pr) +PF_pointcontents (progs_t *pr, void *data) { float *v; @@ -932,7 +932,7 @@ cvar_t *sv_aim; // vector (entity e, float speed) aim */ static void -PF_aim (progs_t *pr) +PF_aim (progs_t *pr, void *data) { const char *noaim; edict_t *ent, *check, *bestent; @@ -1027,7 +1027,7 @@ PF_aim (progs_t *pr) // void () ChangeYaw */ void -PF_changeyaw (progs_t *pr) +PF_changeyaw (progs_t *pr, void *data) { edict_t *ent; float ideal, current, move, speed; @@ -1114,7 +1114,7 @@ Write_GetClient (progs_t *pr) // void (float to, ...) WriteBytes static void -PF_WriteBytes (progs_t *pr) +PF_WriteBytes (progs_t *pr, void *data) { int i, p; byte buf[PR_MAX_PARAMS]; @@ -1158,7 +1158,7 @@ PF_WriteBytes (progs_t *pr) // void (float to, float f) WriteByte static void -PF_WriteByte (progs_t *pr) +PF_WriteByte (progs_t *pr, void *data) { if (P_FLOAT (pr, 0) == MSG_ONE) { client_t *cl = Write_GetClient (pr); @@ -1178,7 +1178,7 @@ PF_WriteByte (progs_t *pr) // void (float to, float f) WriteChar static void -PF_WriteChar (progs_t *pr) +PF_WriteChar (progs_t *pr, void *data) { if (P_FLOAT (pr, 0) == MSG_ONE) { client_t *cl = Write_GetClient (pr); @@ -1198,7 +1198,7 @@ PF_WriteChar (progs_t *pr) // void (float to, float f) WriteShort static void -PF_WriteShort (progs_t *pr) +PF_WriteShort (progs_t *pr, void *data) { if (P_FLOAT (pr, 0) == MSG_ONE) { client_t *cl = Write_GetClient (pr); @@ -1218,7 +1218,7 @@ PF_WriteShort (progs_t *pr) // void (float to, float f) WriteLong static void -PF_WriteLong (progs_t *pr) +PF_WriteLong (progs_t *pr, void *data) { if (P_FLOAT (pr, 0) == MSG_ONE) { client_t *cl = Write_GetClient (pr); @@ -1238,7 +1238,7 @@ PF_WriteLong (progs_t *pr) // void (float to, float f) WriteAngle static void -PF_WriteAngle (progs_t *pr) +PF_WriteAngle (progs_t *pr, void *data) { if (P_FLOAT (pr, 0) == MSG_ONE) { client_t *cl = Write_GetClient (pr); @@ -1258,7 +1258,7 @@ PF_WriteAngle (progs_t *pr) // void (float to, float f) WriteCoord static void -PF_WriteCoord (progs_t *pr) +PF_WriteCoord (progs_t *pr, void *data) { if (P_FLOAT (pr, 0) == MSG_ONE) { client_t *cl = Write_GetClient (pr); @@ -1278,7 +1278,7 @@ PF_WriteCoord (progs_t *pr) // void (float to, vector v) WriteAngleV static void -PF_WriteAngleV (progs_t *pr) +PF_WriteAngleV (progs_t *pr, void *data) { float *ang = P_VECTOR (pr, 1); @@ -1300,7 +1300,7 @@ PF_WriteAngleV (progs_t *pr) // void (float to, vector v) WriteCoordV static void -PF_WriteCoordV (progs_t *pr) +PF_WriteCoordV (progs_t *pr, void *data) { float *coord = P_VECTOR (pr, 1); @@ -1322,7 +1322,7 @@ PF_WriteCoordV (progs_t *pr) // void (float to, string s) WriteString static void -PF_WriteString (progs_t *pr) +PF_WriteString (progs_t *pr, void *data) { const char *str = P_GSTRING (pr, 1); @@ -1344,7 +1344,7 @@ PF_WriteString (progs_t *pr) // void (float to, entity s) WriteEntity static void -PF_WriteEntity (progs_t *pr) +PF_WriteEntity (progs_t *pr, void *data) { int ent = P_EDICTNUM (pr, 1); @@ -1366,7 +1366,7 @@ PF_WriteEntity (progs_t *pr) // void (entity e) makestatic static void -PF_makestatic (progs_t *pr) +PF_makestatic (progs_t *pr, void *data) { const char *model; edict_t *ent; @@ -1394,7 +1394,7 @@ PF_makestatic (progs_t *pr) // void (entity e) setspawnparms static void -PF_setspawnparms (progs_t *pr) +PF_setspawnparms (progs_t *pr, void *data) { client_t *client; edict_t *ent; @@ -1417,7 +1417,7 @@ PF_setspawnparms (progs_t *pr) // void (string s) changelevel static void -PF_changelevel (progs_t *pr) +PF_changelevel (progs_t *pr, void *data) { const char *s; static int last_spawncount; @@ -1438,7 +1438,7 @@ PF_changelevel (progs_t *pr) // void (entity killer, entity killee) logfrag */ static void -PF_logfrag (progs_t *pr) +PF_logfrag (progs_t *pr, void *data) { const char *s; edict_t *ent1, *ent2; @@ -1500,7 +1500,7 @@ PF_logfrag (progs_t *pr) // string (entity e, string key) infokey */ static void -PF_infokey (progs_t *pr) +PF_infokey (progs_t *pr, void *data) { const char *key, *value; edict_t *e; @@ -1544,7 +1544,7 @@ PF_infokey (progs_t *pr) // void (vector where, float set) multicast */ static void -PF_multicast (progs_t *pr) +PF_multicast (progs_t *pr, void *data) { float *o; int to; @@ -1562,7 +1562,7 @@ PF_multicast (progs_t *pr) // float (string path, string mode) cfopen */ static void -PF_cfopen (progs_t *pr) +PF_cfopen (progs_t *pr, void *data) { R_FLOAT (pr) = CF_Open (P_GSTRING (pr, 0), P_GSTRING (pr, 1)); } @@ -1574,7 +1574,7 @@ PF_cfopen (progs_t *pr) // void (float desc) cfclose */ static void -PF_cfclose (progs_t *pr) +PF_cfclose (progs_t *pr, void *data) { CF_Close ((int) P_FLOAT (pr, 0)); } @@ -1586,7 +1586,7 @@ PF_cfclose (progs_t *pr) // string (float desc) cfread */ static void -PF_cfread (progs_t *pr) +PF_cfread (progs_t *pr, void *data) { RETURN_STRING (pr, CF_Read ((int) P_FLOAT (pr, 0))); } @@ -1598,7 +1598,7 @@ PF_cfread (progs_t *pr) // float (float desc, string buf) cfwrite */ static void -PF_cfwrite (progs_t *pr) +PF_cfwrite (progs_t *pr, void *data) { R_FLOAT (pr) = CF_Write ((int) P_FLOAT (pr, 0), P_GSTRING (pr, 1)); } @@ -1610,7 +1610,7 @@ PF_cfwrite (progs_t *pr) // float (float desc) cfeof */ static void -PF_cfeof (progs_t *pr) +PF_cfeof (progs_t *pr, void *data) { R_FLOAT (pr) = CF_EOF ((int) P_FLOAT (pr, 0)); } @@ -1622,14 +1622,14 @@ PF_cfeof (progs_t *pr) // float () cfquota */ static void -PF_cfquota (progs_t *pr) +PF_cfquota (progs_t *pr, void *data) { R_FLOAT (pr) = CF_Quota (); } // void (entity ent, string key, string value) setinfokey static void -PF_setinfokey (progs_t *pr) +PF_setinfokey (progs_t *pr, void *data) { edict_t *edict = P_EDICT (pr, 0); int e1 = NUM_FOR_EDICT (pr, edict); @@ -1645,7 +1645,7 @@ PF_setinfokey (progs_t *pr) // entity (entity ent) testentitypos static void -PF_testentitypos (progs_t *pr) +PF_testentitypos (progs_t *pr, void *data) { edict_t *ent = P_EDICT (pr, 0); ent = SV_TestEntityPosition (ent); @@ -1657,7 +1657,7 @@ clip_hull_t *pf_hull_list[MAX_PF_HULLS]; // int (entity ent, vector point) hullpointcontents static void -PF_hullpointcontents (progs_t *pr) +PF_hullpointcontents (progs_t *pr, void *data) { edict_t *edict = P_EDICT (pr, 0); float *mins = P_VECTOR (pr, 1); @@ -1673,7 +1673,7 @@ PF_hullpointcontents (progs_t *pr) // vector (int hull, int max) getboxbounds static void -PF_getboxbounds (progs_t *pr) +PF_getboxbounds (progs_t *pr, void *data) { clip_hull_t *ch; int h = P_INT (pr, 0) - 1; @@ -1690,7 +1690,7 @@ PF_getboxbounds (progs_t *pr) // int () getboxhull static void -PF_getboxhull (progs_t *pr) +PF_getboxhull (progs_t *pr, void *data) { clip_hull_t *ch = 0; int i; @@ -1715,7 +1715,7 @@ PF_getboxhull (progs_t *pr) // void (int hull) freeboxhull static void -PF_freeboxhull (progs_t *pr) +PF_freeboxhull (progs_t *pr, void *data) { int h = P_INT (pr, 0) - 1; clip_hull_t *ch; @@ -1745,7 +1745,7 @@ calc_dist (vec3_t p, vec3_t n, vec3_t *offsets) // void (int hull, vector right, vector forward, vector up, vector mins, vector maxs) rotate_bbox static void -PF_rotate_bbox (progs_t *pr) +PF_rotate_bbox (progs_t *pr, void *data) { clip_hull_t *ch; float l; @@ -1824,13 +1824,13 @@ PF_rotate_bbox (progs_t *pr) // float () checkextension static void -PF_checkextension (progs_t *pr) +PF_checkextension (progs_t *pr, void *data) { R_FLOAT (pr) = 0; // FIXME: make this function actually useful :P } static void -PF_sv_cvar (progs_t *pr) +PF_sv_cvar (progs_t *pr, void *data) { const char *str; @@ -1848,7 +1848,7 @@ PF_sv_cvar (progs_t *pr) // returns -1 if the entity is not a client (either not in the client range // or the entity is not in use by a client) static void -PF_SV_ClientNumber (progs_t *pr) +PF_SV_ClientNumber (progs_t *pr, void *data) { int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; @@ -1862,7 +1862,7 @@ PF_SV_ClientNumber (progs_t *pr) // entity () SV_AllocClient static void -PF_SV_AllocClient (progs_t *pr) +PF_SV_AllocClient (progs_t *pr, void *data) { client_t *cl = SV_AllocClient (0, 1); @@ -1880,7 +1880,7 @@ PF_SV_AllocClient (progs_t *pr) // void (entity cl) SV_FreeClient static void -PF_SV_FreeClient (progs_t *pr) +PF_SV_FreeClient (progs_t *pr, void *data) { int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; @@ -1901,7 +1901,7 @@ PF_SV_FreeClient (progs_t *pr) // void (entity cl, string userinfo) SV_SetUserinfo static void -PF_SV_SetUserinfo (progs_t *pr) +PF_SV_SetUserinfo (progs_t *pr, void *data) { int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; @@ -1917,7 +1917,7 @@ PF_SV_SetUserinfo (progs_t *pr) // void (entity cl, int ping) SV_SetPing static void -PF_SV_SetPing (progs_t *pr) +PF_SV_SetPing (progs_t *pr, void *data) { int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; @@ -1929,7 +1929,7 @@ PF_SV_SetPing (progs_t *pr) // void (entity cl, float secs, vector angles, vector move, int buttons, int impulse) SV_UserCmd static void -PF_SV_UserCmd (progs_t *pr) +PF_SV_UserCmd (progs_t *pr, void *data) { usercmd_t ucmd; int entnum = P_EDICTNUM (pr, 0); @@ -1955,7 +1955,7 @@ PF_SV_UserCmd (progs_t *pr) // void (entity cl) SV_Spawn static void -PF_SV_Spawn (progs_t *pr) +PF_SV_Spawn (progs_t *pr, void *data) { int entnum = P_EDICTNUM (pr, 0); client_t *cl = svs.clients + entnum - 1; diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index 32e82e7b9..f75cddf98 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -54,7 +54,7 @@ static struct { float(entity client) getuid */ static void -PF_getuid (progs_t *pr) +PF_getuid (progs_t *pr, void *data) { edict_t *client_ent; int e_num; @@ -76,7 +76,7 @@ PF_getuid (progs_t *pr) string(string st1, string st2) strcat */ static void -PF_strcat (progs_t *pr) +PF_strcat (progs_t *pr, void *data) { const char *st1 = P_GSTRING (pr, 0); const char *st2 = P_GSTRING (pr, 1); @@ -90,7 +90,7 @@ PF_strcat (progs_t *pr) string(string st, float len) padstr */ static void -PF_padstr (progs_t *pr) +PF_padstr (progs_t *pr, void *data) { const char *st; size_t i, padlen, givenlen; @@ -133,7 +133,7 @@ PF_padstr (progs_t *pr) // non-original charsets) static void -PF_colstr (progs_t *pr) +PF_colstr (progs_t *pr, void *data) { const char *srcstr; unsigned char *result; @@ -226,7 +226,7 @@ PF_colstr (progs_t *pr) float(string st1, string st2) strcasecmp */ static void -PF_strcasecmp (progs_t *pr) +PF_strcasecmp (progs_t *pr, void *data) { const char *st1; const char *st2; @@ -244,7 +244,7 @@ PF_strcasecmp (progs_t *pr) */ static void -PF_strlen (progs_t *pr) +PF_strlen (progs_t *pr, void *data) { const char *st; @@ -313,7 +313,7 @@ KK_Match_Str2 (const char *substr) entity(string st) getclient */ static void -PF_getclient (progs_t *pr) +PF_getclient (progs_t *pr, void *data) { edict_t *ent; const char *st; @@ -353,7 +353,7 @@ float(entity client) mutedtime */ static void -PF_mutedtime (progs_t *pr) +PF_mutedtime (progs_t *pr, void *data) { edict_t *client_ent; int e_num; @@ -382,7 +382,7 @@ float(string st) validatefile */ static void -PF_validatefile (progs_t *pr) +PF_validatefile (progs_t *pr, void *data) { float retval; QFile *f; @@ -410,7 +410,7 @@ PF_validatefile (progs_t *pr) extern int fp_messages, fp_persecond, fp_secondsdead; static void -PF_putsaytime (progs_t *pr) +PF_putsaytime (progs_t *pr, void *data) { edict_t *client_ent; int e_num, tmp; @@ -444,7 +444,7 @@ PF_putsaytime (progs_t *pr) */ static void -PF_makestr (progs_t *pr) +PF_makestr (progs_t *pr, void *data) { pr_string_t res = PR_NewMutableString (pr); dstring_t *dst = PR_GetMutableString (pr, res); @@ -461,7 +461,7 @@ PF_makestr (progs_t *pr) */ static void -PF_delstr (progs_t *pr) +PF_delstr (progs_t *pr, void *data) { PR_FreeString (pr, P_STRING (pr, 0)); } @@ -548,7 +548,7 @@ GetLinearWave (float inputnum) #define GWAVE_USESHAPE 8 static void -PF_getwave (progs_t *pr) +PF_getwave (progs_t *pr, void *data) { float retval, inputnum, minnum, maxnum, balance, offset, shape; float temp; @@ -625,7 +625,7 @@ PF_getwave (progs_t *pr) */ static void -PF_clientsound (progs_t *pr) +PF_clientsound (progs_t *pr, void *data) { const char *sample; int channel; @@ -700,7 +700,7 @@ PF_clientsound (progs_t *pr) */ static void -PF_touchworld (progs_t *pr) +PF_touchworld (progs_t *pr, void *data) { edict_t *self; pr_int_t oself; @@ -729,7 +729,7 @@ PF_touchworld (progs_t *pr) #define TL_EVERYTHING 4 // scan for anything static void -PF_traceline (progs_t *pr) +PF_traceline (progs_t *pr, void *data) { float *v1, *v2; edict_t *ent; diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index eb7322800..329cea360 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -64,7 +64,7 @@ typedef struct { static qwe_funcs_t qwe_funcs; static void -PF_executecmd (progs_t *pr) +PF_executecmd (progs_t *pr, void *data) { int old_other, old_self; // mod_consolecmd will be executed, so // we need to store these @@ -87,7 +87,7 @@ PF_executecmd (progs_t *pr) */ static void -PF_tokanize (progs_t *pr) +PF_tokanize (progs_t *pr, void *data) { const char *str; @@ -105,7 +105,7 @@ PF_tokanize (progs_t *pr) */ static void -PF_argc (progs_t *pr) +PF_argc (progs_t *pr, void *data) { R_FLOAT (pr) = (float) Cmd_Argc (); } @@ -119,7 +119,7 @@ PF_argc (progs_t *pr) */ static void -PF_argv (progs_t *pr) +PF_argv (progs_t *pr, void *data) { int num; @@ -140,7 +140,7 @@ PF_argv (progs_t *pr) */ static void -PF_teamfield (progs_t *pr) +PF_teamfield (progs_t *pr, void *data) { sv_fields.team_str = P_INT (pr, 0); } @@ -152,7 +152,7 @@ PF_teamfield (progs_t *pr) */ static void -PF_substr (progs_t *pr) +PF_substr (progs_t *pr, void *data) { const char *s; char *tmp; @@ -188,7 +188,7 @@ PF_substr (progs_t *pr) */ static void -PF_strcat (progs_t *pr) +PF_strcat (progs_t *pr, void *data) { RETURN_STRING (pr, PF_VarString (pr, 0, pr->pr_argc)); } @@ -200,7 +200,7 @@ PF_strcat (progs_t *pr) */ static void -PF_strlen (progs_t *pr) +PF_strlen (progs_t *pr, void *data) { R_FLOAT (pr) = (float) strlen (P_GSTRING (pr, 0)); } @@ -212,7 +212,7 @@ PF_strlen (progs_t *pr) */ static void -PF_str2byte (progs_t *pr) +PF_str2byte (progs_t *pr, void *data) { R_FLOAT (pr) = (float) *P_GSTRING (pr, 0); } @@ -224,7 +224,7 @@ PF_str2byte (progs_t *pr) */ static void -PF_str2short (progs_t *pr) +PF_str2short (progs_t *pr, void *data) { const byte *str = (byte *) P_GSTRING (pr, 0); @@ -239,7 +239,7 @@ PF_str2short (progs_t *pr) The new string will be at least as big as size, if given. */ static void -PF_newstr (progs_t *pr) +PF_newstr (progs_t *pr, void *data) { const char *s; dstring_t *dstr; @@ -269,7 +269,7 @@ PF_newstr (progs_t *pr) */ static void -PF_freestr (progs_t *pr) +PF_freestr (progs_t *pr, void *data) { PR_FreeString (pr, P_STRING (pr, 0)); } @@ -281,7 +281,7 @@ PF_freestr (progs_t *pr) */ static void -PF_readcmd (progs_t *pr) +PF_readcmd (progs_t *pr, void *data) { const char *s; redirect_t old; @@ -311,7 +311,7 @@ PF_readcmd (progs_t *pr) */ static void -PF_redirectcmd (progs_t *pr) +PF_redirectcmd (progs_t *pr, void *data) { const char *s; int entnum; @@ -334,7 +334,7 @@ PF_redirectcmd (progs_t *pr) } static void -PF_calltimeofday (progs_t *pr) +PF_calltimeofday (progs_t *pr, void *data) { date_t date; dfunction_t *f; @@ -368,7 +368,7 @@ PF_calltimeofday (progs_t *pr) */ static void -PF_forcedemoframe (progs_t *pr) +PF_forcedemoframe (progs_t *pr, void *data) { SVR_ForceFrame (); if (P_FLOAT (pr, 0) == 1) @@ -383,7 +383,7 @@ PF_forcedemoframe (progs_t *pr) */ static void -PF_strcpy (progs_t *pr) +PF_strcpy (progs_t *pr, void *data) { dstring_copystr (P_DSTRING (pr, 0), P_GSTRING (pr, 1)); } @@ -395,7 +395,7 @@ PF_strcpy (progs_t *pr) */ static void -PF_strncpy (progs_t *pr) +PF_strncpy (progs_t *pr, void *data) { dstring_t *dst = P_DSTRING (pr, 0); const char *src = P_GSTRING (pr, 1); @@ -414,7 +414,7 @@ PF_strncpy (progs_t *pr) */ static void -PF_strstr (progs_t *pr) +PF_strstr (progs_t *pr, void *data) { const char *str, *sub, *p; @@ -445,7 +445,7 @@ clean_text (char *text) */ static void -PF_log (progs_t *pr) +PF_log (progs_t *pr, void *data) { const char *name; char *text; @@ -473,7 +473,7 @@ PF_log (progs_t *pr) PF_conprint */ static void -PF_conprint (progs_t *pr) +PF_conprint (progs_t *pr, void *data) { Sys_Printf ("%s", PF_VarString (pr, 0, pr->pr_argc)); } diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 126c84ef8..0e10bec27 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -1422,7 +1422,7 @@ SV_RemoveUserCommand (void *cmd) } static void -PF_SV_AddUserCommand (progs_t *pr) +PF_SV_AddUserCommand (progs_t *pr, void *data) { const char *name = P_GSTRING (pr, 0); ucmd_t *cmd; diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 504939543..e82b37a5f 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -762,9 +762,9 @@ bi_shutdown (void *_pr) } static void -bi_syncprintf (progs_t *pr) +bi_syncprintf (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; int string_id = qwaq_pipe_acquire_string (&res->commands); dstring_t *print_buffer = qwaq_cmd_string (res, string_id); int command[] = { qwaq_cmd_syncprint, 0, string_id }; @@ -778,9 +778,9 @@ bi_syncprintf (progs_t *pr) } static void -bi_create_window (progs_t *pr) +bi_create_window (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; int xpos = P_INT (pr, 0); int ypos = P_INT (pr, 1); int xlen = P_INT (pr, 2); @@ -799,9 +799,9 @@ bi_create_window (progs_t *pr) } static void -bi_destroy_window (progs_t *pr) +bi_destroy_window (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); if (get_window (res, __FUNCTION__, window_id)) { @@ -812,9 +812,9 @@ bi_destroy_window (progs_t *pr) } static void -qwaq_getwrect (progs_t *pr, int window_id) +qwaq_getwrect (qwaq_resources_t *res, int window_id) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + progs_t *pr = res->pr; if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_getwrect, 0, window_id, }; @@ -832,15 +832,16 @@ qwaq_getwrect (progs_t *pr, int window_id) } } static void -bi_getwrect (progs_t *pr) +bi_getwrect (progs_t *pr, void *_res) { - qwaq_getwrect (pr, P_INT (pr, 0)); + qwaq_resources_t *res = _res; + qwaq_getwrect (res, P_INT (pr, 0)); } static void -bi_create_panel (progs_t *pr) +bi_create_panel (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); if (get_window (res, __FUNCTION__, window_id)) { @@ -856,9 +857,8 @@ bi_create_panel (progs_t *pr) } static void -panel_command (progs_t *pr, qwaq_commands cmd) +panel_command (progs_t *pr, qwaq_resources_t *res, qwaq_commands cmd) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int panel_id = P_INT (pr, 0); if (get_panel (res, __FUNCTION__, panel_id)) { @@ -869,39 +869,44 @@ panel_command (progs_t *pr, qwaq_commands cmd) } static void -bi_destroy_panel (progs_t *pr) +bi_destroy_panel (progs_t *pr, void *_res) { - panel_command (pr, qwaq_cmd_del_panel); + qwaq_resources_t *res = _res; + panel_command (pr, res, qwaq_cmd_del_panel); } static void -bi_hide_panel (progs_t *pr) +bi_hide_panel (progs_t *pr, void *_res) { - panel_command (pr, qwaq_cmd_hide_panel); + qwaq_resources_t *res = _res; + panel_command (pr, res, qwaq_cmd_hide_panel); } static void -bi_show_panel (progs_t *pr) +bi_show_panel (progs_t *pr, void *_res) { - panel_command (pr, qwaq_cmd_show_panel); + qwaq_resources_t *res = _res; + panel_command (pr, res, qwaq_cmd_show_panel); } static void -bi_top_panel (progs_t *pr) +bi_top_panel (progs_t *pr, void *_res) { - panel_command (pr, qwaq_cmd_top_panel); + qwaq_resources_t *res = _res; + panel_command (pr, res, qwaq_cmd_top_panel); } static void -bi_bottom_panel (progs_t *pr) +bi_bottom_panel (progs_t *pr, void *_res) { - panel_command (pr, qwaq_cmd_bottom_panel); + qwaq_resources_t *res = _res; + panel_command (pr, res, qwaq_cmd_bottom_panel); } static void -bi_move_panel (progs_t *pr) +bi_move_panel (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; int panel_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); @@ -914,9 +919,9 @@ bi_move_panel (progs_t *pr) } static void -bi_panel_window (progs_t *pr) +bi_panel_window (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; int panel_id = P_INT (pr, 0); if (get_panel (res, __FUNCTION__, panel_id)) { @@ -932,9 +937,9 @@ bi_panel_window (progs_t *pr) } static void -bi_replace_panel (progs_t *pr) +bi_replace_panel (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; int panel_id = P_INT (pr, 0); int window_id = P_INT (pr, 1); @@ -948,40 +953,40 @@ bi_replace_panel (progs_t *pr) } static void -qwaq_update_panels (progs_t *pr) +qwaq_update_panels (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; int command[] = { qwaq_cmd_update_panels, 0, }; command[1] = CMD_SIZE(command); qwaq_pipe_submit (&res->commands, command, command[1]); } static void -bi_update_panels (progs_t *pr) +bi_update_panels (progs_t *pr, void *_res) { - qwaq_update_panels (pr); + qwaq_resources_t *res = _res; + qwaq_update_panels (pr, res); } static void -qwaq_doupdate (progs_t *pr) +qwaq_doupdate (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; int command[] = { qwaq_cmd_doupdate, 0, }; command[1] = CMD_SIZE(command); qwaq_pipe_submit (&res->commands, command, command[1]); } static void -bi_doupdate (progs_t *pr) +bi_doupdate (progs_t *pr, void *_res) { - qwaq_doupdate (pr); + qwaq_resources_t *res = _res; + qwaq_doupdate (pr, res); } static void -qwaq_waddstr (progs_t *pr, int window_id, const char *str) +qwaq_waddstr (qwaq_resources_t *res, int window_id, const char *str) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int string_id = qwaq_pipe_acquire_string (&res->commands); dstring_t *print_buffer = qwaq_cmd_string (res, string_id); @@ -997,19 +1002,18 @@ qwaq_waddstr (progs_t *pr, int window_id, const char *str) } } static void -bi_waddstr (progs_t *pr) +bi_waddstr (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); const char *str = P_GSTRING (pr, 1); - qwaq_waddstr (pr, window_id, str); + qwaq_waddstr (res, window_id, str); } static void -qwaq_wresize (progs_t *pr, int window_id, int width, int height) +qwaq_wresize (qwaq_resources_t *res, int window_id, int width, int height) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wresize, 0, @@ -1021,39 +1025,38 @@ qwaq_wresize (progs_t *pr, int window_id, int width, int height) } } static void -bi_wresize (progs_t *pr) +bi_wresize (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int width = P_INT (pr, 1); int height = P_INT (pr, 2); - qwaq_wresize (pr, window_id, width, height); + qwaq_wresize (res, window_id, width, height); } static void -qwaq_resizeterm (progs_t *pr, int width, int height) +qwaq_resizeterm (qwaq_resources_t *res, int width, int height) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - int command[] = { qwaq_cmd_resizeterm, 0, width, height }; command[1] = CMD_SIZE(command); qwaq_pipe_submit (&res->commands, command, command[1]); } static void -bi_resizeterm (progs_t *pr) +bi_resizeterm (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int width = P_INT (pr, 0); int height = P_INT (pr, 1); - qwaq_resizeterm (pr, width, height); + qwaq_resizeterm (res, width, height); } static void -qwaq_mvwhline (progs_t *pr, int window_id, int x, int y, int ch, int n) +qwaq_mvwhline (qwaq_resources_t *res, int window_id, + int x, int y, int ch, int n) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_mvwhline, 0, @@ -1065,22 +1068,22 @@ qwaq_mvwhline (progs_t *pr, int window_id, int x, int y, int ch, int n) } } static void -bi_mvwhline (progs_t *pr) +bi_mvwhline (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int x = P_INT (pr, 1); int y = P_INT (pr, 2); int ch = P_INT (pr, 3); int n = P_INT (pr, 4); - qwaq_mvwhline (pr, window_id, x, y, ch, n); + qwaq_mvwhline (res, window_id, x, y, ch, n); } static void -qwaq_mvwvline (progs_t *pr, int window_id, int x, int y, int ch, int n) +qwaq_mvwvline (qwaq_resources_t *res, int window_id, + int x, int y, int ch, int n) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_mvwvline, 0, @@ -1092,22 +1095,22 @@ qwaq_mvwvline (progs_t *pr, int window_id, int x, int y, int ch, int n) } } static void -bi_mvwvline (progs_t *pr) +bi_mvwvline (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int x = P_INT (pr, 1); int y = P_INT (pr, 2); int ch = P_INT (pr, 3); int n = P_INT (pr, 4); - qwaq_mvwvline (pr, window_id, x, y, ch, n); + qwaq_mvwvline (res, window_id, x, y, ch, n); } static void -qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str) +qwaq_mvwaddstr (qwaq_resources_t *res, int window_id, + int x, int y, const char *str) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int string_id = qwaq_pipe_acquire_string (&res->commands); dstring_t *print_buffer = qwaq_cmd_string (res, string_id); @@ -1123,20 +1126,22 @@ qwaq_mvwaddstr (progs_t *pr, int window_id, int x, int y, const char *str) } } static void -bi_mvwaddstr (progs_t *pr) +bi_mvwaddstr (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); const char *str = P_GSTRING (pr, 3); - qwaq_mvwaddstr (pr, window_id, x, y, str); + qwaq_mvwaddstr (res, window_id, x, y, str); } static void -qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, int fmt_arg) +qwaq_mvwprintf (qwaq_resources_t *res, int window_id, + int x, int y, int fmt_arg) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + progs_t *pr = res->pr; if (get_window (res, __FUNCTION__, window_id)) { int string_id = qwaq_pipe_acquire_string (&res->commands); @@ -1155,19 +1160,20 @@ qwaq_mvwprintf (progs_t *pr, int window_id, int x, int y, int fmt_arg) } } static void -bi_mvwprintf (progs_t *pr) +bi_mvwprintf (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); - qwaq_mvwprintf (pr, window_id, x, y, 3); + qwaq_mvwprintf (res, window_id, x, y, 3); } static void -qwaq_wprintf (progs_t *pr, int window_id, int fmt_arg) +qwaq_wprintf (qwaq_resources_t *res, int window_id, int fmt_arg) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + progs_t *pr = res->pr; if (get_window (res, __FUNCTION__, window_id)) { int string_id = qwaq_pipe_acquire_string (&res->commands); @@ -1186,17 +1192,19 @@ qwaq_wprintf (progs_t *pr, int window_id, int fmt_arg) } } static void -bi_wprintf (progs_t *pr) +bi_wprintf (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); - qwaq_wprintf (pr, window_id, 1); + qwaq_wprintf (res, window_id, 1); } static void -qwaq_wvprintf (progs_t *pr, int window_id, const char *fmt, pr_va_list_t *args) +qwaq_wvprintf (qwaq_resources_t *res, int window_id, + const char *fmt, pr_va_list_t *args) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + progs_t *pr = res->pr; pr_type_t *list_start = PR_GetPointer (pr, args->list); pr_type_t **list = alloca (args->count * sizeof (*list)); @@ -1221,20 +1229,19 @@ qwaq_wvprintf (progs_t *pr, int window_id, const char *fmt, pr_va_list_t *args) } } static void -bi_wvprintf (progs_t *pr) +bi_wvprintf (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); const char *fmt = P_GSTRING (pr, 1); __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 2); - qwaq_wvprintf (pr, window_id, fmt, args); + qwaq_wvprintf (res, window_id, fmt, args); } static void -qwaq_waddch (progs_t *pr, int window_id, int ch) +qwaq_waddch (qwaq_resources_t *res, int window_id, int ch) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_waddch, 0, window_id, ch }; @@ -1243,19 +1250,20 @@ qwaq_waddch (progs_t *pr, int window_id, int ch) } } static void -bi_waddch (progs_t *pr) +bi_waddch (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int ch = P_INT (pr, 0); - qwaq_waddch (pr, window_id, ch); + qwaq_waddch (res, window_id, ch); } static void -qwaq_mvwvprintf (progs_t *pr, int window_id, int x, int y, +qwaq_mvwvprintf (qwaq_resources_t *res, int window_id, int x, int y, const char *fmt, pr_va_list_t *args) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + progs_t *pr = res->pr; pr_type_t *list_start = PR_GetPointer (pr, args->list); pr_type_t **list = alloca (args->count * sizeof (*list)); @@ -1280,22 +1288,21 @@ qwaq_mvwvprintf (progs_t *pr, int window_id, int x, int y, } } static void -bi_mvwvprintf (progs_t *pr) +bi_mvwvprintf (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); const char *fmt = P_GSTRING (pr, 2); __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 3); - qwaq_mvwvprintf (pr, window_id, x, y, fmt, args); + qwaq_mvwvprintf (res, window_id, x, y, fmt, args); } static void -qwaq_mvwaddch (progs_t *pr, int window_id, int x, int y, int ch) +qwaq_mvwaddch (qwaq_resources_t *res, int window_id, int x, int y, int ch) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_mvwaddch, 0, @@ -1306,21 +1313,20 @@ qwaq_mvwaddch (progs_t *pr, int window_id, int x, int y, int ch) } } static void -bi_mvwaddch (progs_t *pr) +bi_mvwaddch (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); int ch = P_INT (pr, 3); - qwaq_mvwaddch (pr, window_id, x, y, ch); + qwaq_mvwaddch (res, window_id, x, y, ch); } static void -qwaq_wrefresh (progs_t *pr, int window_id) +qwaq_wrefresh (qwaq_resources_t *res, int window_id) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wrefresh, 0, window_id, }; command[1] = CMD_SIZE(command); @@ -1328,49 +1334,48 @@ qwaq_wrefresh (progs_t *pr, int window_id) } } static void -bi_wrefresh (progs_t *pr) +bi_wrefresh (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); - qwaq_wrefresh (pr, window_id); + qwaq_wrefresh (res, window_id); } static void -bi_max_colors (progs_t *pr) +bi_max_colors (progs_t *pr, void *_res) { R_INT (pr) = COLORS; } static void -bi_max_color_pairs (progs_t *pr) +bi_max_color_pairs (progs_t *pr, void *_res) { R_INT (pr) = COLOR_PAIRS; } static void -qwaq_init_pair (progs_t *pr, int pair, int f, int b) +qwaq_init_pair (qwaq_resources_t *res, int pair, int f, int b) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); int command[] = { qwaq_cmd_init_pair, 0, pair, f, b, }; command[1] = CMD_SIZE(command); qwaq_pipe_submit (&res->commands, command, command[1]); } static void -bi_init_pair (progs_t *pr) +bi_init_pair (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int pair = P_INT (pr, 0); int f = P_INT (pr, 1); int b = P_INT (pr, 2); - qwaq_init_pair (pr, pair, f, b); + qwaq_init_pair (res, pair, f, b); } static void -qwaq_wbkgd (progs_t *pr, int window_id, int ch) +qwaq_wbkgd (qwaq_resources_t *res, int window_id, int ch) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wbkgd, 0, window_id, ch, }; command[1] = CMD_SIZE(command); @@ -1378,19 +1383,18 @@ qwaq_wbkgd (progs_t *pr, int window_id, int ch) } } static void -bi_wbkgd (progs_t *pr) +bi_wbkgd (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int ch = P_INT (pr, 1); - qwaq_wbkgd (pr, window_id, ch); + qwaq_wbkgd (res, window_id, ch); } static void -qwaq_werase (progs_t *pr, int window_id, int ch) +qwaq_werase (qwaq_resources_t *res, int window_id, int ch) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_werase, 0, window_id, }; command[1] = CMD_SIZE(command); @@ -1398,19 +1402,18 @@ qwaq_werase (progs_t *pr, int window_id, int ch) } } static void -bi_werase (progs_t *pr) +bi_werase (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int ch = P_INT (pr, 1); - qwaq_werase (pr, window_id, ch); + qwaq_werase (res, window_id, ch); } static void -qwaq_scrollok (progs_t *pr, int window_id, int flag) +qwaq_scrollok (qwaq_resources_t *res, int window_id, int flag) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_scrollok, 0, window_id, flag, }; command[1] = CMD_SIZE(command); @@ -1418,19 +1421,18 @@ qwaq_scrollok (progs_t *pr, int window_id, int flag) } } static void -bi_scrollok (progs_t *pr) +bi_scrollok (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int flag = P_INT (pr, 1); - qwaq_scrollok (pr, window_id, flag); + qwaq_scrollok (res, window_id, flag); } static void -qwaq_wmove (progs_t *pr, int window_id, int x, int y) +qwaq_wmove (qwaq_resources_t *res, int window_id, int x, int y) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wmove, 0, window_id, x, y, }; command[1] = CMD_SIZE(command); @@ -1438,13 +1440,14 @@ qwaq_wmove (progs_t *pr, int window_id, int x, int y) } } static void -bi_wmove (progs_t *pr) +bi_wmove (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); - qwaq_wmove (pr, window_id, x, y); + qwaq_wmove (res, window_id, x, y); } static const char qwaq_acs_char_map[] = "lmkjtuvwqxnos`afg~,+.-hi0pryz{|}"; @@ -1460,7 +1463,7 @@ qwaq_acs_char (progs_t *pr, unsigned acs) } } static void -bi_acs_char (progs_t *pr) +bi_acs_char (progs_t *pr, void *_res) { int acs = P_INT (pr, 0); @@ -1468,46 +1471,42 @@ bi_acs_char (progs_t *pr) } static void -qwaq_move (progs_t *pr, int x, int y) +qwaq_move (qwaq_resources_t *res, int x, int y) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - int command[] = { qwaq_cmd_move, 0, x, y, }; command[1] = CMD_SIZE(command); qwaq_pipe_submit (&res->commands, command, command[1]); } static void -bi_move (progs_t *pr) +bi_move (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int x = P_INT (pr, 0); int y = P_INT (pr, 1); - qwaq_move (pr, x, y); + qwaq_move (res, x, y); } static void -qwaq_curs_set (progs_t *pr, int visibility) +qwaq_curs_set (qwaq_resources_t *res, int visibility) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - int command[] = { qwaq_cmd_curs_set, 0, visibility, }; command[1] = CMD_SIZE(command); qwaq_pipe_submit (&res->commands, command, command[1]); } static void -bi_curs_set (progs_t *pr) +bi_curs_set (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int visibility = P_INT (pr, 0); - qwaq_curs_set (pr, visibility); + qwaq_curs_set (res, visibility); } static void -qwaq_wborder (progs_t *pr, int window_id, +qwaq_wborder (qwaq_resources_t *res, int window_id, box_sides_t sides, box_corners_t corns) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int command[] = { qwaq_cmd_wborder, 0, window_id, sides.ls, sides.rs, sides.ts, sides.bs, @@ -1517,21 +1516,20 @@ qwaq_wborder (progs_t *pr, int window_id, } } static void -bi_wborder (progs_t *pr) +bi_wborder (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); __auto_type sides = P_PACKED (pr, box_sides_t, 1); __auto_type corns = P_PACKED (pr, box_corners_t, 2); - qwaq_wborder (pr, window_id, sides, corns); + qwaq_wborder (res, window_id, sides, corns); } static void -qwaq__mvwblit_line (progs_t *pr, int window_id, int x, int y, +qwaq__mvwblit_line (qwaq_resources_t *res, int window_id, int x, int y, int *chs, int len) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); - if (get_window (res, __FUNCTION__, window_id)) { int chs_id = qwaq_pipe_acquire_string (&res->commands); dstring_t *chs_buf = qwaq_cmd_string (res, chs_id); @@ -1548,14 +1546,15 @@ qwaq__mvwblit_line (progs_t *pr, int window_id, int x, int y, } } static void -bi_mvwblit_line (progs_t *pr) +bi_mvwblit_line (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_INT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); int *chs = (int *) P_GPOINTER (pr, 3); int len = P_INT (pr, 4); - qwaq__mvwblit_line (pr, window_id, x, y, chs, len); + qwaq__mvwblit_line (res, window_id, x, y, chs, len); } static void * @@ -1571,7 +1570,7 @@ qwaq_curses_thread (qwaq_thread_t *thread) } static void -bi_initialize (progs_t *pr) +bi_initialize (progs_t *pr, void *data) { qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); @@ -1595,36 +1594,39 @@ bi_initialize (progs_t *pr) } static void -bi__c_TextContext__is_initialized (progs_t *pr) +bi__c_TextContext__is_initialized (progs_t *pr, void *_res) { - qwaq_resources_t *res = PR_Resources_Find (pr, "curses"); + qwaq_resources_t *res = _res; R_INT (pr) = res->initialized; } static void -bi__c_TextContext__max_colors (progs_t *pr) +bi__c_TextContext__max_colors (progs_t *pr, void *_res) { - bi_max_colors (pr); + qwaq_resources_t *res = _res; + bi_max_colors (pr, res); } static void -bi__c_TextContext__max_color_pairs (progs_t *pr) +bi__c_TextContext__max_color_pairs (progs_t *pr, void *_res) { - bi_max_color_pairs (pr); + qwaq_resources_t *res = _res; + bi_max_color_pairs (pr, res); } static void -bi__c_TextContext__init_pair_ (progs_t *pr) +bi__c_TextContext__init_pair_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int pair = P_INT (pr, 2); int f = P_INT (pr, 3); int b = P_INT (pr, 4); - qwaq_init_pair (pr, pair, f, b); + qwaq_init_pair (res, pair, f, b); } static void -bi__c_TextContext__acs_char_ (progs_t *pr) +bi__c_TextContext__acs_char_ (progs_t *pr, void *_res) { int acs = P_INT (pr, 2); @@ -1632,203 +1634,223 @@ bi__c_TextContext__acs_char_ (progs_t *pr) } static void -bi__c_TextContext__move_ (progs_t *pr) +bi__c_TextContext__move_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; Point *pos = &P_PACKED (pr, Point, 2); - qwaq_move (pr, pos->x, pos->y); + qwaq_move (res, pos->x, pos->y); } static void -bi__c_TextContext__curs_set_ (progs_t *pr) +bi__c_TextContext__curs_set_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int visibility = P_INT (pr, 2); - qwaq_curs_set (pr, visibility); + qwaq_curs_set (res, visibility); } static void -bi__c_TextContext__doupdate (progs_t *pr) +bi__c_TextContext__doupdate (progs_t *pr, void *_res) { - bi_doupdate (pr); + qwaq_resources_t *res = _res; + bi_doupdate (pr, res); } static void -bi__i_TextContext__mvprintf_ (progs_t *pr) +bi__i_TextContext__mvprintf_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); - qwaq_mvwprintf (pr, window_id, pos->x, pos->y, 3); + qwaq_mvwprintf (res, window_id, pos->x, pos->y, 3); } static void -bi__i_TextContext__printf_ (progs_t *pr) +bi__i_TextContext__printf_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; - qwaq_wprintf (pr, window_id, 2); + qwaq_wprintf (res, window_id, 2); } static void -bi__i_TextContext__vprintf_ (progs_t *pr) +bi__i_TextContext__vprintf_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; const char *fmt = P_GSTRING (pr, 2); __auto_type args = (pr_va_list_t *) &P_POINTER (pr, 3); - qwaq_wvprintf (pr, window_id, fmt, args); + qwaq_wvprintf (res, window_id, fmt, args); } static void -bi__i_TextContext__addch_ (progs_t *pr) +bi__i_TextContext__addch_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int ch = P_INT (pr, 2); - qwaq_waddch (pr, window_id, ch); + qwaq_waddch (res, window_id, ch); } static void -bi__i_TextContext__addstr_ (progs_t *pr) +bi__i_TextContext__addstr_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; const char *str = P_GSTRING (pr, 2); - qwaq_waddstr (pr, window_id, str); + qwaq_waddstr (res, window_id, str); } static void -bi__i_TextContext__mvvprintf_ (progs_t *pr) +bi__i_TextContext__mvvprintf_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); const char *fmt = P_GSTRING (pr, 3); __auto_type args = &P_PACKED (pr, pr_va_list_t, 4); - qwaq_mvwvprintf (pr, window_id, pos->x, pos->y, fmt, args); + qwaq_mvwvprintf (res, window_id, pos->x, pos->y, fmt, args); } static void -bi__i_TextContext__resizeTo_ (progs_t *pr) +bi__i_TextContext__resizeTo_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; self->size = P_PACKED (pr, Extent, 2); - qwaq_wresize (pr, window_id, self->size.width, self->size.height); + qwaq_wresize (res, window_id, self->size.width, self->size.height); if (window_id == 1) { - qwaq_wbkgd (pr, window_id, self->background); + qwaq_wbkgd (res, window_id, self->background); } } static void -bi__c_TextContext__refresh (progs_t *pr) +bi__c_TextContext__refresh (progs_t *pr, void *_res) { - qwaq_update_panels (pr); - qwaq_doupdate (pr); + qwaq_resources_t *res = _res; + qwaq_update_panels (pr, res); + qwaq_doupdate (pr, res); } static void -bi__i_TextContext__refresh (progs_t *pr) +bi__i_TextContext__refresh (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; - qwaq_update_panels (pr); + qwaq_update_panels (pr, res); if (window_id == 1) { - qwaq_wrefresh (pr, window_id); - qwaq_doupdate (pr); + qwaq_wrefresh (res, window_id); + qwaq_doupdate (pr, res); } } static void -bi__i_TextContext__mvaddch_ (progs_t *pr) +bi__i_TextContext__mvaddch_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); int ch = P_INT (pr, 3); - qwaq_mvwaddch (pr, window_id, pos->x, pos->y, ch); + qwaq_mvwaddch (res, window_id, pos->x, pos->y, ch); } static void -bi__i_TextContext__mvaddstr_ (progs_t *pr) +bi__i_TextContext__mvaddstr_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; Point *pos = &P_PACKED (pr, Point, 2); const char *str = P_GSTRING (pr, 3); - qwaq_mvwaddstr (pr, window_id, pos->x, pos->y, str); + qwaq_mvwaddstr (res, window_id, pos->x, pos->y, str); } static void -bi__i_TextContext__bkgd_ (progs_t *pr) +bi__i_TextContext__bkgd_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; int ch = P_INT (pr, 2); self->background = ch; - qwaq_wbkgd (pr, window_id, ch); + qwaq_wbkgd (res, window_id, ch); } static void -bi__i_TextContext__clear (progs_t *pr) +bi__i_TextContext__clear (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; int ch = self->background; - qwaq_werase (pr, window_id, ch); + qwaq_werase (res, window_id, ch); } static void -bi__i_TextContext__scrollok_ (progs_t *pr) +bi__i_TextContext__scrollok_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; int flag = P_INT (pr, 2); - qwaq_scrollok (pr, window_id, flag); + qwaq_scrollok (res, window_id, flag); } static void -bi__i_TextContext__border_ (progs_t *pr) +bi__i_TextContext__border_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; int window_id = P_STRUCT (pr, qwaq_textcontext_t, 0).window; __auto_type sides = P_PACKED (pr, box_sides_t, 2); __auto_type corns = P_PACKED (pr, box_corners_t, 3); - qwaq_wborder (pr, window_id, sides, corns); + qwaq_wborder (res, window_id, sides, corns); } static void -bi__i_TextContext__mvhline_ (progs_t *pr) +bi__i_TextContext__mvhline_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; __auto_type pos = &P_PACKED (pr, Point, 2); int ch = P_INT (pr, 3); int n = P_INT (pr, 4); - qwaq_mvwhline (pr, window_id, pos->x, pos->y, ch, n); + qwaq_mvwhline (res, window_id, pos->x, pos->y, ch, n); } static void -bi__i_TextContext__mvvline_ (progs_t *pr) +bi__i_TextContext__mvvline_ (progs_t *pr, void *_res) { + qwaq_resources_t *res = _res; __auto_type self = &P_STRUCT (pr, qwaq_textcontext_t, 0); int window_id = self->window; __auto_type pos = &P_PACKED (pr, Point, 2); int ch = P_INT (pr, 3); int n = P_INT (pr, 4); - qwaq_mvwvline (pr, window_id, pos->x, pos->y, ch, n); + qwaq_mvwvline (res, window_id, pos->x, pos->y, ch, n); } static void -bi_curses_clear (progs_t *pr, void *data) +bi_curses_clear (progs_t *pr, void *_res) { - __auto_type res = (qwaq_resources_t *) data; + __auto_type res = (qwaq_resources_t *) _res; if (res->initialized) { qwaq_input_disable_mouse (); diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 9b1d2b45e..49b5f5ba7 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -147,7 +147,7 @@ static qwaq_debug_t *qwaq_debug_data; static int qwaq_debug_load (progs_t *pr) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) PR_Resources_Find (pr, "qwaq-debug"); pthread_mutex_lock (&debug_data_mutex); qwaq_debug_data = debug; // FIXME ? see decl @@ -158,14 +158,14 @@ qwaq_debug_load (progs_t *pr) } static void -qwaq_debug_clear (progs_t *pr, void *data) +qwaq_debug_clear (progs_t *pr, void *_res) { - __auto_type debug = (qwaq_debug_t *) data; + __auto_type debug = (qwaq_debug_t *) _res; target_reset (debug); } static void -qwaq_target_clear (progs_t *pr, void *data) +qwaq_target_clear (progs_t *pr, void *_res) { qwaq_target_t *target = pr->debug_data; if (target) { @@ -201,9 +201,9 @@ qwaq_target_load (progs_t *pr) } static void -qdb_set_trace (progs_t *pr) +qdb_set_trace (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); int state = P_INT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); @@ -213,9 +213,9 @@ qdb_set_trace (progs_t *pr) } static void -qdb_set_breakpoint (progs_t *pr) +qdb_set_breakpoint (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); unsigned staddr = P_INT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); @@ -231,9 +231,9 @@ qdb_set_breakpoint (progs_t *pr) } static void -qdb_clear_breakpoint (progs_t *pr) +qdb_clear_breakpoint (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); unsigned staddr = P_UINT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); @@ -248,9 +248,9 @@ qdb_clear_breakpoint (progs_t *pr) } static void -qdb_set_watchpoint (progs_t *pr) +qdb_set_watchpoint (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); pr_ptr_t offset = P_UINT (pr, 1); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); @@ -265,9 +265,9 @@ qdb_set_watchpoint (progs_t *pr) } static void -qdb_clear_watchpoint (progs_t *pr) +qdb_clear_watchpoint (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -277,9 +277,9 @@ qdb_clear_watchpoint (progs_t *pr) } static void -qdb_continue (progs_t *pr) +qdb_continue (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); @@ -290,9 +290,9 @@ qdb_continue (progs_t *pr) } static void -qdb_get_state (progs_t *pr) +qdb_get_state (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -328,9 +328,9 @@ qdb_get_state (progs_t *pr) } static void -qdb_get_stack_depth (progs_t *pr) +qdb_get_stack_depth (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -339,9 +339,9 @@ qdb_get_stack_depth (progs_t *pr) } static void -qdb_get_stack (progs_t *pr) +qdb_get_stack (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -363,9 +363,9 @@ qdb_get_stack (progs_t *pr) } static void -qdb_get_event (progs_t *pr) +qdb_get_event (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); __auto_type event = &P_STRUCT (pr, qdb_event_t, 1); @@ -397,9 +397,9 @@ qdb_get_event (progs_t *pr) } static void -qdb_get_data (progs_t *pr) +qdb_get_data (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -423,9 +423,9 @@ qdb_get_data (progs_t *pr) } static void -qdb_get_string (progs_t *pr) +qdb_get_string (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -438,9 +438,9 @@ qdb_get_string (progs_t *pr) } static void -qdb_get_file_path (progs_t *pr) +qdb_get_file_path (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -463,9 +463,9 @@ qdb_get_file_path (progs_t *pr) } static void -qdb_find_string (progs_t *pr) +qdb_find_string (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -475,9 +475,9 @@ qdb_find_string (progs_t *pr) } static void -qdb_find_global (progs_t *pr) +qdb_find_global (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -495,9 +495,9 @@ qdb_find_global (progs_t *pr) } static void -qdb_find_field (progs_t *pr) +qdb_find_field (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -533,9 +533,9 @@ return_function (progs_t *pr, dfunction_t *func) } static void -qdb_find_function (progs_t *pr) +qdb_find_function (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -546,9 +546,9 @@ qdb_find_function (progs_t *pr) } static void -qdb_get_function (progs_t *pr) +qdb_get_function (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -580,9 +580,9 @@ return_auxfunction (progs_t *pr, pr_auxfunction_t *auxfunc) } static void -qdb_find_auxfunction (progs_t *pr) +qdb_find_auxfunction (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -598,9 +598,9 @@ qdb_find_auxfunction (progs_t *pr) } static void -qdb_get_auxfunction (progs_t *pr) +qdb_get_auxfunction (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -611,9 +611,9 @@ qdb_get_auxfunction (progs_t *pr) } static void -qdb_get_local_defs (progs_t *pr) +qdb_get_local_defs (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -637,9 +637,9 @@ qdb_get_local_defs (progs_t *pr) } static void -qdb_get_source_line_addr (progs_t *pr) +qdb_get_source_line_addr (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -650,9 +650,9 @@ qdb_get_source_line_addr (progs_t *pr) } static void -qdb_has_data_stack (progs_t *pr) +qdb_has_data_stack (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; @@ -661,9 +661,9 @@ qdb_has_data_stack (progs_t *pr) } static void -qdb_get_frame_addr (progs_t *pr) +qdb_get_frame_addr (progs_t *pr, void *_res) { - __auto_type debug = PR_Resources_Find (pr, "qwaq-debug"); + __auto_type debug = (qwaq_debug_t *) _res; pr_ptr_t handle = P_INT (pr, 0); qwaq_target_t *target = get_target (debug, __FUNCTION__, handle); progs_t *tpr = target->pr; diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index 3a8fbdf3a..3bc6b2a26 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -575,11 +575,12 @@ formatLine (txtbuffer_t *buffer, unsigned linePtr, unsigned xpos, //=== static void -bi__i_EditBuffer__init (progs_t *pr) +bi__i_EditBuffer__init (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); - RUA_obj_increment_retaincount (pr);// [super init]; + // [super init]; + RUA_obj_increment_retaincount (pr, pr->pr_objective_resources); txtbuffer_t *txtbuffer = TextBuffer_Create (); editbuffer_t *buffer = editbuffer_new (res); @@ -591,11 +592,12 @@ bi__i_EditBuffer__init (progs_t *pr) } static void -bi__i_EditBuffer__initWithFile_ (progs_t *pr) +bi__i_EditBuffer__initWithFile_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); - RUA_obj_increment_retaincount (pr);// [super init]; + // [super init]; + RUA_obj_increment_retaincount (pr, pr->pr_objective_resources); const char *filename = P_GSTRING (pr, 2); txtbuffer_t *txtbuffer = TextBuffer_Create (); editbuffer_t *buffer = editbuffer_new (res); @@ -610,9 +612,9 @@ bi__i_EditBuffer__initWithFile_ (progs_t *pr) } static void -bi__i_EditBuffer__dealloc (progs_t *pr) +bi__i_EditBuffer__dealloc (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; __auto_type self = &P_STRUCT (pr, qwaq_editbuffer_t, 0); int buffer_id = self->buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); @@ -622,9 +624,9 @@ bi__i_EditBuffer__dealloc (progs_t *pr) } static void -bi__i_EditBuffer__nextChar_ (progs_t *pr) +bi__i_EditBuffer__nextChar_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -633,9 +635,9 @@ bi__i_EditBuffer__nextChar_ (progs_t *pr) } static void -bi__i_EditBuffer__prevChar_ (progs_t *pr) +bi__i_EditBuffer__prevChar_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -644,9 +646,9 @@ bi__i_EditBuffer__prevChar_ (progs_t *pr) } static void -bi__i_EditBuffer__nextNonSpace_ (progs_t *pr) +bi__i_EditBuffer__nextNonSpace_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -655,9 +657,9 @@ bi__i_EditBuffer__nextNonSpace_ (progs_t *pr) } static void -bi__i_EditBuffer__prevNonSpace_ (progs_t *pr) +bi__i_EditBuffer__prevNonSpace_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -666,9 +668,9 @@ bi__i_EditBuffer__prevNonSpace_ (progs_t *pr) } static void -bi__i_EditBuffer__isWord_ (progs_t *pr) +bi__i_EditBuffer__isWord_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -677,9 +679,9 @@ bi__i_EditBuffer__isWord_ (progs_t *pr) } static void -bi__i_EditBuffer__nextWord_ (progs_t *pr) +bi__i_EditBuffer__nextWord_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -688,9 +690,9 @@ bi__i_EditBuffer__nextWord_ (progs_t *pr) } static void -bi__i_EditBuffer__prevWord_ (progs_t *pr) +bi__i_EditBuffer__prevWord_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -699,9 +701,9 @@ bi__i_EditBuffer__prevWord_ (progs_t *pr) } static void -bi__i_EditBuffer__nextLine_ (progs_t *pr) +bi__i_EditBuffer__nextLine_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -710,9 +712,9 @@ bi__i_EditBuffer__nextLine_ (progs_t *pr) } static void -bi__i_EditBuffer__prevLine_ (progs_t *pr) +bi__i_EditBuffer__prevLine_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -721,9 +723,9 @@ bi__i_EditBuffer__prevLine_ (progs_t *pr) } static void -bi__i_EditBuffer__nextLine__ (progs_t *pr) +bi__i_EditBuffer__nextLine__ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -742,9 +744,9 @@ bi__i_EditBuffer__nextLine__ (progs_t *pr) } static void -bi__i_EditBuffer__prevLine__ (progs_t *pr) +bi__i_EditBuffer__prevLine__ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -757,9 +759,9 @@ bi__i_EditBuffer__prevLine__ (progs_t *pr) } static void -bi__i_EditBuffer__charPos_at_ (progs_t *pr) +bi__i_EditBuffer__charPos_at_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -770,9 +772,9 @@ bi__i_EditBuffer__charPos_at_ (progs_t *pr) } static void -bi__i_EditBuffer__charPtr_at_ (progs_t *pr) +bi__i_EditBuffer__charPtr_at_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -783,9 +785,9 @@ bi__i_EditBuffer__charPtr_at_ (progs_t *pr) } static void -bi__i_EditBuffer__getWord_ (progs_t *pr) +bi__i_EditBuffer__getWord_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -797,9 +799,9 @@ bi__i_EditBuffer__getWord_ (progs_t *pr) } static void -bi__i_EditBuffer__getLine_ (progs_t *pr) +bi__i_EditBuffer__getLine_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -811,9 +813,9 @@ bi__i_EditBuffer__getLine_ (progs_t *pr) } static void -bi__i_EditBuffer__getBOL_ (progs_t *pr) +bi__i_EditBuffer__getBOL_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -822,9 +824,9 @@ bi__i_EditBuffer__getBOL_ (progs_t *pr) } static void -bi__i_EditBuffer__getEOL_ (progs_t *pr) +bi__i_EditBuffer__getEOL_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -833,9 +835,9 @@ bi__i_EditBuffer__getEOL_ (progs_t *pr) } static void -bi__i_EditBuffer__getBOT (progs_t *pr) +bi__i_EditBuffer__getBOT (progs_t *pr, void *_res) { - //qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + //qwaq_ebresources_t *res = _res; //int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; //editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); @@ -843,9 +845,9 @@ bi__i_EditBuffer__getBOT (progs_t *pr) } static void -bi__i_EditBuffer__getEOT (progs_t *pr) +bi__i_EditBuffer__getEOT (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); @@ -853,9 +855,9 @@ bi__i_EditBuffer__getEOT (progs_t *pr) } static void -bi__i_EditBuffer__readString_ (progs_t *pr) +bi__i_EditBuffer__readString_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); @@ -868,9 +870,9 @@ bi__i_EditBuffer__readString_ (progs_t *pr) } static void -bi__i_EditBuffer__getChar_ (progs_t *pr) +bi__i_EditBuffer__getChar_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned ptr = P_UINT (pr, 2); @@ -882,9 +884,9 @@ bi__i_EditBuffer__getChar_ (progs_t *pr) } static void -bi__i_EditBuffer__putChar_at_ (progs_t *pr) +bi__i_EditBuffer__putChar_at_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); int chr = P_UINT (pr, 2); @@ -897,9 +899,9 @@ bi__i_EditBuffer__putChar_at_ (progs_t *pr) } static void -bi__i_EditBuffer__insertChar_at_ (progs_t *pr) +bi__i_EditBuffer__insertChar_at_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); char chr = P_UINT (pr, 2); @@ -912,9 +914,9 @@ bi__i_EditBuffer__insertChar_at_ (progs_t *pr) } static void -bi__i_EditBuffer__countLines_ (progs_t *pr) +bi__i_EditBuffer__countLines_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); @@ -924,9 +926,9 @@ bi__i_EditBuffer__countLines_ (progs_t *pr) } static void -bi__i_EditBuffer__search_for_direction_ (progs_t *pr) +bi__i_EditBuffer__search_for_direction_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); @@ -938,9 +940,9 @@ bi__i_EditBuffer__search_for_direction_ (progs_t *pr) } static void -bi__i_EditBuffer__isearch_for_direction_ (progs_t *pr) +bi__i_EditBuffer__isearch_for_direction_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); __auto_type selection = &P_PACKED (pr, eb_sel_t, 2); @@ -952,9 +954,9 @@ bi__i_EditBuffer__isearch_for_direction_ (progs_t *pr) } static void -bi__i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) +bi__i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); unsigned linePtr = P_UINT (pr, 2); @@ -972,27 +974,27 @@ bi__i_EditBuffer__formatLine_from_into_width_highlight_colors_ (progs_t *pr) } static void -bi__i_EditBuffer__modified (progs_t *pr) +bi__i_EditBuffer__modified (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); R_INT (pr) = buffer->modified; } static void -bi__i_EditBuffer__textSize (progs_t *pr) +bi__i_EditBuffer__textSize (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); R_INT (pr) = buffer->txtbuffer->textSize; } static void -bi__i_EditBuffer__saveFile_ (progs_t *pr) +bi__i_EditBuffer__saveFile_ (progs_t *pr, void *_res) { - qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer"); + qwaq_ebresources_t *res = _res; int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer; editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id); const char *filename = P_GSTRING (pr, 2); @@ -1003,9 +1005,9 @@ bi__i_EditBuffer__saveFile_ (progs_t *pr) } static void -qwaq_ebresources_clear (progs_t *pr, void *data) +qwaq_ebresources_clear (progs_t *pr, void *_res) { - __auto_type res = (qwaq_ebresources_t *) data; + __auto_type res = (qwaq_ebresources_t *) _res; for (editbuffer_t *buffer = res->buffer_list; buffer; buffer = buffer->next) { diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 746332cc4..a53275a13 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -100,7 +100,7 @@ static SCR_Func bi_2dfuncs[] = { }; static void -bi_refresh (progs_t *pr) +bi_refresh (progs_t *pr, void *_res) { con_realtime = Sys_DoubleTime () - basetime; con_frametime = con_realtime - old_conrealtime; @@ -114,13 +114,13 @@ bi_refresh (progs_t *pr) } static void -bi_refresh_2d (progs_t *pr) +bi_refresh_2d (progs_t *pr, void *_res) { qc2d = P_FUNCTION (pr, 0); } static void -bi_shutdown (progs_t *pr) +bi_shutdown (progs_t *pr, void *_res) { Sys_Shutdown (); } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 9bb4d838f..4c51edae0 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -146,7 +146,7 @@ init_qf (void) } static void -bi_printf (progs_t *pr) +bi_printf (progs_t *pr, void *_res) { dstring_t *dstr = dstring_new (); @@ -158,14 +158,14 @@ bi_printf (progs_t *pr) } static void -bi_traceon (progs_t *pr) +bi_traceon (progs_t *pr, void *_res) { pr->pr_trace = true; pr->pr_trace_depth = pr->pr_depth; } static void -bi_traceoff (progs_t *pr) +bi_traceoff (progs_t *pr, void *_res) { pr->pr_trace = false; } diff --git a/ruamoko/qwaq/builtins/term-input.c b/ruamoko/qwaq/builtins/term-input.c index 8b34a22e5..4e725a431 100644 --- a/ruamoko/qwaq/builtins/term-input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -639,9 +639,9 @@ qwaq_input_shutdown (qwaq_input_resources_t *res) } static void -bi_send_connected_devices (progs_t *pr) +bi_send_connected_devices (progs_t *pr, void *_res) { - qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); + qwaq_input_resources_t *res = _res; int command[] = { qwaq_cmd_send_connected_devices, 0, @@ -652,9 +652,9 @@ bi_send_connected_devices (progs_t *pr) } static void -bi_get_device_info (progs_t *pr) +bi_get_device_info (progs_t *pr, void *_res) { - qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); + qwaq_input_resources_t *res = _res; int devid = P_INT (pr, 0); int command[] = { @@ -737,9 +737,9 @@ get_event (qwaq_input_resources_t *res, qwaq_event_t *event) } static void -bi_get_event (progs_t *pr) +bi_get_event (progs_t *pr, void *_res) { - qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); + qwaq_input_resources_t *res = _res; qwaq_event_t *event = &P_STRUCT (pr, qwaq_event_t, 0); R_INT (pr) = get_event (res, event); @@ -854,9 +854,9 @@ qwaq_input_thread (qwaq_thread_t *thread) } static void -bi_init_input (progs_t *pr) +bi_init_input (progs_t *pr, void *_res) { - qwaq_input_resources_t *res = PR_Resources_Find (pr, "input"); + qwaq_input_resources_t *res = _res; qwaq_input_init (res); res->initialized = 1; create_thread (qwaq_input_thread, res); @@ -880,9 +880,9 @@ static builtin_t builtins[] = { }; static void -bi_input_clear (progs_t *pr, void *data) +bi_input_clear (progs_t *pr, void *_res) { - __auto_type res = (qwaq_input_resources_t *) data; + __auto_type res = (qwaq_input_resources_t *) _res; if (res->initialized) { qwaq_input_shutdown (res); diff --git a/tools/qfcc/test/test-bi.c b/tools/qfcc/test/test-bi.c index 1965db082..a13cf9ee7 100644 --- a/tools/qfcc/test/test-bi.c +++ b/tools/qfcc/test/test-bi.c @@ -44,7 +44,7 @@ #include "test-bi.h" static void -bi_printf (progs_t *pr) +bi_printf (progs_t *pr, void *data) { static dstring_t *dstr; @@ -62,26 +62,26 @@ bi_printf (progs_t *pr) } static void -bi_errno (progs_t *pr) +bi_errno (progs_t *pr, void *data) { R_INT (pr) = errno; } static void -bi_strerror (progs_t *pr) +bi_strerror (progs_t *pr, void *data) { int err = P_INT (pr, 0); RETURN_STRING (pr, strerror (err)); } static void -bi_exit (progs_t *pr) +bi_exit (progs_t *pr, void *data) { exit (P_INT (pr, 0)); } static void -bi_spawn (progs_t *pr) +bi_spawn (progs_t *pr, void *data) { edict_t *ed; ed = ED_Alloc (pr); @@ -89,7 +89,7 @@ bi_spawn (progs_t *pr) } static void -bi_remove (progs_t *pr) +bi_remove (progs_t *pr, void *data) { edict_t *ed; ed = P_EDICT (pr, 0); From 4d491a444d050cdded4e7a0ce44c7e093e918ebd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 14:28:19 +0900 Subject: [PATCH 2445/3664] [gamecode] Fix handling of undefined builtins The setup of the function descriptor for undefined builtins was incomplete and led to the progs running code at address 0. It didn't end well. --- include/QF/progs.h | 2 +- libs/gamecode/pr_builtins.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 12d96f009..cd1008f91 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1898,7 +1898,7 @@ struct progs_s { struct hashtab_s *builtin_hash; struct hashtab_s *builtin_num_hash; struct biblock_s *builtin_blocks; - pr_int_t bi_no_function; + builtin_t *bi_no_function; unsigned bi_next; unsigned (*bi_map) (progs_t *pr, unsigned binum); ///@} diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index cb0a5a694..821cc7d56 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -121,7 +121,7 @@ PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins, void *data) bi->name = "invalid function"; bi->proc = bi_no_function; bi->binum = builtin_next (pr); - pr->bi_no_function = bi->binum; + pr->bi_no_function = bi; DARRAY_APPEND (pr->builtin_blocks, bi); Hash_AddElement (pr->builtin_num_hash, bi); } @@ -212,9 +212,8 @@ PR_RelocateBuiltins (progs_t *pr) if (!bi) { Sys_Printf ("PR_RelocateBuiltins: %s: undefined builtin %s\n", pr->progs_name, bi_name); - desc->first_statement = -pr->bi_no_function; + bi = pr->bi_no_function; bad = 1; - continue; } desc->first_statement = -bi->binum; } From f3559cedb0a2081d7c4382ea682baf8482822eee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 14:41:14 +0900 Subject: [PATCH 2446/3664] [qwaq] Plug a file handle leak Forgot to call Qclose in load_file. --- ruamoko/qwaq/builtins/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 4c51edae0..940e2072a 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -113,6 +113,7 @@ load_file (progs_t *pr, const char *name, off_t *_size) sym = malloc (size + 1); sym[size] = 0; Qread (file, sym, size); + Qclose (file); *_size = size; return sym; } From f6ac614e097b19ce992d76a4b97f98220a2165b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 16:41:38 +0900 Subject: [PATCH 2447/3664] [scene] Add functions for scene and entity create/delete Scene creation was already there, but now can be deleted, as can entities. --- include/QF/render.h | 2 +- include/QF/scene/scene.h | 13 ++--- include/QF/scene/transform.h | 4 +- libs/scene/scene.c | 96 +++++++++++++++++++++++++++++++----- 4 files changed, 92 insertions(+), 23 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index 3a3f7ae7e..3668a157f 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -172,8 +172,8 @@ typedef struct renderer_s { typedef struct entity_s { struct entity_s *next; - struct transform_s *transform; + int id; ///< scene id animation_t animation; visibility_t visibility; renderer_t renderer; diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index cab3110e0..c55ae8f35 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -40,21 +40,16 @@ */ ///@{ -typedef struct hierarchyset_s DARRAY_TYPE (struct hierarchy_s *) - hierarchyset_t; -typedef struct visibilityset_s DARRAY_TYPE (struct visibility_s *) - visibilityset_t; - typedef struct scene_s { struct scene_resources_s *const resources; - hierarchyset_t roots; - xformset_t transforms; - entityset_t entities; - visibilityset_t visibility; + xformset_t roots; } scene_t; scene_t *Scene_NewScene (void); +void Scene_DeleteScene (scene_t *scene); struct entity_s *Scene_CreateEntity (scene_t *scene); +struct entity_s *Scene_GetEntity (scene_t *scene, int id); +void Scene_DestroyEntity (scene_t *scene, struct entity_s *entity); void Scene_FreeAllEntities (scene_t *scene); diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index 94595447c..fde6899ad 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -43,10 +43,12 @@ typedef struct transform_s { struct hierarchy_s *hierarchy; - uint32_t index; + uint32_t index; ///< index in hierarchy + int32_t id; ///< scene id } transform_t; transform_t *Transform_New (transform_t *parent); +/* Deletes all child transforms, and transform names */ void Transform_Delete (transform_t *transform); transform_t *Transform_NewNamed (transform_t *parent, const char *name); uint32_t Transform_ChildCount (const transform_t *transform) __attribute__((pure)); diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 421021b7c..b7bc2d50b 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -36,6 +36,7 @@ #endif #include "QF/progs.h" // for PR_RESMAP +#include "QF/sys.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" @@ -56,34 +57,105 @@ Scene_NewScene (void) *(scene_resources_t **)&scene->resources = res; DARRAY_INIT (&scene->roots, 16); - DARRAY_INIT (&scene->transforms, 16); - DARRAY_INIT (&scene->entities, 16); - DARRAY_INIT (&scene->visibility, 16); return scene; } +void +Scene_DeleteScene (scene_t *scene) +{ + Scene_FreeAllEntities (scene); + + scene_resources_t *res = scene->resources; + for (unsigned i = 0; i < res->entities._size; i++) { + free (res->entities._map[i]); + } + free (res->entities._map); + + DARRAY_CLEAR (&scene->roots); + + free (scene->resources); + free (scene); +} + entity_t * Scene_CreateEntity (scene_t *scene) { scene_resources_t *res = scene->resources; entity_t *ent = PR_RESNEW_NC (res->entities); - ent->transform = 0; - DARRAY_APPEND (&scene->entities, ent); + ent->transform = Transform_New (0); + ent->id = PR_RESINDEX (res->entities, ent); + + hierarchy_t *h = ent->transform->hierarchy; + h->entity.a[ent->transform->index] = ent; + + DARRAY_APPEND (&scene->roots, ent->transform); return ent; } +entity_t * +Scene_GetEntity (scene_t *scene, int id) +{ + scene_resources_t *res = scene->resources; + return PR_RESGET (res->entities, id); +} + +static void +unroot_transform (scene_t *scene, transform_t *transform) +{ + if (!Transform_GetParent (transform)) { + for (size_t i = 0; i < scene->roots.size; i++) { + if (scene->roots.a[i] == transform) { + DARRAY_REMOVE_AT (&scene->roots, i); + break; + } + } + } +} + +static void +destroy_entity (scene_t *scene, entity_t *ent) +{ + scene_resources_t *res = scene->resources; + // ent->transform will be trampled by the loop below + transform_t *transform = ent->transform; + + // Transform_Delete takes care of all hierarchy stuff (transforms + // themselves, name strings, hierarchy table) + hierarchy_t *h = transform->hierarchy; + for (size_t i = 0; i < h->entity.size; i++) { + entity_t *e = h->entity.a[0]; + e->transform = 0; + PR_RESFREE (res->entities, ent); + } + Transform_Delete (transform); +} + +void +Scene_DestroyEntity (scene_t *scene, entity_t *ent) +{ + scene_resources_t *res = scene->resources; + + if (PR_RESGET (res->entities, ent->id) != ent) { + Sys_Error ("Scene_DestroyEntity: entity not owned by scene"); + } + unroot_transform (scene, ent->transform); + // pull the transform out of the hierarchy to make it easier to destory + // all the child entities + Transform_SetParent (ent->transform, 0); + destroy_entity (scene, ent); +} + void Scene_FreeAllEntities (scene_t *scene) { - scene_resources_t *res = scene->resources; - for (size_t i = 0; i < scene->entities.size; i++) { - entity_t *ent = scene->entities.a[i]; - if (ent->transform) { - Transform_Delete (ent->transform); - ent->transform = 0; - } + for (size_t i = 0; i < scene->roots.size; i++) { + hierarchy_t *h = scene->roots.a[i]->hierarchy; + // deleting the root entity deletes all child entities + entity_t *ent = h->entity.a[0]; + destroy_entity (scene, ent); } + scene_resources_t *res = scene->resources; PR_RESRESET (res->entities); } From afbca54faf39fa98f91a238f2c3633af625f387f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 16:43:10 +0900 Subject: [PATCH 2448/3664] [ruamoko] Add wrappers for the existing scene functions I've run into a bit of an issue with transform management (really, just need to make them owned by the scene, but that means creating a scene for quake and quakeworld). --- include/rua_internal.h | 1 + libs/ruamoko/Makemodule.am | 3 +- libs/ruamoko/rua_game_init.c | 1 + libs/ruamoko/rua_scene.c | 205 +++++++++++++++++++++++++++++++++++ 4 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 libs/ruamoko/rua_scene.c diff --git a/include/rua_internal.h b/include/rua_internal.h index 955e6d5e6..b58eb4530 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -62,5 +62,6 @@ struct plitem_s *Plist_GetItem (struct progs_s *pr, int handle); void RUA_Input_Init (struct progs_s *pr, int secure); void RUA_Mersenne_Init (struct progs_s *pr, int secure); +void RUA_Scene_Init (struct progs_s *pr, int secure); #endif//__rua_internal_h diff --git a/libs/ruamoko/Makemodule.am b/libs/ruamoko/Makemodule.am index 08749dfef..118fde38c 100644 --- a/libs/ruamoko/Makemodule.am +++ b/libs/ruamoko/Makemodule.am @@ -37,4 +37,5 @@ libs_ruamoko_libQFruamoko_client_la_DEPENDENCIES= \ libs_ruamoko_libQFruamoko_client_la_SOURCES= \ libs/ruamoko/rua_game_init.c \ libs/ruamoko/rua_input.c \ - libs/ruamoko/rua_mersenne.c + libs/ruamoko/rua_mersenne.c \ + libs/ruamoko/rua_scene.c diff --git a/libs/ruamoko/rua_game_init.c b/libs/ruamoko/rua_game_init.c index d0b239ddd..ac1628cc8 100644 --- a/libs/ruamoko/rua_game_init.c +++ b/libs/ruamoko/rua_game_init.c @@ -36,6 +36,7 @@ static void (*init_funcs[])(progs_t *, int) = { RUA_Input_Init, RUA_Mersenne_Init, + RUA_Scene_Init, }; VISIBLE void diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c new file mode 100644 index 000000000..1ea641781 --- /dev/null +++ b/libs/ruamoko/rua_scene.c @@ -0,0 +1,205 @@ +/* + bi_scene.c + + Ruamoko scene builtins + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cmem.h" +#include "QF/hash.h" +#include "QF/progs.h" +#include "QF/render.h" + +#include "QF/scene/scene.h" +#include "QF/scene/transform.h" + +#include "rua_internal.h" + +typedef struct rua_scene_s { + struct rua_scene_s *next; + struct rua_scene_s **prev; + scene_t *scene; +} rua_scene_t; + +typedef struct scene_resources_s { + progs_t *pr; + PR_RESMAP (rua_scene_t) scene_map; + rua_scene_t *scenes; +} scene_resources_t; + +static rua_scene_t * +rua_scene_new (scene_resources_t *res) +{ + return PR_RESNEW (res->scene_map); +} + +static void +rua_scene_free (scene_resources_t *res, rua_scene_t *scene) +{ + if (scene->next) { + scene->next->prev = scene->prev; + } + *scene->prev = scene->next; + scene->prev = 0; + PR_RESFREE (res->scene_map, scene); +} + +static rua_scene_t * +rua__scene_get (scene_resources_t *res, int id, const char *name) +{ + rua_scene_t *scene = PR_RESGET (res->scene_map, id); + + // scene->prev will be null if the handle is unallocated + if (!scene || !scene->prev) { + PR_RunError (res->pr, "invalid scene passed to %s", name + 3); + } + return scene; +} +#define rua_scene_get(res, id) rua__scene_get(res, id, __FUNCTION__) + +static entity_t * +rua__entity_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) +{ + entity_t *ent = Scene_GetEntity (scene->scene, id); + + if (!ent) { + PR_RunError (pr, "invalid entity passed to %s", name + 3); + } + return ent; +} +#define rua_entity_get(pr, scene, id) rua__entity_get(pr, scene, id, __FUNCTION__) + +static int +rua_scene_index (scene_resources_t *res, rua_scene_t *scene) +{ + return PR_RESINDEX (res->scene_map, scene); +} + +static void +bi_Scene_NewScene (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + + rua_scene_t *scene = rua_scene_new (res); + + scene->scene = Scene_NewScene (); + + scene->next = res->scenes; + if (res->scenes) { + res->scenes->prev = &scene->next; + } + scene->prev = &res->scenes; + res->scenes = scene; + + R_INT (pr) = rua_scene_index (res, scene); +} + +static void +rua_delete_scene (scene_resources_t *res, rua_scene_t *scene) +{ + Scene_DeleteScene (scene->scene); + rua_scene_free (res, scene); +} + +static void +bi_Scene_DeleteScene (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + + rua_delete_scene (res, scene); +} + +static void +bi_Scene_CreateEntity (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + entity_t *ent = Scene_CreateEntity (scene->scene); + R_INT (pr) = ent->id; +} + +static void +bi_Scene_DestroyEntity (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + entity_t *ent = rua_entity_get (pr, scene, P_INT (pr, 1)); + Scene_DestroyEntity (scene->scene, ent); +} + +static void +bi_Entity_GetTransform (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + entity_t *ent = rua_entity_get (pr, scene, P_INT (pr, 1)); + + R_INT (pr) = ent->transform->id; +} + +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +static builtin_t builtins[] = { + bi(Scene_NewScene, 0), + bi(Scene_DeleteScene, 1, p(ptr)), + bi(Scene_CreateEntity, 1, p(ptr)), + bi(Scene_DestroyEntity, 2, p(ptr), p(ptr)), + + bi(Entity_GetTransform, 2, p(ptr), p(ptr)), + + {0} +}; + +static void +bi_scene_clear (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + + while (res->scenes) { + rua_delete_scene (res, res->scenes); + } +} + +void +RUA_Scene_Init (progs_t *pr, int secure) +{ + scene_resources_t *res = calloc (sizeof (scene_resources_t), 1); + + res->pr = pr; + + PR_Resources_Register (pr, "scene", res, bi_scene_clear); + PR_RegisterBuiltins (pr, builtins, res); +} From 59044d38278324950d4d70e8631e47587338e034 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 19:28:19 +0900 Subject: [PATCH 2449/3664] Fix a bunch of distcheck issues --- config.d/build_control.m4 | 2 ++ include/QF/Makemodule.am | 4 +++- libs/gamecode/Makemodule.am | 2 +- libs/gamecode/test/Makemodule.am | 2 +- tools/qfcc/include/Makemodule.am | 4 +++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index f3e59d2d5..fb0b60951 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -329,6 +329,7 @@ if test x"${top_need_libs}" = xyes; then qfac_include_qf_input="\$(include_qf_input)" qfac_include_qf_math="\$(include_qf_math)" qfac_include_qf_plugin="\$(include_qf_plugin)" + qfac_include_qf_progs="\$(include_qf_progs)" qfac_include_qf_scene="\$(include_qf_scene)" qfac_include_qf_simd="\$(include_qf_simd)" qfac_include_qf_ui="\$(include_qf_ui)" @@ -340,6 +341,7 @@ QF_SUBST(qfac_include_qf_glsl) QF_SUBST(qfac_include_qf_input) QF_SUBST(qfac_include_qf_math) QF_SUBST(qfac_include_qf_plugin) +QF_SUBST(qfac_include_qf_progs) QF_SUBST(qfac_include_qf_scene) QF_SUBST(qfac_include_qf_simd) QF_SUBST(qfac_include_qf_ui) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index d36dd7ead..382e556e3 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -210,6 +210,7 @@ qf_glsl_includedir = $(includedir)/QF/GLSL qf_input_includedir = $(includedir)/QF/input qf_math_includedir = $(includedir)/QF/math qf_plugin_includedir = $(includedir)/QF/plugin +qf_progs_includedir = $(includedir)/QF/progs qf_scene_includedir = $(includedir)/QF/scene qf_simd_includedir = $(includedir)/QF/simd qf_ui_includedir = $(includedir)/QF/ui @@ -220,6 +221,7 @@ qf_glsl_include_HEADERS = @qfac_include_qf_glsl@ qf_input_include_HEADERS = @qfac_include_qf_input@ qf_math_include_HEADERS = @qfac_include_qf_math@ qf_plugin_include_HEADERS = @qfac_include_qf_plugin@ +qf_progs_include_HEADERS = @qfac_include_qf_progs@ qf_scene_include_HEADERS = @qfac_include_qf_scene@ qf_simd_include_HEADERS = @qfac_include_qf_simd@ qf_ui_include_HEADERS = @qfac_include_qf_ui@ @@ -232,7 +234,7 @@ ruamoko_qf_include_HEADERS = @qfac_qfcc_include_qf@ ruamoko_qf_input_include_HEADERS = @qfac_qfcc_include_qf_input@ ruamoko_qf_progs_include_HEADERS = @qfac_qfcc_include_qf_progs@ -EXTRA_HEADERS += \ +EXTRA_DIST += \ $(include_qf) \ $(include_qf_gl) \ $(include_qf_glsl) \ diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index dbffb47b3..411bfb645 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -21,7 +21,7 @@ libs_gamecode_libQFgamecode_la_SOURCES= \ libs/gamecode/pr_v6p_opcode.c \ libs/gamecode/pr_zone.c -noinst_PYTHON += $(opcodes_py) +noinst_PYTHON += $(opcodes_py) $(convert_py) $(hops_py) opcodes_py = $(srcdir)/libs/gamecode/opcodes.py pr_opcode_cinc = $(top_builddir)/libs/gamecode/pr_opcode.cinc diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 57793aa4f..2cfd9fbf9 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -35,7 +35,7 @@ TESTS += $(libs_gamecode_tests) check_PROGRAMS += $(libs_gamecode_tests) -EXTRA_DIST += head.c main.c +EXTRA_DIST += libs/gamecode/test/head.c libs/gamecode/test/main.c test_gamecode_libs= \ libs/gamecode/libQFgamecode.la \ diff --git a/tools/qfcc/include/Makemodule.am b/tools/qfcc/include/Makemodule.am index f6158b5c4..6609ddfc4 100644 --- a/tools/qfcc/include/Makemodule.am +++ b/tools/qfcc/include/Makemodule.am @@ -11,6 +11,7 @@ EXTRA_DIST += \ tools/qfcc/include/dot.h \ tools/qfcc/include/emit.h \ tools/qfcc/include/expr.h \ + tools/qfcc/include/expr_names.h \ tools/qfcc/include/flow.h \ tools/qfcc/include/function.h \ tools/qfcc/include/grab.h \ @@ -32,4 +33,5 @@ EXTRA_DIST += \ tools/qfcc/include/switch.h \ tools/qfcc/include/symtab.h \ tools/qfcc/include/type.h \ - tools/qfcc/include/value.h + tools/qfcc/include/value.h \ + tools/qfcc/include/vec_types.h From e58d53d4b6145a8daecf93405c323bed12450b05 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 19:30:50 +0900 Subject: [PATCH 2450/3664] [gamecode] Pass gcc's purity test again I guess maybe that change might make a bigger difference than I thought, gcc wasn't happy with it. --- libs/console/bi_inputline.c | 2 +- libs/ruamoko/rua_hash.c | 2 +- libs/ruamoko/rua_mersenne.c | 2 +- libs/ruamoko/rua_msgbuf.c | 2 +- libs/ruamoko/rua_plist.c | 2 +- libs/ruamoko/rua_qfile.c | 2 +- libs/ruamoko/rua_set.c | 4 ++-- libs/video/renderer/r_progs.c | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index 1399319e5..c0da2c4e3 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -102,7 +102,7 @@ bi_il_clear (progs_t *pr, void *_res) il_data_reset (res); } -static il_data_t * +static il_data_t * __attribute__((pure)) get_inputline (progs_t *pr, il_resources_t *res, int arg, const char *func) { il_data_t *line = il_data_get (res, arg); diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index c7ca65322..6f8b74547 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -177,7 +177,7 @@ bi_Hash_NewTable (progs_t *pr, void *_res) R_INT (pr) = table_index (res, ht); } -static bi_hashtab_t * +static bi_hashtab_t * __attribute__((pure)) get_table (progs_t *pr, hash_resources_t *res, const char *name, int index) { bi_hashtab_t *ht = table_get (res, index); diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c index 8cb854dc3..83be30604 100644 --- a/libs/ruamoko/rua_mersenne.c +++ b/libs/ruamoko/rua_mersenne.c @@ -89,7 +89,7 @@ bi_mtwist_new (progs_t *pr, void *_res) R_INT (pr) = state_index (res, mt); } -static mtstate_t * +static mtstate_t * __attribute__((pure)) get_state (progs_t *pr, mtwist_resources_t *res, const char *name, int index) { mtstate_t *mt = state_get (res, index); diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index 23959a2cf..d3ad525ab 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -110,7 +110,7 @@ alloc_msgbuf (msgbuf_resources_t *res, byte *buf, int size) return msgbuf_index (res, msgbuf); } -static msgbuf_t * +static msgbuf_t * __attribute__((pure)) get_msgbuf (progs_t *pr, msgbuf_resources_t *res, const char *name, int msgbuf) { msgbuf_t *mb = msgbuf_get (res, msgbuf); diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index b07e365a6..c2b7414d3 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -142,7 +142,7 @@ plist_free_handle (plist_resources_t *res, bi_plist_t *plist) plist_free (res, plist); } -static always_inline bi_plist_t * +static always_inline bi_plist_t * __attribute__((pure)) get_plist (progs_t *pr, plist_resources_t *res, const char *name, int handle) { bi_plist_t *plist = plist_get (res, handle); diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index 89df29a33..ef748b914 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -158,7 +158,7 @@ bi_Qopen (progs_t *pr, void *_res) Qclose (file); } -static qfile_t * +static qfile_t * __attribute__((pure)) get_handle (progs_t *pr, qfile_resources_t *res, const char *name, int handle) { qfile_t *h = handle_get (res, handle); diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index b6ee26f4d..40ed15d12 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -136,7 +136,7 @@ res_set_iter_index (set_resources_t *res, bi_set_iter_t *set_iter) return PR_RESINDEX(res->set_iter_map, set_iter); } -static bi_set_t * +static bi_set_t * __attribute__((pure)) get_set (progs_t *pr, set_resources_t *res, const char *name, int index) { bi_set_t *set = res_set_get (res, index); @@ -146,7 +146,7 @@ get_set (progs_t *pr, set_resources_t *res, const char *name, int index) return set; } -static bi_set_iter_t * +static bi_set_iter_t * __attribute__((pure)) get_set_iter (progs_t *pr, set_resources_t *res, const char *name, int index) { bi_set_iter_t *set = res_set_iter_get (res, index); diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index ef2e5b403..c83adb15c 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -107,7 +107,7 @@ qpic_index (draw_resources_t *res, qpic_res_t *qp) return PR_RESINDEX (res->qpic_map, qp); } -static qpic_res_t * +static qpic_res_t * __attribute__((pure)) get_qpic (progs_t *pr, draw_resources_t *res, const char *name, int qpic_handle) { qpic_res_t *qp = qpic_get (res, qpic_handle); From f0c35e541a217c7087d0e8e22cab280f2cf9f407 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 19:56:56 +0900 Subject: [PATCH 2451/3664] [ruamoko] Pass some more purity tests Separate because I want to cherry-pick the other commit. --- libs/ruamoko/rua_scene.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 1ea641781..4c7d7551e 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -75,7 +75,7 @@ rua_scene_free (scene_resources_t *res, rua_scene_t *scene) PR_RESFREE (res->scene_map, scene); } -static rua_scene_t * +static rua_scene_t * __attribute__((pure)) rua__scene_get (scene_resources_t *res, int id, const char *name) { rua_scene_t *scene = PR_RESGET (res->scene_map, id); @@ -88,7 +88,7 @@ rua__scene_get (scene_resources_t *res, int id, const char *name) } #define rua_scene_get(res, id) rua__scene_get(res, id, __FUNCTION__) -static entity_t * +static entity_t * __attribute__((pure)) rua__entity_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) { entity_t *ent = Scene_GetEntity (scene->scene, id); @@ -100,7 +100,7 @@ rua__entity_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) } #define rua_entity_get(pr, scene, id) rua__entity_get(pr, scene, id, __FUNCTION__) -static int +static int __attribute__((pure)) rua_scene_index (scene_resources_t *res, rua_scene_t *scene) { return PR_RESINDEX (res->scene_map, scene); From ba3879c6e03d5b4c2f61d1ff25393570e9bb7332 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 20:01:36 +0900 Subject: [PATCH 2452/3664] [scene] Make transforms owned by the scene This actually has at least two benefits: the transform id is managed by the scene and thus does not need separate management by the Ruamoko wrapper functions, and better memory handling of the transform objects. Another benefit that isn't realized yet is that this is a step towards breaking the renderers free of quake and quakeworld: although the clients don't actually use the scene yet, it will be a good place to store the rendering information (functions to run, etc). --- include/Makemodule.am | 1 + include/QF/scene/scene.h | 2 +- include/QF/scene/transform.h | 6 +- include/scn_internal.h | 14 +++++ libs/client/cl_temp_entities.c | 6 +- libs/scene/hierarchy.c | 13 ++-- libs/scene/scene.c | 6 +- libs/scene/test/test-hierarchy.c | 103 +++++++++++++++++-------------- libs/scene/transform.c | 18 ++++-- 9 files changed, 102 insertions(+), 67 deletions(-) create mode 100644 include/scn_internal.h diff --git a/include/Makemodule.am b/include/Makemodule.am index d405b745c..40c448f33 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -70,6 +70,7 @@ EXTRA_DIST += \ include/rua_internal.h \ include/sbar.h \ include/skin_stencil.h \ + include/scn_internal.h \ include/snd_internal.h \ include/sv_console.h \ include/varrays.h \ diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index c55ae8f35..e6262c008 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -48,7 +48,7 @@ typedef struct scene_s { scene_t *Scene_NewScene (void); void Scene_DeleteScene (scene_t *scene); struct entity_s *Scene_CreateEntity (scene_t *scene); -struct entity_s *Scene_GetEntity (scene_t *scene, int id); +struct entity_s *Scene_GetEntity (scene_t *scene, int id) __attribute__((pure)); void Scene_DestroyEntity (scene_t *scene, struct entity_s *entity); void Scene_FreeAllEntities (scene_t *scene); diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index fde6899ad..b9a909937 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -43,14 +43,16 @@ typedef struct transform_s { struct hierarchy_s *hierarchy; + struct scene_s *scene; ///< owning scene uint32_t index; ///< index in hierarchy int32_t id; ///< scene id } transform_t; -transform_t *Transform_New (transform_t *parent); +transform_t *Transform_New (struct scene_s *scene, transform_t *parent); /* Deletes all child transforms, and transform names */ void Transform_Delete (transform_t *transform); -transform_t *Transform_NewNamed (transform_t *parent, const char *name); +transform_t *Transform_NewNamed (struct scene_s *scene, transform_t *parent, + const char *name); uint32_t Transform_ChildCount (const transform_t *transform) __attribute__((pure)); transform_t *Transform_GetChild (const transform_t *transform, uint32_t childIndex) __attribute__((pure)); diff --git a/include/scn_internal.h b/include/scn_internal.h new file mode 100644 index 000000000..14faaa3ed --- /dev/null +++ b/include/scn_internal.h @@ -0,0 +1,14 @@ +#ifndef __scn_internal_h +#define __scn_internal_h + +#include "QF/progs.h" +#include "QF/scene/entity.h" +#include "QF/scene/scene.h" +#include "QF/scene/transform.h" + +typedef struct scene_resources_s { + PR_RESMAP (entity_t) entities; + PR_RESMAP (transform_t) transforms; +} scene_resources_t; + +#endif//__scn_internal_h diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 9ce856d70..7683586d7 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -46,6 +46,7 @@ #include "QF/plugin/vid_render.h" //FIXME #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "client/effects.h" #include "client/entities.h" @@ -85,6 +86,7 @@ typedef struct tent_obj_s { static PR_RESMAP (tent_t) temp_entities; static PR_RESMAP (tent_obj_t) tent_objects; +static scene_t *scene; static tent_obj_t *cl_beams; static tent_obj_t *cl_explosions; @@ -135,6 +137,8 @@ CL_TEnts_Precache (int phase) void CL_TEnts_Init (void) { + scene = Scene_NewScene (); + QFS_GamedirCallback (CL_TEnts_Precache); CL_TEnts_Precache (1); for (int i = 0; i < 360; i++) { @@ -151,7 +155,7 @@ CL_Init_Entity (entity_t *ent) } memset (ent, 0, sizeof (*ent)); - ent->transform = Transform_New (0); + ent->transform = Transform_New (scene, 0); ent->renderer.skin = 0; QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); ent->animation.pose1 = ent->animation.pose2 = -1; diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 43c3ea598..2e7ccaf47 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -38,6 +38,8 @@ #include "QF/scene/hierarchy.h" #include "QF/scene/transform.h" +#include "scn_internal.h" + #if defined(_WIN32) && !defined(_WIN64) // FIXME (maybe) this is a hack to make DARRAY arrrays 16-byte aligned on // 32-bit systems (in particular for this case, windows) as the vectors and @@ -430,11 +432,12 @@ Hierarchy_New (size_t grow, int createRoot) void Hierarchy_Delete (hierarchy_t *hierarchy) { - for (size_t i = 0; i < hierarchy->transform.size; i++) { - free (hierarchy->transform.a[i]); - } - for (size_t i = 0; i < hierarchy->name.size; i++) { - free (hierarchy->name.a[i]); + if (hierarchy->transform.size) { + scene_resources_t *res = hierarchy->transform.a[0]->scene->resources; + + for (size_t i = 0; i < hierarchy->transform.size; i++) { + PR_RESFREE (res->transforms, hierarchy->transform.a[i]); + } } DARRAY_CLEAR (&hierarchy->transform); DARRAY_CLEAR (&hierarchy->entity); diff --git a/libs/scene/scene.c b/libs/scene/scene.c index b7bc2d50b..10cfb3237 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -42,9 +42,7 @@ #include "QF/scene/scene.h" #include "QF/scene/transform.h" -typedef struct scene_resources_s { - PR_RESMAP (entity_t) entities; -} scene_resources_t; +#include "scn_internal.h" scene_t * Scene_NewScene (void) @@ -84,7 +82,7 @@ Scene_CreateEntity (scene_t *scene) scene_resources_t *res = scene->resources; entity_t *ent = PR_RESNEW_NC (res->entities); - ent->transform = Transform_New (0); + ent->transform = Transform_New (scene, 0); ent->id = PR_RESINDEX (res->entities, ent); hierarchy_t *h = ent->transform->hierarchy; diff --git a/libs/scene/test/test-hierarchy.c b/libs/scene/test/test-hierarchy.c index b6a3c0ca8..c8adb529e 100644 --- a/libs/scene/test/test-hierarchy.c +++ b/libs/scene/test/test-hierarchy.c @@ -7,8 +7,11 @@ #include #include "QF/scene/hierarchy.h" +#include "QF/scene/scene.h" #include "QF/scene/transform.h" +scene_t *scene; + // NOTE: these are the columns of the matrix! (not that it matters for a // symmetrical matrix, but...) mat4f_t identity = { @@ -112,7 +115,7 @@ check_indices (transform_t *transform, uint32_t index, uint32_t parentIndex, static int test_single_transform (void) { - transform_t *transform = Transform_New (0); + transform_t *transform = Transform_New (scene, 0); hierarchy_t *h; if (!transform) { @@ -149,8 +152,8 @@ test_single_transform (void) static int test_parent_child_init (void) { - transform_t *parent = Transform_New (0); - transform_t *child = Transform_New (parent); + transform_t *parent = Transform_New (scene, 0); + transform_t *child = Transform_New (scene, parent); if (parent->hierarchy != child->hierarchy) { printf ("parent and child transforms have separate hierarchies\n"); @@ -200,8 +203,8 @@ test_parent_child_init (void) static int test_parent_child_setparent (void) { - transform_t *parent = Transform_New (0); - transform_t *child = Transform_New (0); + transform_t *parent = Transform_New (scene, 0); + transform_t *child = Transform_New (scene, 0); Transform_SetName (parent, "parent"); Transform_SetName (child, "child"); @@ -267,17 +270,17 @@ test_build_hierarchy (void) { printf ("test_build_hierarchy\n"); - transform_t *root = Transform_NewNamed (0, "root"); - transform_t *A = Transform_NewNamed (root, "A"); - transform_t *B = Transform_NewNamed (root, "B"); - transform_t *C = Transform_NewNamed (root, "C"); + transform_t *root = Transform_NewNamed (scene, 0, "root"); + transform_t *A = Transform_NewNamed (scene, root, "A"); + transform_t *B = Transform_NewNamed (scene, root, "B"); + transform_t *C = Transform_NewNamed (scene, root, "C"); if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } if (!check_indices (A, 1, 0, 4, 0)) { return 1; } if (!check_indices (B, 2, 0, 4, 0)) { return 1; } if (!check_indices (C, 3, 0, 4, 0)) { return 1; } - transform_t *B1 = Transform_NewNamed (B, "B1"); + transform_t *B1 = Transform_NewNamed (scene, B, "B1"); if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 0)) { return 1; } @@ -285,7 +288,7 @@ test_build_hierarchy (void) if (!check_indices ( C, 3, 0, 5, 0)) { return 1; } if (!check_indices (B1, 4, 2, 5, 0)) { return 1; } - transform_t *A1 = Transform_NewNamed (A, "A1"); + transform_t *A1 = Transform_NewNamed (scene, A, "A1"); if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 1)) { return 1; } @@ -293,11 +296,11 @@ test_build_hierarchy (void) if (!check_indices ( C, 3, 0, 6, 0)) { return 1; } if (!check_indices (A1, 4, 1, 6, 0)) { return 1; } if (!check_indices (B1, 5, 2, 6, 0)) { return 1; } - transform_t *A1a = Transform_NewNamed (A1, "A1a"); - transform_t *B2 = Transform_NewNamed (B, "B2"); - transform_t *A2 = Transform_NewNamed (A, "A2"); - transform_t *B3 = Transform_NewNamed (B, "B3"); - transform_t *B2a = Transform_NewNamed (B2, "B2a"); + transform_t *A1a = Transform_NewNamed (scene, A1, "A1a"); + transform_t *B2 = Transform_NewNamed (scene, B, "B2"); + transform_t *A2 = Transform_NewNamed (scene, A, "A2"); + transform_t *B3 = Transform_NewNamed (scene, B, "B3"); + transform_t *B2a = Transform_NewNamed (scene, B2, "B2a"); if (!check_hierarchy_size (root->hierarchy, 11)) { return 1; } @@ -313,7 +316,7 @@ test_build_hierarchy (void) if (!check_indices (A1a, 9, 4, 11, 0)) { return 1; } if (!check_indices (B2a, 10, 7, 11, 0)) { return 1; } - transform_t *D = Transform_NewNamed (root, "D"); + transform_t *D = Transform_NewNamed (scene, root, "D"); if (!check_hierarchy_size (root->hierarchy, 12)) { return 1; } @@ -331,7 +334,7 @@ test_build_hierarchy (void) if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; } dump_hierarchy (root->hierarchy); - transform_t *C1 = Transform_NewNamed (C, "C1"); + transform_t *C1 = Transform_NewNamed (scene, C, "C1"); dump_hierarchy (root->hierarchy); if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; } @@ -360,19 +363,19 @@ test_build_hierarchy2 (void) { printf ("test_build_hierarchy2\n"); - transform_t *root = Transform_NewNamed (0, "root"); - transform_t *A = Transform_NewNamed (root, "A"); - transform_t *B = Transform_NewNamed (root, "B"); - transform_t *C = Transform_NewNamed (root, "C"); - transform_t *B1 = Transform_NewNamed (B, "B1"); - transform_t *A1 = Transform_NewNamed (A, "A1"); - transform_t *A1a = Transform_NewNamed (A1, "A1a"); - transform_t *B2 = Transform_NewNamed (B, "B2"); - transform_t *A2 = Transform_NewNamed (A, "A2"); - transform_t *B3 = Transform_NewNamed (B, "B3"); - transform_t *B2a = Transform_NewNamed (B2, "B2a"); - transform_t *D = Transform_NewNamed (root, "D"); - transform_t *C1 = Transform_NewNamed (C, "C1"); + transform_t *root = Transform_NewNamed (scene, 0, "root"); + transform_t *A = Transform_NewNamed (scene, root, "A"); + transform_t *B = Transform_NewNamed (scene, root, "B"); + transform_t *C = Transform_NewNamed (scene, root, "C"); + transform_t *B1 = Transform_NewNamed (scene, B, "B1"); + transform_t *A1 = Transform_NewNamed (scene, A, "A1"); + transform_t *A1a = Transform_NewNamed (scene, A1, "A1a"); + transform_t *B2 = Transform_NewNamed (scene, B, "B2"); + transform_t *A2 = Transform_NewNamed (scene, A, "A2"); + transform_t *B3 = Transform_NewNamed (scene, B, "B3"); + transform_t *B2a = Transform_NewNamed (scene, B2, "B2a"); + transform_t *D = Transform_NewNamed (scene, root, "D"); + transform_t *C1 = Transform_NewNamed (scene, C, "C1"); if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; } @@ -390,18 +393,18 @@ test_build_hierarchy2 (void) if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } - transform_t *T = Transform_NewNamed (0, "T"); - transform_t *X = Transform_NewNamed (T, "X"); - transform_t *Y = Transform_NewNamed (T, "Y"); - transform_t *Z = Transform_NewNamed (T, "Z"); - transform_t *Y1 = Transform_NewNamed (Y, "Y1"); - transform_t *X1 = Transform_NewNamed (X, "X1"); - transform_t *X1a = Transform_NewNamed (X1, "X1a"); - transform_t *Y2 = Transform_NewNamed (Y, "Y2"); - transform_t *X2 = Transform_NewNamed (X, "X2"); - transform_t *Y3 = Transform_NewNamed (Y, "Y3"); - transform_t *Y2a = Transform_NewNamed (Y2, "Y2a"); - transform_t *Z1 = Transform_NewNamed (Z, "Z1"); + transform_t *T = Transform_NewNamed (scene, 0, "T"); + transform_t *X = Transform_NewNamed (scene, T, "X"); + transform_t *Y = Transform_NewNamed (scene, T, "Y"); + transform_t *Z = Transform_NewNamed (scene, T, "Z"); + transform_t *Y1 = Transform_NewNamed (scene, Y, "Y1"); + transform_t *X1 = Transform_NewNamed (scene, X, "X1"); + transform_t *X1a = Transform_NewNamed (scene, X1, "X1a"); + transform_t *Y2 = Transform_NewNamed (scene, Y, "Y2"); + transform_t *X2 = Transform_NewNamed (scene, X, "X2"); + transform_t *Y3 = Transform_NewNamed (scene, Y, "Y3"); + transform_t *Y2a = Transform_NewNamed (scene, Y2, "Y2a"); + transform_t *Z1 = Transform_NewNamed (scene, Z, "Z1"); dump_hierarchy (T->hierarchy); if (!check_hierarchy_size (T->hierarchy, 12)) { return 1; } @@ -510,11 +513,11 @@ check_vector (const transform_t *transform, static int test_frames (void) { - transform_t *root = Transform_NewNamed (0, "root"); - transform_t *A = Transform_NewNamed (root, "A"); - transform_t *B = Transform_NewNamed (root, "B"); - transform_t *A1 = Transform_NewNamed (A, "A1"); - transform_t *B1 = Transform_NewNamed (B, "B1"); + transform_t *root = Transform_NewNamed (scene, 0, "root"); + transform_t *A = Transform_NewNamed (scene, root, "A"); + transform_t *B = Transform_NewNamed (scene, root, "B"); + transform_t *A1 = Transform_NewNamed (scene, A, "A1"); + transform_t *B1 = Transform_NewNamed (scene, B, "B1"); Transform_SetLocalPosition (root, (vec4f_t) { 0, 0, 1, 1 }); Transform_SetLocalPosition (A, (vec4f_t) { 1, 0, 0, 1 }); @@ -699,6 +702,8 @@ test_frames (void) int main (void) { + scene = Scene_NewScene (); + if (test_single_transform ()) { return 1; } if (test_parent_child_init ()) { return 1; } if (test_parent_child_setparent ()) { return 1; } @@ -706,5 +711,7 @@ main (void) if (test_build_hierarchy2 ()) { return 1; } if (test_frames ()) { return 1; } + Scene_DeleteScene (scene); + return 0; } diff --git a/libs/scene/transform.c b/libs/scene/transform.c index 5983d83bb..dbb2a6009 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -36,13 +36,19 @@ #endif #include "QF/scene/hierarchy.h" +#include "QF/scene/scene.h" #include "QF/scene/transform.h" -transform_t * -Transform_New (transform_t *parent) -{ - transform_t *transform = malloc (sizeof (transform_t)); +#include "scn_internal.h" +transform_t * +Transform_New (scene_t *scene, transform_t *parent) +{ + scene_resources_t *res = scene->resources; + transform_t *transform = PR_RESNEW_NC (res->transforms); + + transform->scene = scene; + transform->id = PR_RESINDEX (res->transforms, transform); if (parent) { transform->hierarchy = parent->hierarchy; transform->index = Hierarchy_InsertHierarchy (parent->hierarchy, 0, @@ -68,9 +74,9 @@ Transform_Delete (transform_t *transform) } transform_t * -Transform_NewNamed (transform_t *parent, const char *name) +Transform_NewNamed (scene_t *scene, transform_t *parent, const char *name) { - transform_t *transform = Transform_New (parent); + transform_t *transform = Transform_New (scene, parent); Transform_SetName (transform, name); return transform; } From 54f0af854b621957d5087a787a064d139f49c69f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Feb 2022 00:06:39 +0900 Subject: [PATCH 2453/3664] [ruamoko] Wrap the transform fuctions Except for get/set name as I'm still pondering strings. --- include/QF/scene/scene.h | 1 + libs/ruamoko/rua_scene.c | 280 +++++++++++++++++++++++++++++++++++++++ libs/scene/scene.c | 7 + 3 files changed, 288 insertions(+) diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index e6262c008..ea51c44b5 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -49,6 +49,7 @@ scene_t *Scene_NewScene (void); void Scene_DeleteScene (scene_t *scene); struct entity_s *Scene_CreateEntity (scene_t *scene); struct entity_s *Scene_GetEntity (scene_t *scene, int id) __attribute__((pure)); +struct transform_s *Scene_GetTransform (scene_t *scene, int id) __attribute__((pure)); void Scene_DestroyEntity (scene_t *scene, struct entity_s *entity); void Scene_FreeAllEntities (scene_t *scene); diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 4c7d7551e..ec021db37 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -100,6 +100,19 @@ rua__entity_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) } #define rua_entity_get(pr, scene, id) rua__entity_get(pr, scene, id, __FUNCTION__) +static transform_t * __attribute__((pure)) +rua__transform_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) +{ + transform_t *transform = Scene_GetTransform (scene->scene, id); + + if (!transform) { + PR_RunError (pr, "invalid transform passed to %s", name + 3); + } + return transform; +} +#define rua_transform_get(pr, scene, id) \ + rua__transform_get(pr, scene, id, __FUNCTION__) + static int __attribute__((pure)) rua_scene_index (scene_resources_t *res, rua_scene_t *scene) { @@ -169,6 +182,241 @@ bi_Entity_GetTransform (progs_t *pr, void *_res) R_INT (pr) = ent->transform->id; } +static void +bi_Transform_ChildCount (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + + R_UINT (pr) = Transform_ChildCount (transform); +} + +static void +bi_Transform_GetChild (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *child = Transform_GetChild (transform, P_UINT (pr, 2)); + + R_UINT (pr) = child ? child->id : 0; +} + +static void +bi_Transform_SetParent (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *parent = rua_transform_get (pr, scene, P_INT (pr, 2)); + + Transform_SetParent (transform, parent); +} + +static void +bi_Transform_GetParent (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *parent = Transform_GetParent (transform); + + R_INT (pr) = parent ? parent->id : 0; +} + +static void +bi_Transform_SetTag (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + pr_uint_t tag = P_UINT (pr, 2); + Transform_SetTag (transform, tag); +} + +static void +bi_Transform_GetTag (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + + R_UINT (pr) = Transform_GetTag (transform); +} + +static void +bi_Transform_GetLocalMatrix (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_GetLocalMatrix (transform, &R_PACKED (pr, pr_vec4_t)); +} + +static void +bi_Transform_GetLocalInverse (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_GetLocalInverse (transform, &R_PACKED (pr, pr_vec4_t)); +} + +static void +bi_Transform_GetWorldMatrix (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_GetWorldMatrix (transform, &R_PACKED (pr, pr_vec4_t)); +} + +static void +bi_Transform_GetWorldInverse (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_GetWorldInverse (transform, &R_PACKED (pr, pr_vec4_t)); +} + +static void +bi_Transform_SetLocalPosition (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_SetLocalPosition (transform, P_PACKED (pr, pr_vec4_t, 2)); +} + +static void +bi_Transform_GetLocalPosition (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + R_PACKED (pr, pr_vec4_t) = Transform_GetLocalPosition (transform); +} + +static void +bi_Transform_SetLocalRotation (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_SetLocalRotation (transform, P_PACKED (pr, pr_vec4_t, 2)); +} + +static void +bi_Transform_GetLocalRotation (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + R_PACKED (pr, pr_vec4_t) = Transform_GetLocalRotation (transform); +} + +static void +bi_Transform_SetLocalScale (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_SetLocalScale (transform, P_PACKED (pr, pr_vec4_t, 2)); +} + +static void +bi_Transform_GetLocalScale (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + R_PACKED (pr, pr_vec4_t) = Transform_GetLocalScale (transform); +} + +static void +bi_Transform_SetWorldPosition (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_SetWorldPosition (transform, P_PACKED (pr, pr_vec4_t, 2)); +} + +static void +bi_Transform_GetWorldPosition (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + R_PACKED (pr, pr_vec4_t) = Transform_GetWorldPosition (transform); +} + +static void +bi_Transform_SetWorldRotation (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_SetWorldRotation (transform, P_PACKED (pr, pr_vec4_t, 2)); +} + +static void +bi_Transform_GetWorldRotation (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + R_PACKED (pr, pr_vec4_t) = Transform_GetWorldRotation (transform); +} + +static void +bi_Transform_GetWorldScale (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + R_PACKED (pr, pr_vec4_t) = Transform_GetWorldScale (transform); +} + +static void +bi_Transform_SetLocalTransform (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + Transform_SetLocalTransform (transform, P_PACKED (pr, pr_vec4_t, 2), + P_PACKED (pr, pr_vec4_t, 3), P_PACKED (pr, pr_vec4_t, 4)); +} + +static void +bi_Transform_Forward (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + R_PACKED (pr, pr_vec4_t) = Transform_Forward (transform); +} + +static void +bi_Transform_Right (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + R_PACKED (pr, pr_vec4_t) = Transform_Right (transform); +} + +static void +bi_Transform_Up (progs_t *pr, void *_res) +{ + scene_resources_t *res = _res; + rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + R_PACKED (pr, pr_vec4_t) = Transform_Up (transform); +} + #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} @@ -180,6 +428,38 @@ static builtin_t builtins[] = { bi(Entity_GetTransform, 2, p(ptr), p(ptr)), + bi(Transform_ChildCount, 2, p(ptr), p(ptr)), + bi(Transform_GetChild, 3, p(ptr), p(ptr), p(int)), + bi(Transform_SetParent, 3, p(ptr), p(ptr), p(ptr)), + bi(Transform_GetParent, 2, p(ptr), p(ptr)), + + bi(Transform_SetTag, 3, p(ptr), p(ptr), p(uint)), + bi(Transform_GetTag, 2, p(ptr), p(ptr)), + + bi(Transform_GetLocalMatrix, 2, p(ptr), p(ptr)), + bi(Transform_GetLocalInverse, 2, p(ptr), p(ptr)), + bi(Transform_GetWorldMatrix, 2, p(ptr), p(ptr)), + bi(Transform_GetWorldInverse, 2, p(ptr), p(ptr)), + + bi(Transform_SetLocalPosition, 3, p(ptr), p(ptr), p(vec4)), + bi(Transform_GetLocalPosition, 2, p(ptr), p(ptr)), + bi(Transform_SetLocalRotation, 3, p(ptr), p(ptr), p(vec4)), + bi(Transform_GetLocalRotation, 2, p(ptr), p(ptr)), + bi(Transform_SetLocalScale, 3, p(ptr), p(ptr), p(vec4)), + bi(Transform_GetLocalScale, 2, p(ptr), p(ptr)), + + bi(Transform_SetWorldPosition, 3, p(ptr), p(ptr), p(vec4)), + bi(Transform_GetWorldPosition, 2, p(ptr), p(ptr)), + bi(Transform_SetWorldRotation, 3, p(ptr), p(ptr), p(vec4)), + bi(Transform_GetWorldRotation, 2, p(ptr), p(ptr)), + bi(Transform_GetWorldScale, 2, p(ptr), p(ptr)), + + bi(Transform_SetLocalTransform, 5, p(ptr), p(ptr), + p(vec4), p(vec4), p(vec4)), + bi(Transform_Forward, 2, p(ptr), p(ptr)), + bi(Transform_Right, 2, p(ptr), p(ptr)), + bi(Transform_Up, 2, p(ptr), p(ptr)), + {0} }; diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 10cfb3237..933be0db5 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -157,3 +157,10 @@ Scene_FreeAllEntities (scene_t *scene) scene_resources_t *res = scene->resources; PR_RESRESET (res->entities); } + +transform_t * +Scene_GetTransform (scene_t *scene, int id) +{ + scene_resources_t *res = scene->resources; + return PR_RESGET (res->transforms, id); +} From 4f436e8245e5fb83c936baa97103906d48822ee7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Feb 2022 06:46:01 +0900 Subject: [PATCH 2454/3664] [scene] Correct a comment While the plethora of orientations for a reference frame is somewhat annoying, having an incorrect description of the frame is much more annoying. --- include/QF/scene/transform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index b9a909937..3a7b11b74 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -81,7 +81,7 @@ void Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation); vec4f_t Transform_GetWorldScale (const transform_t *transform) __attribute__((pure)); void Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, vec4f_t rotation, vec4f_t position); -// NOTE: these use X: right, Y: forward, Z:up +// NOTE: these use X: forward, -Y: right, Z:up // aslo, not guaranteed to be normalized or even orthogonal vec4f_t Transform_Forward (const transform_t *transform) __attribute__((pure)); vec4f_t Transform_Right (const transform_t *transform) __attribute__((pure)); From 70af3625620bc1e94434cab7083559a1c4904fd2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Feb 2022 08:39:20 +0900 Subject: [PATCH 2455/3664] [qfcc] Unify temp def, return value and parameter sizes In working with vectors and matrices while testing the scene wrappers, I found that there was a fair bit of confusion about how large something could be. Return values can be up to 32 words (but qfcc wasn't aware of that), parameters were limited to 4 words still (and possibly should be for varargs), and temp defs were limited to 8 words (1 lvec4). Temps are used for handling return values (at least when not optimizing) and thus must be capable of holding a return value, and passing large arguments through *formal* parameters should be allowed. It seems reasonable to limit parameter sizes to return value sizes. A temp and a move are still used for large return values (4x4 matrix), but that's an optimization issue: the code itself is at least correct. --- tools/qfcc/include/function.h | 4 +++- tools/qfcc/source/expr.c | 6 ++++-- tools/qfcc/source/function.c | 20 +++++++++++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 83b455555..15f32ddc3 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -41,7 +41,8 @@ #include "def.h" -#define MAX_DEF_SIZE ((int)PR_SIZEOF(lvec4)) +// The maximum size of a temp def, return value, or parameter value +#define MAX_DEF_SIZE 32 /** Represent an overloading of a function. @@ -152,6 +153,7 @@ param_t *check_params (param_t *params); enum storage_class_e; struct defspace_s; +int value_too_large (struct type_s *val_type) __attribute__((const)); void make_function (struct symbol_s *sym, const char *nice_name, struct defspace_s *space, enum storage_class_e storage); struct symbol_s *function_symbol (struct symbol_s *sym, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 65eeb2468..746a94f03 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2197,12 +2197,14 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) return e; } - if (!type_size (t)) + if (!type_size (t)) { err = error (e, "type of formal parameter %d is incomplete", i + 1); - if (type_size (t) > type_size (&type_param)) + } + if (value_too_large (t)) { err = error (e, "formal parameter %d is too large to be passed by" " value", i + 1); + } if (i < param_count) { if (e->type == ex_nil) convert_nil (e, t = ftype->t.func.param_types[i]); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index e9371ea81..d8642d588 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -459,6 +459,18 @@ find_function (expr_t *fexpr, expr_t *params) return fexpr; } +int +value_too_large (type_t *val_type) +{ + if ((options.code.progsversion < PROG_VERSION + && type_size (val_type) > type_size (&type_param)) + || (options.code.progsversion == PROG_VERSION + && type_size (val_type) > MAX_DEF_SIZE)) { + return 1; + } + return 0; +} + static void check_function (symbol_t *fsym) { @@ -470,7 +482,7 @@ check_function (symbol_t *fsym) error (0, "return type is an incomplete type"); fsym->type->t.func.type = &type_void;//FIXME better type? } - if (type_size (fsym->type->t.func.type) > type_size (&type_param)) { + if (value_too_large (fsym->type->t.func.type)) { error (0, "return value too large to be passed by value (%d)", type_size (&type_param)); fsym->type->t.func.type = &type_void;//FIXME better type? @@ -480,12 +492,14 @@ check_function (symbol_t *fsym) continue; // ellipsis marker if (!p->type) continue; // non-param selector - if (!type_size (p->type)) + if (!type_size (p->type)) { error (0, "parameter %d (‘%s’) has incomplete type", i + 1, p->name); - if (type_size (p->type) > type_size (&type_param)) + } + if (value_too_large (p->type)) { error (0, "param %d (‘%s’) is too large to be passed by value", i + 1, p->name); + } } } From 550c0712d8b2f83bef6ad355130e0d70c2f13753 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 19:28:19 +0900 Subject: [PATCH 2456/3664] Fix a bunch of distcheck issues --- config.d/build_control.m4 | 2 ++ include/QF/Makemodule.am | 4 +++- libs/gamecode/Makemodule.am | 2 +- libs/gamecode/test/Makemodule.am | 2 +- tools/qfcc/include/Makemodule.am | 4 +++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index f3e59d2d5..fb0b60951 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -329,6 +329,7 @@ if test x"${top_need_libs}" = xyes; then qfac_include_qf_input="\$(include_qf_input)" qfac_include_qf_math="\$(include_qf_math)" qfac_include_qf_plugin="\$(include_qf_plugin)" + qfac_include_qf_progs="\$(include_qf_progs)" qfac_include_qf_scene="\$(include_qf_scene)" qfac_include_qf_simd="\$(include_qf_simd)" qfac_include_qf_ui="\$(include_qf_ui)" @@ -340,6 +341,7 @@ QF_SUBST(qfac_include_qf_glsl) QF_SUBST(qfac_include_qf_input) QF_SUBST(qfac_include_qf_math) QF_SUBST(qfac_include_qf_plugin) +QF_SUBST(qfac_include_qf_progs) QF_SUBST(qfac_include_qf_scene) QF_SUBST(qfac_include_qf_simd) QF_SUBST(qfac_include_qf_ui) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index d36dd7ead..382e556e3 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -210,6 +210,7 @@ qf_glsl_includedir = $(includedir)/QF/GLSL qf_input_includedir = $(includedir)/QF/input qf_math_includedir = $(includedir)/QF/math qf_plugin_includedir = $(includedir)/QF/plugin +qf_progs_includedir = $(includedir)/QF/progs qf_scene_includedir = $(includedir)/QF/scene qf_simd_includedir = $(includedir)/QF/simd qf_ui_includedir = $(includedir)/QF/ui @@ -220,6 +221,7 @@ qf_glsl_include_HEADERS = @qfac_include_qf_glsl@ qf_input_include_HEADERS = @qfac_include_qf_input@ qf_math_include_HEADERS = @qfac_include_qf_math@ qf_plugin_include_HEADERS = @qfac_include_qf_plugin@ +qf_progs_include_HEADERS = @qfac_include_qf_progs@ qf_scene_include_HEADERS = @qfac_include_qf_scene@ qf_simd_include_HEADERS = @qfac_include_qf_simd@ qf_ui_include_HEADERS = @qfac_include_qf_ui@ @@ -232,7 +234,7 @@ ruamoko_qf_include_HEADERS = @qfac_qfcc_include_qf@ ruamoko_qf_input_include_HEADERS = @qfac_qfcc_include_qf_input@ ruamoko_qf_progs_include_HEADERS = @qfac_qfcc_include_qf_progs@ -EXTRA_HEADERS += \ +EXTRA_DIST += \ $(include_qf) \ $(include_qf_gl) \ $(include_qf_glsl) \ diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index dbffb47b3..411bfb645 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -21,7 +21,7 @@ libs_gamecode_libQFgamecode_la_SOURCES= \ libs/gamecode/pr_v6p_opcode.c \ libs/gamecode/pr_zone.c -noinst_PYTHON += $(opcodes_py) +noinst_PYTHON += $(opcodes_py) $(convert_py) $(hops_py) opcodes_py = $(srcdir)/libs/gamecode/opcodes.py pr_opcode_cinc = $(top_builddir)/libs/gamecode/pr_opcode.cinc diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 57793aa4f..2cfd9fbf9 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -35,7 +35,7 @@ TESTS += $(libs_gamecode_tests) check_PROGRAMS += $(libs_gamecode_tests) -EXTRA_DIST += head.c main.c +EXTRA_DIST += libs/gamecode/test/head.c libs/gamecode/test/main.c test_gamecode_libs= \ libs/gamecode/libQFgamecode.la \ diff --git a/tools/qfcc/include/Makemodule.am b/tools/qfcc/include/Makemodule.am index f6158b5c4..6609ddfc4 100644 --- a/tools/qfcc/include/Makemodule.am +++ b/tools/qfcc/include/Makemodule.am @@ -11,6 +11,7 @@ EXTRA_DIST += \ tools/qfcc/include/dot.h \ tools/qfcc/include/emit.h \ tools/qfcc/include/expr.h \ + tools/qfcc/include/expr_names.h \ tools/qfcc/include/flow.h \ tools/qfcc/include/function.h \ tools/qfcc/include/grab.h \ @@ -32,4 +33,5 @@ EXTRA_DIST += \ tools/qfcc/include/switch.h \ tools/qfcc/include/symtab.h \ tools/qfcc/include/type.h \ - tools/qfcc/include/value.h + tools/qfcc/include/value.h \ + tools/qfcc/include/vec_types.h From 4e229169ec85503973ccc4d005e9f730cc14a919 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Feb 2022 19:30:50 +0900 Subject: [PATCH 2457/3664] [gamecode] Pass gcc's purity test again I guess maybe that change might make a bigger difference than I thought, gcc wasn't happy with it. --- libs/console/bi_inputline.c | 2 +- libs/ruamoko/rua_hash.c | 2 +- libs/ruamoko/rua_mersenne.c | 2 +- libs/ruamoko/rua_msgbuf.c | 2 +- libs/ruamoko/rua_plist.c | 2 +- libs/ruamoko/rua_qfile.c | 2 +- libs/ruamoko/rua_set.c | 4 ++-- libs/video/renderer/r_progs.c | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index 1399319e5..c0da2c4e3 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -102,7 +102,7 @@ bi_il_clear (progs_t *pr, void *_res) il_data_reset (res); } -static il_data_t * +static il_data_t * __attribute__((pure)) get_inputline (progs_t *pr, il_resources_t *res, int arg, const char *func) { il_data_t *line = il_data_get (res, arg); diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index c7ca65322..6f8b74547 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -177,7 +177,7 @@ bi_Hash_NewTable (progs_t *pr, void *_res) R_INT (pr) = table_index (res, ht); } -static bi_hashtab_t * +static bi_hashtab_t * __attribute__((pure)) get_table (progs_t *pr, hash_resources_t *res, const char *name, int index) { bi_hashtab_t *ht = table_get (res, index); diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c index 8cb854dc3..83be30604 100644 --- a/libs/ruamoko/rua_mersenne.c +++ b/libs/ruamoko/rua_mersenne.c @@ -89,7 +89,7 @@ bi_mtwist_new (progs_t *pr, void *_res) R_INT (pr) = state_index (res, mt); } -static mtstate_t * +static mtstate_t * __attribute__((pure)) get_state (progs_t *pr, mtwist_resources_t *res, const char *name, int index) { mtstate_t *mt = state_get (res, index); diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index 23959a2cf..d3ad525ab 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -110,7 +110,7 @@ alloc_msgbuf (msgbuf_resources_t *res, byte *buf, int size) return msgbuf_index (res, msgbuf); } -static msgbuf_t * +static msgbuf_t * __attribute__((pure)) get_msgbuf (progs_t *pr, msgbuf_resources_t *res, const char *name, int msgbuf) { msgbuf_t *mb = msgbuf_get (res, msgbuf); diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index b07e365a6..c2b7414d3 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -142,7 +142,7 @@ plist_free_handle (plist_resources_t *res, bi_plist_t *plist) plist_free (res, plist); } -static always_inline bi_plist_t * +static always_inline bi_plist_t * __attribute__((pure)) get_plist (progs_t *pr, plist_resources_t *res, const char *name, int handle) { bi_plist_t *plist = plist_get (res, handle); diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index 89df29a33..ef748b914 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -158,7 +158,7 @@ bi_Qopen (progs_t *pr, void *_res) Qclose (file); } -static qfile_t * +static qfile_t * __attribute__((pure)) get_handle (progs_t *pr, qfile_resources_t *res, const char *name, int handle) { qfile_t *h = handle_get (res, handle); diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index b6ee26f4d..40ed15d12 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -136,7 +136,7 @@ res_set_iter_index (set_resources_t *res, bi_set_iter_t *set_iter) return PR_RESINDEX(res->set_iter_map, set_iter); } -static bi_set_t * +static bi_set_t * __attribute__((pure)) get_set (progs_t *pr, set_resources_t *res, const char *name, int index) { bi_set_t *set = res_set_get (res, index); @@ -146,7 +146,7 @@ get_set (progs_t *pr, set_resources_t *res, const char *name, int index) return set; } -static bi_set_iter_t * +static bi_set_iter_t * __attribute__((pure)) get_set_iter (progs_t *pr, set_resources_t *res, const char *name, int index) { bi_set_iter_t *set = res_set_iter_get (res, index); diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index ef2e5b403..c83adb15c 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -107,7 +107,7 @@ qpic_index (draw_resources_t *res, qpic_res_t *qp) return PR_RESINDEX (res->qpic_map, qp); } -static qpic_res_t * +static qpic_res_t * __attribute__((pure)) get_qpic (progs_t *pr, draw_resources_t *res, const char *name, int qpic_handle) { qpic_res_t *qp = qpic_get (res, qpic_handle); From 2d2f14cd31b8b16dda66f162d6b06f8f2820cf86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Feb 2022 01:15:38 +0900 Subject: [PATCH 2458/3664] [vulkan] Fix incorrect bsp sky constant ids I guess I got things a little tangled when cleaning up my bindless attempt. Fixes black default skies. --- libs/video/renderer/vulkan/qfpipeline.plist | 6 +++--- libs/video/renderer/vulkan/shader/bsp_sky.frag | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index d503ac144..40a28a89a 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -793,11 +793,11 @@ specializationInfo = { mapEntries = ( // doSkyBox - { size = 4; offset = 4; constantID = 0; }, + { size = 4; offset = 0; constantID = 0; }, // doSkySheet - { size = 4; offset = 0; constantID = 1; }, + { size = 4; offset = 4; constantID = 1; }, ); - data = "array(0, 1)"; + data = "array(1, 0)"; }; }, ); diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index 25ccf9ba0..357d5d55b 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -1,7 +1,7 @@ #version 450 -layout (constant_id = 1) const bool doSkyBox = false; -layout (constant_id = 2) const bool doSkySheet = false; +layout (constant_id = 0) const bool doSkyBox = false; +layout (constant_id = 1) const bool doSkySheet = false; layout (set = 1, binding = 0) uniform sampler2DArray SkySheet; layout (set = 2, binding = 0) uniform samplerCube SkyBox; From d75726dd22f0c320e15cde3ce5371fd9f6027445 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Feb 2022 01:17:25 +0900 Subject: [PATCH 2459/3664] [vulkan] Bind the correct texture for sky boxes That took way too long to find: just couldn't see it for looking. --- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 98ccb1ecc..51932b5c7 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1546,7 +1546,7 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) } if (bctx->skybox_tex) { bctx->skybox_descriptor - = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, + = Vulkan_CreateTextureDescriptor (ctx, bctx->skybox_tex, bctx->sampler); Sys_MaskPrintf (SYS_vulkan, "Skybox %s loaded\n", sky); } From 1447d9297d23e3a28c0e4227ca8fcb10c947b3e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Feb 2022 01:15:38 +0900 Subject: [PATCH 2460/3664] [vulkan] Fix incorrect bsp sky constant ids I guess I got things a little tangled when cleaning up my bindless attempt. Fixes black default skies. --- libs/video/renderer/vulkan/qfpipeline.plist | 6 +++--- libs/video/renderer/vulkan/shader/bsp_sky.frag | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index d503ac144..40a28a89a 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -793,11 +793,11 @@ specializationInfo = { mapEntries = ( // doSkyBox - { size = 4; offset = 4; constantID = 0; }, + { size = 4; offset = 0; constantID = 0; }, // doSkySheet - { size = 4; offset = 0; constantID = 1; }, + { size = 4; offset = 4; constantID = 1; }, ); - data = "array(0, 1)"; + data = "array(1, 0)"; }; }, ); diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index 25ccf9ba0..357d5d55b 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -1,7 +1,7 @@ #version 450 -layout (constant_id = 1) const bool doSkyBox = false; -layout (constant_id = 2) const bool doSkySheet = false; +layout (constant_id = 0) const bool doSkyBox = false; +layout (constant_id = 1) const bool doSkySheet = false; layout (set = 1, binding = 0) uniform sampler2DArray SkySheet; layout (set = 2, binding = 0) uniform samplerCube SkyBox; From a0c21069fac392e8d03242a4bce555dc4c6185c2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Feb 2022 01:17:25 +0900 Subject: [PATCH 2461/3664] [vulkan] Bind the correct texture for sky boxes That took way too long to find: just couldn't see it for looking. --- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 98ccb1ecc..51932b5c7 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1546,7 +1546,7 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) } if (bctx->skybox_tex) { bctx->skybox_descriptor - = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, + = Vulkan_CreateTextureDescriptor (ctx, bctx->skybox_tex, bctx->sampler); Sys_MaskPrintf (SYS_vulkan, "Skybox %s loaded\n", sky); } From 981fcca76d190e2fcf7c61000ded81b495dd6883 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Feb 2022 12:54:54 +0900 Subject: [PATCH 2462/3664] [sw,sw32] Fix broken software skies All for an unfortunate unsigned promotion. I guess I just wasn't testing the software renderers enough. --- libs/video/renderer/sw/d_sky.c | 6 ++++-- libs/video/renderer/sw32/d_sky.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index 853a3e0e0..c6cd5832d 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -42,14 +42,16 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) { float wu, wv, temp; vec3_t end; + int half_width = vid.width >> 1; + int half_height = vid.height >> 1; if (r_refdef.vrect.width >= r_refdef.vrect.height) temp = (float) r_refdef.vrect.width; else temp = (float) r_refdef.vrect.height; - wu = 8192.0 * (float) (u - (vid.width >> 1)) / temp; - wv = 8192.0 * (float) ((vid.height >> 1) - v) / temp; + wu = 8192.0 * (float) (u - half_width) / temp; + wv = 8192.0 * (float) (half_height - v) / temp; end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0]; end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1]; diff --git a/libs/video/renderer/sw32/d_sky.c b/libs/video/renderer/sw32/d_sky.c index 989fd4369..b9c03b5a0 100644 --- a/libs/video/renderer/sw32/d_sky.c +++ b/libs/video/renderer/sw32/d_sky.c @@ -47,14 +47,16 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) { float wu, wv, temp; vec3_t end; + int half_width = vid.width >> 1; + int half_height = vid.height >> 1; if (r_refdef.vrect.width >= r_refdef.vrect.height) temp = (float) r_refdef.vrect.width; else temp = (float) r_refdef.vrect.height; - wu = 8192.0 * (float) (u - (vid.width >> 1)) / temp; - wv = 8192.0 * (float) ((vid.height >> 1) - v) / temp; + wu = 8192.0 * (float) (u - half_width) / temp; + wv = 8192.0 * (float) (half_height - v) / temp; end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0]; end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1]; From 7b0736e208f4188641e797276d6bce52824c4aea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Feb 2022 12:54:54 +0900 Subject: [PATCH 2463/3664] [sw,sw32] Fix broken software skies All for an unfortunate unsigned promotion. I guess I just wasn't testing the software renderers enough. --- libs/video/renderer/sw/d_sky.c | 6 ++++-- libs/video/renderer/sw32/d_sky.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index 853a3e0e0..c6cd5832d 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -42,14 +42,16 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) { float wu, wv, temp; vec3_t end; + int half_width = vid.width >> 1; + int half_height = vid.height >> 1; if (r_refdef.vrect.width >= r_refdef.vrect.height) temp = (float) r_refdef.vrect.width; else temp = (float) r_refdef.vrect.height; - wu = 8192.0 * (float) (u - (vid.width >> 1)) / temp; - wv = 8192.0 * (float) ((vid.height >> 1) - v) / temp; + wu = 8192.0 * (float) (u - half_width) / temp; + wv = 8192.0 * (float) (half_height - v) / temp; end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0]; end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1]; diff --git a/libs/video/renderer/sw32/d_sky.c b/libs/video/renderer/sw32/d_sky.c index 989fd4369..b9c03b5a0 100644 --- a/libs/video/renderer/sw32/d_sky.c +++ b/libs/video/renderer/sw32/d_sky.c @@ -47,14 +47,16 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) { float wu, wv, temp; vec3_t end; + int half_width = vid.width >> 1; + int half_height = vid.height >> 1; if (r_refdef.vrect.width >= r_refdef.vrect.height) temp = (float) r_refdef.vrect.width; else temp = (float) r_refdef.vrect.height; - wu = 8192.0 * (float) (u - (vid.width >> 1)) / temp; - wv = 8192.0 * (float) ((vid.height >> 1) - v) / temp; + wu = 8192.0 * (float) (u - half_width) / temp; + wv = 8192.0 * (float) (half_height - v) / temp; end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0]; end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1]; From cd26073b6ada5fcc08ab775d21d066a714dc9be1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Feb 2022 13:29:41 +0900 Subject: [PATCH 2464/3664] [vulkan] Update the sky matrix Regardless of whether the sky is spinning or not, the matrix needs to be updated with the current origin in order to get the direction vector right in the shader. Also, it's in the update that the required x-y plane rotation gets in so the skies move in the correct direction. --- include/QF/Vulkan/qf_bsp.h | 4 -- include/QF/Vulkan/qf_matrices.h | 6 +++ libs/video/renderer/vulkan/vulkan_bsp.c | 32 -------------- libs/video/renderer/vulkan/vulkan_matrices.c | 46 ++++++++++++++++++++ 4 files changed, 52 insertions(+), 36 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 9f1108601..380b88e6f 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -133,10 +133,6 @@ typedef struct bspctx_s { struct qfv_tex_s *default_skybox; struct qfv_tex_s *skybox_tex; VkDescriptorSet skybox_descriptor; - vec4f_t sky_rotation[2]; - vec4f_t sky_velocity; - vec4f_t sky_fix; - double sky_time; quat_t default_color; quat_t last_color; diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index 5b6537e28..9a3df6f58 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -68,6 +68,11 @@ typedef struct matrixctx_s { struct qfv_stagebuf_s *stage; VkDescriptorPool pool; VkDescriptorSetLayout setLayout; + + vec4f_t sky_rotation[2]; + vec4f_t sky_velocity; + vec4f_t sky_fix; + double sky_time; } matrixctx_t; struct vulkan_ctx_s; @@ -77,6 +82,7 @@ void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx); void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx); void Vulkan_SetViewMatrix (struct vulkan_ctx_s *ctx, mat4f_t view); void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky); +void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky); void Vulkan_Matrix_Init (struct vulkan_ctx_s *ctx); void Vulkan_Matrix_Shutdown (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 51932b5c7..962735f99 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -413,13 +413,6 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) bsppoly_t *poly; mod_brush_t *brush; - bctx->sky_fix = (vec4f_t) { 0, 0, 1, 1 } * sqrtf (0.5); - bctx->sky_rotation[0] = (vec4f_t) { 0, 0, 0, 1}; - bctx->sky_rotation[1] = bctx->sky_rotation[0]; - bctx->sky_velocity = (vec4f_t) { }; - bctx->sky_velocity = qexpf (bctx->sky_velocity); - bctx->sky_time = vr_data.realtime; - // run through all surfaces, chaining them to their textures, thus // effectively sorting the surfaces by texture (without worrying about // surface order on the same texture chain). @@ -948,30 +941,7 @@ turb_end (vulkan_ctx_t *ctx) bsp_end_subpass (bframe->cmdSet.a[QFV_bspTurb], ctx); } -/*XXX -static void -spin (mat4f_t mat, bspctx_t *bctx) -{ - vec4f_t q; - mat4f_t m; - float blend; - while (vr_data.realtime - bctx->sky_time > 1) { - bctx->sky_rotation[0] = bctx->sky_rotation[1]; - bctx->sky_rotation[1] = qmulf (bctx->sky_velocity, - bctx->sky_rotation[0]); - bctx->sky_time += 1; - } - blend = bound (0, (vr_data.realtime - bctx->sky_time), 1); - - q = Blend (bctx->sky_rotation[0], bctx->sky_rotation[1], blend); - q = normalf (qmulf (bctx->sky_fix, q)); - mat4fidentity (mat); - VectorNegate (r_origin, mat[3]); - mat4fquat (m, q); - mmulf (mat, m, mat); -} -*/ static void sky_begin (qfv_renderframe_t *rFrame) { @@ -981,8 +951,6 @@ sky_begin (qfv_renderframe_t *rFrame) bctx->default_color[3] = 1; QuatCopy (bctx->default_color, bctx->last_color); - //XXX spin (ctx->matrices.sky_3d, bctx); - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 0f5536596..b35759ab9 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -86,6 +86,32 @@ setup_view (vulkan_ctx_t *ctx) Vulkan_SetViewMatrix (ctx, view); } +static void +setup_sky (vulkan_ctx_t *ctx) +{ + __auto_type mctx = ctx->matrix_context; + vec4f_t q; + mat4f_t m; + float blend; + mat4f_t mat; + + while (vr_data.realtime - mctx->sky_time > 1) { + mctx->sky_rotation[0] = mctx->sky_rotation[1]; + mctx->sky_rotation[1] = qmulf (mctx->sky_velocity, + mctx->sky_rotation[0]); + mctx->sky_time += 1; + } + blend = bound (0, (vr_data.realtime - mctx->sky_time), 1); + + q = Blend (mctx->sky_rotation[0], mctx->sky_rotation[1], blend); + q = normalf (qmulf (mctx->sky_fix, q)); + mat4fidentity (mat); + VectorNegate (r_origin, mat[3]); + mat4fquat (m, q); + mmulf (mat, m, mat); + Vulkan_SetSkyMatrix (ctx, mat); +} + void Vulkan_SetViewMatrix (vulkan_ctx_t *ctx, mat4f_t view) { @@ -97,6 +123,17 @@ Vulkan_SetViewMatrix (vulkan_ctx_t *ctx, mat4f_t view) } } +void +Vulkan_SetSkyMatrix (vulkan_ctx_t *ctx, mat4f_t sky) +{ + __auto_type mctx = ctx->matrix_context; + + if (memcmp (mctx->matrices.Sky, sky, sizeof (mat4f_t))) { + memcpy (mctx->matrices.Sky, sky, sizeof (mat4f_t)); + mctx->dirty = mctx->frames.size; + } +} + void Vulkan_Matrix_Draw (qfv_renderframe_t *rFrame) { @@ -108,6 +145,7 @@ Vulkan_Matrix_Draw (qfv_renderframe_t *rFrame) __auto_type mframe = &mctx->frames.a[ctx->curFrame]; setup_view (ctx); + setup_sky (ctx); if (mctx->dirty <= 0) { mctx->dirty = 0; @@ -241,10 +279,18 @@ Vulkan_Matrix_Init (vulkan_ctx_t *ctx) } free (sets); + mctx->sky_fix = (vec4f_t) { 0, 0, 1, 1 } * sqrtf (0.5); + mctx->sky_rotation[0] = (vec4f_t) { 0, 0, 0, 1}; + mctx->sky_rotation[1] = mctx->sky_rotation[0]; + mctx->sky_velocity = (vec4f_t) { }; + mctx->sky_velocity = qexpf (mctx->sky_velocity); + mctx->sky_time = vr_data.realtime; + mat4fidentity (mctx->matrices.Projection3d); mat4fidentity (mctx->matrices.View); mat4fidentity (mctx->matrices.Sky); mat4fidentity (mctx->matrices.Projection2d); + mctx->dirty = mctx->frames.size; mctx->stage = QFV_CreateStagingBuffer (device, "matrix", From e67ec84db9fe117ee00541cba8b740b88ff986cf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Feb 2022 13:40:24 +0900 Subject: [PATCH 2465/3664] [vulkan] Use simpler projection and z_up matrices While both matrices had positive determinants in the first place, I find the projection matrix easier to understand without all the negatives, and having quake-x/vulkan-z positively parallel in the z-up matrix makes that a lot easier to think about. --- libs/video/renderer/vulkan/projection.c | 4 ++-- libs/video/renderer/vulkan/vulkan_matrices.c | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/vulkan/projection.c b/libs/video/renderer/vulkan/projection.c index a4f597268..1dda6a7b6 100644 --- a/libs/video/renderer/vulkan/projection.c +++ b/libs/video/renderer/vulkan/projection.c @@ -77,8 +77,8 @@ QFV_PerspectiveTan (mat4f_t proj, float fov, float aspect) fard = r_farclip->value; proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 }; - proj[1] = (vec4f_t) { 0, -f, 0, 0 }; - proj[2] = (vec4f_t) { 0, 0, fard / (neard - fard), -1 }; + proj[1] = (vec4f_t) { 0, f, 0, 0 }; + proj[2] = (vec4f_t) { 0, 0, fard / (fard - neard), 1 }; proj[3] = (vec4f_t) { 0, 0, (neard * fard) / (neard - fard), 0 }; } diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index b35759ab9..fe66c04d4 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -64,11 +64,13 @@ static void setup_view (vulkan_ctx_t *ctx) { mat4f_t view; + // Quake's world is z-up, x-forward, y-left, but Vulkan's world is + // z-forward, x-right, y-down. static mat4f_t z_up = { - { 0, 0, -1, 0}, - {-1, 0, 0, 0}, - { 0, 1, 0, 0}, - { 0, 0, 0, 1}, + { 0, 0, 1, 0}, + {-1, 0, 0, 0}, + { 0,-1, 0, 0}, + { 0, 0, 0, 1}, }; vec4f_t offset = { 0, 0, 0, 1 }; From 2615953e17ca4ae968031c38db29777c4aea7e9a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Feb 2022 08:33:41 +0900 Subject: [PATCH 2466/3664] [scene] Move transform getters into inline functions --- include/QF/scene/transform.h | 226 +++++++++++++++++++++++++++++++---- libs/scene/transform.c | 141 +--------------------- 2 files changed, 207 insertions(+), 160 deletions(-) diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index 3a7b11b74..66f552df8 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -33,6 +33,7 @@ #include "QF/darray.h" #include "QF/qtypes.h" +#include "QF/scene/hierarchy.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" @@ -42,52 +43,235 @@ ///@{ typedef struct transform_s { - struct hierarchy_s *hierarchy; + hierarchy_t *hierarchy; struct scene_s *scene; ///< owning scene uint32_t index; ///< index in hierarchy int32_t id; ///< scene id } transform_t; +#define XFORMINLINE GNU89INLINE inline __attribute__((pure)) + transform_t *Transform_New (struct scene_s *scene, transform_t *parent); /* Deletes all child transforms, and transform names */ void Transform_Delete (transform_t *transform); transform_t *Transform_NewNamed (struct scene_s *scene, transform_t *parent, const char *name); -uint32_t Transform_ChildCount (const transform_t *transform) __attribute__((pure)); -transform_t *Transform_GetChild (const transform_t *transform, - uint32_t childIndex) __attribute__((pure)); +XFORMINLINE uint32_t Transform_ChildCount (const transform_t *transform); +XFORMINLINE transform_t *Transform_GetChild (const transform_t *transform, + uint32_t childIndex); void Transform_SetParent (transform_t *transform, transform_t *parent); -transform_t *Transform_GetParent (const transform_t *transform) __attribute__((pure)); +XFORMINLINE transform_t *Transform_GetParent (const transform_t *transform); void Transform_SetName (transform_t *transform, const char *name); -const char *Transform_GetName (const transform_t *transform) __attribute__((pure)); +XFORMINLINE const char *Transform_GetName (const transform_t *transform); void Transform_SetTag (transform_t *transform, uint32_t tag); -uint32_t Transform_GetTag (const transform_t *transform) __attribute__((pure)); -void Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat); -void Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat); -void Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat); +XFORMINLINE uint32_t Transform_GetTag (const transform_t *transform); +GNU89INLINE inline void Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat); +GNU89INLINE inline void Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat); +GNU89INLINE inline void Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat); // XXX the pointer may be invalidated by hierarchy updates -const vec4f_t *Transform_GetWorldMatrixPtr (const transform_t *transform) __attribute__((pure)); -void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat); -vec4f_t Transform_GetLocalPosition (const transform_t *transform) __attribute__((pure)); +XFORMINLINE const vec4f_t *Transform_GetWorldMatrixPtr (const transform_t *transform); +GNU89INLINE inline void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat); +XFORMINLINE vec4f_t Transform_GetLocalPosition (const transform_t *transform); void Transform_SetLocalPosition (transform_t *transform, vec4f_t position); -vec4f_t Transform_GetLocalRotation (const transform_t *transform) __attribute__((pure)); +XFORMINLINE vec4f_t Transform_GetLocalRotation (const transform_t *transform); void Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation); -vec4f_t Transform_GetLocalScale (const transform_t *transform) __attribute__((pure)); +XFORMINLINE vec4f_t Transform_GetLocalScale (const transform_t *transform); void Transform_SetLocalScale (transform_t *transform, vec4f_t scale); -vec4f_t Transform_GetWorldPosition (const transform_t *transform) __attribute__((pure)); +XFORMINLINE vec4f_t Transform_GetWorldPosition (const transform_t *transform); void Transform_SetWorldPosition (transform_t *transform, vec4f_t position); -vec4f_t Transform_GetWorldRotation (const transform_t *transform) __attribute__((pure)); +XFORMINLINE vec4f_t Transform_GetWorldRotation (const transform_t *transform); void Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation); -vec4f_t Transform_GetWorldScale (const transform_t *transform) __attribute__((pure)); +XFORMINLINE vec4f_t Transform_GetWorldScale (const transform_t *transform); void Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, vec4f_t rotation, vec4f_t position); // NOTE: these use X: forward, -Y: right, Z:up // aslo, not guaranteed to be normalized or even orthogonal -vec4f_t Transform_Forward (const transform_t *transform) __attribute__((pure)); -vec4f_t Transform_Right (const transform_t *transform) __attribute__((pure)); -vec4f_t Transform_Up (const transform_t *transform) __attribute__((pure)); +XFORMINLINE vec4f_t Transform_Forward (const transform_t *transform); +XFORMINLINE vec4f_t Transform_Right (const transform_t *transform); +XFORMINLINE vec4f_t Transform_Up (const transform_t *transform); // no SetWorldScale because after rotations, non uniform scale becomes shear +#undef XFORMINLINE +#ifndef IMPLEMENT_TRANSFORM_Funcs +#define XFORMINLINE GNU89INLINE inline +#else +#define XFORMINLINE VISIBLE +#endif + +XFORMINLINE +uint32_t +Transform_ChildCount (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->childCount.a[transform->index]; +} + +XFORMINLINE +transform_t * +Transform_GetChild (const transform_t *transform, uint32_t childIndex) +{ + hierarchy_t *h = transform->hierarchy; + if (childIndex >= h->childCount.a[transform->index]) { + return 0; + } + return h->transform.a[h->childIndex.a[transform->index] + childIndex]; +} + +XFORMINLINE +transform_t * +Transform_GetParent (const transform_t *transform) +{ + if (transform->index == 0) { + return 0; + } + hierarchy_t *h = transform->hierarchy; + return h->transform.a[h->parentIndex.a[transform->index]]; +} + +XFORMINLINE +const char * +Transform_GetName (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->name.a[transform->index]; +} + +XFORMINLINE +uint32_t +Transform_GetTag (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->tag.a[transform->index]; +} + +XFORMINLINE +void +Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat) +{ + hierarchy_t *h = transform->hierarchy; + vec4f_t *src = h->localMatrix.a[transform->index]; + mat[0] = src[0]; + mat[1] = src[1]; + mat[2] = src[2]; + mat[3] = src[3]; +} + +XFORMINLINE +void +Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat) +{ + hierarchy_t *h = transform->hierarchy; + vec4f_t *src = h->localInverse.a[transform->index]; + mat[0] = src[0]; + mat[1] = src[1]; + mat[2] = src[2]; + mat[3] = src[3]; +} + +XFORMINLINE +void +Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat) +{ + hierarchy_t *h = transform->hierarchy; + vec4f_t *src = h->worldMatrix.a[transform->index]; + mat[0] = src[0]; + mat[1] = src[1]; + mat[2] = src[2]; + mat[3] = src[3]; +} + +XFORMINLINE +const vec4f_t * +Transform_GetWorldMatrixPtr (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldMatrix.a[transform->index]; +} + +XFORMINLINE +void +Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat) +{ + hierarchy_t *h = transform->hierarchy; + vec4f_t *src = h->worldInverse.a[transform->index]; + mat[0] = src[0]; + mat[1] = src[1]; + mat[2] = src[2]; + mat[3] = src[3]; +} + +XFORMINLINE +vec4f_t +Transform_GetLocalPosition (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->localMatrix.a[transform->index][3]; +} + +XFORMINLINE +vec4f_t +Transform_GetLocalRotation (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->localRotation.a[transform->index]; +} + +XFORMINLINE +vec4f_t +Transform_GetLocalScale (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->localScale.a[transform->index]; +} + +XFORMINLINE +vec4f_t +Transform_GetWorldPosition (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldMatrix.a[transform->index][3]; +} + +XFORMINLINE +vec4f_t +Transform_GetWorldRotation (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldRotation.a[transform->index]; +} + +XFORMINLINE +vec4f_t +Transform_GetWorldScale (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldScale.a[transform->index]; +} + +XFORMINLINE +vec4f_t +Transform_Forward (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldMatrix.a[transform->index][0]; +} + +XFORMINLINE +vec4f_t +Transform_Right (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return -h->worldMatrix.a[transform->index][1]; +} + +XFORMINLINE +vec4f_t +Transform_Up (const transform_t *transform) +{ + hierarchy_t *h = transform->hierarchy; + return h->worldMatrix.a[transform->index][2]; +} + ///@} #endif//__QF_scene_transform_h diff --git a/libs/scene/transform.c b/libs/scene/transform.c index dbb2a6009..70c0f19b6 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -35,6 +35,8 @@ # include #endif +#define IMPLEMENT_TRANSFORM_Funcs + #include "QF/scene/hierarchy.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" @@ -81,23 +83,6 @@ Transform_NewNamed (scene_t *scene, transform_t *parent, const char *name) return transform; } -uint32_t -Transform_ChildCount (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->childCount.a[transform->index]; -} - -transform_t * -Transform_GetChild (const transform_t *transform, uint32_t childIndex) -{ - hierarchy_t *h = transform->hierarchy; - if (childIndex >= h->childCount.a[transform->index]) { - return 0; - } - return h->transform.a[h->childIndex.a[transform->index] + childIndex]; -} - void Transform_SetParent (transform_t *transform, transform_t *parent) { @@ -126,16 +111,6 @@ Transform_SetParent (transform_t *transform, transform_t *parent) } } -transform_t * -Transform_GetParent (const transform_t *transform) -{ - if (transform->index == 0) { - return 0; - } - hierarchy_t *h = transform->hierarchy; - return h->transform.a[h->parentIndex.a[transform->index]]; -} - void Transform_SetName (transform_t *transform, const char *name) { @@ -147,13 +122,6 @@ Transform_SetName (transform_t *transform, const char *name) h->name.a[transform->index] = strdup (name); } -const char * -Transform_GetName (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->name.a[transform->index]; -} - void Transform_SetTag (transform_t *transform, uint32_t tag) { @@ -161,55 +129,6 @@ Transform_SetTag (transform_t *transform, uint32_t tag) h->tag.a[transform->index] = tag; } -uint32_t -Transform_GetTag (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->tag.a[transform->index]; -} - -void -Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat) -{ - hierarchy_t *h = transform->hierarchy; - memcpy (mat, h->localMatrix.a[transform->index], sizeof (mat4f_t)); -} - -void -Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat) -{ - hierarchy_t *h = transform->hierarchy; - memcpy (mat, h->localInverse.a[transform->index], sizeof (mat4f_t)); -} - -void -Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat) -{ - hierarchy_t *h = transform->hierarchy; - memcpy (mat, h->worldMatrix.a[transform->index], sizeof (mat4f_t)); -} - -const vec4f_t * -Transform_GetWorldMatrixPtr (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index]; -} - -void -Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat) -{ - hierarchy_t *h = transform->hierarchy; - memcpy (mat, h->worldInverse.a[transform->index], sizeof (mat4f_t)); -} - -vec4f_t -Transform_GetLocalPosition (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->localMatrix.a[transform->index][3]; -} - void Transform_SetLocalPosition (transform_t *transform, vec4f_t position) { @@ -219,13 +138,6 @@ Transform_SetLocalPosition (transform_t *transform, vec4f_t position) Hierarchy_UpdateMatrices (h); } -vec4f_t -Transform_GetLocalRotation (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->localRotation.a[transform->index]; -} - void Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation) { @@ -243,13 +155,6 @@ Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation) Hierarchy_UpdateMatrices (h); } -vec4f_t -Transform_GetLocalScale (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->localScale.a[transform->index]; -} - void Transform_SetLocalScale (transform_t *transform, vec4f_t scale) { @@ -267,13 +172,6 @@ Transform_SetLocalScale (transform_t *transform, vec4f_t scale) Hierarchy_UpdateMatrices (h); } -vec4f_t -Transform_GetWorldPosition (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][3]; -} - void Transform_SetWorldPosition (transform_t *transform, vec4f_t position) { @@ -285,13 +183,6 @@ Transform_SetWorldPosition (transform_t *transform, vec4f_t position) Transform_SetLocalPosition (transform, position); } -vec4f_t -Transform_GetWorldRotation (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->worldRotation.a[transform->index]; -} - void Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation) { @@ -303,13 +194,6 @@ Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation) Transform_SetLocalRotation (transform, rotation); } -vec4f_t -Transform_GetWorldScale (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->worldScale.a[transform->index]; -} - void Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, vec4f_t rotation, vec4f_t position) @@ -328,24 +212,3 @@ Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, h->modified.a[transform->index] = 1; Hierarchy_UpdateMatrices (h); } - -vec4f_t -Transform_Forward (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][0]; -} - -vec4f_t -Transform_Right (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return -h->worldMatrix.a[transform->index][1]; -} - -vec4f_t -Transform_Up (const transform_t *transform) -{ - hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][2]; -} From deff95f490d26654e5a3521c0d7fafd1af4f57ae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 22 Feb 2022 15:23:09 +0900 Subject: [PATCH 2467/3664] [client] Merge chase camera and much of input Handling of view angles is a little hacky at the moment, but this gets the chase camera code and most of the common input code into one place, which will make cleaning up the camera code much easier. --- {nq/include => include/client}/chase.h | 13 +- include/client/input.h | 40 ++- libs/client/Makemodule.am | 1 + {nq/source => libs/client}/cl_chase.c | 61 ++-- libs/client/cl_input.c | 377 ++++++++++++++++++++++++- nq/include/client.h | 36 +-- nq/source/Makemodule.am | 2 +- nq/source/cl_ents.c | 3 +- nq/source/cl_input.c | 314 +------------------- nq/source/cl_main.c | 40 +-- nq/source/cl_view.c | 5 +- nq/source/host.c | 3 +- qw/include/chase.h | 37 --- qw/include/cl_input.h | 14 +- qw/include/client.h | 22 +- qw/source/Makemodule.am | 2 +- qw/source/cl_cam.c | 1 - qw/source/cl_chase.c | 262 ----------------- qw/source/cl_chat.c | 3 +- qw/source/cl_ents.c | 1 - qw/source/cl_input.c | 356 +---------------------- qw/source/cl_main.c | 59 ++-- qw/source/cl_view.c | 4 +- 23 files changed, 529 insertions(+), 1127 deletions(-) rename {nq/include => include/client}/chase.h (79%) rename {nq/source => libs/client}/cl_chase.c (77%) delete mode 100644 qw/include/chase.h delete mode 100644 qw/source/cl_chase.c diff --git a/nq/include/chase.h b/include/client/chase.h similarity index 79% rename from nq/include/chase.h rename to include/client/chase.h index a2d894b9d..1a8fcfa54 100644 --- a/nq/include/chase.h +++ b/include/client/chase.h @@ -25,13 +25,18 @@ */ -#ifndef __chase_h -#define __chase_h +#ifndef __client_chase_h +#define __client_chase_h + +typedef struct chasestate_s { + struct model_s *worldmodel; + struct viewstate_s *viewstate; +} chasestate_t; extern struct cvar_s *chase_active; void Chase_Init_Cvars (void); void Chase_Reset (void); -void Chase_Update (void); +void Chase_Update (chasestate_t *cs); -#endif // __chase_h +#endif // __client_chase_h diff --git a/include/client/input.h b/include/client/input.h index 89dc9cbc6..7ec0d6f73 100644 --- a/include/client/input.h +++ b/include/client/input.h @@ -27,8 +27,46 @@ #ifndef __client_input_h_ #define __client_input_h_ -void CL_Legacy_Init (void); +#include "QF/simd/vec4f.h" + +#include "QF/input.h" + +struct cbuf_s; + +extern struct cvar_s *cl_upspeed; +extern struct cvar_s *cl_forwardspeed; +extern struct cvar_s *cl_backspeed; +extern struct cvar_s *cl_sidespeed; + +extern struct cvar_s *cl_movespeedkey; + +extern struct cvar_s *cl_yawspeed; +extern struct cvar_s *cl_pitchspeed; + +extern struct cvar_s *cl_anglespeedkey; + + +#define FORWARD 0 +#define SIDE 1 +#define UP 2 + +typedef struct movestate_s { + vec4f_t move; + vec4f_t angles; +} movestate_t; #define freelook (in_mlook.state & 1 || in_freelook->int_val) +void CL_OnFocusChange (void (*func) (int game)); +void CL_Input_BuildMove (float frametime, movestate_t *state); +void CL_Input_Init (struct cbuf_s *cbuf); +void CL_Input_Init_Cvars (void); +void CL_Input_Activate (int in_game); + +extern in_button_t in_left, in_right, in_forward, in_back; +extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; +extern in_button_t in_use, in_jump, in_attack; +extern in_button_t in_up, in_down; +extern in_button_t in_strafe, in_klook, in_speed, in_mlook; + #endif // __client_input_h_ diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 2cd5a80af..397eacc9f 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES += libs/client/libQFclient.la libs_client_libQFclient_la_LDFLAGS= @STATIC@ libs_client_libQFclient_la_LIBADD= libs/gamecode/libQFgamecode.la libs/util/libQFutil.la libs_client_libQFclient_la_SOURCES= \ + libs/client/cl_chase.c \ libs/client/cl_effects.c \ libs/client/cl_entities.c \ libs/client/cl_input.c \ diff --git a/nq/source/cl_chase.c b/libs/client/cl_chase.c similarity index 77% rename from nq/source/cl_chase.c rename to libs/client/cl_chase.c index 1b88e15c8..bafac3b51 100644 --- a/nq/source/cl_chase.c +++ b/libs/client/cl_chase.c @@ -45,8 +45,9 @@ #include "world.h" -#include "nq/include/chase.h" -#include "nq/include/client.h" +#include "client/chase.h" +#include "client/input.h" +#include "client/view.h" vec4f_t camera_origin = {0,0,0,1}; @@ -83,22 +84,22 @@ Chase_Reset (void) } static inline void -TraceLine (vec3_t start, vec3_t end, vec3_t impact) +TraceLine (chasestate_t *cs, vec3_t start, vec3_t end, vec3_t impact) { trace_t trace; memset (&trace, 0, sizeof (trace)); trace.fraction = 1; - MOD_TraceLine (cl.worldmodel->brush.hulls, 0, start, end, &trace); + MOD_TraceLine (cs->worldmodel->brush.hulls, 0, start, end, &trace); VectorCopy (trace.endpos, impact); } void -Chase_Update (void) +Chase_Update (chasestate_t *cs) { float pitch, yaw, fwd; - usercmd_t cmd; // movement direction + vec4f_t move = {}; vec4f_t forward = {}, up = {}, right = {}, stop = {}, dir = {}; // lazy camera, look toward player entity @@ -106,7 +107,7 @@ Chase_Update (void) if (chase_active->int_val == 2 || chase_active->int_val == 3) { // control camera angles with key/mouse/joy-look vec3_t d; - VectorSubtract (cl.viewstate.angles, player_angles, d); + VectorSubtract (cs->viewstate->angles, player_angles, d); VectorAdd (camera_angles, d, camera_angles); if (chase_active->int_val == 2) { @@ -148,7 +149,7 @@ Chase_Update (void) camera_origin += 8 * forward; //FIXME - TraceLine (&player_origin[0], &camera_origin[0], &stop[0]); + TraceLine (cs, &player_origin[0], &camera_origin[0], &stop[0]); stop[3] = 1; if (magnitude3f (stop)[0] != 0) { camera_origin = stop - forward; @@ -160,7 +161,7 @@ Chase_Update (void) if (chase_active->int_val == 2) { if (dir[1] == 0 && dir[0] == 0) { // look straight up or down -// camera_angles[YAW] = r_data->refdef->viewstate.angles[YAW]; +// camera_angles[YAW] = r_data->refdef->viewstate->angles[YAW]; if (dir[2] > 0) camera_angles[PITCH] = 90; else @@ -188,53 +189,51 @@ Chase_Update (void) // get basic movement from keyboard - memset (&cmd, 0, sizeof (cmd)); -// VectorCopy (cl.viewstate.angles, cmd.angles); +// VectorCopy (cs->viewstate->angles, cmd.angles); if (in_strafe.state & 1) { - cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); - cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); + move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_right); + move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_left); } - cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); - cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); + move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_moveright); + move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); if (!(in_klook.state & 1)) { - cmd.forwardmove += cl_forwardspeed->value + move[FORWARD] += cl_forwardspeed->value * IN_ButtonState (&in_forward); - cmd.forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); + move[FORWARD] -= cl_backspeed->value * IN_ButtonState (&in_back); } if (in_speed.state & 1) { - cmd.forwardmove *= cl_movespeedkey->value; - cmd.sidemove *= cl_movespeedkey->value; + move *= cl_movespeedkey->value; } // mouse and joystick controllers add to movement - VectorSet (0, cl.viewstate.angles[1] - camera_angles[1], 0, dir); + VectorSet (0, cs->viewstate->angles[1] - camera_angles[1], 0, dir); AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME //forward *= viewdelta.position[2] * m_forward->value; FIXME //right *= viewdelta.position[0] * m_side->value; FIXME dir = forward + right; - cmd.forwardmove += dir[0]; - cmd.sidemove -= dir[1]; + move[FORWARD] += dir[0]; + move[SIDE] -= dir[1]; VectorSet (0, camera_angles[1], 0, dir); AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME - VectorScale (forward, cmd.forwardmove, forward); - VectorScale (right, cmd.sidemove, right); + VectorScale (forward, move[FORWARD], forward); + VectorScale (right, move[SIDE], right); VectorAdd (forward, right, dir); if (dir[1] || dir[0]) { - cl.viewstate.angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (cl.viewstate.angles[YAW] < 0) { - cl.viewstate.angles[YAW] += 360; + cs->viewstate->angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); + if (cs->viewstate->angles[YAW] < 0) { + cs->viewstate->angles[YAW] += 360; } } - cl.viewstate.angles[PITCH] = 0; + cs->viewstate->angles[PITCH] = 0; // remember the new angle to calculate the difference next frame - VectorCopy (cl.viewstate.angles, player_angles); + VectorCopy (cs->viewstate->angles, player_angles); return; } @@ -242,7 +241,7 @@ Chase_Update (void) // regular camera, faces same direction as player //FIXME - AngleVectors (cl.viewstate.angles, &forward[0], &right[0], &up[0]); + AngleVectors (cs->viewstate->angles, &forward[0], &right[0], &up[0]); // calc exact destination camera_origin = r_data->refdef->viewposition @@ -252,7 +251,7 @@ Chase_Update (void) // check for walls between player and camera //FIXME - TraceLine (&r_data->refdef->viewposition[0], &camera_origin[0], &stop[0]); + TraceLine (cs, &r_data->refdef->viewposition[0], &camera_origin[0], &stop[0]); stop[3] = 1; if (magnitude3f (stop)[0] != 0) { camera_origin = stop + forward * 8; diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 80ea95ff9..0d9c2cf39 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -39,15 +39,230 @@ #endif #include "QF/cmd.h" +#include "QF/console.h" #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/input.h" #include "QF/plist.h" #include "QF/sys.h" +#include "QF/input/event.h" + #include "old_keys.h" #include "client/input.h" +#include "client/view.h" + +int cl_game_context; +int cl_demo_context; +static int cl_event_id; + +static struct LISTENER_SET_TYPE(int) cl_on_focus_change + = LISTENER_SET_STATIC_INIT(4); + +in_axis_t viewdelta_position_forward = { + .mode = ina_set, + .name = "move.forward", + .description = "Move forward (negative) or backward (positive)", +}; +in_axis_t viewdelta_position_side = { + .mode = ina_set, + .name = "move.side", + .description = "Move right (positive) or left (negative)", +}; +in_axis_t viewdelta_position_up = { + .mode = ina_set, + .name = "move.up", + .description = "Move up (positive) or down (negative)", +}; + +in_axis_t viewdelta_angles_pitch = { + .mode = ina_set, + .name = "move.pitch", + .description = "Pitch axis", +}; +in_axis_t viewdelta_angles_yaw = { + .mode = ina_set, + .name = "move.yaw", + .description = "Yaw axis", +}; +in_axis_t viewdelta_angles_roll = { + .mode = ina_set, + .name = "move.roll", + .description = "Roll axis", +}; + +in_button_t in_left = { + .name = "left", + .description = "When active the player is turning left" +}; +in_button_t in_right = { + .name = "right", + .description = "When active the player is turning right" +}; +in_button_t in_forward = { + .name = "forward", + .description = "When active the player is moving forward" +}; +in_button_t in_back = { + .name = "back", + .description = "When active the player is moving backwards" +}; +in_button_t in_lookup = { + .name = "lookup", + .description = "When active the player's view is looking up" +}; +in_button_t in_lookdown = { + .name = "lookdown", + .description = "When active the player's view is looking down" +}; +in_button_t in_moveleft = { + .name = "moveleft", + .description = "When active the player is strafing left" +}; +in_button_t in_moveright = { + .name = "moveright", + .description = "When active the player is strafing right" +}; +in_button_t in_use = { + .name = "use", + .description = "Left over command for opening doors and triggering" + " switches" +}; +in_button_t in_jump = { + .name = "jump", + .description = "When active the player is jumping" +}; +in_button_t in_attack = { + .name = "attack", + .description = "When active player is firing/using current weapon" +}; +in_button_t in_up = { + .name = "moveup", + .description = "When active the player is swimming up in a liquid" +}; +in_button_t in_down = { + .name = "movedown", + .description = "When active the player is swimming down in a liquid" +}; +in_button_t in_strafe = { + .name = "strafe", + .description = "When active, +left and +right function like +moveleft and" + " +moveright" +}; +in_button_t in_klook = { + .name = "klook", + .description = "When active, +forward and +back perform +lookup and" + " +lookdown" +}; +in_button_t in_speed = { + .name = "speed", + .description = "When active the player is running" +}; +in_button_t in_mlook = { + .name = "mlook", + .description = "When active moving the mouse or joystick forwards " + "and backwards performs +lookup and " + "+lookdown" +}; + +static in_axis_t *cl_in_axes[] = { + &viewdelta_position_forward, + &viewdelta_position_side, + &viewdelta_position_up, + &viewdelta_angles_pitch, + &viewdelta_angles_yaw, + &viewdelta_angles_roll, + 0, +}; + +static in_button_t *cl_in_buttons[] = { + &in_left, + &in_right, + &in_forward, + &in_back, + &in_lookup, + &in_lookdown, + &in_moveleft, + &in_moveright, + &in_use, + &in_jump, + &in_attack, + &in_up, + &in_down, + &in_strafe, + &in_klook, + &in_speed, + &in_mlook, + 0 +}; + +cvar_t *cl_anglespeedkey; +cvar_t *cl_backspeed; +cvar_t *cl_forwardspeed; +cvar_t *cl_movespeedkey; +cvar_t *cl_pitchspeed; +cvar_t *cl_sidespeed; +cvar_t *cl_upspeed; +cvar_t *cl_yawspeed; + +cvar_t *lookspring; +cvar_t *m_pitch; +cvar_t *m_yaw; +cvar_t *m_forward; +cvar_t *m_side; + +static void +CL_AdjustAngles (float frametime, movestate_t *ms) +{ + float down, up; + float pitchspeed, yawspeed; + vec4f_t delta = {}; + + pitchspeed = cl_pitchspeed->value; + yawspeed = cl_yawspeed->value; + + if (in_speed.state & inb_down) { + pitchspeed *= cl_anglespeedkey->value; + yawspeed *= cl_anglespeedkey->value; + } + + pitchspeed *= frametime; + yawspeed *= frametime; + + if (!(in_strafe.state & inb_down)) { + delta[YAW] -= yawspeed * IN_ButtonState (&in_right); + delta[YAW] += yawspeed * IN_ButtonState (&in_left); + } + if (in_klook.state & inb_down) { + V_StopPitchDrift (); + delta[PITCH] -= pitchspeed * IN_ButtonState (&in_forward); + delta[PITCH] += pitchspeed * IN_ButtonState (&in_back); + } + + up = IN_ButtonState (&in_lookup); + down = IN_ButtonState (&in_lookdown); + + delta[PITCH] -= pitchspeed * up; + delta[PITCH] += pitchspeed * down; + + delta[PITCH] -= IN_UpdateAxis (&viewdelta_angles_pitch) * m_pitch->value; + delta[YAW] -= IN_UpdateAxis (&viewdelta_angles_yaw) * m_yaw->value; + delta[ROLL] -= IN_UpdateAxis (&viewdelta_angles_roll) * m_pitch->value; + + ms->angles += delta; + + if (delta[PITCH]) { + V_StopPitchDrift (); + ms->angles[PITCH] = bound (-70, ms->angles[PITCH], 80); + } + if (delta[ROLL]) { + ms->angles[ROLL] = bound (-50, ms->angles[ROLL], 50); + } + if (delta[YAW]) { + ms->angles[YAW] = anglemod (ms->angles[YAW]); + } +} static const char default_input_config[] = { #include "libs/client/default_input.plc" @@ -114,7 +329,7 @@ cl_unbind_f (void) Cmd_ExecuteString (cmd_buf->str, src_command); } -void +static void CL_Legacy_Init (void) { OK_Init (); @@ -123,3 +338,163 @@ CL_Legacy_Init (void) // FIXME hashlinks IN_LoadConfig (PL_GetPropertyList (default_input_config, 0)); } + +void +CL_Input_BuildMove (float frametime, movestate_t *state) +{ + if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring->int_val) { + V_StartPitchDrift (); + } + + CL_AdjustAngles (frametime, state); + + vec4f_t move = {}; + + if (in_strafe.state & inb_down) { + move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_right); + move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_left); + } + + move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_moveright); + move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); + + move[UP] += cl_upspeed->value * IN_ButtonState (&in_up); + move[UP] -= cl_upspeed->value * IN_ButtonState (&in_down); + + if (!(in_klook.state & inb_down)) { + move[FORWARD] += cl_forwardspeed->value * IN_ButtonState (&in_forward); + move[FORWARD] -= cl_backspeed->value * IN_ButtonState (&in_back); + } + + // adjust for speed key + if (in_speed.state & inb_down) { + move *= cl_movespeedkey->value; + } + + move[FORWARD] -= IN_UpdateAxis (&viewdelta_position_forward) * m_forward->value; + move[SIDE] += IN_UpdateAxis (&viewdelta_position_side) * m_side->value; + move[UP] -= IN_UpdateAxis (&viewdelta_position_up); + + if (freelook) + V_StopPitchDrift (); + + //if (cl.chase + // && (chase_active->int_val == 2 || chase_active->int_val == 3)) { + // /* adjust for chase camera angles + // * makes the player move relative to the chase camera frame rather + // * than the player's frame + // */ + // vec3_t forward, right, up, f, r; + // vec3_t dir = {0, 0, 0}; + // // need separate camera and player angles + // //FIXME dir[1] = r_data->refdef->viewangles[1] - cl.viewstate.angles[1]; + // AngleVectors (dir, forward, right, up); + // VectorScale (forward, move[FORWARD], f); + // VectorScale (right, move[SIDE], r); + // move[FORWARD] = f[0] + r[0]; + // move[SIDE] = f[1] + r[1]; + //} + state->move = move; +} + +static void +cl_on_focus_change_redirect (void *_func, const int *game) +{ + void (*func) (int game) = _func; + func (*game); +} + +void +CL_OnFocusChange (void (*func) (int game)) +{ + LISTENER_ADD (&cl_on_focus_change, cl_on_focus_change_redirect, func); +} + +static int +cl_focus_event (const IE_event_t *ie_event) +{ + int game = ie_event->type == ie_gain_focus; + LISTENER_INVOKE (&cl_on_focus_change, &game); + return 1; +} + +static int +cl_key_event (const IE_event_t *ie_event) +{ + if (ie_event->key.code == QFK_ESCAPE) { + Con_SetState (con_menu); + return 1; + } + return 0; +} + +static int +cl_event_handler (const IE_event_t *ie_event, void *unused) +{ + static int (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { + [ie_key] = cl_key_event, + [ie_gain_focus] = cl_focus_event, + [ie_lose_focus] = cl_focus_event, + }; + if (ie_event->type < 0 || ie_event->type >= ie_event_count + || !handlers[ie_event->type]) { + return IN_Binding_HandleEvent (ie_event); + } + return handlers[ie_event->type] (ie_event); +} + +void +CL_Input_Init (cbuf_t *cbuf) +{ + cl_event_id = IE_Add_Handler (cl_event_handler, 0); + + for (int i = 0; cl_in_axes[i]; i++) { + IN_RegisterAxis (cl_in_axes[i]); + } + for (int i = 0; cl_in_buttons[i]; i++) { + IN_RegisterButton (cl_in_buttons[i]); + } + cl_game_context = IMT_CreateContext ("key_game"); + IMT_SetContextCbuf (cl_game_context, cbuf); + cl_demo_context = IMT_CreateContext ("key_demo"); + IMT_SetContextCbuf (cl_demo_context, cbuf); + CL_Legacy_Init (); +} + +void +CL_Input_Init_Cvars (void) +{ + lookspring = Cvar_Get ("lookspring", "0", CVAR_ARCHIVE, NULL, "Snap view " + "to center when moving and no mlook/klook"); + m_pitch = Cvar_Get ("m_pitch", "0.022", CVAR_ARCHIVE, NULL, + "mouse pitch (up/down) multipier"); + m_yaw = Cvar_Get ("m_yaw", "0.022", CVAR_ARCHIVE, NULL, + "mouse yaw (left/right) multipiler"); + m_forward = Cvar_Get ("m_forward", "1", CVAR_ARCHIVE, NULL, + "mouse forward/back speed"); + m_side = Cvar_Get ("m_side", "0.8", CVAR_ARCHIVE, NULL, + "mouse strafe speed"); + cl_anglespeedkey = Cvar_Get ("cl_anglespeedkey", "1.5", CVAR_NONE, NULL, + "turn `run' speed multiplier"); + cl_backspeed = Cvar_Get ("cl_backspeed", "200", CVAR_ARCHIVE, NULL, + "backward speed"); + cl_forwardspeed = Cvar_Get ("cl_forwardspeed", "200", CVAR_ARCHIVE, NULL, + "forward speed"); + cl_movespeedkey = Cvar_Get ("cl_movespeedkey", "2.0", CVAR_NONE, NULL, + "move `run' speed multiplier"); + cl_pitchspeed = Cvar_Get ("cl_pitchspeed", "150", CVAR_NONE, NULL, + "look up/down speed"); + cl_sidespeed = Cvar_Get ("cl_sidespeed", "350", CVAR_NONE, NULL, + "strafe speed"); + cl_upspeed = Cvar_Get ("cl_upspeed", "200", CVAR_NONE, NULL, + "swim/fly up/down speed"); + cl_yawspeed = Cvar_Get ("cl_yawspeed", "140", CVAR_NONE, NULL, + "turning speed"); +} + +void +CL_Input_Activate (int in_game) +{ + IMT_SetContext (!in_game ? cl_demo_context : cl_game_context); + IE_Set_Focus (cl_event_id); +} diff --git a/nq/include/client.h b/nq/include/client.h index 20e4347c8..d7d6deee3 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -30,14 +30,15 @@ #include -#include "QF/input.h" #include "QF/mathlib.h" #include "QF/model.h" #include "QF/quakefs.h" #include "QF/sound.h" #include "QF/render.h" +#include "client/chase.h" #include "client/entities.h" +#include "client/input.h" #include "client/state.h" #include "client/view.h" @@ -160,6 +161,8 @@ typedef struct client_state_s { vec4f_t frameVelocity[2]; // Update by server, used for lean+bob // (0 is newest) viewstate_t viewstate; + movestate_t movestate; + chasestate_t chasestate; // pitch drifting vars float idealpitch; @@ -230,18 +233,6 @@ typedef struct client_state_s { extern struct cvar_s *cl_name; extern struct cvar_s *cl_color; -extern struct cvar_s *cl_upspeed; -extern struct cvar_s *cl_forwardspeed; -extern struct cvar_s *cl_backspeed; -extern struct cvar_s *cl_sidespeed; - -extern struct cvar_s *cl_movespeedkey; - -extern struct cvar_s *cl_yawspeed; -extern struct cvar_s *cl_pitchspeed; - -extern struct cvar_s *cl_anglespeedkey; - extern struct cvar_s *cl_autofire; extern struct cvar_s *cl_shownet; @@ -250,12 +241,6 @@ extern struct cvar_s *cl_nolerp; extern struct cvar_s *hud_sbar; extern struct cvar_s *cl_pitchdriftspeed; -extern struct cvar_s *lookspring; - -extern struct cvar_s *m_pitch; -extern struct cvar_s *m_yaw; -extern struct cvar_s *m_forward; -extern struct cvar_s *m_side; extern struct cvar_s *cl_name; extern struct cvar_s *cl_writecfg; @@ -297,8 +282,8 @@ void CL_NextDemo (void); // cl_input -void CL_Input_Init (struct cbuf_s *cbuf); -void CL_Input_Activate (void); +void CL_Init_Input (struct cbuf_s *cbuf); +void CL_Init_Input_Cvars (void); void CL_SendCmd (void); void CL_SendMove (usercmd_t *cmd); @@ -325,9 +310,6 @@ void CL_NewTranslation (int slot, struct skin_s *skin); // view -void V_StartPitchDrift (void); -void V_StopPitchDrift (void); - void V_UpdatePalette (void); void V_Register (void); void V_ParseDamage (void); @@ -339,12 +321,6 @@ void CL_SignonReply (void); void CL_RelinkEntities (void); void CL_ClearEnts (void); -extern in_button_t in_left, in_right, in_forward, in_back; -extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; -extern in_button_t in_use, in_jump, in_attack; -extern in_button_t in_up, in_down; -extern in_button_t in_strafe, in_klook, in_speed, in_mlook; - extern double realtime; extern qboolean recording; diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 61767a4df..0c05bb277 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -71,7 +71,7 @@ nq_server_LIBS= $(nq_server_LIBFILES) $(nq_common_LIBFILES) $(NET_LIBS) nq_server_LIB_DEPS=$(nq_server_LIBFILES) $(nq_common_LIBFILES) nq_source_libnq_client_a_SOURCES= \ - nq/source/cl_chase.c nq/source/cl_cmd.c nq/source/cl_demo.c nq/source/cl_ents.c nq/source/cl_input.c nq/source/cl_main.c \ + nq/source/cl_cmd.c nq/source/cl_demo.c nq/source/cl_ents.c nq/source/cl_input.c nq/source/cl_main.c \ nq/source/cl_screen.c nq/source/cl_parse.c nq/source/cl_view.c nq/source/sbar.c nq_source_libnq_server_a_SOURCES= \ diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 1bfae5670..c186c91a8 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -50,7 +50,8 @@ #include "client/effects.h" #include "client/temp_entities.h" -#include "nq/include/chase.h" +#include "client/chase.h" + #include "nq/include/client.h" #include "nq/include/host.h" #include "nq/include/host.h" diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 0943b4fdc..40d7794fd 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -50,151 +50,9 @@ #include "client/input.h" -#include "nq/include/chase.h" #include "nq/include/client.h" #include "nq/include/host.h" -int cl_game_context; -int cl_demo_context; -static int cl_event_id; - -in_axis_t viewdelta_position_forward = { - .mode = ina_set, - .name = "move.forward", - .description = "Move forward (negative) or backward (positive)", -}; -in_axis_t viewdelta_position_side = { - .mode = ina_set, - .name = "move.side", - .description = "Move right (positive) or left (negative)", -}; -in_axis_t viewdelta_position_up = { - .mode = ina_set, - .name = "move.up", - .description = "Move up (positive) or down (negative)", -}; - -in_axis_t viewdelta_angles_pitch = { - .mode = ina_set, - .name = "move.pitch", - .description = "Pitch axis", -}; -in_axis_t viewdelta_angles_yaw = { - .mode = ina_set, - .name = "move.yaw", - .description = "Yaw axis", -}; -in_axis_t viewdelta_angles_roll = { - .mode = ina_set, - .name = "move.roll", - .description = "Roll axis", -}; - -in_button_t in_left = { - .name = "left", - .description = "When active the player is turning left" -}; -in_button_t in_right = { - .name = "right", - .description = "When active the player is turning right" -}; -in_button_t in_forward = { - .name = "forward", - .description = "When active the player is moving forward" -}; -in_button_t in_back = { - .name = "back", - .description = "When active the player is moving backwards" -}; -in_button_t in_lookup = { - .name = "lookup", - .description = "When active the player's view is looking up" -}; -in_button_t in_lookdown = { - .name = "lookdown", - .description = "When active the player's view is looking down" -}; -in_button_t in_moveleft = { - .name = "moveleft", - .description = "When active the player is strafing left" -}; -in_button_t in_moveright = { - .name = "moveright", - .description = "When active the player is strafing right" -}; -in_button_t in_use = { - .name = "use", - .description = "Left over command for opening doors and triggering" - " switches" -}; -in_button_t in_jump = { - .name = "jump", - .description = "When active the player is jumping" -}; -in_button_t in_attack = { - .name = "attack", - .description = "When active player is firing/using current weapon" -}; -in_button_t in_up = { - .name = "moveup", - .description = "When active the player is swimming up in a liquid" -}; -in_button_t in_down = { - .name = "movedown", - .description = "When active the player is swimming down in a liquid" -}; -in_button_t in_strafe = { - .name = "strafe", - .description = "When active, +left and +right function like +moveleft and" - " +moveright" -}; -in_button_t in_klook = { - .name = "klook", - .description = "When active, +forward and +back perform +lookup and" - " +lookdown" -}; -in_button_t in_speed = { - .name = "speed", - .description = "When active the player is running" -}; -in_button_t in_mlook = { - .name = "mlook", - .description = "When active moving the mouse or joystick forwards " - "and backwards performs +lookup and " - "+lookdown" -}; - -static in_axis_t *cl_in_axes[] = { - &viewdelta_position_forward, - &viewdelta_position_side, - &viewdelta_position_up, - &viewdelta_angles_pitch, - &viewdelta_angles_yaw, - &viewdelta_angles_roll, - 0, -}; - -static in_button_t *cl_in_buttons[] = { - &in_left, - &in_right, - &in_forward, - &in_back, - &in_lookup, - &in_lookdown, - &in_moveleft, - &in_moveright, - &in_use, - &in_jump, - &in_attack, - &in_up, - &in_down, - &in_strafe, - &in_klook, - &in_speed, - &in_mlook, - 0 -}; - int in_impulse; void (*write_angles) (sizebuf_t *sb, const vec3_t angles); @@ -205,74 +63,6 @@ IN_Impulse (void *data) in_impulse = atoi (Cmd_Argv (1)); } -cvar_t *cl_anglespeedkey; -cvar_t *cl_backspeed; -cvar_t *cl_forwardspeed; -cvar_t *cl_movespeedkey; -cvar_t *cl_pitchspeed; -cvar_t *cl_sidespeed; -cvar_t *cl_upspeed; -cvar_t *cl_yawspeed; - -/* - CL_AdjustAngles - - Moves the local angle positions -*/ -static void -CL_AdjustAngles (void) -{ - float down, up; - float pitchspeed, yawspeed; - - pitchspeed = cl_pitchspeed->value; - yawspeed = cl_yawspeed->value; - - if (in_speed.state & inb_down) { - pitchspeed *= cl_anglespeedkey->value; - yawspeed *= cl_anglespeedkey->value; - } - - if ((cl.fpd & FPD_LIMIT_PITCH) && pitchspeed > FPD_MAXPITCH) - pitchspeed = FPD_MAXPITCH; - if ((cl.fpd & FPD_LIMIT_YAW) && yawspeed > FPD_MAXYAW) - yawspeed = FPD_MAXYAW; - - pitchspeed *= host_frametime; - yawspeed *= host_frametime; - - if (!(in_strafe.state & inb_down)) { - cl.viewstate.angles[YAW] -= yawspeed * IN_ButtonState (&in_right); - cl.viewstate.angles[YAW] += yawspeed * IN_ButtonState (&in_left); - cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); - } - if (in_klook.state & inb_down) { - V_StopPitchDrift (); - cl.viewstate.angles[PITCH] -= pitchspeed * IN_ButtonState (&in_forward); - cl.viewstate.angles[PITCH] += pitchspeed * IN_ButtonState (&in_back); - } - - up = IN_ButtonState (&in_lookup); - down = IN_ButtonState (&in_lookdown); - - cl.viewstate.angles[PITCH] -= pitchspeed * up; - cl.viewstate.angles[PITCH] += pitchspeed * down; - - if (up || down) - V_StopPitchDrift (); - - // FIXME: Need to clean up view angle limits - if (cl.viewstate.angles[PITCH] > 80) - cl.viewstate.angles[PITCH] = 80; - if (cl.viewstate.angles[PITCH] < -70) - cl.viewstate.angles[PITCH] = -70; - - if (cl.viewstate.angles[ROLL] > 50) - cl.viewstate.angles[ROLL] = 50; - if (cl.viewstate.angles[ROLL] < -50) - cl.viewstate.angles[ROLL] = -50; -} - /* CL_BaseMove @@ -281,75 +71,17 @@ CL_AdjustAngles (void) void CL_BaseMove (usercmd_t *cmd) { - if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring->int_val) { - V_StartPitchDrift (); - } - if (cls.state != ca_active) { return; } - - CL_AdjustAngles (); + VectorCopy (cl.viewstate.angles, cl.movestate.angles);//FIXME + CL_Input_BuildMove (host_frametime, &cl.movestate); + VectorCopy (cl.movestate.angles, cl.viewstate.angles);//FIXME memset (cmd, 0, sizeof (*cmd)); - - if (in_strafe.state & inb_down) { - cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); - cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); - } - - cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); - cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); - - cmd->upmove += cl_upspeed->value * IN_ButtonState (&in_up); - cmd->upmove -= cl_upspeed->value * IN_ButtonState (&in_down); - - if (!(in_klook.state & inb_down)) { - cmd->forwardmove += cl_forwardspeed->value * IN_ButtonState (&in_forward); - cmd->forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); - } - - // adjust for speed key - if (in_speed.state & inb_down) { - cmd->forwardmove *= cl_movespeedkey->value; - cmd->sidemove *= cl_movespeedkey->value; - cmd->upmove *= cl_movespeedkey->value; - } - - if (freelook) - V_StopPitchDrift (); - - // adjust for chase camera angles - /*FIXME:chase figure out just what this does and get it working - if (cl.chase - && (chase_active->int_val == 2 || chase_active->int_val == 3)) { - vec3_t forward, right, up, f, r; - vec3_t dir = {0, 0, 0}; - - dir[1] = r_data->refdef->viewangles[1] - cl.viewstate.angles[1]; - AngleVectors (dir, forward, right, up); - VectorScale (forward, cmd->forwardmove, f); - VectorScale (right, cmd->sidemove, r); - cmd->forwardmove = f[0] + r[0]; - cmd->sidemove = f[1] + r[1]; - VectorScale (forward, viewdelta.position[2], f); - VectorScale (right, viewdelta.position[0], r); - viewdelta.position[2] = f[0] + r[0]; - viewdelta.position[0] = (f[1] + r[1]) * -1; - } - */ - - cmd->forwardmove -= IN_UpdateAxis (&viewdelta_position_forward) * m_forward->value; - cmd->sidemove += IN_UpdateAxis (&viewdelta_position_side) * m_side->value; - cmd->upmove -= IN_UpdateAxis (&viewdelta_position_up); - cl.viewstate.angles[PITCH] -= IN_UpdateAxis (&viewdelta_angles_pitch) * m_pitch->value; - cl.viewstate.angles[YAW] -= IN_UpdateAxis (&viewdelta_angles_yaw) * m_yaw->value; - cl.viewstate.angles[ROLL] -= IN_UpdateAxis (&viewdelta_angles_roll) * m_pitch->value; - - if (freelook && !(in_strafe.state & inb_down)) { - cl.viewstate.angles[PITCH] - = bound (-70, cl.viewstate.angles[PITCH], 80); - } + cmd->forwardmove = cl.movestate.move[FORWARD]; + cmd->sidemove = cl.movestate.move[SIDE]; + cmd->upmove = cl.movestate.move[UP]; } @@ -404,42 +136,16 @@ CL_SendMove (usercmd_t *cmd) } } -static int -cl_event_handler (const IE_event_t *ie_event, void *unused) -{ - if (ie_event->type == ie_key) { - if (ie_event->key.code == QFK_ESCAPE) { - Con_SetState (con_menu); - return 1; - } - } - return IN_Binding_HandleEvent (ie_event); -} - void -CL_Input_Init (cbuf_t *cbuf) +CL_Init_Input (cbuf_t *cbuf) { - cl_event_id = IE_Add_Handler (cl_event_handler, 0); - - for (int i = 0; cl_in_axes[i]; i++) { - IN_RegisterAxis (cl_in_axes[i]); - } - for (int i = 0; cl_in_buttons[i]; i++) { - IN_RegisterButton (cl_in_buttons[i]); - } - cl_game_context = IMT_CreateContext ("key_game"); - IMT_SetContextCbuf (cl_game_context, cbuf); - cl_demo_context = IMT_CreateContext ("key_demo"); - IMT_SetContextCbuf (cl_demo_context, cbuf); + CL_Input_Init (cbuf); Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); - CL_Legacy_Init (); } void -CL_Input_Activate (void) +CL_Init_Input_Cvars (void) { - host_in_game = !cls.demoplayback; - IMT_SetContext (cls.demoplayback ? cl_demo_context : cl_game_context); - IE_Set_Focus (cl_event_id); + CL_Input_Init_Cvars (); } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index cd5ab5730..409a1fb75 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -55,7 +55,7 @@ #include "client/particles.h" #include "client/temp_entities.h" -#include "nq/include/chase.h" +#include "client/chase.h" #include "nq/include/cl_skin.h" #include "nq/include/client.h" #include "nq/include/host.h" @@ -81,13 +81,6 @@ cvar_t *cl_cshift_contents; cvar_t *cl_cshift_damage; cvar_t *cl_cshift_powerup; -cvar_t *lookspring; - -cvar_t *m_pitch; -cvar_t *m_yaw; -cvar_t *m_forward; -cvar_t *m_side; - cvar_t *hud_fps; cvar_t *hud_time; @@ -174,6 +167,7 @@ CL_InitCvars (void) S_Init_Cvars (); CL_Demo_Init (); + CL_Init_Input_Cvars (); Chase_Init_Cvars (); V_Init_Cvars (); @@ -188,38 +182,12 @@ CL_InitCvars (void) cl_name = Cvar_Get ("_cl_name", "player", CVAR_ARCHIVE, NULL, "Player name"); cl_color = Cvar_Get ("_cl_color", "0", CVAR_ARCHIVE, NULL, "Player color"); - cl_anglespeedkey = Cvar_Get ("cl_anglespeedkey", "1.5", CVAR_NONE, NULL, - "turn `run' speed multiplier"); - cl_backspeed = Cvar_Get ("cl_backspeed", "200", CVAR_ARCHIVE, NULL, - "backward speed"); - cl_forwardspeed = Cvar_Get ("cl_forwardspeed", "200", CVAR_ARCHIVE, NULL, - "forward speed"); - cl_movespeedkey = Cvar_Get ("cl_movespeedkey", "2.0", CVAR_NONE, NULL, - "move `run' speed multiplier"); - cl_pitchspeed = Cvar_Get ("cl_pitchspeed", "150", CVAR_NONE, NULL, - "look up/down speed"); - cl_sidespeed = Cvar_Get ("cl_sidespeed", "350", CVAR_NONE, NULL, - "strafe speed"); - cl_upspeed = Cvar_Get ("cl_upspeed", "200", CVAR_NONE, NULL, - "swim/fly up/down speed"); - cl_yawspeed = Cvar_Get ("cl_yawspeed", "140", CVAR_NONE, NULL, - "turning speed"); cl_writecfg = Cvar_Get ("cl_writecfg", "1", CVAR_NONE, NULL, "write config files?"); cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_NONE, NULL, "show network packets. 0=off, 1=basic, 2=verbose"); cl_nolerp = Cvar_Get ("cl_nolerp", "0", CVAR_NONE, NULL, "linear motion interpolation"); - lookspring = Cvar_Get ("lookspring", "0", CVAR_ARCHIVE, NULL, "Snap view " - "to center when moving and no mlook/klook"); - m_pitch = Cvar_Get ("m_pitch", "0.022", CVAR_ARCHIVE, NULL, - "mouse pitch (up/down) multipier"); - m_yaw = Cvar_Get ("m_yaw", "0.022", CVAR_ARCHIVE, NULL, - "mouse yaw (left/right) multipiler"); - m_forward = Cvar_Get ("m_forward", "1", CVAR_ARCHIVE, NULL, - "mouse forward/back speed"); - m_side = Cvar_Get ("m_side", "0.8", CVAR_ARCHIVE, NULL, - "mouse strafe speed"); hud_fps = Cvar_Get ("hud_fps", "0", CVAR_ARCHIVE, NULL, "display realtime frames per second"); Cvar_MakeAlias ("show_fps", hud_fps); @@ -564,7 +532,7 @@ CL_SetState (cactive_t state) host_in_game = 0; Con_SetState (state == ca_active ? con_inactive : con_fullscreen); if (state != old_state && state == ca_active) { - CL_Input_Activate (); + CL_Input_Activate (host_in_game = !cls.demoplayback); } } @@ -603,7 +571,7 @@ CL_Init (cbuf_t *cbuf) Sbar_Init (); - CL_Input_Init (cbuf); + CL_Init_Input (cbuf); CL_Particles_Init (); CL_TEnts_Init (); CL_ClearState (); diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index 80a5dbe1d..d71e75f8b 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -40,7 +40,8 @@ #include "compat.h" -#include "nq/include/chase.h" +#include "client/chase.h" + #include "nq/include/client.h" #include "nq/include/host.h" @@ -696,7 +697,7 @@ V_CalcRefdef (void) } if (cl.chase && chase_active->int_val) { - Chase_Update (); + Chase_Update (&cl.chasestate); } } diff --git a/nq/source/host.c b/nq/source/host.c index 601d5d335..77b93a5a5 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -58,7 +58,8 @@ #include "buildnum.h" #include "compat.h" -#include "nq/include/chase.h" +#include "client/chase.h" + #include "nq/include/host.h" #include "nq/include/server.h" #include "nq/include/sv_progs.h" diff --git a/qw/include/chase.h b/qw/include/chase.h deleted file mode 100644 index a2d894b9d..000000000 --- a/qw/include/chase.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - chase.h - - @description@ - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ - -#ifndef __chase_h -#define __chase_h - -extern struct cvar_s *chase_active; - -void Chase_Init_Cvars (void); -void Chase_Reset (void); -void Chase_Update (void); - -#endif // __chase_h diff --git a/qw/include/cl_input.h b/qw/include/cl_input.h index 90c125171..95f1aef98 100644 --- a/qw/include/cl_input.h +++ b/qw/include/cl_input.h @@ -28,15 +28,12 @@ #ifndef _CL_INPUT_H #define _CL_INPUT_H -#include "QF/input.h" - #include "qw/protocol.h" -void CL_OnFocusChange (void (*func) (int game)); +struct cbuf_s; -void CL_Input_Activate (void); -void CL_Input_Init (void); -void CL_Input_Init_Cvars (void); +void CL_Init_Input (struct cbuf_s *cbuf); +void CL_Init_Input_Cvars (void); void CL_ClearStates (void); void CL_SendCmd (void); void CL_SendMove (usercmd_t *cmd); @@ -49,11 +46,6 @@ int CL_ReadFromServer (void); void CL_WriteToServer (usercmd_t *cmd); void CL_BaseMove (usercmd_t *cmd); -extern in_button_t in_left, in_right, in_forward, in_back; -extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; -extern in_button_t in_use, in_jump, in_attack; -extern in_button_t in_up, in_down; -extern in_button_t in_strafe, in_klook, in_speed, in_mlook; extern int in_impulse; #endif diff --git a/qw/include/client.h b/qw/include/client.h index eb78c5a8c..1df0fe33f 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -36,7 +36,9 @@ #include "QF/plugin/vid_render.h" #include "QF/scene/entity.h" +#include "client/chase.h" #include "client/entities.h" +#include "client/input.h" #include "client/state.h" #include "client/view.h" @@ -198,6 +200,8 @@ typedef struct client_state_s { // the client maintains its own idea of view angles, which are sent to the // server each frame. And reset only at level change and teleport times viewstate_t viewstate; + movestate_t movestate; + chasestate_t chasestate; // pitch drifting vars float idealpitch; float pitchvel; @@ -275,18 +279,6 @@ extern struct cvar_s *cl_netgraph_height; extern struct cvar_s *cl_netgraph_alpha; extern struct cvar_s *cl_netgraph_box; -extern struct cvar_s *cl_upspeed; -extern struct cvar_s *cl_forwardspeed; -extern struct cvar_s *cl_backspeed; -extern struct cvar_s *cl_sidespeed; - -extern struct cvar_s *cl_movespeedkey; - -extern struct cvar_s *cl_yawspeed; -extern struct cvar_s *cl_pitchspeed; - -extern struct cvar_s *cl_anglespeedkey; - extern struct cvar_s *cl_draw_locs; extern struct cvar_s *cl_shownet; extern struct cvar_s *hud_sbar; @@ -294,12 +286,6 @@ extern struct cvar_s *hud_sbar_separator; extern struct cvar_s *hud_swap; extern struct cvar_s *cl_pitchdriftspeed; -extern struct cvar_s *lookspring; - -extern struct cvar_s *m_pitch; -extern struct cvar_s *m_yaw; -extern struct cvar_s *m_forward; -extern struct cvar_s *m_side; extern struct cvar_s *cl_name; diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 315fe6c37..86228215b 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -103,7 +103,7 @@ qw_client_libs= qw/source/libqw_client.a qw/source/libqw_common.a \ libs/client/libQFclient.la qw_source_libqw_client_a_SOURCES= \ - qw/source/cl_cam.c qw/source/cl_chase.c qw/source/cl_chat.c qw/source/cl_cmd.c qw/source/cl_cvar.c qw/source/cl_demo.c \ + qw/source/cl_cam.c qw/source/cl_chat.c qw/source/cl_cmd.c qw/source/cl_cvar.c qw/source/cl_demo.c \ qw/source/cl_entparse.c qw/source/cl_ents.c qw/source/cl_http.c qw/source/cl_input.c qw/source/cl_main.c qw/source/cl_ngraph.c \ qw/source/cl_parse.c qw/source/cl_pred.c qw/source/cl_rss.c qw/source/cl_screen.c qw/source/cl_skin.c qw/source/cl_slist.c \ qw/source/cl_view.c \ diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 383bc313a..51a6fcee7 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -48,7 +48,6 @@ #include "compat.h" #include "sbar.h" -#include "qw/include/chase.h" #include "qw/include/cl_cam.h" #include "qw/include/cl_input.h" #include "qw/include/client.h" diff --git a/qw/source/cl_chase.c b/qw/source/cl_chase.c deleted file mode 100644 index 6c747f6f9..000000000 --- a/qw/source/cl_chase.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - cl_chase.c - - chase camera support - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cvar.h" -#include "QF/keys.h" -#include "QF/input.h" -#include "QF/mathlib.h" - -#include "QF/plugin/vid_render.h" -#include "QF/simd/vec4f.h" - -#include "qw/include/chase.h" -#include "qw/include/cl_input.h" -#include "qw/include/client.h" -#include "world.h" - - -vec4f_t camera_origin = {0,0,0,1}; -vec4f_t player_origin = {0,0,0,1}; -vec4f_t player_angles = {0,0,0,1}; - -vec3_t camera_angles = {0,0,0}; - -vec3_t chase_angles; -vec3_t chase_dest; -vec3_t chase_dest_angles; -vec3_t chase_pos; - -cvar_t *chase_back; -cvar_t *chase_up; -cvar_t *chase_right; -cvar_t *chase_active; - - -void -Chase_Init_Cvars (void) -{ - chase_back = Cvar_Get ("chase_back", "100", CVAR_NONE, NULL, "None"); - chase_up = Cvar_Get ("chase_up", "16", CVAR_NONE, NULL, "None"); - chase_right = Cvar_Get ("chase_right", "0", CVAR_NONE, NULL, "None"); - chase_active = Cvar_Get ("chase_active", "0", CVAR_NONE, NULL, "None"); -} - -void -Chase_Reset (void) -{ - // for respawning and teleporting - // start position 12 units behind head -} - -static inline void -TraceLine (vec3_t start, vec3_t end, vec3_t impact) -{ - trace_t trace; - - memset (&trace, 0, sizeof (trace)); - trace.fraction = 1; - MOD_TraceLine (cl.worldmodel->brush.hulls, 0, start, end, &trace); - - VectorCopy (trace.endpos, impact); -} - -void -Chase_Update (void) -{ - float pitch, yaw, fwd; - usercmd_t cmd; // movement direction - vec4f_t forward = {}, up = {}, right = {}, stop = {}, dir = {}; - - // lazy camera, look toward player entity - - if (chase_active->int_val == 2 || chase_active->int_val == 3) { - // control camera angles with key/mouse/joy-look - vec3_t d; - VectorSubtract (cl.viewstate.angles, player_angles, d); - VectorAdd (camera_angles, d, camera_angles); - - if (chase_active->int_val == 2) { - if (camera_angles[PITCH] < -60) - camera_angles[PITCH] = -60; - if (camera_angles[PITCH] > 60) - camera_angles[PITCH] = 60; - } - - // move camera, it's not enough to just change the angles because - // the angles are automatically changed to look toward the player - - if (chase_active->int_val == 3) { - player_origin = r_data->refdef->viewposition; - } - - AngleVectors (camera_angles, &forward[0], &right[0], &up[0]); - camera_origin = player_origin - chase_back->value * forward; - - if (chase_active->int_val == 2) { - player_origin = r_data->refdef->viewposition; - - // don't let camera get too low - if (camera_origin[2] < player_origin[2] + chase_up->value) { - camera_origin[2] = player_origin[2] + chase_up->value; - } - } - - // don't let camera get too far from player - - dir = camera_origin - player_origin; - forward = normalf (dir); - - if (magnitudef (dir)[0] > chase_back->value) { - camera_origin = player_origin + forward * chase_back->value; - } - - // check for walls between player and camera - - camera_origin += 8 * forward; - //FIXME - TraceLine (&player_origin[0], &camera_origin[0], &stop[0]); - stop[3] = 1; - if (magnitude3f (stop)[0] != 0) { - camera_origin = stop - forward; - } - - dir = camera_origin - r_data->refdef->viewposition; - forward = normalf (dir); - - if (chase_active->int_val == 2) { - if (dir[1] == 0 && dir[0] == 0) { - // look straight up or down -// camera_angles[YAW] = r_data->refdef->viewstate.angles[YAW]; - if (dir[2] > 0) - camera_angles[PITCH] = 90; - else - camera_angles[PITCH] = 270; - } else { - yaw = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - if (yaw < 180) - yaw += 180; - else - yaw -= 180; - camera_angles[YAW] = yaw; - - fwd = sqrt (dir[0] * dir[0] + dir[1] * dir[1]); - pitch = (atan2 (dir[2], fwd) * 180 / M_PI); - if (pitch < 0) - pitch += 360; - camera_angles[PITCH] = pitch; - } - } - - AngleQuat (camera_angles, &r_data->refdef->viewrotation[0]);//FIXME rotate camera - r_data->refdef->viewposition = camera_origin; // move camera - - // get basic movement from keyboard - - memset (&cmd, 0, sizeof (cmd)); -// VectorCopy (cl.viewstate.angles, cmd.angles); - - if (in_strafe.state & 1) { - cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); - cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); - } - cmd.sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); - cmd.sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); - - if (!(in_klook.state & 1)) { - cmd.forwardmove += cl_forwardspeed->value - * IN_ButtonState (&in_forward); - cmd.forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); - } - if (in_speed.state & 1) { - cmd.forwardmove *= cl_movespeedkey->value; - cmd.sidemove *= cl_movespeedkey->value; - } - - // mouse and joystick controllers add to movement - VectorSet (0, cl.viewstate.angles[1] - camera_angles[1], 0, dir); - AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME - //forward *= viewdelta.position[2] * m_forward->value; FIXME - //right *= viewdelta.position[0] * m_side->value; FIXME - dir = forward + right; - cmd.forwardmove += dir[0]; - cmd.sidemove -= dir[1]; - - VectorSet (0, camera_angles[1], 0, dir); - AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME - - VectorScale (forward, cmd.forwardmove, forward); - VectorScale (right, cmd.sidemove, right); - VectorAdd (forward, right, dir); - - if (dir[1] || dir[0]) { - cl.viewstate.angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (cl.viewstate.angles[YAW] < 0) { - cl.viewstate.angles[YAW] += 360; - } - } - - cl.viewstate.angles[PITCH] = 0; - - // remember the new angle to calculate the difference next frame - VectorCopy (cl.viewstate.angles, player_angles); - - return; - } - - // regular camera, faces same direction as player - - //FIXME - AngleVectors (cl.viewstate.angles, &forward[0], &right[0], &up[0]); - - // calc exact destination - camera_origin = r_data->refdef->viewposition - - forward * chase_back->value - right * chase_right->value; - // chase_up is world up - camera_origin[2] += chase_up->value; - - // check for walls between player and camera - //FIXME - TraceLine (&r_data->refdef->viewposition[0], &camera_origin[0], &stop[0]); - stop[3] = 1; - if (magnitude3f (stop)[0] != 0) { - camera_origin = stop + forward * 8; - } - - r_data->refdef->viewposition = camera_origin; -} diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index a20eb7b89..5e170c3c9 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -44,9 +44,10 @@ #include "QF/sys.h" #include "QF/va.h" +#include "client/input.h" + #include "qw/include/client.h" #include "qw/include/cl_chat.h" -#include "qw/include/cl_input.h" llist_t *ignore_list, *dead_ignore_list; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 489d5e8de..5b03d3b02 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -55,7 +55,6 @@ #include "qw/msg_ucmd.h" #include "qw/pmove.h" -#include "qw/include/chase.h" #include "qw/include/cl_cam.h" #include "qw/include/cl_ents.h" #include "qw/include/cl_main.h" diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index c33cd4966..43dae8bd9 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -56,7 +56,6 @@ #include "qw/msg_ucmd.h" -#include "qw/include/chase.h" #include "qw/include/cl_cam.h" #include "qw/include/cl_demo.h" #include "qw/include/cl_input.h" @@ -64,153 +63,10 @@ #include "qw/include/client.h" #include "qw/include/host.h" -int cl_game_context; -int cl_demo_context; -static int cl_event_id; -static struct LISTENER_SET_TYPE(int) cl_on_focus_change - = LISTENER_SET_STATIC_INIT(4); - cvar_t *cl_nodelta; cvar_t *cl_maxnetfps; cvar_t *cl_spamimpulse; -in_axis_t viewdelta_position_forward = { - .mode = ina_set, - .name = "move.forward", - .description = "Move forward (negative) or backward (positive)", -}; -in_axis_t viewdelta_position_side = { - .mode = ina_set, - .name = "move.side", - .description = "Move right (positive) or left (negative)", -}; -in_axis_t viewdelta_position_up = { - .mode = ina_set, - .name = "move.up", - .description = "Move up (positive) or down (negative)", -}; - -in_axis_t viewdelta_angles_pitch = { - .mode = ina_set, - .name = "move.pitch", - .description = "Pitch axis", -}; -in_axis_t viewdelta_angles_yaw = { - .mode = ina_set, - .name = "move.yaw", - .description = "Yaw axis", -}; -in_axis_t viewdelta_angles_roll = { - .mode = ina_set, - .name = "move.roll", - .description = "Roll axis", -}; - -in_button_t in_left = { - .name = "left", - .description = "When active the player is turning left" -}; -in_button_t in_right = { - .name = "right", - .description = "When active the player is turning right" -}; -in_button_t in_forward = { - .name = "forward", - .description = "When active the player is moving forward" -}; -in_button_t in_back = { - .name = "back", - .description = "When active the player is moving backwards" -}; -in_button_t in_lookup = { - .name = "lookup", - .description = "When active the player's view is looking up" -}; -in_button_t in_lookdown = { - .name = "lookdown", - .description = "When active the player's view is looking down" -}; -in_button_t in_moveleft = { - .name = "moveleft", - .description = "When active the player is strafing left" -}; -in_button_t in_moveright = { - .name = "moveright", - .description = "When active the player is strafing right" -}; -in_button_t in_use = { - .name = "use", - .description = "Left over command for opening doors and triggering" - " switches" -}; -in_button_t in_jump = { - .name = "jump", - .description = "When active the player is jumping" -}; -in_button_t in_attack = { - .name = "attack", - .description = "When active player is firing/using current weapon" -}; -in_button_t in_up = { - .name = "moveup", - .description = "When active the player is swimming up in a liquid" -}; -in_button_t in_down = { - .name = "movedown", - .description = "When active the player is swimming down in a liquid" -}; -in_button_t in_strafe = { - .name = "strafe", - .description = "When active, +left and +right function like +moveleft and" - " +moveright" -}; -in_button_t in_klook = { - .name = "klook", - .description = "When active, +forward and +back perform +lookup and" - " +lookdown" -}; -in_button_t in_speed = { - .name = "speed", - .description = "When active the player is running" -}; -in_button_t in_mlook = { - .name = "mlook", - .description = "When active moving the mouse or joystick forwards " - "and backwards performs +lookup and " - "+lookdown" -}; - -static in_axis_t *cl_in_axes[] = { - &viewdelta_position_forward, - &viewdelta_position_side, - &viewdelta_position_up, - &viewdelta_angles_pitch, - &viewdelta_angles_yaw, - &viewdelta_angles_roll, - 0, -}; - -static in_button_t *cl_in_buttons[] = { - &in_left, - &in_right, - &in_forward, - &in_back, - &in_lookup, - &in_lookdown, - &in_moveleft, - &in_moveright, - &in_use, - &in_jump, - &in_attack, - &in_up, - &in_down, - &in_strafe, - &in_klook, - &in_speed, - &in_mlook, - 0 -}; - int in_impulse; static void @@ -223,74 +79,6 @@ IN_Impulse (void *data) Team_BestWeaponImpulse (); // HACK HACK HACK } -cvar_t *cl_anglespeedkey; -cvar_t *cl_backspeed; -cvar_t *cl_forwardspeed; -cvar_t *cl_movespeedkey; -cvar_t *cl_pitchspeed; -cvar_t *cl_sidespeed; -cvar_t *cl_upspeed; -cvar_t *cl_yawspeed; - -/* - CL_AdjustAngles - - Moves the local angle positions -*/ -static void -CL_AdjustAngles (void) -{ - float down, up; - float pitchspeed, yawspeed; - - pitchspeed = cl_pitchspeed->value; - yawspeed = cl_yawspeed->value; - - if (in_speed.state & inb_down) { - pitchspeed *= cl_anglespeedkey->value; - yawspeed *= cl_anglespeedkey->value; - } - - if ((cl.fpd & FPD_LIMIT_PITCH) && pitchspeed > FPD_MAXPITCH) - pitchspeed = FPD_MAXPITCH; - if ((cl.fpd & FPD_LIMIT_YAW) && yawspeed > FPD_MAXYAW) - yawspeed = FPD_MAXYAW; - - pitchspeed *= host_frametime; - yawspeed *= host_frametime; - - if (!(in_strafe.state & inb_down)) { - cl.viewstate.angles[YAW] -= yawspeed * IN_ButtonState (&in_right); - cl.viewstate.angles[YAW] += yawspeed * IN_ButtonState (&in_left); - cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); - } - if (in_klook.state & inb_down) { - V_StopPitchDrift (); - cl.viewstate.angles[PITCH] -= pitchspeed * IN_ButtonState (&in_forward); - cl.viewstate.angles[PITCH] += pitchspeed * IN_ButtonState (&in_back); - } - - up = IN_ButtonState (&in_lookup); - down = IN_ButtonState (&in_lookdown); - - cl.viewstate.angles[PITCH] -= pitchspeed * up; - cl.viewstate.angles[PITCH] += pitchspeed * down; - - if (up || down) - V_StopPitchDrift (); - - // FIXME: Need to clean up view angle limits - if (cl.viewstate.angles[PITCH] > 80) - cl.viewstate.angles[PITCH] = 80; - if (cl.viewstate.angles[PITCH] < -70) - cl.viewstate.angles[PITCH] = -70; - - if (cl.viewstate.angles[ROLL] > 50) - cl.viewstate.angles[ROLL] = 50; - if (cl.viewstate.angles[ROLL] < -50) - cl.viewstate.angles[ROLL] = -50; -} - /* CL_BaseMove @@ -299,76 +87,18 @@ CL_AdjustAngles (void) void CL_BaseMove (usercmd_t *cmd) { - if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring->int_val) { - V_StartPitchDrift (); - } - if (cls.state != ca_active) { return; } - - CL_AdjustAngles (); + VectorCopy (cl.viewstate.angles, cl.movestate.angles);//FIXME + CL_Input_BuildMove (host_frametime, &cl.movestate); + VectorCopy (cl.movestate.angles, cl.viewstate.angles);//FIXME memset (cmd, 0, sizeof (*cmd)); - - VectorCopy (cl.viewstate.angles, cmd->angles); - if (in_strafe.state & inb_down) { - cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_right); - cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_left); - } - - cmd->sidemove += cl_sidespeed->value * IN_ButtonState (&in_moveright); - cmd->sidemove -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); - - cmd->upmove += cl_upspeed->value * IN_ButtonState (&in_up); - cmd->upmove -= cl_upspeed->value * IN_ButtonState (&in_down); - - if (!(in_klook.state & inb_down)) { - cmd->forwardmove += cl_forwardspeed->value * IN_ButtonState (&in_forward); - cmd->forwardmove -= cl_backspeed->value * IN_ButtonState (&in_back); - } - - // adjust for speed key - if (in_speed.state & inb_down) { - cmd->forwardmove *= cl_movespeedkey->value; - cmd->sidemove *= cl_movespeedkey->value; - cmd->upmove *= cl_movespeedkey->value; - } - - if (freelook) - V_StopPitchDrift (); - - // adjust for chase camera angles - /*FIXME:chase figure out just what this does and get it working - if (cl.chase - && (chase_active->int_val == 2 || chase_active->int_val == 3)) { - vec3_t forward, right, up, f, r; - vec3_t dir = {0, 0, 0}; - - dir[1] = r_data->refdef->viewangles[1] - cl.viewstate.angles[1]; - AngleVectors (dir, forward, right, up); - VectorScale (forward, cmd->forwardmove, f); - VectorScale (right, cmd->sidemove, r); - cmd->forwardmove = f[0] + r[0]; - cmd->sidemove = f[1] + r[1]; - VectorScale (forward, viewdelta.position[2], f); - VectorScale (right, viewdelta.position[0], r); - viewdelta.position[2] = f[0] + r[0]; - viewdelta.position[0] = (f[1] + r[1]) * -1; - } - */ - - cmd->forwardmove -= IN_UpdateAxis (&viewdelta_position_forward) * m_forward->value; - cmd->sidemove += IN_UpdateAxis (&viewdelta_position_side) * m_side->value; - cmd->upmove -= IN_UpdateAxis (&viewdelta_position_up); - cl.viewstate.angles[PITCH] -= IN_UpdateAxis (&viewdelta_angles_pitch) * m_pitch->value; - cl.viewstate.angles[YAW] -= IN_UpdateAxis (&viewdelta_angles_yaw) * m_yaw->value; - cl.viewstate.angles[ROLL] -= IN_UpdateAxis (&viewdelta_angles_roll) * m_pitch->value; - - if (freelook && !(in_strafe.state & inb_down)) { - cl.viewstate.angles[PITCH] - = bound (-70, cl.viewstate.angles[PITCH], 80); - } + cmd->forwardmove = cl.movestate.move[FORWARD]; + cmd->sidemove = cl.movestate.move[SIDE]; + cmd->upmove = cl.movestate.move[UP]; + VectorCopy (cl.movestate.angles, cmd->angles); } static int @@ -564,82 +294,18 @@ CL_SendCmd (void) Netchan_Transmit (&cls.netchan, buf.cursize, buf.data); } -static int -cl_key_event (const IE_event_t *ie_event) -{ - if (ie_event->key.code == QFK_ESCAPE) { - Con_SetState (con_menu); - return 1; - } - return 0; -} - -static void -cl_on_focus_change_redirect (void *_func, const int *game) -{ - void (*func) (int game) = _func; - func (*game); -} - void -CL_OnFocusChange (void (*func) (int game)) +CL_Init_Input (cbuf_t *cbuf) { - LISTENER_ADD (&cl_on_focus_change, cl_on_focus_change_redirect, func); -} - -static int -cl_focus_event (const IE_event_t *ie_event) -{ - int game = ie_event->type == ie_gain_focus; - LISTENER_INVOKE (&cl_on_focus_change, &game); - return 1; -} - -static int -cl_event_handler (const IE_event_t *ie_event, void *unused) -{ - static int (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { - [ie_key] = cl_key_event, - [ie_gain_focus] = cl_focus_event, - [ie_lose_focus] = cl_focus_event, - }; - if (ie_event->type < 0 || ie_event->type >= ie_event_count - || !handlers[ie_event->type]) { - return IN_Binding_HandleEvent (ie_event); - } - return handlers[ie_event->type] (ie_event); -} - -void -CL_Input_Init (void) -{ - cl_event_id = IE_Add_Handler (cl_event_handler, 0); - - for (int i = 0; cl_in_axes[i]; i++) { - IN_RegisterAxis (cl_in_axes[i]); - } - for (int i = 0; cl_in_buttons[i]; i++) { - IN_RegisterButton (cl_in_buttons[i]); - } - cl_game_context = IMT_CreateContext ("key_game"); - IMT_SetContextCbuf (cl_game_context, cl_cbuf); - cl_demo_context = IMT_CreateContext ("key_demo"); - IMT_SetContextCbuf (cl_demo_context, cl_cbuf); + CL_Input_Init (cbuf); Cmd_AddDataCommand ("impulse", IN_Impulse, 0, "Call a game function or QuakeC function."); - CL_Legacy_Init (); } void -CL_Input_Activate (void) -{ - IMT_SetContext (cls.demoplayback ? cl_demo_context : cl_game_context); - IE_Set_Focus (cl_event_id); -} - -void -CL_Input_Init_Cvars (void) +CL_Init_Input_Cvars (void) { + CL_Input_Init_Cvars (); cl_nodelta = Cvar_Get ("cl_nodelta", "0", CVAR_NONE, NULL, "Disable player delta compression. Set to 1 if you " "have a poor ISP and get many U_REMOVE warnings."); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index bfd520246..ee83578f2 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -158,13 +158,6 @@ cvar_t *cl_cshift_powerup; cvar_t *cl_model_crcs; -cvar_t *lookspring; - -cvar_t *m_pitch; -cvar_t *m_yaw; -cvar_t *m_forward; -cvar_t *m_side; - cvar_t *cl_predict_players; cvar_t *cl_solid_players; @@ -1172,7 +1165,7 @@ CL_SetState (cactive_t state) } Con_SetState (state == ca_active ? con_inactive : con_fullscreen); if (state != old_state && state == ca_active) { - CL_Input_Activate (); + CL_Input_Activate (!cls.demoplayback); } } @@ -1211,7 +1204,7 @@ CL_Init (void) Sbar_Init (); - CL_Input_Init (); + CL_Init_Input (cl_cbuf); CL_Ents_Init (); CL_Particles_Init (); CL_TEnts_Init (); @@ -1312,6 +1305,23 @@ cl_cmd_pkt_adr_f (cvar_t *var) memset (&cl_cmd_packet_address, 0, sizeof (cl_cmd_packet_address)); } +static void +cl_pitchspeed_f (cvar_t *var) +{ + if ((cl.fpd & FPD_LIMIT_PITCH) && var->value > FPD_MAXPITCH) { + var->value = FPD_MAXPITCH; + } +} + +static void +cl_yawspeed_f (cvar_t *var) +{ + if ((cl.fpd & FPD_LIMIT_YAW) && var->value > FPD_MAXYAW) { + var->value = FPD_MAXYAW; + } +} + + static void CL_Init_Cvars (void) { @@ -1321,7 +1331,7 @@ CL_Init_Cvars (void) S_Init_Cvars (); CL_Cam_Init_Cvars (); - CL_Input_Init_Cvars (); + CL_Init_Input_Cvars (); CL_Prediction_Init_Cvars (); CL_NetGraph_Init_Cvars (); Game_Init_Cvars (); @@ -1329,6 +1339,9 @@ CL_Init_Cvars (void) Team_Init_Cvars (); V_Init_Cvars (); + cl_pitchspeed->callback = cl_pitchspeed_f; + cl_yawspeed->callback = cl_yawspeed_f; + cls.userinfo = Info_ParseString ("", MAX_INFO_STRING, 0); cl_model_crcs = Cvar_Get ("cl_model_crcs", "1", CVAR_ARCHIVE, NULL, @@ -1358,24 +1371,8 @@ CL_Init_Cvars (void) "Shift view colors on damage"); cl_cshift_powerup = Cvar_Get ("cl_cshift_powerup", "1", CVAR_ARCHIVE, NULL, "Shift view colors for powerups"); - cl_anglespeedkey = Cvar_Get ("cl_anglespeedkey", "1.5", CVAR_NONE, NULL, - "turn `run' speed multiplier"); - cl_backspeed = Cvar_Get ("cl_backspeed", "200", CVAR_ARCHIVE, NULL, - "backward speed"); cl_fb_players = Cvar_Get ("cl_fb_players", "0", CVAR_ARCHIVE, NULL, "fullbrightness of player models. " "server must allow (via fbskins serverinfo)."); - cl_forwardspeed = Cvar_Get ("cl_forwardspeed", "200", CVAR_ARCHIVE, NULL, - "forward speed"); - cl_movespeedkey = Cvar_Get ("cl_movespeedkey", "2.0", CVAR_NONE, NULL, - "move `run' speed multiplier"); - cl_pitchspeed = Cvar_Get ("cl_pitchspeed", "150", CVAR_NONE, NULL, - "look up/down speed"); - cl_sidespeed = Cvar_Get ("cl_sidespeed", "350", CVAR_NONE, NULL, - "strafe speed"); - cl_upspeed = Cvar_Get ("cl_upspeed", "200", CVAR_NONE, NULL, - "swim/fly up/down speed"); - cl_yawspeed = Cvar_Get ("cl_yawspeed", "140", CVAR_NONE, NULL, - "turning speed"); cl_writecfg = Cvar_Get ("cl_writecfg", "1", CVAR_NONE, NULL, "write config files?"); cl_draw_locs = Cvar_Get ("cl_draw_locs", "0", CVAR_NONE, NULL, @@ -1388,16 +1385,6 @@ CL_Init_Cvars (void) "connection timeout (since last packet received)"); host_speeds = Cvar_Get ("host_speeds", "0", CVAR_NONE, NULL, "display host processing times"); - lookspring = Cvar_Get ("lookspring", "0", CVAR_ARCHIVE, NULL, "Snap view " - "to center when moving and no mlook/klook"); - m_forward = Cvar_Get ("m_forward", "1", CVAR_ARCHIVE, NULL, - "mouse forward/back speed"); - m_pitch = Cvar_Get ("m_pitch", "0.022", CVAR_ARCHIVE, NULL, - "mouse pitch (up/down) multipier"); - m_side = Cvar_Get ("m_side", "0.8", CVAR_ARCHIVE, NULL, - "mouse strafe speed"); - m_yaw = Cvar_Get ("m_yaw", "0.022", CVAR_ARCHIVE, NULL, - "mouse yaw (left/right) multiplier"); rcon_password = Cvar_Get ("rcon_password", "", CVAR_NONE, NULL, "remote control password"); rcon_address = Cvar_Get ("rcon_address", "", CVAR_NONE, NULL, "server IP " diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index bf9fe4ae9..21fb7bf69 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -39,7 +39,7 @@ #include "qw/bothdefs.h" -#include "qw/include/chase.h" +#include "client/chase.h" #include "qw/include/cl_cam.h" #include "qw/include/cl_ents.h" #include "qw/include/cl_main.h" @@ -701,7 +701,7 @@ V_CalcRefdef (void) } if (cl.chase && chase_active->int_val) { - Chase_Update (); + Chase_Update (&cl.chasestate); } } From 5ad7c0fbd61d6b39e96249561787f7585da8fc88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Feb 2022 10:41:50 +0900 Subject: [PATCH 2468/3664] [scene] Add a camera object It holds the data for a basic 3d camera (transform, fov, near and far clip). Not used yet as there is much work to be done in cleaning up the client code. --- include/QF/Makemodule.am | 1 + include/QF/scene/camera.h | 57 +++++++++++++++++++++++++++++++++ libs/scene/Makemodule.am | 1 + libs/scene/camera.c | 66 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 include/QF/scene/camera.h create mode 100644 libs/scene/camera.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 382e556e3..86f135c59 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -140,6 +140,7 @@ include_qf_progs = \ include/QF/progs/pr_type_names.h include_qf_scene = \ + include/QF/scene/camera.h \ include/QF/scene/entity.h \ include/QF/scene/hierarchy.h \ include/QF/scene/transform.h \ diff --git a/include/QF/scene/camera.h b/include/QF/scene/camera.h new file mode 100644 index 000000000..a7da8412b --- /dev/null +++ b/include/QF/scene/camera.h @@ -0,0 +1,57 @@ +/* + camera.h + + Scene camera data + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/02/18 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_scene_camera_h +#define __QF_scene_camera_h + +#include "QF/qtypes.h" +#include "QF/simd/mat4f.h" + +/** \defgroup scene_camera Camera data + \ingroup scene +*/ +///@{ + +typedef struct camera_s { + struct scene_s *scene; ///< owning scene + int32_t id; ///< id in scene + int32_t transform; + float field_of_view; + float aspect; + float near_clip; + float far_clip; +} camera_t; + +void Camera_GetViewMatrix (const camera_t *camera, mat4f_t mat); +void Camera_GetProjectionMatrix (const camera_t *camera, mat4f_t mat); + +///@} + +#endif//__QF_scene_camera_h diff --git a/libs/scene/Makemodule.am b/libs/scene/Makemodule.am index eaf988539..060e1d31d 100644 --- a/libs/scene/Makemodule.am +++ b/libs/scene/Makemodule.am @@ -8,6 +8,7 @@ libs_scene_libQFscene_la_LDFLAGS= $(lib_ldflags) libs_scene_libQFscene_la_LIBADD= $(scene_deps) libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps) libs_scene_libQFscene_la_SOURCES= \ + libs/scene/camera.c \ libs/scene/hierarchy.c \ libs/scene/scene.c \ libs/scene/transform.c diff --git a/libs/scene/camera.c b/libs/scene/camera.c new file mode 100644 index 000000000..1526abb19 --- /dev/null +++ b/libs/scene/camera.c @@ -0,0 +1,66 @@ +/* + camera.c + + Scene camera data + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/02/18 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/scene/camera.h" +#include "QF/scene/scene.h" +#include "QF/scene/transform.h" + +#include "scn_internal.h" + +void +Camera_GetViewMatrix (const camera_t *camera, mat4f_t view) +{ + scene_resources_t *res = camera->scene->resources; + transform_t *transform = PR_RESGET (res->transforms, camera->transform); + vec4f_t rotation = Transform_GetWorldRotation (transform); + vec4f_t position = Transform_GetWorldPosition (transform); + mat4fquat (view, qconjf (rotation)); + // qconjf negates xyz but leaves w alone, which is what we want for + // inverting the translation (essentially, rotation+position form a + // dual quaternion, but without the complication of dealing with + // half-translations) + view[3] = mvmulf (view, qconjf (position)); +} + +void Camera_GetProjectionMatrix (const camera_t *camera, mat4f_t proj) +{ + float v = camera->field_of_view; + float a = camera->aspect; + float f = camera->far_clip; + float n = camera->near_clip; + + proj[0] = (vec4f_t) { v / a, 0, 0, 0 }; + proj[1] = (vec4f_t) { 0, v, 0, 0 }; + proj[2] = (vec4f_t) { 0, 0, f / (f - n), 1 }; + proj[2] = (vec4f_t) { 0, 0, n * f / (n - f), 0 }; +} From e920abe142e93b028e80527a18e328a0231b5b7a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Feb 2022 10:50:53 +0900 Subject: [PATCH 2469/3664] [glsl] Adjust view/projection matrices for consistency The actual view and projection matrices are now consistent with vulkan, with the vulkan-gl disparity moved into adjustment matrices. The goal is to allow the same camera data and code to be used in all renderers. The extra matrix multiplication shouldn't be too expensive as it occurs only when the field of view (not often, under user control) or near and far clip distances (very rarely) change. --- libs/video/renderer/glsl/glsl_main.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 1295ca7e4..a4d22326b 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -78,8 +78,17 @@ glsl_R_ViewChanged (void) // NOTE columns! proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 }; proj[1] = (vec4f_t) { 0, f, 0, 0 }; - proj[2] = (vec4f_t) { 0, 0, (fard + neard) / (neard - fard), -1 }; - proj[3] = (vec4f_t) { 0, 0, (2 * fard * neard) / (neard - fard), 0 }; + proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 }; + proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 }; + + // convert 0..1 depth buffer range to -1..1 + static mat4f_t depth_range = { + { 1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 2, 0}, + { 0, 0,-1, 1}, + }; + mmulf (proj, depth_range, proj); } void @@ -90,9 +99,10 @@ glsl_R_SetupFrame (void) r_framecount++; VectorCopy (r_refdef.viewposition, r_origin); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); + vec4f_t rotation = r_refdef.viewrotation; + VectorCopy (qvmulf (rotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); + VectorCopy (qvmulf (rotation, (vec4f_t) { 0,-1, 0, 0 }), vright); + VectorCopy (qvmulf (rotation, (vec4f_t) { 0, 0, 1, 0 }), vup); R_SetFrustum (); @@ -105,7 +115,7 @@ R_SetupView (void) { float x, y, w, h; static mat4f_t z_up = { - { 0, 0, -1, 0}, + { 0, 0, 1, 0}, {-1, 0, 0, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 1}, From f04459f03f2d97e89ec59ee7d60e8c23be35808c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Feb 2022 11:39:11 +0900 Subject: [PATCH 2470/3664] [nq,qw] Clean up some bogus diffs in cl_view The diffs were caused by white space and a redundant line. --- nq/source/cl_view.c | 4 ++-- qw/source/cl_view.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index d71e75f8b..49dc4c949 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -579,8 +579,8 @@ V_CalcViewRoll (void) static void V_CalcIntermissionRefdef (void) { - // ent is the player model (visible when out of body) - entity_t *ent = &cl_entities[cl.viewentity]; + // ent is the player model (visible when out of body) + entity_t *ent = &cl_entities[cl.viewentity]; entity_t *view; float old; vec4f_t origin = Transform_GetWorldPosition (ent->transform); diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 21fb7bf69..3527242bd 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -580,7 +580,8 @@ V_CalcViewRoll (void) static void V_CalcIntermissionRefdef (void) { - entity_t *ent = &cl_entities[cl.viewentity]; + // ent is the player model (visible when out of body) + entity_t *ent = &cl_entities[cl.viewentity]; entity_t *view; float old; vec4f_t origin = Transform_GetWorldPosition (ent->transform); @@ -592,7 +593,6 @@ V_CalcIntermissionRefdef (void) r_data->refdef->viewposition = origin; r_data->refdef->viewrotation = rotation; view->renderer.model = NULL; - view->renderer.model = NULL; // always idle in intermission old = v_idlescale->value; @@ -716,7 +716,7 @@ DropPunchAngle (void) cl.viewstate.punchangle = (vec4f_t) { 0, 0, 0, 1 }; return; } - float pc = punch[3]; + float pc = punch[3]; float ds = 0.0871557427 * cl.viewstate.frametime; float dc = sqrt (1 - ds * ds); float s = ps * dc - pc * ds; From aac9069d9f0f2c8f999a18fb8a379c4c8ba8cc7a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Feb 2022 15:48:57 +0900 Subject: [PATCH 2471/3664] [nq,qw] Clean up cl_view's use of the client struct This is a huge step towards merging cl_view. --- include/client/input.h | 5 +- include/client/view.h | 39 ++++- libs/client/cl_input.c | 14 +- nq/include/client.h | 17 +- nq/source/cl_input.c | 2 +- nq/source/cl_main.c | 10 +- nq/source/cl_parse.c | 19 ++- nq/source/cl_screen.c | 7 +- nq/source/cl_view.c | 352 ++++++++++++++++++-------------------- qw/include/client.h | 15 +- qw/source/cl_cam.c | 6 +- qw/source/cl_input.c | 2 +- qw/source/cl_main.c | 12 +- qw/source/cl_parse.c | 11 +- qw/source/cl_screen.c | 17 +- qw/source/cl_view.c | 376 +++++++++++++++++++---------------------- 16 files changed, 452 insertions(+), 452 deletions(-) diff --git a/include/client/input.h b/include/client/input.h index 7ec0d6f73..ace69afa3 100644 --- a/include/client/input.h +++ b/include/client/input.h @@ -57,8 +57,11 @@ typedef struct movestate_s { #define freelook (in_mlook.state & 1 || in_freelook->int_val) +struct viewstate_s; + void CL_OnFocusChange (void (*func) (int game)); -void CL_Input_BuildMove (float frametime, movestate_t *state); +void CL_Input_BuildMove (float frametime, movestate_t *state, + struct viewstate_s *vs); void CL_Input_Init (struct cbuf_s *cbuf); void CL_Input_Init_Cvars (void); void CL_Input_Activate (int in_game); diff --git a/include/client/view.h b/include/client/view.h index 7a7f8e005..b0419e165 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -30,6 +30,7 @@ #define __client_view_h_ #include "QF/mathlib.h" +#include "QF/render.h" #include "QF/simd/types.h" #define INFO_CSHIFT_BONUS (1 << 0) @@ -41,12 +42,38 @@ typedef struct viewstate_s { vec4f_t movecmd; vec4f_t velocity; vec4f_t origin; + vec4f_t punchangle; vec3_t angles; + float frametime; + double time; + float height; int weaponframe; int onground; // -1 when in air + int active:1; + int drift_enabled:1; + int voffs_enabled:1; + int bob_enabled:1; + int intermission:1; + int force_cshifts; // bitfield of server enforced cshifts uint32_t flags; - float frametime; - vec4f_t punchangle; + + int powerup_index; + cshift_t cshifts[NUM_CSHIFTS]; // Color shifts for damage, powerups + cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types + +// pitch drifting vars + float idealpitch; + float pitchvel; + qboolean nodrift; + float driftmove; + double laststop; + + struct model_s *weapon_model; + struct entity_s *weapon_entity; + struct entity_s *player_entity; + + struct chasestate_s *chasestate; + int chase; } viewstate_t; #define VF_DEAD 1 @@ -54,11 +81,11 @@ typedef struct viewstate_s { void V_Init (void); void V_Init_Cvars (void); -void V_RenderView (void); +void V_RenderView (viewstate_t *vs); float V_CalcRoll (const vec3_t angles, vec4f_t velocity); -void V_StartPitchDrift (void); -void V_StopPitchDrift (void); +void V_StartPitchDrift (viewstate_t *vs); +void V_StopPitchDrift (viewstate_t *vs); -void V_SetContentsColor (int contents); +void V_SetContentsColor (viewstate_t *vs, int contents); #endif // __client_view_h_ diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 0d9c2cf39..02c3a8255 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -213,7 +213,7 @@ cvar_t *m_forward; cvar_t *m_side; static void -CL_AdjustAngles (float frametime, movestate_t *ms) +CL_AdjustAngles (float frametime, movestate_t *ms, viewstate_t *vs) { float down, up; float pitchspeed, yawspeed; @@ -235,7 +235,7 @@ CL_AdjustAngles (float frametime, movestate_t *ms) delta[YAW] += yawspeed * IN_ButtonState (&in_left); } if (in_klook.state & inb_down) { - V_StopPitchDrift (); + V_StopPitchDrift (vs); delta[PITCH] -= pitchspeed * IN_ButtonState (&in_forward); delta[PITCH] += pitchspeed * IN_ButtonState (&in_back); } @@ -253,7 +253,7 @@ CL_AdjustAngles (float frametime, movestate_t *ms) ms->angles += delta; if (delta[PITCH]) { - V_StopPitchDrift (); + V_StopPitchDrift (vs); ms->angles[PITCH] = bound (-70, ms->angles[PITCH], 80); } if (delta[ROLL]) { @@ -340,13 +340,13 @@ CL_Legacy_Init (void) } void -CL_Input_BuildMove (float frametime, movestate_t *state) +CL_Input_BuildMove (float frametime, movestate_t *state, viewstate_t *vs) { if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring->int_val) { - V_StartPitchDrift (); + V_StartPitchDrift (vs); } - CL_AdjustAngles (frametime, state); + CL_AdjustAngles (frametime, state, vs); vec4f_t move = {}; @@ -376,7 +376,7 @@ CL_Input_BuildMove (float frametime, movestate_t *state) move[UP] -= IN_UpdateAxis (&viewdelta_position_up); if (freelook) - V_StopPitchDrift (); + V_StopPitchDrift (vs); //if (cl.chase // && (chase_active->int_val == 2 || chase_active->int_val == 3)) { diff --git a/nq/include/client.h b/nq/include/client.h index d7d6deee3..3aed4fb9e 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -148,9 +148,6 @@ typedef struct client_state_s { float item_gettime[32]; // cl.time of aquiring item, for blinking float faceanimtime; // Use anim frame if cl.time < this - cshift_t cshifts[NUM_CSHIFTS]; // Color shifts for damage, powerups - cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types - // The client maintains its own idea of view angles, which are sent to the // server each frame. The server sets punchangle when the view is temporarily // offset, and an angle reset commands at the start of each level and after @@ -164,15 +161,7 @@ typedef struct client_state_s { movestate_t movestate; chasestate_t chasestate; -// pitch drifting vars - float idealpitch; - float pitchvel; - qboolean nodrift; - float driftmove; - double laststop; - qboolean paused; // Sent over by server - float viewheight; float crouch; // Local amount for smoothing stepups qboolean inwater; @@ -208,7 +197,6 @@ typedef struct client_state_s { int gametype; int maxclients; // serverinfo mirrors - int chase; int sv_cshifts; int no_pogo_stick; int teamplay; @@ -312,9 +300,8 @@ void CL_NewTranslation (int slot, struct skin_s *skin); // view void V_UpdatePalette (void); void V_Register (void); -void V_ParseDamage (void); -void V_SetContentsColor (int contents); -void V_PrepBlend (void); +void V_ParseDamage (viewstate_t *vs); +void V_PrepBlend (viewstate_t *vs); // cl_tent void CL_SignonReply (void); diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 40d7794fd..0f63d7017 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -75,7 +75,7 @@ CL_BaseMove (usercmd_t *cmd) return; } VectorCopy (cl.viewstate.angles, cl.movestate.angles);//FIXME - CL_Input_BuildMove (host_frametime, &cl.movestate); + CL_Input_BuildMove (host_frametime, &cl.movestate, &cl.viewstate); VectorCopy (cl.movestate.angles, cl.viewstate.angles);//FIXME memset (cmd, 0, sizeof (*cmd)); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 409a1fb75..80b97fe01 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -213,12 +213,14 @@ CL_ClearState (void) // wipe the entire cl structure memset (&cl, 0, sizeof (cl)); - cl.chase = 1; + cl.viewstate.chase = 1; + cl.viewstate.chasestate = &cl.chasestate; cl.watervis = 1; r_data->force_fullscreen = 0; r_data->lightstyle = cl.lightstyle; CL_Init_Entity (&cl.viewent); + cl.viewstate.weapon_entity = &cl.viewent; r_data->view_model = &cl.viewent; SZ_Clear (&cls.message); @@ -241,7 +243,7 @@ CL_StopCshifts (void) int i; for (i = 0; i < NUM_CSHIFTS; i++) - cl.cshifts[i].percent = 0; + cl.viewstate.cshifts[i].percent = 0; for (i = 0; i < MAX_CL_STATS; i++) cl.stats[i] = 0; } @@ -285,6 +287,7 @@ CL_Disconnect (void) cl.worldmodel = NULL; cl.intermission = 0; + cl.viewstate.intermission = 0; } void @@ -435,6 +438,7 @@ CL_ReadFromServer (void) cl.oldtime = cl.time; cl.time += host_frametime; cl.viewstate.frametime = host_frametime; + cl.viewstate.time = cl.time; do { ret = CL_GetMessage (); @@ -496,6 +500,8 @@ CL_SetState (cactive_t state) { cactive_t old_state = cls.state; cls.state = state; + cl.viewstate.active = cls.state == ca_active; + cl.viewstate.drift_enabled = !cls.demoplayback; Sys_MaskPrintf (SYS_net, "CL_SetState: %d -> %d\n", old_state, state); if (old_state != state) { if (old_state == ca_active) { diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index ae7577b8f..76d9f8021 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -367,6 +367,8 @@ CL_ParseServerInfo (void) } cl.players = Hunk_AllocName (0, cl.maxclients * sizeof (*cl.players), "players"); + cl.viewstate.voffs_enabled = cl.maxclients == 1; + cl.viewstate.bob_enabled = 1; for (i = 0; i < cl.maxclients; i++) { cl.players[i].userinfo = Info_ParseString ("name\\", 0, 0); cl.players[i].name = Info_Key (cl.players[i].userinfo, "name"); @@ -653,14 +655,14 @@ CL_ParseClientdata (void) bits |= MSG_ReadByte (net_message) << 24; if (bits & SU_VIEWHEIGHT) - cl.viewheight = ((signed char) MSG_ReadByte (net_message)); + cl.viewstate.height = ((signed char) MSG_ReadByte (net_message)); else - cl.viewheight = DEFAULT_VIEWHEIGHT; + cl.viewstate.height = DEFAULT_VIEWHEIGHT; if (bits & SU_IDEALPITCH) - cl.idealpitch = ((signed char) MSG_ReadByte (net_message)); + cl.viewstate.idealpitch = ((signed char) MSG_ReadByte (net_message)); else - cl.idealpitch = 0; + cl.viewstate.idealpitch = 0; cl.frameVelocity[1] = cl.frameVelocity[0]; vec3_t punchangle = { }; @@ -691,6 +693,8 @@ CL_ParseClientdata (void) if ((i & (1 << j)) && !(cl.stats[STAT_ITEMS] & (1 << j))) cl.item_gettime[j] = cl.time; cl.stats[STAT_ITEMS] = i; +#define IT_POWER (IT_QUAD | IT_SUIT | IT_INVULNERABILITY | IT_INVISIBILITY) + cl.viewstate.powerup_index = (cl.stats[STAT_ITEMS] & IT_POWER) >> 19; } cl.viewstate.onground = (bits & SU_ONGROUND) ? 0 : -1; @@ -700,6 +704,7 @@ CL_ParseClientdata (void) cl.stats[STAT_WEAPONFRAME] = MSG_ReadByte (net_message); else cl.stats[STAT_WEAPONFRAME] = 0; + cl.viewstate.weaponframe = cl.stats[STAT_WEAPONFRAME]; if (bits & SU_ARMOR) i = MSG_ReadByte (net_message); @@ -717,6 +722,7 @@ CL_ParseClientdata (void) if (cl.stats[STAT_WEAPON] != i) { cl.stats[STAT_WEAPON] = i; Sbar_Changed (); + cl.viewstate.weapon_model = cl.model_precache[cl.stats[STAT_WEAPON]]; } i = (short) MSG_ReadShort (net_message); @@ -914,6 +920,7 @@ CL_ParseServerMessage (void) case svc_setview: cl.viewentity = MSG_ReadShort (net_message); + cl.viewstate.player_entity = &cl_entities[cl.viewentity]; break; case svc_sound: @@ -1047,7 +1054,9 @@ CL_ParseServerMessage (void) break; case svc_damage: - V_ParseDamage (); + V_ParseDamage (&cl.viewstate); + // put sbar face into pain frame + cl.faceanimtime = cl.time + 0.2; break; case svc_spawnstatic: diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index d238a204a..214f764a4 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -80,7 +80,7 @@ SCR_CShift (void) cl.worldmodel); contents = leaf->contents; } - V_SetContentsColor (contents); + V_SetContentsColor (&cl.viewstate, contents); r_funcs->Draw_BlendScreen (r_data->vid->cshift_color); } @@ -164,7 +164,8 @@ CL_UpdateScreen (double realtime) scr_funcs_normal[2] = r_funcs->SCR_DrawTurtle; scr_funcs_normal[3] = r_funcs->SCR_DrawPause; - V_PrepBlend (); - V_RenderView (); + cl.viewstate.intermission = cl.intermission != 0; + V_PrepBlend (&cl.viewstate); + V_RenderView (&cl.viewstate); SCR_UpdateScreen (realtime, scr_funcs[index]); } diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index 49dc4c949..42db23b44 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -85,11 +85,37 @@ vec4f_t v_idle_yaw; vec4f_t v_idle_roll; vec4f_t v_idle_pitch; -cshift_t cshift_empty = { {130, 80, 50}, 0}; -cshift_t cshift_water = { {130, 80, 50}, 128}; -cshift_t cshift_slime = { {0, 25, 5}, 150}; -cshift_t cshift_lava = { {255, 80, 0}, 150}; -cshift_t cshift_bonus = { {215, 186, 60}, 50}; +static cshift_t cshift_empty = { {130, 80, 50}, 0}; +static cshift_t cshift_water = { {130, 80, 50}, 128}; +static cshift_t cshift_slime = { { 0, 25, 5}, 150}; +static cshift_t cshift_lava = { {255, 80, 0}, 150}; +static cshift_t cshift_bonus = { {215, 186, 60}, 50}; + +static cshift_t armor_blood[] = { + { {255, 0, 0} }, // blood + { {220, 50, 50} }, // armor + blood + { {200, 100, 100} }, // armor > blood need two for logic + { {200, 100, 100} }, // armor > blood need two for logic +}; + +static cshift_t powerup[] = { + { { 0, 0, 0}, 0}, + { {100, 100, 100}, 100}, // IT_INVISIBILITY + { {255, 255, 0}, 30}, // IT_INVULNERABILITY + { {255, 255, 0}, 30}, // IT_INVULNERABILITY + { { 0, 255, 0}, 20}, // IT_SUIT + { { 0, 255, 0}, 20}, // IT_SUIT + { { 0, 255, 0}, 20}, // IT_SUIT + { { 0, 255, 0}, 20}, // IT_SUIT + { { 0, 0, 255}, 30}, // IT_QUAD + { { 0, 0, 255}, 30}, // IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD +}; #define sqr(x) ((x) * (x)) @@ -115,20 +141,20 @@ V_CalcRoll (const vec3_t angles, vec4f_t velocity) } static float -V_CalcBob (void) +V_CalcBob (viewstate_t *vs) { - vec4f_t velocity = cl.viewstate.velocity; + vec4f_t velocity = vs->velocity; float cycle; static double bobtime; static float bob; - if (cl.spectator) + if (!vs->bob_enabled) return 0; - if (cl.viewstate.onground == -1) + if (vs->onground == -1) return bob; // just use old value - bobtime += cl.viewstate.frametime; + bobtime += vs->frametime; cycle = bobtime - (int) (bobtime / cl_bobcycle->value) * cl_bobcycle->value; cycle /= cl_bobcycle->value; @@ -150,31 +176,37 @@ V_CalcBob (void) } void -V_StartPitchDrift (void) +V_StartPitchDrift (viewstate_t *vs) { - if (cl.laststop == cl.time) { + if (vs->laststop == vs->time) { return; // something else is keeping it from drifting } - if (cl.nodrift || !cl.pitchvel) { - cl.pitchvel = v_centerspeed->value; - cl.nodrift = false; - cl.driftmove = 0; + if (vs->nodrift || !vs->pitchvel) { + vs->pitchvel = v_centerspeed->value; + vs->nodrift = false; + vs->driftmove = 0; } } -void -V_StopPitchDrift (void) +static void +V_StartPitchDrift_f (void *data) { - cl.laststop = cl.time; - cl.nodrift = true; - cl.pitchvel = 0; + V_StartPitchDrift (data); +} + +void +V_StopPitchDrift (viewstate_t *vs) +{ + vs->laststop = vs->time; + vs->nodrift = true; + vs->pitchvel = 0; } /* V_DriftPitch - Moves the client pitch angle towards cl.idealpitch sent by the server. + Moves the client pitch angle towards vs->idealpitch sent by the server. If the user is adjusting pitch manually, either with lookup/lookdown, mlook and mouse, or klook and keyboard, pitch drifting is constantly @@ -184,64 +216,64 @@ V_StopPitchDrift (void) and lookspring is non 0, or when */ static void -V_DriftPitch (void) +V_DriftPitch (viewstate_t *vs) { float delta, move; - float forwardmove = cl.viewstate.movecmd[0]; + float forwardmove = vs->movecmd[0]; - if (noclip_anglehack || cl.viewstate.onground == -1 || cls.demoplayback) { - cl.driftmove = 0; - cl.pitchvel = 0; + if (noclip_anglehack || vs->onground == -1 || !vs->drift_enabled) { + vs->driftmove = 0; + vs->pitchvel = 0; return; } // don't count small mouse motion - if (cl.nodrift) { + if (vs->nodrift) { if (fabs (forwardmove) < cl_forwardspeed->value) - cl.driftmove = 0; + vs->driftmove = 0; else - cl.driftmove += cl.viewstate.frametime; + vs->driftmove += vs->frametime; - if (cl.driftmove > v_centermove->value) { - V_StartPitchDrift (); + if (vs->driftmove > v_centermove->value) { + V_StartPitchDrift (vs); } return; } - delta = cl.idealpitch - cl.viewstate.angles[PITCH]; + delta = vs->idealpitch - vs->angles[PITCH]; if (!delta) { - cl.pitchvel = 0; + vs->pitchvel = 0; return; } - move = cl.viewstate.frametime * cl.pitchvel; - cl.pitchvel += cl.viewstate.frametime * v_centerspeed->value; + move = vs->frametime * vs->pitchvel; + vs->pitchvel += vs->frametime * v_centerspeed->value; if (delta > 0) { if (move > delta) { - cl.pitchvel = 0; + vs->pitchvel = 0; move = delta; } - cl.viewstate.angles[PITCH] += move; + vs->angles[PITCH] += move; } else if (delta < 0) { if (move > -delta) { - cl.pitchvel = 0; + vs->pitchvel = 0; move = -delta; } - cl.viewstate.angles[PITCH] -= move; + vs->angles[PITCH] -= move; } } /* PALETTE FLASHES */ void -V_ParseDamage (void) +V_ParseDamage (viewstate_t *vs) { float count, side; int armor, blood; - vec4f_t origin = cl.viewstate.origin; - vec_t *angles = cl.viewstate.angles; + vec4f_t origin = vs->origin; + vec_t *angles = vs->angles; vec3_t from, forward, right, up; armor = MSG_ReadByte (net_message); @@ -252,31 +284,15 @@ V_ParseDamage (void) if (count < 10) count = 10; - cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame - if (cl_cshift_damage->int_val - || (cl.sv_cshifts & INFO_CSHIFT_DAMAGE)) { - cshift_t *cshift = &cl.cshifts[CSHIFT_DAMAGE]; - - cshift->percent += 3 * count; - cshift->percent = - bound (0, cshift->percent, 150); - - if (armor > blood) { - cshift->destcolor[0] = 200; - cshift->destcolor[1] = 100; - cshift->destcolor[2] = 100; - } else if (armor) { - cshift->destcolor[0] = 220; - cshift->destcolor[1] = 50; - cshift->destcolor[2] = 50; - } else { - cshift->destcolor[0] = 255; - cshift->destcolor[1] = 0; - cshift->destcolor[2] = 0; - } + || (vs->force_cshifts & INFO_CSHIFT_DAMAGE)) { + cshift_t *cshift = &vs->cshifts[CSHIFT_DAMAGE]; + int percent = cshift->percent; + *cshift = armor_blood[(2 * (armor > blood)) + (armor > 0)]; + cshift->percent = percent + 3 * count; + cshift->percent = bound (0, cshift->percent, 150); cshift->initialpct = cshift->percent; - cshift->time = cl.time; + cshift->time = vs->time; } // calculate view angle kicks @@ -309,15 +325,16 @@ V_cshift_f (void) When you run over an item, the server sends this command */ static void -V_BonusFlash_f (void) +V_BonusFlash_f (void *data) { + viewstate_t *vs = data; if (!cl_cshift_bonus->int_val - && !(cl.sv_cshifts & INFO_CSHIFT_BONUS)) + && !(vs->force_cshifts & INFO_CSHIFT_BONUS)) return; - cl.cshifts[CSHIFT_BONUS] = cshift_bonus; - cl.cshifts[CSHIFT_BONUS].initialpct = cl.cshifts[CSHIFT_BONUS].percent; - cl.cshifts[CSHIFT_BONUS].time = cl.time; + vs->cshifts[CSHIFT_BONUS] = cshift_bonus; + vs->cshifts[CSHIFT_BONUS].initialpct = vs->cshifts[CSHIFT_BONUS].percent; + vs->cshifts[CSHIFT_BONUS].time = vs->time; } /* @@ -326,69 +343,34 @@ V_BonusFlash_f (void) Underwater, lava, etc each has a color shift */ void -V_SetContentsColor (int contents) +V_SetContentsColor (viewstate_t *vs, int contents) { if (!cl_cshift_contents->int_val - && !(cl.sv_cshifts & INFO_CSHIFT_CONTENTS)) { - cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; + && !(vs->force_cshifts & INFO_CSHIFT_CONTENTS)) { + vs->cshifts[CSHIFT_CONTENTS] = cshift_empty; return; } switch (contents) { case CONTENTS_EMPTY: - cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; + vs->cshifts[CSHIFT_CONTENTS] = cshift_empty; break; case CONTENTS_LAVA: - cl.cshifts[CSHIFT_CONTENTS] = cshift_lava; + vs->cshifts[CSHIFT_CONTENTS] = cshift_lava; break; case CONTENTS_SOLID: case CONTENTS_SLIME: - cl.cshifts[CSHIFT_CONTENTS] = cshift_slime; + vs->cshifts[CSHIFT_CONTENTS] = cshift_slime; break; default: - cl.cshifts[CSHIFT_CONTENTS] = cshift_water; + vs->cshifts[CSHIFT_CONTENTS] = cshift_water; } } static void -V_CalcPowerupCshift (void) +V_CalcPowerupCshift (viewstate_t *vs) { - if (!cl.stats[STAT_ITEMS] & (IT_SUIT || IT_INVISIBILITY || IT_QUAD - || IT_INVULNERABILITY)) - { - cl.cshifts[CSHIFT_POWERUP].percent = 0; - return; - } - - if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY && - cl.stats[STAT_ITEMS] & IT_QUAD) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } else if (cl.stats[STAT_ITEMS] & IT_QUAD) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } else if (cl.stats[STAT_ITEMS] & IT_SUIT) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 20; - } else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100; - cl.cshifts[CSHIFT_POWERUP].percent = 100; - } else { - cl.cshifts[CSHIFT_POWERUP].percent = 0; - } + vs->cshifts[CSHIFT_POWERUP] = powerup[vs->powerup_index]; } /* @@ -398,22 +380,22 @@ V_CalcPowerupCshift (void) a bit, but otherwise this is his code. --KB */ static void -V_CalcBlend (void) +V_CalcBlend (viewstate_t *vs) { float a2, a3; float r = 0, g = 0, b = 0, a = 0; int i; for (i = 0; i < NUM_CSHIFTS; i++) { - a2 = cl.cshifts[i].percent / 255.0; + a2 = vs->cshifts[i].percent / 255.0; if (!a2) continue; a2 = min (a2, 1.0); - r += (cl.cshifts[i].destcolor[0] - r) * a2; - g += (cl.cshifts[i].destcolor[1] - g) * a2; - b += (cl.cshifts[i].destcolor[2] - b) * a2; + r += (vs->cshifts[i].destcolor[0] - r) * a2; + g += (vs->cshifts[i].destcolor[1] - g) * a2; + b += (vs->cshifts[i].destcolor[2] - b) * a2; a3 = (1.0 - a) * (1.0 - a2); a = 1.0 - a3; @@ -434,12 +416,12 @@ V_CalcBlend (void) } static void -V_DropCShift (cshift_t *cs, float droprate) +V_DropCShift (cshift_t *cs, double time, float droprate) { if (cs->time < 0) { cs->percent = 0; } else { - cs->percent = cs->initialpct - (cl.time - cs->time) * droprate; + cs->percent = cs->initialpct - (time - cs->time) * droprate; if (cs->percent <= 0) { cs->percent = 0; cs->time = -1; @@ -448,56 +430,55 @@ V_DropCShift (cshift_t *cs, float droprate) } void -V_PrepBlend (void) +V_PrepBlend (viewstate_t *vs) { int i, j; if (cl_cshift_powerup->int_val - || (cl.sv_cshifts & INFO_CSHIFT_POWERUP)) - V_CalcPowerupCshift (); + || (vs->force_cshifts & INFO_CSHIFT_POWERUP)) + V_CalcPowerupCshift (vs); r_data->vid->cshift_changed = false; for (i = 0; i < NUM_CSHIFTS; i++) { - if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent) { + if (vs->cshifts[i].percent != vs->prev_cshifts[i].percent) { r_data->vid->cshift_changed = true; - cl.prev_cshifts[i].percent = cl.cshifts[i].percent; + vs->prev_cshifts[i].percent = vs->cshifts[i].percent; } for (j = 0; j < 3; j++) { - if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j]) + if (vs->cshifts[i].destcolor[j] != vs->prev_cshifts[i].destcolor[j]) { r_data->vid->cshift_changed = true; - cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j]; + vs->prev_cshifts[i].destcolor[j] = vs->cshifts[i].destcolor[j]; } } } // drop the damage value - V_DropCShift (&cl.cshifts[CSHIFT_DAMAGE], 150); + V_DropCShift (&vs->cshifts[CSHIFT_DAMAGE], vs->time, 150); // drop the bonus value - V_DropCShift (&cl.cshifts[CSHIFT_BONUS], 100); + V_DropCShift (&vs->cshifts[CSHIFT_BONUS], vs->time, 100); if (!r_data->vid->cshift_changed && !r_data->vid->recalc_refdef) return; - V_CalcBlend (); + V_CalcBlend (vs); } /* VIEW RENDERING */ static void -CalcGunAngle (void) +CalcGunAngle (viewstate_t *vs) { vec4f_t rotation = r_data->refdef->viewrotation; //FIXME make child of camera - Transform_SetWorldRotation (cl.viewent.transform, rotation); + Transform_SetWorldRotation (vs->weapon_entity->transform, rotation); } static void -V_BoundOffsets (void) +V_BoundOffsets (viewstate_t *vs) { - vec4f_t offset = r_data->refdef->viewposition - - cl.viewstate.origin; + vec4f_t offset = r_data->refdef->viewposition - vs->origin; // absolutely bound refresh reletive to entity clipping hull // so the view can never be inside a solid wall @@ -505,17 +486,17 @@ V_BoundOffsets (void) offset[0] = bound (-14, offset[0], 14); offset[1] = bound (-14, offset[1], 14); offset[2] = bound (-22, offset[2], 30); - r_data->refdef->viewposition = cl.viewstate.origin + offset; + r_data->refdef->viewposition = vs->origin + offset; } static vec4f_t -idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level) +idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level, double time) { vec4f_t identity = { 0, 0, 0, 1 }; if (!level || !cycle) { return identity; } - float scale = sin (cl.time * cycle->value); + float scale = sin (time * cycle->value); float ang = scale * level->value * v_idlescale->value; float c = cos (ang * M_PI / 360); float s = sin (ang * M_PI / 360); @@ -528,14 +509,14 @@ idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level) Idle swaying */ static void -V_AddIdle (void) +V_AddIdle (viewstate_t *vs) { vec4f_t roll = idle_quat ((vec4f_t) { 1, 0, 0, 0}, - v_iroll_cycle, v_iroll_level); + v_iroll_cycle, v_iroll_level, vs->time); vec4f_t pitch = idle_quat ((vec4f_t) { 0, 1, 0, 0}, - v_ipitch_cycle, v_ipitch_level); + v_ipitch_cycle, v_ipitch_level, vs->time); vec4f_t yaw = idle_quat ((vec4f_t) { 0, 0, 1, 0}, - v_iyaw_cycle, v_iyaw_level); + v_iyaw_cycle, v_iyaw_level, vs->time); vec4f_t rot = normalf (qmulf (yaw, qmulf (pitch, roll))); // rotate the view @@ -543,8 +524,8 @@ V_AddIdle (void) // counter-rotate the weapon rot = qmulf (qconjf (rot), - Transform_GetWorldRotation (cl.viewent.transform)); - Transform_SetWorldRotation (cl.viewent.transform, rot); + Transform_GetWorldRotation (vs->weapon_entity->transform)); + Transform_SetWorldRotation (vs->weapon_entity->transform, rot); } /* @@ -553,10 +534,10 @@ V_AddIdle (void) Roll is induced by movement and damage */ static void -V_CalcViewRoll (void) +V_CalcViewRoll (viewstate_t *vs) { - vec_t *angles = cl.viewstate.angles; - vec4f_t velocity = cl.viewstate.velocity; + vec_t *angles = vs->angles; + vec4f_t velocity = vs->velocity; vec3_t ang = { }; ang[ROLL] = V_CalcRoll (angles, velocity); @@ -564,10 +545,10 @@ V_CalcViewRoll (void) if (v_dmg_time > 0) { ang[ROLL] += v_dmg_time / v_kicktime->value * v_dmg_roll; ang[PITCH] += v_dmg_time / v_kicktime->value * v_dmg_pitch; - v_dmg_time -= cl.viewstate.frametime; + v_dmg_time -= vs->frametime; } - if (cl.viewstate.flags & VF_DEAD) { // VF_GIB will also set VF_DEAD + if (vs->flags & VF_DEAD) { // VF_GIB will also set VF_DEAD ang[ROLL] = 80; // dead view angle } @@ -577,17 +558,17 @@ V_CalcViewRoll (void) } static void -V_CalcIntermissionRefdef (void) +V_CalcIntermissionRefdef (viewstate_t *vs) { - // ent is the player model (visible when out of body) - entity_t *ent = &cl_entities[cl.viewentity]; + // vs->player_entity is the player model (visible when out of body) + entity_t *ent = vs->player_entity; entity_t *view; float old; vec4f_t origin = Transform_GetWorldPosition (ent->transform); vec4f_t rotation = Transform_GetWorldRotation (ent->transform); // view is the weapon model (visible only from inside body) - view = &cl.viewent; + view = vs->weapon_entity; r_data->refdef->viewposition = origin; r_data->refdef->viewrotation = rotation; @@ -596,37 +577,37 @@ V_CalcIntermissionRefdef (void) // always idle in intermission old = v_idlescale->value; Cvar_SetValue (v_idlescale, 1); - V_AddIdle (); + V_AddIdle (vs); Cvar_SetValue (v_idlescale, old); } static void -V_CalcRefdef (void) +V_CalcRefdef (viewstate_t *vs) { // view is the weapon model (visible only from inside body) - entity_t *view = &cl.viewent; + entity_t *view = vs->weapon_entity; float bob; static float oldz = 0; vec4f_t forward = {}, right = {}, up = {}; - vec4f_t origin = cl.viewstate.origin; - vec_t *viewangles = cl.viewstate.angles; + vec4f_t origin = vs->origin; + vec_t *viewangles = vs->angles; - V_DriftPitch (); + V_DriftPitch (vs); - bob = V_CalcBob (); + bob = V_CalcBob (vs); // refresh position r_data->refdef->viewposition = origin; - r_data->refdef->viewposition[2] += cl.viewheight + bob; + r_data->refdef->viewposition[2] += vs->height + bob; // never let it sit exactly on a node line, because a water plane can // disappear when viewed with the eye exactly on it. // server protocol specifies to only 1/8 pixel, so add 1/16 in each axis r_data->refdef->viewposition += (vec4f_t) { 1.0/16, 1.0/16, 1.0/16, 0}; - AngleQuat (cl.viewstate.angles, &r_data->refdef->viewrotation[0]);//FIXME - V_CalcViewRoll (); - V_AddIdle (); + AngleQuat (vs->angles, &r_data->refdef->viewrotation[0]);//FIXME + V_CalcViewRoll (vs); + V_AddIdle (vs); // offsets //FIXME semi-duplicates AngleQuat (also, vec3_t vs vec4f_t) @@ -634,18 +615,18 @@ V_CalcRefdef (void) // don't allow cheats in multiplayer // FIXME check for dead - if (cl.maxclients == 1) { + if (vs->voffs_enabled) { r_data->refdef->viewposition += scr_ofsx->value * forward + scr_ofsy->value * right + scr_ofsz->value * up; } - V_BoundOffsets (); + V_BoundOffsets (vs); // set up gun position - CalcGunAngle (); + CalcGunAngle (vs); - origin += (vec4f_t) { 0, 0, cl.viewheight, 0 }; + origin += (vec4f_t) { 0, 0, vs->height, 0 }; origin += forward * bob * 0.4f + (vec4f_t) { 0, 0, bob, 0 }; // fudge position around to keep amount of weapon visible @@ -662,23 +643,23 @@ V_CalcRefdef (void) origin += (vec4f_t) { 0, 0, 0.5, 0}; } - model_t *model = cl.model_precache[cl.stats[STAT_WEAPON]]; + model_t *model = vs->weapon_model; if (view->renderer.model != model) { view->animation.pose2 = -1; } view->renderer.model = model; - view->animation.frame = cl.stats[STAT_WEAPONFRAME]; + view->animation.frame = vs->weaponframe; view->renderer.skin = 0; // set up the refresh position - r_data->refdef->viewrotation = qmulf (cl.viewstate.punchangle, + r_data->refdef->viewrotation = qmulf (vs->punchangle, r_data->refdef->viewrotation); // smooth out stair step ups - if ((cl.viewstate.onground != -1) && (origin[2] - oldz > 0)) { + if ((vs->onground != -1) && (origin[2] - oldz > 0)) { float steptime; - steptime = cl.viewstate.frametime; + steptime = vs->frametime; oldz += steptime * 80; if (oldz > origin[2]) @@ -696,8 +677,8 @@ V_CalcRefdef (void) CL_TransformEntity (view, 1, ang, origin); } - if (cl.chase && chase_active->int_val) { - Chase_Update (&cl.chasestate); + if (vs->chase && chase_active->int_val) { + Chase_Update (vs->chasestate); } } @@ -708,27 +689,28 @@ V_CalcRefdef (void) the entity origin, so any view position inside that will be valid */ void -V_RenderView (void) +V_RenderView (viewstate_t *vs) { - if (cls.state != ca_active) { + if (!vs->active) { r_data->refdef->viewposition = (vec4f_t) { 0, 0, 0, 1 }; r_data->refdef->viewrotation = (vec4f_t) { 0, 0, 0, 1 }; return; } - if (cl.intermission) { // intermission / finale rendering - V_CalcIntermissionRefdef (); + if (vs->intermission) { // intermission / finale rendering + V_CalcIntermissionRefdef (vs); } else { - V_CalcRefdef (); + V_CalcRefdef (vs); } } void V_Init (void) { - Cmd_AddCommand ("bf", V_BonusFlash_f, "Background flash, used when you " - "pick up an item"); - Cmd_AddCommand ("centerview", V_StartPitchDrift, "Centers the player's " + Cmd_AddDataCommand ("bf", V_BonusFlash_f, &cl.viewstate, + "Background flash, used when you pick up an item"); + Cmd_AddDataCommand ("centerview", V_StartPitchDrift_f, &cl.viewstate, + "Centers the player's " "view ahead after +lookup or +lookdown\n" "Will not work while mlook is active or freelook is 1."); Cmd_AddCommand ("v_cshift", V_cshift_f, "This adjusts all of the colors " diff --git a/qw/include/client.h b/qw/include/client.h index 1df0fe33f..cc2e586d2 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -191,9 +191,6 @@ typedef struct client_state_s { float item_gettime[32]; // cl.time of aquiring item, for blinking float faceanimtime; // Use anim frame if cl.time < this - cshift_t cshifts[NUM_CSHIFTS]; // Color shifts for damage, powerups - cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types - // the client simulates or interpolates movement to get these values double time; // this is the time value that the client // is rendering at. always <= realtime @@ -202,15 +199,8 @@ typedef struct client_state_s { viewstate_t viewstate; movestate_t movestate; chasestate_t chasestate; -// pitch drifting vars - float idealpitch; - float pitchvel; - qboolean nodrift; - float driftmove; - double laststop; qboolean paused; // Sent over by server - float viewheight; float crouch; // Local amount for smoothing stepups qboolean inwater; @@ -249,7 +239,6 @@ typedef struct client_state_s { int gametype; int maxclients; // serverinfo mirrors - int chase; int sv_cshifts; int no_pogo_stick; int teamplay; @@ -327,9 +316,9 @@ void CL_UpdateScreen (double realtime); void CL_SetState (cactive_t state); -void V_ParseDamage (void); +void V_ParseDamage (viewstate_t *vs); -void V_PrepBlend (void); +void V_PrepBlend (viewstate_t *vs); void CL_Cmd_ForwardToServer (void); void CL_Cmd_Init (void); diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 51a6fcee7..48a34cb9a 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -116,7 +116,7 @@ vectoangles (vec3_t vec, vec3_t ang) qboolean Cam_DrawViewModel (void) { - if (cl.chase && chase_active->int_val) + if (cl.viewstate.chase && chase_active->int_val) return false; if (!cl.spectator) @@ -132,7 +132,7 @@ qboolean Cam_DrawPlayer (int playernum) { if (playernum == cl.playernum) { // client player - if (cl.chase == 0 || chase_active->int_val == 0) + if (cl.viewstate.chase == 0 || chase_active->int_val == 0) return false; if (!cl.spectator) return true; @@ -141,7 +141,7 @@ Cam_DrawPlayer (int playernum) return true; if (cl.spectator && autocam && locked && spec_track == playernum) return false; - if (cl.chase == 0 || chase_active->int_val == 0) + if (cl.viewstate.chase == 0 || chase_active->int_val == 0) return true; } return false; diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 43dae8bd9..9fe4be0ea 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -91,7 +91,7 @@ CL_BaseMove (usercmd_t *cmd) return; } VectorCopy (cl.viewstate.angles, cl.movestate.angles);//FIXME - CL_Input_BuildMove (host_frametime, &cl.movestate); + CL_Input_BuildMove (host_frametime, &cl.movestate, &cl.viewstate); VectorCopy (cl.movestate.angles, cl.viewstate.angles);//FIXME memset (cmd, 0, sizeof (*cmd)); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index ee83578f2..8a4c02512 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -399,6 +399,8 @@ CL_ClearState (void) r_data->force_fullscreen = 0; cl.maxclients = MAX_CLIENTS; + cl.viewstate.voffs_enabled = 0; + cl.viewstate.chasestate = &cl.chasestate; // Note: we should probably hack around this and give diff values for // diff gamedirs @@ -410,6 +412,7 @@ CL_ClearState (void) cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING, 0); CL_Init_Entity (&cl.viewent); + cl.viewstate.weapon_entity = &cl.viewent; Sys_MaskPrintf (SYS_dev, "Clearing memory\n"); VID_ClearMemory (); @@ -439,7 +442,7 @@ CL_StopCshifts (void) int i; for (i = 0; i < NUM_CSHIFTS; i++) - cl.cshifts[i].percent = 0; + cl.viewstate.cshifts[i].percent = 0; for (i = 0; i < MAX_CL_STATS; i++) cl.stats[i] = 0; } @@ -618,9 +621,9 @@ CL_FullServerinfo_f (void) Sys_Printf ("Invalid QSG Protocol number: %s", p); } - cl.chase = cl.sv_cshifts = cl.no_pogo_stick = cl.teamplay = 0; + cl.viewstate.chase = cl.sv_cshifts = cl.no_pogo_stick = cl.teamplay = 0; if ((p = Info_ValueForKey (cl.serverinfo, "chase")) && *p) { - cl.chase = atoi (p); + cl.viewstate.chase = atoi (p); } if ((p = Info_ValueForKey (cl.serverinfo, "cshifts")) && *p) { cl.sv_cshifts = atoi (p); @@ -801,6 +804,7 @@ CL_Changing_f (void) S_StopAllSounds (); cl.intermission = 0; + cl.viewstate.intermission = 0; r_data->force_fullscreen = 0; CL_SetState (ca_connected); // not active anymore, but not // disconnected @@ -1141,6 +1145,8 @@ CL_SetState (cactive_t state) Sys_MaskPrintf (SYS_dev, "CL_SetState (%s)\n", state_names[state]); cls.state = state; + cl.viewstate.active = cls.state == ca_active; + cl.viewstate.drift_enabled = !cls.demoplayback; if (old_state != state) { if (old_state == ca_active) { // leaving active state diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index c0c37fb14..5e72ccee8 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -831,6 +831,8 @@ CL_ParseServerData (void) } cl.viewentity = cl.playernum + 1; + cl.viewstate.player_entity = &cl_entities[cl.viewentity]; + cl.viewstate.bob_enabled = !cl.spectator; // get the full level name str = MSG_ReadString (net_message); @@ -1216,7 +1218,7 @@ CL_ServerInfo (void) Info_SetValueForKey (cl.serverinfo, key, value, 0); if (strequal (key, "chase")) { - cl.chase = atoi (value); + cl.viewstate.chase = atoi (value); } else if (strequal (key, "cshifts")) { cl.sv_cshifts = atoi (value); } else if (strequal (key, "no_pogo_stick")) { @@ -1260,6 +1262,8 @@ CL_SetStat (int stat, int value) switch (stat) { case STAT_ITEMS: Sbar_Changed (); +#define IT_POWER (IT_QUAD | IT_SUIT | IT_INVULNERABILITY | IT_INVISIBILITY) + cl.viewstate.powerup_index = (cl.stats[STAT_ITEMS]&IT_POWER) >> 19; break; case STAT_HEALTH: if (cl_player_health_e->func) @@ -1270,6 +1274,7 @@ CL_SetStat (int stat, int value) break; } cl.stats[stat] = value; + cl.viewstate.weapon_model = cl.model_precache[cl.stats[STAT_WEAPON]]; } static void @@ -1501,7 +1506,9 @@ CL_ParseServerMessage (void) // svc_particle case svc_damage: - V_ParseDamage (); + V_ParseDamage (&cl.viewstate); + // put sbar face into pain frame + cl.faceanimtime = cl.time + 0.2; break; case svc_spawnstatic: diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 8eb1ecb3b..29af9187a 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -81,7 +81,7 @@ SCR_CShift (void) cl.worldmodel); contents = leaf->contents; } - V_SetContentsColor (contents); + V_SetContentsColor (&cl.viewstate, contents); r_funcs->Draw_BlendScreen (r_data->vid->cshift_color); } @@ -186,7 +186,18 @@ CL_UpdateScreen (double realtime) scr_funcs_normal[2] = r_funcs->SCR_DrawTurtle; scr_funcs_normal[3] = r_funcs->SCR_DrawPause; - V_PrepBlend (); - V_RenderView (); + if (cl.viewstate.flags & VF_GIB) { + cl.viewstate.height = 8; // gib view height + } else if (cl.viewstate.flags & VF_DEAD) { + cl.viewstate.height = -16; // corpse view height + } else { + cl.viewstate.height = DEFAULT_VIEWHEIGHT; // view height + if (cl.stdver) + cl.viewstate.height = cl.stats[STAT_VIEWHEIGHT]; + } + + cl.viewstate.intermission = cl.intermission != 0; + V_PrepBlend (&cl.viewstate); + V_RenderView (&cl.viewstate); SCR_UpdateScreen (realtime, scr_funcs[index]); } diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index 3527242bd..5eb642b7c 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -86,11 +86,37 @@ vec4f_t v_idle_yaw; vec4f_t v_idle_roll; vec4f_t v_idle_pitch; -cshift_t cshift_empty = { {130, 80, 50}, 0}; -cshift_t cshift_water = { {130, 80, 50}, 128}; -cshift_t cshift_slime = { {0, 25, 5}, 150}; -cshift_t cshift_lava = { {255, 80, 0}, 150}; -cshift_t cshift_bonus = { {215, 186, 60}, 50}; +static cshift_t cshift_empty = { {130, 80, 50}, 0}; +static cshift_t cshift_water = { {130, 80, 50}, 128}; +static cshift_t cshift_slime = { { 0, 25, 5}, 150}; +static cshift_t cshift_lava = { {255, 80, 0}, 150}; +static cshift_t cshift_bonus = { {215, 186, 60}, 50}; + +static cshift_t armor_blood[] = { + { {255, 0, 0} }, // blood + { {220, 50, 50} }, // armor + blood + { {200, 100, 100} }, // armor > blood need two for logic + { {200, 100, 100} }, // armor > blood need two for logic +}; + +static cshift_t powerup[] = { + { { 0, 0, 0}, 0}, + { {100, 100, 100}, 100}, // IT_INVISIBILITY + { {255, 255, 0}, 30}, // IT_INVULNERABILITY + { {255, 255, 0}, 30}, // IT_INVULNERABILITY + { { 0, 255, 0}, 20}, // IT_SUIT + { { 0, 255, 0}, 20}, // IT_SUIT + { { 0, 255, 0}, 20}, // IT_SUIT + { { 0, 255, 0}, 20}, // IT_SUIT + { { 0, 0, 255}, 30}, // IT_QUAD + { { 0, 0, 255}, 30}, // IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD + { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD +}; #define sqr(x) ((x) * (x)) @@ -116,20 +142,20 @@ V_CalcRoll (const vec3_t angles, vec4f_t velocity) } static float -V_CalcBob (void) +V_CalcBob (viewstate_t *vs) { - vec4f_t velocity = cl.viewstate.velocity; + vec4f_t velocity = vs->velocity; float cycle; static double bobtime; static float bob; - if (cl.spectator) + if (!vs->bob_enabled) return 0; - if (cl.viewstate.onground == -1) + if (vs->onground == -1) return bob; // just use old value - bobtime += cl.viewstate.frametime; + bobtime += vs->frametime; cycle = bobtime - (int) (bobtime / cl_bobcycle->value) * cl_bobcycle->value; cycle /= cl_bobcycle->value; @@ -151,31 +177,37 @@ V_CalcBob (void) } void -V_StartPitchDrift (void) +V_StartPitchDrift (viewstate_t *vs) { - if (cl.laststop == cl.time) { + if (vs->laststop == vs->time) { return; // something else is keeping it from drifting } - if (cl.nodrift || !cl.pitchvel) { - cl.pitchvel = v_centerspeed->value; - cl.nodrift = false; - cl.driftmove = 0; + if (vs->nodrift || !vs->pitchvel) { + vs->pitchvel = v_centerspeed->value; + vs->nodrift = false; + vs->driftmove = 0; } } -void -V_StopPitchDrift (void) +static void +V_StartPitchDrift_f (void *data) { - cl.laststop = cl.time; - cl.nodrift = true; - cl.pitchvel = 0; + V_StartPitchDrift (data); +} + +void +V_StopPitchDrift (viewstate_t *vs) +{ + vs->laststop = vs->time; + vs->nodrift = true; + vs->pitchvel = 0; } /* V_DriftPitch - Moves the client pitch angle towards cl.idealpitch sent by the server. + Moves the client pitch angle towards vs->idealpitch sent by the server. If the user is adjusting pitch manually, either with lookup/lookdown, mlook and mouse, or klook and keyboard, pitch drifting is constantly @@ -185,64 +217,64 @@ V_StopPitchDrift (void) and lookspring is non 0, or when */ static void -V_DriftPitch (void) +V_DriftPitch (viewstate_t *vs) { float delta, move; - float forwardmove = cl.viewstate.movecmd[0]; + float forwardmove = vs->movecmd[0]; - if (noclip_anglehack || cl.viewstate.onground == -1 || cls.demoplayback) { - cl.driftmove = 0; - cl.pitchvel = 0; + if (noclip_anglehack || vs->onground == -1 || !vs->drift_enabled) { + vs->driftmove = 0; + vs->pitchvel = 0; return; } // don't count small mouse motion - if (cl.nodrift) { + if (vs->nodrift) { if (fabs (forwardmove) < cl_forwardspeed->value) - cl.driftmove = 0; + vs->driftmove = 0; else - cl.driftmove += cl.viewstate.frametime; + vs->driftmove += vs->frametime; - if (cl.driftmove > v_centermove->value) { - V_StartPitchDrift (); + if (vs->driftmove > v_centermove->value) { + V_StartPitchDrift (vs); } return; } - delta = cl.idealpitch - cl.viewstate.angles[PITCH]; + delta = vs->idealpitch - vs->angles[PITCH]; if (!delta) { - cl.pitchvel = 0; + vs->pitchvel = 0; return; } - move = cl.viewstate.frametime * cl.pitchvel; - cl.pitchvel += cl.viewstate.frametime * v_centerspeed->value; + move = vs->frametime * vs->pitchvel; + vs->pitchvel += vs->frametime * v_centerspeed->value; if (delta > 0) { if (move > delta) { - cl.pitchvel = 0; + vs->pitchvel = 0; move = delta; } - cl.viewstate.angles[PITCH] += move; + vs->angles[PITCH] += move; } else if (delta < 0) { if (move > -delta) { - cl.pitchvel = 0; + vs->pitchvel = 0; move = -delta; } - cl.viewstate.angles[PITCH] -= move; + vs->angles[PITCH] -= move; } } /* PALETTE FLASHES */ void -V_ParseDamage (void) +V_ParseDamage (viewstate_t *vs) { float count, side; int armor, blood; - vec4f_t origin = cl.viewstate.origin; - vec_t *angles = cl.viewstate.angles; + vec4f_t origin = vs->origin; + vec_t *angles = vs->angles; vec3_t from, forward, right, up; armor = MSG_ReadByte (net_message); @@ -253,31 +285,15 @@ V_ParseDamage (void) if (count < 10) count = 10; - cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame - if (cl_cshift_damage->int_val - || (cl.sv_cshifts & INFO_CSHIFT_DAMAGE)) { - cshift_t *cshift = &cl.cshifts[CSHIFT_DAMAGE]; - - cshift->percent += 3 * count; - cshift->percent = - bound (0, cshift->percent, 150); - - if (armor > blood) { - cshift->destcolor[0] = 200; - cshift->destcolor[1] = 100; - cshift->destcolor[2] = 100; - } else if (armor) { - cshift->destcolor[0] = 220; - cshift->destcolor[1] = 50; - cshift->destcolor[2] = 50; - } else { - cshift->destcolor[0] = 255; - cshift->destcolor[1] = 0; - cshift->destcolor[2] = 0; - } + || (vs->force_cshifts & INFO_CSHIFT_DAMAGE)) { + cshift_t *cshift = &vs->cshifts[CSHIFT_DAMAGE]; + int percent = cshift->percent; + *cshift = armor_blood[(2 * (armor > blood)) + (armor > 0)]; + cshift->percent = percent + 3 * count; + cshift->percent = bound (0, cshift->percent, 150); cshift->initialpct = cshift->percent; - cshift->time = cl.time; + cshift->time = vs->time; } // calculate view angle kicks @@ -310,15 +326,16 @@ V_cshift_f (void) When you run over an item, the server sends this command */ static void -V_BonusFlash_f (void) +V_BonusFlash_f (void *data) { + viewstate_t *vs = data; if (!cl_cshift_bonus->int_val - && !(cl.sv_cshifts & INFO_CSHIFT_BONUS)) + && !(vs->force_cshifts & INFO_CSHIFT_BONUS)) return; - cl.cshifts[CSHIFT_BONUS] = cshift_bonus; - cl.cshifts[CSHIFT_BONUS].initialpct = cl.cshifts[CSHIFT_BONUS].percent; - cl.cshifts[CSHIFT_BONUS].time = cl.time; + vs->cshifts[CSHIFT_BONUS] = cshift_bonus; + vs->cshifts[CSHIFT_BONUS].initialpct = vs->cshifts[CSHIFT_BONUS].percent; + vs->cshifts[CSHIFT_BONUS].time = vs->time; } /* @@ -327,69 +344,34 @@ V_BonusFlash_f (void) Underwater, lava, etc each has a color shift */ void -V_SetContentsColor (int contents) +V_SetContentsColor (viewstate_t *vs, int contents) { if (!cl_cshift_contents->int_val - && !(cl.sv_cshifts & INFO_CSHIFT_CONTENTS)) { - cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; + && !(vs->force_cshifts & INFO_CSHIFT_CONTENTS)) { + vs->cshifts[CSHIFT_CONTENTS] = cshift_empty; return; } switch (contents) { case CONTENTS_EMPTY: - cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; + vs->cshifts[CSHIFT_CONTENTS] = cshift_empty; break; case CONTENTS_LAVA: - cl.cshifts[CSHIFT_CONTENTS] = cshift_lava; + vs->cshifts[CSHIFT_CONTENTS] = cshift_lava; break; case CONTENTS_SOLID: case CONTENTS_SLIME: - cl.cshifts[CSHIFT_CONTENTS] = cshift_slime; + vs->cshifts[CSHIFT_CONTENTS] = cshift_slime; break; default: - cl.cshifts[CSHIFT_CONTENTS] = cshift_water; + vs->cshifts[CSHIFT_CONTENTS] = cshift_water; } } static void -V_CalcPowerupCshift (void) +V_CalcPowerupCshift (viewstate_t *vs) { - if (!cl.stats[STAT_ITEMS] & (IT_SUIT || IT_INVISIBILITY || IT_QUAD - || IT_INVULNERABILITY)) - { - cl.cshifts[CSHIFT_POWERUP].percent = 0; - return; - } - - if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY && - cl.stats[STAT_ITEMS] & IT_QUAD) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } else if (cl.stats[STAT_ITEMS] & IT_QUAD) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 30; - } else if (cl.stats[STAT_ITEMS] & IT_SUIT) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 20; - } else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) { - cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100; - cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100; - cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100; - cl.cshifts[CSHIFT_POWERUP].percent = 100; - } else { - cl.cshifts[CSHIFT_POWERUP].percent = 0; - } + vs->cshifts[CSHIFT_POWERUP] = powerup[vs->powerup_index]; } /* @@ -399,22 +381,22 @@ V_CalcPowerupCshift (void) a bit, but otherwise this is his code. --KB */ static void -V_CalcBlend (void) +V_CalcBlend (viewstate_t *vs) { float a2, a3; float r = 0, g = 0, b = 0, a = 0; int i; for (i = 0; i < NUM_CSHIFTS; i++) { - a2 = cl.cshifts[i].percent / 255.0; + a2 = vs->cshifts[i].percent / 255.0; if (!a2) continue; a2 = min (a2, 1.0); - r += (cl.cshifts[i].destcolor[0] - r) * a2; - g += (cl.cshifts[i].destcolor[1] - g) * a2; - b += (cl.cshifts[i].destcolor[2] - b) * a2; + r += (vs->cshifts[i].destcolor[0] - r) * a2; + g += (vs->cshifts[i].destcolor[1] - g) * a2; + b += (vs->cshifts[i].destcolor[2] - b) * a2; a3 = (1.0 - a) * (1.0 - a2); a = 1.0 - a3; @@ -435,12 +417,12 @@ V_CalcBlend (void) } static void -V_DropCShift (cshift_t *cs, float droprate) +V_DropCShift (cshift_t *cs, double time, float droprate) { if (cs->time < 0) { cs->percent = 0; } else { - cs->percent = cs->initialpct - (cl.time - cs->time) * droprate; + cs->percent = cs->initialpct - (time - cs->time) * droprate; if (cs->percent <= 0) { cs->percent = 0; cs->time = -1; @@ -449,56 +431,55 @@ V_DropCShift (cshift_t *cs, float droprate) } void -V_PrepBlend (void) +V_PrepBlend (viewstate_t *vs) { int i, j; if (cl_cshift_powerup->int_val - || (cl.sv_cshifts & INFO_CSHIFT_POWERUP)) - V_CalcPowerupCshift (); + || (vs->force_cshifts & INFO_CSHIFT_POWERUP)) + V_CalcPowerupCshift (vs); r_data->vid->cshift_changed = false; for (i = 0; i < NUM_CSHIFTS; i++) { - if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent) { + if (vs->cshifts[i].percent != vs->prev_cshifts[i].percent) { r_data->vid->cshift_changed = true; - cl.prev_cshifts[i].percent = cl.cshifts[i].percent; + vs->prev_cshifts[i].percent = vs->cshifts[i].percent; } for (j = 0; j < 3; j++) { - if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j]) + if (vs->cshifts[i].destcolor[j] != vs->prev_cshifts[i].destcolor[j]) { r_data->vid->cshift_changed = true; - cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j]; + vs->prev_cshifts[i].destcolor[j] = vs->cshifts[i].destcolor[j]; } } } // drop the damage value - V_DropCShift (&cl.cshifts[CSHIFT_DAMAGE], 150); + V_DropCShift (&vs->cshifts[CSHIFT_DAMAGE], vs->time, 150); // drop the bonus value - V_DropCShift (&cl.cshifts[CSHIFT_BONUS], 100); + V_DropCShift (&vs->cshifts[CSHIFT_BONUS], vs->time, 100); if (!r_data->vid->cshift_changed && !r_data->vid->recalc_refdef) return; - V_CalcBlend (); + V_CalcBlend (vs); } /* VIEW RENDERING */ static void -CalcGunAngle (void) +CalcGunAngle (viewstate_t *vs) { vec4f_t rotation = r_data->refdef->viewrotation; //FIXME make child of camera - Transform_SetWorldRotation (cl.viewent.transform, rotation); + Transform_SetWorldRotation (vs->weapon_entity->transform, rotation); } static void -V_BoundOffsets (void) +V_BoundOffsets (viewstate_t *vs) { - vec4f_t offset = r_data->refdef->viewposition - - cl.viewstate.origin; + vec4f_t offset = r_data->refdef->viewposition - vs->origin; // absolutely bound refresh reletive to entity clipping hull // so the view can never be inside a solid wall @@ -506,17 +487,17 @@ V_BoundOffsets (void) offset[0] = bound (-14, offset[0], 14); offset[1] = bound (-14, offset[1], 14); offset[2] = bound (-22, offset[2], 30); - r_data->refdef->viewposition = cl.viewstate.origin + offset; + r_data->refdef->viewposition = vs->origin + offset; } static vec4f_t -idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level) +idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level, double time) { vec4f_t identity = { 0, 0, 0, 1 }; if (!level || !cycle) { return identity; } - float scale = sin (cl.time * cycle->value); + float scale = sin (time * cycle->value); float ang = scale * level->value * v_idlescale->value; float c = cos (ang * M_PI / 360); float s = sin (ang * M_PI / 360); @@ -529,14 +510,14 @@ idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level) Idle swaying */ static void -V_AddIdle (void) +V_AddIdle (viewstate_t *vs) { vec4f_t roll = idle_quat ((vec4f_t) { 1, 0, 0, 0}, - v_iroll_cycle, v_iroll_level); + v_iroll_cycle, v_iroll_level, vs->time); vec4f_t pitch = idle_quat ((vec4f_t) { 0, 1, 0, 0}, - v_ipitch_cycle, v_ipitch_level); + v_ipitch_cycle, v_ipitch_level, vs->time); vec4f_t yaw = idle_quat ((vec4f_t) { 0, 0, 1, 0}, - v_iyaw_cycle, v_iyaw_level); + v_iyaw_cycle, v_iyaw_level, vs->time); vec4f_t rot = normalf (qmulf (yaw, qmulf (pitch, roll))); // rotate the view @@ -544,8 +525,8 @@ V_AddIdle (void) // counter-rotate the weapon rot = qmulf (qconjf (rot), - Transform_GetWorldRotation (cl.viewent.transform)); - Transform_SetWorldRotation (cl.viewent.transform, rot); + Transform_GetWorldRotation (vs->weapon_entity->transform)); + Transform_SetWorldRotation (vs->weapon_entity->transform, rot); } /* @@ -554,10 +535,10 @@ V_AddIdle (void) Roll is induced by movement and damage */ static void -V_CalcViewRoll (void) +V_CalcViewRoll (viewstate_t *vs) { - vec_t *angles = cl.viewstate.angles; - vec4f_t velocity = cl.viewstate.velocity; + vec_t *angles = vs->angles; + vec4f_t velocity = vs->velocity; vec3_t ang = { }; ang[ROLL] = V_CalcRoll (angles, velocity); @@ -565,10 +546,10 @@ V_CalcViewRoll (void) if (v_dmg_time > 0) { ang[ROLL] += v_dmg_time / v_kicktime->value * v_dmg_roll; ang[PITCH] += v_dmg_time / v_kicktime->value * v_dmg_pitch; - v_dmg_time -= cl.viewstate.frametime; + v_dmg_time -= vs->frametime; } - if (cl.viewstate.flags & VF_DEAD) { // VF_GIB will also set VF_DEAD + if (vs->flags & VF_DEAD) { // VF_GIB will also set VF_DEAD ang[ROLL] = 80; // dead view angle } @@ -578,17 +559,17 @@ V_CalcViewRoll (void) } static void -V_CalcIntermissionRefdef (void) +V_CalcIntermissionRefdef (viewstate_t *vs) { - // ent is the player model (visible when out of body) - entity_t *ent = &cl_entities[cl.viewentity]; + // vs->player_entity is the player model (visible when out of body) + entity_t *ent = vs->player_entity; entity_t *view; float old; vec4f_t origin = Transform_GetWorldPosition (ent->transform); vec4f_t rotation = Transform_GetWorldRotation (ent->transform); // view is the weapon model (visible only from inside body) - view = &cl.viewent; + view = vs->weapon_entity; r_data->refdef->viewposition = origin; r_data->refdef->viewrotation = rotation; @@ -597,37 +578,37 @@ V_CalcIntermissionRefdef (void) // always idle in intermission old = v_idlescale->value; Cvar_SetValue (v_idlescale, 1); - V_AddIdle (); + V_AddIdle (vs); Cvar_SetValue (v_idlescale, old); } static void -V_CalcRefdef (void) +V_CalcRefdef (viewstate_t *vs) { // view is the weapon model (visible only from inside body) - entity_t *view = &cl.viewent; + entity_t *view = vs->weapon_entity; float bob; static float oldz = 0; vec4f_t forward = {}, right = {}, up = {}; - vec4f_t origin = cl.viewstate.origin; - vec_t *viewangles = cl.viewstate.angles; + vec4f_t origin = vs->origin; + vec_t *viewangles = vs->angles; - V_DriftPitch (); + V_DriftPitch (vs); - bob = V_CalcBob (); + bob = V_CalcBob (vs); // refresh position r_data->refdef->viewposition = origin; - r_data->refdef->viewposition[2] += cl.viewheight + bob; + r_data->refdef->viewposition[2] += vs->height + bob; // never let it sit exactly on a node line, because a water plane can // disappear when viewed with the eye exactly on it. // server protocol specifies to only 1/8 pixel, so add 1/16 in each axis r_data->refdef->viewposition += (vec4f_t) { 1.0/16, 1.0/16, 1.0/16, 0}; - AngleQuat (cl.viewstate.angles, &r_data->refdef->viewrotation[0]);//FIXME - V_CalcViewRoll (); - V_AddIdle (); + AngleQuat (vs->angles, &r_data->refdef->viewrotation[0]);//FIXME + V_CalcViewRoll (vs); + V_AddIdle (vs); // offsets //FIXME semi-duplicates AngleQuat (also, vec3_t vs vec4f_t) @@ -635,18 +616,18 @@ V_CalcRefdef (void) // don't allow cheats in multiplayer // FIXME check for dead - if (cl.maxclients == 1) { + if (vs->voffs_enabled) { r_data->refdef->viewposition += scr_ofsx->value * forward + scr_ofsy->value * right + scr_ofsz->value * up; } - V_BoundOffsets (); + V_BoundOffsets (vs); // set up gun position - CalcGunAngle (); + CalcGunAngle (vs); - origin += (vec4f_t) { 0, 0, cl.viewheight, 0 }; + origin += (vec4f_t) { 0, 0, vs->height, 0 }; origin += forward * bob * 0.4f + (vec4f_t) { 0, 0, bob, 0 }; // fudge position around to keep amount of weapon visible @@ -663,26 +644,26 @@ V_CalcRefdef (void) origin += (vec4f_t) { 0, 0, 0.5, 0}; } - model_t *model = cl.model_precache[cl.stats[STAT_WEAPON]]; - if (cl.viewstate.flags & (VF_GIB | VF_DEAD)) { + model_t *model = vs->weapon_model; + if (vs->flags & (VF_GIB | VF_DEAD)) { model = NULL; } if (view->renderer.model != model) { view->animation.pose2 = -1; } view->renderer.model = model; - view->animation.frame = cl.viewstate.weaponframe; + view->animation.frame = vs->weaponframe; view->renderer.skin = 0; // set up the refresh position - r_data->refdef->viewrotation = qmulf (cl.viewstate.punchangle, + r_data->refdef->viewrotation = qmulf (vs->punchangle, r_data->refdef->viewrotation); // smooth out stair step ups - if ((cl.viewstate.onground != -1) && (origin[2] - oldz > 0)) { + if ((vs->onground != -1) && (origin[2] - oldz > 0)) { float steptime; - steptime = cl.viewstate.frametime; + steptime = vs->frametime; oldz += steptime * 80; if (oldz > origin[2]) @@ -700,29 +681,29 @@ V_CalcRefdef (void) CL_TransformEntity (view, 1, ang, origin); } - if (cl.chase && chase_active->int_val) { - Chase_Update (&cl.chasestate); + if (vs->chase && chase_active->int_val) { + Chase_Update (vs->chasestate); } } static void -DropPunchAngle (void) +DropPunchAngle (viewstate_t *vs) { - vec4f_t punch = cl.viewstate.punchangle; + vec4f_t punch = vs->punchangle; float ps = magnitude3f (punch)[0]; if (ps < 1e-3) { // < 0.2 degree rotation, not worth worrying about //ensure the quaternion is normalized - cl.viewstate.punchangle = (vec4f_t) { 0, 0, 0, 1 }; + vs->punchangle = (vec4f_t) { 0, 0, 0, 1 }; return; } float pc = punch[3]; - float ds = 0.0871557427 * cl.viewstate.frametime; + float ds = 0.0871557427 * vs->frametime; float dc = sqrt (1 - ds * ds); float s = ps * dc - pc * ds; float c = pc * dc + ps * ds; if (s <= 0 || c >= 1) { - cl.viewstate.punchangle = (vec4f_t) { 0, 0, 0, 1 }; + vs->punchangle = (vec4f_t) { 0, 0, 0, 1 }; } else { punch *= s / ps; punch[3] = c; @@ -736,38 +717,29 @@ DropPunchAngle (void) the entity origin, so any view position inside that will be valid */ void -V_RenderView (void) +V_RenderView (viewstate_t *vs) { - if (cls.state != ca_active) { + if (!vs->active) { r_data->refdef->viewposition = (vec4f_t) { 0, 0, 0, 1 }; r_data->refdef->viewrotation = (vec4f_t) { 0, 0, 0, 1 }; return; } - if (cl.viewstate.flags & VF_GIB) { - cl.viewheight = 8; // gib view height - } else if (cl.viewstate.flags & VF_DEAD) { - cl.viewheight = -16; // corpse view height + DropPunchAngle (vs); + if (vs->intermission) { // intermission / finale rendering + V_CalcIntermissionRefdef (vs); } else { - cl.viewheight = DEFAULT_VIEWHEIGHT; // view height - if (cl.stdver) - cl.viewheight = cl.stats[STAT_VIEWHEIGHT]; - } - - DropPunchAngle (); - if (cl.intermission) { // intermission / finale rendering - V_CalcIntermissionRefdef (); - } else { - V_CalcRefdef (); + V_CalcRefdef (vs); } } void V_Init (void) { - Cmd_AddCommand ("bf", V_BonusFlash_f, "Background flash, used when you " - "pick up an item"); - Cmd_AddCommand ("centerview", V_StartPitchDrift, "Centers the player's " + Cmd_AddDataCommand ("bf", V_BonusFlash_f, &cl.viewstate, + "Background flash, used when you pick up an item"); + Cmd_AddDataCommand ("centerview", V_StartPitchDrift_f, &cl.viewstate, + "Centers the player's " "view ahead after +lookup or +lookdown\n" "Will not work while mlook is active or freelook is 1."); Cmd_AddCommand ("v_cshift", V_cshift_f, "This adjusts all of the colors " From 7d059a0b562d3dace7b2fc4cb93c5764fd6ec6b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Feb 2022 12:12:51 +0900 Subject: [PATCH 2472/3664] [client] Merge nq and qw cl_view They've been near-identical for years, now they're only one. It proved necessary to start merging the HUD code which for now is just a few cvar declarations (not even init), but that should be a separate set of commits. --- include/Makemodule.am | 3 +- include/client/hud.h | 35 ++ include/client/view.h | 16 +- libs/client/Makemodule.am | 2 + {qw/source => libs/client}/cl_view.c | 39 +- libs/client/hud.c | 36 ++ nq/include/client.h | 8 - nq/include/host.h | 2 - nq/source/Makemodule.am | 2 +- nq/source/cl_main.c | 15 +- nq/source/cl_parse.c | 2 +- nq/source/cl_view.c | 773 --------------------------- nq/source/sbar.c | 5 +- qw/include/client.h | 7 - qw/include/host.h | 2 - qw/source/Makemodule.am | 1 - qw/source/cl_main.c | 16 +- qw/source/cl_parse.c | 2 +- qw/source/cl_screen.c | 1 + qw/source/sbar.c | 5 +- 20 files changed, 123 insertions(+), 849 deletions(-) create mode 100644 include/client/hud.h rename {qw/source => libs/client}/cl_view.c (95%) create mode 100644 libs/client/hud.c delete mode 100644 nq/source/cl_view.c diff --git a/include/Makemodule.am b/include/Makemodule.am index 40c448f33..01bdc2a69 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -84,11 +84,12 @@ EXTRA_DIST += \ include/world.h \ include/client/effects.h \ include/client/entities.h \ + include/client/hud.h \ include/client/input.h \ - include/client/temp_entities.h \ include/client/locs.h \ include/client/particles.h \ include/client/state.h \ + include/client/temp_entities.h \ include/client/view.h \ include/evdev/hotplug.h \ include/evdev/inputlib.h \ diff --git a/include/client/hud.h b/include/client/hud.h new file mode 100644 index 000000000..31b4d5542 --- /dev/null +++ b/include/client/hud.h @@ -0,0 +1,35 @@ +/* + hud.h + + Heads-up display + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __client_hud_h_ +#define __client_hud_h_ + +extern struct cvar_s *hud_sbar; +extern struct cvar_s *hud_scoreboard_gravity; +extern struct cvar_s *hud_swap; + +#endif // __client_hud_h_ diff --git a/include/client/view.h b/include/client/view.h index b0419e165..ea7712a31 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -26,8 +26,8 @@ */ // view.h -#ifndef __client_view_h_ -#define __client_view_h_ +#ifndef __client_view_h +#define __client_view_h #include "QF/mathlib.h" #include "QF/render.h" @@ -54,6 +54,7 @@ typedef struct viewstate_s { int voffs_enabled:1; int bob_enabled:1; int intermission:1; + int decay_punchangle:1; int force_cshifts; // bitfield of server enforced cshifts uint32_t flags; @@ -79,13 +80,18 @@ typedef struct viewstate_s { #define VF_DEAD 1 #define VF_GIB 2 -void V_Init (void); +struct msg_s; + +void V_Init (viewstate_t *vs); void V_Init_Cvars (void); void V_RenderView (viewstate_t *vs); float V_CalcRoll (const vec3_t angles, vec4f_t velocity); void V_StartPitchDrift (viewstate_t *vs); void V_StopPitchDrift (viewstate_t *vs); - void V_SetContentsColor (viewstate_t *vs, int contents); +void V_ParseDamage (struct msg_s *net_message, viewstate_t *vs); +void V_PrepBlend (viewstate_t *vs); -#endif // __client_view_h_ +extern qboolean noclip_anglehack; + +#endif // __client_view_h diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 397eacc9f..14e52a315 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -9,6 +9,8 @@ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_input.c \ libs/client/cl_particles.c \ libs/client/cl_temp_entities.c \ + libs/client/cl_view.c \ + libs/client/hud.c \ libs/client/locs.c \ libs/client/old_keys.c diff --git a/qw/source/cl_view.c b/libs/client/cl_view.c similarity index 95% rename from qw/source/cl_view.c rename to libs/client/cl_view.c index 5eb642b7c..6eb3c20d8 100644 --- a/qw/source/cl_view.c +++ b/libs/client/cl_view.c @@ -33,18 +33,17 @@ #include "QF/msg.h" #include "QF/screen.h" +#include "QF/plugin/vid_render.h" +#include "QF/scene/transform.h" #include "QF/simd/vec4f.h" #include "compat.h" -#include "qw/bothdefs.h" - #include "client/chase.h" -#include "qw/include/cl_cam.h" -#include "qw/include/cl_ents.h" -#include "qw/include/cl_main.h" -#include "qw/include/client.h" -#include "qw/include/host.h" +#include "client/entities.h" +#include "client/hud.h" +#include "client/input.h" +#include "client/view.h" /* The view is allowed to move slightly from it's true position for bobbing, @@ -71,6 +70,11 @@ cvar_t *v_kicktime; cvar_t *v_kickroll; cvar_t *v_kickpitch; +cvar_t *cl_cshift_bonus; +cvar_t *cl_cshift_contents; +cvar_t *cl_cshift_damage; +cvar_t *cl_cshift_powerup; + cvar_t *v_iyaw_cycle; cvar_t *v_iroll_cycle; cvar_t *v_ipitch_cycle; @@ -269,7 +273,7 @@ V_DriftPitch (viewstate_t *vs) /* PALETTE FLASHES */ void -V_ParseDamage (viewstate_t *vs) +V_ParseDamage (qmsg_t *net_message, viewstate_t *vs) { float count, side; int armor, blood; @@ -725,7 +729,9 @@ V_RenderView (viewstate_t *vs) return; } - DropPunchAngle (vs); + if (vs->decay_punchangle) { + DropPunchAngle (vs); + } if (vs->intermission) { // intermission / finale rendering V_CalcIntermissionRefdef (vs); } else { @@ -734,11 +740,11 @@ V_RenderView (viewstate_t *vs) } void -V_Init (void) +V_Init (viewstate_t *viewstate) { - Cmd_AddDataCommand ("bf", V_BonusFlash_f, &cl.viewstate, + Cmd_AddDataCommand ("bf", V_BonusFlash_f, viewstate, "Background flash, used when you pick up an item"); - Cmd_AddDataCommand ("centerview", V_StartPitchDrift_f, &cl.viewstate, + Cmd_AddDataCommand ("centerview", V_StartPitchDrift_f, viewstate, "Centers the player's " "view ahead after +lookup or +lookdown\n" "Will not work while mlook is active or freelook is 1."); @@ -799,4 +805,13 @@ V_Init_Cvars (void) "How much you lean when hit"); v_kickpitch = Cvar_Get ("v_kickpitch", "0.6", CVAR_NONE, NULL, "How much you look up when hit"); + cl_cshift_bonus = Cvar_Get ("cl_cshift_bonus", "1", CVAR_ARCHIVE, NULL, + "Show bonus flash on item pickup"); + cl_cshift_contents = Cvar_Get ("cl_cshift_content", "1", CVAR_ARCHIVE, + NULL, "Shift view colors for contents " + "(water, slime, etc)"); + cl_cshift_damage = Cvar_Get ("cl_cshift_damage", "1", CVAR_ARCHIVE, NULL, + "Shift view colors on damage"); + cl_cshift_powerup = Cvar_Get ("cl_cshift_powerup", "1", CVAR_ARCHIVE, NULL, + "Shift view colors for powerups"); } diff --git a/libs/client/hud.c b/libs/client/hud.c new file mode 100644 index 000000000..2d8f880ed --- /dev/null +++ b/libs/client/hud.c @@ -0,0 +1,36 @@ +/* + hud.c + + Heads-up display bar + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/cvar.h" + +cvar_t *hud_sbar; +cvar_t *hud_scoreboard_gravity; +cvar_t *hud_swap; diff --git a/nq/include/client.h b/nq/include/client.h index 3aed4fb9e..6437cf81f 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -226,8 +226,6 @@ extern struct cvar_s *cl_autofire; extern struct cvar_s *cl_shownet; extern struct cvar_s *cl_nolerp; -extern struct cvar_s *hud_sbar; - extern struct cvar_s *cl_pitchdriftspeed; extern struct cvar_s *cl_name; @@ -297,12 +295,6 @@ void CL_ParseServerMessage (void); void CL_NewTranslation (int slot, struct skin_s *skin); -// view -void V_UpdatePalette (void); -void V_Register (void); -void V_ParseDamage (viewstate_t *vs); -void V_PrepBlend (viewstate_t *vs); - // cl_tent void CL_SignonReply (void); void CL_RelinkEntities (void); diff --git a/nq/include/host.h b/nq/include/host.h index 8a6ab52c9..70c7327f9 100644 --- a/nq/include/host.h +++ b/nq/include/host.h @@ -30,8 +30,6 @@ #include "QF/qtypes.h" -extern qboolean noclip_anglehack; - typedef struct { int argc; diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 0c05bb277..4d1a88955 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -72,7 +72,7 @@ nq_server_LIB_DEPS=$(nq_server_LIBFILES) $(nq_common_LIBFILES) nq_source_libnq_client_a_SOURCES= \ nq/source/cl_cmd.c nq/source/cl_demo.c nq/source/cl_ents.c nq/source/cl_input.c nq/source/cl_main.c \ - nq/source/cl_screen.c nq/source/cl_parse.c nq/source/cl_view.c nq/source/sbar.c + nq/source/cl_screen.c nq/source/cl_parse.c nq/source/sbar.c nq_source_libnq_server_a_SOURCES= \ nq/source/host.c nq/source/host_cmd.c nq/source/sv_cl_phys.c nq/source/sv_cvar.c nq/source/sv_main.c \ diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 80b97fe01..ca17c7d9d 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -76,11 +76,6 @@ cvar_t *cl_writecfg; cvar_t *cl_shownet; cvar_t *cl_nolerp; -cvar_t *cl_cshift_bonus; -cvar_t *cl_cshift_contents; -cvar_t *cl_cshift_damage; -cvar_t *cl_cshift_powerup; - cvar_t *hud_fps; cvar_t *hud_time; @@ -171,14 +166,6 @@ CL_InitCvars (void) Chase_Init_Cvars (); V_Init_Cvars (); - cl_cshift_bonus = Cvar_Get ("cl_cshift_bonus", "1", CVAR_ARCHIVE, NULL, - "Show bonus flash on item pickup"); - cl_cshift_contents = Cvar_Get ("cl_cshift_content", "1", CVAR_ARCHIVE, - NULL, "Shift view colors for contents " - "(water, slime, etc)"); - cl_cshift_damage = Cvar_Get ("cl_cshift_damage", "1", CVAR_ARCHIVE, NULL, - "Shift view colors on damage"); - cl_cshift_powerup = Cvar_Get ("cl_cshift_powerup", "1", CVAR_ARCHIVE, NULL, "Shift view colors for powerups"); cl_name = Cvar_Get ("_cl_name", "player", CVAR_ARCHIVE, NULL, "Player name"); cl_color = Cvar_Get ("_cl_color", "0", CVAR_ARCHIVE, NULL, "Player color"); @@ -582,7 +569,7 @@ CL_Init (cbuf_t *cbuf) CL_TEnts_Init (); CL_ClearState (); - V_Init (); + V_Init (&cl.viewstate); Cmd_AddCommand ("pointfile", pointfile_f, "Load a pointfile to determine map leaks."); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 76d9f8021..595bec0a7 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -1054,7 +1054,7 @@ CL_ParseServerMessage (void) break; case svc_damage: - V_ParseDamage (&cl.viewstate); + V_ParseDamage (net_message, &cl.viewstate); // put sbar face into pain frame cl.faceanimtime = cl.time + 0.2; break; diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c deleted file mode 100644 index 42db23b44..000000000 --- a/nq/source/cl_view.c +++ /dev/null @@ -1,773 +0,0 @@ -/* - cl_view.c - - player eye positioning - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "QF/cmd.h" -#include "QF/cvar.h" -#include "QF/msg.h" -#include "QF/screen.h" - -#include "QF/simd/vec4f.h" - -#include "QF/plugin/vid_render.h" -#include "QF/scene/entity.h" - -#include "compat.h" - -#include "client/chase.h" - -#include "nq/include/client.h" -#include "nq/include/host.h" - -/* - The view is allowed to move slightly from it's true position for bobbing, - but if it exceeds 8 pixels linear distance (spherical, not box), the list - of entities sent from the server may not include everything in the pvs, - especially when crossing a water boudnary. -*/ - -cvar_t *scr_ofsx; -cvar_t *scr_ofsy; -cvar_t *scr_ofsz; - -cvar_t *cl_rollspeed; -cvar_t *cl_rollangle; - -cvar_t *cl_bob; -cvar_t *cl_bobcycle; -cvar_t *cl_bobup; - -cvar_t *v_centermove; -cvar_t *v_centerspeed; - -cvar_t *v_kicktime; -cvar_t *v_kickroll; -cvar_t *v_kickpitch; - -cvar_t *v_iyaw_cycle; -cvar_t *v_iroll_cycle; -cvar_t *v_ipitch_cycle; -cvar_t *v_iyaw_level; -cvar_t *v_iroll_level; -cvar_t *v_ipitch_level; - -cvar_t *v_idlescale; - -float v_dmg_time, v_dmg_roll, v_dmg_pitch; - -vec4f_t v_idle_yaw; -vec4f_t v_idle_roll; -vec4f_t v_idle_pitch; - -static cshift_t cshift_empty = { {130, 80, 50}, 0}; -static cshift_t cshift_water = { {130, 80, 50}, 128}; -static cshift_t cshift_slime = { { 0, 25, 5}, 150}; -static cshift_t cshift_lava = { {255, 80, 0}, 150}; -static cshift_t cshift_bonus = { {215, 186, 60}, 50}; - -static cshift_t armor_blood[] = { - { {255, 0, 0} }, // blood - { {220, 50, 50} }, // armor + blood - { {200, 100, 100} }, // armor > blood need two for logic - { {200, 100, 100} }, // armor > blood need two for logic -}; - -static cshift_t powerup[] = { - { { 0, 0, 0}, 0}, - { {100, 100, 100}, 100}, // IT_INVISIBILITY - { {255, 255, 0}, 30}, // IT_INVULNERABILITY - { {255, 255, 0}, 30}, // IT_INVULNERABILITY - { { 0, 255, 0}, 20}, // IT_SUIT - { { 0, 255, 0}, 20}, // IT_SUIT - { { 0, 255, 0}, 20}, // IT_SUIT - { { 0, 255, 0}, 20}, // IT_SUIT - { { 0, 0, 255}, 30}, // IT_QUAD - { { 0, 0, 255}, 30}, // IT_QUAD - { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD - { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD - { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD - { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD - { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD - { {255, 0, 255}, 30}, // IT_INVULNERABILITY | IT_QUAD -}; - -#define sqr(x) ((x) * (x)) - -float -V_CalcRoll (const vec3_t angles, vec4f_t velocity) -{ - float side, sign, value; - vec3_t forward, right, up; - - AngleVectors (angles, forward, right, up); - side = DotProduct (velocity, right); - sign = side < 0 ? -1 : 1; - side = fabs (side); - - value = cl_rollangle->value; - - if (side < cl_rollspeed->value) - side = side * value / cl_rollspeed->value; - else - side = value; - - return side * sign; -} - -static float -V_CalcBob (viewstate_t *vs) -{ - vec4f_t velocity = vs->velocity; - float cycle; - static double bobtime; - static float bob; - - if (!vs->bob_enabled) - return 0; - - if (vs->onground == -1) - return bob; // just use old value - - bobtime += vs->frametime; - cycle = bobtime - (int) (bobtime / cl_bobcycle->value) * - cl_bobcycle->value; - cycle /= cl_bobcycle->value; - if (cycle < cl_bobup->value) - cycle = cycle / cl_bobup->value; - else - cycle = 1 + (cycle - cl_bobup->value) / (1.0 - cl_bobup->value); - - // bob is proportional to velocity in the xy plane - // (don't count Z, or jumping messes it up) - velocity[2] = 0; - bob = sqrt (dotf (velocity, velocity)[0]) * cl_bob->value; - bob = bob * 0.3 + bob * 0.7 * sin (cycle * M_PI); - if (bob > 4) - bob = 4; - else if (bob < -7) - bob = -7; - return bob; -} - -void -V_StartPitchDrift (viewstate_t *vs) -{ - if (vs->laststop == vs->time) { - return; // something else is keeping it from drifting - } - - if (vs->nodrift || !vs->pitchvel) { - vs->pitchvel = v_centerspeed->value; - vs->nodrift = false; - vs->driftmove = 0; - } -} - -static void -V_StartPitchDrift_f (void *data) -{ - V_StartPitchDrift (data); -} - -void -V_StopPitchDrift (viewstate_t *vs) -{ - vs->laststop = vs->time; - vs->nodrift = true; - vs->pitchvel = 0; -} - -/* - V_DriftPitch - - Moves the client pitch angle towards vs->idealpitch sent by the server. - - If the user is adjusting pitch manually, either with lookup/lookdown, - mlook and mouse, or klook and keyboard, pitch drifting is constantly - stopped. - - Drifting is enabled when the center view key is hit, mlook is released - and lookspring is non 0, or when -*/ -static void -V_DriftPitch (viewstate_t *vs) -{ - float delta, move; - float forwardmove = vs->movecmd[0]; - - if (noclip_anglehack || vs->onground == -1 || !vs->drift_enabled) { - vs->driftmove = 0; - vs->pitchvel = 0; - return; - } - - // don't count small mouse motion - if (vs->nodrift) { - if (fabs (forwardmove) < cl_forwardspeed->value) - vs->driftmove = 0; - else - vs->driftmove += vs->frametime; - - if (vs->driftmove > v_centermove->value) { - V_StartPitchDrift (vs); - } - return; - } - - delta = vs->idealpitch - vs->angles[PITCH]; - - if (!delta) { - vs->pitchvel = 0; - return; - } - - move = vs->frametime * vs->pitchvel; - vs->pitchvel += vs->frametime * v_centerspeed->value; - - if (delta > 0) { - if (move > delta) { - vs->pitchvel = 0; - move = delta; - } - vs->angles[PITCH] += move; - } else if (delta < 0) { - if (move > -delta) { - vs->pitchvel = 0; - move = -delta; - } - vs->angles[PITCH] -= move; - } -} - -/* PALETTE FLASHES */ - -void -V_ParseDamage (viewstate_t *vs) -{ - float count, side; - int armor, blood; - vec4f_t origin = vs->origin; - vec_t *angles = vs->angles; - vec3_t from, forward, right, up; - - armor = MSG_ReadByte (net_message); - blood = MSG_ReadByte (net_message); - MSG_ReadCoordV (net_message, from); - - count = blood * 0.5 + armor * 0.5; - if (count < 10) - count = 10; - - if (cl_cshift_damage->int_val - || (vs->force_cshifts & INFO_CSHIFT_DAMAGE)) { - cshift_t *cshift = &vs->cshifts[CSHIFT_DAMAGE]; - int percent = cshift->percent; - *cshift = armor_blood[(2 * (armor > blood)) + (armor > 0)]; - cshift->percent = percent + 3 * count; - cshift->percent = bound (0, cshift->percent, 150); - cshift->initialpct = cshift->percent; - cshift->time = vs->time; - } - - // calculate view angle kicks - VectorSubtract (from, origin, from); - VectorNormalize (from); - - AngleVectors (angles, forward, right, up); - - side = DotProduct (from, right); - v_dmg_roll = count * side * v_kickroll->value; - - side = DotProduct (from, forward); - v_dmg_pitch = count * side * v_kickpitch->value; - - v_dmg_time = v_kicktime->value; -} - -static void -V_cshift_f (void) -{ - cshift_empty.destcolor[0] = atoi (Cmd_Argv (1)); - cshift_empty.destcolor[1] = atoi (Cmd_Argv (2)); - cshift_empty.destcolor[2] = atoi (Cmd_Argv (3)); - cshift_empty.percent = atoi (Cmd_Argv (4)); -} - -/* - V_BonusFlash_f - - When you run over an item, the server sends this command -*/ -static void -V_BonusFlash_f (void *data) -{ - viewstate_t *vs = data; - if (!cl_cshift_bonus->int_val - && !(vs->force_cshifts & INFO_CSHIFT_BONUS)) - return; - - vs->cshifts[CSHIFT_BONUS] = cshift_bonus; - vs->cshifts[CSHIFT_BONUS].initialpct = vs->cshifts[CSHIFT_BONUS].percent; - vs->cshifts[CSHIFT_BONUS].time = vs->time; -} - -/* - V_SetContentsColor - - Underwater, lava, etc each has a color shift -*/ -void -V_SetContentsColor (viewstate_t *vs, int contents) -{ - if (!cl_cshift_contents->int_val - && !(vs->force_cshifts & INFO_CSHIFT_CONTENTS)) { - vs->cshifts[CSHIFT_CONTENTS] = cshift_empty; - return; - } - - switch (contents) { - case CONTENTS_EMPTY: - vs->cshifts[CSHIFT_CONTENTS] = cshift_empty; - break; - case CONTENTS_LAVA: - vs->cshifts[CSHIFT_CONTENTS] = cshift_lava; - break; - case CONTENTS_SOLID: - case CONTENTS_SLIME: - vs->cshifts[CSHIFT_CONTENTS] = cshift_slime; - break; - default: - vs->cshifts[CSHIFT_CONTENTS] = cshift_water; - } -} - -static void -V_CalcPowerupCshift (viewstate_t *vs) -{ - vs->cshifts[CSHIFT_POWERUP] = powerup[vs->powerup_index]; -} - -/* - V_CalcBlend - - LordHavoc made this a real, true alpha blend. Cleaned it up - a bit, but otherwise this is his code. --KB -*/ -static void -V_CalcBlend (viewstate_t *vs) -{ - float a2, a3; - float r = 0, g = 0, b = 0, a = 0; - int i; - - for (i = 0; i < NUM_CSHIFTS; i++) { - a2 = vs->cshifts[i].percent / 255.0; - - if (!a2) - continue; - - a2 = min (a2, 1.0); - r += (vs->cshifts[i].destcolor[0] - r) * a2; - g += (vs->cshifts[i].destcolor[1] - g) * a2; - b += (vs->cshifts[i].destcolor[2] - b) * a2; - - a3 = (1.0 - a) * (1.0 - a2); - a = 1.0 - a3; - } - - // LordHavoc: saturate color - if (a) { - a2 = 1.0 / a; - r *= a2; - g *= a2; - b *= a2; - } - - r_data->vid->cshift_color[0] = min (r, 255.0) / 255.0; - r_data->vid->cshift_color[1] = min (g, 255.0) / 255.0; - r_data->vid->cshift_color[2] = min (b, 255.0) / 255.0; - r_data->vid->cshift_color[3] = bound (0.0, a, 1.0); -} - -static void -V_DropCShift (cshift_t *cs, double time, float droprate) -{ - if (cs->time < 0) { - cs->percent = 0; - } else { - cs->percent = cs->initialpct - (time - cs->time) * droprate; - if (cs->percent <= 0) { - cs->percent = 0; - cs->time = -1; - } - } -} - -void -V_PrepBlend (viewstate_t *vs) -{ - int i, j; - - if (cl_cshift_powerup->int_val - || (vs->force_cshifts & INFO_CSHIFT_POWERUP)) - V_CalcPowerupCshift (vs); - - r_data->vid->cshift_changed = false; - - for (i = 0; i < NUM_CSHIFTS; i++) { - if (vs->cshifts[i].percent != vs->prev_cshifts[i].percent) { - r_data->vid->cshift_changed = true; - vs->prev_cshifts[i].percent = vs->cshifts[i].percent; - } - for (j = 0; j < 3; j++) { - if (vs->cshifts[i].destcolor[j] != vs->prev_cshifts[i].destcolor[j]) - { - r_data->vid->cshift_changed = true; - vs->prev_cshifts[i].destcolor[j] = vs->cshifts[i].destcolor[j]; - } - } - } - - // drop the damage value - V_DropCShift (&vs->cshifts[CSHIFT_DAMAGE], vs->time, 150); - // drop the bonus value - V_DropCShift (&vs->cshifts[CSHIFT_BONUS], vs->time, 100); - - if (!r_data->vid->cshift_changed && !r_data->vid->recalc_refdef) - return; - - V_CalcBlend (vs); -} - -/* VIEW RENDERING */ - -static void -CalcGunAngle (viewstate_t *vs) -{ - vec4f_t rotation = r_data->refdef->viewrotation; - //FIXME make child of camera - Transform_SetWorldRotation (vs->weapon_entity->transform, rotation); -} - -static void -V_BoundOffsets (viewstate_t *vs) -{ - vec4f_t offset = r_data->refdef->viewposition - vs->origin; - - // absolutely bound refresh reletive to entity clipping hull - // so the view can never be inside a solid wall - - offset[0] = bound (-14, offset[0], 14); - offset[1] = bound (-14, offset[1], 14); - offset[2] = bound (-22, offset[2], 30); - r_data->refdef->viewposition = vs->origin + offset; -} - -static vec4f_t -idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level, double time) -{ - vec4f_t identity = { 0, 0, 0, 1 }; - if (!level || !cycle) { - return identity; - } - float scale = sin (time * cycle->value); - float ang = scale * level->value * v_idlescale->value; - float c = cos (ang * M_PI / 360); - float s = sin (ang * M_PI / 360); - return axis * s + identity * c; -} - -/* - V_AddIdle - - Idle swaying -*/ -static void -V_AddIdle (viewstate_t *vs) -{ - vec4f_t roll = idle_quat ((vec4f_t) { 1, 0, 0, 0}, - v_iroll_cycle, v_iroll_level, vs->time); - vec4f_t pitch = idle_quat ((vec4f_t) { 0, 1, 0, 0}, - v_ipitch_cycle, v_ipitch_level, vs->time); - vec4f_t yaw = idle_quat ((vec4f_t) { 0, 0, 1, 0}, - v_iyaw_cycle, v_iyaw_level, vs->time); - vec4f_t rot = normalf (qmulf (yaw, qmulf (pitch, roll))); - - // rotate the view - r_data->refdef->viewrotation = qmulf (rot, r_data->refdef->viewrotation); - - // counter-rotate the weapon - rot = qmulf (qconjf (rot), - Transform_GetWorldRotation (vs->weapon_entity->transform)); - Transform_SetWorldRotation (vs->weapon_entity->transform, rot); -} - -/* - V_CalcViewRoll - - Roll is induced by movement and damage -*/ -static void -V_CalcViewRoll (viewstate_t *vs) -{ - vec_t *angles = vs->angles; - vec4f_t velocity = vs->velocity; - vec3_t ang = { }; - - ang[ROLL] = V_CalcRoll (angles, velocity); - - if (v_dmg_time > 0) { - ang[ROLL] += v_dmg_time / v_kicktime->value * v_dmg_roll; - ang[PITCH] += v_dmg_time / v_kicktime->value * v_dmg_pitch; - v_dmg_time -= vs->frametime; - } - - if (vs->flags & VF_DEAD) { // VF_GIB will also set VF_DEAD - ang[ROLL] = 80; // dead view angle - } - - vec4f_t rot; - AngleQuat (ang, &rot[0]);//FIXME - r_data->refdef->viewrotation = qmulf (r_data->refdef->viewrotation, rot); -} - -static void -V_CalcIntermissionRefdef (viewstate_t *vs) -{ - // vs->player_entity is the player model (visible when out of body) - entity_t *ent = vs->player_entity; - entity_t *view; - float old; - vec4f_t origin = Transform_GetWorldPosition (ent->transform); - vec4f_t rotation = Transform_GetWorldRotation (ent->transform); - - // view is the weapon model (visible only from inside body) - view = vs->weapon_entity; - - r_data->refdef->viewposition = origin; - r_data->refdef->viewrotation = rotation; - view->renderer.model = NULL; - - // always idle in intermission - old = v_idlescale->value; - Cvar_SetValue (v_idlescale, 1); - V_AddIdle (vs); - Cvar_SetValue (v_idlescale, old); -} - -static void -V_CalcRefdef (viewstate_t *vs) -{ - // view is the weapon model (visible only from inside body) - entity_t *view = vs->weapon_entity; - float bob; - static float oldz = 0; - vec4f_t forward = {}, right = {}, up = {}; - vec4f_t origin = vs->origin; - vec_t *viewangles = vs->angles; - - V_DriftPitch (vs); - - bob = V_CalcBob (vs); - - // refresh position - r_data->refdef->viewposition = origin; - r_data->refdef->viewposition[2] += vs->height + bob; - - // never let it sit exactly on a node line, because a water plane can - // disappear when viewed with the eye exactly on it. - // server protocol specifies to only 1/8 pixel, so add 1/16 in each axis - r_data->refdef->viewposition += (vec4f_t) { 1.0/16, 1.0/16, 1.0/16, 0}; - - AngleQuat (vs->angles, &r_data->refdef->viewrotation[0]);//FIXME - V_CalcViewRoll (vs); - V_AddIdle (vs); - - // offsets - //FIXME semi-duplicates AngleQuat (also, vec3_t vs vec4f_t) - AngleVectors (viewangles, &forward[0], &right[0], &up[0]); - - // don't allow cheats in multiplayer - // FIXME check for dead - if (vs->voffs_enabled) { - r_data->refdef->viewposition += scr_ofsx->value * forward - + scr_ofsy->value * right - + scr_ofsz->value * up; - } - - V_BoundOffsets (vs); - - // set up gun position - CalcGunAngle (vs); - - origin += (vec4f_t) { 0, 0, vs->height, 0 }; - origin += forward * bob * 0.4f + (vec4f_t) { 0, 0, bob, 0 }; - - // fudge position around to keep amount of weapon visible - // roughly equal with different FOV - if (hud_sbar->int_val == 0 && r_data->scr_viewsize->int_val >= 100) { - ; - } else if (r_data->scr_viewsize->int_val == 110) { - origin += (vec4f_t) { 0, 0, 1, 0}; - } else if (r_data->scr_viewsize->int_val == 100) { - origin += (vec4f_t) { 0, 0, 2, 0}; - } else if (r_data->scr_viewsize->int_val == 90) { - origin += (vec4f_t) { 0, 0, 1, 0}; - } else if (r_data->scr_viewsize->int_val == 80) { - origin += (vec4f_t) { 0, 0, 0.5, 0}; - } - - model_t *model = vs->weapon_model; - if (view->renderer.model != model) { - view->animation.pose2 = -1; - } - view->renderer.model = model; - view->animation.frame = vs->weaponframe; - view->renderer.skin = 0; - - // set up the refresh position - r_data->refdef->viewrotation = qmulf (vs->punchangle, - r_data->refdef->viewrotation); - - // smooth out stair step ups - if ((vs->onground != -1) && (origin[2] - oldz > 0)) { - float steptime; - - steptime = vs->frametime; - - oldz += steptime * 80; - if (oldz > origin[2]) - oldz = origin[2]; - if (origin[2] - oldz > 12) - oldz = origin[2] - 12; - r_data->refdef->viewposition[2] += oldz - origin[2]; - origin[2] += oldz - origin[2]; - } else { - oldz = origin[2]; - } - { - // FIXME sort out the alias model specific negation - vec3_t ang = {-viewangles[0], viewangles[1], viewangles[2]}; - CL_TransformEntity (view, 1, ang, origin); - } - - if (vs->chase && chase_active->int_val) { - Chase_Update (vs->chasestate); - } -} - -/* - V_RenderView - - The player's clipping box goes from (-16 -16 -24) to (16 16 32) from - the entity origin, so any view position inside that will be valid -*/ -void -V_RenderView (viewstate_t *vs) -{ - if (!vs->active) { - r_data->refdef->viewposition = (vec4f_t) { 0, 0, 0, 1 }; - r_data->refdef->viewrotation = (vec4f_t) { 0, 0, 0, 1 }; - return; - } - - if (vs->intermission) { // intermission / finale rendering - V_CalcIntermissionRefdef (vs); - } else { - V_CalcRefdef (vs); - } -} - -void -V_Init (void) -{ - Cmd_AddDataCommand ("bf", V_BonusFlash_f, &cl.viewstate, - "Background flash, used when you pick up an item"); - Cmd_AddDataCommand ("centerview", V_StartPitchDrift_f, &cl.viewstate, - "Centers the player's " - "view ahead after +lookup or +lookdown\n" - "Will not work while mlook is active or freelook is 1."); - Cmd_AddCommand ("v_cshift", V_cshift_f, "This adjusts all of the colors " - "currently being displayed.\n" - "Used when you are underwater, hit, have the Ring of " - "Shadows, or Quad Damage. (v_cshift r g b intensity)"); -} - -void -V_Init_Cvars (void) -{ - v_centermove = Cvar_Get ("v_centermove", "0.15", CVAR_NONE, NULL, - "How far the player must move forward before the " - "view re-centers"); - v_centerspeed = Cvar_Get ("v_centerspeed", "500", CVAR_NONE, NULL, - "How quickly you return to a center view after " - "a lookup or lookdown"); - v_iyaw_cycle = Cvar_Get ("v_iyaw_cycle", "2", CVAR_NONE, NULL, - "How far you tilt right and left when " - "v_idlescale is enabled"); - v_iroll_cycle = Cvar_Get ("v_iroll_cycle", "0.5", CVAR_NONE, NULL, - "How quickly you tilt right and left when " - "v_idlescale is enabled"); - v_ipitch_cycle = Cvar_Get ("v_ipitch_cycle", "1", CVAR_NONE, NULL, - "How quickly you lean forwards and backwards " - "when v_idlescale is enabled"); - v_iyaw_level = Cvar_Get ("v_iyaw_level", "0.3", CVAR_NONE, NULL, - "How far you tilt right and left when " - "v_idlescale is enabled"); - v_iroll_level = Cvar_Get ("v_iroll_level", "0.1", CVAR_NONE, NULL, - "How far you tilt right and left when " - "v_idlescale is enabled"); - v_ipitch_level = Cvar_Get ("v_ipitch_level", "0.3", CVAR_NONE, NULL, - "How far you lean forwards and backwards when " - "v_idlescale is enabled"); - v_idlescale = Cvar_Get ("v_idlescale", "0", CVAR_NONE, NULL, - "Toggles whether the view remains idle"); - - scr_ofsx = Cvar_Get ("scr_ofsx", "0", CVAR_NONE, NULL, "None"); - scr_ofsy = Cvar_Get ("scr_ofsy", "0", CVAR_NONE, NULL, "None"); - scr_ofsz = Cvar_Get ("scr_ofsz", "0", CVAR_NONE, NULL, "None"); - cl_rollspeed = Cvar_Get ("cl_rollspeed", "200", CVAR_NONE, NULL, - "How quickly you straighten out after strafing"); - cl_rollangle = Cvar_Get ("cl_rollangle", "2.0", CVAR_NONE, NULL, - "How much your screen tilts when strafing"); - cl_bob = Cvar_Get ("cl_bob", "0.02", CVAR_NONE, NULL, - "How much your weapon moves up and down when walking"); - cl_bobcycle = Cvar_Get ("cl_bobcycle", "0.6", CVAR_NONE, NULL, - "How quickly your weapon moves up and down when " - "walking"); - cl_bobup = Cvar_Get ("cl_bobup", "0.5", CVAR_NONE, NULL, - "How long your weapon stays up before cycling when " - "walking"); - v_kicktime = Cvar_Get ("v_kicktime", "0.5", CVAR_NONE, NULL, - "How long the kick from an attack lasts"); - v_kickroll = Cvar_Get ("v_kickroll", "0.6", CVAR_NONE, NULL, - "How much you lean when hit"); - v_kickpitch = Cvar_Get ("v_kickpitch", "0.6", CVAR_NONE, NULL, - "How much you look up when hit"); -} diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 3bef29f54..af78bea47 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -57,6 +57,8 @@ #include "compat.h" #include "sbar.h" +#include "client/hud.h" + #include "nq/include/client.h" #include "nq/include/game.h" #include "nq/include/server.h" @@ -105,9 +107,6 @@ int hipweapons[4] = { HIT_LASER_CANNON_BIT, HIT_MJOLNIR_BIT, 4, HIT_PROXIMITY_GUN_BIT }; qpic_t *hsb_items[2]; // MED 01/04/97 added hipnotic items array -cvar_t *hud_sbar; -cvar_t *hud_swap; -cvar_t *hud_scoreboard_gravity; cvar_t *scr_centertime; cvar_t *scr_printspeed; diff --git a/qw/include/client.h b/qw/include/client.h index cc2e586d2..e6410ecaa 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -270,9 +270,6 @@ extern struct cvar_s *cl_netgraph_box; extern struct cvar_s *cl_draw_locs; extern struct cvar_s *cl_shownet; -extern struct cvar_s *hud_sbar; -extern struct cvar_s *hud_sbar_separator; -extern struct cvar_s *hud_swap; extern struct cvar_s *cl_pitchdriftspeed; @@ -316,10 +313,6 @@ void CL_UpdateScreen (double realtime); void CL_SetState (cactive_t state); -void V_ParseDamage (viewstate_t *vs); - -void V_PrepBlend (viewstate_t *vs); - void CL_Cmd_ForwardToServer (void); void CL_Cmd_Init (void); diff --git a/qw/include/host.h b/qw/include/host.h index d7a290284..ccf759a26 100644 --- a/qw/include/host.h +++ b/qw/include/host.h @@ -38,8 +38,6 @@ #define MAX_NUM_ARGVS 50 -extern qboolean noclip_anglehack; - extern struct cvar_s *sys_ticrate; extern struct cvar_s *password; diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 86228215b..145c4a540 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -106,7 +106,6 @@ qw_source_libqw_client_a_SOURCES= \ qw/source/cl_cam.c qw/source/cl_chat.c qw/source/cl_cmd.c qw/source/cl_cvar.c qw/source/cl_demo.c \ qw/source/cl_entparse.c qw/source/cl_ents.c qw/source/cl_http.c qw/source/cl_input.c qw/source/cl_main.c qw/source/cl_ngraph.c \ qw/source/cl_parse.c qw/source/cl_pred.c qw/source/cl_rss.c qw/source/cl_screen.c qw/source/cl_skin.c qw/source/cl_slist.c \ - qw/source/cl_view.c \ qw/source/sbar.c qw/source/teamplay.c # Software-rendering clients diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 8a4c02512..c4a809f68 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -151,11 +151,6 @@ cvar_t *cl_quakerc; cvar_t *cl_maxfps; cvar_t *cl_usleep; -cvar_t *cl_cshift_bonus; -cvar_t *cl_cshift_contents; -cvar_t *cl_cshift_damage; -cvar_t *cl_cshift_powerup; - cvar_t *cl_model_crcs; cvar_t *cl_predict_players; @@ -1221,7 +1216,7 @@ CL_Init (void) CL_Skin_Init (); Locs_Init (); - V_Init (); + V_Init (&cl.viewstate); Info_SetValueForStarKey (cls.userinfo, "*ver", QW_VERSION, 0); @@ -1368,15 +1363,6 @@ CL_Init_Cvars (void) "exec autoexec.cfg on gamedir change"); cl_quakerc = Cvar_Get ("cl_quakerc", "1", CVAR_NONE, NULL, "exec quake.rc on startup"); - cl_cshift_bonus = Cvar_Get ("cl_cshift_bonus", "1", CVAR_ARCHIVE, NULL, - "Show bonus flash on item pickup"); - cl_cshift_contents = Cvar_Get ("cl_cshift_content", "1", CVAR_ARCHIVE, - NULL, "Shift view colors for contents " - "(water, slime, etc)"); - cl_cshift_damage = Cvar_Get ("cl_cshift_damage", "1", CVAR_ARCHIVE, NULL, - "Shift view colors on damage"); - cl_cshift_powerup = Cvar_Get ("cl_cshift_powerup", "1", CVAR_ARCHIVE, NULL, - "Shift view colors for powerups"); cl_fb_players = Cvar_Get ("cl_fb_players", "0", CVAR_ARCHIVE, NULL, "fullbrightness of player models. " "server must allow (via fbskins serverinfo)."); cl_writecfg = Cvar_Get ("cl_writecfg", "1", CVAR_NONE, NULL, diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 5e72ccee8..d8d2dd5e2 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1506,7 +1506,7 @@ CL_ParseServerMessage (void) // svc_particle case svc_damage: - V_ParseDamage (&cl.viewstate); + V_ParseDamage (net_message, &cl.viewstate); // put sbar face into pain frame cl.faceanimtime = cl.time + 0.2; break; diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 29af9187a..ff4006437 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -48,6 +48,7 @@ #include "sbar.h" +#include "client/hud.h" #include "client/view.h" #include "qw/include/client.h" diff --git a/qw/source/sbar.c b/qw/source/sbar.c index d8dde4f52..6f60de764 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -57,6 +57,8 @@ #include "compat.h" +#include "client/hud.h" + #include "qw/bothdefs.h" #include "qw/include/cl_cam.h" #include "qw/include/cl_parse.h" @@ -96,9 +98,6 @@ static qboolean largegame = false; cvar_t *fs_fraglog; cvar_t *cl_fraglog; -cvar_t *hud_sbar; -cvar_t *hud_swap; -cvar_t *hud_scoreboard_gravity; cvar_t *hud_scoreboard_uid; cvar_t *scr_centertime; cvar_t *scr_printspeed; From 2477a44d15abae9afcbbdee9533481cfa072ec73 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Feb 2022 16:55:12 +0900 Subject: [PATCH 2473/3664] [client] Move cshift info from viddef to viewstate It makes much more sense for cshift state to be in viewstate because it is very much an effect rather than anything specific to a renderer. --- include/QF/vid.h | 2 -- include/client/view.h | 2 ++ libs/client/cl_view.c | 16 ++++++++-------- nq/source/cl_screen.c | 2 +- qw/source/cl_screen.c | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/QF/vid.h b/include/QF/vid.h index 499989f20..c5fd95751 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -53,8 +53,6 @@ typedef struct { unsigned height; int numpages; qboolean recalc_refdef; // if true, recalc vid-based stuff - qboolean cshift_changed; - quat_t cshift_color; struct view_s *conview; struct vid_internal_s *vid_internal; diff --git a/include/client/view.h b/include/client/view.h index ea7712a31..9cf2d8ed7 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -61,6 +61,8 @@ typedef struct viewstate_s { int powerup_index; cshift_t cshifts[NUM_CSHIFTS]; // Color shifts for damage, powerups cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types + quat_t cshift_color; + qboolean cshift_changed; // pitch drifting vars float idealpitch; diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index 6eb3c20d8..139e2d8fb 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -414,10 +414,10 @@ V_CalcBlend (viewstate_t *vs) b *= a2; } - r_data->vid->cshift_color[0] = min (r, 255.0) / 255.0; - r_data->vid->cshift_color[1] = min (g, 255.0) / 255.0; - r_data->vid->cshift_color[2] = min (b, 255.0) / 255.0; - r_data->vid->cshift_color[3] = bound (0.0, a, 1.0); + vs->cshift_color[0] = min (r, 255.0) / 255.0; + vs->cshift_color[1] = min (g, 255.0) / 255.0; + vs->cshift_color[2] = min (b, 255.0) / 255.0; + vs->cshift_color[3] = bound (0.0, a, 1.0); } static void @@ -443,17 +443,17 @@ V_PrepBlend (viewstate_t *vs) || (vs->force_cshifts & INFO_CSHIFT_POWERUP)) V_CalcPowerupCshift (vs); - r_data->vid->cshift_changed = false; + vs->cshift_changed = false; for (i = 0; i < NUM_CSHIFTS; i++) { if (vs->cshifts[i].percent != vs->prev_cshifts[i].percent) { - r_data->vid->cshift_changed = true; + vs->cshift_changed = true; vs->prev_cshifts[i].percent = vs->cshifts[i].percent; } for (j = 0; j < 3; j++) { if (vs->cshifts[i].destcolor[j] != vs->prev_cshifts[i].destcolor[j]) { - r_data->vid->cshift_changed = true; + vs->cshift_changed = true; vs->prev_cshifts[i].destcolor[j] = vs->cshifts[i].destcolor[j]; } } @@ -464,7 +464,7 @@ V_PrepBlend (viewstate_t *vs) // drop the bonus value V_DropCShift (&vs->cshifts[CSHIFT_BONUS], vs->time, 100); - if (!r_data->vid->cshift_changed && !r_data->vid->recalc_refdef) + if (!vs->cshift_changed && !r_data->vid->recalc_refdef) return; V_CalcBlend (vs); diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 214f764a4..01188572e 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -81,7 +81,7 @@ SCR_CShift (void) contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); - r_funcs->Draw_BlendScreen (r_data->vid->cshift_color); + r_funcs->Draw_BlendScreen (cl.viewstate.cshift_color); } static void diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index ff4006437..8bf09229a 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -83,7 +83,7 @@ SCR_CShift (void) contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); - r_funcs->Draw_BlendScreen (r_data->vid->cshift_color); + r_funcs->Draw_BlendScreen (cl.viewstate.cshift_color); } static void From ca9e8a3b68c407bc34509d3b162d77635c1ac642 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Feb 2022 16:57:43 +0900 Subject: [PATCH 2474/3664] [client] Pass time into locs_draw This avoids unnecessary access to r_data. --- include/client/locs.h | 2 +- libs/client/locs.c | 8 ++++---- qw/source/cl_ents.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/client/locs.h b/include/client/locs.h index 06817ef5a..ac0198d2d 100644 --- a/include/client/locs.h +++ b/include/client/locs.h @@ -47,6 +47,6 @@ int locs_nearest (vec4f_t loc) __attribute__((pure)); void locs_reset (void); void locs_save (const char *filename, qboolean gz); void map_to_loc (const char *mapname, char *filename); -void locs_draw (vec4f_t simorg); +void locs_draw (double time, vec4f_t simorg); #endif//__QF_locs_h diff --git a/libs/client/locs.c b/libs/client/locs.c index ce5bd3ef4..e8e2df89e 100644 --- a/libs/client/locs.c +++ b/libs/client/locs.c @@ -287,7 +287,7 @@ map_to_loc (const char *mapname, char *filename) } void -locs_draw (vec4f_t simorg) +locs_draw (double time, vec4f_t simorg) { //FIXME custom ent rendering code would be nice dlight_t *dl; @@ -302,7 +302,7 @@ locs_draw (vec4f_t simorg) if (dl) { VectorCopy (nearloc->loc, dl->origin); dl->radius = 200; - dl->die = r_data->realtime + 0.1; + dl->die = time + 0.1; dl->color[0] = 0; dl->color[1] = 1; dl->color[2] = 0; @@ -310,11 +310,11 @@ locs_draw (vec4f_t simorg) } trueloc = nearloc->loc; clp_funcs->Particle_New (pt_smokecloud, part_tex_smoke, trueloc, 2.0, - zero, r_data->realtime + 9.0, 254, + zero, time + 9.0, 254, 0.25 + qfrandom (0.125), 0.0); for (i = 0; i < 15; i++) clp_funcs->Particle_NewRandom (pt_fallfade, part_tex_dot, trueloc, - 12, 0.7, 96, r_data->realtime + 5.0, + 12, 0.7, 96, time + 5.0, 104 + (rand () & 7), 1.0, 0.0); } } diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 5b03d3b02..e1eb60d8d 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -523,7 +523,7 @@ CL_EmitEntities (void) CL_LinkPacketEntities (); CL_UpdateTEnts (cl.time, &tentCtx); if (cl_draw_locs->int_val) { - locs_draw (cl.viewstate.origin); + locs_draw (cl.time, cl.viewstate.origin); } } From 57dd4494cc1bdd8d7530093db7d65d82013175b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Feb 2022 16:59:38 +0900 Subject: [PATCH 2475/3664] [renderer] Pass in a camera transform More r_data cleanup. Things could be better still, but this is a start. --- include/QF/plugin/snd_render.h | 4 +- include/QF/screen.h | 5 +- include/QF/sound.h | 9 ++-- include/client/temp_entities.h | 2 + include/client/view.h | 1 + include/snd_internal.h | 4 +- libs/audio/renderer/snd_channels.c | 38 ++++++++++------ libs/audio/renderer/snd_dma.c | 5 +- libs/audio/snd.c | 6 +-- libs/audio/test/Makemodule.am | 1 + libs/audio/test/testsound.c | 2 +- libs/client/cl_temp_entities.c | 6 +-- libs/client/cl_view.c | 73 +++++++++++++++++------------- libs/video/renderer/r_screen.c | 11 ++++- nq/source/Makemodule.am | 2 +- nq/source/cl_main.c | 2 + nq/source/cl_screen.c | 9 ++-- nq/source/host.c | 12 +++-- nq/source/sv_ded.c | 3 +- qw/source/cl_main.c | 12 +++-- qw/source/cl_screen.c | 9 ++-- ruamoko/qwaq/builtins/graphics.c | 2 +- 22 files changed, 134 insertions(+), 84 deletions(-) diff --git a/include/QF/plugin/snd_render.h b/include/QF/plugin/snd_render.h index d4add32aa..bb99df885 100644 --- a/include/QF/plugin/snd_render.h +++ b/include/QF/plugin/snd_render.h @@ -31,6 +31,7 @@ #include struct sfx_s; +struct transform_s; typedef struct snd_render_funcs_s { void (*init) (void); @@ -47,8 +48,7 @@ typedef struct snd_render_funcs_s { struct sfx_s *(*precache_sound) (const char *sample); struct sfx_s *(*load_sound) (const char *name); - void (*update) (const vec3_t origin, const vec3_t v_forward, - const vec3_t v_right, const vec3_t v_up, + void (*update) (struct transform_s *ear, const byte *ambient_sound_levels); void (*stop_all_sounds) (void); void (*extra_update) (void); diff --git a/include/QF/screen.h b/include/QF/screen.h index 514bb7b60..98b198415 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -31,12 +31,15 @@ #include "QF/qtypes.h" +struct transform_s; + void SCR_Init_Cvars (void); void SCR_Init (void); typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array -void SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs); +void SCR_UpdateScreen (struct transform_s *camera, double realtime, + SCR_Func *scr_funcs); void SCR_SizeUp (void); void SCR_SizeDown (void); diff --git a/include/QF/sound.h b/include/QF/sound.h index 06238114d..3c2968298 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -34,6 +34,8 @@ #include "QF/mathlib.h" +struct transform_s; + /** \ingroup sound */ @@ -129,16 +131,15 @@ void S_StopAllSounds(void); /** Update the sound engine with the client's position and orientation and render some sound. - \param origin 3d coords of the client + \param ear Transform for the position and orientation of the stereo + sound pickup. \param v_forward 3d vector of the client's facing direction \param v_right 3d vector of the client's rightward direction \param v_up 3d vector of the client's upward direction \param ambient_sound_level NUM_AMBIENTS bytes indicating current ambient sound levels */ -void S_Update (const vec3_t origin, const vec3_t v_forward, - const vec3_t v_right, const vec3_t v_up, - const byte *ambient_sound_level); +void S_Update (struct transform_s *ear, const byte *ambient_sound_level); /** Render some more sound without updating the client's position/orientation. */ diff --git a/include/client/temp_entities.h b/include/client/temp_entities.h index c4dbc0868..f7f9477cf 100644 --- a/include/client/temp_entities.h +++ b/include/client/temp_entities.h @@ -103,6 +103,8 @@ typedef struct TEntContext_s { struct msg_s; struct entity_s; +extern struct scene_s *cl_scene; + void CL_TEnts_Init (void); void CL_Init_Entity (struct entity_s *ent); void CL_ClearTEnts (void); diff --git a/include/client/view.h b/include/client/view.h index 9cf2d8ed7..d832fe0af 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -45,6 +45,7 @@ typedef struct viewstate_s { vec4f_t punchangle; vec3_t angles; float frametime; + struct transform_s *camera_transform; double time; float height; int weaponframe; diff --git a/include/snd_internal.h b/include/snd_internal.h index 1d7479096..fe666f42a 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -44,6 +44,7 @@ #include "QF/sound.h" #include "QF/zone.h" +struct transform_s; typedef struct portable_samplepair_s portable_samplepair_t; typedef struct snd_s snd_t; typedef struct wavinfo_s wavinfo_t; @@ -363,8 +364,7 @@ void SND_AmbientOn (snd_t *snd); \param ambient_sound_level Pointer to 4 bytes indicating the levels at which to play the ambient sounds. */ -void SND_SetListener (snd_t *snd, const vec3_t origin, const vec3_t v_forward, - const vec3_t v_right, const vec3_t v_up, +void SND_SetListener (snd_t *snd, struct transform_s *ear, const byte *ambient_sound_level); /** Stop all sounds from playing. diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index d08706d65..bd820cf72 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -47,6 +47,8 @@ #include "QF/quakefs.h" #include "QF/sys.h" +#include "QF/scene/transform.h" + #include "snd_internal.h" static channel_t *free_channels; @@ -64,10 +66,10 @@ static sfx_t *ambient_sfx[NUM_AMBIENTS]; static vec_t sound_nominal_clip_dist = 1000.0; -static vec3_t listener_origin; -static vec3_t listener_forward; -static vec3_t listener_right; -static vec3_t listener_up; +static vec4f_t listener_origin; +static vec4f_t listener_forward; +static vec4f_t listener_right; +static vec4f_t listener_up; static cvar_t *snd_phasesep; static cvar_t *snd_volumesep; @@ -245,7 +247,8 @@ s_play_f (void *_snd) dsprintf (name, "%s", Cmd_Argv (i)); } sfx = SND_PrecacheSound (snd, name->str); - SND_StartSound (snd, hash++, 0, sfx, listener_origin, 1.0, 1.0); + //FIXME + SND_StartSound (snd, hash++, 0, sfx, &listener_origin[0], 1.0, 1.0); i++; } dstring_delete (name); @@ -270,7 +273,8 @@ s_playcenter_f (void *_snd) dsprintf (name, "%s", Cmd_Argv (i)); } sfx = SND_PrecacheSound (snd, name->str); - SND_StartSound (snd, viewent, 0, sfx, listener_origin, 1.0, 1.0); + //FIXME + SND_StartSound (snd, viewent, 0, sfx, &listener_origin[0], 1.0, 1.0); } dstring_delete (name); } @@ -294,7 +298,8 @@ s_playvol_f (void *_snd) } sfx = SND_PrecacheSound (snd, name->str); vol = atof (Cmd_Argv (i + 1)); - SND_StartSound (snd, hash++, 0, sfx, listener_origin, vol, 1.0); + //FIXME + SND_StartSound (snd, hash++, 0, sfx, &listener_origin[0], vol, 1.0); i += 2; } dstring_delete (name); @@ -539,17 +544,22 @@ s_combine_channel (channel_t *combine, channel_t *ch) } void -SND_SetListener (snd_t *snd, const vec3_t origin, const vec3_t forward, - const vec3_t right, const vec3_t up, - const byte *ambient_sound_level) +SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level) { int i, j; channel_t *combine, *ch; - VectorCopy (origin, listener_origin); - VectorCopy (forward, listener_forward); - VectorCopy (right, listener_right); - VectorCopy (up, listener_up); + if (ear) { + listener_origin = Transform_GetWorldPosition (ear); + listener_forward = Transform_Forward (ear); + listener_right = Transform_Right (ear); + listener_up = Transform_Up (ear); + } else { + listener_origin = (vec4f_t) { }; + listener_forward = (vec4f_t) {1, 0, 0, 0}; + listener_right = (vec4f_t) {0, -1, 0, 0}; + listener_up = (vec4f_t) {0, 0, 1, 0}; + } // update general area ambient sound sources s_updateAmbientSounds (snd, ambient_sound_level); diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 489f3b620..d5714c55a 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -211,8 +211,7 @@ s_update_ (void) Called once each time through the main loop */ static void -s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, - const vec3_t up, const byte *ambient_sound_level) +s_update (struct transform_s *ear, const byte *ambient_sound_level) { if (!sound_started || (snd_blocked > 0)) return; @@ -221,7 +220,7 @@ s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, snd_output_funcs->on_update (&snd); } - SND_SetListener (&snd, origin, forward, right, up, ambient_sound_level); + SND_SetListener (&snd, ear, ambient_sound_level); if (snd_output_data->model == som_push) { // mix some sound diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 5b7c4c082..e7c1b0d3b 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -166,12 +166,10 @@ S_PrecacheSound (const char *sample) } VISIBLE void -S_Update (const vec3_t origin, const vec3_t v_forward, const vec3_t v_right, - const vec3_t v_up, const byte *ambient_sound_level) +S_Update (struct transform_s *ear, const byte *ambient_sound_level) { if (snd_render_funcs) - snd_render_funcs->update (origin, v_forward, v_right, v_up, - ambient_sound_level); + snd_render_funcs->update (ear, ambient_sound_level); } VISIBLE void diff --git a/libs/audio/test/Makemodule.am b/libs/audio/test/Makemodule.am index e1a4800b0..6b97b2e53 100644 --- a/libs/audio/test/Makemodule.am +++ b/libs/audio/test/Makemodule.am @@ -4,6 +4,7 @@ EXTRA_PROGRAMS += libs/audio/test/testsound testaudio_libs= \ libs/audio/libQFsound.la \ + libs/scene/libQFscene.la \ libs/ruamoko/libQFruamoko.la \ libs/util/libQFutil.la diff --git a/libs/audio/test/testsound.c b/libs/audio/test/testsound.c index 1af4730c1..d5fe91347 100644 --- a/libs/audio/test/testsound.c +++ b/libs/audio/test/testsound.c @@ -88,7 +88,7 @@ main (int argc, const char *argv[]) while (1) { Cbuf_Execute_Stack (testsound_cbuf); - S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin, 0); + S_Update (0, 0); usleep(20 * 1000); } Sys_Quit (); diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 7683586d7..de6233556 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -86,7 +86,7 @@ typedef struct tent_obj_s { static PR_RESMAP (tent_t) temp_entities; static PR_RESMAP (tent_obj_t) tent_objects; -static scene_t *scene; +scene_t *cl_scene; static tent_obj_t *cl_beams; static tent_obj_t *cl_explosions; @@ -137,7 +137,7 @@ CL_TEnts_Precache (int phase) void CL_TEnts_Init (void) { - scene = Scene_NewScene (); + cl_scene = Scene_NewScene (); QFS_GamedirCallback (CL_TEnts_Precache); CL_TEnts_Precache (1); @@ -155,7 +155,7 @@ CL_Init_Entity (entity_t *ent) } memset (ent, 0, sizeof (*ent)); - ent->transform = Transform_New (scene, 0); + ent->transform = Transform_New (cl_scene, 0); ent->renderer.skin = 0; QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); ent->animation.pose1 = ent->animation.pose2 = -1; diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index 139e2d8fb..fd93dc16a 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -43,6 +43,7 @@ #include "client/entities.h" #include "client/hud.h" #include "client/input.h" +#include "client/temp_entities.h"//FIXME for cl_scene #include "client/view.h" /* @@ -475,7 +476,7 @@ V_PrepBlend (viewstate_t *vs) static void CalcGunAngle (viewstate_t *vs) { - vec4f_t rotation = r_data->refdef->viewrotation; + vec4f_t rotation = Transform_GetWorldRotation (vs->camera_transform); //FIXME make child of camera Transform_SetWorldRotation (vs->weapon_entity->transform, rotation); } @@ -483,7 +484,8 @@ CalcGunAngle (viewstate_t *vs) static void V_BoundOffsets (viewstate_t *vs) { - vec4f_t offset = r_data->refdef->viewposition - vs->origin; + vec4f_t offset = Transform_GetWorldPosition (vs->camera_transform); + offset -= vs->origin; // absolutely bound refresh reletive to entity clipping hull // so the view can never be inside a solid wall @@ -491,7 +493,7 @@ V_BoundOffsets (viewstate_t *vs) offset[0] = bound (-14, offset[0], 14); offset[1] = bound (-14, offset[1], 14); offset[2] = bound (-22, offset[2], 30); - r_data->refdef->viewposition = vs->origin + offset; + Transform_SetWorldPosition (vs->camera_transform, vs->origin + offset); } static vec4f_t @@ -525,7 +527,8 @@ V_AddIdle (viewstate_t *vs) vec4f_t rot = normalf (qmulf (yaw, qmulf (pitch, roll))); // rotate the view - r_data->refdef->viewrotation = qmulf (rot, r_data->refdef->viewrotation); + vec4f_t rotation = Transform_GetWorldRotation (vs->camera_transform); + Transform_SetWorldRotation (vs->camera_transform, qmulf (rot, rotation)); // counter-rotate the weapon rot = qmulf (qconjf (rot), @@ -559,7 +562,8 @@ V_CalcViewRoll (viewstate_t *vs) vec4f_t rot; AngleQuat (ang, &rot[0]);//FIXME - r_data->refdef->viewrotation = qmulf (r_data->refdef->viewrotation, rot); + vec4f_t rotation = Transform_GetWorldRotation (vs->camera_transform); + Transform_SetWorldRotation (vs->camera_transform, qmulf (rotation, rot)); } static void @@ -575,8 +579,8 @@ V_CalcIntermissionRefdef (viewstate_t *vs) // view is the weapon model (visible only from inside body) view = vs->weapon_entity; - r_data->refdef->viewposition = origin; - r_data->refdef->viewrotation = rotation; + Transform_SetWorldPosition (vs->camera_transform, origin); + Transform_SetWorldRotation (vs->camera_transform, rotation); view->renderer.model = NULL; // always idle in intermission @@ -602,15 +606,17 @@ V_CalcRefdef (viewstate_t *vs) bob = V_CalcBob (vs); // refresh position - r_data->refdef->viewposition = origin; - r_data->refdef->viewposition[2] += vs->height + bob; + origin = origin; + origin[2] += vs->height + bob; // never let it sit exactly on a node line, because a water plane can // disappear when viewed with the eye exactly on it. // server protocol specifies to only 1/8 pixel, so add 1/16 in each axis - r_data->refdef->viewposition += (vec4f_t) { 1.0/16, 1.0/16, 1.0/16, 0}; + origin += (vec4f_t) { 1.0/16, 1.0/16, 1.0/16, 0}; - AngleQuat (vs->angles, &r_data->refdef->viewrotation[0]);//FIXME + vec4f_t rotation; + AngleQuat (vs->angles, &rotation[0]);//FIXME + Transform_SetWorldRotation (vs->camera_transform, rotation); V_CalcViewRoll (vs); V_AddIdle (vs); @@ -621,7 +627,7 @@ V_CalcRefdef (viewstate_t *vs) // don't allow cheats in multiplayer // FIXME check for dead if (vs->voffs_enabled) { - r_data->refdef->viewposition += scr_ofsx->value * forward + origin += scr_ofsx->value * forward + scr_ofsy->value * right + scr_ofsz->value * up; } @@ -629,23 +635,24 @@ V_CalcRefdef (viewstate_t *vs) V_BoundOffsets (vs); // set up gun position + vec4f_t gun_origin = vs->origin; CalcGunAngle (vs); - origin += (vec4f_t) { 0, 0, vs->height, 0 }; - origin += forward * bob * 0.4f + (vec4f_t) { 0, 0, bob, 0 }; + gun_origin += (vec4f_t) { 0, 0, vs->height, 0 }; + gun_origin += forward * bob * 0.4f + (vec4f_t) { 0, 0, bob, 0 }; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if (hud_sbar->int_val == 0 && r_data->scr_viewsize->int_val >= 100) { ; } else if (r_data->scr_viewsize->int_val == 110) { - origin += (vec4f_t) { 0, 0, 1, 0}; + gun_origin += (vec4f_t) { 0, 0, 1, 0}; } else if (r_data->scr_viewsize->int_val == 100) { - origin += (vec4f_t) { 0, 0, 2, 0}; + gun_origin += (vec4f_t) { 0, 0, 2, 0}; } else if (r_data->scr_viewsize->int_val == 90) { - origin += (vec4f_t) { 0, 0, 1, 0}; + gun_origin += (vec4f_t) { 0, 0, 1, 0}; } else if (r_data->scr_viewsize->int_val == 80) { - origin += (vec4f_t) { 0, 0, 0.5, 0}; + gun_origin += (vec4f_t) { 0, 0, 0.5, 0}; } model_t *model = vs->weapon_model; @@ -660,29 +667,30 @@ V_CalcRefdef (viewstate_t *vs) view->renderer.skin = 0; // set up the refresh position - r_data->refdef->viewrotation = qmulf (vs->punchangle, - r_data->refdef->viewrotation); + Transform_SetWorldRotation (vs->camera_transform, + qmulf (vs->punchangle, rotation)); // smooth out stair step ups - if ((vs->onground != -1) && (origin[2] - oldz > 0)) { + if ((vs->onground != -1) && (gun_origin[2] - oldz > 0)) { float steptime; steptime = vs->frametime; oldz += steptime * 80; - if (oldz > origin[2]) - oldz = origin[2]; - if (origin[2] - oldz > 12) - oldz = origin[2] - 12; - r_data->refdef->viewposition[2] += oldz - origin[2]; - origin[2] += oldz - origin[2]; + if (oldz > gun_origin[2]) + oldz = gun_origin[2]; + if (gun_origin[2] - oldz > 12) + oldz = gun_origin[2] - 12; + origin[2] += oldz - gun_origin[2]; + gun_origin[2] += oldz - gun_origin[2]; } else { - oldz = origin[2]; + oldz = gun_origin[2]; } + Transform_SetWorldPosition (vs->camera_transform, origin); { // FIXME sort out the alias model specific negation vec3_t ang = {-viewangles[0], viewangles[1], viewangles[2]}; - CL_TransformEntity (view, 1, ang, origin); + CL_TransformEntity (view, 1, ang, gun_origin); } if (vs->chase && chase_active->int_val) { @@ -724,8 +732,9 @@ void V_RenderView (viewstate_t *vs) { if (!vs->active) { - r_data->refdef->viewposition = (vec4f_t) { 0, 0, 0, 1 }; - r_data->refdef->viewrotation = (vec4f_t) { 0, 0, 0, 1 }; + vec4f_t base = { 0, 0, 0, 1 }; + Transform_SetWorldPosition (vs->camera_transform, base); + Transform_SetWorldRotation (vs->camera_transform, base); return; } @@ -752,6 +761,8 @@ V_Init (viewstate_t *viewstate) "currently being displayed.\n" "Used when you are underwater, hit, have the Ring of " "Shadows, or Quad Damage. (v_cshift r g b intensity)"); + + viewstate->camera_transform = Transform_New (cl_scene, 0); } void diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 30ff8ab1c..cc36528e4 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -44,6 +44,7 @@ #include "QF/screen.h" #include "QF/sys.h" +#include "QF/scene/transform.h" #include "QF/ui/view.h" #include "compat.h" @@ -199,12 +200,20 @@ SCR_CalcRefdef (void) needs almost the entire 256k of stack space! */ void -SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs) +SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) { if (scr_skipupdate || !scr_initialized) { return; } + if (camera) { + r_data->refdef->viewposition = Transform_GetWorldPosition (camera); + r_data->refdef->viewrotation = Transform_GetWorldRotation (camera); + } else { + r_data->refdef->viewposition = (vec4f_t) { 0, 0, 0, 1 }; + r_data->refdef->viewrotation = (vec4f_t) { 0, 0, 0, 1 }; + } + r_data->realtime = realtime; scr_copytop = r_data->scr_copyeverything = 0; diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 4d1a88955..403c29f1c 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -46,7 +46,6 @@ nq_cl_plugin_LIBS= \ nq_client_LIBFILES= \ libs/gib/libQFgib_client.la \ - libs/scene/libQFscene.la \ libs/audio/libQFcd.la \ libs/audio/libQFsound.la @@ -55,6 +54,7 @@ nq_server_LIBFILES= \ libs/models/libQFmodels.la nq_common_LIBFILES= \ + libs/scene/libQFscene.la \ libs/net/libnet_main.la \ libs/console/libQFconsole.la \ libs/image/libQFimage.la \ diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index ca17c7d9d..1384bf721 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -199,7 +199,9 @@ CL_ClearState (void) } // wipe the entire cl structure + __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); + cl.viewstate.camera_transform = cam; cl.viewstate.chase = 1; cl.viewstate.chasestate = &cl.chasestate; cl.watervis = 1; diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 01188572e..927608352 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -46,6 +46,7 @@ #include "QF/plugin/vid_render.h" +#include "QF/scene/transform.h" #include "QF/ui/view.h" #include "sbar.h" @@ -75,9 +76,10 @@ SCR_CShift (void) int contents = CONTENTS_EMPTY; if (cls.state == ca_active && cl.worldmodel) { + vec4f_t origin; + origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); //FIXME - leaf = Mod_PointInLeaf (&r_data->refdef->viewposition[0], - cl.worldmodel); + leaf = Mod_PointInLeaf (&origin[0], cl.worldmodel); contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); @@ -167,5 +169,6 @@ CL_UpdateScreen (double realtime) cl.viewstate.intermission = cl.intermission != 0; V_PrepBlend (&cl.viewstate); V_RenderView (&cl.viewstate); - SCR_UpdateScreen (realtime, scr_funcs[index]); + SCR_UpdateScreen (cl.viewstate.camera_transform, + realtime, scr_funcs[index]); } diff --git a/nq/source/host.c b/nq/source/host.c index 77b93a5a5..9ecc52069 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -54,6 +54,7 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/transform.h" #include "buildnum.h" #include "compat.h" @@ -504,7 +505,9 @@ Host_ClearMemory (void) cls.signon = 0; memset (&sv, 0, sizeof (sv)); + __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); + cl.viewstate.camera_transform = cam; } /* @@ -606,15 +609,16 @@ Host_ClientFrame (void) if (cls.state == ca_active) { mleaf_t *l; byte *asl = 0; + vec4f_t origin; - l = Mod_PointInLeaf (r_data->origin, cl.worldmodel); + origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); + l = Mod_PointInLeaf (&origin[0], cl.worldmodel);//FIXME if (l) asl = l->ambient_sound_level; - S_Update (r_data->origin, r_data->vpn, r_data->vright, r_data->vup, - asl); + S_Update (cl.viewstate.camera_transform, asl); r_funcs->R_DecayLights (host_frametime); } else - S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin, 0); + S_Update (0, 0); CDAudio_Update (); diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index ea693c175..50dd443d9 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -141,8 +141,7 @@ IN_ProcessEvents (void) } void -S_Update (const vec3_t origin, const vec3_t v_forward, const vec3_t v_right, - const vec3_t v_up, const byte *ambient_sound_level) +S_Update (struct transform_s *ere, const byte *ambient_sound_level) { } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index c4a809f68..ee876eac5 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -90,6 +90,7 @@ #include "QF/gib.h" #include "QF/plugin/console.h" +#include "QF/scene/transform.h" #include "buildnum.h" #include "compat.h" @@ -389,7 +390,9 @@ CL_ClearState (void) Info_Destroy (cl.serverinfo); if (cl.players) free (cl.players); + __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); + cl.viewstate.camera_transform = cam; cl.players = calloc (MAX_CLIENTS, sizeof (player_info_t)); r_data->force_fullscreen = 0; @@ -1714,15 +1717,16 @@ Host_Frame (float time) if (cls.state == ca_active) { mleaf_t *l; byte *asl = 0; + vec4f_t origin; - l = Mod_PointInLeaf (r_data->origin, cl.worldmodel); + origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); + l = Mod_PointInLeaf (&origin[0], cl.worldmodel);//FIXME if (l) asl = l->ambient_sound_level; - S_Update (r_data->origin, r_data->vpn, r_data->vright, r_data->vup, - asl); + S_Update (cl.viewstate.camera_transform, asl); r_funcs->R_DecayLights (host_frametime); } else - S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin, 0); + S_Update (0, 0); CDAudio_Update (); diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 8bf09229a..fc26c6754 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -44,6 +44,7 @@ #include "QF/pcx.h" #include "QF/screen.h" +#include "QF/scene/transform.h" #include "QF/ui/view.h" #include "sbar.h" @@ -77,9 +78,10 @@ SCR_CShift (void) int contents = CONTENTS_EMPTY; if (cls.state == ca_active && cl.worldmodel) { + vec4f_t origin; + origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); //FIXME - leaf = Mod_PointInLeaf (&r_data->refdef->viewposition[0], - cl.worldmodel); + leaf = Mod_PointInLeaf (&origin[0], cl.worldmodel); contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); @@ -200,5 +202,6 @@ CL_UpdateScreen (double realtime) cl.viewstate.intermission = cl.intermission != 0; V_PrepBlend (&cl.viewstate); V_RenderView (&cl.viewstate); - SCR_UpdateScreen (realtime, scr_funcs[index]); + SCR_UpdateScreen (cl.viewstate.camera_transform, + realtime, scr_funcs[index]); } diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index a53275a13..1d6841998 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -109,7 +109,7 @@ bi_refresh (progs_t *pr, void *_res) IN_ProcessEvents (); //GIB_Thread_Execute (); Cbuf_Execute_Stack (qwaq_cbuf); - SCR_UpdateScreen (con_realtime, bi_2dfuncs); + SCR_UpdateScreen (0, con_realtime, bi_2dfuncs); R_FLOAT (pr) = con_frametime; } From 457c73967bf0421218cedc80f606d91829558e6a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Mar 2022 01:02:11 +0900 Subject: [PATCH 2476/3664] [sound] Correct "default" listener origin Position vectors need to be homogeneous, I forgot that when doing the change. --- libs/audio/renderer/snd_channels.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index bd820cf72..09e1bda30 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -555,7 +555,7 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level) listener_right = Transform_Right (ear); listener_up = Transform_Up (ear); } else { - listener_origin = (vec4f_t) { }; + listener_origin = (vec4f_t) {0, 0, 0, 1}; listener_forward = (vec4f_t) {1, 0, 0, 0}; listener_right = (vec4f_t) {0, -1, 0, 0}; listener_up = (vec4f_t) {0, 0, 1, 0}; From fb83d87a0efca956469c259209bd0745ac87a992 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Mar 2022 10:12:50 +0900 Subject: [PATCH 2477/3664] Fix some distcheck issues Just keeping up with myself. --- include/Makemodule.am | 1 + libs/gamecode/Makemodule.am | 6 ++++++ nq/include/Makemodule.am | 1 - qw/include/Makemodule.am | 1 - 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/Makemodule.am b/include/Makemodule.am index 01bdc2a69..e548f8bbf 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -82,6 +82,7 @@ EXTRA_DIST += \ include/vregset.h \ include/winquake.h \ include/world.h \ + include/client/chase.h \ include/client/effects.h \ include/client/entities.h \ include/client/hud.h \ diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index 411bfb645..ab294580a 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -43,6 +43,12 @@ BUILT_SOURCES += \ $(pr_convert_cinc) \ $(pr_hops_cinc) +CLEANFILES += \ + $(pr_opcode_cinc) \ + $(pr_opcode_hinc) \ + $(pr_hops_cinc) \ + $(pr_convert_cinc) + $(pr_opcode_cinc): $(opcodes_py) $(V_PY)$(PYTHON) $(opcodes_py) table > $(pr_opcode_cinc).t && \ $(am__mv) $(pr_opcode_cinc).t $(pr_opcode_cinc) diff --git a/nq/include/Makemodule.am b/nq/include/Makemodule.am index ba1076749..6956660cc 100644 --- a/nq/include/Makemodule.am +++ b/nq/include/Makemodule.am @@ -1,6 +1,5 @@ ## Process this file with automake to produce Makefile.in EXTRA_DIST += \ - nq/include/chase.h \ nq/include/cl_skin.h \ nq/include/client.h \ nq/include/game.h \ diff --git a/qw/include/Makemodule.am b/qw/include/Makemodule.am index c30d5decf..4a937f07b 100644 --- a/qw/include/Makemodule.am +++ b/qw/include/Makemodule.am @@ -1,5 +1,4 @@ EXTRA_DIST += \ - qw/include/chase.h \ qw/include/cl_cam.h \ qw/include/cl_chat.h \ qw/include/cl_demo.h \ From 43a329dcb545d755623dcf06e5debb85cff261ea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Mar 2022 11:43:23 +0900 Subject: [PATCH 2478/3664] [client] Get the basic chase camera working The more advanced modes are rather broken (continuous spinning), but they may have been for a while. The bulk of the various changes were due to renaming viewstate's origin and angles to make their meaning more explicit. --- include/client/view.h | 6 ++--- libs/client/cl_chase.c | 58 ++++++++++++++++++++---------------------- libs/client/cl_view.c | 25 +++++++++--------- nq/source/cl_demo.c | 2 +- nq/source/cl_ents.c | 5 ++-- nq/source/cl_input.c | 7 ++--- nq/source/cl_main.c | 3 ++- nq/source/cl_parse.c | 3 ++- qw/source/cl_cam.c | 14 +++++----- qw/source/cl_demo.c | 4 +-- qw/source/cl_ents.c | 10 ++++---- qw/source/cl_input.c | 6 ++--- qw/source/cl_main.c | 16 ++++++------ qw/source/cl_parse.c | 18 ++++++------- qw/source/cl_pred.c | 9 ++++--- qw/source/cl_screen.c | 3 +++ qw/source/teamplay.c | 16 ++++++------ 17 files changed, 105 insertions(+), 100 deletions(-) diff --git a/include/client/view.h b/include/client/view.h index d832fe0af..ee6620ed0 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -39,11 +39,12 @@ #define INFO_CSHIFT_POWERUP (1 << 3) typedef struct viewstate_s { + vec4f_t player_origin; + vec3_t player_angles; + int chase; vec4f_t movecmd; vec4f_t velocity; - vec4f_t origin; vec4f_t punchangle; - vec3_t angles; float frametime; struct transform_s *camera_transform; double time; @@ -77,7 +78,6 @@ typedef struct viewstate_s { struct entity_s *player_entity; struct chasestate_s *chasestate; - int chase; } viewstate_t; #define VF_DEAD 1 diff --git a/libs/client/cl_chase.c b/libs/client/cl_chase.c index bafac3b51..1fcb332a4 100644 --- a/libs/client/cl_chase.c +++ b/libs/client/cl_chase.c @@ -41,7 +41,7 @@ #include "QF/mathlib.h" #include "QF/plugin/vid_render.h" -#include "QF/simd/vec4f.h" +#include "QF/scene/transform.h" #include "world.h" @@ -83,21 +83,22 @@ Chase_Reset (void) // start position 12 units behind head } -static inline void -TraceLine (chasestate_t *cs, vec3_t start, vec3_t end, vec3_t impact) +static inline vec4f_t +TraceLine (chasestate_t *cs, vec4f_t start, vec4f_t end) { trace_t trace; memset (&trace, 0, sizeof (trace)); trace.fraction = 1; - MOD_TraceLine (cs->worldmodel->brush.hulls, 0, start, end, &trace); + MOD_TraceLine (cs->worldmodel->brush.hulls, 0, &start[0], &end[0], &trace); - VectorCopy (trace.endpos, impact); + return (vec4f_t) {trace.endpos[0], trace.endpos[1], trace.endpos[2], 1}; } void Chase_Update (chasestate_t *cs) { + viewstate_t *vs = cs->viewstate; float pitch, yaw, fwd; vec4f_t move = {}; vec4f_t forward = {}, up = {}, right = {}, stop = {}, dir = {}; @@ -107,28 +108,25 @@ Chase_Update (chasestate_t *cs) if (chase_active->int_val == 2 || chase_active->int_val == 3) { // control camera angles with key/mouse/joy-look vec3_t d; - VectorSubtract (cs->viewstate->angles, player_angles, d); + VectorSubtract (vs->player_angles, player_angles, d); VectorAdd (camera_angles, d, camera_angles); if (chase_active->int_val == 2) { - if (camera_angles[PITCH] < -60) - camera_angles[PITCH] = -60; - if (camera_angles[PITCH] > 60) - camera_angles[PITCH] = 60; + camera_angles[PITCH] = bound (-60, camera_angles[PITCH], 60); } // move camera, it's not enough to just change the angles because // the angles are automatically changed to look toward the player if (chase_active->int_val == 3) { - player_origin = r_data->refdef->viewposition; + player_origin = vs->player_origin; } AngleVectors (camera_angles, &forward[0], &right[0], &up[0]); camera_origin = player_origin - chase_back->value * forward; if (chase_active->int_val == 2) { - player_origin = r_data->refdef->viewposition; + player_origin = vs->player_origin; // don't let camera get too low if (camera_origin[2] < player_origin[2] + chase_up->value) { @@ -148,14 +146,12 @@ Chase_Update (chasestate_t *cs) // check for walls between player and camera camera_origin += 8 * forward; - //FIXME - TraceLine (cs, &player_origin[0], &camera_origin[0], &stop[0]); - stop[3] = 1; + stop = TraceLine (cs, player_origin, camera_origin); if (magnitude3f (stop)[0] != 0) { camera_origin = stop - forward; } - dir = camera_origin - r_data->refdef->viewposition; + dir = camera_origin - vs->player_origin; forward = normalf (dir); if (chase_active->int_val == 2) { @@ -184,12 +180,14 @@ Chase_Update (chasestate_t *cs) } } - AngleQuat (camera_angles, &r_data->refdef->viewrotation[0]);//FIXME rotate camera - r_data->refdef->viewposition = camera_origin; // move camera + vec4f_t rotation; + AngleQuat (camera_angles, &rotation[0]);//FIXME + Transform_SetWorldRotation (vs->camera_transform, rotation); + Transform_SetWorldPosition (vs->camera_transform, camera_origin); // get basic movement from keyboard -// VectorCopy (cs->viewstate->angles, cmd.angles); +// VectorCopy (vs->player_angles, cmd.angles); if (in_strafe.state & 1) { move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_right); @@ -208,7 +206,7 @@ Chase_Update (chasestate_t *cs) } // mouse and joystick controllers add to movement - VectorSet (0, cs->viewstate->angles[1] - camera_angles[1], 0, dir); + VectorSet (0, vs->player_angles[1] - camera_angles[1], 0, dir); AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME //forward *= viewdelta.position[2] * m_forward->value; FIXME //right *= viewdelta.position[0] * m_side->value; FIXME @@ -224,16 +222,16 @@ Chase_Update (chasestate_t *cs) VectorAdd (forward, right, dir); if (dir[1] || dir[0]) { - cs->viewstate->angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (cs->viewstate->angles[YAW] < 0) { - cs->viewstate->angles[YAW] += 360; + vs->player_angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); + if (vs->player_angles[YAW] < 0) { + vs->player_angles[YAW] += 360; } } - cs->viewstate->angles[PITCH] = 0; + vs->player_angles[PITCH] = 0; // remember the new angle to calculate the difference next frame - VectorCopy (cs->viewstate->angles, player_angles); + VectorCopy (vs->player_angles, player_angles); return; } @@ -241,21 +239,19 @@ Chase_Update (chasestate_t *cs) // regular camera, faces same direction as player //FIXME - AngleVectors (cs->viewstate->angles, &forward[0], &right[0], &up[0]); + AngleVectors (vs->player_angles, &forward[0], &right[0], &up[0]); // calc exact destination - camera_origin = r_data->refdef->viewposition + camera_origin = vs->player_origin - forward * chase_back->value - right * chase_right->value; // chase_up is world up camera_origin[2] += chase_up->value; // check for walls between player and camera - //FIXME - TraceLine (cs, &r_data->refdef->viewposition[0], &camera_origin[0], &stop[0]); - stop[3] = 1; + stop = TraceLine (cs, vs->player_origin, camera_origin); if (magnitude3f (stop)[0] != 0) { camera_origin = stop + forward * 8; } - r_data->refdef->viewposition = camera_origin; + Transform_SetWorldPosition (vs->camera_transform, camera_origin); } diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index fd93dc16a..2bf0c7921 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -246,7 +246,7 @@ V_DriftPitch (viewstate_t *vs) return; } - delta = vs->idealpitch - vs->angles[PITCH]; + delta = vs->idealpitch - vs->player_angles[PITCH]; if (!delta) { vs->pitchvel = 0; @@ -261,13 +261,13 @@ V_DriftPitch (viewstate_t *vs) vs->pitchvel = 0; move = delta; } - vs->angles[PITCH] += move; + vs->player_angles[PITCH] += move; } else if (delta < 0) { if (move > -delta) { vs->pitchvel = 0; move = -delta; } - vs->angles[PITCH] -= move; + vs->player_angles[PITCH] -= move; } } @@ -278,8 +278,8 @@ V_ParseDamage (qmsg_t *net_message, viewstate_t *vs) { float count, side; int armor, blood; - vec4f_t origin = vs->origin; - vec_t *angles = vs->angles; + vec4f_t origin = vs->player_origin; + vec_t *angles = vs->player_angles; vec3_t from, forward, right, up; armor = MSG_ReadByte (net_message); @@ -485,7 +485,7 @@ static void V_BoundOffsets (viewstate_t *vs) { vec4f_t offset = Transform_GetWorldPosition (vs->camera_transform); - offset -= vs->origin; + offset -= vs->player_origin; // absolutely bound refresh reletive to entity clipping hull // so the view can never be inside a solid wall @@ -493,7 +493,8 @@ V_BoundOffsets (viewstate_t *vs) offset[0] = bound (-14, offset[0], 14); offset[1] = bound (-14, offset[1], 14); offset[2] = bound (-22, offset[2], 30); - Transform_SetWorldPosition (vs->camera_transform, vs->origin + offset); + Transform_SetWorldPosition (vs->camera_transform, + vs->player_origin + offset); } static vec4f_t @@ -544,7 +545,7 @@ V_AddIdle (viewstate_t *vs) static void V_CalcViewRoll (viewstate_t *vs) { - vec_t *angles = vs->angles; + vec_t *angles = vs->player_angles; vec4f_t velocity = vs->velocity; vec3_t ang = { }; @@ -598,8 +599,8 @@ V_CalcRefdef (viewstate_t *vs) float bob; static float oldz = 0; vec4f_t forward = {}, right = {}, up = {}; - vec4f_t origin = vs->origin; - vec_t *viewangles = vs->angles; + vec4f_t origin = vs->player_origin; + vec_t *viewangles = vs->player_angles; V_DriftPitch (vs); @@ -615,7 +616,7 @@ V_CalcRefdef (viewstate_t *vs) origin += (vec4f_t) { 1.0/16, 1.0/16, 1.0/16, 0}; vec4f_t rotation; - AngleQuat (vs->angles, &rotation[0]);//FIXME + AngleQuat (vs->player_angles, &rotation[0]);//FIXME Transform_SetWorldRotation (vs->camera_transform, rotation); V_CalcViewRoll (vs); V_AddIdle (vs); @@ -635,7 +636,7 @@ V_CalcRefdef (viewstate_t *vs) V_BoundOffsets (vs); // set up gun position - vec4f_t gun_origin = vs->origin; + vec4f_t gun_origin = vs->player_origin; CalcGunAngle (vs); gun_origin += (vec4f_t) { 0, 0, vs->height, 0 }; diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 606eb243e..bdcf684a8 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -105,7 +105,7 @@ CL_WriteDemoMessage (sizebuf_t *msg) len = LittleLong (msg->cursize); Qwrite (cls.demofile, &len, 4); for (i = 0; i < 3; i++) { - f = LittleFloat (cl.viewstate.angles[i]); + f = LittleFloat (cl.viewstate.player_angles[i]); Qwrite (cls.demofile, &f, 4); } Qwrite (cls.demofile, msg->data, msg->cursize); diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index c186c91a8..16c590061 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -170,7 +170,8 @@ CL_RelinkEntities (void) d[j] += 360; } } - VectorMultAdd (cl.frameViewAngles[1], frac, d, cl.viewstate.angles); + VectorMultAdd (cl.frameViewAngles[1], frac, d, + cl.viewstate.player_angles); } bobjrotate = anglemod (100 * cl.time); @@ -304,6 +305,6 @@ CL_RelinkEntities (void) cl_forcelink[i] = false; } - cl.viewstate.origin + cl.viewstate.player_origin = Transform_GetWorldPosition (cl_entities[cl.viewentity].transform); } diff --git a/nq/source/cl_input.c b/nq/source/cl_input.c index 0f63d7017..a2e039730 100644 --- a/nq/source/cl_input.c +++ b/nq/source/cl_input.c @@ -74,14 +74,15 @@ CL_BaseMove (usercmd_t *cmd) if (cls.state != ca_active) { return; } - VectorCopy (cl.viewstate.angles, cl.movestate.angles);//FIXME + VectorCopy (cl.viewstate.player_angles, cl.movestate.angles);//FIXME CL_Input_BuildMove (host_frametime, &cl.movestate, &cl.viewstate); - VectorCopy (cl.movestate.angles, cl.viewstate.angles);//FIXME + VectorCopy (cl.movestate.angles, cl.viewstate.player_angles);//FIXME memset (cmd, 0, sizeof (*cmd)); cmd->forwardmove = cl.movestate.move[FORWARD]; cmd->sidemove = cl.movestate.move[SIDE]; cmd->upmove = cl.movestate.move[UP]; + cl.viewstate.movecmd = cl.movestate.move; } @@ -103,7 +104,7 @@ CL_SendMove (usercmd_t *cmd) MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times - write_angles (&buf, cl.viewstate.angles); + write_angles (&buf, cl.viewstate.player_angles); MSG_WriteShort (&buf, cmd->forwardmove); MSG_WriteShort (&buf, cmd->sidemove); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 1384bf721..83748c3c4 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -204,6 +204,7 @@ CL_ClearState (void) cl.viewstate.camera_transform = cam; cl.viewstate.chase = 1; cl.viewstate.chasestate = &cl.chasestate; + cl.chasestate.viewstate = &cl.viewstate; cl.watervis = 1; r_data->force_fullscreen = 0; r_data->lightstyle = cl.lightstyle; @@ -534,7 +535,7 @@ CL_SetState (cactive_t state) static void Force_CenterView_f (void) { - cl.viewstate.angles[PITCH] = 0; + cl.viewstate.player_angles[PITCH] = 0; } void diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 595bec0a7..f8e052151 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -440,6 +440,7 @@ CL_ParseServerInfo (void) // local state cl_entities[0].renderer.model = cl.worldmodel = cl.model_precache[1]; + cl.chasestate.worldmodel = cl.worldmodel; if (!centerprint) centerprint = dstring_newstr (); else @@ -959,7 +960,7 @@ CL_ParseServerMessage (void) case svc_setangle: { - vec_t *dest = cl.viewstate.angles; + vec_t *dest = cl.viewstate.player_angles; MSG_ReadAngleV (net_message, dest); break; diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 48a34cb9a..d5d75ce22 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -438,7 +438,7 @@ Cam_Track (usercmd_t *cmd) if (cl_chasecam->int_val) { cmd->forwardmove = cmd->sidemove = cmd->upmove = 0; - VectorCopy (player->viewangles, cl.viewstate.angles); + VectorCopy (player->viewangles, cl.viewstate.player_angles); VectorCopy (player->pls.es.origin, desired_position); if (memcmp (&desired_position, &self->pls.es.origin, sizeof (desired_position)) != 0) { @@ -467,8 +467,8 @@ Cam_Track (usercmd_t *cmd) VectorCopy (desired_position, self->pls.es.origin); VectorSubtract (player->pls.es.origin, desired_position, vec); - vectoangles (vec, cl.viewstate.angles); - cl.viewstate.angles[0] = -cl.viewstate.angles[0]; + vectoangles (vec, cl.viewstate.player_angles); + cl.viewstate.player_angles[0] = -cl.viewstate.player_angles[0]; } } @@ -535,8 +535,8 @@ Cam_SetView (void) adjustang (cam_viewangles[YAW], vec2[YAW], cl_camera_maxyaw->value); } - VectorCopy (cam_viewangles, cl.viewstate.angles); - VectorCopy (cl.viewstate.angles, cl.simangles); + VectorCopy (cam_viewangles, cl.viewstate.player_angles); + VectorCopy (cl.viewstate.player_angles, cl.simangles); cl.simangles[ROLL] = 0; // FIXME @@@ } #endif @@ -575,7 +575,7 @@ Cam_FinishMove (usercmd_t *cmd) adjustang (cam_viewangles[YAW], vec2[YAW], cl_camera_maxyaw->value); } - VectorCopy (cam_viewangles, cl.viewstate.angles); + VectorCopy (cam_viewangles, cl.viewstate.player_angles); } #endif @@ -586,7 +586,7 @@ Cam_FinishMove (usercmd_t *cmd) if (autocam > CAM_TRACK) { Cam_Unlock (); - VectorCopy (cl.viewstate.angles, cmd->angles); + VectorCopy (cl.viewstate.player_angles, cmd->angles); return; } } else diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index e82e45d10..d03e7b4b5 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -333,7 +333,7 @@ nextdemomessage: cls.netchan.outgoing_sequence++; for (i = 0; i < 3; i++) { Qread (cls.demofile, &f, 4); - cl.viewstate.angles[i] = LittleFloat (f); + cl.viewstate.player_angles[i] = LittleFloat (f); } break; @@ -462,7 +462,7 @@ CL_WriteDemoCmd (usercmd_t *pcmd) Qwrite (cls.demofile, &cmd, sizeof (cmd)); for (i = 0; i < 3; i++) { - fl = LittleFloat (cl.viewstate.angles[i]); + fl = LittleFloat (cl.viewstate.player_angles[i]); Qwrite (cls.demofile, &fl, 4); } diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index e1eb60d8d..84bd9ba72 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -394,7 +394,7 @@ CL_LinkPlayers (void) // spawn light flashes, even ones coming from invisible objects if (j == cl.playernum) { - org = cl.viewstate.origin; + org = cl.viewstate.player_origin; r_data->player_entity = &cl_player_ents[j]; clientplayer = true; } else { @@ -444,8 +444,8 @@ CL_LinkPlayers (void) // angles if (j == cl.playernum) { - ang[PITCH] = -cl.viewstate.angles[PITCH] / 3.0; - ang[YAW] = cl.viewstate.angles[YAW]; + ang[PITCH] = -cl.viewstate.player_angles[PITCH] / 3.0; + ang[YAW] = cl.viewstate.player_angles[YAW]; } else { ang[PITCH] = -state->viewangles[PITCH] / 3.0; ang[YAW] = state->viewangles[YAW]; @@ -516,14 +516,14 @@ CL_EmitEntities (void) return; TEntContext_t tentCtx = { - cl.viewstate.origin, cl.worldmodel, cl.viewentity + cl.viewstate.player_origin, cl.worldmodel, cl.viewentity }; CL_LinkPlayers (); CL_LinkPacketEntities (); CL_UpdateTEnts (cl.time, &tentCtx); if (cl_draw_locs->int_val) { - locs_draw (cl.time, cl.viewstate.origin); + locs_draw (cl.time, cl.viewstate.player_origin); } } diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 9fe4be0ea..1a04d1579 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -90,9 +90,9 @@ CL_BaseMove (usercmd_t *cmd) if (cls.state != ca_active) { return; } - VectorCopy (cl.viewstate.angles, cl.movestate.angles);//FIXME + VectorCopy (cl.viewstate.player_angles, cl.movestate.angles);//FIXME CL_Input_BuildMove (host_frametime, &cl.movestate, &cl.viewstate); - VectorCopy (cl.movestate.angles, cl.viewstate.angles);//FIXME + VectorCopy (cl.movestate.angles, cl.viewstate.player_angles);//FIXME memset (cmd, 0, sizeof (*cmd)); cmd->forwardmove = cl.movestate.move[FORWARD]; @@ -139,7 +139,7 @@ CL_FinishMove (usercmd_t *cmd) } cmd->msec = ms; - VectorCopy (cl.viewstate.angles, cmd->angles); + VectorCopy (cl.viewstate.player_angles, cmd->angles); cmd->impulse = in_impulse; in_impulse = 0; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index ee876eac5..566fa1a10 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1102,7 +1102,7 @@ CL_Download_f (void) static void Force_CenterView_f (void) { - cl.viewstate.angles[PITCH] = 0; + cl.viewstate.player_angles[PITCH] = 0; } static void @@ -1111,12 +1111,12 @@ CL_PRotate_f (void) if ((cl.fpd & FPD_LIMIT_PITCH) || Cmd_Argc() < 2) return; - cl.viewstate.angles[PITCH] += atoi (Cmd_Argv (1)); + cl.viewstate.player_angles[PITCH] += atoi (Cmd_Argv (1)); - if (cl.viewstate.angles[PITCH] < -70) - cl.viewstate.angles[PITCH] = -70; - else if (cl.viewstate.angles[PITCH] > 80) - cl.viewstate.angles[PITCH] = 80; + if (cl.viewstate.player_angles[PITCH] < -70) + cl.viewstate.player_angles[PITCH] = -70; + else if (cl.viewstate.player_angles[PITCH] > 80) + cl.viewstate.player_angles[PITCH] = 80; } static void @@ -1125,8 +1125,8 @@ CL_Rotate_f (void) if ((cl.fpd & FPD_LIMIT_YAW) || Cmd_Argc() < 2) return; - cl.viewstate.angles[YAW] += atoi (Cmd_Argv (1)); - cl.viewstate.angles[YAW] = anglemod (cl.viewstate.angles[YAW]); + cl.viewstate.player_angles[YAW] += atoi (Cmd_Argv (1)); + cl.viewstate.player_angles[YAW] = anglemod(cl.viewstate.player_angles[YAW]); } void diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index d8d2dd5e2..d25c42405 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1295,7 +1295,7 @@ CL_ParseMuzzleFlash (void) pl = &cl.frames[parsecountmod].playerstate[i - 1]; if (i - 1 == cl.playernum) - AngleVectors (cl.viewstate.angles, f, r, u); + AngleVectors (cl.viewstate.player_angles, f, r, u); else AngleVectors (pl->viewangles, f, r, u); @@ -1317,7 +1317,7 @@ CL_ParseServerMessage (void) const char *str; static dstring_t *stuffbuf; TEntContext_t tentCtx = { - cl.viewstate.origin, cl.worldmodel, cl.viewentity + cl.viewstate.player_origin, cl.worldmodel, cl.viewentity }; received_framecount = host_framecount; @@ -1437,7 +1437,7 @@ CL_ParseServerMessage (void) case svc_setangle: { - vec_t *dest = cl.viewstate.angles; + vec_t *dest = cl.viewstate.player_angles; vec3_t dummy; if (cls.demoplayback2) { @@ -1565,15 +1565,15 @@ CL_ParseServerMessage (void) cl.completed_time = realtime; r_data->vid->recalc_refdef = true; // go to full screen Sys_MaskPrintf (SYS_dev, "intermission simorg: "); - MSG_ReadCoordV (net_message, &cl.viewstate.origin[0]);//FIXME - cl.viewstate.origin[3] = 1; + MSG_ReadCoordV (net_message, &cl.viewstate.player_origin[0]);//FIXME + cl.viewstate.player_origin[3] = 1; Sys_MaskPrintf (SYS_dev, VEC4F_FMT, - VEC4_EXP (cl.viewstate.origin)); + VEC4_EXP (cl.viewstate.player_origin)); Sys_MaskPrintf (SYS_dev, "\nintermission simangles: "); - MSG_ReadAngleV (net_message, cl.viewstate.angles); - cl.viewstate.angles[ROLL] = 0; // FIXME @@@ + MSG_ReadAngleV (net_message, cl.viewstate.player_angles); + cl.viewstate.player_angles[ROLL] = 0; // FIXME @@@ Sys_MaskPrintf (SYS_dev, "%f %f %f", - VectorExpand (cl.viewstate.angles)); + VectorExpand (cl.viewstate.player_angles)); Sys_MaskPrintf (SYS_dev, "\n"); cl.viewstate.velocity = (vec4f_t) { }; diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index 40f9f1459..7d25dd354 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -133,7 +133,7 @@ CL_PredictMove (void) return; //VectorCopy (cl.viewstate.angles, cl.viewstate.angles); - cl.viewstate.angles[ROLL] = 0; // FIXME @@@ + cl.viewstate.player_angles[ROLL] = 0; // FIXME @@@ // this is the last frame received from the server from = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; @@ -141,7 +141,7 @@ CL_PredictMove (void) if (!cl_predict->int_val) { cl.viewstate.velocity = fromes->velocity; - cl.viewstate.origin = fromes->origin; + cl.viewstate.player_origin = fromes->origin; return; } @@ -182,11 +182,12 @@ CL_PredictMove (void) if (fabs (fromes->origin[i] - toes->origin[i]) > 128) { // teleported, so don't lerp cl.viewstate.velocity = toes->velocity; - cl.viewstate.origin = toes->origin; + cl.viewstate.player_origin = toes->origin; return; } - cl.viewstate.origin = fromes->origin + f * (toes->origin - fromes->origin); + cl.viewstate.player_origin = fromes->origin + + f * (toes->origin - fromes->origin); } void diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index fc26c6754..3bdef1963 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -201,6 +201,9 @@ CL_UpdateScreen (double realtime) cl.viewstate.intermission = cl.intermission != 0; V_PrepBlend (&cl.viewstate); + int seq = (cls.netchan.outgoing_sequence - 1) & UPDATE_MASK; + frame_t *frame = &cl.frames[seq]; + cl.viewstate.movecmd[FORWARD] = frame->cmd.forwardmove; V_RenderView (&cl.viewstate); SCR_UpdateScreen (cl.viewstate.camera_transform, realtime, scr_funcs[index]); diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index c3e2a0424..3bc9894f5 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -184,10 +184,10 @@ Team_ParseSay (dstring_t *buf, const char *s) case 'l': location: bracket = 0; - location = locs_find (cl.viewstate.origin); + location = locs_find (cl.viewstate.player_origin); if (location) { recorded_location = true; - last_recorded_location = cl.viewstate.origin; + last_recorded_location = cl.viewstate.player_origin; t1 = location->name; } else snprintf (t2, sizeof (t2), "Unknown!"); @@ -279,7 +279,7 @@ void Team_Dead (void) { died = true; - death_location = cl.viewstate.origin; + death_location = cl.viewstate.player_origin; } void @@ -370,7 +370,7 @@ locs_loc (void) if (strcasecmp (Cmd_Argv (1), "add") == 0) { if (Cmd_Argc () >= 3) - locs_mark (cl.viewstate.origin, desc); + locs_mark (cl.viewstate.player_origin, desc); else Sys_Printf ("loc add :marks the current location " "with the description and records the information " @@ -379,7 +379,7 @@ locs_loc (void) if (strcasecmp (Cmd_Argv (1), "rename") == 0) { if (Cmd_Argc () >= 3) - locs_edit (cl.viewstate.origin, desc); + locs_edit (cl.viewstate.player_origin, desc); else Sys_Printf ("loc rename :changes the description of " "the nearest location marker\n"); @@ -387,14 +387,14 @@ locs_loc (void) if (strcasecmp (Cmd_Argv (1),"delete") == 0) { if (Cmd_Argc () == 2) - locs_del (cl.viewstate.origin); + locs_del (cl.viewstate.player_origin); else Sys_Printf ("loc delete :removes nearest location marker\n"); } if (strcasecmp (Cmd_Argv (1),"move") == 0) { if (Cmd_Argc () == 2) - locs_edit (cl.viewstate.origin, NULL); + locs_edit (cl.viewstate.player_origin, NULL); else Sys_Printf ("loc move :moves the nearest location marker to your " "current location\n"); @@ -409,7 +409,7 @@ Locs_Loc_Get (void) if (GIB_Argc () != 1) GIB_USAGE (""); else { - location = locs_find (cl.viewstate.origin); + location = locs_find (cl.viewstate.player_origin); GIB_Return (location ? location->name : "unknown"); } } From 5b08ee768cd6eea89651f79b4ce987d451e3dde1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Mar 2022 13:49:14 +0900 Subject: [PATCH 2479/3664] [client] Clean up chase camera code It's a lot easier to read (and see the difference between modes 2 and 3) with all the ifs removed, and the state is properly is chasestate_t now (though not handled properly on level reset etc). --- include/client/chase.h | 7 + libs/client/cl_chase.c | 337 +++++++++++++++++++++++------------------ 2 files changed, 197 insertions(+), 147 deletions(-) diff --git a/include/client/chase.h b/include/client/chase.h index 1a8fcfa54..a1415408b 100644 --- a/include/client/chase.h +++ b/include/client/chase.h @@ -28,9 +28,16 @@ #ifndef __client_chase_h #define __client_chase_h +#include "QF/math/vector.h" +#include "QF/simd/vec4f.h" + typedef struct chasestate_s { struct model_s *worldmodel; struct viewstate_s *viewstate; + vec4f_t camera_origin; + vec4f_t player_origin; + vec3_t camera_angles; + vec3_t player_angles; } chasestate_t; extern struct cvar_s *chase_active; diff --git a/libs/client/cl_chase.c b/libs/client/cl_chase.c index 1fcb332a4..e7e0eb079 100644 --- a/libs/client/cl_chase.c +++ b/libs/client/cl_chase.c @@ -50,17 +50,6 @@ #include "client/view.h" -vec4f_t camera_origin = {0,0,0,1}; -vec4f_t player_origin = {0,0,0,1}; -vec4f_t player_angles = {0,0,0,1}; - -vec3_t camera_angles = {0,0,0}; - -vec3_t chase_angles; -vec3_t chase_dest; -vec3_t chase_dest_angles; -vec3_t chase_pos; - cvar_t *chase_back; cvar_t *chase_up; cvar_t *chase_right; @@ -95,163 +84,217 @@ TraceLine (chasestate_t *cs, vec4f_t start, vec4f_t end) return (vec4f_t) {trace.endpos[0], trace.endpos[1], trace.endpos[2], 1}; } -void -Chase_Update (chasestate_t *cs) +static void +check_for_walls (chasestate_t *cs, vec4f_t forward) { - viewstate_t *vs = cs->viewstate; - float pitch, yaw, fwd; - vec4f_t move = {}; - vec4f_t forward = {}, up = {}, right = {}, stop = {}, dir = {}; + // check for walls between player and camera + cs->camera_origin += 8 * forward; + vec4f_t stop = TraceLine (cs, cs->player_origin, cs->camera_origin); + if (magnitude3f (stop)[0] != 0) { + cs->camera_origin = stop - forward; + } +} - // lazy camera, look toward player entity - if (chase_active->int_val == 2 || chase_active->int_val == 3) { - // control camera angles with key/mouse/joy-look - vec3_t d; - VectorSubtract (vs->player_angles, player_angles, d); - VectorAdd (camera_angles, d, camera_angles); +static void +limit_distance (chasestate_t *cs) +{ + // don't let camera get too far from player - if (chase_active->int_val == 2) { - camera_angles[PITCH] = bound (-60, camera_angles[PITCH], 60); - } + vec4f_t dir = cs->camera_origin - cs->player_origin; + vec4f_t forward = normalf (dir); - // move camera, it's not enough to just change the angles because - // the angles are automatically changed to look toward the player + if (magnitudef (dir)[0] > chase_back->value) { + cs->camera_origin = cs->player_origin + forward * chase_back->value; + } +} - if (chase_active->int_val == 3) { - player_origin = vs->player_origin; - } +static void +set_camera (chasestate_t *cs, viewstate_t *vs) +{ + vec4f_t rotation; + AngleQuat (cs->camera_angles, &rotation[0]);//FIXME + Transform_SetWorldRotation (vs->camera_transform, rotation); + Transform_SetWorldPosition (vs->camera_transform, cs->camera_origin); +} - AngleVectors (camera_angles, &forward[0], &right[0], &up[0]); - camera_origin = player_origin - chase_back->value * forward; +static void +cam_controls (chasestate_t *cs, viewstate_t *vs) +{ + // get basic movement from keyboard + vec4f_t move = { }; + vec4f_t forward = { }; + vec4f_t right = { }; + vec4f_t up = { }; + vec4f_t dir = { }; - if (chase_active->int_val == 2) { - player_origin = vs->player_origin; + if (in_strafe.state & 1) { + move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_right); + move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_left); + } + move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_moveright); + move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); - // don't let camera get too low - if (camera_origin[2] < player_origin[2] + chase_up->value) { - camera_origin[2] = player_origin[2] + chase_up->value; - } - } - - // don't let camera get too far from player - - dir = camera_origin - player_origin; - forward = normalf (dir); - - if (magnitudef (dir)[0] > chase_back->value) { - camera_origin = player_origin + forward * chase_back->value; - } - - // check for walls between player and camera - - camera_origin += 8 * forward; - stop = TraceLine (cs, player_origin, camera_origin); - if (magnitude3f (stop)[0] != 0) { - camera_origin = stop - forward; - } - - dir = camera_origin - vs->player_origin; - forward = normalf (dir); - - if (chase_active->int_val == 2) { - if (dir[1] == 0 && dir[0] == 0) { - // look straight up or down -// camera_angles[YAW] = r_data->refdef->viewstate->angles[YAW]; - if (dir[2] > 0) - camera_angles[PITCH] = 90; - else - camera_angles[PITCH] = 270; - } else { - yaw = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - if (yaw < 180) - yaw += 180; - else - yaw -= 180; - camera_angles[YAW] = yaw; - - fwd = sqrt (dir[0] * dir[0] + dir[1] * dir[1]); - pitch = (atan2 (dir[2], fwd) * 180 / M_PI); - if (pitch < 0) - pitch += 360; - camera_angles[PITCH] = pitch; - } - } - - vec4f_t rotation; - AngleQuat (camera_angles, &rotation[0]);//FIXME - Transform_SetWorldRotation (vs->camera_transform, rotation); - Transform_SetWorldPosition (vs->camera_transform, camera_origin); - - // get basic movement from keyboard - -// VectorCopy (vs->player_angles, cmd.angles); - - if (in_strafe.state & 1) { - move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_right); - move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_left); - } - move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_moveright); - move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); - - if (!(in_klook.state & 1)) { - move[FORWARD] += cl_forwardspeed->value - * IN_ButtonState (&in_forward); - move[FORWARD] -= cl_backspeed->value * IN_ButtonState (&in_back); - } - if (in_speed.state & 1) { - move *= cl_movespeedkey->value; - } - - // mouse and joystick controllers add to movement - VectorSet (0, vs->player_angles[1] - camera_angles[1], 0, dir); - AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME - //forward *= viewdelta.position[2] * m_forward->value; FIXME - //right *= viewdelta.position[0] * m_side->value; FIXME - dir = forward + right; - move[FORWARD] += dir[0]; - move[SIDE] -= dir[1]; - - VectorSet (0, camera_angles[1], 0, dir); - AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME - - VectorScale (forward, move[FORWARD], forward); - VectorScale (right, move[SIDE], right); - VectorAdd (forward, right, dir); - - if (dir[1] || dir[0]) { - vs->player_angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (vs->player_angles[YAW] < 0) { - vs->player_angles[YAW] += 360; - } - } - - vs->player_angles[PITCH] = 0; - - // remember the new angle to calculate the difference next frame - VectorCopy (vs->player_angles, player_angles); - - return; + if (!(in_klook.state & 1)) { + move[FORWARD] += cl_forwardspeed->value + * IN_ButtonState (&in_forward); + move[FORWARD] -= cl_backspeed->value * IN_ButtonState (&in_back); + } + if (in_speed.state & 1) { + move *= cl_movespeedkey->value; } - // regular camera, faces same direction as player + // mouse and joystick controllers add to movement + VectorSet (0, vs->player_angles[1] - cs->camera_angles[1], 0, dir); + AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME + //forward *= viewdelta.position[2] * m_forward->value; FIXME + //right *= viewdelta.position[0] * m_side->value; FIXME + dir = forward + right; + move[FORWARD] += dir[0]; + move[SIDE] -= dir[1]; + VectorSet (0, cs->camera_angles[1], 0, dir); + AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME + + dir = forward * move[FORWARD] + right * move[SIDE]; + + if (dir[1] || dir[0]) { + vs->player_angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); + if (vs->player_angles[YAW] < 0) { + vs->player_angles[YAW] += 360; + } + } + + vs->player_angles[PITCH] = 0; + + // remember the new angle to calculate the difference next frame + VectorCopy (vs->player_angles, cs->player_angles); +} + +static void +update_cam_frame (chasestate_t *cs, viewstate_t *vs) +{ + // control camera angles with key/mouse/joy-look + vec3_t d; + VectorSubtract (vs->player_angles, cs->player_angles, d); + VectorAdd (cs->camera_angles, d, cs->camera_angles); +} + +static void +chase_mode_1 (chasestate_t *cs) +{ + // regular camera, faces same direction as player + viewstate_t *vs = cs->viewstate; + vec4f_t forward = {}, up = {}, right = {}, stop = {}; //FIXME AngleVectors (vs->player_angles, &forward[0], &right[0], &up[0]); // calc exact destination - camera_origin = vs->player_origin + cs->camera_origin = vs->player_origin - forward * chase_back->value - right * chase_right->value; // chase_up is world up - camera_origin[2] += chase_up->value; + cs->camera_origin[2] += chase_up->value; // check for walls between player and camera - stop = TraceLine (cs, vs->player_origin, camera_origin); + stop = TraceLine (cs, vs->player_origin, cs->camera_origin); if (magnitude3f (stop)[0] != 0) { - camera_origin = stop + forward * 8; + cs->camera_origin = stop + forward * 8; } - Transform_SetWorldPosition (vs->camera_transform, camera_origin); + Transform_SetWorldPosition (vs->camera_transform, cs->camera_origin); +} + +static void +chase_mode_2 (chasestate_t *cs) +{ + viewstate_t *vs = cs->viewstate; + vec4f_t forward = {}, up = {}, right = {}, dir = {}; + + // lazy camera, look toward player entity + + update_cam_frame (cs, vs); + + cs->camera_angles[PITCH] = bound (-60, cs->camera_angles[PITCH], 60); + + // move camera, it's not enough to just change the angles because + // the angles are automatically changed to look toward the player + AngleVectors (cs->camera_angles, &forward[0], &right[0], &up[0]); + cs->camera_origin = cs->player_origin - chase_back->value * forward; + + cs->player_origin = vs->player_origin; + + // don't let camera get too low + if (cs->camera_origin[2] < cs->player_origin[2] + chase_up->value) { + cs->camera_origin[2] = cs->player_origin[2] + chase_up->value; + } + + limit_distance (cs); + check_for_walls (cs, forward); + + dir = cs->camera_origin - vs->player_origin; + forward = normalf (dir); + + if (dir[1] == 0 && dir[0] == 0) { + // look straight up or down + cs->camera_angles[YAW] = vs->player_angles[YAW]; + if (dir[2] > 0) + cs->camera_angles[PITCH] = 90; + else + cs->camera_angles[PITCH] = 270; + } else { + float pitch, yaw, fwd; + yaw = (atan2 (dir[1], dir[0]) * 180 / M_PI); + if (yaw < 0) + yaw += 360; + if (yaw < 180) + yaw += 180; + else + yaw -= 180; + cs->camera_angles[YAW] = yaw; + + fwd = sqrt (dir[0] * dir[0] + dir[1] * dir[1]); + pitch = (atan2 (dir[2], fwd) * 180 / M_PI); + if (pitch < 0) + pitch += 360; + cs->camera_angles[PITCH] = pitch; + } + set_camera (cs, vs); + cam_controls (cs, vs); +} + +static void +chase_mode_3 (chasestate_t *cs) +{ + viewstate_t *vs = cs->viewstate; + vec4f_t forward = {}, up = {}, right = {}; + + // lazy camera, look toward player entity + update_cam_frame (cs, vs); + + // move camera, it's not enough to just change the angles because + // the angles are automatically changed to look toward the player + + cs->player_origin = vs->player_origin; + AngleVectors (cs->camera_angles, &forward[0], &right[0], &up[0]); + cs->camera_origin = cs->player_origin - chase_back->value * forward; + limit_distance (cs); + check_for_walls (cs, forward); + set_camera (cs, vs); + cam_controls (cs, vs); +} + +void +Chase_Update (chasestate_t *cs) +{ + switch (chase_active->int_val) { + case 1: + chase_mode_1 (cs); + return; + case 2: + chase_mode_2 (cs); + return; + case 3: + chase_mode_3 (cs); + return; + } } From 1859ff233d6f05f175dc20d50186251d70a6174a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Mar 2022 14:44:53 +0900 Subject: [PATCH 2480/3664] [client] Fix the chase cameras They no longer spin like crazy. I don't know how, but I must have broken something over the years as I'm sure Seth had the code working (and I seem to remember seeing it working). In the process, clean up a lot of the angle mess. --- libs/client/cl_chase.c | 24 +++++------------------- libs/client/cl_view.c | 10 +++++----- nq/source/cl_main.c | 1 + 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/libs/client/cl_chase.c b/libs/client/cl_chase.c index e7e0eb079..f3a8131f7 100644 --- a/libs/client/cl_chase.c +++ b/libs/client/cl_chase.c @@ -160,24 +160,19 @@ cam_controls (chasestate_t *cs, viewstate_t *vs) if (dir[1] || dir[0]) { vs->player_angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (vs->player_angles[YAW] < 0) { - vs->player_angles[YAW] += 360; - } } vs->player_angles[PITCH] = 0; - - // remember the new angle to calculate the difference next frame - VectorCopy (vs->player_angles, cs->player_angles); } static void update_cam_frame (chasestate_t *cs, viewstate_t *vs) { - // control camera angles with key/mouse/joy-look vec3_t d; VectorSubtract (vs->player_angles, cs->player_angles, d); VectorAdd (cs->camera_angles, d, cs->camera_angles); + // remember the new angle to calculate the difference next frame + VectorCopy (vs->player_angles, cs->player_angles); } static void @@ -231,8 +226,7 @@ chase_mode_2 (chasestate_t *cs) limit_distance (cs); check_for_walls (cs, forward); - dir = cs->camera_origin - vs->player_origin; - forward = normalf (dir); + dir = vs->player_origin - cs->camera_origin; if (dir[1] == 0 && dir[0] == 0) { // look straight up or down @@ -240,22 +234,14 @@ chase_mode_2 (chasestate_t *cs) if (dir[2] > 0) cs->camera_angles[PITCH] = 90; else - cs->camera_angles[PITCH] = 270; + cs->camera_angles[PITCH] = -90; } else { float pitch, yaw, fwd; yaw = (atan2 (dir[1], dir[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - if (yaw < 180) - yaw += 180; - else - yaw -= 180; cs->camera_angles[YAW] = yaw; fwd = sqrt (dir[0] * dir[0] + dir[1] * dir[1]); - pitch = (atan2 (dir[2], fwd) * 180 / M_PI); - if (pitch < 0) - pitch += 360; + pitch = -(atan2 (dir[2], fwd) * 180 / M_PI); cs->camera_angles[PITCH] = pitch; } set_camera (cs, vs); diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index 2bf0c7921..f6371e69e 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -693,10 +693,6 @@ V_CalcRefdef (viewstate_t *vs) vec3_t ang = {-viewangles[0], viewangles[1], viewangles[2]}; CL_TransformEntity (view, 1, ang, gun_origin); } - - if (vs->chase && chase_active->int_val) { - Chase_Update (vs->chasestate); - } } static void @@ -745,7 +741,11 @@ V_RenderView (viewstate_t *vs) if (vs->intermission) { // intermission / finale rendering V_CalcIntermissionRefdef (vs); } else { - V_CalcRefdef (vs); + if (vs->chase && chase_active->int_val) { + Chase_Update (vs->chasestate); + } else { + V_CalcRefdef (vs); + } } } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 83748c3c4..2618706f9 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -202,6 +202,7 @@ CL_ClearState (void) __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); cl.viewstate.camera_transform = cam; + cl.viewstate.player_origin = (vec4f_t) {0, 0, 0, 1}; cl.viewstate.chase = 1; cl.viewstate.chasestate = &cl.chasestate; cl.chasestate.viewstate = &cl.viewstate; From 7c071185417cea5212393dca5959878f58f48e61 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Mar 2022 14:52:45 +0900 Subject: [PATCH 2481/3664] [mathlib] Clean up AngleVectors comment I finally spent the time to work out what it was trying to say. Still not sure it's clear, but what is clear is that there was probably some disagreement at Id about the orientation of the world. --- libs/util/mathlib.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index f4bf46dba..eca73126a 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -504,15 +504,13 @@ BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, plane_t *p) #endif /* - FIXME these comments are a confused mess (the code is fine) - angles is a left(?) handed system: 'pitch yaw roll' with x (pitch) axis to the right, y (yaw) axis up and z (roll) axis forward. - the math in AngleVectors has the entity frame as left handed with x + The math in AngleVectors has the entity frame as left handed with x (forward) axis forward, y (right) axis to the right and z (up) up. However, - the world is a right handed system with x to the right, y forward and - z up. + the world is a right handed system with x forward, y to the left and + z up, thus the negation for right. pitch = cp 0 -sp From 8407e3acd1a5703dd98f998219e972c51db5e67b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Mar 2022 15:13:55 +0900 Subject: [PATCH 2482/3664] [client] Make input axes accessible and add camera axes And clean up the names (viewdelta_position_forward -> in_move_forward). --- include/client/input.h | 7 ++++++ libs/client/cl_chase.c | 4 +-- libs/client/cl_input.c | 56 +++++++++++++++++++++++++++--------------- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/include/client/input.h b/include/client/input.h index ace69afa3..e66d02140 100644 --- a/include/client/input.h +++ b/include/client/input.h @@ -45,6 +45,10 @@ extern struct cvar_s *cl_pitchspeed; extern struct cvar_s *cl_anglespeedkey; +extern struct cvar_s *m_pitch; +extern struct cvar_s *m_yaw; +extern struct cvar_s *m_forward; +extern struct cvar_s *m_side; #define FORWARD 0 #define SIDE 1 @@ -66,6 +70,9 @@ void CL_Input_Init (struct cbuf_s *cbuf); void CL_Input_Init_Cvars (void); void CL_Input_Activate (int in_game); +extern in_axis_t in_move_forward, in_move_side, in_move_up; +extern in_axis_t in_move_pitch, in_move_yaw, in_move_roll; +extern in_axis_t in_cam_forward, in_cam_side, in_cam_up; extern in_button_t in_left, in_right, in_forward, in_back; extern in_button_t in_lookup, in_lookdown, in_moveleft, in_moveright; extern in_button_t in_use, in_jump, in_attack; diff --git a/libs/client/cl_chase.c b/libs/client/cl_chase.c index f3a8131f7..67d3f5749 100644 --- a/libs/client/cl_chase.c +++ b/libs/client/cl_chase.c @@ -147,8 +147,8 @@ cam_controls (chasestate_t *cs, viewstate_t *vs) // mouse and joystick controllers add to movement VectorSet (0, vs->player_angles[1] - cs->camera_angles[1], 0, dir); AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME - //forward *= viewdelta.position[2] * m_forward->value; FIXME - //right *= viewdelta.position[0] * m_side->value; FIXME + forward *= IN_UpdateAxis (&in_cam_forward) * m_forward->value; + right *= IN_UpdateAxis (&in_cam_side) * m_side->value; dir = forward + right; move[FORWARD] += dir[0]; move[SIDE] -= dir[1]; diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 02c3a8255..739176db4 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -1,7 +1,7 @@ /* - cl_legacy.c + cl_input.c - Client legacy commands + Client input commands Copyright (C) 2021 Bill Currie @@ -60,33 +60,49 @@ static int cl_event_id; static struct LISTENER_SET_TYPE(int) cl_on_focus_change = LISTENER_SET_STATIC_INIT(4); -in_axis_t viewdelta_position_forward = { +in_axis_t in_move_forward = { .mode = ina_set, .name = "move.forward", .description = "Move forward (negative) or backward (positive)", }; -in_axis_t viewdelta_position_side = { +in_axis_t in_move_side = { .mode = ina_set, .name = "move.side", .description = "Move right (positive) or left (negative)", }; -in_axis_t viewdelta_position_up = { +in_axis_t in_move_up = { .mode = ina_set, .name = "move.up", .description = "Move up (positive) or down (negative)", }; -in_axis_t viewdelta_angles_pitch = { +in_axis_t in_cam_forward = { + .mode = ina_set, + .name = "cam.forward", + .description = "Move camera forward (negative) or backward (positive)", +}; +in_axis_t in_cam_side = { + .mode = ina_set, + .name = "cam.side", + .description = "Move camera right (positive) or left (negative)", +}; +in_axis_t in_cam_up = { + .mode = ina_set, + .name = "cam.up", + .description = "Move camera up (positive) or down (negative)", +}; + +in_axis_t in_move_pitch = { .mode = ina_set, .name = "move.pitch", .description = "Pitch axis", }; -in_axis_t viewdelta_angles_yaw = { +in_axis_t in_move_yaw = { .mode = ina_set, .name = "move.yaw", .description = "Yaw axis", }; -in_axis_t viewdelta_angles_roll = { +in_axis_t in_move_roll = { .mode = ina_set, .name = "move.roll", .description = "Roll axis", @@ -167,12 +183,12 @@ in_button_t in_mlook = { }; static in_axis_t *cl_in_axes[] = { - &viewdelta_position_forward, - &viewdelta_position_side, - &viewdelta_position_up, - &viewdelta_angles_pitch, - &viewdelta_angles_yaw, - &viewdelta_angles_roll, + &in_move_forward, + &in_move_side, + &in_move_up, + &in_move_pitch, + &in_move_yaw, + &in_move_roll, 0, }; @@ -246,9 +262,9 @@ CL_AdjustAngles (float frametime, movestate_t *ms, viewstate_t *vs) delta[PITCH] -= pitchspeed * up; delta[PITCH] += pitchspeed * down; - delta[PITCH] -= IN_UpdateAxis (&viewdelta_angles_pitch) * m_pitch->value; - delta[YAW] -= IN_UpdateAxis (&viewdelta_angles_yaw) * m_yaw->value; - delta[ROLL] -= IN_UpdateAxis (&viewdelta_angles_roll) * m_pitch->value; + delta[PITCH] -= IN_UpdateAxis (&in_move_pitch) * m_pitch->value; + delta[YAW] -= IN_UpdateAxis (&in_move_yaw) * m_yaw->value; + delta[ROLL] -= IN_UpdateAxis (&in_move_roll) * m_pitch->value; ms->angles += delta; @@ -371,9 +387,9 @@ CL_Input_BuildMove (float frametime, movestate_t *state, viewstate_t *vs) move *= cl_movespeedkey->value; } - move[FORWARD] -= IN_UpdateAxis (&viewdelta_position_forward) * m_forward->value; - move[SIDE] += IN_UpdateAxis (&viewdelta_position_side) * m_side->value; - move[UP] -= IN_UpdateAxis (&viewdelta_position_up); + move[FORWARD] -= IN_UpdateAxis (&in_move_forward) * m_forward->value; + move[SIDE] += IN_UpdateAxis (&in_move_side) * m_side->value; + move[UP] -= IN_UpdateAxis (&in_move_up); if (freelook) V_StopPitchDrift (vs); From ee3c9fa59fb0899fc0d1daa2e252abcf9f39fa17 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Mar 2022 15:31:00 +0900 Subject: [PATCH 2483/3664] [client] Sort out the chase mode input FIXME It's messing with player motion (so not working properly), but at least now it compiles, I can get it working. --- libs/client/cl_input.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 739176db4..00eebfc75 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -50,6 +50,7 @@ #include "old_keys.h" +#include "client/chase.h" #include "client/input.h" #include "client/view.h" @@ -394,22 +395,22 @@ CL_Input_BuildMove (float frametime, movestate_t *state, viewstate_t *vs) if (freelook) V_StopPitchDrift (vs); - //if (cl.chase - // && (chase_active->int_val == 2 || chase_active->int_val == 3)) { - // /* adjust for chase camera angles - // * makes the player move relative to the chase camera frame rather - // * than the player's frame - // */ - // vec3_t forward, right, up, f, r; - // vec3_t dir = {0, 0, 0}; - // // need separate camera and player angles - // //FIXME dir[1] = r_data->refdef->viewangles[1] - cl.viewstate.angles[1]; - // AngleVectors (dir, forward, right, up); - // VectorScale (forward, move[FORWARD], f); - // VectorScale (right, move[SIDE], r); - // move[FORWARD] = f[0] + r[0]; - // move[SIDE] = f[1] + r[1]; - //} + if (vs->chase + && (chase_active->int_val == 2 || chase_active->int_val == 3)) { + /* adjust for chase camera angles + * makes the player move relative to the chase camera frame rather + * than the player's frame + */ + chasestate_t *cs = vs->chasestate; + vec3_t forward, right, up, f, r; + vec3_t dir = {0, 0, 0}; + dir[1] = cs->camera_angles[1] - vs->player_angles[1]; + AngleVectors (dir, forward, right, up); + VectorScale (forward, move[FORWARD], f); + VectorScale (right, move[SIDE], r); + move[FORWARD] = f[0] + r[0]; + move[SIDE] = f[1] + r[1]; + } state->move = move; } From 54c3b4cc536480d0be5e57b8e7b75f7e30086d69 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Mar 2022 16:07:04 +0900 Subject: [PATCH 2484/3664] [client] Get the chase camera working with input It turns out cam_controls is for pointing the player model in the direction of movement rather than controlling the camera (I should add proper camera controls). --- libs/client/cl_chase.c | 6 +++++- libs/client/cl_input.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/client/cl_chase.c b/libs/client/cl_chase.c index 67d3f5749..9f1a08b6e 100644 --- a/libs/client/cl_chase.c +++ b/libs/client/cl_chase.c @@ -121,6 +121,9 @@ set_camera (chasestate_t *cs, viewstate_t *vs) static void cam_controls (chasestate_t *cs, viewstate_t *vs) { + // FIXME this doesn't actually control the camera, but rather makes the + // player face the direction of motion. It probably should not access + // movement input buttons and axes directly. // get basic movement from keyboard vec4f_t move = { }; vec4f_t forward = { }; @@ -162,7 +165,8 @@ cam_controls (chasestate_t *cs, viewstate_t *vs) vs->player_angles[YAW] = (atan2 (dir[1], dir[0]) * 180 / M_PI); } - vs->player_angles[PITCH] = 0; + //vs->player_angles[PITCH] = 0; + VectorCopy (vs->player_angles, cs->player_angles); } static void diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 00eebfc75..3ca4b306a 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -409,7 +409,7 @@ CL_Input_BuildMove (float frametime, movestate_t *state, viewstate_t *vs) VectorScale (forward, move[FORWARD], f); VectorScale (right, move[SIDE], r); move[FORWARD] = f[0] + r[0]; - move[SIDE] = f[1] + r[1]; + move[SIDE] = -f[1] - r[1]; } state->move = move; } From b210f0183736b970d16b4d9c384febd31db970de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Mar 2022 10:43:52 +0900 Subject: [PATCH 2485/3664] [scene] Manage scene roots in transform Since transforms now know the scene to which they belong, and they know when they are root and when not, getting the transform code to manage the scene roots is the best way to keep the list of root transforms consistent. --- include/scn_internal.h | 3 +++ libs/scene/scene.c | 14 ++++++++++---- libs/scene/transform.c | 4 ++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/scn_internal.h b/include/scn_internal.h index 14faaa3ed..907e0c0d6 100644 --- a/include/scn_internal.h +++ b/include/scn_internal.h @@ -11,4 +11,7 @@ typedef struct scene_resources_s { PR_RESMAP (transform_t) transforms; } scene_resources_t; +void scene_add_root (scene_t *scene, transform_t *transform); +void scene_del_root (scene_t *scene, transform_t *transform); + #endif//__scn_internal_h diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 933be0db5..99d856b0e 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -88,7 +88,6 @@ Scene_CreateEntity (scene_t *scene) hierarchy_t *h = ent->transform->hierarchy; h->entity.a[ent->transform->index] = ent; - DARRAY_APPEND (&scene->roots, ent->transform); return ent; } @@ -99,8 +98,16 @@ Scene_GetEntity (scene_t *scene, int id) return PR_RESGET (res->entities, id); } -static void -unroot_transform (scene_t *scene, transform_t *transform) +void +scene_add_root (scene_t *scene, transform_t *transform) +{ + if (!Transform_GetParent (transform)) { + DARRAY_APPEND (&scene->roots, transform); + } +} + +void +scene_del_root (scene_t *scene, transform_t *transform) { if (!Transform_GetParent (transform)) { for (size_t i = 0; i < scene->roots.size; i++) { @@ -138,7 +145,6 @@ Scene_DestroyEntity (scene_t *scene, entity_t *ent) if (PR_RESGET (res->entities, ent->id) != ent) { Sys_Error ("Scene_DestroyEntity: entity not owned by scene"); } - unroot_transform (scene, ent->transform); // pull the transform out of the hierarchy to make it easier to destory // all the child entities Transform_SetParent (ent->transform, 0); diff --git a/libs/scene/transform.c b/libs/scene/transform.c index 70c0f19b6..78ff85a6b 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -58,6 +58,7 @@ Transform_New (scene_t *scene, transform_t *parent) } else { transform->hierarchy = Hierarchy_New (16, 1);//FIXME should be config transform->index = 0; + scene_add_root (scene, transform); } transform->hierarchy->transform.a[transform->index] = transform; Hierarchy_UpdateMatrices (transform->hierarchy); @@ -72,6 +73,7 @@ Transform_Delete (transform_t *transform) // hierarchy so deleting it is easier Transform_SetParent (transform, 0); } + scene_del_root (transform->scene, transform); Hierarchy_Delete (transform->hierarchy); } @@ -87,6 +89,7 @@ void Transform_SetParent (transform_t *transform, transform_t *parent) { if (parent) { + scene_del_root (transform->scene, transform); hierarchy_t *hierarchy = transform->hierarchy; uint32_t index = transform->index; Hierarchy_InsertHierarchy (parent->hierarchy, hierarchy, @@ -108,6 +111,7 @@ Transform_SetParent (transform_t *transform, transform_t *parent) Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, null_transform, index); Hierarchy_RemoveHierarchy (hierarchy, index); + scene_add_root (transform->scene, transform); } } From ab91d73635d3f3ee5d0da9196d31110c761b544f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Mar 2022 10:46:29 +0900 Subject: [PATCH 2486/3664] [scene] Use scene resources for the main hierarchy block This will reduce the memory churn when creating hierarchies as transforms switch between being root and child. --- include/QF/scene/hierarchy.h | 3 ++- include/scn_internal.h | 2 ++ libs/scene/hierarchy.c | 21 +++++++++------------ libs/scene/transform.c | 5 +++-- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/include/QF/scene/hierarchy.h b/include/QF/scene/hierarchy.h index 24c46df0a..6800887fa 100644 --- a/include/QF/scene/hierarchy.h +++ b/include/QF/scene/hierarchy.h @@ -61,9 +61,10 @@ typedef struct hierarchy_s { vec4fset_t localScale; vec4fset_t worldRotation; vec4fset_t worldScale; + struct scene_s *scene; } hierarchy_t; -hierarchy_t *Hierarchy_New (size_t grow, int createRoot); +hierarchy_t *Hierarchy_New (struct scene_s *scene, int createRoot); hierarchy_t *Hierarchy_Copy (hierarchy_t *src); void Hierarchy_Delete (hierarchy_t *hierarchy); diff --git a/include/scn_internal.h b/include/scn_internal.h index 907e0c0d6..1ef11163f 100644 --- a/include/scn_internal.h +++ b/include/scn_internal.h @@ -3,11 +3,13 @@ #include "QF/progs.h" #include "QF/scene/entity.h" +#include "QF/scene/hierarchy.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" typedef struct scene_resources_s { PR_RESMAP (entity_t) entities; + PR_RESMAP (hierarchy_t) hierarchies; PR_RESMAP (transform_t) transforms; } scene_resources_t; diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 2e7ccaf47..5218e39f9 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -397,13 +397,13 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) } hierarchy_t * -Hierarchy_New (size_t grow, int createRoot) +Hierarchy_New (scene_t *scene, int createRoot) { - if (!grow) { - grow = 16; - } - hierarchy_t *hierarchy = malloc (sizeof (hierarchy_t)); + scene_resources_t *res = scene->resources; + hierarchy_t *hierarchy = PR_RESNEW_NC (res->hierarchies); + hierarchy->scene = scene; + size_t grow = 16; DARRAY_INIT (&hierarchy->transform, grow); DARRAY_INIT (&hierarchy->entity, grow); DARRAY_INIT (&hierarchy->childCount, grow); @@ -432,12 +432,9 @@ Hierarchy_New (size_t grow, int createRoot) void Hierarchy_Delete (hierarchy_t *hierarchy) { - if (hierarchy->transform.size) { - scene_resources_t *res = hierarchy->transform.a[0]->scene->resources; - - for (size_t i = 0; i < hierarchy->transform.size; i++) { - PR_RESFREE (res->transforms, hierarchy->transform.a[i]); - } + scene_resources_t *res = hierarchy->scene->resources; + for (size_t i = 0; i < hierarchy->transform.size; i++) { + PR_RESFREE (res->transforms, hierarchy->transform.a[i]); } DARRAY_CLEAR (&hierarchy->transform); DARRAY_CLEAR (&hierarchy->entity); @@ -455,5 +452,5 @@ Hierarchy_Delete (hierarchy_t *hierarchy) DARRAY_CLEAR (&hierarchy->localScale); DARRAY_CLEAR (&hierarchy->worldRotation); DARRAY_CLEAR (&hierarchy->worldScale); - free (hierarchy); + PR_RESFREE (res->hierarchies, hierarchy); } diff --git a/libs/scene/transform.c b/libs/scene/transform.c index 78ff85a6b..dd7facbe1 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -56,7 +56,7 @@ Transform_New (scene_t *scene, transform_t *parent) transform->index = Hierarchy_InsertHierarchy (parent->hierarchy, 0, parent->index, 0); } else { - transform->hierarchy = Hierarchy_New (16, 1);//FIXME should be config + transform->hierarchy = Hierarchy_New (scene, 1); transform->index = 0; scene_add_root (scene, transform); } @@ -74,6 +74,7 @@ Transform_Delete (transform_t *transform) Transform_SetParent (transform, 0); } scene_del_root (transform->scene, transform); + // Takes care of freeing the transforms Hierarchy_Delete (transform->hierarchy); } @@ -107,7 +108,7 @@ Transform_SetParent (transform_t *transform, transform_t *parent) hierarchy_t *hierarchy = transform->hierarchy; uint32_t index = transform->index; - hierarchy_t *new_hierarchy = Hierarchy_New (16, 0); + hierarchy_t *new_hierarchy = Hierarchy_New (transform->scene, 0); Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, null_transform, index); Hierarchy_RemoveHierarchy (hierarchy, index); From ae6970a005b1fd2ca81d532eb4122163ce97808e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Mar 2022 15:00:32 +0900 Subject: [PATCH 2487/3664] [renderer] Split entity queue into per-model-type While I doubt the difference is all that significant, this should speed up entity rendering because it cuts out a lot of branching, and eliminates scanning the same list multiple times only to not do anything for large chunks of the list. --- include/QF/model.h | 9 +- include/r_local.h | 2 +- libs/video/renderer/gl/gl_lightmap.c | 5 +- libs/video/renderer/gl/gl_rmain.c | 12 +- libs/video/renderer/gl/gl_rsurf.c | 5 +- libs/video/renderer/glsl/glsl_bsp.c | 4 +- libs/video/renderer/glsl/glsl_main.c | 4 +- libs/video/renderer/r_efrag.c | 2 - libs/video/renderer/r_ent.c | 24 +- libs/video/renderer/sw/sw_rmain.c | 287 ++++++++++++----------- libs/video/renderer/sw32/sw32_rmain.c | 287 ++++++++++++----------- libs/video/renderer/vulkan/vulkan_bsp.c | 4 +- libs/video/renderer/vulkan/vulkan_main.c | 4 +- 13 files changed, 334 insertions(+), 315 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 9f308e997..875aeec3b 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -373,7 +373,14 @@ typedef struct { // Whole model ================================================================ -typedef enum {mod_brush, mod_sprite, mod_alias, mod_iqm} modtype_t; +typedef enum { + mod_brush, + mod_sprite, + mod_alias, + mod_iqm, + + mod_num_types +} modtype_t; #define EF_ROCKET 1 // leave a trail #define EF_GRENADE 2 // leave a trail diff --git a/include/r_local.h b/include/r_local.h index c45ca74c6..4e4e00bfd 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -292,7 +292,7 @@ extern mleaf_t *r_viewleaf; extern int r_clipflags; extern int r_dlightframecount; -extern struct entity_s *r_ent_queue; +extern struct entity_s *r_ent_queue[mod_num_types]; struct dlight_s; extern vec3_t lightspot; diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 0c128069c..c7ec6d042 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -598,11 +598,8 @@ gl_overbright_f (cvar_t *var) if (!gl_R_BuildLightMap) return; - for (ent = r_ent_queue; ent; ent = ent->next) { + for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { m = ent->renderer.model; - - if (m->type != mod_brush) - continue; if (m->path[0] == '*') continue; diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index cd5e406a1..1a32c9c7c 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -220,9 +220,7 @@ R_DrawEntitiesOnList (void) qfglEnable (GL_NORMALIZE); } - for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->renderer.model->type != mod_alias) - continue; + for (ent = r_ent_queue[mod_alias]; ent; ent = ent->next) { gl_R_DrawAliasModel (ent); } qfglColor3ubv (color_white); @@ -250,9 +248,7 @@ R_DrawEntitiesOnList (void) qglActiveTexture (gl_mtex_enum + 0); } - for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->renderer.model->type != mod_iqm) - continue; + for (ent = r_ent_queue[mod_iqm]; ent; ent = ent->next) { gl_R_DrawIQMModel (ent); } qfglColor3ubv (color_white); @@ -261,9 +257,7 @@ R_DrawEntitiesOnList (void) qfglEnable (GL_ALPHA_TEST); if (gl_va_capable) qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray); - for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->renderer.model->type != mod_sprite) - continue; + for (ent = r_ent_queue[mod_sprite]; ent; ent = ent->next) { R_DrawSpriteModel (ent); } qfglDisable (GL_ALPHA_TEST); diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index c27788a5c..77a4e0349 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -741,10 +741,7 @@ gl_R_DrawWorld (void) R_VisitWorldNodes (&bctx); if (r_drawentities->int_val) { entity_t *ent; - for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->renderer.model->type != mod_brush) { - continue; - } + for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { gl_R_DrawBrushModel (ent); } } diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index bdaede468..2ee30363a 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -1150,9 +1150,7 @@ glsl_R_DrawWorld (void) R_VisitWorldNodes (&bctx); if (r_drawentities->int_val) { entity_t *ent; - for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->renderer.model->type != mod_brush) - continue; + for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { R_DrawBrushModel (ent); } } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index a4d22326b..4e599561d 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -149,9 +149,7 @@ R_RenderEntities (void) #define RE_LOOP(type_name, Type) \ do { \ begun = 0; \ - for (ent = r_ent_queue; ent; ent = ent->next) { \ - if (ent->renderer.model->type != mod_##type_name) \ - continue; \ + for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ if (!begun) { \ glsl_R_##Type##Begin (); \ begun = 1; \ diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 4ee676d86..3766f681d 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -244,8 +244,6 @@ R_StoreEfrags (const efrag_t *efrag) break; default: - Sys_Error ("R_StoreEfrags: Bad entity type %d", - model->type); } } } diff --git a/libs/video/renderer/r_ent.c b/libs/video/renderer/r_ent.c index 303053800..9dcba8401 100644 --- a/libs/video/renderer/r_ent.c +++ b/libs/video/renderer/r_ent.c @@ -55,8 +55,13 @@ typedef struct entity_pool_s { entity_t entities[ENT_POOL_SIZE]; } entity_pool_t; -entity_t *r_ent_queue; -static entity_t **vis_tail = &r_ent_queue; +entity_t *r_ent_queue[mod_num_types]; +static entity_t **vis_tail[mod_num_types] = { + [mod_brush] &r_ent_queue[mod_brush], + [mod_sprite] &r_ent_queue[mod_sprite], + [mod_alias] &r_ent_queue[mod_alias], + [mod_iqm] &r_ent_queue[mod_iqm], +}; static entity_pool_t *entity_pools = 0; static entity_pool_t **entpool_tail = &entity_pools; @@ -119,16 +124,23 @@ R_FreeAllEntities (void) void R_ClearEnts (void) { - r_ent_queue = 0; - vis_tail = &r_ent_queue; + for (int i = 0; i < mod_num_types; i++) { + r_ent_queue[i] = 0; + vis_tail[i] = &r_ent_queue[i]; + } } void R_EnqueueEntity (entity_t *ent) { + modtype_t type = ent->renderer.model->type; + + if (type < 0 || type >= mod_num_types) { + Sys_Error ("R_EnqueueEntity: Bad entity model type %d", type); + } ent->next = 0; - *vis_tail = ent; - vis_tail = &ent->next; + *vis_tail[type] = ent; + vis_tail[type] = &ent->next; } float diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index d99259e4b..d28b60b27 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -340,84 +340,102 @@ R_ViewChanged (void) D_ViewChanged (); } +static inline void +draw_sprite_entity (entity_t *ent) +{ + VectorSubtract (r_origin, r_entorigin, modelorg); + R_DrawSprite (); +} + +static inline void +setup_lighting (alight_t *lighting) +{ + float minlight = 0; + int j; + // FIXME: remove and do real lighting + vec3_t dist; + float add; + float lightvec[3] = { -1, 0, 0 }; + + minlight = max (currententity->renderer.model->min_light, + currententity->renderer.min_light); + + // 128 instead of 255 due to clamping below + j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin), + minlight * 128); + + lighting->ambientlight = j; + lighting->shadelight = j; + + lighting->plightvec = lightvec; + + for (unsigned lnum = 0; lnum < r_maxdlights; lnum++) { + if (r_dlights[lnum].die >= vr_data.realtime) { + VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist); + add = r_dlights[lnum].radius - VectorLength (dist); + + if (add > 0) + lighting->ambientlight += add; + } + } + + // clamp lighting so it doesn't overbright as much + if (lighting->ambientlight > 128) + lighting->ambientlight = 128; + if (lighting->ambientlight + lighting->shadelight > 192) + lighting->shadelight = 192 - lighting->ambientlight; +} + +static inline void +draw_alias_entity (entity_t *ent) +{ + VectorSubtract (r_origin, r_entorigin, modelorg); + + // see if the bounding box lets us trivially reject, also + // sets trivial accept status + currententity->visibility.trivial_accept = 0; //FIXME + if (R_AliasCheckBBox ()) { + alight_t lighting; + setup_lighting (&lighting); + R_AliasDrawModel (&lighting); + } +} + +static inline void +draw_iqm_entity (entity_t *ent) +{ + VectorSubtract (r_origin, r_entorigin, modelorg); + + // see if the bounding box lets us trivially reject, also + // sets trivial accept status + currententity->visibility.trivial_accept = 0; //FIXME + + alight_t lighting; + setup_lighting (&lighting); + R_IQMDrawModel (&lighting); +} + static void R_DrawEntitiesOnList (void) { - int j; - unsigned int lnum; - alight_t lighting; entity_t *ent; - // FIXME: remove and do real lighting - float lightvec[3] = { -1, 0, 0 }; - vec3_t dist; - float add; - float minlight = 0; - if (!r_drawentities->int_val) return; - for (ent = r_ent_queue; ent; ent = ent->next) { - currententity = ent; +#define RE_LOOP(type_name) \ + do { \ + for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ + VectorCopy (Transform_GetWorldPosition (ent->transform), \ + r_entorigin); \ + currententity = ent; \ + draw_##type_name##_entity (ent); \ + } \ + } while (0) - VectorCopy (Transform_GetWorldPosition (currententity->transform), - r_entorigin); - switch (currententity->renderer.model->type) { - case mod_sprite: - VectorSubtract (r_origin, r_entorigin, modelorg); - R_DrawSprite (); - break; - - case mod_alias: - case mod_iqm: - VectorSubtract (r_origin, r_entorigin, modelorg); - - minlight = max (currententity->renderer.model->min_light, - currententity->renderer.min_light); - - // see if the bounding box lets us trivially reject, also - // sets trivial accept status - currententity->visibility.trivial_accept = 0; //FIXME - if (currententity->renderer.model->type == mod_iqm//FIXME - || R_AliasCheckBBox ()) { - // 128 instead of 255 due to clamping below - j = max (R_LightPoint (&r_worldentity.renderer.model->brush, - r_entorigin), minlight * 128); - - lighting.ambientlight = j; - lighting.shadelight = j; - - lighting.plightvec = lightvec; - - for (lnum = 0; lnum < r_maxdlights; lnum++) { - if (r_dlights[lnum].die >= vr_data.realtime) { - VectorSubtract (r_entorigin, - r_dlights[lnum].origin, dist); - add = r_dlights[lnum].radius - VectorLength (dist); - - if (add > 0) - lighting.ambientlight += add; - } - } - - // clamp lighting so it doesn't overbright as much - if (lighting.ambientlight > 128) - lighting.ambientlight = 128; - if (lighting.ambientlight + lighting.shadelight > 192) - lighting.shadelight = 192 - lighting.ambientlight; - - if (currententity->renderer.model->type == mod_iqm) - R_IQMDrawModel (&lighting); - else - R_AliasDrawModel (&lighting); - } - - break; - - default: - break; - } - } + RE_LOOP (alias); + RE_LOOP (iqm); + RE_LOOP (sprite); } static void @@ -556,90 +574,83 @@ R_DrawBEntitiesOnList (void) VectorCopy (modelorg, oldorigin); insubmodel = true; - for (ent = r_ent_queue; ent; ent = ent->next) { + for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { currententity = ent; VectorCopy (Transform_GetWorldPosition (currententity->transform), origin); - switch (currententity->renderer.model->type) { - case mod_brush: - clmodel = currententity->renderer.model; + clmodel = currententity->renderer.model; - // see if the bounding box lets us trivially reject, also - // sets trivial accept status - for (j = 0; j < 3; j++) { - minmaxs[j] = origin[j] + clmodel->mins[j]; - minmaxs[3 + j] = origin[j] + clmodel->maxs[j]; - } + // see if the bounding box lets us trivially reject, also + // sets trivial accept status + for (j = 0; j < 3; j++) { + minmaxs[j] = origin[j] + clmodel->mins[j]; + minmaxs[3 + j] = origin[j] + clmodel->maxs[j]; + } - clipflags = R_BmodelCheckBBox (clmodel, minmaxs); + clipflags = R_BmodelCheckBBox (clmodel, minmaxs); - if (clipflags != BMODEL_FULLY_CLIPPED) { - mod_brush_t *brush = &clmodel->brush; - VectorCopy (origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); + if (clipflags != BMODEL_FULLY_CLIPPED) { + mod_brush_t *brush = &clmodel->brush; + VectorCopy (origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); - // FIXME: is this needed? - VectorCopy (modelorg, r_worldmodelorg); - r_pcurrentvertbase = brush->vertexes; + // FIXME: is this needed? + VectorCopy (modelorg, r_worldmodelorg); + r_pcurrentvertbase = brush->vertexes; - // FIXME: stop transforming twice - R_RotateBmodel (); + // FIXME: stop transforming twice + R_RotateBmodel (); - // calculate dynamic lighting for bmodel if it's not an - // instanced model - if (brush->firstmodelsurface != 0) { - vec3_t lightorigin; + // calculate dynamic lighting for bmodel if it's not an + // instanced model + if (brush->firstmodelsurface != 0) { + vec3_t lightorigin; - for (k = 0; k < r_maxdlights; k++) { - if ((r_dlights[k].die < vr_data.realtime) || - (!r_dlights[k].radius)) continue; - - VectorSubtract (r_dlights[k].origin, origin, - lightorigin); - R_RecursiveMarkLights (brush, lightorigin, - &r_dlights[k], k, - brush->nodes - + brush->hulls[0].firstclipnode); - } + for (k = 0; k < r_maxdlights; k++) { + if ((r_dlights[k].die < vr_data.realtime) || + (!r_dlights[k].radius)) { + continue; } - // if the driver wants polygons, deliver those. - // Z-buffering is on at this point, so no clipping to the - // world tree is needed, just frustum clipping - if (r_drawpolys | r_drawculledpolys) { - R_ZDrawSubmodelPolys (clmodel); + + VectorSubtract (r_dlights[k].origin, origin, lightorigin); + R_RecursiveMarkLights (brush, lightorigin, + &r_dlights[k], k, + brush->nodes + + brush->hulls[0].firstclipnode); + } + } + // if the driver wants polygons, deliver those. + // Z-buffering is on at this point, so no clipping to the + // world tree is needed, just frustum clipping + if (r_drawpolys | r_drawculledpolys) { + R_ZDrawSubmodelPolys (clmodel); + } else { + if (currententity->visibility.topnode) { + mnode_t *topnode = currententity->visibility.topnode; + + if (topnode->contents >= 0) { + // not a leaf; has to be clipped to the world + // BSP + r_clipflags = clipflags; + R_DrawSolidClippedSubmodelPolygons (clmodel); } else { - if (currententity->visibility.topnode) { - mnode_t *topnode - = currententity->visibility.topnode; - - if (topnode->contents >= 0) { - // not a leaf; has to be clipped to the world - // BSP - r_clipflags = clipflags; - R_DrawSolidClippedSubmodelPolygons (clmodel); - } else { - // falls entirely in one leaf, so we just put - // all the edges in the edge list and let 1/z - // sorting handle drawing order - R_DrawSubmodelPolygons (clmodel, clipflags); - } - - } + // falls entirely in one leaf, so we just put + // all the edges in the edge list and let 1/z + // sorting handle drawing order + R_DrawSubmodelPolygons (clmodel, clipflags); } - - // put back world rotation and frustum clipping - // FIXME: R_RotateBmodel should just work off base_vxx - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); - VectorCopy (oldorigin, modelorg); - R_TransformFrustum (); } - break; - default: - break; + } + + // put back world rotation and frustum clipping + // FIXME: R_RotateBmodel should just work off base_vxx + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + VectorCopy (oldorigin, modelorg); + R_TransformFrustum (); } } diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 2dc129df9..3c147862b 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -347,85 +347,102 @@ sw32_R_ViewChanged (void) sw32_D_ViewChanged (); } +static inline void +draw_sprite_entity (entity_t *ent) +{ + VectorSubtract (r_origin, r_entorigin, modelorg); + sw32_R_DrawSprite (); +} + +static inline void +setup_lighting (alight_t *lighting) +{ + float minlight = 0; + int j; + // FIXME: remove and do real lighting + vec3_t dist; + float add; + float lightvec[3] = { -1, 0, 0 }; + + minlight = max (currententity->renderer.model->min_light, + currententity->renderer.min_light); + + // 128 instead of 255 due to clamping below + j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin), + minlight * 128); + + lighting->ambientlight = j; + lighting->shadelight = j; + + lighting->plightvec = lightvec; + + for (unsigned lnum = 0; lnum < r_maxdlights; lnum++) { + if (r_dlights[lnum].die >= vr_data.realtime) { + VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist); + add = r_dlights[lnum].radius - VectorLength (dist); + + if (add > 0) + lighting->ambientlight += add; + } + } + + // clamp lighting so it doesn't overbright as much + if (lighting->ambientlight > 128) + lighting->ambientlight = 128; + if (lighting->ambientlight + lighting->shadelight > 192) + lighting->shadelight = 192 - lighting->ambientlight; +} + +static inline void +draw_alias_entity (entity_t *ent) +{ + VectorSubtract (r_origin, r_entorigin, modelorg); + + // see if the bounding box lets us trivially reject, also + // sets trivial accept status + currententity->visibility.trivial_accept = 0; //FIXME + if (R_AliasCheckBBox ()) { + alight_t lighting; + setup_lighting (&lighting); + sw32_R_AliasDrawModel (&lighting); + } +} + +static inline void +draw_iqm_entity (entity_t *ent) +{ + VectorSubtract (r_origin, r_entorigin, modelorg); + + // see if the bounding box lets us trivially reject, also + // sets trivial accept status + currententity->visibility.trivial_accept = 0; //FIXME + + alight_t lighting; + setup_lighting (&lighting); + sw32_R_IQMDrawModel (&lighting); +} + static void R_DrawEntitiesOnList (void) { - int j; - unsigned int lnum; - alight_t lighting; entity_t *ent; - // FIXME: remove and do real lighting - float lightvec[3] = { -1, 0, 0 }; - vec3_t dist; - float add; - float minlight; - if (!r_drawentities->int_val) return; - for (ent = r_ent_queue; ent; ent = ent->next) { - currententity = ent; +#define RE_LOOP(type_name) \ + do { \ + for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ + VectorCopy (Transform_GetWorldPosition (ent->transform), \ + r_entorigin); \ + currententity = ent; \ + draw_##type_name##_entity (ent); \ + } \ + } while (0) - VectorCopy (Transform_GetWorldPosition (currententity->transform), - r_entorigin); - switch (currententity->renderer.model->type) { - case mod_sprite: - VectorSubtract (r_origin, r_entorigin, modelorg); - sw32_R_DrawSprite (); - break; - - case mod_alias: - case mod_iqm: - VectorSubtract (r_origin, r_entorigin, modelorg); - - minlight = max (currententity->renderer.min_light, - currententity->renderer.model->min_light); - - // see if the bounding box lets us trivially reject, also - // sets trivial accept status - currententity->visibility.trivial_accept = 0; //FIXME - if (currententity->renderer.model->type == mod_iqm//FIXME - || sw32_R_AliasCheckBBox ()) { - // 128 instead of 255 due to clamping below - j = max (R_LightPoint (&r_worldentity.renderer.model->brush, - r_entorigin), - minlight * 128); - - lighting.ambientlight = j; - lighting.shadelight = j; - - lighting.plightvec = lightvec; - - for (lnum = 0; lnum < r_maxdlights; lnum++) { - if (r_dlights[lnum].die >= vr_data.realtime) { - VectorSubtract (r_entorigin, - r_dlights[lnum].origin, dist); - add = r_dlights[lnum].radius - VectorLength (dist); - - if (add > 0) - lighting.ambientlight += add; - } - } - - // clamp lighting so it doesn't overbright as much - if (lighting.ambientlight > 128) - lighting.ambientlight = 128; - if (lighting.ambientlight + lighting.shadelight > 192) - lighting.shadelight = 192 - lighting.ambientlight; - - if (currententity->renderer.model->type == mod_iqm) - sw32_R_IQMDrawModel (&lighting); - else - sw32_R_AliasDrawModel (&lighting); - } - - break; - - default: - break; - } - } + RE_LOOP (alias); + RE_LOOP (iqm); + RE_LOOP (sprite); } static void @@ -563,89 +580,83 @@ R_DrawBEntitiesOnList (void) VectorCopy (modelorg, oldorigin); insubmodel = true; - for (ent = r_ent_queue; ent; ent = ent->next) { + for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { currententity = ent; VectorCopy (Transform_GetWorldPosition (currententity->transform), origin); - switch (currententity->renderer.model->type) { - case mod_brush: - clmodel = currententity->renderer.model; + clmodel = currententity->renderer.model; - // see if the bounding box lets us trivially reject, also - // sets trivial accept status - for (j = 0; j < 3; j++) { - minmaxs[j] = origin[j] + clmodel->mins[j]; - minmaxs[3 + j] = origin[j] + clmodel->maxs[j]; - } + // see if the bounding box lets us trivially reject, also + // sets trivial accept status + for (j = 0; j < 3; j++) { + minmaxs[j] = origin[j] + clmodel->mins[j]; + minmaxs[3 + j] = origin[j] + clmodel->maxs[j]; + } - clipflags = R_BmodelCheckBBox (clmodel, minmaxs); + clipflags = R_BmodelCheckBBox (clmodel, minmaxs); - if (clipflags != BMODEL_FULLY_CLIPPED) { - mod_brush_t *brush = &clmodel->brush; - VectorCopy (origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); + if (clipflags != BMODEL_FULLY_CLIPPED) { + mod_brush_t *brush = &clmodel->brush; + VectorCopy (origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); - // FIXME: is this needed? - VectorCopy (modelorg, sw32_r_worldmodelorg); - r_pcurrentvertbase = brush->vertexes; + // FIXME: is this needed? + VectorCopy (modelorg, sw32_r_worldmodelorg); + r_pcurrentvertbase = brush->vertexes; - // FIXME: stop transforming twice - sw32_R_RotateBmodel (); + // FIXME: stop transforming twice + sw32_R_RotateBmodel (); - // calculate dynamic lighting for bmodel if it's not an - // instanced model - if (brush->firstmodelsurface != 0) { - vec3_t lightorigin; + // calculate dynamic lighting for bmodel if it's not an + // instanced model + if (brush->firstmodelsurface != 0) { + vec3_t lightorigin; - for (k = 0; k < r_maxdlights; k++) { - if ((r_dlights[k].die < vr_data.realtime) || - (!r_dlights[k].radius)) continue; - - VectorSubtract (r_dlights[k].origin, origin, - lightorigin); - R_RecursiveMarkLights (brush, lightorigin, - &r_dlights[k], k, - brush->nodes - + brush->hulls[0].firstclipnode); - } + for (k = 0; k < r_maxdlights; k++) { + if ((r_dlights[k].die < vr_data.realtime) || + (!r_dlights[k].radius)) { + continue; } - // if the driver wants polygons, deliver those. - // Z-buffering is on at this point, so no clipping to the - // world tree is needed, just frustum clipping - if (sw32_r_drawpolys | sw32_r_drawculledpolys) { - sw32_R_ZDrawSubmodelPolys (clmodel); + + VectorSubtract (r_dlights[k].origin, origin, lightorigin); + R_RecursiveMarkLights (brush, lightorigin, + &r_dlights[k], k, + brush->nodes + + brush->hulls[0].firstclipnode); + } + } + // if the driver wants polygons, deliver those. + // Z-buffering is on at this point, so no clipping to the + // world tree is needed, just frustum clipping + if (sw32_r_drawpolys | sw32_r_drawculledpolys) { + sw32_R_ZDrawSubmodelPolys (clmodel); + } else { + if (currententity->visibility.topnode) { + mnode_t *topnode = currententity->visibility.topnode; + + if (topnode->contents >= 0) { + // not a leaf; has to be clipped to the world + // BSP + sw32_r_clipflags = clipflags; + sw32_R_DrawSolidClippedSubmodelPolygons (clmodel); } else { - if (currententity->visibility.topnode) { - mnode_t *topnode - = currententity->visibility.topnode; - - if (topnode->contents >= 0) { - // not a leaf; has to be clipped to the world - // BSP - sw32_r_clipflags = clipflags; - sw32_R_DrawSolidClippedSubmodelPolygons (clmodel); - } else { - // falls entirely in one leaf, so we just put - // all the edges in the edge list and let 1/z - // sorting handle drawing order - sw32_R_DrawSubmodelPolygons (clmodel, clipflags); - } - } + // falls entirely in one leaf, so we just put + // all the edges in the edge list and let 1/z + // sorting handle drawing order + sw32_R_DrawSubmodelPolygons (clmodel, clipflags); } - - // put back world rotation and frustum clipping - // FIXME: sw32_R_RotateBmodel should just work off base_vxx - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); - VectorCopy (oldorigin, modelorg); - sw32_R_TransformFrustum (); } - break; - default: - break; + } + + // put back world rotation and frustum clipping + // FIXME: sw32_R_RotateBmodel should just work off base_vxx + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + VectorCopy (oldorigin, modelorg); + sw32_R_TransformFrustum (); } } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 962735f99..c4ad3dc3e 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1040,9 +1040,7 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) R_VisitWorldNodes (brush, ctx); if (r_drawentities->int_val) { entity_t *ent; - for (ent = r_ent_queue; ent; ent = ent->next) { - if (ent->renderer.model->type != mod_brush) - continue; + for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { R_DrawBrushModel (ent, ctx); } } diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 06a99a046..4eb55f08c 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -87,9 +87,7 @@ Vulkan_RenderEntities (qfv_renderframe_t *rFrame) do { \ entity_t *ent; \ int begun = 0; \ - for (ent = r_ent_queue; ent; ent = ent->next) { \ - if (ent->renderer.model->type != mod_##type_name) \ - continue; \ + for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ if (!begun) { \ Vulkan_##Type##Begin (rFrame); \ begun = 1; \ From f296cb897e2fdede546d5eb7062bb60c9a2f0fd6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Mar 2022 16:29:40 +0900 Subject: [PATCH 2488/3664] [renderer] Make draw order a little more consistent GL and GLSL were drawing the view model after particles instead of before. For GL, this is likely due to avoiding fog affecting the view model (which I think is not the right thing to do), and GLSL due to copying GL (because I had no idea at the time). This makes the two renderers consistent with the software renderers, and might even speed things up a little as that's one less set of blends to do when the particles are covered by the view model (I don't expect much difference). --- libs/video/renderer/gl/gl_rmain.c | 5 ++--- libs/video/renderer/glsl/glsl_main.c | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 1a32c9c7c..1c9fa7f00 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -448,20 +448,19 @@ R_RenderScene (void) gl_R_SetupFrame (); R_SetupGL (); gl_Fog_EnableGFog (); + R_MarkLeaves (); // done here so we know if we're in water R_PushDlights (vec3_origin); gl_R_DrawWorld (); // adds static entities to the list S_ExtraUpdate (); // don't let sound get messed up if going slow R_DrawEntitiesOnList (); gl_R_RenderDlights (); - gl_R_DrawWaterSurfaces (); + R_DrawViewModel (); gl_R_DrawParticles (); gl_Fog_DisableGFog (); - R_DrawViewModel (); - if (R_TestErrors (0)) R_DisplayErrors (); R_ClearErrors (); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 4e599561d..7dad33b8d 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -217,15 +217,15 @@ glsl_R_RenderView (void) glsl_R_DrawWaterSurfaces (); if (speeds) t[7] = Sys_DoubleTime (); - glsl_R_DrawParticles (); + R_DrawViewModel (); if (speeds) t[8] = Sys_DoubleTime (); - R_DrawViewModel (); + glsl_R_DrawParticles (); if (speeds) t[9] = Sys_DoubleTime (); if (speeds) { Sys_Printf ("frame: %g, setup: %g, mark: %g, pushdl: %g, world: %g," - " sky: %g, ents: %g, water: %g, part: %g, view: %g\n", + " sky: %g, ents: %g, water: %g, view: %g, part: %g\n", (t[9] - t[0]) * 1000, (t[1] - t[0]) * 1000, (t[2] - t[1]) * 1000, (t[3] - t[2]) * 1000, (t[4] - t[3]) * 1000, (t[5] - t[4]) * 1000, From 7906db5a375595eff3d42705f40365e0bc64aaa7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Mar 2022 19:13:58 +0900 Subject: [PATCH 2489/3664] [client] Set camera rotation for chase mode 1 With the change in cl_view separating chase cam updates from first-person updates, the auto-rotation of the camera was lost. --- libs/client/cl_chase.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/client/cl_chase.c b/libs/client/cl_chase.c index 9f1a08b6e..62e0d471f 100644 --- a/libs/client/cl_chase.c +++ b/libs/client/cl_chase.c @@ -187,6 +187,7 @@ chase_mode_1 (chasestate_t *cs) vec4f_t forward = {}, up = {}, right = {}, stop = {}; //FIXME AngleVectors (vs->player_angles, &forward[0], &right[0], &up[0]); + VectorCopy (vs->player_angles, cs->camera_angles); // calc exact destination cs->camera_origin = vs->player_origin @@ -200,7 +201,7 @@ chase_mode_1 (chasestate_t *cs) cs->camera_origin = stop + forward * 8; } - Transform_SetWorldPosition (vs->camera_transform, cs->camera_origin); + set_camera (cs, vs); } static void From 6ec8e294290ec5a0422e0f1f4a11037b5f8e4e03 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Mar 2022 06:43:30 +0900 Subject: [PATCH 2490/3664] [scene] Track hierarchies instead of root transforms The root transform of each hierarchy can be extracted from the first transform of the list in the hierarchy, so no information is lost. The main reason for the change is I discovered (obvious in hindsight) that deleting root transforms was O(n) due to keeping them in an array, thus the use of a linked list (I don't expect a hierarchy to be in more than one such list), and I didn't want the transforms to be in a linked list. --- include/QF/scene/hierarchy.h | 4 +++- include/QF/scene/scene.h | 2 +- include/scn_internal.h | 3 --- libs/scene/hierarchy.c | 12 ++++++++++++ libs/scene/scene.c | 29 ++--------------------------- libs/scene/transform.c | 4 ---- 6 files changed, 18 insertions(+), 36 deletions(-) diff --git a/include/QF/scene/hierarchy.h b/include/QF/scene/hierarchy.h index 6800887fa..61a77c36b 100644 --- a/include/QF/scene/hierarchy.h +++ b/include/QF/scene/hierarchy.h @@ -45,6 +45,9 @@ #define null_transform (~0u) typedef struct hierarchy_s { + struct hierarchy_s *next; + struct hierarchy_s **prev; + struct scene_s *scene; xformset_t transform; entityset_t entity; uint32set_t childCount; @@ -61,7 +64,6 @@ typedef struct hierarchy_s { vec4fset_t localScale; vec4fset_t worldRotation; vec4fset_t worldScale; - struct scene_s *scene; } hierarchy_t; hierarchy_t *Hierarchy_New (struct scene_s *scene, int createRoot); diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index ea51c44b5..b74c29955 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -42,7 +42,7 @@ typedef struct scene_s { struct scene_resources_s *const resources; - xformset_t roots; + struct hierarchy_s *hierarchies; } scene_t; scene_t *Scene_NewScene (void); diff --git a/include/scn_internal.h b/include/scn_internal.h index 1ef11163f..9ad3521dc 100644 --- a/include/scn_internal.h +++ b/include/scn_internal.h @@ -13,7 +13,4 @@ typedef struct scene_resources_s { PR_RESMAP (transform_t) transforms; } scene_resources_t; -void scene_add_root (scene_t *scene, transform_t *transform); -void scene_del_root (scene_t *scene, transform_t *transform); - #endif//__scn_internal_h diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 5218e39f9..4573e9e6e 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -403,6 +403,13 @@ Hierarchy_New (scene_t *scene, int createRoot) hierarchy_t *hierarchy = PR_RESNEW_NC (res->hierarchies); hierarchy->scene = scene; + hierarchy->prev = &scene->hierarchies; + hierarchy->next = scene->hierarchies; + if (scene->hierarchies) { + scene->hierarchies->prev = &hierarchy->next; + } + scene->hierarchies = hierarchy; + size_t grow = 16; DARRAY_INIT (&hierarchy->transform, grow); DARRAY_INIT (&hierarchy->entity, grow); @@ -432,6 +439,11 @@ Hierarchy_New (scene_t *scene, int createRoot) void Hierarchy_Delete (hierarchy_t *hierarchy) { + if (hierarchy->next) { + hierarchy->next->prev = hierarchy->prev; + } + *hierarchy->prev = hierarchy->next; + scene_resources_t *res = hierarchy->scene->resources; for (size_t i = 0; i < hierarchy->transform.size; i++) { PR_RESFREE (res->transforms, hierarchy->transform.a[i]); diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 99d856b0e..e08fb718c 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -54,8 +54,6 @@ Scene_NewScene (void) res = calloc (1, sizeof (scene_resources_t)); *(scene_resources_t **)&scene->resources = res; - DARRAY_INIT (&scene->roots, 16); - return scene; } @@ -70,8 +68,6 @@ Scene_DeleteScene (scene_t *scene) } free (res->entities._map); - DARRAY_CLEAR (&scene->roots); - free (scene->resources); free (scene); } @@ -98,27 +94,6 @@ Scene_GetEntity (scene_t *scene, int id) return PR_RESGET (res->entities, id); } -void -scene_add_root (scene_t *scene, transform_t *transform) -{ - if (!Transform_GetParent (transform)) { - DARRAY_APPEND (&scene->roots, transform); - } -} - -void -scene_del_root (scene_t *scene, transform_t *transform) -{ - if (!Transform_GetParent (transform)) { - for (size_t i = 0; i < scene->roots.size; i++) { - if (scene->roots.a[i] == transform) { - DARRAY_REMOVE_AT (&scene->roots, i); - break; - } - } - } -} - static void destroy_entity (scene_t *scene, entity_t *ent) { @@ -154,8 +129,8 @@ Scene_DestroyEntity (scene_t *scene, entity_t *ent) void Scene_FreeAllEntities (scene_t *scene) { - for (size_t i = 0; i < scene->roots.size; i++) { - hierarchy_t *h = scene->roots.a[i]->hierarchy; + while (scene->hierarchies) { + hierarchy_t *h = scene->hierarchies; // deleting the root entity deletes all child entities entity_t *ent = h->entity.a[0]; destroy_entity (scene, ent); diff --git a/libs/scene/transform.c b/libs/scene/transform.c index dd7facbe1..d855c4dc9 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -58,7 +58,6 @@ Transform_New (scene_t *scene, transform_t *parent) } else { transform->hierarchy = Hierarchy_New (scene, 1); transform->index = 0; - scene_add_root (scene, transform); } transform->hierarchy->transform.a[transform->index] = transform; Hierarchy_UpdateMatrices (transform->hierarchy); @@ -73,7 +72,6 @@ Transform_Delete (transform_t *transform) // hierarchy so deleting it is easier Transform_SetParent (transform, 0); } - scene_del_root (transform->scene, transform); // Takes care of freeing the transforms Hierarchy_Delete (transform->hierarchy); } @@ -90,7 +88,6 @@ void Transform_SetParent (transform_t *transform, transform_t *parent) { if (parent) { - scene_del_root (transform->scene, transform); hierarchy_t *hierarchy = transform->hierarchy; uint32_t index = transform->index; Hierarchy_InsertHierarchy (parent->hierarchy, hierarchy, @@ -112,7 +109,6 @@ Transform_SetParent (transform_t *transform, transform_t *parent) Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, null_transform, index); Hierarchy_RemoveHierarchy (hierarchy, index); - scene_add_root (transform->scene, transform); } } From 6573acbc7471d5ec668237ced8723197f0ffa269 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Mar 2022 01:14:43 +0900 Subject: [PATCH 2491/3664] [qw] Fix some segfaults in chase mode And unconditionally allow chase cam when playing demos. --- qw/source/cl_main.c | 5 +++++ qw/source/cl_parse.c | 1 + 2 files changed, 6 insertions(+) diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 566fa1a10..3724a5a41 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -399,6 +399,9 @@ CL_ClearState (void) cl.maxclients = MAX_CLIENTS; cl.viewstate.voffs_enabled = 0; cl.viewstate.chasestate = &cl.chasestate; + cl.chasestate.viewstate = &cl.viewstate; + cl.viewstate.punchangle = (vec4f_t) {0, 0, 0, 1}; + // Note: we should probably hack around this and give diff values for // diff gamedirs @@ -623,6 +626,7 @@ CL_FullServerinfo_f (void) if ((p = Info_ValueForKey (cl.serverinfo, "chase")) && *p) { cl.viewstate.chase = atoi (p); } + cl.viewstate.chase |= cls.demoplayback; if ((p = Info_ValueForKey (cl.serverinfo, "cshifts")) && *p) { cl.sv_cshifts = atoi (p); } @@ -1341,6 +1345,7 @@ CL_Init_Cvars (void) Game_Init_Cvars (); Pmove_Init_Cvars (); Team_Init_Cvars (); + Chase_Init_Cvars (); V_Init_Cvars (); cl_pitchspeed->callback = cl_pitchspeed_f; diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index d25c42405..e73c7ad3d 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -414,6 +414,7 @@ Model_NextDownload (void) // all done cl.worldmodel = cl.model_precache[1]; + cl.chasestate.worldmodel = cl.worldmodel; CL_NewMap (cl.model_name[1]); // done with modellist, request first of static signon messages From d69355f521f00f32cc3e6e57fc1eb416a988aa01 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Mar 2022 01:48:10 +0900 Subject: [PATCH 2492/3664] [renderer] Support multiple entity queues While there's currently only the one still, this will allow the entities to be multiply queued for multi-pass rendering (eg, shadows). As the avoidance of putting an entity in the same queue more than once relies on the entity id, all entities now come from the scene (which is stored in cl_world in the client code for nq and qw), thus the extensive changes in the clients. --- include/QF/plugin/vid_render.h | 1 - include/QF/render.h | 1 - include/QF/scene/entity.h | 33 ++++ include/client/entities.h | 7 + include/client/temp_entities.h | 3 - include/client/world.h | 70 +++++++ include/r_internal.h | 4 - include/r_local.h | 2 +- libs/client/Makemodule.am | 1 + libs/client/cl_entities.c | 9 +- libs/client/cl_temp_entities.c | 54 +++--- libs/client/cl_view.c | 4 +- libs/client/cl_world.c | 224 +++++++++++++++++++++++ libs/scene/Makemodule.am | 1 + libs/scene/entity.c | 71 +++++++ libs/video/renderer/gl/gl_lightmap.c | 4 +- libs/video/renderer/gl/gl_rmain.c | 13 +- libs/video/renderer/gl/gl_rmisc.c | 5 +- libs/video/renderer/gl/gl_rsurf.c | 4 +- libs/video/renderer/glsl/glsl_bsp.c | 4 +- libs/video/renderer/glsl/glsl_main.c | 11 +- libs/video/renderer/r_efrag.c | 6 +- libs/video/renderer/r_ent.c | 95 +--------- libs/video/renderer/sw/sw_rmain.c | 23 ++- libs/video/renderer/sw/sw_rmisc.c | 4 +- libs/video/renderer/sw32/sw32_rmain.c | 23 ++- libs/video/renderer/sw32/sw32_rmisc.c | 4 +- libs/video/renderer/vid_render_gl.c | 1 - libs/video/renderer/vid_render_glsl.c | 1 - libs/video/renderer/vid_render_sw.c | 1 - libs/video/renderer/vid_render_sw32.c | 1 - libs/video/renderer/vid_render_vulkan.c | 4 +- libs/video/renderer/vulkan/vulkan_bsp.c | 4 +- libs/video/renderer/vulkan/vulkan_main.c | 12 +- nq/include/client.h | 13 +- nq/source/cl_demo.c | 6 +- nq/source/cl_ents.c | 73 +++++--- nq/source/cl_main.c | 34 ++-- nq/source/cl_parse.c | 190 +++---------------- nq/source/cl_screen.c | 6 +- nq/source/host.c | 3 +- nq/source/host_cmd.c | 10 +- nq/source/sv_ded.c | 4 + qw/include/cl_ents.h | 5 +- qw/include/client.h | 11 +- qw/source/cl_demo.c | 6 +- qw/source/cl_entparse.c | 13 +- qw/source/cl_ents.c | 74 +++++--- qw/source/cl_main.c | 20 +- qw/source/cl_parse.c | 165 +++-------------- qw/source/cl_screen.c | 5 +- qw/source/sbar.c | 5 +- qw/source/teamplay.c | 11 +- 53 files changed, 741 insertions(+), 618 deletions(-) create mode 100644 include/client/world.h create mode 100644 libs/client/cl_world.c create mode 100644 libs/scene/entity.c diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 46e48a040..41a889bec 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -119,7 +119,6 @@ typedef struct vid_render_funcs_s { void (*R_RemoveEfrags) (entity_t *ent); void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); dlight_t *(*R_AllocDlight) (int key); - entity_t *(*R_AllocEntity) (void); void (*R_MaxDlightsCheck) (struct cvar_s *var); void (*R_DecayLights) (double frametime); diff --git a/include/QF/render.h b/include/QF/render.h index 3668a157f..fa36bff67 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -155,7 +155,6 @@ typedef struct visibility_s { struct mnode_s *topnode; // bmodels, first world node that // splits bmodel, or NULL if not split // applies to other models, too - int visframe; // last frame this entity was // found in an active leaf int trivial_accept; // view clipping (frustum and depth) } visibility_t; diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index f6bd82e4b..fd5ca8bc0 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -33,6 +33,7 @@ #include "QF/darray.h" #include "QF/qtypes.h" +#include "QF/set.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" @@ -46,6 +47,38 @@ #include "QF/render.h" //FIXME move entity_t here +typedef struct entqueue_s { + set_t *queued_ents; + entityset_t *ent_queues; + int num_queues; +} entqueue_t; + +#define ENTINLINE GNU89INLINE inline + +entqueue_t *EntQueue_New (int num_queues); +void EntQueue_Delete (entqueue_t *queue); +ENTINLINE void EntQueue_AddEntity (entqueue_t *queue, entity_t *ent, + int queue_num); +void EntQueue_Clear (entqueue_t *queue); + +#undef ENTINLINE +#ifndef IMPLEMENT_ENTITY_Funcs +#define ENTINLINE GNU89INLINE inline +#else +#define ENTINLINE VISIBLE +#endif + +ENTINLINE +void +EntQueue_AddEntity (entqueue_t *queue, entity_t *ent, int queue_num) +{ + if (!set_is_member (queue->queued_ents, ent->id)) { + // entity ids are negative (ones-complement) + set_add (queue->queued_ents, -ent->id);//FIXME use ~ + DARRAY_APPEND (&queue->ent_queues[queue_num], ent); + } +} + ///@} #endif//__QF_scene_entity_h diff --git a/include/client/entities.h b/include/client/entities.h index 5981d1c9d..d93107bec 100644 --- a/include/client/entities.h +++ b/include/client/entities.h @@ -31,9 +31,16 @@ #ifndef __client_entities_h #define __client_entities_h +#include "QF/darray.h" +#include "QF/msg.h" #include "QF/qtypes.h" + #include "QF/simd/types.h" +typedef struct entitystateset_s DARRAY_TYPE (struct entity_state_s) + entitystateset_t; +extern entitystateset_t cl_static_entities; + // entity_state_t is the information conveyed from the server // in an update message typedef struct entity_state_s { diff --git a/include/client/temp_entities.h b/include/client/temp_entities.h index f7f9477cf..e88a07331 100644 --- a/include/client/temp_entities.h +++ b/include/client/temp_entities.h @@ -96,15 +96,12 @@ typedef enum TE_qwEffect { //FIXME find a better way to get this info from the parser typedef struct TEntContext_s { vec4f_t simorg; - struct model_s *worldModel; int playerEntity; } TEntContext_t; struct msg_s; struct entity_s; -extern struct scene_s *cl_scene; - void CL_TEnts_Init (void); void CL_Init_Entity (struct entity_s *ent); void CL_ClearTEnts (void); diff --git a/include/client/world.h b/include/client/world.h new file mode 100644 index 000000000..191e313d8 --- /dev/null +++ b/include/client/world.h @@ -0,0 +1,70 @@ +/* + world.h + + Client world scene management + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/3/4 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __client_world_h +#define __client_world_h + +#include "QF/darray.h" +#include "QF/msg.h" +#include "QF/qtypes.h" + +#include "QF/simd/types.h" + +typedef struct modelset_s DARRAY_TYPE (struct model_s *) modelset_t; + +typedef struct worldscene_s { + struct scene_s *scene; + struct plitem_s *edicts; + struct plitem_s *worldspawn; + struct model_s *worldmodel; + modelset_t models; +} worldscene_t; + +extern worldscene_t cl_world; + +struct msg_s; +struct entity_state_s; + +void CL_World_Init (void); + +// PROTOCOL_FITZQUAKE -- flags for entity baseline messages +#define B_LARGEMODEL (1<<0) // modelindex is short instead of byte +#define B_LARGEFRAME (1<<1) // frame is short instead of byte +#define B_ALPHA (1<<2) // 1 byte, uses ENTALPHA_ENCODE, not sent if ENTALPHA_DEFAULT +void CL_ParseBaseline (struct msg_s *msg, struct entity_state_s *baseline, + int version); +/* + Static entities are non-interactive world objects like torches +*/ +void CL_ParseStatic (struct msg_s *msg, int version); +void CL_MapCfg (const char *mapname); +void CL_World_NewMap (const char *mapname, const char *skyname); + +#endif//__client_world_h diff --git a/include/r_internal.h b/include/r_internal.h index bc2b2b464..e2924f047 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -81,10 +81,6 @@ void R_SetVrect (const vrect_t *pvrect, vrect_t *pvrectin, int lineadj); void R_LoadSkys (const char *); void R_ClearEfrags (void); -void R_ClearEnts (void); -void R_EnqueueEntity (struct entity_s *ent); -entity_t *R_AllocEntity (void); -void R_FreeAllEntities (void); void R_FindNearLights (const vec3_t pos, int count, dlight_t **lights); dlight_t *R_AllocDlight (int key); diff --git a/include/r_local.h b/include/r_local.h index 4e4e00bfd..d6d7b35a9 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -292,7 +292,7 @@ extern mleaf_t *r_viewleaf; extern int r_clipflags; extern int r_dlightframecount; -extern struct entity_s *r_ent_queue[mod_num_types]; +extern struct entqueue_s *r_ent_queue; struct dlight_s; extern vec3_t lightspot; diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 14e52a315..95664df07 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -10,6 +10,7 @@ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_particles.c \ libs/client/cl_temp_entities.c \ libs/client/cl_view.c \ + libs/client/cl_world.c \ libs/client/hud.c \ libs/client/locs.c \ libs/client/old_keys.c diff --git a/libs/client/cl_entities.c b/libs/client/cl_entities.c index 4403a49bd..d4cac0dfa 100644 --- a/libs/client/cl_entities.c +++ b/libs/client/cl_entities.c @@ -31,11 +31,18 @@ # include "config.h" #endif -#include "QF/render.h" //FIXME for entity_t +#include "QF/msg.h" + #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/simd/vec4f.h" +#include "QF/plugin/vid_render.h" //FIXME + #include "client/entities.h" +#include "client/temp_entities.h" + +entitystateset_t cl_static_entities = DARRAY_STATIC_INIT (32); /* QW has a max of 512 entities and wants 64 frames of data per entity, plus the baseline data (512 * (64 + 1) = 33280), but NQ has a max of 32000 diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index de6233556..86f41a339 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -52,10 +52,11 @@ #include "client/entities.h" #include "client/particles.h" #include "client/temp_entities.h" +#include "client/world.h" typedef struct tent_s { struct tent_s *next; - entity_t ent; + entity_t *ent; } tent_t; typedef struct { @@ -86,7 +87,6 @@ typedef struct tent_obj_s { static PR_RESMAP (tent_t) temp_entities; static PR_RESMAP (tent_obj_t) tent_objects; -scene_t *cl_scene; static tent_obj_t *cl_beams; static tent_obj_t *cl_explosions; @@ -137,8 +137,6 @@ CL_TEnts_Precache (int phase) void CL_TEnts_Init (void) { - cl_scene = Scene_NewScene (); - QFS_GamedirCallback (CL_TEnts_Precache); CL_TEnts_Precache (1); for (int i = 0; i < 360; i++) { @@ -150,12 +148,12 @@ CL_TEnts_Init (void) void CL_Init_Entity (entity_t *ent) { - if (ent->transform) { - Transform_Delete (ent->transform); - } - memset (ent, 0, sizeof (*ent)); + memset (&ent->animation, 0, sizeof (ent->animation)); + memset (&ent->visibility, 0, sizeof (ent->visibility)); + memset (&ent->renderer, 0, sizeof (ent->renderer)); + ent->active = 1; + ent->old_origin = (vec4f_t) {}; - ent->transform = Transform_New (cl_scene, 0); ent->renderer.skin = 0; QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); ent->animation.pose1 = ent->animation.pose2 = -1; @@ -165,9 +163,9 @@ static tent_t * new_temp_entity (void) { tent_t *tent = PR_RESNEW_NC (temp_entities); - tent->ent.transform = 0; + tent->ent = Scene_CreateEntity (cl_world.scene); tent->next = 0; - CL_Init_Entity (&tent->ent); + CL_Init_Entity (tent->ent); return tent; } @@ -177,7 +175,7 @@ free_temp_entities (tent_t *tents) tent_t **t = &tents; while (*t) { - Transform_Delete ((*t)->ent.transform);//FIXME reuse? + Scene_DestroyEntity (cl_world.scene, (*t)->ent);//FIXME reuse? t = &(*t)->next; } *t = temp_entities._free; @@ -215,8 +213,8 @@ beam_clear (beam_t *b) tent_t *t; for (t = b->tents; t; t = t->next) { - r_funcs->R_RemoveEfrags (&t->ent); - t->ent.visibility.efrag = 0; + r_funcs->R_RemoveEfrags (t->ent); + t->ent->visibility.efrag = 0; } free_temp_entities (b->tents); b->tents = 0; @@ -263,17 +261,17 @@ beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx) vec4f_t position = org + d * dist; d += 1.0; - tent->ent.renderer.model = b->model; + tent->ent->renderer.model = b->model; if (transform) { seed = seed * BEAM_SEED_PRIME; - Transform_SetLocalTransform (tent->ent.transform, scale, + Transform_SetLocalTransform (tent->ent->transform, scale, qmulf (rotation, beam_rolls[seed % 360]), position); } else { - Transform_SetLocalPosition (tent->ent.transform, position); + Transform_SetLocalPosition (tent->ent->transform, position); } - r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, tent->ent); } } @@ -377,8 +375,8 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, if (!cl_spr_explod->cache.data) { cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); } - ex->tent->ent.renderer.model = cl_spr_explod; - Transform_SetLocalPosition (ex->tent->ent.transform,//FIXME + ex->tent->ent->renderer.model = cl_spr_explod; + Transform_SetLocalPosition (ex->tent->ent->transform,//FIXME (vec4f_t) {VectorExpand (position), 1}); break; case TE_Explosion2: @@ -601,7 +599,7 @@ CL_UpdateBeams (double time, TEntContext_t *ctx) // add new entities for the lightning for (t = b->tents; t; t = t->next) { seed = seed * BEAM_SEED_PRIME; - Transform_SetLocalRotation (t->ent.transform, + Transform_SetLocalRotation (t->ent->transform, qmulf (b->rotation, beam_rolls[seed % 360])); } @@ -618,7 +616,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) for (to = &cl_explosions; *to; ) { ex = &(*to)->to.ex; - ent = &ex->tent->ent; + ent = ex->tent->ent; f = 10 * (time - ex->start); if (f >= ent->renderer.model->numframes) { tent_obj_t *_to; @@ -634,7 +632,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) ent->animation.frame = f; if (!ent->visibility.efrag) { - r_funcs->R_AddEfrags (&ctx->worldModel->brush, ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); } } } @@ -675,8 +673,8 @@ CL_ClearProjectiles (void) tent_t *tent; for (tent = cl_projectiles; tent; tent = tent->next) { - r_funcs->R_RemoveEfrags (&tent->ent); - tent->ent.visibility.efrag = 0; + r_funcs->R_RemoveEfrags (tent->ent); + tent->ent->visibility.efrag = 0; } free_temp_entities (cl_projectiles); cl_projectiles = 0; @@ -712,7 +710,7 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) *tail = tent; tail = &tent->next; - pr = &tent->ent; + pr = tent->ent; pr->renderer.model = cl_spike; pr->renderer.skin = 0; position[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096; @@ -721,9 +719,9 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) angles[0] = (bits[4] >> 4) * (360.0 / 16.0); angles[1] = bits[5] * (360.0 / 256.0); angles[2] = 0; - CL_TransformEntity (&tent->ent, 1, angles, position); + CL_TransformEntity (tent->ent, 1, angles, position); - r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, tent->ent); } *tail = cl_projectiles; diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index f6371e69e..a1ab36e82 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -43,8 +43,8 @@ #include "client/entities.h" #include "client/hud.h" #include "client/input.h" -#include "client/temp_entities.h"//FIXME for cl_scene #include "client/view.h" +#include "client/world.h" /* The view is allowed to move slightly from it's true position for bobbing, @@ -763,7 +763,7 @@ V_Init (viewstate_t *viewstate) "Used when you are underwater, hit, have the Ring of " "Shadows, or Quad Damage. (v_cshift r g b intensity)"); - viewstate->camera_transform = Transform_New (cl_scene, 0); + viewstate->camera_transform = Transform_New (cl_world.scene, 0); } void diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c new file mode 100644 index 000000000..f0ef82072 --- /dev/null +++ b/libs/client/cl_world.c @@ -0,0 +1,224 @@ +/* + cl_entities.c + + Client side entity management + + Copyright (C) 2012 Bill Currie + + Author: Bill Currie + Date: 2012/6/28 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cbuf.h" +#include "QF/cmd.h" +#include "QF/idparse.h" +#include "QF/quakefs.h" +#include "QF/plist.h" +#include "QF/progs.h" +#include "QF/msg.h" + +#include "QF/scene/entity.h" +#include "QF/scene/scene.h" +#include "QF/simd/vec4f.h" + +#include "QF/plugin/vid_render.h" //FIXME + +#include "client/entities.h" +#include "client/temp_entities.h" +#include "client/world.h" + +worldscene_t cl_world = { + .models = DARRAY_STATIC_INIT (32), +}; + +void +CL_World_Init (void) +{ + cl_world.scene = Scene_NewScene (); +} + +void +CL_ParseBaseline (qmsg_t *msg, entity_state_t *baseline, int version) +{ + int bits = 0; + + if (version == 2) + bits = MSG_ReadByte (msg); + + if (bits & B_LARGEMODEL) + baseline->modelindex = MSG_ReadShort (msg); + else + baseline->modelindex = MSG_ReadByte (msg); + + if (bits & B_LARGEFRAME) + baseline->frame = MSG_ReadShort (msg); + else + baseline->frame = MSG_ReadByte (msg); + + baseline->colormap = MSG_ReadByte (msg); + baseline->skinnum = MSG_ReadByte (msg); + + MSG_ReadCoordAngleV (msg, &baseline->origin[0], baseline->angles); + baseline->origin[3] = 1;//FIXME + + if (bits & B_ALPHA) + baseline->alpha = MSG_ReadByte (msg); + else + baseline->alpha = 255;//FIXME alpha + baseline->scale = 16; + baseline->glow_size = 0; + baseline->glow_color = 254; + baseline->colormod = 255; +} + +void +CL_ParseStatic (qmsg_t *msg, int version) +{ + entity_t *ent; + entity_state_t es; + + ent = Scene_CreateEntity (cl_world.scene); + CL_Init_Entity (ent); + + CL_ParseBaseline (msg, &es, version); + DARRAY_APPEND (&cl_static_entities, es); + + // copy it to the current state + ent->renderer.model = cl_world.models.a[es.modelindex]; + ent->animation.frame = es.frame; + ent->renderer.skinnum = es.skinnum; + + CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin); + + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); +} + +static void +map_cfg (const char *mapname, int all) +{ + char *name = malloc (strlen (mapname) + 4 + 1); + cbuf_t *cbuf = Cbuf_New (&id_interp); + QFile *f; + + QFS_StripExtension (mapname, name); + strcat (name, ".cfg"); + f = QFS_FOpenFile (name); + if (f) { + Qclose (f); + Cmd_Exec_File (cbuf, name, 1); + } else { + Cmd_Exec_File (cbuf, "maps_default.cfg", 1); + } + if (all) { + Cbuf_Execute_Stack (cbuf); + } else { + Cbuf_Execute_Sets (cbuf); + } + free (name); + Cbuf_Delete (cbuf); +} + +void +CL_MapCfg (const char *mapname) +{ + map_cfg (mapname, 0); +} + +static plitem_t * +map_ent (const char *mapname) +{ + static progs_t edpr; + char *name = malloc (strlen (mapname) + 4 + 1); + char *buf; + plitem_t *edicts = 0; + QFile *ent_file; + + QFS_StripExtension (mapname, name); + strcat (name, ".ent"); + ent_file = QFS_VOpenFile (name, 0, cl_world.models.a[1]->vpath); + if ((buf = (char *) QFS_LoadFile (ent_file, 0))) { + edicts = ED_Parse (&edpr, buf); + free (buf); + } else { + edicts = ED_Parse (&edpr, cl_world.models.a[1]->brush.entities); + } + free (name); + return edicts; +} + +static void +CL_LoadSky (const char *name) +{ + plitem_t *worldspawn = cl_world.worldspawn; + plitem_t *item; + static const char *sky_keys[] = { + "sky", // Q2/DarkPlaces + "skyname", // old QF + "qlsky", // QuakeLives + 0 + }; + + if (!name) { + if (!worldspawn) { + r_funcs->R_LoadSkys (0); + return; + } + for (const char **key = sky_keys; *key; key++) { + if ((item = PL_ObjectForKey (cl_world.worldspawn, *key))) { + name = PL_String (item); + break; + } + } + } + r_funcs->R_LoadSkys (name); +} + +void +CL_World_NewMap (const char *mapname, const char *skyname) +{ + cl_static_entities.size = 0; + r_funcs->R_NewMap (cl_world.worldmodel, + cl_world.models.a, cl_world.models.size); + if (cl_world.models.a[1] && cl_world.models.a[1]->brush.entities) { + if (cl_world.edicts) { + PL_Free (cl_world.edicts); + } + cl_world.edicts = map_ent (mapname); + if (cl_world.edicts) { + cl_world.worldspawn = PL_ObjectAtIndex (cl_world.edicts, 0); + CL_LoadSky (skyname); + if (r_funcs->Fog_ParseWorldspawn) + r_funcs->Fog_ParseWorldspawn (cl_world.worldspawn); + } + } + map_cfg (mapname, 1); +} diff --git a/libs/scene/Makemodule.am b/libs/scene/Makemodule.am index 060e1d31d..25b3e7562 100644 --- a/libs/scene/Makemodule.am +++ b/libs/scene/Makemodule.am @@ -9,6 +9,7 @@ libs_scene_libQFscene_la_LIBADD= $(scene_deps) libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps) libs_scene_libQFscene_la_SOURCES= \ libs/scene/camera.c \ + libs/scene/entity.c \ libs/scene/hierarchy.c \ libs/scene/scene.c \ libs/scene/transform.c diff --git a/libs/scene/entity.c b/libs/scene/entity.c new file mode 100644 index 000000000..92e5099d7 --- /dev/null +++ b/libs/scene/entity.c @@ -0,0 +1,71 @@ +/* + entity.c + + Entity management + + Copyright (C) 2022 Bill Currke + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/set.h" + +#define IMPLEMENT_ENTITY_Funcs + +#include "QF/scene/entity.h" +#include "QF/scene/scene.h" + +#include "scn_internal.h" + +entqueue_t * +EntQueue_New (int num_queues) +{ + int size = sizeof (entqueue_t) + num_queues * sizeof (entityset_t); + entqueue_t *queue = calloc (1, size); + queue->queued_ents = set_new (); + queue->ent_queues = (entityset_t *) (queue + 1); + queue->num_queues = num_queues; + for (int i = 0; i < num_queues; i++) { + queue->ent_queues[i].grow = 64; + } + return queue; +} + +void +EntQueue_Delete (entqueue_t *queue) +{ + for (int i = 0; i < queue->num_queues; i++) { + DARRAY_CLEAR (&queue->ent_queues[i]); + } + set_delete (queue->queued_ents); + free (queue); +} + +void +EntQueue_Clear (entqueue_t *queue) +{ + for (int i = 0; i < queue->num_queues; i++) { + queue->ent_queues[i].size = 0; + } + set_empty (queue->queued_ents); +} diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index c7ec6d042..f601e2755 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -551,7 +551,6 @@ gl_overbright_f (cvar_t *var) { int num; model_t *m; - entity_t *ent; mod_brush_t *brush; if (!var) @@ -598,7 +597,8 @@ gl_overbright_f (cvar_t *var) if (!gl_R_BuildLightMap) return; - for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \ + entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \ m = ent->renderer.model; if (m->path[0] == '*') continue; diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 1c9fa7f00..07dd2a8b2 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -193,8 +193,6 @@ gl_R_RotateForEntity (entity_t *e) static void R_DrawEntitiesOnList (void) { - entity_t *ent; - if (!r_drawentities->int_val) return; @@ -220,7 +218,8 @@ R_DrawEntitiesOnList (void) qfglEnable (GL_NORMALIZE); } - for (ent = r_ent_queue[mod_alias]; ent; ent = ent->next) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_alias].size; i++) { \ + entity_t *ent = r_ent_queue->ent_queues[mod_alias].a[i]; \ gl_R_DrawAliasModel (ent); } qfglColor3ubv (color_white); @@ -248,7 +247,8 @@ R_DrawEntitiesOnList (void) qglActiveTexture (gl_mtex_enum + 0); } - for (ent = r_ent_queue[mod_iqm]; ent; ent = ent->next) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_iqm].size; i++) { \ + entity_t *ent = r_ent_queue->ent_queues[mod_iqm].a[i]; \ gl_R_DrawIQMModel (ent); } qfglColor3ubv (color_white); @@ -257,7 +257,8 @@ R_DrawEntitiesOnList (void) qfglEnable (GL_ALPHA_TEST); if (gl_va_capable) qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray); - for (ent = r_ent_queue[mod_sprite]; ent; ent = ent->next) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_sprite].size; i++) { \ + entity_t *ent = r_ent_queue->ent_queues[mod_sprite].a[i]; \ R_DrawSpriteModel (ent); } qfglDisable (GL_ALPHA_TEST); @@ -328,7 +329,7 @@ void gl_R_SetupFrame (void) { R_AnimateLight (); - R_ClearEnts (); + EntQueue_Clear (r_ent_queue); r_framecount++; gl_Fog_SetupFrame (); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index f035be9dd..90bfc1b10 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -61,6 +61,8 @@ #include "QF/GL/qf_textures.h" #include "QF/GL/qf_vid.h" +#include "QF/scene/entity.h" + #include "mod_internal.h" #include "r_internal.h" #include "varrays.h" @@ -140,6 +142,7 @@ gl_R_LoadSky_f (void) void gl_R_Init (void) { + r_ent_queue = EntQueue_New (mod_num_types); R_Init_Cvars (); gl_R_Particles_Init_Cvars (); @@ -191,8 +194,6 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_worldentity.renderer.model = worldmodel; brush = &worldmodel->brush; - R_FreeAllEntities (); - // clear out efrags in case the level hasn't been reloaded for (unsigned i = 0; i < brush->modleafs; i++) brush->leafs[i].efrags = NULL; diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 77a4e0349..5d32d9c5e 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -740,8 +740,8 @@ gl_R_DrawWorld (void) R_VisitWorldNodes (&bctx); if (r_drawentities->int_val) { - entity_t *ent; - for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \ + entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \ gl_R_DrawBrushModel (ent); } } diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 2ee30363a..0605d81b4 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -1149,8 +1149,8 @@ glsl_R_DrawWorld (void) R_VisitWorldNodes (&bctx); if (r_drawentities->int_val) { - entity_t *ent; - for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { + entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; R_DrawBrushModel (ent); } } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 7dad33b8d..d7cf28aa2 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -48,6 +48,8 @@ #include "QF/screen.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" #include "QF/GLSL/qf_alias.h" @@ -95,7 +97,7 @@ void glsl_R_SetupFrame (void) { R_AnimateLight (); - R_ClearEnts (); + EntQueue_Clear (r_ent_queue); r_framecount++; VectorCopy (r_refdef.viewposition, r_origin); @@ -141,7 +143,6 @@ R_SetupView (void) static void R_RenderEntities (void) { - entity_t *ent; int begun; if (!r_drawentities->int_val) @@ -149,7 +150,9 @@ R_RenderEntities (void) #define RE_LOOP(type_name, Type) \ do { \ begun = 0; \ - for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \ + i++) { \ + entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \ if (!begun) { \ glsl_R_##Type##Begin (); \ begun = 1; \ @@ -237,6 +240,7 @@ glsl_R_RenderView (void) void glsl_R_Init (void) { + r_ent_queue = EntQueue_New (mod_num_types); Cmd_AddCommand ("timerefresh", glsl_R_TimeRefresh_f, "Test the current refresh rate for the current location."); R_Init_Cvars (); @@ -267,7 +271,6 @@ glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_viewleaf = NULL; R_MarkLeaves (); - R_FreeAllEntities (); R_ClearParticles (); glsl_R_RegisterTextures (models, num_models); glsl_R_BuildLightmaps (models, num_models); diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 3766f681d..6c2bd3a70 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -235,11 +235,7 @@ R_StoreEfrags (const efrag_t *efrag) case mod_brush: case mod_sprite: case mod_iqm: - if (ent->visibility.visframe != r_framecount) { - R_EnqueueEntity (ent); - // mark that we've recorded this entity for this frame - ent->visibility.visframe = r_framecount; - } + EntQueue_AddEntity (r_ent_queue, ent, model->type); efrag = efrag->leafnext; break; diff --git a/libs/video/renderer/r_ent.c b/libs/video/renderer/r_ent.c index 9dcba8401..fb133d388 100644 --- a/libs/video/renderer/r_ent.c +++ b/libs/video/renderer/r_ent.c @@ -48,100 +48,7 @@ #include "r_internal.h" -#define ENT_POOL_SIZE 32 - -typedef struct entity_pool_s { - struct entity_pool_s *next; - entity_t entities[ENT_POOL_SIZE]; -} entity_pool_t; - -entity_t *r_ent_queue[mod_num_types]; -static entity_t **vis_tail[mod_num_types] = { - [mod_brush] &r_ent_queue[mod_brush], - [mod_sprite] &r_ent_queue[mod_sprite], - [mod_alias] &r_ent_queue[mod_alias], - [mod_iqm] &r_ent_queue[mod_iqm], -}; - -static entity_pool_t *entity_pools = 0; -static entity_pool_t **entpool_tail = &entity_pools; -static entity_t *free_entities; - -entity_t * -R_AllocEntity (void) -{ - entity_pool_t *pool; - entity_t *ent; - int i; - - if ((ent = free_entities)) { - free_entities = ent->next; - ent->next = 0; - ent->transform = 0; - return ent; - } - - pool = malloc (sizeof (entity_pool_t)); - pool->next = 0; - *entpool_tail = pool; - entpool_tail = &pool->next; - - for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) { - ent->next = ent + 1; - ent->transform = 0; - } - ent->next = 0; - ent->transform = 0; - free_entities = pool->entities; - - return R_AllocEntity (); -} - -void -R_FreeAllEntities (void) -{ - entity_pool_t *pool; - entity_t *ent; - int i; - - for (pool = entity_pools; pool; pool = pool->next) { - for (ent = pool->entities, i = 0; i < ENT_POOL_SIZE - 1; i++, ent++) { - ent->next = ent + 1; - if (ent->transform) { - Transform_Delete (ent->transform); - ent->transform = 0; - } - } - ent->next = pool->next ? pool->next->entities : 0; - if (ent->transform) { - Transform_Delete (ent->transform); - ent->transform = 0; - } - } - free_entities = entity_pools ? entity_pools->entities : 0; -} - -void -R_ClearEnts (void) -{ - for (int i = 0; i < mod_num_types; i++) { - r_ent_queue[i] = 0; - vis_tail[i] = &r_ent_queue[i]; - } -} - -void -R_EnqueueEntity (entity_t *ent) -{ - modtype_t type = ent->renderer.model->type; - - if (type < 0 || type >= mod_num_types) { - Sys_Error ("R_EnqueueEntity: Bad entity model type %d", type); - } - ent->next = 0; - *vis_tail[type] = ent; - vis_tail[type] = &ent->next; -} +entqueue_t *r_ent_queue; float R_EntityBlend (animation_t *animation, int pose, float interval) diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index d28b60b27..e482d7617 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -117,6 +117,8 @@ sw_R_Init (void) { int dummy; + r_ent_queue = EntQueue_New (mod_num_types); + // get stack position so we can guess if we are going to overflow r_stack_start = (byte *) & dummy; @@ -167,8 +169,6 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) memset (&r_worldentity, 0, sizeof (r_worldentity)); r_worldentity.renderer.model = worldmodel; - R_FreeAllEntities (); - // clear out efrags in case the level hasn't been reloaded for (unsigned i = 0; i < brush->modleafs; i++) brush->leafs[i].efrags = NULL; @@ -418,14 +418,14 @@ draw_iqm_entity (entity_t *ent) static void R_DrawEntitiesOnList (void) { - entity_t *ent; - if (!r_drawentities->int_val) return; #define RE_LOOP(type_name) \ do { \ - for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \ + i++) { \ + entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \ VectorCopy (Transform_GetWorldPosition (ent->transform), \ r_entorigin); \ currententity = ent; \ @@ -566,7 +566,6 @@ R_DrawBEntitiesOnList (void) vec3_t origin; model_t *clmodel; float minmaxs[6]; - entity_t *ent; if (!r_drawentities->int_val) return; @@ -574,12 +573,12 @@ R_DrawBEntitiesOnList (void) VectorCopy (modelorg, oldorigin); insubmodel = true; - for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { + entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; currententity = ent; - VectorCopy (Transform_GetWorldPosition (currententity->transform), - origin); - clmodel = currententity->renderer.model; + VectorCopy (Transform_GetWorldPosition (ent->transform), origin); + clmodel = ent->renderer.model; // see if the bounding box lets us trivially reject, also // sets trivial accept status @@ -626,8 +625,8 @@ R_DrawBEntitiesOnList (void) if (r_drawpolys | r_drawculledpolys) { R_ZDrawSubmodelPolys (clmodel); } else { - if (currententity->visibility.topnode) { - mnode_t *topnode = currententity->visibility.topnode; + if (ent->visibility.topnode) { + mnode_t *topnode = ent->visibility.topnode; if (topnode->contents >= 0) { // not a leaf; has to be clipped to the world diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index f0ab9c9bb..481a3f64d 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -35,6 +35,8 @@ #include "QF/sys.h" #include "QF/ui/view.h" +#include "QF/scene/entity.h" + #include "compat.h" #include "r_internal.h" #include "vid_internal.h" @@ -224,7 +226,7 @@ R_SetupFrame (void) R_CheckVariables (); R_AnimateLight (); - R_ClearEnts (); + EntQueue_Clear (r_ent_queue); r_framecount++; numbtofpolys = 0; diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 3c147862b..517f471c3 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -142,6 +142,8 @@ sw32_R_Init (void) { int dummy; + r_ent_queue = EntQueue_New (mod_num_types); + // get stack position so we can guess if we are going to overflow r_stack_start = (byte *) & dummy; @@ -182,8 +184,6 @@ sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) memset (&r_worldentity, 0, sizeof (r_worldentity)); r_worldentity.renderer.model = worldmodel; - R_FreeAllEntities (); - // clear out efrags in case the level hasn't been reloaded for (unsigned i = 0; i < brush->modleafs; i++) brush->leafs[i].efrags = NULL; @@ -425,14 +425,14 @@ draw_iqm_entity (entity_t *ent) static void R_DrawEntitiesOnList (void) { - entity_t *ent; - if (!r_drawentities->int_val) return; #define RE_LOOP(type_name) \ do { \ - for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \ + i++) { \ + entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \ VectorCopy (Transform_GetWorldPosition (ent->transform), \ r_entorigin); \ currententity = ent; \ @@ -572,7 +572,6 @@ R_DrawBEntitiesOnList (void) vec3_t origin; model_t *clmodel; float minmaxs[6]; - entity_t *ent; if (!r_drawentities->int_val) return; @@ -580,12 +579,12 @@ R_DrawBEntitiesOnList (void) VectorCopy (modelorg, oldorigin); insubmodel = true; - for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { + entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; currententity = ent; - VectorCopy (Transform_GetWorldPosition (currententity->transform), - origin); - clmodel = currententity->renderer.model; + VectorCopy (Transform_GetWorldPosition (ent->transform), origin); + clmodel = ent->renderer.model; // see if the bounding box lets us trivially reject, also // sets trivial accept status @@ -632,8 +631,8 @@ R_DrawBEntitiesOnList (void) if (sw32_r_drawpolys | sw32_r_drawculledpolys) { sw32_R_ZDrawSubmodelPolys (clmodel); } else { - if (currententity->visibility.topnode) { - mnode_t *topnode = currententity->visibility.topnode; + if (ent->visibility.topnode) { + mnode_t *topnode = ent->visibility.topnode; if (topnode->contents >= 0) { // not a leaf; has to be clipped to the world diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c index 1845fe06e..5b4092250 100644 --- a/libs/video/renderer/sw32/sw32_rmisc.c +++ b/libs/video/renderer/sw32/sw32_rmisc.c @@ -38,6 +38,8 @@ #include "QF/sys.h" #include "QF/ui/view.h" +#include "QF/scene/entity.h" + #include "compat.h" #include "r_internal.h" #include "vid_internal.h" @@ -220,7 +222,7 @@ sw32_R_SetupFrame (void) R_CheckVariables (); R_AnimateLight (); - R_ClearEnts (); + EntQueue_Clear (r_ent_queue); r_framecount++; sw32_numbtofpolys = 0; diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index d95f53a3c..d56d065e3 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -152,7 +152,6 @@ vid_render_funcs_t gl_vid_render_funcs = { R_RemoveEfrags, gl_R_LineGraph, R_AllocDlight, - R_AllocEntity, R_MaxDlightsCheck, R_DecayLights, gl_R_ViewChanged, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 8b98654a1..b611eb25e 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -151,7 +151,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { R_RemoveEfrags, glsl_R_LineGraph, R_AllocDlight, - R_AllocEntity, R_MaxDlightsCheck, R_DecayLights, glsl_R_ViewChanged, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 45f961f6b..325371a07 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -148,7 +148,6 @@ vid_render_funcs_t sw_vid_render_funcs = { R_RemoveEfrags, R_LineGraph, R_AllocDlight, - R_AllocEntity, R_MaxDlightsCheck, R_DecayLights, R_ViewChanged, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index d24da6128..95f81a8e1 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -153,7 +153,6 @@ vid_render_funcs_t sw32_vid_render_funcs = { R_RemoveEfrags, sw32_R_LineGraph, R_AllocDlight, - R_AllocEntity, R_MaxDlightsCheck, R_DecayLights, sw32_R_ViewChanged, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index ef35d022a..cb05aea8c 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -61,6 +61,8 @@ #include "QF/Vulkan/swapchain.h" #include "QF/ui/view.h" +#include "QF/scene/entity.h" + #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" @@ -100,6 +102,7 @@ vulkan_ParticleSystem (void) static void vulkan_R_Init (void) { + r_ent_queue = EntQueue_New (mod_num_types); Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx); @@ -679,7 +682,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { R_RemoveEfrags, vulkan_R_LineGraph, R_AllocDlight, - R_AllocEntity, R_MaxDlightsCheck, R_DecayLights, vulkan_R_ViewChanged, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index c4ad3dc3e..040f7db91 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1039,8 +1039,8 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) R_VisitWorldNodes (brush, ctx); if (r_drawentities->int_val) { - entity_t *ent; - for (ent = r_ent_queue[mod_brush]; ent; ent = ent->next) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { + entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; R_DrawBrushModel (ent, ctx); } } diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 4eb55f08c..2059a5b66 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -45,6 +45,8 @@ #include "QF/screen.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" @@ -65,7 +67,7 @@ static void setup_frame (vulkan_ctx_t *ctx) { R_AnimateLight (); - R_ClearEnts (); + EntQueue_Clear (r_ent_queue); r_framecount++; VectorCopy (r_refdef.viewposition, r_origin); @@ -85,9 +87,10 @@ Vulkan_RenderEntities (qfv_renderframe_t *rFrame) return; #define RE_LOOP(type_name, Type) \ do { \ - entity_t *ent; \ int begun = 0; \ - for (ent = r_ent_queue[mod_##type_name]; ent; ent = ent->next) { \ + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \ + i++) { \ + entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \ if (!begun) { \ Vulkan_##Type##Begin (rFrame); \ begun = 1; \ @@ -122,7 +125,7 @@ Vulkan_DrawViewModel (vulkan_ctx_t *ctx) || !ent->renderer.model) return; - R_EnqueueEntity (ent); + EntQueue_AddEntity (r_ent_queue, ent, ent->renderer.model->type); } void @@ -195,7 +198,6 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, r_viewleaf = NULL; R_MarkLeaves (); - R_FreeAllEntities (); R_ClearParticles (); Vulkan_RegisterTextures (models, num_models, ctx); //Vulkan_BuildLightmaps (models, num_models, ctx); diff --git a/nq/include/client.h b/nq/include/client.h index 6437cf81f..62b24a4d4 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -180,14 +180,9 @@ typedef struct client_state_s { /* information that is static for the entire time connected to a server */ - struct model_s *model_precache[MAX_MODELS]; struct sfx_s *sound_precache[MAX_SOUNDS]; - int nummodels; int numsounds; - struct plitem_s *edicts; - struct plitem_s *worldspawn; - char levelname[40]; // for display on solo scoreboard int spectator; int playernum; @@ -205,9 +200,7 @@ typedef struct client_state_s { int fbskins; // refresh related state - struct model_s *worldmodel; // cl_entitites[0].model int num_entities; // held in cl_entities array - entity_t viewent; // the weapon model int cdtrack; // cd audio @@ -240,10 +233,9 @@ extern struct cvar_s *noskins; extern client_state_t cl; -// FIXME, allocate dynamically -extern entity_t cl_entities[MAX_EDICTS]; +extern entity_t *cl_entities[MAX_EDICTS]; extern double cl_msgtime[MAX_EDICTS]; -extern byte cl_forcelink[MAX_EDICTS]; +extern struct set_s cl_forcelink; extern int fps_count; @@ -299,6 +291,7 @@ void CL_NewTranslation (int slot, struct skin_s *skin); void CL_SignonReply (void); void CL_RelinkEntities (void); void CL_ClearEnts (void); +entity_t *CL_GetEntity (int num); extern double realtime; diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index bdcf684a8..b4d47eebe 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -48,6 +48,8 @@ #include "compat.h" +#include "client/world.h" + #include "nq/include/client.h" #include "nq/include/host.h" @@ -338,8 +340,8 @@ demo_default_name (const char *argv1) time (&tim); strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim)); - // the leading path-name is to be removed from cl.worldmodel->name - mapname = QFS_SkipPath (cl.worldmodel->path); + // the leading path-name is to be removed from cl_world.worldmodel->name + mapname = QFS_SkipPath (cl_world.worldmodel->path); // the map name is cut off after any "." because this would prevent // an extension being appended diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 16c590061..a85b46c56 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -44,11 +44,13 @@ #include "QF/plugin/vid_render.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "compat.h" #include "client/effects.h" #include "client/temp_entities.h" +#include "client/world.h" #include "client/chase.h" @@ -57,9 +59,12 @@ #include "nq/include/host.h" #include "nq/include/server.h" -entity_t cl_entities[MAX_EDICTS]; -double cl_msgtime[MAX_EDICTS]; -byte cl_forcelink[MAX_EDICTS]; +entity_t *cl_entities[MAX_EDICTS]; +double cl_msgtime[MAX_EDICTS]; +static byte forcelink_bytes[SET_SIZE(MAX_EDICTS)]; +#define alloc_forcelink(s) (set_bits_t *)forcelink_bytes +set_t cl_forcelink = SET_STATIC_INIT (MAX_EDICTS, alloc_forcelink); +#undef alloc_forcelink void CL_ClearEnts (void) @@ -67,14 +72,27 @@ CL_ClearEnts (void) size_t i; for (i = 0; i < MAX_EDICTS; i++) { - CL_Init_Entity (cl_entities + i); + if (cl_entities[i]) { + Scene_DestroyEntity (cl_world.scene, cl_entities[i]); + cl_entities[i] = 0; + } } // clear other arrays i = nq_entstates.num_frames * nq_entstates.num_entities; memset (nq_entstates.frame[0], 0, i * sizeof (entity_state_t)); memset (cl_msgtime, 0, sizeof (cl_msgtime)); - memset (cl_forcelink, 0, sizeof (cl_forcelink)); + set_empty (&cl_forcelink); +} + +entity_t * +CL_GetEntity (int num) +{ + if (!cl_entities[num]) { + cl_entities[num] = Scene_CreateEntity (cl_world.scene); + CL_Init_Entity (cl_entities[num]); + } + return cl_entities[num]; } /* @@ -115,12 +133,12 @@ CL_LerpPoint (void) } static void -set_entity_model (entity_t *ent, int modelindex) +set_entity_model (int ent_ind, int modelindex) { - int i = ent - cl_entities; + entity_t *ent = cl_entities[ent_ind]; renderer_t *renderer = &ent->renderer; animation_t *animation = &ent->animation; - renderer->model = cl.model_precache[modelindex]; + renderer->model = cl_world.models.a[modelindex]; // automatic animation (torches, etc) can be either all together // or randomized if (renderer->model) { @@ -130,11 +148,12 @@ set_entity_model (entity_t *ent, int modelindex) animation->syncbase = 0.0; } } else { - cl_forcelink[i] = true; // hack to make null model players work + // hack to make null model players work + SET_ADD (&cl_forcelink, ent_ind); } animation->nolerp = 1; // don't try to lerp when the model has changed - if (i <= cl.maxclients) { - renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, i); + if (ent_ind <= cl.maxclients) { + renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, ent_ind); } } @@ -150,8 +169,6 @@ CL_RelinkEntities (void) int entvalid; int model_flags; - r_data->player_entity = &cl_entities[cl.viewentity]; - // determine partial update time frac = CL_LerpPoint (); @@ -180,7 +197,7 @@ CL_RelinkEntities (void) for (i = 1; i < cl.num_entities; i++) { new = &nq_entstates.frame[0 + cl.frameIndex][i]; old = &nq_entstates.frame[1 - cl.frameIndex][i]; - ent = &cl_entities[i]; + ent = CL_GetEntity (i); renderer = &ent->renderer; animation = &ent->animation; @@ -200,20 +217,24 @@ CL_RelinkEntities (void) continue; } - if (cl_forcelink[i]) + if (SET_TEST_MEMBER (&cl_forcelink, i)) { *old = *new; + } - if (cl_forcelink[i] || new->modelindex != old->modelindex) { + if (SET_TEST_MEMBER (&cl_forcelink, i) + || new->modelindex != old->modelindex) { old->modelindex = new->modelindex; - set_entity_model (ent, new->modelindex); + set_entity_model (i, new->modelindex); } animation->frame = new->frame; - if (cl_forcelink[i] || new->colormap != old->colormap) { + if (SET_TEST_MEMBER (&cl_forcelink, i) + || new->colormap != old->colormap) { old->colormap = new->colormap; renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, new->colormap); } - if (cl_forcelink[i] || new->skinnum != old->skinnum) { + if (SET_TEST_MEMBER (&cl_forcelink, i) + || new->skinnum != old->skinnum) { old->skinnum = new->skinnum; renderer->skinnum = new->skinnum; if (i <= cl.maxclients) { @@ -232,7 +253,7 @@ CL_RelinkEntities (void) model_flags = renderer->model->flags; } - if (cl_forcelink[i]) { + if (SET_TEST_MEMBER (&cl_forcelink, i)) { // The entity was not updated in the last message so move to the // final spot animation->pose1 = animation->pose2 = -1; @@ -242,7 +263,7 @@ CL_RelinkEntities (void) if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); } - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); } ent->old_origin = new->origin; } else { @@ -278,10 +299,10 @@ CL_RelinkEntities (void) = Transform_GetWorldPosition (ent->transform); if (!VectorCompare (org, ent->old_origin)) {//FIXME r_funcs->R_RemoveEfrags (ent); - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); } } else { - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); } } } @@ -303,8 +324,10 @@ CL_RelinkEntities (void) if (model_flags & ~EF_ROTATE) CL_ModelEffects (ent, i, new->glow_color, cl.time); - cl_forcelink[i] = false; + SET_REMOVE (&cl_forcelink, i); } + r_data->player_entity = CL_GetEntity (cl.viewentity); + cl.viewstate.player_entity = CL_GetEntity (cl.viewentity); cl.viewstate.player_origin - = Transform_GetWorldPosition (cl_entities[cl.viewentity].transform); + = Transform_GetWorldPosition (cl.viewstate.player_entity->transform); } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 2618706f9..e789b66ac 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -48,14 +48,16 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "compat.h" #include "sbar.h" +#include "client/chase.h" #include "client/particles.h" #include "client/temp_entities.h" +#include "client/world.h" -#include "client/chase.h" #include "nq/include/cl_skin.h" #include "nq/include/client.h" #include "nq/include/host.h" @@ -188,9 +190,9 @@ CL_ClearState (void) if (!sv.active) Host_ClearMemory (); - if (cl.edicts) - PL_Free (cl.edicts); - + if (cl.viewstate.weapon_entity) { + Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity); + } if (cl.players) { int i; @@ -202,6 +204,7 @@ CL_ClearState (void) __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); cl.viewstate.camera_transform = cam; + cl.viewstate.player_origin = (vec4f_t) {0, 0, 0, 1}; cl.viewstate.chase = 1; cl.viewstate.chasestate = &cl.chasestate; @@ -210,10 +213,6 @@ CL_ClearState (void) r_data->force_fullscreen = 0; r_data->lightstyle = cl.lightstyle; - CL_Init_Entity (&cl.viewent); - cl.viewstate.weapon_entity = &cl.viewent; - r_data->view_model = &cl.viewent; - SZ_Clear (&cls.message); CL_ClearTEnts (); @@ -221,6 +220,10 @@ CL_ClearState (void) r_funcs->R_ClearState (); CL_ClearEnts (); + + cl.viewstate.weapon_entity = Scene_CreateEntity (cl_world.scene); + CL_Init_Entity (cl.viewstate.weapon_entity); + r_data->view_model = cl.viewstate.weapon_entity; } /* @@ -276,7 +279,7 @@ CL_Disconnect (void) Host_ShutdownServer (false); } - cl.worldmodel = NULL; + cl_world.worldmodel = NULL; cl.intermission = 0; cl.viewstate.intermission = 0; } @@ -389,18 +392,18 @@ CL_NextDemo (void) static void pointfile_f (void) { - CL_LoadPointFile (cl.worldmodel); + CL_LoadPointFile (cl_world.worldmodel); } static void CL_PrintEntities_f (void) { - entity_t *ent; int i; - for (i = 0, ent = cl_entities; i < cl.num_entities; i++, ent++) { + for (i = 0; i < cl.num_entities; i++) { + entity_t *ent = cl_entities[i]; Sys_Printf ("%3i:", i); - if (!ent->renderer.model) { + if (!ent || !ent->renderer.model) { Sys_Printf ("EMPTY\n"); continue; } @@ -422,8 +425,8 @@ CL_ReadFromServer (void) { int ret; TEntContext_t tentCtx = { - Transform_GetWorldPosition (cl_entities[cl.viewentity].transform), - cl.worldmodel, cl.viewentity + cl.viewstate.player_origin, + cl.viewentity }; cl.oldtime = cl.time; @@ -571,6 +574,7 @@ CL_Init (cbuf_t *cbuf) CL_Init_Input (cbuf); CL_Particles_Init (); CL_TEnts_Init (); + CL_World_Init (); CL_ClearState (); V_Init (&cl.viewstate); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index f8e052151..b6bcba5b9 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -51,10 +51,13 @@ #include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_* #include "QF/va.h" +#include "QF/scene/scene.h" + #include "QF/plugin/vid_render.h" #include "QF/scene/entity.h" #include "client/temp_entities.h" +#include "client/world.h" #include "compat.h" #include "sbar.h" @@ -125,24 +128,6 @@ const char *svc_strings[] = { dstring_t *centerprint; -static void -CL_LoadSky (void) -{ - plitem_t *item; - const char *name = 0; - - if (!cl.worldspawn) { - r_funcs->R_LoadSkys (0); - return; - } - if ((item = PL_ObjectForKey (cl.worldspawn, "sky")) // Q2/DarkPlaces - || (item = PL_ObjectForKey (cl.worldspawn, "skyname")) // old QF - || (item = PL_ObjectForKey (cl.worldspawn, "qlsky"))) /* QuakeLives */ { - name = PL_String (item); - } - r_funcs->R_LoadSkys (name); -} - /* CL_EntityNum @@ -263,72 +248,13 @@ CL_KeepaliveMessage (void) SZ_Clear (&cls.message); } -static void -map_cfg (const char *mapname, int all) -{ - char *name = malloc (strlen (mapname) + 4 + 1); - cbuf_t *cbuf = Cbuf_New (&id_interp); - QFile *f; - - QFS_StripExtension (mapname, name); - strcat (name, ".cfg"); - f = QFS_FOpenFile (name); - if (f) { - Qclose (f); - Cmd_Exec_File (cbuf, name, 1); - } else { - Cmd_Exec_File (cbuf, "maps_default.cfg", 1); - } - if (all) { - Cbuf_Execute_Stack (cbuf); - } else { - Cbuf_Execute_Sets (cbuf); - } - free (name); - Cbuf_Delete (cbuf); -} - -static plitem_t * -map_ent (const char *mapname) -{ - static progs_t edpr; - char *name = malloc (strlen (mapname) + 4 + 1); - char *buf; - plitem_t *edicts = 0; - QFile *ent_file; - - QFS_StripExtension (mapname, name); - strcat (name, ".ent"); - ent_file = QFS_VOpenFile (name, 0, cl.model_precache[1]->vpath); - if ((buf = (char *) QFS_LoadFile (ent_file, 0))) { - edicts = ED_Parse (&edpr, buf); - free (buf); - } else { - edicts = ED_Parse (&edpr, cl.model_precache[1]->brush.entities); - } - free (name); - return edicts; -} - static void CL_NewMap (const char *mapname) { - r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels); Con_NewMap (); Hunk_Check (0); // make sure nothing is hurt Sbar_CenterPrint (0); - - if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) { - cl.edicts = map_ent (mapname); - if (cl.edicts) { - cl.worldspawn = PL_ObjectAtIndex (cl.edicts, 0); - CL_LoadSky (); - if (r_funcs->Fog_ParseWorldspawn) - r_funcs->Fog_ParseWorldspawn (cl.worldspawn); - } - } - - map_cfg (mapname, 1); + CL_World_NewMap (mapname, 0); } static void @@ -338,6 +264,7 @@ CL_ParseServerInfo (void) char sound_precache[MAX_SOUNDS][MAX_QPATH]; const char *str; int i; + int nummodels; Sys_MaskPrintf (SYS_dev, "Serverinfo packet received.\n"); @@ -394,16 +321,17 @@ CL_ParseServerInfo (void) // needlessly purge it // precache models - memset (cl.model_precache, 0, sizeof (cl.model_precache)); - for (cl.nummodels = 1;; cl.nummodels++) { + cl_world.models.size = 0; + DARRAY_APPEND (&cl_world.models, 0); // ind 0 is null model + for (nummodels = 1;; nummodels++) { str = MSG_ReadString (net_message); if (!str[0]) break; - if (cl.nummodels >= MAX_MODELS) { + if (nummodels >= MAX_MODELS) { Sys_Printf ("Server sent too many model precaches\n"); goto done; } - strcpy (model_precache[cl.nummodels], str); + strcpy (model_precache[nummodels], str); Mod_TouchModel (str); } @@ -421,12 +349,12 @@ CL_ParseServerInfo (void) } // now we try to load everything else until a cache allocation fails - if (model_precache[1]) - map_cfg (model_precache[1], 0); + CL_MapCfg (model_precache[1]); - for (i = 1; i < cl.nummodels; i++) { - cl.model_precache[i] = Mod_ForName (model_precache[i], false); - if (cl.model_precache[i] == NULL) { + for (i = 1; i < nummodels; i++) { + DARRAY_APPEND (&cl_world.models, + Mod_ForName (model_precache[i], false)); + if (cl_world.models.a[i] == NULL) { Sys_Printf ("Model %s not found\n", model_precache[i]); goto done; } @@ -439,8 +367,8 @@ CL_ParseServerInfo (void) } // local state - cl_entities[0].renderer.model = cl.worldmodel = cl.model_precache[1]; - cl.chasestate.worldmodel = cl.worldmodel; + cl_world.worldmodel = cl_world.models.a[1]; + cl.chasestate.worldmodel = cl_world.worldmodel; if (!centerprint) centerprint = dstring_newstr (); else @@ -600,44 +528,10 @@ CL_ParseUpdate (int bits) //VectorCopy (state->msg_angles[0], state->msg_angles[1]); //CL_TransformEntity (ent, state->msg_angles[0]); //state->forcelink = true; - cl_forcelink[num] = true; + SET_ADD (&cl_forcelink, num); } } -static void -CL_ParseBaseline (entity_state_t *baseline, int version) -{ - int bits = 0; - - if (version == 2) - bits = MSG_ReadByte (net_message); - - if (bits & B_LARGEMODEL) - baseline->modelindex = MSG_ReadShort (net_message); - else - baseline->modelindex = MSG_ReadByte (net_message); - - if (bits & B_LARGEFRAME) - baseline->frame = MSG_ReadShort (net_message); - else - baseline->frame = MSG_ReadByte (net_message); - - baseline->colormap = MSG_ReadByte (net_message); - baseline->skinnum = MSG_ReadByte (net_message); - - MSG_ReadCoordAngleV (net_message, &baseline->origin[0], baseline->angles); - baseline->origin[3] = 1;//FIXME - - if (bits & B_ALPHA) - baseline->alpha = MSG_ReadByte (net_message); - else - baseline->alpha = 255;//FIXME alpha - baseline->scale = 16; - baseline->glow_size = 0; - baseline->glow_color = 254; - baseline->colormod = 255; -} - /* CL_ParseClientdata @@ -723,7 +617,7 @@ CL_ParseClientdata (void) if (cl.stats[STAT_WEAPON] != i) { cl.stats[STAT_WEAPON] = i; Sbar_Changed (); - cl.viewstate.weapon_model = cl.model_precache[cl.stats[STAT_WEAPON]]; + cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]]; } i = (short) MSG_ReadShort (net_message); @@ -779,38 +673,13 @@ CL_ParseClientdata (void) cl.stats[STAT_WEAPONFRAME] |= MSG_ReadByte (net_message) << 8; if (bits & SU_WEAPONALPHA) { byte alpha = MSG_ReadByte (net_message); - cl.viewent.renderer.colormod[3] = ENTALPHA_DECODE (alpha); + float a = ENTALPHA_DECODE (alpha); + cl.viewstate.weapon_entity->renderer.colormod[3] = a; } else { - cl.viewent.renderer.colormod[3] = 1.0; + cl.viewstate.weapon_entity->renderer.colormod[3] = 1; } } -static void -CL_ParseStatic (int version) -{ - entity_state_t baseline; - entity_t *ent; - - ent = r_funcs->R_AllocEntity (); - CL_Init_Entity (ent); - - CL_ParseBaseline (&baseline, version); - - // copy it to the current state - //FIXME alpha & lerp - ent->renderer.model = cl.model_precache[baseline.modelindex]; - ent->animation.frame = baseline.frame; - ent->renderer.skin = 0; - ent->renderer.skinnum = baseline.skinnum; - VectorCopy (ent_colormod[baseline.colormod], ent->renderer.colormod); - ent->renderer.colormod[3] = ENTALPHA_DECODE (baseline.alpha); - - CL_TransformEntity (ent, baseline.scale / 16.0, baseline.angles, - baseline.origin); - - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); -} - static void CL_ParseStaticSound (int version) { @@ -850,8 +719,8 @@ CL_ParseServerMessage (void) cl.last_servermessage = realtime; TEntContext_t tentCtx = { - Transform_GetWorldPosition (cl_entities[cl.viewentity].transform), - cl.worldmodel, cl.viewentity + cl.viewstate.player_origin, + cl.viewentity }; // if recording demos, copy the message out @@ -921,7 +790,6 @@ CL_ParseServerMessage (void) case svc_setview: cl.viewentity = MSG_ReadShort (net_message); - cl.viewstate.player_entity = &cl_entities[cl.viewentity]; break; case svc_sound: @@ -1035,7 +903,7 @@ CL_ParseServerMessage (void) Host_Error ("CL_ParseServerMessage: svc_updatecolors > " "MAX_SCOREBOARD"); } else { - entity_t *ent = &cl_entities[i+1]; + entity_t *ent = CL_GetEntity (i + 1); byte col = MSG_ReadByte (net_message); byte top = col >> 4; byte bot = col & 0xf; @@ -1061,7 +929,7 @@ CL_ParseServerMessage (void) break; case svc_spawnstatic: - CL_ParseStatic (1); + CL_ParseStatic (net_message, 1); break; // svc_spawnbinary @@ -1069,7 +937,7 @@ CL_ParseServerMessage (void) case svc_spawnbaseline: i = MSG_ReadShort (net_message); // must use CL_EntityNum () to force cl.num_entities up - CL_ParseBaseline (CL_EntityNum (i), 1); + CL_ParseBaseline (net_message, CL_EntityNum (i), 1); break; case svc_temp_entity: @@ -1205,10 +1073,10 @@ CL_ParseServerMessage (void) case svc_spawnbaseline2: i = MSG_ReadShort (net_message); // must use CL_EntityNum() to force cl.num_entities up - CL_ParseBaseline (CL_EntityNum(i), 2); + CL_ParseBaseline (net_message, CL_EntityNum(i), 2); break; case svc_spawnstatic2: - CL_ParseStatic (2); + CL_ParseStatic (net_message, 2); break; case svc_spawnstaticsound2: CL_ParseStaticSound (2); diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 927608352..7c2a033f7 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -51,6 +51,8 @@ #include "sbar.h" +#include "client/world.h" + #include "nq/include/client.h" static view_t *net_view; @@ -75,11 +77,11 @@ SCR_CShift (void) mleaf_t *leaf; int contents = CONTENTS_EMPTY; - if (cls.state == ca_active && cl.worldmodel) { + if (cls.state == ca_active && cl_world.worldmodel) { vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); //FIXME - leaf = Mod_PointInLeaf (&origin[0], cl.worldmodel); + leaf = Mod_PointInLeaf (&origin[0], cl_world.worldmodel); contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); diff --git a/nq/source/host.c b/nq/source/host.c index 9ecc52069..e4007dd37 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -60,6 +60,7 @@ #include "compat.h" #include "client/chase.h" +#include "client/world.h" #include "nq/include/host.h" #include "nq/include/server.h" @@ -612,7 +613,7 @@ Host_ClientFrame (void) vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - l = Mod_PointInLeaf (&origin[0], cl.worldmodel);//FIXME + l = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);//FIXME if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 3c51cb894..e58098241 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -50,6 +50,8 @@ #include "QF/sys.h" #include "QF/va.h" +#include "client/world.h" + #include "compat.h" #include "world.h" @@ -1320,7 +1322,7 @@ Host_Viewmodel_f (void) } SVfloat (e, frame) = 0; - cl.model_precache[(int) SVfloat (e, modelindex)] = m; + cl_world.models.a[(int) SVfloat (e, modelindex)] = m; } static void @@ -1333,7 +1335,7 @@ Host_Viewframe_f (void) e = FindViewthing (); if (!e) return; - m = cl.model_precache[(int) SVfloat (e, modelindex)]; + m = cl_world.models.a[(int) SVfloat (e, modelindex)]; f = atoi (Cmd_Argv (1)); if (f >= m->numframes) @@ -1366,7 +1368,7 @@ Host_Viewnext_f (void) e = FindViewthing (); if (!e) return; - m = cl.model_precache[(int) SVfloat (e, modelindex)]; + m = cl_world.models.a[(int) SVfloat (e, modelindex)]; SVfloat (e, frame) = SVfloat (e, frame) + 1; if (SVfloat (e, frame) >= m->numframes) @@ -1385,7 +1387,7 @@ Host_Viewprev_f (void) if (!e) return; - m = cl.model_precache[(int) SVfloat (e, modelindex)]; + m = cl_world.models.a[(int) SVfloat (e, modelindex)]; SVfloat (e, frame) = SVfloat (e, frame) - 1; if (SVfloat (e, frame) < 0) diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index 50dd443d9..d8a0a601e 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -36,12 +36,16 @@ #include "QF/plugin/vid_render.h" +#include "client/world.h" + #include "nq/include/host.h" #include "nq/include/server.h" client_state_t cl; client_static_t cls; +worldscene_t cl_world; + cvar_t *cl_name; cvar_t *cl_writecfg; cvar_t *demo_speed; diff --git a/qw/include/cl_ents.h b/qw/include/cl_ents.h index b56e162d9..53ec080f7 100644 --- a/qw/include/cl_ents.h +++ b/qw/include/cl_ents.h @@ -41,12 +41,9 @@ void CL_ParsePacketEntities (qboolean delta); void CL_SetSolidEntities (void); void CL_ParsePlayerinfo (void); void CL_Ents_Init (void); +entity_t *CL_GetEntity (int num); extern struct cvar_s *cl_deadbodyfilter; extern struct cvar_s *cl_gibfilter; -extern entity_t cl_player_ents[]; -extern entity_t cl_flag_ents[]; -extern entity_t cl_packet_ents[]; - #endif diff --git a/qw/include/client.h b/qw/include/client.h index e6410ecaa..6355b1921 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -222,14 +222,10 @@ typedef struct client_state_s { char model_name[MAX_MODELS][MAX_QPATH]; char sound_name[MAX_SOUNDS][MAX_QPATH]; - struct model_s *model_precache[MAX_MODELS]; struct sfx_s *sound_precache[MAX_SOUNDS]; int nummodels; int numsounds; - struct plitem_s *edicts; - struct plitem_s *worldspawn; - char levelname[40]; // for display on solo scoreboard int spectator; int playernum; @@ -247,9 +243,7 @@ typedef struct client_state_s { int fbskins; // refresh related state - struct model_s *worldmodel; // cl_entitites[0].model int num_entities; // held in cl_entities array - entity_t viewent; // the weapon model int cdtrack; // cd audio @@ -288,10 +282,7 @@ extern struct cvar_s *cl_fb_players; extern client_state_t cl; -typedef struct entitystateset_s DARRAY_TYPE (struct entity_state_s) - entitystateset_t; -extern entitystateset_t cl_static_entities; -extern entity_t cl_entities[512]; +extern entity_t *cl_entities[512]; extern byte cl_entity_valid[2][512]; extern qboolean nomaster; diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index d03e7b4b5..2a5069db4 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -56,6 +56,8 @@ #include "compat.h" +#include "client/world.h" + #include "qw/include/cl_cam.h" #include "qw/include/cl_demo.h" #include "qw/include/cl_ents.h" @@ -633,8 +635,8 @@ demo_default_name (const char *argv1) time (&tim); strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim)); - // the leading path-name is to be removed from cl.worldmodel->name - mapname = QFS_SkipPath (cl.worldmodel->path); + // the leading path-name is to be removed from cl_world.worldmodel->name + mapname = QFS_SkipPath (cl_world.worldmodel->path); // the map name is cut off after any "." because this would prevent // an extension being appended diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index a47edb4af..550a8b308 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -45,6 +45,7 @@ #include "client/temp_entities.h" #include "client/view.h" +#include "client/world.h" #include "qw/msg_ucmd.h" #include "qw/pmove.h" @@ -481,7 +482,7 @@ CL_ParsePlayerinfo (void) byte val; entity_t *ent; - ent = &cl_player_ents[num]; + ent = CL_GetEntity (num + 1); bits = MSG_ReadByte (net_message); if (bits & PF_ALPHA) { val = MSG_ReadByte (net_message); @@ -529,7 +530,7 @@ CL_SetSolidEntities (void) frame_t *frame; packet_entities_t *pak; - pmove.physents[0].model = cl.worldmodel; + pmove.physents[0].model = cl_world.worldmodel; VectorZero (pmove.physents[0].origin); VectorZero (pmove.physents[0].angles); pmove.physents[0].info = 0; @@ -543,17 +544,17 @@ CL_SetSolidEntities (void) if (!state->modelindex) continue; - if (!cl.model_precache[state->modelindex]) + if (!cl_world.models.a[state->modelindex]) continue; - if (cl.model_precache[state->modelindex]->brush.hulls[1].firstclipnode - || cl.model_precache[state->modelindex]->clipbox) { + if (cl_world.models.a[state->modelindex]->brush.hulls[1].firstclipnode + || cl_world.models.a[state->modelindex]->clipbox) { if (pmove.numphysent == MAX_PHYSENTS) { Sys_Printf ("WARNING: entity physent overflow, email " "quakeforge-devel@lists.quakeforge.net\n"); break; } pmove.physents[pmove.numphysent].model = - cl.model_precache[state->modelindex]; + cl_world.models.a[state->modelindex]; VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin); VectorCopy (state->angles, diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 84bd9ba72..19cc8f9ac 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -42,6 +42,7 @@ #include "QF/sys.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "compat.h" #include "d_iface.h" @@ -50,6 +51,7 @@ #include "client/locs.h" #include "client/temp_entities.h" #include "client/view.h" +#include "client/world.h" #include "qw/bothdefs.h" #include "qw/msg_ucmd.h" @@ -62,9 +64,8 @@ #include "qw/include/cl_pred.h" #include "qw/include/host.h" -entity_t cl_player_ents[MAX_CLIENTS]; -entity_t cl_flag_ents[MAX_CLIENTS]; -entity_t cl_entities[512]; // FIXME: magic number +entity_t *cl_flag_ents[MAX_CLIENTS]; +entity_t *cl_entities[512]; // FIXME: magic number byte cl_entity_valid[2][512]; void @@ -72,15 +73,32 @@ CL_ClearEnts (void) { size_t i; + for (i = 0; i < MAX_CLIENTS; i++) { + if (cl_flag_ents[i]) { + Scene_DestroyEntity (cl_world.scene, cl_flag_ents[i]); + cl_flag_ents[i] = 0; + } + } + + for (i = 0; i < 512; i++) { + if (cl_entities[i]) { + Scene_DestroyEntity (cl_world.scene, cl_entities[i]); + cl_entities[i] = 0; + } + } i = qw_entstates.num_frames * qw_entstates.num_entities; memset (qw_entstates.frame[0], 0, i * sizeof (entity_state_t)); memset (cl_entity_valid, 0, sizeof (cl_entity_valid)); - for (i = 0; i < sizeof (cl_entities) / sizeof (cl_entities[0]); i++) - CL_Init_Entity (&cl_entities[i]); - for (i = 0; i < sizeof (cl_flag_ents) / sizeof (cl_flag_ents[0]); i++) - CL_Init_Entity (&cl_flag_ents[i]); - for (i = 0; i < sizeof (cl_player_ents) / sizeof (cl_player_ents[0]); i++) - CL_Init_Entity (&cl_player_ents[i]); +} + +entity_t * +CL_GetEntity (int num) +{ + if (!cl_entities[num]) { + cl_entities[num] = Scene_CreateEntity (cl_world.scene); + CL_Init_Entity (cl_entities[num]); + } + return cl_entities[num]; } // Hack hack hack @@ -110,7 +128,7 @@ set_entity_model (entity_t *ent, int modelindex) { renderer_t *renderer = &ent->renderer; animation_t *animation = &ent->animation; - renderer->model = cl.model_precache[modelindex]; + renderer->model = cl_world.models.a[modelindex]; // automatic animation (torches, etc) can be either all together // or randomized if (renderer->model) { @@ -134,10 +152,10 @@ CL_LinkPacketEntities (void) animation_t *animation; frac = 1; - for (i = 0; i < 512; i++) { + for (i = MAX_CLIENTS + 1; i < 512; i++) { new = &qw_entstates.frame[cl.link_sequence & UPDATE_MASK][i]; old = &qw_entstates.frame[cl.prev_sequence & UPDATE_MASK][i]; - ent = &cl_entities[i]; + ent = CL_GetEntity (i); renderer = &ent->renderer; animation = &ent->animation; forcelink = cl_entity_valid[0][i] != cl_entity_valid[1][i]; @@ -216,7 +234,7 @@ CL_LinkPacketEntities (void) if (ent->visibility.efrag) { r_funcs->R_RemoveEfrags (ent); } - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); } } else { vec4f_t delta = new->origin - old->origin; @@ -248,15 +266,15 @@ CL_LinkPacketEntities (void) = Transform_GetWorldPosition (ent->transform); if (!VectorCompare (org, ent->old_origin)) {//FIXME r_funcs->R_RemoveEfrags (ent); - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); } } else { - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); } } } if (!ent->visibility.efrag) { - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); } // rotate binary objects locally @@ -288,7 +306,7 @@ CL_UpdateFlagModels (entity_t *ent, int key) float f; entity_t *fent; - fent = &cl_flag_ents[key]; + fent = cl_flag_ents[key]; if (!fent->active) { return; @@ -322,7 +340,7 @@ CL_AddFlagModels (entity_t *ent, int team, int key) { entity_t *fent; - fent = &cl_flag_ents[key]; + fent = cl_flag_ents[key]; if (cl_flagindex == -1) { fent->active = 0; @@ -336,7 +354,7 @@ CL_AddFlagModels (entity_t *ent, int team, int key) } CL_UpdateFlagModels (ent, key); - fent->renderer.model = cl.model_precache[cl_flagindex]; + fent->renderer.model = cl_world.models.a[cl_flagindex]; fent->renderer.skinnum = team; return fent; @@ -347,7 +365,7 @@ CL_RemoveFlagModels (int key) { entity_t *fent; - fent = &cl_flag_ents[key]; + fent = cl_flag_ents[key]; fent->active = 0; Transform_SetParent (fent->transform, 0); } @@ -380,7 +398,7 @@ CL_LinkPlayers (void) for (j = 0, player = cl.players, state = frame->playerstate; j < MAX_CLIENTS; j++, player++, state++) { - ent = &cl_player_ents[j]; + ent = CL_GetEntity (j + 1); if (ent->visibility.efrag) r_funcs->R_RemoveEfrags (ent); if (player->flag_ent && player->flag_ent->visibility.efrag) { @@ -395,7 +413,8 @@ CL_LinkPlayers (void) // spawn light flashes, even ones coming from invisible objects if (j == cl.playernum) { org = cl.viewstate.player_origin; - r_data->player_entity = &cl_player_ents[j]; + r_data->player_entity = ent; + cl.viewstate.player_entity = ent; clientplayer = true; } else { org = state->pls.es.origin; @@ -453,8 +472,8 @@ CL_LinkPlayers (void) ang[ROLL] = V_CalcRoll (ang, state->pls.es.velocity) * 4.0; if (ent->renderer.model - != cl.model_precache[state->pls.es.modelindex]) { - ent->renderer.model = cl.model_precache[state->pls.es.modelindex]; + != cl_world.models.a[state->pls.es.modelindex]) { + ent->renderer.model = cl_world.models.a[state->pls.es.modelindex]; ent->animation.nolerp = 1; } ent->animation.frame = state->pls.es.frame; @@ -492,10 +511,10 @@ CL_LinkPlayers (void) } // stuff entity in map - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); if (player->flag_ent) { CL_UpdateFlagModels (ent, j); - r_funcs->R_AddEfrags (&cl.worldmodel->brush, player->flag_ent); + r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, player->flag_ent); } } } @@ -516,7 +535,7 @@ CL_EmitEntities (void) return; TEntContext_t tentCtx = { - cl.viewstate.player_origin, cl.worldmodel, cl.viewentity + cl.viewstate.player_origin, cl.viewentity }; CL_LinkPlayers (); @@ -530,5 +549,4 @@ CL_EmitEntities (void) void CL_Ents_Init (void) { - r_data->view_model = &cl.viewent; } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 3724a5a41..6b4bb9f18 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -91,6 +91,7 @@ #include "QF/plugin/console.h" #include "QF/scene/transform.h" +#include "QF/scene/scene.h" #include "buildnum.h" #include "compat.h" @@ -99,6 +100,7 @@ #include "client/particles.h" #include "client/temp_entities.h" #include "client/view.h" +#include "client/world.h" #include "qw/bothdefs.h" #include "qw/pmove.h" @@ -229,7 +231,7 @@ CL_Quit_f (void) static void pointfile_f (void) { - CL_LoadPointFile (cl.worldmodel); + CL_LoadPointFile (cl_world.worldmodel); } static void @@ -385,6 +387,9 @@ CL_ClearState (void) S_StopAllSounds (); + if (cl.viewstate.weapon_entity) { + Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity); + } // wipe the entire cl structure if (cl.serverinfo) Info_Destroy (cl.serverinfo); @@ -402,7 +407,6 @@ CL_ClearState (void) cl.chasestate.viewstate = &cl.viewstate; cl.viewstate.punchangle = (vec4f_t) {0, 0, 0, 1}; - // Note: we should probably hack around this and give diff values for // diff gamedirs cl.fpd = FPD_DEFAULT; @@ -412,9 +416,6 @@ CL_ClearState (void) cl.frames[i].packet_entities.entities = qw_entstates.frame[i]; cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING, 0); - CL_Init_Entity (&cl.viewent); - cl.viewstate.weapon_entity = &cl.viewent; - Sys_MaskPrintf (SYS_dev, "Clearing memory\n"); VID_ClearMemory (); Mod_ClearAll (); @@ -424,6 +425,10 @@ CL_ClearState (void) CL_ClearEnts (); CL_ClearTEnts (); + cl.viewstate.weapon_entity = Scene_CreateEntity (cl_world.scene); + CL_Init_Entity (cl.viewstate.weapon_entity); + r_data->view_model = cl.viewstate.weapon_entity; + r_funcs->R_ClearState (); SZ_Clear (&cls.netchan.message); @@ -519,7 +524,7 @@ CL_Disconnect (void) Info_Destroy (cl.players[i].userinfo); memset (&cl.players[i], 0, sizeof (cl.players[i])); } - cl.worldmodel = NULL; + cl_world.worldmodel = NULL; cl.validsequence = 0; } @@ -1216,6 +1221,7 @@ CL_Init (void) CL_Ents_Init (); CL_Particles_Init (); CL_TEnts_Init (); + CL_World_Init (); CL_ClearState (); Pmove_Init (); @@ -1725,7 +1731,7 @@ Host_Frame (float time) vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - l = Mod_PointInLeaf (&origin[0], cl.worldmodel);//FIXME + l = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);//FIXME if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index e73c7ad3d..e585dbc48 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -61,12 +61,15 @@ #include "QF/teamplay.h" #include "QF/va.h" +#include "QF/scene/scene.h" + #include "compat.h" #include "sbar.h" #include "client/effects.h" #include "client/temp_entities.h" #include "client/view.h" +#include "client/world.h" #include "qw/bothdefs.h" #include "qw/pmove.h" @@ -170,40 +173,6 @@ int packet_latency[NET_TIMINGS]; extern cvar_t *hud_scoreboard_uid; -entitystateset_t cl_static_entities = DARRAY_STATIC_INIT (32); - -static void -CL_LoadSky (void) -{ - plitem_t *item; - const char *name = 0; - static const char *sky_keys[] = { - "sky", // Q2/DarkPlaces - "skyname", // old QF - "qlsky", // QuakeLives - 0 - }; - - // R_LoadSkys does the right thing with null pointers. - if (cl.serverinfo) { - name = Info_ValueForKey (cl.serverinfo, "sky"); - } - - if (!name) { - if (!cl.worldspawn) { - r_funcs->R_LoadSkys (0); - return; - } - for (const char **key = sky_keys; *key; key++) { - if ((item = PL_ObjectForKey (cl.worldspawn, *key))) { - name = PL_String (item); - break; - } - } - } - r_funcs->R_LoadSkys (name); -} - int CL_CalcNet (void) { @@ -290,49 +259,20 @@ CL_CheckOrDownloadFile (const char *filename) return false; } -static plitem_t * -map_ent (const char *mapname) -{ - static progs_t edpr; - char *name = malloc (strlen (mapname) + 4 + 1); - char *buf; - plitem_t *edicts = 0; - QFile *ent_file; - - QFS_StripExtension (mapname, name); - strcat (name, ".ent"); - ent_file = QFS_VOpenFile (name, 0, cl.model_precache[1]->vpath); - if ((buf = (char *) QFS_LoadFile (ent_file, 0))) { - edicts = ED_Parse (&edpr, buf); - free (buf); - } else { - edicts = ED_Parse (&edpr, cl.model_precache[1]->brush.entities); - } - free (name); - return edicts; -} - static void CL_NewMap (const char *mapname) { - cl_static_entities.size = 0; - r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels); Team_NewMap (); Con_NewMap (); Hunk_Check (0); // make sure nothing is hurt Sbar_CenterPrint (0); - if (cl.model_precache[1] && cl.model_precache[1]->brush.entities) { - cl.edicts = map_ent (mapname); - if (cl.edicts) { - cl.worldspawn = PL_ObjectAtIndex (cl.edicts, 0); - CL_LoadSky (); - if (r_funcs->Fog_ParseWorldspawn) - r_funcs->Fog_ParseWorldspawn (cl.worldspawn); - } + const char *skyname = 0; + // R_LoadSkys does the right thing with null pointers. + if (cl.serverinfo) { + skyname = Info_ValueForKey (cl.serverinfo, "sky"); } - - map_cfg (mapname, 1); + CL_World_NewMap (mapname, skyname); } static void @@ -357,7 +297,7 @@ Model_NextDownload (void) } if (cl.model_name[1]) - map_cfg (cl.model_name[1], 0); + CL_MapCfg (cl.model_name[1]); for (i = 1; i < cl.nummodels; i++) { const char *info_key = 0; @@ -365,9 +305,10 @@ Model_NextDownload (void) if (!cl.model_name[i][0]) break; - cl.model_precache[i] = Mod_ForName (cl.model_name[i], false); + DARRAY_APPEND (&cl_world.models, + Mod_ForName (cl.model_name[i], false)); - if (!cl.model_precache[i]) { + if (!cl_world.models.a[i]) { Sys_Printf ("\nThe required model file '%s' could not be found or " "downloaded.\n\n", cl.model_name[i]); Sys_Printf ("You may need to download or purchase a %s client " @@ -378,18 +319,18 @@ Model_NextDownload (void) } if (strequal (cl.model_name[i], "progs/player.mdl") - && cl.model_precache[i]->type == mod_alias) { + && cl_world.models.a[i]->type == mod_alias) { info_key = pmodel_name; - //XXX mod_funcs->Skin_Player_Model (cl.model_precache[i]); + //XXX mod_funcs->Skin_Player_Model (cl_world.models.a[i]); } if (strequal (cl.model_name[i], "progs/eyes.mdl") - && cl.model_precache[i]->type == mod_alias) + && cl_world.models.a[i]->type == mod_alias) info_key = emodel_name; if (info_key && cl_model_crcs->int_val) { - aliashdr_t *ahdr = cl.model_precache[i]->aliashdr; + aliashdr_t *ahdr = cl_world.models.a[i]->aliashdr; if (!ahdr) - ahdr = Cache_Get (&cl.model_precache[i]->cache); + ahdr = Cache_Get (&cl_world.models.a[i]->cache); Info_SetValueForKey (cls.userinfo, info_key, va (0, "%d", ahdr->crc), 0); @@ -398,14 +339,14 @@ Model_NextDownload (void) SZ_Print (&cls.netchan.message, va (0, "setinfo %s %d", info_key, ahdr->crc)); } - if (!cl.model_precache[i]->aliashdr) - Cache_Release (&cl.model_precache[i]->cache); + if (!cl_world.models.a[i]->aliashdr) + Cache_Release (&cl_world.models.a[i]->cache); } } // Something went wrong (probably in the server, probably a TF server) // We need to disconnect gracefully. - if (!cl.model_precache[1]) { + if (!cl_world.models.a[1]) { Sys_Printf ("\nThe server has failed to provide the map name.\n\n"); Sys_Printf ("Disconnecting to prevent a crash.\n\n"); CL_Disconnect (); @@ -413,8 +354,8 @@ Model_NextDownload (void) } // all done - cl.worldmodel = cl.model_precache[1]; - cl.chasestate.worldmodel = cl.worldmodel; + cl_world.worldmodel = cl_world.models.a[1]; + cl.chasestate.worldmodel = cl_world.worldmodel; CL_NewMap (cl.model_name[1]); // done with modellist, request first of static signon messages @@ -422,7 +363,7 @@ Model_NextDownload (void) MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va (0, prespawn_name, cl.servercount, - cl.worldmodel->brush.checksum2)); + cl_world.worldmodel->brush.checksum2)); } } @@ -453,7 +394,8 @@ Sound_NextDownload (void) } // done with sounds, request models now - memset (cl.model_precache, 0, sizeof (cl.model_precache)); + cl_world.models.size = 0; + DARRAY_APPEND (&cl_world.models, 0);// ind 0 is null model cl_playerindex = -1; cl_flagindex = -1; cl_h_playerindex = -1; @@ -832,7 +774,6 @@ CL_ParseServerData (void) } cl.viewentity = cl.playernum + 1; - cl.viewstate.player_entity = &cl_entities[cl.viewentity]; cl.viewstate.bob_enabled = !cl.spectator; // get the full level name @@ -957,54 +898,6 @@ CL_ParseModellist (void) Model_NextDownload (); } -static void -CL_ParseBaseline (entity_state_t *es) -{ - es->modelindex = MSG_ReadByte (net_message); - es->frame = MSG_ReadByte (net_message); - es->colormap = MSG_ReadByte (net_message); - es->skinnum = MSG_ReadByte (net_message); - - MSG_ReadCoordAngleV (net_message, &es->origin[0], es->angles);//FIXME - es->origin[3] = 1; - - // LordHavoc: set up baseline to for new effects (alpha, colormod, etc) - es->colormod = 255; - es->alpha = 255; - es->scale = 16; - es->glow_size = 0; - es->glow_color = 254; -} - -/* - CL_ParseStatic - - Static entities are non-interactive world objects - like torches -*/ -static void -CL_ParseStatic (void) -{ - entity_t *ent; - entity_state_t es; - - CL_ParseBaseline (&es); - - ent = r_funcs->R_AllocEntity (); - CL_Init_Entity (ent); - - DARRAY_APPEND (&cl_static_entities, es); - - // copy it to the current state - ent->renderer.model = cl.model_precache[es.modelindex]; - ent->animation.frame = es.frame; - ent->renderer.skinnum = es.skinnum; - - CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin); - - r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent); -} - static void CL_ParseStaticSound (void) { @@ -1275,7 +1168,7 @@ CL_SetStat (int stat, int value) break; } cl.stats[stat] = value; - cl.viewstate.weapon_model = cl.model_precache[cl.stats[STAT_WEAPON]]; + cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]]; } static void @@ -1318,7 +1211,7 @@ CL_ParseServerMessage (void) const char *str; static dstring_t *stuffbuf; TEntContext_t tentCtx = { - cl.viewstate.player_origin, cl.worldmodel, cl.viewentity + cl.viewstate.player_origin, cl.viewentity }; received_framecount = host_framecount; @@ -1513,14 +1406,14 @@ CL_ParseServerMessage (void) break; case svc_spawnstatic: - CL_ParseStatic (); + CL_ParseStatic (net_message, 1); break; // svc_spawnbinary case svc_spawnbaseline: i = MSG_ReadShort (net_message); - CL_ParseBaseline (&qw_entstates.baseline[i]); + CL_ParseBaseline (net_message, &qw_entstates.baseline[i], 1); break; case svc_temp_entity: diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 3bdef1963..5e3978e5b 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -51,6 +51,7 @@ #include "client/hud.h" #include "client/view.h" +#include "client/world.h" #include "qw/include/client.h" #include "qw/include/cl_parse.h" @@ -77,11 +78,11 @@ SCR_CShift (void) mleaf_t *leaf; int contents = CONTENTS_EMPTY; - if (cls.state == ca_active && cl.worldmodel) { + if (cls.state == ca_active && cl_world.worldmodel) { vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); //FIXME - leaf = Mod_PointInLeaf (&origin[0], cl.worldmodel); + leaf = Mod_PointInLeaf (&origin[0], cl_world.worldmodel); contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 6f60de764..3cf903cf7 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -58,6 +58,7 @@ #include "compat.h" #include "client/hud.h" +#include "client/world.h" #include "qw/bothdefs.h" #include "qw/include/cl_cam.h" @@ -1109,8 +1110,8 @@ Sbar_LogFrags (void) if (t) Qwrite (file, t, strlen (t)); - Qprintf (file, "%s\n%s %s\n", cls.servername->str, cl.worldmodel->path, - cl.levelname); + Qprintf (file, "%s\n%s %s\n", cls.servername->str, + cl_world.worldmodel->path, cl.levelname); // scores Sbar_SortFrags (true); diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index 3bc9894f5..731ac279a 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -52,6 +52,7 @@ #include "compat.h" #include "client/locs.h" +#include "client/world.h" #include "qw/bothdefs.h" #include "qw/include/cl_input.h" @@ -289,8 +290,8 @@ Team_NewMap (void) died = false; recorded_location = false; - mapname = strdup (cl.worldmodel->path); - t2 = malloc (sizeof (cl.worldmodel->path)); + mapname = strdup (cl_world.worldmodel->path); + t2 = malloc (sizeof (cl_world.worldmodel->path)); if (!mapname || !t2) Sys_Error ("Can't duplicate mapname!"); map_to_loc (mapname,t2); @@ -340,16 +341,16 @@ locs_loc (void) "parameter\n"); return; } - if (!cl.worldmodel) { + if (!cl_world.worldmodel) { Sys_Printf ("No map loaded. Unable to work with location markers.\n"); return; } if (Cmd_Argc () >= 3) desc = Cmd_Args (2); - mapname = malloc (sizeof (cl.worldmodel->path)); + mapname = malloc (sizeof (cl_world.worldmodel->path)); if (!mapname) Sys_Error ("Can't duplicate mapname!"); - map_to_loc (cl.worldmodel->path, mapname); + map_to_loc (cl_world.worldmodel->path, mapname); snprintf (locfile, sizeof (locfile), "%s/%s", qfs_gamedir->dir.def, mapname); free (mapname); From 73444c3b7aab0a2cd0e0630776cd268cbbf2c702 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Mar 2022 02:05:59 +0900 Subject: [PATCH 2493/3664] [ruamoko] Give the scene resource block a rua prefix No effect on the code itself, but it makes debugging much easier when there aren't two very different structs with the same name. --- libs/ruamoko/rua_scene.c | 78 ++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index ec021db37..9656ba0da 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -52,20 +52,20 @@ typedef struct rua_scene_s { scene_t *scene; } rua_scene_t; -typedef struct scene_resources_s { +typedef struct rua_scene_resources_s { progs_t *pr; PR_RESMAP (rua_scene_t) scene_map; rua_scene_t *scenes; -} scene_resources_t; +} rua_scene_resources_t; static rua_scene_t * -rua_scene_new (scene_resources_t *res) +rua_scene_new (rua_scene_resources_t *res) { return PR_RESNEW (res->scene_map); } static void -rua_scene_free (scene_resources_t *res, rua_scene_t *scene) +rua_scene_free (rua_scene_resources_t *res, rua_scene_t *scene) { if (scene->next) { scene->next->prev = scene->prev; @@ -76,7 +76,7 @@ rua_scene_free (scene_resources_t *res, rua_scene_t *scene) } static rua_scene_t * __attribute__((pure)) -rua__scene_get (scene_resources_t *res, int id, const char *name) +rua__scene_get (rua_scene_resources_t *res, int id, const char *name) { rua_scene_t *scene = PR_RESGET (res->scene_map, id); @@ -114,7 +114,7 @@ rua__transform_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) rua__transform_get(pr, scene, id, __FUNCTION__) static int __attribute__((pure)) -rua_scene_index (scene_resources_t *res, rua_scene_t *scene) +rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene) { return PR_RESINDEX (res->scene_map, scene); } @@ -122,7 +122,7 @@ rua_scene_index (scene_resources_t *res, rua_scene_t *scene) static void bi_Scene_NewScene (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_new (res); @@ -139,7 +139,7 @@ bi_Scene_NewScene (progs_t *pr, void *_res) } static void -rua_delete_scene (scene_resources_t *res, rua_scene_t *scene) +rua_delete_scene (rua_scene_resources_t *res, rua_scene_t *scene) { Scene_DeleteScene (scene->scene); rua_scene_free (res, scene); @@ -148,7 +148,7 @@ rua_delete_scene (scene_resources_t *res, rua_scene_t *scene) static void bi_Scene_DeleteScene (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); rua_delete_scene (res, scene); @@ -157,7 +157,7 @@ bi_Scene_DeleteScene (progs_t *pr, void *_res) static void bi_Scene_CreateEntity (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); entity_t *ent = Scene_CreateEntity (scene->scene); R_INT (pr) = ent->id; @@ -166,7 +166,7 @@ bi_Scene_CreateEntity (progs_t *pr, void *_res) static void bi_Scene_DestroyEntity (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); entity_t *ent = rua_entity_get (pr, scene, P_INT (pr, 1)); Scene_DestroyEntity (scene->scene, ent); @@ -175,7 +175,7 @@ bi_Scene_DestroyEntity (progs_t *pr, void *_res) static void bi_Entity_GetTransform (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); entity_t *ent = rua_entity_get (pr, scene, P_INT (pr, 1)); @@ -185,7 +185,7 @@ bi_Entity_GetTransform (progs_t *pr, void *_res) static void bi_Transform_ChildCount (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); @@ -195,7 +195,7 @@ bi_Transform_ChildCount (progs_t *pr, void *_res) static void bi_Transform_GetChild (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); transform_t *child = Transform_GetChild (transform, P_UINT (pr, 2)); @@ -206,7 +206,7 @@ bi_Transform_GetChild (progs_t *pr, void *_res) static void bi_Transform_SetParent (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); transform_t *parent = rua_transform_get (pr, scene, P_INT (pr, 2)); @@ -217,7 +217,7 @@ bi_Transform_SetParent (progs_t *pr, void *_res) static void bi_Transform_GetParent (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); transform_t *parent = Transform_GetParent (transform); @@ -228,7 +228,7 @@ bi_Transform_GetParent (progs_t *pr, void *_res) static void bi_Transform_SetTag (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); pr_uint_t tag = P_UINT (pr, 2); @@ -238,7 +238,7 @@ bi_Transform_SetTag (progs_t *pr, void *_res) static void bi_Transform_GetTag (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); @@ -248,7 +248,7 @@ bi_Transform_GetTag (progs_t *pr, void *_res) static void bi_Transform_GetLocalMatrix (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_GetLocalMatrix (transform, &R_PACKED (pr, pr_vec4_t)); @@ -257,7 +257,7 @@ bi_Transform_GetLocalMatrix (progs_t *pr, void *_res) static void bi_Transform_GetLocalInverse (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_GetLocalInverse (transform, &R_PACKED (pr, pr_vec4_t)); @@ -266,7 +266,7 @@ bi_Transform_GetLocalInverse (progs_t *pr, void *_res) static void bi_Transform_GetWorldMatrix (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_GetWorldMatrix (transform, &R_PACKED (pr, pr_vec4_t)); @@ -275,7 +275,7 @@ bi_Transform_GetWorldMatrix (progs_t *pr, void *_res) static void bi_Transform_GetWorldInverse (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_GetWorldInverse (transform, &R_PACKED (pr, pr_vec4_t)); @@ -284,7 +284,7 @@ bi_Transform_GetWorldInverse (progs_t *pr, void *_res) static void bi_Transform_SetLocalPosition (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_SetLocalPosition (transform, P_PACKED (pr, pr_vec4_t, 2)); @@ -293,7 +293,7 @@ bi_Transform_SetLocalPosition (progs_t *pr, void *_res) static void bi_Transform_GetLocalPosition (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalPosition (transform); @@ -302,7 +302,7 @@ bi_Transform_GetLocalPosition (progs_t *pr, void *_res) static void bi_Transform_SetLocalRotation (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_SetLocalRotation (transform, P_PACKED (pr, pr_vec4_t, 2)); @@ -311,7 +311,7 @@ bi_Transform_SetLocalRotation (progs_t *pr, void *_res) static void bi_Transform_GetLocalRotation (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalRotation (transform); @@ -320,7 +320,7 @@ bi_Transform_GetLocalRotation (progs_t *pr, void *_res) static void bi_Transform_SetLocalScale (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_SetLocalScale (transform, P_PACKED (pr, pr_vec4_t, 2)); @@ -329,7 +329,7 @@ bi_Transform_SetLocalScale (progs_t *pr, void *_res) static void bi_Transform_GetLocalScale (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalScale (transform); @@ -338,7 +338,7 @@ bi_Transform_GetLocalScale (progs_t *pr, void *_res) static void bi_Transform_SetWorldPosition (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_SetWorldPosition (transform, P_PACKED (pr, pr_vec4_t, 2)); @@ -347,7 +347,7 @@ bi_Transform_SetWorldPosition (progs_t *pr, void *_res) static void bi_Transform_GetWorldPosition (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldPosition (transform); @@ -356,7 +356,7 @@ bi_Transform_GetWorldPosition (progs_t *pr, void *_res) static void bi_Transform_SetWorldRotation (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_SetWorldRotation (transform, P_PACKED (pr, pr_vec4_t, 2)); @@ -365,7 +365,7 @@ bi_Transform_SetWorldRotation (progs_t *pr, void *_res) static void bi_Transform_GetWorldRotation (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldRotation (transform); @@ -374,7 +374,7 @@ bi_Transform_GetWorldRotation (progs_t *pr, void *_res) static void bi_Transform_GetWorldScale (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldScale (transform); @@ -383,7 +383,7 @@ bi_Transform_GetWorldScale (progs_t *pr, void *_res) static void bi_Transform_SetLocalTransform (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); Transform_SetLocalTransform (transform, P_PACKED (pr, pr_vec4_t, 2), @@ -393,7 +393,7 @@ bi_Transform_SetLocalTransform (progs_t *pr, void *_res) static void bi_Transform_Forward (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); R_PACKED (pr, pr_vec4_t) = Transform_Forward (transform); @@ -402,7 +402,7 @@ bi_Transform_Forward (progs_t *pr, void *_res) static void bi_Transform_Right (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); R_PACKED (pr, pr_vec4_t) = Transform_Right (transform); @@ -411,7 +411,7 @@ bi_Transform_Right (progs_t *pr, void *_res) static void bi_Transform_Up (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); R_PACKED (pr, pr_vec4_t) = Transform_Up (transform); @@ -466,7 +466,7 @@ static builtin_t builtins[] = { static void bi_scene_clear (progs_t *pr, void *_res) { - scene_resources_t *res = _res; + rua_scene_resources_t *res = _res; while (res->scenes) { rua_delete_scene (res, res->scenes); @@ -476,7 +476,7 @@ bi_scene_clear (progs_t *pr, void *_res) void RUA_Scene_Init (progs_t *pr, int secure) { - scene_resources_t *res = calloc (sizeof (scene_resources_t), 1); + rua_scene_resources_t *res = calloc (sizeof (rua_scene_resources_t), 1); res->pr = pr; From 2a9566d380f7eea086e2da6d098bdd53ad115bb2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Mar 2022 14:17:48 +0900 Subject: [PATCH 2494/3664] [qwaq] Handle memory alignment for windows builds --- ruamoko/qwaq/builtins/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 940e2072a..48c404338 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -121,13 +121,21 @@ load_file (progs_t *pr, const char *name, off_t *_size) static void * allocate_progs_mem (progs_t *pr, int size) { +#ifdef _WIN32 + return _aligned_malloc (size, 64); +#else return aligned_alloc (64, size); +#endif } static void free_progs_mem (progs_t *pr, void *mem) { +#ifdef _WIN32 + _aligned_free (mem); +#else free (mem); +#endif } static void From 610bf20f2dc8487a6f3b0472b8f65107b2d2e2a6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Mar 2022 14:25:31 +0900 Subject: [PATCH 2495/3664] Fix a missing header for distcheck --- include/Makemodule.am | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Makemodule.am b/include/Makemodule.am index e548f8bbf..5a47125b1 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -92,6 +92,7 @@ EXTRA_DIST += \ include/client/state.h \ include/client/temp_entities.h \ include/client/view.h \ + include/client/world.h \ include/evdev/hotplug.h \ include/evdev/inputlib.h \ include/qw/bothdefs.h \ From 45c3c6d7be6b87f794e74c9269a8c1775224e127 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Mar 2022 14:35:56 +0900 Subject: [PATCH 2496/3664] [screen] Clean up some dead declarations --- include/QF/screen.h | 19 ------------------- libs/video/renderer/r_screen.c | 2 +- libs/video/targets/context_win.c | 3 --- nq/source/cl_main.c | 3 --- nq/source/sbar.c | 2 -- qw/source/sbar.c | 2 -- 6 files changed, 1 insertion(+), 30 deletions(-) diff --git a/include/QF/screen.h b/include/QF/screen.h index 98b198415..bfb8ab85e 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -33,7 +33,6 @@ struct transform_s; -void SCR_Init_Cvars (void); void SCR_Init (void); typedef void (*SCR_Func)(void); @@ -41,35 +40,17 @@ typedef void (*SCR_Func)(void); void SCR_UpdateScreen (struct transform_s *camera, double realtime, SCR_Func *scr_funcs); -void SCR_SizeUp (void); -void SCR_SizeDown (void); -void SCR_BringDownConsole (void); -void SCR_CalcRefdef (void); - -void SCR_BeginLoadingPlaque (void); -void SCR_EndLoadingPlaque (void); - -struct view_s; - int MipColor (int r, int g, int b); -int SCR_ModalMessage (const char *text); - -extern float scr_con_current; extern int sb_lines; -extern qboolean scr_disabled_for_loading; extern qboolean scr_skipupdate; -extern qboolean hudswap; extern struct cvar_s *scr_fov; extern struct cvar_s *scr_viewsize; // only the refresh window will be updated unless these variables are flagged -extern struct qpic_s *scr_ram; -extern struct qpic_s *scr_turtle; - extern struct cvar_s *hud_fps, *hud_time; #endif//__QF_screen_h diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index cc36528e4..fd7d7b57e 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -160,7 +160,7 @@ CalcFov (float fov_x, float width, float height) return a; } -void +static void SCR_CalcRefdef (void) { vrect_t vrect; diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index 283c4cdfe..d116243a3 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -613,8 +613,6 @@ VID_SetMode (int modenum, const byte *palette) return true; // so Con_Printfs don't mess us up by forcing vid and snd updates -//FIXME? temp = scr_disabled_for_loading; -//FIXME? scr_disabled_for_loading = true; in_mode_set = true; //FIXME CDAudio_Pause (); //FIXME S_ClearBuffer (); @@ -643,7 +641,6 @@ VID_SetMode (int modenum, const byte *palette) Win_UpdateWindowStatus (0, 0); // FIXME right numbers? //FIXME CDAudio_Resume (); -//FIXME? scr_disabled_for_loading = temp; if (!stat) { VID_RestoreOldMode (original_mode); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index e789b66ac..44041949b 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -257,9 +257,6 @@ CL_Disconnect (void) // Clean the Cshifts CL_StopCshifts (); - // bring the console down and fade the colors back to normal -// SCR_BringDownConsole (); - // if running a local server, shut it down if (cls.demoplayback) CL_StopPlayback (); diff --git a/nq/source/sbar.c b/nq/source/sbar.c index af78bea47..4797363c7 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -89,7 +89,6 @@ qpic_t *sb_face_invis_invuln; qboolean sb_showscores; int sb_lines; // scan lines to draw -qboolean hudswap; qpic_t *rsb_invbar[2]; qpic_t *rsb_weapons[5]; @@ -126,7 +125,6 @@ static view_t *main_view; static void hud_swap_f (cvar_t *var) { - hudswap = var->int_val; if (var->int_val) { hud_armament_view->gravity = grav_southwest; hud_armament_view->children[0]->gravity = grav_northwest; diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 3cf903cf7..0281c332f 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -93,7 +93,6 @@ qboolean sb_showscores; qboolean sb_showteamscores; int sb_lines; // scan lines to draw -qboolean hudswap; static qboolean largegame = false; @@ -121,7 +120,6 @@ static void (*Sbar_Draw_DMO_func) (view_t *view, int l, int y, int skip); static void hud_swap_f (cvar_t *var) { - hudswap = var->int_val; if (var->int_val) { view_setgravity (hud_armament_view, grav_southwest); view_setgravity (stuff_view, grav_southeast); From 1ea3a3807ee19be720e71ae8cdf8057d14afd3c3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Mar 2022 13:47:41 +0900 Subject: [PATCH 2497/3664] [renderer] Clean up a pile of dead screen declarations The declarations were either unused, or the functions empty stubs for all renderers. --- include/QF/screen.h | 13 ------ include/r_screen.h | 31 ++----------- libs/video/renderer/gl/gl_screen.c | 1 - libs/video/renderer/glsl/glsl_screen.c | 1 - libs/video/renderer/r_screen.c | 63 ++------------------------ libs/video/renderer/sw/screen.c | 8 ---- libs/video/renderer/sw32/screen.c | 8 ---- qw/source/cl_screen.c | 1 - 8 files changed, 7 insertions(+), 119 deletions(-) diff --git a/include/QF/screen.h b/include/QF/screen.h index bfb8ab85e..6aaea601d 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -29,8 +29,6 @@ #ifndef __QF_screen_h #define __QF_screen_h -#include "QF/qtypes.h" - struct transform_s; void SCR_Init (void); @@ -40,17 +38,6 @@ typedef void (*SCR_Func)(void); void SCR_UpdateScreen (struct transform_s *camera, double realtime, SCR_Func *scr_funcs); -int MipColor (int r, int g, int b); - -extern int sb_lines; - -extern qboolean scr_skipupdate; - -extern struct cvar_s *scr_fov; -extern struct cvar_s *scr_viewsize; - -// only the refresh window will be updated unless these variables are flagged - extern struct cvar_s *hud_fps, *hud_time; #endif//__QF_screen_h diff --git a/include/r_screen.h b/include/r_screen.h index e684b2028..e9059e0df 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -31,42 +31,17 @@ #ifndef __r_screen_h #define __r_screen_h -#include "QF/screen.h" -#include "QF/vid.h" - void SCR_DrawRam (void); -void SCR_DrawFPS (void); -void SCR_DrawTime (void); void SCR_DrawTurtle (void); void SCR_DrawPause (void); struct tex_s *SCR_CaptureBGR (void); struct tex_s *SCR_ScreenShot (unsigned width, unsigned height); void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); - +void SCR_SetFOV (float fov); +void SCR_ScreenShot_f (void); +int MipColor (int r, int g, int b); extern int scr_copytop; - -extern float scr_con_current; -extern float scr_conlines; // lines of console to display - -extern int oldscreensize; -extern int oldsbar; - -extern qboolean scr_initialized; // ready to draw - -extern struct qpic_s *scr_ram; -extern struct qpic_s *scr_net; -extern struct qpic_s *scr_turtle; - -extern int clearconsole; -extern int clearnotify; - -extern vrect_t *pconupdate; - extern qboolean scr_skipupdate; -void SCR_SetFOV (float fov); -void SCR_SetUpToDrawConsole (void); -void SCR_ScreenShot_f (void); - #endif//__r_screen_h diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index dff7b88b9..32cf78848 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -230,7 +230,6 @@ gl_R_RenderFrame (SCR_Func *scr_funcs) // do 3D refresh drawing, and then update the screen gl_R_RenderView (); - SCR_SetUpToDrawConsole (); GL_Set2D (); GL_DrawReset (); diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index d484799c3..d33e13257 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -180,7 +180,6 @@ glsl_R_RenderFrame (SCR_Func *scr_funcs) glsl_R_RenderView (); - SCR_SetUpToDrawConsole (); GLSL_Set2D (); GLSL_DrawReset (); SCR_TileClear (); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index fd7d7b57e..992822f5f 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -51,65 +51,15 @@ #include "r_internal.h" #include "sbar.h" -/* - background clear - rendering - turtle/net/ram icons - sbar - centerprint / slow centerprint - notify lines - intermission / finale overlay - loading plaque - console - menu - - required background clears - required update regions - - syncronous draw mode or async - One off screen buffer, with updates either copied or xblited - Need to double buffer? - - async draw will require the refresh area to be cleared, because it will be - xblited, but sync draw can just ignore it. - - sync - draw - - CenterPrint () - SlowPrint () - Screen_Update (); - Sys_Printf (); - - net - turn off messages option - - the refresh is always rendered, unless the console is full screen - - console is: - notify lines - half - full -*/ - // only the refresh window will be updated unless these variables are flagged int scr_copytop; -byte *draw_chars; // 8*8 graphic characters FIXME location - -int oldsbar; - +byte *draw_chars; // 8*8 graphic characters FIXME location qboolean r_cache_thrash; // set if surface cache is thrashing -qboolean scr_initialized; // ready to draw - -qpic_t *scr_ram; -qpic_t *scr_turtle; - -int clearconsole; - -vrect_t *pconupdate; - qboolean scr_skipupdate; +static qboolean scr_initialized;// ready to draw +static qpic_t *scr_ram; +static qpic_t *scr_turtle; void R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) @@ -318,11 +268,6 @@ SCR_DrawPause (void) pic); } -void -SCR_SetUpToDrawConsole (void) -{ -} - /* Find closest color in the palette for named color */ diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index a3b7966c0..17c47e213 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -195,10 +195,6 @@ R_RenderFrame (SCR_Func *scr_funcs) Draw_TileClear (0, 0, vid.width, vid.height); } - pconupdate = NULL; - - SCR_SetUpToDrawConsole (); - D_DisableBackBufferAccess (); // for adapters that can't stay mapped // in for linear writes all the time VID_LockBuffer (); @@ -216,10 +212,6 @@ R_RenderFrame (SCR_Func *scr_funcs) D_DisableBackBufferAccess (); // for adapters that can't stay mapped // in for linear writes all the time - if (pconupdate) { - D_UpdateRects (pconupdate); - } - // update one of three areas if (vr_data.scr_copyeverything) { vrect.x = 0; diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index be5fd5fec..b6a4c7037 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -152,10 +152,6 @@ sw32_R_RenderFrame (SCR_Func *scr_funcs) sw32_Draw_TileClear (0, 0, vid.width, vid.height); } - pconupdate = NULL; - - SCR_SetUpToDrawConsole (); - sw32_D_DisableBackBufferAccess (); // for adapters that can't stay mapped // in for linear writes all the time VID_LockBuffer (); @@ -173,10 +169,6 @@ sw32_R_RenderFrame (SCR_Func *scr_funcs) sw32_D_DisableBackBufferAccess (); // for adapters that can't stay mapped // in for linear writes all the time - if (pconupdate) { - sw32_D_UpdateRects (pconupdate); - } - // update one of three areas if (vr_data.scr_copyeverything) { vrect.x = 0; diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 5e3978e5b..6584516cd 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -112,7 +112,6 @@ static SCR_Func scr_funcs_normal[] = { 0, //SCR_DrawRam, 0, //SCR_DrawTurtle, 0, //SCR_DrawPause, - //CL_NetGraph,FIXME Sbar_Draw, SCR_CShift, scr_draw_views, From 71c1b4e0c4bcfb272a83e767b2b9688972d4d06d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 08:38:38 +0900 Subject: [PATCH 2498/3664] [gl] Clean up some triple buffer and multi-texture cvar mess Excess declarations for gl_multitexture_f, and move gl_triplebuffer into a callback. --- include/QF/GL/qf_rmain.h | 6 ++++-- libs/video/renderer/gl/gl_lightmap.c | 3 --- libs/video/renderer/gl/gl_screen.c | 4 ---- libs/video/renderer/gl/vid_common_gl.c | 11 ++++++++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/QF/GL/qf_rmain.h b/include/QF/GL/qf_rmain.h index 63735a926..4625b94dc 100644 --- a/include/QF/GL/qf_rmain.h +++ b/include/QF/GL/qf_rmain.h @@ -29,7 +29,9 @@ #define __QF_GL_rmain_h #include "QF/qtypes.h" -#include "QF/cvar.h" + +struct cvar_s; +struct entity_s; extern qboolean gl_envmap; extern int c_brush_polys, c_alias_polys; @@ -38,7 +40,7 @@ extern float r_world_matrix[16]; extern float gl_modelalpha; //extern vec3_t shadecolor; -extern void gl_multitexture_f (cvar_t *var); +extern void gl_multitexture_f (struct cvar_s *var); void glrmain_init (void); void R_RotateForEntity (struct entity_s *e); diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index f601e2755..52cbb00b8 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -80,9 +80,6 @@ static int lmshift = 7; void (*gl_R_BuildLightMap) (const transform_t *transform, mod_brush_t *brush, msurface_t *surf); -extern void gl_multitexture_f (cvar_t *var); - - void gl_lightmap_init (void) { diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 32cf78848..8e03bc5f9 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -211,8 +211,6 @@ gl_R_RenderFrame (SCR_Func *scr_funcs) begun = 0; } - vid.numpages = 2 + gl_triplebuffer->int_val; - //FIXME forces the status bar to redraw. needed because it does not fully //update in sw modes but must in gl mode vr_data.scr_copyeverything = 1; @@ -223,8 +221,6 @@ gl_R_RenderFrame (SCR_Func *scr_funcs) if (r_speeds->int_val) { time1 = Sys_DoubleTime (); - gl_c_brush_polys = 0; - gl_c_alias_polys = 0; } // do 3D refresh drawing, and then update the screen diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index 7b8c213e7..ce8a5e3d6 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -48,6 +48,7 @@ #include "QF/GL/defines.h" #include "QF/GL/extensions.h" #include "QF/GL/funcs.h" +#include "QF/GL/qf_rmain.h" #include "QF/GL/qf_vid.h" #include "compat.h" @@ -150,8 +151,11 @@ cvar_t *gl_texsort; cvar_t *gl_triplebuffer; static cvar_t *vid_use8bit; -void gl_multitexture_f (cvar_t *var); - +static void +gl_triplebuffer_f (cvar_t *var) +{ + vid.numpages = var->int_val ? 3 : 2; +} static void gl_max_size_f (cvar_t *var) @@ -401,7 +405,8 @@ GL_Common_Init_Cvars (void) "controls whether the skydome is single or " "double pass"); gl_texsort = Cvar_Get ("gl_texsort", "1", CVAR_NONE, NULL, "None"); - gl_triplebuffer = Cvar_Get ("gl_triplebuffer", "1", CVAR_ARCHIVE, NULL, + gl_triplebuffer = Cvar_Get ("gl_triplebuffer", "1", CVAR_ARCHIVE, + gl_triplebuffer_f, "Set to 1 by default. Fixes status bar " "flicker on some hardware"); } From 9514ad1ae4c046014c7180682767ad56c43baea8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 08:40:39 +0900 Subject: [PATCH 2499/3664] [gl] Draw sky chains before brush entities Drawing sky chains first ensures that sky surfaces correctly block parts of the map that should not be visible (by writing the correct depth to the depth buffer when doing box or dome skies). Writing brush models first means that the models (ammo boxes etc) could be visible when they should not be. --- libs/video/renderer/gl/gl_rsurf.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 5d32d9c5e..8a131ff44 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -739,6 +739,11 @@ gl_R_DrawWorld (void) bctx.entity = &r_worldentity; R_VisitWorldNodes (&bctx); + + gl_R_CalcLightmaps (); + + gl_R_DrawSkyChain (sky_chain); + if (r_drawentities->int_val) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \ entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \ @@ -746,10 +751,6 @@ gl_R_DrawWorld (void) } } - gl_R_CalcLightmaps (); - - gl_R_DrawSkyChain (sky_chain); - if (!gl_Fog_GetDensity () || (gl_fb_bmodels->int_val && gl_mtex_fullbright) || gl_mtex_active_tmus > 1) { From 04fd9baff52671c6344a2301b202f68d2cfe1493 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 08:43:23 +0900 Subject: [PATCH 2500/3664] [glsl] Reorder some code for consistency --- libs/video/renderer/glsl/glsl_screen.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index d33e13257..a25425f02 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -169,14 +169,13 @@ glsl_R_RenderFrame (SCR_Func *scr_funcs) glsl_ctx->end_rendering (); } - //FIXME useless cvar? vid.numpages = 2 + gl_triplebuffer->int_val; + //FIXME forces the status bar to redraw. needed because it does not fully + //update in sw modes but must in glsl mode + vr_data.scr_copyeverything = 1; qfeglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); begun = 1; - //FIXME forces the status bar to redraw. needed because it does not fully - //update in sw modes but must in glsl mode - vr_data.scr_copyeverything = 1; glsl_R_RenderView (); From 5eb397dd313a6b287fcabcbad44ebfcb7f4ce70c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 08:44:53 +0900 Subject: [PATCH 2501/3664] [renderer] Remove more dead code The back-buffer and video buffer locking code was pretty much never more than stubs (except maybe in dos quake). --- include/d_iface.h | 2 -- include/r_shared.h | 2 +- include/vid_internal.h | 2 -- libs/video/renderer/sw/d_init.c | 12 ----------- libs/video/renderer/sw/draw.c | 4 ---- libs/video/renderer/sw/screen.c | 29 +-------------------------- libs/video/renderer/sw/sw_redge.c | 2 -- libs/video/renderer/sw/sw_rmain.c | 9 --------- libs/video/renderer/sw/sw_rmisc.c | 4 ---- libs/video/renderer/sw32/d_init.c | 12 ----------- libs/video/renderer/sw32/draw.c | 4 ---- libs/video/renderer/sw32/namehack.h | 4 ---- libs/video/renderer/sw32/screen.c | 21 ------------------- libs/video/renderer/sw32/sw32_redge.c | 2 -- libs/video/renderer/sw32/sw32_rmain.c | 9 --------- libs/video/renderer/sw32/sw32_rmisc.c | 9 --------- libs/video/targets/vid_fbdev.c | 10 --------- libs/video/targets/vid_sdl.c | 10 --------- libs/video/targets/vid_svgalib.c | 10 --------- libs/video/targets/vid_win.c | 10 --------- libs/video/targets/vid_x11.c | 10 --------- 21 files changed, 2 insertions(+), 175 deletions(-) diff --git a/include/d_iface.h b/include/d_iface.h index f4272e508..3587a55da 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -145,7 +145,6 @@ extern vec3_t r_pright, r_pup, r_ppn; void D_Aff8Patch (void *pcolormap); void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height); -void D_DisableBackBufferAccess (void); void D_EndDirectRect (int x, int y, int width, int height); void D_PolysetDraw (void); void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts); @@ -155,7 +154,6 @@ void D_DrawPoly (void); void D_DrawSprite (void); void D_DrawSurfaces (void); void D_DrawZPoint (void); -void D_EnableBackBufferAccess (void); void D_Init (void); void D_Init_Cvars (void); void D_ViewChanged (void); diff --git a/include/r_shared.h b/include/r_shared.h index b39e387f8..b04e129f1 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -105,7 +105,7 @@ typedef struct surf_s { qboolean insubmodel; float d_ziorigin, d_zistepu, d_zistepv; - int pad[2]; // to 64 bytes + int pad[2]; // to 64 bytes (FIXME not for 64-bit) } surf_t; extern surf_t *surfaces, *surface_p, *surf_max; diff --git a/include/vid_internal.h b/include/vid_internal.h index 035f36170..5b677bcf0 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -34,8 +34,6 @@ void VID_InitGamma (const byte *); qboolean VID_SetGamma (double); void VID_UpdateGamma (struct cvar_s *); -void VID_LockBuffer (void); -void VID_UnlockBuffer (void); void VID_InitBuffers (void); void VID_MakeColormaps (void); diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index 00fb21a89..634762d28 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -63,24 +63,12 @@ D_Init (void) VID_InitBuffers (); } -void -D_EnableBackBufferAccess (void) -{ - VID_LockBuffer (); -} - void D_TurnZOn (void) { // not needed for software version } -void -D_DisableBackBufferAccess (void) -{ - VID_UnlockBuffer (); -} - void D_SetupFrame (void) { diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index a24117118..1b3d0c0c9 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -782,9 +782,7 @@ Draw_FadeScreen (void) int width = vid.conview->xlen / 4; uint32_t *pbuf; - VID_UnlockBuffer (); S_ExtraUpdate (); - VID_LockBuffer (); for (y = 0; y < height; y++) { uint32_t mask; @@ -798,9 +796,7 @@ Draw_FadeScreen (void) } vr_data.scr_copyeverything = 1; - VID_UnlockBuffer (); S_ExtraUpdate (); - VID_LockBuffer (); } void diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 17c47e213..3e5b288d6 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -72,7 +72,6 @@ SCR_CaptureBGR (void) tex->height = vid.height; tex->format = tex_rgb; tex->palette = 0; - D_EnableBackBufferAccess (); src = vid.buffer; for (y = 0; y < tex->height; y++) { dst = tex->data + (tex->height - 1 - y) * tex->width * 3; @@ -83,7 +82,6 @@ SCR_CaptureBGR (void) src++; } } - D_DisableBackBufferAccess (); return tex; } @@ -95,9 +93,6 @@ SCR_ScreenShot (unsigned width, unsigned height) int count, dex, dey, dx, dy, nx, r, g, b, x, y, w, h; tex_t *tex; - // enable direct drawing of console to back buffer - D_EnableBackBufferAccess (); - w = (vid.width < width) ? vid.width : width; h = (vid.height < height) ? vid.height : height; @@ -145,8 +140,6 @@ SCR_ScreenShot (unsigned width, unsigned height) *dest++ = MipColor (r, g, b); } } - // for adapters that can't stay mapped in for linear writes all the time - D_DisableBackBufferAccess (); return tex; } @@ -163,19 +156,12 @@ SCR_ScreenShot_f (void) va (0, "%s/qf", qfs_gamedir->dir.shots), ".pcx")) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); } else { - // enable direct drawing of console to back buffer - D_EnableBackBufferAccess (); - // save the pcx file pcx = EncodePCX (vid.buffer, vid.width, vid.height, vid.rowbytes, vid.basepal, false, &pcx_len); QFS_WriteFile (pcxname->str, pcx, pcx_len); - // for adapters that can't stay mapped in for linear writes all the - // time - D_DisableBackBufferAccess (); - Sys_Printf ("Wrote %s/%s\n", qfs_userpath, pcxname->str); } dstring_delete (pcxname); @@ -184,25 +170,13 @@ SCR_ScreenShot_f (void) void R_RenderFrame (SCR_Func *scr_funcs) { - vrect_t vrect; - // do 3D refresh drawing, and then update the screen - D_EnableBackBufferAccess (); // of all overlay stuff if drawing - // directly - if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen vr_data.scr_copyeverything = 1; Draw_TileClear (0, 0, vid.width, vid.height); } - D_DisableBackBufferAccess (); // for adapters that can't stay mapped - // in for linear writes all the time - VID_LockBuffer (); R_RenderView (); - VID_UnlockBuffer (); - - D_EnableBackBufferAccess (); // of all overlay stuff if drawing - // directly view_draw (vr_data.scr_view); while (*scr_funcs) { @@ -210,9 +184,8 @@ R_RenderFrame (SCR_Func *scr_funcs) scr_funcs++; } - D_DisableBackBufferAccess (); // for adapters that can't stay mapped - // in for linear writes all the time // update one of three areas + vrect_t vrect; if (vr_data.scr_copyeverything) { vrect.x = 0; vrect.y = 0; diff --git a/libs/video/renderer/sw/sw_redge.c b/libs/video/renderer/sw/sw_redge.c index 173157677..8efc09753 100644 --- a/libs/video/renderer/sw/sw_redge.c +++ b/libs/video/renderer/sw/sw_redge.c @@ -522,9 +522,7 @@ R_ScanEdges (void) // flush the span list if we can't be sure we have enough spans left // for the next scan if (span_p > max_span_p) { - VID_UnlockBuffer (); S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); if (r_drawculledpolys) R_DrawCulledPolys (); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index e482d7617..841036858 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -731,9 +731,7 @@ R_EdgeDrawing (void) } if (!r_dspeeds->int_val) { - VID_UnlockBuffer (); S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); } if (!(r_drawpolys | r_drawculledpolys)) @@ -773,21 +771,14 @@ R_RenderView_ (void) // done in screen.c R_LowFPPrecision (); - if (!r_worldentity.renderer.model) - Sys_Error ("R_RenderView: NULL worldmodel"); - if (!r_dspeeds->int_val) { - VID_UnlockBuffer (); S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); } R_EdgeDrawing (); if (!r_dspeeds->int_val) { - VID_UnlockBuffer (); S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); } if (r_dspeeds->int_val) { diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index 481a3f64d..1dfa026f8 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -68,12 +68,8 @@ R_TimeRefresh_f (void) for (i = 0; i < 128; i++) { r_refdef.viewangles[1] = i / 128.0 * 360.0; - VID_LockBuffer (); - R_RenderView (); - VID_UnlockBuffer (); - vr.x = r_refdef.vrect.x; vr.y = r_refdef.vrect.y; vr.width = r_refdef.vrect.width; diff --git a/libs/video/renderer/sw32/d_init.c b/libs/video/renderer/sw32/d_init.c index 28d0ea85f..29027a0a7 100644 --- a/libs/video/renderer/sw32/d_init.c +++ b/libs/video/renderer/sw32/d_init.c @@ -75,24 +75,12 @@ sw32_D_Init (void) VID_MakeColormaps(); } -void -sw32_D_EnableBackBufferAccess (void) -{ - VID_LockBuffer (); -} - void sw32_D_TurnZOn (void) { // not needed for software version } -void -sw32_D_DisableBackBufferAccess (void) -{ - VID_UnlockBuffer (); -} - void sw32_D_SetupFrame (void) { diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c index 6c8621097..9e8244371 100644 --- a/libs/video/renderer/sw32/draw.c +++ b/libs/video/renderer/sw32/draw.c @@ -1224,9 +1224,7 @@ sw32_Draw_FadeScreen (void) { int x, y; - VID_UnlockBuffer (); S_ExtraUpdate (); - VID_LockBuffer (); switch(sw32_ctx->pixbytes) { case 1: @@ -1269,9 +1267,7 @@ sw32_Draw_FadeScreen (void) } vr_data.scr_copyeverything = 1; - VID_UnlockBuffer (); S_ExtraUpdate (); - VID_LockBuffer (); } void diff --git a/libs/video/renderer/sw32/namehack.h b/libs/video/renderer/sw32/namehack.h index b1cf44f01..9cbbfe348 100644 --- a/libs/video/renderer/sw32/namehack.h +++ b/libs/video/renderer/sw32/namehack.h @@ -1,7 +1,6 @@ #ifdef NH_DEFINE #undef NH_DEFINE #define D_CacheSurface sw32_D_CacheSurface -#define D_DisableBackBufferAccess sw32_D_DisableBackBufferAccess #define D_DrawParticle sw32_D_DrawParticle #define D_DrawPoly sw32_D_DrawPoly #define D_DrawSkyScans sw32_D_DrawSkyScans @@ -10,7 +9,6 @@ #define D_DrawSurfaces sw32_D_DrawSurfaces #define D_DrawZPoint sw32_D_DrawZPoint #define D_DrawZSpans sw32_D_DrawZSpans -#define D_EnableBackBufferAccess sw32_D_EnableBackBufferAccess #define D_FillRect sw32_D_FillRect #define D_FlushCaches sw32_D_FlushCaches #define D_Init sw32_D_Init @@ -240,7 +238,6 @@ extern struct surf_s *sw32_surfaces; #define zspantable sw32_zspantable #else #undef D_CacheSurface -#undef D_DisableBackBufferAccess #undef D_DrawParticle #undef D_DrawPoly #undef D_DrawSkyScans @@ -249,7 +246,6 @@ extern struct surf_s *sw32_surfaces; #undef D_DrawSurfaces #undef D_DrawZPoint #undef D_DrawZSpans -#undef D_EnableBackBufferAccess #undef D_FillRect #undef D_FlushCaches #undef D_Init diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index b6a4c7037..4a77aac77 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -75,7 +75,6 @@ sw32_SCR_CaptureBGR (void) tex->height = vid.height; tex->format = tex_rgb; tex->palette = 0; - sw32_D_EnableBackBufferAccess (); src = vid.buffer; for (y = 0; y < tex->height; y++) { dst = tex->data + (tex->height - 1 - y) * tex->width * 3; @@ -86,7 +85,6 @@ sw32_SCR_CaptureBGR (void) src++; } } - sw32_D_DisableBackBufferAccess (); return tex; } @@ -108,9 +106,6 @@ sw32_SCR_ScreenShot_f (void) qfs_gamedir->dir.shots), ".pcx")) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); } else { - // enable direct drawing of console to back buffer - sw32_D_EnableBackBufferAccess (); - // save the pcx file switch(sw32_ctx->pixbytes) { case 1: @@ -127,9 +122,6 @@ sw32_SCR_ScreenShot_f (void) Sys_Error("SCR_ScreenShot_f: unsupported r_pixbytes %i", sw32_ctx->pixbytes); } - // for adapters that can't stay mapped in for linear writes all the time - sw32_D_DisableBackBufferAccess (); - if (pcx) { QFS_WriteFile (pcxname->str, pcx, pcx_len); Sys_Printf ("Wrote %s/%s\n", qfs_userpath, pcxname->str); @@ -143,23 +135,12 @@ sw32_R_RenderFrame (SCR_Func *scr_funcs) { vrect_t vrect; - // do 3D refresh drawing, and then update the screen - sw32_D_EnableBackBufferAccess (); // of all overlay stuff if drawing - // directly - if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen vr_data.scr_copyeverything = 1; sw32_Draw_TileClear (0, 0, vid.width, vid.height); } - sw32_D_DisableBackBufferAccess (); // for adapters that can't stay mapped - // in for linear writes all the time - VID_LockBuffer (); sw32_R_RenderView (); - VID_UnlockBuffer (); - - sw32_D_EnableBackBufferAccess (); // of all overlay stuff if drawing - // directly view_draw (vr_data.scr_view); while (*scr_funcs) { @@ -167,8 +148,6 @@ sw32_R_RenderFrame (SCR_Func *scr_funcs) scr_funcs++; } - sw32_D_DisableBackBufferAccess (); // for adapters that can't stay mapped - // in for linear writes all the time // update one of three areas if (vr_data.scr_copyeverything) { vrect.x = 0; diff --git a/libs/video/renderer/sw32/sw32_redge.c b/libs/video/renderer/sw32/sw32_redge.c index 91765fd5b..8498f22a9 100644 --- a/libs/video/renderer/sw32/sw32_redge.c +++ b/libs/video/renderer/sw32/sw32_redge.c @@ -503,9 +503,7 @@ sw32_R_ScanEdges (void) // flush the span list if we can't be sure we have enough spans left // for the next scan if (span_p > max_span_p) { - VID_UnlockBuffer (); S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); if (sw32_r_drawculledpolys) R_DrawCulledPolys (); diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c index 517f471c3..b201ff07c 100644 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -736,9 +736,7 @@ R_EdgeDrawing (void) } if (!r_dspeeds->int_val) { - VID_UnlockBuffer (); S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); } if (!(sw32_r_drawpolys | sw32_r_drawculledpolys)) @@ -776,21 +774,14 @@ R_RenderView_ (void) #endif R_PushDlights (vec3_origin); - if (!r_worldentity.renderer.model) - Sys_Error ("R_RenderView: NULL worldmodel"); - if (!r_dspeeds->int_val) { - VID_UnlockBuffer (); S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); } R_EdgeDrawing (); if (!r_dspeeds->int_val) { - VID_UnlockBuffer (); S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); } if (r_dspeeds->int_val) { diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c index 5b4092250..6d40529cc 100644 --- a/libs/video/renderer/sw32/sw32_rmisc.c +++ b/libs/video/renderer/sw32/sw32_rmisc.c @@ -70,12 +70,8 @@ sw32_R_TimeRefresh_f (void) for (i = 0; i < 128; i++) { r_refdef.viewangles[1] = i / 128.0 * 360.0; - VID_LockBuffer (); - sw32_R_RenderView (); - VID_UnlockBuffer (); - vr.x = r_refdef.vrect.x; vr.y = r_refdef.vrect.y; vr.width = r_refdef.vrect.width; @@ -289,11 +285,6 @@ sw32_R_SetupFrame (void) sw32_R_ViewChanged (); } } else { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - r_refdef.vrect.x = vr_data.scr_view->xpos; r_refdef.vrect.y = vr_data.scr_view->ypos; r_refdef.vrect.width = vr_data.scr_view->xlen; diff --git a/libs/video/targets/vid_fbdev.c b/libs/video/targets/vid_fbdev.c index 2f40413d1..b56d94dee 100644 --- a/libs/video/targets/vid_fbdev.c +++ b/libs/video/targets/vid_fbdev.c @@ -525,16 +525,6 @@ VID_Update (vrect_t *rects) } } -void -VID_LockBuffer (void) -{ -} - -void -VID_UnlockBuffer (void) -{ -} - void VID_SetCaption (const char *text) { diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index e71660cb6..21ec6f051 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -156,13 +156,3 @@ D_EndDirectRect (int x, int y, int width, int height) x = sdl_screen->w + x - 1; SDL_UpdateRect (sdl_screen, x, y, width, height); } - -void -VID_LockBuffer (void) -{ -} - -void -VID_UnlockBuffer (void) -{ -} diff --git a/libs/video/targets/vid_svgalib.c b/libs/video/targets/vid_svgalib.c index 592d917dc..66eacea49 100644 --- a/libs/video/targets/vid_svgalib.c +++ b/libs/video/targets/vid_svgalib.c @@ -462,16 +462,6 @@ VID_Update (vrect_t *rects) } } -void -VID_LockBuffer (void) -{ -} - -void -VID_UnlockBuffer (void) -{ -} - void VID_SetCaption (const char *text) { diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index d09f64d43..02b919f04 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -154,16 +154,6 @@ VID_Init_Cvars (void) Win_GL_Init_Cvars (); } -void -VID_LockBuffer (void) -{ -} - -void -VID_UnlockBuffer (void) -{ -} - void VID_SetCaption (const char *text) { diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 6fc26e050..ad452316b 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -167,16 +167,6 @@ update () } #endif -void -VID_LockBuffer (void) -{ -} - -void -VID_UnlockBuffer (void) -{ -} - void VID_SetCaption (const char *text) { From 2a87983bf4a5879656b63263e5aa240e6f971235 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 08:47:54 +0900 Subject: [PATCH 2502/3664] [sw] Remove some unnecessary casting I'm not sure what the author of that code was thinking (maybe trying to do 4 pixels at a time?), but the resulting code still did only one. Better to remove all the casts, use the right pointer type, and keep the code clear. --- libs/video/renderer/sw/sw_rsky.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/libs/video/renderer/sw/sw_rsky.c b/libs/video/renderer/sw/sw_rsky.c index 5a5670c57..b179ce420 100644 --- a/libs/video/renderer/sw/sw_rsky.c +++ b/libs/video/renderer/sw/sw_rsky.c @@ -94,7 +94,7 @@ R_MakeSky (void) int x, y; int ofs, baseofs; int xshift, yshift; - unsigned int *pnewsky; + byte *pnewsky; static int xlast = -1, ylast = -1; xshift = r_skytime * r_skyspeed; @@ -106,19 +106,17 @@ R_MakeSky (void) xlast = xshift; ylast = yshift; - pnewsky = (unsigned int *) &newsky[0]; + pnewsky = &newsky[0]; for (y = 0; y < SKYSIZE; y++) { baseofs = ((y + yshift) & SKYMASK) * 131; for (x = 0; x < SKYSIZE; x++) { ofs = baseofs + ((x + xshift) & SKYMASK); - *(byte *) pnewsky = (*((byte *) pnewsky + 128) & - *(byte *) & bottommask[ofs]) | - *(byte *) & bottomsky[ofs]; - pnewsky = (unsigned int *) ((byte *) pnewsky + 1); + *pnewsky = (*(pnewsky + 128) & bottommask[ofs]) | bottomsky[ofs]; + pnewsky = pnewsky + 1; } - pnewsky += 128 / sizeof (unsigned int); + pnewsky += 128; } r_skymade = 1; From 2eae2e5d74a1839d65c9b208dde49369476d0b88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 13:40:04 +0900 Subject: [PATCH 2503/3664] [renderer] Move some functions from plugins to main lib One step in cleaning up vid_render_funcs. --- include/QF/plugin/vid_render.h | 9 --------- include/QF/render.h | 6 ++++++ include/QF/screen.h | 5 +++++ include/r_internal.h | 3 --- include/r_screen.h | 4 ---- libs/client/cl_effects.c | 6 +++--- libs/client/cl_temp_entities.c | 20 +++++++++---------- libs/client/cl_world.c | 2 +- libs/client/locs.c | 2 +- libs/video/renderer/Makemodule.am | 6 +++--- libs/video/renderer/r_cvar.c | 2 +- libs/video/renderer/r_efrag.c | 8 ++++---- libs/video/renderer/r_ent.c | 2 -- libs/video/renderer/r_light.c | 20 +++++++++---------- libs/video/renderer/vid_render_gl.c | 9 --------- libs/video/renderer/vid_render_glsl.c | 9 --------- libs/video/renderer/vid_render_sw.c | 9 --------- libs/video/renderer/vid_render_sw32.c | 9 --------- libs/video/renderer/vid_render_vulkan.c | 9 --------- nq/source/cl_ents.c | 12 ++++++------ nq/source/cl_screen.c | 9 +++------ nq/source/host.c | 2 +- nq/source/sv_ded.c | 5 +++++ qw/source/cl_ents.c | 26 ++++++++++++------------- qw/source/cl_main.c | 2 +- qw/source/cl_screen.c | 9 +++------ 26 files changed, 76 insertions(+), 129 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 41a889bec..478641a24 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -96,10 +96,6 @@ typedef struct vid_render_funcs_s { void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); - void (*SCR_SetFOV) (float fov); - void (*SCR_DrawRam) (void); - void (*SCR_DrawTurtle) (void); - void (*SCR_DrawPause) (void); struct tex_s *(*SCR_CaptureBGR) (void); struct tex_s *(*SCR_ScreenShot) (unsigned width, unsigned height); void (*SCR_DrawStringToSnap) (const char *s, struct tex_s *tex, @@ -115,12 +111,7 @@ typedef struct vid_render_funcs_s { void (*R_ClearState) (void); void (*R_LoadSkys) (const char *); void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); - void (*R_AddEfrags) (mod_brush_t *brush, entity_t *ent); - void (*R_RemoveEfrags) (entity_t *ent); void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); - dlight_t *(*R_AllocDlight) (int key); - void (*R_MaxDlightsCheck) (struct cvar_s *var); - void (*R_DecayLights) (double frametime); void (*R_ViewChanged) (void); void (*SCR_ScreenShot_f) (void); diff --git a/include/QF/render.h b/include/QF/render.h index fa36bff67..c8f277ca6 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -239,4 +239,10 @@ void R_LoadModule (struct vid_internal_s *vid_internal); struct progs_s; void R_Progs_Init (struct progs_s *pr); +void R_AddEfrags (mod_brush_t *, entity_t *ent); +void R_RemoveEfrags (entity_t *ent); +dlight_t *R_AllocDlight (int key); +void R_MaxDlightsCheck (struct cvar_s *var); +void R_DecayLights (double frametime); + #endif//__QF_render_h diff --git a/include/QF/screen.h b/include/QF/screen.h index 6aaea601d..4adf0a519 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -32,6 +32,11 @@ struct transform_s; void SCR_Init (void); +void SCR_SetFOV (float fov); + +void SCR_DrawRam (void); +void SCR_DrawTurtle (void); +void SCR_DrawPause (void); typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array diff --git a/include/r_internal.h b/include/r_internal.h index e2924f047..14476d74b 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -62,9 +62,6 @@ struct psystem_s *sw_ParticleSystem (void); struct psystem_s *sw32_ParticleSystem (void); void R_RunParticles (float dT); -void R_AddEfrags (mod_brush_t *, entity_t *ent); -void R_RemoveEfrags (entity_t *ent); - void R_NewMap (model_t *worldmodel, model_t **models, int num_models); // LordHavoc: relative bmodel lighting diff --git a/include/r_screen.h b/include/r_screen.h index e9059e0df..1a0b91860 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -31,13 +31,9 @@ #ifndef __r_screen_h #define __r_screen_h -void SCR_DrawRam (void); -void SCR_DrawTurtle (void); -void SCR_DrawPause (void); struct tex_s *SCR_CaptureBGR (void); struct tex_s *SCR_ScreenShot (unsigned width, unsigned height); void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); -void SCR_SetFOV (float fov); void SCR_ScreenShot_f (void); int MipColor (int r, int g, int b); diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index f327a1e6d..e5fc1d858 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -64,7 +64,7 @@ CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size, return; } - dl = r_funcs->R_AllocDlight (key); + dl = R_AllocDlight (key); if (!dl) return; VectorCopy (org, dl->origin); @@ -124,7 +124,7 @@ CL_ModelEffects (entity_t *ent, int num, int glow_color, double time) // add automatic particle trails if (model->flags & EF_ROCKET) { - dl = r_funcs->R_AllocDlight (num); + dl = R_AllocDlight (num); if (dl) { VectorCopy (ent_origin, dl->origin); dl->radius = 200.0; @@ -154,7 +154,7 @@ void CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num, double time) { - dlight_t *dl = r_funcs->R_AllocDlight (num); + dlight_t *dl = R_AllocDlight (num); if (dl) { position += 18 * fv; VectorCopy (position, dl->origin); diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 86f41a339..fefdb3b35 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -213,7 +213,7 @@ beam_clear (beam_t *b) tent_t *t; for (t = b->tents; t; t = t->next) { - r_funcs->R_RemoveEfrags (t->ent); + R_RemoveEfrags (t->ent); t->ent->visibility.efrag = 0; } free_temp_entities (b->tents); @@ -271,7 +271,7 @@ beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx) } else { Transform_SetLocalPosition (tent->ent->transform, position); } - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, tent->ent); + R_AddEfrags (&cl_world.worldmodel->brush, tent->ent); } } @@ -350,7 +350,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, clp_funcs->ParticleExplosion (position); // light - dl = r_funcs->R_AllocDlight (0); + dl = R_AllocDlight (0); if (dl) { VectorCopy (position, dl->origin); dl->radius = 350; @@ -385,7 +385,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, colorLength = MSG_ReadByte (net_message); S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); clp_funcs->ParticleExplosion2 (position, colorStart, colorLength); - dl = r_funcs->R_AllocDlight (0); + dl = R_AllocDlight (0); if (!dl) break; VectorCopy (position, dl->origin); @@ -403,7 +403,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, color[3] = 0.7; clp_funcs->ParticleExplosion (position); S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); - dl = r_funcs->R_AllocDlight (0); + dl = R_AllocDlight (0); if (dl) { VectorCopy (position, dl->origin); dl->radius = 350; @@ -447,7 +447,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, MSG_ReadCoordV (net_message, &position[0]); // light - dl = r_funcs->R_AllocDlight (0); + dl = R_AllocDlight (0); if (dl) { VectorCopy (position, dl->origin); dl->radius = 150; @@ -620,7 +620,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) f = 10 * (time - ex->start); if (f >= ent->renderer.model->numframes) { tent_obj_t *_to; - r_funcs->R_RemoveEfrags (ent); + R_RemoveEfrags (ent); ent->visibility.efrag = 0; free_temp_entities (ex->tent); _to = *to; @@ -632,7 +632,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) ent->animation.frame = f; if (!ent->visibility.efrag) { - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); } } } @@ -673,7 +673,7 @@ CL_ClearProjectiles (void) tent_t *tent; for (tent = cl_projectiles; tent; tent = tent->next) { - r_funcs->R_RemoveEfrags (tent->ent); + R_RemoveEfrags (tent->ent); tent->ent->visibility.efrag = 0; } free_temp_entities (cl_projectiles); @@ -721,7 +721,7 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) angles[2] = 0; CL_TransformEntity (tent->ent, 1, angles, position); - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, tent->ent); + R_AddEfrags (&cl_world.worldmodel->brush, tent->ent); } *tail = cl_projectiles; diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index f0ef82072..61dfa3abe 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -119,7 +119,7 @@ CL_ParseStatic (qmsg_t *msg, int version) CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin); - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); } static void diff --git a/libs/client/locs.c b/libs/client/locs.c index e8e2df89e..9f98a7ce6 100644 --- a/libs/client/locs.c +++ b/libs/client/locs.c @@ -298,7 +298,7 @@ locs_draw (double time, vec4f_t simorg) nearloc = locs_find (simorg); if (nearloc) { - dl = r_funcs->R_AllocDlight (4096); + dl = R_AllocDlight (4096); if (dl) { VectorCopy (nearloc->loc, dl->origin); dl->radius = 200; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 0a676497c..1d498b249 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -32,12 +32,9 @@ video_renderer_common_sources = \ libs/video/renderer/r_billboard.c \ libs/video/renderer/r_bsp.c \ libs/video/renderer/r_dyn_textures.c \ - libs/video/renderer/r_efrag.c \ libs/video/renderer/r_ent.c \ libs/video/renderer/r_graph.c \ libs/video/renderer/r_iqm.c \ - libs/video/renderer/r_light.c \ - libs/video/renderer/r_main.c \ libs/video/renderer/r_part.c \ libs/video/renderer/r_sprite.c \ libs/video/renderer/vid_common.c @@ -51,7 +48,10 @@ libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libs) libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs) libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_cvar.c \ + libs/video/renderer/r_efrag.c \ libs/video/renderer/r_init.c \ + libs/video/renderer/r_light.c \ + libs/video/renderer/r_main.c \ libs/video/renderer/r_scrap.c \ libs/video/renderer/r_screen.c \ libs/video/renderer/r_progs.c diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index 24a9b6234..94a9b88e8 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -200,7 +200,7 @@ viewsize_f (cvar_t *var) static void r_dlight_max_f (cvar_t *var) { - r_funcs->R_MaxDlightsCheck (var); + R_MaxDlightsCheck (var); } void diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 6c2bd3a70..09129ed8c 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -46,6 +46,8 @@ typedef struct s_efrag_list { static efrag_t *r_free_efrags; static t_efrag_list *efrag_list; +entqueue_t *r_ent_queue; + /* ENTITY FRAGMENT FUNCTIONS */ static inline void @@ -204,11 +206,9 @@ R_AddEfrags (mod_brush_t *brush, entity_t *ent) model_t *entmodel; vec3_t emins, emaxs; - if (!ent->renderer.model || !r_worldentity.renderer.model) + if (!ent->renderer.model) { return; - - if (ent == &r_worldentity) - return; // never add the world + } entmodel = ent->renderer.model; diff --git a/libs/video/renderer/r_ent.c b/libs/video/renderer/r_ent.c index fb133d388..6868a38ef 100644 --- a/libs/video/renderer/r_ent.c +++ b/libs/video/renderer/r_ent.c @@ -48,8 +48,6 @@ #include "r_internal.h" -entqueue_t *r_ent_queue; - float R_EntityBlend (animation_t *animation, int pose, float interval) { diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 7debf10c1..8ecf947de 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -63,7 +63,7 @@ R_FindNearLights (const vec3_t pos, int count, dlight_t **lights) dl = r_dlights; for (i = 0; i < r_maxdlights; i++, dl++) { - if (dl->die < vr_data.realtime || !dl->radius) + if (dl->die < r_data->realtime || !dl->radius) continue; VectorSubtract (dl->origin, pos, d); score = DotProduct (d, d) / dl->radius; @@ -128,19 +128,19 @@ R_AnimateLight (void) // light animations // 'm' is normal light, 'a' is no light, 'z' is double bright - i = (int) (vr_data.realtime * 10); + i = (int) (r_data->realtime * 10); for (j = 0; j < MAX_LIGHTSTYLES; j++) { - if (!vr_data.lightstyle[j].length) { + if (!r_data->lightstyle[j].length) { d_lightstylevalue[j] = 256; continue; } if (r_flatlightstyles->int_val == 2) { - k = vr_data.lightstyle[j].peak - 'a'; + k = r_data->lightstyle[j].peak - 'a'; } else if (r_flatlightstyles->int_val == 1) { - k = vr_data.lightstyle[j].average - 'a'; + k = r_data->lightstyle[j].average - 'a'; } else { - k = i % vr_data.lightstyle[j].length; - k = vr_data.lightstyle[j].map[k] - 'a'; + k = i % r_data->lightstyle[j].length; + k = r_data->lightstyle[j].map[k] - 'a'; } d_lightstylevalue[j] = k * 22; } @@ -325,7 +325,7 @@ R_PushDlights (const vec3_t entorigin) l = r_dlights; for (i = 0; i < r_maxdlights; i++, l++) { - if (l->die < vr_data.realtime || !l->radius) + if (l->die < r_data->realtime || !l->radius) continue; VectorSubtract (l->origin, entorigin, lightorigin); R_MarkLights (lightorigin, l, i, r_worldentity.renderer.model); @@ -526,7 +526,7 @@ R_AllocDlight (int key) // then look for anything else dl = r_dlights; for (i = 0; i < r_maxdlights; i++, dl++) { - if (dl->die < vr_data.realtime) { + if (dl->die < r_data->realtime) { memset (dl, 0, sizeof (*dl)); dl->key = key; dl->color[0] = dl->color[1] = dl->color[2] = 1; @@ -548,7 +548,7 @@ R_DecayLights (double frametime) dl = r_dlights; for (i = 0; i < r_maxdlights; i++, dl++) { - if (dl->die < vr_data.realtime || !dl->radius) + if (dl->die < r_data->realtime || !dl->radius) continue; dl->radius -= frametime * dl->decay; diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index d56d065e3..ad2e5c272 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -131,10 +131,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_Picf, gl_Draw_SubPic, - SCR_SetFOV, - SCR_DrawRam, - SCR_DrawTurtle, - SCR_DrawPause, gl_SCR_CaptureBGR, gl_SCR_ScreenShot, SCR_DrawStringToSnap, @@ -148,12 +144,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_ClearState, gl_R_LoadSkys, gl_R_NewMap, - R_AddEfrags, - R_RemoveEfrags, gl_R_LineGraph, - R_AllocDlight, - R_MaxDlightsCheck, - R_DecayLights, gl_R_ViewChanged, gl_SCR_ScreenShot_f, &model_funcs diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index b611eb25e..a0978a685 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -130,10 +130,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_Picf, glsl_Draw_SubPic, - SCR_SetFOV, - SCR_DrawRam, - SCR_DrawTurtle, - SCR_DrawPause, glsl_SCR_CaptureBGR, glsl_SCR_ScreenShot, SCR_DrawStringToSnap, @@ -147,12 +143,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_ClearState, glsl_R_LoadSkys, glsl_R_NewMap, - R_AddEfrags, - R_RemoveEfrags, glsl_R_LineGraph, - R_AllocDlight, - R_MaxDlightsCheck, - R_DecayLights, glsl_R_ViewChanged, glsl_SCR_ScreenShot_f, &model_funcs diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 325371a07..02ba975b7 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -127,10 +127,6 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_Picf, Draw_SubPic, - SCR_SetFOV, - SCR_DrawRam, - SCR_DrawTurtle, - SCR_DrawPause, SCR_CaptureBGR, SCR_ScreenShot, SCR_DrawStringToSnap, @@ -144,12 +140,7 @@ vid_render_funcs_t sw_vid_render_funcs = { R_ClearState, R_LoadSkys, R_NewMap, - R_AddEfrags, - R_RemoveEfrags, R_LineGraph, - R_AllocDlight, - R_MaxDlightsCheck, - R_DecayLights, R_ViewChanged, SCR_ScreenShot_f, &model_funcs diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 95f81a8e1..0fe8469fb 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -132,10 +132,6 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_Draw_Picf, sw32_Draw_SubPic, - SCR_SetFOV, - SCR_DrawRam, - SCR_DrawTurtle, - SCR_DrawPause, sw32_SCR_CaptureBGR, sw32_SCR_ScreenShot, SCR_DrawStringToSnap, @@ -149,12 +145,7 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_R_ClearState, sw32_R_LoadSkys, sw32_R_NewMap, - R_AddEfrags, - R_RemoveEfrags, sw32_R_LineGraph, - R_AllocDlight, - R_MaxDlightsCheck, - R_DecayLights, sw32_R_ViewChanged, sw32_SCR_ScreenShot_f, &model_funcs diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index cb05aea8c..d72e2da86 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -661,10 +661,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_Picf, vulkan_Draw_SubPic, - SCR_SetFOV, - SCR_DrawRam, - SCR_DrawTurtle, - SCR_DrawPause, vulkan_SCR_CaptureBGR, vulkan_SCR_ScreenShot, SCR_DrawStringToSnap, @@ -678,12 +674,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_R_ClearState, vulkan_R_LoadSkys, vulkan_R_NewMap, - R_AddEfrags, - R_RemoveEfrags, vulkan_R_LineGraph, - R_AllocDlight, - R_MaxDlightsCheck, - R_DecayLights, vulkan_R_ViewChanged, vulkan_SCR_ScreenShot_f, &model_funcs diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index a85b46c56..47cd44293 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -212,7 +212,7 @@ CL_RelinkEntities (void) renderer->model = NULL; animation->pose1 = animation->pose2 = -1; if (ent->visibility.efrag) { - r_funcs->R_RemoveEfrags (ent); // just became empty + R_RemoveEfrags (ent); // just became empty } continue; } @@ -261,9 +261,9 @@ CL_RelinkEntities (void) new->origin); if (i != cl.viewentity || chase_active->int_val) { if (ent->visibility.efrag) { - r_funcs->R_RemoveEfrags (ent); + R_RemoveEfrags (ent); } - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); } ent->old_origin = new->origin; } else { @@ -298,11 +298,11 @@ CL_RelinkEntities (void) vec4f_t org = Transform_GetWorldPosition (ent->transform); if (!VectorCompare (org, ent->old_origin)) {//FIXME - r_funcs->R_RemoveEfrags (ent); - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_RemoveEfrags (ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); } } else { - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); } } } diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 7c2a033f7..fe533c95f 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -100,9 +100,9 @@ scr_draw_views (void) static SCR_Func scr_funcs_normal[] = { 0, //Draw_Crosshair, - 0, //SCR_DrawRam, - 0, //SCR_DrawTurtle, - 0, //SCR_DrawPause, + SCR_DrawRam, + SCR_DrawTurtle, + SCR_DrawPause, Sbar_Draw, SCR_CShift, Sbar_DrawCenterPrint, @@ -164,9 +164,6 @@ CL_UpdateScreen (double realtime) r_data->min_wateralpha = 1.0; } scr_funcs_normal[0] = r_funcs->Draw_Crosshair; - scr_funcs_normal[1] = r_funcs->SCR_DrawRam; - scr_funcs_normal[2] = r_funcs->SCR_DrawTurtle; - scr_funcs_normal[3] = r_funcs->SCR_DrawPause; cl.viewstate.intermission = cl.intermission != 0; V_PrepBlend (&cl.viewstate); diff --git a/nq/source/host.c b/nq/source/host.c index e4007dd37..5ec8ee16e 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -617,7 +617,7 @@ Host_ClientFrame (void) if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); - r_funcs->R_DecayLights (host_frametime); + R_DecayLights (host_frametime); } else S_Update (0, 0); diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index d8a0a601e..d687063ed 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -165,3 +165,8 @@ console_client_PluginInfo (void) { return 0; } + +void +R_DecayLights (double frametime) +{ +} diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 19cc8f9ac..e844afe69 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -165,7 +165,7 @@ CL_LinkPacketEntities (void) renderer->model = NULL; animation->pose1 = animation->pose2 = -1; if (ent->visibility.efrag) { - r_funcs->R_RemoveEfrags (ent); // just became empty + R_RemoveEfrags (ent); // just became empty } continue; } @@ -179,7 +179,7 @@ CL_LinkPacketEntities (void) || (cl_deadbodyfilter->int_val && is_dead_body (new)) || (cl_gibfilter->int_val && is_gib (new))) { if (ent->visibility.efrag) { - r_funcs->R_RemoveEfrags (ent); + R_RemoveEfrags (ent); } continue; } @@ -232,9 +232,9 @@ CL_LinkPacketEntities (void) new->origin); if (i != cl.viewentity || chase_active->int_val) { if (ent->visibility.efrag) { - r_funcs->R_RemoveEfrags (ent); + R_RemoveEfrags (ent); } - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); } } else { vec4f_t delta = new->origin - old->origin; @@ -265,16 +265,16 @@ CL_LinkPacketEntities (void) vec4f_t org = Transform_GetWorldPosition (ent->transform); if (!VectorCompare (org, ent->old_origin)) {//FIXME - r_funcs->R_RemoveEfrags (ent); - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_RemoveEfrags (ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); } } else { - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); } } } if (!ent->visibility.efrag) { - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); } // rotate binary objects locally @@ -400,9 +400,9 @@ CL_LinkPlayers (void) j < MAX_CLIENTS; j++, player++, state++) { ent = CL_GetEntity (j + 1); if (ent->visibility.efrag) - r_funcs->R_RemoveEfrags (ent); + R_RemoveEfrags (ent); if (player->flag_ent && player->flag_ent->visibility.efrag) { - r_funcs->R_RemoveEfrags (player->flag_ent); + R_RemoveEfrags (player->flag_ent); } if (state->messagenum != cl.parsecount) continue; // not present this frame @@ -421,7 +421,7 @@ CL_LinkPlayers (void) clientplayer = false; } if (player->chat && player->chat->value[0] != '0') { - dlight_t *dl = r_funcs->R_AllocDlight (j + 1); + dlight_t *dl = R_AllocDlight (j + 1); VectorCopy (org, dl->origin); dl->radius = 100; dl->die = cl.time + 0.1; @@ -511,10 +511,10 @@ CL_LinkPlayers (void) } // stuff entity in map - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.worldmodel->brush, ent); if (player->flag_ent) { CL_UpdateFlagModels (ent, j); - r_funcs->R_AddEfrags (&cl_world.worldmodel->brush, player->flag_ent); + R_AddEfrags (&cl_world.worldmodel->brush, player->flag_ent); } } } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 6b4bb9f18..6b8e8301a 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1735,7 +1735,7 @@ Host_Frame (float time) if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); - r_funcs->R_DecayLights (host_frametime); + R_DecayLights (host_frametime); } else S_Update (0, 0); diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 6584516cd..3242a7ebe 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -109,9 +109,9 @@ scr_draw_views (void) static SCR_Func scr_funcs_normal[] = { 0, //Draw_Crosshair, - 0, //SCR_DrawRam, - 0, //SCR_DrawTurtle, - 0, //SCR_DrawPause, + SCR_DrawRam, + SCR_DrawTurtle, + SCR_DrawPause, Sbar_Draw, SCR_CShift, scr_draw_views, @@ -185,9 +185,6 @@ CL_UpdateScreen (double realtime) r_data->min_wateralpha = 1.0; } scr_funcs_normal[0] = r_funcs->Draw_Crosshair; - scr_funcs_normal[1] = r_funcs->SCR_DrawRam; - scr_funcs_normal[2] = r_funcs->SCR_DrawTurtle; - scr_funcs_normal[3] = r_funcs->SCR_DrawPause; if (cl.viewstate.flags & VF_GIB) { cl.viewstate.height = 8; // gib view height From ea2fd322280b4f6be9ac33d3ef5149c0389d4f91 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 14:39:47 +0900 Subject: [PATCH 2504/3664] [renderer] Merge screenshot code as much as possible Only CaptureBGR is per-renderer as the rest of the screenshot code uses it to do the actual capture (which is target dependent). Vulkan is currently broken due to capture being an asynchronous process and the rest of the code expecting capture to be synchronous (also, bgr vs rgb). The best thing is all renderers now write the same format (currently png). --- include/QF/plugin/vid_render.h | 5 -- include/QF/screen.h | 3 + libs/video/renderer/gl/gl_screen.c | 83 ------------------------ libs/video/renderer/glsl/glsl_screen.c | 26 -------- libs/video/renderer/r_screen.c | 84 ++++++++++++++++++++++++- libs/video/renderer/sw/screen.c | 82 ------------------------ libs/video/renderer/sw32/screen.c | 42 ------------- libs/video/renderer/vid_render_gl.c | 3 - libs/video/renderer/vid_render_glsl.c | 3 - libs/video/renderer/vid_render_sw.c | 3 - libs/video/renderer/vid_render_sw32.c | 3 - libs/video/renderer/vid_render_vulkan.c | 25 ++------ qw/source/cl_rss.c | 17 +++-- 13 files changed, 98 insertions(+), 281 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 478641a24..aa17f35ec 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -97,9 +97,6 @@ typedef struct vid_render_funcs_s { void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); struct tex_s *(*SCR_CaptureBGR) (void); - struct tex_s *(*SCR_ScreenShot) (unsigned width, unsigned height); - void (*SCR_DrawStringToSnap) (const char *s, struct tex_s *tex, - int x, int y); void (*Fog_Update) (float density, float red, float green, float blue, float time); @@ -112,9 +109,7 @@ typedef struct vid_render_funcs_s { void (*R_LoadSkys) (const char *); void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); - void (*R_ViewChanged) (void); - void (*SCR_ScreenShot_f) (void); vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/QF/screen.h b/include/QF/screen.h index 4adf0a519..c58351d84 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -30,6 +30,7 @@ #define __QF_screen_h struct transform_s; +struct tex_s; void SCR_Init (void); void SCR_SetFOV (float fov); @@ -42,6 +43,8 @@ typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array void SCR_UpdateScreen (struct transform_s *camera, double realtime, SCR_Func *scr_funcs); +void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); +struct tex_s *SCR_SnapScreen (unsigned width, unsigned height); extern struct cvar_s *hud_fps, *hud_time; diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 8e03bc5f9..3647b2c53 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -83,89 +83,6 @@ gl_SCR_CaptureBGR (void) return tex; } -tex_t * -gl_SCR_ScreenShot (unsigned width, unsigned height) -{ - unsigned char *src, *dest, *snap; - float fracw, frach; - int count, dex, dey, dx, dy, nx, r, g, b, x, y, w, h; - tex_t *tex; - - snap = Hunk_TempAlloc (0, vid.width * vid.height * 3); - - qfglReadPixels (0, 0, vid.width, vid.height, GL_RGB, GL_UNSIGNED_BYTE, - snap); - - w = (vid.width < width) ? vid.width : width; - h = (vid.height < height) ? vid.height : height; - - fracw = (float) vid.width / (float) w; - frach = (float) vid.height / (float) h; - - tex = malloc (sizeof (tex_t) + w * h); - tex->data = (byte *) (tex + 1); - if (!tex) - return 0; - - tex->width = w; - tex->height = h; - tex->palette = vid.palette; - - for (y = 0; y < h; y++) { - dest = tex->data + (w * y); - - for (x = 0; x < w; x++) { - r = g = b = 0; - - dx = x * fracw; - dex = (x + 1) * fracw; - if (dex == dx) - dex++; // at least one - dy = y * frach; - dey = (y + 1) * frach; - if (dey == dy) - dey++; // at least one - - count = 0; - for (; dy < dey; dy++) { - src = snap + (vid.width * 3 * dy) + dx * 3; - for (nx = dx; nx < dex; nx++) { - r += *src++; - g += *src++; - b += *src++; - count++; - } - } - r /= count; - g /= count; - b /= count; - *dest++ = MipColor (r, g, b); - } - } - - return tex; -} - -void -gl_SCR_ScreenShot_f (void) -{ - dstring_t *pcxname = dstring_new (); - - // find a file name to save it to - if (!QFS_NextFilename (pcxname, - va (0, "%s/qf", qfs_gamedir->dir.shots), ".tga")) { - Sys_Printf ("SCR_ScreenShot_f: Couldn't create a TGA file\n"); - } else { - tex_t *tex; - - tex = gl_SCR_CaptureBGR (); - WriteTGAfile (pcxname->str, tex->data, tex->width, tex->height); - free (tex); - Sys_Printf ("Wrote %s/%s\n", qfs_userpath, pcxname->str); - } - dstring_delete (pcxname); -} - static void SCR_TileClear (void) { diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index a25425f02..ff110f5fa 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -219,29 +219,3 @@ glsl_SCR_CaptureBGR (void) } return tex; } - -__attribute__((const)) tex_t * -glsl_SCR_ScreenShot (unsigned width, unsigned height) -{ - return 0; -} - -void -glsl_SCR_ScreenShot_f (void) -{ - dstring_t *name = dstring_new (); - - // find a file name to save it to - if (!QFS_NextFilename (name, va (0, "%s/qf", - qfs_gamedir->dir.shots), ".png")) { - Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file\n"); - } else { - tex_t *tex; - - tex = glsl_SCR_CaptureBGR (); - WritePNGqfs (name->str, tex->data, tex->width, tex->height); - free (tex); - Sys_Printf ("Wrote %s/%s\n", qfs_userpath, name->str); - } - dstring_delete (name); -} diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 992822f5f..740b97640 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -38,11 +38,15 @@ #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/draw.h" +#include "QF/dstring.h" #include "QF/image.h" +#include "QF/png.h" #include "QF/pcx.h" +#include "QF/quakefs.h" #include "QF/render.h" #include "QF/screen.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/scene/transform.h" #include "QF/ui/view.h" @@ -185,7 +189,21 @@ SCR_SetFOV (float fov) static void ScreenShot_f (void) { - r_funcs->SCR_ScreenShot_f (); + dstring_t *name = dstring_new (); + + // find a file name to save it to + if (!QFS_NextFilename (name, va (0, "%s/qf", + qfs_gamedir->dir.shots), ".png")) { + Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file\n"); + } else { + tex_t *tex; + + tex = r_funcs->SCR_CaptureBGR (); + WritePNGqfs (name->str, tex->data, tex->width, tex->height); + free (tex); + Sys_Printf ("Wrote %s/%s\n", qfs_userpath, name->str); + } + dstring_delete (name); } /* @@ -347,12 +365,74 @@ SCR_DrawStringToSnap (const char *s, tex_t *tex, int x, int y) } } +tex_t * +SCR_SnapScreen (unsigned width, unsigned height) +{ + byte *src, *dest; + float fracw, frach; + unsigned count, dex, dey, dx, dy, nx, r, g, b, x, y, w, h; + tex_t *tex; + + tex_t *snap = r_funcs->SCR_CaptureBGR (); + + //FIXME casts + w = ((unsigned)snap->width < width) ? (unsigned)snap->width : width; + h = ((unsigned)snap->height < height) ? (unsigned)snap->height : height; + + fracw = (float) snap->width / (float) w; + frach = (float) snap->height / (float) h; + + tex = malloc (sizeof (tex_t) + w * h); + tex->data = (byte *) (tex + 1); + if (!tex) + return 0; + + tex->width = w; + tex->height = h; + tex->palette = r_data->vid->palette; + + for (y = 0; y < h; y++) { + dest = tex->data + (w * y); + + for (x = 0; x < w; x++) { + r = g = b = 0; + + dx = x * fracw; + dex = (x + 1) * fracw; + if (dex == dx) + dex++; // at least one + dy = y * frach; + dey = (y + 1) * frach; + if (dey == dy) + dey++; // at least one + + count = 0; + for (; dy < dey; dy++) { + src = snap->data + (snap->width * 3 * dy) + dx * 3; + for (nx = dx; nx < dex; nx++) { + b += *src++; + g += *src++; + r += *src++; + count++; + } + } + r /= count; + g /= count; + b /= count; + *dest++ = MipColor (r, g, b); + } + } + free (snap); + + return tex; +} + void SCR_Init (void) { // register our commands Cmd_AddCommand ("screenshot", ScreenShot_f, "Take a screenshot, " - "saves as qfxxx.pcx in the current directory"); + "saves as qfxxxx.png in the QF directory"); Cmd_AddCommand ("sizeup", SCR_SizeUp_f, "Increases the screen size"); Cmd_AddCommand ("sizedown", SCR_SizeDown_f, "Decreases the screen size"); diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 3e5b288d6..27a3741d1 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -85,88 +85,6 @@ SCR_CaptureBGR (void) return tex; } -tex_t * -SCR_ScreenShot (unsigned width, unsigned height) -{ - unsigned char *src, *dest; - float fracw, frach; - int count, dex, dey, dx, dy, nx, r, g, b, x, y, w, h; - tex_t *tex; - - w = (vid.width < width) ? vid.width : width; - h = (vid.height < height) ? vid.height : height; - - fracw = (float) vid.width / (float) w; - frach = (float) vid.height / (float) h; - - tex = malloc (sizeof (tex_t) + w * h); - tex->data = (byte *) (tex + 1); - if (!tex) - return 0; - - tex->width = w; - tex->height = h; - tex->palette = vid.palette; - - for (y = 0; y < h; y++) { - dest = tex->data + (w * (h - y - 1)); - - for (x = 0; x < w; x++) { - r = g = b = 0; - - dx = x * fracw; - dex = (x + 1) * fracw; - if (dex == dx) - dex++; // at least one - dy = y * frach; - dey = (y + 1) * frach; - if (dey == dy) - dey++; // at least one - - count = 0; - for (; dy < dey; dy++) { - src = ((byte*)vid.buffer) + (vid.rowbytes * dy) + dx; - for (nx = dx; nx < dex; nx++) { - r += vid.basepal[*src * 3]; - g += vid.basepal[*src * 3 + 1]; - b += vid.basepal[*src * 3 + 2]; - src++; - count++; - } - } - r /= count; - g /= count; - b /= count; - *dest++ = MipColor (r, g, b); - } - } - - return tex; -} - -void -SCR_ScreenShot_f (void) -{ - dstring_t *pcxname = dstring_new (); - pcx_t *pcx; - int pcx_len; - - // find a file name to save it to - if (!QFS_NextFilename (pcxname, - va (0, "%s/qf", qfs_gamedir->dir.shots), ".pcx")) { - Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); - } else { - // save the pcx file - pcx = EncodePCX (vid.buffer, vid.width, vid.height, vid.rowbytes, - vid.basepal, false, &pcx_len); - QFS_WriteFile (pcxname->str, pcx, pcx_len); - - - Sys_Printf ("Wrote %s/%s\n", qfs_userpath, pcxname->str); - } - dstring_delete (pcxname); -} - void R_RenderFrame (SCR_Func *scr_funcs) { diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index 4a77aac77..072c88182 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -88,48 +88,6 @@ sw32_SCR_CaptureBGR (void) return tex; } -__attribute__((const)) tex_t * -sw32_SCR_ScreenShot (unsigned width, unsigned height) -{ - return 0; -} - -void -sw32_SCR_ScreenShot_f (void) -{ - dstring_t *pcxname = dstring_new (); - pcx_t *pcx = 0; - int pcx_len; - - // find a file name to save it to - if (!QFS_NextFilename (pcxname, va (0, "%s/qf", - qfs_gamedir->dir.shots), ".pcx")) { - Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); - } else { - // save the pcx file - switch(sw32_ctx->pixbytes) { - case 1: - pcx = EncodePCX (vid.buffer, vid.width, vid.height, vid.rowbytes, - vid.basepal, false, &pcx_len); - break; - case 2: - Sys_Printf("SCR_ScreenShot_f: FIXME - add 16bit support\n"); - break; - case 4: - Sys_Printf("SCR_ScreenShot_f: FIXME - add 32bit support\n"); - break; - default: - Sys_Error("SCR_ScreenShot_f: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } - - if (pcx) { - QFS_WriteFile (pcxname->str, pcx, pcx_len); - Sys_Printf ("Wrote %s/%s\n", qfs_userpath, pcxname->str); - } - } - dstring_delete (pcxname); -} - void sw32_R_RenderFrame (SCR_Func *scr_funcs) { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index ad2e5c272..c68cd8c9e 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -132,8 +132,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_SubPic, gl_SCR_CaptureBGR, - gl_SCR_ScreenShot, - SCR_DrawStringToSnap, gl_Fog_Update, gl_Fog_ParseWorldspawn, @@ -146,7 +144,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_NewMap, gl_R_LineGraph, gl_R_ViewChanged, - gl_SCR_ScreenShot_f, &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index a0978a685..2ca14d425 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -131,8 +131,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_SubPic, glsl_SCR_CaptureBGR, - glsl_SCR_ScreenShot, - SCR_DrawStringToSnap, glsl_Fog_Update, glsl_Fog_ParseWorldspawn, @@ -145,7 +143,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_NewMap, glsl_R_LineGraph, glsl_R_ViewChanged, - glsl_SCR_ScreenShot_f, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 02ba975b7..9ad7939ec 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -128,8 +128,6 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_SubPic, SCR_CaptureBGR, - SCR_ScreenShot, - SCR_DrawStringToSnap, 0, 0, @@ -142,7 +140,6 @@ vid_render_funcs_t sw_vid_render_funcs = { R_NewMap, R_LineGraph, R_ViewChanged, - SCR_ScreenShot_f, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 0fe8469fb..4f417d840 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -133,8 +133,6 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_Draw_SubPic, sw32_SCR_CaptureBGR, - sw32_SCR_ScreenShot, - SCR_DrawStringToSnap, 0, 0, @@ -147,7 +145,6 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_R_NewMap, sw32_R_LineGraph, sw32_R_ViewChanged, - sw32_SCR_ScreenShot_f, &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index d72e2da86..72e6caa5e 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -70,18 +70,6 @@ static vulkan_ctx_t *vulkan_ctx; -static tex_t * -vulkan_SCR_CaptureBGR (void) -{ - return 0; -} - -static tex_t * -vulkan_SCR_ScreenShot (unsigned width, unsigned height) -{ - return 0; -} - static void vulkan_Fog_Update (float density, float red, float green, float blue, float time) @@ -442,14 +430,16 @@ capture_screenshot (const byte *data, int width, int height) dstring_delete (name); } -static void -vulkan_SCR_ScreenShot_f (void) +static tex_t * +vulkan_SCR_CaptureBGR (void) { if (!vulkan_ctx->capture) { - Sys_Printf ("Screenshot not supported\n"); - return; + Sys_Printf ("Capture not supported\n"); + return 0; } vulkan_ctx->capture_callback = capture_screenshot; + //FIXME async process + return 0; } static void @@ -662,8 +652,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_SubPic, vulkan_SCR_CaptureBGR, - vulkan_SCR_ScreenShot, - SCR_DrawStringToSnap, vulkan_Fog_Update, vulkan_Fog_ParseWorldspawn, @@ -676,7 +664,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_R_NewMap, vulkan_R_LineGraph, vulkan_R_ViewChanged, - vulkan_SCR_ScreenShot_f, &model_funcs }; diff --git a/qw/source/cl_rss.c b/qw/source/cl_rss.c index bb4cbd993..ad519418a 100644 --- a/qw/source/cl_rss.c +++ b/qw/source/cl_rss.c @@ -61,25 +61,22 @@ CL_RSShot_f (void) Sys_Printf ("Remote screen shot requested.\n"); - tex = r_funcs->SCR_ScreenShot (RSSHOT_WIDTH, RSSHOT_HEIGHT); + tex = SCR_SnapScreen (RSSHOT_WIDTH, RSSHOT_HEIGHT); if (tex) { time (&now); st = dstring_strdup (ctime (&now)); dstring_snip (st, strlen (st->str) - 1, 1); - r_funcs->SCR_DrawStringToSnap (st->str, tex, - tex->width - strlen (st->str) * 8, - tex->height - 1); + SCR_DrawStringToSnap (st->str, tex, tex->width - strlen (st->str) * 8, + tex->height - 1); dstring_copystr (st, cls.servername->str); - r_funcs->SCR_DrawStringToSnap (st->str, tex, - tex->width - strlen (st->str) * 8, - tex->height - 11); + SCR_DrawStringToSnap (st->str, tex, tex->width - strlen (st->str) * 8, + tex->height - 11); dstring_copystr (st, cl_name->string); - r_funcs->SCR_DrawStringToSnap (st->str, tex, - tex->width - strlen (st->str) * 8, - tex->height - 21); + SCR_DrawStringToSnap (st->str, tex, tex->width - strlen (st->str) * 8, + tex->height - 21); pcx = EncodePCX (tex->data, tex->width, tex->height, tex->width, r_data->vid->basepal, true, &pcx_len); From ea223f631215b102a69237615b249d2b2fec3d70 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 16:57:22 +0900 Subject: [PATCH 2505/3664] [sw] Clean up use of r_rectdesc I have no idea why the struct even had a local vrect that was used for temporary storage. --- libs/video/renderer/sw/draw.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 1b3d0c0c9..b242e06c1 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -49,7 +49,6 @@ #include "vid_internal.h" typedef struct { - vrect_t rect; int width; int height; byte *ptexbytes; @@ -699,19 +698,14 @@ Draw_TileClear (int x, int y, int w, int h) CLIP (x, y, w, h, (int) vid.width, (int) vid.height); - r_rectdesc.rect.x = x; - r_rectdesc.rect.y = y; - r_rectdesc.rect.width = w; - r_rectdesc.rect.height = h; - - vr.y = r_rectdesc.rect.y; - height = r_rectdesc.rect.height; + vr.y = y; + height = h; tileoffsety = vr.y % r_rectdesc.height; while (height > 0) { - vr.x = r_rectdesc.rect.x; - width = r_rectdesc.rect.width; + vr.x = x; + width = w; if (tileoffsety != 0) vr.height = r_rectdesc.height - tileoffsety; From e1d38a9373d5aaa1e36e035eaf1ad74da9f5db2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 16:59:01 +0900 Subject: [PATCH 2506/3664] [renderer] Force-link r_efrag.o for static qwaq As qwaq doesn't yet do any 3d rendering, it doesn't use efrags and thus wasn't pulling in the object file, but the various renderers were trying to access it. And I thought plugin builds were more difficult (I had forgotten). --- libs/video/renderer/r_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 5c39ba165..a3a418dd8 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -97,4 +97,5 @@ VISIBLE void R_Init (void) { r_funcs->R_Init (); + R_ClearEfrags (); //FIXME force link of r_efrag.o for qwaq } From af0c66dff92ea1cc12cc0514f6b779e83e88112d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Mar 2022 23:32:44 +0900 Subject: [PATCH 2507/3664] [renderer] Move frame rendering out a layer. This is a step towards high-level unification of the renderers, as far as possible keeping only actual low-level implementation details in the individual renderers (some higher level stuff, eg shadows, is expected to be per-renderer as some things are just not feasible to implement in all renderers). However, the idea is to move the high-level functionality into scene rendering. --- include/QF/plugin/vid_render.h | 6 +- include/r_screen.h | 6 - include/vid_gl.h | 8 + include/vid_sw.h | 3 + libs/video/renderer/gl/gl_mod_alias.c | 3 +- libs/video/renderer/gl/gl_rmain.c | 5 - libs/video/renderer/gl/gl_rsurf.c | 7 +- libs/video/renderer/gl/gl_screen.c | 117 +------- libs/video/renderer/glsl/glsl_screen.c | 154 +--------- libs/video/renderer/r_screen.c | 14 +- libs/video/renderer/sw/screen.c | 63 +--- libs/video/renderer/sw32/namehack.h | 1 - libs/video/renderer/sw32/screen.c | 64 +---- libs/video/renderer/vid_render_gl.c | 97 ++++++- libs/video/renderer/vid_render_glsl.c | 136 ++++++++- libs/video/renderer/vid_render_sw.c | 57 +++- libs/video/renderer/vid_render_sw32.c | 54 +++- libs/video/renderer/vid_render_vulkan.c | 271 ++++++++++-------- .../video/renderer/vulkan/vulkan_vid_common.c | 2 +- 19 files changed, 524 insertions(+), 544 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index aa17f35ec..26233dcaa 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -104,13 +104,17 @@ typedef struct vid_render_funcs_s { struct psystem_s *(*ParticleSystem) (void); void (*R_Init) (void); - void (*R_RenderFrame) (SCR_Func *scr_funcs); void (*R_ClearState) (void); void (*R_LoadSkys) (const char *); void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); void (*R_ViewChanged) (void); + void (*begin_frame) (void); + void (*render_view) (void); + void (*set_2d) (void); + void (*end_frame) (void); + vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/r_screen.h b/include/r_screen.h index 1a0b91860..41963b400 100644 --- a/include/r_screen.h +++ b/include/r_screen.h @@ -31,12 +31,6 @@ #ifndef __r_screen_h #define __r_screen_h -struct tex_s *SCR_CaptureBGR (void); -struct tex_s *SCR_ScreenShot (unsigned width, unsigned height); -void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); -void SCR_ScreenShot_f (void); -int MipColor (int r, int g, int b); - extern int scr_copytop; extern qboolean scr_skipupdate; diff --git a/include/vid_gl.h b/include/vid_gl.h index 7ad9378b1..b4cd3b45f 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -12,9 +12,17 @@ typedef struct gl_ctx_s { void (*init_gl) (void); void *(*get_proc_address) (const char *name, qboolean crit); void (*end_rendering) (void); + + int begun; + double start_time; + int brush_polys; + int alias_polys; } gl_ctx_t; extern gl_ctx_t *gl_ctx; extern gl_ctx_t *glsl_ctx; +struct tex_s *gl_SCR_CaptureBGR (void); +struct tex_s *glsl_SCR_CaptureBGR (void); + #endif//__vid_gl_h diff --git a/include/vid_sw.h b/include/vid_sw.h index cd60a6d56..1515bae65 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -13,4 +13,7 @@ typedef struct sw_ctx_s { extern sw_ctx_t *sw_ctx; extern sw_ctx_t *sw32_ctx; +struct tex_s *sw_SCR_CaptureBGR (void); +struct tex_s *sw32_SCR_CaptureBGR (void); + #endif//__vid_sw_h diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index f41821031..e968586cb 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -62,6 +62,7 @@ #include "compat.h" #include "r_internal.h" +#include "vid_gl.h" typedef struct { vec3_t normal; @@ -559,7 +560,7 @@ gl_R_DrawAliasModel (entity_t *e) if (!(paliashdr = e->renderer.model->aliashdr)) { paliashdr = Cache_Get (&e->renderer.model->cache); } - gl_c_alias_polys += paliashdr->mdl.numtris; + gl_ctx->alias_polys += paliashdr->mdl.numtris; // if the model has a colorised/external skin, use it, otherwise use // the skin embedded in the model data diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 07dd2a8b2..0875da139 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -67,8 +67,6 @@ #include "r_internal.h" #include "varrays.h" -int gl_c_brush_polys, gl_c_alias_polys; - qboolean gl_envmap; // true during envmap command capture int gl_mirrortexturenum; // quake texturenum, not gltexturenum @@ -348,9 +346,6 @@ gl_R_SetupFrame (void) r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); r_cache_thrash = false; - - gl_c_brush_polys = 0; - gl_c_alias_polys = 0; } static void diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 8a131ff44..775b9ee03 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -61,6 +61,7 @@ #include "compat.h" #include "r_internal.h" +#include "vid_gl.h" static instsurf_t *waterchain = NULL; static instsurf_t **waterchain_tail = &waterchain; @@ -222,7 +223,7 @@ R_RenderBrushPoly_3 (msurface_t *surf) float *v; int i; - gl_c_brush_polys++; + gl_ctx->brush_polys++; qfglBegin (GL_POLYGON); v = surf->polys->verts[0]; @@ -243,7 +244,7 @@ R_RenderBrushPoly_2 (msurface_t *surf) float *v; int i; - gl_c_brush_polys++; + gl_ctx->brush_polys++; qfglBegin (GL_POLYGON); v = surf->polys->verts[0]; @@ -263,7 +264,7 @@ R_RenderBrushPoly_1 (msurface_t *surf) float *v; int i; - gl_c_brush_polys++; + gl_ctx->brush_polys++; qfglBegin (GL_POLYGON); v = surf->polys->verts[0]; diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 3647b2c53..8bd6c462d 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -28,38 +28,16 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" +#include -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/dstring.h" #include "QF/image.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/screen.h" #include "QF/sys.h" -#include "QF/tga.h" -#include "QF/va.h" + #include "QF/GL/defines.h" #include "QF/GL/funcs.h" -#include "QF/GL/qf_draw.h" #include "QF/GL/qf_rmain.h" -#include "QF/GL/qf_vid.h" -#include "QF/ui/view.h" -#include "compat.h" #include "r_internal.h" -#include "sbar.h" #include "vid_gl.h" /* SCREEN SHOTS */ @@ -82,94 +60,3 @@ gl_SCR_CaptureBGR (void) GL_UNSIGNED_BYTE, tex->data); return tex; } - -static void -SCR_TileClear (void) -{ - if (r_refdef.vrect.x > 0) { - // left - Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); - // right - Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, - vid.width - r_refdef.vrect.x + r_refdef.vrect.width, - vid.height - vr_data.lineadj); - } - if (r_refdef.vrect.y > 0) { - // top - Draw_TileClear (r_refdef.vrect.x, 0, - r_refdef.vrect.x + r_refdef.vrect.width, - r_refdef.vrect.y); - // bottom - Draw_TileClear (r_refdef.vrect.x, - r_refdef.vrect.y + r_refdef.vrect.height, - r_refdef.vrect.width, - vid.height - vr_data.lineadj - - (r_refdef.vrect.height + r_refdef.vrect.y)); - } -} - -static void -R_Clear (void) -{ - if (gl_clear->int_val) - qfglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - qfglClear (GL_DEPTH_BUFFER_BIT); -} - -void -gl_R_RenderFrame (SCR_Func *scr_funcs) -{ - double time1 = 0, time2; - static int begun = 0; - - if (begun) { - gl_ctx->end_rendering (); - begun = 0; - } - - //FIXME forces the status bar to redraw. needed because it does not fully - //update in sw modes but must in gl mode - vr_data.scr_copyeverything = 1; - - R_Clear (); - - begun = 1; - - if (r_speeds->int_val) { - time1 = Sys_DoubleTime (); - } - - // do 3D refresh drawing, and then update the screen - gl_R_RenderView (); - - GL_Set2D (); - GL_DrawReset (); - - // draw any areas not covered by the refresh - SCR_TileClear (); - - GL_Set2DScaled (); - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs)(); - scr_funcs++; - } - - if (r_speeds->int_val) { -// qfglFinish (); - time2 = Sys_DoubleTime (); - Sys_MaskPrintf (SYS_dev, "%3i ms %4i wpoly %4i epoly %4i parts\n", - (int) ((time2 - time1) * 1000), gl_c_brush_polys, - gl_c_alias_polys, r_psystem.numparticles); - } - - GL_FlushText (); - qfglFlush (); - - if (gl_finish->int_val) { - gl_ctx->end_rendering (); - begun = 0; - } -} diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index ff110f5fa..4848b9018 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -31,169 +31,17 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" +#include -#ifdef HAVE_STRING_H -# include "string.h" -#endif -#ifdef HAVE_STRINGS_H -# include "strings.h" -#endif - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/dstring.h" #include "QF/image.h" -#include "QF/png.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/screen.h" -#include "QF/skin.h" #include "QF/sys.h" -#include "QF/va.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" -#include "QF/GLSL/qf_draw.h" -#include "QF/GLSL/qf_textures.h" -#include "QF/GLSL/qf_vid.h" -#include "QF/ui/view.h" #include "r_internal.h" #include "vid_gl.h" -/* Unknown renamed to GLErr_Unknown to solve conflict with winioctl.h */ -static unsigned int GLErr_InvalidEnum; -static unsigned int GLErr_InvalidValue; -static unsigned int GLErr_InvalidOperation; -static unsigned int GLErr_OutOfMemory; -static unsigned int GLErr_Unknown; - -extern void (*R_DrawSpriteModel) (struct entity_s *ent); - - -static unsigned int -R_TestErrors (unsigned int numerous) -{ - switch (qfeglGetError ()) { - case GL_NO_ERROR: - return numerous; - break; - case GL_INVALID_ENUM: - GLErr_InvalidEnum++; - R_TestErrors (numerous++); - break; - case GL_INVALID_VALUE: - GLErr_InvalidValue++; - R_TestErrors (numerous++); - break; - case GL_INVALID_OPERATION: - GLErr_InvalidOperation++; - R_TestErrors (numerous++); - break; - case GL_OUT_OF_MEMORY: - GLErr_OutOfMemory++; - R_TestErrors (numerous++); - break; - default: - GLErr_Unknown++; - R_TestErrors (numerous++); - break; - } - - return numerous; -} - -static void -R_DisplayErrors (void) -{ - if (GLErr_InvalidEnum) - printf ("%d OpenGL errors: Invalid Enum!\n", GLErr_InvalidEnum); - if (GLErr_InvalidValue) - printf ("%d OpenGL errors: Invalid Value!\n", GLErr_InvalidValue); - if (GLErr_InvalidOperation) - printf ("%d OpenGL errors: Invalid Operation!\n", GLErr_InvalidOperation); - if (GLErr_OutOfMemory) - printf ("%d OpenGL errors: Out Of Memory!\n", GLErr_OutOfMemory); - if (GLErr_Unknown) - printf ("%d Unknown OpenGL errors!\n", GLErr_Unknown); -} - -static void -R_ClearErrors (void) -{ - GLErr_InvalidEnum = 0; - GLErr_InvalidValue = 0; - GLErr_InvalidOperation = 0; - GLErr_OutOfMemory = 0; - GLErr_Unknown = 0; -} - -static void -SCR_TileClear (void) -{ - if (r_refdef.vrect.x > 0) { - // left - Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); - // right - Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, - vid.width - r_refdef.vrect.x + r_refdef.vrect.width, - vid.height - vr_data.lineadj); - } - if (r_refdef.vrect.y > 0) { - // top - Draw_TileClear (r_refdef.vrect.x, 0, - r_refdef.vrect.x + r_refdef.vrect.width, - r_refdef.vrect.y); - // bottom - Draw_TileClear (r_refdef.vrect.x, - r_refdef.vrect.y + r_refdef.vrect.height, - r_refdef.vrect.width, - vid.height - vr_data.lineadj - - (r_refdef.vrect.height + r_refdef.vrect.y)); - } -} - -void -glsl_R_RenderFrame (SCR_Func *scr_funcs) -{ - static int begun = 0; - - if (R_TestErrors (0)) - R_DisplayErrors (); - R_ClearErrors (); - - if (begun) { - begun = 0; - glsl_ctx->end_rendering (); - } - - //FIXME forces the status bar to redraw. needed because it does not fully - //update in sw modes but must in glsl mode - vr_data.scr_copyeverything = 1; - - qfeglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - begun = 1; - - glsl_R_RenderView (); - - GLSL_Set2D (); - GLSL_DrawReset (); - SCR_TileClear (); - GLSL_Set2DScaled (); - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs)(); - scr_funcs++; - GLSL_FlushText (); - } - GLSL_End2D (); - qfeglFlush (); -} - tex_t * glsl_SCR_CaptureBGR (void) { diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 740b97640..4daff497c 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -71,9 +71,9 @@ R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) float size; int h; - // intermission is always full screen size = min (r_viewsize, 100); if (r_data->force_fullscreen) { + // intermission is always full screen size = 100.0; lineadj = 0; } @@ -175,7 +175,15 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) SCR_CalcRefdef (); } - r_funcs->R_RenderFrame (scr_funcs); + r_funcs->begin_frame (); + r_funcs->render_view (); + r_funcs->set_2d(); + view_draw (vr_data.scr_view); + while (*scr_funcs) { + (*scr_funcs)(); + scr_funcs++; + } + r_funcs->end_frame (); } void @@ -289,7 +297,7 @@ SCR_DrawPause (void) /* Find closest color in the palette for named color */ -int +static int MipColor (int r, int g, int b) { float bestdist, dist; diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 27a3741d1..30a60379e 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -28,36 +28,18 @@ # include "config.h" #endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif +#include -#include - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/dstring.h" #include "QF/image.h" -#include "QF/pcx.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/screen.h" #include "QF/sys.h" -#include "QF/va.h" -#include "QF/ui/view.h" -#include "compat.h" #include "r_internal.h" -#include "vid_internal.h" #include "vid_sw.h" /* SCREEN SHOTS */ tex_t * -SCR_CaptureBGR (void) +sw_SCR_CaptureBGR (void) { int count, x, y; tex_t *tex; @@ -84,44 +66,3 @@ SCR_CaptureBGR (void) } return tex; } - -void -R_RenderFrame (SCR_Func *scr_funcs) -{ - // do 3D refresh drawing, and then update the screen - if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen - vr_data.scr_copyeverything = 1; - Draw_TileClear (0, 0, vid.width, vid.height); - } - - R_RenderView (); - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs)(); - scr_funcs++; - } - - // update one of three areas - vrect_t vrect; - if (vr_data.scr_copyeverything) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - vrect.next = 0; - } else if (scr_copytop) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height - vr_data.lineadj; - vrect.next = 0; - } else { - vrect.x = vr_data.scr_view->xpos; - vrect.y = vr_data.scr_view->ypos; - vrect.width = vr_data.scr_view->xlen; - vrect.height = vr_data.scr_view->ylen; - vrect.next = 0; - } - sw_ctx->update (sw_ctx, &vrect); -} diff --git a/libs/video/renderer/sw32/namehack.h b/libs/video/renderer/sw32/namehack.h index 9cbbfe348..ff78b73b6 100644 --- a/libs/video/renderer/sw32/namehack.h +++ b/libs/video/renderer/sw32/namehack.h @@ -104,7 +104,6 @@ #define R_TransformPlane sw32_R_TransformPlane #define R_ViewChanged sw32_R_ViewChanged #define R_ZDrawSubmodelPolys sw32_R_ZDrawSubmodelPolys -#define SCR_CaptureBGR sw32_SCR_CaptureBGR #define SCR_ScreenShot sw32_SCR_ScreenShot #define SCR_ScreenShot_f sw32_SCR_ScreenShot_f #define R_RenderFrame sw32_R_RenderFrame diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index 072c88182..77fc155e6 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -28,33 +28,12 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" +#include -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/dstring.h" #include "QF/image.h" -#include "QF/pcx.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/screen.h" #include "QF/sys.h" -#include "QF/va.h" -#include "QF/ui/view.h" -#include "compat.h" #include "r_internal.h" -#include "vid_internal.h" #include "vid_sw.h" /* SCREEN SHOTS */ @@ -87,44 +66,3 @@ sw32_SCR_CaptureBGR (void) } return tex; } - -void -sw32_R_RenderFrame (SCR_Func *scr_funcs) -{ - vrect_t vrect; - - if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen - vr_data.scr_copyeverything = 1; - sw32_Draw_TileClear (0, 0, vid.width, vid.height); - } - - sw32_R_RenderView (); - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs)(); - scr_funcs++; - } - - // update one of three areas - if (vr_data.scr_copyeverything) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - vrect.next = 0; - } else if (scr_copytop) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height - vr_data.lineadj; - vrect.next = 0; - } else { - vrect.x = vr_data.scr_view->xpos; - vrect.y = vr_data.scr_view->ypos; - vrect.width = vr_data.scr_view->xlen; - vrect.height = vr_data.scr_view->ylen; - vrect.next = 0; - } - sw32_ctx->update (sw32_ctx, &vrect); -} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index c68cd8c9e..6b9bc08ed 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -31,13 +31,18 @@ #define NH_DEFINE #include "gl/namehack.h" +#include "QF/cvar.h" + #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/GL/funcs.h" +#include "QF/GL/qf_draw.h" #include "QF/GL/qf_rsurf.h" #include "QF/GL/qf_vid.h" #include "mod_internal.h" +#include "r_cvar.h" #include "r_internal.h" #include "vid_internal.h" #include "vid_gl.h" @@ -108,6 +113,93 @@ gl_vid_render_shutdown (void) { } +static void +gl_begin_frame (void) +{ + if (gl_ctx->begun) { + gl_ctx->end_rendering (); + gl_ctx->begun = 0; + } + + //FIXME forces the status bar to redraw. needed because it does not fully + //update in sw modes but must in gl mode + vr_data.scr_copyeverything = 1; + + if (gl_clear->int_val) { + qfglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } else { + qfglClear (GL_DEPTH_BUFFER_BIT); + } + + gl_ctx->begun = 1; + + if (r_speeds->int_val) { + gl_ctx->start_time = Sys_DoubleTime (); + gl_ctx->brush_polys = 0; + gl_ctx->alias_polys = 0; + } + + GL_Set2D (); + GL_DrawReset (); + + // draw any areas not covered by the refresh + if (r_refdef.vrect.x > 0) { + // left + Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); + // right + Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, + vid.width - r_refdef.vrect.x + r_refdef.vrect.width, + vid.height - vr_data.lineadj); + } + if (r_refdef.vrect.y > 0) { + // top + Draw_TileClear (r_refdef.vrect.x, 0, + r_refdef.vrect.x + r_refdef.vrect.width, + r_refdef.vrect.y); + // bottom + Draw_TileClear (r_refdef.vrect.x, + r_refdef.vrect.y + r_refdef.vrect.height, + r_refdef.vrect.width, + vid.height - vr_data.lineadj - + (r_refdef.vrect.height + r_refdef.vrect.y)); + } +} + +static void +gl_render_view (void) +{ + // do 3D refresh drawing, and then update the screen + gl_R_RenderView (); +} + +static void +gl_set_2d (void) +{ + GL_Set2DScaled (); +} + +static void +gl_end_frame (void) +{ + if (r_speeds->int_val) { +// qfglFinish (); + double start_time = gl_ctx->start_time; + double end_time = Sys_DoubleTime (); + Sys_MaskPrintf (SYS_dev, "%3i ms %4i wpoly %4i epoly %4i parts\n", + (int) ((end_time - start_time) * 1000), + gl_ctx->brush_polys, gl_ctx->alias_polys, + r_psystem.numparticles); + } + + GL_FlushText (); + qfglFlush (); + + if (gl_finish->int_val) { + gl_ctx->end_rendering (); + gl_ctx->begun = 0; + } +} + vid_render_funcs_t gl_vid_render_funcs = { gl_vid_render_init, gl_Draw_Character, @@ -138,12 +230,15 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_ParticleSystem, gl_R_Init, - gl_R_RenderFrame, gl_R_ClearState, gl_R_LoadSkys, gl_R_NewMap, gl_R_LineGraph, gl_R_ViewChanged, + gl_begin_frame, + gl_render_view, + gl_set_2d, + gl_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 2ca14d425..9bf4c6b35 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -34,7 +34,10 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/GLSL/funcs.h" +#include "QF/GLSL/defines.h" #include "QF/GLSL/qf_bsp.h" +#include "QF/GLSL/qf_draw.h" #include "QF/GLSL/qf_vid.h" #include "mod_internal.h" @@ -107,6 +110,134 @@ glsl_vid_render_shutdown (void) { } +static unsigned int GLErr_InvalidEnum; +static unsigned int GLErr_InvalidValue; +static unsigned int GLErr_InvalidOperation; +static unsigned int GLErr_OutOfMemory; +static unsigned int GLErr_Unknown; + +static unsigned int +R_TestErrors (unsigned int numerous) +{ + switch (qfeglGetError ()) { + case GL_NO_ERROR: + return numerous; + break; + case GL_INVALID_ENUM: + GLErr_InvalidEnum++; + R_TestErrors (numerous++); + break; + case GL_INVALID_VALUE: + GLErr_InvalidValue++; + R_TestErrors (numerous++); + break; + case GL_INVALID_OPERATION: + GLErr_InvalidOperation++; + R_TestErrors (numerous++); + break; + case GL_OUT_OF_MEMORY: + GLErr_OutOfMemory++; + R_TestErrors (numerous++); + break; + default: + GLErr_Unknown++; + R_TestErrors (numerous++); + break; + } + + return numerous; +} + +static void +R_DisplayErrors (void) +{ + if (GLErr_InvalidEnum) + printf ("%d OpenGL errors: Invalid Enum!\n", GLErr_InvalidEnum); + if (GLErr_InvalidValue) + printf ("%d OpenGL errors: Invalid Value!\n", GLErr_InvalidValue); + if (GLErr_InvalidOperation) + printf ("%d OpenGL errors: Invalid Operation!\n", GLErr_InvalidOperation); + if (GLErr_OutOfMemory) + printf ("%d OpenGL errors: Out Of Memory!\n", GLErr_OutOfMemory); + if (GLErr_Unknown) + printf ("%d Unknown OpenGL errors!\n", GLErr_Unknown); +} + +static void +R_ClearErrors (void) +{ + GLErr_InvalidEnum = 0; + GLErr_InvalidValue = 0; + GLErr_InvalidOperation = 0; + GLErr_OutOfMemory = 0; + GLErr_Unknown = 0; +} + +static void +glsl_begin_frame (void) +{ + if (R_TestErrors (0)) + R_DisplayErrors (); + R_ClearErrors (); + + if (glsl_ctx->begun) { + glsl_ctx->begun = 0; + glsl_ctx->end_rendering (); + } + + //FIXME forces the status bar to redraw. needed because it does not fully + //update in sw modes but must in glsl mode + vr_data.scr_copyeverything = 1; + + qfeglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glsl_ctx->begun = 1; + + GLSL_Set2D (); + GLSL_DrawReset (); + + if (r_refdef.vrect.x > 0) { + // left + Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); + // right + Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, + vid.width - r_refdef.vrect.x + r_refdef.vrect.width, + vid.height - vr_data.lineadj); + } + if (r_refdef.vrect.y > 0) { + // top + Draw_TileClear (r_refdef.vrect.x, 0, + r_refdef.vrect.x + r_refdef.vrect.width, + r_refdef.vrect.y); + // bottom + Draw_TileClear (r_refdef.vrect.x, + r_refdef.vrect.y + r_refdef.vrect.height, + r_refdef.vrect.width, + vid.height - vr_data.lineadj - + (r_refdef.vrect.height + r_refdef.vrect.y)); + } +} + +static void +glsl_render_view (void) +{ + glsl_R_RenderView (); +} + +static void +glsl_set_2d (void) +{ + GLSL_Set2DScaled (); +} + +static void +glsl_end_frame (void) +{ + GLSL_FlushText (); + GLSL_End2D (); + qfeglFlush (); +} + vid_render_funcs_t glsl_vid_render_funcs = { glsl_vid_render_init, glsl_Draw_Character, @@ -137,12 +268,15 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_ParticleSystem, glsl_R_Init, - glsl_R_RenderFrame, glsl_R_ClearState, glsl_R_LoadSkys, glsl_R_NewMap, glsl_R_LineGraph, glsl_R_ViewChanged, + glsl_begin_frame, + glsl_render_view, + glsl_set_2d, + glsl_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 9ad7939ec..b994bf579 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -31,6 +31,8 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/view.h" + #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" @@ -104,6 +106,54 @@ sw_vid_render_shutdown (void) { } +static void +sw_begin_frame (void) +{ + // do 3D refresh drawing, and then update the screen + if (vr_data.scr_fullupdate++ < vid.numpages) { + vr_data.scr_copyeverything = 1; + Draw_TileClear (0, 0, vid.width, vid.height); + } +} + +static void +sw_render_view (void) +{ + R_RenderView (); +} + +static void +sw_set_2d (void) +{ +} + +static void +sw_end_frame (void) +{ + // update one of three areas + vrect_t vrect; + if (vr_data.scr_copyeverything) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + vrect.next = 0; + } else if (scr_copytop) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height - vr_data.lineadj; + vrect.next = 0; + } else { + vrect.x = vr_data.scr_view->xpos; + vrect.y = vr_data.scr_view->ypos; + vrect.width = vr_data.scr_view->xlen; + vrect.height = vr_data.scr_view->ylen; + vrect.next = 0; + } + sw_ctx->update (sw_ctx, &vrect); +} + vid_render_funcs_t sw_vid_render_funcs = { sw_vid_render_init, Draw_Character, @@ -127,19 +177,22 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_Picf, Draw_SubPic, - SCR_CaptureBGR, + sw_SCR_CaptureBGR, 0, 0, sw_ParticleSystem, sw_R_Init, - R_RenderFrame, R_ClearState, R_LoadSkys, R_NewMap, R_LineGraph, R_ViewChanged, + sw_begin_frame, + sw_render_view, + sw_set_2d, + sw_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 4f417d840..2d30ec65c 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -34,6 +34,8 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/view.h" + #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" @@ -109,6 +111,53 @@ sw32_vid_render_shutdown (void) { } +static void +sw32_begin_frame (void) +{ + if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen + vr_data.scr_copyeverything = 1; + sw32_Draw_TileClear (0, 0, vid.width, vid.height); + } +} + +static void +sw32_render_view (void) +{ + sw32_R_RenderView (); +} + +static void +sw32_set_2d (void) +{ +} + +static void +sw32_end_frame (void) +{ + // update one of three areas + vrect_t vrect; + if (vr_data.scr_copyeverything) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + vrect.next = 0; + } else if (scr_copytop) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height - vr_data.lineadj; + vrect.next = 0; + } else { + vrect.x = vr_data.scr_view->xpos; + vrect.y = vr_data.scr_view->ypos; + vrect.width = vr_data.scr_view->xlen; + vrect.height = vr_data.scr_view->ylen; + vrect.next = 0; + } + sw32_ctx->update (sw32_ctx, &vrect); +} + vid_render_funcs_t sw32_vid_render_funcs = { sw32_vid_render_init, sw32_Draw_Character, @@ -139,12 +188,15 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_ParticleSystem, sw32_R_Init, - sw32_R_RenderFrame, sw32_R_ClearState, sw32_R_LoadSkys, sw32_R_NewMap, sw32_R_LineGraph, sw32_R_ViewChanged, + sw32_begin_frame, + sw32_render_view, + sw32_set_2d, + sw32_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 72e6caa5e..524580ecb 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -112,131 +112,6 @@ vulkan_R_Init (void) SCR_Init (); } -static void -vulkan_R_RenderFrame (SCR_Func *scr_funcs) -{ - uint32_t imageIndex = 0; - qfv_device_t *device = vulkan_ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkDevice dev = device->dev; - qfv_queue_t *queue = &vulkan_ctx->device->queue; - - __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; - - dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); - QFV_AcquireNextImage (vulkan_ctx->swapchain, - frame->imageAvailableSemaphore, - 0, &imageIndex); - vulkan_ctx->swapImageIndex = imageIndex; - - view_draw (vr_data.scr_view); - while (*scr_funcs) { - (*scr_funcs) (); - scr_funcs++; - } - - for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { - __auto_type rp = vulkan_ctx->renderPasses.a[i]; - __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - frame->framebuffer = rp->framebuffers->a[imageIndex]; - rp->draw (rpFrame); - } - - VkCommandBufferBeginInfo beginInfo - = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - - VkRenderPassBeginInfo renderPassInfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderArea = { {0, 0}, vulkan_ctx->swapchain->extent }, - }; - - dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); - for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { - __auto_type rp = vulkan_ctx->renderPasses.a[i]; - __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - - if (rpFrame->renderpass) { - renderPassInfo.framebuffer = frame->framebuffer, - renderPassInfo.renderPass = rp->renderpass; - renderPassInfo.clearValueCount = rp->clearValues->size; - renderPassInfo.pClearValues = rp->clearValues->a; - - dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, - rpFrame->subpassContents); - - for (int j = 0; j < rpFrame->subpassCount; j++) { - __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; - if (cmdSet->size) { - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, - cmdSet->size, cmdSet->a); - } - // reset for next time around - cmdSet->size = 0; - - //Regardless of whether any commands were submitted for this - //subpass, must step through each and every subpass, otherwise - //the attachments won't be transitioned correctly. - if (j < rpFrame->subpassCount - 1) { - dfunc->vkCmdNextSubpass (frame->cmdBuffer, - rpFrame->subpassContents); - } - } - dfunc->vkCmdEndRenderPass (frame->cmdBuffer); - } else { - for (int j = 0; j < rpFrame->subpassCount; j++) { - __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; - if (cmdSet->size) { - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, - cmdSet->size, cmdSet->a); - } - // reset for next time around - cmdSet->size = 0; - } - } - } - - if (vulkan_ctx->capture_callback) { - VkImage srcImage = vulkan_ctx->swapchain->images->a[imageIndex]; - VkCommandBuffer cmd = QFV_CaptureImage (vulkan_ctx->capture, srcImage, - vulkan_ctx->curFrame); - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, 1, &cmd); - } - dfunc->vkEndCommandBuffer (frame->cmdBuffer); - - VkPipelineStageFlags waitStage - = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submitInfo = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 1, &frame->imageAvailableSemaphore, &waitStage, - 1, &frame->cmdBuffer, - 1, &frame->renderDoneSemaphore, - }; - dfunc->vkResetFences (dev, 1, &frame->fence); - dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); - - if (vulkan_ctx->capture_callback) { - //FIXME look into "threading" this rather than waiting here - dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE, - 1000000000ull); - vulkan_ctx->capture_callback (QFV_CaptureData (vulkan_ctx->capture, - vulkan_ctx->curFrame), - vulkan_ctx->capture->extent.width, - vulkan_ctx->capture->extent.height); - vulkan_ctx->capture_callback = 0; - } - - VkPresentInfoKHR presentInfo = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, - 1, &frame->renderDoneSemaphore, - 1, &vulkan_ctx->swapchain->swapchain, &imageIndex, - 0 - }; - dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); - - vulkan_ctx->curFrame++; - vulkan_ctx->curFrame %= vulkan_ctx->frames.size; -} - static void vulkan_R_ClearState (void) { @@ -389,6 +264,147 @@ vulkan_R_ViewChanged (void) Vulkan_CalcProjectionMatrices (vulkan_ctx); } +static void +vulkan_begin_frame (void) +{ + uint32_t imageIndex = 0; + qfv_device_t *device = vulkan_ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkDevice dev = device->dev; + + __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; + + dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); + QFV_AcquireNextImage (vulkan_ctx->swapchain, + frame->imageAvailableSemaphore, + 0, &imageIndex); + vulkan_ctx->swapImageIndex = imageIndex; +} + +static void +vulkan_render_view (void) +{ + __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; + uint32_t imageIndex = vulkan_ctx->swapImageIndex; + + for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { + __auto_type rp = vulkan_ctx->renderPasses.a[i]; + __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + frame->framebuffer = rp->framebuffers->a[imageIndex]; + rp->draw (rpFrame); + } +} + +static void +vulkan_set_2d (void) +{ +} + +static void +vulkan_end_frame (void) +{ + qfv_device_t *device = vulkan_ctx->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; + qfv_queue_t *queue = &device->queue; + __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; + uint32_t imageIndex = vulkan_ctx->swapImageIndex; + + VkCommandBufferBeginInfo beginInfo + = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + + VkRenderPassBeginInfo renderPassInfo = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderArea = { {0, 0}, vulkan_ctx->swapchain->extent }, + }; + + dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); + for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { + __auto_type rp = vulkan_ctx->renderPasses.a[i]; + __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + + if (rpFrame->renderpass) { + renderPassInfo.framebuffer = frame->framebuffer, + renderPassInfo.renderPass = rp->renderpass; + renderPassInfo.clearValueCount = rp->clearValues->size; + renderPassInfo.pClearValues = rp->clearValues->a; + + dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, + rpFrame->subpassContents); + + for (int j = 0; j < rpFrame->subpassCount; j++) { + __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; + if (cmdSet->size) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, + cmdSet->size, cmdSet->a); + } + // reset for next time around + cmdSet->size = 0; + + //Regardless of whether any commands were submitted for this + //subpass, must step through each and every subpass, otherwise + //the attachments won't be transitioned correctly. + if (j < rpFrame->subpassCount - 1) { + dfunc->vkCmdNextSubpass (frame->cmdBuffer, + rpFrame->subpassContents); + } + } + dfunc->vkCmdEndRenderPass (frame->cmdBuffer); + } else { + for (int j = 0; j < rpFrame->subpassCount; j++) { + __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; + if (cmdSet->size) { + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, + cmdSet->size, cmdSet->a); + } + // reset for next time around + cmdSet->size = 0; + } + } + } + + if (vulkan_ctx->capture_callback) { + VkImage srcImage = vulkan_ctx->swapchain->images->a[imageIndex]; + VkCommandBuffer cmd = QFV_CaptureImage (vulkan_ctx->capture, srcImage, + vulkan_ctx->curFrame); + dfunc->vkCmdExecuteCommands (frame->cmdBuffer, 1, &cmd); + } + dfunc->vkEndCommandBuffer (frame->cmdBuffer); + + VkPipelineStageFlags waitStage + = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + 1, &frame->imageAvailableSemaphore, &waitStage, + 1, &frame->cmdBuffer, + 1, &frame->renderDoneSemaphore, + }; + dfunc->vkResetFences (dev, 1, &frame->fence); + dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); + + if (vulkan_ctx->capture_callback) { + //FIXME look into "threading" this rather than waiting here + dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE, + 1000000000ull); + vulkan_ctx->capture_callback (QFV_CaptureData (vulkan_ctx->capture, + vulkan_ctx->curFrame), + vulkan_ctx->capture->extent.width, + vulkan_ctx->capture->extent.height); + vulkan_ctx->capture_callback = 0; + } + + VkPresentInfoKHR presentInfo = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, + 1, &frame->renderDoneSemaphore, + 1, &vulkan_ctx->swapchain->swapchain, &imageIndex, + 0 + }; + dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); + + vulkan_ctx->curFrame++; + vulkan_ctx->curFrame %= vulkan_ctx->frames.size; +} + static int is_bgr (VkFormat format) { @@ -658,12 +674,15 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_ParticleSystem, vulkan_R_Init, - vulkan_R_RenderFrame, vulkan_R_ClearState, vulkan_R_LoadSkys, vulkan_R_NewMap, vulkan_R_LineGraph, vulkan_R_ViewChanged, + vulkan_begin_frame, + vulkan_render_view, + vulkan_set_2d, + vulkan_end_frame, &model_funcs }; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 3d85fcd08..e6c1bea5b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -339,7 +339,7 @@ renderpass_draw (qfv_renderframe_t *rFrame) { Vulkan_Matrix_Draw (rFrame); Vulkan_RenderView (rFrame); - Vulkan_FlushText (rFrame); + Vulkan_FlushText (rFrame);//FIXME delayed by a frame? Vulkan_Lighting_Draw (rFrame); Vulkan_Compose_Draw (rFrame); } From 48c225da89096be0290f19d9f8f226440f30838b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Mar 2022 02:10:47 +0900 Subject: [PATCH 2508/3664] [renderer] Merge the fog support code GL still has its own functions for enabling and disabling fog while rendering, but GLSL doesn't need such (thanks to the shaders), nor will vulkan (and the software renderers don't support fog). --- include/QF/plugin/vid_render.h | 4 - include/QF/render.h | 11 + include/r_internal.h | 13 - include/vid_gl.h | 6 + libs/client/cl_world.c | 3 +- libs/video/renderer/Makemodule.am | 2 +- libs/video/renderer/gl/gl_fog.c | 273 +----------------- libs/video/renderer/gl/gl_rmain.c | 3 +- libs/video/renderer/gl/gl_rmisc.c | 1 - libs/video/renderer/gl/gl_rsurf.c | 2 +- libs/video/renderer/gl/namehack.h | 20 -- libs/video/renderer/glsl/glsl_alias.c | 4 +- libs/video/renderer/glsl/glsl_bsp.c | 12 +- libs/video/renderer/glsl/glsl_iqm.c | 4 +- libs/video/renderer/glsl/glsl_main.c | 1 - libs/video/renderer/glsl/glsl_particles.c | 8 +- libs/video/renderer/glsl/glsl_sprite.c | 4 +- libs/video/renderer/glsl/namehack.h | 20 -- .../renderer/{glsl/glsl_fog.c => r_fog.c} | 20 +- libs/video/renderer/r_init.c | 1 + libs/video/renderer/vid_render_gl.c | 5 +- libs/video/renderer/vid_render_glsl.c | 3 - libs/video/renderer/vid_render_sw.c | 3 - libs/video/renderer/vid_render_sw32.c | 3 - libs/video/renderer/vid_render_vulkan.c | 14 - nq/source/cl_parse.c | 3 +- nq/source/sbar.c | 1 + 27 files changed, 60 insertions(+), 384 deletions(-) rename libs/video/renderer/{glsl/glsl_fog.c => r_fog.c} (92%) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 26233dcaa..0def162d1 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -98,10 +98,6 @@ typedef struct vid_render_funcs_s { struct tex_s *(*SCR_CaptureBGR) (void); - void (*Fog_Update) (float density, float red, float green, float blue, - float time); - void (*Fog_ParseWorldspawn) (struct plitem_s *worldspawn); - struct psystem_s *(*ParticleSystem) (void); void (*R_Init) (void); void (*R_ClearState) (void); diff --git a/include/QF/render.h b/include/QF/render.h index c8f277ca6..9f7a0c690 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -244,5 +244,16 @@ void R_RemoveEfrags (entity_t *ent); dlight_t *R_AllocDlight (int key); void R_MaxDlightsCheck (struct cvar_s *var); void R_DecayLights (double frametime); +void Fog_Update (float density, float red, float green, float blue, + float time); +struct plitem_s; +void Fog_ParseWorldspawn (struct plitem_s *worldspawn); + +void Fog_GetColor (quat_t fogcolor); +float Fog_GetDensity (void) __attribute__((pure)); +void Fog_SetupFrame (void); +void Fog_StartAdditive (void); +void Fog_StopAdditive (void); +void Fog_Init (void); #endif//__QF_render_h diff --git a/include/r_internal.h b/include/r_internal.h index 14476d74b..abe115399 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -27,19 +27,6 @@ extern int r_viewsize; void R_LineGraph (int x, int y, int *h_vals, int count, int height); -void Fog_Update (float density, float red, float green, float blue, - float time); -struct plitem_s; -void Fog_ParseWorldspawn (struct plitem_s *worldspawn); - -void Fog_GetColor (quat_t fogcolor); -float Fog_GetDensity (void) __attribute__((pure)); -void Fog_SetupFrame (void); -void Fog_EnableGFog (void); -void Fog_DisableGFog (void); -void Fog_StartAdditive (void); -void Fog_StopAdditive (void); -void Fog_Init (void); void gl_R_Init (void); void glsl_R_Init (void); diff --git a/include/vid_gl.h b/include/vid_gl.h index b4cd3b45f..3d16e75db 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -25,4 +25,10 @@ extern gl_ctx_t *glsl_ctx; struct tex_s *gl_SCR_CaptureBGR (void); struct tex_s *glsl_SCR_CaptureBGR (void); +void gl_Fog_SetupFrame (void); +void gl_Fog_EnableGFog (void); +void gl_Fog_DisableGFog (void); +void gl_Fog_StartAdditive (void); +void gl_Fog_StopAdditive (void); + #endif//__vid_gl_h diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index 61dfa3abe..8a45e44d1 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -216,8 +216,7 @@ CL_World_NewMap (const char *mapname, const char *skyname) if (cl_world.edicts) { cl_world.worldspawn = PL_ObjectAtIndex (cl_world.edicts, 0); CL_LoadSky (skyname); - if (r_funcs->Fog_ParseWorldspawn) - r_funcs->Fog_ParseWorldspawn (cl_world.worldspawn); + Fog_ParseWorldspawn (cl_world.worldspawn); } } map_cfg (mapname, 1); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 1d498b249..b3e83c709 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -49,6 +49,7 @@ libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs) libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_cvar.c \ libs/video/renderer/r_efrag.c \ + libs/video/renderer/r_fog.c \ libs/video/renderer/r_init.c \ libs/video/renderer/r_light.c \ libs/video/renderer/r_main.c \ @@ -112,7 +113,6 @@ libs_video_renderer_librender_glsl_la_SOURCES = \ libs/video/renderer/glsl/glsl_alias.c \ libs/video/renderer/glsl/glsl_bsp.c \ libs/video/renderer/glsl/glsl_draw.c \ - libs/video/renderer/glsl/glsl_fog.c \ libs/video/renderer/glsl/glsl_iqm.c \ libs/video/renderer/glsl/glsl_lightmap.c \ libs/video/renderer/glsl/glsl_main.c \ diff --git a/libs/video/renderer/gl/gl_fog.c b/libs/video/renderer/gl/gl_fog.c index 0b74d0b80..edcac74e1 100644 --- a/libs/video/renderer/gl/gl_fog.c +++ b/libs/video/renderer/gl/gl_fog.c @@ -23,214 +23,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cmd.h" -#include "QF/plist.h" -#include "QF/render.h" -#include "QF/sys.h" - #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "compat.h" #include "r_internal.h" - -//============================================================================== -// -// GLOBAL FOG -// -//============================================================================== - -static float fog_density; -static float fog_red; -static float fog_green; -static float fog_blue; - -static float old_density; -static float old_red; -static float old_green; -static float old_blue; - -static float fade_time; //duration of fade -static float fade_done; //time when fade will be done - -/* - Fog_Update - - update internal variables -*/ -void -gl_Fog_Update (float density, float red, float green, float blue, float time) -{ - //save previous settings for fade - if (time > 0) { - //check for a fade in progress - if (fade_done > vr_data.realtime) { - float f; - - f = (fade_done - vr_data.realtime) / fade_time; - old_density = f * old_density + (1.0 - f) * fog_density; - old_red = f * old_red + (1.0 - f) * fog_red; - old_green = f * old_green + (1.0 - f) * fog_green; - old_blue = f * old_blue + (1.0 - f) * fog_blue; - } else { - old_density = fog_density; - old_red = fog_red; - old_green = fog_green; - old_blue = fog_blue; - } - } - - fog_density = density; - fog_red = red; - fog_green = green; - fog_blue = blue; - fade_time = time; - fade_done = vr_data.realtime + time; -} - -/* - Fog_FogCommand_f - - handle the 'fog' console command -*/ -static void -Fog_FogCommand_f (void) -{ - float density = fog_density; - float red = fog_red; - float green = fog_green; - float blue = fog_blue; - float time = 0.0; - - switch (Cmd_Argc ()) { - default: - case 1: - Sys_Printf ("usage:\n"); - Sys_Printf (" fog \n"); - Sys_Printf (" fog \n"); - Sys_Printf (" fog \n"); - Sys_Printf ("current values:\n"); - Sys_Printf (" \"density\" is \"%f\"\n", fog_density); - Sys_Printf (" \"red\" is \"%f\"\n", fog_red); - Sys_Printf (" \"green\" is \"%f\"\n", fog_green); - Sys_Printf (" \"blue\" is \"%f\"\n", fog_blue); - return; - case 2: - density = atof (Cmd_Argv(1)); - break; - case 3: //TEST - density = atof (Cmd_Argv(1)); - time = atof (Cmd_Argv(2)); - break; - case 4: - red = atof (Cmd_Argv(1)); - green = atof (Cmd_Argv(2)); - blue = atof (Cmd_Argv(3)); - break; - case 5: - density = atof (Cmd_Argv(1)); - red = atof (Cmd_Argv(2)); - green = atof (Cmd_Argv(3)); - blue = atof (Cmd_Argv(4)); - break; - case 6: //TEST - density = atof (Cmd_Argv(1)); - red = atof (Cmd_Argv(2)); - green = atof (Cmd_Argv(3)); - blue = atof (Cmd_Argv(4)); - time = atof (Cmd_Argv(5)); - break; - } - density = max (0.0, density); - red = bound (0.0, red, 1.0); - green = bound (0.0, green, 1.0); - blue = bound (0.0, blue, 1.0); - gl_Fog_Update (density, red, green, blue, time); -} - -/* - Fog_ParseWorldspawn - - called at map load -*/ -void -gl_Fog_ParseWorldspawn (plitem_t *worldspawn) -{ - plitem_t *fog; - const char *value; - - //initially no fog - fog_density = 0.0; - old_density = 0.0; - fade_time = 0.0; - fade_done = 0.0; - - if (!worldspawn) - return; // error - if ((fog = PL_ObjectForKey (worldspawn, "fog")) - && (value = PL_String (fog))) { - sscanf (value, "%f %f %f %f", &fog_density, - &fog_red, &fog_green, &fog_blue); - } -} - -/* - Fog_GetColor - - calculates fog color for this frame, taking into account fade times -*/ -void -gl_Fog_GetColor (quat_t fogcolor) -{ - float f; - int i; - - if (fade_done > vr_data.realtime) { - f = (fade_done - vr_data.realtime) / fade_time; - fogcolor[0] = f * old_red + (1.0 - f) * fog_red; - fogcolor[1] = f * old_green + (1.0 - f) * fog_green; - fogcolor[2] = f * old_blue + (1.0 - f) * fog_blue; - fogcolor[3] = 1.0; - } else { - fogcolor[0] = fog_red; - fogcolor[1] = fog_green; - fogcolor[2] = fog_blue; - fogcolor[3] = 1.0; - } - - //find closest 24-bit RGB value, so solid-colored sky can match the fog - //perfectly - for (i = 0; i < 3; i++) - fogcolor[i] = (float) (rint (fogcolor[i] * 255)) / 255.0f; -} - -/* - Fog_GetDensity - - returns current density of fog -*/ -float -gl_Fog_GetDensity (void) -{ - float f; - - if (fade_done > vr_data.realtime) { - f = (fade_done - vr_data.realtime) / fade_time; - return f * old_density + (1.0 - f) * fog_density; - } else { - return fog_density; - } -} +#include "vid_gl.h" /* Fog_SetupFrame @@ -242,11 +40,13 @@ gl_Fog_SetupFrame (void) { quat_t fogcolor; - gl_Fog_GetColor (fogcolor); + Fog_GetColor (fogcolor); qfglFogfv (GL_FOG_COLOR, fogcolor); - qfglFogf (GL_FOG_DENSITY, gl_Fog_GetDensity () / 64.0); + qfglFogf (GL_FOG_DENSITY, Fog_GetDensity () / 64.0); + qfglFogi (GL_FOG_MODE, GL_EXP2); } + /* Fog_EnableGFog @@ -255,7 +55,7 @@ gl_Fog_SetupFrame (void) void gl_Fog_EnableGFog (void) { - if (gl_Fog_GetDensity () > 0) + if (Fog_GetDensity () > 0) qfglEnable (GL_FOG); } @@ -267,7 +67,7 @@ gl_Fog_EnableGFog (void) void gl_Fog_DisableGFog (void) { - if (gl_Fog_GetDensity () > 0) + if (Fog_GetDensity () > 0) qfglDisable (GL_FOG); } @@ -282,7 +82,8 @@ gl_Fog_StartAdditive (void) { vec3_t color = {0, 0, 0}; - if (gl_Fog_GetDensity () > 0) + qfglFogi (GL_FOG_MODE, GL_EXP2); + if (Fog_GetDensity () > 0) qfglFogfv (GL_FOG_COLOR, color); } @@ -294,61 +95,9 @@ gl_Fog_StartAdditive (void) void gl_Fog_StopAdditive (void) { - if (gl_Fog_GetDensity () > 0) { + if (Fog_GetDensity () > 0) { quat_t fogcolor; - gl_Fog_GetColor (fogcolor); + Fog_GetColor (fogcolor); qfglFogfv (GL_FOG_COLOR, fogcolor); } } - -//============================================================================== -// -// VOLUMETRIC FOG -// -//============================================================================== - -//cvar_t r_vfog = {"r_vfog", "1"}; - -//void Fog_DrawVFog (void) {} -//void Fog_MarkModels (void) {} - -//============================================================================== -// -// INIT -// -//============================================================================== - -/* - Fog_NewMap - - called whenever a map is loaded -*/ -#if 0 -void -gl_Fog_NewMap (void) -{ - Fog_ParseWorldspawn (); //for global fog - Fog_MarkModels (); //for volumetric fog -} -#endif - -/* - Fog_Init - - called when quake initializes -*/ -void -gl_Fog_Init (void) -{ - Cmd_AddCommand ("fog", Fog_FogCommand_f, ""); - - //Cvar_RegisterVariable (&r_vfog, NULL); - - //set up global fog - fog_density = 0.0; - fog_red = 0.3; - fog_green = 0.3; - fog_blue = 0.3; - - qfglFogi (GL_FOG_MODE, GL_EXP2); -} diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 0875da139..554d13e46 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -66,6 +66,7 @@ #include "compat.h" #include "r_internal.h" #include "varrays.h" +#include "vid_gl.h" qboolean gl_envmap; // true during envmap command capture @@ -330,8 +331,6 @@ gl_R_SetupFrame (void) EntQueue_Clear (r_ent_queue); r_framecount++; - gl_Fog_SetupFrame (); - // build the transformation matrix for the given view angles VectorCopy (r_refdef.viewposition, r_origin); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 90bfc1b10..49aef8679 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -164,7 +164,6 @@ gl_R_Init (void) r_init = 1; gl_R_InitParticles (); gl_R_InitSprites (); - gl_Fog_Init (); Skin_Init (); } diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 775b9ee03..53a0b5142 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -752,7 +752,7 @@ gl_R_DrawWorld (void) } } - if (!gl_Fog_GetDensity () + if (!Fog_GetDensity () || (gl_fb_bmodels->int_val && gl_mtex_fullbright) || gl_mtex_active_tmus > 1) { // we have enough active TMUs to render everything in one go diff --git a/libs/video/renderer/gl/namehack.h b/libs/video/renderer/gl/namehack.h index 2f2b37ae4..547442279 100644 --- a/libs/video/renderer/gl/namehack.h +++ b/libs/video/renderer/gl/namehack.h @@ -21,16 +21,6 @@ #define Draw_Pic gl_Draw_Pic #define Draw_Picf gl_Draw_Picf #define Draw_SubPic gl_Draw_SubPic -#define Fog_DisableGFog gl_Fog_DisableGFog -#define Fog_EnableGFog gl_Fog_EnableGFog -#define Fog_GetColor gl_Fog_GetColor -#define Fog_GetDensity gl_Fog_GetDensity -#define Fog_Init gl_Fog_Init -#define Fog_ParseWorldspawn gl_Fog_ParseWorldspawn -#define Fog_SetupFrame gl_Fog_SetupFrame -#define Fog_StartAdditive gl_Fog_StartAdditive -#define Fog_StopAdditive gl_Fog_StopAdditive -#define Fog_Update gl_Fog_Update #define R_AddTexture gl_R_AddTexture #define R_BlendLightmaps gl_R_BlendLightmaps #define R_CalcLightmaps gl_R_CalcLightmaps @@ -74,16 +64,6 @@ #define r_particles_style_f gl_r_particles_style_f #define r_world_matrix gl_r_world_matrix #else -#undef Fog_DisableGFog -#undef Fog_EnableGFog -#undef Fog_GetColor -#undef Fog_GetDensity -#undef Fog_Init -#undef Fog_ParseWorldspawn -#undef Fog_SetupFrame -#undef Fog_StartAdditive -#undef Fog_StopAdditive -#undef Fog_Update #undef R_AddTexture #undef R_BlendLightmaps #undef R_CalcLightmaps diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index d7025fe72..05f2df3cd 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -342,8 +342,8 @@ glsl_R_AliasBegin (void) qfeglDisableVertexAttribArray (quake_mdl.colora.location); qfeglDisableVertexAttribArray (quake_mdl.colorb.location); - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; + Fog_GetColor (fog); + fog[3] = Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_mdl.fog.location, 1, fog); qfeglUniform1i (quake_mdl.colormap.location, 1); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 0605d81b4..82fe7ca39 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -896,8 +896,8 @@ bsp_begin (void) qfeglVertexAttrib4fv (quake_bsp.color.location, default_color); - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; + Fog_GetColor (fog); + fog[3] = Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_bsp.fog.location, 1, fog); qfeglUniform1i (quake_bsp.colormap.location, 2); @@ -951,8 +951,8 @@ turb_begin (void) qfeglVertexAttrib4fv (quake_turb.color.location, default_color); - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; + Fog_GetColor (fog); + fog[3] = Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_turb.fog.location, 1, fog); qfeglUniform1i (quake_turb.palette.location, 1); @@ -1055,8 +1055,8 @@ sky_begin (void) qfeglEnable (GL_TEXTURE_2D); } - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; + Fog_GetColor (fog); + fog[3] = Fog_GetDensity () / 64.0; qfeglUniform4fv (sky_params.fog->location, 1, fog); spin (mat); diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index 2e66e8f74..a8e05096f 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -285,8 +285,8 @@ glsl_R_IQMBegin (void) qfeglUseProgram (iqm_shader.program); - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; + Fog_GetColor (fog); + fog[3] = Fog_GetDensity () / 64.0; qfeglUniform4fv (iqm_shader.fog.location, 1, fog); qfeglUniform1i (iqm_shader.texture.location, 0); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index d7cf28aa2..f4a0bfc88 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -252,7 +252,6 @@ glsl_R_Init (void) glsl_R_InitIQM (); glsl_R_InitSprites (); glsl_R_InitParticles (); - glsl_Fog_Init (); Skin_Init (); } diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index c6b4b0153..682846c38 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -236,8 +236,8 @@ draw_qf_particles (void) qfeglEnableVertexAttribArray (quake_part.color.location); qfeglEnableVertexAttribArray (quake_part.st.location); - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; + Fog_GetColor (fog); + fog[3] = Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_part.fog.location, 1, fog); qfeglUniformMatrix4fv (quake_part.mvp_matrix.location, 1, false, @@ -361,8 +361,8 @@ draw_id_particles (void) qfeglUniformMatrix4fv (quake_point.mvp_matrix.location, 1, false, &vp_mat[0][0]); - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; + Fog_GetColor (fog); + fog[3] = Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_point.fog.location, 1, fog); qfeglUniform1i (quake_point.palette.location, 0); diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 71f3c08f8..de1d00185 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -277,8 +277,8 @@ R_SpriteBegin (void) qfeglDisableVertexAttribArray (quake_sprite.colorb.location); qfeglDisableVertexAttribArray (quake_sprite.blend.location); - glsl_Fog_GetColor (fog); - fog[3] = glsl_Fog_GetDensity () / 64.0; + Fog_GetColor (fog); + fog[3] = Fog_GetDensity () / 64.0; qfeglUniform4fv (quake_sprite.fog.location, 1, fog); qfeglUniform1i (quake_sprite.spritea.location, 0); diff --git a/libs/video/renderer/glsl/namehack.h b/libs/video/renderer/glsl/namehack.h index 62e75dc87..9aa8f0ed5 100644 --- a/libs/video/renderer/glsl/namehack.h +++ b/libs/video/renderer/glsl/namehack.h @@ -21,16 +21,6 @@ #define Draw_Pic glsl_Draw_Pic #define Draw_Picf glsl_Draw_Picf #define Draw_SubPic glsl_Draw_SubPic -#define Fog_DisableGFog glsl_Fog_DisableGFog -#define Fog_EnableGFog glsl_Fog_EnableGFog -#define Fog_GetColor glsl_Fog_GetColor -#define Fog_GetDensity glsl_Fog_GetDensity -#define Fog_Init glsl_Fog_Init -#define Fog_ParseWorldspawn glsl_Fog_ParseWorldspawn -#define Fog_SetupFrame glsl_Fog_SetupFrame -#define Fog_StartAdditive glsl_Fog_StartAdditive -#define Fog_StopAdditive glsl_Fog_StopAdditive -#define Fog_Update glsl_Fog_Update #define R_AddTexture glsl_R_AddTexture #define R_BlendLightmaps glsl_R_BlendLightmaps #define R_BuildLightMap glsl_R_BuildLightMap @@ -76,16 +66,6 @@ #define r_particles_style_f glsl_r_particles_style_f #define r_world_matrix glsl_r_world_matrix #else -#undef Fog_DisableGFog -#undef Fog_EnableGFog -#undef Fog_GetColor -#undef Fog_GetDensity -#undef Fog_Init -#undef Fog_ParseWorldspawn -#undef Fog_SetupFrame -#undef Fog_StartAdditive -#undef Fog_StopAdditive -#undef Fog_Update #undef R_AddTexture #undef R_BlendLightmaps #undef R_BuildLightMap diff --git a/libs/video/renderer/glsl/glsl_fog.c b/libs/video/renderer/r_fog.c similarity index 92% rename from libs/video/renderer/glsl/glsl_fog.c rename to libs/video/renderer/r_fog.c index 82777061e..2145bfdf4 100644 --- a/libs/video/renderer/glsl/glsl_fog.c +++ b/libs/video/renderer/r_fog.c @@ -17,15 +17,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -//gl_fog.c -- global and volumetric fog +//r_fog.c -- global and volumetric fog #ifdef HAVE_CONFIG_H # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -38,9 +35,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "QF/render.h" #include "QF/sys.h" -#include "QF/GLSL/defines.h" -#include "QF/GLSL/funcs.h" - #include "compat.h" #include "r_internal.h" @@ -69,7 +63,7 @@ static float fade_done; //time when fade will be done update internal variables */ void -glsl_Fog_Update (float density, float red, float green, float blue, float time) +Fog_Update (float density, float red, float green, float blue, float time) { //save previous settings for fade if (time > 0) { @@ -155,7 +149,7 @@ Fog_FogCommand_f (void) red = bound (0.0, red, 1.0); green = bound (0.0, green, 1.0); blue = bound (0.0, blue, 1.0); - glsl_Fog_Update (density, red, green, blue, time); + Fog_Update (density, red, green, blue, time); } /* @@ -164,7 +158,7 @@ Fog_FogCommand_f (void) called at map load */ void -glsl_Fog_ParseWorldspawn (plitem_t *worldspawn) +Fog_ParseWorldspawn (plitem_t *worldspawn) { plitem_t *fog; const char *value; @@ -190,7 +184,7 @@ glsl_Fog_ParseWorldspawn (plitem_t *worldspawn) calculates fog color for this frame, taking into account fade times */ void -glsl_Fog_GetColor (quat_t fogcolor) +Fog_GetColor (quat_t fogcolor) { float f; int i; @@ -220,7 +214,7 @@ glsl_Fog_GetColor (quat_t fogcolor) returns current density of fog */ float -glsl_Fog_GetDensity (void) +Fog_GetDensity (void) { float f; @@ -238,7 +232,7 @@ glsl_Fog_GetDensity (void) called when quake initializes */ void -glsl_Fog_Init (void) +Fog_Init (void) { Cmd_AddCommand ("fog", Fog_FogCommand_f, ""); diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index a3a418dd8..4ddfe33eb 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -98,4 +98,5 @@ R_Init (void) { r_funcs->R_Init (); R_ClearEfrags (); //FIXME force link of r_efrag.o for qwaq + Fog_Init (); } diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 6b9bc08ed..1ae2db22c 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -163,6 +163,8 @@ gl_begin_frame (void) vid.height - vr_data.lineadj - (r_refdef.vrect.height + r_refdef.vrect.y)); } + + gl_Fog_SetupFrame (); } static void @@ -225,9 +227,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_SCR_CaptureBGR, - gl_Fog_Update, - gl_Fog_ParseWorldspawn, - gl_ParticleSystem, gl_R_Init, gl_R_ClearState, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 9bf4c6b35..b5996226d 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -263,9 +263,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_SCR_CaptureBGR, - glsl_Fog_Update, - glsl_Fog_ParseWorldspawn, - glsl_ParticleSystem, glsl_R_Init, glsl_R_ClearState, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index b994bf579..9cb1872a3 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -179,9 +179,6 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_SCR_CaptureBGR, - 0, - 0, - sw_ParticleSystem, sw_R_Init, R_ClearState, diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 2d30ec65c..c1af7d5df 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -183,9 +183,6 @@ vid_render_funcs_t sw32_vid_render_funcs = { sw32_SCR_CaptureBGR, - 0, - 0, - sw32_ParticleSystem, sw32_R_Init, sw32_R_ClearState, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 524580ecb..c8e910ee3 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -70,17 +70,6 @@ static vulkan_ctx_t *vulkan_ctx; -static void -vulkan_Fog_Update (float density, float red, float green, float blue, - float time) -{ -} - -static void -vulkan_Fog_ParseWorldspawn (struct plitem_s *worldspawn) -{ -} - static struct psystem_s * vulkan_ParticleSystem (void) { @@ -669,9 +658,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_SCR_CaptureBGR, - vulkan_Fog_Update, - vulkan_Fog_ParseWorldspawn, - vulkan_ParticleSystem, vulkan_R_Init, vulkan_R_ClearState, diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index b6bcba5b9..0d85bb3a2 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -1066,8 +1066,7 @@ CL_ParseServerMessage (void) blue = MSG_ReadByte (net_message) / 255.0; time = (short) MSG_ReadShort (net_message) / 100.0; time = max (0.0, time); - if (r_funcs->Fog_Update) - r_funcs->Fog_Update (density, red, green, blue, time); + Fog_Update (density, red, green, blue, time); } break; case svc_spawnbaseline2: diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 4797363c7..5e596f07a 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -497,6 +497,7 @@ draw_sigils (view_t *view) static void draw_inventory_sbar (view_t *view) { + printf ("sbar: %d\n", sbar_view->visible); draw_pic (view, 0, 0, sb_ibar); view_draw (view); } From 075a0fe32625eacfc7f898d043b8130006a1f429 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Mar 2022 03:47:36 +0900 Subject: [PATCH 2509/3664] [renderer] Clean up r_origin and modelorg So far, in gl and glsl, but viewposition is much clearer than r_origin (despite being the same thing), and modelorg is just confusing (I think it's the view position relative to the current model). --- include/QF/plugin/vid_render.h | 4 ---- libs/video/renderer/gl/gl_dyn_lights.c | 3 +-- libs/video/renderer/gl/gl_mod_alias.c | 2 -- libs/video/renderer/gl/gl_mod_sprite.c | 3 +-- libs/video/renderer/gl/gl_rmain.c | 17 ++++++----------- libs/video/renderer/gl/gl_rsurf.c | 19 +++++++++---------- libs/video/renderer/gl/gl_sky_clip.c | 3 ++- libs/video/renderer/glsl/glsl_bsp.c | 7 ++++--- libs/video/renderer/glsl/glsl_main.c | 5 ++--- libs/video/renderer/glsl/glsl_sprite.c | 3 +-- libs/video/renderer/r_graph.c | 2 +- libs/video/renderer/r_main.c | 3 ++- libs/video/renderer/vid_common.c | 1 - 13 files changed, 29 insertions(+), 43 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 0def162d1..c3dbc62e6 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -135,10 +135,6 @@ typedef struct vid_render_data_s { double frametime; double realtime; lightstyle_t *lightstyle; - vec_t *origin; - vec_t *vpn; - vec_t *vright; - vec_t *vup; } vid_render_data_t; #endif // __QF_plugin_vid_render_h diff --git a/libs/video/renderer/gl/gl_dyn_lights.c b/libs/video/renderer/gl/gl_dyn_lights.c index a430f95bc..d29737d2a 100644 --- a/libs/video/renderer/gl/gl_dyn_lights.c +++ b/libs/video/renderer/gl/gl_dyn_lights.c @@ -81,7 +81,7 @@ R_RenderDlight (dlight_t *light) bub_cos = gl_bubble_costable; rad = light->radius * 0.35; - VectorSubtract (light->origin, r_origin, v); + VectorSubtract (r_refdef.viewposition, light->origin, v); if (VectorLength (v) < rad) // view is inside the dlight return; @@ -89,7 +89,6 @@ R_RenderDlight (dlight_t *light) qfglColor4fv (light->color); - VectorSubtract (r_origin, light->origin, v); VectorNormalize (v); for (i = 0; i < 3; i++) diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index e968586cb..7934b1332 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -440,8 +440,6 @@ gl_R_DrawAliasModel (entity_t *e) return; } - VectorSubtract (r_origin, origin, modelorg); - gl_modelalpha = e->renderer.colormod[3]; is_fullbright = (model->fullbright || e->renderer.fullbright); diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index 583f518dc..fd5599857 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -68,8 +68,7 @@ R_DrawSpriteModel_f (entity_t *e) mspriteframe_t *frame; origin = Transform_GetWorldPosition (e->transform); - VectorCopy (r_origin, cameravec); - cameravec -= origin; + cameravec = r_refdef.viewposition - origin; // don't bother culling, it's just a single polygon without a surface cache frame = R_GetSpriteFrame (sprite, &e->animation); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 554d13e46..4b6806f4b 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -331,20 +331,15 @@ gl_R_SetupFrame (void) EntQueue_Clear (r_ent_queue); r_framecount++; - // build the transformation matrix for the given view angles - VectorCopy (r_refdef.viewposition, r_origin); - - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); - + vec4f_t position = r_refdef.viewposition; + vec4f_t rotation = r_refdef.viewrotation; + VectorCopy (qvmulf (rotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); + VectorCopy (qvmulf (rotation, (vec4f_t) { 0, -1, 0, 0 }), vright); + VectorCopy (qvmulf (rotation, (vec4f_t) { 0, 0, 1, 0 }), vup); R_SetFrustum (); - // current viewleaf - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); - - r_cache_thrash = false; + r_viewleaf = Mod_PointInLeaf (&position[0], r_worldentity.renderer.model); } static void diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 53a0b5142..280d5d626 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -565,13 +565,13 @@ gl_R_DrawBrushModel (entity_t *e) return; } - VectorSubtract (r_refdef.viewposition, worldMatrix[3], modelorg); + vec4f_t relviewpos = r_refdef.viewposition - worldMatrix[3]; if (rotated) { - vec4f_t temp = { modelorg[0], modelorg[1], modelorg[2], 0 }; + vec4f_t temp = relviewpos; - modelorg[0] = dotf (temp, worldMatrix[0])[0]; - modelorg[1] = dotf (temp, worldMatrix[1])[0]; - modelorg[2] = dotf (temp, worldMatrix[2])[0]; + relviewpos[0] = dotf (temp, worldMatrix[0])[0]; + relviewpos[1] = dotf (temp, worldMatrix[1])[0]; + relviewpos[2] = dotf (temp, worldMatrix[2])[0]; } // calculate dynamic lighting for bmodel if it's not an instanced model @@ -601,7 +601,7 @@ gl_R_DrawBrushModel (entity_t *e) // find which side of the node we are on plane_t *plane = surf->plane; - dot = DotProduct (modelorg, plane->normal) - plane->dist; + dot = DotProduct (relviewpos, plane->normal) - plane->dist; // draw the polygon if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || @@ -626,10 +626,11 @@ get_side (mnode_t *node) { // find which side of the node we are on plane_t *plane = node->plane; + vec4f_t org = r_refdef.viewposition; if (plane->type < 3) - return (modelorg[plane->type] - plane->dist) < 0; - return (DotProduct (modelorg, plane->normal) - plane->dist) < 0; + return (org[plane->type] - plane->dist) < 0; + return (DotProduct (org, plane->normal) - plane->dist) < 0; } static inline void @@ -728,8 +729,6 @@ gl_R_DrawWorld (void) memset (&worldent, 0, sizeof (worldent)); worldent.renderer.model = r_worldentity.renderer.model; - VectorCopy (r_refdef.viewposition, modelorg); - sky_chain = 0; sky_chain_tail = &sky_chain; if (!gl_sky_clip->int_val) { diff --git a/libs/video/renderer/gl/gl_sky_clip.c b/libs/video/renderer/gl/gl_sky_clip.c index 0ac4d2dde..89f521ebd 100644 --- a/libs/video/renderer/gl/gl_sky_clip.c +++ b/libs/video/renderer/gl/gl_sky_clip.c @@ -645,12 +645,13 @@ EmitSkyPolys (float speedscale, const instsurf_t *sc) glpoly_t *p; vec3_t dir; msurface_t *surf = sc->surface; + vec4f_t origin = r_refdef.viewposition; //FIXME transform/color for (p = surf->polys; p; p = p->next) { qfglBegin (GL_POLYGON); for (i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE) { - VectorSubtract (v, r_origin, dir); + VectorSubtract (v, origin, dir); dir[2] *= 3.0; // flatten the sphere length = DotProduct (dir, dir); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 82fe7ca39..40e7d5911 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -744,10 +744,11 @@ get_side (mnode_t *node) { // find the node side on which we are plane_t *plane = node->plane; + vec4f_t org = r_refdef.viewposition; if (plane->type < 3) - return (r_origin[plane->type] - plane->dist) < 0; - return (DotProduct (r_origin, plane->normal) - plane->dist) < 0; + return (org[plane->type] - plane->dist) < 0; + return (DotProduct (org, plane->normal) - plane->dist) < 0; } static inline void @@ -1000,7 +1001,7 @@ spin (mat4_t mat) QuatBlend (sky_rotation[0], sky_rotation[1], blend, q); QuatMult (sky_fix, q, q); Mat4Identity (mat); - VectorNegate (r_origin, mat + 12); + VectorNegate (r_refdef.viewposition, mat + 12); QuatToMatrix (q, m, 1, 1); Mat4Mult (m, mat, mat); } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index f4a0bfc88..e1313ed1c 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -100,16 +100,15 @@ glsl_R_SetupFrame (void) EntQueue_Clear (r_ent_queue); r_framecount++; - VectorCopy (r_refdef.viewposition, r_origin); + vec4f_t position = r_refdef.viewposition; vec4f_t rotation = r_refdef.viewrotation; VectorCopy (qvmulf (rotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); VectorCopy (qvmulf (rotation, (vec4f_t) { 0,-1, 0, 0 }), vright); VectorCopy (qvmulf (rotation, (vec4f_t) { 0, 0, 1, 0 }), vup); - R_SetFrustum (); - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); + r_viewleaf = Mod_PointInLeaf (&position[0], r_worldentity.renderer.model); } static void diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index de1d00185..61ab28937 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -229,8 +229,7 @@ glsl_R_DrawSprite (entity_t *ent) }; vec4f_t origin = Transform_GetWorldPosition (ent->transform); - VectorCopy (r_origin, cameravec); - cameravec -= origin; + cameravec = r_refdef.viewposition - origin; if (!R_BillboardFrame (ent, sprite->type, &cameravec[0], &svup[0], &svright[0], &svpn[0])) { diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index 4ca80c262..81c92169c 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -95,7 +95,7 @@ R_ZGraph (void) else w = 256; - height[r_framecount & 255] = ((int) r_origin[2]) & 31; + height[r_framecount & 255] = ((int) r_refdef.viewposition[2]) & 31; x = 0; vr_funcs->R_LineGraph (x, r_refdef.vrect.height - 2, height, diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index 4bb57c720..dd9860c4c 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -115,9 +115,10 @@ R_SetFrustum (void) RotatePointAroundVector (frustum[3].normal, vright, vpn, -(90 - r_refdef.fov_y / 2)); + vec4f_t origin = r_refdef.viewposition; for (i = 0; i < 4; i++) { frustum[i].type = PLANE_ANYZ; - frustum[i].dist = DotProduct (r_origin, frustum[i].normal); + frustum[i].dist = DotProduct (origin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } } diff --git a/libs/video/renderer/vid_common.c b/libs/video/renderer/vid_common.c index 149cf85fb..004410c58 100644 --- a/libs/video/renderer/vid_common.c +++ b/libs/video/renderer/vid_common.c @@ -51,7 +51,6 @@ vid_render_data_t vid_render_data = { 0, 0.0, 0.0, 0, - r_origin, vpn, vright, vup }; vid_render_funcs_t *vid_render_funcs; From 20536d83eba8a8cffe0828a2ea4a3a365850f763 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Mar 2022 18:41:09 +0900 Subject: [PATCH 2510/3664] [vulkan] Clean up r_origin and modelorg Same deal as for GL and GLSL. --- libs/video/renderer/sw/draw.c | 11 ++--------- libs/video/renderer/vulkan/vulkan_bsp.c | 5 +++-- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- libs/video/renderer/vulkan/vulkan_main.c | 11 ++++++----- libs/video/renderer/vulkan/vulkan_matrices.c | 2 +- libs/video/renderer/vulkan/vulkan_sprite.c | 12 ++++-------- 6 files changed, 17 insertions(+), 26 deletions(-) diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index b242e06c1..c909dd293 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -707,10 +707,7 @@ Draw_TileClear (int x, int y, int w, int h) vr.x = x; width = w; - if (tileoffsety != 0) - vr.height = r_rectdesc.height - tileoffsety; - else - vr.height = r_rectdesc.height; + vr.height = r_rectdesc.height - tileoffsety; if (vr.height > height) vr.height = height; @@ -718,11 +715,7 @@ Draw_TileClear (int x, int y, int w, int h) tileoffsetx = vr.x % r_rectdesc.width; while (width > 0) { - if (tileoffsetx != 0) - vr.width = r_rectdesc.width - tileoffsetx; - else - vr.width = r_rectdesc.width; - + vr.width = r_rectdesc.width - tileoffsetx; if (vr.width > width) vr.width = width; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 040f7db91..773acae04 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -653,10 +653,11 @@ get_side (mnode_t *node) { // find the node side on which we are plane_t *plane = node->plane; + vec4f_t org = r_refdef.viewposition; if (plane->type < 3) - return (r_origin[plane->type] - plane->dist) < 0; - return (DotProduct (r_origin, plane->normal) - plane->dist) < 0; + return (org[plane->type] - plane->dist) < 0; + return (DotProduct (org, plane->normal) - plane->dist) < 0; } static inline void diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 5fd4c9dfb..931995bb2 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -160,7 +160,7 @@ update_lights (vulkan_ctx_t *ctx) light_data->distFactor2 = 1 / 16384.0; light_data->lightCount = 0; - R_FindNearLights (r_origin, MaxLights - 1, lights); + R_FindNearLights (&r_refdef.viewposition[0], MaxLights - 1, lights); for (int i = 0; i < MaxLights - 1; i++) { if (!lights[i]) { break; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 2059a5b66..9cfa136b0 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -70,14 +70,15 @@ setup_frame (vulkan_ctx_t *ctx) EntQueue_Clear (r_ent_queue); r_framecount++; - VectorCopy (r_refdef.viewposition, r_origin); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); + vec4f_t position = r_refdef.viewposition; + vec4f_t rotation = r_refdef.viewrotation; + VectorCopy (qvmulf (rotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); + VectorCopy (qvmulf (rotation, (vec4f_t) { 0, -1, 0, 0 }), vright); + VectorCopy (qvmulf (rotation, (vec4f_t) { 0, 0, 1, 0 }), vup); R_SetFrustum (); - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); + r_viewleaf = Mod_PointInLeaf (&position[0], r_worldentity.renderer.model); } static void diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index fe66c04d4..5c0fc0a91 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -108,7 +108,7 @@ setup_sky (vulkan_ctx_t *ctx) q = Blend (mctx->sky_rotation[0], mctx->sky_rotation[1], blend); q = normalf (qmulf (mctx->sky_fix, q)); mat4fidentity (mat); - VectorNegate (r_origin, mat[3]); + VectorNegate (r_refdef.viewposition, mat[3]); mat4fquat (m, q); mmulf (mat, m, mat); Vulkan_SetSkyMatrix (ctx, mat); diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index a27f9947c..c5b0aed4e 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -108,7 +108,7 @@ Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) msprite_t *sprite = model->cache.data; animation_t *animation = &ent->animation; - mat4f_t mat; + mat4f_t mat = {}; uint32_t frame; qfv_push_constants_t push_constants[] = { { VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat), mat }, @@ -119,14 +119,10 @@ Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) frame = (ptrdiff_t) R_GetSpriteFrame (sprite, animation); mat[3] = Transform_GetWorldPosition (ent->transform); - vec4f_t cameravec = {r_origin[0], r_origin[1], r_origin[2], 0 }; - vec4f_t svpn = {}, svright = {}, svup = {}; - cameravec -= mat[3]; + vec4f_t cameravec = r_refdef.viewposition - mat[3]; R_BillboardFrame (ent, sprite->type, &cameravec[0], - &svup[0], &svright[0], &svpn[0]); - mat[2] = svup; - mat[1] = svright; - mat[0] = -svpn; + &mat[2][0], &mat[1][0], &mat[0][0]); + mat[0] = -mat[0]; emit_commands (sframe->cmdSet.a[QFV_spriteDepth], (qfv_sprite_t *) ((byte *) sprite + sprite->data), From a9cc51b22c9b02632301f2de9c93784560f5146a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Mar 2022 20:16:18 +0900 Subject: [PATCH 2511/3664] [particles] Use correct index for source ramp This fixes both the weird colors and a segfault in the 32-bit software renderer. --- libs/video/renderer/r_part.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index 1eafeca54..3c3898ee3 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -100,7 +100,7 @@ R_RunParticles (float dT) if (p->live <= 0 || p->ramp >= parm->ramp_max) { continue; } - const int *ramp = ps->partramps[j]; + const int *ramp = ps->partramps[i]; if (i > j) { ps->particles[j] = *p; ps->partparams[j] = *parm; From 1fef0e50e0802e8c5e175ffaf036b5f4c8ba892e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 06:47:43 +0900 Subject: [PATCH 2512/3664] [particles] Use read data instead of written data I'm not sure this makes any difference (at 2500fps, the noise is crazy), but fewer instructions can't hurt. --- libs/video/renderer/r_part.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index 3c3898ee3..5a5c03057 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -106,8 +106,6 @@ R_RunParticles (float dT) ps->partparams[j] = *parm; ps->partramps[j] = ramp; } - p = &ps->particles[j]; - parm = &ps->partparams[j]; j += 1; p->pos += dT * p->vel; From 5c8f3ec3acc6924be01157e43187b63a0d585593 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 06:55:31 +0900 Subject: [PATCH 2513/3664] [renderer] Fix some non-static linking issues Well, hopefully I'll get the root cause sorted eventually. I really hate globals. --- libs/video/renderer/r_fog.c | 14 +++++++------- libs/video/renderer/r_screen.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/video/renderer/r_fog.c b/libs/video/renderer/r_fog.c index 2145bfdf4..51595cfe6 100644 --- a/libs/video/renderer/r_fog.c +++ b/libs/video/renderer/r_fog.c @@ -68,10 +68,10 @@ Fog_Update (float density, float red, float green, float blue, float time) //save previous settings for fade if (time > 0) { //check for a fade in progress - if (fade_done > vr_data.realtime) { + if (fade_done > r_data->realtime) { float f; - f = (fade_done - vr_data.realtime) / fade_time; + f = (fade_done - r_data->realtime) / fade_time; old_density = f * old_density + (1.0 - f) * fog_density; old_red = f * old_red + (1.0 - f) * fog_red; old_green = f * old_green + (1.0 - f) * fog_green; @@ -89,7 +89,7 @@ Fog_Update (float density, float red, float green, float blue, float time) fog_green = green; fog_blue = blue; fade_time = time; - fade_done = vr_data.realtime + time; + fade_done = r_data->realtime + time; } /* @@ -189,8 +189,8 @@ Fog_GetColor (quat_t fogcolor) float f; int i; - if (fade_done > vr_data.realtime) { - f = (fade_done - vr_data.realtime) / fade_time; + if (fade_done > r_data->realtime) { + f = (fade_done - r_data->realtime) / fade_time; fogcolor[0] = f * old_red + (1.0 - f) * fog_red; fogcolor[1] = f * old_green + (1.0 - f) * fog_green; fogcolor[2] = f * old_blue + (1.0 - f) * fog_blue; @@ -218,8 +218,8 @@ Fog_GetDensity (void) { float f; - if (fade_done > vr_data.realtime) { - f = (fade_done - vr_data.realtime) / fade_time; + if (fade_done > r_data->realtime) { + f = (fade_done - r_data->realtime) / fade_time; return f * old_density + (1.0 - f) * fog_density; } else { return fog_density; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 4daff497c..a345e2df9 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -178,7 +178,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) r_funcs->begin_frame (); r_funcs->render_view (); r_funcs->set_2d(); - view_draw (vr_data.scr_view); + view_draw (r_data->scr_view); while (*scr_funcs) { (*scr_funcs)(); scr_funcs++; From cfe0455cce2173ea9fe2f57137d35ee246c629a7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 09:31:22 +0900 Subject: [PATCH 2514/3664] [screen] Move some flags into screen.h And remove r_screen.h. Fixes windows builds due to missing scr_skipupdate. --- include/Makemodule.am | 1 - include/QF/screen.h | 2 ++ include/r_internal.h | 1 - include/r_screen.h | 37 ------------------------------------- 4 files changed, 2 insertions(+), 39 deletions(-) delete mode 100644 include/r_screen.h diff --git a/include/Makemodule.am b/include/Makemodule.am index 5a47125b1..1a5ba7216 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -64,7 +64,6 @@ EXTRA_DIST += \ include/r_internal.h \ include/r_local.h \ include/r_scrap.h \ - include/r_screen.h \ include/r_shared.h \ include/regex.h \ include/rua_internal.h \ diff --git a/include/QF/screen.h b/include/QF/screen.h index c58351d84..4b3215064 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -47,5 +47,7 @@ void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); struct tex_s *SCR_SnapScreen (unsigned width, unsigned height); extern struct cvar_s *hud_fps, *hud_time; +extern int scr_copytop; +extern qboolean scr_skipupdate; #endif//__QF_screen_h diff --git a/include/r_internal.h b/include/r_internal.h index abe115399..690aa8629 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -6,7 +6,6 @@ #include "r_cvar.h" #include "r_dynamic.h" #include "r_local.h" -#include "r_screen.h" #include "r_shared.h" extern viddef_t vid; // global video state diff --git a/include/r_screen.h b/include/r_screen.h deleted file mode 100644 index 41963b400..000000000 --- a/include/r_screen.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - r_screen.h - - shared screen declarations - - Copyright (C) 2002 Bill Currie - - Author: Bill Currie - Date: 2002/12/11 - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ - -#ifndef __r_screen_h -#define __r_screen_h - -extern int scr_copytop; -extern qboolean scr_skipupdate; - -#endif//__r_screen_h From 6377734e32cadc3f66da1a5fd50efd6bbfd2ac5c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 14:26:16 +0900 Subject: [PATCH 2515/3664] [renderer] Merge the two software renderers I got tired of having to maintain two separate software renderers, but didn't want to just nuke sw32, so its core changes are merged into sw. Alias model rendering is broken, but I know exactly what's wrong and how to fix it, just need to take care due to asm. --- config.d/build_control.m4 | 18 +- include/context_x11.h | 1 - include/vid_internal.h | 5 +- include/vid_sw.h | 39 +- include/vid_sw_draw.h | 25 + libs/video/renderer/Makemodule.am | 44 - libs/video/renderer/sw/d_draw.S | 4 +- libs/video/renderer/sw/d_edge.c | 52 +- libs/video/renderer/sw/d_init.c | 15 +- libs/video/renderer/sw/d_modech.c | 5 +- libs/video/renderer/sw/d_part.c | 261 +++- libs/video/renderer/sw/d_parta.S | 4 +- libs/video/renderer/sw/d_polysa.S | 4 +- libs/video/renderer/sw/d_polyse.c | 179 ++- libs/video/renderer/sw/d_scan.c | 423 +++++- libs/video/renderer/sw/d_scana.S | 4 +- libs/video/renderer/sw/d_sky.c | 141 +- libs/video/renderer/sw/d_spr8.S | 4 +- libs/video/renderer/sw/d_sprite.c | 307 ++++- libs/video/renderer/sw/d_surf.c | 12 +- libs/video/renderer/sw/d_zpoint.c | 36 +- libs/video/renderer/sw/draw.c | 867 ++++++++++--- libs/video/renderer/sw/screen.c | 21 +- libs/video/renderer/sw/surf8.S | 40 +- libs/video/renderer/sw/sw_graph.c | 86 +- libs/video/renderer/sw/sw_ralias.c | 13 + libs/video/renderer/sw/sw_rmain.c | 28 +- libs/video/renderer/sw/sw_rpart.c | 4 +- libs/video/renderer/sw/sw_rsky.c | 182 +-- libs/video/renderer/sw/sw_rsurf.c | 617 +++++++-- libs/video/renderer/sw/vid_common_sw.c | 129 +- libs/video/renderer/sw32/d_edge.c | 325 ----- libs/video/renderer/sw32/d_fill.c | 164 --- libs/video/renderer/sw32/d_init.c | 112 -- libs/video/renderer/sw32/d_modech.c | 100 -- libs/video/renderer/sw32/d_part.c | 374 ------ libs/video/renderer/sw32/d_polyse.c | 797 ------------ libs/video/renderer/sw32/d_scan.c | 883 ------------- libs/video/renderer/sw32/d_sky.c | 286 ---- libs/video/renderer/sw32/d_sprite.c | 732 ----------- libs/video/renderer/sw32/d_surf.c | 287 ---- libs/video/renderer/sw32/d_vars.c | 55 - libs/video/renderer/sw32/d_zpoint.c | 73 -- libs/video/renderer/sw32/draw.c | 1369 -------------------- libs/video/renderer/sw32/namehack.h | 473 ------- libs/video/renderer/sw32/screen.c | 68 - libs/video/renderer/sw32/sw32_graph.c | 102 -- libs/video/renderer/sw32/sw32_raclip.c | 315 ----- libs/video/renderer/sw32/sw32_ralias.c | 681 ---------- libs/video/renderer/sw32/sw32_rbsp.c | 536 -------- libs/video/renderer/sw32/sw32_rdraw.c | 804 ------------ libs/video/renderer/sw32/sw32_redge.c | 544 -------- libs/video/renderer/sw32/sw32_riqm.c | 330 ----- libs/video/renderer/sw32/sw32_rmain.c | 877 ------------- libs/video/renderer/sw32/sw32_rmisc.c | 321 ----- libs/video/renderer/sw32/sw32_rpart.c | 108 -- libs/video/renderer/sw32/sw32_rsky.c | 224 ---- libs/video/renderer/sw32/sw32_rsprite.c | 261 ---- libs/video/renderer/sw32/sw32_rsurf.c | 898 ------------- libs/video/renderer/sw32/vid_common_sw32.c | 157 --- libs/video/renderer/vid_render_sw32.c | 232 ---- libs/video/targets/context_win.c | 2 - libs/video/targets/vid_x11.c | 1 - libs/video/targets/vid_x11_sw.c | 12 - 64 files changed, 3044 insertions(+), 13029 deletions(-) create mode 100644 include/vid_sw_draw.h delete mode 100644 libs/video/renderer/sw32/d_edge.c delete mode 100644 libs/video/renderer/sw32/d_fill.c delete mode 100644 libs/video/renderer/sw32/d_init.c delete mode 100644 libs/video/renderer/sw32/d_modech.c delete mode 100644 libs/video/renderer/sw32/d_part.c delete mode 100644 libs/video/renderer/sw32/d_polyse.c delete mode 100644 libs/video/renderer/sw32/d_scan.c delete mode 100644 libs/video/renderer/sw32/d_sky.c delete mode 100644 libs/video/renderer/sw32/d_sprite.c delete mode 100644 libs/video/renderer/sw32/d_surf.c delete mode 100644 libs/video/renderer/sw32/d_vars.c delete mode 100644 libs/video/renderer/sw32/d_zpoint.c delete mode 100644 libs/video/renderer/sw32/draw.c delete mode 100644 libs/video/renderer/sw32/namehack.h delete mode 100644 libs/video/renderer/sw32/screen.c delete mode 100644 libs/video/renderer/sw32/sw32_graph.c delete mode 100644 libs/video/renderer/sw32/sw32_raclip.c delete mode 100644 libs/video/renderer/sw32/sw32_ralias.c delete mode 100644 libs/video/renderer/sw32/sw32_rbsp.c delete mode 100644 libs/video/renderer/sw32/sw32_rdraw.c delete mode 100644 libs/video/renderer/sw32/sw32_redge.c delete mode 100644 libs/video/renderer/sw32/sw32_riqm.c delete mode 100644 libs/video/renderer/sw32/sw32_rmain.c delete mode 100644 libs/video/renderer/sw32/sw32_rmisc.c delete mode 100644 libs/video/renderer/sw32/sw32_rpart.c delete mode 100644 libs/video/renderer/sw32/sw32_rsky.c delete mode 100644 libs/video/renderer/sw32/sw32_rsprite.c delete mode 100644 libs/video/renderer/sw32/sw32_rsurf.c delete mode 100644 libs/video/renderer/sw32/vid_common_sw32.c delete mode 100644 libs/video/renderer/vid_render_sw32.c diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index fb0b60951..48adc0b03 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -95,8 +95,8 @@ if test "x$HAVE_X" = xyes; then QF_NEED(iqm, [vulkan]) QF_NEED(sprite, [vulkan]) fi - QF_NEED(vid_render, [sw sw32 gl glsl]) - QF_NEED(render, [sw sw32 gl glsl]) + QF_NEED(vid_render, [sw gl glsl]) + QF_NEED(render, [sw gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -120,8 +120,8 @@ if test "x$HAVE_SDL" = xyes; then NQ_DESKTOP_DATA="$NQ_DESKTOP_DATA desktop/quakeforge-nq-sdl.desktop" CL_TARGETS="$CL_TARGETS SDL" VID_TARGETS="$VID_TARGETS libs/video/targets/libQFsdl.la" - QF_NEED(vid_render, [sw sw32 gl glsl]) - QF_NEED(render, [sw sw32 gl glsl]) + QF_NEED(vid_render, [sw gl glsl]) + QF_NEED(render, [sw gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -175,7 +175,7 @@ if test "x$mingw" = xyes; then QF_NEED(iqm, [vulkan]) QF_NEED(sprite, [vulkan]) fi - QF_NEED(vid_render, [sw sw32 gl glsl]) + QF_NEED(vid_render, [sw gl glsl]) QF_NEED(models, [sw gl glsl]) QF_NEED(alias, [sw gl glsl]) QF_NEED(brush, [sw gl glsl]) @@ -356,8 +356,8 @@ QF_SUBST(progs_gz) QF_PROCESS_NEED_LIST(top, [libs hw nq qtv qw tools ruamoko]) QF_PROCESS_NEED_LIBS(swrend, [asm]) -QF_PROCESS_NEED_LIBS(render, [gl glsl sw sw32 vulkan], [libs/video/renderer]) -QF_PROCESS_NEED_LIST(vid_render, [gl glsl sw sw32 vulkan]) +QF_PROCESS_NEED_LIBS(render, [gl glsl sw vulkan], [libs/video/renderer]) +QF_PROCESS_NEED_LIST(vid_render, [gl glsl sw vulkan]) QF_PROCESS_NEED_LIBS(models, [gl glsl sw vulkan], [libs/models]) QF_PROCESS_NEED_LIBS(alias, [gl glsl sw vulkan], [libs/models/alias]) QF_PROCESS_NEED_LIBS(brush, [gl glsl sw vulkan], [libs/models/brush]) @@ -407,7 +407,7 @@ if test "x$static_plugins" = xauto; then fi fi if test "x$static_plugins" = xyes; then - QF_PROCESS_NEED_STATIC_PLUGINS(vid_render, [sw sw32 glsl gl vulkan], [libs/video/renderer]) + QF_PROCESS_NEED_STATIC_PLUGINS(vid_render, [sw glsl gl vulkan], [libs/video/renderer]) QF_PROCESS_NEED_STATIC_PLUGINS(console, [server], [libs/console], [server]) QF_PROCESS_NEED_STATIC_PLUGINS(console, [client], [libs/console], [client]) @@ -422,7 +422,7 @@ if test "x$static_plugins" = xyes; then CDTYPE="$CDTYPE (static)" fi else - QF_PROCESS_NEED_PLUGINS(vid_render, [sw sw32 glsl gl vulkan], [libs/video/renderer]) + QF_PROCESS_NEED_PLUGINS(vid_render, [sw glsl gl vulkan], [libs/video/renderer]) QF_PROCESS_NEED_PLUGINS(console, [server], [libs/console], [server]) QF_PROCESS_NEED_PLUGINS(console, [client], [libs/console], [client]) QF_PROCESS_NEED_PLUGINS(snd_output, [sdl mme sgi sun win dx oss jack alsa], [libs/audio/targets]) diff --git a/include/context_x11.h b/include/context_x11.h index 0bc29df44..1409b5b93 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -83,7 +83,6 @@ struct gl_ctx_s *X11_GL_Context (void); void X11_GL_Init_Cvars (void); struct sw_ctx_s *X11_SW_Context (void); -struct sw_ctx_s *X11_SW32_Context (void); void X11_SW_Init_Cvars (void); // sw and sw32 cvars shared struct vulkan_ctx_s *X11_Vulkan_Context (void); diff --git a/include/vid_internal.h b/include/vid_internal.h index 5b677bcf0..cc574c373 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -18,7 +18,6 @@ typedef struct vid_internal_s { struct gl_ctx_s *(*gl_context) (void); struct sw_ctx_s *(*sw_context) (void); - struct sw_ctx_s *(*sw32_context) (void); struct vulkan_ctx_s *(*vulkan_context) (void); } vid_internal_t; @@ -26,10 +25,10 @@ extern struct cvar_s *vid_fullscreen; extern struct cvar_s *vid_system_gamma; extern struct cvar_s *vid_gamma; -extern unsigned short sw32_8to16table[256]; - void VID_GetWindowSize (int def_w, int def_h); +extern unsigned short d_8to16table[256]; + void VID_InitGamma (const byte *); qboolean VID_SetGamma (double); void VID_UpdateGamma (struct cvar_s *); diff --git a/include/vid_sw.h b/include/vid_sw.h index 1515bae65..00a15357b 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -1,19 +1,46 @@ #ifndef __vid_sw_h #define __vid_sw_h +#include "QF/qtypes.h" + +struct surf_s; +struct vrect_s; +struct particle_s; +struct spanpackage_s; +struct qpic_s; +struct espan_s; +struct sspan_s; + +typedef struct sw_draw_s { +#define SW_DRAW_FUNC(name, rettype, params) \ + rettype (*name) params; +#include "vid_sw_draw.h" +} sw_draw_t; + struct vrect_s; typedef struct sw_ctx_s { int pixbytes; - void (*choose_visual) (struct sw_ctx_s *ctx); - void (*create_context) (struct sw_ctx_s *ctx); - void (*set_palette) (struct sw_ctx_s *ctx, const byte *palette); - void (*update) (struct sw_ctx_s *ctx, struct vrect_s *rects); + void (*choose_visual) (struct sw_ctx_s *ctx); + void (*create_context) (struct sw_ctx_s *ctx); + void (*set_palette) (struct sw_ctx_s *ctx, const byte *palette); + void (*update) (struct sw_ctx_s *ctx, struct vrect_s *rects); + sw_draw_t *draw; } sw_ctx_t; extern sw_ctx_t *sw_ctx; -extern sw_ctx_t *sw32_ctx; + +#define SW_DRAW_FUNC(name, rettype, params) \ + rettype name##_8 params; +#include "vid_sw_draw.h" + +#define SW_DRAW_FUNC(name, rettype, params) \ + rettype name##_16 params; +#include "vid_sw_draw.h" + +#define SW_DRAW_FUNC(name, rettype, params) \ + rettype name##_32 params; +#include "vid_sw_draw.h" struct tex_s *sw_SCR_CaptureBGR (void); -struct tex_s *sw32_SCR_CaptureBGR (void); #endif//__vid_sw_h diff --git a/include/vid_sw_draw.h b/include/vid_sw_draw.h new file mode 100644 index 000000000..879c1cd65 --- /dev/null +++ b/include/vid_sw_draw.h @@ -0,0 +1,25 @@ +#ifndef SW_DRAW_FUNC +#define SW_DRAW_FUNC(name, rettype, params) +#endif + +SW_DRAW_FUNC(draw_solid_usrface, void, (struct surf_s *surf, int color)) +SW_DRAW_FUNC(draw_particle, void, (struct particle_s *particle)) +SW_DRAW_FUNC(polyset_draw_spans, void, (struct spanpackage_s *spanpackage)) +SW_DRAW_FUNC(draw_character, void, (int x, int y, byte *source, int drawline)) +SW_DRAW_FUNC(draw_pixel, void, (int x, int y, byte color)) +SW_DRAW_FUNC(draw_subpic, void, (int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height)) +SW_DRAW_FUNC(draw_console_background, void, (int lines, byte *data)) +SW_DRAW_FUNC(draw_rect, void, (struct vrect_s *rect, int rowbytes, byte *src, int transparent)) +SW_DRAW_FUNC(draw_fill, void, (int x, int y, int w, int h, int c)) +SW_DRAW_FUNC(draw_fadescreen, void, (void)) +SW_DRAW_FUNC(draw_blendscreen, void, (quat_t color)) +SW_DRAW_FUNC(warp_screen, void, (void)) +SW_DRAW_FUNC(draw_turbulent_span, void, (void)) +SW_DRAW_FUNC(draw_spans, void, (struct espan_s *span)) +SW_DRAW_FUNC(draw_sky_scans, void, (struct espan_s *span)) +SW_DRAW_FUNC(sprite_draw_spans, void, (struct sspan_s *span)) +SW_DRAW_FUNC(draw_z_point, void, (void)) +SW_DRAW_FUNC(line_grapn, void, (int x, int y, int *h_vals, int count, int height)) +SW_DRAW_FUNC(make_sky, void, (void)) +SW_DRAW_FUNC(capture_bgr, struct tex_s *, (void)) +#undef SW_DRAW_FUNC diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index b3e83c709..710117e1f 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -11,7 +11,6 @@ noinst_LTLIBRARIES += \ #plugins EXTRA_LTLIBRARIES += \ libs/video/renderer/vid_render_sw.la \ - libs/video/renderer/vid_render_sw32.la \ libs/video/renderer/vid_render_gl.la \ libs/video/renderer/vid_render_glsl.la \ libs/video/renderer/vid_render_vulkan.la @@ -19,7 +18,6 @@ EXTRA_LTLIBRARIES += \ #helper libraries EXTRA_LTLIBRARIES += \ libs/video/renderer/librender_sw.la \ - libs/video/renderer/librender_sw32.la \ libs/video/renderer/librender_gl.la \ libs/video/renderer/librender_glsl.la \ libs/video/renderer/librender_vulkan.la @@ -140,7 +138,6 @@ libs_video_renderer_librender_sw_la_SOURCES = \ libs/video/renderer/sw/d_copy.S \ libs/video/renderer/sw/d_draw.S \ libs/video/renderer/sw/d_edge.c \ - libs/video/renderer/sw/d_fill.c \ libs/video/renderer/sw/d_init.c \ libs/video/renderer/sw/d_modech.c \ libs/video/renderer/sw/d_part.c \ @@ -183,47 +180,6 @@ libs_video_renderer_librender_sw_la_SOURCES = \ libs/video/renderer/sw/transform.S \ libs/video/renderer/sw/vid_common_sw.c -video_renderer_sw32_libs= \ - libs/video/renderer/librender_sw32.la \ - libs/models/libmodels_sw.la -libs_video_renderer_vid_render_sw32_la_LDFLAGS= $(plugin_ldflags) -libs_video_renderer_vid_render_sw32_la_LIBADD= $(video_renderer_sw32_libs) -libs_video_renderer_vid_render_sw32_la_DEPENDENCIES=$(video_renderer_sw32_libs) -libs_video_renderer_vid_render_sw32_la_SOURCES=\ - $(video_renderer_common_sources) \ - libs/video/renderer/vid_render_sw32.c - -libs_video_renderer_librender_sw32_la_SOURCES = \ - libs/video/renderer/sw32/d_edge.c \ - libs/video/renderer/sw32/d_fill.c \ - libs/video/renderer/sw32/d_init.c \ - libs/video/renderer/sw32/d_modech.c \ - libs/video/renderer/sw32/d_part.c \ - libs/video/renderer/sw32/d_polyse.c \ - libs/video/renderer/sw32/d_scan.c \ - libs/video/renderer/sw32/d_sky.c \ - libs/video/renderer/sw32/d_sprite.c \ - libs/video/renderer/sw32/d_surf.c \ - libs/video/renderer/sw32/d_vars.c \ - libs/video/renderer/sw32/d_zpoint.c \ - libs/video/renderer/sw32/draw.c \ - libs/video/renderer/sw32/namehack.h \ - libs/video/renderer/sw32/screen.c \ - libs/video/renderer/sw32/sw32_graph.c \ - libs/video/renderer/sw32/sw32_raclip.c \ - libs/video/renderer/sw32/sw32_ralias.c \ - libs/video/renderer/sw32/sw32_rbsp.c \ - libs/video/renderer/sw32/sw32_rdraw.c \ - libs/video/renderer/sw32/sw32_redge.c \ - libs/video/renderer/sw32/sw32_riqm.c \ - libs/video/renderer/sw32/sw32_rmain.c \ - libs/video/renderer/sw32/sw32_rmisc.c \ - libs/video/renderer/sw32/sw32_rpart.c \ - libs/video/renderer/sw32/sw32_rsky.c \ - libs/video/renderer/sw32/sw32_rsprite.c \ - libs/video/renderer/sw32/sw32_rsurf.c \ - libs/video/renderer/sw32/vid_common_sw32.c - pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc renderpass_src = libs/video/renderer/vulkan/deferred.plist diff --git a/libs/video/renderer/sw/d_draw.S b/libs/video/renderer/sw/d_draw.S index e4642025b..e615d677f 100644 --- a/libs/video/renderer/sw/d_draw.S +++ b/libs/video/renderer/sw/d_draw.S @@ -99,8 +99,8 @@ LClampHigh5: #define pspans 4+16 .align 4 -.globl C(D_DrawSpans8) -C(D_DrawSpans8): +.globl C(draw_spans_8) +C(draw_spans_8): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 59963dc3a..9b50e932b 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -35,6 +35,8 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" static int miplevel; @@ -72,15 +74,14 @@ D_MipLevelForScale (float scale) // FIXME: clean this up -static void -D_DrawSolidSurface (surf_t *surf, int color) +void +draw_solid_usrface_8 (surf_t *surf, int color) { - espan_t *span; byte *pdest; int u, u2, pix; pix = (color << 24) | (color << 16) | (color << 8) | color; - for (span = surf->spans; span; span = span->pnext) { + for (espan_t *span = surf->spans; span; span = span->pnext) { pdest = (byte *) d_viewbuffer + screenwidth * span->v; u = span->u; u2 = span->u + span->count - 1; @@ -103,6 +104,39 @@ D_DrawSolidSurface (surf_t *surf, int color) } } +void +draw_solid_usrface_16 (surf_t *surf, int color) +{ + short *pdest, pix; + int u, u2; + + pix = d_8to16table[color]; + for (espan_t *span = surf->spans; span; span = span->pnext) { + pdest = (short *) d_viewbuffer + screenwidth * span->v; + u = span->u; + u2 = span->u + span->count - 1; + for (;u <= u2; u++) { + pdest[u] = pix; + } + } +} + +void +draw_solid_usrface_32 (surf_t *surf, int color) +{ + int *pdest, pix; + int u, u2; + + pix = d_8to24table[color]; + for (espan_t *span = surf->spans; span; span = span->pnext) { + pdest = (int *) d_viewbuffer + screenwidth * span->v; + u = span->u; + u2 = span->u + span->count - 1; + for (;u <= u2; u++) { + pdest[u] = pix; + } + } +} static void D_CalcGradients (msurface_t *pface) @@ -167,7 +201,8 @@ D_DrawSurfaces (void) d_zistepv = s->d_zistepv; d_ziorigin = s->d_ziorigin; - D_DrawSolidSurface (s, ((size_t) s->data & 0xFF)); + int color = (size_t) s->data & 0xff; + sw_ctx->draw->draw_solid_usrface (s, color); D_DrawZSpans (s->spans); } } else { @@ -183,10 +218,10 @@ D_DrawSurfaces (void) if (s->flags & SURF_DRAWSKY) { if (!r_skymade) { - R_MakeSky (); + sw_ctx->draw->make_sky (); } - D_DrawSkyScans (s->spans); + sw_ctx->draw->draw_sky_scans (s->spans); D_DrawZSpans (s->spans); } else if (s->flags & SURF_DRAWBACKGROUND) { // set up a gradient for the background surface that places @@ -195,7 +230,8 @@ D_DrawSurfaces (void) d_zistepv = 0; d_ziorigin = -0.9; - D_DrawSolidSurface (s, r_clearcolor->int_val & 0xFF); + int color = r_clearcolor->int_val & 0xff; + sw_ctx->draw->draw_solid_usrface (s, color); D_DrawZSpans (s->spans); } else if (s->flags & SURF_DRAWTURB) { pface = s->data; diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index 634762d28..bfd7de7f6 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -35,6 +35,7 @@ #include "d_local.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" #define NUM_MIPS 4 @@ -45,6 +46,7 @@ float d_scalemip[NUM_MIPS - 1]; static float basemip[NUM_MIPS - 1] = { 1.0, 0.5 * 0.8, 0.25 * 0.8 }; +float d_zitable[65536]; void (*d_drawspans) (espan_t *pspan); @@ -60,7 +62,16 @@ D_Init (void) vr_data.vid->vid_internal->flush_caches = D_FlushCaches; vr_data.vid->vid_internal->init_caches = D_InitCaches; + // LordHavoc: compute 1/zi table for use in rendering code everywhere + if (!d_zitable[1]) { + int i; + d_zitable[0] = 0; + for (i = 1;i < 65536;i++) + d_zitable[i] = (65536.0 * 65536.0 / (double) i); + } + VID_InitBuffers (); + VID_MakeColormaps (); } void @@ -82,7 +93,7 @@ D_SetupFrame (void) if (r_dowarp) screenwidth = WARP_WIDTH; else - screenwidth = vid.rowbytes; + screenwidth = vid.rowbytes / sw_ctx->pixbytes; d_roverwrapped = false; d_initial_rover = sc_rover; @@ -92,7 +103,7 @@ D_SetupFrame (void) for (i = 0; i < (NUM_MIPS - 1); i++) d_scalemip[i] = basemip[i] * d_mipscale->value; - d_drawspans = D_DrawSpans8; + d_drawspans = sw_ctx->draw->draw_spans; } void diff --git a/libs/video/renderer/sw/d_modech.c b/libs/video/renderer/sw/d_modech.c index 40956fc53..c0ab33618 100644 --- a/libs/video/renderer/sw/d_modech.c +++ b/libs/video/renderer/sw/d_modech.c @@ -31,8 +31,9 @@ #include "QF/render.h" #include "QF/sys.h" -#include "r_internal.h" #include "d_local.h" +#include "r_internal.h" +#include "vid_sw.h" int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; @@ -70,7 +71,7 @@ D_ViewChanged (void) if (r_dowarp) rowpixels = WARP_WIDTH; else - rowpixels = vid.rowbytes; + rowpixels = vid.rowbytes / sw_ctx->pixbytes; scale_for_mip = xscale; if (yscale > xscale) diff --git a/libs/video/renderer/sw/d_part.c b/libs/video/renderer/sw/d_part.c index b8b5b1c82..7052462e8 100644 --- a/libs/video/renderer/sw/d_part.c +++ b/libs/video/renderer/sw/d_part.c @@ -30,6 +30,8 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" #ifdef PIC @@ -38,7 +40,7 @@ #ifndef USE_INTEL_ASM void -D_DrawParticle (particle_t *pparticle) +draw_particle_8 (particle_t *pparticle) { vec3_t local, transformed; float zi; @@ -163,3 +165,260 @@ D_DrawParticle (particle_t *pparticle) } } #endif // !USE_INTEL_ASM + +void +draw_particle_16 (particle_t *pparticle) +{ + vec3_t local, transformed; + float zi; + short *pz; + int i, izi, pix, count, u, v; + + // transform point + VectorSubtract (pparticle->pos, r_origin, local); + + transformed[0] = DotProduct (local, r_pright); + transformed[1] = DotProduct (local, r_pup); + transformed[2] = DotProduct (local, r_ppn); + + if (transformed[2] < PARTICLE_Z_CLIP) + return; + + // project the point + // FIXME: preadjust xcenter and ycenter + zi = 1.0 / transformed[2]; + u = (int) (xcenter + zi * transformed[0] + 0.5); + v = (int) (ycenter - zi * transformed[1] + 0.5); + + if ((v > d_vrectbottom_particle) + || (u > d_vrectright_particle) + || (v < d_vrecty) || (u < d_vrectx)) { + return; + } + + pz = d_pzbuffer + (d_zwidth * v) + u; + izi = (int) (zi * 0x8000); + + pix = izi >> d_pix_shift; + + if (pix < d_pix_min) + pix = d_pix_min; + else if (pix > d_pix_max) + pix = d_pix_max; + + unsigned short *pdest = (unsigned short *) d_viewbuffer + + d_scantable[v] + u, + pixcolor = d_8to16table[(int) pparticle->icolor]; + switch (pix) { + case 1: + count = 1 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + } + break; + case 2: + count = 2 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + } + break; + case 3: + count = 3 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + } + break; + case 4: + count = 4 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + + if (pz[3] <= izi) { + pz[3] = izi; + pdest[3] = pixcolor; + } + } + break; + default: + count = pix << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (i = 0; i < pix; i++) { + if (pz[i] <= izi) { + pz[i] = izi; + pdest[i] = pixcolor; + } + } + } + break; + } +} + +void +draw_particle_32 (particle_t *pparticle) +{ + vec3_t local, transformed; + float zi; + short *pz; + int i, izi, pix, count, u, v; + + // transform point + VectorSubtract (pparticle->pos, r_origin, local); + + transformed[0] = DotProduct (local, r_pright); + transformed[1] = DotProduct (local, r_pup); + transformed[2] = DotProduct (local, r_ppn); + + if (transformed[2] < PARTICLE_Z_CLIP) + return; + + // project the point + // FIXME: preadjust xcenter and ycenter + zi = 1.0 / transformed[2]; + u = (int) (xcenter + zi * transformed[0] + 0.5); + v = (int) (ycenter - zi * transformed[1] + 0.5); + + if ((v > d_vrectbottom_particle) + || (u > d_vrectright_particle) + || (v < d_vrecty) || (u < d_vrectx)) { + return; + } + + pz = d_pzbuffer + (d_zwidth * v) + u; + izi = (int) (zi * 0x8000); + + pix = izi >> d_pix_shift; + + if (pix < d_pix_min) + pix = d_pix_min; + else if (pix > d_pix_max) + pix = d_pix_max; + + int *pdest = (int *) d_viewbuffer + d_scantable[v] + u, + pixcolor = d_8to24table[(int) pparticle->icolor]; + switch (pix) { + case 1: + count = 1 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + } + break; + case 2: + count = 2 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + } + break; + case 3: + count = 3 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + } + break; + case 4: + count = 4 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + + if (pz[3] <= izi) { + pz[3] = izi; + pdest[3] = pixcolor; + } + } + break; + default: + count = pix << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (i = 0; i < pix; i++) { + if (pz[i] <= izi) { + pz[i] = izi; + pdest[i] = pixcolor; + } + } + } + break; + } +} diff --git a/libs/video/renderer/sw/d_parta.S b/libs/video/renderer/sw/d_parta.S index a7b9a8543..13a7a5299 100644 --- a/libs/video/renderer/sw/d_parta.S +++ b/libs/video/renderer/sw/d_parta.S @@ -55,8 +55,8 @@ #define P 12+4 .align 4 -.globl C(D_DrawParticle) -C(D_DrawParticle): +.globl C(draw_particle_8) +C(draw_particle_8): pushl %ebp // preserve caller's stack frame pushl %edi // preserve register variables pushl %ebx diff --git a/libs/video/renderer/sw/d_polysa.S b/libs/video/renderer/sw/d_polysa.S index ec2511e30..0c254cbf5 100644 --- a/libs/video/renderer/sw/d_polysa.S +++ b/libs/video/renderer/sw/d_polysa.S @@ -756,8 +756,8 @@ LDone: .globl C(D_PolysetAff8Start) C(D_PolysetAff8Start): -.globl C(D_PolysetDrawSpans8) -C(D_PolysetDrawSpans8): +.globl C(polyset_draw_spans_8) +C(polyset_draw_spans_8): pushl %esi // preserve register variables pushl %ebx diff --git a/libs/video/renderer/sw/d_polyse.c b/libs/video/renderer/sw/d_polyse.c index 5e7f9fbc9..1c64e01fe 100644 --- a/libs/video/renderer/sw/d_polyse.c +++ b/libs/video/renderer/sw/d_polyse.c @@ -33,6 +33,7 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_sw.h" int ubasestep, errorterm, erroradjustup, erroradjustdown; @@ -594,7 +595,7 @@ InitGel (byte * palette) #ifndef USE_INTEL_ASM void -D_PolysetDrawSpans8 (spanpackage_t * pspanpackage) +polyset_draw_spans_8 (spanpackage_t * pspanpackage) { int lcount; byte *lpdest; @@ -651,6 +652,178 @@ D_PolysetDrawSpans8 (spanpackage_t * pspanpackage) } #endif // !USE_INTEL_ASM +void +polyset_draw_spans_16 (spanpackage_t * pspanpackage) +{ + int i, j, texscantable[2*MAX_LBM_HEIGHT], *texscan; + // LordHavoc: compute skin row table + for (i = 0, j = -r_affinetridesc.skinheight * r_affinetridesc.skinwidth; + i < r_affinetridesc.skinheight*2;i++, j += r_affinetridesc.skinwidth) + texscantable[i] = j; + texscan = texscantable + r_affinetridesc.skinheight; + + { + int lcount, count = 0; + short *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + d_aspancount += ubasestep; + + if (lcount) + { + lpdest = (short *) pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) < *lpz) // hidden + { + count = 0; + goto skiploop16; + } +drawloop16: + *lpz++ = lzi >> 16; + *lpdest++ = ((short *)acolormap)[(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] + (lsfrac >> 16)]]; + lzi += r_zistepx; + lsfrac += r_sstepx; + ltfrac += r_tstepx; + llight += r_lstepx; + } + while (--lcount); + goto done16; + + do + { + if ((lzi >> 16) >= *lpz) // draw + { + lsfrac += r_sstepx * count; + ltfrac += r_tstepx * count; + llight += r_lstepx * count; + lpdest += count; + goto drawloop16; + } +skiploop16: + count++; + lzi += r_zistepx; + lpz++; + } + while (--lcount); +done16: ; + } + + pspanpackage++; + } + while (pspanpackage->count != -999999); + } +} + +void +polyset_draw_spans_32 (spanpackage_t * pspanpackage) +{ + int i, j, texscantable[2*MAX_LBM_HEIGHT], *texscan; + // LordHavoc: compute skin row table + for (i = 0, j = -r_affinetridesc.skinheight * r_affinetridesc.skinwidth; + i < r_affinetridesc.skinheight*2;i++, j += r_affinetridesc.skinwidth) + texscantable[i] = j; + texscan = texscantable + r_affinetridesc.skinheight; + + { + int lcount, count = 0; + int *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + d_aspancount += ubasestep; + + if (lcount) + { + lpdest = (int *) pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) < *lpz) // hidden + { + count = 0; + goto skiploop32; + } +drawloop32: + *lpz++ = lzi >> 16; + *lpdest++ = + vid.colormap32[(llight & 0xFF00) | + lptex[texscan[ltfrac >> 16] + + (lsfrac >> 16)]]; + lzi += r_zistepx; + lsfrac += r_sstepx; + ltfrac += r_tstepx; + llight += r_lstepx; + } + while (--lcount); + goto done32; + + do + { + if ((lzi >> 16) >= *lpz) // draw + { + lsfrac += r_sstepx * count; + ltfrac += r_tstepx * count; + llight += r_lstepx * count; + lpdest += count; + goto drawloop32; + } +skiploop32: + count++; + lzi += r_zistepx; + lpz++; + } + while (--lcount); +done32: ; + } + + pspanpackage++; + } + while (pspanpackage->count != -999999); + } +} void D_RasterizeAliasPolySmooth (void) @@ -824,7 +997,7 @@ D_RasterizeAliasPolySmooth (void) originalcount = a_spans[initialrightheight].count; a_spans[initialrightheight].count = -999999; // mark end of the // spanpackages - D_PolysetDrawSpans8 (a_spans); + sw_ctx->draw->polyset_draw_spans (a_spans); // scan out the bottom part of the right edge, if it exists if (pedgetable->numrightedges == 2) { @@ -847,7 +1020,7 @@ D_RasterizeAliasPolySmooth (void) d_countextrastep = ubasestep + 1; a_spans[initialrightheight + height].count = -999999; // mark end of the spanpackages - D_PolysetDrawSpans8 (pstart); + sw_ctx->draw->polyset_draw_spans (pstart); } } diff --git a/libs/video/renderer/sw/d_scan.c b/libs/video/renderer/sw/d_scan.c index c411e8b1e..91b0d5a67 100644 --- a/libs/video/renderer/sw/d_scan.c +++ b/libs/video/renderer/sw/d_scan.c @@ -33,6 +33,8 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" byte *r_turb_pbase; byte *r_turb_pdest; @@ -47,7 +49,7 @@ int r_turb_spancount; the sine warp, to keep the edges from wrapping */ void -D_WarpScreen (void) +warp_screen_8 (void) { int w, h; int u, v; @@ -96,6 +98,105 @@ D_WarpScreen (void) } } +void +warp_screen_16 (void) +{ + int w, h; + int u, v; + int scr_x = vr_data.scr_view->xpos; + int scr_y = vr_data.scr_view->ylen; + int scr_w = vr_data.scr_view->xpos; + int scr_h = vr_data.scr_view->ylen; + short *dest; + int *turb; + int *col; + short **row; + short *rowptr[MAXHEIGHT]; + int column[MAXWIDTH]; + float wratio, hratio; + + w = r_refdef.vrect.width; + h = r_refdef.vrect.height; + + wratio = w / (float) scr_w; + hratio = h / (float) scr_h; + + for (v = 0; v < scr_h + AMP2 * 2; v++) { + rowptr[v] = (short *) d_viewbuffer + + (r_refdef.vrect.y * screenwidth) + + (screenwidth * (int) ((float) v * hratio * h / + (h + AMP2 * 2))); + } + + for (u = 0; u < scr_w + AMP2 * 2; u++) { + column[u] = r_refdef.vrect.x + + (int) ((float) u * wratio * w / (w + AMP2 * 2)); + } + + turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); + dest = (short *) vid.buffer + scr_y * (vid.rowbytes >> 1) + scr_x; + + for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 1)) { + col = &column[turb[v]]; + row = &rowptr[v]; + for (u = 0; u < scr_w; u += 4) { + dest[u + 0] = row[turb[u + 0]][col[u + 0]]; + dest[u + 1] = row[turb[u + 1]][col[u + 1]]; + dest[u + 2] = row[turb[u + 2]][col[u + 2]]; + dest[u + 3] = row[turb[u + 3]][col[u + 3]]; + } + } +} + +void +warp_screen_32 (void) +{ + int w, h; + int u, v; + int scr_x = vr_data.scr_view->xpos; + int scr_y = vr_data.scr_view->ylen; + int scr_w = vr_data.scr_view->xpos; + int scr_h = vr_data.scr_view->ylen; + int *dest; + int *turb; + int *col; + int **row; + int *rowptr[MAXHEIGHT]; + int column[MAXWIDTH]; + float wratio, hratio; + + w = r_refdef.vrect.width; + h = r_refdef.vrect.height; + + wratio = w / (float) scr_w; + hratio = h / (float) scr_h; + + for (v = 0; v < scr_h + AMP2 * 2; v++) { + rowptr[v] = (int *) d_viewbuffer + + (r_refdef.vrect.y * screenwidth) + + (screenwidth * (int) ((float) v * hratio * h / + (h + AMP2 * 2))); + } + + for (u = 0; u < scr_w + AMP2 * 2; u++) { + column[u] = r_refdef.vrect.x + + (int) ((float) u * wratio * w / (w + AMP2 * 2)); + } + + turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); + dest = (int *) vid.buffer + scr_y * (vid.rowbytes >> 2) + scr_x; + + for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 2)) { + col = &column[turb[v]]; + row = &rowptr[v]; + for (u = 0; u < scr_w; u += 4) { + dest[u + 0] = row[turb[u + 0]][col[u + 0]]; + dest[u + 1] = row[turb[u + 1]][col[u + 1]]; + dest[u + 2] = row[turb[u + 2]][col[u + 2]]; + dest[u + 3] = row[turb[u + 3]][col[u + 3]]; + } + } +} #ifdef PIC #undef USE_INTEL_ASM //XXX asm pic hack @@ -103,7 +204,7 @@ D_WarpScreen (void) #ifndef USE_INTEL_ASM void -D_DrawTurbulent8Span (void) +draw_turbulent_span_8 (void) { int sturb, tturb; @@ -121,6 +222,41 @@ D_DrawTurbulent8Span (void) } #endif // !USE_INTEL_ASM +void +draw_turbulent_span_16 (void) +{ + int sturb, tturb; + short *pdest = (short *) r_turb_pdest; + + do { + sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & + (CYCLE - 1)]) >> 16) & 63; + tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & + (CYCLE - 1)]) >> 16) & 63; + *pdest++ = d_8to16table[r_turb_pbase[(tturb << 6) + sturb]]; + r_turb_s += r_turb_sstep; + r_turb_t += r_turb_tstep; + } while (--r_turb_spancount > 0); + r_turb_pdest = (byte *)pdest; +} + +void +draw_turbulent_span_32 (void) +{ + int sturb, tturb; + int *pdest = (int *) r_turb_pdest; + do { + sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & + (CYCLE - 1)]) >> 16) & 63; + tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & + (CYCLE - 1)]) >> 16) & 63; + *pdest++ = d_8to24table[r_turb_pbase[(tturb << 6) + sturb]]; + r_turb_s += r_turb_sstep; + r_turb_t += r_turb_tstep; + } while (--r_turb_spancount > 0); + r_turb_pdest = (byte *)pdest; +} + void Turbulent (espan_t *pspan) { @@ -236,7 +372,7 @@ Turbulent (espan_t *pspan) r_turb_s = r_turb_s & ((CYCLE << 16) - 1); r_turb_t = r_turb_t & ((CYCLE << 16) - 1); - D_DrawTurbulent8Span (); + sw_ctx->draw->draw_turbulent_span (); r_turb_s = snext; r_turb_t = tnext; @@ -248,7 +384,7 @@ Turbulent (espan_t *pspan) #ifndef USE_INTEL_ASM void -D_DrawSpans8 (espan_t *pspan) +draw_spans_8 (espan_t *pspan) { int count, spancount; unsigned char *pbase, *pdest; @@ -373,6 +509,285 @@ D_DrawSpans8 (espan_t *pspan) } #endif +void +draw_spans_16 (espan_t *pspan) +{ + short *pbase = (short *) cacheblock, *pdest; + int count; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv; + float sdivz8stepu, tdivz8stepu, zi8stepu; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536; + + do { + pdest = (short *) d_viewbuffer + (screenwidth * pspan->v) + + pspan->u; + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(unsigned short) zi]; + + s = (int) (sdivz * z) + sadjust; + s = bound(0, s, bbextents); + t = (int) (tdivz * z) + tadjust; + t = bound(0, t, bbextentt); + + while(count >= 8) { + count -= 8; + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(unsigned short) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(8, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(8, tnext, bbextentt); + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[4] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[5] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[6] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[7] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s = snext;t = tnext; + pdest += 8; + } + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span + // (so can't step off polygon), clamp, calculate s and t steps + // across span by division, biasing steps low so we don't run + // off the texture + //countminus1 = (float) (count - 1); + sdivz += d_sdivzstepu * count; //minus1; + tdivz += d_tdivzstepu * count; //minus1; + zi += d_zistepu * 65536.0f * count; //minus1; + z = d_zitable[(unsigned short) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(count, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(count, tnext, bbextentt); + + if (count > 1) { + sstep = (snext - s) / count; //(count - 1); + tstep = (tnext - t) / count; //(count - 1); + + if (count & 4) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep;t += tstep; + pdest += 4; + } + if (count & 2) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest += 2; + } + if (count & 1) + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + } + else + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + } + } + } while ((pspan = pspan->pnext) != NULL); +} + +void +draw_spans_32 (espan_t *pspan) +{ + int *pbase = (int *) cacheblock, *pdest; + int count; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv; + float sdivz8stepu, tdivz8stepu, zi8stepu; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536; + + do { + pdest = (int *) d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(unsigned short) zi]; + + s = (int) (sdivz * z) + sadjust; + s = bound(0, s, bbextents); + t = (int) (tdivz * z) + tadjust; + t = bound(0, t, bbextentt); + + while(count >= 8) { + count -= 8; + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(unsigned short) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(8, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(8, tnext, bbextentt); + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[4] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[5] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[6] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[7] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s = snext; + t = tnext; + pdest += 8; + } + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span + // (so can't step off polygon), clamp, calculate s and t steps + // across span by division, biasing steps low so we don't run + // off the texture + //countminus1 = (float) (count - 1); + sdivz += d_sdivzstepu * count; //minus1; + tdivz += d_tdivzstepu * count; //minus1; + zi += d_zistepu * 65536.0f * count; //minus1; + z = d_zitable[(unsigned short) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(count, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(count, tnext, bbextentt); + + if (count > 1) { + sstep = (snext - s) / count; //(count - 1); + tstep = (tnext - t) / count; //(count - 1); + + if (count & 4) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest += 4; + } + if (count & 2) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest += 2; + } + if (count & 1) + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + } + else + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + } + } + } while ((pspan = pspan->pnext) != NULL); +} + #ifndef USE_INTEL_ASM void D_DrawZSpans (espan_t *pspan) diff --git a/libs/video/renderer/sw/d_scana.S b/libs/video/renderer/sw/d_scana.S index 6ca194e72..aa3eb2112 100644 --- a/libs/video/renderer/sw/d_scana.S +++ b/libs/video/renderer/sw/d_scana.S @@ -49,8 +49,8 @@ //---------------------------------------------------------------------- .align 4 -.globl C(D_DrawTurbulent8Span) -C(D_DrawTurbulent8Span): +.globl C(draw_turbulent_span_8) +C(draw_turbulent_span_8): pushl %ebp // preserve caller's stack frame pointer pushl %esi // preserve register variables pushl %edi diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index c6cd5832d..88ee451f6 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -32,6 +32,7 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_sw.h" #define SKY_SPAN_SHIFT 5 #define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT) @@ -65,7 +66,7 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) } void -D_DrawSkyScans (espan_t *pspan) +draw_sky_scans_8 (espan_t *pspan) { int count, spancount, u, v; unsigned char *pdest; @@ -133,3 +134,141 @@ D_DrawSkyScans (espan_t *pspan) } while ((pspan = pspan->pnext) != NULL); } + +void +draw_sky_scans_16 (espan_t *pspan) +{ + int count, spancount, u, v; + short *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + int spancountminus1; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + snext = 0; // ditto + tnext = 0; // ditto + + do { + pdest = (short *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + + count = pspan->count; + + // calculate the initial s & t + u = pspan->u; + v = pspan->v; + D_Sky_uv_To_st (u, v, &s, &t); + + do { + if (count >= SKY_SPAN_MAX) + spancount = SKY_SPAN_MAX; + else + spancount = count; + + count -= spancount; + + if (count) { + u += spancount; + + // calculate s and t at far end of span, + // calculate s and t steps across span by shifting + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) >> SKY_SPAN_SHIFT; + tstep = (tnext - t) >> SKY_SPAN_SHIFT; + } else { + // calculate s and t at last pixel in span, + // calculate s and t steps across span by division + spancountminus1 = (float) (spancount - 1); + + if (spancountminus1 > 0) { + u += spancountminus1; + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) / spancountminus1; + tstep = (tnext - t) / spancountminus1; + } + } + + do { + *pdest++ = ((short *) r_skysource) + [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + +void +draw_sky_scans_32 (espan_t *pspan) +{ + int count, spancount, u, v; + int *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + int spancountminus1; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + snext = 0; // ditto + tnext = 0; // ditto + + do { + pdest = (int *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + + count = pspan->count; + + // calculate the initial s & t + u = pspan->u; + v = pspan->v; + D_Sky_uv_To_st (u, v, &s, &t); + + do { + if (count >= SKY_SPAN_MAX) + spancount = SKY_SPAN_MAX; + else + spancount = count; + + count -= spancount; + + if (count) { + u += spancount; + + // calculate s and t at far end of span, + // calculate s and t steps across span by shifting + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) >> SKY_SPAN_SHIFT; + tstep = (tnext - t) >> SKY_SPAN_SHIFT; + } else { + // calculate s and t at last pixel in span, + // calculate s and t steps across span by division + spancountminus1 = (float) (spancount - 1); + + if (spancountminus1 > 0) { + u += spancountminus1; + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) / spancountminus1; + tstep = (tnext - t) / spancountminus1; + } + } + + do { + *pdest++ = ((int *) r_skysource) + [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} diff --git a/libs/video/renderer/sw/d_spr8.S b/libs/video/renderer/sw/d_spr8.S index fcda6abd6..3043b36c2 100644 --- a/libs/video/renderer/sw/d_spr8.S +++ b/libs/video/renderer/sw/d_spr8.S @@ -95,8 +95,8 @@ LClampHigh5: #define pspans 4+16 .align 4 -.globl C(D_SpriteDrawSpans) -C(D_SpriteDrawSpans): +.globl C(sprite_draw_spans_8) +C(sprite_draw_spans_8): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables diff --git a/libs/video/renderer/sw/d_sprite.c b/libs/video/renderer/sw/d_sprite.c index b4f35202f..64757b283 100644 --- a/libs/video/renderer/sw/d_sprite.c +++ b/libs/video/renderer/sw/d_sprite.c @@ -32,6 +32,8 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" static int sprite_height; static int minindex, maxindex; @@ -45,7 +47,7 @@ static sspan_t *sprite_spans; #ifndef USE_INTEL_ASM void -D_SpriteDrawSpans (sspan_t *pspan) +sprite_draw_spans_8 (sspan_t *pspan) { int count, spancount, izistep; int izi; @@ -194,6 +196,307 @@ D_SpriteDrawSpans (sspan_t *pspan) } #endif +void +sprite_draw_spans_16 (sspan_t *pspan) +{ + int count, spancount, izistep; + int izi; + byte *pbase; + short *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + byte btemp; + short *pz; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (byte *) cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536; + + // we count on FP exceptions being turned off to avoid range problems + izistep = (int) (d_zistepu * 0x8000 * 0x10000); + + do { + pdest = (short *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + if (count <= 0) + goto NextSpan2; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(int) zi]; + // we count on FP exceptions being turned off to avoid range + // problems + izi = (int) (zi * 0x8000); + + s = (int) (sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int) (tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) { + // calculate s/z, t/z, zi->fixed s and t at far end of + // span, calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(int) zi]; + + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps from causing overstepping + // & running off the texture's edge + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on + // <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } else { + // calculate s/z, t/z, zi->fixed s and t at last pixel in + // span (so can't step off polygon), clamp, calculate s + // and t steps across span by division, biasing steps + // low so we don't run off the texture + spancountminus1 = (float) (spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * 65536.0f * spancountminus1; + z = d_zitable[(int) zi]; + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps from from causing + // overstepping & running off the + // edge of the texture + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on + // <0 steps + + if (spancount > 1) { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + do { + btemp = pbase[(s >> 16) + (t >> 16) * cachewidth]; + if (btemp != TRANSPARENT_COLOR) { + if (*pz <= (izi >> 16)) { + *pz = izi >> 16; + *pdest = d_8to16table[btemp]; + } + } + + izi += izistep; + pdest++; + pz++; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + +NextSpan2: + pspan++; + + } while (pspan->count != DS_SPAN_LIST_END); +} + +void +sprite_draw_spans_32 (sspan_t *pspan) +{ + int count, spancount, izistep; + int izi; + byte *pbase; + int *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + byte btemp; + short *pz; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (byte *) cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536; + + // we count on FP exceptions being turned off to avoid range problems + izistep = (int) (d_zistepu * 0x8000 * 0x10000); + + do { + pdest = (int *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + if (count <= 0) + goto NextSpan4; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(int) zi]; + // we count on FP exceptions being turned off to avoid range + // problems + izi = (int) (zi * 0x8000); + + s = (int) (sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int) (tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) { + // calculate s/z, t/z, zi->fixed s and t at far end of + // span, calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(int) zi]; + + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps from causing overstepping + // & running off the texture's edge + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on + // <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } else { + // calculate s/z, t/z, zi->fixed s and t at last pixel in + // span (so can't step off polygon), clamp, calculate s + // and t steps across span by division, biasing steps low + // so we don't run off the texture + spancountminus1 = (float) (spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * 65536.0f * spancountminus1; + z = d_zitable[(int) zi]; + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps fromcausing overstepping + // & running off the texture's edge + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on + // <0 steps + + if (spancount > 1) { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + do { + btemp = pbase[(s >> 16) + (t >> 16) * cachewidth]; + if (btemp != TRANSPARENT_COLOR) { + if (*pz <= (izi >> 16)) { + *pz = izi >> 16; + *pdest = d_8to24table[btemp]; + } + } + + izi += izistep; + pdest++; + pz++; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + +NextSpan4: + pspan++; + + } while (pspan->count != DS_SPAN_LIST_END); +} + static void D_SpriteScanLeftEdge (void) { @@ -412,5 +715,5 @@ D_DrawSprite (void) D_SpriteCalculateGradients (); D_SpriteScanLeftEdge (); D_SpriteScanRightEdge (); - D_SpriteDrawSpans (sprite_spans); + sw_ctx->draw->sprite_draw_spans (sprite_spans); } diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 8e6e53c75..c711a1a27 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -37,6 +37,7 @@ #include "compat.h" #include "d_local.h" #include "r_internal.h" +#include "vid_sw.h" float surfscale; @@ -69,7 +70,7 @@ D_SurfaceCacheForRes (void *data, int width, int height) if (pix > 64000) size += (pix - 64000) * 3; - return size; + return size * sw_ctx->pixbytes; } static void @@ -141,7 +142,7 @@ D_SCAlloc (int width, int size) if ((width < 0) || (width > 512)) // FIXME shouldn't really have a max Sys_Error ("D_SCAlloc: bad cache width %d", width); - if ((size <= 0) || (size > 0x40000)) // FIXME ditto + if ((size <= 0) || (size > 0x40000 * sw_ctx->pixbytes)) // FIXME ditto Sys_Error ("D_SCAlloc: bad cache size %d", size); // This adds the offset of data[0] in the surfcache_t struct. @@ -195,7 +196,8 @@ D_SCAlloc (int width, int size) new->width = width; // DEBUG if (width > 0) - new->height = (size - sizeof (*new) + sizeof (new->data)) / width; + new->height = (size - sizeof (*new) + sizeof (new->data)) / + (width * sw_ctx->pixbytes); new->owner = NULL; // should be set properly after return @@ -252,14 +254,14 @@ D_CacheSurface (msurface_t *surface, int miplevel) surfscale = 1.0 / (1 << miplevel); r_drawsurf.surfmip = miplevel; r_drawsurf.surfwidth = surface->extents[0] >> miplevel; - r_drawsurf.rowbytes = r_drawsurf.surfwidth; + r_drawsurf.rowbytes = r_drawsurf.surfwidth * sw_ctx->pixbytes; r_drawsurf.surfheight = surface->extents[1] >> miplevel; // allocate memory if needed if (!cache) { // if a texture just animated, don't reallocate it cache = D_SCAlloc (r_drawsurf.surfwidth, - r_drawsurf.surfwidth * r_drawsurf.surfheight); + r_drawsurf.rowbytes * r_drawsurf.surfheight); surface->cachespots[miplevel] = cache; cache->owner = &surface->cachespots[miplevel]; cache->mipscale = surfscale; diff --git a/libs/video/renderer/sw/d_zpoint.c b/libs/video/renderer/sw/d_zpoint.c index b7ed9e2bf..1daf056ff 100644 --- a/libs/video/renderer/sw/d_zpoint.c +++ b/libs/video/renderer/sw/d_zpoint.c @@ -30,10 +30,12 @@ #include "d_local.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" void -D_DrawZPoint (void) +draw_z_point_8 (void) { byte *pdest; short *pz; @@ -48,3 +50,35 @@ D_DrawZPoint (void) *pdest = r_zpointdesc.color; } } + +void +draw_z_point_16 (void) +{ + short *pz; + int izi; + + pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u; + izi = (int) (r_zpointdesc.zi * 0x8000); + + if (*pz <= izi) { + *pz = izi; + ((short *) d_viewbuffer) [d_scantable[r_zpointdesc.v] + + r_zpointdesc.u] = d_8to16table[r_zpointdesc.color]; + } +} + +void +draw_z_point_32 (void) +{ + short *pz; + int izi; + + pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u; + izi = (int) (r_zpointdesc.zi * 0x8000); + + if (*pz <= izi) { + *pz = izi; + ((int *) d_viewbuffer) [d_scantable[r_zpointdesc.v] + + r_zpointdesc.u] = d_8to24table[r_zpointdesc.color]; + } +} diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index c909dd293..1b6a9bcb0 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -47,6 +47,7 @@ #include "d_iface.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" typedef struct { int width; @@ -242,6 +243,88 @@ Draw_Init (void) r_rectdesc.rowbytes = draw_backtile->width; } +void +draw_character_8 (int x, int y, byte *source, int drawline) +{ + byte *dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + + while (drawline--) { + if (source[0]) + dest[0] = source[0]; + if (source[1]) + dest[1] = source[1]; + if (source[2]) + dest[2] = source[2]; + if (source[3]) + dest[3] = source[3]; + if (source[4]) + dest[4] = source[4]; + if (source[5]) + dest[5] = source[5]; + if (source[6]) + dest[6] = source[6]; + if (source[7]) + dest[7] = source[7]; + source += 128; + dest += vid.rowbytes; + } +} + +void +draw_character_16 (int x, int y, byte *source, int drawline) +{ + uint16_t *dest = (uint16_t *) vid.buffer + y * (vid.rowbytes >> 1) + x; + + while (drawline--) { + if (source[0]) + dest[0] = d_8to16table[source[0]]; + if (source[1]) + dest[1] = d_8to16table[source[1]]; + if (source[2]) + dest[2] = d_8to16table[source[2]]; + if (source[3]) + dest[3] = d_8to16table[source[3]]; + if (source[4]) + dest[4] = d_8to16table[source[4]]; + if (source[5]) + dest[5] = d_8to16table[source[5]]; + if (source[6]) + dest[6] = d_8to16table[source[6]]; + if (source[7]) + dest[7] = d_8to16table[source[7]]; + + source += 128; + dest += (vid.rowbytes >> 1); + } +} + +void +draw_character_32 (int x, int y, byte *source, int drawline) +{ + uint32_t *dest = (uint32_t *) vid.buffer + y * (vid.rowbytes >> 2) + x; + + while (drawline--) { + if (source[0]) + dest[0] = d_8to24table[source[0]]; + if (source[1]) + dest[1] = d_8to24table[source[1]]; + if (source[2]) + dest[2] = d_8to24table[source[2]]; + if (source[3]) + dest[3] = d_8to24table[source[3]]; + if (source[4]) + dest[4] = d_8to24table[source[4]]; + if (source[5]) + dest[5] = d_8to24table[source[5]]; + if (source[6]) + dest[6] = d_8to24table[source[6]]; + if (source[7]) + dest[7] = d_8to24table[source[7]]; + + source += 128; + dest += (vid.rowbytes >> 2); + } +} /* Draw_Character @@ -253,7 +336,6 @@ Draw_Init (void) inline void Draw_Character (int x, int y, unsigned int chr) { - byte *dest; byte *source; int drawline; int row, col; @@ -279,28 +361,7 @@ Draw_Character (int x, int y, unsigned int chr) } else drawline = 8; - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; - - while (drawline--) { - if (source[0]) - dest[0] = source[0]; - if (source[1]) - dest[1] = source[1]; - if (source[2]) - dest[2] = source[2]; - if (source[3]) - dest[3] = source[3]; - if (source[4]) - dest[4] = source[4]; - if (source[5]) - dest[5] = source[5]; - if (source[6]) - dest[6] = source[6]; - if (source[7]) - dest[7] = source[7]; - source += 128; - dest += vid.rowbytes; - } + sw_ctx->draw->draw_character (x, y, source, drawline); } @@ -333,9 +394,8 @@ Draw_AltString (int x, int y, const char *str) } } - -static void -Draw_Pixel (int x, int y, byte color) +void +draw_pixel_8 (int x, int y, byte color) { byte *dest; @@ -343,6 +403,24 @@ Draw_Pixel (int x, int y, byte color) *dest = color; } +void +draw_pixel_16 (int x, int y, byte color) +{ + uint16_t *dest; + + dest = ((uint16_t*)vid.buffer) + y * vid.rowbytes + x; + *dest = d_8to16table[color]; +} + +void +draw_pixel_32 (int x, int y, byte color) +{ + uint32_t *dest; + + dest = ((uint32_t*)vid.buffer) + y * vid.rowbytes + x; + *dest = d_8to24table[color]; +} + static void crosshair_1 (int x, int y) { @@ -354,14 +432,14 @@ crosshair_2 (int x, int y) { byte c = crosshaircolor->int_val; - Draw_Pixel (x - 1, y, c); - Draw_Pixel (x - 3, y, c); - Draw_Pixel (x + 1, y, c); - Draw_Pixel (x + 3, y, c); - Draw_Pixel (x, y - 1, c); - Draw_Pixel (x, y - 3, c); - Draw_Pixel (x, y + 1, c); - Draw_Pixel (x, y + 3, c); + sw_ctx->draw->draw_pixel (x - 1, y, c); + sw_ctx->draw->draw_pixel (x - 3, y, c); + sw_ctx->draw->draw_pixel (x + 1, y, c); + sw_ctx->draw->draw_pixel (x + 3, y, c); + sw_ctx->draw->draw_pixel (x, y - 1, c); + sw_ctx->draw->draw_pixel (x, y - 3, c); + sw_ctx->draw->draw_pixel (x, y + 1, c); + sw_ctx->draw->draw_pixel (x, y + 3, c); } static void @@ -369,14 +447,14 @@ crosshair_3 (int x, int y) { byte c = crosshaircolor->int_val; - Draw_Pixel (x - 3, y - 3, c); - Draw_Pixel (x + 3, y - 3, c); - Draw_Pixel (x - 2, y - 2, c); - Draw_Pixel (x + 2, y - 2, c); - Draw_Pixel (x - 3, y + 3, c); - Draw_Pixel (x + 2, y + 2, c); - Draw_Pixel (x - 2, y + 2, c); - Draw_Pixel (x + 3, y + 3, c); + sw_ctx->draw->draw_pixel (x - 3, y - 3, c); + sw_ctx->draw->draw_pixel (x + 3, y - 3, c); + sw_ctx->draw->draw_pixel (x - 2, y - 2, c); + sw_ctx->draw->draw_pixel (x + 2, y - 2, c); + sw_ctx->draw->draw_pixel (x - 3, y + 3, c); + sw_ctx->draw->draw_pixel (x + 2, y + 2, c); + sw_ctx->draw->draw_pixel (x - 2, y + 2, c); + sw_ctx->draw->draw_pixel (x + 3, y + 3, c); } static void @@ -384,33 +462,33 @@ crosshair_4 (int x, int y) { //byte c = crosshaircolor->int_val; - Draw_Pixel (x, y - 2, 8); - Draw_Pixel (x + 1, y - 2, 9); + sw_ctx->draw->draw_pixel (x, y - 2, 8); + sw_ctx->draw->draw_pixel (x + 1, y - 2, 9); - Draw_Pixel (x, y - 1, 6); - Draw_Pixel (x + 1, y - 1, 8); - Draw_Pixel (x + 2, y - 1, 2); + sw_ctx->draw->draw_pixel (x, y - 1, 6); + sw_ctx->draw->draw_pixel (x + 1, y - 1, 8); + sw_ctx->draw->draw_pixel (x + 2, y - 1, 2); - Draw_Pixel (x - 2, y, 6); - Draw_Pixel (x - 1, y, 8); - Draw_Pixel (x, y, 8); - Draw_Pixel (x + 1, y, 6); - Draw_Pixel (x + 2, y, 8); - Draw_Pixel (x + 3, y, 8); + sw_ctx->draw->draw_pixel (x - 2, y, 6); + sw_ctx->draw->draw_pixel (x - 1, y, 8); + sw_ctx->draw->draw_pixel (x, y, 8); + sw_ctx->draw->draw_pixel (x + 1, y, 6); + sw_ctx->draw->draw_pixel (x + 2, y, 8); + sw_ctx->draw->draw_pixel (x + 3, y, 8); - Draw_Pixel (x - 1, y + 1, 2); - Draw_Pixel (x, y + 1, 8); - Draw_Pixel (x + 1, y + 1, 8); - Draw_Pixel (x + 2, y + 1, 2); - Draw_Pixel (x + 3, y + 1, 2); - Draw_Pixel (x + 4, y + 1, 2); + sw_ctx->draw->draw_pixel (x - 1, y + 1, 2); + sw_ctx->draw->draw_pixel (x, y + 1, 8); + sw_ctx->draw->draw_pixel (x + 1, y + 1, 8); + sw_ctx->draw->draw_pixel (x + 2, y + 1, 2); + sw_ctx->draw->draw_pixel (x + 3, y + 1, 2); + sw_ctx->draw->draw_pixel (x + 4, y + 1, 2); - Draw_Pixel (x, y + 2, 7); - Draw_Pixel (x + 1, y + 2, 8); - Draw_Pixel (x + 2, y + 2, 2); + sw_ctx->draw->draw_pixel (x, y + 2, 7); + sw_ctx->draw->draw_pixel (x + 1, y + 2, 8); + sw_ctx->draw->draw_pixel (x + 2, y + 2, 2); - Draw_Pixel (x + 1, y + 3, 2); - Draw_Pixel (x + 2, y + 3, 2); + sw_ctx->draw->draw_pixel (x + 1, y + 3, 2); + sw_ctx->draw->draw_pixel (x + 2, y + 3, 2); } static void @@ -418,29 +496,29 @@ crosshair_5 (int x, int y) { byte c = crosshaircolor->int_val; - Draw_Pixel (x - 1, y - 3, c); - Draw_Pixel (x + 0, y - 3, c); - Draw_Pixel (x + 1, y - 3, c); + sw_ctx->draw->draw_pixel (x - 1, y - 3, c); + sw_ctx->draw->draw_pixel (x + 0, y - 3, c); + sw_ctx->draw->draw_pixel (x + 1, y - 3, c); - Draw_Pixel (x - 2, y - 2, c); - Draw_Pixel (x + 2, y - 2, c); + sw_ctx->draw->draw_pixel (x - 2, y - 2, c); + sw_ctx->draw->draw_pixel (x + 2, y - 2, c); - Draw_Pixel (x - 3, y - 1, c); - Draw_Pixel (x + 3, y - 1, c); + sw_ctx->draw->draw_pixel (x - 3, y - 1, c); + sw_ctx->draw->draw_pixel (x + 3, y - 1, c); - Draw_Pixel (x - 3, y, c); - Draw_Pixel (x, y, c); - Draw_Pixel (x + 3, y, c); + sw_ctx->draw->draw_pixel (x - 3, y, c); + sw_ctx->draw->draw_pixel (x, y, c); + sw_ctx->draw->draw_pixel (x + 3, y, c); - Draw_Pixel (x - 3, y + 1, c); - Draw_Pixel (x + 3, y + 1, c); + sw_ctx->draw->draw_pixel (x - 3, y + 1, c); + sw_ctx->draw->draw_pixel (x + 3, y + 1, c); - Draw_Pixel (x - 2, y + 2, c); - Draw_Pixel (x + 2, y + 2, c); + sw_ctx->draw->draw_pixel (x - 2, y + 2, c); + sw_ctx->draw->draw_pixel (x + 2, y + 2, c); - Draw_Pixel (x - 1, y + 3, c); - Draw_Pixel (x + 0, y + 3, c); - Draw_Pixel (x + 1, y + 3, c); + sw_ctx->draw->draw_pixel (x - 1, y + 3, c); + sw_ctx->draw->draw_pixel (x + 0, y + 3, c); + sw_ctx->draw->draw_pixel (x + 1, y + 3, c); } static void (*crosshair_func[]) (int x, int y) = { @@ -481,53 +559,11 @@ Draw_CrosshairAt (int ch, int x, int y) void Draw_Pic (int x, int y, qpic_t *pic) { - byte *dest, *source, tbyte; - int v, u; - if (x < 0 || (x + pic->width) > vid.conview->xlen || y < 0 || (y + pic->height) > vid.conview->ylen) { Sys_MaskPrintf (SYS_vid, "Draw_Pic: bad coordinates"); - Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); - return; - } - - source = pic->data; - - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; - - if (pic->width & 7) { // general - for (v = 0; v < pic->height; v++) { - for (u = 0; u < pic->width; u++) - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = tbyte; - - dest += vid.rowbytes; - source += pic->width; - } - } else { // unwound - for (v = 0; v < pic->height; v++) { - for (u = 0; u < pic->width; u += 8) { - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = tbyte; - if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR) - dest[u + 1] = tbyte; - if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR) - dest[u + 2] = tbyte; - if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR) - dest[u + 3] = tbyte; - if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR) - dest[u + 4] = tbyte; - if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR) - dest[u + 5] = tbyte; - if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR) - dest[u + 6] = tbyte; - if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) - dest[u + 7] = tbyte; - } - dest += vid.rowbytes; - source += pic->width; - } } + Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); } void @@ -536,13 +572,65 @@ Draw_Picf (float x, float y, qpic_t *pic) Draw_Pic (x, y, pic); } +void +draw_subpic_8 (int x, int y, struct qpic_s *pic, int srcx, int srcy, + int width, int height) +{ + byte *source = pic->data + srcy * pic->width + srcx; + byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; + + for (int v = 0; v < height; v++) { + for (int u = 0; u < width; u++) { + byte tbyte = source[u]; + if (tbyte != TRANSPARENT_COLOR) { + dest[u] = tbyte; + } + } + dest += vid.rowbytes; + source += pic->width; + } +} + +void +draw_subpic_16 (int x, int y, struct qpic_s *pic, int srcx, int srcy, + int width, int height) +{ + byte *source = pic->data + srcy * pic->width + srcx; + uint16_t *dest = (uint16_t *) vid.buffer + y * (vid.rowbytes >> 1) + x; + for (int v = 0; v < height; v++) { + for (int u = 0; u < width; u++) { + byte tbyte = source[u]; + if (tbyte != TRANSPARENT_COLOR) { + dest[u] = d_8to16table[tbyte]; + } + } + dest += vid.rowbytes >> 1; + source += pic->width; + } +} + +void +draw_subpic_32 (int x, int y, struct qpic_s *pic, int srcx, int srcy, + int width, int height) +{ + byte *source = pic->data + srcy * pic->width + srcx; + uint32_t *dest = (uint32_t *) vid.buffer + y * (vid.rowbytes >> 2) + x; + for (int v = 0; v < height; v++) { + for (int u = 0; u < width; u++) { + byte tbyte = source[u]; + if (tbyte != TRANSPARENT_COLOR) { + dest[u] = d_8to24table[tbyte]; + } + } + dest += vid.rowbytes >> 2; + source += pic->width; + } +} + void Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height) { - byte *dest, *source, tbyte; - int u, v; - if ((x < 0) || (x + width > vid.conview->xlen) || (y < 0) || (y + height > vid.conview->ylen)) { Sys_MaskPrintf (SYS_vid, "Draw_SubPic: bad coordinates"); @@ -569,68 +657,23 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, // next, clip to pic CLIP (srcx, srcy, width, height, pic->width, pic->height); - source = pic->data + srcy * pic->width + srcx; - - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; - - if (width & 7) { // general - for (v = 0; v < height; v++) { - for (u = 0; u < width; u++) - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = tbyte; - - dest += vid.rowbytes; - source += pic->width; - } - } else { // unwound - for (v = 0; v < height; v++) { - for (u = 0; u < width; u += 8) { - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = tbyte; - if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR) - dest[u + 1] = tbyte; - if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR) - dest[u + 2] = tbyte; - if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR) - dest[u + 3] = tbyte; - if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR) - dest[u + 4] = tbyte; - if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR) - dest[u + 5] = tbyte; - if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR) - dest[u + 6] = tbyte; - if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) - dest[u + 7] = tbyte; - } - dest += vid.rowbytes; - source += pic->width; - } - } + sw_ctx->draw->draw_subpic (x, y, pic, srcx, srcy, width, height); } - void -Draw_ConsoleBackground (int lines, byte alpha) +draw_console_background_8 (int lines, byte *data) { - int x, y, v; - byte *src, *dest; - int f, fstep; - qpic_t *conback; + byte *dest = vid.buffer; - conback = Draw_CachePic ("gfx/conback.lmp", false); - - // draw the pic - dest = vid.buffer; - - for (y = 0; y < lines; y++, dest += vid.rowbytes) { - v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; - src = conback->data + v * 320; + for (int y = 0; y < lines; y++, dest += vid.rowbytes) { + int v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; + byte *src = data + v * 320; if (vid.conview->xlen == 320) memcpy (dest, src, vid.conview->xlen); else { - f = 0; - fstep = 320 * 0x10000 / vid.conview->xlen; - for (x = 0; x < vid.conview->xlen; x += 4) { + int f = 0; + int fstep = 320 * 0x10000 / vid.conview->xlen; + for (int x = 0; x < vid.conview->xlen; x += 4) { dest[x] = src[f >> 16]; f += fstep; dest[x + 1] = src[f >> 16]; @@ -642,13 +685,72 @@ Draw_ConsoleBackground (int lines, byte alpha) } } } +} + +void +draw_console_background_16 (int lines, byte *data) +{ + uint16_t *dest = (uint16_t *) vid.buffer; + + for (int y = 0; y < lines; y++, dest += (vid.rowbytes >> 1)) { + // FIXME: pre-expand to native format? + // FIXME: does the endian switching go away in production? + int v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; + byte *src = data + v * 320; + int f = 0; + int fstep = 320 * 0x10000 / vid.conview->xlen; + for (int x = 0; x < vid.conview->xlen; x += 4) { + dest[x] = d_8to16table[src[f >> 16]]; + f += fstep; + dest[x + 1] = d_8to16table[src[f >> 16]]; + f += fstep; + dest[x + 2] = d_8to16table[src[f >> 16]]; + f += fstep; + dest[x + 3] = d_8to16table[src[f >> 16]]; + f += fstep; + } + } +} + +void +draw_console_background_32 (int lines, byte *data) +{ + uint32_t *dest = (uint32_t *) vid.buffer; + + for (int y = 0; y < lines; y++, dest += (vid.rowbytes >> 2)) { + // FIXME: pre-expand to native format? + // FIXME: does the endian switching go away in production? + int v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; + byte *src = data + v * 320; + int f = 0; + int fstep = 320 * 0x10000 / vid.conview->xlen; + for (int x = 0; x < vid.conview->xlen; x += 4) { + dest[x] = d_8to24table[src[f >> 16]]; + f += fstep; + dest[x + 1] = d_8to24table[src[f >> 16]]; + f += fstep; + dest[x + 2] = d_8to24table[src[f >> 16]]; + f += fstep; + dest[x + 3] = d_8to24table[src[f >> 16]]; + f += fstep; + } + } +} + +void +Draw_ConsoleBackground (int lines, byte alpha) +{ + qpic_t *conback = Draw_CachePic ("gfx/conback.lmp", false); + + // draw the pic + sw_ctx->draw->draw_console_background (lines, conback->data); Draw_AltString (vid.conview->xlen - strlen (cl_verstring->string) * 8 - 11, lines - 14, cl_verstring->string); } -static void -R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) +void +draw_rect_8 (vrect_t *prect, int rowbytes, byte *psrc, int transparent) { byte t; int i, j, srcdelta, destdelta; @@ -683,6 +785,223 @@ R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) } } +void +draw_rect_16 (vrect_t *prect, int rowbytes, byte *psrc, int transparent) +{ + int i, j, srcdelta, destdelta; + uint16_t *pdest; + + pdest = (uint16_t *) vid.buffer + + (prect->y * (vid.rowbytes >> 1)) + prect->x; + + srcdelta = rowbytes - prect->width; + destdelta = (vid.rowbytes >> 1) - prect->width; + + if (transparent) { + for (i = 0; i < prect->height; i++) { + j = prect->width; + while(j >= 8) { + j -= 8; + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to16table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to16table[psrc[1]]; + if (psrc[2] != TRANSPARENT_COLOR) + pdest[2] = d_8to16table[psrc[2]]; + if (psrc[3] != TRANSPARENT_COLOR) + pdest[3] = d_8to16table[psrc[3]]; + if (psrc[4] != TRANSPARENT_COLOR) + pdest[4] = d_8to16table[psrc[4]]; + if (psrc[5] != TRANSPARENT_COLOR) + pdest[5] = d_8to16table[psrc[5]]; + if (psrc[6] != TRANSPARENT_COLOR) + pdest[6] = d_8to16table[psrc[6]]; + if (psrc[7] != TRANSPARENT_COLOR) + pdest[7] = d_8to16table[psrc[7]]; + psrc += 8; + pdest += 8; + } + if (j & 4) { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to16table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to16table[psrc[1]]; + if (psrc[2] != TRANSPARENT_COLOR) + pdest[2] = d_8to16table[psrc[2]]; + if (psrc[3] != TRANSPARENT_COLOR) + pdest[3] = d_8to16table[psrc[3]]; + psrc += 4; + pdest += 4; + } + if (j & 2) { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to16table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to16table[psrc[1]]; + psrc += 2; + pdest += 2; + } + if (j & 1) { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to16table[psrc[0]]; + psrc++; + pdest++; + } + + psrc += srcdelta; + pdest += destdelta; + } + } else { + for (i = 0; i < prect->height; + i++, psrc += srcdelta, pdest += destdelta) { + j = prect->width; + while(j >= 8) { + j -= 8; + pdest[0] = d_8to16table[psrc[0]]; + pdest[1] = d_8to16table[psrc[1]]; + pdest[2] = d_8to16table[psrc[2]]; + pdest[3] = d_8to16table[psrc[3]]; + pdest[4] = d_8to16table[psrc[4]]; + pdest[5] = d_8to16table[psrc[5]]; + pdest[6] = d_8to16table[psrc[6]]; + pdest[7] = d_8to16table[psrc[7]]; + psrc += 8; + pdest += 8; + } + if (j & 4) { + pdest[0] = d_8to16table[psrc[0]]; + pdest[1] = d_8to16table[psrc[1]]; + pdest[2] = d_8to16table[psrc[2]]; + pdest[3] = d_8to16table[psrc[3]]; + psrc += 4; + pdest += 4; + } + if (j & 2) { + pdest[0] = d_8to16table[psrc[0]]; + pdest[1] = d_8to16table[psrc[1]]; + psrc += 2; + pdest += 2; + } + if (j & 1) { + pdest[0] = d_8to16table[psrc[0]]; + psrc++; + pdest++; + } + } + } +} + +void +draw_rect_32 (vrect_t *prect, int rowbytes, byte *psrc, int transparent) +{ + int i, j, srcdelta, destdelta; + uint32_t *pdest; + + pdest = (uint32_t *)vid.buffer + prect->y * (vid.rowbytes >> 2) + prect->x; + + srcdelta = rowbytes - prect->width; + destdelta = (vid.rowbytes >> 2) - prect->width; + + if (transparent) { + for (i = 0; i < prect->height; i++) { + j = prect->width; + while(j >= 8) { + j -= 8; + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to24table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to24table[psrc[1]]; + if (psrc[2] != TRANSPARENT_COLOR) + pdest[2] = d_8to24table[psrc[2]]; + if (psrc[3] != TRANSPARENT_COLOR) + pdest[3] = d_8to24table[psrc[3]]; + if (psrc[4] != TRANSPARENT_COLOR) + pdest[4] = d_8to24table[psrc[4]]; + if (psrc[5] != TRANSPARENT_COLOR) + pdest[5] = d_8to24table[psrc[5]]; + if (psrc[6] != TRANSPARENT_COLOR) + pdest[6] = d_8to24table[psrc[6]]; + if (psrc[7] != TRANSPARENT_COLOR) + pdest[7] = d_8to24table[psrc[7]]; + psrc += 8; + pdest += 8; + } + if (j & 4) { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to24table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to24table[psrc[1]]; + if (psrc[2] != TRANSPARENT_COLOR) + pdest[2] = d_8to24table[psrc[2]]; + if (psrc[3] != TRANSPARENT_COLOR) + pdest[3] = d_8to24table[psrc[3]]; + psrc += 4; + pdest += 4; + } + if (j & 2) { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to24table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to24table[psrc[1]]; + psrc += 2; + pdest += 2; + } + if (j & 1) { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to24table[psrc[0]]; + psrc++; + pdest++; + } + + psrc += srcdelta; + pdest += destdelta; + } + } else { + for (i = 0; i < prect->height; + i++, psrc += srcdelta, pdest += destdelta) { + j = prect->width; + while(j >= 8) { + j -= 8; + pdest[0] = d_8to24table[psrc[0]]; + pdest[1] = d_8to24table[psrc[1]]; + pdest[2] = d_8to24table[psrc[2]]; + pdest[3] = d_8to24table[psrc[3]]; + pdest[4] = d_8to24table[psrc[4]]; + pdest[5] = d_8to24table[psrc[5]]; + pdest[6] = d_8to24table[psrc[6]]; + pdest[7] = d_8to24table[psrc[7]]; + psrc += 8; + pdest += 8; + } + if (j & 4) { + pdest[0] = d_8to24table[psrc[0]]; + pdest[1] = d_8to24table[psrc[1]]; + pdest[2] = d_8to24table[psrc[2]]; + pdest[3] = d_8to24table[psrc[3]]; + psrc += 4; + pdest += 4; + } + if (j & 2) { + pdest[0] = d_8to24table[psrc[0]]; + pdest[1] = d_8to24table[psrc[1]]; + psrc += 2; + pdest += 2; + } + if (j & 1) { + pdest[0] = d_8to24table[psrc[0]]; + psrc++; + pdest++; + } + } + } +} + +static void +R_DrawRect (vrect_t *prect, int rowbytes, byte *psrc, int transparent) +{ + sw_ctx->draw->draw_rect (prect, rowbytes, psrc, transparent); +} + /* Draw_TileClear @@ -735,6 +1054,40 @@ Draw_TileClear (int x, int y, int w, int h) } } +void +draw_fill_8 (int x, int y, int w, int h, int c) +{ + byte *dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + for (int v = 0; v < h; v++, dest += vid.rowbytes) { + for (int u = 0; u < w; u++) { + dest[u] = c; + } + } +} + +void +draw_fill_16 (int x, int y, int w, int h, int c) +{ + byte *dest = ((byte*)vid.buffer) + y * (vid.rowbytes >> 1) + x; + c = d_8to16table[c]; + for (int v = 0; v < h; v++, dest += vid.rowbytes >> 1) { + for (int u = 0; u < w; u++) { + dest[u] = c; + } + } +} + +void +draw_fill_32 (int x, int y, int w, int h, int c) +{ + byte *dest = ((byte*)vid.buffer) + y * (vid.rowbytes >> 2) + x; + c = d_8to24table[c]; + for (int v = 0; v < h; v++, dest += vid.rowbytes >> 2) { + for (int u = 0; u < w; u++) { + dest[u] = c; + } + } +} /* Draw_Fill @@ -744,9 +1097,6 @@ Draw_TileClear (int x, int y, int w, int h) void Draw_Fill (int x, int y, int w, int h, int c) { - byte *dest; - int u, v; - if (x < 0 || x + w > vid.conview->xlen || y < 0 || y + h > vid.conview->ylen) { Sys_MaskPrintf (SYS_vid, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", @@ -754,40 +1104,77 @@ Draw_Fill (int x, int y, int w, int h, int c) } CLIP (x, y, w, h, (int) vid.width, (int) vid.height); - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; - for (v = 0; v < h; v++, dest += vid.rowbytes) - for (u = 0; u < w; u++) - dest[u] = c; + sw_ctx->draw->draw_fill (x, y, w, h, c); } +void +draw_fadescreen_8 (void) +{ + int height = vid.conview->ylen; + int width = vid.conview->xlen / 4; + int offset = vid.rowbytes; + uint32_t *pbuf; + + for (int y = 0; y < height; y++) { + uint32_t mask; + + pbuf = (uint32_t *) ((byte *)vid.buffer + offset * y); + mask = 0xff << ((y & 1) << 4); + + for (int x = 0; x < width; x++) { + *pbuf++ &= mask; + } + } +} + +void +draw_fadescreen_16 (void) +{ + int height = vid.conview->ylen; + int width = vid.conview->xlen / 4; + int offset = vid.rowbytes >> 1; + uint32_t *pbuf; + + for (int y = 0; y < height; y++) { + pbuf = (uint32_t *) ((byte *)vid.buffer + offset * y); + + for (int x = 0; x < width; x++, pbuf++) { + *pbuf = (*pbuf >> 1) & 0x7bef7bef; + } + } +} + +void +draw_fadescreen_32 (void) +{ + int height = vid.conview->ylen; + int width = vid.conview->xlen / 4; + int offset = vid.rowbytes >> 2; + uint32_t *pbuf; + + for (int y = 0; y < height; y++) { + pbuf = (uint32_t *) ((byte *)vid.buffer + offset * y); + + for (int x = 0; x < width; x++, pbuf++) { + *pbuf = (*pbuf >> 1) & 0x7f7f7f7f; + } + } +} void Draw_FadeScreen (void) { - int x, y; - int height = vid.conview->ylen; - int width = vid.conview->xlen / 4; - uint32_t *pbuf; S_ExtraUpdate (); - for (y = 0; y < height; y++) { - uint32_t mask; - - pbuf = (uint32_t *) ((byte *)vid.buffer + vid.rowbytes * y); - mask = 0xff << ((y & 1) << 4); - - for (x = 0; x < width; x++) { - *pbuf++ &= mask; - } - } + sw_ctx->draw->draw_fadescreen (); vr_data.scr_copyeverything = 1; S_ExtraUpdate (); } void -Draw_BlendScreen (quat_t color) +draw_blendscreen_8 (quat_t color) { int r, g, b, i; const byte *basepal; @@ -813,3 +1200,73 @@ Draw_BlendScreen (quat_t color) } vid.vid_internal->set_palette (vid.vid_internal->data, pal); } + +void +draw_blendscreen_16 (quat_t color) +{ + int i, r, b; + int g1, g2; + unsigned x, y; + unsigned short rramp[32], gramp[64], bramp[32], *temp; + for (i = 0; i < 32; i++) { + r = i << 3; + g1 = i << 3; + g2 = g1 + 4; + b = i << 3; + + r += (int) (color[3] * (color[0] * 256 - r)); + g1 += (int) (color[3] * (color[1] - g1)); + g2 += (int) (color[3] * (color[1] - g2)); + b += (int) (color[3] * (color[2] - b)); + + rramp[i] = (vid.gammatable[r] << 8) & 0xF800; + gramp[i*2+0] = (vid.gammatable[g1] << 3) & 0x07E0; + gramp[i*2+1] = (vid.gammatable[g2] << 3) & 0x07E0; + bramp[i] = (vid.gammatable[b] >> 3) & 0x001F; + } + temp = vid.buffer; + for (y = 0;y < vid.height;y++, temp += (vid.rowbytes >> 1)) + for (x = 0;x < vid.width;x++) + temp[x] = rramp[(temp[x] & 0xF800) >> 11] + + gramp[(temp[x] & 0x07E0) >> 5] + bramp[temp[x] & 0x001F]; +} + +void +draw_blendscreen_32 (quat_t color) +{ + unsigned x, y; + int i, r, g, b; + + byte ramp[256][4], *temp; + for (i = 0; i < 256; i++) { + r = i; + g = i; + b = i; + + r += (int) (color[3] * (color[0] * 256 - r)); + g += (int) (color[3] * (color[1] * 256 - g)); + b += (int) (color[3] * (color[2] * 256 - b)); + + ramp[i][0] = vid.gammatable[r]; + ramp[i][1] = vid.gammatable[g]; + ramp[i][2] = vid.gammatable[b]; + ramp[i][3] = 0; + } + temp = vid.buffer; + for (y = 0; y < vid.height; y++, temp += vid.rowbytes) + { + for (x = 0;x < vid.width;x++) + { + temp[x*4+0] = ramp[temp[x*4+0]][0]; + temp[x*4+1] = ramp[temp[x*4+1]][1]; + temp[x*4+2] = ramp[temp[x*4+2]][2]; + temp[x*4+3] = 0; + } + } +} + +void +Draw_BlendScreen (quat_t color) +{ + sw_ctx->draw->draw_blendscreen (color); +} diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 30a60379e..31daf43f3 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -37,9 +37,8 @@ #include "vid_sw.h" /* SCREEN SHOTS */ - tex_t * -sw_SCR_CaptureBGR (void) +capture_bgr_8 (void) { int count, x, y; tex_t *tex; @@ -66,3 +65,21 @@ sw_SCR_CaptureBGR (void) } return tex; } + +tex_t * +capture_bgr_16 (void) +{ + return capture_bgr_8 ();//FIXME +} + +tex_t * +capture_bgr_32 (void) +{ + return capture_bgr_8 ();//FIXME +} + +tex_t * +sw_SCR_CaptureBGR (void) +{ + return sw_ctx->draw->capture_bgr (); +} diff --git a/libs/video/renderer/sw/surf8.S b/libs/video/renderer/sw/surf8.S index c15d2c689..c112bf1f7 100644 --- a/libs/video/renderer/sw/surf8.S +++ b/libs/video/renderer/sw/surf8.S @@ -55,8 +55,8 @@ C(R_Surf8Start): //---------------------------------------------------------------------- .align 4 -.globl C(R_DrawSurfaceBlock_mip0) -C(R_DrawSurfaceBlock_mip0): +.globl C(R_DrawSurfaceBlock8_mip0) +C(R_DrawSurfaceBlock8_mip0): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables @@ -70,7 +70,7 @@ C(R_DrawSurfaceBlock_mip0): movl %eax,sb_v movl C(prowdestbase),%edi - movl C(pbasesource),%esi + movl C(psource),%esi Lv_loop_mip0: @@ -256,8 +256,8 @@ LBPatch15: movl %edx,C(lightright) jc Lblockloop8_mip0 -// if (pbasesource >= r_sourcemax) -// pbasesource -= stepback; +// if (psource >= r_sourcemax) +// psource -= stepback; cmpl C(r_sourcemax),%esi jb LSkip_mip0 @@ -281,8 +281,8 @@ LSkip_mip0: //---------------------------------------------------------------------- .align 4 -.globl C(R_DrawSurfaceBlock_mip1) -C(R_DrawSurfaceBlock_mip1): +.globl C(R_DrawSurfaceBlock8_mip1) +C(R_DrawSurfaceBlock8_mip1): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables @@ -296,7 +296,7 @@ C(R_DrawSurfaceBlock_mip1): movl %eax,sb_v movl C(prowdestbase),%edi - movl C(pbasesource),%esi + movl C(psource),%esi Lv_loop_mip1: @@ -426,8 +426,8 @@ LBPatch29: jc Lblockloop8_mip1 -// if (pbasesource >= r_sourcemax) -// pbasesource -= stepback; +// if (psource >= r_sourcemax) +// psource -= stepback; cmpl C(r_sourcemax),%esi jb LSkip_mip1 @@ -451,8 +451,8 @@ LSkip_mip1: //---------------------------------------------------------------------- .align 4 -.globl C(R_DrawSurfaceBlock_mip2) -C(R_DrawSurfaceBlock_mip2): +.globl C(R_DrawSurfaceBlock8_mip2) +C(R_DrawSurfaceBlock8_mip2): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables @@ -466,7 +466,7 @@ C(R_DrawSurfaceBlock_mip2): movl %eax,sb_v movl C(prowdestbase),%edi - movl C(pbasesource),%esi + movl C(psource),%esi Lv_loop_mip2: @@ -566,8 +566,8 @@ LBPatch21: jc Lblockloop8_mip2 -// if (pbasesource >= r_sourcemax) -// pbasesource -= stepback; +// if (psource >= r_sourcemax) +// psource -= stepback; cmpl C(r_sourcemax),%esi jb LSkip_mip2 @@ -591,8 +591,8 @@ LSkip_mip2: //---------------------------------------------------------------------- .align 4 -.globl C(R_DrawSurfaceBlock_mip3) -C(R_DrawSurfaceBlock_mip3): +.globl C(R_DrawSurfaceBlock8_mip3) +C(R_DrawSurfaceBlock8_mip3): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables @@ -606,7 +606,7 @@ C(R_DrawSurfaceBlock_mip3): movl %eax,sb_v movl C(prowdestbase),%edi - movl C(pbasesource),%esi + movl C(psource),%esi Lv_loop_mip3: @@ -708,8 +708,8 @@ LBPatch31: addl %edx,%esi addl %ebp,%edi -// if (pbasesource >= r_sourcemax) -// pbasesource -= stepback; +// if (psource >= r_sourcemax) +// psource -= stepback; cmpl C(r_sourcemax),%esi jb LSkip_mip3 diff --git a/libs/video/renderer/sw/sw_graph.c b/libs/video/renderer/sw/sw_graph.c index 4480a7eb7..edcecf9a4 100644 --- a/libs/video/renderer/sw/sw_graph.c +++ b/libs/video/renderer/sw/sw_graph.c @@ -33,23 +33,21 @@ #include "QF/render.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" -/* - R_LineGraph - - Called by only R_DisplayTime -*/ void -R_LineGraph (int x, int y, int *h_vals, int count, int height) +line_grapn_8 (int x, int y, int *h_vals, int count, int height) { int h, i, s, color; + int offset = vid.rowbytes; byte *dest; // FIXME: disable on no-buffer adapters, or put in the driver s = height; while (count--) { - dest = ((byte*)vid.buffer) + vid.rowbytes * y + x++; + dest = ((byte*)vid.buffer) + offset * y + x++; h = *h_vals++; @@ -65,8 +63,80 @@ R_LineGraph (int x, int y, int *h_vals, int count, int height) if (h > s) h = s; - for (i = 0; i < h; i++, dest -= vid.rowbytes) { + for (i = 0; i < h; i++, dest -= offset) { dest[0] = color; } } } + +void +line_grapn_16 (int x, int y, int *h_vals, int count, int height) +{ + int h, i, s, color; + int offset = vid.rowbytes >> 1; + uint16_t *dest; + + // FIXME: disable on no-buffer adapters, or put in the driver + s = height; + + while (count--) { + dest = ((uint16_t*)vid.buffer) + offset * y + x++; + + h = *h_vals++; + + if (h == 10000) + color = d_8to16table[0x6f]; // yellow + else if (h == 9999) + color = d_8to16table[0x4f]; // red + else if (h == 9998) + color = d_8to16table[0xd0]; // blue + else + color = d_8to16table[0xff]; // pink + + if (h > s) + h = s; + + for (i = 0; i < h; i++, dest -= offset) { + dest[0] = color; + } + } +} + +void +line_grapn_32 (int x, int y, int *h_vals, int count, int height) +{ + int h, i, s, color; + int offset = vid.rowbytes >> 2; + uint32_t *dest; + + // FIXME: disable on no-buffer adapters, or put in the driver + s = height; + + while (count--) { + dest = ((uint32_t*)vid.buffer) + offset * y + x++; + + h = *h_vals++; + + if (h == 10000) + color = d_8to24table[0x6f]; // yellow + else if (h == 9999) + color = d_8to24table[0x4f]; // red + else if (h == 9998) + color = d_8to24table[0xd0]; // blue + else + color = d_8to24table[0xff]; // pink + + if (h > s) + h = s; + + for (i = 0; i < h; i++, dest -= offset) { + dest[0] = color; + } + } +} + +void +R_LineGraph (int x, int y, int *h_vals, int count, int height) +{ + sw_ctx->draw->line_grapn (x, y, h_vals, count, height); +} diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 1899e2a47..0158524e5 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -39,6 +39,7 @@ #include "d_ifacea.h" #include "r_internal.h" +#include "vid_sw.h" #define LIGHT_MIN 5 // lowest light value we'll allow, to // avoid the need for inner-loop light @@ -563,6 +564,12 @@ R_AliasSetupSkin (entity_t *ent) r_affinetridesc.skinheight = pmdl->skinheight; acolormap = vid.colormap8; + if (sw_ctx->pixbytes != 1) { + if (sw_ctx->pixbytes == 2) + acolormap = vid.colormap16; + else + acolormap = vid.colormap32; + } if (ent->renderer.skin) { tex_t *base; @@ -655,6 +662,12 @@ R_AliasDrawModel (alight_t *plighting) if (!acolormap) acolormap = vid.colormap8; + if (acolormap == vid.colormap8 && sw_ctx->pixbytes != 1) { + if (sw_ctx->pixbytes == 2) + acolormap = vid.colormap16; + else + acolormap = vid.colormap32; + } if (r_affinetridesc.drawtype) { D_PolysetUpdateTables (); // FIXME: precalc... diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 841036858..6b56f18eb 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -54,11 +54,28 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" #ifdef PIC # undef USE_INTEL_ASM //XXX asm pic hack #endif +static sw_draw_t sw_draw_8 = { +#define SW_DRAW_FUNC(name, rettype, params) \ + .name = name##_8, +#include "vid_sw_draw.h" +}; +static sw_draw_t sw_draw_16 = { +#define SW_DRAW_FUNC(name, rettype, params) \ + .name = name##_16, +#include "vid_sw_draw.h" +}; +static sw_draw_t sw_draw_32 = { +#define SW_DRAW_FUNC(name, rettype, params) \ + .name = name##_32, +#include "vid_sw_draw.h" +}; + void *colormap; static vec3_t viewlightvec; static alight_t r_viewlighting = { 128, 192, viewlightvec }; @@ -117,6 +134,15 @@ sw_R_Init (void) { int dummy; + switch (sw_ctx->pixbytes) { + case 1: sw_ctx->draw = &sw_draw_8; break; + case 2: sw_ctx->draw = &sw_draw_16; break; + case 4: sw_ctx->draw = &sw_draw_32; break; + default: + Sys_Error("R_Init: unsupported pixbytes %i", + sw_ctx->pixbytes); + } + r_ent_queue = EntQueue_New (mod_num_types); // get stack position so we can guess if we are going to overflow @@ -806,7 +832,7 @@ R_RenderView_ (void) dp_time2 = Sys_DoubleTime (); if (r_dowarp) - D_WarpScreen (); + sw_ctx->draw->warp_screen (); if (r_timegraph->int_val) R_TimeGraph (); diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index a76d2d105..15928e633 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -48,6 +48,7 @@ #include "compat.h" #include "r_internal.h" +#include "vid_sw.h" void R_DrawParticles (void) @@ -58,9 +59,10 @@ R_DrawParticles (void) R_RunParticles (vr_data.frametime); + void (*draw) (struct particle_s *particle) = sw_ctx->draw->draw_particle; for (unsigned i = 0; i < r_psystem.numparticles; i++) { particle_t *p = &r_psystem.particles[i]; - D_DrawParticle (p); + draw (p); } } diff --git a/libs/video/renderer/sw/sw_rsky.c b/libs/video/renderer/sw/sw_rsky.c index b179ce420..d67d0f375 100644 --- a/libs/video/renderer/sw/sw_rsky.c +++ b/libs/video/renderer/sw/sw_rsky.c @@ -28,9 +28,13 @@ # include "config.h" #endif +#include + #include "QF/render.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" static int iskyspeed = 8; @@ -47,10 +51,12 @@ int r_skymade; byte bottomsky[128 * 131]; byte bottommask[128 * 131]; -byte newsky[128 * 256]; // newsky and topsky both pack in here, 128 - // bytes of newsky on the left of each scan, - // 128 bytes of topsky on the right, because - // the low-level drawers need 256-byte widths +// sky and topsky both pack in here, 128 +// bytes of sky on the left of each scan, +// 128 bytes of topsky on the right, because +// the low-level drawers need 256-byte widths +byte skydata[128 * 256]; +byte skytex[128 * 256 * 4]; /* @@ -61,115 +67,115 @@ byte newsky[128 * 256]; // newsky and topsky both pack in here, 128 void R_InitSky (texture_t *mt) { - int i, j; - byte *src; - - src = (byte *) mt + mt->offsets[0]; - - for (i = 0; i < 128; i++) { - for (j = 0; j < 128; j++) { - newsky[(i * 256) + j + 128] = src[i * 256 + j + 128]; - } - } - - for (i = 0; i < 128; i++) { - for (j = 0; j < 131; j++) { - if (src[i * 256 + (j & 0x7F)]) { - bottomsky[(i * 131) + j] = src[i * 256 + (j & 0x7F)]; - bottommask[(i * 131) + j] = 0; - } else { - bottomsky[(i * 131) + j] = 0; - bottommask[(i * 131) + j] = 0xff; - } - } - } - - r_skysource = newsky; + memcpy (skydata, (byte *) mt + mt->offsets[0], 128 * 256); + r_skysource = skytex; } - void -R_MakeSky (void) +make_sky_8 (void) { - int x, y; - int ofs, baseofs; - int xshift, yshift; - byte *pnewsky; + int x, y, xshift1, yshift1, xshift2, yshift2; + byte *base1, *base2; static int xlast = -1, ylast = -1; - xshift = r_skytime * r_skyspeed; - yshift = r_skytime * r_skyspeed; + xshift2 = r_skytime * r_skyspeed * 2.0f; + yshift2 = r_skytime * r_skyspeed * 2.0f; - if ((xshift == xlast) && (yshift == ylast)) + if ((xshift2 == xlast) && (yshift2 == ylast)) return; - xlast = xshift; - ylast = yshift; + xlast = xshift2; + ylast = yshift2; + xshift1 = xshift2 >> 1; + yshift1 = yshift2 >> 1; - pnewsky = &newsky[0]; - - for (y = 0; y < SKYSIZE; y++) { - baseofs = ((y + yshift) & SKYMASK) * 131; - for (x = 0; x < SKYSIZE; x++) { - ofs = baseofs + ((x + xshift) & SKYMASK); - - *pnewsky = (*(pnewsky + 128) & bottommask[ofs]) | bottomsky[ofs]; - pnewsky = pnewsky + 1; + byte *out = (byte *) skytex; + for (y = 0;y < 128;y++) + { + base1 = &skydata[((y + yshift1) & 127) * 256]; + base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; + for (x = 0;x < 128;x++) + { + if (base1[(x + xshift1) & 127]) + *out = base1[(x + xshift1) & 127]; + else + *out = base2[(x + xshift2) & 127]; + out++; } - pnewsky += 128; + out += 128; } - r_skymade = 1; } - void -R_GenSkyTile (void *pdest) +make_sky_16 (void) { - int x, y; - int ofs, baseofs; - int xshift, yshift; - unsigned int *pnewsky; - unsigned int *pd; + int x, y, xshift1, yshift1, xshift2, yshift2; + byte *base1, *base2; + static int xlast = -1, ylast = -1; - xshift = r_skytime * r_skyspeed; - yshift = r_skytime * r_skyspeed; + xshift2 = r_skytime * r_skyspeed * 2.0f; + yshift2 = r_skytime * r_skyspeed * 2.0f; - pnewsky = (unsigned int *) &newsky[0]; - pd = (unsigned int *) pdest; + if ((xshift2 == xlast) && (yshift2 == ylast)) + return; - for (y = 0; y < SKYSIZE; y++) { - baseofs = ((y + yshift) & SKYMASK) * 131; + xlast = xshift2; + ylast = yshift2; + xshift1 = xshift2 >> 1; + yshift1 = yshift2 >> 1; -// FIXME: clean this up -#if UNALIGNED_OK - for (x = 0; x < SKYSIZE; x += 4) { - ofs = baseofs + ((x + xshift) & SKYMASK); - - // PORT: unaligned dword access to bottommask and bottomsky - - *pd = (*(pnewsky + (128 / sizeof (unsigned int))) & - *(unsigned int *) &bottommask[ofs]) | - *(unsigned int *) &bottomsky[ofs]; - - pnewsky++; - pd++; + unsigned short *out = (unsigned short *) skytex; + for (y = 0;y < 128;y++) + { + base1 = &skydata[((y + yshift1) & 127) * 256]; + base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; + for (x = 0;x < 128;x++) + { + if (base1[(x + xshift1) & 127]) + *out = d_8to16table[base1[(x + xshift1) & 127]]; + else + *out = d_8to16table[base2[(x + xshift2) & 127]]; + out++; } -#else - for (x = 0; x < SKYSIZE; x++) { - ofs = baseofs + ((x + xshift) & SKYMASK); - - *(byte *) pd = (*((byte *) pnewsky + 128) & - *(byte *) & bottommask[ofs]) | - *(byte *) & bottomsky[ofs]; - pnewsky = (unsigned int *) ((byte *) pnewsky + 1); - pd = (unsigned int *) ((byte *) pd + 1); - } -#endif - pnewsky += 128 / sizeof (unsigned int); + out += 128; } + r_skymade = 1; } +void +make_sky_32 (void) +{ + int x, y, xshift1, yshift1, xshift2, yshift2; + byte *base1, *base2; + static int xlast = -1, ylast = -1; + + xshift2 = r_skytime * r_skyspeed * 2.0f; + yshift2 = r_skytime * r_skyspeed * 2.0f; + + if ((xshift2 == xlast) && (yshift2 == ylast)) + return; + + xlast = xshift2; + ylast = yshift2; + xshift1 = xshift2 >> 1; + yshift1 = yshift2 >> 1; + + unsigned int *out = (unsigned int *) skytex; + for (y = 0;y < 128;y++) { + base1 = &skydata[((y + yshift1) & 127) * 256]; + base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; + for (x = 0;x < 128;x++) { + if (base1[(x + xshift1) & 127]) + *out = d_8to24table[base1[(x + xshift1) & 127]]; + else + *out = d_8to24table[base2[(x + xshift2) & 127]]; + out++; + } + out += 128; + } + r_skymade = 1; +} void R_SetSkyFrame (void) diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 106dd8f29..3b968bd88 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -1,5 +1,5 @@ /* - sw_rsurf.c + rsurf.c surface-related refresh code @@ -33,43 +33,63 @@ #include "QF/scene/entity.h" +#include "compat.h" #include "r_internal.h" - -#ifdef PIC -# undef USE_INTEL_ASM //XXX asm pic hack -#endif +#include "vid_sw.h" drawsurf_t r_drawsurf; -int sourcesstep, sourcetstep; -#ifndef USE_INTEL_ASM -static int lightleft; -#endif -static int blocksize; +int sourcetstep; +static int lightleft, blocksize; int lightdelta, lightdeltastep; int lightright, lightleftstep, lightrightstep, blockdivshift; static unsigned int blockdivmask; -void *prowdestbase; -unsigned char *pbasesource; -int surfrowbytes; // used by ASM files -unsigned int *r_lightptr; +byte *prowdestbase; +byte *psource; +int surfrowbytes; +unsigned int *r_lightptr; int r_stepback; int r_lightwidth; static int r_numhblocks; int r_numvblocks; -static unsigned char *r_source; -unsigned char *r_sourcemax; +static byte *r_source; +byte *r_sourcemax; -void R_DrawSurfaceBlock_mip0 (void); -void R_DrawSurfaceBlock_mip1 (void); -void R_DrawSurfaceBlock_mip2 (void); -void R_DrawSurfaceBlock_mip3 (void); +void R_DrawSurfaceBlock8_mip0 (void); +void R_DrawSurfaceBlock8_mip1 (void); +void R_DrawSurfaceBlock8_mip2 (void); +void R_DrawSurfaceBlock8_mip3 (void); +static void R_DrawSurfaceBlock16_mip0 (void); +static void R_DrawSurfaceBlock16_mip1 (void); +static void R_DrawSurfaceBlock16_mip2 (void); +static void R_DrawSurfaceBlock16_mip3 (void); +static void R_DrawSurfaceBlock32_mip0 (void); +static void R_DrawSurfaceBlock32_mip1 (void); +static void R_DrawSurfaceBlock32_mip2 (void); +static void R_DrawSurfaceBlock32_mip3 (void); -static void (*surfmiptable[4]) (void) = { - R_DrawSurfaceBlock_mip0, R_DrawSurfaceBlock_mip1, - R_DrawSurfaceBlock_mip2, R_DrawSurfaceBlock_mip3}; +static void (*surfmiptable8[4]) (void) = { + R_DrawSurfaceBlock8_mip0, + R_DrawSurfaceBlock8_mip1, + R_DrawSurfaceBlock8_mip2, + R_DrawSurfaceBlock8_mip3 +}; -static unsigned int blocklights[34 * 34]; //FIXME make dynamic +static void (*surfmiptable16[4]) (void) = { + R_DrawSurfaceBlock16_mip0, + R_DrawSurfaceBlock16_mip1, + R_DrawSurfaceBlock16_mip2, + R_DrawSurfaceBlock16_mip3 +}; + +static void (*surfmiptable32[4]) (void) = { + R_DrawSurfaceBlock32_mip0, + R_DrawSurfaceBlock32_mip1, + R_DrawSurfaceBlock32_mip2, + R_DrawSurfaceBlock32_mip3 +}; + +static unsigned blocklights[34 * 34]; //FIXME make dynamic static void @@ -182,14 +202,30 @@ R_BuildLightMap (void) if (surf->dlightframe == r_framecount) R_AddDynamicLights (); - // bound, invert, and shift - for (i = 0; i < size; i++) { - t = (255 * 256 - (int) blocklights[i]) >> (8 - VID_CBITS); + /* + * JohnnyonFlame: + * 32 and 16bpp modes uses the positive lighting, unlike 8bpp + */ + switch (sw_ctx->pixbytes) { + case 1: + // bound, invert, and shift + for (i = 0; i < size; i++) { + t = (255 * 256 - blocklights[i]) >> (8 - VID_CBITS); - if (t < (1 << 6)) - t = (1 << 6); + if (t < (1 << 6)) + t = (1 << 6); - blocklights[i] = t; + blocklights[i] = t; + } + break; + default: + // LordHavoc: changed to positive (not inverse) lighting + for (i = 0; i < size; i++) { + t = bound(256, blocklights[i] >> (8 - VID_CBITS), + 256 * (VID_GRADES - 1)); + blocklights[i] = t; + } + break; } } @@ -230,34 +266,47 @@ R_DrawSurface (void) //============================== - pblockdrawer = surfmiptable[r_drawsurf.surfmip]; - // TODO: needs to be set only when there is a display settings change - horzblockstep = blocksize; - smax = mt->width >> r_drawsurf.surfmip; twidth = texwidth; tmax = mt->height >> r_drawsurf.surfmip; sourcetstep = texwidth; r_stepback = tmax * twidth; - r_sourcemax = r_source + (tmax * smax); - soffset = r_drawsurf.surf->texturemins[0]; basetoffset = r_drawsurf.surf->texturemins[1]; - // << 16 components are to guarantee positive values for % - soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax; - basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip) - + (tmax << 16)) % tmax) * twidth)]; + switch (sw_ctx->pixbytes) { + case 1: + pblockdrawer = surfmiptable8[r_drawsurf.surfmip]; + break; + case 2: + pblockdrawer = surfmiptable16[r_drawsurf.surfmip]; + break; + case 4: + pblockdrawer = surfmiptable32[r_drawsurf.surfmip]; + break; + default: + Sys_Error("R_DrawSurface: unsupported r_pixbytes %i", sw_ctx->pixbytes); + pblockdrawer = NULL; + } - pcolumndest = r_drawsurf.surfdat; + horzblockstep = blocksize * sw_ctx->pixbytes; + + r_sourcemax = r_source + (tmax * smax); + + // << 16 components are to guarantee positive values for % + basetptr = r_source + (((basetoffset >> r_drawsurf.surfmip) + + (tmax << 16)) % tmax) * twidth; + soffset = (((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax); + + pcolumndest = (byte *) r_drawsurf.surfdat; for (u = 0; u < r_numhblocks; u++) { r_lightptr = blocklights + u; prowdestbase = pcolumndest; - pbasesource = basetptr + soffset; + psource = basetptr + soffset; (*pblockdrawer) (); @@ -269,15 +318,16 @@ R_DrawSurface (void) } } +//============================================================================= + #ifndef USE_INTEL_ASM void -R_DrawSurfaceBlock_mip0 (void) +R_DrawSurfaceBlock8_mip0 (void) { - int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + int v, i, b, lightstep, light; + unsigned char pix, *prowdest; - psource = pbasesource; prowdest = prowdestbase; for (v = 0; v < r_numvblocks; v++) { @@ -290,15 +340,13 @@ R_DrawSurfaceBlock_mip0 (void) lightrightstep = (r_lightptr[1] - lightright) >> 4; for (i = 0; i < 16; i++) { - lighttemp = lightleft - lightright; - lightstep = lighttemp >> 4; + lightstep = (lightleft - lightright) >> 4; light = lightright; for (b = 15; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap8) - [(light & 0xFF00) + pix]; + prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; light += lightstep; } @@ -314,12 +362,11 @@ R_DrawSurfaceBlock_mip0 (void) } void -R_DrawSurfaceBlock_mip1 (void) +R_DrawSurfaceBlock8_mip1 (void) { - int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + int v, i, b, lightstep, light; + unsigned char pix, *prowdest; - psource = pbasesource; prowdest = prowdestbase; for (v = 0; v < r_numvblocks; v++) { @@ -332,15 +379,13 @@ R_DrawSurfaceBlock_mip1 (void) lightrightstep = (r_lightptr[1] - lightright) >> 3; for (i = 0; i < 8; i++) { - lighttemp = lightleft - lightright; - lightstep = lighttemp >> 3; + lightstep = (lightleft - lightright) >> 3; light = lightright; for (b = 7; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap8) - [(light & 0xFF00) + pix]; + prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; light += lightstep; } @@ -356,12 +401,11 @@ R_DrawSurfaceBlock_mip1 (void) } void -R_DrawSurfaceBlock_mip2 (void) +R_DrawSurfaceBlock8_mip2 (void) { - int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + int v, i, b, lightstep, light; + unsigned char pix, *prowdest; - psource = pbasesource; prowdest = prowdestbase; for (v = 0; v < r_numvblocks; v++) { @@ -374,15 +418,13 @@ R_DrawSurfaceBlock_mip2 (void) lightrightstep = (r_lightptr[1] - lightright) >> 2; for (i = 0; i < 4; i++) { - lighttemp = lightleft - lightright; - lightstep = lighttemp >> 2; + lightstep = (lightleft - lightright) >> 2; light = lightright; for (b = 3; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap8) - [(light & 0xFF00) + pix]; + prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; light += lightstep; } @@ -398,12 +440,11 @@ R_DrawSurfaceBlock_mip2 (void) } void -R_DrawSurfaceBlock_mip3 (void) +R_DrawSurfaceBlock8_mip3 (void) { - int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + int v, i, b, lightstep, light; + unsigned char pix, *prowdest; - psource = pbasesource; prowdest = prowdestbase; for (v = 0; v < r_numvblocks; v++) { @@ -416,15 +457,13 @@ R_DrawSurfaceBlock_mip3 (void) lightrightstep = (r_lightptr[1] - lightright) >> 1; for (i = 0; i < 2; i++) { - lighttemp = lightleft - lightright; - lightstep = lighttemp >> 1; + lightstep = (lightleft - lightright) >> 1; light = lightright; for (b = 1; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap8) - [(light & 0xFF00) + pix]; + prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; light += lightstep; } @@ -442,33 +481,423 @@ R_DrawSurfaceBlock_mip3 (void) #endif static void -R_GenTurbTile (byte *pbasetex, void *pdest) +R_DrawSurfaceBlock16_mip0 (void) { - int *turb; - int i, j, s, t; - byte *pd; + int k, v; + int lightstep, light; + unsigned short *prowdest; - turb = sintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - pd = (byte *) pdest; + prowdest = (unsigned short *) prowdestbase; - for (i = 0; i < TILE_SIZE; i++) { - for (j = 0; j < TILE_SIZE; j++) { - s = (((j << 16) + turb[i & (CYCLE - 1)]) >> 16) & 63; - t = (((i << 16) + turb[j & (CYCLE - 1)]) >> 16) & 63; - *pd++ = *(pbasetex + (t << 6) + s); + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 4; + lightrightstep = (r_lightptr[1] - lightright) >> 4; + + for (k = 0; k < 16; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 4; + + prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; + light += lightstep; + prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]]; + light += lightstep; + prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]]; + light += lightstep; + prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]]; + light += lightstep; + prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]]; + light += lightstep; + prowdest[8] = vid.colormap16[(light & 0xFF00) + psource[8]]; + light += lightstep; + prowdest[9] = vid.colormap16[(light & 0xFF00) + psource[9]]; + light += lightstep; + prowdest[10] = vid.colormap16[(light & 0xFF00) + psource[10]]; + light += lightstep; + prowdest[11] = vid.colormap16[(light & 0xFF00) + psource[11]]; + light += lightstep; + prowdest[12] = vid.colormap16[(light & 0xFF00) + psource[12]]; + light += lightstep; + prowdest[13] = vid.colormap16[(light & 0xFF00) + psource[13]]; + light += lightstep; + prowdest[14] = vid.colormap16[(light & 0xFF00) + psource[14]]; + light += lightstep; + prowdest[15] = vid.colormap16[(light & 0xFF00) + psource[15]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 1); } + + if (psource >= r_sourcemax) + psource -= r_stepback; } } -void -R_GenTile (msurface_t *psurf, void *pdest) +static void +R_DrawSurfaceBlock16_mip1 (void) { - if (psurf->flags & SURF_DRAWTURB) { - R_GenTurbTile (((byte *) psurf->texinfo->texture + - psurf->texinfo->texture->offsets[0]), pdest); - } else if (psurf->flags & SURF_DRAWSKY) { - R_GenSkyTile (pdest); - } else { - Sys_Error ("Unknown tile type"); + int k, v; + int lightstep, light; + unsigned short *prowdest; + + prowdest = (unsigned short *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 3; + lightrightstep = (r_lightptr[1] - lightright) >> 3; + + for (k = 0; k < 8; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 3; + + prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; + light += lightstep; + prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]]; + light += lightstep; + prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]]; + light += lightstep; + prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]]; + light += lightstep; + prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 1); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; } } + +static void +R_DrawSurfaceBlock16_mip2 (void) +{ + int k, v; + int lightstep, light; + unsigned short *prowdest; + + prowdest = (unsigned short *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 2; + lightrightstep = (r_lightptr[1] - lightright) >> 2; + + for (k = 0; k < 4; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 2; + + prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 1); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +static void +R_DrawSurfaceBlock16_mip3 (void) +{ + int v; + unsigned short *prowdest; + + prowdest = (unsigned short *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 1; + lightrightstep = (r_lightptr[1] - lightright) >> 1; + + prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]]; + prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) & + 0xFF00) + psource[1]]; + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 1); + + prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]]; + prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) & + 0xFF00) + psource[1]]; + psource += sourcetstep; + prowdest += (surfrowbytes >> 1); + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +static void +R_DrawSurfaceBlock32_mip0 (void) +{ + int k, v; + int lightstep, light; + unsigned int *prowdest; + + prowdest = (unsigned int *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 4; + lightrightstep = (r_lightptr[1] - lightright) >> 4; + + for (k = 0; k < 16; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 4; + + prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; + light += lightstep; + prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]]; + light += lightstep; + prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]]; + light += lightstep; + prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]]; + light += lightstep; + prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]]; + light += lightstep; + prowdest[8] = vid.colormap32[(light & 0xFF00) + psource[8]]; + light += lightstep; + prowdest[9] = vid.colormap32[(light & 0xFF00) + psource[9]]; + light += lightstep; + prowdest[10] = vid.colormap32[(light & 0xFF00) + psource[10]]; + light += lightstep; + prowdest[11] = vid.colormap32[(light & 0xFF00) + psource[11]]; + light += lightstep; + prowdest[12] = vid.colormap32[(light & 0xFF00) + psource[12]]; + light += lightstep; + prowdest[13] = vid.colormap32[(light & 0xFF00) + psource[13]]; + light += lightstep; + prowdest[14] = vid.colormap32[(light & 0xFF00) + psource[14]]; + light += lightstep; + prowdest[15] = vid.colormap32[(light & 0xFF00) + psource[15]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +static void +R_DrawSurfaceBlock32_mip1 (void) +{ + int k, v; + int lightstep, light; + unsigned int *prowdest; + + prowdest = (unsigned int *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 3; + lightrightstep = (r_lightptr[1] - lightright) >> 3; + + for (k = 0; k < 8; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 3; + + prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; + light += lightstep; + prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]]; + light += lightstep; + prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]]; + light += lightstep; + prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]]; + light += lightstep; + prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +static void +R_DrawSurfaceBlock32_mip2 (void) +{ + int k, v; + int lightstep, light; + unsigned int *prowdest; + + prowdest = (unsigned int *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 2; + lightrightstep = (r_lightptr[1] - lightright) >> 2; + + for (k = 0; k < 4; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 2; + + prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +static void +R_DrawSurfaceBlock32_mip3 (void) +{ + int v; + unsigned int *prowdest; + + prowdest = (unsigned int *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 1; + lightrightstep = (r_lightptr[1] - lightright) >> 1; + + prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]]; + prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) & + 0xFF00) + psource[1]]; + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + + prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]]; + prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) & + 0xFF00) + psource[1]]; + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +/* +void +R_DrawSurfaceBlock32 (void) +{ + int k, v; + int lightstep, light; + unsigned int *prowdest; + + prowdest = prowdestbase; + + for (v = 0; v < r_numvblocks; v++) { + + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> blockdivshift; + lightrightstep = (r_lightptr[1] - lightright) >> blockdivshift; + + for (k = 0; k < blocksize; k++) { + int b; + + lightstep = (lightright - lightleft) >> blockdivshift; + + light = lightleft; + + for (b = 0;b < blocksize;b++, light += lightstep) + prowdest[b] = vid.colormap32[(light & 0xFF00) + psource[b]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} +*/ diff --git a/libs/video/renderer/sw/vid_common_sw.c b/libs/video/renderer/sw/vid_common_sw.c index f67a4ce8b..554daeddb 100644 --- a/libs/video/renderer/sw/vid_common_sw.c +++ b/libs/video/renderer/sw/vid_common_sw.c @@ -1,9 +1,9 @@ /* vid_common_sw.c - Common software video driver functions + general video driver functions - Copyright (C) 2001 Jeff Teunissen + Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -28,11 +28,130 @@ # include "config.h" #endif -#include -#include - +#include "QF/cvar.h" #include "QF/mathlib.h" +#include "QF/qargs.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/vid.h" +#include "compat.h" +#include "r_internal.h" #include "vid_internal.h" + +unsigned short d_8to16table[256]; + + +/* + VID_MakeColormap32 + + LordHavoc: makes a 32bit color*light table, RGBA order, no endian, + may need to be re-ordered to hardware at display time +*/ +static void +VID_MakeColormap32 (void *outcolormap, byte *pal) +{ + int c, l; + byte *out; + out = (byte *)&d_8to24table; + + /* + * Generates colors not affected by lighting, such as + * HUD pieces and general sprites (such as explosions) + */ + for (c = 0; c < 256; c++) { + *out++ = pal[c*3+2]; + *out++ = pal[c*3+1]; + *out++ = pal[c*3+0]; + *out++ = 255; + } + d_8to24table[255] = 0; // 255 is transparent + out = (byte *) outcolormap; + + /* + * Generates colors affected by lighting, such as the + * world and other models that give it life, like foes and pickups. + */ + for (l = 0;l < VID_GRADES;l++) + { + for (c = 0;c < vid.fullbright;c++) + { + out[(l*256+c)*4+0] = bound(0, (pal[c*3+2] * l) >> (VID_CBITS - 1), + 255); + out[(l*256+c)*4+1] = bound(0, (pal[c*3+1] * l) >> (VID_CBITS - 1), + 255); + out[(l*256+c)*4+2] = bound(0, (pal[c*3+0] * l) >> (VID_CBITS - 1), + 255); + out[(l*256+c)*4+3] = 255; + } + for (;c < 255;c++) + { + out[(l*256+c)*4+0] = pal[c*3+2]; + out[(l*256+c)*4+1] = pal[c*3+1]; + out[(l*256+c)*4+2] = pal[c*3+0]; + out[(l*256+c)*4+3] = 255; + } + out[(l*256+255)*4+0] = 0; + out[(l*256+255)*4+1] = 0; + out[(l*256+255)*4+2] = 0; + out[(l*256+255)*4+3] = 0; + } +} + +static unsigned short +lh24to16bit (int red, int green, int blue) +{ + red = bound(0, red, 255); + green = bound(0, green, 255); + blue = bound(0, blue, 255); + red >>= 3; + green >>= 2; + blue >>= 3; + red <<= 11; + green <<= 5; + return (unsigned short) (red | green | blue); +} + +/* + VID_MakeColormap16 + + LordHavoc: makes a 16bit color*light table, RGB order, native endian, + may need to be translated to hardware order at display time +*/ +static void +VID_MakeColormap16 (void *outcolormap, byte *pal) +{ + int c, l; + unsigned short *out; + out = (unsigned short *)&d_8to16table; + for (c = 0; c < 256; c++) + *out++ = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]); + d_8to16table[255] = 0; // 255 is transparent + out = (unsigned short *) outcolormap; + for (l = 0;l < VID_GRADES;l++) + { + for (c = 0;c < vid.fullbright;c++) + out[l*256+c] = lh24to16bit( + (pal[c*3+0] * l) >> (VID_CBITS - 1), + (pal[c*3+1] * l) >> (VID_CBITS - 1), + (pal[c*3+2] * l) >> (VID_CBITS - 1)); + for (;c < 255;c++) + out[l*256+c] = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]); + out[l*256+255] = 0; + } +} + +/* + VID_MakeColormaps + + LordHavoc: makes 8bit, 16bit, and 32bit colormaps and palettes +*/ +void +VID_MakeColormaps (void) +{ + vid.colormap16 = malloc (256*VID_GRADES * sizeof (unsigned short)); + vid.colormap32 = malloc (256*VID_GRADES * sizeof (unsigned int)); + SYS_CHECKMEM (vid.colormap16 && vid.colormap32); + VID_MakeColormap16(vid.colormap16, vid.palette); + VID_MakeColormap32(vid.colormap32, vid.palette); +} diff --git a/libs/video/renderer/sw32/d_edge.c b/libs/video/renderer/sw32/d_edge.c deleted file mode 100644 index 38ee43f63..000000000 --- a/libs/video/renderer/sw32/d_edge.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - d_edge.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/cvar.h" -#include "QF/render.h" -#include "QF/sys.h" - -#include "QF/scene/entity.h" - -#include "d_local.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - -static int miplevel; - -float sw32_scale_for_mip; - -static vec3_t transformed_modelorg; - - -void -sw32_D_DrawPoly (void) -{ -// this driver takes spans, not polygons -} - - -int -sw32_D_MipLevelForScale (float scale) -{ - int lmiplevel; - - if (scale >= sw32_d_scalemip[0]) - lmiplevel = 0; - else if (scale >= sw32_d_scalemip[1]) - lmiplevel = 1; - else if (scale >= sw32_d_scalemip[2]) - lmiplevel = 2; - else - lmiplevel = 3; - - if (lmiplevel < sw32_d_minmip) - lmiplevel = sw32_d_minmip; - - return lmiplevel; -} - -// FIXME: clean this up - -static void -D_DrawSolidSurface (surf_t *surf, int color) -{ - espan_t *span; - - switch(sw32_ctx->pixbytes) { - case 1: - { - byte *pdest, pix; - int u, u2; - - pix = color; - for (span = surf->spans; span; span = span->pnext) - { - pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * span->v; - u = span->u; - u2 = span->u + span->count - 1; - for (;u <= u2; u++) - pdest[u] = pix; - } - } - break; - case 2: - { - short *pdest, pix; - int u, u2; - - pix = sw32_8to16table[color]; - for (span = surf->spans; span; span = span->pnext) - { - pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * span->v; - u = span->u; - u2 = span->u + span->count - 1; - for (;u <= u2; u++) - pdest[u] = pix; - } - } - break; - case 4: - { - int *pdest, pix; - int u, u2; - - pix = d_8to24table[color]; - for (span = surf->spans; span; span = span->pnext) - { - pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * span->v; - u = span->u; - u2 = span->u + span->count - 1; - for (;u <= u2; u++) - pdest[u] = pix; - } - } - break; - default: - Sys_Error("D_DrawSolidSurface: unsupported r_pixbytes %i", - sw32_ctx->pixbytes); - } -} - - -static void -D_CalcGradients (msurface_t *pface) -{ - float mipscale, t; - vec3_t p_temp1, p_saxis, p_taxis; - - mipscale = 1.0 / (float) (1 << miplevel); - - sw32_TransformVector (pface->texinfo->vecs[0], p_saxis); - sw32_TransformVector (pface->texinfo->vecs[1], p_taxis); - - t = sw32_xscaleinv * mipscale; - sw32_d_sdivzstepu = p_saxis[0] * t; - sw32_d_tdivzstepu = p_taxis[0] * t; - - t = sw32_yscaleinv * mipscale; - sw32_d_sdivzstepv = -p_saxis[1] * t; - sw32_d_tdivzstepv = -p_taxis[1] * t; - - sw32_d_sdivzorigin = p_saxis[2] * mipscale - - sw32_xcenter * sw32_d_sdivzstepu - - sw32_ycenter * sw32_d_sdivzstepv; - sw32_d_tdivzorigin = p_taxis[2] * mipscale - - sw32_xcenter * sw32_d_tdivzstepu - - sw32_ycenter * sw32_d_tdivzstepv; - - VectorScale (transformed_modelorg, mipscale, p_temp1); - - t = 0x10000 * mipscale; - sw32_sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - - ((pface->texturemins[0] << 16) >> miplevel) - + pface->texinfo->vecs[0][3] * t; - sw32_tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - - ((pface->texturemins[1] << 16) >> miplevel) - + pface->texinfo->vecs[1][3] * t; - - // -1 (-epsilon) so we never wander off the edge of the texture - sw32_bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; - sw32_bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; -} - - -void -sw32_D_DrawSurfaces (void) -{ - surf_t *s; - msurface_t *pface; - surfcache_t *pcurrentcache; - vec3_t world_transformed_modelorg; - vec3_t local_modelorg; - - currententity = &r_worldentity; - sw32_TransformVector (modelorg, transformed_modelorg); - VectorCopy (transformed_modelorg, world_transformed_modelorg); - - // TODO: could preset a lot of this at mode set time - if (r_drawflat->int_val) { - for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++) { - if (!s->spans) - continue; - - d_zistepu = s->d_zistepu; - d_zistepv = s->d_zistepv; - d_ziorigin = s->d_ziorigin; - - D_DrawSolidSurface (s, ((intptr_t) s->data & 0xFF)); - sw32_D_DrawZSpans (s->spans); - } - } else { - for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++) { - if (!s->spans) - continue; - - sw32_r_drawnpolycount++; - - d_zistepu = s->d_zistepu; - d_zistepv = s->d_zistepv; - d_ziorigin = s->d_ziorigin; - - if (s->flags & SURF_DRAWSKY) { - if (!sw32_r_skymade) { - sw32_R_MakeSky (); - } - - sw32_D_DrawSkyScans (s->spans); - sw32_D_DrawZSpans (s->spans); - } else if (s->flags & SURF_DRAWBACKGROUND) { - // set up a gradient for the background surface that places - // it effectively at infinity distance from the viewpoint - d_zistepu = 0; - d_zistepv = 0; - d_ziorigin = -0.9; - - D_DrawSolidSurface (s, r_clearcolor->int_val & 0xFF); - sw32_D_DrawZSpans (s->spans); - } else if (s->flags & SURF_DRAWTURB) { - pface = s->data; - miplevel = 0; - sw32_cacheblock = ((byte *) pface->texinfo->texture + - pface->texinfo->texture->offsets[0]); - sw32_cachewidth = 64; - - if (s->insubmodel) { - // FIXME: we don't want to do all this for every polygon! - // TODO: store once at start of frame - currententity = s->entity; // FIXME: make this passed in - // to sw32_R_RotateBmodel () - VectorSubtract (r_origin, - Transform_GetWorldPosition (currententity->transform), - local_modelorg); - sw32_TransformVector (local_modelorg, transformed_modelorg); - - sw32_R_RotateBmodel (); // FIXME: don't mess with the - // frustum, make entity passed in - } - - D_CalcGradients (pface); - - sw32_Turbulent (s->spans); - sw32_D_DrawZSpans (s->spans); - - if (s->insubmodel) { - // restore the old drawing state - // FIXME: we don't want to do this every time! - // TODO: speed up - - currententity = &r_worldentity; - VectorCopy (world_transformed_modelorg, - transformed_modelorg); - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); - sw32_R_TransformFrustum (); - } - } else { - if (s->insubmodel) { - // FIXME: we don't want to do all this for every polygon! - // TODO: store once at start of frame - currententity = s->entity; // FIXME: make this passed in - // to sw32_R_RotateBmodel () - VectorSubtract (r_origin, - Transform_GetWorldPosition (currententity->transform), - local_modelorg); - sw32_TransformVector (local_modelorg, transformed_modelorg); - - sw32_R_RotateBmodel (); // FIXME: don't mess with the - // frustum, make entity passed in - } - - pface = s->data; - miplevel = sw32_D_MipLevelForScale (s->nearzi * sw32_scale_for_mip - * pface->texinfo->mipadjust); - - // FIXME: make this passed in to D_CacheSurface - pcurrentcache = sw32_D_CacheSurface (pface, miplevel); - - sw32_cacheblock = (byte *) pcurrentcache->data; - sw32_cachewidth = pcurrentcache->width; - - D_CalcGradients (pface); - - sw32_D_DrawSpans (s->spans); - - sw32_D_DrawZSpans (s->spans); - - if (s->insubmodel) { - // restore the old drawing state - // FIXME: we don't want to do this every time! - // TODO: speed up - - VectorCopy (world_transformed_modelorg, - transformed_modelorg); - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); - sw32_R_TransformFrustum (); - currententity = &r_worldentity; - } - } - } - } -} diff --git a/libs/video/renderer/sw32/d_fill.c b/libs/video/renderer/sw32/d_fill.c deleted file mode 100644 index 79cf71cfe..000000000 --- a/libs/video/renderer/sw32/d_fill.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - d_fill.c - - clears a specified rectangle to the specified color - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/sys.h" - -#include "d_iface.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - -void -sw32_D_FillRect (vrect_t *rect, int color) -{ - switch (sw32_ctx->pixbytes) - { - case 1: - { - int rx, ry, rwidth, rheight; - byte *dest, pix; - - pix = color; - - rx = rect->x; - ry = rect->y; - rwidth = rect->width; - rheight = rect->height; - - if (rx < 0) { - rwidth += rx; - rx = 0; - } - if (ry < 0) { - rheight += ry; - ry = 0; - } - if ((unsigned) (rx + rwidth) > vid.width) - rwidth = vid.width - rx; - if ((unsigned) (ry + rheight) > vid.height) - rheight = vid.height - rx; - - if (rwidth < 1 || rheight < 1) - return; - - dest = (byte *) vid.buffer + ry * vid.rowbytes + rx; - - for (ry = 0; ry < rheight; ry++) - { - for (rx = 0; rx < rwidth; rx++) - dest[rx] = pix; - dest += vid.rowbytes; - } - } - break; - case 2: - { - int rx, ry, rwidth, rheight; - unsigned short *dest, pix; - - pix = sw32_8to16table[color]; - - rx = rect->x; - ry = rect->y; - rwidth = rect->width; - rheight = rect->height; - - if (rx < 0) { - rwidth += rx; - rx = 0; - } - if (ry < 0) { - rheight += ry; - ry = 0; - } - if ((unsigned) (rx + rwidth) > vid.width) - rwidth = vid.width - rx; - if ((unsigned) (ry + rheight) > vid.height) - rheight = vid.height - rx; - - if (rwidth < 1 || rheight < 1) - return; - - dest = (unsigned short *) vid.buffer + ry * (vid.rowbytes >> 1) + - rx; - - for (ry = 0; ry < rheight; ry++) - { - for (rx = 0; rx < rwidth; rx++) - dest[rx] = pix; - dest += (vid.rowbytes >> 1); - } - } - break; - case 4: - { - int rx, ry, rwidth, rheight; - unsigned int *dest, pix; - - pix = d_8to24table[color]; - - rx = rect->x; - ry = rect->y; - rwidth = rect->width; - rheight = rect->height; - - if (rx < 0) { - rwidth += rx; - rx = 0; - } - if (ry < 0) { - rheight += ry; - ry = 0; - } - if ((unsigned) (rx + rwidth) > vid.width) - rwidth = vid.width - rx; - if ((unsigned) (ry + rheight) > vid.height) - rheight = vid.height - rx; - - if (rwidth < 1 || rheight < 1) - return; - - dest = (unsigned int *) vid.buffer + ry * (vid.rowbytes >> 2) + rx; - - for (ry = 0; ry < rheight; ry++) - { - for (rx = 0; rx < rwidth; rx++) - dest[rx] = pix; - dest += (vid.rowbytes >> 2); - } - } - break; - default: - Sys_Error("D_FillRect: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} diff --git a/libs/video/renderer/sw32/d_init.c b/libs/video/renderer/sw32/d_init.c deleted file mode 100644 index 29027a0a7..000000000 --- a/libs/video/renderer/sw32/d_init.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - d_init.c - - rasterization driver initialization - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/cvar.h" -#include "QF/render.h" - -#include "compat.h" -#include "d_local.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - -#define NUM_MIPS 4 - -surfcache_t *sw32_d_initial_rover; -qboolean sw32_d_roverwrapped; -int sw32_d_minmip; -float sw32_d_scalemip[NUM_MIPS - 1]; - -static float basemip[NUM_MIPS - 1] = { 1.0, 0.5 * 0.8, 0.25 * 0.8 }; - - -float sw32_d_zitable[65536]; - - -void -sw32_D_Init (void) -{ - sw32_r_drawpolys = false; - sw32_r_worldpolysbacktofront = false; - - // LordHavoc: compute 1/zi table for use in rendering code everywhere - if (!sw32_d_zitable[1]) { - int i; - sw32_d_zitable[0] = 0; - for (i = 1;i < 65536;i++) - sw32_d_zitable[i] = (65536.0 * 65536.0 / (double) i); - } - - vr_data.vid->vid_internal->surf_cache_size = sw32_D_SurfaceCacheForRes; - vr_data.vid->vid_internal->flush_caches = sw32_D_FlushCaches; - vr_data.vid->vid_internal->init_caches = sw32_D_InitCaches; - - VID_InitBuffers (); - VID_MakeColormaps(); -} - -void -sw32_D_TurnZOn (void) -{ - // not needed for software version -} - -void -sw32_D_SetupFrame (void) -{ - int i; - - if (sw32_r_dowarp) - sw32_d_viewbuffer = sw32_r_warpbuffer; - else - sw32_d_viewbuffer = vid.buffer; - - if (sw32_r_dowarp) - sw32_screenwidth = WARP_WIDTH; - else - sw32_screenwidth = vid.rowbytes / sw32_ctx->pixbytes; - - sw32_d_roverwrapped = false; - sw32_d_initial_rover = sw32_sc_rover; - - sw32_d_minmip = bound (0, d_mipcap->value, 3); - - for (i = 0; i < (NUM_MIPS - 1); i++) - sw32_d_scalemip[i] = basemip[i] * d_mipscale->value; -} - -void -sw32_D_UpdateRects (vrect_t *prect) -{ - // the software driver draws these directly to the vid buffer -} diff --git a/libs/video/renderer/sw32/d_modech.c b/libs/video/renderer/sw32/d_modech.c deleted file mode 100644 index 71497b5f3..000000000 --- a/libs/video/renderer/sw32/d_modech.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - d_modech.c - - called when mode has just changed - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/render.h" - -#include "d_local.h" -#include "r_internal.h" -#include "vid_sw.h" - -int sw32_d_vrectx, sw32_d_vrecty, sw32_d_vrectright_particle, sw32_d_vrectbottom_particle; - -int sw32_d_y_aspect_shift, sw32_d_pix_min, sw32_d_pix_max, sw32_d_pix_shift; - -int sw32_d_scantable[MAXHEIGHT]; -short *sw32_zspantable[MAXHEIGHT]; - - -static void -D_Patch (void) -{ -} - -void -sw32_D_ViewChanged (void) -{ - int rowpixels; - - if (sw32_r_dowarp) - rowpixels = WARP_WIDTH; - else - rowpixels = vid.rowbytes / sw32_ctx->pixbytes; - - sw32_scale_for_mip = sw32_xscale; - if (sw32_yscale > sw32_xscale) - sw32_scale_for_mip = sw32_yscale; - - sw32_d_zrowbytes = vid.width * 2; - sw32_d_zwidth = vid.width; - - sw32_d_pix_min = r_refdef.vrect.width / 320; - if (sw32_d_pix_min < 1) - sw32_d_pix_min = 1; - - sw32_d_pix_max = (int) ((float) r_refdef.vrect.width / (320.0 / 4.0) + 0.5); - sw32_d_pix_shift = 8 - (int) ((float) r_refdef.vrect.width / 320.0 + 0.5); - if (sw32_d_pix_max < 1) - sw32_d_pix_max = 1; - - if (sw32_pixelAspect > 1.4) - sw32_d_y_aspect_shift = 1; - else - sw32_d_y_aspect_shift = 0; - - sw32_d_vrectx = r_refdef.vrect.x; - sw32_d_vrecty = r_refdef.vrect.y; - sw32_d_vrectright_particle = r_refdef.vrectright - sw32_d_pix_max; - sw32_d_vrectbottom_particle = - r_refdef.vrectbottom - (sw32_d_pix_max << sw32_d_y_aspect_shift); - - { - unsigned i; - - for (i = 0; i < vid.height; i++) { - sw32_d_scantable[i] = i * rowpixels; - sw32_zspantable[i] = sw32_d_pzbuffer + i * sw32_d_zwidth; - } - } - - D_Patch (); -} diff --git a/libs/video/renderer/sw32/d_part.c b/libs/video/renderer/sw32/d_part.c deleted file mode 100644 index 8ac57af54..000000000 --- a/libs/video/renderer/sw32/d_part.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - d_part.c - - software driver module for drawing particles - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/sys.h" - -#include "d_local.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - - -void -sw32_D_DrawParticle (particle_t *pparticle) -{ - vec3_t local, transformed; - float zi; - short *pz; - int i, izi, pix, count, u, v; - - // transform point - VectorSubtract (pparticle->pos, r_origin, local); - - transformed[0] = DotProduct (local, r_pright); - transformed[1] = DotProduct (local, r_pup); - transformed[2] = DotProduct (local, r_ppn); - - if (transformed[2] < PARTICLE_Z_CLIP) - return; - - // project the point - // FIXME: preadjust sw32_xcenter and sw32_ycenter - zi = 1.0 / transformed[2]; - u = (int) (sw32_xcenter + zi * transformed[0] + 0.5); - v = (int) (sw32_ycenter - zi * transformed[1] + 0.5); - - if ((v > sw32_d_vrectbottom_particle) - || (u > sw32_d_vrectright_particle) - || (v < sw32_d_vrecty) || (u < sw32_d_vrectx)) { - return; - } - - pz = sw32_d_pzbuffer + (sw32_d_zwidth * v) + u; - izi = (int) (zi * 0x8000); - - pix = izi >> sw32_d_pix_shift; - - if (pix < sw32_d_pix_min) - pix = sw32_d_pix_min; - else if (pix > sw32_d_pix_max) - pix = sw32_d_pix_max; - - switch(sw32_ctx->pixbytes) - { - case 1: - { - byte *pdest = (byte *) sw32_d_viewbuffer + sw32_d_scantable[v] + u, - pixcolor = pparticle->icolor; - switch (pix) { - case 1: - count = 1 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - } - break; - case 2: - count = 2 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - } - break; - case 3: - count = 3 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - } - break; - case 4: - count = 4 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - - if (pz[3] <= izi) { - pz[3] = izi; - pdest[3] = pixcolor; - } - } - break; - default: - count = pix << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - for (i = 0; i < pix; i++) { - if (pz[i] <= izi) { - pz[i] = izi; - pdest[i] = pixcolor; - } - } - } - break; - } - } - break; - case 2: - { - unsigned short *pdest = (unsigned short *) sw32_d_viewbuffer + - sw32_d_scantable[v] + u, - pixcolor = sw32_8to16table[(int) pparticle->icolor]; - switch (pix) { - case 1: - count = 1 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - } - break; - case 2: - count = 2 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - } - break; - case 3: - count = 3 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - } - break; - case 4: - count = 4 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - - if (pz[3] <= izi) { - pz[3] = izi; - pdest[3] = pixcolor; - } - } - break; - default: - count = pix << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - for (i = 0; i < pix; i++) { - if (pz[i] <= izi) { - pz[i] = izi; - pdest[i] = pixcolor; - } - } - } - break; - } - } - break; - case 4: - { - int *pdest = (int *) sw32_d_viewbuffer + sw32_d_scantable[v] + u, - pixcolor = d_8to24table[(int) pparticle->icolor]; - switch (pix) { - case 1: - count = 1 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - } - break; - case 2: - count = 2 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - } - break; - case 3: - count = 3 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - } - break; - case 4: - count = 4 << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - - if (pz[3] <= izi) { - pz[3] = izi; - pdest[3] = pixcolor; - } - } - break; - default: - count = pix << sw32_d_y_aspect_shift; - - for (; count; count--, pz += sw32_d_zwidth, - pdest += sw32_screenwidth) { - for (i = 0; i < pix; i++) { - if (pz[i] <= izi) { - pz[i] = izi; - pdest[i] = pixcolor; - } - } - } - break; - } - } - break; - default: - Sys_Error("D_DrawParticles: unsupported r_pixbytes %i", - sw32_ctx->pixbytes); - } -} diff --git a/libs/video/renderer/sw32/d_polyse.c b/libs/video/renderer/sw32/d_polyse.c deleted file mode 100644 index 88fe6e13f..000000000 --- a/libs/video/renderer/sw32/d_polyse.c +++ /dev/null @@ -1,797 +0,0 @@ -/* - d_polyse.c - - routines for drawing sets of polygons sharing the same texture - (used for Alias models) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/sys.h" - -#include "d_local.h" -#include "r_internal.h" -#include "vid_sw.h" - -static int ubasestep, errorterm, erroradjustup, erroradjustdown; - -// TODO: put in span spilling to shrink list size -// !!! if this is changed, it must be changed in d_polysa.s too !!! -#define DPS_MAXSPANS MAXHEIGHT+1 // +1 for spanpackage marking end - -// !!! if this is changed, it must be changed in asm_draw.h too !!! -typedef struct { - int pdest; - short *pz; - int count; - byte *ptex; - int sfrac, tfrac, light, zi; -} spanpackage_t; - -typedef struct { - int isflattop; - int numleftedges; - int *pleftedgevert0; - int *pleftedgevert1; - int *pleftedgevert2; - int numrightedges; - int *prightedgevert0; - int *prightedgevert1; - int *prightedgevert2; -} edgetable; - -static int r_p0[6], r_p1[6], r_p2[6]; - -static int d_xdenom; - -static edgetable *pedgetable; - -static edgetable edgetables[12] = { - {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2}, - {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL}, - {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL}, - {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0}, - {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL}, - {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL}, - {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1}, - {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL}, - {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL}, - {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL}, - {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL}, - {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL}, -}; - -static int r_sstepx, r_tstepx, r_lstepx, r_lstepy, r_sstepy, r_tstepy; -static int r_zistepx, r_zistepy; -static int d_aspancount, d_countextrastep; - -static spanpackage_t *a_spans; -static spanpackage_t *d_pedgespanpackage; -static int ystart; -static int d_pdest; -static byte *d_ptex; -static short *d_pz; -static int d_sfrac, d_tfrac, d_light, d_zi; -static int d_ptexextrastep, d_sfracextrastep; -static int d_tfracextrastep, d_lightextrastep, d_pdestextrastep; -static int d_lightbasestep, d_pdestbasestep, d_ptexbasestep; -static int d_sfracbasestep, d_tfracbasestep; -static int d_ziextrastep, d_zibasestep; -static int d_pzextrastep, d_pzbasestep; - -typedef struct { - int quotient; - int remainder; -} adivtab_t; - -static adivtab_t adivtab[32 * 32] = { -#include "adivtab.h" -}; - - -void -sw32_D_PolysetSetEdgeTable (void) -{ - int edgetableindex; - - // assume the vertices are already in top to bottom order - edgetableindex = 0; - - // determine which edges are right & left, and the order in which - // to rasterize them - if (r_p0[1] >= r_p1[1]) { - if (r_p0[1] == r_p1[1]) { - if (r_p0[1] < r_p2[1]) - pedgetable = &edgetables[2]; - else - pedgetable = &edgetables[5]; - - return; - } else { - edgetableindex = 1; - } - } - - if (r_p0[1] == r_p2[1]) { - if (edgetableindex) - pedgetable = &edgetables[8]; - else - pedgetable = &edgetables[9]; - - return; - } else if (r_p1[1] == r_p2[1]) { - if (edgetableindex) - pedgetable = &edgetables[10]; - else - pedgetable = &edgetables[11]; - - return; - } - - if (r_p0[1] > r_p2[1]) - edgetableindex += 2; - - if (r_p1[1] > r_p2[1]) - edgetableindex += 4; - - pedgetable = &edgetables[edgetableindex]; -} - -static void -D_DrawNonSubdiv (void) -{ - mtriangle_t *ptri; - finalvert_t *pfv, *index0, *index1, *index2; - int i; - int lnumtriangles; - - pfv = sw32_r_affinetridesc.pfinalverts; - ptri = sw32_r_affinetridesc.ptriangles; - lnumtriangles = sw32_r_affinetridesc.numtriangles; - - for (i = 0; i < lnumtriangles; i++, ptri++) { - index0 = pfv + ptri->vertindex[0]; - index1 = pfv + ptri->vertindex[1]; - index2 = pfv + ptri->vertindex[2]; - - d_xdenom = - (index0->v[1] - index1->v[1]) * (index0->v[0] - index2->v[0]) - - (index0->v[0] - index1->v[0]) * (index0->v[1] - index2->v[1]); - - if (d_xdenom >= 0) - continue; - - r_p0[0] = index0->v[0]; // u - r_p0[1] = index0->v[1]; // v - r_p0[2] = index0->v[2]; // s - r_p0[3] = index0->v[3]; // t - r_p0[4] = index0->v[4]; // light - r_p0[5] = index0->v[5]; // iz - - r_p1[0] = index1->v[0]; - r_p1[1] = index1->v[1]; - r_p1[2] = index1->v[2]; - r_p1[3] = index1->v[3]; - r_p1[4] = index1->v[4]; - r_p1[5] = index1->v[5]; - - r_p2[0] = index2->v[0]; - r_p2[1] = index2->v[1]; - r_p2[2] = index2->v[2]; - r_p2[3] = index2->v[3]; - r_p2[4] = index2->v[4]; - r_p2[5] = index2->v[5]; - - if (!ptri->facesfront) { - if (index0->flags & ALIAS_ONSEAM) - r_p0[2] += sw32_r_affinetridesc.seamfixupX16; - if (index1->flags & ALIAS_ONSEAM) - r_p1[2] += sw32_r_affinetridesc.seamfixupX16; - if (index2->flags & ALIAS_ONSEAM) - r_p2[2] += sw32_r_affinetridesc.seamfixupX16; - } - - sw32_D_PolysetSetEdgeTable (); - sw32_D_RasterizeAliasPolySmooth (); - } -} - -void -sw32_D_PolysetDraw (void) -{ - spanpackage_t spans[DPS_MAXSPANS + 1 + - ((CACHE_SIZE - 1) / sizeof (spanpackage_t)) + 1]; - - // one extra because of cache line pretouching - - a_spans = (spanpackage_t *) - (((intptr_t) &spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - - D_DrawNonSubdiv (); -} - -void -sw32_D_PolysetScanLeftEdge (int height) -{ - - do { - d_pedgespanpackage->pdest = d_pdest; - d_pedgespanpackage->pz = d_pz; - d_pedgespanpackage->count = d_aspancount; - d_pedgespanpackage->ptex = d_ptex; - - d_pedgespanpackage->sfrac = d_sfrac; - d_pedgespanpackage->tfrac = d_tfrac; - - // FIXME: need to clamp l, s, t, at both ends? - d_pedgespanpackage->light = d_light; - d_pedgespanpackage->zi = d_zi; - - d_pedgespanpackage++; - - errorterm += erroradjustup; - if (errorterm >= 0) { - d_pdest += d_pdestextrastep; - d_pz += d_pzextrastep; - d_aspancount += d_countextrastep; - d_ptex += d_ptexextrastep; - d_sfrac += d_sfracextrastep; - d_ptex += d_sfrac >> 16; - - d_sfrac &= 0xFFFF; - d_tfrac += d_tfracextrastep; - if (d_tfrac & 0x10000) { - d_ptex += sw32_r_affinetridesc.skinwidth; - d_tfrac &= 0xFFFF; - } - d_light += d_lightextrastep; - d_zi += d_ziextrastep; - errorterm -= erroradjustdown; - } else { - d_pdest += d_pdestbasestep; - d_pz += d_pzbasestep; - d_aspancount += ubasestep; - d_ptex += d_ptexbasestep; - d_sfrac += d_sfracbasestep; - d_ptex += d_sfrac >> 16; - d_sfrac &= 0xFFFF; - d_tfrac += d_tfracbasestep; - if (d_tfrac & 0x10000) { - d_ptex += sw32_r_affinetridesc.skinwidth; - d_tfrac &= 0xFFFF; - } - d_light += d_lightbasestep; - d_zi += d_zibasestep; - } - } while (--height); -} - -static void -D_PolysetSetUpForLineScan (fixed8_t startvertu, fixed8_t startvertv, - fixed8_t endvertu, fixed8_t endvertv) -{ - double dm, dn; - int tm, tn; - adivtab_t *ptemp; - - // TODO: implement x86 version - - errorterm = -1; - - tm = endvertu - startvertu; - tn = endvertv - startvertv; - - if (((tm <= 16) && (tm >= -15)) && ((tn <= 16) && (tn >= -15))) { - ptemp = &adivtab[((tm + 15) << 5) + (tn + 15)]; - ubasestep = ptemp->quotient; - erroradjustup = ptemp->remainder; - erroradjustdown = tn; - } else { - dm = (double) tm; - dn = (double) tn; - - FloorDivMod (dm, dn, &ubasestep, &erroradjustup); - - erroradjustdown = dn; - } -} - -void -sw32_D_PolysetCalcGradients (int skinwidth) -{ - float xstepdenominv, ystepdenominv, t0, t1; - float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; - - p00_minus_p20 = r_p0[0] - r_p2[0]; - p01_minus_p21 = r_p0[1] - r_p2[1]; - p10_minus_p20 = r_p1[0] - r_p2[0]; - p11_minus_p21 = r_p1[1] - r_p2[1]; - - xstepdenominv = 1.0 / (float) d_xdenom; - - ystepdenominv = -xstepdenominv; - - // ceil () for light so positive steps are exaggerated, negative steps - // diminished, pushing us away from underflow toward overflow. Underflow - // is very visible, overflow is very unlikely, because of ambient lighting - t0 = r_p0[4] - r_p2[4]; - t1 = r_p1[4] - r_p2[4]; - r_lstepx = (int) - ceil ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); - r_lstepy = (int) - ceil ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); - - t0 = r_p0[2] - r_p2[2]; - t1 = r_p1[2] - r_p2[2]; - r_sstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * - xstepdenominv); - r_sstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * - ystepdenominv); - - t0 = r_p0[3] - r_p2[3]; - t1 = r_p1[3] - r_p2[3]; - r_tstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * - xstepdenominv); - r_tstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * - ystepdenominv); - - t0 = r_p0[5] - r_p2[5]; - t1 = r_p1[5] - r_p2[5]; - r_zistepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * - xstepdenominv); - r_zistepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * - ystepdenominv); - -// a_sstepxfrac = r_sstepx & 0xFFFF; -// a_tstepxfrac = r_tstepx & 0xFFFF; - -// a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); -} - - -static void -D_PolysetDrawSpans (spanpackage_t * pspanpackage) -{ - int i, j, texscantable[2*MAX_LBM_HEIGHT], *texscan; - // LordHavoc: compute skin row table - for (i = 0, j = -sw32_r_affinetridesc.skinheight * sw32_r_affinetridesc.skinwidth; - i < sw32_r_affinetridesc.skinheight*2;i++, j += sw32_r_affinetridesc.skinwidth) - texscantable[i] = j; - texscan = texscantable + sw32_r_affinetridesc.skinheight; - - switch(sw32_ctx->pixbytes) { - case 1: - { - int lcount, count = 0; - byte *lpdest; - byte *lptex; - int lsfrac, ltfrac; - int llight; - int lzi; - short *lpz; - - do - { - lcount = d_aspancount - pspanpackage->count; - - errorterm += erroradjustup; - if (errorterm >= 0) - { - d_aspancount += d_countextrastep; - errorterm -= erroradjustdown; - } - else - d_aspancount += ubasestep; - - if (lcount) - { - lpdest = (byte *) sw32_d_viewbuffer + pspanpackage->pdest; - lptex = pspanpackage->ptex; - lpz = pspanpackage->pz; - lsfrac = pspanpackage->sfrac; - ltfrac = pspanpackage->tfrac; - llight = pspanpackage->light; - lzi = pspanpackage->zi; - - // LordHavoc: optimized zbuffer check (switchs between - // loops when state changes, and quickly skips groups - // of hidden pixels) - do - { - if ((lzi >> 16) < *lpz) // hidden - { - count = 0; - goto skiploop8; - } -drawloop8: - *lpz++ = lzi >> 16; - *lpdest++ = ((byte *)sw32_acolormap) - [(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] + - (lsfrac >> 16)]]; - lzi += r_zistepx; - lsfrac += r_sstepx; - ltfrac += r_tstepx; - llight += r_lstepx; - } - while (--lcount); - goto done8; - - do - { - if ((lzi >> 16) >= *lpz) // draw - { - lsfrac += r_sstepx * count; - ltfrac += r_tstepx * count; - llight += r_lstepx * count; - lpdest += count; - goto drawloop8; - } -skiploop8: - count++; - lzi += r_zistepx; - lpz++; - } - while (--lcount); -done8: ; - } - - pspanpackage++; - } - while (pspanpackage->count != -999999); - } - break; - - case 2: - { - int lcount, count = 0; - short *lpdest; - byte *lptex; - int lsfrac, ltfrac; - int llight; - int lzi; - short *lpz; - - do - { - lcount = d_aspancount - pspanpackage->count; - - errorterm += erroradjustup; - if (errorterm >= 0) - { - d_aspancount += d_countextrastep; - errorterm -= erroradjustdown; - } - else - d_aspancount += ubasestep; - - if (lcount) - { - lpdest = (short *) sw32_d_viewbuffer + pspanpackage->pdest; - lptex = pspanpackage->ptex; - lpz = pspanpackage->pz; - lsfrac = pspanpackage->sfrac; - ltfrac = pspanpackage->tfrac; - llight = pspanpackage->light; - lzi = pspanpackage->zi; - - do - { - if ((lzi >> 16) < *lpz) // hidden - { - count = 0; - goto skiploop16; - } -drawloop16: - *lpz++ = lzi >> 16; - *lpdest++ = ((short *)sw32_acolormap)[(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] + (lsfrac >> 16)]]; - lzi += r_zistepx; - lsfrac += r_sstepx; - ltfrac += r_tstepx; - llight += r_lstepx; - } - while (--lcount); - goto done16; - - do - { - if ((lzi >> 16) >= *lpz) // draw - { - lsfrac += r_sstepx * count; - ltfrac += r_tstepx * count; - llight += r_lstepx * count; - lpdest += count; - goto drawloop16; - } -skiploop16: - count++; - lzi += r_zistepx; - lpz++; - } - while (--lcount); -done16: ; - } - - pspanpackage++; - } - while (pspanpackage->count != -999999); - } - break; - - case 4: - { - int lcount, count = 0; - int *lpdest; - byte *lptex; - int lsfrac, ltfrac; - int llight; - int lzi; - short *lpz; - - do - { - lcount = d_aspancount - pspanpackage->count; - - errorterm += erroradjustup; - if (errorterm >= 0) - { - d_aspancount += d_countextrastep; - errorterm -= erroradjustdown; - } - else - d_aspancount += ubasestep; - - if (lcount) - { - lpdest = (int *) sw32_d_viewbuffer + pspanpackage->pdest; - lptex = pspanpackage->ptex; - lpz = pspanpackage->pz; - lsfrac = pspanpackage->sfrac; - ltfrac = pspanpackage->tfrac; - llight = pspanpackage->light; - lzi = pspanpackage->zi; - - do - { - if ((lzi >> 16) < *lpz) // hidden - { - count = 0; - goto skiploop32; - } -drawloop32: - *lpz++ = lzi >> 16; - *lpdest++ = - vid.colormap32[(llight & 0xFF00) | - lptex[texscan[ltfrac >> 16] + - (lsfrac >> 16)]]; - lzi += r_zistepx; - lsfrac += r_sstepx; - ltfrac += r_tstepx; - llight += r_lstepx; - } - while (--lcount); - goto done32; - - do - { - if ((lzi >> 16) >= *lpz) // draw - { - lsfrac += r_sstepx * count; - ltfrac += r_tstepx * count; - llight += r_lstepx * count; - lpdest += count; - goto drawloop32; - } -skiploop32: - count++; - lzi += r_zistepx; - lpz++; - } - while (--lcount); -done32: ; - } - - pspanpackage++; - } - while (pspanpackage->count != -999999); - } - break; - - default: - Sys_Error("D_PolysetDrawSpans: unsupported r_pixbytes %i", - sw32_ctx->pixbytes); - } -} - - -void -sw32_D_RasterizeAliasPolySmooth (void) -{ - int initialleftheight, initialrightheight; - int *plefttop, *prighttop, *pleftbottom, *prightbottom; - int working_lstepx, originalcount; - - plefttop = pedgetable->pleftedgevert0; - prighttop = pedgetable->prightedgevert0; - - pleftbottom = pedgetable->pleftedgevert1; - prightbottom = pedgetable->prightedgevert1; - - initialleftheight = pleftbottom[1] - plefttop[1]; - initialrightheight = prightbottom[1] - prighttop[1]; - - // set the s, t, and light gradients, which are consistent across the - // triangle, because being a triangle, things are affine - sw32_D_PolysetCalcGradients (sw32_r_affinetridesc.skinwidth); - -// rasterize the polygon - - // scan out the top (and possibly only) part of the left edge - D_PolysetSetUpForLineScan (plefttop[0], plefttop[1], - pleftbottom[0], pleftbottom[1]); - - d_pedgespanpackage = a_spans; - - ystart = plefttop[1]; - d_aspancount = plefttop[0] - prighttop[0]; - - d_ptex = (byte *) sw32_r_affinetridesc.pskin + (plefttop[2] >> 16) + - (plefttop[3] >> 16) * sw32_r_affinetridesc.skinwidth; - d_sfrac = plefttop[2] & 0xFFFF; - d_tfrac = plefttop[3] & 0xFFFF; - d_pzbasestep = sw32_d_zwidth + ubasestep; - d_pzextrastep = d_pzbasestep + 1; - d_light = plefttop[4]; - d_zi = plefttop[5]; - - d_pdestbasestep = sw32_screenwidth + ubasestep; - d_pdestextrastep = d_pdestbasestep + 1; - // LordHavoc: d_pdest has been changed to pixel offset - d_pdest = ystart * sw32_screenwidth + plefttop[0]; - d_pz = sw32_d_pzbuffer + ystart * sw32_d_zwidth + plefttop[0]; - -// TODO: can reuse partial expressions here - - // for negative steps in x along left edge, bias toward overflow rather - // than underflow (sort of turning the floor () we did in the gradient - // calcs into ceil (), but plus a little bit) - if (ubasestep < 0) - working_lstepx = r_lstepx - 1; - else - working_lstepx = r_lstepx; - - d_countextrastep = ubasestep + 1; - d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + - ((r_tstepy + r_tstepx * ubasestep) >> 16) * sw32_r_affinetridesc.skinwidth; - d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; - d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; - d_lightbasestep = r_lstepy + working_lstepx * ubasestep; - d_zibasestep = r_zistepy + r_zistepx * ubasestep; - - d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + - ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * - sw32_r_affinetridesc.skinwidth; - d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF; - d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF; - d_lightextrastep = d_lightbasestep + working_lstepx; - d_ziextrastep = d_zibasestep + r_zistepx; - - sw32_D_PolysetScanLeftEdge (initialleftheight); - - // scan out the bottom part of the left edge, if it exists - if (pedgetable->numleftedges == 2) { - int height; - - plefttop = pleftbottom; - pleftbottom = pedgetable->pleftedgevert2; - - D_PolysetSetUpForLineScan (plefttop[0], plefttop[1], - pleftbottom[0], pleftbottom[1]); - - height = pleftbottom[1] - plefttop[1]; - -// TODO: make this a function; modularize this function in general - - ystart = plefttop[1]; - d_aspancount = plefttop[0] - prighttop[0]; - d_ptex = (byte *) sw32_r_affinetridesc.pskin + (plefttop[2] >> 16) + - (plefttop[3] >> 16) * sw32_r_affinetridesc.skinwidth; - d_sfrac = 0; - d_tfrac = 0; - d_light = plefttop[4]; - d_zi = plefttop[5]; - - d_pdestbasestep = sw32_screenwidth + ubasestep; - d_pdestextrastep = d_pdestbasestep + 1; - // LordHavoc: d_pdest and relatives have been changed to pixel - // offsets into framebuffer - d_pdest = ystart * sw32_screenwidth + plefttop[0]; - d_pzbasestep = sw32_d_zwidth + ubasestep; - d_pzextrastep = d_pzbasestep + 1; - d_pz = sw32_d_pzbuffer + ystart * sw32_d_zwidth + plefttop[0]; - - if (ubasestep < 0) - working_lstepx = r_lstepx - 1; - else - working_lstepx = r_lstepx; - - d_countextrastep = ubasestep + 1; - d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + - ((r_tstepy + r_tstepx * ubasestep) >> 16) * - sw32_r_affinetridesc.skinwidth; - d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; - d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; - d_lightbasestep = r_lstepy + working_lstepx * ubasestep; - d_zibasestep = r_zistepy + r_zistepx * ubasestep; - - d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + - ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * - sw32_r_affinetridesc.skinwidth; - d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF; - d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF; - d_lightextrastep = d_lightbasestep + working_lstepx; - d_ziextrastep = d_zibasestep + r_zistepx; - - sw32_D_PolysetScanLeftEdge (height); - } - // scan out the top (and possibly only) part of the right edge, updating - // the count field - d_pedgespanpackage = a_spans; - - D_PolysetSetUpForLineScan (prighttop[0], prighttop[1], - prightbottom[0], prightbottom[1]); - d_aspancount = 0; - d_countextrastep = ubasestep + 1; - originalcount = a_spans[initialrightheight].count; - a_spans[initialrightheight].count = -999999; // mark end of the - // spanpackages - D_PolysetDrawSpans (a_spans); - - // scan out the bottom part of the right edge, if it exists - if (pedgetable->numrightedges == 2) { - int height; - spanpackage_t *pstart; - - pstart = a_spans + initialrightheight; - pstart->count = originalcount; - - d_aspancount = prightbottom[0] - prighttop[0]; - - prighttop = prightbottom; - prightbottom = pedgetable->prightedgevert2; - - height = prightbottom[1] - prighttop[1]; - - D_PolysetSetUpForLineScan (prighttop[0], prighttop[1], - prightbottom[0], prightbottom[1]); - - d_countextrastep = ubasestep + 1; - a_spans[initialrightheight + height].count = -999999; - // mark end of the spanpackages - D_PolysetDrawSpans (pstart); - } -} diff --git a/libs/video/renderer/sw32/d_scan.c b/libs/video/renderer/sw32/d_scan.c deleted file mode 100644 index 50ef352da..000000000 --- a/libs/video/renderer/sw32/d_scan.c +++ /dev/null @@ -1,883 +0,0 @@ -/* - d_scan.c - - Portable C scan-level rasterization code, all pixel depths. - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/qendian.h" -#include "QF/render.h" -#include "QF/sys.h" -#include "QF/ui/view.h" - -#include "compat.h" -#include "d_local.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - -static byte *r_turb_pbase; -static void *r_turb_pdest; -static fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; -static int *r_turb_turb; -static int r_turb_spancount; - -/* - D_WarpScreen - - this performs a slight compression of the screen at the same time as - the sine warp, to keep the edges from wrapping -*/ -void -sw32_D_WarpScreen (void) -{ - switch(sw32_ctx->pixbytes) { - case 1: - { - int w, h; - int u, v; - int scr_x = vr_data.scr_view->xpos; - int scr_y = vr_data.scr_view->ylen; - int scr_w = vr_data.scr_view->xpos; - int scr_h = vr_data.scr_view->ylen; - byte *dest; - int *turb; - int *col; - byte **row; - byte *rowptr[MAXHEIGHT]; - int column[MAXWIDTH]; - float wratio, hratio; - - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - - wratio = w / (float) scr_w; - hratio = h / (float) scr_h; - - for (v = 0; v < scr_h + AMP2 * 2; v++) { - rowptr[v] = (byte *) sw32_d_viewbuffer + (r_refdef.vrect.y * - sw32_screenwidth) + - (sw32_screenwidth * (int) ((float) v * hratio * h / - (h + AMP2 * 2))); - } - - for (u = 0; u < scr_w + AMP2 * 2; u++) { - column[u] = r_refdef.vrect.x + - (int) ((float) u * wratio * w / (w + AMP2 * 2)); - } - - turb = sw32_intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = (byte *)vid.buffer + scr_y * vid.rowbytes + scr_x; - - for (v = 0; v < scr_h; v++, dest += vid.rowbytes) { - col = &column[turb[v]]; - row = &rowptr[v]; - for (u = 0; u < scr_w; u += 4) { - dest[u + 0] = row[turb[u + 0]][col[u + 0]]; - dest[u + 1] = row[turb[u + 1]][col[u + 1]]; - dest[u + 2] = row[turb[u + 2]][col[u + 2]]; - dest[u + 3] = row[turb[u + 3]][col[u + 3]]; - } - } - } - break; - case 2: - { - int w, h; - int u, v; - int scr_x = vr_data.scr_view->xpos; - int scr_y = vr_data.scr_view->ylen; - int scr_w = vr_data.scr_view->xpos; - int scr_h = vr_data.scr_view->ylen; - short *dest; - int *turb; - int *col; - short **row; - short *rowptr[MAXHEIGHT]; - int column[MAXWIDTH]; - float wratio, hratio; - - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - - wratio = w / (float) scr_w; - hratio = h / (float) scr_h; - - for (v = 0; v < scr_h + AMP2 * 2; v++) { - rowptr[v] = (short *) sw32_d_viewbuffer + - (r_refdef.vrect.y * sw32_screenwidth) + - (sw32_screenwidth * (int) ((float) v * hratio * h / - (h + AMP2 * 2))); - } - - for (u = 0; u < scr_w + AMP2 * 2; u++) { - column[u] = r_refdef.vrect.x + - (int) ((float) u * wratio * w / (w + AMP2 * 2)); - } - - turb = sw32_intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = (short *) vid.buffer + scr_y * (vid.rowbytes >> 1) + scr_x; - - for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 1)) { - col = &column[turb[v]]; - row = &rowptr[v]; - for (u = 0; u < scr_w; u += 4) { - dest[u + 0] = row[turb[u + 0]][col[u + 0]]; - dest[u + 1] = row[turb[u + 1]][col[u + 1]]; - dest[u + 2] = row[turb[u + 2]][col[u + 2]]; - dest[u + 3] = row[turb[u + 3]][col[u + 3]]; - } - } - } - break; - case 4: - { - int w, h; - int u, v; - int scr_x = vr_data.scr_view->xpos; - int scr_y = vr_data.scr_view->ylen; - int scr_w = vr_data.scr_view->xpos; - int scr_h = vr_data.scr_view->ylen; - int *dest; - int *turb; - int *col; - int **row; - int *rowptr[MAXHEIGHT]; - int column[MAXWIDTH]; - float wratio, hratio; - - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - - wratio = w / (float) scr_w; - hratio = h / (float) scr_h; - - for (v = 0; v < scr_h + AMP2 * 2; v++) { - rowptr[v] = (int *) sw32_d_viewbuffer + - (r_refdef.vrect.y * sw32_screenwidth) + - (sw32_screenwidth * (int) ((float) v * hratio * h / - (h + AMP2 * 2))); - } - - for (u = 0; u < scr_w + AMP2 * 2; u++) { - column[u] = r_refdef.vrect.x + - (int) ((float) u * wratio * w / (w + AMP2 * 2)); - } - - turb = sw32_intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = (int *) vid.buffer + scr_y * (vid.rowbytes >> 2) + scr_x; - - for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 2)) { - col = &column[turb[v]]; - row = &rowptr[v]; - for (u = 0; u < scr_w; u += 4) { - dest[u + 0] = row[turb[u + 0]][col[u + 0]]; - dest[u + 1] = row[turb[u + 1]][col[u + 1]]; - dest[u + 2] = row[turb[u + 2]][col[u + 2]]; - dest[u + 3] = row[turb[u + 3]][col[u + 3]]; - } - } - } - break; - default: - Sys_Error("D_WarpScreen: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} - -static void -D_DrawTurbulentSpan (void) -{ - int sturb, tturb; - - switch (sw32_ctx->pixbytes) { - case 1: - { - byte *pdest = (byte *) r_turb_pdest; - do { - sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & - (CYCLE - 1)]) >> 16) & 63; - tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & - (CYCLE - 1)]) >> 16) & 63; - *pdest++ = r_turb_pbase[(tturb << 6) + sturb]; - r_turb_s += r_turb_sstep; - r_turb_t += r_turb_tstep; - } while (--r_turb_spancount > 0); - r_turb_pdest = (byte *)pdest; - } - break; - case 2: - { - short *pdest = (short *) r_turb_pdest; - do { - sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & - (CYCLE - 1)]) >> 16) & 63; - tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & - (CYCLE - 1)]) >> 16) & 63; - *pdest++ = sw32_8to16table[r_turb_pbase[(tturb << 6) + sturb]]; - r_turb_s += r_turb_sstep; - r_turb_t += r_turb_tstep; - } while (--r_turb_spancount > 0); - r_turb_pdest = (byte *)pdest; - } - break; - case 4: - { - int *pdest = (int *) r_turb_pdest; - do { - sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & - (CYCLE - 1)]) >> 16) & 63; - tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & - (CYCLE - 1)]) >> 16) & 63; - *pdest++ = d_8to24table[r_turb_pbase[(tturb << 6) + sturb]]; - r_turb_s += r_turb_sstep; - r_turb_t += r_turb_tstep; - } while (--r_turb_spancount > 0); - r_turb_pdest = (byte *)pdest; - } - break; - default: - Sys_Error("D_DrawTurbulentSpan: unsupported r_pixbytes %i", - sw32_ctx->pixbytes); - } -} - -void -sw32_Turbulent (espan_t *pspan) -{ - int count; - fixed16_t snext, tnext; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivz16stepu, tdivz16stepu, zi16stepu; - - r_turb_turb = sw32_sintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - - r_turb_sstep = 0; // keep compiler happy - r_turb_tstep = 0; // ditto - - r_turb_pbase = (byte *) sw32_cacheblock; - - sdivz16stepu = sw32_d_sdivzstepu * 16; - tdivz16stepu = sw32_d_tdivzstepu * 16; - zi16stepu = d_zistepu * 16 * 65536; - - do { - r_turb_pdest = (byte *) sw32_d_viewbuffer + ((sw32_screenwidth * pspan->v) + - pspan->u) * sw32_ctx->pixbytes; - - count = pspan->count; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu; - tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = sw32_d_zitable[(unsigned short) zi]; - - r_turb_s = (int) (sdivz * z) + sw32_sadjust; - if (r_turb_s > sw32_bbextents) - r_turb_s = sw32_bbextents; - else if (r_turb_s < 0) - r_turb_s = 0; - - r_turb_t = (int) (tdivz * z) + sw32_tadjust; - if (r_turb_t > sw32_bbextentt) - r_turb_t = sw32_bbextentt; - else if (r_turb_t < 0) - r_turb_t = 0; - - do { - // calculate s and t at the far end of the span - if (count >= 16) - r_turb_spancount = 16; - else - r_turb_spancount = count; - - count -= r_turb_spancount; - - if (count) { - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivz16stepu; - tdivz += tdivz16stepu; - zi += zi16stepu; - z = sw32_d_zitable[(unsigned short) zi]; - - snext = (int) (sdivz * z) + sw32_sadjust; - if (snext > sw32_bbextents) - snext = sw32_bbextents; - else if (snext < 16) - snext = 16; // prevent round-off error on <0 - // steps from - // from causing overstepping & running off the - // edge of the texture - - tnext = (int) (tdivz * z) + sw32_tadjust; - if (tnext > sw32_bbextentt) - tnext = sw32_bbextentt; - else if (tnext < 16) - tnext = 16; // guard against round-off error on - // <0 steps - - r_turb_sstep = (snext - r_turb_s) >> 4; - r_turb_tstep = (tnext - r_turb_t) >> 4; - } else { - // calculate s/z, t/z, zi->fixed s and t at last pixel in - // span (so can't step off polygon), clamp, calculate s and t - // steps across span by division, biasing steps low so we - // don't run off the texture - spancountminus1 = (float) (r_turb_spancount - 1); - sdivz += sw32_d_sdivzstepu * spancountminus1; - tdivz += sw32_d_tdivzstepu * spancountminus1; - zi += d_zistepu * 65536.0f * spancountminus1; - z = sw32_d_zitable[(unsigned short) zi]; - snext = (int) (sdivz * z) + sw32_sadjust; - if (snext > sw32_bbextents) - snext = sw32_bbextents; - else if (snext < 16) - snext = 16; // prevent round-off error on <0 steps - // from causing overstepping & running - // off the edge of the texture - - tnext = (int) (tdivz * z) + sw32_tadjust; - if (tnext > sw32_bbextentt) - tnext = sw32_bbextentt; - else if (tnext < 16) - tnext = 16; // guard against round-off error on - // <0 steps - - if (r_turb_spancount > 1) { - r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); - r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); - } - } - - r_turb_s = r_turb_s & ((CYCLE << 16) - 1); - r_turb_t = r_turb_t & ((CYCLE << 16) - 1); - - D_DrawTurbulentSpan (); - - r_turb_s = snext; - r_turb_t = tnext; - - } while (count > 0); - - } while ((pspan = pspan->pnext) != NULL); -} - -void -sw32_D_DrawSpans (espan_t *pspan) -{ - switch(sw32_ctx->pixbytes) { - case 1: - { - byte *pbase = (byte *) sw32_cacheblock, *pdest; - int count; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv; - float sdivz8stepu, tdivz8stepu, zi8stepu; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - sdivz8stepu = sw32_d_sdivzstepu * 8; - tdivz8stepu = sw32_d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536; - - do { - pdest = (byte *) sw32_d_viewbuffer + (sw32_screenwidth * pspan->v) + - pspan->u; - - count = pspan->count; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu; - tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = sw32_d_zitable[(unsigned short) zi]; - - s = (int) (sdivz * z) + sw32_sadjust; - s = bound(0, s, sw32_bbextents); - t = (int) (tdivz * z) + sw32_tadjust; - t = bound(0, t, sw32_bbextentt); - - while(count >= 8) { - count -= 8; - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = sw32_d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sw32_sadjust; - snext = bound(8, snext, sw32_bbextents); - tnext = (int) (tdivz * z) + sw32_tadjust; - tnext = bound(8, tnext, sw32_bbextentt); - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep;t += tstep; - pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[4] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[5] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[6] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[7] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s = snext; - t = tnext; - pdest += 8; - } - if (count) - { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span - // (so can't step off polygon), clamp, calculate s and t steps - // across span by division, biasing steps low so we don't run - // off the texture - //countminus1 = (float) (count - 1); - sdivz += sw32_d_sdivzstepu * count; //minus1; - tdivz += sw32_d_tdivzstepu * count; //minus1; - zi += d_zistepu * 65536.0f * count; //minus1; - z = sw32_d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sw32_sadjust; - snext = bound(count, snext, sw32_bbextents); - tnext = (int) (tdivz * z) + sw32_tadjust; - tnext = bound(count, tnext, sw32_bbextentt); - - if (count > 1) { - sstep = (snext - s) / count; //(count - 1); - tstep = (tnext - t) / count; //(count - 1); - - if (count & 4) - { - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest += 4; - } - if (count & 2) - { - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest += 2; - } - if (count & 1) - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - } - else - { - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - } - } - } while ((pspan = pspan->pnext) != NULL); - } - break; - case 2: - { - short *pbase = (short *) sw32_cacheblock, *pdest; - int count; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv; - float sdivz8stepu, tdivz8stepu, zi8stepu; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - sdivz8stepu = sw32_d_sdivzstepu * 8; - tdivz8stepu = sw32_d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536; - - do { - pdest = (short *) sw32_d_viewbuffer + (sw32_screenwidth * pspan->v) + - pspan->u; - - count = pspan->count; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu; - tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = sw32_d_zitable[(unsigned short) zi]; - - s = (int) (sdivz * z) + sw32_sadjust; - s = bound(0, s, sw32_bbextents); - t = (int) (tdivz * z) + sw32_tadjust; - t = bound(0, t, sw32_bbextentt); - - while(count >= 8) { - count -= 8; - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = sw32_d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sw32_sadjust; - snext = bound(8, snext, sw32_bbextents); - tnext = (int) (tdivz * z) + sw32_tadjust; - tnext = bound(8, tnext, sw32_bbextentt); - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[4] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[5] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[6] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[7] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s = snext;t = tnext; - pdest += 8; - } - if (count) - { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span - // (so can't step off polygon), clamp, calculate s and t steps - // across span by division, biasing steps low so we don't run - // off the texture - //countminus1 = (float) (count - 1); - sdivz += sw32_d_sdivzstepu * count; //minus1; - tdivz += sw32_d_tdivzstepu * count; //minus1; - zi += d_zistepu * 65536.0f * count; //minus1; - z = sw32_d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sw32_sadjust; - snext = bound(count, snext, sw32_bbextents); - tnext = (int) (tdivz * z) + sw32_tadjust; - tnext = bound(count, tnext, sw32_bbextentt); - - if (count > 1) { - sstep = (snext - s) / count; //(count - 1); - tstep = (tnext - t) / count; //(count - 1); - - if (count & 4) - { - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep;t += tstep; - pdest += 4; - } - if (count & 2) - { - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest += 2; - } - if (count & 1) - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - } - else - { - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - } - } - } while ((pspan = pspan->pnext) != NULL); - } - break; - case 4: - { - int *pbase = (int *) sw32_cacheblock, *pdest; - int count; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv; - float sdivz8stepu, tdivz8stepu, zi8stepu; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - sdivz8stepu = sw32_d_sdivzstepu * 8; - tdivz8stepu = sw32_d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536; - - do { - pdest = (int *) sw32_d_viewbuffer + (sw32_screenwidth * pspan->v) + pspan->u; - - count = pspan->count; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu; - tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = sw32_d_zitable[(unsigned short) zi]; - - s = (int) (sdivz * z) + sw32_sadjust; - s = bound(0, s, sw32_bbextents); - t = (int) (tdivz * z) + sw32_tadjust; - t = bound(0, t, sw32_bbextentt); - - while(count >= 8) { - count -= 8; - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = sw32_d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sw32_sadjust; - snext = bound(8, snext, sw32_bbextents); - tnext = (int) (tdivz * z) + sw32_tadjust; - tnext = bound(8, tnext, sw32_bbextentt); - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[4] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[5] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[6] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[7] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s = snext; - t = tnext; - pdest += 8; - } - if (count) - { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span - // (so can't step off polygon), clamp, calculate s and t steps - // across span by division, biasing steps low so we don't run - // off the texture - //countminus1 = (float) (count - 1); - sdivz += sw32_d_sdivzstepu * count; //minus1; - tdivz += sw32_d_tdivzstepu * count; //minus1; - zi += d_zistepu * 65536.0f * count; //minus1; - z = sw32_d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sw32_sadjust; - snext = bound(count, snext, sw32_bbextents); - tnext = (int) (tdivz * z) + sw32_tadjust; - tnext = bound(count, tnext, sw32_bbextentt); - - if (count > 1) { - sstep = (snext - s) / count; //(count - 1); - tstep = (tnext - t) / count; //(count - 1); - - if (count & 4) - { - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest += 4; - } - if (count & 2) - { - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest += 2; - } - if (count & 1) - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - } - else - { - pdest[0] = pbase[(t >> 16) * sw32_cachewidth + (s >> 16)]; - } - } - } while ((pspan = pspan->pnext) != NULL); - } - break; - default: - Sys_Error("D_DrawSpans: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} - -void -sw32_D_DrawZSpans (espan_t *pspan) -{ - int count, doublecount, izistep; - int izi; - short *pdest; - unsigned int ltemp; - double zi; - float du, dv; - - // FIXME: check for clamping/range problems - // we count on FP exceptions being turned off to avoid range problems - izistep = (int) (d_zistepu * 0x8000 * 0x10000); - - do { - pdest = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u; - - count = pspan->count; - - // calculate the initial 1/z - du = (float) pspan->u; - dv = (float) pspan->v; - - zi = d_ziorigin + dv * d_zistepv + du * d_zistepu; - // we count on FP exceptions being turned off to avoid range problems - izi = (int) (zi * 0x8000 * 0x10000); - - // LordHavoc: added big endian case, the old code is not correct on - // big-endian (results in swapped depth pairs), and is tuned more for - // x86, PowerPC compilers can probably do a good job with raw loop - // unrolling if it is even necessary... - if (bigendien) - { - do - { - *pdest++ = (short) (izi >> 16); - izi += izistep; - } - while(--count); - } - else - { - if ((intptr_t) pdest & 0x02) { - *pdest++ = (short) (izi >> 16); - izi += izistep; - count--; - } - - if ((doublecount = count >> 1) > 0) { - do { - ltemp = izi >> 16; - izi += izistep; - ltemp |= izi & 0xFFFF0000; - izi += izistep; - *(int *) pdest = ltemp; - pdest += 2; - } while (--doublecount > 0); - } - - if (count & 1) - *pdest = (short) (izi >> 16); - } - } while ((pspan = pspan->pnext) != NULL); -} diff --git a/libs/video/renderer/sw32/d_sky.c b/libs/video/renderer/sw32/d_sky.c deleted file mode 100644 index b9c03b5a0..000000000 --- a/libs/video/renderer/sw32/d_sky.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - d_sky.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/render.h" -#include "QF/sys.h" - -#include "d_local.h" -#include "r_internal.h" -#include "vid_sw.h" - -#define SKY_SPAN_SHIFT 5 -#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT) - - -static void -D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) -{ - float wu, wv, temp; - vec3_t end; - int half_width = vid.width >> 1; - int half_height = vid.height >> 1; - - if (r_refdef.vrect.width >= r_refdef.vrect.height) - temp = (float) r_refdef.vrect.width; - else - temp = (float) r_refdef.vrect.height; - - wu = 8192.0 * (float) (u - half_width) / temp; - wv = 8192.0 * (float) (half_height - v) / temp; - - end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0]; - end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1]; - end[2] = 4096 * vpn[2] + wu * vright[2] + wv * vup[2]; - end[2] *= 3; - VectorNormalize (end); - - temp = sw32_r_skytime * sw32_r_skyspeed; // TODO: add D_SetupFrame & set this there - *s = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[0]) * 0x10000); - *t = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[1]) * 0x10000); -} - -void -sw32_D_DrawSkyScans (espan_t *pspan) -{ - switch(sw32_ctx->pixbytes) { - case 1: - { - int count, spancount, u, v; - byte *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - int spancountminus1; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - snext = 0; // ditto - tnext = 0; // ditto - - do { - pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u; - - count = pspan->count; - - // calculate the initial s & t - u = pspan->u; - v = pspan->v; - D_Sky_uv_To_st (u, v, &s, &t); - - do { - if (count >= SKY_SPAN_MAX) - spancount = SKY_SPAN_MAX; - else - spancount = count; - - count -= spancount; - - if (count) { - u += spancount; - - // calculate s and t at far end of span, - // calculate s and t steps across span by shifting - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) >> SKY_SPAN_SHIFT; - tstep = (tnext - t) >> SKY_SPAN_SHIFT; - } else { - // calculate s and t at last pixel in span, - // calculate s and t steps across span by division - spancountminus1 = (float) (spancount - 1); - - if (spancountminus1 > 0) { - u += spancountminus1; - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) / spancountminus1; - tstep = (tnext - t) / spancountminus1; - } - } - - do { - *pdest++ = ((byte *) sw32_r_skysource) - [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - - } while ((pspan = pspan->pnext) != NULL); - } - break; - - case 2: - { - int count, spancount, u, v; - short *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - int spancountminus1; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - snext = 0; // ditto - tnext = 0; // ditto - - do { - pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u; - - count = pspan->count; - - // calculate the initial s & t - u = pspan->u; - v = pspan->v; - D_Sky_uv_To_st (u, v, &s, &t); - - do { - if (count >= SKY_SPAN_MAX) - spancount = SKY_SPAN_MAX; - else - spancount = count; - - count -= spancount; - - if (count) { - u += spancount; - - // calculate s and t at far end of span, - // calculate s and t steps across span by shifting - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) >> SKY_SPAN_SHIFT; - tstep = (tnext - t) >> SKY_SPAN_SHIFT; - } else { - // calculate s and t at last pixel in span, - // calculate s and t steps across span by division - spancountminus1 = (float) (spancount - 1); - - if (spancountminus1 > 0) { - u += spancountminus1; - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) / spancountminus1; - tstep = (tnext - t) / spancountminus1; - } - } - - do { - *pdest++ = ((short *) sw32_r_skysource) - [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - - } while ((pspan = pspan->pnext) != NULL); - } - break; - - case 4: - { - int count, spancount, u, v; - int *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - int spancountminus1; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - snext = 0; // ditto - tnext = 0; // ditto - - do { - pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u; - - count = pspan->count; - - // calculate the initial s & t - u = pspan->u; - v = pspan->v; - D_Sky_uv_To_st (u, v, &s, &t); - - do { - if (count >= SKY_SPAN_MAX) - spancount = SKY_SPAN_MAX; - else - spancount = count; - - count -= spancount; - - if (count) { - u += spancount; - - // calculate s and t at far end of span, - // calculate s and t steps across span by shifting - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) >> SKY_SPAN_SHIFT; - tstep = (tnext - t) >> SKY_SPAN_SHIFT; - } else { - // calculate s and t at last pixel in span, - // calculate s and t steps across span by division - spancountminus1 = (float) (spancount - 1); - - if (spancountminus1 > 0) { - u += spancountminus1; - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) / spancountminus1; - tstep = (tnext - t) / spancountminus1; - } - } - - do { - *pdest++ = ((int *) sw32_r_skysource) - [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - - } while ((pspan = pspan->pnext) != NULL); - } - break; - - default: - Sys_Error("D_DrawSkyScans: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} diff --git a/libs/video/renderer/sw32/d_sprite.c b/libs/video/renderer/sw32/d_sprite.c deleted file mode 100644 index d81fda3bb..000000000 --- a/libs/video/renderer/sw32/d_sprite.c +++ /dev/null @@ -1,732 +0,0 @@ -/* - d_sprite.c - - software top-level rasterization driver module for drawing sprites - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/render.h" -#include "QF/sys.h" - -#include "compat.h" -#include "d_local.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - -static int sprite_height; -static int minindex, maxindex; -static sspan_t *sprite_spans; - - - -void -sw32_D_SpriteDrawSpans (sspan_t *pspan) -{ - switch(sw32_ctx->pixbytes) { - case 1: - { - int count, spancount, izistep; - int izi; - byte *pbase; - byte *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivz8stepu, tdivz8stepu, zi8stepu; - byte btemp; - short *pz; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - pbase = (byte *) sw32_cacheblock; - - sdivz8stepu = sw32_d_sdivzstepu * 8; - tdivz8stepu = sw32_d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536.0f; - - // we count on FP exceptions being turned off to avoid range problems - izistep = (int) (d_zistepu * 0x8000 * 0x10000); - - do { - pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u; - pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u; - - count = pspan->count; - - if (count <= 0) - goto NextSpan1; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu; - tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = sw32_d_zitable[(int) zi]; - // we count on FP exceptions being turned off to avoid range - // problems - - izi = (int) (zi * 0x8000); - - s = (int) (sdivz * z) + sw32_sadjust; - if (s > sw32_bbextents) - s = sw32_bbextents; - else if (s < 0) - s = 0; - - t = (int) (tdivz * z) + sw32_tadjust; - if (t > sw32_bbextentt) - t = sw32_bbextentt; - else if (t < 0) - t = 0; - - do { - // calculate s and t at the far end of the span - if (count >= 8) - spancount = 8; - else - spancount = count; - - count -= spancount; - - if (count) { - // calculate s/z, t/z, zi->fixed s and t at far end of - // span, calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = sw32_d_zitable[(int) zi]; - - snext = (int) (sdivz * z) + sw32_sadjust; - if (snext > sw32_bbextents) - snext = sw32_bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps from causing overstepping - // & running off the texture's edge - - tnext = (int) (tdivz * z) + sw32_tadjust; - if (tnext > sw32_bbextentt) - tnext = sw32_bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off - // error on <0 steps - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - } else { - // calculate s/z, t/z, zi->fixed s and t at last pixel - // in span (so can't step off polygon), clamp, - // calculate s and t steps across span by division, - // biasing steps low so we don't run off the texture - spancountminus1 = (float) (spancount - 1); - sdivz += sw32_d_sdivzstepu * spancountminus1; - tdivz += sw32_d_tdivzstepu * spancountminus1; - zi += d_zistepu * 65536.0f * spancountminus1; - z = sw32_d_zitable[(int) zi]; - snext = (int) (sdivz * z) + sw32_sadjust; - if (snext > sw32_bbextents) - snext = sw32_bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps from from causing - // overstepping & running off the - // edge of the texture - - tnext = (int) (tdivz * z) + sw32_tadjust; - if (tnext > sw32_bbextentt) - tnext = sw32_bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on - // <0 steps - - if (spancount > 1) { - sstep = (snext - s) / (spancount - 1); - tstep = (tnext - t) / (spancount - 1); - } - } - - do { - btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth]; - if (btemp != TRANSPARENT_COLOR) { - if (*pz <= (izi >> 16)) { - *pz = izi >> 16; - *pdest = btemp; - } - } - - izi += izistep; - pdest++; - pz++; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - -NextSpan1: - pspan++; - - } while (pspan->count != DS_SPAN_LIST_END); - } - break; - - case 2: - { - int count, spancount, izistep; - int izi; - byte *pbase; - short *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivz8stepu, tdivz8stepu, zi8stepu; - byte btemp; - short *pz; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - pbase = (byte *) sw32_cacheblock; - - sdivz8stepu = sw32_d_sdivzstepu * 8; - tdivz8stepu = sw32_d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536; - - // we count on FP exceptions being turned off to avoid range problems - izistep = (int) (d_zistepu * 0x8000 * 0x10000); - - do { - pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u; - pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u; - - count = pspan->count; - - if (count <= 0) - goto NextSpan2; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu; - tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = sw32_d_zitable[(int) zi]; - // we count on FP exceptions being turned off to avoid range - // problems - izi = (int) (zi * 0x8000); - - s = (int) (sdivz * z) + sw32_sadjust; - if (s > sw32_bbextents) - s = sw32_bbextents; - else if (s < 0) - s = 0; - - t = (int) (tdivz * z) + sw32_tadjust; - if (t > sw32_bbextentt) - t = sw32_bbextentt; - else if (t < 0) - t = 0; - - do { - // calculate s and t at the far end of the span - if (count >= 8) - spancount = 8; - else - spancount = count; - - count -= spancount; - - if (count) { - // calculate s/z, t/z, zi->fixed s and t at far end of - // span, calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = sw32_d_zitable[(int) zi]; - - snext = (int) (sdivz * z) + sw32_sadjust; - if (snext > sw32_bbextents) - snext = sw32_bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps from causing overstepping - // & running off the texture's edge - - tnext = (int) (tdivz * z) + sw32_tadjust; - if (tnext > sw32_bbextentt) - tnext = sw32_bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on - // <0 steps - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - } else { - // calculate s/z, t/z, zi->fixed s and t at last pixel in - // span (so can't step off polygon), clamp, calculate s - // and t steps across span by division, biasing steps - // low so we don't run off the texture - spancountminus1 = (float) (spancount - 1); - sdivz += sw32_d_sdivzstepu * spancountminus1; - tdivz += sw32_d_tdivzstepu * spancountminus1; - zi += d_zistepu * 65536.0f * spancountminus1; - z = sw32_d_zitable[(int) zi]; - snext = (int) (sdivz * z) + sw32_sadjust; - if (snext > sw32_bbextents) - snext = sw32_bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps from from causing - // overstepping & running off the - // edge of the texture - - tnext = (int) (tdivz * z) + sw32_tadjust; - if (tnext > sw32_bbextentt) - tnext = sw32_bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on - // <0 steps - - if (spancount > 1) { - sstep = (snext - s) / (spancount - 1); - tstep = (tnext - t) / (spancount - 1); - } - } - - do { - btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth]; - if (btemp != TRANSPARENT_COLOR) { - if (*pz <= (izi >> 16)) { - *pz = izi >> 16; - *pdest = sw32_8to16table[btemp]; - } - } - - izi += izistep; - pdest++; - pz++; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - -NextSpan2: - pspan++; - - } while (pspan->count != DS_SPAN_LIST_END); - } - break; - - case 4: - { - int count, spancount, izistep; - int izi; - byte *pbase; - int *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivz8stepu, tdivz8stepu, zi8stepu; - byte btemp; - short *pz; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - pbase = (byte *) sw32_cacheblock; - - sdivz8stepu = sw32_d_sdivzstepu * 8; - tdivz8stepu = sw32_d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536; - - // we count on FP exceptions being turned off to avoid range problems - izistep = (int) (d_zistepu * 0x8000 * 0x10000); - - do { - pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * pspan->v + pspan->u; - pz = sw32_d_pzbuffer + (sw32_d_zwidth * pspan->v) + pspan->u; - - count = pspan->count; - - if (count <= 0) - goto NextSpan4; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = sw32_d_sdivzorigin + dv * sw32_d_sdivzstepv + du * sw32_d_sdivzstepu; - tdivz = sw32_d_tdivzorigin + dv * sw32_d_tdivzstepv + du * sw32_d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = sw32_d_zitable[(int) zi]; - // we count on FP exceptions being turned off to avoid range - // problems - izi = (int) (zi * 0x8000); - - s = (int) (sdivz * z) + sw32_sadjust; - if (s > sw32_bbextents) - s = sw32_bbextents; - else if (s < 0) - s = 0; - - t = (int) (tdivz * z) + sw32_tadjust; - if (t > sw32_bbextentt) - t = sw32_bbextentt; - else if (t < 0) - t = 0; - - do { - // calculate s and t at the far end of the span - if (count >= 8) - spancount = 8; - else - spancount = count; - - count -= spancount; - - if (count) { - // calculate s/z, t/z, zi->fixed s and t at far end of - // span, calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = sw32_d_zitable[(int) zi]; - - snext = (int) (sdivz * z) + sw32_sadjust; - if (snext > sw32_bbextents) - snext = sw32_bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps from causing overstepping - // & running off the texture's edge - - tnext = (int) (tdivz * z) + sw32_tadjust; - if (tnext > sw32_bbextentt) - tnext = sw32_bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on - // <0 steps - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - } else { - // calculate s/z, t/z, zi->fixed s and t at last pixel in - // span (so can't step off polygon), clamp, calculate s - // and t steps across span by division, biasing steps low - // so we don't run off the texture - spancountminus1 = (float) (spancount - 1); - sdivz += sw32_d_sdivzstepu * spancountminus1; - tdivz += sw32_d_tdivzstepu * spancountminus1; - zi += d_zistepu * 65536.0f * spancountminus1; - z = sw32_d_zitable[(int) zi]; - snext = (int) (sdivz * z) + sw32_sadjust; - if (snext > sw32_bbextents) - snext = sw32_bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps fromcausing overstepping - // & running off the texture's edge - - tnext = (int) (tdivz * z) + sw32_tadjust; - if (tnext > sw32_bbextentt) - tnext = sw32_bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on - // <0 steps - - if (spancount > 1) { - sstep = (snext - s) / (spancount - 1); - tstep = (tnext - t) / (spancount - 1); - } - } - - do { - btemp = pbase[(s >> 16) + (t >> 16) * sw32_cachewidth]; - if (btemp != TRANSPARENT_COLOR) { - if (*pz <= (izi >> 16)) { - *pz = izi >> 16; - *pdest = d_8to24table[btemp]; - } - } - - izi += izistep; - pdest++; - pz++; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - -NextSpan4: - pspan++; - - } while (pspan->count != DS_SPAN_LIST_END); - } - break; - - default: - Sys_Error("D_SpriteDrawSpans: unsupported r_pixbytes %i", - sw32_ctx->pixbytes); - } -} - -static void -D_SpriteScanLeftEdge (void) -{ - int i, v, itop, ibottom, lmaxindex; - emitpoint_t *pvert, *pnext; - sspan_t *pspan; - float du, dv, vtop, vbottom, slope; - fixed16_t u, u_step; - - pspan = sprite_spans; - i = minindex; - if (i == 0) - i = sw32_r_spritedesc.nump; - - lmaxindex = maxindex; - if (lmaxindex == 0) - lmaxindex = sw32_r_spritedesc.nump; - - vtop = ceil (sw32_r_spritedesc.pverts[i].v); - - do { - pvert = &sw32_r_spritedesc.pverts[i]; - pnext = pvert - 1; - - vbottom = ceil (pnext->v); - - if (vtop < vbottom) { - du = pnext->u - pvert->u; - dv = pnext->v - pvert->v; - slope = du / dv; - u_step = (int) (slope * 0x10000); - // adjust u to ceil the integer portion - u = (int) ((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) + - (0x10000 - 1); - itop = (int) vtop; - ibottom = (int) vbottom; - - for (v = itop; v < ibottom; v++) { - pspan->u = u >> 16; - pspan->v = v; - u += u_step; - pspan++; - } - } - - vtop = vbottom; - - i--; - if (i == 0) - i = sw32_r_spritedesc.nump; - - } while (i != lmaxindex); -} - -static void -D_SpriteScanRightEdge (void) -{ - int i, v, itop, ibottom; - emitpoint_t *pvert, *pnext; - sspan_t *pspan; - float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext; - fixed16_t u, u_step; - - pspan = sprite_spans; - i = minindex; - - vvert = sw32_r_spritedesc.pverts[i].v; - if (vvert < r_refdef.fvrecty_adj) - vvert = r_refdef.fvrecty_adj; - if (vvert > r_refdef.fvrectbottom_adj) - vvert = r_refdef.fvrectbottom_adj; - - vtop = ceil (vvert); - - do { - pvert = &sw32_r_spritedesc.pverts[i]; - pnext = pvert + 1; - - vnext = pnext->v; - if (vnext < r_refdef.fvrecty_adj) - vnext = r_refdef.fvrecty_adj; - if (vnext > r_refdef.fvrectbottom_adj) - vnext = r_refdef.fvrectbottom_adj; - - vbottom = ceil (vnext); - - if (vtop < vbottom) { - uvert = pvert->u; - if (uvert < r_refdef.fvrectx_adj) - uvert = r_refdef.fvrectx_adj; - if (uvert > r_refdef.fvrectright_adj) - uvert = r_refdef.fvrectright_adj; - - unext = pnext->u; - if (unext < r_refdef.fvrectx_adj) - unext = r_refdef.fvrectx_adj; - if (unext > r_refdef.fvrectright_adj) - unext = r_refdef.fvrectright_adj; - - du = unext - uvert; - dv = vnext - vvert; - slope = du / dv; - u_step = (int) (slope * 0x10000); - // adjust u to ceil the integer portion - u = (int) ((uvert + (slope * (vtop - vvert))) * 0x10000) + - (0x10000 - 1); - itop = (int) vtop; - ibottom = (int) vbottom; - - for (v = itop; v < ibottom; v++) { - pspan->count = (u >> 16) - pspan->u; - u += u_step; - pspan++; - } - } - - vtop = vbottom; - vvert = vnext; - - i++; - if (i == sw32_r_spritedesc.nump) - i = 0; - - } while (i != maxindex); - - pspan->count = DS_SPAN_LIST_END; // mark the end of the span list -} - -static void -D_SpriteCalculateGradients (void) -{ - vec3_t p_normal, p_saxis, p_taxis, p_temp1; - float distinv; - - sw32_TransformVector (sw32_r_spritedesc.vpn, p_normal); - sw32_TransformVector (sw32_r_spritedesc.vright, p_saxis); - sw32_TransformVector (sw32_r_spritedesc.vup, p_taxis); - VectorNegate (p_taxis, p_taxis); - - distinv = 1.0 / (-DotProduct (modelorg, sw32_r_spritedesc.vpn)); - distinv = min (distinv, 1.0); - - sw32_d_sdivzstepu = p_saxis[0] * sw32_xscaleinv; - sw32_d_tdivzstepu = p_taxis[0] * sw32_xscaleinv; - - sw32_d_sdivzstepv = -p_saxis[1] * sw32_yscaleinv; - sw32_d_tdivzstepv = -p_taxis[1] * sw32_yscaleinv; - - d_zistepu = p_normal[0] * sw32_xscaleinv * distinv; - d_zistepv = -p_normal[1] * sw32_yscaleinv * distinv; - - sw32_d_sdivzorigin = p_saxis[2] - sw32_xcenter * sw32_d_sdivzstepu - - sw32_ycenter * sw32_d_sdivzstepv; - sw32_d_tdivzorigin = p_taxis[2] - sw32_xcenter * sw32_d_tdivzstepu - - sw32_ycenter * sw32_d_tdivzstepv; - d_ziorigin = p_normal[2] * distinv - sw32_xcenter * d_zistepu - - sw32_ycenter * d_zistepv; - - sw32_TransformVector (modelorg, p_temp1); - - sw32_sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - - (-(sw32_cachewidth >> 1) << 16); - sw32_tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - - (-(sprite_height >> 1) << 16); - - // -1 (-epsilon) so we never wander off the edge of the texture - sw32_bbextents = (sw32_cachewidth << 16) - 1; - sw32_bbextentt = (sprite_height << 16) - 1; -} - -void -sw32_D_DrawSprite (void) -{ - int i, nump; - float ymin, ymax; - emitpoint_t *pverts; - sspan_t spans[MAXHEIGHT + 1]; - - sprite_spans = spans; - - // find the top and bottom vertices, and make sure there's at least one - // scan to draw - ymin = 999999.9; - ymax = -999999.9; - pverts = sw32_r_spritedesc.pverts; - - for (i = 0; i < sw32_r_spritedesc.nump; i++) { - if (pverts->v < ymin) { - ymin = pverts->v; - minindex = i; - } - - if (pverts->v > ymax) { - ymax = pverts->v; - maxindex = i; - } - - pverts++; - } - - ymin = ceil (ymin); - ymax = ceil (ymax); - - if (ymin >= ymax) - return; // doesn't cross any scans at all - - sw32_cachewidth = sw32_r_spritedesc.pspriteframe->width; - sprite_height = sw32_r_spritedesc.pspriteframe->height; - sw32_cacheblock = &sw32_r_spritedesc.pspriteframe->pixels[0]; - - // copy the first vertex to the last vertex, so we don't have to deal with - // wrapping - nump = sw32_r_spritedesc.nump; - pverts = sw32_r_spritedesc.pverts; - pverts[nump] = pverts[0]; - - D_SpriteCalculateGradients (); - D_SpriteScanLeftEdge (); - D_SpriteScanRightEdge (); - sw32_D_SpriteDrawSpans (sprite_spans); -} diff --git a/libs/video/renderer/sw32/d_surf.c b/libs/video/renderer/sw32/d_surf.c deleted file mode 100644 index 3b1b68c6a..000000000 --- a/libs/video/renderer/sw32/d_surf.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - d_surf.c - - rasterization driver surface heap manager - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include - -#include "QF/qargs.h" -#include "QF/render.h" -#include "QF/sys.h" - -#include "compat.h" -#include "d_local.h" -#include "r_internal.h" -#include "vid_sw.h" - -static float surfscale; - -static int sc_size; -surfcache_t *sw32_sc_rover; -static surfcache_t *sc_base; - -#define GUARDSIZE 4 - - -void * -sw32_D_SurfaceCacheAddress (void) -{ - return sc_base; -} - - -int -sw32_D_SurfaceCacheForRes (void *data, int width, int height) -{ - int size, pix; - - if (COM_CheckParm ("-surfcachesize")) { - size = atoi (com_argv[COM_CheckParm ("-surfcachesize") + 1]) * 1024; - return size; - } - - size = SURFCACHE_SIZE_AT_320X200; - - pix = width * height; - if (pix > 64000) - size += (pix - 64000) * 3; - - size *= sw32_ctx->pixbytes; - - return size; -} - - -static void -D_CheckCacheGuard (void) -{ - byte *s; - int i; - - s = (byte *) sc_base + sc_size; - for (i = 0; i < GUARDSIZE; i++) - if (s[i] != (byte) i) - Sys_Error ("D_CheckCacheGuard: failed"); -} - - -static void -D_ClearCacheGuard (void) -{ - byte *s; - int i; - - s = (byte *) sc_base + sc_size; - for (i = 0; i < GUARDSIZE; i++) - s[i] = (byte) i; -} - - -void -sw32_D_InitCaches (void *data, void *buffer, int size) -{ - Sys_MaskPrintf (SYS_dev, "D_InitCaches: %ik surface cache\n", size/1024); - - sc_size = size - GUARDSIZE; - sc_base = (surfcache_t *) buffer; - sw32_sc_rover = sc_base; - - sc_base->next = NULL; - sc_base->owner = NULL; - sc_base->size = sc_size; - - sw32_d_pzbuffer = vid.zbuffer; - - D_ClearCacheGuard (); -} - - -void -sw32_D_FlushCaches (void *data) -{ - surfcache_t *c; - - if (!sc_base) - return; - - for (c = sc_base; c; c = c->next) { - if (c->owner) - *c->owner = NULL; - } - - sw32_sc_rover = sc_base; - sc_base->next = NULL; - sc_base->owner = NULL; - sc_base->size = sc_size; -} - - -static surfcache_t * -D_SCAlloc (int width, int size) -{ - surfcache_t *new; - qboolean wrapped_this_time; - - if ((width < 0) || (width > 512)) // FIXME shouldn't really have a max - Sys_Error ("D_SCAlloc: bad cache width %d", width); - - if ((size <= 0) || (size > (0x40000 * sw32_ctx->pixbytes))) //FIXME ditto - Sys_Error ("D_SCAlloc: bad cache size %d", size); - - /* This adds the offset of data[0] in the surfcache_t struct. */ - size += field_offset (surfcache_t, data); - -#define SIZE_ALIGN (sizeof(surfcache_t*)-1) - size = (size + SIZE_ALIGN) & ~SIZE_ALIGN; -#undef SIZE_ALIGN - size = (size + 3) & ~3; - if (size > sc_size) - Sys_Error ("D_SCAlloc: %i > cache size", size); - - // if there is not size bytes after the rover, reset to the start - wrapped_this_time = false; - - if (!sw32_sc_rover || (byte *) sw32_sc_rover - (byte *) sc_base > sc_size - size) { - if (sw32_sc_rover) { - wrapped_this_time = true; - } - sw32_sc_rover = sc_base; - } - // colect and free surfcache_t blocks until the rover block is large enough - new = sw32_sc_rover; - if (sw32_sc_rover->owner) - *sw32_sc_rover->owner = NULL; - - while (new->size < size) { - // free another - sw32_sc_rover = sw32_sc_rover->next; - if (!sw32_sc_rover) - Sys_Error ("D_SCAlloc: hit the end of memory"); - if (sw32_sc_rover->owner) - *sw32_sc_rover->owner = NULL; - - new->size += sw32_sc_rover->size; - new->next = sw32_sc_rover->next; - } - - // create a fragment out of any leftovers - if (new->size - size > 256) { - sw32_sc_rover = (surfcache_t *) ((byte *) new + size); - sw32_sc_rover->size = new->size - size; - sw32_sc_rover->next = new->next; - sw32_sc_rover->width = 0; - sw32_sc_rover->owner = NULL; - new->next = sw32_sc_rover; - new->size = size; - } else - sw32_sc_rover = new->next; - - new->width = width; -// DEBUG - if (width > 0) - new->height = (size - sizeof (*new) + sizeof (new->data)) / - (width * sw32_ctx->pixbytes); - - new->owner = NULL; // should be set properly after return - - if (sw32_d_roverwrapped) { - if (wrapped_this_time || (sw32_sc_rover >= sw32_d_initial_rover)) - r_cache_thrash = true; - } else if (wrapped_this_time) { - sw32_d_roverwrapped = true; - } - - D_CheckCacheGuard (); // DEBUG - return new; -} - - -surfcache_t * -sw32_D_CacheSurface (msurface_t *surface, int miplevel) -{ - surfcache_t *cache; - - // if the surface is animating or flashing, flush the cache - sw32_r_drawsurf.texture = R_TextureAnimation (currententity, surface); - sw32_r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; - sw32_r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; - sw32_r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; - sw32_r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]]; - - // see if the cache holds apropriate data - cache = surface->cachespots[miplevel]; - - if (cache && !cache->dlight && surface->dlightframe != r_framecount - && cache->texture == sw32_r_drawsurf.texture - && cache->lightadj[0] == sw32_r_drawsurf.lightadj[0] - && cache->lightadj[1] == sw32_r_drawsurf.lightadj[1] - && cache->lightadj[2] == sw32_r_drawsurf.lightadj[2] - && cache->lightadj[3] == sw32_r_drawsurf.lightadj[3]) - return cache; - - // determine shape of surface - surfscale = 1.0 / (1 << miplevel); - sw32_r_drawsurf.surfmip = miplevel; - sw32_r_drawsurf.surfwidth = surface->extents[0] >> miplevel; - sw32_r_drawsurf.rowbytes = sw32_r_drawsurf.surfwidth * sw32_ctx->pixbytes; - sw32_r_drawsurf.surfheight = surface->extents[1] >> miplevel; - - // allocate memory if needed - if (!cache) { - // if a texture just animated, don't reallocate it - cache = D_SCAlloc (sw32_r_drawsurf.surfwidth, - sw32_r_drawsurf.rowbytes * sw32_r_drawsurf.surfheight); - surface->cachespots[miplevel] = cache; - cache->owner = &surface->cachespots[miplevel]; - cache->mipscale = surfscale; - } - - if (surface->dlightframe == r_framecount) - cache->dlight = 1; - else - cache->dlight = 0; - - sw32_r_drawsurf.surfdat = (byte *) cache->data; - - cache->texture = sw32_r_drawsurf.texture; - cache->lightadj[0] = sw32_r_drawsurf.lightadj[0]; - cache->lightadj[1] = sw32_r_drawsurf.lightadj[1]; - cache->lightadj[2] = sw32_r_drawsurf.lightadj[2]; - cache->lightadj[3] = sw32_r_drawsurf.lightadj[3]; - - // draw and light the surface texture - sw32_r_drawsurf.surf = surface; - - sw32_c_surf++; - sw32_R_DrawSurface (); - - return surface->cachespots[miplevel]; -} diff --git a/libs/video/renderer/sw32/d_vars.c b/libs/video/renderer/sw32/d_vars.c deleted file mode 100644 index f5e2752e1..000000000 --- a/libs/video/renderer/sw32/d_vars.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - d_vars.c - - global refresh variables - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/qtypes.h" - -// all global and static refresh variables are collected in a contiguous block -// to avoid cache conflicts. - -// global refresh variables ----------------------------- - -// FIXME: make into one big structure, like cl or sv -// FIXME: do separately for refresh engine and driver - -float sw32_d_sdivzstepu, sw32_d_tdivzstepu, sw32_d_zistepu; -float sw32_d_sdivzstepv, sw32_d_tdivzstepv, sw32_d_zistepv; -float sw32_d_sdivzorigin, sw32_d_tdivzorigin, sw32_d_ziorigin; - -fixed16_t sw32_sadjust, sw32_tadjust, sw32_bbextents, sw32_bbextentt; - -byte *sw32_cacheblock; -int sw32_cachewidth; -byte *sw32_d_viewbuffer; -short *sw32_d_pzbuffer; -int sw32_d_zrowbytes; -int sw32_d_zwidth; diff --git a/libs/video/renderer/sw32/d_zpoint.c b/libs/video/renderer/sw32/d_zpoint.c deleted file mode 100644 index 5d0ab372b..000000000 --- a/libs/video/renderer/sw32/d_zpoint.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - d_zpoint.c - - software driver module for drawing z-buffered points - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/sys.h" - -#include "d_local.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - - -void -sw32_D_DrawZPoint (void) -{ - short *pz; - int izi; - - pz = sw32_d_pzbuffer + (sw32_d_zwidth * sw32_r_zpointdesc.v) + sw32_r_zpointdesc.u; - izi = (int) (sw32_r_zpointdesc.zi * 0x8000); - - if (*pz <= izi) { - *pz = izi; - switch(sw32_ctx->pixbytes) - { - case 1: - ((byte *) sw32_d_viewbuffer) [sw32_d_scantable[sw32_r_zpointdesc.v] + - sw32_r_zpointdesc.u] = sw32_r_zpointdesc.color; - break; - case 2: - ((short *) sw32_d_viewbuffer) [sw32_d_scantable[sw32_r_zpointdesc.v] + - sw32_r_zpointdesc.u] = - sw32_8to16table[sw32_r_zpointdesc.color]; - break; - case 4: - ((int *) sw32_d_viewbuffer) [sw32_d_scantable[sw32_r_zpointdesc.v] + - sw32_r_zpointdesc.u] = - d_8to24table[sw32_r_zpointdesc.color]; - break; - default: - Sys_Error("D_DrawZPoint: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } - } -} diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c deleted file mode 100644 index 9e8244371..000000000 --- a/libs/video/renderer/sw32/draw.c +++ /dev/null @@ -1,1369 +0,0 @@ -/* - draw.c - - this is the only file outside the refresh that touches the vid buffer - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/quakefs.h" -#include "QF/sound.h" -#include "QF/sys.h" -#include "QF/ui/view.h" - -#include "d_iface.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - -typedef struct { - vrect_t rect; - int width; - int height; - byte *ptexbytes; - int rowbytes; -} rectdesc_t; - -static rectdesc_t r_rectdesc; - -static qpic_t *draw_disc; -static qpic_t *draw_backtile; - - -/* Support Routines */ - -typedef struct cachepic_s { - char name[MAX_QPATH]; - cache_user_t cache; -} cachepic_t; - -#define MAX_CACHED_PICS 128 -static cachepic_t cachepics[MAX_CACHED_PICS]; -static int numcachepics; - -#define CLIP(x,y,w,h,mw,mh) \ - do { \ - if (y < 0) { \ - h += y; \ - y = 0; \ - } \ - if (y + h > mh) \ - h = mh - y; \ - if (h <= 0) \ - return; \ - if (x < 0) { \ - w += x; \ - x = 0; \ - } \ - if (x + w > mw) \ - w = mw - x; \ - if (w <= 0) \ - return; \ - } while (0) - - -qpic_t * -sw32_Draw_MakePic (int width, int height, const byte *data) -{ - qpic_t *pic; - int size = width * height; - - pic = malloc (field_offset (qpic_t, data[size])); - pic->width = width; - pic->height = height; - memcpy (pic->data, data, size); - return pic; -} - -void -sw32_Draw_DestroyPic (qpic_t *pic) -{ - free (pic); -} - -qpic_t * -sw32_Draw_PicFromWad (const char *name) -{ - return W_GetLumpName (name); -} - - -qpic_t * -sw32_Draw_CachePic (const char *path, qboolean alpha) -{ - cachepic_t *pic; - int i; - qpic_t *dat; - - for (pic = cachepics, i = 0; i < numcachepics; pic++, i++) - if (!strcmp (path, pic->name)) - break; - - if (i == numcachepics) { - for (pic = cachepics, i = 0; i < numcachepics; pic++, i++) - if (!pic->name[0]) - break; - if (i == numcachepics) { - if (numcachepics == MAX_CACHED_PICS) - Sys_Error ("numcachepics == MAX_CACHED_PICS"); - numcachepics++; - } - strcpy (pic->name, path); - } - - dat = Cache_Check (&pic->cache); - - if (dat) - return dat; - - // load the pic from disk - QFS_LoadCacheFile (QFS_FOpenFile (path), &pic->cache); - - dat = (qpic_t *) pic->cache.data; - if (!dat) { - Sys_Error ("Draw_CachePic: failed to load %s", path); - } - - SwapPic (dat); - - return dat; -} - -void -sw32_Draw_UncachePic (const char *path) -{ - cachepic_t *pic; - int i; - - for (pic = cachepics, i = 0; i < numcachepics; pic++, i++) { - if (!strcmp (path, pic->name)) { - Cache_Release (&pic->cache); - pic->name[0] = 0; - break; - } - } -} - - -void -sw32_Draw_TextBox (int x, int y, int width, int lines, byte alpha) -{ - qpic_t *p; - int cx, cy; - int n; - - // draw left side - cx = x; - cy = y; - p = sw32_Draw_CachePic ("gfx/box_tl.lmp", true); - sw32_Draw_Pic (cx, cy, p); - p = sw32_Draw_CachePic ("gfx/box_ml.lmp", true); - for (n = 0; n < lines; n++) { - cy += 8; - sw32_Draw_Pic (cx, cy, p); - } - p = sw32_Draw_CachePic ("gfx/box_bl.lmp", true); - sw32_Draw_Pic (cx, cy + 8, p); - - // draw middle - cx += 8; - while (width > 0) { - cy = y; - p = sw32_Draw_CachePic ("gfx/box_tm.lmp", true); - sw32_Draw_Pic (cx, cy, p); - p = sw32_Draw_CachePic ("gfx/box_mm.lmp", true); - for (n = 0; n < lines; n++) { - cy += 8; - if (n == 1) - p = sw32_Draw_CachePic ("gfx/box_mm2.lmp", true); - sw32_Draw_Pic (cx, cy, p); - } - p = sw32_Draw_CachePic ("gfx/box_bm.lmp", true); - sw32_Draw_Pic (cx, cy + 8, p); - width -= 2; - cx += 16; - } - - // draw right side - cy = y; - p = sw32_Draw_CachePic ("gfx/box_tr.lmp", true); - sw32_Draw_Pic (cx, cy, p); - p = sw32_Draw_CachePic ("gfx/box_mr.lmp", true); - for (n = 0; n < lines; n++) { - cy += 8; - sw32_Draw_Pic (cx, cy, p); - } - p = sw32_Draw_CachePic ("gfx/box_br.lmp", true); - sw32_Draw_Pic (cx, cy + 8, p); -} - - -void -sw32_Draw_Init (void) -{ - draw_chars = W_GetLumpName ("conchars"); - draw_disc = W_GetLumpName ("disc"); - draw_backtile = W_GetLumpName ("backtile"); - - r_rectdesc.width = draw_backtile->width; - r_rectdesc.height = draw_backtile->height; - r_rectdesc.ptexbytes = draw_backtile->data; - r_rectdesc.rowbytes = draw_backtile->width; -} - - -/* - Draw_Character - - Draws one 8*8 graphics character with 0 being transparent. - It can be clipped to the top of the screen to allow the console to be - smoothly scrolled off. -*/ -void -sw32_Draw_Character (int x, int y, unsigned int chr) -{ - byte *source; - int drawline; - int row, col; - - chr &= 255; - - if (y <= -8) - return; // totally off screen - - if (y > vid.conview->ylen - 8 || x < 0 || x > vid.conview->xlen - 8) - return; - if (chr > 255) - return; - - row = chr >> 4; - col = chr & 15; - source = draw_chars + (row << 10) + (col << 3); - - if (y < 0) { // clipped - drawline = 8 + y; - source -= 128 * y; - y = 0; - } else - drawline = 8; - - - switch(sw32_ctx->pixbytes) { - case 1: - { - byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; - - while (drawline--) { - if (source[0]) - dest[0] = source[0]; - if (source[1]) - dest[1] = source[1]; - if (source[2]) - dest[2] = source[2]; - if (source[3]) - dest[3] = source[3]; - if (source[4]) - dest[4] = source[4]; - if (source[5]) - dest[5] = source[5]; - if (source[6]) - dest[6] = source[6]; - if (source[7]) - dest[7] = source[7]; - source += 128; - dest += vid.rowbytes; - } - } - break; - case 2: - { - unsigned short *dest = (unsigned short *) vid.buffer + y * - (vid.rowbytes >> 1) + x; - - while (drawline--) { - if (source[0]) - dest[0] = sw32_8to16table[source[0]]; - if (source[1]) - dest[1] = sw32_8to16table[source[1]]; - if (source[2]) - dest[2] = sw32_8to16table[source[2]]; - if (source[3]) - dest[3] = sw32_8to16table[source[3]]; - if (source[4]) - dest[4] = sw32_8to16table[source[4]]; - if (source[5]) - dest[5] = sw32_8to16table[source[5]]; - if (source[6]) - dest[6] = sw32_8to16table[source[6]]; - if (source[7]) - dest[7] = sw32_8to16table[source[7]]; - - source += 128; - dest += (vid.rowbytes >> 1); - } - } - break; - case 4: - { - unsigned int *dest = (unsigned int *) vid.buffer + y * - (vid.rowbytes >> 2) + x; - - while (drawline--) { - if (source[0]) - dest[0] = d_8to24table[source[0]]; - if (source[1]) - dest[1] = d_8to24table[source[1]]; - if (source[2]) - dest[2] = d_8to24table[source[2]]; - if (source[3]) - dest[3] = d_8to24table[source[3]]; - if (source[4]) - dest[4] = d_8to24table[source[4]]; - if (source[5]) - dest[5] = d_8to24table[source[5]]; - if (source[6]) - dest[6] = d_8to24table[source[6]]; - if (source[7]) - dest[7] = d_8to24table[source[7]]; - - source += 128; - dest += (vid.rowbytes >> 2); - } - } - break; - default: - Sys_Error("Draw_Character: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} - -void -sw32_Draw_String (int x, int y, const char *str) -{ - while (*str) { - sw32_Draw_Character (x, y, *str++); - x += 8; - } -} - -void -sw32_Draw_nString (int x, int y, const char *str, int count) -{ - while (count-- && *str) { - sw32_Draw_Character (x, y, *str++); - x += 8; - } -} - - -void -sw32_Draw_AltString (int x, int y, const char *str) -{ - while (*str) { - sw32_Draw_Character (x, y, (*str++) | 0x80); - x += 8; - } -} - - -static void -Draw_Pixel (int x, int y, byte color) -{ - switch(sw32_ctx->pixbytes) - { - case 1: - ((byte *) vid.buffer)[y * vid.rowbytes + x] = color; - break; - case 2: - ((unsigned short *) vid.buffer)[y * (vid.rowbytes >> 1) + x] = - sw32_8to16table[color]; - break; - case 4: - ((unsigned int *) vid.buffer)[y * (vid.rowbytes >> 2) + x] = - d_8to24table[color]; - break; - default: - Sys_Error("Draw_Pixel: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} - -static void -crosshair_1 (int x, int y) -{ - sw32_Draw_Character (x - 4, y - 4, '+'); -} - -static void -crosshair_2 (int x, int y) -{ - byte c = crosshaircolor->int_val; - - Draw_Pixel (x - 1, y, c); - Draw_Pixel (x - 3, y, c); - Draw_Pixel (x + 1, y, c); - Draw_Pixel (x + 3, y, c); - Draw_Pixel (x, y - 1, c); - Draw_Pixel (x, y - 3, c); - Draw_Pixel (x, y + 1, c); - Draw_Pixel (x, y + 3, c); -} - -static void -crosshair_3 (int x, int y) -{ - byte c = crosshaircolor->int_val; - - Draw_Pixel (x - 3, y - 3, c); - Draw_Pixel (x + 3, y - 3, c); - Draw_Pixel (x - 2, y - 2, c); - Draw_Pixel (x + 2, y - 2, c); - Draw_Pixel (x - 3, y + 3, c); - Draw_Pixel (x + 2, y + 2, c); - Draw_Pixel (x - 2, y + 2, c); - Draw_Pixel (x + 3, y + 3, c); -} - -static void -crosshair_4 (int x, int y) -{ - //byte c = crosshaircolor->int_val; - - Draw_Pixel (x, y - 2, 8); - Draw_Pixel (x + 1, y - 2, 9); - - Draw_Pixel (x, y - 1, 6); - Draw_Pixel (x + 1, y - 1, 8); - Draw_Pixel (x + 2, y - 1, 2); - - Draw_Pixel (x - 2, y, 6); - Draw_Pixel (x - 1, y, 8); - Draw_Pixel (x, y, 8); - Draw_Pixel (x + 1, y, 6); - Draw_Pixel (x + 2, y, 8); - Draw_Pixel (x + 3, y, 8); - - Draw_Pixel (x - 1, y + 1, 2); - Draw_Pixel (x, y + 1, 8); - Draw_Pixel (x + 1, y + 1, 8); - Draw_Pixel (x + 2, y + 1, 2); - Draw_Pixel (x + 3, y + 1, 2); - Draw_Pixel (x + 4, y + 1, 2); - - Draw_Pixel (x, y + 2, 7); - Draw_Pixel (x + 1, y + 2, 8); - Draw_Pixel (x + 2, y + 2, 2); - - Draw_Pixel (x + 1, y + 3, 2); - Draw_Pixel (x + 2, y + 3, 2); -} - -static void -crosshair_5 (int x, int y) -{ - byte c = crosshaircolor->int_val; - - Draw_Pixel (x - 1, y - 3, c); - Draw_Pixel (x + 0, y - 3, c); - Draw_Pixel (x + 1, y - 3, c); - - Draw_Pixel (x - 2, y - 2, c); - Draw_Pixel (x + 2, y - 2, c); - - Draw_Pixel (x - 3, y - 1, c); - Draw_Pixel (x + 3, y - 1, c); - - Draw_Pixel (x - 3, y, c); - Draw_Pixel (x, y, c); - Draw_Pixel (x + 3, y, c); - - Draw_Pixel (x - 3, y + 1, c); - Draw_Pixel (x + 3, y + 1, c); - - Draw_Pixel (x - 2, y + 2, c); - Draw_Pixel (x + 2, y + 2, c); - - Draw_Pixel (x - 1, y + 3, c); - Draw_Pixel (x + 0, y + 3, c); - Draw_Pixel (x + 1, y + 3, c); -} - -static void (*crosshair_func[]) (int x, int y) = { - crosshair_1, - crosshair_2, - crosshair_3, - crosshair_4, - crosshair_5, -}; - -void -sw32_Draw_Crosshair (void) -{ - int x, y; - int ch; - - ch = crosshair->int_val - 1; - if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) - return; - - x = vid.conview->xlen / 2 + cl_crossx->int_val; - y = vid.conview->ylen / 2 + cl_crossy->int_val; - - crosshair_func[ch] (x, y); -} - -void -sw32_Draw_CrosshairAt (int ch, int x, int y) -{ - ch -= 1; - if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) - return; - - crosshair_func[ch] (x, y); -} - -void -sw32_Draw_Pic (int x, int y, qpic_t *pic) -{ - byte *source, tbyte; - int v, u; - - if (x < 0 || (x + pic->width) > vid.conview->xlen - || y < 0 || (y + pic->height) > vid.conview->ylen) { - Sys_MaskPrintf (SYS_vid, "Draw_Pic: bad coordinates"); - sw32_Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); - return; - } - - source = pic->data; - - switch(sw32_ctx->pixbytes) { - case 1: - { - byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; - - if (pic->width & 7) { // general - for (v = 0; v < pic->height; v++) { - for (u = 0; u < pic->width; u++) - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = tbyte; - - dest += vid.rowbytes; - source += pic->width; - } - } else { // unwound - for (v = 0; v < pic->height; v++) { - for (u = 0; u < pic->width; u += 8) { - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = tbyte; - if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR) - dest[u + 1] = tbyte; - if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR) - dest[u + 2] = tbyte; - if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR) - dest[u + 3] = tbyte; - if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR) - dest[u + 4] = tbyte; - if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR) - dest[u + 5] = tbyte; - if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR) - dest[u + 6] = tbyte; - if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) - dest[u + 7] = tbyte; - } - dest += vid.rowbytes; - source += pic->width; - } - } - } - break; - case 2: - { - unsigned short *dest = (unsigned short *) vid.buffer + y * - (vid.rowbytes >> 1) + x; - - for (v = 0; v < pic->height; v++) { - for (u = 0; u < pic->width; u++) { - tbyte = source[u]; - if (tbyte != TRANSPARENT_COLOR) - dest[u] = sw32_8to16table[tbyte]; - } - - dest += vid.rowbytes >> 1; - source += pic->width; - } - } - break; - case 4: - { - unsigned int *dest = (unsigned int *) vid.buffer + y * - (vid.rowbytes >> 2) + x; - for (v = 0; v < pic->height; v++) { - for (u = 0; u < pic->width; u++) { - tbyte = source[u]; - if (tbyte != TRANSPARENT_COLOR) - dest[u] = d_8to24table[tbyte]; - } - dest += vid.rowbytes >> 2; - source += pic->width; - } - } - break; - default: - Sys_Error("Draw_Pic: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} - -void -sw32_Draw_Picf (float x, float y, qpic_t *pic) -{ - sw32_Draw_Pic (x, y, pic); -} - -void -sw32_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, - int height) -{ - byte *source, tbyte; - int v, u; - - if ((x < 0) || (x + width > vid.conview->xlen) - || (y < 0) || (y + height > vid.conview->ylen)) { - Sys_MaskPrintf (SYS_vid, "Draw_SubPic: bad coordinates"); - } - // first, clip to screen - if (x < 0) { - srcx += x; - width += x; - x = 0; - } - if ((unsigned) (x + width) > vid.width) - width = vid.width - x; - if (width <= 0) - return; - if (y < 0) { - srcy += y; - height += y; - y = 0; - } - if ((unsigned) (y + height) > vid.height) - height = vid.height - y; - if (height <= 0) - return; - // next, clip to pic - CLIP (srcx, srcy, width, height, pic->width, pic->height); - - source = pic->data + srcy * pic->width + srcx; - - switch (sw32_ctx->pixbytes) { - case 1: - { - byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; - - for (v = 0; v < height; v++) { - for (u = 0; u < width; u++) - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = tbyte; - dest += vid.rowbytes; - source += pic->width; - } - } - break; - case 2: - { - unsigned short *dest = (unsigned short *) vid.buffer + y * - (vid.rowbytes >> 1) + x; - for (v = 0; v < height; v++, dest += vid.rowbytes >> 1, - source += pic->width) - for (u = 0; u < width; u++) - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = sw32_8to16table[tbyte]; - } - break; - case 4: - { - unsigned int *dest = (unsigned int *) vid.buffer + y * - (vid.rowbytes >> 2) + x; - for (v = 0; v < height; v++, dest += vid.rowbytes >> 2, - source += pic->width) - for (u = 0; u < width; u++) - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = d_8to24table[tbyte]; - } - break; - default: - Sys_Error("Draw_SubPic: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} - - -void -sw32_Draw_ConsoleBackground (int lines, byte alpha) -{ - int x, y, v; - byte *src; - int f, fstep; - qpic_t *conback; - - conback = sw32_Draw_CachePic ("gfx/conback.lmp", true); - - // draw the pic - switch(sw32_ctx->pixbytes) { - case 1: - { - byte *dest = vid.buffer; - - for (y = 0; y < lines; y++, dest += vid.rowbytes) { - v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; - src = conback->data + v * 320; - if (vid.conview->xlen == 320) - memcpy (dest, src, vid.conview->xlen); - else { - f = 0; - fstep = 320 * 0x10000 / vid.conview->xlen; - for (x = 0; x < vid.conview->xlen; x += 4) { - dest[x] = src[f >> 16]; - f += fstep; - dest[x + 1] = src[f >> 16]; - f += fstep; - dest[x + 2] = src[f >> 16]; - f += fstep; - dest[x + 3] = src[f >> 16]; - f += fstep; - } - } - } - } - break; - case 2: - { - unsigned short *dest = (unsigned short *) vid.buffer; - - for (y = 0; y < lines; y++, dest += (vid.rowbytes >> 1)) { - // FIXME: pre-expand to native format? - // FIXME: does the endian switching go away in production? - v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; - src = conback->data + v * 320; - f = 0; - fstep = 320 * 0x10000 / vid.conview->xlen; - for (x = 0; x < vid.conview->xlen; x += 4) { - dest[x] = sw32_8to16table[src[f >> 16]]; - f += fstep; - dest[x + 1] = sw32_8to16table[src[f >> 16]]; - f += fstep; - dest[x + 2] = sw32_8to16table[src[f >> 16]]; - f += fstep; - dest[x + 3] = sw32_8to16table[src[f >> 16]]; - f += fstep; - } - } - } - break; - case 4: - { - unsigned int *dest = (unsigned int *) vid.buffer; - for (y = 0; y < lines; y++, dest += (vid.rowbytes >> 2)) { - v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; - src = conback->data + v * 320; - f = 0; - fstep = 320 * 0x10000 / vid.conview->xlen; - for (x = 0; x < vid.conview->xlen; x += 4) { - dest[x ] = d_8to24table[src[f >> 16]];f += fstep; - dest[x + 1] = d_8to24table[src[f >> 16]];f += fstep; - dest[x + 2] = d_8to24table[src[f >> 16]];f += fstep; - dest[x + 3] = d_8to24table[src[f >> 16]];f += fstep; - } - } - } - break; - - default: - Sys_Error("Draw_ConsoleBackground: unsupported r_pixbytes %i", - sw32_ctx->pixbytes); - } - -// if (!cls.download) - int len = strlen (cl_verstring->string); - sw32_Draw_AltString (vid.conview->xlen - len * 8 - 11, - lines - 14, cl_verstring->string); -} - -static void -R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) -{ - switch(sw32_ctx->pixbytes) { - case 1: - { - byte t; - int i, j, srcdelta, destdelta; - byte *pdest; - - pdest = (byte *) vid.buffer + prect->y * vid.rowbytes + prect->x; - - srcdelta = rowbytes - prect->width; - destdelta = vid.rowbytes - prect->width; - - if (transparent) - { - for (i = 0; i < prect->height; i++) - { - for (j = 0; j < prect->width; j++) - { - t = *psrc; - if (t != TRANSPARENT_COLOR) - *pdest = t; - psrc++; - pdest++; - } - - psrc += srcdelta; - pdest += destdelta; - } - } - else - { - for (i = 0; i < prect->height; i++) - { - memcpy (pdest, psrc, prect->width); - psrc += rowbytes; - pdest += vid.rowbytes; - } - } - } - break; - case 2: - { - int i, j, srcdelta, destdelta; - unsigned short *pdest; - - pdest = (unsigned short *) vid.buffer + - (prect->y * (vid.rowbytes >> 1)) + prect->x; - - srcdelta = rowbytes - prect->width; - destdelta = (vid.rowbytes >> 1) - prect->width; - - if (transparent) { - for (i = 0; i < prect->height; i++) - { - j = prect->width; - while(j >= 8) - { - j -= 8; - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = sw32_8to16table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = sw32_8to16table[psrc[1]]; - if (psrc[2] != TRANSPARENT_COLOR) - pdest[2] = sw32_8to16table[psrc[2]]; - if (psrc[3] != TRANSPARENT_COLOR) - pdest[3] = sw32_8to16table[psrc[3]]; - if (psrc[4] != TRANSPARENT_COLOR) - pdest[4] = sw32_8to16table[psrc[4]]; - if (psrc[5] != TRANSPARENT_COLOR) - pdest[5] = sw32_8to16table[psrc[5]]; - if (psrc[6] != TRANSPARENT_COLOR) - pdest[6] = sw32_8to16table[psrc[6]]; - if (psrc[7] != TRANSPARENT_COLOR) - pdest[7] = sw32_8to16table[psrc[7]]; - psrc += 8; - pdest += 8; - } - if (j & 4) - { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = sw32_8to16table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = sw32_8to16table[psrc[1]]; - if (psrc[2] != TRANSPARENT_COLOR) - pdest[2] = sw32_8to16table[psrc[2]]; - if (psrc[3] != TRANSPARENT_COLOR) - pdest[3] = sw32_8to16table[psrc[3]]; - psrc += 4; - pdest += 4; - } - if (j & 2) - { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = sw32_8to16table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = sw32_8to16table[psrc[1]]; - psrc += 2; - pdest += 2; - } - if (j & 1) - { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = sw32_8to16table[psrc[0]]; - psrc++; - pdest++; - } - - psrc += srcdelta; - pdest += destdelta; - } - } else { - for (i = 0; i < prect->height; i++, psrc += srcdelta, - pdest += destdelta) - { - j = prect->width; - while(j >= 8) - { - j -= 8; - pdest[0] = sw32_8to16table[psrc[0]]; - pdest[1] = sw32_8to16table[psrc[1]]; - pdest[2] = sw32_8to16table[psrc[2]]; - pdest[3] = sw32_8to16table[psrc[3]]; - pdest[4] = sw32_8to16table[psrc[4]]; - pdest[5] = sw32_8to16table[psrc[5]]; - pdest[6] = sw32_8to16table[psrc[6]]; - pdest[7] = sw32_8to16table[psrc[7]]; - psrc += 8; - pdest += 8; - } - if (j & 4) - { - pdest[0] = sw32_8to16table[psrc[0]]; - pdest[1] = sw32_8to16table[psrc[1]]; - pdest[2] = sw32_8to16table[psrc[2]]; - pdest[3] = sw32_8to16table[psrc[3]]; - psrc += 4; - pdest += 4; - } - if (j & 2) - { - pdest[0] = sw32_8to16table[psrc[0]]; - pdest[1] = sw32_8to16table[psrc[1]]; - psrc += 2; - pdest += 2; - } - if (j & 1) - { - pdest[0] = sw32_8to16table[psrc[0]]; - psrc++; - pdest++; - } - } - } - } - break; - case 4: - { - int i, j, srcdelta, destdelta; - int *pdest; - - pdest = (int *) vid.buffer + prect->y * (vid.rowbytes >> 2) + prect->x; - - srcdelta = rowbytes - prect->width; - destdelta = (vid.rowbytes >> 2) - prect->width; - - if (transparent) - { - for (i = 0; i < prect->height; i++) - { - j = prect->width; - while(j >= 8) - { - j -= 8; - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to24table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = d_8to24table[psrc[1]]; - if (psrc[2] != TRANSPARENT_COLOR) - pdest[2] = d_8to24table[psrc[2]]; - if (psrc[3] != TRANSPARENT_COLOR) - pdest[3] = d_8to24table[psrc[3]]; - if (psrc[4] != TRANSPARENT_COLOR) - pdest[4] = d_8to24table[psrc[4]]; - if (psrc[5] != TRANSPARENT_COLOR) - pdest[5] = d_8to24table[psrc[5]]; - if (psrc[6] != TRANSPARENT_COLOR) - pdest[6] = d_8to24table[psrc[6]]; - if (psrc[7] != TRANSPARENT_COLOR) - pdest[7] = d_8to24table[psrc[7]]; - psrc += 8; - pdest += 8; - } - if (j & 4) - { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to24table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = d_8to24table[psrc[1]]; - if (psrc[2] != TRANSPARENT_COLOR) - pdest[2] = d_8to24table[psrc[2]]; - if (psrc[3] != TRANSPARENT_COLOR) - pdest[3] = d_8to24table[psrc[3]]; - psrc += 4; - pdest += 4; - } - if (j & 2) - { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to24table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = d_8to24table[psrc[1]]; - psrc += 2; - pdest += 2; - } - if (j & 1) - { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to24table[psrc[0]]; - psrc++; - pdest++; - } - - psrc += srcdelta; - pdest += destdelta; - } - } - else - { - for (i = 0; i < prect->height; i++, psrc += srcdelta, - pdest += destdelta) - { - j = prect->width; - while(j >= 8) - { - j -= 8; - pdest[0] = d_8to24table[psrc[0]]; - pdest[1] = d_8to24table[psrc[1]]; - pdest[2] = d_8to24table[psrc[2]]; - pdest[3] = d_8to24table[psrc[3]]; - pdest[4] = d_8to24table[psrc[4]]; - pdest[5] = d_8to24table[psrc[5]]; - pdest[6] = d_8to24table[psrc[6]]; - pdest[7] = d_8to24table[psrc[7]]; - psrc += 8; - pdest += 8; - } - if (j & 4) - { - pdest[0] = d_8to24table[psrc[0]]; - pdest[1] = d_8to24table[psrc[1]]; - pdest[2] = d_8to24table[psrc[2]]; - pdest[3] = d_8to24table[psrc[3]]; - psrc += 4; - pdest += 4; - } - if (j & 2) - { - pdest[0] = d_8to24table[psrc[0]]; - pdest[1] = d_8to24table[psrc[1]]; - psrc += 2; - pdest += 2; - } - if (j & 1) - { - pdest[0] = d_8to24table[psrc[0]]; - psrc++; - pdest++; - } - } - } - } - break; - default: - Sys_Error("R_DrawRect: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} - -/* - Draw_TileClear - - This repeats a 64*64 tile graphic to fill the screen around a sized down - refresh window. -*/ -void -sw32_Draw_TileClear (int x, int y, int w, int h) -{ - int width, height, tileoffsetx, tileoffsety; - byte *psrc; - vrect_t vr; - - CLIP (x, y, w, h, (int) vid.width, (int) vid.height); - - r_rectdesc.rect.x = x; - r_rectdesc.rect.y = y; - r_rectdesc.rect.width = w; - r_rectdesc.rect.height = h; - - vr.y = r_rectdesc.rect.y; - height = r_rectdesc.rect.height; - - tileoffsety = vr.y % r_rectdesc.height; - - while (height > 0) { - vr.x = r_rectdesc.rect.x; - width = r_rectdesc.rect.width; - - if (tileoffsety != 0) - vr.height = r_rectdesc.height - tileoffsety; - else - vr.height = r_rectdesc.height; - - if (vr.height > height) - vr.height = height; - - tileoffsetx = vr.x % r_rectdesc.width; - - while (width > 0) { - if (tileoffsetx != 0) - vr.width = r_rectdesc.width - tileoffsetx; - else - vr.width = r_rectdesc.width; - - if (vr.width > width) - vr.width = width; - - psrc = r_rectdesc.ptexbytes + - (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx; - - R_DrawRect (&vr, r_rectdesc.rowbytes, psrc, 0); - - vr.x += vr.width; - width -= vr.width; - tileoffsetx = 0; // only the left tile can be left-clipped - } - - vr.y += vr.height; - height -= vr.height; - tileoffsety = 0; // only the top tile can be top-clipped - } -} - - -/* - Draw_Fill - - Fills a box of pixels with a single color -*/ -void -sw32_Draw_Fill (int x, int y, int w, int h, int c) -{ - int u, v; - - if (x < 0 || x + w > vid.conview->xlen - || y < 0 || y + h > vid.conview->ylen) { - Sys_MaskPrintf (SYS_vid, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", - x, y, w, h, c); - } - CLIP (x, y, w, h, (int) vid.width, (int) vid.height); - - switch (sw32_ctx->pixbytes) { - case 1: - { - byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; - for (v = 0; v < h; v++, dest += vid.rowbytes) - for (u = 0; u < w; u++) - dest[u] = c; - } - break; - case 2: - { - unsigned short *dest = (unsigned short *) vid.buffer + y * - (vid.rowbytes >> 1) + x; - c = sw32_8to16table[c]; - for (v = 0; v < h; v++, dest += (vid.rowbytes >> 1)) - for (u = 0; u < w; u++) - dest[u] = c; - } - break; - case 4: - { - unsigned int *dest = (unsigned int *) vid.buffer + y * - (vid.rowbytes >> 2) + x; - c = d_8to24table[c]; - for (v = 0; v < h; v++, dest += (vid.rowbytes >> 2)) - for (u = 0; u < w; u++) - dest[u] = c; - } - break; - default: - Sys_Error("Draw_Fill: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } -} - - -void -sw32_Draw_FadeScreen (void) -{ - int x, y; - - S_ExtraUpdate (); - - switch(sw32_ctx->pixbytes) { - case 1: - { - for (y = 0; y < vid.conview->ylen; y++) { - unsigned int t; - byte *pbuf = (byte *) ((byte *) vid.buffer + vid.rowbytes * y); - t = (y & 1) << 1; - - for (x = 0; x < vid.conview->xlen; x++) { - if ((x & 3) != t) - pbuf[x] = 0; - } - } - } - break; - case 2: - { - for (y = 0; y < vid.conview->ylen; y++) { - unsigned short *pbuf = (unsigned short *) - ((byte *) vid.buffer + vid.rowbytes * y); - pbuf = (unsigned short *) vid.buffer + (vid.rowbytes >> 1) * y; - for (x = 0; x < vid.conview->xlen; x++) - pbuf[x] = (pbuf[x] >> 1) & 0x7BEF; - } - } - break; - case 4: - { - for (y = 0; y < vid.conview->ylen; y++) { - unsigned int *pbuf = (unsigned int *) - ((byte *) vid.buffer + vid.rowbytes * y); - for (x = 0; x < vid.conview->xlen; x++) - pbuf[x] = (pbuf[x] >> 1) & 0x7F7F7F7F; - } - } - break; - default: - Sys_Error("Draw_FadeScreen: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } - vr_data.scr_copyeverything = 1; - - S_ExtraUpdate (); -} - -void -sw32_Draw_BlendScreen (quat_t color) -{ - int r, g, b, i; - const byte *basepal; - byte *newpal; - byte pal[768]; - - switch(sw32_ctx->pixbytes) { - case 1: - { - basepal = vid.basepal; - newpal = pal; - - for (i = 0; i < 256; i++) { - r = basepal[0]; - g = basepal[1]; - b = basepal[2]; - basepal += 3; - - r += (int) (color[3] * (color[0] * 256 - r)); - g += (int) (color[3] * (color[1] * 256 - g)); - b += (int) (color[3] * (color[2] * 256 - b)); - - newpal[0] = vid.gammatable[r]; - newpal[1] = vid.gammatable[g]; - newpal[2] = vid.gammatable[b]; - newpal += 3; - } - vid.vid_internal->set_palette (vid.vid_internal->data, pal); - } - break; - case 2: - { - int g1, g2; - unsigned x, y; - unsigned short rramp[32], gramp[64], bramp[32], *temp; - for (i = 0; i < 32; i++) { - r = i << 3; - g1 = i << 3; - g2 = g1 + 4; - b = i << 3; - - r += (int) (color[3] * (color[0] * 256 - r)); - g1 += (int) (color[3] * (color[1] - g1)); - g2 += (int) (color[3] * (color[1] - g2)); - b += (int) (color[3] * (color[2] - b)); - - rramp[i] = (vid.gammatable[r] << 8) & 0xF800; - gramp[i*2+0] = (vid.gammatable[g1] << 3) & 0x07E0; - gramp[i*2+1] = (vid.gammatable[g2] << 3) & 0x07E0; - bramp[i] = (vid.gammatable[b] >> 3) & 0x001F; - } - temp = vid.buffer; - for (y = 0;y < vid.height;y++, temp += (vid.rowbytes >> 1)) - for (x = 0;x < vid.width;x++) - temp[x] = rramp[(temp[x] & 0xF800) >> 11] - + gramp[(temp[x] & 0x07E0) >> 5] + bramp[temp[x] & 0x001F]; - } - break; - case 4: - { - unsigned x, y; - - byte ramp[256][4], *temp; - for (i = 0; i < 256; i++) { - r = i; - g = i; - b = i; - - r += (int) (color[3] * (color[0] * 256 - r)); - g += (int) (color[3] * (color[1] * 256 - g)); - b += (int) (color[3] * (color[2] * 256 - b)); - - ramp[i][0] = vid.gammatable[r]; - ramp[i][1] = vid.gammatable[g]; - ramp[i][2] = vid.gammatable[b]; - ramp[i][3] = 0; - } - temp = vid.buffer; - for (y = 0; y < vid.height; y++, temp += vid.rowbytes) - { - for (x = 0;x < vid.width;x++) - { - temp[x*4+0] = ramp[temp[x*4+0]][0]; - temp[x*4+1] = ramp[temp[x*4+1]][1]; - temp[x*4+2] = ramp[temp[x*4+2]][2]; - temp[x*4+3] = 0; - } - } - } - break; - default: - Sys_Error("sw32_Draw_BlendScreen: unsupported r_pixbytes %i", - sw32_ctx->pixbytes); - } -} diff --git a/libs/video/renderer/sw32/namehack.h b/libs/video/renderer/sw32/namehack.h deleted file mode 100644 index ff78b73b6..000000000 --- a/libs/video/renderer/sw32/namehack.h +++ /dev/null @@ -1,473 +0,0 @@ -#ifdef NH_DEFINE -#undef NH_DEFINE -#define D_CacheSurface sw32_D_CacheSurface -#define D_DrawParticle sw32_D_DrawParticle -#define D_DrawPoly sw32_D_DrawPoly -#define D_DrawSkyScans sw32_D_DrawSkyScans -#define D_DrawSpans sw32_D_DrawSpans -#define D_DrawSprite sw32_D_DrawSprite -#define D_DrawSurfaces sw32_D_DrawSurfaces -#define D_DrawZPoint sw32_D_DrawZPoint -#define D_DrawZSpans sw32_D_DrawZSpans -#define D_FillRect sw32_D_FillRect -#define D_FlushCaches sw32_D_FlushCaches -#define D_Init sw32_D_Init -#define D_InitCaches sw32_D_InitCaches -#define D_MipLevelForScale sw32_D_MipLevelForScale -#define D_PolysetCalcGradients sw32_D_PolysetCalcGradients -#define D_PolysetDraw sw32_D_PolysetDraw -#define D_PolysetScanLeftEdge sw32_D_PolysetScanLeftEdge -#define D_PolysetSetEdgeTable sw32_D_PolysetSetEdgeTable -#define D_RasterizeAliasPolySmooth sw32_D_RasterizeAliasPolySmooth -#define D_SetupFrame sw32_D_SetupFrame -#define D_SpriteDrawSpans sw32_D_SpriteDrawSpans -#define D_SurfaceCacheAddress sw32_D_SurfaceCacheAddress -#define D_SurfaceCacheForRes sw32_D_SurfaceCacheForRes -#define D_TurnZOn sw32_D_TurnZOn -#define D_UpdateRects sw32_D_UpdateRects -#define D_ViewChanged sw32_D_ViewChanged -#define D_WarpScreen sw32_D_WarpScreen -#define Draw_AltString sw32_Draw_AltString -#define Draw_BlendScreen sw32_Draw_BlendScreen -#define Draw_CachePic sw32_Draw_CachePic -#define Draw_Character sw32_Draw_Character -#define Draw_ConsoleBackground sw32_Draw_ConsoleBackground -#define Draw_Crosshair sw32_Draw_Crosshair -#define Draw_CrosshairAt sw32_Draw_CrosshairAt -#define Draw_DestroyPic sw32_Draw_DestroyPic -#define Draw_FadeScreen sw32_Draw_FadeScreen -#define Draw_Fill sw32_Draw_Fill -#define Draw_Init sw32_Draw_Init -#define Draw_MakePic sw32_Draw_MakePic -#define Draw_Pic sw32_Draw_Pic -#define Draw_PicFromWad sw32_Draw_PicFromWad -#define Draw_Picf sw32_Draw_Picf -#define Draw_String sw32_Draw_String -#define Draw_SubPic sw32_Draw_SubPic -#define Draw_TextBox sw32_Draw_TextBox -#define Draw_TileClear sw32_Draw_TileClear -#define Draw_UncachePic sw32_Draw_UncachePic -#define Draw_nString sw32_Draw_nString -#define R_AliasCheckBBox sw32_R_AliasCheckBBox -#define R_AliasClipTriangle sw32_R_AliasClipTriangle -#define R_AliasClipAndProjectFinalVert sw32_R_AliasClipAndProjectFinalVert -#define R_AliasDrawModel sw32_R_AliasDrawModel -#define R_AliasProjectFinalVert sw32_R_AliasProjectFinalVert -#define R_AliasSetUpTransform sw32_R_AliasSetUpTransform -#define R_AliasTransformAndProjectFinalVerts sw32_R_AliasTransformAndProjectFinalVerts -#define R_AliasTransformFinalVert sw32_R_AliasTransformFinalVert -#define R_AliasTransformVector sw32_R_AliasTransformVector -#define R_Alias_clip_bottom sw32_R_Alias_clip_bottom -#define R_Alias_clip_left sw32_R_Alias_clip_left -#define R_Alias_clip_right sw32_R_Alias_clip_right -#define R_Alias_clip_top sw32_R_Alias_clip_top -#define R_IQMDrawModel sw32_R_IQMDrawModel -#define R_BeginEdgeFrame sw32_R_BeginEdgeFrame -#define R_ClearState sw32_R_ClearState -#define R_ClipEdge sw32_R_ClipEdge -#define R_DrawParticles sw32_R_DrawParticles -#define R_DrawSolidClippedSubmodelPolygons sw32_R_DrawSolidClippedSubmodelPolygons -#define R_DrawSprite sw32_R_DrawSprite -#define R_DrawSubmodelPolygons sw32_R_DrawSubmodelPolygons -#define R_DrawSurface sw32_R_DrawSurface -#define R_EmitEdge sw32_R_EmitEdge -#define R_GenerateSpans sw32_R_GenerateSpans -#define R_InitParticles sw32_R_InitParticles -#define R_InitSky sw32_R_InitSky -#define R_InitTurb sw32_R_InitTurb -#define R_InsertNewEdges sw32_R_InsertNewEdges -#define R_LineGraph sw32_R_LineGraph -#define R_LoadSky_f sw32_R_LoadSky_f -#define R_LoadSkys sw32_R_LoadSkys -#define R_MakeSky sw32_R_MakeSky -#define R_NewMap sw32_R_NewMap -#define R_Particle_New sw32_R_Particle_New -#define R_Particle_NewRandom sw32_R_Particle_NewRandom -#define R_Particles_Init_Cvars sw32_R_Particles_Init_Cvars -#define R_PrintAliasStats sw32_R_PrintAliasStats -#define R_PrintTimes sw32_R_PrintTimes -#define R_ReadPointFile_f sw32_R_ReadPointFile_f -#define R_RemoveEdges sw32_R_RemoveEdges -#define R_RenderBmodelFace sw32_R_RenderBmodelFace -#define R_RenderFace sw32_R_RenderFace -#define R_RenderPoly sw32_R_RenderPoly -#define R_RenderView sw32_R_RenderView -#define R_RenderWorld sw32_R_RenderWorld -#define R_RotateBmodel sw32_R_RotateBmodel -#define R_ScanEdges sw32_R_ScanEdges -#define R_SetSkyFrame sw32_R_SetSkyFrame -#define R_SetupFrame sw32_R_SetupFrame -#define R_StepActiveU sw32_R_StepActiveU -#define R_Textures_Init sw32_R_Textures_Init -#define R_TimeRefresh_f sw32_R_TimeRefresh_f -#define R_TransformFrustum sw32_R_TransformFrustum -#define R_TransformPlane sw32_R_TransformPlane -#define R_ViewChanged sw32_R_ViewChanged -#define R_ZDrawSubmodelPolys sw32_R_ZDrawSubmodelPolys -#define SCR_ScreenShot sw32_SCR_ScreenShot -#define SCR_ScreenShot_f sw32_SCR_ScreenShot_f -#define R_RenderFrame sw32_R_RenderFrame -#define TransformVector sw32_TransformVector -#define Turbulent sw32_Turbulent -#define acolormap sw32_acolormap -#define aliastransform sw32_aliastransform -#define aliasxcenter sw32_aliasxcenter -#define aliasxscale sw32_aliasxscale -#define aliasycenter sw32_aliasycenter -#define aliasyscale sw32_aliasyscale -#define auxedges sw32_auxedges -#define bbextents sw32_bbextents -#define bbextentt sw32_bbextentt -#define c_faceclip sw32_c_faceclip -#define c_surf sw32_c_surf -#define cacheblock sw32_cacheblock -#define cachewidth sw32_cachewidth -#define d_initial_rover sw32_d_initial_rover -#define d_minmip sw32_d_minmip -#define d_pix_max sw32_d_pix_max -#define d_pix_min sw32_d_pix_min -#define d_pix_shift sw32_d_pix_shift -#define d_pzbuffer sw32_d_pzbuffer -#define d_roverwrapped sw32_d_roverwrapped -#define d_scalemip sw32_d_scalemip -#define d_scantable sw32_d_scantable -#define d_sdivzorigin sw32_d_sdivzorigin -#define d_sdivzstepu sw32_d_sdivzstepu -#define d_sdivzstepv sw32_d_sdivzstepv -#define d_tdivzorigin sw32_d_tdivzorigin -#define d_tdivzstepu sw32_d_tdivzstepu -#define d_tdivzstepv sw32_d_tdivzstepv -#define d_viewbuffer sw32_d_viewbuffer -#define d_vrectbottom_particle sw32_d_vrectbottom_particle -#define d_vrectright_particle sw32_d_vrectright_particle -#define d_vrectx sw32_d_vrectx -#define d_vrecty sw32_d_vrecty -#define d_y_aspect_shift sw32_d_y_aspect_shift -#define d_ziorigin sw32_d_ziorigin -#define d_zistepu sw32_d_zistepu -#define d_zistepv sw32_d_zistepv -#define d_zitable sw32_d_zitable -#define d_zrowbytes sw32_d_zrowbytes -#define d_zwidth sw32_d_zwidth -#define edge_max sw32_edge_max -#define edge_p sw32_edge_p -#define insubmodel sw32_insubmodel -#define intsintable sw32_intsintable -#define newedges sw32_newedges -#define numbtofpolys sw32_numbtofpolys -#define pauxverts sw32_pauxverts -#define pfinalverts sw32_pfinalverts -#define pfrustum_indexes sw32_pfrustum_indexes -#define pixelAspect sw32_pixelAspect -#define r_affinetridesc sw32_r_affinetridesc -#define r_aliastransition sw32_r_aliastransition -#define r_aliasuvscale sw32_r_aliasuvscale -#define r_ambientlight sw32_r_ambientlight -#define r_amodels_drawn sw32_r_amodels_drawn -#define r_apverts sw32_r_apverts -#define r_ceilv1 sw32_r_ceilv1 -#define r_clipflags sw32_r_clipflags -#define r_currentbkey sw32_r_currentbkey -#define r_currentkey sw32_r_currentkey -#define r_dowarp sw32_r_dowarp -#define r_dowarpold sw32_r_dowarpold -#define r_drawculledpolys sw32_r_drawculledpolys -#define r_drawnpolycount sw32_r_drawnpolycount -#define r_drawpolys sw32_r_drawpolys -#define r_drawsurf sw32_r_drawsurf -#define r_easter_eggs_f sw32_r_easter_eggs_f -#define r_edges sw32_r_edges -#define r_emitted sw32_r_emitted -#define r_frustum_indexes sw32_r_frustum_indexes -#define r_lastvertvalid sw32_r_lastvertvalid -#define r_leftclipped sw32_r_leftclipped -#define r_leftenter sw32_r_leftenter -#define r_leftexit sw32_r_leftexit -#define r_lzi1 sw32_r_lzi1 -#define r_maxedgesseen sw32_r_maxedgesseen -#define r_maxsurfsseen sw32_r_maxsurfsseen -#define r_nearzi sw32_r_nearzi -#define r_nearzionly sw32_r_nearzionly -#define r_numallocatededges sw32_r_numallocatededges -#define r_outofedges sw32_r_outofedges -#define r_outofsurfaces sw32_r_outofsurfaces -#define r_particles_style_f sw32_r_particles_style_f -#define r_pedge sw32_r_pedge -#define r_pixbytes sw32_r_pixbytes -#define r_plightvec sw32_r_plightvec -#define r_polycount sw32_r_polycount -#define r_resfudge sw32_r_resfudge -#define r_rightclipped sw32_r_rightclipped -#define r_rightenter sw32_r_rightenter -#define r_rightexit sw32_r_rightexit -#define r_shadelight sw32_r_shadelight -#define r_skymade sw32_r_skymade -#define r_skysource sw32_r_skysource -#define r_skyspeed sw32_r_skyspeed -#define r_skytime sw32_r_skytime -#define r_spritedesc sw32_r_spritedesc -#define r_u1 sw32_r_u1 -#define r_v1 sw32_r_v1 -#define r_viewchanged sw32_r_viewchanged -#define r_warpbuffer sw32_r_warpbuffer -#define r_worldmodelorg sw32_r_worldmodelorg -#define r_worldpolysbacktofront sw32_r_worldpolysbacktofront -#define r_zpointdesc sw32_r_zpointdesc -#define removeedges sw32_removeedges -#define sadjust sw32_sadjust -#define sc_rover sw32_sc_rover -#define scale_for_mip sw32_scale_for_mip -#define screenedge sw32_screenedge -#define screenwidth sw32_screenwidth -#define sintable sw32_sintable -#define surf_max sw32_surf_max -#define surface_p sw32_surface_p -extern struct surf_s *sw32_surfaces; -//#define surfaces sw32_surfaces -#define tadjust sw32_tadjust -#define view_clipplanes sw32_view_clipplanes -#define xcenter sw32_xcenter -#define xscale sw32_xscale -#define xscaleinv sw32_xscaleinv -#define xscaleshrink sw32_xscaleshrink -#define ycenter sw32_ycenter -#define yscale sw32_yscale -#define yscaleinv sw32_yscaleinv -#define yscaleshrink sw32_yscaleshrink -#define zspantable sw32_zspantable -#else -#undef D_CacheSurface -#undef D_DrawParticle -#undef D_DrawPoly -#undef D_DrawSkyScans -#undef D_DrawSpans -#undef D_DrawSprite -#undef D_DrawSurfaces -#undef D_DrawZPoint -#undef D_DrawZSpans -#undef D_FillRect -#undef D_FlushCaches -#undef D_Init -#undef D_InitCaches -#undef D_MipLevelForScale -#undef D_PolysetCalcGradients -#undef D_PolysetDraw -#undef D_PolysetScanLeftEdge -#undef D_PolysetSetEdgeTable -#undef D_RasterizeAliasPolySmooth -#undef D_SetupFrame -#undef D_SpriteDrawSpans -#undef D_SurfaceCacheAddress -#undef D_SurfaceCacheForRes -#undef D_TurnZOn -#undef D_UpdateRects -#undef D_ViewChanged -#undef D_WarpScreen -#undef Draw_AltString -#undef Draw_BlendScreen -#undef Draw_CachePic -#undef Draw_Character -#undef Draw_ConsoleBackground -#undef Draw_Crosshair -#undef Draw_CrosshairAt -#undef Draw_DestroyPic -#undef Draw_FadeScreen -#undef Draw_Fill -#undef Draw_Init -#undef Draw_MakePic -#undef Draw_Pic -#undef Draw_PicFromWad -#undef Draw_Picf -#undef Draw_String -#undef Draw_SubPic -#undef Draw_TextBox -#undef Draw_TileClear -#undef Draw_UncachePic -#undef Draw_nString -#undef R_AliasCheckBBox -#undef R_AliasClipTriangle -#undef R_AliasClipAndProjectFinalVert -#undef R_AliasDrawModel -#undef R_AliasProjectFinalVert -#undef R_AliasSetUpTransform -#undef R_AliasTransformAndProjectFinalVerts -#undef R_AliasTransformFinalVert -#undef R_AliasTransformVector -#undef R_Alias_clip_bottom -#undef R_Alias_clip_left -#undef R_Alias_clip_right -#undef R_Alias_clip_top -#undef R_IQMDrawModel -#undef R_BeginEdgeFrame -#undef R_ClearState -#undef R_ClipEdge -#undef R_DrawParticles -#undef R_DrawSolidClippedSubmodelPolygons -#undef R_DrawSprite -#undef R_DrawSubmodelPolygons -#undef R_DrawSurface -#undef R_EmitEdge -#undef R_GenerateSpans -#undef R_Init -#undef R_InitParticles -#undef R_InitSky -#undef R_InitTurb -#undef R_InsertNewEdges -#undef R_LineGraph -#undef R_LoadSky_f -#undef R_LoadSkys -#undef R_MakeSky -#undef R_NewMap -#undef R_Particle_New -#undef R_Particle_NewRandom -#undef R_Particles_Init_Cvars -#undef R_PrintAliasStats -#undef R_PrintTimes -#undef R_ReadPointFile_f -#undef R_RemoveEdges -#undef R_RenderBmodelFace -#undef R_RenderFace -#undef R_RenderPoly -#undef R_RenderView -#undef R_RenderWorld -#undef R_RotateBmodel -#undef R_ScanEdges -#undef R_SetSkyFrame -#undef R_SetupFrame -#undef R_StepActiveU -#undef R_Textures_Init -#undef R_TimeRefresh_f -#undef R_TransformFrustum -#undef R_TransformPlane -#undef R_ViewChanged -#undef R_ZDrawSubmodelPolys -#undef SCR_CaptureBGR -#undef SCR_ScreenShot -#undef SCR_ScreenShot_f -#undef R_RenderFrame -#undef TransformVector -#undef Turbulent -#undef VID_InitBuffers -#undef VID_ShiftPalette -#undef acolormap -#undef aliasxcenter -#undef aliasxscale -#undef aliasycenter -#undef aliasyscale -#undef auxedges -#undef bbextents -#undef bbextentt -#undef c_faceclip -#undef c_surf -#undef cacheblock -#undef cachewidth -#undef d_initial_rover -#undef d_minmip -#undef d_pix_max -#undef d_pix_min -#undef d_pix_shift -#undef d_pzbuffer -#undef d_roverwrapped -#undef d_scalemip -#undef d_scantable -#undef d_sdivzorigin -#undef d_sdivzstepu -#undef d_sdivzstepv -#undef d_tdivzorigin -#undef d_tdivzstepu -#undef d_tdivzstepv -#undef d_viewbuffer -#undef d_vrectbottom_particle -#undef d_vrectright_particle -#undef d_vrectx -#undef d_vrecty -#undef d_y_aspect_shift -#undef d_zitable -#undef d_zrowbytes -#undef d_zwidth -#undef edge_max -#undef edge_p -#undef insubmodel -#undef intsintable -#undef newedges -#undef numbtofpolys -#undef pauxverts -#undef pfinalverts -#undef pfrustum_indexes -#undef pixelAspect -#undef r_affinetridesc -#undef r_aliastransition -#undef r_aliasuvscale -#undef r_ambientlight -#undef r_amodels_drawn -#undef r_apverts -#undef r_ceilv1 -#undef r_clipflags -#undef r_currentbkey -#undef r_currentkey -#undef r_dowarp -#undef r_dowarpold -#undef r_drawculledpolys -#undef r_drawnpolycount -#undef r_drawpolys -#undef r_drawsurf -#undef r_easter_eggs_f -#undef r_edges -#undef r_emitted -#undef r_frustum_indexes -#undef r_lastvertvalid -#undef r_leftclipped -#undef r_leftenter -#undef r_leftexit -#undef r_lzi1 -#undef r_maxedgesseen -#undef r_maxsurfsseen -#undef r_nearzi -#undef r_nearzionly -#undef r_numallocatededges -#undef r_outofedges -#undef r_outofsurfaces -#undef r_particles_style_f -#undef r_pedge -#undef r_pixbytes -#undef r_plightvec -#undef r_polycount -#undef r_resfudge -#undef r_rightclipped -#undef r_rightenter -#undef r_rightexit -#undef r_shadelight -#undef r_skymade -#undef r_skysource -#undef r_skyspeed -#undef r_skytime -#undef r_spritedesc -#undef r_u1 -#undef r_v1 -#undef r_viewchanged -#undef r_warpbuffer -#undef r_worldmodelorg -#undef r_worldpolysbacktofront -#undef r_zpointdesc -#undef removeedges -#undef sadjust -#undef sc_rover -#undef scale_for_mip -#undef screenedge -#undef screenwidth -#undef sintable -#undef surf_max -#undef surface_p -//#undef surfaces -#undef tadjust -#undef view_clipplanes -#undef xcenter -#undef xscale -#undef xscaleinv -#undef xscaleshrink -#undef ycenter -#undef yscale -#undef yscaleinv -#undef yscaleshrink -#undef zspantable -#endif diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c deleted file mode 100644 index 77fc155e6..000000000 --- a/libs/video/renderer/sw32/screen.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - screen.c - - master for refresh, status bar, console, chat, notify, etc - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "QF/image.h" -#include "QF/sys.h" - -#include "r_internal.h" -#include "vid_sw.h" - -/* SCREEN SHOTS */ - -tex_t * -sw32_SCR_CaptureBGR (void) -{ - int count, x, y; - tex_t *tex; - const byte *src; - byte *dst; - - count = vid.width * vid.height; - tex = malloc (sizeof (tex_t) + count * 3); - tex->data = (byte *) (tex + 1); - SYS_CHECKMEM (tex); - tex->width = vid.width; - tex->height = vid.height; - tex->format = tex_rgb; - tex->palette = 0; - src = vid.buffer; - for (y = 0; y < tex->height; y++) { - dst = tex->data + (tex->height - 1 - y) * tex->width * 3; - for (x = 0; x < tex->width; x++) { - *dst++ = vid.basepal[*src * 3 + 2]; // blue - *dst++ = vid.basepal[*src * 3 + 1]; // green - *dst++ = vid.basepal[*src * 3 + 0]; // red - src++; - } - } - return tex; -} diff --git a/libs/video/renderer/sw32/sw32_graph.c b/libs/video/renderer/sw32/sw32_graph.c deleted file mode 100644 index e5bec2a7e..000000000 --- a/libs/video/renderer/sw32/sw32_graph.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - sw32_graph.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/render.h" -#include "QF/sys.h" - -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - -/* - R_LineGraph - - Called by only R_DisplayTime -*/ -void -sw32_R_LineGraph (int x, int y, int *h_vals, int count, int height) -{ - int h, i, s, color; - - // FIXME: disable on no-buffer adapters, or put in the driver - s = height; - - while (count--) { - h = *h_vals++; - - if (h == 10000) - color = 0x6f; // yellow - else if (h == 9999) - color = 0x4f; // red - else if (h == 9998) - color = 0xd0; // blue - else - color = 0xff; // pink - - if (h > s) - h = s; - - switch(sw32_ctx->pixbytes) { - case 1: - { - byte *dest = (byte *) vid.buffer + vid.rowbytes * y + x; - for (i = 0; i < h; i++, dest -= vid.rowbytes) - *dest = color; - } - break; - case 2: - { - short *dest = (short *) vid.buffer + - (vid.rowbytes >> 1) * y + x; - color = sw32_8to16table[color]; - for (i = 0; i < h; i++, dest -= (vid.rowbytes >> 1)) - *dest = color; - } - break; - case 4: - { - int *dest = (int *) vid.buffer + - (vid.rowbytes >> 2) * y + x; - color = d_8to24table[color]; - for (i = 0; i < h; i++, dest -= (vid.rowbytes >> 2)) - *dest = color; - } - break; - default: - Sys_Error("R_LineGraph: unsupported r_pixbytes %i", - sw32_ctx->pixbytes); - } - } -} diff --git a/libs/video/renderer/sw32/sw32_raclip.c b/libs/video/renderer/sw32/sw32_raclip.c deleted file mode 100644 index 164008769..000000000 --- a/libs/video/renderer/sw32/sw32_raclip.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - r_aclip.c - - clip routines for drawing Alias models directly to the screen - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/render.h" - -#include "d_local.h" -#include "r_internal.h" - -static finalvert_t fv[2][8]; -static auxvert_t av[8]; - -/* - R_Alias_clip_z - - pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex -*/ -static void -R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) -{ - float scale; - auxvert_t *pav0, *pav1, avout; - - pav0 = &av[pfv0 - &fv[0][0]]; - pav1 = &av[pfv1 - &fv[0][0]]; - - if (pfv0->v[1] >= pfv1->v[1]) { - scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) / - (pav1->fv[2] - pav0->fv[2]); - - avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale; - avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale; - avout.fv[2] = ALIAS_Z_CLIP_PLANE; - - out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale; - out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale; - out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale; - } else { - scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) / - (pav0->fv[2] - pav1->fv[2]); - - avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale; - avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale; - avout.fv[2] = ALIAS_Z_CLIP_PLANE; - - out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale; - out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale; - out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale; - } - - sw32_R_AliasProjectFinalVert (out, &avout); - - if (out->v[0] < r_refdef.aliasvrect.x) - out->flags |= ALIAS_LEFT_CLIP; - if (out->v[1] < r_refdef.aliasvrect.y) - out->flags |= ALIAS_TOP_CLIP; - if (out->v[0] > r_refdef.aliasvrectright) - out->flags |= ALIAS_RIGHT_CLIP; - if (out->v[1] > r_refdef.aliasvrectbottom) - out->flags |= ALIAS_BOTTOM_CLIP; -} - - -void -sw32_R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) -{ - float scale; - int i; - - if (pfv0->v[1] >= pfv1->v[1]) { - scale = (float) (r_refdef.aliasvrect.x - pfv0->v[0]) / - (pfv1->v[0] - pfv0->v[0]); - for (i = 0; i < 6; i++) - out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; - } else { - scale = (float) (r_refdef.aliasvrect.x - pfv1->v[0]) / - (pfv0->v[0] - pfv1->v[0]); - for (i = 0; i < 6; i++) - out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; - } -} - - -void -sw32_R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) -{ - float scale; - int i; - - if (pfv0->v[1] >= pfv1->v[1]) { - scale = (float) (r_refdef.aliasvrectright - pfv0->v[0]) / - (pfv1->v[0] - pfv0->v[0]); - for (i = 0; i < 6; i++) - out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; - } else { - scale = (float) (r_refdef.aliasvrectright - pfv1->v[0]) / - (pfv0->v[0] - pfv1->v[0]); - for (i = 0; i < 6; i++) - out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; - } -} - - -void -sw32_R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) -{ - float scale; - int i; - - if (pfv0->v[1] >= pfv1->v[1]) { - scale = (float) (r_refdef.aliasvrect.y - pfv0->v[1]) / - (pfv1->v[1] - pfv0->v[1]); - for (i = 0; i < 6; i++) - out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; - } else { - scale = (float) (r_refdef.aliasvrect.y - pfv1->v[1]) / - (pfv0->v[1] - pfv1->v[1]); - for (i = 0; i < 6; i++) - out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; - } -} - - -void -sw32_R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) -{ - float scale; - int i; - - if (pfv0->v[1] >= pfv1->v[1]) { - scale = (float) (r_refdef.aliasvrectbottom - pfv0->v[1]) / - (pfv1->v[1] - pfv0->v[1]); - - for (i = 0; i < 6; i++) - out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; - } else { - scale = (float) (r_refdef.aliasvrectbottom - pfv1->v[1]) / - (pfv0->v[1] - pfv1->v[1]); - - for (i = 0; i < 6; i++) - out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; - } -} - - -static int -R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count, - void (*clip) (finalvert_t *pfv0, finalvert_t *pfv1, - finalvert_t *out)) -{ - int i, j, k; - int flags, oldflags; - - j = count - 1; - k = 0; - for (i = 0; i < count; j = i, i++) { - oldflags = in[j].flags & flag; - flags = in[i].flags & flag; - - if (flags && oldflags) - continue; - if (oldflags ^ flags) { - clip (&in[j], &in[i], &out[k]); - out[k].flags = 0; - if (out[k].v[0] < r_refdef.aliasvrect.x) - out[k].flags |= ALIAS_LEFT_CLIP; - if (out[k].v[1] < r_refdef.aliasvrect.y) - out[k].flags |= ALIAS_TOP_CLIP; - if (out[k].v[0] > r_refdef.aliasvrectright) - out[k].flags |= ALIAS_RIGHT_CLIP; - if (out[k].v[1] > r_refdef.aliasvrectbottom) - out[k].flags |= ALIAS_BOTTOM_CLIP; - k++; - } - if (!flags) { - out[k] = in[i]; - k++; - } - } - - return k; -} - - -void -sw32_R_AliasClipTriangle (mtriangle_t *ptri) -{ - int i, k, pingpong; - mtriangle_t mtri; - unsigned int clipflags; - - // copy vertexes and fix seam texture coordinates - if (ptri->facesfront) { - fv[0][0] = pfinalverts[ptri->vertindex[0]]; - fv[0][1] = pfinalverts[ptri->vertindex[1]]; - fv[0][2] = pfinalverts[ptri->vertindex[2]]; - } else { - for (i = 0; i < 3; i++) { - fv[0][i] = pfinalverts[ptri->vertindex[i]]; - - if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM)) - fv[0][i].v[2] += sw32_r_affinetridesc.seamfixupX16; - } - } - - // clip - clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags; - - if (clipflags & ALIAS_Z_CLIP) { - for (i = 0; i < 3; i++) - av[i] = sw32_pauxverts[ptri->vertindex[i]]; - - k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z); - if (k == 0) - return; - - pingpong = 1; - clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags; - } else { - pingpong = 0; - k = 3; - } - - if (clipflags & ALIAS_LEFT_CLIP) { - k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], - ALIAS_LEFT_CLIP, k, sw32_R_Alias_clip_left); - if (k == 0) - return; - - pingpong ^= 1; - } - - if (clipflags & ALIAS_RIGHT_CLIP) { - k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], - ALIAS_RIGHT_CLIP, k, sw32_R_Alias_clip_right); - if (k == 0) - return; - - pingpong ^= 1; - } - - if (clipflags & ALIAS_BOTTOM_CLIP) { - k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], - ALIAS_BOTTOM_CLIP, k, sw32_R_Alias_clip_bottom); - if (k == 0) - return; - - pingpong ^= 1; - } - - if (clipflags & ALIAS_TOP_CLIP) { - k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], - ALIAS_TOP_CLIP, k, sw32_R_Alias_clip_top); - if (k == 0) - return; - - pingpong ^= 1; - } - - for (i = 0; i < k; i++) { - if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x) - fv[pingpong][i].v[0] = r_refdef.aliasvrect.x; - else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright) - fv[pingpong][i].v[0] = r_refdef.aliasvrectright; - - if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y) - fv[pingpong][i].v[1] = r_refdef.aliasvrect.y; - else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom) - fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom; - - fv[pingpong][i].flags = 0; - } - - // draw triangles - mtri.facesfront = ptri->facesfront; - sw32_r_affinetridesc.ptriangles = &mtri; - sw32_r_affinetridesc.pfinalverts = fv[pingpong]; - - // FIXME: do all at once as trifan? - mtri.vertindex[0] = 0; - for (i = 1; i < k - 1; i++) { - mtri.vertindex[1] = i; - mtri.vertindex[2] = i + 1; - sw32_D_PolysetDraw (); - } -} diff --git a/libs/video/renderer/sw32/sw32_ralias.c b/libs/video/renderer/sw32/sw32_ralias.c deleted file mode 100644 index ae7f1350a..000000000 --- a/libs/video/renderer/sw32/sw32_ralias.c +++ /dev/null @@ -1,681 +0,0 @@ -/* - sw32_ralias.c - - routines for setting up to draw alias models - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/image.h" -#include "QF/render.h" -#include "QF/skin.h" -#include "QF/sys.h" - -#include "QF/scene/entity.h" - -#include "d_ifacea.h" -#include "r_internal.h" -#include "vid_sw.h" - -#define LIGHT_MIN 5 // lowest light value we'll allow, to - // avoid the need for inner-loop light - // clamping - -affinetridesc_t sw32_r_affinetridesc; - -void *sw32_acolormap; // FIXME: should go away - -trivertx_t *sw32_r_apverts; - -// TODO: these probably will go away with optimized rasterization -static mdl_t *pmdl; -vec3_t sw32_r_plightvec; -int sw32_r_ambientlight; -float sw32_r_shadelight; -static aliashdr_t *paliashdr; -finalvert_t *sw32_pfinalverts; -auxvert_t *sw32_pauxverts; -float sw32_ziscale; -static model_t *pmodel; - -static vec3_t alias_forward, alias_right, alias_up; - -static maliasskindesc_t *pskindesc; - -int sw32_r_amodels_drawn; -static int a_skinwidth; -static int r_anumverts; - -float sw32_aliastransform[3][4]; - -typedef struct { - int index0; - int index1; -} aedge_t; - -static aedge_t aedges[12] = { - {0, 1}, {1, 2}, {2, 3}, {3, 0}, - {4, 5}, {5, 6}, {6, 7}, {7, 4}, - {0, 5}, {1, 4}, {2, 7}, {3, 6} -}; - -qboolean -sw32_R_AliasCheckBBox (void) -{ - int i, flags, frame, numv; - aliashdr_t *pahdr; - float zi, basepts[8][3], v0, v1, frac; - finalvert_t *pv0, *pv1, viewpts[16]; - auxvert_t *pa0, *pa1, viewaux[16]; - maliasframedesc_t *pframedesc; - qboolean zclipped, zfullyclipped; - unsigned int anyclip, allclip; - int minz; - - // expand, rotate, and translate points into worldspace - currententity->visibility.trivial_accept = 0; - pmodel = currententity->renderer.model; - if (!(pahdr = pmodel->aliashdr)) - pahdr = Cache_Get (&pmodel->cache); - pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model); - - sw32_R_AliasSetUpTransform (0); - - // construct the base bounding box for this frame - frame = currententity->animation.frame; -// TODO: don't repeat this check when drawing? - if ((frame >= pmdl->numframes) || (frame < 0)) { - Sys_MaskPrintf (SYS_dev, "No such frame %d %s\n", frame, pmodel->path); - frame = 0; - } - - pframedesc = &pahdr->frames[frame]; - - // x worldspace coordinates - basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = - (float) pframedesc->bboxmin.v[0]; - basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = - (float) pframedesc->bboxmax.v[0]; - - // y worldspace coordinates - basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = - (float) pframedesc->bboxmin.v[1]; - basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = - (float) pframedesc->bboxmax.v[1]; - - // z worldspace coordinates - basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = - (float) pframedesc->bboxmin.v[2]; - basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = - (float) pframedesc->bboxmax.v[2]; - - zclipped = false; - zfullyclipped = true; - - minz = 9999; - for (i = 0; i < 8; i++) { - sw32_R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]); - - if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) { - // we must clip points that are closer than the near clip plane - viewpts[i].flags = ALIAS_Z_CLIP; - zclipped = true; - } else { - if (viewaux[i].fv[2] < minz) - minz = viewaux[i].fv[2]; - viewpts[i].flags = 0; - zfullyclipped = false; - } - } - - if (zfullyclipped) { - if (!pmodel->aliashdr) - Cache_Release (&pmodel->cache); - return false; // everything was near-z-clipped - } - - numv = 8; - - if (zclipped) { - // organize points by edges, use edges to get new points (possible - // trivial reject) - for (i = 0; i < 12; i++) { - // edge endpoints - pv0 = &viewpts[aedges[i].index0]; - pv1 = &viewpts[aedges[i].index1]; - pa0 = &viewaux[aedges[i].index0]; - pa1 = &viewaux[aedges[i].index1]; - - // if one end is clipped and the other isn't, make a new point - if (pv0->flags ^ pv1->flags) { - frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) / - (pa1->fv[2] - pa0->fv[2]); - viewaux[numv].fv[0] = pa0->fv[0] + - (pa1->fv[0] - pa0->fv[0]) * frac; - viewaux[numv].fv[1] = pa0->fv[1] + - (pa1->fv[1] - pa0->fv[1]) * frac; - viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; - viewpts[numv].flags = 0; - numv++; - } - } - } - // project the vertices that remain after clipping - anyclip = 0; - allclip = ALIAS_XY_CLIP_MASK; - -// TODO: probably should do this loop in ASM, especially if we use floats - for (i = 0; i < numv; i++) { - // we don't need to bother with vertices that were z-clipped - if (viewpts[i].flags & ALIAS_Z_CLIP) - continue; - - zi = 1.0 / viewaux[i].fv[2]; - - // FIXME: do with chop mode in ASM, or convert to float - v0 = (viewaux[i].fv[0] * sw32_xscale * zi) + sw32_xcenter; - v1 = (viewaux[i].fv[1] * sw32_yscale * zi) + sw32_ycenter; - - flags = 0; - - if (v0 < r_refdef.fvrectx) - flags |= ALIAS_LEFT_CLIP; - if (v1 < r_refdef.fvrecty) - flags |= ALIAS_TOP_CLIP; - if (v0 > r_refdef.fvrectright) - flags |= ALIAS_RIGHT_CLIP; - if (v1 > r_refdef.fvrectbottom) - flags |= ALIAS_BOTTOM_CLIP; - - anyclip |= flags; - allclip &= flags; - } - - if (allclip) { - if (!pmodel->aliashdr) - Cache_Release (&pmodel->cache); - return false; // trivial reject off one side - } - - currententity->visibility.trivial_accept = !anyclip & !zclipped; - - if (currententity->visibility.trivial_accept) { - if (minz > (sw32_r_aliastransition + (pmdl->size * sw32_r_resfudge))) { - currententity->visibility.trivial_accept |= 2; - } - } - - if (!pmodel->aliashdr) - Cache_Release (&pmodel->cache); - return true; -} - - -void -sw32_R_AliasTransformVector (vec3_t in, vec3_t out) -{ - out[0] = DotProduct (in, sw32_aliastransform[0]) - + sw32_aliastransform[0][3]; - out[1] = DotProduct (in, sw32_aliastransform[1]) - + sw32_aliastransform[1][3]; - out[2] = DotProduct (in, sw32_aliastransform[2]) - + sw32_aliastransform[2][3]; -} - - -void -sw32_R_AliasClipAndProjectFinalVert (finalvert_t *fv, auxvert_t *av) -{ - if (av->fv[2] < ALIAS_Z_CLIP_PLANE) { - fv->flags |= ALIAS_Z_CLIP; - return; - } - - sw32_R_AliasProjectFinalVert (fv, av); - - if (fv->v[0] < r_refdef.aliasvrect.x) - fv->flags |= ALIAS_LEFT_CLIP; - if (fv->v[1] < r_refdef.aliasvrect.y) - fv->flags |= ALIAS_TOP_CLIP; - if (fv->v[0] > r_refdef.aliasvrectright) - fv->flags |= ALIAS_RIGHT_CLIP; - if (fv->v[1] > r_refdef.aliasvrectbottom) - fv->flags |= ALIAS_BOTTOM_CLIP; -} - -static void -R_AliasTransformFinalVert16 (auxvert_t *av, trivertx_t *pverts) -{ - trivertx_t * pextra; - float vextra[3]; - - pextra = pverts + pmdl->numverts; - vextra[0] = pverts->v[0] + pextra->v[0] / (float)256; - vextra[1] = pverts->v[1] + pextra->v[1] / (float)256; - vextra[2] = pverts->v[2] + pextra->v[2] / (float)256; - av->fv[0] = DotProduct (vextra, sw32_aliastransform[0]) + - sw32_aliastransform[0][3]; - av->fv[1] = DotProduct (vextra, sw32_aliastransform[1]) + - sw32_aliastransform[1][3]; - av->fv[2] = DotProduct (vextra, sw32_aliastransform[2]) + - sw32_aliastransform[2][3]; -} - -static void -R_AliasTransformFinalVert8 (auxvert_t *av, trivertx_t *pverts) -{ - av->fv[0] = DotProduct (pverts->v, sw32_aliastransform[0]) + - sw32_aliastransform[0][3]; - av->fv[1] = DotProduct (pverts->v, sw32_aliastransform[1]) + - sw32_aliastransform[1][3]; - av->fv[2] = DotProduct (pverts->v, sw32_aliastransform[2]) + - sw32_aliastransform[2][3]; -} - -/* - R_AliasPreparePoints - - General clipped case -*/ -static void -R_AliasPreparePoints (void) -{ - int i; - stvert_t *pstverts; - finalvert_t *fv; - auxvert_t *av; - mtriangle_t *ptri; - finalvert_t *pfv[3]; - - pstverts = (stvert_t *) ((byte *) paliashdr + paliashdr->stverts); - r_anumverts = pmdl->numverts; - fv = pfinalverts; - av = sw32_pauxverts; - - if (pmdl->ident == HEADER_MDL16) { - for (i = 0; i < r_anumverts; i++, fv++, av++, sw32_r_apverts++, - pstverts++) { - R_AliasTransformFinalVert16 (av, sw32_r_apverts); - sw32_R_AliasTransformFinalVert (fv, sw32_r_apverts, pstverts); - R_AliasClipAndProjectFinalVert (fv, av); - } - } - else { - for (i = 0; i < r_anumverts; i++, fv++, av++, sw32_r_apverts++, - pstverts++) { - R_AliasTransformFinalVert8 (av, sw32_r_apverts); - sw32_R_AliasTransformFinalVert (fv, sw32_r_apverts, pstverts); - R_AliasClipAndProjectFinalVert (fv, av); - } - } - - // clip and draw all triangles - sw32_r_affinetridesc.numtriangles = 1; - - ptri = (mtriangle_t *) ((byte *) paliashdr + paliashdr->triangles); - for (i = 0; i < pmdl->numtris; i++, ptri++) { - pfv[0] = &pfinalverts[ptri->vertindex[0]]; - pfv[1] = &pfinalverts[ptri->vertindex[1]]; - pfv[2] = &pfinalverts[ptri->vertindex[2]]; - - if (pfv[0]->flags & pfv[1]->flags & pfv[2]-> - flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP)) - continue; // completely clipped - - if (!((pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) & - (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP))) { // totally unclipped - sw32_r_affinetridesc.pfinalverts = pfinalverts; - sw32_r_affinetridesc.ptriangles = ptri; - sw32_D_PolysetDraw (); - } else { // partially clipped - sw32_R_AliasClipTriangle (ptri); - } - } -} - - -void -sw32_R_AliasSetUpTransform (int trivial_accept) -{ - int i; - float rotationmatrix[3][4], t2matrix[3][4]; - static float tmatrix[3][4]; - static float viewmatrix[3][4]; - - mat4f_t mat; - Transform_GetWorldMatrix (currententity->transform, mat); - VectorCopy (mat[0], alias_forward); - VectorNegate (mat[1], alias_right); - VectorCopy (mat[2], alias_up); - - tmatrix[0][0] = pmdl->scale[0]; - tmatrix[1][1] = pmdl->scale[1]; - tmatrix[2][2] = pmdl->scale[2]; - - tmatrix[0][3] = pmdl->scale_origin[0]; - tmatrix[1][3] = pmdl->scale_origin[1]; - tmatrix[2][3] = pmdl->scale_origin[2]; - -// TODO: can do this with simple matrix rearrangement - - for (i = 0; i < 3; i++) { - t2matrix[i][0] = alias_forward[i]; - t2matrix[i][1] = -alias_right[i]; - t2matrix[i][2] = alias_up[i]; - } - - t2matrix[0][3] = -modelorg[0]; - t2matrix[1][3] = -modelorg[1]; - t2matrix[2][3] = -modelorg[2]; - -// FIXME: can do more efficiently than full concatenation - R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); - -// TODO: should be global, set when vright, etc., set - VectorCopy (vright, viewmatrix[0]); - VectorCopy (vup, viewmatrix[1]); - VectorNegate (viewmatrix[1], viewmatrix[1]); - VectorCopy (vpn, viewmatrix[2]); - -// viewmatrix[0][3] = 0; -// viewmatrix[1][3] = 0; -// viewmatrix[2][3] = 0; - - R_ConcatTransforms (viewmatrix, rotationmatrix, sw32_aliastransform); - -// do the scaling up of x and y to screen coordinates as part of the transform -// for the unclipped case (it would mess up clipping in the clipped case). -// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y -// correspondingly so the projected x and y come out right -// FIXME: make this work for clipped case too? - if (trivial_accept) { - for (i = 0; i < 4; i++) { - sw32_aliastransform[0][i] *= sw32_aliasxscale * - (1.0 / ((float) 0x8000 * 0x10000)); - sw32_aliastransform[1][i] *= sw32_aliasyscale * - (1.0 / ((float) 0x8000 * 0x10000)); - sw32_aliastransform[2][i] *= 1.0 / ((float) 0x8000 * 0x10000); - } - } -} - -/* -sw32_R_AliasTransformFinalVert - -now this function just copies the texture coordinates and calculates lighting -actual 3D transform is done by R_AliasTransformFinalVert8/16 functions above -*/ -void -sw32_R_AliasTransformFinalVert (finalvert_t *fv, trivertx_t *pverts, - stvert_t *pstverts) -{ - int temp; - float lightcos, *plightnormal; - - fv->v[2] = pstverts->s; - fv->v[3] = pstverts->t; - - fv->flags = pstverts->onseam; - - // lighting - // LordHavoc: flipped lightcos so it is + for bright, not - - plightnormal = r_avertexnormals[pverts->lightnormalindex]; - lightcos = -DotProduct (plightnormal, sw32_r_plightvec); - temp = sw32_r_ambientlight; - - if (lightcos > 0) { - temp += (int) (sw32_r_shadelight * lightcos); - - // clamp; because we limited the minimum ambient and shading light, - // we don't have to clamp low light, just bright - if (temp < 0) - temp = 0; - } - - fv->v[4] = temp; -} - -void -sw32_R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts) -{ - int i, temp; - float lightcos, *plightnormal, zi; - trivertx_t *pverts; - - pverts = sw32_r_apverts; - - for (i = 0; i < r_anumverts; i++, fv++, pverts++, pstverts++) { - // transform and project - zi = 1.0 / (DotProduct (pverts->v, sw32_aliastransform[2]) + - sw32_aliastransform[2][3]); - - // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is - // scaled up by 1/2**31, and the scaling cancels out for x and y in - // the projection - fv->v[5] = zi; - - fv->v[0] = ((DotProduct (pverts->v, sw32_aliastransform[0]) + - sw32_aliastransform[0][3]) * zi) + sw32_aliasxcenter; - fv->v[1] = ((DotProduct (pverts->v, sw32_aliastransform[1]) + - sw32_aliastransform[1][3]) * zi) + sw32_aliasycenter; - - fv->v[2] = pstverts->s; - fv->v[3] = pstverts->t; - fv->flags = pstverts->onseam; - - // lighting - // LordHavoc: flipped lightcos so it is + for bright, not - - plightnormal = r_avertexnormals[pverts->lightnormalindex]; - lightcos = -DotProduct (plightnormal, sw32_r_plightvec); - temp = sw32_r_ambientlight; - - if (lightcos > 0) { - temp += (int) (sw32_r_shadelight * lightcos); - - // clamp; because we limited the minimum ambient and shading - // light, we don't have to clamp low light, just bright - if (temp < 0) - temp = 0; - } - - fv->v[4] = temp; - } -} - -void -sw32_R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av) -{ - float zi; - - // project points - zi = 1.0 / av->fv[2]; - - fv->v[5] = zi * sw32_ziscale; - - fv->v[0] = (av->fv[0] * sw32_aliasxscale * zi) + sw32_aliasxcenter; - fv->v[1] = (av->fv[1] * sw32_aliasyscale * zi) + sw32_aliasycenter; -} - - -static void -R_AliasPrepareUnclippedPoints (void) -{ - stvert_t *pstverts; - - pstverts = (stvert_t *) ((byte *) paliashdr + paliashdr->stverts); - r_anumverts = pmdl->numverts; - - sw32_R_AliasTransformAndProjectFinalVerts (pfinalverts, pstverts); - - sw32_r_affinetridesc.pfinalverts = pfinalverts; - sw32_r_affinetridesc.ptriangles = (mtriangle_t *) - ((byte *) paliashdr + paliashdr->triangles); - sw32_r_affinetridesc.numtriangles = pmdl->numtris; - - sw32_D_PolysetDraw (); -} - - -static void -R_AliasSetupSkin (entity_t *ent) -{ - int skinnum; - - skinnum = ent->renderer.skinnum; - if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { - Sys_MaskPrintf (SYS_dev, "R_AliasSetupSkin: no such skin # %d\n", - skinnum); - skinnum = 0; - } - - pskindesc = R_AliasGetSkindesc (&ent->animation, skinnum, paliashdr); - a_skinwidth = pmdl->skinwidth; - - sw32_r_affinetridesc.pskin = (void *) ((byte *) paliashdr + pskindesc->skin); - sw32_r_affinetridesc.skinwidth = a_skinwidth; - sw32_r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16; - sw32_r_affinetridesc.skinheight = pmdl->skinheight; - - sw32_acolormap = vid.colormap8; - if (ent->renderer.skin) { - tex_t *base; - - base = ent->renderer.skin->texels; - if (base) { - sw32_r_affinetridesc.pskin = base->data; - sw32_r_affinetridesc.skinwidth = base->width; - sw32_r_affinetridesc.skinheight = base->height; - } - sw32_acolormap = ent->renderer.skin->colormap; - } -} - -static void -R_AliasSetupLighting (alight_t *plighting) -{ - // guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't - // have to clamp off the bottom - sw32_r_ambientlight = plighting->ambientlight; - - if (sw32_r_ambientlight < LIGHT_MIN) - sw32_r_ambientlight = LIGHT_MIN; - - sw32_r_ambientlight = (/*255 -*/ sw32_r_ambientlight) << VID_CBITS; - -// if (sw32_r_ambientlight < LIGHT_MIN) -// sw32_r_ambientlight = LIGHT_MIN; - - sw32_r_shadelight = plighting->shadelight; - - if (sw32_r_shadelight < 0) - sw32_r_shadelight = 0; - - sw32_r_shadelight *= VID_GRADES; - - // rotate the lighting vector into the model's frame of reference - sw32_r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward); - sw32_r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right); - sw32_r_plightvec[2] = DotProduct (plighting->plightvec, alias_up); -} - - -/* - R_AliasSetupFrame - - set sw32_r_apverts -*/ -static void -R_AliasSetupFrame (entity_t *ent) -{ - maliasframedesc_t *frame; - - frame = R_AliasGetFramedesc (&ent->animation, paliashdr); - sw32_r_apverts = (trivertx_t *) ((byte *) paliashdr + frame->frame); -} - - -void -sw32_R_AliasDrawModel (alight_t *plighting) -{ - entity_t *ent = currententity; - int size; - finalvert_t *finalverts; - - sw32_r_amodels_drawn++; - - if (!(paliashdr = ent->renderer.model->aliashdr)) - paliashdr = Cache_Get (&ent->renderer.model->cache); - pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model); - - size = (CACHE_SIZE - 1) - + sizeof (finalvert_t) * (pmdl->numverts + 1) - + sizeof (auxvert_t) * pmdl->numverts; - finalverts = (finalvert_t *) Hunk_TempAlloc (0, size); - if (!finalverts) - Sys_Error ("R_AliasDrawModel: out of memory"); - - // cache align - pfinalverts = (finalvert_t *) - (((intptr_t) &finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - sw32_pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1]; - - R_AliasSetupSkin (ent); - sw32_R_AliasSetUpTransform (ent->visibility.trivial_accept); - R_AliasSetupLighting (plighting); - R_AliasSetupFrame (ent); - - if (!sw32_acolormap) - sw32_acolormap = vid.colormap8; - if (sw32_acolormap == &vid.colormap8 && sw32_ctx->pixbytes != 1) - { - if (sw32_ctx->pixbytes == 2) - sw32_acolormap = vid.colormap16; - else if (sw32_ctx->pixbytes == 4) - sw32_acolormap = vid.colormap32; - else - Sys_Error("R_AliasDrawmodel: unsupported r_pixbytes %i", - sw32_ctx->pixbytes); - } - - if (ent != vr_data.view_model) - sw32_ziscale = (float) 0x8000 *(float) 0x10000; - else - sw32_ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - - if (ent->visibility.trivial_accept) { - R_AliasPrepareUnclippedPoints (); - } else { - R_AliasPreparePoints (); - } - - if (!ent->renderer.model->aliashdr) { - Cache_Release (&ent->renderer.model->cache); - } -} diff --git a/libs/video/renderer/sw32/sw32_rbsp.c b/libs/video/renderer/sw32/sw32_rbsp.c deleted file mode 100644 index 44ae8122f..000000000 --- a/libs/video/renderer/sw32/sw32_rbsp.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - sw32_r_bsp.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include -#include - -#include "qfalloca.h" - -#include "QF/render.h" -#include "QF/sys.h" - -#include "QF/scene/entity.h" - -#include "r_internal.h" - -// current entity info -qboolean sw32_insubmodel; -vec3_t sw32_r_worldmodelorg; -static float entity_rotation[3][3]; - -int sw32_r_currentbkey; - -typedef enum { touchessolid, drawnode, nodrawnode } solidstate_t; - -#define MAX_BMODEL_VERTS 500 // 6K -#define MAX_BMODEL_EDGES 1000 // 12K - -static mvertex_t *pbverts; -static bedge_t *pbedges; -static int numbverts, numbedges; - -int sw32_numbtofpolys; -static btofpoly_t *pbtofpolys; - -static mvertex_t *pfrontenter, *pfrontexit; - -static qboolean makeclippededge; - - -static void -R_EntityRotate (vec3_t vec) -{ - vec3_t tvec; - - VectorCopy (vec, tvec); - vec[0] = DotProduct (entity_rotation[0], tvec); - vec[1] = DotProduct (entity_rotation[1], tvec); - vec[2] = DotProduct (entity_rotation[2], tvec); -} - - -void -sw32_R_RotateBmodel (void) -{ - mat4f_t mat; - Transform_GetWorldMatrix (currententity->transform, mat); - VectorCopy (mat[0], entity_rotation[0]); - VectorCopy (mat[1], entity_rotation[1]); - VectorCopy (mat[2], entity_rotation[2]); - - // rotate modelorg and the transformation matrix - R_EntityRotate (modelorg); - R_EntityRotate (vpn); - R_EntityRotate (vright); - R_EntityRotate (vup); - - sw32_R_TransformFrustum (); -} - - -static void -R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) -{ - bedge_t *psideedges[2], *pnextedge, *ptedge; - int i, side, lastside; - float dist, frac, lastdist; - plane_t *splitplane, tplane; - mvertex_t *pvert, *plastvert, *ptvert; - mnode_t *pn; - - psideedges[0] = psideedges[1] = NULL; - - makeclippededge = false; - - // transform the BSP plane into model space - // FIXME: cache these? - splitplane = pnode->plane; - tplane.dist = splitplane->dist - - DotProduct (r_entorigin, splitplane->normal); - tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal); - tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal); - tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal); - - // clip edges to BSP plane - for (; pedges; pedges = pnextedge) { - pnextedge = pedges->pnext; - - // set the status for the last point as the previous point - // FIXME: cache this stuff somehow? - plastvert = pedges->v[0]; - lastdist = DotProduct (plastvert->position, tplane.normal) - - tplane.dist; - - if (lastdist > 0) - lastside = 0; - else - lastside = 1; - - pvert = pedges->v[1]; - - dist = DotProduct (pvert->position, tplane.normal) - tplane.dist; - - if (dist > 0) - side = 0; - else - side = 1; - - if (side != lastside) { - // clipped - if (numbverts >= MAX_BMODEL_VERTS) - return; - - // generate the clipped vertex - frac = lastdist / (lastdist - dist); - ptvert = &pbverts[numbverts++]; - ptvert->position[0] = plastvert->position[0] + - frac * (pvert->position[0] - plastvert->position[0]); - ptvert->position[1] = plastvert->position[1] + - frac * (pvert->position[1] - plastvert->position[1]); - ptvert->position[2] = plastvert->position[2] + - frac * (pvert->position[2] - plastvert->position[2]); - - // split into two edges, one on each side, and remember entering - // and exiting points - // FIXME: share the clip edge by having a winding direction flag? - if (numbedges >= (MAX_BMODEL_EDGES - 1)) { - Sys_Printf ("Out of edges for bmodel\n"); - return; - } - - ptedge = &pbedges[numbedges]; - ptedge->pnext = psideedges[lastside]; - psideedges[lastside] = ptedge; - ptedge->v[0] = plastvert; - ptedge->v[1] = ptvert; - - ptedge = &pbedges[numbedges + 1]; - ptedge->pnext = psideedges[side]; - psideedges[side] = ptedge; - ptedge->v[0] = ptvert; - ptedge->v[1] = pvert; - - numbedges += 2; - - if (side == 0) { - // entering for front, exiting for back - pfrontenter = ptvert; - makeclippededge = true; - } else { - pfrontexit = ptvert; - makeclippededge = true; - } - } else { - // add the edge to the appropriate side - pedges->pnext = psideedges[side]; - psideedges[side] = pedges; - } - } - - // if anything was clipped, reconstitute and add the edges along the clip - // plane to both sides (but in opposite directions) - if (makeclippededge) { - if (numbedges >= (MAX_BMODEL_EDGES - 2)) { - Sys_Printf ("Out of edges for bmodel\n"); - return; - } - - ptedge = &pbedges[numbedges]; - ptedge->pnext = psideedges[0]; - psideedges[0] = ptedge; - ptedge->v[0] = pfrontexit; - ptedge->v[1] = pfrontenter; - - ptedge = &pbedges[numbedges + 1]; - ptedge->pnext = psideedges[1]; - psideedges[1] = ptedge; - ptedge->v[0] = pfrontenter; - ptedge->v[1] = pfrontexit; - - numbedges += 2; - } - // draw or recurse further - for (i = 0; i < 2; i++) { - if (psideedges[i]) { - // draw if we've reached a non-solid leaf, done if all that's left - // is a solid leaf, and continue down the tree if it's not a leaf - pn = pnode->children[i]; - - // we're done with this branch if the node or leaf isn't in the PVS - if (pn->visframe == r_visframecount) { - if (pn->contents < 0) { - if (pn->contents != CONTENTS_SOLID) { - sw32_r_currentbkey = ((mleaf_t *) pn)->key; - sw32_R_RenderBmodelFace (psideedges[i], psurf); - } - } else { - R_RecursiveClipBPoly (psideedges[i], pnode->children[i], - psurf); - } - } - } - } -} - - -void -sw32_R_DrawSolidClippedSubmodelPolygons (model_t *model) -{ - int i, j, lindex; - vec_t dot; - msurface_t *psurf; - int numsurfaces; - plane_t *pplane; - mvertex_t bverts[MAX_BMODEL_VERTS]; - bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; - medge_t *pedge, *pedges; - mod_brush_t *brush = &model->brush; - - // FIXME: use bounding-box-based frustum clipping info? - - psurf = &brush->surfaces[brush->firstmodelsurface]; - numsurfaces = brush->nummodelsurfaces; - pedges = brush->edges; - - for (i = 0; i < numsurfaces; i++, psurf++) { - // find which side of the node we are on - pplane = psurf->plane; - - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; - - // draw the polygon - if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || - (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - // FIXME: use bounding-box-based frustum clipping info? - - // copy the edges to bedges, flipping if necessary so always - // clockwise winding - // FIXME: if edges and vertices get caches, these assignments must - // move outside the loop, and overflow checking must be done here - pbverts = bverts; - pbedges = bedges; - numbverts = numbedges = 0; - - if (psurf->numedges > 0) { - pbedge = &bedges[numbedges]; - numbedges += psurf->numedges; - - for (j = 0; j < psurf->numedges; j++) { - lindex = brush->surfedges[psurf->firstedge + j]; - - if (lindex > 0) { - pedge = &pedges[lindex]; - pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]]; - pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]]; - } else { - lindex = -lindex; - pedge = &pedges[lindex]; - pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]]; - pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]]; - } - - pbedge[j].pnext = &pbedge[j + 1]; - } - - pbedge[j - 1].pnext = NULL; // mark end of edges - - R_RecursiveClipBPoly (pbedge, - currententity->visibility.topnode, - psurf); - } else { - Sys_Error ("no edges in bmodel"); - } - } - } -} - - -void -sw32_R_DrawSubmodelPolygons (model_t *model, int clipflags) -{ - int i; - vec_t dot; - msurface_t *psurf; - int numsurfaces; - plane_t *pplane; - mod_brush_t *brush = &model->brush; - - // FIXME: use bounding-box-based frustum clipping info? - - psurf = &brush->surfaces[brush->firstmodelsurface]; - numsurfaces = brush->nummodelsurfaces; - - for (i = 0; i < numsurfaces; i++, psurf++) { - // find which side of the node we are on - pplane = psurf->plane; - - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; - - // draw the polygon - if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || - (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - sw32_r_currentkey - = ((mleaf_t *) currententity->visibility.topnode)->key; - - // FIXME: use bounding-box-based frustum clipping info? - sw32_R_RenderFace (psurf, clipflags); - } - } -} - -static inline void -visit_leaf (mleaf_t *leaf) -{ - // deal with model fragments in this leaf - if (leaf->efrags) - R_StoreEfrags (leaf->efrags); - leaf->key = sw32_r_currentkey; - sw32_r_currentkey++; // all bmodels in a leaf share the same key -} - -static inline int -get_side (mnode_t *node) -{ - // find which side of the node we are on - plane_t *plane = node->plane; - - if (plane->type < 3) - return (modelorg[plane->type] - plane->dist) < 0; - return (DotProduct (modelorg, plane->normal) - plane->dist) < 0; -} - -static void -visit_node (mod_brush_t *brush, mnode_t *node, int side, int clipflags) -{ - int c; - msurface_t *surf; - - // sneaky hack for side = side ? SURF_PLANEBACK : 0; - side = (~side + 1) & SURF_PLANEBACK; - // draw stuff - if ((c = node->numsurfaces)) { - surf = brush->surfaces + node->firstsurface; - for (; c; c--, surf++) { - if (surf->visframe != r_visframecount) - continue; - - // side is either 0 or SURF_PLANEBACK - if (side ^ (surf->flags & SURF_PLANEBACK)) - continue; // wrong side - - if (sw32_r_drawpolys) { - if (sw32_r_worldpolysbacktofront) { - if (sw32_numbtofpolys < MAX_BTOFPOLYS) { - pbtofpolys[sw32_numbtofpolys].clipflags = clipflags; - pbtofpolys[sw32_numbtofpolys].psurf = surf; - sw32_numbtofpolys++; - } - } else { - sw32_R_RenderPoly (surf, clipflags); - } - } else { - sw32_R_RenderFace (surf, clipflags); - } - } - // all surfaces on the same node share the same sequence number - sw32_r_currentkey++; - } -} - -static inline int -test_node (mnode_t *node, int *clipflags) -{ - int i, *pindex; - vec3_t acceptpt, rejectpt; - double d; - - if (node->contents < 0) - return 0; - if (node->visframe != r_visframecount) - return 0; - // cull the clipping planes if not trivial accept - // FIXME: the compiler is doing a lousy job of optimizing here; it could be - // twice as fast in ASM - if (*clipflags) { - for (i = 0; i < 4; i++) { - if (!(*clipflags & (1 << i))) - continue; // don't need to clip against it - - // generate accept and reject points - // FIXME: do with fast look-ups or integer tests based on the - // sign bit of the floating point values - - pindex = sw32_pfrustum_indexes[i]; - - rejectpt[0] = (float) node->minmaxs[pindex[0]]; - rejectpt[1] = (float) node->minmaxs[pindex[1]]; - rejectpt[2] = (float) node->minmaxs[pindex[2]]; - - d = DotProduct (rejectpt, sw32_view_clipplanes[i].normal); - d -= sw32_view_clipplanes[i].dist; - - if (d <= 0) - return 0; - - acceptpt[0] = (float) node->minmaxs[pindex[3 + 0]]; - acceptpt[1] = (float) node->minmaxs[pindex[3 + 1]]; - acceptpt[2] = (float) node->minmaxs[pindex[3 + 2]]; - - d = DotProduct (acceptpt, sw32_view_clipplanes[i].normal); - d -= sw32_view_clipplanes[i].dist; - if (d >= 0) - *clipflags &= ~(1 << i); // node is entirely on screen - } - } - return 1; -} - -static void -R_VisitWorldNodes (mod_brush_t *brush, int clipflags) -{ - typedef struct { - mnode_t *node; - int side, clipflags; - } rstack_t; - rstack_t *node_ptr; - rstack_t *node_stack; - mnode_t *node; - mnode_t *front; - int side, cf; - - node = brush->nodes; - // +2 for paranoia - node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); - node_ptr = node_stack; - - cf = clipflags; - while (1) { - while (test_node (node, &cf)) { - cf = clipflags; - side = get_side (node); - front = node->children[side]; - if (test_node (front, &cf)) { - node_ptr->node = node; - node_ptr->side = side; - node_ptr->clipflags = clipflags; - node_ptr++; - clipflags = cf; - node = front; - continue; - } - if (front->contents < 0 && front->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) front); - visit_node (brush, node, side, clipflags); - node = node->children[!side]; - } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); - if (node_ptr != node_stack) { - node_ptr--; - node = node_ptr->node; - side = node_ptr->side; - clipflags = node_ptr->clipflags; - visit_node (brush, node, side, clipflags); - node = node->children[!side]; - continue; - } - break; - } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); -} - -void -sw32_R_RenderWorld (void) -{ - int i; - btofpoly_t btofpolys[MAX_BTOFPOLYS]; - mod_brush_t *brush; - - pbtofpolys = btofpolys; - - currententity = &r_worldentity; - VectorCopy (r_origin, modelorg); - brush = ¤tentity->renderer.model->brush; - r_pcurrentvertbase = brush->vertexes; - - R_VisitWorldNodes (brush, 15); - - // if the driver wants the polygons back to front, play the visible ones - // back in that order - if (sw32_r_worldpolysbacktofront) { - for (i = sw32_numbtofpolys - 1; i >= 0; i--) { - sw32_R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags); - } - } -} diff --git a/libs/video/renderer/sw32/sw32_rdraw.c b/libs/video/renderer/sw32/sw32_rdraw.c deleted file mode 100644 index 7c1e696be..000000000 --- a/libs/video/renderer/sw32/sw32_rdraw.c +++ /dev/null @@ -1,804 +0,0 @@ -/* - sw32_r_draw.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/render.h" - -#include "compat.h" -#include "r_internal.h" - -#define MAXLEFTCLIPEDGES 100 - -// !!! if these are changed, they must be changed in asm_draw.h too !!! -#define FULLY_CLIPPED_CACHED 0x80000000 -#define FRAMECOUNT_MASK 0x7FFFFFFF - -static unsigned int cacheoffset; - -int sw32_c_faceclip; // number of faces clipped - -zpointdesc_t sw32_r_zpointdesc; - -static polydesc_t r_polydesc; - -clipplane_t sw32_view_clipplanes[4]; - -medge_t *sw32_r_pedge; - -qboolean sw32_r_leftclipped, sw32_r_rightclipped; -static qboolean makeleftedge, makerightedge; -qboolean sw32_r_nearzionly; - -int sw32_sintable[SIN_BUFFER_SIZE]; -int sw32_intsintable[SIN_BUFFER_SIZE]; - -mvertex_t sw32_r_leftenter, sw32_r_leftexit; -mvertex_t sw32_r_rightenter, sw32_r_rightexit; - -typedef struct { - float u, v; - int ceilv; -} evert_t; - -int sw32_r_emitted; -float sw32_r_nearzi; -float sw32_r_u1, sw32_r_v1, sw32_r_lzi1; -int sw32_r_ceilv1; - -qboolean sw32_r_lastvertvalid; - - -void -sw32_R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) -{ - edge_t *edge, *pcheck; - int u_check; - float u, u_step; - vec3_t local, transformed; - float *world; - int v, v2, ceilv0; - float scale, lzi0, u0, v0; - int side; - - if (sw32_r_lastvertvalid) { - u0 = sw32_r_u1; - v0 = sw32_r_v1; - lzi0 = sw32_r_lzi1; - ceilv0 = sw32_r_ceilv1; - } else { - world = &pv0->position[0]; - - // transform and project - VectorSubtract (world, modelorg, local); - sw32_TransformVector (local, transformed); - - if (transformed[2] < NEAR_CLIP) - transformed[2] = NEAR_CLIP; - - lzi0 = 1.0 / transformed[2]; - - // FIXME: build x/sw32_yscale into transform? - scale = sw32_xscale * lzi0; - u0 = (sw32_xcenter + scale * transformed[0]); - if (u0 < r_refdef.fvrectx_adj) - u0 = r_refdef.fvrectx_adj; - if (u0 > r_refdef.fvrectright_adj) - u0 = r_refdef.fvrectright_adj; - - scale = sw32_yscale * lzi0; - v0 = (sw32_ycenter - scale * transformed[1]); - if (v0 < r_refdef.fvrecty_adj) - v0 = r_refdef.fvrecty_adj; - if (v0 > r_refdef.fvrectbottom_adj) - v0 = r_refdef.fvrectbottom_adj; - - ceilv0 = (int) ceil (v0); - } - - world = &pv1->position[0]; - - // transform and project - VectorSubtract (world, modelorg, local); - sw32_TransformVector (local, transformed); - - if (transformed[2] < NEAR_CLIP) - transformed[2] = NEAR_CLIP; - - sw32_r_lzi1 = 1.0 / transformed[2]; - - scale = sw32_xscale * sw32_r_lzi1; - sw32_r_u1 = (sw32_xcenter + scale * transformed[0]); - if (sw32_r_u1 < r_refdef.fvrectx_adj) - sw32_r_u1 = r_refdef.fvrectx_adj; - if (sw32_r_u1 > r_refdef.fvrectright_adj) - sw32_r_u1 = r_refdef.fvrectright_adj; - - scale = sw32_yscale * sw32_r_lzi1; - sw32_r_v1 = (sw32_ycenter - scale * transformed[1]); - if (sw32_r_v1 < r_refdef.fvrecty_adj) - sw32_r_v1 = r_refdef.fvrecty_adj; - if (sw32_r_v1 > r_refdef.fvrectbottom_adj) - sw32_r_v1 = r_refdef.fvrectbottom_adj; - - if (sw32_r_lzi1 > lzi0) - lzi0 = sw32_r_lzi1; - - if (lzi0 > sw32_r_nearzi) // for mipmap finding - sw32_r_nearzi = lzi0; - - // for right edges, all we want is the effect on 1/z - if (sw32_r_nearzionly) - return; - - sw32_r_emitted = 1; - - sw32_r_ceilv1 = (int) ceil (sw32_r_v1); - - // create the edge - if (ceilv0 == sw32_r_ceilv1) { - // we cache unclipped horizontal edges as fully clipped - if (cacheoffset != 0x7FFFFFFF) { - cacheoffset = FULLY_CLIPPED_CACHED | - (r_framecount & FRAMECOUNT_MASK); - } - - return; // horizontal edge - } - - side = ceilv0 > sw32_r_ceilv1; - - edge = sw32_edge_p++; - - edge->owner = sw32_r_pedge; - - edge->nearzi = lzi0; - - if (side == 0) { - // trailing edge (go from p1 to p2) - v = ceilv0; - v2 = sw32_r_ceilv1 - 1; - - edge->surfs[0] = sw32_surface_p - sw32_surfaces; - edge->surfs[1] = 0; - - u_step = ((sw32_r_u1 - u0) / (sw32_r_v1 - v0)); - u = u0 + ((float) v - v0) * u_step; - } else { - // leading edge (go from p2 to p1) - v2 = ceilv0 - 1; - v = sw32_r_ceilv1; - - edge->surfs[0] = 0; - edge->surfs[1] = sw32_surface_p - sw32_surfaces; - - u_step = ((u0 - sw32_r_u1) / (v0 - sw32_r_v1)); - u = sw32_r_u1 + ((float) v - sw32_r_v1) * u_step; - } - - edge->u_step = u_step * 0x100000; - edge->u = u * 0x100000 + 0xFFFFF; - - // we need to do this to avoid stepping off the edges if a very nearly - // horizontal edge is less than epsilon above a scan, and numeric error - // causes it to incorrectly extend to the scan, and the extension of the - // line goes off the edge of the screen - // FIXME: is this actually needed? - if (edge->u < r_refdef.vrect_x_adj_shift20) - edge->u = r_refdef.vrect_x_adj_shift20; - if (edge->u > r_refdef.vrectright_adj_shift20) - edge->u = r_refdef.vrectright_adj_shift20; - - // sort the edge in normally - u_check = edge->u; - if (edge->surfs[0]) - u_check++; // sort trailers after leaders - - if (!sw32_newedges[v] || sw32_newedges[v]->u >= u_check) { - edge->next = sw32_newedges[v]; - sw32_newedges[v] = edge; - } else { - pcheck = sw32_newedges[v]; - while (pcheck->next && pcheck->next->u < u_check) - pcheck = pcheck->next; - edge->next = pcheck->next; - pcheck->next = edge; - } - - edge->nextremove = sw32_removeedges[v2]; - sw32_removeedges[v2] = edge; -} - - -void -sw32_R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) -{ - float d0, d1, f; - mvertex_t clipvert; - - if (clip) { - do { - d0 = DotProduct (pv0->position, clip->normal) - clip->dist; - d1 = DotProduct (pv1->position, clip->normal) - clip->dist; - - if (d0 >= 0) { - // point 0 is unclipped - if (d1 >= 0) { - // both points are unclipped - continue; - } - // only point 1 is clipped - - // we don't cache clipped edges - cacheoffset = 0x7FFFFFFF; - - f = d0 / (d0 - d1); - clipvert.position[0] = pv0->position[0] + - f * (pv1->position[0] - pv0->position[0]); - clipvert.position[1] = pv0->position[1] + - f * (pv1->position[1] - pv0->position[1]); - clipvert.position[2] = pv0->position[2] + - f * (pv1->position[2] - pv0->position[2]); - - if (clip->leftedge) { - sw32_r_leftclipped = true; - sw32_r_leftexit = clipvert; - } else if (clip->rightedge) { - sw32_r_rightclipped = true; - sw32_r_rightexit = clipvert; - } - - sw32_R_ClipEdge (pv0, &clipvert, clip->next); - return; - } else { - // point 0 is clipped - if (d1 < 0) { - // both points are clipped - // we do cache fully clipped edges - if (!sw32_r_leftclipped) - cacheoffset = FULLY_CLIPPED_CACHED | - (r_framecount & FRAMECOUNT_MASK); - return; - } - // only point 0 is clipped - sw32_r_lastvertvalid = false; - - // we don't cache partially clipped edges - cacheoffset = 0x7FFFFFFF; - - f = d0 / (d0 - d1); - clipvert.position[0] = pv0->position[0] + - f * (pv1->position[0] - pv0->position[0]); - clipvert.position[1] = pv0->position[1] + - f * (pv1->position[1] - pv0->position[1]); - clipvert.position[2] = pv0->position[2] + - f * (pv1->position[2] - pv0->position[2]); - - if (clip->leftedge) { - sw32_r_leftclipped = true; - sw32_r_leftenter = clipvert; - } else if (clip->rightedge) { - sw32_r_rightclipped = true; - sw32_r_rightenter = clipvert; - } - - sw32_R_ClipEdge (&clipvert, pv1, clip->next); - return; - } - } while ((clip = clip->next) != NULL); - } - // add the edge - sw32_R_EmitEdge (pv0, pv1); -} - - -static void -R_EmitCachedEdge (void) -{ - edge_t *pedge_t; - - pedge_t = (edge_t *) ((intptr_t) sw32_r_edges + sw32_r_pedge->cachededgeoffset); - - if (!pedge_t->surfs[0]) - pedge_t->surfs[0] = sw32_surface_p - sw32_surfaces; - else - pedge_t->surfs[1] = sw32_surface_p - sw32_surfaces; - - if (pedge_t->nearzi > sw32_r_nearzi) // for mipmap finding - sw32_r_nearzi = pedge_t->nearzi; - - sw32_r_emitted = 1; -} - - -void -sw32_R_RenderFace (msurface_t *fa, int clipflags) -{ - int i, lindex; - unsigned int mask; - plane_t *pplane; - float distinv; - vec3_t p_normal; - medge_t *pedges, tedge; - clipplane_t *pclip; - mod_brush_t *brush = ¤tentity->renderer.model->brush; - - // skip out if no more surfs - if ((sw32_surface_p) >= sw32_surf_max) { - sw32_r_outofsurfaces++; - return; - } - // ditto if not enough edges left, or switch to auxedges if possible - if ((sw32_edge_p + fa->numedges + 4) >= sw32_edge_max) { - sw32_r_outofedges += fa->numedges; - return; - } - - sw32_c_faceclip++; - - // set up clip planes - pclip = NULL; - - for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { - if (clipflags & mask) { - sw32_view_clipplanes[i].next = pclip; - pclip = &sw32_view_clipplanes[i]; - } - } - - // push the edges through - sw32_r_emitted = 0; - sw32_r_nearzi = 0; - sw32_r_nearzionly = false; - makeleftedge = makerightedge = false; - pedges = brush->edges; - sw32_r_lastvertvalid = false; - - for (i = 0; i < fa->numedges; i++) { - lindex = brush->surfedges[fa->firstedge + i]; - - if (lindex > 0) { - sw32_r_pedge = &pedges[lindex]; - - // if the edge is cached, we can just reuse the edge - if (!insubmodel) { - if (sw32_r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { - if ((sw32_r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == - (unsigned int) r_framecount) { - sw32_r_lastvertvalid = false; - continue; - } - } else { - if ((((uintptr_t) sw32_edge_p - (uintptr_t) sw32_r_edges) > - sw32_r_pedge->cachededgeoffset) && - (((edge_t *) ((intptr_t) sw32_r_edges + - sw32_r_pedge->cachededgeoffset))->owner == - sw32_r_pedge)) { - R_EmitCachedEdge (); - sw32_r_lastvertvalid = false; - continue; - } - } - } - // assume it's cacheable - cacheoffset = (byte *) sw32_edge_p - (byte *) sw32_r_edges; - sw32_r_leftclipped = sw32_r_rightclipped = false; - sw32_R_ClipEdge (&r_pcurrentvertbase[sw32_r_pedge->v[0]], - &r_pcurrentvertbase[sw32_r_pedge->v[1]], pclip); - sw32_r_pedge->cachededgeoffset = cacheoffset; - - if (sw32_r_leftclipped) - makeleftedge = true; - if (sw32_r_rightclipped) - makerightedge = true; - sw32_r_lastvertvalid = true; - } else { - lindex = -lindex; - sw32_r_pedge = &pedges[lindex]; - // if the edge is cached, we can just reuse the edge - if (!insubmodel) { - if (sw32_r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { - if ((sw32_r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == - (unsigned int) r_framecount) { - sw32_r_lastvertvalid = false; - continue; - } - } else { - // it's cached if the cached edge is valid and is owned - // by this medge_t - if ((((uintptr_t) sw32_edge_p - (uintptr_t) sw32_r_edges) > - sw32_r_pedge->cachededgeoffset) && - (((edge_t *) ((intptr_t) sw32_r_edges + - sw32_r_pedge->cachededgeoffset))->owner == - sw32_r_pedge)) { - R_EmitCachedEdge (); - sw32_r_lastvertvalid = false; - continue; - } - } - } - // assume it's cacheable - cacheoffset = (byte *) sw32_edge_p - (byte *) sw32_r_edges; - sw32_r_leftclipped = sw32_r_rightclipped = false; - sw32_R_ClipEdge (&r_pcurrentvertbase[sw32_r_pedge->v[1]], - &r_pcurrentvertbase[sw32_r_pedge->v[0]], pclip); - sw32_r_pedge->cachededgeoffset = cacheoffset; - - if (sw32_r_leftclipped) - makeleftedge = true; - if (sw32_r_rightclipped) - makerightedge = true; - sw32_r_lastvertvalid = true; - } - } - - // if there was a clip off the left edge, add that edge too - // FIXME: faster to do in screen space? - // FIXME: share clipped edges? - if (makeleftedge) { - sw32_r_pedge = &tedge; - sw32_r_lastvertvalid = false; - sw32_R_ClipEdge (&sw32_r_leftexit, &sw32_r_leftenter, pclip->next); - } - // if there was a clip off the right edge, get the right sw32_r_nearzi - if (makerightedge) { - sw32_r_pedge = &tedge; - sw32_r_lastvertvalid = false; - sw32_r_nearzionly = true; - sw32_R_ClipEdge (&sw32_r_rightexit, &sw32_r_rightenter, sw32_view_clipplanes[1].next); - } - // if no edges made it out, return without posting the surface - if (!sw32_r_emitted) - return; - - sw32_r_polycount++; - - sw32_surface_p->data = (void *) fa; - sw32_surface_p->nearzi = sw32_r_nearzi; - sw32_surface_p->flags = fa->flags; - sw32_surface_p->insubmodel = insubmodel; - sw32_surface_p->spanstate = 0; - sw32_surface_p->entity = currententity; - sw32_surface_p->key = sw32_r_currentkey++; - sw32_surface_p->spans = NULL; - - pplane = fa->plane; -// FIXME: cache this? - sw32_TransformVector (pplane->normal, p_normal); -// FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); - distinv = min (distinv, 1.0); - - sw32_surface_p->d_zistepu = p_normal[0] * sw32_xscaleinv * distinv; - sw32_surface_p->d_zistepv = -p_normal[1] * sw32_yscaleinv * distinv; - sw32_surface_p->d_ziorigin = p_normal[2] * distinv - - sw32_xcenter * sw32_surface_p->d_zistepu - sw32_ycenter * sw32_surface_p->d_zistepv; - -//JDC VectorCopy (r_worldmodelorg, sw32_surface_p->modelorg); - sw32_surface_p++; -} - - -void -sw32_R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) -{ - int i; - unsigned int mask; - plane_t *pplane; - float distinv; - vec3_t p_normal; - medge_t tedge; - clipplane_t *pclip; - - // skip out if no more surfs - if (sw32_surface_p >= sw32_surf_max) { - sw32_r_outofsurfaces++; - return; - } - // ditto if not enough edges left, or switch to auxedges if possible - if ((sw32_edge_p + psurf->numedges + 4) >= sw32_edge_max) { - sw32_r_outofedges += psurf->numedges; - return; - } - - sw32_c_faceclip++; - - // this is a dummy to give the caching mechanism someplace to write to - sw32_r_pedge = &tedge; - - // set up clip planes - pclip = NULL; - - for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { - if (sw32_r_clipflags & mask) { - sw32_view_clipplanes[i].next = pclip; - pclip = &sw32_view_clipplanes[i]; - } - } - - // push the edges through - sw32_r_emitted = 0; - sw32_r_nearzi = 0; - sw32_r_nearzionly = false; - makeleftedge = makerightedge = false; - // FIXME: keep clipped bmodel edges in clockwise order so last vertex - // caching can be used? - sw32_r_lastvertvalid = false; - - for (; pedges; pedges = pedges->pnext) { - sw32_r_leftclipped = sw32_r_rightclipped = false; - sw32_R_ClipEdge (pedges->v[0], pedges->v[1], pclip); - - if (sw32_r_leftclipped) - makeleftedge = true; - if (sw32_r_rightclipped) - makerightedge = true; - } - - // if there was a clip off the left edge, add that edge too - // FIXME: faster to do in screen space? - // FIXME: share clipped edges? - if (makeleftedge) { - sw32_r_pedge = &tedge; - sw32_R_ClipEdge (&sw32_r_leftexit, &sw32_r_leftenter, pclip->next); - } - // if there was a clip off the right edge, get the right sw32_r_nearzi - if (makerightedge) { - sw32_r_pedge = &tedge; - sw32_r_nearzionly = true; - sw32_R_ClipEdge (&sw32_r_rightexit, &sw32_r_rightenter, sw32_view_clipplanes[1].next); - } - // if no edges made it out, return without posting the surface - if (!sw32_r_emitted) - return; - - sw32_r_polycount++; - - sw32_surface_p->data = (void *) psurf; - sw32_surface_p->nearzi = sw32_r_nearzi; - sw32_surface_p->flags = psurf->flags; - sw32_surface_p->insubmodel = true; - sw32_surface_p->spanstate = 0; - sw32_surface_p->entity = currententity; - sw32_surface_p->key = sw32_r_currentbkey; - sw32_surface_p->spans = NULL; - - pplane = psurf->plane; -// FIXME: cache this? - sw32_TransformVector (pplane->normal, p_normal); -// FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); - distinv = min (distinv, 1.0); - - sw32_surface_p->d_zistepu = p_normal[0] * sw32_xscaleinv * distinv; - sw32_surface_p->d_zistepv = -p_normal[1] * sw32_yscaleinv * distinv; - sw32_surface_p->d_ziorigin = p_normal[2] * distinv - - sw32_xcenter * sw32_surface_p->d_zistepu - sw32_ycenter * sw32_surface_p->d_zistepv; - -//JDC VectorCopy (r_worldmodelorg, sw32_surface_p->modelorg); - sw32_surface_p++; -} - - -void -sw32_R_RenderPoly (msurface_t *fa, int clipflags) -{ - int i, lindex, lnumverts, s_axis, t_axis; - float dist, lastdist, lzi, scale, u, v, frac; - unsigned int mask; - vec3_t local, transformed; - clipplane_t *pclip; - medge_t *pedges; - plane_t *pplane; - mvertex_t verts[2][100]; // FIXME: do real number - polyvert_t pverts[100]; // FIXME: do real number, safely - int vertpage, newverts, newpage, lastvert; - qboolean visible; - mod_brush_t *brush = ¤tentity->renderer.model->brush; - - // FIXME: clean this up and make it faster - // FIXME: guard against running out of vertices - - s_axis = t_axis = 0; // keep compiler happy - - // set up clip planes - pclip = NULL; - - for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { - if (clipflags & mask) { - sw32_view_clipplanes[i].next = pclip; - pclip = &sw32_view_clipplanes[i]; - } - } - - // reconstruct the polygon - // FIXME: these should be precalculated and loaded off disk - pedges = brush->edges; - lnumverts = fa->numedges; - vertpage = 0; - - for (i = 0; i < lnumverts; i++) { - lindex = brush->surfedges[fa->firstedge + i]; - - if (lindex > 0) { - sw32_r_pedge = &pedges[lindex]; - verts[0][i] = r_pcurrentvertbase[sw32_r_pedge->v[0]]; - } else { - sw32_r_pedge = &pedges[-lindex]; - verts[0][i] = r_pcurrentvertbase[sw32_r_pedge->v[1]]; - } - } - - // clip the polygon, done if not visible - while (pclip) { - lastvert = lnumverts - 1; - lastdist = DotProduct (verts[vertpage][lastvert].position, - pclip->normal) - pclip->dist; - - visible = false; - newverts = 0; - newpage = vertpage ^ 1; - - for (i = 0; i < lnumverts; i++) { - dist = DotProduct (verts[vertpage][i].position, pclip->normal) - - pclip->dist; - - if ((lastdist > 0) != (dist > 0)) { - frac = dist / (dist - lastdist); - verts[newpage][newverts].position[0] = - verts[vertpage][i].position[0] + - ((verts[vertpage][lastvert].position[0] - - verts[vertpage][i].position[0]) * frac); - verts[newpage][newverts].position[1] = - verts[vertpage][i].position[1] + - ((verts[vertpage][lastvert].position[1] - - verts[vertpage][i].position[1]) * frac); - verts[newpage][newverts].position[2] = - verts[vertpage][i].position[2] + - ((verts[vertpage][lastvert].position[2] - - verts[vertpage][i].position[2]) * frac); - newverts++; - } - - if (dist >= 0) { - verts[newpage][newverts] = verts[vertpage][i]; - newverts++; - visible = true; - } - - lastvert = i; - lastdist = dist; - } - - if (!visible || (newverts < 3)) - return; - - lnumverts = newverts; - vertpage ^= 1; - pclip = pclip->next; - } - - // transform and project, remembering the z values at the vertices and - // sw32_r_nearzi, and extract the s and t coordinates at the vertices - pplane = fa->plane; - switch (pplane->type) { - case PLANE_X: - case PLANE_ANYX: - s_axis = 1; - t_axis = 2; - break; - case PLANE_Y: - case PLANE_ANYY: - s_axis = 0; - t_axis = 2; - break; - case PLANE_Z: - case PLANE_ANYZ: - s_axis = 0; - t_axis = 1; - break; - } - - sw32_r_nearzi = 0; - - for (i = 0; i < lnumverts; i++) { - // transform and project - VectorSubtract (verts[vertpage][i].position, modelorg, local); - sw32_TransformVector (local, transformed); - - if (transformed[2] < NEAR_CLIP) - transformed[2] = NEAR_CLIP; - - lzi = 1.0 / transformed[2]; - - if (lzi > sw32_r_nearzi) // for mipmap finding - sw32_r_nearzi = lzi; - - // FIXME: build x/sw32_yscale into transform? - scale = sw32_xscale * lzi; - u = (sw32_xcenter + scale * transformed[0]); - if (u < r_refdef.fvrectx_adj) - u = r_refdef.fvrectx_adj; - if (u > r_refdef.fvrectright_adj) - u = r_refdef.fvrectright_adj; - - scale = sw32_yscale * lzi; - v = (sw32_ycenter - scale * transformed[1]); - if (v < r_refdef.fvrecty_adj) - v = r_refdef.fvrecty_adj; - if (v > r_refdef.fvrectbottom_adj) - v = r_refdef.fvrectbottom_adj; - - pverts[i].u = u; - pverts[i].v = v; - pverts[i].zi = lzi; - pverts[i].s = verts[vertpage][i].position[s_axis]; - pverts[i].t = verts[vertpage][i].position[t_axis]; - } - - // build the polygon descriptor, including fa, sw32_r_nearzi, and u, v, s, t, - // and z for each vertex - r_polydesc.numverts = lnumverts; - r_polydesc.nearzi = sw32_r_nearzi; - r_polydesc.pcurrentface = fa; - r_polydesc.pverts = pverts; - - // draw the polygon - sw32_D_DrawPoly (); -} - - -void -sw32_R_ZDrawSubmodelPolys (model_t *model) -{ - int i, numsurfaces; - msurface_t *psurf; - float dot; - plane_t *pplane; - mod_brush_t *brush = &model->brush; - - psurf = &brush->surfaces[brush->firstmodelsurface]; - numsurfaces = brush->nummodelsurfaces; - - for (i = 0; i < numsurfaces; i++, psurf++) { - // find which side of the node we are on - pplane = psurf->plane; - - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; - - // draw the polygon - if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || - (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - // FIXME: use bounding-box-based frustum clipping info? - sw32_R_RenderPoly (psurf, 15); - } - } -} diff --git a/libs/video/renderer/sw32/sw32_redge.c b/libs/video/renderer/sw32/sw32_redge.c deleted file mode 100644 index 8498f22a9..000000000 --- a/libs/video/renderer/sw32/sw32_redge.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - sw32_redge.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/render.h" -#include "QF/sound.h" - -#include "d_ifacea.h" -#include "r_internal.h" -#include "vid_internal.h" - -/* - FIXME - the complex cases add new polys on most lines, so dont optimize for - keeping them the same have multiple free span lists to try to get better - coherence ? low depth complexity-- 1 to 3 or so this breaks spans at every - edge, even hidden ones (bad) - - have a sentinal at both ends? -*/ - -edge_t *sw32_auxedges; -edge_t *sw32_r_edges, *sw32_edge_p, *sw32_edge_max; - -surf_t *sw32_surfaces, *sw32_surface_p, *sw32_surf_max; - -/* - surfaces are generated in back to front order by the bsp, so if a surf - pointer is greater than another one, it should be drawn in front - sw32_surfaces[1] is the background, and is used as the active surface stack -*/ - -edge_t *sw32_newedges[MAXHEIGHT]; -edge_t *sw32_removeedges[MAXHEIGHT]; - -static espan_t *span_p, *max_span_p; - -int sw32_r_currentkey; - - -static int current_iv; - -static int edge_head_u_shift20, edge_tail_u_shift20; - -static void (*pdrawfunc) (void); - -static edge_t edge_head; -static edge_t edge_tail; -static edge_t edge_aftertail; -static edge_t edge_sentinel; - -static float fv; - -static void -R_DrawCulledPolys (void) -{ - surf_t *s; - msurface_t *pface; - - currententity = &r_worldentity; - - if (sw32_r_worldpolysbacktofront) { - for (s = sw32_surface_p - 1; s > &sw32_surfaces[1]; s--) { - if (!s->spans) - continue; - - if (!(s->flags & SURF_DRAWBACKGROUND)) { - pface = (msurface_t *) s->data; - sw32_R_RenderPoly (pface, 15); - } - } - } else { - for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++) { - if (!s->spans) - continue; - - if (!(s->flags & SURF_DRAWBACKGROUND)) { - pface = (msurface_t *) s->data; - sw32_R_RenderPoly (pface, 15); - } - } - } -} - -void -sw32_R_BeginEdgeFrame (void) -{ - int v; - - sw32_edge_p = sw32_r_edges; - sw32_edge_max = &sw32_r_edges[sw32_r_numallocatededges]; - - sw32_surface_p = &sw32_surfaces[2]; // background is surface 1, - // surface 0 is a dummy - sw32_surfaces[1].spans = NULL; // no background spans yet - sw32_surfaces[1].flags = SURF_DRAWBACKGROUND; - - // put the background behind everything in the world - pdrawfunc = sw32_R_GenerateSpans; - sw32_surfaces[1].key = 0x7FFFFFFF; - sw32_r_currentkey = 0; - - // FIXME: set with memset - for (v = r_refdef.vrect.y; v < r_refdef.vrectbottom; v++) { - sw32_newedges[v] = sw32_removeedges[v] = NULL; - } -} - -/* - sw32_R_InsertNewEdges - - Adds the edges in the linked list edgestoadd, adding them to the edges - in the linked list edgelist. edgestoadd is assumed to be sorted on u, - and non-empty (this is actually sw32_newedges[v]). edgelist is assumed to - be sorted on u, with a sentinel at the end (actually, this is the - active edge table starting at edge_head.next). -*/ -void -sw32_R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist) -{ - edge_t *next_edge; - - do { - next_edge = edgestoadd->next; - edgesearch: - if (edgelist->u >= edgestoadd->u) - goto addedge; - edgelist = edgelist->next; - if (edgelist->u >= edgestoadd->u) - goto addedge; - edgelist = edgelist->next; - if (edgelist->u >= edgestoadd->u) - goto addedge; - edgelist = edgelist->next; - if (edgelist->u >= edgestoadd->u) - goto addedge; - edgelist = edgelist->next; - goto edgesearch; - - // insert edgestoadd before edgelist - addedge: - edgestoadd->next = edgelist; - edgestoadd->prev = edgelist->prev; - edgelist->prev->next = edgestoadd; - edgelist->prev = edgestoadd; - } while ((edgestoadd = next_edge) != NULL); -} - -void -sw32_R_RemoveEdges (edge_t *pedge) -{ - - do { - pedge->next->prev = pedge->prev; - pedge->prev->next = pedge->next; - } while ((pedge = pedge->nextremove) != NULL); -} - -void -sw32_R_StepActiveU (edge_t *pedge) -{ - edge_t *pnext_edge, *pwedge; - - while (1) { - nextedge: - pedge->u += pedge->u_step; - if (pedge->u < pedge->prev->u) - goto pushback; - pedge = pedge->next; - - pedge->u += pedge->u_step; - if (pedge->u < pedge->prev->u) - goto pushback; - pedge = pedge->next; - - pedge->u += pedge->u_step; - if (pedge->u < pedge->prev->u) - goto pushback; - pedge = pedge->next; - - pedge->u += pedge->u_step; - if (pedge->u < pedge->prev->u) - goto pushback; - pedge = pedge->next; - - goto nextedge; - - pushback: - if (pedge == &edge_aftertail) - return; - - // push it back to keep it sorted - pnext_edge = pedge->next; - - // pull the edge out of the edge list - pedge->next->prev = pedge->prev; - pedge->prev->next = pedge->next; - - // find out where the edge goes in the edge list - pwedge = pedge->prev->prev; - - while (pwedge->u > pedge->u) { - pwedge = pwedge->prev; - } - - // put the edge back into the edge list - pedge->next = pwedge->next; - pedge->prev = pwedge; - pedge->next->prev = pedge; - pwedge->next = pedge; - - pedge = pnext_edge; - if (pedge == &edge_tail) - return; - } -} - -static void -R_CleanupSpan (void) -{ - surf_t *surf; - int iu; - espan_t *span; - - // now that we've reached the right edge of the screen, we're done with any - // unfinished surfaces, so emit a span for whatever's on top - surf = sw32_surfaces[1].next; - iu = edge_tail_u_shift20; - if (iu > surf->last_u) { - span = span_p++; - span->u = surf->last_u; - span->count = iu - span->u; - span->v = current_iv; - span->pnext = surf->spans; - surf->spans = span; - } - // reset spanstate for all surfaces in the surface stack - do { - surf->spanstate = 0; - surf = surf->next; - } while (surf != &sw32_surfaces[1]); -} - -static void -R_TrailingEdge (surf_t *surf, edge_t *edge) -{ - espan_t *span; - int iu; - - // don't generate a span if this is an inverted span, with the end edge - // preceding the start edge (that is, we haven't seen the start edge yet) - if (--surf->spanstate == 0) { - if (surf == sw32_surfaces[1].next) { - // emit a span (current top going away) - iu = edge->u >> 20; - if (iu > surf->last_u) { - span = span_p++; - span->u = surf->last_u; - span->count = iu - span->u; - span->v = current_iv; - span->pnext = surf->spans; - surf->spans = span; - } - // set last_u on the surface below - surf->next->last_u = iu; - } - - surf->prev->next = surf->next; - surf->next->prev = surf->prev; - } -} - -static void -R_LeadingEdge (edge_t *edge) -{ - espan_t *span; - surf_t *surf, *surf2; - int iu; - double fu, newzi, testzi, newzitop, newzibottom; - - if (edge->surfs[1]) { - // it's adding a new surface in, so find the correct place - surf = &sw32_surfaces[edge->surfs[1]]; - - // don't start a span if this is an inverted span, with the end edge - // preceding the start edge (that is, we've already seen the end edge) - if (++surf->spanstate == 1) { - surf2 = sw32_surfaces[1].next; - - if (surf->key < surf2->key) - goto newtop; - - // if it's two surfaces on the same plane, the one that's already - // active is in front, so keep going unless it's a bmodel - if (surf->insubmodel && (surf->key == surf2->key)) { - // must be two bmodels in the same leaf; sort on 1/z - fu = (float) (edge->u - 0xFFFFF) * (1.0 / 0x100000); - newzi = surf->d_ziorigin + fv * surf->d_zistepv + - fu * surf->d_zistepu; - newzibottom = newzi * 0.99; - - testzi = surf2->d_ziorigin + fv * surf2->d_zistepv + - fu * surf2->d_zistepu; - - if (newzibottom >= testzi) { - goto newtop; - } - - newzitop = newzi * 1.01; - if (newzitop >= testzi) { - if (surf->d_zistepu >= surf2->d_zistepu) { - goto newtop; - } - } - } - - continue_search: - - do { - surf2 = surf2->next; - } while (surf->key > surf2->key); - - if (surf->key == surf2->key) { - // if it's two surfaces on the same plane, the already active - // one is in front, so keep going unless it's a bmodel - if (!surf->insubmodel) - goto continue_search; - - // must be two bmodels in the same leaf; sort on 1/z - fu = (float) (edge->u - 0xFFFFF) * (1.0 / 0x100000); - newzi = surf->d_ziorigin + fv * surf->d_zistepv + - fu * surf->d_zistepu; - newzibottom = newzi * 0.99; - - testzi = surf2->d_ziorigin + fv * surf2->d_zistepv + - fu * surf2->d_zistepu; - - if (newzibottom >= testzi) { - goto gotposition; - } - - newzitop = newzi * 1.01; - if (newzitop >= testzi) { - if (surf->d_zistepu >= surf2->d_zistepu) { - goto gotposition; - } - } - - goto continue_search; - } - - goto gotposition; - - newtop: - // emit a span (obscures current top) - iu = edge->u >> 20; - - if (iu > surf2->last_u) { - span = span_p++; - span->u = surf2->last_u; - span->count = iu - span->u; - span->v = current_iv; - span->pnext = surf2->spans; - surf2->spans = span; - } - // set last_u on the new span - surf->last_u = iu; - - gotposition: - // insert before surf2 - surf->next = surf2; - surf->prev = surf2->prev; - surf2->prev->next = surf; - surf2->prev = surf; - } - } -} - -void -sw32_R_GenerateSpans (void) -{ - edge_t *edge; - surf_t *surf; - - // clear active surfaces to just the background surface - sw32_surfaces[1].next = sw32_surfaces[1].prev = &sw32_surfaces[1]; - sw32_surfaces[1].last_u = edge_head_u_shift20; - - // generate spans - for (edge = edge_head.next; edge != &edge_tail; edge = edge->next) { - if (edge->surfs[0]) { - // it has a left surface, so a surface is going away for this span - surf = &sw32_surfaces[edge->surfs[0]]; - - R_TrailingEdge (surf, edge); - - if (!edge->surfs[1]) - continue; - } - - R_LeadingEdge (edge); - } - - R_CleanupSpan (); -} - -/* - R_ScanEdges - - Input: - sw32_newedges[] array - this has links to edges, which have links to surfaces - - Output: - Each surface has a linked list of its visible spans -*/ -void -sw32_R_ScanEdges (void) -{ - int iv, bottom; - byte basespans[MAXSPANS * sizeof (espan_t) + CACHE_SIZE]; - espan_t *basespan_p; - surf_t *s; - - basespan_p = (espan_t *) - ((intptr_t) (basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width]; - - span_p = basespan_p; - - // clear active edges to just the background edges around the whole screen - // FIXME: most of this needs to be set up only once - edge_head.u = r_refdef.vrect.x << 20; - edge_head_u_shift20 = edge_head.u >> 20; - edge_head.u_step = 0; - edge_head.prev = NULL; - edge_head.next = &edge_tail; - edge_head.surfs[0] = 0; - edge_head.surfs[1] = 1; - - edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF; - edge_tail_u_shift20 = edge_tail.u >> 20; - edge_tail.u_step = 0; - edge_tail.prev = &edge_head; - edge_tail.next = &edge_aftertail; - edge_tail.surfs[0] = 1; - edge_tail.surfs[1] = 0; - - edge_aftertail.u = -1; // force a move - edge_aftertail.u_step = 0; - edge_aftertail.next = &edge_sentinel; - edge_aftertail.prev = &edge_tail; - - // FIXME: do we need this now that we clamp x in r_draw.c? - edge_sentinel.u = 32767 << 16; // make sure nothing sorts past this - edge_sentinel.prev = &edge_aftertail; - - // process all scan lines - bottom = r_refdef.vrectbottom - 1; - - for (iv = r_refdef.vrect.y; iv < bottom; iv++) { - current_iv = iv; - fv = (float) iv; - - // mark that the head (background start) span is pre-included - sw32_surfaces[1].spanstate = 1; - - if (sw32_newedges[iv]) { - sw32_R_InsertNewEdges (sw32_newedges[iv], edge_head.next); - } - - (*pdrawfunc) (); - - // flush the span list if we can't be sure we have enough spans left - // for the next scan - if (span_p > max_span_p) { - S_ExtraUpdate (); // don't let sound get messed up if going slow - - if (sw32_r_drawculledpolys) - R_DrawCulledPolys (); - else - sw32_D_DrawSurfaces (); - - // clear the surface span pointers - for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++) - s->spans = NULL; - - span_p = basespan_p; - } - - if (sw32_removeedges[iv]) - sw32_R_RemoveEdges (sw32_removeedges[iv]); - - if (edge_head.next != &edge_tail) - sw32_R_StepActiveU (edge_head.next); - } - - // do the last scan (no need to step or sort or remove on the last scan) - current_iv = iv; - fv = (float) iv; - - // mark that the head (background start) span is pre-included - sw32_surfaces[1].spanstate = 1; - - if (sw32_newedges[iv]) - sw32_R_InsertNewEdges (sw32_newedges[iv], edge_head.next); - - (*pdrawfunc) (); - - // draw whatever's left in the span list - if (sw32_r_drawculledpolys) - R_DrawCulledPolys (); - else - sw32_D_DrawSurfaces (); -} diff --git a/libs/video/renderer/sw32/sw32_riqm.c b/libs/video/renderer/sw32/sw32_riqm.c deleted file mode 100644 index 193d28216..000000000 --- a/libs/video/renderer/sw32/sw32_riqm.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - sw32_riqm.c - - 32bit SW IQM rendering - - Copyright (C) 2012 Bill Currie - - Author: Bill Currie - Date: 2012/5/18 - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#include - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/cvar.h" -#include "QF/image.h" -#include "QF/render.h" -#include "QF/skin.h" -#include "QF/sys.h" - -#include "QF/scene/entity.h" - -#include "d_ifacea.h" -#include "r_internal.h" - -#define LIGHT_MIN 5 // lowest light value we'll allow, to - // avoid the need for inner-loop light - // clamping - -static vec3_t r_plightvec; -static int r_ambientlight; -static float r_shadelight; - -static inline int -calc_light (float *normal) -{ - float lightcos = DotProduct (normal, r_plightvec); - int temp = r_ambientlight; - - if (lightcos < 0) { - temp += (int) (r_shadelight * lightcos); - - // clamp; because we limited the minimum ambient and shading - // light, we don't have to clamp low light, just bright - if (temp < 0) - temp = 0; - } - return temp; -} - -static void -R_IQMTransformAndProjectFinalVerts (iqm_t *iqm, swiqm_t *sw, iqmframe_t *frame) -{ - finalvert_t *fv = pfinalverts; - float zi; - int i; - - for (i = 0; i < iqm->num_verts; i++, fv++) { - byte *vert = iqm->vertices + i * iqm->stride; - uint32_t bind = *(uint32_t *) (vert + sw->bindices->offset); - vec_t *mat = (vec_t *) &frame[bind]; - float *position = (float *) (vert + sw->position->offset); - float *normal = (float *) (vert + sw->normal->offset); - int32_t *texcoord = (int32_t *) (vert + sw->texcoord->offset); - vec3_t tv, tn; - Mat4MultVec (mat, position, tv); - Mat4as3MultVec (mat, normal, tn); - zi = 1.0 / (DotProduct (tv, sw32_aliastransform[2]) - + sw32_aliastransform[2][3]); - fv->v[5] = zi; - fv->v[0] = (DotProduct (tv, sw32_aliastransform[0]) - + sw32_aliastransform[0][3]) * zi + aliasxcenter; - fv->v[1] = (DotProduct (tv, sw32_aliastransform[1]) - + sw32_aliastransform[1][3]) * zi + aliasxcenter; - fv->v[2] = texcoord[0]; - fv->v[3] = texcoord[1]; - fv->v[4] = calc_light (tn); - } -} - -static void -iqm_setup_skin (swiqm_t *sw, int skinnum) -{ - tex_t *skin = sw->skins[skinnum]; - - sw32_r_affinetridesc.pskin = skin->data; - sw32_r_affinetridesc.skinwidth = skin->width; - sw32_r_affinetridesc.skinheight = skin->height; - sw32_r_affinetridesc.seamfixupX16 = (skin->width >> 1) << 16; -} - -static void -R_IQMPrepareUnclippedPoints (iqm_t *iqm, swiqm_t *sw, iqmframe_t *frame) -{ - int i; - - R_IQMTransformAndProjectFinalVerts (iqm, sw, frame); - - sw32_r_affinetridesc.pfinalverts = pfinalverts; - for (i = 0; i < iqm->num_meshes; i++) { - iqmmesh *mesh = &iqm->meshes[i]; - uint16_t *tris; - - iqm_setup_skin (sw, i); - - tris = iqm->elements + mesh->first_triangle; - sw32_r_affinetridesc.ptriangles = (mtriangle_t *) tris; - sw32_r_affinetridesc.numtriangles = mesh->num_triangles; - sw32_D_PolysetDraw (); - } -} - -static void -R_IQMPreparePoints (iqm_t *iqm, swiqm_t *sw, iqmframe_t *frame) -{ - finalvert_t *fv = pfinalverts; - auxvert_t *av = pauxverts; - int i; - uint32_t j; - finalvert_t *pfv[3]; - - for (i = 0; i < iqm->num_verts; i++, fv++, av++) { - byte *vert = iqm->vertices + i * iqm->stride; - uint32_t bind = *(uint32_t *) (vert + sw->bindices->offset); - vec_t *mat = (vec_t *) &frame[bind]; - float *position = (float *) (vert + sw->position->offset); - float *normal = (float *) (vert + sw->normal->offset); - int32_t *texcoord = (int32_t *) (vert + sw->texcoord->offset); - vec3_t tv, tn; - Mat4MultVec (mat, position, tv); - Mat4as3MultVec (mat, normal, tn); - av->fv[0] = DotProduct (tv, sw32_aliastransform[0]) - + sw32_aliastransform[0][3]; - av->fv[1] = DotProduct (tv, sw32_aliastransform[1]) - + sw32_aliastransform[1][3]; - av->fv[2] = DotProduct (tv, sw32_aliastransform[2]) - + sw32_aliastransform[2][3]; - fv->v[2] = texcoord[0]; - fv->v[3] = texcoord[1]; - fv->flags = 0; - fv->v[4] = calc_light (tn); - sw32_R_AliasClipAndProjectFinalVert (fv, av); - } - - for (i = 0; i < iqm->num_meshes; i++) { - iqmmesh *mesh = &iqm->meshes[i]; - mtriangle_t *mtri; - - iqm_setup_skin (sw, i); - - mtri = (mtriangle_t *) iqm->elements + mesh->first_triangle; - sw32_r_affinetridesc.numtriangles = 1; - for (j = 0; j < mesh->num_triangles; j++, mtri++) { - pfv[0] = &pfinalverts[mtri->vertindex[0]]; - pfv[1] = &pfinalverts[mtri->vertindex[1]]; - pfv[2] = &pfinalverts[mtri->vertindex[2]]; - - if (pfv[0]->flags & pfv[1]->flags & pfv[2]->flags - & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP)) - continue; // completely clipped - - if (!((pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) - & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP))) {// totally unclipped - sw32_r_affinetridesc.pfinalverts = pfinalverts; - sw32_r_affinetridesc.ptriangles = mtri; - sw32_D_PolysetDraw (); - } else { // partially clipped - sw32_R_AliasClipTriangle (mtri); - } - } - } -} - -static void -R_IQMSetupLighting (entity_t *ent, alight_t *plighting) -{ - // guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't - // have to clamp off the bottom - r_ambientlight = plighting->ambientlight; - - if (r_ambientlight < LIGHT_MIN) - r_ambientlight = LIGHT_MIN; - - r_ambientlight = (255 - r_ambientlight) << VID_CBITS; - - if (r_ambientlight < LIGHT_MIN) - r_ambientlight = LIGHT_MIN; - - r_shadelight = plighting->shadelight; - - if (r_shadelight < 0) - r_shadelight = 0; - - r_shadelight *= VID_GRADES; - - // rotate the lighting vector into the model's frame of reference - mat4f_t mat; - Transform_GetWorldMatrix (ent->transform, mat); - //FIXME vectorize - r_plightvec[0] = DotProduct (plighting->plightvec, mat[0]); - r_plightvec[1] = DotProduct (plighting->plightvec, mat[1]); - r_plightvec[2] = DotProduct (plighting->plightvec, mat[2]); -} - -static void -R_IQMSetUpTransform (int trivial_accept) -{ - int i; - float rotationmatrix[3][4]; - static float viewmatrix[3][4]; - vec3_t forward, left, up; - - mat4f_t mat; - Transform_GetWorldMatrix (currententity->transform, mat); - VectorCopy (mat[0], forward); - VectorCopy (mat[1], left); - VectorCopy (mat[2], up); - -// TODO: can do this with simple matrix rearrangement - - for (i = 0; i < 3; i++) { - rotationmatrix[i][0] = forward[i]; - rotationmatrix[i][1] = left[i]; - rotationmatrix[i][2] = up[i]; - } - - rotationmatrix[0][3] = -modelorg[0]; - rotationmatrix[1][3] = -modelorg[1]; - rotationmatrix[2][3] = -modelorg[2]; - -// TODO: should be global, set when vright, etc., set - VectorCopy (vright, viewmatrix[0]); - VectorCopy (vup, viewmatrix[1]); - VectorNegate (viewmatrix[1], viewmatrix[1]); - VectorCopy (vpn, viewmatrix[2]); - -// viewmatrix[0][3] = 0; -// viewmatrix[1][3] = 0; -// viewmatrix[2][3] = 0; - - R_ConcatTransforms (viewmatrix, rotationmatrix, sw32_aliastransform); - -// do the scaling up of x and y to screen coordinates as part of the transform -// for the unclipped case (it would mess up clipping in the clipped case). -// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y -// correspondingly so the projected x and y come out right -// FIXME: make this work for clipped case too? - - if (trivial_accept) { - for (i = 0; i < 4; i++) { - sw32_aliastransform[0][i] *= aliasxscale * - (1.0 / ((float) 0x8000 * 0x10000)); - sw32_aliastransform[1][i] *= aliasyscale * - (1.0 / ((float) 0x8000 * 0x10000)); - sw32_aliastransform[2][i] *= 1.0 / ((float) 0x8000 * 0x10000); - } - } -} - -void -sw32_R_IQMDrawModel (alight_t *plighting) -{ - entity_t *ent = currententity; - model_t *model = ent->renderer.model; - iqm_t *iqm = (iqm_t *) model->aliashdr; - swiqm_t *sw = (swiqm_t *) iqm->extra_data; - int size; - float blend; - iqmframe_t *frame; - - size = (CACHE_SIZE - 1) - + sizeof (finalvert_t) * (iqm->num_verts + 1) - + sizeof (auxvert_t) * iqm->num_verts; - blend = R_IQMGetLerpedFrames (ent, iqm); - frame = R_IQMBlendPalette (iqm, ent->animation.pose1, ent->animation.pose2, - blend, size, - sw->blend_palette, sw->palette_size); - - pfinalverts = (finalvert_t *) &frame[sw->palette_size]; - pfinalverts = (finalvert_t *) - (((intptr_t) &pfinalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - pauxverts = (auxvert_t *) &pfinalverts[iqm->num_verts + 1]; - - R_IQMSetUpTransform (ent->visibility.trivial_accept); - - R_IQMSetupLighting (ent, plighting); - - //if (!sw32_acolormap) - sw32_acolormap = vid.colormap8; - - if (ent != vr_data.view_model) - sw32_ziscale = (float) 0x8000 *(float) 0x10000; - else - sw32_ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - - if (ent->visibility.trivial_accept) - R_IQMPrepareUnclippedPoints (iqm, sw, frame); - else - R_IQMPreparePoints (iqm, sw, frame); -} diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c deleted file mode 100644 index b201ff07c..000000000 --- a/libs/video/renderer/sw32/sw32_rmain.c +++ /dev/null @@ -1,877 +0,0 @@ -/* - sw32_rmain.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include - -#include "QF/cmd.h" -#include "QF/cvar.h" -#include "QF/mathlib.h" -#include "QF/render.h" -#include "QF/screen.h" -#include "QF/sound.h" -#include "QF/sys.h" - -#include "QF/scene/entity.h" - -#include "compat.h" -#include "mod_internal.h" -#include "r_internal.h" -#include "vid_internal.h" - -//define PASSAGES - -static vec3_t viewlightvec; -static alight_t r_viewlighting = { 128, 192, viewlightvec }; -int sw32_r_numallocatededges; -qboolean sw32_r_drawpolys; -qboolean sw32_r_drawculledpolys; -qboolean sw32_r_worldpolysbacktofront; -float sw32_r_aliasuvscale = 1.0; -int sw32_r_outofsurfaces; -int sw32_r_outofedges; - -qboolean sw32_r_dowarp, sw32_r_dowarpold, sw32_r_viewchanged; - -int sw32_c_surf; -int sw32_r_maxsurfsseen, sw32_r_maxedgesseen; -static int r_cnumsurfs; -static qboolean r_surfsonstack; -int sw32_r_clipflags; - -byte *sw32_r_warpbuffer; - -static byte *r_stack_start; - -// screen size info -float sw32_xcenter, sw32_ycenter; -float sw32_xscale, sw32_yscale; -float sw32_xscaleinv, sw32_yscaleinv; -float sw32_xscaleshrink, sw32_yscaleshrink; -float sw32_aliasxscale, sw32_aliasyscale, sw32_aliasxcenter, sw32_aliasycenter; - -int sw32_screenwidth; - -float sw32_pixelAspect; -static float screenAspect; -static float verticalFieldOfView; -static float xOrigin, yOrigin; - -plane_t sw32_screenedge[4]; - -// refresh flags -int sw32_r_polycount; -int sw32_r_drawnpolycount; - -int *sw32_pfrustum_indexes[4]; -int sw32_r_frustum_indexes[4 * 6]; - -float sw32_r_aliastransition, sw32_r_resfudge; - -static float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; -static float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; - -void -sw32_R_Textures_Init (void) -{ - int x, y, m; - byte *dest; - - // create a simple checkerboard texture for the default - r_notexture_mip = - Hunk_AllocName (0, sizeof (texture_t) + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2, - "notexture"); - - r_notexture_mip->width = r_notexture_mip->height = 16; - r_notexture_mip->offsets[0] = sizeof (texture_t); - - r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16 * 16; - r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8 * 8; - r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4 * 4; - - for (m = 0; m < 4; m++) { - dest = (byte *) r_notexture_mip + r_notexture_mip->offsets[m]; - for (y = 0; y < (16 >> m); y++) - for (x = 0; x < (16 >> m); x++) { - if ((y < (8 >> m)) ^ (x < (8 >> m))) - *dest++ = 0; - else - *dest++ = 0xff; - } - } -} - -void -sw32_R_Init (void) -{ - int dummy; - - r_ent_queue = EntQueue_New (mod_num_types); - - // get stack position so we can guess if we are going to overflow - r_stack_start = (byte *) & dummy; - - R_Init_Cvars (); - sw32_R_Particles_Init_Cvars (); - - sw32_Draw_Init (); - SCR_Init (); - sw32_R_InitTurb (); - - Cmd_AddCommand ("timerefresh", sw32_R_TimeRefresh_f, "Tests the current " - "refresh rate for the current location"); - Cmd_AddCommand ("loadsky", sw32_R_LoadSky_f, "Load a skybox"); - - Cvar_SetValue (r_maxedges, (float) NUMSTACKEDGES); - Cvar_SetValue (r_maxsurfs, (float) NUMSTACKSURFACES); - - sw32_view_clipplanes[0].leftedge = true; - sw32_view_clipplanes[1].rightedge = true; - sw32_view_clipplanes[1].leftedge = sw32_view_clipplanes[2].leftedge = - sw32_view_clipplanes[3].leftedge = false; - sw32_view_clipplanes[0].rightedge = sw32_view_clipplanes[2].rightedge = - sw32_view_clipplanes[3].rightedge = false; - - r_refdef.xOrigin = XCENTERING; - r_refdef.yOrigin = YCENTERING; - - sw32_D_Init (); - - Skin_Init (); -} - -void -sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) -{ - mod_brush_t *brush = &worldmodel->brush; - - memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.renderer.model = worldmodel; - - // clear out efrags in case the level hasn't been reloaded - for (unsigned i = 0; i < brush->modleafs; i++) - brush->leafs[i].efrags = NULL; - - if (brush->skytexture) - sw32_R_InitSky (brush->skytexture); - - // Force a vis update - r_viewleaf = NULL; - R_MarkLeaves (); - - R_ClearParticles (); - - r_cnumsurfs = r_maxsurfs->int_val; - - if (r_cnumsurfs <= MINSURFACES) - r_cnumsurfs = MINSURFACES; - - if (r_cnumsurfs > NUMSTACKSURFACES) { - sw32_surfaces = Hunk_AllocName (0, r_cnumsurfs * sizeof (surf_t), - "surfaces"); - - sw32_surface_p = sw32_surfaces; - sw32_surf_max = &sw32_surfaces[r_cnumsurfs]; - r_surfsonstack = false; - // surface 0 doesn't really exist; it's just a dummy because index 0 - // is used to indicate no edge attached to surface - sw32_surfaces--; - } else { - r_surfsonstack = true; - } - - sw32_r_maxedgesseen = 0; - sw32_r_maxsurfsseen = 0; - - sw32_r_numallocatededges = r_maxedges->int_val; - - if (sw32_r_numallocatededges < MINEDGES) - sw32_r_numallocatededges = MINEDGES; - - if (sw32_r_numallocatededges <= NUMSTACKEDGES) { - sw32_auxedges = NULL; - } else { - sw32_auxedges = Hunk_AllocName (0, - sw32_r_numallocatededges * sizeof (edge_t), - "edges"); - } - - sw32_r_dowarpold = false; - sw32_r_viewchanged = false; -} - -/* - R_ViewChanged - - Called every time the vid structure or r_refdef changes. - Guaranteed to be called before the first refresh -*/ -void -sw32_R_ViewChanged (void) -{ - int i; - float res_scale; - - sw32_r_viewchanged = true; - - r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x / 360 * M_PI); - r_refdef.fvrectx = (float) r_refdef.vrect.x; - r_refdef.fvrectx_adj = (float) r_refdef.vrect.x - 0.5; - r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x << 20) + (1 << 19) - 1; - r_refdef.fvrecty = (float) r_refdef.vrect.y; - r_refdef.fvrecty_adj = (float) r_refdef.vrect.y - 0.5; - r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; - r_refdef.vrectright_adj_shift20 = - (r_refdef.vrectright << 20) + (1 << 19) - 1; - r_refdef.fvrectright = (float) r_refdef.vrectright; - r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5; - r_refdef.vrectrightedge = (float) r_refdef.vrectright - 0.99; - r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; - r_refdef.fvrectbottom = (float) r_refdef.vrectbottom; - r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5; - - r_refdef.aliasvrect.x = (int) (r_refdef.vrect.x * sw32_r_aliasuvscale); - r_refdef.aliasvrect.y = (int) (r_refdef.vrect.y * sw32_r_aliasuvscale); - r_refdef.aliasvrect.width = (int) (r_refdef.vrect.width * sw32_r_aliasuvscale); - r_refdef.aliasvrect.height = (int) (r_refdef.vrect.height * - sw32_r_aliasuvscale); - r_refdef.aliasvrectright = r_refdef.aliasvrect.x + - r_refdef.aliasvrect.width; - r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + - r_refdef.aliasvrect.height; - - sw32_pixelAspect = 1;//FIXME vid.aspect; - xOrigin = r_refdef.xOrigin; - yOrigin = r_refdef.yOrigin; - - screenAspect = r_refdef.vrect.width * sw32_pixelAspect / r_refdef.vrect.height; - // 320*200 1.0 sw32_pixelAspect = 1.6 screenAspect - // 320*240 1.0 sw32_pixelAspect = 1.3333 screenAspect - // proper 320*200 sw32_pixelAspect = 0.8333333 - - verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; - - // values for perspective projection - // if math were exact, the values would range from 0.5 to to range+0.5 - // hopefully they wll be in the 0.000001 to range+.999999 and truncate - // the polygon rasterization will never render in the first row or column - // but will definately render in the [range] row and column, so adjust the - // buffer origin to get an exact edge to edge fill - sw32_xcenter = ((float) r_refdef.vrect.width * XCENTERING) + - r_refdef.vrect.x - 0.5; - sw32_aliasxcenter = sw32_xcenter * sw32_r_aliasuvscale; - sw32_ycenter = ((float) r_refdef.vrect.height * YCENTERING) + - r_refdef.vrect.y - 0.5; - sw32_aliasycenter = sw32_ycenter * sw32_r_aliasuvscale; - - sw32_xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; - sw32_aliasxscale = sw32_xscale * sw32_r_aliasuvscale; - sw32_xscaleinv = 1.0 / sw32_xscale; - sw32_yscale = sw32_xscale * sw32_pixelAspect; - sw32_aliasyscale = sw32_yscale * sw32_r_aliasuvscale; - sw32_yscaleinv = 1.0 / sw32_yscale; - sw32_xscaleshrink = (r_refdef.vrect.width - 6) / r_refdef.horizontalFieldOfView; - sw32_yscaleshrink = sw32_xscaleshrink * sw32_pixelAspect; - - // left side clip - sw32_screenedge[0].normal[0] = -1.0 / (xOrigin * - r_refdef.horizontalFieldOfView); - sw32_screenedge[0].normal[1] = 0; - sw32_screenedge[0].normal[2] = 1; - sw32_screenedge[0].type = PLANE_ANYZ; - - // right side clip - sw32_screenedge[1].normal[0] = 1.0 / ((1.0 - xOrigin) * - r_refdef.horizontalFieldOfView); - sw32_screenedge[1].normal[1] = 0; - sw32_screenedge[1].normal[2] = 1; - sw32_screenedge[1].type = PLANE_ANYZ; - - // top side clip - sw32_screenedge[2].normal[0] = 0; - sw32_screenedge[2].normal[1] = -1.0 / (yOrigin * verticalFieldOfView); - sw32_screenedge[2].normal[2] = 1; - sw32_screenedge[2].type = PLANE_ANYZ; - - // bottom side clip - sw32_screenedge[3].normal[0] = 0; - sw32_screenedge[3].normal[1] = 1.0 / ((1.0 - yOrigin) * verticalFieldOfView); - sw32_screenedge[3].normal[2] = 1; - sw32_screenedge[3].type = PLANE_ANYZ; - - for (i = 0; i < 4; i++) - VectorNormalize (sw32_screenedge[i].normal); - - res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) / - (320.0 * 152.0)) * (2.0 / - r_refdef.horizontalFieldOfView); - sw32_r_aliastransition = r_aliastransbase->value * res_scale; - sw32_r_resfudge = r_aliastransadj->value * res_scale; - - sw32_D_ViewChanged (); -} - -static inline void -draw_sprite_entity (entity_t *ent) -{ - VectorSubtract (r_origin, r_entorigin, modelorg); - sw32_R_DrawSprite (); -} - -static inline void -setup_lighting (alight_t *lighting) -{ - float minlight = 0; - int j; - // FIXME: remove and do real lighting - vec3_t dist; - float add; - float lightvec[3] = { -1, 0, 0 }; - - minlight = max (currententity->renderer.model->min_light, - currententity->renderer.min_light); - - // 128 instead of 255 due to clamping below - j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin), - minlight * 128); - - lighting->ambientlight = j; - lighting->shadelight = j; - - lighting->plightvec = lightvec; - - for (unsigned lnum = 0; lnum < r_maxdlights; lnum++) { - if (r_dlights[lnum].die >= vr_data.realtime) { - VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist); - add = r_dlights[lnum].radius - VectorLength (dist); - - if (add > 0) - lighting->ambientlight += add; - } - } - - // clamp lighting so it doesn't overbright as much - if (lighting->ambientlight > 128) - lighting->ambientlight = 128; - if (lighting->ambientlight + lighting->shadelight > 192) - lighting->shadelight = 192 - lighting->ambientlight; -} - -static inline void -draw_alias_entity (entity_t *ent) -{ - VectorSubtract (r_origin, r_entorigin, modelorg); - - // see if the bounding box lets us trivially reject, also - // sets trivial accept status - currententity->visibility.trivial_accept = 0; //FIXME - if (R_AliasCheckBBox ()) { - alight_t lighting; - setup_lighting (&lighting); - sw32_R_AliasDrawModel (&lighting); - } -} - -static inline void -draw_iqm_entity (entity_t *ent) -{ - VectorSubtract (r_origin, r_entorigin, modelorg); - - // see if the bounding box lets us trivially reject, also - // sets trivial accept status - currententity->visibility.trivial_accept = 0; //FIXME - - alight_t lighting; - setup_lighting (&lighting); - sw32_R_IQMDrawModel (&lighting); -} - -static void -R_DrawEntitiesOnList (void) -{ - if (!r_drawentities->int_val) - return; - -#define RE_LOOP(type_name) \ - do { \ - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \ - i++) { \ - entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \ - VectorCopy (Transform_GetWorldPosition (ent->transform), \ - r_entorigin); \ - currententity = ent; \ - draw_##type_name##_entity (ent); \ - } \ - } while (0) - - RE_LOOP (alias); - RE_LOOP (iqm); - RE_LOOP (sprite); -} - -static void -R_DrawViewModel (void) -{ - // FIXME: remove and do real lighting - float lightvec[3] = { -1, 0, 0 }; - int j; - unsigned int lnum; - vec3_t dist; - float add; - float minlight; - dlight_t *dl; - - if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val - || !r_drawentities->int_val) - return; - - currententity = vr_data.view_model; - if (!currententity->renderer.model) - return; - - VectorCopy (Transform_GetWorldPosition (currententity->transform), - r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - - VectorCopy (vup, viewlightvec); - VectorNegate (viewlightvec, viewlightvec); - - minlight = max (currententity->renderer.min_light, - currententity->renderer.model->min_light); - - j = max (R_LightPoint (&r_worldentity.renderer.model->brush, - r_entorigin), minlight * 128); - - r_viewlighting.ambientlight = j; - r_viewlighting.shadelight = j; - - // add dynamic lights - for (lnum = 0; lnum < r_maxdlights; lnum++) { - dl = &r_dlights[lnum]; - if (!dl->radius) - continue; - if (!dl->radius) - continue; - if (dl->die < vr_data.realtime) - continue; - - VectorSubtract (r_entorigin, dl->origin, dist); - add = dl->radius - VectorLength (dist); - if (add > 0) - r_viewlighting.ambientlight += add; - } - - // clamp lighting so it doesn't overbright as much - if (r_viewlighting.ambientlight > 128) - r_viewlighting.ambientlight = 128; - if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192) - r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight; - - r_viewlighting.plightvec = lightvec; - - sw32_R_AliasDrawModel (&r_viewlighting); -} - -static int -R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) -{ - int i, *pindex, clipflags; - vec3_t acceptpt, rejectpt; - double d; - mat4f_t mat; - - clipflags = 0; - - Transform_GetWorldMatrix (currententity->transform, mat); - if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { - for (i = 0; i < 4; i++) { - d = DotProduct (mat[3], sw32_view_clipplanes[i].normal); - d -= sw32_view_clipplanes[i].dist; - - if (d <= -clmodel->radius) - return BMODEL_FULLY_CLIPPED; - - if (d <= clmodel->radius) - clipflags |= (1 << i); - } - } else { - for (i = 0; i < 4; i++) { - // generate accept and reject points - // FIXME: do with fast look-ups or integer tests based on the - // sign bit of the floating point values - - pindex = sw32_pfrustum_indexes[i]; - - rejectpt[0] = minmaxs[pindex[0]]; - rejectpt[1] = minmaxs[pindex[1]]; - rejectpt[2] = minmaxs[pindex[2]]; - - d = DotProduct (rejectpt, sw32_view_clipplanes[i].normal); - d -= sw32_view_clipplanes[i].dist; - - if (d <= 0) - return BMODEL_FULLY_CLIPPED; - - acceptpt[0] = minmaxs[pindex[3 + 0]]; - acceptpt[1] = minmaxs[pindex[3 + 1]]; - acceptpt[2] = minmaxs[pindex[3 + 2]]; - - d = DotProduct (acceptpt, sw32_view_clipplanes[i].normal); - d -= sw32_view_clipplanes[i].dist; - - if (d <= 0) - clipflags |= (1 << i); - } - } - - return clipflags; -} - -static void -R_DrawBEntitiesOnList (void) -{ - int j, clipflags; - unsigned int k; - vec3_t oldorigin; - vec3_t origin; - model_t *clmodel; - float minmaxs[6]; - - if (!r_drawentities->int_val) - return; - - VectorCopy (modelorg, oldorigin); - insubmodel = true; - - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { - entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; - currententity = ent; - - VectorCopy (Transform_GetWorldPosition (ent->transform), origin); - clmodel = ent->renderer.model; - - // see if the bounding box lets us trivially reject, also - // sets trivial accept status - for (j = 0; j < 3; j++) { - minmaxs[j] = origin[j] + clmodel->mins[j]; - minmaxs[3 + j] = origin[j] + clmodel->maxs[j]; - } - - clipflags = R_BmodelCheckBBox (clmodel, minmaxs); - - if (clipflags != BMODEL_FULLY_CLIPPED) { - mod_brush_t *brush = &clmodel->brush; - VectorCopy (origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - - // FIXME: is this needed? - VectorCopy (modelorg, sw32_r_worldmodelorg); - r_pcurrentvertbase = brush->vertexes; - - // FIXME: stop transforming twice - sw32_R_RotateBmodel (); - - // calculate dynamic lighting for bmodel if it's not an - // instanced model - if (brush->firstmodelsurface != 0) { - vec3_t lightorigin; - - for (k = 0; k < r_maxdlights; k++) { - if ((r_dlights[k].die < vr_data.realtime) || - (!r_dlights[k].radius)) { - continue; - } - - VectorSubtract (r_dlights[k].origin, origin, lightorigin); - R_RecursiveMarkLights (brush, lightorigin, - &r_dlights[k], k, - brush->nodes - + brush->hulls[0].firstclipnode); - } - } - // if the driver wants polygons, deliver those. - // Z-buffering is on at this point, so no clipping to the - // world tree is needed, just frustum clipping - if (sw32_r_drawpolys | sw32_r_drawculledpolys) { - sw32_R_ZDrawSubmodelPolys (clmodel); - } else { - if (ent->visibility.topnode) { - mnode_t *topnode = ent->visibility.topnode; - - if (topnode->contents >= 0) { - // not a leaf; has to be clipped to the world - // BSP - sw32_r_clipflags = clipflags; - sw32_R_DrawSolidClippedSubmodelPolygons (clmodel); - } else { - // falls entirely in one leaf, so we just put - // all the edges in the edge list and let 1/z - // sorting handle drawing order - sw32_R_DrawSubmodelPolygons (clmodel, clipflags); - } - } - } - - // put back world rotation and frustum clipping - // FIXME: sw32_R_RotateBmodel should just work off base_vxx - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); - VectorCopy (oldorigin, modelorg); - sw32_R_TransformFrustum (); - } - } - - insubmodel = false; -} - -static void -R_PrintDSpeeds (void) -{ - float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, - - dv_time; - - r_time2 = Sys_DoubleTime (); - - dp_time = (dp_time2 - dp_time1) * 1000; - rw_time = (rw_time2 - rw_time1) * 1000; - db_time = (db_time2 - db_time1) * 1000; - se_time = (se_time2 - se_time1) * 1000; - de_time = (de_time2 - de_time1) * 1000; - dv_time = (dv_time2 - dv_time1) * 1000; - ms = (r_time2 - r_time1) * 1000; - - Sys_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n", - (int) ms, dp_time, (int) rw_time, db_time, (int) se_time, - de_time, dv_time); -} - -static void -R_EdgeDrawing (void) -{ - edge_t ledges[NUMSTACKEDGES + - ((CACHE_SIZE - 1) / sizeof (edge_t)) + 1]; - surf_t lsurfs[NUMSTACKSURFACES + - ((CACHE_SIZE - 1) / sizeof (surf_t)) + 1]; - - if (sw32_auxedges) { - sw32_r_edges = sw32_auxedges; - } else { - sw32_r_edges = (edge_t *) - (((intptr_t) &ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - } - - if (r_surfsonstack) { - sw32_surfaces = (surf_t *) - (((intptr_t) &lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - sw32_surf_max = &sw32_surfaces[r_cnumsurfs]; - // surface 0 doesn't really exist; it's just a dummy because index 0 - // is used to indicate no edge attached to surface - sw32_surfaces--; - } - - sw32_R_BeginEdgeFrame (); - - if (r_dspeeds->int_val) { - rw_time1 = Sys_DoubleTime (); - } - - sw32_R_RenderWorld (); - - if (sw32_r_drawculledpolys) - sw32_R_ScanEdges (); - - // only the world can be drawn back to front with no z reads or compares, - // just z writes, so have the driver turn z compares on now - sw32_D_TurnZOn (); - - if (r_dspeeds->int_val) { - rw_time2 = Sys_DoubleTime (); - db_time1 = rw_time2; - } - - R_DrawBEntitiesOnList (); - - if (r_dspeeds->int_val) { - db_time2 = Sys_DoubleTime (); - se_time1 = db_time2; - } - - if (!r_dspeeds->int_val) { - S_ExtraUpdate (); // don't let sound get messed up if going slow - } - - if (!(sw32_r_drawpolys | sw32_r_drawculledpolys)) - sw32_R_ScanEdges (); -} - -// LordHavoc: took out of stack and made 4x size for 32bit capacity -static byte warpbuffer[WARP_WIDTH * WARP_HEIGHT * 4]; - -/* - R_RenderView - - r_refdef must be set before the first call -*/ -static void -R_RenderView_ (void) -{ - if (r_norefresh->int_val) - return; - if (!r_worldentity.renderer.model) { - return; - } - - sw32_r_warpbuffer = warpbuffer; - - if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val) - r_time1 = Sys_DoubleTime (); - - sw32_R_SetupFrame (); - -#ifdef PASSAGES - SetVisibilityByPassages (); -#else - R_MarkLeaves (); // done here so we know if we're in water -#endif - R_PushDlights (vec3_origin); - - if (!r_dspeeds->int_val) { - S_ExtraUpdate (); // don't let sound get messed up if going slow - } - - R_EdgeDrawing (); - - if (!r_dspeeds->int_val) { - S_ExtraUpdate (); // don't let sound get messed up if going slow - } - - if (r_dspeeds->int_val) { - se_time2 = Sys_DoubleTime (); - de_time1 = se_time2; - } - - R_DrawEntitiesOnList (); - - if (r_dspeeds->int_val) { - de_time2 = Sys_DoubleTime (); - dv_time1 = de_time2; - } - - R_DrawViewModel (); - - if (r_dspeeds->int_val) { - dv_time2 = Sys_DoubleTime (); - dp_time1 = Sys_DoubleTime (); - } - - sw32_R_DrawParticles (); - - if (r_dspeeds->int_val) - dp_time2 = Sys_DoubleTime (); - - if (sw32_r_dowarp) - sw32_D_WarpScreen (); - - if (r_timegraph->int_val) - R_TimeGraph (); - - if (r_zgraph->int_val) - R_ZGraph (); - - if (r_aliasstats->int_val) - sw32_R_PrintAliasStats (); - - if (r_speeds->int_val) - sw32_R_PrintTimes (); - - if (r_dspeeds->int_val) - R_PrintDSpeeds (); - - if (r_reportsurfout->int_val && sw32_r_outofsurfaces) - Sys_Printf ("Short %d surfaces\n", sw32_r_outofsurfaces); - - if (r_reportedgeout->int_val && sw32_r_outofedges) - Sys_Printf ("Short roughly %d edges\n", sw32_r_outofedges * 2 / 3); -} - -void -sw32_R_RenderView (void) -{ - int dummy; - int delta; - - delta = (byte *) & dummy - r_stack_start; - if (delta < -10000 || delta > 10000) - Sys_Error ("R_RenderView: called without enough stack"); - - if (Hunk_LowMark (0) & 3) - Sys_Error ("Hunk is missaligned"); - - if ((intptr_t) (&dummy) & 3) - Sys_Error ("Stack is missaligned"); - - if ((intptr_t) (&sw32_r_warpbuffer) & 3) - Sys_Error ("Globals are missaligned"); - - R_RenderView_ (); -} - -void -sw32_R_InitTurb (void) -{ - int i; - - for (i = 0; i < MAXWIDTH; i++) { - sw32_sintable[i] = AMP + sin (i * 3.14159 * 2 / CYCLE) * AMP; - sw32_intsintable[i] = AMP2 + sin (i * 3.14159 * 2 / CYCLE) * AMP2; - // AMP2 not 20 - } -} - -void -sw32_R_ClearState (void) -{ - r_worldentity.renderer.model = 0; - R_ClearEfrags (); - R_ClearDlights (); - R_ClearParticles (); -} diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c deleted file mode 100644 index 6d40529cc..000000000 --- a/libs/video/renderer/sw32/sw32_rmisc.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - sw32_rmisc.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/cmd.h" -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/render.h" -#include "QF/sys.h" -#include "QF/ui/view.h" - -#include "QF/scene/entity.h" - -#include "compat.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - -static void -R_CheckVariables (void) -{ -} - -/* - R_TimeRefresh_f - - For program optimization -*/ -void -sw32_R_TimeRefresh_f (void) -{ -/* FIXME update for simd - int i; - float start, stop, time; - int startangle; - vrect_t vr; - - startangle = r_refdef.viewangles[1]; - - start = Sys_DoubleTime (); - for (i = 0; i < 128; i++) { - r_refdef.viewangles[1] = i / 128.0 * 360.0; - - sw32_R_RenderView (); - - vr.x = r_refdef.vrect.x; - vr.y = r_refdef.vrect.y; - vr.width = r_refdef.vrect.width; - vr.height = r_refdef.vrect.height; - vr.next = NULL; - sw32_ctx->update (&vr); - } - stop = Sys_DoubleTime (); - time = stop - start; - Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); - - r_refdef.viewangles[1] = startangle; -*/ -} - -void -sw32_R_LoadSky_f (void) -{ - if (Cmd_Argc () != 2) { - Sys_Printf ("loadsky : load a skybox\n"); - return; - } - - sw32_R_LoadSkys (Cmd_Argv (1)); -} - -void -sw32_R_PrintTimes (void) -{ - float r_time2; - float ms; - - r_time2 = Sys_DoubleTime (); - - ms = 1000 * (r_time2 - r_time1); - - Sys_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n", - ms, sw32_c_faceclip, sw32_r_polycount, sw32_r_drawnpolycount, sw32_c_surf); - sw32_c_surf = 0; -} - -void -sw32_R_PrintAliasStats (void) -{ - Sys_Printf ("%3i polygon model drawn\n", sw32_r_amodels_drawn); -} - -void -sw32_R_TransformFrustum (void) -{ - int i; - vec3_t v, v2; - - for (i = 0; i < 4; i++) { - v[0] = sw32_screenedge[i].normal[2]; - v[1] = -sw32_screenedge[i].normal[0]; - v[2] = sw32_screenedge[i].normal[1]; - - v2[0] = v[1] * vright[0] + v[2] * vup[0] + v[0] * vpn[0]; - v2[1] = v[1] * vright[1] + v[2] * vup[1] + v[0] * vpn[1]; - v2[2] = v[1] * vright[2] + v[2] * vup[2] + v[0] * vpn[2]; - - VectorCopy (v2, sw32_view_clipplanes[i].normal); - - sw32_view_clipplanes[i].dist = DotProduct (modelorg, v2); - } -} - -void -sw32_TransformVector (const vec3_t in, vec3_t out) -{ - out[0] = DotProduct (in, vright); - out[1] = DotProduct (in, vup); - out[2] = DotProduct (in, vpn); -} - -void -sw32_R_TransformPlane (plane_t *p, float *normal, float *dist) -{ - float d; - - d = DotProduct (r_origin, p->normal); - *dist = p->dist - d; -// TODO: when we have rotating entities, this will need to use the view matrix - sw32_TransformVector (p->normal, normal); -} - -static void -R_SetUpFrustumIndexes (void) -{ - int i, j, *pindex; - - pindex = sw32_r_frustum_indexes; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 3; j++) { - if (sw32_view_clipplanes[i].normal[j] < 0) { - pindex[j] = j; - pindex[j + 3] = j + 3; - } else { - pindex[j] = j + 3; - pindex[j + 3] = j; - } - } - - // FIXME: do just once at start - sw32_pfrustum_indexes[i] = pindex; - pindex += 6; - } -} - -void -sw32_R_SetupFrame (void) -{ - int edgecount; - vrect_t vrect; - float w, h; - - // don't allow cheats in multiplayer - Cvar_SetValue (r_ambient, 0); - Cvar_SetValue (r_drawflat, 0); - - if (r_numsurfs->int_val) { - if ((sw32_surface_p - sw32_surfaces) > sw32_r_maxsurfsseen) - sw32_r_maxsurfsseen = sw32_surface_p - sw32_surfaces; - - Sys_Printf ("Used %ld of %ld surfs; %d max\n", - (long) (sw32_surface_p - sw32_surfaces), - (long) (sw32_surf_max - sw32_surfaces), sw32_r_maxsurfsseen); - } - - if (r_numedges->int_val) { - edgecount = sw32_edge_p - sw32_r_edges; - - if (edgecount > sw32_r_maxedgesseen) - sw32_r_maxedgesseen = edgecount; - - Sys_Printf ("Used %d of %d edges; %d max\n", edgecount, - sw32_r_numallocatededges, sw32_r_maxedgesseen); - } - - r_refdef.ambientlight = max (r_ambient->value, 0); - - R_CheckVariables (); - - R_AnimateLight (); - EntQueue_Clear (r_ent_queue); - r_framecount++; - - sw32_numbtofpolys = 0; - - // debugging -#if 0 - r_refdef.vieworg[0] = 80; - r_refdef.vieworg[1] = 64; - r_refdef.vieworg[2] = 40; - r_refdef.viewangles[0] = 0; - r_refdef.viewangles[1] = 46.763641357; - r_refdef.viewangles[2] = 0; -#endif - - // build the transformation matrix for the given view angles - VectorCopy (r_refdef.viewposition, modelorg); - VectorCopy (r_refdef.viewposition, r_origin); - - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); - R_SetFrustum (); - - // current viewleaf - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); - - sw32_r_dowarpold = sw32_r_dowarp; - sw32_r_dowarp = r_waterwarp->int_val && (r_viewleaf->contents <= - CONTENTS_WATER); - - if ((sw32_r_dowarp != sw32_r_dowarpold) || sw32_r_viewchanged) { - if (sw32_r_dowarp) { - if ((vid.width <= WARP_WIDTH) - && (vid.height <= WARP_HEIGHT)) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - - R_SetVrect (&vrect, &r_refdef.vrect, vr_data.lineadj); - sw32_R_ViewChanged (); - } else { - w = vid.width; - h = vid.height; - - if (w > WARP_WIDTH) { - h *= (float) WARP_WIDTH / w; - w = WARP_WIDTH; - } - - if (h > WARP_HEIGHT) { - h = WARP_HEIGHT; - w *= (float) WARP_HEIGHT / h; - } - - vrect.x = 0; - vrect.y = 0; - vrect.width = (int) w; - vrect.height = (int) h; - - R_SetVrect (&vrect, &r_refdef.vrect, - (int) ((float) vr_data.lineadj * - (h / (float) vid.height))); - sw32_R_ViewChanged (); - } - } else { - r_refdef.vrect.x = vr_data.scr_view->xpos; - r_refdef.vrect.y = vr_data.scr_view->ypos; - r_refdef.vrect.width = vr_data.scr_view->xlen; - r_refdef.vrect.height = vr_data.scr_view->ylen; - sw32_R_ViewChanged (); - } - - sw32_r_viewchanged = false; - } - // start off with just the four screen edge clip planes - sw32_R_TransformFrustum (); - - // save base values - VectorCopy (vpn, base_vpn); - VectorCopy (vright, base_vright); - VectorCopy (vup, base_vup); - VectorCopy (modelorg, base_modelorg); - - sw32_R_SetSkyFrame (); - - R_SetUpFrustumIndexes (); - - r_cache_thrash = false; - - // clear frame counts - sw32_c_faceclip = 0; - sw32_r_polycount = 0; - sw32_r_drawnpolycount = 0; - sw32_r_amodels_drawn = 0; - sw32_r_outofsurfaces = 0; - sw32_r_outofedges = 0; - - sw32_D_SetupFrame (); -} diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c deleted file mode 100644 index d43397a89..000000000 --- a/libs/video/renderer/sw32/sw32_rpart.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - sw32_rpart.c - - 24 bit color software renderer particle effects. - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cvar.h" -#include "QF/mersenne.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/sys.h" -#include "QF/va.h" - -#include "QF/scene/entity.h" - -#include "compat.h" -#include "r_internal.h" - -void -sw32_R_DrawParticles (void) -{ - VectorScale (vright, xscaleshrink, r_pright); - VectorScale (vup, yscaleshrink, r_pup); - VectorCopy (vpn, r_ppn); - - R_RunParticles (vr_data.frametime); - - for (unsigned i = 0; i < r_psystem.numparticles; i++) { - particle_t *p = &r_psystem.particles[i]; - sw32_D_DrawParticle (p); - } -} - -static void -r_particles_nearclip_f (cvar_t *var) -{ - Cvar_SetValue (r_particles_nearclip, bound (r_nearclip->value, var->value, - r_farclip->value)); -} - -static void -r_particles_f (cvar_t *var) -{ - R_MaxParticlesCheck (var, r_particles_max); -} - -static void -r_particles_max_f (cvar_t *var) -{ - R_MaxParticlesCheck (r_particles, var); -} - -void -sw32_R_Particles_Init_Cvars (void) -{ - r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, - "Toggles drawing of particles."); - r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, - r_particles_max_f, "Maximum amount of " - "particles to display. No maximum, minimum " - "is 0."); - r_particles_nearclip = Cvar_Get ("r_particles_nearclip", "32", - CVAR_ARCHIVE, r_particles_nearclip_f, - "Distance of the particle near clipping " - "plane from the player."); -} - -psystem_t * __attribute__((const))//FIXME -sw32_ParticleSystem (void) -{ - return &r_psystem; -} diff --git a/libs/video/renderer/sw32/sw32_rsky.c b/libs/video/renderer/sw32/sw32_rsky.c deleted file mode 100644 index c07f07570..000000000 --- a/libs/video/renderer/sw32/sw32_rsky.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - r_sky.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#ifdef HAVE_STRING_H -# include "string.h" -#endif -#ifdef HAVE_STRINGS_H -# include "strings.h" -#endif - -#include "QF/sys.h" -#include "QF/render.h" - -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - - -static int iskyspeed = 8; -static int iskyspeed2 = 2; -float sw32_r_skyspeed; - -float sw32_r_skytime; - -byte *sw32_r_skysource; - -int sw32_r_skymade; - -// TODO: clean up these routines - -/* -byte bottomsky[128 * 131]; -byte bottommask[128 * 131]; -byte newsky[128 * 256]; // newsky and topsky both pack in here, - // 128 bytes of newsky on the left of - // each scan, 128 bytes of topsky on - // the right, because the low-level - // drawers need 256-byte scan widths -*/ -static byte skydata[128*256]; // sky layers for making skytex -static byte skytex[128*256*4]; // current sky texture - - -/* - R_InitSky - - A sky texture is 256*128, with the right side being a masked overlay -*/ -void -sw32_R_InitSky (texture_t *mt) -{ - /* - int i, j; - byte *src; - - src = (byte *) mt + mt->offsets[0]; - - for (i = 0; i < 128; i++) { - for (j = 0; j < 128; j++) { - newsky[(i * 256) + j + 128] = src[i * 256 + j + 128]; - } - } - - for (i = 0; i < 128; i++) { - for (j = 0; j < 131; j++) { - if (src[i * 256 + (j & 0x7F)]) { - bottomsky[(i * 131) + j] = src[i * 256 + (j & 0x7F)]; - bottommask[(i * 131) + j] = 0; - } else { - bottomsky[(i * 131) + j] = 0; - bottommask[(i * 131) + j] = 0xff; - } - } - } - - sw32_r_skysource = newsky; - */ - - // LordHavoc: save sky for use - memcpy(skydata, (byte *) mt + mt->offsets[0], 128*256); - sw32_r_skysource = skytex; -} - -void -sw32_R_MakeSky (void) -{ - int x, y, xshift1, yshift1, xshift2, yshift2; - byte *base1, *base2; - static int xlast = -1, ylast = -1; - - xshift2 = sw32_r_skytime * sw32_r_skyspeed * 2.0f; - yshift2 = sw32_r_skytime * sw32_r_skyspeed * 2.0f; - - if ((xshift2 == xlast) && (yshift2 == ylast)) - return; - - xlast = xshift2; - ylast = yshift2; - xshift1 = xshift2 >> 1; - yshift1 = yshift2 >> 1; - - switch(sw32_ctx->pixbytes) - { - case 1: - { - byte *out = (byte *) skytex; - for (y = 0;y < 128;y++) - { - base1 = &skydata[((y + yshift1) & 127) * 256]; - base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; - for (x = 0;x < 128;x++) - { - if (base1[(x + xshift1) & 127]) - *out = base1[(x + xshift1) & 127]; - else - *out = base2[(x + xshift2) & 127]; - out++; - } - out += 128; - } - } - break; - case 2: - { - unsigned short *out = (unsigned short *) skytex; - for (y = 0;y < 128;y++) - { - base1 = &skydata[((y + yshift1) & 127) * 256]; - base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; - for (x = 0;x < 128;x++) - { - if (base1[(x + xshift1) & 127]) - *out = sw32_8to16table[base1[(x + xshift1) & 127]]; - else - *out = sw32_8to16table[base2[(x + xshift2) & 127]]; - out++; - } - out += 128; - } - } - break; - case 4: - { - unsigned int *out = (unsigned int *) skytex; - for (y = 0;y < 128;y++) - { - base1 = &skydata[((y + yshift1) & 127) * 256]; - base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; - for (x = 0;x < 128;x++) - { - if (base1[(x + xshift1) & 127]) - *out = d_8to24table[base1[(x + xshift1) & 127]]; - else - *out = d_8to24table[base2[(x + xshift2) & 127]]; - out++; - } - out += 128; - } - } - break; - default: - Sys_Error("R_MakeSky: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - } - sw32_r_skymade = 1; -} - - -void -sw32_R_SetSkyFrame (void) -{ - int g, s1, s2; - float temp; - - sw32_r_skyspeed = iskyspeed; - - g = GreatestCommonDivisor (iskyspeed, iskyspeed2); - s1 = iskyspeed / g; - s2 = iskyspeed2 / g; - temp = SKYSIZE * s1 * s2; - - sw32_r_skytime = vr_data.realtime - ((int) (vr_data.realtime / temp) * temp); - - sw32_r_skymade = 0; -} - - -/* - Stub function for loading a skybox. Currently we have support for - skyboxes only in GL targets, so we just do nothing here. --KB -*/ -void -sw32_R_LoadSkys (const char *name) -{ -} diff --git a/libs/video/renderer/sw32/sw32_rsprite.c b/libs/video/renderer/sw32/sw32_rsprite.c deleted file mode 100644 index 40f8f5a38..000000000 --- a/libs/video/renderer/sw32/sw32_rsprite.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - sw32_rsprite.c - - (description) - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include - -#include "QF/render.h" -#include "QF/sys.h" - -#include "QF/scene/entity.h" - -#include "r_internal.h" - -static int clip_current; -static vec5_t clip_verts[2][MAXWORKINGVERTS]; -static int sprite_width, sprite_height; - -spritedesc_t sw32_r_spritedesc; - - -static void -R_RotateSprite (float beamlength) -{ - vec3_t vec; - - if (beamlength == 0.0) - return; - - VectorScale (sw32_r_spritedesc.vpn, -beamlength, vec); - VectorAdd (r_entorigin, vec, r_entorigin); - VectorSubtract (modelorg, vec, modelorg); -} - - -/* - R_ClipSpriteFace - - Clips the winding at clip_verts[clip_current] and changes clip_current - Throws out the back side -*/ -static int -R_ClipSpriteFace (int nump, clipplane_t *pclipplane) -{ - int i, outcount; - float dists[MAXWORKINGVERTS + 1]; - float frac, clipdist, *pclipnormal; - float *in, *instep, *outstep, *vert2; - - clipdist = pclipplane->dist; - pclipnormal = pclipplane->normal; - - // calc dists - if (clip_current) { - in = clip_verts[1][0]; - outstep = clip_verts[0][0]; - clip_current = 0; - } else { - in = clip_verts[0][0]; - outstep = clip_verts[1][0]; - clip_current = 1; - } - - instep = in; - for (i = 0; i < nump; i++, instep += sizeof (vec5_t) / sizeof (float)) { - dists[i] = DotProduct (instep, pclipnormal) - clipdist; - } - - // handle wraparound case - dists[nump] = dists[0]; - memcpy (instep, in, sizeof (vec5_t)); - - // clip the winding - instep = in; - outcount = 0; - - for (i = 0; i < nump; i++, instep += sizeof (vec5_t) / sizeof (float)) { - if (dists[i] >= 0) { - memcpy (outstep, instep, sizeof (vec5_t)); - outstep += sizeof (vec5_t) / sizeof (float); - outcount++; - } - - if (dists[i] == 0 || dists[i + 1] == 0) - continue; - - if ((dists[i] > 0) == (dists[i + 1] > 0)) - continue; - - // split it into a new vertex - frac = dists[i] / (dists[i] - dists[i + 1]); - - vert2 = instep + sizeof (vec5_t) / sizeof (float); - - outstep[0] = instep[0] + frac * (vert2[0] - instep[0]); - outstep[1] = instep[1] + frac * (vert2[1] - instep[1]); - outstep[2] = instep[2] + frac * (vert2[2] - instep[2]); - outstep[3] = instep[3] + frac * (vert2[3] - instep[3]); - outstep[4] = instep[4] + frac * (vert2[4] - instep[4]); - - outstep += sizeof (vec5_t) / sizeof (float); - - outcount++; - } - - return outcount; -} - - -static void -R_SetupAndDrawSprite (void) -{ - int i, nump; - float dot, scale, *pv; - vec5_t *pverts; - vec3_t left, up, right, down, transformed, local; - emitpoint_t outverts[MAXWORKINGVERTS + 1], *pout; - - dot = DotProduct (sw32_r_spritedesc.vpn, modelorg); - - // backface cull - if (dot >= 0) - return; - - // build the sprite poster in worldspace - VectorScale (sw32_r_spritedesc.vright, sw32_r_spritedesc.pspriteframe->right, right); - VectorScale (sw32_r_spritedesc.vup, sw32_r_spritedesc.pspriteframe->up, up); - VectorScale (sw32_r_spritedesc.vright, sw32_r_spritedesc.pspriteframe->left, left); - VectorScale (sw32_r_spritedesc.vup, sw32_r_spritedesc.pspriteframe->down, down); - - pverts = clip_verts[0]; - - pverts[0][0] = r_entorigin[0] + up[0] + left[0]; - pverts[0][1] = r_entorigin[1] + up[1] + left[1]; - pverts[0][2] = r_entorigin[2] + up[2] + left[2]; - pverts[0][3] = 0; - pverts[0][4] = 0; - - pverts[1][0] = r_entorigin[0] + up[0] + right[0]; - pverts[1][1] = r_entorigin[1] + up[1] + right[1]; - pverts[1][2] = r_entorigin[2] + up[2] + right[2]; - pverts[1][3] = sprite_width; - pverts[1][4] = 0; - - pverts[2][0] = r_entorigin[0] + down[0] + right[0]; - pverts[2][1] = r_entorigin[1] + down[1] + right[1]; - pverts[2][2] = r_entorigin[2] + down[2] + right[2]; - pverts[2][3] = sprite_width; - pverts[2][4] = sprite_height; - - pverts[3][0] = r_entorigin[0] + down[0] + left[0]; - pverts[3][1] = r_entorigin[1] + down[1] + left[1]; - pverts[3][2] = r_entorigin[2] + down[2] + left[2]; - pverts[3][3] = 0; - pverts[3][4] = sprite_height; - - // clip to the frustum in worldspace - nump = 4; - clip_current = 0; - - for (i = 0; i < 4; i++) { - nump = R_ClipSpriteFace (nump, &sw32_view_clipplanes[i]); - if (nump < 3) - return; - if (nump >= MAXWORKINGVERTS) - Sys_Error ("R_SetupAndDrawSprite: too many points"); - } - - // transform vertices into viewspace and project - pv = &clip_verts[clip_current][0][0]; - sw32_r_spritedesc.nearzi = -999999; - - for (i = 0; i < nump; i++) { - VectorSubtract (pv, r_origin, local); - sw32_TransformVector (local, transformed); - - if (transformed[2] < NEAR_CLIP) - transformed[2] = NEAR_CLIP; - - pout = &outverts[i]; - pout->zi = 1.0 / transformed[2]; - if (pout->zi > sw32_r_spritedesc.nearzi) - sw32_r_spritedesc.nearzi = pout->zi; - - pout->s = pv[3]; - pout->t = pv[4]; - - scale = sw32_xscale * pout->zi; - pout->u = (sw32_xcenter + scale * transformed[0]); - - scale = sw32_yscale * pout->zi; - pout->v = (sw32_ycenter - scale * transformed[1]); - - pv += sizeof (vec5_t) / sizeof (*pv); - } - - // draw it - sw32_r_spritedesc.nump = nump; - sw32_r_spritedesc.pverts = outverts; - sw32_D_DrawSprite (); -} - - -void -sw32_R_DrawSprite (void) -{ - msprite_t *sprite = currententity->renderer.model->cache.data; - - sw32_r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, - ¤tentity->animation); - - sprite_width = sw32_r_spritedesc.pspriteframe->width; - sprite_height = sw32_r_spritedesc.pspriteframe->height; - - if (!R_BillboardFrame (currententity, sprite->type, modelorg, - r_spritedesc.vup, - r_spritedesc.vright, - r_spritedesc.vpn)) { - // the orientation is undefined so can't draw the sprite - return; - } - - R_RotateSprite (sprite->beamlength); - - R_SetupAndDrawSprite (); -} diff --git a/libs/video/renderer/sw32/sw32_rsurf.c b/libs/video/renderer/sw32/sw32_rsurf.c deleted file mode 100644 index dac3e2173..000000000 --- a/libs/video/renderer/sw32/sw32_rsurf.c +++ /dev/null @@ -1,898 +0,0 @@ -/* - sw32_rsurf.c - - surface-related refresh code - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "namehack.h" - -#include "QF/render.h" -#include "QF/sys.h" - -#include "QF/scene/entity.h" - -#include "compat.h" -#include "r_internal.h" -#include "vid_sw.h" - -drawsurf_t sw32_r_drawsurf; - -static int lightleft, blocksize, sourcetstep; -static int lightright, lightleftstep, lightrightstep, blockdivshift; -static unsigned int blockdivmask; -static byte *prowdestbase; -static byte *psource; -static int surfrowbytes; -static int *r_lightptr; -static int r_stepback; -static int r_lightwidth; -static int r_numhblocks, r_numvblocks; -static byte *r_source, *r_sourcemax; - -static void R_DrawSurfaceBlock8_mip0 (void); -static void R_DrawSurfaceBlock8_mip1 (void); -static void R_DrawSurfaceBlock8_mip2 (void); -static void R_DrawSurfaceBlock8_mip3 (void); -static void R_DrawSurfaceBlock16_mip0 (void); -static void R_DrawSurfaceBlock16_mip1 (void); -static void R_DrawSurfaceBlock16_mip2 (void); -static void R_DrawSurfaceBlock16_mip3 (void); -static void R_DrawSurfaceBlock32_mip0 (void); -static void R_DrawSurfaceBlock32_mip1 (void); -static void R_DrawSurfaceBlock32_mip2 (void); -static void R_DrawSurfaceBlock32_mip3 (void); - -static void (*surfmiptable8[4]) (void) = { - R_DrawSurfaceBlock8_mip0, - R_DrawSurfaceBlock8_mip1, - R_DrawSurfaceBlock8_mip2, - R_DrawSurfaceBlock8_mip3 -}; - -static void (*surfmiptable16[4]) (void) = { - R_DrawSurfaceBlock16_mip0, - R_DrawSurfaceBlock16_mip1, - R_DrawSurfaceBlock16_mip2, - R_DrawSurfaceBlock16_mip3 -}; - -static void (*surfmiptable32[4]) (void) = { - R_DrawSurfaceBlock32_mip0, - R_DrawSurfaceBlock32_mip1, - R_DrawSurfaceBlock32_mip2, - R_DrawSurfaceBlock32_mip3 -}; - -static int blocklights[34 * 34]; //FIXME make dynamic - - -static void -R_AddDynamicLights (void) -{ - msurface_t *surf; - unsigned int lnum; - int sd, td; - float dist, rad, minlight; - vec3_t impact, local, lightorigin; - vec4f_t entorigin = { 0, 0, 0, 1 }; - int s, t; - int i; - int smax, tmax; - mtexinfo_t *tex; - - surf = sw32_r_drawsurf.surf; - smax = (surf->extents[0] >> 4) + 1; - tmax = (surf->extents[1] >> 4) + 1; - tex = surf->texinfo; - - if (currententity->transform) { - //FIXME give world entity a transform - entorigin = Transform_GetWorldPosition (currententity->transform); - } - - for (lnum = 0; lnum < r_maxdlights; lnum++) { - if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32)))) - continue; // not lit by this light - - VectorSubtract (r_dlights[lnum].origin, entorigin, lightorigin); - rad = r_dlights[lnum].radius; - dist = DotProduct (lightorigin, surf->plane->normal) - - surf->plane->dist; - rad -= fabs (dist); - minlight = r_dlights[lnum].minlight; - if (rad < minlight) - continue; - minlight = rad - minlight; - - for (i = 0; i < 3; i++) - impact[i] = lightorigin[i] - surf->plane->normal[i] * dist; - - local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]; - local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]; - - local[0] -= surf->texturemins[0]; - local[1] -= surf->texturemins[1]; - - for (t = 0; t < tmax; t++) { - td = local[1] - t * 16; - if (td < 0) - td = -td; - for (s = 0; s < smax; s++) { - sd = local[0] - s * 16; - if (sd < 0) - sd = -sd; - if (sd > td) - dist = sd + (td >> 1); - else - dist = td + (sd >> 1); - if (dist < minlight) - blocklights[t * smax + s] += (rad - dist) * 256; - } - } - } -} - -/* - R_BuildLightMap - - Combine and scale multiple lightmaps into the 8.8 format in blocklights -*/ -static void -R_BuildLightMap (void) -{ - int smax, tmax; - int t; - int i, size; - byte *lightmap; - unsigned int scale; - int maps; - msurface_t *surf; - - surf = sw32_r_drawsurf.surf; - - smax = (surf->extents[0] >> 4) + 1; - tmax = (surf->extents[1] >> 4) + 1; - size = smax * tmax; - lightmap = surf->samples; - - if (!r_worldentity.renderer.model->brush.lightdata) { - for (i = 0; i < size; i++) - blocklights[i] = 0; - return; - } - // clear to ambient - for (i = 0; i < size; i++) - blocklights[i] = r_refdef.ambientlight << 8; - - // add all the lightmaps - if (lightmap) - for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) { - scale = sw32_r_drawsurf.lightadj[maps]; // 8.8 fraction - for (i = 0; i < size; i++) - blocklights[i] += lightmap[i] * scale; - lightmap += size; // skip to next lightmap - } - // add all the dynamic lights - if (surf->dlightframe == r_framecount) - R_AddDynamicLights (); - - /* - * JohnnyonFlame: - * 32 and 16bpp modes uses the positive lighting, unlike 8bpp - */ - switch (sw32_ctx->pixbytes) { - case 1: - // bound, invert, and shift - for (i = 0; i < size; i++) { - t = (255 * 256 - blocklights[i]) >> (8 - VID_CBITS); - - if (t < (1 << 6)) - t = (1 << 6); - - blocklights[i] = t; - } - break; - default: - // LordHavoc: changed to positive (not inverse) lighting - for (i = 0; i < size; i++) { - t = bound(256, blocklights[i] >> (8 - VID_CBITS), - 256 * (VID_GRADES - 1)); - blocklights[i] = t; - } - break; - } -} - -void -sw32_R_DrawSurface (void) -{ - byte *basetptr; - int smax, tmax, twidth; - int u; - int soffset, basetoffset, texwidth; - int horzblockstep; - byte *pcolumndest; - void (*pblockdrawer) (void); - texture_t *mt; - - // calculate the lightings - R_BuildLightMap (); - - surfrowbytes = sw32_r_drawsurf.rowbytes; - - mt = sw32_r_drawsurf.texture; - - r_source = (byte *) mt + mt->offsets[sw32_r_drawsurf.surfmip]; - - // the fractional light values should range from 0 to - // (VID_GRADES - 1) << 16 from a source range of 0 - 255 - - texwidth = mt->width >> sw32_r_drawsurf.surfmip; - - blocksize = 16 >> sw32_r_drawsurf.surfmip; - blockdivshift = 4 - sw32_r_drawsurf.surfmip; - blockdivmask = (1 << blockdivshift) - 1; - - r_lightwidth = (sw32_r_drawsurf.surf->extents[0] >> 4) + 1; - - r_numhblocks = sw32_r_drawsurf.surfwidth >> blockdivshift; - r_numvblocks = sw32_r_drawsurf.surfheight >> blockdivshift; - -//============================== - - smax = mt->width >> sw32_r_drawsurf.surfmip; - twidth = texwidth; - tmax = mt->height >> sw32_r_drawsurf.surfmip; - sourcetstep = texwidth; - r_stepback = tmax * twidth; - - soffset = sw32_r_drawsurf.surf->texturemins[0]; - basetoffset = sw32_r_drawsurf.surf->texturemins[1]; - - switch (sw32_ctx->pixbytes) { - case 1: - pblockdrawer = surfmiptable8[sw32_r_drawsurf.surfmip]; - break; - case 2: - pblockdrawer = surfmiptable16[sw32_r_drawsurf.surfmip]; - break; - case 4: - pblockdrawer = surfmiptable32[sw32_r_drawsurf.surfmip]; - break; - default: - Sys_Error("R_DrawSurface: unsupported r_pixbytes %i", sw32_ctx->pixbytes); - pblockdrawer = NULL; - } - - horzblockstep = blocksize * sw32_ctx->pixbytes; - - r_sourcemax = r_source + (tmax * smax); - - // << 16 components are to guarantee positive values for % - basetptr = r_source + (((basetoffset >> sw32_r_drawsurf.surfmip) + - (tmax << 16)) % tmax) * twidth; - soffset = (((soffset >> sw32_r_drawsurf.surfmip) + (smax << 16)) % smax); - - pcolumndest = (byte *) sw32_r_drawsurf.surfdat; - - for (u = 0; u < r_numhblocks; u++) { - r_lightptr = blocklights + u; - - prowdestbase = pcolumndest; - - psource = basetptr + soffset; - - (*pblockdrawer) (); - - soffset = soffset + blocksize; - if (soffset >= smax) - soffset = 0; - - pcolumndest += horzblockstep; - } -} - -//============================================================================= - -static void -R_DrawSurfaceBlock8_mip0 (void) -{ - int v, i, b, lightstep, light; - unsigned char pix, *prowdest; - - prowdest = prowdestbase; - - for (v = 0; v < r_numvblocks; v++) { - // FIXME: make these locals? - // FIXME: use delta rather than both right and left, like ASM? - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 4; - lightrightstep = (r_lightptr[1] - lightright) >> 4; - - for (i = 0; i < 16; i++) { - lightstep = (lightleft - lightright) >> 4; - - light = lightright; - - for (b = 15; b >= 0; b--) { - pix = psource[b]; - prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; - light += lightstep; - } - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += surfrowbytes; - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock8_mip1 (void) -{ - int v, i, b, lightstep, light; - unsigned char pix, *prowdest; - - prowdest = prowdestbase; - - for (v = 0; v < r_numvblocks; v++) { - // FIXME: make these locals? - // FIXME: use delta rather than both right and left, like ASM? - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 3; - lightrightstep = (r_lightptr[1] - lightright) >> 3; - - for (i = 0; i < 8; i++) { - lightstep = (lightleft - lightright) >> 3; - - light = lightright; - - for (b = 7; b >= 0; b--) { - pix = psource[b]; - prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; - light += lightstep; - } - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += surfrowbytes; - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock8_mip2 (void) -{ - int v, i, b, lightstep, light; - unsigned char pix, *prowdest; - - prowdest = prowdestbase; - - for (v = 0; v < r_numvblocks; v++) { - // FIXME: make these locals? - // FIXME: use delta rather than both right and left, like ASM? - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 2; - lightrightstep = (r_lightptr[1] - lightright) >> 2; - - for (i = 0; i < 4; i++) { - lightstep = (lightleft - lightright) >> 2; - - light = lightright; - - for (b = 3; b >= 0; b--) { - pix = psource[b]; - prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; - light += lightstep; - } - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += surfrowbytes; - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock8_mip3 (void) -{ - int v, i, b, lightstep, light; - unsigned char pix, *prowdest; - - prowdest = prowdestbase; - - for (v = 0; v < r_numvblocks; v++) { - // FIXME: make these locals? - // FIXME: use delta rather than both right and left, like ASM? - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 1; - lightrightstep = (r_lightptr[1] - lightright) >> 1; - - for (i = 0; i < 2; i++) { - lightstep = (lightleft - lightright) >> 1; - - light = lightright; - - for (b = 1; b >= 0; b--) { - pix = psource[b]; - prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; - light += lightstep; - } - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += surfrowbytes; - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock16_mip0 (void) -{ - int k, v; - int lightstep, light; - unsigned short *prowdest; - - prowdest = (unsigned short *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 4; - lightrightstep = (r_lightptr[1] - lightright) >> 4; - - for (k = 0; k < 16; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 4; - - prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; - light += lightstep; - prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]]; - light += lightstep; - prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]]; - light += lightstep; - prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]]; - light += lightstep; - prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]]; - light += lightstep; - prowdest[8] = vid.colormap16[(light & 0xFF00) + psource[8]]; - light += lightstep; - prowdest[9] = vid.colormap16[(light & 0xFF00) + psource[9]]; - light += lightstep; - prowdest[10] = vid.colormap16[(light & 0xFF00) + psource[10]]; - light += lightstep; - prowdest[11] = vid.colormap16[(light & 0xFF00) + psource[11]]; - light += lightstep; - prowdest[12] = vid.colormap16[(light & 0xFF00) + psource[12]]; - light += lightstep; - prowdest[13] = vid.colormap16[(light & 0xFF00) + psource[13]]; - light += lightstep; - prowdest[14] = vid.colormap16[(light & 0xFF00) + psource[14]]; - light += lightstep; - prowdest[15] = vid.colormap16[(light & 0xFF00) + psource[15]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 1); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock16_mip1 (void) -{ - int k, v; - int lightstep, light; - unsigned short *prowdest; - - prowdest = (unsigned short *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 3; - lightrightstep = (r_lightptr[1] - lightright) >> 3; - - for (k = 0; k < 8; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 3; - - prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; - light += lightstep; - prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]]; - light += lightstep; - prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]]; - light += lightstep; - prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]]; - light += lightstep; - prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 1); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock16_mip2 (void) -{ - int k, v; - int lightstep, light; - unsigned short *prowdest; - - prowdest = (unsigned short *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 2; - lightrightstep = (r_lightptr[1] - lightright) >> 2; - - for (k = 0; k < 4; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 2; - - prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 1); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock16_mip3 (void) -{ - int v; - unsigned short *prowdest; - - prowdest = (unsigned short *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 1; - lightrightstep = (r_lightptr[1] - lightright) >> 1; - - prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]]; - prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) & - 0xFF00) + psource[1]]; - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 1); - - prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]]; - prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) & - 0xFF00) + psource[1]]; - psource += sourcetstep; - prowdest += (surfrowbytes >> 1); - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock32_mip0 (void) -{ - int k, v; - int lightstep, light; - unsigned int *prowdest; - - prowdest = (unsigned int *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 4; - lightrightstep = (r_lightptr[1] - lightright) >> 4; - - for (k = 0; k < 16; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 4; - - prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; - light += lightstep; - prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]]; - light += lightstep; - prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]]; - light += lightstep; - prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]]; - light += lightstep; - prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]]; - light += lightstep; - prowdest[8] = vid.colormap32[(light & 0xFF00) + psource[8]]; - light += lightstep; - prowdest[9] = vid.colormap32[(light & 0xFF00) + psource[9]]; - light += lightstep; - prowdest[10] = vid.colormap32[(light & 0xFF00) + psource[10]]; - light += lightstep; - prowdest[11] = vid.colormap32[(light & 0xFF00) + psource[11]]; - light += lightstep; - prowdest[12] = vid.colormap32[(light & 0xFF00) + psource[12]]; - light += lightstep; - prowdest[13] = vid.colormap32[(light & 0xFF00) + psource[13]]; - light += lightstep; - prowdest[14] = vid.colormap32[(light & 0xFF00) + psource[14]]; - light += lightstep; - prowdest[15] = vid.colormap32[(light & 0xFF00) + psource[15]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock32_mip1 (void) -{ - int k, v; - int lightstep, light; - unsigned int *prowdest; - - prowdest = (unsigned int *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 3; - lightrightstep = (r_lightptr[1] - lightright) >> 3; - - for (k = 0; k < 8; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 3; - - prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; - light += lightstep; - prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]]; - light += lightstep; - prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]]; - light += lightstep; - prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]]; - light += lightstep; - prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock32_mip2 (void) -{ - int k, v; - int lightstep, light; - unsigned int *prowdest; - - prowdest = (unsigned int *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 2; - lightrightstep = (r_lightptr[1] - lightright) >> 2; - - for (k = 0; k < 4; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 2; - - prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock32_mip3 (void) -{ - int v; - unsigned int *prowdest; - - prowdest = (unsigned int *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 1; - lightrightstep = (r_lightptr[1] - lightright) >> 1; - - prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]]; - prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) & - 0xFF00) + psource[1]]; - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - - prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]]; - prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) & - 0xFF00) + psource[1]]; - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -/* -void -R_DrawSurfaceBlock32 (void) -{ - int k, v; - int lightstep, light; - unsigned int *prowdest; - - prowdest = prowdestbase; - - for (v = 0; v < r_numvblocks; v++) { - - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> blockdivshift; - lightrightstep = (r_lightptr[1] - lightright) >> blockdivshift; - - for (k = 0; k < blocksize; k++) { - int b; - - lightstep = (lightright - lightleft) >> blockdivshift; - - light = lightleft; - - for (b = 0;b < blocksize;b++, light += lightstep) - prowdest[b] = vid.colormap32[(light & 0xFF00) + psource[b]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} -*/ diff --git a/libs/video/renderer/sw32/vid_common_sw32.c b/libs/video/renderer/sw32/vid_common_sw32.c deleted file mode 100644 index 5bc9fbc47..000000000 --- a/libs/video/renderer/sw32/vid_common_sw32.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - vid_common_sw32.c - - general video driver functions - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "QF/cvar.h" -#include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" - -#include "compat.h" -#include "r_internal.h" -#include "vid_internal.h" - -unsigned short sw32_8to16table[256]; - - -/* - VID_MakeColormap32 - - LordHavoc: makes a 32bit color*light table, RGBA order, no endian, - may need to be re-ordered to hardware at display time -*/ -static void -VID_MakeColormap32 (void *outcolormap, byte *pal) -{ - int c, l; - byte *out; - out = (byte *)&d_8to24table; - - /* - * Generates colors not affected by lighting, such as - * HUD pieces and general sprites (such as explosions) - */ - for (c = 0; c < 256; c++) { - *out++ = pal[c*3+2]; - *out++ = pal[c*3+1]; - *out++ = pal[c*3+0]; - *out++ = 255; - } - d_8to24table[255] = 0; // 255 is transparent - out = (byte *) outcolormap; - - /* - * Generates colors affected by lighting, such as the - * world and other models that give it life, like foes and pickups. - */ - for (l = 0;l < VID_GRADES;l++) - { - for (c = 0;c < vid.fullbright;c++) - { - out[(l*256+c)*4+0] = bound(0, (pal[c*3+2] * l) >> (VID_CBITS - 1), - 255); - out[(l*256+c)*4+1] = bound(0, (pal[c*3+1] * l) >> (VID_CBITS - 1), - 255); - out[(l*256+c)*4+2] = bound(0, (pal[c*3+0] * l) >> (VID_CBITS - 1), - 255); - out[(l*256+c)*4+3] = 255; - } - for (;c < 255;c++) - { - out[(l*256+c)*4+0] = pal[c*3+2]; - out[(l*256+c)*4+1] = pal[c*3+1]; - out[(l*256+c)*4+2] = pal[c*3+0]; - out[(l*256+c)*4+3] = 255; - } - out[(l*256+255)*4+0] = 0; - out[(l*256+255)*4+1] = 0; - out[(l*256+255)*4+2] = 0; - out[(l*256+255)*4+3] = 0; - } -} - -static unsigned short -lh24to16bit (int red, int green, int blue) -{ - red = bound(0, red, 255); - green = bound(0, green, 255); - blue = bound(0, blue, 255); - red >>= 3; - green >>= 2; - blue >>= 3; - red <<= 11; - green <<= 5; - return (unsigned short) (red | green | blue); -} - -/* - VID_MakeColormap16 - - LordHavoc: makes a 16bit color*light table, RGB order, native endian, - may need to be translated to hardware order at display time -*/ -static void -VID_MakeColormap16 (void *outcolormap, byte *pal) -{ - int c, l; - unsigned short *out; - out = (unsigned short *)&sw32_8to16table; - for (c = 0; c < 256; c++) - *out++ = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]); - sw32_8to16table[255] = 0; // 255 is transparent - out = (unsigned short *) outcolormap; - for (l = 0;l < VID_GRADES;l++) - { - for (c = 0;c < vid.fullbright;c++) - out[l*256+c] = lh24to16bit( - (pal[c*3+0] * l) >> (VID_CBITS - 1), - (pal[c*3+1] * l) >> (VID_CBITS - 1), - (pal[c*3+2] * l) >> (VID_CBITS - 1)); - for (;c < 255;c++) - out[l*256+c] = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]); - out[l*256+255] = 0; - } -} - -/* - VID_MakeColormaps - - LordHavoc: makes 8bit, 16bit, and 32bit colormaps and palettes -*/ -void -VID_MakeColormaps (void) -{ - vid.colormap16 = malloc (256*VID_GRADES * sizeof (unsigned short)); - vid.colormap32 = malloc (256*VID_GRADES * sizeof (unsigned int)); - SYS_CHECKMEM (vid.colormap16 && vid.colormap32); - VID_MakeColormap16(vid.colormap16, vid.palette); - VID_MakeColormap32(vid.colormap32, vid.palette); -} diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c deleted file mode 100644 index c1af7d5df..000000000 --- a/libs/video/renderer/vid_render_sw32.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - vid_render_gl.c - - SW32 version of the renderer - - Copyright (C) 2012 Bill Currie - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define NH_DEFINE -#include "sw32/namehack.h" - -#include "QF/plugin/general.h" -#include "QF/plugin/vid_render.h" - -#include "QF/ui/view.h" - -#include "mod_internal.h" -#include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" - -#include "sw32/namehack.h" - -sw_ctx_t *sw32_ctx; - -static void -sw32_vid_render_choose_visual (void *data) -{ - sw32_ctx->choose_visual (sw32_ctx); -} - -static void -sw32_vid_render_create_context (void *data) -{ - sw32_ctx->create_context (sw32_ctx); -} - -static void -sw32_vid_render_set_palette (void *data, const byte *palette) -{ - sw32_ctx->set_palette (sw32_ctx, palette); -} - -static vid_model_funcs_t model_funcs = { - 0, - sw_Mod_LoadLighting, - 0,//Mod_SubdivideSurface, - 0,//Mod_ProcessTexture, - - Mod_LoadIQM, - Mod_LoadAliasModel, - Mod_LoadSpriteModel, - - sw_Mod_MakeAliasModelDisplayLists, - sw_Mod_LoadSkin, - 0, - 0, - sw_Mod_IQMFinish, - 1, - sw_Mod_SpriteLoadFrames, - - Skin_SetColormap, - Skin_SetSkin, - sw_Skin_SetupSkin, - Skin_SetTranslation, - sw_Skin_ProcessTranslation, - sw_Skin_InitTranslations, -}; - -static void -sw32_vid_render_init (void) -{ - if (!vr_data.vid->vid_internal->sw_context) { - Sys_Error ("Sorry, software rendering not supported by this program."); - } - sw32_ctx = vr_data.vid->vid_internal->sw32_context (); - - vr_data.vid->vid_internal->data = sw32_ctx; - vr_data.vid->vid_internal->set_palette = sw32_vid_render_set_palette; - vr_data.vid->vid_internal->choose_visual = sw32_vid_render_choose_visual; - vr_data.vid->vid_internal->create_context = sw32_vid_render_create_context; - - vr_funcs = &sw32_vid_render_funcs; - m_funcs = &model_funcs; -} - -static void -sw32_vid_render_shutdown (void) -{ -} - -static void -sw32_begin_frame (void) -{ - if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen - vr_data.scr_copyeverything = 1; - sw32_Draw_TileClear (0, 0, vid.width, vid.height); - } -} - -static void -sw32_render_view (void) -{ - sw32_R_RenderView (); -} - -static void -sw32_set_2d (void) -{ -} - -static void -sw32_end_frame (void) -{ - // update one of three areas - vrect_t vrect; - if (vr_data.scr_copyeverything) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - vrect.next = 0; - } else if (scr_copytop) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height - vr_data.lineadj; - vrect.next = 0; - } else { - vrect.x = vr_data.scr_view->xpos; - vrect.y = vr_data.scr_view->ypos; - vrect.width = vr_data.scr_view->xlen; - vrect.height = vr_data.scr_view->ylen; - vrect.next = 0; - } - sw32_ctx->update (sw32_ctx, &vrect); -} - -vid_render_funcs_t sw32_vid_render_funcs = { - sw32_vid_render_init, - sw32_Draw_Character, - sw32_Draw_String, - sw32_Draw_nString, - sw32_Draw_AltString, - sw32_Draw_ConsoleBackground, - sw32_Draw_Crosshair, - sw32_Draw_CrosshairAt, - sw32_Draw_TileClear, - sw32_Draw_Fill, - sw32_Draw_TextBox, - sw32_Draw_FadeScreen, - sw32_Draw_BlendScreen, - sw32_Draw_CachePic, - sw32_Draw_UncachePic, - sw32_Draw_MakePic, - sw32_Draw_DestroyPic, - sw32_Draw_PicFromWad, - sw32_Draw_Pic, - sw32_Draw_Picf, - sw32_Draw_SubPic, - - sw32_SCR_CaptureBGR, - - sw32_ParticleSystem, - sw32_R_Init, - sw32_R_ClearState, - sw32_R_LoadSkys, - sw32_R_NewMap, - sw32_R_LineGraph, - sw32_R_ViewChanged, - sw32_begin_frame, - sw32_render_view, - sw32_set_2d, - sw32_end_frame, - &model_funcs -}; - -static general_funcs_t plugin_info_general_funcs = { - .shutdown = sw32_vid_render_shutdown, -}; - -static general_data_t plugin_info_general_data; - -static plugin_funcs_t plugin_info_funcs = { - .general = &plugin_info_general_funcs, - .vid_render = &sw32_vid_render_funcs, -}; - -static plugin_data_t plugin_info_data = { - .general = &plugin_info_general_data, - .vid_render = &vid_render_data, -}; - -static plugin_t plugin_info = { - qfp_vid_render, - 0, - QFPLUGIN_VERSION, - "0.1", - "SW32 Renderer", - "Copyright (C) 1996-1997 Id Software, Inc.\n" - "Copyright (C) 1999-2012 contributors of the QuakeForge project\n" - "Please see the file \"AUTHORS\" for a list of contributors", - &plugin_info_funcs, - &plugin_info_data, -}; - -PLUGIN_INFO(vid_render, sw32) -{ - return &plugin_info; -} diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index d116243a3..55a6910c9 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -110,8 +110,6 @@ modestate_t modestate = MS_UNINIT; byte vid_curpal[256 * 3]; -unsigned short d_8to16table[256]; - int mode; typedef struct { diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index ad452316b..fb0fa703d 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -101,7 +101,6 @@ VID_Init (byte *palette, byte *colormap) vid_internal.gl_context = X11_GL_Context; vid_internal.sw_context = X11_SW_Context; - vid_internal.sw32_context = X11_SW32_Context; #ifdef HAVE_VULKAN vid_internal.vulkan_context = X11_Vulkan_Context; #endif diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index b52d3366d..84588fb32 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -642,18 +642,6 @@ x11_create_context (sw_ctx_t *ctx) sw_ctx_t * X11_SW_Context (void) -{ - sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); - ctx->pixbytes = 1; - ctx->set_palette = x11_set_palette; - ctx->choose_visual = x11_choose_visual; - ctx->create_context = x11_create_context; - ctx->update = x11_sw8_update; - return ctx; -} - -sw_ctx_t * -X11_SW32_Context (void) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); ctx->pixbytes = 1; From 747494c03a549c059882bcab52ad310d001fc24d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 16:56:36 +0900 Subject: [PATCH 2516/3664] [sw] Fix 16 and 32 bit alias model rendering Intel asm needs testing still, but C is working nicely. --- libs/video/renderer/sw/d_polyse.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/libs/video/renderer/sw/d_polyse.c b/libs/video/renderer/sw/d_polyse.c index 1c64e01fe..a707d807c 100644 --- a/libs/video/renderer/sw/d_polyse.c +++ b/libs/video/renderer/sw/d_polyse.c @@ -43,7 +43,7 @@ int ubasestep, errorterm, erroradjustup, erroradjustdown; // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct spanpackage_s { - void *pdest; + int pdest; short *pz; int count; byte *ptex; @@ -94,7 +94,8 @@ int d_aspancount, d_countextrastep; spanpackage_t *a_spans; spanpackage_t *d_pedgespanpackage; static int ystart; -byte *d_pdest, *d_ptex; +int d_pdest; +byte *d_ptex; short *d_pz; int d_sfrac, d_tfrac, d_light, d_zi; int d_ptexextrastep, d_sfracextrastep; @@ -617,7 +618,7 @@ polyset_draw_spans_8 (spanpackage_t * pspanpackage) } if (lcount) { - lpdest = pspanpackage->pdest; + lpdest = d_viewbuffer + pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; lsfrac = pspanpackage->sfrac; @@ -686,7 +687,7 @@ polyset_draw_spans_16 (spanpackage_t * pspanpackage) if (lcount) { - lpdest = (short *) pspanpackage->pdest; + lpdest = (short *) d_viewbuffer + pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; lsfrac = pspanpackage->sfrac; @@ -771,7 +772,7 @@ polyset_draw_spans_32 (spanpackage_t * pspanpackage) if (lcount) { - lpdest = (int *) pspanpackage->pdest; + lpdest = (int *) d_viewbuffer + pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; lsfrac = pspanpackage->sfrac; @@ -874,7 +875,13 @@ D_RasterizeAliasPolySmooth (void) d_pdestbasestep = screenwidth + ubasestep; d_pdestextrastep = d_pdestbasestep + 1; - d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0]; +#ifdef USE_INTEL_ASM + if (sw_ctx->pixbytes == 1) { + d_pdest = (int) d_viewbuffer + ystart * screenwidth + plefttop[0]; + } else +#endif + d_pdest = ystart * screenwidth + plefttop[0]; + d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; // TODO: can reuse partial expressions here @@ -940,7 +947,13 @@ D_RasterizeAliasPolySmooth (void) d_pdestbasestep = screenwidth + ubasestep; d_pdestextrastep = d_pdestbasestep + 1; - d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0]; +#ifdef USE_INTEL_ASM + if (sw_ctx->pixbytes == 1) { + d_pdest = (int) d_viewbuffer + ystart * screenwidth + plefttop[0]; + } else +#endif + d_pdest = ystart * screenwidth + plefttop[0]; + #ifdef USE_INTEL_ASM d_pzbasestep = (d_zwidth + ubasestep) << 1; d_pzextrastep = d_pzbasestep + 2; From dce1a4d2921a835d2eb95ca68bf3e7b45abb88bb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 19:57:28 +0900 Subject: [PATCH 2517/3664] [util] Force 32-bit windows malloc to be 16-byte aligned By replacing it :P (and its friends). This gets the non-sw renderers working with recent scene changes. --- libs/scene/hierarchy.c | 11 ----------- libs/util/sys.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 4573e9e6e..3aa758624 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -40,17 +40,6 @@ #include "scn_internal.h" -#if defined(_WIN32) && !defined(_WIN64) -// FIXME (maybe) this is a hack to make DARRAY arrrays 16-byte aligned on -// 32-bit systems (in particular for this case, windows) as the vectors and -// matrices require 16-byte alignment but system malloc (etc) provide only -// 8-byte alignment. -// Really, a custom allocator (maybe using cmem) would be better. -#define free(mem) _aligned_free(mem) -#define malloc(size) _aligned_malloc(size, 16) -#define realloc(mem, size) _aligned_realloc(mem, size, 16) -#endif - static void hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, int offset) diff --git a/libs/util/sys.c b/libs/util/sys.c index bd985428f..43b3b1e05 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -646,6 +646,39 @@ Sys_PageIn (void *ptr, size_t size) //#endif } +#if defined(_WIN32) && !defined(_WIN64) +// this is a hack to make memory allocations 16-byte aligned on 32-bit +// systems (in particular for this case, windows) as vectors and +// matrices require 16-byte alignment but system malloc (etc) provide only +// 8-byte alignment. +void *__cdecl +calloc (size_t nume, size_t sizee) +{ + size_t size = nume * sizee; + void *mem = _aligned_malloc (size, 16); + memset (mem, 0, size); + return mem; +} + +void __cdecl +free (void *mem) +{ + _aligned_free (mem); +} + +void *__cdecl +malloc (size_t size) +{ + return _aligned_malloc (size, 16); +} + +void *__cdecl +realloc (void *mem, size_t size) +{ + return _aligned_realloc (mem, size, 16); +} +#endif + VISIBLE size_t Sys_PageSize (void) { From 19348f678f4a89ff492e062c971a63d021f1f19a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 20:00:59 +0900 Subject: [PATCH 2518/3664] [win] Get the software renderer hobbling 16 and 32 bit rendering are disabled at the moment because there's a weird segfault I need to fix, but the 8-bit dynamic lights are doing weird things (for x11, too) when updating the light maps. --- libs/video/targets/vid_win.c | 1 + libs/video/targets/vid_win_sw.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 02b919f04..47e62ef29 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -152,6 +152,7 @@ VID_Init_Cvars (void) Win_Vulkan_Init_Cvars (); #endif Win_GL_Init_Cvars (); + Win_SW_Init_Cvars (); } void diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index 9ded596fb..69e099b08 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -50,6 +50,8 @@ static win_palette_t st2d_8to32table[256]; static byte current_palette[768]; static int palette_changed; +static cvar_t *vid_bitdepth; + static LPDIRECTDRAW dd_Object; static HINSTANCE hInstDDraw; static LPDIRECTDRAWSURFACE dd_frontbuffer; @@ -469,14 +471,32 @@ sw_ctx_t * Win_SW_Context (void) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); + ctx->pixbytes = 1; ctx->set_palette = win_set_palette; ctx->choose_visual = win_choose_visual; ctx->create_context = win_create_context; ctx->update = win_sw_update; +#if 0 //FIXME need to figure out 16 and 32 bit buffers + switch (vid_bitdepth->int_val) { + case 8: + ctx->pixbytes = 1; + break; + case 16: + ctx->pixbytes = 2; + break; + case 32: + ctx->pixbytes = 4; + break; + default: + Sys_Error ("X11_SW32_Context: unsupported bit depth"); + } +#endif return ctx; } void Win_SW_Init_Cvars (void) { + vid_bitdepth = Cvar_Get ("vid_bitdepth", "8", CVAR_ROM, NULL, "Sets " + "display bitdepth (supported modes: 8 16 32)"); } From 5477352e938285424dff4324a2e4a6314c96087b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 20:19:14 +0900 Subject: [PATCH 2519/3664] [renderer] Abandon sw32 altogether I'd been considering it for a while, but in the end, all the issues it presented made me decide it wasn't worth merging and was never really worth keeping: it was a neat proof of concept but of little actual use, especially now everyone either has an OK GPU or would want to stick to 8-bit rendering anyway (sorry L-Havoc). However, both it and my merge work are preserved in git history :) --- include/context_x11.h | 2 +- include/r_internal.h | 3 - include/r_local.h | 2 +- include/vid_internal.h | 2 - include/vid_sw.h | 29 - include/vid_sw_draw.h | 25 - libs/video/renderer/sw/d_draw.S | 4 +- libs/video/renderer/sw/d_edge.c | 52 +- libs/video/renderer/sw/d_init.c | 15 +- libs/video/renderer/sw/d_modech.c | 5 +- libs/video/renderer/sw/d_part.c | 261 +------- libs/video/renderer/sw/d_parta.S | 4 +- libs/video/renderer/sw/d_polysa.S | 4 +- libs/video/renderer/sw/d_polyse.c | 202 +----- libs/video/renderer/sw/d_scan.c | 423 +----------- libs/video/renderer/sw/d_scana.S | 4 +- libs/video/renderer/sw/d_sky.c | 141 +--- libs/video/renderer/sw/d_spr8.S | 4 +- libs/video/renderer/sw/d_sprite.c | 307 +-------- libs/video/renderer/sw/d_surf.c | 12 +- libs/video/renderer/sw/d_zpoint.c | 36 +- libs/video/renderer/sw/draw.c | 871 ++++++------------------- libs/video/renderer/sw/screen.c | 21 +- libs/video/renderer/sw/surf8.S | 40 +- libs/video/renderer/sw/sw_graph.c | 86 +-- libs/video/renderer/sw/sw_ralias.c | 13 - libs/video/renderer/sw/sw_rmain.c | 28 +- libs/video/renderer/sw/sw_rpart.c | 4 +- libs/video/renderer/sw/sw_rsky.c | 182 +++--- libs/video/renderer/sw/sw_rsurf.c | 613 +++-------------- libs/video/renderer/sw/vid_common_sw.c | 129 +--- libs/video/targets/vid_win_sw.c | 19 - libs/video/targets/vid_x11_sw.c | 20 +- 33 files changed, 471 insertions(+), 3092 deletions(-) delete mode 100644 include/vid_sw_draw.h diff --git a/include/context_x11.h b/include/context_x11.h index 1409b5b93..ebb4b6d3b 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -83,7 +83,7 @@ struct gl_ctx_s *X11_GL_Context (void); void X11_GL_Init_Cvars (void); struct sw_ctx_s *X11_SW_Context (void); -void X11_SW_Init_Cvars (void); // sw and sw32 cvars shared +void X11_SW_Init_Cvars (void); struct vulkan_ctx_s *X11_Vulkan_Context (void); void X11_Vulkan_Init_Cvars (void); diff --git a/include/r_internal.h b/include/r_internal.h index 690aa8629..8a1ae465c 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -14,7 +14,6 @@ extern vid_render_data_t vid_render_data; extern vid_render_funcs_t gl_vid_render_funcs; extern vid_render_funcs_t glsl_vid_render_funcs; extern vid_render_funcs_t sw_vid_render_funcs; -extern vid_render_funcs_t sw32_vid_render_funcs; extern vid_render_funcs_t vulkan_vid_render_funcs; extern vid_render_funcs_t *vid_render_funcs; @@ -30,7 +29,6 @@ void R_LineGraph (int x, int y, int *h_vals, int count, int height); void gl_R_Init (void); void glsl_R_Init (void); void sw_R_Init (void); -void sw32_R_Init (void); void R_RenderFrame (SCR_Func *scr_funcs); void R_Init_Cvars (void); void R_InitEfrags (void); @@ -45,7 +43,6 @@ extern struct psystem_s r_psystem; struct psystem_s *gl_ParticleSystem (void); struct psystem_s *glsl_ParticleSystem (void); struct psystem_s *sw_ParticleSystem (void); -struct psystem_s *sw32_ParticleSystem (void); void R_RunParticles (float dT); void R_NewMap (model_t *worldmodel, model_t **models, int num_models); diff --git a/include/r_local.h b/include/r_local.h index d6d7b35a9..95302ad49 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -236,7 +236,7 @@ extern float leftclip, topclip, rightclip, bottomclip; extern int r_acliptype; extern finalvert_t *pfinalverts; extern auxvert_t *pauxverts; -extern float ziscale, sw32_ziscale; +extern float ziscale; extern float aliastransform[3][4]; qboolean R_AliasCheckBBox (void); diff --git a/include/vid_internal.h b/include/vid_internal.h index cc574c373..7912dca52 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -27,8 +27,6 @@ extern struct cvar_s *vid_gamma; void VID_GetWindowSize (int def_w, int def_h); -extern unsigned short d_8to16table[256]; - void VID_InitGamma (const byte *); qboolean VID_SetGamma (double); void VID_UpdateGamma (struct cvar_s *); diff --git a/include/vid_sw.h b/include/vid_sw.h index 00a15357b..92fb00d55 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -1,22 +1,6 @@ #ifndef __vid_sw_h #define __vid_sw_h -#include "QF/qtypes.h" - -struct surf_s; -struct vrect_s; -struct particle_s; -struct spanpackage_s; -struct qpic_s; -struct espan_s; -struct sspan_s; - -typedef struct sw_draw_s { -#define SW_DRAW_FUNC(name, rettype, params) \ - rettype (*name) params; -#include "vid_sw_draw.h" -} sw_draw_t; - struct vrect_s; typedef struct sw_ctx_s { int pixbytes; @@ -24,23 +8,10 @@ typedef struct sw_ctx_s { void (*create_context) (struct sw_ctx_s *ctx); void (*set_palette) (struct sw_ctx_s *ctx, const byte *palette); void (*update) (struct sw_ctx_s *ctx, struct vrect_s *rects); - sw_draw_t *draw; } sw_ctx_t; extern sw_ctx_t *sw_ctx; -#define SW_DRAW_FUNC(name, rettype, params) \ - rettype name##_8 params; -#include "vid_sw_draw.h" - -#define SW_DRAW_FUNC(name, rettype, params) \ - rettype name##_16 params; -#include "vid_sw_draw.h" - -#define SW_DRAW_FUNC(name, rettype, params) \ - rettype name##_32 params; -#include "vid_sw_draw.h" - struct tex_s *sw_SCR_CaptureBGR (void); #endif//__vid_sw_h diff --git a/include/vid_sw_draw.h b/include/vid_sw_draw.h deleted file mode 100644 index 879c1cd65..000000000 --- a/include/vid_sw_draw.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef SW_DRAW_FUNC -#define SW_DRAW_FUNC(name, rettype, params) -#endif - -SW_DRAW_FUNC(draw_solid_usrface, void, (struct surf_s *surf, int color)) -SW_DRAW_FUNC(draw_particle, void, (struct particle_s *particle)) -SW_DRAW_FUNC(polyset_draw_spans, void, (struct spanpackage_s *spanpackage)) -SW_DRAW_FUNC(draw_character, void, (int x, int y, byte *source, int drawline)) -SW_DRAW_FUNC(draw_pixel, void, (int x, int y, byte color)) -SW_DRAW_FUNC(draw_subpic, void, (int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height)) -SW_DRAW_FUNC(draw_console_background, void, (int lines, byte *data)) -SW_DRAW_FUNC(draw_rect, void, (struct vrect_s *rect, int rowbytes, byte *src, int transparent)) -SW_DRAW_FUNC(draw_fill, void, (int x, int y, int w, int h, int c)) -SW_DRAW_FUNC(draw_fadescreen, void, (void)) -SW_DRAW_FUNC(draw_blendscreen, void, (quat_t color)) -SW_DRAW_FUNC(warp_screen, void, (void)) -SW_DRAW_FUNC(draw_turbulent_span, void, (void)) -SW_DRAW_FUNC(draw_spans, void, (struct espan_s *span)) -SW_DRAW_FUNC(draw_sky_scans, void, (struct espan_s *span)) -SW_DRAW_FUNC(sprite_draw_spans, void, (struct sspan_s *span)) -SW_DRAW_FUNC(draw_z_point, void, (void)) -SW_DRAW_FUNC(line_grapn, void, (int x, int y, int *h_vals, int count, int height)) -SW_DRAW_FUNC(make_sky, void, (void)) -SW_DRAW_FUNC(capture_bgr, struct tex_s *, (void)) -#undef SW_DRAW_FUNC diff --git a/libs/video/renderer/sw/d_draw.S b/libs/video/renderer/sw/d_draw.S index e615d677f..e4642025b 100644 --- a/libs/video/renderer/sw/d_draw.S +++ b/libs/video/renderer/sw/d_draw.S @@ -99,8 +99,8 @@ LClampHigh5: #define pspans 4+16 .align 4 -.globl C(draw_spans_8) -C(draw_spans_8): +.globl C(D_DrawSpans8) +C(D_DrawSpans8): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 9b50e932b..59963dc3a 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -35,8 +35,6 @@ #include "d_local.h" #include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" static int miplevel; @@ -74,14 +72,15 @@ D_MipLevelForScale (float scale) // FIXME: clean this up -void -draw_solid_usrface_8 (surf_t *surf, int color) +static void +D_DrawSolidSurface (surf_t *surf, int color) { + espan_t *span; byte *pdest; int u, u2, pix; pix = (color << 24) | (color << 16) | (color << 8) | color; - for (espan_t *span = surf->spans; span; span = span->pnext) { + for (span = surf->spans; span; span = span->pnext) { pdest = (byte *) d_viewbuffer + screenwidth * span->v; u = span->u; u2 = span->u + span->count - 1; @@ -104,39 +103,6 @@ draw_solid_usrface_8 (surf_t *surf, int color) } } -void -draw_solid_usrface_16 (surf_t *surf, int color) -{ - short *pdest, pix; - int u, u2; - - pix = d_8to16table[color]; - for (espan_t *span = surf->spans; span; span = span->pnext) { - pdest = (short *) d_viewbuffer + screenwidth * span->v; - u = span->u; - u2 = span->u + span->count - 1; - for (;u <= u2; u++) { - pdest[u] = pix; - } - } -} - -void -draw_solid_usrface_32 (surf_t *surf, int color) -{ - int *pdest, pix; - int u, u2; - - pix = d_8to24table[color]; - for (espan_t *span = surf->spans; span; span = span->pnext) { - pdest = (int *) d_viewbuffer + screenwidth * span->v; - u = span->u; - u2 = span->u + span->count - 1; - for (;u <= u2; u++) { - pdest[u] = pix; - } - } -} static void D_CalcGradients (msurface_t *pface) @@ -201,8 +167,7 @@ D_DrawSurfaces (void) d_zistepv = s->d_zistepv; d_ziorigin = s->d_ziorigin; - int color = (size_t) s->data & 0xff; - sw_ctx->draw->draw_solid_usrface (s, color); + D_DrawSolidSurface (s, ((size_t) s->data & 0xFF)); D_DrawZSpans (s->spans); } } else { @@ -218,10 +183,10 @@ D_DrawSurfaces (void) if (s->flags & SURF_DRAWSKY) { if (!r_skymade) { - sw_ctx->draw->make_sky (); + R_MakeSky (); } - sw_ctx->draw->draw_sky_scans (s->spans); + D_DrawSkyScans (s->spans); D_DrawZSpans (s->spans); } else if (s->flags & SURF_DRAWBACKGROUND) { // set up a gradient for the background surface that places @@ -230,8 +195,7 @@ D_DrawSurfaces (void) d_zistepv = 0; d_ziorigin = -0.9; - int color = r_clearcolor->int_val & 0xff; - sw_ctx->draw->draw_solid_usrface (s, color); + D_DrawSolidSurface (s, r_clearcolor->int_val & 0xFF); D_DrawZSpans (s->spans); } else if (s->flags & SURF_DRAWTURB) { pface = s->data; diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index bfd7de7f6..634762d28 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -35,7 +35,6 @@ #include "d_local.h" #include "r_internal.h" #include "vid_internal.h" -#include "vid_sw.h" #define NUM_MIPS 4 @@ -46,7 +45,6 @@ float d_scalemip[NUM_MIPS - 1]; static float basemip[NUM_MIPS - 1] = { 1.0, 0.5 * 0.8, 0.25 * 0.8 }; -float d_zitable[65536]; void (*d_drawspans) (espan_t *pspan); @@ -62,16 +60,7 @@ D_Init (void) vr_data.vid->vid_internal->flush_caches = D_FlushCaches; vr_data.vid->vid_internal->init_caches = D_InitCaches; - // LordHavoc: compute 1/zi table for use in rendering code everywhere - if (!d_zitable[1]) { - int i; - d_zitable[0] = 0; - for (i = 1;i < 65536;i++) - d_zitable[i] = (65536.0 * 65536.0 / (double) i); - } - VID_InitBuffers (); - VID_MakeColormaps (); } void @@ -93,7 +82,7 @@ D_SetupFrame (void) if (r_dowarp) screenwidth = WARP_WIDTH; else - screenwidth = vid.rowbytes / sw_ctx->pixbytes; + screenwidth = vid.rowbytes; d_roverwrapped = false; d_initial_rover = sc_rover; @@ -103,7 +92,7 @@ D_SetupFrame (void) for (i = 0; i < (NUM_MIPS - 1); i++) d_scalemip[i] = basemip[i] * d_mipscale->value; - d_drawspans = sw_ctx->draw->draw_spans; + d_drawspans = D_DrawSpans8; } void diff --git a/libs/video/renderer/sw/d_modech.c b/libs/video/renderer/sw/d_modech.c index c0ab33618..40956fc53 100644 --- a/libs/video/renderer/sw/d_modech.c +++ b/libs/video/renderer/sw/d_modech.c @@ -31,9 +31,8 @@ #include "QF/render.h" #include "QF/sys.h" -#include "d_local.h" #include "r_internal.h" -#include "vid_sw.h" +#include "d_local.h" int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; @@ -71,7 +70,7 @@ D_ViewChanged (void) if (r_dowarp) rowpixels = WARP_WIDTH; else - rowpixels = vid.rowbytes / sw_ctx->pixbytes; + rowpixels = vid.rowbytes; scale_for_mip = xscale; if (yscale > xscale) diff --git a/libs/video/renderer/sw/d_part.c b/libs/video/renderer/sw/d_part.c index 7052462e8..b8b5b1c82 100644 --- a/libs/video/renderer/sw/d_part.c +++ b/libs/video/renderer/sw/d_part.c @@ -30,8 +30,6 @@ #include "d_local.h" #include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" #ifdef PIC @@ -40,7 +38,7 @@ #ifndef USE_INTEL_ASM void -draw_particle_8 (particle_t *pparticle) +D_DrawParticle (particle_t *pparticle) { vec3_t local, transformed; float zi; @@ -165,260 +163,3 @@ draw_particle_8 (particle_t *pparticle) } } #endif // !USE_INTEL_ASM - -void -draw_particle_16 (particle_t *pparticle) -{ - vec3_t local, transformed; - float zi; - short *pz; - int i, izi, pix, count, u, v; - - // transform point - VectorSubtract (pparticle->pos, r_origin, local); - - transformed[0] = DotProduct (local, r_pright); - transformed[1] = DotProduct (local, r_pup); - transformed[2] = DotProduct (local, r_ppn); - - if (transformed[2] < PARTICLE_Z_CLIP) - return; - - // project the point - // FIXME: preadjust xcenter and ycenter - zi = 1.0 / transformed[2]; - u = (int) (xcenter + zi * transformed[0] + 0.5); - v = (int) (ycenter - zi * transformed[1] + 0.5); - - if ((v > d_vrectbottom_particle) - || (u > d_vrectright_particle) - || (v < d_vrecty) || (u < d_vrectx)) { - return; - } - - pz = d_pzbuffer + (d_zwidth * v) + u; - izi = (int) (zi * 0x8000); - - pix = izi >> d_pix_shift; - - if (pix < d_pix_min) - pix = d_pix_min; - else if (pix > d_pix_max) - pix = d_pix_max; - - unsigned short *pdest = (unsigned short *) d_viewbuffer + - d_scantable[v] + u, - pixcolor = d_8to16table[(int) pparticle->icolor]; - switch (pix) { - case 1: - count = 1 << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - } - break; - case 2: - count = 2 << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - } - break; - case 3: - count = 3 << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - } - break; - case 4: - count = 4 << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - - if (pz[3] <= izi) { - pz[3] = izi; - pdest[3] = pixcolor; - } - } - break; - default: - count = pix << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - for (i = 0; i < pix; i++) { - if (pz[i] <= izi) { - pz[i] = izi; - pdest[i] = pixcolor; - } - } - } - break; - } -} - -void -draw_particle_32 (particle_t *pparticle) -{ - vec3_t local, transformed; - float zi; - short *pz; - int i, izi, pix, count, u, v; - - // transform point - VectorSubtract (pparticle->pos, r_origin, local); - - transformed[0] = DotProduct (local, r_pright); - transformed[1] = DotProduct (local, r_pup); - transformed[2] = DotProduct (local, r_ppn); - - if (transformed[2] < PARTICLE_Z_CLIP) - return; - - // project the point - // FIXME: preadjust xcenter and ycenter - zi = 1.0 / transformed[2]; - u = (int) (xcenter + zi * transformed[0] + 0.5); - v = (int) (ycenter - zi * transformed[1] + 0.5); - - if ((v > d_vrectbottom_particle) - || (u > d_vrectright_particle) - || (v < d_vrecty) || (u < d_vrectx)) { - return; - } - - pz = d_pzbuffer + (d_zwidth * v) + u; - izi = (int) (zi * 0x8000); - - pix = izi >> d_pix_shift; - - if (pix < d_pix_min) - pix = d_pix_min; - else if (pix > d_pix_max) - pix = d_pix_max; - - int *pdest = (int *) d_viewbuffer + d_scantable[v] + u, - pixcolor = d_8to24table[(int) pparticle->icolor]; - switch (pix) { - case 1: - count = 1 << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - } - break; - case 2: - count = 2 << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - } - break; - case 3: - count = 3 << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - } - break; - case 4: - count = 4 << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - if (pz[0] <= izi) { - pz[0] = izi; - pdest[0] = pixcolor; - } - - if (pz[1] <= izi) { - pz[1] = izi; - pdest[1] = pixcolor; - } - - if (pz[2] <= izi) { - pz[2] = izi; - pdest[2] = pixcolor; - } - - if (pz[3] <= izi) { - pz[3] = izi; - pdest[3] = pixcolor; - } - } - break; - default: - count = pix << d_y_aspect_shift; - - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { - for (i = 0; i < pix; i++) { - if (pz[i] <= izi) { - pz[i] = izi; - pdest[i] = pixcolor; - } - } - } - break; - } -} diff --git a/libs/video/renderer/sw/d_parta.S b/libs/video/renderer/sw/d_parta.S index 13a7a5299..a7b9a8543 100644 --- a/libs/video/renderer/sw/d_parta.S +++ b/libs/video/renderer/sw/d_parta.S @@ -55,8 +55,8 @@ #define P 12+4 .align 4 -.globl C(draw_particle_8) -C(draw_particle_8): +.globl C(D_DrawParticle) +C(D_DrawParticle): pushl %ebp // preserve caller's stack frame pushl %edi // preserve register variables pushl %ebx diff --git a/libs/video/renderer/sw/d_polysa.S b/libs/video/renderer/sw/d_polysa.S index 0c254cbf5..ec2511e30 100644 --- a/libs/video/renderer/sw/d_polysa.S +++ b/libs/video/renderer/sw/d_polysa.S @@ -756,8 +756,8 @@ LDone: .globl C(D_PolysetAff8Start) C(D_PolysetAff8Start): -.globl C(polyset_draw_spans_8) -C(polyset_draw_spans_8): +.globl C(D_PolysetDrawSpans8) +C(D_PolysetDrawSpans8): pushl %esi // preserve register variables pushl %ebx diff --git a/libs/video/renderer/sw/d_polyse.c b/libs/video/renderer/sw/d_polyse.c index a707d807c..5e7f9fbc9 100644 --- a/libs/video/renderer/sw/d_polyse.c +++ b/libs/video/renderer/sw/d_polyse.c @@ -33,7 +33,6 @@ #include "d_local.h" #include "r_internal.h" -#include "vid_sw.h" int ubasestep, errorterm, erroradjustup, erroradjustdown; @@ -43,7 +42,7 @@ int ubasestep, errorterm, erroradjustup, erroradjustdown; // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct spanpackage_s { - int pdest; + void *pdest; short *pz; int count; byte *ptex; @@ -94,8 +93,7 @@ int d_aspancount, d_countextrastep; spanpackage_t *a_spans; spanpackage_t *d_pedgespanpackage; static int ystart; -int d_pdest; -byte *d_ptex; +byte *d_pdest, *d_ptex; short *d_pz; int d_sfrac, d_tfrac, d_light, d_zi; int d_ptexextrastep, d_sfracextrastep; @@ -596,7 +594,7 @@ InitGel (byte * palette) #ifndef USE_INTEL_ASM void -polyset_draw_spans_8 (spanpackage_t * pspanpackage) +D_PolysetDrawSpans8 (spanpackage_t * pspanpackage) { int lcount; byte *lpdest; @@ -618,7 +616,7 @@ polyset_draw_spans_8 (spanpackage_t * pspanpackage) } if (lcount) { - lpdest = d_viewbuffer + pspanpackage->pdest; + lpdest = pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; lsfrac = pspanpackage->sfrac; @@ -653,178 +651,6 @@ polyset_draw_spans_8 (spanpackage_t * pspanpackage) } #endif // !USE_INTEL_ASM -void -polyset_draw_spans_16 (spanpackage_t * pspanpackage) -{ - int i, j, texscantable[2*MAX_LBM_HEIGHT], *texscan; - // LordHavoc: compute skin row table - for (i = 0, j = -r_affinetridesc.skinheight * r_affinetridesc.skinwidth; - i < r_affinetridesc.skinheight*2;i++, j += r_affinetridesc.skinwidth) - texscantable[i] = j; - texscan = texscantable + r_affinetridesc.skinheight; - - { - int lcount, count = 0; - short *lpdest; - byte *lptex; - int lsfrac, ltfrac; - int llight; - int lzi; - short *lpz; - - do - { - lcount = d_aspancount - pspanpackage->count; - - errorterm += erroradjustup; - if (errorterm >= 0) - { - d_aspancount += d_countextrastep; - errorterm -= erroradjustdown; - } - else - d_aspancount += ubasestep; - - if (lcount) - { - lpdest = (short *) d_viewbuffer + pspanpackage->pdest; - lptex = pspanpackage->ptex; - lpz = pspanpackage->pz; - lsfrac = pspanpackage->sfrac; - ltfrac = pspanpackage->tfrac; - llight = pspanpackage->light; - lzi = pspanpackage->zi; - - do - { - if ((lzi >> 16) < *lpz) // hidden - { - count = 0; - goto skiploop16; - } -drawloop16: - *lpz++ = lzi >> 16; - *lpdest++ = ((short *)acolormap)[(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] + (lsfrac >> 16)]]; - lzi += r_zistepx; - lsfrac += r_sstepx; - ltfrac += r_tstepx; - llight += r_lstepx; - } - while (--lcount); - goto done16; - - do - { - if ((lzi >> 16) >= *lpz) // draw - { - lsfrac += r_sstepx * count; - ltfrac += r_tstepx * count; - llight += r_lstepx * count; - lpdest += count; - goto drawloop16; - } -skiploop16: - count++; - lzi += r_zistepx; - lpz++; - } - while (--lcount); -done16: ; - } - - pspanpackage++; - } - while (pspanpackage->count != -999999); - } -} - -void -polyset_draw_spans_32 (spanpackage_t * pspanpackage) -{ - int i, j, texscantable[2*MAX_LBM_HEIGHT], *texscan; - // LordHavoc: compute skin row table - for (i = 0, j = -r_affinetridesc.skinheight * r_affinetridesc.skinwidth; - i < r_affinetridesc.skinheight*2;i++, j += r_affinetridesc.skinwidth) - texscantable[i] = j; - texscan = texscantable + r_affinetridesc.skinheight; - - { - int lcount, count = 0; - int *lpdest; - byte *lptex; - int lsfrac, ltfrac; - int llight; - int lzi; - short *lpz; - - do - { - lcount = d_aspancount - pspanpackage->count; - - errorterm += erroradjustup; - if (errorterm >= 0) - { - d_aspancount += d_countextrastep; - errorterm -= erroradjustdown; - } - else - d_aspancount += ubasestep; - - if (lcount) - { - lpdest = (int *) d_viewbuffer + pspanpackage->pdest; - lptex = pspanpackage->ptex; - lpz = pspanpackage->pz; - lsfrac = pspanpackage->sfrac; - ltfrac = pspanpackage->tfrac; - llight = pspanpackage->light; - lzi = pspanpackage->zi; - - do - { - if ((lzi >> 16) < *lpz) // hidden - { - count = 0; - goto skiploop32; - } -drawloop32: - *lpz++ = lzi >> 16; - *lpdest++ = - vid.colormap32[(llight & 0xFF00) | - lptex[texscan[ltfrac >> 16] + - (lsfrac >> 16)]]; - lzi += r_zistepx; - lsfrac += r_sstepx; - ltfrac += r_tstepx; - llight += r_lstepx; - } - while (--lcount); - goto done32; - - do - { - if ((lzi >> 16) >= *lpz) // draw - { - lsfrac += r_sstepx * count; - ltfrac += r_tstepx * count; - llight += r_lstepx * count; - lpdest += count; - goto drawloop32; - } -skiploop32: - count++; - lzi += r_zistepx; - lpz++; - } - while (--lcount); -done32: ; - } - - pspanpackage++; - } - while (pspanpackage->count != -999999); - } -} void D_RasterizeAliasPolySmooth (void) @@ -875,13 +701,7 @@ D_RasterizeAliasPolySmooth (void) d_pdestbasestep = screenwidth + ubasestep; d_pdestextrastep = d_pdestbasestep + 1; -#ifdef USE_INTEL_ASM - if (sw_ctx->pixbytes == 1) { - d_pdest = (int) d_viewbuffer + ystart * screenwidth + plefttop[0]; - } else -#endif - d_pdest = ystart * screenwidth + plefttop[0]; - + d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0]; d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; // TODO: can reuse partial expressions here @@ -947,13 +767,7 @@ D_RasterizeAliasPolySmooth (void) d_pdestbasestep = screenwidth + ubasestep; d_pdestextrastep = d_pdestbasestep + 1; -#ifdef USE_INTEL_ASM - if (sw_ctx->pixbytes == 1) { - d_pdest = (int) d_viewbuffer + ystart * screenwidth + plefttop[0]; - } else -#endif - d_pdest = ystart * screenwidth + plefttop[0]; - + d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0]; #ifdef USE_INTEL_ASM d_pzbasestep = (d_zwidth + ubasestep) << 1; d_pzextrastep = d_pzbasestep + 2; @@ -1010,7 +824,7 @@ D_RasterizeAliasPolySmooth (void) originalcount = a_spans[initialrightheight].count; a_spans[initialrightheight].count = -999999; // mark end of the // spanpackages - sw_ctx->draw->polyset_draw_spans (a_spans); + D_PolysetDrawSpans8 (a_spans); // scan out the bottom part of the right edge, if it exists if (pedgetable->numrightedges == 2) { @@ -1033,7 +847,7 @@ D_RasterizeAliasPolySmooth (void) d_countextrastep = ubasestep + 1; a_spans[initialrightheight + height].count = -999999; // mark end of the spanpackages - sw_ctx->draw->polyset_draw_spans (pstart); + D_PolysetDrawSpans8 (pstart); } } diff --git a/libs/video/renderer/sw/d_scan.c b/libs/video/renderer/sw/d_scan.c index 91b0d5a67..c411e8b1e 100644 --- a/libs/video/renderer/sw/d_scan.c +++ b/libs/video/renderer/sw/d_scan.c @@ -33,8 +33,6 @@ #include "d_local.h" #include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" byte *r_turb_pbase; byte *r_turb_pdest; @@ -49,7 +47,7 @@ int r_turb_spancount; the sine warp, to keep the edges from wrapping */ void -warp_screen_8 (void) +D_WarpScreen (void) { int w, h; int u, v; @@ -98,105 +96,6 @@ warp_screen_8 (void) } } -void -warp_screen_16 (void) -{ - int w, h; - int u, v; - int scr_x = vr_data.scr_view->xpos; - int scr_y = vr_data.scr_view->ylen; - int scr_w = vr_data.scr_view->xpos; - int scr_h = vr_data.scr_view->ylen; - short *dest; - int *turb; - int *col; - short **row; - short *rowptr[MAXHEIGHT]; - int column[MAXWIDTH]; - float wratio, hratio; - - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - - wratio = w / (float) scr_w; - hratio = h / (float) scr_h; - - for (v = 0; v < scr_h + AMP2 * 2; v++) { - rowptr[v] = (short *) d_viewbuffer + - (r_refdef.vrect.y * screenwidth) + - (screenwidth * (int) ((float) v * hratio * h / - (h + AMP2 * 2))); - } - - for (u = 0; u < scr_w + AMP2 * 2; u++) { - column[u] = r_refdef.vrect.x + - (int) ((float) u * wratio * w / (w + AMP2 * 2)); - } - - turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = (short *) vid.buffer + scr_y * (vid.rowbytes >> 1) + scr_x; - - for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 1)) { - col = &column[turb[v]]; - row = &rowptr[v]; - for (u = 0; u < scr_w; u += 4) { - dest[u + 0] = row[turb[u + 0]][col[u + 0]]; - dest[u + 1] = row[turb[u + 1]][col[u + 1]]; - dest[u + 2] = row[turb[u + 2]][col[u + 2]]; - dest[u + 3] = row[turb[u + 3]][col[u + 3]]; - } - } -} - -void -warp_screen_32 (void) -{ - int w, h; - int u, v; - int scr_x = vr_data.scr_view->xpos; - int scr_y = vr_data.scr_view->ylen; - int scr_w = vr_data.scr_view->xpos; - int scr_h = vr_data.scr_view->ylen; - int *dest; - int *turb; - int *col; - int **row; - int *rowptr[MAXHEIGHT]; - int column[MAXWIDTH]; - float wratio, hratio; - - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - - wratio = w / (float) scr_w; - hratio = h / (float) scr_h; - - for (v = 0; v < scr_h + AMP2 * 2; v++) { - rowptr[v] = (int *) d_viewbuffer + - (r_refdef.vrect.y * screenwidth) + - (screenwidth * (int) ((float) v * hratio * h / - (h + AMP2 * 2))); - } - - for (u = 0; u < scr_w + AMP2 * 2; u++) { - column[u] = r_refdef.vrect.x + - (int) ((float) u * wratio * w / (w + AMP2 * 2)); - } - - turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = (int *) vid.buffer + scr_y * (vid.rowbytes >> 2) + scr_x; - - for (v = 0; v < scr_h; v++, dest += (vid.rowbytes >> 2)) { - col = &column[turb[v]]; - row = &rowptr[v]; - for (u = 0; u < scr_w; u += 4) { - dest[u + 0] = row[turb[u + 0]][col[u + 0]]; - dest[u + 1] = row[turb[u + 1]][col[u + 1]]; - dest[u + 2] = row[turb[u + 2]][col[u + 2]]; - dest[u + 3] = row[turb[u + 3]][col[u + 3]]; - } - } -} #ifdef PIC #undef USE_INTEL_ASM //XXX asm pic hack @@ -204,7 +103,7 @@ warp_screen_32 (void) #ifndef USE_INTEL_ASM void -draw_turbulent_span_8 (void) +D_DrawTurbulent8Span (void) { int sturb, tturb; @@ -222,41 +121,6 @@ draw_turbulent_span_8 (void) } #endif // !USE_INTEL_ASM -void -draw_turbulent_span_16 (void) -{ - int sturb, tturb; - short *pdest = (short *) r_turb_pdest; - - do { - sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & - (CYCLE - 1)]) >> 16) & 63; - tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & - (CYCLE - 1)]) >> 16) & 63; - *pdest++ = d_8to16table[r_turb_pbase[(tturb << 6) + sturb]]; - r_turb_s += r_turb_sstep; - r_turb_t += r_turb_tstep; - } while (--r_turb_spancount > 0); - r_turb_pdest = (byte *)pdest; -} - -void -draw_turbulent_span_32 (void) -{ - int sturb, tturb; - int *pdest = (int *) r_turb_pdest; - do { - sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & - (CYCLE - 1)]) >> 16) & 63; - tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & - (CYCLE - 1)]) >> 16) & 63; - *pdest++ = d_8to24table[r_turb_pbase[(tturb << 6) + sturb]]; - r_turb_s += r_turb_sstep; - r_turb_t += r_turb_tstep; - } while (--r_turb_spancount > 0); - r_turb_pdest = (byte *)pdest; -} - void Turbulent (espan_t *pspan) { @@ -372,7 +236,7 @@ Turbulent (espan_t *pspan) r_turb_s = r_turb_s & ((CYCLE << 16) - 1); r_turb_t = r_turb_t & ((CYCLE << 16) - 1); - sw_ctx->draw->draw_turbulent_span (); + D_DrawTurbulent8Span (); r_turb_s = snext; r_turb_t = tnext; @@ -384,7 +248,7 @@ Turbulent (espan_t *pspan) #ifndef USE_INTEL_ASM void -draw_spans_8 (espan_t *pspan) +D_DrawSpans8 (espan_t *pspan) { int count, spancount; unsigned char *pbase, *pdest; @@ -509,285 +373,6 @@ draw_spans_8 (espan_t *pspan) } #endif -void -draw_spans_16 (espan_t *pspan) -{ - short *pbase = (short *) cacheblock, *pdest; - int count; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv; - float sdivz8stepu, tdivz8stepu, zi8stepu; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - sdivz8stepu = d_sdivzstepu * 8; - tdivz8stepu = d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536; - - do { - pdest = (short *) d_viewbuffer + (screenwidth * pspan->v) + - pspan->u; - - count = pspan->count; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; - tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = d_zitable[(unsigned short) zi]; - - s = (int) (sdivz * z) + sadjust; - s = bound(0, s, bbextents); - t = (int) (tdivz * z) + tadjust; - t = bound(0, t, bbextentt); - - while(count >= 8) { - count -= 8; - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sadjust; - snext = bound(8, snext, bbextents); - tnext = (int) (tdivz * z) + tadjust; - tnext = bound(8, tnext, bbextentt); - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[4] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[5] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[6] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[7] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s = snext;t = tnext; - pdest += 8; - } - if (count) - { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span - // (so can't step off polygon), clamp, calculate s and t steps - // across span by division, biasing steps low so we don't run - // off the texture - //countminus1 = (float) (count - 1); - sdivz += d_sdivzstepu * count; //minus1; - tdivz += d_tdivzstepu * count; //minus1; - zi += d_zistepu * 65536.0f * count; //minus1; - z = d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sadjust; - snext = bound(count, snext, bbextents); - tnext = (int) (tdivz * z) + tadjust; - tnext = bound(count, tnext, bbextentt); - - if (count > 1) { - sstep = (snext - s) / count; //(count - 1); - tstep = (tnext - t) / count; //(count - 1); - - if (count & 4) - { - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep;t += tstep; - pdest += 4; - } - if (count & 2) - { - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest += 2; - } - if (count & 1) - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - } - else - { - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - } - } - } while ((pspan = pspan->pnext) != NULL); -} - -void -draw_spans_32 (espan_t *pspan) -{ - int *pbase = (int *) cacheblock, *pdest; - int count; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv; - float sdivz8stepu, tdivz8stepu, zi8stepu; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - sdivz8stepu = d_sdivzstepu * 8; - tdivz8stepu = d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536; - - do { - pdest = (int *) d_viewbuffer + (screenwidth * pspan->v) + pspan->u; - - count = pspan->count; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; - tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = d_zitable[(unsigned short) zi]; - - s = (int) (sdivz * z) + sadjust; - s = bound(0, s, bbextents); - t = (int) (tdivz * z) + tadjust; - t = bound(0, t, bbextentt); - - while(count >= 8) { - count -= 8; - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sadjust; - snext = bound(8, snext, bbextents); - tnext = (int) (tdivz * z) + tadjust; - tnext = bound(8, tnext, bbextentt); - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[4] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[5] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[6] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[7] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s = snext; - t = tnext; - pdest += 8; - } - if (count) - { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span - // (so can't step off polygon), clamp, calculate s and t steps - // across span by division, biasing steps low so we don't run - // off the texture - //countminus1 = (float) (count - 1); - sdivz += d_sdivzstepu * count; //minus1; - tdivz += d_tdivzstepu * count; //minus1; - zi += d_zistepu * 65536.0f * count; //minus1; - z = d_zitable[(unsigned short) zi]; - - // prevent round-off error on <0 steps from from causing - // overstepping & running off the edge of the texture - snext = (int) (sdivz * z) + sadjust; - snext = bound(count, snext, bbextents); - tnext = (int) (tdivz * z) + tadjust; - tnext = bound(count, tnext, bbextentt); - - if (count > 1) { - sstep = (snext - s) / count; //(count - 1); - tstep = (tnext - t) / count; //(count - 1); - - if (count & 4) - { - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest += 4; - } - if (count & 2) - { - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - s += sstep; - t += tstep; - pdest += 2; - } - if (count & 1) - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - } - else - { - pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; - } - } - } while ((pspan = pspan->pnext) != NULL); -} - #ifndef USE_INTEL_ASM void D_DrawZSpans (espan_t *pspan) diff --git a/libs/video/renderer/sw/d_scana.S b/libs/video/renderer/sw/d_scana.S index aa3eb2112..6ca194e72 100644 --- a/libs/video/renderer/sw/d_scana.S +++ b/libs/video/renderer/sw/d_scana.S @@ -49,8 +49,8 @@ //---------------------------------------------------------------------- .align 4 -.globl C(draw_turbulent_span_8) -C(draw_turbulent_span_8): +.globl C(D_DrawTurbulent8Span) +C(D_DrawTurbulent8Span): pushl %ebp // preserve caller's stack frame pointer pushl %esi // preserve register variables pushl %edi diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index 88ee451f6..c6cd5832d 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -32,7 +32,6 @@ #include "d_local.h" #include "r_internal.h" -#include "vid_sw.h" #define SKY_SPAN_SHIFT 5 #define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT) @@ -66,7 +65,7 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) } void -draw_sky_scans_8 (espan_t *pspan) +D_DrawSkyScans (espan_t *pspan) { int count, spancount, u, v; unsigned char *pdest; @@ -134,141 +133,3 @@ draw_sky_scans_8 (espan_t *pspan) } while ((pspan = pspan->pnext) != NULL); } - -void -draw_sky_scans_16 (espan_t *pspan) -{ - int count, spancount, u, v; - short *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - int spancountminus1; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - snext = 0; // ditto - tnext = 0; // ditto - - do { - pdest = (short *) d_viewbuffer + screenwidth * pspan->v + pspan->u; - - count = pspan->count; - - // calculate the initial s & t - u = pspan->u; - v = pspan->v; - D_Sky_uv_To_st (u, v, &s, &t); - - do { - if (count >= SKY_SPAN_MAX) - spancount = SKY_SPAN_MAX; - else - spancount = count; - - count -= spancount; - - if (count) { - u += spancount; - - // calculate s and t at far end of span, - // calculate s and t steps across span by shifting - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) >> SKY_SPAN_SHIFT; - tstep = (tnext - t) >> SKY_SPAN_SHIFT; - } else { - // calculate s and t at last pixel in span, - // calculate s and t steps across span by division - spancountminus1 = (float) (spancount - 1); - - if (spancountminus1 > 0) { - u += spancountminus1; - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) / spancountminus1; - tstep = (tnext - t) / spancountminus1; - } - } - - do { - *pdest++ = ((short *) r_skysource) - [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - - } while ((pspan = pspan->pnext) != NULL); -} - -void -draw_sky_scans_32 (espan_t *pspan) -{ - int count, spancount, u, v; - int *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - int spancountminus1; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - snext = 0; // ditto - tnext = 0; // ditto - - do { - pdest = (int *) d_viewbuffer + screenwidth * pspan->v + pspan->u; - - count = pspan->count; - - // calculate the initial s & t - u = pspan->u; - v = pspan->v; - D_Sky_uv_To_st (u, v, &s, &t); - - do { - if (count >= SKY_SPAN_MAX) - spancount = SKY_SPAN_MAX; - else - spancount = count; - - count -= spancount; - - if (count) { - u += spancount; - - // calculate s and t at far end of span, - // calculate s and t steps across span by shifting - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) >> SKY_SPAN_SHIFT; - tstep = (tnext - t) >> SKY_SPAN_SHIFT; - } else { - // calculate s and t at last pixel in span, - // calculate s and t steps across span by division - spancountminus1 = (float) (spancount - 1); - - if (spancountminus1 > 0) { - u += spancountminus1; - D_Sky_uv_To_st (u, v, &snext, &tnext); - - sstep = (snext - s) / spancountminus1; - tstep = (tnext - t) / spancountminus1; - } - } - - do { - *pdest++ = ((int *) r_skysource) - [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - - } while ((pspan = pspan->pnext) != NULL); -} diff --git a/libs/video/renderer/sw/d_spr8.S b/libs/video/renderer/sw/d_spr8.S index 3043b36c2..fcda6abd6 100644 --- a/libs/video/renderer/sw/d_spr8.S +++ b/libs/video/renderer/sw/d_spr8.S @@ -95,8 +95,8 @@ LClampHigh5: #define pspans 4+16 .align 4 -.globl C(sprite_draw_spans_8) -C(sprite_draw_spans_8): +.globl C(D_SpriteDrawSpans) +C(D_SpriteDrawSpans): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables diff --git a/libs/video/renderer/sw/d_sprite.c b/libs/video/renderer/sw/d_sprite.c index 64757b283..b4f35202f 100644 --- a/libs/video/renderer/sw/d_sprite.c +++ b/libs/video/renderer/sw/d_sprite.c @@ -32,8 +32,6 @@ #include "d_local.h" #include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" static int sprite_height; static int minindex, maxindex; @@ -47,7 +45,7 @@ static sspan_t *sprite_spans; #ifndef USE_INTEL_ASM void -sprite_draw_spans_8 (sspan_t *pspan) +D_SpriteDrawSpans (sspan_t *pspan) { int count, spancount, izistep; int izi; @@ -196,307 +194,6 @@ sprite_draw_spans_8 (sspan_t *pspan) } #endif -void -sprite_draw_spans_16 (sspan_t *pspan) -{ - int count, spancount, izistep; - int izi; - byte *pbase; - short *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivz8stepu, tdivz8stepu, zi8stepu; - byte btemp; - short *pz; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - pbase = (byte *) cacheblock; - - sdivz8stepu = d_sdivzstepu * 8; - tdivz8stepu = d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536; - - // we count on FP exceptions being turned off to avoid range problems - izistep = (int) (d_zistepu * 0x8000 * 0x10000); - - do { - pdest = (short *) d_viewbuffer + screenwidth * pspan->v + pspan->u; - pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; - - count = pspan->count; - - if (count <= 0) - goto NextSpan2; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; - tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = d_zitable[(int) zi]; - // we count on FP exceptions being turned off to avoid range - // problems - izi = (int) (zi * 0x8000); - - s = (int) (sdivz * z) + sadjust; - if (s > bbextents) - s = bbextents; - else if (s < 0) - s = 0; - - t = (int) (tdivz * z) + tadjust; - if (t > bbextentt) - t = bbextentt; - else if (t < 0) - t = 0; - - do { - // calculate s and t at the far end of the span - if (count >= 8) - spancount = 8; - else - spancount = count; - - count -= spancount; - - if (count) { - // calculate s/z, t/z, zi->fixed s and t at far end of - // span, calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = d_zitable[(int) zi]; - - snext = (int) (sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps from causing overstepping - // & running off the texture's edge - - tnext = (int) (tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on - // <0 steps - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - } else { - // calculate s/z, t/z, zi->fixed s and t at last pixel in - // span (so can't step off polygon), clamp, calculate s - // and t steps across span by division, biasing steps - // low so we don't run off the texture - spancountminus1 = (float) (spancount - 1); - sdivz += d_sdivzstepu * spancountminus1; - tdivz += d_tdivzstepu * spancountminus1; - zi += d_zistepu * 65536.0f * spancountminus1; - z = d_zitable[(int) zi]; - snext = (int) (sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps from from causing - // overstepping & running off the - // edge of the texture - - tnext = (int) (tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on - // <0 steps - - if (spancount > 1) { - sstep = (snext - s) / (spancount - 1); - tstep = (tnext - t) / (spancount - 1); - } - } - - do { - btemp = pbase[(s >> 16) + (t >> 16) * cachewidth]; - if (btemp != TRANSPARENT_COLOR) { - if (*pz <= (izi >> 16)) { - *pz = izi >> 16; - *pdest = d_8to16table[btemp]; - } - } - - izi += izistep; - pdest++; - pz++; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - -NextSpan2: - pspan++; - - } while (pspan->count != DS_SPAN_LIST_END); -} - -void -sprite_draw_spans_32 (sspan_t *pspan) -{ - int count, spancount, izistep; - int izi; - byte *pbase; - int *pdest; - fixed16_t s, t, snext, tnext, sstep, tstep; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivz8stepu, tdivz8stepu, zi8stepu; - byte btemp; - short *pz; - - sstep = 0; // keep compiler happy - tstep = 0; // ditto - - pbase = (byte *) cacheblock; - - sdivz8stepu = d_sdivzstepu * 8; - tdivz8stepu = d_tdivzstepu * 8; - zi8stepu = d_zistepu * 8 * 65536; - - // we count on FP exceptions being turned off to avoid range problems - izistep = (int) (d_zistepu * 0x8000 * 0x10000); - - do { - pdest = (int *) d_viewbuffer + screenwidth * pspan->v + pspan->u; - pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; - - count = pspan->count; - - if (count <= 0) - goto NextSpan4; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float) pspan->u; - dv = (float) pspan->v; - - sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; - tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; - zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; - z = d_zitable[(int) zi]; - // we count on FP exceptions being turned off to avoid range - // problems - izi = (int) (zi * 0x8000); - - s = (int) (sdivz * z) + sadjust; - if (s > bbextents) - s = bbextents; - else if (s < 0) - s = 0; - - t = (int) (tdivz * z) + tadjust; - if (t > bbextentt) - t = bbextentt; - else if (t < 0) - t = 0; - - do { - // calculate s and t at the far end of the span - if (count >= 8) - spancount = 8; - else - spancount = count; - - count -= spancount; - - if (count) { - // calculate s/z, t/z, zi->fixed s and t at far end of - // span, calculate s and t steps across span by shifting - sdivz += sdivz8stepu; - tdivz += tdivz8stepu; - zi += zi8stepu; - z = d_zitable[(int) zi]; - - snext = (int) (sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps from causing overstepping - // & running off the texture's edge - - tnext = (int) (tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on - // <0 steps - - sstep = (snext - s) >> 3; - tstep = (tnext - t) >> 3; - } else { - // calculate s/z, t/z, zi->fixed s and t at last pixel in - // span (so can't step off polygon), clamp, calculate s - // and t steps across span by division, biasing steps low - // so we don't run off the texture - spancountminus1 = (float) (spancount - 1); - sdivz += d_sdivzstepu * spancountminus1; - tdivz += d_tdivzstepu * spancountminus1; - zi += d_zistepu * 65536.0f * spancountminus1; - z = d_zitable[(int) zi]; - snext = (int) (sdivz * z) + sadjust; - if (snext > bbextents) - snext = bbextents; - else if (snext < 8) - snext = 8; // prevent round-off error on <0 - // steps fromcausing overstepping - // & running off the texture's edge - - tnext = (int) (tdivz * z) + tadjust; - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < 8) - tnext = 8; // guard against round-off error on - // <0 steps - - if (spancount > 1) { - sstep = (snext - s) / (spancount - 1); - tstep = (tnext - t) / (spancount - 1); - } - } - - do { - btemp = pbase[(s >> 16) + (t >> 16) * cachewidth]; - if (btemp != TRANSPARENT_COLOR) { - if (*pz <= (izi >> 16)) { - *pz = izi >> 16; - *pdest = d_8to24table[btemp]; - } - } - - izi += izistep; - pdest++; - pz++; - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; - - } while (count > 0); - -NextSpan4: - pspan++; - - } while (pspan->count != DS_SPAN_LIST_END); -} - static void D_SpriteScanLeftEdge (void) { @@ -715,5 +412,5 @@ D_DrawSprite (void) D_SpriteCalculateGradients (); D_SpriteScanLeftEdge (); D_SpriteScanRightEdge (); - sw_ctx->draw->sprite_draw_spans (sprite_spans); + D_SpriteDrawSpans (sprite_spans); } diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index c711a1a27..8e6e53c75 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -37,7 +37,6 @@ #include "compat.h" #include "d_local.h" #include "r_internal.h" -#include "vid_sw.h" float surfscale; @@ -70,7 +69,7 @@ D_SurfaceCacheForRes (void *data, int width, int height) if (pix > 64000) size += (pix - 64000) * 3; - return size * sw_ctx->pixbytes; + return size; } static void @@ -142,7 +141,7 @@ D_SCAlloc (int width, int size) if ((width < 0) || (width > 512)) // FIXME shouldn't really have a max Sys_Error ("D_SCAlloc: bad cache width %d", width); - if ((size <= 0) || (size > 0x40000 * sw_ctx->pixbytes)) // FIXME ditto + if ((size <= 0) || (size > 0x40000)) // FIXME ditto Sys_Error ("D_SCAlloc: bad cache size %d", size); // This adds the offset of data[0] in the surfcache_t struct. @@ -196,8 +195,7 @@ D_SCAlloc (int width, int size) new->width = width; // DEBUG if (width > 0) - new->height = (size - sizeof (*new) + sizeof (new->data)) / - (width * sw_ctx->pixbytes); + new->height = (size - sizeof (*new) + sizeof (new->data)) / width; new->owner = NULL; // should be set properly after return @@ -254,14 +252,14 @@ D_CacheSurface (msurface_t *surface, int miplevel) surfscale = 1.0 / (1 << miplevel); r_drawsurf.surfmip = miplevel; r_drawsurf.surfwidth = surface->extents[0] >> miplevel; - r_drawsurf.rowbytes = r_drawsurf.surfwidth * sw_ctx->pixbytes; + r_drawsurf.rowbytes = r_drawsurf.surfwidth; r_drawsurf.surfheight = surface->extents[1] >> miplevel; // allocate memory if needed if (!cache) { // if a texture just animated, don't reallocate it cache = D_SCAlloc (r_drawsurf.surfwidth, - r_drawsurf.rowbytes * r_drawsurf.surfheight); + r_drawsurf.surfwidth * r_drawsurf.surfheight); surface->cachespots[miplevel] = cache; cache->owner = &surface->cachespots[miplevel]; cache->mipscale = surfscale; diff --git a/libs/video/renderer/sw/d_zpoint.c b/libs/video/renderer/sw/d_zpoint.c index 1daf056ff..b7ed9e2bf 100644 --- a/libs/video/renderer/sw/d_zpoint.c +++ b/libs/video/renderer/sw/d_zpoint.c @@ -30,12 +30,10 @@ #include "d_local.h" #include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" void -draw_z_point_8 (void) +D_DrawZPoint (void) { byte *pdest; short *pz; @@ -50,35 +48,3 @@ draw_z_point_8 (void) *pdest = r_zpointdesc.color; } } - -void -draw_z_point_16 (void) -{ - short *pz; - int izi; - - pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u; - izi = (int) (r_zpointdesc.zi * 0x8000); - - if (*pz <= izi) { - *pz = izi; - ((short *) d_viewbuffer) [d_scantable[r_zpointdesc.v] - + r_zpointdesc.u] = d_8to16table[r_zpointdesc.color]; - } -} - -void -draw_z_point_32 (void) -{ - short *pz; - int izi; - - pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u; - izi = (int) (r_zpointdesc.zi * 0x8000); - - if (*pz <= izi) { - *pz = izi; - ((int *) d_viewbuffer) [d_scantable[r_zpointdesc.v] - + r_zpointdesc.u] = d_8to24table[r_zpointdesc.color]; - } -} diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 1b6a9bcb0..c909dd293 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -47,7 +47,6 @@ #include "d_iface.h" #include "r_internal.h" #include "vid_internal.h" -#include "vid_sw.h" typedef struct { int width; @@ -243,88 +242,6 @@ Draw_Init (void) r_rectdesc.rowbytes = draw_backtile->width; } -void -draw_character_8 (int x, int y, byte *source, int drawline) -{ - byte *dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; - - while (drawline--) { - if (source[0]) - dest[0] = source[0]; - if (source[1]) - dest[1] = source[1]; - if (source[2]) - dest[2] = source[2]; - if (source[3]) - dest[3] = source[3]; - if (source[4]) - dest[4] = source[4]; - if (source[5]) - dest[5] = source[5]; - if (source[6]) - dest[6] = source[6]; - if (source[7]) - dest[7] = source[7]; - source += 128; - dest += vid.rowbytes; - } -} - -void -draw_character_16 (int x, int y, byte *source, int drawline) -{ - uint16_t *dest = (uint16_t *) vid.buffer + y * (vid.rowbytes >> 1) + x; - - while (drawline--) { - if (source[0]) - dest[0] = d_8to16table[source[0]]; - if (source[1]) - dest[1] = d_8to16table[source[1]]; - if (source[2]) - dest[2] = d_8to16table[source[2]]; - if (source[3]) - dest[3] = d_8to16table[source[3]]; - if (source[4]) - dest[4] = d_8to16table[source[4]]; - if (source[5]) - dest[5] = d_8to16table[source[5]]; - if (source[6]) - dest[6] = d_8to16table[source[6]]; - if (source[7]) - dest[7] = d_8to16table[source[7]]; - - source += 128; - dest += (vid.rowbytes >> 1); - } -} - -void -draw_character_32 (int x, int y, byte *source, int drawline) -{ - uint32_t *dest = (uint32_t *) vid.buffer + y * (vid.rowbytes >> 2) + x; - - while (drawline--) { - if (source[0]) - dest[0] = d_8to24table[source[0]]; - if (source[1]) - dest[1] = d_8to24table[source[1]]; - if (source[2]) - dest[2] = d_8to24table[source[2]]; - if (source[3]) - dest[3] = d_8to24table[source[3]]; - if (source[4]) - dest[4] = d_8to24table[source[4]]; - if (source[5]) - dest[5] = d_8to24table[source[5]]; - if (source[6]) - dest[6] = d_8to24table[source[6]]; - if (source[7]) - dest[7] = d_8to24table[source[7]]; - - source += 128; - dest += (vid.rowbytes >> 2); - } -} /* Draw_Character @@ -336,6 +253,7 @@ draw_character_32 (int x, int y, byte *source, int drawline) inline void Draw_Character (int x, int y, unsigned int chr) { + byte *dest; byte *source; int drawline; int row, col; @@ -361,7 +279,28 @@ Draw_Character (int x, int y, unsigned int chr) } else drawline = 8; - sw_ctx->draw->draw_character (x, y, source, drawline); + dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + + while (drawline--) { + if (source[0]) + dest[0] = source[0]; + if (source[1]) + dest[1] = source[1]; + if (source[2]) + dest[2] = source[2]; + if (source[3]) + dest[3] = source[3]; + if (source[4]) + dest[4] = source[4]; + if (source[5]) + dest[5] = source[5]; + if (source[6]) + dest[6] = source[6]; + if (source[7]) + dest[7] = source[7]; + source += 128; + dest += vid.rowbytes; + } } @@ -394,8 +333,9 @@ Draw_AltString (int x, int y, const char *str) } } -void -draw_pixel_8 (int x, int y, byte color) + +static void +Draw_Pixel (int x, int y, byte color) { byte *dest; @@ -403,24 +343,6 @@ draw_pixel_8 (int x, int y, byte color) *dest = color; } -void -draw_pixel_16 (int x, int y, byte color) -{ - uint16_t *dest; - - dest = ((uint16_t*)vid.buffer) + y * vid.rowbytes + x; - *dest = d_8to16table[color]; -} - -void -draw_pixel_32 (int x, int y, byte color) -{ - uint32_t *dest; - - dest = ((uint32_t*)vid.buffer) + y * vid.rowbytes + x; - *dest = d_8to24table[color]; -} - static void crosshair_1 (int x, int y) { @@ -432,14 +354,14 @@ crosshair_2 (int x, int y) { byte c = crosshaircolor->int_val; - sw_ctx->draw->draw_pixel (x - 1, y, c); - sw_ctx->draw->draw_pixel (x - 3, y, c); - sw_ctx->draw->draw_pixel (x + 1, y, c); - sw_ctx->draw->draw_pixel (x + 3, y, c); - sw_ctx->draw->draw_pixel (x, y - 1, c); - sw_ctx->draw->draw_pixel (x, y - 3, c); - sw_ctx->draw->draw_pixel (x, y + 1, c); - sw_ctx->draw->draw_pixel (x, y + 3, c); + Draw_Pixel (x - 1, y, c); + Draw_Pixel (x - 3, y, c); + Draw_Pixel (x + 1, y, c); + Draw_Pixel (x + 3, y, c); + Draw_Pixel (x, y - 1, c); + Draw_Pixel (x, y - 3, c); + Draw_Pixel (x, y + 1, c); + Draw_Pixel (x, y + 3, c); } static void @@ -447,14 +369,14 @@ crosshair_3 (int x, int y) { byte c = crosshaircolor->int_val; - sw_ctx->draw->draw_pixel (x - 3, y - 3, c); - sw_ctx->draw->draw_pixel (x + 3, y - 3, c); - sw_ctx->draw->draw_pixel (x - 2, y - 2, c); - sw_ctx->draw->draw_pixel (x + 2, y - 2, c); - sw_ctx->draw->draw_pixel (x - 3, y + 3, c); - sw_ctx->draw->draw_pixel (x + 2, y + 2, c); - sw_ctx->draw->draw_pixel (x - 2, y + 2, c); - sw_ctx->draw->draw_pixel (x + 3, y + 3, c); + Draw_Pixel (x - 3, y - 3, c); + Draw_Pixel (x + 3, y - 3, c); + Draw_Pixel (x - 2, y - 2, c); + Draw_Pixel (x + 2, y - 2, c); + Draw_Pixel (x - 3, y + 3, c); + Draw_Pixel (x + 2, y + 2, c); + Draw_Pixel (x - 2, y + 2, c); + Draw_Pixel (x + 3, y + 3, c); } static void @@ -462,33 +384,33 @@ crosshair_4 (int x, int y) { //byte c = crosshaircolor->int_val; - sw_ctx->draw->draw_pixel (x, y - 2, 8); - sw_ctx->draw->draw_pixel (x + 1, y - 2, 9); + Draw_Pixel (x, y - 2, 8); + Draw_Pixel (x + 1, y - 2, 9); - sw_ctx->draw->draw_pixel (x, y - 1, 6); - sw_ctx->draw->draw_pixel (x + 1, y - 1, 8); - sw_ctx->draw->draw_pixel (x + 2, y - 1, 2); + Draw_Pixel (x, y - 1, 6); + Draw_Pixel (x + 1, y - 1, 8); + Draw_Pixel (x + 2, y - 1, 2); - sw_ctx->draw->draw_pixel (x - 2, y, 6); - sw_ctx->draw->draw_pixel (x - 1, y, 8); - sw_ctx->draw->draw_pixel (x, y, 8); - sw_ctx->draw->draw_pixel (x + 1, y, 6); - sw_ctx->draw->draw_pixel (x + 2, y, 8); - sw_ctx->draw->draw_pixel (x + 3, y, 8); + Draw_Pixel (x - 2, y, 6); + Draw_Pixel (x - 1, y, 8); + Draw_Pixel (x, y, 8); + Draw_Pixel (x + 1, y, 6); + Draw_Pixel (x + 2, y, 8); + Draw_Pixel (x + 3, y, 8); - sw_ctx->draw->draw_pixel (x - 1, y + 1, 2); - sw_ctx->draw->draw_pixel (x, y + 1, 8); - sw_ctx->draw->draw_pixel (x + 1, y + 1, 8); - sw_ctx->draw->draw_pixel (x + 2, y + 1, 2); - sw_ctx->draw->draw_pixel (x + 3, y + 1, 2); - sw_ctx->draw->draw_pixel (x + 4, y + 1, 2); + Draw_Pixel (x - 1, y + 1, 2); + Draw_Pixel (x, y + 1, 8); + Draw_Pixel (x + 1, y + 1, 8); + Draw_Pixel (x + 2, y + 1, 2); + Draw_Pixel (x + 3, y + 1, 2); + Draw_Pixel (x + 4, y + 1, 2); - sw_ctx->draw->draw_pixel (x, y + 2, 7); - sw_ctx->draw->draw_pixel (x + 1, y + 2, 8); - sw_ctx->draw->draw_pixel (x + 2, y + 2, 2); + Draw_Pixel (x, y + 2, 7); + Draw_Pixel (x + 1, y + 2, 8); + Draw_Pixel (x + 2, y + 2, 2); - sw_ctx->draw->draw_pixel (x + 1, y + 3, 2); - sw_ctx->draw->draw_pixel (x + 2, y + 3, 2); + Draw_Pixel (x + 1, y + 3, 2); + Draw_Pixel (x + 2, y + 3, 2); } static void @@ -496,29 +418,29 @@ crosshair_5 (int x, int y) { byte c = crosshaircolor->int_val; - sw_ctx->draw->draw_pixel (x - 1, y - 3, c); - sw_ctx->draw->draw_pixel (x + 0, y - 3, c); - sw_ctx->draw->draw_pixel (x + 1, y - 3, c); + Draw_Pixel (x - 1, y - 3, c); + Draw_Pixel (x + 0, y - 3, c); + Draw_Pixel (x + 1, y - 3, c); - sw_ctx->draw->draw_pixel (x - 2, y - 2, c); - sw_ctx->draw->draw_pixel (x + 2, y - 2, c); + Draw_Pixel (x - 2, y - 2, c); + Draw_Pixel (x + 2, y - 2, c); - sw_ctx->draw->draw_pixel (x - 3, y - 1, c); - sw_ctx->draw->draw_pixel (x + 3, y - 1, c); + Draw_Pixel (x - 3, y - 1, c); + Draw_Pixel (x + 3, y - 1, c); - sw_ctx->draw->draw_pixel (x - 3, y, c); - sw_ctx->draw->draw_pixel (x, y, c); - sw_ctx->draw->draw_pixel (x + 3, y, c); + Draw_Pixel (x - 3, y, c); + Draw_Pixel (x, y, c); + Draw_Pixel (x + 3, y, c); - sw_ctx->draw->draw_pixel (x - 3, y + 1, c); - sw_ctx->draw->draw_pixel (x + 3, y + 1, c); + Draw_Pixel (x - 3, y + 1, c); + Draw_Pixel (x + 3, y + 1, c); - sw_ctx->draw->draw_pixel (x - 2, y + 2, c); - sw_ctx->draw->draw_pixel (x + 2, y + 2, c); + Draw_Pixel (x - 2, y + 2, c); + Draw_Pixel (x + 2, y + 2, c); - sw_ctx->draw->draw_pixel (x - 1, y + 3, c); - sw_ctx->draw->draw_pixel (x + 0, y + 3, c); - sw_ctx->draw->draw_pixel (x + 1, y + 3, c); + Draw_Pixel (x - 1, y + 3, c); + Draw_Pixel (x + 0, y + 3, c); + Draw_Pixel (x + 1, y + 3, c); } static void (*crosshair_func[]) (int x, int y) = { @@ -559,11 +481,53 @@ Draw_CrosshairAt (int ch, int x, int y) void Draw_Pic (int x, int y, qpic_t *pic) { + byte *dest, *source, tbyte; + int v, u; + if (x < 0 || (x + pic->width) > vid.conview->xlen || y < 0 || (y + pic->height) > vid.conview->ylen) { Sys_MaskPrintf (SYS_vid, "Draw_Pic: bad coordinates"); + Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); + return; + } + + source = pic->data; + + dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + + if (pic->width & 7) { // general + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u++) + if ((tbyte = source[u]) != TRANSPARENT_COLOR) + dest[u] = tbyte; + + dest += vid.rowbytes; + source += pic->width; + } + } else { // unwound + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u += 8) { + if ((tbyte = source[u]) != TRANSPARENT_COLOR) + dest[u] = tbyte; + if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR) + dest[u + 1] = tbyte; + if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR) + dest[u + 2] = tbyte; + if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR) + dest[u + 3] = tbyte; + if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR) + dest[u + 4] = tbyte; + if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR) + dest[u + 5] = tbyte; + if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR) + dest[u + 6] = tbyte; + if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) + dest[u + 7] = tbyte; + } + dest += vid.rowbytes; + source += pic->width; + } } - Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); } void @@ -572,65 +536,13 @@ Draw_Picf (float x, float y, qpic_t *pic) Draw_Pic (x, y, pic); } -void -draw_subpic_8 (int x, int y, struct qpic_s *pic, int srcx, int srcy, - int width, int height) -{ - byte *source = pic->data + srcy * pic->width + srcx; - byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; - - for (int v = 0; v < height; v++) { - for (int u = 0; u < width; u++) { - byte tbyte = source[u]; - if (tbyte != TRANSPARENT_COLOR) { - dest[u] = tbyte; - } - } - dest += vid.rowbytes; - source += pic->width; - } -} - -void -draw_subpic_16 (int x, int y, struct qpic_s *pic, int srcx, int srcy, - int width, int height) -{ - byte *source = pic->data + srcy * pic->width + srcx; - uint16_t *dest = (uint16_t *) vid.buffer + y * (vid.rowbytes >> 1) + x; - for (int v = 0; v < height; v++) { - for (int u = 0; u < width; u++) { - byte tbyte = source[u]; - if (tbyte != TRANSPARENT_COLOR) { - dest[u] = d_8to16table[tbyte]; - } - } - dest += vid.rowbytes >> 1; - source += pic->width; - } -} - -void -draw_subpic_32 (int x, int y, struct qpic_s *pic, int srcx, int srcy, - int width, int height) -{ - byte *source = pic->data + srcy * pic->width + srcx; - uint32_t *dest = (uint32_t *) vid.buffer + y * (vid.rowbytes >> 2) + x; - for (int v = 0; v < height; v++) { - for (int u = 0; u < width; u++) { - byte tbyte = source[u]; - if (tbyte != TRANSPARENT_COLOR) { - dest[u] = d_8to24table[tbyte]; - } - } - dest += vid.rowbytes >> 2; - source += pic->width; - } -} - void Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height) { + byte *dest, *source, tbyte; + int u, v; + if ((x < 0) || (x + width > vid.conview->xlen) || (y < 0) || (y + height > vid.conview->ylen)) { Sys_MaskPrintf (SYS_vid, "Draw_SubPic: bad coordinates"); @@ -657,23 +569,68 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, // next, clip to pic CLIP (srcx, srcy, width, height, pic->width, pic->height); - sw_ctx->draw->draw_subpic (x, y, pic, srcx, srcy, width, height); + source = pic->data + srcy * pic->width + srcx; + + dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + + if (width & 7) { // general + for (v = 0; v < height; v++) { + for (u = 0; u < width; u++) + if ((tbyte = source[u]) != TRANSPARENT_COLOR) + dest[u] = tbyte; + + dest += vid.rowbytes; + source += pic->width; + } + } else { // unwound + for (v = 0; v < height; v++) { + for (u = 0; u < width; u += 8) { + if ((tbyte = source[u]) != TRANSPARENT_COLOR) + dest[u] = tbyte; + if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR) + dest[u + 1] = tbyte; + if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR) + dest[u + 2] = tbyte; + if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR) + dest[u + 3] = tbyte; + if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR) + dest[u + 4] = tbyte; + if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR) + dest[u + 5] = tbyte; + if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR) + dest[u + 6] = tbyte; + if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) + dest[u + 7] = tbyte; + } + dest += vid.rowbytes; + source += pic->width; + } + } } -void -draw_console_background_8 (int lines, byte *data) -{ - byte *dest = vid.buffer; - for (int y = 0; y < lines; y++, dest += vid.rowbytes) { - int v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; - byte *src = data + v * 320; +void +Draw_ConsoleBackground (int lines, byte alpha) +{ + int x, y, v; + byte *src, *dest; + int f, fstep; + qpic_t *conback; + + conback = Draw_CachePic ("gfx/conback.lmp", false); + + // draw the pic + dest = vid.buffer; + + for (y = 0; y < lines; y++, dest += vid.rowbytes) { + v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; + src = conback->data + v * 320; if (vid.conview->xlen == 320) memcpy (dest, src, vid.conview->xlen); else { - int f = 0; - int fstep = 320 * 0x10000 / vid.conview->xlen; - for (int x = 0; x < vid.conview->xlen; x += 4) { + f = 0; + fstep = 320 * 0x10000 / vid.conview->xlen; + for (x = 0; x < vid.conview->xlen; x += 4) { dest[x] = src[f >> 16]; f += fstep; dest[x + 1] = src[f >> 16]; @@ -685,72 +642,13 @@ draw_console_background_8 (int lines, byte *data) } } } -} - -void -draw_console_background_16 (int lines, byte *data) -{ - uint16_t *dest = (uint16_t *) vid.buffer; - - for (int y = 0; y < lines; y++, dest += (vid.rowbytes >> 1)) { - // FIXME: pre-expand to native format? - // FIXME: does the endian switching go away in production? - int v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; - byte *src = data + v * 320; - int f = 0; - int fstep = 320 * 0x10000 / vid.conview->xlen; - for (int x = 0; x < vid.conview->xlen; x += 4) { - dest[x] = d_8to16table[src[f >> 16]]; - f += fstep; - dest[x + 1] = d_8to16table[src[f >> 16]]; - f += fstep; - dest[x + 2] = d_8to16table[src[f >> 16]]; - f += fstep; - dest[x + 3] = d_8to16table[src[f >> 16]]; - f += fstep; - } - } -} - -void -draw_console_background_32 (int lines, byte *data) -{ - uint32_t *dest = (uint32_t *) vid.buffer; - - for (int y = 0; y < lines; y++, dest += (vid.rowbytes >> 2)) { - // FIXME: pre-expand to native format? - // FIXME: does the endian switching go away in production? - int v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; - byte *src = data + v * 320; - int f = 0; - int fstep = 320 * 0x10000 / vid.conview->xlen; - for (int x = 0; x < vid.conview->xlen; x += 4) { - dest[x] = d_8to24table[src[f >> 16]]; - f += fstep; - dest[x + 1] = d_8to24table[src[f >> 16]]; - f += fstep; - dest[x + 2] = d_8to24table[src[f >> 16]]; - f += fstep; - dest[x + 3] = d_8to24table[src[f >> 16]]; - f += fstep; - } - } -} - -void -Draw_ConsoleBackground (int lines, byte alpha) -{ - qpic_t *conback = Draw_CachePic ("gfx/conback.lmp", false); - - // draw the pic - sw_ctx->draw->draw_console_background (lines, conback->data); Draw_AltString (vid.conview->xlen - strlen (cl_verstring->string) * 8 - 11, lines - 14, cl_verstring->string); } -void -draw_rect_8 (vrect_t *prect, int rowbytes, byte *psrc, int transparent) +static void +R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) { byte t; int i, j, srcdelta, destdelta; @@ -785,223 +683,6 @@ draw_rect_8 (vrect_t *prect, int rowbytes, byte *psrc, int transparent) } } -void -draw_rect_16 (vrect_t *prect, int rowbytes, byte *psrc, int transparent) -{ - int i, j, srcdelta, destdelta; - uint16_t *pdest; - - pdest = (uint16_t *) vid.buffer + - (prect->y * (vid.rowbytes >> 1)) + prect->x; - - srcdelta = rowbytes - prect->width; - destdelta = (vid.rowbytes >> 1) - prect->width; - - if (transparent) { - for (i = 0; i < prect->height; i++) { - j = prect->width; - while(j >= 8) { - j -= 8; - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to16table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = d_8to16table[psrc[1]]; - if (psrc[2] != TRANSPARENT_COLOR) - pdest[2] = d_8to16table[psrc[2]]; - if (psrc[3] != TRANSPARENT_COLOR) - pdest[3] = d_8to16table[psrc[3]]; - if (psrc[4] != TRANSPARENT_COLOR) - pdest[4] = d_8to16table[psrc[4]]; - if (psrc[5] != TRANSPARENT_COLOR) - pdest[5] = d_8to16table[psrc[5]]; - if (psrc[6] != TRANSPARENT_COLOR) - pdest[6] = d_8to16table[psrc[6]]; - if (psrc[7] != TRANSPARENT_COLOR) - pdest[7] = d_8to16table[psrc[7]]; - psrc += 8; - pdest += 8; - } - if (j & 4) { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to16table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = d_8to16table[psrc[1]]; - if (psrc[2] != TRANSPARENT_COLOR) - pdest[2] = d_8to16table[psrc[2]]; - if (psrc[3] != TRANSPARENT_COLOR) - pdest[3] = d_8to16table[psrc[3]]; - psrc += 4; - pdest += 4; - } - if (j & 2) { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to16table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = d_8to16table[psrc[1]]; - psrc += 2; - pdest += 2; - } - if (j & 1) { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to16table[psrc[0]]; - psrc++; - pdest++; - } - - psrc += srcdelta; - pdest += destdelta; - } - } else { - for (i = 0; i < prect->height; - i++, psrc += srcdelta, pdest += destdelta) { - j = prect->width; - while(j >= 8) { - j -= 8; - pdest[0] = d_8to16table[psrc[0]]; - pdest[1] = d_8to16table[psrc[1]]; - pdest[2] = d_8to16table[psrc[2]]; - pdest[3] = d_8to16table[psrc[3]]; - pdest[4] = d_8to16table[psrc[4]]; - pdest[5] = d_8to16table[psrc[5]]; - pdest[6] = d_8to16table[psrc[6]]; - pdest[7] = d_8to16table[psrc[7]]; - psrc += 8; - pdest += 8; - } - if (j & 4) { - pdest[0] = d_8to16table[psrc[0]]; - pdest[1] = d_8to16table[psrc[1]]; - pdest[2] = d_8to16table[psrc[2]]; - pdest[3] = d_8to16table[psrc[3]]; - psrc += 4; - pdest += 4; - } - if (j & 2) { - pdest[0] = d_8to16table[psrc[0]]; - pdest[1] = d_8to16table[psrc[1]]; - psrc += 2; - pdest += 2; - } - if (j & 1) { - pdest[0] = d_8to16table[psrc[0]]; - psrc++; - pdest++; - } - } - } -} - -void -draw_rect_32 (vrect_t *prect, int rowbytes, byte *psrc, int transparent) -{ - int i, j, srcdelta, destdelta; - uint32_t *pdest; - - pdest = (uint32_t *)vid.buffer + prect->y * (vid.rowbytes >> 2) + prect->x; - - srcdelta = rowbytes - prect->width; - destdelta = (vid.rowbytes >> 2) - prect->width; - - if (transparent) { - for (i = 0; i < prect->height; i++) { - j = prect->width; - while(j >= 8) { - j -= 8; - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to24table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = d_8to24table[psrc[1]]; - if (psrc[2] != TRANSPARENT_COLOR) - pdest[2] = d_8to24table[psrc[2]]; - if (psrc[3] != TRANSPARENT_COLOR) - pdest[3] = d_8to24table[psrc[3]]; - if (psrc[4] != TRANSPARENT_COLOR) - pdest[4] = d_8to24table[psrc[4]]; - if (psrc[5] != TRANSPARENT_COLOR) - pdest[5] = d_8to24table[psrc[5]]; - if (psrc[6] != TRANSPARENT_COLOR) - pdest[6] = d_8to24table[psrc[6]]; - if (psrc[7] != TRANSPARENT_COLOR) - pdest[7] = d_8to24table[psrc[7]]; - psrc += 8; - pdest += 8; - } - if (j & 4) { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to24table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = d_8to24table[psrc[1]]; - if (psrc[2] != TRANSPARENT_COLOR) - pdest[2] = d_8to24table[psrc[2]]; - if (psrc[3] != TRANSPARENT_COLOR) - pdest[3] = d_8to24table[psrc[3]]; - psrc += 4; - pdest += 4; - } - if (j & 2) { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to24table[psrc[0]]; - if (psrc[1] != TRANSPARENT_COLOR) - pdest[1] = d_8to24table[psrc[1]]; - psrc += 2; - pdest += 2; - } - if (j & 1) { - if (psrc[0] != TRANSPARENT_COLOR) - pdest[0] = d_8to24table[psrc[0]]; - psrc++; - pdest++; - } - - psrc += srcdelta; - pdest += destdelta; - } - } else { - for (i = 0; i < prect->height; - i++, psrc += srcdelta, pdest += destdelta) { - j = prect->width; - while(j >= 8) { - j -= 8; - pdest[0] = d_8to24table[psrc[0]]; - pdest[1] = d_8to24table[psrc[1]]; - pdest[2] = d_8to24table[psrc[2]]; - pdest[3] = d_8to24table[psrc[3]]; - pdest[4] = d_8to24table[psrc[4]]; - pdest[5] = d_8to24table[psrc[5]]; - pdest[6] = d_8to24table[psrc[6]]; - pdest[7] = d_8to24table[psrc[7]]; - psrc += 8; - pdest += 8; - } - if (j & 4) { - pdest[0] = d_8to24table[psrc[0]]; - pdest[1] = d_8to24table[psrc[1]]; - pdest[2] = d_8to24table[psrc[2]]; - pdest[3] = d_8to24table[psrc[3]]; - psrc += 4; - pdest += 4; - } - if (j & 2) { - pdest[0] = d_8to24table[psrc[0]]; - pdest[1] = d_8to24table[psrc[1]]; - psrc += 2; - pdest += 2; - } - if (j & 1) { - pdest[0] = d_8to24table[psrc[0]]; - psrc++; - pdest++; - } - } - } -} - -static void -R_DrawRect (vrect_t *prect, int rowbytes, byte *psrc, int transparent) -{ - sw_ctx->draw->draw_rect (prect, rowbytes, psrc, transparent); -} - /* Draw_TileClear @@ -1054,40 +735,6 @@ Draw_TileClear (int x, int y, int w, int h) } } -void -draw_fill_8 (int x, int y, int w, int h, int c) -{ - byte *dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; - for (int v = 0; v < h; v++, dest += vid.rowbytes) { - for (int u = 0; u < w; u++) { - dest[u] = c; - } - } -} - -void -draw_fill_16 (int x, int y, int w, int h, int c) -{ - byte *dest = ((byte*)vid.buffer) + y * (vid.rowbytes >> 1) + x; - c = d_8to16table[c]; - for (int v = 0; v < h; v++, dest += vid.rowbytes >> 1) { - for (int u = 0; u < w; u++) { - dest[u] = c; - } - } -} - -void -draw_fill_32 (int x, int y, int w, int h, int c) -{ - byte *dest = ((byte*)vid.buffer) + y * (vid.rowbytes >> 2) + x; - c = d_8to24table[c]; - for (int v = 0; v < h; v++, dest += vid.rowbytes >> 2) { - for (int u = 0; u < w; u++) { - dest[u] = c; - } - } -} /* Draw_Fill @@ -1097,6 +744,9 @@ draw_fill_32 (int x, int y, int w, int h, int c) void Draw_Fill (int x, int y, int w, int h, int c) { + byte *dest; + int u, v; + if (x < 0 || x + w > vid.conview->xlen || y < 0 || y + h > vid.conview->ylen) { Sys_MaskPrintf (SYS_vid, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", @@ -1104,77 +754,40 @@ Draw_Fill (int x, int y, int w, int h, int c) } CLIP (x, y, w, h, (int) vid.width, (int) vid.height); - sw_ctx->draw->draw_fill (x, y, w, h, c); + dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + for (v = 0; v < h; v++, dest += vid.rowbytes) + for (u = 0; u < w; u++) + dest[u] = c; } -void -draw_fadescreen_8 (void) -{ - int height = vid.conview->ylen; - int width = vid.conview->xlen / 4; - int offset = vid.rowbytes; - uint32_t *pbuf; - - for (int y = 0; y < height; y++) { - uint32_t mask; - - pbuf = (uint32_t *) ((byte *)vid.buffer + offset * y); - mask = 0xff << ((y & 1) << 4); - - for (int x = 0; x < width; x++) { - *pbuf++ &= mask; - } - } -} - -void -draw_fadescreen_16 (void) -{ - int height = vid.conview->ylen; - int width = vid.conview->xlen / 4; - int offset = vid.rowbytes >> 1; - uint32_t *pbuf; - - for (int y = 0; y < height; y++) { - pbuf = (uint32_t *) ((byte *)vid.buffer + offset * y); - - for (int x = 0; x < width; x++, pbuf++) { - *pbuf = (*pbuf >> 1) & 0x7bef7bef; - } - } -} - -void -draw_fadescreen_32 (void) -{ - int height = vid.conview->ylen; - int width = vid.conview->xlen / 4; - int offset = vid.rowbytes >> 2; - uint32_t *pbuf; - - for (int y = 0; y < height; y++) { - pbuf = (uint32_t *) ((byte *)vid.buffer + offset * y); - - for (int x = 0; x < width; x++, pbuf++) { - *pbuf = (*pbuf >> 1) & 0x7f7f7f7f; - } - } -} void Draw_FadeScreen (void) { + int x, y; + int height = vid.conview->ylen; + int width = vid.conview->xlen / 4; + uint32_t *pbuf; S_ExtraUpdate (); - sw_ctx->draw->draw_fadescreen (); + for (y = 0; y < height; y++) { + uint32_t mask; + + pbuf = (uint32_t *) ((byte *)vid.buffer + vid.rowbytes * y); + mask = 0xff << ((y & 1) << 4); + + for (x = 0; x < width; x++) { + *pbuf++ &= mask; + } + } vr_data.scr_copyeverything = 1; S_ExtraUpdate (); } void -draw_blendscreen_8 (quat_t color) +Draw_BlendScreen (quat_t color) { int r, g, b, i; const byte *basepal; @@ -1200,73 +813,3 @@ draw_blendscreen_8 (quat_t color) } vid.vid_internal->set_palette (vid.vid_internal->data, pal); } - -void -draw_blendscreen_16 (quat_t color) -{ - int i, r, b; - int g1, g2; - unsigned x, y; - unsigned short rramp[32], gramp[64], bramp[32], *temp; - for (i = 0; i < 32; i++) { - r = i << 3; - g1 = i << 3; - g2 = g1 + 4; - b = i << 3; - - r += (int) (color[3] * (color[0] * 256 - r)); - g1 += (int) (color[3] * (color[1] - g1)); - g2 += (int) (color[3] * (color[1] - g2)); - b += (int) (color[3] * (color[2] - b)); - - rramp[i] = (vid.gammatable[r] << 8) & 0xF800; - gramp[i*2+0] = (vid.gammatable[g1] << 3) & 0x07E0; - gramp[i*2+1] = (vid.gammatable[g2] << 3) & 0x07E0; - bramp[i] = (vid.gammatable[b] >> 3) & 0x001F; - } - temp = vid.buffer; - for (y = 0;y < vid.height;y++, temp += (vid.rowbytes >> 1)) - for (x = 0;x < vid.width;x++) - temp[x] = rramp[(temp[x] & 0xF800) >> 11] - + gramp[(temp[x] & 0x07E0) >> 5] + bramp[temp[x] & 0x001F]; -} - -void -draw_blendscreen_32 (quat_t color) -{ - unsigned x, y; - int i, r, g, b; - - byte ramp[256][4], *temp; - for (i = 0; i < 256; i++) { - r = i; - g = i; - b = i; - - r += (int) (color[3] * (color[0] * 256 - r)); - g += (int) (color[3] * (color[1] * 256 - g)); - b += (int) (color[3] * (color[2] * 256 - b)); - - ramp[i][0] = vid.gammatable[r]; - ramp[i][1] = vid.gammatable[g]; - ramp[i][2] = vid.gammatable[b]; - ramp[i][3] = 0; - } - temp = vid.buffer; - for (y = 0; y < vid.height; y++, temp += vid.rowbytes) - { - for (x = 0;x < vid.width;x++) - { - temp[x*4+0] = ramp[temp[x*4+0]][0]; - temp[x*4+1] = ramp[temp[x*4+1]][1]; - temp[x*4+2] = ramp[temp[x*4+2]][2]; - temp[x*4+3] = 0; - } - } -} - -void -Draw_BlendScreen (quat_t color) -{ - sw_ctx->draw->draw_blendscreen (color); -} diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 31daf43f3..30a60379e 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -37,8 +37,9 @@ #include "vid_sw.h" /* SCREEN SHOTS */ + tex_t * -capture_bgr_8 (void) +sw_SCR_CaptureBGR (void) { int count, x, y; tex_t *tex; @@ -65,21 +66,3 @@ capture_bgr_8 (void) } return tex; } - -tex_t * -capture_bgr_16 (void) -{ - return capture_bgr_8 ();//FIXME -} - -tex_t * -capture_bgr_32 (void) -{ - return capture_bgr_8 ();//FIXME -} - -tex_t * -sw_SCR_CaptureBGR (void) -{ - return sw_ctx->draw->capture_bgr (); -} diff --git a/libs/video/renderer/sw/surf8.S b/libs/video/renderer/sw/surf8.S index c112bf1f7..c15d2c689 100644 --- a/libs/video/renderer/sw/surf8.S +++ b/libs/video/renderer/sw/surf8.S @@ -55,8 +55,8 @@ C(R_Surf8Start): //---------------------------------------------------------------------- .align 4 -.globl C(R_DrawSurfaceBlock8_mip0) -C(R_DrawSurfaceBlock8_mip0): +.globl C(R_DrawSurfaceBlock_mip0) +C(R_DrawSurfaceBlock_mip0): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables @@ -70,7 +70,7 @@ C(R_DrawSurfaceBlock8_mip0): movl %eax,sb_v movl C(prowdestbase),%edi - movl C(psource),%esi + movl C(pbasesource),%esi Lv_loop_mip0: @@ -256,8 +256,8 @@ LBPatch15: movl %edx,C(lightright) jc Lblockloop8_mip0 -// if (psource >= r_sourcemax) -// psource -= stepback; +// if (pbasesource >= r_sourcemax) +// pbasesource -= stepback; cmpl C(r_sourcemax),%esi jb LSkip_mip0 @@ -281,8 +281,8 @@ LSkip_mip0: //---------------------------------------------------------------------- .align 4 -.globl C(R_DrawSurfaceBlock8_mip1) -C(R_DrawSurfaceBlock8_mip1): +.globl C(R_DrawSurfaceBlock_mip1) +C(R_DrawSurfaceBlock_mip1): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables @@ -296,7 +296,7 @@ C(R_DrawSurfaceBlock8_mip1): movl %eax,sb_v movl C(prowdestbase),%edi - movl C(psource),%esi + movl C(pbasesource),%esi Lv_loop_mip1: @@ -426,8 +426,8 @@ LBPatch29: jc Lblockloop8_mip1 -// if (psource >= r_sourcemax) -// psource -= stepback; +// if (pbasesource >= r_sourcemax) +// pbasesource -= stepback; cmpl C(r_sourcemax),%esi jb LSkip_mip1 @@ -451,8 +451,8 @@ LSkip_mip1: //---------------------------------------------------------------------- .align 4 -.globl C(R_DrawSurfaceBlock8_mip2) -C(R_DrawSurfaceBlock8_mip2): +.globl C(R_DrawSurfaceBlock_mip2) +C(R_DrawSurfaceBlock_mip2): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables @@ -466,7 +466,7 @@ C(R_DrawSurfaceBlock8_mip2): movl %eax,sb_v movl C(prowdestbase),%edi - movl C(psource),%esi + movl C(pbasesource),%esi Lv_loop_mip2: @@ -566,8 +566,8 @@ LBPatch21: jc Lblockloop8_mip2 -// if (psource >= r_sourcemax) -// psource -= stepback; +// if (pbasesource >= r_sourcemax) +// pbasesource -= stepback; cmpl C(r_sourcemax),%esi jb LSkip_mip2 @@ -591,8 +591,8 @@ LSkip_mip2: //---------------------------------------------------------------------- .align 4 -.globl C(R_DrawSurfaceBlock8_mip3) -C(R_DrawSurfaceBlock8_mip3): +.globl C(R_DrawSurfaceBlock_mip3) +C(R_DrawSurfaceBlock_mip3): pushl %ebp // preserve caller's stack frame pushl %edi pushl %esi // preserve register variables @@ -606,7 +606,7 @@ C(R_DrawSurfaceBlock8_mip3): movl %eax,sb_v movl C(prowdestbase),%edi - movl C(psource),%esi + movl C(pbasesource),%esi Lv_loop_mip3: @@ -708,8 +708,8 @@ LBPatch31: addl %edx,%esi addl %ebp,%edi -// if (psource >= r_sourcemax) -// psource -= stepback; +// if (pbasesource >= r_sourcemax) +// pbasesource -= stepback; cmpl C(r_sourcemax),%esi jb LSkip_mip3 diff --git a/libs/video/renderer/sw/sw_graph.c b/libs/video/renderer/sw/sw_graph.c index edcecf9a4..4480a7eb7 100644 --- a/libs/video/renderer/sw/sw_graph.c +++ b/libs/video/renderer/sw/sw_graph.c @@ -33,21 +33,23 @@ #include "QF/render.h" #include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" +/* + R_LineGraph + + Called by only R_DisplayTime +*/ void -line_grapn_8 (int x, int y, int *h_vals, int count, int height) +R_LineGraph (int x, int y, int *h_vals, int count, int height) { int h, i, s, color; - int offset = vid.rowbytes; byte *dest; // FIXME: disable on no-buffer adapters, or put in the driver s = height; while (count--) { - dest = ((byte*)vid.buffer) + offset * y + x++; + dest = ((byte*)vid.buffer) + vid.rowbytes * y + x++; h = *h_vals++; @@ -63,80 +65,8 @@ line_grapn_8 (int x, int y, int *h_vals, int count, int height) if (h > s) h = s; - for (i = 0; i < h; i++, dest -= offset) { + for (i = 0; i < h; i++, dest -= vid.rowbytes) { dest[0] = color; } } } - -void -line_grapn_16 (int x, int y, int *h_vals, int count, int height) -{ - int h, i, s, color; - int offset = vid.rowbytes >> 1; - uint16_t *dest; - - // FIXME: disable on no-buffer adapters, or put in the driver - s = height; - - while (count--) { - dest = ((uint16_t*)vid.buffer) + offset * y + x++; - - h = *h_vals++; - - if (h == 10000) - color = d_8to16table[0x6f]; // yellow - else if (h == 9999) - color = d_8to16table[0x4f]; // red - else if (h == 9998) - color = d_8to16table[0xd0]; // blue - else - color = d_8to16table[0xff]; // pink - - if (h > s) - h = s; - - for (i = 0; i < h; i++, dest -= offset) { - dest[0] = color; - } - } -} - -void -line_grapn_32 (int x, int y, int *h_vals, int count, int height) -{ - int h, i, s, color; - int offset = vid.rowbytes >> 2; - uint32_t *dest; - - // FIXME: disable on no-buffer adapters, or put in the driver - s = height; - - while (count--) { - dest = ((uint32_t*)vid.buffer) + offset * y + x++; - - h = *h_vals++; - - if (h == 10000) - color = d_8to24table[0x6f]; // yellow - else if (h == 9999) - color = d_8to24table[0x4f]; // red - else if (h == 9998) - color = d_8to24table[0xd0]; // blue - else - color = d_8to24table[0xff]; // pink - - if (h > s) - h = s; - - for (i = 0; i < h; i++, dest -= offset) { - dest[0] = color; - } - } -} - -void -R_LineGraph (int x, int y, int *h_vals, int count, int height) -{ - sw_ctx->draw->line_grapn (x, y, h_vals, count, height); -} diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 0158524e5..1899e2a47 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -39,7 +39,6 @@ #include "d_ifacea.h" #include "r_internal.h" -#include "vid_sw.h" #define LIGHT_MIN 5 // lowest light value we'll allow, to // avoid the need for inner-loop light @@ -564,12 +563,6 @@ R_AliasSetupSkin (entity_t *ent) r_affinetridesc.skinheight = pmdl->skinheight; acolormap = vid.colormap8; - if (sw_ctx->pixbytes != 1) { - if (sw_ctx->pixbytes == 2) - acolormap = vid.colormap16; - else - acolormap = vid.colormap32; - } if (ent->renderer.skin) { tex_t *base; @@ -662,12 +655,6 @@ R_AliasDrawModel (alight_t *plighting) if (!acolormap) acolormap = vid.colormap8; - if (acolormap == vid.colormap8 && sw_ctx->pixbytes != 1) { - if (sw_ctx->pixbytes == 2) - acolormap = vid.colormap16; - else - acolormap = vid.colormap32; - } if (r_affinetridesc.drawtype) { D_PolysetUpdateTables (); // FIXME: precalc... diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 6b56f18eb..841036858 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -54,28 +54,11 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" -#include "vid_sw.h" #ifdef PIC # undef USE_INTEL_ASM //XXX asm pic hack #endif -static sw_draw_t sw_draw_8 = { -#define SW_DRAW_FUNC(name, rettype, params) \ - .name = name##_8, -#include "vid_sw_draw.h" -}; -static sw_draw_t sw_draw_16 = { -#define SW_DRAW_FUNC(name, rettype, params) \ - .name = name##_16, -#include "vid_sw_draw.h" -}; -static sw_draw_t sw_draw_32 = { -#define SW_DRAW_FUNC(name, rettype, params) \ - .name = name##_32, -#include "vid_sw_draw.h" -}; - void *colormap; static vec3_t viewlightvec; static alight_t r_viewlighting = { 128, 192, viewlightvec }; @@ -134,15 +117,6 @@ sw_R_Init (void) { int dummy; - switch (sw_ctx->pixbytes) { - case 1: sw_ctx->draw = &sw_draw_8; break; - case 2: sw_ctx->draw = &sw_draw_16; break; - case 4: sw_ctx->draw = &sw_draw_32; break; - default: - Sys_Error("R_Init: unsupported pixbytes %i", - sw_ctx->pixbytes); - } - r_ent_queue = EntQueue_New (mod_num_types); // get stack position so we can guess if we are going to overflow @@ -832,7 +806,7 @@ R_RenderView_ (void) dp_time2 = Sys_DoubleTime (); if (r_dowarp) - sw_ctx->draw->warp_screen (); + D_WarpScreen (); if (r_timegraph->int_val) R_TimeGraph (); diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index 15928e633..a76d2d105 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -48,7 +48,6 @@ #include "compat.h" #include "r_internal.h" -#include "vid_sw.h" void R_DrawParticles (void) @@ -59,10 +58,9 @@ R_DrawParticles (void) R_RunParticles (vr_data.frametime); - void (*draw) (struct particle_s *particle) = sw_ctx->draw->draw_particle; for (unsigned i = 0; i < r_psystem.numparticles; i++) { particle_t *p = &r_psystem.particles[i]; - draw (p); + D_DrawParticle (p); } } diff --git a/libs/video/renderer/sw/sw_rsky.c b/libs/video/renderer/sw/sw_rsky.c index d67d0f375..b179ce420 100644 --- a/libs/video/renderer/sw/sw_rsky.c +++ b/libs/video/renderer/sw/sw_rsky.c @@ -28,13 +28,9 @@ # include "config.h" #endif -#include - #include "QF/render.h" #include "r_internal.h" -#include "vid_internal.h" -#include "vid_sw.h" static int iskyspeed = 8; @@ -51,12 +47,10 @@ int r_skymade; byte bottomsky[128 * 131]; byte bottommask[128 * 131]; -// sky and topsky both pack in here, 128 -// bytes of sky on the left of each scan, -// 128 bytes of topsky on the right, because -// the low-level drawers need 256-byte widths -byte skydata[128 * 256]; -byte skytex[128 * 256 * 4]; +byte newsky[128 * 256]; // newsky and topsky both pack in here, 128 + // bytes of newsky on the left of each scan, + // 128 bytes of topsky on the right, because + // the low-level drawers need 256-byte widths /* @@ -67,116 +61,116 @@ byte skytex[128 * 256 * 4]; void R_InitSky (texture_t *mt) { - memcpy (skydata, (byte *) mt + mt->offsets[0], 128 * 256); - r_skysource = skytex; + int i, j; + byte *src; + + src = (byte *) mt + mt->offsets[0]; + + for (i = 0; i < 128; i++) { + for (j = 0; j < 128; j++) { + newsky[(i * 256) + j + 128] = src[i * 256 + j + 128]; + } + } + + for (i = 0; i < 128; i++) { + for (j = 0; j < 131; j++) { + if (src[i * 256 + (j & 0x7F)]) { + bottomsky[(i * 131) + j] = src[i * 256 + (j & 0x7F)]; + bottommask[(i * 131) + j] = 0; + } else { + bottomsky[(i * 131) + j] = 0; + bottommask[(i * 131) + j] = 0xff; + } + } + } + + r_skysource = newsky; } + void -make_sky_8 (void) +R_MakeSky (void) { - int x, y, xshift1, yshift1, xshift2, yshift2; - byte *base1, *base2; + int x, y; + int ofs, baseofs; + int xshift, yshift; + byte *pnewsky; static int xlast = -1, ylast = -1; - xshift2 = r_skytime * r_skyspeed * 2.0f; - yshift2 = r_skytime * r_skyspeed * 2.0f; + xshift = r_skytime * r_skyspeed; + yshift = r_skytime * r_skyspeed; - if ((xshift2 == xlast) && (yshift2 == ylast)) + if ((xshift == xlast) && (yshift == ylast)) return; - xlast = xshift2; - ylast = yshift2; - xshift1 = xshift2 >> 1; - yshift1 = yshift2 >> 1; + xlast = xshift; + ylast = yshift; - byte *out = (byte *) skytex; - for (y = 0;y < 128;y++) - { - base1 = &skydata[((y + yshift1) & 127) * 256]; - base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; - for (x = 0;x < 128;x++) - { - if (base1[(x + xshift1) & 127]) - *out = base1[(x + xshift1) & 127]; - else - *out = base2[(x + xshift2) & 127]; - out++; + pnewsky = &newsky[0]; + + for (y = 0; y < SKYSIZE; y++) { + baseofs = ((y + yshift) & SKYMASK) * 131; + for (x = 0; x < SKYSIZE; x++) { + ofs = baseofs + ((x + xshift) & SKYMASK); + + *pnewsky = (*(pnewsky + 128) & bottommask[ofs]) | bottomsky[ofs]; + pnewsky = pnewsky + 1; } - out += 128; + pnewsky += 128; } + r_skymade = 1; } -void -make_sky_16 (void) -{ - int x, y, xshift1, yshift1, xshift2, yshift2; - byte *base1, *base2; - static int xlast = -1, ylast = -1; - - xshift2 = r_skytime * r_skyspeed * 2.0f; - yshift2 = r_skytime * r_skyspeed * 2.0f; - - if ((xshift2 == xlast) && (yshift2 == ylast)) - return; - - xlast = xshift2; - ylast = yshift2; - xshift1 = xshift2 >> 1; - yshift1 = yshift2 >> 1; - - unsigned short *out = (unsigned short *) skytex; - for (y = 0;y < 128;y++) - { - base1 = &skydata[((y + yshift1) & 127) * 256]; - base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; - for (x = 0;x < 128;x++) - { - if (base1[(x + xshift1) & 127]) - *out = d_8to16table[base1[(x + xshift1) & 127]]; - else - *out = d_8to16table[base2[(x + xshift2) & 127]]; - out++; - } - out += 128; - } - r_skymade = 1; -} void -make_sky_32 (void) +R_GenSkyTile (void *pdest) { - int x, y, xshift1, yshift1, xshift2, yshift2; - byte *base1, *base2; - static int xlast = -1, ylast = -1; + int x, y; + int ofs, baseofs; + int xshift, yshift; + unsigned int *pnewsky; + unsigned int *pd; - xshift2 = r_skytime * r_skyspeed * 2.0f; - yshift2 = r_skytime * r_skyspeed * 2.0f; + xshift = r_skytime * r_skyspeed; + yshift = r_skytime * r_skyspeed; - if ((xshift2 == xlast) && (yshift2 == ylast)) - return; + pnewsky = (unsigned int *) &newsky[0]; + pd = (unsigned int *) pdest; - xlast = xshift2; - ylast = yshift2; - xshift1 = xshift2 >> 1; - yshift1 = yshift2 >> 1; + for (y = 0; y < SKYSIZE; y++) { + baseofs = ((y + yshift) & SKYMASK) * 131; - unsigned int *out = (unsigned int *) skytex; - for (y = 0;y < 128;y++) { - base1 = &skydata[((y + yshift1) & 127) * 256]; - base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; - for (x = 0;x < 128;x++) { - if (base1[(x + xshift1) & 127]) - *out = d_8to24table[base1[(x + xshift1) & 127]]; - else - *out = d_8to24table[base2[(x + xshift2) & 127]]; - out++; +// FIXME: clean this up +#if UNALIGNED_OK + for (x = 0; x < SKYSIZE; x += 4) { + ofs = baseofs + ((x + xshift) & SKYMASK); + + // PORT: unaligned dword access to bottommask and bottomsky + + *pd = (*(pnewsky + (128 / sizeof (unsigned int))) & + *(unsigned int *) &bottommask[ofs]) | + *(unsigned int *) &bottomsky[ofs]; + + pnewsky++; + pd++; } - out += 128; +#else + for (x = 0; x < SKYSIZE; x++) { + ofs = baseofs + ((x + xshift) & SKYMASK); + + *(byte *) pd = (*((byte *) pnewsky + 128) & + *(byte *) & bottommask[ofs]) | + *(byte *) & bottomsky[ofs]; + pnewsky = (unsigned int *) ((byte *) pnewsky + 1); + pd = (unsigned int *) ((byte *) pd + 1); + } +#endif + pnewsky += 128 / sizeof (unsigned int); } - r_skymade = 1; } + void R_SetSkyFrame (void) { diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 3b968bd88..106dd8f29 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -1,5 +1,5 @@ /* - rsurf.c + sw_rsurf.c surface-related refresh code @@ -33,63 +33,43 @@ #include "QF/scene/entity.h" -#include "compat.h" #include "r_internal.h" -#include "vid_sw.h" + +#ifdef PIC +# undef USE_INTEL_ASM //XXX asm pic hack +#endif drawsurf_t r_drawsurf; -int sourcetstep; -static int lightleft, blocksize; +int sourcesstep, sourcetstep; +#ifndef USE_INTEL_ASM +static int lightleft; +#endif +static int blocksize; int lightdelta, lightdeltastep; int lightright, lightleftstep, lightrightstep, blockdivshift; static unsigned int blockdivmask; -byte *prowdestbase; -byte *psource; -int surfrowbytes; -unsigned int *r_lightptr; +void *prowdestbase; +unsigned char *pbasesource; +int surfrowbytes; // used by ASM files +unsigned int *r_lightptr; int r_stepback; int r_lightwidth; static int r_numhblocks; int r_numvblocks; -static byte *r_source; -byte *r_sourcemax; +static unsigned char *r_source; +unsigned char *r_sourcemax; -void R_DrawSurfaceBlock8_mip0 (void); -void R_DrawSurfaceBlock8_mip1 (void); -void R_DrawSurfaceBlock8_mip2 (void); -void R_DrawSurfaceBlock8_mip3 (void); -static void R_DrawSurfaceBlock16_mip0 (void); -static void R_DrawSurfaceBlock16_mip1 (void); -static void R_DrawSurfaceBlock16_mip2 (void); -static void R_DrawSurfaceBlock16_mip3 (void); -static void R_DrawSurfaceBlock32_mip0 (void); -static void R_DrawSurfaceBlock32_mip1 (void); -static void R_DrawSurfaceBlock32_mip2 (void); -static void R_DrawSurfaceBlock32_mip3 (void); +void R_DrawSurfaceBlock_mip0 (void); +void R_DrawSurfaceBlock_mip1 (void); +void R_DrawSurfaceBlock_mip2 (void); +void R_DrawSurfaceBlock_mip3 (void); -static void (*surfmiptable8[4]) (void) = { - R_DrawSurfaceBlock8_mip0, - R_DrawSurfaceBlock8_mip1, - R_DrawSurfaceBlock8_mip2, - R_DrawSurfaceBlock8_mip3 -}; +static void (*surfmiptable[4]) (void) = { + R_DrawSurfaceBlock_mip0, R_DrawSurfaceBlock_mip1, + R_DrawSurfaceBlock_mip2, R_DrawSurfaceBlock_mip3}; -static void (*surfmiptable16[4]) (void) = { - R_DrawSurfaceBlock16_mip0, - R_DrawSurfaceBlock16_mip1, - R_DrawSurfaceBlock16_mip2, - R_DrawSurfaceBlock16_mip3 -}; - -static void (*surfmiptable32[4]) (void) = { - R_DrawSurfaceBlock32_mip0, - R_DrawSurfaceBlock32_mip1, - R_DrawSurfaceBlock32_mip2, - R_DrawSurfaceBlock32_mip3 -}; - -static unsigned blocklights[34 * 34]; //FIXME make dynamic +static unsigned int blocklights[34 * 34]; //FIXME make dynamic static void @@ -202,30 +182,14 @@ R_BuildLightMap (void) if (surf->dlightframe == r_framecount) R_AddDynamicLights (); - /* - * JohnnyonFlame: - * 32 and 16bpp modes uses the positive lighting, unlike 8bpp - */ - switch (sw_ctx->pixbytes) { - case 1: - // bound, invert, and shift - for (i = 0; i < size; i++) { - t = (255 * 256 - blocklights[i]) >> (8 - VID_CBITS); + // bound, invert, and shift + for (i = 0; i < size; i++) { + t = (255 * 256 - (int) blocklights[i]) >> (8 - VID_CBITS); - if (t < (1 << 6)) - t = (1 << 6); + if (t < (1 << 6)) + t = (1 << 6); - blocklights[i] = t; - } - break; - default: - // LordHavoc: changed to positive (not inverse) lighting - for (i = 0; i < size; i++) { - t = bound(256, blocklights[i] >> (8 - VID_CBITS), - 256 * (VID_GRADES - 1)); - blocklights[i] = t; - } - break; + blocklights[i] = t; } } @@ -266,47 +230,34 @@ R_DrawSurface (void) //============================== + pblockdrawer = surfmiptable[r_drawsurf.surfmip]; + // TODO: needs to be set only when there is a display settings change + horzblockstep = blocksize; + smax = mt->width >> r_drawsurf.surfmip; twidth = texwidth; tmax = mt->height >> r_drawsurf.surfmip; sourcetstep = texwidth; r_stepback = tmax * twidth; + r_sourcemax = r_source + (tmax * smax); + soffset = r_drawsurf.surf->texturemins[0]; basetoffset = r_drawsurf.surf->texturemins[1]; - switch (sw_ctx->pixbytes) { - case 1: - pblockdrawer = surfmiptable8[r_drawsurf.surfmip]; - break; - case 2: - pblockdrawer = surfmiptable16[r_drawsurf.surfmip]; - break; - case 4: - pblockdrawer = surfmiptable32[r_drawsurf.surfmip]; - break; - default: - Sys_Error("R_DrawSurface: unsupported r_pixbytes %i", sw_ctx->pixbytes); - pblockdrawer = NULL; - } - - horzblockstep = blocksize * sw_ctx->pixbytes; - - r_sourcemax = r_source + (tmax * smax); - // << 16 components are to guarantee positive values for % - basetptr = r_source + (((basetoffset >> r_drawsurf.surfmip) + - (tmax << 16)) % tmax) * twidth; - soffset = (((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax); + soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax; + basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip) + + (tmax << 16)) % tmax) * twidth)]; - pcolumndest = (byte *) r_drawsurf.surfdat; + pcolumndest = r_drawsurf.surfdat; for (u = 0; u < r_numhblocks; u++) { r_lightptr = blocklights + u; prowdestbase = pcolumndest; - psource = basetptr + soffset; + pbasesource = basetptr + soffset; (*pblockdrawer) (); @@ -318,16 +269,15 @@ R_DrawSurface (void) } } -//============================================================================= - #ifndef USE_INTEL_ASM void -R_DrawSurfaceBlock8_mip0 (void) +R_DrawSurfaceBlock_mip0 (void) { - int v, i, b, lightstep, light; - unsigned char pix, *prowdest; + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + psource = pbasesource; prowdest = prowdestbase; for (v = 0; v < r_numvblocks; v++) { @@ -340,13 +290,15 @@ R_DrawSurfaceBlock8_mip0 (void) lightrightstep = (r_lightptr[1] - lightright) >> 4; for (i = 0; i < 16; i++) { - lightstep = (lightleft - lightright) >> 4; + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 4; light = lightright; for (b = 15; b >= 0; b--) { pix = psource[b]; - prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; + prowdest[b] = ((unsigned char *) vid.colormap8) + [(light & 0xFF00) + pix]; light += lightstep; } @@ -362,11 +314,12 @@ R_DrawSurfaceBlock8_mip0 (void) } void -R_DrawSurfaceBlock8_mip1 (void) +R_DrawSurfaceBlock_mip1 (void) { - int v, i, b, lightstep, light; - unsigned char pix, *prowdest; + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + psource = pbasesource; prowdest = prowdestbase; for (v = 0; v < r_numvblocks; v++) { @@ -379,13 +332,15 @@ R_DrawSurfaceBlock8_mip1 (void) lightrightstep = (r_lightptr[1] - lightright) >> 3; for (i = 0; i < 8; i++) { - lightstep = (lightleft - lightright) >> 3; + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 3; light = lightright; for (b = 7; b >= 0; b--) { pix = psource[b]; - prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; + prowdest[b] = ((unsigned char *) vid.colormap8) + [(light & 0xFF00) + pix]; light += lightstep; } @@ -401,11 +356,12 @@ R_DrawSurfaceBlock8_mip1 (void) } void -R_DrawSurfaceBlock8_mip2 (void) +R_DrawSurfaceBlock_mip2 (void) { - int v, i, b, lightstep, light; - unsigned char pix, *prowdest; + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + psource = pbasesource; prowdest = prowdestbase; for (v = 0; v < r_numvblocks; v++) { @@ -418,13 +374,15 @@ R_DrawSurfaceBlock8_mip2 (void) lightrightstep = (r_lightptr[1] - lightright) >> 2; for (i = 0; i < 4; i++) { - lightstep = (lightleft - lightright) >> 2; + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 2; light = lightright; for (b = 3; b >= 0; b--) { pix = psource[b]; - prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; + prowdest[b] = ((unsigned char *) vid.colormap8) + [(light & 0xFF00) + pix]; light += lightstep; } @@ -440,11 +398,12 @@ R_DrawSurfaceBlock8_mip2 (void) } void -R_DrawSurfaceBlock8_mip3 (void) +R_DrawSurfaceBlock_mip3 (void) { - int v, i, b, lightstep, light; - unsigned char pix, *prowdest; + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + psource = pbasesource; prowdest = prowdestbase; for (v = 0; v < r_numvblocks; v++) { @@ -457,13 +416,15 @@ R_DrawSurfaceBlock8_mip3 (void) lightrightstep = (r_lightptr[1] - lightright) >> 1; for (i = 0; i < 2; i++) { - lightstep = (lightleft - lightright) >> 1; + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 1; light = lightright; for (b = 1; b >= 0; b--) { pix = psource[b]; - prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; + prowdest[b] = ((unsigned char *) vid.colormap8) + [(light & 0xFF00) + pix]; light += lightstep; } @@ -481,423 +442,33 @@ R_DrawSurfaceBlock8_mip3 (void) #endif static void -R_DrawSurfaceBlock16_mip0 (void) +R_GenTurbTile (byte *pbasetex, void *pdest) { - int k, v; - int lightstep, light; - unsigned short *prowdest; + int *turb; + int i, j, s, t; + byte *pd; - prowdest = (unsigned short *) prowdestbase; + turb = sintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); + pd = (byte *) pdest; - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 4; - lightrightstep = (r_lightptr[1] - lightright) >> 4; - - for (k = 0; k < 16; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 4; - - prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; - light += lightstep; - prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]]; - light += lightstep; - prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]]; - light += lightstep; - prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]]; - light += lightstep; - prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]]; - light += lightstep; - prowdest[8] = vid.colormap16[(light & 0xFF00) + psource[8]]; - light += lightstep; - prowdest[9] = vid.colormap16[(light & 0xFF00) + psource[9]]; - light += lightstep; - prowdest[10] = vid.colormap16[(light & 0xFF00) + psource[10]]; - light += lightstep; - prowdest[11] = vid.colormap16[(light & 0xFF00) + psource[11]]; - light += lightstep; - prowdest[12] = vid.colormap16[(light & 0xFF00) + psource[12]]; - light += lightstep; - prowdest[13] = vid.colormap16[(light & 0xFF00) + psource[13]]; - light += lightstep; - prowdest[14] = vid.colormap16[(light & 0xFF00) + psource[14]]; - light += lightstep; - prowdest[15] = vid.colormap16[(light & 0xFF00) + psource[15]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 1); + for (i = 0; i < TILE_SIZE; i++) { + for (j = 0; j < TILE_SIZE; j++) { + s = (((j << 16) + turb[i & (CYCLE - 1)]) >> 16) & 63; + t = (((i << 16) + turb[j & (CYCLE - 1)]) >> 16) & 63; + *pd++ = *(pbasetex + (t << 6) + s); } - - if (psource >= r_sourcemax) - psource -= r_stepback; } } -static void -R_DrawSurfaceBlock16_mip1 (void) -{ - int k, v; - int lightstep, light; - unsigned short *prowdest; - - prowdest = (unsigned short *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 3; - lightrightstep = (r_lightptr[1] - lightright) >> 3; - - for (k = 0; k < 8; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 3; - - prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; - light += lightstep; - prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]]; - light += lightstep; - prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]]; - light += lightstep; - prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]]; - light += lightstep; - prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 1); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock16_mip2 (void) -{ - int k, v; - int lightstep, light; - unsigned short *prowdest; - - prowdest = (unsigned short *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 2; - lightrightstep = (r_lightptr[1] - lightright) >> 2; - - for (k = 0; k < 4; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 2; - - prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 1); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock16_mip3 (void) -{ - int v; - unsigned short *prowdest; - - prowdest = (unsigned short *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 1; - lightrightstep = (r_lightptr[1] - lightright) >> 1; - - prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]]; - prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) & - 0xFF00) + psource[1]]; - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 1); - - prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]]; - prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) & - 0xFF00) + psource[1]]; - psource += sourcetstep; - prowdest += (surfrowbytes >> 1); - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock32_mip0 (void) -{ - int k, v; - int lightstep, light; - unsigned int *prowdest; - - prowdest = (unsigned int *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 4; - lightrightstep = (r_lightptr[1] - lightright) >> 4; - - for (k = 0; k < 16; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 4; - - prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; - light += lightstep; - prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]]; - light += lightstep; - prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]]; - light += lightstep; - prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]]; - light += lightstep; - prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]]; - light += lightstep; - prowdest[8] = vid.colormap32[(light & 0xFF00) + psource[8]]; - light += lightstep; - prowdest[9] = vid.colormap32[(light & 0xFF00) + psource[9]]; - light += lightstep; - prowdest[10] = vid.colormap32[(light & 0xFF00) + psource[10]]; - light += lightstep; - prowdest[11] = vid.colormap32[(light & 0xFF00) + psource[11]]; - light += lightstep; - prowdest[12] = vid.colormap32[(light & 0xFF00) + psource[12]]; - light += lightstep; - prowdest[13] = vid.colormap32[(light & 0xFF00) + psource[13]]; - light += lightstep; - prowdest[14] = vid.colormap32[(light & 0xFF00) + psource[14]]; - light += lightstep; - prowdest[15] = vid.colormap32[(light & 0xFF00) + psource[15]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock32_mip1 (void) -{ - int k, v; - int lightstep, light; - unsigned int *prowdest; - - prowdest = (unsigned int *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 3; - lightrightstep = (r_lightptr[1] - lightright) >> 3; - - for (k = 0; k < 8; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 3; - - prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; - light += lightstep; - prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]]; - light += lightstep; - prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]]; - light += lightstep; - prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]]; - light += lightstep; - prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock32_mip2 (void) -{ - int k, v; - int lightstep, light; - unsigned int *prowdest; - - prowdest = (unsigned int *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 2; - lightrightstep = (r_lightptr[1] - lightright) >> 2; - - for (k = 0; k < 4; k++) - { - light = lightleft; - lightstep = (lightright - lightleft) >> 2; - - prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; - light += lightstep; - prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; - light += lightstep; - prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; - light += lightstep; - prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -static void -R_DrawSurfaceBlock32_mip3 (void) -{ - int v; - unsigned int *prowdest; - - prowdest = (unsigned int *) prowdestbase; - - for (v = 0; v < r_numvblocks; v++) - { - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 1; - lightrightstep = (r_lightptr[1] - lightright) >> 1; - - prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]]; - prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) & - 0xFF00) + psource[1]]; - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - - prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]]; - prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) & - 0xFF00) + psource[1]]; - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - - if (psource >= r_sourcemax) - psource -= r_stepback; - } -} - -/* void -R_DrawSurfaceBlock32 (void) +R_GenTile (msurface_t *psurf, void *pdest) { - int k, v; - int lightstep, light; - unsigned int *prowdest; - - prowdest = prowdestbase; - - for (v = 0; v < r_numvblocks; v++) { - - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> blockdivshift; - lightrightstep = (r_lightptr[1] - lightright) >> blockdivshift; - - for (k = 0; k < blocksize; k++) { - int b; - - lightstep = (lightright - lightleft) >> blockdivshift; - - light = lightleft; - - for (b = 0;b < blocksize;b++, light += lightstep) - prowdest[b] = vid.colormap32[(light & 0xFF00) + psource[b]]; - - psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; - prowdest += (surfrowbytes >> 2); - } - - if (psource >= r_sourcemax) - psource -= r_stepback; + if (psurf->flags & SURF_DRAWTURB) { + R_GenTurbTile (((byte *) psurf->texinfo->texture + + psurf->texinfo->texture->offsets[0]), pdest); + } else if (psurf->flags & SURF_DRAWSKY) { + R_GenSkyTile (pdest); + } else { + Sys_Error ("Unknown tile type"); } } -*/ diff --git a/libs/video/renderer/sw/vid_common_sw.c b/libs/video/renderer/sw/vid_common_sw.c index 554daeddb..f67a4ce8b 100644 --- a/libs/video/renderer/sw/vid_common_sw.c +++ b/libs/video/renderer/sw/vid_common_sw.c @@ -1,9 +1,9 @@ /* vid_common_sw.c - general video driver functions + Common software video driver functions - Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2001 Jeff Teunissen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -28,130 +28,11 @@ # include "config.h" #endif -#include "QF/cvar.h" +#include +#include + #include "QF/mathlib.h" -#include "QF/qargs.h" #include "QF/sys.h" -#include "QF/va.h" #include "QF/vid.h" -#include "compat.h" -#include "r_internal.h" #include "vid_internal.h" - -unsigned short d_8to16table[256]; - - -/* - VID_MakeColormap32 - - LordHavoc: makes a 32bit color*light table, RGBA order, no endian, - may need to be re-ordered to hardware at display time -*/ -static void -VID_MakeColormap32 (void *outcolormap, byte *pal) -{ - int c, l; - byte *out; - out = (byte *)&d_8to24table; - - /* - * Generates colors not affected by lighting, such as - * HUD pieces and general sprites (such as explosions) - */ - for (c = 0; c < 256; c++) { - *out++ = pal[c*3+2]; - *out++ = pal[c*3+1]; - *out++ = pal[c*3+0]; - *out++ = 255; - } - d_8to24table[255] = 0; // 255 is transparent - out = (byte *) outcolormap; - - /* - * Generates colors affected by lighting, such as the - * world and other models that give it life, like foes and pickups. - */ - for (l = 0;l < VID_GRADES;l++) - { - for (c = 0;c < vid.fullbright;c++) - { - out[(l*256+c)*4+0] = bound(0, (pal[c*3+2] * l) >> (VID_CBITS - 1), - 255); - out[(l*256+c)*4+1] = bound(0, (pal[c*3+1] * l) >> (VID_CBITS - 1), - 255); - out[(l*256+c)*4+2] = bound(0, (pal[c*3+0] * l) >> (VID_CBITS - 1), - 255); - out[(l*256+c)*4+3] = 255; - } - for (;c < 255;c++) - { - out[(l*256+c)*4+0] = pal[c*3+2]; - out[(l*256+c)*4+1] = pal[c*3+1]; - out[(l*256+c)*4+2] = pal[c*3+0]; - out[(l*256+c)*4+3] = 255; - } - out[(l*256+255)*4+0] = 0; - out[(l*256+255)*4+1] = 0; - out[(l*256+255)*4+2] = 0; - out[(l*256+255)*4+3] = 0; - } -} - -static unsigned short -lh24to16bit (int red, int green, int blue) -{ - red = bound(0, red, 255); - green = bound(0, green, 255); - blue = bound(0, blue, 255); - red >>= 3; - green >>= 2; - blue >>= 3; - red <<= 11; - green <<= 5; - return (unsigned short) (red | green | blue); -} - -/* - VID_MakeColormap16 - - LordHavoc: makes a 16bit color*light table, RGB order, native endian, - may need to be translated to hardware order at display time -*/ -static void -VID_MakeColormap16 (void *outcolormap, byte *pal) -{ - int c, l; - unsigned short *out; - out = (unsigned short *)&d_8to16table; - for (c = 0; c < 256; c++) - *out++ = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]); - d_8to16table[255] = 0; // 255 is transparent - out = (unsigned short *) outcolormap; - for (l = 0;l < VID_GRADES;l++) - { - for (c = 0;c < vid.fullbright;c++) - out[l*256+c] = lh24to16bit( - (pal[c*3+0] * l) >> (VID_CBITS - 1), - (pal[c*3+1] * l) >> (VID_CBITS - 1), - (pal[c*3+2] * l) >> (VID_CBITS - 1)); - for (;c < 255;c++) - out[l*256+c] = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]); - out[l*256+255] = 0; - } -} - -/* - VID_MakeColormaps - - LordHavoc: makes 8bit, 16bit, and 32bit colormaps and palettes -*/ -void -VID_MakeColormaps (void) -{ - vid.colormap16 = malloc (256*VID_GRADES * sizeof (unsigned short)); - vid.colormap32 = malloc (256*VID_GRADES * sizeof (unsigned int)); - SYS_CHECKMEM (vid.colormap16 && vid.colormap32); - VID_MakeColormap16(vid.colormap16, vid.palette); - VID_MakeColormap32(vid.colormap32, vid.palette); -} diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index 69e099b08..2303742e2 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -50,8 +50,6 @@ static win_palette_t st2d_8to32table[256]; static byte current_palette[768]; static int palette_changed; -static cvar_t *vid_bitdepth; - static LPDIRECTDRAW dd_Object; static HINSTANCE hInstDDraw; static LPDIRECTDRAWSURFACE dd_frontbuffer; @@ -476,27 +474,10 @@ Win_SW_Context (void) ctx->choose_visual = win_choose_visual; ctx->create_context = win_create_context; ctx->update = win_sw_update; -#if 0 //FIXME need to figure out 16 and 32 bit buffers - switch (vid_bitdepth->int_val) { - case 8: - ctx->pixbytes = 1; - break; - case 16: - ctx->pixbytes = 2; - break; - case 32: - ctx->pixbytes = 4; - break; - default: - Sys_Error ("X11_SW32_Context: unsupported bit depth"); - } -#endif return ctx; } void Win_SW_Init_Cvars (void) { - vid_bitdepth = Cvar_Get ("vid_bitdepth", "8", CVAR_ROM, NULL, "Sets " - "display bitdepth (supported modes: 8 16 32)"); } diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 84588fb32..12dba8e49 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -69,8 +69,6 @@ int XShmGetEventBase (Display *x); // for broken X11 headers static GC x_gc; -static cvar_t *vid_bitdepth; - static qboolean doShm; static XShmSegmentInfo x_shminfo[2]; @@ -648,27 +646,11 @@ X11_SW_Context (void) ctx->set_palette = x11_set_palette; ctx->choose_visual = x11_choose_visual; ctx->create_context = x11_create_context; - - switch (vid_bitdepth->int_val) { - case 8: - ctx->pixbytes = 1; - break; - case 16: - ctx->pixbytes = 2; - break; - case 32: - ctx->pixbytes = 4; - break; - default: - Sys_Error ("X11_SW32_Context: unsupported bit depth"); - } + ctx->update = x11_sw8_update; return ctx; } void X11_SW_Init_Cvars (void) { -// FIXME: vid_colorbpp in common GL setup, make consistent with sdl32 scheme - vid_bitdepth = Cvar_Get ("vid_bitdepth", "8", CVAR_ROM, NULL, "Sets " - "display bitdepth (supported modes: 8 16 32)"); } From 3414eb12a3451c507eca39ebdd1243ed78b27f90 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 22:51:21 +0900 Subject: [PATCH 2520/3664] [renderer] Move r_ambient and r_drawflat to client code It makes more sense for these cvars to be under client control via r_refdef. Completely disabled in qw, and currently ignored in nq. --- include/QF/render.h | 1 + include/r_cvar.h | 2 -- libs/video/renderer/r_cvar.c | 6 ------ libs/video/renderer/sw/d_edge.c | 2 +- libs/video/renderer/sw/sw_rmisc.c | 6 ------ nq/source/cl_main.c | 10 ++++++++++ 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index 9f7a0c690..c6977ff32 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -208,6 +208,7 @@ typedef struct { vec4f_t viewrotation; int ambientlight; + int drawflat; float fov_x, fov_y; } refdef_t; diff --git a/include/r_cvar.h b/include/r_cvar.h index c8b02f489..5b1090c1d 100644 --- a/include/r_cvar.h +++ b/include/r_cvar.h @@ -48,12 +48,10 @@ extern struct cvar_s *gl_vector_light; extern struct cvar_s *r_aliasstats; extern struct cvar_s *r_aliastransadj; extern struct cvar_s *r_aliastransbase; -extern struct cvar_s *r_ambient; extern struct cvar_s *r_clearcolor; extern struct cvar_s *r_dlight_lightmap; extern struct cvar_s *r_drawentities; extern struct cvar_s *r_drawexplosions; -extern struct cvar_s *r_drawflat; extern struct cvar_s *r_drawviewmodel; extern struct cvar_s *r_dspeeds; extern struct cvar_s *r_dynamic; diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index 94a9b88e8..6f5f16d64 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -53,13 +53,11 @@ cvar_t *d_mipscale; cvar_t *r_aliasstats; cvar_t *r_aliastransadj; cvar_t *r_aliastransbase; -cvar_t *r_ambient; cvar_t *r_clearcolor; cvar_t *r_dlight_lightmap; cvar_t *r_dlight_max; cvar_t *r_drawentities; cvar_t *r_drawexplosions; -cvar_t *r_drawflat; cvar_t *r_drawviewmodel; cvar_t *r_dspeeds; cvar_t *r_dynamic; @@ -230,8 +228,6 @@ R_Init_Cvars (void) r_aliastransbase = Cvar_Get ("r_aliastransbase", "200", CVAR_NONE, NULL, "Determines how much of an alias model is " "clipped away and how much is viewable"); - r_ambient = Cvar_Get ("r_ambient", "0", CVAR_NONE, NULL, - "Determines the ambient lighting for a level"); r_clearcolor = Cvar_Get ("r_clearcolor", "2", CVAR_NONE, NULL, "This sets the color for areas outside of the " "current map"); @@ -245,8 +241,6 @@ R_Init_Cvars (void) "everything but the world)"); r_drawexplosions = Cvar_Get ("r_drawexplosions", "1", CVAR_ARCHIVE, NULL, "Draw explosions."); - r_drawflat = Cvar_Get ("r_drawflat", "0", CVAR_NONE, NULL, - "Toggles the drawing of textures"); r_drawviewmodel = Cvar_Get ("r_drawviewmodel", "1", CVAR_ARCHIVE, NULL, "Toggles view model drawing (your weapons)"); r_dspeeds = Cvar_Get ("r_dspeeds", "0", CVAR_NONE, NULL, diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 59963dc3a..930d35707 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -158,7 +158,7 @@ D_DrawSurfaces (void) VectorCopy (transformed_modelorg, world_transformed_modelorg); // TODO: could preset a lot of this at mode set time - if (r_drawflat->int_val) { + if (r_refdef.drawflat) { for (s = &surfaces[1]; s < surface_p; s++) { if (!s->spans) continue; diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index 1dfa026f8..075c8b1b4 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -194,10 +194,6 @@ R_SetupFrame (void) vrect_t vrect; float w, h; - // don't allow cheats in multiplayer - Cvar_SetValue (r_ambient, 0); - Cvar_SetValue (r_drawflat, 0); - if (r_numsurfs->int_val) { if ((surface_p - surfaces) > r_maxsurfsseen) r_maxsurfsseen = surface_p - surfaces; @@ -217,8 +213,6 @@ R_SetupFrame (void) r_numallocatededges, r_maxedgesseen); } - r_refdef.ambientlight = max (r_ambient->value, 0); - R_CheckVariables (); R_AnimateLight (); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 44041949b..9c7fb5c2d 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -81,6 +81,9 @@ cvar_t *cl_nolerp; cvar_t *hud_fps; cvar_t *hud_time; +static cvar_t *r_ambient; +static cvar_t *r_drawflat; + int fps_count; client_static_t cls; @@ -182,6 +185,13 @@ CL_InitCvars (void) Cvar_MakeAlias ("show_fps", hud_fps); hud_time = Cvar_Get ("hud_time", "0", CVAR_ARCHIVE, NULL, "display the current time"); + + //FIXME not hooked up (don't do anything), but should not work in + //multi-player + r_ambient = Cvar_Get ("r_ambient", "0", CVAR_NONE, NULL, + "Determines the ambient lighting for a level"); + r_drawflat = Cvar_Get ("r_drawflat", "0", CVAR_NONE, NULL, + "Toggles the drawing of textures"); } void From 0cfff27cd059cecf15aa84270c81db930999f28c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Mar 2022 22:53:15 +0900 Subject: [PATCH 2521/3664] [sw] Move surf and edge stats printing to begin_frame Part of cleaning up SetupFrame --- libs/video/renderer/sw/sw_rmisc.c | 20 -------------------- libs/video/renderer/vid_render_sw.c | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index 075c8b1b4..b4d3f721a 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -190,29 +190,9 @@ R_SetUpFrustumIndexes (void) void R_SetupFrame (void) { - int edgecount; vrect_t vrect; float w, h; - if (r_numsurfs->int_val) { - if ((surface_p - surfaces) > r_maxsurfsseen) - r_maxsurfsseen = surface_p - surfaces; - - Sys_Printf ("Used %ld of %ld surfs; %d max\n", - (long)(surface_p - surfaces), - (long)(surf_max - surfaces), r_maxsurfsseen); - } - - if (r_numedges->int_val) { - edgecount = edge_p - r_edges; - - if (edgecount > r_maxedgesseen) - r_maxedgesseen = edgecount; - - Sys_Printf ("Used %d of %d edges; %d max\n", edgecount, - r_numallocatededges, r_maxedgesseen); - } - R_CheckVariables (); R_AnimateLight (); diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 9cb1872a3..75b5f9ab9 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -28,6 +28,8 @@ # include "config.h" #endif +#include "QF/cvar.h" + #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -109,6 +111,26 @@ sw_vid_render_shutdown (void) static void sw_begin_frame (void) { + if (r_numsurfs->int_val) { + int surfcount = surface_p - surfaces; + int max_surfs = surf_max - surfaces; + if (surfcount > r_maxsurfsseen) + r_maxsurfsseen = surfcount; + + Sys_Printf ("Used %d of %d surfs; %d max\n", + surfcount, max_surfs, r_maxsurfsseen); + } + + if (r_numedges->int_val) { + int edgecount = edge_p - r_edges; + + if (edgecount > r_maxedgesseen) + r_maxedgesseen = edgecount; + + Sys_Printf ("Used %d of %d edges; %d max\n", edgecount, + r_numallocatededges, r_maxedgesseen); + } + // do 3D refresh drawing, and then update the screen if (vr_data.scr_fullupdate++ < vid.numpages) { vr_data.scr_copyeverything = 1; From 2606564955363aabd753a253e434fbdc2dbca55f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Mar 2022 11:37:19 +0900 Subject: [PATCH 2522/3664] [sw] Remove some dead code --- libs/video/renderer/sw/sw_rmisc.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index b4d3f721a..6e59cdf7b 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -42,12 +42,6 @@ #include "vid_internal.h" #include "vid_sw.h" - -static void -R_CheckVariables (void) -{ -} - /* R_TimeRefresh_f @@ -193,24 +187,12 @@ R_SetupFrame (void) vrect_t vrect; float w, h; - R_CheckVariables (); - R_AnimateLight (); EntQueue_Clear (r_ent_queue); r_framecount++; numbtofpolys = 0; - // debugging -#if 0 - r_refdef.vieworg[0] = 80; - r_refdef.vieworg[1] = 64; - r_refdef.vieworg[2] = 40; - r_refdef.viewangles[0] = 0; - r_refdef.viewangles[1] = 46.763641357; - r_refdef.viewangles[2] = 0; -#endif - // build the transformation matrix for the given view angles VectorCopy (r_refdef.viewposition, modelorg); VectorCopy (r_refdef.viewposition, r_origin); From 3bdec495878f5c02c6a5f3924bfb969da7627e5e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Mar 2022 13:10:20 +0900 Subject: [PATCH 2523/3664] [sw] Remove r_origin entirely And clean up a lot of modelorg (a little trickier than it was for gl due to messy usage). --- include/d_iface.h | 4 ++-- include/quakeasm.h | 2 +- include/r_local.h | 12 +++++------ libs/video/renderer/r_part.c | 2 -- libs/video/renderer/sw/d_edge.c | 4 ++-- libs/video/renderer/sw/d_part.c | 2 +- libs/video/renderer/sw/d_parta.S | 8 ++++---- libs/video/renderer/sw/d_sprite.c | 10 +++++----- libs/video/renderer/sw/sw_ralias.c | 16 +++++++-------- libs/video/renderer/sw/sw_rbsp.c | 6 +++--- libs/video/renderer/sw/sw_rdraw.c | 2 -- libs/video/renderer/sw/sw_riqm.c | 12 +++++------ libs/video/renderer/sw/sw_rmain.c | 31 +++++++++++++++-------------- libs/video/renderer/sw/sw_rmisc.c | 22 ++++++-------------- libs/video/renderer/sw/sw_rpart.c | 3 +++ libs/video/renderer/sw/sw_rsprite.c | 22 ++++++++++---------- 16 files changed, 74 insertions(+), 84 deletions(-) diff --git a/include/d_iface.h b/include/d_iface.h index 3587a55da..279a10baf 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -140,7 +140,7 @@ extern int d_con_indirect; // if 0, Quake will draw console directly // draw console via D_DrawRect. Must be // defined by driver -extern vec3_t r_pright, r_pup, r_ppn; +extern vec3_t r_pright, r_pup, r_ppn, r_porigin; void D_Aff8Patch (void *pcolormap); @@ -151,7 +151,7 @@ void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts); void D_PolysetSetEdgeTable (void); void D_DrawParticle (particle_t *pparticle); void D_DrawPoly (void); -void D_DrawSprite (void); +void D_DrawSprite (const vec3_t relvieworg); void D_DrawSurfaces (void); void D_DrawZPoint (void); void D_Init (void); diff --git a/include/quakeasm.h b/include/quakeasm.h index 8192e05f5..f9c663aae 100644 --- a/include/quakeasm.h +++ b/include/quakeasm.h @@ -85,10 +85,10 @@ .extern C(lightleft) .extern C(blockdivshift) .extern C(lightleftstep) - .extern C(r_origin) .extern C(r_ppn) .extern C(r_pup) .extern C(r_pright) + .extern C(r_porigin) .extern C(ycenter) .extern C(xcenter) .extern C(d_vrectbottom_particle) diff --git a/include/r_local.h b/include/r_local.h index 95302ad49..16adee2bc 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -117,7 +117,6 @@ void R_RenderWorld (void); extern plane_t screenedge[4]; -extern vec3_t r_origin; extern vec3_t r_entorigin; extern int r_visframecount; @@ -144,11 +143,10 @@ void R_SetFrustum (void); void R_SpriteBegin (void); void R_SpriteEnd (void); -void R_DrawSprite (void); +void R_DrawSprite (const vec3_t relvieworg); void R_RenderFace (msurface_t *fa, int clipflags); void R_RenderPoly (msurface_t *fa, int clipflags); void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf); -void R_TransformPlane (plane_t *p, float *normal, float *dist); void R_TransformFrustum (void); void R_SetSkyFrame (void); void R_DrawSurfaceBlock (void); @@ -162,8 +160,8 @@ void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel); void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); surf_t *R_GetSurf (void); void R_AliasClipAndProjectFinalVert (finalvert_t *fv, auxvert_t *av); -void R_AliasDrawModel (alight_t *plighting); -void R_IQMDrawModel (alight_t *plighting); +void R_AliasDrawModel (const vec3_t relvieworg, alight_t *plighting); +void R_IQMDrawModel (const vec3_t relvieworg, alight_t *plighting); maliasskindesc_t *R_AliasGetSkindesc (animation_t *animation, int skinnum, aliashdr_t *hdr); maliasframedesc_t *R_AliasGetFramedesc (animation_t *animation, aliashdr_t *hdr); float R_AliasGetLerpedFrames (animation_t *animation, aliashdr_t *hdr); @@ -239,7 +237,7 @@ extern auxvert_t *pauxverts; extern float ziscale; extern float aliastransform[3][4]; -qboolean R_AliasCheckBBox (void); +qboolean R_AliasCheckBBox (const vec3_t relvieworg); // turbulence stuff ======================================= @@ -330,7 +328,7 @@ void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out); void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out); -void R_AliasSetUpTransform (int trivial_accept); +void R_AliasSetUpTransform (const vec3_t relvieworg, int trivial_accept); void R_AliasTransformVector (vec3_t in, vec3_t out); void R_AliasTransformFinalVert (finalvert_t *fv, trivertx_t *pverts, stvert_t *pstverts); diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index 5a5c03057..9d43dead3 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -38,8 +38,6 @@ psystem_t r_psystem; //FIXME singleton -vec3_t r_pright, r_pup, r_ppn; - /* R_MaxParticlesCheck diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 930d35707..a4ddcfb5d 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -209,7 +209,7 @@ D_DrawSurfaces (void) // TODO: store once at start of frame currententity = s->entity; // FIXME: make this passed in // to R_RotateBmodel () - VectorSubtract (r_origin, + VectorSubtract (r_refdef.viewposition, Transform_GetWorldPosition (currententity->transform), local_modelorg); TransformVector (local_modelorg, transformed_modelorg); @@ -243,7 +243,7 @@ D_DrawSurfaces (void) // TODO: store once at start of frame currententity = s->entity; // FIXME: make this passed in // to R_RotateBmodel () - VectorSubtract (r_origin, + VectorSubtract (r_refdef.viewposition, Transform_GetWorldPosition (currententity->transform), local_modelorg); TransformVector (local_modelorg, transformed_modelorg); diff --git a/libs/video/renderer/sw/d_part.c b/libs/video/renderer/sw/d_part.c index b8b5b1c82..82371ce28 100644 --- a/libs/video/renderer/sw/d_part.c +++ b/libs/video/renderer/sw/d_part.c @@ -47,7 +47,7 @@ D_DrawParticle (particle_t *pparticle) int i, izi, pix, count, u, v; // transform point - VectorSubtract (pparticle->pos, r_origin, local); + VectorSubtract (pparticle->pos, r_porigin, local); transformed[0] = DotProduct (local, r_pright); transformed[1] = DotProduct (local, r_pup); diff --git a/libs/video/renderer/sw/d_parta.S b/libs/video/renderer/sw/d_parta.S index a7b9a8543..b35597dcd 100644 --- a/libs/video/renderer/sw/d_parta.S +++ b/libs/video/renderer/sw/d_parta.S @@ -66,13 +66,13 @@ C(D_DrawParticle): // FIXME: better FP overlap in general here // transform point -// VectorSubtract (p->org, r_origin, local); - flds C(r_origin) +// VectorSubtract (p->org, r_porigin, local); + flds C(r_porigin) fsubrs pt_pos(%edi) flds pt_pos+4(%edi) - fsubs C(r_origin)+4 + fsubs C(r_porigin)+4 flds pt_pos+8(%edi) - fsubs C(r_origin)+8 + fsubs C(r_porigin)+8 fxch %st(2) // local[0] | local[1] | local[2] // transformed[2] = DotProduct(local, r_ppn); diff --git a/libs/video/renderer/sw/d_sprite.c b/libs/video/renderer/sw/d_sprite.c index b4f35202f..7f0b20ce6 100644 --- a/libs/video/renderer/sw/d_sprite.c +++ b/libs/video/renderer/sw/d_sprite.c @@ -323,7 +323,7 @@ D_SpriteScanRightEdge (void) } static void -D_SpriteCalculateGradients (void) +D_SpriteCalculateGradients (const vec3_t relvieworg) { vec3_t p_normal, p_saxis, p_taxis, p_temp1; float distinv; @@ -333,7 +333,7 @@ D_SpriteCalculateGradients (void) TransformVector (r_spritedesc.vup, p_taxis); VectorNegate (p_taxis, p_taxis); - distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn)); + distinv = 1.0 / (-DotProduct (relvieworg, r_spritedesc.vpn)); d_sdivzstepu = p_saxis[0] * xscaleinv; d_tdivzstepu = p_taxis[0] * xscaleinv; @@ -351,7 +351,7 @@ D_SpriteCalculateGradients (void) d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv; - TransformVector (modelorg, p_temp1); + TransformVector (relvieworg, p_temp1); sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - (-(cachewidth >> 1) << 16); @@ -364,7 +364,7 @@ D_SpriteCalculateGradients (void) } void -D_DrawSprite (void) +D_DrawSprite (const vec3_t relvieworg) { int i, nump; float ymin, ymax; @@ -409,7 +409,7 @@ D_DrawSprite (void) pverts = r_spritedesc.pverts; pverts[nump] = pverts[0]; - D_SpriteCalculateGradients (); + D_SpriteCalculateGradients (relvieworg); D_SpriteScanLeftEdge (); D_SpriteScanRightEdge (); D_SpriteDrawSpans (sprite_spans); diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 1899e2a47..581d926a0 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -83,7 +83,7 @@ static aedge_t aedges[12] = { }; qboolean -R_AliasCheckBBox (void) +R_AliasCheckBBox (const vec3_t relvieworg) { int i, flags, frame, numv; aliashdr_t *pahdr; @@ -102,7 +102,7 @@ R_AliasCheckBBox (void) pahdr = Cache_Get (&pmodel->cache); pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model); - R_AliasSetUpTransform (0); + R_AliasSetUpTransform (relvieworg, 0); // construct the base bounding box for this frame frame = currententity->animation.frame; @@ -351,7 +351,7 @@ R_AliasPreparePoints (void) } void -R_AliasSetUpTransform (int trivial_accept) +R_AliasSetUpTransform (const vec3_t relvieworg, int trivial_accept) { int i; float rotationmatrix[3][4], t2matrix[3][4]; @@ -380,9 +380,9 @@ R_AliasSetUpTransform (int trivial_accept) t2matrix[i][2] = alias_up[i]; } - t2matrix[0][3] = -modelorg[0]; - t2matrix[1][3] = -modelorg[1]; - t2matrix[2][3] = -modelorg[2]; + t2matrix[0][3] = -relvieworg[0]; + t2matrix[1][3] = -relvieworg[1]; + t2matrix[2][3] = -relvieworg[2]; // FIXME: can do more efficiently than full concatenation R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); @@ -621,7 +621,7 @@ R_AliasSetupFrame (entity_t *ent) void -R_AliasDrawModel (alight_t *plighting) +R_AliasDrawModel (const vec3_t relvieworg, alight_t *plighting) { entity_t *ent = currententity; int size; @@ -646,7 +646,7 @@ R_AliasDrawModel (alight_t *plighting) pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1]; R_AliasSetupSkin (ent); - R_AliasSetUpTransform (ent->visibility.trivial_accept); + R_AliasSetUpTransform (relvieworg, ent->visibility.trivial_accept); R_AliasSetupLighting (plighting); R_AliasSetupFrame (ent); diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 3d726766c..ac9028209 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -358,10 +358,11 @@ get_side (mnode_t *node) { // find which side of the node we are on plane_t *plane = node->plane; + vec4f_t org = r_refdef.viewposition; if (plane->type < 3) - return (modelorg[plane->type] - plane->dist) < 0; - return (DotProduct (modelorg, plane->normal) - plane->dist) < 0; + return (org[plane->type] - plane->dist) < 0; + return (DotProduct (org, plane->normal) - plane->dist) < 0; } static void @@ -515,7 +516,6 @@ R_RenderWorld (void) pbtofpolys = btofpolys; currententity = &r_worldentity; - VectorCopy (r_origin, modelorg); brush = ¤tentity->renderer.model->brush; r_pcurrentvertbase = brush->vertexes; diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index 67c298187..b466d1b61 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -505,7 +505,6 @@ R_RenderFace (msurface_t *fa, int clipflags) surface_p->d_ziorigin = p_normal[2] * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; -//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); surface_p++; } @@ -605,7 +604,6 @@ R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) surface_p->d_ziorigin = p_normal[2] * distinv - xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; -//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); surface_p++; } diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index d2ed9e79c..ee4016f8f 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -242,7 +242,7 @@ R_IQMSetupLighting (entity_t *ent, alight_t *plighting) } static void -R_IQMSetUpTransform (int trivial_accept) +R_IQMSetUpTransform (const vec3_t relvieworg, int trivial_accept) { int i; float rotationmatrix[3][4]; @@ -263,9 +263,9 @@ R_IQMSetUpTransform (int trivial_accept) rotationmatrix[i][2] = up[i]; } - rotationmatrix[0][3] = -modelorg[0]; - rotationmatrix[1][3] = -modelorg[1]; - rotationmatrix[2][3] = -modelorg[2]; + rotationmatrix[0][3] = -relvieworg[0]; + rotationmatrix[1][3] = -relvieworg[1]; + rotationmatrix[2][3] = -relvieworg[2]; // TODO: should be global, set when vright, etc., set VectorCopy (vright, viewmatrix[0]); @@ -297,7 +297,7 @@ R_IQMSetUpTransform (int trivial_accept) } void -R_IQMDrawModel (alight_t *plighting) +R_IQMDrawModel (const vec3_t relvieworg, alight_t *plighting) { entity_t *ent = currententity; model_t *model = ent->renderer.model; @@ -320,7 +320,7 @@ R_IQMDrawModel (alight_t *plighting) (((intptr_t) &pfinalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); pauxverts = (auxvert_t *) &pfinalverts[iqm->num_verts + 1]; - R_IQMSetUpTransform (ent->visibility.trivial_accept); + R_IQMSetUpTransform (relvieworg, ent->visibility.trivial_accept); R_IQMSetupLighting (ent, plighting); r_affinetridesc.drawtype = (ent->visibility.trivial_accept == 3) && diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 841036858..a96803029 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -343,8 +343,9 @@ R_ViewChanged (void) static inline void draw_sprite_entity (entity_t *ent) { - VectorSubtract (r_origin, r_entorigin, modelorg); - R_DrawSprite (); + vec3_t org; + VectorSubtract (r_refdef.viewposition, r_entorigin, org); + R_DrawSprite (org); } static inline void @@ -389,22 +390,24 @@ setup_lighting (alight_t *lighting) static inline void draw_alias_entity (entity_t *ent) { - VectorSubtract (r_origin, r_entorigin, modelorg); + vec3_t org; + VectorSubtract (r_refdef.viewposition, r_entorigin, org); // see if the bounding box lets us trivially reject, also // sets trivial accept status currententity->visibility.trivial_accept = 0; //FIXME - if (R_AliasCheckBBox ()) { + if (R_AliasCheckBBox (org)) { alight_t lighting; setup_lighting (&lighting); - R_AliasDrawModel (&lighting); + R_AliasDrawModel (org, &lighting); } } static inline void draw_iqm_entity (entity_t *ent) { - VectorSubtract (r_origin, r_entorigin, modelorg); + vec3_t org; + VectorSubtract (r_refdef.viewposition, r_entorigin, org); // see if the bounding box lets us trivially reject, also // sets trivial accept status @@ -412,7 +415,7 @@ draw_iqm_entity (entity_t *ent) alight_t lighting; setup_lighting (&lighting); - R_IQMDrawModel (&lighting); + R_IQMDrawModel (org, &lighting); } static void @@ -461,7 +464,6 @@ R_DrawViewModel (void) VectorCopy (Transform_GetWorldPosition (currententity->transform), r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); VectorCopy (vup, viewlightvec); VectorNegate (viewlightvec, viewlightvec); @@ -499,7 +501,9 @@ R_DrawViewModel (void) r_viewlighting.plightvec = lightvec; - R_AliasDrawModel (&r_viewlighting); + vec3_t org; + VectorSubtract (r_refdef.viewposition, r_entorigin, org); + R_AliasDrawModel (org, &r_viewlighting); } static int @@ -558,11 +562,10 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) } static void -R_DrawBEntitiesOnList (void) +R_DrawBrushEntitiesOnList (void) { int j, clipflags; unsigned int k; - vec3_t oldorigin; vec3_t origin; model_t *clmodel; float minmaxs[6]; @@ -570,7 +573,6 @@ R_DrawBEntitiesOnList (void) if (!r_drawentities->int_val) return; - VectorCopy (modelorg, oldorigin); insubmodel = true; for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { @@ -592,7 +594,7 @@ R_DrawBEntitiesOnList (void) if (clipflags != BMODEL_FULLY_CLIPPED) { mod_brush_t *brush = &clmodel->brush; VectorCopy (origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); + VectorSubtract (r_refdef.viewposition, r_entorigin, modelorg); // FIXME: is this needed? VectorCopy (modelorg, r_worldmodelorg); @@ -648,7 +650,6 @@ R_DrawBEntitiesOnList (void) VectorCopy (base_vup, vup); VectorCopy (base_vright, vright); VectorCopy (base_modelorg, modelorg); - VectorCopy (oldorigin, modelorg); R_TransformFrustum (); } } @@ -723,7 +724,7 @@ R_EdgeDrawing (void) db_time1 = rw_time2; } - R_DrawBEntitiesOnList (); + R_DrawBrushEntitiesOnList (); if (r_dspeeds->int_val) { db_time2 = Sys_DoubleTime (); diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index 6e59cdf7b..9c5d05054 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -146,17 +146,6 @@ TransformVector (const vec3_t in, vec3_t out) } #endif -void -R_TransformPlane (plane_t *p, float *normal, float *dist) -{ - float d; - - d = DotProduct (r_origin, p->normal); - *dist = p->dist - d; -// TODO: when we have rotating entities, this will need to use the view matrix - TransformVector (p->normal, normal); -} - static void R_SetUpFrustumIndexes (void) { @@ -195,15 +184,16 @@ R_SetupFrame (void) // build the transformation matrix for the given view angles VectorCopy (r_refdef.viewposition, modelorg); - VectorCopy (r_refdef.viewposition, r_origin); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, -1, 0, 0 }), vright); - VectorCopy (qvmulf (r_refdef.viewrotation, (vec4f_t) { 0, 0, 1, 0 }), vup); + vec4f_t position = r_refdef.viewposition; + vec4f_t rotation = r_refdef.viewrotation; + VectorCopy (qvmulf (rotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); + VectorCopy (qvmulf (rotation, (vec4f_t) { 0, -1, 0, 0 }), vright); + VectorCopy (qvmulf (rotation, (vec4f_t) { 0, 0, 1, 0 }), vup); R_SetFrustum (); // current viewleaf - r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.renderer.model); + r_viewleaf = Mod_PointInLeaf (&position[0], r_worldentity.renderer.model); r_dowarpold = r_dowarp; r_dowarp = r_waterwarp->int_val && (r_viewleaf->contents <= diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index a76d2d105..b64f848b3 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -49,12 +49,15 @@ #include "compat.h" #include "r_internal.h" +vec3_t r_pright, r_pup, r_ppn, r_porigin; + void R_DrawParticles (void) { VectorScale (vright, xscaleshrink, r_pright); VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); + VectorCopy (r_refdef.viewposition, r_porigin); R_RunParticles (vr_data.frametime); diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index ca2ee5d9b..0518a24af 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -52,16 +52,17 @@ spritedesc_t r_spritedesc; static void -R_RotateSprite (float beamlength) +R_RotateSprite (const vec3_t relvieworg, float beamlength, vec3_t org) { vec3_t vec; + VectorCopy (relvieworg, org); if (beamlength == 0.0) return; VectorScale (r_spritedesc.vpn, -beamlength, vec); VectorAdd (r_entorigin, vec, r_entorigin); - VectorSubtract (modelorg, vec, modelorg); + VectorSubtract (relvieworg, vec, org); } @@ -147,7 +148,7 @@ R_ClipSpriteFace (int nump, clipplane_t *pclipplane) static void -R_SetupAndDrawSprite (void) +R_SetupAndDrawSprite (const vec3_t relvieworg) { int i, nump; float dot, scale, *pv; @@ -155,7 +156,7 @@ R_SetupAndDrawSprite (void) vec3_t left, up, right, down, transformed, local; emitpoint_t outverts[MAXWORKINGVERTS + 1], *pout; - dot = DotProduct (r_spritedesc.vpn, modelorg); + dot = DotProduct (r_spritedesc.vpn, relvieworg); // backface cull if (dot >= 0) @@ -210,7 +211,7 @@ R_SetupAndDrawSprite (void) r_spritedesc.nearzi = -999999; for (i = 0; i < nump; i++) { - VectorSubtract (pv, r_origin, local); + VectorSubtract (pv, r_refdef.viewposition, local); TransformVector (local, transformed); if (transformed[2] < NEAR_CLIP) @@ -236,11 +237,11 @@ R_SetupAndDrawSprite (void) // draw it r_spritedesc.nump = nump; r_spritedesc.pverts = outverts; - D_DrawSprite (); + D_DrawSprite (relvieworg); } void -R_DrawSprite (void) +R_DrawSprite (const vec3_t relvieworg) { msprite_t *sprite = currententity->renderer.model->cache.data; @@ -250,7 +251,7 @@ R_DrawSprite (void) sprite_width = r_spritedesc.pspriteframe->width; sprite_height = r_spritedesc.pspriteframe->height; - if (!R_BillboardFrame (currententity, sprite->type, modelorg, + if (!R_BillboardFrame (currententity, sprite->type, relvieworg, r_spritedesc.vup, r_spritedesc.vright, r_spritedesc.vpn)) { @@ -258,7 +259,8 @@ R_DrawSprite (void) return; } - R_RotateSprite (sprite->beamlength); + vec3_t org; + R_RotateSprite (relvieworg, sprite->beamlength, org); - R_SetupAndDrawSprite (); + R_SetupAndDrawSprite (org); } From 64666cfa5b47903f2f38a34369c523c8f47ef1b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Mar 2022 15:07:38 +0900 Subject: [PATCH 2524/3664] [renderer] Clean up most uses of currententity Just some brush model related code in the software renderer remaining. --- include/QF/Vulkan/qf_lightmap.h | 3 +- include/r_local.h | 9 ++-- libs/video/renderer/sw/sw_ralias.c | 35 +++++++------- libs/video/renderer/sw/sw_riqm.c | 15 +++--- libs/video/renderer/sw/sw_rmain.c | 48 +++++++------------- libs/video/renderer/sw/sw_rsprite.c | 12 +++-- libs/video/renderer/vulkan/vulkan_lightmap.c | 14 +++--- 7 files changed, 63 insertions(+), 73 deletions(-) diff --git a/include/QF/Vulkan/qf_lightmap.h b/include/QF/Vulkan/qf_lightmap.h index eaca4e35f..d9371dbaa 100644 --- a/include/QF/Vulkan/qf_lightmap.h +++ b/include/QF/Vulkan/qf_lightmap.h @@ -38,11 +38,12 @@ struct vulkan_ctx_s; struct model_s; struct mod_brush_s; struct msurface_s; +struct transform_s; void Vulkan_lightmap_init (struct vulkan_ctx_s *ctx); void Vulkan_BuildLightmaps (struct model_s **models, int num_models, struct vulkan_ctx_s *ctx); void Vulkan_CalcLightmaps (struct vulkan_ctx_s *ctx); -void Vulkan_BuildLightMap (struct mod_brush_s *brush, struct msurface_s *surf, struct vulkan_ctx_s *ctx); +void Vulkan_BuildLightMap (const struct transform_s *transform, struct mod_brush_s *brush, struct msurface_s *surf, struct vulkan_ctx_s *ctx); VkImageView Vulkan_LightmapImageView (struct vulkan_ctx_s *ctx) __attribute__((pure)); void Vulkan_FlushLightmaps (struct vulkan_ctx_s *ctx); diff --git a/include/r_local.h b/include/r_local.h index 16adee2bc..6efd16c3d 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -143,7 +143,7 @@ void R_SetFrustum (void); void R_SpriteBegin (void); void R_SpriteEnd (void); -void R_DrawSprite (const vec3_t relvieworg); +void R_DrawSprite (entity_t *ent); void R_RenderFace (msurface_t *fa, int clipflags); void R_RenderPoly (msurface_t *fa, int clipflags); void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf); @@ -160,8 +160,8 @@ void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel); void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); surf_t *R_GetSurf (void); void R_AliasClipAndProjectFinalVert (finalvert_t *fv, auxvert_t *av); -void R_AliasDrawModel (const vec3_t relvieworg, alight_t *plighting); -void R_IQMDrawModel (const vec3_t relvieworg, alight_t *plighting); +void R_AliasDrawModel (entity_t *ent, alight_t *plighting); +void R_IQMDrawModel (entity_t *ent, alight_t *plighting); maliasskindesc_t *R_AliasGetSkindesc (animation_t *animation, int skinnum, aliashdr_t *hdr); maliasframedesc_t *R_AliasGetFramedesc (animation_t *animation, aliashdr_t *hdr); float R_AliasGetLerpedFrames (animation_t *animation, aliashdr_t *hdr); @@ -237,7 +237,7 @@ extern auxvert_t *pauxverts; extern float ziscale; extern float aliastransform[3][4]; -qboolean R_AliasCheckBBox (const vec3_t relvieworg); +qboolean R_AliasCheckBBox (entity_t *ent); // turbulence stuff ======================================= @@ -328,7 +328,6 @@ void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out); void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out); -void R_AliasSetUpTransform (const vec3_t relvieworg, int trivial_accept); void R_AliasTransformVector (vec3_t in, vec3_t out); void R_AliasTransformFinalVert (finalvert_t *fv, trivertx_t *pverts, stvert_t *pstverts); diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 581d926a0..837d616a4 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -82,8 +82,10 @@ static aedge_t aedges[12] = { {0, 5}, {1, 4}, {2, 7}, {3, 6} }; +static void R_AliasSetUpTransform (entity_t *ent, int trivial_accept); + qboolean -R_AliasCheckBBox (const vec3_t relvieworg) +R_AliasCheckBBox (entity_t *ent) { int i, flags, frame, numv; aliashdr_t *pahdr; @@ -96,16 +98,16 @@ R_AliasCheckBBox (const vec3_t relvieworg) int minz; // expand, rotate, and translate points into worldspace - currententity->visibility.trivial_accept = 0; - pmodel = currententity->renderer.model; + ent->visibility.trivial_accept = 0; + pmodel = ent->renderer.model; if (!(pahdr = pmodel->aliashdr)) pahdr = Cache_Get (&pmodel->cache); pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model); - R_AliasSetUpTransform (relvieworg, 0); + R_AliasSetUpTransform (ent, 0); // construct the base bounding box for this frame - frame = currententity->animation.frame; + frame = ent->animation.frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { Sys_MaskPrintf (SYS_dev, "No such frame %d %s\n", frame, pmodel->path); @@ -220,11 +222,11 @@ R_AliasCheckBBox (const vec3_t relvieworg) return false; // trivial reject off one side } - currententity->visibility.trivial_accept = !anyclip & !zclipped; + ent->visibility.trivial_accept = !anyclip & !zclipped; - if (currententity->visibility.trivial_accept) { + if (ent->visibility.trivial_accept) { if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) { - currententity->visibility.trivial_accept |= 2; + ent->visibility.trivial_accept |= 2; } } @@ -350,8 +352,8 @@ R_AliasPreparePoints (void) } } -void -R_AliasSetUpTransform (const vec3_t relvieworg, int trivial_accept) +static void +R_AliasSetUpTransform (entity_t *ent, int trivial_accept) { int i; float rotationmatrix[3][4], t2matrix[3][4]; @@ -359,7 +361,7 @@ R_AliasSetUpTransform (const vec3_t relvieworg, int trivial_accept) static float viewmatrix[3][4]; mat4f_t mat; - Transform_GetWorldMatrix (currententity->transform, mat); + Transform_GetWorldMatrix (ent->transform, mat); VectorCopy (mat[0], alias_forward); VectorNegate (mat[1], alias_right); VectorCopy (mat[2], alias_up); @@ -380,9 +382,9 @@ R_AliasSetUpTransform (const vec3_t relvieworg, int trivial_accept) t2matrix[i][2] = alias_up[i]; } - t2matrix[0][3] = -relvieworg[0]; - t2matrix[1][3] = -relvieworg[1]; - t2matrix[2][3] = -relvieworg[2]; + t2matrix[0][3] = r_entorigin[0] - r_refdef.viewposition[0]; + t2matrix[1][3] = r_entorigin[1] - r_refdef.viewposition[1]; + t2matrix[2][3] = r_entorigin[2] - r_refdef.viewposition[2]; // FIXME: can do more efficiently than full concatenation R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); @@ -621,9 +623,8 @@ R_AliasSetupFrame (entity_t *ent) void -R_AliasDrawModel (const vec3_t relvieworg, alight_t *plighting) +R_AliasDrawModel (entity_t *ent, alight_t *plighting) { - entity_t *ent = currententity; int size; finalvert_t *finalverts; @@ -646,7 +647,7 @@ R_AliasDrawModel (const vec3_t relvieworg, alight_t *plighting) pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1]; R_AliasSetupSkin (ent); - R_AliasSetUpTransform (relvieworg, ent->visibility.trivial_accept); + R_AliasSetUpTransform (ent, ent->visibility.trivial_accept); R_AliasSetupLighting (plighting); R_AliasSetupFrame (ent); diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index ee4016f8f..ad41ab405 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -242,7 +242,7 @@ R_IQMSetupLighting (entity_t *ent, alight_t *plighting) } static void -R_IQMSetUpTransform (const vec3_t relvieworg, int trivial_accept) +R_IQMSetUpTransform (entity_t *ent, int trivial_accept) { int i; float rotationmatrix[3][4]; @@ -250,7 +250,7 @@ R_IQMSetUpTransform (const vec3_t relvieworg, int trivial_accept) vec3_t forward, left, up; mat4f_t mat; - Transform_GetWorldMatrix (currententity->transform, mat); + Transform_GetWorldMatrix (ent->transform, mat); VectorCopy (mat[0], forward); VectorCopy (mat[1], left); VectorCopy (mat[2], up); @@ -263,9 +263,9 @@ R_IQMSetUpTransform (const vec3_t relvieworg, int trivial_accept) rotationmatrix[i][2] = up[i]; } - rotationmatrix[0][3] = -relvieworg[0]; - rotationmatrix[1][3] = -relvieworg[1]; - rotationmatrix[2][3] = -relvieworg[2]; + rotationmatrix[0][3] = r_entorigin[0] - r_refdef.viewposition[0]; + rotationmatrix[1][3] = r_entorigin[1] - r_refdef.viewposition[1]; + rotationmatrix[2][3] = r_entorigin[2] - r_refdef.viewposition[2]; // TODO: should be global, set when vright, etc., set VectorCopy (vright, viewmatrix[0]); @@ -297,9 +297,8 @@ R_IQMSetUpTransform (const vec3_t relvieworg, int trivial_accept) } void -R_IQMDrawModel (const vec3_t relvieworg, alight_t *plighting) +R_IQMDrawModel (entity_t *ent, alight_t *plighting) { - entity_t *ent = currententity; model_t *model = ent->renderer.model; iqm_t *iqm = (iqm_t *) model->aliashdr; swiqm_t *sw = (swiqm_t *) iqm->extra_data; @@ -320,7 +319,7 @@ R_IQMDrawModel (const vec3_t relvieworg, alight_t *plighting) (((intptr_t) &pfinalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); pauxverts = (auxvert_t *) &pfinalverts[iqm->num_verts + 1]; - R_IQMSetUpTransform (relvieworg, ent->visibility.trivial_accept); + R_IQMSetUpTransform (ent, ent->visibility.trivial_accept); R_IQMSetupLighting (ent, plighting); r_affinetridesc.drawtype = (ent->visibility.trivial_accept == 3) && diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index a96803029..c6b7ddf1f 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -343,13 +343,11 @@ R_ViewChanged (void) static inline void draw_sprite_entity (entity_t *ent) { - vec3_t org; - VectorSubtract (r_refdef.viewposition, r_entorigin, org); - R_DrawSprite (org); + R_DrawSprite (ent); } static inline void -setup_lighting (alight_t *lighting) +setup_lighting (entity_t *ent, alight_t *lighting) { float minlight = 0; int j; @@ -358,8 +356,7 @@ setup_lighting (alight_t *lighting) float add; float lightvec[3] = { -1, 0, 0 }; - minlight = max (currententity->renderer.model->min_light, - currententity->renderer.min_light); + minlight = max (ent->renderer.model->min_light, ent->renderer.min_light); // 128 instead of 255 due to clamping below j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin), @@ -390,32 +387,26 @@ setup_lighting (alight_t *lighting) static inline void draw_alias_entity (entity_t *ent) { - vec3_t org; - VectorSubtract (r_refdef.viewposition, r_entorigin, org); - // see if the bounding box lets us trivially reject, also // sets trivial accept status - currententity->visibility.trivial_accept = 0; //FIXME - if (R_AliasCheckBBox (org)) { + ent->visibility.trivial_accept = 0; //FIXME + if (R_AliasCheckBBox (ent)) { alight_t lighting; - setup_lighting (&lighting); - R_AliasDrawModel (org, &lighting); + setup_lighting (ent, &lighting); + R_AliasDrawModel (ent, &lighting); } } static inline void draw_iqm_entity (entity_t *ent) { - vec3_t org; - VectorSubtract (r_refdef.viewposition, r_entorigin, org); - // see if the bounding box lets us trivially reject, also // sets trivial accept status - currententity->visibility.trivial_accept = 0; //FIXME + ent->visibility.trivial_accept = 0; //FIXME alight_t lighting; - setup_lighting (&lighting); - R_IQMDrawModel (org, &lighting); + setup_lighting (ent, &lighting); + R_IQMDrawModel (ent, &lighting); } static void @@ -431,7 +422,6 @@ R_DrawEntitiesOnList (void) entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \ VectorCopy (Transform_GetWorldPosition (ent->transform), \ r_entorigin); \ - currententity = ent; \ draw_##type_name##_entity (ent); \ } \ } while (0) @@ -452,24 +442,24 @@ R_DrawViewModel (void) float add; float minlight; dlight_t *dl; + entity_t *viewent; if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val || !r_drawentities->int_val) return; - currententity = vr_data.view_model; - if (!currententity->renderer.model) + viewent = vr_data.view_model; + if (!viewent->renderer.model) return; - VectorCopy (Transform_GetWorldPosition (currententity->transform), - r_entorigin); + VectorCopy (Transform_GetWorldPosition (viewent->transform), r_entorigin); VectorCopy (vup, viewlightvec); VectorNegate (viewlightvec, viewlightvec); - minlight = max (currententity->renderer.min_light, - currententity->renderer.model->min_light); + minlight = max (viewent->renderer.min_light, + viewent->renderer.model->min_light); j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin), minlight * 128); @@ -501,9 +491,7 @@ R_DrawViewModel (void) r_viewlighting.plightvec = lightvec; - vec3_t org; - VectorSubtract (r_refdef.viewposition, r_entorigin, org); - R_AliasDrawModel (org, &r_viewlighting); + R_AliasDrawModel (viewent, &r_viewlighting); } static int @@ -596,8 +584,6 @@ R_DrawBrushEntitiesOnList (void) VectorCopy (origin, r_entorigin); VectorSubtract (r_refdef.viewposition, r_entorigin, modelorg); - // FIXME: is this needed? - VectorCopy (modelorg, r_worldmodelorg); r_pcurrentvertbase = brush->vertexes; // FIXME: stop transforming twice diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 0518a24af..a1cdf0663 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -241,17 +241,19 @@ R_SetupAndDrawSprite (const vec3_t relvieworg) } void -R_DrawSprite (const vec3_t relvieworg) +R_DrawSprite (entity_t *ent) { - msprite_t *sprite = currententity->renderer.model->cache.data; + msprite_t *sprite = ent->renderer.model->cache.data; + vec3_t relvieworg; - r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, - ¤tentity->animation); + VectorSubtract (r_refdef.viewposition, r_entorigin, relvieworg); + + r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, &ent->animation); sprite_width = r_spritedesc.pspriteframe->width; sprite_height = r_spritedesc.pspriteframe->height; - if (!R_BillboardFrame (currententity, sprite->type, relvieworg, + if (!R_BillboardFrame (ent, sprite->type, relvieworg, r_spritedesc.vup, r_spritedesc.vright, r_spritedesc.vpn)) { diff --git a/libs/video/renderer/vulkan/vulkan_lightmap.c b/libs/video/renderer/vulkan/vulkan_lightmap.c index 7e6a61cef..9eecc8616 100644 --- a/libs/video/renderer/vulkan/vulkan_lightmap.c +++ b/libs/video/renderer/vulkan/vulkan_lightmap.c @@ -57,7 +57,8 @@ #define LUXEL_SIZE 4 static inline void -add_dynamic_lights (msurface_t *surf, float *block) +add_dynamic_lights (const transform_t *transform, msurface_t *surf, + float *block) { unsigned lnum; int sd, td; @@ -74,9 +75,9 @@ add_dynamic_lights (msurface_t *surf, float *block) tex = surf->texinfo; plane = surf->plane; - if (currententity->transform) { + if (transform) { //FIXME give world entity a transform - entorigin = Transform_GetWorldPosition (currententity->transform); + entorigin = Transform_GetWorldPosition (transform); } for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -130,7 +131,8 @@ add_dynamic_lights (msurface_t *surf, float *block) } void -Vulkan_BuildLightMap (mod_brush_t *brush, msurface_t *surf, vulkan_ctx_t *ctx) +Vulkan_BuildLightMap (const transform_t *transform, mod_brush_t *brush, + msurface_t *surf, vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; int smax, tmax, size; @@ -178,7 +180,7 @@ Vulkan_BuildLightMap (mod_brush_t *brush, msurface_t *surf, vulkan_ctx_t *ctx) } // add all the dynamic lights if (surf->dlightframe == r_framecount) { - add_dynamic_lights (surf, block); + add_dynamic_lights (transform, surf, block); } } @@ -267,7 +269,7 @@ Vulkan_BuildLightmaps (model_t **models, int num_models, vulkan_ctx_t *ctx) for (i = 0; i < brush->numsurfaces; i++) { msurface_t *surf = brush->surfaces + i; if (surf->lightpic) { - Vulkan_BuildLightMap (brush, surf, ctx); + Vulkan_BuildLightMap (0, brush, surf, ctx); } } } From f3768e3dfba675fb8a2dc1d8677e96d573f02a89 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Mar 2022 16:39:08 +0900 Subject: [PATCH 2525/3664] [renderer] Remove currententity One more global in the trash :) --- include/d_iface.h | 4 ++-- include/d_local.h | 4 +++- include/r_local.h | 15 +++++++------ include/r_shared.h | 1 - libs/video/renderer/r_light.c | 2 -- libs/video/renderer/r_main.c | 2 -- libs/video/renderer/sw/d_edge.c | 22 +++++++----------- libs/video/renderer/sw/d_surf.c | 6 ++--- libs/video/renderer/sw/sw_rbsp.c | 37 +++++++++++++++++-------------- libs/video/renderer/sw/sw_rdraw.c | 18 +++++++-------- libs/video/renderer/sw/sw_redge.c | 6 ++--- libs/video/renderer/sw/sw_rmain.c | 15 ++++++------- libs/video/renderer/sw/sw_rsurf.c | 14 ++++++------ 13 files changed, 69 insertions(+), 77 deletions(-) diff --git a/include/d_iface.h b/include/d_iface.h index 279a10baf..9536f1725 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -200,8 +200,8 @@ typedef struct } drawsurf_t; extern drawsurf_t r_drawsurf; - -void R_DrawSurface (void); +struct transform_s; +void R_DrawSurface (struct transform_s *transform); void R_GenTile (msurface_t *psurf, void *pdest); // !!! if this is changed, it must be changed in d_iface.h too !!! diff --git a/include/d_local.h b/include/d_local.h index f67dcea74..1ff077d82 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -91,7 +91,9 @@ void D_DrawSkyScans (struct espan_s *pspan); void R_ShowSubDiv (void); extern void (*prealspandrawer)(void); -surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel); +struct entity_s; +surfcache_t *D_CacheSurface (struct entity_s *ent, + msurface_t *surface, int miplevel); int D_MipLevelForScale (float scale) __attribute__((pure)); diff --git a/include/r_local.h b/include/r_local.h index 6efd16c3d..fe8c19713 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -144,9 +144,9 @@ void R_SetFrustum (void); void R_SpriteBegin (void); void R_SpriteEnd (void); void R_DrawSprite (entity_t *ent); -void R_RenderFace (msurface_t *fa, int clipflags); -void R_RenderPoly (msurface_t *fa, int clipflags); -void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf); +void R_RenderFace (entity_t *ent, msurface_t *fa, int clipflags); +void R_RenderPoly (entity_t *ent, msurface_t *fa, int clipflags); +void R_RenderBmodelFace (entity_t *ent, bedge_t *pedges, msurface_t *psurf); void R_TransformFrustum (void); void R_SetSkyFrame (void); void R_DrawSurfaceBlock (void); @@ -154,8 +154,8 @@ texture_t *R_TextureAnimation (const entity_t *entity, msurface_t *surf) __attri void R_GenSkyTile (void *pdest); void R_SurfPatch (void); -void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags); -void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel); +void R_DrawSubmodelPolygons (entity_t *ent, model_t *pmodel, int clipflags, struct mnode_s *topnode); +void R_DrawSolidClippedSubmodelPolygons (entity_t *ent, model_t *pmodel, struct mnode_s *topnode); void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); surf_t *R_GetSurf (void); @@ -188,7 +188,8 @@ extern void R_Surf8End (void); extern void R_EdgeCodeStart (void); extern void R_EdgeCodeEnd (void); -extern void R_RotateBmodel (void); +struct transform_s; +extern void R_RotateBmodel (struct transform_s *transform); extern int c_faceclip; extern int r_polycount; @@ -222,7 +223,7 @@ typedef struct btofpoly_s { extern int numbtofpolys; void R_InitTurb (void); -void R_ZDrawSubmodelPolys (model_t *clmodel); +void R_ZDrawSubmodelPolys (entity_t *ent, model_t *clmodel); // Alias models =========================================== diff --git a/include/r_shared.h b/include/r_shared.h index b04e129f1..84616a77c 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -72,7 +72,6 @@ extern byte color_black[4]; extern vec3_t vup, base_vup; extern vec3_t vpn, base_vpn; extern vec3_t vright, base_vright; -extern struct entity_s *currententity; #define NUMSTACKEDGES 2400 //2000 #define MINEDGES NUMSTACKEDGES diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 8ecf947de..8de8f2738 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -210,9 +210,7 @@ R_RecursiveMarkLights (mod_brush_t *brush, const vec3_t lightorigin, float ndist, maxdist; plane_t *splitplane; msurface_t *surf; - //XXX mvertex_t *vertices; - //XXX vertices = r_worldentity.model->vertexes; maxdist = light->radius; loc0: diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index dd9860c4c..ba3b260a3 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -65,14 +65,12 @@ vec3_t modelorg; // modelorg is the viewpoint relative to vec3_t base_modelorg; vec3_t r_entorigin; // the currently rendering entity in world // coordinates -entity_t *currententity; entity_t r_worldentity; // view origin vec3_t vup, base_vup; vec3_t vpn, base_vpn; vec3_t vright, base_vright; -vec3_t r_origin; // screen size info refdef_t r_refdef; diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index a4ddcfb5d..91c0b2f53 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -153,7 +153,6 @@ D_DrawSurfaces (void) vec3_t world_transformed_modelorg; vec3_t local_modelorg; - currententity = &r_worldentity; TransformVector (modelorg, transformed_modelorg); VectorCopy (transformed_modelorg, world_transformed_modelorg); @@ -207,14 +206,13 @@ D_DrawSurfaces (void) if (s->insubmodel) { // FIXME: we don't want to do all this for every polygon! // TODO: store once at start of frame - currententity = s->entity; // FIXME: make this passed in - // to R_RotateBmodel () + transform_t *transform = s->entity->transform; + transform = s->entity->transform; VectorSubtract (r_refdef.viewposition, - Transform_GetWorldPosition (currententity->transform), - local_modelorg); + Transform_GetWorldPosition (transform), local_modelorg); TransformVector (local_modelorg, transformed_modelorg); - R_RotateBmodel (); // FIXME: don't mess with the + R_RotateBmodel (transform); // FIXME: don't mess with the // frustum, make entity passed in } @@ -228,7 +226,6 @@ D_DrawSurfaces (void) // FIXME: we don't want to do this every time! // TODO: speed up - currententity = &r_worldentity; VectorCopy (world_transformed_modelorg, transformed_modelorg); VectorCopy (base_vpn, vpn); @@ -241,14 +238,12 @@ D_DrawSurfaces (void) if (s->insubmodel) { // FIXME: we don't want to do all this for every polygon! // TODO: store once at start of frame - currententity = s->entity; // FIXME: make this passed in - // to R_RotateBmodel () + transform_t *transform = s->entity->transform; VectorSubtract (r_refdef.viewposition, - Transform_GetWorldPosition (currententity->transform), - local_modelorg); + Transform_GetWorldPosition (transform), local_modelorg); TransformVector (local_modelorg, transformed_modelorg); - R_RotateBmodel (); // FIXME: don't mess with the + R_RotateBmodel (transform); // FIXME: don't mess with the // frustum, make entity passed in } @@ -257,7 +252,7 @@ D_DrawSurfaces (void) * pface->texinfo->mipadjust); // FIXME: make this passed in to D_CacheSurface - pcurrentcache = D_CacheSurface (pface, miplevel); + pcurrentcache = D_CacheSurface (s->entity, pface, miplevel); cacheblock = (byte *) pcurrentcache->data; cachewidth = pcurrentcache->width; @@ -280,7 +275,6 @@ D_DrawSurfaces (void) VectorCopy (base_vright, vright); VectorCopy (base_modelorg, modelorg); R_TransformFrustum (); - currententity = &r_worldentity; } } } diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 8e6e53c75..33b4b399f 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -226,12 +226,12 @@ D_SCDump (void) #endif surfcache_t * -D_CacheSurface (msurface_t *surface, int miplevel) +D_CacheSurface (entity_t *ent, msurface_t *surface, int miplevel) { surfcache_t *cache; // if the surface is animating or flashing, flush the cache - r_drawsurf.texture = R_TextureAnimation (currententity, surface); + r_drawsurf.texture = R_TextureAnimation (ent, surface); r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; @@ -282,7 +282,7 @@ D_CacheSurface (msurface_t *surface, int miplevel) r_drawsurf.surf = surface; c_surf++; - R_DrawSurface (); + R_DrawSurface (ent->transform); return surface->cachespots[miplevel]; } diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index ac9028209..1fbab1168 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -77,10 +77,10 @@ R_EntityRotate (vec3_t vec) void -R_RotateBmodel (void) +R_RotateBmodel (transform_t *transform) { mat4f_t mat; - Transform_GetWorldMatrix (currententity->transform, mat); + Transform_GetWorldMatrix (transform, mat); VectorCopy (mat[0], entity_rotation[0]); VectorCopy (mat[1], entity_rotation[1]); VectorCopy (mat[2], entity_rotation[2]); @@ -96,7 +96,8 @@ R_RotateBmodel (void) static void -R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) +R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode, + msurface_t *psurf) { bedge_t *psideedges[2], *pnextedge, *ptedge; int i, side, lastside; @@ -228,11 +229,11 @@ R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) if (pn->contents < 0) { if (pn->contents != CONTENTS_SOLID) { r_currentbkey = ((mleaf_t *) pn)->key; - R_RenderBmodelFace (psideedges[i], psurf); + R_RenderBmodelFace (ent, psideedges[i], psurf); } } else { - R_RecursiveClipBPoly (psideedges[i], pnode->children[i], - psurf); + R_RecursiveClipBPoly (ent, psideedges[i], + pnode->children[i], psurf); } } } @@ -241,7 +242,8 @@ R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) void -R_DrawSolidClippedSubmodelPolygons (model_t *model) +R_DrawSolidClippedSubmodelPolygons (entity_t *ent, model_t *model, + mnode_t *topnode) { int i, j, lindex; vec_t dot; @@ -301,8 +303,7 @@ R_DrawSolidClippedSubmodelPolygons (model_t *model) pbedge[j - 1].pnext = NULL; // mark end of edges - R_RecursiveClipBPoly (pbedge, - currententity->visibility.topnode, psurf); + R_RecursiveClipBPoly (ent, pbedge, topnode, psurf); } else { Sys_Error ("no edges in bmodel"); } @@ -312,7 +313,8 @@ R_DrawSolidClippedSubmodelPolygons (model_t *model) void -R_DrawSubmodelPolygons (model_t *model, int clipflags) +R_DrawSubmodelPolygons (entity_t *ent, model_t *model, int clipflags, + mnode_t *topnode) { int i; vec_t dot; @@ -335,10 +337,10 @@ R_DrawSubmodelPolygons (model_t *model, int clipflags) // draw the polygon if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - r_currentkey = ((mleaf_t *) currententity->visibility.topnode)->key; + r_currentkey = ((mleaf_t *) topnode)->key; // FIXME: use bounding-box-based frustum clipping info? - R_RenderFace (psurf, clipflags); + R_RenderFace (ent, psurf, clipflags); } } } @@ -370,6 +372,7 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, int clipflags) { int c; msurface_t *surf; + entity_t *ent = &r_worldentity; // sneaky hack for side = side ? SURF_PLANEBACK : 0; side = (~side + 1) & SURF_PLANEBACK; @@ -392,10 +395,10 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, int clipflags) numbtofpolys++; } } else { - R_RenderPoly (surf, clipflags); + R_RenderPoly (ent, surf, clipflags); } } else { - R_RenderFace (surf, clipflags); + R_RenderFace (ent, surf, clipflags); } } // all surfaces on the same node share the same sequence number @@ -512,11 +515,11 @@ R_RenderWorld (void) int i; btofpoly_t btofpolys[MAX_BTOFPOLYS]; mod_brush_t *brush; + entity_t *ent = &r_worldentity; pbtofpolys = btofpolys; - currententity = &r_worldentity; - brush = ¤tentity->renderer.model->brush; + brush = &r_worldentity.renderer.model->brush; r_pcurrentvertbase = brush->vertexes; R_VisitWorldNodes (brush, 15); @@ -525,7 +528,7 @@ R_RenderWorld (void) // back in that order if (r_worldpolysbacktofront) { for (i = numbtofpolys - 1; i >= 0; i--) { - R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags); + R_RenderPoly (ent, btofpolys[i].psurf, btofpolys[i].clipflags); } } } diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index b466d1b61..48c8489df 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -344,7 +344,7 @@ R_EmitCachedEdge (void) void -R_RenderFace (msurface_t *fa, int clipflags) +R_RenderFace (entity_t *ent, msurface_t *fa, int clipflags) { int i, lindex; unsigned int mask; @@ -353,7 +353,7 @@ R_RenderFace (msurface_t *fa, int clipflags) vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; - mod_brush_t *brush = ¤tentity->renderer.model->brush; + mod_brush_t *brush = &ent->renderer.model->brush; // skip out if no more surfs if ((surface_p) >= surf_max) { @@ -490,7 +490,7 @@ R_RenderFace (msurface_t *fa, int clipflags) surface_p->flags = fa->flags; surface_p->insubmodel = insubmodel; surface_p->spanstate = 0; - surface_p->entity = currententity; + surface_p->entity = ent; surface_p->key = r_currentkey++; surface_p->spans = NULL; @@ -510,7 +510,7 @@ R_RenderFace (msurface_t *fa, int clipflags) void -R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) +R_RenderBmodelFace (entity_t *ent, bedge_t *pedges, msurface_t *psurf) { int i; unsigned int mask; @@ -589,7 +589,7 @@ R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) surface_p->flags = psurf->flags; surface_p->insubmodel = true; surface_p->spanstate = 0; - surface_p->entity = currententity; + surface_p->entity = ent; surface_p->key = r_currentbkey; surface_p->spans = NULL; @@ -609,7 +609,7 @@ R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) void -R_RenderPoly (msurface_t *fa, int clipflags) +R_RenderPoly (entity_t *ent, msurface_t *fa, int clipflags) { int i, lindex, lnumverts, s_axis, t_axis; float dist, lastdist, lzi, scale, u, v, frac; @@ -622,7 +622,7 @@ R_RenderPoly (msurface_t *fa, int clipflags) polyvert_t pverts[100]; // FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; qboolean visible; - mod_brush_t *brush = ¤tentity->renderer.model->brush; + mod_brush_t *brush = &ent->renderer.model->brush; // FIXME: clean this up and make it faster // FIXME: guard against running out of vertices @@ -777,7 +777,7 @@ R_RenderPoly (msurface_t *fa, int clipflags) void -R_ZDrawSubmodelPolys (model_t *model) +R_ZDrawSubmodelPolys (entity_t *ent, model_t *model) { int i, numsurfaces; msurface_t *psurf; @@ -798,7 +798,7 @@ R_ZDrawSubmodelPolys (model_t *model) if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { // FIXME: use bounding-box-based frustum clipping info? - R_RenderPoly (psurf, 15); + R_RenderPoly (ent, psurf, 15); } } } diff --git a/libs/video/renderer/sw/sw_redge.c b/libs/video/renderer/sw/sw_redge.c index 8efc09753..92499477a 100644 --- a/libs/video/renderer/sw/sw_redge.c +++ b/libs/video/renderer/sw/sw_redge.c @@ -85,8 +85,6 @@ R_DrawCulledPolys (void) surf_t *s; msurface_t *pface; - currententity = &r_worldentity; - if (r_worldpolysbacktofront) { for (s = surface_p - 1; s > &surfaces[1]; s--) { if (!s->spans) @@ -94,7 +92,7 @@ R_DrawCulledPolys (void) if (!(s->flags & SURF_DRAWBACKGROUND)) { pface = (msurface_t *) s->data; - R_RenderPoly (pface, 15); + R_RenderPoly (s->entity, pface, 15); } } } else { @@ -104,7 +102,7 @@ R_DrawCulledPolys (void) if (!(s->flags & SURF_DRAWBACKGROUND)) { pface = (msurface_t *) s->data; - R_RenderPoly (pface, 15); + R_RenderPoly (s->entity, pface, 15); } } } diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index c6b7ddf1f..98e98f4d6 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -495,7 +495,7 @@ R_DrawViewModel (void) } static int -R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) +R_BmodelCheckBBox (entity_t *ent, model_t *clmodel, float *minmaxs) { int i, *pindex, clipflags; vec3_t acceptpt, rejectpt; @@ -504,7 +504,7 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) clipflags = 0; - Transform_GetWorldMatrix (currententity->transform, mat); + Transform_GetWorldMatrix (ent->transform, mat); if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { for (i = 0; i < 4; i++) { d = DotProduct (mat[3], view_clipplanes[i].normal); @@ -565,7 +565,6 @@ R_DrawBrushEntitiesOnList (void) for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; - currententity = ent; VectorCopy (Transform_GetWorldPosition (ent->transform), origin); clmodel = ent->renderer.model; @@ -577,7 +576,7 @@ R_DrawBrushEntitiesOnList (void) minmaxs[3 + j] = origin[j] + clmodel->maxs[j]; } - clipflags = R_BmodelCheckBBox (clmodel, minmaxs); + clipflags = R_BmodelCheckBBox (ent, clmodel, minmaxs); if (clipflags != BMODEL_FULLY_CLIPPED) { mod_brush_t *brush = &clmodel->brush; @@ -587,7 +586,7 @@ R_DrawBrushEntitiesOnList (void) r_pcurrentvertbase = brush->vertexes; // FIXME: stop transforming twice - R_RotateBmodel (); + R_RotateBmodel (ent->transform); // calculate dynamic lighting for bmodel if it's not an // instanced model @@ -611,7 +610,7 @@ R_DrawBrushEntitiesOnList (void) // Z-buffering is on at this point, so no clipping to the // world tree is needed, just frustum clipping if (r_drawpolys | r_drawculledpolys) { - R_ZDrawSubmodelPolys (clmodel); + R_ZDrawSubmodelPolys (ent, clmodel); } else { if (ent->visibility.topnode) { mnode_t *topnode = ent->visibility.topnode; @@ -620,12 +619,12 @@ R_DrawBrushEntitiesOnList (void) // not a leaf; has to be clipped to the world // BSP r_clipflags = clipflags; - R_DrawSolidClippedSubmodelPolygons (clmodel); + R_DrawSolidClippedSubmodelPolygons (ent, clmodel, topnode); } else { // falls entirely in one leaf, so we just put // all the edges in the edge list and let 1/z // sorting handle drawing order - R_DrawSubmodelPolygons (clmodel, clipflags); + R_DrawSubmodelPolygons (ent, clmodel, clipflags, topnode); } } } diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 106dd8f29..819293d1b 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -73,7 +73,7 @@ static unsigned int blocklights[34 * 34]; //FIXME make dynamic static void -R_AddDynamicLights (void) +R_AddDynamicLights (transform_t *transform) { msurface_t *surf; unsigned int lnum; @@ -91,9 +91,9 @@ R_AddDynamicLights (void) tmax = (surf->extents[1] >> 4) + 1; tex = surf->texinfo; - if (currententity->transform) { + if (transform) { //FIXME give world entity a transform - entorigin = Transform_GetWorldPosition (currententity->transform); + entorigin = Transform_GetWorldPosition (transform); } for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -144,7 +144,7 @@ R_AddDynamicLights (void) Combine and scale multiple lightmaps into the 8.8 format in blocklights */ static void -R_BuildLightMap (void) +R_BuildLightMap (transform_t *transform) { int smax, tmax; int t; @@ -180,7 +180,7 @@ R_BuildLightMap (void) } // add all the dynamic lights if (surf->dlightframe == r_framecount) - R_AddDynamicLights (); + R_AddDynamicLights (transform); // bound, invert, and shift for (i = 0; i < size; i++) { @@ -194,7 +194,7 @@ R_BuildLightMap (void) } void -R_DrawSurface (void) +R_DrawSurface (transform_t *transform) { byte *basetptr; int smax, tmax, twidth; @@ -206,7 +206,7 @@ R_DrawSurface (void) texture_t *mt; // calculate the lightings - R_BuildLightMap (); + R_BuildLightMap (transform); surfrowbytes = r_drawsurf.rowbytes; From bce7d5b8326d0a2b09b9fb77a05eb60a118b5129 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Mar 2022 09:34:24 +0900 Subject: [PATCH 2526/3664] [renderer] Clean up use of vup/vright/vpn This moves the common camera setup code out of the individual drivers, and completely removes vup/vright/vpn from the non-software renderers. This has highlighted the craziness around AngleVectors with it putting +X forward, -Y right and +Z up. The main issue with this is it requires a 90 degree pre-rotation about the Z axis to get the camera pointing in the right direction, and that's for the native sw renderer (vulkan needs a 90 degree pre-rotation about X, and gl and glsl need to invert an axis, too), though at least it's just a matrix swizzle and vector negation. However, it does mean the camera matrices can't be used directly. Also rename vpn to vfwd (still abbreviated, but fwd is much clearer in meaning (to me, at least) than pn (plane normal, I guess, but which way?)). --- include/QF/render.h | 14 ++++++-- include/d_iface.h | 2 +- include/quakeasm.h | 2 +- include/r_internal.h | 2 +- include/r_shared.h | 2 +- libs/video/renderer/gl/gl_dyn_lights.c | 6 ++-- libs/video/renderer/gl/gl_dyn_part.c | 9 +++--- libs/video/renderer/gl/gl_mod_sprite.c | 8 ++--- libs/video/renderer/gl/gl_rmain.c | 12 ++----- libs/video/renderer/gl/gl_rsurf.c | 4 +-- libs/video/renderer/gl/gl_sky.c | 20 ++++++------ libs/video/renderer/gl/gl_sky_clip.c | 16 ++++----- libs/video/renderer/glsl/glsl_bsp.c | 6 ++-- libs/video/renderer/glsl/glsl_main.c | 13 ++------ libs/video/renderer/glsl/glsl_particles.c | 14 ++++---- libs/video/renderer/glsl/glsl_sprite.c | 2 +- libs/video/renderer/r_billboard.c | 34 ++++++++++---------- libs/video/renderer/r_graph.c | 2 +- libs/video/renderer/r_main.c | 18 +++++------ libs/video/renderer/r_screen.c | 19 ++++++++--- libs/video/renderer/sw/d_edge.c | 18 +++++------ libs/video/renderer/sw/d_sky.c | 6 ++-- libs/video/renderer/sw/d_sprite.c | 4 +-- libs/video/renderer/sw/sw_ralias.c | 8 ++--- libs/video/renderer/sw/sw_rbsp.c | 4 +-- libs/video/renderer/sw/sw_rdrawa.S | 6 ++-- libs/video/renderer/sw/sw_riqm.c | 8 ++--- libs/video/renderer/sw/sw_rmain.c | 8 +++-- libs/video/renderer/sw/sw_rmisc.c | 21 ++++++------ libs/video/renderer/sw/sw_rpart.c | 4 +-- libs/video/renderer/sw/sw_rsprite.c | 10 +++--- libs/video/renderer/sw/transform.S | 22 ++++++------- libs/video/renderer/vulkan/vulkan_bsp.c | 4 +-- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- libs/video/renderer/vulkan/vulkan_main.c | 7 +--- libs/video/renderer/vulkan/vulkan_matrices.c | 9 ++---- libs/video/renderer/vulkan/vulkan_sprite.c | 2 +- 37 files changed, 172 insertions(+), 176 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index c6977ff32..788c41dca 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -203,9 +203,17 @@ typedef struct { float xOrigin; // should probably always be 0.5 float yOrigin; // between be around 0.3 to 0.5 - //FIXME was vec3_t, need to deal with asm (maybe? is it worth it?) - vec4f_t viewposition; - vec4f_t viewrotation; + union { + mat4f_t mat; + struct { + vec4f_t right; + vec4f_t forward; + vec4f_t up; + vec4f_t position; + }; + } frame; + mat4f_t camera; + mat4f_t camera_inverse; int ambientlight; int drawflat; diff --git a/include/d_iface.h b/include/d_iface.h index 9536f1725..4e78c43e8 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -101,7 +101,7 @@ typedef struct // if the driver wants to duplicate element [0] at // element [nump] to avoid dealing with wrapping mspriteframe_t *pspriteframe; - vec3_t vup, vright, vpn; // in worldspace + vec3_t vup, vright, vfwd; // in worldspace float nearzi; } spritedesc_t; diff --git a/include/quakeasm.h b/include/quakeasm.h index f9c663aae..2ee8bb720 100644 --- a/include/quakeasm.h +++ b/include/quakeasm.h @@ -255,7 +255,7 @@ .extern C(vright) .extern C(vup) - .extern C(vpn) + .extern C(vfwd) #endif diff --git a/include/r_internal.h b/include/r_internal.h index 8a1ae465c..c25ba7271 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -77,7 +77,7 @@ void GL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette); int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, - vec3_t bbup, vec3_t bbright, vec3_t bbpn); + vec3_t bbup, vec3_t bbright, vec3_t bbfwd); mspriteframe_t *R_GetSpriteFrame (const msprite_t *sprite, const animation_t *animation); diff --git a/include/r_shared.h b/include/r_shared.h index 84616a77c..e3e3c585f 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -70,7 +70,7 @@ extern byte color_white[4]; extern byte color_black[4]; extern vec3_t vup, base_vup; -extern vec3_t vpn, base_vpn; +extern vec3_t vfwd, base_vfwd; extern vec3_t vright, base_vright; #define NUMSTACKEDGES 2400 //2000 diff --git a/libs/video/renderer/gl/gl_dyn_lights.c b/libs/video/renderer/gl/gl_dyn_lights.c index d29737d2a..2d006c5cd 100644 --- a/libs/video/renderer/gl/gl_dyn_lights.c +++ b/libs/video/renderer/gl/gl_dyn_lights.c @@ -81,7 +81,7 @@ R_RenderDlight (dlight_t *light) bub_cos = gl_bubble_costable; rad = light->radius * 0.35; - VectorSubtract (r_refdef.viewposition, light->origin, v); + VectorSubtract (r_refdef.frame.position, light->origin, v); if (VectorLength (v) < rad) // view is inside the dlight return; @@ -99,8 +99,8 @@ R_RenderDlight (dlight_t *light) for (i = 16; i >= 0; i--) { for (j = 0; j < 3; j++) - v[j] = light->origin[j] + (vright[j] * (*bub_cos) + - vup[j] * (*bub_sin)) * rad; + v[j] = light->origin[j] + (r_refdef.frame.right[j] * (*bub_cos) + + r_refdef.frame.up[j] * (*bub_sin)) * rad; bub_sin += 2; bub_cos += 2; qfglVertex3fv (v); diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 6ed7d01c6..a236179dc 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -131,7 +131,8 @@ gl_R_DrawParticles (void) qfglDepthMask (GL_FALSE); qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, particleVertexArray); - minparticledist = DotProduct (r_refdef.viewposition, vpn) + + minparticledist = DotProduct (r_refdef.frame.position, + r_refdef.frame.forward) + r_particles_nearclip->value; vacount = 0; @@ -141,7 +142,7 @@ gl_R_DrawParticles (void) particle_t *p = &r_psystem.particles[i]; // Don't render particles too close to us. // Note, we must still do physics and such on them. - if (!(DotProduct (p->pos, vpn) < minparticledist)) { + if (!(DotProduct (p->pos, r_refdef.frame.forward) < minparticledist)) { at = (byte *) &d_8to24table[(byte) p->icolor]; VA[0].color[0] = at[0]; VA[0].color[1] = at[1]; @@ -186,8 +187,8 @@ gl_R_DrawParticles (void) scale = p->scale; - VectorScale (vup, scale, up_scale); - VectorScale (vright, scale, right_scale); + VectorScale (r_refdef.frame.up, scale, up_scale); + VectorScale (r_refdef.frame.right, scale, right_scale); VectorAdd (right_scale, up_scale, up_right_scale); VectorSubtract (right_scale, up_scale, down_right_scale); diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index fd5599857..1c37cd2ce 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -68,7 +68,7 @@ R_DrawSpriteModel_f (entity_t *e) mspriteframe_t *frame; origin = Transform_GetWorldPosition (e->transform); - cameravec = r_refdef.viewposition - origin; + cameravec = r_refdef.frame.position - origin; // don't bother culling, it's just a single polygon without a surface cache frame = R_GetSpriteFrame (sprite, &e->animation); @@ -138,10 +138,10 @@ R_DrawSpriteModel_VA_f (entity_t *e) right = Transform_Right (e->transform); } else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) { up = (vec4f_t) { 0, 0, 1, 0 }; - VectorCopy (vright, right); + VectorCopy (r_refdef.frame.right, right); } else { // normal sprite - VectorCopy (vup, up); - VectorCopy (vright, right); + VectorCopy (r_refdef.frame.up, up); + VectorCopy (r_refdef.frame.right, right); } for (i = 0; i < 4; i++) { diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 4b6806f4b..3a393fa6f 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -331,11 +331,7 @@ gl_R_SetupFrame (void) EntQueue_Clear (r_ent_queue); r_framecount++; - vec4f_t position = r_refdef.viewposition; - vec4f_t rotation = r_refdef.viewrotation; - VectorCopy (qvmulf (rotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); - VectorCopy (qvmulf (rotation, (vec4f_t) { 0, -1, 0, 0 }), vright); - VectorCopy (qvmulf (rotation, (vec4f_t) { 0, 0, 1, 0 }), vup); + vec4f_t position = r_refdef.frame.position; R_SetFrustum (); @@ -409,11 +405,7 @@ R_SetupGL (void) { 0, 0, 0, 1}, }; mat4f_t view; - mat4fquat (view, qconjf (r_refdef.viewrotation)); - mmulf (view, z_up, view); - vec4f_t offset = -r_refdef.viewposition; - offset[3] = 1; - view[3] = mvmulf (view, offset); + mmulf (view, z_up, r_refdef.camera_inverse); qfglLoadMatrixf (&view[0][0]); qfglGetFloatv (GL_MODELVIEW_MATRIX, gl_r_world_matrix); diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 280d5d626..5a5bf3476 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -565,7 +565,7 @@ gl_R_DrawBrushModel (entity_t *e) return; } - vec4f_t relviewpos = r_refdef.viewposition - worldMatrix[3]; + vec4f_t relviewpos = r_refdef.frame.position - worldMatrix[3]; if (rotated) { vec4f_t temp = relviewpos; @@ -626,7 +626,7 @@ get_side (mnode_t *node) { // find which side of the node we are on plane_t *plane = node->plane; - vec4f_t org = r_refdef.viewposition; + vec4f_t org = r_refdef.frame.position; if (plane->type < 3) return (org[plane->type] - plane->dist) < 0; diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index 718343f55..e0ad50869 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -189,9 +189,9 @@ R_DrawSkyBox (void) float *v = (float *) gl_skyvec[i][j]; qfglTexCoord2fv (v); - qfglVertex3f (r_refdef.viewposition[0] + v[2], - r_refdef.viewposition[1] + v[3], - r_refdef.viewposition[2] + v[4]); + qfglVertex3f (r_refdef.frame.position[0] + v[2], + r_refdef.frame.position[1] + v[3], + r_refdef.frame.position[2] + v[4]); } qfglEnd (); } @@ -219,7 +219,7 @@ skydome_vertex (const vec3_t v, float speedscale) s = speedscale + dir[0]; t = speedscale + dir[1]; - VectorAdd (r_refdef.viewposition, v, point); + VectorAdd (r_refdef.frame.position, v, point); qfglTexCoord2f (s, t); qfglVertex3fv (point); @@ -242,7 +242,7 @@ skydome_debug (void) h = 1; t = 0; - VectorAdd (zenith, r_refdef.viewposition, v[0]); + VectorAdd (zenith, r_refdef.frame.position, v[0]); for (b = 1; b <= 8; b++) { x = gl_bubble_costable[b + 8]; y = -gl_bubble_sintable[b + 8]; @@ -250,7 +250,7 @@ skydome_debug (void) v[h][0] = a1x * x; v[h][1] = a1y * x; v[h][2] = y * domescale[2]; - VectorAdd (v[h], r_refdef.viewposition, v[h]); + VectorAdd (v[h], r_refdef.frame.position, v[h]); for (i = t; i != h; i = (i + 1) % 3) { qfglVertex3fv (v[i]); qfglVertex3fv (v[h]); @@ -262,7 +262,7 @@ skydome_debug (void) v[h][0] = a2x * x; v[h][1] = a2y * x; v[h][2] = y * domescale[2]; - VectorAdd (v[h], r_refdef.viewposition, v[h]); + VectorAdd (v[h], r_refdef.frame.position, v[h]); for (i = t; i != h; i = (i + 1) % 3) { qfglVertex3fv (v[i]); qfglVertex3fv (v[h]); @@ -274,7 +274,7 @@ skydome_debug (void) h = 1; t = 0; - VectorAdd (nadir, r_refdef.viewposition, v[0]); + VectorAdd (nadir, r_refdef.frame.position, v[0]); for (b = 15; b >= 8; b--) { x = gl_bubble_costable[b + 8]; y = -gl_bubble_sintable[b + 8]; @@ -282,7 +282,7 @@ skydome_debug (void) v[h][0] = a2x * x; v[h][1] = a2y * x; v[h][2] = y * domescale[2]; - VectorAdd (v[h], r_refdef.viewposition, v[h]); + VectorAdd (v[h], r_refdef.frame.position, v[h]); for (i = t; i != h; i = (i + 1) % 3) { qfglVertex3fv (v[i]); qfglVertex3fv (v[h]); @@ -294,7 +294,7 @@ skydome_debug (void) v[h][0] = a1x * x; v[h][1] = a1y * x; v[h][2] = y * domescale[2]; - VectorAdd (v[h], r_refdef.viewposition, v[h]); + VectorAdd (v[h], r_refdef.frame.position, v[h]); for (i = t; i != h; i = (i + 1) % 3) { qfglVertex3fv (v[i]); qfglVertex3fv (v[h]); diff --git a/libs/video/renderer/gl/gl_sky_clip.c b/libs/video/renderer/gl/gl_sky_clip.c index 89f521ebd..c11554315 100644 --- a/libs/video/renderer/gl/gl_sky_clip.c +++ b/libs/video/renderer/gl/gl_sky_clip.c @@ -220,14 +220,14 @@ find_cube_vertex (int face1, int face2, int face3, vec3_t v) set_vertex add the vertex to the polygon describing the face of the cube. Offsets - the vertex relative to r_refdef.viewposition so the cube is always centered + the vertex relative to r_refdef.frame.position so the cube is always centered on the player and also calculates the texture coordinates of the vertex (wish I could find a cleaner way of calculating s and t). */ static void set_vertex (struct box_def *box, int face, int ind, const vec3_t v) { - VectorAdd (v, r_refdef.viewposition, box->face[face].poly.verts[ind]); + VectorAdd (v, r_refdef.frame.position, box->face[face].poly.verts[ind]); switch (face) { case 0: box->face[face].poly.verts[ind][3] = (1024 - v[1] + 4) / BOX_WIDTH; @@ -601,14 +601,14 @@ R_DrawSkyBoxPoly (const glpoly_t *poly) Sys_Error ("too many verts!"); } - VectorSubtract (poly->verts[poly->numverts - 1], r_refdef.viewposition, last_v); + VectorSubtract (poly->verts[poly->numverts - 1], r_refdef.frame.position, last_v); prev_face = determine_face (last_v); box.visited_faces[0].face = prev_face; box.face_count = 1; for (i = 0; i < poly->numverts; i++) { - VectorSubtract (poly->verts[i], r_refdef.viewposition, v); + VectorSubtract (poly->verts[i], r_refdef.frame.position, v); face = determine_face (v); if (face != prev_face) { if ((face_axis[face]) == (face_axis[prev_face])) { @@ -645,7 +645,7 @@ EmitSkyPolys (float speedscale, const instsurf_t *sc) glpoly_t *p; vec3_t dir; msurface_t *surf = sc->surface; - vec4f_t origin = r_refdef.viewposition; + vec4f_t origin = r_refdef.frame.position; //FIXME transform/color for (p = surf->polys; p; p = p->next) { @@ -865,11 +865,11 @@ gl_R_DrawSkyChain (const instsurf_t *sky_chain) vec3_t x, c = { 0, 0, 0 }; for (i = 0; i < p->numverts; i++) { - VectorSubtract (p->verts[i], r_refdef.viewposition, x); + VectorSubtract (p->verts[i], r_refdef.frame.position, x); VectorAdd (x, c, c); } VectorScale (c, 1.0 / p->numverts, c); - VectorAdd (c, r_refdef.viewposition, c); + VectorAdd (c, r_refdef.frame.position, c); qfglVertex3fv (c); p = p->next; } @@ -890,7 +890,7 @@ gl_R_DrawSkyChain (const instsurf_t *sky_chain) qfglBegin (GL_LINE_LOOP); for (j = 0; j < 4; j++) { VectorScale (&gl_skyvec[i][j][2], 1.0 / 128.0, v); - VectorAdd (v, r_refdef.viewposition, v); + VectorAdd (v, r_refdef.frame.position, v); qfglVertex3fv (v); } qfglEnd (); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 40e7d5911..c01de2119 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -691,7 +691,7 @@ R_DrawBrushModel (entity_t *e) return; } - org = r_refdef.viewposition - mat[3]; + org = r_refdef.frame.position - mat[3]; if (rotated) { vec4f_t temp = org; @@ -744,7 +744,7 @@ get_side (mnode_t *node) { // find the node side on which we are plane_t *plane = node->plane; - vec4f_t org = r_refdef.viewposition; + vec4f_t org = r_refdef.frame.position; if (plane->type < 3) return (org[plane->type] - plane->dist) < 0; @@ -1001,7 +1001,7 @@ spin (mat4_t mat) QuatBlend (sky_rotation[0], sky_rotation[1], blend, q); QuatMult (sky_fix, q, q); Mat4Identity (mat); - VectorNegate (r_refdef.viewposition, mat + 12); + VectorNegate (r_refdef.frame.position, mat + 12); QuatToMatrix (q, m, 1, 1); Mat4Mult (m, mat, mat); } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index e1313ed1c..d13196908 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -100,11 +100,7 @@ glsl_R_SetupFrame (void) EntQueue_Clear (r_ent_queue); r_framecount++; - vec4f_t position = r_refdef.viewposition; - vec4f_t rotation = r_refdef.viewrotation; - VectorCopy (qvmulf (rotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); - VectorCopy (qvmulf (rotation, (vec4f_t) { 0,-1, 0, 0 }), vright); - VectorCopy (qvmulf (rotation, (vec4f_t) { 0, 0, 1, 0 }), vup); + vec4f_t position = r_refdef.frame.position; R_SetFrustum (); @@ -121,7 +117,6 @@ R_SetupView (void) { 0, 1, 0, 0}, { 0, 0, 0, 1}, }; - vec4f_t offset = { 0, 0, 0, 1 }; x = r_refdef.vrect.x; y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); @@ -129,11 +124,7 @@ R_SetupView (void) h = r_refdef.vrect.height; qfeglViewport (x, y, w, h); - mat4fquat (glsl_view, qconjf (r_refdef.viewrotation)); - mmulf (glsl_view, z_up, glsl_view); - offset = -r_refdef.viewposition; - offset[3] = 1; - glsl_view[3] = mvmulf (glsl_view, offset); + mmulf (glsl_view, z_up, r_refdef.camera_inverse); qfeglEnable (GL_CULL_FACE); qfeglEnable (GL_DEPTH_TEST); diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 682846c38..81473369c 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -251,7 +251,8 @@ draw_qf_particles (void) // LordHavoc: particles should not affect zbuffer qfeglDepthMask (GL_FALSE); - minparticledist = DotProduct (r_refdef.viewposition, vpn) + + minparticledist = DotProduct (r_refdef.frame.position, + r_refdef.frame.forward) + r_particles_nearclip->value; vacount = 0; @@ -261,7 +262,7 @@ draw_qf_particles (void) particle_t *p = &r_psystem.particles[i]; // Don't render particles too close to us. // Note, we must still do physics and such on them. - if (!(DotProduct (p->pos, vpn) < minparticledist)) { + if (!(DotProduct (p->pos, r_refdef.frame.forward) < minparticledist)) { at = (byte *) &d_8to24table[(byte) p->icolor]; VA[0].color[0] = at[0]; VA[0].color[1] = at[1]; @@ -306,8 +307,8 @@ draw_qf_particles (void) scale = p->scale; - VectorScale (vup, scale, up_scale); - VectorScale (vright, scale, right_scale); + VectorScale (r_refdef.frame.up, scale, up_scale); + VectorScale (r_refdef.frame.right, scale, right_scale); VectorAdd (right_scale, up_scale, up_right_scale); VectorSubtract (right_scale, up_scale, down_right_scale); @@ -370,7 +371,8 @@ draw_id_particles (void) qfeglEnable (GL_TEXTURE_2D); qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); - minparticledist = DotProduct (r_refdef.viewposition, vpn) + + minparticledist = DotProduct (r_refdef.frame.position, + r_refdef.frame.forward) + r_particles_nearclip->value; vacount = 0; @@ -380,7 +382,7 @@ draw_id_particles (void) particle_t *p = &r_psystem.particles[i]; // Don't render particles too close to us. // Note, we must still do physics and such on them. - if (!(DotProduct (p->pos, vpn) < minparticledist)) { + if (!(DotProduct (p->pos, r_refdef.frame.forward) < minparticledist)) { VA[0].color[0] = (byte) p->icolor; VectorCopy (p->pos, VA[0].vertex); VA++; diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 61ab28937..fc4cf8be7 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -229,7 +229,7 @@ glsl_R_DrawSprite (entity_t *ent) }; vec4f_t origin = Transform_GetWorldPosition (ent->transform); - cameravec = r_refdef.viewposition - origin; + cameravec = r_refdef.frame.position - origin; if (!R_BillboardFrame (ent, sprite->type, &cameravec[0], &svup[0], &svright[0], &svpn[0])) { diff --git a/libs/video/renderer/r_billboard.c b/libs/video/renderer/r_billboard.c index d66d954ad..bd0afa7d1 100644 --- a/libs/video/renderer/r_billboard.c +++ b/libs/video/renderer/r_billboard.c @@ -47,7 +47,7 @@ int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, - vec3_t bbup, vec3_t bbright, vec3_t bbpn) + vec3_t bbup, vec3_t bbright, vec3_t bbfwd) { vec3_t tvec; float dot; @@ -66,28 +66,26 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, //CrossProduct(bbup, -cameravec, bbright) VectorSet (tvec[1], -tvec[0], 0, bbright); VectorNormalize (bbright); - //CrossProduct (bbright, bbup, bbpn) - VectorSet (-bbright[1], bbright[0], 0, bbpn); + //CrossProduct (bbright, bbup, bbfwd) + VectorSet (-bbright[1], bbright[0], 0, bbfwd); break; case SPR_VP_PARALLEL: // the billboard always has the same orientation as the camera - VectorCopy (vup, bbup); - VectorCopy (vright, bbright); - VectorCopy (vpn, bbpn); + VectorCopy (r_refdef.frame.up, bbup); + VectorCopy (r_refdef.frame.right, bbright); + VectorCopy (r_refdef.frame.forward, bbfwd); break; case SPR_VP_PARALLEL_UPRIGHT: // the billboar has its up vector parallel with world up, and // its right vector parallel with the view plane. // Undefined if the camera is looking straight up or down. - dot = vpn[2]; // DotProduct (vpn, world up) + dot = r_refdef.frame.forward[2]; if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) return 0; VectorSet (0, 0, 1, bbup); - //CrossProduct(bbup, vpn, bbright) - VectorSet (vpn[1], -vpn[0], 0, bbright); + VectorSet (r_refdef.frame.forward[1], -r_refdef.frame.forward[0], 0, bbright); VectorNormalize (bbright); - //CrossProduct (bbright, bbup, bbpn) - VectorSet (-bbright[1], bbright[0], 0, bbpn); + VectorSet (-bbright[1], bbright[0], 0, bbfwd); break; case SPR_ORIENTED: { @@ -95,7 +93,7 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, // entity's orientation. mat4f_t mat; Transform_GetWorldMatrix (ent->transform, mat); - VectorCopy (mat[0], bbpn); + VectorCopy (mat[0], bbfwd); VectorNegate (mat[1], bbright); VectorCopy (mat[2], bbup); } @@ -104,13 +102,15 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, { // The billboard is rotated relative to the camera using // the entity's local rotation. - vec4f_t rot = Transform_GetLocalRotation (ent->transform); + mat4f_t entmat; + mat4f_t spmat; + Transform_GetLocalMatrix (ent->transform, entmat); // FIXME needs proper testing (need to find, make, or fake a // parallel oriented sprite) - rot = qmulf (r_refdef.viewrotation, rot); - QuatMultVec (&rot[0], vpn, bbpn); - QuatMultVec (&rot[0], vright, bbright); - QuatMultVec (&rot[0], vup, bbup); + mmulf (spmat, r_refdef.camera, entmat); + VectorCopy (spmat[0], bbfwd); + VectorNegate (spmat[1], bbright); + VectorCopy (spmat[1], bbup); } break; default: diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index 81c92169c..7c890dcb7 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -95,7 +95,7 @@ R_ZGraph (void) else w = 256; - height[r_framecount & 255] = ((int) r_refdef.viewposition[2]) & 31; + height[r_framecount & 255] = ((int) r_refdef.frame.position[2]) & 31; x = 0; vr_funcs->R_LineGraph (x, r_refdef.vrect.height - 2, height, diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index ba3b260a3..bf05d12aa 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -67,11 +67,6 @@ vec3_t r_entorigin; // the currently rendering entity in world // coordinates entity_t r_worldentity; -// view origin -vec3_t vup, base_vup; -vec3_t vpn, base_vpn; -vec3_t vright, base_vright; - // screen size info refdef_t r_refdef; @@ -99,21 +94,24 @@ void R_SetFrustum (void) { int i; + vec4f_t vright = r_refdef.frame.right; + vec4f_t vfwd = r_refdef.frame.forward; + vec4f_t vup = r_refdef.frame.up; // rotate VPN right by FOV_X/2 degrees - RotatePointAroundVector (frustum[0].normal, vup, vpn, + RotatePointAroundVector (frustum[0].normal, &vup[0], &vfwd[0], -(90 - r_refdef.fov_x / 2)); // rotate VPN left by FOV_X/2 degrees - RotatePointAroundVector (frustum[1].normal, vup, vpn, + RotatePointAroundVector (frustum[1].normal, &vup[0], &vfwd[0], 90 - r_refdef.fov_x / 2); // rotate VPN up by FOV_Y/2 degrees - RotatePointAroundVector (frustum[2].normal, vright, vpn, + RotatePointAroundVector (frustum[2].normal, &vright[0], &vfwd[0], 90 - r_refdef.fov_y / 2); // rotate VPN down by FOV_Y/2 degrees - RotatePointAroundVector (frustum[3].normal, vright, vpn, + RotatePointAroundVector (frustum[3].normal, &vright[0], &vfwd[0], -(90 - r_refdef.fov_y / 2)); - vec4f_t origin = r_refdef.viewposition; + vec4f_t origin = r_refdef.frame.position; for (i = 0; i < 4; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (origin, frustum[i].normal); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index a345e2df9..e174039aa 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -161,12 +161,23 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) } if (camera) { - r_data->refdef->viewposition = Transform_GetWorldPosition (camera); - r_data->refdef->viewrotation = Transform_GetWorldRotation (camera); + Transform_GetWorldMatrix (camera, r_data->refdef->camera); + Transform_GetWorldInverse (camera, r_data->refdef->camera_inverse); } else { - r_data->refdef->viewposition = (vec4f_t) { 0, 0, 0, 1 }; - r_data->refdef->viewrotation = (vec4f_t) { 0, 0, 0, 1 }; + mat4fidentity (r_data->refdef->camera); + mat4fidentity (r_data->refdef->camera_inverse); } + // FIXME pre-rotate the camera 90 degrees about the z axis such that the + // camera forward vector (camera Y) points along the world +X axis and the + // camera right vector (camera X) points along the world -Y axis. This + // should not be necessary here but is due to AngleVectors (and thus + // AngleQuat for compatibility) treating X as forward and Y as left (or -Y + // as right). Fixing this would take an audit of the usage of both, but is + // probably worthwhile in the long run. + r_data->refdef->frame.mat[0] = -r_data->refdef->camera[1]; + r_data->refdef->frame.mat[1] = r_data->refdef->camera[0]; + r_data->refdef->frame.mat[2] = r_data->refdef->camera[2]; + r_data->refdef->frame.mat[3] = r_data->refdef->camera[3]; r_data->realtime = realtime; scr_copytop = r_data->scr_copyeverything = 0; diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 91c0b2f53..ec2c186e6 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -151,7 +151,7 @@ D_DrawSurfaces (void) msurface_t *pface; surfcache_t *pcurrentcache; vec3_t world_transformed_modelorg; - vec3_t local_modelorg; + vec4f_t local_modelorg; TransformVector (modelorg, transformed_modelorg); VectorCopy (transformed_modelorg, world_transformed_modelorg); @@ -208,9 +208,9 @@ D_DrawSurfaces (void) // TODO: store once at start of frame transform_t *transform = s->entity->transform; transform = s->entity->transform; - VectorSubtract (r_refdef.viewposition, - Transform_GetWorldPosition (transform), local_modelorg); - TransformVector (local_modelorg, transformed_modelorg); + local_modelorg = r_refdef.frame.position - + Transform_GetWorldPosition (transform); + TransformVector (&local_modelorg[0], transformed_modelorg); R_RotateBmodel (transform); // FIXME: don't mess with the // frustum, make entity passed in @@ -228,7 +228,7 @@ D_DrawSurfaces (void) VectorCopy (world_transformed_modelorg, transformed_modelorg); - VectorCopy (base_vpn, vpn); + VectorCopy (base_vfwd, vfwd); VectorCopy (base_vup, vup); VectorCopy (base_vright, vright); VectorCopy (base_modelorg, modelorg); @@ -239,9 +239,9 @@ D_DrawSurfaces (void) // FIXME: we don't want to do all this for every polygon! // TODO: store once at start of frame transform_t *transform = s->entity->transform; - VectorSubtract (r_refdef.viewposition, - Transform_GetWorldPosition (transform), local_modelorg); - TransformVector (local_modelorg, transformed_modelorg); + local_modelorg = r_refdef.frame.position - + Transform_GetWorldPosition (transform); + TransformVector (&local_modelorg[0], transformed_modelorg); R_RotateBmodel (transform); // FIXME: don't mess with the // frustum, make entity passed in @@ -270,7 +270,7 @@ D_DrawSurfaces (void) VectorCopy (world_transformed_modelorg, transformed_modelorg); - VectorCopy (base_vpn, vpn); + VectorCopy (base_vfwd, vfwd); VectorCopy (base_vup, vup); VectorCopy (base_vright, vright); VectorCopy (base_modelorg, modelorg); diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index c6cd5832d..5a3a3443f 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -53,9 +53,9 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) wu = 8192.0 * (float) (u - half_width) / temp; wv = 8192.0 * (float) (half_height - v) / temp; - end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0]; - end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1]; - end[2] = 4096 * vpn[2] + wu * vright[2] + wv * vup[2]; + end[0] = 4096 * vfwd[0] + wu * vright[0] + wv * vup[0]; + end[1] = 4096 * vfwd[1] + wu * vright[1] + wv * vup[1]; + end[2] = 4096 * vfwd[2] + wu * vright[2] + wv * vup[2]; end[2] *= 3; VectorNormalize (end); diff --git a/libs/video/renderer/sw/d_sprite.c b/libs/video/renderer/sw/d_sprite.c index 7f0b20ce6..04f994f4c 100644 --- a/libs/video/renderer/sw/d_sprite.c +++ b/libs/video/renderer/sw/d_sprite.c @@ -328,12 +328,12 @@ D_SpriteCalculateGradients (const vec3_t relvieworg) vec3_t p_normal, p_saxis, p_taxis, p_temp1; float distinv; - TransformVector (r_spritedesc.vpn, p_normal); + TransformVector (r_spritedesc.vfwd, p_normal); TransformVector (r_spritedesc.vright, p_saxis); TransformVector (r_spritedesc.vup, p_taxis); VectorNegate (p_taxis, p_taxis); - distinv = 1.0 / (-DotProduct (relvieworg, r_spritedesc.vpn)); + distinv = 1.0 / (-DotProduct (relvieworg, r_spritedesc.vfwd)); d_sdivzstepu = p_saxis[0] * xscaleinv; d_tdivzstepu = p_taxis[0] * xscaleinv; diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 837d616a4..d8c5dd2e4 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -382,9 +382,9 @@ R_AliasSetUpTransform (entity_t *ent, int trivial_accept) t2matrix[i][2] = alias_up[i]; } - t2matrix[0][3] = r_entorigin[0] - r_refdef.viewposition[0]; - t2matrix[1][3] = r_entorigin[1] - r_refdef.viewposition[1]; - t2matrix[2][3] = r_entorigin[2] - r_refdef.viewposition[2]; + t2matrix[0][3] = r_entorigin[0] - r_refdef.frame.position[0]; + t2matrix[1][3] = r_entorigin[1] - r_refdef.frame.position[1]; + t2matrix[2][3] = r_entorigin[2] - r_refdef.frame.position[2]; // FIXME: can do more efficiently than full concatenation R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); @@ -393,7 +393,7 @@ R_AliasSetUpTransform (entity_t *ent, int trivial_accept) VectorCopy (vright, viewmatrix[0]); VectorCopy (vup, viewmatrix[1]); VectorNegate (viewmatrix[1], viewmatrix[1]); - VectorCopy (vpn, viewmatrix[2]); + VectorCopy (vfwd, viewmatrix[2]); // viewmatrix[0][3] = 0; // viewmatrix[1][3] = 0; diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 1fbab1168..47771697a 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -87,7 +87,7 @@ R_RotateBmodel (transform_t *transform) // rotate modelorg and the transformation matrix R_EntityRotate (modelorg); - R_EntityRotate (vpn); + R_EntityRotate (vfwd); R_EntityRotate (vright); R_EntityRotate (vup); @@ -360,7 +360,7 @@ get_side (mnode_t *node) { // find which side of the node we are on plane_t *plane = node->plane; - vec4f_t org = r_refdef.viewposition; + vec4f_t org = r_refdef.frame.position; if (plane->type < 3) return (org[plane->type] - plane->dist) < 0; diff --git a/libs/video/renderer/sw/sw_rdrawa.S b/libs/video/renderer/sw/sw_rdrawa.S index f7b9a4acd..7c4ac232f 100644 --- a/libs/video/renderer/sw/sw_rdrawa.S +++ b/libs/video/renderer/sw/sw_rdrawa.S @@ -738,7 +738,7 @@ LTransformAndProject: // // lzi0 = 1.0 / transformed[2]; fld %st(0) // local[0] | local[0] | local[1] | local[2] - fmuls C(vpn)+0 // zm0 | local[0] | local[1] | local[2] + fmuls C(vfwd)+0 // zm0 | local[0] | local[1] | local[2] fld %st(1) // local[0] | zm0 | local[0] | local[1] | // local[2] fmuls C(vright)+0 // xm0 | zm0 | local[0] | local[1] | local[2] @@ -746,7 +746,7 @@ LTransformAndProject: fmuls C(vup)+0 // ym0 | zm0 | xm0 | local[1] | local[2] fld %st(3) // local[1] | ym0 | zm0 | xm0 | local[1] | // local[2] - fmuls C(vpn)+4 // zm1 | ym0 | zm0 | xm0 | local[1] | + fmuls C(vfwd)+4 // zm1 | ym0 | zm0 | xm0 | local[1] | // local[2] fld %st(4) // local[1] | zm1 | ym0 | zm0 | xm0 | // local[1] | local[2] @@ -763,7 +763,7 @@ LTransformAndProject: faddp %st(0),%st(4) // ym0 | zm2 | ym1 | xm2 | local[2] faddp %st(0),%st(2) // zm2 | ym2 | xm2 | local[2] fld %st(3) // local[2] | zm2 | ym2 | xm2 | local[2] - fmuls C(vpn)+8 // zm3 | zm2 | ym2 | xm2 | local[2] + fmuls C(vfwd)+8 // zm3 | zm2 | ym2 | xm2 | local[2] fld %st(4) // local[2] | zm3 | zm2 | ym2 | xm2 | local[2] fmuls C(vright)+8 // xm3 | zm3 | zm2 | ym2 | xm2 | local[2] fxch %st(5) // local[2] | zm3 | zm2 | ym2 | xm2 | xm3 diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index ad41ab405..b81c0951e 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -263,15 +263,15 @@ R_IQMSetUpTransform (entity_t *ent, int trivial_accept) rotationmatrix[i][2] = up[i]; } - rotationmatrix[0][3] = r_entorigin[0] - r_refdef.viewposition[0]; - rotationmatrix[1][3] = r_entorigin[1] - r_refdef.viewposition[1]; - rotationmatrix[2][3] = r_entorigin[2] - r_refdef.viewposition[2]; + rotationmatrix[0][3] = r_entorigin[0] - r_refdef.frame.position[0]; + rotationmatrix[1][3] = r_entorigin[1] - r_refdef.frame.position[1]; + rotationmatrix[2][3] = r_entorigin[2] - r_refdef.frame.position[2]; // TODO: should be global, set when vright, etc., set VectorCopy (vright, viewmatrix[0]); VectorCopy (vup, viewmatrix[1]); VectorNegate (viewmatrix[1], viewmatrix[1]); - VectorCopy (vpn, viewmatrix[2]); + VectorCopy (vfwd, viewmatrix[2]); // viewmatrix[0][3] = 0; // viewmatrix[1][3] = 0; diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 98e98f4d6..1dd5ffe87 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -107,6 +107,10 @@ int r_drawnpolycount; int *pfrustum_indexes[4]; int r_frustum_indexes[4 * 6]; +vec3_t vup, base_vup; +vec3_t vfwd, base_vfwd; +vec3_t vright, base_vright; + float r_aliastransition, r_resfudge; static float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; @@ -581,7 +585,7 @@ R_DrawBrushEntitiesOnList (void) if (clipflags != BMODEL_FULLY_CLIPPED) { mod_brush_t *brush = &clmodel->brush; VectorCopy (origin, r_entorigin); - VectorSubtract (r_refdef.viewposition, r_entorigin, modelorg); + VectorSubtract (r_refdef.frame.position, r_entorigin, modelorg); r_pcurrentvertbase = brush->vertexes; @@ -631,7 +635,7 @@ R_DrawBrushEntitiesOnList (void) // put back world rotation and frustum clipping // FIXME: R_RotateBmodel should just work off base_vxx - VectorCopy (base_vpn, vpn); + VectorCopy (base_vfwd, vfwd); VectorCopy (base_vup, vup); VectorCopy (base_vright, vright); VectorCopy (base_modelorg, modelorg); diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index 9c5d05054..c3f95b084 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -122,9 +122,9 @@ R_TransformFrustum (void) v[1] = -screenedge[i].normal[0]; v[2] = screenedge[i].normal[1]; - v2[0] = v[1] * vright[0] + v[2] * vup[0] + v[0] * vpn[0]; - v2[1] = v[1] * vright[1] + v[2] * vup[1] + v[0] * vpn[1]; - v2[2] = v[1] * vright[2] + v[2] * vup[2] + v[0] * vpn[2]; + v2[0] = v[1] * vright[0] + v[2] * vup[0] + v[0] * vfwd[0]; + v2[1] = v[1] * vright[1] + v[2] * vup[1] + v[0] * vfwd[1]; + v2[2] = v[1] * vright[2] + v[2] * vup[2] + v[0] * vfwd[2]; VectorCopy (v2, view_clipplanes[i].normal); @@ -142,7 +142,7 @@ TransformVector (const vec3_t in, vec3_t out) { out[0] = DotProduct (in, vright); out[1] = DotProduct (in, vup); - out[2] = DotProduct (in, vpn); + out[2] = DotProduct (in, vfwd); } #endif @@ -183,13 +183,12 @@ R_SetupFrame (void) numbtofpolys = 0; // build the transformation matrix for the given view angles - VectorCopy (r_refdef.viewposition, modelorg); + VectorCopy (r_refdef.frame.position, modelorg); - vec4f_t position = r_refdef.viewposition; - vec4f_t rotation = r_refdef.viewrotation; - VectorCopy (qvmulf (rotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); - VectorCopy (qvmulf (rotation, (vec4f_t) { 0, -1, 0, 0 }), vright); - VectorCopy (qvmulf (rotation, (vec4f_t) { 0, 0, 1, 0 }), vup); + vec4f_t position = r_refdef.frame.position; + VectorCopy (r_refdef.frame.right, vright); + VectorCopy (r_refdef.frame.forward, vfwd); + VectorCopy (r_refdef.frame.up, vup); R_SetFrustum (); // current viewleaf @@ -248,7 +247,7 @@ R_SetupFrame (void) R_TransformFrustum (); // save base values - VectorCopy (vpn, base_vpn); + VectorCopy (vfwd, base_vfwd); VectorCopy (vright, base_vright); VectorCopy (vup, base_vup); VectorCopy (modelorg, base_modelorg); diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index b64f848b3..c0526b3ee 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -56,8 +56,8 @@ R_DrawParticles (void) { VectorScale (vright, xscaleshrink, r_pright); VectorScale (vup, yscaleshrink, r_pup); - VectorCopy (vpn, r_ppn); - VectorCopy (r_refdef.viewposition, r_porigin); + VectorCopy (vfwd, r_ppn); + VectorCopy (r_refdef.frame.position, r_porigin); R_RunParticles (vr_data.frametime); diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index a1cdf0663..5f09dea40 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -60,7 +60,7 @@ R_RotateSprite (const vec3_t relvieworg, float beamlength, vec3_t org) if (beamlength == 0.0) return; - VectorScale (r_spritedesc.vpn, -beamlength, vec); + VectorScale (r_spritedesc.vfwd, -beamlength, vec); VectorAdd (r_entorigin, vec, r_entorigin); VectorSubtract (relvieworg, vec, org); } @@ -156,7 +156,7 @@ R_SetupAndDrawSprite (const vec3_t relvieworg) vec3_t left, up, right, down, transformed, local; emitpoint_t outverts[MAXWORKINGVERTS + 1], *pout; - dot = DotProduct (r_spritedesc.vpn, relvieworg); + dot = DotProduct (r_spritedesc.vfwd, relvieworg); // backface cull if (dot >= 0) @@ -211,7 +211,7 @@ R_SetupAndDrawSprite (const vec3_t relvieworg) r_spritedesc.nearzi = -999999; for (i = 0; i < nump; i++) { - VectorSubtract (pv, r_refdef.viewposition, local); + VectorSubtract (pv, r_refdef.frame.position, local); TransformVector (local, transformed); if (transformed[2] < NEAR_CLIP) @@ -246,7 +246,7 @@ R_DrawSprite (entity_t *ent) msprite_t *sprite = ent->renderer.model->cache.data; vec3_t relvieworg; - VectorSubtract (r_refdef.viewposition, r_entorigin, relvieworg); + VectorSubtract (r_refdef.frame.position, r_entorigin, relvieworg); r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, &ent->animation); @@ -256,7 +256,7 @@ R_DrawSprite (entity_t *ent) if (!R_BillboardFrame (ent, sprite->type, relvieworg, r_spritedesc.vup, r_spritedesc.vright, - r_spritedesc.vpn)) { + r_spritedesc.vfwd)) { // the orientation is undefined so can't draw the sprite return; } diff --git a/libs/video/renderer/sw/transform.S b/libs/video/renderer/sw/transform.S index f25e78630..2c0ec053c 100644 --- a/libs/video/renderer/sw/transform.S +++ b/libs/video/renderer/sw/transform.S @@ -77,31 +77,31 @@ C(TransformVector): flds (%eax) // in[0] | in[0]*vright[0] fmuls C(vup) // in[0]*vup[0] | in[0]*vright[0] flds (%eax) // in[0] | in[0]*vup[0] | in[0]*vright[0] - fmuls C(vpn) // in[0]*vpn[0] | in[0]*vup[0] | in[0]*vright[0] + fmuls C(vfwd) // in[0]*vfwd[0] | in[0]*vup[0] | in[0]*vright[0] flds 4(%eax) // in[1] | ... fmuls C(vright)+4 // in[1]*vright[1] | ... flds 4(%eax) // in[1] | in[1]*vright[1] | ... fmuls C(vup)+4 // in[1]*vup[1] | in[1]*vright[1] | ... flds 4(%eax) // in[1] | in[1]*vup[1] | in[1]*vright[1] | ... - fmuls C(vpn)+4 // in[1]*vpn[1] | in[1]*vup[1] | in[1]*vright[1] | ... - fxch %st(2) // in[1]*vright[1] | in[1]*vup[1] | in[1]*vpn[1] | ... + fmuls C(vfwd)+4 // in[1]*vfwd[1] | in[1]*vup[1] | in[1]*vright[1] | ... + fxch %st(2) // in[1]*vright[1] | in[1]*vup[1] | in[1]*vfwd[1] | ... - faddp %st(0),%st(5) // in[1]*vup[1] | in[1]*vpn[1] | ... - faddp %st(0),%st(3) // in[1]*vpn[1] | ... - faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum + faddp %st(0),%st(5) // in[1]*vup[1] | in[1]*vfwd[1] | ... + faddp %st(0),%st(3) // in[1]*vfwd[1] | ... + faddp %st(0),%st(1) // vfwd | vup_accum | vright_accum flds 8(%eax) // in[2] | ... fmuls C(vright)+8 // in[2]*vright[2] | ... flds 8(%eax) // in[2] | in[2]*vright[2] | ... fmuls C(vup)+8 // in[2]*vup[2] | in[2]*vright[2] | ... flds 8(%eax) // in[2] | in[2]*vup[2] | in[2]*vright[2] | ... - fmuls C(vpn)+8 // in[2]*vpn[2] | in[2]*vup[2] | in[2]*vright[2] | ... - fxch %st(2) // in[2]*vright[2] | in[2]*vup[2] | in[2]*vpn[2] | ... + fmuls C(vfwd)+8 // in[2]*vfwd[2] | in[2]*vup[2] | in[2]*vright[2] | ... + fxch %st(2) // in[2]*vright[2] | in[2]*vup[2] | in[2]*vfwd[2] | ... - faddp %st(0),%st(5) // in[2]*vup[2] | in[2]*vpn[2] | ... - faddp %st(0),%st(3) // in[2]*vpn[2] | ... - faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum + faddp %st(0),%st(5) // in[2]*vup[2] | in[2]*vfwd[2] | ... + faddp %st(0),%st(3) // in[2]*vfwd[2] | ... + faddp %st(0),%st(1) // vfwd | vup_accum | vright_accum fstps 8(%edx) // out[2] fstps 4(%edx) // out[1] diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 773acae04..17aebcb51 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -615,7 +615,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) return; } - org = r_refdef.viewposition - mat[3]; + org = r_refdef.frame.position - mat[3]; if (rotated) { vec4f_t temp = org; @@ -653,7 +653,7 @@ get_side (mnode_t *node) { // find the node side on which we are plane_t *plane = node->plane; - vec4f_t org = r_refdef.viewposition; + vec4f_t org = r_refdef.frame.position; if (plane->type < 3) return (org[plane->type] - plane->dist) < 0; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 931995bb2..771c3553f 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -160,7 +160,7 @@ update_lights (vulkan_ctx_t *ctx) light_data->distFactor2 = 1 / 16384.0; light_data->lightCount = 0; - R_FindNearLights (&r_refdef.viewposition[0], MaxLights - 1, lights); + R_FindNearLights (&r_refdef.frame.position[0], MaxLights - 1, lights); for (int i = 0; i < MaxLights - 1; i++) { if (!lights[i]) { break; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 9cfa136b0..a1fa92bae 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -70,14 +70,9 @@ setup_frame (vulkan_ctx_t *ctx) EntQueue_Clear (r_ent_queue); r_framecount++; - vec4f_t position = r_refdef.viewposition; - vec4f_t rotation = r_refdef.viewrotation; - VectorCopy (qvmulf (rotation, (vec4f_t) { 1, 0, 0, 0 }), vpn); - VectorCopy (qvmulf (rotation, (vec4f_t) { 0, -1, 0, 0 }), vright); - VectorCopy (qvmulf (rotation, (vec4f_t) { 0, 0, 1, 0 }), vup); - R_SetFrustum (); + vec4f_t position = r_refdef.frame.position; r_viewleaf = Mod_PointInLeaf (&position[0], r_worldentity.renderer.model); } diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 5c0fc0a91..40ad0c066 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -72,7 +72,6 @@ setup_view (vulkan_ctx_t *ctx) { 0,-1, 0, 0}, { 0, 0, 0, 1}, }; - vec4f_t offset = { 0, 0, 0, 1 }; /*x = r_refdef.vrect.x; y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); @@ -80,11 +79,7 @@ setup_view (vulkan_ctx_t *ctx) h = r_refdef.vrect.height; qfeglViewport (x, y, w, h);*/ - mat4fquat (view, qconjf (r_refdef.viewrotation)); - mmulf (view, z_up, view); - offset = -r_refdef.viewposition; - offset[3] = 1; - view[3] = mvmulf (view, offset); + mmulf (view, z_up, r_refdef.camera_inverse); Vulkan_SetViewMatrix (ctx, view); } @@ -108,7 +103,7 @@ setup_sky (vulkan_ctx_t *ctx) q = Blend (mctx->sky_rotation[0], mctx->sky_rotation[1], blend); q = normalf (qmulf (mctx->sky_fix, q)); mat4fidentity (mat); - VectorNegate (r_refdef.viewposition, mat[3]); + VectorNegate (r_refdef.frame.position, mat[3]); mat4fquat (m, q); mmulf (mat, m, mat); Vulkan_SetSkyMatrix (ctx, mat); diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index c5b0aed4e..77c02d30c 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -119,7 +119,7 @@ Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) frame = (ptrdiff_t) R_GetSpriteFrame (sprite, animation); mat[3] = Transform_GetWorldPosition (ent->transform); - vec4f_t cameravec = r_refdef.viewposition - mat[3]; + vec4f_t cameravec = r_refdef.frame.position - mat[3]; R_BillboardFrame (ent, sprite->type, &cameravec[0], &mat[2][0], &mat[1][0], &mat[0][0]); mat[0] = -mat[0]; From ef850d97ea7ce4862b921422adb31f762c57a4cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Mar 2022 11:11:18 +0900 Subject: [PATCH 2527/3664] [qfmdl] Speed up vertex import slightly Well, not measured, but I expect that python allocates the destination list before executing the loop (I've forgotten the name of that coding form). --- tools/io_mesh_qfmdl/import_mdl.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index d27ed45a1..2a7da9a93 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -31,15 +31,13 @@ def make_verts(mdl, framenum, subframenum=0): frame = mdl.frames[framenum] if frame.type: frame = frame.frames[subframenum] - verts = [] s = Vector(mdl.scale) o = Vector(mdl.scale_origin) m = Matrix(((s.x, 0, 0,o.x), ( 0,s.y, 0,o.y), ( 0, 0,s.z,o.z), ( 0, 0, 0, 1))) - for v in frame.verts: - verts.append(m @ Vector(v.r)) + verts = [m @ Vector(v.r) for v in frame.verts] return verts def make_faces(mdl): From 16440bce2d27263612a1ade183f6f841f5eee62a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Mar 2022 11:51:50 +0900 Subject: [PATCH 2528/3664] [mathlib] Clean up AngleVectors comments a little They're still slightly confusing, but the situation itself is confusing, but the comments should be a little more helpful now as they are more explicit about the orientation of the matrices and just which axis points where. --- libs/util/mathlib.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index eca73126a..e047fca89 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -504,13 +504,21 @@ BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, plane_t *p) #endif /* - angles is a left(?) handed system: 'pitch yaw roll' with x (pitch) axis to - the right, y (yaw) axis up and z (roll) axis forward. + angles is a left handed system: 'pitch yaw roll' with x (pitch) axis to + the right, y (yaw) axis up and z (roll) axis forward. However, the + rotations themselves are right-handed in that they follow the right-hand + rule for the world axes: pitch around +y, yaw around +z, and roll around + +x. - The math in AngleVectors has the entity frame as left handed with x - (forward) axis forward, y (right) axis to the right and z (up) up. However, - the world is a right handed system with x forward, y to the left and - z up, thus the negation for right. + This results in the entity frame having forward pointed along the world +x + axis, right along the world -y axis, and up along the world +z axis. + Whether this means the entity frame is left-handed depends on whether + forward is local X and right is local Y (left handed), or forward is local + Y and right is local X (right handed). + + NOTE: these matrices have forward, left and up vectors horizontal rather + than vertical and are thus the inverse of the matrices to produce the + actual rotation. pitch = cp 0 -sp @@ -551,11 +559,10 @@ AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) forward[0] = cp * cy; forward[1] = cp * sy; forward[2] = -sp; - // need to flip right because it's a left handed system in a right handed - // world - right[0] = -1 * (sr * sp * cy + cr * -sy); - right[1] = -1 * (sr * sp * sy + cr * cy); - right[2] = -1 * (sr * cp); + // need to flip right because the trig produces +Y but right is -Y + right[0] = -(sr * sp * cy + cr * -sy); + right[1] = -(sr * sp * sy + cr * cy); + right[2] = -(sr * cp); up[0] = (cr * sp * cy + -sr * -sy); up[1] = (cr * sp * sy + -sr * cy); up[2] = cr * cp; From 04ba7243828378c9b3c50c5a243022cfcda40654 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Mar 2022 11:56:10 +0900 Subject: [PATCH 2529/3664] [sw] Clean up alias and iqm matrix setup This removes some FIXMEs and might even speed things up ever so slightly. --- include/r_shared.h | 1 + libs/video/renderer/sw/sw_ralias.c | 49 ++++++++---------------------- libs/video/renderer/sw/sw_riqm.c | 13 +------- libs/video/renderer/sw/sw_rmain.c | 1 + libs/video/renderer/sw/sw_rmisc.c | 4 +++ 5 files changed, 19 insertions(+), 49 deletions(-) diff --git a/include/r_shared.h b/include/r_shared.h index e3e3c585f..d24632139 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -72,6 +72,7 @@ extern byte color_black[4]; extern vec3_t vup, base_vup; extern vec3_t vfwd, base_vfwd; extern vec3_t vright, base_vright; +extern float r_viewmatrix[3][4]; #define NUMSTACKEDGES 2400 //2000 #define MINEDGES NUMSTACKEDGES diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index d8c5dd2e4..f99b2712d 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -61,7 +61,7 @@ auxvert_t *pauxverts; float ziscale; static model_t *pmodel; -static vec3_t alias_forward, alias_right, alias_up; +static vec3_t alias_forward, alias_left, alias_up; static maliasskindesc_t *pskindesc; @@ -356,50 +356,25 @@ static void R_AliasSetUpTransform (entity_t *ent, int trivial_accept) { int i; - float rotationmatrix[3][4], t2matrix[3][4]; - static float tmatrix[3][4]; - static float viewmatrix[3][4]; + float rotationmatrix[3][4]; mat4f_t mat; Transform_GetWorldMatrix (ent->transform, mat); VectorCopy (mat[0], alias_forward); - VectorNegate (mat[1], alias_right); + VectorCopy (mat[1], alias_left); VectorCopy (mat[2], alias_up); - tmatrix[0][0] = pmdl->scale[0]; - tmatrix[1][1] = pmdl->scale[1]; - tmatrix[2][2] = pmdl->scale[2]; - - tmatrix[0][3] = pmdl->scale_origin[0]; - tmatrix[1][3] = pmdl->scale_origin[1]; - tmatrix[2][3] = pmdl->scale_origin[2]; - -// TODO: can do this with simple matrix rearrangement - for (i = 0; i < 3; i++) { - t2matrix[i][0] = alias_forward[i]; - t2matrix[i][1] = -alias_right[i]; - t2matrix[i][2] = alias_up[i]; + rotationmatrix[i][0] = pmdl->scale[0] * alias_forward[i]; + rotationmatrix[i][1] = pmdl->scale[1] * alias_left[i]; + rotationmatrix[i][2] = pmdl->scale[2] * alias_up[i]; + rotationmatrix[i][3] = pmdl->scale_origin[0] * alias_forward[i] + + pmdl->scale_origin[1] * alias_left[i] + + pmdl->scale_origin[2] * alias_up[i] + + r_entorigin[i] - r_refdef.frame.position[i]; } - t2matrix[0][3] = r_entorigin[0] - r_refdef.frame.position[0]; - t2matrix[1][3] = r_entorigin[1] - r_refdef.frame.position[1]; - t2matrix[2][3] = r_entorigin[2] - r_refdef.frame.position[2]; - -// FIXME: can do more efficiently than full concatenation - R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); - -// TODO: should be global, set when vright, etc., set - VectorCopy (vright, viewmatrix[0]); - VectorCopy (vup, viewmatrix[1]); - VectorNegate (viewmatrix[1], viewmatrix[1]); - VectorCopy (vfwd, viewmatrix[2]); - -// viewmatrix[0][3] = 0; -// viewmatrix[1][3] = 0; -// viewmatrix[2][3] = 0; - - R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); + R_ConcatTransforms (r_viewmatrix, rotationmatrix, aliastransform); // do the scaling up of x and y to screen coordinates as part of the transform // for the unclipped case (it would mess up clipping in the clipped case). @@ -603,7 +578,7 @@ R_AliasSetupLighting (alight_t *plighting) // rotate the lighting vector into the model's frame of reference r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward); - r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right); + r_plightvec[1] = DotProduct (plighting->plightvec, alias_left); r_plightvec[2] = DotProduct (plighting->plightvec, alias_up); } diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index b81c0951e..b4851c991 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -246,7 +246,6 @@ R_IQMSetUpTransform (entity_t *ent, int trivial_accept) { int i; float rotationmatrix[3][4]; - static float viewmatrix[3][4]; vec3_t forward, left, up; mat4f_t mat; @@ -267,17 +266,7 @@ R_IQMSetUpTransform (entity_t *ent, int trivial_accept) rotationmatrix[1][3] = r_entorigin[1] - r_refdef.frame.position[1]; rotationmatrix[2][3] = r_entorigin[2] - r_refdef.frame.position[2]; -// TODO: should be global, set when vright, etc., set - VectorCopy (vright, viewmatrix[0]); - VectorCopy (vup, viewmatrix[1]); - VectorNegate (viewmatrix[1], viewmatrix[1]); - VectorCopy (vfwd, viewmatrix[2]); - -// viewmatrix[0][3] = 0; -// viewmatrix[1][3] = 0; -// viewmatrix[2][3] = 0; - - R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); + R_ConcatTransforms (r_viewmatrix, rotationmatrix, aliastransform); // do the scaling up of x and y to screen coordinates as part of the transform // for the unclipped case (it would mess up clipping in the clipped case). diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 1dd5ffe87..19be8c6e0 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -110,6 +110,7 @@ int r_frustum_indexes[4 * 6]; vec3_t vup, base_vup; vec3_t vfwd, base_vfwd; vec3_t vright, base_vright; +float r_viewmatrix[3][4]; float r_aliastransition, r_resfudge; diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index c3f95b084..ebc56a34d 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -252,6 +252,10 @@ R_SetupFrame (void) VectorCopy (vup, base_vup); VectorCopy (modelorg, base_modelorg); + VectorCopy (vright, r_viewmatrix[0]); + VectorNegate (vup, r_viewmatrix[1]); + VectorCopy (vfwd, r_viewmatrix[2]); + R_SetSkyFrame (); R_SetUpFrustumIndexes (); From 56c39c34bae9d3d59861da56f6031c9bb3d68f7b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Mar 2022 14:31:23 +0900 Subject: [PATCH 2530/3664] [renderer] Remove namehack.h Finally. I never liked it (felt bad adding it in the first place), and it has caused confusion with function and global variable names, but it did let me get the render plugins working. --- include/QF/GL/qf_alias.h | 44 +++++++++ include/QF/GL/qf_draw.h | 27 ++++++ include/QF/GL/qf_lightmap.h | 4 +- include/QF/GL/qf_particles.h | 45 +++++++++ include/QF/GL/qf_rlight.h | 3 +- include/QF/GL/qf_rmain.h | 12 ++- include/QF/GL/qf_rsurf.h | 12 ++- include/QF/GL/qf_sky.h | 8 +- include/QF/GL/qf_sprite.h | 37 +++++++ include/QF/GLSL/qf_bsp.h | 2 + include/QF/GLSL/qf_draw.h | 32 +++++- include/QF/GLSL/qf_main.h | 37 +++++++ include/QF/GLSL/qf_particles.h | 10 +- include/QF/GLSL/qf_sprite.h | 3 + include/QF/Makemodule.am | 5 +- libs/video/renderer/Makemodule.am | 2 - libs/video/renderer/gl/gl_draw.c | 3 - libs/video/renderer/gl/gl_dyn_lights.c | 3 - libs/video/renderer/gl/gl_dyn_part.c | 5 +- libs/video/renderer/gl/gl_dyn_textures.c | 3 - libs/video/renderer/gl/gl_graph.c | 4 +- libs/video/renderer/gl/gl_lightmap.c | 3 - libs/video/renderer/gl/gl_mod_alias.c | 4 +- libs/video/renderer/gl/gl_mod_iqm.c | 3 - libs/video/renderer/gl/gl_mod_sprite.c | 4 +- libs/video/renderer/gl/gl_rmain.c | 13 +-- libs/video/renderer/gl/gl_rmisc.c | 66 +++++++------ libs/video/renderer/gl/gl_rsurf.c | 16 ++- libs/video/renderer/gl/gl_sky.c | 3 - libs/video/renderer/gl/gl_sky_clip.c | 3 - libs/video/renderer/gl/gl_textures.c | 3 - libs/video/renderer/gl/gl_warp.c | 3 - libs/video/renderer/gl/namehack.h | 110 --------------------- libs/video/renderer/glsl/glsl_alias.c | 3 - libs/video/renderer/glsl/glsl_bsp.c | 9 +- libs/video/renderer/glsl/glsl_draw.c | 3 - libs/video/renderer/glsl/glsl_iqm.c | 3 - libs/video/renderer/glsl/glsl_lightmap.c | 3 - libs/video/renderer/glsl/glsl_main.c | 52 +++++----- libs/video/renderer/glsl/glsl_particles.c | 3 - libs/video/renderer/glsl/glsl_sprite.c | 7 +- libs/video/renderer/glsl/glsl_textures.c | 3 - libs/video/renderer/glsl/namehack.h | 113 ---------------------- libs/video/renderer/vid_render_gl.c | 6 +- libs/video/renderer/vid_render_glsl.c | 6 +- 45 files changed, 347 insertions(+), 396 deletions(-) create mode 100644 include/QF/GL/qf_alias.h create mode 100644 include/QF/GL/qf_particles.h create mode 100644 include/QF/GL/qf_sprite.h create mode 100644 include/QF/GLSL/qf_main.h delete mode 100644 libs/video/renderer/gl/namehack.h delete mode 100644 libs/video/renderer/glsl/namehack.h diff --git a/include/QF/GL/qf_alias.h b/include/QF/GL/qf_alias.h new file mode 100644 index 000000000..644f58a74 --- /dev/null +++ b/include/QF/GL/qf_alias.h @@ -0,0 +1,44 @@ +/* + qf_alias.h + + GL specific alias model stuff + + Copyright (C) 2012 Bill Currie + + Author: Bill Currie + Date: 2012/1/1 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_GL_qf_alias_h +#define __QF_GL_qf_alias_h + +#include "QF/GL/types.h" + +typedef struct aliasvrt_s { + GLshort st[2]; + GLshort normal[3]; + GLushort vertex[3]; +} aliasvrt_t; + +struct entity_s; +void gl_R_DrawAliasModel (struct entity_s *ent); + +#endif//__QF_GL_qf_alias_h diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index 5644e6a74..65f1a03da 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -28,8 +28,35 @@ #ifndef __gl_draw_h #define __gl_draw_h +struct qpic_s; + +void gl_Draw_Init (void); +void gl_Draw_Shutdown (void); +void gl_Draw_Character (int x, int y, unsigned ch); +void gl_Draw_String (int x, int y, const char *str); +void gl_Draw_nString (int x, int y, const char *str, int count); +void gl_Draw_AltString (int x, int y, const char *str); +void gl_Draw_ConsoleBackground (int lines, byte alpha); +void gl_Draw_Crosshair (void); +void gl_Draw_CrosshairAt (int ch, int x, int y); +void gl_Draw_TileClear (int x, int y, int w, int h); +void gl_Draw_Fill (int x, int y, int w, int h, int c); +void gl_Draw_TextBox (int x, int y, int width, int lines, byte alpha); +void gl_Draw_FadeScreen (void); +void gl_Draw_BlendScreen (quat_t color); +struct qpic_s *gl_Draw_CachePic (const char *path, qboolean alpha); +void gl_Draw_UncachePic (const char *path); +struct qpic_s *gl_Draw_MakePic (int width, int height, const byte *data); +void gl_Draw_DestroyPic (struct qpic_s *pic); +struct qpic_s *gl_Draw_PicFromWad (const char *name); +void gl_Draw_Pic (int x, int y, struct qpic_s *pic); +void gl_Draw_Picf (float x, float y, struct qpic_s *pic); +void gl_Draw_SubPic(int x, int y, struct qpic_s *pic, + int srcx, int srcy, int width, int height); + void GL_Set2D (void); void GL_Set2DScaled (void); +void GL_End2D (void); void GL_DrawReset (void); void GL_FlushText (void); diff --git a/include/QF/GL/qf_lightmap.h b/include/QF/GL/qf_lightmap.h index 6125ea57e..102f26313 100644 --- a/include/QF/GL/qf_lightmap.h +++ b/include/QF/GL/qf_lightmap.h @@ -48,8 +48,8 @@ extern glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; void GL_BuildSurfaceDisplayList (msurface_t *fa); void gl_lightmap_init (void); void GL_BuildLightmaps (struct model_s **models, int num_models); -void R_BlendLightmaps (void); -void R_CalcLightmaps (void); +void gl_R_BlendLightmaps (void); +void gl_R_CalcLightmaps (void); struct transform_s; extern void (*gl_R_BuildLightMap) (const struct transform_s *transform, mod_brush_t *brush, msurface_t *surf); diff --git a/include/QF/GL/qf_particles.h b/include/QF/GL/qf_particles.h new file mode 100644 index 000000000..f053e0523 --- /dev/null +++ b/include/QF/GL/qf_particles.h @@ -0,0 +1,45 @@ +/* + qf_particles.h + + GL specific particles stuff + + Copyright (C) 2012 Bill Currie + + Author: Bill Currie + Date: 2012/1/15 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_GL_qf_particles_h +#define __QF_GL_qf_particles_h + +#include "QF/GL/types.h" + +typedef struct { + float texcoord[2]; + float vertex[3]; + byte color[4]; +} partvert_t; + +void gl_R_DrawParticles (void); +void gl_R_Particles_Init_Cvars (void); +void gl_R_InitParticles (void); + +#endif//__QF_GL_qf_particles_h diff --git a/include/QF/GL/qf_rlight.h b/include/QF/GL/qf_rlight.h index 0fdeaf2d8..66e719f78 100644 --- a/include/QF/GL/qf_rlight.h +++ b/include/QF/GL/qf_rlight.h @@ -29,6 +29,7 @@ #define __QF_GL_rlight_h extern float gl_bubble_sintable[], gl_bubble_costable[]; -void R_RenderDlights (void); +void gl_R_RenderDlights (void); +void gl_R_InitBubble (void); #endif // __QF_GL_rlight_h diff --git a/include/QF/GL/qf_rmain.h b/include/QF/GL/qf_rmain.h index 4625b94dc..651a9fff2 100644 --- a/include/QF/GL/qf_rmain.h +++ b/include/QF/GL/qf_rmain.h @@ -35,7 +35,6 @@ struct entity_s; extern qboolean gl_envmap; extern int c_brush_polys, c_alias_polys; -extern float r_world_matrix[16]; extern float gl_modelalpha; //extern vec3_t shadecolor; @@ -43,6 +42,15 @@ extern float gl_modelalpha; extern void gl_multitexture_f (struct cvar_s *var); void glrmain_init (void); -void R_RotateForEntity (struct entity_s *e); +void gl_R_RotateForEntity (struct entity_s *e); + +struct model_s; +void gl_R_NewMap (struct model_s *worldmodel, struct model_s **models, + int num_models); +void gl_R_RenderView (void); +void gl_R_ClearState (void); +void gl_R_ViewChanged (void); +void gl_R_LineGraph (int x, int y, int *h_vals, int count, int height); +int gl_R_InitGraphTextures (int base); #endif // __QF_GL_rmain_h diff --git a/include/QF/GL/qf_rsurf.h b/include/QF/GL/qf_rsurf.h index e799747ee..5a7e4c698 100644 --- a/include/QF/GL/qf_rsurf.h +++ b/include/QF/GL/qf_rsurf.h @@ -41,13 +41,21 @@ extern int gl_mirrortexturenum; // quake texturenum, not gltexturenum struct model_s; struct entity_s; struct msurface_s; +struct mod_brush_s; void gl_lightmap_init (void); void GL_BuildLightmaps (struct model_s **models, int num_models); -void R_DrawBrushModel (struct entity_s *e); -void R_DrawWorld (void); +void gl_R_DrawBrushModel (struct entity_s *e); +void gl_R_DrawWorld (void); +void gl_R_DrawWaterSurfaces (void); void GL_EmitWaterPolys (struct msurface_s *fa); +void gl_R_LoadSkys (const char *sky); + +struct texture_s; +void gl_R_AddTexture (struct texture_s *tx); +void gl_R_ClearTextures (void); +void gl_R_InitSurfaceChains (struct mod_brush_s *brush); #endif // __QF_GL_rsurf_h diff --git a/include/QF/GL/qf_sky.h b/include/QF/GL/qf_sky.h index 2524016b9..f2f030bb4 100644 --- a/include/QF/GL/qf_sky.h +++ b/include/QF/GL/qf_sky.h @@ -36,7 +36,11 @@ extern qboolean gl_skyloaded; extern vec5_t gl_skyvec[6][4]; -void R_DrawSky (void); -void R_DrawSkyChain (const instsurf_t *s); +struct texture_s; + +void gl_R_InitSky (struct texture_s *mt); +void gl_R_DrawSky (void); +void gl_R_DrawSkyChain (const instsurf_t *s); +void gl_R_LoadSkys (const char *skyname); #endif // __QF_GL_sky_h diff --git a/include/QF/GL/qf_sprite.h b/include/QF/GL/qf_sprite.h new file mode 100644 index 000000000..38498d127 --- /dev/null +++ b/include/QF/GL/qf_sprite.h @@ -0,0 +1,37 @@ +/* + qf_sprite.h + + GL specific sprite model stuff + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/7/22 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_GL_qf_sprite_h +#define __QF_GL_qf_sprite_h + +struct entity_s; +void gl_R_InitSprites (void); +extern void (*gl_R_DrawSpriteModel) (struct entity_s *ent); + +#endif//__QF_GL_qf_sprite_h diff --git a/include/QF/GLSL/qf_bsp.h b/include/QF/GLSL/qf_bsp.h index 7e74aa9f7..482484b6a 100644 --- a/include/QF/GLSL/qf_bsp.h +++ b/include/QF/GLSL/qf_bsp.h @@ -68,8 +68,10 @@ struct model_s; void glsl_R_ClearElements (void); void glsl_R_DrawWorld (void); void glsl_R_DrawSky (void); +void glsl_R_DrawWaterSurfaces (void); void glsl_R_RegisterTextures (struct model_s **models, int num_models); void glsl_R_BuildDisplayLists (struct model_s **models, int num_models); void glsl_R_InitBsp (void); +void glsl_R_LoadSkys (const char *sky); #endif//__QF_GLSL_qf_bsp_h diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index aa708a96a..653e2bc5f 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -25,8 +25,34 @@ */ -#ifndef __gl_draw_h -#define __gl_draw_h +#ifndef __QF_GLSL_qf_draw_h +#define __QF_GLSL_qf_draw_h + +struct qpic_s; + +void glsl_Draw_Init (void); +void glsl_Draw_Shutdown (void); +void glsl_Draw_Character (int x, int y, unsigned ch); +void glsl_Draw_String (int x, int y, const char *str); +void glsl_Draw_nString (int x, int y, const char *str, int count); +void glsl_Draw_AltString (int x, int y, const char *str); +void glsl_Draw_ConsoleBackground (int lines, byte alpha); +void glsl_Draw_Crosshair (void); +void glsl_Draw_CrosshairAt (int ch, int x, int y); +void glsl_Draw_TileClear (int x, int y, int w, int h); +void glsl_Draw_Fill (int x, int y, int w, int h, int c); +void glsl_Draw_TextBox (int x, int y, int width, int lines, byte alpha); +void glsl_Draw_FadeScreen (void); +void glsl_Draw_BlendScreen (quat_t color); +struct qpic_s *glsl_Draw_CachePic (const char *path, qboolean alpha); +void glsl_Draw_UncachePic (const char *path); +struct qpic_s *glsl_Draw_MakePic (int width, int height, const byte *data); +void glsl_Draw_DestroyPic (struct qpic_s *pic); +struct qpic_s *glsl_Draw_PicFromWad (const char *name); +void glsl_Draw_Pic (int x, int y, struct qpic_s *pic); +void glsl_Draw_Picf (float x, float y, struct qpic_s *pic); +void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic, + int srcx, int srcy, int width, int height); void GLSL_Set2D (void); void GLSL_Set2DScaled (void); @@ -34,4 +60,4 @@ void GLSL_End2D (void); void GLSL_DrawReset (void); void GLSL_FlushText (void); -#endif//__gl_draw_h +#endif//__QF_GLSL_qf_draw_h diff --git a/include/QF/GLSL/qf_main.h b/include/QF/GLSL/qf_main.h new file mode 100644 index 000000000..c41601802 --- /dev/null +++ b/include/QF/GLSL/qf_main.h @@ -0,0 +1,37 @@ +/* + qf_main.h + + glsl main stuff from the renderer. + + Copyright (C) 2021 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_GLSL_qf_main_h +#define __QF_GLSL_qf_main_h + +void glsl_R_NewMap (model_t *worldmodel, model_t **models, int num_models); +void glsl_R_RenderView (void); +void glsl_R_ClearState (void); +void glsl_R_ViewChanged (void); +void glsl_R_LineGraph (int x, int y, int *h_vals, int count, int height); + +#endif//__QF_GLSL_qf_main_h diff --git a/include/QF/GLSL/qf_particles.h b/include/QF/GLSL/qf_particles.h index 0c42d218e..67fa52049 100644 --- a/include/QF/GLSL/qf_particles.h +++ b/include/QF/GLSL/qf_particles.h @@ -27,8 +27,8 @@ Boston, MA 02111-1307, USA */ -#ifndef __QF_GLSL_qf_bsp_h -#define __QF_GLSL_qf_bsp_h +#ifndef __QF_GLSL_qf_particles_h +#define __QF_GLSL_qf_particles_h #include "QF/GLSL/types.h" @@ -38,4 +38,8 @@ typedef struct { byte color[4]; } partvert_t; -#endif//__QF_GLSL_qf_bsp_h +void glsl_R_DrawParticles (void); +void glsl_R_Particles_Init_Cvars (void); +void glsl_R_InitParticles (void); + +#endif//__QF_GLSL_qf_particles_h diff --git a/include/QF/GLSL/qf_sprite.h b/include/QF/GLSL/qf_sprite.h index af7817b1b..12f14a858 100644 --- a/include/QF/GLSL/qf_sprite.h +++ b/include/QF/GLSL/qf_sprite.h @@ -32,5 +32,8 @@ struct entity_s; void glsl_R_DrawSprite (struct entity_s *ent); +void glsl_R_SpriteBegin (void); +void glsl_R_SpriteEnd (void); +void glsl_R_InitSprites (void); #endif//__QF_GLSL_qf_sprite_h diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 86f135c59..c842cb050 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -80,15 +80,17 @@ include_qf_gl = \ include/QF/GL/defines.h \ include/QF/GL/extensions.h \ include/QF/GL/funcs.h \ + include/QF/GL/qf_alias.h \ include/QF/GL/qf_draw.h \ - include/QF/GL/qf_explosions.h \ include/QF/GL/qf_funcs_list.h \ include/QF/GL/qf_iqm.h \ include/QF/GL/qf_lightmap.h \ + include/QF/GL/qf_particles.h \ include/QF/GL/qf_rlight.h \ include/QF/GL/qf_rmain.h \ include/QF/GL/qf_rsurf.h \ include/QF/GL/qf_sky.h \ + include/QF/GL/qf_sprite.h \ include/QF/GL/qf_textures.h \ include/QF/GL/qf_vid.h \ include/QF/GL/types.h @@ -102,6 +104,7 @@ include_qf_glsl = \ include/QF/GLSL/qf_funcs_list.h \ include/QF/GLSL/qf_iqm.h \ include/QF/GLSL/qf_lightmap.h \ + include/QF/GLSL/qf_main.h \ include/QF/GLSL/qf_particles.h \ include/QF/GLSL/qf_sprite.h \ include/QF/GLSL/qf_textures.h \ diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 710117e1f..1b6bd2ab0 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -84,7 +84,6 @@ libs_video_renderer_librender_gl_la_SOURCES = \ libs/video/renderer/gl/gl_sky_clip.c \ libs/video/renderer/gl/gl_textures.c \ libs/video/renderer/gl/gl_warp.c \ - libs/video/renderer/gl/namehack.h \ libs/video/renderer/gl/qfgl_ext.c \ libs/video/renderer/gl/vid_common_gl.c \ libs/video/renderer/gl/vtxarray.c @@ -119,7 +118,6 @@ libs_video_renderer_librender_glsl_la_SOURCES = \ libs/video/renderer/glsl/glsl_shader.c \ libs/video/renderer/glsl/glsl_sprite.c \ libs/video/renderer/glsl/glsl_textures.c \ - libs/video/renderer/glsl/namehack.h \ libs/video/renderer/glsl/qfglsl.c \ libs/video/renderer/glsl/quakeforge.glsl \ libs/video/renderer/glsl/vid_common_glsl.c diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 7a7bc9048..6d64779d8 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/gl/gl_dyn_lights.c b/libs/video/renderer/gl/gl_dyn_lights.c index 2d006c5cd..6af2287b2 100644 --- a/libs/video/renderer/gl/gl_dyn_lights.c +++ b/libs/video/renderer/gl/gl_dyn_lights.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index a236179dc..097533de0 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -53,7 +50,7 @@ #include "QF/GL/defines.h" #include "QF/GL/funcs.h" -#include "QF/GL/qf_explosions.h" +#include "QF/GL/qf_particles.h" #include "QF/GL/qf_textures.h" #include "QF/GL/qf_vid.h" diff --git a/libs/video/renderer/gl/gl_dyn_textures.c b/libs/video/renderer/gl/gl_dyn_textures.c index 093a1b905..28e7d8ef4 100644 --- a/libs/video/renderer/gl/gl_dyn_textures.c +++ b/libs/video/renderer/gl/gl_dyn_textures.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/gl/gl_graph.c b/libs/video/renderer/gl/gl_graph.c index 821620811..12c5e3774 100644 --- a/libs/video/renderer/gl/gl_graph.c +++ b/libs/video/renderer/gl/gl_graph.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -47,6 +44,7 @@ #include "QF/sys.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" +#include "QF/GL/qf_rmain.h" #include "QF/GL/qf_textures.h" #include "r_internal.h" diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 52cbb00b8..4f2d4a3c8 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -29,9 +29,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 7934b1332..32ff19857 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -55,6 +52,7 @@ #include "QF/GL/defines.h" #include "QF/GL/funcs.h" +#include "QF/GL/qf_alias.h" #include "QF/GL/qf_rlight.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_rsurf.h" diff --git a/libs/video/renderer/gl/gl_mod_iqm.c b/libs/video/renderer/gl/gl_mod_iqm.c index f66c2c7ca..f33828c29 100644 --- a/libs/video/renderer/gl/gl_mod_iqm.c +++ b/libs/video/renderer/gl/gl_mod_iqm.c @@ -31,9 +31,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index 1c37cd2ce..0f710a0b4 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -46,6 +43,7 @@ #include "QF/GL/defines.h" #include "QF/GL/funcs.h" +#include "QF/GL/qf_sprite.h" #include "compat.h" #include "r_internal.h" diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 3a393fa6f..e8caaf3d6 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -56,11 +53,14 @@ #include "QF/GL/defines.h" #include "QF/GL/funcs.h" +#include "QF/GL/qf_alias.h" #include "QF/GL/qf_draw.h" #include "QF/GL/qf_iqm.h" +#include "QF/GL/qf_particles.h" #include "QF/GL/qf_rlight.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_rsurf.h" +#include "QF/GL/qf_sprite.h" #include "QF/GL/qf_vid.h" #include "compat.h" @@ -89,9 +89,6 @@ static unsigned int GLErr_StackOverflow; static unsigned int GLErr_StackUnderflow; static unsigned int GLErr_Unknown; -extern void (*R_DrawSpriteModel) (struct entity_s *ent); - - static unsigned int R_TestErrors (unsigned int numerous) { @@ -258,7 +255,7 @@ R_DrawEntitiesOnList (void) qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray); for (size_t i = 0; i < r_ent_queue->ent_queues[mod_sprite].size; i++) { \ entity_t *ent = r_ent_queue->ent_queues[mod_sprite].a[i]; \ - R_DrawSpriteModel (ent); + gl_R_DrawSpriteModel (ent); } qfglDisable (GL_ALPHA_TEST); } @@ -324,7 +321,7 @@ R_DrawViewModel (void) qfglDepthRange (gldepthmin, gldepthmax); } -void +static void gl_R_SetupFrame (void) { R_AnimateLight (); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 49aef8679..35087b1fb 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -56,8 +53,13 @@ #include "QF/vid.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" +#include "QF/GL/qf_draw.h" +#include "QF/GL/qf_particles.h" +#include "QF/GL/qf_rlight.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_rsurf.h" +#include "QF/GL/qf_sky.h" +#include "QF/GL/qf_sprite.h" #include "QF/GL/qf_textures.h" #include "QF/GL/qf_vid.h" @@ -128,7 +130,7 @@ R_Envmap_f (void) gl_ctx->end_rendering ();*/ } -void +static void gl_R_LoadSky_f (void) { if (Cmd_Argc () != 2) { @@ -139,6 +141,34 @@ gl_R_LoadSky_f (void) gl_R_LoadSkys (Cmd_Argv (1)); } +/* + R_TimeRefresh_f + + For program optimization + LordHavoc: improved appearance and accuracy of timerefresh +*/ +static void +gl_R_TimeRefresh_f (void) +{ +/*FIXME update for simd + double start, stop, time; + int i; + + gl_ctx->end_rendering (); + + start = Sys_DoubleTime (); + for (i = 0; i < 128; i++) { + r_refdef.viewangles[1] = i * (360.0 / 128.0); + gl_R_RenderView (); + gl_ctx->end_rendering (); + } + + stop = Sys_DoubleTime (); + time = stop - start; + Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); +*/ +} + void gl_R_Init (void) { @@ -237,31 +267,3 @@ void gl_R_ViewChanged (void) { } - -/* - R_TimeRefresh_f - - For program optimization - LordHavoc: improved appearance and accuracy of timerefresh -*/ -void -gl_R_TimeRefresh_f (void) -{ -/*FIXME update for simd - double start, stop, time; - int i; - - gl_ctx->end_rendering (); - - start = Sys_DoubleTime (); - for (i = 0; i < 128; i++) { - r_refdef.viewangles[1] = i * (360.0 / 128.0); - gl_R_RenderView (); - gl_ctx->end_rendering (); - } - - stop = Sys_DoubleTime (); - time = stop - start; - Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); -*/ -} diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 5a5bf3476..2e5f1d94a 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -29,9 +29,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -329,9 +326,6 @@ gl_R_DrawWaterSurfaces (void) if (!waterchain) return; - // go back to the world matrix - qfglLoadMatrixf (gl_r_world_matrix); - if (wateralpha < 1.0) { qfglDepthMask (GL_FALSE); color_white[3] = wateralpha * 255; @@ -342,18 +336,20 @@ gl_R_DrawWaterSurfaces (void) for (s = waterchain; s; s = s->tex_chain) { gltex_t *tex; surf = s->surface; - if (s->transform) + if (s->transform) { + qfglPushMatrix (); qfglLoadMatrixf (s->transform); - else - qfglLoadMatrixf (gl_r_world_matrix); + } tex = surf->texinfo->texture->render; if (i != tex->gl_texturenum) { i = tex->gl_texturenum; qfglBindTexture (GL_TEXTURE_2D, i); } GL_EmitWaterPolys (surf); + if (s->transform) { + qfglPopMatrix (); + } } - qfglLoadMatrixf (gl_r_world_matrix); waterchain = NULL; waterchain_tail = &waterchain; diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index e0ad50869..b0f00cfbe 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/gl/gl_sky_clip.c b/libs/video/renderer/gl/gl_sky_clip.c index c11554315..fc1331dc8 100644 --- a/libs/video/renderer/gl/gl_sky_clip.c +++ b/libs/video/renderer/gl/gl_sky_clip.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #include #ifdef HAVE_STRING_H # include diff --git a/libs/video/renderer/gl/gl_textures.c b/libs/video/renderer/gl/gl_textures.c index 00a3d47c4..85a43eec9 100644 --- a/libs/video/renderer/gl/gl_textures.c +++ b/libs/video/renderer/gl/gl_textures.c @@ -29,9 +29,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/gl/gl_warp.c b/libs/video/renderer/gl/gl_warp.c index d32bc4141..3f08d83d7 100644 --- a/libs/video/renderer/gl/gl_warp.c +++ b/libs/video/renderer/gl/gl_warp.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #include "QF/cvar.h" #include "QF/sys.h" diff --git a/libs/video/renderer/gl/namehack.h b/libs/video/renderer/gl/namehack.h deleted file mode 100644 index 547442279..000000000 --- a/libs/video/renderer/gl/namehack.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifdef NH_DEFINE -#undef NH_DEFINE -#define Draw_Init gl_Draw_Init -#define Draw_Character gl_Draw_Character -#define Draw_String gl_Draw_String -#define Draw_nString gl_Draw_nString -#define Draw_AltString gl_Draw_AltString -#define Draw_ConsoleBackground gl_Draw_ConsoleBackground -#define Draw_Crosshair gl_Draw_Crosshair -#define Draw_CrosshairAt gl_Draw_CrosshairAt -#define Draw_TileClear gl_Draw_TileClear -#define Draw_Fill gl_Draw_Fill -#define Draw_TextBox gl_Draw_TextBox -#define Draw_FadeScreen gl_Draw_FadeScreen -#define Draw_BlendScreen gl_Draw_BlendScreen -#define Draw_CachePic gl_Draw_CachePic -#define Draw_UncachePic gl_Draw_UncachePic -#define Draw_MakePic gl_Draw_MakePic -#define Draw_DestroyPic gl_Draw_DestroyPic -#define Draw_PicFromWad gl_Draw_PicFromWad -#define Draw_Pic gl_Draw_Pic -#define Draw_Picf gl_Draw_Picf -#define Draw_SubPic gl_Draw_SubPic -#define R_AddTexture gl_R_AddTexture -#define R_BlendLightmaps gl_R_BlendLightmaps -#define R_CalcLightmaps gl_R_CalcLightmaps -#define R_ClearState gl_R_ClearState -#define R_ClearTextures gl_R_ClearTextures -#define R_DrawAliasModel gl_R_DrawAliasModel -#define R_DrawBrushModel gl_R_DrawBrushModel -#define R_DrawParticles gl_R_DrawParticles -#define R_DrawSky gl_R_DrawSky -#define R_DrawSkyChain gl_R_DrawSkyChain -#define R_DrawSpriteModel gl_R_DrawSpriteModel -#define R_DrawWaterSurfaces gl_R_DrawWaterSurfaces -#define R_DrawWorld gl_R_DrawWorld -#define R_InitBubble gl_R_InitBubble -#define R_InitGraphTextures gl_R_InitGraphTextures -#define R_InitParticles gl_R_InitParticles -#define R_InitSky gl_R_InitSky -#define R_InitSprites gl_R_InitSprites -#define R_InitSurfaceChains gl_R_InitSurfaceChains -#define R_LineGraph gl_R_LineGraph -#define R_LoadSky_f gl_R_LoadSky_f -#define R_LoadSkys gl_R_LoadSkys -#define R_NewMap gl_R_NewMap -#define R_Particle_New gl_R_Particle_New -#define R_Particle_NewRandom gl_R_Particle_NewRandom -#define R_Particles_Init_Cvars gl_R_Particles_Init_Cvars -#define R_ReadPointFile_f gl_R_ReadPointFile_f -#define R_RenderDlights gl_R_RenderDlights -#define R_RenderView gl_R_RenderView -#define R_RotateForEntity gl_R_RotateForEntity -#define R_SetupFrame gl_R_SetupFrame -#define R_TimeRefresh_f gl_R_TimeRefresh_f -#define R_ViewChanged gl_R_ViewChanged -#define SCR_CaptureBGR gl_SCR_CaptureBGR -#define SCR_ScreenShot gl_SCR_ScreenShot -#define SCR_ScreenShot_f gl_SCR_ScreenShot_f -#define R_RenderFrame gl_R_RenderFrame -#define c_alias_polys gl_c_alias_polys -#define c_brush_polys gl_c_brush_polys -#define r_easter_eggs_f gl_r_easter_eggs_f -#define r_particles_style_f gl_r_particles_style_f -#define r_world_matrix gl_r_world_matrix -#else -#undef R_AddTexture -#undef R_BlendLightmaps -#undef R_CalcLightmaps -#undef R_ClearState -#undef R_ClearTextures -#undef R_DrawAliasModel -#undef R_DrawBrushModel -#undef R_DrawParticles -#undef R_DrawSky -#undef R_DrawSkyChain -#undef R_DrawSpriteModel -#undef R_DrawWaterSurfaces -#undef R_DrawWorld -#undef R_Init -#undef R_InitBubble -#undef R_InitGraphTextures -#undef R_InitParticles -#undef R_InitSky -#undef R_InitSprites -#undef R_InitSurfaceChains -#undef R_LineGraph -#undef R_LoadSky_f -#undef R_LoadSkys -#undef R_NewMap -#undef R_Particle_New -#undef R_Particle_NewRandom -#undef R_Particles_Init_Cvars -#undef R_ReadPointFile_f -#undef R_RenderDlights -#undef R_RenderView -#undef R_RotateForEntity -#undef R_SetupFrame -#undef R_TimeRefresh_f -#undef R_ViewChanged -#undef SCR_CaptureBGR -#undef SCR_ScreenShot -#undef SCR_ScreenShot_f -#undef R_RenderFrame -#undef c_alias_polys -#undef c_brush_polys -#undef r_easter_eggs_f -#undef r_particles_style_f -#undef r_world_matrix -#endif diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 05f2df3cd..f3399b119 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -31,9 +31,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index c01de2119..aecb2a9d1 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -31,9 +31,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -303,7 +300,7 @@ GET_RELEASE (elements_t, elements) GET_RELEASE (instsurf_t, static_instsurf) GET_RELEASE (instsurf_t, instsurf) -void +static void glsl_R_AddTexture (texture_t *tx) { int i; @@ -422,7 +419,7 @@ register_textures (mod_brush_t *brush) } } -void +static void glsl_R_ClearTextures (void) { r_num_texture_chains = 0; @@ -1183,7 +1180,7 @@ glsl_R_DrawWorld (void) } void -glsl_R_DrawWaterSurfaces () +glsl_R_DrawWaterSurfaces (void) { instsurf_t *is; msurface_t *surf; diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index f39040ab8..47b99575b 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -31,9 +31,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index a8e05096f..e140f6232 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -31,9 +31,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index 14561bbb0..8fa99cb8a 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -33,9 +33,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index d13196908..527843b43 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -31,9 +31,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include "string.h" #endif @@ -54,8 +51,11 @@ #include "QF/GLSL/funcs.h" #include "QF/GLSL/qf_alias.h" #include "QF/GLSL/qf_bsp.h" +#include "QF/GLSL/qf_draw.h" #include "QF/GLSL/qf_iqm.h" #include "QF/GLSL/qf_lightmap.h" +#include "QF/GLSL/qf_main.h" +#include "QF/GLSL/qf_particles.h" #include "QF/GLSL/qf_sprite.h" #include "QF/GLSL/qf_textures.h" @@ -93,7 +93,7 @@ glsl_R_ViewChanged (void) mmulf (proj, depth_range, proj); } -void +static void glsl_R_SetupFrame (void) { R_AnimateLight (); @@ -227,6 +227,28 @@ glsl_R_RenderView (void) } } +static void +glsl_R_TimeRefresh_f (void) +{ +/* FIXME update for simd + double start, stop, time; + int i; + + glsl_ctx->end_rendering (); + + start = Sys_DoubleTime (); + for (i = 0; i < 128; i++) { + r_refdef.viewangles[1] = i * (360.0 / 128.0); + glsl_R_RenderView (); + glsl_ctx->end_rendering (); + } + + stop = Sys_DoubleTime (); + time = stop - start; + Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); +*/ +} + void glsl_R_Init (void) { @@ -279,25 +301,3 @@ glsl_R_ClearState (void) R_ClearDlights (); R_ClearParticles (); } - -void -glsl_R_TimeRefresh_f (void) -{ -/* FIXME update for simd - double start, stop, time; - int i; - - glsl_ctx->end_rendering (); - - start = Sys_DoubleTime (); - for (i = 0; i < 128; i++) { - r_refdef.viewangles[1] = i * (360.0 / 128.0); - glsl_R_RenderView (); - glsl_ctx->end_rendering (); - } - - stop = Sys_DoubleTime (); - time = stop - start; - Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); -*/ -} diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 81473369c..2dae866f0 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index fc4cf8be7..8fabaffcc 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -31,9 +31,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif @@ -263,7 +260,7 @@ glsl_R_DrawSprite (entity_t *ent) // All sprites are drawn in a batch, so avoid thrashing the gl state void -R_SpriteBegin (void) +glsl_R_SpriteBegin (void) { mat4f_t mat; quat_t fog; @@ -298,7 +295,7 @@ R_SpriteBegin (void) } void -R_SpriteEnd (void) +glsl_R_SpriteEnd (void) { qfeglDisableVertexAttribArray (quake_sprite.vertexa.location); qfeglDisableVertexAttribArray (quake_sprite.vertexb.location); diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index 96c0f0c77..2aa971734 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -29,9 +29,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "namehack.h" - #ifdef HAVE_STRING_H # include #endif diff --git a/libs/video/renderer/glsl/namehack.h b/libs/video/renderer/glsl/namehack.h deleted file mode 100644 index 9aa8f0ed5..000000000 --- a/libs/video/renderer/glsl/namehack.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifdef NH_DEFINE -#undef NH_DEFINE -#define Draw_Init glsl_Draw_Init -#define Draw_Character glsl_Draw_Character -#define Draw_String glsl_Draw_String -#define Draw_nString glsl_Draw_nString -#define Draw_AltString glsl_Draw_AltString -#define Draw_ConsoleBackground glsl_Draw_ConsoleBackground -#define Draw_Crosshair glsl_Draw_Crosshair -#define Draw_CrosshairAt glsl_Draw_CrosshairAt -#define Draw_TileClear glsl_Draw_TileClear -#define Draw_Fill glsl_Draw_Fill -#define Draw_TextBox glsl_Draw_TextBox -#define Draw_FadeScreen glsl_Draw_FadeScreen -#define Draw_BlendScreen glsl_Draw_BlendScreen -#define Draw_CachePic glsl_Draw_CachePic -#define Draw_UncachePic glsl_Draw_UncachePic -#define Draw_MakePic glsl_Draw_MakePic -#define Draw_DestroyPic glsl_Draw_DestroyPic -#define Draw_PicFromWad glsl_Draw_PicFromWad -#define Draw_Pic glsl_Draw_Pic -#define Draw_Picf glsl_Draw_Picf -#define Draw_SubPic glsl_Draw_SubPic -#define R_AddTexture glsl_R_AddTexture -#define R_BlendLightmaps glsl_R_BlendLightmaps -#define R_BuildLightMap glsl_R_BuildLightMap -#define R_CalcLightmaps glsl_R_CalcLightmaps -#define R_ClearState glsl_R_ClearState -#define R_ClearTextures glsl_R_ClearTextures -#define R_DrawAliasModel glsl_R_DrawAliasModel -#define R_DrawBrushModel glsl_R_DrawBrushModel -#define R_DrawParticles glsl_R_DrawParticles -#define R_DrawSky glsl_R_DrawSky -#define R_DrawSkyChain glsl_R_DrawSkyChain -#define R_DrawSpriteModel glsl_R_DrawSpriteModel -#define R_DrawWaterSurfaces glsl_R_DrawWaterSurfaces -#define R_DrawWorld glsl_R_DrawWorld -#define R_InitBubble glsl_R_InitBubble -#define R_InitGraphTextures glsl_R_InitGraphTextures -#define R_InitParticles glsl_R_InitParticles -#define R_InitSky glsl_R_InitSky -#define R_InitSprites glsl_R_InitSprites -#define R_LineGraph glsl_R_LineGraph -#define R_LoadSky_f glsl_R_LoadSky_f -#define R_LoadSkys glsl_R_LoadSkys -#define R_NewMap glsl_R_NewMap -#define R_Particle_New glsl_R_Particle_New -#define R_Particle_NewRandom glsl_R_Particle_NewRandom -#define R_Particles_Init_Cvars glsl_R_Particles_Init_Cvars -#define R_ReadPointFile_f glsl_R_ReadPointFile_f -#define R_RenderDlights glsl_R_RenderDlights -#define R_RenderView glsl_R_RenderView -#define R_RotateForEntity glsl_R_RotateForEntity -#define R_SetupFrame glsl_R_SetupFrame -#define R_SpriteBegin glsl_R_SpriteBegin -#define R_SpriteEnd glsl_R_SpriteEnd -#define R_TimeRefresh_f glsl_R_TimeRefresh_f -#define R_ViewChanged glsl_R_ViewChanged -#define SCR_CaptureBGR glsl_SCR_CaptureBGR -#define SCR_ScreenShot glsl_SCR_ScreenShot -#define SCR_ScreenShot_f glsl_SCR_ScreenShot_f -#define R_RenderFrame glsl_R_RenderFrame -#define c_alias_polys glsl_c_alias_polys -#define c_brush_polys glsl_c_brush_polys -#define r_easter_eggs_f glsl_r_easter_eggs_f -#define r_particles_style_f glsl_r_particles_style_f -#define r_world_matrix glsl_r_world_matrix -#else -#undef R_AddTexture -#undef R_BlendLightmaps -#undef R_BuildLightMap -#undef R_CalcLightmaps -#undef R_ClearState -#undef R_ClearTextures -#undef R_DrawAliasModel -#undef R_DrawBrushModel -#undef R_DrawParticles -#undef R_DrawSky -#undef R_DrawSkyChain -#undef R_DrawSpriteModel -#undef R_DrawWaterSurfaces -#undef R_DrawWorld -#undef R_Init -#undef R_InitBubble -#undef R_InitGraphTextures -#undef R_InitParticles -#undef R_InitSky -#undef R_InitSprites -#undef R_InitSurfaceChains -#undef R_LineGraph -#undef R_LoadSky_f -#undef R_LoadSkys -#undef R_NewMap -#undef R_Particle_New -#undef R_Particle_NewRandom -#undef R_Particles_Init_Cvars -#undef R_ReadPointFile_f -#undef R_RenderDlights -#undef R_RenderView -#undef R_RotateForEntity -#undef R_SetupFrame -#undef R_TimeRefresh_f -#undef R_ViewChanged -#undef SCR_CaptureBGR -#undef SCR_ScreenShot -#undef SCR_ScreenShot_f -#undef R_RenderFrame -#undef c_alias_polys -#undef c_brush_polys -#undef r_easter_eggs_f -#undef r_particles_style_f -#undef r_world_matrix -#endif diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 1ae2db22c..05a7c378c 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "gl/namehack.h" - #include "QF/cvar.h" #include "QF/plugin/general.h" @@ -38,6 +35,7 @@ #include "QF/GL/funcs.h" #include "QF/GL/qf_draw.h" +#include "QF/GL/qf_rmain.h" #include "QF/GL/qf_rsurf.h" #include "QF/GL/qf_vid.h" @@ -47,8 +45,6 @@ #include "vid_internal.h" #include "vid_gl.h" -#include "gl/namehack.h" - gl_ctx_t *gl_ctx; static void diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index b5996226d..cb7e812ab 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#define NH_DEFINE -#include "glsl/namehack.h" - #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -38,6 +35,7 @@ #include "QF/GLSL/defines.h" #include "QF/GLSL/qf_bsp.h" #include "QF/GLSL/qf_draw.h" +#include "QF/GLSL/qf_main.h" #include "QF/GLSL/qf_vid.h" #include "mod_internal.h" @@ -45,8 +43,6 @@ #include "vid_internal.h" #include "vid_gl.h" -#include "glsl/namehack.h" - gl_ctx_t *glsl_ctx; static void From 2641fe3241199dda1a334fa21bc1fc4de0962869 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Mar 2022 15:12:33 +0900 Subject: [PATCH 2531/3664] [gl] Remove some dead code R_RecursiveLightUpdate has been obsolete for a very long time, and R_Mirror is just wrong (needs envmaps etc, wonder if it can be done in the fixed function code using skyclip?) --- libs/video/renderer/gl/gl_lightmap.c | 16 ------ libs/video/renderer/gl/gl_rmain.c | 80 ---------------------------- 2 files changed, 96 deletions(-) diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 4f2d4a3c8..5ccbbae13 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -87,23 +87,7 @@ gl_lightmap_init (void) for (s = 1; s < 8192; s++) dlightdivtable[s] = 1048576 / (s << 7); } -/* -static void -R_RecursiveLightUpdate (mnode_t *node) -{ - int c; - msurface_t *surf; - if (node->children[0]->contents >= 0) - R_RecursiveLightUpdate (node->children[0]); - if (node->children[1]->contents >= 0) - R_RecursiveLightUpdate (node->children[1]); - if ((c = node->numsurfaces)) - for (surf = r_worldentity.model->surfaces + node->firstsurface; c; - c--, surf++) - surf->cached_dlight = true; -} -*/ static inline void R_AddDynamicLights_1 (const transform_t *transform, msurface_t *surf) { diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index e8caaf3d6..3fa3eb207 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -445,83 +445,6 @@ R_RenderScene (void) R_ClearErrors (); } -static void -R_Mirror (void) -{ - //float d; -// msurface_t *surf; - -// if (!gl_mirror) // FIXME: Broken - return; -/* - memcpy (r_base_world_matrix, gl_r_world_matrix, - sizeof (r_base_world_matrix)); - - d = 2 * DotProduct (r_refdef.vieworg, gl_mirror_plane->normal) - - gl_mirror_plane->dist; - VectorMultSub (r_refdef.vieworg, d, gl_mirror_plane->normal, - r_refdef.vieworg); - - d = 2 * DotProduct (vpn, gl_mirror_plane->normal); - VectorMultSub (vpn, d, gl_mirror_plane->normal, vpn); - - r_refdef.viewangles[0] = -asin (vpn[2]) / M_PI * 180; - r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0]) / M_PI * 180; - r_refdef.viewangles[2] = -r_refdef.viewangles[2]; - - R_EnqueueEntity (vr_data.player_entity); - - gldepthmin = 0.5; - gldepthmax = 1; - qfglDepthRange (gldepthmin, gldepthmax); - - R_RenderScene (); - gl_R_DrawWaterSurfaces (); - - gldepthmin = 0; - gldepthmax = 1; - qfglDepthRange (gldepthmin, gldepthmax); - - // blend on top - qfglMatrixMode (GL_PROJECTION); - if (gl_mirror_plane->normal[2]) - qfglScalef (1, -1, 1); - else - qfglScalef (-1, 1, 1); - qfglFrontFace (GL_CW); - qfglMatrixMode (GL_MODELVIEW); - - qfglLoadMatrixf (r_base_world_matrix); - - color_white[3] = r_mirroralpha->value * 255; - qfglColor4ubv (color_white); -#if 0//FIXME - surf = r_worldentity.model->textures[gl_mirrortexturenum]->texturechain; - for (; surf; surf = surf->texturechain) { - texture_t *tex; - - if (!surf->texinfo->texture->anim_total) - tex = surf->texinfo->texture; - else - tex = R_TextureAnimation (surf); - -// FIXME: Needs to set the texture, the tmu, and include the header, and then -// clean up afterwards. -// if (tex->gl_fb_texturenum && gl_mtex_fullbright -// && gl_fb_models->int_val) { -// surf->polys->fb_chain = fullbright_polys[tex->gl_fb_texturenum]; -// fullbright_polys[tex->gl_fb_texturenum] = surf->polys; -// } - - qfglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum); -// R_RenderBrushPoly (surf, tex); // FIXME: Need to move R_Mirror to gl_rsurf.c, and uncommment this line! - } - r_worldentity.model->textures[gl_mirrortexturenum]->texturechain = NULL; -#endif - qfglColor3ubv (color_white); -*/ -} - /* R_RenderView_ @@ -542,9 +465,6 @@ R_RenderView_ (void) // render normal view R_RenderScene (); - // render mirror view - R_Mirror (); - if (r_timegraph->int_val) R_TimeGraph (); if (r_zgraph->int_val) From 7402fcfd0c1cd117edc1fe63679da3d9a574b1a7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Mar 2022 15:27:43 +0900 Subject: [PATCH 2532/3664] [renderer] move r_worldentity and r_viewleaf into refdef More cleanup of globals that seem to be quake specific. --- include/QF/render.h | 5 ++-- include/r_local.h | 2 -- libs/video/renderer/gl/gl_lightmap.c | 2 +- libs/video/renderer/gl/gl_mod_alias.c | 2 +- libs/video/renderer/gl/gl_rmain.c | 6 ++-- libs/video/renderer/gl/gl_rmisc.c | 7 ++--- libs/video/renderer/gl/gl_rsurf.c | 4 +-- libs/video/renderer/glsl/glsl_alias.c | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 14 ++++----- libs/video/renderer/glsl/glsl_iqm.c | 2 +- libs/video/renderer/glsl/glsl_main.c | 11 ++++--- libs/video/renderer/r_bsp.c | 11 ++++--- libs/video/renderer/r_light.c | 2 +- libs/video/renderer/r_main.c | 2 -- libs/video/renderer/sw/sw_rbsp.c | 31 ++++++++++++++------ libs/video/renderer/sw/sw_rmain.c | 13 ++++---- libs/video/renderer/sw/sw_rmisc.c | 4 +-- libs/video/renderer/sw/sw_rsurf.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 14 ++++----- libs/video/renderer/vulkan/vulkan_lighting.c | 4 +-- libs/video/renderer/vulkan/vulkan_main.c | 9 +++--- 22 files changed, 78 insertions(+), 73 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index 788c41dca..bd05032eb 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -219,6 +219,9 @@ typedef struct { int drawflat; float fov_x, fov_y; + + struct model_s *worldmodel; + struct mleaf_s *viewleaf; } refdef_t; // color shifts ============================================================= @@ -240,8 +243,6 @@ typedef struct { extern struct texture_s *r_notexture_mip; -extern entity_t r_worldentity; - void R_Init (void); struct vid_internal_s; void R_LoadModule (struct vid_internal_s *vid_internal); diff --git a/include/r_local.h b/include/r_local.h index fe8c19713..1c42b3685 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -286,8 +286,6 @@ extern int r_frustum_indexes[4*6]; extern int r_maxsurfsseen, r_maxedgesseen; extern qboolean r_dowarpold, r_viewchanged; -extern mleaf_t *r_viewleaf; - extern int r_clipflags; extern int r_dlightframecount; diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 5ccbbae13..964b5aa36 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -598,7 +598,7 @@ gl_overbright_f (cvar_t *var) } } - brush = &r_worldentity.renderer.model->brush; + brush = &r_refdef.worldmodel->brush; for (unsigned i = 0; i < brush->numsurfaces; i++) { msurface_t *surf = brush->surfaces + i; diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 32ff19857..307410f53 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -449,7 +449,7 @@ gl_R_DrawAliasModel (entity_t *e) float lightadj; // get lighting information - R_LightPoint (&r_worldentity.renderer.model->brush, &origin[0]);//FIXME + R_LightPoint (&r_refdef.worldmodel->brush, &origin[0]);//FIXME lightadj = (ambientcolor[0] + ambientcolor[1] + ambientcolor[2]) / 765.0; diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 3fa3eb207..7126a6c2d 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -332,7 +332,7 @@ gl_R_SetupFrame (void) R_SetFrustum (); - r_viewleaf = Mod_PointInLeaf (&position[0], r_worldentity.renderer.model); + r_refdef.viewleaf = Mod_PointInLeaf (&position[0], r_refdef.worldmodel); } static void @@ -456,7 +456,7 @@ R_RenderView_ (void) if (r_norefresh->int_val) { return; } - if (!r_worldentity.renderer.model) { + if (!r_refdef.worldmodel) { return; } @@ -784,7 +784,7 @@ R_RenderViewFishEye (void) void gl_R_ClearState (void) { - r_worldentity.renderer.model = 0; + r_refdef.worldmodel = 0; R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 35087b1fb..2cbfcdfee 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -219,8 +219,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) for (int i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value - memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.renderer.model = worldmodel; + r_refdef.worldmodel = worldmodel; brush = &worldmodel->brush; // clear out efrags in case the level hasn't been reloaded @@ -228,7 +227,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) brush->leafs[i].efrags = NULL; // Force a vis update - r_viewleaf = NULL; + r_refdef.viewleaf = NULL; R_MarkLeaves (); R_ClearParticles (); @@ -257,7 +256,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) continue; if (*models[i]->path == '*') continue; - if (models[i] != r_worldentity.renderer.model + if (models[i] != r_refdef.worldmodel && models[i]->type == mod_brush) register_textures (&models[i]->brush); } diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 2e5f1d94a..9b6bd214c 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -723,7 +723,7 @@ gl_R_DrawWorld (void) glbspctx_t bctx = { }; memset (&worldent, 0, sizeof (worldent)); - worldent.renderer.model = r_worldentity.renderer.model; + worldent.renderer.model = r_refdef.worldmodel; sky_chain = 0; sky_chain_tail = &sky_chain; @@ -732,7 +732,7 @@ gl_R_DrawWorld (void) } bctx.brush = &worldent.renderer.model->brush; - bctx.entity = &r_worldentity; + bctx.entity = &worldent; R_VisitWorldNodes (&bctx); diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index f3399b119..b7b50eb3b 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -161,7 +161,7 @@ calc_lighting (entity_t *ent, float *ambient, float *shadelight, entorigin = Transform_GetWorldPosition (ent->transform); VectorSet ( -1, 0, 0, lightvec); //FIXME - light = R_LightPoint (&r_worldentity.renderer.model->brush, &entorigin[0]); + light = R_LightPoint (&r_refdef.worldmodel->brush, &entorigin[0]); *ambient = max (light, max (ent->renderer.model->min_light, ent->renderer.min_light) * 128); *shadelight = *ambient; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index aecb2a9d1..aced41a62 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -433,9 +433,9 @@ glsl_R_RegisterTextures (model_t **models, int num_models) mod_brush_t *brush; glsl_R_ClearTextures (); - glsl_R_InitSurfaceChains (&r_worldentity.renderer.model->brush); + glsl_R_InitSurfaceChains (&r_refdef.worldmodel->brush); glsl_R_AddTexture (r_notexture_mip); - register_textures (&r_worldentity.renderer.model->brush); + register_textures (&r_refdef.worldmodel->brush); for (i = 0; i < num_models; i++) { m = models[i]; if (!m) @@ -444,7 +444,7 @@ glsl_R_RegisterTextures (model_t **models, int num_models) if (*m->path == '*') continue; // world has already been done, not interested in non-brush models - if (m == r_worldentity.renderer.model || m->type != mod_brush) + if (m == r_refdef.worldmodel || m->type != mod_brush) continue; brush = &m->brush; brush->numsubmodels = 1; // no support for submodels in non-world model @@ -489,7 +489,7 @@ build_surf_displist (model_t **models, msurface_t *surf, int base, if (surf->model_index < 0) { brush = &models[-surf->model_index - 1]->brush; } else { - brush = &r_worldentity.renderer.model->brush; + brush = &r_refdef.worldmodel->brush; } vertices = brush->vertexes; edges = brush->edges; @@ -588,7 +588,7 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) } surf = brush->surfaces + j; surf->model_index = dm - brush->submodels; - if (!surf->model_index && m != r_worldentity.renderer.model) + if (!surf->model_index && m != r_refdef.worldmodel) surf->model_index = -1 - i; // instanced model tex = surf->texinfo->texture->render; CHAIN_SURF_F2B (surf, tex->tex_chain); @@ -1140,10 +1140,10 @@ glsl_R_DrawWorld (void) clear_texture_chains (); // do this first for water and skys memset (&worldent, 0, sizeof (worldent)); - worldent.renderer.model = r_worldentity.renderer.model; + worldent.renderer.model = r_refdef.worldmodel; bctx.brush = &worldent.renderer.model->brush; - bctx.entity = &r_worldentity; + bctx.entity = &worldent; R_VisitWorldNodes (&bctx); if (r_drawentities->int_val) { diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index e140f6232..2978534d3 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -225,7 +225,7 @@ glsl_R_DrawIQM (entity_t *ent) entorigin = mat[3]; mmulf (mvp_mat, iqm_vp, mat); - R_LightPoint (&r_worldentity.renderer.model->brush, &entorigin[0]);//FIXME min_light? + R_LightPoint (&r_refdef.worldmodel->brush, &entorigin[0]);//FIXME min_light? VectorScale (ambientcolor, 1/255.0, ambientcolor); R_FindNearLights (&entorigin[0], MAX_IQM_LIGHTS, lights);//FIXME diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 527843b43..e90578ad1 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -104,7 +104,7 @@ glsl_R_SetupFrame (void) R_SetFrustum (); - r_viewleaf = Mod_PointInLeaf (&position[0], r_worldentity.renderer.model); + r_refdef.viewleaf = Mod_PointInLeaf (&position[0], r_refdef.worldmodel); } static void @@ -182,7 +182,7 @@ glsl_R_RenderView (void) double t[10] = {}; int speeds = r_speeds->int_val; - if (!r_worldentity.renderer.model) { + if (!r_refdef.worldmodel) { return; } @@ -275,11 +275,10 @@ glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) for (i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value - memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.renderer.model = worldmodel; + r_refdef.worldmodel = worldmodel; // Force a vis update - r_viewleaf = NULL; + r_refdef.viewleaf = NULL; R_MarkLeaves (); R_ClearParticles (); @@ -296,7 +295,7 @@ glsl_R_LineGraph (int x, int y, int *h_vals, int count, int height) void glsl_R_ClearState (void) { - r_worldentity.renderer.model = 0; + r_refdef.worldmodel = 0; R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 695f7e063..b4fdf36c9 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -42,7 +42,6 @@ #include "r_internal.h" mvertex_t *r_pcurrentvertbase; -mleaf_t *r_viewleaf; static mleaf_t *r_oldviewleaf; static set_t *solid; @@ -54,14 +53,14 @@ R_MarkLeaves (void) mleaf_t *leaf; mnode_t *node; msurface_t **mark; - mod_brush_t *brush = &r_worldentity.renderer.model->brush; + mod_brush_t *brush = &r_refdef.worldmodel->brush; - if (r_oldviewleaf == r_viewleaf && !r_novis->int_val) + if (r_oldviewleaf == r_refdef.viewleaf && !r_novis->int_val) return; r_visframecount++; - r_oldviewleaf = r_viewleaf; - if (!r_viewleaf) + r_oldviewleaf = r_refdef.viewleaf; + if (!r_refdef.viewleaf) return; if (r_novis->int_val) { @@ -73,7 +72,7 @@ R_MarkLeaves (void) } vis = solid; } else - vis = Mod_LeafPVS (r_viewleaf, r_worldentity.renderer.model); + vis = Mod_LeafPVS (r_refdef.viewleaf, r_refdef.worldmodel); for (unsigned i = 0; i < brush->visleafs; i++) { if (set_is_member (vis, i)) { diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 8de8f2738..0b32a6f6d 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -326,7 +326,7 @@ R_PushDlights (const vec3_t entorigin) if (l->die < r_data->realtime || !l->radius) continue; VectorSubtract (l->origin, entorigin, lightorigin); - R_MarkLights (lightorigin, l, i, r_worldentity.renderer.model); + R_MarkLights (lightorigin, l, i, r_refdef.worldmodel); } } diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index bf05d12aa..d6ecf3a54 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -65,8 +65,6 @@ vec3_t modelorg; // modelorg is the viewpoint relative to vec3_t base_modelorg; vec3_t r_entorigin; // the currently rendering entity in world // coordinates -entity_t r_worldentity; - // screen size info refdef_t r_refdef; diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 47771697a..c1470e0e6 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -40,6 +40,11 @@ #include "r_internal.h" +typedef struct glbspctx_s { + mod_brush_t *brush; + entity_t *entity; +} swbspctx_t; + // current entity info qboolean insubmodel; vec3_t r_worldmodelorg; @@ -368,11 +373,12 @@ get_side (mnode_t *node) } static void -visit_node (mod_brush_t *brush, mnode_t *node, int side, int clipflags) +visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags) { int c; msurface_t *surf; - entity_t *ent = &r_worldentity; + entity_t *ent = bctx->entity; + mod_brush_t *brush = &ent->renderer.model->brush; // sneaky hack for side = side ? SURF_PLANEBACK : 0; side = (~side + 1) & SURF_PLANEBACK; @@ -455,7 +461,7 @@ test_node (mnode_t *node, int *clipflags) } static void -R_VisitWorldNodes (mod_brush_t *brush, int clipflags) +R_VisitWorldNodes (swbspctx_t *bctx, int clipflags) { typedef struct { mnode_t *node; @@ -466,6 +472,7 @@ R_VisitWorldNodes (mod_brush_t *brush, int clipflags) mnode_t *node; mnode_t *front; int side, cf; + mod_brush_t *brush = &bctx->entity->renderer.model->brush; node = brush->nodes; // +2 for paranoia @@ -489,7 +496,7 @@ R_VisitWorldNodes (mod_brush_t *brush, int clipflags) } if (front->contents < 0 && front->contents != CONTENTS_SOLID) visit_leaf ((mleaf_t *) front); - visit_node (brush, node, side, clipflags); + visit_node (bctx, node, side, clipflags); node = node->children[!side]; } if (node->contents < 0 && node->contents != CONTENTS_SOLID) @@ -499,7 +506,7 @@ R_VisitWorldNodes (mod_brush_t *brush, int clipflags) node = node_ptr->node; side = node_ptr->side; clipflags = node_ptr->clipflags; - visit_node (brush, node, side, clipflags); + visit_node (bctx, node, side, clipflags); node = node->children[!side]; continue; } @@ -514,15 +521,21 @@ R_RenderWorld (void) { int i; btofpoly_t btofpolys[MAX_BTOFPOLYS]; - mod_brush_t *brush; - entity_t *ent = &r_worldentity; + entity_t worldent = {}; + entity_t *ent = &worldent; + mod_brush_t *brush = &r_refdef.worldmodel->brush; + swbspctx_t bspctx = { + brush, + ent, + }; + worldent.renderer.model = r_refdef.worldmodel; pbtofpolys = btofpolys; - brush = &r_worldentity.renderer.model->brush; + brush = &r_refdef.worldmodel->brush; r_pcurrentvertbase = brush->vertexes; - R_VisitWorldNodes (brush, 15); + R_VisitWorldNodes (&bspctx, 15); // if the driver wants the polygons back to front, play the visible ones // back in that order diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 19be8c6e0..f5d157ac0 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -171,8 +171,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) { mod_brush_t *brush = &worldmodel->brush; - memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.renderer.model = worldmodel; + r_refdef.worldmodel = worldmodel; // clear out efrags in case the level hasn't been reloaded for (unsigned i = 0; i < brush->modleafs; i++) @@ -182,7 +181,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) R_InitSky (brush->skytexture); // Force a vis update - r_viewleaf = NULL; + r_refdef.viewleaf = NULL; R_MarkLeaves (); R_ClearParticles (); @@ -364,7 +363,7 @@ setup_lighting (entity_t *ent, alight_t *lighting) minlight = max (ent->renderer.model->min_light, ent->renderer.min_light); // 128 instead of 255 due to clamping below - j = max (R_LightPoint (&r_worldentity.renderer.model->brush, r_entorigin), + j = max (R_LightPoint (&r_refdef.worldmodel->brush, r_entorigin), minlight * 128); lighting->ambientlight = j; @@ -466,7 +465,7 @@ R_DrawViewModel (void) minlight = max (viewent->renderer.min_light, viewent->renderer.model->min_light); - j = max (R_LightPoint (&r_worldentity.renderer.model->brush, + j = max (R_LightPoint (&r_refdef.worldmodel->brush, r_entorigin), minlight * 128); r_viewlighting.ambientlight = j; @@ -741,7 +740,7 @@ R_RenderView_ (void) if (r_norefresh->int_val) return; - if (!r_worldentity.renderer.model) { + if (!r_refdef.worldmodel) { return; } @@ -1153,7 +1152,7 @@ R_RenderViewFishEye (void) void R_ClearState (void) { - r_worldentity.renderer.model = 0; + r_refdef.worldmodel = 0; R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index ebc56a34d..d29b68186 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -192,10 +192,10 @@ R_SetupFrame (void) R_SetFrustum (); // current viewleaf - r_viewleaf = Mod_PointInLeaf (&position[0], r_worldentity.renderer.model); + r_refdef.viewleaf = Mod_PointInLeaf (&position[0], r_refdef.worldmodel); r_dowarpold = r_dowarp; - r_dowarp = r_waterwarp->int_val && (r_viewleaf->contents <= + r_dowarp = r_waterwarp->int_val && (r_refdef.viewleaf->contents <= CONTENTS_WATER); if ((r_dowarp != r_dowarpold) || r_viewchanged) { diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 819293d1b..c3938c282 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -161,7 +161,7 @@ R_BuildLightMap (transform_t *transform) size = smax * tmax; lightmap = surf->samples; - if (!r_worldentity.renderer.model->brush.lightdata) { + if (!r_refdef.worldmodel->brush.lightdata) { for (i = 0; i < size; i++) blocklights[i] = 0; return; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index c8e910ee3..92b0f71a6 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -104,7 +104,7 @@ vulkan_R_Init (void) static void vulkan_R_ClearState (void) { - r_worldentity.renderer.model = 0; + r_refdef.worldmodel = 0; R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 17aebcb51..40dee2f61 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -275,7 +275,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) { int i; model_t *m; - mod_brush_t *brush = &r_worldentity.renderer.model->brush; + mod_brush_t *brush = &r_refdef.worldmodel->brush; clear_textures (ctx); init_surface_chains (brush, ctx); @@ -289,7 +289,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) if (*m->path == '*') continue; // world has already been done, not interested in non-brush models - if (m == r_worldentity.renderer.model || m->type != mod_brush) + if (m == r_refdef.worldmodel || m->type != mod_brush) continue; brush = &m->brush; brush->numsubmodels = 1; // no support for submodels in non-world model @@ -342,7 +342,7 @@ build_surf_displist (model_t **models, msurface_t *surf, int base, brush = &models[~surf->model_index]->brush; } else { // main or sub model - brush = &r_worldentity.renderer.model->brush; + brush = &r_refdef.worldmodel->brush; } vertices = brush->vertexes; edges = brush->edges; @@ -441,7 +441,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } surf = brush->surfaces + j; surf->model_index = dm - brush->submodels; - if (!surf->model_index && m != r_worldentity.renderer.model) { + if (!surf->model_index && m != r_refdef.worldmodel) { surf->model_index = -1 - i; // instanced model } tex = surf->texinfo->texture->render; @@ -1031,10 +1031,10 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bframe->index_count = 0; memset (&worldent, 0, sizeof (worldent)); - worldent.renderer.model = r_worldentity.renderer.model; - brush = &r_worldentity.renderer.model->brush; + worldent.renderer.model = r_refdef.worldmodel; + brush = &r_refdef.worldmodel->brush; - bctx->entity = &r_worldentity; + bctx->entity = &worldent; bctx->transform = 0; bctx->color = 0; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 771c3553f..d6578356d 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -90,8 +90,8 @@ find_visible_lights (vulkan_ctx_t *ctx) lightingctx_t *lctx = ctx->lighting_context; lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; - mleaf_t *leaf = r_viewleaf; - model_t *model = r_worldentity.renderer.model; + mleaf_t *leaf = r_refdef.viewleaf; + model_t *model = r_refdef.worldmodel; if (!leaf || !model) { return; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index a1fa92bae..fe5ee3c29 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -73,7 +73,7 @@ setup_frame (vulkan_ctx_t *ctx) R_SetFrustum (); vec4f_t position = r_refdef.frame.position; - r_viewleaf = Mod_PointInLeaf (&position[0], r_worldentity.renderer.model); + r_refdef.viewleaf = Mod_PointInLeaf (&position[0], r_refdef.worldmodel); } static void @@ -131,7 +131,7 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) double t[10] = {}; int speeds = r_speeds->int_val; - if (!r_worldentity.renderer.model) { + if (!r_refdef.worldmodel) { return; } @@ -187,11 +187,10 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, d_lightstylevalue[i] = 264; // normal light value } - memset (&r_worldentity, 0, sizeof (r_worldentity)); - r_worldentity.renderer.model = worldmodel; + r_refdef.worldmodel = worldmodel; // Force a vis update - r_viewleaf = NULL; + r_refdef.viewleaf = NULL; R_MarkLeaves (); R_ClearParticles (); From fd805886f7247b706340514d582409777d202fb5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Mar 2022 23:51:30 +0900 Subject: [PATCH 2533/3664] [renderer] Get fisheye working again Only for gl and sw at the moment (want to merge things further before I do anything for glsl or vulkan). However, with with I've learned getting gl and sw to work, glsl and vulkan will be trivial. --- libs/video/renderer/gl/gl_rmain.c | 133 +++++++------- libs/video/renderer/sw/sw_rmain.c | 282 +++++++++++------------------- libs/video/renderer/sw/sw_rmisc.c | 4 +- 3 files changed, 173 insertions(+), 246 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 7126a6c2d..a48035799 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -471,18 +471,18 @@ R_RenderView_ (void) R_ZGraph (); } -//FIXME static void R_RenderViewFishEye (void); +static void R_RenderViewFishEye (void); void gl_R_RenderView (void) { - R_RenderView_ (); - /*if(!scr_fisheye->int_val) + if(!scr_fisheye->int_val) R_RenderView_ (); else - R_RenderViewFishEye ();*/ + R_RenderViewFishEye (); } -/*FIXME + +//FIXME // Algorithm: // Draw up to six views, one in each direction. // Save the picture to cube map texture, use GL_ARB_texture_cube_map. @@ -499,7 +499,34 @@ gl_R_RenderView (void) #define BOX_TOP 4 #define BOX_BOTTOM 5 -#define FPOLYCNT 16 +static mat4f_t box_rotations[] = { + { { 1, 0, 0, 0}, // front + { 0, 1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0,-1, 0, 0}, // right + { 1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { {-1, 0, 0, 0}, // back + { 0,-1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0, 1, 0, 0}, // left + {-1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0, 0, 1, 0}, // top + { 0, 1, 0, 0}, + {-1, 0, 0, 0}, + { 0, 0, 0, 1} }, + { { 0, 0,-1, 0}, // bottom + { 0, 1, 0, 0}, + { 1, 0, 0, 0}, + { 0, 0, 0, 1} }, +}; + +#define FPOLYCNT 128 struct xyz { float x, y, z; @@ -548,79 +575,51 @@ do { \ printf ("%s: gl error %d\n", s, (int) err); \ } while (0); -#define NO(x) \ -do { \ - if (x < 0) \ - x += 360; \ - else if (x >= 360) \ - x -= 360; \ -} while (0) static void R_RenderCubeSide (int side) { - float pitch, n_pitch; - float yaw, n_yaw; - float roll, n_roll; - float s_roll; + mat4f_t camera; + mat4f_t camera_inverse; + mat4f_t rotinv; - pitch = n_pitch = r_refdef.viewangles[PITCH]; - yaw = n_yaw = r_refdef.viewangles[YAW]; - // setting ROLL for now to 0, correct roll handling - // requre more exhaustive changes in rotation - // TODO: implement via matrix -// roll = n_roll = r_refdef.viewangles[ROLL]; - s_roll = r_refdef.viewangles[ROLL]; - roll = n_roll = 0; -// roll -= scr_fviews->int_val * 10; -// n_roll = roll; - - switch (side) { - case BOX_FRONT: - break; - case BOX_RIGHT: - n_pitch = roll; - n_yaw -= 90; - n_roll = -pitch; - break; - case BOX_LEFT: - n_pitch = -roll; - n_yaw += 90; - n_roll = pitch; -// static int f = 0; -// if (!(f++ % 100)) -// printf ("%4d %4d %4d | %4d %4d %4d\n", (int) pitch, (int) yaw, -// (int) roll, (int) n_pitch, (int) n_yaw, (int) n_roll); - break; - case BOX_TOP: - n_pitch -= 90; - break; - case BOX_BOTTOM: - n_pitch += 90; - break; - case BOX_BEHIND: - n_pitch = -pitch; - n_yaw += 180; - break; - } - NO (n_pitch); - NO (n_yaw); - NO (n_roll); - r_refdef.viewangles[PITCH] = n_pitch; - r_refdef.viewangles[YAW] = n_yaw; - r_refdef.viewangles[ROLL] = n_roll; + memcpy (camera, r_refdef.camera, sizeof (camera)); + memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse)); + mmulf (r_refdef.camera, camera, box_rotations[side]); + mat4ftranspose (rotinv, box_rotations[side]); + mmulf (r_refdef.camera_inverse, rotinv, camera_inverse); + //FIXME see fixme in r_screen.c + r_refdef.frame.mat[0] = -r_refdef.camera[1]; + r_refdef.frame.mat[1] = r_refdef.camera[0]; + r_refdef.frame.mat[2] = r_refdef.camera[2]; + r_refdef.frame.mat[3] = r_refdef.camera[3]; +#if 0 + printf ("side: %d\n", side); + printf ("c: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 3)); + printf ("f: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 3)); +#endif + qfglClear (GL_DEPTH_BUFFER_BIT); R_RenderView_ (); qfglEnable (GL_TEXTURE_CUBE_MAP_ARB); qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, cube_map_tex); qfglCopyTexSubImage2D (box2cube_map[side], 0, 0, 0, 0, 0, gl_cube_map_size, gl_cube_map_size); -// CHKGLERR ("qfglCopyTexSubImage2D"); + CHKGLERR ("qfglCopyTexSubImage2D"); qfglDisable (GL_TEXTURE_CUBE_MAP_ARB); - r_refdef.viewangles[PITCH] = pitch; - r_refdef.viewangles[YAW] = yaw; - r_refdef.viewangles[ROLL] = s_roll; + memcpy (r_refdef.camera, camera, sizeof (camera)); + memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); } static qboolean gl_cube_map_capable = false; @@ -779,7 +778,7 @@ R_RenderViewFishEye (void) R_SetupGL_Viewport_and_Perspective (); qfglMatrixMode (GL_MODELVIEW); qfglCallList (fisheye_grid); -}*/ +} void gl_R_ClearState (void) diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index f5d157ac0..95498b0df 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -823,7 +823,7 @@ R_RenderView_ (void) R_HighFPPrecision (); } -//XXX FIXME static void R_RenderViewFishEye (void); +static void R_RenderViewFishEye (void); void R_RenderView (void) @@ -843,12 +843,10 @@ R_RenderView (void) if ((intptr_t) (&r_warpbuffer) & 3) Sys_Error ("Globals are missaligned"); - R_RenderView_ (); -/*XXX FIXME if (!scr_fisheye->int_val) R_RenderView_ (); else - R_RenderViewFishEye ();*/ + R_RenderViewFishEye (); } void @@ -862,161 +860,55 @@ R_InitTurb (void) // AMP2 not 20 } } -/*XXX FIXME + #define BOX_FRONT 0 +#define BOX_RIGHT 1 #define BOX_BEHIND 2 #define BOX_LEFT 3 -#define BOX_RIGHT 1 #define BOX_TOP 4 #define BOX_BOTTOM 5 -#define DEG(x) (x / M_PI * 180.0) -#define RAD(x) (x * M_PI / 180.0) - -struct my_coords -{ - double x, y, z; +static mat4f_t box_rotations[] = { + { { 1, 0, 0, 0}, // front + { 0, 1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0,-1, 0, 0}, // right + { 1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { {-1, 0, 0, 0}, // back + { 0,-1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0, 1, 0, 0}, // left + {-1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} }, + { { 0, 0, 1, 0}, // top + { 0, 1, 0, 0}, + {-1, 0, 0, 0}, + { 0, 0, 0, 1} }, + { { 0, 0,-1, 0}, // bottom + { 0, 1, 0, 0}, + { 1, 0, 0, 0}, + { 0, 0, 0, 1} }, }; -struct my_angles -{ - double yaw, pitch, roll; -}; - -static void -x_rot (struct my_coords *c, double pitch) -{ - double nx, ny, nz; - - nx = c->x; - ny = (c->y * cos(pitch)) - (c->z * sin(pitch)); - nz = (c->y * sin(pitch)) + (c->z * cos(pitch)); - - c->x = nx; c->y = ny; c->z = nz; -} - -static void -y_rot (struct my_coords *c, double yaw) -{ - double nx, ny, nz; - - nx = (c->x * cos(yaw)) - (c->z * sin(yaw)); - ny = c->y; - nz = (c->x * sin(yaw)) + (c->z * cos(yaw)); - - c->x = nx; c->y = ny; c->z = nz; -} - -static void -z_rot (struct my_coords *c, double roll) -{ - double nx, ny, nz; - - nx = (c->x * cos(roll)) - (c->y * sin(roll)); - ny = (c->x * sin(roll)) + (c->y * cos(roll)); - nz = c->z; - - c->x = nx; c->y = ny; c->z = nz; -} - -static void -my_get_angles (struct my_coords *in_o, struct my_coords *in_u, struct my_angles *a) -{ - double rad_yaw, rad_pitch; - struct my_coords o, u; - - a->pitch = 0.0; - a->yaw = 0.0; - a->roll = 0.0; - - // make a copy of the coords - o.x = in_o->x; o.y = in_o->y; o.z = in_o->z; - u.x = in_u->x; u.y = in_u->y; u.z = in_u->z; - - // special case when looking straight up or down - if ((o.x == 0.0) && (o.z == 0.0)) { - a->yaw = 0.0; - if (o.y > 0.0) { a->pitch = -90.0; a->roll = 180.0 - DEG(atan2(u.x, u.z)); } // down - else { a->pitch = 90.0; a->roll = DEG(atan2(u.x, u.z)); } // up - return; - } - - // get yaw angle and then rotate o and u so that yaw = 0 - rad_yaw = atan2 (-o.x, o.z); - a->yaw = DEG (rad_yaw); - - y_rot (&o, -rad_yaw); - y_rot (&u, -rad_yaw); - - // get pitch and then rotate o and u so that pitch = 0 - rad_pitch = atan2 (-o.y, o.z); - a->pitch = DEG (rad_pitch); - - x_rot (&o, -rad_pitch); - x_rot (&u, -rad_pitch); - - // get roll - a->roll = DEG (-atan2(u.x, u.y)); -} - -static void -get_ypr (double yaw, double pitch, double roll, int side, struct my_angles *a) -{ - struct my_coords o, u; - - // get 'o' (observer) and 'u' ('this_way_up') depending on box side - switch(side) { - case BOX_FRONT: - o.x = 0.0; o.y = 0.0; o.z = 1.0; - u.x = 0.0; u.y = 1.0; u.z = 0.0; - break; - case BOX_BEHIND: - o.x = 0.0; o.y = 0.0; o.z = -1.0; - u.x = 0.0; u.y = 1.0; u.z = 0.0; - break; - case BOX_LEFT: - o.x = -1.0; o.y = 0.0; o.z = 0.0; - u.x = -1.0; u.y = 1.0; u.z = 0.0; - break; - case BOX_RIGHT: - o.x = 1.0; o.y = 0.0; o.z = 0.0; - u.x = 0.0; u.y = 1.0; u.z = 0.0; - break; - case BOX_TOP: - o.x = 0.0; o.y = -1.0; o.z = 0.0; - u.x = 0.0; u.y = 0.0; u.z = -1.0; - break; - case BOX_BOTTOM: - o.x = 0.0; o.y = 1.0; o.z = 0.0; - u.x = 0.0; u.y = 0.0; u.z = -1.0; - break; - } - z_rot (&o, roll); z_rot (&u, roll); - x_rot (&o, pitch); x_rot (&u, pitch); - y_rot (&o, yaw); y_rot (&u, yaw); - - my_get_angles (&o, &u, a); - - // normalise angles - while (a->yaw < 0.0) a->yaw += 360.0; - while (a->yaw > 360.0) a->yaw -= 360.0; - while (a->pitch < 0.0) a->pitch += 360.0; - while (a->pitch > 360.0) a->pitch -= 360.0; - while (a->roll < 0.0) a->roll += 360.0; - while (a->roll > 360.0) a->roll -= 360.0; -} +static int sw_cube_map_size; static void fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov) { int x, y; + int scrsize = sw_cube_map_size * sw_cube_map_size; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { double dx = x-width/2; double dy = -(y-height/2); double yaw = sqrt(dx*dx+dy*dy)*fov/((double)width); - double roll = -atan2(dy, dx); + double roll = atan2(dy, dx); double sx = sin(yaw) * cos(roll); double sy = sin(yaw) * sin(roll); double sz = cos(yaw); @@ -1035,26 +927,26 @@ fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov) else { side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); } } - #define RC(x) ((x / 2.06) + 0.5) - #define R2(x) ((x / 2.03) + 0.5) + #define RC(x) ((x / 2) + 0.5) + #define R2(x) ((x / 2) + 0.5) // scale up our vector [x,y,z] to the box switch(side) { - case BOX_FRONT: xs = RC( sx / sz); ys = R2( sy / sz); break; - case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2( sy / -sz); break; - case BOX_LEFT: xs = RC( sz / -sx); ys = R2( sy / -sx); break; - case BOX_RIGHT: xs = RC(-sz / sx); ys = R2( sy / sx); break; - case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / -sy); break; //bot - case BOX_BOTTOM: xs = RC(-sx / sy); ys = R2( sz / -sy); break; //top?? + case BOX_FRONT: xs = RC( sx / sz); ys = R2(-sy / sz); break; + case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2(-sy / -sz); break; + case BOX_LEFT: xs = RC( sz / -sx); ys = R2(-sy / -sx); break; + case BOX_RIGHT: xs = RC(-sz / sx); ys = R2(-sy / sx); break; + case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / sy); break; + case BOX_BOTTOM: xs = RC( sx / -sy); ys = R2( sz / sy); break; } if (xs < 0.0) xs = 0.0; if (xs >= 1.0) xs = 0.999; if (ys < 0.0) ys = 0.0; if (ys >= 1.0) ys = 0.999; - *buf++ = scrp+(((int)(xs*(double)width))+ - ((int)(ys*(double)height))*width)+ - side*width*height; + int sxs = xs * sw_cube_map_size; + int sys = ys * sw_cube_map_size; + *buf++ = scrp+side * scrsize + sys * sw_cube_map_size + sxs; } } } @@ -1070,18 +962,45 @@ rendercopy (void *dest) } static void -renderside (byte* bufs, double yaw, double pitch, double roll, int side) +renderside (byte *bufs, int side) { - struct my_angles a; + mat4f_t camera; + mat4f_t camera_inverse; + mat4f_t rotinv; + + memcpy (camera, r_refdef.camera, sizeof (camera)); + memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse)); + mmulf (r_refdef.camera, camera, box_rotations[side]); + mat4ftranspose (rotinv, box_rotations[side]); + mmulf (r_refdef.camera_inverse, rotinv, camera_inverse); + + //FIXME see fixme in r_screen.c + r_refdef.frame.mat[0] = -r_refdef.camera[1]; + r_refdef.frame.mat[1] = r_refdef.camera[0]; + r_refdef.frame.mat[2] = r_refdef.camera[2]; + r_refdef.frame.mat[3] = r_refdef.camera[3]; + + float fov_x = r_refdef.fov_x; + float fov_y = r_refdef.fov_y; + unsigned width = vid.width; + unsigned height = vid.height; + vrect_t rect = r_refdef.vrect; + r_refdef.fov_x = r_refdef.fov_y = 90; + r_refdef.vrect.x = r_refdef.vrect.y = 0; + r_refdef.vrect.height = r_refdef.vrect.width = sw_cube_map_size; + vid.height = vid.width = sw_cube_map_size; + R_ViewChanged (); - get_ypr (RAD(yaw), RAD(pitch), RAD(roll), side, &a); - if (side == BOX_RIGHT) { a.roll = -a.roll; a.pitch = -a.pitch; } - if (side == BOX_LEFT) { a.roll = -a.roll; a.pitch = -a.pitch; } - if (side == BOX_TOP) { a.yaw += 180.0; a.pitch = 180.0 - a.pitch; } - r_refdef.viewangles[YAW] = a.yaw; - r_refdef.viewangles[PITCH] = a.pitch; - r_refdef.viewangles[ROLL] = a.roll; rendercopy (bufs); + + r_refdef.vrect = rect; + vid.height = height; + vid.width = width; + r_refdef.fov_x = fov_x; + r_refdef.fov_y = fov_y; + + memcpy (r_refdef.camera, camera, sizeof (camera)); + memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); } static void @@ -1099,14 +1018,12 @@ renderlookup (byte **offs, byte* bufs) static void R_RenderViewFishEye (void) { + sw_cube_map_size = vid.width; int width = vid.width; //r_refdef.vrect.width; int height = vid.height; //r_refdef.vrect.height; - int scrsize = width*height; + int scrsize = sw_cube_map_size * sw_cube_map_size; int fov = scr_ffov->int_val; int views = scr_fviews->int_val; - double yaw = r_refdef.viewangles[YAW]; - double pitch = r_refdef.viewangles[PITCH]; - double roll = 0; //r_refdef.viewangles[ROLL]; static int pwidth = -1; static int pheight = -1; static int pfov = -1; @@ -1119,14 +1036,15 @@ R_RenderViewFishEye (void) if (pwidth != width || pheight != height || pfov != fov) { if (scrbufs) free (scrbufs); if (offs) free (offs); - scrbufs = malloc (scrsize*6); // front|right|back|left|top|bottom + // front|right|back|left|top|bottom + scrbufs = malloc (scrsize*6); SYS_CHECKMEM (scrbufs); - offs = malloc (scrsize*sizeof(byte*)); + offs = malloc (width*height*sizeof(byte*)); SYS_CHECKMEM (offs); pwidth = width; pheight = height; pfov = fov; - fisheyelookuptable (offs, width, height, scrbufs, ((double)fov)*M_PI/180.0); + fisheyelookuptable (offs, width, height, scrbufs, fov*M_PI/180.0); } if (views != pviews) { @@ -1135,19 +1053,27 @@ R_RenderViewFishEye (void) } switch (views) { - case 6: renderside (scrbufs+scrsize*2, yaw, pitch, roll, BOX_BEHIND); - case 5: renderside (scrbufs+scrsize*5, yaw, pitch, roll, BOX_BOTTOM); - case 4: renderside (scrbufs+scrsize*4, yaw, pitch, roll, BOX_TOP); - case 3: renderside (scrbufs+scrsize*3, yaw, pitch, roll, BOX_LEFT); - case 2: renderside (scrbufs+scrsize, yaw, pitch, roll, BOX_RIGHT); - default: renderside (scrbufs, yaw, pitch, roll, BOX_FRONT); + case 6: renderside (scrbufs + scrsize * BOX_BEHIND, BOX_BEHIND); + case 5: renderside (scrbufs + scrsize * BOX_BOTTOM, BOX_BOTTOM); + case 4: renderside (scrbufs + scrsize * BOX_TOP, BOX_TOP); + case 3: renderside (scrbufs + scrsize * BOX_LEFT, BOX_LEFT); + case 2: renderside (scrbufs + scrsize * BOX_RIGHT, BOX_RIGHT); + default: renderside (scrbufs + scrsize * BOX_FRONT, BOX_FRONT); } - - r_refdef.viewangles[YAW] = yaw; - r_refdef.viewangles[PITCH] = pitch; - r_refdef.viewangles[ROLL] = roll; +#if 0 + memset (scrbufs + scrsize*0, 31, sw_cube_map_size); + memset (scrbufs + scrsize*1, 31, sw_cube_map_size); + memset (scrbufs + scrsize*2, 31, sw_cube_map_size); + memset (scrbufs + scrsize*3, 31, sw_cube_map_size); + memset (scrbufs + scrsize*4, 31, sw_cube_map_size); + memset (scrbufs + scrsize*5, 31, sw_cube_map_size); + for (int y = 0; y < sw_cube_map_size * 6; y++) { + scrbufs[y * sw_cube_map_size] = 31; + scrbufs[y * sw_cube_map_size + sw_cube_map_size - 1] = 31; + } +#endif renderlookup (offs, scrbufs); -}*/ +} void R_ClearState (void) diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index d29b68186..1d7bc491f 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -233,7 +233,9 @@ R_SetupFrame (void) (h / (float) vid.height))); R_ViewChanged (); } - } else { + } else if (!scr_fisheye->int_val) { + //FIXME the above test shouldn't be necessary (this whole section + //is a bit of a mess, though) r_refdef.vrect.x = vr_data.scr_view->xpos; r_refdef.vrect.y = vr_data.scr_view->ypos; r_refdef.vrect.width = vr_data.scr_view->xlen; From 1d93bcfc348d660cbaaa69de16c133b1d57ec190 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Mar 2022 00:09:37 +0900 Subject: [PATCH 2534/3664] [gl] Clean out some missed mirror code --- libs/video/renderer/gl/gl_rmain.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index a48035799..f69b63228 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -71,7 +71,6 @@ qboolean gl_envmap; // true during envmap command capture int gl_mirrortexturenum; // quake texturenum, not gltexturenum -qboolean gl_mirror; plane_t *gl_mirror_plane; float gl_r_world_matrix[16]; @@ -383,14 +382,7 @@ R_SetupGL (void) { R_SetupGL_Viewport_and_Perspective (); - if (gl_mirror) { - if (gl_mirror_plane->normal[2]) - qfglScalef (1, -1, 1); - else - qfglScalef (-1, 1, 1); - qfglFrontFace (GL_CCW); - } else - qfglFrontFace (GL_CW); + qfglFrontFace (GL_CW); qfglMatrixMode (GL_MODELVIEW); qfglLoadIdentity (); @@ -460,8 +452,6 @@ R_RenderView_ (void) return; } - gl_mirror = false; - // render normal view R_RenderScene (); From fb4fd979ec51d69557c43d0d6419c897f44ed98e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Mar 2022 12:33:25 +0900 Subject: [PATCH 2535/3664] [gl] Move error check support into a better place This makes it a little easier to spam checks everywhere and thus narrow down the location of the error. --- include/vid_gl.h | 2 + libs/video/renderer/gl/gl_rmain.c | 84 --------------------------- libs/video/renderer/vid_render_gl.c | 90 +++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 84 deletions(-) diff --git a/include/vid_gl.h b/include/vid_gl.h index 3d16e75db..618e89d44 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -31,4 +31,6 @@ void gl_Fog_DisableGFog (void); void gl_Fog_StartAdditive (void); void gl_Fog_StopAdditive (void); +void gl_errors (const char *msg); + #endif//__vid_gl_h diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index f69b63228..1050fef18 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -79,86 +79,6 @@ float gl_r_world_matrix[16]; //vec3_t gl_shadecolor; // Ender (Extend) Colormod float gl_modelalpha; // Ender (Extend) Alpha -/* Unknown renamed to GLErr_Unknown to solve conflict with winioctl.h */ -static unsigned int GLErr_InvalidEnum; -static unsigned int GLErr_InvalidValue; -static unsigned int GLErr_InvalidOperation; -static unsigned int GLErr_OutOfMemory; -static unsigned int GLErr_StackOverflow; -static unsigned int GLErr_StackUnderflow; -static unsigned int GLErr_Unknown; - -static unsigned int -R_TestErrors (unsigned int numerous) -{ - switch (qfglGetError ()) { - case GL_NO_ERROR: - return numerous; - break; - case GL_INVALID_ENUM: - GLErr_InvalidEnum++; - R_TestErrors (numerous++); - break; - case GL_INVALID_VALUE: - GLErr_InvalidValue++; - R_TestErrors (numerous++); - break; - case GL_INVALID_OPERATION: - GLErr_InvalidOperation++; - R_TestErrors (numerous++); - break; - case GL_STACK_OVERFLOW: - GLErr_StackOverflow++; - R_TestErrors (numerous++); - break; - case GL_STACK_UNDERFLOW: - GLErr_StackUnderflow++; - R_TestErrors (numerous++); - break; - case GL_OUT_OF_MEMORY: - GLErr_OutOfMemory++; - R_TestErrors (numerous++); - break; - default: - GLErr_Unknown++; - R_TestErrors (numerous++); - break; - } - - return numerous; -} - -static void -R_DisplayErrors (void) -{ - if (GLErr_InvalidEnum) - printf ("%d OpenGL errors: Invalid Enum!\n", GLErr_InvalidEnum); - if (GLErr_InvalidValue) - printf ("%d OpenGL errors: Invalid Value!\n", GLErr_InvalidValue); - if (GLErr_InvalidOperation) - printf ("%d OpenGL errors: Invalid Operation!\n", GLErr_InvalidOperation); - if (GLErr_StackOverflow) - printf ("%d OpenGL errors: Stack Overflow!\n", GLErr_StackOverflow); - if (GLErr_StackUnderflow) - printf ("%d OpenGL errors: Stack Underflow\n!", GLErr_StackUnderflow); - if (GLErr_OutOfMemory) - printf ("%d OpenGL errors: Out Of Memory!\n", GLErr_OutOfMemory); - if (GLErr_Unknown) - printf ("%d Unknown OpenGL errors!\n", GLErr_Unknown); -} - -static void -R_ClearErrors (void) -{ - GLErr_InvalidEnum = 0; - GLErr_InvalidValue = 0; - GLErr_InvalidOperation = 0; - GLErr_OutOfMemory = 0; - GLErr_StackOverflow = 0; - GLErr_StackUnderflow = 0; - GLErr_Unknown = 0; -} - void glrmain_init (void) { @@ -431,10 +351,6 @@ R_RenderScene (void) gl_R_DrawParticles (); gl_Fog_DisableGFog (); - - if (R_TestErrors (0)) - R_DisplayErrors (); - R_ClearErrors (); } /* diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 05a7c378c..ac93ae5c2 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -47,6 +47,96 @@ gl_ctx_t *gl_ctx; +/* Unknown renamed to GLErr_Unknown to solve conflict with winioctl.h */ +static unsigned int GLErr_InvalidEnum; +static unsigned int GLErr_InvalidValue; +static unsigned int GLErr_InvalidOperation; +static unsigned int GLErr_OutOfMemory; +static unsigned int GLErr_StackOverflow; +static unsigned int GLErr_StackUnderflow; +static unsigned int GLErr_Unknown; + +static unsigned int +R_TestErrors (unsigned int numerous) +{ + switch (qfglGetError ()) { + case GL_NO_ERROR: + return numerous; + break; + case GL_INVALID_ENUM: + GLErr_InvalidEnum++; + R_TestErrors (numerous++); + break; + case GL_INVALID_VALUE: + GLErr_InvalidValue++; + R_TestErrors (numerous++); + break; + case GL_INVALID_OPERATION: + GLErr_InvalidOperation++; + R_TestErrors (numerous++); + break; + case GL_STACK_OVERFLOW: + GLErr_StackOverflow++; + R_TestErrors (numerous++); + break; + case GL_STACK_UNDERFLOW: + GLErr_StackUnderflow++; + R_TestErrors (numerous++); + break; + case GL_OUT_OF_MEMORY: + GLErr_OutOfMemory++; + R_TestErrors (numerous++); + break; + default: + GLErr_Unknown++; + R_TestErrors (numerous++); + break; + } + + return numerous; +} + +static void +R_DisplayErrors (void) +{ + if (GLErr_InvalidEnum) + printf ("%d OpenGL errors: Invalid Enum!\n", GLErr_InvalidEnum); + if (GLErr_InvalidValue) + printf ("%d OpenGL errors: Invalid Value!\n", GLErr_InvalidValue); + if (GLErr_InvalidOperation) + printf ("%d OpenGL errors: Invalid Operation!\n", GLErr_InvalidOperation); + if (GLErr_StackOverflow) + printf ("%d OpenGL errors: Stack Overflow!\n", GLErr_StackOverflow); + if (GLErr_StackUnderflow) + printf ("%d OpenGL errors: Stack Underflow\n!", GLErr_StackUnderflow); + if (GLErr_OutOfMemory) + printf ("%d OpenGL errors: Out Of Memory!\n", GLErr_OutOfMemory); + if (GLErr_Unknown) + printf ("%d Unknown OpenGL errors!\n", GLErr_Unknown); +} + +static void +R_ClearErrors (void) +{ + GLErr_InvalidEnum = 0; + GLErr_InvalidValue = 0; + GLErr_InvalidOperation = 0; + GLErr_OutOfMemory = 0; + GLErr_StackOverflow = 0; + GLErr_StackUnderflow = 0; + GLErr_Unknown = 0; +} + +void +gl_errors (const char *msg) +{ + if (R_TestErrors (0)) { + printf ("gl_errors: %s\n", msg); + R_DisplayErrors (); + } + R_ClearErrors (); +} + static void gl_vid_render_choose_visual (void *data) { From 5a57280aa900d2831497f36f3c9f525b6154acf2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Mar 2022 13:29:05 +0900 Subject: [PATCH 2536/3664] [gl] Use glGenTextures to allocate texture numbers While the scheme of using our own allocated did work just fine, fisheye rendering uses glGenTextures which caused a texture id clash and thus invalid operations (the cube map texture happened to be the same as the console background texture). Sure, I could have just "fixed" the fisheye init code, but this brings gl closer in line with glsl (which makes extensive use of glGenTextures and glDeleteTextures). This doesn't fix any texture leaks gl has (plenty, I imagine), but it's a step in the right direction. --- include/QF/GL/qf_lightmap.h | 4 +++- include/QF/GL/qf_rmain.h | 2 +- include/QF/GL/qf_sky.h | 3 +++ include/QF/GL/qf_textures.h | 3 ++- include/QF/GL/qf_vid.h | 1 - include/mod_internal.h | 2 +- include/r_shared.h | 3 --- libs/models/gl_skin.c | 23 ++++++++++------------- libs/video/renderer/gl/gl_draw.c | 4 ++-- libs/video/renderer/gl/gl_dyn_textures.c | 4 ++-- libs/video/renderer/gl/gl_graph.c | 12 ++++-------- libs/video/renderer/gl/gl_lightmap.c | 13 ++++++------- libs/video/renderer/gl/gl_rmisc.c | 5 ++--- libs/video/renderer/gl/gl_rsurf.c | 8 ++++---- libs/video/renderer/gl/gl_sky.c | 14 ++++++++------ libs/video/renderer/gl/gl_textures.c | 5 ++--- libs/video/renderer/gl/vid_common_gl.c | 1 - 17 files changed, 50 insertions(+), 57 deletions(-) diff --git a/include/QF/GL/qf_lightmap.h b/include/QF/GL/qf_lightmap.h index 102f26313..37485888f 100644 --- a/include/QF/GL/qf_lightmap.h +++ b/include/QF/GL/qf_lightmap.h @@ -28,6 +28,8 @@ #ifndef __QF_GL_lightmap_h #define __QF_GL_lightmap_h +#include "QF/GL/types.h" + // LordHavoc: since lightmaps are now allocated only as needed, allow a ridiculous number :) #define MAX_LIGHTMAPS 1024 #define BLOCK_WIDTH 64 @@ -40,7 +42,7 @@ typedef struct glRect_s { extern int lm_src_blend, lm_dest_blend; extern model_t *gl_currentmodel; -extern int gl_lightmap_textures; +extern GLuint gl_lightmap_textures[MAX_LIGHTMAPS]; extern qboolean gl_lightmap_modified[MAX_LIGHTMAPS]; extern instsurf_t *gl_lightmap_polys[MAX_LIGHTMAPS]; extern glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; diff --git a/include/QF/GL/qf_rmain.h b/include/QF/GL/qf_rmain.h index 651a9fff2..d6b8fe94b 100644 --- a/include/QF/GL/qf_rmain.h +++ b/include/QF/GL/qf_rmain.h @@ -51,6 +51,6 @@ void gl_R_RenderView (void); void gl_R_ClearState (void); void gl_R_ViewChanged (void); void gl_R_LineGraph (int x, int y, int *h_vals, int count, int height); -int gl_R_InitGraphTextures (int base); +void gl_R_InitGraphTextures (void); #endif // __QF_GL_rmain_h diff --git a/include/QF/GL/qf_sky.h b/include/QF/GL/qf_sky.h index f2f030bb4..b7a0fc35a 100644 --- a/include/QF/GL/qf_sky.h +++ b/include/QF/GL/qf_sky.h @@ -30,11 +30,14 @@ #include "QF/qtypes.h" #include "QF/model.h" +#include "QF/GL/types.h" #define SKY_TEX 2000 // Quake 2 environment sky extern qboolean gl_skyloaded; extern vec5_t gl_skyvec[6][4]; +extern GLuint gl_solidskytexture; +extern GLuint gl_alphaskytexture; struct texture_s; diff --git a/include/QF/GL/qf_textures.h b/include/QF/GL/qf_textures.h index aae32fb50..9a905b649 100644 --- a/include/QF/GL/qf_textures.h +++ b/include/QF/GL/qf_textures.h @@ -29,6 +29,7 @@ #define __gl_textures_h #include "QF/qtypes.h" +#include "QF/GL/types.h" #define MAX_GLTEXTURES 2048 @@ -39,7 +40,7 @@ extern int gl_filter_min; extern int gl_filter_max; extern qboolean gl_Anisotropy; extern float gl_aniso; -extern int gl_part_tex; +extern GLuint gl_part_tex; void GL_Upload8 (const byte *data, int width, int height, qboolean mipmap, qboolean alpha); void GL_Upload8_EXT (const byte *data, int width, int height, qboolean mipmap, qboolean alpha); diff --git a/include/QF/GL/qf_vid.h b/include/QF/GL/qf_vid.h index bb6291aa1..6702c2a6e 100644 --- a/include/QF/GL/qf_vid.h +++ b/include/QF/GL/qf_vid.h @@ -44,7 +44,6 @@ extern qboolean gl_mtex_fullbright; extern GLenum gl_mtex_enum; extern qboolean gl_combine_capable; extern float gl_rgb_scale; -extern int gl_texture_number; extern qboolean gl_feature_mach64; extern float gldepthmin, gldepthmax; diff --git a/include/mod_internal.h b/include/mod_internal.h index 9126a3280..b54496dc4 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -120,6 +120,6 @@ void glsl_Skin_InitTranslations (void); void gl_Skin_SetupSkin (skin_t *skin, int cmap); void gl_Skin_ProcessTranslation (int cmap, const byte *translation); void gl_Skin_InitTranslations (void); -int gl_Skin_Init_Textures (int base); +void gl_Skin_Init_Textures (void); void gl_Skin_SetPlayerSkin (int width, int height, const byte *data); #endif// __mod_internal_h diff --git a/include/r_shared.h b/include/r_shared.h index d24632139..843978033 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -137,9 +137,6 @@ extern void SetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, extern int r_skymade; extern void R_MakeSky (void); -extern int gl_solidskytexture; -extern int gl_alphaskytexture; - // flags in finalvert_t.flags #define ALIAS_LEFT_CLIP 0x0001 #define ALIAS_TOP_CLIP 0x0002 diff --git a/libs/models/gl_skin.c b/libs/models/gl_skin.c index e55a88791..5ecef36ba 100644 --- a/libs/models/gl_skin.c +++ b/libs/models/gl_skin.c @@ -60,8 +60,8 @@ typedef struct { qboolean fb; } glskin_t; -static int skin_textures; -static int skin_fb_textures; +static GLuint skin_textures[MAX_TRANSLATIONS]; +static GLuint skin_fb_textures[MAX_TRANSLATIONS]; static byte skin_cmap[MAX_TRANSLATIONS][256]; static glskin_t skins[MAX_TRANSLATIONS]; @@ -189,10 +189,10 @@ build_skin (skin_t *skin, int cmap) if (!s->tex) // we haven't loaded the player model yet return; - texnum = skin_textures + cmap; + texnum = skin_textures[cmap]; fb_texnum = 0; if (s->fb) - fb_texnum = skin_fb_textures + cmap; + fb_texnum = skin_fb_textures[cmap]; if (skin) { skin->texnum = texnum; skin->auxtex = fb_texnum; @@ -245,9 +245,9 @@ gl_Skin_SetupSkin (skin_t *skin, int cmap) changed = (s->tex != skin->texels); s->tex = skin->texels; if (!changed) { - skin->texnum = skin_textures + cmap; + skin->texnum = skin_textures[cmap]; if (s->fb) - skin->auxtex = skin_fb_textures + cmap; + skin->auxtex = skin_fb_textures[cmap]; return; } if (s->tex) @@ -260,12 +260,9 @@ gl_Skin_InitTranslations (void) { } -int -gl_Skin_Init_Textures (int base) +void +gl_Skin_Init_Textures (void) { - skin_textures = base; - base += MAX_TRANSLATIONS; - skin_fb_textures = base; - base += MAX_TRANSLATIONS; - return base; + qfglGenTextures (MAX_TRANSLATIONS, skin_textures); + qfglGenTextures (MAX_TRANSLATIONS, skin_fb_textures); } diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 6d64779d8..c2009f609 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -82,7 +82,7 @@ static float *textCoords, *tC; static qpic_t *draw_backtile; static cc_cell_t char_cells[256]; -static int translate_texture; +static GLuint translate_texture; static int char_texture; static int cs_texture; // crosshair texturea @@ -403,7 +403,7 @@ gl_Draw_Init (void) qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // save a texture slot for translated picture - translate_texture = gl_texture_number++; + qfglGenTextures (1, &translate_texture); // get the other pics we need draw_backtile = gl_Draw_PicFromWad ("backtile"); diff --git a/libs/video/renderer/gl/gl_dyn_textures.c b/libs/video/renderer/gl/gl_dyn_textures.c index 28e7d8ef4..d9004a69a 100644 --- a/libs/video/renderer/gl/gl_dyn_textures.c +++ b/libs/video/renderer/gl/gl_dyn_textures.c @@ -46,7 +46,7 @@ #include "r_internal.h" -int gl_part_tex; +GLuint gl_part_tex; static GLint part_tex_internal_format = 2; @@ -57,7 +57,7 @@ GDT_InitParticleTexture (void) memset (data, 0, sizeof (data)); - gl_part_tex = gl_texture_number++; + qfglGenTextures (1, &gl_part_tex); qfglBindTexture (GL_TEXTURE_2D, gl_part_tex); qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); diff --git a/libs/video/renderer/gl/gl_graph.c b/libs/video/renderer/gl/gl_graph.c index 12c5e3774..8e816eb11 100644 --- a/libs/video/renderer/gl/gl_graph.c +++ b/libs/video/renderer/gl/gl_graph.c @@ -52,20 +52,16 @@ #define NUM_GRAPH_TEXTURES 8 static byte *graph_texels[NUM_GRAPH_TEXTURES]; -static int graph_texture[NUM_GRAPH_TEXTURES]; +static GLuint graph_texture[NUM_GRAPH_TEXTURES]; static int graph_index; static int graph_size[NUM_GRAPH_TEXTURES]; static int graph_width[NUM_GRAPH_TEXTURES]; -int -gl_R_InitGraphTextures (int base) +void +gl_R_InitGraphTextures (void) { - int i; - - for (i = 0; i < NUM_GRAPH_TEXTURES; i++) - graph_texture[i] = base++; - return base; + qfglGenTextures (NUM_GRAPH_TEXTURES, graph_texture); } void diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 964b5aa36..ca54c7061 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -59,7 +59,7 @@ static int dlightdivtable[8192]; static int gl_internalformat; // 1 or 3 static int lightmap_bytes; // 1, 3, or 4 -int gl_lightmap_textures; +GLuint gl_lightmap_textures[MAX_LIGHTMAPS]; // keep lightmap texture data in main memory so texsubimage can update properly // LordHavoc: changed to be allocated at runtime (typically lower memory usage) @@ -480,7 +480,7 @@ gl_R_CalcLightmaps (void) if (!gl_lightmap_polys[i]) continue; if (gl_lightmap_modified[i]) { - qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + i); + qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures[i]); GL_UploadLightmap (i); gl_lightmap_modified[i] = false; } @@ -500,7 +500,7 @@ gl_R_BlendLightmaps (void) for (i = 0; i < MAX_LIGHTMAPS; i++) { for (sc = gl_lightmap_polys[i]; sc; sc = sc->lm_chain) { - qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + i); + qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures[i]); if (sc->transform) { qfglPushMatrix (); qfglLoadMatrixf (sc->transform); @@ -691,9 +691,8 @@ GL_BuildLightmaps (model_t **models, int num_models) r_framecount = 1; // no dlightcache - if (!gl_lightmap_textures) { - gl_lightmap_textures = gl_texture_number; - gl_texture_number += MAX_LIGHTMAPS; + if (!gl_lightmap_textures[0]) { + qfglGenTextures (MAX_LIGHTMAPS, gl_lightmap_textures); } switch (r_lightmap_components->int_val) { @@ -756,7 +755,7 @@ GL_BuildLightmaps (model_t **models, int num_models) gl_lightmap_rectchange[i].t = BLOCK_HEIGHT; gl_lightmap_rectchange[i].w = 0; gl_lightmap_rectchange[i].h = 0; - qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + i); + qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures[i]); qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (gl_Anisotropy) diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 2cbfcdfee..93375ece1 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -187,9 +187,8 @@ gl_R_Init (void) GDT_Init (); - gl_texture_number = gl_R_InitGraphTextures (gl_texture_number); - - gl_texture_number = gl_Skin_Init_Textures (gl_texture_number); + gl_R_InitGraphTextures (); + gl_Skin_Init_Textures (); r_init = 1; gl_R_InitParticles (); diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 9b6bd214c..0de24b23f 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -397,8 +397,8 @@ DrawTextureChains (int disable_blend, int do_bind) } if (s->color && do_bind) qfglColor4fv (s->color); - qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + - surf->lightmaptexturenum); + qfglBindTexture (GL_TEXTURE_2D, + gl_lightmap_textures[surf->lightmaptexturenum]); R_RenderBrushPoly_3 (surf); @@ -416,8 +416,8 @@ DrawTextureChains (int disable_blend, int do_bind) qglActiveTexture (gl_mtex_enum + 1); for (s = tex->tex_chain; s; s = s->tex_chain) { surf = s->surface; - qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures + - surf->lightmaptexturenum); + qfglBindTexture (GL_TEXTURE_2D, + gl_lightmap_textures[surf->lightmaptexturenum]); if (s->transform) { qfglPushMatrix (); diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index b0f00cfbe..47c6bc072 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -56,8 +56,8 @@ // cube from the outside on the -ve y axis with +x to the right, +y going in, // +z up, and front is the nearest face. static const char *suf[6] = { "rt", "bk", "lf", "ft", "up", "dn" }; -int gl_solidskytexture; -int gl_alphaskytexture; +GLuint gl_solidskytexture; +GLuint gl_alphaskytexture; // Set to true if a valid skybox is loaded --KB qboolean gl_skyloaded = false; @@ -428,8 +428,9 @@ gl_R_InitSky (texture_t *mt) ((byte *) & transpix)[2] = b / (128 * 128); ((byte *) & transpix)[3] = 0; - if (!gl_solidskytexture) - gl_solidskytexture = gl_texture_number++; + if (!gl_solidskytexture) { + qfglGenTextures (1, &gl_solidskytexture); + } qfglBindTexture (GL_TEXTURE_2D, gl_solidskytexture); qfglTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); @@ -448,8 +449,9 @@ gl_R_InitSky (texture_t *mt) trans[(i * 128) + j] = d_8to24table[p]; } - if (!gl_alphaskytexture) - gl_alphaskytexture = gl_texture_number++; + if (!gl_alphaskytexture) { + qfglGenTextures (1, &gl_alphaskytexture); + } qfglBindTexture (GL_TEXTURE_2D, gl_alphaskytexture); qfglTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans); diff --git a/libs/video/renderer/gl/gl_textures.c b/libs/video/renderer/gl/gl_textures.c index 85a43eec9..9beb146dc 100644 --- a/libs/video/renderer/gl/gl_textures.c +++ b/libs/video/renderer/gl/gl_textures.c @@ -55,7 +55,7 @@ #include "vid_internal.h" typedef struct { - int texnum; + GLuint texnum; char identifier[64]; int width, height; int bytesperpixel; @@ -584,8 +584,7 @@ GL_LoadTexture (const char *identifier, int width, int height, const byte *data, strncpy (glt->identifier, identifier, sizeof (glt->identifier) - 1); glt->identifier[sizeof (glt->identifier) - 1] = '\0'; - glt->texnum = gl_texture_number; - gl_texture_number++; + qfglGenTextures (1, &glt->texnum); SetupTexture: glt->crc = crc; diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index ce8a5e3d6..d1547d2d9 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -79,7 +79,6 @@ int gl_use_bgra; int gl_va_capable; static int driver_vaelements; int vaelements; -int gl_texture_number = 1; int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; int gl_filter_max = GL_LINEAR; float gldepthmin, gldepthmax; From 91d7a80dff69c4f11d161b602c47ed417816a65b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Mar 2022 15:42:43 +0900 Subject: [PATCH 2537/3664] [renderer] Get timegraph and zgraph working Only for sw and gl right now, but this sorts out the issues that prevented the graphs working at all. --- include/QF/plugin/vid_render.h | 2 +- include/QF/screen.h | 6 +++++- include/r_local.h | 4 +--- libs/video/renderer/gl/gl_rmain.c | 5 ----- libs/video/renderer/r_graph.c | 27 ++++++++++++------------- libs/video/renderer/r_main.c | 2 +- libs/video/renderer/r_screen.c | 5 +++-- libs/video/renderer/sw/sw_rmain.c | 6 ------ libs/video/renderer/vid_render_gl.c | 8 ++++++-- libs/video/renderer/vid_render_glsl.c | 8 ++++++-- libs/video/renderer/vid_render_sw.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 2 +- nq/source/cl_screen.c | 20 ++++++++++++++++++ 13 files changed, 58 insertions(+), 39 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index c3dbc62e6..aff978c79 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -108,7 +108,7 @@ typedef struct vid_render_funcs_s { void (*begin_frame) (void); void (*render_view) (void); - void (*set_2d) (void); + void (*set_2d) (int scaled); void (*end_frame) (void); vid_model_funcs_t *model_funcs; diff --git a/include/QF/screen.h b/include/QF/screen.h index 4b3215064..7db658a4c 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -46,8 +46,12 @@ void SCR_UpdateScreen (struct transform_s *camera, double realtime, void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); struct tex_s *SCR_SnapScreen (unsigned width, unsigned height); -extern struct cvar_s *hud_fps, *hud_time; +extern struct cvar_s *hud_fps, *hud_time, *r_timegraph, *r_zgraph; extern int scr_copytop; extern qboolean scr_skipupdate; +struct view_s; +void R_TimeGraph (struct view_s *view); +void R_ZGraph (struct view_s *view); + #endif//__QF_screen_h diff --git a/include/r_local.h b/include/r_local.h index 1c42b3685..53a503a2f 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -281,7 +281,7 @@ extern int r_maxvalidedgeoffset; void R_AliasClipTriangle (mtriangle_t *ptri); -extern float r_time1; +extern double r_time1; extern int r_frustum_indexes[4*6]; extern int r_maxsurfsseen, r_maxedgesseen; extern qboolean r_dowarpold, r_viewchanged; @@ -296,8 +296,6 @@ extern vec3_t lightspot; void R_StoreEfrags (const efrag_t *ppefrag); void R_TimeRefresh_f (void); -void R_TimeGraph (void); -void R_ZGraph (void); void R_PrintAliasStats (void); void R_PrintTimes (void); void R_AnimateLight (void); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 1050fef18..b45ea5acf 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -370,11 +370,6 @@ R_RenderView_ (void) // render normal view R_RenderScene (); - - if (r_timegraph->int_val) - R_TimeGraph (); - if (r_zgraph->int_val) - R_ZGraph (); } static void R_RenderViewFishEye (void); diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index 7c890dcb7..c831780a5 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -35,6 +35,8 @@ #include "QF/plugin.h" #include "QF/sys.h" +#include "QF/ui/view.h" + #include "r_internal.h" @@ -48,26 +50,24 @@ int graphval; Performance monitoring tool */ void -R_TimeGraph (void) +R_TimeGraph (view_t *view) { static int timex; int a; int l; - //XXX float r_time2; + double r_time2; static int r_timings[MAX_TIMINGS]; int timings[MAX_TIMINGS]; - int x, o; + int o; - //XXX r_time2 = Sys_DoubleTime (); + r_time2 = Sys_DoubleTime (); - a = graphval; - - r_timings[timex] = a; + r_timings[timex] = (r_time2 - r_time1) * 10000; + //printf ("%d %g\n", r_timings[timex], r_time2 - r_time1); l = MAX_TIMINGS; if (l > r_refdef.vrect.width) l = r_refdef.vrect.width; - x = r_refdef.vrect.width - l; o = 0; a = timex - l; if (a < 0) { @@ -78,16 +78,16 @@ R_TimeGraph (void) a = 0; } memcpy (timings + o, r_timings + a, l * sizeof (timings[0])); - vr_funcs->R_LineGraph (x, r_refdef.vrect.height - 2, r_timings, - MAX_TIMINGS, vr_data.graphheight->int_val); + vr_funcs->R_LineGraph (view->xabs, view->yabs, r_timings, + MAX_TIMINGS, 200);//vr_data.graphheight->int_val); timex = (timex + 1) % MAX_TIMINGS; } void -R_ZGraph (void) +R_ZGraph (view_t *view) { - int x, w; + int w; static int height[256]; if (r_refdef.vrect.width <= 256) @@ -97,7 +97,6 @@ R_ZGraph (void) height[r_framecount & 255] = ((int) r_refdef.frame.position[2]) & 31; - x = 0; - vr_funcs->R_LineGraph (x, r_refdef.vrect.height - 2, height, + vr_funcs->R_LineGraph (view->xabs, view->yabs, height, w, vr_data.graphheight->int_val); } diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index d6ecf3a54..5eb7d3cd2 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -52,7 +52,7 @@ double r_realtime; double r_frametime; entity_t *r_view_model; entity_t *r_player_entity; -float r_time1; +double r_time1; int r_lineadj; qboolean r_active; int r_init; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index e174039aa..938b5f3a8 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -188,10 +188,11 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) r_funcs->begin_frame (); r_funcs->render_view (); - r_funcs->set_2d(); + r_funcs->set_2d (0); view_draw (r_data->scr_view); + r_funcs->set_2d (1); while (*scr_funcs) { - (*scr_funcs)(); + (*scr_funcs) (); scr_funcs++; } r_funcs->end_frame (); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 95498b0df..233160c64 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -798,12 +798,6 @@ R_RenderView_ (void) if (r_dowarp) D_WarpScreen (); - if (r_timegraph->int_val) - R_TimeGraph (); - - if (r_zgraph->int_val) - R_ZGraph (); - if (r_aliasstats->int_val) R_PrintAliasStats (); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index ac93ae5c2..6edc3fb0f 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -261,9 +261,13 @@ gl_render_view (void) } static void -gl_set_2d (void) +gl_set_2d (int scaled) { - GL_Set2DScaled (); + if (scaled) { + GL_Set2DScaled (); + } else { + GL_Set2D (); + } } static void diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index cb7e812ab..d782d3d92 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -221,9 +221,13 @@ glsl_render_view (void) } static void -glsl_set_2d (void) +glsl_set_2d (int scaled) { - GLSL_Set2DScaled (); + if (scaled) { + GLSL_Set2DScaled (); + } else { + GLSL_Set2D (); + } } static void diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 75b5f9ab9..b3bb1eb14 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -145,7 +145,7 @@ sw_render_view (void) } static void -sw_set_2d (void) +sw_set_2d (int scaled) { } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 92b0f71a6..f295f3204 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -285,7 +285,7 @@ vulkan_render_view (void) } static void -vulkan_set_2d (void) +vulkan_set_2d (int scaled) { } diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index fe533c95f..70333bc4d 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -56,6 +56,8 @@ #include "nq/include/client.h" static view_t *net_view; +static view_t *timegraph_view; +static view_t *zgraph_view; static view_t *loading_view; static void @@ -94,6 +96,8 @@ scr_draw_views (void) net_view->visible = (!cls.demoplayback && realtime - cl.last_servermessage >= 0.3); loading_view->visible = cl.loading; + timegraph_view->visible = r_timegraph->int_val; + zgraph_view->visible = r_zgraph->int_val; view_draw (r_data->vid->conview); } @@ -146,6 +150,22 @@ CL_UpdateScreen (double realtime) view_add (r_data->scr_view, net_view); } + if (!timegraph_view) { + view_t *parent = r_data->scr_view; + timegraph_view = view_new (0, 0, parent->xlen, 100, grav_southwest); + timegraph_view->draw = R_TimeGraph; + timegraph_view->visible = 0; + view_add (parent, timegraph_view); + } + + if (!zgraph_view) { + view_t *parent = r_data->scr_view; + zgraph_view = view_new (0, 0, parent->xlen, 100, grav_southwest); + zgraph_view->draw = R_ZGraph; + zgraph_view->visible = 0; + view_add (parent, zgraph_view); + } + if (!loading_view) { const char *name = "gfx/loading.lmp"; qpic_t *pic = r_funcs->Draw_CachePic (name, 1); From ab78e9d2ffbe45e02ae8d71964e79488fb9904ce Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Mar 2022 16:53:10 +0900 Subject: [PATCH 2538/3664] [sw] Make worldent local static It being on the stack was a bad idea as R_RenderWorld returns before the scans are rendered and thus the entity pointer winds up pointing to abandoned stack space. --- libs/video/renderer/sw/sw_rbsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index c1470e0e6..67aed7fed 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -521,7 +521,7 @@ R_RenderWorld (void) { int i; btofpoly_t btofpolys[MAX_BTOFPOLYS]; - entity_t worldent = {}; + static entity_t worldent = {}; entity_t *ent = &worldent; mod_brush_t *brush = &r_refdef.worldmodel->brush; swbspctx_t bspctx = { From 9241efaf1e009e22e4d38645f9e73a76fe608542 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 16 Mar 2022 13:55:44 +0900 Subject: [PATCH 2539/3664] [sw] Use a smaller size for the fish eye cube map This speeds up sw rendering of the fish eye effect. --- libs/video/renderer/sw/sw_rmain.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 233160c64..e668b1458 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -982,11 +982,12 @@ renderside (byte *bufs, int side) r_refdef.fov_x = r_refdef.fov_y = 90; r_refdef.vrect.x = r_refdef.vrect.y = 0; r_refdef.vrect.height = r_refdef.vrect.width = sw_cube_map_size; - vid.height = vid.width = sw_cube_map_size; + vid.rowbytes = vid.height = vid.width = sw_cube_map_size; R_ViewChanged (); rendercopy (bufs); + vid.rowbytes = width; r_refdef.vrect = rect; vid.height = height; vid.width = width; @@ -1012,7 +1013,7 @@ renderlookup (byte **offs, byte* bufs) static void R_RenderViewFishEye (void) { - sw_cube_map_size = vid.width; + sw_cube_map_size = vid.height; int width = vid.width; //r_refdef.vrect.width; int height = vid.height; //r_refdef.vrect.height; int scrsize = sw_cube_map_size * sw_cube_map_size; From d3bfc54a68966f7b024b933b01abeada05a129f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 09:42:09 +0900 Subject: [PATCH 2540/3664] [sw] Disable water warp when doing fisheye The two aren't compatible (but warping might be doable in the fisheye code). The whole frame setup code needs a rework, and really, even the buffer handling. --- libs/video/renderer/sw/sw_rmisc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index 1d7bc491f..91728168b 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -198,6 +198,13 @@ R_SetupFrame (void) r_dowarp = r_waterwarp->int_val && (r_refdef.viewleaf->contents <= CONTENTS_WATER); + if (scr_fisheye->int_val) { + //FIXME this shouldn't be necessary, but warp doesn't work well in + //fisheye, aand allowing the non-warp code to mess with vrect messes + //things up for the cube map rendering. This whole frame setup path + //needs to be redesigned + r_dowarp = r_viewchanged = 0; + } if ((r_dowarp != r_dowarpold) || r_viewchanged) { if (r_dowarp) { if ((vid.width <= WARP_WIDTH) @@ -233,9 +240,7 @@ R_SetupFrame (void) (h / (float) vid.height))); R_ViewChanged (); } - } else if (!scr_fisheye->int_val) { - //FIXME the above test shouldn't be necessary (this whole section - //is a bit of a mess, though) + } else { r_refdef.vrect.x = vr_data.scr_view->xpos; r_refdef.vrect.y = vr_data.scr_view->ypos; r_refdef.vrect.width = vr_data.scr_view->xlen; From 1458f61a4891c873bd98b6d9deffdd28e41721e4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 10:51:29 +0900 Subject: [PATCH 2541/3664] [renderer] Fix non-static linking of graph code Obviously forgot to test the changes I made to graph rendering in non-static builds. Oops :P --- libs/video/renderer/Makemodule.am | 2 +- libs/video/renderer/r_graph.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 1b6bd2ab0..44d8bd5ac 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -31,7 +31,6 @@ video_renderer_common_sources = \ libs/video/renderer/r_bsp.c \ libs/video/renderer/r_dyn_textures.c \ libs/video/renderer/r_ent.c \ - libs/video/renderer/r_graph.c \ libs/video/renderer/r_iqm.c \ libs/video/renderer/r_part.c \ libs/video/renderer/r_sprite.c \ @@ -48,6 +47,7 @@ libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_cvar.c \ libs/video/renderer/r_efrag.c \ libs/video/renderer/r_fog.c \ + libs/video/renderer/r_graph.c \ libs/video/renderer/r_init.c \ libs/video/renderer/r_light.c \ libs/video/renderer/r_main.c \ diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index c831780a5..4c309aacf 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -78,8 +78,8 @@ R_TimeGraph (view_t *view) a = 0; } memcpy (timings + o, r_timings + a, l * sizeof (timings[0])); - vr_funcs->R_LineGraph (view->xabs, view->yabs, r_timings, - MAX_TIMINGS, 200);//vr_data.graphheight->int_val); + r_funcs->R_LineGraph (view->xabs, view->yabs, r_timings, + MAX_TIMINGS, 200);//r_data->graphheight->int_val); timex = (timex + 1) % MAX_TIMINGS; } @@ -97,6 +97,6 @@ R_ZGraph (view_t *view) height[r_framecount & 255] = ((int) r_refdef.frame.position[2]) & 31; - vr_funcs->R_LineGraph (view->xabs, view->yabs, height, - w, vr_data.graphheight->int_val); + r_funcs->R_LineGraph (view->xabs, view->yabs, height, + w, r_data->graphheight->int_val); } From 0e58f96d3774f66ee4481c6bc88b606a62d2bd60 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 11:21:38 +0900 Subject: [PATCH 2542/3664] [renderer] Fix more plugin linking errors --- libs/video/renderer/vid_render_gl.c | 25 +++++++++++++------------ libs/video/renderer/vid_render_glsl.c | 23 +++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 6edc3fb0f..5c33f688d 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -231,23 +231,24 @@ gl_begin_frame (void) // draw any areas not covered by the refresh if (r_refdef.vrect.x > 0) { // left - Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); + gl_Draw_TileClear (0, 0, r_refdef.vrect.x, + vid.height - vr_data.lineadj); // right - Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, - vid.width - r_refdef.vrect.x + r_refdef.vrect.width, - vid.height - vr_data.lineadj); + gl_Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, + vid.width - r_refdef.vrect.x + r_refdef.vrect.width, + vid.height - vr_data.lineadj); } if (r_refdef.vrect.y > 0) { // top - Draw_TileClear (r_refdef.vrect.x, 0, - r_refdef.vrect.x + r_refdef.vrect.width, - r_refdef.vrect.y); + gl_Draw_TileClear (r_refdef.vrect.x, 0, + r_refdef.vrect.x + r_refdef.vrect.width, + r_refdef.vrect.y); // bottom - Draw_TileClear (r_refdef.vrect.x, - r_refdef.vrect.y + r_refdef.vrect.height, - r_refdef.vrect.width, - vid.height - vr_data.lineadj - - (r_refdef.vrect.height + r_refdef.vrect.y)); + gl_Draw_TileClear (r_refdef.vrect.x, + r_refdef.vrect.y + r_refdef.vrect.height, + r_refdef.vrect.width, + vid.height - vr_data.lineadj - + (r_refdef.vrect.height + r_refdef.vrect.y)); } gl_Fog_SetupFrame (); diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index d782d3d92..a7274b7f8 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -193,24 +193,23 @@ glsl_begin_frame (void) GLSL_DrawReset (); if (r_refdef.vrect.x > 0) { + int rx = r_refdef.vrect.x + r_refdef.vrect.width; + int vh = vid.height - vr_data.lineadj; // left - Draw_TileClear (0, 0, r_refdef.vrect.x, vid.height - vr_data.lineadj); + glsl_Draw_TileClear (0, 0, r_refdef.vrect.x, vh); // right - Draw_TileClear (r_refdef.vrect.x + r_refdef.vrect.width, 0, - vid.width - r_refdef.vrect.x + r_refdef.vrect.width, - vid.height - vr_data.lineadj); + glsl_Draw_TileClear (rx, 0, vid.width - rx, vh); } if (r_refdef.vrect.y > 0) { + int lx = r_refdef.vrect.x; + int ty = r_refdef.vrect.y; + int rx = r_refdef.vrect.x + r_refdef.vrect.width; + int by = r_refdef.vrect.y + r_refdef.vrect.height; + int vh = vid.height - vr_data.lineadj; // top - Draw_TileClear (r_refdef.vrect.x, 0, - r_refdef.vrect.x + r_refdef.vrect.width, - r_refdef.vrect.y); + glsl_Draw_TileClear (lx, 0, rx, ty); // bottom - Draw_TileClear (r_refdef.vrect.x, - r_refdef.vrect.y + r_refdef.vrect.height, - r_refdef.vrect.width, - vid.height - vr_data.lineadj - - (r_refdef.vrect.height + r_refdef.vrect.y)); + glsl_Draw_TileClear (lx, by, r_refdef.vrect.width, vh - by); } } From 335d387ba887308374f41763a60ac768430d14ba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 11:55:58 +0900 Subject: [PATCH 2543/3664] [renderer] Clean up some stray vup etc Now vup, vfwd, vright names are restricted to only the software renderer (the only one that has such global variables). --- libs/video/renderer/glsl/glsl_sprite.c | 19 +++++++++-------- libs/video/renderer/r_main.c | 28 ++++++++++++-------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 8fabaffcc..196b99a73 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -180,18 +180,17 @@ R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, } static void -make_quad (mspriteframe_t *frame, vec4f_t origin, vec4f_t vpn, vec4f_t vright, - vec4f_t vup, float verts[6][3]) +make_quad (mspriteframe_t *frame, vec4f_t origin, vec4f_t sright, vec4f_t sup, float verts[6][3]) { vec4f_t left, up, right, down; vec4f_t ul, ur, ll, lr; // build the sprite poster in worldspace // first, rotate the sprite axes into world space - right = frame->right * vright; - up = frame->up * vup; - left = frame->left * vright; - down = frame->down * vup; + right = frame->right * sright; + up = frame->up * sup; + left = frame->left * sright; + down = frame->down * sup; // next, build the sprite corners from the axes ul = up + left; ur = up + right; @@ -213,7 +212,7 @@ glsl_R_DrawSprite (entity_t *ent) mspriteframe_t *frame1, *frame2; float blend; vec4f_t cameravec = {}; - vec4f_t svpn = {}, svright = {}, svup = {}; + vec4f_t spn = {}, sright = {}, sup = {}; static quat_t color = { 1, 1, 1, 1}; float vertsa[6][3], vertsb[6][3]; static float uvab[6][4] = { @@ -229,7 +228,7 @@ glsl_R_DrawSprite (entity_t *ent) cameravec = r_refdef.frame.position - origin; if (!R_BillboardFrame (ent, sprite->type, &cameravec[0], - &svup[0], &svright[0], &svpn[0])) { + &sup[0], &sright[0], &spn[0])) { // the orientation is undefined so can't draw the sprite return; } @@ -246,8 +245,8 @@ glsl_R_DrawSprite (entity_t *ent) qfeglVertexAttrib4fv (quake_sprite.colorb.location, color); qfeglVertexAttrib1f (quake_sprite.blend.location, blend); - make_quad (frame1, origin, svpn, svright, svup, vertsa); - make_quad (frame2, origin, svpn, svright, svup, vertsb); + make_quad (frame1, origin, sright, sup, vertsa); + make_quad (frame2, origin, sright, sup, vertsb); qfeglVertexAttribPointer (quake_sprite.vertexa.location, 3, GL_FLOAT, 0, 0, vertsa); diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index 5eb7d3cd2..016bd0136 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -92,22 +92,20 @@ void R_SetFrustum (void) { int i; - vec4f_t vright = r_refdef.frame.right; - vec4f_t vfwd = r_refdef.frame.forward; - vec4f_t vup = r_refdef.frame.up; + vec4f_t right = r_refdef.frame.right; + vec4f_t fwd = r_refdef.frame.forward; + vec4f_t up = r_refdef.frame.up; + float rot_x = 90 - r_refdef.fov_x / 2; + float rot_y = 90 - r_refdef.fov_y / 2; - // rotate VPN right by FOV_X/2 degrees - RotatePointAroundVector (frustum[0].normal, &vup[0], &vfwd[0], - -(90 - r_refdef.fov_x / 2)); - // rotate VPN left by FOV_X/2 degrees - RotatePointAroundVector (frustum[1].normal, &vup[0], &vfwd[0], - 90 - r_refdef.fov_x / 2); - // rotate VPN up by FOV_Y/2 degrees - RotatePointAroundVector (frustum[2].normal, &vright[0], &vfwd[0], - 90 - r_refdef.fov_y / 2); - // rotate VPN down by FOV_Y/2 degrees - RotatePointAroundVector (frustum[3].normal, &vright[0], &vfwd[0], - -(90 - r_refdef.fov_y / 2)); + // rotate FWD right by FOV_X/2 degrees + RotatePointAroundVector (frustum[0].normal, &up[0], &fwd[0], -rot_x); + // rotate FWD left by FOV_X/2 degrees + RotatePointAroundVector (frustum[1].normal, &up[0], &fwd[0], rot_x); + // rotate FWD up by FOV_Y/2 degrees + RotatePointAroundVector (frustum[2].normal, &right[0], &fwd[0], rot_y); + // rotate FWD down by FOV_Y/2 degrees + RotatePointAroundVector (frustum[3].normal, &right[0], &fwd[0], -rot_y); vec4f_t origin = r_refdef.frame.position; for (i = 0; i < 4; i++) { From 7ee915963835272e293f8241a5e7d2182ded9d7c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 12:00:43 +0900 Subject: [PATCH 2544/3664] [renderer] Move common R_SetupFrame code to r_screen The code is really part of scene (not a typo wrt r_screen: that is misnamed as such, or at least SCR_UpdateScreen needs to be split into screen (2d overlay, really) and scene updates). This breaks fisheye rendering as the fisheye code calls the actual scene render code multiple times, but the fisheye code is called by said scene render code via a diversion. The fisheye needs to be moved out to the high level scene render, but that will takes some extra work for frame buffer setup. --- libs/video/renderer/gl/gl_rmain.c | 15 ------------ libs/video/renderer/glsl/glsl_main.c | 15 ------------ libs/video/renderer/r_screen.c | 31 ++++++++++++++++++------ libs/video/renderer/sw/sw_rmisc.c | 9 ------- libs/video/renderer/vulkan/vulkan_main.c | 14 ----------- 5 files changed, 23 insertions(+), 61 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index b45ea5acf..36a7ed133 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -240,20 +240,6 @@ R_DrawViewModel (void) qfglDepthRange (gldepthmin, gldepthmax); } -static void -gl_R_SetupFrame (void) -{ - R_AnimateLight (); - EntQueue_Clear (r_ent_queue); - r_framecount++; - - vec4f_t position = r_refdef.frame.position; - - R_SetFrustum (); - - r_refdef.viewleaf = Mod_PointInLeaf (&position[0], r_refdef.worldmodel); -} - static void MYgluPerspective (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) @@ -336,7 +322,6 @@ R_RenderScene (void) if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val) r_time1 = Sys_DoubleTime (); - gl_R_SetupFrame (); R_SetupGL (); gl_Fog_EnableGFog (); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index e90578ad1..54cef78b2 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -93,20 +93,6 @@ glsl_R_ViewChanged (void) mmulf (proj, depth_range, proj); } -static void -glsl_R_SetupFrame (void) -{ - R_AnimateLight (); - EntQueue_Clear (r_ent_queue); - r_framecount++; - - vec4f_t position = r_refdef.frame.position; - - R_SetFrustum (); - - r_refdef.viewleaf = Mod_PointInLeaf (&position[0], r_refdef.worldmodel); -} - static void R_SetupView (void) { @@ -188,7 +174,6 @@ glsl_R_RenderView (void) if (speeds) t[0] = Sys_DoubleTime (); - glsl_R_SetupFrame (); R_SetupView (); if (speeds) t[1] = Sys_DoubleTime (); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 938b5f3a8..611ba885f 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -48,6 +48,7 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/entity.h" #include "QF/scene/transform.h" #include "QF/ui/view.h" @@ -160,13 +161,15 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) return; } + refdef_t *refdef = r_data->refdef; if (camera) { - Transform_GetWorldMatrix (camera, r_data->refdef->camera); - Transform_GetWorldInverse (camera, r_data->refdef->camera_inverse); + Transform_GetWorldMatrix (camera, refdef->camera); + Transform_GetWorldInverse (camera, refdef->camera_inverse); } else { - mat4fidentity (r_data->refdef->camera); - mat4fidentity (r_data->refdef->camera_inverse); + mat4fidentity (refdef->camera); + mat4fidentity (refdef->camera_inverse); } + // FIXME pre-rotate the camera 90 degrees about the z axis such that the // camera forward vector (camera Y) points along the world +X axis and the // camera right vector (camera X) points along the world -Y axis. This @@ -174,10 +177,15 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) // AngleQuat for compatibility) treating X as forward and Y as left (or -Y // as right). Fixing this would take an audit of the usage of both, but is // probably worthwhile in the long run. - r_data->refdef->frame.mat[0] = -r_data->refdef->camera[1]; - r_data->refdef->frame.mat[1] = r_data->refdef->camera[0]; - r_data->refdef->frame.mat[2] = r_data->refdef->camera[2]; - r_data->refdef->frame.mat[3] = r_data->refdef->camera[3]; + refdef->frame.mat[0] = -refdef->camera[1]; + refdef->frame.mat[1] = refdef->camera[0]; + refdef->frame.mat[2] = refdef->camera[2]; + refdef->frame.mat[3] = refdef->camera[3]; + + //FIXME breaks fisheye as it calls the view render many times + EntQueue_Clear (r_ent_queue); + r_framecount++; + R_SetFrustum (); r_data->realtime = realtime; scr_copytop = r_data->scr_copyeverything = 0; @@ -186,6 +194,13 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) SCR_CalcRefdef (); } + R_AnimateLight (); + refdef->viewleaf = 0; + if (refdef->worldmodel) { + vec4f_t position = refdef->frame.position; + refdef->viewleaf = Mod_PointInLeaf (&position[0], refdef->worldmodel); + } + r_funcs->begin_frame (); r_funcs->render_view (); r_funcs->set_2d (0); diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index 91728168b..f7d41734f 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -176,23 +176,14 @@ R_SetupFrame (void) vrect_t vrect; float w, h; - R_AnimateLight (); - EntQueue_Clear (r_ent_queue); - r_framecount++; - numbtofpolys = 0; // build the transformation matrix for the given view angles VectorCopy (r_refdef.frame.position, modelorg); - vec4f_t position = r_refdef.frame.position; VectorCopy (r_refdef.frame.right, vright); VectorCopy (r_refdef.frame.forward, vfwd); VectorCopy (r_refdef.frame.up, vup); - R_SetFrustum (); - - // current viewleaf - r_refdef.viewleaf = Mod_PointInLeaf (&position[0], r_refdef.worldmodel); r_dowarpold = r_dowarp; r_dowarp = r_waterwarp->int_val && (r_refdef.viewleaf->contents <= diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index fe5ee3c29..bf26856dc 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -63,19 +63,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -static void -setup_frame (vulkan_ctx_t *ctx) -{ - R_AnimateLight (); - EntQueue_Clear (r_ent_queue); - r_framecount++; - - R_SetFrustum (); - - vec4f_t position = r_refdef.frame.position; - r_refdef.viewleaf = Mod_PointInLeaf (&position[0], r_refdef.worldmodel); -} - static void Vulkan_RenderEntities (qfv_renderframe_t *rFrame) { @@ -137,7 +124,6 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) if (speeds) t[0] = Sys_DoubleTime (); - setup_frame (ctx); if (speeds) t[1] = Sys_DoubleTime (); R_MarkLeaves (); From d8a4c8dbe9ff692df4268202a5ac2231780b3980 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 13:09:20 +0900 Subject: [PATCH 2545/3664] [renderer] Clean up r_bsp a little Move r_pcurrentvertbase into the sw renderer, cleaning up gl's use of (not really needed there). Not ready to move r_bsp into the main bin yet as there are linking issues since only the low-level code references any of its symbols. --- include/QF/GL/qf_lightmap.h | 1 - include/QF/GL/qf_rsurf.h | 4 ++-- libs/video/renderer/gl/gl_draw.c | 4 ---- libs/video/renderer/gl/gl_lightmap.c | 4 ++-- libs/video/renderer/gl/gl_rmisc.c | 3 +++ libs/video/renderer/gl/gl_rsurf.c | 7 ++++--- libs/video/renderer/r_bsp.c | 3 +-- libs/video/renderer/sw/sw_rbsp.c | 1 + 8 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/QF/GL/qf_lightmap.h b/include/QF/GL/qf_lightmap.h index 37485888f..8518b93fd 100644 --- a/include/QF/GL/qf_lightmap.h +++ b/include/QF/GL/qf_lightmap.h @@ -47,7 +47,6 @@ extern qboolean gl_lightmap_modified[MAX_LIGHTMAPS]; extern instsurf_t *gl_lightmap_polys[MAX_LIGHTMAPS]; extern glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; -void GL_BuildSurfaceDisplayList (msurface_t *fa); void gl_lightmap_init (void); void GL_BuildLightmaps (struct model_s **models, int num_models); void gl_R_BlendLightmaps (void); diff --git a/include/QF/GL/qf_rsurf.h b/include/QF/GL/qf_rsurf.h index 5a7e4c698..af7c334ff 100644 --- a/include/QF/GL/qf_rsurf.h +++ b/include/QF/GL/qf_rsurf.h @@ -43,8 +43,8 @@ struct entity_s; struct msurface_s; struct mod_brush_s; -void gl_lightmap_init (void); -void GL_BuildLightmaps (struct model_s **models, int num_models); +void GL_BuildSurfaceDisplayList (struct mod_brush_s *brush, + struct msurface_s *fa); void gl_R_DrawBrushModel (struct entity_s *e); void gl_R_DrawWorld (void); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index c2009f609..624d685ac 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -408,10 +408,6 @@ gl_Draw_Init (void) // get the other pics we need draw_backtile = gl_Draw_PicFromWad ("backtile"); - // LordHavoc: call init code for other GL renderer modules - glrmain_init (); - gl_lightmap_init (); - Draw_InitText (); } diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index ca54c7061..49469067c 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -49,6 +49,7 @@ #include "QF/GL/funcs.h" #include "QF/GL/qf_lightmap.h" #include "QF/GL/qf_rmain.h" +#include "QF/GL/qf_rsurf.h" #include "QF/GL/qf_sky.h" #include "QF/GL/qf_textures.h" #include "QF/GL/qf_vid.h" @@ -732,7 +733,6 @@ GL_BuildLightmaps (model_t **models, int num_models) continue; } brush = &m->brush; - r_pcurrentvertbase = brush->vertexes; gl_currentmodel = m; // non-bsp models don't have surfaces. for (unsigned i = 0; i < brush->numsurfaces; i++) { @@ -742,7 +742,7 @@ GL_BuildLightmaps (model_t **models, int num_models) SURF_DRAWSKY)) continue; GL_CreateSurfaceLightmap (brush, brush->surfaces + i); - GL_BuildSurfaceDisplayList (brush->surfaces + i); + GL_BuildSurfaceDisplayList (brush, brush->surfaces + i); } } diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 93375ece1..819aa31e7 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -54,6 +54,7 @@ #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_draw.h" +#include "QF/GL/qf_lightmap.h" #include "QF/GL/qf_particles.h" #include "QF/GL/qf_rlight.h" #include "QF/GL/qf_rmain.h" @@ -182,6 +183,8 @@ gl_R_Init (void) Cmd_AddCommand ("loadsky", gl_R_LoadSky_f, "Load a skybox"); gl_Draw_Init (); + glrmain_init (); + gl_lightmap_init (); SCR_Init (); gl_R_InitBubble (); diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 0de24b23f..d2b0aff68 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -817,13 +817,14 @@ gl_R_DrawWorld (void) model_t *gl_currentmodel; void -GL_BuildSurfaceDisplayList (msurface_t *surf) +GL_BuildSurfaceDisplayList (mod_brush_t *brush, msurface_t *surf) { float s, t; float *vec; int lindex, lnumverts, i; glpoly_t *poly; medge_t *pedges, *r_pedge; + mvertex_t *vertex_base = brush->vertexes; // reconstruct the polygon pedges = gl_currentmodel->brush.edges; @@ -843,10 +844,10 @@ GL_BuildSurfaceDisplayList (msurface_t *surf) if (lindex > 0) { r_pedge = &pedges[lindex]; - vec = r_pcurrentvertbase[r_pedge->v[0]].position; + vec = vertex_base[r_pedge->v[0]].position; } else { r_pedge = &pedges[-lindex]; - vec = r_pcurrentvertbase[r_pedge->v[1]].position; + vec = vertex_base[r_pedge->v[1]].position; } s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; s /= texinfo->texture->width; diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index b4fdf36c9..2abb2c05d 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -41,7 +41,6 @@ #include "r_internal.h" -mvertex_t *r_pcurrentvertbase; static mleaf_t *r_oldviewleaf; static set_t *solid; @@ -115,7 +114,7 @@ R_TextureAnimation (const entity_t *entity, msurface_t *surf) if (!base->anim_total) return base; - relative = (int) (vr_data.realtime * 10) % base->anim_total; + relative = (int) (r_data->realtime * 10) % base->anim_total; count = 0; while (base->anim_min > relative || base->anim_max <= relative) { diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 67aed7fed..81c8efc44 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -48,6 +48,7 @@ typedef struct glbspctx_s { // current entity info qboolean insubmodel; vec3_t r_worldmodelorg; +mvertex_t *r_pcurrentvertbase; static float entity_rotation[3][3]; int r_currentbkey; From 6c29904b1d4e19892988e5d70b654ad647248082 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 13:37:21 +0900 Subject: [PATCH 2546/3664] [sw] Clean up R_SetSkyFrame a little Move the constant data into R_InitSky so it doesn't get calculated every frame (doesn't make much difference of course, but...) --- include/d_local.h | 2 ++ libs/video/renderer/sw/d_init.c | 2 ++ libs/video/renderer/sw/d_sky.c | 6 +++--- libs/video/renderer/sw/sw_rsky.c | 21 ++++++++++----------- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/include/d_local.h b/include/d_local.h index 1ff077d82..4dac4ee58 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -75,6 +75,8 @@ extern float d_sdivzstepu, d_tdivzstepu, d_zistepu; extern float d_sdivzstepv, d_tdivzstepv, d_zistepv; extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin; +extern float d_skyoffs; + extern fixed16_t sadjust, tadjust; extern fixed16_t bbextents, bbextentt; diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index 634762d28..9eed2bb89 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -93,6 +93,8 @@ D_SetupFrame (void) d_scalemip[i] = basemip[i] * d_mipscale->value; d_drawspans = D_DrawSpans8; + + d_skyoffs = r_skytime * r_skyspeed; } void diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index 5a3a3443f..289564b27 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -36,6 +36,7 @@ #define SKY_SPAN_SHIFT 5 #define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT) +float d_skyoffs; static void D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) @@ -59,9 +60,8 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) end[2] *= 3; VectorNormalize (end); - temp = r_skytime * r_skyspeed; // TODO: add D_SetupFrame & set this there - *s = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[0]) * 0x10000); - *t = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[1]) * 0x10000); + *s = (int) ((d_skyoffs + 6 * (SKYSIZE / 2 - 1) * end[0]) * 0x10000); + *t = (int) ((d_skyoffs + 6 * (SKYSIZE / 2 - 1) * end[1]) * 0x10000); } void diff --git a/libs/video/renderer/sw/sw_rsky.c b/libs/video/renderer/sw/sw_rsky.c index b179ce420..9a05d0e24 100644 --- a/libs/video/renderer/sw/sw_rsky.c +++ b/libs/video/renderer/sw/sw_rsky.c @@ -35,6 +35,7 @@ static int iskyspeed = 8; static int iskyspeed2 = 2; +static float r_skyperiod; float r_skyspeed; float r_skytime; @@ -64,6 +65,13 @@ R_InitSky (texture_t *mt) int i, j; byte *src; + int g = GreatestCommonDivisor (iskyspeed, iskyspeed2); + int s1 = iskyspeed / g; + int s2 = iskyspeed2 / g; + r_skyperiod = SKYSIZE * s1 * s2; + + r_skyspeed = iskyspeed; + src = (byte *) mt + mt->offsets[0]; for (i = 0; i < 128; i++) { @@ -174,17 +182,8 @@ R_GenSkyTile (void *pdest) void R_SetSkyFrame (void) { - int g, s1, s2; - float temp; - - r_skyspeed = iskyspeed; - - g = GreatestCommonDivisor (iskyspeed, iskyspeed2); - s1 = iskyspeed / g; - s2 = iskyspeed2 / g; - temp = SKYSIZE * s1 * s2; - - r_skytime = vr_data.realtime - ((int) (vr_data.realtime / temp) * temp); + r_skytime = vr_data.realtime; + r_skytime -= trunc (vr_data.realtime / r_skyperiod) * r_skyperiod; r_skymade = 0; } From 833fb2f4f853e7912dcf8d3916643cfa544b22cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 15:04:30 +0900 Subject: [PATCH 2547/3664] [sw] Make alight_t lightvec an actual vector The change to using separate per-model-type entity queues resulted in the lighting vector used for alias and iqm models being in an ephemeral location (in the shared setup_lighting function's stack frame). This resulted in the model rendering code getting a garbage vector due to it being overwritten by another stack frame. What I don't get is why the garbage varied from run to run for the same demo (demo2, the first scrag behind the start door showed the bad lighting nicely), which made tracking down the offending commit (and thus the code) rather troublesome, though once I found it, it was a bit of a face-palm moment. --- include/r_local.h | 6 +++--- libs/video/renderer/sw/sw_ralias.c | 22 +++++++++++----------- libs/video/renderer/sw/sw_riqm.c | 10 +++++----- libs/video/renderer/sw/sw_rmain.c | 27 +++++++++++---------------- 4 files changed, 30 insertions(+), 35 deletions(-) diff --git a/include/r_local.h b/include/r_local.h index 53a503a2f..b78954e0e 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -47,9 +47,9 @@ // viewmodel lighting ======================================================= typedef struct { - int ambientlight; - int shadelight; - float *plightvec; + int ambientlight; + int shadelight; + vec3_t lightvec; } alight_t; // clipped bmodel edges ===================================================== diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index f99b2712d..81e59720a 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -52,7 +52,7 @@ trivertx_t *r_apverts; // TODO: these probably will go away with optimized rasterization static mdl_t *pmdl; -vec3_t r_plightvec; +vec3_t r_lightvec; int r_ambientlight; float r_shadelight; static aliashdr_t *paliashdr; @@ -413,7 +413,7 @@ R_AliasTransformFinalVert (finalvert_t *fv, trivertx_t *pverts, // lighting plightnormal = r_avertexnormals[pverts->lightnormalindex]; - lightcos = DotProduct (plightnormal, r_plightvec); + lightcos = DotProduct (plightnormal, r_lightvec); temp = r_ambientlight; if (lightcos < 0) { @@ -463,7 +463,7 @@ R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts) // lighting plightnormal = r_avertexnormals[pverts->lightnormalindex]; - lightcos = DotProduct (plightnormal, r_plightvec); + lightcos = DotProduct (plightnormal, r_lightvec); temp = r_ambientlight; if (lightcos < 0) { @@ -555,11 +555,11 @@ R_AliasSetupSkin (entity_t *ent) static void -R_AliasSetupLighting (alight_t *plighting) +R_AliasSetupLighting (alight_t *lighting) { // guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't // have to clamp off the bottom - r_ambientlight = plighting->ambientlight; + r_ambientlight = lighting->ambientlight; if (r_ambientlight < LIGHT_MIN) r_ambientlight = LIGHT_MIN; @@ -569,7 +569,7 @@ R_AliasSetupLighting (alight_t *plighting) if (r_ambientlight < LIGHT_MIN) r_ambientlight = LIGHT_MIN; - r_shadelight = plighting->shadelight; + r_shadelight = lighting->shadelight; if (r_shadelight < 0) r_shadelight = 0; @@ -577,9 +577,9 @@ R_AliasSetupLighting (alight_t *plighting) r_shadelight *= VID_GRADES; // rotate the lighting vector into the model's frame of reference - r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward); - r_plightvec[1] = DotProduct (plighting->plightvec, alias_left); - r_plightvec[2] = DotProduct (plighting->plightvec, alias_up); + r_lightvec[0] = DotProduct (lighting->lightvec, alias_forward); + r_lightvec[1] = DotProduct (lighting->lightvec, alias_left); + r_lightvec[2] = DotProduct (lighting->lightvec, alias_up); } /* @@ -598,7 +598,7 @@ R_AliasSetupFrame (entity_t *ent) void -R_AliasDrawModel (entity_t *ent, alight_t *plighting) +R_AliasDrawModel (entity_t *ent, alight_t *lighting) { int size; finalvert_t *finalverts; @@ -623,7 +623,7 @@ R_AliasDrawModel (entity_t *ent, alight_t *plighting) R_AliasSetupSkin (ent); R_AliasSetUpTransform (ent, ent->visibility.trivial_accept); - R_AliasSetupLighting (plighting); + R_AliasSetupLighting (lighting); R_AliasSetupFrame (ent); r_affinetridesc.drawtype = ((ent->visibility.trivial_accept == 3) diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index b4851c991..e2691d2e5 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -58,14 +58,14 @@ // avoid the need for inner-loop light // clamping -static vec3_t r_plightvec; +static vec3_t r_lightvec; static int r_ambientlight; static float r_shadelight; static inline int calc_light (float *normal) { - float lightcos = DotProduct (normal, r_plightvec); + float lightcos = DotProduct (normal, r_lightvec); int temp = r_ambientlight; if (lightcos < 0) { @@ -236,9 +236,9 @@ R_IQMSetupLighting (entity_t *ent, alight_t *plighting) mat4f_t mat; Transform_GetWorldMatrix (ent->transform, mat); //FIXME vectorize - r_plightvec[0] = DotProduct (plighting->plightvec, mat[0]); - r_plightvec[1] = DotProduct (plighting->plightvec, mat[1]); - r_plightvec[2] = DotProduct (plighting->plightvec, mat[2]); + r_lightvec[0] = DotProduct (plighting->lightvec, mat[0]); + r_lightvec[1] = DotProduct (plighting->lightvec, mat[1]); + r_lightvec[2] = DotProduct (plighting->lightvec, mat[2]); } static void diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index e668b1458..9771e8182 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -60,8 +60,6 @@ #endif void *colormap; -static vec3_t viewlightvec; -static alight_t r_viewlighting = { 128, 192, viewlightvec }; int r_numallocatededges; qboolean r_drawpolys; qboolean r_drawculledpolys; @@ -369,7 +367,7 @@ setup_lighting (entity_t *ent, alight_t *lighting) lighting->ambientlight = j; lighting->shadelight = j; - lighting->plightvec = lightvec; + VectorCopy (lightvec, lighting->lightvec); for (unsigned lnum = 0; lnum < r_maxdlights; lnum++) { if (r_dlights[lnum].die >= vr_data.realtime) { @@ -439,7 +437,6 @@ static void R_DrawViewModel (void) { // FIXME: remove and do real lighting - float lightvec[3] = { -1, 0, 0 }; int j; unsigned int lnum; vec3_t dist; @@ -447,6 +444,7 @@ R_DrawViewModel (void) float minlight; dlight_t *dl; entity_t *viewent; + alight_t lighting; if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val @@ -459,8 +457,7 @@ R_DrawViewModel (void) VectorCopy (Transform_GetWorldPosition (viewent->transform), r_entorigin); - VectorCopy (vup, viewlightvec); - VectorNegate (viewlightvec, viewlightvec); + VectorNegate (vup, lighting.lightvec); minlight = max (viewent->renderer.min_light, viewent->renderer.model->min_light); @@ -468,8 +465,8 @@ R_DrawViewModel (void) j = max (R_LightPoint (&r_refdef.worldmodel->brush, r_entorigin), minlight * 128); - r_viewlighting.ambientlight = j; - r_viewlighting.shadelight = j; + lighting.ambientlight = j; + lighting.shadelight = j; // add dynamic lights for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -484,18 +481,16 @@ R_DrawViewModel (void) VectorSubtract (r_entorigin, dl->origin, dist); add = dl->radius - VectorLength (dist); if (add > 0) - r_viewlighting.ambientlight += add; + lighting.ambientlight += add; } // clamp lighting so it doesn't overbright as much - if (r_viewlighting.ambientlight > 128) - r_viewlighting.ambientlight = 128; - if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192) - r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight; + if (lighting.ambientlight > 128) + lighting.ambientlight = 128; + if (lighting.ambientlight + lighting.shadelight > 192) + lighting.shadelight = 192 - lighting.ambientlight; - r_viewlighting.plightvec = lightvec; - - R_AliasDrawModel (viewent, &r_viewlighting); + R_AliasDrawModel (viewent, &lighting); } static int From 961e6d9e6c387781ec5bf0c1db9caa1203bb60bc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 17:46:25 +0900 Subject: [PATCH 2548/3664] [gl] Remove unnecessary light map update code gl_overbright_f shouldn't need to run through any entity queues to update the light maps as only the world model has light maps, and hitting the world model should hit all its sub-models. --- libs/video/renderer/gl/gl_lightmap.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 49469067c..a2ce210da 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -529,7 +529,6 @@ void gl_overbright_f (cvar_t *var) { int num; - model_t *m; mod_brush_t *brush; if (!var) @@ -576,29 +575,6 @@ gl_overbright_f (cvar_t *var) if (!gl_R_BuildLightMap) return; - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \ - entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \ - m = ent->renderer.model; - if (m->path[0] == '*') - continue; - - brush = &m->brush; - for (unsigned j = 0; j < brush->numsurfaces; j++) { - msurface_t *surf = brush->surfaces + j; - if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) - continue; - - num = surf->lightmaptexturenum; - gl_lightmap_modified[num] = true; - gl_lightmap_rectchange[num].l = 0; - gl_lightmap_rectchange[num].t = 0; - gl_lightmap_rectchange[num].w = BLOCK_WIDTH; - gl_lightmap_rectchange[num].h = BLOCK_HEIGHT; - - gl_R_BuildLightMap (0, brush, surf); - } - } - brush = &r_refdef.worldmodel->brush; for (unsigned i = 0; i < brush->numsurfaces; i++) { From c05476f94bcfc2d703338fc0a18d36c484d04b9f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Mar 2022 17:50:38 +0900 Subject: [PATCH 2549/3664] [renderer] Move most of the scene rendering into r_screen r_screen isn't really the right place, but it gets the scene rendering out of the low-level renderers and will make it easier to sort out later, and hopefully easier to figure out a good design for vulkan. --- include/QF/GL/qf_particles.h | 3 +- include/QF/GL/qf_rmain.h | 2 + include/QF/GLSL/qf_main.h | 3 + include/QF/GLSL/qf_particles.h | 3 +- include/QF/Vulkan/qf_main.h | 3 + include/QF/plugin/vid_render.h | 3 + include/r_dynamic.h | 1 - include/r_local.h | 5 +- libs/video/renderer/Makemodule.am | 4 +- libs/video/renderer/gl/gl_dyn_part.c | 7 +- libs/video/renderer/gl/gl_rmain.c | 28 ++---- libs/video/renderer/gl/gl_rmisc.c | 1 - libs/video/renderer/glsl/glsl_main.c | 45 +-------- libs/video/renderer/glsl/glsl_particles.c | 24 ++--- libs/video/renderer/r_part.c | 2 +- libs/video/renderer/r_screen.c | 11 +++ libs/video/renderer/sw/sw_rmain.c | 114 ++-------------------- libs/video/renderer/sw/sw_rpart.c | 11 ++- libs/video/renderer/vid_render_gl.c | 3 + libs/video/renderer/vid_render_glsl.c | 3 + libs/video/renderer/vid_render_sw.c | 8 ++ libs/video/renderer/vid_render_vulkan.c | 21 ++++ libs/video/renderer/vulkan/vulkan_main.c | 44 +-------- 23 files changed, 115 insertions(+), 234 deletions(-) diff --git a/include/QF/GL/qf_particles.h b/include/QF/GL/qf_particles.h index f053e0523..9452fe454 100644 --- a/include/QF/GL/qf_particles.h +++ b/include/QF/GL/qf_particles.h @@ -38,7 +38,8 @@ typedef struct { byte color[4]; } partvert_t; -void gl_R_DrawParticles (void); +struct psystem_s; +void gl_R_DrawParticles (struct psystem_s *pssystem); void gl_R_Particles_Init_Cvars (void); void gl_R_InitParticles (void); diff --git a/include/QF/GL/qf_rmain.h b/include/QF/GL/qf_rmain.h index d6b8fe94b..910f98b33 100644 --- a/include/QF/GL/qf_rmain.h +++ b/include/QF/GL/qf_rmain.h @@ -45,9 +45,11 @@ void glrmain_init (void); void gl_R_RotateForEntity (struct entity_s *e); struct model_s; +struct entqueue_s; void gl_R_NewMap (struct model_s *worldmodel, struct model_s **models, int num_models); void gl_R_RenderView (void); +void gl_R_RenderEntities (struct entqueue_s *queue); void gl_R_ClearState (void); void gl_R_ViewChanged (void); void gl_R_LineGraph (int x, int y, int *h_vals, int count, int height); diff --git a/include/QF/GLSL/qf_main.h b/include/QF/GLSL/qf_main.h index c41601802..b194805fb 100644 --- a/include/QF/GLSL/qf_main.h +++ b/include/QF/GLSL/qf_main.h @@ -28,7 +28,10 @@ #ifndef __QF_GLSL_qf_main_h #define __QF_GLSL_qf_main_h +struct entqueue_s; + void glsl_R_NewMap (model_t *worldmodel, model_t **models, int num_models); +void glsl_R_RenderEntities (struct entqueue_s *queue); void glsl_R_RenderView (void); void glsl_R_ClearState (void); void glsl_R_ViewChanged (void); diff --git a/include/QF/GLSL/qf_particles.h b/include/QF/GLSL/qf_particles.h index 67fa52049..30d016d8e 100644 --- a/include/QF/GLSL/qf_particles.h +++ b/include/QF/GLSL/qf_particles.h @@ -38,7 +38,8 @@ typedef struct { byte color[4]; } partvert_t; -void glsl_R_DrawParticles (void); +struct psystem_s; +void glsl_R_DrawParticles (struct psystem_s *psystem); void glsl_R_Particles_Init_Cvars (void); void glsl_R_InitParticles (void); diff --git a/include/QF/Vulkan/qf_main.h b/include/QF/Vulkan/qf_main.h index 23a02e11d..b52b0a7f3 100644 --- a/include/QF/Vulkan/qf_main.h +++ b/include/QF/Vulkan/qf_main.h @@ -30,9 +30,12 @@ struct vulkan_ctx_s; struct qfv_renderframe_s; +struct entqueue_s; void Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, struct vulkan_ctx_s *ctx); void Vulkan_RenderView (struct qfv_renderframe_s *rFrame); +void Vulkan_RenderEntities (struct entqueue_s *queue, + struct qfv_renderframe_s *rFrame); #endif//__QF_Vulkan_qf_main_h diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index aff978c79..d88632356 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -39,6 +39,7 @@ struct skin_s; struct mod_alias_ctx_s; struct mod_sprite_ctx_s; +struct entqueue_s; /* All video plugins must export these functions @@ -108,6 +109,8 @@ typedef struct vid_render_funcs_s { void (*begin_frame) (void); void (*render_view) (void); + void (*draw_entities) (struct entqueue_s *queue); + void (*draw_particles) (struct psystem_s *psystem); void (*set_2d) (int scaled); void (*end_frame) (void); diff --git a/include/r_dynamic.h b/include/r_dynamic.h index 611d2a158..3239a9297 100644 --- a/include/r_dynamic.h +++ b/include/r_dynamic.h @@ -53,7 +53,6 @@ void R_InitBubble (void); void R_InitParticles (void); void R_ClearParticles (void); -void R_DrawParticles (void); struct cvar_s; void R_MaxParticlesCheck (struct cvar_s *r_particles, struct cvar_s *r_particles_max); diff --git a/include/r_local.h b/include/r_local.h index b78954e0e..9c3059479 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -112,6 +112,8 @@ extern clipplane_t view_clipplanes[4]; //============================================================================= void R_RenderWorld (void); +struct entqueue_s; +void R_DrawEntitiesOnList (struct entqueue_s *queue); //============================================================================= @@ -248,7 +250,8 @@ qboolean R_AliasCheckBBox (entity_t *ent); // particle stuff ========================================= -void R_DrawParticles (void); +struct psystem_s; +void R_DrawParticles (struct psystem_s *psystem); void R_InitParticles (void); void R_ClearParticles (void); void R_ReadPointFile_f (void); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 44d8bd5ac..ca7f487af 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -28,11 +28,9 @@ video_renderer_common_sources = \ libs/video/renderer/noisetextures.c \ libs/video/renderer/r_alias.c \ libs/video/renderer/r_billboard.c \ - libs/video/renderer/r_bsp.c \ libs/video/renderer/r_dyn_textures.c \ libs/video/renderer/r_ent.c \ libs/video/renderer/r_iqm.c \ - libs/video/renderer/r_part.c \ libs/video/renderer/r_sprite.c \ libs/video/renderer/vid_common.c @@ -44,6 +42,7 @@ libs_video_renderer_libQFrenderer_la_LDFLAGS= @STATIC@ libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libs) libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs) libs_video_renderer_libQFrenderer_la_SOURCES=\ + libs/video/renderer/r_bsp.c \ libs/video/renderer/r_cvar.c \ libs/video/renderer/r_efrag.c \ libs/video/renderer/r_fog.c \ @@ -51,6 +50,7 @@ libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_init.c \ libs/video/renderer/r_light.c \ libs/video/renderer/r_main.c \ + libs/video/renderer/r_part.c \ libs/video/renderer/r_scrap.c \ libs/video/renderer/r_screen.c \ libs/video/renderer/r_progs.c diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 097533de0..b64cd9481 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -110,7 +110,7 @@ gl_R_InitParticles (void) } void -gl_R_DrawParticles (void) +gl_R_DrawParticles (psystem_t *psystem) { unsigned char *at; int vacount; @@ -118,10 +118,9 @@ gl_R_DrawParticles (void) vec3_t up_scale, right_scale, up_right_scale, down_right_scale; varray_t2f_c4ub_v3f_t *VA; - if (!r_particles->int_val) + if (!r_psystem.numparticles) { return; - - R_RunParticles (vr_data.frametime); + } qfglBindTexture (GL_TEXTURE_2D, gl_part_tex); // LordHavoc: particles should not affect zbuffer diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 36a7ed133..c54d0fd96 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -100,13 +100,8 @@ gl_R_RotateForEntity (entity_t *e) qfglMultMatrixf (&mat[0][0]); } -/* - R_DrawEntitiesOnList - - Draw all the entities we have information on. -*/ -static void -R_DrawEntitiesOnList (void) +void +gl_R_RenderEntities (entqueue_t *queue) { if (!r_drawentities->int_val) return; @@ -133,8 +128,8 @@ R_DrawEntitiesOnList (void) qfglEnable (GL_NORMALIZE); } - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_alias].size; i++) { \ - entity_t *ent = r_ent_queue->ent_queues[mod_alias].a[i]; \ + for (size_t i = 0; i < queue->ent_queues[mod_alias].size; i++) { \ + entity_t *ent = queue->ent_queues[mod_alias].a[i]; \ gl_R_DrawAliasModel (ent); } qfglColor3ubv (color_white); @@ -162,8 +157,8 @@ R_DrawEntitiesOnList (void) qglActiveTexture (gl_mtex_enum + 0); } - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_iqm].size; i++) { \ - entity_t *ent = r_ent_queue->ent_queues[mod_iqm].a[i]; \ + for (size_t i = 0; i < queue->ent_queues[mod_iqm].size; i++) { \ + entity_t *ent = queue->ent_queues[mod_iqm].a[i]; \ gl_R_DrawIQMModel (ent); } qfglColor3ubv (color_white); @@ -172,8 +167,8 @@ R_DrawEntitiesOnList (void) qfglEnable (GL_ALPHA_TEST); if (gl_va_capable) qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray); - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_sprite].size; i++) { \ - entity_t *ent = r_ent_queue->ent_queues[mod_sprite].a[i]; \ + for (size_t i = 0; i < queue->ent_queues[mod_sprite].size; i++) { \ + entity_t *ent = queue->ent_queues[mod_sprite].a[i]; \ gl_R_DrawSpriteModel (ent); } qfglDisable (GL_ALPHA_TEST); @@ -319,21 +314,14 @@ R_SetupGL (void) static void R_RenderScene (void) { - if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val) - r_time1 = Sys_DoubleTime (); - R_SetupGL (); gl_Fog_EnableGFog (); - R_MarkLeaves (); // done here so we know if we're in water - R_PushDlights (vec3_origin); gl_R_DrawWorld (); // adds static entities to the list S_ExtraUpdate (); // don't let sound get messed up if going slow - R_DrawEntitiesOnList (); gl_R_RenderDlights (); gl_R_DrawWaterSurfaces (); R_DrawViewModel (); - gl_R_DrawParticles (); gl_Fog_DisableGFog (); } diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 819aa31e7..5694f07c5 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -173,7 +173,6 @@ gl_R_TimeRefresh_f (void) void gl_R_Init (void) { - r_ent_queue = EntQueue_New (mod_num_types); R_Init_Cvars (); gl_R_Particles_Init_Cvars (); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 54cef78b2..4761bad6d 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -116,8 +116,8 @@ R_SetupView (void) qfeglEnable (GL_DEPTH_TEST); } -static void -R_RenderEntities (void) +void +glsl_R_RenderEntities (entqueue_t *queue) { int begun; @@ -126,9 +126,9 @@ R_RenderEntities (void) #define RE_LOOP(type_name, Type) \ do { \ begun = 0; \ - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \ + for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ i++) { \ - entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \ + entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \ if (!begun) { \ glsl_R_##Type##Begin (); \ begun = 1; \ @@ -165,51 +165,15 @@ R_DrawViewModel (void) void glsl_R_RenderView (void) { - double t[10] = {}; - int speeds = r_speeds->int_val; - if (!r_refdef.worldmodel) { return; } - if (speeds) - t[0] = Sys_DoubleTime (); R_SetupView (); - if (speeds) - t[1] = Sys_DoubleTime (); - R_MarkLeaves (); - if (speeds) - t[2] = Sys_DoubleTime (); - R_PushDlights (vec3_origin); - if (speeds) - t[3] = Sys_DoubleTime (); glsl_R_DrawWorld (); - if (speeds) - t[4] = Sys_DoubleTime (); glsl_R_DrawSky (); - if (speeds) - t[5] = Sys_DoubleTime (); - R_RenderEntities (); - if (speeds) - t[6] = Sys_DoubleTime (); glsl_R_DrawWaterSurfaces (); - if (speeds) - t[7] = Sys_DoubleTime (); R_DrawViewModel (); - if (speeds) - t[8] = Sys_DoubleTime (); - glsl_R_DrawParticles (); - if (speeds) - t[9] = Sys_DoubleTime (); - if (speeds) { - Sys_Printf ("frame: %g, setup: %g, mark: %g, pushdl: %g, world: %g," - " sky: %g, ents: %g, water: %g, view: %g, part: %g\n", - (t[9] - t[0]) * 1000, (t[1] - t[0]) * 1000, - (t[2] - t[1]) * 1000, (t[3] - t[2]) * 1000, - (t[4] - t[3]) * 1000, (t[5] - t[4]) * 1000, - (t[6] - t[5]) * 1000, (t[7] - t[6]) * 1000, - (t[8] - t[7]) * 1000, (t[9] - t[8]) * 1000); - } } static void @@ -237,7 +201,6 @@ glsl_R_TimeRefresh_f (void) void glsl_R_Init (void) { - r_ent_queue = EntQueue_New (mod_num_types); Cmd_AddCommand ("timerefresh", glsl_R_TimeRefresh_f, "Test the current refresh rate for the current location."); R_Init_Cvars (); diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 2dae866f0..74957ce3e 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -215,7 +215,7 @@ glsl_R_InitParticles (void) } static void -draw_qf_particles (void) +draw_qf_particles (psystem_t *psystem) { byte *at; int vacount; @@ -255,8 +255,8 @@ draw_qf_particles (void) vacount = 0; VA = particleVertexArray; - for (unsigned i = 0; i < r_psystem.numparticles; i++) { - particle_t *p = &r_psystem.particles[i]; + for (unsigned i = 0; i < psystem->numparticles; i++) { + particle_t *p = &psystem->particles[i]; // Don't render particles too close to us. // Note, we must still do physics and such on them. if (!(DotProduct (p->pos, r_refdef.frame.forward) < minparticledist)) { @@ -340,7 +340,7 @@ draw_qf_particles (void) } static void -draw_id_particles (void) +draw_id_particles (psystem_t *psystem) { int vacount; float minparticledist; @@ -375,8 +375,8 @@ draw_id_particles (void) vacount = 0; VA = particleVertexArray; - for (unsigned i = 0; i < r_psystem.numparticles; i++) { - particle_t *p = &r_psystem.particles[i]; + for (unsigned i = 0; i < psystem->numparticles; i++) { + particle_t *p = &psystem->particles[i]; // Don't render particles too close to us. // Note, we must still do physics and such on them. if (!(DotProduct (p->pos, r_refdef.frame.forward) < minparticledist)) { @@ -403,15 +403,15 @@ draw_id_particles (void) } void -glsl_R_DrawParticles (void) +glsl_R_DrawParticles (psystem_t *psystem) { - if (!r_particles->int_val || !r_psystem.numparticles) + if (!psystem->numparticles) { return; - R_RunParticles (vr_data.frametime); - if (!r_psystem.points_only) { - draw_qf_particles (); + } + if (!psystem->points_only) { + draw_qf_particles (psystem); } else { - draw_id_particles (); + draw_id_particles (psystem); } } diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index 9d43dead3..fd12cc206 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -88,7 +88,7 @@ void R_RunParticles (float dT) { psystem_t *ps = &r_psystem;//FIXME - vec4f_t gravity = {0, 0, -vr_data.gravity, 0}; + vec4f_t gravity = {0, 0, -r_data->gravity, 0}; unsigned j = 0; for (unsigned i = 0; i < ps->numparticles; i++) { diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 611ba885f..46d591dbb 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -161,6 +161,10 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) return; } + if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val) { + r_time1 = Sys_DoubleTime (); + } + refdef_t *refdef = r_data->refdef; if (camera) { Transform_GetWorldMatrix (camera, refdef->camera); @@ -194,15 +198,20 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) SCR_CalcRefdef (); } + R_RunParticles (r_data->frametime); R_AnimateLight (); refdef->viewleaf = 0; if (refdef->worldmodel) { vec4f_t position = refdef->frame.position; refdef->viewleaf = Mod_PointInLeaf (&position[0], refdef->worldmodel); } + R_MarkLeaves (); + R_PushDlights (vec3_origin); r_funcs->begin_frame (); r_funcs->render_view (); + r_funcs->draw_entities (r_ent_queue); + r_funcs->draw_particles (&r_psystem); r_funcs->set_2d (0); view_draw (r_data->scr_view); r_funcs->set_2d (1); @@ -475,4 +484,6 @@ SCR_Init (void) scr_turtle = r_funcs->Draw_PicFromWad ("turtle"); scr_initialized = true; + + r_ent_queue = EntQueue_New (mod_num_types); } diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 9771e8182..263a7645d 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -112,16 +112,11 @@ float r_viewmatrix[3][4]; float r_aliastransition, r_resfudge; -static float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; -static float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; - void sw_R_Init (void) { int dummy; - r_ent_queue = EntQueue_New (mod_num_types); - // get stack position so we can guess if we are going to overflow r_stack_start = (byte *) & dummy; @@ -411,17 +406,17 @@ draw_iqm_entity (entity_t *ent) R_IQMDrawModel (ent, &lighting); } -static void -R_DrawEntitiesOnList (void) +void +R_DrawEntitiesOnList (entqueue_t *queue) { if (!r_drawentities->int_val) return; #define RE_LOOP(type_name) \ do { \ - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \ + for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ i++) { \ - entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \ + entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \ VectorCopy (Transform_GetWorldPosition (ent->transform), \ r_entorigin); \ draw_##type_name##_entity (ent); \ @@ -549,7 +544,7 @@ R_BmodelCheckBBox (entity_t *ent, model_t *clmodel, float *minmaxs) } static void -R_DrawBrushEntitiesOnList (void) +R_DrawBrushEntitiesOnList (entqueue_t *queue) { int j, clipflags; unsigned int k; @@ -562,8 +557,8 @@ R_DrawBrushEntitiesOnList (void) insubmodel = true; - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { - entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; + for (size_t i = 0; i < queue->ent_queues[mod_brush].size; i++) { + entity_t *ent = queue->ent_queues[mod_brush].a[i]; VectorCopy (Transform_GetWorldPosition (ent->transform), origin); clmodel = ent->renderer.model; @@ -642,29 +637,7 @@ R_DrawBrushEntitiesOnList (void) } static void -R_PrintDSpeeds (void) -{ - float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, - - dv_time; - - r_time2 = Sys_DoubleTime (); - - dp_time = (dp_time2 - dp_time1) * 1000; - rw_time = (rw_time2 - rw_time1) * 1000; - db_time = (db_time2 - db_time1) * 1000; - se_time = (se_time2 - se_time1) * 1000; - de_time = (de_time2 - de_time1) * 1000; - dv_time = (dv_time2 - dv_time1) * 1000; - ms = (r_time2 - r_time1) * 1000; - - Sys_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n", - (int) ms, dp_time, (int) rw_time, db_time, (int) se_time, - de_time, dv_time); -} - -static void -R_EdgeDrawing (void) +R_EdgeDrawing (entqueue_t *queue) { edge_t ledges[NUMSTACKEDGES + ((CACHE_SIZE - 1) / sizeof (edge_t)) + 1]; @@ -690,10 +663,6 @@ R_EdgeDrawing (void) R_BeginEdgeFrame (); - if (r_dspeeds->int_val) { - rw_time1 = Sys_DoubleTime (); - } - R_RenderWorld (); if (r_drawculledpolys) @@ -703,21 +672,7 @@ R_EdgeDrawing (void) // just z writes, so have the driver turn z compares on now D_TurnZOn (); - if (r_dspeeds->int_val) { - rw_time2 = Sys_DoubleTime (); - db_time1 = rw_time2; - } - - R_DrawBrushEntitiesOnList (); - - if (r_dspeeds->int_val) { - db_time2 = Sys_DoubleTime (); - se_time1 = db_time2; - } - - if (!r_dspeeds->int_val) { - S_ExtraUpdate (); // don't let sound get messed up if going slow - } + R_DrawBrushEntitiesOnList (queue); if (!(r_drawpolys | r_drawculledpolys)) R_ScanEdges (); @@ -741,73 +696,24 @@ R_RenderView_ (void) r_warpbuffer = warpbuffer; - if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val) - r_time1 = Sys_DoubleTime (); - R_SetupFrame (); - R_MarkLeaves (); // done here so we know if we're in water - - R_PushDlights (vec3_origin); - // make FDIV fast. This reduces timing precision after we've been running for a // while, so we don't do it globally. This also sets chop mode, and we do it // here so that setup stuff like the refresh area calculations match what's // done in screen.c R_LowFPPrecision (); - if (!r_dspeeds->int_val) { - S_ExtraUpdate (); // don't let sound get messed up if going slow - } - - R_EdgeDrawing (); - - if (!r_dspeeds->int_val) { - S_ExtraUpdate (); // don't let sound get messed up if going slow - } - - if (r_dspeeds->int_val) { - se_time2 = Sys_DoubleTime (); - de_time1 = se_time2; - } - - R_DrawEntitiesOnList (); - - if (r_dspeeds->int_val) { - de_time2 = Sys_DoubleTime (); - dv_time1 = de_time2; - } + R_EdgeDrawing (r_ent_queue); R_DrawViewModel (); - if (r_dspeeds->int_val) { - dv_time2 = Sys_DoubleTime (); - dp_time1 = Sys_DoubleTime (); - } - - R_DrawParticles (); - - if (r_dspeeds->int_val) - dp_time2 = Sys_DoubleTime (); - if (r_dowarp) D_WarpScreen (); if (r_aliasstats->int_val) R_PrintAliasStats (); - if (r_speeds->int_val) - R_PrintTimes (); - - if (r_dspeeds->int_val) - R_PrintDSpeeds (); - - if (r_reportsurfout->int_val && r_outofsurfaces) - Sys_Printf ("Short %d surfaces\n", r_outofsurfaces); - - if (r_reportedgeout->int_val && r_outofedges) - Sys_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); - // back to high floating-point precision R_HighFPPrecision (); } diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index c0526b3ee..d24eeda2c 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -52,17 +52,18 @@ vec3_t r_pright, r_pup, r_ppn, r_porigin; void -R_DrawParticles (void) +R_DrawParticles (psystem_t *psystem) { + if (!psystem->numparticles) { + return; + } VectorScale (vright, xscaleshrink, r_pright); VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vfwd, r_ppn); VectorCopy (r_refdef.frame.position, r_porigin); - R_RunParticles (vr_data.frametime); - - for (unsigned i = 0; i < r_psystem.numparticles; i++) { - particle_t *p = &r_psystem.particles[i]; + for (unsigned i = 0; i < psystem->numparticles; i++) { + particle_t *p = &psystem->particles[i]; D_DrawParticle (p); } } diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 5c33f688d..c47213090 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -37,6 +37,7 @@ #include "QF/GL/qf_draw.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_rsurf.h" +#include "QF/GL/qf_particles.h" #include "QF/GL/qf_vid.h" #include "mod_internal.h" @@ -327,6 +328,8 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_ViewChanged, gl_begin_frame, gl_render_view, + gl_R_RenderEntities, + gl_R_DrawParticles, gl_set_2d, gl_end_frame, &model_funcs diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index a7274b7f8..b69c0b763 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -36,6 +36,7 @@ #include "QF/GLSL/qf_bsp.h" #include "QF/GLSL/qf_draw.h" #include "QF/GLSL/qf_main.h" +#include "QF/GLSL/qf_particles.h" #include "QF/GLSL/qf_vid.h" #include "mod_internal.h" @@ -271,6 +272,8 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_ViewChanged, glsl_begin_frame, glsl_render_view, + glsl_R_RenderEntities, + glsl_R_DrawParticles, glsl_set_2d, glsl_end_frame, &model_funcs diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index b3bb1eb14..f89735267 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -152,6 +152,12 @@ sw_set_2d (int scaled) static void sw_end_frame (void) { + if (r_reportsurfout->int_val && r_outofsurfaces) + Sys_Printf ("Short %d surfaces\n", r_outofsurfaces); + + if (r_reportedgeout->int_val && r_outofedges) + Sys_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); + // update one of three areas vrect_t vrect; if (vr_data.scr_copyeverything) { @@ -210,6 +216,8 @@ vid_render_funcs_t sw_vid_render_funcs = { R_ViewChanged, sw_begin_frame, sw_render_view, + R_DrawEntitiesOnList, + R_DrawParticles, sw_set_2d, sw_end_frame, &model_funcs diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index f295f3204..a14306caa 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -284,6 +284,25 @@ vulkan_render_view (void) } } +static void +vulkan_draw_entities (entqueue_t *queue) +{ + __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; + uint32_t imageIndex = vulkan_ctx->swapImageIndex; + + for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { + __auto_type rp = vulkan_ctx->renderPasses.a[i]; + __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + frame->framebuffer = rp->framebuffers->a[imageIndex]; + Vulkan_RenderEntities (queue, rpFrame); + } +} + +static void +vulkan_draw_particles (struct psystem_s *psystem) +{ +} + static void vulkan_set_2d (int scaled) { @@ -667,6 +686,8 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_R_ViewChanged, vulkan_begin_frame, vulkan_render_view, + vulkan_draw_entities, + vulkan_draw_particles, vulkan_set_2d, vulkan_end_frame, &model_funcs diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index bf26856dc..1eedc04ce 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -63,17 +63,17 @@ #include "r_internal.h" #include "vid_vulkan.h" -static void -Vulkan_RenderEntities (qfv_renderframe_t *rFrame) +void +Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame) { if (!r_drawentities->int_val) return; #define RE_LOOP(type_name, Type) \ do { \ int begun = 0; \ - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_##type_name].size; \ + for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ i++) { \ - entity_t *ent = r_ent_queue->ent_queues[mod_##type_name].a[i]; \ + entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \ if (!begun) { \ Vulkan_##Type##Begin (rFrame); \ begun = 1; \ @@ -115,52 +115,16 @@ void Vulkan_RenderView (qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - double t[10] = {}; - int speeds = r_speeds->int_val; if (!r_refdef.worldmodel) { return; } - if (speeds) - t[0] = Sys_DoubleTime (); - if (speeds) - t[1] = Sys_DoubleTime (); - R_MarkLeaves (); - if (speeds) - t[2] = Sys_DoubleTime (); - R_PushDlights (vec3_origin); - if (speeds) - t[3] = Sys_DoubleTime (); Vulkan_DrawWorld (rFrame); - if (speeds) - t[4] = Sys_DoubleTime (); Vulkan_DrawSky (rFrame); - if (speeds) - t[5] = Sys_DoubleTime (); Vulkan_DrawViewModel (ctx); - Vulkan_RenderEntities (rFrame); - if (speeds) - t[6] = Sys_DoubleTime (); Vulkan_DrawWaterSurfaces (rFrame); - if (speeds) - t[7] = Sys_DoubleTime (); - Vulkan_DrawParticles (ctx); - if (speeds) - t[8] = Sys_DoubleTime (); Vulkan_Bsp_Flush (ctx); - if (speeds) - t[9] = Sys_DoubleTime (); - if (speeds) { - double total = (t[9] - t[0]) * 1000; - for (int i = 0; i < 9; i++) { - t[i] = (t[i + 1] - t[i]) * 1000; - } - Sys_Printf ("frame: %g, setup: %g, mark: %g, pushdl: %g, world: %g," - " sky: %g, ents: %g, water: %g, flush: %g, part: %g\n", - total, - t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8]); - } } void From 2b72506868c14d37bea72b9fd68729ef3f2b2d88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Mar 2022 00:14:48 +0900 Subject: [PATCH 2550/3664] [renderer] Handle transparent surfaces Other than the view model (undecided on the approach) this has R_RenderView pretty much pulled out of the low level renderers. With this, I'll be able to focus on scene handling for a bit then getting shadows and fisheye working (again for fisheye). --- include/QF/plugin/vid_render.h | 1 + libs/video/renderer/gl/gl_rmain.c | 1 - libs/video/renderer/glsl/glsl_main.c | 1 - libs/video/renderer/r_screen.c | 1 + libs/video/renderer/vid_render_gl.c | 7 +++++++ libs/video/renderer/vid_render_glsl.c | 7 +++++++ libs/video/renderer/vid_render_sw.c | 6 ++++++ libs/video/renderer/vid_render_vulkan.c | 6 ++++++ 8 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index d88632356..61026553b 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -111,6 +111,7 @@ typedef struct vid_render_funcs_s { void (*render_view) (void); void (*draw_entities) (struct entqueue_s *queue); void (*draw_particles) (struct psystem_s *psystem); + void (*draw_transparent) (void); void (*set_2d) (int scaled); void (*end_frame) (void); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index c54d0fd96..6a5c247ba 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -320,7 +320,6 @@ R_RenderScene (void) gl_R_DrawWorld (); // adds static entities to the list S_ExtraUpdate (); // don't let sound get messed up if going slow gl_R_RenderDlights (); - gl_R_DrawWaterSurfaces (); R_DrawViewModel (); gl_Fog_DisableGFog (); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 4761bad6d..8e62fbb07 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -172,7 +172,6 @@ glsl_R_RenderView (void) R_SetupView (); glsl_R_DrawWorld (); glsl_R_DrawSky (); - glsl_R_DrawWaterSurfaces (); R_DrawViewModel (); } diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 46d591dbb..9d3b1994b 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -212,6 +212,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) r_funcs->render_view (); r_funcs->draw_entities (r_ent_queue); r_funcs->draw_particles (&r_psystem); + r_funcs->draw_transparent (); r_funcs->set_2d (0); view_draw (r_data->scr_view); r_funcs->set_2d (1); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index c47213090..6651b97ca 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -262,6 +262,12 @@ gl_render_view (void) gl_R_RenderView (); } +static void +gl_draw_transparent (void) +{ + gl_R_DrawWaterSurfaces (); +} + static void gl_set_2d (int scaled) { @@ -330,6 +336,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_render_view, gl_R_RenderEntities, gl_R_DrawParticles, + gl_draw_transparent, gl_set_2d, gl_end_frame, &model_funcs diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index b69c0b763..2913cd4f5 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -220,6 +220,12 @@ glsl_render_view (void) glsl_R_RenderView (); } +static void +glsl_draw_transparent (void) +{ + glsl_R_DrawWaterSurfaces (); +} + static void glsl_set_2d (int scaled) { @@ -274,6 +280,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_render_view, glsl_R_RenderEntities, glsl_R_DrawParticles, + glsl_draw_transparent, glsl_set_2d, glsl_end_frame, &model_funcs diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index f89735267..010133375 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -144,6 +144,11 @@ sw_render_view (void) R_RenderView (); } +static void +sw_draw_transparent (void) +{ +} + static void sw_set_2d (int scaled) { @@ -218,6 +223,7 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_render_view, R_DrawEntitiesOnList, R_DrawParticles, + sw_draw_transparent, sw_set_2d, sw_end_frame, &model_funcs diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a14306caa..352d24ae3 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -303,6 +303,11 @@ vulkan_draw_particles (struct psystem_s *psystem) { } +static void +vulkan_draw_transparent (void) +{ +} + static void vulkan_set_2d (int scaled) { @@ -688,6 +693,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_render_view, vulkan_draw_entities, vulkan_draw_particles, + vulkan_draw_transparent, vulkan_set_2d, vulkan_end_frame, &model_funcs From c8c742b24008b6b9e3dd16e0eab58e8cf5ecb10b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Mar 2022 11:03:37 +0900 Subject: [PATCH 2551/3664] [renderer] Use a better calculation for fov_y This avoids the possibility of a singularity (and thus the temptation to use Sys_Error). While the rendering is rubbish, 0 degrees is allowed because values less than 1 should be allowed, but where does one stop? 170 is the maximum in order to avoid any issues with (near) parallel or inverted frustum planes (or other fun things) in the low level code. --- libs/video/renderer/r_screen.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 9d3b1994b..63d2aace3 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -101,18 +101,11 @@ R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) static float __attribute__((pure)) CalcFov (float fov_x, float width, float height) { - float a, x; + double f = fov_x * M_PI / 360; + double c = cos(f); + double s = sin(f); - if (fov_x < 1 || fov_x > 179) - Sys_Error ("Bad fov: %f", fov_x); - - x = width / tan (fov_x * (M_PI / 360)); - - a = (x == 0) ? 90 : atan (height / x); // 0 shouldn't happen - - a = a * (360 / M_PI); - - return a; + return 360 * atan2 (s * height, c * width) / M_PI; } static void @@ -136,7 +129,7 @@ SCR_CalcRefdef (void) refdef->vrect.width, refdef->vrect.height); // bound field of view - Cvar_SetValue (scr_fov, bound (1, scr_fov->value, 170)); + Cvar_SetValue (scr_fov, bound (0, scr_fov->value, 170)); refdef->fov_y = CalcFov (refdef->fov_x, refdef->vrect.width, refdef->vrect.height); From a4479f48402ee8e2a70523502ae9f95421da5c52 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Mar 2022 11:42:14 +0900 Subject: [PATCH 2552/3664] [cvar] Ensure floats can round-trip when setting The way Cvar_SetValue is used, floats need to be able to round-trip reliably and thus need up to 9 digits of precision. --- libs/util/cvar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 0b383bd8f..d1f9b693d 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -307,7 +307,7 @@ Cvar_Set (cvar_t *var, const char *value) VISIBLE void Cvar_SetValue (cvar_t *var, float value) { - Cvar_Set (var, va (0, "%g", value)); + Cvar_Set (var, va (0, "%.9g", value)); } /* From ee51d06aa332727c0a8af9e1727566b33b2a4d30 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Mar 2022 00:56:30 +0900 Subject: [PATCH 2553/3664] [renderer] Clean up a lot of recalc_refdef use I think the widespread use of recalc_refdef (and force_fullscreen) was the result of a rushed merge of the renderer and video code (I do seem to remember sprinkling them around). This cleans the two out of the client code. --- include/QF/screen.h | 4 +- include/client/view.h | 1 - libs/client/cl_view.c | 8 +-- libs/console/menu.c | 1 - libs/video/renderer/r_cvar.c | 9 +++- libs/video/renderer/r_screen.c | 93 +++++++++++++++++++++++----------- nq/source/cl_main.c | 5 +- nq/source/cl_parse.c | 11 ++-- nq/source/sbar.c | 8 +-- qw/source/cl_main.c | 4 +- qw/source/cl_parse.c | 8 +-- qw/source/sbar.c | 8 +-- 12 files changed, 96 insertions(+), 64 deletions(-) diff --git a/include/QF/screen.h b/include/QF/screen.h index 7db658a4c..892fd6cf3 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -33,7 +33,6 @@ struct transform_s; struct tex_s; void SCR_Init (void); -void SCR_SetFOV (float fov); void SCR_DrawRam (void); void SCR_DrawTurtle (void); @@ -43,6 +42,9 @@ typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array void SCR_UpdateScreen (struct transform_s *camera, double realtime, SCR_Func *scr_funcs); +// control whether the 3d viewport is user-controlled or always fullscreen +void SCR_SetFullscreen (qboolean fullscreen); +void SCR_SetBottomMargin (int lines); void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); struct tex_s *SCR_SnapScreen (unsigned width, unsigned height); diff --git a/include/client/view.h b/include/client/view.h index ee6620ed0..59d7959f0 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -64,7 +64,6 @@ typedef struct viewstate_s { cshift_t cshifts[NUM_CSHIFTS]; // Color shifts for damage, powerups cshift_t prev_cshifts[NUM_CSHIFTS]; // and content types quat_t cshift_color; - qboolean cshift_changed; // pitch drifting vars float idealpitch; diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index a1ab36e82..7668ca832 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -444,17 +444,17 @@ V_PrepBlend (viewstate_t *vs) || (vs->force_cshifts & INFO_CSHIFT_POWERUP)) V_CalcPowerupCshift (vs); - vs->cshift_changed = false; + qboolean cshift_changed = false; for (i = 0; i < NUM_CSHIFTS; i++) { if (vs->cshifts[i].percent != vs->prev_cshifts[i].percent) { - vs->cshift_changed = true; + cshift_changed = true; vs->prev_cshifts[i].percent = vs->cshifts[i].percent; } for (j = 0; j < 3; j++) { if (vs->cshifts[i].destcolor[j] != vs->prev_cshifts[i].destcolor[j]) { - vs->cshift_changed = true; + cshift_changed = true; vs->prev_cshifts[i].destcolor[j] = vs->cshifts[i].destcolor[j]; } } @@ -465,7 +465,7 @@ V_PrepBlend (viewstate_t *vs) // drop the bonus value V_DropCShift (&vs->cshifts[CSHIFT_BONUS], vs->time, 100); - if (!vs->cshift_changed && !r_data->vid->recalc_refdef) + if (!cshift_changed) return; V_CalcBlend (vs); diff --git a/libs/console/menu.c b/libs/console/menu.c index 896ab7b82..619b06c1a 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -865,5 +865,4 @@ Menu_Leave () Con_SetState (con_inactive); } } - r_data->vid->recalc_refdef = true; } diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index 6f5f16d64..c7b96969c 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -161,7 +161,14 @@ r_nearclip_f (cvar_t *var) static void scr_fov_f (cvar_t *var) { - SCR_SetFOV (var->value); + // bound field of view + float fov = bound (0, var->value, 170); + + if (fov != var->value) { + Cvar_SetValue (var, fov); + } else { + r_data->vid->recalc_refdef = 1; + } } static void diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 63d2aace3..cd52efec9 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -66,8 +66,8 @@ static qboolean scr_initialized;// ready to draw static qpic_t *scr_ram; static qpic_t *scr_turtle; -void -R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) +static void +set_vrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) { float size; int h; @@ -98,44 +98,43 @@ R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) vrect->y = (h - vrect->height) / 2; } -static float __attribute__((pure)) -CalcFov (float fov_x, float width, float height) +void//FIXME remove when sw warp is cleaned up +R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) { - double f = fov_x * M_PI / 360; + set_vrect (vrectin, vrect, lineadj); +} + +static void +set_fov (float fov) +{ + + refdef_t *refdef = r_data->refdef; + + double f = fov * M_PI / 360; double c = cos(f); double s = sin(f); + double w = refdef->vrect.width; + double h = refdef->vrect.height; - return 360 * atan2 (s * height, c * width) / M_PI; + refdef->fov_x = fov; + refdef->fov_y = 360 * atan2 (s * h, c * w) / M_PI; } static void SCR_CalcRefdef (void) { - vrect_t vrect; - refdef_t *refdef = r_data->refdef; + view_t *view = r_data->scr_view; + const vrect_t *rect = &r_data->refdef->vrect; - // force a background redraw - r_data->scr_fullupdate = 0; r_data->vid->recalc_refdef = 0; - vrect.x = 0; - vrect.y = 0; - vrect.width = r_data->vid->width; - vrect.height = r_data->vid->height; - - R_SetVrect (&vrect, &refdef->vrect, r_data->lineadj); - - view_setgeometry (r_data->scr_view, refdef->vrect.x, refdef->vrect.y, - refdef->vrect.width, refdef->vrect.height); - - // bound field of view - Cvar_SetValue (scr_fov, bound (0, scr_fov->value, 170)); - - refdef->fov_y = CalcFov (refdef->fov_x, refdef->vrect.width, - refdef->vrect.height); + view_setgeometry (view, rect->x, rect->y, rect->width, rect->height); // notify the refresh of the change r_funcs->R_ViewChanged (); + + // force a background redraw + r_data->scr_fullupdate = 0; } /* @@ -216,12 +215,39 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) r_funcs->end_frame (); } -void -SCR_SetFOV (float fov) +static void +update_vrect (void) { - refdef_t *refdef = r_data->refdef; - refdef->fov_x = fov; r_data->vid->recalc_refdef = 1; + + vrect_t vrect; + refdef_t *refdef = r_data->refdef; + + vrect.x = 0; + vrect.y = 0; + vrect.width = r_data->vid->width; + vrect.height = r_data->vid->height; + + set_vrect (&vrect, &refdef->vrect, r_data->lineadj); + set_fov (scr_fov->value); +} + +void +SCR_SetFullscreen (qboolean fullscreen) +{ + if (r_data->force_fullscreen == fullscreen) { + return; + } + + r_data->force_fullscreen = fullscreen; + update_vrect (); +} + +void +SCR_SetBottomMargin (int lines) +{ + r_data->lineadj = lines; + update_vrect (); } static void @@ -465,6 +491,12 @@ SCR_SnapScreen (unsigned width, unsigned height) return tex; } +static void +viewsize_listener (void *data, const cvar_t *cvar) +{ + update_vrect (); +} + void SCR_Init (void) { @@ -480,4 +512,7 @@ SCR_Init (void) scr_initialized = true; r_ent_queue = EntQueue_New (mod_num_types); + + Cvar_AddListener (scr_viewsize, viewsize_listener, 0); + update_vrect (); } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 9c7fb5c2d..3b63db068 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -154,8 +154,7 @@ void CL_ClearMemory (void) { VID_ClearMemory (); - if (r_data) - r_data->force_fullscreen = 0; + SCR_SetFullscreen (0); } void @@ -220,7 +219,7 @@ CL_ClearState (void) cl.viewstate.chasestate = &cl.chasestate; cl.chasestate.viewstate = &cl.viewstate; cl.watervis = 1; - r_data->force_fullscreen = 0; + SCR_SetFullscreen (0); r_data->lightstyle = cl.lightstyle; SZ_Clear (&cls.message); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 0d85bb3a2..f186b31c8 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -841,8 +841,6 @@ CL_ParseServerMessage (void) } Cbuf_Execute_Stack (host_cbuf); CL_ParseServerInfo (); - // leave full screen intermission - r_data->vid->recalc_refdef = true; break; case svc_lightstyle: @@ -984,16 +982,14 @@ CL_ParseServerMessage (void) case svc_intermission: cl.intermission = 1; - r_data->force_fullscreen = 1; + SCR_SetFullscreen (1); cl.completed_time = cl.time; - r_data->vid->recalc_refdef = true; // go to full screen break; case svc_finale: cl.intermission = 2; - r_data->force_fullscreen = 1; + SCR_SetFullscreen (1); cl.completed_time = cl.time; - r_data->vid->recalc_refdef = true; // go to full screen str = MSG_ReadString (net_message); if (strcmp (str, centerprint->str)) { dstring_copystr (centerprint, str); @@ -1018,9 +1014,8 @@ CL_ParseServerMessage (void) case svc_cutscene: cl.intermission = 3; - r_data->force_fullscreen = 1; + SCR_SetFullscreen (1); cl.completed_time = cl.time; - r_data->vid->recalc_refdef = true; // go to full screen str = MSG_ReadString (net_message); if (strcmp (str, centerprint->str)) { dstring_copystr (centerprint, str); diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 5e596f07a..7a564ed87 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -206,10 +206,9 @@ calc_sb_lines (cvar_t *var) static void hud_sbar_f (cvar_t *var) { - r_data->vid->recalc_refdef = true; if (r_data->scr_viewsize) calc_sb_lines (r_data->scr_viewsize); - r_data->lineadj = var->int_val ? sb_lines : 0; + SCR_SetBottomMargin (var->int_val ? sb_lines : 0); if (var->int_val) { view_remove (main_view, main_view->children[0]); view_insert (main_view, sbar_view, 0); @@ -223,8 +222,9 @@ static void viewsize_f (cvar_t *var) { calc_sb_lines (var); - if (hud_sbar) - r_data->lineadj = hud_sbar->int_val ? sb_lines : 0; + if (hud_sbar) { + SCR_SetBottomMargin (hud_sbar->int_val ? sb_lines : 0); + } } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 6b8e8301a..6777a822f 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -399,7 +399,7 @@ CL_ClearState (void) memset (&cl, 0, sizeof (cl)); cl.viewstate.camera_transform = cam; cl.players = calloc (MAX_CLIENTS, sizeof (player_info_t)); - r_data->force_fullscreen = 0; + SCR_SetFullscreen (0); cl.maxclients = MAX_CLIENTS; cl.viewstate.voffs_enabled = 0; @@ -812,7 +812,7 @@ CL_Changing_f (void) S_StopAllSounds (); cl.intermission = 0; cl.viewstate.intermission = 0; - r_data->force_fullscreen = 0; + SCR_SetFullscreen (0); CL_SetState (ca_connected); // not active anymore, but not // disconnected Sys_Printf ("\nChanging map...\n"); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index e585dbc48..b27dff394 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1351,8 +1351,6 @@ CL_ParseServerMessage (void) } Cbuf_Execute_Stack (cl_stbuf); CL_ParseServerData (); - // leave full screen intermission - r_data->vid->recalc_refdef = true; break; case svc_lightstyle: @@ -1455,9 +1453,8 @@ CL_ParseServerMessage (void) Sys_MaskPrintf (SYS_dev, "svc_intermission\n"); cl.intermission = 1; - r_data->force_fullscreen = 1; + SCR_SetFullscreen (1); cl.completed_time = realtime; - r_data->vid->recalc_refdef = true; // go to full screen Sys_MaskPrintf (SYS_dev, "intermission simorg: "); MSG_ReadCoordV (net_message, &cl.viewstate.player_origin[0]);//FIXME cl.viewstate.player_origin[3] = 1; @@ -1479,9 +1476,8 @@ CL_ParseServerMessage (void) case svc_finale: cl.intermission = 2; - r_data->force_fullscreen = 1; + SCR_SetFullscreen (1); cl.completed_time = realtime; - r_data->vid->recalc_refdef = true; // go to full screen str = MSG_ReadString (net_message); if (strcmp (str, centerprint->str)) { dstring_copystr (centerprint, str); diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 0281c332f..84532d2ed 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -194,10 +194,9 @@ calc_sb_lines (cvar_t *var) static void hud_sbar_f (cvar_t *var) { - r_data->vid->recalc_refdef = true; if (r_data->scr_viewsize) calc_sb_lines (r_data->scr_viewsize); - r_data->lineadj = var->int_val ? sb_lines : 0; + SCR_SetBottomMargin (var->int_val ? sb_lines : 0); if (var->int_val) { view_remove (main_view, main_view->children[0]); view_insert (main_view, sbar_view, 0); @@ -211,8 +210,9 @@ static void viewsize_f (cvar_t *var) { calc_sb_lines (var); - if (hud_sbar) - r_data->lineadj = hud_sbar->int_val ? sb_lines : 0; + if (hud_sbar) { + SCR_SetBottomMargin (hud_sbar->int_val ? sb_lines : 0); + } } From c3f38e1c799de7e351fbae2b6e030b0fb3e768f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Mar 2022 09:46:53 +0900 Subject: [PATCH 2554/3664] [renderer] Remove player_entity field This was a hold-over from the gl mirror code. --- include/QF/plugin/vid_render.h | 1 - libs/video/renderer/vid_common.c | 1 - nq/source/cl_ents.c | 1 - qw/source/cl_ents.c | 1 - 4 files changed, 4 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 61026553b..a49a3bd36 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -134,7 +134,6 @@ typedef struct vid_render_data_s { qboolean paused; int lineadj; struct entity_s *view_model; - struct entity_s *player_entity; float gravity; double frametime; double realtime; diff --git a/libs/video/renderer/vid_common.c b/libs/video/renderer/vid_common.c index 004410c58..546bb4b9b 100644 --- a/libs/video/renderer/vid_common.c +++ b/libs/video/renderer/vid_common.c @@ -48,7 +48,6 @@ vid_render_data_t vid_render_data = { false, false, false, 0, 0, 0, - 0, 0.0, 0.0, 0, }; diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 47cd44293..588753fd2 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -326,7 +326,6 @@ CL_RelinkEntities (void) SET_REMOVE (&cl_forcelink, i); } - r_data->player_entity = CL_GetEntity (cl.viewentity); cl.viewstate.player_entity = CL_GetEntity (cl.viewentity); cl.viewstate.player_origin = Transform_GetWorldPosition (cl.viewstate.player_entity->transform); diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index e844afe69..c0cd30bd1 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -413,7 +413,6 @@ CL_LinkPlayers (void) // spawn light flashes, even ones coming from invisible objects if (j == cl.playernum) { org = cl.viewstate.player_origin; - r_data->player_entity = ent; cl.viewstate.player_entity = ent; clientplayer = true; } else { From b912c2a667bd0212ce9698a50a971f1694fd3302 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Mar 2022 10:06:38 +0900 Subject: [PATCH 2555/3664] [renderer] Clean up R_SetFrustum The only global it touches now is frustum, and that needs fixing in mathlib (good grief, we (probably I) did some weird things when merging the code). --- include/QF/render.h | 20 +++++++++++--------- include/r_local.h | 3 ++- libs/video/renderer/r_main.c | 23 ++++++++++++----------- libs/video/renderer/r_screen.c | 2 +- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index bd05032eb..61bde87db 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -181,6 +181,16 @@ typedef struct entity_s { vec4f_t old_origin; } entity_t; +typedef union refframe_s { + mat4f_t mat; + struct { + vec4f_t right; + vec4f_t forward; + vec4f_t up; + vec4f_t position; + }; +} refframe_t; + // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { vrect_t vrect; // subwindow in video for refresh @@ -203,15 +213,7 @@ typedef struct { float xOrigin; // should probably always be 0.5 float yOrigin; // between be around 0.3 to 0.5 - union { - mat4f_t mat; - struct { - vec4f_t right; - vec4f_t forward; - vec4f_t up; - vec4f_t position; - }; - } frame; + refframe_t frame; mat4f_t camera; mat4f_t camera_inverse; diff --git a/include/r_local.h b/include/r_local.h index 9c3059479..469baca0b 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -141,7 +141,8 @@ extern vec3_t r_worldmodelorg; extern mat4f_t glsl_projection; extern mat4f_t glsl_view; -void R_SetFrustum (void); +union refframe_s; +void R_SetFrustum (const union refframe_s *frame, float fov_x, float fov_y); void R_SpriteBegin (void); void R_SpriteEnd (void); diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index 016bd0136..b9cafb9a1 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -89,25 +89,26 @@ SignbitsForPlane (plane_t *out) } void -R_SetFrustum (void) +R_SetFrustum (const refframe_t *frame, float fov_x, float fov_y) { int i; - vec4f_t right = r_refdef.frame.right; - vec4f_t fwd = r_refdef.frame.forward; - vec4f_t up = r_refdef.frame.up; - float rot_x = 90 - r_refdef.fov_x / 2; - float rot_y = 90 - r_refdef.fov_y / 2; + vec4f_t right = frame->right; + vec4f_t fwd = frame->forward; + vec4f_t up = frame->up; + + fov_x = 90 - fov_x / 2; + fov_y = 90 - fov_y / 2; // rotate FWD right by FOV_X/2 degrees - RotatePointAroundVector (frustum[0].normal, &up[0], &fwd[0], -rot_x); + RotatePointAroundVector (frustum[0].normal, &up[0], &fwd[0], -fov_x); // rotate FWD left by FOV_X/2 degrees - RotatePointAroundVector (frustum[1].normal, &up[0], &fwd[0], rot_x); + RotatePointAroundVector (frustum[1].normal, &up[0], &fwd[0], fov_x); // rotate FWD up by FOV_Y/2 degrees - RotatePointAroundVector (frustum[2].normal, &right[0], &fwd[0], rot_y); + RotatePointAroundVector (frustum[2].normal, &right[0], &fwd[0], fov_y); // rotate FWD down by FOV_Y/2 degrees - RotatePointAroundVector (frustum[3].normal, &right[0], &fwd[0], -rot_y); + RotatePointAroundVector (frustum[3].normal, &right[0], &fwd[0], -fov_y); - vec4f_t origin = r_refdef.frame.position; + vec4f_t origin = frame->position; for (i = 0; i < 4; i++) { frustum[i].type = PLANE_ANYZ; frustum[i].dist = DotProduct (origin, frustum[i].normal); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index cd52efec9..bb2ce0b21 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -177,11 +177,11 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) refdef->frame.mat[1] = refdef->camera[0]; refdef->frame.mat[2] = refdef->camera[2]; refdef->frame.mat[3] = refdef->camera[3]; + R_SetFrustum (&refdef->frame, refdef->fov_x, refdef->fov_y); //FIXME breaks fisheye as it calls the view render many times EntQueue_Clear (r_ent_queue); r_framecount++; - R_SetFrustum (); r_data->realtime = realtime; scr_copytop = r_data->scr_copyeverything = 0; From 65af7fb4a463963a03a887d0cb6018e77498fc6a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Mar 2022 12:33:12 +0900 Subject: [PATCH 2556/3664] [mathlib] Remove frustum global It should never have been there and is now in the refdef (not its final home: it should probably be part of the camera). --- include/QF/mathlib.h | 11 +++++------ include/QF/render.h | 1 + include/r_local.h | 3 ++- libs/util/mathlib.c | 4 +--- libs/video/renderer/gl/gl_mod_alias.c | 2 +- libs/video/renderer/gl/gl_rsurf.c | 6 +++--- libs/video/renderer/glsl/glsl_bsp.c | 6 +++--- libs/video/renderer/r_light.c | 2 +- libs/video/renderer/r_main.c | 3 ++- libs/video/renderer/r_screen.c | 3 ++- libs/video/renderer/vulkan/vulkan_bsp.c | 6 +++--- 11 files changed, 24 insertions(+), 23 deletions(-) diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index ef65f6aa8..a0e7b8103 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -141,7 +141,7 @@ void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, void AngleQuat (const vec3_t angles, quat_t q); void VectorVectors (const vec3_t forward, vec3_t right, vec3_t up); int BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, - struct plane_s *plane) __attribute__((pure)); + const plane_t *plane) __attribute__((pure)); float anglemod (float a) __attribute__((const)); void RotatePointAroundVector (vec3_t dst, const vec3_t axis, @@ -175,9 +175,8 @@ void RotatePointAroundVector (vec3_t dst, const vec3_t axis, VectorNegate ((sp)->normal, (dp)->normal); \ } while (0) -extern plane_t * const frustum; -GNU89INLINE inline qboolean R_CullBox (const vec3_t mins, const vec3_t maxs) __attribute__((pure)); -GNU89INLINE inline qboolean R_CullSphere (const vec3_t origin, const float radius); +GNU89INLINE inline qboolean R_CullBox (const plane_t *frustum, const vec3_t mins, const vec3_t maxs) __attribute__((pure)); +GNU89INLINE inline qboolean R_CullSphere (const plane_t *frustum, const vec3_t origin, const float radius); #ifndef IMPLEMENT_R_Cull GNU89INLINE inline @@ -185,7 +184,7 @@ GNU89INLINE inline VISIBLE #endif qboolean -R_CullBox (const vec3_t mins, const vec3_t maxs) +R_CullBox (const plane_t *frustum, const vec3_t mins, const vec3_t maxs) { int i; @@ -203,7 +202,7 @@ GNU89INLINE inline VISIBLE #endif qboolean -R_CullSphere (const vec3_t origin, const float radius) +R_CullSphere (const plane_t *frustum, const vec3_t origin, const float radius) { int i; float r; diff --git a/include/QF/render.h b/include/QF/render.h index 61bde87db..bffec3a85 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -214,6 +214,7 @@ typedef struct { float yOrigin; // between be around 0.3 to 0.5 refframe_t frame; + plane_t frustum[4]; mat4f_t camera; mat4f_t camera_inverse; diff --git a/include/r_local.h b/include/r_local.h index 469baca0b..0c7a7129e 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -142,7 +142,8 @@ extern mat4f_t glsl_projection; extern mat4f_t glsl_view; union refframe_s; -void R_SetFrustum (const union refframe_s *frame, float fov_x, float fov_y); +void R_SetFrustum (plane_t *frustum, const union refframe_s *frame, + float fov_x, float fov_y); void R_SpriteBegin (void); void R_SpriteEnd (void); diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index e047fca89..9f8aa2def 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -48,8 +48,6 @@ #include "QF/sys.h" VISIBLE int nanmask = 255 << 23; -static plane_t _frustum[4]; -VISIBLE plane_t *const frustum = _frustum; static vec3_t _vec3_origin = { 0, 0, 0 }; VISIBLE const vec_t * const vec3_origin = _vec3_origin; static quat_t _quat_origin = { 0, 0, 0, 0 }; @@ -393,7 +391,7 @@ BOPS_Error (void) Returns 1, 2, or 1 + 2 */ VISIBLE int -BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, plane_t *p) +BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, const plane_t *p) { float dist1, dist2; int sides; diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 307410f53..1ba1f64ab 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -434,7 +434,7 @@ gl_R_DrawAliasModel (entity_t *e) if (scale[0] != 1.0) { radius *= scale[0]; } - if (R_CullSphere (&origin[0], radius)) {//FIXME + if (R_CullSphere (r_refdef.frustum, &origin[0], radius)) {//FIXME return; } diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index d2b0aff68..75e42ff5a 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -544,7 +544,7 @@ gl_R_DrawBrushModel (entity_t *e) if (e->scale != 1.0) radius *= e->scale; #endif - if (R_CullSphere (&worldMatrix[3][0], radius)) {//FIXME + if (R_CullSphere (r_refdef.frustum, &worldMatrix[3][0], radius)) {//FIXME return; } } else { @@ -557,7 +557,7 @@ gl_R_DrawBrushModel (entity_t *e) VectorScale (maxs, e->scale, maxs); } #endif - if (R_CullBox (mins, maxs)) + if (R_CullBox (r_refdef.frustum, mins, maxs)) return; } @@ -660,7 +660,7 @@ test_node (mnode_t *node) return 0; if (node->visframe != r_visframecount) return 0; - if (R_CullBox (node->minmaxs, node->minmaxs + 3)) + if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) return 0; return 1; } diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index aced41a62..eb8fdab4b 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -677,14 +677,14 @@ R_DrawBrushModel (entity_t *e) if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; - if (R_CullSphere (&mat[3][0], radius)) { // FIXME + if (R_CullSphere (r_refdef.frustum, &mat[3][0], radius)) { // FIXME return; } } else { rotated = false; VectorAdd (mat[3], model->mins, mins); VectorAdd (mat[3], model->maxs, maxs); - if (R_CullBox (mins, maxs)) + if (R_CullBox (r_refdef.frustum, mins, maxs)) return; } @@ -779,7 +779,7 @@ test_node (mnode_t *node) return 0; if (node->visframe != r_visframecount) return 0; - if (R_CullBox (node->minmaxs, node->minmaxs + 3)) + if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) return 0; return 1; } diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 0b32a6f6d..6356d4c2b 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -297,7 +297,7 @@ R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, || leaf->mins[1] > maxs[1] || leaf->maxs[1] < mins[1] || leaf->mins[2] > maxs[2] || leaf->maxs[2] < mins[2]) continue; - if (R_CullBox (leaf->mins, leaf->maxs)) + if (R_CullBox (r_refdef.frustum, leaf->mins, leaf->maxs)) continue; for (m = 0; m < leaf->nummarksurfaces; m++) { msurface_t *surf = leaf->firstmarksurface[m]; diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index b9cafb9a1..e9184c80f 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -89,7 +89,8 @@ SignbitsForPlane (plane_t *out) } void -R_SetFrustum (const refframe_t *frame, float fov_x, float fov_y) +R_SetFrustum (plane_t *frustum, const refframe_t *frame, + float fov_x, float fov_y) { int i; vec4f_t right = frame->right; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index bb2ce0b21..77fdeb411 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -177,7 +177,8 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) refdef->frame.mat[1] = refdef->camera[0]; refdef->frame.mat[2] = refdef->camera[2]; refdef->frame.mat[3] = refdef->camera[3]; - R_SetFrustum (&refdef->frame, refdef->fov_x, refdef->fov_y); + R_SetFrustum (refdef->frustum, &refdef->frame, + refdef->fov_x, refdef->fov_y); //FIXME breaks fisheye as it calls the view render many times EntQueue_Clear (r_ent_queue); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 40dee2f61..53c4d65a3 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -604,14 +604,14 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; - if (R_CullSphere (&mat[3][0], radius)) { //FIXME + if (R_CullSphere (r_refdef.frustum, &mat[3][0], radius)) { //FIXME return; } } else { rotated = false; VectorAdd (mat[3], model->mins, mins); VectorAdd (mat[3], model->maxs, maxs); - if (R_CullBox (mins, maxs)) + if (R_CullBox (r_refdef.frustum, mins, maxs)) return; } @@ -691,7 +691,7 @@ test_node (mnode_t *node) return 0; if (node->visframe != r_visframecount) return 0; - if (R_CullBox (node->minmaxs, node->minmaxs + 3)) + if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) return 0; return 1; } From 0f30f0a133741af7943ef6ab84c65bc687d89c2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Mar 2022 12:35:01 +0900 Subject: [PATCH 2557/3664] [mathlib] Remove suspicious IS_NAN The implementation looks wrong (more like infinity). Where it was used is currently disabled, but the usages were replaced with C99's isnan. --- include/QF/mathlib.h | 4 ---- libs/util/mathlib.c | 1 - nq/source/sv_phys.c | 7 +++---- qw/source/sv_phys.c | 7 +++---- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index a0e7b8103..5f8c900d2 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -50,13 +50,9 @@ # define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h #endif -extern int nanmask; - #define EQUAL_EPSILON 0.001 #define RINT(x) (floor ((x) + 0.5)) -#define IS_NAN(x) (((*(int *) (char *) &x) & nanmask) == nanmask) - #define Blend(a,b,blend) ((1 - (blend)) * (a) + (blend) * (b)) #include "QF/math/vector.h" diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 9f8aa2def..3846f9dd7 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -47,7 +47,6 @@ #include "QF/set.h" #include "QF/sys.h" -VISIBLE int nanmask = 255 << 23; static vec3_t _vec3_origin = { 0, 0, 0 }; VISIBLE const vec_t * const vec3_origin = _vec3_origin; static quat_t _quat_origin = { 0, 0, 0, 0 }; diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index ab2b4f966..552fe227a 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -88,18 +88,17 @@ void SV_CheckVelocity (edict_t *ent) { float wishspeed; -// int i; // bound velocity #if 0 - for (i = 0; i < 3; i++) { - if (IS_NAN (SVvector (ent, velocity)[i])) { + for (int i = 0; i < 3; i++) { + if (isnan (SVvector (ent, velocity)[i])) { Sys_Printf ("Got a NaN velocity on %s\n", PR_GetString (&sv_pr_state, SVstring (ent, classname))); SVvector (ent, velocity)[i] = 0; } - if (IS_NAN (SVvector (ent, origin)[i])) { + if (isnan (SVvector (ent, origin)[i])) { Sys_Printf ("Got a NaN origin on %s\n", PR_GetString (&sv_pr_state, SVstring (ent, classname))); diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index 856a5ef16..5e1122053 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -87,18 +87,17 @@ void SV_CheckVelocity (edict_t *ent) { float wishspeed; -// int i; // bound velocity #if 0 - for (i = 0; i < 3; i++) { - if (IS_NAN (SVvector (ent, velocity)[i])) { + for (int i = 0; i < 3; i++) { + if (isnan (SVvector (ent, velocity)[i])) { Sys_Printf ("Got a NaN velocity on %s\n", PR_GetString (&sv_pr_state, SVstring (ent, classname))); SVvector (ent, velocity)[i] = 0; } - if (IS_NAN (SVvector (ent, origin)[i])) { + if (isnan (SVvector (ent, origin)[i])) { Sys_Printf ("Got a NaN origin on %s\n", PR_GetString (&sv_pr_state, SVstring (ent, classname))); From 3b4608a0cd3eca851ca93d1a5db1701666f5eed5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Mar 2022 12:52:20 +0900 Subject: [PATCH 2558/3664] [vid] Update glx handling to ensure GL 3.0 With what I have planned for frame buffers etc, GL 3.0 will be needed even for the fixed-function GL renderer, and then I might even take the GLSL renderer to 4.6 (dunno yet). This means that wgl will need to be updated too, and I've found the info I need for that, but it's a bit much to take on just yet. --- libs/video/targets/vid_x11_gl.c | 77 ++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index bcfbcd68c..7f6285506 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -61,13 +61,26 @@ #define GLX_RED_SIZE 8 // number of red component bits #define GLX_GREEN_SIZE 9 // number of green component bits #define GLX_BLUE_SIZE 10 // number of blue component bits +#define GLX_ALPHA_SIZE 11 // number of alpha component bits #define GLX_DEPTH_SIZE 12 // number of depth bits +#define GLX_STENCIL_SIZE 13 // number of stencil bits +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 + +#define GLX_X_RENDERABLE 0x8012 +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_X_VISUAL_TYPE 0x22 +#define GLX_TRUE_COLOR 0x8002 + typedef XID GLXDrawable; // GLXContext is a pointer to opaque data typedef struct __GLXcontextRec *GLXContext; - +typedef struct __GLXFBConfigRec *GLXFBConfig; // Define GLAPIENTRY to a useful value #ifndef GLAPIENTRY @@ -79,16 +92,24 @@ typedef struct __GLXcontextRec *GLXContext; #endif static void *libgl_handle; static void (*qfglXSwapBuffers) (Display *dpy, GLXDrawable drawable); -static XVisualInfo* (*qfglXChooseVisual) (Display *dpy, int screen, - int *attribList); -static GLXContext (*qfglXCreateContext) (Display *dpy, XVisualInfo *vis, - GLXContext shareList, Bool direct); +static GLXContext (*qfglXCreateContextAttribsARB) (Display *dpy, + GLXFBConfig cfg, + GLXContext ctx, + Bool direct, + const int *attribs); +static GLXFBConfig *(*qfglXChooseFBConfig) (Display *dpy, int screen, + const int *attribs, int *nitems); +static XVisualInfo *(*qfglXGetVisualFromFBConfig) (Display *dpy, + GLXFBConfig config); +static int (*qfglXGetFBConfigAttrib) (Display *dpy, GLXFBConfig config, + int attribute, int *value); static Bool (*qfglXMakeCurrent) (Display *dpy, GLXDrawable drawable, GLXContext ctx); static void (GLAPIENTRY *qfglFinish) (void); static void *(*glGetProcAddress) (const char *symbol) = NULL; static int use_gl_procaddress = 0; +static GLXFBConfig glx_cfg; static cvar_t *gl_driver; static void * @@ -133,28 +154,50 @@ static void glx_choose_visual (gl_ctx_t *ctx) { int attrib[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, - GLX_DEPTH_SIZE, 1, + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 24, + //I can't tell if this makes any difference to performance, but it's + //currently not needed + //GLX_STENCIL_SIZE, 8, + GLX_DOUBLEBUFFER, True, None }; + int fbcount; + GLXFBConfig *fbc = qfglXChooseFBConfig (x_disp, x_screen, attrib, &fbcount); - x_visinfo = qfglXChooseVisual (x_disp, x_screen, attrib); + if (!fbc) { + Sys_Error ("Failed to retrieve a framebuffer config"); + } + Sys_MaskPrintf (SYS_vid, "Found %d matching FB configs.\n", fbcount); + glx_cfg = fbc[0]; + XFree (fbc); + x_visinfo = qfglXGetVisualFromFBConfig (x_disp, glx_cfg); if (!x_visinfo) { Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth visual"); } x_vis = x_visinfo->visual; + printf ("%p\n", x_vis); } static void glx_create_context (gl_ctx_t *ctx) { + int attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + //GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB + None + }; XSync (x_disp, 0); - ctx->context = (GL_context) qfglXCreateContext (x_disp, x_visinfo, NULL, - True); + ctx->context = (GL_context) qfglXCreateContextAttribsARB (x_disp, glx_cfg, + 0, True, attribs); qfglXMakeCurrent (x_disp, x_win, (GLXContext) ctx->context); ctx->init_gl (); } @@ -179,8 +222,10 @@ glx_load_gl (void) glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddressARB"); qfglXSwapBuffers = QFGL_ProcAddress ("glXSwapBuffers", true); - qfglXChooseVisual = QFGL_ProcAddress ("glXChooseVisual", true); - qfglXCreateContext = QFGL_ProcAddress ("glXCreateContext", true); + qfglXChooseFBConfig = QFGL_ProcAddress ("glXChooseFBConfig", true); + qfglXGetVisualFromFBConfig = QFGL_ProcAddress ("glXGetVisualFromFBConfig", true); + qfglXGetFBConfigAttrib = QFGL_ProcAddress ("glXGetFBConfigAttrib", true); + qfglXCreateContextAttribsARB = QFGL_ProcAddress ("glXCreateContextAttribsARB", true); qfglXMakeCurrent = QFGL_ProcAddress ("glXMakeCurrent", true); use_gl_procaddress = 1; From b82a353a203715a59c8fd31c3a8286342ab93f92 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Mar 2022 11:12:58 +0900 Subject: [PATCH 2559/3664] [vid] Remove VID_InitBuffers Its guts have been moved to D_Init temporarily while I work on the frame buffer design. This is actually a big part of that work as it moves most of the frame buffer creation into the one place, making it easier to ensure I get all the sub-buffers and caches created. --- include/r_internal.h | 4 +- include/vid_internal.h | 3 -- libs/video/renderer/sw/d_init.c | 30 +++++++++++++-- libs/video/renderer/sw/d_surf.c | 4 +- libs/video/targets/vid.c | 67 --------------------------------- libs/video/targets/vid_x11_sw.c | 9 +++++ 6 files changed, 39 insertions(+), 78 deletions(-) diff --git a/include/r_internal.h b/include/r_internal.h index c25ba7271..71841b948 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -52,10 +52,10 @@ void R_PushDlights (const vec3_t entorigin); void R_DrawWaterSurfaces (void); void *D_SurfaceCacheAddress (void) __attribute__((pure)); -int D_SurfaceCacheForRes (void *data, int width, int height); +int D_SurfaceCacheForRes (int width, int height); void D_FlushCaches (void *data); void D_DeleteSurfaceCache (void); -void D_InitCaches (void *data, void *buffer, int size); +void D_InitCaches (void *buffer, int size); void R_SetVrect (const vrect_t *pvrect, vrect_t *pvrectin, int lineadj); void R_LoadSkys (const char *); diff --git a/include/vid_internal.h b/include/vid_internal.h index 7912dca52..0136d0cc0 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -5,9 +5,7 @@ #include "QF/plugin/vid_render.h" typedef struct vid_internal_s { - int (*surf_cache_size) (void *data, int width, int height); void (*flush_caches) (void *data); - void (*init_caches) (void *data, void *cache, int size); void (*init_buffers) (void *data); void (*set_palette) (void *data, const byte *palette); @@ -31,7 +29,6 @@ void VID_InitGamma (const byte *); qboolean VID_SetGamma (double); void VID_UpdateGamma (struct cvar_s *); -void VID_InitBuffers (void); void VID_MakeColormaps (void); #endif//__vid_internal_h diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index 9eed2bb89..349733f76 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -56,11 +56,33 @@ D_Init (void) r_worldpolysbacktofront = false; r_recursiveaffinetriangles = true; - vr_data.vid->vid_internal->surf_cache_size = D_SurfaceCacheForRes; - vr_data.vid->vid_internal->flush_caches = D_FlushCaches; - vr_data.vid->vid_internal->init_caches = D_InitCaches; + viddef_t *vid = vr_data.vid; - VID_InitBuffers (); + vid->vid_internal->flush_caches = D_FlushCaches; + + int buffersize = vid->rowbytes * vid->height; + int zbuffersize = vid->width * vid->height * sizeof (*vid->zbuffer); + int cachesize = D_SurfaceCacheForRes (vid->width, vid->height); + + if (vid->zbuffer) { + free (vid->zbuffer); + vid->zbuffer = 0; + } + if (vid->surfcache) { + D_FlushCaches (0); + free (vid->surfcache); + vid->surfcache = 0; + } + if (vid->vid_internal->init_buffers) { + vid->vid_internal->init_buffers (vid->vid_internal->data); + } else { + free (vid->buffer); + vid->buffer = calloc (buffersize, 1); + } + vid->zbuffer = calloc (zbuffersize, 1); + vid->surfcache = calloc (cachesize, 1); + + D_InitCaches (vid->surfcache, cachesize); } void diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 33b4b399f..eb45010db 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -54,7 +54,7 @@ D_SurfaceCacheAddress (void) } int -D_SurfaceCacheForRes (void *data, int width, int height) +D_SurfaceCacheForRes (int width, int height) { int size, pix; @@ -96,7 +96,7 @@ D_ClearCacheGuard (void) } void -D_InitCaches (void *data, void *buffer, int size) +D_InitCaches (void *buffer, int size) { Sys_MaskPrintf (SYS_dev, "D_InitCaches: %ik surface cache\n", size/1024); diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index b918dd1b9..12aeedf99 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -247,73 +247,6 @@ VID_InitGamma (const byte *pal) } } -void -VID_InitBuffers (void) -{ - int buffersize, zbuffersize, cachesize = 1; - - // No console scaling in the sw renderer - viddef.conview->xlen = viddef.width; - viddef.conview->ylen = viddef.height; - Con_CheckResize (); - - // Calculate the sizes we want first - buffersize = viddef.rowbytes * viddef.height; - zbuffersize = viddef.width * viddef.height * sizeof (*viddef.zbuffer); - if (vi->surf_cache_size) { - cachesize = vi->surf_cache_size (vi->data, - viddef.width, viddef.height); - } - - // Free the old z-buffer - if (viddef.zbuffer) { - free (viddef.zbuffer); - viddef.zbuffer = NULL; - } - // Free the old surface cache - if (viddef.surfcache) { - if (vi->flush_caches) { - vi->flush_caches (vi->data); - } - free (viddef.surfcache); - viddef.surfcache = NULL; - } - if (vi->init_buffers) { - vi->init_buffers (vi->data); - } else { - // Free the old screen buffer - if (viddef.buffer) { - free (viddef.buffer); - viddef.buffer = NULL; - } - // Allocate the new screen buffer - viddef.buffer = calloc (buffersize, 1); - if (!viddef.buffer) { - Sys_Error ("Not enough memory for video mode"); - } - } - // Allocate the new z-buffer - viddef.zbuffer = calloc (zbuffersize, 1); - if (!viddef.zbuffer) { - free (viddef.buffer); - viddef.buffer = NULL; - Sys_Error ("Not enough memory for video mode"); - } - // Allocate the new surface cache; free the z-buffer if we fail - viddef.surfcache = calloc (cachesize, 1); - if (!viddef.surfcache) { - free (viddef.buffer); - free (viddef.zbuffer); - viddef.buffer = NULL; - viddef.zbuffer = NULL; - Sys_Error ("Not enough memory for video mode"); - } - - if (vi->init_caches) { - vi->init_caches (vi->data, viddef.surfcache, cachesize); - } -} - void VID_ClearMemory (void) { diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 12dba8e49..cba768b8a 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -55,11 +55,14 @@ #include #include +#include "QF/console.h" #include "QF/cvar.h" #include "QF/qargs.h" #include "QF/sys.h" #include "QF/vid.h" +#include "QF/ui/view.h" + #include "context_x11.h" #include "r_internal.h" #include "vid_internal.h" @@ -633,6 +636,12 @@ x11_create_context (sw_ctx_t *ctx) x_shmeventtype = XShmGetEventBase (x_disp) + ShmCompletion; } + // FIXME this really shouldn't be here (ideally, scale console in sw) + // No console scaling in the sw renderer + viddef.conview->xlen = viddef.width; + viddef.conview->ylen = viddef.height; + Con_CheckResize (); + viddef.vid_internal->init_buffers = x11_init_buffers; // XSynchronize (x_disp, False); // X11_AddEvent (x_shmeventtype, event_shm); From 4c90c3c4bb2a01bf50dd719f1e96743c2d22cfe9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Mar 2022 14:36:57 +0900 Subject: [PATCH 2560/3664] [sw] Remove pixbytes from sw_ctx_t It's no longer needed as the sw renderer is 8-bit only. --- include/vid_sw.h | 1 - libs/video/targets/vid_win_sw.c | 1 - libs/video/targets/vid_x11_sw.c | 59 +++++++++++++++++++-------------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/include/vid_sw.h b/include/vid_sw.h index 92fb00d55..a43a1a9a2 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -3,7 +3,6 @@ struct vrect_s; typedef struct sw_ctx_s { - int pixbytes; void (*choose_visual) (struct sw_ctx_s *ctx); void (*create_context) (struct sw_ctx_s *ctx); void (*set_palette) (struct sw_ctx_s *ctx, const byte *palette); diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index 2303742e2..9ded596fb 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -469,7 +469,6 @@ sw_ctx_t * Win_SW_Context (void) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); - ctx->pixbytes = 1; ctx->set_palette = win_set_palette; ctx->choose_visual = win_choose_visual; ctx->create_context = win_create_context; diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index cba768b8a..ed0719720 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -307,7 +307,7 @@ x11_put_image (vrect_t *rects) Flush the given rectangles from the view buffer to the screen. */ static void -x11_sw8_update (sw_ctx_t *ctx, vrect_t *rects) +x11_sw8_8_update (sw_ctx_t *ctx, vrect_t *rects) { while (rects) { switch (x_visinfo->depth) { @@ -327,6 +327,32 @@ x11_sw8_update (sw_ctx_t *ctx, vrect_t *rects) r_data->scr_fullupdate = 0; } +static void +x11_sw8_16_update (sw_ctx_t *ctx, vrect_t *rects) +{ + while (rects) { + st2_fixup (x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + x11_put_image (rects); + rects = rects->next; + } + XSync (x_disp, False); + r_data->scr_fullupdate = 0; +} + +static void +x11_sw8_24_update (sw_ctx_t *ctx, vrect_t *rects) +{ + while (rects) { + st3_fixup (x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + x11_put_image (rects); + rects = rects->next; + } + XSync (x_disp, False); + r_data->scr_fullupdate = 0; +} +#if 0 static void x11_sw16_16_update (sw_ctx_t *ctx, vrect_t *rects) { @@ -411,7 +437,7 @@ x11_sw32_update (sw_ctx_t *ctx, vrect_t *rects) XSync (x_disp, False); r_data->scr_fullupdate = 0; } - +#endif static void x11_choose_visual (sw_ctx_t *ctx) { @@ -441,31 +467,16 @@ x11_choose_visual (sw_ctx_t *ctx) x_cmap = XCreateColormap (x_disp, x_win, x_vis, AllocAll); x_vis = x_visinfo->visual; - ctx->update = x11_sw8_update; + ctx->update = x11_sw8_8_update; switch (x_visinfo->depth) { case 8: - ctx->pixbytes = 1; - ctx->update = x11_sw8_update; + ctx->update = x11_sw8_8_update; break; case 16: - if (ctx->pixbytes > 2) { - ctx->pixbytes = 2; - } - if (ctx->pixbytes == 2) { - ctx->update = x11_sw16_16_update; - } + ctx->update = x11_sw8_16_update; break; case 24: - switch (ctx->pixbytes) { - case 1: - break; - case 2: - ctx->update = x11_sw16_32_update; - break; - case 4: - ctx->update = x11_sw32_update; - break; - } + ctx->update = x11_sw8_24_update; break; } @@ -584,7 +595,6 @@ ResetSharedFrameBuffers (void) static void x11_init_buffers (void *data) { - sw_ctx_t *ctx = data; if (doShm) ResetSharedFrameBuffers (); else @@ -592,7 +602,7 @@ x11_init_buffers (void *data) current_framebuffer = 0; - viddef.rowbytes = ctx->pixbytes * viddef.width; + viddef.rowbytes = viddef.width; if (x_visinfo->depth != 8) { if (viddef.buffer) free (viddef.buffer); @@ -651,11 +661,10 @@ sw_ctx_t * X11_SW_Context (void) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); - ctx->pixbytes = 1; ctx->set_palette = x11_set_palette; ctx->choose_visual = x11_choose_visual; ctx->create_context = x11_create_context; - ctx->update = x11_sw8_update; + ctx->update = x11_sw8_8_update; return ctx; } From 296c04c8eb7d254d2319575835c5a86160467585 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Mar 2022 19:21:54 +0900 Subject: [PATCH 2561/3664] [console] Ensure console lines doesn't exceed view This fixes a segfault in 32-bit nq-win caused by negative frame times (due to something going weird with Sys_DoubleTime). --- libs/console/client.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/console/client.c b/libs/console/client.c index c1a9f60ac..7aa375d0d 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -673,6 +673,9 @@ setup_console (void) } else { con_data.lines = lines; } + if (con_data.lines > r_data->vid->conview->ylen) { + con_data.lines = r_data->vid->conview->ylen; + } if (con_data.lines >= r_data->vid->conview->ylen - r_data->lineadj) r_data->scr_copyeverything = 1; } From 939a73fb52a6787d8152d193f8fa9e73bc6489a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Mar 2022 19:23:49 +0900 Subject: [PATCH 2562/3664] [sys] Override strdup for 32-bit windows This fixes some nasty segfaults when calling free due to different allocators being used. --- libs/util/sys.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libs/util/sys.c b/libs/util/sys.c index 43b3b1e05..8aefe89f5 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -677,6 +677,15 @@ realloc (void *mem, size_t size) { return _aligned_realloc (mem, size, 16); } + +char *__cdecl +strdup(const char *src) +{ + size_t len = strlen (src); + char *dup = malloc (len + 1); + strcpy (dup, src); + return dup; +} #endif VISIBLE size_t From 2e1ddfed0d3358f30b3e8378f27112d6edf600d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Mar 2022 19:24:43 +0900 Subject: [PATCH 2563/3664] [sw] Fix some missed symbol renames Missed due to assembly language :P --- libs/video/renderer/sw/sw_raliasa.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/sw/sw_raliasa.S b/libs/video/renderer/sw/sw_raliasa.S index 31df86303..8840ad4f8 100644 --- a/libs/video/renderer/sw/sw_raliasa.S +++ b/libs/video/renderer/sw/sw_raliasa.S @@ -124,13 +124,13 @@ Lloop: fxch %st(3) // v[0] | v[2] | v[1] | zi -// lightcos = DotProduct (plightnormal, r_plightvec); +// lightcos = DotProduct (plightnormal, r_lightvec); flds C(r_avertexnormals)(,%eax,4) - fmuls C(r_plightvec) + fmuls C(r_lightvec) flds C(r_avertexnormals)+4(,%eax,4) - fmuls C(r_plightvec)+4 + fmuls C(r_lightvec)+4 flds C(r_avertexnormals)+8(,%eax,4) - fmuls C(r_plightvec)+8 + fmuls C(r_lightvec)+8 fxch %st(1) faddp %st(0),%st(2) fld %st(2) // v[0] | laccum | laccum2 | v[0] | v[2] | From 376a173e669df1c38a6bc92cb73afae75a7dfdbc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Mar 2022 21:59:07 +0900 Subject: [PATCH 2564/3664] [sw] Set FP precision in R_DrawEntitiesOnList This used to be handled by R_RenderView (encompassing all of the rendering) before the scene rendering was moved out to r_screen. This fixes the stuck time in 32-bit nq-win. --- libs/video/renderer/sw/sw_ralias.c | 3 +-- libs/video/renderer/sw/sw_rmain.c | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 81e59720a..0c9a3dee2 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -645,8 +645,7 @@ R_AliasDrawModel (entity_t *ent, alight_t *lighting) else ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - if (ent->visibility.trivial_accept - && pmdl->ident != HEADER_MDL16) { + if (ent->visibility.trivial_accept && pmdl->ident != HEADER_MDL16) { R_AliasPrepareUnclippedPoints (); } else { R_AliasPreparePoints (); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 263a7645d..99778f9bb 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -412,6 +412,7 @@ R_DrawEntitiesOnList (entqueue_t *queue) if (!r_drawentities->int_val) return; + R_LowFPPrecision (); #define RE_LOOP(type_name) \ do { \ for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ @@ -426,6 +427,8 @@ R_DrawEntitiesOnList (entqueue_t *queue) RE_LOOP (alias); RE_LOOP (iqm); RE_LOOP (sprite); + + R_HighFPPrecision (); } static void From 8ee776e8fbf719448a0a1e0474e67223b470f306 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Mar 2022 23:11:09 +0900 Subject: [PATCH 2565/3664] [sw] Rename d_pzbuffer to d_zbuffer --- include/d_local.h | 2 +- include/quakeasm.h | 3 +-- libs/video/renderer/sw/d_draw.S | 4 ++-- libs/video/renderer/sw/d_modech.c | 2 +- libs/video/renderer/sw/d_part.c | 2 +- libs/video/renderer/sw/d_parta.S | 2 +- libs/video/renderer/sw/d_polyse.c | 8 ++++---- libs/video/renderer/sw/d_scan.c | 2 +- libs/video/renderer/sw/d_spr8.S | 2 +- libs/video/renderer/sw/d_sprite.c | 2 +- libs/video/renderer/sw/d_surf.c | 2 +- libs/video/renderer/sw/d_vars.c | 2 +- libs/video/renderer/sw/d_varsa.S | 4 ++-- libs/video/renderer/sw/d_zpoint.c | 2 +- 14 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/d_local.h b/include/d_local.h index 4dac4ee58..042ce2919 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -104,7 +104,7 @@ void D_PolysetAff8Start (void); void D_PolysetAff8End (void); #endif -extern short *d_pzbuffer; +extern short *d_zbuffer; extern int d_zrowbytes, d_zwidth; extern int *d_pscantable; diff --git a/include/quakeasm.h b/include/quakeasm.h index 2ee8bb720..e8ca5183d 100644 --- a/include/quakeasm.h +++ b/include/quakeasm.h @@ -32,7 +32,7 @@ #define TRANSPARENT_COLOR 255 .extern C(d_zistepu) - .extern C(d_pzbuffer) + .extern C(d_zbuffer) .extern C(d_zistepv) .extern C(d_zrowbytes) .extern C(d_ziorigin) @@ -58,7 +58,6 @@ .extern C(cacheblock) .extern C(d_viewbuffer) .extern C(cachewidth) - .extern C(d_pzbuffer) .extern C(d_zrowbytes) .extern C(d_zwidth) .extern C(d_scantable) diff --git a/libs/video/renderer/sw/d_draw.S b/libs/video/renderer/sw/d_draw.S index e4642025b..012b9a281 100644 --- a/libs/video/renderer/sw/d_draw.S +++ b/libs/video/renderer/sw/d_draw.S @@ -821,7 +821,7 @@ LFSpanLoop: fildl espan_t_v(%esi) fildl espan_t_u(%esi) movl espan_t_v(%esi),%ecx - movl C(d_pzbuffer),%edi + movl C(d_zbuffer),%edi fmuls C(d_zistepu) fxch %st(1) fmuls C(d_zistepv) @@ -936,7 +936,7 @@ LFNegSpanLoop: fildl espan_t_v(%esi) fildl espan_t_u(%esi) movl espan_t_v(%esi),%ecx - movl C(d_pzbuffer),%edi + movl C(d_zbuffer),%edi fmuls C(d_zistepu) fxch %st(1) fmuls C(d_zistepv) diff --git a/libs/video/renderer/sw/d_modech.c b/libs/video/renderer/sw/d_modech.c index 40956fc53..3709cc179 100644 --- a/libs/video/renderer/sw/d_modech.c +++ b/libs/video/renderer/sw/d_modech.c @@ -104,7 +104,7 @@ D_ViewChanged (void) for (i = 0; i < vid.height; i++) { d_scantable[i] = i * rowpixels; - zspantable[i] = d_pzbuffer + i * d_zwidth; + zspantable[i] = d_zbuffer + i * d_zwidth; } } diff --git a/libs/video/renderer/sw/d_part.c b/libs/video/renderer/sw/d_part.c index 82371ce28..65fa5ddac 100644 --- a/libs/video/renderer/sw/d_part.c +++ b/libs/video/renderer/sw/d_part.c @@ -67,7 +67,7 @@ D_DrawParticle (particle_t *pparticle) return; } - pz = d_pzbuffer + (d_zwidth * v) + u; + pz = d_zbuffer + (d_zwidth * v) + u; pdest = d_viewbuffer + d_scantable[v] + u; izi = (int) (zi * 0x8000); diff --git a/libs/video/renderer/sw/d_parta.S b/libs/video/renderer/sw/d_parta.S index b35597dcd..41debaa27 100644 --- a/libs/video/renderer/sw/d_parta.S +++ b/libs/video/renderer/sw/d_parta.S @@ -189,7 +189,7 @@ C(D_DrawParticle): imull C(d_zrowbytes),%edx // point to the z pixel leal (%edx,%eax,2),%edx - movl C(d_pzbuffer),%eax + movl C(d_zbuffer),%eax fistpl C(izi) diff --git a/libs/video/renderer/sw/d_polyse.c b/libs/video/renderer/sw/d_polyse.c index 5e7f9fbc9..e0364b62f 100644 --- a/libs/video/renderer/sw/d_polyse.c +++ b/libs/video/renderer/sw/d_polyse.c @@ -702,7 +702,7 @@ D_RasterizeAliasPolySmooth (void) d_pdestbasestep = screenwidth + ubasestep; d_pdestextrastep = d_pdestbasestep + 1; d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0]; - d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + d_pz = d_zbuffer + ystart * d_zwidth + plefttop[0]; // TODO: can reuse partial expressions here @@ -775,7 +775,7 @@ D_RasterizeAliasPolySmooth (void) d_pzbasestep = d_zwidth + ubasestep; d_pzextrastep = d_pzbasestep + 1; #endif - d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + d_pz = d_zbuffer + ystart * d_zwidth + plefttop[0]; if (ubasestep < 0) working_lstepx = r_lstepx - 1; @@ -881,10 +881,10 @@ D_PolysetRecursiveDrawLine (int *lp1, int *lp2) // draw the point ofs = d_scantable[new[1]] + new[0]; - if (new[5] > d_pzbuffer[ofs]) { + if (new[5] > d_zbuffer[ofs]) { int pix; - d_pzbuffer[ofs] = new[5]; + d_zbuffer[ofs] = new[5]; pix = skintable[new[3] >> 16][new[2] >> 16]; // pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)]; d_viewbuffer[ofs] = pix; diff --git a/libs/video/renderer/sw/d_scan.c b/libs/video/renderer/sw/d_scan.c index c411e8b1e..9b5287fd2 100644 --- a/libs/video/renderer/sw/d_scan.c +++ b/libs/video/renderer/sw/d_scan.c @@ -389,7 +389,7 @@ D_DrawZSpans (espan_t *pspan) izistep = (int) (d_zistepu * 0x8000 * 0x10000); do { - pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + pdest = d_zbuffer + (d_zwidth * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_spr8.S b/libs/video/renderer/sw/d_spr8.S index fcda6abd6..b2174b384 100644 --- a/libs/video/renderer/sw/d_spr8.S +++ b/libs/video/renderer/sw/d_spr8.S @@ -211,7 +211,7 @@ LSpanLoop: movl sspan_t_u(%ebx),%ebp imull C(d_zrowbytes) shll $1,%ebp // a word per pixel - addl C(d_pzbuffer),%eax + addl C(d_zbuffer),%eax addl %ebp,%eax movl %eax,C(pz) diff --git a/libs/video/renderer/sw/d_sprite.c b/libs/video/renderer/sw/d_sprite.c index 04f994f4c..cba4fac8a 100644 --- a/libs/video/renderer/sw/d_sprite.c +++ b/libs/video/renderer/sw/d_sprite.c @@ -70,7 +70,7 @@ D_SpriteDrawSpans (sspan_t *pspan) do { pdest = (byte *) d_viewbuffer + (screenwidth * pspan->v) + pspan->u; - pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + pz = d_zbuffer + (d_zwidth * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index eb45010db..59c28c4cb 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -108,7 +108,7 @@ D_InitCaches (void *buffer, int size) sc_base->owner = NULL; sc_base->size = sc_size; - d_pzbuffer = vid.zbuffer; + d_zbuffer = vid.zbuffer; D_ClearCacheGuard (); } diff --git a/libs/video/renderer/sw/d_vars.c b/libs/video/renderer/sw/d_vars.c index 96a0b0f4b..88288f8bb 100644 --- a/libs/video/renderer/sw/d_vars.c +++ b/libs/video/renderer/sw/d_vars.c @@ -53,7 +53,7 @@ fixed16_t sadjust, tadjust, bbextents, bbextentt; byte *cacheblock; int cachewidth; byte *d_viewbuffer; -short *d_pzbuffer; +short *d_zbuffer; int d_zrowbytes; int d_zwidth; diff --git a/libs/video/renderer/sw/d_varsa.S b/libs/video/renderer/sw/d_varsa.S index bb6eb6f42..642e7ab47 100644 --- a/libs/video/renderer/sw/d_varsa.S +++ b/libs/video/renderer/sw/d_varsa.S @@ -81,13 +81,13 @@ C(bbextentt): .long 0 .globl C(cacheblock) .globl C(d_viewbuffer) .globl C(cachewidth) -.globl C(d_pzbuffer) +.globl C(d_zbuffer) .globl C(d_zrowbytes) .globl C(d_zwidth) C(cacheblock): .long 0 C(cachewidth): .long 0 C(d_viewbuffer): .long 0 -C(d_pzbuffer): .long 0 +C(d_zbuffer): .long 0 C(d_zrowbytes): .long 0 C(d_zwidth): .long 0 diff --git a/libs/video/renderer/sw/d_zpoint.c b/libs/video/renderer/sw/d_zpoint.c index b7ed9e2bf..05f57ad10 100644 --- a/libs/video/renderer/sw/d_zpoint.c +++ b/libs/video/renderer/sw/d_zpoint.c @@ -39,7 +39,7 @@ D_DrawZPoint (void) short *pz; int izi; - pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u; + pz = d_zbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u; pdest = d_viewbuffer + d_scantable[r_zpointdesc.v] + r_zpointdesc.u; izi = (int) (r_zpointdesc.zi * 0x8000); From d54f146089a23cfbf643974d9345c9dedc60614b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Mar 2022 23:13:09 +0900 Subject: [PATCH 2566/3664] [sw] Remove a pile of duplicate asm externs I imagine the file was generated via grep and sed. --- include/quakeasm.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/include/quakeasm.h b/include/quakeasm.h index e8ca5183d..16567c31d 100644 --- a/include/quakeasm.h +++ b/include/quakeasm.h @@ -58,7 +58,6 @@ .extern C(cacheblock) .extern C(d_viewbuffer) .extern C(cachewidth) - .extern C(d_zrowbytes) .extern C(d_zwidth) .extern C(d_scantable) .extern C(r_lightptr) @@ -70,12 +69,8 @@ .extern C(lightrightstep) .extern C(lightdeltastep) .extern C(lightdelta) - .extern C(lightright) - .extern C(lightdelta) .extern C(sourcetstep) .extern C(surfrowbytes) - .extern C(lightrightstep) - .extern C(lightdeltastep) .extern C(r_sourcemax) .extern C(r_stepback) .extern C(colormap) @@ -137,7 +132,7 @@ .extern C(r_anumverts) .extern C(aliastransform) .extern C(r_avertexnormals) - .extern C(r_plightvec) + .extern C(r_lightvec) .extern C(r_ambientlight) .extern C(r_shadelight) .extern C(aliasxcenter) @@ -146,7 +141,6 @@ .extern C(r_affinetridesc) .extern C(acolormap) .extern C(d_pcolormap) - .extern C(r_affinetridesc) .extern C(d_sfrac) .extern C(d_ptex) .extern C(d_pedgespanpackage) @@ -172,16 +166,12 @@ .extern C(erroradjustdown) .extern C(d_countextrastep) .extern C(ubasestep) - .extern C(a_ststepxwhole) - .extern C(a_tstepxfrac) .extern C(r_lstepx) .extern C(a_spans) - .extern C(erroradjustdown) .extern C(d_pdestextrastep) .extern C(d_pzextrastep) .extern C(d_sfracextrastep) .extern C(d_ptexextrastep) - .extern C(d_countextrastep) .extern C(d_tfracextrastep) .extern C(d_lightextrastep) .extern C(d_ziextrastep) @@ -189,11 +179,9 @@ .extern C(d_pzbasestep) .extern C(d_sfracbasestep) .extern C(d_ptexbasestep) - .extern C(ubasestep) .extern C(d_tfracbasestep) .extern C(d_lightbasestep) .extern C(d_zibasestep) - .extern C(zspantable) .extern C(r_lstepy) .extern C(r_sstepy) .extern C(r_tstepy) From 4a917449b76529877353a1fe89d5819f8f89dc2f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Mar 2022 23:15:14 +0900 Subject: [PATCH 2567/3664] [sw] Clean up a bunch of unnecessary casts They won't affect performance, but they cluttered the code making it harder to read. --- libs/video/renderer/sw/d_edge.c | 2 +- libs/video/renderer/sw/d_polyse.c | 2 +- libs/video/renderer/sw/d_scan.c | 8 +++----- libs/video/renderer/sw/d_sky.c | 5 ++--- libs/video/renderer/sw/d_sprite.c | 2 +- 5 files changed, 8 insertions(+), 11 deletions(-) diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index ec2c186e6..0f4c65f13 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -81,7 +81,7 @@ D_DrawSolidSurface (surf_t *surf, int color) pix = (color << 24) | (color << 16) | (color << 8) | color; for (span = surf->spans; span; span = span->pnext) { - pdest = (byte *) d_viewbuffer + screenwidth * span->v; + pdest = d_viewbuffer + screenwidth * span->v; u = span->u; u2 = span->u + span->count - 1; ((byte *) pdest)[u] = pix; diff --git a/libs/video/renderer/sw/d_polyse.c b/libs/video/renderer/sw/d_polyse.c index e0364b62f..723b9f135 100644 --- a/libs/video/renderer/sw/d_polyse.c +++ b/libs/video/renderer/sw/d_polyse.c @@ -767,7 +767,7 @@ D_RasterizeAliasPolySmooth (void) d_pdestbasestep = screenwidth + ubasestep; d_pdestextrastep = d_pdestbasestep + 1; - d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0]; + d_pdest = d_viewbuffer + ystart * screenwidth + plefttop[0]; #ifdef USE_INTEL_ASM d_pzbasestep = (d_zwidth + ubasestep) << 1; d_pzextrastep = d_pzbasestep + 2; diff --git a/libs/video/renderer/sw/d_scan.c b/libs/video/renderer/sw/d_scan.c index 9b5287fd2..74f8743db 100644 --- a/libs/video/renderer/sw/d_scan.c +++ b/libs/video/renderer/sw/d_scan.c @@ -141,8 +141,7 @@ Turbulent (espan_t *pspan) zi16stepu = d_zistepu * 16; do { - r_turb_pdest = (byte *) d_viewbuffer + (screenwidth * pspan->v) + - pspan->u; + r_turb_pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; count = pspan->count; @@ -251,7 +250,7 @@ void D_DrawSpans8 (espan_t *pspan) { int count, spancount; - unsigned char *pbase, *pdest; + byte *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz8stepu, tdivz8stepu, zi8stepu; @@ -266,8 +265,7 @@ D_DrawSpans8 (espan_t *pspan) zi8stepu = d_zistepu * 8; do { - pdest = (unsigned char *) ((byte *) d_viewbuffer + - (screenwidth * pspan->v) + pspan->u); + pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index 289564b27..bfc3a2fed 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -68,7 +68,7 @@ void D_DrawSkyScans (espan_t *pspan) { int count, spancount, u, v; - unsigned char *pdest; + byte *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; int spancountminus1; @@ -78,8 +78,7 @@ D_DrawSkyScans (espan_t *pspan) tnext = 0; // ditto do { - pdest = (unsigned char *) ((byte *) d_viewbuffer + - (screenwidth * pspan->v) + pspan->u); + pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_sprite.c b/libs/video/renderer/sw/d_sprite.c index cba4fac8a..884e2dbd7 100644 --- a/libs/video/renderer/sw/d_sprite.c +++ b/libs/video/renderer/sw/d_sprite.c @@ -69,7 +69,7 @@ D_SpriteDrawSpans (sspan_t *pspan) izistep = (int) (d_zistepu * 0x8000 * 0x10000); do { - pdest = (byte *) d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; pz = d_zbuffer + (d_zwidth * pspan->v) + pspan->u; count = pspan->count; From 0c437492b424eb383235b06219eae2ca4852beb1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Mar 2022 12:22:27 +0900 Subject: [PATCH 2568/3664] [renderer] Move to using dynamic frame buffers For now, OpenGL and Vulkan renderers are broken as I focused on getting the software renderer working (which was quite tricky to get right). This fixes a couple of issues: the segfault when warping the screen (due to the scene rendering move invalidating the warp buffer), and warp always having 320x200 resolution. There's still the problem of the effect being too subtle at high resolution, but that's just a matter of updating the tables and tweaking the code in D_WarpScreen. Another issue is the Draw functions should probably write directly to the main frame buffer or even one passed in as a parameter. This would remove the need for binding the main buffer at the beginning and end of the frame. --- include/QF/plugin/vid_render.h | 3 + include/QF/render.h | 10 +++ include/QF/scene/camera.h | 1 + include/QF/vid.h | 4 - include/d_iface.h | 2 - include/d_local.h | 9 +- include/quakeasm.h | 2 +- include/r_local.h | 2 - include/r_shared.h | 1 - include/vid_gl.h | 6 ++ include/vid_sw.h | 9 ++ libs/video/renderer/r_main.c | 1 + libs/video/renderer/r_screen.c | 11 +++ libs/video/renderer/sw/d_draw.S | 2 +- libs/video/renderer/sw/d_edge.c | 2 +- libs/video/renderer/sw/d_init.c | 38 ++------- libs/video/renderer/sw/d_modech.c | 19 ----- libs/video/renderer/sw/d_part.c | 10 +-- libs/video/renderer/sw/d_parta.S | 10 +-- libs/video/renderer/sw/d_polyse.c | 8 +- libs/video/renderer/sw/d_scan.c | 16 ++-- libs/video/renderer/sw/d_sky.c | 2 +- libs/video/renderer/sw/d_spr8.S | 2 +- libs/video/renderer/sw/d_sprite.c | 2 +- libs/video/renderer/sw/d_surf.c | 2 - libs/video/renderer/sw/d_vars.c | 2 + libs/video/renderer/sw/d_varsa.S | 4 + libs/video/renderer/sw/draw.c | 35 ++++---- libs/video/renderer/sw/screen.c | 19 +++-- libs/video/renderer/sw/sw_graph.c | 6 +- libs/video/renderer/sw/sw_ralias.c | 1 + libs/video/renderer/sw/sw_rmain.c | 37 ++++----- libs/video/renderer/sw/sw_rmisc.c | 59 ------------- libs/video/renderer/vid_render_gl.c | 15 ++++ libs/video/renderer/vid_render_glsl.c | 15 ++++ libs/video/renderer/vid_render_sw.c | 77 +++++++++++++++++ libs/video/renderer/vid_render_vulkan.c | 15 ++++ libs/video/targets/vid_win.c | 6 ++ libs/video/targets/vid_win_sw.c | 32 ++++--- libs/video/targets/vid_x11_sw.c | 106 ++++++++++++++++-------- 40 files changed, 362 insertions(+), 241 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index a49a3bd36..b425cce54 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -115,6 +115,9 @@ typedef struct vid_render_funcs_s { void (*set_2d) (int scaled); void (*end_frame) (void); + struct framebuffer_s *(*create_frame_buffer) (int width, int height); + void (*bind_framebuffer) (struct framebuffer_s *framebuffer); + vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/QF/render.h b/include/QF/render.h index bffec3a85..ed1d66b94 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -191,6 +191,16 @@ typedef union refframe_s { }; } refframe_t; +/** Generic frame buffer object. + * + * For attaching scene cameras to render targets. + */ +typedef struct framebuffer_s { + unsigned width; + unsigned height; + void *buffer; ///< renderer-specific frame buffer data +} framebuffer_t; + // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { vrect_t vrect; // subwindow in video for refresh diff --git a/include/QF/scene/camera.h b/include/QF/scene/camera.h index a7da8412b..5584f397c 100644 --- a/include/QF/scene/camera.h +++ b/include/QF/scene/camera.h @@ -41,6 +41,7 @@ typedef struct camera_s { struct scene_s *scene; ///< owning scene + struct framebuffer_s *framebuffer; int32_t id; ///< id in scene int32_t transform; float field_of_view; diff --git a/include/QF/vid.h b/include/QF/vid.h index c5fd95751..c8ce3b226 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -37,9 +37,6 @@ typedef struct { qboolean initialized; qboolean is8bit; - void *buffer; // invisible buffer - short *zbuffer; - void *surfcache; byte *gammatable; // 256 const byte *basepal; // 256 * 3 byte *palette; // 256 * 3 @@ -48,7 +45,6 @@ typedef struct { unsigned short *colormap16; // 256 * VID_GRADES size unsigned int *colormap32; // 256 * VID_GRADES size int fullbright; // index of first fullbright color - int rowbytes; // may be > width if displayed in a window unsigned width; unsigned height; int numpages; diff --git a/include/d_iface.h b/include/d_iface.h index 4e78c43e8..7f12523ac 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -226,6 +226,4 @@ extern float r_skytime; extern int c_surf; -extern byte *r_warpbuffer; - #endif // _D_IFACE_H diff --git a/include/d_local.h b/include/d_local.h index 042ce2919..51a2cd220 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -104,8 +104,13 @@ void D_PolysetAff8Start (void); void D_PolysetAff8End (void); #endif +extern byte *d_viewbuffer; +extern int d_rowbytes; +extern unsigned d_height; + extern short *d_zbuffer; -extern int d_zrowbytes, d_zwidth; +extern int d_zrowbytes; +extern unsigned d_zwidth; extern int *d_pscantable; extern int d_scantable[]; @@ -114,8 +119,6 @@ extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; -extern byte *d_viewbuffer; - extern short *zspantable[]; extern int d_minmip; diff --git a/include/quakeasm.h b/include/quakeasm.h index 16567c31d..a3657fdc0 100644 --- a/include/quakeasm.h +++ b/include/quakeasm.h @@ -93,7 +93,7 @@ .extern C(d_pix_min) .extern C(d_pix_max) .extern C(d_y_aspect_shift) - .extern C(screenwidth) + .extern C(d_rowbytes) .extern C(r_leftclipped) .extern C(r_leftenter) .extern C(r_rightclipped) diff --git a/include/r_local.h b/include/r_local.h index 0c7a7129e..0b15583ae 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -270,8 +270,6 @@ extern edge_t *r_edges, *edge_p, *edge_max; extern edge_t *newedges[MAXHEIGHT]; extern edge_t *removeedges[MAXHEIGHT]; -extern int screenwidth; - extern int r_bmodelactive; extern vrect_t *pconupdate; diff --git a/include/r_shared.h b/include/r_shared.h index 843978033..2251a7b1d 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -54,7 +54,6 @@ extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1); extern int cachewidth; extern byte *cacheblock; -extern int screenwidth; extern int r_init; extern float pixelAspect; diff --git a/include/vid_gl.h b/include/vid_gl.h index 618e89d44..8b82ae069 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -19,6 +19,12 @@ typedef struct gl_ctx_s { int alias_polys; } gl_ctx_t; +typedef struct gl_framebuffer_s { + unsigned handle; + unsigned color; + unsigned depth; +} gl_framebuffer_t; + extern gl_ctx_t *gl_ctx; extern gl_ctx_t *glsl_ctx; diff --git a/include/vid_sw.h b/include/vid_sw.h index a43a1a9a2..ed2f21a1a 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -1,14 +1,23 @@ #ifndef __vid_sw_h #define __vid_sw_h +#include "QF/qtypes.h" + struct vrect_s; typedef struct sw_ctx_s { void (*choose_visual) (struct sw_ctx_s *ctx); void (*create_context) (struct sw_ctx_s *ctx); void (*set_palette) (struct sw_ctx_s *ctx, const byte *palette); void (*update) (struct sw_ctx_s *ctx, struct vrect_s *rects); + struct framebuffer_s *framebuffer; } sw_ctx_t; +typedef struct sw_framebuffer_s { + byte *color; + short *depth; + int rowbytes; +} sw_framebuffer_t; + extern sw_ctx_t *sw_ctx; struct tex_s *sw_SCR_CaptureBGR (void); diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index e9184c80f..846a57dad 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -45,6 +45,7 @@ #include "r_internal.h" +qboolean r_dowarp, r_dowarpold; qboolean r_inhibit_viewmodel; qboolean r_force_fullscreen; qboolean r_paused; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 77fdeb411..7089b0cc9 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -66,6 +66,7 @@ static qboolean scr_initialized;// ready to draw static qpic_t *scr_ram; static qpic_t *scr_turtle; +static framebuffer_t *warp_buffer; static void set_vrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) { @@ -197,11 +198,21 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) if (refdef->worldmodel) { vec4f_t position = refdef->frame.position; refdef->viewleaf = Mod_PointInLeaf (&position[0], refdef->worldmodel); + r_dowarpold = r_dowarp; + if (r_waterwarp->int_val) { + r_dowarp = refdef->viewleaf->contents <= CONTENTS_WATER; + } + if (r_dowarp && !warp_buffer) { + warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, r_data->vid->height); + } } R_MarkLeaves (); R_PushDlights (vec3_origin); r_funcs->begin_frame (); + if (r_dowarp) { + r_funcs->bind_framebuffer (warp_buffer); + } r_funcs->render_view (); r_funcs->draw_entities (r_ent_queue); r_funcs->draw_particles (&r_psystem); diff --git a/libs/video/renderer/sw/d_draw.S b/libs/video/renderer/sw/d_draw.S index 012b9a281..cf97cacaa 100644 --- a/libs/video/renderer/sw/d_draw.S +++ b/libs/video/renderer/sw/d_draw.S @@ -194,7 +194,7 @@ LSpanLoop: movl C(tadjust),%edx movl C(sadjust),%esi - movl C(d_scantable)(,%eax,4),%edi // v * screenwidth + movl C(d_scantable)(,%eax,4),%edi // v * d_rowbytes addl %ecx,%edi movl espan_t_u(%ebx),%ecx addl %ecx,%edi // pdest = &pdestspan[scans->u]; diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 0f4c65f13..60590c4d3 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -81,7 +81,7 @@ D_DrawSolidSurface (surf_t *surf, int color) pix = (color << 24) | (color << 16) | (color << 8) | color; for (span = surf->spans; span; span = span->pnext) { - pdest = d_viewbuffer + screenwidth * span->v; + pdest = d_viewbuffer + d_rowbytes * span->v; u = span->u; u2 = span->u + span->count - 1; ((byte *) pdest)[u] = pix; diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index 349733f76..ec0353817 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -45,6 +45,7 @@ float d_scalemip[NUM_MIPS - 1]; static float basemip[NUM_MIPS - 1] = { 1.0, 0.5 * 0.8, 0.25 * 0.8 }; +static byte *surfcache; void (*d_drawspans) (espan_t *pspan); @@ -60,29 +61,16 @@ D_Init (void) vid->vid_internal->flush_caches = D_FlushCaches; - int buffersize = vid->rowbytes * vid->height; - int zbuffersize = vid->width * vid->height * sizeof (*vid->zbuffer); int cachesize = D_SurfaceCacheForRes (vid->width, vid->height); - if (vid->zbuffer) { - free (vid->zbuffer); - vid->zbuffer = 0; + if (surfcache) { + D_FlushCaches (vid->vid_internal->data); + free (surfcache); + surfcache = 0; } - if (vid->surfcache) { - D_FlushCaches (0); - free (vid->surfcache); - vid->surfcache = 0; - } - if (vid->vid_internal->init_buffers) { - vid->vid_internal->init_buffers (vid->vid_internal->data); - } else { - free (vid->buffer); - vid->buffer = calloc (buffersize, 1); - } - vid->zbuffer = calloc (zbuffersize, 1); - vid->surfcache = calloc (cachesize, 1); - - D_InitCaches (vid->surfcache, cachesize); + surfcache = calloc (cachesize, 1); + vid->vid_internal->init_buffers (vid->vid_internal->data); + D_InitCaches (surfcache, cachesize); } void @@ -96,16 +84,6 @@ D_SetupFrame (void) { int i; - if (r_dowarp) - d_viewbuffer = r_warpbuffer; - else - d_viewbuffer = vid.buffer; - - if (r_dowarp) - screenwidth = WARP_WIDTH; - else - screenwidth = vid.rowbytes; - d_roverwrapped = false; d_initial_rover = sc_rover; diff --git a/libs/video/renderer/sw/d_modech.c b/libs/video/renderer/sw/d_modech.c index 3709cc179..0d17c2550 100644 --- a/libs/video/renderer/sw/d_modech.c +++ b/libs/video/renderer/sw/d_modech.c @@ -65,20 +65,10 @@ D_Patch (void) void D_ViewChanged (void) { - int rowpixels; - - if (r_dowarp) - rowpixels = WARP_WIDTH; - else - rowpixels = vid.rowbytes; - scale_for_mip = xscale; if (yscale > xscale) scale_for_mip = yscale; - d_zrowbytes = vid.width * 2; - d_zwidth = vid.width; - d_pix_min = r_refdef.vrect.width / 320; if (d_pix_min < 1) d_pix_min = 1; @@ -99,14 +89,5 @@ D_ViewChanged (void) d_vrectbottom_particle = r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift); - { - unsigned i; - - for (i = 0; i < vid.height; i++) { - d_scantable[i] = i * rowpixels; - zspantable[i] = d_zbuffer + i * d_zwidth; - } - } - D_Patch (); } diff --git a/libs/video/renderer/sw/d_part.c b/libs/video/renderer/sw/d_part.c index 65fa5ddac..f79229b9f 100644 --- a/libs/video/renderer/sw/d_part.c +++ b/libs/video/renderer/sw/d_part.c @@ -81,7 +81,7 @@ D_DrawParticle (particle_t *pparticle) switch (pix) { case 1: count = 1 << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { if (pz[0] <= izi) { pz[0] = izi; pdest[0] = pparticle->icolor; @@ -91,7 +91,7 @@ D_DrawParticle (particle_t *pparticle) case 2: count = 2 << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { if (pz[0] <= izi) { pz[0] = izi; pdest[0] = pparticle->icolor; @@ -106,7 +106,7 @@ D_DrawParticle (particle_t *pparticle) case 3: count = 3 << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { if (pz[0] <= izi) { pz[0] = izi; pdest[0] = pparticle->icolor; @@ -126,7 +126,7 @@ D_DrawParticle (particle_t *pparticle) case 4: count = 4 << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { if (pz[0] <= izi) { pz[0] = izi; pdest[0] = pparticle->icolor; @@ -151,7 +151,7 @@ D_DrawParticle (particle_t *pparticle) default: count = pix << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { for (i = 0; i < pix; i++) { if (pz[i] <= izi) { pz[i] = izi; diff --git a/libs/video/renderer/sw/d_parta.S b/libs/video/renderer/sw/d_parta.S index 41debaa27..ab4b8c969 100644 --- a/libs/video/renderer/sw/d_parta.S +++ b/libs/video/renderer/sw/d_parta.S @@ -245,7 +245,7 @@ C(DP_1x1): .globl C(DP_2x2) C(DP_2x2): pushl %esi - movl C(screenwidth),%ebx + movl C(d_rowbytes),%ebx movl C(d_zrowbytes),%esi cmpw %bp,(%edx) @@ -276,7 +276,7 @@ L2x2_4: .globl C(DP_3x3) C(DP_3x3): pushl %esi - movl C(screenwidth),%ebx + movl C(d_rowbytes),%ebx movl C(d_zrowbytes),%esi cmpw %bp,(%edx) @@ -335,7 +335,7 @@ L3x3_9: .globl C(DP_4x4) C(DP_4x4): pushl %esi - movl C(screenwidth),%ebx + movl C(d_rowbytes),%ebx movl C(d_zrowbytes),%esi cmpw %bp,(%edx) @@ -438,7 +438,7 @@ LDefault: movb C(d_y_aspect_shift),%cl shll %cl,%ebx -// for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) +// for ( ; count ; count--, pz += d_zwidth, pdest += d_rowbytes) // { // for (i=0 ; iframebuffer->buffer; int w, h; int u, v; int scr_x = vr_data.scr_view->xpos; @@ -59,6 +61,8 @@ D_WarpScreen (void) int *turb; int *col; byte **row; + byte *color = _swfb->color; + int rowbytes = _swfb->rowbytes; /* FIXME: allocate these arrays properly */ byte *rowptr[MAXHEIGHT + AMP2 * 2]; @@ -72,8 +76,8 @@ D_WarpScreen (void) hratio = h / (float) scr_h; for (v = 0; v < scr_h + AMP2 * 2; v++) { - rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) + - (screenwidth * (int) ((float) v * hratio * h / (h + AMP2 * 2))); + rowptr[v] = d_viewbuffer + (0*r_refdef.vrect.y * d_rowbytes) + + (d_rowbytes * (int) ((float) v * hratio * h / (h + AMP2 * 2))); } for (u = 0; u < scr_w + AMP2 * 2; u++) { @@ -82,9 +86,9 @@ D_WarpScreen (void) } turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = ((byte*)vid.buffer) + scr_y * vid.rowbytes + scr_x; + dest = color + scr_y * rowbytes + scr_x; - for (v = 0; v < scr_h; v++, dest += vid.rowbytes) { + for (v = 0; v < scr_h; v++, dest += rowbytes) { col = &column[turb[v]]; row = &rowptr[v]; for (u = 0; u < scr_w; u += 4) { @@ -141,7 +145,7 @@ Turbulent (espan_t *pspan) zi16stepu = d_zistepu * 16; do { - r_turb_pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + r_turb_pdest = d_viewbuffer + (d_rowbytes * pspan->v) + pspan->u; count = pspan->count; @@ -265,7 +269,7 @@ D_DrawSpans8 (espan_t *pspan) zi8stepu = d_zistepu * 8; do { - pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + pdest = d_viewbuffer + (d_rowbytes * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index bfc3a2fed..2671de132 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -78,7 +78,7 @@ D_DrawSkyScans (espan_t *pspan) tnext = 0; // ditto do { - pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + pdest = d_viewbuffer + (d_rowbytes * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_spr8.S b/libs/video/renderer/sw/d_spr8.S index b2174b384..ebc005d9c 100644 --- a/libs/video/renderer/sw/d_spr8.S +++ b/libs/video/renderer/sw/d_spr8.S @@ -223,7 +223,7 @@ LSpanLoop: pushl %ebx // preserve spans pointer movl C(tadjust),%edx movl C(sadjust),%esi - movl C(d_scantable)(,%eax,4),%edi // v * screenwidth + movl C(d_scantable)(,%eax,4),%edi // v * d_rowbytes addl %ebp,%edi movl sspan_t_u(%ebx),%ebp addl %ebp,%edi // pdest = &pdestspan[scans->u]; diff --git a/libs/video/renderer/sw/d_sprite.c b/libs/video/renderer/sw/d_sprite.c index 884e2dbd7..c17e5957f 100644 --- a/libs/video/renderer/sw/d_sprite.c +++ b/libs/video/renderer/sw/d_sprite.c @@ -69,7 +69,7 @@ D_SpriteDrawSpans (sspan_t *pspan) izistep = (int) (d_zistepu * 0x8000 * 0x10000); do { - pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + pdest = d_viewbuffer + (d_rowbytes * pspan->v) + pspan->u; pz = d_zbuffer + (d_zwidth * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 59c28c4cb..cc90bd95b 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -108,8 +108,6 @@ D_InitCaches (void *buffer, int size) sc_base->owner = NULL; sc_base->size = sc_size; - d_zbuffer = vid.zbuffer; - D_ClearCacheGuard (); } diff --git a/libs/video/renderer/sw/d_vars.c b/libs/video/renderer/sw/d_vars.c index 88288f8bb..5864d906b 100644 --- a/libs/video/renderer/sw/d_vars.c +++ b/libs/video/renderer/sw/d_vars.c @@ -54,7 +54,9 @@ byte *cacheblock; int cachewidth; byte *d_viewbuffer; short *d_zbuffer; +int d_rowbytes; int d_zrowbytes; int d_zwidth; +int d_height; #endif // !USE_INTEL_ASM diff --git a/libs/video/renderer/sw/d_varsa.S b/libs/video/renderer/sw/d_varsa.S index 642e7ab47..dba80a3e6 100644 --- a/libs/video/renderer/sw/d_varsa.S +++ b/libs/video/renderer/sw/d_varsa.S @@ -80,6 +80,8 @@ C(bbextentt): .long 0 .globl C(cacheblock) .globl C(d_viewbuffer) +.globl C(d_rowbytes) +.globl C(d_height) .globl C(cachewidth) .globl C(d_zbuffer) .globl C(d_zrowbytes) @@ -87,6 +89,8 @@ C(bbextentt): .long 0 C(cacheblock): .long 0 C(cachewidth): .long 0 C(d_viewbuffer): .long 0 +C(d_rowbytes): .long 0 +C(d_height): .long 0 C(d_zbuffer): .long 0 C(d_zrowbytes): .long 0 C(d_zwidth): .long 0 diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index c909dd293..750105e39 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -45,6 +45,7 @@ #include "QF/ui/view.h" #include "d_iface.h" +#include "d_local.h" #include "r_internal.h" #include "vid_internal.h" @@ -279,7 +280,7 @@ Draw_Character (int x, int y, unsigned int chr) } else drawline = 8; - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + dest = d_viewbuffer + y * d_rowbytes + x; while (drawline--) { if (source[0]) @@ -299,7 +300,7 @@ Draw_Character (int x, int y, unsigned int chr) if (source[7]) dest[7] = source[7]; source += 128; - dest += vid.rowbytes; + dest += d_rowbytes; } } @@ -339,7 +340,7 @@ Draw_Pixel (int x, int y, byte color) { byte *dest; - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + dest = d_viewbuffer + y * d_rowbytes + x; *dest = color; } @@ -493,7 +494,7 @@ Draw_Pic (int x, int y, qpic_t *pic) source = pic->data; - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + dest = d_viewbuffer + y * d_rowbytes + x; if (pic->width & 7) { // general for (v = 0; v < pic->height; v++) { @@ -501,7 +502,7 @@ Draw_Pic (int x, int y, qpic_t *pic) if ((tbyte = source[u]) != TRANSPARENT_COLOR) dest[u] = tbyte; - dest += vid.rowbytes; + dest += d_rowbytes; source += pic->width; } } else { // unwound @@ -524,7 +525,7 @@ Draw_Pic (int x, int y, qpic_t *pic) if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) dest[u + 7] = tbyte; } - dest += vid.rowbytes; + dest += d_rowbytes; source += pic->width; } } @@ -571,7 +572,7 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, source = pic->data + srcy * pic->width + srcx; - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + dest = d_viewbuffer + y * d_rowbytes + x; if (width & 7) { // general for (v = 0; v < height; v++) { @@ -579,7 +580,7 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, if ((tbyte = source[u]) != TRANSPARENT_COLOR) dest[u] = tbyte; - dest += vid.rowbytes; + dest += d_rowbytes; source += pic->width; } } else { // unwound @@ -602,7 +603,7 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) dest[u + 7] = tbyte; } - dest += vid.rowbytes; + dest += d_rowbytes; source += pic->width; } } @@ -620,9 +621,9 @@ Draw_ConsoleBackground (int lines, byte alpha) conback = Draw_CachePic ("gfx/conback.lmp", false); // draw the pic - dest = vid.buffer; + dest = d_viewbuffer; - for (y = 0; y < lines; y++, dest += vid.rowbytes) { + for (y = 0; y < lines; y++, dest += d_rowbytes) { v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; src = conback->data + v * 320; if (vid.conview->xlen == 320) @@ -654,10 +655,10 @@ R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) int i, j, srcdelta, destdelta; byte *pdest; - pdest = ((byte*)vid.buffer) + (prect->y * vid.rowbytes) + prect->x; + pdest = d_viewbuffer + (prect->y * d_rowbytes) + prect->x; srcdelta = rowbytes - prect->width; - destdelta = vid.rowbytes - prect->width; + destdelta = d_rowbytes - prect->width; if (transparent) { for (i = 0; i < prect->height; i++) { @@ -678,7 +679,7 @@ R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) for (i = 0; i < prect->height; i++) { memcpy (pdest, psrc, prect->width); psrc += rowbytes; - pdest += vid.rowbytes; + pdest += d_rowbytes; } } } @@ -754,8 +755,8 @@ Draw_Fill (int x, int y, int w, int h, int c) } CLIP (x, y, w, h, (int) vid.width, (int) vid.height); - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; - for (v = 0; v < h; v++, dest += vid.rowbytes) + dest = d_viewbuffer + y * d_rowbytes + x; + for (v = 0; v < h; v++, dest += d_rowbytes) for (u = 0; u < w; u++) dest[u] = c; } @@ -774,7 +775,7 @@ Draw_FadeScreen (void) for (y = 0; y < height; y++) { uint32_t mask; - pbuf = (uint32_t *) ((byte *)vid.buffer + vid.rowbytes * y); + pbuf = (uint32_t *) (d_viewbuffer + d_rowbytes * y); mask = 0xff << ((y & 1) << 4); for (x = 0; x < width; x++) { diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 30a60379e..543d831f1 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -45,24 +45,27 @@ sw_SCR_CaptureBGR (void) tex_t *tex; const byte *src; byte *dst; + framebuffer_t *fb = sw_ctx->framebuffer; - count = vid.width * vid.height; + count = fb->width * fb->height; tex = malloc (sizeof (tex_t) + count * 3); tex->data = (byte *) (tex + 1); SYS_CHECKMEM (tex); - tex->width = vid.width; - tex->height = vid.height; + tex->width = fb->width; + tex->height = fb->height; tex->format = tex_rgb; tex->palette = 0; - src = vid.buffer; + src = ((sw_framebuffer_t *) fb->buffer)->color; + int rowbytes = ((sw_framebuffer_t *) fb->buffer)->rowbytes; for (y = 0; y < tex->height; y++) { dst = tex->data + (tex->height - 1 - y) * tex->width * 3; for (x = 0; x < tex->width; x++) { - *dst++ = vid.basepal[*src * 3 + 2]; // blue - *dst++ = vid.basepal[*src * 3 + 1]; // green - *dst++ = vid.basepal[*src * 3 + 0]; // red - src++; + byte c = src[x]; + *dst++ = vid.basepal[c * 3 + 2]; // blue + *dst++ = vid.basepal[c * 3 + 1]; // green + *dst++ = vid.basepal[c * 3 + 0]; // red } + src += rowbytes; } return tex; } diff --git a/libs/video/renderer/sw/sw_graph.c b/libs/video/renderer/sw/sw_graph.c index 4480a7eb7..da8d17a90 100644 --- a/libs/video/renderer/sw/sw_graph.c +++ b/libs/video/renderer/sw/sw_graph.c @@ -33,6 +33,7 @@ #include "QF/render.h" #include "r_internal.h" +#include "vid_sw.h" /* R_LineGraph @@ -44,12 +45,13 @@ R_LineGraph (int x, int y, int *h_vals, int count, int height) { int h, i, s, color; byte *dest; + sw_framebuffer_t *fb = sw_ctx->framebuffer->buffer; // FIXME: disable on no-buffer adapters, or put in the driver s = height; while (count--) { - dest = ((byte*)vid.buffer) + vid.rowbytes * y + x++; + dest = fb->color + fb->rowbytes * y + x++; h = *h_vals++; @@ -65,7 +67,7 @@ R_LineGraph (int x, int y, int *h_vals, int count, int height) if (h > s) h = s; - for (i = 0; i < h; i++, dest -= vid.rowbytes) { + for (i = 0; i < h; i++, dest -= fb->rowbytes) { dest[0] = color; } } diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 0c9a3dee2..acf1b4101 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -29,6 +29,7 @@ #endif #include +#include #include "QF/image.h" #include "QF/render.h" diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 99778f9bb..11c3cfe96 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -54,6 +54,7 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" #ifdef PIC # undef USE_INTEL_ASM //XXX asm pic hack @@ -70,7 +71,7 @@ float r_aliasuvscale = 1.0; int r_outofsurfaces; int r_outofedges; -qboolean r_dowarp, r_dowarpold, r_viewchanged; +qboolean r_viewchanged; int c_surf; int r_maxsurfsseen, r_maxedgesseen; @@ -78,8 +79,6 @@ static int r_cnumsurfs; static qboolean r_surfsonstack; int r_clipflags; -byte *r_warpbuffer; - static byte *r_stack_start; // screen size info @@ -689,16 +688,12 @@ R_EdgeDrawing (entqueue_t *queue) static void R_RenderView_ (void) { - byte warpbuffer[WARP_WIDTH * WARP_HEIGHT]; - if (r_norefresh->int_val) return; if (!r_refdef.worldmodel) { return; } - r_warpbuffer = warpbuffer; - R_SetupFrame (); // make FDIV fast. This reduces timing precision after we've been running for a @@ -711,9 +706,6 @@ R_RenderView_ (void) R_DrawViewModel (); - if (r_dowarp) - D_WarpScreen (); - if (r_aliasstats->int_val) R_PrintAliasStats (); @@ -739,7 +731,7 @@ R_RenderView (void) if ((intptr_t) (&dummy) & 3) Sys_Error ("Stack is missaligned"); - if ((intptr_t) (&r_warpbuffer) & 3) + if ((intptr_t) (&colormap) & 3) Sys_Error ("Globals are missaligned"); if (!scr_fisheye->int_val) R_RenderView_ (); @@ -765,7 +757,7 @@ R_InitTurb (void) #define BOX_LEFT 3 #define BOX_TOP 4 #define BOX_BOTTOM 5 - +#if 0 static mat4f_t box_rotations[] = { { { 1, 0, 0, 0}, // front { 0, 1, 0, 0}, @@ -792,7 +784,7 @@ static mat4f_t box_rotations[] = { { 1, 0, 0, 0}, { 0, 0, 0, 1} }, }; - +#endif static int sw_cube_map_size; static void @@ -848,7 +840,7 @@ fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov) } } } - +#if 0 static void rendercopy (void *dest) { @@ -901,16 +893,18 @@ renderside (byte *bufs, int side) memcpy (r_refdef.camera, camera, sizeof (camera)); memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); } - +#endif static void renderlookup (byte **offs, byte* bufs) { - byte *p = (byte*)vid.buffer; - unsigned x, y; - for (y = 0; y < vid.height; y++) { - for (x = 0; x < vid.width; x++, offs++) + framebuffer_t *fb = sw_ctx->framebuffer; + sw_framebuffer_t *swfb = fb->buffer; + byte *p = swfb->color; + unsigned x, y; + for (y = 0; y < fb->height; y++) { + for (x = 0; x < fb->width; x++, offs++) p[x] = **offs; - p += vid.rowbytes; + p += swfb->rowbytes; } } @@ -950,7 +944,7 @@ R_RenderViewFishEye (void) pviews = views; memset (scrbufs, 0, scrsize*6); } - +#if 0 switch (views) { case 6: renderside (scrbufs + scrsize * BOX_BEHIND, BOX_BEHIND); case 5: renderside (scrbufs + scrsize * BOX_BOTTOM, BOX_BOTTOM); @@ -959,6 +953,7 @@ R_RenderViewFishEye (void) case 2: renderside (scrbufs + scrsize * BOX_RIGHT, BOX_RIGHT); default: renderside (scrbufs + scrsize * BOX_FRONT, BOX_FRONT); } +#endif #if 0 memset (scrbufs + scrsize*0, 31, sw_cube_map_size); memset (scrbufs + scrsize*1, 31, sw_cube_map_size); diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index f7d41734f..47818af22 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -173,9 +173,6 @@ R_SetUpFrustumIndexes (void) void R_SetupFrame (void) { - vrect_t vrect; - float w, h; - numbtofpolys = 0; // build the transformation matrix for the given view angles @@ -185,62 +182,6 @@ R_SetupFrame (void) VectorCopy (r_refdef.frame.forward, vfwd); VectorCopy (r_refdef.frame.up, vup); - r_dowarpold = r_dowarp; - r_dowarp = r_waterwarp->int_val && (r_refdef.viewleaf->contents <= - CONTENTS_WATER); - - if (scr_fisheye->int_val) { - //FIXME this shouldn't be necessary, but warp doesn't work well in - //fisheye, aand allowing the non-warp code to mess with vrect messes - //things up for the cube map rendering. This whole frame setup path - //needs to be redesigned - r_dowarp = r_viewchanged = 0; - } - if ((r_dowarp != r_dowarpold) || r_viewchanged) { - if (r_dowarp) { - if ((vid.width <= WARP_WIDTH) - && (vid.height <= WARP_HEIGHT)) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - - R_SetVrect (&vrect, &r_refdef.vrect, vr_data.lineadj); - R_ViewChanged (); - } else { - w = vid.width; - h = vid.height; - - if (w > WARP_WIDTH) { - h *= (float) WARP_WIDTH / w; - w = WARP_WIDTH; - } - - if (h > WARP_HEIGHT) { - h = WARP_HEIGHT; - w *= (float) WARP_HEIGHT / h; - } - - vrect.x = 0; - vrect.y = 0; - vrect.width = (int) w; - vrect.height = (int) h; - - R_SetVrect (&vrect, &r_refdef.vrect, - (int) ((float) vr_data.lineadj * - (h / (float) vid.height))); - R_ViewChanged (); - } - } else { - r_refdef.vrect.x = vr_data.scr_view->xpos; - r_refdef.vrect.y = vr_data.scr_view->ypos; - r_refdef.vrect.width = vr_data.scr_view->xlen; - r_refdef.vrect.height = vr_data.scr_view->ylen; - R_ViewChanged (); - } - - r_viewchanged = false; - } // start off with just the four screen edge clip planes R_TransformFrustum (); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 6651b97ca..4bcdcbc65 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -300,6 +300,17 @@ gl_end_frame (void) } } +static framebuffer_t * +gl_create_frame_buffer (int width, int height) +{ + Sys_Error ("not implemented"); +} + +static void +gl_bind_framebuffer (framebuffer_t *framebuffer) +{ +} + vid_render_funcs_t gl_vid_render_funcs = { gl_vid_render_init, gl_Draw_Character, @@ -339,6 +350,10 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_draw_transparent, gl_set_2d, gl_end_frame, + + gl_create_frame_buffer, + gl_bind_framebuffer, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 2913cd4f5..35eab3a20 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -244,6 +244,17 @@ glsl_end_frame (void) qfeglFlush (); } +static framebuffer_t * +glsl_create_frame_buffer (int width, int height) +{ + Sys_Error ("not implemented"); +} + +static void +glsl_bind_framebuffer (framebuffer_t *framebuffer) +{ +} + vid_render_funcs_t glsl_vid_render_funcs = { glsl_vid_render_init, glsl_Draw_Character, @@ -283,6 +294,10 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_draw_transparent, glsl_set_2d, glsl_end_frame, + + glsl_create_frame_buffer, + glsl_bind_framebuffer, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 010133375..d78c1b825 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -28,6 +28,8 @@ # include "config.h" #endif +#include + #include "QF/cvar.h" #include "QF/plugin/general.h" @@ -35,6 +37,7 @@ #include "QF/ui/view.h" +#include "d_local.h" #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" @@ -108,6 +111,8 @@ sw_vid_render_shutdown (void) { } +static void sw_bind_framebuffer (framebuffer_t *framebuffer); + static void sw_begin_frame (void) { @@ -131,6 +136,8 @@ sw_begin_frame (void) r_numallocatededges, r_maxedgesseen); } + sw_bind_framebuffer (0); + // do 3D refresh drawing, and then update the screen if (vr_data.scr_fullupdate++ < vid.numpages) { vr_data.scr_copyeverything = 1; @@ -152,6 +159,10 @@ sw_draw_transparent (void) static void sw_set_2d (int scaled) { + if (!scaled && r_dowarp) { + D_WarpScreen (); + sw_bind_framebuffer (0); + } } static void @@ -187,6 +198,68 @@ sw_end_frame (void) sw_ctx->update (sw_ctx, &vrect); } +static framebuffer_t * +sw_create_frame_buffer (int width, int height) +{ + size_t pixels = width * height; + size_t size = sizeof (framebuffer_t); + size += sizeof (sw_framebuffer_t); + size += pixels; // color buffer + size += pixels * sizeof (short); // depth buffer + + framebuffer_t *fb = malloc (size); + fb->width = width; + fb->height = height; + __auto_type buffer = (sw_framebuffer_t *) &fb[1]; + fb->buffer = buffer; + buffer->color = (byte *) &buffer[1]; + buffer->depth = (short *) (buffer->color + pixels); + buffer->rowbytes = width; + return fb; +} + +static void +sw_bind_framebuffer (framebuffer_t *framebuffer) +{ + int changed = 0; + + if (!framebuffer) { + framebuffer = sw_ctx->framebuffer; + } + sw_framebuffer_t *fb = framebuffer->buffer; + + if (!fb->depth) { + fb->depth = malloc (framebuffer->width * framebuffer->height + * sizeof (short)); + } + + if (d_zbuffer != fb->depth + || d_zwidth != framebuffer->width || d_height != framebuffer->height) { + d_zwidth = framebuffer->width; + d_zrowbytes = d_zwidth * sizeof (short); + for (unsigned i = 0; i < framebuffer->height; i++) { + zspantable[i] = fb->depth + i * d_zwidth; + } + changed = 1; + } + if (d_rowbytes != fb->rowbytes || d_height != framebuffer->height) { + d_rowbytes = fb->rowbytes; + d_height = framebuffer->height; + for (unsigned i = 0; i < framebuffer->height; i++) { + d_scantable[i] = i * d_rowbytes; + } + changed = 1; + } + d_viewbuffer = fb->color; + d_zbuffer = fb->depth; + + if (changed) { + vrect_t r = { 0, 0, framebuffer->width, framebuffer->height }; + R_SetVrect (&r, &r_refdef.vrect, 0); + R_ViewChanged (); + } +} + vid_render_funcs_t sw_vid_render_funcs = { sw_vid_render_init, Draw_Character, @@ -226,6 +299,10 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_draw_transparent, sw_set_2d, sw_end_frame, + + sw_create_frame_buffer, + sw_bind_framebuffer, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 352d24ae3..1990ce1ef 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -418,6 +418,17 @@ vulkan_end_frame (void) vulkan_ctx->curFrame %= vulkan_ctx->frames.size; } +static framebuffer_t * +vulkan_create_frame_buffer (int width, int height) +{ + Sys_Error ("not implemented"); +} + +static void +vulkan_bind_framebuffer (framebuffer_t *framebuffer) +{ +} + static int is_bgr (VkFormat format) { @@ -696,6 +707,10 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_draw_transparent, vulkan_set_2d, vulkan_end_frame, + + vulkan_create_frame_buffer, + vulkan_bind_framebuffer, + &model_funcs }; diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 47e62ef29..08de11276 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -39,11 +39,14 @@ static vid_internal_t vid_internal; +#if 0 static byte backingbuf[48 * 24]; +#endif void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { +#if 0 int i, j, reps = 1, repshift = 0; vrect_t rect; @@ -72,12 +75,14 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) rect.next = NULL; win_sw_context->update (win_sw_context, &rect); +#endif } void D_EndDirectRect (int x, int y, int width, int height) { +#if 0 int i, j, reps = 1, repshift = 0; vrect_t rect; @@ -102,6 +107,7 @@ D_EndDirectRect (int x, int y, int width, int height) rect.next = NULL; win_sw_context->update (win_sw_context, &rect); +#endif } static void diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index 9ded596fb..2e8667c85 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -72,6 +72,9 @@ static ddCreateProc_t ddCreate; static int dd_window_width = 640; static int dd_window_height = 480; +static sw_framebuffer_t swfb; +static framebuffer_t fb = { .buffer = &swfb }; + static void DD_UpdateRects (int width, int height) { @@ -94,8 +97,10 @@ VID_CreateDDrawDriver (int width, int height) dd_window_width = width; dd_window_height = height; - viddef.buffer = malloc (width * height); - viddef.rowbytes = width; + fb.width = width; + fb.height = height; + swfb.color = malloc (width * height); + swfb.rowbytes = width; if (!(hInstDDraw = LoadLibrary ("ddraw.dll"))) { return; @@ -162,7 +167,7 @@ VID_CreateDDrawDriver (int width, int height) } static void -VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer, +VID_CreateGDIDriver (int width, int height, const byte *palette, byte **buffer, int *rowbytes) { // common bitmap definition @@ -235,10 +240,13 @@ void Win_UnloadAllDrivers (void) { // shut down ddraw - if (viddef.buffer) { - free (viddef.buffer); - *(int *)0xdb = 0; - viddef.buffer = 0; + if (swfb.color) { + free (swfb.color); + swfb.color = 0; + } + if (swfb.depth) { + free (swfb.depth); + swfb.depth = 0; } if (dd_Clipper) { @@ -303,13 +311,17 @@ Win_CreateDriver (void) Win_UnloadAllDrivers (); VID_CreateGDIDriver (viddef.width, viddef.height, viddef.palette, - &viddef.buffer, &viddef.rowbytes); + &swfb.color, &swfb.rowbytes); } } static void win_init_bufers (void *data) { + sw_ctx_t *ctx = data; + + ctx->framebuffer = &fb; + Win_UnloadAllDrivers (); Win_CreateDriver (); } @@ -372,13 +384,13 @@ dd_blit_rect (vrect_t *rect) // convert pitch to 32-bit addressable ddsd.lPitch >>= 2; - byte *src = viddef.buffer + rect->y * viddef.rowbytes + rect->x; + byte *src = swfb.color + rect->y * swfb.rowbytes + rect->x; unsigned *dst = ddsd.lpSurface; for (int y = rect->height; y-- > 0; ) { for (int x = rect->width; x-- > 0; ) { *dst++ = st2d_8to32table[*src++].value; } - src += viddef.rowbytes - rect->width; + src += swfb.rowbytes - rect->width; dst += ddsd.lPitch - rect->width; } diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index ed0719720..7601d72d0 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -219,17 +219,18 @@ x11_set_palette (sw_ctx_t *ctx, const byte *palette) } static void -st2_fixup (XImage *framebuf, int x, int y, int width, int height) +st2_fixup (sw_ctx_t *ctx, XImage *framebuf, int x, int y, int width, int height) { int xi, yi; unsigned char *src; PIXEL16 *dest; + sw_framebuffer_t *fb = ctx->framebuffer->buffer; if (x < 0 || y < 0) return; for (yi = y; yi < (y + height); yi++) { - src = &((byte *)viddef.buffer)[yi * viddef.width]; + src = &fb->color[yi * fb->rowbytes]; dest = (PIXEL16 *) &framebuf->data[yi * framebuf->bytes_per_line]; for (xi = x; xi < x + width; xi++) { dest[xi] = st2d_8to16table[src[xi]]; @@ -238,18 +239,19 @@ st2_fixup (XImage *framebuf, int x, int y, int width, int height) } static void -st3_fixup (XImage * framebuf, int x, int y, int width, int height) +st3_fixup (sw_ctx_t *ctx, XImage *framebuf, int x, int y, int width, int height) { int yi; unsigned char *src; PIXEL24 *dest; + sw_framebuffer_t *fb = ctx->framebuffer->buffer; register int count, n; if (x < 0 || y < 0) return; for (yi = y; yi < (y + height); yi++) { - src = &((byte *)viddef.buffer)[yi * viddef.width + x]; + src = &fb->color[yi * fb->rowbytes + x]; dest = (PIXEL24 *) &framebuf->data[yi * framebuf->bytes_per_line + x]; // Duff's Device @@ -280,13 +282,13 @@ st3_fixup (XImage * framebuf, int x, int y, int width, int height) } static void -x11_put_image (vrect_t *rects) +x11_put_image (vrect_t *rect) { if (doShm) { if (!XShmPutImage (x_disp, x_win, x_gc, x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height, True)) { + rect->x, rect->y, rect->x, rect->y, + rect->width, rect->height, True)) { Sys_Error ("VID_Update: XShmPutImage failed"); } oktodraw = false; @@ -296,8 +298,8 @@ x11_put_image (vrect_t *rects) current_framebuffer = !current_framebuffer; } else { if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height)) { + rect->x, rect->y, rect->x, rect->y, + rect->width, rect->height)) { Sys_Error ("VID_Update: XPutImage failed"); } } @@ -309,33 +311,46 @@ x11_put_image (vrect_t *rects) static void x11_sw8_8_update (sw_ctx_t *ctx, vrect_t *rects) { - while (rects) { - switch (x_visinfo->depth) { - case 16: - st2_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - break; - case 24: - st3_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - break; - } - x11_put_image (rects); + vrect_t urect = *rects; + while (rects->next) { rects = rects->next; + int minx = min (VRect_MinX (&urect), VRect_MinX (rects)); + int miny = min (VRect_MinY (&urect), VRect_MinY (rects)); + int maxx = max (VRect_MaxX (&urect), VRect_MaxX (rects)); + int maxy = max (VRect_MaxY (&urect), VRect_MaxY (rects)); + urect.x = minx; + urect.y = miny; + urect.width = maxx - minx; + urect.height = maxy - miny; } + x11_put_image (&urect); XSync (x_disp, False); r_data->scr_fullupdate = 0; + + sw_framebuffer_t *fb = ctx->framebuffer->buffer; + fb->color = (byte *) x_framebuffer[current_framebuffer]->data; } static void x11_sw8_16_update (sw_ctx_t *ctx, vrect_t *rects) { - while (rects) { - st2_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - x11_put_image (rects); + vrect_t urect = *rects; + st2_fixup (ctx, x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + while (rects->next) { rects = rects->next; + st2_fixup (ctx, x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + int minx = min (VRect_MinX (&urect), VRect_MinX (rects)); + int miny = min (VRect_MinY (&urect), VRect_MinY (rects)); + int maxx = max (VRect_MaxX (&urect), VRect_MaxX (rects)); + int maxy = max (VRect_MaxY (&urect), VRect_MaxY (rects)); + urect.x = minx; + urect.y = miny; + urect.width = maxx - minx; + urect.height = maxy - miny; } + x11_put_image (&urect); XSync (x_disp, False); r_data->scr_fullupdate = 0; } @@ -343,12 +358,23 @@ x11_sw8_16_update (sw_ctx_t *ctx, vrect_t *rects) static void x11_sw8_24_update (sw_ctx_t *ctx, vrect_t *rects) { - while (rects) { - st3_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - x11_put_image (rects); + vrect_t urect = *rects; + st3_fixup (ctx, x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + while (rects->next) { rects = rects->next; + st3_fixup (ctx, x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + int minx = min (VRect_MinX (&urect), VRect_MinX (rects)); + int miny = min (VRect_MinY (&urect), VRect_MinY (rects)); + int maxx = max (VRect_MaxX (&urect), VRect_MaxX (rects)); + int maxy = max (VRect_MaxY (&urect), VRect_MaxY (rects)); + urect.x = minx; + urect.y = miny; + urect.width = maxx - minx; + urect.height = maxy - miny; } + x11_put_image (&urect); XSync (x_disp, False); r_data->scr_fullupdate = 0; } @@ -592,9 +618,16 @@ ResetSharedFrameBuffers (void) } } +static sw_framebuffer_t swfb; +static framebuffer_t fb = { .buffer = &swfb }; + static void x11_init_buffers (void *data) { + sw_ctx_t *ctx = data; + + ctx->framebuffer = &fb; + if (doShm) ResetSharedFrameBuffers (); else @@ -602,15 +635,18 @@ x11_init_buffers (void *data) current_framebuffer = 0; - viddef.rowbytes = viddef.width; + fb.width = viddef.width; + fb.height = viddef.height; if (x_visinfo->depth != 8) { - if (viddef.buffer) - free (viddef.buffer); - viddef.buffer = calloc (viddef.rowbytes, viddef.height); - if (!viddef.buffer) + if (swfb.color) + free (swfb.color); + swfb.rowbytes = viddef.width; + swfb.color = calloc (swfb.rowbytes, viddef.height); + if (!swfb.color) Sys_Error ("Not enough memory for video mode"); } else { - viddef.buffer = x_framebuffer[current_framebuffer]->data; + swfb.rowbytes = x_framebuffer[current_framebuffer]->bytes_per_line; + swfb.color = (byte *) x_framebuffer[current_framebuffer]->data; } } From 20a2e7e06f214fea9977d493939ec4a64c37d822 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Mar 2022 15:45:01 +0900 Subject: [PATCH 2569/3664] [renderer] Get sw fisheye working again Again, gl/vulkan not working yet (on the assumption that sw would be trickier). Fisheye overrides water warp because updating the projection map every frame is far too expensive. I've added a post-process pass to the interface in order to hide the implementation details, but I'm not sure I'm happy about how the multi-pass rendering for cube maps is handled (or having the frame buffers as exposed as they are), but mainly because Vulkan will make implementation interesting. --- include/QF/plugin/vid_render.h | 3 + include/r_internal.h | 9 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/gl/gl_rmain.c | 4 +- libs/video/renderer/r_screen.c | 109 +++++++++++- libs/video/renderer/sw/sw_fisheye.c | 166 +++++++++++++++++ libs/video/renderer/sw/sw_rmain.c | 226 +----------------------- libs/video/renderer/vid_render_gl.c | 13 ++ libs/video/renderer/vid_render_glsl.c | 13 ++ libs/video/renderer/vid_render_sw.c | 46 ++++- libs/video/renderer/vid_render_vulkan.c | 13 ++ 11 files changed, 366 insertions(+), 237 deletions(-) create mode 100644 libs/video/renderer/sw/sw_fisheye.c diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index b425cce54..3cb8b46b1 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -40,6 +40,7 @@ struct skin_s; struct mod_alias_ctx_s; struct mod_sprite_ctx_s; struct entqueue_s; +struct framebuffer_s; /* All video plugins must export these functions @@ -112,9 +113,11 @@ typedef struct vid_render_funcs_s { void (*draw_entities) (struct entqueue_s *queue); void (*draw_particles) (struct psystem_s *psystem); void (*draw_transparent) (void); + void (*post_process) (struct framebuffer_s *src); void (*set_2d) (int scaled); void (*end_frame) (void); + struct framebuffer_s *(*create_cube_map) (int side); struct framebuffer_s *(*create_frame_buffer) (int width, int height); void (*bind_framebuffer) (struct framebuffer_s *framebuffer); diff --git a/include/r_internal.h b/include/r_internal.h index 71841b948..c1c01bf0c 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -81,4 +81,13 @@ int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, mspriteframe_t *R_GetSpriteFrame (const msprite_t *sprite, const animation_t *animation); +// These correspond to the standard box sides for OpenGL cube maps +#define BOX_FRONT 4 +#define BOX_RIGHT 0 +#define BOX_BEHIND 5 +#define BOX_LEFT 1 +#define BOX_TOP 2 +#define BOX_BOTTOM 3 +void R_RenderFisheye (framebuffer_t *cube); + #endif//__r_internal_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index ca7f487af..065f7f0a0 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -157,6 +157,7 @@ libs_video_renderer_librender_sw_la_SOURCES = \ libs/video/renderer/sw/nonintel.c \ libs/video/renderer/sw/screen.c \ libs/video/renderer/sw/surf8.S \ + libs/video/renderer/sw/sw_fisheye.c \ libs/video/renderer/sw/sw_graph.c \ libs/video/renderer/sw/sw_raclip.c \ libs/video/renderer/sw/sw_raclipa.S \ diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 6a5c247ba..325def941 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -364,14 +364,14 @@ gl_R_RenderView (void) // translation function to map texture coordinates to fixed/regular // grid vertices coordinates. // Render view. Fisheye is done. - +#if 0 #define BOX_FRONT 0 #define BOX_RIGHT 1 #define BOX_BEHIND 2 #define BOX_LEFT 3 #define BOX_TOP 4 #define BOX_BOTTOM 5 - +#endif static mat4f_t box_rotations[] = { { { 1, 0, 0, 0}, // front { 0, 1, 0, 0}, diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 7089b0cc9..d2f47edce 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -66,7 +66,48 @@ static qboolean scr_initialized;// ready to draw static qpic_t *scr_ram; static qpic_t *scr_turtle; +static framebuffer_t *fisheye_cube_map; static framebuffer_t *warp_buffer; + +static mat4f_t box_rotations[] = { + [BOX_FRONT] = { + { 1, 0, 0, 0}, // front + { 0, 1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} + }, + [BOX_RIGHT] = { + { 0,-1, 0, 0}, // right + { 1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} + }, + [BOX_BEHIND] = { + {-1, 0, 0, 0}, // back + { 0,-1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} + }, + [BOX_LEFT] = { + { 0, 1, 0, 0}, // left + {-1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} + }, + [BOX_TOP] = { + { 0, 0, 1, 0}, // top + { 0, 1, 0, 0}, + {-1, 0, 0, 0}, + { 0, 0, 0, 1} + }, + [BOX_BOTTOM] = { + { 0, 0,-1, 0}, // bottom + { 0, 1, 0, 0}, + { 1, 0, 0, 0}, + { 0, 0, 0, 1} + }, +}; + static void set_vrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) { @@ -138,6 +179,44 @@ SCR_CalcRefdef (void) r_data->scr_fullupdate = 0; } +static void +render_scene (void) +{ + r_framecount++; + EntQueue_Clear (r_ent_queue); + r_funcs->render_view (); + r_funcs->draw_entities (r_ent_queue); + r_funcs->draw_particles (&r_psystem); + r_funcs->draw_transparent (); +} + +static void +render_side (int side) +{ + mat4f_t camera; + mat4f_t camera_inverse; + mat4f_t rotinv; + + memcpy (camera, r_refdef.camera, sizeof (camera)); + memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse)); + mmulf (r_refdef.camera, camera, box_rotations[side]); + mat4ftranspose (rotinv, box_rotations[side]); + mmulf (r_refdef.camera_inverse, rotinv, camera_inverse); + + //FIXME see fixme in r_screen.c + r_refdef.frame.mat[0] = -r_refdef.camera[1]; + r_refdef.frame.mat[1] = r_refdef.camera[0]; + r_refdef.frame.mat[2] = r_refdef.camera[2]; + r_refdef.frame.mat[3] = r_refdef.camera[3]; + + r_data->refdef->fov_x = r_data->refdef->fov_y = 90; + r_funcs->bind_framebuffer (&fisheye_cube_map[side]); + render_scene (); + + memcpy (r_refdef.camera, camera, sizeof (camera)); + memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); +} + /* SCR_UpdateScreen @@ -158,6 +237,10 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) r_time1 = Sys_DoubleTime (); } + if (scr_fisheye->int_val && !fisheye_cube_map) { + fisheye_cube_map = r_funcs->create_cube_map (r_data->vid->height); + } + refdef_t *refdef = r_data->refdef; if (camera) { Transform_GetWorldMatrix (camera, refdef->camera); @@ -181,10 +264,6 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) R_SetFrustum (refdef->frustum, &refdef->frame, refdef->fov_x, refdef->fov_y); - //FIXME breaks fisheye as it calls the view render many times - EntQueue_Clear (r_ent_queue); - r_framecount++; - r_data->realtime = realtime; scr_copytop = r_data->scr_copyeverything = 0; @@ -203,7 +282,8 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) r_dowarp = refdef->viewleaf->contents <= CONTENTS_WATER; } if (r_dowarp && !warp_buffer) { - warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, r_data->vid->height); + warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, + r_data->vid->height); } } R_MarkLeaves (); @@ -213,10 +293,21 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) if (r_dowarp) { r_funcs->bind_framebuffer (warp_buffer); } - r_funcs->render_view (); - r_funcs->draw_entities (r_ent_queue); - r_funcs->draw_particles (&r_psystem); - r_funcs->draw_transparent (); + if (scr_fisheye->int_val) { + switch (scr_fviews->int_val) { + case 6: render_side (BOX_BEHIND); + case 5: render_side (BOX_BOTTOM); + case 4: render_side (BOX_TOP); + case 3: render_side (BOX_LEFT); + case 2: render_side (BOX_RIGHT); + default:render_side (BOX_FRONT); + } + r_funcs->bind_framebuffer (0); + r_funcs->post_process (fisheye_cube_map); + } else { + render_scene (); + r_funcs->post_process (warp_buffer); + } r_funcs->set_2d (0); view_draw (r_data->scr_view); r_funcs->set_2d (1); diff --git a/libs/video/renderer/sw/sw_fisheye.c b/libs/video/renderer/sw/sw_fisheye.c new file mode 100644 index 000000000..c1c782e47 --- /dev/null +++ b/libs/video/renderer/sw/sw_fisheye.c @@ -0,0 +1,166 @@ +/* + sw_fisheye.c + + SW fisheye rendering + + Copyright (C) 2003 Arkadi Shishlov + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif + +#include + +#include "QF/cvar.h" +#include "QF/render.h" + +#include "compat.h" +#include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" + +static void +fisheyelookuptable (byte **buf, int width, int height, framebuffer_t *cube, + double fov) +{ + int cube_size = cube->width; + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + double dx = x - width / 2; + double dy = -(y - height / 2); + double yaw = sqrt (dx * dx + dy * dy) * fov / width; + double roll = atan2 (dy, dx); + double sx = sin (yaw) * cos (roll); + double sy = sin (yaw) * sin (roll); + double sz = cos (yaw); + + // determine which side of the box we need + double abs_x = fabs (sx); + double abs_y = fabs (sy); + double abs_z = fabs (sz); + int side; + double xs = 0, ys = 0; + + if (abs_x > abs_y) { + if (abs_x > abs_z) { + side = ((sx > 0.0) ? BOX_RIGHT : BOX_LEFT); + } else { + side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); + } + } else { + if (abs_y > abs_z) { + side = ((sy > 0.0) ? BOX_TOP : BOX_BOTTOM); + } else { + side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); + } + } + + #define RC(x) ((x / 2) + 0.5) + #define R2(x) ((x / 2) + 0.5) + + // scale up our vector [x,y,z] to the box + switch(side) { + case BOX_FRONT: xs = RC( sx / sz); ys = R2(-sy / sz); break; + case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2(-sy / -sz); break; + case BOX_LEFT: xs = RC( sz / -sx); ys = R2(-sy / -sx); break; + case BOX_RIGHT: xs = RC(-sz / sx); ys = R2(-sy / sx); break; + case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / sy); break; + case BOX_BOTTOM: xs = RC( sx / -sy); ys = R2( sz / sy); break; + } + + xs = bound (0, xs, 1); + ys = bound (0, ys, 1); + int sxs = xs * (cube_size - 1); + int sys = ys * (cube_size - 1); + sw_framebuffer_t *fb = cube[side].buffer; + *buf++ = fb->color + sys * fb->rowbytes + sxs; + } + } +} + +static void +renderlookup (byte **offs) +{ + framebuffer_t *fb = sw_ctx->framebuffer; + sw_framebuffer_t *swfb = fb->buffer; + byte *p = swfb->color; + unsigned x, y; + for (y = 0; y < fb->height; y++) { + for (x = 0; x < fb->width; x++, offs++) + p[x] = **offs; + p += swfb->rowbytes; + } +} + +void +R_RenderFisheye (framebuffer_t *cube) +{ + int width = r_refdef.vrect.width; + int height = r_refdef.vrect.height; + int fov = scr_ffov->int_val; + static int pwidth = -1; + static int pheight = -1; + static int pfov = -1; + static unsigned psize = -1; + static byte **offs = NULL; + + if (fov < 1) fov = 1; + + if (pwidth != width || pheight != height || pfov != fov + || psize != cube->width) { + if (offs) free (offs); + offs = malloc (width*height*sizeof(byte*)); + SYS_CHECKMEM (offs); + pwidth = width; + pheight = height; + pfov = fov; + psize = cube->width; + fisheyelookuptable (offs, width, height, cube, fov*M_PI/180.0); + } +#if 0 + sw_framebuffer_t *fb = cube[0].buffer; + int rowbytes = fb->rowbytes; + int csize = cube[0].width; + for (int s = 0; s < 6; s++) { + fb = cube[s].buffer; + memset (fb->color, 31, csize); + memset (fb->color + (csize - 1) * rowbytes, 31, csize); + for (int y = 0; y < csize; y++) { + fb->color[y * rowbytes] = 31; + fb->color[y * rowbytes + csize - 1] = 31; + } + } +#endif + renderlookup (offs); +} diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 11c3cfe96..235a60a9c 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -713,8 +713,6 @@ R_RenderView_ (void) R_HighFPPrecision (); } -static void R_RenderViewFishEye (void); - void R_RenderView (void) { @@ -733,10 +731,8 @@ R_RenderView (void) if ((intptr_t) (&colormap) & 3) Sys_Error ("Globals are missaligned"); - if (!scr_fisheye->int_val) - R_RenderView_ (); - else - R_RenderViewFishEye (); + + R_RenderView_ (); } void @@ -751,224 +747,6 @@ R_InitTurb (void) } } -#define BOX_FRONT 0 -#define BOX_RIGHT 1 -#define BOX_BEHIND 2 -#define BOX_LEFT 3 -#define BOX_TOP 4 -#define BOX_BOTTOM 5 -#if 0 -static mat4f_t box_rotations[] = { - { { 1, 0, 0, 0}, // front - { 0, 1, 0, 0}, - { 0, 0, 1, 0}, - { 0, 0, 0, 1} }, - { { 0,-1, 0, 0}, // right - { 1, 0, 0, 0}, - { 0, 0, 1, 0}, - { 0, 0, 0, 1} }, - { {-1, 0, 0, 0}, // back - { 0,-1, 0, 0}, - { 0, 0, 1, 0}, - { 0, 0, 0, 1} }, - { { 0, 1, 0, 0}, // left - {-1, 0, 0, 0}, - { 0, 0, 1, 0}, - { 0, 0, 0, 1} }, - { { 0, 0, 1, 0}, // top - { 0, 1, 0, 0}, - {-1, 0, 0, 0}, - { 0, 0, 0, 1} }, - { { 0, 0,-1, 0}, // bottom - { 0, 1, 0, 0}, - { 1, 0, 0, 0}, - { 0, 0, 0, 1} }, -}; -#endif -static int sw_cube_map_size; - -static void -fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov) -{ - int x, y; - int scrsize = sw_cube_map_size * sw_cube_map_size; - - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - double dx = x-width/2; - double dy = -(y-height/2); - double yaw = sqrt(dx*dx+dy*dy)*fov/((double)width); - double roll = atan2(dy, dx); - double sx = sin(yaw) * cos(roll); - double sy = sin(yaw) * sin(roll); - double sz = cos(yaw); - - // determine which side of the box we need - double abs_x = fabs(sx); - double abs_y = fabs(sy); - double abs_z = fabs(sz); - int side; - double xs = 0, ys = 0; - if (abs_x > abs_y) { - if (abs_x > abs_z) { side = ((sx > 0.0) ? BOX_RIGHT : BOX_LEFT); } - else { side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); } - } else { - if (abs_y > abs_z) { side = ((sy > 0.0) ? BOX_TOP : BOX_BOTTOM); } - else { side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); } - } - - #define RC(x) ((x / 2) + 0.5) - #define R2(x) ((x / 2) + 0.5) - - // scale up our vector [x,y,z] to the box - switch(side) { - case BOX_FRONT: xs = RC( sx / sz); ys = R2(-sy / sz); break; - case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2(-sy / -sz); break; - case BOX_LEFT: xs = RC( sz / -sx); ys = R2(-sy / -sx); break; - case BOX_RIGHT: xs = RC(-sz / sx); ys = R2(-sy / sx); break; - case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / sy); break; - case BOX_BOTTOM: xs = RC( sx / -sy); ys = R2( sz / sy); break; - } - - if (xs < 0.0) xs = 0.0; - if (xs >= 1.0) xs = 0.999; - if (ys < 0.0) ys = 0.0; - if (ys >= 1.0) ys = 0.999; - int sxs = xs * sw_cube_map_size; - int sys = ys * sw_cube_map_size; - *buf++ = scrp+side * scrsize + sys * sw_cube_map_size + sxs; - } - } -} -#if 0 -static void -rendercopy (void *dest) -{ - void *p = vid.buffer; - // XXX - vid.buffer = dest; - R_RenderView_ (); - vid.buffer = p; -} - -static void -renderside (byte *bufs, int side) -{ - mat4f_t camera; - mat4f_t camera_inverse; - mat4f_t rotinv; - - memcpy (camera, r_refdef.camera, sizeof (camera)); - memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse)); - mmulf (r_refdef.camera, camera, box_rotations[side]); - mat4ftranspose (rotinv, box_rotations[side]); - mmulf (r_refdef.camera_inverse, rotinv, camera_inverse); - - //FIXME see fixme in r_screen.c - r_refdef.frame.mat[0] = -r_refdef.camera[1]; - r_refdef.frame.mat[1] = r_refdef.camera[0]; - r_refdef.frame.mat[2] = r_refdef.camera[2]; - r_refdef.frame.mat[3] = r_refdef.camera[3]; - - float fov_x = r_refdef.fov_x; - float fov_y = r_refdef.fov_y; - unsigned width = vid.width; - unsigned height = vid.height; - vrect_t rect = r_refdef.vrect; - r_refdef.fov_x = r_refdef.fov_y = 90; - r_refdef.vrect.x = r_refdef.vrect.y = 0; - r_refdef.vrect.height = r_refdef.vrect.width = sw_cube_map_size; - vid.rowbytes = vid.height = vid.width = sw_cube_map_size; - R_ViewChanged (); - - rendercopy (bufs); - - vid.rowbytes = width; - r_refdef.vrect = rect; - vid.height = height; - vid.width = width; - r_refdef.fov_x = fov_x; - r_refdef.fov_y = fov_y; - - memcpy (r_refdef.camera, camera, sizeof (camera)); - memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); -} -#endif -static void -renderlookup (byte **offs, byte* bufs) -{ - framebuffer_t *fb = sw_ctx->framebuffer; - sw_framebuffer_t *swfb = fb->buffer; - byte *p = swfb->color; - unsigned x, y; - for (y = 0; y < fb->height; y++) { - for (x = 0; x < fb->width; x++, offs++) - p[x] = **offs; - p += swfb->rowbytes; - } -} - -static void -R_RenderViewFishEye (void) -{ - sw_cube_map_size = vid.height; - int width = vid.width; //r_refdef.vrect.width; - int height = vid.height; //r_refdef.vrect.height; - int scrsize = sw_cube_map_size * sw_cube_map_size; - int fov = scr_ffov->int_val; - int views = scr_fviews->int_val; - static int pwidth = -1; - static int pheight = -1; - static int pfov = -1; - static int pviews = -1; - static byte *scrbufs = NULL; - static byte **offs = NULL; - - if (fov < 1) fov = 1; - - if (pwidth != width || pheight != height || pfov != fov) { - if (scrbufs) free (scrbufs); - if (offs) free (offs); - // front|right|back|left|top|bottom - scrbufs = malloc (scrsize*6); - SYS_CHECKMEM (scrbufs); - offs = malloc (width*height*sizeof(byte*)); - SYS_CHECKMEM (offs); - pwidth = width; - pheight = height; - pfov = fov; - fisheyelookuptable (offs, width, height, scrbufs, fov*M_PI/180.0); - } - - if (views != pviews) { - pviews = views; - memset (scrbufs, 0, scrsize*6); - } -#if 0 - switch (views) { - case 6: renderside (scrbufs + scrsize * BOX_BEHIND, BOX_BEHIND); - case 5: renderside (scrbufs + scrsize * BOX_BOTTOM, BOX_BOTTOM); - case 4: renderside (scrbufs + scrsize * BOX_TOP, BOX_TOP); - case 3: renderside (scrbufs + scrsize * BOX_LEFT, BOX_LEFT); - case 2: renderside (scrbufs + scrsize * BOX_RIGHT, BOX_RIGHT); - default: renderside (scrbufs + scrsize * BOX_FRONT, BOX_FRONT); - } -#endif -#if 0 - memset (scrbufs + scrsize*0, 31, sw_cube_map_size); - memset (scrbufs + scrsize*1, 31, sw_cube_map_size); - memset (scrbufs + scrsize*2, 31, sw_cube_map_size); - memset (scrbufs + scrsize*3, 31, sw_cube_map_size); - memset (scrbufs + scrsize*4, 31, sw_cube_map_size); - memset (scrbufs + scrsize*5, 31, sw_cube_map_size); - for (int y = 0; y < sw_cube_map_size * 6; y++) { - scrbufs[y * sw_cube_map_size] = 31; - scrbufs[y * sw_cube_map_size + sw_cube_map_size - 1] = 31; - } -#endif - renderlookup (offs, scrbufs); -} - void R_ClearState (void) { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 4bcdcbc65..38ecf6afb 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -268,6 +268,11 @@ gl_draw_transparent (void) gl_R_DrawWaterSurfaces (); } +static void +gl_post_process (framebuffer_t *src) +{ +} + static void gl_set_2d (int scaled) { @@ -300,6 +305,12 @@ gl_end_frame (void) } } +static framebuffer_t * +gl_create_cube_map (int size) +{ + Sys_Error ("not implemented"); +} + static framebuffer_t * gl_create_frame_buffer (int width, int height) { @@ -348,9 +359,11 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_RenderEntities, gl_R_DrawParticles, gl_draw_transparent, + gl_post_process, gl_set_2d, gl_end_frame, + gl_create_cube_map, gl_create_frame_buffer, gl_bind_framebuffer, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 35eab3a20..d7eea168b 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -226,6 +226,11 @@ glsl_draw_transparent (void) glsl_R_DrawWaterSurfaces (); } +static void +glsl_post_process (framebuffer_t *src) +{ +} + static void glsl_set_2d (int scaled) { @@ -244,6 +249,12 @@ glsl_end_frame (void) qfeglFlush (); } +static framebuffer_t * +glsl_create_cube_map (int size) +{ + Sys_Error ("not implemented"); +} + static framebuffer_t * glsl_create_frame_buffer (int width, int height) { @@ -292,9 +303,11 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_RenderEntities, glsl_R_DrawParticles, glsl_draw_transparent, + glsl_post_process, glsl_set_2d, glsl_end_frame, + glsl_create_cube_map, glsl_create_frame_buffer, glsl_bind_framebuffer, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index d78c1b825..8c31e703e 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -157,14 +157,27 @@ sw_draw_transparent (void) } static void -sw_set_2d (int scaled) +sw_post_process (framebuffer_t *src) { - if (!scaled && r_dowarp) { + int bind = 0; + + if (scr_fisheye->int_val) { + R_RenderFisheye (src); + bind = 1; + } else if (r_dowarp) { D_WarpScreen (); + bind = 1; + } + if (bind) { sw_bind_framebuffer (0); } } +static void +sw_set_2d (int scaled) +{ +} + static void sw_end_frame (void) { @@ -198,6 +211,33 @@ sw_end_frame (void) sw_ctx->update (sw_ctx, &vrect); } +static framebuffer_t * +sw_create_cube_map (int side) +{ + size_t pixels = side * side; // per face + size_t size = sizeof (framebuffer_t) * 6; + size += sizeof (sw_framebuffer_t) * 6; + size += pixels * 6; // color buffer + // depth buffer, scan table and zspantable are shared between cube faces + // FIXME need *6 depth and zspan for multi-threaded + size += pixels * sizeof (short); // depth buffer + + framebuffer_t *cube = malloc (size); + __auto_type buffer_base = (sw_framebuffer_t *) &cube[6]; + byte *color_base = (byte *) &buffer_base[6]; + short *depth_base = (short *) (color_base + 6 * pixels); + for (int i = 0; i < 6; i++) { + cube[i].width = side; + cube[i].height = side; + __auto_type buffer = buffer_base + i; + cube[i].buffer = buffer; + buffer->color = color_base + i * pixels; + buffer->depth = depth_base; + buffer->rowbytes = side; + } + return cube; +} + static framebuffer_t * sw_create_frame_buffer (int width, int height) { @@ -297,9 +337,11 @@ vid_render_funcs_t sw_vid_render_funcs = { R_DrawEntitiesOnList, R_DrawParticles, sw_draw_transparent, + sw_post_process, sw_set_2d, sw_end_frame, + sw_create_cube_map, sw_create_frame_buffer, sw_bind_framebuffer, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 1990ce1ef..df86644dc 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -308,6 +308,11 @@ vulkan_draw_transparent (void) { } +static void +vulkan_post_process (framebuffer_t *src) +{ +} + static void vulkan_set_2d (int scaled) { @@ -418,6 +423,12 @@ vulkan_end_frame (void) vulkan_ctx->curFrame %= vulkan_ctx->frames.size; } +static framebuffer_t * +vulkan_create_cube_map (int size) +{ + Sys_Error ("not implemented"); +} + static framebuffer_t * vulkan_create_frame_buffer (int width, int height) { @@ -705,9 +716,11 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_draw_entities, vulkan_draw_particles, vulkan_draw_transparent, + vulkan_post_process, vulkan_set_2d, vulkan_end_frame, + vulkan_create_cube_map, vulkan_create_frame_buffer, vulkan_bind_framebuffer, From 7ca3b56620b88ef943cc84db90f6a22a624ce6b6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Mar 2022 15:53:46 +0900 Subject: [PATCH 2570/3664] [glsl] Fix a silly typo in a comment --- libs/video/renderer/glsl/glsl_bsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index eb8fdab4b..66658c8e6 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -1390,7 +1390,7 @@ glsl_R_LoadSkys (const char *sky) // a -90 degree rotation on the (quake) z-axis. This is taken care of in // the sky_matrix setup code. // However, from the player's perspective, skymaps have lf and rt - // swapped, but everythink makes sense if looking at the cube from outside + // swapped, but everything makes sense if looking at the cube from outside // along the positive y axis, with the front of the cube being the nearest // face. This matches nicely with Blender's default cube in front (num-1) // view. From 00362e9f4eb8261a457abf1caff7272cc274b288 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Mar 2022 20:35:29 +0900 Subject: [PATCH 2571/3664] [gl] Explicitly request compatibility profile And core profile for glsl --- include/vid_gl.h | 2 +- libs/video/renderer/vid_render_gl.c | 2 +- libs/video/renderer/vid_render_glsl.c | 2 +- libs/video/targets/vid_win_gl.c | 2 +- libs/video/targets/vid_x11_gl.c | 12 ++++++++++-- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/vid_gl.h b/include/vid_gl.h index 8b82ae069..26d445770 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -8,7 +8,7 @@ typedef struct gl_ctx_s { GL_context context; void (*load_gl) (void); void (*choose_visual) (struct gl_ctx_s *ctx); - void (*create_context) (struct gl_ctx_s *ctx); + void (*create_context) (struct gl_ctx_s *ctx, int core); void (*init_gl) (void); void *(*get_proc_address) (const char *name, qboolean crit); void (*end_rendering) (void); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 38ecf6afb..9647c01aa 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -147,7 +147,7 @@ gl_vid_render_choose_visual (void *data) static void gl_vid_render_create_context (void *data) { - gl_ctx->create_context (gl_ctx); + gl_ctx->create_context (gl_ctx, 0); } static vid_model_funcs_t model_funcs = { diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index d7eea168b..19c8d3c95 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -55,7 +55,7 @@ glsl_vid_render_choose_visual (void *data) static void glsl_vid_render_create_context (void *data) { - glsl_ctx->create_context (glsl_ctx); + glsl_ctx->create_context (glsl_ctx, 1); } static vid_model_funcs_t model_funcs = { diff --git a/libs/video/targets/vid_win_gl.c b/libs/video/targets/vid_win_gl.c index 1975b8741..8723225c8 100644 --- a/libs/video/targets/vid_win_gl.c +++ b/libs/video/targets/vid_win_gl.c @@ -117,7 +117,7 @@ wgl_set_pixel_format (void) } static void -wgl_create_context (gl_ctx_t *ctx) +wgl_create_context (gl_ctx_t *ctx, int core) { DWORD lasterror; diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index 7f6285506..a29b01d74 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -66,6 +66,12 @@ #define GLX_STENCIL_SIZE 13 // number of stencil bits #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 #define GLX_X_RENDERABLE 0x8012 #define GLX_DRAWABLE_TYPE 0x8010 @@ -187,12 +193,14 @@ glx_choose_visual (gl_ctx_t *ctx) } static void -glx_create_context (gl_ctx_t *ctx) +glx_create_context (gl_ctx_t *ctx, int core) { int attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 0, - //GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB + GLX_CONTEXT_PROFILE_MASK_ARB, + core ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB + : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, None }; XSync (x_disp, 0); From e263521330b054042af2552d802fbb2f7a8c2020 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Mar 2022 01:17:12 +0900 Subject: [PATCH 2572/3664] [glsl] Put #line after any #version lines in the chunks The GLSL compiler requires any #version lines to be the first (real) line of the program, even #line causes an error, so if the first line of the chunk starts with #version, insert the #line directive as the second line. --- libs/video/renderer/glsl/glsl_shader.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_shader.c b/libs/video/renderer/glsl/glsl_shader.c index c45494dc0..d7eace17a 100644 --- a/libs/video/renderer/glsl/glsl_shader.c +++ b/libs/video/renderer/glsl/glsl_shader.c @@ -129,8 +129,17 @@ GLSL_BuildShader (const char **effect_keys) Sys_Printf ("Unknown shader key: '%s'\n", dot); goto error; } - shader->strings[num] = nva ("#line %d\n%s", chunk->start_line, - chunk->text); + if (strncmp ("#version ", chunk->text, 9) == 0) { + const char *eol = strchr (chunk->text, '\n'); + int vline_len = eol ? eol - chunk->text + 1 : 0; + shader->strings[num] = nva ("%.*s#line %d\n%s", vline_len, + chunk->text, + chunk->start_line + 1, + chunk->text + vline_len); + } else { + shader->strings[num] = nva ("#line %d\n%s", chunk->start_line, + chunk->text); + } shader->src[num] = strdup (ekey->str); } dstring_delete (ekey); From 18aae8205eeef8c283c79a8c08967a6e5dc7c5bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Mar 2022 01:24:38 +0900 Subject: [PATCH 2573/3664] [glsl] Implement screen warp when in liquids Finally, after a decade :P Looks pretty good, too, and is (almost) properly scaled to the resolution (almost because the effect is a little squashed, but I think the sw renderer does the same). --- include/QF/GLSL/qf_funcs_list.h | 2 + include/QF/GLSL/qf_warp.h | 37 ++++++++ include/QF/Makemodule.am | 1 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/glsl/glsl_main.c | 2 + libs/video/renderer/glsl/glsl_warp.c | 114 +++++++++++++++++++++++ libs/video/renderer/glsl/quakeforge.glsl | 35 +++++++ libs/video/renderer/vid_render_glsl.c | 49 +++++++++- libs/video/targets/vid_x11_gl.c | 1 - 9 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 include/QF/GLSL/qf_warp.h create mode 100644 libs/video/renderer/glsl/glsl_warp.c diff --git a/include/QF/GLSL/qf_funcs_list.h b/include/QF/GLSL/qf_funcs_list.h index 7eab3ecdf..26adfea69 100644 --- a/include/QF/GLSL/qf_funcs_list.h +++ b/include/QF/GLSL/qf_funcs_list.h @@ -57,6 +57,8 @@ QFGL_NEED (void, glDepthMask, (GLboolean flag)) QFGL_NEED (void, glDepthRangef, (GLclampf zNear, GLclampf zFar)) QFGL_NEED (void, glDetachShader, (GLuint program, GLuint shader)) QFGL_NEED (void, glDisable, (GLenum cap)) +QFGL_NEED (void, glCreateVertexArrays, (GLsizei n, GLuint *arrays)) +QFGL_NEED (void, glBindVertexArray, (GLuint array)) QFGL_NEED (void, glDisableVertexAttribArray, (GLuint index)) QFGL_NEED (void, glDrawArrays, (GLenum mode, GLint first, GLsizei count)) QFGL_NEED (void, glDrawElements, (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)) diff --git a/include/QF/GLSL/qf_warp.h b/include/QF/GLSL/qf_warp.h new file mode 100644 index 000000000..3b91b7183 --- /dev/null +++ b/include/QF/GLSL/qf_warp.h @@ -0,0 +1,37 @@ +/* + qf_warp.h + + GLSL screen warp + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/3/24 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_GLSL_qf_warp_h +#define __QF_GLSL_qf_warp_h + +void glsl_InitWarp (void); +struct framebuffer_s; +void glsl_WarpScreen (struct framebuffer_s *fb); + +#endif//__QF_GLSL_qf_warp_h diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index c842cb050..1edf58746 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -109,6 +109,7 @@ include_qf_glsl = \ include/QF/GLSL/qf_sprite.h \ include/QF/GLSL/qf_textures.h \ include/QF/GLSL/qf_vid.h \ + include/QF/GLSL/qf_warp.h \ include/QF/GLSL/types.h include_qf_input = \ diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 065f7f0a0..0230080f4 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -118,6 +118,7 @@ libs_video_renderer_librender_glsl_la_SOURCES = \ libs/video/renderer/glsl/glsl_shader.c \ libs/video/renderer/glsl/glsl_sprite.c \ libs/video/renderer/glsl/glsl_textures.c \ + libs/video/renderer/glsl/glsl_warp.c \ libs/video/renderer/glsl/qfglsl.c \ libs/video/renderer/glsl/quakeforge.glsl \ libs/video/renderer/glsl/vid_common_glsl.c diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 8e62fbb07..f494c2ef6 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -58,6 +58,7 @@ #include "QF/GLSL/qf_particles.h" #include "QF/GLSL/qf_sprite.h" #include "QF/GLSL/qf_textures.h" +#include "QF/GLSL/qf_warp.h" #include "mod_internal.h" #include "r_internal.h" @@ -211,6 +212,7 @@ glsl_R_Init (void) glsl_R_InitIQM (); glsl_R_InitSprites (); glsl_R_InitParticles (); + glsl_InitWarp (); Skin_Init (); } diff --git a/libs/video/renderer/glsl/glsl_warp.c b/libs/video/renderer/glsl/glsl_warp.c new file mode 100644 index 000000000..d0e16727d --- /dev/null +++ b/libs/video/renderer/glsl/glsl_warp.c @@ -0,0 +1,114 @@ +/* + glsl_warp.c + + GLSL screen warp + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/3/24 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/cvar.h" +#include "QF/render.h" +#include "QF/sys.h" + +#include "QF/GLSL/defines.h" +#include "QF/GLSL/funcs.h" +#include "QF/GLSL/qf_vid.h" +#include "QF/GLSL/qf_warp.h" + +#include "r_internal.h" +#include "vid_gl.h" + +static const char *warp_vert_effects[] = +{ + "QuakeForge.Vertex.fstri", + 0 +}; + +static const char *warp_frag_effects[] = +{ + "QuakeForge.Math.const", + "QuakeForge.Fragment.screen.warp", + 0 +}; + +static struct { + int program; + GLuint vao; + shaderparam_t screenTex; + shaderparam_t time; +} warp = { + .screenTex = {"screenTex", 1}, + .time = {"time", 1}, +}; + +void +glsl_InitWarp (void) +{ + shader_t *vert_shader, *frag_shader; + int vert; + int frag; + + vert_shader = GLSL_BuildShader (warp_vert_effects); + frag_shader = GLSL_BuildShader (warp_frag_effects); + vert = GLSL_CompileShader ("scrwarp.vert", vert_shader, GL_VERTEX_SHADER); + frag = GLSL_CompileShader ("scrwarp.frag", frag_shader, GL_FRAGMENT_SHADER); + warp.program = GLSL_LinkProgram ("scrwarp", vert, frag); + GLSL_ResolveShaderParam (warp.program, &warp.screenTex); + GLSL_ResolveShaderParam (warp.program, &warp.time); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); + + qfeglCreateVertexArrays (1, &warp.vao); +} + +void +glsl_WarpScreen (framebuffer_t *fb) +{ + qfeglUseProgram (warp.program); + + qfeglUniform1f (warp.time.location, vr_data.realtime); + + gl_framebuffer_t *buffer = fb->buffer; + qfeglActiveTexture (GL_TEXTURE0 + 0); + qfeglBindTexture (GL_TEXTURE_2D, buffer->color); + + qfeglBindVertexArray (warp.vao); + qfeglDrawArrays (GL_TRIANGLES, 0, 3); + qfeglBindVertexArray (0); + + qfeglActiveTexture (GL_TEXTURE0 + 0); + qfeglDisable (GL_TEXTURE_2D); +} diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index 2a912fcb0..2a92840d4 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -551,3 +551,38 @@ main (void) col = texture2D (texture, st) * color * vec4 (l, 1.0); gl_FragColor = fogBlend (col); } + +-- Vertex.fstri +#version 130 + +out vec2 uv; + +void +main () +{ + // quake uses clockwise triangle order + float x = (gl_VertexID & 2); + float y = (gl_VertexID & 1); + uv = vec2(x, y*2); + gl_Position = vec4 (2, 4, 0, 0) * vec4 (x, y, 0, 0) - vec4 (1, 1, 0, -1); +} + +-- Fragment.screen.warp + +uniform sampler2D screenTex; +uniform float time; + +in vec2 uv; + +const float S = 0.15625; +const float F = 2.5; +const float A = 0.01; +const vec2 B = vec2 (1, 1); + +void +main () +{ + uv = uv * (1.0 - 2.0*A) + A * (B + sin ((time * S + F * uv.yx) * 2.0*PI)); + vec4 c = texture2D (screenTex, uv); + gl_FragColor = c;//vec4(uv, c.x, 1); +} diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 19c8d3c95..02166fd1a 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -38,6 +38,7 @@ #include "QF/GLSL/qf_main.h" #include "QF/GLSL/qf_particles.h" #include "QF/GLSL/qf_vid.h" +#include "QF/GLSL/qf_warp.h" #include "mod_internal.h" #include "r_internal.h" @@ -229,6 +230,15 @@ glsl_draw_transparent (void) static void glsl_post_process (framebuffer_t *src) { + qfeglBindFramebuffer (GL_FRAMEBUFFER, 0); + if (r_dowarp) { + glsl_WarpScreen (src); + + gl_framebuffer_t *buffer = src->buffer; + qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); + qfeglClear (GL_DEPTH_BUFFER_BIT); + } + qfeglBindFramebuffer (GL_FRAMEBUFFER, 0); } static void @@ -258,12 +268,49 @@ glsl_create_cube_map (int size) static framebuffer_t * glsl_create_frame_buffer (int width, int height) { - Sys_Error ("not implemented"); + size_t size = sizeof (framebuffer_t) + sizeof (gl_framebuffer_t); + + framebuffer_t *fb = malloc (size); + fb->width = width; + fb->height = height; + __auto_type buffer = (gl_framebuffer_t *) &fb[1]; + fb->buffer = buffer; + qfeglGenFramebuffers (1, &buffer->handle); + + GLuint tex[2]; + qfeglGenTextures (2, tex); + + buffer->color = tex[0]; + buffer->depth = tex[1]; + + qfeglBindTexture (GL_TEXTURE_2D, buffer->color); + qfeglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, 0); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + qfeglBindTexture (GL_TEXTURE_2D, buffer->depth); + qfeglTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); + + qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); + qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, buffer->color, 0); + qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, buffer->depth, 0); + + qfeglBindFramebuffer (GL_FRAMEBUFFER, 0); + return fb; } static void glsl_bind_framebuffer (framebuffer_t *framebuffer) { + gl_framebuffer_t *buffer = framebuffer->buffer; + qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); + + vrect_t r = { 0, 0, framebuffer->width, framebuffer->height }; + R_SetVrect (&r, &r_refdef.vrect, 0); + R_ViewChanged (); } vid_render_funcs_t glsl_vid_render_funcs = { diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index a29b01d74..30bf0aa19 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -189,7 +189,6 @@ glx_choose_visual (gl_ctx_t *ctx) Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth visual"); } x_vis = x_visinfo->visual; - printf ("%p\n", x_vis); } static void From 286344c7b6edcb61a6552c7aacda2b57bc18f84e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Mar 2022 12:22:16 +0900 Subject: [PATCH 2574/3664] [glsl] Implement fisheye rendering The code dealing with state is a bit of a mess, but everything is working nicely. Get around 400fps when all 6 faces need to be rendered (no surprise: it should be about 1/6 of that for normal rendering). The messy state handling code did not come as a surprise as I suspected there were various mistakes in my scene rendering "recipe", and fisheye highlighted them nicely (I'm sure getting this stuff working in Vulkan will highlight even more issues). --- include/QF/GLSL/qf_fisheye.h | 37 +++++++ include/QF/Makemodule.am | 1 + include/r_internal.h | 8 +- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/glsl/glsl_fisheye.c | 121 +++++++++++++++++++++++ libs/video/renderer/glsl/glsl_main.c | 2 + libs/video/renderer/glsl/quakeforge.glsl | 21 ++++ libs/video/renderer/r_screen.c | 4 + libs/video/renderer/vid_render_glsl.c | 90 ++++++++++++++--- 9 files changed, 269 insertions(+), 16 deletions(-) create mode 100644 include/QF/GLSL/qf_fisheye.h create mode 100644 libs/video/renderer/glsl/glsl_fisheye.c diff --git a/include/QF/GLSL/qf_fisheye.h b/include/QF/GLSL/qf_fisheye.h new file mode 100644 index 000000000..359606f25 --- /dev/null +++ b/include/QF/GLSL/qf_fisheye.h @@ -0,0 +1,37 @@ +/* + qf_fisheye.h + + GLSL screen fisheye + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/3/25 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_GLSL_qf_fisheye_h +#define __QF_GLSL_qf_fisheye_h + +void glsl_InitFisheye (void); +struct framebuffer_s; +void glsl_FisheyeScreen (struct framebuffer_s *fb); + +#endif//__QF_GLSL_qf_fisheye_h diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 1edf58746..537d03001 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -101,6 +101,7 @@ include_qf_glsl = \ include/QF/GLSL/qf_alias.h \ include/QF/GLSL/qf_bsp.h \ include/QF/GLSL/qf_draw.h \ + include/QF/GLSL/qf_fisheye.h \ include/QF/GLSL/qf_funcs_list.h \ include/QF/GLSL/qf_iqm.h \ include/QF/GLSL/qf_lightmap.h \ diff --git a/include/r_internal.h b/include/r_internal.h index c1c01bf0c..c4b5a15b7 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -81,13 +81,15 @@ int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, mspriteframe_t *R_GetSpriteFrame (const msprite_t *sprite, const animation_t *animation); -// These correspond to the standard box sides for OpenGL cube maps +// These correspond to the standard box sides for OpenGL cube maps but with +// TOP and BOTTOM swapped due to lelt/right handed systems (quake/gl are right, +// cube maps are left) #define BOX_FRONT 4 #define BOX_RIGHT 0 #define BOX_BEHIND 5 #define BOX_LEFT 1 -#define BOX_TOP 2 -#define BOX_BOTTOM 3 +#define BOX_TOP 3 +#define BOX_BOTTOM 2 void R_RenderFisheye (framebuffer_t *cube); #endif//__r_internal_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 0230080f4..aa4119ec6 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -110,6 +110,7 @@ libs_video_renderer_librender_glsl_la_SOURCES = \ libs/video/renderer/glsl/glsl_alias.c \ libs/video/renderer/glsl/glsl_bsp.c \ libs/video/renderer/glsl/glsl_draw.c \ + libs/video/renderer/glsl/glsl_fisheye.c \ libs/video/renderer/glsl/glsl_iqm.c \ libs/video/renderer/glsl/glsl_lightmap.c \ libs/video/renderer/glsl/glsl_main.c \ diff --git a/libs/video/renderer/glsl/glsl_fisheye.c b/libs/video/renderer/glsl/glsl_fisheye.c new file mode 100644 index 000000000..2635d8ffe --- /dev/null +++ b/libs/video/renderer/glsl/glsl_fisheye.c @@ -0,0 +1,121 @@ +/* + glsl_fisheye.c + + GLSL screen fisheye + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/3/25 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/cvar.h" +#include "QF/render.h" +#include "QF/sys.h" + +#include "QF/GLSL/defines.h" +#include "QF/GLSL/funcs.h" +#include "QF/GLSL/qf_vid.h" +#include "QF/GLSL/qf_fisheye.h" + +#include "r_internal.h" +#include "vid_gl.h" + +static const char *fisheye_vert_effects[] = +{ + "QuakeForge.Vertex.fstri", + 0 +}; + +static const char *fisheye_frag_effects[] = +{ + "QuakeForge.Math.const", + "QuakeForge.Fragment.screen.fisheye", + 0 +}; + +static struct { + int program; + GLuint vao; + shaderparam_t screenTex; + shaderparam_t fov; + shaderparam_t aspect; +} fisheye = { + .screenTex = {"screenTex", 1}, + .fov = {"fov", 1}, + .aspect = {"aspect", 1}, +}; + +void +glsl_InitFisheye (void) +{ + shader_t *vert_shader, *frag_shader; + int vert; + int frag; + + vert_shader = GLSL_BuildShader (fisheye_vert_effects); + frag_shader = GLSL_BuildShader (fisheye_frag_effects); + vert = GLSL_CompileShader ("scrfisheye.vert", vert_shader, + GL_VERTEX_SHADER); + frag = GLSL_CompileShader ("scrfisheye.frag", frag_shader, + GL_FRAGMENT_SHADER); + fisheye.program = GLSL_LinkProgram ("scrfisheye", vert, frag); + GLSL_ResolveShaderParam (fisheye.program, &fisheye.screenTex); + GLSL_ResolveShaderParam (fisheye.program, &fisheye.fov); + GLSL_ResolveShaderParam (fisheye.program, &fisheye.aspect); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); + + qfeglCreateVertexArrays (1, &fisheye.vao); +} + +void +glsl_FisheyeScreen (framebuffer_t *fb) +{ + qfeglUseProgram (fisheye.program); + + qfeglUniform1f (fisheye.fov.location, scr_ffov->value * M_PI / 360); + qfeglUniform1f (fisheye.aspect.location, + (float) r_refdef.vrect.height / r_refdef.vrect.width); + + gl_framebuffer_t *buffer = fb->buffer; + qfeglActiveTexture (GL_TEXTURE0 + 0); + qfeglBindTexture (GL_TEXTURE_CUBE_MAP, buffer->color); + + qfeglBindVertexArray (fisheye.vao); + qfeglDrawArrays (GL_TRIANGLES, 0, 3); + qfeglBindVertexArray (0); + + qfeglActiveTexture (GL_TEXTURE0 + 0); + qfeglDisable (GL_TEXTURE_2D); +} diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index f494c2ef6..a89f1439e 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -52,6 +52,7 @@ #include "QF/GLSL/qf_alias.h" #include "QF/GLSL/qf_bsp.h" #include "QF/GLSL/qf_draw.h" +#include "QF/GLSL/qf_fisheye.h" #include "QF/GLSL/qf_iqm.h" #include "QF/GLSL/qf_lightmap.h" #include "QF/GLSL/qf_main.h" @@ -212,6 +213,7 @@ glsl_R_Init (void) glsl_R_InitIQM (); glsl_R_InitSprites (); glsl_R_InitParticles (); + glsl_InitFisheye (); glsl_InitWarp (); Skin_Init (); } diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index 2a92840d4..7b284c302 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -586,3 +586,24 @@ main () vec4 c = texture2D (screenTex, uv); gl_FragColor = c;//vec4(uv, c.x, 1); } + +-- Fragment.screen.fisheye + +uniform samplerCube screenTex; +uniform float fov; +uniform float aspect; + +in vec2 uv; + +void +main () +{ + // slight offset on y is to avoid the singularity straight aheat + vec2 xy = (2.0 * uv - vec2 (1, 1.00002)) * (vec2(1, -aspect)); + float r = sqrt (dot (xy, xy)); + vec2 cs = vec2 (cos (r * fov), sin (r * fov)); + vec3 dir = vec3 (cs.y * xy / r, cs.x); + + vec4 c = textureCube(screenTex, dir); + gl_FragColor = c;// * 0.001 + vec4(dir, 1); +} diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index d2f47edce..cf098233f 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -209,6 +209,10 @@ render_side (int side) r_refdef.frame.mat[2] = r_refdef.camera[2]; r_refdef.frame.mat[3] = r_refdef.camera[3]; + refdef_t *refdef = r_data->refdef; + R_SetFrustum (refdef->frustum, &refdef->frame, + refdef->fov_x, refdef->fov_y); + r_data->refdef->fov_x = r_data->refdef->fov_y = 90; r_funcs->bind_framebuffer (&fisheye_cube_map[side]); render_scene (); diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 02166fd1a..aeb936d40 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -28,6 +28,8 @@ # include "config.h" #endif +#include "QF/cvar.h" + #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -35,6 +37,7 @@ #include "QF/GLSL/defines.h" #include "QF/GLSL/qf_bsp.h" #include "QF/GLSL/qf_draw.h" +#include "QF/GLSL/qf_fisheye.h" #include "QF/GLSL/qf_main.h" #include "QF/GLSL/qf_particles.h" #include "QF/GLSL/qf_vid.h" @@ -218,6 +221,7 @@ glsl_begin_frame (void) static void glsl_render_view (void) { + qfeglClear (GL_DEPTH_BUFFER_BIT); glsl_R_RenderView (); } @@ -227,18 +231,22 @@ glsl_draw_transparent (void) glsl_R_DrawWaterSurfaces (); } +static void glsl_bind_framebuffer (framebuffer_t *fb); + static void glsl_post_process (framebuffer_t *src) { - qfeglBindFramebuffer (GL_FRAMEBUFFER, 0); - if (r_dowarp) { + glsl_bind_framebuffer (0); + float x = r_refdef.vrect.x; + float y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); + float w = r_refdef.vrect.width; + float h = r_refdef.vrect.height; + qfeglViewport (x, y, w, h); + if (scr_fisheye->int_val) { + glsl_FisheyeScreen (src); + } else if (r_dowarp) { glsl_WarpScreen (src); - - gl_framebuffer_t *buffer = src->buffer; - qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); - qfeglClear (GL_DEPTH_BUFFER_BIT); } - qfeglBindFramebuffer (GL_FRAMEBUFFER, 0); } static void @@ -260,9 +268,53 @@ glsl_end_frame (void) } static framebuffer_t * -glsl_create_cube_map (int size) +glsl_create_cube_map (int side) { - Sys_Error ("not implemented"); + GLuint tex[2]; + qfeglGenTextures (2, tex); + + qfeglBindTexture (GL_TEXTURE_CUBE_MAP, tex[0]); + for (int i = 0; i < 6; i++) { + qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA, + side, side, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } + qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + qfeglBindTexture (GL_TEXTURE_2D, tex[1]); + qfeglTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, side, side, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + size_t size = sizeof (framebuffer_t) * 6; + size += sizeof (gl_framebuffer_t) * 6; + + framebuffer_t *cube = malloc (size); + __auto_type buffer_base = (gl_framebuffer_t *) &cube[6]; + for (int i = 0; i < 6; i++) { + cube[i].width = side; + cube[i].height = side; + __auto_type buffer = buffer_base + i; + cube[i].buffer = buffer; + + buffer->color = tex[0]; + buffer->depth = tex[1]; + qfeglGenFramebuffers (1, &buffer->handle); + + qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); + qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + buffer->color, 0); + qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, buffer->depth, 0); + } + qfeglBindFramebuffer (GL_FRAMEBUFFER, 0); + return cube; } static framebuffer_t * @@ -287,10 +339,13 @@ glsl_create_frame_buffer (int width, int height) qfeglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qfeglBindTexture (GL_TEXTURE_2D, buffer->depth); qfeglTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); qfeglFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -305,12 +360,21 @@ glsl_create_frame_buffer (int width, int height) static void glsl_bind_framebuffer (framebuffer_t *framebuffer) { - gl_framebuffer_t *buffer = framebuffer->buffer; - qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); + unsigned width = vr_data.vid->width; + unsigned height = vr_data.vid->height; + if (!framebuffer) { + qfeglBindFramebuffer (GL_FRAMEBUFFER, 0); + } else { + gl_framebuffer_t *buffer = framebuffer->buffer; + qfeglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); - vrect_t r = { 0, 0, framebuffer->width, framebuffer->height }; + width = framebuffer->width; + height = framebuffer->height; + } + + vrect_t r = { 0, 0, width, height }; R_SetVrect (&r, &r_refdef.vrect, 0); - R_ViewChanged (); + glsl_R_ViewChanged (); } vid_render_funcs_t glsl_vid_render_funcs = { From 25e6865fa5fd7f26c6201b4a2974361c7dc3a1a6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Mar 2022 14:48:01 +0900 Subject: [PATCH 2575/3664] [glsl] Update particle arrays when maximum changes The cvar setup for particles is a bit wonky in that the arrays get initialized using the default max particle count but never updated. Though things could be improved some more, this solution works (and has been more or less copied to gl, but I couldn't reproduce the crash there, or even the valgrind error). --- libs/video/renderer/gl/gl_dyn_part.c | 20 +++++++--- libs/video/renderer/glsl/glsl_particles.c | 45 ++++++++++++++--------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index b64cd9481..151a2ed72 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -63,23 +63,23 @@ static int pVAsize; static int *pVAindices; static varray_t2f_c4ub_v3f_t *particleVertexArray; -void -gl_R_InitParticles (void) +static void +alloc_arrays (psystem_t *ps) { int i; - if (r_psystem.maxparticles && r_init) { + if (ps->maxparticles && r_init) { if (vaelements) { partUseVA = 0; - pVAsize = r_psystem.maxparticles * 4; + pVAsize = ps->maxparticles * 4; Sys_MaskPrintf (SYS_dev, "Particles: Vertex Array use disabled.\n"); } else { if (vaelements > 3) pVAsize = min ((unsigned int) (vaelements - (vaelements % 4)), - r_psystem.maxparticles * 4); + ps->maxparticles * 4); else if (vaelements >= 0) - pVAsize = r_psystem.maxparticles * 4; + pVAsize = ps->maxparticles * 4; Sys_MaskPrintf (SYS_dev, "Particles: %i maximum vertex elements.\n", pVAsize); @@ -109,6 +109,12 @@ gl_R_InitParticles (void) } } +void +gl_R_InitParticles (void) +{ + alloc_arrays (&r_psystem); +} + void gl_R_DrawParticles (psystem_t *psystem) { @@ -238,12 +244,14 @@ static void r_particles_f (cvar_t *var) { R_MaxParticlesCheck (var, r_particles_max); + alloc_arrays (&r_psystem); } static void r_particles_max_f (cvar_t *var) { R_MaxParticlesCheck (r_particles, var); + alloc_arrays (&r_psystem); } void diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 74957ce3e..89645e72c 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -63,6 +63,7 @@ # define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 #endif +static uint32_t maxparticles; static GLushort *pVAindices; static partvert_t *particleVertexArray; @@ -130,11 +131,34 @@ static struct { {"fog", 1}, }; +static void +alloc_arrays (psystem_t *ps) +{ + if (ps->maxparticles > maxparticles) { + maxparticles = ps->maxparticles; + if (particleVertexArray) + free (particleVertexArray); + particleVertexArray = calloc (ps->maxparticles * 4, + sizeof (partvert_t)); + + if (pVAindices) + free (pVAindices); + pVAindices = calloc (ps->maxparticles * 6, sizeof (GLushort)); + for (uint32_t i = 0; i < ps->maxparticles; i++) { + pVAindices[i * 6 + 0] = i * 4 + 0; + pVAindices[i * 6 + 1] = i * 4 + 1; + pVAindices[i * 6 + 2] = i * 4 + 2; + pVAindices[i * 6 + 3] = i * 4 + 0; + pVAindices[i * 6 + 4] = i * 4 + 2; + pVAindices[i * 6 + 5] = i * 4 + 3; + } + } +} + void glsl_R_InitParticles (void) { shader_t *vert_shader, *frag_shader; - unsigned i; int vert; int frag; float v[2] = {0, 0}; @@ -196,22 +220,7 @@ glsl_R_InitParticles (void) GL_UNSIGNED_BYTE, tex->data); free (tex); - if (particleVertexArray) - free (particleVertexArray); - particleVertexArray = calloc (r_psystem.maxparticles * 4, - sizeof (partvert_t)); - - if (pVAindices) - free (pVAindices); - pVAindices = calloc (r_psystem.maxparticles * 6, sizeof (GLushort)); - for (i = 0; i < r_psystem.maxparticles; i++) { - pVAindices[i * 6 + 0] = i * 4 + 0; - pVAindices[i * 6 + 1] = i * 4 + 1; - pVAindices[i * 6 + 2] = i * 4 + 2; - pVAindices[i * 6 + 3] = i * 4 + 0; - pVAindices[i * 6 + 4] = i * 4 + 2; - pVAindices[i * 6 + 5] = i * 4 + 3; - } + alloc_arrays (&r_psystem); } static void @@ -426,12 +435,14 @@ static void r_particles_f (cvar_t *var) { R_MaxParticlesCheck (var, r_particles_max); + alloc_arrays (&r_psystem); } static void r_particles_max_f (cvar_t *var) { R_MaxParticlesCheck (r_particles, var); + alloc_arrays (&r_psystem); } void From f2bc5b560fcee63b8847323f2a89e8d9ade9cdb8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Mar 2022 00:29:34 +0900 Subject: [PATCH 2576/3664] [renderer] Clean up post processing While it's not where I want it to be, it at least now no longer messes with frame buffer binding or the view ports. This involved switching around buffers in D_WarpScreen so that the main buffer could be bound before post-processing. --- include/QF/plugin/vid_render.h | 2 ++ include/d_iface.h | 2 +- libs/video/renderer/r_screen.c | 15 +++++---------- libs/video/renderer/sw/d_scan.c | 14 +++++++------- libs/video/renderer/vid_render_gl.c | 6 ++++++ libs/video/renderer/vid_render_glsl.c | 16 +++++++++++----- libs/video/renderer/vid_render_sw.c | 15 +++++++-------- libs/video/renderer/vid_render_vulkan.c | 6 ++++++ 8 files changed, 45 insertions(+), 31 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 3cb8b46b1..e7027d07d 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -41,6 +41,7 @@ struct mod_alias_ctx_s; struct mod_sprite_ctx_s; struct entqueue_s; struct framebuffer_s; +struct vrect_s; /* All video plugins must export these functions @@ -120,6 +121,7 @@ typedef struct vid_render_funcs_s { struct framebuffer_s *(*create_cube_map) (int side); struct framebuffer_s *(*create_frame_buffer) (int width, int height); void (*bind_framebuffer) (struct framebuffer_s *framebuffer); + void (*set_viewport) (const struct vrect_s *view); vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/d_iface.h b/include/d_iface.h index 7f12523ac..77529dc55 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -159,7 +159,7 @@ void D_Init_Cvars (void); void D_ViewChanged (void); void D_SetupFrame (void); void D_TurnZOn (void); -void D_WarpScreen (void); +void D_WarpScreen (framebuffer_t *src); void D_FillRect (vrect_t *vrect, int color); void D_DrawRect (void); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index cf098233f..4de6c3881 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -221,15 +221,6 @@ render_side (int side) memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); } -/* - SCR_UpdateScreen - - This is called every frame, and can also be called explicitly to flush - text to the screen. - - WARNING: be very careful calling this from elsewhere, because the refresh - needs almost the entire 256k of stack space! -*/ void SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) { @@ -307,10 +298,14 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) default:render_side (BOX_FRONT); } r_funcs->bind_framebuffer (0); + r_funcs->set_viewport (&r_refdef.vrect); r_funcs->post_process (fisheye_cube_map); } else { render_scene (); - r_funcs->post_process (warp_buffer); + if (r_dowarp) { + r_funcs->bind_framebuffer (0); + r_funcs->post_process (warp_buffer); + } } r_funcs->set_2d (0); view_draw (r_data->scr_view); diff --git a/libs/video/renderer/sw/d_scan.c b/libs/video/renderer/sw/d_scan.c index 65eda134c..bb3151500 100644 --- a/libs/video/renderer/sw/d_scan.c +++ b/libs/video/renderer/sw/d_scan.c @@ -48,9 +48,9 @@ int r_turb_spancount; the sine warp, to keep the edges from wrapping */ void -D_WarpScreen (void) +D_WarpScreen (framebuffer_t *src) { - sw_framebuffer_t *_swfb = sw_ctx->framebuffer->buffer; + sw_framebuffer_t *buffer = src->buffer; int w, h; int u, v; int scr_x = vr_data.scr_view->xpos; @@ -61,8 +61,8 @@ D_WarpScreen (void) int *turb; int *col; byte **row; - byte *color = _swfb->color; - int rowbytes = _swfb->rowbytes; + byte *color = buffer->color; + int rowbytes = buffer->rowbytes; /* FIXME: allocate these arrays properly */ byte *rowptr[MAXHEIGHT + AMP2 * 2]; @@ -76,7 +76,7 @@ D_WarpScreen (void) hratio = h / (float) scr_h; for (v = 0; v < scr_h + AMP2 * 2; v++) { - rowptr[v] = d_viewbuffer + (0*r_refdef.vrect.y * d_rowbytes) + + rowptr[v] = color + (0*r_refdef.vrect.y * rowbytes) + (d_rowbytes * (int) ((float) v * hratio * h / (h + AMP2 * 2))); } @@ -86,9 +86,9 @@ D_WarpScreen (void) } turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = color + scr_y * rowbytes + scr_x; + dest = d_viewbuffer + scr_y * d_rowbytes + scr_x; - for (v = 0; v < scr_h; v++, dest += rowbytes) { + for (v = 0; v < scr_h; v++, dest += d_rowbytes) { col = &column[turb[v]]; row = &rowptr[v]; for (u = 0; u < scr_w; u += 4) { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 9647c01aa..798b3bac7 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -322,6 +322,11 @@ gl_bind_framebuffer (framebuffer_t *framebuffer) { } +static void +gl_set_viewport (const vrect_t *view) +{ +} + vid_render_funcs_t gl_vid_render_funcs = { gl_vid_render_init, gl_Draw_Character, @@ -366,6 +371,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_create_cube_map, gl_create_frame_buffer, gl_bind_framebuffer, + gl_set_viewport, &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index aeb936d40..58f72e5ad 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -237,11 +237,6 @@ static void glsl_post_process (framebuffer_t *src) { glsl_bind_framebuffer (0); - float x = r_refdef.vrect.x; - float y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); - float w = r_refdef.vrect.width; - float h = r_refdef.vrect.height; - qfeglViewport (x, y, w, h); if (scr_fisheye->int_val) { glsl_FisheyeScreen (src); } else if (r_dowarp) { @@ -377,6 +372,16 @@ glsl_bind_framebuffer (framebuffer_t *framebuffer) glsl_R_ViewChanged (); } +static void +glsl_set_viewport (const vrect_t *view) +{ + float x = view->x; + float y = vid.height - (view->y + view->height); + float w = view->width; + float h = view->height; + qfeglViewport (x, y, w, h); +} + vid_render_funcs_t glsl_vid_render_funcs = { glsl_vid_render_init, glsl_Draw_Character, @@ -421,6 +426,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_create_cube_map, glsl_create_frame_buffer, glsl_bind_framebuffer, + glsl_set_viewport, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 8c31e703e..bfc881de6 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -159,17 +159,10 @@ sw_draw_transparent (void) static void sw_post_process (framebuffer_t *src) { - int bind = 0; - if (scr_fisheye->int_val) { R_RenderFisheye (src); - bind = 1; } else if (r_dowarp) { - D_WarpScreen (); - bind = 1; - } - if (bind) { - sw_bind_framebuffer (0); + D_WarpScreen (src); } } @@ -300,6 +293,11 @@ sw_bind_framebuffer (framebuffer_t *framebuffer) } } +static void +sw_set_viewport (const vrect_t *view) +{ +} + vid_render_funcs_t sw_vid_render_funcs = { sw_vid_render_init, Draw_Character, @@ -344,6 +342,7 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_create_cube_map, sw_create_frame_buffer, sw_bind_framebuffer, + sw_set_viewport, &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index df86644dc..95fdb8642 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -440,6 +440,11 @@ vulkan_bind_framebuffer (framebuffer_t *framebuffer) { } +static void +vulkan_set_viewport (const vrect_t *view) +{ +} + static int is_bgr (VkFormat format) { @@ -723,6 +728,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_create_cube_map, vulkan_create_frame_buffer, vulkan_bind_framebuffer, + vulkan_set_viewport, &model_funcs }; From 77a797d04b2fb65aa24b0dc5e5ecd96dd594da6f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Mar 2022 09:41:58 +0900 Subject: [PATCH 2577/3664] [renderer] Clean up viewport setting Software is still a mess, and vulkan never supported viewsize, but otherwise everything seems fine. --- libs/video/renderer/gl/gl_rmain.c | 14 -------------- libs/video/renderer/glsl/glsl_main.c | 7 ------- libs/video/renderer/r_screen.c | 4 ++++ libs/video/renderer/vid_render_gl.c | 5 +++++ libs/video/renderer/vid_render_glsl.c | 8 ++++---- libs/video/renderer/vulkan/vulkan_matrices.c | 6 ------ 6 files changed, 13 insertions(+), 31 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 325def941..61dfe7c0c 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -255,24 +255,10 @@ static void R_SetupGL_Viewport_and_Perspective (void) { float screenaspect; - int x, y2, w, h; - // set up viewpoint qfglMatrixMode (GL_PROJECTION); qfglLoadIdentity (); - if (gl_envmap) { - x = y2 = 0; - w = h = 256; - } else { - x = r_refdef.vrect.x; - y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); - - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - } -// printf ("glViewport(%d, %d, %d, %d)\n", glx + x, gly + y2, w, h); - qfglViewport (x, y2, w, h); screenaspect = r_refdef.vrect.width / (float) r_refdef.vrect.height; MYgluPerspective (r_refdef.fov_y, screenaspect, r_nearclip->value, r_farclip->value); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index a89f1439e..c0195d394 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -98,7 +98,6 @@ glsl_R_ViewChanged (void) static void R_SetupView (void) { - float x, y, w, h; static mat4f_t z_up = { { 0, 0, 1, 0}, {-1, 0, 0, 0}, @@ -106,12 +105,6 @@ R_SetupView (void) { 0, 0, 0, 1}, }; - x = r_refdef.vrect.x; - y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - qfeglViewport (x, y, w, h); - mmulf (glsl_view, z_up, r_refdef.camera_inverse); qfeglEnable (GL_CULL_FACE); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 4de6c3881..5de3b8184 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -289,6 +289,9 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) r_funcs->bind_framebuffer (warp_buffer); } if (scr_fisheye->int_val) { + int side = fisheye_cube_map->width; + vrect_t feye = { 0, 0, side, side }; + r_funcs->set_viewport (&feye); switch (scr_fviews->int_val) { case 6: render_side (BOX_BEHIND); case 5: render_side (BOX_BOTTOM); @@ -301,6 +304,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) r_funcs->set_viewport (&r_refdef.vrect); r_funcs->post_process (fisheye_cube_map); } else { + r_funcs->set_viewport (&r_refdef.vrect); render_scene (); if (r_dowarp) { r_funcs->bind_framebuffer (0); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 798b3bac7..c09af57b1 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -325,6 +325,11 @@ gl_bind_framebuffer (framebuffer_t *framebuffer) static void gl_set_viewport (const vrect_t *view) { + int x = r_refdef.vrect.x; + int y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); + int w = r_refdef.vrect.width; + int h = r_refdef.vrect.height; + qfglViewport (x, y2, w, h); } vid_render_funcs_t gl_vid_render_funcs = { diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 58f72e5ad..2c6fa374c 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -375,10 +375,10 @@ glsl_bind_framebuffer (framebuffer_t *framebuffer) static void glsl_set_viewport (const vrect_t *view) { - float x = view->x; - float y = vid.height - (view->y + view->height); - float w = view->width; - float h = view->height; + int x = view->x; + int y = vid.height - (view->y + view->height); + int w = view->width; + int h = view->height; qfeglViewport (x, y, w, h); } diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 40ad0c066..79ca29906 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -73,12 +73,6 @@ setup_view (vulkan_ctx_t *ctx) { 0, 0, 0, 1}, }; - /*x = r_refdef.vrect.x; - y = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); - w = r_refdef.vrect.width; - h = r_refdef.vrect.height; - qfeglViewport (x, y, w, h);*/ - mmulf (view, z_up, r_refdef.camera_inverse); Vulkan_SetViewMatrix (ctx, view); } From 303756b41bce935f8dfaede81806518b062cf051 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Mar 2022 09:43:54 +0900 Subject: [PATCH 2578/3664] [gl] Remove the envmap command It has never worked, but it should be easy enough to implement for all renderers since fisheye does the same thing. --- include/QF/GL/qf_rmain.h | 1 - libs/video/renderer/gl/gl_rmain.c | 3 -- libs/video/renderer/gl/gl_rmisc.c | 61 ------------------------------- 3 files changed, 65 deletions(-) diff --git a/include/QF/GL/qf_rmain.h b/include/QF/GL/qf_rmain.h index 910f98b33..8aeb4c898 100644 --- a/include/QF/GL/qf_rmain.h +++ b/include/QF/GL/qf_rmain.h @@ -33,7 +33,6 @@ struct cvar_s; struct entity_s; -extern qboolean gl_envmap; extern int c_brush_polys, c_alias_polys; extern float gl_modelalpha; diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 61dfe7c0c..6ed36295a 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -68,8 +68,6 @@ #include "varrays.h" #include "vid_gl.h" -qboolean gl_envmap; // true during envmap command capture - int gl_mirrortexturenum; // quake texturenum, not gltexturenum plane_t *gl_mirror_plane; @@ -180,7 +178,6 @@ R_DrawViewModel (void) entity_t *ent = vr_data.view_model; if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val - || gl_envmap || !r_drawentities->int_val || !ent->renderer.model) return; diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 5694f07c5..65dbf5a54 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -71,66 +71,6 @@ #include "varrays.h" #include "vid_gl.h" -/* - R_Envmap_f - - Grab six views for environment mapping tests -*/ -static void -R_Envmap_f (void) -{ - /*FIXME update for simd - byte buffer[256 * 256 * 4]; - - qfglDrawBuffer (GL_FRONT); - qfglReadBuffer (GL_FRONT); - gl_envmap = true; - - r_refdef.vrect.x = 0; - r_refdef.vrect.y = 0; - r_refdef.vrect.width = 256; - r_refdef.vrect.height = 256; - - r_refdef.viewangles[0] = 0; - r_refdef.viewangles[1] = 0; - r_refdef.viewangles[2] = 0; - gl_R_RenderView (); - qfglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - QFS_WriteFile ("env0.rgb", buffer, sizeof (buffer)); - - r_refdef.viewangles[1] = 90; - gl_R_RenderView (); - qfglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - QFS_WriteFile ("env1.rgb", buffer, sizeof (buffer)); - - r_refdef.viewangles[1] = 180; - gl_R_RenderView (); - qfglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - QFS_WriteFile ("env2.rgb", buffer, sizeof (buffer)); - - r_refdef.viewangles[1] = 270; - gl_R_RenderView (); - qfglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - QFS_WriteFile ("env3.rgb", buffer, sizeof (buffer)); - - r_refdef.viewangles[0] = -90; - r_refdef.viewangles[1] = 0; - gl_R_RenderView (); - qfglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - QFS_WriteFile ("env4.rgb", buffer, sizeof (buffer)); - - r_refdef.viewangles[0] = 90; - r_refdef.viewangles[1] = 0; - gl_R_RenderView (); - qfglReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer); - QFS_WriteFile ("env5.rgb", buffer, sizeof (buffer)); - - gl_envmap = false; - qfglDrawBuffer (GL_BACK); - qfglReadBuffer (GL_BACK); - gl_ctx->end_rendering ();*/ -} - static void gl_R_LoadSky_f (void) { @@ -178,7 +118,6 @@ gl_R_Init (void) Cmd_AddCommand ("timerefresh", gl_R_TimeRefresh_f, "Tests the current refresh rate for the current location"); - Cmd_AddCommand ("envmap", R_Envmap_f, "No Description"); Cmd_AddCommand ("loadsky", gl_R_LoadSky_f, "Load a skybox"); gl_Draw_Init (); From aa412590085aaaa1f4f1dad14e2b7c852ff8d181 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Mar 2022 09:52:40 +0900 Subject: [PATCH 2579/3664] [gl] Clean out the last of the mirror code Stragglers... --- include/QF/GL/qf_rsurf.h | 2 -- libs/video/renderer/gl/gl_rmain.c | 3 --- libs/video/renderer/gl/gl_rmisc.c | 3 --- 3 files changed, 8 deletions(-) diff --git a/include/QF/GL/qf_rsurf.h b/include/QF/GL/qf_rsurf.h index af7c334ff..f2f300f1e 100644 --- a/include/QF/GL/qf_rsurf.h +++ b/include/QF/GL/qf_rsurf.h @@ -36,8 +36,6 @@ typedef struct gltex_s { struct instsurf_s **tex_chain_tail; } gltex_t; -extern int gl_mirrortexturenum; // quake texturenum, not gltexturenum - struct model_s; struct entity_s; struct msurface_s; diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 6ed36295a..f8d3256fe 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -68,9 +68,6 @@ #include "varrays.h" #include "vid_gl.h" -int gl_mirrortexturenum; // quake texturenum, not gltexturenum -plane_t *gl_mirror_plane; - float gl_r_world_matrix[16]; //FIXME static float r_base_world_matrix[16]; diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 65dbf5a54..7a0295d7f 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -175,7 +175,6 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) GL_BuildLightmaps (models, num_models); // identify sky texture - gl_mirrortexturenum = -1; gl_R_ClearTextures (); for (unsigned i = 0; i < brush->numtextures; i++) { tex = brush->textures[i]; @@ -184,8 +183,6 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) if (!strncmp (tex->name, "sky", 3)) { gl_R_InitSky (tex); } - if (!strncmp (tex->name, "window02_1", 10)) - gl_mirrortexturenum = i; } gl_R_InitSurfaceChains (brush); From a0adca011ffbabeb1676b54b2ebc944efb898737 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Mar 2022 12:08:06 +0900 Subject: [PATCH 2580/3664] [gl] Get fisheye working with frame buffers Of course, it's not as correct as glsl or sw due to using polygons and uvs rather than a fragment shader (not that such is out of the question since GL 3.0 is requested, but I don't feel like getting shaders going just for a couple of post-processing effects in an obsolete renderer). --- include/QF/GL/defines.h | 39 +++ include/QF/GL/qf_fisheye.h | 37 +++ include/QF/GL/qf_funcs_list.h | 13 + include/QF/Makemodule.am | 1 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/gl/gl_fisheye.c | 183 ++++++++++++++ libs/video/renderer/gl/gl_rmain.c | 339 +------------------------- libs/video/renderer/gl/gl_rmisc.c | 2 + libs/video/renderer/vid_render_gl.c | 82 ++++++- libs/video/renderer/vid_render_glsl.c | 3 +- 10 files changed, 361 insertions(+), 339 deletions(-) create mode 100644 include/QF/GL/qf_fisheye.h create mode 100644 libs/video/renderer/gl/gl_fisheye.c diff --git a/include/QF/GL/defines.h b/include/QF/GL/defines.h index d690559e1..522e289c3 100644 --- a/include/QF/GL/defines.h +++ b/include/QF/GL/defines.h @@ -830,4 +830,43 @@ # define GL_OPERAND1_ALPHA 0x8599 # define GL_OPERAND2_ALPHA 0x859A +/* framebuffer */ +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 + + #endif // __gl_defines_h diff --git a/include/QF/GL/qf_fisheye.h b/include/QF/GL/qf_fisheye.h new file mode 100644 index 000000000..44a6f7234 --- /dev/null +++ b/include/QF/GL/qf_fisheye.h @@ -0,0 +1,37 @@ +/* + qf_fisheye.h + + GL screen fisheye + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/3/25 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_GL_qf_fisheye_h +#define __QF_GL_qf_fisheye_h + +void gl_InitFisheye (void); +struct framebuffer_s; +void gl_FisheyeScreen (struct framebuffer_s *fb); + +#endif//__QF_GL_qf_fisheye_h diff --git a/include/QF/GL/qf_funcs_list.h b/include/QF/GL/qf_funcs_list.h index 8c007e804..d3bfe8063 100644 --- a/include/QF/GL/qf_funcs_list.h +++ b/include/QF/GL/qf_funcs_list.h @@ -418,6 +418,19 @@ QFGL_NEED (void, glViewport, (GLint x, GLint y, GLsizei width, GLsizei height)) // ATI Extensions QFGL_WANT (void, glPNTrianglesiATI, (GLint x, GLint y)) +// frame buffers +QFGL_DONT_NEED (GLboolean, glIsFramebuffer, (GLuint framebuffer)) +QFGL_NEED (void, glBindFramebuffer, (GLenum target, GLuint framebuffer)) +QFGL_DONT_NEED (void, glDeleteFramebuffers, (GLsizei n, const GLuint *framebuffers)) +QFGL_NEED (void, glGenFramebuffers, (GLsizei n, GLuint *framebuffers)) +QFGL_DONT_NEED (GLenum, glCheckFramebufferStatus, (GLenum target)) +QFGL_DONT_NEED (void, glFramebufferTexture1D, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)) +QFGL_NEED (void, glFramebufferTexture2D, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)) +QFGL_DONT_NEED (void, glFramebufferTexture3D, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)) +QFGL_DONT_NEED (void, glFramebufferRenderbuffer, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)) +QFGL_DONT_NEED (void, glGetFramebufferAttachmentParameteriv, (GLenum target, GLenum attachment, GLenum pname, GLint *params)) + + #ifdef UNDEF_QFGL_DONT_NEED #undef QFGL_DONT_NEED #endif diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 537d03001..b18a43f55 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -82,6 +82,7 @@ include_qf_gl = \ include/QF/GL/funcs.h \ include/QF/GL/qf_alias.h \ include/QF/GL/qf_draw.h \ + include/QF/GL/qf_fisheye.h \ include/QF/GL/qf_funcs_list.h \ include/QF/GL/qf_iqm.h \ include/QF/GL/qf_lightmap.h \ diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index aa4119ec6..c19d5bcdb 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -70,6 +70,7 @@ libs_video_renderer_librender_gl_la_SOURCES = \ libs/video/renderer/gl/gl_dyn_lights.c \ libs/video/renderer/gl/gl_dyn_part.c \ libs/video/renderer/gl/gl_dyn_textures.c \ + libs/video/renderer/gl/gl_fisheye.c \ libs/video/renderer/gl/gl_fog.c \ libs/video/renderer/gl/gl_graph.c \ libs/video/renderer/gl/gl_lightmap.c \ diff --git a/libs/video/renderer/gl/gl_fisheye.c b/libs/video/renderer/gl/gl_fisheye.c new file mode 100644 index 000000000..edace6c55 --- /dev/null +++ b/libs/video/renderer/gl/gl_fisheye.c @@ -0,0 +1,183 @@ +/* + gl_fisheye.c + + GL fisheye rendering + + Copyright (C) 2003 Arkadi Shishlov + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include + +#include "QF/cvar.h" +#include "QF/mathlib.h" +#include "QF/render.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "QF/GL/defines.h" +#include "QF/GL/funcs.h" +#include "QF/GL/qf_draw.h" +#include "QF/GL/qf_fisheye.h" +#include "QF/GL/qf_vid.h" + +#include "compat.h" +#include "r_internal.h" +#include "varrays.h" +#include "vid_gl.h" + +// Algorithm: +// Draw up to six views, one in each direction. +// Save the picture to cube map texture, use GL_ARB_texture_cube_map. +// Create FPOLYCNTxFPOLYCNT polygons sized flat grid. +// Baseing on field of view, tie cube map texture to grid using +// translation function to map texture coordinates to fixed/regular +// grid vertices coordinates. +// Render view. Fisheye is done. + +#define FPOLYCNT 128 + +struct xyz { + float x, y, z; +}; + +static struct xyz FisheyeLookupTbl[FPOLYCNT + 1][FPOLYCNT + 1]; +//static GLint gl_cube_map_size; +static GLint gl_cube_map_step; + +static void +R_BuildFisheyeLookup (int width, int height, float fov) +{ + int x, y; + struct xyz *v; + + for (y = 0; y <= height; y += gl_cube_map_step) { + for (x = 0; x <= width; x += gl_cube_map_step) { + float dx = x - width / 2; + float dy = y - height / 2; + float yaw = sqrt (dx * dx + dy * dy) * fov / width; + float roll = atan2 (dy, dx); + // X is a first index and Y is a second, because later + // when we draw QUAD_STRIPs we need next Y vertex coordinate. + v = &FisheyeLookupTbl[x / gl_cube_map_step][y / gl_cube_map_step]; + v->x = sin (yaw) * cos (roll); + v->y = sin (yaw) * sin (roll); + v->z = cos (yaw); + } + } +} + +#define CHKGLERR(s) \ +do { \ + GLint err = qfglGetError(); \ + if (err != GL_NO_ERROR) \ + printf ("%s: gl error %d\n", s, (int) err); \ +} while (0); + + +static GLuint fisheye_grid; + +void +gl_InitFisheye (void) +{ + fisheye_grid = qfglGenLists (1); +} + +static void +build_display_list (int width, int height, float fov) +{ + int maxd = max (width, height); + gl_cube_map_step = maxd / FPOLYCNT; + + R_BuildFisheyeLookup (width, height, fov * M_PI / 180.0); + + qfglNewList (fisheye_grid, GL_COMPILE); + + qfglDisable (GL_DEPTH_TEST); + qfglFrontFace (GL_CCW); + qfglClear (GL_COLOR_BUFFER_BIT); + + for (int y = 0; y < height; y += gl_cube_map_step) { + qfglBegin (GL_QUAD_STRIP); + // quad_strip, so X is inclusive + for (int x = 0; x <= width; x += gl_cube_map_step) { + int xind = x / gl_cube_map_step; + int yind = y / gl_cube_map_step; + struct xyz *v = &FisheyeLookupTbl[xind][yind + 1]; + qfglTexCoord3f (v->x, v->y, v->z); + qfglVertex2i (x, y + gl_cube_map_step); + --v; + qfglTexCoord3f (v->x, v->y, v->z); + qfglVertex2i (x, y); + } + qfglEnd (); + } + qfglEnable (GL_DEPTH_TEST); + qfglEndList (); + CHKGLERR("build list"); +} + +void +gl_FisheyeScreen (framebuffer_t *fb) +{ + static int pwidth = -1; + static int pheight = -1; + static float pfov = -1; + + if (pwidth != r_refdef.vrect.width || pheight != r_refdef.vrect.height + || pfov != scr_ffov->value) { + pwidth = r_refdef.vrect.width; + pheight = r_refdef.vrect.height; + pfov = scr_ffov->value; + + build_display_list (pwidth, pheight, pfov); + } + + gl_framebuffer_t *buffer = fb->buffer; + + qfglViewport (r_refdef.vrect.x, r_refdef.vrect.x, + r_refdef.vrect.width, r_refdef.vrect.height); + qfglMatrixMode (GL_PROJECTION); + qfglLoadIdentity (); + qfglOrtho (0, r_refdef.vrect.width, r_refdef.vrect.height, 0, -9999, 9999); + qfglMatrixMode (GL_MODELVIEW); + qfglLoadIdentity (); + qfglColor3ubv (color_white); + + qfglEnable (GL_TEXTURE_CUBE_MAP_ARB); + qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, buffer->color); + qfglCallList (fisheye_grid); + qfglDisable (GL_TEXTURE_CUBE_MAP_ARB); + CHKGLERR("fisheye"); +} diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index f8d3256fe..3e587d2b4 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -291,27 +291,8 @@ R_SetupGL (void) qfglShadeModel (GL_FLAT); } -static void -R_RenderScene (void) -{ - R_SetupGL (); - gl_Fog_EnableGFog (); - - gl_R_DrawWorld (); // adds static entities to the list - S_ExtraUpdate (); // don't let sound get messed up if going slow - gl_R_RenderDlights (); - R_DrawViewModel (); - - gl_Fog_DisableGFog (); -} - -/* - R_RenderView_ - - r_refdef must be set before the first call -*/ -static void -R_RenderView_ (void) +void +gl_R_RenderView (void) { if (r_norefresh->int_val) { return; @@ -320,317 +301,15 @@ R_RenderView_ (void) return; } - // render normal view - R_RenderScene (); -} + R_SetupGL (); + gl_Fog_EnableGFog (); -static void R_RenderViewFishEye (void); + gl_R_DrawWorld (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + gl_R_RenderDlights (); + R_DrawViewModel (); -void -gl_R_RenderView (void) -{ - if(!scr_fisheye->int_val) - R_RenderView_ (); - else - R_RenderViewFishEye (); -} - -//FIXME -// Algorithm: -// Draw up to six views, one in each direction. -// Save the picture to cube map texture, use GL_ARB_texture_cube_map. -// Create FPOLYCNTxFPOLYCNT polygons sized flat grid. -// Baseing on field of view, tie cube map texture to grid using -// translation function to map texture coordinates to fixed/regular -// grid vertices coordinates. -// Render view. Fisheye is done. -#if 0 -#define BOX_FRONT 0 -#define BOX_RIGHT 1 -#define BOX_BEHIND 2 -#define BOX_LEFT 3 -#define BOX_TOP 4 -#define BOX_BOTTOM 5 -#endif -static mat4f_t box_rotations[] = { - { { 1, 0, 0, 0}, // front - { 0, 1, 0, 0}, - { 0, 0, 1, 0}, - { 0, 0, 0, 1} }, - { { 0,-1, 0, 0}, // right - { 1, 0, 0, 0}, - { 0, 0, 1, 0}, - { 0, 0, 0, 1} }, - { {-1, 0, 0, 0}, // back - { 0,-1, 0, 0}, - { 0, 0, 1, 0}, - { 0, 0, 0, 1} }, - { { 0, 1, 0, 0}, // left - {-1, 0, 0, 0}, - { 0, 0, 1, 0}, - { 0, 0, 0, 1} }, - { { 0, 0, 1, 0}, // top - { 0, 1, 0, 0}, - {-1, 0, 0, 0}, - { 0, 0, 0, 1} }, - { { 0, 0,-1, 0}, // bottom - { 0, 1, 0, 0}, - { 1, 0, 0, 0}, - { 0, 0, 0, 1} }, -}; - -#define FPOLYCNT 128 - -struct xyz { - float x, y, z; -}; - -static struct xyz FisheyeLookupTbl[FPOLYCNT + 1][FPOLYCNT + 1]; -static GLuint cube_map_tex; -static GLint gl_cube_map_size; -static GLint gl_cube_map_step; - -static const GLenum box2cube_map[] = { - GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB -}; - -static void -R_BuildFisheyeLookup (int width, int height, float fov) -{ - int x, y; - struct xyz *v; - - for (y = 0; y <= height; y += gl_cube_map_step) { - for (x = 0; x <= width; x += gl_cube_map_step) { - float dx = x - width / 2; - float dy = y - height / 2; - float yaw = sqrt (dx * dx + dy * dy) * fov / width; - float roll = atan2 (dy, dx); - // X is a first index and Y is a second, because later - // when we draw QUAD_STRIPs we need next Y vertex coordinate. - v = &FisheyeLookupTbl[x / gl_cube_map_step][y / gl_cube_map_step]; - v->x = sin (yaw) * cos (roll); - v->y = -sin (yaw) * sin (roll); - v->z = cos (yaw); - } - } -} - -#define CHKGLERR(s) \ -do { \ - GLint err = qfglGetError(); \ - if (err != GL_NO_ERROR) \ - printf ("%s: gl error %d\n", s, (int) err); \ -} while (0); - - -static void -R_RenderCubeSide (int side) -{ - mat4f_t camera; - mat4f_t camera_inverse; - mat4f_t rotinv; - - memcpy (camera, r_refdef.camera, sizeof (camera)); - memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse)); - mmulf (r_refdef.camera, camera, box_rotations[side]); - mat4ftranspose (rotinv, box_rotations[side]); - mmulf (r_refdef.camera_inverse, rotinv, camera_inverse); - - //FIXME see fixme in r_screen.c - r_refdef.frame.mat[0] = -r_refdef.camera[1]; - r_refdef.frame.mat[1] = r_refdef.camera[0]; - r_refdef.frame.mat[2] = r_refdef.camera[2]; - r_refdef.frame.mat[3] = r_refdef.camera[3]; -#if 0 - printf ("side: %d\n", side); - printf ("c: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 3)); - printf ("i: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 3)); - printf ("f: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 3)); -#endif - qfglClear (GL_DEPTH_BUFFER_BIT); - R_RenderView_ (); - qfglEnable (GL_TEXTURE_CUBE_MAP_ARB); - qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, cube_map_tex); - qfglCopyTexSubImage2D (box2cube_map[side], 0, 0, 0, 0, 0, - gl_cube_map_size, gl_cube_map_size); - CHKGLERR ("qfglCopyTexSubImage2D"); - qfglDisable (GL_TEXTURE_CUBE_MAP_ARB); - - memcpy (r_refdef.camera, camera, sizeof (camera)); - memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); -} - -static qboolean gl_cube_map_capable = false; -static GLint gl_cube_map_maxtex; -static GLuint fisheye_grid; - -static int -R_InitFishEyeOnce (void) -{ - static qboolean fisheye_init_once_completed = false; - - if (fisheye_init_once_completed) - return 1; - Sys_MaskPrintf (SYS_dev, "GL_ARB_texture_cube_map "); - if (QFGL_ExtensionPresent ("GL_ARB_texture_cube_map")) { - qfglGetIntegerv (GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, - &gl_cube_map_maxtex); - Sys_MaskPrintf (SYS_dev, "present, max texture size %d.\n", - (int) gl_cube_map_maxtex); - gl_cube_map_capable = true; - } else { - Sys_MaskPrintf (SYS_dev, "not found.\n"); - gl_cube_map_capable = false; - } - fisheye_init_once_completed = true; - return 1; -} - -static int -R_InitFishEye (void) -{ - int width = vid.width; - int height = vid.height; - int fov = scr_ffov->int_val; - int views = scr_fviews->int_val; - - static int pwidth = -1; - static int pheight = -1; - static int pfov = -1; - static int pviews = -1; - - int i, x, y, min_wh, wh_changed = 0; - - if (!R_InitFishEyeOnce()) - return 0; - if (!gl_cube_map_capable) - return 0; - - // There is a problem when max texture size is bigger than - // min(width, height), it shows up as black fat stripes at the edges - // of box polygons, probably due to missing texture fragment. Try - // to play in 640x480 with gl_cube_map_size == 512. - if (pwidth != width || pheight != height) { - wh_changed = 1; - min_wh = (height < width) ? height : width; - gl_cube_map_size = gl_cube_map_maxtex; - while (gl_cube_map_size > min_wh) - gl_cube_map_size /= 2; - gl_cube_map_step = gl_cube_map_size / FPOLYCNT; - } - if (pviews != views) { - qfglEnable (GL_TEXTURE_CUBE_MAP_ARB); - if (pviews != -1) - qfglDeleteTextures (1, &cube_map_tex); - pviews = views; - qfglGenTextures (1, &cube_map_tex); - qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, cube_map_tex); - for (i = 0; i < 6; ++i) { - qfglTexImage2D (box2cube_map[i], 0, 3, gl_cube_map_size, - gl_cube_map_size, 0, GL_RGB, GL_UNSIGNED_SHORT, - NULL); - } - qfglTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, - GL_LINEAR); - qfglTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, - GL_LINEAR); - qfglDisable (GL_TEXTURE_CUBE_MAP_ARB); - } - if (wh_changed || pfov != fov) { - if (pfov != -1) - qfglDeleteLists (fisheye_grid, 1); - pwidth = width; - pheight = height; - pfov = fov; - - R_BuildFisheyeLookup (gl_cube_map_size, gl_cube_map_size, - ((float) fov) * M_PI / 180.0); - - fisheye_grid = qfglGenLists (1); - qfglNewList (fisheye_grid, GL_COMPILE); - qfglLoadIdentity (); - qfglTranslatef (-gl_cube_map_size / 2, -gl_cube_map_size / 2, - -gl_cube_map_size / 2); - - qfglDisable (GL_DEPTH_TEST); - qfglFrontFace (GL_CCW); - qfglClear (GL_COLOR_BUFFER_BIT); - - qfglEnable (GL_TEXTURE_CUBE_MAP_ARB); - qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, cube_map_tex); - for (y = 0; y < gl_cube_map_size; y += gl_cube_map_step) { - qfglBegin (GL_QUAD_STRIP); - for (x = 0; x <= gl_cube_map_size; x += gl_cube_map_step) { // quad_strip, X should be inclusive - struct xyz *v = &FisheyeLookupTbl[x / gl_cube_map_step] - [y / gl_cube_map_step + 1]; - qfglTexCoord3f (v->x, v->y, v->z); - qfglVertex2i (x, y + gl_cube_map_step); - --v; - qfglTexCoord3f (v->x, v->y, v->z); - qfglVertex2i (x, y); - } - qfglEnd (); - } - qfglDisable (GL_TEXTURE_CUBE_MAP_ARB); - qfglEnable (GL_DEPTH_TEST); - qfglEndList (); - } - return 1; -} - -static void -R_RenderViewFishEye (void) -{ - float s_fov_x, s_fov_y; - int s_vid_w, s_vid_h, s_rect_w, s_rect_h; - - if (!R_InitFishEye()) return; - - // save values - s_fov_x = r_refdef.fov_x; - s_fov_y = r_refdef.fov_y; - s_vid_w = vid.width; - s_vid_h = vid.height; - s_rect_w = r_refdef.vrect.width; - s_rect_h = r_refdef.vrect.height; - // the view should be square - r_refdef.fov_x = r_refdef.fov_y = 90; - vid.width = vid.height = - r_refdef.vrect.height = r_refdef.vrect.width = - gl_cube_map_size; - switch (scr_fviews->int_val) { - case 6: R_RenderCubeSide (BOX_BEHIND); - case 5: R_RenderCubeSide (BOX_BOTTOM); - case 4: R_RenderCubeSide (BOX_TOP); - case 3: R_RenderCubeSide (BOX_LEFT); - case 2: R_RenderCubeSide (BOX_RIGHT); - default: R_RenderCubeSide (BOX_FRONT); - } - // restore - r_refdef.fov_x = s_fov_x; - r_refdef.fov_y = s_fov_y; - vid.width = s_vid_w; - vid.height = s_vid_h; - r_refdef.vrect.width = s_rect_w; - r_refdef.vrect.height = s_rect_h; - R_SetupGL_Viewport_and_Perspective (); - qfglMatrixMode (GL_MODELVIEW); - qfglCallList (fisheye_grid); + gl_Fog_DisableGFog (); } void diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 7a0295d7f..f5f822dd6 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -54,6 +54,7 @@ #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_draw.h" +#include "QF/GL/qf_fisheye.h" #include "QF/GL/qf_lightmap.h" #include "QF/GL/qf_particles.h" #include "QF/GL/qf_rlight.h" @@ -135,6 +136,7 @@ gl_R_Init (void) gl_R_InitParticles (); gl_R_InitSprites (); Skin_Init (); + gl_InitFisheye (); } static void diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index c09af57b1..e1ccfe1e4 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -35,6 +35,7 @@ #include "QF/GL/funcs.h" #include "QF/GL/qf_draw.h" +#include "QF/GL/qf_fisheye.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_rsurf.h" #include "QF/GL/qf_particles.h" @@ -259,6 +260,7 @@ static void gl_render_view (void) { // do 3D refresh drawing, and then update the screen + qfglClear (GL_DEPTH_BUFFER_BIT); gl_R_RenderView (); } @@ -271,6 +273,11 @@ gl_draw_transparent (void) static void gl_post_process (framebuffer_t *src) { + if (scr_fisheye->int_val) { + gl_FisheyeScreen (src); + } else if (r_dowarp) { + //gl_WarpScreen (src); + } } static void @@ -306,9 +313,55 @@ gl_end_frame (void) } static framebuffer_t * -gl_create_cube_map (int size) +gl_create_cube_map (int side) { - Sys_Error ("not implemented"); + GLuint tex[2]; + qfglGenTextures (2, tex); + + qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, tex[0]); + for (int i = 0; i < 6; i++) { + qfglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, 0, GL_RGBA, + side, side, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } + qfglTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + qfglTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + qfglTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + qfglTexParameteri (GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + + qfglBindTexture (GL_TEXTURE_2D, tex[1]); + qfglTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, side, side, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + size_t size = sizeof (framebuffer_t) * 6; + size += sizeof (gl_framebuffer_t) * 6; + + framebuffer_t *cube = malloc (size); + __auto_type buffer_base = (gl_framebuffer_t *) &cube[6]; + for (int i = 0; i < 6; i++) { + cube[i].width = side; + cube[i].height = side; + __auto_type buffer = buffer_base + i; + cube[i].buffer = buffer; + + buffer->color = tex[0]; + buffer->depth = tex[1]; + qfglGenFramebuffers (1, &buffer->handle); + + qfglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); + qfglFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, + buffer->color, 0); + qfglFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, buffer->depth, 0); + } + qfglBindFramebuffer (GL_FRAMEBUFFER, 0); + return cube; } static framebuffer_t * @@ -320,16 +373,31 @@ gl_create_frame_buffer (int width, int height) static void gl_bind_framebuffer (framebuffer_t *framebuffer) { + unsigned width = vr_data.vid->width; + unsigned height = vr_data.vid->height; + if (!framebuffer) { + qfglBindFramebuffer (GL_FRAMEBUFFER, 0); + } else { + gl_framebuffer_t *buffer = framebuffer->buffer; + qfglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); + + width = framebuffer->width; + height = framebuffer->height; + } + + vrect_t r = { 0, 0, width, height }; + R_SetVrect (&r, &r_refdef.vrect, 0); + gl_R_ViewChanged (); } static void gl_set_viewport (const vrect_t *view) { - int x = r_refdef.vrect.x; - int y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)); - int w = r_refdef.vrect.width; - int h = r_refdef.vrect.height; - qfglViewport (x, y2, w, h); + int x = view->x; + int y = vid.height - (view->y + view->height);//FIXME vid.height + int w = view->width; + int h = view->height; + qfglViewport (x, y, w, h); } vid_render_funcs_t gl_vid_render_funcs = { diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 2c6fa374c..dcc8125ea 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -236,7 +236,6 @@ static void glsl_bind_framebuffer (framebuffer_t *fb); static void glsl_post_process (framebuffer_t *src) { - glsl_bind_framebuffer (0); if (scr_fisheye->int_val) { glsl_FisheyeScreen (src); } else if (r_dowarp) { @@ -376,7 +375,7 @@ static void glsl_set_viewport (const vrect_t *view) { int x = view->x; - int y = vid.height - (view->y + view->height); + int y = vid.height - (view->y + view->height);//FIXME vid.height int w = view->width; int h = view->height; qfeglViewport (x, y, w, h); From 12776e487a1541758e5d702bf178bf9664e9fa21 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Mar 2022 18:13:37 +0900 Subject: [PATCH 2581/3664] [gl] Implement screen warping for liquids It's not the most efficient code (uses sin() directly), but at least it works (and with about 75% cpu headroom at 72fps on my machine). --- include/QF/GL/qf_rsurf.h | 3 ++ libs/video/renderer/gl/gl_warp.c | 61 ++++++++++++++++++++++++++++- libs/video/renderer/vid_render_gl.c | 38 +++++++++++++++++- 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/include/QF/GL/qf_rsurf.h b/include/QF/GL/qf_rsurf.h index f2f300f1e..8a2d012ad 100644 --- a/include/QF/GL/qf_rsurf.h +++ b/include/QF/GL/qf_rsurf.h @@ -56,4 +56,7 @@ void gl_R_AddTexture (struct texture_s *tx); void gl_R_ClearTextures (void); void gl_R_InitSurfaceChains (struct mod_brush_s *brush); +struct framebuffer_s; +void gl_WarpScreen (struct framebuffer_s *fb); + #endif // __QF_GL_rsurf_h diff --git a/libs/video/renderer/gl/gl_warp.c b/libs/video/renderer/gl/gl_warp.c index 3f08d83d7..4ae963cf7 100644 --- a/libs/video/renderer/gl/gl_warp.c +++ b/libs/video/renderer/gl/gl_warp.c @@ -31,12 +31,13 @@ #include "QF/cvar.h" #include "QF/sys.h" -#include "r_internal.h" - #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_rsurf.h" +#include "r_internal.h" +#include "vid_gl.h" + // speed up sin calculations - Ed static float turbsin[] = { # include "gl_warp_sin.h" @@ -81,3 +82,59 @@ GL_EmitWaterPolys (msurface_t *surf) qfglEnd (); } } + +const float S = 0.15625; +const float F = 2.5; +const float A = 0.01; + +static void +warp_uv (float *uv, float time) +{ + float p1 = (time * S + F * uv[1]) * 2 * M_PI; + float p2 = (time * S + F * uv[0]) * 2 * M_PI; + uv[0] = uv[0] * (1 - 2 * A) + A * (1 + sin (p1)); + uv[1] = uv[1] * (1 - 2 * A) + A * (1 + sin (p2)); +} + +void +gl_WarpScreen (framebuffer_t *fb) +{ + gl_framebuffer_t *buffer = fb->buffer; + + qfglMatrixMode (GL_PROJECTION); + qfglLoadIdentity (); + qfglOrtho (0, r_refdef.vrect.width, r_refdef.vrect.height, 0, -9999, 9999); + qfglMatrixMode (GL_MODELVIEW); + qfglLoadIdentity (); + qfglColor3ubv (color_white); + + qfglDisable (GL_DEPTH_TEST); + qfglFrontFace (GL_CCW); + + qfglBindTexture (GL_TEXTURE_2D, buffer->color); + + int base_x = r_refdef.vrect.x; + int base_y = r_refdef.vrect.y; + int width = r_refdef.vrect.width; + int height = r_refdef.vrect.height; + + float time = vr_data.realtime; + + for (int y = 0; y < height; y += 40) { + qfglBegin (GL_QUAD_STRIP); + for (int x = 0; x <= width; x+= 40) { + int y2 = y + 40; + int xy1[] = { base_x + x, base_y + y }; + int xy2[] = { base_x + x, base_y + y2}; + float uv1[] = { (float) x / width, 1 - (float) y / height }; + float uv2[] = { (float) x / width, 1 - (float) y2 / height }; + warp_uv (uv1, time); + warp_uv (uv2, time); + qfglTexCoord2fv (uv2); + qfglVertex2iv (xy2); + qfglTexCoord2fv (uv1); + qfglVertex2iv (xy1); + } + qfglEnd (); + } +} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index e1ccfe1e4..7d31c65d2 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -276,7 +276,7 @@ gl_post_process (framebuffer_t *src) if (scr_fisheye->int_val) { gl_FisheyeScreen (src); } else if (r_dowarp) { - //gl_WarpScreen (src); + gl_WarpScreen (src); } } @@ -367,7 +367,41 @@ gl_create_cube_map (int side) static framebuffer_t * gl_create_frame_buffer (int width, int height) { - Sys_Error ("not implemented"); + size_t size = sizeof (framebuffer_t) + sizeof (gl_framebuffer_t); + + framebuffer_t *fb = malloc (size); + fb->width = width; + fb->height = height; + __auto_type buffer = (gl_framebuffer_t *) &fb[1]; + fb->buffer = buffer; + qfglGenFramebuffers (1, &buffer->handle); + + GLuint tex[2]; + qfglGenTextures (2, tex); + + buffer->color = tex[0]; + buffer->depth = tex[1]; + + qfglBindTexture (GL_TEXTURE_2D, buffer->color); + qfglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, 0); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + qfglBindTexture (GL_TEXTURE_2D, buffer->depth); + qfglTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, + GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + qfglBindFramebuffer (GL_FRAMEBUFFER, buffer->handle); + qfglFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, buffer->color, 0); + qfglFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, buffer->depth, 0); + + qfglBindFramebuffer (GL_FRAMEBUFFER, 0); + return fb; } static void From aafd5c3d8190199588e434f947718b921e9f13db Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Mar 2022 13:15:15 +0900 Subject: [PATCH 2582/3664] [gl] Make perspective matrix setup consistent Now GL perspective matrix setup matches that of GLSL and Vulkan, and GL's z_up matrix matches GLSL's (as it should, since they're really going through the same API). GL also needs the depth adjustmet matrix now. Other than having to google the docs for glFrustum, there's nothing wrong with the function itself, but it's nice to have direct control over the matrices. In the process, I discovered how horribly confused I've been at times with respect to the handedness of GL and Quake: GL is right-handed (y-up, z-out, x-right), as is Quake itself (but z-up, y-left, x-in), but as the perspective matrix used in the three renderers expects z-in, having x-right and y-up makes the matrix effectively left-handed (not for Vulkan though, because there it's y-down, x-right, z-up, so right-handed again). --- libs/video/renderer/gl/gl_rmain.c | 45 ++++++++++++++++--------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 3e587d2b4..a782abae0 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -230,38 +230,39 @@ R_DrawViewModel (void) } static void -MYgluPerspective (GLdouble fovy, GLdouble aspect, GLdouble zNear, - GLdouble zFar) +R_Perspective (void) { - GLdouble xmin, xmax, ymin, ymax; + float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; + float f = 1 / tan (r_refdef.fov_y * M_PI / 360); + float neard, fard; + mat4f_t proj; - ymax = zNear * tan (fovy * M_PI / 360.0); - ymin = -ymax; + neard = r_nearclip->value; + fard = r_farclip->value; - xmin = ymin * aspect; - xmax = -xmin; + // NOTE columns! + proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 }; + proj[1] = (vec4f_t) { 0, f, 0, 0 }; + proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 }; + proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 }; -// printf ("glFrustum (%f, %f, %f, %f)\n", xmin, xmax, ymin, ymax); - qfglFrustum (xmin, xmax, ymin, ymax, zNear, zFar); -} - -static void -R_SetupGL_Viewport_and_Perspective (void) -{ - float screenaspect; + // convert 0..1 depth buffer range to -1..1 + static mat4f_t depth_range = { + { 1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 2, 0}, + { 0, 0,-1, 1}, + }; + mmulf (proj, depth_range, proj); qfglMatrixMode (GL_PROJECTION); - qfglLoadIdentity (); - - screenaspect = r_refdef.vrect.width / (float) r_refdef.vrect.height; - MYgluPerspective (r_refdef.fov_y, screenaspect, r_nearclip->value, - r_farclip->value); + qfglLoadMatrixf (&proj[0][0]); } static void R_SetupGL (void) { - R_SetupGL_Viewport_and_Perspective (); + R_Perspective (); qfglFrontFace (GL_CW); @@ -269,7 +270,7 @@ R_SetupGL (void) qfglLoadIdentity (); static mat4f_t z_up = { - { 0, 0, -1, 0}, + { 0, 0, 1, 0}, {-1, 0, 0, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 1}, From 3103f400fda366d452973720744468645a88f5e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Mar 2022 15:27:35 +0900 Subject: [PATCH 2583/3664] [sw] Clean up r_refdef and R_ViewChanged r_refdef is really meant for holding the various screen "constants" for the software renderer rather than the more generic scene stuff. All the fields referenced by the low level rendering code (especially assembly) have been moved to the beginning of the struct (and nicely fit within 64 bytes). The other fields should be moved elsewhere, but not this commit. On top of that, R_ViewChanged is much easier to read, and there are fewer static globals. --- include/QF/render.h | 24 +++---- include/asm_draw.h | 43 +++++------- libs/video/renderer/sw/sw_raclip.c | 24 +++---- libs/video/renderer/sw/sw_raclipa.S | 4 +- libs/video/renderer/sw/sw_ralias.c | 4 +- libs/video/renderer/sw/sw_rdraw.c | 4 +- libs/video/renderer/sw/sw_rdrawa.S | 6 +- libs/video/renderer/sw/sw_rmain.c | 102 +++++++++++++--------------- 8 files changed, 94 insertions(+), 117 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index ed1d66b94..18c760f7f 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -203,25 +203,21 @@ typedef struct framebuffer_s { // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { - vrect_t vrect; // subwindow in video for refresh - // FIXME: not need vrect next field here? - vrect_t aliasvrect; // scaled Alias version - int vrectright, vrectbottom; // right & bottom screen coords - int aliasvrectright, aliasvrectbottom; // scaled Alias versions - float vrectrightedge; // rightmost right edge we care about, - // for use in edge list - float fvrectx, fvrecty; // for floating-point compares float fvrectx_adj, fvrecty_adj; // left and top edges, for clamping - int vrect_x_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20 - int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20 float fvrectright_adj, fvrectbottom_adj; + int aliasvrectleft, aliasvrecttop; // scaled Alias versions + int aliasvrectright, aliasvrectbottom; // scaled Alias versions + int vrectright, vrectbottom; // right & bottom screen coords + int vrectx_adj_shift20; // (vrect.x + 0.5 - epsilon) << 20 + int vrectright_adj_shift20; // (vrectright + 0.5 - epsilon) << 20 + float fvrectx, fvrecty; // for floating-point compares // right and bottom edges, for clamping float fvrectright; // rightmost edge, for Alias clamping float fvrectbottom; // bottommost edge, for Alias clamping - float horizontalFieldOfView; // at Z = 1.0, this many X is visible - // 2.0 = 90 degrees - float xOrigin; // should probably always be 0.5 - float yOrigin; // between be around 0.3 to 0.5 + // end of asm refs + + //FIXME move all of below elsewhere + vrect_t vrect; // subwindow in video for refresh refframe_t frame; plane_t frustum[4]; diff --git a/include/asm_draw.h b/include/asm_draw.h index 1e2ae1da4..50f720c63 100644 --- a/include/asm_draw.h +++ b/include/asm_draw.h @@ -118,32 +118,23 @@ // refdef_t structure // !!! if this is changed, it must be changed in render.h too !!! -#define rd_vrect 0 -#define rd_aliasvrect 20 -#define rd_vrectright 40 -#define rd_vrectbottom 44 -#define rd_aliasvrectright 48 -#define rd_aliasvrectbottom 52 -#define rd_vrectrightedge 56 -#define rd_fvrectx 60 -#define rd_fvrecty 64 -#define rd_fvrectx_adj 68 -#define rd_fvrecty_adj 72 -#define rd_vrect_x_adj_shift20 76 -#define rd_vrectright_adj_shift20 80 -#define rd_fvrectright_adj 84 -#define rd_fvrectbottom_adj 88 -#define rd_fvrectright 92 -#define rd_fvrectbottom 96 -#define rd_horizontalFieldOfView 100 -#define rd_xOrigin 104 -#define rd_yOrigin 108 -#define rd_viewposition 112 -#define rd_viewrotation 128 -#define rd_ambientlight 144 -#defin rd_fov_x 148 -#defin rd_fov_y 152 -#define rd_size 156 // sizeof (refdef_t) +#define rd_fvrectx_adj 0 +#define rd_fvrecty_adj 4 +#define rd_fvrectright_adj 8 +#define rd_fvrectbottom_adj 12 +#define rd_aliasvrectleft 16 +#define rd_aliasvrecttop 20 +#define rd_aliasvrectright 24 +#define rd_aliasvrectbottom 28 +#define rd_vrectright 32 +#define rd_vrectbottom 36 +#define rd_vrectx_adj_shift20 40 +#define rd_vrectright_adj_shift20 44 +#define rd_fvrectx 48 +#define rd_fvrecty 52 +#define rd_fvrectright 56 +#define rd_fvrectbottom 60 +#define rd_size 64 // sizeof (refdef_t) FIXME make true // mtriangle_t structure // !!! if this is changed, it must be changed in model.h too !!! diff --git a/libs/video/renderer/sw/sw_raclip.c b/libs/video/renderer/sw/sw_raclip.c index 18a89bf0d..2b1ff56b1 100644 --- a/libs/video/renderer/sw/sw_raclip.c +++ b/libs/video/renderer/sw/sw_raclip.c @@ -80,9 +80,9 @@ R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) R_AliasProjectFinalVert (out, &avout); - if (out->v[0] < r_refdef.aliasvrect.x) + if (out->v[0] < r_refdef.aliasvrectleft) out->flags |= ALIAS_LEFT_CLIP; - if (out->v[1] < r_refdef.aliasvrect.y) + if (out->v[1] < r_refdef.aliasvrecttop) out->flags |= ALIAS_TOP_CLIP; if (out->v[0] > r_refdef.aliasvrectright) out->flags |= ALIAS_RIGHT_CLIP; @@ -99,12 +99,12 @@ R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) int i; if (pfv0->v[1] >= pfv1->v[1]) { - scale = (float) (r_refdef.aliasvrect.x - pfv0->v[0]) / + scale = (float) (r_refdef.aliasvrectleft - pfv0->v[0]) / (pfv1->v[0] - pfv0->v[0]); for (i = 0; i < 6; i++) out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; } else { - scale = (float) (r_refdef.aliasvrect.x - pfv1->v[0]) / + scale = (float) (r_refdef.aliasvrectleft - pfv1->v[0]) / (pfv0->v[0] - pfv1->v[0]); for (i = 0; i < 6; i++) out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; @@ -139,12 +139,12 @@ R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) int i; if (pfv0->v[1] >= pfv1->v[1]) { - scale = (float) (r_refdef.aliasvrect.y - pfv0->v[1]) / + scale = (float) (r_refdef.aliasvrecttop - pfv0->v[1]) / (pfv1->v[1] - pfv0->v[1]); for (i = 0; i < 6; i++) out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; } else { - scale = (float) (r_refdef.aliasvrect.y - pfv1->v[1]) / + scale = (float) (r_refdef.aliasvrecttop - pfv1->v[1]) / (pfv0->v[1] - pfv1->v[1]); for (i = 0; i < 6; i++) out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; @@ -195,9 +195,9 @@ R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count, if (oldflags ^ flags) { clip (&in[j], &in[i], &out[k]); out[k].flags = 0; - if (out[k].v[0] < r_refdef.aliasvrect.x) + if (out[k].v[0] < r_refdef.aliasvrectleft) out[k].flags |= ALIAS_LEFT_CLIP; - if (out[k].v[1] < r_refdef.aliasvrect.y) + if (out[k].v[1] < r_refdef.aliasvrecttop) out[k].flags |= ALIAS_TOP_CLIP; if (out[k].v[0] > r_refdef.aliasvrectright) out[k].flags |= ALIAS_RIGHT_CLIP; @@ -291,13 +291,13 @@ R_AliasClipTriangle (mtriangle_t *ptri) } for (i = 0; i < k; i++) { - if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x) - fv[pingpong][i].v[0] = r_refdef.aliasvrect.x; + if (fv[pingpong][i].v[0] < r_refdef.aliasvrectleft) + fv[pingpong][i].v[0] = r_refdef.aliasvrectleft; else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright) fv[pingpong][i].v[0] = r_refdef.aliasvrectright; - if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y) - fv[pingpong][i].v[1] = r_refdef.aliasvrect.y; + if (fv[pingpong][i].v[1] < r_refdef.aliasvrecttop) + fv[pingpong][i].v[1] = r_refdef.aliasvrecttop; else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom) fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom; diff --git a/libs/video/renderer/sw/sw_raclipa.S b/libs/video/renderer/sw/sw_raclipa.S index 510b1fb43..d97199866 100644 --- a/libs/video/renderer/sw/sw_raclipa.S +++ b/libs/video/renderer/sw/sw_raclipa.S @@ -219,7 +219,7 @@ C(R_Alias_clip_top): leal C(r_refdef),%eax movl C(float_point5),%edx #endif - movl rd_aliasvrect+4(%eax),%eax + movl rd_aliasvrecttop(%eax),%eax movl %edx,point5(%esp) jmp LDoForwardOrBackward #ifdef PIC @@ -310,7 +310,7 @@ C(R_Alias_clip_left): leal C(r_refdef),%eax movl C(float_point5),%edx #endif - movl rd_aliasvrect+0(%eax),%eax + movl rd_aliasvrectleft(%eax),%eax movl %edx,point5(%esp) jmp LRightLeftEntry #ifdef PIC diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index acf1b4101..6aba6ba03 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -254,9 +254,9 @@ R_AliasClipAndProjectFinalVert (finalvert_t *fv, auxvert_t *av) R_AliasProjectFinalVert (fv, av); - if (fv->v[0] < r_refdef.aliasvrect.x) + if (fv->v[0] < r_refdef.aliasvrectleft) fv->flags |= ALIAS_LEFT_CLIP; - if (fv->v[1] < r_refdef.aliasvrect.y) + if (fv->v[1] < r_refdef.aliasvrecttop) fv->flags |= ALIAS_TOP_CLIP; if (fv->v[0] > r_refdef.aliasvrectright) fv->flags |= ALIAS_RIGHT_CLIP; diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index 48c8489df..38e80cfd1 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -214,8 +214,8 @@ R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) // causes it to incorrectly extend to the scan, and the extension of the // line goes off the edge of the screen // FIXME: is this actually needed? - if (edge->u < r_refdef.vrect_x_adj_shift20) - edge->u = r_refdef.vrect_x_adj_shift20; + if (edge->u < r_refdef.vrectx_adj_shift20) + edge->u = r_refdef.vrectx_adj_shift20; if (edge->u > r_refdef.vrectright_adj_shift20) edge->u = r_refdef.vrectright_adj_shift20; diff --git a/libs/video/renderer/sw/sw_rdrawa.S b/libs/video/renderer/sw/sw_rdrawa.S index 7c4ac232f..531b53367 100644 --- a/libs/video/renderer/sw/sw_rdrawa.S +++ b/libs/video/renderer/sw/sw_rdrawa.S @@ -412,12 +412,12 @@ LSideDone: // // causes it to incorrectly extend to the scan, and the extension of the // // line goes off the edge of the screen // // FIXME: is this actually needed? -// if (edge->u < r_refdef.vrect_x_adj_shift20) -// edge->u = r_refdef.vrect_x_adj_shift20; +// if (edge->u < r_refdef.vrectx_adj_shift20) +// edge->u = r_refdef.vrectx_adj_shift20; // if (edge->u > r_refdef.vrectright_adj_shift20) // edge->u = r_refdef.vrectright_adj_shift20; movl et_u(%edi),%eax - movl C(r_refdef)+rd_vrect_x_adj_shift20,%edx + movl C(r_refdef)+rd_vrectx_adj_shift20,%edx cmpl %edx,%eax jl LP4 movl C(r_refdef)+rd_vrectright_adj_shift20,%edx diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 235a60a9c..5b459cf41 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -91,9 +91,6 @@ float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; int screenwidth; float pixelAspect; -static float screenAspect; -static float verticalFieldOfView; -static float xOrigin, yOrigin; plane_t screenedge[4]; @@ -145,9 +142,6 @@ sw_R_Init (void) view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = view_clipplanes[3].rightedge = false; - r_refdef.xOrigin = XCENTERING; - r_refdef.yOrigin = YCENTERING; - // TODO: collect 386-specific code in one place #ifdef USE_INTEL_ASM Sys_MakeCodeWriteable ((long) R_EdgeCodeStart, @@ -231,42 +225,30 @@ R_ViewChanged (void) r_viewchanged = true; - r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x / 360 * M_PI); - r_refdef.fvrectx = (float) r_refdef.vrect.x; - r_refdef.fvrectx_adj = (float) r_refdef.vrect.x - 0.5; - r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x << 20) + (1 << 19) - 1; - r_refdef.fvrecty = (float) r_refdef.vrect.y; - r_refdef.fvrecty_adj = (float) r_refdef.vrect.y - 0.5; - r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; - r_refdef.vrectright_adj_shift20 = - (r_refdef.vrectright << 20) + (1 << 19) - 1; - r_refdef.fvrectright = (float) r_refdef.vrectright; - r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5; - r_refdef.vrectrightedge = (float) r_refdef.vrectright - 0.99; - r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; +#define SHIFT20(x) (((x) << 20) + (1 << 19) - 1) + r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; + r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; + r_refdef.vrectx_adj_shift20 = SHIFT20 (r_refdef.vrect.x); + r_refdef.vrectright_adj_shift20 = SHIFT20 (r_refdef.vrectright); + + r_refdef.fvrectx = (float) r_refdef.vrect.x; + r_refdef.fvrecty = (float) r_refdef.vrect.y; + r_refdef.fvrectright = (float) r_refdef.vrectright; r_refdef.fvrectbottom = (float) r_refdef.vrectbottom; + + r_refdef.fvrectx_adj = (float) r_refdef.vrect.x - 0.5; + r_refdef.fvrecty_adj = (float) r_refdef.vrect.y - 0.5; + r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5; r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5; - r_refdef.aliasvrect.x = (int) (r_refdef.vrect.x * r_aliasuvscale); - r_refdef.aliasvrect.y = (int) (r_refdef.vrect.y * r_aliasuvscale); - r_refdef.aliasvrect.width = (int) (r_refdef.vrect.width * r_aliasuvscale); - r_refdef.aliasvrect.height = (int) (r_refdef.vrect.height * - r_aliasuvscale); - r_refdef.aliasvrectright = r_refdef.aliasvrect.x + - r_refdef.aliasvrect.width; - r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + - r_refdef.aliasvrect.height; - - pixelAspect = 1;//FIXME vid.aspect; - xOrigin = r_refdef.xOrigin; - yOrigin = r_refdef.yOrigin; - - screenAspect = r_refdef.vrect.width * pixelAspect / r_refdef.vrect.height; - // 320*200 1.0 pixelAspect = 1.6 screenAspect - // 320*240 1.0 pixelAspect = 1.3333 screenAspect - // proper 320*200 pixelAspect = 0.8333333 - - verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; + int aleft = r_refdef.vrect.x * r_aliasuvscale; + int atop = r_refdef.vrect.y * r_aliasuvscale; + int awidth = r_refdef.vrect.width * r_aliasuvscale; + int aheight = r_refdef.vrect.height * r_aliasuvscale; + r_refdef.aliasvrectleft = aleft; + r_refdef.aliasvrecttop = atop; + r_refdef.aliasvrectright = aleft + awidth; + r_refdef.aliasvrectbottom = atop + aheight; // values for perspective projection // if math were exact, the values would range from 0.5 to to range+0.5 @@ -274,45 +256,54 @@ R_ViewChanged (void) // the polygon rasterization will never render in the first row or column // but will definately render in the [range] row and column, so adjust the // buffer origin to get an exact edge to edge fill - xcenter = ((float) r_refdef.vrect.width * XCENTERING) + - r_refdef.vrect.x - 0.5; + xcenter = r_refdef.vrect.width * XCENTERING + r_refdef.vrect.x - 0.5; + ycenter = r_refdef.vrect.height * YCENTERING + r_refdef.vrect.y - 0.5; aliasxcenter = xcenter * r_aliasuvscale; - ycenter = ((float) r_refdef.vrect.height * YCENTERING) + - r_refdef.vrect.y - 0.5; aliasycenter = ycenter * r_aliasuvscale; - xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; - aliasxscale = xscale * r_aliasuvscale; - xscaleinv = 1.0 / xscale; + pixelAspect = 1;//FIXME vid.aspect; + + float aspect = r_refdef.vrect.width * pixelAspect / r_refdef.vrect.height; + // 320*200 1.0 pixelAspect = 1.6 aspect + // 320*240 1.0 pixelAspect = 1.3333 aspect + // proper 320*200 pixelAspect = 0.8333333 + + float hFOV = 2.0 * tan (r_refdef.fov_x / 360 * M_PI); + float vFOV = hFOV / aspect; + + // general perspective scaling + xscale = r_refdef.vrect.width / hFOV; yscale = xscale * pixelAspect; - aliasyscale = yscale * r_aliasuvscale; + xscaleinv = 1.0 / xscale; yscaleinv = 1.0 / yscale; - xscaleshrink = (r_refdef.vrect.width - 6) / r_refdef.horizontalFieldOfView; + // perspective scaling for alias models + aliasxscale = xscale * r_aliasuvscale; + aliasyscale = yscale * r_aliasuvscale; + // perspective scaling for paricle position + xscaleshrink = (r_refdef.vrect.width - 6) / hFOV; yscaleshrink = xscaleshrink * pixelAspect; // left side clip - screenedge[0].normal[0] = -1.0 / (xOrigin * - r_refdef.horizontalFieldOfView); + screenedge[0].normal[0] = -1.0 / (XCENTERING * hFOV); screenedge[0].normal[1] = 0; screenedge[0].normal[2] = 1; screenedge[0].type = PLANE_ANYZ; // right side clip - screenedge[1].normal[0] = 1.0 / ((1.0 - xOrigin) * - r_refdef.horizontalFieldOfView); + screenedge[1].normal[0] = 1.0 / ((1.0 - XCENTERING) * hFOV); screenedge[1].normal[1] = 0; screenedge[1].normal[2] = 1; screenedge[1].type = PLANE_ANYZ; // top side clip screenedge[2].normal[0] = 0; - screenedge[2].normal[1] = -1.0 / (yOrigin * verticalFieldOfView); + screenedge[2].normal[1] = -1.0 / (YCENTERING * vFOV); screenedge[2].normal[2] = 1; screenedge[2].type = PLANE_ANYZ; // bottom side clip screenedge[3].normal[0] = 0; - screenedge[3].normal[1] = 1.0 / ((1.0 - yOrigin) * verticalFieldOfView); + screenedge[3].normal[1] = 1.0 / ((1.0 - YCENTERING) * vFOV); screenedge[3].normal[2] = 1; screenedge[3].type = PLANE_ANYZ; @@ -320,8 +311,7 @@ R_ViewChanged (void) VectorNormalize (screenedge[i].normal); res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) / - (320.0 * 152.0)) * (2.0 / - r_refdef.horizontalFieldOfView); + (320.0 * 152.0)) * (2.0 / hFOV); r_aliastransition = r_aliastransbase->value * res_scale; r_resfudge = r_aliastransadj->value * res_scale; From d53b0b00643403a200f4559cfe1eea5ff8acf633 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Mar 2022 13:08:58 +0900 Subject: [PATCH 2584/3664] [sw] Clean up use of vid.colormap8 The main goal was to not update the colormap pointers when only the viewport or fov changed. --- include/d_iface.h | 4 ++-- include/quakeasm.h | 2 +- include/r_local.h | 2 ++ include/vid_internal.h | 1 + libs/video/renderer/sw/surf8.S | 2 +- libs/video/renderer/sw/sw_ralias.c | 6 +++--- libs/video/renderer/sw/sw_riqm.c | 2 +- libs/video/renderer/sw/sw_rmain.c | 14 +++++++++----- libs/video/renderer/sw/sw_rsurf.c | 26 +++++++++++--------------- libs/video/renderer/vid_render_sw.c | 7 +++++++ libs/video/targets/vid_win.c | 3 +++ libs/video/targets/vid_x11.c | 3 +++ 12 files changed, 44 insertions(+), 28 deletions(-) diff --git a/include/d_iface.h b/include/d_iface.h index 77529dc55..32e7e307a 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -143,7 +143,7 @@ extern int d_con_indirect; // if 0, Quake will draw console directly extern vec3_t r_pright, r_pup, r_ppn, r_porigin; -void D_Aff8Patch (void *pcolormap); +void D_Aff8Patch (const byte *pcolormap); void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height); void D_EndDirectRect (int x, int y, int width, int height); void D_PolysetDraw (void); @@ -180,7 +180,7 @@ extern byte *r_skysource; // !!! must be kept the same as in quakeasm.h !!! #define TRANSPARENT_COLOR 0xFF -extern void *acolormap; // FIXME: should go away +extern const byte *acolormap; // FIXME: should go away //=======================================================================// diff --git a/include/quakeasm.h b/include/quakeasm.h index a3657fdc0..6a4342f2f 100644 --- a/include/quakeasm.h +++ b/include/quakeasm.h @@ -73,7 +73,7 @@ .extern C(surfrowbytes) .extern C(r_sourcemax) .extern C(r_stepback) - .extern C(colormap) + .extern C(r_colormap) .extern C(blocksize) .extern C(sourcesstep) .extern C(lightleft) diff --git a/include/r_local.h b/include/r_local.h index 0b15583ae..4ae111026 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -187,6 +187,8 @@ struct vulkan_ctx_s; void R_ClearTextures (void); void R_InitSurfaceChains (mod_brush_t *brush); +extern const byte *r_colormap; +void R_SetColormap (const byte *cmap); extern void R_Surf8Start (void); extern void R_Surf8End (void); extern void R_EdgeCodeStart (void); diff --git a/include/vid_internal.h b/include/vid_internal.h index 0136d0cc0..9df75a395 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -8,6 +8,7 @@ typedef struct vid_internal_s { void (*flush_caches) (void *data); void (*init_buffers) (void *data); void (*set_palette) (void *data, const byte *palette); + void (*set_colormap) (void *data, const byte *colormap); void (*choose_visual) (void *data); void (*create_context) (void *data); diff --git a/libs/video/renderer/sw/surf8.S b/libs/video/renderer/sw/surf8.S index c15d2c689..c01343525 100644 --- a/libs/video/renderer/sw/surf8.S +++ b/libs/video/renderer/sw/surf8.S @@ -778,7 +778,7 @@ LPatchTable8: C(R_SurfPatch): pushl %ebx - movl C(colormap),%eax + movl C(r_colormap),%eax movl $LPatchTable8,%ebx movl $32,%ecx LPatchLoop8: diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 6aba6ba03..05ae2c1fa 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -47,7 +47,7 @@ affinetridesc_t r_affinetridesc; -void *acolormap; // FIXME: should go away +const byte *acolormap; // FIXME: should go away trivertx_t *r_apverts; @@ -540,7 +540,7 @@ R_AliasSetupSkin (entity_t *ent) r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16; r_affinetridesc.skinheight = pmdl->skinheight; - acolormap = vid.colormap8; + acolormap = r_colormap; if (ent->renderer.skin) { tex_t *base; @@ -631,7 +631,7 @@ R_AliasDrawModel (entity_t *ent, alight_t *lighting) && r_recursiveaffinetriangles); if (!acolormap) - acolormap = vid.colormap8; + acolormap = r_colormap; if (r_affinetridesc.drawtype) { D_PolysetUpdateTables (); // FIXME: precalc... diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index e2691d2e5..6c6a5608b 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -315,7 +315,7 @@ R_IQMDrawModel (entity_t *ent, alight_t *plighting) r_recursiveaffinetriangles; //if (!acolormap) - acolormap = vid.colormap8; + acolormap = r_colormap; if (ent != vr_data.view_model) ziscale = (float) 0x8000 *(float) 0x10000; diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 5b459cf41..255da2ba6 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -60,7 +60,7 @@ # undef USE_INTEL_ASM //XXX asm pic hack #endif -void *colormap; +const byte *r_colormap; int r_numallocatededges; qboolean r_drawpolys; qboolean r_drawculledpolys; @@ -315,15 +315,19 @@ R_ViewChanged (void) r_aliastransition = r_aliastransbase->value * res_scale; r_resfudge = r_aliastransadj->value * res_scale; + D_ViewChanged (); +} + +void +R_SetColormap (const byte *cmap) +{ + r_colormap = cmap; // TODO: collect 386-specific code in one place #ifdef USE_INTEL_ASM Sys_MakeCodeWriteable ((long) R_Surf8Start, (long) R_Surf8End - (long) R_Surf8Start); - colormap = vid.colormap8; R_SurfPatch (); #endif // USE_INTEL_ASM - - D_ViewChanged (); } static inline void @@ -719,7 +723,7 @@ R_RenderView (void) if ((intptr_t) (&dummy) & 3) Sys_Error ("Stack is missaligned"); - if ((intptr_t) (&colormap) & 3) + if ((intptr_t) (&r_colormap) & 3) Sys_Error ("Globals are missaligned"); R_RenderView_ (); diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index c3938c282..601bf2d8d 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -50,15 +50,15 @@ int lightdelta, lightdeltastep; int lightright, lightleftstep, lightrightstep, blockdivshift; static unsigned int blockdivmask; void *prowdestbase; -unsigned char *pbasesource; +byte *pbasesource; int surfrowbytes; // used by ASM files unsigned int *r_lightptr; int r_stepback; int r_lightwidth; static int r_numhblocks; int r_numvblocks; -static unsigned char *r_source; -unsigned char *r_sourcemax; +static byte *r_source; +byte *r_sourcemax; void R_DrawSurfaceBlock_mip0 (void); void R_DrawSurfaceBlock_mip1 (void); @@ -275,7 +275,7 @@ void R_DrawSurfaceBlock_mip0 (void) { int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + byte pix, *psource, *prowdest; psource = pbasesource; prowdest = prowdestbase; @@ -297,8 +297,7 @@ R_DrawSurfaceBlock_mip0 (void) for (b = 15; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap8) - [(light & 0xFF00) + pix]; + prowdest[b] = r_colormap[(light & 0xFF00) + pix]; light += lightstep; } @@ -317,7 +316,7 @@ void R_DrawSurfaceBlock_mip1 (void) { int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + byte pix, *psource, *prowdest; psource = pbasesource; prowdest = prowdestbase; @@ -339,8 +338,7 @@ R_DrawSurfaceBlock_mip1 (void) for (b = 7; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap8) - [(light & 0xFF00) + pix]; + prowdest[b] = r_colormap[(light & 0xFF00) + pix]; light += lightstep; } @@ -359,7 +357,7 @@ void R_DrawSurfaceBlock_mip2 (void) { int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + byte pix, *psource, *prowdest; psource = pbasesource; prowdest = prowdestbase; @@ -381,8 +379,7 @@ R_DrawSurfaceBlock_mip2 (void) for (b = 3; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap8) - [(light & 0xFF00) + pix]; + prowdest[b] = r_colormap[(light & 0xFF00) + pix]; light += lightstep; } @@ -401,7 +398,7 @@ void R_DrawSurfaceBlock_mip3 (void) { int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + byte pix, *psource, *prowdest; psource = pbasesource; prowdest = prowdestbase; @@ -423,8 +420,7 @@ R_DrawSurfaceBlock_mip3 (void) for (b = 1; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap8) - [(light & 0xFF00) + pix]; + prowdest[b] = r_colormap[(light & 0xFF00) + pix]; light += lightstep; } diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index bfc881de6..bf3145b5c 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -63,6 +63,12 @@ sw_vid_render_set_palette (void *data, const byte *palette) sw_ctx->set_palette (sw_ctx, palette); } +static void +sw_vid_render_set_colormap (void *data, const byte *colormap) +{ + R_SetColormap (colormap); +} + static vid_model_funcs_t model_funcs = { 0, sw_Mod_LoadLighting, @@ -99,6 +105,7 @@ sw_vid_render_init (void) vr_data.vid->vid_internal->data = sw_ctx; vr_data.vid->vid_internal->set_palette = sw_vid_render_set_palette; + vr_data.vid->vid_internal->set_colormap = sw_vid_render_set_colormap; vr_data.vid->vid_internal->choose_visual = sw_vid_render_choose_visual; vr_data.vid->vid_internal->create_context = sw_vid_render_create_context; diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 08de11276..eb04efef9 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -133,6 +133,9 @@ VID_Init (byte *palette, byte *colormap) viddef.numpages = 1; viddef.colormap8 = colormap; viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; + if (vid_internal.set_colormap) { + vid_internal.set_colormap (vid_internal.data, colormap); + } VID_GetWindowSize (640, 480); Win_OpenDisplay (); diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index fb0fa703d..d60d1b9f1 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -110,6 +110,9 @@ VID_Init (byte *palette, byte *colormap) viddef.numpages = 2; viddef.colormap8 = colormap; viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; + if (vid_internal.set_colormap) { + vid_internal.set_colormap (vid_internal.data, colormap); + } srandom (getpid ()); From ca9e18b9d6df53a040ee4b6cb3477f2a50523c6d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Mar 2022 13:34:46 +0900 Subject: [PATCH 2585/3664] [renderer] Use initializer labels for vid_render_data Got tired of figuring out which initializers to remove when editing vid_render_data_t. --- libs/video/renderer/vid_common.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/vid_common.c b/libs/video/renderer/vid_common.c index 546bb4b9b..2a5285859 100644 --- a/libs/video/renderer/vid_common.c +++ b/libs/video/renderer/vid_common.c @@ -40,16 +40,25 @@ viddef_t vid; // global video state view_t scr_view; vid_render_data_t vid_render_data = { - &vid, &r_refdef, &scr_view, - 0, 0, 0, - 0, - 0, 0, - 0.0, - false, false, false, - 0, - 0, 0, - 0.0, 0.0, - 0, + .vid = &vid, + .refdef = &r_refdef, + .scr_view = &scr_view, + .scr_copytop = 0, + .scr_copyeverything = 0, + .scr_fullupdate = 0, + .viewsize_callback = 0, + .scr_viewsize = 0, + .graphheight = 0, + .min_wateralpha = 0.0, + .force_fullscreen = false, + .inhibit_viewmodel = false, + .paused = false, + .lineadj = 0, + .view_model = 0, + .gravity = 0, + .frametime = 0.0, + .realtime = 0.0, + .lightstyle = 0, }; vid_render_funcs_t *vid_render_funcs; From 75d7f4cecbf0a0642f36ab677bd3dfec1ee42eb1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Mar 2022 13:46:11 +0900 Subject: [PATCH 2586/3664] [renderer] Clean up particles a little The quake-specific enums are now in the client header, and the particle system now has a gravity field rather than getting it from vid_render_data (which I hope to eventually get rid of entirely). --- include/QF/plugin/vid_render.h | 1 - include/QF/render.h | 20 +------------------- include/client/particles.h | 20 ++++++++++++++++++++ libs/client/cl_particles.c | 6 ++++++ libs/video/renderer/r_part.c | 2 +- libs/video/renderer/vid_common.c | 1 - nq/source/cl_parse.c | 3 ++- qw/source/cl_parse.c | 3 ++- 8 files changed, 32 insertions(+), 24 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index e7027d07d..60fda8e3b 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -142,7 +142,6 @@ typedef struct vid_render_data_s { qboolean paused; int lineadj; struct entity_s *view_model; - float gravity; double frametime; double realtime; lightstyle_t *lightstyle; diff --git a/include/QF/render.h b/include/QF/render.h index 18c760f7f..b4f6c32d6 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -35,25 +35,6 @@ #include "QF/simd/types.h" #include "QF/ui/vrect.h" -typedef enum { - pt_static, - pt_grav, - pt_slowgrav, - pt_fire, - pt_explode, - pt_explode2, - pt_blob, - pt_blob2, - pt_smoke, - pt_smokecloud, - pt_bloodcloud, - pt_fadespark, - pt_fadespark2, - pt_fallfade, - pt_fallfadespark, - pt_flame -} ptype_t; - typedef enum { part_tex_dot, part_tex_spark, @@ -91,6 +72,7 @@ typedef struct partparm_s { } partparm_t; typedef struct psystem_s { + vec4f_t gravity; uint32_t maxparticles; uint32_t numparticles; particle_t *particles; diff --git a/include/client/particles.h b/include/client/particles.h index a56762bd8..0b91f9daf 100644 --- a/include/client/particles.h +++ b/include/client/particles.h @@ -29,6 +29,25 @@ #include "QF/render.h" +typedef enum { + pt_static, + pt_grav, + pt_slowgrav, + pt_fire, + pt_explode, + pt_explode2, + pt_blob, + pt_blob2, + pt_smoke, + pt_smokecloud, + pt_bloodcloud, + pt_fadespark, + pt_fadespark2, + pt_fallfade, + pt_fallfadespark, + pt_flame +} ptype_t; + typedef struct cl_particle_funcs_s { void (*RocketTrail) (vec4f_t start, vec4f_t end); void (*GrenadeTrail) (vec4f_t start, vec4f_t end); @@ -70,6 +89,7 @@ extern float cl_frametime; extern float cl_realtime; void CL_Particles_Init (void); +void CL_ParticlesGravity (float gravity); struct model_s; void CL_LoadPointFile (const struct model_s *model); diff --git a/libs/client/cl_particles.c b/libs/client/cl_particles.c index e43a028c2..7ff731315 100644 --- a/libs/client/cl_particles.c +++ b/libs/client/cl_particles.c @@ -1279,3 +1279,9 @@ CL_Particles_Init (void) "Sets particle style. 0 for Id, 1 for QF."); CL_ParticleFunctionInit (); } + +void +CL_ParticlesGravity (float gravity) +{ + cl_psystem->gravity = (vec4f_t) { 0, 0, -gravity, 0 }; +} diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index fd12cc206..e0b6c56be 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -88,7 +88,7 @@ void R_RunParticles (float dT) { psystem_t *ps = &r_psystem;//FIXME - vec4f_t gravity = {0, 0, -r_data->gravity, 0}; + vec4f_t gravity = ps->gravity; unsigned j = 0; for (unsigned i = 0; i < ps->numparticles; i++) { diff --git a/libs/video/renderer/vid_common.c b/libs/video/renderer/vid_common.c index 2a5285859..c8edf8067 100644 --- a/libs/video/renderer/vid_common.c +++ b/libs/video/renderer/vid_common.c @@ -55,7 +55,6 @@ vid_render_data_t vid_render_data = { .paused = false, .lineadj = 0, .view_model = 0, - .gravity = 0, .frametime = 0.0, .realtime = 0.0, .lightstyle = 0, diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index f186b31c8..de98ec63d 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -56,6 +56,7 @@ #include "QF/plugin/vid_render.h" #include "QF/scene/entity.h" +#include "client/particles.h" #include "client/temp_entities.h" #include "client/world.h" @@ -378,7 +379,7 @@ CL_ParseServerInfo (void) Hunk_Check (0); // make sure nothing is hurt noclip_anglehack = false; // noclip is turned off at start - r_data->gravity = 800.0; // Set up gravity for renderer effects + CL_ParticlesGravity (800); // Set up gravity for renderer effects done: S_UnblockSound (); } diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index b27dff394..2dfe6e25b 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -67,6 +67,7 @@ #include "sbar.h" #include "client/effects.h" +#include "client/particles.h" #include "client/temp_entities.h" #include "client/view.h" #include "client/world.h" @@ -782,7 +783,7 @@ CL_ParseServerData (void) // get the movevars movevars.gravity = MSG_ReadFloat (net_message); - r_data->gravity = movevars.gravity; // Gravity for renderer effects + CL_ParticlesGravity (movevars.gravity);// Gravity for renderer effects movevars.stopspeed = MSG_ReadFloat (net_message); movevars.maxspeed = MSG_ReadFloat (net_message); movevars.spectatormaxspeed = MSG_ReadFloat (net_message); From 3c86764eb23cc4b5fdb5e8b4dd6a1e1b707e4a44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Mar 2022 14:40:48 +0900 Subject: [PATCH 2587/3664] [scene] Move entity_t etc into scene headers I meant to do this a while ago but forgot about it. Things are a bit of a mess in that the renderer knows too much about entities, but eventually the renderer will know about only things to render (meshes, particles, etc). --- include/QF/GL/qf_iqm.h | 3 +- include/QF/render.h | 45 ---------------------------- include/QF/scene/entity.h | 46 ++++++++++++++++++++++++++++- include/r_internal.h | 8 +++-- include/r_local.h | 35 ++++++++++++---------- libs/client/cl_view.c | 1 + libs/ruamoko/rua_scene.c | 2 +- libs/video/renderer/gl/gl_mod_iqm.c | 1 + libs/video/renderer/r_alias.c | 1 + libs/video/renderer/r_bsp.c | 2 ++ libs/video/renderer/r_iqm.c | 1 + libs/video/renderer/r_main.c | 2 -- libs/video/renderer/r_sprite.c | 1 + libs/video/renderer/sw/d_surf.c | 1 + libs/video/renderer/sw/sw_rdraw.c | 1 + nq/include/client.h | 4 +-- qw/include/cl_ents.h | 2 +- 17 files changed, 84 insertions(+), 72 deletions(-) diff --git a/include/QF/GL/qf_iqm.h b/include/QF/GL/qf_iqm.h index 47a77d6da..f661bcde7 100644 --- a/include/QF/GL/qf_iqm.h +++ b/include/QF/GL/qf_iqm.h @@ -44,6 +44,7 @@ typedef struct glsliqm_s { iqmvertexarray *color; } gliqm_t; -void gl_R_DrawIQMModel (entity_t *ent); +struct entity_s; +void gl_R_DrawIQMModel (struct entity_s *ent); #endif//__QF_GL_qf_iqm_h diff --git a/include/QF/render.h b/include/QF/render.h index b4f6c32d6..8a3feb5df 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -120,49 +120,6 @@ typedef struct //=============== -typedef struct animation_s { - int frame; - float syncbase; // randomize time base for local animations - float frame_start_time; - float frame_interval; - int pose1; - int pose2; - float blend; - int nolerp; // don't lerp this frame (pose data invalid) -} animation_t; - -typedef struct visibility_s { - struct entity_s *entity; // owning entity - struct efrag_s *efrag; // linked list of efrags - struct mnode_s *topnode; // bmodels, first world node that - // splits bmodel, or NULL if not split - // applies to other models, too - // found in an active leaf - int trivial_accept; // view clipping (frustum and depth) -} visibility_t; - -typedef struct renderer_s { - struct model_s *model; // NULL = no model - struct skin_s *skin; - float colormod[4]; // color tint and alpha for model - int skinnum; // for Alias models - int fullbright; - float min_light; - mat4_t full_transform; -} renderer_t; - -typedef struct entity_s { - struct entity_s *next; - struct transform_s *transform; - int id; ///< scene id - animation_t animation; - visibility_t visibility; - renderer_t renderer; - int active; - //XXX FIXME XXX should not be here - vec4f_t old_origin; -} entity_t; - typedef union refframe_s { mat4f_t mat; struct { @@ -240,8 +197,6 @@ void R_LoadModule (struct vid_internal_s *vid_internal); struct progs_s; void R_Progs_Init (struct progs_s *pr); -void R_AddEfrags (mod_brush_t *, entity_t *ent); -void R_RemoveEfrags (entity_t *ent); dlight_t *R_AllocDlight (int key); void R_MaxDlightsCheck (struct cvar_s *var); void R_DecayLights (double frametime); diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index fd5ca8bc0..2345ac3e2 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -45,7 +45,48 @@ #include "QF/scene/hierarchy.h" #include "QF/scene/transform.h" -#include "QF/render.h" //FIXME move entity_t here +typedef struct animation_s { + int frame; + float syncbase; // randomize time base for local animations + float frame_start_time; + float frame_interval; + int pose1; + int pose2; + float blend; + int nolerp; // don't lerp this frame (pose data invalid) +} animation_t; + +typedef struct visibility_s { + struct entity_s *entity; // owning entity + struct efrag_s *efrag; // linked list of efrags + struct mnode_s *topnode; // bmodels, first world node that + // splits bmodel, or NULL if not split + // applies to other models, too + // found in an active leaf + int trivial_accept; // view clipping (frustum and depth) +} visibility_t; + +typedef struct renderer_s { + struct model_s *model; // NULL = no model + struct skin_s *skin; + float colormod[4]; // color tint and alpha for model + int skinnum; // for Alias models + int fullbright; + float min_light; + mat4_t full_transform; +} renderer_t; + +typedef struct entity_s { + struct entity_s *next; + struct transform_s *transform; + int id; ///< scene id + animation_t animation; + visibility_t visibility; + renderer_t renderer; + int active; + //XXX FIXME XXX should not be here + vec4f_t old_origin; +} entity_t; typedef struct entqueue_s { set_t *queued_ents; @@ -78,6 +119,9 @@ EntQueue_AddEntity (entqueue_t *queue, entity_t *ent, int queue_num) DARRAY_APPEND (&queue->ent_queues[queue_num], ent); } } +struct mod_brush_s; +void R_AddEfrags (struct mod_brush_s *, entity_t *ent); +void R_RemoveEfrags (entity_t *ent); ///@} diff --git a/include/r_internal.h b/include/r_internal.h index c4b5a15b7..456c4572a 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -69,17 +69,19 @@ void R_ClearDlights (void); int R_InitGraphTextures (int base); -void R_DrawAliasModel (entity_t *e); +struct entity_s; +struct animation_s; +void R_DrawAliasModel (struct entity_s *e); void R_MarkLeaves (void); void GL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette); -int R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, +int R_BillboardFrame (struct entity_s *ent, int orientation, const vec3_t cameravec, vec3_t bbup, vec3_t bbright, vec3_t bbfwd); mspriteframe_t *R_GetSpriteFrame (const msprite_t *sprite, - const animation_t *animation); + const struct animation_s *animation); // These correspond to the standard box sides for OpenGL cube maps but with // TOP and BOTTOM swapped due to lelt/right handed systems (quake/gl are right, diff --git a/include/r_local.h b/include/r_local.h index 4ae111026..d5ca6113c 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -145,37 +145,40 @@ union refframe_s; void R_SetFrustum (plane_t *frustum, const union refframe_s *frame, float fov_x, float fov_y); +struct entity_s; + void R_SpriteBegin (void); void R_SpriteEnd (void); -void R_DrawSprite (entity_t *ent); -void R_RenderFace (entity_t *ent, msurface_t *fa, int clipflags); -void R_RenderPoly (entity_t *ent, msurface_t *fa, int clipflags); -void R_RenderBmodelFace (entity_t *ent, bedge_t *pedges, msurface_t *psurf); +void R_DrawSprite (struct entity_s *ent); +void R_RenderFace (struct entity_s *ent, msurface_t *fa, int clipflags); +void R_RenderPoly (struct entity_s *ent, msurface_t *fa, int clipflags); +void R_RenderBmodelFace (struct entity_s *ent, bedge_t *pedges, msurface_t *psurf); void R_TransformFrustum (void); void R_SetSkyFrame (void); void R_DrawSurfaceBlock (void); -texture_t *R_TextureAnimation (const entity_t *entity, msurface_t *surf) __attribute__((pure)); +texture_t *R_TextureAnimation (const struct entity_s *entity, msurface_t *surf) __attribute__((pure)); void R_GenSkyTile (void *pdest); void R_SurfPatch (void); -void R_DrawSubmodelPolygons (entity_t *ent, model_t *pmodel, int clipflags, struct mnode_s *topnode); -void R_DrawSolidClippedSubmodelPolygons (entity_t *ent, model_t *pmodel, struct mnode_s *topnode); +void R_DrawSubmodelPolygons (struct entity_s *ent, model_t *pmodel, int clipflags, struct mnode_s *topnode); +void R_DrawSolidClippedSubmodelPolygons (struct entity_s *ent, model_t *pmodel, struct mnode_s *topnode); void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); surf_t *R_GetSurf (void); void R_AliasClipAndProjectFinalVert (finalvert_t *fv, auxvert_t *av); -void R_AliasDrawModel (entity_t *ent, alight_t *plighting); -void R_IQMDrawModel (entity_t *ent, alight_t *plighting); -maliasskindesc_t *R_AliasGetSkindesc (animation_t *animation, int skinnum, aliashdr_t *hdr); -maliasframedesc_t *R_AliasGetFramedesc (animation_t *animation, aliashdr_t *hdr); -float R_AliasGetLerpedFrames (animation_t *animation, aliashdr_t *hdr); -float R_IQMGetLerpedFrames (entity_t *ent, iqm_t *hdr); +void R_AliasDrawModel (struct entity_s *ent, alight_t *plighting); +void R_IQMDrawModel (struct entity_s *ent, alight_t *plighting); +struct animation_s; +maliasskindesc_t *R_AliasGetSkindesc (struct animation_s *animation, int skinnum, aliashdr_t *hdr); +maliasframedesc_t *R_AliasGetFramedesc (struct animation_s *animation, aliashdr_t *hdr); +float R_AliasGetLerpedFrames (struct animation_s *animation, aliashdr_t *hdr); +float R_IQMGetLerpedFrames (struct entity_s *ent, iqm_t *hdr); iqmframe_t *R_IQMBlendFrames (const iqm_t *iqm, int frame1, int frame2, float blend, int extra); iqmframe_t *R_IQMBlendPalette (const iqm_t *iqm, int frame1, int frame2, float blend, int extra, iqmblend_t *blend_palette, int palette_size); -float R_EntityBlend (animation_t *animation, int pose, float interval); +float R_EntityBlend (struct animation_s *animation, int pose, float interval); void R_BeginEdgeFrame (void); void R_ScanEdges (void); void D_DrawSurfaces (void); @@ -229,7 +232,7 @@ typedef struct btofpoly_s { extern int numbtofpolys; void R_InitTurb (void); -void R_ZDrawSubmodelPolys (entity_t *ent, model_t *clmodel); +void R_ZDrawSubmodelPolys (struct entity_s *ent, model_t *clmodel); // Alias models =========================================== @@ -244,7 +247,7 @@ extern auxvert_t *pauxverts; extern float ziscale; extern float aliastransform[3][4]; -qboolean R_AliasCheckBBox (entity_t *ent); +qboolean R_AliasCheckBBox (struct entity_s *ent); // turbulence stuff ======================================= diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index 7668ca832..a4120eeab 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -34,6 +34,7 @@ #include "QF/screen.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/entity.h" #include "QF/scene/transform.h" #include "QF/simd/vec4f.h" diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 9656ba0da..11aee7eb7 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -39,8 +39,8 @@ #include "QF/cmem.h" #include "QF/hash.h" #include "QF/progs.h" -#include "QF/render.h" +#include "QF/scene/entity.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" diff --git a/libs/video/renderer/gl/gl_mod_iqm.c b/libs/video/renderer/gl/gl_mod_iqm.c index f33828c29..2b2555020 100644 --- a/libs/video/renderer/gl/gl_mod_iqm.c +++ b/libs/video/renderer/gl/gl_mod_iqm.c @@ -49,6 +49,7 @@ #include "QF/GL/qf_iqm.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_vid.h" +#include "QF/scene/entity.h" #include "r_internal.h" diff --git a/libs/video/renderer/r_alias.c b/libs/video/renderer/r_alias.c index 6dea420b6..bd3b7b931 100644 --- a/libs/video/renderer/r_alias.c +++ b/libs/video/renderer/r_alias.c @@ -29,6 +29,7 @@ #endif #include "QF/sys.h" +#include "QF/scene/entity.h" #include "r_internal.h" diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 2abb2c05d..53b778647 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -39,6 +39,8 @@ #include "QF/set.h" #include "QF/sys.h" +#include "QF/scene/entity.h" + #include "r_internal.h" static mleaf_t *r_oldviewleaf; diff --git a/libs/video/renderer/r_iqm.c b/libs/video/renderer/r_iqm.c index 84ce67744..aaecb5aab 100644 --- a/libs/video/renderer/r_iqm.c +++ b/libs/video/renderer/r_iqm.c @@ -43,6 +43,7 @@ #include "QF/render.h" #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/entity.h" #include "r_internal.h" diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index 846a57dad..c93c8f467 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -51,8 +51,6 @@ qboolean r_force_fullscreen; qboolean r_paused; double r_realtime; double r_frametime; -entity_t *r_view_model; -entity_t *r_player_entity; double r_time1; int r_lineadj; qboolean r_active; diff --git a/libs/video/renderer/r_sprite.c b/libs/video/renderer/r_sprite.c index ecce7ad55..cfe0beb59 100644 --- a/libs/video/renderer/r_sprite.c +++ b/libs/video/renderer/r_sprite.c @@ -29,6 +29,7 @@ #endif #include "QF/sys.h" +#include "QF/scene/entity.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index cc90bd95b..f16122d79 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -33,6 +33,7 @@ #include "QF/qargs.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/entity.h" #include "compat.h" #include "d_local.h" diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index 38e80cfd1..1d7a2a545 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -29,6 +29,7 @@ #endif #include "QF/render.h" +#include "QF/scene/entity.h" #include "r_internal.h" diff --git a/nq/include/client.h b/nq/include/client.h index 62b24a4d4..28394ce52 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -233,7 +233,7 @@ extern struct cvar_s *noskins; extern client_state_t cl; -extern entity_t *cl_entities[MAX_EDICTS]; +extern struct entity_s *cl_entities[MAX_EDICTS]; extern double cl_msgtime[MAX_EDICTS]; extern struct set_s cl_forcelink; @@ -291,7 +291,7 @@ void CL_NewTranslation (int slot, struct skin_s *skin); void CL_SignonReply (void); void CL_RelinkEntities (void); void CL_ClearEnts (void); -entity_t *CL_GetEntity (int num); +struct entity_s *CL_GetEntity (int num); extern double realtime; diff --git a/qw/include/cl_ents.h b/qw/include/cl_ents.h index 53ec080f7..93872edda 100644 --- a/qw/include/cl_ents.h +++ b/qw/include/cl_ents.h @@ -41,7 +41,7 @@ void CL_ParsePacketEntities (qboolean delta); void CL_SetSolidEntities (void); void CL_ParsePlayerinfo (void); void CL_Ents_Init (void); -entity_t *CL_GetEntity (int num); +struct entity_s *CL_GetEntity (int num); extern struct cvar_s *cl_deadbodyfilter; extern struct cvar_s *cl_gibfilter; From f21c2178fa7ffdd2b4f87fdee89fcd1bcf7668a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 29 Mar 2022 14:45:49 +0900 Subject: [PATCH 2588/3664] [renderer] Move cshift defs into client Definitely not something for the renderer to care about directly (ie, at most, a post-process filter setting or palette update, which is how it actually is currently). --- include/QF/render.h | 15 --------------- include/client/view.h | 14 +++++++++++++- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index 8a3feb5df..124e9ae0a 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -172,21 +172,6 @@ typedef struct { struct mleaf_s *viewleaf; } refdef_t; -// color shifts ============================================================= - -typedef struct { - int destcolor[3]; - int percent; // 0-255 - double time; - int initialpct; -} cshift_t; - -#define CSHIFT_CONTENTS 0 -#define CSHIFT_DAMAGE 1 -#define CSHIFT_BONUS 2 -#define CSHIFT_POWERUP 3 -#define NUM_CSHIFTS 4 - // REFRESH ==================================================================== extern struct texture_s *r_notexture_mip; diff --git a/include/client/view.h b/include/client/view.h index 59d7959f0..edea89758 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -30,9 +30,21 @@ #define __client_view_h #include "QF/mathlib.h" -#include "QF/render.h" #include "QF/simd/types.h" +typedef struct { + int destcolor[3]; + int percent; // 0-255 + double time; + int initialpct; +} cshift_t; + +#define CSHIFT_CONTENTS 0 +#define CSHIFT_DAMAGE 1 +#define CSHIFT_BONUS 2 +#define CSHIFT_POWERUP 3 +#define NUM_CSHIFTS 4 + #define INFO_CSHIFT_BONUS (1 << 0) #define INFO_CSHIFT_CONTENTS (1 << 1) #define INFO_CSHIFT_DAMAGE (1 << 2) From 9fbd16be05cf60ad4778638818eb9debc5ebdab2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Mar 2022 11:05:16 +0900 Subject: [PATCH 2589/3664] [renderer] Avoid infinite loop If the entity didn't have a known model type, R_StoreEfrags would get stuck in an infinite loop (fortunately, never actually happened. The result of making it not call Sys_Error for unknown models)). --- libs/video/renderer/r_efrag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 09129ed8c..4a60ed6d1 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -236,10 +236,10 @@ R_StoreEfrags (const efrag_t *efrag) case mod_sprite: case mod_iqm: EntQueue_AddEntity (r_ent_queue, ent, model->type); - efrag = efrag->leafnext; break; default: } + efrag = efrag->leafnext; } } From 495dd759f0e385c91dea50339230f46c26150950 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Mar 2022 14:55:32 +0900 Subject: [PATCH 2590/3664] [renderer] Clean up FOV and viewport handling Viewport and FOV updates are now separate so updating one doesn't cause recalculations of the other. Also, perspective setup is now done directly from the tangents of the half angles for fov_x and fov_y making the renderers independent of fov/aspect mode. I imagine things are a bit of a mess with view size changes, and especially screen size changes (not supported yet anyway), and vulkan winds up updating its projection matrices every frame, but everything that's expected to work does (vulkan errors out for fisheye or warp due to frame buffer creation not being supported yet). --- include/QF/Vulkan/projection.h | 6 +- include/QF/Vulkan/qf_matrices.h | 1 - include/QF/plugin/vid_render.h | 3 +- include/QF/render.h | 2 - include/QF/screen.h | 1 + include/vid_gl.h | 4 + libs/video/renderer/gl/gl_fisheye.c | 2 - libs/video/renderer/gl/gl_rmain.c | 33 +----- libs/video/renderer/gl/gl_rmisc.c | 5 - libs/video/renderer/glsl/glsl_main.c | 29 +---- libs/video/renderer/r_cvar.c | 2 +- libs/video/renderer/r_screen.c | 27 ++--- libs/video/renderer/sw/sw_rmain.c | 108 ------------------ libs/video/renderer/vid_render_gl.c | 30 ++++- libs/video/renderer/vid_render_glsl.c | 30 ++++- libs/video/renderer/vid_render_sw.c | 112 ++++++++++++++++++- libs/video/renderer/vid_render_vulkan.c | 32 ++++-- libs/video/renderer/vulkan/projection.c | 18 +-- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- libs/video/renderer/vulkan/vulkan_matrices.c | 35 ------ 20 files changed, 224 insertions(+), 258 deletions(-) diff --git a/include/QF/Vulkan/projection.h b/include/QF/Vulkan/projection.h index 7a1dc96bd..7936008aa 100644 --- a/include/QF/Vulkan/projection.h +++ b/include/QF/Vulkan/projection.h @@ -5,8 +5,8 @@ void QFV_Orthographic (mat4f_t proj, float xmin, float xmax, float ymin, float ymax, float znear, float zfar); -void QFV_PerspectiveTan (mat4f_t proj, float fov, float aspect); -void QFV_PerspectiveCos (mat4f_t proj, float fov, float aspect); -void QFV_Perspective (mat4f_t proj, float fov, float aspect); +// fov_x and fov_y are tan(fov/2) for x and y respectively +void QFV_PerspectiveTan (mat4f_t proj, float fov_x, float fov_y); +void QFV_PerspectiveCos (mat4f_t proj, float fov); #endif//__QF_Vulkan_projection_h diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index 9a3df6f58..4a8d0e413 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -78,7 +78,6 @@ typedef struct matrixctx_s { struct vulkan_ctx_s; struct qfv_renderframe_s; -void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx); void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx); void Vulkan_SetViewMatrix (struct vulkan_ctx_s *ctx, mat4f_t view); void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky); diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 60fda8e3b..c0ad899c9 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -107,7 +107,6 @@ typedef struct vid_render_funcs_s { void (*R_LoadSkys) (const char *); void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); - void (*R_ViewChanged) (void); void (*begin_frame) (void); void (*render_view) (void); @@ -122,6 +121,8 @@ typedef struct vid_render_funcs_s { struct framebuffer_s *(*create_frame_buffer) (int width, int height); void (*bind_framebuffer) (struct framebuffer_s *framebuffer); void (*set_viewport) (const struct vrect_s *view); + // x and y are tan(f/2) for fov_x and fov_y + void (*set_fov) (float x, float y); vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/QF/render.h b/include/QF/render.h index 124e9ae0a..d989bd38b 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -166,8 +166,6 @@ typedef struct { int ambientlight; int drawflat; - float fov_x, fov_y; - struct model_s *worldmodel; struct mleaf_s *viewleaf; } refdef_t; diff --git a/include/QF/screen.h b/include/QF/screen.h index 892fd6cf3..11a591f87 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -42,6 +42,7 @@ typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array void SCR_UpdateScreen (struct transform_s *camera, double realtime, SCR_Func *scr_funcs); +void SCR_SetFOV (float fov); // control whether the 3d viewport is user-controlled or always fullscreen void SCR_SetFullscreen (qboolean fullscreen); void SCR_SetBottomMargin (int lines); diff --git a/include/vid_gl.h b/include/vid_gl.h index 26d445770..6249790dd 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -1,6 +1,8 @@ #ifndef __vid_gl_h #define __vid_gl_h +#include "QF/simd/types.h" + // GL_context is a pointer to opaque data typedef struct GL_context *GL_context; @@ -13,6 +15,8 @@ typedef struct gl_ctx_s { void *(*get_proc_address) (const char *name, qboolean crit); void (*end_rendering) (void); + mat4f_t projection; + int begun; double start_time; int brush_polys; diff --git a/libs/video/renderer/gl/gl_fisheye.c b/libs/video/renderer/gl/gl_fisheye.c index edace6c55..bb0a34e21 100644 --- a/libs/video/renderer/gl/gl_fisheye.c +++ b/libs/video/renderer/gl/gl_fisheye.c @@ -166,8 +166,6 @@ gl_FisheyeScreen (framebuffer_t *fb) gl_framebuffer_t *buffer = fb->buffer; - qfglViewport (r_refdef.vrect.x, r_refdef.vrect.x, - r_refdef.vrect.width, r_refdef.vrect.height); qfglMatrixMode (GL_PROJECTION); qfglLoadIdentity (); qfglOrtho (0, r_refdef.vrect.width, r_refdef.vrect.height, 0, -9999, 9999); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index a782abae0..19da42cbe 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -229,40 +229,11 @@ R_DrawViewModel (void) qfglDepthRange (gldepthmin, gldepthmax); } -static void -R_Perspective (void) -{ - float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; - float f = 1 / tan (r_refdef.fov_y * M_PI / 360); - float neard, fard; - mat4f_t proj; - - neard = r_nearclip->value; - fard = r_farclip->value; - - // NOTE columns! - proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 }; - proj[1] = (vec4f_t) { 0, f, 0, 0 }; - proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 }; - proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 }; - - // convert 0..1 depth buffer range to -1..1 - static mat4f_t depth_range = { - { 1, 0, 0, 0}, - { 0, 1, 0, 0}, - { 0, 0, 2, 0}, - { 0, 0,-1, 1}, - }; - mmulf (proj, depth_range, proj); - - qfglMatrixMode (GL_PROJECTION); - qfglLoadMatrixf (&proj[0][0]); -} - static void R_SetupGL (void) { - R_Perspective (); + qfglMatrixMode (GL_PROJECTION); + qfglLoadMatrixf (&gl_ctx->projection[0][0]); qfglFrontFace (GL_CW); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index f5f822dd6..fc72d7f96 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -200,8 +200,3 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) register_textures (&models[i]->brush); } } - -void -gl_R_ViewChanged (void) -{ -} diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index c0195d394..892f8d235 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -68,33 +68,6 @@ mat4f_t glsl_projection; mat4f_t glsl_view; -void -glsl_R_ViewChanged (void) -{ - float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; - float f = 1 / tan (r_refdef.fov_y * M_PI / 360); - float neard, fard; - vec4f_t *proj = glsl_projection; - - neard = r_nearclip->value; - fard = r_farclip->value; - - // NOTE columns! - proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 }; - proj[1] = (vec4f_t) { 0, f, 0, 0 }; - proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 }; - proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 }; - - // convert 0..1 depth buffer range to -1..1 - static mat4f_t depth_range = { - { 1, 0, 0, 0}, - { 0, 1, 0, 0}, - { 0, 0, 2, 0}, - { 0, 0,-1, 1}, - }; - mmulf (proj, depth_range, proj); -} - static void R_SetupView (void) { @@ -164,6 +137,8 @@ glsl_R_RenderView (void) return; } + memcpy (glsl_projection, glsl_ctx->projection, sizeof (mat4f_t)); + R_SetupView (); glsl_R_DrawWorld (); glsl_R_DrawSky (); diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index c7b96969c..83c5f1958 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -167,7 +167,7 @@ scr_fov_f (cvar_t *var) if (fov != var->value) { Cvar_SetValue (var, fov); } else { - r_data->vid->recalc_refdef = 1; + SCR_SetFOV (var->value); } } diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 5de3b8184..cd8ff5102 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -69,6 +69,9 @@ static qpic_t *scr_turtle; static framebuffer_t *fisheye_cube_map; static framebuffer_t *warp_buffer; +static float fov_x, fov_y; +static float tan_fov_x, tan_fov_y; + static mat4f_t box_rotations[] = { [BOX_FRONT] = { { 1, 0, 0, 0}, // front @@ -146,8 +149,8 @@ R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) set_vrect (vrectin, vrect, lineadj); } -static void -set_fov (float fov) +void +SCR_SetFOV (float fov) { refdef_t *refdef = r_data->refdef; @@ -158,8 +161,11 @@ set_fov (float fov) double w = refdef->vrect.width; double h = refdef->vrect.height; - refdef->fov_x = fov; - refdef->fov_y = 360 * atan2 (s * h, c * w) / M_PI; + fov_x = fov; + fov_y = 360 * atan2 (s * h, c * w) / M_PI; + tan_fov_x = s / c; + tan_fov_y = (s * h) / (c * w); + r_funcs->set_fov (tan_fov_x, tan_fov_y); } static void @@ -172,9 +178,6 @@ SCR_CalcRefdef (void) view_setgeometry (view, rect->x, rect->y, rect->width, rect->height); - // notify the refresh of the change - r_funcs->R_ViewChanged (); - // force a background redraw r_data->scr_fullupdate = 0; } @@ -210,10 +213,8 @@ render_side (int side) r_refdef.frame.mat[3] = r_refdef.camera[3]; refdef_t *refdef = r_data->refdef; - R_SetFrustum (refdef->frustum, &refdef->frame, - refdef->fov_x, refdef->fov_y); + R_SetFrustum (refdef->frustum, &refdef->frame, 90, 90); - r_data->refdef->fov_x = r_data->refdef->fov_y = 90; r_funcs->bind_framebuffer (&fisheye_cube_map[side]); render_scene (); @@ -256,8 +257,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) refdef->frame.mat[1] = refdef->camera[0]; refdef->frame.mat[2] = refdef->camera[2]; refdef->frame.mat[3] = refdef->camera[3]; - R_SetFrustum (refdef->frustum, &refdef->frame, - refdef->fov_x, refdef->fov_y); + R_SetFrustum (refdef->frustum, &refdef->frame, fov_x, fov_y); r_data->realtime = realtime; scr_copytop = r_data->scr_copyeverything = 0; @@ -292,6 +292,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) int side = fisheye_cube_map->width; vrect_t feye = { 0, 0, side, side }; r_funcs->set_viewport (&feye); + r_funcs->set_fov (1, 1); //FIXME shouldn't be every frame (2d stuff) switch (scr_fviews->int_val) { case 6: render_side (BOX_BEHIND); case 5: render_side (BOX_BOTTOM); @@ -335,7 +336,7 @@ update_vrect (void) vrect.height = r_data->vid->height; set_vrect (&vrect, &refdef->vrect, r_data->lineadj); - set_fov (scr_fov->value); + SCR_SetFOV (scr_fov->value); } void diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 255da2ba6..74ad36338 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -67,7 +67,6 @@ qboolean r_drawculledpolys; qboolean r_worldpolysbacktofront; qboolean r_recursiveaffinetriangles = true; int r_pixbytes = 1; -float r_aliasuvscale = 1.0; int r_outofsurfaces; int r_outofedges; @@ -211,113 +210,6 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_viewchanged = false; } -/* - R_ViewChanged - - Called every time the vid structure or r_refdef changes. - Guaranteed to be called before the first refresh -*/ -void -R_ViewChanged (void) -{ - int i; - float res_scale; - - r_viewchanged = true; - -#define SHIFT20(x) (((x) << 20) + (1 << 19) - 1) - r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; - r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; - r_refdef.vrectx_adj_shift20 = SHIFT20 (r_refdef.vrect.x); - r_refdef.vrectright_adj_shift20 = SHIFT20 (r_refdef.vrectright); - - r_refdef.fvrectx = (float) r_refdef.vrect.x; - r_refdef.fvrecty = (float) r_refdef.vrect.y; - r_refdef.fvrectright = (float) r_refdef.vrectright; - r_refdef.fvrectbottom = (float) r_refdef.vrectbottom; - - r_refdef.fvrectx_adj = (float) r_refdef.vrect.x - 0.5; - r_refdef.fvrecty_adj = (float) r_refdef.vrect.y - 0.5; - r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5; - r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5; - - int aleft = r_refdef.vrect.x * r_aliasuvscale; - int atop = r_refdef.vrect.y * r_aliasuvscale; - int awidth = r_refdef.vrect.width * r_aliasuvscale; - int aheight = r_refdef.vrect.height * r_aliasuvscale; - r_refdef.aliasvrectleft = aleft; - r_refdef.aliasvrecttop = atop; - r_refdef.aliasvrectright = aleft + awidth; - r_refdef.aliasvrectbottom = atop + aheight; - - // values for perspective projection - // if math were exact, the values would range from 0.5 to to range+0.5 - // hopefully they wll be in the 0.000001 to range+.999999 and truncate - // the polygon rasterization will never render in the first row or column - // but will definately render in the [range] row and column, so adjust the - // buffer origin to get an exact edge to edge fill - xcenter = r_refdef.vrect.width * XCENTERING + r_refdef.vrect.x - 0.5; - ycenter = r_refdef.vrect.height * YCENTERING + r_refdef.vrect.y - 0.5; - aliasxcenter = xcenter * r_aliasuvscale; - aliasycenter = ycenter * r_aliasuvscale; - - pixelAspect = 1;//FIXME vid.aspect; - - float aspect = r_refdef.vrect.width * pixelAspect / r_refdef.vrect.height; - // 320*200 1.0 pixelAspect = 1.6 aspect - // 320*240 1.0 pixelAspect = 1.3333 aspect - // proper 320*200 pixelAspect = 0.8333333 - - float hFOV = 2.0 * tan (r_refdef.fov_x / 360 * M_PI); - float vFOV = hFOV / aspect; - - // general perspective scaling - xscale = r_refdef.vrect.width / hFOV; - yscale = xscale * pixelAspect; - xscaleinv = 1.0 / xscale; - yscaleinv = 1.0 / yscale; - // perspective scaling for alias models - aliasxscale = xscale * r_aliasuvscale; - aliasyscale = yscale * r_aliasuvscale; - // perspective scaling for paricle position - xscaleshrink = (r_refdef.vrect.width - 6) / hFOV; - yscaleshrink = xscaleshrink * pixelAspect; - - // left side clip - screenedge[0].normal[0] = -1.0 / (XCENTERING * hFOV); - screenedge[0].normal[1] = 0; - screenedge[0].normal[2] = 1; - screenedge[0].type = PLANE_ANYZ; - - // right side clip - screenedge[1].normal[0] = 1.0 / ((1.0 - XCENTERING) * hFOV); - screenedge[1].normal[1] = 0; - screenedge[1].normal[2] = 1; - screenedge[1].type = PLANE_ANYZ; - - // top side clip - screenedge[2].normal[0] = 0; - screenedge[2].normal[1] = -1.0 / (YCENTERING * vFOV); - screenedge[2].normal[2] = 1; - screenedge[2].type = PLANE_ANYZ; - - // bottom side clip - screenedge[3].normal[0] = 0; - screenedge[3].normal[1] = 1.0 / ((1.0 - YCENTERING) * vFOV); - screenedge[3].normal[2] = 1; - screenedge[3].type = PLANE_ANYZ; - - for (i = 0; i < 4; i++) - VectorNormalize (screenedge[i].normal); - - res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) / - (320.0 * 152.0)) * (2.0 / hFOV); - r_aliastransition = r_aliastransbase->value * res_scale; - r_resfudge = r_aliastransadj->value * res_scale; - - D_ViewChanged (); -} - void R_SetColormap (const byte *cmap) { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 7d31c65d2..687f8765e 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -421,19 +421,43 @@ gl_bind_framebuffer (framebuffer_t *framebuffer) vrect_t r = { 0, 0, width, height }; R_SetVrect (&r, &r_refdef.vrect, 0); - gl_R_ViewChanged (); } static void gl_set_viewport (const vrect_t *view) { int x = view->x; - int y = vid.height - (view->y + view->height);//FIXME vid.height + int y = vid.height - (view->y + view->height); //FIXME vid.height int w = view->width; int h = view->height; qfglViewport (x, y, w, h); } +static void +gl_set_fov (float x, float y) +{ + float neard, fard; + mat4f_t proj; + + neard = r_nearclip->value; + fard = r_farclip->value; + + // NOTE columns! + proj[0] = (vec4f_t) { 1/x, 0, 0, 0 }; + proj[1] = (vec4f_t) { 0, 1/y, 0, 0 }; + proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 }; + proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 }; + + // convert 0..1 depth buffer range to -1..1 + static mat4f_t depth_range = { + { 1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 2, 0}, + { 0, 0,-1, 1}, + }; + mmulf (gl_ctx->projection, depth_range, proj); +} + vid_render_funcs_t gl_vid_render_funcs = { gl_vid_render_init, gl_Draw_Character, @@ -465,7 +489,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_LoadSkys, gl_R_NewMap, gl_R_LineGraph, - gl_R_ViewChanged, gl_begin_frame, gl_render_view, gl_R_RenderEntities, @@ -479,6 +502,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_create_frame_buffer, gl_bind_framebuffer, gl_set_viewport, + gl_set_fov, &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index dcc8125ea..669cedab9 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -368,19 +368,43 @@ glsl_bind_framebuffer (framebuffer_t *framebuffer) vrect_t r = { 0, 0, width, height }; R_SetVrect (&r, &r_refdef.vrect, 0); - glsl_R_ViewChanged (); } static void glsl_set_viewport (const vrect_t *view) { int x = view->x; - int y = vid.height - (view->y + view->height);//FIXME vid.height + int y = vid.height - (view->y + view->height); //FIXME vid.height int w = view->width; int h = view->height; qfeglViewport (x, y, w, h); } +static void +glsl_set_fov (float x, float y) +{ + float neard, fard; + mat4f_t proj; + + neard = r_nearclip->value; + fard = r_farclip->value; + + // NOTE columns! + proj[0] = (vec4f_t) { 1/x, 0, 0, 0 }; + proj[1] = (vec4f_t) { 0, 1/y, 0, 0 }; + proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 }; + proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 }; + + // convert 0..1 depth buffer range to -1..1 + static mat4f_t depth_range = { + { 1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 2, 0}, + { 0, 0,-1, 1}, + }; + mmulf (glsl_ctx->projection, depth_range, proj); +} + vid_render_funcs_t glsl_vid_render_funcs = { glsl_vid_render_init, glsl_Draw_Character, @@ -412,7 +436,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_LoadSkys, glsl_R_NewMap, glsl_R_LineGraph, - glsl_R_ViewChanged, glsl_begin_frame, glsl_render_view, glsl_R_RenderEntities, @@ -426,6 +449,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_create_frame_buffer, glsl_bind_framebuffer, glsl_set_viewport, + glsl_set_fov, &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index bf3145b5c..23a920a36 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -45,6 +45,8 @@ sw_ctx_t *sw_ctx; +static float r_aliasuvscale = 1.0; + static void sw_vid_render_choose_visual (void *data) { @@ -258,6 +260,8 @@ sw_create_frame_buffer (int width, int height) return fb; } +static void sw_set_viewport (const vrect_t *view); + static void sw_bind_framebuffer (framebuffer_t *framebuffer) { @@ -295,14 +299,116 @@ sw_bind_framebuffer (framebuffer_t *framebuffer) if (changed) { vrect_t r = { 0, 0, framebuffer->width, framebuffer->height }; - R_SetVrect (&r, &r_refdef.vrect, 0); - R_ViewChanged (); + sw_set_viewport (&r); } } static void sw_set_viewport (const vrect_t *view) { +#define SHIFT20(x) (((x) << 20) + (1 << 19) - 1) + r_refdef.vrectright = view->x + view->width; + r_refdef.vrectbottom = view->y + view->height; + r_refdef.vrectx_adj_shift20 = SHIFT20 (view->x); + r_refdef.vrectright_adj_shift20 = SHIFT20 (r_refdef.vrectright); + + r_refdef.fvrectx = (float) view->x; + r_refdef.fvrecty = (float) view->y; + r_refdef.fvrectright = (float) r_refdef.vrectright; + r_refdef.fvrectbottom = (float) r_refdef.vrectbottom; + + r_refdef.fvrectx_adj = (float) view->x - 0.5; + r_refdef.fvrecty_adj = (float) view->y - 0.5; + r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5; + r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5; + + int aleft = view->x * r_aliasuvscale; + int atop = view->y * r_aliasuvscale; + int awidth = view->width * r_aliasuvscale; + int aheight = view->height * r_aliasuvscale; + r_refdef.aliasvrectleft = aleft; + r_refdef.aliasvrecttop = atop; + r_refdef.aliasvrectright = aleft + awidth; + r_refdef.aliasvrectbottom = atop + aheight; + + // values for perspective projection + // if math were exact, the values would range from 0.5 to to range+0.5 + // hopefully they wll be in the 0.000001 to range+.999999 and truncate + // the polygon rasterization will never render in the first row or column + // but will definately render in the [range] row and column, so adjust the + // buffer origin to get an exact edge to edge fill + xcenter = view->width * XCENTERING + view->x - 0.5; + ycenter = view->height * YCENTERING + view->y - 0.5; + aliasxcenter = xcenter * r_aliasuvscale; + aliasycenter = ycenter * r_aliasuvscale; + + r_refdef.vrect.x = view->x; + r_refdef.vrect.y = view->y; + r_refdef.vrect.width = view->width; + r_refdef.vrect.height = view->height; + + D_ViewChanged (); +} + +static void +sw_set_fov (float x, float y) +{ + int i; + float res_scale; + + r_viewchanged = true; + + // 320*200 1.0 pixelAspect = 1.6 aspect + // 320*240 1.0 pixelAspect = 1.3333 aspect + // proper 320*200 pixelAspect = 0.8333333 + pixelAspect = 1;//FIXME vid.aspect; + + float hFOV = 2 * x; + float vFOV = 2 * y * pixelAspect; + + // general perspective scaling + xscale = r_refdef.vrect.width / hFOV; + yscale = xscale * pixelAspect; + xscaleinv = 1.0 / xscale; + yscaleinv = 1.0 / yscale; + // perspective scaling for alias models + aliasxscale = xscale * r_aliasuvscale; + aliasyscale = yscale * r_aliasuvscale; + // perspective scaling for paricle position + xscaleshrink = (r_refdef.vrect.width - 6) / hFOV; + yscaleshrink = xscaleshrink * pixelAspect; + + // left side clip + screenedge[0].normal[0] = -1.0 / (XCENTERING * hFOV); + screenedge[0].normal[1] = 0; + screenedge[0].normal[2] = 1; + screenedge[0].type = PLANE_ANYZ; + + // right side clip + screenedge[1].normal[0] = 1.0 / ((1.0 - XCENTERING) * hFOV); + screenedge[1].normal[1] = 0; + screenedge[1].normal[2] = 1; + screenedge[1].type = PLANE_ANYZ; + + // top side clip + screenedge[2].normal[0] = 0; + screenedge[2].normal[1] = -1.0 / (YCENTERING * vFOV); + screenedge[2].normal[2] = 1; + screenedge[2].type = PLANE_ANYZ; + + // bottom side clip + screenedge[3].normal[0] = 0; + screenedge[3].normal[1] = 1.0 / ((1.0 - YCENTERING) * vFOV); + screenedge[3].normal[2] = 1; + screenedge[3].type = PLANE_ANYZ; + + for (i = 0; i < 4; i++) + VectorNormalize (screenedge[i].normal); + + res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) / + (320.0 * 152.0)) * (2.0 / hFOV); + r_aliastransition = r_aliastransbase->value * res_scale; + r_resfudge = r_aliastransadj->value * res_scale; } vid_render_funcs_t sw_vid_render_funcs = { @@ -336,7 +442,6 @@ vid_render_funcs_t sw_vid_render_funcs = { R_LoadSkys, R_NewMap, R_LineGraph, - R_ViewChanged, sw_begin_frame, sw_render_view, R_DrawEntitiesOnList, @@ -350,6 +455,7 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_create_frame_buffer, sw_bind_framebuffer, sw_set_viewport, + sw_set_fov, &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 95fdb8642..7224dc2ef 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -57,6 +57,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/projection.h" #include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/swapchain.h" #include "QF/ui/view.h" @@ -247,12 +248,6 @@ vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, in Vulkan_Draw_SubPic (x, y, pic, srcx, srcy, width, height, vulkan_ctx); } -static void -vulkan_R_ViewChanged (void) -{ - Vulkan_CalcProjectionMatrices (vulkan_ctx); -} - static void vulkan_begin_frame (void) { @@ -316,6 +311,15 @@ vulkan_post_process (framebuffer_t *src) static void vulkan_set_2d (int scaled) { + //FIXME this should not be done every frame + __auto_type mctx = vulkan_ctx->matrix_context; + __auto_type mat = &mctx->matrices; + + int width = vid.conview->xlen; //FIXME vid + int height = vid.conview->ylen; + QFV_Orthographic (mat->Projection2d, 0, width, 0, height, 0, 99999); + + mctx->dirty = mctx->frames.size; } static void @@ -445,6 +449,20 @@ vulkan_set_viewport (const vrect_t *view) { } +static void +vulkan_set_fov (float x, float y) +{ + if (!vulkan_ctx || !vulkan_ctx->matrix_context) { + return; + } + __auto_type mctx = vulkan_ctx->matrix_context; + __auto_type mat = &mctx->matrices; + + QFV_PerspectiveTan (mat->Projection3d, x, y); + + mctx->dirty = mctx->frames.size; +} + static int is_bgr (VkFormat format) { @@ -715,7 +733,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_R_LoadSkys, vulkan_R_NewMap, vulkan_R_LineGraph, - vulkan_R_ViewChanged, vulkan_begin_frame, vulkan_render_view, vulkan_draw_entities, @@ -729,6 +746,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_create_frame_buffer, vulkan_bind_framebuffer, vulkan_set_viewport, + vulkan_set_fov, &model_funcs }; diff --git a/libs/video/renderer/vulkan/projection.c b/libs/video/renderer/vulkan/projection.c index 1dda6a7b6..7102acb26 100644 --- a/libs/video/renderer/vulkan/projection.c +++ b/libs/video/renderer/vulkan/projection.c @@ -68,30 +68,24 @@ QFV_Orthographic (mat4f_t proj, float xmin, float xmax, float ymin, float ymax, } void -QFV_PerspectiveTan (mat4f_t proj, float fov, float aspect) +QFV_PerspectiveTan (mat4f_t proj, float fov_x, float fov_y) { - float f = 1 / fov; float neard, fard; neard = r_nearclip->value; fard = r_farclip->value; - proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 }; - proj[1] = (vec4f_t) { 0, f, 0, 0 }; + proj[0] = (vec4f_t) { 1 / fov_x, 0, 0, 0 }; + proj[1] = (vec4f_t) { 0, 1 / fov_y, 0, 0 }; proj[2] = (vec4f_t) { 0, 0, fard / (fard - neard), 1 }; proj[3] = (vec4f_t) { 0, 0, (neard * fard) / (neard - fard), 0 }; } void -QFV_PerspectiveCos (mat4f_t proj, float fov, float aspect) +QFV_PerspectiveCos (mat4f_t proj, float fov) { // square first for auto-abs (no support for > 180 degree fov) fov = fov * fov; - QFV_PerspectiveTan (proj, sqrt ((1 - fov) / fov), aspect); -} - -void -QFV_Perspective (mat4f_t proj, float fov, float aspect) -{ - QFV_PerspectiveTan (proj, tan (fov * M_PI / 360), aspect); + float t = sqrt ((1 - fov) / fov); + QFV_PerspectiveTan (proj, t, t); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index d6578356d..b34d70e38 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -711,7 +711,7 @@ create_light_matrices (lightingctx_t *lctx) mat4fidentity (proj); break; case ST_PLANE: - QFV_PerspectiveCos (proj, light->cone, 1); + QFV_PerspectiveCos (proj, light->cone); break; } mmulf (lctx->lightmats.a[i], proj, view); diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 79ca29906..5ad3a2ca6 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -169,41 +169,6 @@ Vulkan_Matrix_Draw (qfv_renderframe_t *rFrame) QFV_PacketSubmit (packet); } -void -Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx) -{ - __auto_type mctx = ctx->matrix_context; - __auto_type mat = &mctx->matrices; - - int width = vid.conview->xlen; - int height = vid.conview->ylen; - QFV_Orthographic (mat->Projection2d, 0, width, 0, height, 0, 99999); - - float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height; - QFV_Perspective (mat->Projection3d, r_refdef.fov_y, aspect); -#if 0 - Sys_MaskPrintf (SYS_vulkan, "ortho:\n"); - Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n", - QuatExpand (mat->Projection2d + 0)); - Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", - QuatExpand (mat->Projection2d + 4)); - Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", - QuatExpand (mat->Projection2d + 8)); - Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g]]\n", - QuatExpand (mat->Projection2d + 12)); - Sys_MaskPrintf (SYS_vulkan, "presp:\n"); - Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n", - QuatExpand (mat->Projection3d + 0)); - Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", - QuatExpand (mat->Projection3d + 4)); - Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n", - QuatExpand (mat->Projection3d + 8)); - Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g]]\n", - QuatExpand (mat->Projection3d + 12)); -#endif - mctx->dirty = mctx->frames.size; -} - void Vulkan_Matrix_Init (vulkan_ctx_t *ctx) { From d35154ecf17e510d2359881145bb3e05d4c830c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Mar 2022 15:54:07 +0900 Subject: [PATCH 2591/3664] [vulkan] Clean up a lot of unnecessary includes Too much copying of base files. --- include/QF/Vulkan/scrap.h | 6 ++-- libs/video/renderer/vulkan/buffer.c | 25 ---------------- libs/video/renderer/vulkan/capture.c | 13 -------- libs/video/renderer/vulkan/command.c | 30 ------------------- libs/video/renderer/vulkan/descriptor.c | 26 +--------------- libs/video/renderer/vulkan/device.c | 21 ++----------- libs/video/renderer/vulkan/image.c | 26 +--------------- libs/video/renderer/vulkan/instance.c | 14 ++------- libs/video/renderer/vulkan/memory.c | 26 ---------------- libs/video/renderer/vulkan/pipeline.c | 29 +----------------- libs/video/renderer/vulkan/projection.c | 4 +-- libs/video/renderer/vulkan/renderpass.c | 27 +---------------- libs/video/renderer/vulkan/scrap.c | 20 ++----------- libs/video/renderer/vulkan/shader.c | 20 ++----------- libs/video/renderer/vulkan/staging.c | 18 +---------- libs/video/renderer/vulkan/swapchain.c | 10 ++----- libs/video/renderer/vulkan/util.c | 7 +---- libs/video/renderer/vulkan/vkparse.c | 27 ++--------------- libs/video/renderer/vulkan/vulkan_alias.c | 18 +---------- libs/video/renderer/vulkan/vulkan_matrices.c | 1 - .../video/renderer/vulkan/vulkan_vid_common.c | 1 - 21 files changed, 24 insertions(+), 345 deletions(-) diff --git a/include/QF/Vulkan/scrap.h b/include/QF/Vulkan/scrap.h index 31ceba506..760d9cb12 100644 --- a/include/QF/Vulkan/scrap.h +++ b/include/QF/Vulkan/scrap.h @@ -15,10 +15,10 @@ size_t QFV_ScrapSize (scrap_t *scrap) __attribute__((pure)); void QFV_ScrapClear (scrap_t *scrap); void QFV_DestroyScrap (scrap_t *scrap); VkImageView QFV_ScrapImageView (scrap_t *scrap) __attribute__((pure)); -subpic_t *QFV_ScrapSubpic (scrap_t *scrap, int width, int height); -void QFV_SubpicDelete (subpic_t *subpic); +struct subpic_s *QFV_ScrapSubpic (scrap_t *scrap, int width, int height); +void QFV_SubpicDelete (struct subpic_s *subpic); -void *QFV_SubpicBatch (subpic_t *subpic, struct qfv_stagebuf_s *stage); +void *QFV_SubpicBatch (struct subpic_s *subpic, struct qfv_stagebuf_s *stage); void QFV_ScrapFlush (scrap_t *scrap); diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index 9d8b05679..729fe914d 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -29,36 +29,11 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cvar.h" -#include "QF/dstring.h" #include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/memory.h" - -#include "compat.h" -#include "d_iface.h" -#include "r_internal.h" -#include "vid_vulkan.h" - -#include "util.h" VkBuffer QFV_CreateBuffer (qfv_device_t *device, VkDeviceSize size, diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c index 03d57d894..f0a2038e5 100644 --- a/libs/video/renderer/vulkan/capture.c +++ b/libs/video/renderer/vulkan/capture.c @@ -29,17 +29,6 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#include - #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/command.h" @@ -48,8 +37,6 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/swapchain.h" -#include "vid_vulkan.h" - qfv_capture_t * QFV_CreateCapture (qfv_device_t *device, int numframes, qfv_swapchain_t *swapchain, VkCommandPool cmdPool) diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index bd21bb8b6..0dae2bc5e 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -29,39 +29,9 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cvar.h" -#include "QF/dstring.h" -#include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" -#include "QF/Vulkan/buffer.h" -#include "QF/Vulkan/image.h" -#include "QF/Vulkan/renderpass.h" -#include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" -#include "QF/Vulkan/instance.h" - -#include "compat.h" -#include "d_iface.h" -#include "r_internal.h" -#include "vid_vulkan.h" - -#include "util.h" VkCommandPool QFV_CreateCommandPool (qfv_device_t *device, uint32_t queueFamily, diff --git a/libs/video/renderer/vulkan/descriptor.c b/libs/video/renderer/vulkan/descriptor.c index 30cbd0cad..356fa5f40 100644 --- a/libs/video/renderer/vulkan/descriptor.c +++ b/libs/video/renderer/vulkan/descriptor.c @@ -29,35 +29,11 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cvar.h" -#include "QF/dstring.h" #include "QF/hash.h" -#include "QF/mathlib.h" -#include "QF/quakefs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" + #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" -#include "QF/Vulkan/instance.h" - -#include "compat.h" -#include "d_iface.h" -#include "r_internal.h" -#include "vid_vulkan.h" - -#include "util.h" VkSampler QFV_CreateSampler (qfv_device_t *device, diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 392953826..6f632ef34 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -29,31 +29,14 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif +#include -#include "QF/cvar.h" -#include "QF/dstring.h" -#include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" #include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" + #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" -#include "compat.h" -#include "d_iface.h" -#include "r_internal.h" #include "vid_vulkan.h" #include "util.h" diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 49d234b62..092af713a 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -29,37 +29,13 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cvar.h" -#include "QF/dstring.h" #include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" + #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/memory.h" - -#include "compat.h" -#include "d_iface.h" -#include "r_internal.h" -#include "vid_vulkan.h" - -#include "util.h" VkImage QFV_CreateImage (qfv_device_t *device, int cubemap, diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index 4ba0a9cd8..d8cc53c2d 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -26,21 +26,11 @@ # include "config.h" #endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif +#include #include "QF/cvar.h" -#include "QF/dstring.h" #include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" + #include "QF/Vulkan/instance.h" #include "vid_vulkan.h" diff --git a/libs/video/renderer/vulkan/memory.c b/libs/video/renderer/vulkan/memory.c index 8f0ea2b9e..dbcc81de6 100644 --- a/libs/video/renderer/vulkan/memory.c +++ b/libs/video/renderer/vulkan/memory.c @@ -29,36 +29,10 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cvar.h" -#include "QF/dstring.h" -#include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" -#include "QF/Vulkan/instance.h" #include "QF/Vulkan/memory.h" -#include "compat.h" -#include "d_iface.h" -#include "r_internal.h" -#include "vid_vulkan.h" - -#include "util.h" - void * QFV_MapMemory (qfv_device_t *device, VkDeviceMemory object, VkDeviceSize offset, VkDeviceSize size) diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c index baade73a1..5130a55c2 100644 --- a/libs/video/renderer/vulkan/pipeline.c +++ b/libs/video/renderer/vulkan/pipeline.c @@ -29,39 +29,12 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/hash.h" -#include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" + #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" -#include "QF/Vulkan/image.h" -#include "QF/Vulkan/instance.h" #include "QF/Vulkan/pipeline.h" -#include "QF/Vulkan/renderpass.h" - -#include "compat.h" -#include "d_iface.h" -#include "r_internal.h" -#include "vid_vulkan.h" - -#include "util.h" VkPipelineCache QFV_CreatePipelineCache (qfv_device_t *device, dstring_t *cacheData) diff --git a/libs/video/renderer/vulkan/projection.c b/libs/video/renderer/vulkan/projection.c index 7102acb26..701b52af2 100644 --- a/libs/video/renderer/vulkan/projection.c +++ b/libs/video/renderer/vulkan/projection.c @@ -28,9 +28,7 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif +#include #include "QF/cvar.h" #include "QF/Vulkan/projection.h" diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 3be4f7295..04936b310 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -29,38 +29,13 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - #include "QF/cvar.h" -#include "QF/dstring.h" -#include "QF/hash.h" -#include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" + #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" -#include "QF/Vulkan/instance.h" #include "QF/Vulkan/renderpass.h" -#include "compat.h" -#include "d_iface.h" -#include "r_internal.h" -#include "vid_vulkan.h" - -#include "util.h" - VkRenderPass QFV_CreateRenderPass (qfv_device_t *device, qfv_attachmentdescription_t *attachments, diff --git a/libs/video/renderer/vulkan/scrap.c b/libs/video/renderer/vulkan/scrap.c index e56c2a7a5..3eaf74840 100644 --- a/libs/video/renderer/vulkan/scrap.c +++ b/libs/video/renderer/vulkan/scrap.c @@ -28,24 +28,12 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif +#include -#include "QF/alloc.h" -#include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/hash.h" -#include "QF/image.h" -#include "QF/quakefs.h" #include "QF/render.h" -#include "QF/sys.h" +#include "QF/ui/vrect.h" + #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" @@ -53,12 +41,10 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" -#include "QF/Vulkan/instance.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" #include "r_scrap.h" -#include "vid_vulkan.h" struct scrap_s { rscrap_t rscrap; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index bd12d3b79..a71c83300 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -28,32 +28,16 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif +#include -#include "QF/alloc.h" -#include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/hash.h" #include "QF/quakefs.h" #include "QF/sys.h" -#include "QF/Vulkan/qf_vid.h" + #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" -#include "QF/Vulkan/image.h" -#include "QF/Vulkan/instance.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/shader.h" -#include "vid_vulkan.h" - static #include "libs/video/renderer/vulkan/shader/particle.vert.spvc" static diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 60c617b7d..660e61a64 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -28,22 +28,8 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include "QF/alloc.h" -#include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/hash.h" -#include "QF/quakefs.h" -#include "QF/sys.h" + #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" @@ -52,8 +38,6 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/staging.h" -#include "vid_vulkan.h" - qfv_stagebuf_t * QFV_CreateStagingBuffer (qfv_device_t *device, const char *name, size_t size, VkCommandPool cmdPool) diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 74990f37d..20766233a 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -3,27 +3,21 @@ #endif #ifdef HAVE_MATH_H -# include +//# include #endif #include "QF/cvar.h" #include "QF/mathlib.h" -#include "QF/sys.h" + #include "QF/Vulkan/qf_vid.h" -#include "QF/Vulkan/cvars.h" -#include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/swapchain.h" -#include "compat.h" -#include "d_iface.h" #include "r_internal.h" #include "vid_vulkan.h" -#include "util.h" - qfv_swapchain_t * QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) { diff --git a/libs/video/renderer/vulkan/util.c b/libs/video/renderer/vulkan/util.c index c62fdbcb6..edd5f5b0f 100644 --- a/libs/video/renderer/vulkan/util.c +++ b/libs/video/renderer/vulkan/util.c @@ -26,12 +26,7 @@ # include "config.h" #endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif +#include #include "QF/hash.h" diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 51ef1136f..79c6811e3 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -28,48 +28,25 @@ # include "config.h" #endif -#ifdef HAVE_MATH_H -# include -#endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif +#include -#include "QF/cexpr.h" #include "QF/cmem.h" #include "QF/cvar.h" -#include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" -#include "QF/plist.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" #include "QF/va.h" -#include "QF/vid.h" -#include "QF/simd/vec4f.h" + #include "QF/Vulkan/qf_vid.h" -#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" -#include "QF/Vulkan/command.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/pipeline.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/shader.h" #include "QF/Vulkan/swapchain.h" -#include "compat.h" -#include "d_iface.h" -#include "r_internal.h" #include "vid_vulkan.h" -#include "util.h" - #define vkparse_internal #include "vkparse.h" #undef vkparse_internal diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 24e11fd8b..95bc262fb 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -33,22 +33,9 @@ # include "config.h" #endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#include - -#include "qfalloca.h" +#include #include "QF/cvar.h" -#include "QF/darray.h" -#include "QF/image.h" -#include "QF/render.h" -#include "QF/skin.h" -#include "QF/sys.h" #include "QF/va.h" #include "QF/scene/entity.h" @@ -56,10 +43,7 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_texture.h" -#include "QF/Vulkan/buffer.h" -#include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" -#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/renderpass.h" diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 5ad3a2ca6..363ca70be 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -42,7 +42,6 @@ #include "QF/cvar.h" #include "QF/sys.h" #include "QF/va.h" -#include "QF/vid.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index e6c1bea5b..d5cbcfaf6 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -49,7 +49,6 @@ #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/va.h" -#include "QF/vid.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" From d8a7706e588cff43e220666407c9da8fef2befd3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Mar 2022 23:23:34 +0900 Subject: [PATCH 2592/3664] [build] Test for gcc optimization options While clang accepts gcc's optimization options, it produces a warning when it ignores them, so need to set -Werror before checking for those options when building with -Werror otherwise the build will fail. --- config.d/compiling.m4 | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 7fd5bd6c2..463dd8795 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -76,6 +76,21 @@ else AC_MSG_RESULT(no) fi +AC_ARG_ENABLE(Werror, + AS_HELP_STRING([--disable-Werror], [do not treat warnings as errors])) +dnl We want warnings, lots of warnings... +dnl The help text should be INVERTED before release! +dnl when in git, this test defaults to ENABLED. +dnl In a release, this test defaults to DISABLED. +if test "x$GCC" = "xyes"; then + if test "x$enable_Werror" $cvs_def_enabled; then + CFLAGS="$CFLAGS -Wall -Werror -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations" + else + CFLAGS="$CFLAGS -Wall" + fi + CFLAGS="$CFLAGS -fno-common" +fi + AC_ARG_ENABLE(optimize, AS_HELP_STRING([--disable-optimize], [compile without optimizations (for development)]), @@ -121,13 +136,14 @@ if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then BUILD_TYPE="$BUILD_TYPE Optimize" if test "x$GCC" = xyes; then saved_cflags="$CFLAGS" - CFLAGS="" + dnl CFLAGS="" QF_CC_OPTION(-frename-registers) + QF_CC_OPTION(-fexpensive-optimizations) dnl if test "$CC_MAJ" -ge 4; then dnl QF_CC_OPTION(-finline-limit=32000 -Winline) dnl fi - dnl heavy="-O2 $CFLAGS -ffast-math -fno-unsafe-math-optimizations -funroll-loops -fomit-frame-pointer -fexpensive-optimizations" - heavy="-O2 $CFLAGS -fno-fast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations" + dnl heavy="-O2 $CFLAGS -ffast-math -fno-unsafe-math-optimizations -funroll-loops -fomit-frame-pointer" + heavy="-O2 $CFLAGS -fno-fast-math -funroll-loops -fomit-frame-pointer " CFLAGS="$saved_cflags" light="-O2" AC_ARG_ENABLE(strict-aliasing, @@ -280,21 +296,6 @@ if test "x$GCC" != xyes; then esac fi -AC_ARG_ENABLE(Werror, - AS_HELP_STRING([--disable-Werror], [do not treat warnings as errors])) -dnl We want warnings, lots of warnings... -dnl The help text should be INVERTED before release! -dnl when in git, this test defaults to ENABLED. -dnl In a release, this test defaults to DISABLED. -if test "x$GCC" = "xyes"; then - if test "x$enable_Werror" $cvs_def_enabled; then - CFLAGS="$CFLAGS -Wall -Werror -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations" - else - CFLAGS="$CFLAGS -Wall" - fi - CFLAGS="$CFLAGS -fno-common" -fi - AS="$CC" if test "x$SYSTYPE" = "xWIN32"; then ASFLAGS="\$(DEFS) \$(CFLAGS) \$(CPPFLAGS) \$(DEFAULT_INCLUDES) \$(INCLUDES) -D_WIN32" From 1d1a59ac948661a2f085918c3fa3c81ca65cf15f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Mar 2022 23:29:17 +0900 Subject: [PATCH 2593/3664] [build] Ensure va_copy def comes after HAVE_VA_COPY and HAVE__VA_COPY as well. Fixes clang's complaint about va_copy being redefined. --- config.d/library_functions.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.d/library_functions.m4 b/config.d/library_functions.m4 index 533e5cb78..65c8a841f 100644 --- a/config.d/library_functions.m4 +++ b/config.d/library_functions.m4 @@ -19,7 +19,7 @@ AC_CHECK_FUNCS( AC_FUNC_VA_COPY AC_FUNC__VA_COPY -AH_VERBATIM([DEFINE_VA_COPY], +AH_VERBATIM([HAVE__VA_COPY_], [#ifndef HAVE_VA_COPY # ifdef HAVE__VA_COPY # define va_copy(d,s) __va_copy ((d), (s)) From da42aaf423421cd99d77d17dedd51b176a1d9185 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Mar 2022 23:38:01 +0900 Subject: [PATCH 2594/3664] [sound] Use vec4f_t for api functions Fixes a few vec3_t/vec4f_t FIXMEs. --- include/QF/plugin/snd_render.h | 5 +++-- include/QF/sound.h | 6 +++--- include/snd_internal.h | 4 ++-- libs/audio/renderer/snd_channels.c | 15 ++++++--------- libs/audio/renderer/snd_dma.c | 4 ++-- libs/audio/snd.c | 4 ++-- libs/client/cl_temp_entities.c | 16 ++++++++-------- nq/source/cl_parse.c | 8 ++++---- qw/source/cl_parse.c | 8 ++++---- 9 files changed, 34 insertions(+), 36 deletions(-) diff --git a/include/QF/plugin/snd_render.h b/include/QF/plugin/snd_render.h index bb99df885..8d88163c2 100644 --- a/include/QF/plugin/snd_render.h +++ b/include/QF/plugin/snd_render.h @@ -29,6 +29,7 @@ #include #include +#include struct sfx_s; struct transform_s; @@ -37,8 +38,8 @@ typedef struct snd_render_funcs_s { void (*init) (void); void (*ambient_off) (void); void (*ambient_on) (void); - void (*static_sound) (struct sfx_s *sfx, const vec3_t origin, float vol, float attenuation); - void (*start_sound) (int entnum, int entchannel, struct sfx_s *sfx, const vec3_t origin, float vol, float attenuation); + void (*static_sound) (struct sfx_s *sfx, vec4f_t origin, float vol, float attenuation); + void (*start_sound) (int entnum, int entchannel, struct sfx_s *sfx, const vec4f_t, float vol, float attenuation); void (*local_sound) (const char *s); void (*stop_sound) (int entnum, int entchannel); diff --git a/include/QF/sound.h b/include/QF/sound.h index 3c2968298..7d2227fc4 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -33,6 +33,7 @@ */ #include "QF/mathlib.h" +#include "QF/simd/types.h" struct transform_s; @@ -108,7 +109,7 @@ void S_Shutdown (void); \param vol absolute volume of the sound \param attenuation rate of volume dropoff vs distance */ -void S_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, +void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec4f_t origin, float vol, float attenuation); /** Create a sound generated by the world. @@ -117,8 +118,7 @@ void S_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, \param vol absolute volume of the sound \param attenuation rate of volume dropoff vs distance */ -void S_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, - float attenuation); +void S_StaticSound (sfx_t *sfx, vec4f_t origin, float vol, float attenuation); /** Stop an entity's sound. \param entnum index of entity the sound is associated with. \param entchannel channel to silence diff --git a/include/snd_internal.h b/include/snd_internal.h index fe666f42a..8d95d0615 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -392,7 +392,7 @@ void SND_Channels_Init (snd_t *snd); \param attenuation rate of volume dropoff vs distance */ void SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, - const vec3_t origin, float fvol, float attenuation); + vec4f_t origin, float fvol, float attenuation); /** Create a sound generated by the world. \param snd sound system state @@ -401,7 +401,7 @@ void SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, \param vol absolute volume of the sound \param attenuation rate of volume dropoff vs distance */ -void SND_StaticSound (snd_t *snd, sfx_t *sfx, const vec3_t origin, float vol, +void SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol, float attenuation); /** Stop an entity's sound. \param snd sound system state diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 09e1bda30..492fb430b 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -247,8 +247,7 @@ s_play_f (void *_snd) dsprintf (name, "%s", Cmd_Argv (i)); } sfx = SND_PrecacheSound (snd, name->str); - //FIXME - SND_StartSound (snd, hash++, 0, sfx, &listener_origin[0], 1.0, 1.0); + SND_StartSound (snd, hash++, 0, sfx, listener_origin, 1.0, 1.0); i++; } dstring_delete (name); @@ -273,8 +272,7 @@ s_playcenter_f (void *_snd) dsprintf (name, "%s", Cmd_Argv (i)); } sfx = SND_PrecacheSound (snd, name->str); - //FIXME - SND_StartSound (snd, viewent, 0, sfx, &listener_origin[0], 1.0, 1.0); + SND_StartSound (snd, viewent, 0, sfx, listener_origin, 1.0, 1.0); } dstring_delete (name); } @@ -298,8 +296,7 @@ s_playvol_f (void *_snd) } sfx = SND_PrecacheSound (snd, name->str); vol = atof (Cmd_Argv (i + 1)); - //FIXME - SND_StartSound (snd, hash++, 0, sfx, &listener_origin[0], vol, 1.0); + SND_StartSound (snd, hash++, 0, sfx, listener_origin, vol, 1.0); i += 2; } dstring_delete (name); @@ -617,7 +614,7 @@ snd_check_channels (snd_t *snd, channel_t *target_chan, const channel_t *check, void SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, - const vec3_t origin, float fvol, float attenuation) + vec4f_t origin, float fvol, float attenuation) { int vol; int looped; @@ -691,7 +688,7 @@ SND_StopSound (snd_t *snd, int entnum, int entchannel) } void -SND_StaticSound (snd_t *snd, sfx_t *sfx, const vec3_t origin, float vol, +SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol, float attenuation) { channel_t *ss; @@ -743,5 +740,5 @@ SND_LocalSound (snd_t *snd, const char *sound) } if (snd_render_data.viewentity) viewent = *snd_render_data.viewentity; - SND_StartSound (snd, viewent, -1, sfx, vec3_origin, 1, 1); + SND_StartSound (snd, viewent, -1, sfx, (vec4f_t) {0, 0, 0, 1}, 1, 1); } diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index d5714c55a..ecf5b2707 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -392,7 +392,7 @@ s_ambient_on (void) } static void -s_static_sound (sfx_t *sfx, const vec3_t origin, float vol, +s_static_sound (sfx_t *sfx, vec4f_t origin, float vol, float attenuation) { if (!sound_started) @@ -401,7 +401,7 @@ s_static_sound (sfx_t *sfx, const vec3_t origin, float vol, } static void -s_start_sound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, +s_start_sound (int entnum, int entchannel, sfx_t *sfx, vec4f_t origin, float vol, float attenuation) { if (!sound_started) diff --git a/libs/audio/snd.c b/libs/audio/snd.c index e7c1b0d3b..072fef20f 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -135,14 +135,14 @@ S_AmbientOn (void) } VISIBLE void -S_StaticSound (sfx_t *sfx, const vec3_t origin, float vol, float attenuation) +S_StaticSound (sfx_t *sfx, vec4f_t origin, float vol, float attenuation) { if (snd_render_funcs) snd_render_funcs->static_sound (sfx, origin, vol, attenuation); } VISIBLE void -S_StartSound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin, +S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec4f_t origin, float vol, float attenuation) { if (snd_render_funcs) diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index fefdb3b35..3b932d3ca 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -361,7 +361,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } // sound - S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); // sprite to = new_tent_object (); @@ -383,7 +383,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, MSG_ReadCoordV (net_message, &position[0]); colorStart = MSG_ReadByte (net_message); colorLength = MSG_ReadByte (net_message); - S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); clp_funcs->ParticleExplosion2 (position, colorStart, colorLength); dl = R_AllocDlight (0); if (!dl) @@ -402,7 +402,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, MSG_ReadCoordV (net_message, color); // OUCH! color[3] = 0.7; clp_funcs->ParticleExplosion (position); - S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); dl = R_AllocDlight (0); if (dl) { VectorCopy (position, dl->origin); @@ -424,7 +424,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, case TE_KnightSpike: MSG_ReadCoordV (net_message, &position[0]); clp_funcs->KnightSpikeEffect (position); - S_StartSound (-1, 0, cl_sfx_knighthit, &position[0], 1, 1); + S_StartSound (-1, 0, cl_sfx_knighthit, position, 1, 1); break; case TE_LavaSplash: MSG_ReadCoordV (net_message, &position[0]); @@ -471,7 +471,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } else { sound = cl_sfx_tink1; } - S_StartSound (-1, 0, sound, &position[0], 1, 1); + S_StartSound (-1, 0, sound, position, 1, 1); } break; case TE_SuperSpike: @@ -487,14 +487,14 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } else { sound = cl_sfx_tink1; } - S_StartSound (-1, 0, sound, &position[0], 1, 1); + S_StartSound (-1, 0, sound, position, 1, 1); } break; case TE_TarExplosion: MSG_ReadCoordV (net_message, &position[0]); clp_funcs->BlobExplosion (position); - S_StartSound (-1, 0, cl_sfx_r_exp3, &position[0], 1, 1); + S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); break; case TE_Teleport: MSG_ReadCoordV (net_message, &position[0]); @@ -503,7 +503,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, case TE_WizSpike: MSG_ReadCoordV (net_message, &position[0]); clp_funcs->WizSpikeEffect (position); - S_StartSound (-1, 0, cl_sfx_wizhit, &position[0], 1, 1); + S_StartSound (-1, 0, cl_sfx_wizhit, position, 1, 1); break; } } diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index de98ec63d..475ede102 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -150,7 +150,6 @@ CL_ParseStartSoundPacket (void) { float attenuation; int channel, ent, field_mask, sound_num, volume; - vec3_t pos; field_mask = MSG_ReadByte (net_message); @@ -183,7 +182,8 @@ CL_ParseStartSoundPacket (void) if (ent > MAX_EDICTS) Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent); - MSG_ReadCoordV (net_message, pos); + vec4f_t pos = { 0, 0, 0, 1}; + MSG_ReadCoordV (net_message, (vec_t*)&pos);//FIXME S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume / 255.0, attenuation); @@ -685,9 +685,9 @@ static void CL_ParseStaticSound (int version) { int sound_num, vol, atten; - vec3_t org; + vec4f_t org = { 0, 0, 0, 1 }; - MSG_ReadCoordV (net_message, org); + MSG_ReadCoordV (net_message, (vec_t*)&org);//FIXME if (version == 2) sound_num = MSG_ReadShort (net_message); else diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 2dfe6e25b..0d3cac20b 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -903,9 +903,9 @@ static void CL_ParseStaticSound (void) { int sound_num, vol, atten; - vec3_t org; + vec4f_t org = { 0, 0, 0, 1 }; - MSG_ReadCoordV (net_message, org); + MSG_ReadCoordV (net_message, (vec_t*)&org);//FIXME sound_num = MSG_ReadByte (net_message); vol = MSG_ReadByte (net_message); atten = MSG_ReadByte (net_message); @@ -920,7 +920,6 @@ CL_ParseStartSoundPacket (void) { float attenuation; int bits, channel, ent, sound_num, volume; - vec3_t pos; bits = MSG_ReadShort (net_message); @@ -936,7 +935,8 @@ CL_ParseStartSoundPacket (void) sound_num = MSG_ReadByte (net_message); - MSG_ReadCoordV (net_message, pos); + vec4f_t pos = { 0, 0, 0, 1 }; + MSG_ReadCoordV (net_message, (vec_t*)&pos);//FIXME ent = (bits >> 3) & 1023; channel = bits & 7; From a6df8ab9957435477142aa41b26fa47e0c0774c5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Mar 2022 23:50:12 +0900 Subject: [PATCH 2595/3664] [renderer] Move a couple functions to using vec4f_t Makes for a few less FIXMEs and better consistency with vectors. --- include/r_internal.h | 7 ++-- include/r_local.h | 4 +- libs/video/renderer/gl/gl_mod_alias.c | 4 +- libs/video/renderer/gl/gl_mod_sprite.c | 3 +- libs/video/renderer/glsl/glsl_alias.c | 2 +- libs/video/renderer/glsl/glsl_iqm.c | 4 +- libs/video/renderer/glsl/glsl_sprite.c | 3 +- libs/video/renderer/r_billboard.c | 42 ++++++++++---------- libs/video/renderer/r_light.c | 23 ++++------- libs/video/renderer/r_main.c | 2 +- libs/video/renderer/sw/sw_rsprite.c | 18 +++++---- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- libs/video/renderer/vulkan/vulkan_sprite.c | 4 +- 13 files changed, 54 insertions(+), 64 deletions(-) diff --git a/include/r_internal.h b/include/r_internal.h index 456c4572a..8b43dac0a 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -62,7 +62,7 @@ void R_LoadSkys (const char *); void R_ClearEfrags (void); -void R_FindNearLights (const vec3_t pos, int count, dlight_t **lights); +void R_FindNearLights (vec4f_t pos, int count, dlight_t **lights); dlight_t *R_AllocDlight (int key); void R_DecayLights (double frametime); void R_ClearDlights (void); @@ -78,8 +78,9 @@ void R_MarkLeaves (void); void GL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette); -int R_BillboardFrame (struct entity_s *ent, int orientation, const vec3_t cameravec, - vec3_t bbup, vec3_t bbright, vec3_t bbfwd); +int R_BillboardFrame (struct entity_s *ent, int orientation, + vec4f_t cameravec, + vec4f_t *bbup, vec4f_t *bbright, vec4f_t *bbfwd); mspriteframe_t *R_GetSpriteFrame (const msprite_t *sprite, const struct animation_s *animation); diff --git a/include/r_local.h b/include/r_local.h index d5ca6113c..e6a068501 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -119,7 +119,7 @@ void R_DrawEntitiesOnList (struct entqueue_s *queue); extern plane_t screenedge[4]; -extern vec3_t r_entorigin; +extern vec4f_t r_entorigin; extern int r_visframecount; @@ -307,7 +307,7 @@ void R_TimeRefresh_f (void); void R_PrintAliasStats (void); void R_PrintTimes (void); void R_AnimateLight (void); -int R_LightPoint (mod_brush_t *brush, const vec3_t p); +int R_LightPoint (mod_brush_t *brush, vec4f_t p); void R_SetupFrame (void); void R_cshift_f (void); void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1); diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 1ba1f64ab..a66cccbd1 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -434,7 +434,7 @@ gl_R_DrawAliasModel (entity_t *e) if (scale[0] != 1.0) { radius *= scale[0]; } - if (R_CullSphere (r_refdef.frustum, &origin[0], radius)) {//FIXME + if (R_CullSphere (r_refdef.frustum, (vec_t*)&origin, radius)) {//FIXME return; } @@ -449,7 +449,7 @@ gl_R_DrawAliasModel (entity_t *e) float lightadj; // get lighting information - R_LightPoint (&r_refdef.worldmodel->brush, &origin[0]);//FIXME + R_LightPoint (&r_refdef.worldmodel->brush, origin);//FIXME lightadj = (ambientcolor[0] + ambientcolor[1] + ambientcolor[2]) / 765.0; diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index 0f710a0b4..36b5ba633 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -71,8 +71,7 @@ R_DrawSpriteModel_f (entity_t *e) // don't bother culling, it's just a single polygon without a surface cache frame = R_GetSpriteFrame (sprite, &e->animation); - if (!R_BillboardFrame (e, sprite->type, &cameravec[0], - &up[0], &right[0], &pn[0])) { + if (!R_BillboardFrame (e, sprite->type, cameravec, &up, &right, &pn)) { // the orientation is undefined so can't draw the sprite return; } diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index b7b50eb3b..7d94f6029 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -161,7 +161,7 @@ calc_lighting (entity_t *ent, float *ambient, float *shadelight, entorigin = Transform_GetWorldPosition (ent->transform); VectorSet ( -1, 0, 0, lightvec); //FIXME - light = R_LightPoint (&r_refdef.worldmodel->brush, &entorigin[0]); + light = R_LightPoint (&r_refdef.worldmodel->brush, entorigin); *ambient = max (light, max (ent->renderer.model->min_light, ent->renderer.min_light) * 128); *shadelight = *ambient; diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index 2978534d3..056ac85fb 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -225,9 +225,9 @@ glsl_R_DrawIQM (entity_t *ent) entorigin = mat[3]; mmulf (mvp_mat, iqm_vp, mat); - R_LightPoint (&r_refdef.worldmodel->brush, &entorigin[0]);//FIXME min_light? + R_LightPoint (&r_refdef.worldmodel->brush, entorigin);//FIXME min_light? VectorScale (ambientcolor, 1/255.0, ambientcolor); - R_FindNearLights (&entorigin[0], MAX_IQM_LIGHTS, lights);//FIXME + R_FindNearLights (entorigin, MAX_IQM_LIGHTS, lights); blend = R_IQMGetLerpedFrames (ent, iqm); frame = R_IQMBlendFrames (iqm, ent->animation.pose1, ent->animation.pose2, diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 196b99a73..913217cfe 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -227,8 +227,7 @@ glsl_R_DrawSprite (entity_t *ent) vec4f_t origin = Transform_GetWorldPosition (ent->transform); cameravec = r_refdef.frame.position - origin; - if (!R_BillboardFrame (ent, sprite->type, &cameravec[0], - &sup[0], &sright[0], &spn[0])) { + if (!R_BillboardFrame (ent, sprite->type, cameravec, &sup, &sright, &spn)) { // the orientation is undefined so can't draw the sprite return; } diff --git a/libs/video/renderer/r_billboard.c b/libs/video/renderer/r_billboard.c index bd0afa7d1..9fe3653bd 100644 --- a/libs/video/renderer/r_billboard.c +++ b/libs/video/renderer/r_billboard.c @@ -46,10 +46,10 @@ int -R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, - vec3_t bbup, vec3_t bbright, vec3_t bbfwd) +R_BillboardFrame (entity_t *ent, int orientation, vec4f_t cameravec, + vec4f_t *bbup, vec4f_t *bbright, vec4f_t *bbfwd) { - vec3_t tvec; + vec4f_t tvec; float dot; switch (orientation) { @@ -57,23 +57,21 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, // the billboard has its up vector parallel with world up, and // its right vector perpendicular to cameravec. // Undefined if the camera is too close to the entity. - VectorNegate (cameravec, tvec); - VectorNormalize (tvec); + tvec = -normalf (cameravec); dot = tvec[2]; // DotProduct (tvec, world up) if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) return 0; - VectorSet (0, 0, 1, bbup); + *bbup = (vec4f_t) { 0, 0, 1, 0 }; //CrossProduct(bbup, -cameravec, bbright) - VectorSet (tvec[1], -tvec[0], 0, bbright); - VectorNormalize (bbright); + *bbright = normalf ((vec4f_t) { tvec[1], -tvec[0], 0, 0 }); //CrossProduct (bbright, bbup, bbfwd) - VectorSet (-bbright[1], bbright[0], 0, bbfwd); + *bbfwd = (vec4f_t) { -(*bbright)[1], (*bbright)[0], 0, 0}; break; case SPR_VP_PARALLEL: // the billboard always has the same orientation as the camera - VectorCopy (r_refdef.frame.up, bbup); - VectorCopy (r_refdef.frame.right, bbright); - VectorCopy (r_refdef.frame.forward, bbfwd); + *bbup = r_refdef.frame.up; + *bbright = r_refdef.frame.right; + *bbfwd = r_refdef.frame.forward; break; case SPR_VP_PARALLEL_UPRIGHT: // the billboar has its up vector parallel with world up, and @@ -82,10 +80,10 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, dot = r_refdef.frame.forward[2]; if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) return 0; - VectorSet (0, 0, 1, bbup); - VectorSet (r_refdef.frame.forward[1], -r_refdef.frame.forward[0], 0, bbright); - VectorNormalize (bbright); - VectorSet (-bbright[1], bbright[0], 0, bbfwd); + *bbup = (vec4f_t) { 0, 0, 1, 0 }; + *bbright = normalf ((vec4f_t) {r_refdef.frame.forward[1], + -r_refdef.frame.forward[0], 0, 0 }); + *bbfwd = (vec4f_t) { -(*bbright)[1], (*bbright)[0], 0, 0}; break; case SPR_ORIENTED: { @@ -93,9 +91,9 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, // entity's orientation. mat4f_t mat; Transform_GetWorldMatrix (ent->transform, mat); - VectorCopy (mat[0], bbfwd); - VectorNegate (mat[1], bbright); - VectorCopy (mat[2], bbup); + *bbfwd = mat[0]; + *bbright = mat[1]; + *bbup = mat[2]; } break; case SPR_VP_PARALLEL_ORIENTED: @@ -108,9 +106,9 @@ R_BillboardFrame (entity_t *ent, int orientation, const vec3_t cameravec, // FIXME needs proper testing (need to find, make, or fake a // parallel oriented sprite) mmulf (spmat, r_refdef.camera, entmat); - VectorCopy (spmat[0], bbfwd); - VectorNegate (spmat[1], bbright); - VectorCopy (spmat[1], bbup); + *bbfwd = spmat[0]; + *bbright = spmat[1]; + *bbup = spmat[2]; } break; default: diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 6356d4c2b..d9a96915e 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -52,7 +52,7 @@ vec3_t ambientcolor; unsigned int r_maxdlights; void -R_FindNearLights (const vec3_t pos, int count, dlight_t **lights) +R_FindNearLights (vec4f_t pos, int count, dlight_t **lights) { float *scores = alloca (count * sizeof (float)); float score; @@ -399,8 +399,8 @@ calc_lighting_3 (msurface_t *surf, int ds, int dt) } static int -RecursiveLightPoint (mod_brush_t *brush, mnode_t *node, const vec3_t start, - const vec3_t end) +RecursiveLightPoint (mod_brush_t *brush, mnode_t *node, vec4f_t start, + vec4f_t end) { unsigned i; int r, s, t, ds, dt, side; @@ -408,7 +408,6 @@ RecursiveLightPoint (mod_brush_t *brush, mnode_t *node, const vec3_t start, plane_t *plane; msurface_t *surf; mtexinfo_t *tex; - vec3_t mid; loop: if (node->contents < 0) return -1; // didn't hit anything @@ -425,9 +424,7 @@ loop: } frac = front / (front - back); - mid[0] = start[0] + (end[0] - start[0]) * frac; - mid[1] = start[1] + (end[1] - start[1]) * frac; - mid[2] = start[2] + (end[2] - start[2]) * frac; + vec4f_t mid = start + (end - start) * frac; // go down front side r = RecursiveLightPoint (brush, node->children[side], start, mid); @@ -476,22 +473,16 @@ loop: } int -R_LightPoint (mod_brush_t *brush, const vec3_t p) +R_LightPoint (mod_brush_t *brush, vec4f_t p) { - vec3_t end; - int r; - if (!brush->lightdata) { // allow dlights to have some effect, so don't go /quite/ fullbright ambientcolor[2] = ambientcolor[1] = ambientcolor[0] = 200; return 200; } - end[0] = p[0]; - end[1] = p[1]; - end[2] = p[2] - 2048; - - r = RecursiveLightPoint (brush, brush->nodes, p, end); + vec4f_t end = p - (vec4f_t) { 0, 0, 2048, 0 }; + int r = RecursiveLightPoint (brush, brush->nodes, p, end); if (r == -1) r = 0; diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index c93c8f467..a32826dff 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -62,7 +62,7 @@ int r_framecount = 1; // so frame counts initialized to 0 don't match vec3_t modelorg; // modelorg is the viewpoint relative to // the currently rendering entity vec3_t base_modelorg; -vec3_t r_entorigin; // the currently rendering entity in world +vec4f_t r_entorigin; // the currently rendering entity in world // coordinates // screen size info refdef_t r_refdef; diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 5f09dea40..f5e612dfb 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -52,7 +52,7 @@ spritedesc_t r_spritedesc; static void -R_RotateSprite (const vec3_t relvieworg, float beamlength, vec3_t org) +R_RotateSprite (vec4f_t relvieworg, float beamlength, vec3_t org) { vec3_t vec; @@ -244,25 +244,27 @@ void R_DrawSprite (entity_t *ent) { msprite_t *sprite = ent->renderer.model->cache.data; - vec3_t relvieworg; - VectorSubtract (r_refdef.frame.position, r_entorigin, relvieworg); + vec4f_t cameravec = r_refdef.frame.position - r_entorigin; r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, &ent->animation); sprite_width = r_spritedesc.pspriteframe->width; sprite_height = r_spritedesc.pspriteframe->height; - if (!R_BillboardFrame (ent, sprite->type, relvieworg, - r_spritedesc.vup, - r_spritedesc.vright, - r_spritedesc.vfwd)) { + vec4f_t up = {}; + vec4f_t right = {}; + vec4f_t fwd = {}; + if (!R_BillboardFrame (ent, sprite->type, cameravec, &up, &right, &fwd)) { // the orientation is undefined so can't draw the sprite return; } + VectorCopy (up, r_spritedesc.vup);//FIXME + VectorCopy (right, r_spritedesc.vright); + VectorCopy (fwd, r_spritedesc.vfwd); vec3_t org; - R_RotateSprite (relvieworg, sprite->beamlength, org); + R_RotateSprite (cameravec, sprite->beamlength, org); R_SetupAndDrawSprite (org); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index b34d70e38..83a8ee061 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -160,7 +160,7 @@ update_lights (vulkan_ctx_t *ctx) light_data->distFactor2 = 1 / 16384.0; light_data->lightCount = 0; - R_FindNearLights (&r_refdef.frame.position[0], MaxLights - 1, lights); + R_FindNearLights (r_refdef.frame.position, MaxLights - 1, lights); for (int i = 0; i < MaxLights - 1; i++) { if (!lights[i]) { break; diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 77c02d30c..c01ddb329 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -120,8 +120,8 @@ Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) mat[3] = Transform_GetWorldPosition (ent->transform); vec4f_t cameravec = r_refdef.frame.position - mat[3]; - R_BillboardFrame (ent, sprite->type, &cameravec[0], - &mat[2][0], &mat[1][0], &mat[0][0]); + R_BillboardFrame (ent, sprite->type, cameravec, + &mat[2], &mat[1], &mat[0]); mat[0] = -mat[0]; emit_commands (sframe->cmdSet.a[QFV_spriteDepth], From db01650daceddcb1ceed7ea76428177844453658 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 00:07:20 +0900 Subject: [PATCH 2596/3664] Update vec3_t/vec4f_t hacks to work with clang Still work with gcc, of course, and I still need to fix them properly, but now they're actually slightly easier to find as they all have vec_t and FIXME on the same line. --- libs/client/cl_chase.c | 16 +++++------ libs/client/cl_entities.c | 2 +- libs/client/cl_particles.c | 10 +++++-- libs/client/cl_temp_entities.c | 34 +++++++++++------------ libs/client/cl_view.c | 7 ++--- libs/client/cl_world.c | 2 +- libs/video/renderer/gl/gl_mod_sprite.c | 8 +++--- libs/video/renderer/gl/gl_rmain.c | 6 ++-- libs/video/renderer/gl/gl_rsurf.c | 2 +- libs/video/renderer/glsl/glsl_alias.c | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 6 ++-- libs/video/renderer/glsl/glsl_iqm.c | 2 +- libs/video/renderer/glsl/glsl_particles.c | 4 +-- libs/video/renderer/glsl/glsl_sprite.c | 2 +- libs/video/renderer/r_main.c | 8 +++--- libs/video/renderer/r_screen.c | 2 +- libs/video/renderer/sw/d_edge.c | 4 +-- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- nq/source/cl_parse.c | 2 +- nq/source/cl_screen.c | 3 +- nq/source/host.c | 2 +- nq/source/sv_main.c | 2 +- qtv/source/client.c | 2 +- qtv/source/sv_parse.c | 4 +-- qw/source/cl_cam.c | 8 +++--- qw/source/cl_demo.c | 4 +-- qw/source/cl_entparse.c | 2 +- qw/source/cl_main.c | 2 +- qw/source/cl_parse.c | 2 +- qw/source/cl_screen.c | 3 +- qw/source/sv_ents.c | 2 +- qw/source/sv_init.c | 5 ++-- 32 files changed, 82 insertions(+), 80 deletions(-) diff --git a/libs/client/cl_chase.c b/libs/client/cl_chase.c index 62e0d471f..483e1605f 100644 --- a/libs/client/cl_chase.c +++ b/libs/client/cl_chase.c @@ -79,7 +79,7 @@ TraceLine (chasestate_t *cs, vec4f_t start, vec4f_t end) memset (&trace, 0, sizeof (trace)); trace.fraction = 1; - MOD_TraceLine (cs->worldmodel->brush.hulls, 0, &start[0], &end[0], &trace); + MOD_TraceLine (cs->worldmodel->brush.hulls, 0, (vec_t*)&start, (vec_t*)&end, &trace);//FIXME return (vec4f_t) {trace.endpos[0], trace.endpos[1], trace.endpos[2], 1}; } @@ -113,7 +113,7 @@ static void set_camera (chasestate_t *cs, viewstate_t *vs) { vec4f_t rotation; - AngleQuat (cs->camera_angles, &rotation[0]);//FIXME + AngleQuat (cs->camera_angles, (vec_t*)&rotation);//FIXME Transform_SetWorldRotation (vs->camera_transform, rotation); Transform_SetWorldPosition (vs->camera_transform, cs->camera_origin); } @@ -149,7 +149,7 @@ cam_controls (chasestate_t *cs, viewstate_t *vs) // mouse and joystick controllers add to movement VectorSet (0, vs->player_angles[1] - cs->camera_angles[1], 0, dir); - AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME + AngleVectors ((vec_t*)&dir, (vec_t*)&forward, (vec_t*)&right, (vec_t*)&up); //FIXME forward *= IN_UpdateAxis (&in_cam_forward) * m_forward->value; right *= IN_UpdateAxis (&in_cam_side) * m_side->value; dir = forward + right; @@ -157,7 +157,7 @@ cam_controls (chasestate_t *cs, viewstate_t *vs) move[SIDE] -= dir[1]; VectorSet (0, cs->camera_angles[1], 0, dir); - AngleVectors (&dir[0], &forward[0], &right[0], &up[0]); //FIXME + AngleVectors ((vec_t*)&dir, (vec_t*)&forward, (vec_t*)&right, (vec_t*)&up); //FIXME dir = forward * move[FORWARD] + right * move[SIDE]; @@ -185,8 +185,8 @@ chase_mode_1 (chasestate_t *cs) // regular camera, faces same direction as player viewstate_t *vs = cs->viewstate; vec4f_t forward = {}, up = {}, right = {}, stop = {}; - //FIXME - AngleVectors (vs->player_angles, &forward[0], &right[0], &up[0]); + + AngleVectors (vs->player_angles, (vec_t*)&forward, (vec_t*)&right, (vec_t*)&up);//FIXME VectorCopy (vs->player_angles, cs->camera_angles); // calc exact destination @@ -218,7 +218,7 @@ chase_mode_2 (chasestate_t *cs) // move camera, it's not enough to just change the angles because // the angles are automatically changed to look toward the player - AngleVectors (cs->camera_angles, &forward[0], &right[0], &up[0]); + AngleVectors (cs->camera_angles, (vec_t*)&forward, (vec_t*)&right, (vec_t*)&up);//FIXME cs->camera_origin = cs->player_origin - chase_back->value * forward; cs->player_origin = vs->player_origin; @@ -266,7 +266,7 @@ chase_mode_3 (chasestate_t *cs) // the angles are automatically changed to look toward the player cs->player_origin = vs->player_origin; - AngleVectors (cs->camera_angles, &forward[0], &right[0], &up[0]); + AngleVectors (cs->camera_angles, (vec_t*)&forward, (vec_t*)&right, (vec_t*)&up);//FIXME cs->camera_origin = cs->player_origin - chase_back->value * forward; limit_distance (cs); check_for_walls (cs, forward); diff --git a/libs/client/cl_entities.c b/libs/client/cl_entities.c index d4cac0dfa..01ffd7d6b 100644 --- a/libs/client/cl_entities.c +++ b/libs/client/cl_entities.c @@ -370,7 +370,7 @@ CL_TransformEntity (entity_t *ent, float scale, const vec3_t angles, // to everything else? ang[PITCH] = -ang[PITCH]; } - AngleQuat (ang, &rotation[0]);//FIXME + AngleQuat (ang, (vec_t*)&rotation);//FIXME } Transform_SetLocalTransform (ent->transform, scalevec, rotation, position); } diff --git a/libs/client/cl_particles.c b/libs/client/cl_particles.c index 7ff731315..618067612 100644 --- a/libs/client/cl_particles.c +++ b/libs/client/cl_particles.c @@ -249,15 +249,19 @@ CL_LoadPointFile (const model_t *model) vec4f_t zero = {}; for (;;) { char buf[64]; - vec4f_t org = { 0, 0, 0, 1 }; + union { + vec4f_t org; + vec3_t org3; + } o = { .org = { 0, 0, 0, 1 }}; Qgets (f, buf, sizeof (buf)); - int r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); + int r = sscanf (buf, "%f %f %f\n", + &o.org3[0], &o.org3[1], &o.org3[2]); if (r != 3) break; c++; - if (!particle_new (pt_static, part_tex_dot, org, 1.5, zero, + if (!particle_new (pt_static, part_tex_dot, o.org, 1.5, zero, 99999, (-c) & 15, 1.0, 0.0)) { Sys_MaskPrintf (SYS_dev, "Not enough free particles\n"); break; diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 3b932d3ca..269a1c9ed 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -285,8 +285,8 @@ CL_ParseBeam (qmsg_t *net_message, model_t *m, double time, TEntContext_t *ctx) ent = MSG_ReadShort (net_message); - MSG_ReadCoordV (net_message, &start[0]);//FIXME - MSG_ReadCoordV (net_message, &end[0]);//FIXME + MSG_ReadCoordV (net_message, (vec_t*)&start);//FIXME + MSG_ReadCoordV (net_message, (vec_t*)&end);//FIXME start[3] = end[3] = 1;//FIXME to = 0; @@ -340,11 +340,11 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, break; case TE_Blood: count = MSG_ReadByte (net_message) * 20; - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->BloodPuffEffect (position, count); break; case TE_Explosion: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME // particles clp_funcs->ParticleExplosion (position); @@ -380,7 +380,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, (vec4f_t) {VectorExpand (position), 1}); break; case TE_Explosion2: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME colorStart = MSG_ReadByte (net_message); colorLength = MSG_ReadByte (net_message); S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); @@ -398,7 +398,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, dl->color[3] = 0.7; break; case TE_Explosion3: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME MSG_ReadCoordV (net_message, color); // OUCH! color[3] = 0.7; clp_funcs->ParticleExplosion (position); @@ -413,21 +413,21 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } break; case TE_Gunshot1: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->GunshotEffect (position, 20); break; case TE_Gunshot2: count = MSG_ReadByte (net_message) * 20; - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->GunshotEffect (position, count); break; case TE_KnightSpike: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->KnightSpikeEffect (position); S_StartSound (-1, 0, cl_sfx_knighthit, position, 1, 1); break; case TE_LavaSplash: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->LavaSplash (position); break; case TE_Lightning1: @@ -444,7 +444,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, CL_ParseBeam (net_message, Mod_ForName (name, true), time, ctx); break; case TE_LightningBlood: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME // light dl = R_AllocDlight (0); @@ -459,7 +459,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, clp_funcs->LightningBloodEffect (position); break; case TE_Spike: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->SpikeEffect (position); { int i; @@ -475,7 +475,7 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } break; case TE_SuperSpike: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->SuperSpikeEffect (position); { int i; @@ -491,17 +491,17 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, } break; case TE_TarExplosion: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->BlobExplosion (position); S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); break; case TE_Teleport: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->TeleportSplash (position); break; case TE_WizSpike: - MSG_ReadCoordV (net_message, &position[0]); + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->WizSpikeEffect (position); S_StartSound (-1, 0, cl_sfx_wizhit, position, 1, 1); break; @@ -655,7 +655,7 @@ CL_ParseParticleEffect (qmsg_t *net_message) int i, count, color; vec4f_t org = {0, 0, 0, 1}, dir = {}; - MSG_ReadCoordV (net_message, &org[0]); + MSG_ReadCoordV (net_message, (vec_t*)&org);//FIXME for (i = 0; i < 3; i++) dir[i] = ((signed char) MSG_ReadByte (net_message)) * (15.0 / 16.0); count = MSG_ReadByte (net_message); diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index a4120eeab..fa693107b 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -563,7 +563,7 @@ V_CalcViewRoll (viewstate_t *vs) } vec4f_t rot; - AngleQuat (ang, &rot[0]);//FIXME + AngleQuat (ang, (vec_t*)&rot);//FIXME vec4f_t rotation = Transform_GetWorldRotation (vs->camera_transform); Transform_SetWorldRotation (vs->camera_transform, qmulf (rotation, rot)); } @@ -608,7 +608,6 @@ V_CalcRefdef (viewstate_t *vs) bob = V_CalcBob (vs); // refresh position - origin = origin; origin[2] += vs->height + bob; // never let it sit exactly on a node line, because a water plane can @@ -617,14 +616,14 @@ V_CalcRefdef (viewstate_t *vs) origin += (vec4f_t) { 1.0/16, 1.0/16, 1.0/16, 0}; vec4f_t rotation; - AngleQuat (vs->player_angles, &rotation[0]);//FIXME + AngleQuat (vs->player_angles, (vec_t*)&rotation);//FIXME Transform_SetWorldRotation (vs->camera_transform, rotation); V_CalcViewRoll (vs); V_AddIdle (vs); // offsets //FIXME semi-duplicates AngleQuat (also, vec3_t vs vec4f_t) - AngleVectors (viewangles, &forward[0], &right[0], &up[0]); + AngleVectors (viewangles, (vec_t*)&forward, (vec_t*)&right, (vec_t*)&up);//FIXME // don't allow cheats in multiplayer // FIXME check for dead diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index 8a45e44d1..436013f79 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -87,7 +87,7 @@ CL_ParseBaseline (qmsg_t *msg, entity_state_t *baseline, int version) baseline->colormap = MSG_ReadByte (msg); baseline->skinnum = MSG_ReadByte (msg); - MSG_ReadCoordAngleV (msg, &baseline->origin[0], baseline->angles); + MSG_ReadCoordAngleV (msg, (vec_t*)&baseline->origin, baseline->angles);//FIXME baseline->origin[3] = 1;//FIXME if (bits & B_ALPHA) diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index 36b5ba633..226a4443b 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -90,20 +90,20 @@ R_DrawSpriteModel_f (entity_t *e) point = origin + frame->down * up + frame->left * right; qfglTexCoord2f (0, 1); - qfglVertex3fv (&point[0]); + qfglVertex3fv ((vec_t*)&point);//FIXME point = origin + frame->up * up + frame->left * right; qfglTexCoord2f (0, 0); - qfglVertex3fv (&point[0]); + qfglVertex3fv ((vec_t*)&point);//FIXME point = origin + frame->up * up + frame->right * right; qfglTexCoord2f (1, 0); - qfglVertex3fv (&point[0]); + qfglVertex3fv ((vec_t*)&point);//FIXME point = origin + frame->down * up + frame->right * right; qfglTexCoord2f (1, 1); - qfglVertex3fv (&point[0]); + qfglVertex3fv ((vec_t*)&point);//FIXME qfglEnd (); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 19da42cbe..a3b19615b 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -92,7 +92,7 @@ gl_R_RotateForEntity (entity_t *e) { mat4f_t mat; Transform_GetWorldMatrix (e->transform, mat); - qfglMultMatrixf (&mat[0][0]); + qfglMultMatrixf ((vec_t*)&mat[0]);//FIXME } void @@ -233,7 +233,7 @@ static void R_SetupGL (void) { qfglMatrixMode (GL_PROJECTION); - qfglLoadMatrixf (&gl_ctx->projection[0][0]); + qfglLoadMatrixf ((vec_t*)&gl_ctx->projection[0]);//FIXME qfglFrontFace (GL_CW); @@ -248,7 +248,7 @@ R_SetupGL (void) }; mat4f_t view; mmulf (view, z_up, r_refdef.camera_inverse); - qfglLoadMatrixf (&view[0][0]); + qfglLoadMatrixf ((vec_t*)&view[0]);//FIXME qfglGetFloatv (GL_MODELVIEW_MATRIX, gl_r_world_matrix); diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 75e42ff5a..bb3f4a958 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -544,7 +544,7 @@ gl_R_DrawBrushModel (entity_t *e) if (e->scale != 1.0) radius *= e->scale; #endif - if (R_CullSphere (r_refdef.frustum, &worldMatrix[3][0], radius)) {//FIXME + if (R_CullSphere (r_refdef.frustum, (vec_t*)&worldMatrix[3], radius)) {//FIXME return; } } else { diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 7d94f6029..3ecf33bc6 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -299,7 +299,7 @@ glsl_R_DrawAlias (entity_t *ent) qfeglUniform3fv (quake_mdl.lightvec.location, 1, lightvec); qfeglUniform2fv (quake_mdl.skin_size.location, 1, skin_size); qfeglUniformMatrix4fv (quake_mdl.mvp_matrix.location, 1, false, - &mvp_mat[0][0]); + (vec_t*)&mvp_mat[0]);//FIXME qfeglUniformMatrix3fv (quake_mdl.norm_matrix.location, 1, false, norm_mat); #ifndef TETRAHEDRON diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 66658c8e6..7ae7dec1e 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -677,7 +677,7 @@ R_DrawBrushModel (entity_t *e) if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; - if (R_CullSphere (r_refdef.frustum, &mat[3][0], radius)) { // FIXME + if (R_CullSphere (r_refdef.frustum, (vec_t*)&mat[3], radius)) { // FIXME return; } } else { @@ -854,10 +854,10 @@ draw_elechain (elechain_t *ec, int matloc, int vertloc, int tlstloc, } } if (ec->transform) { - Mat4Mult (&bsp_vp[0][0], ec->transform, mat);//FIXME + Mat4Mult ((vec_t*)&bsp_vp[0], ec->transform, mat);//FIXME qfeglUniformMatrix4fv (matloc, 1, false, mat); } else { - qfeglUniformMatrix4fv (matloc, 1, false, &bsp_vp[0][0]); + qfeglUniformMatrix4fv (matloc, 1, false, (vec_t*)&bsp_vp[0]);//FIXME } for (el = ec->elements; el; el = el->next) { if (!el->list->size) diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index 056ac85fb..21f44243b 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -253,7 +253,7 @@ glsl_R_DrawIQM (entity_t *ent) qfeglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, glsl->element_array); qfeglUniformMatrix4fv (iqm_shader.mvp_matrix.location, 1, false, - &mvp_mat[0][0]); + (vec_t*)&mvp_mat[0]);//FIXME qfeglUniformMatrix3fv (iqm_shader.norm_matrix.location, 1, false, norm_mat); qfeglUniformMatrix4fv (iqm_shader.bonemats.location, iqm->num_joints, diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index 89645e72c..a4caefa6f 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -247,7 +247,7 @@ draw_qf_particles (psystem_t *psystem) qfeglUniform4fv (quake_part.fog.location, 1, fog); qfeglUniformMatrix4fv (quake_part.mvp_matrix.location, 1, false, - &vp_mat[0][0]); + (vec_t*)&vp_mat[0]);//FIXME qfeglUniform1i (quake_part.texture.location, 0); qfeglActiveTexture (GL_TEXTURE0 + 0); @@ -366,7 +366,7 @@ draw_id_particles (psystem_t *psystem) qfeglEnableVertexAttribArray (quake_point.color.location); qfeglUniformMatrix4fv (quake_point.mvp_matrix.location, 1, false, - &vp_mat[0][0]); + (vec_t*)&vp_mat[0]);//FIXME Fog_GetColor (fog); fog[3] = Fog_GetDensity () / 64.0; diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 913217cfe..baac6108e 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -289,7 +289,7 @@ glsl_R_SpriteBegin (void) qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); mmulf (mat, glsl_projection, glsl_view); - qfeglUniformMatrix4fv (quake_sprite.matrix.location, 1, false, &mat[0][0]); + qfeglUniformMatrix4fv (quake_sprite.matrix.location, 1, false, (vec_t*)&mat[0]);//FIXME } void diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index a32826dff..d29bcd1a4 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -100,13 +100,13 @@ R_SetFrustum (plane_t *frustum, const refframe_t *frame, fov_y = 90 - fov_y / 2; // rotate FWD right by FOV_X/2 degrees - RotatePointAroundVector (frustum[0].normal, &up[0], &fwd[0], -fov_x); + RotatePointAroundVector (frustum[0].normal, (vec_t*)&up, (vec_t*)&fwd, -fov_x);//FIXME // rotate FWD left by FOV_X/2 degrees - RotatePointAroundVector (frustum[1].normal, &up[0], &fwd[0], fov_x); + RotatePointAroundVector (frustum[1].normal, (vec_t*)&up, (vec_t*)&fwd, fov_x);//FIXME // rotate FWD up by FOV_Y/2 degrees - RotatePointAroundVector (frustum[2].normal, &right[0], &fwd[0], fov_y); + RotatePointAroundVector (frustum[2].normal, (vec_t*)&right, (vec_t*)&fwd, fov_y);//FIXME // rotate FWD down by FOV_Y/2 degrees - RotatePointAroundVector (frustum[3].normal, &right[0], &fwd[0], -fov_y); + RotatePointAroundVector (frustum[3].normal, (vec_t*)&right, (vec_t*)&fwd, -fov_y);//FIXME vec4f_t origin = frame->position; for (i = 0; i < 4; i++) { diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index cd8ff5102..2ebc122be 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -271,7 +271,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) refdef->viewleaf = 0; if (refdef->worldmodel) { vec4f_t position = refdef->frame.position; - refdef->viewleaf = Mod_PointInLeaf (&position[0], refdef->worldmodel); + refdef->viewleaf = Mod_PointInLeaf ((vec_t*)&position, refdef->worldmodel);//FIXME r_dowarpold = r_dowarp; if (r_waterwarp->int_val) { r_dowarp = refdef->viewleaf->contents <= CONTENTS_WATER; diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 60590c4d3..a1fd07616 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -210,7 +210,7 @@ D_DrawSurfaces (void) transform = s->entity->transform; local_modelorg = r_refdef.frame.position - Transform_GetWorldPosition (transform); - TransformVector (&local_modelorg[0], transformed_modelorg); + TransformVector ((vec_t*)&local_modelorg, transformed_modelorg);//FIXME R_RotateBmodel (transform); // FIXME: don't mess with the // frustum, make entity passed in @@ -241,7 +241,7 @@ D_DrawSurfaces (void) transform_t *transform = s->entity->transform; local_modelorg = r_refdef.frame.position - Transform_GetWorldPosition (transform); - TransformVector (&local_modelorg[0], transformed_modelorg); + TransformVector ((vec_t*)&local_modelorg, transformed_modelorg);//FIXME R_RotateBmodel (transform); // FIXME: don't mess with the // frustum, make entity passed in diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 53c4d65a3..80da6abaa 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -604,7 +604,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; - if (R_CullSphere (r_refdef.frustum, &mat[3][0], radius)) { //FIXME + if (R_CullSphere (r_refdef.frustum, (vec_t*)&mat[3], radius)) { //FIXME return; } } else { diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 475ede102..2bf14fe2c 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -572,7 +572,7 @@ CL_ParseClientdata (void) else cl.frameVelocity[0][i] = 0; } - AngleQuat (punchangle, &cl.viewstate.punchangle[0]);//FIXME + AngleQuat (punchangle, (vec_t*)&cl.viewstate.punchangle);//FIXME //FIXME //if (!VectorCompare (v_punchangles[0], cl.punchangle[0])) { diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 70333bc4d..3fd0a3bf5 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -82,8 +82,7 @@ SCR_CShift (void) if (cls.state == ca_active && cl_world.worldmodel) { vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - //FIXME - leaf = Mod_PointInLeaf (&origin[0], cl_world.worldmodel); + leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.worldmodel);//FIXME contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); diff --git a/nq/source/host.c b/nq/source/host.c index 5ec8ee16e..16b029e13 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -613,7 +613,7 @@ Host_ClientFrame (void) vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - l = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);//FIXME + l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.worldmodel);//FIXME if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index d1d795de8..21a18fbfc 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1037,7 +1037,7 @@ SV_CreateBaseline (void) MSG_WriteByte (&sv.signon, baseline->colormap); MSG_WriteByte (&sv.signon, baseline->skinnum); - MSG_WriteCoordAngleV (&sv.signon, &baseline->origin[0],//FIXME + MSG_WriteCoordAngleV (&sv.signon, (vec_t*)&baseline->origin,//FIXME baseline->angles); if (bits & B_ALPHA) diff --git a/qtv/source/client.c b/qtv/source/client.c index 5feee07d7..9113d2b7d 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -683,7 +683,7 @@ write_player (int num, plent_state_t *pl, server_t *sv, sizebuf_t *msg) MSG_WriteByte (msg, num); MSG_WriteShort (msg, pflags); - MSG_WriteCoordV (msg, &pl->es.origin[0]);//FIXME + MSG_WriteCoordV (msg, (vec_t*)&pl->es.origin);//FIXME pl->es.origin[3] = 1; MSG_WriteByte (msg, pl->es.frame); diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index ba31950dc..db4a8c3e7 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -615,7 +615,7 @@ parse_player_delta (qmsg_t *msg, plent_state_t *from, plent_state_t *to) int flags; flags = to->es.flags = MSG_ReadShort (msg); - MSG_ReadCoordV (msg, &to->es.origin[0]); + MSG_ReadCoordV (msg, (vec_t*)&to->es.origin);//FIXME to->es.frame = (to->es.frame & 0xff00) | MSG_ReadByte (msg); if (flags & PF_MSEC) to->msec = MSG_ReadByte (msg); @@ -852,7 +852,7 @@ parse_baseline (qmsg_t *msg, entity_state_t *ent) ent->frame = MSG_ReadByte (msg); ent->colormap = MSG_ReadByte (msg); ent->skinnum = MSG_ReadByte (msg); - MSG_ReadCoordAngleV (msg, &ent->origin[0], ent->angles); //FIXME + MSG_ReadCoordAngleV (msg, (vec_t*)&ent->origin, ent->angles); //FIXME ent->origin[3] = 1; ent->colormod = 255; ent->alpha = 255; diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index d5d75ce22..e41e76a5f 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -191,7 +191,7 @@ Cam_Lock (int playernum) } static trace_t -Cam_DoTrace (vec3_t vec1, vec3_t vec2) +Cam_DoTrace (vec4f_t vec1, vec3_t vec2)//FIXME vec2 type { #if 0 memset (&pmove, 0, sizeof (pmove)); @@ -220,7 +220,7 @@ Cam_TryFlyby (player_state_t * self, player_state_t * player, vec3_t vec, VectorMultAdd (player->pls.es.origin, 800, vec, v); // v is endpos // fake a player move - trace = Cam_DoTrace (&player->pls.es.origin[0], v);//FIXME + trace = Cam_DoTrace (player->pls.es.origin, v); if ( /* trace.inopen || */ trace.inwater) return 9999; VectorCopy (trace.endpos, vec); @@ -229,7 +229,7 @@ Cam_TryFlyby (player_state_t * self, player_state_t * player, vec3_t vec, if (len < 32 || len > 800) return 9999; if (checkvis) { - trace = Cam_DoTrace (&self->pls.es.origin[0], vec);//FIXME + trace = Cam_DoTrace (self->pls.es.origin, vec); if (trace.fraction != 1 || trace.inwater) return 9999; @@ -247,7 +247,7 @@ Cam_IsVisible (player_state_t *player, vec3_t vec) trace_t trace; vec3_t v; - trace = Cam_DoTrace (&player->pls.es.origin[0], vec);//FIXME + trace = Cam_DoTrace (player->pls.es.origin, vec); if (trace.fraction != 1 || /* trace.inopen || */ trace.inwater) return false; // check distance, don't let the player get too far away or too close diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 2a5069db4..91fd7ced3 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -767,7 +767,7 @@ demo_start_recording (int track) MSG_WriteByte (&buf, es->frame); MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, es->skinnum); - MSG_WriteCoordAngleV (&buf, &es->origin[0], &es->angles[0]); + MSG_WriteCoordAngleV (&buf, (vec_t*)&es->origin, es->angles);//FIXME if (buf.cursize > MAX_MSGLEN / 2) { CL_WriteRecordDemoMessage (&buf, seq++); @@ -791,7 +791,7 @@ demo_start_recording (int track) MSG_WriteByte (&buf, es->frame); MSG_WriteByte (&buf, es->colormap); MSG_WriteByte (&buf, es->skinnum); - MSG_WriteCoordAngleV (&buf, &es->origin[0], es->angles);//FIXME + MSG_WriteCoordAngleV (&buf, (vec_t*)&es->origin, es->angles);//FIXME if (buf.cursize > MAX_MSGLEN / 2) { CL_WriteRecordDemoMessage (&buf, seq++); diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 550a8b308..80ec0112e 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -430,7 +430,7 @@ CL_ParsePlayerinfo (void) flags = state->pls.es.flags = MSG_ReadShort (net_message); state->messagenum = cl.parsecount; - MSG_ReadCoordV (net_message, &state->pls.es.origin[0]);//FIXME + MSG_ReadCoordV (net_message, (vec_t*)&state->pls.es.origin);//FIXME state->pls.es.origin[3] = 1; state->pls.es.frame = MSG_ReadByte (net_message); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 6777a822f..bdc7a3996 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1731,7 +1731,7 @@ Host_Frame (float time) vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - l = Mod_PointInLeaf (&origin[0], cl_world.worldmodel);//FIXME + l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.worldmodel);//FIXME if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 0d3cac20b..c7478445d 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1457,7 +1457,7 @@ CL_ParseServerMessage (void) SCR_SetFullscreen (1); cl.completed_time = realtime; Sys_MaskPrintf (SYS_dev, "intermission simorg: "); - MSG_ReadCoordV (net_message, &cl.viewstate.player_origin[0]);//FIXME + MSG_ReadCoordV (net_message, (vec_t*)&cl.viewstate.player_origin);//FIXME cl.viewstate.player_origin[3] = 1; Sys_MaskPrintf (SYS_dev, VEC4F_FMT, VEC4_EXP (cl.viewstate.player_origin)); diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 3242a7ebe..de8d13cf0 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -81,8 +81,7 @@ SCR_CShift (void) if (cls.state == ca_active && cl_world.worldmodel) { vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - //FIXME - leaf = Mod_PointInLeaf (&origin[0], cl_world.worldmodel); + leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.worldmodel);//FIXME contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index e38c2ca67..b5c7df94c 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -509,7 +509,7 @@ write_player (delta_t *delta, plent_state_t *from, plent_state_t *to, MSG_WriteByte (msg, to->es.number); MSG_WriteShort (msg, flags); - MSG_WriteCoordV (msg, &to->es.origin[0]);//FIXME + MSG_WriteCoordV (msg, (vec_t*)&to->es.origin);//FIXME MSG_WriteByte (msg, to->es.frame); diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 929cd4853..6f0d9753f 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -165,8 +165,9 @@ SV_CreateBaseline (void) MSG_WriteByte (&sv.signon, SVdata (svent)->state.colormap); MSG_WriteByte (&sv.signon, SVdata (svent)->state.skinnum); - MSG_WriteCoordAngleV (&sv.signon, &SVdata (svent)->state.origin[0], - SVdata (svent)->state.angles);//FIXME + MSG_WriteCoordAngleV (&sv.signon, + (vec_t*)&SVdata (svent)->state.origin,//FIXME + SVdata (svent)->state.angles); } } From 63e5655f68727744383e556a15df8ef11af27b55 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 00:16:29 +0900 Subject: [PATCH 2597/3664] Clean up some enum sanity checks It seems clang defaults to unsigned for enums. Interestingly, gcc was ok with the checks being either way. I guess gcc treats enums that *can* be unsigned as DWIM. --- libs/client/cl_input.c | 2 +- libs/console/client.c | 2 +- libs/console/menu.c | 2 +- libs/gamecode/pr_debug.c | 2 +- libs/input/in_binding.c | 4 ++-- libs/video/targets/in_x11.c | 2 +- tools/qfcc/source/dot_expr.c | 2 +- tools/qfcc/source/dump_globals.c | 7 +++---- 8 files changed, 11 insertions(+), 12 deletions(-) diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 3ca4b306a..ec2201cd2 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -453,7 +453,7 @@ cl_event_handler (const IE_event_t *ie_event, void *unused) [ie_gain_focus] = cl_focus_event, [ie_lose_focus] = cl_focus_event, }; - if (ie_event->type < 0 || ie_event->type >= ie_event_count + if ((unsigned) ie_event->type >= ie_event_count || !handlers[ie_event->type]) { return IN_Binding_HandleEvent (ie_event); } diff --git a/libs/console/client.c b/libs/console/client.c index 7aa375d0d..0ae47ae0b 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -821,7 +821,7 @@ con_event_handler (const IE_event_t *ie_event, void *data) [ie_key] = con_key_event, [ie_mouse] = con_mouse_event, }; - if (ie_event->type < 0 || ie_event->type >= ie_event_count + if ((unsigned) ie_event->type >= ie_event_count || !handlers[ie_event->type]) { return 0; } diff --git a/libs/console/menu.c b/libs/console/menu.c index 619b06c1a..0e02d63e3 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -824,7 +824,7 @@ Menu_EventHandler (const IE_event_t *ie_event) [ie_key] = menu_key_event, [ie_mouse] = menu_mouse_event, }; - if (ie_event->type < 0 || ie_event->type >= ie_event_count + if ((unsigned) ie_event->type >= ie_event_count || !handlers[ie_event->type]) { return 0; } diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 67f6b981e..3df6ba2a8 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -564,7 +564,7 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) type_ptr += type->size) { type = &G_STRUCT (pr, qfot_type_t, type_encodings + type_ptr); if (type->meta == ty_basic - && type->type >= 0 && type->type < ev_type_count) { + && (unsigned) type->type < ev_type_count) { res->type_encodings[type->type] = type; } } diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index acc80601a..74459481c 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -250,7 +250,7 @@ in_binding_event_handler (const IE_event_t *ie_event, void *unused) [ie_add_device] = in_binding_add_device, [ie_remove_device] = in_binding_remove_device, }; - if (ie_event->type < 0 || ie_event->type >= ie_event_count + if ((unsigned) ie_event->type >= ie_event_count || !handlers[ie_event->type]) { return 0; } @@ -265,7 +265,7 @@ IN_Binding_HandleEvent (const IE_event_t *ie_event) [ie_axis] = in_binding_axis, [ie_button] = in_binding_button, }; - if (ie_event->type < 0 || ie_event->type >= ie_event_count + if ((unsigned) ie_event->type >= ie_event_count || !handlers[ie_event->type]) { return 0; } diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 3f7685fb1..40bd1e0ef 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -1495,7 +1495,7 @@ x11_event_handler (const IE_event_t *ie_event, void *unused) static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { [ie_app_window] = x11_app_window, }; - if (ie_event->type < 0 || ie_event->type >= ie_event_count + if ((unsigned) ie_event->type >= ie_event_count || !handlers[ie_event->type]) { return 0; } diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 52db56ca9..29c5ac319 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -711,7 +711,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) if ((int) e->type < 0 || e->type >= ex_count || !print_funcs[e->type]) { const char *type = va (0, "%d", e->type); - if (e->type >= 0 && e->type < ex_count) { + if ((unsigned) e->type < ex_count) { type = expr_names[e->type]; } dasprintf (dstr, "%*se_%p [label=\"(bad expr type: %s)\\n%d\"];\n", diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index c0ade919b..d95c772cc 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -543,20 +543,19 @@ dump_qfo_types (qfo_t *qfo, int base_address) qfo->spaces[qfo_type_space].data_size); continue; } - if (type->meta < 0 || type->meta >= NUM_META) + if ((unsigned) type->meta >= NUM_META) meta = va (0, "invalid meta: %d", type->meta); else meta = ty_meta_names[type->meta]; printf ("%-5x %-9s %-20s", type_ptr + base_address, meta, QFO_TYPESTR (qfo, type_ptr)); - if (type->meta < 0 || type->meta >= NUM_META) { + if ((unsigned) type->meta >= NUM_META) { puts (""); break; } switch ((ty_meta_e) type->meta) { case ty_basic: - printf (" %-10s", (type->type < 0 - || type->type >= ev_type_count) + printf (" %-10s", ((unsigned) type->type >= ev_type_count) ? "invalid type" : pr_type_name[type->type]); if (type->type == ev_func) { From 38319d01b20723b3f09b18805d278bf340795724 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 00:21:44 +0900 Subject: [PATCH 2598/3664] Fix some null pointer shenanigans clang doesn't like anything but a bare 0 as null (and in some of the cases, it was quite right: '\0' should not be treated as a null pointer). And the crashers were just for paranoia and probably aren't needed any more (kept for now, though). --- libs/gib/regex.c | 2 +- libs/util/cmem.c | 20 ++++++++++---------- qw/source/cl_slist.c | 4 ++-- tools/qfvis/source/qfvis.c | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libs/gib/regex.c b/libs/gib/regex.c index 1d6e19dc4..74a16b1a2 100644 --- a/libs/gib/regex.c +++ b/libs/gib/regex.c @@ -2849,7 +2849,7 @@ re_set_registers (bufp, regs, num_regs, starts, ends) { bufp->regs_allocated = REGS_UNALLOCATED; regs->num_regs = 0; - regs->start = regs->end = (regoff_t) 0; + regs->start = regs->end = 0; } } diff --git a/libs/util/cmem.c b/libs/util/cmem.c index 1f448481c..9b13a4b6e 100644 --- a/libs/util/cmem.c +++ b/libs/util/cmem.c @@ -175,9 +175,9 @@ line_free (memsuper_t *super, memblock_t *block, void *mem) for (l = &block->free_lines; *l; l = &(*l)->block_next) { line = *l; - if (line->block_next && line->block_next < line) { - *(int *)0 = 0; - } +// if (line->block_next && line->block_next < line) { +// *(int *)0 = 0; +// } if ((size_t) mem + size < (size_t) line) { // line to be freed is below the free line break; @@ -206,10 +206,10 @@ line_free (memsuper_t *super, memblock_t *block, void *mem) link_free_line (super, line); return; } - if ((size_t) mem >= (size_t) line - && (size_t) mem < (size_t) line + line->size) { - *(int *) 0 = 0; - } +// if ((size_t) mem >= (size_t) line +// && (size_t) mem < (size_t) line + line->size) { +// *(int *) 0 = 0; +// } line = 0; } memline_t *memline = (memline_t *) mem; @@ -326,9 +326,9 @@ cmemalloc (memsuper_t *super, size_t size) static void unlink_block (memblock_t *block) { - if (!block->free_lines || block->free_lines->block_next) { - *(int *) 0 = 0; - } +// if (!block->free_lines || block->free_lines->block_next) { +// *(int *) 0 = 0; +// } unlink_line (block->free_lines); if (block->next) { diff --git a/qw/source/cl_slist.c b/qw/source/cl_slist.c index ded6445c8..4d5b43513 100644 --- a/qw/source/cl_slist.c +++ b/qw/source/cl_slist.c @@ -324,7 +324,7 @@ gettokstart (char *str, int req, char delim) start++; } if (*start == '\0') - return '\0'; + return 0; while (tok < req) { // Stop when we get to the requested // token if (*++start == delim) { // Increment pointer and test @@ -334,7 +334,7 @@ gettokstart (char *str, int req, char delim) tok++; } if (*start == '\0') { - return '\0'; + return 0; } } return start; diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 263e9ebb2..26164c30a 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -251,7 +251,7 @@ split_edge (const vec4f_t *points, const vec4f_t *dists, mid = (vec4f_t) ((vec4i_t) _mm_and_ps (y, (__m128) x) | (vec4i_t) _mm_and_ps (mid, (__m128) ~x)); #endif - if (isnan (mid[0])) *(int *) 0 = 0; +// if (isnan (mid[0])) *(int *) 0 = 0; return mid; } From 0bb562f93f8ef3b2647bd4f776ed9bbd89a9ee28 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 00:28:26 +0900 Subject: [PATCH 2599/3664] Fix a bunch of float vs int bugs Just those made me glad I tried compiling with clang: running into those bugs would have lead to some serious headaches, I imagine. --- nq/source/cl_ents.c | 2 +- nq/source/sv_move.c | 2 +- qw/source/cl_ents.c | 2 +- qw/source/sv_move.c | 2 +- tools/bsp2img/bsp2img.c | 2 +- tools/qflight/include/entities.h | 2 +- tools/qflight/source/entities.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 588753fd2..92ea20f5b 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -271,7 +271,7 @@ CL_RelinkEntities (void) f = frac; ent->old_origin = Transform_GetWorldPosition (ent->transform); // If the delta is large, assume a teleport and don't lerp - if (fabs (delta[0]) > 100 || fabs (delta[1] > 100) + if (fabs (delta[0]) > 100 || fabs (delta[1]) > 100 || fabs (delta[2]) > 100) { // assume a teleportation, not a motion CL_TransformEntity (ent, new->scale / 16.0, new->angles, diff --git a/nq/source/sv_move.c b/nq/source/sv_move.c index 3970f6d78..cb94c1c89 100644 --- a/nq/source/sv_move.c +++ b/nq/source/sv_move.c @@ -294,7 +294,7 @@ SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) return; } // try other directions - if (((rand () & 3) & 1) || abs (deltay) > abs (deltax)) { + if (((rand () & 3) & 1) || fabsf (deltay) > fabsf (deltax)) { tdir = d[1]; d[1] = d[2]; d[2] = tdir; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index c0cd30bd1..5e9bb0069 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -240,7 +240,7 @@ CL_LinkPacketEntities (void) vec4f_t delta = new->origin - old->origin; f = frac; // If the delta is large, assume a teleport and don't lerp - if (fabs (delta[0]) > 100 || fabs (delta[1] > 100) + if (fabs (delta[0]) > 100 || fabs (delta[1]) > 100 || fabs (delta[2]) > 100) { // assume a teleportation, not a motion CL_TransformEntity (ent, new->scale / 16, new->angles, diff --git a/qw/source/sv_move.c b/qw/source/sv_move.c index c500e30ed..9df58daa0 100644 --- a/qw/source/sv_move.c +++ b/qw/source/sv_move.c @@ -293,7 +293,7 @@ SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) return; } // try other directions - if (((rand () & 3) & 1) || abs (deltay) > abs (deltax)) { + if (((rand () & 3) & 1) || fabsf (deltay) > fabsf (deltax)) { tdir = d[1]; d[1] = d[2]; d[2] = tdir; diff --git a/tools/bsp2img/bsp2img.c b/tools/bsp2img/bsp2img.c index 5301e09fe..f469e6bf9 100644 --- a/tools/bsp2img/bsp2img.c +++ b/tools/bsp2img/bsp2img.c @@ -820,7 +820,7 @@ render_map (bsp_t *bsp) vert1 = &vertexlist[edgelist[i].v[0]]; vert2 = &vertexlist[edgelist[i].v[1]]; SUB (*vert1, *vert2, vect); - if (abs (tempf) < options.flat_threshold + if (fabsf (tempf) < options.flat_threshold && usearea > options.area_threshold && sqrt (DOT (vect, vect)) > options.linelen_threshold) { float offs0, offs1; diff --git a/tools/qflight/include/entities.h b/tools/qflight/include/entities.h index 6f3d1dd12..0873369d7 100644 --- a/tools/qflight/include/entities.h +++ b/tools/qflight/include/entities.h @@ -56,7 +56,7 @@ typedef struct entity_s { const char *classname; vec3_t origin; vec_t angle; - int light; + vec_t light; int sun_light[2]; vec3_t sun_color[2]; diff --git a/tools/qflight/source/entities.c b/tools/qflight/source/entities.c index 8c2260fcd..85ce43431 100644 --- a/tools/qflight/source/entities.c +++ b/tools/qflight/source/entities.c @@ -241,7 +241,7 @@ LoadEntities (void) } if (options.verbosity > 1 && entity->targetname) - printf ("%s %d %d\n", entity->targetname, entity->light, + printf ("%s %g %d\n", entity->targetname, entity->light, entity->style); // all fields have been parsed From 78089a0e9915a9e6033c7d1be43e7d6c5f23cb17 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 00:30:00 +0900 Subject: [PATCH 2600/3664] [mode] Fix a sizeof error I'm surprised that got past gcc, but it's nice clang caught it. --- libs/models/model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/models/model.c b/libs/models/model.c index bee2ac385..2e7dc48b2 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -178,7 +178,7 @@ Mod_RealLoadModel (model_t *mod, qboolean crash, cache_allocator_t allocator) } char *name = QFS_FileBase (mod->path); - strncpy (mod->name, name, sizeof (mod->name - 1)); + strncpy (mod->name, name, sizeof (mod->name) - 1); mod->name[sizeof (mod->name) - 1] = 0; free (name); From 68b133417be8f2f49c3aadeb0ba104b63a0efe66 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 00:31:15 +0900 Subject: [PATCH 2601/3664] [net] Fix some logic precedence errors --- libs/net/nm/net_udp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/net/nm/net_udp.c b/libs/net/nm/net_udp.c index ebc49a886..13044d0c3 100644 --- a/libs/net/nm/net_udp.c +++ b/libs/net/nm/net_udp.c @@ -195,7 +195,7 @@ get_iface_list (int sock) if (getifaddrs (&ifa_head) < 0) goto no_ifaddrs; for (ifa = ifa_head; ifa; ifa = ifa->ifa_next) { - if (!ifa->ifa_flags & IFF_UP) + if (!(ifa->ifa_flags & IFF_UP)) continue; if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET) continue; @@ -208,7 +208,7 @@ get_iface_list (int sock) for (ifa = ifa_head; ifa; ifa = ifa->ifa_next) { struct sockaddr_in *sa; - if (!ifa->ifa_flags & IFF_UP) + if (!(ifa->ifa_flags & IFF_UP)) continue; if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET) continue; From b02e29ea8923500ebd25bcc2b29d2e27af30915d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 00:34:40 +0900 Subject: [PATCH 2602/3664] [x11] Clear up some signed/unsigned ambiguity I don't remember what gcc does with unsigned-int, but obviously clang produces another unsigned, which is most definitely not wanted. --- libs/video/targets/in_x11.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 40bd1e0ef..5395ea639 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -801,8 +801,10 @@ event_motion (XEvent *event) } else { if (vid_fullscreen->int_val || input_grabbed) { if (!event->xmotion.send_event) { - unsigned dist_x = abs (viddef.width / 2 - event->xmotion.x); - unsigned dist_y = abs (viddef.height / 2 - event->xmotion.y); + int center_x = viddef.width / 2; + int center_y = viddef.height / 2; + unsigned dist_x = abs (center_x / 2 - event->xmotion.x); + unsigned dist_y = abs (center_y / 2 - event->xmotion.y); x11_mouse_axes[0].value = event->xmotion.x - x11_mouse.x; x11_mouse_axes[1].value = event->xmotion.y - x11_mouse.y; From 3479897224c4c4c5400061f232f27b4d8650e8b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 00:37:53 +0900 Subject: [PATCH 2603/3664] [qfcc] Fix some not uninitialized warnings The "not" because I'm pretty sure they're false positives due to when the function is called, but clang doesn't know that (wonder why gcc was ok with it). --- tools/qfcc/source/expr_binary.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 832abdc09..6c792a1de 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -647,10 +647,10 @@ pointer_arithmetic (int op, expr_t *e1, expr_t *e2) { type_t *t1 = get_type (e1); type_t *t2 = get_type (e2); - expr_t *ptr; - expr_t *offset; + expr_t *ptr = 0; + expr_t *offset = 0; expr_t *psize; - type_t *ptype; + type_t *ptype = 0; if (!is_ptr (t1) && !is_ptr (t2)) { internal_error (e1, "pointer arithmetic on non-pointers"); From 12300d9a985063107eda3353c85880f0eb82462d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 01:15:59 +0900 Subject: [PATCH 2604/3664] [qfcc] Remove alias offset from initialize_def I'm not sure which is mysterious: why it's there, or why it did nothing. Since it does nothing and things are working, it should be safe to remove. --- tools/qfcc/source/def.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 29214b5c3..7a06a1730 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -605,15 +605,11 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, // fold_constants takes care of int/float conversions append_expr (local_expr, fold_constants (init)); } else { - int offset = 0; if (!is_constant (init)) { error (init, "non-constant initializier"); return; } while (init->type == ex_alias) { - if (init->e.alias.offset) { - offset += expr_int (init->e.alias.offset); - } init = init->e.alias.expr; } if (init->type != ex_value) { //FIXME enum etc From 73c65749fc07039334822ecb68815122593b9d31 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 01:17:47 +0900 Subject: [PATCH 2605/3664] [qfvis] Fix a vector type error I suspect I wasn't getting nan like I wanted. --- tools/qfvis/source/qfvis.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 26164c30a..f05b108b8 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -240,9 +240,9 @@ split_edge (const vec4f_t *points, const vec4f_t *dists, // component to the split-plane's distance when the split-plane's // normal is signed-canonical. // "nan" because 0x7fffffff is nan when viewed as a float - static const vec4f_t onenan = { 1, 1, 1, ~0u >> 1 }; + static const vec4i_t onenan = {0x3f800000,0x3f800000,0x3f800000,~0u >> 1}; static const vec4i_t nan = { ~0u >> 1, ~0u >> 1, ~0u >> 1, ~0u >> 1}; - vec4i_t x = _mm_and_ps (split, (__m128) nan) == onenan; + vec4i_t x = _mm_and_ps (split, (__m128) nan) == (__m128) onenan; // plane vector has -dist in w vec4f_t y = _mm_and_ps (split, (__m128) x) * -split[3]; #ifdef __SSE3__ From 7305406f46677c74f61a2e04c28fbbede7692b0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 01:26:57 +0900 Subject: [PATCH 2606/3664] [vulkan] Update labeled struct inits I had used some legacy gcc extensions rather than standard C (clang wasn't too happy about that). --- libs/video/renderer/vulkan/scrap.c | 2 +- .../video/renderer/vulkan/test/test-staging.c | 38 +++++++++---------- libs/video/renderer/vulkan/vulkan_bsp.c | 6 +-- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libs/video/renderer/vulkan/scrap.c b/libs/video/renderer/vulkan/scrap.c index 3eaf74840..6517d2b17 100644 --- a/libs/video/renderer/vulkan/scrap.c +++ b/libs/video/renderer/vulkan/scrap.c @@ -137,7 +137,7 @@ QFV_CreateScrap (qfv_device_t *device, const char *name, int size, 0, 0, 0, 0, 0, 1, &ib.barrier); VkClearColorValue color = { - float32:{0xde/255.0, 0xad/255.0, 0xbe/255.0, 0xef/255.0}, + .float32 = {0xde/255.0, 0xad/255.0, 0xbe/255.0, 0xef/255.0}, }; VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; dfunc->vkCmdClearColorImage (packet->cmd, scrap->image, diff --git a/libs/video/renderer/vulkan/test/test-staging.c b/libs/video/renderer/vulkan/test/test-staging.c index 4f1705ce8..d8c772222 100644 --- a/libs/video/renderer/vulkan/test/test-staging.c +++ b/libs/video/renderer/vulkan/test/test-staging.c @@ -139,31 +139,31 @@ vkQueueSubmit (VkQueue queue, uint32_t count, const VkSubmitInfo *submits, } qfv_devfuncs_t dfuncs = { - vkCreateBuffer:vkCreateBuffer, - vkGetBufferMemoryRequirements:vkGetBufferMemoryRequirements, - vkMapMemory:vkMapMemory, - vkBindBufferMemory:vkBindBufferMemory, - vkAllocateCommandBuffers:vkAllocateCommandBuffers, - vkCreateFence:vkCreateFence, - vkWaitForFences:vkWaitForFences, - vkResetFences:vkResetFences, - vkGetFenceStatus:vkGetFenceStatus, - vkResetCommandBuffer:vkResetCommandBuffer, - vkBeginCommandBuffer:vkBeginCommandBuffer, - vkEndCommandBuffer:vkEndCommandBuffer, - vkFlushMappedMemoryRanges:vkFlushMappedMemoryRanges, - vkQueueSubmit:vkQueueSubmit, + .vkCreateBuffer = vkCreateBuffer, + .vkGetBufferMemoryRequirements = vkGetBufferMemoryRequirements, + .vkMapMemory = vkMapMemory, + .vkBindBufferMemory = vkBindBufferMemory, + .vkAllocateCommandBuffers = vkAllocateCommandBuffers, + .vkCreateFence = vkCreateFence, + .vkWaitForFences = vkWaitForFences, + .vkResetFences = vkResetFences, + .vkGetFenceStatus = vkGetFenceStatus, + .vkResetCommandBuffer = vkResetCommandBuffer, + .vkBeginCommandBuffer = vkBeginCommandBuffer, + .vkEndCommandBuffer = vkEndCommandBuffer, + .vkFlushMappedMemoryRanges = vkFlushMappedMemoryRanges, + .vkQueueSubmit = vkQueueSubmit, }; qfv_physdev_t physDev = { - properties:{ - limits:{ - nonCoherentAtomSize:256, + .properties = { + .limits = { + .nonCoherentAtomSize = 256, }, }, }; qfv_device_t device = { - physDev:&physDev, - funcs:&dfuncs, + .physDev = &physDev, + .funcs = &dfuncs, }; static void __attribute__ ((format (PRINTF, 2, 3), noreturn)) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 80da6abaa..1097222a6 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1052,7 +1052,7 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bframe->cmdSet.a[QFV_bspDepth]); push_transform (identity, bctx->layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); - bsp_push_constants_t frag_constants = { time: vr_data.realtime }; + bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); for (size_t i = 0; i < bctx->texture_chains.size; i++) { @@ -1120,7 +1120,7 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) turb_begin (rFrame); push_transform (identity, bctx->layout, device, bframe->cmdSet.a[QFV_bspTurb]); - bsp_push_constants_t frag_constants = { time: vr_data.realtime }; + bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspTurb]); for (is = bctx->waterchain; is; is = is->tex_chain) { @@ -1182,7 +1182,7 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) bframe->cmdSet.a[QFV_bspSky]); push_transform (identity, bctx->layout, device, bframe->cmdSet.a[QFV_bspSky]); - bsp_push_constants_t frag_constants = { time: vr_data.realtime }; + bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspSky]); for (is = bctx->sky_chain; is; is = is->tex_chain) { From 7a6ca0ebcb5559a3a06d8ccc4f7b9b31e2a19da6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 02:25:33 +0900 Subject: [PATCH 2607/3664] [simd] Use portable swizzles gcc and clang have rather different swizzle builtins, but both do a nice job of optimizing the intuitive initializer swizzle (I think gcc 8(?) didn't do such a good job thus my use of __builtin_shuffle). --- include/QF/simd/mat4f.h | 24 +- include/QF/simd/vec4d.h | 11 +- include/QF/simd/vec4f.h | 6 +- libs/gamecode/Makemodule.am | 18 +- libs/gamecode/pr_exec.c | 650 +----------------------------------- libs/gamecode/swizzle.py | 6 +- 6 files changed, 42 insertions(+), 673 deletions(-) diff --git a/include/QF/simd/mat4f.h b/include/QF/simd/mat4f.h index e461fe4a3..d442bdac9 100644 --- a/include/QF/simd/mat4f.h +++ b/include/QF/simd/mat4f.h @@ -159,9 +159,9 @@ mat4fquat (mat4f_t m, vec4f_t q) vec4f_t zq = q[2] * q; vec4f_t wq = q[3] * q; - static const vec4i_t shuff103 = { 1, 0, 3, 2 }; - static const vec4i_t shuff230 = { 2, 3, 0, 1 }; - static const vec4i_t shuff321 = { 3, 2, 1, 0 }; +#define shuff103(v) (vec4f_t) {v[1], v[0], v[3], v[2]} +#define shuff230(v) (vec4f_t) {v[2], v[3], v[0], v[1]} +#define shuff321(v) (vec4f_t) {v[3], v[2], v[1], v[0]} #define p (0) #define m (1u << 31) static const vec4i_t mpm = { m, p, m, 0 }; @@ -172,24 +172,24 @@ mat4fquat (mat4f_t m, vec4f_t q) #undef m { vec4f_t a = xq; - vec4f_t b = _mm_xor_ps (__builtin_shuffle (yq, shuff103), (__m128) mpm); - vec4f_t c = _mm_xor_ps (__builtin_shuffle (zq, shuff230), (__m128) pmm); - vec4f_t d = _mm_xor_ps (__builtin_shuffle (wq, shuff321), (__m128) mmp); + vec4f_t b = _mm_xor_ps (shuff103 (yq), (__m128) mpm); + vec4f_t c = _mm_xor_ps (shuff230 (zq), (__m128) pmm); + vec4f_t d = _mm_xor_ps (shuff321 (wq), (__m128) mmp); m[0] = _mm_and_ps (a + b - c - d, (__m128) mask); } { - vec4f_t a = _mm_xor_ps (__builtin_shuffle (xq, shuff103), (__m128) mpm); + vec4f_t a = _mm_xor_ps (shuff103 (xq), (__m128) mpm); vec4f_t b = yq; - vec4f_t c = _mm_xor_ps (__builtin_shuffle (zq, shuff321), (__m128) mmp); - vec4f_t d = _mm_xor_ps (__builtin_shuffle (wq, shuff230), (__m128) pmm); + vec4f_t c = _mm_xor_ps (shuff321 (zq), (__m128) mmp); + vec4f_t d = _mm_xor_ps (shuff230 (wq), (__m128) pmm); m[1] = _mm_and_ps (b + c - a - d, (__m128) mask); } { - vec4f_t a = _mm_xor_ps (__builtin_shuffle (xq, shuff230), (__m128) pmm); - vec4f_t b = _mm_xor_ps (__builtin_shuffle (yq, shuff321), (__m128) mmp); + vec4f_t a = _mm_xor_ps (shuff230 (xq), (__m128) pmm); + vec4f_t b = _mm_xor_ps (shuff321 (yq), (__m128) mmp); vec4f_t c = zq; - vec4f_t d = _mm_xor_ps (__builtin_shuffle (wq, shuff103), (__m128) mpm); + vec4f_t d = _mm_xor_ps (shuff103 (wq), (__m128) mpm); m[2] = _mm_and_ps (a - b + c - d, (__m128) mask); } m[3] = (vec4f_t) { 0, 0, 0, 1 }; diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 791c48dde..58c18a8e1 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -184,11 +184,9 @@ VISIBLE vec4d_t crossd (vec4d_t a, vec4d_t b) { - static const vec4l_t A = {1, 2, 0, 3}; - vec4d_t c = a * __builtin_shuffle (b, A); - vec4d_t d = __builtin_shuffle (a, A) * b; - c = c - d; - return __builtin_shuffle(c, A); + vec4d_t c = a * (vec4d_t) {b[1], b[2], b[0], b[3]} + - b * (vec4d_t) {a[1], a[2], a[0], a[3]}; + return (vec4d_t) {c[1], c[2], c[0], c[3]}; } #ifndef IMPLEMENT_VEC4D_Funcs @@ -205,8 +203,7 @@ dotd (vec4d_t a, vec4d_t b) #else c = _mm256_hadd_pd (c, c); #endif - static const vec4l_t A = {2, 3, 0, 1}; - c += __builtin_shuffle(c, A); + c += (vec4d_t) {c[2], c[3], c[0], c[1]}; return c; } diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 7b7c8429d..9ccda895e 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -197,9 +197,9 @@ VISIBLE vec4f_t crossf (vec4f_t a, vec4f_t b) { - static const vec4i_t A = {1, 2, 0, 3}; - vec4f_t c = a * __builtin_shuffle (b, A) - __builtin_shuffle (a, A) * b; - return __builtin_shuffle(c, A); + vec4f_t c = a * (vec4f_t) {b[1], b[2], b[0], b[3]} + - b * (vec4f_t) {a[1], a[2], a[0], a[3]}; + return (vec4f_t) {c[1], c[2], c[0], c[3]}; } #ifndef IMPLEMENT_VEC4F_Funcs diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index ab294580a..d26ac90e7 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -21,7 +21,7 @@ libs_gamecode_libQFgamecode_la_SOURCES= \ libs/gamecode/pr_v6p_opcode.c \ libs/gamecode/pr_zone.c -noinst_PYTHON += $(opcodes_py) $(convert_py) $(hops_py) +noinst_PYTHON += $(opcodes_py) $(convert_py) $(hops_py) $(swizzle_py) opcodes_py = $(srcdir)/libs/gamecode/opcodes.py pr_opcode_cinc = $(top_builddir)/libs/gamecode/pr_opcode.cinc @@ -37,11 +37,17 @@ pr_convert_cinc = $(top_builddir)/libs/gamecode/pr_convert.cinc hops_py = $(srcdir)/libs/gamecode/hops.py pr_hops_cinc = $(top_builddir)/libs/gamecode/pr_hops.cinc +swizzle_py = $(srcdir)/libs/gamecode/swizzle.py +pr_swizzle32_cinc = $(top_builddir)/libs/gamecode/pr_swizzle32.cinc +pr_swizzle64_cinc = $(top_builddir)/libs/gamecode/pr_swizzle64.cinc + BUILT_SOURCES += \ $(pr_opcode_cinc) \ $(pr_opcode_hinc) \ $(pr_convert_cinc) \ - $(pr_hops_cinc) + $(pr_hops_cinc) \ + $(pr_swizzle32_cinc) \ + $(pr_swizzle64_cinc) CLEANFILES += \ $(pr_opcode_cinc) \ @@ -65,3 +71,11 @@ $(pr_convert_cinc): $(convert_py) $(pr_hops_cinc): $(hops_py) $(V_PY)$(PYTHON) $(hops_py) table > $(pr_hops_cinc).t && \ $(am__mv) $(pr_hops_cinc).t $(pr_hops_cinc) + +$(pr_swizzle32_cinc): $(swizzle_py) + $(V_PY)$(PYTHON) $(swizzle_py) case int > $(pr_swizzle32_cinc).t && \ + $(am__mv) $(pr_swizzle32_cinc).t $(pr_swizzle32_cinc) + +$(pr_swizzle64_cinc): $(swizzle_py) + $(V_PY)$(PYTHON) $(swizzle_py) case long > $(pr_swizzle64_cinc).t && \ + $(am__mv) $(pr_swizzle64_cinc).t $(pr_swizzle64_cinc) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index ea819c6e9..194237768 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2001,330 +2001,7 @@ static pr_ivec4_t pr_swizzle_f (pr_ivec4_t vec, pr_ushort_t swiz) { goto do_swizzle; -#define swizzle __builtin_shuffle - swizzle_xxxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 0 }); goto negate; - swizzle_yxxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 0 }); goto negate; - swizzle_zxxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 0 }); goto negate; - swizzle_wxxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 0 }); goto negate; - swizzle_xyxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 0 }); goto negate; - swizzle_yyxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 0 }); goto negate; - swizzle_zyxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 0 }); goto negate; - swizzle_wyxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 0 }); goto negate; - swizzle_xzxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 0 }); goto negate; - swizzle_yzxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 0 }); goto negate; - swizzle_zzxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 0 }); goto negate; - swizzle_wzxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 0 }); goto negate; - swizzle_xwxx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 0 }); goto negate; - swizzle_ywxx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 0 }); goto negate; - swizzle_zwxx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 0 }); goto negate; - swizzle_wwxx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 0 }); goto negate; - swizzle_xxyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 0 }); goto negate; - swizzle_yxyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 0 }); goto negate; - swizzle_zxyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 0 }); goto negate; - swizzle_wxyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 0 }); goto negate; - swizzle_xyyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 0 }); goto negate; - swizzle_yyyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 0 }); goto negate; - swizzle_zyyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 0 }); goto negate; - swizzle_wyyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 0 }); goto negate; - swizzle_xzyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 0 }); goto negate; - swizzle_yzyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 0 }); goto negate; - swizzle_zzyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 0 }); goto negate; - swizzle_wzyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 0 }); goto negate; - swizzle_xwyx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 0 }); goto negate; - swizzle_ywyx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 0 }); goto negate; - swizzle_zwyx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 0 }); goto negate; - swizzle_wwyx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 0 }); goto negate; - swizzle_xxzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 0 }); goto negate; - swizzle_yxzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 0 }); goto negate; - swizzle_zxzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 0 }); goto negate; - swizzle_wxzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 0 }); goto negate; - swizzle_xyzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 0 }); goto negate; - swizzle_yyzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 0 }); goto negate; - swizzle_zyzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 0 }); goto negate; - swizzle_wyzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 0 }); goto negate; - swizzle_xzzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 0 }); goto negate; - swizzle_yzzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 0 }); goto negate; - swizzle_zzzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 0 }); goto negate; - swizzle_wzzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 0 }); goto negate; - swizzle_xwzx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 0 }); goto negate; - swizzle_ywzx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 0 }); goto negate; - swizzle_zwzx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 0 }); goto negate; - swizzle_wwzx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 0 }); goto negate; - swizzle_xxwx: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 0 }); goto negate; - swizzle_yxwx: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 0 }); goto negate; - swizzle_zxwx: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 0 }); goto negate; - swizzle_wxwx: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 0 }); goto negate; - swizzle_xywx: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 0 }); goto negate; - swizzle_yywx: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 0 }); goto negate; - swizzle_zywx: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 0 }); goto negate; - swizzle_wywx: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 0 }); goto negate; - swizzle_xzwx: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 0 }); goto negate; - swizzle_yzwx: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 0 }); goto negate; - swizzle_zzwx: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 0 }); goto negate; - swizzle_wzwx: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 0 }); goto negate; - swizzle_xwwx: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 0 }); goto negate; - swizzle_ywwx: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 0 }); goto negate; - swizzle_zwwx: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 0 }); goto negate; - swizzle_wwwx: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 0 }); goto negate; - swizzle_xxxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 1 }); goto negate; - swizzle_yxxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 1 }); goto negate; - swizzle_zxxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 1 }); goto negate; - swizzle_wxxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 1 }); goto negate; - swizzle_xyxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 1 }); goto negate; - swizzle_yyxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 1 }); goto negate; - swizzle_zyxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 1 }); goto negate; - swizzle_wyxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 1 }); goto negate; - swizzle_xzxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 1 }); goto negate; - swizzle_yzxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 1 }); goto negate; - swizzle_zzxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 1 }); goto negate; - swizzle_wzxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 1 }); goto negate; - swizzle_xwxy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 1 }); goto negate; - swizzle_ywxy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 1 }); goto negate; - swizzle_zwxy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 1 }); goto negate; - swizzle_wwxy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 1 }); goto negate; - swizzle_xxyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 1 }); goto negate; - swizzle_yxyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 1 }); goto negate; - swizzle_zxyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 1 }); goto negate; - swizzle_wxyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 1 }); goto negate; - swizzle_xyyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 1 }); goto negate; - swizzle_yyyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 1 }); goto negate; - swizzle_zyyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 1 }); goto negate; - swizzle_wyyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 1 }); goto negate; - swizzle_xzyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 1 }); goto negate; - swizzle_yzyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 1 }); goto negate; - swizzle_zzyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 1 }); goto negate; - swizzle_wzyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 1 }); goto negate; - swizzle_xwyy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 1 }); goto negate; - swizzle_ywyy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 1 }); goto negate; - swizzle_zwyy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 1 }); goto negate; - swizzle_wwyy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 1 }); goto negate; - swizzle_xxzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 1 }); goto negate; - swizzle_yxzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 1 }); goto negate; - swizzle_zxzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 1 }); goto negate; - swizzle_wxzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 1 }); goto negate; - swizzle_xyzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 1 }); goto negate; - swizzle_yyzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 1 }); goto negate; - swizzle_zyzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 1 }); goto negate; - swizzle_wyzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 1 }); goto negate; - swizzle_xzzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 1 }); goto negate; - swizzle_yzzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 1 }); goto negate; - swizzle_zzzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 1 }); goto negate; - swizzle_wzzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 1 }); goto negate; - swizzle_xwzy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 1 }); goto negate; - swizzle_ywzy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 1 }); goto negate; - swizzle_zwzy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 1 }); goto negate; - swizzle_wwzy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 1 }); goto negate; - swizzle_xxwy: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 1 }); goto negate; - swizzle_yxwy: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 1 }); goto negate; - swizzle_zxwy: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 1 }); goto negate; - swizzle_wxwy: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 1 }); goto negate; - swizzle_xywy: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 1 }); goto negate; - swizzle_yywy: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 1 }); goto negate; - swizzle_zywy: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 1 }); goto negate; - swizzle_wywy: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 1 }); goto negate; - swizzle_xzwy: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 1 }); goto negate; - swizzle_yzwy: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 1 }); goto negate; - swizzle_zzwy: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 1 }); goto negate; - swizzle_wzwy: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 1 }); goto negate; - swizzle_xwwy: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 1 }); goto negate; - swizzle_ywwy: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 1 }); goto negate; - swizzle_zwwy: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 1 }); goto negate; - swizzle_wwwy: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 1 }); goto negate; - swizzle_xxxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 2 }); goto negate; - swizzle_yxxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 2 }); goto negate; - swizzle_zxxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 2 }); goto negate; - swizzle_wxxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 2 }); goto negate; - swizzle_xyxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 2 }); goto negate; - swizzle_yyxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 2 }); goto negate; - swizzle_zyxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 2 }); goto negate; - swizzle_wyxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 2 }); goto negate; - swizzle_xzxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 2 }); goto negate; - swizzle_yzxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 2 }); goto negate; - swizzle_zzxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 2 }); goto negate; - swizzle_wzxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 2 }); goto negate; - swizzle_xwxz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 2 }); goto negate; - swizzle_ywxz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 2 }); goto negate; - swizzle_zwxz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 2 }); goto negate; - swizzle_wwxz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 2 }); goto negate; - swizzle_xxyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 2 }); goto negate; - swizzle_yxyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 2 }); goto negate; - swizzle_zxyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 2 }); goto negate; - swizzle_wxyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 2 }); goto negate; - swizzle_xyyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 2 }); goto negate; - swizzle_yyyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 2 }); goto negate; - swizzle_zyyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 2 }); goto negate; - swizzle_wyyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 2 }); goto negate; - swizzle_xzyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 2 }); goto negate; - swizzle_yzyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 2 }); goto negate; - swizzle_zzyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 2 }); goto negate; - swizzle_wzyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 2 }); goto negate; - swizzle_xwyz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 2 }); goto negate; - swizzle_ywyz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 2 }); goto negate; - swizzle_zwyz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 2 }); goto negate; - swizzle_wwyz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 2 }); goto negate; - swizzle_xxzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 2 }); goto negate; - swizzle_yxzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 2 }); goto negate; - swizzle_zxzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 2 }); goto negate; - swizzle_wxzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 2 }); goto negate; - swizzle_xyzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 2 }); goto negate; - swizzle_yyzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 2 }); goto negate; - swizzle_zyzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 2 }); goto negate; - swizzle_wyzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 2 }); goto negate; - swizzle_xzzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 2 }); goto negate; - swizzle_yzzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 2 }); goto negate; - swizzle_zzzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 2 }); goto negate; - swizzle_wzzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 2 }); goto negate; - swizzle_xwzz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 2 }); goto negate; - swizzle_ywzz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 2 }); goto negate; - swizzle_zwzz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 2 }); goto negate; - swizzle_wwzz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 2 }); goto negate; - swizzle_xxwz: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 2 }); goto negate; - swizzle_yxwz: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 2 }); goto negate; - swizzle_zxwz: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 2 }); goto negate; - swizzle_wxwz: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 2 }); goto negate; - swizzle_xywz: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 2 }); goto negate; - swizzle_yywz: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 2 }); goto negate; - swizzle_zywz: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 2 }); goto negate; - swizzle_wywz: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 2 }); goto negate; - swizzle_xzwz: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 2 }); goto negate; - swizzle_yzwz: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 2 }); goto negate; - swizzle_zzwz: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 2 }); goto negate; - swizzle_wzwz: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 2 }); goto negate; - swizzle_xwwz: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 2 }); goto negate; - swizzle_ywwz: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 2 }); goto negate; - swizzle_zwwz: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 2 }); goto negate; - swizzle_wwwz: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 2 }); goto negate; - swizzle_xxxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 0, 3 }); goto negate; - swizzle_yxxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 0, 3 }); goto negate; - swizzle_zxxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 0, 3 }); goto negate; - swizzle_wxxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 0, 3 }); goto negate; - swizzle_xyxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 0, 3 }); goto negate; - swizzle_yyxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 0, 3 }); goto negate; - swizzle_zyxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 0, 3 }); goto negate; - swizzle_wyxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 0, 3 }); goto negate; - swizzle_xzxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 0, 3 }); goto negate; - swizzle_yzxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 0, 3 }); goto negate; - swizzle_zzxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 0, 3 }); goto negate; - swizzle_wzxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 0, 3 }); goto negate; - swizzle_xwxw: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 0, 3 }); goto negate; - swizzle_ywxw: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 0, 3 }); goto negate; - swizzle_zwxw: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 0, 3 }); goto negate; - swizzle_wwxw: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 0, 3 }); goto negate; - swizzle_xxyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 1, 3 }); goto negate; - swizzle_yxyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 1, 3 }); goto negate; - swizzle_zxyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 1, 3 }); goto negate; - swizzle_wxyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 1, 3 }); goto negate; - swizzle_xyyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 1, 3 }); goto negate; - swizzle_yyyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 1, 3 }); goto negate; - swizzle_zyyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 1, 3 }); goto negate; - swizzle_wyyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 1, 3 }); goto negate; - swizzle_xzyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 1, 3 }); goto negate; - swizzle_yzyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 1, 3 }); goto negate; - swizzle_zzyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 1, 3 }); goto negate; - swizzle_wzyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 1, 3 }); goto negate; - swizzle_xwyw: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 1, 3 }); goto negate; - swizzle_ywyw: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 1, 3 }); goto negate; - swizzle_zwyw: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 1, 3 }); goto negate; - swizzle_wwyw: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 1, 3 }); goto negate; - swizzle_xxzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 2, 3 }); goto negate; - swizzle_yxzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 2, 3 }); goto negate; - swizzle_zxzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 2, 3 }); goto negate; - swizzle_wxzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 2, 3 }); goto negate; - swizzle_xyzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 2, 3 }); goto negate; - swizzle_yyzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 2, 3 }); goto negate; - swizzle_zyzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 2, 3 }); goto negate; - swizzle_wyzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 2, 3 }); goto negate; - swizzle_xzzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 2, 3 }); goto negate; - swizzle_yzzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 2, 3 }); goto negate; - swizzle_zzzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 2, 3 }); goto negate; - swizzle_wzzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 2, 3 }); goto negate; - swizzle_xwzw: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 2, 3 }); goto negate; - swizzle_ywzw: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 2, 3 }); goto negate; - swizzle_zwzw: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 2, 3 }); goto negate; - swizzle_wwzw: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 2, 3 }); goto negate; - swizzle_xxww: vec = swizzle (vec, (pr_ivec4_t) { 0, 0, 3, 3 }); goto negate; - swizzle_yxww: vec = swizzle (vec, (pr_ivec4_t) { 1, 0, 3, 3 }); goto negate; - swizzle_zxww: vec = swizzle (vec, (pr_ivec4_t) { 2, 0, 3, 3 }); goto negate; - swizzle_wxww: vec = swizzle (vec, (pr_ivec4_t) { 3, 0, 3, 3 }); goto negate; - swizzle_xyww: vec = swizzle (vec, (pr_ivec4_t) { 0, 1, 3, 3 }); goto negate; - swizzle_yyww: vec = swizzle (vec, (pr_ivec4_t) { 1, 1, 3, 3 }); goto negate; - swizzle_zyww: vec = swizzle (vec, (pr_ivec4_t) { 2, 1, 3, 3 }); goto negate; - swizzle_wyww: vec = swizzle (vec, (pr_ivec4_t) { 3, 1, 3, 3 }); goto negate; - swizzle_xzww: vec = swizzle (vec, (pr_ivec4_t) { 0, 2, 3, 3 }); goto negate; - swizzle_yzww: vec = swizzle (vec, (pr_ivec4_t) { 1, 2, 3, 3 }); goto negate; - swizzle_zzww: vec = swizzle (vec, (pr_ivec4_t) { 2, 2, 3, 3 }); goto negate; - swizzle_wzww: vec = swizzle (vec, (pr_ivec4_t) { 3, 2, 3, 3 }); goto negate; - swizzle_xwww: vec = swizzle (vec, (pr_ivec4_t) { 0, 3, 3, 3 }); goto negate; - swizzle_ywww: vec = swizzle (vec, (pr_ivec4_t) { 1, 3, 3, 3 }); goto negate; - swizzle_zwww: vec = swizzle (vec, (pr_ivec4_t) { 2, 3, 3, 3 }); goto negate; - swizzle_wwww: vec = swizzle (vec, (pr_ivec4_t) { 3, 3, 3, 3 }); goto negate; - static void *swizzle_table[256] = { - &&swizzle_xxxx, &&swizzle_yxxx, &&swizzle_zxxx, &&swizzle_wxxx, - &&swizzle_xyxx, &&swizzle_yyxx, &&swizzle_zyxx, &&swizzle_wyxx, - &&swizzle_xzxx, &&swizzle_yzxx, &&swizzle_zzxx, &&swizzle_wzxx, - &&swizzle_xwxx, &&swizzle_ywxx, &&swizzle_zwxx, &&swizzle_wwxx, - &&swizzle_xxyx, &&swizzle_yxyx, &&swizzle_zxyx, &&swizzle_wxyx, - &&swizzle_xyyx, &&swizzle_yyyx, &&swizzle_zyyx, &&swizzle_wyyx, - &&swizzle_xzyx, &&swizzle_yzyx, &&swizzle_zzyx, &&swizzle_wzyx, - &&swizzle_xwyx, &&swizzle_ywyx, &&swizzle_zwyx, &&swizzle_wwyx, - &&swizzle_xxzx, &&swizzle_yxzx, &&swizzle_zxzx, &&swizzle_wxzx, - &&swizzle_xyzx, &&swizzle_yyzx, &&swizzle_zyzx, &&swizzle_wyzx, - &&swizzle_xzzx, &&swizzle_yzzx, &&swizzle_zzzx, &&swizzle_wzzx, - &&swizzle_xwzx, &&swizzle_ywzx, &&swizzle_zwzx, &&swizzle_wwzx, - &&swizzle_xxwx, &&swizzle_yxwx, &&swizzle_zxwx, &&swizzle_wxwx, - &&swizzle_xywx, &&swizzle_yywx, &&swizzle_zywx, &&swizzle_wywx, - &&swizzle_xzwx, &&swizzle_yzwx, &&swizzle_zzwx, &&swizzle_wzwx, - &&swizzle_xwwx, &&swizzle_ywwx, &&swizzle_zwwx, &&swizzle_wwwx, - &&swizzle_xxxy, &&swizzle_yxxy, &&swizzle_zxxy, &&swizzle_wxxy, - &&swizzle_xyxy, &&swizzle_yyxy, &&swizzle_zyxy, &&swizzle_wyxy, - &&swizzle_xzxy, &&swizzle_yzxy, &&swizzle_zzxy, &&swizzle_wzxy, - &&swizzle_xwxy, &&swizzle_ywxy, &&swizzle_zwxy, &&swizzle_wwxy, - &&swizzle_xxyy, &&swizzle_yxyy, &&swizzle_zxyy, &&swizzle_wxyy, - &&swizzle_xyyy, &&swizzle_yyyy, &&swizzle_zyyy, &&swizzle_wyyy, - &&swizzle_xzyy, &&swizzle_yzyy, &&swizzle_zzyy, &&swizzle_wzyy, - &&swizzle_xwyy, &&swizzle_ywyy, &&swizzle_zwyy, &&swizzle_wwyy, - &&swizzle_xxzy, &&swizzle_yxzy, &&swizzle_zxzy, &&swizzle_wxzy, - &&swizzle_xyzy, &&swizzle_yyzy, &&swizzle_zyzy, &&swizzle_wyzy, - &&swizzle_xzzy, &&swizzle_yzzy, &&swizzle_zzzy, &&swizzle_wzzy, - &&swizzle_xwzy, &&swizzle_ywzy, &&swizzle_zwzy, &&swizzle_wwzy, - &&swizzle_xxwy, &&swizzle_yxwy, &&swizzle_zxwy, &&swizzle_wxwy, - &&swizzle_xywy, &&swizzle_yywy, &&swizzle_zywy, &&swizzle_wywy, - &&swizzle_xzwy, &&swizzle_yzwy, &&swizzle_zzwy, &&swizzle_wzwy, - &&swizzle_xwwy, &&swizzle_ywwy, &&swizzle_zwwy, &&swizzle_wwwy, - &&swizzle_xxxz, &&swizzle_yxxz, &&swizzle_zxxz, &&swizzle_wxxz, - &&swizzle_xyxz, &&swizzle_yyxz, &&swizzle_zyxz, &&swizzle_wyxz, - &&swizzle_xzxz, &&swizzle_yzxz, &&swizzle_zzxz, &&swizzle_wzxz, - &&swizzle_xwxz, &&swizzle_ywxz, &&swizzle_zwxz, &&swizzle_wwxz, - &&swizzle_xxyz, &&swizzle_yxyz, &&swizzle_zxyz, &&swizzle_wxyz, - &&swizzle_xyyz, &&swizzle_yyyz, &&swizzle_zyyz, &&swizzle_wyyz, - &&swizzle_xzyz, &&swizzle_yzyz, &&swizzle_zzyz, &&swizzle_wzyz, - &&swizzle_xwyz, &&swizzle_ywyz, &&swizzle_zwyz, &&swizzle_wwyz, - &&swizzle_xxzz, &&swizzle_yxzz, &&swizzle_zxzz, &&swizzle_wxzz, - &&swizzle_xyzz, &&swizzle_yyzz, &&swizzle_zyzz, &&swizzle_wyzz, - &&swizzle_xzzz, &&swizzle_yzzz, &&swizzle_zzzz, &&swizzle_wzzz, - &&swizzle_xwzz, &&swizzle_ywzz, &&swizzle_zwzz, &&swizzle_wwzz, - &&swizzle_xxwz, &&swizzle_yxwz, &&swizzle_zxwz, &&swizzle_wxwz, - &&swizzle_xywz, &&swizzle_yywz, &&swizzle_zywz, &&swizzle_wywz, - &&swizzle_xzwz, &&swizzle_yzwz, &&swizzle_zzwz, &&swizzle_wzwz, - &&swizzle_xwwz, &&swizzle_ywwz, &&swizzle_zwwz, &&swizzle_wwwz, - &&swizzle_xxxw, &&swizzle_yxxw, &&swizzle_zxxw, &&swizzle_wxxw, - &&swizzle_xyxw, &&swizzle_yyxw, &&swizzle_zyxw, &&swizzle_wyxw, - &&swizzle_xzxw, &&swizzle_yzxw, &&swizzle_zzxw, &&swizzle_wzxw, - &&swizzle_xwxw, &&swizzle_ywxw, &&swizzle_zwxw, &&swizzle_wwxw, - &&swizzle_xxyw, &&swizzle_yxyw, &&swizzle_zxyw, &&swizzle_wxyw, - &&swizzle_xyyw, &&swizzle_yyyw, &&swizzle_zyyw, &&swizzle_wyyw, - &&swizzle_xzyw, &&swizzle_yzyw, &&swizzle_zzyw, &&swizzle_wzyw, - &&swizzle_xwyw, &&swizzle_ywyw, &&swizzle_zwyw, &&swizzle_wwyw, - &&swizzle_xxzw, &&swizzle_yxzw, &&swizzle_zxzw, &&swizzle_wxzw, - &&swizzle_xyzw, &&swizzle_yyzw, &&swizzle_zyzw, &&swizzle_wyzw, - &&swizzle_xzzw, &&swizzle_yzzw, &&swizzle_zzzw, &&swizzle_wzzw, - &&swizzle_xwzw, &&swizzle_ywzw, &&swizzle_zwzw, &&swizzle_wwzw, - &&swizzle_xxww, &&swizzle_yxww, &&swizzle_zxww, &&swizzle_wxww, - &&swizzle_xyww, &&swizzle_yyww, &&swizzle_zyww, &&swizzle_wyww, - &&swizzle_xzww, &&swizzle_yzww, &&swizzle_zzww, &&swizzle_wzww, - &&swizzle_xwww, &&swizzle_ywww, &&swizzle_zwww, &&swizzle_wwww, - }; -#undef swizzle +#include "libs/gamecode/pr_swizzle32.cinc" static const pr_ivec4_t neg[16] = { { 0, 0, 0, 0 }, { 1<<31, 0, 0, 0 }, @@ -2379,330 +2056,7 @@ __attribute__((sysv_abi)) pr_swizzle_d (pr_lvec4_t vec, pr_ushort_t swiz) { goto do_swizzle; -#define swizzle __builtin_shuffle - swizzle_xxxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 0 }); goto negate; - swizzle_yxxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 0 }); goto negate; - swizzle_zxxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 0 }); goto negate; - swizzle_wxxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 0 }); goto negate; - swizzle_xyxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 0 }); goto negate; - swizzle_yyxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 0 }); goto negate; - swizzle_zyxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 0 }); goto negate; - swizzle_wyxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 0 }); goto negate; - swizzle_xzxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 0 }); goto negate; - swizzle_yzxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 0 }); goto negate; - swizzle_zzxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 0 }); goto negate; - swizzle_wzxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 0 }); goto negate; - swizzle_xwxx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 0 }); goto negate; - swizzle_ywxx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 0 }); goto negate; - swizzle_zwxx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 0 }); goto negate; - swizzle_wwxx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 0 }); goto negate; - swizzle_xxyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 0 }); goto negate; - swizzle_yxyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 0 }); goto negate; - swizzle_zxyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 0 }); goto negate; - swizzle_wxyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 0 }); goto negate; - swizzle_xyyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 0 }); goto negate; - swizzle_yyyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 0 }); goto negate; - swizzle_zyyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 0 }); goto negate; - swizzle_wyyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 0 }); goto negate; - swizzle_xzyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 0 }); goto negate; - swizzle_yzyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 0 }); goto negate; - swizzle_zzyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 0 }); goto negate; - swizzle_wzyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 0 }); goto negate; - swizzle_xwyx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 0 }); goto negate; - swizzle_ywyx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 0 }); goto negate; - swizzle_zwyx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 0 }); goto negate; - swizzle_wwyx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 0 }); goto negate; - swizzle_xxzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 0 }); goto negate; - swizzle_yxzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 0 }); goto negate; - swizzle_zxzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 0 }); goto negate; - swizzle_wxzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 0 }); goto negate; - swizzle_xyzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 0 }); goto negate; - swizzle_yyzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 0 }); goto negate; - swizzle_zyzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 0 }); goto negate; - swizzle_wyzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 0 }); goto negate; - swizzle_xzzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 0 }); goto negate; - swizzle_yzzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 0 }); goto negate; - swizzle_zzzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 0 }); goto negate; - swizzle_wzzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 0 }); goto negate; - swizzle_xwzx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 0 }); goto negate; - swizzle_ywzx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 0 }); goto negate; - swizzle_zwzx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 0 }); goto negate; - swizzle_wwzx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 0 }); goto negate; - swizzle_xxwx: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 0 }); goto negate; - swizzle_yxwx: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 0 }); goto negate; - swizzle_zxwx: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 0 }); goto negate; - swizzle_wxwx: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 0 }); goto negate; - swizzle_xywx: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 0 }); goto negate; - swizzle_yywx: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 0 }); goto negate; - swizzle_zywx: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 0 }); goto negate; - swizzle_wywx: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 0 }); goto negate; - swizzle_xzwx: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 0 }); goto negate; - swizzle_yzwx: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 0 }); goto negate; - swizzle_zzwx: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 0 }); goto negate; - swizzle_wzwx: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 0 }); goto negate; - swizzle_xwwx: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 0 }); goto negate; - swizzle_ywwx: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 0 }); goto negate; - swizzle_zwwx: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 0 }); goto negate; - swizzle_wwwx: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 0 }); goto negate; - swizzle_xxxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 1 }); goto negate; - swizzle_yxxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 1 }); goto negate; - swizzle_zxxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 1 }); goto negate; - swizzle_wxxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 1 }); goto negate; - swizzle_xyxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 1 }); goto negate; - swizzle_yyxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 1 }); goto negate; - swizzle_zyxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 1 }); goto negate; - swizzle_wyxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 1 }); goto negate; - swizzle_xzxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 1 }); goto negate; - swizzle_yzxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 1 }); goto negate; - swizzle_zzxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 1 }); goto negate; - swizzle_wzxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 1 }); goto negate; - swizzle_xwxy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 1 }); goto negate; - swizzle_ywxy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 1 }); goto negate; - swizzle_zwxy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 1 }); goto negate; - swizzle_wwxy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 1 }); goto negate; - swizzle_xxyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 1 }); goto negate; - swizzle_yxyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 1 }); goto negate; - swizzle_zxyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 1 }); goto negate; - swizzle_wxyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 1 }); goto negate; - swizzle_xyyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 1 }); goto negate; - swizzle_yyyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 1 }); goto negate; - swizzle_zyyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 1 }); goto negate; - swizzle_wyyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 1 }); goto negate; - swizzle_xzyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 1 }); goto negate; - swizzle_yzyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 1 }); goto negate; - swizzle_zzyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 1 }); goto negate; - swizzle_wzyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 1 }); goto negate; - swizzle_xwyy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 1 }); goto negate; - swizzle_ywyy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 1 }); goto negate; - swizzle_zwyy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 1 }); goto negate; - swizzle_wwyy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 1 }); goto negate; - swizzle_xxzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 1 }); goto negate; - swizzle_yxzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 1 }); goto negate; - swizzle_zxzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 1 }); goto negate; - swizzle_wxzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 1 }); goto negate; - swizzle_xyzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 1 }); goto negate; - swizzle_yyzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 1 }); goto negate; - swizzle_zyzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 1 }); goto negate; - swizzle_wyzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 1 }); goto negate; - swizzle_xzzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 1 }); goto negate; - swizzle_yzzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 1 }); goto negate; - swizzle_zzzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 1 }); goto negate; - swizzle_wzzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 1 }); goto negate; - swizzle_xwzy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 1 }); goto negate; - swizzle_ywzy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 1 }); goto negate; - swizzle_zwzy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 1 }); goto negate; - swizzle_wwzy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 1 }); goto negate; - swizzle_xxwy: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 1 }); goto negate; - swizzle_yxwy: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 1 }); goto negate; - swizzle_zxwy: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 1 }); goto negate; - swizzle_wxwy: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 1 }); goto negate; - swizzle_xywy: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 1 }); goto negate; - swizzle_yywy: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 1 }); goto negate; - swizzle_zywy: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 1 }); goto negate; - swizzle_wywy: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 1 }); goto negate; - swizzle_xzwy: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 1 }); goto negate; - swizzle_yzwy: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 1 }); goto negate; - swizzle_zzwy: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 1 }); goto negate; - swizzle_wzwy: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 1 }); goto negate; - swizzle_xwwy: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 1 }); goto negate; - swizzle_ywwy: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 1 }); goto negate; - swizzle_zwwy: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 1 }); goto negate; - swizzle_wwwy: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 1 }); goto negate; - swizzle_xxxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 2 }); goto negate; - swizzle_yxxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 2 }); goto negate; - swizzle_zxxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 2 }); goto negate; - swizzle_wxxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 2 }); goto negate; - swizzle_xyxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 2 }); goto negate; - swizzle_yyxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 2 }); goto negate; - swizzle_zyxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 2 }); goto negate; - swizzle_wyxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 2 }); goto negate; - swizzle_xzxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 2 }); goto negate; - swizzle_yzxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 2 }); goto negate; - swizzle_zzxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 2 }); goto negate; - swizzle_wzxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 2 }); goto negate; - swizzle_xwxz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 2 }); goto negate; - swizzle_ywxz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 2 }); goto negate; - swizzle_zwxz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 2 }); goto negate; - swizzle_wwxz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 2 }); goto negate; - swizzle_xxyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 2 }); goto negate; - swizzle_yxyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 2 }); goto negate; - swizzle_zxyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 2 }); goto negate; - swizzle_wxyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 2 }); goto negate; - swizzle_xyyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 2 }); goto negate; - swizzle_yyyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 2 }); goto negate; - swizzle_zyyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 2 }); goto negate; - swizzle_wyyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 2 }); goto negate; - swizzle_xzyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 2 }); goto negate; - swizzle_yzyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 2 }); goto negate; - swizzle_zzyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 2 }); goto negate; - swizzle_wzyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 2 }); goto negate; - swizzle_xwyz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 2 }); goto negate; - swizzle_ywyz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 2 }); goto negate; - swizzle_zwyz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 2 }); goto negate; - swizzle_wwyz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 2 }); goto negate; - swizzle_xxzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 2 }); goto negate; - swizzle_yxzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 2 }); goto negate; - swizzle_zxzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 2 }); goto negate; - swizzle_wxzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 2 }); goto negate; - swizzle_xyzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 2 }); goto negate; - swizzle_yyzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 2 }); goto negate; - swizzle_zyzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 2 }); goto negate; - swizzle_wyzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 2 }); goto negate; - swizzle_xzzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 2 }); goto negate; - swizzle_yzzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 2 }); goto negate; - swizzle_zzzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 2 }); goto negate; - swizzle_wzzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 2 }); goto negate; - swizzle_xwzz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 2 }); goto negate; - swizzle_ywzz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 2 }); goto negate; - swizzle_zwzz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 2 }); goto negate; - swizzle_wwzz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 2 }); goto negate; - swizzle_xxwz: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 2 }); goto negate; - swizzle_yxwz: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 2 }); goto negate; - swizzle_zxwz: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 2 }); goto negate; - swizzle_wxwz: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 2 }); goto negate; - swizzle_xywz: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 2 }); goto negate; - swizzle_yywz: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 2 }); goto negate; - swizzle_zywz: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 2 }); goto negate; - swizzle_wywz: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 2 }); goto negate; - swizzle_xzwz: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 2 }); goto negate; - swizzle_yzwz: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 2 }); goto negate; - swizzle_zzwz: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 2 }); goto negate; - swizzle_wzwz: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 2 }); goto negate; - swizzle_xwwz: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 2 }); goto negate; - swizzle_ywwz: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 2 }); goto negate; - swizzle_zwwz: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 2 }); goto negate; - swizzle_wwwz: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 2 }); goto negate; - swizzle_xxxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 0, 3 }); goto negate; - swizzle_yxxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 0, 3 }); goto negate; - swizzle_zxxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 0, 3 }); goto negate; - swizzle_wxxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 0, 3 }); goto negate; - swizzle_xyxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 0, 3 }); goto negate; - swizzle_yyxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 0, 3 }); goto negate; - swizzle_zyxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 0, 3 }); goto negate; - swizzle_wyxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 0, 3 }); goto negate; - swizzle_xzxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 0, 3 }); goto negate; - swizzle_yzxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 0, 3 }); goto negate; - swizzle_zzxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 0, 3 }); goto negate; - swizzle_wzxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 0, 3 }); goto negate; - swizzle_xwxw: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 0, 3 }); goto negate; - swizzle_ywxw: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 0, 3 }); goto negate; - swizzle_zwxw: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 0, 3 }); goto negate; - swizzle_wwxw: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 0, 3 }); goto negate; - swizzle_xxyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 1, 3 }); goto negate; - swizzle_yxyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 1, 3 }); goto negate; - swizzle_zxyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 1, 3 }); goto negate; - swizzle_wxyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 1, 3 }); goto negate; - swizzle_xyyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 1, 3 }); goto negate; - swizzle_yyyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 1, 3 }); goto negate; - swizzle_zyyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 1, 3 }); goto negate; - swizzle_wyyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 1, 3 }); goto negate; - swizzle_xzyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 1, 3 }); goto negate; - swizzle_yzyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 1, 3 }); goto negate; - swizzle_zzyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 1, 3 }); goto negate; - swizzle_wzyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 1, 3 }); goto negate; - swizzle_xwyw: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 1, 3 }); goto negate; - swizzle_ywyw: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 1, 3 }); goto negate; - swizzle_zwyw: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 1, 3 }); goto negate; - swizzle_wwyw: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 1, 3 }); goto negate; - swizzle_xxzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 2, 3 }); goto negate; - swizzle_yxzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 2, 3 }); goto negate; - swizzle_zxzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 2, 3 }); goto negate; - swizzle_wxzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 2, 3 }); goto negate; - swizzle_xyzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 2, 3 }); goto negate; - swizzle_yyzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 2, 3 }); goto negate; - swizzle_zyzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 2, 3 }); goto negate; - swizzle_wyzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 2, 3 }); goto negate; - swizzle_xzzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 2, 3 }); goto negate; - swizzle_yzzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 2, 3 }); goto negate; - swizzle_zzzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 2, 3 }); goto negate; - swizzle_wzzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 2, 3 }); goto negate; - swizzle_xwzw: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 2, 3 }); goto negate; - swizzle_ywzw: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 2, 3 }); goto negate; - swizzle_zwzw: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 2, 3 }); goto negate; - swizzle_wwzw: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 2, 3 }); goto negate; - swizzle_xxww: vec = swizzle (vec, (pr_lvec4_t) { 0, 0, 3, 3 }); goto negate; - swizzle_yxww: vec = swizzle (vec, (pr_lvec4_t) { 1, 0, 3, 3 }); goto negate; - swizzle_zxww: vec = swizzle (vec, (pr_lvec4_t) { 2, 0, 3, 3 }); goto negate; - swizzle_wxww: vec = swizzle (vec, (pr_lvec4_t) { 3, 0, 3, 3 }); goto negate; - swizzle_xyww: vec = swizzle (vec, (pr_lvec4_t) { 0, 1, 3, 3 }); goto negate; - swizzle_yyww: vec = swizzle (vec, (pr_lvec4_t) { 1, 1, 3, 3 }); goto negate; - swizzle_zyww: vec = swizzle (vec, (pr_lvec4_t) { 2, 1, 3, 3 }); goto negate; - swizzle_wyww: vec = swizzle (vec, (pr_lvec4_t) { 3, 1, 3, 3 }); goto negate; - swizzle_xzww: vec = swizzle (vec, (pr_lvec4_t) { 0, 2, 3, 3 }); goto negate; - swizzle_yzww: vec = swizzle (vec, (pr_lvec4_t) { 1, 2, 3, 3 }); goto negate; - swizzle_zzww: vec = swizzle (vec, (pr_lvec4_t) { 2, 2, 3, 3 }); goto negate; - swizzle_wzww: vec = swizzle (vec, (pr_lvec4_t) { 3, 2, 3, 3 }); goto negate; - swizzle_xwww: vec = swizzle (vec, (pr_lvec4_t) { 0, 3, 3, 3 }); goto negate; - swizzle_ywww: vec = swizzle (vec, (pr_lvec4_t) { 1, 3, 3, 3 }); goto negate; - swizzle_zwww: vec = swizzle (vec, (pr_lvec4_t) { 2, 3, 3, 3 }); goto negate; - swizzle_wwww: vec = swizzle (vec, (pr_lvec4_t) { 3, 3, 3, 3 }); goto negate; - static void *swizzle_table[256] = { - &&swizzle_xxxx, &&swizzle_yxxx, &&swizzle_zxxx, &&swizzle_wxxx, - &&swizzle_xyxx, &&swizzle_yyxx, &&swizzle_zyxx, &&swizzle_wyxx, - &&swizzle_xzxx, &&swizzle_yzxx, &&swizzle_zzxx, &&swizzle_wzxx, - &&swizzle_xwxx, &&swizzle_ywxx, &&swizzle_zwxx, &&swizzle_wwxx, - &&swizzle_xxyx, &&swizzle_yxyx, &&swizzle_zxyx, &&swizzle_wxyx, - &&swizzle_xyyx, &&swizzle_yyyx, &&swizzle_zyyx, &&swizzle_wyyx, - &&swizzle_xzyx, &&swizzle_yzyx, &&swizzle_zzyx, &&swizzle_wzyx, - &&swizzle_xwyx, &&swizzle_ywyx, &&swizzle_zwyx, &&swizzle_wwyx, - &&swizzle_xxzx, &&swizzle_yxzx, &&swizzle_zxzx, &&swizzle_wxzx, - &&swizzle_xyzx, &&swizzle_yyzx, &&swizzle_zyzx, &&swizzle_wyzx, - &&swizzle_xzzx, &&swizzle_yzzx, &&swizzle_zzzx, &&swizzle_wzzx, - &&swizzle_xwzx, &&swizzle_ywzx, &&swizzle_zwzx, &&swizzle_wwzx, - &&swizzle_xxwx, &&swizzle_yxwx, &&swizzle_zxwx, &&swizzle_wxwx, - &&swizzle_xywx, &&swizzle_yywx, &&swizzle_zywx, &&swizzle_wywx, - &&swizzle_xzwx, &&swizzle_yzwx, &&swizzle_zzwx, &&swizzle_wzwx, - &&swizzle_xwwx, &&swizzle_ywwx, &&swizzle_zwwx, &&swizzle_wwwx, - &&swizzle_xxxy, &&swizzle_yxxy, &&swizzle_zxxy, &&swizzle_wxxy, - &&swizzle_xyxy, &&swizzle_yyxy, &&swizzle_zyxy, &&swizzle_wyxy, - &&swizzle_xzxy, &&swizzle_yzxy, &&swizzle_zzxy, &&swizzle_wzxy, - &&swizzle_xwxy, &&swizzle_ywxy, &&swizzle_zwxy, &&swizzle_wwxy, - &&swizzle_xxyy, &&swizzle_yxyy, &&swizzle_zxyy, &&swizzle_wxyy, - &&swizzle_xyyy, &&swizzle_yyyy, &&swizzle_zyyy, &&swizzle_wyyy, - &&swizzle_xzyy, &&swizzle_yzyy, &&swizzle_zzyy, &&swizzle_wzyy, - &&swizzle_xwyy, &&swizzle_ywyy, &&swizzle_zwyy, &&swizzle_wwyy, - &&swizzle_xxzy, &&swizzle_yxzy, &&swizzle_zxzy, &&swizzle_wxzy, - &&swizzle_xyzy, &&swizzle_yyzy, &&swizzle_zyzy, &&swizzle_wyzy, - &&swizzle_xzzy, &&swizzle_yzzy, &&swizzle_zzzy, &&swizzle_wzzy, - &&swizzle_xwzy, &&swizzle_ywzy, &&swizzle_zwzy, &&swizzle_wwzy, - &&swizzle_xxwy, &&swizzle_yxwy, &&swizzle_zxwy, &&swizzle_wxwy, - &&swizzle_xywy, &&swizzle_yywy, &&swizzle_zywy, &&swizzle_wywy, - &&swizzle_xzwy, &&swizzle_yzwy, &&swizzle_zzwy, &&swizzle_wzwy, - &&swizzle_xwwy, &&swizzle_ywwy, &&swizzle_zwwy, &&swizzle_wwwy, - &&swizzle_xxxz, &&swizzle_yxxz, &&swizzle_zxxz, &&swizzle_wxxz, - &&swizzle_xyxz, &&swizzle_yyxz, &&swizzle_zyxz, &&swizzle_wyxz, - &&swizzle_xzxz, &&swizzle_yzxz, &&swizzle_zzxz, &&swizzle_wzxz, - &&swizzle_xwxz, &&swizzle_ywxz, &&swizzle_zwxz, &&swizzle_wwxz, - &&swizzle_xxyz, &&swizzle_yxyz, &&swizzle_zxyz, &&swizzle_wxyz, - &&swizzle_xyyz, &&swizzle_yyyz, &&swizzle_zyyz, &&swizzle_wyyz, - &&swizzle_xzyz, &&swizzle_yzyz, &&swizzle_zzyz, &&swizzle_wzyz, - &&swizzle_xwyz, &&swizzle_ywyz, &&swizzle_zwyz, &&swizzle_wwyz, - &&swizzle_xxzz, &&swizzle_yxzz, &&swizzle_zxzz, &&swizzle_wxzz, - &&swizzle_xyzz, &&swizzle_yyzz, &&swizzle_zyzz, &&swizzle_wyzz, - &&swizzle_xzzz, &&swizzle_yzzz, &&swizzle_zzzz, &&swizzle_wzzz, - &&swizzle_xwzz, &&swizzle_ywzz, &&swizzle_zwzz, &&swizzle_wwzz, - &&swizzle_xxwz, &&swizzle_yxwz, &&swizzle_zxwz, &&swizzle_wxwz, - &&swizzle_xywz, &&swizzle_yywz, &&swizzle_zywz, &&swizzle_wywz, - &&swizzle_xzwz, &&swizzle_yzwz, &&swizzle_zzwz, &&swizzle_wzwz, - &&swizzle_xwwz, &&swizzle_ywwz, &&swizzle_zwwz, &&swizzle_wwwz, - &&swizzle_xxxw, &&swizzle_yxxw, &&swizzle_zxxw, &&swizzle_wxxw, - &&swizzle_xyxw, &&swizzle_yyxw, &&swizzle_zyxw, &&swizzle_wyxw, - &&swizzle_xzxw, &&swizzle_yzxw, &&swizzle_zzxw, &&swizzle_wzxw, - &&swizzle_xwxw, &&swizzle_ywxw, &&swizzle_zwxw, &&swizzle_wwxw, - &&swizzle_xxyw, &&swizzle_yxyw, &&swizzle_zxyw, &&swizzle_wxyw, - &&swizzle_xyyw, &&swizzle_yyyw, &&swizzle_zyyw, &&swizzle_wyyw, - &&swizzle_xzyw, &&swizzle_yzyw, &&swizzle_zzyw, &&swizzle_wzyw, - &&swizzle_xwyw, &&swizzle_ywyw, &&swizzle_zwyw, &&swizzle_wwyw, - &&swizzle_xxzw, &&swizzle_yxzw, &&swizzle_zxzw, &&swizzle_wxzw, - &&swizzle_xyzw, &&swizzle_yyzw, &&swizzle_zyzw, &&swizzle_wyzw, - &&swizzle_xzzw, &&swizzle_yzzw, &&swizzle_zzzw, &&swizzle_wzzw, - &&swizzle_xwzw, &&swizzle_ywzw, &&swizzle_zwzw, &&swizzle_wwzw, - &&swizzle_xxww, &&swizzle_yxww, &&swizzle_zxww, &&swizzle_wxww, - &&swizzle_xyww, &&swizzle_yyww, &&swizzle_zyww, &&swizzle_wyww, - &&swizzle_xzww, &&swizzle_yzww, &&swizzle_zzww, &&swizzle_wzww, - &&swizzle_xwww, &&swizzle_ywww, &&swizzle_zwww, &&swizzle_wwww, - }; -#undef swizzle +#include "libs/gamecode/pr_swizzle64.cinc" #define L(x) UINT64_C(x) static const pr_lvec4_t neg[16] = { { INT64_C(0), INT64_C(0), INT64_C(0), INT64_C(0) }, diff --git a/libs/gamecode/swizzle.py b/libs/gamecode/swizzle.py index f61d50de5..59640ea66 100644 --- a/libs/gamecode/swizzle.py +++ b/libs/gamecode/swizzle.py @@ -19,7 +19,7 @@ def print_ref(i, j, k, l): print(f"\t\t&&{label(i, j, k, l)},") def print_op(i, j, k, l): - print(f"\t{label(i, j, k, l)}: vec = swizzle (vec, (pr_ivec4_t) {{ {l}, {k}, {j}, {i} }}); goto negate;") + print(f"\t{label(i, j, k, l)}: vec = ({optype}) {{ vec[{l}], vec[{k}], vec[{j}], vec[{i}] }}; goto negate;") def print_data(i, j, k, l): print(f"\t{{ {l+1:2}, {k+1:2}, {j+1:2}, {i+1:2} }},") @@ -78,6 +78,10 @@ types = ["f", "d"] tests = ["swizzle", "neg", "zero"] if sys.argv[1] == "case": + if sys.argv[2] == "int": + optype = "pr_ivec4_t" + elif sys.argv[2] == "long": + optype = "pr_lvec4_t" iter(print_op) print("\tstatic void *swizzle_table[256] = {") iter(print_ref) From 5b3cd93fa31f5d5ca5258f99518f109249499be7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 02:38:26 +0900 Subject: [PATCH 2608/3664] [gamecode] Implement with more portably clang doesn't support taking the address of a vector component. I was just being lazy when I used a pointer when setting the base register. --- libs/gamecode/pr_exec.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 194237768..a07aab80e 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1938,41 +1938,40 @@ pr_with (progs_t *pr, const dstatement_t *st) pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; pr_type_t *op_b = pr->pr_globals + PR_BASE (pr, st, B) + st->b; pr_type_t *stk; - pr_uint_t *base = &pr->pr_bases[st->c & 3]; switch (st->a) { // fixed offset case 0: // hard-0 base - *base = st->b; + pr->pr_bases[st->c & 3] = st->b; return; case 1: // relative to current base (-ve offset) - *base = PR_BASE (pr, st, B) + (pr_short_t) st->b; + pr->pr_bases[st->c & 3] = PR_BASE (pr, st, B) + (pr_short_t) st->b; return; case 2: // relative to stack (-ve offset) - *base = *pr->globals.stack + (pr_short_t) st->b; + pr->pr_bases[st->c & 3] = *pr->globals.stack + (pr_short_t) st->b; return; case 3: // relative to edict_area (only +ve) - *base = edict_area + st->b; + pr->pr_bases[st->c & 3] = edict_area + st->b; return; case 4: // hard-0 base - *base = pr->pr_globals[st->b].pointer_var; + pr->pr_bases[st->c & 3] = pr->pr_globals[st->b].pointer_var; return; case 5: - *base = OPB(ptr); + pr->pr_bases[st->c & 3] = OPB(ptr); return; case 6: // relative to stack (-ve offset) - *base = *pr->globals.stack + OPB(int); + pr->pr_bases[st->c & 3] = *pr->globals.stack + OPB(int); return; case 7: // relative to edict_area (only +ve) - *base = edict_area + OPB(field); + pr->pr_bases[st->c & 3] = edict_area + OPB(field); return; case 8: @@ -1991,7 +1990,7 @@ pr_with (progs_t *pr, const dstatement_t *st) return; case 11: // return pointer - *base = pr->pr_return - pr->pr_globals; + pr->pr_bases[st->c & 3] = pr->pr_return - pr->pr_globals; return; } PR_RunError (pr, "Invalid with index: %u", st->a); From 2f9df0f05b6723a44d0863943d83f37ada46c4f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 02:44:58 +0900 Subject: [PATCH 2609/3664] Work around some clang parsing issues clang has no problem with labels crossing declarations, but it can't cope with a declaration (or end of block) just after a label. --- libs/gamecode/pr_exec.c | 5 +++++ libs/gamecode/test/main.c | 1 + libs/video/renderer/r_efrag.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index a07aab80e..0138ef7c3 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1797,6 +1797,7 @@ op_call: } } exit_program: + (void)0;//FIXME for clang } #define MM(type) (*((pr_##type##_t *) (mm))) @@ -1816,6 +1817,7 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 1: // entity.field (equivalent to OP_LOAD_t_v6p) + (void)0;//FIXME for clang pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; mm_offs = edict_area + OPA(entity) + OPB(field); break; @@ -1853,6 +1855,7 @@ pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 4: // entity.field (equivalent to OP_LOAD_t_v6p) + (void)0;//FIXME for clang pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; mm_offs = edict_area + OPA(entity) + OPB(field); break; @@ -2547,6 +2550,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; OP_cmp_T (LT, U, long, lvec2, lvec4, <, ulong, ulvec2, ulvec4); case OP_RETURN: + (void)0;//FIXME for clang int ret_size = (st->c & 0x1f) + 1; // up to 32 words if (st->c != 0xffff) { mm = pr_address_mode (pr, st, st->c >> 5); @@ -2872,6 +2876,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) } } exit_program: + (void)0;//FIXME for clang } /* PR_ExecuteProgram diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index bb0efb2fd..b2fdd45c8 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -42,6 +42,7 @@ test_debug_handler (prdebug_t event, void *param, void *data) case prd_subexit: break; case prd_trace: + (void)0;//FIXME for clang dstatement_t *st = test_pr.pr_statements + test_pr.pr_xstatement; if (verbose > 1) { printf ("---\n"); diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 4a60ed6d1..a1d4e6ea3 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -237,8 +237,8 @@ R_StoreEfrags (const efrag_t *efrag) case mod_iqm: EntQueue_AddEntity (r_ent_queue, ent, model->type); break; - default: + (void)0;//FIXME for clang } efrag = efrag->leafnext; } From cdcf1a71ea725b1043ffffe67a842b4916e52fc5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 02:48:01 +0900 Subject: [PATCH 2610/3664] [gamecode] use correct void for global_string It seems gcc is a little fast and loose with 0 as a null vector. --- libs/gamecode/pr_debug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 3df6ba2a8..61016e371 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1641,7 +1641,8 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) break; case 'V': opval += pr->pr_bases[opreg]; - str = global_string (&data, opval, ev_void, + optype = &res->void_type; + str = global_string (&data, opval, optype, contents & 1); break; case 'G': From f601606ad7fb72448e16935fc33e291525760e85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 02:50:03 +0900 Subject: [PATCH 2611/3664] [gamecode] Fix an enum cast warning Harmless, but it doesn't hurt to make it explicit. --- libs/gamecode/pr_v6p_opcode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index bc3848de1..dd609ad12 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -1622,7 +1622,7 @@ PR_Check_v6p_Opcodes (progs_t *pr) if (0 && !pr_boundscheck->int_val) { for (i = 0, st = pr->pr_statements; i < pr->progs->statements.count; st++, i++) { - pr_opcode_v6p_e st_op = st->op; + pr_opcode_v6p_e st_op = (pr_opcode_v6p_e) st->op; op = PR_v6p_Opcode (st_op); if (!op) { PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " @@ -1643,7 +1643,7 @@ PR_Check_v6p_Opcodes (progs_t *pr) } else { for (i = 0, st = pr->pr_statements; i < pr->progs->statements.count; st++, i++) { - pr_opcode_v6p_e st_op = st->op; + pr_opcode_v6p_e st_op = (pr_opcode_v6p_e) st->op; op = PR_v6p_Opcode (st_op); if (!op) { PR_Error (pr, "PR_Check_Opcodes: unknown opcode %d at " From d109571994c7122321c0c381b9df32690eaec80b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 02:51:05 +0900 Subject: [PATCH 2612/3664] [gamecode] Use 64 byte alignment for most of progs memory Only edicts themselves get a smaller alignment (4, 8 or 32 bytes, depending on hardware and progs version). I didn't want to waste too much memory on edict alignment for progs that don't need any better than void *, but the zone really wants 64 bytes, and the stack might as well have 64 bytes as well. Fixes a segfault when running v6 progs in a clang build (clang got really agressive with simd in zone.c). --- libs/gamecode/pr_load.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index c2c3c31d1..492d65bd7 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -124,7 +124,7 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) ddef_t *global_ddefs; ddef_t *field_ddefs; // absolute minimum alignment is 4 bytes - int alignment = sizeof (void *); + int edict_alignment = __alignof__(pr_lvec4_t); if (!pr->file_error) pr->file_error = file_error; @@ -175,8 +175,10 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) // ensure SIMD types can be aligned (qfcc will align them within // the progs memory map, so the engine needs to ensure the progs memory // is aligned) - alignment = __alignof__(pr_lvec4_t); + edict_alignment = __alignof__(pr_lvec4_t); } + // edict size is in words + edict_alignment /= 4; // Some compilers (eg, FTE) put extra data between the header and the // strings section. What's worse, they de-align the data. @@ -187,15 +189,15 @@ PR_LoadProgsFile (progs_t *pr, QFile *file, int size) pr->progs_size = size + offset_tweak; Sys_MaskPrintf (SYS_dev, "Programs occupy %iK.\n", size / 1024); - pr->progs_size = align_size (pr->progs_size, alignment); - pr->zone_size = align_size (pr->zone_size, alignment); - pr->stack_size = align_size (pr->stack_size, alignment); + pr->progs_size = align_size (pr->progs_size, 64); + pr->zone_size = align_size (pr->zone_size, 64); + pr->stack_size = align_size (pr->stack_size, 64); // size of edict asked for by progs, but at least 1 pr->pr_edict_size = max (1, progs.entityfields); - // edict size is in words - pr->pr_edict_size = align_size (pr->pr_edict_size, alignment / 4); + pr->pr_edict_size = align_size (pr->pr_edict_size, edict_alignment); pr->pr_edict_area_size = pr->max_edicts * pr->pr_edict_size; + pr->pr_edict_area_size = align_size (pr->pr_edict_area_size, 64); mem_size = pr->pr_edict_area_size * sizeof (pr_type_t); mem_size += pr->progs_size + pr->zone_size + pr->stack_size; From 8f6ee4f5ac46dd2ffe72e287fbc5b78cf28396a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 02:56:14 +0900 Subject: [PATCH 2613/3664] [gl] Work aground clang not liking variable structs with followers Really, it's an ugly hack made uglier, but I don't feel like dealing with it right now. --- libs/video/renderer/gl/gl_draw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 624d685ac..e20718da5 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -95,8 +95,10 @@ typedef struct { typedef struct cachepic_s { char name[MAX_QPATH]; qboolean dirty; - qpic_t pic; - byte padding[32]; // for appended glpic + union { + qpic_t pic; + byte padding[sizeof (qpic_t) + 32];// for appended glpic FIXME + }; } cachepic_t; #define MAX_CACHED_PICS 128 From dad17162bb16aa951456207f88707d708df41f79 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 02:57:38 +0900 Subject: [PATCH 2614/3664] [console] Rewrite the download progress indicator It was a nasty mess of suspicious strncats and the like. --- libs/console/client.c | 59 ++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/libs/console/client.c b/libs/console/client.c index 0ae47ae0b..02f7d2f62 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -503,46 +503,47 @@ draw_input (view_t *view) static void draw_download (view_t *view) { - char dlbar[1024]; + static dstring_t *dlbar; const char *text; - size_t i, j, x, y, n; if (!con_data.dl_name || !*con_data.dl_name->str) return; + if (!dlbar) { + dlbar = dstring_new (); + } + text = QFS_SkipPath(con_data.dl_name->str); - x = con_linewidth - ((con_linewidth * 7) / 40); - y = x - strlen (text) - 8; - i = con_linewidth / 3; - if (strlen (text) > i) { - y = x - i - 11; - strncpy (dlbar, text, i); - dlbar[i] = 0; - strncat (dlbar, "...", sizeof (dlbar) - strlen (dlbar)); - } else - strncpy (dlbar, text, sizeof (dlbar)); - strncat (dlbar, ": ", sizeof (dlbar) - strlen (dlbar)); - i = strlen (dlbar); - dlbar[i++] = '\x80'; + int line_size = con_linewidth - ((con_linewidth * 7) / 40); + int dot_space = line_size - strlen (text) - 8; + const char *ellipsis = ""; + int txt_size = con_linewidth / 3; + if (strlen (text) > (size_t) txt_size) { + ellipsis = "..."; + dot_space = line_size - txt_size - 11; + } else { + txt_size = strlen (text); + } // where's the dot go? - if (con_data.dl_percent == 0) - n = 0; - else - n = y * *con_data.dl_percent / 100; - for (j = 0; j < y; j++) - if (j == n) - dlbar[i++] = '\x83'; - else - dlbar[i++] = '\x81'; - dlbar[i++] = '\x82'; - dlbar[i] = 0; + int n = 0; + if (con_data.dl_percent) { + n = dot_space * *con_data.dl_percent / 100; + } + char *dots = alloca (dot_space + 1); + dots[dot_space] = 0; + for (int j = 0; j < dot_space; j++) { + if (j == n) { + dots[j++] = '\x83'; + } else { + dots[j++] = '\x81'; + } + } - snprintf (dlbar + strlen (dlbar), sizeof (dlbar) - strlen (dlbar), - " %02d%%", *con_data.dl_percent); + dsprintf (dlbar, "%.*s%s: \x80%s\x82 %02d%%", txt_size, text, ellipsis, dots, *con_data.dl_percent); // draw it - r_funcs->Draw_String (view->xabs, view->yabs, dlbar); + r_funcs->Draw_String (view->xabs, view->yabs, dlbar->str); } static void From d3afb0da504352949c5a1f25a739e700e9a8557a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 02:59:37 +0900 Subject: [PATCH 2615/3664] [vulkan] Remove a dead function I guess gcc missed it because it's inline. --- libs/video/renderer/vulkan/vulkan_bsp.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 1097222a6..a29ba4742 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1436,17 +1436,6 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) free (bctx->default_skybox); } -static inline __attribute__((const)) int -is_pow2 (unsigned x) -{ - int count; - - for (count = 0; x; x >>= 1) - if (x & 1) - count++; - return count == 1; -} - void Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) { From 2abd4a5e791c2864f5273194d84cf70b517b9ab9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 03:00:24 +0900 Subject: [PATCH 2616/3664] [qw] Clean up some int-char warnings More harmlessness, but no harm telling the compiler to sit in the corner. --- qw/source/teamplay.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index 731ac279a..a2ced2126 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -199,17 +199,17 @@ Team_ParseSay (dstring_t *buf, const char *s) bracket = 0; if (cl.stats[STAT_ITEMS] & IT_ARMOR3) - t3[0] = 'R' | 0x80; + t3[0] = (char) ('R' | 0x80); else if (cl.stats[STAT_ITEMS] & IT_ARMOR2) - t3[0] = 'Y' | 0x80; + t3[0] = (char) ('Y' | 0x80); else if (cl.stats[STAT_ITEMS] & IT_ARMOR1) - t3[0] = 'G' | 0x80; + t3[0] = (char) ('G' | 0x80); else { - t2[0] = 'N' | 0x80; - t2[1] = 'O' | 0x80; - t2[2] = 'N' | 0x80; - t2[3] = 'E' | 0x80; - t2[4] = '!' | 0x80; + t2[0] = (char) ('N' | 0x80); + t2[1] = (char) ('O' | 0x80); + t2[2] = (char) ('N' | 0x80); + t2[3] = (char) ('E' | 0x80); + t2[4] = (char) ('!' | 0x80); } snprintf (t2, sizeof (t2), "%sa:%i", t3, @@ -221,17 +221,17 @@ Team_ParseSay (dstring_t *buf, const char *s) case 'A': bracket = 0; if (cl.stats[STAT_ITEMS] & IT_ARMOR3) - t2[0] = 'R' | 0x80; + t2[0] = (char) ('R' | 0x80); else if (cl.stats[STAT_ITEMS] & IT_ARMOR2) - t2[0] = 'Y' | 0x80; + t2[0] = (char) ('Y' | 0x80); else if (cl.stats[STAT_ITEMS] & IT_ARMOR1) - t2[0] = 'G' | 0x80; + t2[0] = (char) ('G' | 0x80); else { - t2[0] = 'N' | 0x80; - t2[1] = 'O' | 0x80; - t2[2] = 'N' | 0x80; - t2[3] = 'E' | 0x80; - t2[4] = '!' | 0x80; + t2[0] = (char) ('N' | 0x80); + t2[1] = (char) ('O' | 0x80); + t2[2] = (char) ('N' | 0x80); + t2[3] = (char) ('E' | 0x80); + t2[4] = (char) ('!' | 0x80); } break; case 'h': From aed5cdee8e3aaea1de43583e52c814d68cc1de76 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 03:02:55 +0900 Subject: [PATCH 2617/3664] [sbar] Disable some unused functions I don't know why draw_altstring is there at all, but draw_nstring being in nq is likely due to minimising the diffs between nq and qw. --- nq/source/sbar.c | 4 ++-- qw/source/sbar.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 7a564ed87..9e98ce717 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -300,7 +300,7 @@ draw_string (view_t *view, int x, int y, const char *str) { r_funcs->Draw_String (view->xabs + x, view->yabs + y, str); } - +#if 0 static inline void draw_altstring (view_t *view, int x, int y, const char *str) { @@ -312,7 +312,7 @@ draw_nstring (view_t *view, int x, int y, const char *str, int n) { r_funcs->Draw_nString (view->xabs + x, view->yabs + y, str, n); } - +#endif static inline void draw_fill (view_t *view, int x, int y, int w, int h, int col) { diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 84532d2ed..15863b80d 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -305,13 +305,13 @@ draw_string (view_t *view, int x, int y, const char *str) { r_funcs->Draw_String (view->xabs + x, view->yabs + y, str); } - +#if 0 static inline void draw_altstring (view_t *view, int x, int y, const char *str) { r_funcs->Draw_AltString (view->xabs + x, view->yabs + y, str); } - +#endif static inline void draw_nstring (view_t *view, int x, int y, const char *str, int n) { From 020ada9fb1e4f5e544c9748122e071a241188950 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 14:44:51 +0900 Subject: [PATCH 2618/3664] [util] Clean up nested macro temp var names a little clang doesn't like the same variable name being used in nested expression statements, so give the "safety" variables in reused macros semi-meaningful (based on macro name) tails to keep them separate. --- include/QF/darray.h | 40 ++++++++++++++++++++-------------------- include/QF/pqueue.h | 4 ++-- include/QF/ringbuffer.h | 6 +++--- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/QF/darray.h b/include/QF/darray.h index 57111e772..8126be871 100644 --- a/include/QF/darray.h +++ b/include/QF/darray.h @@ -179,21 +179,21 @@ */ #define DARRAY_RESIZE(array, newSize) \ do { \ - __auto_type ar = (array); \ + __auto_type ar_r = (array); \ size_t ns = (newSize); \ - if (__builtin_expect (ns > ar->maxSize, 0)) { \ - if (__builtin_expect (!ar->grow, 0)) { \ + if (__builtin_expect (ns > ar_r->maxSize, 0)) { \ + if (__builtin_expect (!ar_r->grow, 0)) { \ Sys_Error ("Attempt to grow fixed-size darray: %s:%d", \ __FILE__, __LINE__); \ } \ - ar->maxSize = ar->grow * ((ns + ar->grow - 1) / ar->grow); \ - ar->a = realloc (ar->a, ar->maxSize * sizeof (*ar->a)); \ - if (__builtin_expect (!ar->a, 0)) { \ + ar_r->maxSize = ar_r->grow * ((ns + ar_r->grow - 1) / ar_r->grow);\ + ar_r->a = realloc (ar_r->a, ar_r->maxSize * sizeof (*ar_r->a)); \ + if (__builtin_expect (!ar_r->a, 0)) { \ Sys_Error ("failed to realloc darray: %s:%d", \ __FILE__, __LINE__); \ } \ } \ - ar->size = ns; \ + ar_r->size = ns; \ } while (0) /** Append a value to the end of the array. @@ -250,17 +250,17 @@ */ #define DARRAY_OPEN_AT(array, index, space) \ ({ \ - __auto_type ar = (array); \ + __auto_type ar_o = (array); \ size_t po = (index); \ size_t sp = (space); \ - if (__builtin_expect (po > ar->size, 0)) { \ + if (__builtin_expect (po > ar_o->size, 0)) { \ Sys_Error ("Attempt to insert elements outside darray: " \ "%s:%d", __FILE__, __LINE__); \ } \ - DARRAY_RESIZE (ar, ar->size + sp); \ - memmove (&ar->a[po + sp], &ar->a[po], \ - (ar->size - po - sp) * sizeof (*ar->a)); \ - &ar->a[po]; \ + DARRAY_RESIZE (ar_o, ar_o->size + sp); \ + memmove (&ar_o->a[po + sp], &ar_o->a[po], \ + (ar_o->size - po - sp) * sizeof (*ar_o->a)); \ + &ar_o->a[po]; \ }) /** Insert a value into the array at the specified index. @@ -314,18 +314,18 @@ */ #define DARRAY_CLOSE_AT(array, index, count) \ ({ \ - __auto_type ar = (array); \ + __auto_type ar_c = (array); \ size_t po = (index); \ size_t co = (count); \ - if (__builtin_expect (po + co > ar->size \ - || po >= ar->size, 0)) { \ + if (__builtin_expect (po + co > ar_c->size \ + || po >= ar_c->size, 0)) { \ Sys_Error ("Attempt to remove elements outside darray: " \ "%s:%d", __FILE__, __LINE__); \ } \ - __auto_type ob = ar->a[po]; \ - memmove (&ar->a[po], &ar->a[po + co], \ - (ar->size - po - co) * sizeof (ob)); \ - ar->size -= co; \ + __auto_type ob = ar_c->a[po]; \ + memmove (&ar_c->a[po], &ar_c->a[po + co], \ + (ar_c->size - po - co) * sizeof (ob)); \ + ar_c->size -= co; \ ob; \ }) diff --git a/include/QF/pqueue.h b/include/QF/pqueue.h index a9428ae48..7ee3c73d8 100644 --- a/include/QF/pqueue.h +++ b/include/QF/pqueue.h @@ -73,8 +73,8 @@ #define PQUEUE_IS_FULL(queue) \ ({ \ - __auto_type q = (queue); \ - q->size == q->maxSize; \ + __auto_type q_f = (queue); \ + q_f->size == q_f->maxSize; \ }) #define PQUEUE_PEEK(queue) ((queue)->a[0]) diff --git a/include/QF/ringbuffer.h b/include/QF/ringbuffer.h index c0f99d4ba..60eb5d440 100644 --- a/include/QF/ringbuffer.h +++ b/include/QF/ringbuffer.h @@ -45,9 +45,9 @@ unsigned tail; \ } -#define RB_buffer_size(ring_buffer) \ - ({ __auto_type rb = (ring_buffer); \ - sizeof (rb->buffer) / sizeof (rb->buffer[0]); \ +#define RB_buffer_size(ring_buffer) \ + ({ __auto_type rb_s = (ring_buffer); \ + sizeof (rb_s->buffer) / sizeof (rb_s->buffer[0]); \ }) /** Return the amount of space available for writing in the ring buffer. From 14ad364e17cced5e770bceb4027450853efc5a21 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 14:47:04 +0900 Subject: [PATCH 2619/3664] [gamecode] Document the tests that fail under clang The tests fail due to differences in how clang and gcc treat floating point to unsigned integral type conversions when the values overflow. It wouldn't be so bad if clang was consistent with conversions to 32-bit unsigned integers, like it seems to be with conversion to 64-bit unsigned integers. With this, the "get QF building with clang" mini-project is done and I won't have to panic when someone comes to me and asks if it will work. At worst, there'll be a little bit-rot. --- libs/gamecode/test/test-conv4.c | 8 ++++++++ libs/gamecode/test/test-conv6.c | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c index 246b4bec3..3fb1b8d47 100644 --- a/libs/gamecode/test/test-conv4.c +++ b/libs/gamecode/test/test-conv4.c @@ -25,6 +25,14 @@ static pr_ivec4_t uint_conv_init[] = { { 0, 0, 0, 0}, }; +/* Note that these tests (specifically 1, 3a and 3b) fail when compiled with + * clang and optimzing due to difference between clang and gcc, and more + * interestingly, within clang itself: with optimization enabled, the entries + * marked with "undef?" produce 0x80000000 instead of 0, but with optimization + * disabled, the expected 0 is produced. + * Inspecting the results, it seems that clang sets negative floats and doubles + * to 0 when casting to unsigned long, but not consistently. + */ static pr_ivec4_t uint_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c index b32cfc537..76bb018ed 100644 --- a/libs/gamecode/test/test-conv6.c +++ b/libs/gamecode/test/test-conv6.c @@ -33,6 +33,12 @@ static pr_ivec4_t ulong_conv_init[] = { { 0, 0, 0, 0}, }; +/* Note that these tests fail when compiled with clang due to difference + * between clang and gcc. However, unlike test-conv4, the failure is + * consistent between optimized and unoptimized: all tests fail either way. + * Inspecting the results, it seems that clang sets negative floats and doubles + * to 0 when casting to unsigned long. + */ static pr_ivec4_t ulong_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float From a35bfef24c97123223bb1f8cd383fee8d6be8e76 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 16:31:13 +0900 Subject: [PATCH 2620/3664] [sys] Add a function to safely create a unique file QF currently uses unique file names for screenshots and server-side demos (and remote snapshots), but they're generally useful. QFS_NextFilename has been filling this role, but it is highly insecure in its current implementation. This is the first step to taking care of that. --- include/QF/sys.h | 33 +++++++++++++++++++++++++++++++++ libs/util/sys.c | 27 +++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/QF/sys.h b/include/QF/sys.h index 631489d79..3b6d5aed3 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -38,6 +38,8 @@ #include #include +struct dstring_s; + extern struct cvar_s *sys_nostdout; extern struct cvar_s *sys_extrasleep; extern struct cvar_s *sys_dead_sleep; @@ -166,6 +168,37 @@ int Sys_CreatePath (const char *path); */ char *Sys_ExpandSquiggle (const char *path); +/** Open a newly created file with a guaranteed unique name. + + Uniqueness is guaranteed by adding a numeric sequence between the \a + prefix and \a suffix, with a minium of \a mindigits numeric characters + (with any required leading 0s to expand the number to \a mindigits). + + The created file has read and write permissions as modified by the OS, + and the handle can be bothe written and read. + + \param name dstring into which the name will be generated. Any + existing contents will be lost. If an error occurs, + \a name will be set to the error string. + \param prefix This includes the path to the file and any file name + prefix. The numeric sequence will be appended directly + to the prefix with no directory separator. + \param suffix Optional tail to be appended after the numeric sequence, + usually the file extension. A dot is not added + automatically, it is up to the caller to supply one. NULL + and an empty string are equivalent. + \param mindigits The minimum number of digits to include in the + generated file name. The sequence number will be padded + with 0s in order to meet this menimum. Overflow will + simply produce longer numeric sequence sub-strings. + \return File handle to the newly created file, or a negative + value if an error occured (the negative error code). + Suitable for use with read, write, fdopen, Qdopen, etc. + \note It is the caller's responsibility to close the file. +*/ +int Sys_UniqueFile (struct dstring_s *name, const char *prefix, + const char *suffix, int mindigits); + ///@} #endif//__QF_sys_h diff --git a/libs/util/sys.c b/libs/util/sys.c index 8aefe89f5..daa9adb55 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -60,6 +60,7 @@ # include #endif +#include #include #include #include @@ -1155,3 +1156,29 @@ Sys_ExpandSquiggle (const char *path) home = "."; return nva ("%s%s", home, path + 1); // skip leading ~ } + +VISIBLE int +Sys_UniqueFile (dstring_t *name, const char *prefix, const char *suffix, + int mindigits) +{ + const int flags = O_CREAT | O_EXCL | O_RDWR; + const int mode = 0644; + int64_t seq = 0; // it should take a while to run out + + if (!suffix) { + suffix = ""; + } + while (1) { + dsprintf (name, "%s%0*"PRIi64"%s", prefix, mindigits, seq, suffix); + int fd = open (name->str, flags, mode); + if (fd >= 0) { + return fd; + } + int err = errno; + if (err != EEXIST) { + dsprintf (name, "%s", strerror (err)); + return -err; + } + seq++; + } +} From 8cdabc89054de88cc5cc4641a8b0b9fc01cdfbd2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 16:40:27 +0900 Subject: [PATCH 2621/3664] [quakefs] Reimplement QFS_NextFilename to be more secure It's not there yet as it promptly closes the file and returns only the filename (and then only the portion within the user's directory tree). However, this worked nicely as a test for Sys_UniqueFile. --- libs/util/quakefs.c | 25 +++++++++---------------- libs/video/renderer/r_screen.c | 3 ++- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 465b8c534..66cce7931 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1557,26 +1557,19 @@ QFS_SetExtension (struct dstring_s *path, const char *extension) VISIBLE int QFS_NextFilename (dstring_t *filename, const char *prefix, const char *ext) { - char *digits; - int i; int ret = 0; dstring_t *full_path = dstring_new (); - dsprintf (filename, "%s0000%s", prefix, ext); - digits = filename->str + strlen (prefix); - - for (i = 0; i <= 9999; i++) { - digits[0] = i / 1000 + '0'; - digits[1] = i / 100 % 10 + '0'; - digits[2] = i / 10 % 10 + '0'; - digits[3] = i % 10 + '0'; - - if (qfs_expand_userpath (full_path, filename->str) == -1) - break; - if (Sys_FileExists (full_path->str) == -1) { - // file doesn't exist, so we can use this name + if (qfs_expand_userpath (full_path, "") == -1) { + dsprintf (filename, "failed to expand userpath"); + } else { + size_t qfs_pos = strlen (full_path->str); + dstring_appendstr (full_path, prefix); + int fd = Sys_UniqueFile (filename, full_path->str, ext, 4); + if (fd >= 0) { + dstring_snip (filename, 0, qfs_pos); + close (fd); ret = 1; - break; } } dstring_delete (full_path); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 2ebc122be..af8ceb19a 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -365,7 +365,8 @@ ScreenShot_f (void) // find a file name to save it to if (!QFS_NextFilename (name, va (0, "%s/qf", qfs_gamedir->dir.shots), ".png")) { - Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file\n"); + Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file: %s\n", + name->str); } else { tex_t *tex; From a29836cc2c793f24080a053babd84ec1f4ec1f36 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 17:27:04 +0900 Subject: [PATCH 2622/3664] [quakefs] Return QFile pointer from QFS_NextFile(name) QFS_NextFilename was renamed to QFS_NextFile to reflect the fact it now returns a QFile pointer for the newly created file (as well as the name). This necessitated updating WritePNG to take a file pointer instead of a file name, with the advantage that WritePNGqfs is no longer necessary and callers have much more control over the creation of the file. This makes QFS_NextFile much more secure against file system race conditions and attacks (at least in theory). If nothing else, it will make it more robust in a multi-threaded environment. --- include/QF/png.h | 4 +-- include/QF/quakefs.h | 13 +++++--- libs/image/png.c | 41 ++----------------------- libs/util/quakefs.c | 13 ++++---- libs/video/renderer/r_screen.c | 8 +++-- libs/video/renderer/vid_render_vulkan.c | 6 ++-- nq/source/host.c | 10 ++++-- qw/include/server.h | 1 + qw/source/cl_main.c | 10 ++++-- qw/source/sv_ccmds.c | 19 ++++++------ qw/source/sv_demo.c | 16 +++++----- qw/source/sv_user.c | 15 +++------ tools/bsp2img/bsp2img.c | 6 +++- 13 files changed, 70 insertions(+), 92 deletions(-) diff --git a/include/QF/png.h b/include/QF/png.h index b322a93f0..1128a8a4f 100644 --- a/include/QF/png.h +++ b/include/QF/png.h @@ -34,8 +34,6 @@ #include "QF/quakefs.h" struct tex_s *LoadPNG (QFile *infile, int load); -void WritePNG (const char *fileName, const byte *data, int width, int height); -void WritePNGqfs (const char *fileName, const byte *data, - int width, int height); +int WritePNG (QFile *outfile, const byte *data, int width, int height); #endif//__QF_png_h diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index 064193ce9..c95560b10 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -290,17 +290,20 @@ int QFS_Remove (const char *path); /** Find available filename. The filename will be of the form \c prefixXXXX.ext where \c XXXX - is a zero padded number from 0 to 9999. + is a zero padded number from 0 to 9999. Should there already be 10000 + files of such a pattern, then extra digits will be added. \param filename This will be set to the available filename. \param prefix The part of the filename preceeding the numers. \param ext The extension to add to the filename. - \return 1 for success, 0 for failure. + \return NULL for failure (with an error message in \a filename) + or a quakeio file handle. - \note \a prefix is relative to \c qfc_userpath. + \note \a prefix is relative to \c qfc_userpath, as is the generated + filename. */ -int QFS_NextFilename (struct dstring_s *filename, const char *prefix, - const char *ext); +QFile *QFS_NextFile (struct dstring_s *filename, const char *prefix, + const char *ext); /** Extract the non-extension part of the file name from the path. diff --git a/libs/image/png.c b/libs/image/png.c index 90fe93463..a64f91912 100644 --- a/libs/image/png.c +++ b/libs/image/png.c @@ -205,8 +205,8 @@ LoadPNG (QFile *infile, int load) #define WRITEPNG_BIT_DEPTH 8 -static int -write_png (QFile *outfile, const byte *data, int width, int height) +int +WritePNG (QFile *outfile, const byte *data, int width, int height) { int i; png_structp png_ptr; @@ -282,36 +282,6 @@ write_png (QFile *outfile, const byte *data, int width, int height) return 1; } -VISIBLE void -WritePNG (const char *fileName, const byte *data, int width, int height) -{ - QFile *outfile; - - outfile = Qopen (fileName, "wb"); - if (!outfile) { - Sys_Printf ("Couldn't open %s\n", fileName); - return; /* Can't open file */ - } - if (!write_png (outfile, data, width, height)) - Qremove (fileName); - Qclose (outfile); -} - -VISIBLE void -WritePNGqfs (const char *fileName, const byte *data, int width, int height) -{ - QFile *outfile; - - outfile = QFS_Open (fileName, "wb"); - if (!outfile) { - Sys_Printf ("Couldn't open %s\n", fileName); - return; /* Can't open file */ - } - if (!write_png (outfile, data, width, height)) - QFS_Remove (fileName); - Qclose (outfile); -} - #else #include "QF/image.h" @@ -324,12 +294,7 @@ LoadPNG (QFile *infile, int load) } VISIBLE void -WritePNG (const char *fileName, const byte *data, int width, int height) -{ -} - -VISIBLE void -WritePNGqfs (const char *fileName, const byte *data, int width, int height) +WritePNG (QFile *outfile, const byte *data, int width, int height) { } diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 66cce7931..b9ea4c38a 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1554,10 +1554,10 @@ QFS_SetExtension (struct dstring_s *path, const char *extension) dstring_appendstr (path, extension); } -VISIBLE int -QFS_NextFilename (dstring_t *filename, const char *prefix, const char *ext) +VISIBLE QFile * +QFS_NextFile (dstring_t *filename, const char *prefix, const char *ext) { - int ret = 0; + QFile *file = 0; dstring_t *full_path = dstring_new (); if (qfs_expand_userpath (full_path, "") == -1) { @@ -1568,12 +1568,13 @@ QFS_NextFilename (dstring_t *filename, const char *prefix, const char *ext) int fd = Sys_UniqueFile (filename, full_path->str, ext, 4); if (fd >= 0) { dstring_snip (filename, 0, qfs_pos); - close (fd); - ret = 1; + // Sys_UniqueFile opens with O_RDWR, and ensure binary files work + // on Windows. gzip writing is NOT specified + file = Qdopen (fd, "w+b"); } } dstring_delete (full_path); - return ret; + return file; } VISIBLE QFile * diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index af8ceb19a..d9380affd 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -361,18 +361,20 @@ static void ScreenShot_f (void) { dstring_t *name = dstring_new (); + QFile *file; // find a file name to save it to - if (!QFS_NextFilename (name, va (0, "%s/qf", - qfs_gamedir->dir.shots), ".png")) { + if (!(file = QFS_NextFile (name, va (0, "%s/qf", qfs_gamedir->dir.shots), + ".png"))) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file: %s\n", name->str); } else { tex_t *tex; tex = r_funcs->SCR_CaptureBGR (); - WritePNGqfs (name->str, tex->data, tex->width, tex->height); + WritePNG (file, tex->data, tex->width, tex->height); free (tex); + Qclose (file); Sys_Printf ("Wrote %s/%s\n", qfs_userpath, name->str); } dstring_delete (name); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 7224dc2ef..0a8c786ab 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -462,17 +462,18 @@ vulkan_set_fov (float x, float y) mctx->dirty = mctx->frames.size; } - +#if 0 static int is_bgr (VkFormat format) { return (format >= VK_FORMAT_B8G8R8A8_UNORM && format <= VK_FORMAT_B8G8R8A8_SRGB); } - +#endif static void capture_screenshot (const byte *data, int width, int height) { +#if 0 dstring_t *name = dstring_new (); // find a file name to save it to if (!QFS_NextFilename (name, va (vulkan_ctx->va_ctx, "%s/qf", @@ -502,6 +503,7 @@ capture_screenshot (const byte *data, int width, int height) } } dstring_delete (name); +#endif } static tex_t * diff --git a/nq/source/host.c b/nq/source/host.c index 16b029e13..6b17ddc12 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -702,9 +702,13 @@ _Host_Frame (float time) if (cls.demo_capture) { tex_t *tex = r_funcs->SCR_CaptureBGR (); - WritePNGqfs (va (0, "%s/qfmv%06d.png", qfs_gamedir->dir.shots, - cls.demo_capture++), - tex->data, tex->width, tex->height); + QFile *file = Qopen (va (0, "%s/qfmv%06d.png", + qfs_gamedir->dir.shots, + cls.demo_capture++), "wb"); + if (file) { + WritePNG (file, tex->data, tex->width, tex->height); + Qclose (file); + } free (tex); } diff --git a/qw/include/server.h b/qw/include/server.h index be60ccf95..dfdc48f72 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -252,6 +252,7 @@ typedef struct client_s { QFile *upload; struct dstring_s *uploadfn; + int upload_started; netadr_t snap_from; qboolean remote_snap; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index bdc7a3996..f0207396c 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1752,9 +1752,13 @@ Host_Frame (float time) if (cls.demo_capture) { tex_t *tex = r_funcs->SCR_CaptureBGR (); - WritePNGqfs (va (0, "%s/qfmv%06d.png", qfs_gamedir->dir.shots, - cls.demo_capture++), - tex->data, tex->width, tex->height); + QFile *file = Qopen (va (0, "%s/qfmv%06d.png", + qfs_gamedir->dir.shots, cls.demo_capture++), + "wb"); + if (file) { + WritePNG (file, tex->data, tex->width, tex->height); + Qclose (file); + } free (tex); } diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index 780556a82..f9e99f0b5 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -249,13 +249,12 @@ SV_Fraglogfile_f (void) return; } name = dstring_new (); - if (!QFS_NextFilename (name, - va (0, "%s/frag_", qfs_gamedir->dir.def), ".log")) { - SV_Printf ("Can't open any logfiles.\n"); - sv_fraglogfile = NULL; + if (!(sv_fraglogfile = QFS_NextFile (name, + va (0, "%s/frag_", + qfs_gamedir->dir.def), ".log"))) { + SV_Printf ("Can't open any logfiles.\n%s\n", name->str); } else { SV_Printf ("Logging frags to %s.\n", name->str); - sv_fraglogfile = QFS_WOpen (name->str, 0); } dstring_delete (name); } @@ -1136,14 +1135,16 @@ SV_Snap (int uid) if (!cl->uploadfn) cl->uploadfn = dstring_new (); - if (!QFS_NextFilename (cl->uploadfn, - va (0, "%s/snap/%d-", qfs_gamedir->dir.def, uid), - ".pcx")) { - SV_Printf ("Snap: Couldn't create a file, clean some out.\n"); + if (!(cl->upload = QFS_NextFile (cl->uploadfn, + va (0, "%s/snap/%d-", + qfs_gamedir->dir.def, uid), ".pcx"))) { + SV_Printf ("Snap: Couldn't create a file, clean some out.\n%s\n", + cl->uploadfn->str); dstring_delete (cl->uploadfn); cl->uploadfn = 0; return; } + cl->upload_started = 0; memcpy (&cl->snap_from, &net_from, sizeof (net_from)); if (sv_redirected != RD_NONE) diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index 9ddd21a5d..47580b4e0 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -366,12 +366,6 @@ SV_Record (char *name) client_t *player; const char *gamedir, *s; - demo_file = QFS_Open (name, "wb"); - if (!demo_file) { - Sys_Printf ("ERROR: couldn't open %s\n", name); - return; - } - SV_InitRecord (); dstring_copystr (demo_name, name); @@ -642,7 +636,12 @@ SV_Record_f (void) // open the demo file QFS_DefaultExtension (name, ".mvd"); - SV_Record (name->str); + demo_file = QFS_Open (name->str, "wb"); + if (!demo_file) { + Sys_Printf ("ERROR: couldn't open %s\n", name->str); + } else { + SV_Record (name->str); + } dstring_delete (name); } @@ -757,8 +756,9 @@ SV_EasyRecord_f (void) sv_demoPrefix->string, SV_CleanName (name->str), sv_demoSuffix->string); - if (QFS_NextFilename (name, name2->str, ".mvd")) + if ((demo_file = QFS_NextFile (name, name2->str, ".mvd"))) { SV_Record (name->str); + } dstring_delete (name); dstring_delete (name2); diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 0e10bec27..a9eb02fe4 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -647,7 +647,7 @@ SV_NextUpload (void) { int percent, size; - if (!host_client->uploadfn) { + if (!host_client->upload) { SV_ClientPrintf (1, host_client, PRINT_HIGH, "Upload denied\n"); MSG_ReliableWrite_Begin (&host_client->backbuf, svc_stufftext, 8); MSG_ReliableWrite_String (&host_client->backbuf, "stopul"); @@ -662,16 +662,8 @@ SV_NextUpload (void) size = MSG_ReadShort (net_message); percent = MSG_ReadByte (net_message); - if (!host_client->upload) { - host_client->upload = QFS_Open (host_client->uploadfn->str, "wb"); - if (!host_client->upload) { - SV_Printf ("Can't create %s\n", host_client->uploadfn->str); - MSG_ReliableWrite_Begin (&host_client->backbuf, svc_stufftext, 8); - MSG_ReliableWrite_String (&host_client->backbuf, "stopul"); - dstring_delete (host_client->uploadfn); - host_client->uploadfn = 0; - return; - } + if (!host_client->upload_started) { + host_client->upload_started = 1; SV_Printf ("Receiving %s from %d...\n", host_client->uploadfn->str, host_client->userid); if (host_client->remote_snap) @@ -708,6 +700,7 @@ SV_NextUpload (void) } dstring_delete (host_client->uploadfn); host_client->uploadfn = 0; + host_client->upload_started = 0; } } diff --git a/tools/bsp2img/bsp2img.c b/tools/bsp2img/bsp2img.c index f469e6bf9..58c377fc6 100644 --- a/tools/bsp2img/bsp2img.c +++ b/tools/bsp2img/bsp2img.c @@ -898,7 +898,11 @@ write_png (image_t *image) *out++ = b; *out++ = b; } - WritePNG (options.outf_name, data, image->width, image->height); + QFile *file = Qopen (options.outf_name, "wb"); + if (file) { + WritePNG (file, data, image->width, image->height); + Qclose (file); + } } static void From acffacc59b1ce1d4d0d260d27052eda52f21ce95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 19:07:15 +0900 Subject: [PATCH 2623/3664] [renderer] Make screen capture support asynchronous operation This fixes (*ahem*) the vulkan renderer segfaulting when attempting to take a screenshot. However, the image is upside down. Also, remote snapshots and demo capture are broken for the moment. --- include/QF/plugin/vid_render.h | 6 +- include/vid_gl.h | 3 - include/vid_sw.h | 2 - include/vid_vulkan.h | 3 + libs/video/renderer/Makemodule.am | 3 - libs/video/renderer/gl/gl_screen.c | 62 ------------------ libs/video/renderer/glsl/glsl_screen.c | 69 -------------------- libs/video/renderer/r_screen.c | 40 +++++++++--- libs/video/renderer/sw/screen.c | 71 --------------------- libs/video/renderer/vid_render_gl.c | 25 +++++++- libs/video/renderer/vid_render_glsl.c | 34 +++++++++- libs/video/renderer/vid_render_sw.c | 40 +++++++++++- libs/video/renderer/vid_render_vulkan.c | 83 ++++++++++++++----------- nq/source/host.c | 4 +- qw/source/cl_main.c | 4 +- 15 files changed, 183 insertions(+), 266 deletions(-) delete mode 100644 libs/video/renderer/gl/gl_screen.c delete mode 100644 libs/video/renderer/glsl/glsl_screen.c delete mode 100644 libs/video/renderer/sw/screen.c diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index c0ad899c9..19ed1e394 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -76,6 +76,9 @@ typedef struct vid_model_funcs_s { void (*Skin_InitTranslations) (void); } vid_model_funcs_t; +struct tex_s; +typedef void (*capfunc_t) (struct tex_s *screencap, void *data); + typedef struct vid_render_funcs_s { void (*init) (void); void (*Draw_Character) (int x, int y, unsigned ch); @@ -99,7 +102,6 @@ typedef struct vid_render_funcs_s { void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); - struct tex_s *(*SCR_CaptureBGR) (void); struct psystem_s *(*ParticleSystem) (void); void (*R_Init) (void); @@ -124,6 +126,8 @@ typedef struct vid_render_funcs_s { // x and y are tan(f/2) for fov_x and fov_y void (*set_fov) (float x, float y); + void (*capture_screen) (capfunc_t callback, void *data); + vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/vid_gl.h b/include/vid_gl.h index 6249790dd..c073837bc 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -32,9 +32,6 @@ typedef struct gl_framebuffer_s { extern gl_ctx_t *gl_ctx; extern gl_ctx_t *glsl_ctx; -struct tex_s *gl_SCR_CaptureBGR (void); -struct tex_s *glsl_SCR_CaptureBGR (void); - void gl_Fog_SetupFrame (void); void gl_Fog_EnableGFog (void); void gl_Fog_DisableGFog (void); diff --git a/include/vid_sw.h b/include/vid_sw.h index ed2f21a1a..913052242 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -20,6 +20,4 @@ typedef struct sw_framebuffer_s { extern sw_ctx_t *sw_ctx; -struct tex_s *sw_SCR_CaptureBGR (void); - #endif//__vid_sw_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 66d394181..56aa8c3f3 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -79,6 +79,9 @@ typedef struct vulkan_ctx_s { struct qfv_capture_s *capture; void (*capture_callback) (const byte *data, int width, int height); + // make a queue? + void *capture_complete;// really capfunc_t + void *capture_complete_data; struct qfv_tex_s *default_black; struct qfv_tex_s *default_white; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index c19d5bcdb..bc48a77e2 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -80,7 +80,6 @@ libs_video_renderer_librender_gl_la_SOURCES = \ libs/video/renderer/gl/gl_rmain.c \ libs/video/renderer/gl/gl_rmisc.c \ libs/video/renderer/gl/gl_rsurf.c \ - libs/video/renderer/gl/gl_screen.c \ libs/video/renderer/gl/gl_sky.c \ libs/video/renderer/gl/gl_sky_clip.c \ libs/video/renderer/gl/gl_textures.c \ @@ -116,7 +115,6 @@ libs_video_renderer_librender_glsl_la_SOURCES = \ libs/video/renderer/glsl/glsl_lightmap.c \ libs/video/renderer/glsl/glsl_main.c \ libs/video/renderer/glsl/glsl_particles.c \ - libs/video/renderer/glsl/glsl_screen.c \ libs/video/renderer/glsl/glsl_shader.c \ libs/video/renderer/glsl/glsl_sprite.c \ libs/video/renderer/glsl/glsl_textures.c \ @@ -158,7 +156,6 @@ libs_video_renderer_librender_sw_la_SOURCES = \ libs/video/renderer/sw/fpu.c \ libs/video/renderer/sw/fpua.S \ libs/video/renderer/sw/nonintel.c \ - libs/video/renderer/sw/screen.c \ libs/video/renderer/sw/surf8.S \ libs/video/renderer/sw/sw_fisheye.c \ libs/video/renderer/sw/sw_graph.c \ diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c deleted file mode 100644 index 8bd6c462d..000000000 --- a/libs/video/renderer/gl/gl_screen.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - gl_screen.c - - master for refresh, status bar, console, chat, notify, etc - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "QF/image.h" -#include "QF/sys.h" - -#include "QF/GL/defines.h" -#include "QF/GL/funcs.h" -#include "QF/GL/qf_rmain.h" - -#include "r_internal.h" -#include "vid_gl.h" - -/* SCREEN SHOTS */ - -tex_t * -gl_SCR_CaptureBGR (void) -{ - int count; - tex_t *tex; - - count = vid.width * vid.height; - tex = malloc (sizeof (tex_t) + count * 3); - tex->data = (byte *) (tex + 1); - SYS_CHECKMEM (tex); - tex->width = vid.width; - tex->height = vid.height; - tex->format = tex_rgb; - tex->palette = 0; - qfglReadPixels (0, 0, tex->width, tex->height, GL_BGR_EXT, - GL_UNSIGNED_BYTE, tex->data); - return tex; -} diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c deleted file mode 100644 index 4848b9018..000000000 --- a/libs/video/renderer/glsl/glsl_screen.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - glsl_main.c - - GLSL rendering - - Copyright (C) 2011 Bill Currie - - Author: Bill Currie - Date: 2011/12/23 - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "QF/image.h" -#include "QF/sys.h" - -#include "QF/GLSL/defines.h" -#include "QF/GLSL/funcs.h" - -#include "r_internal.h" -#include "vid_gl.h" - -tex_t * -glsl_SCR_CaptureBGR (void) -{ - byte *r, *b; - int count, i; - tex_t *tex; - - count = vid.width * vid.height; - tex = malloc (sizeof (tex_t) + count * 3); - tex->data = (byte *) (tex + 1); - SYS_CHECKMEM (tex); - tex->width = vid.width; - tex->height = vid.height; - tex->format = tex_rgb; - tex->palette = 0; - qfeglReadPixels (0, 0, vid.width, vid.height, GL_RGB, - GL_UNSIGNED_BYTE, tex->data); - for (i = 0, r = tex->data, b = tex->data + 2; i < count; - i++, r += 3, b += 3) { - byte t = *b; - *b = *r; - *r = t; - } - return tex; -} diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index d9380affd..31ebcbf0d 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -357,6 +357,28 @@ SCR_SetBottomMargin (int lines) update_vrect (); } +typedef struct scr_capture_s { + dstring_t *name; + QFile *file; +} scr_capture_t; + +static void +scr_write_caputre (tex_t *tex, void *data) +{ + scr_capture_t *cap = data; + + if (tex) { + WritePNG (cap->file, tex->data, tex->width, tex->height); + free (tex); + Sys_Printf ("Wrote %s/%s\n", qfs_userpath, cap->name->str); + } else { + Sys_Printf ("Capture failed\n"); + } + Qclose (cap->file); + dstring_delete (cap->name); + free (cap); +} + static void ScreenShot_f (void) { @@ -368,16 +390,13 @@ ScreenShot_f (void) ".png"))) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file: %s\n", name->str); + dstring_delete (name); } else { - tex_t *tex; - - tex = r_funcs->SCR_CaptureBGR (); - WritePNG (file, tex->data, tex->width, tex->height); - free (tex); - Qclose (file); - Sys_Printf ("Wrote %s/%s\n", qfs_userpath, name->str); + scr_capture_t *cap = malloc (sizeof (scr_capture_t)); + cap->file = file; + cap->name = name; + r_funcs->capture_screen (scr_write_caputre, cap); } - dstring_delete (name); } /* @@ -463,6 +482,7 @@ SCR_DrawPause (void) /* Find closest color in the palette for named color */ +#if 0 static int MipColor (int r, int g, int b) { @@ -495,6 +515,7 @@ MipColor (int r, int g, int b) lastbest = best; return best; } +#endif // in draw.c @@ -542,6 +563,8 @@ SCR_DrawStringToSnap (const char *s, tex_t *tex, int x, int y) tex_t * SCR_SnapScreen (unsigned width, unsigned height) { + return 0; +#if 0 byte *src, *dest; float fracw, frach; unsigned count, dex, dey, dx, dy, nx, r, g, b, x, y, w, h; @@ -599,6 +622,7 @@ SCR_SnapScreen (unsigned width, unsigned height) free (snap); return tex; +#endif } static void diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c deleted file mode 100644 index 543d831f1..000000000 --- a/libs/video/renderer/sw/screen.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - screen.c - - master for refresh, status bar, console, chat, notify, etc - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "QF/image.h" -#include "QF/sys.h" - -#include "r_internal.h" -#include "vid_sw.h" - -/* SCREEN SHOTS */ - -tex_t * -sw_SCR_CaptureBGR (void) -{ - int count, x, y; - tex_t *tex; - const byte *src; - byte *dst; - framebuffer_t *fb = sw_ctx->framebuffer; - - count = fb->width * fb->height; - tex = malloc (sizeof (tex_t) + count * 3); - tex->data = (byte *) (tex + 1); - SYS_CHECKMEM (tex); - tex->width = fb->width; - tex->height = fb->height; - tex->format = tex_rgb; - tex->palette = 0; - src = ((sw_framebuffer_t *) fb->buffer)->color; - int rowbytes = ((sw_framebuffer_t *) fb->buffer)->rowbytes; - for (y = 0; y < tex->height; y++) { - dst = tex->data + (tex->height - 1 - y) * tex->width * 3; - for (x = 0; x < tex->width; x++) { - byte c = src[x]; - *dst++ = vid.basepal[c * 3 + 2]; // blue - *dst++ = vid.basepal[c * 3 + 1]; // green - *dst++ = vid.basepal[c * 3 + 0]; // red - } - src += rowbytes; - } - return tex; -} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 687f8765e..761854407 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -29,6 +29,7 @@ #endif #include "QF/cvar.h" +#include "QF/image.h" #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -458,6 +459,26 @@ gl_set_fov (float x, float y) mmulf (gl_ctx->projection, depth_range, proj); } +static void +gl_capture_screen (capfunc_t callback, void *data) +{ + int count; + tex_t *tex; + + count = vid.width * vid.height; + tex = malloc (sizeof (tex_t) + count * 3); + if (tex) { + tex->data = (byte *) (tex + 1); + tex->width = vid.width; + tex->height = vid.height; + tex->format = tex_rgb; + tex->palette = 0; + qfglReadPixels (0, 0, tex->width, tex->height, GL_BGR_EXT, + GL_UNSIGNED_BYTE, tex->data); + } + callback (tex, data); +} + vid_render_funcs_t gl_vid_render_funcs = { gl_vid_render_init, gl_Draw_Character, @@ -481,8 +502,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_Picf, gl_Draw_SubPic, - gl_SCR_CaptureBGR, - gl_ParticleSystem, gl_R_Init, gl_R_ClearState, @@ -504,6 +523,8 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_set_viewport, gl_set_fov, + gl_capture_screen, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 669cedab9..1860f2ba7 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -29,6 +29,7 @@ #endif #include "QF/cvar.h" +#include "QF/image.h" #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -405,6 +406,35 @@ glsl_set_fov (float x, float y) mmulf (glsl_ctx->projection, depth_range, proj); } +static void +glsl_capture_screen (capfunc_t callback, void *data) +{ + byte *r, *b; + int count, i; + tex_t *tex; + + count = vid.width * vid.height; + tex = malloc (sizeof (tex_t) + count * 3); + if (tex) { + tex->data = (byte *) (tex + 1); + tex->width = vid.width; + tex->height = vid.height; + tex->format = tex_rgb; + tex->palette = 0; + qfeglReadPixels (0, 0, tex->width, tex->height, GL_RGB, + GL_UNSIGNED_BYTE, tex->data); + //FIXME shouldn't have to swap between rgb and bgr since WritePNG + //swaps back + for (i = 0, r = tex->data, b = tex->data + 2; i < count; + i++, r+= 3, b += 3) { + byte t = *b; + *b = *r; + *r = t; + } + } + callback (tex, data); +} + vid_render_funcs_t glsl_vid_render_funcs = { glsl_vid_render_init, glsl_Draw_Character, @@ -428,8 +458,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_Picf, glsl_Draw_SubPic, - glsl_SCR_CaptureBGR, - glsl_ParticleSystem, glsl_R_Init, glsl_R_ClearState, @@ -451,6 +479,8 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_set_viewport, glsl_set_fov, + glsl_capture_screen, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 23a920a36..43c1dfc1d 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -31,6 +31,7 @@ #include #include "QF/cvar.h" +#include "QF/image.h" #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -411,6 +412,41 @@ sw_set_fov (float x, float y) r_resfudge = r_aliastransadj->value * res_scale; } +static void +sw_capture_screen (capfunc_t callback, void *data) +{ + int count, x, y; + tex_t *tex; + const byte *src; + byte *dst; + framebuffer_t *fb = sw_ctx->framebuffer; + + count = fb->width * fb->height; + tex = malloc (sizeof (tex_t) + count * 3); + if (tex) { + tex->data = (byte *) (tex + 1); + tex->width = fb->width; + tex->height = fb->height; + tex->format = tex_rgb; + tex->palette = 0; + src = ((sw_framebuffer_t *) fb->buffer)->color; + int rowbytes = ((sw_framebuffer_t *) fb->buffer)->rowbytes; + //FIXME shouldn't have to swap between rgb and bgr since WritePNG + //swaps back + for (y = 0; y < tex->height; y++) { + dst = tex->data + (tex->height - 1 - y) * tex->width * 3; + for (x = 0; x < tex->width; x++) { + byte c = src[x]; + *dst++ = vid.basepal[c * 3 + 2]; // blue + *dst++ = vid.basepal[c * 3 + 1]; // green + *dst++ = vid.basepal[c * 3 + 0]; // red + } + src += rowbytes; + } + } + callback (tex, data); +} + vid_render_funcs_t sw_vid_render_funcs = { sw_vid_render_init, Draw_Character, @@ -434,8 +470,6 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_Picf, Draw_SubPic, - sw_SCR_CaptureBGR, - sw_ParticleSystem, sw_R_Init, R_ClearState, @@ -457,6 +491,8 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_set_viewport, sw_set_fov, + sw_capture_screen, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 0a8c786ab..5cb1acf5c 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -462,60 +462,69 @@ vulkan_set_fov (float x, float y) mctx->dirty = mctx->frames.size; } -#if 0 + static int is_bgr (VkFormat format) { return (format >= VK_FORMAT_B8G8R8A8_UNORM && format <= VK_FORMAT_B8G8R8A8_SRGB); } -#endif + static void capture_screenshot (const byte *data, int width, int height) { -#if 0 - dstring_t *name = dstring_new (); - // find a file name to save it to - if (!QFS_NextFilename (name, va (vulkan_ctx->va_ctx, "%s/qf", - qfs_gamedir->dir.shots), - ".ppm")) { - Sys_Printf ("SCR_ScreenShot_f: Couldn't create a ppm file\n"); - } else { - QFile *file = QFS_Open (name->str, "wb"); - if (!file) { - Sys_Printf ("Couldn't open %s\n", name->str); - } else { - Qprintf (file, "P6\n%d\n%d\n255\n", width, height); - if (vulkan_ctx->capture->canBlit || - !is_bgr (vulkan_ctx->swapchain->format)) { - for (int count = width * height; count-- > 0; ) { - Qwrite (file, data, 3); - data += 4; - } - } else { - for (int count = width * height; count-- > 0; ) { - byte rgb[] = { data[2], data[1], data[0] }; - Qwrite (file, rgb, 3); - data += 4; - } + int count = width * height; + tex_t *tex = malloc (sizeof (tex_t) + count * 3); + + if (tex) { + tex->data = (byte *) (tex + 1); + tex->width = width; + tex->height = height; + tex->format = tex_rgb; + tex->palette = 0; + + //FIXME shouldn't have to swap between rgb and bgr since WritePNG + //swaps back (ie, it can work with either) + //can it auto-convert RGBA to RGB? + if (!vulkan_ctx->capture->canBlit || + is_bgr (vulkan_ctx->swapchain->format)) { + const byte *src = data; + byte *dst = tex->data; + for (int count = width * height; count-- > 0; ) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + src++; + } + } else { + const byte *src = data; + byte *dst = tex->data; + for (int count = width * height; count-- > 0; ) { + byte r = *src++; + byte g = *src++; + byte b = *src++; + *dst++ = b; + *dst++ = g; + *dst++ = r; + src++; } - Qclose (file); } } - dstring_delete (name); -#endif + capfunc_t callback = vulkan_ctx->capture_complete; + callback (tex, vulkan_ctx->capture_complete_data);; } -static tex_t * -vulkan_SCR_CaptureBGR (void) +static void +vulkan_capture_screen (capfunc_t callback, void *data) { if (!vulkan_ctx->capture) { Sys_Printf ("Capture not supported\n"); - return 0; + callback (0, data); + return; } vulkan_ctx->capture_callback = capture_screenshot; - //FIXME async process - return 0; + vulkan_ctx->capture_complete = callback; + vulkan_ctx->capture_complete_data = data; } static void @@ -727,8 +736,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_Picf, vulkan_Draw_SubPic, - vulkan_SCR_CaptureBGR, - vulkan_ParticleSystem, vulkan_R_Init, vulkan_R_ClearState, @@ -750,6 +757,8 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_set_viewport, vulkan_set_fov, + vulkan_capture_screen, + &model_funcs }; diff --git a/nq/source/host.c b/nq/source/host.c index 6b17ddc12..b34feedde 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -699,7 +699,7 @@ _Host_Frame (float time) Host_ClientFrame (); else host_time += host_frametime; //FIXME is this needed? vcr stuff - +#if 0 if (cls.demo_capture) { tex_t *tex = r_funcs->SCR_CaptureBGR (); QFile *file = Qopen (va (0, "%s/qfmv%06d.png", @@ -711,7 +711,7 @@ _Host_Frame (float time) } free (tex); } - +#endif host_framecount++; fps_count++; } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index f0207396c..ea89cb825 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1749,7 +1749,7 @@ Host_Frame (float time) Sys_Printf ("%3i tot %3i server %3i gfx %3i snd\n", pass1 + pass2 + pass3, pass1, pass2, pass3); } - +#if 0 if (cls.demo_capture) { tex_t *tex = r_funcs->SCR_CaptureBGR (); QFile *file = Qopen (va (0, "%s/qfmv%06d.png", @@ -1761,7 +1761,7 @@ Host_Frame (float time) } free (tex); } - +#endif host_framecount++; fps_count++; } From 790f62a209fdd067016e2a9aed8799c19ee95739 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 20:00:13 +0900 Subject: [PATCH 2624/3664] [image] Make WritePNG take settings from tex_t This means that a tex_t object is passed in instead of just raw bytes and width and height, but it means the texture can specify whether it's flipped or uses BGR instead of RGB. This fixes the upside down screenshots for vulkan. --- include/QF/image.h | 9 +++++- include/QF/png.h | 2 +- libs/image/png.c | 28 ++++++++++------- libs/models/iqm/sw_model_iqm.c | 9 +++++- libs/video/renderer/r_screen.c | 2 +- libs/video/renderer/vid_render_gl.c | 4 +++ libs/video/renderer/vid_render_glsl.c | 18 +++-------- libs/video/renderer/vid_render_sw.c | 12 +++---- libs/video/renderer/vid_render_vulkan.c | 35 +++++++-------------- libs/video/renderer/vulkan/vulkan_texture.c | 27 ++++++++++++++-- tools/bsp2img/bsp2img.c | 15 +++++++-- 11 files changed, 98 insertions(+), 63 deletions(-) diff --git a/include/QF/image.h b/include/QF/image.h index 2bbf7fb0a..d57b7253b 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -46,7 +46,14 @@ typedef struct tex_s { int width; int height; QFFormat format; - int loaded; // 0 if size info only, otherwise data loaded + union { + struct { + int loaded:1; // 0 if size info only, otherwise data loaded + int flipped:1; // 1 if first pixel is bottom instead of top + int bgr:1; // 1 if image is bgr (for tex_rgb) + }; + int flagbits; // for eazy zeroing + }; const byte *palette; // 0 = 32 bit, otherwise 8 byte *data; } tex_t; diff --git a/include/QF/png.h b/include/QF/png.h index 1128a8a4f..62c69a305 100644 --- a/include/QF/png.h +++ b/include/QF/png.h @@ -34,6 +34,6 @@ #include "QF/quakefs.h" struct tex_s *LoadPNG (QFile *infile, int load); -int WritePNG (QFile *outfile, const byte *data, int width, int height); +int WritePNG (QFile *outfile, const struct tex_s *tex); #endif//__QF_png_h diff --git a/libs/image/png.c b/libs/image/png.c index a64f91912..3b67983cd 100644 --- a/libs/image/png.c +++ b/libs/image/png.c @@ -48,6 +48,7 @@ #include "QF/zone.h" #include "compat.h" +#include "qfalloca.h" /* Qread wrapper for libpng */ @@ -206,7 +207,7 @@ LoadPNG (QFile *infile, int load) #define WRITEPNG_BIT_DEPTH 8 int -WritePNG (QFile *outfile, const byte *data, int width, int height) +WritePNG (QFile *outfile, const tex_t *tex) { int i; png_structp png_ptr; @@ -240,27 +241,32 @@ WritePNG (QFile *outfile, const byte *data, int width, int height) return 0; } - png_set_IHDR (png_ptr, info_ptr, width, height, WRITEPNG_BIT_DEPTH, + png_set_IHDR (png_ptr, info_ptr, tex->width, tex->height, + WRITEPNG_BIT_DEPTH, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* NOTE: Write gamma support? */ /* png_set_gAMA (png_ptr, info_ptr, gamma); */ - png_set_bgr(png_ptr); + if (tex->bgr) { + png_set_bgr(png_ptr); + } png_write_info (png_ptr, info_ptr); /* Setup row pointers */ - row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep)); - if (row_pointers == NULL) { - png_destroy_write_struct (&png_ptr, &info_ptr); - return 0; /* Out of memory */ - } + row_pointers = (png_bytepp)alloca(tex->height * sizeof(png_bytep)); - for (i = 0; i < height; i++) { - //FIXME stupid png types :P - row_pointers[height - i - 1] = (byte *) data + (i * width * 3); + int rowbytes = tex->width * 3; + if (tex->flipped) { + for (i = 0; i < tex->height; i++) { + row_pointers[tex->height - i - 1] = tex->data + (i * rowbytes); + } + } else { + for (i = 0; i < tex->height; i++) { + row_pointers[i] = tex->data + (i * rowbytes); + } } diff --git a/libs/models/iqm/sw_model_iqm.c b/libs/models/iqm/sw_model_iqm.c index b715bb5da..0e6d1fa48 100644 --- a/libs/models/iqm/sw_model_iqm.c +++ b/libs/models/iqm/sw_model_iqm.c @@ -54,7 +54,14 @@ #include "r_internal.h" static byte null_data[] = {15, 15, 15, 15}; -static tex_t null_texture = { 2, 2, tex_palette, 1, 0, null_data }; +static tex_t null_texture = { + .width = 2, + .height = 2, + .format = tex_palette, + .loaded = 1, + .palette =0, + .data = null_data +}; static void sw_iqm_clear (model_t *mod, void *data) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 31ebcbf0d..f07a51fd7 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -368,7 +368,7 @@ scr_write_caputre (tex_t *tex, void *data) scr_capture_t *cap = data; if (tex) { - WritePNG (cap->file, tex->data, tex->width, tex->height); + WritePNG (cap->file, tex); free (tex); Sys_Printf ("Wrote %s/%s\n", qfs_userpath, cap->name->str); } else { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 761854407..0d5f5b640 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -473,6 +473,10 @@ gl_capture_screen (capfunc_t callback, void *data) tex->height = vid.height; tex->format = tex_rgb; tex->palette = 0; + tex->flagbits = 0; + tex->loaded = 1; + tex->bgr = 1; + tex->flipped = 1; qfglReadPixels (0, 0, tex->width, tex->height, GL_BGR_EXT, GL_UNSIGNED_BYTE, tex->data); } diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 1860f2ba7..5c93e36b1 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -409,28 +409,20 @@ glsl_set_fov (float x, float y) static void glsl_capture_screen (capfunc_t callback, void *data) { - byte *r, *b; - int count, i; - tex_t *tex; + int count = vid.width * vid.height; + tex_t *tex = malloc (sizeof (tex_t) + count * 3); - count = vid.width * vid.height; - tex = malloc (sizeof (tex_t) + count * 3); if (tex) { tex->data = (byte *) (tex + 1); tex->width = vid.width; tex->height = vid.height; tex->format = tex_rgb; tex->palette = 0; + tex->flagbits = 0; + tex->loaded = 1; + tex->flipped = 1; qfeglReadPixels (0, 0, tex->width, tex->height, GL_RGB, GL_UNSIGNED_BYTE, tex->data); - //FIXME shouldn't have to swap between rgb and bgr since WritePNG - //swaps back - for (i = 0, r = tex->data, b = tex->data + 2; i < count; - i++, r+= 3, b += 3) { - byte t = *b; - *b = *r; - *r = t; - } } callback (tex, data); } diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 43c1dfc1d..14e09d3d4 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -429,17 +429,17 @@ sw_capture_screen (capfunc_t callback, void *data) tex->height = fb->height; tex->format = tex_rgb; tex->palette = 0; + tex->flagbits = 0; + tex->loaded = 1; src = ((sw_framebuffer_t *) fb->buffer)->color; int rowbytes = ((sw_framebuffer_t *) fb->buffer)->rowbytes; - //FIXME shouldn't have to swap between rgb and bgr since WritePNG - //swaps back for (y = 0; y < tex->height; y++) { - dst = tex->data + (tex->height - 1 - y) * tex->width * 3; + dst = tex->data + y * tex->width * 3; for (x = 0; x < tex->width; x++) { byte c = src[x]; - *dst++ = vid.basepal[c * 3 + 2]; // blue - *dst++ = vid.basepal[c * 3 + 1]; // green - *dst++ = vid.basepal[c * 3 + 0]; // red + *dst++ = vid.basepal[c * 3 + 0]; + *dst++ = vid.basepal[c * 3 + 1]; + *dst++ = vid.basepal[c * 3 + 2]; } src += rowbytes; } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 5cb1acf5c..9c65ef615 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -478,36 +478,25 @@ capture_screenshot (const byte *data, int width, int height) if (tex) { tex->data = (byte *) (tex + 1); + tex->flagbits = 0; tex->width = width; tex->height = height; tex->format = tex_rgb; tex->palette = 0; + tex->flagbits = 0; + tex->loaded = 1; - //FIXME shouldn't have to swap between rgb and bgr since WritePNG - //swaps back (ie, it can work with either) - //can it auto-convert RGBA to RGB? if (!vulkan_ctx->capture->canBlit || is_bgr (vulkan_ctx->swapchain->format)) { - const byte *src = data; - byte *dst = tex->data; - for (int count = width * height; count-- > 0; ) { - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - src++; - } - } else { - const byte *src = data; - byte *dst = tex->data; - for (int count = width * height; count-- > 0; ) { - byte r = *src++; - byte g = *src++; - byte b = *src++; - *dst++ = b; - *dst++ = g; - *dst++ = r; - src++; - } + tex->bgr = 1; + } + const byte *src = data; + byte *dst = tex->data; + for (int count = width * height; count-- > 0; ) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + src++; } } capfunc_t callback = vulkan_ctx->capture_complete; diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 611836cc2..f30d3407e 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -420,9 +420,30 @@ Vulkan_UnloadTex (vulkan_ctx_t *ctx, qfv_tex_t *tex) static byte black_data[] = {0, 0, 0, 0}; static byte white_data[] = {255, 255, 255, 255}; static byte magenta_data[] = {255, 0, 255, 255}; -static tex_t default_black_tex = {1, 1, tex_rgba, 1, 0, black_data}; -static tex_t default_white_tex = {1, 1, tex_rgba, 1, 0, white_data}; -static tex_t default_magenta_tex = {1, 1, tex_rgba, 1, 0, magenta_data}; +static tex_t default_black_tex = { + .width = 1, + .height = 1, + .format = tex_rgba, + .loaded = 1, + .palette =0, + .data = black_data, +}; +static tex_t default_white_tex = { + .width = 1, + .height = 1, + .format = tex_rgba, + .loaded = 1, + .palette =0, + .data = white_data, +}; +static tex_t default_magenta_tex = { + .width = 1, + .height = 1, + .format = tex_rgba, + .loaded = 1, + .palette =0, + .data = magenta_data, +}; void Vulkan_Texture_Init (vulkan_ctx_t *ctx) diff --git a/tools/bsp2img/bsp2img.c b/tools/bsp2img/bsp2img.c index 58c377fc6..1742034a8 100644 --- a/tools/bsp2img/bsp2img.c +++ b/tools/bsp2img/bsp2img.c @@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "QF/bspfile.h" #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/image.h" #include "QF/mathlib.h" #include "QF/pcx.h" #include "QF/png.h" @@ -888,10 +889,17 @@ render_map (bsp_t *bsp) static void write_png (image_t *image) { - byte *data, *in, *out, b; + byte *in, *out, b; int size = image->width * image->height; + tex_t tex = { + .width = image->width, + .height = image->height, + .format = tex_rgb, + .loaded = 1, + .data = malloc (size * 3), + }; - out = data = malloc (size * 3); + out = tex.data; for (in = image->image; in - image->image < size; in++) { b = *in; *out++ = b; @@ -900,9 +908,10 @@ write_png (image_t *image) } QFile *file = Qopen (options.outf_name, "wb"); if (file) { - WritePNG (file, data, image->width, image->height); + WritePNG (file, &tex); Qclose (file); } + free (tex.data); } static void From 86e95fc1d08bd703c6ab847ce531c5b65ee80e50 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 31 Mar 2022 21:24:29 +0900 Subject: [PATCH 2625/3664] [vulkan] Use host-cached memory for captures This takes simply reading the transfer buffer from about 400ms down to about 3ms (for 1920x1080 rgba). PNG compression is now the bottleneck. --- libs/video/renderer/vulkan/capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c index f0a2038e5..a7c190fe9 100644 --- a/libs/video/renderer/vulkan/capture.c +++ b/libs/video/renderer/vulkan/capture.c @@ -104,7 +104,7 @@ QFV_CreateCapture (qfv_device_t *device, int numframes, capture->memsize = numframes * image_size; capture->memory = QFV_AllocImageMemory (device, capture->image_set->a[0].image, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, capture->memsize, 0); byte *data; dfunc->vkMapMemory (device->dev, capture->memory, 0, capture->memsize, 0, From 0880fab909e007be248e75f5d7c7b623059c2bc5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 00:58:14 +0900 Subject: [PATCH 2626/3664] [nq,qw] Get demo capture working again It turns it it had been broken for some time: it was attempting to write the files to the wrong place. --- nq/include/client.h | 2 +- nq/source/host.c | 27 ++++++++++++++++----------- qw/include/client.h | 2 +- qw/source/cl_main.c | 27 ++++++++++++++++----------- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index 28394ce52..3096f6321 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -103,7 +103,7 @@ typedef struct { QFile *demofile; qboolean demorecording; - qboolean demo_capture; + int demo_capture; qboolean demoplayback; int forcetrack; // -1 = use normal cd track qboolean timedemo; diff --git a/nq/source/host.c b/nq/source/host.c index b34feedde..d19d30114 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -633,6 +633,19 @@ Host_ClientFrame (void) } } +static void +write_capture (tex_t *tex, void *data) +{ + QFile *file = QFS_Open (va (0, "%s/qfmv%06d.png", + qfs_gamedir->dir.shots, + cls.demo_capture++), "wb"); + if (file) { + WritePNG (file, tex); + Qclose (file); + } + free (tex); +} + /* Host_Frame @@ -699,19 +712,11 @@ _Host_Frame (float time) Host_ClientFrame (); else host_time += host_frametime; //FIXME is this needed? vcr stuff -#if 0 + if (cls.demo_capture) { - tex_t *tex = r_funcs->SCR_CaptureBGR (); - QFile *file = Qopen (va (0, "%s/qfmv%06d.png", - qfs_gamedir->dir.shots, - cls.demo_capture++), "wb"); - if (file) { - WritePNG (file, tex->data, tex->width, tex->height); - Qclose (file); - } - free (tex); + r_funcs->capture_screen (write_capture, 0); } -#endif + host_framecount++; fps_count++; } diff --git a/qw/include/client.h b/qw/include/client.h index 6355b1921..57b87f514 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -136,7 +136,7 @@ typedef struct { QFile *demofile; qboolean demorecording; - qboolean demo_capture; + int demo_capture; qboolean demoplayback; qboolean demoplayback2; qboolean findtrack; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index ea89cb825..c70a137ef 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1617,6 +1617,19 @@ Host_SimulationTime (float time) return 0; } +static void +write_capture (tex_t *tex, void *data) +{ + QFile *file = QFS_Open (va (0, "%s/qfmv%06d.png", + qfs_gamedir->dir.shots, + cls.demo_capture++), "wb"); + if (file) { + WritePNG (file, tex); + Qclose (file); + } + free (tex); +} + int nopacketcount; /* @@ -1749,19 +1762,11 @@ Host_Frame (float time) Sys_Printf ("%3i tot %3i server %3i gfx %3i snd\n", pass1 + pass2 + pass3, pass1, pass2, pass3); } -#if 0 + if (cls.demo_capture) { - tex_t *tex = r_funcs->SCR_CaptureBGR (); - QFile *file = Qopen (va (0, "%s/qfmv%06d.png", - qfs_gamedir->dir.shots, cls.demo_capture++), - "wb"); - if (file) { - WritePNG (file, tex->data, tex->width, tex->height); - Qclose (file); - } - free (tex); + r_funcs->capture_screen (write_capture, 0); } -#endif + host_framecount++; fps_count++; } From ddfacf61ee613849c1e2391d30e1d2bf8898d80a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 02:04:24 +0900 Subject: [PATCH 2627/3664] [qw] Get remote screen shots working again Probably better than they ever have, really, since I think they were broken for one renderer or another. --- include/QF/screen.h | 2 - libs/video/renderer/r_screen.c | 146 ------------------------ qw/source/cl_rss.c | 197 +++++++++++++++++++++++++++++---- 3 files changed, 175 insertions(+), 170 deletions(-) diff --git a/include/QF/screen.h b/include/QF/screen.h index 11a591f87..10e0176e1 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -46,8 +46,6 @@ void SCR_SetFOV (float fov); // control whether the 3d viewport is user-controlled or always fullscreen void SCR_SetFullscreen (qboolean fullscreen); void SCR_SetBottomMargin (int lines); -void SCR_DrawStringToSnap (const char *s, struct tex_s *tex, int x, int y); -struct tex_s *SCR_SnapScreen (unsigned width, unsigned height); extern struct cvar_s *hud_fps, *hud_time, *r_timegraph, *r_zgraph; extern int scr_copytop; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index f07a51fd7..86608c069 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -479,152 +479,6 @@ SCR_DrawPause (void) pic); } -/* - Find closest color in the palette for named color -*/ -#if 0 -static int -MipColor (int r, int g, int b) -{ - float bestdist, dist; - int r1, g1, b1, i; - int best = 0; - static int lastbest; - static int lr = -1, lg = -1, lb = -1; - - if (r == lr && g == lg && b == lb) - return lastbest; - - bestdist = 256 * 256 * 3; - - for (i = 0; i < 256; i++) { - int j; - j = i * 3; - r1 = r_data->vid->palette[j] - r; - g1 = r_data->vid->palette[j + 1] - g; - b1 = r_data->vid->palette[j + 2] - b; - dist = r1 * r1 + g1 * g1 + b1 * b1; - if (dist < bestdist) { - bestdist = dist; - best = i; - } - } - lr = r; - lg = g; - lb = b; - lastbest = best; - return best; -} -#endif - -// in draw.c - -static void -SCR_DrawCharToSnap (int num, byte *dest, int width) -{ - byte *source; - int col, row, drawline, x; - - row = num >> 4; - col = num & 15; - source = draw_chars + (row << 10) + (col << 3); - - drawline = 8; - - while (drawline--) { - for (x = 0; x < 8; x++) - if (source[x]) - dest[x] = source[x]; - else - dest[x] = 98; - source += 128; - dest -= width; - } - -} - -void -SCR_DrawStringToSnap (const char *s, tex_t *tex, int x, int y) -{ - byte *dest; - byte *buf = tex->data; - const unsigned char *p; - int width = tex->width; - - dest = buf + ((y * width) + x); - - p = (const unsigned char *) s; - while (*p) { - SCR_DrawCharToSnap (*p++, dest, width); - dest += 8; - } -} - -tex_t * -SCR_SnapScreen (unsigned width, unsigned height) -{ - return 0; -#if 0 - byte *src, *dest; - float fracw, frach; - unsigned count, dex, dey, dx, dy, nx, r, g, b, x, y, w, h; - tex_t *tex; - - tex_t *snap = r_funcs->SCR_CaptureBGR (); - - //FIXME casts - w = ((unsigned)snap->width < width) ? (unsigned)snap->width : width; - h = ((unsigned)snap->height < height) ? (unsigned)snap->height : height; - - fracw = (float) snap->width / (float) w; - frach = (float) snap->height / (float) h; - - tex = malloc (sizeof (tex_t) + w * h); - tex->data = (byte *) (tex + 1); - if (!tex) - return 0; - - tex->width = w; - tex->height = h; - tex->palette = r_data->vid->palette; - - for (y = 0; y < h; y++) { - dest = tex->data + (w * y); - - for (x = 0; x < w; x++) { - r = g = b = 0; - - dx = x * fracw; - dex = (x + 1) * fracw; - if (dex == dx) - dex++; // at least one - dy = y * frach; - dey = (y + 1) * frach; - if (dey == dy) - dey++; // at least one - - count = 0; - for (; dy < dey; dy++) { - src = snap->data + (snap->width * 3 * dy) + dx * 3; - for (nx = dx; nx < dex; nx++) { - b += *src++; - g += *src++; - r += *src++; - count++; - } - } - r /= count; - g /= count; - b /= count; - *dest++ = MipColor (r, g, b); - } - } - free (snap); - - return tex; -#endif -} - static void viewsize_listener (void *data, const cvar_t *cvar) { diff --git a/qw/source/cl_rss.c b/qw/source/cl_rss.c index ad519418a..b5974ba53 100644 --- a/qw/source/cl_rss.c +++ b/qw/source/cl_rss.c @@ -45,41 +45,180 @@ #include "qw/include/cl_parse.h" #include "qw/include/client.h" -void -CL_RSShot_f (void) +/* + Find closest color in the palette for named color +*/ +static int +rgb_palette (int r, int g, int b, int bgr) +{ + float bestdist, dist; + int r1, g1, b1, i; + int best = 0; + static int lastbest; + static int lr = -1, lg = -1, lb = -1; + + if (bgr) { + int t = r; + r = b; + b = t; + } + + if (r == lr && g == lg && b == lb) + return lastbest; + + bestdist = 256 * 256 * 3; + + for (i = 0; i < 256; i++) { + int j; + j = i * 3; + r1 = r_data->vid->palette[j] - r; + g1 = r_data->vid->palette[j + 1] - g; + b1 = r_data->vid->palette[j + 2] - b; + dist = r1 * r1 + g1 * g1 + b1 * b1; + if (dist < bestdist) { + bestdist = dist; + best = i; + } + } + lr = r; + lg = g; + lb = b; + lastbest = best; + return best; +} + +static void +snap_drawchar (int num, byte *dest, int width) +{ + byte *source; + int col, row, drawline, x; + + row = num >> 4; + col = num & 15; + source = draw_chars + (row << 10) + (col << 3); + + drawline = 8; + + while (drawline--) { + for (x = 0; x < 8; x++) + if (source[x]) + dest[x] = source[x]; + else + dest[x] = 98; + source += 128; + dest -= width; + } + +} + +static void +snap_drawstring (const char *s, tex_t *tex, int x, int y) +{ + byte *dest; + byte *buf = tex->data; + const byte *p; + int width = tex->width; + + dest = buf + ((y * width) + x); + + p = (const byte *) s; + while (*p) { + snap_drawchar (*p++, dest, width); + dest += 8; + } +} + +static tex_t * +cruch_snap (tex_t *snap, unsigned width, unsigned height) +{ + byte *src, *dest; + float fracw, frach; + unsigned count, dex, dey, dx, dy, nx, r, g, b, x, y, w, h; + tex_t *tex; + + //FIXME casts + w = ((unsigned)snap->width < width) ? (unsigned)snap->width : width; + h = ((unsigned)snap->height < height) ? (unsigned)snap->height : height; + + fracw = (float) snap->width / (float) w; + frach = (float) snap->height / (float) h; + + tex = malloc (sizeof (tex_t) + w * h); + tex->data = (byte *) (tex + 1); + if (!tex) + return 0; + + tex->width = w; + tex->height = h; + tex->flagbits = 0; + tex->loaded = 1; + tex->flipped = snap->flipped; + tex->palette = r_data->vid->palette; + + for (y = 0; y < h; y++) { + dest = tex->data + (w * y); + + for (x = 0; x < w; x++) { + r = g = b = 0; + + dx = x * fracw; + dex = (x + 1) * fracw; + if (dex == dx) + dex++; // at least one + dy = y * frach; + dey = (y + 1) * frach; + if (dey == dy) + dey++; // at least one + + count = 0; + for (; dy < dey; dy++) { + src = snap->data + (snap->width * 3 * dy) + dx * 3; + for (nx = dx; nx < dex; nx++) { + r += *src++; + g += *src++; + b += *src++; + count++; + } + } + r /= count; + g /= count; + b /= count; + *dest++ = rgb_palette (r, g, b, snap->bgr); + } + } + free (snap); + + return tex; +} + +static int snap_pending; + +static void +snap_capture (tex_t *snap, void *data) { - dstring_t *st; int pcx_len; pcx_t *pcx = 0; - tex_t *tex = 0; - time_t now; - - if (CL_IsUploading ()) - return; // already one pending - if (cls.state < ca_onserver) - return; // must be connected - - Sys_Printf ("Remote screen shot requested.\n"); - - tex = SCR_SnapScreen (RSSHOT_WIDTH, RSSHOT_HEIGHT); + tex_t *tex = cruch_snap (snap, RSSHOT_WIDTH, RSSHOT_HEIGHT); + snap_pending = 0; if (tex) { + time_t now; time (&now); - st = dstring_strdup (ctime (&now)); + dstring_t *st = dstring_strdup (ctime (&now)); dstring_snip (st, strlen (st->str) - 1, 1); - SCR_DrawStringToSnap (st->str, tex, tex->width - strlen (st->str) * 8, - tex->height - 1); + snap_drawstring (st->str, tex, tex->width - strlen (st->str) * 8, + tex->height - 1); dstring_copystr (st, cls.servername->str); - SCR_DrawStringToSnap (st->str, tex, tex->width - strlen (st->str) * 8, - tex->height - 11); + snap_drawstring (st->str, tex, tex->width - strlen (st->str) * 8, + tex->height - 11); dstring_copystr (st, cl_name->string); - SCR_DrawStringToSnap (st->str, tex, tex->width - strlen (st->str) * 8, - tex->height - 21); + snap_drawstring (st->str, tex, tex->width - strlen (st->str) * 8, + tex->height - 21); pcx = EncodePCX (tex->data, tex->width, tex->height, tex->width, - r_data->vid->basepal, true, &pcx_len); + r_data->vid->basepal, tex->flipped, &pcx_len); free (tex); } if (pcx) { @@ -88,3 +227,17 @@ CL_RSShot_f (void) Sys_Printf ("Sending shot to server...\n"); } } + +void +CL_RSShot_f (void) +{ + if (snap_pending || CL_IsUploading ()) + return; // already one pending + if (cls.state < ca_onserver) + return; // must be connected + + Sys_Printf ("Remote screen shot requested.\n"); + + snap_pending = 1; + r_funcs->capture_screen (snap_capture, 0); +} From 78119aeb7a383253f9201bd81ebc8930b0b63475 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 02:14:05 +0900 Subject: [PATCH 2628/3664] [gamecode] Clean up generated swizzle code --- libs/gamecode/Makemodule.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index d26ac90e7..b3d26d62f 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -52,8 +52,10 @@ BUILT_SOURCES += \ CLEANFILES += \ $(pr_opcode_cinc) \ $(pr_opcode_hinc) \ + $(pr_convert_cinc) \ $(pr_hops_cinc) \ - $(pr_convert_cinc) + $(pr_swizzle32_cinc) \ + $(pr_swizzle64_cinc) $(pr_opcode_cinc): $(opcodes_py) $(V_PY)$(PYTHON) $(opcodes_py) table > $(pr_opcode_cinc).t && \ From c2119f0e24eb8f7d805e0f584ac3057ec180ff28 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 02:35:03 +0900 Subject: [PATCH 2629/3664] Fix a typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d36cd9d8..f0f4e2f55 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Vulkan (very WIP), all within the one executable. Dedicated servers for both Quake (nq-server) and QuakeWorld (qw-server) are included, as well as a master server for QuakeWorld (qw-master). -## Tool +## Tools QuakeForge includes several tools for working with Quake data: - bsp2image produces wireframe images from Quake maps (bsp files) From 56715e6796993fff95e3603cdee310cde5c72bd2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 02:35:03 +0900 Subject: [PATCH 2630/3664] Fix a typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d36cd9d8..f0f4e2f55 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Vulkan (very WIP), all within the one executable. Dedicated servers for both Quake (nq-server) and QuakeWorld (qw-server) are included, as well as a master server for QuakeWorld (qw-master). -## Tool +## Tools QuakeForge includes several tools for working with Quake data: - bsp2image produces wireframe images from Quake maps (bsp files) From 6d0abd42bb84e92c94d5ec07d6dad2e2d765acb1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 15:14:56 +0900 Subject: [PATCH 2631/3664] [vulkan] Use host-cached memory for staging buffers It makes a significant difference to level load times (approximately halves them for demo1 and demo2). Nicely, it turns out I had implemented the rest of the staging buffer code (in particular, flushing) correctly in that it seems there's no corruption any of the data. --- libs/video/renderer/vulkan/staging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 660e61a64..e16aa49df 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -55,7 +55,7 @@ QFV_CreateStagingBuffer (qfv_device_t *device, const char *name, size_t size, QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, stage->buffer, dsprintf (str, "staging:buffer:%s", name)); stage->memory = QFV_AllocBufferMemory (device, stage->buffer, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, size, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, stage->memory, dsprintf (str, "staging:memory:%s", name)); From 42a03758c50b5e38f018b6e1fee6fcbaa4e764b1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 15:25:52 +0900 Subject: [PATCH 2632/3664] [vulkan] Remove redundant entity queue creation I'd missed this when cleaning up entity queue creation for the other renderers. --- libs/video/renderer/vid_render_vulkan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 9c65ef615..2b056e7b1 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -80,7 +80,6 @@ vulkan_ParticleSystem (void) static void vulkan_R_Init (void) { - r_ent_queue = EntQueue_New (mod_num_types); Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx); From 6bbbe4997bde7e6260aca317141c60368f6377ef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 16:19:10 +0900 Subject: [PATCH 2633/3664] [vulkan] Invalidate mapped capture image memory I think I had gotten lucky with captures not being corrupt due to them being much bigger than all but the L3 cache (and then they're over 1/2 the size), so the memory was being automatically invalidated by other activity. Don't want to trust such luck, though. --- include/QF/Vulkan/capture.h | 2 ++ include/QF/Vulkan/funclist.h | 1 + libs/video/renderer/vulkan/capture.c | 22 +++++++++++++++------- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/capture.h b/include/QF/Vulkan/capture.h index a2fa1397b..6cfd9d47e 100644 --- a/include/QF/Vulkan/capture.h +++ b/include/QF/Vulkan/capture.h @@ -23,7 +23,9 @@ typedef struct qfv_capture_s { int canBlit; VkExtent2D extent; qfv_capture_image_set_t *image_set; + size_t imgsize; size_t memsize; + byte *data; VkDeviceMemory memory; } qfv_capture_t; diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 1dec3bcc3..94189143d 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -131,6 +131,7 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkMapMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkUnmapMemory) DEVICE_LEVEL_VULKAN_FUNCTION (vkFlushMappedMemoryRanges) +DEVICE_LEVEL_VULKAN_FUNCTION (vkInvalidateMappedMemoryRanges) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSampler) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateDescriptorSetLayout) diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c index a7c190fe9..d11ea7ad9 100644 --- a/libs/video/renderer/vulkan/capture.c +++ b/libs/video/renderer/vulkan/capture.c @@ -99,22 +99,21 @@ QFV_CreateCapture (qfv_device_t *device, int numframes, image->layout = VK_IMAGE_LAYOUT_UNDEFINED; image->cmd = cmdset->a[i]; } - size_t image_size = QFV_GetImageSize (device, - capture->image_set->a[0].image); - capture->memsize = numframes * image_size; + capture->imgsize = QFV_GetImageSize (device, + capture->image_set->a[0].image); + capture->memsize = numframes * capture->imgsize; capture->memory = QFV_AllocImageMemory (device, capture->image_set->a[0].image, VK_MEMORY_PROPERTY_HOST_CACHED_BIT, capture->memsize, 0); - byte *data; dfunc->vkMapMemory (device->dev, capture->memory, 0, capture->memsize, 0, - (void **) &data); + (void **) &capture->data); for (int i = 0; i < numframes; i++) { __auto_type image = &capture->image_set->a[i]; - image->data = data + i * image_size; + image->data = capture->data + i * capture->imgsize; dfunc->vkBindImageMemory (device->dev, image->image, capture->memory, - image->data - data); + image->data - capture->data); } return capture; } @@ -252,6 +251,15 @@ QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame) const byte * QFV_CaptureData (qfv_capture_t *capture, int frame) { + qfv_device_t *device = capture->device; + qfv_devfuncs_t *dfunc = device->funcs; __auto_type image = &capture->image_set->a[frame]; + VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = capture->memory, + .offset = image->data - capture->data, + .size = capture->imgsize, + }; + dfunc->vkInvalidateMappedMemoryRanges (device->dev, 1, &range); return image->data; } From 03c403610dd77887dd5a06886009a8871e598283 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 16:49:39 +0900 Subject: [PATCH 2634/3664] [vulkan] Safely ignore fisheye and water warp I didn't like the abort (especially having pushed it to master). This takes care of things until I can get them implemented properly (hopefully soon). --- libs/video/renderer/r_screen.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 86608c069..cabd491cc 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -288,7 +288,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) if (r_dowarp) { r_funcs->bind_framebuffer (warp_buffer); } - if (scr_fisheye->int_val) { + if (scr_fisheye->int_val && fisheye_cube_map) { int side = fisheye_cube_map->width; vrect_t feye = { 0, 0, side, side }; r_funcs->set_viewport (&feye); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 2b056e7b1..94ffcc987 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -429,13 +429,13 @@ vulkan_end_frame (void) static framebuffer_t * vulkan_create_cube_map (int size) { - Sys_Error ("not implemented"); + return 0; } static framebuffer_t * vulkan_create_frame_buffer (int width, int height) { - Sys_Error ("not implemented"); + return 0; } static void From 88343d73eaef283f908aab6dd043e53ad1103583 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 16:49:39 +0900 Subject: [PATCH 2635/3664] [vulkan] Safely ignore fisheye and water warp I didn't like the abort (especially having pushed it to master). This takes care of things until I can get them implemented properly (hopefully soon). --- libs/video/renderer/r_screen.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 86608c069..cabd491cc 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -288,7 +288,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) if (r_dowarp) { r_funcs->bind_framebuffer (warp_buffer); } - if (scr_fisheye->int_val) { + if (scr_fisheye->int_val && fisheye_cube_map) { int side = fisheye_cube_map->width; vrect_t feye = { 0, 0, side, side }; r_funcs->set_viewport (&feye); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 9c65ef615..f845ce9c2 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -430,13 +430,13 @@ vulkan_end_frame (void) static framebuffer_t * vulkan_create_cube_map (int size) { - Sys_Error ("not implemented"); + return 0; } static framebuffer_t * vulkan_create_frame_buffer (int width, int height) { - Sys_Error ("not implemented"); + return 0; } static void From 11e30583cf9580e8cf82972dff29dd87ddfb0f1c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 19:50:41 +0900 Subject: [PATCH 2636/3664] [vulkan] Switch to full screen triangle instead of quad While I have trouble imagining it making that much performance difference going from 4 verts to 3 for a whopping 2 polygons, or even from 2 triangles to 1 for each poly, using only indices for the vertices does remove a lot of code, and better yet, some memory and buffer allocations... always a good thing. That said, I guess freeing up a GPU thread for something else could make a difference. --- include/QF/Vulkan/qf_vid.h | 4 +- include/vid_vulkan.h | 3 -- libs/video/renderer/Makemodule.am | 6 +++ libs/video/renderer/vulkan/qfpipeline.plist | 28 ++++++------- libs/video/renderer/vulkan/shader.c | 3 ++ .../renderer/vulkan/shader/fstriangle.vert | 9 +++++ libs/video/renderer/vulkan/vulkan_compose.c | 4 +- libs/video/renderer/vulkan/vulkan_lighting.c | 4 +- .../video/renderer/vulkan/vulkan_vid_common.c | 40 ------------------- 9 files changed, 34 insertions(+), 67 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/fstriangle.vert diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index f729c2b65..bf76b13d2 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -40,8 +40,8 @@ typedef enum { QFV_passDepth, // geometry QFV_passTranslucent, // geometry QFV_passGBuffer, // geometry - QFV_passLighting, // single quad - QFV_passCompose, // single quad + QFV_passLighting, // single triangle + QFV_passCompose, // single triangle QFV_NumPasses } QFV_Subpass; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 56aa8c3f3..7778dda83 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -66,9 +66,6 @@ typedef struct vulkan_ctx_s { struct lightingctx_s *lighting_context; struct composectx_s *compose_context; - VkBuffer quad_buffer; - VkDeviceMemory quad_memory; - VkCommandPool cmdpool; VkCommandBuffer cmdbuffer; VkFence fence; // for ctx->cmdbuffer only diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index bc48a77e2..2743a4a68 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -301,6 +301,8 @@ alias_shadow_src = $(vkshaderpath)/alias_shadow.vert alias_shadow_c = $(vkshaderpath)/alias_shadow.vert.spvc passthrough_src = $(vkshaderpath)/passthrough.vert passthrough_c = $(vkshaderpath)/passthrough.vert.spvc +fstriangle_src = $(vkshaderpath)/fstriangle.vert +fstriangle_c = $(vkshaderpath)/fstriangle.vert.spvc pushcolor_src = $(vkshaderpath)/pushcolor.frag pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc shadow_src = $(vkshaderpath)/shadow.geom @@ -358,6 +360,8 @@ $(alias_shadow_c): $(alias_shadow_src) $(passthrough_c): $(passthrough_src) +$(fstriangle_c): $(fstriangle_src) + $(pushcolor_c): $(pushcolor_src) $(shadow_c): $(shadow_src) @@ -391,6 +395,7 @@ vkshader_c = \ $(alias_gbuf_c) \ $(alias_shadow_c) \ $(passthrough_c) \ + $(fstriangle_c) \ $(pushcolor_c) \ $(shadow_c) @@ -443,6 +448,7 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/compose.frag \ libs/video/renderer/vulkan/shader/lighting.frag \ libs/video/renderer/vulkan/shader/passthrough.vert \ + libs/video/renderer/vulkan/shader/fstriangle.vert \ libs/video/renderer/vulkan/shader/partphysics.comp \ libs/video/renderer/vulkan/shader/partupdate.comp \ libs/video/renderer/vulkan/shader/particle.vert \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 40a28a89a..876613b98 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -559,17 +559,13 @@ }; }; - fsquad = { + fstriangle = { vertexInput = { - bindings = ( - { binding = 0; stride = "4 * 4"; inputRate = vertex; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, - ); + bindings = (); + attributes = (); }; inputAssembly = { - topology = triangle_strip; + topology = triangle_list; primitiveRestartEnable = false; }; colorBlend = { @@ -1008,7 +1004,7 @@ { stage = vertex; name = main; - module = $builtin/passthrough.vert; + module = $builtin/fstriangle.vert; }, { stage = fragment; @@ -1022,13 +1018,13 @@ }; }, ); - vertexInput = $properties.fsquad.vertexInput; - inputAssembly = $properties.fsquad.inputAssembly; + vertexInput = $properties.fstriangle.vertexInput; + inputAssembly = $properties.fstriangle.inputAssembly; viewport = $properties.viewport; rasterization = $properties.rasterization.counter_cw_cull_back; multisample = $properties.multisample; depthStencil = $properties.depthStencil.disable; - colorBlend = $properties.fsquad.colorBlend; + colorBlend = $properties.fstriangle.colorBlend; dynamic = { dynamicState = ( viewport, scissor ); }; @@ -1041,7 +1037,7 @@ { stage = vertex; name = main; - module = $builtin/passthrough.vert; + module = $builtin/fstriangle.vert; }, { stage = fragment; @@ -1049,13 +1045,13 @@ module = $builtin/compose.frag; }, ); - vertexInput = $properties.fsquad.vertexInput; - inputAssembly = $properties.fsquad.inputAssembly; + vertexInput = $properties.fstriangle.vertexInput; + inputAssembly = $properties.fstriangle.inputAssembly; viewport = $properties.viewport; rasterization = $properties.rasterization.counter_cw_cull_back; multisample = $properties.multisample; depthStencil = $properties.depthStencil.disable; - colorBlend = $properties.fsquad.colorBlend; + colorBlend = $properties.fstriangle.colorBlend; dynamic = { dynamicState = ( viewport, scissor ); }; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index a71c83300..8cab2d8a6 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -95,6 +95,8 @@ static static #include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc" static +#include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc" +static #include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc" static #include "libs/video/renderer/vulkan/shader/shadow.geom.spvc" @@ -134,6 +136,7 @@ static shaderdata_t builtin_shaders[] = { { "alias_gbuf.frag", alias_gbuf_frag, sizeof (alias_gbuf_frag) }, { "alias_shadow.vert", alias_shadow_vert, sizeof (alias_shadow_vert) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, + { "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, { "shadow.geom", shadow_geom, sizeof (shadow_geom) }, {} diff --git a/libs/video/renderer/vulkan/shader/fstriangle.vert b/libs/video/renderer/vulkan/shader/fstriangle.vert new file mode 100644 index 000000000..66c55d6ac --- /dev/null +++ b/libs/video/renderer/vulkan/shader/fstriangle.vert @@ -0,0 +1,9 @@ +#version 450 + +void +main () +{ + float x = (gl_VertexIndex & 2); + float y = (gl_VertexIndex & 1); + gl_Position = vec4 (2, 4, 0, 1) * vec4 (x, y, 0, 1) - vec4 (1, 1, 0, 0); +} diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 161012ae0..9da079647 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -105,9 +105,7 @@ Vulkan_Compose_Draw (qfv_renderframe_t *rFrame) dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); - VkDeviceSize offset = 0; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); - dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); + dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 83a8ee061..03a6b3501 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -260,9 +260,7 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); - VkDeviceSize offset = 0; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &ctx->quad_buffer, &offset); - dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); + dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index d5cbcfaf6..bfbc69e03 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -446,43 +446,6 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) rp->draw = renderpass_draw; DARRAY_APPEND (&ctx->renderPasses, rp); - - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - static float quad_vertices[] = { - -1, -1, 0, 1, - -1, 1, 0, 1, - 1, -1, 0, 1, - 1, 1, 0, 1, - }; - ctx->quad_buffer = QFV_CreateBuffer (device, sizeof (quad_vertices), - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT - | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - ctx->quad_memory = QFV_AllocBufferMemory (device, ctx->quad_buffer, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - 0, 0); - QFV_BindBufferMemory (device, ctx->quad_buffer, ctx->quad_memory, 0); - - qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); - float *verts = QFV_PacketExtend (packet, sizeof (quad_vertices)); - memcpy (verts, quad_vertices, sizeof (quad_vertices)); - - qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; - bb.barrier.buffer = ctx->quad_buffer; - bb.barrier.size = sizeof (quad_vertices); - dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, - 0, 0, 0, 1, &bb.barrier, 0, 0); - VkBufferCopy copy_region[] = { - { packet->offset, 0, sizeof (quad_vertices) }, - }; - dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, - ctx->quad_buffer, 1, ©_region[0]); - bb = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead]; - bb.barrier.buffer = ctx->quad_buffer; - bb.barrier.size = sizeof (quad_vertices); - dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, - 0, 0, 0, 1, &bb.barrier, 0, 0); - QFV_PacketSubmit (packet); } static void @@ -542,9 +505,6 @@ Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) free (rp); } - - dfunc->vkFreeMemory (device->dev, ctx->quad_memory, 0); - dfunc->vkDestroyBuffer (device->dev, ctx->quad_buffer, 0); } VkPipeline From 9892e571ce5afdaccd65dbf410c2a42079a26344 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 20:34:41 +0900 Subject: [PATCH 2637/3664] [vulkan] Move viewport and scissor into qfv_renderpass_t This makes much more sense as they are intimately tied to the frame buffer on which a render pass is working. Now, just the window width and height are stored in vulkan_ctx_t. As a side benefit, QFV_CreateSwapchain no long references viddef (now just palette and conview in vulkan_draw.c to go). --- include/QF/Vulkan/renderpass.h | 2 ++ include/vid_vulkan.h | 5 +++-- libs/video/renderer/vulkan/swapchain.c | 2 +- libs/video/renderer/vulkan/vulkan_alias.c | 6 +++--- libs/video/renderer/vulkan/vulkan_bsp.c | 4 ++-- libs/video/renderer/vulkan/vulkan_compose.c | 4 ++-- libs/video/renderer/vulkan/vulkan_draw.c | 4 ++-- libs/video/renderer/vulkan/vulkan_lighting.c | 4 ++-- libs/video/renderer/vulkan/vulkan_sprite.c | 4 ++-- libs/video/renderer/vulkan/vulkan_vid_common.c | 5 +++++ libs/video/targets/vid_x11_vulkan.c | 6 ++---- 11 files changed, 26 insertions(+), 20 deletions(-) diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index 31ea607ca..5e3daaa26 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -70,6 +70,8 @@ typedef struct qfv_renderpass_s { VkDeviceMemory attachmentMemory; qfv_framebufferset_t *framebuffers; + VkViewport viewport; + VkRect2D scissor; qfv_renderframeset_t frames; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 7778dda83..56516113f 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -85,8 +85,9 @@ typedef struct vulkan_ctx_s { struct qfv_tex_s *default_magenta; struct qfv_tex_s *default_magenta_array; - VkViewport viewport; - VkRect2D scissor; + // size of window + int window_width; + int window_height; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 20766233a..aa09a6db6 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -62,7 +62,7 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) numImages = surfCaps.maxImageCount; } - VkExtent2D imageSize = {viddef.width, viddef.height}; + VkExtent2D imageSize = {ctx->window_width, ctx->window_height}; if (surfCaps.currentExtent.width == ~0u) { imageSize.width = bound (surfCaps.minImageExtent.width, imageSize.width, diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 95bc262fb..8da5de204 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -206,8 +206,8 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->layout, 0, 1, sets, 0, 0); - dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -261,7 +261,7 @@ Vulkan_AliasDepthRange (qfv_renderframe_t *rFrame, aliasctx_t *actx = ctx->alias_context; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - VkViewport viewport = ctx->viewport; + VkViewport viewport = rFrame->renderpass->viewport; viewport.minDepth = minDepth; viewport.maxDepth = maxDepth; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a29ba4742..a6047f57b 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -853,8 +853,8 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); VkDeviceSize offsets[] = { 0 }; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &bctx->vertex_buffer, offsets); diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 9da079647..6d8ad105e 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -102,8 +102,8 @@ Vulkan_Compose_Draw (qfv_renderframe_t *rFrame) dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, cctx->layout, 0, 1, sets, 0, 0); - dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index a936f0b6f..24c11db91 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -840,8 +840,8 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dctx->pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); VkDeviceSize offsets[] = {dframe->vert_offset}; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets); dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 03a6b3501..83e7e6fdc 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -257,8 +257,8 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, lctx->layout, 0, 3, sets, 0, 0); - dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index c01ddb329..b0d9866cd 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -168,8 +168,8 @@ sprite_begin_subpass (QFV_SpriteSubpass subpass, VkPipeline pipeline, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, sctx->layout, 0, 1, sets, 0, 0); - dfunc->vkCmdSetViewport (cmd, 0, 1, &ctx->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &ctx->scissor); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index bfbc69e03..193f09e12 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -432,6 +432,11 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) name)); } + int width = ctx->window_width; + int height = ctx->window_height; + rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; + rp->scissor = (VkRect2D) { {0, 0}, {width, height} }; + DARRAY_INIT (&rp->frames, 4); DARRAY_RESIZE (&rp->frames, ctx->frames.size); for (size_t i = 0; i < rp->frames.size; i++) { diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index 39bf90310..1e9d39087 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -194,10 +194,8 @@ x11_vulkan_create_surface (vulkan_ctx_t *ctx) .window = pres->window }; - int width = viddef.width; - int height = viddef.height; - ctx->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; - ctx->scissor = (VkRect2D) { {0, 0}, {width, height} }; + ctx->window_width = viddef.width; + ctx->window_height = viddef.height; if (pres->vkCreateXlibSurfaceKHR (inst, &createInfo, 0, &surface) != VK_SUCCESS) { From 9b11992de4abcfc6cee6fb04b9ceb2d5de163d11 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Apr 2022 10:53:23 +0900 Subject: [PATCH 2638/3664] [plist] Fix some typos and improve plfield_t's docs --- include/QF/plist.h | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/include/QF/plist.h b/include/QF/plist.h index c83f8d5a3..72b09682b 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -67,12 +67,12 @@ struct plfield_s; dictionary objects. If null, then the default parser for the object type is used: - * QFString: the point to the actual string. The string continues - to be owned by the string object. + * QFString: pointer to the actual string. The string continues to + be owned by the string object. * QFBinary: pointer to fixed-size DARRAY_TYPE(byte) (so size isn't lost) * QFArray: pointer to fixed-size DARRAY_TYPE(plitem_t *) with the - indivisual objects. The individual objects continue to be owned + individual objects. The individual objects continue to be owned by the array object. * QFDictionary: pointer to the hashtab_t hash table used for the dictionary object. The hash table continues to be owned by the @@ -86,7 +86,9 @@ struct plfield_s; checking is done: it is up to the top-level caller to parse out the messages. \param context Additional context data passed to the parser. - \return 0 for error, 1 for success. See \a PL_ParseDictionary. + \return 0 for error, 1 for success. See \a PL_ParseStruct, + \a PL_ParseArray, \a PL_ParseLabeledArray, and + \a PL_ParseSymtab. */ typedef int (*plparser_t) (const struct plfield_s *field, const struct plitem_s *item, @@ -96,7 +98,15 @@ typedef int (*plparser_t) (const struct plfield_s *field, /** A field to be parsed from a dictionary item. - something + \a PL_ParseStruct uses an array (terminated by an element with \a name + set to null) of these to describe the fields in the structure being + parsed. + + \a PL_ParseArray, \a PL_ParseLabeledArray, and \a PL_ParseSymtab use only + a single \a plfield_t object, and then only the \a data field, which must + point to a \a plelement_t object. This allows all the parse functions to + be used directly as either a \a plfield_t or \a plelement_t object's + \a parser. */ typedef struct plfield_s { const char *name; ///< matched by dictionary key From bbbdc41af30b7c9bb093d75b07f53d85a71a6d6c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Apr 2022 11:42:36 +0900 Subject: [PATCH 2639/3664] [vulkan] Break render pass parsing away from swapchain This allows a single render pass description to be used for both on-screen and off-screen targets. While Vulkan does allow a VkRenderPass to be used with any compatible frame buffer, and vkparse caches a VkRenderPass created from the same description, this allows the same description to be used for a compatible off-screen target without any dependence on the swapchain. However, there is a problem in the caching when it comes to targeting outputs with different formats. --- include/vid_vulkan.h | 10 ++ libs/video/renderer/vulkan/deferred.plist | 40 +++---- libs/video/renderer/vulkan/vkparse.c | 104 +++++------------- libs/video/renderer/vulkan/vkparse.h | 12 -- .../video/renderer/vulkan/vulkan_vid_common.c | 11 +- 5 files changed, 66 insertions(+), 111 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 56516113f..b23654ef5 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -9,6 +9,13 @@ #include "QF/darray.h" #include "QF/simd/types.h" +//FIXME name +typedef struct qfv_output_s { + VkExtent2D extent; + VkImageView view; + VkFormat format; +} qfv_output_t; + typedef struct vulkan_frame_s { VkFramebuffer framebuffer; VkFence fence; @@ -89,6 +96,9 @@ typedef struct vulkan_ctx_s { int window_width; int window_height; + //FIXME not sure I like it being here (also, type name) + qfv_output_t output; + #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 1eade9e2e..c5ce13c0f 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -5,8 +5,8 @@ format = x8_d24_unorm_pack32; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -20,8 +20,8 @@ format = r8g8b8a8_unorm; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -35,8 +35,8 @@ format = r16g16b16a16_sfloat; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -50,8 +50,8 @@ format = r16g16b16a16_sfloat; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -65,8 +65,8 @@ format = r32g32b32a32_sfloat; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -80,8 +80,8 @@ format = r8g8b8a8_unorm; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -95,8 +95,8 @@ format = r8g8b8a8_unorm; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -223,9 +223,9 @@ framebuffer = { renderPass = $properties.renderpass; attachments = (depth, color, emission, normal, position, opaque, - translucent, "$swapchain.views[$swapImageIndex]"); - width = $swapchain.extent.width; - height = $swapchain.extent.height; + translucent, $output.view); + width = $output.extent.width; + height = $output.extent.height; layers = 1; }; clearValues = ( @@ -236,7 +236,7 @@ { color = "[0, 0, 0, 1]"; }, // position { color = "[0, 0, 0, 1]"; }, // opaque { color = "[0, 0, 0, 0]"; }, // translucent - { color = "[0, 0, 0, 1]"; }, // swapchain + { color = "[0, 0, 0, 1]"; }, // output ); renderpass = { attachments = ( @@ -311,7 +311,7 @@ finalLayout = color_attachment_optimal; }, { - format = $swapchain.format; + format = $output.format; samples = 1; loadOp = clear; storeOp = store; @@ -414,7 +414,7 @@ }, ); colorAttachments = ( - { // swapchain + { // output attachment = 7; layout = color_attachment_optimal; }, diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 79c6811e3..97fdd813d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -42,8 +42,8 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/pipeline.h" +#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/shader.h" -#include "QF/Vulkan/swapchain.h" #include "vid_vulkan.h" @@ -51,6 +51,17 @@ #include "vkparse.h" #undef vkparse_internal +typedef struct parseres_s { + const char *name; + plfield_t *field; + size_t offset; +} parseres_t; + +typedef struct handleref_s { + char *name; + uint64_t handle; +} handleref_t; + static void flag_or (const exprval_t *val1, const exprval_t *val2, exprval_t *result, exprctx_t *ctx) { @@ -577,7 +588,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, return ret; } -static exprtype_t imageview_type = { +exprtype_t VkImageView_type = { "VkImageView", sizeof (VkImageView), 0, 0, 0 @@ -610,7 +621,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, plitem_t *imageViewItem = 0; if (ret) { VkImageView imageView; - if (value->type == &imageview_type) { + if (value->type == &VkImageView_type) { imageView = *(VkImageView *) value->value; } else if (value->type == &cexpr_plitem) { imageView = QFV_ParseImageView (ctx, imageViewItem, @@ -856,82 +867,21 @@ parse_specialization_data (const plitem_t *item, void **data, #include "libs/video/renderer/vulkan/vkparse.cinc" -static void -imageviewset_index (const exprval_t *a, size_t index, exprval_t *c, - exprctx_t *ctx) -{ - __auto_type set = *(qfv_imageviewset_t **) a->value; - exprval_t *val = 0; - if (index >= set->size) { - cexpr_error (ctx, "invalid index: %zd", index); - } else { - val = cexpr_value (&imageview_type, ctx); - *(VkImageView *) val->value = set->a[index]; - } - *(exprval_t **) c->value = val; -} - -static void -imageviewset_int (const exprval_t *a, const exprval_t *b, exprval_t *c, - exprctx_t *ctx) -{ - size_t index = *(int *) b->value; - imageviewset_index (a, index, c, ctx); -} - -static void -imageviewset_uint (const exprval_t *a, const exprval_t *b, exprval_t *c, - exprctx_t *ctx) -{ - size_t index = *(unsigned *) b->value; - imageviewset_index (a, index, c, ctx); -} - -static void -imageviewset_size_t (const exprval_t *a, const exprval_t *b, exprval_t *c, - exprctx_t *ctx) -{ - size_t index = *(size_t *) b->value; - imageviewset_index (a, index, c, ctx); -} - -binop_t imageviewset_binops[] = { - { '.', &cexpr_field, &cexpr_exprval, cexpr_struct_pointer_getfield }, - { '[', &cexpr_int, &imageview_type, imageviewset_int }, - { '[', &cexpr_uint, &imageview_type, imageviewset_uint }, - { '[', &cexpr_size_t, &imageview_type, imageviewset_size_t }, - {} -}; - -static exprsym_t imageviewset_symbols[] = { - {"size", &cexpr_size_t, (void *)field_offset (qfv_imageviewset_t, size)}, +static exprsym_t qfv_output_t_symbols[] = { + {"format", &VkFormat_type, (void *)field_offset (qfv_output_t, format)}, + {"extent", &VkExtent2D_type, (void *)field_offset (qfv_output_t, extent)}, + {"view", &VkImageView_type, (void *)field_offset (qfv_output_t, view)}, { } }; -static exprtab_t imageviewset_symtab = { - imageviewset_symbols, +static exprtab_t qfv_output_t_symtab = { + qfv_output_t_symbols, }; -exprtype_t imageviewset_type = { - "imageviewset", - sizeof (qfv_imageviewset_t *), - imageviewset_binops, - 0, - &imageviewset_symtab, -}; -static exprsym_t qfv_swapchain_t_symbols[] = { - {"format", &VkFormat_type, (void *)field_offset (qfv_swapchain_t, format)}, - {"extent", &VkExtent2D_type, (void *)field_offset (qfv_swapchain_t, extent)}, - {"views", &imageviewset_type, (void *)field_offset (qfv_swapchain_t, imageViews)}, - { } -}; -static exprtab_t qfv_swapchain_t_symtab = { - qfv_swapchain_t_symbols, -}; -exprtype_t qfv_swapchain_t_type = { - "qfv_swapchain_t", - sizeof (qfv_swapchain_t), +exprtype_t qfv_output_t_type = { + "qfv_output_t", + sizeof (qfv_output_t), cexpr_struct_binops, 0, - &qfv_swapchain_t_symtab, + &qfv_output_t_symtab, }; static exprsym_t vulkan_frameset_t_symbols[] = { @@ -1023,9 +973,8 @@ QFV_InitParse (vulkan_ctx_t *ctx) &ctx->hashlinks); context.hashlinks = &ctx->hashlinks; vkgen_init_symtabs (&context); - cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); + cexpr_init_symtab (&qfv_output_t_symtab, &context); cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); - cexpr_init_symtab (&imageviewset_symtab, &context); cexpr_init_symtab (&data_array_symtab, &context); if (!ctx->setLayouts) { @@ -1054,10 +1003,9 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, exprctx_t exprctx = { .symtab = &root_symtab }; parsectx_t parsectx = { &exprctx, ctx, properties }; exprsym_t var_syms[] = { - {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {"output", &qfv_output_t_type, &ctx->output}, {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {"swapImageIndex", &cexpr_uint, &ctx->swapImageIndex}, {"physDevLimits", &VkPhysicalDeviceLimits_type, &ctx->device->physDev->properties.limits }, {QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties}, diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 6f2ea6357..730094e3b 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -10,24 +10,12 @@ typedef struct parsectx_s { #include "QF/cexpr.h" #include "QF/plist.h" -#include "QF/Vulkan/renderpass.h" #ifdef vkparse_internal #include "libs/video/renderer/vulkan/vkparse.hinc" #endif #define QFV_PROPERTIES "properties" -typedef struct parseres_s { - const char *name; - plfield_t *field; - size_t offset; -} parseres_t; - -typedef struct handleref_s { - char *name; - uint64_t handle; -} handleref_t; - void QFV_InitParse (vulkan_ctx_t *ctx); exprenum_t *QFV_GetEnum (const char *name); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 193f09e12..06ba768f0 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -388,7 +388,11 @@ create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, malloc); for (size_t i = 0; i < rp->framebuffers->size; i++) { - ctx->swapImageIndex = i; // for $swapImageIndex in the config + ctx->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[i], + .format = ctx->swapchain->format, + }; rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, rp->renderpassDef); } @@ -424,6 +428,11 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) if (renderpass) { rp->renderpass = renderpass; } else { + ctx->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[0], + .format = ctx->swapchain->format, + }; item = qfv_load_renderpass (ctx, rp, name); rp->renderpass = QFV_ParseRenderPass (ctx, item, rp->renderpassDef); QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); From eb4d5668011bb26443add0ed8582291544c10c75 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 3 Apr 2022 11:11:28 +0900 Subject: [PATCH 2640/3664] [vkparse] Add support for inheriting objects It simply parses the referenced plist dictionary (via @inherit = plist.path;) into the current data block, then allows the data to be overwritten by the current plist dictionary. This may be a bit iffy for any allocated resources, so some care must be taken, but it seems to work nicely. --- libs/video/renderer/vulkan/vkgen/vkstruct.r | 3 +++ libs/video/renderer/vulkan/vkparse.c | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 500659bc0..cd580849b 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -130,6 +130,9 @@ [field_def writeParseData]; } fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self outname]); + fprintf (output_file, + "\t{\"@inherit\", 0, QFString, parse_inherit, &%s_fields},\n", + [self outname]); for (int i = [field_defs count]; i-- > 0; ) { FieldDef *field_def = [field_defs objectAtIndex:i]; [field_def writeField]; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 97fdd813d..e6c084672 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -376,6 +376,24 @@ parse_custom (const plfield_t *field, const plitem_t *item, return custom->parse (item, offsets, messages, context); } +static int +parse_inherit (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + exprctx_t ectx = *((parsectx_t *)context)->ectx; + plitem_t *inheritItem = 0; + exprval_t result = { &cexpr_plitem, &inheritItem }; + ectx.result = &result; + const char *inheritstr = PL_String (item); + Sys_MaskPrintf (SYS_vulkan_parse, "parse_inherit: %s\n", inheritstr); + int ret = !cexpr_eval_string (inheritstr, &ectx); + if (ret) { + ret = PL_ParseStruct (field->data, inheritItem, data, messages, + context); + } + return ret; +} + static int parse_RGBA (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context) From 39e7c4a9b2daff1756697db81f11c4bbdc7efb94 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 3 Apr 2022 11:47:53 +0900 Subject: [PATCH 2641/3664] [vulkan] Use a template for the deferred image views That certainly makes it nicer to work with large sets, and shows one way to be careful with allocated resources: don't allocate them in the inherited data and use a template that needs a few things filled in to be valid. Also, it seems that overriding values in sub-structures "just works" :) --- libs/video/renderer/vulkan/deferred.plist | 102 +++++----------------- 1 file changed, 21 insertions(+), 81 deletions(-) diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index c5ce13c0f..ad1d7df68 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -106,118 +106,58 @@ initialLayout = undefined; }; }; + flat_color_view_template = { + viewType = VK_IMAGE_VIEW_TYPE_2D; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; imageViews = { depth = { + @inherit = $properties.flat_color_view_template; image = depth; - viewType = VK_IMAGE_VIEW_TYPE_2D; format = $properties.images.depth.format; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; subresourceRange = { aspectMask = depth; - levelCount = 1; - layerCount = 1; }; }; color = { + @inherit = $properties.flat_color_view_template; image = color; - viewType = VK_IMAGE_VIEW_TYPE_2D; format = $properties.images.color.format; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; }; emission = { + @inherit = $properties.flat_color_view_template; image = emission; - viewType = VK_IMAGE_VIEW_TYPE_2D; format = $properties.images.emission.format; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; }; normal = { + @inherit = $properties.flat_color_view_template; image = normal; - viewType = VK_IMAGE_VIEW_TYPE_2D; format = $properties.images.normal.format; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; }; position = { + @inherit = $properties.flat_color_view_template; image = position; - viewType = VK_IMAGE_VIEW_TYPE_2D; format = $properties.images.position.format; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; }; opaque = { + @inherit = $properties.flat_color_view_template; image = opaque; - viewType = VK_IMAGE_VIEW_TYPE_2D; format = $properties.images.opaque.format; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; }; translucent = { + @inherit = $properties.flat_color_view_template; image = translucent; - viewType = VK_IMAGE_VIEW_TYPE_2D; format = $properties.images.translucent.format; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; }; }; framebuffer = { From d3d081ea0a9294fb588abbad20fdc730469c8768 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 3 Apr 2022 12:02:13 +0900 Subject: [PATCH 2642/3664] [vulkan] Switch deferred opaque attachment to f16 rgb While looking at the deferred attachment images with using a template in mind, I noticed that the opaque attachment was using 8-bit color. The problem is, it's meant to be HDRI with the compose pass crunching it down to LDRI. Switching to 16-bit float does seem to have made a subtle difference (hey, it's still quake data, not much HDRI in there). --- libs/video/renderer/vulkan/deferred.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index ad1d7df68..e70a1bc27 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -77,7 +77,7 @@ }; opaque = { imageType = `2d; - format = r8g8b8a8_unorm; + format = r16g16b16a16_sfloat; samples = 1; extent = { width = $output.extent.width; From c8e299ca58c6cdb3c1a5a53e040b1e40478fdd16 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 3 Apr 2022 12:25:04 +0900 Subject: [PATCH 2643/3664] [vulkan] Use a template for the deferred attachment images It's certainly much easier to read and see what's different between the attachment. --- libs/video/renderer/vulkan/deferred.plist | 104 +++++----------------- 1 file changed, 21 insertions(+), 83 deletions(-) diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index e70a1bc27..74c3e7743 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -1,109 +1,47 @@ { + flat_color_image_template = { + imageType = `2d; + samples = 1; + extent = { + width = $output.extent.width; + height = $output.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment|transient_attachment; + initialLayout = undefined; + }; images = { depth = { - imageType = `2d; + @inherit = $properties.flat_color_image_template; format = x8_d24_unorm_pack32; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; usage = depth_stencil_attachment|input_attachment|transient_attachment; - initialLayout = undefined; }; color = { - imageType = `2d; + @inherit = $properties.flat_color_image_template; format = r8g8b8a8_unorm; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; }; emission = { - imageType = `2d; + @inherit = $properties.flat_color_image_template; format = r16g16b16a16_sfloat; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; }; normal = { - imageType = `2d; + @inherit = $properties.flat_color_image_template; format = r16g16b16a16_sfloat; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; }; position = { - imageType = `2d; + @inherit = $properties.flat_color_image_template; format = r32g32b32a32_sfloat; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; }; opaque = { - imageType = `2d; + @inherit = $properties.flat_color_image_template; format = r16g16b16a16_sfloat; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; }; translucent = { - imageType = `2d; + @inherit = $properties.flat_color_image_template; format = r8g8b8a8_unorm; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; }; }; flat_color_view_template = { From f66df59c43f5c31d3130785fe264331c346236a0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 3 Apr 2022 13:15:30 +0900 Subject: [PATCH 2644/3664] [vulkan] Use a template for the attachment desciptions --- libs/video/renderer/vulkan/deferred.plist | 65 ++++++----------------- 1 file changed, 17 insertions(+), 48 deletions(-) diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 74c3e7743..f846b1799 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -116,86 +116,55 @@ { color = "[0, 0, 0, 0]"; }, // translucent { color = "[0, 0, 0, 1]"; }, // output ); + attachment_template = { + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }; renderpass = { attachments = ( { + @inherit = $properties.attachment_template; format = $properties.images.depth.format; - samples = 1; loadOp = clear; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; finalLayout = depth_stencil_attachment_optimal; }, { + @inherit = $properties.attachment_template; format = $properties.images.color.format; - samples = 1; loadOp = clear; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; }, { + @inherit = $properties.attachment_template; format = $properties.images.emission.format; - samples = 1; loadOp = clear; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; }, { + @inherit = $properties.attachment_template; format = $properties.images.normal.format; - samples = 1; - loadOp = dont_care; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; }, { + @inherit = $properties.attachment_template; format = $properties.images.position.format; - samples = 1; - loadOp = dont_care; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; }, { + @inherit = $properties.attachment_template; format = $properties.images.opaque.format; - samples = 1; - loadOp = dont_care; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; }, { + @inherit = $properties.attachment_template; format = $properties.images.translucent.format; - samples = 1; loadOp = clear; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; }, { + @inherit = $properties.attachment_template; format = $output.format; - samples = 1; loadOp = clear; storeOp = store; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; finalLayout = present_src_khr; }, ); From e40f3f4f932a2b2c4f16f53a20a84b97f3a3ad2c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Apr 2022 15:38:27 +0900 Subject: [PATCH 2645/3664] [model] Make alias skin loading a batch operation Really, this won't make all that much difference because alias models with more than one skin are quite rare, and those with animated skin groups are even rarer. However, for those models that do have more than one skin, it will allow for reduced allocation overheads, and when supported (glsl, vulkan, maybe gl), loading all the skins into an array texture (since all skins are the same size, though external skins may vary), but that's not implemented yet, this just wraps the old one skin at a time code. --- include/QF/Vulkan/qf_alias.h | 6 ++---- include/QF/plugin/vid_render.h | 4 +--- include/mod_internal.h | 21 ++++++++++++--------- libs/models/alias/gl_model_alias.c | 16 +++++++++++++++- libs/models/alias/glsl_model_alias.c | 16 +++++++++++++++- libs/models/alias/model_alias.c | 25 ++++++++++++++++++++----- libs/models/alias/sw_model_alias.c | 16 +++++++++++++++- libs/models/alias/vulkan_model_alias.c | 19 ++++++++++++++++++- libs/video/renderer/vid_render_gl.c | 2 +- libs/video/renderer/vid_render_glsl.c | 2 +- libs/video/renderer/vid_render_sw.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 11 ++++------- 12 files changed, 105 insertions(+), 35 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 08ca86e94..24f8a6944 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -94,10 +94,8 @@ struct qfv_renderframe_s; struct entity_s; struct mod_alias_ctx_s; -void *Vulkan_Mod_LoadSkin (struct mod_alias_ctx_s *alias_ctx, byte *skin, - int skinsize, int snum, int gnum, qboolean group, - maliasskindesc_t *skindesc, - struct vulkan_ctx_s *ctx); +void Vulkan_Mod_LoadAllSkins (struct mod_alias_ctx_s *alias_ctx, + struct vulkan_ctx_s *ctx); void Vulkan_Mod_FinalizeAliasModel (struct mod_alias_ctx_s *alias_ctx, struct vulkan_ctx_s *ctx); void Vulkan_Mod_LoadExternalSkins (struct mod_alias_ctx_s *alias_ctx, diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 19ed1e394..f63e6b7db 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -58,9 +58,7 @@ typedef struct vid_model_funcs_s { void (*Mod_LoadSpriteModel) (model_t *mod, void *buffer); void (*Mod_MakeAliasModelDisplayLists) (struct mod_alias_ctx_s *alias_ctx, void *_m, int _s, int extra); - void *(*Mod_LoadSkin) (struct mod_alias_ctx_s *alias_ctx, byte *skin, - int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc); + void (*Mod_LoadAllSkins) (struct mod_alias_ctx_s *alias_ctx); void (*Mod_FinalizeAliasModel) (struct mod_alias_ctx_s *alias_ctx); void (*Mod_LoadExternalSkins) (struct mod_alias_ctx_s *alias_ctx); void (*Mod_IQMFinish) (model_t *mod); diff --git a/include/mod_internal.h b/include/mod_internal.h index b54496dc4..af7581266 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -7,9 +7,17 @@ #include "QF/skin.h" #include "QF/plugin/vid_render.h" +typedef struct mod_alias_skin_s { + int skin_num; + int group_num; // -1 if not in an animated group + byte *texels; + maliasskindesc_t *skindesc; +} mod_alias_skin_t; + typedef struct stvertset_s DARRAY_TYPE (stvert_t) stvertset_t; typedef struct mtriangleset_s DARRAY_TYPE (mtriangle_t) mtriangleset_t; typedef struct trivertxset_s DARRAY_TYPE (trivertx_t *) trivertxset_t; +typedef struct askinset_s DARRAY_TYPE (mod_alias_skin_t) askinset_t; typedef struct mod_alias_ctx_s { aliashdr_t *header; @@ -17,6 +25,7 @@ typedef struct mod_alias_ctx_s { stvertset_t stverts; mtriangleset_t triangles; trivertxset_t poseverts; + askinset_t skins; int aliasbboxmins[3]; int aliasbboxmaxs[3]; } mod_alias_ctx_t; @@ -49,27 +58,21 @@ extern vid_model_funcs_t *m_funcs; void gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra); -void *gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, - int snum, int gnum, qboolean group, - maliasskindesc_t *skindesc); +void gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx); void gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx); void gl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx); void gl_Mod_IQMFinish (model_t *mod); void glsl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra); -void *glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, - int snum, int gnum, qboolean group, - maliasskindesc_t *skindesc); +void glsl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx); void glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx); void glsl_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx); void glsl_Mod_IQMFinish (model_t *mod); void sw_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra); -void *sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, - int snum, int gnum, qboolean group, - maliasskindesc_t *skindesc); +void sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx); void sw_Mod_IQMFinish (model_t *mod); void gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp); diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index 85d91c3b2..a3e5047aa 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -52,7 +52,7 @@ #include "compat.h" -void * +static void * gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) @@ -103,6 +103,20 @@ gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, return skin + skinsize; } +void +gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx) +{ + aliashdr_t *header = alias_ctx->header; + int skinsize = header->mdl.skinwidth * header->mdl.skinheight; + + for (size_t i = 0; i < alias_ctx->skins.size; i++) { + __auto_type skin = alias_ctx->skins.a + i; + gl_Mod_LoadSkin (alias_ctx, skin->texels, skinsize, + skin->skin_num, skin->group_num, + skin->group_num != -1, skin->skindesc); + } +} + void gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx) { diff --git a/libs/models/alias/glsl_model_alias.c b/libs/models/alias/glsl_model_alias.c index c48500ad7..f5e74b62f 100644 --- a/libs/models/alias/glsl_model_alias.c +++ b/libs/models/alias/glsl_model_alias.c @@ -90,7 +90,7 @@ glsl_alias_clear (model_t *m, void *data) } } -void * +static void * glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) @@ -114,6 +114,20 @@ glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, return skin + skinsize; } +void +glsl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx) +{ + aliashdr_t *header = alias_ctx->header; + int skinsize = header->mdl.skinwidth * header->mdl.skinheight; + + for (size_t i = 0; i < alias_ctx->skins.size; i++) { + __auto_type skin = alias_ctx->skins.a + i; + glsl_Mod_LoadSkin (alias_ctx, skin->texels, skinsize, + skin->skin_num, skin->group_num, + skin->group_num != -1, skin->skindesc); + } +} + void glsl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx) { diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index aa1186b98..4e1832bd2 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -75,8 +75,14 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins, pskindesc[snum].type = pskintype->type; if (pskintype->type == ALIAS_SKIN_SINGLE) { skin = (byte *) (pskintype + 1); - skin = m_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize, snum, 0, - false, &pskindesc[snum]); + mod_alias_skin_t askin = { + .skin_num = snum, + .group_num = -1, + .texels = skin, + .skindesc = &pskindesc[snum], + }; + skin += skinsize; + DARRAY_APPEND (&alias_ctx->skins, askin); } else { pskintype++; pinskingroup = (daliasskingroup_t *) pskintype; @@ -107,13 +113,20 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins, for (gnum = 0; gnum < groupskins; gnum++) { paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE; - skin = mod_funcs->Mod_LoadSkin (alias_ctx, skin, skinsize, - snum, gnum, true, - &paliasskingroup->skindescs[gnum]); + skin = (byte *) (pskintype + 1); + mod_alias_skin_t askin = { + .skin_num = snum, + .group_num = gnum, + .texels = skin, + .skindesc = &paliasskingroup->skindescs[gnum], + }; + skin += skinsize; + DARRAY_APPEND (&alias_ctx->skins, askin); } } pskintype = (daliasskintype_t *) skin; } + mod_funcs->Mod_LoadAllSkins (alias_ctx); return pskintype; } @@ -232,6 +245,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) DARRAY_INIT (&alias_ctx.poseverts, 256); DARRAY_INIT (&alias_ctx.stverts, 256); DARRAY_INIT (&alias_ctx.triangles, 256); + DARRAY_INIT (&alias_ctx.skins, 256); if (LittleLong (* (unsigned int *) buffer) == HEADER_MDL16) extra = 1; // extra precision bytes @@ -392,4 +406,5 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) DARRAY_CLEAR (&alias_ctx.poseverts); DARRAY_CLEAR (&alias_ctx.stverts); DARRAY_CLEAR (&alias_ctx.triangles); + DARRAY_CLEAR (&alias_ctx.skins); } diff --git a/libs/models/alias/sw_model_alias.c b/libs/models/alias/sw_model_alias.c index 62a559332..cd67e1f3f 100644 --- a/libs/models/alias/sw_model_alias.c +++ b/libs/models/alias/sw_model_alias.c @@ -49,7 +49,7 @@ // an animating sequence of poses -void * +static void * sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc) @@ -64,6 +64,20 @@ sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, return skin + skinsize; } +void +sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx) +{ + aliashdr_t *header = alias_ctx->header; + int skinsize = header->mdl.skinwidth * header->mdl.skinheight; + + for (size_t i = 0; i < alias_ctx->skins.size; i++) { + __auto_type skin = alias_ctx->skins.a + i; + sw_Mod_LoadSkin (alias_ctx, skin->texels, skinsize, + skin->skin_num, skin->group_num, + skin->group_num != -1, skin->skindesc); + } +} + static void process_frame (mod_alias_ctx_t *alias_ctx, maliasframedesc_t *frame, int posenum, int extra) diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 0bda057bb..89cadd84f 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -111,7 +111,7 @@ vulkan_alias_clear (model_t *m, void *data) } } -void * +static void * Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, int snum, int gnum, qboolean group, maliasskindesc_t *skindesc, vulkan_ctx_t *ctx) @@ -228,6 +228,20 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, return skinpix + skinsize; } +void +Vulkan_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx) +{ + aliashdr_t *header = alias_ctx->header; + int skinsize = header->mdl.skinwidth * header->mdl.skinheight; + + for (size_t i = 0; i < alias_ctx->skins.size; i++) { + __auto_type skin = alias_ctx->skins.a + i; + Vulkan_Mod_LoadSkin (alias_ctx, skin->texels, skinsize, + skin->skin_num, skin->group_num, + skin->group_num != -1, skin->skindesc, ctx); + } +} + void Vulkan_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx, vulkan_ctx_t *ctx) { @@ -401,6 +415,9 @@ Vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, for (i = 0; i < numtris; i++) { for (j = 0; j < 3; j++) { int vind = alias_ctx->triangles.a[i].vertindex[j]; + // can't use indexmap to do the test because it indicates only + // that the vertex has been duplicated, not whether or not + // the vertex is the original or the duplicate if (alias_ctx->stverts.a[vind].onseam && !alias_ctx->triangles.a[i].facesfront) { vind = indexmap[vind]; diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 0d5f5b640..1dc1d337b 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -163,7 +163,7 @@ static vid_model_funcs_t model_funcs = { Mod_LoadSpriteModel, gl_Mod_MakeAliasModelDisplayLists, - gl_Mod_LoadSkin, + gl_Mod_LoadAllSkins, gl_Mod_FinalizeAliasModel, gl_Mod_LoadExternalSkins, gl_Mod_IQMFinish, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 5c93e36b1..7297739f7 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -74,7 +74,7 @@ static vid_model_funcs_t model_funcs = { Mod_LoadSpriteModel, glsl_Mod_MakeAliasModelDisplayLists, - glsl_Mod_LoadSkin, + glsl_Mod_LoadAllSkins, glsl_Mod_FinalizeAliasModel, glsl_Mod_LoadExternalSkins, glsl_Mod_IQMFinish, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 14e09d3d4..727293ee5 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -83,7 +83,7 @@ static vid_model_funcs_t model_funcs = { Mod_LoadSpriteModel, sw_Mod_MakeAliasModelDisplayLists, - sw_Mod_LoadSkin, + sw_Mod_LoadAllSkins, 0, 0, sw_Mod_IQMFinish, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 94ffcc987..3f4fb4b38 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -540,13 +540,10 @@ vulkan_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, vulkan_ctx); } -static void * -vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, - int snum, int gnum, qboolean group, - maliasskindesc_t *skindesc) +static void +vulkan_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx) { - return Vulkan_Mod_LoadSkin (alias_ctx, skin, skinsize, snum, gnum, group, - skindesc, vulkan_ctx); + Vulkan_Mod_LoadAllSkins (alias_ctx, vulkan_ctx); } static void @@ -638,7 +635,7 @@ static vid_model_funcs_t model_funcs = { Mod_LoadSpriteModel, vulkan_Mod_MakeAliasModelDisplayLists, - vulkan_Mod_LoadSkin, + vulkan_Mod_LoadAllSkins, vulkan_Mod_FinalizeAliasModel, vulkan_Mod_LoadExternalSkins, vulkan_Mod_IQMFinish, From b011f9101866491c78de28ff6fa9eea4ce8614c0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 4 Apr 2022 17:47:21 +0900 Subject: [PATCH 2646/3664] [model] Clean up alias skin loading a little The improved allocation overheads have been implemented for gl and sw, and glsl no longer uses malloc. Using array textures will have to wait as the current texture loading code doesn't support them. --- libs/models/alias/gl_model_alias.c | 40 +++++++++++++--------------- libs/models/alias/glsl_model_alias.c | 31 +++++++++------------ libs/models/alias/sw_model_alias.c | 26 +++++------------- 3 files changed, 38 insertions(+), 59 deletions(-) diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index a3e5047aa..5abc7e4d5 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -52,55 +52,47 @@ #include "compat.h" -static void * -gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, - int snum, int gnum, qboolean group, - maliasskindesc_t *skindesc) +static void +gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *texels, + int snum, int gnum, maliasskindesc_t *skindesc) { aliashdr_t *header = alias_ctx->header; - byte *pskin; char modname[MAX_QPATH + 4]; int fb_texnum = 0, texnum = 0; dstring_t *name = dstring_new (); - pskin = Hunk_AllocName (0, skinsize, alias_ctx->mod->name); - skindesc->skin = (byte *) pskin - (byte *) header; - - memcpy (pskin, skin, skinsize); - - Mod_FloodFillSkin (pskin, header->mdl.skinwidth, header->mdl.skinheight); + Mod_FloodFillSkin (texels, header->mdl.skinwidth, header->mdl.skinheight); // save 8 bit texels for the player model to remap // FIXME remove model restriction if (strequal (alias_ctx->mod->path, "progs/player.mdl")) gl_Skin_SetPlayerSkin (header->mdl.skinwidth, header->mdl.skinheight, - pskin); + texels); QFS_StripExtension (alias_ctx->mod->path, modname); if (!alias_ctx->mod->fullbright) { - if (group) { + if (gnum != -1) { dsprintf (name, "fb_%s_%i_%i", modname, snum, gnum); } else { dsprintf (name, "fb_%s_%i", modname, snum); } - fb_texnum = Mod_Fullbright (pskin, header->mdl.skinwidth, + fb_texnum = Mod_Fullbright (texels, header->mdl.skinwidth, header->mdl.skinheight, name->str); Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, fb_texnum); } - if (group) { + if (gnum != -1) { dsprintf (name, "%s_%i_%i", modname, snum, gnum); } else { dsprintf (name, "%s_%i", modname, snum); } texnum = GL_LoadTexture (name->str, header->mdl.skinwidth, - header->mdl.skinheight, pskin, true, false, 1); + header->mdl.skinheight, texels, true, false, 1); Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, texnum); skindesc->texnum = texnum; skindesc->fb_texnum = fb_texnum; alias_ctx->mod->hasfullbrights = fb_texnum; dstring_delete (name); // alpha param was true for non group skins - return skin + skinsize; } void @@ -108,12 +100,18 @@ gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx) { aliashdr_t *header = alias_ctx->header; int skinsize = header->mdl.skinwidth * header->mdl.skinheight; + int num_skins = alias_ctx->skins.size; + byte *texel_block = Hunk_AllocName (0, skinsize * num_skins, + alias_ctx->mod->name); - for (size_t i = 0; i < alias_ctx->skins.size; i++) { + for (int i = 0; i < num_skins; i++) { __auto_type skin = alias_ctx->skins.a + i; - gl_Mod_LoadSkin (alias_ctx, skin->texels, skinsize, - skin->skin_num, skin->group_num, - skin->group_num != -1, skin->skindesc); + byte *texels = texel_block + i * skinsize; + + skin->skindesc->skin = texels - (byte *) header; + memcpy (texels, skin->texels, skinsize); + gl_Mod_LoadSkin (alias_ctx, texels, skin->skin_num, skin->group_num, + skin->skindesc); } } diff --git a/libs/models/alias/glsl_model_alias.c b/libs/models/alias/glsl_model_alias.c index f5e74b62f..4e04b419d 100644 --- a/libs/models/alias/glsl_model_alias.c +++ b/libs/models/alias/glsl_model_alias.c @@ -48,6 +48,7 @@ #include "QF/GLSL/qf_textures.h" #include "mod_internal.h" +#include "qfalloca.h" #include "r_shared.h" static vec3_t vertex_normals[NUMVERTEXNORMALS] = { @@ -90,41 +91,33 @@ glsl_alias_clear (model_t *m, void *data) } } -static void * -glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, int skinsize, - int snum, int gnum, qboolean group, - maliasskindesc_t *skindesc) +static void +glsl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *texels, + int snum, int gnum, maliasskindesc_t *skindesc) { aliashdr_t *header = alias_ctx->header; - byte *tskin; + int w = header->mdl.skinwidth; + int h = header->mdl.skinheight; + size_t skinsize = w * h; + byte *tskin = alloca (skinsize); const char *name; - int w, h; - w = header->mdl.skinwidth; - h = header->mdl.skinheight; - tskin = malloc (skinsize); - memcpy (tskin, skin, skinsize); + memcpy (tskin, texels, skinsize); Mod_FloodFillSkin (tskin, w, h); - if (group) + if (gnum != -1) name = va (0, "%s_%i_%i", alias_ctx->mod->path, snum, gnum); else name = va (0, "%s_%i", alias_ctx->mod->path, snum); skindesc->texnum = GLSL_LoadQuakeTexture (name, w, h, tskin); - free (tskin); - return skin + skinsize; } void glsl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx) { - aliashdr_t *header = alias_ctx->header; - int skinsize = header->mdl.skinwidth * header->mdl.skinheight; - for (size_t i = 0; i < alias_ctx->skins.size; i++) { __auto_type skin = alias_ctx->skins.a + i; - glsl_Mod_LoadSkin (alias_ctx, skin->texels, skinsize, - skin->skin_num, skin->group_num, - skin->group_num != -1, skin->skindesc); + glsl_Mod_LoadSkin (alias_ctx, skin->texels, + skin->skin_num, skin->group_num, skin->skindesc); } } diff --git a/libs/models/alias/sw_model_alias.c b/libs/models/alias/sw_model_alias.c index cd67e1f3f..797ec38de 100644 --- a/libs/models/alias/sw_model_alias.c +++ b/libs/models/alias/sw_model_alias.c @@ -48,33 +48,21 @@ // a pose is a single set of vertexes. a frame may be // an animating sequence of poses - -static void * -sw_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skin, - int skinsize, int snum, int gnum, - qboolean group, maliasskindesc_t *skindesc) -{ - byte *pskin; - - pskin = Hunk_AllocName (0, skinsize, alias_ctx->mod->name); - skindesc->skin = (byte *) pskin - (byte *) alias_ctx->header; - - memcpy (pskin, skin, skinsize); - - return skin + skinsize; -} - void sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx) { aliashdr_t *header = alias_ctx->header; int skinsize = header->mdl.skinwidth * header->mdl.skinheight; + int num_skins = alias_ctx->skins.size; + byte *texel_block = Hunk_AllocName (0, skinsize * num_skins, + alias_ctx->mod->name); for (size_t i = 0; i < alias_ctx->skins.size; i++) { __auto_type skin = alias_ctx->skins.a + i; - sw_Mod_LoadSkin (alias_ctx, skin->texels, skinsize, - skin->skin_num, skin->group_num, - skin->group_num != -1, skin->skindesc); + byte *texels = texel_block + i * skinsize; + + skin->skindesc->skin = texels - (byte *) header; + memcpy (texels, skin->texels, skinsize); } } From 2798b5fd587bfaaf20e09edeb61685e56f2cfc1c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 6 Apr 2022 14:40:40 +0900 Subject: [PATCH 2647/3664] [vulkan] Use cached memory for the bsp index buffer Since it is updated every frame, it needs to be as fast as possible for the cpu code. This seems to make a difference of about 10us (~130 -> ~120) when testing in marcher. Not a huge change, but the timing calculation was wrapped around the entire base world pass, so there was a fair bit of overhead from bsp traversal etc. --- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a6047f57b..464af0280 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -522,7 +522,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) "buffer:bsp:index"); bctx->index_memory = QFV_AllocBufferMemory (device, bctx->index_buffer, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, index_buffer_size, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, bctx->index_memory, "memory:bsp:index"); From 3f575ab02587e839f3c90b42b13c5a6de81428d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 6 Apr 2022 18:36:07 +0900 Subject: [PATCH 2648/3664] [win] Update for moved vulkan viewport I forgot to do a windows test build. --- libs/video/targets/vid_win_vulkan.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libs/video/targets/vid_win_vulkan.c b/libs/video/targets/vid_win_vulkan.c index 240fa2355..c67826ccb 100644 --- a/libs/video/targets/vid_win_vulkan.c +++ b/libs/video/targets/vid_win_vulkan.c @@ -155,10 +155,8 @@ win_vulkan_create_surface (vulkan_ctx_t *ctx) .hwnd = pres->window, }; - int width = viddef.width; - int height = viddef.height; - ctx->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; - ctx->scissor = (VkRect2D) { {0, 0}, {width, height} }; + ctx->window_width = viddef.width; + ctx->window_height = viddef.height; if (pres->vkCreateWin32SurfaceKHR (inst, &createInfo, 0, &surface) != VK_SUCCESS) { From 8f56f28ad7c2442c82483b36c2e793b45dcde8ae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 6 Apr 2022 18:46:28 +0900 Subject: [PATCH 2649/3664] [net] Use designated initializers for drivers Not that I expect anything to change any time soon, but nice to have the initializers explicitly named. --- libs/net/nm/net_bsd.c | 100 +++++++++++++++++++++--------------------- libs/net/nm/net_win.c | 100 +++++++++++++++++++++--------------------- 2 files changed, 102 insertions(+), 98 deletions(-) diff --git a/libs/net/nm/net_bsd.c b/libs/net/nm/net_bsd.c index 008a0b58a..3e49f31e8 100644 --- a/libs/net/nm/net_bsd.c +++ b/libs/net/nm/net_bsd.c @@ -34,36 +34,37 @@ net_driver_t net_drivers[MAX_NET_DRIVERS] = { { - "Loopback", - false, - Loop_Init, - Loop_Listen, - Loop_SearchForHosts, - Loop_Connect, - Loop_CheckNewConnections, - Loop_GetMessage, - Loop_SendMessage, - Loop_SendUnreliableMessage, - Loop_CanSendMessage, - Loop_CanSendUnreliableMessage, - Loop_Close, - Loop_Shutdown} - , + .name = "Loopback", + .initialized = false, + .Init = Loop_Init, + .Listen = Loop_Listen, + .SearchForHosts = Loop_SearchForHosts, + .Connect = Loop_Connect, + .CheckNewConnections = Loop_CheckNewConnections, + .QGetMessage = Loop_GetMessage, + .QSendMessage = Loop_SendMessage, + .SendUnreliableMessage = Loop_SendUnreliableMessage, + .CanSendMessage = Loop_CanSendMessage, + .CanSendUnreliableMessage = Loop_CanSendUnreliableMessage, + .Close = Loop_Close, + .Shutdown = Loop_Shutdown, + }, { - "Datagram", - false, - Datagram_Init, - Datagram_Listen, - Datagram_SearchForHosts, - Datagram_Connect, - Datagram_CheckNewConnections, - Datagram_GetMessage, - Datagram_SendMessage, - Datagram_SendUnreliableMessage, - Datagram_CanSendMessage, - Datagram_CanSendUnreliableMessage, - Datagram_Close, - Datagram_Shutdown} + .name = "Datagram", + .initialized = false, + .Init = Datagram_Init, + .Listen = Datagram_Listen, + .SearchForHosts = Datagram_SearchForHosts, + .Connect = Datagram_Connect, + .CheckNewConnections = Datagram_CheckNewConnections, + .QGetMessage = Datagram_GetMessage, + .QSendMessage = Datagram_SendMessage, + .SendUnreliableMessage = Datagram_SendUnreliableMessage, + .CanSendMessage = Datagram_CanSendMessage, + .CanSendUnreliableMessage = Datagram_CanSendUnreliableMessage, + .Close = Datagram_Close, + .Shutdown = Datagram_Shutdown, + }, }; int net_numdrivers = 2; @@ -72,26 +73,27 @@ int net_numdrivers = 2; net_landriver_t net_landrivers[MAX_NET_DRIVERS] = { { - "UDP", - false, - 0, - UDP_Init, - UDP_Shutdown, - UDP_Listen, - UDP_OpenSocket, - UDP_CloseSocket, - UDP_Connect, - UDP_CheckNewConnections, - UDP_Read, - UDP_Write, - UDP_Broadcast, - UDP_AddrToString, - UDP_GetSocketAddr, - UDP_GetNameFromAddr, - UDP_GetAddrFromName, - UDP_AddrCompare, - UDP_GetSocketPort, - UDP_SetSocketPort} + .name = "UDP", + .initialized = false, + .controlSock = 0, + .Init = UDP_Init, + .Shutdown = UDP_Shutdown, + .Listen = UDP_Listen, + .OpenSocket = UDP_OpenSocket, + .CloseSocket = UDP_CloseSocket, + .Connect = UDP_Connect, + .CheckNewConnections = UDP_CheckNewConnections, + .Read = UDP_Read, + .Write = UDP_Write, + .Broadcast = UDP_Broadcast, + .AddrToString = UDP_AddrToString, + .GetSocketAddr = UDP_GetSocketAddr, + .GetNameFromAddr = UDP_GetNameFromAddr, + .GetAddrFromName = UDP_GetAddrFromName, + .AddrCompare = UDP_AddrCompare, + .GetSocketPort = UDP_GetSocketPort, + .SetSocketPort = UDP_SetSocketPort, + }, }; int net_numlandrivers = 1; diff --git a/libs/net/nm/net_win.c b/libs/net/nm/net_win.c index 0dcbd27e6..f343d907a 100644 --- a/libs/net/nm/net_win.c +++ b/libs/net/nm/net_win.c @@ -33,36 +33,37 @@ net_driver_t net_drivers[MAX_NET_DRIVERS] = { { - "Loopback", - false, - Loop_Init, - Loop_Listen, - Loop_SearchForHosts, - Loop_Connect, - Loop_CheckNewConnections, - Loop_GetMessage, - Loop_SendMessage, - Loop_SendUnreliableMessage, - Loop_CanSendMessage, - Loop_CanSendUnreliableMessage, - Loop_Close, - Loop_Shutdown} - , + .name = "Loopback", + .initialized = false, + .Init = Loop_Init, + .Listen = Loop_Listen, + .SearchForHosts = Loop_SearchForHosts, + .Connect = Loop_Connect, + .CheckNewConnections = Loop_CheckNewConnections, + .QGetMessage = Loop_GetMessage, + .QSendMessage = Loop_SendMessage, + .SendUnreliableMessage = Loop_SendUnreliableMessage, + .CanSendMessage = Loop_CanSendMessage, + .CanSendUnreliableMessage = Loop_CanSendUnreliableMessage, + .Close = Loop_Close, + .Shutdown = Loop_Shutdown, + }, { - "Datagram", - false, - Datagram_Init, - Datagram_Listen, - Datagram_SearchForHosts, - Datagram_Connect, - Datagram_CheckNewConnections, - Datagram_GetMessage, - Datagram_SendMessage, - Datagram_SendUnreliableMessage, - Datagram_CanSendMessage, - Datagram_CanSendUnreliableMessage, - Datagram_Close, - Datagram_Shutdown} + .name = "Datagram", + .initialized = false, + .Init = Datagram_Init, + .Listen = Datagram_Listen, + .SearchForHosts = Datagram_SearchForHosts, + .Connect = Datagram_Connect, + .CheckNewConnections = Datagram_CheckNewConnections, + .QGetMessage = Datagram_GetMessage, + .QSendMessage = Datagram_SendMessage, + .SendUnreliableMessage = Datagram_SendUnreliableMessage, + .CanSendMessage = Datagram_CanSendMessage, + .CanSendUnreliableMessage = Datagram_CanSendUnreliableMessage, + .Close = Datagram_Close, + .Shutdown = Datagram_Shutdown, + }, }; int net_numdrivers = 2; @@ -72,26 +73,27 @@ int net_numdrivers = 2; net_landriver_t net_landrivers[MAX_NET_DRIVERS] = { { - "Winsock TCPIP", - false, - 0, - WINS_Init, - WINS_Shutdown, - WINS_Listen, - WINS_OpenSocket, - WINS_CloseSocket, - WINS_Connect, - WINS_CheckNewConnections, - WINS_Read, - WINS_Write, - WINS_Broadcast, - WINS_AddrToString, - WINS_GetSocketAddr, - WINS_GetNameFromAddr, - WINS_GetAddrFromName, - WINS_AddrCompare, - WINS_GetSocketPort, - WINS_SetSocketPort}, + .name = "Winsock TCPIP", + .initialized = false, + .controlSock = 0, + .Init = WINS_Init, + .Shutdown = WINS_Shutdown, + .Listen = WINS_Listen, + .OpenSocket = WINS_OpenSocket, + .CloseSocket = WINS_CloseSocket, + .Connect = WINS_Connect, + .CheckNewConnections = WINS_CheckNewConnections, + .Read = WINS_Read, + .Write = WINS_Write, + .Broadcast = WINS_Broadcast, + .AddrToString = WINS_AddrToString, + .GetSocketAddr = WINS_GetSocketAddr, + .GetNameFromAddr = WINS_GetNameFromAddr, + .GetAddrFromName = WINS_GetAddrFromName, + .AddrCompare = WINS_AddrCompare, + .GetSocketPort = WINS_GetSocketPort, + .SetSocketPort = WINS_SetSocketPort, + }, }; int net_numlandrivers = 1; From f6541dbe3f8ac99ce272fea69461f409b397b148 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 6 Apr 2022 19:32:55 +0900 Subject: [PATCH 2650/3664] [net] Remove client references from net_main This is progress towards #23. There are still some references to host_time and host_client (via nq's server.h), and a lot of references to sv and svs, but this is definitely a step in the right direction. --- include/netmain.h | 5 ++++- libs/net/net_main.c | 21 +++++++++++++-------- libs/net/nm/net_dgrm.c | 2 -- libs/net/nm/net_loop.c | 3 +-- libs/net/nm/net_wins.c | 1 - nq/include/client.h | 1 - nq/source/cl_main.c | 4 +--- nq/source/host.c | 22 +++++++++++----------- nq/source/host_cmd.c | 14 +++++++------- nq/source/sv_main.c | 2 +- nq/source/sys_sdl.c | 2 +- nq/source/sys_unix.c | 2 +- nq/source/sys_win.c | 2 +- 13 files changed, 41 insertions(+), 40 deletions(-) diff --git a/include/netmain.h b/include/netmain.h index 0a4587b26..882b7acc9 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -270,9 +270,11 @@ extern double net_time; extern struct msg_s *net_message; extern unsigned net_activeconnections; +struct cbuf_s; + /** Initialize the networking sub-system. */ -void NET_Init (void); +void NET_Init (struct cbuf_s *cbuf); /** Check for new connections. @@ -447,6 +449,7 @@ typedef struct { extern int net_numdrivers; extern net_driver_t net_drivers[MAX_NET_DRIVERS]; +extern int net_is_dedicated; ///@} diff --git a/libs/net/net_main.c b/libs/net/net_main.c index e534c4156..6ef7e9a0f 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -47,9 +47,10 @@ #include "netmain.h" #include "net_vcr.h" -#include "../nq/include/host.h" #include "../nq/include/server.h" +int net_is_dedicated = 0; + qsocket_t *net_activeSockets = NULL; qsocket_t *net_freeSockets = NULL; int net_numsockets = 0; @@ -102,6 +103,8 @@ double net_time; static int hostCacheCount = 0; static hostcache_t hostcache[HOSTCACHESIZE]; +static cbuf_t *net_cbuf; + double SetNetTime (void) { @@ -219,10 +222,10 @@ MaxPlayers_f (void) } if ((n == 1) && listening) - Cbuf_AddText (host_cbuf, "listen 0\n"); + Cbuf_AddText (net_cbuf, "listen 0\n"); if ((n > 1) && (!listening)) - Cbuf_AddText (host_cbuf, "listen 1\n"); + Cbuf_AddText (net_cbuf, "listen 1\n"); svs.maxclients = n; if (n == 1) @@ -253,8 +256,8 @@ NET_Port_f (void) if (listening) { // force a change to the new port - Cbuf_AddText (host_cbuf, "listen 0\n"); - Cbuf_AddText (host_cbuf, "listen 1\n"); + Cbuf_AddText (net_cbuf, "listen 0\n"); + Cbuf_AddText (net_cbuf, "listen 1\n"); } } @@ -796,12 +799,14 @@ NET_shutdown (void *data) } void -NET_Init (void) +NET_Init (cbuf_t *cbuf) { int i; int controlSocket; qsocket_t *s; + net_cbuf = cbuf; + Sys_RegisterShutdown (NET_shutdown, 0); if (COM_CheckParm ("-playback")) { @@ -826,10 +831,10 @@ NET_Init (void) } net_hostport = DEFAULTnet_hostport; - if (COM_CheckParm ("-listen") || cls.state == ca_dedicated) + if (COM_CheckParm ("-listen") || net_is_dedicated) listening = true; net_numsockets = svs.maxclientslimit; - if (cls.state != ca_dedicated) + if (!net_is_dedicated) net_numsockets++; SetNetTime (); diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 9aa10ef31..71f74ff4a 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -46,9 +46,7 @@ #include "netmain.h" -#include "../nq/include/client.h" #include "../nq/include/server.h" -#include "../nq/include/game.h" // This is enables a simple IP banning mechanism #define BAN_TEST diff --git a/libs/net/nm/net_loop.c b/libs/net/nm/net_loop.c index cb1ddb180..ddf61f6f3 100644 --- a/libs/net/nm/net_loop.c +++ b/libs/net/nm/net_loop.c @@ -35,7 +35,6 @@ #include "netmain.h" #include "net_loop.h" -#include "../nq/include/client.h" #include "../nq/include/server.h" qboolean localconnectpending = false; @@ -45,7 +44,7 @@ qsocket_t *loop_server = NULL; __attribute__((pure)) int Loop_Init (void) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) return -1; return 0; } diff --git a/libs/net/nm/net_wins.c b/libs/net/nm/net_wins.c index 6b779bfa5..411c0b838 100644 --- a/libs/net/nm/net_wins.c +++ b/libs/net/nm/net_wins.c @@ -1,4 +1,3 @@ - /* net_wins.c diff --git a/nq/include/client.h b/nq/include/client.h index 3096f6321..4e5c148e8 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -70,7 +70,6 @@ typedef enum { #define MAX_DEMONAME 16 typedef enum { - ca_dedicated, // a dedicated server with no ability to start a client ca_disconnected, // full screen console with no connection ca_connected, // talking to a server ca_active, // everything is in, so frames can be rendered diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 3b63db068..1a489621a 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -306,7 +306,7 @@ CL_Disconnect_f (void) void CL_EstablishConnection (const char *host) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) return; if (cls.demoplayback) @@ -510,8 +510,6 @@ CL_SetState (cactive_t state) r_funcs->R_ClearState (); } switch (state) { - case ca_dedicated: - break; case ca_disconnected: CL_ClearState (); cls.signon = so_none; diff --git a/nq/source/host.c b/nq/source/host.c index d19d30114..86b428c5a 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -157,7 +157,7 @@ Host_EndGame (const char *message, ...) if (sv.active) Host_ShutdownServer (false); - if (cls.state == ca_dedicated) + if (net_is_dedicated) Sys_Error ("Host_EndGame: %s", str->str); // dedicated servers exit if (cls.demonum != -1) @@ -197,7 +197,7 @@ Host_Error (const char *error, ...) if (sv.active) Host_ShutdownServer (false); - if (cls.state == ca_dedicated) + if (net_is_dedicated) Sys_Error ("Host_Error: %s", str->str); // dedicated servers exit Sys_Printf ("Host_Error: %s\n", str->str); @@ -219,17 +219,17 @@ Host_FindMaxClients (void) i = COM_CheckParm ("-dedicated"); if (i) { - cls.state = ca_dedicated; if (i != (com_argc - 1)) { svs.maxclients = atoi (com_argv[i + 1]); } else svs.maxclients = 8; - } else - cls.state = ca_disconnected; + } + cls.state = ca_disconnected; + net_is_dedicated = i; i = COM_CheckParm ("-listen"); if (i) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) Sys_Error ("Only one of -dedicated or -listen can be specified"); if (i != (com_argc - 1)) svs.maxclients = atoi (com_argv[i + 1]); @@ -676,10 +676,10 @@ _Host_Frame (float time) return; } - if (cls.state != ca_dedicated) + if (!net_is_dedicated) IN_ProcessEvents (); - if (cls.state == ca_dedicated) + if (net_is_dedicated) Con_ProcessInput (); GIB_Thread_Execute (); @@ -708,7 +708,7 @@ _Host_Frame (float time) Host_ServerFrame (); } - if (cls.state != ca_dedicated) + if (!net_is_dedicated) Host_ClientFrame (); else host_time += host_frametime; //FIXME is this needed? vcr stuff @@ -920,13 +920,13 @@ Host_Init (void) Host_InitVCR (&host_parms); Host_InitLocal (); - NET_Init (); + NET_Init (host_cbuf); Mod_Init (); SV_Init (); - if (cls.state != ca_dedicated) + if (!net_is_dedicated) CL_Init (host_cbuf); if (con_module) { diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index e58098241..2ad67d3b3 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -303,7 +303,7 @@ Host_Map_f (void) if (!sv.active) return; - if (cls.state != ca_dedicated) { + if (!net_is_dedicated) { Cmd_ExecuteString ("connect local", src_command); } } @@ -717,7 +717,7 @@ Host_Loadgame_f (void) for (i = 0; i < NUM_SPAWN_PARMS; i++) svs.clients->spawn_parms[i] = spawn_parms[i]; - if (cls.state != ca_dedicated) { + if (!net_is_dedicated) { CL_EstablishConnection ("local"); Host_Reconnect_f (); } @@ -790,7 +790,7 @@ Host_Say (qboolean teamonly) qboolean fromServer = false; if (cmd_source == src_command) { - if (cls.state == ca_dedicated) { + if (net_is_dedicated) { fromServer = true; teamonly = false; } else { @@ -1134,7 +1134,7 @@ Host_Kick_f (void) if (i < svs.maxclients) { if (cmd_source == src_command) - if (cls.state == ca_dedicated) + if (net_is_dedicated) who = "Console"; else who = cl_name->string; @@ -1403,7 +1403,7 @@ Host_Startdemos_f (void) { int i, c; - if (cls.state == ca_dedicated) { + if (net_is_dedicated) { if (!sv.active) Cbuf_AddText (host_cbuf, "map start\n"); return; @@ -1434,7 +1434,7 @@ Host_Startdemos_f (void) static void Host_Demos_f (void) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) return; if (cls.demonum == -1) cls.demonum = 1; @@ -1450,7 +1450,7 @@ Host_Demos_f (void) static void Host_Stopdemo_f (void) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) return; if (!cls.demoplayback) return; diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 21a18fbfc..57282ea1d 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1064,7 +1064,7 @@ SV_SendReconnect (void) MSG_WriteString (&msg, "reconnect\n"); NET_SendToAll (&msg, 5.0); - if (cls.state != ca_dedicated) + if (!net_is_dedicated) Cmd_ExecuteString ("reconnect\n", src_command); } diff --git a/nq/source/sys_sdl.c b/nq/source/sys_sdl.c index 76e84b558..68c2e91eb 100644 --- a/nq/source/sys_sdl.c +++ b/nq/source/sys_sdl.c @@ -136,7 +136,7 @@ SDL_main (int argc, char *argv[]) newtime = Sys_DoubleTime (); time = newtime - oldtime; - if (cls.state == ca_dedicated) { // play vcrfiles at max speed + if (net_is_dedicated) { // play vcrfiles at max speed if (time < sys_ticrate->value && (!vcrFile || recording)) { usleep (1); continue; // not time to run a server-only tic yet diff --git a/nq/source/sys_unix.c b/nq/source/sys_unix.c index 20cce79a5..e244b940e 100644 --- a/nq/source/sys_unix.c +++ b/nq/source/sys_unix.c @@ -91,7 +91,7 @@ main (int argc, const char **argv) newtime = Sys_DoubleTime (); time = newtime - oldtime; - if (cls.state == ca_dedicated) { // play vcrfiles at max speed + if (net_is_dedicated) { // play vcrfiles at max speed if (time < sys_ticrate->value && (!vcrFile || recording)) { usleep (1); continue; // not time to run a server-only tic yet diff --git a/nq/source/sys_win.c b/nq/source/sys_win.c index ee040f956..59c61b796 100644 --- a/nq/source/sys_win.c +++ b/nq/source/sys_win.c @@ -228,7 +228,7 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, newtime = Sys_DoubleTime (); time = newtime - oldtime; - if (cls.state == ca_dedicated) { // play vcrfiles at max speed + if (net_is_dedicated) { // play vcrfiles at max speed if (time < sys_ticrate->value && (!vcrFile || recording)) { Sleep (1); continue; // not time to run a server-only tic yet From 6b81a4b8825f3496e220be071d2b80829a274b9e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 7 Apr 2022 22:30:19 +0900 Subject: [PATCH 2651/3664] [renderer] Don't try to animate lightstyles that aren't there Prevents a segfault when running the renderer via qwaq-x11. --- libs/video/renderer/r_light.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index d9a96915e..2f063e9d9 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -126,6 +126,10 @@ R_AnimateLight (void) { int i, j, k; + if (!r_data->lightstyle) { + return; + } + // light animations // 'm' is normal light, 'a' is no light, 'z' is double bright i = (int) (r_data->realtime * 10); From 8d725a1d0a1a02693adbca151bdde4e215b8b822 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 8 Apr 2022 18:27:53 +0900 Subject: [PATCH 2652/3664] [nq] Clean up Host_Frame_ a little This simplifies the logic around dedicated servers and clients connecting to remote servers. --- nq/source/cl_main.c | 5 ++++ nq/source/host.c | 63 ++++++++++++++++++++------------------------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 1a489621a..9a3b00ae1 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -155,6 +155,11 @@ CL_ClearMemory (void) { VID_ClearMemory (); SCR_SetFullscreen (0); + + cls.signon = 0; + __auto_type cam = cl.viewstate.camera_transform; + memset (&cl, 0, sizeof (cl)); + cl.viewstate.camera_transform = cam; } void diff --git a/nq/source/host.c b/nq/source/host.c index 86b428c5a..2e4298007 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -503,12 +503,6 @@ Host_ClearMemory (void) Mod_ClearAll (); if (host_hunklevel) Hunk_FreeToLowMark (0, host_hunklevel); - - cls.signon = 0; - memset (&sv, 0, sizeof (sv)); - __auto_type cam = cl.viewstate.camera_transform; - memset (&cl, 0, sizeof (cl)); - cl.viewstate.camera_transform = cam; } /* @@ -575,19 +569,25 @@ Host_ServerFrame (void) SV_SendClientMessages (); } +static void +write_capture (tex_t *tex, void *data) +{ + QFile *file = QFS_Open (va (0, "%s/qfmv%06d.png", + qfs_gamedir->dir.shots, + cls.demo_capture++), "wb"); + if (file) { + WritePNG (file, tex); + Qclose (file); + } + free (tex); +} + static void Host_ClientFrame (void) { static double time1 = 0, time2 = 0, time3 = 0; int pass1, pass2, pass3; - // if running the server remotely, send intentions now after - // the incoming messages have been read - if (!sv.active) - CL_SendCmd (); - - host_time += host_frametime; - // fetch results from server if (cls.state >= ca_connected) CL_ReadFromServer (); @@ -631,19 +631,10 @@ Host_ClientFrame (void) Sys_Printf ("%3i tot %3i server %3i gfx %3i snd\n", pass1 + pass2 + pass3, pass1, pass2, pass3); } -} -static void -write_capture (tex_t *tex, void *data) -{ - QFile *file = QFS_Open (va (0, "%s/qfmv%06d.png", - qfs_gamedir->dir.shots, - cls.demo_capture++), "wb"); - if (file) { - WritePNG (file, tex); - Qclose (file); + if (cls.demo_capture) { + r_funcs->capture_screen (write_capture, 0); } - free (tex); } /* @@ -675,12 +666,13 @@ _Host_Frame (float time) #endif return; } + host_time += host_frametime; //FIXME is this needed? vcr stuff - if (!net_is_dedicated) - IN_ProcessEvents (); - - if (net_is_dedicated) + if (net_is_dedicated) { Con_ProcessInput (); + } else { + IN_ProcessEvents (); + } GIB_Thread_Execute (); cmd_source = src_command; @@ -703,18 +695,19 @@ _Host_Frame (float time) NET_Poll (); - if (sv.active) { + if (!net_is_dedicated) { + // Whether or not the server is active, if this is not a dedicated + // server, then the client always needs to be able to process input + // and send commands to the server before the server runs a frame. CL_SendCmd (); + } + + if (sv.active) { Host_ServerFrame (); } - if (!net_is_dedicated) + if (!net_is_dedicated) { Host_ClientFrame (); - else - host_time += host_frametime; //FIXME is this needed? vcr stuff - - if (cls.demo_capture) { - r_funcs->capture_screen (write_capture, 0); } host_framecount++; From bffd0605b72737597813b0f96345d5f3f2f4a680 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 8 Apr 2022 18:29:04 +0900 Subject: [PATCH 2653/3664] [nq] Show sub-millisecond times for serverprofile Integer milliseconds are a little too coarse when the range is 1-3ms. --- nq/source/host.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nq/source/host.c b/nq/source/host.c index 2e4298007..45f23d4a4 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -719,7 +719,8 @@ Host_Frame (float time) { double time1, time2; static double timetotal; - int c, m; + int c; + double m; static int timecount; if (!serverprofile->int_val) { @@ -746,7 +747,7 @@ Host_Frame (float time) c++; } - Sys_Printf ("serverprofile: %2i clients %2i msec\n", c, m); + Sys_Printf ("serverprofile: %2i clients %5.3g msec\n", c, m); } From dcd13e4230c3b680fe76eab07ef640e6d857e018 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 8 Apr 2022 20:07:45 +0900 Subject: [PATCH 2654/3664] [qw] Fix an extern in a C file Rather worrying finding one. I guess I didn't feel like finding a header for the declaration at time time. --- qw/include/client.h | 2 ++ qw/source/cl_main.c | 1 - qw/source/cl_parse.c | 2 -- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/qw/include/client.h b/qw/include/client.h index 57b87f514..dbd0f35d0 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -280,6 +280,8 @@ extern struct cvar_s *skin; extern struct cvar_s *cl_fb_players; +extern struct cvar_s *hud_scoreboard_uid; + extern client_state_t cl; extern entity_t *cl_entities[512]; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index c70a137ef..7b4179907 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -216,7 +216,6 @@ jmp_buf host_abort; char *server_version = NULL; // version of server we connected to -extern cvar_t *hud_scoreboard_uid; static netadr_t cl_cmd_packet_address; static void diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index c7478445d..cd97ec003 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -172,8 +172,6 @@ int cl_h_playerindex, cl_gib1index, cl_gib2index, cl_gib3index; int packet_latency[NET_TIMINGS]; -extern cvar_t *hud_scoreboard_uid; - int CL_CalcNet (void) { From 4d443d31148bfef3f7cef360c9ba702b33016b85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 8 Apr 2022 20:42:59 +0900 Subject: [PATCH 2655/3664] [vid] Fix non-utf8 circle-c in fbset Python didn't like reading the files. --- include/fbset.h | 2 +- libs/video/targets/fbset.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fbset.h b/include/fbset.h index 82f2f9bd3..8dc8cbb87 100644 --- a/include/fbset.h +++ b/include/fbset.h @@ -1,7 +1,7 @@ /* * Linux Frame Buffer Device Configuration * - * © Copyright 1995-1998 by Geert Uytterhoeven + * © Copyright 1995-1998 by Geert Uytterhoeven * (Geert.Uytterhoeven@cs.kuleuven.ac.be) * * -------------------------------------------------------------------------- diff --git a/libs/video/targets/fbset.c b/libs/video/targets/fbset.c index 51866326a..c24a5db7a 100644 --- a/libs/video/targets/fbset.c +++ b/libs/video/targets/fbset.c @@ -1,7 +1,7 @@ /* * Linux Frame Buffer Device Configuration * - * © Copyright 1995-1999 by Geert Uytterhoeven + * © Copyright 1995-1999 by Geert Uytterhoeven * (Geert.Uytterhoeven@cs.kuleuven.ac.be) * * -------------------------------------------------------------------------- From e97b96b536f2f04ebf6f3e61e4768b5af1939e07 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 9 Apr 2022 01:06:03 +0900 Subject: [PATCH 2656/3664] Remove some long dead cvars The declarations were still around, but the creation and code using them was removed long ago. --- include/QF/input.h | 1 - include/d_local.h | 2 -- include/r_cvar.h | 4 ---- include/r_local.h | 1 - include/snd_internal.h | 4 ---- libs/audio/renderer/snd_dma.c | 1 + libs/video/renderer/gl/vid_common_gl.c | 4 ---- nq/include/client.h | 4 ---- qw/include/cl_main.h | 1 - qw/include/client.h | 2 -- qw/source/cl_skin.c | 2 +- 11 files changed, 2 insertions(+), 24 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index ade3b97d0..119ad170b 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -129,7 +129,6 @@ void IN_ClearStates (void); extern struct cvar_s *in_grab; extern struct cvar_s *in_amp; extern struct cvar_s *in_pre_amp; -extern struct cvar_s *m_filter; extern struct cvar_s *in_mouse_accel; extern struct cvar_s *in_freelook; extern struct cvar_s *lookstrafe; diff --git a/include/d_local.h b/include/d_local.h index 51a2cd220..7b9cc3fac 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -63,8 +63,6 @@ typedef struct sspan_s { int u, v, count; } sspan_t; -extern struct cvar_s *d_subdiv16; - extern float scale_for_mip; extern qboolean d_roverwrapped; diff --git a/include/r_cvar.h b/include/r_cvar.h index 5b1090c1d..756c2ef03 100644 --- a/include/r_cvar.h +++ b/include/r_cvar.h @@ -59,9 +59,7 @@ extern struct cvar_s *r_explosionclip; extern struct cvar_s *r_farclip; extern struct cvar_s *r_firecolor; extern struct cvar_s *r_flatlightstyles; -extern struct cvar_s *r_fullbright; extern struct cvar_s *r_graphheight; -extern struct cvar_s *r_lightmap; extern struct cvar_s *r_lightmap_components; extern struct cvar_s *r_maxedges; extern struct cvar_s *r_maxsurfs; @@ -85,8 +83,6 @@ extern struct cvar_s *r_waterripple; extern struct cvar_s *r_waterwarp; extern struct cvar_s *r_zgraph; -extern struct cvar_s *scr_consize; -extern struct cvar_s *scr_conspeed; extern struct cvar_s *scr_fov; extern struct cvar_s *scr_fisheye; extern struct cvar_s *scr_fviews; diff --git a/include/r_local.h b/include/r_local.h index e6a068501..ef0db6963 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -71,7 +71,6 @@ extern struct cvar_s *r_timegraph; extern struct cvar_s *r_graphheight; extern struct cvar_s *r_clearcolor; extern struct cvar_s *r_waterwarp; -extern struct cvar_s *r_fullbright; extern struct cvar_s *r_drawentities; extern struct cvar_s *r_aliasstats; extern struct cvar_s *r_dspeeds; diff --git a/include/snd_internal.h b/include/snd_internal.h index 8d95d0615..078d32cbb 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -229,12 +229,8 @@ struct channel_s { //@} }; -extern struct cvar_s *snd_loadas8bit; extern struct cvar_s *snd_volume; -extern struct cvar_s *snd_interp; -extern struct cvar_s *snd_stereo_phase_separation; - extern snd_render_data_t snd_render_data; #define PAINTBUFFER_SIZE 512 extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index ecf5b2707..010793cae 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -345,6 +345,7 @@ s_init (void) "fix permanently blocked sound"); // FIXME +//extern struct cvar_s *snd_loadas8bit; // if (host_parms.memsize < 0x800000) { // Cvar_Set (snd_loadas8bit, "1"); // Sys_Printf ("loading all sounds as 8bit\n"); diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index d1547d2d9..e0e5f5231 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -113,7 +113,6 @@ int gl_tess; int gl_max_lights; cvar_t *gl_anisotropy; -cvar_t *gl_doublebright; cvar_t *gl_fb_bmodels; cvar_t *gl_finish; cvar_t *gl_max_size; @@ -485,9 +484,6 @@ CheckCombineExtensions (void) "doublebright enabled.\n"); } else { gl_combine_capable = false; - Sys_MaskPrintf (SYS_vid, "GL_ARB_texture_env_combine not found. " - "gl_doublebright will have no effect with " - "gl_multitexture on.\n"); } } diff --git a/nq/include/client.h b/nq/include/client.h index 4e5c148e8..de0e7cb02 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -213,13 +213,9 @@ typedef struct client_state_s { extern struct cvar_s *cl_name; extern struct cvar_s *cl_color; -extern struct cvar_s *cl_autofire; - extern struct cvar_s *cl_shownet; extern struct cvar_s *cl_nolerp; -extern struct cvar_s *cl_pitchdriftspeed; - extern struct cvar_s *cl_name; extern struct cvar_s *cl_writecfg; diff --git a/qw/include/cl_main.h b/qw/include/cl_main.h index 640c206cc..61d9d0481 100644 --- a/qw/include/cl_main.h +++ b/qw/include/cl_main.h @@ -52,7 +52,6 @@ void CL_BeginServerConnect(void); #define soundlist_name "soundlist %i %i" -extern struct cvar_s *cl_timeframes; extern struct cvar_s *cl_predict_players; extern struct cvar_s *cl_solid_players; extern struct cvar_s *cl_autoexec; diff --git a/qw/include/client.h b/qw/include/client.h index dbd0f35d0..876bc6cca 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -265,8 +265,6 @@ extern struct cvar_s *cl_netgraph_box; extern struct cvar_s *cl_draw_locs; extern struct cvar_s *cl_shownet; -extern struct cvar_s *cl_pitchdriftspeed; - extern struct cvar_s *cl_name; extern struct cvar_s *cl_model_crcs; diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index 24f2a809d..6ff72805b 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -200,7 +200,7 @@ CL_Skin_Init (void) "shirt pants) Note that if only shirt color is given, " "pants will match"); - noskins = Cvar_Get ("noskins", "0", CVAR_ARCHIVE, NULL, //XXX FIXME + noskins = Cvar_Get ("noskins", "0", CVAR_ARCHIVE, NULL, "set to 1 to not download new skins"); skin = Cvar_Get ("skin", "", CVAR_ARCHIVE | CVAR_USERINFO, skin_f, "Players skin"); From 063c0797d60100c7171f942202fd178fe1221e03 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 9 Apr 2022 01:57:14 +0900 Subject: [PATCH 2657/3664] Fix some inconsistent cvar uses Surprisingly, only two, but they were caught by the different value fields being used, thus the cvar was checked in multiple places. I imagine that's not really all that common, so there may be some inconsistencies between default value and use. --- libs/video/renderer/sw/sw_fisheye.c | 2 +- qw/source/sv_user.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/sw/sw_fisheye.c b/libs/video/renderer/sw/sw_fisheye.c index c1c782e47..83d6c2a15 100644 --- a/libs/video/renderer/sw/sw_fisheye.c +++ b/libs/video/renderer/sw/sw_fisheye.c @@ -128,7 +128,7 @@ R_RenderFisheye (framebuffer_t *cube) { int width = r_refdef.vrect.width; int height = r_refdef.vrect.height; - int fov = scr_ffov->int_val; + float fov = scr_ffov->value; static int pwidth = -1; static int pheight = -1; static int pfov = -1; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index a9eb02fe4..31dc6c142 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -940,7 +940,7 @@ SV_Say (qboolean team) } // non-team messages should be seen allways, even if not tracking any // player - if (!team && ((host_client->spectator && sv_spectalk->value) + if (!team && ((host_client->spectator && sv_spectalk->int_val) || !host_client->spectator)) { dbuf = SVR_WriteBegin (dem_all, 0, strlen (text->str) + 3); } else { From 32a395a8d57737d0ef0f99b327aba11bb31e5638 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 12 Apr 2022 21:01:41 +0900 Subject: [PATCH 2658/3664] [dox] Fix up some doxygen issues I found a few doxygen related patches in my git stash and while testing them, found a few doc issues. --- doc/quakeforge.dox.conf.in | 4 +++- include/QF/input.h | 5 +++++ include/QF/input/binding.h | 7 +++++++ include/QF/input/event.h | 7 +++++++ include/QF/input/imt.h | 7 +++++++ include/QF/keys.h | 2 -- include/QF/progs/pr_comp.h | 2 ++ include/QF/sound.h | 3 --- include/snd_internal.h | 6 ++---- 9 files changed, 33 insertions(+), 10 deletions(-) diff --git a/doc/quakeforge.dox.conf.in b/doc/quakeforge.dox.conf.in index 3d22be413..76b963cb4 100644 --- a/doc/quakeforge.dox.conf.in +++ b/doc/quakeforge.dox.conf.in @@ -2133,7 +2133,8 @@ SEARCH_INCLUDES = YES INCLUDE_PATH = @TOPSRC@/include \ @TOPSRC@/nq/include \ @TOPSRC@/qw/include \ - @TOPSRC@/qtv/include + @TOPSRC@/qtv/include \ + @TOPSRC@ # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -2152,6 +2153,7 @@ INCLUDE_FILE_PATTERNS = *.h # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. PREDEFINED = "__attribute__(x)=" \ + IN_DOXYGEN=1 \ VISIBLE= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this diff --git a/include/QF/input.h b/include/QF/input.h index 119ad170b..bb1e8a09c 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -28,6 +28,9 @@ #ifndef __QF_input_h #define __QF_input_h +/** \defgroup input Input Sub-system */ + +///@{ typedef struct in_axisinfo_s { int deviceid; int axis; @@ -135,4 +138,6 @@ extern struct cvar_s *lookstrafe; #endif +///@} + #endif//__QF_input_h diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 3570c42e4..02363abe5 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -34,6 +34,11 @@ #include "QF/mathlib.h" #endif +/** \defgroup input_bindings Input Bindings + \ingroup input +*/ +///@{ + /*** Recipe for converting an axis to a floating point value. Absolute axes are converted to the 0..1 range for unbalanced axes, and @@ -366,4 +371,6 @@ void IN_Binding_LoadConfig (struct plitem_s *config); #endif +///@} + #endif//__QF_input_binding_h diff --git a/include/QF/input/event.h b/include/QF/input/event.h index 97902029d..698fd21bb 100644 --- a/include/QF/input/event.h +++ b/include/QF/input/event.h @@ -33,6 +33,11 @@ #include "QF/qtypes.h" +/** \defgroup input_events Input Events + \ingroup input +*/ +///@{ + typedef struct { int xpos, ypos; int xlen, ylen; @@ -122,4 +127,6 @@ void IE_Remove_Handler (int handle); void IE_Set_Focus (int handle); int IE_Get_Focus (void) __attribute__ ((pure)); +///@} + #endif//__QF_in_event_h diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index e3777e8ea..5f3f8c2d3 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -29,6 +29,11 @@ #ifndef __QF_input_imt_h #define __QF_input_imt_h +/** \defgroup input_imt Input Mapping Tables + \ingroup input +*/ +///@{ + #ifndef __QFCC__ #include "QF/darray.h" @@ -134,4 +139,6 @@ void IMT_LoadConfig (struct plitem_s *config); #endif +///@} + #endif//__QF_input_imt_h diff --git a/include/QF/keys.h b/include/QF/keys.h index caf8f55de..4d0387467 100644 --- a/include/QF/keys.h +++ b/include/QF/keys.h @@ -34,8 +34,6 @@ # include "QF/quakeio.h" #endif -/** \defgroup input Input Sub-system */ - /** \defgroup input_keybinding Key Binding Sub-system \ingroup input */ diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index bc0c1030e..a1051c079 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -431,7 +431,9 @@ typedef enum { #define OP_BREAK 0x8000 typedef enum { +#ifndef IN_DOXYGEN #include "QF/progs/pr_opcode.hinc" +#endif } pr_opcode_e; // Used for both branch and comparison, with jump and call being ignored for diff --git a/include/QF/sound.h b/include/QF/sound.h index 7d2227fc4..3e6237962 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -133,9 +133,6 @@ void S_StopAllSounds(void); render some sound. \param ear Transform for the position and orientation of the stereo sound pickup. - \param v_forward 3d vector of the client's facing direction - \param v_right 3d vector of the client's rightward direction - \param v_up 3d vector of the client's upward direction \param ambient_sound_level NUM_AMBIENTS bytes indicating current ambient sound levels */ diff --git a/include/snd_internal.h b/include/snd_internal.h index 078d32cbb..59d2f8578 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -353,10 +353,8 @@ void SND_AmbientOn (snd_t *snd); /** Update the sound engine with the client's position and orientation and render some sound. \param snd sound system state - \param origin 3d coords of the client - \param v_forward 3d vector of the client's facing direction - \param v_right 3d vector of the client's rightward direction - \param v_up 3d vector of the client's upward direction + \param ear Transform for the position and orientation of the stereo + sound pickup. \param ambient_sound_level Pointer to 4 bytes indicating the levels at which to play the ambient sounds. */ From b649638400131b4fa8aaefb79313eace2312d6ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Apr 2022 11:27:50 +0900 Subject: [PATCH 2659/3664] [joy] Clean up some redundant cvar flags No need to or CVAR_NONE with other flags. --- libs/video/targets/joy.c | 8 ++++---- libs/video/targets/joy_win.c | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libs/video/targets/joy.c b/libs/video/targets/joy.c index a7a55f6dd..3ff827726 100644 --- a/libs/video/targets/joy.c +++ b/libs/video/targets/joy.c @@ -466,12 +466,12 @@ JOY_Init_Cvars (void) int i; joy_device = Cvar_Get ("joy_device", "/dev/input/js0", - CVAR_NONE | CVAR_ROM, 0, "Joystick device"); - joy_enable = Cvar_Get ("joy_enable", "1", CVAR_NONE | CVAR_ARCHIVE, 0, + CVAR_ROM, 0, "Joystick device"); + joy_enable = Cvar_Get ("joy_enable", "1", CVAR_ARCHIVE, 0, "Joystick enable flag"); - joy_amp = Cvar_Get ("joy_amp", "1", CVAR_NONE | CVAR_ARCHIVE, joyamp_f, + joy_amp = Cvar_Get ("joy_amp", "1", CVAR_ARCHIVE, joyamp_f, "Joystick amplification"); - joy_pre_amp = Cvar_Get ("joy_pre_amp", "0.01", CVAR_NONE | CVAR_ARCHIVE, + joy_pre_amp = Cvar_Get ("joy_pre_amp", "0.01", CVAR_ARCHIVE, joyamp_f, "Joystick pre-amplification"); Cmd_AddCommand ("in_joy", in_joy_f, "Configures the joystick behaviour"); diff --git a/libs/video/targets/joy_win.c b/libs/video/targets/joy_win.c index babd2e270..f42b5022a 100644 --- a/libs/video/targets/joy_win.c +++ b/libs/video/targets/joy_win.c @@ -353,12 +353,11 @@ void JOY_Init_Cvars(void) { // joystick variables - joy_device = Cvar_Get ("joy_device", "none", CVAR_NONE | CVAR_ROM, 0, + joy_device = Cvar_Get ("joy_device", "none", CVAR_ROM, 0, "Joystick device"); - joy_enable = Cvar_Get ("joy_enable", "1", CVAR_NONE | CVAR_ARCHIVE, 0, + joy_enable = Cvar_Get ("joy_enable", "1", CVAR_ARCHIVE, 0, "Joystick enable flag"); - joy_sensitivity = Cvar_Get ("joy_sensitivity", "1", CVAR_NONE | - CVAR_ARCHIVE, 0, "Joystick sensitivity"); + joy_sensitivity = Cvar_Get ("joy_sensitivity", "1", CVAR_ARCHIVE, 0, "Joystick sensitivity"); in_joystick = Cvar_Get ("joystick", "0", CVAR_ARCHIVE, 0, "FIXME: No " "Description"); joy_name = Cvar_Get ("joyname", "joystick", CVAR_NONE, 0, "FIXME: No " From f15abcea537f1236c7d3c63d9095415b3bff3359 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Apr 2022 10:46:55 +0900 Subject: [PATCH 2660/3664] [vulkan] Add a FIXME for the flashing Q icon As I had suspected, it's due to a synchronization problem between the scrap and drawing. There's actually a double problem in that data uploaded to the scrap isn't flushed until the first frame is rendered causing a quick init-shutdown sequence to take at least five seconds due to the staging buffer waiting (and timing out) on a stuck fence. Rendering just one frame "fixes" the problem (draw was one of the earliest subsystems to get going in vulkan). --- libs/video/renderer/vulkan/vulkan_draw.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 24c11db91..7552b9a2a 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -276,6 +276,11 @@ pic_data (const char *name, int w, int h, const byte *data, drawctx_t *dctx) *picdata++ = *col++; *picdata++ = (pix == 255) - 1; } + //FIXME live updates of the scrap aren't + //syncronized properly for some reason and result in stale texels being + //rendered (flashing pink around the Q menu cursor the first time it's + //displayed). I suspect simple barriers aren't enough and more + //sophisticated syncronization (events? semaphores?) is needed. return pic; } From bc1fe6aa0133c5a6d09fc738d20f93fd0599013a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Apr 2022 10:56:56 +0900 Subject: [PATCH 2661/3664] [renderer] Remove some redundant comments No need for comments when the code says it all. --- libs/video/renderer/r_screen.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index cabd491cc..5d2d69ac6 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -74,37 +74,37 @@ static float tan_fov_x, tan_fov_y; static mat4f_t box_rotations[] = { [BOX_FRONT] = { - { 1, 0, 0, 0}, // front + { 1, 0, 0, 0}, { 0, 1, 0, 0}, { 0, 0, 1, 0}, { 0, 0, 0, 1} }, [BOX_RIGHT] = { - { 0,-1, 0, 0}, // right + { 0,-1, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 1, 0}, { 0, 0, 0, 1} }, [BOX_BEHIND] = { - {-1, 0, 0, 0}, // back + {-1, 0, 0, 0}, { 0,-1, 0, 0}, { 0, 0, 1, 0}, { 0, 0, 0, 1} }, [BOX_LEFT] = { - { 0, 1, 0, 0}, // left + { 0, 1, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 1, 0}, { 0, 0, 0, 1} }, [BOX_TOP] = { - { 0, 0, 1, 0}, // top + { 0, 0, 1, 0}, { 0, 1, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 0, 1} }, [BOX_BOTTOM] = { - { 0, 0,-1, 0}, // bottom + { 0, 0,-1, 0}, { 0, 1, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 1} From b2d4fa0ccf96995c83e2fd6354e10e03000facd7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 2 Apr 2022 11:42:36 +0900 Subject: [PATCH 2662/3664] [vulkan] Break render pass parsing away from swapchain This allows a single render pass description to be used for both on-screen and off-screen targets. While Vulkan does allow a VkRenderPass to be used with any compatible frame buffer, and vkparse caches a VkRenderPass created from the same description, this allows the same description to be used for a compatible off-screen target without any dependence on the swapchain. However, there is a problem in the caching when it comes to targeting outputs with different formats. --- include/vid_vulkan.h | 10 ++ libs/video/renderer/vulkan/deferred.plist | 40 +++---- libs/video/renderer/vulkan/vkparse.c | 104 +++++------------- libs/video/renderer/vulkan/vkparse.h | 12 -- .../video/renderer/vulkan/vulkan_vid_common.c | 11 +- 5 files changed, 66 insertions(+), 111 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 56aa8c3f3..def07b666 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -9,6 +9,13 @@ #include "QF/darray.h" #include "QF/simd/types.h" +//FIXME name +typedef struct qfv_output_s { + VkExtent2D extent; + VkImageView view; + VkFormat format; +} qfv_output_t; + typedef struct vulkan_frame_s { VkFramebuffer framebuffer; VkFence fence; @@ -91,6 +98,9 @@ typedef struct vulkan_ctx_s { VkViewport viewport; VkRect2D scissor; + //FIXME not sure I like it being here (also, type name) + qfv_output_t output; + #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index 1eade9e2e..c5ce13c0f 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -5,8 +5,8 @@ format = x8_d24_unorm_pack32; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -20,8 +20,8 @@ format = r8g8b8a8_unorm; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -35,8 +35,8 @@ format = r16g16b16a16_sfloat; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -50,8 +50,8 @@ format = r16g16b16a16_sfloat; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -65,8 +65,8 @@ format = r32g32b32a32_sfloat; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -80,8 +80,8 @@ format = r8g8b8a8_unorm; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -95,8 +95,8 @@ format = r8g8b8a8_unorm; samples = 1; extent = { - width = $swapchain.extent.width; - height = $swapchain.extent.height; + width = $output.extent.width; + height = $output.extent.height; depth = 1; }; mipLevels = 1; @@ -223,9 +223,9 @@ framebuffer = { renderPass = $properties.renderpass; attachments = (depth, color, emission, normal, position, opaque, - translucent, "$swapchain.views[$swapImageIndex]"); - width = $swapchain.extent.width; - height = $swapchain.extent.height; + translucent, $output.view); + width = $output.extent.width; + height = $output.extent.height; layers = 1; }; clearValues = ( @@ -236,7 +236,7 @@ { color = "[0, 0, 0, 1]"; }, // position { color = "[0, 0, 0, 1]"; }, // opaque { color = "[0, 0, 0, 0]"; }, // translucent - { color = "[0, 0, 0, 1]"; }, // swapchain + { color = "[0, 0, 0, 1]"; }, // output ); renderpass = { attachments = ( @@ -311,7 +311,7 @@ finalLayout = color_attachment_optimal; }, { - format = $swapchain.format; + format = $output.format; samples = 1; loadOp = clear; storeOp = store; @@ -414,7 +414,7 @@ }, ); colorAttachments = ( - { // swapchain + { // output attachment = 7; layout = color_attachment_optimal; }, diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 79c6811e3..97fdd813d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -42,8 +42,8 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/pipeline.h" +#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/shader.h" -#include "QF/Vulkan/swapchain.h" #include "vid_vulkan.h" @@ -51,6 +51,17 @@ #include "vkparse.h" #undef vkparse_internal +typedef struct parseres_s { + const char *name; + plfield_t *field; + size_t offset; +} parseres_t; + +typedef struct handleref_s { + char *name; + uint64_t handle; +} handleref_t; + static void flag_or (const exprval_t *val1, const exprval_t *val2, exprval_t *result, exprctx_t *ctx) { @@ -577,7 +588,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, return ret; } -static exprtype_t imageview_type = { +exprtype_t VkImageView_type = { "VkImageView", sizeof (VkImageView), 0, 0, 0 @@ -610,7 +621,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, plitem_t *imageViewItem = 0; if (ret) { VkImageView imageView; - if (value->type == &imageview_type) { + if (value->type == &VkImageView_type) { imageView = *(VkImageView *) value->value; } else if (value->type == &cexpr_plitem) { imageView = QFV_ParseImageView (ctx, imageViewItem, @@ -856,82 +867,21 @@ parse_specialization_data (const plitem_t *item, void **data, #include "libs/video/renderer/vulkan/vkparse.cinc" -static void -imageviewset_index (const exprval_t *a, size_t index, exprval_t *c, - exprctx_t *ctx) -{ - __auto_type set = *(qfv_imageviewset_t **) a->value; - exprval_t *val = 0; - if (index >= set->size) { - cexpr_error (ctx, "invalid index: %zd", index); - } else { - val = cexpr_value (&imageview_type, ctx); - *(VkImageView *) val->value = set->a[index]; - } - *(exprval_t **) c->value = val; -} - -static void -imageviewset_int (const exprval_t *a, const exprval_t *b, exprval_t *c, - exprctx_t *ctx) -{ - size_t index = *(int *) b->value; - imageviewset_index (a, index, c, ctx); -} - -static void -imageviewset_uint (const exprval_t *a, const exprval_t *b, exprval_t *c, - exprctx_t *ctx) -{ - size_t index = *(unsigned *) b->value; - imageviewset_index (a, index, c, ctx); -} - -static void -imageviewset_size_t (const exprval_t *a, const exprval_t *b, exprval_t *c, - exprctx_t *ctx) -{ - size_t index = *(size_t *) b->value; - imageviewset_index (a, index, c, ctx); -} - -binop_t imageviewset_binops[] = { - { '.', &cexpr_field, &cexpr_exprval, cexpr_struct_pointer_getfield }, - { '[', &cexpr_int, &imageview_type, imageviewset_int }, - { '[', &cexpr_uint, &imageview_type, imageviewset_uint }, - { '[', &cexpr_size_t, &imageview_type, imageviewset_size_t }, - {} -}; - -static exprsym_t imageviewset_symbols[] = { - {"size", &cexpr_size_t, (void *)field_offset (qfv_imageviewset_t, size)}, +static exprsym_t qfv_output_t_symbols[] = { + {"format", &VkFormat_type, (void *)field_offset (qfv_output_t, format)}, + {"extent", &VkExtent2D_type, (void *)field_offset (qfv_output_t, extent)}, + {"view", &VkImageView_type, (void *)field_offset (qfv_output_t, view)}, { } }; -static exprtab_t imageviewset_symtab = { - imageviewset_symbols, +static exprtab_t qfv_output_t_symtab = { + qfv_output_t_symbols, }; -exprtype_t imageviewset_type = { - "imageviewset", - sizeof (qfv_imageviewset_t *), - imageviewset_binops, - 0, - &imageviewset_symtab, -}; -static exprsym_t qfv_swapchain_t_symbols[] = { - {"format", &VkFormat_type, (void *)field_offset (qfv_swapchain_t, format)}, - {"extent", &VkExtent2D_type, (void *)field_offset (qfv_swapchain_t, extent)}, - {"views", &imageviewset_type, (void *)field_offset (qfv_swapchain_t, imageViews)}, - { } -}; -static exprtab_t qfv_swapchain_t_symtab = { - qfv_swapchain_t_symbols, -}; -exprtype_t qfv_swapchain_t_type = { - "qfv_swapchain_t", - sizeof (qfv_swapchain_t), +exprtype_t qfv_output_t_type = { + "qfv_output_t", + sizeof (qfv_output_t), cexpr_struct_binops, 0, - &qfv_swapchain_t_symtab, + &qfv_output_t_symtab, }; static exprsym_t vulkan_frameset_t_symbols[] = { @@ -1023,9 +973,8 @@ QFV_InitParse (vulkan_ctx_t *ctx) &ctx->hashlinks); context.hashlinks = &ctx->hashlinks; vkgen_init_symtabs (&context); - cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); + cexpr_init_symtab (&qfv_output_t_symtab, &context); cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); - cexpr_init_symtab (&imageviewset_symtab, &context); cexpr_init_symtab (&data_array_symtab, &context); if (!ctx->setLayouts) { @@ -1054,10 +1003,9 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, exprctx_t exprctx = { .symtab = &root_symtab }; parsectx_t parsectx = { &exprctx, ctx, properties }; exprsym_t var_syms[] = { - {"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, + {"output", &qfv_output_t_type, &ctx->output}, {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {"swapImageIndex", &cexpr_uint, &ctx->swapImageIndex}, {"physDevLimits", &VkPhysicalDeviceLimits_type, &ctx->device->physDev->properties.limits }, {QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties}, diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 6f2ea6357..730094e3b 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -10,24 +10,12 @@ typedef struct parsectx_s { #include "QF/cexpr.h" #include "QF/plist.h" -#include "QF/Vulkan/renderpass.h" #ifdef vkparse_internal #include "libs/video/renderer/vulkan/vkparse.hinc" #endif #define QFV_PROPERTIES "properties" -typedef struct parseres_s { - const char *name; - plfield_t *field; - size_t offset; -} parseres_t; - -typedef struct handleref_s { - char *name; - uint64_t handle; -} handleref_t; - void QFV_InitParse (vulkan_ctx_t *ctx); exprenum_t *QFV_GetEnum (const char *name); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index d5cbcfaf6..e429f688b 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -388,7 +388,11 @@ create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, malloc); for (size_t i = 0; i < rp->framebuffers->size; i++) { - ctx->swapImageIndex = i; // for $swapImageIndex in the config + ctx->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[i], + .format = ctx->swapchain->format, + }; rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, rp->renderpassDef); } @@ -424,6 +428,11 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) if (renderpass) { rp->renderpass = renderpass; } else { + ctx->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[0], + .format = ctx->swapchain->format, + }; item = qfv_load_renderpass (ctx, rp, name); rp->renderpass = QFV_ParseRenderPass (ctx, item, rp->renderpassDef); QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); From ef574e67d0e014a461b9575facc79099b5c3934e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 6 Apr 2022 19:32:55 +0900 Subject: [PATCH 2663/3664] [net] Remove client references from net_main This is progress towards #23. There are still some references to host_time and host_client (via nq's server.h), and a lot of references to sv and svs, but this is definitely a step in the right direction. --- include/netmain.h | 5 ++++- libs/net/net_main.c | 21 +++++++++++++-------- libs/net/nm/net_dgrm.c | 2 -- libs/net/nm/net_loop.c | 3 +-- libs/net/nm/net_wins.c | 1 - nq/include/client.h | 1 - nq/source/cl_main.c | 4 +--- nq/source/host.c | 22 +++++++++++----------- nq/source/host_cmd.c | 14 +++++++------- nq/source/sv_main.c | 2 +- nq/source/sys_sdl.c | 2 +- nq/source/sys_unix.c | 2 +- nq/source/sys_win.c | 2 +- 13 files changed, 41 insertions(+), 40 deletions(-) diff --git a/include/netmain.h b/include/netmain.h index 0a4587b26..882b7acc9 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -270,9 +270,11 @@ extern double net_time; extern struct msg_s *net_message; extern unsigned net_activeconnections; +struct cbuf_s; + /** Initialize the networking sub-system. */ -void NET_Init (void); +void NET_Init (struct cbuf_s *cbuf); /** Check for new connections. @@ -447,6 +449,7 @@ typedef struct { extern int net_numdrivers; extern net_driver_t net_drivers[MAX_NET_DRIVERS]; +extern int net_is_dedicated; ///@} diff --git a/libs/net/net_main.c b/libs/net/net_main.c index e534c4156..6ef7e9a0f 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -47,9 +47,10 @@ #include "netmain.h" #include "net_vcr.h" -#include "../nq/include/host.h" #include "../nq/include/server.h" +int net_is_dedicated = 0; + qsocket_t *net_activeSockets = NULL; qsocket_t *net_freeSockets = NULL; int net_numsockets = 0; @@ -102,6 +103,8 @@ double net_time; static int hostCacheCount = 0; static hostcache_t hostcache[HOSTCACHESIZE]; +static cbuf_t *net_cbuf; + double SetNetTime (void) { @@ -219,10 +222,10 @@ MaxPlayers_f (void) } if ((n == 1) && listening) - Cbuf_AddText (host_cbuf, "listen 0\n"); + Cbuf_AddText (net_cbuf, "listen 0\n"); if ((n > 1) && (!listening)) - Cbuf_AddText (host_cbuf, "listen 1\n"); + Cbuf_AddText (net_cbuf, "listen 1\n"); svs.maxclients = n; if (n == 1) @@ -253,8 +256,8 @@ NET_Port_f (void) if (listening) { // force a change to the new port - Cbuf_AddText (host_cbuf, "listen 0\n"); - Cbuf_AddText (host_cbuf, "listen 1\n"); + Cbuf_AddText (net_cbuf, "listen 0\n"); + Cbuf_AddText (net_cbuf, "listen 1\n"); } } @@ -796,12 +799,14 @@ NET_shutdown (void *data) } void -NET_Init (void) +NET_Init (cbuf_t *cbuf) { int i; int controlSocket; qsocket_t *s; + net_cbuf = cbuf; + Sys_RegisterShutdown (NET_shutdown, 0); if (COM_CheckParm ("-playback")) { @@ -826,10 +831,10 @@ NET_Init (void) } net_hostport = DEFAULTnet_hostport; - if (COM_CheckParm ("-listen") || cls.state == ca_dedicated) + if (COM_CheckParm ("-listen") || net_is_dedicated) listening = true; net_numsockets = svs.maxclientslimit; - if (cls.state != ca_dedicated) + if (!net_is_dedicated) net_numsockets++; SetNetTime (); diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 9aa10ef31..71f74ff4a 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -46,9 +46,7 @@ #include "netmain.h" -#include "../nq/include/client.h" #include "../nq/include/server.h" -#include "../nq/include/game.h" // This is enables a simple IP banning mechanism #define BAN_TEST diff --git a/libs/net/nm/net_loop.c b/libs/net/nm/net_loop.c index cb1ddb180..ddf61f6f3 100644 --- a/libs/net/nm/net_loop.c +++ b/libs/net/nm/net_loop.c @@ -35,7 +35,6 @@ #include "netmain.h" #include "net_loop.h" -#include "../nq/include/client.h" #include "../nq/include/server.h" qboolean localconnectpending = false; @@ -45,7 +44,7 @@ qsocket_t *loop_server = NULL; __attribute__((pure)) int Loop_Init (void) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) return -1; return 0; } diff --git a/libs/net/nm/net_wins.c b/libs/net/nm/net_wins.c index 6b779bfa5..411c0b838 100644 --- a/libs/net/nm/net_wins.c +++ b/libs/net/nm/net_wins.c @@ -1,4 +1,3 @@ - /* net_wins.c diff --git a/nq/include/client.h b/nq/include/client.h index 3096f6321..4e5c148e8 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -70,7 +70,6 @@ typedef enum { #define MAX_DEMONAME 16 typedef enum { - ca_dedicated, // a dedicated server with no ability to start a client ca_disconnected, // full screen console with no connection ca_connected, // talking to a server ca_active, // everything is in, so frames can be rendered diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 3b63db068..1a489621a 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -306,7 +306,7 @@ CL_Disconnect_f (void) void CL_EstablishConnection (const char *host) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) return; if (cls.demoplayback) @@ -510,8 +510,6 @@ CL_SetState (cactive_t state) r_funcs->R_ClearState (); } switch (state) { - case ca_dedicated: - break; case ca_disconnected: CL_ClearState (); cls.signon = so_none; diff --git a/nq/source/host.c b/nq/source/host.c index d19d30114..86b428c5a 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -157,7 +157,7 @@ Host_EndGame (const char *message, ...) if (sv.active) Host_ShutdownServer (false); - if (cls.state == ca_dedicated) + if (net_is_dedicated) Sys_Error ("Host_EndGame: %s", str->str); // dedicated servers exit if (cls.demonum != -1) @@ -197,7 +197,7 @@ Host_Error (const char *error, ...) if (sv.active) Host_ShutdownServer (false); - if (cls.state == ca_dedicated) + if (net_is_dedicated) Sys_Error ("Host_Error: %s", str->str); // dedicated servers exit Sys_Printf ("Host_Error: %s\n", str->str); @@ -219,17 +219,17 @@ Host_FindMaxClients (void) i = COM_CheckParm ("-dedicated"); if (i) { - cls.state = ca_dedicated; if (i != (com_argc - 1)) { svs.maxclients = atoi (com_argv[i + 1]); } else svs.maxclients = 8; - } else - cls.state = ca_disconnected; + } + cls.state = ca_disconnected; + net_is_dedicated = i; i = COM_CheckParm ("-listen"); if (i) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) Sys_Error ("Only one of -dedicated or -listen can be specified"); if (i != (com_argc - 1)) svs.maxclients = atoi (com_argv[i + 1]); @@ -676,10 +676,10 @@ _Host_Frame (float time) return; } - if (cls.state != ca_dedicated) + if (!net_is_dedicated) IN_ProcessEvents (); - if (cls.state == ca_dedicated) + if (net_is_dedicated) Con_ProcessInput (); GIB_Thread_Execute (); @@ -708,7 +708,7 @@ _Host_Frame (float time) Host_ServerFrame (); } - if (cls.state != ca_dedicated) + if (!net_is_dedicated) Host_ClientFrame (); else host_time += host_frametime; //FIXME is this needed? vcr stuff @@ -920,13 +920,13 @@ Host_Init (void) Host_InitVCR (&host_parms); Host_InitLocal (); - NET_Init (); + NET_Init (host_cbuf); Mod_Init (); SV_Init (); - if (cls.state != ca_dedicated) + if (!net_is_dedicated) CL_Init (host_cbuf); if (con_module) { diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index e58098241..2ad67d3b3 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -303,7 +303,7 @@ Host_Map_f (void) if (!sv.active) return; - if (cls.state != ca_dedicated) { + if (!net_is_dedicated) { Cmd_ExecuteString ("connect local", src_command); } } @@ -717,7 +717,7 @@ Host_Loadgame_f (void) for (i = 0; i < NUM_SPAWN_PARMS; i++) svs.clients->spawn_parms[i] = spawn_parms[i]; - if (cls.state != ca_dedicated) { + if (!net_is_dedicated) { CL_EstablishConnection ("local"); Host_Reconnect_f (); } @@ -790,7 +790,7 @@ Host_Say (qboolean teamonly) qboolean fromServer = false; if (cmd_source == src_command) { - if (cls.state == ca_dedicated) { + if (net_is_dedicated) { fromServer = true; teamonly = false; } else { @@ -1134,7 +1134,7 @@ Host_Kick_f (void) if (i < svs.maxclients) { if (cmd_source == src_command) - if (cls.state == ca_dedicated) + if (net_is_dedicated) who = "Console"; else who = cl_name->string; @@ -1403,7 +1403,7 @@ Host_Startdemos_f (void) { int i, c; - if (cls.state == ca_dedicated) { + if (net_is_dedicated) { if (!sv.active) Cbuf_AddText (host_cbuf, "map start\n"); return; @@ -1434,7 +1434,7 @@ Host_Startdemos_f (void) static void Host_Demos_f (void) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) return; if (cls.demonum == -1) cls.demonum = 1; @@ -1450,7 +1450,7 @@ Host_Demos_f (void) static void Host_Stopdemo_f (void) { - if (cls.state == ca_dedicated) + if (net_is_dedicated) return; if (!cls.demoplayback) return; diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 21a18fbfc..57282ea1d 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1064,7 +1064,7 @@ SV_SendReconnect (void) MSG_WriteString (&msg, "reconnect\n"); NET_SendToAll (&msg, 5.0); - if (cls.state != ca_dedicated) + if (!net_is_dedicated) Cmd_ExecuteString ("reconnect\n", src_command); } diff --git a/nq/source/sys_sdl.c b/nq/source/sys_sdl.c index 76e84b558..68c2e91eb 100644 --- a/nq/source/sys_sdl.c +++ b/nq/source/sys_sdl.c @@ -136,7 +136,7 @@ SDL_main (int argc, char *argv[]) newtime = Sys_DoubleTime (); time = newtime - oldtime; - if (cls.state == ca_dedicated) { // play vcrfiles at max speed + if (net_is_dedicated) { // play vcrfiles at max speed if (time < sys_ticrate->value && (!vcrFile || recording)) { usleep (1); continue; // not time to run a server-only tic yet diff --git a/nq/source/sys_unix.c b/nq/source/sys_unix.c index 20cce79a5..e244b940e 100644 --- a/nq/source/sys_unix.c +++ b/nq/source/sys_unix.c @@ -91,7 +91,7 @@ main (int argc, const char **argv) newtime = Sys_DoubleTime (); time = newtime - oldtime; - if (cls.state == ca_dedicated) { // play vcrfiles at max speed + if (net_is_dedicated) { // play vcrfiles at max speed if (time < sys_ticrate->value && (!vcrFile || recording)) { usleep (1); continue; // not time to run a server-only tic yet diff --git a/nq/source/sys_win.c b/nq/source/sys_win.c index ee040f956..59c61b796 100644 --- a/nq/source/sys_win.c +++ b/nq/source/sys_win.c @@ -228,7 +228,7 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, newtime = Sys_DoubleTime (); time = newtime - oldtime; - if (cls.state == ca_dedicated) { // play vcrfiles at max speed + if (net_is_dedicated) { // play vcrfiles at max speed if (time < sys_ticrate->value && (!vcrFile || recording)) { Sleep (1); continue; // not time to run a server-only tic yet From d987cef32eecffc16a07da8def36c84edae8c9d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 8 Apr 2022 20:07:45 +0900 Subject: [PATCH 2664/3664] [qw] Fix an extern in a C file Rather worrying finding one. I guess I didn't feel like finding a header for the declaration at time time. --- qw/include/client.h | 2 ++ qw/source/cl_main.c | 1 - qw/source/cl_parse.c | 2 -- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/qw/include/client.h b/qw/include/client.h index 57b87f514..dbd0f35d0 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -280,6 +280,8 @@ extern struct cvar_s *skin; extern struct cvar_s *cl_fb_players; +extern struct cvar_s *hud_scoreboard_uid; + extern client_state_t cl; extern entity_t *cl_entities[512]; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index c70a137ef..7b4179907 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -216,7 +216,6 @@ jmp_buf host_abort; char *server_version = NULL; // version of server we connected to -extern cvar_t *hud_scoreboard_uid; static netadr_t cl_cmd_packet_address; static void diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index c7478445d..cd97ec003 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -172,8 +172,6 @@ int cl_h_playerindex, cl_gib1index, cl_gib2index, cl_gib3index; int packet_latency[NET_TIMINGS]; -extern cvar_t *hud_scoreboard_uid; - int CL_CalcNet (void) { From 55f78866078f357381eeb4b232e606e4111ff00b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 9 Apr 2022 01:06:03 +0900 Subject: [PATCH 2665/3664] Remove some long dead cvars The declarations were still around, but the creation and code using them was removed long ago. --- include/QF/input.h | 1 - include/d_local.h | 2 -- include/r_cvar.h | 4 ---- include/r_local.h | 1 - include/snd_internal.h | 4 ---- libs/audio/renderer/snd_dma.c | 1 + libs/video/renderer/gl/vid_common_gl.c | 4 ---- nq/include/client.h | 4 ---- qw/include/cl_main.h | 1 - qw/include/client.h | 2 -- qw/source/cl_skin.c | 2 +- 11 files changed, 2 insertions(+), 24 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index ade3b97d0..119ad170b 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -129,7 +129,6 @@ void IN_ClearStates (void); extern struct cvar_s *in_grab; extern struct cvar_s *in_amp; extern struct cvar_s *in_pre_amp; -extern struct cvar_s *m_filter; extern struct cvar_s *in_mouse_accel; extern struct cvar_s *in_freelook; extern struct cvar_s *lookstrafe; diff --git a/include/d_local.h b/include/d_local.h index 51a2cd220..7b9cc3fac 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -63,8 +63,6 @@ typedef struct sspan_s { int u, v, count; } sspan_t; -extern struct cvar_s *d_subdiv16; - extern float scale_for_mip; extern qboolean d_roverwrapped; diff --git a/include/r_cvar.h b/include/r_cvar.h index 5b1090c1d..756c2ef03 100644 --- a/include/r_cvar.h +++ b/include/r_cvar.h @@ -59,9 +59,7 @@ extern struct cvar_s *r_explosionclip; extern struct cvar_s *r_farclip; extern struct cvar_s *r_firecolor; extern struct cvar_s *r_flatlightstyles; -extern struct cvar_s *r_fullbright; extern struct cvar_s *r_graphheight; -extern struct cvar_s *r_lightmap; extern struct cvar_s *r_lightmap_components; extern struct cvar_s *r_maxedges; extern struct cvar_s *r_maxsurfs; @@ -85,8 +83,6 @@ extern struct cvar_s *r_waterripple; extern struct cvar_s *r_waterwarp; extern struct cvar_s *r_zgraph; -extern struct cvar_s *scr_consize; -extern struct cvar_s *scr_conspeed; extern struct cvar_s *scr_fov; extern struct cvar_s *scr_fisheye; extern struct cvar_s *scr_fviews; diff --git a/include/r_local.h b/include/r_local.h index e6a068501..ef0db6963 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -71,7 +71,6 @@ extern struct cvar_s *r_timegraph; extern struct cvar_s *r_graphheight; extern struct cvar_s *r_clearcolor; extern struct cvar_s *r_waterwarp; -extern struct cvar_s *r_fullbright; extern struct cvar_s *r_drawentities; extern struct cvar_s *r_aliasstats; extern struct cvar_s *r_dspeeds; diff --git a/include/snd_internal.h b/include/snd_internal.h index 8d95d0615..078d32cbb 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -229,12 +229,8 @@ struct channel_s { //@} }; -extern struct cvar_s *snd_loadas8bit; extern struct cvar_s *snd_volume; -extern struct cvar_s *snd_interp; -extern struct cvar_s *snd_stereo_phase_separation; - extern snd_render_data_t snd_render_data; #define PAINTBUFFER_SIZE 512 extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index ecf5b2707..010793cae 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -345,6 +345,7 @@ s_init (void) "fix permanently blocked sound"); // FIXME +//extern struct cvar_s *snd_loadas8bit; // if (host_parms.memsize < 0x800000) { // Cvar_Set (snd_loadas8bit, "1"); // Sys_Printf ("loading all sounds as 8bit\n"); diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index d1547d2d9..e0e5f5231 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -113,7 +113,6 @@ int gl_tess; int gl_max_lights; cvar_t *gl_anisotropy; -cvar_t *gl_doublebright; cvar_t *gl_fb_bmodels; cvar_t *gl_finish; cvar_t *gl_max_size; @@ -485,9 +484,6 @@ CheckCombineExtensions (void) "doublebright enabled.\n"); } else { gl_combine_capable = false; - Sys_MaskPrintf (SYS_vid, "GL_ARB_texture_env_combine not found. " - "gl_doublebright will have no effect with " - "gl_multitexture on.\n"); } } diff --git a/nq/include/client.h b/nq/include/client.h index 4e5c148e8..de0e7cb02 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -213,13 +213,9 @@ typedef struct client_state_s { extern struct cvar_s *cl_name; extern struct cvar_s *cl_color; -extern struct cvar_s *cl_autofire; - extern struct cvar_s *cl_shownet; extern struct cvar_s *cl_nolerp; -extern struct cvar_s *cl_pitchdriftspeed; - extern struct cvar_s *cl_name; extern struct cvar_s *cl_writecfg; diff --git a/qw/include/cl_main.h b/qw/include/cl_main.h index 640c206cc..61d9d0481 100644 --- a/qw/include/cl_main.h +++ b/qw/include/cl_main.h @@ -52,7 +52,6 @@ void CL_BeginServerConnect(void); #define soundlist_name "soundlist %i %i" -extern struct cvar_s *cl_timeframes; extern struct cvar_s *cl_predict_players; extern struct cvar_s *cl_solid_players; extern struct cvar_s *cl_autoexec; diff --git a/qw/include/client.h b/qw/include/client.h index dbd0f35d0..876bc6cca 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -265,8 +265,6 @@ extern struct cvar_s *cl_netgraph_box; extern struct cvar_s *cl_draw_locs; extern struct cvar_s *cl_shownet; -extern struct cvar_s *cl_pitchdriftspeed; - extern struct cvar_s *cl_name; extern struct cvar_s *cl_model_crcs; diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index 24f2a809d..6ff72805b 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -200,7 +200,7 @@ CL_Skin_Init (void) "shirt pants) Note that if only shirt color is given, " "pants will match"); - noskins = Cvar_Get ("noskins", "0", CVAR_ARCHIVE, NULL, //XXX FIXME + noskins = Cvar_Get ("noskins", "0", CVAR_ARCHIVE, NULL, "set to 1 to not download new skins"); skin = Cvar_Get ("skin", "", CVAR_ARCHIVE | CVAR_USERINFO, skin_f, "Players skin"); From 001b3eb908ca0fb86c8f358e31c57151fd32a97e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 9 Apr 2022 01:57:14 +0900 Subject: [PATCH 2666/3664] Fix some inconsistent cvar uses Surprisingly, only two, but they were caught by the different value fields being used, thus the cvar was checked in multiple places. I imagine that's not really all that common, so there may be some inconsistencies between default value and use. --- libs/video/renderer/sw/sw_fisheye.c | 2 +- qw/source/sv_user.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/sw/sw_fisheye.c b/libs/video/renderer/sw/sw_fisheye.c index c1c782e47..83d6c2a15 100644 --- a/libs/video/renderer/sw/sw_fisheye.c +++ b/libs/video/renderer/sw/sw_fisheye.c @@ -128,7 +128,7 @@ R_RenderFisheye (framebuffer_t *cube) { int width = r_refdef.vrect.width; int height = r_refdef.vrect.height; - int fov = scr_ffov->int_val; + float fov = scr_ffov->value; static int pwidth = -1; static int pheight = -1; static int pfov = -1; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index a9eb02fe4..31dc6c142 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -940,7 +940,7 @@ SV_Say (qboolean team) } // non-team messages should be seen allways, even if not tracking any // player - if (!team && ((host_client->spectator && sv_spectalk->value) + if (!team && ((host_client->spectator && sv_spectalk->int_val) || !host_client->spectator)) { dbuf = SVR_WriteBegin (dem_all, 0, strlen (text->str) + 3); } else { From 8a411dc1206ee432010d1b1eb2a94652ef5a96e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 13 Apr 2022 11:27:50 +0900 Subject: [PATCH 2667/3664] [joy] Clean up some redundant cvar flags No need to or CVAR_NONE with other flags. --- libs/video/targets/joy.c | 8 ++++---- libs/video/targets/joy_win.c | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libs/video/targets/joy.c b/libs/video/targets/joy.c index a7a55f6dd..3ff827726 100644 --- a/libs/video/targets/joy.c +++ b/libs/video/targets/joy.c @@ -466,12 +466,12 @@ JOY_Init_Cvars (void) int i; joy_device = Cvar_Get ("joy_device", "/dev/input/js0", - CVAR_NONE | CVAR_ROM, 0, "Joystick device"); - joy_enable = Cvar_Get ("joy_enable", "1", CVAR_NONE | CVAR_ARCHIVE, 0, + CVAR_ROM, 0, "Joystick device"); + joy_enable = Cvar_Get ("joy_enable", "1", CVAR_ARCHIVE, 0, "Joystick enable flag"); - joy_amp = Cvar_Get ("joy_amp", "1", CVAR_NONE | CVAR_ARCHIVE, joyamp_f, + joy_amp = Cvar_Get ("joy_amp", "1", CVAR_ARCHIVE, joyamp_f, "Joystick amplification"); - joy_pre_amp = Cvar_Get ("joy_pre_amp", "0.01", CVAR_NONE | CVAR_ARCHIVE, + joy_pre_amp = Cvar_Get ("joy_pre_amp", "0.01", CVAR_ARCHIVE, joyamp_f, "Joystick pre-amplification"); Cmd_AddCommand ("in_joy", in_joy_f, "Configures the joystick behaviour"); diff --git a/libs/video/targets/joy_win.c b/libs/video/targets/joy_win.c index babd2e270..f42b5022a 100644 --- a/libs/video/targets/joy_win.c +++ b/libs/video/targets/joy_win.c @@ -353,12 +353,11 @@ void JOY_Init_Cvars(void) { // joystick variables - joy_device = Cvar_Get ("joy_device", "none", CVAR_NONE | CVAR_ROM, 0, + joy_device = Cvar_Get ("joy_device", "none", CVAR_ROM, 0, "Joystick device"); - joy_enable = Cvar_Get ("joy_enable", "1", CVAR_NONE | CVAR_ARCHIVE, 0, + joy_enable = Cvar_Get ("joy_enable", "1", CVAR_ARCHIVE, 0, "Joystick enable flag"); - joy_sensitivity = Cvar_Get ("joy_sensitivity", "1", CVAR_NONE | - CVAR_ARCHIVE, 0, "Joystick sensitivity"); + joy_sensitivity = Cvar_Get ("joy_sensitivity", "1", CVAR_ARCHIVE, 0, "Joystick sensitivity"); in_joystick = Cvar_Get ("joystick", "0", CVAR_ARCHIVE, 0, "FIXME: No " "Description"); joy_name = Cvar_Get ("joyname", "joystick", CVAR_NONE, 0, "FIXME: No " From db5b77c838d5071a07371328d714efd953f5a358 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 14:55:35 +0900 Subject: [PATCH 2668/3664] [cexpr] Require designated initializers for exprtype_t This will make expanding it much safer in the future. --- include/QF/cexpr.h | 2 +- libs/util/cexpr-type.c | 88 +++++++++---------- libs/util/cexpr-vars.c | 8 +- libs/util/test/test-cexpr.c | 10 +-- libs/video/renderer/vulkan/vkgen/vkenum.r | 25 +++--- .../renderer/vulkan/vkgen/vkfixedarray.r | 12 +-- libs/video/renderer/vulkan/vkgen/vkstruct.r | 10 +-- libs/video/renderer/vulkan/vkparse.c | 36 ++++---- 8 files changed, 100 insertions(+), 91 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 75e7e8ae1..b8bc734f5 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -55,7 +55,7 @@ typedef struct exprtype_s { binop_t *binops; unop_t *unops; void *data; -} exprtype_t; +} __attribute__((designated_init)) exprtype_t; typedef struct exprval_s { exprtype_t *type; diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 1efbb2f2a..9c62dec40 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -124,10 +124,10 @@ unop_t int_unops[] = { }; exprtype_t cexpr_int = { - "int", - sizeof (int), - int_binops, - int_unops, + .name = "int", + .size = sizeof (int), + .binops = int_binops, + .unops = int_unops, }; BINOP(uint, shl, unsigned, <<) @@ -179,10 +179,10 @@ unop_t uint_unops[] = { }; exprtype_t cexpr_uint = { - "uint", - sizeof (unsigned), - uint_binops, - uint_unops, + .name = "uint", + .size = sizeof (unsigned), + .binops = uint_binops, + .unops = uint_unops, }; BINOP(size_t, shl, unsigned, <<) @@ -248,10 +248,10 @@ unop_t size_t_unops[] = { }; exprtype_t cexpr_size_t = { - "size_t", - sizeof (size_t), - size_t_binops, - size_t_unops, + .name = "size_t", + .size = sizeof (size_t), + .binops = size_t_binops, + .unops = size_t_unops, }; BINOP(float, add, float, +) @@ -333,10 +333,10 @@ unop_t float_unops[] = { }; exprtype_t cexpr_float = { - "float", - sizeof (float), - float_binops, - float_unops, + .name = "float", + .size = sizeof (float), + .binops = float_binops, + .unops = float_unops, }; BINOP(double, add, double, +) @@ -397,10 +397,10 @@ unop_t double_unops[] = { }; exprtype_t cexpr_double = { - "double", - sizeof (double), - double_binops, - double_unops, + .name = "double", + .size = sizeof (double), + .binops = double_binops, + .unops = double_unops, }; BINOP(vector, add, vec4f_t, +) @@ -546,10 +546,10 @@ unop_t vector_unops[] = { }; exprtype_t cexpr_vector = { - "vector", - sizeof (vec4f_t), - vector_binops, - vector_unops, + .name = "vector", + .size = sizeof (vec4f_t), + .binops = vector_binops, + .unops = vector_unops, }; static void @@ -588,31 +588,31 @@ unop_t quaternion_unops[] = { }; exprtype_t cexpr_quaternion = { - "quaterion", - sizeof (vec4f_t), - quaternion_binops, - quaternion_unops, + .name = "quaterion", + .size = sizeof (vec4f_t), + .binops = quaternion_binops, + .unops = quaternion_unops, }; exprtype_t cexpr_exprval = { - "exprval", - sizeof (exprval_t *), - 0, // can't actually do anything with an exprval - 0, + .name = "exprval", + .size = sizeof (exprval_t *), + .binops = 0, // can't actually do anything with an exprval + .unops = 0, }; exprtype_t cexpr_field = { - "field", - 0, // has no size of its own, rather, it's the length of the name - 0, // can't actually do anything with a field - 0, + .name = "field", + .size = 0, // has no size of its own, rather, it's the length of the name + .binops = 0, // can't actually do anything with a field + .unops = 0, }; exprtype_t cexpr_function = { - "function", - 0, // has no size of its own - 0, // can't actually do anything with a function other than call - 0, + .name = "function", + .size = 0, // has no size of its own + .binops = 0,// can't actually do anything with a function other than call + .unops = 0, }; void @@ -711,10 +711,10 @@ binop_t plitem_binops[] = { }; exprtype_t cexpr_plitem = { - "plitem", - sizeof (plitem_t *), - plitem_binops, - 0, + .name = "plitem", + .size = sizeof (plitem_t *), + .binops = plitem_binops, + .unops = 0, }; VISIBLE binop_t * diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c index afe8de859..c9af82710 100644 --- a/libs/util/cexpr-vars.c +++ b/libs/util/cexpr-vars.c @@ -114,10 +114,10 @@ static binop_t cvar_binops[] = { }; static exprtype_t cvar_type = { - "cvar", - sizeof (void *), // ref to struct (will always be 0) - cvar_binops, - 0, + .name = "cvar", + .size = sizeof (void *), // ref to struct (will always be 0) + .binops = cvar_binops, + .unops = 0, }; VISIBLE exprval_t * diff --git a/libs/util/test/test-cexpr.c b/libs/util/test/test-cexpr.c index b67eea284..5b3de9875 100644 --- a/libs/util/test/test-cexpr.c +++ b/libs/util/test/test-cexpr.c @@ -50,11 +50,11 @@ exprarray_t int_array_4_data = { sizeof (array) / sizeof (array[0]), }; exprtype_t int_array_4 = { - "int[4]", - 4 * sizeof (int), - cexpr_array_binops, - 0, - &int_array_4_data, + .name = "int[4]", + .size = 4 * sizeof (int), + .binops = cexpr_array_binops, + .unops = 0, + .data = &int_array_4_data, }; exprsym_t symbols[] = { diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index ab0ec084c..cc22577a5 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -89,16 +89,17 @@ skip_value(string name) strip_bit = 1; } - fprintf (output_file, "static exprtype_t %s_type = {\n", [self name]); - fprintf (output_file, "\t\"%s\",\n", [self name]); - fprintf (output_file, "\tsizeof (int),\n"); + fprintf (output_file, "exprtype_t %s_type = {\n", [self name]); + fprintf (output_file, "\t.name = \"%s\",\n", [self name]); + fprintf (output_file, "\t.size = sizeof (int),\n"); if (strip_bit) { - fprintf (output_file, "\tflag_binops,\n"); - fprintf (output_file, "\tflag_unops,\n"); + fprintf (output_file, "\t.binops = flag_binops,\n"); + fprintf (output_file, "\t.unops = flag_unops,\n"); } else { - fprintf (output_file, "\tenum_binops,\n"); - fprintf (output_file, "\t0,\n"); + fprintf (output_file, "\t.binops = enum_binops,\n"); + fprintf (output_file, "\t.unops = 0,\n"); } + fprintf (output_file, "\t.data = &%s_enum,\n", [self name]); fprintf (output_file, "};\n"); if (![self isEmpty]) { @@ -114,7 +115,7 @@ skip_value(string name) } fprintf (output_file, "};\n"); } - fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self name]); + fprintf (output_file, "exprsym_t %s_symbols[] = {\n", [self name]); for (int i = 0, index = 0; i < type.strct.num_fields; i++) { qfot_var_t *var = &type.strct.fields[i]; if (skip_value (var.name)) { @@ -137,10 +138,10 @@ skip_value(string name) } fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); - fprintf (output_file, "static exprtab_t %s_symtab = {\n", [self name]); + fprintf (output_file, "exprtab_t %s_symtab = {\n", [self name]); fprintf (output_file, "\t%s_symbols,\n", [self name]); fprintf (output_file, "};\n"); - fprintf (output_file, "static exprenum_t %s_enum = {\n", [self name]); + fprintf (output_file, "exprenum_t %s_enum = {\n", [self name]); fprintf (output_file, "\t&%s_type,\n", [self name]); fprintf (output_file, "\t&%s_symtab,\n", [self name]); fprintf (output_file, "};\n"); @@ -163,6 +164,10 @@ skip_value(string name) " const plitem_t *item, void *data, plitem_t *messages," " void *context);\n", [self name]); + fprintf (header_file, "extern exprenum_t %s_enum;\n", [self name]); + fprintf (header_file, "extern exprtype_t %s_type;\n", [self name]); + fprintf (header_file, "extern exprtab_t %s_symtab;\n", [self name]); + fprintf (header_file, "extern exprsym_t %s_symbols[];\n", [self name]); } -(void) writeSymtabInit diff --git a/libs/video/renderer/vulkan/vkgen/vkfixedarray.r b/libs/video/renderer/vulkan/vkgen/vkfixedarray.r index 36ad6f2f7..b7cd47463 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfixedarray.r +++ b/libs/video/renderer/vulkan/vkgen/vkfixedarray.r @@ -52,11 +52,13 @@ fprintf (output_file, "\t%d,\n", ele_count); fprintf (output_file, "};\n"); fprintf (output_file, "exprtype_t %s_type = {\n", [self name]); - fprintf (output_file, "\t\"%s[%d]\",\n", [ele_type name], ele_count); - fprintf (output_file, "\t%d * sizeof (%s),\n", ele_count, [ele_type name]); - fprintf (output_file, "\tcexpr_array_binops,\n"); - fprintf (output_file, "\t0,\n"); - fprintf (output_file, "\t&%s_array,\n", [self name]); + fprintf (output_file, "\t.name = \"%s[%d]\",\n", [ele_type name], + ele_count); + fprintf (output_file, "\t.size = %d * sizeof (%s),\n", ele_count, + [ele_type name]); + fprintf (output_file, "\t.binops = cexpr_array_binops,\n"); + fprintf (output_file, "\t.unops = 0,\n"); + fprintf (output_file, "\t.data = &%s_array,\n", [self name]); fprintf (output_file, "};\n"); fprintf (output_file, "\n"); fprintf (header_file, "extern exprtype_t %s_type;\n", [self name]); diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 500659bc0..cae788c22 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -189,11 +189,11 @@ fprintf (output_file, "};\n"); fprintf (output_file, "exprtype_t %s_type = {\n", [self outname]); - fprintf (output_file, "\t\"%s\",\n", [self outname]); - fprintf (output_file, "\tsizeof (%s),\n", [self outname]); - fprintf (output_file, "\tcexpr_struct_binops,\n"); - fprintf (output_file, "\t0,\n"); - fprintf (output_file, "\t&%s_symtab,\n", [self outname]); + fprintf (output_file, "\t.name = \"%s\",\n", [self outname]); + fprintf (output_file, "\t.size = sizeof (%s),\n", [self outname]); + fprintf (output_file, "\t.binops = cexpr_struct_binops,\n"); + fprintf (output_file, "\t.unops = 0,\n"); + fprintf (output_file, "\t.data = &%s_symtab,\n", [self outname]); fprintf (output_file, "};\n"); fprintf (output_file, "\n"); fprintf (header_file, "extern exprtype_t %s_type;\n", [self outname]); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 97fdd813d..1faf34bf5 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -589,9 +589,11 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, } exprtype_t VkImageView_type = { - "VkImageView", - sizeof (VkImageView), - 0, 0, 0 + .name = "VkImageView", + .size = sizeof (VkImageView), + .binops = 0, + .unops = 0, + .data = 0 }; static int @@ -805,10 +807,10 @@ data_array (const exprval_t **params, exprval_t *result, exprctx_t *context) } static exprtype_t data_array_type = { - "array", - sizeof (data_array_t *), - 0, - 0, + .name = "array", + .size = sizeof (data_array_t *), + .binops = 0, + .unops = 0, }; static exprfunc_t data_array_func[] = { { &data_array_type, -1, 0, data_array }, @@ -877,11 +879,11 @@ static exprtab_t qfv_output_t_symtab = { qfv_output_t_symbols, }; exprtype_t qfv_output_t_type = { - "qfv_output_t", - sizeof (qfv_output_t), - cexpr_struct_binops, - 0, - &qfv_output_t_symtab, + .name = "qfv_output_t", + .size = sizeof (qfv_output_t), + .binops = cexpr_struct_binops, + .unops = 0, + .data = &qfv_output_t_symtab, }; static exprsym_t vulkan_frameset_t_symbols[] = { @@ -892,11 +894,11 @@ static exprtab_t vulkan_frameset_t_symtab = { vulkan_frameset_t_symbols, }; exprtype_t vulkan_frameset_t_type = { - "frameset", - sizeof (vulkan_frameset_t *), - cexpr_struct_binops, - 0, - &vulkan_frameset_t_symtab, + .name = "frameset", + .size = sizeof (vulkan_frameset_t *), + .binops = cexpr_struct_binops, + .unops = 0, + .data = &vulkan_frameset_t_symtab, }; typedef struct { From 392e032ce29a2826d62c2cfbb46dc0961fb615f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 15:04:08 +0900 Subject: [PATCH 2669/3664] [cexpr] Add a get_string function to exprtype_t This allows for easy (and safe) printing of cexpr values where the type supports it. Types that don't support printing would be due to being too complex or possibly write-only (eg, password strings, when strings are supported directly). --- include/QF/cexpr.h | 3 + libs/util/cexpr-type.c | 72 +++++++++++++++++++++++ libs/video/renderer/vulkan/vkgen/vkenum.r | 2 + 3 files changed, 77 insertions(+) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index b8bc734f5..665595d92 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -31,6 +31,7 @@ struct exprval_s; struct exprctx_s; +struct va_ctx_s; typedef struct binop_s { int op; @@ -52,6 +53,7 @@ typedef struct unop_s { typedef struct exprtype_s { const char *name; size_t size; + const char *(*get_string) (const struct exprval_s *val, struct va_ctx_s *va_ctx); binop_t *binops; unop_t *unops; void *data; @@ -114,6 +116,7 @@ int cexpr_parse_enum (exprenum_t *enm, const char *str, binop_t *cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) __attribute__((pure)); exprval_t *cexpr_value (exprtype_t *type, exprctx_t *ctx); exprval_t *cexpr_value_reference (exprtype_t *type, void *data, exprctx_t *ctx); +const char *cexpr_enum_get_string (const exprval_t *val, struct va_ctx_s *va_ctx) __attribute__((pure)); int cexpr_eval_string (const char *str, exprctx_t *context); void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 9c62dec40..2df8bfdce 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -28,11 +28,14 @@ # include "config.h" #endif #include +#include #include "QF/cexpr.h" #include "QF/cmem.h" #include "QF/mathlib.h" #include "QF/plist.h" +#include "QF/sys.h" +#include "QF/va.h" #include "QF/simd/vec4f.h" #include "libs/util/cexpr-parse.h" @@ -99,6 +102,12 @@ int_mod (const exprval_t *val1, const exprval_t *val2, exprval_t *result, *(int *) result->value = c + (mask & b); } +static const char * +int_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + return va (va_ctx, "%d", *(int *) val->value); +} + binop_t int_binops[] = { { SHL, &cexpr_int, &cexpr_int, int_shl }, { SHR, &cexpr_int, &cexpr_int, int_shr }, @@ -128,6 +137,7 @@ exprtype_t cexpr_int = { .size = sizeof (int), .binops = int_binops, .unops = int_unops, + .get_string = int_get_string, }; BINOP(uint, shl, unsigned, <<) @@ -153,6 +163,12 @@ UNOP(uint, neg, unsigned, -) UNOP(uint, tnot, unsigned, !) UNOP(uint, bnot, unsigned, ~) +static const char * +uint_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + return va (va_ctx, "%u", *(unsigned *) val->value); +} + binop_t uint_binops[] = { { SHL, &cexpr_uint, &cexpr_uint, uint_shl }, { SHR, &cexpr_uint, &cexpr_uint, uint_shr }, @@ -183,6 +199,7 @@ exprtype_t cexpr_uint = { .size = sizeof (unsigned), .binops = uint_binops, .unops = uint_unops, + .get_string = uint_get_string, }; BINOP(size_t, shl, unsigned, <<) @@ -221,6 +238,12 @@ UNOP(size_t, neg, unsigned, -) UNOP(size_t, tnot, unsigned, !) UNOP(size_t, bnot, unsigned, ~) +static const char * +size_t_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + return va (va_ctx, "%zd", *(size_t *) val->value); +} + binop_t size_t_binops[] = { { SHL, &cexpr_size_t, &cexpr_size_t, size_t_shl }, { SHR, &cexpr_size_t, &cexpr_size_t, size_t_shr }, @@ -252,6 +275,7 @@ exprtype_t cexpr_size_t = { .size = sizeof (size_t), .binops = size_t_binops, .unops = size_t_unops, + .get_string = size_t_get_string, }; BINOP(float, add, float, +) @@ -309,6 +333,12 @@ UNOP(float, pos, float, +) UNOP(float, neg, float, -) UNOP(float, tnot, float, !) +static const char * +float_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + return va (va_ctx, "%.9g", *(float *) val->value); +} + binop_t float_binops[] = { { '+', &cexpr_float, &cexpr_float, float_add }, { '-', &cexpr_float, &cexpr_float, float_sub }, @@ -337,6 +367,7 @@ exprtype_t cexpr_float = { .size = sizeof (float), .binops = float_binops, .unops = float_unops, + .get_string = float_get_string, }; BINOP(double, add, double, +) @@ -375,6 +406,12 @@ UNOP(double, pos, double, +) UNOP(double, neg, double, -) UNOP(double, tnot, double, !) +static const char * +double_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + return va (va_ctx, "%.17g", *(double *) val->value); +} + binop_t double_binops[] = { { '+', &cexpr_double, &cexpr_double, double_add }, { '-', &cexpr_double, &cexpr_double, double_sub }, @@ -401,6 +438,7 @@ exprtype_t cexpr_double = { .size = sizeof (double), .binops = double_binops, .unops = double_unops, + .get_string = double_get_string, }; BINOP(vector, add, vec4f_t, +) @@ -518,6 +556,13 @@ vector_swizzle (const exprval_t *val1, const exprval_t *val2, UNOP(vector, pos, vec4f_t, +) UNOP(vector, neg, vec4f_t, -) +static const char * +vector_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + vec4f_t vec = *(vec4f_t *) val->value; + return va (va_ctx, VEC4F_FMT, VEC4_EXP (vec)); +} + static void vector_tnot (const exprval_t *val, exprval_t *result, exprctx_t *ctx) { @@ -550,6 +595,7 @@ exprtype_t cexpr_vector = { .size = sizeof (vec4f_t), .binops = vector_binops, .unops = vector_unops, + .get_string = vector_get_string, }; static void @@ -572,6 +618,13 @@ quaternion_vector_mul (const exprval_t *val1, const exprval_t *val2, *c = qvmulf (a, b); } +static const char * +quaternion_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + vec4f_t vec = *(vec4f_t *) val->value; + return va (va_ctx, VEC4F_FMT, VEC4_EXP (vec)); +} + binop_t quaternion_binops[] = { { '+', &cexpr_quaternion, &cexpr_quaternion, vector_add }, { '-', &cexpr_quaternion, &cexpr_quaternion, vector_sub }, @@ -592,6 +645,7 @@ exprtype_t cexpr_quaternion = { .size = sizeof (vec4f_t), .binops = quaternion_binops, .unops = quaternion_unops, + .get_string = quaternion_get_string, }; exprtype_t cexpr_exprval = { @@ -743,3 +797,21 @@ cexpr_parse_enum (exprenum_t *enm, const char *str, const exprctx_t *ctx, context.result = &result; return cexpr_eval_string (str, &context); } + +VISIBLE const char * +cexpr_enum_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + exprenum_t *enm = val->type->data; + exprsym_t *symbols = enm->symtab->symbols; + for (exprsym_t *sym = symbols; sym->name; sym++) { + // if there are duplicate values, choose the *later* value + if (sym[1].name + && memcmp (sym->value, sym[1].value, val->type->size) == 0) { + continue; + } + if (memcmp (sym->value, val->value, val->type->size) == 0) { + return sym->name; + } + } + return ""; +} diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index cc22577a5..7725c6b34 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -95,9 +95,11 @@ skip_value(string name) if (strip_bit) { fprintf (output_file, "\t.binops = flag_binops,\n"); fprintf (output_file, "\t.unops = flag_unops,\n"); + fprintf (output_file, "\t.get_string = cexpr_flags_get_string,\n"); } else { fprintf (output_file, "\t.binops = enum_binops,\n"); fprintf (output_file, "\t.unops = 0,\n"); + fprintf (output_file, "\t.get_string = cexpr_enum_get_string,\n"); } fprintf (output_file, "\t.data = &%s_enum,\n", [self name]); fprintf (output_file, "};\n"); From d68db74049f93805060e555b13d5f9a1b372517a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 15:12:56 +0900 Subject: [PATCH 2670/3664] [cexpr] Add a flags type Based on the flags type used in vkparse (difference is the lack of support for plists). Having this will make supporting named flags in cvars much easier (though setting up the enum type is a bit of a chore). --- include/QF/cexpr.h | 3 +++ libs/util/cexpr-type.c | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 665595d92..c0d608f80 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -117,6 +117,7 @@ binop_t *cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) __attribut exprval_t *cexpr_value (exprtype_t *type, exprctx_t *ctx); exprval_t *cexpr_value_reference (exprtype_t *type, void *data, exprctx_t *ctx); const char *cexpr_enum_get_string (const exprval_t *val, struct va_ctx_s *va_ctx) __attribute__((pure)); +const char *cexpr_flags_get_string (const exprval_t *val, struct va_ctx_s *va_ctx) __attribute__((pure)); int cexpr_eval_string (const char *str, exprctx_t *context); void cexpr_error(exprctx_t *ctx, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); @@ -151,6 +152,8 @@ extern exprtype_t cexpr_plitem; extern binop_t cexpr_array_binops[]; extern binop_t cexpr_struct_binops[]; extern binop_t cexpr_struct_pointer_binops[]; +extern binop_t cexpr_flag_binops[]; +extern unop_t cexpr_flag_unops[]; extern exprsym_t cexpr_lib_symbols[]; diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 2df8bfdce..cf622e786 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -815,3 +815,53 @@ cexpr_enum_get_string (const exprval_t *val, va_ctx_t *va_ctx) } return ""; } + +BINOP(flag, and, int, &) +BINOP(flag, or, int, |) +BINOP(flag, xor, int, ^) + +UNOP(flag, not, int, ~) + +binop_t cexpr_flag_binops[] = { + { '&', 0, 0, flag_and }, + { '|', 0, 0, flag_or }, + { '^', 0, 0, flag_xor }, + { '=', &cexpr_int, 0, uint_cast_int }, + {} +}; + +unop_t cexpr_flag_unops[] = { + { '~', 0, flag_not }, + {} +}; + +VISIBLE const char * +cexpr_flags_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + exprenum_t *enm = val->type->data; + exprsym_t *symbols = enm->symtab->symbols; + const char *val_str = 0; + + if (val->type->size != 4) { + Sys_Error ("cexpr_flags_get_string: only 32-bit values supported"); + } + uint32_t flags = *(uint32_t *) val->value; + for (exprsym_t *sym = symbols; sym->name; sym++) { + uint32_t sym_flags = *(uint32_t *) sym->value; + // if there are duplicate values, choose the *later* value + if (sym[1].name && sym_flags == *(uint32_t *) sym[1].value) { + continue; + } + if ((flags & sym_flags) && !(sym_flags & ~flags)) { + if (val_str) { + val_str = va (va_ctx, "%s | %s", val_str, sym->name); + } else { + val_str = sym->name; + } + } + } + if (!val_str) { + val_str = "0"; + } + return val_str; +} From 021ec4962bb7f539effbc325f2771b034fdf62bb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 15:16:15 +0900 Subject: [PATCH 2671/3664] [cexpr] Add optional error message prefix string The prefix gives more context to the error messages, making the system a lot easier to use (it was especially helpful when getting my cvar revamp into shape). --- include/QF/cexpr.h | 1 + libs/util/cexpr-lex.l | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index c0d608f80..91e19ced2 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -99,6 +99,7 @@ typedef struct exprctx_s { exprval_t *result; exprtab_t *symtab; // directly accessible symbols exprtab_t *external_variables; // accessible via $id + const char *msg_prefix; // optional prefix for error messages struct memsuper_s *memsuper; const struct plitem_s *item; struct plitem_s *messages; diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index bb4387a10..28551b1dc 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -94,9 +94,18 @@ cexpr_error(exprctx_t *ctx, const char *fmt, ...) va_end (args); if (ctx->messages) { - PL_Message (ctx->messages, ctx->item, "%s", string->str); + if (ctx->msg_prefix) { + PL_Message (ctx->messages, ctx->item, "%s:%s", + ctx->msg_prefix, string->str); + } else { + PL_Message (ctx->messages, ctx->item, "%s", string->str); + } } else { - Sys_Printf ("%s\n", string->str); + if (ctx->msg_prefix) { + Sys_Printf ("%s:%s\n", ctx->msg_prefix, string->str); + } else { + Sys_Printf ("%s\n", string->str); + } } dstring_delete (string); } From aad4546c013bb71da908f492eb57f32899ce2194 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 15:18:09 +0900 Subject: [PATCH 2672/3664] [cexpr] Expose cexpr assignment This makes it much easier for other systems (in particular, cvar) to copy values safely. --- include/QF/cexpr.h | 2 ++ libs/util/cexpr-parse.y | 10 ++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 91e19ced2..b61653eef 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -112,6 +112,8 @@ typedef struct exprenum_s { exprtab_t *symtab; } exprenum_t; +exprval_t *cexpr_assign_value (exprval_t *dst, const exprval_t *src, + exprctx_t *context); int cexpr_parse_enum (exprenum_t *enm, const char *str, const exprctx_t *context, void *data); binop_t *cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) __attribute__((pure)); diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index 1f76071ad..f47176b9b 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -51,8 +51,6 @@ #include "QF/cexpr.h" -static exprval_t *assign_expr (exprval_t *dst, const exprval_t *src, - exprctx_t *context); static exprval_t *binary_expr (int op, const exprval_t *a, const exprval_t *b, exprctx_t *context); static exprval_t *field_expr (const exprval_t *a, const exprval_t *b, @@ -109,7 +107,7 @@ yyerror (void *scanner, exprctx_t *context, const char *s) %% start - : expr { assign_expr (context->result, $1, context); } + : expr { cexpr_assign_value (context->result, $1, context); } ; uexpr @@ -138,7 +136,7 @@ uexpr expr : uexpr - | expr '=' expr { $$ = assign_expr ($1, $3, context); } + | expr '=' expr { $$ = cexpr_assign_value ($1, $3, context); } | expr SHL expr { $$ = binary_expr (SHL, $1, $3, context); } | expr SHR expr { $$ = binary_expr (SHR, $1, $3, context); } | expr '+' expr { $$ = binary_expr ('+', $1, $3, context); } @@ -185,8 +183,8 @@ arg_expr %% -static exprval_t * -assign_expr (exprval_t *dst, const exprval_t *src, exprctx_t *context) +exprval_t * +cexpr_assign_value (exprval_t *dst, const exprval_t *src, exprctx_t *context) { binop_t *binop; if (!dst || !src) { From a52704e8cad20d6aace53b8aa4fb695ba7bf677d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 16:45:39 +0900 Subject: [PATCH 2673/3664] [cexpr] Allow assignment of double to float I didn't really want this, but it's needed for cvar support. --- libs/util/cexpr-type.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index cf622e786..97c15606f 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -328,6 +328,7 @@ float_div_quat (const exprval_t *val1, const exprval_t *val2, CASTOP (float, int) CASTOP (float, uint) +CASTOP (float, double) UNOP(float, pos, float, +) UNOP(float, neg, float, -) @@ -351,6 +352,7 @@ binop_t float_binops[] = { { MOD, &cexpr_float, &cexpr_float, float_mod }, { '=', &cexpr_int, &cexpr_float, float_cast_int }, { '=', &cexpr_uint, &cexpr_float, float_cast_uint }, + { '=', &cexpr_double, &cexpr_float, float_cast_double }, { '=', &cexpr_plitem, &cexpr_float, cexpr_cast_plitem }, {} }; From 87b3c648017ba5ec4fb772fd87dc8f6147cd4099 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 15:40:28 +0900 Subject: [PATCH 2674/3664] [vulkan] Parse VkPresentModeKHR And strip the KHR for short names. --- libs/video/renderer/vulkan/vkgen/vkenum.r | 11 +++++++++++ libs/video/renderer/vulkan/vkparse.plist | 1 + 2 files changed, 12 insertions(+) diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 7725c6b34..bd12ade7f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -20,6 +20,8 @@ typedef enum VkBool32 { end = "_FLAG_BITS_MAX_ENUM"; } else if (str_mid([self name], -11) == "FlagBitsEXT") { end = "_FLAG_BITS_MAX_ENUM_EXT"; + } else if (str_mid([self name], -3) == "KHR") { + end = "_MAX_ENUM_KHR"; } len = -strlen (end); for (int i = 0; i < type.strct.num_fields; i++) { @@ -84,10 +86,14 @@ skip_value(string name) -(void) writeTable { int strip_bit = 0; + int strip_khr = 0; if (str_mid([self name], -8) == "FlagBits" || str_mid([self name], -11) == "FlagBitsEXT") { strip_bit = 1; } + if (str_mid([self name], -3) == "KHR") { + strip_khr = 1; + } fprintf (output_file, "exprtype_t %s_type = {\n", [self name]); fprintf (output_file, "\t.name = \"%s\",\n", [self name]); @@ -132,6 +138,11 @@ skip_value(string name) if (bit_pos >= 0) { shortname = str_mid (shortname, 0, bit_pos); } + } else if (strip_khr) { + int khr_pos = str_str (shortname, "_KHR"); + if (khr_pos >= 0) { + shortname = str_mid (shortname, 0, khr_pos); + } } fprintf (output_file, "\t{\"%s\", &%s_type, %s_values + %d},\n", str_lower(shortname), [self name], [self name], index); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 23577cb79..4379d39c4 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -2,6 +2,7 @@ search = ( VkAttachmentDescription, VkDebugUtilsMessageSeverityFlagBitsEXT, + VkPresentModeKHR, VkSubpassDescription, VkSubpassDependency, VkSpecializationInfo, From 12c84046f30a39dd76b3e8e77dbe7272f47be6ea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 23 Apr 2022 12:22:45 +0900 Subject: [PATCH 2675/3664] [cvar] Make cvars properly typed This is an extremely extensive patch as it hits every cvar, and every usage of the cvars. Cvars no longer store the value they control, instead, they use a cexpr value object to reference the value and specify the value's type (currently, a null type is used for strings). Non-string cvars are passed through cexpr, allowing expressions in the cvars' settings. Also, cvars have returned to an enhanced version of the original (id quake) registration scheme. As a minor benefit, relevant code having direct access to the cvar-controlled variables is probably a slight optimization as it removed a pointer dereference, and the variables can be located for data locality. The static cvar descriptors are made private as an additional safety layer, though there's nothing stopping external modification via Cvar_FindVar (which is needed for adding listeners). While not used yet (partly due to working out the design), cvars can have a validation function. Registering a cvar allows a primary listener (and its data) to be specified: it will always be called first when the cvar is modified. The combination of proper listeners and direct access to the controlled variable greatly simplifies the more complex cvar interactions as much less null checking is required, and there's no need for one cvar's callback to call another's. nq-x11 is known to work at least well enough for the demos. More testing will come. --- hw/source/master.c | 15 +- include/QF/GL/qf_rmain.h | 2 +- include/QF/Vulkan/cvars.h | 6 +- include/QF/cmd.h | 2 +- include/QF/cvar.h | 42 +- include/QF/input.h | 14 +- include/QF/joystick.h | 8 +- include/QF/model.h | 9 +- include/QF/plugin.h | 2 +- include/QF/plugin/vid_render.h | 6 +- include/QF/progs.h | 11 +- include/QF/qargs.h | 4 +- include/QF/render.h | 1 - include/QF/screen.h | 5 +- include/QF/sys.h | 10 +- include/QF/teamplay.h | 6 +- include/client/chase.h | 2 +- include/client/hud.h | 30 +- include/client/input.h | 26 +- include/context_win.h | 2 +- include/context_x11.h | 1 + include/d_iface.h | 4 +- include/netchan.h | 4 +- include/netmain.h | 2 +- include/qw/pmove.h | 2 +- include/r_cvar.h | 169 ++-- include/r_dynamic.h | 6 +- include/r_local.h | 32 +- include/r_shared.h | 2 +- include/sbar.h | 2 +- include/snd_internal.h | 2 +- include/vid_internal.h | 16 +- include/vid_vulkan.h | 4 +- libs/audio/cd.c | 19 +- libs/audio/cd_file.c | 44 +- libs/audio/cd_linux.c | 44 +- libs/audio/cd_sdl.c | 21 +- libs/audio/cd_sgi.c | 23 +- libs/audio/cd_win.c | 23 +- libs/audio/renderer/Makemodule.am | 60 +- libs/audio/renderer/midi.c | 29 +- libs/audio/renderer/snd_channels.c | 83 +- libs/audio/renderer/snd_dma.c | 78 +- libs/audio/renderer/snd_mix.c | 4 +- libs/audio/renderer/snd_sfx.c | 15 +- libs/audio/snd.c | 36 +- libs/audio/targets/snd_alsa.c | 66 +- libs/audio/targets/snd_dx.c | 45 +- libs/audio/targets/snd_jack.c | 40 +- libs/audio/targets/snd_oss.c | 79 +- libs/audio/targets/snd_sdl.c | 49 +- libs/audio/targets/snd_win.c | 45 +- libs/audio/test/testsound.c | 2 +- libs/client/cl_chase.c | 84 +- libs/client/cl_effects.c | 2 +- libs/client/cl_input.c | 209 +++-- libs/client/cl_particles.c | 64 +- libs/client/cl_view.c | 395 ++++++--- libs/client/hud.c | 162 +++- libs/console/client.c | 125 ++- libs/console/console.c | 22 +- libs/console/menu.c | 15 +- libs/console/server.c | 87 +- libs/gamecode/pr_debug.c | 45 +- libs/gamecode/pr_edict.c | 2 +- libs/gamecode/pr_exec.c | 116 +-- libs/gamecode/pr_load.c | 54 +- libs/gamecode/pr_v6p_opcode.c | 4 +- libs/gamecode/test/main.c | 2 +- libs/gib/gib_init.c | 4 +- libs/gib/gib_process.c | 6 +- libs/gib/gib_vars.c | 6 +- libs/input/in_common.c | 124 ++- libs/input/in_imt.c | 4 +- libs/models/alias/gl_mesh.c | 5 +- libs/models/brush/gl_model_brush.c | 5 +- libs/models/brush/model_brush.c | 10 +- libs/models/gl_skin.c | 8 +- libs/models/model.c | 57 +- libs/net/nc/net_udp6.c | 22 +- libs/net/net_chan.c | 58 +- libs/net/net_main.c | 31 +- libs/net/nm/net_dgrm.c | 4 +- libs/net/nm/net_loop.c | 4 +- libs/net/nm/net_udp.c | 8 +- libs/net/nm/net_wins.c | 4 +- libs/ruamoko/pr_cmds.c | 4 +- libs/ruamoko/rua_cvar.c | 32 +- libs/ruamoko/rua_obj.c | 10 +- libs/util/cexpr-vars.c | 20 +- libs/util/cmd.c | 19 +- libs/util/cvar.c | 414 +++++---- libs/util/plugin.c | 17 +- libs/util/qargs.c | 34 +- libs/util/quakefs.c | 69 +- libs/util/sys.c | 70 +- libs/util/zone.c | 4 +- libs/video/renderer/gl/gl_draw.c | 26 +- libs/video/renderer/gl/gl_dyn_lights.c | 4 +- libs/video/renderer/gl/gl_dyn_part.c | 48 +- libs/video/renderer/gl/gl_fisheye.c | 4 +- libs/video/renderer/gl/gl_lightmap.c | 20 +- libs/video/renderer/gl/gl_mod_alias.c | 26 +- libs/video/renderer/gl/gl_rmain.c | 33 +- libs/video/renderer/gl/gl_rmisc.c | 1 - libs/video/renderer/gl/gl_rsurf.c | 16 +- libs/video/renderer/gl/gl_sky.c | 6 +- libs/video/renderer/gl/gl_sky_clip.c | 18 +- libs/video/renderer/gl/gl_textures.c | 20 +- libs/video/renderer/gl/gl_warp.c | 4 +- libs/video/renderer/gl/vid_common_gl.c | 564 ++++++++---- libs/video/renderer/glsl/glsl_alias.c | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 10 +- libs/video/renderer/glsl/glsl_draw.c | 26 +- libs/video/renderer/glsl/glsl_fisheye.c | 2 +- libs/video/renderer/glsl/glsl_main.c | 7 +- libs/video/renderer/glsl/glsl_particles.c | 54 +- libs/video/renderer/glsl/vid_common_glsl.c | 8 +- libs/video/renderer/r_bsp.c | 4 +- libs/video/renderer/r_cvar.c | 769 +++++++++++----- libs/video/renderer/r_graph.c | 2 +- libs/video/renderer/r_init.c | 17 +- libs/video/renderer/r_light.c | 10 +- libs/video/renderer/r_part.c | 62 +- libs/video/renderer/r_screen.c | 27 +- libs/video/renderer/sw/d_edge.c | 2 +- libs/video/renderer/sw/d_init.c | 4 +- libs/video/renderer/sw/draw.c | 18 +- libs/video/renderer/sw/sw_fisheye.c | 2 +- libs/video/renderer/sw/sw_rmain.c | 21 +- libs/video/renderer/sw/sw_rpart.c | 34 - libs/video/renderer/vid_render_gl.c | 14 +- libs/video/renderer/vid_render_glsl.c | 6 +- libs/video/renderer/vid_render_sw.c | 14 +- libs/video/renderer/vid_render_vulkan.c | 2 +- libs/video/renderer/vulkan/instance.c | 12 +- libs/video/renderer/vulkan/projection.c | 4 +- libs/video/renderer/vulkan/renderpass.c | 2 +- libs/video/renderer/vulkan/swapchain.c | 4 +- libs/video/renderer/vulkan/vulkan_bsp.c | 6 +- libs/video/renderer/vulkan/vulkan_draw.c | 6 +- libs/video/renderer/vulkan/vulkan_main.c | 6 +- .../video/renderer/vulkan/vulkan_vid_common.c | 178 ++-- libs/video/targets/context_sdl.c | 13 +- libs/video/targets/context_win.c | 241 +++-- libs/video/targets/context_x11.c | 42 +- libs/video/targets/in_sdl.c | 17 +- libs/video/targets/in_win.c | 4 +- libs/video/targets/in_x11.c | 83 +- libs/video/targets/joy.c | 64 +- libs/video/targets/joy_linux.c | 4 +- libs/video/targets/joy_win.c | 300 +++++-- libs/video/targets/vid.c | 177 ++-- libs/video/targets/vid_3dfxsvga.c | 7 +- libs/video/targets/vid_fbdev.c | 30 +- libs/video/targets/vid_sdl.c | 2 +- libs/video/targets/vid_sdl_gl.c | 17 +- libs/video/targets/vid_svgalib.c | 35 +- libs/video/targets/vid_win.c | 59 +- libs/video/targets/vid_win_gl.c | 21 +- libs/video/targets/vid_win_sw.c | 2 +- libs/video/targets/vid_win_vulkan.c | 18 +- libs/video/targets/vid_x11.c | 14 +- libs/video/targets/vid_x11_gl.c | 17 +- libs/video/targets/vid_x11_vulkan.c | 18 +- nq/include/client.h | 29 +- nq/include/game.h | 2 +- nq/include/host.h | 8 +- nq/include/server.h | 49 +- nq/source/cl_demo.c | 65 +- nq/source/cl_ents.c | 6 +- nq/source/cl_main.c | 128 ++- nq/source/cl_parse.c | 6 +- nq/source/cl_screen.c | 4 +- nq/source/game.c | 27 +- nq/source/host.c | 278 ++++-- nq/source/host_cmd.c | 18 +- nq/source/sbar.c | 222 ++--- nq/source/sv_cl_phys.c | 4 +- nq/source/sv_cvar.c | 6 +- nq/source/sv_ded.c | 8 +- nq/source/sv_main.c | 46 +- nq/source/sv_phys.c | 73 +- nq/source/sv_pr_cmds.c | 18 +- nq/source/sv_progs.c | 215 ++++- nq/source/sv_user.c | 145 ++- nq/source/sys_sdl.c | 8 +- nq/source/sys_unix.c | 8 +- nq/source/sys_unixd.c | 6 +- nq/source/sys_win.c | 6 +- nq/source/sys_wind.c | 6 +- qtv/include/qtv.h | 2 +- qtv/source/qtv.c | 65 +- qtv/source/server.c | 4 +- qw/include/cl_demo.h | 4 +- qw/include/cl_ents.h | 4 +- qw/include/cl_main.h | 14 +- qw/include/client.h | 31 +- qw/include/game.h | 2 +- qw/include/host.h | 4 +- qw/include/server.h | 77 +- qw/include/sv_demo.h | 6 +- qw/source/cl_cam.c | 82 +- qw/source/cl_cvar.c | 15 +- qw/source/cl_demo.c | 67 +- qw/source/cl_entparse.c | 2 +- qw/source/cl_ents.c | 18 +- qw/source/cl_input.c | 58 +- qw/source/cl_main.c | 567 ++++++++---- qw/source/cl_ngraph.c | 75 +- qw/source/cl_parse.c | 18 +- qw/source/cl_pred.c | 34 +- qw/source/cl_rss.c | 2 +- qw/source/cl_screen.c | 10 +- qw/source/cl_skin.c | 68 +- qw/source/cl_slist.c | 70 +- qw/source/crudefile.c | 17 +- qw/source/game.c | 15 +- qw/source/net_packetlog.c | 50 +- qw/source/pmove.c | 22 +- qw/source/sbar.c | 279 +++--- qw/source/sv_ccmds.c | 34 +- qw/source/sv_demo.c | 216 +++-- qw/source/sv_init.c | 22 +- qw/source/sv_main.c | 831 +++++++++++------- qw/source/sv_phys.c | 75 +- qw/source/sv_pr_cmds.c | 28 +- qw/source/sv_pr_cpqw.c | 2 +- qw/source/sv_progs.c | 161 +++- qw/source/sv_qtv.c | 2 +- qw/source/sv_recorder.c | 4 +- qw/source/sv_send.c | 7 +- qw/source/sv_sys_unix.c | 4 +- qw/source/sv_sys_win.c | 4 +- qw/source/sv_user.c | 384 +++++--- qw/source/teamplay.c | 81 +- ruamoko/qwaq/builtins/main.c | 5 +- tools/misc/cvar2.py | 335 +++++++ tools/qfcc/source/qfprogs.c | 6 +- tools/qfcc/test/test-harness.c | 14 +- 240 files changed, 8069 insertions(+), 4224 deletions(-) create mode 100644 tools/misc/cvar2.py diff --git a/hw/source/master.c b/hw/source/master.c index 2142eaa81..f05a34d69 100644 --- a/hw/source/master.c +++ b/hw/source/master.c @@ -55,7 +55,15 @@ typedef struct server_s { double timeout; } server_t; -static cvar_t *sv_console_plugin; +static char *sv_console_plugin; +static cvar_t sv_console_plugin_cvar = { + .name = "sv_console_plugin", + .description = + "Plugin used for the console", + .default_value = "server", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &sv_console_plugin }, +}; SERVER_PLUGIN_PROTOS static plugin_list_t server_plugin_list[] = { SERVER_PLUGIN_LIST @@ -535,10 +543,9 @@ main (int argc, const char **argv) PI_Init (); - sv_console_plugin = Cvar_Get ("sv_console_plugin", "server", - CVAR_ROM, 0, "Plugin used for the console"); + Cvar_Register (&sv_console_plugin_cvar, 0, 0); PI_RegisterPlugins (server_plugin_list); - Con_Init (sv_console_plugin->string); + Con_Init (sv_console_plugin); if (con_module) con_module->data->console->cbuf = mst_cbuf; con_list_print = Sys_Printf; diff --git a/include/QF/GL/qf_rmain.h b/include/QF/GL/qf_rmain.h index 8aeb4c898..a9aea8770 100644 --- a/include/QF/GL/qf_rmain.h +++ b/include/QF/GL/qf_rmain.h @@ -38,7 +38,7 @@ extern int c_brush_polys, c_alias_polys; extern float gl_modelalpha; //extern vec3_t shadecolor; -extern void gl_multitexture_f (struct cvar_s *var); +extern void gl_multitexture_f (void *data, const struct cvar_s *var); void glrmain_init (void); void gl_R_RotateForEntity (struct entity_s *e); diff --git a/include/QF/Vulkan/cvars.h b/include/QF/Vulkan/cvars.h index 54a34048b..c9869d1c2 100644 --- a/include/QF/Vulkan/cvars.h +++ b/include/QF/Vulkan/cvars.h @@ -1,8 +1,8 @@ #ifndef __QF_Vulkan_cvars_h #define __QF_Vulkan_cvars_h -extern struct cvar_s *vulkan_use_validation; -extern struct cvar_s *vulkan_presentation_mode; -extern struct cvar_s *vulkan_frame_count; +extern int vulkan_use_validation; +extern int vulkan_presentation_mode; +extern int vulkan_frame_count; #endif//__QF_Vulkan_cvars_h diff --git a/include/QF/cmd.h b/include/QF/cmd.h index b57e8ca15..f9ae0c7b6 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -85,7 +85,7 @@ struct cbuf_interpreter_s *Cmd_GetProvider(const char *name); extern struct cbuf_args_s *cmd_args; -extern struct cvar_s *cmd_warncmd; +extern int cmd_warncmd; ///@} diff --git a/include/QF/cvar.h b/include/QF/cvar.h index 2fe20aafa..de87ee6ff 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -33,31 +33,20 @@ */ ///@{ +#include "QF/cexpr.h" #include "QF/listener.h" #include "QF/qtypes.h" #include "QF/quakeio.h" typedef struct cvar_s { - const char *name; ///< The name of the cvar. - const char *string; ///< The current cvar value as a string. - const char *default_string; ///< The default value of the cvar. - int flags; ///< Cvar flags - /** Callback for when the cvar value changes. - - This allows for more flexibility in what happens when a cvar is - nodifed than can be achieved with flags alone. While a similar could - be done using commands, a cvar with a callback and CVAR_ARCHIVE set - allows the setting to be saved automatically. - - \param var This cvar. - */ - void (*callback)(struct cvar_s *var); + const char *name; + const char *description; + const char *default_value; + unsigned flags; + exprval_t value; + int (*validator) (const struct cvar_s *var); struct cvar_listener_set_s *listeners; - const char *description; ///< for "help" command - float value; ///< The current cvar value as a float - int int_val; ///< The current cvar value as an integer - vec3_t vec; ///< The current cvar value as a vector - struct cvar_s *next; ///< \internal Linked list of cvars. + struct cvar_s *next; } cvar_t; typedef struct cvar_listener_set_s LISTENER_SET_TYPE (cvar_t) @@ -88,16 +77,14 @@ typedef struct cvar_alias_s { ///< (not implemented) #define CVAR_ROM 64 ///< display only, cannot be set #define CVAR_USER_CREATED 128 ///< created by a set command +#define CVAR_REGISTERED 256 ///< var has been registered #define CVAR_LATCH 2048 ///< will change only when C code next does ///< a Cvar_Get(), so it can't be changed ///< (not implemented) ///@} -// Returns the Cvar if found, creates it with value if not. Description and -// flags are always updated. -cvar_t *Cvar_Get (const char *name, const char *value, int cvarflags, - void (*callback)(cvar_t*), const char *description); +void Cvar_Register (cvar_t *var, cvar_listener_t listener, void *data); cvar_t *Cvar_FindAlias (const char *alias_name); @@ -107,17 +94,18 @@ void Cvar_AddListener (cvar_t *cvar, cvar_listener_t listener, void *data); void Cvar_RemoveListener (cvar_t *cvar, cvar_listener_t listener, void *data); // equivelants to " " typed at the console -void Cvar_Set (cvar_t *var, const char *value); -void Cvar_SetValue (cvar_t *var, float value); +void Cvar_Set (const char *var, const char *value); +void Cvar_SetVar (cvar_t *var, const char *value); // allows you to change a Cvar's flags without a full Cvar_Get void Cvar_SetFlags (cvar_t *var, int cvarflags); // returns 0 if not defined or non numeric -float Cvar_VariableValue (const char *var_name); +float Cvar_Value (const char *var_name); // returns an empty string if not defined -const char *Cvar_VariableString (const char *var_name); +const char *Cvar_String (const char *var_name); +const char *Cvar_VarString (const cvar_t *var); // called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known // command. Returns true if the command was a variable reference that diff --git a/include/QF/input.h b/include/QF/input.h index 119ad170b..2b85ee3c4 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -122,16 +122,16 @@ int IN_GetButtonInfo (int devid, int button_num, in_buttoninfo_t *info); void IN_ProcessEvents (void); -void IN_UpdateGrab (struct cvar_s *); +void IN_UpdateGrab (int grab); void IN_ClearStates (void); -extern struct cvar_s *in_grab; -extern struct cvar_s *in_amp; -extern struct cvar_s *in_pre_amp; -extern struct cvar_s *in_mouse_accel; -extern struct cvar_s *in_freelook; -extern struct cvar_s *lookstrafe; +extern int in_grab; +extern float in_amp; +extern float in_pre_amp; +extern int in_mouse_accel; +extern int in_freelook; +extern char *lookstrafe; #endif diff --git a/include/QF/joystick.h b/include/QF/joystick.h index 4b8163f7e..2e23d39f7 100644 --- a/include/QF/joystick.h +++ b/include/QF/joystick.h @@ -34,8 +34,8 @@ #define JOY_MAX_AXES 32 #define JOY_MAX_BUTTONS 64 -extern struct cvar_s *joy_device; // Joystick device name -extern struct cvar_s *joy_enable; // Joystick enabling flag +extern char *joy_device; +extern int joy_enable; struct joy_axis_button { float threshold; @@ -92,7 +92,7 @@ extern struct joy_button joy_buttons[JOY_MAX_BUTTONS]; frame. You should exit this function immediately if either joy_active or - joy_enable->int_val are zero. + joy_enable are zero. */ void JOY_Command (void); void joy_clear_axis (int i); @@ -103,7 +103,7 @@ void joy_clear_axis (int i); Use this function to process joystick movements to move the player around. You should exit this function immediately if either joy_active or - joy_enable->int_val are zero. + joy_enable are zero. */ void JOY_Move (void); diff --git a/include/QF/model.h b/include/QF/model.h index 875aeec3b..66628d37c 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -449,10 +449,11 @@ void Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, void Mod_Print (void); -extern struct cvar_s *gl_mesh_cache; -extern struct cvar_s *gl_subdivide_size; -extern struct cvar_s *gl_alias_render_tri; -extern struct cvar_s *gl_textures_external; +extern int gl_mesh_cache; +extern float gl_subdivide_size; +extern int gl_alias_render_tri; +extern int gl_textures_external; +extern int mod_sky_divide; extern int mod_lightmap_bytes; #endif//__QF_model_h diff --git a/include/QF/plugin.h b/include/QF/plugin.h index 96de3124e..cb73f6b7f 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -98,7 +98,7 @@ typedef struct plugin_list_s { /* Plugin system variables */ -extern struct cvar_s *fs_pluginpath; +extern char *fs_pluginpath; /* Function prototypes diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 19ed1e394..6f775de78 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -138,9 +138,9 @@ typedef struct vid_render_data_s { int scr_copytop; int scr_copyeverything; int scr_fullupdate; // set to 0 to force full redraw - void (*viewsize_callback) (struct cvar_s *); - struct cvar_s *scr_viewsize; - struct cvar_s *graphheight; + void (*viewsize_callback) (int view_size); + int *scr_viewsize; + int *graphheight; float min_wateralpha; qboolean force_fullscreen; qboolean inhibit_viewmodel; diff --git a/include/QF/progs.h b/include/QF/progs.h index cd1008f91..b90c96e99 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1829,11 +1829,12 @@ void PR_DumpState (progs_t *pr); void PR_StackTrace (progs_t *pr); void PR_Profile (progs_t *pr); -extern struct cvar_s *pr_debug; -extern struct cvar_s *pr_deadbeef_ents; -extern struct cvar_s *pr_deadbeef_locals; -extern struct cvar_s *pr_boundscheck; -extern struct cvar_s *pr_faultchecks; +extern int pr_debug; +extern char *pr_source_path; +extern int pr_deadbeef_ents; +extern int pr_deadbeef_locals; +extern int pr_boundscheck; +extern int pr_faultchecks; ///@} diff --git a/include/QF/qargs.h b/include/QF/qargs.h index 947bea592..689b5b5a1 100644 --- a/include/QF/qargs.h +++ b/include/QF/qargs.h @@ -39,8 +39,8 @@ extern int com_argc; extern const char **com_argv; extern const char *com_cmdline; -extern struct cvar_s *fs_globalcfg; -extern struct cvar_s *fs_usercfg; +extern char *fs_globalcfg; +extern char *fs_usercfg; int COM_CheckParm (const char *parm) __attribute__((pure)); void COM_AddParm (const char *parm); diff --git a/include/QF/render.h b/include/QF/render.h index d989bd38b..01994d095 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -181,7 +181,6 @@ struct progs_s; void R_Progs_Init (struct progs_s *pr); dlight_t *R_AllocDlight (int key); -void R_MaxDlightsCheck (struct cvar_s *var); void R_DecayLights (double frametime); void Fog_Update (float density, float red, float green, float blue, float time); diff --git a/include/QF/screen.h b/include/QF/screen.h index 10e0176e1..362cae41b 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -47,7 +47,10 @@ void SCR_SetFOV (float fov); void SCR_SetFullscreen (qboolean fullscreen); void SCR_SetBottomMargin (int lines); -extern struct cvar_s *hud_fps, *hud_time, *r_timegraph, *r_zgraph; +extern int hud_fps; +extern int hud_time; +extern int r_timegraph; +extern int r_zgraph; extern int scr_copytop; extern qboolean scr_skipupdate; diff --git a/include/QF/sys.h b/include/QF/sys.h index 3b6d5aed3..dde61872b 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -40,12 +40,12 @@ struct dstring_s; -extern struct cvar_s *sys_nostdout; -extern struct cvar_s *sys_extrasleep; -extern struct cvar_s *sys_dead_sleep; -extern struct cvar_s *sys_sleep; +extern int sys_nostdout; +extern int sys_extrasleep; +extern int sys_dead_sleep; +extern int sys_sleep; -extern struct cvar_s *developer; +extern int developer; extern const char sys_char_map[256]; diff --git a/include/QF/teamplay.h b/include/QF/teamplay.h index 91b2a6f65..0f03ff5e9 100644 --- a/include/QF/teamplay.h +++ b/include/QF/teamplay.h @@ -28,9 +28,9 @@ #ifndef __QF_teamplay_h #define __QF_teamplay_h -extern struct cvar_s *cl_parsesay; -extern struct cvar_s *cl_nofake; -extern struct cvar_s *cl_freply; +extern int cl_parsesay; +extern int cl_nofake; +extern float cl_freply; typedef const char *(*ffunc_t) (char *args); typedef struct freply_s { diff --git a/include/client/chase.h b/include/client/chase.h index a1415408b..91e12cd5a 100644 --- a/include/client/chase.h +++ b/include/client/chase.h @@ -40,7 +40,7 @@ typedef struct chasestate_s { vec3_t player_angles; } chasestate_t; -extern struct cvar_s *chase_active; +extern int chase_active; void Chase_Init_Cvars (void); void Chase_Reset (void); diff --git a/include/client/hud.h b/include/client/hud.h index 31b4d5542..82fa94365 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -25,11 +25,29 @@ Boston, MA 02111-1307, USA */ -#ifndef __client_hud_h_ -#define __client_hud_h_ +#ifndef __client_hud_h +#define __client_hud_h -extern struct cvar_s *hud_sbar; -extern struct cvar_s *hud_scoreboard_gravity; -extern struct cvar_s *hud_swap; +extern int hud_sb_lines; -#endif // __client_hud_h_ +extern int hud_sbar; +extern char *hud_scoreboard_gravity; +extern int hud_swap; + +extern struct view_s *sbar_view; +extern struct view_s *sbar_inventory_view; +extern struct view_s *sbar_frags_view; + +extern struct view_s *hud_view; +extern struct view_s *hud_inventory_view; +extern struct view_s *hud_armament_view; +extern struct view_s *hud_frags_view; + +extern struct view_s *hud_overlay_view; +extern struct view_s *hud_stuff_view; +extern struct view_s *hud_main_view; + +void HUD_Init_Cvars (void); +void HUD_Calc_sb_lines (int view_size); + +#endif//__client_hud_h diff --git a/include/client/input.h b/include/client/input.h index e66d02140..3cf9cee24 100644 --- a/include/client/input.h +++ b/include/client/input.h @@ -33,22 +33,22 @@ struct cbuf_s; -extern struct cvar_s *cl_upspeed; -extern struct cvar_s *cl_forwardspeed; -extern struct cvar_s *cl_backspeed; -extern struct cvar_s *cl_sidespeed; +extern float cl_upspeed; +extern float cl_forwardspeed; +extern float cl_backspeed; +extern float cl_sidespeed; -extern struct cvar_s *cl_movespeedkey; +extern float cl_movespeedkey; -extern struct cvar_s *cl_yawspeed; -extern struct cvar_s *cl_pitchspeed; +extern float cl_yawspeed; +extern float cl_pitchspeed; -extern struct cvar_s *cl_anglespeedkey; +extern float cl_anglespeedkey; -extern struct cvar_s *m_pitch; -extern struct cvar_s *m_yaw; -extern struct cvar_s *m_forward; -extern struct cvar_s *m_side; +extern float m_pitch; +extern float m_yaw; +extern float m_forward; +extern float m_side; #define FORWARD 0 #define SIDE 1 @@ -59,7 +59,7 @@ typedef struct movestate_s { vec4f_t angles; } movestate_t; -#define freelook (in_mlook.state & 1 || in_freelook->int_val) +#define freelook (in_mlook.state & 1 || in_freelook) struct viewstate_s; diff --git a/include/context_win.h b/include/context_win.h index 536a01564..4921ce24f 100644 --- a/include/context_win.h +++ b/include/context_win.h @@ -40,7 +40,7 @@ extern int win_canalttab; extern DEVMODE win_gdevmode; extern struct sw_ctx_s *win_sw_context; extern int win_minimized; -extern struct cvar_s *vid_ddraw; +extern int vid_ddraw; extern int win_center_x, win_center_y; extern RECT win_rect; diff --git a/include/context_x11.h b/include/context_x11.h index ebb4b6d3b..48e350826 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -67,6 +67,7 @@ void X11_CloseDisplay (void); void X11_CreateNullCursor (void); void X11_CreateWindow (int, int); void X11_ForceViewPort (void); +void X11_UpdateFullscreen (int fullscreen); void X11_Init_Cvars (void); void X11_OpenDisplay (void); void X11_ProcessEvent (void); diff --git a/include/d_iface.h b/include/d_iface.h index 32e7e307a..1a0479d44 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -112,8 +112,8 @@ typedef struct int color; } zpointdesc_t; -extern struct cvar_s *r_drawflat; -extern int r_framecount; // sequence # of current frame since Quake +extern int r_drawflat; +extern int r_framecount; // sequence # of current frame since Quake // started extern qboolean r_drawpolys; // 1 if driver wants clipped polygons // rather than a span list diff --git a/include/netchan.h b/include/netchan.h index 5fe10eb81..94b56f954 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -62,7 +62,7 @@ extern netadr_t net_loopback_adr; extern netadr_t net_from; // address of who sent the packet extern struct msg_s *net_message; -extern struct cvar_s *qport; +extern int qport; int Net_Log_Init (const char **sound_precache, int server); void Net_LogPrintf (const char *fmt, ...) __attribute__ ((format (PRINTF, 1, 2))); @@ -72,7 +72,7 @@ void Net_LogStop (void *data); void Analyze_Client_Packet (const byte * data, int len, int has_sequence); void Analyze_Server_Packet (const byte * data, int len, int has_sequence); -extern struct cvar_s *net_packetlog; +extern int net_packetlog; ///@} /** \defgroup qw-udp QuakeWorld udp support. diff --git a/include/netmain.h b/include/netmain.h index 882b7acc9..dbf319914 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -385,7 +385,7 @@ extern qboolean slistInProgress; extern qboolean slistSilent; extern qboolean slistLocal; -extern struct cvar_s *hostname; +extern char *hostname; extern QFile *vcrFile; diff --git a/include/qw/pmove.h b/include/qw/pmove.h index b8c436e56..20e68bb05 100644 --- a/include/qw/pmove.h +++ b/include/qw/pmove.h @@ -88,7 +88,7 @@ typedef struct { float entgravity; } movevars_t; -extern struct cvar_s *no_pogo_stick; +extern int no_pogo_stick; extern movevars_t movevars; extern playermove_t pmove; extern int onground; diff --git a/include/r_cvar.h b/include/r_cvar.h index 756c2ef03..3aac1e6db 100644 --- a/include/r_cvar.h +++ b/include/r_cvar.h @@ -1,93 +1,92 @@ #include "QF/mathlib.h" -extern void gl_overbright_f (struct cvar_s *cvar); +extern void gl_overbright_f (void *data, const struct cvar_s *cvar); -extern struct cvar_s *cl_crossx; -extern struct cvar_s *cl_crossy; -extern struct cvar_s *cl_verstring; -extern struct cvar_s *crosshair; -extern struct cvar_s *crosshaircolor; +extern int cl_crossx; +extern int cl_crossy; +extern char *cl_verstring; +extern int crosshair; +extern int crosshaircolor; extern quat_t crosshair_color; -extern struct cvar_s *d_mipcap; -extern struct cvar_s *d_mipscale; +extern float d_mipcap; +extern float d_mipscale; -extern struct cvar_s *gl_affinemodels; -extern struct cvar_s *gl_anisotropy; -extern struct cvar_s *gl_clear; -extern struct cvar_s *gl_conspin; -extern struct cvar_s *gl_constretch; -extern struct cvar_s *gl_dlight_polyblend; -extern struct cvar_s *gl_dlight_smooth; -extern struct cvar_s *gl_fb_bmodels; -extern struct cvar_s *gl_fb_models; -extern struct cvar_s *gl_finish; -extern struct cvar_s *gl_keeptjunctions; -extern struct cvar_s *gl_lerp_anim; -extern struct cvar_s *gl_lightmap_align; -extern struct cvar_s *gl_lightmap_subimage; -extern struct cvar_s *gl_max_size; -extern struct cvar_s *gl_multitexture; -extern struct cvar_s *gl_nocolors; -extern struct cvar_s *gl_overbright; -extern struct cvar_s *gl_particle_mip; -extern struct cvar_s *gl_particle_size; -extern struct cvar_s *gl_picmip; -extern struct cvar_s *gl_playermip; -extern struct cvar_s *gl_reporttjunctions; -extern struct cvar_s *gl_sky_clip; -extern struct cvar_s *gl_sky_debug; -extern struct cvar_s *gl_sky_divide; -extern struct cvar_s *gl_sky_multipass; -extern struct cvar_s *gl_tessellate; -extern struct cvar_s *gl_texsort; -extern struct cvar_s *gl_textures_bgra; -extern struct cvar_s *gl_triplebuffer; -extern struct cvar_s *gl_vector_light; +extern int gl_affinemodels; +extern float gl_anisotropy; +extern int gl_clear; +extern float gl_conspin; +extern int gl_constretch; +extern int gl_dlight_polyblend; +extern int gl_dlight_smooth; +extern int gl_fb_bmodels; +extern int gl_fb_models; +extern int gl_finish; +extern int gl_keeptjunctions; +extern int gl_lerp_anim; +extern int gl_lightmap_align; +extern int gl_lightmap_subimage; +extern int gl_max_size; +extern int gl_multitexture; +extern int gl_nocolors; +extern int gl_overbright; +extern int gl_particle_mip; +extern int gl_particle_size; +extern int gl_picmip; +extern int gl_playermip; +extern int gl_reporttjunctions; +extern int gl_sky_clip; +extern int gl_sky_debug; +extern int gl_sky_multipass; +extern int gl_tessellate; +extern int gl_texsort; +extern int gl_textures_bgra; +extern int gl_triplebuffer; +extern int gl_vector_light; -extern struct cvar_s *r_aliasstats; -extern struct cvar_s *r_aliastransadj; -extern struct cvar_s *r_aliastransbase; -extern struct cvar_s *r_clearcolor; -extern struct cvar_s *r_dlight_lightmap; -extern struct cvar_s *r_drawentities; -extern struct cvar_s *r_drawexplosions; -extern struct cvar_s *r_drawviewmodel; -extern struct cvar_s *r_dspeeds; -extern struct cvar_s *r_dynamic; -extern struct cvar_s *r_explosionclip; -extern struct cvar_s *r_farclip; -extern struct cvar_s *r_firecolor; -extern struct cvar_s *r_flatlightstyles; -extern struct cvar_s *r_graphheight; -extern struct cvar_s *r_lightmap_components; -extern struct cvar_s *r_maxedges; -extern struct cvar_s *r_maxsurfs; -extern struct cvar_s *r_mirroralpha; -extern struct cvar_s *r_nearclip; -extern struct cvar_s *r_norefresh; -extern struct cvar_s *r_novis; -extern struct cvar_s *r_numedges; -extern struct cvar_s *r_numsurfs; -extern struct cvar_s *r_particles; -extern struct cvar_s *r_particles_max; -extern struct cvar_s *r_particles_nearclip; -extern struct cvar_s *r_reportedgeout; -extern struct cvar_s *r_reportsurfout; -extern struct cvar_s *r_shadows; -extern struct cvar_s *r_skyname; -extern struct cvar_s *r_speeds; -extern struct cvar_s *r_timegraph; -extern struct cvar_s *r_wateralpha; -extern struct cvar_s *r_waterripple; -extern struct cvar_s *r_waterwarp; -extern struct cvar_s *r_zgraph; +extern int r_aliasstats; +extern float r_aliastransadj; +extern float r_aliastransbase; +extern int r_clearcolor; +extern int r_dlight_lightmap; +extern int r_drawentities; +extern int r_drawexplosions; +extern int r_drawviewmodel; +extern int r_dspeeds; +extern int r_dynamic; +extern int r_explosionclip; +extern float r_farclip; +extern vec4f_t r_firecolor; +extern int r_flatlightstyles; +extern int r_graphheight; +extern int r_lightmap_components; +extern int r_maxedges; +extern int r_maxsurfs; +extern float r_mirroralpha; +extern float r_nearclip; +extern int r_norefresh; +extern int r_novis; +extern int r_numedges; +extern int r_numsurfs; +extern int r_particles; +extern int r_particles_max; +extern float r_particles_nearclip; +extern int r_reportedgeout; +extern int r_reportsurfout; +extern int r_shadows; +extern char *r_skyname; +extern int r_speeds; +extern int r_timegraph; +extern float r_wateralpha; +extern float r_waterripple; +extern int r_waterwarp; +extern int r_zgraph; -extern struct cvar_s *scr_fov; -extern struct cvar_s *scr_fisheye; -extern struct cvar_s *scr_fviews; -extern struct cvar_s *scr_ffov; -extern struct cvar_s *scr_showpause; -extern struct cvar_s *scr_showram; -extern struct cvar_s *scr_showturtle; -extern struct cvar_s *scr_viewsize; +extern float scr_fov; +extern int scr_fisheye; +extern int scr_fviews; +extern float scr_ffov; +extern int scr_showpause; +extern int scr_showram; +extern int scr_showturtle; +extern int scr_viewsize; diff --git a/include/r_dynamic.h b/include/r_dynamic.h index 3239a9297..9c2a23525 100644 --- a/include/r_dynamic.h +++ b/include/r_dynamic.h @@ -46,16 +46,12 @@ typedef enum { struct entity_s; void R_PushDlights (const vec3_t entorigin); -struct cvar_s; -void R_MaxDlightsCheck (struct cvar_s *var); +void R_MaxDlightsCheck (int max_dlights); void R_Particles_Init_Cvars (void); void R_InitBubble (void); void R_InitParticles (void); void R_ClearParticles (void); -struct cvar_s; -void R_MaxParticlesCheck (struct cvar_s *r_particles, - struct cvar_s *r_particles_max); void R_InitSprites (void); #endif // _R_DYNAMIC_H diff --git a/include/r_local.h b/include/r_local.h index ef0db6963..486347f0d 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -66,22 +66,22 @@ typedef struct { //=========================================================================== -extern struct cvar_s *r_speeds; -extern struct cvar_s *r_timegraph; -extern struct cvar_s *r_graphheight; -extern struct cvar_s *r_clearcolor; -extern struct cvar_s *r_waterwarp; -extern struct cvar_s *r_drawentities; -extern struct cvar_s *r_aliasstats; -extern struct cvar_s *r_dspeeds; -extern struct cvar_s *r_drawflat; -extern struct cvar_s *r_ambient; -extern struct cvar_s *r_reportsurfout; -extern struct cvar_s *r_maxsurfs; -extern struct cvar_s *r_numsurfs; -extern struct cvar_s *r_reportedgeout; -extern struct cvar_s *r_maxedges; -extern struct cvar_s *r_numedges; +extern int r_speeds; +extern int r_timegraph; +extern int r_graphheight; +extern int r_clearcolor; +extern int r_waterwarp; +extern int r_drawentities; +extern int r_aliasstats; +extern int r_dspeeds; +extern int r_drawflat; +extern int r_ambient; +extern int r_reportsurfout; +extern int r_maxsurfs; +extern int r_numsurfs; +extern int r_reportedgeout; +extern int r_maxedges; +extern int r_numedges; extern float cl_wateralpha; diff --git a/include/r_shared.h b/include/r_shared.h index 2251a7b1d..16bb3bbb2 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -60,7 +60,7 @@ extern float pixelAspect; extern int r_drawnpolycount; -extern struct cvar_s *r_clearcolor; +extern int r_clearcolor; extern int sintable[SIN_BUFFER_SIZE]; extern int intsintable[SIN_BUFFER_SIZE]; diff --git a/include/sbar.h b/include/sbar.h index 7fa9fbdd3..a8d964010 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -38,7 +38,7 @@ extern int sb_lines; // scan lines to draw void Sbar_Init (void); struct cvar_s; -void Sbar_DMO_Init_f (struct cvar_s *var); +void Sbar_DMO_Init_f (void *data, const struct cvar_s *var); void Sbar_Changed (void); // call whenever any of the client stats represented on the sbar changes diff --git a/include/snd_internal.h b/include/snd_internal.h index 078d32cbb..63dd6a62d 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -229,7 +229,7 @@ struct channel_s { //@} }; -extern struct cvar_s *snd_volume; +extern float snd_volume; extern snd_render_data_t snd_render_data; #define PAINTBUFFER_SIZE 512 diff --git a/include/vid_internal.h b/include/vid_internal.h index 9df75a395..f413d4d66 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -4,6 +4,14 @@ #include "QF/vid.h" #include "QF/plugin/vid_render.h" +typedef struct vid_system_s { + void (*init) (byte *palette, byte *colormap); + void (*init_cvars) (void); + void (*update_fullscreen) (int fullscreen); +} vid_system_t; + +extern vid_system_t vid_system; + typedef struct vid_internal_s { void (*flush_caches) (void *data); void (*init_buffers) (void *data); @@ -20,15 +28,15 @@ typedef struct vid_internal_s { struct vulkan_ctx_s *(*vulkan_context) (void); } vid_internal_t; -extern struct cvar_s *vid_fullscreen; -extern struct cvar_s *vid_system_gamma; -extern struct cvar_s *vid_gamma; +extern int vid_fullscreen; +extern int vid_system_gamma; +extern float vid_gamma; void VID_GetWindowSize (int def_w, int def_h); void VID_InitGamma (const byte *); qboolean VID_SetGamma (double); -void VID_UpdateGamma (struct cvar_s *); +void VID_UpdateGamma (void); void VID_MakeColormaps (void); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index def07b666..9cfe51ca7 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -108,13 +108,13 @@ typedef struct vulkan_ctx_s { #define qfvPushDebug(ctx, x) \ do { \ - if (developer->int_val & SYS_vulkan) { \ + if (developer & SYS_vulkan) { \ DARRAY_APPEND(&(ctx)->instance->debug_stack, (x)); \ } \ } while (0) #define qfvPopDebug(ctx) \ do { \ - if (developer->int_val & SYS_vulkan) { \ + if (developer & SYS_vulkan) { \ __auto_type ds = &(ctx)->instance->debug_stack; \ DARRAY_REMOVE_AT(ds, ds->size - 1); \ } \ diff --git a/libs/audio/cd.c b/libs/audio/cd.c index 0faee5a13..4ac01e361 100644 --- a/libs/audio/cd.c +++ b/libs/audio/cd.c @@ -40,7 +40,15 @@ #include "QF/plugin/general.h" #include "QF/plugin/cd.h" -cvar_t *cd_plugin; +char *cd_plugin; +static cvar_t cd_plugin_cvar = { + .name = "cd_plugin", + .description = + "CD Plugin to use", + .default_value = CD_DEFAULT, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &cd_plugin }, +}; plugin_t *cdmodule = NULL; CD_PLUGIN_PROTOS @@ -96,19 +104,18 @@ CDAudio_Init (void) Sys_RegisterShutdown (CDAudio_shutdown, 0); PI_RegisterPlugins (cd_plugin_list); - cd_plugin = Cvar_Get ("cd_plugin", CD_DEFAULT, CVAR_ROM, NULL, - "CD Plugin to use"); + Cvar_Register (&cd_plugin_cvar, 0, 0); if (COM_CheckParm ("-nocdaudio")) return 0; - if (!*cd_plugin->string) { + if (!*cd_plugin) { Sys_Printf ("Not loading CD due to no driver\n"); return 0; } - cdmodule = PI_LoadPlugin ("cd", cd_plugin->string); + cdmodule = PI_LoadPlugin ("cd", cd_plugin); if (!cdmodule) { - Sys_Printf ("Loading of cd module: %s failed!\n", cd_plugin->string); + Sys_Printf ("Loading of cd module: %s failed!\n", cd_plugin); return -1; } Cmd_AddCommand ( diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index 126dabd1e..401c6b59a 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -84,15 +84,31 @@ static plitem_t *play_list; // string or array of strings static int play_pos = -1; // position in play_list (0 for string) // -1 = invalid (both) -static cvar_t *bgmvolume; // volume cvar -static cvar_t *mus_ogglist; // tracklist cvar +static float bgmvolume; +static cvar_t bgmvolume_cvar = { + .name = "bgmvolume", + .description = + "Volume of CD music", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &bgmvolume }, +}; +static char *mus_ogglist; +static cvar_t mus_ogglist_cvar = { + .name = "mus_ogglist", + .description = + "filename of track to music file map", + .default_value = "tracklist.cfg", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &mus_ogglist }, +}; static void set_volume (void) { if (cd_channel && cd_channel->sfx) { - int vol = bgmvolume->value * 255; + int vol = bgmvolume * 255; cd_channel->master_vol = vol; cd_channel->leftvol = cd_channel->rightvol = cd_channel->master_vol; @@ -151,14 +167,14 @@ Load_Tracklist (void) ogglistvalid = false; mus_enabled = false; - if (!mus_ogglist || strequal (mus_ogglist->string, "none")) { + if (!mus_ogglist || strequal (mus_ogglist, "none")) { return -1; // bail if we don't have a valid filename } - oggfile = QFS_FOpenFile (mus_ogglist->string); + oggfile = QFS_FOpenFile (mus_ogglist); if (!oggfile) { Sys_Printf ("Mus_OggInit: open of file \"%s\" failed\n", - mus_ogglist->string); + mus_ogglist); return -1; } @@ -324,7 +340,7 @@ I_OGGMus_Info (void) return; Sys_Printf ("\n" "Tracklist loaded from file:\n%s\n" - "---------------------------\n", mus_ogglist->string); + "---------------------------\n", mus_ogglist); /* loop, and count up the Highest key number. */ for (iter = 1, count = 0; count < keycount && iter <= 99 ; iter++) { @@ -439,15 +455,14 @@ I_OGGMus_Update (void) /* called when the mus_ogglist cvar is changed */ static void -Mus_OggChange (cvar_t *ogglist) +Mus_OggChange (void *data, const cvar_t *cvar) { - mus_ogglist = ogglist; Load_Tracklist (); } /* change volume on sound object */ static void -Mus_VolChange (cvar_t *bgmvolume) +Mus_VolChange (void *data, const cvar_t *bgmvolume) { set_volume (); } @@ -456,18 +471,15 @@ static void Mus_gamedir (int phase) { if (phase) - Mus_OggChange (mus_ogglist); + Load_Tracklist (); } static void I_OGGMus_Init (void) { /* check list file cvar, open list file, create map, close file. */ - mus_ogglist = Cvar_Get ("mus_ogglist", "tracklist.cfg", CVAR_NONE, - Mus_OggChange, - "filename of track to music file map"); - bgmvolume = Cvar_Get ("bgmvolume", "1.0", CVAR_ARCHIVE, Mus_VolChange, - "Volume of CD music"); + Cvar_Register (&mus_ogglist_cvar, Mus_OggChange, 0); + Cvar_Register (&bgmvolume_cvar, Mus_VolChange, 0); QFS_GamedirCallback (Mus_gamedir); } diff --git a/libs/audio/cd_linux.c b/libs/audio/cd_linux.c index 53bc7f450..15452ce8c 100644 --- a/libs/audio/cd_linux.c +++ b/libs/audio/cd_linux.c @@ -77,8 +77,24 @@ static byte playTrack; static byte maxTrack; static int cdfile = -1; -static cvar_t *mus_cddevice; -static cvar_t *bgmvolume; +static char *mus_cddevice; +static cvar_t mus_cddevice_cvar = { + .name = "mus_cddevice", + .description = + "device to use for CD music", + .default_value = "/dev/cdrom", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &mus_cddevice }, +}; +static float bgmvolume; +static cvar_t bgmvolume_cvar = { + .name = "bgmvolume", + .description = + "Volume of CD music", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &bgmvolume }, +}; static void @@ -382,14 +398,14 @@ I_CDAudio_Update (void) if (!mus_enabled) return; - if (bgmvolume->value != cdvolume) { + if (bgmvolume != cdvolume) { if (cdvolume) { - Cvar_SetValue (bgmvolume, 0.0); - cdvolume = bgmvolume->value; + bgmvolume = 0.0; + cdvolume = bgmvolume; I_CDAudio_Pause (); } else { - Cvar_SetValue (bgmvolume, 1.0); - cdvolume = bgmvolume->value; + bgmvolume = 1.0; + cdvolume = bgmvolume; I_CDAudio_Resume (); } } @@ -412,20 +428,20 @@ I_CDAudio_Update (void) } static void -Mus_CDChange (cvar_t *mus_cdaudio) +Mus_CDChange (void *data, const cvar_t *cvar) { int i; I_CDAudio_Shutdown (); - if (strequal (mus_cdaudio->string, "none")) { + if (strequal (mus_cddevice, "none")) { return; } - cdfile = open (mus_cdaudio->string, O_RDONLY | O_NONBLOCK); + cdfile = open (mus_cddevice, O_RDONLY | O_NONBLOCK); if (cdfile == -1) { Sys_MaskPrintf (SYS_snd, "Mus_CDInit: open device \"%s\" failed (error %i)\n", - mus_cdaudio->string, errno); + mus_cddevice, errno); return; } @@ -443,10 +459,8 @@ Mus_CDChange (cvar_t *mus_cdaudio) static void I_CDAudio_Init (void) { - mus_cddevice = Cvar_Get ("mus_cddevice", "/dev/cdrom", CVAR_NONE, - Mus_CDChange, "device to use for CD music"); - bgmvolume = Cvar_Get ("bgmvolume", "1", CVAR_ARCHIVE, NULL, - "Volume of CD music"); + Cvar_Register (&mus_cddevice_cvar, Mus_CDChange, 0); + Cvar_Register (&bgmvolume_cvar, 0, 0); } static general_funcs_t plugin_info_general_funcs = { diff --git a/libs/audio/cd_sdl.c b/libs/audio/cd_sdl.c index fb3b9b502..2e90c342a 100644 --- a/libs/audio/cd_sdl.c +++ b/libs/audio/cd_sdl.c @@ -64,7 +64,15 @@ static qboolean playLooping = false; static SDL_CD *cd_id; static float cdvolume = 1.0; -static cvar_t *bgmvolume; +static float bgmvolume; +static cvar_t bgmvolume_cvar = { + .name = "bgmvolume", + .description = + "Volume of CD music", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &bgmvolume }, +}; static void @@ -168,15 +176,15 @@ I_CDAudio_Update (void) { if (!cd_id || !enabled) return; - if (bgmvolume->value != cdvolume) { + if (bgmvolume != cdvolume) { if (cdvolume) { - Cvar_SetValue (bgmvolume, 0.0); + bgmvolume = 0.0; I_CDAudio_Pause (); } else { - Cvar_SetValue (bgmvolume, 1.0); + bgmvolume = 1.0; I_CDAudio_Resume (); } - cdvolume = bgmvolume->value; + cdvolume = bgmvolume; return; } if (playLooping && (SDL_CDStatus (cd_id) != CD_PLAYING) @@ -276,8 +284,7 @@ I_CDAudio_Init (void) cdValid = false; } - bgmvolume = Cvar_Get ("bgmvolume", "1", CVAR_ARCHIVE, NULL, - "Volume of CD music"); + Cvar_Register (&bgmvolume_cvar, 0, 0); Sys_Printf ("CD Audio Initialized.\n"); } diff --git a/libs/audio/cd_sgi.c b/libs/audio/cd_sgi.c index 2f235d86b..8e57bb9ed 100644 --- a/libs/audio/cd_sgi.c +++ b/libs/audio/cd_sgi.c @@ -63,7 +63,15 @@ static byte playTrack; static char cd_dev[] = "/dev/cdrom"; static CDPLAYER *cdp = NULL; -static cvar_t *bgmvolume; +static float bgmvolume; +static cvar_t bgmvolume_cvar = { + .name = "bgmvolume", + .description = + "Volume of CD music", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &bgmvolume }, +}; static void I_SGI_Eject (void) @@ -219,14 +227,14 @@ I_SGI_Update (void) if (!initialized || !enabled) return; - if (bgmvolume->value != cdvolume) { + if (bgmvolume != cdvolume) { if (cdvolume) { - Cvar_SetValue (bgmvolume, 0.0); - cdvolume = bgmvolume->value; + bgmvolume = 0.0; + cdvolume = bgmvolume; CDAudio_Pause (); } else { - Cvar_SetValue (bgmvolume, 1.0); - cdvolume = bgmvolume->value; + bgmvolume = 1.0; + cdvolume = bgmvolume; CDAudio_Resume (); } } @@ -334,8 +342,7 @@ I_SGI_Init (void) { int i; - bgmvolume = Cvar_Get ("bgmvolume", "1", CVAR_ARCHIVE, NULL, - "Volume of CD music"); + Cvar_Register (&bgmvolume_cvar, 0, 0); if ((i = COM_CheckParm ("-cddev")) != 0 && i < com_argc - 1) { strncpy (cd_dev, com_argv[i + 1], sizeof (cd_dev)); cd_dev[sizeof (cd_dev) - 1] = 0; diff --git a/libs/audio/cd_win.c b/libs/audio/cd_win.c index 919908a79..2d2aa59fe 100644 --- a/libs/audio/cd_win.c +++ b/libs/audio/cd_win.c @@ -64,7 +64,15 @@ static UINT wDeviceID; static void I_CDAudio_Play (int track, qboolean looping); static void I_CDAudio_Stop (void); -static cvar_t *bgmvolume; +static float bgmvolume; +static cvar_t bgmvolume_cvar = { + .name = "bgmvolume", + .description = + "Volume of CD music", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &bgmvolume }, +}; static void @@ -331,14 +339,14 @@ I_CDAudio_Update (void) if (!enabled) return; - if (bgmvolume->value != cdvolume) { + if (bgmvolume != cdvolume) { if (cdvolume) { - Cvar_SetValue (bgmvolume, 0.0); - cdvolume = bgmvolume->value; + bgmvolume = 0.0; + cdvolume = bgmvolume; I_CDAudio_Pause (); } else { - Cvar_SetValue (bgmvolume, 1.0); - cdvolume = bgmvolume->value; + bgmvolume = 1.0; + cdvolume = bgmvolume; I_CDAudio_Resume (); } } @@ -483,8 +491,7 @@ I_CDAudio_Init (void) initialized = true; enabled = true; - bgmvolume = Cvar_Get ("bgmvolume", "1", CVAR_ARCHIVE, NULL, - "Volume of CD music"); + Cvar_Register (&bgmvolume_cvar, 0, 0); if (I_CDAudio_GetAudioDiskInfo ()) { Sys_Printf ("CDAudio_Init: No CD in player.\n"); diff --git a/libs/audio/renderer/Makemodule.am b/libs/audio/renderer/Makemodule.am index a98c2214f..0e726fe36 100644 --- a/libs/audio/renderer/Makemodule.am +++ b/libs/audio/renderer/Makemodule.am @@ -2,39 +2,57 @@ plugin_LTLIBRARIES += @snd_render_plugins@ noinst_LTLIBRARIES += @snd_render_static_plugins@ EXTRA_LTLIBRARIES += libs/audio/renderer/snd_render_default.la -flac_src=libs/audio/renderer/flac.c -midi_src=libs/audio/renderer/midi.c -vorbis_src=libs/audio/renderer/vorbis.c -wav_src=libs/audio/renderer/wav.c +flac_src = libs/audio/renderer/flac.c +midi_src = libs/audio/renderer/midi.c +vorbis_src = libs/audio/renderer/vorbis.c +wav_src = libs/audio/renderer/wav.c if HAVE_FLAC -have_flac_src=$(flac_src) +have_flac_src = $(flac_src) else -have_flac_src= +have_flac_src = endif if HAVE_MIDI -have_midi_src=$(midi_src) +have_midi_src = $(midi_src) else -have_midi_src= +have_midi_src = endif if HAVE_VORBIS -have_vorbis_src=$(vorbis_src) +have_vorbis_src = $(vorbis_src) else -have_vorbis_src= +have_vorbis_src = endif -have_wav_src=$(wav_src) +have_wav_src = $(wav_src) format_src=$(have_flac_src) $(have_midi_src) $(have_vorbis_src) $(have_wav_src) format_libs= \ - $(SAMPLERATE_LIBS) $(VORBISFILE_LIBS) $(VORBIS_LIBS) $(FLAC_LIBS) \ - $(OGG_LIBS) $(WM_LIBS) -extra_format_src=libs/audio/renderer/flac.c libs/audio/renderer/midi.c libs/audio/renderer/vorbis.c libs/audio/renderer/wav.c -snd_common=libs/audio/renderer/snd_channels.c libs/audio/renderer/snd_mem.c libs/audio/renderer/snd_mix.c libs/audio/renderer/snd_resample.c libs/audio/renderer/snd_sfx.c -snd_libs= \ + $(SAMPLERATE_LIBS) \ + $(VORBISFILE_LIBS) \ + $(VORBIS_LIBS) \ + $(FLAC_LIBS) \ + $(OGG_LIBS) \ + $(WM_LIBS) +extra_format_src = \ + libs/audio/renderer/flac.c \ + libs/audio/renderer/midi.c \ + libs/audio/renderer/vorbis.c \ + libs/audio/renderer/wav.c +snd_common = \ + libs/audio/renderer/snd_channels.c \ + libs/audio/renderer/snd_mem.c \ + libs/audio/renderer/snd_mix.c \ + libs/audio/renderer/snd_resample.c \ + libs/audio/renderer/snd_sfx.c +snd_libs = \ libs/util/libQFutil.la -libs_audio_renderer_snd_render_default_la_LDFLAGS= $(plugin_ldflags) -libs_audio_renderer_snd_render_default_la_SOURCES= libs/audio/renderer/snd_dma.c $(snd_common) $(format_src) -libs_audio_renderer_snd_render_default_la_LIBADD= $(snd_libs) $(format_libs) -libs_audio_renderer_snd_render_default_la_DEPENDENCIES= $(snd_libs) -EXTRA_libs_audio_renderer_snd_render_default_la_SOURCES=$(extra_format_src) +libs_audio_renderer_snd_render_default_la_LDFLAGS = $(plugin_ldflags) +libs_audio_renderer_snd_render_default_la_SOURCES = \ + libs/audio/renderer/snd_dma.c \ + $(snd_common) \ + $(format_src) +libs_audio_renderer_snd_render_default_la_LIBADD = \ + $(snd_libs) \ + $(format_libs) +libs_audio_renderer_snd_render_default_la_DEPENDENCIES = $(snd_libs) +EXTRA_libs_audio_renderer_snd_render_default_la_SOURCES = $(extra_format_src) diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index 4a2b51ab2..f0dc91b58 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -57,19 +57,32 @@ typedef struct { static int midi_intiialized = 0; -static cvar_t *wildmidi_volume; -static cvar_t *wildmidi_config; +static char *wildmidi_volume; +static cvar_t wildmidi_volume_cvar = { + .name = "wildmidi_volume", + .description = + "Set the Master Volume", + .default_value = "100", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &wildmidi_volume }, +}; +static char *wildmidi_config; +static cvar_t wildmidi_config_cvar = { + .name = "wildmidi_config", + .description = + "path/filename of timidity.cfg", + .default_value = "/etc/timidity.cfg", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &wildmidi_config }, +}; static int midi_init (snd_t *snd) { - wildmidi_volume = Cvar_Get ("wildmidi_volume", "100", CVAR_ARCHIVE, NULL, - "Set the Master Volume"); - wildmidi_config = Cvar_Get ("wildmidi_config", "/etc/timidity.cfg", - CVAR_ROM, NULL, - "path/filename of timidity.cfg"); + Cvar_Register (&wildmidi_volume_cvar, 0, 0); + Cvar_Register (&wildmidi_config_cvar, 0, 0); - if (WildMidi_Init (wildmidi_config->string, snd->speed, 0) == -1) + if (WildMidi_Init (wildmidi_config, snd->speed, 0) == -1) return 1; midi_intiialized = 1; return 0; diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 492fb430b..66e9f19ab 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -71,11 +71,51 @@ static vec4f_t listener_forward; static vec4f_t listener_right; static vec4f_t listener_up; -static cvar_t *snd_phasesep; -static cvar_t *snd_volumesep; -static cvar_t *snd_swapchannelside; -static cvar_t *ambient_fade; -static cvar_t *ambient_level; +static float snd_phasesep; +static cvar_t snd_phasesep_cvar = { + .name = "snd_phasesep", + .description = + "max stereo phase separation in ms. 0.6 is for 20cm head", + .default_value = "0.0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &snd_phasesep }, +}; +static float snd_volumesep; +static cvar_t snd_volumesep_cvar = { + .name = "snd_volumesep", + .description = + "max stereo volume separation. 1.0 is max", + .default_value = "1.0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &snd_volumesep }, +}; +static int snd_swapchannelside; +static cvar_t snd_swapchannelside_cvar = { + .name = "snd_swapchannelside", + .description = + "Toggle swapping of left and right channels", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &snd_swapchannelside }, +}; +static float ambient_fade; +static cvar_t ambient_fade_cvar = { + .name = "ambient_fade", + .description = + "How quickly ambient sounds fade in or out", + .default_value = "100", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &ambient_fade }, +}; +static float ambient_level; +static cvar_t ambient_level_cvar = { + .name = "ambient_level", + .description = + "Ambient sounds' volume", + .default_value = "0.3", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &ambient_level }, +}; static inline channel_t * unlink_channel (channel_t **_ch) @@ -320,18 +360,11 @@ SND_Channels_Init (snd_t *snd) { int i; - snd_phasesep = Cvar_Get ("snd_phasesep", "0.0", CVAR_ARCHIVE, NULL, - "max stereo phase separation in ms. 0.6 is for " - "20cm head"); - snd_volumesep = Cvar_Get ("snd_volumesep", "1.0", CVAR_ARCHIVE, NULL, - "max stereo volume separation. 1.0 is max"); - snd_swapchannelside = Cvar_Get ("snd_swapchannelside", "0", CVAR_ARCHIVE, - NULL, "Toggle swapping of left and right " - "channels"); - ambient_fade = Cvar_Get ("ambient_fade", "100", CVAR_NONE, NULL, - "How quickly ambient sounds fade in or out"); - ambient_level = Cvar_Get ("ambient_level", "0.3", CVAR_NONE, NULL, - "Ambient sounds' volume"); + Cvar_Register (&snd_phasesep_cvar, 0, 0); + Cvar_Register (&snd_volumesep_cvar, 0, 0); + Cvar_Register (&snd_swapchannelside_cvar, 0, 0); + Cvar_Register (&ambient_fade_cvar, 0, 0); + Cvar_Register (&ambient_level_cvar, 0, 0); Cmd_AddDataCommand ("play", s_play_f, snd, "Play selected sound effect (play pathto/sound.wav)"); @@ -408,7 +441,7 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) if (!snd_ambient) return; // calc ambient sound levels - if (!ambient_sound_level || !ambient_level->value) { + if (!ambient_sound_level || !ambient_level) { // if we're not in a leaf (huh?) or ambients have been turned off, // stop all ambient channels. for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS; @@ -447,19 +480,19 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) // sfx will be written to chan->sfx later to ensure mixer doesn't use // channel prematurely. - vol = ambient_level->value * ambient_sound_level[ambient_channel]; + vol = ambient_level * ambient_sound_level[ambient_channel]; if (vol < 8) vol = 0; // don't adjust volume too fast if (chan->master_vol < vol) { chan->master_vol += *snd_render_data.host_frametime - * ambient_fade->value; + * ambient_fade; if (chan->master_vol > vol) chan->master_vol = vol; } else if (chan->master_vol > vol) { chan->master_vol -= *snd_render_data.host_frametime - * ambient_fade->value; + * ambient_fade; if (chan->master_vol < vol) chan->master_vol = vol; } @@ -494,7 +527,7 @@ s_spatialize (snd_t *snd, channel_t *ch) dist = VectorNormalize (source_vec) * ch->dist_mult; dot = DotProduct (listener_right, source_vec); - if (snd_swapchannelside->int_val) + if (snd_swapchannelside) dot = -dot; if (snd->channels == 1) { @@ -502,9 +535,9 @@ s_spatialize (snd_t *snd, channel_t *ch) lscale = 1.0; phase = 0; } else { - rscale = 1.0 + dot * snd_volumesep->value; - lscale = 1.0 - dot * snd_volumesep->value; - phase = snd_phasesep->value * 0.001 * snd->speed * dot; + rscale = 1.0 + dot * snd_volumesep; + lscale = 1.0 - dot * snd_volumesep; + phase = snd_phasesep * 0.001 * snd->speed * dot; } // add in distance effect diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 010793cae..c8ab69577 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -60,10 +60,52 @@ static unsigned soundtime; // sample PAIRS static int sound_started = 0; -static cvar_t *nosound; -static cvar_t *snd_mixahead; -static cvar_t *snd_noextraupdate; -static cvar_t *snd_show; +float snd_volume; +static cvar_t snd_volume_cvar = { + .name = "volume", + .description = + "Set the volume for sound playback", + .default_value = "0.7", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &snd_volume }, +}; +static char *nosound; +static cvar_t nosound_cvar = { + .name = "nosound", + .description = + "Set to turn sound off", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &nosound }, +}; +static float snd_mixahead; +static cvar_t snd_mixahead_cvar = { + .name = "snd_mixahead", + .description = + "Delay time for sounds", + .default_value = "0.1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &snd_mixahead }, +}; +static int snd_noextraupdate; +static cvar_t snd_noextraupdate_cvar = { + .name = "snd_noextraupdate", + .description = + "Toggles the correct value display in host_speeds. Usually messes up " + "sound playback when in effect", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &snd_noextraupdate }, +}; +static char *snd_show; +static cvar_t snd_show_cvar = { + .name = "snd_show", + .description = + "Toggles display of sounds currently being played", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &snd_show }, +}; static general_data_t plugin_info_general_data; @@ -196,7 +238,7 @@ s_update_ (void) snd.paintedtime = soundtime; } // mix ahead of current position - endtime = soundtime + snd_mixahead->value * snd.speed; + endtime = soundtime + snd_mixahead * snd.speed; samps = snd.frames; if (endtime - soundtime > samps) endtime = soundtime + samps; @@ -233,7 +275,7 @@ static void s_extra_update (void) { if (snd_output_data->model == som_push) { - if (!sound_started || snd_noextraupdate->int_val) + if (!sound_started || snd_noextraupdate) return; // don't pollute timings s_update_ (); } @@ -315,18 +357,11 @@ s_snd_force_unblock (void) static void s_init_cvars (void) { - nosound = Cvar_Get ("nosound", "0", CVAR_NONE, NULL, - "Set to turn sound off"); - snd_volume = Cvar_Get ("volume", "0.7", CVAR_ARCHIVE, NULL, - "Set the volume for sound playback"); - snd_mixahead = Cvar_Get ("snd_mixahead", "0.1", CVAR_ARCHIVE, NULL, - "Delay time for sounds"); - snd_noextraupdate = Cvar_Get ("snd_noextraupdate", "0", CVAR_NONE, NULL, - "Toggles the correct value display in " - "host_speeds. Usually messes up sound " - "playback when in effect"); - snd_show = Cvar_Get ("snd_show", "0", CVAR_NONE, NULL, - "Toggles display of sounds currently being played"); + Cvar_Register (&nosound_cvar, 0, 0); + Cvar_Register (&snd_volume_cvar, 0, 0); + Cvar_Register (&snd_mixahead_cvar, 0, 0); + Cvar_Register (&snd_noextraupdate_cvar, 0, 0); + Cvar_Register (&snd_show_cvar, 0, 0); } static void @@ -344,13 +379,6 @@ s_init (void) Cmd_AddCommand ("snd_force_unblock", s_snd_force_unblock, "fix permanently blocked sound"); -// FIXME -//extern struct cvar_s *snd_loadas8bit; -// if (host_parms.memsize < 0x800000) { -// Cvar_Set (snd_loadas8bit, "1"); -// Sys_Printf ("loading all sounds as 8bit\n"); -// } - snd_initialized = true; s_startup (); diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index d26b4e430..36ee40527 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -48,8 +48,6 @@ // note: must be >= 255 due to the channel // volumes being 0-255. -cvar_t *snd_volume; - portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; static int max_overpaint; // number of extra samples painted // due to phase shift @@ -170,7 +168,7 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) // transfer out according to DMA format snd->xfer (snd, snd_paintbuffer, end - snd->paintedtime, - snd_volume->value); + snd_volume); memmove (snd_paintbuffer, snd_paintbuffer + end - snd->paintedtime, max_overpaint * sizeof (snd_paintbuffer[0])); diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index b3abc6f66..b3ad1b602 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -53,7 +53,15 @@ static sfx_t snd_sfx[MAX_SFX]; static int snd_num_sfx; static hashtab_t *snd_sfx_hash; -static cvar_t *precache; +static int precache; +static cvar_t precache_cvar = { + .name = "precache", + .description = + "Toggle the use of a precache", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &precache }, +}; static const char * snd_sfx_getkey (const void *sfx, void *unused) @@ -203,7 +211,7 @@ SND_PrecacheSound (snd_t *snd, const char *name) Sys_Error ("SND_PrecacheSound: NULL"); sfx = SND_LoadSound (snd, va (0, "sound/%s", name)); - if (sfx && precache->int_val) { + if (sfx && precache) { if (sfx->retain (sfx)) sfx->release (sfx); } @@ -249,8 +257,7 @@ void SND_SFX_Init (snd_t *snd) { snd_sfx_hash = Hash_NewTable (511, snd_sfx_getkey, snd_sfx_free, 0, 0); - precache = Cvar_Get ("precache", "1", CVAR_NONE, NULL, - "Toggle the use of a precache"); + Cvar_Register (&precache_cvar, 0, 0); QFS_GamedirCallback (s_gamedir); diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 072fef20f..86ddda631 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -37,8 +37,24 @@ #include "snd_internal.h" -static cvar_t *snd_output; -static cvar_t *snd_render; +static char *snd_output; +static cvar_t snd_output_cvar = { + .name = "snd_output", + .description = + "Sound Output Plugin to use", + .default_value = SND_OUTPUT_DEFAULT, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &snd_output }, +}; +static char *snd_render; +static cvar_t snd_render_cvar = { + .name = "snd_render", + .description = + "Sound Renderer Plugin to use", + .default_value = "default", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &snd_render }, +}; static plugin_t *snd_render_module = NULL; static plugin_t *snd_output_module = NULL; static snd_render_funcs_t *snd_render_funcs = NULL; @@ -73,7 +89,7 @@ S_Init (int *viewentity, double *host_frametime) if (COM_CheckParm ("-nosound")) return; - if (!*snd_output->string || !*snd_render->string) { + if (!*snd_output || !*snd_render) { Sys_Printf ("Not loading sound due to no renderer/output\n"); return; } @@ -82,15 +98,15 @@ S_Init (int *viewentity, double *host_frametime) PI_RegisterPlugins (snd_output_list); PI_RegisterPlugins (snd_render_list); - snd_output_module = PI_LoadPlugin ("snd_output", snd_output->string); + snd_output_module = PI_LoadPlugin ("snd_output", snd_output); if (!snd_output_module) { Sys_Printf ("Loading of sound output module: %s failed!\n", - snd_output->string); + snd_output); } else { - snd_render_module = PI_LoadPlugin ("snd_render", snd_render->string); + snd_render_module = PI_LoadPlugin ("snd_render", snd_render); if (!snd_render_module) { Sys_Printf ("Loading of sound render module: %s failed!\n", - snd_render->string); + snd_render); PI_UnloadPlugin (snd_output_module); snd_output_module = NULL; } else { @@ -114,10 +130,8 @@ S_Init (int *viewentity, double *host_frametime) VISIBLE void S_Init_Cvars (void) { - snd_output = Cvar_Get ("snd_output", SND_OUTPUT_DEFAULT, CVAR_ROM, NULL, - "Sound Output Plugin to use"); - snd_render = Cvar_Get ("snd_render", "default", CVAR_ROM, NULL, - "Sound Renderer Plugin to use"); + Cvar_Register (&snd_output_cvar, 0, 0); + Cvar_Register (&snd_render_cvar, 0, 0); } VISIBLE void diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index fdee222b1..8fba39a2c 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -53,10 +53,42 @@ static void *alsa_handle; static snd_pcm_t *pcm; static snd_async_handler_t *async_handler; -static cvar_t *snd_bits; -static cvar_t *snd_device; -static cvar_t *snd_rate; -static cvar_t *snd_stereo; +static int snd_bits; +static cvar_t snd_bits_cvar = { + .name = "snd_bits", + .description = + "sound sample depth. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_bits }, +}; +static char *snd_device; +static cvar_t snd_device_cvar = { + .name = "snd_device", + .description = + "sound device. \"\" is system default", + .default_value = "", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &snd_device }, +}; +static int snd_rate; +static cvar_t snd_rate_cvar = { + .name = "snd_rate", + .description = + "sound playback rate. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_rate }, +}; +static int snd_stereo; +static cvar_t snd_stereo_cvar = { + .name = "snd_stereo", + .description = + "sound stereo output", + .default_value = "1", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_stereo }, +}; //FIXME xfer probably should not be touching this (such data should probably //come through snd_t) @@ -92,14 +124,10 @@ load_libasound (void) static void SNDDMA_Init_Cvars (void) { - snd_stereo = Cvar_Get ("snd_stereo", "1", CVAR_ROM, NULL, - "sound stereo output"); - snd_rate = Cvar_Get ("snd_rate", "0", CVAR_ROM, NULL, - "sound playback rate. 0 is system default"); - snd_device = Cvar_Get ("snd_device", "", CVAR_ROM, NULL, - "sound device. \"\" is system default"); - snd_bits = Cvar_Get ("snd_bits", "0", CVAR_ROM, NULL, - "sound sample depth. 0 is system default"); + Cvar_Register (&snd_stereo_cvar, 0, 0); + Cvar_Register (&snd_rate_cvar, 0, 0); + Cvar_Register (&snd_device_cvar, 0, 0); + Cvar_Register (&snd_bits_cvar, 0, 0); } static __attribute__((const)) snd_pcm_uframes_t @@ -415,13 +443,13 @@ alsa_playback_set_bps (snd_t *snd, snd_pcm_hw_params_t *hw) int res; int bps = 0; - if (snd_bits->int_val == 16) { + if (snd_bits == 16) { bps = SND_PCM_FORMAT_S16_LE; snd->samplebits = 16; - } else if (snd_bits->int_val == 8) { + } else if (snd_bits == 8) { bps = SND_PCM_FORMAT_U8; snd->samplebits = 8; - } else if (snd_bits->int_val) { + } else if (snd_bits) { Sys_Printf ("snd_alsa: invalid sample bits: %d\n", bps); return 0; } @@ -454,7 +482,7 @@ alsa_playback_set_channels (snd_t *snd, snd_pcm_hw_params_t *hw) int res; int channels = 1; - if (snd_stereo->int_val) { + if (snd_stereo) { channels = 2; } if ((res = qfsnd_pcm_hw_params_set_channels (pcm, hw, channels)) == 0) { @@ -473,8 +501,8 @@ alsa_playback_set_rate (snd_t *snd, snd_pcm_hw_params_t *hw) unsigned rate = 0; static int default_rates[] = { 48000, 44100, 22050, 11025, 0 }; - if (snd_rate->int_val) { - rate = snd_rate->int_val; + if (snd_rate) { + rate = snd_rate; } if (rate) { @@ -531,7 +559,7 @@ static int SNDDMA_Init (snd_t *snd) { int res; - const char *device = snd_device->string; + const char *device = snd_device; snd_pcm_hw_params_t *hw; snd_pcm_sw_params_t *sw; diff --git a/libs/audio/targets/snd_dx.c b/libs/audio/targets/snd_dx.c index e53839c4e..610fc4616 100644 --- a/libs/audio/targets/snd_dx.c +++ b/libs/audio/targets/snd_dx.c @@ -83,21 +83,42 @@ static HINSTANCE hInstDS; static sndinitstat SNDDMA_InitDirect (snd_t *snd); -static cvar_t *snd_stereo; -static cvar_t *snd_rate; -static cvar_t *snd_bits; +static int snd_stereo; +static cvar_t snd_stereo_cvar = { + .name = "snd_stereo", + .description = + "sound stereo output", + .default_value = "1", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_stereo }, +}; +static int snd_rate; +static cvar_t snd_rate_cvar = { + .name = "snd_rate", + .description = + "sound playback rate. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_rate }, +}; +static int snd_bits; +static cvar_t snd_bits_cvar = { + .name = "snd_bits", + .description = + "sound sample depth. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_bits }, +}; static DWORD *DSOUND_LockBuffer (snd_t *snd, qboolean lockit); static void SNDDMA_Init_Cvars (void) { - snd_stereo = Cvar_Get ("snd_stereo", "1", CVAR_ROM, NULL, - "sound stereo output"); - snd_rate = Cvar_Get ("snd_rate", "11025", CVAR_ROM, NULL, - "sound playback rate. 0 is system default"); - snd_bits = Cvar_Get ("snd_bits", "16", CVAR_ROM, NULL, - "sound sample depth. 0 is system default"); + Cvar_Register (&snd_stereo_cvar, 0, 0); + Cvar_Register (&snd_rate_cvar, 0, 0); + Cvar_Register (&snd_bits_cvar, 0, 0); } static void @@ -152,14 +173,14 @@ SNDDMA_InitDirect (snd_t *snd) HRESULT hresult; WAVEFORMATEX format, pformat; - if (!snd_stereo->int_val) { + if (!snd_stereo) { snd->channels = 1; } else { snd->channels = 2; } - snd->samplebits = snd_bits->int_val; - snd->speed = snd_rate->int_val; + snd->samplebits = snd_bits; + snd->speed = snd_rate; memset (&format, 0, sizeof (format)); format.wFormatTag = WAVE_FORMAT_PCM; diff --git a/libs/audio/targets/snd_jack.c b/libs/audio/targets/snd_jack.c index 095349e1b..d484c3e46 100644 --- a/libs/audio/targets/snd_jack.c +++ b/libs/audio/targets/snd_jack.c @@ -55,8 +55,25 @@ static double snd_alive_time = 0; static jack_client_t *jack_handle; static jack_port_t *jack_out[2]; static float *output[2]; -static cvar_t *snd_jack_server; -static cvar_t *snd_jack_ports; +static char *snd_jack_server; +static cvar_t snd_jack_server_cvar = { + .name = "snd_jack_server", + .description = + "The name of the JACK server to connect to", + .default_value = "default", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &snd_jack_server }, +}; +static char *snd_jack_ports; +static cvar_t snd_jack_ports_cvar = { + .name = "snd_jack_ports", + .description = + "; separated list of port names to which QF will connect. Defaults to " + "the first two physical ports. Currently only two ports are supported.", + .default_value = "", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &snd_jack_ports }, +}; static int s_jack_connect (snd_t *snd); @@ -126,13 +143,13 @@ s_jack_activate (void) int i; snd_shutdown = 0; - if (!*snd_jack_ports->string) { + if (!*snd_jack_ports) { ports = jack_get_ports (jack_handle, 0, 0, JackPortIsPhysical | JackPortIsInput); } else { - ports = s_jack_parse_ports (snd_jack_ports->string); + ports = s_jack_parse_ports (snd_jack_ports); } - if (developer->int_val & SYS_snd) { + if (developer & SYS_snd) { for (i = 0; ports[i]; i++) { Sys_Printf ("%s\n", ports[i]); } @@ -222,7 +239,7 @@ snd_jack_error (const char *desc) static int snd_jack_xrun (void *arg) { - if (developer->int_val & SYS_snd) { + if (developer & SYS_snd) { fprintf (stderr, "snd_jack: xrun\n"); } return 0; @@ -236,7 +253,7 @@ s_jack_connect (snd_t *snd) jack_set_error_function (snd_jack_error); if ((jack_handle = jack_client_open ("QuakeForge", JackServerName | JackNoStartServer, 0, - snd_jack_server->string)) == 0) { + snd_jack_server)) == 0) { Sys_Printf ("Could not connect to JACK\n"); return 0; } @@ -280,13 +297,8 @@ s_shutdown (snd_t *snd) static void s_init_cvars (void) { - snd_jack_server = Cvar_Get ("snd_jack_server", "default", CVAR_ROM, NULL, - "The name of the JACK server to connect to"); - snd_jack_ports = Cvar_Get ("snd_jack_ports", "", CVAR_ROM, NULL, - "; separated list of port names to which QF " - "will connect. Defaults to the first two " - "physical ports. Currently only two ports " - "are supported."); + Cvar_Register (&snd_jack_server_cvar, 0, 0); + Cvar_Register (&snd_jack_ports_cvar, 0, 0); } static general_funcs_t plugin_info_general_funcs = { diff --git a/libs/audio/targets/snd_oss.c b/libs/audio/targets/snd_oss.c index 59e34cf93..e938e3965 100644 --- a/libs/audio/targets/snd_oss.c +++ b/libs/audio/targets/snd_oss.c @@ -81,11 +81,51 @@ static const char *snd_dev = "/dev/dsp"; static int tryrates[] = { 44100, 48000, 11025, 22050, 22051, 44100, 8000 }; -static cvar_t *snd_stereo; -static cvar_t *snd_rate; -static cvar_t *snd_device; -static cvar_t *snd_bits; -static cvar_t *snd_oss_mmaped; +static int snd_stereo; +static cvar_t snd_stereo_cvar = { + .name = "snd_stereo", + .description = + "sound stereo output", + .default_value = "1", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_stereo }, +}; +static int snd_rate; +static cvar_t snd_rate_cvar = { + .name = "snd_rate", + .description = + "sound playback rate. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_rate }, +}; +static char *snd_device; +static cvar_t snd_device_cvar = { + .name = "snd_device", + .description = + "sound device. \"\" is system default", + .default_value = "", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &snd_device }, +}; +static int snd_bits; +static cvar_t snd_bits_cvar = { + .name = "snd_bits", + .description = + "sound sample depth. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_bits }, +}; +static int snd_oss_mmaped; +static cvar_t snd_oss_mmaped_cvar = { + .name = "snd_oss_mmaped", + .description = + "mmaped io", + .default_value = "1", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_oss_mmaped }, +}; static plugin_t plugin_info; static plugin_data_t plugin_info_data; @@ -99,16 +139,11 @@ static snd_output_funcs_t plugin_info_snd_output_funcs; static void SNDDMA_Init_Cvars (void) { - snd_stereo = Cvar_Get ("snd_stereo", "1", CVAR_ROM, NULL, - "sound stereo output"); - snd_rate = Cvar_Get ("snd_rate", "0", CVAR_ROM, NULL, - "sound playback rate. 0 is system default"); - snd_device = Cvar_Get ("snd_device", "", CVAR_ROM, NULL, - "sound device. \"\" is system default"); - snd_bits = Cvar_Get ("snd_bits", "0", CVAR_ROM, NULL, - "sound sample depth. 0 is system default"); - snd_oss_mmaped = Cvar_Get ("snd_oss_mmaped", "1", CVAR_ROM, NULL, - "mmaped io"); + Cvar_Register (&snd_stereo_cvar, 0, 0); + Cvar_Register (&snd_rate_cvar, 0, 0); + Cvar_Register (&snd_device_cvar, 0, 0); + Cvar_Register (&snd_bits_cvar, 0, 0); + Cvar_Register (&snd_oss_mmaped_cvar, 0, 0); } static int @@ -122,11 +157,11 @@ try_open (snd_t *snd, int rw) struct audio_buf_info info; snd_inited = 0; - mmaped_io = snd_oss_mmaped->int_val; + mmaped_io = snd_oss_mmaped; // open snd_dev, confirm capability to mmap, and get size of dma buffer - if (snd_device->string[0]) - snd_dev = snd_device->string; + if (snd_device[0]) + snd_dev = snd_device; if (rw) { omode = O_RDWR; @@ -168,7 +203,7 @@ try_open (snd_t *snd, int rw) } // set sample bits & speed - snd->samplebits = snd_bits->int_val; + snd->samplebits = snd_bits; if (snd->samplebits != 16 && snd->samplebits != 8) { ioctl (audio_fd, SNDCTL_DSP_GETFMTS, &fmt); @@ -216,8 +251,8 @@ try_open (snd_t *snd, int rw) return 0; } - if (snd_rate->int_val) { - snd->speed = snd_rate->int_val; + if (snd_rate) { + snd->speed = snd_rate; } else { for (i = 0; i < ((int) sizeof (tryrates) / 4); i++) if (!ioctl (audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) @@ -225,7 +260,7 @@ try_open (snd_t *snd, int rw) snd->speed = tryrates[i]; } - if (!snd_stereo->int_val) { + if (!snd_stereo) { snd->channels = 1; } else { snd->channels = 2; diff --git a/libs/audio/targets/snd_sdl.c b/libs/audio/targets/snd_sdl.c index c9ab69060..f77f17a61 100644 --- a/libs/audio/targets/snd_sdl.c +++ b/libs/audio/targets/snd_sdl.c @@ -55,9 +55,33 @@ static unsigned shm_rpos; static unsigned wpos; -static cvar_t *snd_bits; -static cvar_t *snd_rate; -static cvar_t *snd_stereo; +static int snd_bits; +static cvar_t snd_bits_cvar = { + .name = "snd_bits", + .description = + "sound sample depth. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_bits }, +}; +static int snd_rate; +static cvar_t snd_rate_cvar = { + .name = "snd_rate", + .description = + "sound playback rate. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_rate }, +}; +static int snd_stereo; +static cvar_t snd_stereo_cvar = { + .name = "snd_stereo", + .description = + "sound stereo output", + .default_value = "1", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_stereo }, +}; static plugin_t plugin_info; static plugin_data_t plugin_info_data; @@ -86,12 +110,9 @@ paint_audio (void *unused, Uint8 * stream, int len) static void SNDDMA_Init_Cvars (void) { - snd_stereo = Cvar_Get ("snd_stereo", "1", CVAR_ROM, NULL, - "sound stereo output"); - snd_rate = Cvar_Get ("snd_rate", "0", CVAR_ROM, NULL, - "sound playback rate. 0 is system default"); - snd_bits = Cvar_Get ("snd_bits", "0", CVAR_ROM, NULL, - "sound sample depth. 0 is system default"); + Cvar_Register (&snd_stereo_cvar, 0, 0); + Cvar_Register (&snd_rate_cvar, 0, 0); + Cvar_Register (&snd_bits_cvar, 0, 0); } static int @@ -109,9 +130,9 @@ SNDDMA_Init (snd_t *snd) /* Set up the desired format */ desired.freq = 22050; - if (snd_rate->int_val) - desired.freq = snd_rate->int_val; - switch (snd_bits->int_val) { + if (snd_rate) + desired.freq = snd_rate; + switch (snd_bits) { case 8: desired.format = AUDIO_U8; break; @@ -124,10 +145,10 @@ SNDDMA_Init (snd_t *snd) break; default: Sys_Printf ("Unknown number of audio bits: %d\n", - snd_bits->int_val); + snd_bits); return 0; } - desired.channels = snd_stereo->int_val ? 2 : 1; + desired.channels = snd_stereo ? 2 : 1; desired.samples = 1024; desired.callback = paint_audio; diff --git a/libs/audio/targets/snd_win.c b/libs/audio/targets/snd_win.c index 361bb5afc..42b23a820 100644 --- a/libs/audio/targets/snd_win.c +++ b/libs/audio/targets/snd_win.c @@ -70,20 +70,41 @@ static DWORD gSndBufSize; static qboolean SNDDMA_InitWav (snd_t *snd); -static cvar_t *snd_stereo; -static cvar_t *snd_rate; -static cvar_t *snd_bits; +static int snd_stereo; +static cvar_t snd_stereo_cvar = { + .name = "snd_stereo", + .description = + "sound stereo output", + .default_value = "1", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_stereo }, +}; +static int snd_rate; +static cvar_t snd_rate_cvar = { + .name = "snd_rate", + .description = + "sound playback rate. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_rate }, +}; +static int snd_bits; +static cvar_t snd_bits_cvar = { + .name = "snd_bits", + .description = + "sound sample depth. 0 is system default", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &snd_bits }, +}; static void SNDDMA_Init_Cvars (void) { - snd_stereo = Cvar_Get ("snd_stereo", "1", CVAR_ROM, NULL, - "sound stereo output"); - snd_rate = Cvar_Get ("snd_rate", "11025", CVAR_ROM, NULL, - "sound playback rate. 0 is system default"); - snd_bits = Cvar_Get ("snd_bits", "16", CVAR_ROM, NULL, - "sound sample depth. 0 is system default"); + Cvar_Register (&snd_stereo_cvar, 0, 0); + Cvar_Register (&snd_rate_cvar, 0, 0); + Cvar_Register (&snd_bits_cvar, 0, 0); } static void @@ -150,14 +171,14 @@ SNDDMA_InitWav (snd_t *snd) snd_sent = 0; snd_completed = 0; - if (!snd_stereo->int_val) { + if (!snd_stereo) { snd->channels = 1; } else { snd->channels = 2; } - snd->samplebits = snd_bits->int_val; - snd->speed = snd_rate->int_val; + snd->samplebits = snd_bits; + snd->speed = snd_rate; memset (&format, 0, sizeof (format)); format.wFormatTag = WAVE_FORMAT_PCM; diff --git a/libs/audio/test/testsound.c b/libs/audio/test/testsound.c index d5fe91347..f917a4440 100644 --- a/libs/audio/test/testsound.c +++ b/libs/audio/test/testsound.c @@ -66,7 +66,7 @@ init (void) Sys_Init (); COM_ParseConfig (testsound_cbuf); - Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); + cmd_warncmd = 1; memhunk_t *hunk = Memory_Init (Sys_Alloc (MEMSIZE), MEMSIZE); diff --git a/libs/client/cl_chase.c b/libs/client/cl_chase.c index 483e1605f..7712875ba 100644 --- a/libs/client/cl_chase.c +++ b/libs/client/cl_chase.c @@ -50,19 +50,51 @@ #include "client/view.h" -cvar_t *chase_back; -cvar_t *chase_up; -cvar_t *chase_right; -cvar_t *chase_active; +float chase_back; +static cvar_t chase_back_cvar = { + .name = "chase_back", + .description = + "None", + .default_value = "100", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &chase_back }, +}; +float chase_up; +static cvar_t chase_up_cvar = { + .name = "chase_up", + .description = + "None", + .default_value = "16", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &chase_up }, +}; +float chase_right; +static cvar_t chase_right_cvar = { + .name = "chase_right", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &chase_right }, +}; +int chase_active; +static cvar_t chase_active_cvar = { + .name = "chase_active", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &chase_active }, +}; void Chase_Init_Cvars (void) { - chase_back = Cvar_Get ("chase_back", "100", CVAR_NONE, NULL, "None"); - chase_up = Cvar_Get ("chase_up", "16", CVAR_NONE, NULL, "None"); - chase_right = Cvar_Get ("chase_right", "0", CVAR_NONE, NULL, "None"); - chase_active = Cvar_Get ("chase_active", "0", CVAR_NONE, NULL, "None"); + Cvar_Register (&chase_back_cvar, 0, 0); + Cvar_Register (&chase_up_cvar, 0, 0); + Cvar_Register (&chase_right_cvar, 0, 0); + Cvar_Register (&chase_active_cvar, 0, 0); } void @@ -104,8 +136,8 @@ limit_distance (chasestate_t *cs) vec4f_t dir = cs->camera_origin - cs->player_origin; vec4f_t forward = normalf (dir); - if (magnitudef (dir)[0] > chase_back->value) { - cs->camera_origin = cs->player_origin + forward * chase_back->value; + if (magnitudef (dir)[0] > chase_back) { + cs->camera_origin = cs->player_origin + forward * chase_back; } } @@ -132,26 +164,26 @@ cam_controls (chasestate_t *cs, viewstate_t *vs) vec4f_t dir = { }; if (in_strafe.state & 1) { - move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_right); - move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_left); + move[SIDE] += cl_sidespeed * IN_ButtonState (&in_right); + move[SIDE] -= cl_sidespeed * IN_ButtonState (&in_left); } - move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_moveright); - move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); + move[SIDE] += cl_sidespeed * IN_ButtonState (&in_moveright); + move[SIDE] -= cl_sidespeed * IN_ButtonState (&in_moveleft); if (!(in_klook.state & 1)) { - move[FORWARD] += cl_forwardspeed->value + move[FORWARD] += cl_forwardspeed * IN_ButtonState (&in_forward); - move[FORWARD] -= cl_backspeed->value * IN_ButtonState (&in_back); + move[FORWARD] -= cl_backspeed * IN_ButtonState (&in_back); } if (in_speed.state & 1) { - move *= cl_movespeedkey->value; + move *= cl_movespeedkey; } // mouse and joystick controllers add to movement VectorSet (0, vs->player_angles[1] - cs->camera_angles[1], 0, dir); AngleVectors ((vec_t*)&dir, (vec_t*)&forward, (vec_t*)&right, (vec_t*)&up); //FIXME - forward *= IN_UpdateAxis (&in_cam_forward) * m_forward->value; - right *= IN_UpdateAxis (&in_cam_side) * m_side->value; + forward *= IN_UpdateAxis (&in_cam_forward) * m_forward; + right *= IN_UpdateAxis (&in_cam_side) * m_side; dir = forward + right; move[FORWARD] += dir[0]; move[SIDE] -= dir[1]; @@ -191,9 +223,9 @@ chase_mode_1 (chasestate_t *cs) // calc exact destination cs->camera_origin = vs->player_origin - - forward * chase_back->value - right * chase_right->value; + - forward * chase_back - right * chase_right; // chase_up is world up - cs->camera_origin[2] += chase_up->value; + cs->camera_origin[2] += chase_up; // check for walls between player and camera stop = TraceLine (cs, vs->player_origin, cs->camera_origin); @@ -219,13 +251,13 @@ chase_mode_2 (chasestate_t *cs) // move camera, it's not enough to just change the angles because // the angles are automatically changed to look toward the player AngleVectors (cs->camera_angles, (vec_t*)&forward, (vec_t*)&right, (vec_t*)&up);//FIXME - cs->camera_origin = cs->player_origin - chase_back->value * forward; + cs->camera_origin = cs->player_origin - chase_back * forward; cs->player_origin = vs->player_origin; // don't let camera get too low - if (cs->camera_origin[2] < cs->player_origin[2] + chase_up->value) { - cs->camera_origin[2] = cs->player_origin[2] + chase_up->value; + if (cs->camera_origin[2] < cs->player_origin[2] + chase_up) { + cs->camera_origin[2] = cs->player_origin[2] + chase_up; } limit_distance (cs); @@ -267,7 +299,7 @@ chase_mode_3 (chasestate_t *cs) cs->player_origin = vs->player_origin; AngleVectors (cs->camera_angles, (vec_t*)&forward, (vec_t*)&right, (vec_t*)&up);//FIXME - cs->camera_origin = cs->player_origin - chase_back->value * forward; + cs->camera_origin = cs->player_origin - chase_back * forward; limit_distance (cs); check_for_walls (cs, forward); set_camera (cs, vs); @@ -277,7 +309,7 @@ chase_mode_3 (chasestate_t *cs) void Chase_Update (chasestate_t *cs) { - switch (chase_active->int_val) { + switch (chase_active) { case 1: chase_mode_1 (cs); return; diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index e5fc1d858..083d955ed 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -129,7 +129,7 @@ CL_ModelEffects (entity_t *ent, int num, int glow_color, double time) VectorCopy (ent_origin, dl->origin); dl->radius = 200.0; dl->die = time + 0.1; - //FIXME VectorCopy (r_firecolor->vec, dl->color); + //FIXME VectorCopy (r_firecolor, dl->color); VectorSet (0.9, 0.7, 0.0, dl->color); dl->color[3] = 0.7; } diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index ec2201cd2..6feefdf50 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -214,20 +214,124 @@ static in_button_t *cl_in_buttons[] = { 0 }; -cvar_t *cl_anglespeedkey; -cvar_t *cl_backspeed; -cvar_t *cl_forwardspeed; -cvar_t *cl_movespeedkey; -cvar_t *cl_pitchspeed; -cvar_t *cl_sidespeed; -cvar_t *cl_upspeed; -cvar_t *cl_yawspeed; +float cl_anglespeedkey; +static cvar_t cl_anglespeedkey_cvar = { + .name = "cl_anglespeedkey", + .description = + "turn `run' speed multiplier", + .default_value = "1.5", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_anglespeedkey }, +}; +float cl_backspeed; +static cvar_t cl_backspeed_cvar = { + .name = "cl_backspeed", + .description = + "backward speed", + .default_value = "200", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_backspeed }, +}; +float cl_forwardspeed; +static cvar_t cl_forwardspeed_cvar = { + .name = "cl_forwardspeed", + .description = + "forward speed", + .default_value = "200", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_forwardspeed }, +}; +float cl_movespeedkey; +static cvar_t cl_movespeedkey_cvar = { + .name = "cl_movespeedkey", + .description = + "move `run' speed multiplier", + .default_value = "2.0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_movespeedkey }, +}; +float cl_pitchspeed; +static cvar_t cl_pitchspeed_cvar = { + .name = "cl_pitchspeed", + .description = + "look up/down speed", + .default_value = "150", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_pitchspeed }, +}; +float cl_sidespeed; +static cvar_t cl_sidespeed_cvar = { + .name = "cl_sidespeed", + .description = + "strafe speed", + .default_value = "350", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_sidespeed }, +}; +float cl_upspeed; +static cvar_t cl_upspeed_cvar = { + .name = "cl_upspeed", + .description = + "swim/fly up/down speed", + .default_value = "200", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_upspeed }, +}; +float cl_yawspeed; +static cvar_t cl_yawspeed_cvar = { + .name = "cl_yawspeed", + .description = + "turning speed", + .default_value = "140", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_yawspeed }, +}; -cvar_t *lookspring; -cvar_t *m_pitch; -cvar_t *m_yaw; -cvar_t *m_forward; -cvar_t *m_side; +int lookspring; +static cvar_t lookspring_cvar = { + .name = "lookspring", + .description = + "Snap view to center when moving and no mlook/klook", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &lookspring }, +}; +float m_pitch; +static cvar_t m_pitch_cvar = { + .name = "m_pitch", + .description = + "mouse pitch (up/down) multipier", + .default_value = "0.022", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &m_pitch }, +}; +float m_yaw; +static cvar_t m_yaw_cvar = { + .name = "m_yaw", + .description = + "mouse yaw (left/right) multipiler", + .default_value = "0.022", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &m_yaw }, +}; +float m_forward; +static cvar_t m_forward_cvar = { + .name = "m_forward", + .description = + "mouse forward/back speed", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &m_forward }, +}; +float m_side; +static cvar_t m_side_cvar = { + .name = "m_side", + .description = + "mouse strafe speed", + .default_value = "0.8", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &m_side }, +}; static void CL_AdjustAngles (float frametime, movestate_t *ms, viewstate_t *vs) @@ -236,12 +340,12 @@ CL_AdjustAngles (float frametime, movestate_t *ms, viewstate_t *vs) float pitchspeed, yawspeed; vec4f_t delta = {}; - pitchspeed = cl_pitchspeed->value; - yawspeed = cl_yawspeed->value; + pitchspeed = cl_pitchspeed; + yawspeed = cl_yawspeed; if (in_speed.state & inb_down) { - pitchspeed *= cl_anglespeedkey->value; - yawspeed *= cl_anglespeedkey->value; + pitchspeed *= cl_anglespeedkey; + yawspeed *= cl_anglespeedkey; } pitchspeed *= frametime; @@ -263,9 +367,9 @@ CL_AdjustAngles (float frametime, movestate_t *ms, viewstate_t *vs) delta[PITCH] -= pitchspeed * up; delta[PITCH] += pitchspeed * down; - delta[PITCH] -= IN_UpdateAxis (&in_move_pitch) * m_pitch->value; - delta[YAW] -= IN_UpdateAxis (&in_move_yaw) * m_yaw->value; - delta[ROLL] -= IN_UpdateAxis (&in_move_roll) * m_pitch->value; + delta[PITCH] -= IN_UpdateAxis (&in_move_pitch) * m_pitch; + delta[YAW] -= IN_UpdateAxis (&in_move_yaw) * m_yaw; + delta[ROLL] -= IN_UpdateAxis (&in_move_roll) * m_pitch; ms->angles += delta; @@ -359,7 +463,7 @@ CL_Legacy_Init (void) void CL_Input_BuildMove (float frametime, movestate_t *state, viewstate_t *vs) { - if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring->int_val) { + if (IN_ButtonReleased (&in_mlook) && !freelook && lookspring) { V_StartPitchDrift (vs); } @@ -368,35 +472,35 @@ CL_Input_BuildMove (float frametime, movestate_t *state, viewstate_t *vs) vec4f_t move = {}; if (in_strafe.state & inb_down) { - move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_right); - move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_left); + move[SIDE] += cl_sidespeed * IN_ButtonState (&in_right); + move[SIDE] -= cl_sidespeed * IN_ButtonState (&in_left); } - move[SIDE] += cl_sidespeed->value * IN_ButtonState (&in_moveright); - move[SIDE] -= cl_sidespeed->value * IN_ButtonState (&in_moveleft); + move[SIDE] += cl_sidespeed * IN_ButtonState (&in_moveright); + move[SIDE] -= cl_sidespeed * IN_ButtonState (&in_moveleft); - move[UP] += cl_upspeed->value * IN_ButtonState (&in_up); - move[UP] -= cl_upspeed->value * IN_ButtonState (&in_down); + move[UP] += cl_upspeed * IN_ButtonState (&in_up); + move[UP] -= cl_upspeed * IN_ButtonState (&in_down); if (!(in_klook.state & inb_down)) { - move[FORWARD] += cl_forwardspeed->value * IN_ButtonState (&in_forward); - move[FORWARD] -= cl_backspeed->value * IN_ButtonState (&in_back); + move[FORWARD] += cl_forwardspeed * IN_ButtonState (&in_forward); + move[FORWARD] -= cl_backspeed * IN_ButtonState (&in_back); } // adjust for speed key if (in_speed.state & inb_down) { - move *= cl_movespeedkey->value; + move *= cl_movespeedkey; } - move[FORWARD] -= IN_UpdateAxis (&in_move_forward) * m_forward->value; - move[SIDE] += IN_UpdateAxis (&in_move_side) * m_side->value; + move[FORWARD] -= IN_UpdateAxis (&in_move_forward) * m_forward; + move[SIDE] += IN_UpdateAxis (&in_move_side) * m_side; move[UP] -= IN_UpdateAxis (&in_move_up); if (freelook) V_StopPitchDrift (vs); if (vs->chase - && (chase_active->int_val == 2 || chase_active->int_val == 3)) { + && (chase_active == 2 || chase_active == 3)) { /* adjust for chase camera angles * makes the player move relative to the chase camera frame rather * than the player's frame @@ -481,32 +585,19 @@ CL_Input_Init (cbuf_t *cbuf) void CL_Input_Init_Cvars (void) { - lookspring = Cvar_Get ("lookspring", "0", CVAR_ARCHIVE, NULL, "Snap view " - "to center when moving and no mlook/klook"); - m_pitch = Cvar_Get ("m_pitch", "0.022", CVAR_ARCHIVE, NULL, - "mouse pitch (up/down) multipier"); - m_yaw = Cvar_Get ("m_yaw", "0.022", CVAR_ARCHIVE, NULL, - "mouse yaw (left/right) multipiler"); - m_forward = Cvar_Get ("m_forward", "1", CVAR_ARCHIVE, NULL, - "mouse forward/back speed"); - m_side = Cvar_Get ("m_side", "0.8", CVAR_ARCHIVE, NULL, - "mouse strafe speed"); - cl_anglespeedkey = Cvar_Get ("cl_anglespeedkey", "1.5", CVAR_NONE, NULL, - "turn `run' speed multiplier"); - cl_backspeed = Cvar_Get ("cl_backspeed", "200", CVAR_ARCHIVE, NULL, - "backward speed"); - cl_forwardspeed = Cvar_Get ("cl_forwardspeed", "200", CVAR_ARCHIVE, NULL, - "forward speed"); - cl_movespeedkey = Cvar_Get ("cl_movespeedkey", "2.0", CVAR_NONE, NULL, - "move `run' speed multiplier"); - cl_pitchspeed = Cvar_Get ("cl_pitchspeed", "150", CVAR_NONE, NULL, - "look up/down speed"); - cl_sidespeed = Cvar_Get ("cl_sidespeed", "350", CVAR_NONE, NULL, - "strafe speed"); - cl_upspeed = Cvar_Get ("cl_upspeed", "200", CVAR_NONE, NULL, - "swim/fly up/down speed"); - cl_yawspeed = Cvar_Get ("cl_yawspeed", "140", CVAR_NONE, NULL, - "turning speed"); + Cvar_Register (&lookspring_cvar, 0, 0); + Cvar_Register (&m_pitch_cvar, 0, 0); + Cvar_Register (&m_yaw_cvar, 0, 0); + Cvar_Register (&m_forward_cvar, 0, 0); + Cvar_Register (&m_side_cvar, 0, 0); + Cvar_Register (&cl_anglespeedkey_cvar, 0, 0); + Cvar_Register (&cl_backspeed_cvar, 0, 0); + Cvar_Register (&cl_forwardspeed_cvar, 0, 0); + Cvar_Register (&cl_movespeedkey_cvar, 0, 0); + Cvar_Register (&cl_pitchspeed_cvar, 0, 0); + Cvar_Register (&cl_sidespeed_cvar, 0, 0); + Cvar_Register (&cl_upspeed_cvar, 0, 0); + Cvar_Register (&cl_yawspeed_cvar, 0, 0); } void diff --git a/libs/client/cl_particles.c b/libs/client/cl_particles.c index 618067612..249a14aaf 100644 --- a/libs/client/cl_particles.c +++ b/libs/client/cl_particles.c @@ -60,8 +60,24 @@ cl_particle_funcs_t *clp_funcs; static mtstate_t mt; // private PRNG state static psystem_t *cl_psystem; -static cvar_t *easter_eggs; -static cvar_t *particles_style; +static int easter_eggs; +static cvar_t easter_eggs_cvar = { + .name = "easter_eggs", + .description = + "Enables easter eggs.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &easter_eggs }, +}; +static int particles_style; +static cvar_t particles_style_cvar = { + .name = "particles_style", + .description = + "Sets particle style. 0 for Id, 1 for QF.", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &particles_style }, +}; static int ramp[] = { /*ramp1*/ 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61, @@ -1238,37 +1254,34 @@ static cl_particle_funcs_t particles_ID_egg = { }; static void -easter_eggs_f (cvar_t *var) +set_particle_funcs (void) { if (easter_eggs) { - if (easter_eggs->int_val) { - if (particles_style->int_val) { - clp_funcs = &particles_QF_egg; - } else { - clp_funcs = &particles_ID_egg; - } - } else if (particles_style) { - if (particles_style->int_val) { - clp_funcs = &particles_QF; - } else { - clp_funcs = &particles_ID; - } + if (particles_style) { + clp_funcs = &particles_QF_egg; + } else { + clp_funcs = &particles_ID_egg; + } + } else { + if (particles_style) { + clp_funcs = &particles_QF; + } else { + clp_funcs = &particles_ID; } } } static void -particles_style_f (cvar_t *var) +easter_eggs_f (void *data, const cvar_t *cvar) { - easter_eggs_f (easter_eggs); - cl_psystem->points_only = !var->int_val; + set_particle_funcs (); } static void -CL_ParticleFunctionInit (void) +particles_style_f (void *data, const cvar_t *cvar) { - particles_style_f (particles_style); - easter_eggs_f (easter_eggs); + set_particle_funcs (); + cl_psystem->points_only = !particles_style; } void @@ -1276,12 +1289,9 @@ CL_Particles_Init (void) { mtwist_seed (&mt, 0xdeadbeef); cl_psystem = r_funcs->ParticleSystem (); - easter_eggs = Cvar_Get ("easter_eggs", "0", CVAR_NONE, easter_eggs_f, - "Enables easter eggs."); - particles_style = Cvar_Get ("particles_style", "1", CVAR_ARCHIVE, - particles_style_f, - "Sets particle style. 0 for Id, 1 for QF."); - CL_ParticleFunctionInit (); + Cvar_Register (&easter_eggs_cvar, easter_eggs_f, 0); + Cvar_Register (&particles_style_cvar, particles_style_f, 0); + set_particle_funcs (); } void diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index fa693107b..b163efa65 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -54,37 +54,230 @@ especially when crossing a water boudnary. */ -cvar_t *scr_ofsx; -cvar_t *scr_ofsy; -cvar_t *scr_ofsz; +float scr_ofsx; +static cvar_t scr_ofsx_cvar = { + .name = "scr_ofsx", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &scr_ofsx }, +}; +float scr_ofsy; +static cvar_t scr_ofsy_cvar = { + .name = "scr_ofsy", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &scr_ofsy }, +}; +float scr_ofsz; +static cvar_t scr_ofsz_cvar = { + .name = "scr_ofsz", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &scr_ofsz }, +}; -cvar_t *cl_rollspeed; -cvar_t *cl_rollangle; +float cl_rollspeed; +static cvar_t cl_rollspeed_cvar = { + .name = "cl_rollspeed", + .description = + "How quickly you straighten out after strafing", + .default_value = "200", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_rollspeed }, +}; +float cl_rollangle; +static cvar_t cl_rollangle_cvar = { + .name = "cl_rollangle", + .description = + "How much your screen tilts when strafing", + .default_value = "2.0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_rollangle }, +}; -cvar_t *cl_bob; -cvar_t *cl_bobcycle; -cvar_t *cl_bobup; +float cl_bob; +static cvar_t cl_bob_cvar = { + .name = "cl_bob", + .description = + "How much your weapon moves up and down when walking", + .default_value = "0.02", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_bob }, +}; +float cl_bobcycle; +static cvar_t cl_bobcycle_cvar = { + .name = "cl_bobcycle", + .description = + "How quickly your weapon moves up and down when walking", + .default_value = "0.6", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_bobcycle }, +}; +float cl_bobup; +static cvar_t cl_bobup_cvar = { + .name = "cl_bobup", + .description = + "How long your weapon stays up before cycling when walking", + .default_value = "0.5", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_bobup }, +}; -cvar_t *v_centermove; -cvar_t *v_centerspeed; +float v_centermove; +static cvar_t v_centermove_cvar = { + .name = "v_centermove", + .description = + "How far the player must move forward before the view re-centers", + .default_value = "0.15", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_centermove }, +}; +float v_centerspeed; +static cvar_t v_centerspeed_cvar = { + .name = "v_centerspeed", + .description = + "How quickly you return to a center view after a lookup or lookdown", + .default_value = "500", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_centerspeed }, +}; -cvar_t *v_kicktime; -cvar_t *v_kickroll; -cvar_t *v_kickpitch; +float v_kicktime; +static cvar_t v_kicktime_cvar = { + .name = "v_kicktime", + .description = + "How long the kick from an attack lasts", + .default_value = "0.5", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_kicktime }, +}; +float v_kickroll; +static cvar_t v_kickroll_cvar = { + .name = "v_kickroll", + .description = + "How much you lean when hit", + .default_value = "0.6", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_kickroll }, +}; +float v_kickpitch; +static cvar_t v_kickpitch_cvar = { + .name = "v_kickpitch", + .description = + "How much you look up when hit", + .default_value = "0.6", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_kickpitch }, +}; -cvar_t *cl_cshift_bonus; -cvar_t *cl_cshift_contents; -cvar_t *cl_cshift_damage; -cvar_t *cl_cshift_powerup; +int cl_cshift_bonus; +static cvar_t cl_cshift_bonus_cvar = { + .name = "cl_cshift_bonus", + .description = + "Show bonus flash on item pickup", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_cshift_bonus }, +}; +int cl_cshift_contents; +static cvar_t cl_cshift_contents_cvar = { + .name = "cl_cshift_content", + .description = + "Shift view colors for contents (water, slime, etc)", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_cshift_contents }, +}; +int cl_cshift_damage; +static cvar_t cl_cshift_damage_cvar = { + .name = "cl_cshift_damage", + .description = + "Shift view colors on damage", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_cshift_damage }, +}; +int cl_cshift_powerup; +static cvar_t cl_cshift_powerup_cvar = { + .name = "cl_cshift_powerup", + .description = + "Shift view colors for powerups", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_cshift_powerup }, +}; -cvar_t *v_iyaw_cycle; -cvar_t *v_iroll_cycle; -cvar_t *v_ipitch_cycle; -cvar_t *v_iyaw_level; -cvar_t *v_iroll_level; -cvar_t *v_ipitch_level; +float v_iyaw_cycle; +static cvar_t v_iyaw_cycle_cvar = { + .name = "v_iyaw_cycle", + .description = + "How far you tilt right and left when v_idlescale is enabled", + .default_value = "2", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_iyaw_cycle }, +}; +float v_iroll_cycle; +static cvar_t v_iroll_cycle_cvar = { + .name = "v_iroll_cycle", + .description = + "How quickly you tilt right and left when v_idlescale is enabled", + .default_value = "0.5", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_iroll_cycle }, +}; +float v_ipitch_cycle; +static cvar_t v_ipitch_cycle_cvar = { + .name = "v_ipitch_cycle", + .description = + "How quickly you lean forwards and backwards when v_idlescale is " + "enabled", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_ipitch_cycle }, +}; +float v_iyaw_level; +static cvar_t v_iyaw_level_cvar = { + .name = "v_iyaw_level", + .description = + "How far you tilt right and left when v_idlescale is enabled", + .default_value = "0.3", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_iyaw_level }, +}; +float v_iroll_level; +static cvar_t v_iroll_level_cvar = { + .name = "v_iroll_level", + .description = + "How far you tilt right and left when v_idlescale is enabled", + .default_value = "0.1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_iroll_level }, +}; +float v_ipitch_level; +static cvar_t v_ipitch_level_cvar = { + .name = "v_ipitch_level", + .description = + "How far you lean forwards and backwards when v_idlescale is enabled", + .default_value = "0.3", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_ipitch_level }, +}; -cvar_t *v_idlescale; +float v_idlescale; +static cvar_t v_idlescale_cvar = { + .name = "v_idlescale", + .description = + "Toggles whether the view remains idle", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &v_idlescale }, +}; float v_dmg_time, v_dmg_roll, v_dmg_pitch; @@ -137,10 +330,10 @@ V_CalcRoll (const vec3_t angles, vec4f_t velocity) sign = side < 0 ? -1 : 1; side = fabs (side); - value = cl_rollangle->value; + value = cl_rollangle; - if (side < cl_rollspeed->value) - side = side * value / cl_rollspeed->value; + if (side < cl_rollspeed) + side = side * value / cl_rollspeed; else side = value; @@ -162,18 +355,18 @@ V_CalcBob (viewstate_t *vs) return bob; // just use old value bobtime += vs->frametime; - cycle = bobtime - (int) (bobtime / cl_bobcycle->value) * - cl_bobcycle->value; - cycle /= cl_bobcycle->value; - if (cycle < cl_bobup->value) - cycle = cycle / cl_bobup->value; + cycle = bobtime - (int) (bobtime / cl_bobcycle) * + cl_bobcycle; + cycle /= cl_bobcycle; + if (cycle < cl_bobup) + cycle = cycle / cl_bobup; else - cycle = 1 + (cycle - cl_bobup->value) / (1.0 - cl_bobup->value); + cycle = 1 + (cycle - cl_bobup) / (1.0 - cl_bobup); // bob is proportional to velocity in the xy plane // (don't count Z, or jumping messes it up) velocity[2] = 0; - bob = sqrt (dotf (velocity, velocity)[0]) * cl_bob->value; + bob = sqrt (dotf (velocity, velocity)[0]) * cl_bob; bob = bob * 0.3 + bob * 0.7 * sin (cycle * M_PI); if (bob > 4) bob = 4; @@ -190,7 +383,7 @@ V_StartPitchDrift (viewstate_t *vs) } if (vs->nodrift || !vs->pitchvel) { - vs->pitchvel = v_centerspeed->value; + vs->pitchvel = v_centerspeed; vs->nodrift = false; vs->driftmove = 0; } @@ -236,12 +429,12 @@ V_DriftPitch (viewstate_t *vs) // don't count small mouse motion if (vs->nodrift) { - if (fabs (forwardmove) < cl_forwardspeed->value) + if (fabs (forwardmove) < cl_forwardspeed) vs->driftmove = 0; else vs->driftmove += vs->frametime; - if (vs->driftmove > v_centermove->value) { + if (vs->driftmove > v_centermove) { V_StartPitchDrift (vs); } return; @@ -255,7 +448,7 @@ V_DriftPitch (viewstate_t *vs) } move = vs->frametime * vs->pitchvel; - vs->pitchvel += vs->frametime * v_centerspeed->value; + vs->pitchvel += vs->frametime * v_centerspeed; if (delta > 0) { if (move > delta) { @@ -291,7 +484,7 @@ V_ParseDamage (qmsg_t *net_message, viewstate_t *vs) if (count < 10) count = 10; - if (cl_cshift_damage->int_val + if (cl_cshift_damage || (vs->force_cshifts & INFO_CSHIFT_DAMAGE)) { cshift_t *cshift = &vs->cshifts[CSHIFT_DAMAGE]; int percent = cshift->percent; @@ -309,12 +502,12 @@ V_ParseDamage (qmsg_t *net_message, viewstate_t *vs) AngleVectors (angles, forward, right, up); side = DotProduct (from, right); - v_dmg_roll = count * side * v_kickroll->value; + v_dmg_roll = count * side * v_kickroll; side = DotProduct (from, forward); - v_dmg_pitch = count * side * v_kickpitch->value; + v_dmg_pitch = count * side * v_kickpitch; - v_dmg_time = v_kicktime->value; + v_dmg_time = v_kicktime; } static void @@ -335,7 +528,7 @@ static void V_BonusFlash_f (void *data) { viewstate_t *vs = data; - if (!cl_cshift_bonus->int_val + if (!cl_cshift_bonus && !(vs->force_cshifts & INFO_CSHIFT_BONUS)) return; @@ -352,7 +545,7 @@ V_BonusFlash_f (void *data) void V_SetContentsColor (viewstate_t *vs, int contents) { - if (!cl_cshift_contents->int_val + if (!cl_cshift_contents && !(vs->force_cshifts & INFO_CSHIFT_CONTENTS)) { vs->cshifts[CSHIFT_CONTENTS] = cshift_empty; return; @@ -441,7 +634,7 @@ V_PrepBlend (viewstate_t *vs) { int i, j; - if (cl_cshift_powerup->int_val + if (cl_cshift_powerup || (vs->force_cshifts & INFO_CSHIFT_POWERUP)) V_CalcPowerupCshift (vs); @@ -499,14 +692,14 @@ V_BoundOffsets (viewstate_t *vs) } static vec4f_t -idle_quat (vec4f_t axis, cvar_t *cycle, cvar_t *level, double time) +idle_quat (vec4f_t axis, float cycle, float level, double time) { vec4f_t identity = { 0, 0, 0, 1 }; if (!level || !cycle) { return identity; } - float scale = sin (time * cycle->value); - float ang = scale * level->value * v_idlescale->value; + float scale = sin (time * cycle); + float ang = scale * level * v_idlescale; float c = cos (ang * M_PI / 360); float s = sin (ang * M_PI / 360); return axis * s + identity * c; @@ -553,8 +746,8 @@ V_CalcViewRoll (viewstate_t *vs) ang[ROLL] = V_CalcRoll (angles, velocity); if (v_dmg_time > 0) { - ang[ROLL] += v_dmg_time / v_kicktime->value * v_dmg_roll; - ang[PITCH] += v_dmg_time / v_kicktime->value * v_dmg_pitch; + ang[ROLL] += v_dmg_time / v_kicktime * v_dmg_roll; + ang[PITCH] += v_dmg_time / v_kicktime * v_dmg_pitch; v_dmg_time -= vs->frametime; } @@ -586,10 +779,10 @@ V_CalcIntermissionRefdef (viewstate_t *vs) view->renderer.model = NULL; // always idle in intermission - old = v_idlescale->value; - Cvar_SetValue (v_idlescale, 1); + old = v_idlescale; + v_idlescale = 1; V_AddIdle (vs); - Cvar_SetValue (v_idlescale, old); + v_idlescale = old; } static void @@ -628,9 +821,7 @@ V_CalcRefdef (viewstate_t *vs) // don't allow cheats in multiplayer // FIXME check for dead if (vs->voffs_enabled) { - origin += scr_ofsx->value * forward - + scr_ofsy->value * right - + scr_ofsz->value * up; + origin += scr_ofsx * forward + scr_ofsy * right + scr_ofsz * up; } V_BoundOffsets (vs); @@ -644,15 +835,15 @@ V_CalcRefdef (viewstate_t *vs) // fudge position around to keep amount of weapon visible // roughly equal with different FOV - if (hud_sbar->int_val == 0 && r_data->scr_viewsize->int_val >= 100) { + if (hud_sbar == 0 && *r_data->scr_viewsize >= 100) { ; - } else if (r_data->scr_viewsize->int_val == 110) { + } else if (*r_data->scr_viewsize == 110) { gun_origin += (vec4f_t) { 0, 0, 1, 0}; - } else if (r_data->scr_viewsize->int_val == 100) { + } else if (*r_data->scr_viewsize == 100) { gun_origin += (vec4f_t) { 0, 0, 2, 0}; - } else if (r_data->scr_viewsize->int_val == 90) { + } else if (*r_data->scr_viewsize == 90) { gun_origin += (vec4f_t) { 0, 0, 1, 0}; - } else if (r_data->scr_viewsize->int_val == 80) { + } else if (*r_data->scr_viewsize == 80) { gun_origin += (vec4f_t) { 0, 0, 0.5, 0}; } @@ -741,7 +932,7 @@ V_RenderView (viewstate_t *vs) if (vs->intermission) { // intermission / finale rendering V_CalcIntermissionRefdef (vs); } else { - if (vs->chase && chase_active->int_val) { + if (vs->chase && chase_active) { Chase_Update (vs->chasestate); } else { V_CalcRefdef (vs); @@ -769,61 +960,29 @@ V_Init (viewstate_t *viewstate) void V_Init_Cvars (void) { - v_centermove = Cvar_Get ("v_centermove", "0.15", CVAR_NONE, NULL, - "How far the player must move forward before the " - "view re-centers"); - v_centerspeed = Cvar_Get ("v_centerspeed", "500", CVAR_NONE, NULL, - "How quickly you return to a center view after " - "a lookup or lookdown"); - v_iyaw_cycle = Cvar_Get ("v_iyaw_cycle", "2", CVAR_NONE, NULL, - "How far you tilt right and left when " - "v_idlescale is enabled"); - v_iroll_cycle = Cvar_Get ("v_iroll_cycle", "0.5", CVAR_NONE, NULL, - "How quickly you tilt right and left when " - "v_idlescale is enabled"); - v_ipitch_cycle = Cvar_Get ("v_ipitch_cycle", "1", CVAR_NONE, NULL, - "How quickly you lean forwards and backwards " - "when v_idlescale is enabled"); - v_iyaw_level = Cvar_Get ("v_iyaw_level", "0.3", CVAR_NONE, NULL, - "How far you tilt right and left when " - "v_idlescale is enabled"); - v_iroll_level = Cvar_Get ("v_iroll_level", "0.1", CVAR_NONE, NULL, - "How far you tilt right and left when " - "v_idlescale is enabled"); - v_ipitch_level = Cvar_Get ("v_ipitch_level", "0.3", CVAR_NONE, NULL, - "How far you lean forwards and backwards when " - "v_idlescale is enabled"); - v_idlescale = Cvar_Get ("v_idlescale", "0", CVAR_NONE, NULL, - "Toggles whether the view remains idle"); + Cvar_Register (&v_centermove_cvar, 0, 0); + Cvar_Register (&v_centerspeed_cvar, 0, 0); + Cvar_Register (&v_iyaw_cycle_cvar, 0, 0); + Cvar_Register (&v_iroll_cycle_cvar, 0, 0); + Cvar_Register (&v_ipitch_cycle_cvar, 0, 0); + Cvar_Register (&v_iyaw_level_cvar, 0, 0); + Cvar_Register (&v_iroll_level_cvar, 0, 0); + Cvar_Register (&v_ipitch_level_cvar, 0, 0); + Cvar_Register (&v_idlescale_cvar, 0, 0); - scr_ofsx = Cvar_Get ("scr_ofsx", "0", CVAR_NONE, NULL, "None"); - scr_ofsy = Cvar_Get ("scr_ofsy", "0", CVAR_NONE, NULL, "None"); - scr_ofsz = Cvar_Get ("scr_ofsz", "0", CVAR_NONE, NULL, "None"); - cl_rollspeed = Cvar_Get ("cl_rollspeed", "200", CVAR_NONE, NULL, - "How quickly you straighten out after strafing"); - cl_rollangle = Cvar_Get ("cl_rollangle", "2.0", CVAR_NONE, NULL, - "How much your screen tilts when strafing"); - cl_bob = Cvar_Get ("cl_bob", "0.02", CVAR_NONE, NULL, - "How much your weapon moves up and down when walking"); - cl_bobcycle = Cvar_Get ("cl_bobcycle", "0.6", CVAR_NONE, NULL, - "How quickly your weapon moves up and down when " - "walking"); - cl_bobup = Cvar_Get ("cl_bobup", "0.5", CVAR_NONE, NULL, - "How long your weapon stays up before cycling when " - "walking"); - v_kicktime = Cvar_Get ("v_kicktime", "0.5", CVAR_NONE, NULL, - "How long the kick from an attack lasts"); - v_kickroll = Cvar_Get ("v_kickroll", "0.6", CVAR_NONE, NULL, - "How much you lean when hit"); - v_kickpitch = Cvar_Get ("v_kickpitch", "0.6", CVAR_NONE, NULL, - "How much you look up when hit"); - cl_cshift_bonus = Cvar_Get ("cl_cshift_bonus", "1", CVAR_ARCHIVE, NULL, - "Show bonus flash on item pickup"); - cl_cshift_contents = Cvar_Get ("cl_cshift_content", "1", CVAR_ARCHIVE, - NULL, "Shift view colors for contents " - "(water, slime, etc)"); - cl_cshift_damage = Cvar_Get ("cl_cshift_damage", "1", CVAR_ARCHIVE, NULL, - "Shift view colors on damage"); - cl_cshift_powerup = Cvar_Get ("cl_cshift_powerup", "1", CVAR_ARCHIVE, NULL, - "Shift view colors for powerups"); + Cvar_Register (&scr_ofsx_cvar, 0, 0); + Cvar_Register (&scr_ofsy_cvar, 0, 0); + Cvar_Register (&scr_ofsz_cvar, 0, 0); + Cvar_Register (&cl_rollspeed_cvar, 0, 0); + Cvar_Register (&cl_rollangle_cvar, 0, 0); + Cvar_Register (&cl_bob_cvar, 0, 0); + Cvar_Register (&cl_bobcycle_cvar, 0, 0); + Cvar_Register (&cl_bobup_cvar, 0, 0); + Cvar_Register (&v_kicktime_cvar, 0, 0); + Cvar_Register (&v_kickroll_cvar, 0, 0); + Cvar_Register (&v_kickpitch_cvar, 0, 0); + Cvar_Register (&cl_cshift_bonus_cvar, 0, 0); + Cvar_Register (&cl_cshift_contents_cvar, 0, 0); + Cvar_Register (&cl_cshift_damage_cvar, 0, 0); + Cvar_Register (&cl_cshift_powerup_cvar, 0, 0); } diff --git a/libs/client/hud.c b/libs/client/hud.c index 2d8f880ed..5011b3a6e 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -29,8 +29,162 @@ # include "config.h" #endif -#include "QF/cvar.h" +#include -cvar_t *hud_sbar; -cvar_t *hud_scoreboard_gravity; -cvar_t *hud_swap; +#include "QF/cvar.h" +#include "QF/screen.h" +#include "QF/render.h" +#include "QF/plugin/vid_render.h" +#include "QF/ui/view.h" + +#include "compat.h" + +#include "client/hud.h" + +int hud_sb_lines; + +int hud_sbar; +static cvar_t hud_sbar_cvar = { + .name = "hud_sbar", + .description = + "status bar mode: 0 = hud, 1 = oldstyle", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_sbar }, +}; +char *hud_scoreboard_gravity; +static cvar_t hud_scoreboard_gravity_cvar = { + .name = "hud_scoreboard_gravity", + .description = + "control placement of scoreboard overlay: center, northwest, north, " + "northeast, west, east, southwest, south, southeast", + .default_value = "center", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &hud_scoreboard_gravity }, +}; +int hud_swap; +static cvar_t hud_swap_cvar = { + .name = "hud_swap", + .description = + "new HUD on left side?", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_swap }, +}; + +view_t *sbar_view; +view_t *sbar_inventory_view; +view_t *sbar_frags_view; + +view_t *hud_view; +view_t *hud_inventory_view; +view_t *hud_armament_view; +view_t *hud_frags_view; + +view_t *hud_overlay_view; +view_t *hud_stuff_view; +view_t *hud_main_view; + +static void +hud_sbar_f (void *data, const cvar_t *cvar) +{ + HUD_Calc_sb_lines (*r_data->scr_viewsize); + SCR_SetBottomMargin (hud_sbar ? hud_sb_lines : 0); + if (hud_sbar) { + view_remove (hud_main_view, hud_main_view->children[0]); + view_insert (hud_main_view, sbar_view, 0); + } else { + view_remove (hud_main_view, hud_main_view->children[0]); + view_insert (hud_main_view, hud_view, 0); + } +} + +static void +hud_swap_f (void *data, const cvar_t *cvar) +{ + if (hud_swap) { + //FIXME why is this needed for nq but not for qw? + hud_armament_view->children[0]->gravity = grav_northwest; + hud_armament_view->children[1]->gravity = grav_southeast; + view_setgravity (hud_armament_view, grav_southwest); + view_setgravity (hud_stuff_view, grav_southeast); + } else { + //FIXME why is this needed for nq but not for qw? + hud_armament_view->children[0]->gravity = grav_northeast; + hud_armament_view->children[1]->gravity = grav_southwest; + view_setgravity (hud_armament_view, grav_southeast); + view_setgravity (hud_stuff_view, grav_southwest); + } + view_move (hud_armament_view, hud_armament_view->xpos, + hud_armament_view->ypos); + view_move (hud_stuff_view, hud_stuff_view->xpos, hud_stuff_view->ypos); +} + +static void +hud_scoreboard_gravity_f (void *data, const cvar_t *cvar) +{ + grav_t grav; + + if (strequal (hud_scoreboard_gravity, "center")) + grav = grav_center; + else if (strequal (hud_scoreboard_gravity, "northwest")) + grav = grav_northwest; + else if (strequal (hud_scoreboard_gravity, "north")) + grav = grav_north; + else if (strequal (hud_scoreboard_gravity, "northeast")) + grav = grav_northeast; + else if (strequal (hud_scoreboard_gravity, "west")) + grav = grav_west; + else if (strequal (hud_scoreboard_gravity, "east")) + grav = grav_east; + else if (strequal (hud_scoreboard_gravity, "southwest")) + grav = grav_southwest; + else if (strequal (hud_scoreboard_gravity, "south")) + grav = grav_south; + else if (strequal (hud_scoreboard_gravity, "southeast")) + grav = grav_southeast; + else + grav = grav_center; + view_setgravity (hud_overlay_view, grav); +} + +void +HUD_Init_Cvars (void) +{ + Cvar_Register (&hud_sbar_cvar, hud_sbar_f, 0); + Cvar_Register (&hud_swap_cvar, hud_swap_f, 0); + Cvar_Register (&hud_scoreboard_gravity_cvar, hud_scoreboard_gravity_f, 0); +} + +void +HUD_Calc_sb_lines (int view_size) +{ + int stuff_y; + + if (view_size >= 120) { + hud_sb_lines = 0; + stuff_y = 0; + } else if (view_size >= 110) { + hud_sb_lines = 24; + sbar_inventory_view->visible = 0; + hud_inventory_view->visible = 0; + hud_armament_view->visible = 0; + stuff_y = 32; + } else { + hud_sb_lines = 48; + sbar_inventory_view->visible = 1; + hud_inventory_view->visible = 1; + hud_armament_view->visible = 1; + stuff_y = 48; + } + if (hud_sb_lines) { + sbar_view->visible = 1; + hud_view->visible = 1; + view_resize (sbar_view, sbar_view->xlen, hud_sb_lines); + view_resize (hud_view, hud_view->xlen, hud_sb_lines); + } else { + sbar_view->visible = 0; + hud_view->visible = 0; + } + view_move (hud_stuff_view, hud_stuff_view->xpos, stuff_y); +} diff --git a/libs/console/client.c b/libs/console/client.c index 02f7d2f62..0c4970535 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -80,11 +80,79 @@ static old_console_t *con; static float con_cursorspeed = 4; -static cvar_t *con_notifytime; // seconds -static cvar_t *con_alpha; -static cvar_t *con_size; -static cvar_t *con_speed; -static cvar_t *cl_conmode; +static float con_notifytime; +static cvar_t con_notifytime_cvar = { + .name = "con_notifytime", + .description = + "How long in seconds messages are displayed on screen", + .default_value = "3", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &con_notifytime }, +}; +static float con_alpha; +static cvar_t con_alpha_cvar = { + .name = "con_alpha", + .description = + "alpha value for the console background", + .default_value = "0.6", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &con_alpha }, +}; +static float con_size; +static cvar_t con_size_cvar = { + .name = "con_size", + .description = + "Fraction of the screen the console covers when down", + .default_value = "0.5", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &con_size }, +}; +static float con_speed; +static cvar_t con_speed_cvar = { + .name = "con_speed", + .description = + "How quickly the console scrolls up or down", + .default_value = "300", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &con_speed }, +}; +static exprenum_t cl_conmode_enum; +static exprtype_t cl_conmode_type = { + .name = "cl_conmode", + .size = sizeof (int), + .data = &cl_conmode_enum, + .get_string = cexpr_enum_get_string, +}; +static int cl_exec_line_command (void *data, const char *line); +static int cl_exec_line_chat (void *data, const char *line); +static int cl_exec_line_rcon (void *data, const char *line); +static int (*cl_conmode_values[])(void *, const char *) = { + cl_exec_line_command, + cl_exec_line_chat, + cl_exec_line_rcon, +}; +static exprsym_t cl_conmode_symbols[] = { + {"command", &cl_conmode_type, cl_conmode_values + 0}, + {"chat", &cl_conmode_type, cl_conmode_values + 1}, + {"rcon", &cl_conmode_type, cl_conmode_values + 1}, + {} +}; +static exprtab_t cl_conmode_symtab = { + cl_conmode_symbols, +}; +static exprenum_t cl_conmode_enum = { + &cl_conmode_type, + &cl_conmode_symtab, +}; +static char *cl_conmode; +static cvar_t cl_conmode_cvar = { + .name = "cl_conmode", + .description = + "Set the console input mode (command, chat, rcon)", + .default_value = "command", + .flags = CVAR_ARCHIVE, + .value = { .type = &cl_conmode_type, .value = &cl_conmode }, +}; #define NUM_CON_TIMES 4 static float con_times[NUM_CON_TIMES]; // realtime time the line was generated @@ -313,22 +381,6 @@ cl_exec_line_rcon (void *data, const char *line) return 0; } -static void -cl_conmode_f (cvar_t *var) -{ - if (!strcmp (var->string, "command")) { - con_data.exec_line = cl_exec_line_command; - } else if (!strcmp (var->string, "chat")) { - con_data.exec_line = cl_exec_line_chat; - } else if (!strcmp (var->string, "rcon")) { - con_data.exec_line = cl_exec_line_rcon; - } else { - Sys_Printf ("mode must be one of \"command\", \"chat\" or \"rcon\"\n"); - Sys_Printf (" forcing \"command\"\n"); - Cvar_Set (var, "command"); - } -} - static void con_end_message (inputline_t *line) { @@ -588,8 +640,8 @@ draw_console (view_t *view) if (con_state == con_fullscreen) { alpha = 255; } else { - float y = r_data->vid->conview->ylen * con_size->value; - alpha = 255 * con_alpha->value * view->ylen / y; + float y = r_data->vid->conview->ylen * con_size; + alpha = 255 * con_alpha * view->ylen / y; alpha = min (alpha, 255); } // draw the background @@ -632,7 +684,7 @@ draw_notify (view_t *view) if (time == 0) continue; time = *con_data.realtime - time; - if (time > con_notifytime->value) + if (time > con_notifytime) continue; text = con->text + (i % con_totallines) * con_linewidth; @@ -655,7 +707,7 @@ setup_console (void) lines = 0; break; case con_active: - lines = r_data->vid->conview->ylen * bound (0.2, con_size->value, + lines = r_data->vid->conview->ylen * bound (0.2, con_size, 1); break; case con_fullscreen: @@ -663,12 +715,12 @@ setup_console (void) break; } - if (con_speed->value) { + if (con_speed) { if (lines < con_data.lines) { - con_data.lines -= max (0.2, con_speed->value) * *con_data.frametime; + con_data.lines -= max (0.2, con_speed) * *con_data.frametime; con_data.lines = max (con_data.lines, lines); } else if (lines > con_data.lines) { - con_data.lines += max (0.2, con_speed->value) * *con_data.frametime; + con_data.lines += max (0.2, con_speed) * *con_data.frametime; con_data.lines = min (con_data.lines, lines); } } else { @@ -843,19 +895,12 @@ C_Init (void) Menu_Init (); - con_notifytime = Cvar_Get ("con_notifytime", "3", CVAR_NONE, NULL, - "How long in seconds messages are displayed " - "on screen"); + Cvar_Register (&con_notifytime_cvar, 0, 0); - con_alpha = Cvar_Get ("con_alpha", "0.6", CVAR_ARCHIVE, NULL, - "alpha value for the console background"); - con_size = Cvar_Get ("con_size", "0.5", CVAR_ARCHIVE, NULL, - "Fraction of the screen the console covers when " - "down"); - con_speed = Cvar_Get ("con_speed", "300", CVAR_ARCHIVE, NULL, - "How quickly the console scrolls up or down"); - cl_conmode = Cvar_Get ("cl_conmode", "command", CVAR_ARCHIVE, cl_conmode_f, - "Set the console input mode (command, chat, rcon)"); + Cvar_Register (&con_alpha_cvar, 0, 0); + Cvar_Register (&con_size_cvar, 0, 0); + Cvar_Register (&con_speed_cvar, 0, 0); + Cvar_Register (&cl_conmode_cvar, 0, 0); con_debuglog = COM_CheckParm ("-condebug"); diff --git a/libs/console/console.c b/libs/console/console.c index b75884e71..36f137423 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -56,23 +56,31 @@ static U inputline_t *(*const create)(int, int, char) = Con_CreateInputLine; static U void (*const display)(const char **, int) = Con_DisplayList; #undef U -static cvar_t *con_interpreter; +static char *con_interpreter; +static cvar_t con_interpreter_cvar = { + .name = "con_interpreter", + .description = + "Interpreter for the interactive console", + .default_value = "id", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &con_interpreter }, +}; static sys_printf_t saved_sys_printf; static void -Con_Interp_f (cvar_t *var) +Con_Interp_f (void *data, const cvar_t *cvar) { cbuf_interpreter_t *interp; if (!con_module) return; - interp = Cmd_GetProvider(var->string); + interp = Cmd_GetProvider(con_interpreter); if (interp) { cbuf_t *new; - Sys_Printf ("Switching to interpreter '%s'\n", var->string); + Sys_Printf ("Switching to interpreter '%s'\n", con_interpreter); new = Cbuf_New (interp); @@ -83,7 +91,7 @@ Con_Interp_f (cvar_t *var) } con_module->data->console->cbuf = new; } else { - Sys_Printf ("Unknown interpreter '%s'\n", var->string); + Sys_Printf ("Unknown interpreter '%s'\n", con_interpreter); } } @@ -111,9 +119,7 @@ Con_Init (const char *plugin_name) } else { setvbuf (stdout, 0, _IOLBF, BUFSIZ); } - con_interpreter = - Cvar_Get("con_interpreter", "id", CVAR_NONE, Con_Interp_f, - "Interpreter for the interactive console"); + Cvar_Register (&con_interpreter_cvar, Con_Interp_f, 0); } VISIBLE void diff --git a/libs/console/menu.c b/libs/console/menu.c index 0e02d63e3..ef57dc8de 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -79,7 +79,15 @@ typedef struct menu_item_s { menu_pic_t *pics; } menu_item_t; -static cvar_t *confirm_quit; +static int confirm_quit; +static cvar_t confirm_quit_cvar = { + .name = "confirm_quit", + .description = + "confirm quit command", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &confirm_quit }, +}; static progs_t menu_pr_state; static menu_item_t *menu; @@ -482,7 +490,7 @@ quit_f (void) { int ret; - if (confirm_quit->int_val && menu_quit) { + if (confirm_quit && menu_quit) { run_menu_pre (); PR_ExecuteProgram (&menu_pr_state, menu_quit); ret = R_INT (&menu_pr_state); @@ -611,8 +619,7 @@ Menu_Init (void) R_Progs_Init (&menu_pr_state); S_Progs_Init (&menu_pr_state); - confirm_quit = Cvar_Get ("confirm_quit", "1", CVAR_ARCHIVE, NULL, - "confirm quit command"); + Cvar_Register (&confirm_quit_cvar, 0, 0); Cmd_AddCommand ("togglemenu", togglemenu_f, "Toggle the display of the menu"); diff --git a/libs/console/server.c b/libs/console/server.c index f553fa67a..3b10f64e6 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -82,8 +82,59 @@ static console_data_t sv_con_data; static QFile *log_file; -static cvar_t *sv_logfile; -static cvar_t *sv_conmode; +static char *sv_logfile; +static cvar_t sv_logfile_cvar = { + .name = "sv_logfile", + .description = + "Control server console logging. \"none\" for off, or " + "\"filename:gzflags\"", + .default_value = "none", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &sv_logfile }, +}; +static exprenum_t sv_conmode_enum; +static exprtype_t sv_conmode_type = { + .name = "sv_conmode", + .size = sizeof (int), + .data = &sv_conmode_enum, + .get_string = cexpr_enum_get_string, +}; +static int sv_exec_line_command (void *data, const char *line); +static int sv_exec_line_chat (void *data, const char *line); +static int (*sv_conmode_values[])(void *, const char *) = { + sv_exec_line_command, + sv_exec_line_chat, +}; +static exprsym_t sv_conmode_symbols[] = { + {"command", &sv_conmode_type, sv_conmode_values + 0}, + {"chat", &sv_conmode_type, sv_conmode_values + 1}, + {} +}; +static exprtab_t sv_conmode_symtab = { + sv_conmode_symbols, +}; +static exprenum_t sv_conmode_enum = { + &sv_conmode_type, + &sv_conmode_symtab, +}; +static char *sv_conmode; +static cvar_t sv_conmode_cvar = { + .name = "sv_conmode", + .description = + "Set the console input mode (command, chat)", + .default_value = "command", + .flags = CVAR_NONE, + .value = { .type = &sv_conmode_type, .value = &sv_conmode }, +}; +static int sv_use_curses; +static cvar_t sv_use_curses_cvar = { + .name = "sv_use_curses", + .description = + "Set to 1 to enable curses server console.", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &sv_use_curses }, +}; #ifdef HAVE_NCURSES @@ -631,14 +682,14 @@ init (void) #endif static void -sv_logfile_f (cvar_t *var) +sv_logfile_f (void *data, const cvar_t *cvar) { - if (!var->string[0] || strequal (var->string, "none")) { + if (!sv_logfile[0] || strequal (sv_logfile, "none")) { if (log_file) Qclose (log_file); log_file = 0; } else { - char *fname = strdup (var->string); + char *fname = strdup (sv_logfile); char *flags = strrchr (fname, ':'); if (flags) { @@ -670,37 +721,19 @@ sv_exec_line_chat (void *data, const char *line) return 0; } -static void -sv_conmode_f (cvar_t *var) -{ - if (!strcmp (var->string, "command")) { - sv_con_data.exec_line = sv_exec_line_command; - } else if (!strcmp (var->string, "chat")) { - sv_con_data.exec_line = sv_exec_line_chat; - } else { - Sys_Printf ("mode must be one of \"command\" or \"chat\"\n"); - Sys_Printf (" forcing \"command\"\n"); - Cvar_Set (var, "command"); - } -} - static void C_Init (void) { + Cvar_Register (&sv_use_curses_cvar, 0, 0); #ifdef HAVE_NCURSES - cvar_t *curses = Cvar_Get ("sv_use_curses", "0", CVAR_ROM, NULL, - "Set to 1 to enable curses server console."); - use_curses = curses->int_val; + use_curses = sv_use_curses; if (use_curses) { init (); } else #endif setvbuf (stdout, 0, _IOLBF, BUFSIZ); - sv_logfile = Cvar_Get ("sv_logfile", "none", CVAR_NONE, sv_logfile_f, - "Control server console logging. \"none\" for off, " - "or \"filename:gzflags\""); - sv_conmode = Cvar_Get ("sv_conmode", "command", CVAR_NONE, sv_conmode_f, - "Set the console input mode (command, chat)"); + Cvar_Register (&sv_logfile_cvar, sv_logfile_f, 0); + Cvar_Register (&sv_conmode_cvar, 0, 0); } static void diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 61016e371..101bb92dc 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -117,8 +117,24 @@ typedef struct { dstring_t *dstr; } pr_debug_data_t; -cvar_t *pr_debug; -cvar_t *pr_source_path; +int pr_debug; +static cvar_t pr_debug_cvar = { + .name = "pr_debug", + .description = + "enable progs debugging", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &pr_debug }, +}; +char *pr_source_path; +static cvar_t pr_source_path_cvar = { + .name = "pr_source_path", + .description = + "where to look (within gamedir) for source files", + .default_value = ".", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &pr_source_path }, +}; static char *source_path_string; static char **source_paths; @@ -182,7 +198,7 @@ compunit_get_key (const void *cu, void *p) } static void -source_path_f (cvar_t *var) +source_path_f (void *data, const cvar_t *cvar) { int i; char *s; @@ -190,7 +206,7 @@ source_path_f (cvar_t *var) if (source_path_string) { free (source_path_string); } - source_path_string = strdup (var->string); + source_path_string = strdup (pr_source_path); if (source_paths) { free (source_paths); } @@ -587,7 +603,7 @@ PR_LoadDebug (progs_t *pr) res->debug = 0; - if (!pr_debug->int_val) + if (!pr_debug) return 1; def = PR_FindGlobal (pr, ".debug_file"); @@ -976,7 +992,7 @@ PR_DumpState (progs_t *pr) { prdeb_resources_t *res = pr->pr_debug_resources; if (pr->pr_xfunction) { - if (pr_debug->int_val && res->debug) { + if (pr_debug && res->debug) { pr_lineno_t *lineno; pr_auxfunction_t *func = 0; dfunction_t *descriptor = pr->pr_xfunction->descriptor; @@ -1045,7 +1061,7 @@ pr_debug_find_def (progs_t *pr, pr_ptr_t *ofs) prdeb_resources_t *res = pr->pr_debug_resources; pr_def_t *def = 0; - if (pr_debug->int_val && res->debug) { + if (pr_debug && res->debug) { def = PR_Get_Local_Def (pr, ofs); } if (*ofs >= pr->progs->globals.count) { @@ -1486,10 +1502,10 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) data.pr = pr; data.dstr = res->dstr; - if (pr_debug->int_val > 1) + if (pr_debug > 1) dump_code = 1; - if (pr_debug->int_val && res->debug) { + if (pr_debug && res->debug) { const char *source_line = PR_Get_Source_Line (pr, addr); if (source_line) { @@ -1528,7 +1544,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) } dasprintf (res->line, "%04x ", addr); - if (pr_debug->int_val > 2) { + if (pr_debug > 2) { if (pr->progs->version < PROG_VERSION) { dasprintf (res->line, "%03x %04x(%8s) %04x(%8s) %04x(%8s)\t", @@ -1741,7 +1757,7 @@ dump_frame (progs_t *pr, prstack_t *frame) Sys_Printf ("\n"); return; } - if (pr_debug->int_val && res->debug) { + if (pr_debug && res->debug) { pr_lineno_t *lineno = PR_Find_Lineno (pr, frame->staddr); pr_auxfunction_t *func = PR_Get_Lineno_Func (pr, lineno); pr_uint_t line = PR_Get_Lineno_Line (pr, lineno); @@ -1932,9 +1948,6 @@ PR_Debug_Init (progs_t *pr) void PR_Debug_Init_Cvars (void) { - pr_debug = Cvar_Get ("pr_debug", "0", CVAR_NONE, NULL, - "enable progs debugging"); - pr_source_path = Cvar_Get ("pr_source_path", ".", CVAR_NONE, source_path_f, - "where to look (within gamedir) for source " - "files"); + Cvar_Register (&pr_debug_cvar, 0, 0); + Cvar_Register (&pr_source_path_cvar, source_path_f, 0); } diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 34c132b20..174c61ab0 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -114,7 +114,7 @@ ED_Free (progs_t *pr, edict_t *ed) if (pr->unlink) pr->unlink (ed); // unlink from world bsp - if (pr_deadbeef_ents->int_val) { + if (pr_deadbeef_ents) { ED_ClearEdict (pr, ed, 0xdeadbeef); } else { if (pr->free_edict) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 0138ef7c3..a7d4fbac7 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -284,7 +284,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) sizeof (pr_type_t) * f->locals); pr->localstack_used += f->locals; - if (pr_deadbeef_locals->int_val) { + if (pr_deadbeef_locals) { for (pr_uint_t i = f->params_start; i < f->params_start + f->locals; i++) { pr->pr_globals[i].int_var = 0xdeadbeef; @@ -357,7 +357,7 @@ PR_BoundsCheckSize (progs_t *pr, pr_ptr_t addr, unsigned size) || size > (unsigned) (pr->globals_size - addr)) PR_RunError (pr, "invalid memory access: %d (0 to %d-%d)", addr, pr->globals_size, size); - if (pr_boundscheck->int_val >= 2 + if (pr_boundscheck >= 2 && PR_GetPointer (pr, addr + size) > (pr_type_t *) pr->zone) { void *mem = (void *) PR_GetPointer (pr, addr); Z_CheckPointer (pr->zone, mem, size * sizeof (pr_type_t)); @@ -385,7 +385,7 @@ signal_hook (int sig, void *data) { progs_t *pr = (progs_t *) data; - if (sig == SIGFPE && pr_faultchecks->int_val) { + if (sig == SIGFPE && pr_faultchecks) { dstatement_t *st; pr_type_t *op_a, *op_b, *op_c; @@ -501,7 +501,7 @@ PR_SetupParams (progs_t *pr, int num_params, int min_alignment) } pr_ptr_t mask = ~(min_alignment - 1); pr_ptr_t stack = (*pr->globals.stack - offset) & mask; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 0); } *pr->globals.stack = stack; @@ -835,7 +835,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREP_I_v6p: case OP_STOREP_P_v6p: pointer = OPB(ptr); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; @@ -843,7 +843,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_STOREP_V_v6p: pointer = OPB(ptr); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; @@ -851,7 +851,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_STOREP_Q_v6p: pointer = OPB(ptr); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; @@ -859,7 +859,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_STOREP_D_v6p: pointer = OPB(ptr); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_double); } ptr = pr->pr_globals + pointer; @@ -867,7 +867,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_ADDRESS_v6p: - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to address an out " "of bounds edict"); @@ -901,7 +901,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOAD_FN_v6p: case OP_LOAD_I_v6p: case OP_LOAD_P_v6p: - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); @@ -913,7 +913,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) OPC(int) = pr->pr_edict_area[fldofs].int_var; break; case OP_LOAD_V_v6p: - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); @@ -925,7 +925,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) memcpy (op_c, &pr->pr_edict_area[fldofs], 3 * sizeof (*op_c)); break; case OP_LOAD_Q_v6p: - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); @@ -937,7 +937,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) memcpy (op_c, &pr->pr_edict_area[fldofs], 4 * sizeof (*op_c)); break; case OP_LOAD_D_v6p: - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { if (OPA(entity) >= pr->pr_edict_area_size) PR_RunError (pr, "Progs attempted to read an out of " "bounds edict number"); @@ -957,7 +957,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADB_I_v6p: case OP_LOADB_P_v6p: pointer = OPA(entity) + OPB(field); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; @@ -965,7 +965,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_LOADB_V_v6p: pointer = OPA(entity) + OPB(field); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; @@ -973,7 +973,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_LOADB_Q_v6p: pointer = OPA(entity) + OPB(field); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; @@ -981,7 +981,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_LOADB_D_v6p: pointer = OPA(entity) + OPB(field); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_double); } ptr = pr->pr_globals + pointer; @@ -996,7 +996,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_LOADBI_I_v6p: case OP_LOADBI_P_v6p: pointer = OPA(ptr) + (short) st->b; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; @@ -1004,7 +1004,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_LOADBI_V_v6p: pointer = OPA(ptr) + (short) st->b; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; @@ -1012,7 +1012,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_LOADBI_Q_v6p: pointer = OPA(ptr) + (short) st->b; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; @@ -1020,7 +1020,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_LOADBI_D_v6p: pointer = OPA(ptr) + (short) st->b; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; @@ -1045,7 +1045,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREB_I_v6p: case OP_STOREB_P_v6p: pointer = OPB(ptr) + OPC(int); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; @@ -1053,7 +1053,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_STOREB_V_v6p: pointer = OPB(ptr) + OPC(int); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; @@ -1061,7 +1061,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_STOREB_Q_v6p: pointer = OPB(ptr) + OPC(int); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; @@ -1069,7 +1069,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_STOREB_D_v6p: pointer = OPB(ptr) + OPC(int); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; @@ -1084,7 +1084,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) case OP_STOREBI_I_v6p: case OP_STOREBI_P_v6p: pointer = OPB(ptr) + (short) st->c; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; @@ -1092,7 +1092,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_STOREBI_V_v6p: pointer = OPB(ptr) + (short) st->c; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; @@ -1100,7 +1100,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_STOREBI_Q_v6p: pointer = OPB(ptr) + (short) st->c; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; @@ -1108,7 +1108,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_STOREBI_D_v6p: pointer = OPB(ptr) + (short) st->c; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; @@ -1125,7 +1125,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) { pr_ptr_t stack = *pr->globals.stack - 1; pr_type_t *stk = pr->pr_globals + stack; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); } stk->int_var = OPA(int); @@ -1136,7 +1136,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) { pr_ptr_t stack = *pr->globals.stack - 3; pr_type_t *stk = pr->pr_globals + stack; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 3); } memcpy (stk, op_a, 3 * sizeof (*op_c)); @@ -1147,7 +1147,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) { pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 4); } memcpy (stk, op_a, 4 * sizeof (*op_c)); @@ -1169,7 +1169,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); PR_BoundsCheck (pr, pointer, ev_int); } @@ -1186,7 +1186,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 3); PR_BoundsCheck (pr, pointer, ev_int); } @@ -1203,7 +1203,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 4); PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -1227,7 +1227,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); PR_BoundsCheck (pr, pointer, ev_int); } @@ -1244,7 +1244,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 3); PR_BoundsCheck (pr, pointer, ev_int); } @@ -1261,7 +1261,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 4); PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -1281,7 +1281,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) { pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); } OPA(int) = stk->int_var; @@ -1292,7 +1292,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) { pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 3); } memcpy (op_a, stk, 3 * sizeof (*op_c)); @@ -1303,7 +1303,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) { pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 4); } memcpy (op_a, stk, 4 * sizeof (*op_c)); @@ -1325,7 +1325,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); PR_BoundsCheck (pr, pointer, ev_int); } @@ -1342,7 +1342,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 3); PR_BoundsCheck (pr, pointer, ev_int); } @@ -1359,7 +1359,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 4); PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -1383,7 +1383,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); PR_BoundsCheck (pr, pointer, ev_int); } @@ -1400,7 +1400,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 3); PR_BoundsCheck (pr, pointer, ev_int); } @@ -1417,7 +1417,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 4); PR_BoundsCheck (pr, pointer, ev_quaternion); } @@ -1469,7 +1469,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) st = pr->pr_statements + pr->pr_xstatement; break; case OP_JUMP_v6p: - if (pr_boundscheck->int_val + if (pr_boundscheck && (OPA(uint) >= pr->progs->statements.count)) { PR_RunError (pr, "Invalid jump destination"); } @@ -1478,12 +1478,12 @@ pr_exec_quakec (progs_t *pr, int exitdepth) break; case OP_JUMPB_v6p: pointer = st->a + OPB(int); - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; pointer = ptr->int_var; - if (pr_boundscheck->int_val + if (pr_boundscheck && (pointer >= pr->progs->statements.count)) { PR_RunError (pr, "Invalid jump destination"); } @@ -1701,7 +1701,7 @@ op_call: memmove (op_c, op_a, st->b * 4); break; case OP_MOVEP_v6p: - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheckSize (pr, OPC(ptr), OPB(uint)); PR_BoundsCheckSize (pr, OPA(ptr), OPB(uint)); } @@ -1710,7 +1710,7 @@ op_call: OPB(uint) * 4); break; case OP_MOVEPI_v6p: - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheckSize (pr, OPC(ptr), st->b); PR_BoundsCheckSize (pr, OPA(ptr), st->b); } @@ -1722,14 +1722,14 @@ op_call: pr_memset (op_c, OPA(ptr), st->b); break; case OP_MEMSETP_v6p: - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheckSize (pr, OPC(ptr), OPB(uint)); } pr_memset (pr->pr_globals + OPC(ptr), OPA(int), OPB(uint)); break; case OP_MEMSETPI_v6p: - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheckSize (pr, OPC(ptr), st->b); } pr_memset (pr->pr_globals + OPC(ptr), OPA(int), @@ -1888,7 +1888,7 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind) jump_offs = OPA(ptr) + OPB(int); break; } - if (pr_boundscheck->int_val && jump_offs >= pr->progs->statements.count) { + if (pr_boundscheck && jump_offs >= pr->progs->statements.count) { PR_RunError (pr, "out of bounds: %x", jump_offs); } return jump_offs - 1; // for st++ @@ -1900,7 +1900,7 @@ pr_stack_push (progs_t *pr) // keep the stack 16-byte aligned pr_ptr_t stack = *pr->globals.stack - 4; pr_type_t *stk = pr->pr_globals + stack; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 4); } *pr->globals.stack = stack; @@ -1912,7 +1912,7 @@ pr_stack_pop (progs_t *pr) { pr_ptr_t stack = *pr->globals.stack; pr_type_t *stk = pr->pr_globals + stack; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack, 4); } // keep the stack 16-byte aligned @@ -1929,7 +1929,7 @@ pr_stack_adjust (progs_t *pr, int mode, int offset) } pr_ptr_t stack = *pr->globals.stack; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { check_stack_pointer (pr, stack + offset, 0); } *pr->globals.stack = stack + offset; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 492d65bd7..eabbaa8b9 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -50,10 +50,42 @@ #include "compat.h" -VISIBLE cvar_t *pr_boundscheck; -cvar_t *pr_deadbeef_ents; -cvar_t *pr_deadbeef_locals; -cvar_t *pr_faultchecks; +VISIBLE int pr_boundscheck; +static cvar_t pr_boundscheck_cvar = { + .name = "pr_boundscheck", + .description = + "Server progs bounds checking", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &pr_boundscheck }, +}; +int pr_deadbeef_ents; +static cvar_t pr_deadbeef_ents_cvar = { + .name = "pr_deadbeef_ents", + .description = + "set to clear unallocated memory to 0xdeadbeef", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &pr_deadbeef_ents }, +}; +int pr_deadbeef_locals; +static cvar_t pr_deadbeef_locals_cvar = { + .name = "pr_deadbeef_locals", + .description = + "set to clear uninitialized local vars to 0xdeadbeef", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &pr_deadbeef_locals }, +}; +int pr_faultchecks; +static cvar_t pr_faultchecks_cvar = { + .name = "pr_faultchecks", + .description = + "capture and handle division by 0 in progs", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &pr_faultchecks }, +}; static const char * function_get_key (const void *f, void *_pr) @@ -498,16 +530,10 @@ PR_LoadProgs (progs_t *pr, const char *progsname) VISIBLE void PR_Init_Cvars (void) { - pr_boundscheck = - Cvar_Get ("pr_boundscheck", "0", CVAR_NONE, NULL, - "Server progs bounds checking"); - pr_deadbeef_ents = Cvar_Get ("pr_deadbeef_ents", "0", CVAR_NONE, NULL, - "set to clear unallocated memory to 0xdeadbeef"); - pr_deadbeef_locals = Cvar_Get ("pr_deadbeef_locals", "0", CVAR_NONE, NULL, - "set to clear uninitialized local vars to " - "0xdeadbeef"); - pr_faultchecks = Cvar_Get ("pr_faultchecks", "0", CVAR_NONE, NULL, - "capture and handle division by 0 in progs"); + Cvar_Register (&pr_boundscheck_cvar, 0, 0); + Cvar_Register (&pr_deadbeef_ents_cvar, 0, 0); + Cvar_Register (&pr_deadbeef_locals_cvar, 0, 0); + Cvar_Register (&pr_faultchecks_cvar, 0, 0); PR_Debug_Init_Cvars (); } diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index dd609ad12..2f57d1ad4 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -1562,7 +1562,7 @@ check_global (progs_t *pr, dstatement_t *st, const v6p_opcode_t *op, etype_t typ } if (!pr->denorm_found) { pr->denorm_found = 1; - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { Sys_Printf ("DENORMAL floats detected, these progs might " "not work. Good luck.\n"); return; @@ -1619,7 +1619,7 @@ PR_Check_v6p_Opcodes (progs_t *pr) //FIXME need to decide if I really want to always do static bounds checking // the only problem is that it slows progs load a little, but it's the only // way to check for qccx' evil - if (0 && !pr_boundscheck->int_val) { + if (0 && !pr_boundscheck) { for (i = 0, st = pr->pr_statements; i < pr->progs->statements.count; st++, i++) { pr_opcode_v6p_e st_op = (pr_opcode_v6p_e) st->op; diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index b2fdd45c8..4c8299e17 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -201,7 +201,7 @@ main (int argc, char **argv) Cmd_Init (); Cvar_Init (); PR_Init_Cvars (); - pr_boundscheck->int_val = 1; + pr_boundscheck = 1; while ((c = getopt (argc, argv, "qvt:")) != EOF) { switch (c) { diff --git a/libs/gib/gib_init.c b/libs/gib/gib_init.c index 9b20c61f8..a50df21c3 100644 --- a/libs/gib/gib_init.c +++ b/libs/gib/gib_init.c @@ -76,8 +76,8 @@ GIB_Exec_Override_f (void) return; } if (!Cvar_Command () - && (cmd_warncmd->int_val - || (developer && developer->int_val & SYS_dev))) + && (cmd_warncmd + || (developer && developer & SYS_dev))) Sys_Printf ("execing %s\n", Cmd_Argv (1)); if ((strlen (Cmd_Argv (1)) >= 4 && !strcmp (Cmd_Argv (1) + strlen (Cmd_Argv (1)) - 4, ".gib")) diff --git a/libs/gib/gib_process.c b/libs/gib/gib_process.c index 7492c8a91..182b92294 100644 --- a/libs/gib/gib_process.c +++ b/libs/gib/gib_process.c @@ -114,7 +114,8 @@ GIB_Process_Embedded (gib_tree_t * node, cbuf_args_t * args) } else if (cur->delim == '#') dstring_appendstr (args->argv[args->argc - 1], "0"); else if (cvar) - dstring_appendstr (args->argv[args->argc - 1], cvar->string); + dstring_appendstr (args->argv[args->argc - 1], + Cvar_VarString (cvar)); } else if ((var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &GIB_DATA (cbuf_active)->globals, (char *) cur->str, &index, false))) { @@ -126,7 +127,8 @@ GIB_Process_Embedded (gib_tree_t * node, cbuf_args_t * args) } else if (cur->delim == '#') dstring_appendstr (args->argv[args->argc - 1], "0"); else if ((cvar = Cvar_FindVar (cur->str))) - dstring_appendstr (args->argv[args->argc - 1], cvar->string); + dstring_appendstr (args->argv[args->argc - 1], + Cvar_VarString (cvar)); } if (str[prev]) dstring_appendstr (args->argv[args->argc - 1], str + prev); diff --git a/libs/gib/gib_vars.c b/libs/gib/gib_vars.c index 27adc7f4a..b03d53402 100644 --- a/libs/gib/gib_vars.c +++ b/libs/gib/gib_vars.c @@ -222,9 +222,11 @@ GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *ke dstring_replace (key, n, i-n+varstartskip, "0", 1); protect = n+1; } else if ((cvar = Cvar_FindVar (key->str+n+1+varstartskip))) { + const char *cvar_str = Cvar_VarString (cvar); key->str[i] = c; - dstring_replace (key, n, i-n+varstartskip, cvar->string, strlen (cvar->string)); - protect = n+strlen(cvar->string); + dstring_replace (key, n, i-n+varstartskip, cvar_str, + strlen (cvar_str)); + protect = n+strlen(cvar_str); } else { key->str[i] = c; dstring_snip (key, n, n-i+varstartskip); diff --git a/libs/input/in_common.c b/libs/input/in_common.c index ad69ee3a4..de8e22a68 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -70,14 +70,79 @@ typedef struct { static struct DARRAY_TYPE (in_regdriver_t) in_drivers = { .grow = 8 }; static struct DARRAY_TYPE (in_device_t) in_devices = { .grow = 8 }; -cvar_t *in_grab; -VISIBLE cvar_t *in_amp; -VISIBLE cvar_t *in_pre_amp; -cvar_t *in_freelook; -cvar_t *in_mouse_filter; -cvar_t *in_mouse_amp; -cvar_t *in_mouse_pre_amp; -cvar_t *lookstrafe; +int in_grab; +static cvar_t in_grab_cvar = { + .name = "in_grab", + .description = + "With this set to 1, quake will grab the mouse, preventing loss of " + "input focus.", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &in_grab }, +}; +VISIBLE float in_amp; +static cvar_t in_amp_cvar = { + .name = "in_amp", + .description = + "global in_amp multiplier", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &in_amp }, +}; +VISIBLE float in_pre_amp; +static cvar_t in_pre_amp_cvar = { + .name = "in_pre_amp", + .description = + "global in_pre_amp multiplier", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &in_pre_amp }, +}; +int in_freelook; +static cvar_t in_freelook_cvar = { + .name = "freelook", + .description = + "force +mlook", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &in_freelook }, +}; +char *in_mouse_filter; +static cvar_t in_mouse_filter_cvar = { + .name = "in_mouse_filter", + .description = + "Toggle mouse input filtering.", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &in_mouse_filter }, +}; +char *in_mouse_amp; +static cvar_t in_mouse_amp_cvar = { + .name = "in_mouse_amp", + .description = + "mouse in_mouse_amp multiplier", + .default_value = "15", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &in_mouse_amp }, +}; +char *in_mouse_pre_amp; +static cvar_t in_mouse_pre_amp_cvar = { + .name = "in_mouse_pre_amp", + .description = + "mouse in_mouse_pre_amp multiplier", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &in_mouse_pre_amp }, +}; +char *lookstrafe; +static cvar_t lookstrafe_cvar = { + .name = "lookstrafe", + .description = + "when mlook/klook on player will strafe", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &lookstrafe }, +}; int64_t in_timeout = 10000;//10ms default timeout @@ -395,18 +460,22 @@ IN_GetButtonInfo (int devid, int button_num, in_buttoninfo_t *info) } void -IN_UpdateGrab (cvar_t *var) // called from context_*.c +IN_UpdateGrab (int grab) { - if (var) { - for (size_t i = 0; i < in_drivers.size; i++) { - in_regdriver_t *rd = &in_drivers.a[i]; - if (rd->driver.grab_input) { - rd->driver.grab_input (rd->data, var->int_val); - } + for (size_t i = 0; i < in_drivers.size; i++) { + in_regdriver_t *rd = &in_drivers.a[i]; + if (rd->driver.grab_input) { + rd->driver.grab_input (rd->data, grab); } } } +static void +in_grab_f (void *data, const cvar_t *cvar) +{ + IN_UpdateGrab (in_grab); +} + void IN_ProcessEvents (void) { @@ -488,23 +557,14 @@ IN_Init (void) void IN_Init_Cvars (void) { - in_grab = Cvar_Get ("in_grab", "0", CVAR_ARCHIVE, IN_UpdateGrab, - "With this set to 1, quake will grab the mouse, " - "preventing loss of input focus."); - in_amp = Cvar_Get ("in_amp", "1", CVAR_ARCHIVE, NULL, - "global in_amp multiplier"); - in_pre_amp = Cvar_Get ("in_pre_amp", "1", CVAR_ARCHIVE, NULL, - "global in_pre_amp multiplier"); - in_freelook = Cvar_Get ("freelook", "0", CVAR_ARCHIVE, NULL, - "force +mlook"); - in_mouse_filter = Cvar_Get ("in_mouse_filter", "0", CVAR_ARCHIVE, NULL, - "Toggle mouse input filtering."); - in_mouse_amp = Cvar_Get ("in_mouse_amp", "15", CVAR_ARCHIVE, NULL, - "mouse in_mouse_amp multiplier"); - in_mouse_pre_amp = Cvar_Get ("in_mouse_pre_amp", "1", CVAR_ARCHIVE, NULL, - "mouse in_mouse_pre_amp multiplier"); - lookstrafe = Cvar_Get ("lookstrafe", "0", CVAR_ARCHIVE, NULL, - "when mlook/klook on player will strafe"); + Cvar_Register (&in_grab_cvar, in_grab_f, 0); + Cvar_Register (&in_amp_cvar, 0, 0); + Cvar_Register (&in_pre_amp_cvar, 0, 0); + Cvar_Register (&in_freelook_cvar, 0, 0); + Cvar_Register (&in_mouse_filter_cvar, 0, 0); + Cvar_Register (&in_mouse_amp_cvar, 0, 0); + Cvar_Register (&in_mouse_pre_amp_cvar, 0, 0); + Cvar_Register (&lookstrafe_cvar, 0, 0); for (size_t i = 0; i < in_drivers.size; i++) { in_regdriver_t *rd = &in_drivers.a[i]; if (rd->driver.init_cvars) { diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 2d1d1f5b3..554053df4 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -267,7 +267,8 @@ imt_switcher_update (imt_switcher_t *switcher) val = !!(input->button->state & inb_down); break; case imti_cvar: - val = !!input->cvar->int_val; + //FIXME check cvar type + val = !!*(int *) input->cvar->value.value; break; } state |= val << i; @@ -497,6 +498,7 @@ IMT_CreateSwitcher (const char *switcher_name, int context, imt_t *default_imt, switcher); } else { input->type = imti_cvar; + //FIXME check cvar type input->cvar = Cvar_FindVar (input_name); Cvar_AddListener (input->cvar, imt_switcher_cvar_update, switcher); } diff --git a/libs/models/alias/gl_mesh.c b/libs/models/alias/gl_mesh.c index 9dba75be7..5c7b6a9ce 100644 --- a/libs/models/alias/gl_mesh.c +++ b/libs/models/alias/gl_mesh.c @@ -350,10 +350,9 @@ gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, cache = dstring_new (); fullpath = dstring_new (); - if (!gl_alias_render_tri->int_val) { + if (!gl_alias_render_tri) { - if (gl_mesh_cache->int_val - && gl_mesh_cache->int_val <= header->mdl.numtris) { + if (gl_mesh_cache && gl_mesh_cache <= header->mdl.numtris) { do_cache = true; mdfour (model_digest, (unsigned char *) _m, _s); diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index e4de487e2..4e81f35f1 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -125,7 +125,7 @@ gl_Mod_ProcessTexture (model_t *mod, texture_t *tx) r_notexture_mip->render = &gl_notexture; return; } - if (gl_textures_external && gl_textures_external->int_val) { + if (gl_textures_external) { if (Mod_LoadExternalTextures (mod, tx)) { return; } @@ -239,8 +239,7 @@ SubdividePolygon (int numverts, float *verts) for (i = 0; i < 3; i++) { m = (mins[i] + maxs[i]) * 0.5; - m = gl_subdivide_size->value * floor (m / gl_subdivide_size->value + - 0.5); + m = gl_subdivide_size * floor (m / gl_subdivide_size + 0.5); if (maxs[i] - m < 8) continue; if (m - mins[i] < 8) diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index cf5552aed..ee307da3d 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -56,8 +56,8 @@ #include "compat.h" #include "mod_internal.h" -VISIBLE cvar_t *gl_sky_divide; //FIXME visibility? -VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible? +VISIBLE int mod_sky_divide; //FIXME visibility? +VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible? VISIBLE mleaf_t * Mod_PointInLeaf (const vec3_t p, model_t *model) @@ -640,9 +640,11 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) if (!strncmp (out->texinfo->texture->name, "sky", 3)) { // sky out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); - if (gl_sky_divide && gl_sky_divide->int_val) - if (mod_funcs && mod_funcs->Mod_SubdivideSurface) + if (mod_sky_divide) { + if (mod_funcs && mod_funcs->Mod_SubdivideSurface) { mod_funcs->Mod_SubdivideSurface (mod, out); + } + } continue; } diff --git a/libs/models/gl_skin.c b/libs/models/gl_skin.c index 5ecef36ba..96506fb65 100644 --- a/libs/models/gl_skin.c +++ b/libs/models/gl_skin.c @@ -174,12 +174,12 @@ build_skin (skin_t *skin, int cmap) int texnum, fb_texnum; // FIXME deek: This 512x256 limit sucks! - scaled_width = min (gl_max_size->int_val, 512); - scaled_height = min (gl_max_size->int_val, 256); + scaled_width = min (gl_max_size, 512); + scaled_height = min (gl_max_size, 256); // allow users to crunch sizes down even more if they want - scaled_width >>= gl_playermip->int_val; - scaled_height >>= gl_playermip->int_val; + scaled_width >>= gl_playermip; + scaled_height >>= gl_playermip; scaled_width = max (scaled_width, 1); scaled_height = max (scaled_height, 1); diff --git a/libs/models/model.c b/libs/models/model.c index 2e7dc48b2..ee8969543 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -59,10 +59,43 @@ static size_t mod_numknown; VISIBLE texture_t *r_notexture_mip; -cvar_t *gl_mesh_cache; -cvar_t *gl_subdivide_size; -cvar_t *gl_alias_render_tri; -cvar_t *gl_textures_external; +int gl_mesh_cache; +static cvar_t gl_mesh_cache_cvar = { + .name = "gl_mesh_cache", + .description = + "minimum triangle count in a model for its mesh to be cached. 0 to " + "disable caching", + .default_value = "256", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_mesh_cache }, +}; +float gl_subdivide_size; +static cvar_t gl_subdivide_size_cvar = { + .name = "gl_subdivide_size", + .description = + "Sets the division value for the sky brushes.", + .default_value = "128", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &gl_subdivide_size }, +}; +int gl_alias_render_tri; +static cvar_t gl_alias_render_tri_cvar = { + .name = "gl_alias_render_tri", + .description = + "When loading alias models mesh for pure triangle rendering", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_alias_render_tri }, +}; +int gl_textures_external; +static cvar_t gl_textures_external_cvar = { + .name = "gl_textures_external", + .description = + "Use external textures to replace BSP textures", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_textures_external }, +}; static void Mod_CallbackLoad (void *object, cache_allocator_t allocator); @@ -99,18 +132,10 @@ Mod_Init (void) VISIBLE void Mod_Init_Cvars (void) { - gl_subdivide_size = - Cvar_Get ("gl_subdivide_size", "128", CVAR_ARCHIVE, NULL, - "Sets the division value for the sky brushes."); - gl_mesh_cache = Cvar_Get ("gl_mesh_cache", "256", CVAR_ARCHIVE, NULL, - "minimum triangle count in a model for its mesh" - " to be cached. 0 to disable caching"); - gl_alias_render_tri = - Cvar_Get ("gl_alias_render_tri", "0", CVAR_ARCHIVE, NULL, "When " - "loading alias models mesh for pure triangle rendering"); - gl_textures_external = - Cvar_Get ("gl_textures_external", "1", CVAR_ARCHIVE, NULL, - "Use external textures to replace BSP textures"); + Cvar_Register (&gl_subdivide_size_cvar, 0, 0); + Cvar_Register (&gl_mesh_cache_cvar, 0, 0); + Cvar_Register (&gl_alias_render_tri_cvar, 0, 0); + Cvar_Register (&gl_textures_external_cvar, 0, 0); } VISIBLE void diff --git a/libs/net/nc/net_udp6.c b/libs/net/nc/net_udp6.c index fcbcda1f2..f0e8109e5 100644 --- a/libs/net/nc/net_udp6.c +++ b/libs/net/nc/net_udp6.c @@ -114,7 +114,15 @@ # endif #endif -static cvar_t *net_family; +static char *net_family; +static cvar_t net_family_cvar = { + .name = "net_family", + .description = + "Set the address family to ipv4, ipv6 or unspecified", + .default_value = "unspecified", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &net_family }, +}; netadr_t net_from; netadr_t net_local_adr; @@ -330,9 +338,9 @@ NET_StringToAdr (const char *s, netadr_t *a) memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_DGRAM; - if (strchr (net_family->string, '6')) { + if (strchr (net_family, '6')) { hints.ai_family = AF_INET6; - } else if (strchr (net_family->string, '4')) { + } else if (strchr (net_family, '4')) { hints.ai_family = AF_INET; } else { hints.ai_family = AF_UNSPEC; @@ -492,9 +500,9 @@ UDP_OpenSocket (int port) address.sin6_family = AF_INET6; memset (&hints, 0, sizeof (hints)); - if (strchr (net_family->string, '6')) { + if (strchr (net_family, '6')) { hints.ai_family = AF_INET6; - } else if (strchr (net_family->string, '4')) { + } else if (strchr (net_family, '4')) { hints.ai_family = AF_INET; } else { hints.ai_family = AF_UNSPEC; @@ -581,9 +589,7 @@ NET_Init (int port) if (r) Sys_Error ("Winsock initialization failed."); #endif /* _WIN32 */ - net_family = Cvar_Get ("net_family", "unspecified", CVAR_ROM, 0, - "Set the address family to ipv4, ipv6 or" - " unspecified"); + Cvar_Register (&net_family_cvar, 0, 0); // open the single socket to be used for all communications net_socket = UDP_OpenSocket (port); diff --git a/libs/net/net_chan.c b/libs/net/net_chan.c index 58da40169..13d4e5e9a 100644 --- a/libs/net/net_chan.c +++ b/libs/net/net_chan.c @@ -54,9 +54,35 @@ int net_nochoke; int net_blocksend; double *net_realtime; -cvar_t *showpackets; -cvar_t *showdrop; -cvar_t *qport; +int showpackets; +static cvar_t showpackets_cvar = { + .name = "showpackets", + .description = + "Show all network packets", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &showpackets }, +}; +int showdrop; +static cvar_t showdrop_cvar = { + .name = "showdrop", + .description = + "Toggle the display of how many packets you are dropping", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &showdrop }, +}; +int qport; +static cvar_t qport_cvar = { + .name = "qport", + .description = + "The internal port number for the game networking code. Useful for " + "clients who use multiple connections through one IP address (NAT/IP-" + "MASQ) because default port is random.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &qport }, +}; void (*net_log_packet) (int length, const void *data, netadr_t to); @@ -68,21 +94,15 @@ Netchan_Init (void) // pick a port value that should be nice and random port = Sys_TimeID (); - Cvar_SetValue (qport, port); + qport = port; } void Netchan_Init_Cvars (void) { - showpackets = Cvar_Get ("showpackets", "0", CVAR_NONE, NULL, - "Show all network packets"); - showdrop = Cvar_Get ("showdrop", "0", CVAR_NONE, NULL, "Toggle the " - "display of how many packets you are dropping"); - qport = Cvar_Get ("qport", "0", CVAR_NONE, NULL, "The internal port " - "number for the game networking code. Useful for " - "clients who use multiple connections through one " - "IP address (NAT/IP-MASQ) because default port is " - "random."); + Cvar_Register (&showpackets_cvar, 0, 0); + Cvar_Register (&showdrop_cvar, 0, 0); + Cvar_Register (&qport_cvar, 0, 0); } /* @@ -256,13 +276,13 @@ Netchan_Transmit (netchan_t *chan, unsigned length, byte *data) if (net_nochoke) chan->cleartime = *net_realtime; - if (showpackets->int_val & 1) { + if (showpackets & 1) { Sys_Printf ("--> s=%i(%i) a=%i(%i) %-4i %i\n", chan->outgoing_sequence, send_reliable, chan->incoming_sequence, chan->incoming_reliable_sequence, send.cursize, chan->outgoing_sequence - chan->incoming_sequence); - if (showpackets->int_val & 4) { + if (showpackets & 4) { SZ_Dump (&send); } } @@ -292,10 +312,10 @@ Netchan_Process (netchan_t *chan) sequence &= ~(1 << 31); sequence_ack &= ~(1 << 31); - if (showpackets->int_val & 2) { + if (showpackets & 2) { Sys_Printf ("<-- s=%i(%i) a=%i(%i) %i\n", sequence, reliable_message, sequence_ack, reliable_ack, net_message->message->cursize); - if (showpackets->int_val & 8) { + if (showpackets & 8) { SZ_Dump (net_message->message); } } @@ -329,7 +349,7 @@ Netchan_Process (netchan_t *chan) /// Discard stale or duplicated packets. if (sequence < (unsigned int) chan->incoming_sequence + 1) { - if (showdrop->int_val) + if (showdrop) Sys_Printf ("%s:Out of order packet %i at %i\n", NET_AdrToString (chan->remote_address), sequence, chan->incoming_sequence); @@ -341,7 +361,7 @@ Netchan_Process (netchan_t *chan) if (chan->net_drop > 0) { chan->drop_count += 1; - if (showdrop->int_val) + if (showdrop) Sys_Printf ("%s:Dropped %i packets at %i\n", NET_AdrToString (chan->remote_address), sequence - (chan->incoming_sequence + 1), sequence); diff --git a/libs/net/net_main.c b/libs/net/net_main.c index 6ef7e9a0f..523366bc0 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -86,8 +86,24 @@ int messagesReceived = 0; int unreliableMessagesSent = 0; int unreliableMessagesReceived = 0; -cvar_t *net_messagetimeout; -cvar_t *hostname; +float net_messagetimeout; +static cvar_t net_messagetimeout_cvar = { + .name = "net_messagetimeout", + .description = + "None", + .default_value = "300", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &net_messagetimeout }, +}; +char *hostname; +static cvar_t hostname_cvar = { + .name = "hostname", + .description = + "None", + .default_value = "UNNAMED", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &hostname }, +}; QFile *vcrFile; qboolean recording = false; @@ -229,9 +245,9 @@ MaxPlayers_f (void) svs.maxclients = n; if (n == 1) - Cvar_Set (deathmatch, "0"); + Cvar_Set ("deathmatch", "0"); else - Cvar_Set (deathmatch, "1"); + Cvar_Set ("deathmatch", "1"); } @@ -574,7 +590,7 @@ NET_GetMessage (qsocket_t *sock) // see if this connection has timed out if (ret == 0 && sock->driver) { - if (net_time - sock->lastMessageTime > net_messagetimeout->value) { + if (net_time - sock->lastMessageTime > net_messagetimeout) { Sys_MaskPrintf (SYS_net, "socket timed out\n"); NET_Close (sock); return -1; @@ -849,9 +865,8 @@ NET_Init (cbuf_t *cbuf) // allocate space for network message buffer SZ_Alloc (&_net_message_message, NET_MAXMESSAGE); - net_messagetimeout = - Cvar_Get ("net_messagetimeout", "300", CVAR_NONE, NULL, "None"); - hostname = Cvar_Get ("hostname", "UNNAMED", CVAR_NONE, NULL, "None"); + Cvar_Register (&net_messagetimeout_cvar, 0, 0); + Cvar_Register (&hostname_cvar, 0, 0); Cmd_AddCommand ("slist", NET_Slist_f, "No Description"); Cmd_AddCommand ("listen", NET_Listen_f, "No Description"); diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 71f74ff4a..faa762f92 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -634,7 +634,7 @@ _Datagram_CheckNewConnections (void) MSG_WriteByte (net_message->message, CCREP_SERVER_INFO); dfunc.GetSocketAddr (acceptsock, &newaddr); MSG_WriteString (net_message->message, dfunc.AddrToString (&newaddr)); - MSG_WriteString (net_message->message, hostname->string); + MSG_WriteString (net_message->message, hostname); MSG_WriteString (net_message->message, sv.name); MSG_WriteByte (net_message->message, net_activeconnections); MSG_WriteByte (net_message->message, svs.maxclients); @@ -719,7 +719,7 @@ _Datagram_CheckNewConnections (void) MSG_WriteByte (net_message->message, CCREP_RULE_INFO); if (var) { MSG_WriteString (net_message->message, var->name); - MSG_WriteString (net_message->message, var->string); + MSG_WriteString (net_message->message, Cvar_VarString (var)); } MSG_PokeLongBE (net_message->message, 0, NETFLAG_CTL | net_message->message->cursize); diff --git a/libs/net/nm/net_loop.c b/libs/net/nm/net_loop.c index ddf61f6f3..168cbe23e 100644 --- a/libs/net/nm/net_loop.c +++ b/libs/net/nm/net_loop.c @@ -69,8 +69,8 @@ Loop_SearchForHosts (qboolean xmit) return; const char *name = "local"; - if (strcmp (hostname->string, "UNNAMED") != 0) { - name = hostname->string; + if (strcmp (hostname, "UNNAMED") != 0) { + name = hostname; } const char *map = sv.name; int users = net_activeconnections; diff --git a/libs/net/nm/net_udp.c b/libs/net/nm/net_udp.c index 13044d0c3..8701214cd 100644 --- a/libs/net/nm/net_udp.c +++ b/libs/net/nm/net_udp.c @@ -259,9 +259,9 @@ UDP_Init (void) myAddr = 0; // if the quake hostname isn't set, set it to the machine name - if (strcmp (hostname->string, "UNNAMED") == 0) { + if (strcmp (hostname, "UNNAMED") == 0) { buff[15] = 0; - Cvar_Set (hostname, buff); + Cvar_Set ("hostname", buff); } if ((net_controlsocket = UDP_OpenSocket (0)) == -1) @@ -552,7 +552,7 @@ UDP_Read (int socket, byte *buf, int len, netadr_t *from) UDP_AddrToString (from)); last_iface = default_iface; #endif - if (developer->int_val & SYS_net) { + if (developer & SYS_net) { hex_dump_buf (buf, ret); } return ret; @@ -603,7 +603,7 @@ UDP_Write (int socket, byte *buf, int len, netadr_t *to) return 0; Sys_MaskPrintf (SYS_net, "sent %d bytes to %s\n", ret, UDP_AddrToString (to)); - if (developer->int_val & SYS_net) { + if (developer & SYS_net) { hex_dump_buf (buf, len); } return ret; diff --git a/libs/net/nm/net_wins.c b/libs/net/nm/net_wins.c index 411c0b838..c93229ca2 100644 --- a/libs/net/nm/net_wins.c +++ b/libs/net/nm/net_wins.c @@ -252,7 +252,7 @@ WINS_Init (void) return -1; } // if the quake hostname isn't set, set it to the machine name - if (strcmp (hostname->string, "UNNAMED") == 0) { + if (strcmp (hostname, "UNNAMED") == 0) { // see if it's a text IP address (well, close enough) for (p = buff; *p; p++) if ((*p < '0' || *p > '9') && *p != '.') @@ -265,7 +265,7 @@ WINS_Init (void) break; buff[i] = 0; } - Cvar_Set (hostname, buff); + Cvar_Set ("hostname", buff); } i = COM_CheckParm ("-ip"); diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index 8e38ac948..bf8d9c19c 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -209,7 +209,7 @@ PF_cvar (progs_t *pr, void *data) str = P_GSTRING (pr, 0); - R_FLOAT (pr) = Cvar_VariableValue (str); + R_FLOAT (pr) = Cvar_Value (str); } /* @@ -231,7 +231,7 @@ PF_cvar_set (progs_t *pr, void *data) return; } - Cvar_Set (var, val); + Cvar_SetVar (var, val); } /* diff --git a/libs/ruamoko/rua_cvar.c b/libs/ruamoko/rua_cvar.c index 4d953db9c..e81b9241a 100644 --- a/libs/ruamoko/rua_cvar.c +++ b/libs/ruamoko/rua_cvar.c @@ -41,6 +41,8 @@ #include "QF/progs.h" #include "QF/va.h" +#include "QF/simd/types.h" + #include "rua_internal.h" typedef struct bi_alias_s { @@ -127,7 +129,7 @@ bi_Cvar_SetString (progs_t *pr, void *_res) if (!var) var = Cvar_FindAlias (varname); if (var) - Cvar_Set (var, val); + Cvar_SetVar (var, val); } static void @@ -140,7 +142,7 @@ bi_Cvar_SetInteger (progs_t *pr, void *_res) if (!var) var = Cvar_FindAlias (varname); if (var) - Cvar_Set (var, va (0, "%d", val)); + Cvar_SetVar (var, va (0, "%d", val)); } static void @@ -153,7 +155,7 @@ bi_Cvar_SetFloat (progs_t *pr, void *_res) if (!var) var = Cvar_FindAlias (varname); if (var) - Cvar_Set (var, va (0, "%g", val)); + Cvar_SetVar (var, va (0, "%g", val)); } static void @@ -166,7 +168,7 @@ bi_Cvar_SetVector (progs_t *pr, void *_res) if (!var) var = Cvar_FindAlias (varname); if (var) - Cvar_Set (var, va (0, "%g %g %g", val[0], val[1], val[2])); + Cvar_SetVar (var, va (0, "%g %g %g", val[0], val[1], val[2])); } static void @@ -178,7 +180,7 @@ bi_Cvar_GetString (progs_t *pr, void *_res) if (!var) var = Cvar_FindAlias (varname); if (var) - RETURN_STRING (pr, var->string); + RETURN_STRING (pr, Cvar_VarString (var)); else RETURN_STRING (pr, ""); } @@ -189,9 +191,13 @@ bi_Cvar_GetInteger (progs_t *pr, void *_res) const char *varname = P_GSTRING (pr, 0); cvar_t *var = Cvar_FindVar (varname); + R_INT (pr) = 0; if (!var) var = Cvar_FindAlias (varname); - R_INT (pr) = var ? var->int_val : 0; + if (!var || var->value.type != &cexpr_int) + return; + + R_INT (pr) = *(int *) var->value.value; } static void @@ -200,9 +206,12 @@ bi_Cvar_GetFloat (progs_t *pr, void *_res) const char *varname = P_GSTRING (pr, 0); cvar_t *var = Cvar_FindVar (varname); + R_FLOAT (pr) = 0; if (!var) var = Cvar_FindAlias (varname); - R_FLOAT (pr) = var ? var->value : 0; + if (!var || var->value.type != &cexpr_float) + return; + R_INT (pr) = *(float *) var->value.value; } static void @@ -213,8 +222,8 @@ bi_Cvar_GetVector (progs_t *pr, void *_res) if (!var) var = Cvar_FindAlias (varname); - if (var) - RETURN_VECTOR (pr, var->vec); + if (var && var->value.type == &cexpr_vector) + RETURN_VECTOR (pr, *(vec4f_t *) var->value.value); else VectorZero (R_VECTOR (pr)); } @@ -228,8 +237,9 @@ bi_Cvar_Toggle (progs_t *pr, void *_res) var = Cvar_FindVar (varname); if (!var) var = Cvar_FindAlias (varname); - if (var) - Cvar_Set (var, var->int_val ? "0" : "1"); + if (var && var->value.type == &cexpr_int) { + *(int *) var->value.value = !*(int *) var->value.value; + } } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 65df011d6..510dff248 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -860,7 +860,7 @@ obj_find_message (probj_t *probj, pr_class_t *class, pr_sel_t *selector) pr_method_t *method; pr_sel_t *sel; int i; - int dev = developer->int_val; + int dev = developer; pr_string_t *names; if (dev & SYS_rua_msg) { @@ -882,7 +882,7 @@ obj_find_message (probj_t *probj, pr_class_t *class, pr_sel_t *selector) for (i = 0, method = method_list->method_list; i < method_list->method_count; i++, method++) { sel = &G_STRUCT (pr, pr_sel_t, method->method_name); - if (developer->int_val & SYS_rua_msg) { + if (developer & SYS_rua_msg) { names = probj->selector_names; Sys_Printf (" %s\n", PR_GetString (pr, names[sel->sel_id])); @@ -1214,7 +1214,7 @@ rua___obj_exec_class (progs_t *pr, void *data) Sys_MaskPrintf (SYS_rua_obj, " instance variables: %d @ %x\n", class->instance_size, class->ivars); - if (developer->int_val & SYS_rua_obj) + if (developer & SYS_rua_obj) dump_ivars (probj, class->ivars); Sys_MaskPrintf (SYS_rua_obj, " instance methods: %x\n", class->methods); @@ -1224,7 +1224,7 @@ rua___obj_exec_class (progs_t *pr, void *data) Sys_MaskPrintf (SYS_rua_obj, " instance variables: %d @ %x\n", meta->instance_size, meta->ivars); - if (developer->int_val & SYS_rua_obj) + if (developer & SYS_rua_obj) dump_ivars (probj, meta->ivars); class->subclass_list = 0; @@ -1482,7 +1482,7 @@ rua_obj_msg_sendv (progs_t *pr, void *data) if (count < 2 || count > PR_MAX_PARAMS) { PR_RunError (pr, "bad args count in obj_msg_sendv: %d", count); } - if (pr_boundscheck->int_val) { + if (pr_boundscheck) { PR_BoundsCheckSize (pr, args->list, count * pr->pr_param_size); } diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c index c9af82710..4344c6035 100644 --- a/libs/util/cexpr-vars.c +++ b/libs/util/cexpr-vars.c @@ -132,21 +132,13 @@ cexpr_cvar (const char *name, exprctx_t *ctx) } exprtype_t *type = ctx->result->type; - binop_t *cast = cexpr_find_cast (type, &cexpr_int); - - exprval_t *val = 0; - if (cast || val->type == &cexpr_int || val->type == &cexpr_uint) { - val = cexpr_value (type, ctx); - *(int *) val->value = var->int_val; - } else if (val->type == &cexpr_float) { - val = cexpr_value (type, ctx); - *(float *) val->value = var->value; - } else if (val->type == &cexpr_double) { - val = cexpr_value (type, ctx); - //FIXME cvars need to support double values - *(double *) val->value = var->value; + if (var->value.type) { + exprval_t *val = cexpr_value (type, ctx); + cexpr_assign_value (val, &var->value, ctx); + return val; } - return val; + cexpr_error (ctx, "cvar %s has unknown type", var->name); + return 0; } VISIBLE exprval_t * diff --git a/libs/util/cmd.c b/libs/util/cmd.c index 13038f53d..4b33673e4 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -65,7 +65,15 @@ typedef struct cmd_provider_s static cmdalias_t *cmd_alias; -VISIBLE cvar_t *cmd_warncmd; +VISIBLE int cmd_warncmd; +static cvar_t cmd_warncmd_cvar = { + .name = "cmd_warncmd", + .description = + "Toggles the display of error messages for unknown commands", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cmd_warncmd }, +}; static hashtab_t *cmd_alias_hash; static hashtab_t *cmd_hash; @@ -130,7 +138,7 @@ Cmd_Command (cbuf_args_t *args) return 0; if (cbuf_active->strict) return -1; - else if (cmd_warncmd->int_val || developer->int_val & SYS_dev) + else if (cmd_warncmd || developer & SYS_dev) Sys_Printf ("Unknown command \"%s\"\n", Cmd_Argv (0)); return 0; } @@ -515,9 +523,7 @@ Cmd_Exec_f (void) Sys_Printf ("couldn't exec %s\n", Cmd_Argv (1)); return; } - if (!Cvar_Command () - && (cmd_warncmd->int_val - || (developer && developer->int_val & SYS_dev))) + if (!Cvar_Command () && (cmd_warncmd || (developer & SYS_dev))) Sys_Printf ("execing %s\n", Cmd_Argv (1)); Cbuf_InsertText (cbuf_active, f); Hunk_FreeToLowMark (0, mark); @@ -629,8 +635,7 @@ Cmd_Init (void) Cmd_AddCommand ("echo", Cmd_Echo_f, "Print text to console"); Cmd_AddCommand ("wait", Cmd_Wait_f, "Wait a game tic"); Cmd_AddCommand ("sleep", Cmd_Sleep_f, "Wait for a certain number of seconds."); - cmd_warncmd = Cvar_Get ("cmd_warncmd", "0", CVAR_NONE, NULL, "Toggles the " - "display of error messages for unknown commands"); + Cvar_Register (&cmd_warncmd_cvar, 0, 0); cmd_cbuf = Cbuf_New (&id_interp); Cmd_AddProvider("id", &id_interp); diff --git a/libs/util/cvar.c b/libs/util/cvar.c index d1f9b693d..8eb2ed3aa 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -43,6 +43,7 @@ #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/cmem.h" #include "QF/hash.h" #include "QF/mathlib.h" #include "QF/plist.h" @@ -56,13 +57,82 @@ #define USER_RO_CVAR "User-created READ-ONLY Cvar" #define USER_CVAR "User-created cvar" -VISIBLE cvar_t *developer; +static exprenum_t developer_enum; +static exprtype_t developer_type = { + .name = "developer", + .size = sizeof (int), + .binops = cexpr_flag_binops, + .unops = cexpr_flag_unops, + .data = &developer_enum, + .get_string = cexpr_enum_get_string, +}; + +#define SYS_DEVELOPER(dev) (SYS_##dev & ~SYS_dev), +static int developer_values[] = { + SYS_dev, +#include "QF/sys_developer.h" +}; +#undef SYS_DEVELOPER +#define SYS_DEVELOPER(dev) {#dev, &developer_type, developer_values + __LINE__ - 31}, +static exprsym_t developer_symbols[] = { + {"dev", &developer_type, developer_values + 0}, +#include "QF/sys_developer.h" + {} +}; +#undef SYS_DEVELOPER +static exprtab_t developer_symtab = { + developer_symbols, +}; +static exprenum_t developer_enum = { + &developer_type, + &developer_symtab, +}; + +VISIBLE int developer; +static cvar_t developer_cvar = { + .name = "developer", + .description = + "set to enable extra debugging information", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &developer_type, .value = &developer }, +}; VISIBLE cvar_t *cvar_vars; +static cvar_t *user_cvars; static const char *cvar_null_string = ""; static cvar_alias_t *calias_vars; static hashtab_t *cvar_hash; static hashtab_t *calias_hash; +static cvar_t * +cvar_create (const char *name, const char *value) +{ + cvar_t *var = calloc (1, sizeof (cvar_t) + sizeof (char *)); + var->name = strdup (name); + var->description = cvar_null_string; + var->default_value = cvar_null_string; + var->flags = CVAR_USER_CREATED; + var->value.value = var + 1; + *(char **)var->value.value = strdup (value); + + var->next = user_cvars; + user_cvars = var; + + Hash_Add (cvar_hash, var); + return var; +} + +static void +cvar_destroy (cvar_t *var) +{ + if (!(var->flags & CVAR_USER_CREATED)) { + Sys_Error ("Attempt to destroy non-user cvar"); + } + Hash_Del (cvar_hash, var->name); + free (*(char **) var->value.value); + free ((char *) var->name); + free (var); +} VISIBLE cvar_t * Cvar_FindVar (const char *var_name) @@ -130,8 +200,21 @@ Cvar_RemoveAlias (const char *name) return var; } +static float +cvar_value (cvar_t *var) +{ + if (!var->value.type) { + return atof (*(char **)var->value.value); + } else if (var->value.type == &cexpr_int) { + return *(int *)var->value.value; + } else if (var->value.type == &cexpr_float) { + return *(float *)var->value.value; + } + return 0; +} + VISIBLE float -Cvar_VariableValue (const char *var_name) +Cvar_Value (const char *var_name) { cvar_t *var; @@ -140,11 +223,22 @@ Cvar_VariableValue (const char *var_name) var = Cvar_FindAlias (var_name); if (!var) return 0; - return atof (var->string); + return cvar_value (var); +} + +static const char * +cvar_string (const cvar_t *var) +{ + if (!var->value.type) { + return *(char **)var->value.value; + } else if (var->value.type->get_string) { + return var->value.type->get_string (&var->value, 0); + } + return cvar_null_string; } VISIBLE const char * -Cvar_VariableString (const char *var_name) +Cvar_String (const char *var_name) { cvar_t *var; @@ -153,7 +247,13 @@ Cvar_VariableString (const char *var_name) var = Cvar_FindAlias (var_name); if (!var) return cvar_null_string; - return var->string; + return cvar_string (var); +} + +VISIBLE const char * +Cvar_VarString (const cvar_t *var) +{ + return cvar_string (var); } VISIBLE const char * @@ -267,47 +367,74 @@ Cvar_RemoveListener (cvar_t *cvar, cvar_listener_t listener, void *data) } } -VISIBLE void -Cvar_Set (cvar_t *var, const char *value) +static int +cvar_setvar (cvar_t *var, const char *value) { - int changed; - int vals; + int changed = 0; - if (!var) - return; + if (!var->value.type) { + char **str_value = var->value.value; + changed = !*str_value || !strequal (*str_value, value); + if (var->validator) { + changed = changed && var->validator (var); + } + if (changed) { + free (*str_value); + *str_value = strdup (value); + } + } else { + exprenum_t *enm = var->value.type->data; + exprctx_t context = { + .memsuper = new_memsuper (), + .symtab = enm ? enm->symtab : 0, + .msg_prefix = var->name, + }; + if (context.symtab && !context.symtab->tab) { + cexpr_init_symtab (context.symtab, &context); + } + context.result = cexpr_value (var->value.type, &context); + if (!cexpr_eval_string (value, &context)) { + changed = memcmp (context.result->value, var->value.value, + var->value.type->size) != 0; + if (var->validator) { + changed = changed && var->validator (var); + } + if (changed) { + memcpy (var->value.value, context.result->value, + var->value.type->size); + } + } + delete_memsuper (context.memsuper); + } + if (changed && var->listeners) { + LISTENER_INVOKE (var->listeners, var); + } + return changed; +} + +VISIBLE void +Cvar_SetVar (cvar_t *var, const char *value) +{ if (var->flags & CVAR_ROM) { Sys_MaskPrintf (SYS_dev, "Cvar \"%s\" is read-only, cannot modify\n", var->name); return; } - - changed = !strequal (var->string, value); - if (changed) { - free ((char*)var->string); // free the old value string - - var->string = strdup (value); - var->value = atof (var->string); - var->int_val = atoi (var->string); - VectorZero (var->vec); - vals = sscanf (var->string, "%f %f %f", - &var->vec[0], &var->vec[1], &var->vec[2]); - if (vals == 1) - var->vec[2] = var->vec[1] = var->vec[0]; - - if (var->callback) - var->callback (var); - - if (var->listeners) { - LISTENER_INVOKE (var->listeners, var); - } - } + cvar_setvar (var, value); } VISIBLE void -Cvar_SetValue (cvar_t *var, float value) +Cvar_Set (const char *var_name, const char *value) { - Cvar_Set (var, va (0, "%.9g", value)); + cvar_t *var; + + var = Cvar_FindVar (var_name); + + if (!var) + return; + + Cvar_SetVar (var, value); } /* @@ -329,11 +456,11 @@ Cvar_Command (void) // perform a variable print or set if (Cmd_Argc () == 1) { - Sys_Printf ("\"%s\" is \"%s\"\n", v->name, v->string); + Sys_Printf ("\"%s\" is \"%s\"\n", v->name, cvar_string (v)); return true; } - Cvar_Set (v, Cmd_Argv (1)); + Cvar_SetVar (v, Cmd_Argv (1)); return true; } @@ -350,7 +477,7 @@ Cvar_WriteVariables (QFile *f) for (var = cvar_vars; var; var = var->next) if (var->flags & CVAR_ARCHIVE) - Qprintf (f, "seta %s \"%s\"\n", var->name, var->string); + Qprintf (f, "seta %s \"%s\"\n", var->name, cvar_string (var)); } VISIBLE void @@ -360,7 +487,7 @@ Cvar_SaveConfig (plitem_t *config) PL_D_AddObject (config, "cvars", cvars); for (cvar_t *var = cvar_vars; var; var = var->next) { if (var->flags & CVAR_ARCHIVE) { - PL_D_AddObject (cvars, var->name, PL_NewString (var->string)); + PL_D_AddObject (cvars, var->name, PL_NewString (cvar_string (var))); } } } @@ -379,79 +506,16 @@ Cvar_LoadConfig (plitem_t *config) if (value) { cvar_t *var = Cvar_FindVar (cvar_name); if (var) { - Cvar_Set (var, value); - Cvar_SetFlags (var, var->flags | CVAR_ARCHIVE); + Cvar_SetVar (var, value); + var->flags |= CVAR_ARCHIVE; } else { - Cvar_Get (cvar_name, value, CVAR_USER_CREATED | CVAR_ARCHIVE, - 0, USER_CVAR); + var = cvar_create (cvar_name, value); + var->flags |= CVAR_ARCHIVE; } } } } -#define SYS_DEVELOPER(developer) #developer, -static const char *developer_flags[] = { - "dev", -#include "QF/sys_developer.h" - 0 -}; - -static int -parse_developer_flag (const char *flag) -{ - const char **devflag; - char *end; - int val; - - val = strtol (flag, &end, 0); - if (!*end) { - return val; - } - for (devflag = developer_flags; *devflag; devflag++) { - if (!strcmp (*devflag, flag)) { - return 1 << (devflag - developer_flags); - } - } - return 0; -} - -static void -developer_f (cvar_t *var) -{ - char *buf = alloca (strlen (var->string) + 1); - const char *s; - char *b; - char c; - int parse = 0; - - for (s = var->string; *s; s++) { - if (isalpha (*s) || *s == '|') { - parse = 1; - break; - } - } - if (!parse) { - return; - } - var->int_val = 0; - for (s = var->string, b = buf; (c = *s++); ) { - if (isspace (c)) { - continue; - } - if (c == '|') { - *b = 0; - var->int_val |= parse_developer_flag (buf); - b = buf; - continue; - } - *b++ = c; - } - if (b != buf) { - *b = 0; - var->int_val |= parse_developer_flag (buf); - } -} - static void set_cvar (const char *cmd, int orflags) { @@ -477,12 +541,12 @@ set_cvar (const char *cmd, int orflags) "Cvar \"%s\" is read-only, cannot modify\n", var_name); } else { - Cvar_Set (var, value); - Cvar_SetFlags (var, var->flags | orflags); + Cvar_SetVar (var, value); + var->flags |= orflags; } } else { - Cvar_Get (var_name, value, CVAR_USER_CREATED | orflags, NULL, - USER_CVAR); + var = cvar_create (var_name, value); + var->flags |= orflags; } } @@ -523,11 +587,23 @@ Cvar_Inc_f (void) var = Cvar_FindVar (name); if (!var) var = Cvar_FindAlias (name); - if (!var) + if (!var) { Sys_Printf ("Unknown variable \"%s\"\n", name); + return; + } + if (var->flags & CVAR_ROM) { + Sys_Printf ("Variable \"%s\" is read-only\n", name); + return; + } break; } - Cvar_SetValue (var, var->value + inc); + if (var->value.type == &cexpr_float) { + *(float *) var->value.value += inc; + } else if (var->value.type == &cexpr_int) { + *(int *) var->value.value += inc; + } else { + Sys_Printf ("Variable \"%s\" cannot be incremented\n", name); + } } static void @@ -547,8 +623,12 @@ Cvar_Toggle_f (void) Sys_Printf ("Unknown variable \"%s\"\n", Cmd_Argv (1)); return; } + if ((var->flags & CVAR_ROM) || var->value.type != &cexpr_int) { + Sys_Printf ("Variable \"%s\" cannot be toggled\n", Cmd_Argv (1)); + return; + } - Cvar_Set (var, var->int_val ? "0" : "1"); + *(int *) var->value.value = !*(int *) var->value.value; } static void @@ -569,8 +649,7 @@ Cvar_Cycle_f (void) if (!var) var = Cvar_FindAlias (name); if (!var) { - var = Cvar_Get (name, Cmd_Argv (Cmd_Argc () - 1), CVAR_USER_CREATED, - 0, USER_CVAR); + var = cvar_create (name, Cmd_Argv (Cmd_Argc () - 1)); } // loop through the args until you find one that matches the current cvar @@ -583,27 +662,22 @@ Cvar_Cycle_f (void) // it won't match on zero when it should, but after that, it will be // comparing string that all had the same source (the user) so it will // work. - if (atof (Cmd_Argv (i)) == 0) { - if (!strcmp (Cmd_Argv (i), var->string)) - break; - } else { - if (atof (Cmd_Argv (i)) == var->value) - break; - } + if (!strcmp (Cmd_Argv (i), cvar_string (var))) + break; } if (i == Cmd_Argc ()) - Cvar_Set (var, Cmd_Argv (2)); // no match + Cvar_SetVar (var, Cmd_Argv (2)); // no match else if (i + 1 == Cmd_Argc ()) - Cvar_Set (var, Cmd_Argv (2)); // matched last value in list + Cvar_SetVar (var, Cmd_Argv (2)); // matched last value in list else - Cvar_Set (var, Cmd_Argv (i + 1)); // matched earlier in list + Cvar_SetVar (var, Cmd_Argv (i + 1)); // matched earlier in list } static void Cvar_Reset (cvar_t *var) { - Cvar_Set (var, var->default_string); + Cvar_SetVar (var, var->default_value); } static void @@ -661,7 +735,7 @@ Cvar_CvarList_f (void) var->flags & CVAR_SERVERINFO ? 's' : ' '); if (showhelp == 2) Sys_Printf ("//%s %s\n%s \"%s\"\n\n", flags, var->description, - var->name, var->string); + var->name, cvar_string (var)); else if (showhelp) Sys_Printf ("%s %-20s : %s\n", flags, var->name, var->description); else @@ -671,15 +745,6 @@ Cvar_CvarList_f (void) Sys_Printf ("------------\n%d variables\n", i); } -static void -cvar_free (void *c, void *unused) -{ - cvar_t *cvar = (cvar_t*)c; - free ((char*)cvar->name); - free ((char*)cvar->string); - free (cvar); -} - static const char * cvar_get_key (const void *c, void *unused) { @@ -705,15 +770,14 @@ calias_get_key (const void *c, void *unused) VISIBLE void Cvar_Init_Hash (void) { - cvar_hash = Hash_NewTable (1021, cvar_get_key, cvar_free, 0, 0); + cvar_hash = Hash_NewTable (1021, cvar_get_key, 0, 0, 0); calias_hash = Hash_NewTable (1021, calias_get_key, calias_free, 0, 0); } VISIBLE void Cvar_Init (void) { - developer = Cvar_Get ("developer", "0", CVAR_NONE, developer_f, - "set to enable extra debugging information"); + Cvar_Register (&developer_cvar, 0, 0); Cmd_AddCommand ("set", Cvar_Set_f, "Set the selected variable, useful on " "the command line (+set variablename setting)"); @@ -732,66 +796,38 @@ Cvar_Init (void) Cmd_AddCommand ("resetall", Cvar_ResetAll_f, "Reset all cvars"); } -VISIBLE cvar_t * -Cvar_Get (const char *name, const char *string, int cvarflags, - void (*callback)(cvar_t*), const char *description) +VISIBLE void +Cvar_Register (cvar_t *var, cvar_listener_t listener, void *data) { - int changed = 0; - cvar_t *var; + cvar_t *user_var; - if (Cmd_Exists (name)) { - Sys_Printf ("Cvar_Get: %s is a command\n", name); - return NULL; + if (Cmd_Exists (var->name)) { + Sys_Printf ("Cvar_Get: %s is a command\n", var->name); + return; + } + if (var->flags & CVAR_REGISTERED) { + Sys_Error ("Cvar %s already registered", var->name); } - var = Cvar_FindVar (name); - if (!var) { - cvar_t **v; - var = (cvar_t *) calloc (1, sizeof (cvar_t)); - // Cvar doesn't exist, so we create it - var->name = strdup (name); - var->string = strdup (string); - var->default_string = strdup (string); - var->flags = cvarflags; - var->callback = callback; - var->description = description; - var->value = atof (var->string); - var->int_val = atoi (var->string); - sscanf (var->string, "%f %f %f", - &var->vec[0], &var->vec[1], &var->vec[2]); - Hash_Add (cvar_hash, var); - - for (v = &cvar_vars; *v; v = &(*v)->next) - if (strcmp ((*v)->name, var->name) >= 0) - break; - var->next = *v; - *v = var; - - changed = 1; + if ((user_var = Hash_Find (cvar_hash, var->name))) { + cvar_setvar (var, cvar_string (user_var)); + cvar_destroy (user_var); } else { - // Cvar does exist, so we update the flags and return. - var->flags &= ~CVAR_USER_CREATED; - var->flags |= cvarflags; - changed = !strequal (var->string, string) || var->callback != callback; - if (!var->callback) - var->callback = callback; - if (!var->description - || strequal (var->description, USER_RO_CVAR) - || strequal (var->description, USER_CVAR)) - var->description = description; - if (!var->default_string) - var->default_string = strdup (string); + cvar_setvar (var, var->default_value); } - if (changed) { - if (var->callback) - var->callback (var); + var->flags |= CVAR_REGISTERED; + var->next = cvar_vars; + cvar_vars = var; - if (var->listeners) { - LISTENER_INVOKE (var->listeners, var); - } + if (listener) { + Cvar_AddListener (var, listener, data); } - return var; + Hash_Add (cvar_hash, var); + + if (var->listeners) { + LISTENER_INVOKE (var->listeners, var); + } } /* diff --git a/libs/util/plugin.c b/libs/util/plugin.c index 53ca4012e..e5bf0ace2 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -71,7 +71,15 @@ typedef struct loaded_plugin_s { plugin_t *plugin; } loaded_plugin_t; -cvar_t *fs_pluginpath; +char *fs_pluginpath; +static cvar_t fs_pluginpath_cvar = { + .name = "fs_pluginpath", + .description = + "Location of your plugin directory", + .default_value = FS_PLUGINPATH, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &fs_pluginpath }, +}; hashtab_t *registered_plugins, *loaded_plugins; @@ -155,9 +163,9 @@ static const char * pi_realname (const char *type, const char *name) { #if defined(HAVE_DLOPEN) - return va (0, "%s/%s_%s.so", fs_pluginpath->string, type, name); + return va (0, "%s/%s_%s.so", fs_pluginpath, type, name); #elif defined(_WIN32) - return va (0, "%s/%s_%s.dll", fs_pluginpath->string, type, name); + return va (0, "%s/%s_%s.dll", fs_pluginpath, type, name); #else return "No shared library support. FIXME"; #endif @@ -178,8 +186,7 @@ pi_info_name (const char *type, const char *name) static void PI_InitCvars (void) { - fs_pluginpath = Cvar_Get ("fs_pluginpath", FS_PLUGINPATH, CVAR_ROM, NULL, - "Location of your plugin directory"); + Cvar_Register (&fs_pluginpath_cvar, 0, 0); } static void diff --git a/libs/util/qargs.c b/libs/util/qargs.c index 45bd04636..ad7eda0e7 100644 --- a/libs/util/qargs.c +++ b/libs/util/qargs.c @@ -51,8 +51,24 @@ #include "QF/sys.h" #include "QF/va.h" -cvar_t *fs_globalcfg; -cvar_t *fs_usercfg; +char *fs_globalcfg; +static cvar_t fs_globalcfg_cvar = { + .name = "fs_globalcfg", + .description = + "global configuration file", + .default_value = FS_GLOBALCFG, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &fs_globalcfg }, +}; +char *fs_usercfg; +static cvar_t fs_usercfg_cvar = { + .name = "fs_usercfg", + .description = + "user configuration file", + .default_value = FS_USERCFG, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &fs_usercfg }, +}; static const char **largv; static const char *argvdummy = " "; @@ -160,9 +176,8 @@ COM_ParseConfig (cbuf_t *cbuf) Cbuf_Execute_Sets (cbuf); // execute set commands in the global configuration file if it exists - fs_globalcfg = Cvar_Get ("fs_globalcfg", FS_GLOBALCFG, CVAR_ROM, NULL, - "global configuration file"); - Cmd_Exec_File (cbuf, fs_globalcfg->string, 0); + Cvar_Register (&fs_globalcfg_cvar, 0, 0); + Cmd_Exec_File (cbuf, fs_globalcfg, 0); Cbuf_Execute_Sets (cbuf); // execute +set again to override the config file @@ -170,9 +185,8 @@ COM_ParseConfig (cbuf_t *cbuf) Cbuf_Execute_Sets (cbuf); // execute set commands in the user configuration file if it exists - fs_usercfg = Cvar_Get ("fs_usercfg", FS_USERCFG, CVAR_ROM, NULL, - "user configuration file"); - Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cvar_Register (&fs_usercfg_cvar, 0, 0); + Cmd_Exec_File (cbuf, fs_usercfg, 0); Cbuf_Execute_Sets (cbuf); // execute +set again to override the config file @@ -212,14 +226,14 @@ COM_ExecConfig (cbuf_t *cbuf, int skip_quakerc) // should be used to set up defaults on the assumption that the user has // things set up to work with another (hopefully compatible) client if (Cmd_Exec_File (cbuf, "quakeforge.cfg", 1)) { - Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cmd_Exec_File (cbuf, fs_usercfg, 0); Cmd_StuffCmds (cbuf); COM_Check_quakerc ("startdemos", cbuf); } else { if (!skip_quakerc) { Cbuf_InsertText (cbuf, "exec quake.rc\n"); } - Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cmd_Exec_File (cbuf, fs_usercfg, 0); // Reparse the command line for + commands. // (sets still done, but it doesn't matter) // (Note, no non-base commands exist yet) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index b9ea4c38a..162722a81 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -123,9 +123,33 @@ int fnmatch (const char *__pattern, const char *__string, int __flags); // QUAKE FILESYSTEM static memhunk_t *qfs_hunk; -static cvar_t *fs_userpath; -static cvar_t *fs_sharepath; -static cvar_t *fs_dirconf; +static char *fs_userpath; +static cvar_t fs_userpath_cvar = { + .name = "fs_userpath", + .description = + "location of your game directories", + .default_value = FS_USERPATH, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &fs_userpath }, +}; +static char *fs_sharepath; +static cvar_t fs_sharepath_cvar = { + .name = "fs_sharepath", + .description = + "location of shared (read-only) game directories", + .default_value = FS_SHAREPATH, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &fs_sharepath }, +}; +static char *fs_dirconf; +static cvar_t fs_dirconf_cvar = { + .name = "fs_dirconf", + .description = + "full path to gamedir.conf FIXME", + .default_value = "", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &fs_dirconf }, +}; VISIBLE const char *qfs_userpath; @@ -650,8 +674,8 @@ qfs_load_config (void) char *buf; char *dirconf; - if (*fs_dirconf->string) { - dirconf = Sys_ExpandSquiggle (fs_dirconf->string); + if (*fs_dirconf) { + dirconf = Sys_ExpandSquiggle (fs_dirconf); if (!(f = Qopen (dirconf, "rt"))) Sys_MaskPrintf (SYS_fs, "Could not load `%s', using builtin defaults\n", @@ -1333,17 +1357,17 @@ qfs_add_gamedir (vpath_t *vpath, const char *dir) if (!*dir) return; - e = fs_sharepath->string + strlen (fs_sharepath->string); + e = fs_sharepath + strlen (fs_sharepath); s = e; s_dir = dstring_new (); f_dir = dstring_new (); - while (s >= fs_sharepath->string) { - while (s != fs_sharepath->string && s[-1] !=':') + while (s >= fs_sharepath) { + while (s != fs_sharepath && s[-1] !=':') s--; if (s != e) { dsprintf (s_dir, "%.*s", (int) (e - s), s); - if (strcmp (s_dir->str, fs_userpath->string) != 0) { + if (strcmp (s_dir->str, fs_userpath) != 0) { if (qfs_expand_path (f_dir, s_dir->str, dir, 0) != 0) { Sys_Printf ("dropping bad directory %s\n", dir); break; @@ -1409,12 +1433,15 @@ QFS_GamedirCallback (gamedir_callback_t *func) } static void -qfs_path_cvar (cvar_t *var) +qfs_path_cvar (void *data, const cvar_t *cvar) { - char *cpath = QFS_CompressPath (var->string); - if (strcmp (cpath, var->string)) - Cvar_Set (var, cpath); - free (cpath); + char *cpath = QFS_CompressPath (*(char **)data); + if (strcmp (cpath, *(char **)data)) { + free (*(char **)cvar->value.value); + *(char **)cvar->value.value = cpath; + } else { + free (cpath); + } } static void @@ -1434,19 +1461,13 @@ QFS_Init (memhunk_t *hunk, const char *game) qfs_hunk = hunk; - fs_sharepath = Cvar_Get ("fs_sharepath", FS_SHAREPATH, CVAR_ROM, - qfs_path_cvar, - "location of shared (read-only) game " - "directories"); - fs_userpath = Cvar_Get ("fs_userpath", FS_USERPATH, CVAR_ROM, - qfs_path_cvar, - "location of your game directories"); - fs_dirconf = Cvar_Get ("fs_dirconf", "", CVAR_ROM, NULL, - "full path to gamedir.conf FIXME"); + Cvar_Register (&fs_sharepath_cvar, qfs_path_cvar, &fs_sharepath); + Cvar_Register (&fs_userpath_cvar, qfs_path_cvar, &fs_userpath); + Cvar_Register (&fs_dirconf_cvar, 0, 0); Cmd_AddCommand ("path", qfs_path_f, "Show what paths Quake is using"); - qfs_userpath = Sys_ExpandSquiggle (fs_userpath->string); + qfs_userpath = Sys_ExpandSquiggle (fs_userpath); qfs_load_config (); diff --git a/libs/util/sys.c b/libs/util/sys.c index daa9adb55..f5ebfded5 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -96,10 +96,45 @@ static void Sys_StdPrintf (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); static void Sys_ErrPrintf (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); -VISIBLE cvar_t *sys_nostdout; -VISIBLE cvar_t *sys_extrasleep; -cvar_t *sys_dead_sleep; -cvar_t *sys_sleep; +VISIBLE int sys_nostdout; +static cvar_t sys_nostdout_cvar = { + .name = "sys_nostdout", + .description = + "Set to disable std out", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sys_nostdout }, +}; +VISIBLE int sys_extrasleep; +static cvar_t sys_extrasleep_cvar = { + .name = "sys_extrasleep", + .description = + "Set to cause whatever amount delay in microseconds you want. Mostly " + "useful to generate simulated bad connections.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sys_extrasleep }, +}; +int sys_dead_sleep; +static cvar_t sys_dead_sleep_cvar = { + .name = "sys_dead_sleep", + .description = + "When set, the server gets NO cpu if no clients are connected and " + "there's no other activity. *MIGHT* cause problems with some mods.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sys_dead_sleep }, +}; +int sys_sleep; +static cvar_t sys_sleep_cvar = { + .name = "sys_sleep", + .description = + "Sleep how long in seconds between checking for connections. Minimum " + "is 0, maximum is 13", + .default_value = "8", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sys_sleep }, +}; int sys_checksum; @@ -297,7 +332,7 @@ Sys_Print (FILE *stream, const char *fmt, va_list args) static void Sys_StdPrintf (const char *fmt, va_list args) { - if (sys_nostdout && sys_nostdout->int_val) + if (sys_nostdout) return; Sys_Print (stdout, fmt, args); } @@ -322,7 +357,7 @@ Sys_MaskPrintf (int mask, const char *fmt, ...) { va_list args; - if (!developer || !(developer->int_val & mask)) + if (!(developer & mask)) return; va_start (args, fmt); sys_std_printf_function (fmt, args); @@ -495,21 +530,10 @@ Sys_MakeCodeWriteable (uintptr_t startaddr, size_t length) VISIBLE void Sys_Init_Cvars (void) { - sys_nostdout = Cvar_Get ("sys_nostdout", "0", CVAR_NONE, NULL, - "Set to disable std out"); - sys_extrasleep = Cvar_Get ("sys_extrasleep", "0", CVAR_NONE, NULL, - "Set to cause whatever amount delay in " - "microseconds you want. Mostly " - "useful to generate simulated bad " - "connections."); - sys_dead_sleep = Cvar_Get ("sys_dead_sleep", "0", CVAR_NONE, NULL, - "When set, the server gets NO cpu if no " - "clients are connected and there's no other " - "activity. *MIGHT* cause problems with some " - "mods."); - sys_sleep = Cvar_Get ("sys_sleep", "8", CVAR_NONE, NULL, "Sleep how long " - "in seconds between checking for connections. " - "Minimum is 0, maximum is 13"); + Cvar_Register (&sys_nostdout_cvar, 0, 0); + Cvar_Register (&sys_extrasleep_cvar, 0, 0); + Cvar_Register (&sys_dead_sleep_cvar, 0, 0); + Cvar_Register (&sys_sleep_cvar, 0, 0); } void @@ -802,7 +826,7 @@ Sys_CheckInput (int idle, int net_socket) int sleep_msec; // Now we want to give some processing time to other applications, // such as qw_client, running on this machine. - sleep_msec = sys_sleep->int_val; + sleep_msec = sys_sleep; if (sleep_msec > 0) { if (sleep_msec > 13) sleep_msec = 13; @@ -825,7 +849,7 @@ Sys_CheckInput (int idle, int net_socket) if (net_socket >= 0) QF_FD_SET (((unsigned) net_socket), &fdset);// cast needed for windows - if (idle && sys_dead_sleep->int_val) + if (idle && sys_dead_sleep) usec = -1; res = Sys_Select (max (net_socket, 0), &fdset, usec); diff --git a/libs/util/zone.c b/libs/util/zone.c index cfde5a3dd..0341af421 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -222,7 +222,7 @@ Z_TagMalloc (memzone_t *zone, size_t size, int tag) int requested_size = size; memblock_t *start, *rover, *new, *base; - if (!developer || developer->int_val & SYS_dev) + if (developer & SYS_dev) Z_CheckHeap (zone); // DEBUG if (!tag) { @@ -291,7 +291,7 @@ Z_Realloc (memzone_t *zone, void *ptr, size_t size) if (!ptr) return Z_Malloc (zone, size); - if (!developer || developer->int_val & SYS_dev) + if (developer & SYS_dev) Z_CheckHeap (zone); // DEBUG block = (memblock_t *) ((byte *) ptr - sizeof (memblock_t)); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index e20718da5..f131fa0d7 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -569,7 +569,7 @@ crosshair_2 (int x, int y) { unsigned char *pColor; - pColor = (unsigned char *) &d_8to24table[crosshaircolor->int_val]; + pColor = (unsigned char *) &d_8to24table[crosshaircolor]; qfglColor4ubv (pColor); qfglBindTexture (GL_TEXTURE_2D, cs_texture); @@ -593,7 +593,7 @@ crosshair_3 (int x, int y) { unsigned char *pColor; - pColor = (unsigned char *) &d_8to24table[crosshaircolor->int_val]; + pColor = (unsigned char *) &d_8to24table[crosshaircolor]; qfglColor4ubv (pColor); qfglBindTexture (GL_TEXTURE_2D, cs_texture); @@ -617,7 +617,7 @@ crosshair_4 (int x, int y) { unsigned char *pColor; - pColor = (unsigned char *) &d_8to24table[crosshaircolor->int_val]; + pColor = (unsigned char *) &d_8to24table[crosshaircolor]; qfglColor4ubv (pColor); qfglBindTexture (GL_TEXTURE_2D, cs_texture); @@ -641,7 +641,7 @@ crosshair_5 (int x, int y) //FIXME don't use until the data is filled in { unsigned char *pColor; - pColor = (unsigned char *) &d_8to24table[crosshaircolor->int_val]; + pColor = (unsigned char *) &d_8to24table[crosshaircolor]; qfglColor4ubv (pColor); qfglBindTexture (GL_TEXTURE_2D, cs_texture); @@ -674,12 +674,12 @@ gl_Draw_Crosshair (void) int x, y; int ch; - ch = crosshair->int_val - 1; + ch = crosshair - 1; if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) return; - x = vid.conview->xlen / 2 + cl_crossx->int_val; - y = vid.conview->ylen / 2 + cl_crossy->int_val; + x = vid.conview->xlen / 2 + cl_crossx; + y = vid.conview->ylen / 2 + cl_crossy; crosshair_func[ch] (x, y); } @@ -784,7 +784,7 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) gl = (glpic_t *) conback->data; // spin the console? - effect described in a QER tutorial - if (gl_conspin->value) { + if (gl_conspin) { static float xangle = 0; static float xfactor = .3f; static float xstep = .005f; @@ -793,7 +793,7 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) qfglMatrixMode (GL_TEXTURE); qfglPushMatrix (); qfglLoadIdentity (); - xangle += gl_conspin->value; + xangle += gl_conspin; xfactor += xstep; if (xfactor > 8 || xfactor < .3f) xstep = -xstep; @@ -801,7 +801,7 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) qfglScalef (xfactor, xfactor, xfactor); } // slide console up/down or stretch it? - if (gl_constretch->int_val) { + if (gl_constretch) { ofs = 0; } else ofs = (vid.conview->ylen - lines) / (float) vid.conview->ylen; @@ -827,15 +827,15 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) qfglColor3ubv (color_0_8); } - if (gl_conspin->value) { + if (gl_conspin) { qfglPopMatrix (); qfglMatrixMode (GL_MODELVIEW); qfglPopMatrix (); } - int len = strlen (cl_verstring->string); + int len = strlen (cl_verstring); gl_Draw_AltString (vid.conview->xlen - len * 8 - 11, lines - 14, - cl_verstring->string); + cl_verstring); qfglColor3ubv (color_white); } diff --git a/libs/video/renderer/gl/gl_dyn_lights.c b/libs/video/renderer/gl/gl_dyn_lights.c index 6af2287b2..02bbcb552 100644 --- a/libs/video/renderer/gl/gl_dyn_lights.c +++ b/libs/video/renderer/gl/gl_dyn_lights.c @@ -112,7 +112,7 @@ gl_R_RenderDlights (void) unsigned int i; dlight_t *l; - if (!gl_dlight_polyblend->int_val) + if (!gl_dlight_polyblend) return; qfglDepthMask (GL_FALSE); @@ -127,7 +127,7 @@ gl_R_RenderDlights (void) R_RenderDlight (l); } - if (!gl_dlight_smooth->int_val) + if (!gl_dlight_smooth) qfglShadeModel (GL_FLAT); qfglColor3ubv (color_white); qfglEnable (GL_TEXTURE_2D); diff --git a/libs/video/renderer/gl/gl_dyn_part.c b/libs/video/renderer/gl/gl_dyn_part.c index 151a2ed72..e6ede88fc 100644 --- a/libs/video/renderer/gl/gl_dyn_part.c +++ b/libs/video/renderer/gl/gl_dyn_part.c @@ -109,9 +109,17 @@ alloc_arrays (psystem_t *ps) } } +static void +gl_particles_f (void *data, const cvar_t *cvar) +{ + alloc_arrays (&r_psystem);//FIXME +} + void gl_R_InitParticles (void) { + Cvar_AddListener (Cvar_FindVar ("r_particles"), gl_particles_f, 0); + Cvar_AddListener (Cvar_FindVar ("r_particles_max"), gl_particles_f, 0); alloc_arrays (&r_psystem); } @@ -134,8 +142,8 @@ gl_R_DrawParticles (psystem_t *psystem) qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, particleVertexArray); minparticledist = DotProduct (r_refdef.frame.position, - r_refdef.frame.forward) + - r_particles_nearclip->value; + r_refdef.frame.forward) + + r_particles_nearclip; vacount = 0; VA = particleVertexArray; @@ -233,42 +241,6 @@ gl_R_DrawParticles (psystem_t *psystem) qfglDepthMask (GL_TRUE); } -static void -r_particles_nearclip_f (cvar_t *var) -{ - Cvar_SetValue (r_particles_nearclip, bound (r_nearclip->value, var->value, - r_farclip->value)); -} - -static void -r_particles_f (cvar_t *var) -{ - R_MaxParticlesCheck (var, r_particles_max); - alloc_arrays (&r_psystem); -} - -static void -r_particles_max_f (cvar_t *var) -{ - R_MaxParticlesCheck (r_particles, var); - alloc_arrays (&r_psystem); -} - -void -gl_R_Particles_Init_Cvars (void) -{ - r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, - "Toggles drawing of particles."); - r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, - r_particles_max_f, "Maximum amount of " - "particles to display. No maximum, minimum " - "is 0."); - r_particles_nearclip = Cvar_Get ("r_particles_nearclip", "32", - CVAR_ARCHIVE, r_particles_nearclip_f, - "Distance of the particle near clipping " - "plane from the player."); -} - psystem_t * __attribute__((const))//FIXME gl_ParticleSystem (void) { diff --git a/libs/video/renderer/gl/gl_fisheye.c b/libs/video/renderer/gl/gl_fisheye.c index bb0a34e21..2e1483214 100644 --- a/libs/video/renderer/gl/gl_fisheye.c +++ b/libs/video/renderer/gl/gl_fisheye.c @@ -156,10 +156,10 @@ gl_FisheyeScreen (framebuffer_t *fb) static float pfov = -1; if (pwidth != r_refdef.vrect.width || pheight != r_refdef.vrect.height - || pfov != scr_ffov->value) { + || pfov != scr_ffov) { pwidth = r_refdef.vrect.width; pheight = r_refdef.vrect.height; - pfov = scr_ffov->value; + pfov = scr_ffov; build_display_list (pwidth, pheight, pfov); } diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index a2ce210da..068f0ce00 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -452,7 +452,7 @@ do_subimage_2 (int i) static void GL_UploadLightmap (int i) { - switch (gl_lightmap_subimage->int_val) { + switch (gl_lightmap_subimage) { case 2: do_subimage_2 (i); break; @@ -526,15 +526,15 @@ gl_R_BlendLightmaps (void) } void -gl_overbright_f (cvar_t *var) +gl_overbright_f (void *data, const cvar_t *cvar) { int num; mod_brush_t *brush; - if (!var) + if (!cvar) return; - if (var->int_val) { + if (gl_overbright) { if (!gl_combine_capable && gl_mtex_capable) { Sys_Printf ("Warning: gl_overbright has no effect with " "gl_multitexture enabled if you don't have " @@ -547,7 +547,7 @@ gl_overbright_f (cvar_t *var) lm_src_blend = GL_DST_COLOR; lm_dest_blend = GL_SRC_COLOR; - switch (var->int_val) { + switch (gl_overbright) { case 2: lmshift = 9; gl_rgb_scale = 4.0; @@ -569,9 +569,6 @@ gl_overbright_f (cvar_t *var) gl_rgb_scale = 1.0; } - if (gl_multitexture) - gl_multitexture_f (gl_multitexture); - if (!gl_R_BuildLightMap) return; @@ -672,7 +669,7 @@ GL_BuildLightmaps (model_t **models, int num_models) qfglGenTextures (MAX_LIGHTMAPS, gl_lightmap_textures); } - switch (r_lightmap_components->int_val) { + switch (r_lightmap_components) { case 1: gl_internalformat = 1; gl_lightmap_format = GL_LUMINANCE; @@ -712,10 +709,7 @@ GL_BuildLightmaps (model_t **models, int num_models) gl_currentmodel = m; // non-bsp models don't have surfaces. for (unsigned i = 0; i < brush->numsurfaces; i++) { - if (brush->surfaces[i].flags & SURF_DRAWTURB) - continue; - if (gl_sky_divide->int_val && (brush->surfaces[i].flags & - SURF_DRAWSKY)) + if (brush->surfaces[i].flags & (SURF_DRAWTURB | SURF_DRAWSKY)) continue; GL_CreateSurfaceLightmap (brush, brush->surfaces + i); GL_BuildSurfaceDisplayList (brush, brush->surfaces + i); diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index a66cccbd1..7e28beea9 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -302,7 +302,7 @@ GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t *e) } vo->count = count; - if (!gl_lerp_anim->int_val) + if (!gl_lerp_anim) blend = 1.0; @@ -367,7 +367,7 @@ GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t *e) } vo->count = count; - if (!gl_lerp_anim->int_val) + if (!gl_lerp_anim) blend = 1.0; if (blend == 0.0) { @@ -467,7 +467,7 @@ gl_R_DrawAliasModel (entity_t *e) ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = minlight; } - if (gl_vector_light->int_val) { + if (gl_vector_light) { for (l = r_dlights, lnum = 0; lnum < r_maxdlights; lnum++, l++) { if (l->die >= vr_data.realtime) { VectorSubtract (l->origin, origin, dist); @@ -560,11 +560,11 @@ gl_R_DrawAliasModel (entity_t *e) // if the model has a colorised/external skin, use it, otherwise use // the skin embedded in the model data - if (e->renderer.skin && e->renderer.skin->texnum && !gl_nocolors->int_val) { + if (e->renderer.skin && e->renderer.skin->texnum && !gl_nocolors) { skin_t *skin = e->renderer.skin; texture = skin->texnum; - if (gl_fb_models->int_val) { + if (gl_fb_models) { fb_texture = skin->auxtex; } } else { @@ -574,7 +574,7 @@ gl_R_DrawAliasModel (entity_t *e) skindesc = R_AliasGetSkindesc (animation, e->renderer.skinnum, paliashdr); texture = skindesc->texnum; - if (gl_fb_models->int_val && !is_fullbright) { + if (gl_fb_models && !is_fullbright) { fb_texture = skindesc->fb_texnum; } } @@ -607,7 +607,7 @@ gl_R_DrawAliasModel (entity_t *e) if (is_fullbright) { qfglBindTexture (GL_TEXTURE_2D, texture); - if (gl_vector_light->int_val) { + if (gl_vector_light) { qfglDisable (GL_LIGHTING); if (!gl_tess) qfglDisable (GL_NORMALIZE); @@ -618,7 +618,7 @@ gl_R_DrawAliasModel (entity_t *e) else GL_DrawAliasFrame (vo); - if (gl_vector_light->int_val) { + if (gl_vector_light) { if (!gl_tess) qfglEnable (GL_NORMALIZE); qfglEnable (GL_LIGHTING); @@ -653,7 +653,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglBindTexture (GL_TEXTURE_2D, texture); GL_DrawAliasFrameTri (vo); - if (gl_vector_light->int_val) { + if (gl_vector_light) { qfglDisable (GL_LIGHTING); if (!gl_tess) qfglDisable (GL_NORMALIZE); @@ -664,7 +664,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglBindTexture (GL_TEXTURE_2D, fb_texture); GL_DrawAliasFrameTri (vo); - if (gl_vector_light->int_val) { + if (gl_vector_light) { qfglEnable (GL_LIGHTING); if (!gl_tess) qfglEnable (GL_NORMALIZE); @@ -673,7 +673,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglBindTexture (GL_TEXTURE_2D, texture); GL_DrawAliasFrame (vo); - if (gl_vector_light->int_val) { + if (gl_vector_light) { qfglDisable (GL_LIGHTING); if (!gl_tess) qfglDisable (GL_NORMALIZE); @@ -684,7 +684,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglBindTexture (GL_TEXTURE_2D, fb_texture); GL_DrawAliasFrame (vo); - if (gl_vector_light->int_val) { + if (gl_vector_light) { qfglEnable (GL_LIGHTING); if (!gl_tess) qfglEnable (GL_NORMALIZE); @@ -696,7 +696,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglPopMatrix (); // torches, grenades, and lightning bolts do not have shadows - if (r_shadows->int_val && model->shadow_alpha) { + if (r_shadows && model->shadow_alpha) { mat4f_t shadow_mat; qfglPushMatrix (); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index a3b19615b..720bf9469 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -81,10 +81,9 @@ glrmain_init (void) gldepthmax = 1; qfglDepthFunc (GL_LEQUAL); qfglDepthRange (gldepthmin, gldepthmax); - if (gl_multitexture) - gl_multitexture_f (gl_multitexture); - if (gl_overbright) - gl_overbright_f (gl_overbright); + + gl_overbright_f (0, 0); + gl_multitexture_f (0, 0); } void @@ -98,7 +97,7 @@ gl_R_RotateForEntity (entity_t *e) void gl_R_RenderEntities (entqueue_t *queue) { - if (!r_drawentities->int_val) + if (!r_drawentities) return; // LordHavoc: split into 3 loops to simplify state changes @@ -110,13 +109,13 @@ gl_R_RenderEntities (entqueue_t *queue) qfglDisable (GL_TEXTURE_2D); qglActiveTexture (gl_mtex_enum + 0); } - if (gl_affinemodels->int_val) + if (gl_affinemodels) qfglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); if (gl_tess) qfglEnable (GL_PN_TRIANGLES_ATI); qfglEnable (GL_CULL_FACE); - if (gl_vector_light->int_val) { + if (gl_vector_light) { qfglEnable (GL_LIGHTING); qfglEnable (GL_NORMALIZE); } else if (gl_tess) { @@ -134,13 +133,13 @@ gl_R_RenderEntities (entqueue_t *queue) if (gl_tess) qfglDisable (GL_PN_TRIANGLES_ATI); - if (gl_affinemodels->int_val) + if (gl_affinemodels) qfglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE); if (gl_mtex_active_tmus >= 2) { // FIXME: Ugly, but faster than cleaning // up in every R_DrawAliasModel()! qglActiveTexture (gl_mtex_enum + 1); qfglEnable (GL_TEXTURE_2D); - if (gl_combine_capable && gl_overbright->int_val) { + if (gl_combine_capable && gl_overbright) { qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); qfglTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); qfglTexEnvf (GL_TEXTURE_ENV, GL_RGB_SCALE, gl_rgb_scale); @@ -174,8 +173,8 @@ R_DrawViewModel (void) { entity_t *ent = vr_data.view_model; if (vr_data.inhibit_viewmodel - || !r_drawviewmodel->int_val - || !r_drawentities->int_val + || !r_drawviewmodel + || !r_drawentities || !ent->renderer.model) return; @@ -183,14 +182,14 @@ R_DrawViewModel (void) qfglDepthRange (gldepthmin, gldepthmin + 0.3 * (gldepthmax - gldepthmin)); qfglEnable (GL_CULL_FACE); - if (gl_vector_light->int_val) { + if (gl_vector_light) { qfglEnable (GL_LIGHTING); qfglEnable (GL_NORMALIZE); } else if (gl_tess) { qfglEnable (GL_NORMALIZE); } - if (gl_affinemodels->int_val) + if (gl_affinemodels) qfglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); if (gl_mtex_active_tmus >= 2) { qglActiveTexture (gl_mtex_enum + 1); @@ -207,7 +206,7 @@ R_DrawViewModel (void) // up in every R_DrawAliasModel()! qglActiveTexture (gl_mtex_enum + 1); qfglEnable (GL_TEXTURE_2D); - if (gl_combine_capable && gl_overbright->int_val) { + if (gl_combine_capable && gl_overbright) { qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); qfglTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); qfglTexEnvf (GL_TEXTURE_ENV, GL_RGB_SCALE, gl_rgb_scale); @@ -218,7 +217,7 @@ R_DrawViewModel (void) qglActiveTexture (gl_mtex_enum + 0); } - if (gl_affinemodels->int_val) + if (gl_affinemodels) qfglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE); qfglDisable (GL_NORMALIZE); @@ -257,7 +256,7 @@ R_SetupGL (void) qfglDisable (GL_ALPHA_TEST); qfglAlphaFunc (GL_GREATER, 0.5); qfglEnable (GL_DEPTH_TEST); - if (gl_dlight_smooth->int_val) + if (gl_dlight_smooth) qfglShadeModel (GL_SMOOTH); else qfglShadeModel (GL_FLAT); @@ -266,7 +265,7 @@ R_SetupGL (void) void gl_R_RenderView (void) { - if (r_norefresh->int_val) { + if (r_norefresh) { return; } if (!r_refdef.worldmodel) { diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index fc72d7f96..f7056bcfb 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -115,7 +115,6 @@ void gl_R_Init (void) { R_Init_Cvars (); - gl_R_Particles_Init_Cvars (); Cmd_AddCommand ("timerefresh", gl_R_TimeRefresh_f, "Tests the current refresh rate for the current location"); diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index bb3f4a958..c9c143c08 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -291,7 +291,7 @@ R_AddToLightmapChain (glbspctx_t *bctx, msurface_t *surf, instsurf_t *sc) if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { dynamic: - if (r_dynamic->int_val) { + if (r_dynamic) { gl_lightmap_modified[surf->lightmaptexturenum] = true; theRect = &gl_lightmap_rectchange[surf->lightmaptexturenum]; if (surf->light_t < theRect->t) { @@ -321,7 +321,7 @@ gl_R_DrawWaterSurfaces (void) int i; instsurf_t *s; msurface_t *surf; - float wateralpha = max (vr_data.min_wateralpha, r_wateralpha->value); + float wateralpha = max (vr_data.min_wateralpha, r_wateralpha); if (!waterchain) return; @@ -571,7 +571,7 @@ gl_R_DrawBrushModel (entity_t *e) } // calculate dynamic lighting for bmodel if it's not an instanced model - if (brush->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { + if (brush->firstmodelsurface != 0 && r_dlight_lightmap) { vec3_t lightorigin; for (unsigned k = 0; k < r_maxdlights; k++) { @@ -727,7 +727,7 @@ gl_R_DrawWorld (void) sky_chain = 0; sky_chain_tail = &sky_chain; - if (!gl_sky_clip->int_val) { + if (!gl_sky_clip) { gl_R_DrawSky (); } @@ -740,7 +740,7 @@ gl_R_DrawWorld (void) gl_R_DrawSkyChain (sky_chain); - if (r_drawentities->int_val) { + if (r_drawentities) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \ entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \ gl_R_DrawBrushModel (ent); @@ -748,7 +748,7 @@ gl_R_DrawWorld (void) } if (!Fog_GetDensity () - || (gl_fb_bmodels->int_val && gl_mtex_fullbright) + || (gl_fb_bmodels && gl_mtex_fullbright) || gl_mtex_active_tmus > 1) { // we have enough active TMUs to render everything in one go // or we're not doing fog @@ -757,7 +757,7 @@ gl_R_DrawWorld (void) if (gl_mtex_active_tmus <= 1) gl_R_BlendLightmaps (); - if (gl_fb_bmodels->int_val && !gl_mtex_fullbright) + if (gl_fb_bmodels && !gl_mtex_fullbright) R_RenderFullbrights (); } else { if (gl_mtex_active_tmus > 1) { @@ -877,7 +877,7 @@ GL_BuildSurfaceDisplayList (mod_brush_t *brush, msurface_t *surf) } // remove co-linear points - Ed - if (!gl_keeptjunctions->int_val && !(surf->flags & SURF_UNDERWATER)) { + if (!gl_keeptjunctions && !(surf->flags & SURF_UNDERWATER)) { for (i = 0; i < lnumverts; ++i) { vec3_t v1, v2; float *prev, *this, *next; diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index 47c6bc072..a66261294 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -115,7 +115,7 @@ gl_R_LoadSkys (const char *skyname) int i; // j if (!skyname || !*skyname) - skyname = r_skyname->string; + skyname = r_skyname; if (!*skyname || strcasecmp (skyname, "none") == 0) { gl_skyloaded = false; @@ -370,13 +370,13 @@ R_DrawSkyDome (void) qfglEnable (GL_BLEND); // clouds - if (gl_sky_multipass->int_val) { + if (gl_sky_multipass) { qfglBindTexture (GL_TEXTURE_2D, gl_alphaskytexture); speedscale = vr_data.realtime / 8.0; speedscale -= floor (speedscale); R_DrawSkyLayer (speedscale); } - if (gl_sky_debug->int_val) { + if (gl_sky_debug) { skydome_debug (); } } diff --git a/libs/video/renderer/gl/gl_sky_clip.c b/libs/video/renderer/gl/gl_sky_clip.c index fc1331dc8..e069c8768 100644 --- a/libs/video/renderer/gl/gl_sky_clip.c +++ b/libs/video/renderer/gl/gl_sky_clip.c @@ -750,7 +750,7 @@ draw_id_sky_polys (const instsurf_t *sky_chain) sc = sc->tex_chain; } - if (gl_sky_multipass->int_val) { + if (gl_sky_multipass) { sc = sky_chain; speedscale = vr_data.realtime / 8; @@ -797,19 +797,19 @@ draw_z_sky_polys (const instsurf_t *sky_chain) void gl_R_DrawSkyChain (const instsurf_t *sky_chain) { - if (gl_sky_clip->int_val > 2) { + if (gl_sky_clip > 2) { draw_black_sky_polys (sky_chain); return; } if (gl_skyloaded) { - if (gl_sky_clip->int_val) { + if (gl_sky_clip) { draw_skybox_sky_polys (sky_chain); } draw_z_sky_polys (sky_chain); - } else if (gl_sky_clip->int_val == 2) { + } else if (gl_sky_clip == 2) { draw_id_sky_polys (sky_chain); - } else if (gl_sky_clip->int_val) { + } else if (gl_sky_clip) { // XXX not properly implemented draw_skydome_sky_polys (sky_chain); //draw_z_sky_polys (sky_chain); @@ -817,11 +817,11 @@ gl_R_DrawSkyChain (const instsurf_t *sky_chain) draw_z_sky_polys (sky_chain); } - if (gl_sky_debug->int_val) { + if (gl_sky_debug) { const instsurf_t *sc; qfglDisable (GL_TEXTURE_2D); - if (gl_sky_debug->int_val & 1) { + if (gl_sky_debug & 1) { sc = sky_chain; qfglColor3ub (255, 255, 255); while (sc) { @@ -846,7 +846,7 @@ gl_R_DrawSkyChain (const instsurf_t *sky_chain) sc = sc->tex_chain; } } - if (gl_sky_debug->int_val & 2) { + if (gl_sky_debug & 2) { sc = sky_chain; qfglColor3ub (0, 255, 0); qfglBegin (GL_POINTS); @@ -876,7 +876,7 @@ gl_R_DrawSkyChain (const instsurf_t *sky_chain) } qfglEnd (); } - if (gl_sky_debug->int_val & 4) { + if (gl_sky_debug & 4) { if (gl_skyloaded) { int i, j; diff --git a/libs/video/renderer/gl/gl_textures.c b/libs/video/renderer/gl/gl_textures.c index 9beb146dc..e0c7d893d 100644 --- a/libs/video/renderer/gl/gl_textures.c +++ b/libs/video/renderer/gl/gl_textures.c @@ -374,11 +374,11 @@ GL_Upload32 (unsigned int *data, int width, int height, qboolean mipmap, for (scaled_width = 1; scaled_width < width; scaled_width <<= 1); for (scaled_height = 1; scaled_height < height; scaled_height <<= 1); - scaled_width >>= gl_picmip->int_val; - scaled_height >>= gl_picmip->int_val; + scaled_width >>= gl_picmip; + scaled_height >>= gl_picmip; - scaled_width = min (scaled_width, gl_max_size->int_val); - scaled_height = min (scaled_height, gl_max_size->int_val); + scaled_width = min (scaled_width, gl_max_size); + scaled_height = min (scaled_height, gl_max_size); if (!(scaled = malloc (scaled_width * scaled_height * sizeof (GLuint)))) Sys_Error ("GL_LoadTexture: too big"); @@ -421,7 +421,7 @@ GL_Upload32 (unsigned int *data, int width, int height, qboolean mipmap, } else { qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); - if (gl_picmip->int_val) + if (gl_picmip) qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); else @@ -452,11 +452,11 @@ GL_Upload8_EXT (const byte *data, int width, int height, qboolean mipmap, for (scaled_width = 1; scaled_width < width; scaled_width <<= 1); for (scaled_height = 1; scaled_height < height; scaled_height <<= 1); - scaled_width >>= gl_picmip->int_val; - scaled_height >>= gl_picmip->int_val; + scaled_width >>= gl_picmip; + scaled_height >>= gl_picmip; - scaled_width = min (scaled_width, gl_max_size->int_val); - scaled_height = min (scaled_height, gl_max_size->int_val); + scaled_width = min (scaled_width, gl_max_size); + scaled_height = min (scaled_height, gl_max_size); if (!(scaled = malloc (scaled_width * scaled_height))) Sys_Error ("GL_LoadTexture: too big"); @@ -498,7 +498,7 @@ GL_Upload8_EXT (const byte *data, int width, int height, qboolean mipmap, } else { qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max); - if (gl_picmip->int_val) + if (gl_picmip) qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); else diff --git a/libs/video/renderer/gl/gl_warp.c b/libs/video/renderer/gl/gl_warp.c index 4ae963cf7..f7a0b9ee4 100644 --- a/libs/video/renderer/gl/gl_warp.c +++ b/libs/video/renderer/gl/gl_warp.c @@ -70,11 +70,11 @@ GL_EmitWaterPolys (msurface_t *surf) t = (v[4] + os) * (1.0 / 64.0); qfglTexCoord2f (s, t); - if (r_waterripple->value != 0) { + if (r_waterripple != 0) { vec3_t nv; VectorCopy (v, nv); - nv[2] += r_waterripple->value * os * ot * (1.0 / 64.0); + nv[2] += r_waterripple * os * ot * (1.0 / 64.0); qfglVertex3fv (nv); } else qfglVertex3fv (v); diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index e0e5f5231..4ff4b85fe 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -112,73 +112,358 @@ int gl_tess; // GL_LIGHT int gl_max_lights; -cvar_t *gl_anisotropy; -cvar_t *gl_fb_bmodels; -cvar_t *gl_finish; -cvar_t *gl_max_size; -cvar_t *gl_multitexture; -cvar_t *gl_tessellate; -cvar_t *gl_textures_bgra; -cvar_t *gl_vaelements_max; -cvar_t *gl_vector_light; -cvar_t *gl_screenshot_byte_swap; +float gl_anisotropy; +static cvar_t gl_anisotropy_cvar = { + .name = "gl_anisotropy", + .description = 0, + .default_value = "1.0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &gl_anisotropy }, +}; +int gl_fb_bmodels; +static cvar_t gl_fb_bmodels_cvar = { + .name = "gl_fb_bmodels", + .description = + "Toggles fullbright color support for bmodels", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_fb_bmodels }, +}; +int gl_finish; +static cvar_t gl_finish_cvar = { + .name = "gl_finish", + .description = + "wait for rendering to finish", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_finish }, +}; +int gl_max_size; +static cvar_t gl_max_size_cvar = { + .name = "gl_max_size", + .description = + "Texture dimension", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_max_size }, +}; +int gl_multitexture; +static cvar_t gl_multitexture_cvar = { + .name = "gl_multitexture", + .description = + "Use multitexture when available.", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_multitexture }, +}; +int gl_tessellate; +static cvar_t gl_tessellate_cvar = { + .name = "gl_tessellate", + .description = 0, + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_tessellate }, +}; +int gl_textures_bgra; +static cvar_t gl_textures_bgra_cvar = { + .name = "gl_textures_bgra", + .description = + "If set to 1, try to use BGR & BGRA textures instead of RGB & RGBA.", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &gl_textures_bgra }, +}; +int gl_vaelements_max; +static cvar_t gl_vaelements_max_cvar = { + .name = "gl_vaelements_max", + .description = + "Limit the vertex array size for buggy drivers. 0 (default) uses " + "driver provided limit, -1 disables use of vertex arrays.", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &gl_vaelements_max }, +}; +int gl_vector_light; +static cvar_t gl_vector_light_cvar = { + .name = "gl_vector_light", + .description = + "Enable use of GL vector lighting. 0 = flat lighting.", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_vector_light }, +}; +int gl_screenshot_byte_swap; +static cvar_t gl_screenshot_byte_swap_cvar = { + .name = "gl_screenshot_byte_swap", + .description = + "Swap the bytes for gl screenshots. Needed if you get screenshots with" + " red and blue swapped.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_screenshot_byte_swap }, +}; -cvar_t *gl_affinemodels; -cvar_t *gl_clear; -cvar_t *gl_conspin; -cvar_t *gl_constretch; -cvar_t *gl_dlight_polyblend; -cvar_t *gl_dlight_smooth; -cvar_t *gl_driver; -cvar_t *gl_fb_models; -cvar_t *gl_keeptjunctions; -cvar_t *gl_lerp_anim; -cvar_t *gl_lightmap_align; -cvar_t *gl_lightmap_subimage; -cvar_t *gl_nocolors; -cvar_t *gl_overbright; -cvar_t *gl_particle_mip; -cvar_t *gl_particle_size; -cvar_t *gl_picmip; -cvar_t *gl_playermip; -cvar_t *gl_reporttjunctions; -cvar_t *gl_sky_clip; -cvar_t *gl_sky_debug; -cvar_t *gl_sky_multipass; -cvar_t *gl_texsort; -cvar_t *gl_triplebuffer; -static cvar_t *vid_use8bit; +int gl_affinemodels; +static cvar_t gl_affinemodels_cvar = { + .name = "gl_affinemodels", + .description = + "Makes texture rendering quality better if set to 1", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_affinemodels }, +}; +int gl_clear; +static cvar_t gl_clear_cvar = { + .name = "gl_clear", + .description = + "Set to 1 to make background black. Useful for removing HOM effect", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_clear }, +}; +float gl_conspin; +static cvar_t gl_conspin_cvar = { + .name = "gl_conspin", + .description = + "speed at which the console spins", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &gl_conspin }, +}; +int gl_constretch; +static cvar_t gl_constretch_cvar = { + .name = "gl_constretch", + .description = + "toggle console between slide and stretch", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_constretch }, +}; +int gl_dlight_polyblend; +static cvar_t gl_dlight_polyblend_cvar = { + .name = "gl_dlight_polyblend", + .description = + "Set to 1 to use a dynamic light effect faster on GL", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_dlight_polyblend }, +}; +int gl_dlight_smooth; +static cvar_t gl_dlight_smooth_cvar = { + .name = "gl_dlight_smooth", + .description = + "Smooth dynamic vertex lighting", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_dlight_smooth }, +}; +int gl_fb_models; +static cvar_t gl_fb_models_cvar = { + .name = "gl_fb_models", + .description = + "Toggles fullbright color support for models", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_fb_models }, +}; +int gl_keeptjunctions; +static cvar_t gl_keeptjunctions_cvar = { + .name = "gl_keeptjunctions", + .description = + "Set to 0 to turn off colinear vertexes upon level load.", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_keeptjunctions }, +}; +int gl_lerp_anim; +static cvar_t gl_lerp_anim_cvar = { + .name = "gl_lerp_anim", + .description = + "Toggles model animation interpolation", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_lerp_anim }, +}; +int gl_lightmap_align; +static cvar_t gl_lightmap_align_cvar = { + .name = "gl_lightmap_align", + .description = + "Workaround for nvidia slow path. Set to 4 or 16 if you have an nvidia" + " 3d accelerator, set to 1 otherwise.", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_lightmap_align }, +}; +int gl_lightmap_subimage; +static cvar_t gl_lightmap_subimage_cvar = { + .name = "gl_lightmap_subimage", + .description = + "Lightmap Update method. Default 2 updates a minimum 'dirty rectangle'" + " around the area changed. 1 updates every line that changed. 0 " + "updates the entire lightmap.", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_lightmap_subimage }, +}; +int gl_nocolors; +static cvar_t gl_nocolors_cvar = { + .name = "gl_nocolors", + .description = + "Set to 1, turns off all player colors", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_nocolors }, +}; +int gl_overbright; +static cvar_t gl_overbright_cvar = { + .name = "gl_overbright", + .description = + "Darken lightmaps so that dynamic lights can be overbright. 1 = 0.75 " + "brightness, 2 = 0.5 brightness.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_overbright }, +}; +int gl_particle_mip; +static cvar_t gl_particle_mip_cvar = { + .name = "gl_particle_mip", + .description = + "Toggles particle texture mipmapping.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_particle_mip }, +}; +int gl_particle_size; +static cvar_t gl_particle_size_cvar = { + .name = "gl_particle_size", + .description = + "Vertical and horizontal size of particle textures as a power of 2. " + "Default is 5 (32 texel square).", + .default_value = "5", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_particle_size }, +}; +int gl_picmip; +static cvar_t gl_picmip_cvar = { + .name = "gl_picmip", + .description = + "Dimensions of textures. 0 is normal, 1 is half, 2 is 1/4", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_picmip }, +}; +int gl_playermip; +static cvar_t gl_playermip_cvar = { + .name = "gl_playermip", + .description = + "Detail of player skins. 0 best, 4 worst.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_playermip }, +}; +int gl_reporttjunctions; +static cvar_t gl_reporttjunctions_cvar = { + .name = "gl_reporttjunctions", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_reporttjunctions }, +}; +int gl_sky_clip; +static cvar_t gl_sky_clip_cvar = { + .name = "gl_sky_clip", + .description = + "controls amount of sky overdraw", + .default_value = "2", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_sky_clip }, +}; +int gl_sky_debug; +static cvar_t gl_sky_debug_cvar = { + .name = "gl_sky_debug", + .description = + "debugging `info' for sky clipping", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_sky_debug }, +}; +int gl_sky_divide; +static cvar_t gl_sky_divide_cvar = { + .name = "gl_sky_divide", + .description = + "subdivide sky polys", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_sky_divide }, +}; +int gl_sky_multipass; +static cvar_t gl_sky_multipass_cvar = { + .name = "gl_sky_multipass", + .description = + "controls whether the skydome is single or double pass", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_sky_multipass }, +}; +int gl_texsort; +static cvar_t gl_texsort_cvar = { + .name = "gl_texsort", + .description = + "None", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_texsort }, +}; +int gl_triplebuffer; +static cvar_t gl_triplebuffer_cvar = { + .name = "gl_triplebuffer", + .description = + "Set to 1 by default. Fixes status bar flicker on some hardware", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &gl_triplebuffer }, +}; +static int vid_use8bit; +static cvar_t vid_use8bit_cvar = { + .name = "vid_use8bit", + .description = + "Use 8-bit shared palettes.", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &vid_use8bit }, +}; static void -gl_triplebuffer_f (cvar_t *var) +gl_triplebuffer_f (void *data, const cvar_t *cvar) { - vid.numpages = var->int_val ? 3 : 2; + vid.numpages = gl_triplebuffer ? 3 : 2; } static void -gl_max_size_f (cvar_t *var) +gl_max_size_f (void *data, const cvar_t *cvar) { GLint texSize; - if (!var) + if (!cvar) return; // Check driver's max texture size qfglGetIntegerv (GL_MAX_TEXTURE_SIZE, &texSize); - if (var->int_val < 1) { - Cvar_SetValue (var, texSize); + if (gl_max_size < 1) { + gl_max_size = texSize; } else { - Cvar_SetValue (var, bound (1, var->int_val, texSize)); + gl_max_size = bound (1, gl_max_size, texSize); } } static void -gl_textures_bgra_f (cvar_t *var) +gl_textures_bgra_f (void *data, const cvar_t *cvar) { - if (!var) + if (!cvar) return; - if (var->int_val && gl_bgra_capable) { + if (gl_textures_bgra && gl_bgra_capable) { gl_use_bgra = 1; } else { gl_use_bgra = 0; @@ -186,12 +471,12 @@ gl_textures_bgra_f (cvar_t *var) } static void -gl_fb_bmodels_f (cvar_t *var) +gl_fb_bmodels_f (void *data, const cvar_t *cvar) { - if (!var) + if (!cvar) return; - if (var->int_val && gl_mtex_tmus >= 3) { + if (gl_fb_bmodels && gl_mtex_tmus >= 3) { gl_mtex_fullbright = true; } else { gl_mtex_fullbright = false; @@ -199,16 +484,13 @@ gl_fb_bmodels_f (cvar_t *var) } void -gl_multitexture_f (cvar_t *var) +gl_multitexture_f (void *data, const cvar_t *cvar) { - if (!var) - return; - - if (var->int_val && gl_mtex_capable) { + if (gl_multitexture && gl_mtex_capable) { gl_mtex_active_tmus = gl_mtex_tmus; if (gl_fb_bmodels) { - if (gl_fb_bmodels->int_val) { + if (gl_fb_bmodels) { if (gl_mtex_tmus >= 3) { gl_mtex_fullbright = true; @@ -231,7 +513,7 @@ gl_multitexture_f (cvar_t *var) qglActiveTexture (gl_mtex_enum + 1); qfglEnable (GL_TEXTURE_2D); if (gl_overbright) { - if (gl_combine_capable && gl_overbright->int_val) { + if (gl_combine_capable && gl_overbright) { qfglTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); qfglTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); qfglTexEnvf (GL_TEXTURE_ENV, GL_RGB_SCALE, gl_rgb_scale); @@ -252,19 +534,19 @@ gl_multitexture_f (cvar_t *var) } static void -gl_screenshot_byte_swap_f (cvar_t *var) +gl_screenshot_byte_swap_f (void *data, const cvar_t *cvar) { - if (var) + if (cvar) qfglPixelStorei (GL_PACK_SWAP_BYTES, - var->int_val ? GL_TRUE : GL_FALSE); + gl_screenshot_byte_swap ? GL_TRUE : GL_FALSE); } static void -gl_anisotropy_f (cvar_t * var) +gl_anisotropy_f (void *data, const cvar_t *var) { if (gl_Anisotropy) { if (var) - gl_aniso = (bound (1.0, var->value, aniso_max)); + gl_aniso = (bound (1.0, gl_anisotropy, aniso_max)); else gl_aniso = 1.0; } else { @@ -278,11 +560,11 @@ gl_anisotropy_f (cvar_t * var) } static void -gl_tessellate_f (cvar_t * var) +gl_tessellate_f (void *data, const cvar_t *var) { if (TruForm) { if (var) - gl_tess = (bound (0, var->int_val, tess_max)); + gl_tess = (bound (0, gl_tessellate, tess_max)); else gl_tess = 0; qfglPNTrianglesiATI (GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_tess); @@ -296,117 +578,69 @@ gl_tessellate_f (cvar_t * var) } static void -gl_vaelements_max_f (cvar_t *var) +gl_vaelements_max_f (void *data, const cvar_t *cvar) { - if (var->int_val) - vaelements = min (var->int_val, driver_vaelements); + if (gl_vaelements_max) + vaelements = min (gl_vaelements_max, driver_vaelements); else vaelements = driver_vaelements; } +static void +gl_sky_divide_f (void *data, const cvar_t *cvar) +{ + mod_sky_divide = gl_sky_divide; +} + static void GL_Common_Init_Cvars (void) { - vid_use8bit = Cvar_Get ("vid_use8bit", "0", CVAR_ROM, NULL, "Use 8-bit " - "shared palettes."); - gl_textures_bgra = Cvar_Get ("gl_textures_bgra", "0", CVAR_ROM, - gl_textures_bgra_f, "If set to 1, try to use " - "BGR & BGRA textures instead of RGB & RGBA."); - gl_fb_bmodels = Cvar_Get ("gl_fb_bmodels", "1", CVAR_ARCHIVE, - gl_fb_bmodels_f, "Toggles fullbright color " - "support for bmodels"); - gl_finish = Cvar_Get ("gl_finish", "1", CVAR_ARCHIVE, NULL, - "wait for rendering to finish"); - gl_max_size = Cvar_Get ("gl_max_size", "0", CVAR_NONE, gl_max_size_f, - "Texture dimension"); - gl_multitexture = Cvar_Get ("gl_multitexture", "1", CVAR_ARCHIVE, - gl_multitexture_f, "Use multitexture when " - "available."); - gl_screenshot_byte_swap = - Cvar_Get ("gl_screenshot_byte_swap", "0", CVAR_NONE, - gl_screenshot_byte_swap_f, "Swap the bytes for gl " - "screenshots. Needed if you get screenshots with red and " - "blue swapped."); - gl_anisotropy = - Cvar_Get ("gl_anisotropy", "1.0", CVAR_NONE, gl_anisotropy_f, - nva ("Specifies degree of anisotropy, from 1.0 to %f. " - "Higher anisotropy means less distortion of textures " - "at shallow angles to the viewer.", aniso_max)); - gl_tessellate = - Cvar_Get ("gl_tessellate", "0", CVAR_NONE, gl_tessellate_f, - nva ("Specifies tessellation level from 0 to %i. Higher " - "tessellation level means more triangles.", tess_max)); - gl_vaelements_max = Cvar_Get ("gl_vaelements_max", "0", CVAR_ROM, - gl_vaelements_max_f, - "Limit the vertex array size for buggy " - "drivers. 0 (default) uses driver provided " - "limit, -1 disables use of vertex arrays."); - gl_vector_light = Cvar_Get ("gl_vector_light", "1", CVAR_NONE, NULL, - "Enable use of GL vector lighting. 0 = flat lighting."); - gl_affinemodels = Cvar_Get ("gl_affinemodels", "0", CVAR_ARCHIVE, NULL, - "Makes texture rendering quality better if " - "set to 1"); - gl_clear = Cvar_Get ("gl_clear", "0", CVAR_NONE, NULL, "Set to 1 to make " - "background black. Useful for removing HOM effect"); - gl_conspin = Cvar_Get ("gl_conspin", "0", CVAR_ARCHIVE, NULL, - "speed at which the console spins"); - gl_constretch = Cvar_Get ("gl_constretch", "0", CVAR_ARCHIVE, NULL, - "toggle console between slide and stretch"); - gl_dlight_polyblend = Cvar_Get ("gl_dlight_polyblend", "0", CVAR_ARCHIVE, - NULL, "Set to 1 to use a dynamic light " - "effect faster on GL"); - gl_dlight_smooth = Cvar_Get ("gl_dlight_smooth", "1", CVAR_ARCHIVE, NULL, - "Smooth dynamic vertex lighting"); - gl_fb_models = Cvar_Get ("gl_fb_models", "1", CVAR_ARCHIVE, NULL, - "Toggles fullbright color support for models"); - gl_keeptjunctions = Cvar_Get ("gl_keeptjunctions", "1", CVAR_ARCHIVE, NULL, - "Set to 0 to turn off colinear vertexes " - "upon level load."); - gl_lerp_anim = Cvar_Get ("gl_lerp_anim", "1", CVAR_ARCHIVE, NULL, - "Toggles model animation interpolation"); + Cvar_Register (&vid_use8bit_cvar, 0, 0); + Cvar_Register (&gl_textures_bgra_cvar, gl_textures_bgra_f, 0); + Cvar_Register (&gl_fb_bmodels_cvar, gl_fb_bmodels_f, 0); + Cvar_Register (&gl_finish_cvar, 0, 0); + Cvar_Register (&gl_max_size_cvar, gl_max_size_f, 0); + Cvar_Register (&gl_multitexture_cvar, gl_multitexture_f, 0); + Cvar_Register (&gl_screenshot_byte_swap_cvar, gl_screenshot_byte_swap_f, 0); + Cvar_Register (&gl_anisotropy_cvar, gl_anisotropy_f, 0); + gl_anisotropy_cvar.description = nva ( + "Specifies degree of anisotropy, from 1.0 to %f. Higher anisotropy " + "means less distortion of textures at shallow angles to the viewer.", + aniso_max); + Cvar_Register (&gl_tessellate_cvar, gl_tessellate_f, 0); + gl_tessellate_cvar.description = nva ( + "Specifies tessellation level from 0 to %i. Higher tessellation level " + "means more triangles.", + tess_max); + Cvar_Register (&gl_vaelements_max_cvar, gl_vaelements_max_f, 0); + Cvar_Register (&gl_vector_light_cvar, 0, 0); + Cvar_Register (&gl_affinemodels_cvar, 0, 0); + Cvar_Register (&gl_clear_cvar, 0, 0); + Cvar_Register (&gl_conspin_cvar, 0, 0); + Cvar_Register (&gl_constretch_cvar, 0, 0); + Cvar_Register (&gl_dlight_polyblend_cvar, 0, 0); + Cvar_Register (&gl_dlight_smooth_cvar, 0, 0); + Cvar_Register (&gl_fb_models_cvar, 0, 0); + Cvar_Register (&gl_keeptjunctions_cvar, 0, 0); + Cvar_Register (&gl_lerp_anim_cvar, 0, 0); - gl_lightmap_align = Cvar_Get ("gl_lightmap_align", "1", CVAR_NONE, NULL, - "Workaround for nvidia slow path. Set to 4 " - "or 16 if you have an nvidia 3d " - "accelerator, set to 1 otherwise."); - gl_lightmap_subimage = Cvar_Get ("gl_lightmap_subimage", "1", CVAR_NONE, - NULL, "Lightmap Update method. Default 2 " - "updates a minimum 'dirty rectangle' " - "around the area changed. 1 updates " - "every line that changed. 0 updates the " - "entire lightmap."); - gl_nocolors = Cvar_Get ("gl_nocolors", "0", CVAR_NONE, NULL, - "Set to 1, turns off all player colors"); - gl_overbright = Cvar_Get ("gl_overbright", "0", CVAR_NONE, - gl_overbright_f, "Darken lightmaps so that " - "dynamic lights can be overbright. 1 = 0.75 " - "brightness, 2 = 0.5 brightness."); - gl_particle_mip = Cvar_Get ("gl_particle_mip", "0", CVAR_NONE, NULL, - "Toggles particle texture mipmapping."); - gl_particle_size = Cvar_Get ("gl_particle_size", "5", CVAR_NONE, NULL, - "Vertical and horizontal size of particle " - "textures as a power of 2. Default is 5 " - "(32 texel square)."); - gl_picmip = Cvar_Get ("gl_picmip", "0", CVAR_NONE, NULL, "Dimensions of " - "textures. 0 is normal, 1 is half, 2 is 1/4"); - gl_playermip = Cvar_Get ("gl_playermip", "0", CVAR_NONE, NULL, - "Detail of player skins. 0 best, 4 worst."); - gl_reporttjunctions = Cvar_Get ("gl_reporttjunctions", "0", CVAR_NONE, - NULL, "None"); - gl_sky_clip = Cvar_Get ("gl_sky_clip", "2", CVAR_ARCHIVE, NULL, - "controls amount of sky overdraw"); - gl_sky_debug = Cvar_Get ("gl_sky_debug", "0", CVAR_NONE, NULL, - "debugging `info' for sky clipping"); - gl_sky_divide = Cvar_Get ("gl_sky_divide", "1", CVAR_ARCHIVE, NULL, - "subdivide sky polys"); - gl_sky_multipass = Cvar_Get ("gl_sky_multipass", "1", CVAR_ARCHIVE, NULL, - "controls whether the skydome is single or " - "double pass"); - gl_texsort = Cvar_Get ("gl_texsort", "1", CVAR_NONE, NULL, "None"); - gl_triplebuffer = Cvar_Get ("gl_triplebuffer", "1", CVAR_ARCHIVE, - gl_triplebuffer_f, - "Set to 1 by default. Fixes status bar " - "flicker on some hardware"); + Cvar_Register (&gl_lightmap_align_cvar, 0, 0); + Cvar_Register (&gl_lightmap_subimage_cvar, 0, 0); + Cvar_Register (&gl_nocolors_cvar, 0, 0); + Cvar_Register (&gl_overbright_cvar, gl_overbright_f, 0); + Cvar_Register (&gl_particle_mip_cvar, 0, 0); + Cvar_Register (&gl_particle_size_cvar, 0, 0); + Cvar_Register (&gl_picmip_cvar, 0, 0); + Cvar_Register (&gl_playermip_cvar, 0, 0); + Cvar_Register (&gl_reporttjunctions_cvar, 0, 0); + Cvar_Register (&gl_sky_clip_cvar, 0, 0); + Cvar_Register (&gl_sky_debug_cvar, 0, 0); + Cvar_Register (&gl_sky_divide_cvar, gl_sky_divide_f, 0); + Cvar_Register (&gl_sky_multipass_cvar, 0, 0); + Cvar_Register (&gl_texsort_cvar, 0, 0); + Cvar_Register (&gl_triplebuffer_cvar, gl_triplebuffer_f, 0); + + Cvar_AddListener (&gl_overbright_cvar, gl_multitexture_f, 0); } static void @@ -689,7 +923,7 @@ static void VID_Init8bitPalette (void) { Sys_MaskPrintf (SYS_vid, "Checking for 8-bit extension: "); - if (vid_use8bit->int_val) { + if (vid_use8bit) { Tdfx_Init8bitPalette (); Shared_Init8bitPalette (); if (!vr_data.vid->is8bit) diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 3ecf33bc6..efb814251 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -186,7 +186,7 @@ set_arrays (const shaderparam_t *vert, const shaderparam_t *norm, { byte *pose_offs = (byte *) pose; - if (developer->int_val & SYS_glsl) { + if (developer & SYS_glsl) { GLint size; qfeglGetBufferParameteriv (GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 7ae7dec1e..cfdcec3b9 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -374,7 +374,7 @@ update_lightmap (glslbspctx_t *bctx, msurface_t *surf) if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { dynamic: - if (r_dynamic->int_val) + if (r_dynamic) glsl_R_BuildLightMap (bctx->entity->transform, bctx->brush, surf); } } @@ -698,7 +698,7 @@ R_DrawBrushModel (entity_t *e) } // calculate dynamic lighting for bmodel if it's not an instanced model - if (brush->firstmodelsurface != 0 && r_dlight_lightmap->int_val) { + if (brush->firstmodelsurface != 0 && r_dlight_lightmap) { vec3_t lightorigin; for (k = 0; k < r_maxdlights; k++) { @@ -936,7 +936,7 @@ turb_begin (void) { quat_t fog; - default_color[3] = bound (0, r_wateralpha->value, 1); + default_color[3] = bound (0, r_wateralpha, 1); QuatCopy (default_color, last_color); qfeglVertexAttrib4fv (quake_bsp.color.location, default_color); @@ -1146,7 +1146,7 @@ glsl_R_DrawWorld (void) bctx.entity = &worldent; R_VisitWorldNodes (&bctx); - if (r_drawentities->int_val) { + if (r_drawentities) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; R_DrawBrushModel (ent); @@ -1405,7 +1405,7 @@ glsl_R_LoadSkys (const char *sky) }; if (!sky || !*sky) - sky = r_skyname->string; + sky = r_skyname; if (!*sky || !strcasecmp (sky, "none")) { skybox_loaded = false; diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 47b99575b..1b85edd87 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -110,7 +110,15 @@ static qpic_t *crosshair_pic; static qpic_t *white_pic; static qpic_t *backtile_pic; static hashtab_t *pic_cache; -static cvar_t *glsl_conback_texnum; +static int glsl_conback_texnum; +static cvar_t glsl_conback_texnum_cvar = { + .name = "glsl_conback_texnum", + .description = + "bind conback to this texture for debugging", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &glsl_conback_texnum }, +}; static qpic_t * make_glpic (const char *name, qpic_t *p) @@ -377,7 +385,7 @@ glsl_Draw_Init (void) QFS_GamedirCallback (Draw_ClearCache); //FIXME temporary work around for the timing of cvar creation and palette //loading - crosshaircolor->callback (crosshaircolor); + //crosshaircolor->callback (crosshaircolor); draw_queue = dstring_new (); @@ -427,9 +435,7 @@ glsl_Draw_Init (void) //FIXME qfeglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //FIXME qfeglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glsl_conback_texnum = Cvar_Get ("glsl_conback_texnum", "0", CVAR_NONE, - NULL, "bind conback to this texture for " - "debugging"); + Cvar_Register (&glsl_conback_texnum_cvar, 0, 0); } static inline void @@ -568,10 +574,10 @@ glsl_Draw_Crosshair (void) { int x, y; - x = vid.conview->xlen / 2 + cl_crossx->int_val; - y = vid.conview->ylen / 2 + cl_crossy->int_val; + x = vid.conview->xlen / 2 + cl_crossx; + y = vid.conview->ylen / 2 + cl_crossy; - glsl_Draw_CrosshairAt (crosshair->int_val, x, y); + glsl_Draw_CrosshairAt (crosshair, x, y); } void @@ -621,8 +627,8 @@ glsl_Draw_ConsoleBackground (int lines, byte alpha) QuatCopy (color, verts[4].color); QuatCopy (color, verts[5].color); - if (glsl_conback_texnum->int_val) - qfeglBindTexture (GL_TEXTURE_2D, glsl_conback_texnum->int_val); + if (glsl_conback_texnum) + qfeglBindTexture (GL_TEXTURE_2D, glsl_conback_texnum); else qfeglBindTexture (GL_TEXTURE_2D, conback_texture); diff --git a/libs/video/renderer/glsl/glsl_fisheye.c b/libs/video/renderer/glsl/glsl_fisheye.c index 2635d8ffe..edd7c9871 100644 --- a/libs/video/renderer/glsl/glsl_fisheye.c +++ b/libs/video/renderer/glsl/glsl_fisheye.c @@ -104,7 +104,7 @@ glsl_FisheyeScreen (framebuffer_t *fb) { qfeglUseProgram (fisheye.program); - qfeglUniform1f (fisheye.fov.location, scr_ffov->value * M_PI / 360); + qfeglUniform1f (fisheye.fov.location, scr_ffov * M_PI / 360); qfeglUniform1f (fisheye.aspect.location, (float) r_refdef.vrect.height / r_refdef.vrect.width); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 892f8d235..a2fa1f8f6 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -89,7 +89,7 @@ glsl_R_RenderEntities (entqueue_t *queue) { int begun; - if (!r_drawentities->int_val) + if (!r_drawentities) return; #define RE_LOOP(type_name, Type) \ do { \ @@ -117,8 +117,8 @@ R_DrawViewModel (void) { entity_t *ent = vr_data.view_model; if (vr_data.inhibit_viewmodel - || !r_drawviewmodel->int_val - || !r_drawentities->int_val + || !r_drawviewmodel + || !r_drawentities || !ent->renderer.model) return; @@ -173,7 +173,6 @@ glsl_R_Init (void) Cmd_AddCommand ("timerefresh", glsl_R_TimeRefresh_f, "Test the current refresh rate for the current location."); R_Init_Cvars (); - glsl_R_Particles_Init_Cvars (); glsl_Draw_Init (); SCR_Init (); glsl_R_InitBsp (); diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index a4caefa6f..fd1993bee 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -138,6 +138,7 @@ alloc_arrays (psystem_t *ps) maxparticles = ps->maxparticles; if (particleVertexArray) free (particleVertexArray); + printf ("alloc_arrays: %d\n", ps->maxparticles); particleVertexArray = calloc (ps->maxparticles * 4, sizeof (partvert_t)); @@ -155,6 +156,12 @@ alloc_arrays (psystem_t *ps) } } +static void +glsl_particles_f (void *data, const cvar_t *cvar) +{ + alloc_arrays (&r_psystem);//FIXME +} + void glsl_R_InitParticles (void) { @@ -165,6 +172,9 @@ glsl_R_InitParticles (void) byte data[64][64][2]; tex_t *tex; + Cvar_AddListener (Cvar_FindVar ("r_particles"), glsl_particles_f, 0); + Cvar_AddListener (Cvar_FindVar ("r_particles_max"), glsl_particles_f, 0); + qfeglEnable (GL_VERTEX_PROGRAM_POINT_SIZE); qfeglGetFloatv (GL_ALIASED_POINT_SIZE_RANGE, v); Sys_MaskPrintf (SYS_glsl, "point size: %g - %g\n", v[0], v[1]); @@ -258,8 +268,8 @@ draw_qf_particles (psystem_t *psystem) qfeglDepthMask (GL_FALSE); minparticledist = DotProduct (r_refdef.frame.position, - r_refdef.frame.forward) + - r_particles_nearclip->value; + r_refdef.frame.forward) + + r_particles_nearclip; vacount = 0; VA = particleVertexArray; @@ -378,8 +388,8 @@ draw_id_particles (psystem_t *psystem) qfeglBindTexture (GL_TEXTURE_2D, glsl_palette); minparticledist = DotProduct (r_refdef.frame.position, - r_refdef.frame.forward) + - r_particles_nearclip->value; + r_refdef.frame.forward) + + r_particles_nearclip; vacount = 0; VA = particleVertexArray; @@ -424,42 +434,6 @@ glsl_R_DrawParticles (psystem_t *psystem) } } -static void -r_particles_nearclip_f (cvar_t *var) -{ - Cvar_SetValue (r_particles_nearclip, bound (r_nearclip->value, var->value, - r_farclip->value)); -} - -static void -r_particles_f (cvar_t *var) -{ - R_MaxParticlesCheck (var, r_particles_max); - alloc_arrays (&r_psystem); -} - -static void -r_particles_max_f (cvar_t *var) -{ - R_MaxParticlesCheck (r_particles, var); - alloc_arrays (&r_psystem); -} - -void -glsl_R_Particles_Init_Cvars (void) -{ - r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, - "Toggles drawing of particles."); - r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, - r_particles_max_f, "Maximum amount of " - "particles to display. No maximum, minimum " - "is 0."); - r_particles_nearclip = Cvar_Get ("r_particles_nearclip", "32", - CVAR_ARCHIVE, r_particles_nearclip_f, - "Distance of the particle near clipping " - "plane from the player."); -} - psystem_t * __attribute__((const))//FIXME glsl_ParticleSystem (void) { diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index 0dffe7d11..71e516cec 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -151,7 +151,7 @@ GLSL_Init_Common (void) GLSL_TextureInit (); - if (developer->int_val & SYS_glsl) { + if (developer & SYS_glsl) { GLint max; qfeglGetIntegerv (GL_MAX_VERTEX_UNIFORM_VECTORS, &max); @@ -198,7 +198,7 @@ GLSL_CompileShader (const char *name, const shader_t *shader, int type) qfeglShaderSource (sid, shader->num_strings, shader->strings, 0); qfeglCompileShader (sid); qfeglGetShaderiv (sid, GL_COMPILE_STATUS, &compiled); - if (!compiled || (developer->int_val & SYS_glsl)) { + if (!compiled || (developer & SYS_glsl)) { dstring_t *log = dstring_new (); int size; qfeglGetShaderiv (sid, GL_INFO_LOG_LENGTH, &size); @@ -321,7 +321,7 @@ GLSL_LinkProgram (const char *name, int vert, int frag) qfeglLinkProgram (program); qfeglGetProgramiv (program, GL_LINK_STATUS, &linked); - if (!linked || (developer->int_val & SYS_glsl)) { + if (!linked || (developer & SYS_glsl)) { dstring_t *log = dstring_new (); int size; qfeglGetProgramiv (program, GL_INFO_LOG_LENGTH, &size); @@ -336,7 +336,7 @@ GLSL_LinkProgram (const char *name, int vert, int frag) if (!linked) return 0; } - if (developer->int_val & SYS_glsl) + if (developer & SYS_glsl) dump_program (name, program); return program; } diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 53b778647..31951b46f 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -56,7 +56,7 @@ R_MarkLeaves (void) msurface_t **mark; mod_brush_t *brush = &r_refdef.worldmodel->brush; - if (r_oldviewleaf == r_refdef.viewleaf && !r_novis->int_val) + if (r_oldviewleaf == r_refdef.viewleaf && !r_novis) return; r_visframecount++; @@ -64,7 +64,7 @@ R_MarkLeaves (void) if (!r_refdef.viewleaf) return; - if (r_novis->int_val) { + if (r_novis) { r_oldviewleaf = 0; // so vis will be recalcualted when novis gets // turned off if (!solid) { diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index 83c5f1958..76937ebae 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -41,90 +41,497 @@ #include "compat.h" #include "r_internal.h" -cvar_t *cl_crossx; -cvar_t *cl_crossy; -cvar_t *cl_verstring; -cvar_t *crosshair; -cvar_t *crosshaircolor; +int cl_crossx; +static cvar_t cl_crossx_cvar = { + .name = "cl_crossx", + .description = + "Sets the position of the crosshair on the X-axis.", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_crossx }, +}; +int cl_crossy; +static cvar_t cl_crossy_cvar = { + .name = "cl_crossy", + .description = + "Sets the position of the crosshair on the Y-axis.", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_crossy }, +}; +char *cl_verstring; +static cvar_t cl_verstring_cvar = { + .name = "cl_verstring", + .description = + "Client version string", + .default_value = PACKAGE_VERSION, + .flags = CVAR_NONE, + .value = { .type = 0, .value = &cl_verstring }, +}; +int crosshair; +static cvar_t crosshair_cvar = { + .name = "crosshair", + .description = + "Crosshair type. 0 off, 1 old white, 2 new with colors", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &crosshair }, +}; +int crosshaircolor; +static cvar_t crosshaircolor_cvar = { + .name = "crosshaircolor", + .description = + "Color of the new crosshair", + .default_value = "79", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &crosshaircolor }, +}; -cvar_t *d_mipcap; -cvar_t *d_mipscale; +float d_mipcap; +static cvar_t d_mipcap_cvar = { + .name = "d_mipcap", + .description = + "Detail level. 0 is highest, 3 is lowest.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &d_mipcap }, +}; +float d_mipscale; +static cvar_t d_mipscale_cvar = { + .name = "d_mipscale", + .description = + "Detail level of objects. 0 is highest, 3 is lowest.", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &d_mipscale }, +}; -cvar_t *r_aliasstats; -cvar_t *r_aliastransadj; -cvar_t *r_aliastransbase; -cvar_t *r_clearcolor; -cvar_t *r_dlight_lightmap; -cvar_t *r_dlight_max; -cvar_t *r_drawentities; -cvar_t *r_drawexplosions; -cvar_t *r_drawviewmodel; -cvar_t *r_dspeeds; -cvar_t *r_dynamic; -cvar_t *r_explosionclip; -cvar_t *r_farclip; -cvar_t *r_firecolor; -cvar_t *r_flatlightstyles; -cvar_t *r_graphheight; -cvar_t *r_lightmap_components; -cvar_t *r_maxedges; -cvar_t *r_maxsurfs; -cvar_t *r_mirroralpha; -cvar_t *r_nearclip; -cvar_t *r_norefresh; -cvar_t *r_novis; -cvar_t *r_numedges; -cvar_t *r_numsurfs; -cvar_t *r_particles; -cvar_t *r_particles_max; -cvar_t *r_particles_nearclip; -cvar_t *r_reportedgeout; -cvar_t *r_reportsurfout; -cvar_t *r_shadows; -cvar_t *r_skyname; -cvar_t *r_speeds; -cvar_t *r_timegraph; -cvar_t *r_wateralpha; -cvar_t *r_waterripple; -cvar_t *r_waterwarp; -cvar_t *r_zgraph; +int r_aliasstats; +static cvar_t r_aliasstats_cvar = { + .name = "r_polymodelstats", + .description = + "Toggles the displays of number of polygon models current being viewed", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_aliasstats }, +}; +float r_aliastransadj; +static cvar_t r_aliastransadj_cvar = { + .name = "r_aliastransadj", + .description = + "Determines how much of an alias model is clipped away and how much is" + " viewable.", + .default_value = "100", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &r_aliastransadj }, +}; +float r_aliastransbase; +static cvar_t r_aliastransbase_cvar = { + .name = "r_aliastransbase", + .description = + "Determines how much of an alias model is clipped away and how much is" + " viewable", + .default_value = "200", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &r_aliastransbase }, +}; +int r_clearcolor; +static cvar_t r_clearcolor_cvar = { + .name = "r_clearcolor", + .description = + "This sets the color for areas outside of the current map", + .default_value = "2", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_clearcolor }, +}; +int r_dlight_lightmap; +static cvar_t r_dlight_lightmap_cvar = { + .name = "r_dlight_lightmap", + .description = + "Set to 1 for high quality dynamic lighting.", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &r_dlight_lightmap }, +}; +int r_dlight_max; +static cvar_t r_dlight_max_cvar = { + .name = "r_dlight_max", + .description = + "Number of dynamic lights.", + .default_value = "32", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &r_dlight_max }, +}; +int r_drawentities; +static cvar_t r_drawentities_cvar = { + .name = "r_drawentities", + .description = + "Toggles drawing of entities (almost everything but the world)", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_drawentities }, +}; +int r_drawexplosions; +static cvar_t r_drawexplosions_cvar = { + .name = "r_drawexplosions", + .description = + "Draw explosions.", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &r_drawexplosions }, +}; +int r_drawviewmodel; +static cvar_t r_drawviewmodel_cvar = { + .name = "r_drawviewmodel", + .description = + "Toggles view model drawing (your weapons)", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &r_drawviewmodel }, +}; +int r_dspeeds; +static cvar_t r_dspeeds_cvar = { + .name = "r_dspeeds", + .description = + "Toggles the display of drawing speed information", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_dspeeds }, +}; +int r_dynamic; +static cvar_t r_dynamic_cvar = { + .name = "r_dynamic", + .description = + "Set to 0 to disable lightmap changes", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_dynamic }, +}; +int r_explosionclip; +static cvar_t r_explosionclip_cvar = { + .name = "r_explosionclip", + .description = + "Clip explosions.", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &r_explosionclip }, +}; +float r_farclip; +static cvar_t r_farclip_cvar = { + .name = "r_farclip", + .description = + "Distance of the far clipping plane from the player.", + .default_value = "4096", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &r_farclip }, +}; +vec4f_t r_firecolor; +static cvar_t r_firecolor_cvar = { + .name = "r_firecolor", + .description = + "color of rocket and lava ball fires", + .default_value = "[0.9, 0.7, 0.0]", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_vector, .value = &r_firecolor }, +}; +int r_flatlightstyles; +static cvar_t r_flatlightstyles_cvar = { + .name = "r_flatlightstyles", + .description = + "Disable animated lightmaps. 2 = use peak, 1 = use average, anything " + "else = normal", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_flatlightstyles }, +}; +int r_graphheight; +static cvar_t r_graphheight_cvar = { + .name = "r_graphheight", + .description = + "Set the number of lines displayed in the various graphs", + .default_value = "32", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_graphheight }, +}; +int r_lightmap_components; +static cvar_t r_lightmap_components_cvar = { + .name = "r_lightmap_components", + .description = + "Lightmap texture components. 1 is greyscale, 3 is RGB, 4 is RGBA.", + .default_value = "3", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &r_lightmap_components }, +}; +int r_maxedges; +static cvar_t r_maxedges_cvar = { + .name = "r_maxedges", + .description = + "Sets the maximum number of edges", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_maxedges }, +}; +int r_maxsurfs; +static cvar_t r_maxsurfs_cvar = { + .name = "r_maxsurfs", + .description = + "Sets the maximum number of surfaces", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_maxsurfs }, +}; +float r_mirroralpha; +static cvar_t r_mirroralpha_cvar = { + .name = "r_mirroralpha", + .description = + "None", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &r_mirroralpha }, +}; +float r_nearclip; +static cvar_t r_nearclip_cvar = { + .name = "r_nearclip", + .description = + "Distance of the near clipping plane from the player.", + .default_value = "4", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &r_nearclip }, +}; +int r_norefresh; +static cvar_t r_norefresh_cvar = { + .name = "r_norefresh_", + .description = + "Set to 1 to disable display refresh", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_norefresh }, +}; +int r_novis; +static cvar_t r_novis_cvar = { + .name = "r_novis", + .description = + "Set to 1 to enable runtime visibility checking (SLOW)", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_novis }, +}; +int r_numedges; +static cvar_t r_numedges_cvar = { + .name = "r_numedges", + .description = + "Toggles the displaying of number of edges currently being viewed", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_numedges }, +}; +int r_numsurfs; +static cvar_t r_numsurfs_cvar = { + .name = "r_numsurfs", + .description = + "Toggles the displaying of number of surfaces currently being viewed", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_numsurfs }, +}; +int r_reportedgeout; +static cvar_t r_reportedgeout_cvar = { + .name = "r_reportedgeout", + .description = + "Toggle the display of how many edges were not displayed", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_reportedgeout }, +}; +int r_reportsurfout; +static cvar_t r_reportsurfout_cvar = { + .name = "r_reportsurfout", + .description = + "Toggle the display of how many surfaces were not displayed", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_reportsurfout }, +}; +int r_shadows; +static cvar_t r_shadows_cvar = { + .name = "r_shadows", + .description = + "Set to 1 to enable shadows for entities", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &r_shadows }, +}; +char *r_skyname; +static cvar_t r_skyname_cvar = { + .name = "r_skyname", + .description = + "name of the current skybox", + .default_value = "none", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &r_skyname }, +}; +int r_speeds; +static cvar_t r_speeds_cvar = { + .name = "r_speeds", + .description = + "Display drawing time and statistics of what is being viewed", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_speeds }, +}; +int r_timegraph; +static cvar_t r_timegraph_cvar = { + .name = "r_timegraph", + .description = + "Toggle the display of a performance graph", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_timegraph }, +}; +float r_wateralpha; +static cvar_t r_wateralpha_cvar = { + .name = "r_wateralpha", + .description = + "Determine the opacity of liquids. 1 = opaque, 0 = transparent, " + "otherwise translucent.", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &r_wateralpha }, +}; +float r_waterripple; +static cvar_t r_waterripple_cvar = { + .name = "r_waterripple", + .description = + "Set to make liquids ripple, try setting to 5", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &r_waterripple }, +}; +int r_waterwarp; +static cvar_t r_waterwarp_cvar = { + .name = "r_waterwarp", + .description = + "Toggles whether surfaces are warped in liquid.", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_waterwarp }, +}; +int r_zgraph; +static cvar_t r_zgraph_cvar = { + .name = "r_zgraph", + .description = + "Toggle the graph that reports the changes of z-axis position", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &r_zgraph }, +}; -cvar_t *scr_fov; -cvar_t *scr_fisheye; -cvar_t *scr_fviews; -cvar_t *scr_ffov; -cvar_t *scr_showpause; -cvar_t *scr_showram; -cvar_t *scr_showturtle; -cvar_t *scr_viewsize; +float scr_fov; +static cvar_t scr_fov_cvar = { + .name = "fov", + .description = + "Your field of view in degrees. Smaller than 90 zooms in. Don't touch " + "in fisheye mode, use ffov instead.", + .default_value = "90", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &scr_fov }, +}; +int scr_fisheye; +static cvar_t scr_fisheye_cvar = { + .name = "fisheye", + .description = + "Toggles fisheye mode.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_fisheye }, +}; +int scr_fviews; +static cvar_t scr_fviews_cvar = { + .name = "fviews", + .description = + "The number of fisheye views.", + .default_value = "6", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_fviews }, +}; +float scr_ffov; +static cvar_t scr_ffov_cvar = { + .name = "ffov", + .description = + "Your field of view in degrees in fisheye mode.", + .default_value = "180", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &scr_ffov }, +}; +int scr_showpause; +static cvar_t scr_showpause_cvar = { + .name = "showpause", + .description = + "Toggles display of pause graphic", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_showpause }, +}; +int scr_showram; +static cvar_t scr_showram_cvar = { + .name = "showram", + .description = + "Show RAM icon if game is running low on memory", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_showram }, +}; +int scr_showturtle; +static cvar_t scr_showturtle_cvar = { + .name = "showturtle", + .description = + "Show a turtle icon if your fps is below 10", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_showturtle }, +}; +int scr_viewsize; +static cvar_t scr_viewsize_cvar = { + .name = "viewsize", + .description = + "Set the screen size 30 minimum, 120 maximum", + .default_value = "100", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &scr_viewsize }, +}; int r_viewsize; quat_t crosshair_color; static void -crosshaircolor_update (void *_var, const viddef_t *vid) +set_crosshair_color (int col, const viddef_t *vid) { - cvar_t *var = _var; byte *color; - color = &vid->palette32[bound (0, var->int_val, 255) * 4]; + color = &vid->palette32[bound (0, col, 255) * 4]; QuatScale (color, 1.0 / 255, crosshair_color); } static void -crosshaircolor_f (cvar_t *var) +crosshaircolor_update (void *data, const viddef_t *vid) +{ + set_crosshair_color (crosshaircolor, vid); +} + +static void +crosshaircolor_f (void *data, const cvar_t *cvar) { if (!r_data->vid->palette32) { // palette not initialized yet return; } - crosshaircolor_update (var, r_data->vid); + set_crosshair_color (crosshaircolor, r_data->vid); } static void -r_lightmap_components_f (cvar_t *var) +r_lightmap_components_f (void *data, const cvar_t *cvar) { - switch (var->int_val) { + switch (r_lightmap_components) { case 1: mod_lightmap_bytes = 1; break; @@ -137,200 +544,120 @@ r_lightmap_components_f (cvar_t *var) } static void -r_farclip_f (cvar_t *var) +r_farclip_f (void *data, const cvar_t *cvar) { - Cvar_SetValue (r_farclip, bound (8.0, var->value, Q_MAXFLOAT)); - if (r_particles_nearclip && r_nearclip) - Cvar_SetValue (r_particles_nearclip, - bound (r_nearclip->value, r_particles_nearclip->value, - r_farclip->value)); + r_farclip = bound (8.0, r_farclip, Q_MAXFLOAT); + r_particles_nearclip = bound (r_nearclip, r_particles_nearclip, r_farclip); r_data->vid->recalc_refdef = true; } static void -r_nearclip_f (cvar_t *var) +r_nearclip_f (void *data, const cvar_t *cvar) { - Cvar_SetValue (r_nearclip, bound (0.01, var->value, 4.0)); - if (r_particles_nearclip && r_farclip) - Cvar_SetValue (r_particles_nearclip, - bound (r_nearclip->value, r_particles_nearclip->value, - r_farclip->value)); + r_nearclip = bound (0.01, r_nearclip, 4.0); + r_particles_nearclip = bound (r_nearclip, r_particles_nearclip, r_farclip); r_data->vid->recalc_refdef = true; } static void -scr_fov_f (cvar_t *var) +scr_fov_f (void *data, const cvar_t *cvar) { // bound field of view - float fov = bound (0, var->value, 170); - - if (fov != var->value) { - Cvar_SetValue (var, fov); - } else { - SCR_SetFOV (var->value); - } + scr_fov = bound (0, scr_fov, 170); + SCR_SetFOV (scr_fov); } static void -scr_fisheye_f (cvar_t *var) +scr_fisheye_f (void *data, const cvar_t *cvar) { - if (var->int_val) - Cvar_Set (scr_fov, "90"); + if (scr_fisheye) + Cvar_Set ("fov", "90"); } static void -scr_ffov_f (cvar_t *var) +scr_ffov_f (void *data, const cvar_t *cvar) { - if (var->value < 130) - Cvar_Set (scr_fviews, "3"); - else if (var->value < 220) - Cvar_Set (scr_fviews, "5"); + if (scr_ffov < 130) + Cvar_Set ("fviews", "3"); + else if (scr_ffov < 220) + Cvar_Set ("fviews", "5"); else - Cvar_Set (scr_fviews, "6"); + Cvar_Set ("fviews", "6"); } static void -viewsize_f (cvar_t *var) +viewsize_f (void *data, const cvar_t *cvar) { - if (var->int_val < 30 || var->int_val > 120) { - Cvar_SetValue (var, bound (30, var->int_val, 120)); - } else { - r_data->vid->recalc_refdef = true; - r_viewsize = bound (0, var->int_val, 100); - if (r_data->viewsize_callback) - r_data->viewsize_callback (var); - } + scr_viewsize = bound (30, scr_viewsize, 120); + r_data->vid->recalc_refdef = true; + r_viewsize = bound (0, scr_viewsize, 100); + if (r_data->viewsize_callback) + r_data->viewsize_callback (scr_viewsize); } static void -r_dlight_max_f (cvar_t *var) +r_dlight_max_f (void *data, const cvar_t *cvar) { - R_MaxDlightsCheck (var); + R_MaxDlightsCheck (r_dlight_max); } void R_Init_Cvars (void) { - cl_crossx = Cvar_Get ("cl_crossx", "0", CVAR_ARCHIVE, NULL, - "Sets the position of the crosshair on the X-axis."); - cl_crossy = Cvar_Get ("cl_crossy", "0", CVAR_ARCHIVE, NULL, - "Sets the position of the crosshair on the Y-axis."); - cl_verstring = Cvar_Get ("cl_verstring", PACKAGE_VERSION, CVAR_NONE, - NULL, "Client version string"); - crosshair = Cvar_Get ("crosshair", "0", CVAR_ARCHIVE, NULL, "Crosshair " - "type. 0 off, 1 old white, 2 new with colors"); - crosshaircolor = Cvar_Get ("crosshaircolor", "79", CVAR_ARCHIVE, - crosshaircolor_f, "Color of the new crosshair"); - VID_OnPaletteChange_AddListener (crosshaircolor_update, crosshaircolor); - d_mipcap = Cvar_Get ("d_mipcap", "0", CVAR_NONE, NULL, - "Detail level. 0 is highest, 3 is lowest."); - d_mipscale = Cvar_Get ("d_mipscale", "1", CVAR_NONE, NULL, "Detail level " - "of objects. 0 is highest, 3 is lowest."); - r_aliasstats = Cvar_Get ("r_polymodelstats", "0", CVAR_NONE, NULL, - "Toggles the displays of number of polygon " - "models current being viewed"); - r_aliastransadj = Cvar_Get ("r_aliastransadj", "100", CVAR_NONE, NULL, - "Determines how much of an alias model is " - "clipped away and how much is viewable."); - r_aliastransbase = Cvar_Get ("r_aliastransbase", "200", CVAR_NONE, NULL, - "Determines how much of an alias model is " - "clipped away and how much is viewable"); - r_clearcolor = Cvar_Get ("r_clearcolor", "2", CVAR_NONE, NULL, - "This sets the color for areas outside of the " - "current map"); - r_dlight_lightmap = Cvar_Get ("r_dlight_lightmap", "1", CVAR_ARCHIVE, - NULL, "Set to 1 for high quality dynamic " - "lighting."); - r_dlight_max = Cvar_Get ("r_dlight_max", "32", CVAR_ARCHIVE, - r_dlight_max_f, "Number of dynamic lights."); - r_drawentities = Cvar_Get ("r_drawentities", "1", CVAR_NONE, NULL, - "Toggles drawing of entities (almost " - "everything but the world)"); - r_drawexplosions = Cvar_Get ("r_drawexplosions", "1", CVAR_ARCHIVE, NULL, - "Draw explosions."); - r_drawviewmodel = Cvar_Get ("r_drawviewmodel", "1", CVAR_ARCHIVE, NULL, - "Toggles view model drawing (your weapons)"); - r_dspeeds = Cvar_Get ("r_dspeeds", "0", CVAR_NONE, NULL, - "Toggles the display of drawing speed information"); - r_dynamic = Cvar_Get ("r_dynamic", "1", CVAR_NONE, NULL, - "Set to 0 to disable lightmap changes"); - r_explosionclip = Cvar_Get ("r_explosionclip", "0", CVAR_ARCHIVE, NULL, - "Clip explosions."); - r_farclip = Cvar_Get ("r_farclip", "4096", CVAR_ARCHIVE, r_farclip_f, - "Distance of the far clipping plane from the " - "player."); - r_firecolor = Cvar_Get ("r_firecolor", "0.9 0.7 0.0", CVAR_ARCHIVE, NULL, - "color of rocket and lava ball fires"); - r_flatlightstyles = Cvar_Get ("r_flatlightstyles", "0", CVAR_NONE, NULL, - "Disable animated lightmaps. 2 = use peak, " - "1 = use average, anything else = normal"); - r_graphheight = Cvar_Get ("r_graphheight", "32", CVAR_NONE, NULL, - "Set the number of lines displayed in the " - "various graphs"); - r_lightmap_components = Cvar_Get ("r_lightmap_components", "3", CVAR_ROM, - r_lightmap_components_f, - "Lightmap texture components. 1 " - "is greyscale, 3 is RGB, 4 is RGBA."); - r_maxedges = Cvar_Get ("r_maxedges", "0", CVAR_NONE, NULL, - "Sets the maximum number of edges"); - r_maxsurfs = Cvar_Get ("r_maxsurfs", "0", CVAR_NONE, NULL, - "Sets the maximum number of surfaces"); - r_mirroralpha = Cvar_Get ("r_mirroralpha", "1", CVAR_NONE, NULL, "None"); - r_nearclip = Cvar_Get ("r_nearclip", "4", CVAR_ARCHIVE, r_nearclip_f, - "Distance of the near clipping plane from the " - "player."); - r_norefresh = Cvar_Get ("r_norefresh_", "0", CVAR_NONE, NULL, - "Set to 1 to disable display refresh"); - r_novis = Cvar_Get ("r_novis", "0", CVAR_NONE, NULL, "Set to 1 to enable " - "runtime visibility checking (SLOW)"); - r_numedges = Cvar_Get ("r_numedges", "0", CVAR_NONE, NULL, - "Toggles the displaying of number of edges " - "currently being viewed"); - r_numsurfs = Cvar_Get ("r_numsurfs", "0", CVAR_NONE, NULL, - "Toggles the displaying of number of surfaces " - "currently being viewed"); - r_reportedgeout = Cvar_Get ("r_reportedgeout", "0", CVAR_NONE, NULL, - "Toggle the display of how many edges were " - "not displayed"); - r_reportsurfout = Cvar_Get ("r_reportsurfout", "0", CVAR_NONE, NULL, - "Toggle the display of how many surfaces " - "were not displayed"); - r_shadows = Cvar_Get ("r_shadows", "0", CVAR_ARCHIVE, NULL, - "Set to 1 to enable shadows for entities"); - r_skyname = Cvar_Get ("r_skyname", "none", CVAR_NONE, NULL, - "name of the current skybox"); - r_speeds = Cvar_Get ("r_speeds", "0", CVAR_NONE, NULL, "Display drawing " - "time and statistics of what is being viewed"); - r_timegraph = Cvar_Get ("r_timegraph", "0", CVAR_NONE, NULL, - "Toggle the display of a performance graph"); - r_wateralpha = Cvar_Get ("r_wateralpha", "1", CVAR_ARCHIVE, NULL, - "Determine the opacity of liquids. 1 = opaque, " - "0 = transparent, otherwise translucent."); - r_waterripple = Cvar_Get ("r_waterripple", "0", CVAR_NONE, NULL, - "Set to make liquids ripple, try setting to 5"); - r_waterwarp = Cvar_Get ("r_waterwarp", "1", CVAR_NONE, NULL, - "Toggles whether surfaces are warped in liquid."); - r_zgraph = Cvar_Get ("r_zgraph", "0", CVAR_NONE, NULL, - "Toggle the graph that reports the changes of " - "z-axis position"); - scr_fov = Cvar_Get ("fov", "90", CVAR_NONE, scr_fov_f, - "Your field of view in degrees. Smaller than 90 zooms " - "in. Don't touch in fisheye mode, use ffov instead."); - scr_fisheye = Cvar_Get ("fisheye", "0", CVAR_NONE, scr_fisheye_f, - "Toggles fisheye mode."); - scr_fviews = Cvar_Get ("fviews", "6", CVAR_NONE, NULL, "The number of " - "fisheye views."); - scr_ffov = Cvar_Get ("ffov", "180", CVAR_NONE, scr_ffov_f, "Your field of " - "view in degrees in fisheye mode."); - scr_showpause = Cvar_Get ("showpause", "1", CVAR_NONE, NULL, - "Toggles display of pause graphic"); - scr_showram = Cvar_Get ("showram", "1", CVAR_NONE, NULL, - "Show RAM icon if game is running low on memory"); - scr_showturtle = Cvar_Get ("showturtle", "0", CVAR_NONE, NULL, - "Show a turtle icon if your fps is below 10"); - scr_viewsize = Cvar_Get ("viewsize", "100", CVAR_ARCHIVE, viewsize_f, - "Set the screen size 30 minimum, 120 maximum"); + Cvar_Register (&cl_crossx_cvar, 0, 0); + Cvar_Register (&cl_crossy_cvar, 0, 0); + Cvar_Register (&cl_verstring_cvar, 0, 0); + Cvar_Register (&crosshair_cvar, 0, 0); + Cvar_Register (&crosshaircolor_cvar, crosshaircolor_f, 0); + VID_OnPaletteChange_AddListener (crosshaircolor_update, 0); + Cvar_Register (&d_mipcap_cvar, 0, 0); + Cvar_Register (&d_mipscale_cvar, 0, 0); + Cvar_Register (&r_aliasstats_cvar, 0, 0); + Cvar_Register (&r_aliastransadj_cvar, 0, 0); + Cvar_Register (&r_aliastransbase_cvar, 0, 0); + Cvar_Register (&r_clearcolor_cvar, 0, 0); + Cvar_Register (&r_dlight_lightmap_cvar, 0, 0); + Cvar_Register (&r_dlight_max_cvar, r_dlight_max_f, 0); + Cvar_Register (&r_drawentities_cvar, 0, 0); + Cvar_Register (&r_drawexplosions_cvar, 0, 0); + Cvar_Register (&r_drawviewmodel_cvar, 0, 0); + Cvar_Register (&r_dspeeds_cvar, 0, 0); + Cvar_Register (&r_dynamic_cvar, 0, 0); + Cvar_Register (&r_explosionclip_cvar, 0, 0); + Cvar_Register (&r_farclip_cvar, r_farclip_f, 0); + Cvar_Register (&r_firecolor_cvar, 0, 0); + Cvar_Register (&r_flatlightstyles_cvar, 0, 0); + Cvar_Register (&r_graphheight_cvar, 0, 0); + Cvar_Register (&r_lightmap_components_cvar, r_lightmap_components_f, 0); + Cvar_Register (&r_maxedges_cvar, 0, 0); + Cvar_Register (&r_maxsurfs_cvar, 0, 0); + Cvar_Register (&r_mirroralpha_cvar, 0, 0); + Cvar_Register (&r_nearclip_cvar, r_nearclip_f, 0); + Cvar_Register (&r_norefresh_cvar, 0, 0); + Cvar_Register (&r_novis_cvar, 0, 0); + Cvar_Register (&r_numedges_cvar, 0, 0); + Cvar_Register (&r_numsurfs_cvar, 0, 0); + Cvar_Register (&r_reportedgeout_cvar, 0, 0); + Cvar_Register (&r_reportsurfout_cvar, 0, 0); + Cvar_Register (&r_shadows_cvar, 0, 0); + Cvar_Register (&r_skyname_cvar, 0, 0); + Cvar_Register (&r_speeds_cvar, 0, 0); + Cvar_Register (&r_timegraph_cvar, 0, 0); + Cvar_Register (&r_wateralpha_cvar, 0, 0); + Cvar_Register (&r_waterripple_cvar, 0, 0); + Cvar_Register (&r_waterwarp_cvar, 0, 0); + Cvar_Register (&r_zgraph_cvar, 0, 0); + Cvar_Register (&scr_fov_cvar, scr_fov_f, 0); + Cvar_Register (&scr_fisheye_cvar, scr_fisheye_f, 0); + Cvar_Register (&scr_fviews_cvar, 0, 0); + Cvar_Register (&scr_ffov_cvar, scr_ffov_f, 0); + Cvar_Register (&scr_showpause_cvar, 0, 0); + Cvar_Register (&scr_showram_cvar, 0, 0); + Cvar_Register (&scr_showturtle_cvar, 0, 0); + Cvar_Register (&scr_viewsize_cvar, viewsize_f, 0); - r_data->graphheight = r_graphheight; - r_data->scr_viewsize = scr_viewsize; + r_data->graphheight = &r_graphheight; + r_data->scr_viewsize = &scr_viewsize; + + R_Particles_Init_Cvars (); } diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index 4c309aacf..ff2aee694 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -98,5 +98,5 @@ R_ZGraph (view_t *view) height[r_framecount & 255] = ((int) r_refdef.frame.position[2]) & 31; r_funcs->R_LineGraph (view->xabs, view->yabs, height, - w, r_data->graphheight->int_val); + w, *r_data->graphheight); } diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 4ddfe33eb..5b3b53033 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -49,7 +49,15 @@ #include "r_scrap.h" #include "vid_internal.h" -cvar_t *vidrend_plugin; +char *vidrend_plugin; +static cvar_t vidrend_plugin_cvar = { + .name = "vid_render", + .description = + "Video Render Plugin to use", + .default_value = VID_RENDER_DEFAULT, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &vidrend_plugin }, +}; plugin_t *vidrendmodule = NULL; VID_RENDER_PLUGIN_PROTOS @@ -77,12 +85,11 @@ VISIBLE void R_LoadModule (vid_internal_t *vid_internal) { PI_RegisterPlugins (vidrend_plugin_list); - vidrend_plugin = Cvar_Get ("vid_render", VID_RENDER_DEFAULT, CVAR_ROM, 0, - "Video Render Plugin to use"); - vidrendmodule = PI_LoadPlugin ("vid_render", vidrend_plugin->string); + Cvar_Register (&vidrend_plugin_cvar, 0, 0); + vidrendmodule = PI_LoadPlugin ("vid_render", vidrend_plugin); if (!vidrendmodule) { Sys_Error ("Loading of video render module: %s failed!\n", - vidrend_plugin->string); + vidrend_plugin); } r_funcs = vidrendmodule->functions->vid_render; mod_funcs = r_funcs->model_funcs; diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index d9a96915e..0c9a50a28 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -106,9 +106,9 @@ R_FindNearLights (vec4f_t pos, int count, dlight_t **lights) } void -R_MaxDlightsCheck (cvar_t *var) +R_MaxDlightsCheck (int max_dlights) { - r_maxdlights = bound (0, var->int_val, MAX_DLIGHTS); + r_maxdlights = bound (0, max_dlights, MAX_DLIGHTS); if (r_dlights) free (r_dlights); @@ -134,9 +134,9 @@ R_AnimateLight (void) d_lightstylevalue[j] = 256; continue; } - if (r_flatlightstyles->int_val == 2) { + if (r_flatlightstyles == 2) { k = r_data->lightstyle[j].peak - 'a'; - } else if (r_flatlightstyles->int_val == 1) { + } else if (r_flatlightstyles == 1) { k = r_data->lightstyle[j].average - 'a'; } else { k = i % r_data->lightstyle[j].length; @@ -317,7 +317,7 @@ R_PushDlights (const vec3_t entorigin) dlight_t *l; vec3_t lightorigin; - if (!r_dlight_lightmap->int_val) + if (!r_dlight_lightmap) return; l = r_dlights; diff --git a/libs/video/renderer/r_part.c b/libs/video/renderer/r_part.c index e0b6c56be..0a73882e9 100644 --- a/libs/video/renderer/r_part.c +++ b/libs/video/renderer/r_part.c @@ -37,6 +37,33 @@ #include "r_internal.h" psystem_t r_psystem; //FIXME singleton +int r_particles; +static cvar_t r_particles_cvar = { + .name = "r_particles", + .description = + "Toggles drawing of particles.", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &r_particles }, +}; +int r_particles_max; +static cvar_t r_particles_max_cvar = { + .name = "r_particles_max", + .description = + "Maximum amount of particles to display. No maximum, minimum is 0.", + .default_value = "2048", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &r_particles_max }, +}; +float r_particles_nearclip; +static cvar_t r_particles_nearclip_cvar = { + .name = "r_particles_nearclip", + .description = + "Distance of the particle near clipping plane from the player.", + .default_value = "32", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &r_particles_nearclip }, +}; /* R_MaxParticlesCheck @@ -45,14 +72,13 @@ psystem_t r_psystem; //FIXME singleton Thanks to a LOT of help from Taniwha, Deek, Mercury, Lordhavoc, and lots of others. */ -void -R_MaxParticlesCheck (cvar_t *r_particles, cvar_t *r_particles_max) +static void +R_MaxParticlesCheck (void) { psystem_t *ps = &r_psystem;//FIXME unsigned maxparticles = 0; - if (r_particles && r_particles->int_val) { - maxparticles = r_particles_max ? r_particles_max->int_val : 0; - } + + maxparticles = r_particles ? r_particles_max : 0; if (ps->maxparticles == maxparticles) { return; @@ -116,3 +142,29 @@ R_RunParticles (float dT) } ps->numparticles = j; } + +static void +r_particles_nearclip_f (void *data, const cvar_t *cvar) +{ + r_particles_nearclip = bound (r_nearclip, r_particles_nearclip, r_farclip); +} + +static void +r_particles_f (void *data, const cvar_t *cvar) +{ + R_MaxParticlesCheck (); +} + +static void +r_particles_max_f (void *data, const cvar_t *cvar) +{ + R_MaxParticlesCheck (); +} + +void +R_Particles_Init_Cvars (void) +{ + Cvar_Register (&r_particles_cvar, r_particles_f, 0); + Cvar_Register (&r_particles_max_cvar, r_particles_max_f, 0); + Cvar_Register (&r_particles_nearclip_cvar, r_particles_nearclip_f, 0); +} diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index cabd491cc..6152efce9 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -229,11 +229,11 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) return; } - if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val) { + if (r_timegraph || r_speeds || r_dspeeds) { r_time1 = Sys_DoubleTime (); } - if (scr_fisheye->int_val && !fisheye_cube_map) { + if (scr_fisheye && !fisheye_cube_map) { fisheye_cube_map = r_funcs->create_cube_map (r_data->vid->height); } @@ -273,7 +273,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) vec4f_t position = refdef->frame.position; refdef->viewleaf = Mod_PointInLeaf ((vec_t*)&position, refdef->worldmodel);//FIXME r_dowarpold = r_dowarp; - if (r_waterwarp->int_val) { + if (r_waterwarp) { r_dowarp = refdef->viewleaf->contents <= CONTENTS_WATER; } if (r_dowarp && !warp_buffer) { @@ -288,12 +288,12 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) if (r_dowarp) { r_funcs->bind_framebuffer (warp_buffer); } - if (scr_fisheye->int_val && fisheye_cube_map) { + if (scr_fisheye && fisheye_cube_map) { int side = fisheye_cube_map->width; vrect_t feye = { 0, 0, side, side }; r_funcs->set_viewport (&feye); r_funcs->set_fov (1, 1); //FIXME shouldn't be every frame (2d stuff) - switch (scr_fviews->int_val) { + switch (scr_fviews) { case 6: render_side (BOX_BEHIND); case 5: render_side (BOX_BOTTOM); case 4: render_side (BOX_TOP); @@ -336,7 +336,7 @@ update_vrect (void) vrect.height = r_data->vid->height; set_vrect (&vrect, &refdef->vrect, r_data->lineadj); - SCR_SetFOV (scr_fov->value); + SCR_SetFOV (scr_fov); } void @@ -407,8 +407,8 @@ ScreenShot_f (void) static void SCR_SizeUp_f (void) { - if (scr_viewsize->int_val < 120) { - Cvar_SetValue (scr_viewsize, scr_viewsize->int_val + 10); + if (scr_viewsize < 120) { + scr_viewsize = scr_viewsize + 10; r_data->vid->recalc_refdef = 1; } } @@ -421,14 +421,14 @@ SCR_SizeUp_f (void) static void SCR_SizeDown_f (void) { - Cvar_SetValue (scr_viewsize, scr_viewsize->int_val - 10); + scr_viewsize = scr_viewsize - 10; r_data->vid->recalc_refdef = 1; } void SCR_DrawRam (void) { - if (!scr_showram->int_val) + if (!scr_showram) return; if (!r_cache_thrash) @@ -444,7 +444,7 @@ SCR_DrawTurtle (void) { static int count; - if (!scr_showturtle->int_val) + if (!scr_showturtle) return; if (r_data->frametime < 0.1) { @@ -466,7 +466,7 @@ SCR_DrawPause (void) { qpic_t *pic; - if (!scr_showpause->int_val) // turn off for screenshots + if (!scr_showpause) // turn off for screenshots return; if (!r_data->paused) @@ -501,6 +501,7 @@ SCR_Init (void) r_ent_queue = EntQueue_New (mod_num_types); - Cvar_AddListener (scr_viewsize, viewsize_listener, 0); + cvar_t *var = Cvar_FindVar ("viewsize"); + Cvar_AddListener (var, viewsize_listener, 0); update_vrect (); } diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index a1fd07616..84787f981 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -194,7 +194,7 @@ D_DrawSurfaces (void) d_zistepv = 0; d_ziorigin = -0.9; - D_DrawSolidSurface (s, r_clearcolor->int_val & 0xFF); + D_DrawSolidSurface (s, r_clearcolor & 0xFF); D_DrawZSpans (s->spans); } else if (s->flags & SURF_DRAWTURB) { pface = s->data; diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index ec0353817..e5daaf439 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -87,10 +87,10 @@ D_SetupFrame (void) d_roverwrapped = false; d_initial_rover = sc_rover; - d_minmip = bound (0, d_mipcap->value, 3); + d_minmip = bound (0, d_mipcap, 3); for (i = 0; i < (NUM_MIPS - 1); i++) - d_scalemip[i] = basemip[i] * d_mipscale->value; + d_scalemip[i] = basemip[i] * d_mipscale; d_drawspans = D_DrawSpans8; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 750105e39..bea4c305c 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -353,7 +353,7 @@ crosshair_1 (int x, int y) static void crosshair_2 (int x, int y) { - byte c = crosshaircolor->int_val; + byte c = crosshaircolor; Draw_Pixel (x - 1, y, c); Draw_Pixel (x - 3, y, c); @@ -368,7 +368,7 @@ crosshair_2 (int x, int y) static void crosshair_3 (int x, int y) { - byte c = crosshaircolor->int_val; + byte c = crosshaircolor; Draw_Pixel (x - 3, y - 3, c); Draw_Pixel (x + 3, y - 3, c); @@ -383,7 +383,7 @@ crosshair_3 (int x, int y) static void crosshair_4 (int x, int y) { - //byte c = crosshaircolor->int_val; + //byte c = crosshaircolor; Draw_Pixel (x, y - 2, 8); Draw_Pixel (x + 1, y - 2, 9); @@ -417,7 +417,7 @@ crosshair_4 (int x, int y) static void crosshair_5 (int x, int y) { - byte c = crosshaircolor->int_val; + byte c = crosshaircolor; Draw_Pixel (x - 1, y - 3, c); Draw_Pixel (x + 0, y - 3, c); @@ -458,12 +458,12 @@ Draw_Crosshair (void) int x, y; int ch; - ch = crosshair->int_val - 1; + ch = crosshair - 1; if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) return; - x = vid.conview->xlen / 2 + cl_crossx->int_val; - y = vid.conview->ylen / 2 + cl_crossy->int_val; + x = vid.conview->xlen / 2 + cl_crossx; + y = vid.conview->ylen / 2 + cl_crossy; crosshair_func[ch] (x, y); } @@ -644,8 +644,8 @@ Draw_ConsoleBackground (int lines, byte alpha) } } - Draw_AltString (vid.conview->xlen - strlen (cl_verstring->string) * 8 - 11, - lines - 14, cl_verstring->string); + Draw_AltString (vid.conview->xlen - strlen (cl_verstring) * 8 - 11, + lines - 14, cl_verstring); } static void diff --git a/libs/video/renderer/sw/sw_fisheye.c b/libs/video/renderer/sw/sw_fisheye.c index 83d6c2a15..28500ee68 100644 --- a/libs/video/renderer/sw/sw_fisheye.c +++ b/libs/video/renderer/sw/sw_fisheye.c @@ -128,7 +128,7 @@ R_RenderFisheye (framebuffer_t *cube) { int width = r_refdef.vrect.width; int height = r_refdef.vrect.height; - float fov = scr_ffov->value; + float fov = scr_ffov; static int pwidth = -1; static int pheight = -1; static int pfov = -1; diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 74ad36338..9f9b852a3 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -116,7 +116,6 @@ sw_R_Init (void) r_stack_start = (byte *) & dummy; R_Init_Cvars (); - R_Particles_Init_Cvars (); Draw_Init (); SCR_Init (); @@ -131,8 +130,8 @@ sw_R_Init (void) "refresh rate for the current location"); Cmd_AddCommand ("loadsky", R_LoadSky_f, "Load a skybox"); - Cvar_SetValue (r_maxedges, (float) NUMSTACKEDGES); - Cvar_SetValue (r_maxsurfs, (float) NUMSTACKSURFACES); + r_maxedges = NUMSTACKEDGES; + r_maxsurfs = NUMSTACKSURFACES; view_clipplanes[0].leftedge = true; view_clipplanes[1].rightedge = true; @@ -171,7 +170,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) R_ClearParticles (); - r_cnumsurfs = r_maxsurfs->int_val; + r_cnumsurfs = r_maxsurfs; if (r_cnumsurfs <= MINSURFACES) r_cnumsurfs = MINSURFACES; @@ -194,7 +193,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_maxedgesseen = 0; r_maxsurfsseen = 0; - r_numallocatededges = r_maxedges->int_val; + r_numallocatededges = r_maxedges; if (r_numallocatededges < MINEDGES) r_numallocatededges = MINEDGES; @@ -294,7 +293,7 @@ draw_iqm_entity (entity_t *ent) void R_DrawEntitiesOnList (entqueue_t *queue) { - if (!r_drawentities->int_val) + if (!r_drawentities) return; R_LowFPPrecision (); @@ -330,8 +329,8 @@ R_DrawViewModel (void) alight_t lighting; if (vr_data.inhibit_viewmodel - || !r_drawviewmodel->int_val - || !r_drawentities->int_val) + || !r_drawviewmodel + || !r_drawentities) return; viewent = vr_data.view_model; @@ -440,7 +439,7 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) model_t *clmodel; float minmaxs[6]; - if (!r_drawentities->int_val) + if (!r_drawentities) return; insubmodel = true; @@ -574,7 +573,7 @@ R_EdgeDrawing (entqueue_t *queue) static void R_RenderView_ (void) { - if (r_norefresh->int_val) + if (r_norefresh) return; if (!r_refdef.worldmodel) { return; @@ -592,7 +591,7 @@ R_RenderView_ (void) R_DrawViewModel (); - if (r_aliasstats->int_val) + if (r_aliasstats) R_PrintAliasStats (); // back to high floating-point precision diff --git a/libs/video/renderer/sw/sw_rpart.c b/libs/video/renderer/sw/sw_rpart.c index d24eeda2c..66f623165 100644 --- a/libs/video/renderer/sw/sw_rpart.c +++ b/libs/video/renderer/sw/sw_rpart.c @@ -68,40 +68,6 @@ R_DrawParticles (psystem_t *psystem) } } -static void -r_particles_nearclip_f (cvar_t *var) -{ - Cvar_SetValue (r_particles_nearclip, bound (r_nearclip->value, var->value, - r_farclip->value)); -} - -static void -r_particles_f (cvar_t *var) -{ - R_MaxParticlesCheck (var, r_particles_max); -} - -static void -r_particles_max_f (cvar_t *var) -{ - R_MaxParticlesCheck (r_particles, var); -} - -void -R_Particles_Init_Cvars (void) -{ - r_particles = Cvar_Get ("r_particles", "1", CVAR_ARCHIVE, r_particles_f, - "Toggles drawing of particles."); - r_particles_max = Cvar_Get ("r_particles_max", "2048", CVAR_ARCHIVE, - r_particles_max_f, "Maximum amount of " - "particles to display. No maximum, minimum " - "is 0."); - r_particles_nearclip = Cvar_Get ("r_particles_nearclip", "32", - CVAR_ARCHIVE, r_particles_nearclip_f, - "Distance of the particle near clipping " - "plane from the player."); -} - psystem_t * __attribute__((const))//FIXME sw_ParticleSystem (void) { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 0d5f5b640..f6a980710 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -214,7 +214,7 @@ gl_begin_frame (void) //update in sw modes but must in gl mode vr_data.scr_copyeverything = 1; - if (gl_clear->int_val) { + if (gl_clear) { qfglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } else { qfglClear (GL_DEPTH_BUFFER_BIT); @@ -222,7 +222,7 @@ gl_begin_frame (void) gl_ctx->begun = 1; - if (r_speeds->int_val) { + if (r_speeds) { gl_ctx->start_time = Sys_DoubleTime (); gl_ctx->brush_polys = 0; gl_ctx->alias_polys = 0; @@ -274,7 +274,7 @@ gl_draw_transparent (void) static void gl_post_process (framebuffer_t *src) { - if (scr_fisheye->int_val) { + if (scr_fisheye) { gl_FisheyeScreen (src); } else if (r_dowarp) { gl_WarpScreen (src); @@ -294,7 +294,7 @@ gl_set_2d (int scaled) static void gl_end_frame (void) { - if (r_speeds->int_val) { + if (r_speeds) { // qfglFinish (); double start_time = gl_ctx->start_time; double end_time = Sys_DoubleTime (); @@ -307,7 +307,7 @@ gl_end_frame (void) GL_FlushText (); qfglFlush (); - if (gl_finish->int_val) { + if (gl_finish) { gl_ctx->end_rendering (); gl_ctx->begun = 0; } @@ -440,8 +440,8 @@ gl_set_fov (float x, float y) float neard, fard; mat4f_t proj; - neard = r_nearclip->value; - fard = r_farclip->value; + neard = r_nearclip; + fard = r_farclip; // NOTE columns! proj[0] = (vec4f_t) { 1/x, 0, 0, 0 }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 5c93e36b1..b60624ae6 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -237,7 +237,7 @@ static void glsl_bind_framebuffer (framebuffer_t *fb); static void glsl_post_process (framebuffer_t *src) { - if (scr_fisheye->int_val) { + if (scr_fisheye) { glsl_FisheyeScreen (src); } else if (r_dowarp) { glsl_WarpScreen (src); @@ -387,8 +387,8 @@ glsl_set_fov (float x, float y) float neard, fard; mat4f_t proj; - neard = r_nearclip->value; - fard = r_farclip->value; + neard = r_nearclip; + fard = r_farclip; // NOTE columns! proj[0] = (vec4f_t) { 1/x, 0, 0, 0 }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 14e09d3d4..fdde33ec8 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -126,7 +126,7 @@ static void sw_bind_framebuffer (framebuffer_t *framebuffer); static void sw_begin_frame (void) { - if (r_numsurfs->int_val) { + if (r_numsurfs) { int surfcount = surface_p - surfaces; int max_surfs = surf_max - surfaces; if (surfcount > r_maxsurfsseen) @@ -136,7 +136,7 @@ sw_begin_frame (void) surfcount, max_surfs, r_maxsurfsseen); } - if (r_numedges->int_val) { + if (r_numedges) { int edgecount = edge_p - r_edges; if (edgecount > r_maxedgesseen) @@ -169,7 +169,7 @@ sw_draw_transparent (void) static void sw_post_process (framebuffer_t *src) { - if (scr_fisheye->int_val) { + if (scr_fisheye) { R_RenderFisheye (src); } else if (r_dowarp) { D_WarpScreen (src); @@ -184,10 +184,10 @@ sw_set_2d (int scaled) static void sw_end_frame (void) { - if (r_reportsurfout->int_val && r_outofsurfaces) + if (r_reportsurfout && r_outofsurfaces) Sys_Printf ("Short %d surfaces\n", r_outofsurfaces); - if (r_reportedgeout->int_val && r_outofedges) + if (r_reportedgeout && r_outofedges) Sys_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); // update one of three areas @@ -408,8 +408,8 @@ sw_set_fov (float x, float y) res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) / (320.0 * 152.0)) * (2.0 / hFOV); - r_aliastransition = r_aliastransbase->value * res_scale; - r_resfudge = r_aliastransadj->value * res_scale; + r_aliastransition = r_aliastransbase * res_scale; + r_resfudge = r_aliastransadj * res_scale; } static void diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index f845ce9c2..e23fa7244 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -601,7 +601,7 @@ vulkan_vid_render_choose_visual (void *data) Vulkan_CreateDevice (vulkan_ctx); if (!vulkan_ctx->device) { Sys_Error ("Unable to create Vulkan device.%s", - vulkan_use_validation->int_val ? "" + vulkan_use_validation ? "" : "\nSet vulkan_use_validation for details"); } vulkan_ctx->choose_visual (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index d8cc53c2d..f2dc5ffac 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -37,7 +37,7 @@ #include "util.h" -cvar_t *vulkan_use_validation; +int vulkan_use_validation; static uint32_t numLayers; static VkLayerProperties *instanceLayerProperties; @@ -81,7 +81,7 @@ get_instance_layers_and_extensions (vulkan_ctx_t *ctx) strset_add (instanceExtensions, extensions[i].extensionName); } - if (developer->int_val & SYS_vulkan) { + if (developer & SYS_vulkan) { for (i = 0; i < numLayers; i++) { Sys_Printf ("%s %x %u %s\n", layers[i].layerName, @@ -127,7 +127,7 @@ debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, void *data) { qfv_instance_t *instance = data; - if (!(messageSeverity & vulkan_use_validation->int_val)) { + if (!(messageSeverity & vulkan_use_validation)) { return 0; } const char *msgSev = ""; @@ -223,7 +223,7 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, uint32_t nlay = count_strings (layers) + 1; uint32_t next = count_strings (extensions) + count_strings (ctx->required_extensions) + 1; - if (vulkan_use_validation->int_val) { + if (vulkan_use_validation) { nlay += count_strings (vulkanValidationLayers); next += count_strings (debugExtensions); } @@ -235,7 +235,7 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, memset (ext, 0, next-- * sizeof (const char *)); merge_strings (lay, layers, 0); merge_strings (ext, extensions, ctx->required_extensions); - if (vulkan_use_validation->int_val) { + if (vulkan_use_validation) { merge_strings (lay, lay, vulkanValidationLayers); merge_strings (ext, ext, debugExtensions); } @@ -262,7 +262,7 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, ctx->instance = inst; load_instance_funcs (ctx); - if (vulkan_use_validation->int_val) { + if (vulkan_use_validation) { setup_debug_callback (inst); } diff --git a/libs/video/renderer/vulkan/projection.c b/libs/video/renderer/vulkan/projection.c index 701b52af2..260242f94 100644 --- a/libs/video/renderer/vulkan/projection.c +++ b/libs/video/renderer/vulkan/projection.c @@ -70,8 +70,8 @@ QFV_PerspectiveTan (mat4f_t proj, float fov_x, float fov_y) { float neard, fard; - neard = r_nearclip->value; - fard = r_farclip->value; + neard = r_nearclip; + fard = r_farclip; proj[0] = (vec4f_t) { 1 / fov_x, 0, 0, 0 }; proj[1] = (vec4f_t) { 0, 1 / fov_y, 0, 0 }; diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index 04936b310..ead9a7363 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -45,7 +45,7 @@ QFV_CreateRenderPass (qfv_device_t *device, VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; - if (developer->int_val & SYS_vulkan) { + if (developer & SYS_vulkan) { Sys_Printf ("attachments: %zd\n", attachments->size); for (size_t i = 0; i < attachments->size; i++) { Sys_Printf (" attachment: %zd\n", i); diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 20766233a..390f5dd3c 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -46,12 +46,12 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) ctx->surface, &numModes, modes); for (uint32_t i = 0; i < numModes; i++) { - if ((int) modes[i] == vulkan_presentation_mode->int_val) { + if ((int) modes[i] == vulkan_presentation_mode) { useMode = modes[i]; } } Sys_MaskPrintf (SYS_vulkan, "presentation mode: %d (%d)\n", useMode, - vulkan_presentation_mode->int_val); + vulkan_presentation_mode); VkSurfaceCapabilitiesKHR surfCaps; ifuncs->vkGetPhysicalDeviceSurfaceCapabilitiesKHR (physDev, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a29ba4742..d21f10d63 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -920,7 +920,7 @@ turb_begin (qfv_renderframe_t *rFrame) vulkan_ctx_t *ctx = rFrame->vulkan_ctx; bspctx_t *bctx = ctx->bsp_context; - bctx->default_color[3] = bound (0, r_wateralpha->value, 1); + bctx->default_color[3] = bound (0, r_wateralpha, 1); QuatCopy (bctx->default_color, bctx->last_color); @@ -1039,7 +1039,7 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bctx->color = 0; R_VisitWorldNodes (brush, ctx); - if (r_drawentities->int_val) { + if (r_drawentities) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; R_DrawBrushModel (ent, ctx); @@ -1453,7 +1453,7 @@ Vulkan_LoadSkys (const char *sky, vulkan_ctx_t *ctx) bctx->skybox_tex = 0; if (!sky || !*sky) { - sky = r_skyname->string; + sky = r_skyname; } if (!*sky || !strcasecmp (sky, "none")) { diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index a936f0b6f..f2d1678a7 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -627,10 +627,10 @@ Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx) { int x, y; - x = vid.conview->xlen / 2 + cl_crossx->int_val; - y = vid.conview->ylen / 2 + cl_crossy->int_val; + x = vid.conview->xlen / 2 + cl_crossx; + y = vid.conview->ylen / 2 + cl_crossy; - Vulkan_Draw_CrosshairAt (crosshair->int_val, x, y, ctx); + Vulkan_Draw_CrosshairAt (crosshair, x, y, ctx); } void diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 1eedc04ce..4bb82ecbc 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -66,7 +66,7 @@ void Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame) { - if (!r_drawentities->int_val) + if (!r_drawentities) return; #define RE_LOOP(type_name, Type) \ do { \ @@ -103,8 +103,8 @@ Vulkan_DrawViewModel (vulkan_ctx_t *ctx) { entity_t *ent = vr_data.view_model; if (vr_data.inhibit_viewmodel - || !r_drawviewmodel->int_val - || !r_drawentities->int_val + || !r_drawviewmodel + || !r_drawentities || !ent->renderer.model) return; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index e429f688b..4e9c5991a 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -81,6 +81,8 @@ #include "util.h" #include "vkparse.h" +#include "libs/video/renderer/vulkan/vkparse.hinc" + static const char quakeforge_pipeline[] = #include "libs/video/renderer/vulkan/qfpipeline.plc" ; @@ -89,96 +91,108 @@ static const char quakeforge_renderpass[] = #include "libs/video/renderer/vulkan/deferred.plc" ; -cvar_t *vulkan_frame_count; -cvar_t *vulkan_presentation_mode; -cvar_t *msaaSamples; +int vulkan_frame_count; +static cvar_t vulkan_frame_count_cvar = { + .name = "vulkan_frame_count", + .description = + "Number of frames to render in the background. More frames can " + "increase performance, but at the cost of latency. The default of 3 is" + " recommended.", + .default_value = "3", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &vulkan_frame_count }, +}; +int vulkan_presentation_mode; +static cvar_t vulkan_presentation_mode_cvar = { + .name = "vulkan_presentation_mode", + .description = + "desired presentation mode (may fall back to fifo).", + .default_value = "mailbox", + .flags = CVAR_NONE, + .value = { + .type = &VkPresentModeKHR_type, + .value = &vulkan_presentation_mode, + }, +}; +int msaaSamples; +static cvar_t msaaSamples_cvar = { + .name = "msaaSamples", + .description = + "desired MSAA sample size.", + .default_value = "VK_SAMPLE_COUNT_1_BIT", + .flags = CVAR_NONE, + .value = { .type = &VkSampleCountFlagBits_type, .value = &msaaSamples }, +}; +static exprenum_t validation_enum; +static exprtype_t validation_type = { + .name = "vulkan_use_validation", + .size = sizeof (int), + .binops = cexpr_flag_binops, + .unops = cexpr_flag_unops, + .data = &validation_enum, + .get_string = cexpr_flags_get_string, +}; + +static int validation_values[] = { + 0, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT, +}; +static exprsym_t validation_symbols[] = { + {"none", &validation_type, validation_values + 0}, + {"all", &validation_type, validation_values + 1}, + {} +}; +static exprtab_t validation_symtab = { + validation_symbols, +}; +static exprenum_t validation_enum = { + &validation_type, + &validation_symtab, +}; +static cvar_t vulkan_use_validation_cvar = { + .name = "vulkan_use_validation", + .description = + "enable KRONOS Validation Layer if available (requires instance " + "restart).", + .default_value = "error|warning", + .flags = CVAR_NONE, + .value = { .type = &validation_type, .value = &vulkan_use_validation }, +}; static void -parse_cvar_enum (const char *enum_name, const char *err_str, int err_val, - cvar_t *var) +vulkan_frame_count_f (void *data, const cvar_t *cvar) { - exprctx_t context = {}; - context.memsuper = new_memsuper(); - - if (cexpr_parse_enum (QFV_GetEnum (enum_name), var->string, - &context, &var->int_val)) { - Sys_Printf ("%s\n", err_str); - var->int_val = err_val; + if (vulkan_frame_count < 1) { + Sys_Printf ("Invalid frame count: %d. Setting to 1\n", + vulkan_frame_count); + vulkan_frame_count = 1; } - delete_memsuper (context.memsuper); -} - -static void -vulkan_presentation_mode_f (cvar_t *var) -{ - if (!strcmp (var->string, "immediate")) { - var->int_val = VK_PRESENT_MODE_IMMEDIATE_KHR; - } else if (!strcmp (var->string, "fifo")) { - var->int_val = VK_PRESENT_MODE_FIFO_KHR; - } else if (!strcmp (var->string, "relaxed")) { - var->int_val = VK_PRESENT_MODE_FIFO_RELAXED_KHR; - } else if (!strcmp (var->string, "mailbox")) { - var->int_val = VK_PRESENT_MODE_MAILBOX_KHR; - } else { - Sys_Printf ("Invalid presentation mode, using fifo\n"); - var->int_val = VK_PRESENT_MODE_FIFO_KHR; - } -} - -static void -vulkan_use_validation_f (cvar_t *var) -{ - if (!strcmp (var->string, "none")) { - var->int_val = 0; - } else if (!strcmp (var->string, "all")) { - var->int_val = VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT; - } else { - parse_cvar_enum ("VkDebugUtilsMessageSeverityFlagBitsEXT", - "Invalid validation flags, using all", - VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT, - var); - } -} - -static void -vulkan_frame_count_f (cvar_t *var) -{ - if (var->int_val < 1) { - Sys_Printf ("Invalid frame count: %d. Setting to 1\n", var->int_val); - Cvar_Set (var, "1"); - } -} - -static void -msaaSamples_f (cvar_t *var) -{ - parse_cvar_enum ("VkSampleCountFlagBits", "Invalid MSAA samples, using 1", - VK_SAMPLE_COUNT_1_BIT, var); } static void Vulkan_Init_Cvars (void) { - vulkan_use_validation = Cvar_Get ("vulkan_use_validation", - "error|warning", CVAR_NONE, - vulkan_use_validation_f, - "enable KRONOS Validation Layer if " - "available (requires instance " - "restart)."); + int num_syms = 0; + for (exprsym_t *sym = VkDebugUtilsMessageSeverityFlagBitsEXT_symbols; + sym->name; sym++, num_syms++) { + } + for (exprsym_t *sym = validation_symbols; sym->name; sym++, num_syms++) { + } + validation_symtab.symbols = calloc (num_syms + 1, sizeof (exprsym_t)); + num_syms = 0; + for (exprsym_t *sym = VkDebugUtilsMessageSeverityFlagBitsEXT_symbols; + sym->name; sym++, num_syms++) { + validation_symtab.symbols[num_syms] = *sym; + validation_symtab.symbols[num_syms].type = &validation_type; + } + for (exprsym_t *sym = validation_symbols; sym->name; sym++, num_syms++) { + validation_symtab.symbols[num_syms] = *sym; + } + Cvar_Register (&vulkan_use_validation_cvar, 0, 0); // FIXME implement fallback choices (instead of just fifo) - vulkan_presentation_mode = Cvar_Get ("vulkan_presentation_mode", "mailbox", - CVAR_NONE, vulkan_presentation_mode_f, - "desired presentation mode (may fall " - "back to fifo)."); - vulkan_frame_count = Cvar_Get ("vulkan_frame_count", "3", CVAR_NONE, - vulkan_frame_count_f, - "Number of frames to render in the" - " background. More frames can increase" - " performance, but at the cost of latency." - " The default of 3 is recommended."); - msaaSamples = Cvar_Get ("msaaSamples", "VK_SAMPLE_COUNT_1_BIT", - CVAR_NONE, msaaSamples_f, - "desired MSAA sample size."); + Cvar_Register (&vulkan_presentation_mode_cvar, 0, 0); + Cvar_Register (&vulkan_frame_count_cvar, vulkan_frame_count_f, 0); + Cvar_Register (&msaaSamples_cvar, 0, 0); R_Init_Cvars (); } @@ -254,7 +268,7 @@ Vulkan_CreateDevice (vulkan_ctx_t *ctx) //FIXME msaa and deferred rendering... //also, location ctx->msaaSamples = 1; - /*ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val, + /*ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples, QFV_GetMaxSampleCount (device->physDev)); if (ctx->msaaSamples > 1) { name = "renderpass_msaa"; @@ -703,7 +717,7 @@ Vulkan_CreateFrames (vulkan_ctx_t *ctx) DARRAY_INIT (&ctx->frames, 4); } - DARRAY_RESIZE (&ctx->frames, vulkan_frame_count->int_val); + DARRAY_RESIZE (&ctx->frames, vulkan_frame_count); __auto_type cmdBuffers = QFV_AllocCommandBufferSet (ctx->frames.size, alloca); diff --git a/libs/video/targets/context_sdl.c b/libs/video/targets/context_sdl.c index 91a0927de..a2464144b 100644 --- a/libs/video/targets/context_sdl.c +++ b/libs/video/targets/context_sdl.c @@ -52,12 +52,12 @@ VID_SetGamma (double gamma) } static void -VID_UpdateFullscreen (cvar_t *vid_fullscreen) +VID_UpdateFullscreen (void *data, const cvar_t *cvar) { if (!r_data || !viddef.initialized) return; - if ((vid_fullscreen->int_val && !(sdl_screen->flags & SDL_FULLSCREEN)) - || (!vid_fullscreen->int_val && sdl_screen->flags & SDL_FULLSCREEN)) + if ((cvar && !(sdl_screen->flags & SDL_FULLSCREEN)) + || (!cvar && sdl_screen->flags & SDL_FULLSCREEN)) if (!SDL_WM_ToggleFullScreen (sdl_screen)) Sys_Printf ("VID_UpdateFullscreen: error setting fullscreen\n"); IN_UpdateGrab (in_grab); @@ -66,9 +66,6 @@ VID_UpdateFullscreen (cvar_t *vid_fullscreen) void SDL_Init_Cvars (void) { - vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE, - VID_UpdateFullscreen, - "Toggles fullscreen mode"); - vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, - "Use system gamma control if available"); + Cvar_Register (&vid_fullscreen_cvar, VID_UpdateFullscreen, 0); + Cvar_Register (&vid_system_gamma_cvar, 0, 0); } diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index 55a6910c9..0d3d8e973 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -56,28 +56,156 @@ sw_ctx_t *win_sw_context; #define NO_MODE (MODE_WINDOWED - 1) #define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 3) -cvar_t *vid_ddraw; +int vid_ddraw; +static cvar_t vid_ddraw_cvar = { + .name = "vid_ddraw", + .description = + "", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &vid_ddraw }, +}; // Note that 0 is MODE_WINDOWED -static cvar_t *vid_mode; +static int vid_mode; +static cvar_t vid_mode_cvar = { + .name = "vid_mode", + .description = + "", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &vid_mode }, +}; // Note that 0 is MODE_WINDOWED -static cvar_t *_vid_default_mode; +static char *_vid_default_mode; +static cvar_t _vid_default_mode_cvar = { + .name = "_vid_default_mode", + .description = + "", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &_vid_default_mode }, +}; // Note that 3 is MODE_FULLSCREEN_DEFAULT -static cvar_t *_vid_default_mode_win; -static cvar_t *vid_wait; -static cvar_t *vid_nopageflip; -static cvar_t *_vid_wait_override; -static cvar_t *vid_config_x; -static cvar_t *vid_config_y; -static cvar_t *vid_stretch_by_2; -static cvar_t *_windowed_mouse; -static cvar_t *vid_fullscreen_mode; -static cvar_t *vid_windowed_mode; -static cvar_t *block_switch; -static cvar_t *vid_window_x; -static cvar_t *vid_window_y; +static int _vid_default_mode_win; +static cvar_t _vid_default_mode_win_cvar = { + .name = "_vid_default_mode_win", + .description = + "", + .default_value = "3", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &_vid_default_mode_win }, +}; +static char *vid_wait; +static cvar_t vid_wait_cvar = { + .name = "vid_wait", + .description = + "", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &vid_wait }, +}; +static char *vid_nopageflip; +static cvar_t vid_nopageflip_cvar = { + .name = "vid_nopageflip", + .description = + "", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &vid_nopageflip }, +}; +static char *_vid_wait_override; +static cvar_t _vid_wait_override_cvar = { + .name = "_vid_wait_override", + .description = + "", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &_vid_wait_override }, +}; +static char *vid_config_x; +static cvar_t vid_config_x_cvar = { + .name = "vid_config_x", + .description = + "", + .default_value = "800", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &vid_config_x }, +}; +static char *vid_config_y; +static cvar_t vid_config_y_cvar = { + .name = "vid_config_y", + .description = + "", + .default_value = "600", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &vid_config_y }, +}; +static char *vid_stretch_by_2; +static cvar_t vid_stretch_by_2_cvar = { + .name = "vid_stretch_by_2", + .description = + "", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &vid_stretch_by_2 }, +}; +static int _windowed_mouse; +static cvar_t _windowed_mouse_cvar = { + .name = "_windowed_mouse", + .description = + "", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &_windowed_mouse }, +}; +static int vid_fullscreen_mode; +static cvar_t vid_fullscreen_mode_cvar = { + .name = "vid_fullscreen_mode", + .description = + "", + .default_value = "3", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &vid_fullscreen_mode }, +}; +static int vid_windowed_mode; +static cvar_t vid_windowed_mode_cvar = { + .name = "vid_windowed_mode", + .description = + "", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &vid_windowed_mode }, +}; +static char *block_switch; +static cvar_t block_switch_cvar = { + .name = "block_switch", + .description = + "", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &block_switch }, +}; +static int vid_window_x; +static cvar_t vid_window_x_cvar = { + .name = "vid_window_x", + .description = + "", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &vid_window_x }, +}; +static int vid_window_y; +static cvar_t vid_window_y_cvar = { + .name = "vid_window_y", + .description = + "", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &vid_window_y }, +}; //FIXME?int yeahimconsoled; @@ -168,8 +296,8 @@ VID_RememberWindowPos (void) if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) && (rect.top < GetSystemMetrics (SM_CYSCREEN)) && (rect.right > 0) && (rect.bottom > 0)) { - Cvar_SetValue (vid_window_x, (float) rect.left); - Cvar_SetValue (vid_window_y, (float) rect.top); + vid_window_x = rect.left; + vid_window_y = rect.top; } } } @@ -178,11 +306,11 @@ VID_RememberWindowPos (void) static void VID_CheckWindowXY (void) { - if ((vid_window_x->int_val > (GetSystemMetrics (SM_CXSCREEN) - 160)) || - (vid_window_y->int_val > (GetSystemMetrics (SM_CYSCREEN) - 120)) || - (vid_window_x->int_val < 0) || (vid_window_y->int_val < 0)) { - Cvar_SetValue (vid_window_x, 0.0); - Cvar_SetValue (vid_window_y, 0.0); + if ((vid_window_x > (GetSystemMetrics (SM_CXSCREEN) - 160)) || + (vid_window_y > (GetSystemMetrics (SM_CYSCREEN) - 120)) || + (vid_window_x < 0) || (vid_window_y < 0)) { + vid_window_x = 0.0; + vid_window_y = 0.0; } } #endif @@ -391,8 +519,8 @@ VID_SetWindowedMode (int modenum) #if 0 if (!windowed_mode_set) { if (COM_CheckParm ("-resetwinpos")) { - Cvar_SetValue (vid_window_x, 0.0); - Cvar_SetValue (vid_window_y, 0.0); + vid_window_x = 0.0; + vid_window_y = 0.0; } windowed_mode_set = true; @@ -430,8 +558,8 @@ VID_SetWindowedMode (int modenum) // position and show the DIB window VID_CheckWindowXY (); - SetWindowPos (win_mainwindow, NULL, vid_window_x->int_val, - vid_window_y->int_val, 0, 0, + SetWindowPos (win_mainwindow, NULL, vid_window_x, + vid_window_y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); if (force_minimized) @@ -600,9 +728,9 @@ VID_SetMode (int modenum, const byte *palette) modenum = vid_default; } - Cvar_SetValue (vid_mode, (float) modenum); + vid_mode = modenum; } else { - Cvar_SetValue (vid_mode, (float) vid_modenum); + vid_mode = vid_modenum; return 0; } } @@ -622,7 +750,7 @@ VID_SetMode (int modenum, const byte *palette) // Set either the fullscreen or windowed mode if (modelist[modenum].type == MS_WINDOWED) { - if (_windowed_mouse->int_val) { + if (_windowed_mouse) { stat = VID_SetWindowedMode (modenum); IN_ActivateMouse (); IN_HideMouse (); @@ -663,7 +791,7 @@ VID_SetMode (int modenum, const byte *palette) ReleaseDC (NULL, hdc); vid_modenum = modenum; - Cvar_SetValue (vid_mode, (float) vid_modenum); + vid_mode = vid_modenum; while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); @@ -776,7 +904,7 @@ VID_HandlePause static void __attribute__ ((used)) VID_HandlePause (qboolean pause) { - if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val) { + if ((modestate == MS_WINDOWED) && _windowed_mouse) { if (pause) { IN_DeactivateMouse (); IN_ShowMouse (); @@ -957,13 +1085,13 @@ VID_TestMode_f (void) static void VID_Windowed_f (void) { - VID_SetMode (vid_windowed_mode->int_val, vid_curpal); + VID_SetMode (vid_windowed_mode, vid_curpal); } static void VID_Fullscreen_f (void) { - VID_SetMode (vid_fullscreen_mode->int_val, vid_curpal); + VID_SetMode (vid_fullscreen_mode, vid_curpal); } static void @@ -1018,35 +1146,22 @@ Win_SetGamma (double gamma) void Win_Init_Cvars (void) { - vid_ddraw = Cvar_Get ("vid_ddraw", "1", CVAR_NONE, 0, ""); - vid_mode = Cvar_Get ("vid_mode", "0", CVAR_NONE, 0, ""); - vid_wait = Cvar_Get ("vid_wait", "0", CVAR_NONE, 0, ""); - vid_nopageflip = - Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE, 0, ""); - _vid_wait_override = - Cvar_Get ("_vid_wait_override", "0", CVAR_ARCHIVE, 0, ""); - _vid_default_mode = - Cvar_Get ("_vid_default_mode", "0", CVAR_ARCHIVE, 0, ""); - _vid_default_mode_win = - Cvar_Get ("_vid_default_mode_win", "3", CVAR_ARCHIVE, 0, ""); - vid_config_x = - Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE, 0, ""); - vid_config_y = - Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE, 0, ""); - vid_stretch_by_2 = - Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE, 0, ""); - _windowed_mouse = - Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, 0, ""); - vid_fullscreen_mode = - Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE, 0, ""); - vid_windowed_mode = - Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE, 0, ""); - block_switch = - Cvar_Get ("block_switch", "0", CVAR_ARCHIVE, 0, ""); - vid_window_x = - Cvar_Get ("vid_window_x", "0", CVAR_ARCHIVE, 0, ""); - vid_window_y = - Cvar_Get ("vid_window_y", "0", CVAR_ARCHIVE, 0, ""); + Cvar_Register (&vid_ddraw_cvar, 0, 0); + Cvar_Register (&vid_mode_cvar, 0, 0); + Cvar_Register (&vid_wait_cvar, 0, 0); + Cvar_Register (&vid_nopageflip_cvar, 0, 0); + Cvar_Register (&_vid_wait_override_cvar, 0, 0); + Cvar_Register (&_vid_default_mode_cvar, 0, 0); + Cvar_Register (&_vid_default_mode_win_cvar, 0, 0); + Cvar_Register (&vid_config_x_cvar, 0, 0); + Cvar_Register (&vid_config_y_cvar, 0, 0); + Cvar_Register (&vid_stretch_by_2_cvar, 0, 0); + Cvar_Register (&_windowed_mouse_cvar, 0, 0); + Cvar_Register (&vid_fullscreen_mode_cvar, 0, 0); + Cvar_Register (&vid_windowed_mode_cvar, 0, 0); + Cvar_Register (&block_switch_cvar, 0, 0); + Cvar_Register (&vid_window_x_cvar, 0, 0); + Cvar_Register (&vid_window_y_cvar, 0, 0); Cmd_AddCommand ("vid_testmode", VID_TestMode_f, ""); Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, ""); diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 0f960d7a4..468d29da7 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -125,7 +125,16 @@ static int accel_threshold; static Atom x_net_state; static Atom x_net_fullscreen; -static cvar_t *x11_vidmode; +static int x11_vidmode; +static cvar_t x11_vidmode_cvar = { + .name = "x11_vidmode", + .description = + "Use x11 vidmode extension to set video mode (not recommended for " + "modern systems)", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &x11_vidmode }, +}; static void set_fullscreen (int full) @@ -355,7 +364,7 @@ X11_GetGamma (void) XF86VidModeGamma xgamma; vec3_t *temp; - if (vid_gamma_avail && vid_system_gamma->int_val) { + if (vid_gamma_avail && vid_system_gamma) { if (XF86VidModeGetGamma (x_disp, x_screen, &xgamma)) { if ((temp = malloc (sizeof (vec3_t)))) { (*temp)[0] = xgamma.red; @@ -379,12 +388,12 @@ X11_SetVidMode (int width, int height) if (vidmode_active) return; - if (!x11_vidmode->int_val) { + if (!x11_vidmode) { return; } if (str && (tolower (*str) == 'f')) { - Cvar_Set (vid_fullscreen, "1"); + Cvar_Set ("vid_fullscreen", "1"); } #ifdef HAVE_VIDMODE @@ -412,7 +421,7 @@ X11_SetVidMode (int width, int height) } - if (vid_fullscreen->int_val && vidmode_avail) { + if (vid_fullscreen && vidmode_avail) { int i, dotclock; int best_mode = 0; qboolean found_mode = false; @@ -430,7 +439,7 @@ X11_SetVidMode (int width, int height) (vidmodes[i]->vdisplay == orig_data.vdisplay)) { original_mode = i; } - if (developer->int_val & SYS_vid) { + if (developer & SYS_vid) { Sys_Printf ("VID:%c%dx%d\n", original_mode == i ? '*' : ' ', vidmodes[i]->hdisplay, vidmodes[i]->vdisplay); @@ -471,13 +480,13 @@ X11_SetVidMode (int width, int height) #endif } -static void -X11_UpdateFullscreen (cvar_t *fullscreen) +void +X11_UpdateFullscreen (int fullscreen) { if (!vid_context_created) return; - if (!fullscreen->int_val) { + if (!fullscreen) { X11_RestoreVidMode (); set_fullscreen (0); IN_UpdateGrab (in_grab); @@ -500,14 +509,7 @@ X11_Init_Cvars (void) { Cmd_AddCommand ("vid_center", VID_Center_f, "Center the view port on the " "quake window in a virtual desktop.\n"); - vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE, - &X11_UpdateFullscreen, - "Toggles fullscreen game mode"); - vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, - "Use system gamma control if available"); - x11_vidmode = Cvar_Get ("x11_vidmode", "0", CVAR_ROM, 0, - "Use x11 vidmode extension to set video mode " - "(not recommended for modern systems)"); + Cvar_Register (&x11_vidmode_cvar, 0, 0); } void @@ -573,9 +575,7 @@ X11_CreateWindow (int width, int height) vid_context_created = true; XRaiseWindow (x_disp, x_win); X11_WaitForEvent (VisibilityNotify); - if (vid_fullscreen->int_val) { - X11_UpdateFullscreen (vid_fullscreen); - } + X11_UpdateFullscreen (vid_fullscreen); } void @@ -615,7 +615,7 @@ X11_SetGamma (double gamma) #ifdef HAVE_VIDMODE XF86VidModeGamma xgamma; - if (vid_gamma_avail && vid_system_gamma->int_val && x_have_focus) { + if (vid_gamma_avail && vid_system_gamma && x_have_focus) { xgamma.red = xgamma.green = xgamma.blue = (float) gamma; if (XF86VidModeSetGamma (x_disp, x_screen, &xgamma)) return true; diff --git a/libs/video/targets/in_sdl.c b/libs/video/targets/in_sdl.c index 7ad9c727d..d61a3a5e7 100644 --- a/libs/video/targets/in_sdl.c +++ b/libs/video/targets/in_sdl.c @@ -43,7 +43,15 @@ #include "compat.h" -cvar_t *in_snd_block; +int in_snd_block; +static cvar_t in_snd_block_cvar = { + .name = "in_snd_block", + .description = + "block sound output on window focus loss", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &in_snd_block }, +}; static int have_focus = 1; @@ -53,7 +61,7 @@ event_focusout (void) { if (have_focus) { have_focus = 0; - if (in_snd_block->int_val) { + if (in_snd_block) { S_BlockSound (); CDAudio_Pause (); } @@ -64,7 +72,7 @@ static void event_focusin (void) { have_focus = 1; - if (in_snd_block->int_val) { + if (in_snd_block) { S_UnblockSound (); CDAudio_Resume (); } @@ -599,8 +607,7 @@ IN_LL_Init (void) void IN_LL_Init_Cvars (void) { - in_snd_block = Cvar_Get ("in_snd_block", "0", CVAR_ARCHIVE, NULL, - "block sound output on window focus loss"); + Cvar_Register (&in_snd_block_cvar, 0, 0); } void diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index e9cc1a331..261173511 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -1037,7 +1037,7 @@ Win_Activate (BOOL active, BOOL minimize) win_gdevmode.dmPelsHeight, false); } } - else if ((modestate == MS_WINDOWED) && in_grab->int_val + else if ((modestate == MS_WINDOWED) && in_grab && win_in_game) { IN_ActivateMouse (); IN_HideMouse (); @@ -1050,7 +1050,7 @@ Win_Activate (BOOL active, BOOL minimize) ChangeDisplaySettings (NULL, 0); vid_wassuspended = true; } - } else if ((modestate == MS_WINDOWED) && in_grab->int_val) { + } else if ((modestate == MS_WINDOWED) && in_grab) { IN_DeactivateMouse (); IN_ShowMouse (); } diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 5395ea639..f7552c424 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -132,10 +132,43 @@ static x11_device_t x11_mouse_device = { x11_mouse_axes, x11_mouse_buttons, }; -cvar_t *in_auto_focus; -cvar_t *in_snd_block; -cvar_t *in_dga; -cvar_t *in_mouse_accel; +int in_auto_focus; +static cvar_t in_auto_focus_cvar = { + .name = "in_auto_focus", + .description = + "grab input focus when the mouse enters the window when using xinput2 " + "with certain window managers using focus-follows-mouse (eg, openbox)", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &in_auto_focus }, +}; +int in_snd_block; +static cvar_t in_snd_block_cvar = { + .name = "in_snd_block", + .description = + "block sound output on window focus loss", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &in_snd_block }, +}; +char *in_dga; +static cvar_t in_dga_cvar = { + .name = "in_dga", + .description = + "DGA Input support", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &in_dga }, +}; +int in_mouse_accel; +static cvar_t in_mouse_accel_cvar = { + .name = "in_mouse_accel", + .description = + "set to 0 to remove mouse acceleration", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &in_mouse_accel }, +}; static qboolean dga_avail; static qboolean dga_active; @@ -190,9 +223,9 @@ dga_off (void) } static void -in_dga_f (cvar_t *var) +in_dga_f (void *data, const cvar_t *cvar) { - if (var->int_val && input_grabbed) { + if (in_dga && input_grabbed) { Sys_MaskPrintf (SYS_vid, "VID: in_dga_f on\n"); dga_on (); } else { @@ -202,9 +235,9 @@ in_dga_f (cvar_t *var) } static void -in_mouse_accel_f (cvar_t *var) +in_mouse_accel_f (void *data, const cvar_t *cvar) { - if (var->int_val) { + if (in_mouse_accel) { X11_RestoreMouseAcceleration (); } else { X11_SaveMouseAcceleration (); @@ -232,7 +265,7 @@ enter_notify (XEvent *event) x11_mouse.x = event->xmotion.x; x11_mouse.y = event->xmotion.y; - if (!x_have_focus && (!in_auto_focus || in_auto_focus->int_val)) { + if (!x_have_focus && in_auto_focus) { XSetInputFocus (x_disp, x_win, RevertToPointerRoot, CurrentTime); } } @@ -661,7 +694,7 @@ event_focusout (XEvent *event) if (x_have_focus) { x_have_focus = false; in_x11_send_focus_event (0); - if (in_snd_block->int_val) { + if (in_snd_block) { S_BlockSound (); CDAudio_Pause (); } @@ -674,11 +707,11 @@ event_focusin (XEvent *event) { in_x11_send_focus_event (1); x_have_focus = true; - if (in_snd_block->int_val) { + if (in_snd_block) { S_UnblockSound (); CDAudio_Resume (); } - VID_UpdateGamma (vid_gamma); + VID_UpdateGamma (); } static void @@ -799,7 +832,7 @@ event_motion (XEvent *event) x11_mouse_axes[0].value = event->xmotion.x_root; x11_mouse_axes[1].value = event->xmotion.y_root; } else { - if (vid_fullscreen->int_val || input_grabbed) { + if (vid_fullscreen || input_grabbed) { if (!event->xmotion.send_event) { int center_x = viddef.width / 2; int center_y = viddef.height / 2; @@ -1140,7 +1173,7 @@ in_x11_grab_input (void *data, int grab) #endif if (vid_fullscreen) - grab = grab || vid_fullscreen->int_val; + grab = grab || vid_fullscreen; if ((input_grabbed && grab) || (!input_grabbed && !grab)) return; @@ -1162,12 +1195,12 @@ in_x11_grab_input (void *data, int grab) return; } input_grabbed = 1; - in_dga_f (in_dga); + in_dga_f (0, &in_dga_cvar); } else { XUngrabPointer (x_disp, CurrentTime); XUngrabKeyboard (x_disp, CurrentTime); input_grabbed = 0; - in_dga_f (in_dga); + in_dga_f (0, &in_dga_cvar); } } #ifdef X11_USE_SELECT @@ -1340,7 +1373,7 @@ in_x11_shutdown (void *data) // XAutoRepeatOn (x_disp); dga_off (); } - if (in_mouse_accel && !in_mouse_accel->int_val) + if (!in_mouse_accel) X11_RestoreMouseAcceleration (); } @@ -1361,18 +1394,10 @@ in_x11_get_device_event_data (void *device, void *data) static void in_x11_init_cvars (void *data) { - in_auto_focus = Cvar_Get ("in_auto_focus", "1", CVAR_ARCHIVE, 0, - "grab input focus when the mouse enters the" - " window when using xinput2 with certain" - " window managers using focus-follows-mouse" - " (eg, openbox)"); - in_snd_block = Cvar_Get ("in_snd_block", "0", CVAR_ARCHIVE, NULL, - "block sound output on window focus loss"); - in_dga = Cvar_Get ("in_dga", "0", CVAR_ARCHIVE, in_dga_f, - "DGA Input support"); - in_mouse_accel = Cvar_Get ("in_mouse_accel", "1", CVAR_ARCHIVE, - in_mouse_accel_f, - "set to 0 to remove mouse acceleration"); + Cvar_Register (&in_auto_focus_cvar, 0, 0); + Cvar_Register (&in_snd_block_cvar, 0, 0); + Cvar_Register (&in_dga_cvar, in_dga_f, 0); + Cvar_Register (&in_mouse_accel_cvar, in_mouse_accel_f, 0); } static void diff --git a/libs/video/targets/joy.c b/libs/video/targets/joy.c index 3ff827726..c08174a80 100644 --- a/libs/video/targets/joy.c +++ b/libs/video/targets/joy.c @@ -42,10 +42,42 @@ #include "compat.h" #include -cvar_t *joy_device; // Joystick device name -cvar_t *joy_enable; // Joystick enabling flag -cvar_t *joy_amp; // Joystick amplification -cvar_t *joy_pre_amp; // Joystick pre-amplification +char *joy_device; +static cvar_t joy_device_cvar = { + .name = "joy_device", + .description = + "Joystick device", + .default_value = "none", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &joy_device }, +}; +int joy_enable; +static cvar_t joy_enable_cvar = { + .name = "joy_enable", + .description = + "Joystick enable flag", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &joy_enable }, +}; +float joy_amp; +static cvar_t joy_amp_cvar = { + .name = "joy_amp", + .description = + "Joystick amplification", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &joy_amp }, +}; +float joy_pre_amp; +static cvar_t joy_pre_amp_cvar = { + .name = "joy_pre_amp", + .description = + "Joystick pre-amplification", + .default_value = "0.01", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &joy_pre_amp }, +}; qboolean joy_found = false; qboolean joy_active = false; @@ -117,11 +149,11 @@ JOY_Move (void) { struct joy_axis *ja; float value; - float amp = joy_amp->value * in_amp->value; - float pre = joy_pre_amp->value * in_pre_amp->value; + float amp = joy_amp * in_amp; + float pre = joy_pre_amp * in_pre_amp; int i; - if (!joy_active || !joy_enable->int_val) + if (!joy_active || !joy_enable) return; for (i = 0; i < JOY_MAX_AXES; i++) { @@ -164,7 +196,7 @@ JOY_Init (void) joy_found = true; - if (!joy_enable->int_val) { + if (!joy_enable) { Sys_MaskPrintf (SYS_vid, "JOY: Joystick found, but not enabled.\n"); joy_active = false; JOY_Close (); @@ -181,9 +213,9 @@ JOY_Init (void) } static void -joyamp_f (cvar_t *var) +joyamp_f (void *data, const cvar_t *cvar) { - Cvar_Set (var, va (0, "%g", max (0.0001, var->value))); + Cvar_SetVar (cvar, va (0, "%g", max (0.0001, *(float *)data))); } typedef struct { @@ -465,14 +497,10 @@ JOY_Init_Cvars (void) { int i; - joy_device = Cvar_Get ("joy_device", "/dev/input/js0", - CVAR_ROM, 0, "Joystick device"); - joy_enable = Cvar_Get ("joy_enable", "1", CVAR_ARCHIVE, 0, - "Joystick enable flag"); - joy_amp = Cvar_Get ("joy_amp", "1", CVAR_ARCHIVE, joyamp_f, - "Joystick amplification"); - joy_pre_amp = Cvar_Get ("joy_pre_amp", "0.01", CVAR_ARCHIVE, - joyamp_f, "Joystick pre-amplification"); + Cvar_Register (&joy_device_cvar, 0, 0); + Cvar_Register (&joy_enable_cvar, 0, 0); + Cvar_Register (&joy_amp_cvar, joyamp_f, &joy_amp); + Cvar_Register (&joy_pre_amp_cvar, joyamp_f, &joy_pre_amp); Cmd_AddCommand ("in_joy", in_joy_f, "Configures the joystick behaviour"); diff --git a/libs/video/targets/joy_linux.c b/libs/video/targets/joy_linux.c index c0869553d..3a7e65a09 100644 --- a/libs/video/targets/joy_linux.c +++ b/libs/video/targets/joy_linux.c @@ -48,7 +48,7 @@ JOY_Read (void) { struct js_event event; - if (!joy_active || !joy_enable->int_val) + if (!joy_active || !joy_enable) return; while (read (joy_handle, &event, sizeof (struct js_event)) > -1) { @@ -82,7 +82,7 @@ int JOY_Open (void) { // Open joystick device - joy_handle = open (joy_device->string, O_RDONLY | O_NONBLOCK); + joy_handle = open (joy_device, O_RDONLY | O_NONBLOCK); if (joy_handle < 0) { return -1; } diff --git a/libs/video/targets/joy_win.c b/libs/video/targets/joy_win.c index f42b5022a..65c4d600c 100644 --- a/libs/video/targets/joy_win.c +++ b/libs/video/targets/joy_win.c @@ -46,7 +46,15 @@ #include "compat.h" // Joystick variables and structures -cvar_t *joy_sensitivity; // Joystick sensitivity +char *joy_sensitivity; +static cvar_t joy_sensitivity_cvar = { + .name = "joy_sensitivity", + .description = + "Joystick sensitivity", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &joy_sensitivity }, +}; // joystick defines and variables // where should defines be moved? @@ -82,27 +90,187 @@ JOYINFOEX ji; // when changing from one controller to another. this way at least something // works. -cvar_t *in_joystick; -cvar_t *joy_name; -cvar_t *joy_advanced; -cvar_t *joy_advaxisx; -cvar_t *joy_advaxisy; -cvar_t *joy_advaxisz; -cvar_t *joy_advaxisr; -cvar_t *joy_advaxisu; -cvar_t *joy_advaxisv; -cvar_t *joy_forwardthreshold; -cvar_t *joy_sidethreshold; -cvar_t *joy_pitchthreshold; -cvar_t *joy_yawthreshold; -cvar_t *joy_forwardsensitivity; -cvar_t *joy_sidesensitivity; -cvar_t *joy_pitchsensitivity; -cvar_t *joy_yawsensitivity; -cvar_t *joy_wwhack1; -cvar_t *joy_wwhack2; +char *in_joystick; +static cvar_t in_joystick_cvar = { + .name = "joystick", + .description = + "FIXME: No Description", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &in_joystick }, +}; +char *joy_name; +static cvar_t joy_name_cvar = { + .name = "joyname", + .description = + "FIXME: No Description", + .default_value = "joystick", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &joy_name }, +}; +int joy_advanced; +static cvar_t joy_advanced_cvar = { + .name = "joyadvanced", + .description = + "FIXME: No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &joy_advanced }, +}; +int joy_advaxisx; +static cvar_t joy_advaxisx_cvar = { + .name = "joyadvaxisx", + .description = + "FIXME: No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &joy_advaxisx }, +}; +int joy_advaxisy; +static cvar_t joy_advaxisy_cvar = { + .name = "joyadvaxisy", + .description = + "FIXME: No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &joy_advaxisy }, +}; +int joy_advaxisz; +static cvar_t joy_advaxisz_cvar = { + .name = "joyadvaxisz", + .description = + "FIXME: No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &joy_advaxisz }, +}; +int joy_advaxisr; +static cvar_t joy_advaxisr_cvar = { + .name = "joyadvaxisr", + .description = + "FIXME: No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &joy_advaxisr }, +}; +int joy_advaxisu; +static cvar_t joy_advaxisu_cvar = { + .name = "joyadvaxisu", + .description = + "FIXME: No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &joy_advaxisu }, +}; +int joy_advaxisv; +static cvar_t joy_advaxisv_cvar = { + .name = "joyadvaxisv", + .description = + "FIXME: No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &joy_advaxisv }, +}; +char *joy_forwardthreshold; +static cvar_t joy_forwardthreshold_cvar = { + .name = "joyforwardthreshold", + .description = + "FIXME: No Description", + .default_value = "0.15", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &joy_forwardthreshold }, +}; +char *joy_sidethreshold; +static cvar_t joy_sidethreshold_cvar = { + .name = "joysidethreshold", + .description = + "FIXME: No Description", + .default_value = "0.15", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &joy_sidethreshold }, +}; +char *joy_pitchthreshold; +static cvar_t joy_pitchthreshold_cvar = { + .name = "joypitchthreshold", + .description = + "FIXME: No Description", + .default_value = "0.15", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &joy_pitchthreshold }, +}; +char *joy_yawthreshold; +static cvar_t joy_yawthreshold_cvar = { + .name = "joyyawthreshold", + .description = + "FIXME: No Description", + .default_value = "0.15", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &joy_yawthreshold }, +}; +char *joy_forwardsensitivity; +static cvar_t joy_forwardsensitivity_cvar = { + .name = "joyforwardsensitivity", + .description = + "FIXME: No Description", + .default_value = "-1.0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &joy_forwardsensitivity }, +}; +char *joy_sidesensitivity; +static cvar_t joy_sidesensitivity_cvar = { + .name = "joysidesensitivity", + .description = + "FIXME: No Description", + .default_value = "-1.0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &joy_sidesensitivity }, +}; +char *joy_pitchsensitivity; +static cvar_t joy_pitchsensitivity_cvar = { + .name = "joypitchsensitivity", + .description = + "FIXME: No Description", + .default_value = "1.0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &joy_pitchsensitivity }, +}; +char *joy_yawsensitivity; +static cvar_t joy_yawsensitivity_cvar = { + .name = "joyyawsensitivity", + .description = + "FIXME: No Description", + .default_value = "-1.0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &joy_yawsensitivity }, +}; +int joy_wwhack1; +static cvar_t joy_wwhack1_cvar = { + .name = "joywwhack1", + .description = + "FIXME: No Description", + .default_value = "0.0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &joy_wwhack1 }, +}; +char *joy_wwhack2; +static cvar_t joy_wwhack2_cvar = { + .name = "joywwhack2", + .description = + "FIXME: No Description", + .default_value = "0.0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &joy_wwhack2 }, +}; -cvar_t *joy_debug; +int joy_debug; +static cvar_t joy_debug_cvar = { + .name = "joy_debug", + .description = + "FIXME: No Description", + .default_value = "0.0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &joy_debug }, +}; qboolean joy_advancedinit, joy_haspov; DWORD joy_oldbuttonstate, joy_oldpovstate; @@ -142,10 +310,10 @@ _JOY_Read (void) // DInput driver that causes it to make 32668 the center point // instead // of 32768 - if (joy_wwhack1->int_val) { + if (joy_wwhack1) { ji.dwUpos += 100; } - if (joy_debug->int_val) { + if (joy_debug) { if (ji.dwXpos) Sys_Printf("X: %ld\n",ji.dwXpos); if (ji.dwYpos) Sys_Printf("Y: %ld\n",ji.dwYpos); if (ji.dwZpos) Sys_Printf("Z: %ld\n",ji.dwZpos); @@ -306,7 +474,7 @@ JOY_AdvancedUpdate_f (void) pdwRawValue[i] = RawValuePointer (i); } - if (joy_advanced->int_val) { + if (joy_advanced) { // default joystick initialization // only 2 axes with joystick control dwAxisMap[JOY_AXIS_X] = AxisTurn; @@ -314,28 +482,28 @@ JOY_AdvancedUpdate_f (void) dwAxisMap[JOY_AXIS_Y] = AxisForward; // dwControlMap[JOY_AXIS_Y] = JOY_ABSOLUTE_AXIS; } else { - if (strcmp (joy_name->string, "joystick") != 0) { + if (strcmp (joy_name, "joystick") != 0) { // notify user of advanced controller - Sys_Printf ("\n%s configured\n\n", joy_name->string); + Sys_Printf ("\n%s configured\n\n", joy_name); } // advanced initialization here // data supplied by user via joy_axisn cvars - dwTemp = joy_advaxisx->int_val; + dwTemp = joy_advaxisx; dwAxisMap[JOY_AXIS_X] = dwTemp & 0x0000000f; dwControlMap[JOY_AXIS_X] = dwTemp & JOY_RELATIVE_AXIS; - dwTemp = joy_advaxisy->int_val; + dwTemp = joy_advaxisy; dwAxisMap[JOY_AXIS_Y] = dwTemp & 0x0000000f; dwControlMap[JOY_AXIS_Y] = dwTemp & JOY_RELATIVE_AXIS; - dwTemp = joy_advaxisz->int_val; + dwTemp = joy_advaxisz; dwAxisMap[JOY_AXIS_Z] = dwTemp & 0x0000000f; dwControlMap[JOY_AXIS_Z] = dwTemp & JOY_RELATIVE_AXIS; - dwTemp = joy_advaxisr->int_val; + dwTemp = joy_advaxisr; dwAxisMap[JOY_AXIS_R] = dwTemp & 0x0000000f; dwControlMap[JOY_AXIS_R] = dwTemp & JOY_RELATIVE_AXIS; - dwTemp = joy_advaxisu->int_val; + dwTemp = joy_advaxisu; dwAxisMap[JOY_AXIS_U] = dwTemp & 0x0000000f; dwControlMap[JOY_AXIS_U] = dwTemp & JOY_RELATIVE_AXIS; - dwTemp = joy_advaxisv->int_val; + dwTemp = joy_advaxisv; dwAxisMap[JOY_AXIS_V] = dwTemp & 0x0000000f; dwControlMap[JOY_AXIS_V] = dwTemp & JOY_RELATIVE_AXIS; } @@ -353,52 +521,30 @@ void JOY_Init_Cvars(void) { // joystick variables - joy_device = Cvar_Get ("joy_device", "none", CVAR_ROM, 0, - "Joystick device"); - joy_enable = Cvar_Get ("joy_enable", "1", CVAR_ARCHIVE, 0, - "Joystick enable flag"); - joy_sensitivity = Cvar_Get ("joy_sensitivity", "1", CVAR_ARCHIVE, 0, "Joystick sensitivity"); - in_joystick = Cvar_Get ("joystick", "0", CVAR_ARCHIVE, 0, "FIXME: No " - "Description"); - joy_name = Cvar_Get ("joyname", "joystick", CVAR_NONE, 0, "FIXME: No " - "Description"); - joy_advanced = Cvar_Get ("joyadvanced", "0", CVAR_NONE, 0, "FIXME: No " - "Description"); - joy_advaxisx = Cvar_Get ("joyadvaxisx", "0", CVAR_NONE, 0, "FIXME: No " - "Description"); - joy_advaxisy = Cvar_Get ("joyadvaxisy", "0", CVAR_NONE, 0, "FIXME: No " - "Description"); - joy_advaxisz = Cvar_Get ("joyadvaxisz", "0", CVAR_NONE, 0, "FIXME: No " - "Description"); - joy_advaxisr = Cvar_Get ("joyadvaxisr", "0", CVAR_NONE, 0, "FIXME: No " - "Description"); - joy_advaxisu = Cvar_Get ("joyadvaxisu", "0", CVAR_NONE, 0, "FIXME: No " - "Description"); - joy_advaxisv = Cvar_Get ("joyadvaxisv", "0", CVAR_NONE, 0, "FIXME: No " - "Description"); - joy_forwardthreshold = Cvar_Get ("joyforwardthreshold", "0.15", CVAR_NONE, - 0, "FIXME: No Description"); - joy_sidethreshold = Cvar_Get ("joysidethreshold", "0.15", CVAR_NONE, 0, - "FIXME: No Description"); - joy_pitchthreshold = Cvar_Get ("joypitchthreshold", "0.15", CVAR_NONE, 0, - "FIXME: No Description"); - joy_yawthreshold = Cvar_Get ("joyyawthreshold", "0.15", CVAR_NONE, 0, - "FIXME: No Description"); - joy_forwardsensitivity = Cvar_Get ("joyforwardsensitivity", "-1.0", - CVAR_NONE, 0, "FIXME: No Description"); - joy_sidesensitivity = Cvar_Get ("joysidesensitivity", "-1.0", CVAR_NONE, - 0, "FIXME: No Description"); - joy_pitchsensitivity = Cvar_Get ("joypitchsensitivity", "1.0", CVAR_NONE, - 0, "FIXME: No Description"); - joy_yawsensitivity = Cvar_Get ("joyyawsensitivity", "-1.0", CVAR_NONE, 0, - "FIXME: No Description"); - joy_wwhack1 = Cvar_Get ("joywwhack1", "0.0", CVAR_NONE, 0, "FIXME: No " - "Description"); - joy_wwhack2 = Cvar_Get ("joywwhack2", "0.0", CVAR_NONE, 0, "FIXME: No " - "Description"); + Cvar_Register (&joy_device_cvar, 0, 0); + Cvar_Register (&joy_enable_cvar, 0, 0); + Cvar_Register (&joy_sensitivity_cvar, 0, 0); + Cvar_Register (&in_joystick_cvar, 0, 0); + Cvar_Register (&joy_name_cvar, 0, 0); + Cvar_Register (&joy_advanced_cvar, 0, 0); + Cvar_Register (&joy_advaxisx_cvar, 0, 0); + Cvar_Register (&joy_advaxisy_cvar, 0, 0); + Cvar_Register (&joy_advaxisz_cvar, 0, 0); + Cvar_Register (&joy_advaxisr_cvar, 0, 0); + Cvar_Register (&joy_advaxisu_cvar, 0, 0); + Cvar_Register (&joy_advaxisv_cvar, 0, 0); + Cvar_Register (&joy_forwardthreshold_cvar, 0, 0); + Cvar_Register (&joy_sidethreshold_cvar, 0, 0); + Cvar_Register (&joy_pitchthreshold_cvar, 0, 0); + Cvar_Register (&joy_yawthreshold_cvar, 0, 0); + Cvar_Register (&joy_forwardsensitivity_cvar, 0, 0); + Cvar_Register (&joy_sidesensitivity_cvar, 0, 0); + Cvar_Register (&joy_pitchsensitivity_cvar, 0, 0); + Cvar_Register (&joy_yawsensitivity_cvar, 0, 0); + Cvar_Register (&joy_wwhack1_cvar, 0, 0); + Cvar_Register (&joy_wwhack2_cvar, 0, 0); - joy_debug = Cvar_Get ("joy_debug", "0.0", CVAR_NONE, 0, "FIXME: No " - "Description"); + Cvar_Register (&joy_debug_cvar, 0, 0); return; } #endif diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 12aeedf99..d13da102e 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -51,19 +51,75 @@ /* Software and hardware gamma support */ #define viddef (*r_data->vid) #define vi (viddef.vid_internal) -cvar_t *vid_gamma; -cvar_t *vid_system_gamma; -cvar_t *con_width; // FIXME: Try to move with rest of con code -cvar_t *con_height; // FIXME: Try to move with rest of con code +float vid_gamma; +static cvar_t vid_gamma_cvar = { + .name = "vid_gamma", + .description = + "Gamma correction", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &vid_gamma }, +}; +int vid_system_gamma; +static cvar_t vid_system_gamma_cvar = { + .name = "vid_system_gamma", + .description = + "Use system gamma control if available", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &vid_system_gamma }, +}; +int con_width; +static cvar_t con_width_cvar = { + .name = "con_width", + .description = + "console effective width (GL only)", + .default_value = 0, + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &con_width }, +}; +int con_height; +static cvar_t con_height_cvar = { + .name = "con_height", + .description = + "console effective height (GL only)", + .default_value = 0, + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &con_height }, +}; qboolean vid_gamma_avail; // hardware gamma availability VISIBLE unsigned int d_8to24table[256]; /* Screen size */ -cvar_t *vid_width; -cvar_t *vid_height; +int vid_width; +static cvar_t vid_width_cvar = { + .name = "vid_width", + .description = + "screen width", + .default_value = 0, + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &vid_width }, +}; +int vid_height; +static cvar_t vid_height_cvar = { + .name = "vid_height", + .description = + "screen height", + .default_value = 0, + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &vid_height }, +}; -cvar_t *vid_fullscreen; +int vid_fullscreen; +static cvar_t vid_fullscreen_cvar = { + .name = "vid_fullscreen", + .description = + "Toggles fullscreen mode", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &vid_fullscreen }, +}; static view_t conview; @@ -72,18 +128,17 @@ VID_GetWindowSize (int def_w, int def_h) { int pnum, conheight; - vid_width = Cvar_Get ("vid_width", va (0, "%d", def_w), CVAR_NONE, NULL, - "screen width"); - vid_height = Cvar_Get ("vid_height", va (0, "%d", def_h), CVAR_NONE, NULL, - "screen height"); + vid_width_cvar.default_value = nva ("%d", def_w); + vid_height_cvar.default_value = nva ("%d", def_h); + Cvar_Register (&vid_width_cvar, 0, 0); + Cvar_Register (&vid_height_cvar, 0, 0); if ((pnum = COM_CheckParm ("-width"))) { if (pnum >= com_argc - 1) Sys_Error ("VID: -width "); - Cvar_Set (vid_width, com_argv[pnum + 1]); - - if (!vid_width->int_val) + vid_width = atoi (com_argv[pnum + 1]); + if (!vid_width) Sys_Error ("VID: Bad window width"); } @@ -91,9 +146,8 @@ VID_GetWindowSize (int def_w, int def_h) if (pnum >= com_argc - 1) Sys_Error ("VID: -height "); - Cvar_Set (vid_height, com_argv[pnum + 1]); - - if (!vid_height->int_val) + vid_height = atoi (com_argv[pnum + 1]); + if (!vid_height) Sys_Error ("VID: Bad window height"); } @@ -101,47 +155,43 @@ VID_GetWindowSize (int def_w, int def_h) if (pnum >= com_argc - 2) Sys_Error ("VID: -winsize "); - Cvar_Set (vid_width, com_argv[pnum + 1]); - Cvar_Set (vid_height, com_argv[pnum + 2]); + vid_width = atoi (com_argv[pnum + 1]); + vid_height = atoi (com_argv[pnum + 2]); - if (!vid_width->int_val || !vid_height->int_val) + if (!vid_width || !vid_height) Sys_Error ("VID: Bad window width/height"); } - Cvar_SetFlags (vid_width, vid_width->flags | CVAR_ROM); - Cvar_SetFlags (vid_height, vid_height->flags | CVAR_ROM); // viddef.maxlowwidth = LOW_WIDTH; // viddef.maxlowheight = LOW_HEIGHT; - viddef.width = vid_width->int_val; - viddef.height = vid_height->int_val; + viddef.width = vid_width; + viddef.height = vid_height; viddef.conview = &conview; - con_width = Cvar_Get ("con_width", va (0, "%d", viddef.width), CVAR_NONE, - NULL, "console effective width (GL only)"); + con_width_cvar.default_value = nva ("%d", vid_width); + Cvar_Register (&con_width_cvar, 0, 0); if ((pnum = COM_CheckParm ("-conwidth"))) { if (pnum >= com_argc - 1) Sys_Error ("VID: -conwidth "); - Cvar_Set (con_width, com_argv[pnum + 1]); + con_width = atoi(com_argv[pnum + 1]); } + con_width = max (con_width & ~7, 320); // make con_width a multiple of 8 and >= 320 - Cvar_Set (con_width, va (0, "%d", max (con_width->int_val & ~7, 320))); - Cvar_SetFlags (con_width, con_width->flags | CVAR_ROM); - viddef.conview->xlen = con_width->int_val; + viddef.conview->xlen = con_width; conheight = (viddef.conview->xlen * viddef.height) / viddef.width; - con_height = Cvar_Get ("con_height", va (0, "%d", conheight), CVAR_NONE, - NULL, "console effective height (GL only)"); + con_height_cvar.default_value = nva ("%d", conheight); + Cvar_Register (&con_height_cvar, 0, 0); if ((pnum = COM_CheckParm ("-conheight"))) { if (pnum >= com_argc - 1) Sys_Error ("VID: -conheight "); - Cvar_Set (con_height, com_argv[pnum + 1]); + con_height = atoi (com_argv[pnum + 1]); } // make con_height >= 200 - Cvar_Set (con_height, va (0, "%d", max (con_height->int_val, 200))); - Cvar_SetFlags (con_height, con_height->flags | CVAR_ROM); - viddef.conview->ylen = con_height->int_val; + con_height = max (con_height & ~7, 200); + viddef.conview->ylen = con_height; Con_CheckResize (); // Now that we have a window size, fix console } @@ -168,16 +218,9 @@ VID_BuildGammaTable (double gamma) } } -/* - VID_UpdateGamma - - This is a callback to update the palette or system gamma whenever the - vid_gamma Cvar is changed. -*/ void -VID_UpdateGamma (cvar_t *vid_gamma) +VID_UpdateGamma (void) { - double gamma = bound (0.1, vid_gamma->value, 9.9); byte *p24; byte *p32; const byte *col; @@ -185,10 +228,10 @@ VID_UpdateGamma (cvar_t *vid_gamma) viddef.recalc_refdef = 1; // force a surface cache flush - if (vid_gamma_avail && vid_system_gamma->int_val) { // Have system, use it - Sys_MaskPrintf (SYS_vid, "Setting hardware gamma to %g\n", gamma); + if (vid_gamma_avail && vid_system_gamma) { // Have system, use it + Sys_MaskPrintf (SYS_vid, "Setting hardware gamma to %g\n", vid_gamma); VID_BuildGammaTable (1.0); // hardware gamma wants a linear palette - VID_SetGamma (gamma); + VID_SetGamma (vid_gamma); p24 = viddef.palette; p32 = viddef.palette32; col = viddef.basepal; @@ -200,8 +243,8 @@ VID_UpdateGamma (cvar_t *vid_gamma) } p32[-1] = 0; // color 255 is transparent } else { // We have to hack the palette - Sys_MaskPrintf (SYS_vid, "Setting software gamma to %g\n", gamma); - VID_BuildGammaTable (gamma); + Sys_MaskPrintf (SYS_vid, "Setting software gamma to %g\n", vid_gamma); + VID_BuildGammaTable (vid_gamma); p24 = viddef.palette; p32 = viddef.palette32; col = viddef.basepal; @@ -217,6 +260,13 @@ VID_UpdateGamma (cvar_t *vid_gamma) } } +static void +vid_gamma_f (void *data, const cvar_t *cvar) +{ + vid_gamma = bound (0.1, vid_gamma, 9.9); + VID_UpdateGamma (); +} + /* VID_InitGamma @@ -237,10 +287,9 @@ VID_InitGamma (const byte *pal) } gamma = bound (0.1, gamma, 9.9); - vid_gamma = Cvar_Get ("vid_gamma", va (0, "%f", gamma), CVAR_ARCHIVE, - VID_UpdateGamma, "Gamma correction"); + Cvar_Register (&vid_gamma_cvar, vid_gamma_f, 0); - VID_BuildGammaTable (vid_gamma->value); + VID_BuildGammaTable (vid_gamma); if (viddef.onPaletteChanged) { LISTENER_INVOKE (viddef.onPaletteChanged, &viddef); @@ -272,3 +321,27 @@ VID_OnPaletteChange_RemoveListener (viddef_listener_t listener, void *data) LISTENER_REMOVE (viddef.onPaletteChanged, listener, data); } } + +VISIBLE void +VID_Init (byte *palette, byte *colormap) +{ + vid_system.init (palette, colormap); +} + +static void +vid_fullscreen_f (void *data, const cvar_t *var) +{ + vid_system.update_fullscreen (vid_fullscreen); +} + +VISIBLE void +VID_Init_Cvars (void) +{ + if (vid_system.update_fullscreen) { + // A bit of a hack, but windows registers a vid_fullscreen command + // and does fullscreen handling differently. + Cvar_Register (&vid_fullscreen_cvar, vid_fullscreen_f, 0); + } + Cvar_Register (&vid_system_gamma_cvar, 0, 0); + vid_system.init_cvars (); +} diff --git a/libs/video/targets/vid_3dfxsvga.c b/libs/video/targets/vid_3dfxsvga.c index 48f7dd389..b5e449c60 100644 --- a/libs/video/targets/vid_3dfxsvga.c +++ b/libs/video/targets/vid_3dfxsvga.c @@ -121,8 +121,8 @@ QFGL_LoadLibrary (void) { void *handle; - if (!(handle = dlopen (gl_driver->string, RTLD_NOW))) { - Sys_Error ("Couldn't load OpenGL library %s: %s", gl_driver->string, + if (!(handle = dlopen (gl_driver, RTLD_NOW))) { + Sys_Error ("Couldn't load OpenGL library %s: %s", gl_driver, dlerror ()); } glGetProcAddress = dlsym (handle, "glXGetProcAddress"); @@ -331,8 +331,7 @@ VID_Init (byte *palette, byte *colormap) void VID_Init_Cvars (void) { - vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, - "Use system gamma control if available"); + Cvar_Register (&vid_system_gamma_cvar, 0, 0); } void diff --git a/libs/video/targets/vid_fbdev.c b/libs/video/targets/vid_fbdev.c index b56d94dee..f43b29a07 100644 --- a/libs/video/targets/vid_fbdev.c +++ b/libs/video/targets/vid_fbdev.c @@ -90,8 +90,24 @@ static byte vid_current_palette[768]; static int fbdev_inited = 0; static int fbdev_backgrounded = 0; -static cvar_t *vid_redrawfull; -static cvar_t *vid_waitforrefresh; +static int vid_redrawfull; +static cvar_t vid_redrawfull_cvar = { + .name = "vid_redrawfull", + .description = + "Redraw entire screen each frame instead of just dirty areas", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &vid_redrawfull }, +}; +static int vid_waitforrefresh; +static cvar_t vid_waitforrefresh_cvar = { + .name = "vid_waitforrefresh", + .description = + "Wait for vertical retrace before drawing next frame", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &vid_waitforrefresh }, +}; static byte *framebuffer_ptr; @@ -467,10 +483,8 @@ VID_Init (byte *palette, byte *colormap) void VID_Init_Cvars () { - vid_redrawfull = Cvar_Get ("vid_redrawfull", "0", CVAR_NONE, NULL, - "Redraw entire screen each frame instead of just dirty areas"); - vid_waitforrefresh = Cvar_Get ("vid_waitforrefresh", "0", CVAR_ARCHIVE, - NULL, "Wait for vertical retrace before drawing next frame"); + Cvar_Register (&vid_redrawfull_cvar, 0, 0); + Cvar_Register (&vid_waitforrefresh_cvar, 0, 0); } void @@ -492,11 +506,11 @@ VID_Update (vrect_t *rects) } } - if (vid_waitforrefresh->int_val) { + if (vid_waitforrefresh) { // ??? } - if (vid_redrawfull->int_val) { + if (vid_redrawfull) { double *d = (double *)framebuffer_ptr, *s = (double *)viddef.buffer; double *ends = (double *)(viddef.buffer + viddef.height*viddef.rowbytes); diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index 21ec6f051..b653aa684 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -88,7 +88,7 @@ VID_Init (byte *palette, byte *colormap) // Set video width, height and flags sdl_flags = (SDL_SWSURFACE | SDL_HWPALETTE); - if (vid_fullscreen->int_val) { + if (vid_fullscreen) { sdl_flags |= SDL_FULLSCREEN; #ifndef _WIN32 // Don't annoy Mesa/3dfx folks // doesn't hurt if not using a gl renderer diff --git a/libs/video/targets/vid_sdl_gl.c b/libs/video/targets/vid_sdl_gl.c index 9a0aa0a58..79d1fc47f 100644 --- a/libs/video/targets/vid_sdl_gl.c +++ b/libs/video/targets/vid_sdl_gl.c @@ -66,7 +66,15 @@ static void (GLAPIENTRY *qfglFinish) (void); static int use_gl_procaddress = 0; -static cvar_t *gl_driver; +static char *gl_driver; +static cvar_t gl_driver_cvar = { + .name = "gl_driver", + .description = + "The OpenGL library to use. (path optional)", + .default_value = GL_DRIVER, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &gl_driver }, +}; static void * QFGL_ProcAddress (const char *name, qboolean crit) @@ -151,8 +159,8 @@ sdlgl_end_rendering (void) static void sdl_load_gl (void) { - if (SDL_GL_LoadLibrary (gl_driver->string) != 0) - Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); + if (SDL_GL_LoadLibrary (gl_driver) != 0) + Sys_Error ("Couldn't load OpenGL library %s!", gl_driver); use_gl_procaddress = 1; @@ -173,6 +181,5 @@ SDL_GL_Context (void) void SDL_GL_Init_Cvars () { - gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, - "The OpenGL library to use. (path optional)"); + Cvar_Register (&gl_driver_cvar, 0, 0); } diff --git a/libs/video/targets/vid_svgalib.c b/libs/video/targets/vid_svgalib.c index 66eacea49..bfd490868 100644 --- a/libs/video/targets/vid_svgalib.c +++ b/libs/video/targets/vid_svgalib.c @@ -72,8 +72,24 @@ static byte *framebuffer_ptr; static int svgalib_inited = 0; static int svgalib_backgrounded = 0; -static cvar_t *vid_redrawfull; -static cvar_t *vid_waitforrefresh; +static int vid_redrawfull; +static cvar_t vid_redrawfull_cvar = { + .name = "vid_redrawfull", + .description = + "Redraw entire screen each frame instead of just dirty areas", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &vid_redrawfull }, +}; +static int vid_waitforrefresh; +static cvar_t vid_waitforrefresh_cvar = { + .name = "vid_waitforrefresh", + .description = + "Wait for vertical retrace before drawing next frame", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &vid_waitforrefresh }, +}; int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; byte *VGA_pagebase; @@ -393,14 +409,9 @@ VID_Init (byte *palette, byte *colormap) void VID_Init_Cvars () { - vid_redrawfull = Cvar_Get ("vid_redrawfull", "0", CVAR_NONE, NULL, - "Redraw entire screen each frame instead of " - "just dirty areas"); - vid_waitforrefresh = Cvar_Get ("vid_waitforrefresh", "0", CVAR_ARCHIVE, - NULL, "Wait for vertical retrace before " - "drawing next frame"); - vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, - "Use system gamma control if available"); + Cvar_Register (&vid_redrawfull_cvar, 0, 0); + Cvar_Register (&vid_waitforrefresh_cvar, 0, 0); + Cvar_Register (&vid_system_gamma_cvar, 0, 0); } void @@ -414,13 +425,13 @@ VID_Update (vrect_t *rects) return; } - if (vid_waitforrefresh->int_val) { + if (vid_waitforrefresh) { vga_waitretrace (); } if (VGA_planar) { VGA_UpdatePlanarScreen (vid.buffer); - } else if (vid_redrawfull->int_val) { + } else if (vid_redrawfull) { int total = vid.rowbytes * vid.height; int offset; diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index eb04efef9..124a971c3 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -117,8 +117,8 @@ VID_shutdown (void *data) Win_CloseDisplay (); } -void -VID_Init (byte *palette, byte *colormap) +static void +Win_VID_Init (byte *palette, byte *colormap) { Sys_RegisterShutdown (VID_shutdown, 0); @@ -153,8 +153,8 @@ VID_Init (byte *palette, byte *colormap) viddef.initialized = true; } -void -VID_Init_Cvars (void) +static void +Win_VID_Init_Cvars (void) { Win_Init_Cvars (); #ifdef HAVE_VULKAN @@ -164,6 +164,11 @@ VID_Init_Cvars (void) Win_SW_Init_Cvars (); } +vid_system_t vid_system = { + .init = Win_VID_Init, + .init_cvars = Win_VID_Init_Cvars, +}; + void VID_SetCaption (const char *text) { @@ -195,48 +200,48 @@ VID_Update (vrect_t *rects) if (modestate == MS_WINDOWED) { GetWindowRect (win_mainwindow, &trect); - if ((trect.left != vid_window_x->int_val) || - (trect.top != vid_window_y->int_val)) { + if ((trect.left != vid_window_x) || + (trect.top != vid_window_y)) { if (COM_CheckParm ("-resetwinpos")) { - Cvar_SetValue (vid_window_x, 0.0); - Cvar_SetValue (vid_window_y, 0.0); + vid_window_x = 0.0; + vid_window_y = 0.0; } VID_CheckWindowXY (); - SetWindowPos (win_mainwindow, NULL, vid_window_x->int_val, - vid_window_y->int_val, 0, 0, + SetWindowPos (win_mainwindow, NULL, vid_window_x, + vid_window_y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); } } - if ((_vid_default_mode_win->int_val != vid_default) && + if ((_vid_default_mode_win != vid_default) && (!startwindowed - || (_vid_default_mode_win->int_val < MODE_FULLSCREEN_DEFAULT))) { + || (_vid_default_mode_win < MODE_FULLSCREEN_DEFAULT))) { firstupdate = 0; if (COM_CheckParm ("-resetwinpos")) { - Cvar_SetValue (vid_window_x, 0.0); - Cvar_SetValue (vid_window_y, 0.0); + vid_window_x = 0.0; + vid_window_y = 0.0; } - if ((_vid_default_mode_win->int_val < 0) || - (_vid_default_mode_win->int_val >= nummodes)) { - Cvar_SetValue (_vid_default_mode_win, windowed_default); + if ((_vid_default_mode_win < 0) || + (_vid_default_mode_win >= nummodes)) { + _vid_default_mode_win = windowed_default; } - Cvar_SetValue (vid_mode, _vid_default_mode_win->int_val); + vid_mode = _vid_default_mode_win; } } // We've drawn the frame; copy it to the screen FlipScreen (rects); // check for a driver change - if ((vid_ddraw->int_val && !vid_usingddraw) - || (!vid_ddraw->int_val && vid_usingddraw)) { + if ((vid_ddraw && !vid_usingddraw) + || (!vid_ddraw && vid_usingddraw)) { // reset the mode force_mode_set = true; - VID_SetMode (vid_mode->int_val, vid_curpal); + VID_SetMode (vid_mode, vid_curpal); force_mode_set = false; // store back @@ -252,9 +257,9 @@ VID_Update (vrect_t *rects) vid_testingmode = 0; } } else { - if (vid_mode->int_val != vid_realmode) { - VID_SetMode (vid_mode->int_val, vid_curpal); - Cvar_SetValue (vid_mode, (float) vid_modenum); + if (vid_mode != vid_realmode) { + VID_SetMode (vid_mode, vid_curpal); + vid_mode = vid_modenum; // so if mode set fails, we don't keep on // trying to set that mode vid_realmode = vid_modenum; @@ -263,8 +268,8 @@ VID_Update (vrect_t *rects) // handle the mouse state when windowed if that's changed if (modestate == MS_WINDOWED) { - if (_windowed_mouse->int_val != windowed_mouse) { - if (_windowed_mouse->int_val) { + if (_windowed_mouse != windowed_mouse) { + if (_windowed_mouse) { IN_ActivateMouse (); IN_HideMouse (); } else { @@ -272,7 +277,7 @@ VID_Update (vrect_t *rects) IN_ShowMouse (); } - windowed_mouse = _windowed_mouse->int_val; + windowed_mouse = _windowed_mouse; } } } diff --git a/libs/video/targets/vid_win_gl.c b/libs/video/targets/vid_win_gl.c index 8723225c8..8e5b9d07a 100644 --- a/libs/video/targets/vid_win_gl.c +++ b/libs/video/targets/vid_win_gl.c @@ -54,7 +54,15 @@ static void (GLAPIENTRY *qfglFinish) (void); static void *(WINAPI * glGetProcAddress) (const char *symbol) = NULL; static int use_gl_proceaddress = 0; -static cvar_t *gl_driver; +static char *gl_driver; +static cvar_t gl_driver_cvar = { + .name = "gl_driver", + .description = + "The OpenGL library to use. (path optional)", + .default_value = GL_DRIVER, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &gl_driver }, +}; static HGLRC baseRC;//FIXME should be in gl_ctx_t, but that's GLXContext... static void * QFGL_GetProcAddress (void *handle, const char *name) @@ -155,8 +163,8 @@ wgl_end_rendering (void) SwapBuffers (win_maindc); } // handle the mouse state when windowed if that's changed - if (!vid_fullscreen->int_val) { -//FIXME if (!in_grab->int_val) { + if (!vid_fullscreen) { +//FIXME if (!in_grab) { //FIXME if (windowed_mouse) { //FIXME IN_DeactivateMouse (); //FIXME IN_ShowMouse (); @@ -171,9 +179,9 @@ wgl_end_rendering (void) static void wgl_load_gl (void) { - libgl_handle = LoadLibrary (gl_driver->string); + libgl_handle = LoadLibrary (gl_driver); if (!libgl_handle) { - Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); + Sys_Error ("Couldn't load OpenGL library %s!", gl_driver); } glGetProcAddress = (void *) GetProcAddress (libgl_handle, "wglGetProcAddress"); @@ -204,6 +212,5 @@ Win_GL_Context (void) void Win_GL_Init_Cvars (void) { - gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, - "The OpenGL library to use. (path optional)"); + Cvar_Register (&gl_driver_cvar, 0, 0); } diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index 2e8667c85..052cad570 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -300,7 +300,7 @@ Win_UnloadAllDrivers (void) static void Win_CreateDriver (void) { - if (vid_ddraw->int_val) { + if (vid_ddraw) { VID_CreateDDrawDriver (viddef.width, viddef.height); } if (!using_ddraw) { diff --git a/libs/video/targets/vid_win_vulkan.c b/libs/video/targets/vid_win_vulkan.c index 240fa2355..f9adb967d 100644 --- a/libs/video/targets/vid_win_vulkan.c +++ b/libs/video/targets/vid_win_vulkan.c @@ -44,7 +44,15 @@ #include "vid_internal.h" #include "vid_vulkan.h" -static cvar_t *vulkan_library_name; +static char *vulkan_library_name; +static cvar_t vulkan_library_name_cvar = { + .name = "vulkan_library", + .description = + "the name of the vulkan shared library", + .default_value = "vulkan-1.dll", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &vulkan_library_name }, +}; typedef struct vulkan_presentation_s { #define PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; @@ -65,11 +73,11 @@ static HMODULE vulkan_library; static void load_vulkan_library (vulkan_ctx_t *ctx) { - vulkan_library = LoadLibrary (vulkan_library_name->string); + vulkan_library = LoadLibrary (vulkan_library_name); if (!vulkan_library) { DWORD errcode = GetLastError (); Sys_Error ("Couldn't load vulkan library %s: %ld", - vulkan_library_name->string, errcode); + vulkan_library_name, errcode); } #define EXPORTED_VULKAN_FUNCTION(name) \ @@ -185,7 +193,5 @@ Win_Vulkan_Context (void) void Win_Vulkan_Init_Cvars (void) { - vulkan_library_name = Cvar_Get ("vulkan_library", "vulkan-1.dll", - CVAR_ROM, 0, - "the name of the vulkan shared library"); + Cvar_Register (&vulkan_library_name_cvar, 0, 0); } diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index d60d1b9f1..e1b674e20 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -94,8 +94,8 @@ VID_shutdown (void *data) palette. Palette data will go away after the call, so copy it if you'll need it later. */ -void -VID_Init (byte *palette, byte *colormap) +static void +X11_VID_Init (byte *palette, byte *colormap) { Sys_RegisterShutdown (VID_shutdown, 0); @@ -134,8 +134,8 @@ VID_Init (byte *palette, byte *colormap) viddef.recalc_refdef = 1; // force a surface cache flush } -void -VID_Init_Cvars () +static void +X11_VID_Init_Cvars (void) { X11_Init_Cvars (); #ifdef HAVE_VULKAN @@ -145,6 +145,12 @@ VID_Init_Cvars () X11_SW_Init_Cvars (); } +vid_system_t vid_system = { + .init = X11_VID_Init, + .init_cvars = X11_VID_Init_Cvars, + .update_fullscreen = X11_UpdateFullscreen, +}; + #if 0 static int config_notify = 0; static int config_notify_width; diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index 30bf0aa19..8679479a0 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -116,7 +116,15 @@ static void *(*glGetProcAddress) (const char *symbol) = NULL; static int use_gl_procaddress = 0; static GLXFBConfig glx_cfg; -static cvar_t *gl_driver; +static char *gl_driver; +static cvar_t gl_driver_cvar = { + .name = "gl_driver", + .description = + "The OpenGL library to use. (path optional)", + .default_value = GL_DRIVER, + .flags = CVAR_ROM, + .value = { .type = 0, .value = &gl_driver }, +}; static void * QFGL_GetProcAddress (void *handle, const char *name) @@ -219,9 +227,9 @@ glx_end_rendering (void) static void glx_load_gl (void) { - libgl_handle = dlopen (gl_driver->string, RTLD_NOW); + libgl_handle = dlopen (gl_driver, RTLD_NOW); if (!libgl_handle) { - Sys_Error ("Couldn't load OpenGL library %s: %s", gl_driver->string, + Sys_Error ("Couldn't load OpenGL library %s: %s", gl_driver, dlerror ()); } glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddress"); @@ -255,6 +263,5 @@ X11_GL_Context (void) void X11_GL_Init_Cvars (void) { - gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, - "The OpenGL library to use. (path optional)"); + Cvar_Register (&gl_driver_cvar, 0, 0); } diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index 39bf90310..43af1897e 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -61,7 +61,15 @@ #include "vid_internal.h" #include "vid_vulkan.h" -static cvar_t *vulkan_library_name; +static char *vulkan_library_name; +static cvar_t vulkan_library_name_cvar = { + .name = "vulkan_library", + .description = + "the name of the vulkan shared library", + .default_value = "libvulkan.so.1", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &vulkan_library_name }, +}; typedef struct vulkan_presentation_s { #define PRESENTATION_VULKAN_FUNCTION_FROM_EXTENSION(name,ext) PFN_##name name; @@ -84,11 +92,11 @@ static void *vulkan_library; static void load_vulkan_library (vulkan_ctx_t *ctx) { - vulkan_library = dlopen (vulkan_library_name->string, + vulkan_library = dlopen (vulkan_library_name, RTLD_DEEPBIND | RTLD_NOW); if (!vulkan_library) { Sys_Error ("Couldn't load vulkan library %s: %s", - vulkan_library_name->name, dlerror ()); + vulkan_library_name, dlerror ()); } #define EXPORTED_VULKAN_FUNCTION(name) \ @@ -224,7 +232,5 @@ X11_Vulkan_Context (void) void X11_Vulkan_Init_Cvars (void) { - vulkan_library_name = Cvar_Get ("vulkan_library", "libvulkan.so.1", - CVAR_ROM, 0, - "the name of the vulkan shared library"); + Cvar_Register (&vulkan_library_name_cvar, 0, 0); } diff --git a/nq/include/client.h b/nq/include/client.h index de0e7cb02..d059db54f 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -210,21 +210,21 @@ typedef struct client_state_s { } client_state_t; // cvars -extern struct cvar_s *cl_name; -extern struct cvar_s *cl_color; +extern char *cl_name; +extern int cl_color; -extern struct cvar_s *cl_shownet; -extern struct cvar_s *cl_nolerp; +extern int cl_shownet; +extern int cl_nolerp; -extern struct cvar_s *cl_name; -extern struct cvar_s *cl_writecfg; +extern char *cl_name; +extern int cl_writecfg; -extern struct cvar_s *cl_cshift_bonus; -extern struct cvar_s *cl_cshift_contents; -extern struct cvar_s *cl_cshift_damage; -extern struct cvar_s *cl_cshift_powerup; +extern int cl_cshift_bonus; +extern int cl_cshift_contents; +extern int cl_cshift_damage; +extern int cl_cshift_powerup; -extern struct cvar_s *noskins; +extern int noskins; extern client_state_t cl; @@ -273,8 +273,8 @@ void CL_Record (const char *argv1, int track); int CL_GetMessage (void); void CL_Demo_Init (void); -extern struct cvar_s *demo_gzip; -extern struct cvar_s *demo_speed; +extern int demo_gzip; +extern float demo_speed; // cl_parse.c struct skin_s; @@ -292,7 +292,8 @@ extern double realtime; extern qboolean recording; -void Cvar_Info (struct cvar_s *var); +struct cvar_s; +void Cvar_Info (void *data, const struct cvar_s *cvar); void CL_UpdateScreen (double realtime); diff --git a/nq/include/game.h b/nq/include/game.h index 6cf6a978f..485c82426 100644 --- a/nq/include/game.h +++ b/nq/include/game.h @@ -156,7 +156,7 @@ extern int current_skill; // skill level for currently loaded level (in case extern qboolean isDedicated; extern qboolean standard_quake; -extern struct cvar_s *registered; +extern char *registered; struct memhunk_s; void Game_Init (struct memhunk_s *hunk); diff --git a/nq/include/host.h b/nq/include/host.h index 70c7327f9..460188eb4 100644 --- a/nq/include/host.h +++ b/nq/include/host.h @@ -38,11 +38,11 @@ typedef struct extern quakeparms_t host_parms; -extern struct cvar_s *sys_ticrate; -extern struct cvar_s *sys_nostdout; -extern struct cvar_s *developer; +extern float sys_ticrate; +extern int sys_nostdout; +extern int developer; -extern struct cvar_s *pausable; +extern int pausable; extern int viewentity; diff --git a/nq/include/server.h b/nq/include/server.h index 8c43ed2e4..3518f3257 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -202,31 +202,31 @@ typedef struct client_s //============================================================================ -extern struct cvar_s *teamplay; -extern struct cvar_s *skill; -extern struct cvar_s *deathmatch; -extern struct cvar_s *coop; -extern struct cvar_s *fraglimit; -extern struct cvar_s *timelimit; +extern int teamplay; +extern int skill; +extern int deathmatch; +extern int coop; +extern char *fraglimit; +extern int timelimit; -extern struct cvar_s *sv_rollangle; -extern struct cvar_s *sv_rollspeed; +extern float sv_rollangle; +extern float sv_rollspeed; -extern struct cvar_s *sv_maxvelocity; -extern struct cvar_s *sv_gravity; -extern struct cvar_s *sv_jump_any; -extern struct cvar_s *sv_nostep; -extern struct cvar_s *sv_friction; -extern struct cvar_s *sv_edgefriction; -extern struct cvar_s *sv_stopspeed; -extern struct cvar_s *sv_maxspeed; -extern struct cvar_s *sv_accelerate; -extern struct cvar_s *sv_idealpitchscale; -extern struct cvar_s *sv_aim; -extern struct cvar_s *sv_friction; -extern struct cvar_s *sv_stopspeed; +extern float sv_maxvelocity; +extern float sv_gravity; +extern int sv_jump_any; +extern int sv_nostep; +extern float sv_friction; +extern float sv_edgefriction; +extern float sv_stopspeed; +extern float sv_maxspeed; +extern float sv_accelerate; +extern float sv_idealpitchscale; +extern float sv_aim; +extern float sv_friction; +extern float sv_stopspeed; -extern struct cvar_s *max_edicts; +extern int max_edicts; extern server_static_t svs; // persistant server info extern server_t sv; // local server @@ -277,6 +277,7 @@ void SV_FinishGravity (edict_t *ent, vec3_t move); void SV_Physics_Toss (edict_t *ent); void SV_Physics_Client (edict_t *ent, int num); void SV_Physics (void); +void SV_Physics_Init_Cvars (void); void SV_ProgStartFrame (void); void SV_RunNewmis (void); @@ -289,6 +290,7 @@ void SV_MoveToGoal (progs_t *pr, void *data); void SV_CheckForNewClients (void); void SV_RunClients (void); +void SV_User_Init_Cvars (void); void SV_SaveSpawnparms (void); void SV_SpawnServer (const char *server); @@ -296,7 +298,8 @@ void SV_LoadProgs (void); void SV_Progs_Init (void); void SV_Progs_Init_Cvars (void); -void Cvar_Info (struct cvar_s *var); +struct cvar_s; +void Cvar_Info (void *data, const struct cvar_s *cvar); //FIXME location #define STOP_EPSILON 0.1 diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index b4d47eebe..510ea767c 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -74,10 +74,44 @@ static void CL_TimeFrames_DumpLog (void); static void CL_TimeFrames_AddTimestamp (void); static void CL_TimeFrames_Reset (void); -cvar_t *demo_gzip; -cvar_t *demo_speed; -cvar_t *demo_quit; -cvar_t *demo_timeframes; +int demo_gzip; +static cvar_t demo_gzip_cvar = { + .name = "demo_gzip", + .description = + "Compress demos using gzip. 0 = none, 1 = least compression, 9 = most " + "compression. Compressed demos (1-9) will have .gz appended to the " + "name", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &demo_gzip }, +}; +float demo_speed; +static cvar_t demo_speed_cvar = { + .name = "demo_speed", + .description = + "adjust demo playback speed. 1.0 = normal, < 1 slow-mo, > 1 timelapse", + .default_value = "1.0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &demo_speed }, +}; +int demo_quit; +static cvar_t demo_quit_cvar = { + .name = "demo_quit", + .description = + "automaticly quit after a timedemo has finished", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &demo_quit }, +}; +int demo_timeframes; +static cvar_t demo_timeframes_cvar = { + .name = "demo_timeframes", + .description = + "write timestamps for every frame", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &demo_timeframes }, +}; #define MAX_DEMMSG (MAX_MSGLEN) @@ -370,9 +404,9 @@ CL_Record (const char *argv1, int track) // open the demo file #ifdef HAVE_ZLIB - if (demo_gzip->int_val) { + if (demo_gzip) { QFS_DefaultExtension (name, ".dem.gz"); - cls.demofile = QFS_WOpen (name->str, demo_gzip->int_val); + cls.demofile = QFS_WOpen (name->str, demo_gzip); } else #endif { @@ -544,7 +578,7 @@ CL_StartTimeDemo (void) cls.td_lastframe = -1; // get a new message this frame CL_TimeFrames_Reset (); - if (demo_timeframes->int_val) + if (demo_timeframes) demo_timeframes_isactive = 1; } @@ -603,7 +637,7 @@ CL_FinishTimeDemo (void) Sys_Printf (" min/max fps: %.3f/%.3f\n", min, max); Sys_Printf ("std deviation: %.3f fps\n", sqrt (variance)); } - if (demo_quit->int_val) + if (demo_quit) Cbuf_InsertText (host_cbuf, "quit\n"); } } @@ -648,17 +682,10 @@ CL_Demo_Init (void) demo_timeframes_index = 0; demo_timeframes_array = NULL; - demo_gzip = Cvar_Get ("demo_gzip", "0", CVAR_ARCHIVE, NULL, - "Compress demos using gzip. 0 = none, 1 = least " - "compression, 9 = most compression. Compressed " - " demos (1-9) will have .gz appended to the name"); - demo_speed = Cvar_Get ("demo_speed", "1.0", CVAR_NONE, NULL, - "adjust demo playback speed. 1.0 = normal, " - "< 1 slow-mo, > 1 timelapse"); - demo_quit = Cvar_Get ("demo_quit", "0", CVAR_NONE, NULL, - "automaticly quit after a timedemo has finished"); - demo_timeframes = Cvar_Get ("demo_timeframes", "0", CVAR_NONE, NULL, - "write timestamps for every frame"); + Cvar_Register (&demo_gzip_cvar, 0, 0); + Cvar_Register (&demo_speed_cvar, 0, 0); + Cvar_Register (&demo_quit_cvar, 0, 0); + Cvar_Register (&demo_timeframes_cvar, 0, 0); Cmd_AddCommand ("record", CL_Record_f, "Record a demo, if no filename " "argument is given\n" "the demo will be called Year-Month-Day-Hour-Minute-" diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 92ea20f5b..9d0a4d357 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -108,7 +108,7 @@ CL_LerpPoint (void) f = cl.mtime[0] - cl.mtime[1]; - if (!f || cl_nolerp->int_val || cls.timedemo || sv.active) { + if (!f || cl_nolerp || cls.timedemo || sv.active) { cl.time = cl.mtime[0]; return 1; } @@ -259,7 +259,7 @@ CL_RelinkEntities (void) animation->pose1 = animation->pose2 = -1; CL_TransformEntity (ent, new->scale / 16.0, new->angles, new->origin); - if (i != cl.viewentity || chase_active->int_val) { + if (i != cl.viewentity || chase_active) { if (ent->visibility.efrag) { R_RemoveEfrags (ent); } @@ -293,7 +293,7 @@ CL_RelinkEntities (void) } CL_TransformEntity (ent, new->scale / 16.0, angles, origin); } - if (i != cl.viewentity || chase_active->int_val) { + if (i != cl.viewentity || chase_active) { if (ent->visibility.efrag) { vec4f_t org = Transform_GetWorldPosition (ent->transform); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 1a489621a..25163ade7 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -70,19 +70,91 @@ static plugin_list_t client_plugin_list[] = { }; // these two are not intended to be set directly -cvar_t *cl_name; -cvar_t *cl_color; +char *cl_name; +static cvar_t cl_name_cvar = { + .name = "_cl_name", + .description = + "Player name", + .default_value = "player", + .flags = CVAR_ARCHIVE, + .value = { .type = 0, .value = &cl_name }, +}; +int cl_color; +static cvar_t cl_color_cvar = { + .name = "_cl_color", + .description = + "Player color", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_color }, +}; -cvar_t *cl_writecfg; +int cl_writecfg; +static cvar_t cl_writecfg_cvar = { + .name = "cl_writecfg", + .description = + "write config files?", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_writecfg }, +}; -cvar_t *cl_shownet; -cvar_t *cl_nolerp; +int cl_shownet; +static cvar_t cl_shownet_cvar = { + .name = "cl_shownet", + .description = + "show network packets. 0=off, 1=basic, 2=verbose", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_shownet }, +}; +int cl_nolerp; +static cvar_t cl_nolerp_cvar = { + .name = "cl_nolerp", + .description = + "linear motion interpolation", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_nolerp }, +}; -cvar_t *hud_fps; -cvar_t *hud_time; +int hud_fps; +static cvar_t hud_fps_cvar = { + .name = "hud_fps", + .description = + "display realtime frames per second", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_fps }, +}; +int hud_time; +static cvar_t hud_time_cvar = { + .name = "hud_time", + .description = + "display the current time", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_time }, +}; -static cvar_t *r_ambient; -static cvar_t *r_drawflat; +static char *r_ambient; +static cvar_t r_ambient_cvar = { + .name = "r_ambient", + .description = + "Determines the ambient lighting for a level", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &r_ambient }, +}; +static char *r_drawflat; +static cvar_t r_drawflat_cvar = { + .name = "r_drawflat", + .description = + "Toggles the drawing of textures", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &r_drawflat }, +}; int fps_count; @@ -99,7 +171,7 @@ CL_WriteConfiguration (void) { // dedicated servers initialize the host but don't parse and set the // config.cfg cvars - if (host_initialized && !isDedicated && cl_writecfg->int_val) { + if (host_initialized && !isDedicated && cl_writecfg) { plitem_t *config = PL_NewDictionary (0); //FIXME hashlinks Cvar_SaveConfig (config); IN_SaveConfig (config); @@ -170,27 +242,19 @@ CL_InitCvars (void) Chase_Init_Cvars (); V_Init_Cvars (); - cl_name = Cvar_Get ("_cl_name", "player", CVAR_ARCHIVE, NULL, - "Player name"); - cl_color = Cvar_Get ("_cl_color", "0", CVAR_ARCHIVE, NULL, "Player color"); - cl_writecfg = Cvar_Get ("cl_writecfg", "1", CVAR_NONE, NULL, - "write config files?"); - cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_NONE, NULL, - "show network packets. 0=off, 1=basic, 2=verbose"); - cl_nolerp = Cvar_Get ("cl_nolerp", "0", CVAR_NONE, NULL, - "linear motion interpolation"); - hud_fps = Cvar_Get ("hud_fps", "0", CVAR_ARCHIVE, NULL, - "display realtime frames per second"); - Cvar_MakeAlias ("show_fps", hud_fps); - hud_time = Cvar_Get ("hud_time", "0", CVAR_ARCHIVE, NULL, - "display the current time"); + Cvar_Register (&cl_name_cvar, 0, 0); + Cvar_Register (&cl_color_cvar, 0, 0); + Cvar_Register (&cl_writecfg_cvar, 0, 0); + Cvar_Register (&cl_shownet_cvar, 0, 0); + Cvar_Register (&cl_nolerp_cvar, 0, 0); + Cvar_Register (&hud_fps_cvar, 0, 0); + Cvar_MakeAlias ("show_fps", &hud_fps_cvar); + Cvar_Register (&hud_time_cvar, 0, 0); //FIXME not hooked up (don't do anything), but should not work in //multi-player - r_ambient = Cvar_Get ("r_ambient", "0", CVAR_NONE, NULL, - "Determines the ambient lighting for a level"); - r_drawflat = Cvar_Get ("r_drawflat", "0", CVAR_NONE, NULL, - "Toggles the drawing of textures"); + Cvar_Register (&r_ambient_cvar, 0, 0); + Cvar_Register (&r_drawflat_cvar, 0, 0); } void @@ -345,11 +409,11 @@ CL_SignonReply (void) case so_spawn: MSG_WriteByte (&cls.message, clc_stringcmd); MSG_WriteString (&cls.message, va (0, "name \"%s\"\n", - cl_name->string)); + cl_name)); MSG_WriteByte (&cls.message, clc_stringcmd); MSG_WriteString (&cls.message, - va (0, "color %i %i\n", (cl_color->int_val) >> 4, - (cl_color->int_val) & 15)); + va (0, "color %i %i\n", (cl_color) >> 4, + (cl_color) & 15)); MSG_WriteByte (&cls.message, clc_stringcmd); MSG_WriteString (&cls.message, "spawn"); break; @@ -450,7 +514,7 @@ CL_ReadFromServer (void) CL_ParseServerMessage (); } while (ret && cls.state >= ca_connected); - if (cl_shownet->int_val) + if (cl_shownet) Sys_Printf ("\n"); CL_RelinkEntities (); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 2bf14fe2c..b9c1f0ac6 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -707,7 +707,7 @@ CL_SetStat (int stat, int value) } #define SHOWNET(x) \ - if (cl_shownet->int_val == 2) \ + if (cl_shownet == 2) \ Sys_Printf ("%3i:%s\n", net_message->readcount - 1, x); void @@ -725,9 +725,9 @@ CL_ParseServerMessage (void) }; // if recording demos, copy the message out - if (cl_shownet->int_val == 1) + if (cl_shownet == 1) Sys_Printf ("%i ", net_message->message->cursize); - else if (cl_shownet->int_val == 2) + else if (cl_shownet == 2) Sys_Printf ("------------------\n"); cl.viewstate.onground = -1; // unless the server says otherwise diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 3fd0a3bf5..4bbb1f9dd 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -95,8 +95,8 @@ scr_draw_views (void) net_view->visible = (!cls.demoplayback && realtime - cl.last_servermessage >= 0.3); loading_view->visible = cl.loading; - timegraph_view->visible = r_timegraph->int_val; - zgraph_view->visible = r_zgraph->int_val; + timegraph_view->visible = r_timegraph; + zgraph_view->visible = r_zgraph; view_draw (r_data->vid->conview); } diff --git a/nq/source/game.c b/nq/source/game.c index 6fc7c225b..bbac0de20 100644 --- a/nq/source/game.c +++ b/nq/source/game.c @@ -40,8 +40,24 @@ qboolean standard_quake = false; -cvar_t *registered; -cvar_t *cmdline; +char *registered; +static cvar_t registered_cvar = { + .name = "registered", + .description = + "Is the game the registered version. 1 yes 0 no", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = ®istered }, +}; +char *cmdline; +static cvar_t cmdline_cvar = { + .name = "cmdline", + .description = + "None", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = 0/* not used */, .value = &cmdline }, +}; int static_registered = 1; /* @@ -66,7 +82,7 @@ Game_CheckRegistered (void) } if (static_registered) { - Cvar_Set (registered, "1"); + Cvar_Set ("registered", "1"); Sys_Printf ("Playing registered version.\n"); } } @@ -91,9 +107,8 @@ Game_Init (memhunk_t *hunk) } QFS_Init (hunk, game); - registered = Cvar_Get ("registered", "0", CVAR_NONE, NULL, - "Is the game the registered version. 1 yes 0 no"); - cmdline = Cvar_Get ("cmdline", "0", CVAR_SERVERINFO, Cvar_Info, "None"); + Cvar_Register (®istered_cvar, 0, 0); + Cvar_Register (&cmdline_cvar, Cvar_Info, &cmdline); Game_CheckRegistered (); } diff --git a/nq/source/host.c b/nq/source/host.c index 86b428c5a..dc45ef372 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -105,40 +105,178 @@ client_t *host_client; // current client jmp_buf host_abortserver; -cvar_t *host_mem_size; +float host_mem_size; +static cvar_t host_mem_size_cvar = { + .name = "host_mem_size", + .description = + "Amount of memory (in MB) to allocate for the " + PACKAGE_NAME + " heap", + .default_value = "40", + .flags = CVAR_ROM, + .value = { .type = &cexpr_float, .value = &host_mem_size }, +}; -cvar_t *host_framerate; -cvar_t *host_speeds; -cvar_t *max_edicts; +float host_framerate; +static cvar_t host_framerate_cvar = { + .name = "host_framerate", + .description = + "set for slow motion", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &host_framerate }, +}; +int host_speeds; +static cvar_t host_speeds_cvar = { + .name = "host_speeds", + .description = + "set for running times", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &host_speeds }, +}; +int max_edicts; +static cvar_t max_edicts_cvar = { + .name = "max_edicts", + .description = + "maximum server edicts", + .default_value = "1024", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &max_edicts }, +}; -cvar_t *sys_ticrate; -cvar_t *serverprofile; +float sys_ticrate; +static cvar_t sys_ticrate_cvar = { + .name = "sys_ticrate", + .description = + "None", + .default_value = "0.05", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sys_ticrate }, +}; +int serverprofile; +static cvar_t serverprofile_cvar = { + .name = "serverprofile", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &serverprofile }, +}; -cvar_t *cl_quakerc; +int cl_quakerc; +static cvar_t cl_quakerc_cvar = { + .name = "cl_quakerc", + .description = + "exec quake.rc on startup", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_quakerc }, +}; -cvar_t *fraglimit; -cvar_t *timelimit; -cvar_t *teamplay; -cvar_t *noexit; -cvar_t *samelevel; +char *fraglimit; +static cvar_t fraglimit_cvar = { + .name = "fraglimit", + .description = + "None", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = 0/* not used */, .value = &fraglimit }, +}; +int timelimit; +static cvar_t timelimit_cvar = { + .name = "timelimit", + .description = + "None", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &timelimit }, +}; +int teamplay; +static cvar_t teamplay_cvar = { + .name = "teamplay", + .description = + "None", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &teamplay }, +}; +char *noexit; +static cvar_t noexit_cvar = { + .name = "noexit", + .description = + "None", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = 0/* not used */, .value = &noexit }, +}; +char *samelevel; +static cvar_t samelevel_cvar = { + .name = "samelevel", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &samelevel }, +}; -cvar_t *skill; -cvar_t *coop; -cvar_t *deathmatch; +int skill; +static cvar_t skill_cvar = { + .name = "skill", + .description = + "0 - 3", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &skill }, +}; +int coop; +static cvar_t coop_cvar = { + .name = "coop", + .description = + "0 or 1", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &coop }, +}; +int deathmatch; +static cvar_t deathmatch_cvar = { + .name = "deathmatch", + .description = + "0, 1, or 2", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &deathmatch }, +}; -cvar_t *pausable; - -cvar_t *temp1; -cvar_t *cl_usleep; - -static int cl_usleep_cache; - -static void -cl_usleep_f (cvar_t *var) -{ - cl_usleep_cache = var->int_val; -} +int pausable; +static cvar_t pausable_cvar = { + .name = "pausable", + .description = + "None", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &pausable }, +}; +char *temp1; +static cvar_t temp1_cvar = { + .name = "temp1", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &temp1 }, +}; +int cl_usleep; +static cvar_t cl_usleep_cvar = { + .name = "cl_usleep", + .description = + "Turn this on to save cpu when fps limited. May affect frame rate " + "adversely depending on local machine/os conditions", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_usleep }, +}; void Host_EndGame (const char *message, ...) @@ -248,9 +386,9 @@ Host_FindMaxClients (void) Hunk_AllocName (0, svs.maxclientslimit * sizeof (client_t), "clients"); if (svs.maxclients > 1) - Cvar_SetValue (deathmatch, 1.0); + deathmatch = 1.0; else - Cvar_SetValue (deathmatch, 0.0); + deathmatch = 0.0; } static void @@ -258,37 +396,26 @@ Host_InitLocal (void) { Host_InitCommands (); - host_framerate = - Cvar_Get ("host_framerate", "0", CVAR_NONE, NULL, - "set for slow motion"); - host_speeds = - Cvar_Get ("host_speeds", "0", CVAR_NONE, NULL, - "set for running times"); - max_edicts = Cvar_Get ("max_edicts", "1024", CVAR_NONE, NULL, - "maximum server edicts"); + Cvar_Register (&host_framerate_cvar, 0, 0); + Cvar_Register (&host_speeds_cvar, 0, 0); + Cvar_Register (&max_edicts_cvar, 0, 0); - sys_ticrate = Cvar_Get ("sys_ticrate", "0.05", CVAR_NONE, NULL, "None"); - serverprofile = Cvar_Get ("serverprofile", "0", CVAR_NONE, NULL, "None"); + Cvar_Register (&sys_ticrate_cvar, 0, 0); + Cvar_Register (&serverprofile_cvar, 0, 0); - cl_quakerc = Cvar_Get ("cl_quakerc", "1", CVAR_NONE, NULL, - "exec quake.rc on startup"); + Cvar_Register (&cl_quakerc_cvar, 0, 0); - fraglimit = Cvar_Get ("fraglimit", "0", CVAR_SERVERINFO, Cvar_Info, - "None"); - timelimit = Cvar_Get ("timelimit", "0", CVAR_SERVERINFO, Cvar_Info, - "None"); - teamplay = Cvar_Get ("teamplay", "0", CVAR_SERVERINFO, Cvar_Info, "None"); - samelevel = Cvar_Get ("samelevel", "0", CVAR_NONE, NULL, "None"); - noexit = Cvar_Get ("noexit", "0", CVAR_SERVERINFO, Cvar_Info, "None"); - skill = Cvar_Get ("skill", "1", CVAR_NONE, NULL, "0 - 3"); - deathmatch = Cvar_Get ("deathmatch", "0", CVAR_NONE, NULL, "0, 1, or 2"); - coop = Cvar_Get ("coop", "0", CVAR_NONE, NULL, "0 or 1"); - pausable = Cvar_Get ("pausable", "1", CVAR_NONE, NULL, "None"); - temp1 = Cvar_Get ("temp1", "0", CVAR_NONE, NULL, "None"); - cl_usleep = Cvar_Get ("cl_usleep", "1", CVAR_ARCHIVE, cl_usleep_f, - "Turn this on to save cpu when fps limited. " - "May affect frame rate adversely depending on " - "local machine/os conditions"); + Cvar_Register (&fraglimit_cvar, Cvar_Info, &fraglimit); + Cvar_Register (&timelimit_cvar, Cvar_Info, &timelimit); + Cvar_Register (&teamplay_cvar, Cvar_Info, &teamplay); + Cvar_Register (&samelevel_cvar, 0, 0); + Cvar_Register (&noexit_cvar, Cvar_Info, &noexit); + Cvar_Register (&skill_cvar, 0, 0); + Cvar_Register (&deathmatch_cvar, 0, 0); + Cvar_Register (&coop_cvar, 0, 0); + Cvar_Register (&pausable_cvar, 0, 0); + Cvar_Register (&temp1_cvar, 0, 0); + Cvar_Register (&cl_usleep_cvar, 0, 0); Host_FindMaxClients (); @@ -525,7 +652,7 @@ Host_FilterTime (float time) con_realtime += time; if (cls.demoplayback) { - timescale = max (0, demo_speed->value); + timescale = max (0, demo_speed); time *= timescale; } @@ -543,8 +670,8 @@ Host_FilterTime (float time) con_frametime = con_realtime - oldcon_realtime; oldcon_realtime = con_realtime; - if (host_framerate->value > 0) - host_frametime = host_framerate->value; + if (host_framerate > 0) + host_frametime = host_framerate; else // don't allow really long or short frames host_frametime = bound (0.000, host_frametime, 0.1); @@ -593,17 +720,17 @@ Host_ClientFrame (void) CL_ReadFromServer (); // update video - if (host_speeds->int_val) + if (host_speeds) time1 = Sys_DoubleTime (); - r_data->inhibit_viewmodel = (chase_active->int_val + r_data->inhibit_viewmodel = (chase_active || (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) || cl.stats[STAT_HEALTH] <= 0); r_data->frametime = host_frametime; CL_UpdateScreen (cl.time); - if (host_speeds->int_val) + if (host_speeds) time2 = Sys_DoubleTime (); // update audio @@ -623,7 +750,7 @@ Host_ClientFrame (void) CDAudio_Update (); - if (host_speeds->int_val) { + if (host_speeds) { pass1 = (time1 - time3) * 1000; time3 = Sys_DoubleTime (); pass2 = (time2 - time1) * 1000; @@ -670,7 +797,7 @@ _Host_Frame (float time) if ((sleeptime = Host_FilterTime (time)) != 0) { // don't run too fast, or packet will flood outs #ifdef HAVE_USLEEP - if (cl_usleep_cache && sleeptime > 0.002) // minimum sleep time + if (cl_usleep && sleeptime > 0.002) // minimum sleep time usleep ((unsigned long) (sleeptime * 1000000 / 2)); #endif return; @@ -729,7 +856,7 @@ Host_Frame (float time) int c, m; static int timecount; - if (!serverprofile->int_val) { + if (!serverprofile) { _Host_Frame (time); return; } @@ -835,18 +962,15 @@ Host_Init_Memory (void) else minimum_memory = MINIMUM_MEMORY_LEVELPAK; - host_mem_size = Cvar_Get ("host_mem_size", "40", CVAR_NONE, NULL, - "Amount of memory (in MB) to allocate for the " - PACKAGE_NAME " heap"); + Cvar_Register (&host_mem_size_cvar, 0, 0); if (mem_parm) - Cvar_Set (host_mem_size, com_argv[mem_parm + 1]); + Cvar_Set ("host_mem_size", com_argv[mem_parm + 1]); if (COM_CheckParm ("-minmemory")) - Cvar_SetValue (host_mem_size, minimum_memory / (1024 * 1024.0)); + host_mem_size = minimum_memory / (1024 * 1024.0); - Cvar_SetFlags (host_mem_size, host_mem_size->flags | CVAR_ROM); - mem_size = ((size_t) host_mem_size->value * 1024 * 1024); + mem_size = ((size_t) host_mem_size * 1024 * 1024); if (mem_size < minimum_memory) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", @@ -860,7 +984,7 @@ Host_Init_Memory (void) Sys_PageIn (mem_base, mem_size); memhunk_t *hunk = Memory_Init (mem_base, mem_size); - Sys_Printf ("%4.1f megabyte heap\n", host_mem_size->value); + Sys_Printf ("%4.1f megabyte heap\n", host_mem_size); return hunk; } @@ -873,14 +997,14 @@ Host_ExecConfig (cbuf_t *cbuf, int skip_quakerc) // should be used to set up defaults on the assumption that the user has // things set up to work with another (hopefully compatible) client if (CL_ReadConfiguration ("quakeforge.cfg")) { - Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cmd_Exec_File (cbuf, fs_usercfg, 0); Cmd_StuffCmds (cbuf); COM_Check_quakerc ("startdemos", cbuf); } else { if (!skip_quakerc) { Cbuf_InsertText (cbuf, "exec quake.rc\n"); } - Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cmd_Exec_File (cbuf, fs_usercfg, 0); // Reparse the command line for + commands. // (sets still done, but it doesn't matter) // (Note, no non-base commands exist yet) @@ -939,7 +1063,7 @@ Host_Init (void) CL_UpdateScreen (cl.time); CL_UpdateScreen (cl.time); - Host_ExecConfig (host_cbuf, isDedicated || !cl_quakerc->int_val); + Host_ExecConfig (host_cbuf, isDedicated || !cl_quakerc); Hunk_AllocName (0, 0, "-HOST_HUNKLEVEL-"); host_hunklevel = Hunk_LowMark (0); diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 2ad67d3b3..3bd37b6d0 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -92,7 +92,7 @@ Host_Status_f (void) } else print = SV_ClientPrintf; - print ("host: %s\n", Cvar_VariableString ("hostname")); + print ("host: %s\n", hostname); print ("version: %4.2s\n", PACKAGE_VERSION); if (tcpipAvailable) print ("tcp/ip: %s\n", my_tcpip_address); @@ -667,7 +667,7 @@ Host_Loadgame_f (void) spawn_parms[i] = atof (PL_String (PL_ObjectAtIndex (item, i))); } current_skill = atoi (PL_String (PL_ObjectForKey (game, "current_skill"))); - Cvar_SetValue (skill, current_skill); + skill = current_skill; mapname = strdup (PL_String (PL_ObjectForKey (game, "name"))); CL_Disconnect_f (); @@ -742,7 +742,7 @@ Host_Name_f (void) const char *newName; if (Cmd_Argc () == 1) { - Sys_Printf ("\"name\" is \"%s\"\n", cl_name->string); + Sys_Printf ("\"name\" is \"%s\"\n", cl_name); return; } if (Cmd_Argc () == 2) @@ -751,9 +751,9 @@ Host_Name_f (void) newName = Cmd_Args (1); if (cmd_source == src_command) { - if (strcmp (cl_name->string, newName) == 0) + if (strcmp (cl_name, newName) == 0) return; - Cvar_Set (cl_name, va (0, "%.15s", newName)); + Cvar_Set ("_cl_name", va (0, "%.15s", newName)); if (cls.state >= ca_connected) CL_Cmd_ForwardToServer (); return; @@ -815,7 +815,7 @@ Host_Say (qboolean teamonly) if (!fromServer) snprintf (text, sizeof (text), "%c%s: ", 1, save->name); else - snprintf (text, sizeof (text), "%c<%s> ", 1, hostname->string); + snprintf (text, sizeof (text), "%c<%s> ", 1, hostname); j = sizeof (text) - 2 - strlen (text); // -2 for /n and null terminator if (strlen (p) > j) @@ -827,7 +827,7 @@ Host_Say (qboolean teamonly) for (j = 0, client = svs.clients; j < svs.maxclients; j++, client++) { if (!client || !client->active || !client->spawned) continue; - if (teamplay->int_val && teamonly && SVfloat (client->edict, team) != + if (teamplay && teamonly && SVfloat (client->edict, team) != SVfloat (save->edict, team)) continue; host_client = client; @@ -925,7 +925,7 @@ Host_Pause_f (void) CL_Cmd_ForwardToServer (); return; } - if (!pausable->int_val) + if (!pausable) SV_ClientPrintf ("Pause not allowed.\n"); else { sv.paused ^= 1; @@ -1137,7 +1137,7 @@ Host_Kick_f (void) if (net_is_dedicated) who = "Console"; else - who = cl_name->string; + who = cl_name; else who = save->name; diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 9e98ce717..df3762ed6 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -64,6 +64,7 @@ #include "nq/include/server.h" int sb_updates; // if >= vid.numpages, no update needed +static int sb_view_size; #define STAT_MINUS 10 // num frame for '-' stats digit @@ -106,124 +107,33 @@ int hipweapons[4] = { HIT_LASER_CANNON_BIT, HIT_MJOLNIR_BIT, 4, HIT_PROXIMITY_GUN_BIT }; qpic_t *hsb_items[2]; // MED 01/04/97 added hipnotic items array -cvar_t *scr_centertime; -cvar_t *scr_printspeed; - -static view_t *sbar_view; -static view_t *sbar_inventory_view; -static view_t *sbar_frags_view; - -static view_t *hud_view; -static view_t *hud_inventory_view; -static view_t *hud_armament_view; -static view_t *hud_frags_view; - -static view_t *overlay_view; -static view_t *stuff_view; -static view_t *main_view; +float scr_centertime; +static cvar_t scr_centertime_cvar = { + .name = "scr_centertime", + .description = + "How long in seconds screen hints are displayed", + .default_value = "2", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &scr_centertime }, +}; +float scr_printspeed; +static cvar_t scr_printspeed_cvar = { + .name = "scr_printspeed", + .description = + "How fast the text is displayed at the end of the single player " + "episodes", + .default_value = "8", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &scr_printspeed }, +}; static void -hud_swap_f (cvar_t *var) +viewsize_f (int view_size) { - if (var->int_val) { - hud_armament_view->gravity = grav_southwest; - hud_armament_view->children[0]->gravity = grav_northwest; - hud_armament_view->children[1]->gravity = grav_southeast; - stuff_view->gravity = grav_southeast; - } else { - hud_armament_view->gravity = grav_southeast; - hud_armament_view->children[0]->gravity = grav_northeast; - hud_armament_view->children[1]->gravity = grav_southwest; - stuff_view->gravity = grav_southwest; - } - view_move (hud_armament_view, hud_armament_view->xpos, - hud_armament_view->ypos); - view_move (stuff_view, stuff_view->xpos, stuff_view->ypos); -} - -static void -hud_scoreboard_gravity_f (cvar_t *var) -{ - grav_t grav; - - if (strequal (var->string, "center")) - grav = grav_center; - else if (strequal (var->string, "northwest")) - grav = grav_northwest; - else if (strequal (var->string, "north")) - grav = grav_north; - else if (strequal (var->string, "northeast")) - grav = grav_northeast; - else if (strequal (var->string, "west")) - grav = grav_west; - else if (strequal (var->string, "east")) - grav = grav_east; - else if (strequal (var->string, "southwest")) - grav = grav_southwest; - else if (strequal (var->string, "south")) - grav = grav_south; - else if (strequal (var->string, "southeast")) - grav = grav_southeast; - else - grav = grav_center; - overlay_view->gravity = grav; - view_move (overlay_view, overlay_view->xpos, overlay_view->ypos); -} - -static void -calc_sb_lines (cvar_t *var) -{ - int stuff_y; - - if (var->int_val >= 120) { - sb_lines = 0; - stuff_y = 0; - } else if (var->int_val >= 110) { - sb_lines = 24; - sbar_inventory_view->visible = 0; - hud_inventory_view->visible = 0; - hud_armament_view->visible = 0; - stuff_y = 32; - } else { - sb_lines = 48; - sbar_inventory_view->visible = 1; - hud_inventory_view->visible = 1; - hud_armament_view->visible = 1; - stuff_y = 48; - } - if (sb_lines) { - sbar_view->visible = 1; - hud_view->visible = 1; - view_resize (sbar_view, sbar_view->xlen, sb_lines); - view_resize (hud_view, hud_view->xlen, sb_lines); - } else { - sbar_view->visible = 0; - hud_view->visible = 0; - } - view_move (stuff_view, stuff_view->xpos, stuff_y); -} - -static void -hud_sbar_f (cvar_t *var) -{ - if (r_data->scr_viewsize) - calc_sb_lines (r_data->scr_viewsize); - SCR_SetBottomMargin (var->int_val ? sb_lines : 0); - if (var->int_val) { - view_remove (main_view, main_view->children[0]); - view_insert (main_view, sbar_view, 0); - } else { - view_remove (main_view, main_view->children[0]); - view_insert (main_view, hud_view, 0); - } -} - -static void -viewsize_f (cvar_t *var) -{ - calc_sb_lines (var); + sb_view_size = view_size; + HUD_Calc_sb_lines (view_size); if (hud_sbar) { - SCR_SetBottomMargin (hud_sbar->int_val ? sb_lines : 0); + SCR_SetBottomMargin (hud_sbar ? sb_lines : 0); } } @@ -835,7 +745,7 @@ draw_rogue_status (view_t *view) draw_pic (view, 0, 0, sb_armor[0]); // PGM 03/02/97 - fixed so color swatch appears in only CTF modes - if (cl.maxclients != 1 && teamplay->int_val > 3 && teamplay->int_val < 7) + if (cl.maxclients != 1 && teamplay > 3 && teamplay < 7) draw_rogue_face (view); else draw_face (view); @@ -996,7 +906,7 @@ sbar_update_vis (void) sbar_view->visible = 0; - headsup = !(hud_sbar->int_val || r_data->scr_viewsize->int_val < 100); + headsup = !(hud_sbar || sb_view_size < 100); if ((sb_updates >= r_data->vid->numpages) && !headsup) return; @@ -1007,9 +917,9 @@ sbar_update_vis (void) if (cls.state == ca_active && ((cl.stats[STAT_HEALTH] <= 0) || sb_showscores)) - overlay_view->visible = 1; + hud_overlay_view->visible = 1; else - overlay_view->visible = 0; + hud_overlay_view->visible = 0; if (!sb_lines) return; @@ -1024,7 +934,7 @@ void Sbar_Draw (void) { sbar_update_vis (); - main_view->draw (main_view); + hud_main_view->draw (hud_main_view); } static void @@ -1078,7 +988,7 @@ Sbar_DrawScoreboard (void) { //Sbar_SoloScoreboard (); if (cl.gametype == GAME_DEATHMATCH) - Sbar_DeathmatchOverlay (overlay_view); + Sbar_DeathmatchOverlay (hud_overlay_view); } static void @@ -1109,10 +1019,10 @@ draw_time (view_t *view) # define HOUR24 "%k" # define PM "%P" #endif - if (hud_time->int_val == 1) { // Use international format + if (hud_time == 1) { // Use international format strftime (st, sizeof (st), HOUR24":%M", local); draw_string (view, 8, 0, st); - } else if (hud_time->int_val >= 2) { // US AM/PM display + } else if (hud_time >= 2) { // US AM/PM display strftime (st, sizeof (st), HOUR12":%M "PM, local); draw_string (view, 8, 0, st); } @@ -1139,9 +1049,9 @@ draw_fps (view_t *view) static void draw_stuff (view_t *view) { - if (hud_time->int_val > 0) + if (hud_time > 0) draw_time (view); - if (hud_fps->int_val > 0) + if (hud_fps > 0) draw_fps (view); } @@ -1182,10 +1092,10 @@ Sbar_IntermissionOverlay (void) r_data->scr_fullupdate = 0; if (cl.gametype == GAME_DEATHMATCH) { - Sbar_DeathmatchOverlay (overlay_view); + Sbar_DeathmatchOverlay (hud_overlay_view); return; } - draw_intermission (overlay_view); + draw_intermission (hud_overlay_view); } /* CENTER PRINTING */ @@ -1209,7 +1119,7 @@ Sbar_CenterPrint (const char *str) dstring_copystr (¢er_string, str); - centertime_off = scr_centertime->value; + centertime_off = scr_centertime; centertime_start = realtime; // count the number of lines for centering @@ -1263,10 +1173,10 @@ Sbar_FinaleOverlay (void) r_data->scr_copyeverything = 1; - draw_cachepic (overlay_view, 0, 16, "gfx/finale.lmp", 1); + draw_cachepic (hud_overlay_view, 0, 16, "gfx/finale.lmp", 1); // the finale prints the characters one at a time - remaining = scr_printspeed->value * (realtime - centertime_start); - Sbar_DrawCenterString (overlay_view, remaining); + remaining = scr_printspeed * (realtime - centertime_start); + Sbar_DrawCenterString (hud_overlay_view, remaining); } void @@ -1278,7 +1188,7 @@ Sbar_DrawCenterPrint (void) if (centertime_off <= 0) return; - Sbar_DrawCenterString (overlay_view, -1); + Sbar_DrawCenterString (hud_overlay_view, -1); } static void @@ -1383,7 +1293,7 @@ init_hud_views (void) view_add (hud_view, hud_armament_view); - view_insert (main_view, hud_view, 0); + view_insert (hud_main_view, hud_view, 0); } static void @@ -1495,7 +1405,7 @@ init_hipnotic_hud_views (void) view_add (hud_view, hud_armament_view); - view_insert (main_view, hud_view, 0); + view_insert (hud_main_view, hud_view, 0); } static void @@ -1592,33 +1502,33 @@ init_rogue_hud_views (void) view_add (hud_view, hud_armament_view); - view_insert (main_view, hud_view, 0); + view_insert (hud_main_view, hud_view, 0); } static void init_views (void) { - main_view = view_new (0, 0, r_data->vid->conview->xlen, + hud_main_view = view_new (0, 0, r_data->vid->conview->xlen, r_data->vid->conview->ylen, grav_northwest); if (con_module) - view_insert (con_module->data->console->view, main_view, 0); - main_view->resize_x = 1; // get resized if the 2d view resizes - main_view->resize_y = 1; - main_view->visible = 0; // but don't let the console draw our stuff + view_insert (con_module->data->console->view, hud_main_view, 0); + hud_main_view->resize_x = 1; // get resized if the 2d view resizes + hud_main_view->resize_y = 1; + hud_main_view->visible = 0; // but don't let the console draw our stuff if (r_data->vid->conview->ylen > 300) - overlay_view = view_new (0, 0, 320, 300, grav_center); + hud_overlay_view = view_new (0, 0, 320, 300, grav_center); else - overlay_view = view_new (0, 0, 320, r_data->vid->conview->ylen, + hud_overlay_view = view_new (0, 0, 320, r_data->vid->conview->ylen, grav_center); - overlay_view->draw = draw_overlay; - overlay_view->visible = 0; + hud_overlay_view->draw = draw_overlay; + hud_overlay_view->visible = 0; - stuff_view = view_new (0, 48, 152, 16, grav_southwest); - stuff_view->draw = draw_stuff; + hud_stuff_view = view_new (0, 48, 152, 16, grav_southwest); + hud_stuff_view->draw = draw_stuff; - view_insert (main_view, overlay_view, 0); - view_insert (main_view, stuff_view, 0); + view_insert (hud_main_view, hud_overlay_view, 0); + view_insert (hud_main_view, hud_stuff_view, 0); if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) { init_hipnotic_sbar_views (); @@ -1793,21 +1703,9 @@ Sbar_Init (void) } r_data->viewsize_callback = viewsize_f; - hud_sbar = Cvar_Get ("hud_sbar", "0", CVAR_ARCHIVE, hud_sbar_f, - "status bar mode: 0 = hud, 1 = oldstyle"); - hud_swap = Cvar_Get ("hud_swap", "0", CVAR_ARCHIVE, hud_swap_f, - "new HUD on left side?"); - hud_scoreboard_gravity = Cvar_Get ("hud_scoreboard_gravity", "center", - CVAR_ARCHIVE, hud_scoreboard_gravity_f, - "control placement of scoreboard " - "overlay: center, northwest, north, " - "northeast, west, east, southwest, " - "south, southeast"); - scr_centertime = Cvar_Get ("scr_centertime", "2", CVAR_NONE, NULL, "How " - "long in seconds screen hints are displayed"); - scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_NONE, NULL, - "How fast the text is displayed at the end of " - "the single player episodes"); + HUD_Init_Cvars (); + Cvar_Register (&scr_centertime_cvar, 0, 0); + Cvar_Register (&scr_printspeed_cvar, 0, 0); // register GIB builtins GIB_Builtin_Add ("print::center", Sbar_GIB_Print_Center_f); diff --git a/nq/source/sv_cl_phys.c b/nq/source/sv_cl_phys.c index 5a7cda831..20e5ee784 100644 --- a/nq/source/sv_cl_phys.c +++ b/nq/source/sv_cl_phys.c @@ -39,8 +39,6 @@ #define sv_frametime host_frametime -cvar_t *sv_nostep; - // CLIENT MOVEMENT ============================================================ /* @@ -248,7 +246,7 @@ SV_WalkMove (edict_t *ent) if (SVfloat (ent, movetype) != MOVETYPE_WALK) return; // gibbed by a trigger - if (sv_nostep->int_val) + if (sv_nostep) return; if ((int) SVfloat (sv_player, flags) & FL_WATERJUMP) diff --git a/nq/source/sv_cvar.c b/nq/source/sv_cvar.c index 0e8e35383..ea2bfbfd5 100644 --- a/nq/source/sv_cvar.c +++ b/nq/source/sv_cvar.c @@ -35,11 +35,11 @@ #include "nq/include/server.h" void -Cvar_Info (cvar_t *var) +Cvar_Info (void *data, const cvar_t *cvar) { - if (var->flags & CVAR_SERVERINFO) { + if (cvar->flags & CVAR_SERVERINFO) { if (sv.active) SV_BroadcastPrintf ("\"%s\" changed to \"%s\"\n", - var->name, var->string); + cvar->name, Cvar_VarString (cvar)); } } diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index d687063ed..fd0741a7c 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -46,10 +46,10 @@ client_static_t cls; worldscene_t cl_world; -cvar_t *cl_name; -cvar_t *cl_writecfg; -cvar_t *demo_speed; -cvar_t *chase_active; +char *cl_name; +int cl_writecfg; +float demo_speed; +int chase_active; int fps_count; int viewentity; diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 57282ea1d..04a6bf048 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -85,28 +85,8 @@ SV_Init (void) SV_Progs_Init (); - sv_maxvelocity = Cvar_Get ("sv_maxvelocity", "2000", CVAR_NONE, NULL, - "None"); - sv_gravity = Cvar_Get ("sv_gravity", "800", CVAR_SERVERINFO, Cvar_Info, - "None"); - sv_jump_any = Cvar_Get ("sv_jump_any", "1", CVAR_NONE, NULL, "None"); - sv_friction = Cvar_Get ("sv_friction", "4", CVAR_SERVERINFO, Cvar_Info, - "None"); - //NOTE: the cl/sv clash is deliberate: dedicated server will use the right - //vars, but client/server combo will use the one. - sv_rollspeed = Cvar_Get ("cl_rollspeed", "200", CVAR_NONE, NULL, - "How quickly you straighten out after strafing"); - sv_rollangle = Cvar_Get ("cl_rollangle", "2.0", CVAR_NONE, NULL, - "How much your screen tilts when strafing"); - sv_edgefriction = Cvar_Get ("edgefriction", "2", CVAR_NONE, NULL, "None"); - sv_stopspeed = Cvar_Get ("sv_stopspeed", "100", CVAR_NONE, NULL, "None"); - sv_maxspeed = Cvar_Get ("sv_maxspeed", "320", CVAR_SERVERINFO, Cvar_Info, - "None"); - sv_accelerate = Cvar_Get ("sv_accelerate", "10", CVAR_NONE, NULL, "None"); - sv_idealpitchscale = Cvar_Get ("sv_idealpitchscale", "0.8", CVAR_NONE, - NULL, "None"); - sv_aim = Cvar_Get ("sv_aim", "0.93", CVAR_NONE, NULL, "None"); - sv_nostep = Cvar_Get ("sv_nostep", "0", CVAR_NONE, NULL, "None"); + SV_Physics_Init_Cvars (); + SV_User_Init_Cvars (); Cmd_AddCommand ("sv_protocol", SV_Protocol_f, "set the protocol to be " "used after the next map load"); @@ -254,7 +234,7 @@ SV_SendServerinfo (client_t *client) MSG_WriteLong (&client->message, sv.protocol); MSG_WriteByte (&client->message, svs.maxclients); - if (!coop->int_val && deathmatch->int_val) + if (!coop && deathmatch) MSG_WriteByte (&client->message, GAME_DEATHMATCH); else MSG_WriteByte (&client->message, GAME_COOP); @@ -1109,8 +1089,8 @@ SV_SpawnServer (const char *server) S_BlockSound (); // let's not have any servers with no name - if (hostname->string[0] == 0) - Cvar_Set (hostname, "UNNAMED"); + if (hostname[0] == 0) + Cvar_Set ("hostname", "UNNAMED"); Sys_MaskPrintf (SYS_dev, "SpawnServer: %s\n", server); svs.changelevel_issued = false; // now safe to issue another @@ -1122,15 +1102,15 @@ SV_SpawnServer (const char *server) } // make cvars consistant - if (coop->int_val) - Cvar_SetValue (deathmatch, 0); - current_skill = skill->int_val; + if (coop) + deathmatch = 0; + current_skill = skill; if (current_skill < 0) current_skill = 0; if (current_skill > 3) current_skill = 3; - Cvar_SetValue (skill, (float) current_skill); + skill = current_skill; // set up the new server Host_ClearMemory (); @@ -1142,7 +1122,7 @@ SV_SpawnServer (const char *server) sv.protocol = sv_protocol; // load progs to get entity field count - sv.max_edicts = bound (MIN_EDICTS, max_edicts->int_val, MAX_EDICTS); + sv.max_edicts = bound (MIN_EDICTS, max_edicts, MAX_EDICTS); SV_LoadProgs (); SV_FreeAllEdictLeafs (); @@ -1202,10 +1182,10 @@ SV_SpawnServer (const char *server) SVfloat (ent, solid) = SOLID_BSP; SVfloat (ent, movetype) = MOVETYPE_PUSH; - if (coop->int_val) - *sv_globals.coop = coop->int_val; + if (coop) + *sv_globals.coop = coop; else - *sv_globals.deathmatch = deathmatch->int_val; + *sv_globals.deathmatch = deathmatch; *sv_globals.mapname = PR_SetString (&sv_pr_state, sv.name); diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index 552fe227a..6d8d1cecb 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -54,11 +54,52 @@ solid_edge items clip against only bsp models. */ -cvar_t *sv_friction; -cvar_t *sv_gravity; -cvar_t *sv_jump_any; -cvar_t *sv_maxvelocity; -cvar_t *sv_stopspeed; +float sv_friction; +static cvar_t sv_friction_cvar = { + .name = "sv_friction", + .description = + "Sets the friction value for the players", + .default_value = "4", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_float, .value = &sv_friction }, +}; +float sv_gravity; +static cvar_t sv_gravity_cvar = { + .name = "sv_gravity", + .description = + "Sets the global value for the amount of gravity", + .default_value = "800", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_float, .value = &sv_gravity }, +}; +int sv_jump_any; +static cvar_t sv_jump_any_cvar = { + .name = "sv_jump_any", + .description = + "None", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_jump_any }, +}; +float sv_maxvelocity; +static cvar_t sv_maxvelocity_cvar = { + .name = "sv_maxvelocity", + .description = + "Sets the maximum velocity an object can travel", + .default_value = "2000", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_maxvelocity }, +}; +float sv_stopspeed; +static cvar_t sv_stopspeed_cvar = { + .name = "sv_stopspeed", + .description = + "Sets the value that determines how fast the player should come to a " + "complete stop", + .default_value = "100", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_stopspeed }, +}; #define MOVE_EPSILON 0.01 #if 0 @@ -107,8 +148,8 @@ SV_CheckVelocity (edict_t *ent) } #endif wishspeed = VectorLength (SVvector (ent, velocity)); - if (wishspeed > sv_maxvelocity->value) { - VectorScale (SVvector (ent, velocity), sv_maxvelocity->value / + if (wishspeed > sv_maxvelocity) { + VectorScale (SVvector (ent, velocity), sv_maxvelocity / wishspeed, SVvector (ent, velocity)); } } @@ -208,7 +249,7 @@ SV_EntCanSupportJump (edict_t *ent) int solid = SVfloat (ent, solid); if (solid == SOLID_BSP) return 1; - if (!sv_jump_any->int_val) + if (!sv_jump_any) return 0; if (solid == SOLID_NOT || solid == SOLID_SLIDEBOX) return 0; @@ -352,7 +393,7 @@ SV_AddGravity (edict_t *ent) ent_grav = SVfloat (ent, gravity); else ent_grav = 1.0; - SVvector (ent, velocity)[2] -= ent_grav * sv_gravity->value * sv_frametime; + SVvector (ent, velocity)[2] -= ent_grav * sv_gravity * sv_frametime; SVdata (ent)->add_grav = true; } @@ -365,7 +406,7 @@ SV_FinishGravity (edict_t *ent, vec3_t move) ent_grav = SVfloat (ent, gravity); else ent_grav = 1.0; - ent_grav *= sv_gravity->value; + ent_grav *= sv_gravity; move[2] += ent_grav * sv_frametime * sv_frametime / 2; } @@ -768,7 +809,7 @@ SV_Physics_Step (edict_t *ent) // freefall if not on ground if (!((int) SVfloat (ent, flags) & (FL_ONGROUND | FL_FLY | FL_SWIM))) { - if (SVvector (ent, velocity)[2] < sv_gravity->value * -0.1) + if (SVvector (ent, velocity)[2] < sv_gravity * -0.1) hitsound = true; else hitsound = false; @@ -889,3 +930,13 @@ SV_Physics (void) PR_ExecuteProgram (&sv_pr_state, sv_funcs.EndFrame); } } + +void +SV_Physics_Init_Cvars (void) +{ + Cvar_Register (&sv_friction_cvar, Cvar_Info, &sv_friction); + Cvar_Register (&sv_gravity_cvar, Cvar_Info, &sv_gravity); + Cvar_Register (&sv_jump_any_cvar, 0, 0); + Cvar_Register (&sv_maxvelocity_cvar, 0, 0); + Cvar_Register (&sv_stopspeed_cvar, 0, 0); +} diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index b805a40be..9984d97ff 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -949,7 +949,15 @@ PF_pointcontents (progs_t *pr, void *data) R_FLOAT (pr) = SV_PointContents (v); } -cvar_t *sv_aim; +float sv_aim; +static cvar_t sv_aim_cvar = { + .name = "sv_aim", + .description = + "None", + .default_value = "0.93", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_aim }, +}; /* PF_aim @@ -980,7 +988,7 @@ PF_aim (progs_t *pr, void *data) VectorMultAdd (start, 2048, dir, end); tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent); if (tr.ent && SVfloat (tr.ent, takedamage) == DAMAGE_AIM - && (!teamplay->int_val || SVfloat (ent, team) <= 0 + && (!teamplay || SVfloat (ent, team) <= 0 || SVfloat (ent, team) != SVfloat (tr.ent, team))) { VectorCopy (*sv_globals.v_forward, R_VECTOR (pr)); return; @@ -988,7 +996,7 @@ PF_aim (progs_t *pr, void *data) // try all possible entities VectorCopy (dir, bestdir); - bestdist = sv_aim->value; + bestdist = sv_aim; bestent = NULL; check = NEXT_EDICT (pr, sv.edicts); @@ -997,7 +1005,7 @@ PF_aim (progs_t *pr, void *data) continue; if (check == ent) continue; - if (teamplay->int_val && SVfloat (ent, team) > 0 + if (teamplay && SVfloat (ent, team) > 0 && SVfloat (ent, team) == SVfloat (check, team)) continue; // don't aim at teammate @@ -1574,6 +1582,8 @@ static builtin_t builtins[] = { void SV_PR_Cmds_Init () { + Cvar_Register (&sv_aim_cvar, 0, 0); + RUA_Init (&sv_pr_state, 1); PR_Cmds_Init (&sv_pr_state); diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index a0235e108..e9e318a28 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -55,23 +55,151 @@ sv_fields_t sv_fields; edict_t sv_edicts[MAX_EDICTS]; sv_data_t sv_data[MAX_EDICTS]; -cvar_t *sv_progs; -cvar_t *sv_progs_zone; -cvar_t *sv_progs_stack; -cvar_t *sv_progs_ext; -cvar_t *pr_checkextensions; +char *sv_progs; +static cvar_t sv_progs_cvar = { + .name = "sv_progs", + .description = + "Override the default game progs.", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_progs }, +}; +int sv_progs_zone; +static cvar_t sv_progs_zone_cvar = { + .name = "sv_progs_zone", + .description = + "size of the zone for progs in kb", + .default_value = "256", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_progs_zone }, +}; +int sv_progs_stack; +static cvar_t sv_progs_stack_cvar = { + .name = "sv_progs_stack", + .description = + "size of the stack for progs in kb", + .default_value = "256", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_progs_stack }, +}; +char *sv_progs_ext; +static cvar_t sv_progs_ext_cvar = { + .name = "sv_progs_ext", + .description = + "extention mapping to use: none, id, qf", + .default_value = "qf", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_progs_ext }, +}; +char *pr_checkextensions; +static cvar_t pr_checkextensions_cvar = { + .name = "pr_checkextensions", + .description = + "indicate the presence of the checkextentions qc function", + .default_value = "1", + .flags = CVAR_ROM, + .value = { .type = 0/* not used */, .value = &pr_checkextensions }, +}; -cvar_t *nomonsters; -cvar_t *gamecfg; -cvar_t *scratch1; -cvar_t *scratch2; -cvar_t *scratch3; -cvar_t *scratch4; -cvar_t *savedgamecfg; -cvar_t *saved1; -cvar_t *saved2; -cvar_t *saved3; -cvar_t *saved4; +char *nomonsters; +static cvar_t nomonsters_cvar = { + .name = "nomonsters", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &nomonsters }, +}; +char *gamecfg; +static cvar_t gamecfg_cvar = { + .name = "gamecfg", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &gamecfg }, +}; +char *scratch1; +static cvar_t scratch1_cvar = { + .name = "scratch1", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &scratch1 }, +}; +char *scratch2; +static cvar_t scratch2_cvar = { + .name = "scratch2", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &scratch2 }, +}; +char *scratch3; +static cvar_t scratch3_cvar = { + .name = "scratch3", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &scratch3 }, +}; +char *scratch4; +static cvar_t scratch4_cvar = { + .name = "scratch4", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &scratch4 }, +}; +char *savedgamecfg; +static cvar_t savedgamecfg_cvar = { + .name = "savedgamecfg", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &savedgamecfg }, +}; +char *saved1; +static cvar_t saved1_cvar = { + .name = "saved1", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &saved1 }, +}; +char *saved2; +static cvar_t saved2_cvar = { + .name = "saved2", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &saved2 }, +}; +char *saved3; +static cvar_t saved3_cvar = { + .name = "saved3", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &saved3 }, +}; +char *saved4; +static cvar_t saved4_cvar = { + .name = "saved4", + .description = + "No Description", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = 0/* not used */, .value = &saved4 }, +}; static int sv_range; @@ -93,7 +221,7 @@ static int prune_edict (progs_t *pr, edict_t *ent) { // remove things from different skill levels or deathmatch - if (deathmatch->int_val) { + if (deathmatch) { if (((int) SVfloat (ent, spawnflags) & SPAWNFLAG_NOT_DEATHMATCH)) { return 1; @@ -493,10 +621,10 @@ SV_LoadProgs (void) const char *progs_name = "progs.dat"; const char *range; - if (strequal (sv_progs_ext->string, "qf")) { + if (strequal (sv_progs_ext, "qf")) { sv_range = PR_RANGE_QF; range = "QF"; - } else if (strequal (sv_progs_ext->string, "id")) { + } else if (strequal (sv_progs_ext, "id")) { sv_range = PR_RANGE_ID; range = "ID"; } else { @@ -510,12 +638,12 @@ SV_LoadProgs (void) if (qfs_gamedir->gamecode && *qfs_gamedir->gamecode) progs_name = qfs_gamedir->gamecode; - if (*sv_progs->string) - progs_name = sv_progs->string; + if (*sv_progs) + progs_name = sv_progs; sv_pr_state.max_edicts = sv.max_edicts; - sv_pr_state.zone_size = sv_progs_zone->int_val * 1024; - sv_pr_state.stack_size = sv_progs_stack->int_val * 1024; + sv_pr_state.zone_size = sv_progs_zone * 1024; + sv_pr_state.stack_size = sv_progs_stack * 1024; sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name); @@ -559,30 +687,21 @@ void SV_Progs_Init_Cvars (void) { PR_Init_Cvars (); - sv_progs = Cvar_Get ("sv_progs", "", CVAR_NONE, NULL, - "Override the default game progs."); - sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL, - "size of the zone for progs in kb"); - sv_progs_stack = Cvar_Get ("sv_progs_stack", "256", CVAR_NONE, NULL, - "size of the stack for progs in kb"); - sv_progs_ext = Cvar_Get ("sv_progs_ext", "qf", CVAR_NONE, NULL, - "extention mapping to use: " - "none, id, qf"); - pr_checkextensions = Cvar_Get ("pr_checkextensions", "1", CVAR_ROM, NULL, - "indicate the presence of the " - "checkextentions qc function"); + Cvar_Register (&sv_progs_cvar, 0, 0); + Cvar_Register (&sv_progs_zone_cvar, 0, 0); + Cvar_Register (&sv_progs_stack_cvar, 0, 0); + Cvar_Register (&sv_progs_ext_cvar, 0, 0); + Cvar_Register (&pr_checkextensions_cvar, 0, 0); - nomonsters = Cvar_Get ("nomonsters", "0", CVAR_NONE, NULL, - "No Description"); - gamecfg = Cvar_Get ("gamecfg", "0", CVAR_NONE, NULL, "No Description"); - scratch1 = Cvar_Get ("scratch1", "0", CVAR_NONE, NULL, "No Description"); - scratch2 = Cvar_Get ("scratch2", "0", CVAR_NONE, NULL, "No Description"); - scratch3 = Cvar_Get ("scratch3", "0", CVAR_NONE, NULL, "No Description"); - scratch4 = Cvar_Get ("scratch4", "0", CVAR_NONE, NULL, "No Description"); - savedgamecfg = Cvar_Get ("savedgamecfg", "0", CVAR_ARCHIVE, NULL, - "No Description"); - saved1 = Cvar_Get ("saved1", "0", CVAR_ARCHIVE, NULL, "No Description"); - saved2 = Cvar_Get ("saved2", "0", CVAR_ARCHIVE, NULL, "No Description"); - saved3 = Cvar_Get ("saved3", "0", CVAR_ARCHIVE, NULL, "No Description"); - saved4 = Cvar_Get ("saved4", "0", CVAR_ARCHIVE, NULL, "No Description"); + Cvar_Register (&nomonsters_cvar, 0, 0); + Cvar_Register (&gamecfg_cvar, 0, 0); + Cvar_Register (&scratch1_cvar, 0, 0); + Cvar_Register (&scratch2_cvar, 0, 0); + Cvar_Register (&scratch3_cvar, 0, 0); + Cvar_Register (&scratch4_cvar, 0, 0); + Cvar_Register (&savedgamecfg_cvar, 0, 0); + Cvar_Register (&saved1_cvar, 0, 0); + Cvar_Register (&saved2_cvar, 0, 0); + Cvar_Register (&saved3_cvar, 0, 0); + Cvar_Register (&saved4_cvar, 0, 0); } diff --git a/nq/source/sv_user.c b/nq/source/sv_user.c index 87623e7d6..f1470146d 100644 --- a/nq/source/sv_user.c +++ b/nq/source/sv_user.c @@ -48,12 +48,46 @@ #include "nq/include/server.h" #include "nq/include/sv_progs.h" -cvar_t *sv_rollangle; -cvar_t *sv_rollspeed; +int sv_nostep; +static cvar_t sv_nostep_cvar = { + .name = "sv_nostep", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_nostep }, +}; + +float sv_rollangle; +static cvar_t sv_rollangle_cvar = { + .name = "cl_rollangle", + .description = + "How much your screen tilts when strafing", + .default_value = "2.0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_rollangle }, +}; +float sv_rollspeed; +static cvar_t sv_rollspeed_cvar = { + .name = "cl_rollspeed", + .description = + "How quickly you straighten out after strafing", + .default_value = "200", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_rollspeed }, +}; edict_t *sv_player; -cvar_t *sv_edgefriction; +float sv_edgefriction; +static cvar_t sv_edgefriction_cvar = { + .name = "edgefriction", + .description = + "None", + .default_value = "2", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_edgefriction }, +}; vec3_t forward, right, up; @@ -69,7 +103,15 @@ qboolean onground; usercmd_t cmd; -cvar_t *sv_idealpitchscale; +float sv_idealpitchscale; +static cvar_t sv_idealpitchscale_cvar = { + .name = "sv_idealpitchscale", + .description = + "None", + .default_value = "0.8", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_idealpitchscale }, +}; #define MAX_FORWARD 6 @@ -86,12 +128,12 @@ SV_CalcRoll (const vec3_t angles, const vec3_t velocity) sign = side < 0 ? -1 : 1; side = fabs (side); - value = sv_rollangle->value; + value = sv_rollangle; // if (cl.inwater) // value *= 6; - if (side < sv_rollspeed->value) - side = side * value / sv_rollspeed->value; + if (side < sv_rollspeed) + side = side * value / sv_rollspeed; else side = value; @@ -154,7 +196,7 @@ SV_SetIdealPitch (void) if (steps < 2) return; - SVfloat (sv_player, idealpitch) = -dir * sv_idealpitchscale->value; + SVfloat (sv_player, idealpitch) = -dir * sv_idealpitchscale; } static void @@ -180,12 +222,12 @@ SV_UserFriction (void) trace = SV_Move (start, vec3_origin, vec3_origin, stop, true, sv_player); if (trace.fraction == 1.0) - friction = sv_friction->value * sv_edgefriction->value; + friction = sv_friction * sv_edgefriction; else - friction = sv_friction->value; + friction = sv_friction; // apply friction - control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed; + control = speed < sv_stopspeed ? sv_stopspeed : speed; newspeed = speed - host_frametime * control * friction; if (newspeed < 0) @@ -197,8 +239,24 @@ SV_UserFriction (void) vel[2] = vel[2] * newspeed; } -cvar_t *sv_maxspeed; -cvar_t *sv_accelerate; +float sv_maxspeed; +static cvar_t sv_maxspeed_cvar = { + .name = "sv_maxspeed", + .description = + "None", + .default_value = "320", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_float, .value = &sv_maxspeed }, +}; +float sv_accelerate; +static cvar_t sv_accelerate_cvar = { + .name = "sv_accelerate", + .description = + "None", + .default_value = "10", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_accelerate }, +}; #if 0 void @@ -214,7 +272,7 @@ SV_Accelerate (vec3_t wishvel) VectorSubtract (wishvel, velocity, pushvec); addspeed = VectorNormalize (pushvec); - accelspeed = sv_accelerate->value * host_frametime * addspeed; + accelspeed = sv_accelerate * host_frametime * addspeed; if (accelspeed > addspeed) accelspeed = addspeed; @@ -233,7 +291,7 @@ SV_Accelerate (void) addspeed = wishspeed - currentspeed; if (addspeed <= 0) return; - accelspeed = sv_accelerate->value * host_frametime * wishspeed; + accelspeed = sv_accelerate * host_frametime * wishspeed; if (accelspeed > addspeed) accelspeed = addspeed; @@ -254,8 +312,8 @@ SV_AirAccelerate (vec3_t wishveloc) addspeed = wishspd - currentspeed; if (addspeed <= 0) return; -// accelspeed = sv_accelerate->value * host_frametime; - accelspeed = sv_accelerate->value * wishspeed * host_frametime; +// accelspeed = sv_accelerate * host_frametime; + accelspeed = sv_accelerate * wishspeed * host_frametime; if (accelspeed > addspeed) accelspeed = addspeed; @@ -296,16 +354,16 @@ SV_WaterMove (void) wishvel[2] += cmd.upmove; wishspeed = VectorLength (wishvel); - if (wishspeed > sv_maxspeed->value) { - VectorScale (wishvel, sv_maxspeed->value / wishspeed, wishvel); - wishspeed = sv_maxspeed->value; + if (wishspeed > sv_maxspeed) { + VectorScale (wishvel, sv_maxspeed / wishspeed, wishvel); + wishspeed = sv_maxspeed; } wishspeed *= 0.7; // water friction speed = VectorLength (velocity); if (speed) { - newspeed = speed - host_frametime * speed * sv_friction->value; + newspeed = speed - host_frametime * speed * sv_friction; if (newspeed < 0) newspeed = 0; VectorScale (velocity, newspeed / speed, velocity); @@ -321,7 +379,7 @@ SV_WaterMove (void) return; VectorNormalize (wishvel); - accelspeed = sv_accelerate->value * wishspeed * host_frametime; + accelspeed = sv_accelerate * wishspeed * host_frametime; if (accelspeed > addspeed) accelspeed = addspeed; @@ -368,9 +426,9 @@ SV_AirMove (void) VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize (wishdir); - if (wishspeed > sv_maxspeed->value) { - VectorScale (wishvel, sv_maxspeed->value / wishspeed, wishvel); - wishspeed = sv_maxspeed->value; + if (wishspeed > sv_maxspeed) { + VectorScale (wishvel, sv_maxspeed / wishspeed, wishvel); + wishspeed = sv_maxspeed; } if (SVfloat (sv_player, movetype) == MOVETYPE_NOCLIP) { // noclip @@ -608,3 +666,40 @@ SV_RunClients (void) SV_ClientThink (); } } + +static void +sv_rollspeed_f (void *data, const cvar_t *cvar) +{ + sv_rollspeed = *(float *) cvar->value.value; +} + +static void +sv_rollangle_f (void *data, const cvar_t *cvar) +{ + sv_rollangle = *(float *) cvar->value.value; +} + +void +SV_User_Init_Cvars (void) +{ + //NOTE: the cl/sv clash is deliberate: dedicated server will use the right + //vars, but client/server combo will use the one. + if (isDedicated) { + Cvar_Register (&sv_rollspeed_cvar, 0, 0); + Cvar_Register (&sv_rollangle_cvar, 0, 0); + } else { + cvar_t *var; + var = Cvar_FindVar ("cl_rollspeed"); + Cvar_AddListener (var, sv_rollspeed_f, 0); + sv_rollspeed = *(float *) var->value.value; + var = Cvar_FindVar ("cl_rollangle"); + Cvar_AddListener (var, sv_rollangle_f, 0); + sv_rollangle = *(float *) var->value.value; + } + Cvar_Register (&sv_edgefriction_cvar, 0, 0); + Cvar_Register (&sv_maxspeed_cvar, Cvar_Info, &sv_maxspeed); + Cvar_Register (&sv_accelerate_cvar, 0, 0); + Cvar_Register (&sv_idealpitchscale_cvar, 0, 0); + + Cvar_Register (&sv_nostep_cvar, 0, 0); +} diff --git a/nq/source/sys_sdl.c b/nq/source/sys_sdl.c index 68c2e91eb..70193fd74 100644 --- a/nq/source/sys_sdl.c +++ b/nq/source/sys_sdl.c @@ -119,7 +119,7 @@ SDL_main (int argc, char *argv[]) Host_Init (); #ifndef _WIN32 - if (!sys_nostdout->int_val) { + if (!sys_nostdout) { fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | O_NONBLOCK); Sys_Printf ("Quake -- Version %s\n", NQ_VERSION); } @@ -137,14 +137,14 @@ SDL_main (int argc, char *argv[]) time = newtime - oldtime; if (net_is_dedicated) { // play vcrfiles at max speed - if (time < sys_ticrate->value && (!vcrFile || recording)) { + if (time < sys_ticrate && (!vcrFile || recording)) { usleep (1); continue; // not time to run a server-only tic yet } - time = sys_ticrate->value; + time = sys_ticrate; } - if (time > sys_ticrate->value * 2) + if (time > sys_ticrate * 2) oldtime = newtime; else oldtime += time; diff --git a/nq/source/sys_unix.c b/nq/source/sys_unix.c index e244b940e..83d61a105 100644 --- a/nq/source/sys_unix.c +++ b/nq/source/sys_unix.c @@ -80,7 +80,7 @@ main (int argc, const char **argv) Host_Init (); - if (!sys_nostdout->int_val) { + if (!sys_nostdout) { fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | O_NONBLOCK); Sys_Printf ("Quake -- Version %s\n", NQ_VERSION); } @@ -92,14 +92,14 @@ main (int argc, const char **argv) time = newtime - oldtime; if (net_is_dedicated) { // play vcrfiles at max speed - if (time < sys_ticrate->value && (!vcrFile || recording)) { + if (time < sys_ticrate && (!vcrFile || recording)) { usleep (1); continue; // not time to run a server-only tic yet } - time = sys_ticrate->value; + time = sys_ticrate; } - if (time > sys_ticrate->value * 2) + if (time > sys_ticrate * 2) oldtime = newtime; else oldtime += time; diff --git a/nq/source/sys_unixd.c b/nq/source/sys_unixd.c index 18e45a8ad..2971e2242 100644 --- a/nq/source/sys_unixd.c +++ b/nq/source/sys_unixd.c @@ -100,13 +100,13 @@ main (int argc, const char **argv) // find time spent rendering last frame newtime = Sys_DoubleTime (); time = newtime - oldtime; - if (time < sys_ticrate->value) { + if (time < sys_ticrate) { usleep (1); continue; // not time to run a server-only tic yet } - time = sys_ticrate->value; + time = sys_ticrate; - if (time > sys_ticrate->value * 2) + if (time > sys_ticrate * 2) oldtime = newtime; else oldtime += time; diff --git a/nq/source/sys_win.c b/nq/source/sys_win.c index 59c61b796..eb543d1c9 100644 --- a/nq/source/sys_win.c +++ b/nq/source/sys_win.c @@ -229,14 +229,14 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, time = newtime - oldtime; if (net_is_dedicated) { // play vcrfiles at max speed - if (time < sys_ticrate->value && (!vcrFile || recording)) { + if (time < sys_ticrate && (!vcrFile || recording)) { Sleep (1); continue; // not time to run a server-only tic yet } - time = sys_ticrate->value; + time = sys_ticrate; } - if (time > sys_ticrate->value * 2) + if (time > sys_ticrate * 2) oldtime = newtime; else oldtime += time; diff --git a/nq/source/sys_wind.c b/nq/source/sys_wind.c index 69393dfd6..0f1681278 100644 --- a/nq/source/sys_wind.c +++ b/nq/source/sys_wind.c @@ -79,13 +79,13 @@ main (int argc, const char **argv) // find time spent rendering last frame newtime = Sys_DoubleTime (); time = newtime - oldtime; - if (time < sys_ticrate->value) { + if (time < sys_ticrate) { Sleep (1); continue; // not time to run a server-only tic yet } - time = sys_ticrate->value; + time = sys_ticrate; - if (time > sys_ticrate->value * 2) + if (time > sys_ticrate * 2) oldtime = newtime; else oldtime += time; diff --git a/qtv/include/qtv.h b/qtv/include/qtv.h index f8d0918f3..c6afcf39c 100644 --- a/qtv/include/qtv.h +++ b/qtv/include/qtv.h @@ -54,7 +54,7 @@ extern double realtime; extern struct cbuf_s *qtv_cbuf; extern struct cbuf_args_s *qtv_args; -extern struct cvar_s *sv_timeout; +extern float sv_timeout; struct client_s; diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 7d720ce0a..6c95554a9 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -75,14 +75,49 @@ static plugin_list_t server_plugin_list[] = { double realtime; -cvar_t *sv_timeout; +float sv_timeout; +static cvar_t sv_timeout_cvar = { + .name = "timeout", + .description = + "Sets the amount of time in seconds before a client is considered " + "disconnected if the server does not receive a packet", + .default_value = "60", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_timeout }, +}; cbuf_t *qtv_cbuf; cbuf_args_t *qtv_args; -static cvar_t *qtv_console_plugin; -static cvar_t *qtv_port; -static cvar_t *qtv_mem_size; +static char *qtv_console_plugin; +static cvar_t qtv_console_plugin_cvar = { + .name = "qtv_console_plugin", + .description = + "Plugin used for the console", + .default_value = "server", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &qtv_console_plugin }, +}; +static int qtv_port; +static cvar_t qtv_port_cvar = { + .name = "qtv_port", + .description = + "udp port to use", + .default_value = 0, + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &qtv_port }, +}; +static float qtv_mem_size; +static cvar_t qtv_mem_size_cvar = { + .name = "qtv_mem_size", + .description = + "Amount of memory (in MB) to allocate for the " + PACKAGE_NAME + " heap", + .default_value = "8", + .flags = CVAR_ROM, + .value = { .type = &cexpr_float, .value = &qtv_mem_size }, +}; redirect_t qtv_redirected; client_t *qtv_redirect_client; @@ -208,12 +243,9 @@ qtv_memory_init (void) int mem_size; void *mem_base; - qtv_mem_size = Cvar_Get ("qtv_mem_size", "8", CVAR_NONE, NULL, - "Amount of memory (in MB) to allocate for the " - PACKAGE_NAME " heap"); + Cvar_Register (&qtv_mem_size_cvar, 0, 0); - Cvar_SetFlags (qtv_mem_size, qtv_mem_size->flags | CVAR_ROM); - mem_size = (int) (qtv_mem_size->value * 1024 * 1024); + mem_size = (int) (qtv_mem_size * 1024 * 1024); mem_base = Sys_Alloc (mem_size); if (!mem_base) Sys_Error ("Can't allocate %d", mem_size); @@ -237,10 +269,10 @@ qtv_quit_f (void) static void qtv_net_init (void) { - qtv_port = Cvar_Get ("qtv_port", va (0, "%d", PORT_QTV), 0, 0, - "udp port to use"); - sv_timeout = Cvar_Get ("sv_timeout", "60", 0, 0, "server timeout"); - NET_Init (qtv_port->int_val); + qtv_port_cvar.default_value = nva ("%d", PORT_QTV); + Cvar_Register (&qtv_port_cvar, 0, 0); + Cvar_Register (&sv_timeout_cvar, 0, 0); + NET_Init (qtv_port); Connection_Init (); net_realtime = &realtime; Netchan_Init (); @@ -256,17 +288,16 @@ qtv_init (void) Sys_Init (); COM_ParseConfig (qtv_cbuf); - Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); + cmd_warncmd = 1; memhunk_t *hunk = qtv_memory_init (); QFS_Init (hunk, "qw"); PI_Init (); - qtv_console_plugin = Cvar_Get ("qtv_console_plugin", "server", - CVAR_ROM, 0, "Plugin used for the console"); + Cvar_Register (&qtv_console_plugin_cvar, 0, 0); PI_RegisterPlugins (server_plugin_list); - Con_Init (qtv_console_plugin->string); + Con_Init (qtv_console_plugin); if (con_module) con_module->data->console->cbuf = qtv_cbuf; Sys_SetStdPrintf (qtv_print); diff --git a/qtv/source/server.c b/qtv/source/server.c index 28f43ad6f..6e25723a8 100644 --- a/qtv/source/server.c +++ b/qtv/source/server.c @@ -449,7 +449,7 @@ sv_new_f (void) sv->name = strdup (name); sv->address = strdup (address); sv->adr = adr; - sv->qport = qport->int_val; + sv->qport = qport; sv->info = Info_ParseString ("", MAX_INFO_STRING, 0); Info_SetValueForStarKey (sv->info, "*ver", va (0, "%s QTV %s", QW_VERSION, PACKAGE_VERSION), @@ -554,7 +554,7 @@ Server_Frame (void) server_t *sv; for (sv = servers; sv; sv = sv->next) { - if (realtime - sv->netchan.last_received > sv_timeout->value) { + if (realtime - sv->netchan.last_received > sv_timeout) { qtv_printf ("Server %s timed out\n", sv->name); server_drop (sv); return; // chain has changed, avoid segfaulting diff --git a/qw/include/cl_demo.h b/qw/include/cl_demo.h index 190444785..b11f89583 100644 --- a/qw/include/cl_demo.h +++ b/qw/include/cl_demo.h @@ -40,7 +40,7 @@ void CL_Record (const char *argv1, int track); // track ignored void CL_Demo_Init (void); -extern struct cvar_s *demo_speed; -extern struct cvar_s *demo_gzip; +extern float demo_speed; +extern int demo_gzip; #endif diff --git a/qw/include/cl_ents.h b/qw/include/cl_ents.h index 93872edda..b6d5bc283 100644 --- a/qw/include/cl_ents.h +++ b/qw/include/cl_ents.h @@ -43,7 +43,7 @@ void CL_ParsePlayerinfo (void); void CL_Ents_Init (void); struct entity_s *CL_GetEntity (int num); -extern struct cvar_s *cl_deadbodyfilter; -extern struct cvar_s *cl_gibfilter; +extern int cl_deadbodyfilter; +extern int cl_gibfilter; #endif diff --git a/qw/include/cl_main.h b/qw/include/cl_main.h index 61d9d0481..9ed6667d9 100644 --- a/qw/include/cl_main.h +++ b/qw/include/cl_main.h @@ -52,13 +52,13 @@ void CL_BeginServerConnect(void); #define soundlist_name "soundlist %i %i" -extern struct cvar_s *cl_predict_players; -extern struct cvar_s *cl_solid_players; -extern struct cvar_s *cl_autoexec; -extern struct cvar_s *cl_cshift_bonus; -extern struct cvar_s *cl_cshift_contents; -extern struct cvar_s *cl_cshift_damage; -extern struct cvar_s *cl_cshift_powerup; +extern int cl_predict_players; +extern int cl_solid_players; +extern int cl_autoexec; +extern int cl_cshift_bonus; +extern int cl_cshift_contents; +extern int cl_cshift_damage; +extern int cl_cshift_powerup; extern struct gib_event_s *cl_player_health_e, *cl_chat_e; diff --git a/qw/include/client.h b/qw/include/client.h index 876bc6cca..7951338cb 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -257,28 +257,28 @@ typedef struct client_state_s { /* cvars */ -extern struct cvar_s *cl_netgraph; -extern struct cvar_s *cl_netgraph_height; -extern struct cvar_s *cl_netgraph_alpha; -extern struct cvar_s *cl_netgraph_box; +extern int cl_netgraph; +extern int cl_netgraph_height; +extern float cl_netgraph_alpha; +extern int cl_netgraph_box; -extern struct cvar_s *cl_draw_locs; -extern struct cvar_s *cl_shownet; +extern int cl_draw_locs; +extern int cl_shownet; -extern struct cvar_s *cl_name; +extern char *cl_name; -extern struct cvar_s *cl_model_crcs; +extern int cl_model_crcs; -extern struct cvar_s *rate; +extern float rate; -extern struct cvar_s *hud_ping; -extern struct cvar_s *hud_pl; +extern int hud_ping; +extern int hud_pl; -extern struct cvar_s *skin; +extern char *skin; -extern struct cvar_s *cl_fb_players; +extern float cl_fb_players; -extern struct cvar_s *hud_scoreboard_uid; +extern int hud_scoreboard_uid; extern client_state_t cl; @@ -294,7 +294,8 @@ extern int fps_count; extern struct cbuf_s *cl_cbuf; extern struct cbuf_s *cl_stbuf; -void Cvar_Info (struct cvar_s *var); +struct cvar_s; +void Cvar_Info (void *data, const struct cvar_s *cvar); extern struct view_s *cl_netgraph_view; void CL_NetGraph (struct view_s *view); diff --git a/qw/include/game.h b/qw/include/game.h index 003855f4e..474b11c02 100644 --- a/qw/include/game.h +++ b/qw/include/game.h @@ -33,7 +33,7 @@ #include "QF/qtypes.h" #include "QF/qdefs.h" -extern struct cvar_s *registered; +extern char *registered; void Game_Init (void); void Game_Init_Cvars (void); diff --git a/qw/include/host.h b/qw/include/host.h index ccf759a26..ab0a18770 100644 --- a/qw/include/host.h +++ b/qw/include/host.h @@ -38,8 +38,8 @@ #define MAX_NUM_ARGVS 50 -extern struct cvar_s *sys_ticrate; -extern struct cvar_s *password; +extern float sys_ticrate; +extern char *password; extern double host_frametime; // Tonik diff --git a/qw/include/server.h b/qw/include/server.h index dfdc48f72..9d00ee13e 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -426,21 +426,22 @@ typedef enum { //============================================================================ // FIXME: declare exported variables in their own relevant .h -extern struct cvar_s *sv_hide_version_info; -extern struct cvar_s *sv_highchars; +extern int sv_hide_version_info; +extern int sv_highchars; -extern struct cvar_s *sv_mintic, *sv_maxtic; -extern struct cvar_s *sv_maxspeed; +extern float sv_mintic; +extern float sv_maxtic; +extern float sv_maxspeed; -extern struct cvar_s *sv_timeout; +extern float sv_timeout; extern netadr_t master_adr[MAX_MASTERS]; // address of the master server -extern struct cvar_s *spawn; -extern struct cvar_s *teamplay; -extern struct cvar_s *deathmatch; -extern struct cvar_s *fraglimit; -extern struct cvar_s *timelimit; +extern char *spawn; +extern int teamplay; +extern int deathmatch; +extern char *fraglimit; +extern int timelimit; extern server_static_t svs; // persistant server info extern server_t sv; // local server @@ -544,6 +545,7 @@ void SV_FlushSignon (void); // void SV_ProgStartFrame (void); void SV_Physics (void); +void SV_Physics_Init_Cvars (void); void SV_CheckVelocity (struct edict_s *ent); void SV_AddGravity (struct edict_s *ent); void SV_FinishGravity (struct edict_s *ent, vec3_t move); @@ -630,38 +632,39 @@ void SV_WriteEntitiesToClient (delta_t *delta, sizebuf_t *msg); // sv_nchan.c // -void Cvar_Info (struct cvar_s *var); +struct cvar_s; +void Cvar_Info (void *data, const struct cvar_s *cvar); -extern struct cvar_s *sv_antilag; -extern struct cvar_s *sv_antilag_frac; -extern struct cvar_s *sv_timecheck_fuzz; -extern struct cvar_s *sv_timecheck_decay; -extern struct cvar_s *sv_maxrate; -extern struct cvar_s *sv_timestamps; -extern struct cvar_s *sv_timefmt; -extern struct cvar_s *sv_phs; -extern struct cvar_s *sv_maxvelocity; -extern struct cvar_s *sv_gravity; -extern struct cvar_s *sv_jump_any; -extern struct cvar_s *sv_aim; -extern struct cvar_s *sv_stopspeed; -extern struct cvar_s *sv_spectatormaxspeed; -extern struct cvar_s *sv_accelerate; -extern struct cvar_s *sv_airaccelerate; -extern struct cvar_s *sv_wateraccelerate; -extern struct cvar_s *sv_friction; -extern struct cvar_s *sv_waterfriction; -extern struct cvar_s *pr_double_remove; -extern struct cvar_s *allow_download; -extern struct cvar_s *allow_download_skins; -extern struct cvar_s *allow_download_models; -extern struct cvar_s *allow_download_sounds; -extern struct cvar_s *allow_download_maps; +extern int sv_antilag; +extern float sv_antilag_frac; +extern int sv_timecheck_fuzz; +extern int sv_timecheck_decay; +extern int sv_maxrate; +extern int sv_timestamps; +extern char *sv_timefmt; +extern int sv_phs; +extern float sv_maxvelocity; +extern float sv_gravity; +extern int sv_jump_any; +extern float sv_aim; +extern float sv_stopspeed; +extern float sv_spectatormaxspeed; +extern float sv_accelerate; +extern float sv_airaccelerate; +extern float sv_wateraccelerate; +extern float sv_friction; +extern float sv_waterfriction; +extern int pr_double_remove; +extern int allow_download; +extern int allow_download_skins; +extern int allow_download_models; +extern int allow_download_sounds; +extern int allow_download_maps; extern int fp_messages; extern int fp_persecond; extern int fp_secondsdead; -extern struct cvar_s *pausable; +extern int pausable; extern qboolean nouse; extern char fp_msg[255]; diff --git a/qw/include/sv_demo.h b/qw/include/sv_demo.h index 463d63a49..900362915 100644 --- a/qw/include/sv_demo.h +++ b/qw/include/sv_demo.h @@ -22,9 +22,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define __sv_demo_h extern struct recorder_s demo; -extern struct cvar_s *sv_demofps; -extern struct cvar_s *sv_demoPings; -extern struct cvar_s *sv_demoMaxSize; +extern float sv_demofps; +extern float sv_demoPings; +extern char *sv_demoMaxSize; void SV_Stop (int reason); void Demo_Init (void); diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index e41e76a5f..b730011d8 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -66,10 +66,44 @@ #include "QF/mathlib.h" #include "world.h" -cvar_t *cl_hightrack; // track high fragger -cvar_t *cl_chasecam; -cvar_t *cl_camera_maxpitch; -cvar_t *cl_camera_maxyaw; +int cl_hightrack; +static cvar_t cl_hightrack_cvar = { + .name = "cl_hightrack", + .description = + "view the player who has the most frags while you are in spectator " + "mode.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_hightrack }, +}; +int cl_chasecam; +static cvar_t cl_chasecam_cvar = { + .name = "cl_chasecam", + .description = + "get first person view of the person you are tracking in spectator " + "mode", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_chasecam }, +}; +float cl_camera_maxpitch; +static cvar_t cl_camera_maxpitch_cvar = { + .name = "cl_camera_maxpitch", + .description = + "highest camera pitch in spectator mode", + .default_value = "10", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_camera_maxpitch }, +}; +float cl_camera_maxyaw; +static cvar_t cl_camera_maxyaw_cvar = { + .name = "cl_camera_maxyaw", + .description = + "highest camera yaw in spectator mode", + .default_value = "30", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_camera_maxyaw }, +}; static vec3_t desired_position; // where the camera wants to be static qboolean locked = false; @@ -116,13 +150,13 @@ vectoangles (vec3_t vec, vec3_t ang) qboolean Cam_DrawViewModel (void) { - if (cl.viewstate.chase && chase_active->int_val) + if (cl.viewstate.chase && chase_active) return false; if (!cl.spectator) return true; - if (autocam && locked && cl_chasecam->int_val) + if (autocam && locked && cl_chasecam) return true; return false; } @@ -132,16 +166,16 @@ qboolean Cam_DrawPlayer (int playernum) { if (playernum == cl.playernum) { // client player - if (cl.viewstate.chase == 0 || chase_active->int_val == 0) + if (cl.viewstate.chase == 0 || chase_active == 0) return false; if (!cl.spectator) return true; } else { - if (!cl_chasecam->int_val) + if (!cl_chasecam) return true; if (cl.spectator && autocam && locked && spec_track == playernum) return false; - if (cl.viewstate.chase == 0 || chase_active->int_val == 0) + if (cl.viewstate.chase == 0 || chase_active == 0) return true; } return false; @@ -384,7 +418,7 @@ Cam_Track (usercmd_t *cmd) if (!cl.spectator) return; - if (cl_hightrack->int_val && !locked) + if (cl_hightrack && !locked) Cam_CheckHighTarget (); if (!autocam || cls.state != ca_active) @@ -394,7 +428,7 @@ Cam_Track (usercmd_t *cmd) && (!cl.players[spec_track].name->value[0] || cl.players[spec_track].spectator)) { locked = false; - if (cl_hightrack->int_val) + if (cl_hightrack) Cam_CheckHighTarget (); else Cam_Unlock (); @@ -435,7 +469,7 @@ Cam_Track (usercmd_t *cmd) if (!locked || !autocam) return; - if (cl_chasecam->int_val) { + if (cl_chasecam) { cmd->forwardmove = cmd->sidemove = cmd->upmove = 0; VectorCopy (player->viewangles, cl.viewstate.player_angles); @@ -530,10 +564,10 @@ Cam_SetView (void) cam_viewangles[PITCH] = adjustang (cam_viewangles[PITCH], vec2[PITCH], - cl_camera_maxpitch->value); + cl_camera_maxpitch); cam_viewangles[YAW] = adjustang (cam_viewangles[YAW], vec2[YAW], - cl_camera_maxyaw->value); + cl_camera_maxyaw); } VectorCopy (cam_viewangles, cl.viewstate.player_angles); VectorCopy (cl.viewstate.player_angles, cl.simangles); @@ -570,10 +604,10 @@ Cam_FinishMove (usercmd_t *cmd) cam_viewangles[PITCH] = adjustang (cam_viewangles[PITCH], vec2[PITCH], - cl_camera_maxpitch->value); + cl_camera_maxpitch); cam_viewangles[YAW] = adjustang (cam_viewangles[YAW], vec2[YAW], - cl_camera_maxyaw->value); + cl_camera_maxyaw); } VectorCopy (cam_viewangles, cl.viewstate.player_angles); } @@ -597,7 +631,7 @@ Cam_FinishMove (usercmd_t *cmd) return; } - if (autocam && cl_hightrack->int_val) { + if (autocam && cl_hightrack) { Cam_CheckHighTarget (); return; } @@ -651,14 +685,8 @@ Cam_Reset (void) void CL_Cam_Init_Cvars (void) { - cl_camera_maxpitch = Cvar_Get ("cl_camera_maxpitch", "10", CVAR_NONE, NULL, - "highest camera pitch in spectator mode"); - cl_camera_maxyaw = Cvar_Get ("cl_camera_maxyaw", "30", CVAR_NONE, NULL, - "highest camera yaw in spectator mode"); - cl_chasecam = Cvar_Get ("cl_chasecam", "0", CVAR_NONE, NULL, "get first " - "person view of the person you are tracking in " - "spectator mode"); - cl_hightrack = Cvar_Get ("cl_hightrack", "0", CVAR_NONE, NULL, "view the " - "player who has the most frags while you are in " - "spectator mode."); + Cvar_Register (&cl_camera_maxpitch_cvar, 0, 0); + Cvar_Register (&cl_camera_maxyaw_cvar, 0, 0); + Cvar_Register (&cl_chasecam_cvar, 0, 0); + Cvar_Register (&cl_hightrack_cvar, 0, 0); } diff --git a/qw/source/cl_cvar.c b/qw/source/cl_cvar.c index f9e116ae9..78d6290ec 100644 --- a/qw/source/cl_cvar.c +++ b/qw/source/cl_cvar.c @@ -44,17 +44,18 @@ #include "qw/include/client.h" void -Cvar_Info (cvar_t *var) +Cvar_Info (void *data, const cvar_t *cvar) { - if (var->flags & CVAR_USERINFO) { - Info_SetValueForKey (cls.userinfo, var->name, var->string, - ((!strequal(var->name, "name")) - |(strequal(var->name, "team") << 1))); + if (cvar->flags & CVAR_USERINFO) { + const char *cvar_str = Cvar_VarString (cvar); + Info_SetValueForKey (cls.userinfo, cvar->name, cvar_str, + ((!strequal(cvar->name, "name")) + |(strequal(cvar->name, "team") << 1))); if (cls.state >= ca_connected && !cls.demoplayback) { MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va (0, "setinfo \"%s\" \"%s\"\n", var->name, - var->string)); + va (0, "setinfo \"%s\" \"%s\"\n", cvar->name, + cvar_str)); } } } diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 91fd7ced3..c7ede77e3 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -91,10 +91,44 @@ static void CL_TimeFrames_DumpLog (void); static void CL_TimeFrames_AddTimestamp (void); static void CL_TimeFrames_Reset (void); -cvar_t *demo_gzip; -cvar_t *demo_speed; -cvar_t *demo_quit; -cvar_t *demo_timeframes; +int demo_gzip; +static cvar_t demo_gzip_cvar = { + .name = "demo_gzip", + .description = + "Compress demos using gzip. 0 = none, 1 = least compression, 9 = most " + "compression. Compressed demos (1-9) will have .gz appended to the " + "name", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &demo_gzip }, +}; +float demo_speed; +static cvar_t demo_speed_cvar = { + .name = "demo_speed", + .description = + "adjust demo playback speed. 1.0 = normal, < 1 slow-mo, > 1 timelapse", + .default_value = "1.0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &demo_speed }, +}; +int demo_quit; +static cvar_t demo_quit_cvar = { + .name = "demo_quit", + .description = + "automaticly quit after a timedemo has finished", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &demo_quit }, +}; +int demo_timeframes; +static cvar_t demo_timeframes_cvar = { + .name = "demo_timeframes", + .description = + "write timestamps for every frame", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &demo_timeframes }, +}; #define MAX_DEMMSG (MAX_MSGLEN + 8) //+8 for header @@ -422,7 +456,7 @@ CL_GetMessage (void) if (!CL_GetPacket ()) return 0; - if (net_packetlog->int_val) + if (net_packetlog) Log_Incoming_Packet (net_message->message->data, net_message->message->cursize, 1); @@ -879,9 +913,9 @@ CL_Record (const char *argv1, int track) // open the demo file #ifdef HAVE_ZLIB - if (demo_gzip->int_val) { + if (demo_gzip) { QFS_DefaultExtension (name, ".qwd.gz"); - cls.demofile = QFS_WOpen (name->str, demo_gzip->int_val); + cls.demofile = QFS_WOpen (name->str, demo_gzip); } else #endif { @@ -1091,7 +1125,7 @@ CL_StartTimeDemo (void) cls.td_lastframe = -1; // get a new message this frame CL_TimeFrames_Reset (); - if (demo_timeframes->int_val) + if (demo_timeframes) demo_timeframes_isactive = 1; } @@ -1150,7 +1184,7 @@ CL_FinishTimeDemo (void) Sys_Printf (" min/max fps: %.3f/%.3f\n", min, max); Sys_Printf ("std deviation: %.3f fps\n", sqrt (variance)); } - if (demo_quit->int_val) + if (demo_quit) Cbuf_InsertText (cl_cbuf, "quit\n"); } } @@ -1195,17 +1229,10 @@ CL_Demo_Init (void) demo_timeframes_index = 0; demo_timeframes_array = NULL; - demo_gzip = Cvar_Get ("demo_gzip", "0", CVAR_ARCHIVE, NULL, - "Compress demos using gzip. 0 = none, 1 = least " - "compression, 9 = most compression. Compressed " - " demos (1-9) will have .gz appended to the name"); - demo_speed = Cvar_Get ("demo_speed", "1.0", CVAR_NONE, NULL, - "adjust demo playback speed. 1.0 = normal, " - "< 1 slow-mo, > 1 timelapse"); - demo_quit = Cvar_Get ("demo_quit", "0", CVAR_NONE, NULL, - "automaticly quit after a timedemo has finished"); - demo_timeframes = Cvar_Get ("demo_timeframes", "0", CVAR_NONE, NULL, - "write timestamps for every frame"); + Cvar_Register (&demo_gzip_cvar, 0, 0); + Cvar_Register (&demo_speed_cvar, 0, 0); + Cvar_Register (&demo_quit_cvar, 0, 0); + Cvar_Register (&demo_timeframes_cvar, 0, 0); Cmd_AddCommand ("record", CL_Record_f, "Record a demo, if no filename " "argument is given\n" "the demo will be called Year-Month-Day-Hour-Minute-" diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 80ec0112e..26486ae41 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -648,7 +648,7 @@ CL_SetSolidPlayers (int playernum) physent_t *pent; struct predicted_player *pplayer; - if (!cl_solid_players->int_val) + if (!cl_solid_players) return; pent = pmove.physents + pmove.numphysent; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 5e9bb0069..a4955c409 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -176,8 +176,8 @@ CL_LinkPacketEntities (void) // if set to invisible, skip if (!new->modelindex - || (cl_deadbodyfilter->int_val && is_dead_body (new)) - || (cl_gibfilter->int_val && is_gib (new))) { + || (cl_deadbodyfilter && is_dead_body (new)) + || (cl_gibfilter && is_gib (new))) { if (ent->visibility.efrag) { R_RemoveEfrags (ent); } @@ -219,7 +219,7 @@ CL_LinkPacketEntities (void) renderer->min_light = 0; renderer->fullbright = 0; if (new->modelindex == cl_playerindex) { - renderer->min_light = min (cl.fbskins, cl_fb_players->value); + renderer->min_light = min (cl.fbskins, cl_fb_players); if (renderer->min_light >= 1.0) { renderer->fullbright = 1; } @@ -230,7 +230,7 @@ CL_LinkPacketEntities (void) animation->pose1 = animation->pose2 = -1; CL_TransformEntity (ent, new->scale / 16, new->angles, new->origin); - if (i != cl.viewentity || chase_active->int_val) { + if (i != cl.viewentity || chase_active) { if (ent->visibility.efrag) { R_RemoveEfrags (ent); } @@ -260,7 +260,7 @@ CL_LinkPacketEntities (void) VectorMultAdd (old->angles, f, d, angles); CL_TransformEntity (ent, new->scale / 16.0, angles, origin); } - if (i != cl.viewentity || chase_active->int_val) { + if (i != cl.viewentity || chase_active) { if (ent->visibility.efrag) { vec4f_t org = Transform_GetWorldPosition (ent->transform); @@ -439,14 +439,14 @@ CL_LinkPlayers (void) continue; // Hack hack hack - if (cl_deadbodyfilter->int_val + if (cl_deadbodyfilter && state->pls.es.modelindex == cl_playerindex && is_dead_body (&state->pls.es)) continue; // predict only half the move to minimize overruns msec = 500 * (playertime - state->state_time); - if (msec <= 0 || (!cl_predict_players->int_val) || cls.demoplayback2) { + if (msec <= 0 || (!cl_predict_players) || cls.demoplayback2) { Sys_Printf("a\n"); exact.pls.es.origin = state->pls.es.origin; } else { // predict players movement @@ -488,7 +488,7 @@ CL_LinkPlayers (void) // use custom skin ent->renderer.skin = player->skin; - ent->renderer.min_light = min (cl.fbskins, cl_fb_players->value); + ent->renderer.min_light = min (cl.fbskins, cl_fb_players); if (ent->renderer.min_light >= 1.0) { ent->renderer.fullbright = 1; @@ -540,7 +540,7 @@ CL_EmitEntities (void) CL_LinkPlayers (); CL_LinkPacketEntities (); CL_UpdateTEnts (cl.time, &tentCtx); - if (cl_draw_locs->int_val) { + if (cl_draw_locs) { locs_draw (cl.time, cl.viewstate.player_origin); } } diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index 1a04d1579..d0c8fef58 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -63,9 +63,36 @@ #include "qw/include/client.h" #include "qw/include/host.h" -cvar_t *cl_nodelta; -cvar_t *cl_maxnetfps; -cvar_t *cl_spamimpulse; +int cl_nodelta; +static cvar_t cl_nodelta_cvar = { + .name = "cl_nodelta", + .description = + "Disable player delta compression. Set to 1 if you have a poor ISP and" + " get many U_REMOVE warnings.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_nodelta }, +}; +int cl_maxnetfps; +static cvar_t cl_maxnetfps_cvar = { + .name = "cl_maxnetfps", + .description = + "Controls number of command packets sent per second. Default 0 is " + "unlimited.", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_maxnetfps }, +}; +int cl_spamimpulse; +static cvar_t cl_spamimpulse_cvar = { + .name = "cl_spamimpulse", + .description = + "Controls number of duplicate packets sent if an impulse is being " + "sent. Default (id behavior) is 3.", + .default_value = "3", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_spamimpulse }, +}; int in_impulse; @@ -166,8 +193,8 @@ pps_check (int dontdrop) if (pps_balance > 0.0 || dropcount >= 2 || dontdrop) { float pps; - if (!(pps = cl_maxnetfps->int_val)) - pps = rate->value / 80.0; + if (!(pps = cl_maxnetfps)) + pps = rate / 80.0; pps = bound (1, pps, 72); @@ -250,21 +277,21 @@ CL_SendCmd (void) frame = (cls.netchan.outgoing_sequence - 2) & UPDATE_MASK; cmd = &cl.frames[frame].cmd; - if (cl_spamimpulse->int_val >= 2) + if (cl_spamimpulse >= 2) dontdrop = dontdrop || cmd->impulse; MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd); oldcmd = cmd; frame = (cls.netchan.outgoing_sequence - 1) & UPDATE_MASK; cmd = &cl.frames[frame].cmd; - if (cl_spamimpulse->int_val >= 3) + if (cl_spamimpulse >= 3) dontdrop = dontdrop || cmd->impulse; MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd); oldcmd = cmd; frame = (cls.netchan.outgoing_sequence) & UPDATE_MASK; cmd = &cl.frames[frame].cmd; - if (cl_spamimpulse->int_val >= 1) + if (cl_spamimpulse >= 1) dontdrop = dontdrop || cmd->impulse; MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd); @@ -277,7 +304,7 @@ CL_SendCmd (void) if (cls.netchan.outgoing_sequence - cl.validsequence >= UPDATE_BACKUP - 1) cl.validsequence = 0; - if (cl.validsequence && !cl_nodelta->int_val && cls.state == ca_active + if (cl.validsequence && !cl_nodelta && cls.state == ca_active && !cls.demorecording) { cl.frames[frame].delta_sequence = cl.validsequence; MSG_WriteByte (&buf, clc_delta); @@ -306,14 +333,7 @@ void CL_Init_Input_Cvars (void) { CL_Input_Init_Cvars (); - cl_nodelta = Cvar_Get ("cl_nodelta", "0", CVAR_NONE, NULL, - "Disable player delta compression. Set to 1 if you " - "have a poor ISP and get many U_REMOVE warnings."); - cl_maxnetfps = Cvar_Get ("cl_maxnetfps", "0", CVAR_ARCHIVE, NULL, - "Controls number of command packets sent per " - "second. Default 0 is unlimited."); - cl_spamimpulse = Cvar_Get ("cl_spamimpulse", "3", CVAR_NONE, NULL, - "Controls number of duplicate packets sent if " - "an impulse is being sent. Default (id " - "behavior) is 3."); + Cvar_Register (&cl_nodelta_cvar, 0, 0); + Cvar_Register (&cl_maxnetfps_cvar, 0, 0); + Cvar_Register (&cl_spamimpulse_cvar, 0, 0); } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 7b4179907..73bf69394 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -134,54 +134,285 @@ qboolean noclip_anglehack; // remnant from old quake cbuf_t *cl_cbuf; cbuf_t *cl_stbuf; -cvar_t *cl_mem_size; +float cl_mem_size; +static cvar_t cl_mem_size_cvar = { + .name = "cl_mem_size", + .description = + "Amount of memory (in MB) to allocate for the " + PACKAGE_NAME + " heap", + .default_value = "32", + .flags = CVAR_ROM, + .value = { .type = &cexpr_float, .value = &cl_mem_size }, +}; -cvar_t *rcon_password; +char *rcon_password; +static cvar_t rcon_password_cvar = { + .name = "rcon_password", + .description = + "Set the password for rcon 'root' commands", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &rcon_password }, +}; -cvar_t *rcon_address; +char *rcon_address; +static cvar_t rcon_address_cvar = { + .name = "rcon_address", + .description = + "server IP address when client not connected - for sending rcon " + "commands", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &rcon_address }, +}; -cvar_t *cl_writecfg; -cvar_t *cl_allow_cmd_pkt; -cvar_t *cl_cmd_pkt_adr; -cvar_t *cl_paranoid; +int cl_writecfg; +static cvar_t cl_writecfg_cvar = { + .name = "cl_writecfg", + .description = + "write config files?", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_writecfg }, +}; +int cl_allow_cmd_pkt; +static cvar_t cl_allow_cmd_pkt_cvar = { + .name = "cl_allow_cmd_pkt", + .description = + "enables packets from the likes of gamespy", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_allow_cmd_pkt }, +}; +char *cl_cmd_pkt_adr; +static cvar_t cl_cmd_pkt_adr_cvar = { + .name = "cl_cmd_pkt_adr", + .description = + "allowed address for non-local command packet", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &cl_cmd_pkt_adr }, +}; +int cl_paranoid; +static cvar_t cl_paranoid_cvar = { + .name = "cl_paranoid", + .description = + "print source address of connectionless packets even when coming from " + "the server being connected to.", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_paranoid }, +}; -cvar_t *cl_timeout; +float cl_timeout; +static cvar_t cl_timeout_cvar = { + .name = "cl_timeout", + .description = + "server connection timeout (since last packet received)", + .default_value = "60", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_timeout }, +}; -cvar_t *cl_draw_locs; -cvar_t *cl_shownet; -cvar_t *cl_autoexec; -cvar_t *cl_quakerc; -cvar_t *cl_maxfps; -cvar_t *cl_usleep; +int cl_draw_locs; +static cvar_t cl_draw_locs_cvar = { + .name = "cl_draw_locs", + .description = + "Draw location markers.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_draw_locs }, +}; +int cl_shownet; +static cvar_t cl_shownet_cvar = { + .name = "cl_shownet", + .description = + "show network packets. 0=off, 1=basic, 2=verbose", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_shownet }, +}; +int cl_autoexec; +static cvar_t cl_autoexec_cvar = { + .name = "cl_autoexec", + .description = + "exec autoexec.cfg on gamedir change", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &cl_autoexec }, +}; +int cl_quakerc; +static cvar_t cl_quakerc_cvar = { + .name = "cl_quakerc", + .description = + "exec quake.rc on startup", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_quakerc }, +}; +float cl_maxfps; +static cvar_t cl_maxfps_cvar = { + .name = "cl_maxfps", + .description = + "maximum frames rendered in one second. 0 == 72", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_maxfps }, +}; +int cl_usleep; +static cvar_t cl_usleep_cvar = { + .name = "cl_usleep", + .description = + "Turn this on to save cpu when fps limited. May affect frame rate " + "adversely depending on local machine/os conditions", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_usleep }, +}; -cvar_t *cl_model_crcs; +int cl_model_crcs; +static cvar_t cl_model_crcs_cvar = { + .name = "cl_model_crcs", + .description = + "Controls setting of emodel and pmodel info vars. Required by some " + "servers, but clearing this can make the difference between connecting" + " and not connecting on some others.", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_model_crcs }, +}; -cvar_t *cl_predict_players; -cvar_t *cl_solid_players; +int cl_predict_players; +static cvar_t cl_predict_players_cvar = { + .name = "cl_predict_players", + .description = + "If this is 0, no player prediction is done", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_predict_players }, +}; +int cl_solid_players; +static cvar_t cl_solid_players_cvar = { + .name = "cl_solid_players", + .description = + "Are players solid? If off, you can walk through them with difficulty", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_solid_players }, +}; -cvar_t *localid; +char *localid; +static cvar_t localid_cvar = { + .name = "localid", + .description = + "Used by gamespy+others to authenticate when sending commands to the " + "client", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &localid }, +}; -cvar_t *cl_port; -cvar_t *cl_autorecord; +int cl_port; +static cvar_t cl_port_cvar = { + .name = "cl_port", + .description = + "UDP Port for client to use.", + .default_value = PORT_CLIENT, + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_port }, +}; +int cl_autorecord; +static cvar_t cl_autorecord_cvar = { + .name = "cl_autorecord", + .description = + "Turn this on, if you want to record every game", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_autorecord }, +}; -cvar_t *cl_fb_players; +float cl_fb_players; +static cvar_t cl_fb_players_cvar = { + .name = "cl_fb_players", + .description = + "fullbrightness of player models. server must allow (via fbskins " + "serverinfo).", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_fb_players }, +}; static qboolean allowremotecmd = true; /* info mirrors */ -cvar_t *password; -cvar_t *spectator; -cvar_t *cl_name; -cvar_t *team; -cvar_t *rate; -cvar_t *noaim; -cvar_t *msg; +char *password; +static cvar_t password_cvar = { + .name = "password", + .description = + "Set the server password for players", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &password }, +}; +char *spectator; +static cvar_t spectator_cvar = { + .name = "spectator", + .description = + "Set to 1 before connecting to become a spectator", + .default_value = "", + .flags = CVAR_USERINFO, + .value = { .type = 0/* not used */, .value = &spectator }, +}; +char *cl_name; +static cvar_t cl_name_cvar = { + .name = "_cl_name", + .description = + "Player name", + .default_value = "player", + .flags = CVAR_ARCHIVE, + .value = { .type = 0, .value = &cl_name }, +}; +float team; +static cvar_t team_cvar = { + .name = "team", + .description = + "Team player is on.", + .default_value = "", + .flags = CVAR_ARCHIVE | CVAR_USERINFO, + .value = { .type = &cexpr_float, .value = &team }, +}; +float rate; +static cvar_t rate_cvar = { + .name = "rate", + .description = + "Amount of bytes per second server will send/download to you", + .default_value = "10000", + .flags = CVAR_ARCHIVE | CVAR_USERINFO, + .value = { .type = &cexpr_float, .value = &rate }, +}; +char *noaim; +static cvar_t noaim_cvar = { + .name = "noaim", + .description = + "Auto aim off switch. Set to 1 to turn off.", + .default_value = "0", + .flags = CVAR_ARCHIVE | CVAR_USERINFO, + .value = { .type = 0/* not used */, .value = &noaim }, +}; +char *msg; +static cvar_t msg_cvar = { + .name = "msg", + .description = + "Determines the type of messages reported 0 is maximum, 4 is none", + .default_value = "1", + .flags = CVAR_ARCHIVE | CVAR_USERINFO, + .value = { .type = 0/* not used */, .value = &msg }, +}; /* GIB events */ gib_event_t *cl_player_health_e, *cl_chat_e; -static int cl_usleep_cache; - client_static_t cls; client_state_t cl; @@ -204,11 +435,51 @@ double oldcon_realtime; size_t host_hunklevel; -cvar_t *host_speeds; -cvar_t *hud_fps; -cvar_t *hud_ping; -cvar_t *hud_pl; -cvar_t *hud_time; +int host_speeds; +static cvar_t host_speeds_cvar = { + .name = "host_speeds", + .description = + "set for running times", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &host_speeds }, +}; +int hud_fps; +static cvar_t hud_fps_cvar = { + .name = "hud_fps", + .description = + "display realtime frames per second", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_fps }, +}; +int hud_ping; +static cvar_t hud_ping_cvar = { + .name = "hud_ping", + .description = + "display current ping to server", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_ping }, +}; +int hud_pl; +static cvar_t hud_pl_cvar = { + .name = "hud_pl", + .description = + "display current packet loss to server", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_pl }, +}; +int hud_time; +static cvar_t hud_time_cvar = { + .name = "hud_time", + .description = + "display the current time", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_time }, +}; int fps_count; @@ -272,7 +543,7 @@ CL_SendConnectPacket (void) connect_time = realtime + t2 - t1; // for retransmit requests - cls.qport = qport->int_val; + cls.qport = qport; data = dstring_new (); dsprintf (data, "%c%c%c%cconnect %i %i %i \"%s\"\n", @@ -360,18 +631,18 @@ CL_Rcon_f (void) if (!message) message = dstring_new (); - dsprintf (message, "\377\377\377\377rcon %s %s", rcon_password->string, + dsprintf (message, "\377\377\377\377rcon %s %s", rcon_password, Cmd_Args (1)); if (cls.state >= ca_connected) to = cls.netchan.remote_address; else { - if (!rcon_address->string[0]) { + if (!rcon_address[0]) { Sys_Printf ("You must either be connected, or set the " "'rcon_address' cvar to issue rcon commands\n"); return; } - NET_StringToAdr (rcon_address->string, &to); + NET_StringToAdr (rcon_address, &to); if (to.port == 0) to.port = BigShort (27500); } @@ -639,7 +910,7 @@ CL_FullServerinfo_f (void) } if ((p = Info_ValueForKey (cl.serverinfo, "teamplay")) && *p) { cl.teamplay = atoi (p); - Sbar_DMO_Init_f (hud_scoreboard_uid); // HUD setup, cl.teamplay changed + Sbar_DMO_Init_f (0, 0); // HUD setup, cl.teamplay changed } if ((p = Info_ValueForKey (cl.serverinfo, "watervis")) && *p) { cl.watervis = atoi (p); @@ -867,7 +1138,7 @@ CL_ConnectionlessPacket (void) if (net_message->badread) return; if (!cls.demoplayback - && (cl_paranoid->int_val + && (cl_paranoid || !NET_CompareAdr (net_from, cls.server_addr))) Sys_Printf ("%s: ", NET_AdrToString (net_from)); if (c == S2C_CONNECTION) { @@ -893,16 +1164,16 @@ CL_ConnectionlessPacket (void) Sys_Printf ("client command\n"); - if (!cl_allow_cmd_pkt->int_val + if (!cl_allow_cmd_pkt || (!NET_CompareBaseAdr (net_from, net_local_adr) && !NET_CompareBaseAdr (net_from, net_loopback_adr) - && (!cl_cmd_pkt_adr->string[0] + && (!cl_cmd_pkt_adr[0] || !NET_CompareBaseAdr (net_from, cl_cmd_packet_address)))) { Sys_Printf ("Command packet from remote host. Ignored.\n"); return; } - if (cl_cmd_pkt_adr->string[0] + if (cl_cmd_pkt_adr[0] && NET_CompareBaseAdr (net_from, cl_cmd_packet_address)) allowremotecmd = false; // force password checking s = MSG_ReadString (net_message); @@ -918,10 +1189,10 @@ CL_ConnectionlessPacket (void) while (len && isspace ((byte) s[len - 1])) len--; - if (!allowremotecmd && (!*localid->string || - (int) strlen (localid->string) > len || - strncmp (localid->string, s, len))) { - if (!*localid->string) { + if (!allowremotecmd && (!*localid || + (int) strlen (localid) > len || + strncmp (localid, s, len))) { + if (!*localid) { Sys_Printf ("===========================\n"); Sys_Printf ("Command packet received from local host, but no " "localid has been set. You may need to upgrade " @@ -934,9 +1205,9 @@ CL_ConnectionlessPacket (void) ("Invalid localid on command packet received from local host. " "\n|%s| != |%s|\n" "You may need to reload your server browser and %s.\n", s, - localid->string, PACKAGE_NAME); + localid, PACKAGE_NAME); Sys_Printf ("===========================\n"); - Cvar_Set (localid, ""); + Cvar_Set ("localid", ""); return; } @@ -953,7 +1224,7 @@ CL_ConnectionlessPacket (void) Sys_Printf ("status response\n"); return; } else if (!cls.demoplayback - && (cl_paranoid->int_val + && (cl_paranoid || !NET_CompareAdr (net_from, cls.server_addr))) { Sys_Printf ("print\n"); } @@ -1028,7 +1299,7 @@ CL_ReadPackets (void) continue; } - if (cls.demoplayback && net_packetlog->int_val) + if (cls.demoplayback && net_packetlog) Log_Incoming_Packet (net_message->message->data, net_message->message->cursize, 0); @@ -1068,7 +1339,7 @@ CL_ReadPackets (void) // check timeout if (!cls.demoplayback && cls.state >= ca_connected - && realtime - cls.netchan.last_received > cl_timeout->value) { + && realtime - cls.netchan.last_received > cl_timeout) { Sys_Printf ("\nServer connection timed out.\n"); CL_Disconnect (); return; @@ -1160,7 +1431,7 @@ CL_SetState (cactive_t state) CL_ClearState (); // Auto demo recorder stops here - if (cl_autorecord->int_val && cls.demorecording) + if (cl_autorecord && cls.demorecording) CL_StopRecording (); r_funcs->R_ClearState (); @@ -1170,7 +1441,7 @@ CL_SetState (cactive_t state) IN_ClearStates (); // Auto demo recorder starts here - if (cl_autorecord->int_val && !cls.demoplayback + if (cl_autorecord && !cls.demoplayback && !cls.demorecording) CL_Record (0, -1); } @@ -1304,33 +1575,27 @@ CL_Init (void) } static void -cl_usleep_f (cvar_t *var) +cl_cmd_pkt_adr_f (void *data, const cvar_t *cvar) { - cl_usleep_cache = var->int_val; -} - -static void -cl_cmd_pkt_adr_f (cvar_t *var) -{ - if (var->string[0]) - NET_StringToAdr (var->string, &cl_cmd_packet_address); + if (cl_cmd_pkt_adr[0]) + NET_StringToAdr (cl_cmd_pkt_adr, &cl_cmd_packet_address); else memset (&cl_cmd_packet_address, 0, sizeof (cl_cmd_packet_address)); } static void -cl_pitchspeed_f (cvar_t *var) +cl_pitchspeed_f (void *data, const cvar_t *var) { - if ((cl.fpd & FPD_LIMIT_PITCH) && var->value > FPD_MAXPITCH) { - var->value = FPD_MAXPITCH; + if ((cl.fpd & FPD_LIMIT_PITCH) && cl_pitchspeed > FPD_MAXPITCH) { + cl_pitchspeed = FPD_MAXPITCH; } } static void -cl_yawspeed_f (cvar_t *var) +cl_yawspeed_f (void *data, const cvar_t *var) { - if ((cl.fpd & FPD_LIMIT_YAW) && var->value > FPD_MAXYAW) { - var->value = FPD_MAXYAW; + if ((cl.fpd & FPD_LIMIT_YAW) && cl_yawspeed > FPD_MAXYAW) { + cl_yawspeed = FPD_MAXYAW; } } @@ -1353,91 +1618,48 @@ CL_Init_Cvars (void) Chase_Init_Cvars (); V_Init_Cvars (); - cl_pitchspeed->callback = cl_pitchspeed_f; - cl_yawspeed->callback = cl_yawspeed_f; + cvar_t *var; + var = Cvar_FindVar ("cl_pitchspeed"); + Cvar_AddListener (var, cl_pitchspeed_f, 0); + var = Cvar_FindVar ("cl_yawspeed"); + Cvar_AddListener (var, cl_yawspeed_f, 0); cls.userinfo = Info_ParseString ("", MAX_INFO_STRING, 0); - cl_model_crcs = Cvar_Get ("cl_model_crcs", "1", CVAR_ARCHIVE, NULL, - "Controls setting of emodel and pmodel info " - "vars. Required by some servers, but clearing " - "this can make the difference between " - "connecting and not connecting on some others."); - cl_allow_cmd_pkt = Cvar_Get ("cl_allow_cmd_pkt", "1", CVAR_NONE, NULL, - "enables packets from the likes of gamespy"); - cl_cmd_pkt_adr = Cvar_Get ("cl_cmd_pkt_adr", "", CVAR_NONE, - cl_cmd_pkt_adr_f, - "allowed address for non-local command packet"); - cl_paranoid = Cvar_Get ("cl_paranoid", "1", CVAR_NONE, NULL, - "print source address of connectionless packets" - " even when coming from the server being connected" - " to."); - cl_autoexec = Cvar_Get ("cl_autoexec", "0", CVAR_ROM, NULL, - "exec autoexec.cfg on gamedir change"); - cl_quakerc = Cvar_Get ("cl_quakerc", "1", CVAR_NONE, NULL, - "exec quake.rc on startup"); - cl_fb_players = Cvar_Get ("cl_fb_players", "0", CVAR_ARCHIVE, NULL, "fullbrightness of player models. " - "server must allow (via fbskins serverinfo)."); - cl_writecfg = Cvar_Get ("cl_writecfg", "1", CVAR_NONE, NULL, - "write config files?"); - cl_draw_locs = Cvar_Get ("cl_draw_locs", "0", CVAR_NONE, NULL, - "Draw location markers."); - cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_NONE, NULL, - "show network packets. 0=off, 1=basic, 2=verbose"); - cl_maxfps = Cvar_Get ("cl_maxfps", "0", CVAR_ARCHIVE, NULL, - "maximum frames rendered in one second. 0 == 72"); - cl_timeout = Cvar_Get ("cl_timeout", "60", CVAR_ARCHIVE, NULL, "server " - "connection timeout (since last packet received)"); - host_speeds = Cvar_Get ("host_speeds", "0", CVAR_NONE, NULL, - "display host processing times"); - rcon_password = Cvar_Get ("rcon_password", "", CVAR_NONE, NULL, - "remote control password"); - rcon_address = Cvar_Get ("rcon_address", "", CVAR_NONE, NULL, "server IP " - "address when client not connected - for " - "sending rcon commands"); - hud_fps = Cvar_Get ("hud_fps", "0", CVAR_ARCHIVE, NULL, - "display realtime frames per second"); - Cvar_MakeAlias ("show_fps", hud_fps); - hud_ping = Cvar_Get ("hud_ping", "0", CVAR_ARCHIVE, NULL, - "display current ping to server"); - hud_pl = Cvar_Get ("hud_pl", "0", CVAR_ARCHIVE, NULL, - "display current packet loss to server"); - hud_time = Cvar_Get ("hud_time", "0", CVAR_ARCHIVE, NULL, - "Display the current time, 1 24hr, 2 AM/PM"); - cl_predict_players = Cvar_Get ("cl_predict_players", "1", CVAR_NONE, NULL, - "If this is 0, no player prediction is " - "done"); - cl_solid_players = Cvar_Get ("cl_solid_players", "1", CVAR_NONE, NULL, - "Are players solid? If off, you can walk " - "through them with difficulty"); - localid = Cvar_Get ("localid", "", CVAR_NONE, NULL, "Used by " - "gamespy+others to authenticate when sending " - "commands to the client"); + Cvar_Register (&cl_model_crcs_cvar, 0, 0); + Cvar_Register (&cl_allow_cmd_pkt_cvar, 0, 0); + Cvar_Register (&cl_cmd_pkt_adr_cvar, cl_cmd_pkt_adr_f, 0); + Cvar_Register (&cl_paranoid_cvar, 0, 0); + Cvar_Register (&cl_autoexec_cvar, 0, 0); + Cvar_Register (&cl_quakerc_cvar, 0, 0); + Cvar_Register (&cl_fb_players_cvar, 0, 0); + Cvar_Register (&cl_writecfg_cvar, 0, 0); + Cvar_Register (&cl_draw_locs_cvar, 0, 0); + Cvar_Register (&cl_shownet_cvar, 0, 0); + Cvar_Register (&cl_maxfps_cvar, 0, 0); + Cvar_Register (&cl_timeout_cvar, 0, 0); + Cvar_Register (&host_speeds_cvar, 0, 0); + Cvar_Register (&rcon_password_cvar, 0, 0); + Cvar_Register (&rcon_address_cvar, 0, 0); + Cvar_Register (&hud_fps_cvar, 0, 0); + Cvar_MakeAlias ("show_fps", &hud_fps_cvar); + Cvar_Register (&hud_ping_cvar, 0, 0); + Cvar_Register (&hud_pl_cvar, 0, 0); + Cvar_Register (&hud_time_cvar, 0, 0); + Cvar_Register (&cl_predict_players_cvar, 0, 0); + Cvar_Register (&cl_solid_players_cvar, 0, 0); + Cvar_Register (&localid_cvar, 0, 0); // info mirrors - cl_name = Cvar_Get ("name", "unnamed", CVAR_ARCHIVE | CVAR_USERINFO, - Cvar_Info, "Player name"); - password = Cvar_Get ("password", "", CVAR_USERINFO, Cvar_Info, - "Server password"); - spectator = Cvar_Get ("spectator", "", CVAR_USERINFO, Cvar_Info, - "Set to 1 before connecting to become a spectator"); - team = Cvar_Get ("team", "", CVAR_ARCHIVE | CVAR_USERINFO, Cvar_Info, - "Team player is on."); - rate = Cvar_Get ("rate", "10000", CVAR_ARCHIVE | CVAR_USERINFO, Cvar_Info, - "Amount of bytes per second server will send/download " - "to you"); - msg = Cvar_Get ("msg", "1", CVAR_ARCHIVE | CVAR_USERINFO, Cvar_Info, - "Determines the type of messages reported 0 is maximum, " - "4 is none"); - noaim = Cvar_Get ("noaim", "0", CVAR_ARCHIVE | CVAR_USERINFO, Cvar_Info, - "Auto aim off switch. Set to 1 to turn off."); - cl_port = Cvar_Get ("cl_port", PORT_CLIENT, CVAR_NONE, Cvar_Info, - "UDP Port for client to use."); - cl_usleep = Cvar_Get ("cl_usleep", "1", CVAR_ARCHIVE, cl_usleep_f, - "Turn this on to save cpu when fps limited. " - "May affect frame rate adversely depending on " - "local machine/os conditions"); - cl_autorecord = Cvar_Get ("cl_autorecord", "0", CVAR_ARCHIVE, NULL, "Turn " - "this on, if you want to record every game"); + Cvar_Register (&cl_name_cvar, 0, 0); + Cvar_Register (&password_cvar, 0, 0); + Cvar_Register (&spectator_cvar, Cvar_Info, &spectator); + Cvar_Register (&team_cvar, Cvar_Info, &team); + Cvar_Register (&rate_cvar, Cvar_Info, &rate); + Cvar_Register (&msg_cvar, Cvar_Info, &msg); + Cvar_Register (&noaim_cvar, Cvar_Info, &noaim); + Cvar_Register (&cl_port_cvar, Cvar_Info, &cl_port); + Cvar_Register (&cl_usleep_cvar, 0, 0); + Cvar_Register (&cl_autorecord_cvar, 0, 0); } /* @@ -1507,7 +1729,7 @@ Host_Error (const char *error, ...) void Host_WriteConfiguration (void) { - if (host_initialized && cl_writecfg->int_val) { + if (host_initialized && cl_writecfg) { plitem_t *config = PL_NewDictionary (0); //FIXME hashlinks Cvar_SaveConfig (config); IN_SaveConfig (config); @@ -1561,14 +1783,14 @@ Host_ExecConfig (cbuf_t *cbuf, int skip_quakerc) // should be used to set up defaults on the assumption that the user has // things set up to work with another (hopefully compatible) client if (Host_ReadConfiguration ("quakeforge.cfg")) { - Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cmd_Exec_File (cbuf, fs_usercfg, 0); Cmd_StuffCmds (cbuf); COM_Check_quakerc ("startdemos", cbuf); } else { if (!skip_quakerc) { Cbuf_InsertText (cbuf, "exec quake.rc\n"); } - Cmd_Exec_File (cbuf, fs_usercfg->string, 0); + Cmd_Exec_File (cbuf, fs_usercfg, 0); // Reparse the command line for + commands. // (sets still done, but it doesn't matter) // (Note, no non-base commands exist yet) @@ -1593,7 +1815,7 @@ Host_SimulationTime (float time) con_realtime += time; if (cls.demoplayback) { - timescale = max (0, demo_speed->value); + timescale = max (0, demo_speed); time *= timescale; } @@ -1604,10 +1826,10 @@ Host_SimulationTime (float time) if (cls.demoplayback) return 0; - if (cl_maxfps->value <= 0) + if (cl_maxfps <= 0) fps = 72; else - fps = min (cl_maxfps->value, 72); + fps = min (cl_maxfps, 72); timedifference = (timescale / fps) - (realtime - oldrealtime); @@ -1655,7 +1877,7 @@ Host_Frame (float time) // decide the simulation time if ((sleeptime = Host_SimulationTime (time)) != 0) { #ifdef HAVE_USLEEP - if (cl_usleep_cache && sleeptime > 0.002) // minimum sleep time + if (cl_usleep && sleeptime > 0.002) // minimum sleep time usleep ((unsigned long) (sleeptime * 1000000 / 2)); #endif return; // framerate is too high @@ -1716,14 +1938,14 @@ Host_Frame (float time) CL_PredictMove (); // Set up prediction for other players - CL_SetUpPlayerPrediction (cl_predict_players->int_val); + CL_SetUpPlayerPrediction (cl_predict_players); // build a refresh entity list CL_EmitEntities (); } // update video - if (host_speeds->int_val) + if (host_speeds) time1 = Sys_DoubleTime (); r_data->inhibit_viewmodel = (!Cam_DrawViewModel () @@ -1733,7 +1955,7 @@ Host_Frame (float time) CL_UpdateScreen (realtime); - if (host_speeds->int_val) + if (host_speeds) time2 = Sys_DoubleTime (); // update audio @@ -1753,7 +1975,7 @@ Host_Frame (float time) CDAudio_Update (); - if (host_speeds->int_val) { + if (host_speeds) { pass1 = (time1 - time3) * 1000; time3 = Sys_DoubleTime (); pass2 = (time2 - time1) * 1000; @@ -1777,18 +1999,15 @@ CL_Init_Memory (void) size_t mem_size; void *mem_base; - cl_mem_size = Cvar_Get ("cl_mem_size", "32", CVAR_NONE, NULL, - "Amount of memory (in MB) to allocate for the " - PACKAGE_NAME " heap"); + Cvar_Register (&cl_mem_size_cvar, 0, 0); if (mem_parm) - Cvar_Set (cl_mem_size, com_argv[mem_parm + 1]); + Cvar_Set ("cl_mem_size", com_argv[mem_parm + 1]); if (COM_CheckParm ("-minmemory")) - Cvar_SetValue (cl_mem_size, MINIMUM_MEMORY / (1024 * 1024.0)); + cl_mem_size = MINIMUM_MEMORY / (1024 * 1024.0); - Cvar_SetFlags (cl_mem_size, cl_mem_size->flags | CVAR_ROM); - mem_size = ((size_t) cl_mem_size->value * 1024 * 1024); + mem_size = ((size_t) cl_mem_size * 1024 * 1024); if (mem_size < MINIMUM_MEMORY) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", @@ -1802,7 +2021,7 @@ CL_Init_Memory (void) Sys_PageIn (mem_base, mem_size); memhunk_t *hunk = Memory_Init (mem_base, mem_size); - Sys_Printf ("%4.1f megabyte heap.\n", cl_mem_size->value); + Sys_Printf ("%4.1f megabyte heap.\n", cl_mem_size); return hunk; } @@ -1812,7 +2031,7 @@ CL_Autoexec (int phase) if (!phase) return; if (!Host_ReadConfiguration ("quakeforge.cfg")) { - int cmd_warncmd_val = cmd_warncmd->int_val; + int cmd_warncmd_val = cmd_warncmd; Cbuf_AddText (cl_cbuf, "cmd_warncmd 0\n"); Cbuf_AddText (cl_cbuf, "exec config.cfg\n"); @@ -1821,7 +2040,7 @@ CL_Autoexec (int phase) Cbuf_AddText (cl_cbuf, va (0, "cmd_warncmd %d\n", cmd_warncmd_val)); } - if (cl_autoexec->int_val) { + if (cl_autoexec) { Cbuf_AddText (cl_cbuf, "exec autoexec.cfg\n"); } } @@ -1856,7 +2075,7 @@ Host_Init (void) CL_Cmd_Init (); Game_Init (); - NET_Init (cl_port->int_val); + NET_Init (cl_port); Netchan_Init (); net_realtime = &realtime; { @@ -1876,7 +2095,7 @@ Host_Init (void) CL_UpdateScreen (realtime); CL_UpdateScreen (realtime); - Host_ExecConfig (cl_cbuf, !cl_quakerc->int_val); + Host_ExecConfig (cl_cbuf, !cl_quakerc); // make sure all + commands have been executed Cbuf_Execute_Stack (cl_cbuf); diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 1d31f20da..fb60fe0c8 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -48,29 +48,59 @@ #include "qw/include/client.h" #include "sbar.h" -cvar_t *cl_netgraph; -cvar_t *cl_netgraph_alpha; -cvar_t *cl_netgraph_box; -cvar_t *cl_netgraph_height; +int cl_netgraph; +static cvar_t cl_netgraph_cvar = { + .name = "cl_netgraph", + .description = + "Toggle the display of a graph showing network performance", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_netgraph }, +}; +float cl_netgraph_alpha; +static cvar_t cl_netgraph_alpha_cvar = { + .name = "cl_netgraph_alpha", + .description = + "Net graph translucency", + .default_value = "0.5", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_netgraph_alpha }, +}; +int cl_netgraph_box; +static cvar_t cl_netgraph_box_cvar = { + .name = "cl_netgraph_box", + .description = + " Draw box around net graph", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_netgraph_box }, +}; +int cl_netgraph_height; +static cvar_t cl_netgraph_height_cvar = { + .name = "cl_netgraph_height", + .description = + "Set the fullscale (1s) height of the graph", + .default_value = "32", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_netgraph_height }, +}; view_t *cl_netgraph_view; static void -cl_netgraph_f (cvar_t *var) +cl_netgraph_f (void *data, const cvar_t *cvar) { if (cl_netgraph_view) { - cl_netgraph_view->visible = var->int_val != 0; + cl_netgraph_view->visible = cl_netgraph != 0; } } static void -cl_netgraph_height_f (cvar_t *var) +cl_netgraph_height_f (void *data, const cvar_t *cvar) { - if (var->int_val < 32) { - Cvar_Set (var, "32"); - } + cl_netgraph_height = max (32, cl_netgraph_height); if (cl_netgraph_view) { view_resize (cl_netgraph_view, cl_netgraph_view->xlen, - var->int_val + 25); + cl_netgraph_height + 25); } } @@ -83,10 +113,10 @@ CL_NetGraph (view_t *view) x = view->xabs; y = view->yabs; - if (cl_netgraph_box->int_val) { + if (cl_netgraph_box) { r_funcs->Draw_TextBox (x, y, NET_TIMINGS / 8, - cl_netgraph_height->int_val / 8 + 1, - cl_netgraph_alpha->value * 255); + cl_netgraph_height / 8 + 1, + cl_netgraph_alpha * 255); } lost = CL_CalcNet (); @@ -108,7 +138,7 @@ CL_NetGraph (view_t *view) } memcpy (timings + o, packet_latency + a, l * sizeof (timings[0])); r_funcs->R_LineGraph (x, y, timings, - NET_TIMINGS, cl_netgraph_height->int_val); + NET_TIMINGS, cl_netgraph_height); x = view->xabs + 8; y = view->yabs + 8; @@ -118,15 +148,8 @@ CL_NetGraph (view_t *view) void CL_NetGraph_Init_Cvars (void) { - cl_netgraph = Cvar_Get ("cl_netgraph", "0", CVAR_NONE, cl_netgraph_f, - "Toggle the display of a graph showing network " - "performance"); - cl_netgraph_alpha = Cvar_Get ("cl_netgraph_alpha", "0.5", CVAR_ARCHIVE, 0, - "Net graph translucency"); - cl_netgraph_box = Cvar_Get ("cl_netgraph_box", "1", CVAR_ARCHIVE, 0, - " Draw box around net graph"); - cl_netgraph_height = Cvar_Get ("cl_netgraph_height", "32", CVAR_ARCHIVE, - cl_netgraph_height_f, - "Set the fullscale (1s) height of the " - "graph"); + Cvar_Register (&cl_netgraph_cvar, cl_netgraph_f, 0); + Cvar_Register (&cl_netgraph_alpha_cvar, 0, 0); + Cvar_Register (&cl_netgraph_box_cvar, 0, 0); + Cvar_Register (&cl_netgraph_height_cvar, cl_netgraph_height_f, 0); } diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index cd97ec003..5b58202ac 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -190,7 +190,7 @@ CL_CalcNet (void) } else { double d = frame->receivedtime - frame->senttime; d = log (d * 1000 + 1) / log (1000); - d *= d * cl_netgraph_height->int_val; + d *= d * cl_netgraph_height; packet_latency[i & NET_TIMINGSMASK] = d; } } @@ -326,7 +326,7 @@ Model_NextDownload (void) && cl_world.models.a[i]->type == mod_alias) info_key = emodel_name; - if (info_key && cl_model_crcs->int_val) { + if (info_key && cl_model_crcs) { aliashdr_t *ahdr = cl_world.models.a[i]->aliashdr; if (!ahdr) ahdr = Cache_Get (&cl_world.models.a[i]->cache); @@ -1115,11 +1115,11 @@ CL_ServerInfo (void) } else if (strequal (key, "cshifts")) { cl.sv_cshifts = atoi (value); } else if (strequal (key, "no_pogo_stick")) { - Cvar_Set (no_pogo_stick, value); - cl.no_pogo_stick = no_pogo_stick->int_val; + Cvar_Set ("no_pogo_stick", value); + cl.no_pogo_stick = no_pogo_stick; } else if (strequal (key, "teamplay")) { cl.teamplay = atoi (value); - Sbar_DMO_Init_f (hud_scoreboard_uid); // HUD setup, cl.teamplay changed + Sbar_DMO_Init_f (0, 0); // HUD setup, cl.teamplay changed } else if (strequal (key, "watervis")) { cl.watervis = atoi (value); } else if (strequal (key, "fpd")) { @@ -1198,7 +1198,7 @@ CL_ParseMuzzleFlash (void) } #define SHOWNET(x) \ - if (cl_shownet->int_val == 2) \ + if (cl_shownet == 2) \ Sys_Printf ("%3i:%s\n", net_message->readcount - 1, x); int received_framecount; @@ -1218,9 +1218,9 @@ CL_ParseServerMessage (void) CL_ClearProjectiles (); // if recording demos, copy the message out - if (cl_shownet->int_val == 1) + if (cl_shownet == 1) Sys_Printf ("%i ", net_message->message->cursize); - else if (cl_shownet->int_val == 2) + else if (cl_shownet == 2) Sys_Printf ("------------------ %d\n", cls.netchan.incoming_acknowledged); @@ -1286,7 +1286,7 @@ CL_ParseServerMessage (void) break; // TODO: cl_nofake 2 -- accept fake messages from teammates - if (cl_nofake->int_val) { + if (cl_nofake) { char *c; p = dstring_strdup (str); diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index 7d25dd354..53435937f 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -42,8 +42,24 @@ #include "qw/include/client.h" #include "qw/pmove.h" -cvar_t *cl_predict; -cvar_t *cl_pushlatency; +int cl_predict; +static cvar_t cl_predict_cvar = { + .name = "cl_predict", + .description = + "Set to enable client prediction", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_predict }, +}; +float cl_pushlatency; +static cvar_t cl_pushlatency_cvar = { + .name = "pushlatency", + .description = + "How much prediction should the client make", + .default_value = "-999", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_pushlatency }, +}; void @@ -108,8 +124,8 @@ CL_PredictMove (void) entity_state_t *fromes; entity_state_t *toes; - if (cl_pushlatency->value > 0) - Cvar_Set (cl_pushlatency, "0"); + if (cl_pushlatency > 0) + Cvar_Set ("pushlatency", "0"); if (cl.paused) return; @@ -117,7 +133,7 @@ CL_PredictMove (void) // assume on ground unless prediction says different cl.viewstate.onground = 0; - cl.time = realtime - cls.latency - cl_pushlatency->value * 0.001; + cl.time = realtime - cls.latency - cl_pushlatency * 0.001; if (cl.time > realtime) cl.time = realtime; @@ -139,7 +155,7 @@ CL_PredictMove (void) from = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; fromes = &from->playerstate[cl.playernum].pls.es; - if (!cl_predict->int_val) { + if (!cl_predict) { cl.viewstate.velocity = fromes->velocity; cl.viewstate.player_origin = fromes->origin; return; @@ -193,8 +209,6 @@ CL_PredictMove (void) void CL_Prediction_Init_Cvars (void) { - cl_predict = Cvar_Get ("cl_predict", "1", CVAR_NONE, NULL, - "Set to enable client prediction"); - cl_pushlatency = Cvar_Get ("pushlatency", "-999", CVAR_NONE, NULL, - "How much prediction should the client make"); + Cvar_Register (&cl_predict_cvar, 0, 0); + Cvar_Register (&cl_pushlatency_cvar, 0, 0); } diff --git a/qw/source/cl_rss.c b/qw/source/cl_rss.c index b5974ba53..8e0025454 100644 --- a/qw/source/cl_rss.c +++ b/qw/source/cl_rss.c @@ -213,7 +213,7 @@ snap_capture (tex_t *snap, void *data) snap_drawstring (st->str, tex, tex->width - strlen (st->str) * 8, tex->height - 11); - dstring_copystr (st, cl_name->string); + dstring_copystr (st, cl_name); snap_drawstring (st->str, tex, tex->width - strlen (st->str) * 8, tex->height - 21); diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index de8d13cf0..82fd9b63d 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -96,12 +96,12 @@ scr_draw_views (void) - cls.netchan.incoming_acknowledged) >= UPDATE_BACKUP - 1); loading_view->visible = cl.loading; - cl_netgraph_view->visible = cl_netgraph->int_val != 0; + cl_netgraph_view->visible = cl_netgraph != 0; //FIXME don't do every frame - view_move (cl_netgraph_view, cl_netgraph_view->xpos, sb_lines); + view_move (cl_netgraph_view, cl_netgraph_view->xpos, hud_sb_lines); view_setgravity (cl_netgraph_view, - hud_swap->int_val ? grav_southeast : grav_southwest); + hud_swap ? grav_southeast : grav_southwest); view_draw (r_data->vid->conview); } @@ -167,9 +167,9 @@ CL_UpdateScreen (double realtime) } if (!cl_netgraph_view) { - cl_netgraph_view = view_new (0, sb_lines, + cl_netgraph_view = view_new (0, hud_sb_lines, NET_TIMINGS + 16, - cl_netgraph_height->int_val + 25, + cl_netgraph_height + 25, grav_southwest); cl_netgraph_view->draw = CL_NetGraph; cl_netgraph_view->visible = 0; diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index 6ff72805b..e509764cc 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -50,10 +50,42 @@ #include "qw/include/client.h" #include "qw/include/host.h" -cvar_t *noskins; //XXX FIXME -cvar_t *skin; -cvar_t *topcolor; -cvar_t *bottomcolor; +int noskins; +static cvar_t noskins_cvar = { + .name = "noskins", + .description = + "set to 1 to not download new skins", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &noskins }, +}; +char *skin; +static cvar_t skin_cvar = { + .name = "skin", + .description = + "Players skin", + .default_value = "", + .flags = CVAR_ARCHIVE | CVAR_USERINFO, + .value = { .type = 0, .value = &skin }, +}; +char *topcolor; +static cvar_t topcolor_cvar = { + .name = "topcolor", + .description = + "Players color on top", + .default_value = "0", + .flags = CVAR_ARCHIVE | CVAR_USERINFO, + .value = { .type = 0/* not used */, .value = &topcolor }, +}; +char *bottomcolor; +static cvar_t bottomcolor_cvar = { + .name = "bottomcolor", + .description = + "Players color on bottom", + .default_value = "0", + .flags = CVAR_ARCHIVE | CVAR_USERINFO, + .value = { .type = 0/* not used */, .value = &bottomcolor }, +}; void @@ -76,7 +108,7 @@ Skin_NextDownload (void) if (!sc->name || !sc->name->value[0]) continue; //XXX Skin_Find (sc); - if (noskins->int_val) //XXX FIXME + if (noskins) //XXX FIXME continue; //XXX if (!CL_CheckOrDownloadFile (va (0, "skins/%s.pcx", // sc->skin->name))) @@ -175,18 +207,18 @@ CL_Color_f (void) bottom = 13; snprintf (num, sizeof (num), "%i", top); - Cvar_Set (topcolor, num); + Cvar_Set ("topcolor", num); snprintf (num, sizeof (num), "%i", bottom); - Cvar_Set (bottomcolor, num); + Cvar_Set ("bottomcolor", num); } static void -skin_f (cvar_t *var) +skin_f (void *data, const cvar_t *cvar) { - char *s = Hunk_TempAlloc (0, strlen (var->string) + 1); - QFS_StripExtension (var->string, s); - Cvar_Set (var, s); - Cvar_Info (var); + char *s = Hunk_TempAlloc (0, strlen (skin) + 1); + QFS_StripExtension (skin, s); + skin = strdup (s); + Cvar_Info (0, cvar); } void @@ -200,12 +232,8 @@ CL_Skin_Init (void) "shirt pants) Note that if only shirt color is given, " "pants will match"); - noskins = Cvar_Get ("noskins", "0", CVAR_ARCHIVE, NULL, - "set to 1 to not download new skins"); - skin = Cvar_Get ("skin", "", CVAR_ARCHIVE | CVAR_USERINFO, skin_f, - "Players skin"); - topcolor = Cvar_Get ("topcolor", "0", CVAR_ARCHIVE | CVAR_USERINFO, - Cvar_Info, "Players color on top"); - bottomcolor = Cvar_Get ("bottomcolor", "0", CVAR_ARCHIVE | CVAR_USERINFO, - Cvar_Info, "Players color on bottom"); + Cvar_Register (&noskins_cvar, 0, 0); + Cvar_Register (&skin_cvar, skin_f, 0); + Cvar_Register (&topcolor_cvar, Cvar_Info, &topcolor); + Cvar_Register (&bottomcolor_cvar, Cvar_Info, &bottomcolor); } diff --git a/qw/source/cl_slist.c b/qw/source/cl_slist.c index 4d5b43513..9dd89e9a1 100644 --- a/qw/source/cl_slist.c +++ b/qw/source/cl_slist.c @@ -90,10 +90,42 @@ server_entry_t *fav_slist; int which_slist; int slist_last_details; -cvar_t *sl_sortby; -cvar_t *sl_filter; -cvar_t *sl_game; -cvar_t *sl_ping; +int sl_sortby; +static cvar_t sl_sortby_cvar = { + .name = "sl_sortby", + .description = + "0 = sort by name, 1 = sort by ping", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &sl_sortby }, +}; +int sl_filter; +static cvar_t sl_filter_cvar = { + .name = "sl_filter", + .description = + "enable server filter", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sl_filter }, +}; +char *sl_game; +static cvar_t sl_game_cvar = { + .name = "sl_game", + .description = + "sets the serverlist game filter", + .default_value = "", + .flags = CVAR_ARCHIVE, + .value = { .type = 0, .value = &sl_game }, +}; +int sl_ping; +static cvar_t sl_ping_cvar = { + .name = "sl_ping", + .description = + "sets the serverlist ping filter", + .default_value = "", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &sl_ping }, +}; static void @@ -225,19 +257,19 @@ SL_Swap (server_entry_t *swap1, server_entry_t *swap2) static int SL_CheckFilter (server_entry_t *sl_filteritem) { - if (!sl_filter->int_val) + if (!sl_filter) return (1); if (!sl_filteritem->status) return (0); - if (strlen (sl_game->string)) { + if (strlen (sl_game)) { if (strcasecmp (Info_ValueForKey (sl_filteritem->status, "*gamedir"), - sl_game->string) != 0) + sl_game) != 0) return (0); } - if (sl_ping->int_val) { + if (sl_ping) { if (!sl_filteritem->pongback) return (0); - if (((int) (sl_filteritem->pongback * 1000)) >= sl_ping->int_val) + if (((int) (sl_filteritem->pongback * 1000)) >= sl_ping) return (0); } return (1); @@ -373,7 +405,7 @@ SL_SortEntry (server_entry_t *start) return; for (q = start->next; q; q = q->next) { - if (sl_sortby->int_val) { + if (sl_sortby) { if ((q->pongback) && (start->pongback) && (start->pongback > q->pongback)) { SL_Swap (start, q); @@ -396,7 +428,7 @@ SL_SortEntry (server_entry_t *start) } static void -SL_Sort (cvar_t *var) +SL_Sort (void *data, const cvar_t *cvar) { server_entry_t *p; @@ -413,7 +445,7 @@ SL_Con_List (server_entry_t *sldata) int serv; server_entry_t *cp; - SL_Sort (sl_sortby); + SL_Sort (0, 0); for (serv = 0; serv < SL_Len (sldata); serv++) { cp = SL_Get_By_Num (sldata, serv); @@ -520,7 +552,7 @@ SL_Switch (void) slist = fav_slist; which_slist = 0; } - SL_Sort (sl_sortby); + SL_Sort (0, 0); return (which_slist); } @@ -638,14 +670,10 @@ SL_Init (void) which_slist = 0; Cmd_AddCommand ("slist", SL_Command, "console commands to access server " "list\n"); - sl_sortby = Cvar_Get ("sl_sortby", "0", CVAR_ARCHIVE, SL_Sort, "0 = sort " - "by name, 1 = sort by ping"); - sl_filter = Cvar_Get ("sl_filter", "0", CVAR_NONE, NULL, "enable server " - "filter"); - sl_game = Cvar_Get ("sl_game", "", CVAR_ARCHIVE, NULL, "sets the " - "serverlist game filter"); - sl_ping = Cvar_Get ("sl_ping", "", CVAR_ARCHIVE, NULL, "sets the " - "serverlist ping filter"); + Cvar_Register (&sl_sortby_cvar, SL_Sort, 0); + Cvar_Register (&sl_filter_cvar, 0, 0); + Cvar_Register (&sl_game_cvar, 0, 0); + Cvar_Register (&sl_ping_cvar, 0, 0); } int diff --git a/qw/source/crudefile.c b/qw/source/crudefile.c index 4924a03ee..7ef0cad74 100644 --- a/qw/source/crudefile.c +++ b/qw/source/crudefile.c @@ -66,7 +66,16 @@ typedef struct cf_file_s { } cf_file_t; cf_file_t *cf_filep; -cvar_t *crudefile_quota; +int crudefile_quota; +static cvar_t crudefile_quota_cvar = { + .name = "crudefile_quota", + .description = + "Maximum space available to the Crude File system, -1 to totally " + "disable file writing", + .default_value = "-1", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &crudefile_quota }, +}; int cf_filepcount; // elements in array int cf_openfiles; // used elements @@ -164,10 +173,8 @@ void CF_Init (void) { CF_BuildQuota (); - crudefile_quota = Cvar_Get ("crudefile_quota", "-1", CVAR_ROM, NULL, - "Maximum space available to the Crude File " - "system, -1 to totally disable file writing"); - cf_maxsize = crudefile_quota->int_val; + Cvar_Register (&crudefile_quota_cvar, 0, 0); + cf_maxsize = crudefile_quota; } /* diff --git a/qw/source/game.c b/qw/source/game.c index df180b306..dba073f3e 100644 --- a/qw/source/game.c +++ b/qw/source/game.c @@ -46,7 +46,15 @@ #include "qw/include/game.h" #include "qw/include/server.h" -cvar_t *registered; +char *registered; +static cvar_t registered_cvar = { + .name = "registered", + .description = + "Is the game the registered version. 1 yes 0 no", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = ®istered }, +}; int static_registered = 1; // only for startup check, then set /* @@ -71,7 +79,7 @@ Game_CheckRegistered (void) } if (static_registered) { - Cvar_Set (registered, "1"); + Cvar_Set ("registered", "1"); Sys_Printf ("Playing registered version.\n"); } } @@ -110,8 +118,7 @@ SV_Gamedir_f (void) void Game_Init (void) { - registered = Cvar_Get ("registered", "0", CVAR_NONE, NULL, - "Is the game the registered version. 1 yes 0 no"); + Cvar_Register (®istered_cvar, 0, 0); Game_CheckRegistered (); Cmd_AddCommand ("gamedir", SV_Gamedir_f, "Specifies the directory to be used while playing."); diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index 92cddcb38..cd9b6eed6 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -59,8 +59,24 @@ #include "qw/protocol.h" #include "qw/include/server.h" -cvar_t *net_packetlog; -cvar_t *net_loglevel; +int net_packetlog; +static cvar_t net_packetlog_cvar = { + .name = "net_packetlog", + .description = + "enable/disable packet logging", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &net_packetlog }, +}; +int net_loglevel; +static cvar_t net_loglevel_cvar = { + .name = "net_loglevel", + .description = + "Packet logging/parsing", + .default_value = "2", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &net_loglevel }, +}; // note: this is SUPPOSED to be duplicate, like many others const char *svc_string[] = { @@ -227,22 +243,22 @@ ascii_dump_buf (unsigned char *buf, int len) void Log_Incoming_Packet (const byte *p, int len, int has_sequence) { - if (!net_loglevel->int_val) + if (!net_loglevel) return; if (is_server) { Net_LogPrintf ("\n<<<<<<<<<<<<<<<<<<<<< client to server %d bytes: " "<<<<<<<<<<<<<<<<<<<<<<<<\n", len); - if (net_loglevel->int_val != 3) + if (net_loglevel != 3) hex_dump_buf ((unsigned char *) p, len); - if (net_loglevel->int_val > 1) + if (net_loglevel > 1) Analyze_Client_Packet (p, len, has_sequence); } else { Net_LogPrintf ("\n>>>>>>>>>>>>>>>>>>>>> server to client %d bytes: " ">>>>>>>>>>>>>>>>>>>>>>>>\n", len); - if (net_loglevel->int_val != 3) + if (net_loglevel != 3) hex_dump_buf ((unsigned char *) p, len); - if (net_loglevel->int_val > 1) + if (net_loglevel > 1) Analyze_Server_Packet (p, len, has_sequence); } return; @@ -251,22 +267,22 @@ Log_Incoming_Packet (const byte *p, int len, int has_sequence) void Log_Outgoing_Packet (const byte *p, int len, int has_sequence) { - if (!net_loglevel->int_val) + if (!net_loglevel) return; if (is_server) { Net_LogPrintf ("\n>>>>>>>>>>>>>>>>>>>>> server to client %d bytes: " ">>>>>>>>>>>>>>>>>>>>>>>>\n", len); - if (net_loglevel->int_val != 3) + if (net_loglevel != 3) hex_dump_buf ((unsigned char *) p, len); - if (net_loglevel->int_val > 1) + if (net_loglevel > 1) Analyze_Server_Packet (p, len, has_sequence); } else { Net_LogPrintf ("\n<<<<<<<<<<<<<<<<<<<<< client to server %d bytes: " "<<<<<<<<<<<<<<<<<<<<<<<<\n", len); - if (net_loglevel->int_val != 3) + if (net_loglevel != 3) hex_dump_buf ((unsigned char *) p, len); - if (net_loglevel->int_val > 1) + if (net_loglevel > 1) Analyze_Client_Packet (p, len, has_sequence); } return; @@ -958,9 +974,9 @@ net_packet_log_f (int length, const void *data, netadr_t to) } static void -Net_PacketLog_f (cvar_t *var) +Net_PacketLog_f (void *data, const cvar_t *cvar) { - if (var->int_val) { + if (net_packetlog) { Net_LogStart ("qfpacket.log"); net_log_packet = net_packet_log_f; } else { @@ -990,8 +1006,7 @@ Net_Log_Init (const char **sound_precache, int server) _stdout = Qdopen (1, "wt"); // create a QFile of stdout - net_packetlog = Cvar_Get ("net_packetlog", "0", CVAR_NONE, Net_PacketLog_f, - "enable/disable packet logging"); + Cvar_Register (&net_packetlog_cvar, Net_PacketLog_f, 0); // 0 = no logging // 1 = hex dump only @@ -999,8 +1014,7 @@ Net_Log_Init (const char **sound_precache, int server) // 3 = just parse // 4 = parse/hexdump, skip movement/empty messages - net_loglevel = Cvar_Get ("net_loglevel", "2", CVAR_NONE, NULL, - "Packet logging/parsing"); + Cvar_Register (&net_loglevel_cvar, 0, 0); Cmd_AddCommand ("net_packetlog_zap", Net_PacketLog_Zap_f, "clear the packet log file"); diff --git a/qw/source/pmove.c b/qw/source/pmove.c index 07d30f0bc..0d208f947 100644 --- a/qw/source/pmove.c +++ b/qw/source/pmove.c @@ -39,7 +39,16 @@ #include "qw/include/client.h" #include "qw/pmove.h" -cvar_t *no_pogo_stick; +int no_pogo_stick; +static cvar_t no_pogo_stick_cvar = { + .name = "no_pogo_stick", + .description = + "disable the ability to pogo stick: 0 pogo allowed, 1 no pogo, 2 pogo " + "but high friction, 3 high friction and no pogo", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &no_pogo_stick }, +}; movevars_t movevars; playermove_t pmove; @@ -63,10 +72,7 @@ Pmove_Init (void) void Pmove_Init_Cvars (void) { - no_pogo_stick = Cvar_Get ("no_pogo_stick", "0", CVAR_SERVERINFO, Cvar_Info, - "disable the ability to pogo stick: 0 pogo " - "allowed, 1 no pogo, 2 pogo but high friction, " - "3 high friction and no pogo"); + Cvar_Register (&no_pogo_stick_cvar, Cvar_Info, &no_pogo_stick); } #define STEPSIZE 18 @@ -637,7 +643,7 @@ JumpButton (void) } if (onground == -1) { - if (no_pogo_stick->int_val & 1) + if (no_pogo_stick & 1) pmove.oldbuttons |= BUTTON_JUMP; // don't jump again until // released return; // in air, so no effect @@ -820,9 +826,9 @@ PlayerMove (void) // set onground, watertype, and waterlevel PM_CategorizePosition (); - if (((pmove.cmd.buttons & BUTTON_JUMP) || (no_pogo_stick->int_val & 1)) + if (((pmove.cmd.buttons & BUTTON_JUMP) || (no_pogo_stick & 1)) && onground != -1 && pmove.oldonground == -1 // just landed - && (no_pogo_stick->int_val & 2)) { + && (no_pogo_stick & 2)) { float save = movevars.friction; pmove.waterjumptime = 0; diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 15863b80d..bd717a1c2 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -67,6 +67,7 @@ #include "sbar.h" int sb_updates; // if >= vid.numpages, no update needed +static int sb_view_size; #define STAT_MINUS 10 // num frame for '-' stats digit @@ -92,126 +93,64 @@ qpic_t *sb_face_invis_invuln; qboolean sb_showscores; qboolean sb_showteamscores; -int sb_lines; // scan lines to draw - static qboolean largegame = false; -cvar_t *fs_fraglog; -cvar_t *cl_fraglog; -cvar_t *hud_scoreboard_uid; -cvar_t *scr_centertime; -cvar_t *scr_printspeed; - -static view_t *sbar_view; -static view_t *sbar_inventory_view; -static view_t *sbar_frags_view; - -static view_t *hud_view; -static view_t *hud_inventory_view; -static view_t *hud_armament_view; -static view_t *hud_frags_view; - -static view_t *overlay_view; -static view_t *stuff_view; -static view_t *main_view; +char *fs_fraglog; +static cvar_t fs_fraglog_cvar = { + .name = "fs_fraglog", + .description = + "Filename of the automatic frag-log.", + .default_value = "qw-scores.log", + .flags = CVAR_ARCHIVE, + .value = { .type = 0, .value = &fs_fraglog }, +}; +int cl_fraglog; +static cvar_t cl_fraglog_cvar = { + .name = "cl_fraglog", + .description = + "Automatic fraglogging, non-zero value will switch it on.", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_fraglog }, +}; +int hud_scoreboard_uid; +static cvar_t hud_scoreboard_uid_cvar = { + .name = "hud_scoreboard_uid", + .description = + "Set to 1 to show uid instead of ping. Set to 2 to show both.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &hud_scoreboard_uid }, +}; +float scr_centertime; +static cvar_t scr_centertime_cvar = { + .name = "scr_centertime", + .description = + "How long in seconds screen hints are displayed", + .default_value = "2", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &scr_centertime }, +}; +float scr_printspeed; +static cvar_t scr_printspeed_cvar = { + .name = "scr_printspeed", + .description = + "How fast the text is displayed at the end of the single player " + "episodes", + .default_value = "8", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &scr_printspeed }, +}; static void (*Sbar_Draw_DMO_func) (view_t *view, int l, int y, int skip); static void -hud_swap_f (cvar_t *var) +viewsize_f (int view_size) { - if (var->int_val) { - view_setgravity (hud_armament_view, grav_southwest); - view_setgravity (stuff_view, grav_southeast); - } else { - view_setgravity (hud_armament_view, grav_southeast); - view_setgravity (stuff_view, grav_southwest); - } -} - -static void -hud_scoreboard_gravity_f (cvar_t *var) -{ - grav_t grav; - - if (strequal (var->string, "center")) - grav = grav_center; - else if (strequal (var->string, "northwest")) - grav = grav_northwest; - else if (strequal (var->string, "north")) - grav = grav_north; - else if (strequal (var->string, "northeast")) - grav = grav_northeast; - else if (strequal (var->string, "west")) - grav = grav_west; - else if (strequal (var->string, "east")) - grav = grav_east; - else if (strequal (var->string, "southwest")) - grav = grav_southwest; - else if (strequal (var->string, "south")) - grav = grav_south; - else if (strequal (var->string, "southeast")) - grav = grav_southeast; - else - grav = grav_center; - overlay_view->gravity = grav; - view_move (overlay_view, overlay_view->xpos, overlay_view->ypos); -} - -static void -calc_sb_lines (cvar_t *var) -{ - int stuff_y; - - if (var->int_val >= 120) { - sb_lines = 0; - stuff_y = 0; - } else if (var->int_val >= 110) { - sb_lines = 24; - sbar_inventory_view->visible = 0; - hud_inventory_view->visible = 0; - hud_armament_view->visible = 0; - stuff_y = 32; - } else { - sb_lines = 48; - sbar_inventory_view->visible = 1; - hud_inventory_view->visible = 1; - hud_armament_view->visible = 1; - stuff_y = 48; - } - if (sb_lines) { - sbar_view->visible = 1; - hud_view->visible = 1; - view_resize (sbar_view, sbar_view->xlen, sb_lines); - view_resize (hud_view, hud_view->xlen, sb_lines); - } else { - sbar_view->visible = 0; - hud_view->visible = 0; - } - view_move (stuff_view, stuff_view->xpos, stuff_y); -} - -static void -hud_sbar_f (cvar_t *var) -{ - if (r_data->scr_viewsize) - calc_sb_lines (r_data->scr_viewsize); - SCR_SetBottomMargin (var->int_val ? sb_lines : 0); - if (var->int_val) { - view_remove (main_view, main_view->children[0]); - view_insert (main_view, sbar_view, 0); - } else { - view_remove (main_view, main_view->children[0]); - view_insert (main_view, hud_view, 0); - } -} - -static void -viewsize_f (cvar_t *var) -{ - calc_sb_lines (var); + sb_view_size = view_size; + HUD_Calc_sb_lines (view_size); if (hud_sbar) { - SCR_SetBottomMargin (hud_sbar->int_val ? sb_lines : 0); + SCR_SetBottomMargin (hud_sbar ? hud_sb_lines : 0); } } @@ -1049,7 +988,7 @@ sbar_update_vis (void) sbar_view->visible = 0; - headsup = !(hud_sbar->int_val || r_data->scr_viewsize->int_val < 100); + headsup = !(hud_sbar || sb_view_size < 100); if ((sb_updates >= r_data->vid->numpages) && !headsup) return; @@ -1058,7 +997,7 @@ sbar_update_vis (void) && con_module->data->console->lines == r_data->vid->conview->ylen) return; // console is full screen - if (!sb_lines) + if (!hud_sb_lines) return; sbar_view->visible = 1; @@ -1074,7 +1013,7 @@ void Sbar_Draw (void) { sbar_update_vis (); - main_view->draw (main_view); + hud_main_view->draw (hud_main_view); } /* @@ -1098,10 +1037,10 @@ Sbar_LogFrags (void) const char *t = NULL; time_t tt = time (NULL); - if (!cl_fraglog->int_val) + if (!cl_fraglog) return; - if ((file = QFS_Open (fs_fraglog->string, "a")) == NULL) + if ((file = QFS_Open (fs_fraglog, "a")) == NULL) return; t = ctime (&tt); @@ -1158,7 +1097,7 @@ Sbar_LogFrags (void) } else { if (cl.teamplay) { team = malloc (strlen (s->team->value) + 1); - for (cp = (byte *) s->team->value, d = 0; *cp; cp++, d++) + for (cp = (byte *) s->team, d = 0; *cp; cp++, d++) team[d] = sys_char_map[*cp]; team[d] = 0; @@ -1414,25 +1353,19 @@ Sbar_Draw_DMO_Ping_UID (view_t *view, int l, int y, int skip) } void -Sbar_DMO_Init_f (cvar_t *var) +Sbar_DMO_Init_f (void *data, const cvar_t *cvar) { - // "var" is "hud_scoreboard_uid" - if (!var) { - Sbar_Draw_DMO_func = Sbar_Draw_DMO_Ping; - return; - } - if (cl.teamplay) - if (var->int_val > 1) + if (hud_scoreboard_uid > 1) Sbar_Draw_DMO_func = Sbar_Draw_DMO_Team_Ping_UID; - else if (var->int_val > 0) + else if (hud_scoreboard_uid > 0) Sbar_Draw_DMO_func = Sbar_Draw_DMO_Team_UID; else Sbar_Draw_DMO_func = Sbar_Draw_DMO_Team_Ping; else - if (var->int_val > 1) + if (hud_scoreboard_uid > 1) Sbar_Draw_DMO_func = Sbar_Draw_DMO_Ping_UID; - else if (var->int_val > 0) + else if (hud_scoreboard_uid > 0) Sbar_Draw_DMO_func = Sbar_Draw_DMO_UID; else Sbar_Draw_DMO_func = Sbar_Draw_DMO_Ping; @@ -1572,10 +1505,10 @@ draw_time (view_t *view) # define HOUR24 "%k" # define PM "%P" #endif - if (hud_time->int_val == 1) { // Use international format + if (hud_time == 1) { // Use international format strftime (st, sizeof (st), HOUR24":%M", local); draw_string (view, 8, 0, st); - } else if (hud_time->int_val >= 2) { // US AM/PM display + } else if (hud_time >= 2) { // US AM/PM display strftime (st, sizeof (st), HOUR12":%M "PM, local); draw_string (view, 8, 0, st); } @@ -1608,17 +1541,17 @@ draw_net (view_t *view) MSG_WriteByte (&cls.netchan.message, clc_stringcmd); SZ_Print (&cls.netchan.message, "pings"); } - if (hud_ping->int_val) { + if (hud_ping) { int ping = cl.players[cl.playernum].ping; ping = bound (0, ping, 999); draw_string (view, 0, 0, va (0, "%3d ms ", ping)); } - if (hud_ping->int_val && hud_pl->int_val) + if (hud_ping && hud_pl) draw_character (view, 48, 0, '/'); - if (hud_pl->int_val) { + if (hud_pl) { int lost = CL_CalcNet (); lost = bound (0, lost, 999); @@ -1629,11 +1562,11 @@ draw_net (view_t *view) static void draw_stuff (view_t *view) { - if (hud_time->int_val > 0) + if (hud_time > 0) draw_time (view); - if (hud_fps->int_val > 0) + if (hud_fps > 0) draw_fps (view); - if (cls.state == ca_active && (hud_ping->int_val || hud_pl->int_val)) + if (cls.state == ca_active && (hud_ping || hud_pl)) draw_net (view); } @@ -1644,9 +1577,9 @@ Sbar_IntermissionOverlay (void) r_data->scr_fullupdate = 0; if (cl.teamplay > 0 && !sb_showscores) - Sbar_TeamOverlay (overlay_view); + Sbar_TeamOverlay (hud_overlay_view); else - Sbar_DeathmatchOverlay (overlay_view, 0); + Sbar_DeathmatchOverlay (hud_overlay_view, 0); } /* CENTER PRINTING */ @@ -1670,7 +1603,7 @@ Sbar_CenterPrint (const char *str) dstring_copystr (¢er_string, str); - centertime_off = scr_centertime->value; + centertime_off = scr_centertime; centertime_start = realtime; // count the number of lines for centering @@ -1724,10 +1657,10 @@ Sbar_FinaleOverlay (void) r_data->scr_copyeverything = 1; - draw_cachepic (overlay_view, 0, 16, "gfx/finale.lmp", 1); + draw_cachepic (hud_overlay_view, 0, 16, "gfx/finale.lmp", 1); // the finale prints the characters one at a time - remaining = scr_printspeed->value * (realtime - centertime_start); - Sbar_DrawCenterString (overlay_view, remaining); + remaining = scr_printspeed * (realtime - centertime_start); + Sbar_DrawCenterString (hud_overlay_view, remaining); } void @@ -1739,7 +1672,7 @@ Sbar_DrawCenterPrint (void) if (centertime_off <= 0) return; - Sbar_DrawCenterString (overlay_view, -1); + Sbar_DrawCenterString (hud_overlay_view, -1); } static void @@ -1901,33 +1834,33 @@ init_hud_views (void) view_add (hud_view, hud_armament_view); - view_insert (main_view, hud_view, 0); + view_insert (hud_main_view, hud_view, 0); } static void init_views (void) { - main_view = view_new (0, 0, r_data->vid->conview->xlen, + hud_main_view = view_new (0, 0, r_data->vid->conview->xlen, r_data->vid->conview->ylen, grav_northwest); if (con_module) - view_insert (con_module->data->console->view, main_view, 0); - main_view->resize_x = 1; // get resized if the 2d view resizes - main_view->resize_y = 1; - main_view->visible = 0; // but don't let the console draw our stuff + view_insert (con_module->data->console->view, hud_main_view, 0); + hud_main_view->resize_x = 1; // get resized if the 2d view resizes + hud_main_view->resize_y = 1; + hud_main_view->visible = 0; // but don't let the console draw our stuff if (r_data->vid->conview->ylen > 300) - overlay_view = view_new (0, 0, 320, 300, grav_center); + hud_overlay_view = view_new (0, 0, 320, 300, grav_center); else - overlay_view = view_new (0, 0, 320, r_data->vid->conview->ylen, + hud_overlay_view = view_new (0, 0, 320, r_data->vid->conview->ylen, grav_center); - overlay_view->draw = draw_overlay; - overlay_view->visible = 0; + hud_overlay_view->draw = draw_overlay; + hud_overlay_view->visible = 0; - stuff_view = view_new (0, 48, 152, 16, grav_southwest); - stuff_view->draw = draw_stuff; + hud_stuff_view = view_new (0, 48, 152, 16, grav_southwest); + hud_stuff_view->draw = draw_stuff; - view_insert (main_view, overlay_view, 0); - view_insert (main_view, stuff_view, 0); + view_insert (hud_main_view, hud_overlay_view, 0); + view_insert (hud_main_view, hud_stuff_view, 0); init_sbar_views (); init_hud_views (); @@ -2052,29 +1985,13 @@ Sbar_Init (void) r_data->viewsize_callback = viewsize_f; - hud_scoreboard_uid = Cvar_Get ("hud_scoreboard_uid", "0", CVAR_NONE, - Sbar_DMO_Init_f, "Set to 1 to show uid " - "instead of ping. Set to 2 to show both."); - fs_fraglog = Cvar_Get ("fs_fraglog", "qw-scores.log", CVAR_ARCHIVE, NULL, - "Filename of the automatic frag-log."); - cl_fraglog = Cvar_Get ("cl_fraglog", "0", CVAR_ARCHIVE, NULL, - "Automatic fraglogging, non-zero value will switch " - "it on."); - hud_sbar = Cvar_Get ("hud_sbar", "0", CVAR_ARCHIVE, hud_sbar_f, - "status bar mode: 0 = hud, 1 = oldstyle"); - hud_swap = Cvar_Get ("hud_swap", "0", CVAR_ARCHIVE, hud_swap_f, - "new HUD on left side?"); - hud_scoreboard_gravity = Cvar_Get ("hud_scoreboard_gravity", "center", - CVAR_ARCHIVE, hud_scoreboard_gravity_f, - "control placement of scoreboard " - "overlay: center, northwest, north, " - "northeast, west, east, southwest, " - "south, southeast"); - scr_centertime = Cvar_Get ("scr_centertime", "2", CVAR_NONE, NULL, "How " - "long in seconds screen hints are displayed"); - scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_NONE, NULL, - "How fast the text is displayed at the end of " - "the single player episodes"); + HUD_Init_Cvars (); + + Cvar_Register (&hud_scoreboard_uid_cvar, Sbar_DMO_Init_f, 0); + Cvar_Register (&fs_fraglog_cvar, 0, 0); + Cvar_Register (&cl_fraglog_cvar, 0, 0); + Cvar_Register (&scr_centertime_cvar, 0, 0); + Cvar_Register (&scr_printspeed_cvar, 0, 0); // register GIB builtins GIB_Builtin_Add ("print::center", Sbar_GIB_Print_Center_f); diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index f9e99f0b5..d48ae705f 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -62,7 +62,15 @@ qboolean sv_allow_cheats; int fp_messages = 4, fp_persecond = 4, fp_secondsdead = 10; char fp_msg[255] = { 0 }; -cvar_t *sv_leetnickmatch; +int sv_leetnickmatch; +static cvar_t sv_leetnickmatch_cvar = { + .name = "sv_3133735_7h4n_7h0u", + .description = + "Match '1' as 'i' and such in nicks", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_leetnickmatch }, +}; static qboolean match_char (char a, char b) @@ -70,7 +78,7 @@ match_char (char a, char b) a = tolower ((byte) sys_char_map[(byte) a]); b = tolower ((byte) sys_char_map[(byte) b]); - if (a == b || (sv_leetnickmatch->int_val + if (a == b || (sv_leetnickmatch && ( (a == '1' && b == 'i') || (a == 'i' && b == '1') || (a == '1' && b == 'l') || (a == 'l' && b == '1') || (a == '3' && b == 'e') || (a == 'e' && b == '3') @@ -871,13 +879,12 @@ SV_SendServerInfoChange (const char *key, const char *value) } void -Cvar_Info (cvar_t *var) +Cvar_Info (void *data, const cvar_t *cvar) { - if (var->flags & CVAR_SERVERINFO) { - Info_SetValueForKey (svs.info, var->name, var->string, - (!sv_highchars || !sv_highchars->int_val)); - - SV_SendServerInfoChange (var->name, var->string); + if (cvar->flags & CVAR_SERVERINFO) { + const char *cvar_str = Cvar_VarString (cvar); + Info_SetValueForKey (svs.info, cvar->name, cvar_str, !sv_highchars); + SV_SendServerInfoChange (cvar->name, cvar_str); } } @@ -923,9 +930,9 @@ SV_Serverinfo_f (void) // if this is a cvar, change it too var = Cvar_FindVar (key); if (var && (var->flags & CVAR_SERVERINFO)) { - Cvar_Set (var, value); + Cvar_SetVar (var, value); } else { - Info_SetValueForKey (svs.info, key, value, !sv_highchars->int_val); + Info_SetValueForKey (svs.info, key, value, !sv_highchars); SV_SendServerInfoChange (key, value); } } @@ -939,7 +946,7 @@ SV_SetLocalinfo (const char *key, const char *value) oldvalue = strdup (Info_ValueForKey (localinfo, key)); if (*value) - Info_SetValueForKey (localinfo, key, value, !sv_highchars->int_val); + Info_SetValueForKey (localinfo, key, value, !sv_highchars); else Info_RemoveKey (localinfo, key); @@ -1049,7 +1056,7 @@ SV_Gamedir (void) } Info_SetValueForStarKey (svs.info, "*gamedir", dir, - !sv_highchars->int_val); + !sv_highchars); } /* @@ -1304,6 +1311,5 @@ SV_InitOperatorCommands (void) "commands do, so you can check safely"); // poor description - sv_leetnickmatch = Cvar_Get ("sv_3133735_7h4n_7h0u", "1", CVAR_NONE, NULL, - "Match '1' as 'i' and such in nicks"); + Cvar_Register (&sv_leetnickmatch_cvar, 0, 0); } diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index 47580b4e0..b0b8fb30c 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -66,26 +66,138 @@ static recorder_t *recorder; static int delta_sequence; #define MIN_DEMO_MEMORY 0x100000 -#define USECACHE (sv_demoUseCache->int_val && svs.demomemsize) +#define USECACHE (sv_demoUseCache && svs.demomemsize) #define DWRITE(a,b,d) dwrite((QFile *) d, a, b) static int demo_max_size; static int demo_size; -cvar_t *sv_demofps; -cvar_t *sv_demoPings; -cvar_t *sv_demoMaxSize; -static cvar_t *sv_demoUseCache; -static cvar_t *sv_demoCacheSize; -static cvar_t *sv_demoMaxDirSize; -static cvar_t *sv_demoDir; -static cvar_t *sv_demoNoVis; -static cvar_t *sv_demoPrefix; -static cvar_t *sv_demoSuffix; -static cvar_t *sv_onrecordfinish; -static cvar_t *sv_ondemoremove; -static cvar_t *sv_demotxt; -static cvar_t *serverdemo; +float sv_demofps; +static cvar_t sv_demofps_cvar = { + .name = "sv_demofps", + .description = + "FIXME", + .default_value = "20", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_demofps }, +}; +float sv_demoPings; +static cvar_t sv_demoPings_cvar = { + .name = "sv_demoPings", + .description = + "FIXME", + .default_value = "3", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_demoPings }, +}; +char *sv_demoMaxSize; +static cvar_t sv_demoMaxSize_cvar = { + .name = "sv_demoMaxSize", + .description = + "FIXME", + .default_value = "20480", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &sv_demoMaxSize }, +}; +static int sv_demoUseCache; +static cvar_t sv_demoUseCache_cvar = { + .name = "sv_demoUseCache", + .description = + "FIXME", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_demoUseCache }, +}; +static char *sv_demoCacheSize; +static cvar_t sv_demoCacheSize_cvar = { + .name = "sv_demoCacheSize", + .description = + "FIXME", + .default_value = 0, + .flags = CVAR_ROM, + .value = { .type = 0/* not used */, .value = &sv_demoCacheSize }, +}; +static char *sv_demoMaxDirSize; +static cvar_t sv_demoMaxDirSize_cvar = { + .name = "sv_demoMaxDirSize", + .description = + "FIXME", + .default_value = "102400", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &sv_demoMaxDirSize }, +}; +static char *sv_demoDir; +static cvar_t sv_demoDir_cvar = { + .name = "sv_demoDir", + .description = + "FIXME", + .default_value = "demos", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_demoDir }, +}; +static char *sv_demoNoVis; +static cvar_t sv_demoNoVis_cvar = { + .name = "sv_demoNoVis", + .description = + "FIXME", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &sv_demoNoVis }, +}; +static char *sv_demoPrefix; +static cvar_t sv_demoPrefix_cvar = { + .name = "sv_demoPrefix", + .description = + "FIXME", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_demoPrefix }, +}; +static char *sv_demoSuffix; +static cvar_t sv_demoSuffix_cvar = { + .name = "sv_demoSuffix", + .description = + "FIXME", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_demoSuffix }, +}; +static char *sv_onrecordfinish; +static cvar_t sv_onrecordfinish_cvar = { + .name = "sv_onrecordfinish", + .description = + "FIXME", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_onrecordfinish }, +}; +static char *sv_ondemoremove; +static cvar_t sv_ondemoremove_cvar = { + .name = "sv_ondemoremove", + .description = + "FIXME", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &sv_ondemoremove }, +}; +static int sv_demotxt; +static cvar_t sv_demotxt_cvar = { + .name = "sv_demotxt", + .description = + "FIXME", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_demotxt }, +}; +static char *serverdemo; +static cvar_t serverdemo_cvar = { + .name = "serverdemo", + .description = + "FIXME", + .default_value = "", + .flags = CVAR_SERVERINFO, + .value = { .type = 0, .value = &serverdemo }, +}; static int (*dwrite) (QFile * file, const void *buf, int count); @@ -113,10 +225,10 @@ demo_frame (void *unused) { double min_fps; - if (!sv_demofps->value) + if (!sv_demofps) min_fps = 20.0; else - min_fps = sv_demofps->value; + min_fps = sv_demofps; min_fps = max (4, min_fps); if (sv.time - demo_time < 1.0 / min_fps) return 0; @@ -177,13 +289,13 @@ SV_Stop (int reason) break; } /* - if (sv_onrecordfinish->string[0]) { + if (sv_onrecordfinish[0]) { extern redirect_t sv_redirected; int old = sv_redirected; char path[MAX_OSPATH]; char *p; - if ((p = strstr (sv_onrecordfinish->string, " ")) != NULL) + if ((p = strstr (sv_onrecordfinish, " ")) != NULL) *p = 0; // strip parameters strcpy (path, demo_name->str); @@ -192,8 +304,8 @@ SV_Stop (int reason) sv_redirected = RD_NONE; // onrecord script is called always // from the console Cmd_TokenizeString (va (0, "script %s \"%s\" \"%s\" \"%s\" %s", - sv_onrecordfinish->string, demo.path->str, - serverdemo->string, + sv_onrecordfinish, demo.path->str, + serverdemo, path, p != NULL ? p + 1 : "")); if (p) *p = ' '; @@ -202,7 +314,7 @@ SV_Stop (int reason) sv_redirected = old; } */ - Cvar_Set (serverdemo, ""); + Cvar_Set ("serverdemo", ""); } static void @@ -327,7 +439,7 @@ SV_PrintTeams (void) if (numcl == 2) { // duel dsprintf (buffer, "team1 %s\nteam2 %s\n", clients[0]->name, clients[1]->name); - } else if (!teamplay->int_val) { // ffa + } else if (!teamplay) { // ffa dsprintf (buffer, "players:\n"); for (i = 0; i < numcl; i++) dasprintf (buffer, " %s\n", clients[i]->name); @@ -373,12 +485,12 @@ SV_Record (char *name) SV_BroadcastPrintf (PRINT_CHAT, "Server started recording (%s):\n%s\n", demo_disk ? "disk" : "memory", QFS_SkipPath (demo_name->str)); - Cvar_Set (serverdemo, demo_name->str); + Cvar_Set ("serverdemo", demo_name->str); dstring_copystr (demo_text, name); strcpy (demo_text->str + strlen (demo_text->str) - 3, "txt"); - if (sv_demotxt->int_val) { + if (sv_demotxt) { QFile *f; f = QFS_Open (demo_text->str, "w+t"); @@ -390,8 +502,8 @@ SV_Record (char *name) strftime (date, sizeof (date), "%Y-%m-%d-%H-%M", localtime (&tim)); Qprintf (f, "date %s\nmap %s\nteamplay %d\ndeathmatch %d\n" "timelimit %d\n%s", - date, sv.name, teamplay->int_val, - deathmatch->int_val, timelimit->int_val, + date, sv.name, teamplay, + deathmatch, timelimit, SV_PrintTeams ()); Qclose (f); } @@ -629,9 +741,9 @@ SV_Record_f (void) if (recorder) SV_Stop (0); - dsprintf (name, "%s/%s/%s%s%s", qfs_gamedir->dir.def, sv_demoDir->string, - sv_demoPrefix->string, SV_CleanName (Cmd_Argv (1)), - sv_demoSuffix->string); + dsprintf (name, "%s/%s/%s%s%s", qfs_gamedir->dir.def, sv_demoDir, + sv_demoPrefix, SV_CleanName (Cmd_Argv (1)), + sv_demoSuffix); // open the demo file QFS_DefaultExtension (name, ".mvd"); @@ -733,7 +845,7 @@ SV_EasyRecord_f (void) else { // guess game type and write demo name i = Dem_CountPlayers (); - if (teamplay->int_val && i > 2) { + if (teamplay && i > 2) { // Teamplay dsprintf (name, "team_%s_vs_%s_%s", Dem_Team (1), Dem_Team (2), sv.name); @@ -751,10 +863,10 @@ SV_EasyRecord_f (void) // Make sure the filename doesn't contain illegal characters dsprintf (name2, "%s/%s%s%s%s%s", - qfs_gamedir->dir.def, sv_demoDir->string, - sv_demoDir->string[0] ? "/" : "", - sv_demoPrefix->string, SV_CleanName (name->str), - sv_demoSuffix->string); + qfs_gamedir->dir.def, sv_demoDir, + sv_demoDir[0] ? "/" : "", + sv_demoPrefix, SV_CleanName (name->str), + sv_demoSuffix); if ((demo_file = QFS_NextFile (name, name2->str, ".mvd"))) { SV_Record (name->str); @@ -790,25 +902,21 @@ Demo_Init (void) svs.demomem = Hunk_AllocName (0, size, "demo"); svs.demomemsize = size; demo_max_size = size - 0x80000; - - serverdemo = Cvar_Get ("serverdemo", "", CVAR_SERVERINFO, Cvar_Info, - "FIXME"); - sv_demofps = Cvar_Get ("sv_demofps", "20", CVAR_NONE, 0, "FIXME"); - sv_demoPings = Cvar_Get ("sv_demoPings", "3", CVAR_NONE, 0, "FIXME"); - sv_demoNoVis = Cvar_Get ("sv_demoNoVis", "1", CVAR_NONE, 0, "FIXME"); - sv_demoUseCache = Cvar_Get ("sv_demoUseCache", "0", CVAR_NONE, 0, "FIXME"); - sv_demoCacheSize = Cvar_Get ("sv_demoCacheSize", va (0, "%d", size / 1024), - CVAR_ROM, 0, "FIXME"); - sv_demoMaxSize = Cvar_Get ("sv_demoMaxSize", "20480", CVAR_NONE, 0, - "FIXME"); - sv_demoMaxDirSize = Cvar_Get ("sv_demoMaxDirSize", "102400", CVAR_NONE, 0, - "FIXME"); - sv_demoDir = Cvar_Get ("sv_demoDir", "demos", CVAR_NONE, 0, "FIXME"); - sv_demoPrefix = Cvar_Get ("sv_demoPrefix", "", CVAR_NONE, 0, "FIXME"); - sv_demoSuffix = Cvar_Get ("sv_demoSuffix", "", CVAR_NONE, 0, "FIXME"); - sv_onrecordfinish = Cvar_Get ("sv_onrecordfinish", "", CVAR_NONE, 0, "FIXME"); - sv_ondemoremove = Cvar_Get ("sv_ondemoremove", "", CVAR_NONE, 0, "FIXME"); - sv_demotxt = Cvar_Get ("sv_demotxt", "1", CVAR_NONE, 0, "FIXME"); + sv_demoCacheSize_cvar.default_value = nva ("%d", size / 1024); + Cvar_Register (&serverdemo_cvar, Cvar_Info, &serverdemo); + Cvar_Register (&sv_demofps_cvar, 0, 0); + Cvar_Register (&sv_demoPings_cvar, 0, 0); + Cvar_Register (&sv_demoNoVis_cvar, 0, 0); + Cvar_Register (&sv_demoUseCache_cvar, 0, 0); + Cvar_Register (&sv_demoCacheSize_cvar, 0, 0); + Cvar_Register (&sv_demoMaxSize_cvar, 0, 0); + Cvar_Register (&sv_demoMaxDirSize_cvar, 0, 0); + Cvar_Register (&sv_demoDir_cvar, 0, 0); + Cvar_Register (&sv_demoPrefix_cvar, 0, 0); + Cvar_Register (&sv_demoSuffix_cvar, 0, 0); + Cvar_Register (&sv_onrecordfinish_cvar, 0, 0); + Cvar_Register (&sv_ondemoremove_cvar, 0, 0); + Cvar_Register (&sv_demotxt_cvar, 0, 0); Cmd_AddCommand ("record", SV_Record_f, "FIXME"); Cmd_AddCommand ("easyrecord", SV_EasyRecord_f, "FIXME"); diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 6f0d9753f..29ba96c5a 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -377,7 +377,7 @@ SV_SpawnServer (const char *server) SV_FreeAllEdictLeafs (); SV_SetupUserCommands (); Info_SetValueForStarKey (svs.info, "*progs", va (0, "%i", sv_pr_state.crc), - !sv_highchars->int_val); + !sv_highchars); // leave slots at start for only clients sv.num_edicts = MAX_CLIENTS + 1; @@ -468,7 +468,7 @@ SV_SpawnServer (const char *server) SV_CreateBaseline (); sv.signon_buffer_size[sv.num_signon_buffers - 1] = sv.signon.cursize; - Info_SetValueForKey (svs.info, "map", sv.name, !sv_highchars->int_val); + Info_SetValueForKey (svs.info, "map", sv.name, !sv_highchars); Sys_MaskPrintf (SYS_dev, "Server spawned.\n"); if (sv_map_e->func) GIB_Event_Callback (sv_map_e, 1, server); @@ -477,14 +477,14 @@ SV_SpawnServer (const char *server) void SV_SetMoveVars (void) { - movevars.gravity = sv_gravity->value; - movevars.stopspeed = sv_stopspeed->value; - movevars.maxspeed = sv_maxspeed->value; - movevars.spectatormaxspeed = sv_spectatormaxspeed->value; - movevars.accelerate = sv_accelerate->value; - movevars.airaccelerate = sv_airaccelerate->value; - movevars.wateraccelerate = sv_wateraccelerate->value; - movevars.friction = sv_friction->value; - movevars.waterfriction = sv_waterfriction->value; + movevars.gravity = sv_gravity; + movevars.stopspeed = sv_stopspeed; + movevars.maxspeed = sv_maxspeed; + movevars.spectatormaxspeed = sv_spectatormaxspeed; + movevars.accelerate = sv_accelerate; + movevars.airaccelerate = sv_airaccelerate; + movevars.wateraccelerate = sv_wateraccelerate; + movevars.friction = sv_friction; + movevars.waterfriction = sv_waterfriction; movevars.entgravity = 1.0; } diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 1d81ff1af..651bb8ccf 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -122,74 +122,390 @@ qboolean rcon_from_user; double netdosexpire[DOSFLOODCMDS] = { 1, 1, 2, 0.9, 1, 5 }; double netdosvalues[DOSFLOODCMDS] = { 12, 1, 3, 1, 1, 1 }; -cvar_t *sv_mem_size; +float sv_mem_size; +static cvar_t sv_mem_size_cvar = { + .name = "sv_mem_size", + .description = + "Amount of memory (in MB) to allocate for the " + PACKAGE_NAME + " heap", + .default_value = "8", + .flags = CVAR_ROM, + .value = { .type = &cexpr_float, .value = &sv_mem_size }, +}; -cvar_t *sv_console_plugin; +char *sv_console_plugin; +static cvar_t sv_console_plugin_cvar = { + .name = "sv_console_plugin", + .description = + "Plugin used for the console", + .default_value = "server", + .flags = CVAR_ROM, + .value = { .type = 0, .value = &sv_console_plugin }, +}; -cvar_t *sv_allow_status; -cvar_t *sv_allow_log; -cvar_t *sv_allow_ping; +int sv_allow_status; +static cvar_t sv_allow_status_cvar = { + .name = "sv_allow_status", + .description = + "Allow remote status queries (qstat etc)", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_allow_status }, +}; +int sv_allow_log; +static cvar_t sv_allow_log_cvar = { + .name = "sv_allow_log", + .description = + "Allow remote logging", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_allow_log }, +}; +int sv_allow_ping; +static cvar_t sv_allow_ping_cvar = { + .name = "sv_allow_pings", + .description = + "Allow remote pings (qstat etc)", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_allow_ping }, +}; -cvar_t *sv_extensions; // Use the extended protocols +int sv_extensions; +static cvar_t sv_extensions_cvar = { + .name = "sv_extensions", + .description = + "Use protocol extensions for QuakeForge clients", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_extensions }, +}; -cvar_t *sv_mintic; // bound the size of the -cvar_t *sv_maxtic; // physics time tic +float sv_mintic; +static cvar_t sv_mintic_cvar = { + .name = "sv_mintic", + .description = + "The minimum amount of time the server will wait before sending " + "packets to a client. Set to .5 to make modem users happy", + .default_value = "0.03", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_mintic }, +}; +float sv_maxtic; +static cvar_t sv_maxtic_cvar = { + .name = "sv_maxtic", + .description = + "The maximum amount of time in seconds before a client a receives an " + "update from the server", + .default_value = "0.1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_maxtic }, +}; -cvar_t *sv_netdosprotect; // tone down DoS from quake servers +int sv_netdosprotect; +static cvar_t sv_netdosprotect_cvar = { + .name = "sv_netdosprotect", + .description = + "DoS flood attack protection", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_netdosprotect }, +}; -cvar_t *sv_timeout; // seconds without any message -cvar_t *zombietime; // seconds to sink messages after +float sv_timeout; +static cvar_t sv_timeout_cvar = { + .name = "timeout", + .description = + "Sets the amount of time in seconds before a client is considered " + "disconnected if the server does not receive a packet", + .default_value = "65", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_timeout }, +}; +float zombietime; +static cvar_t zombietime_cvar = { + .name = "zombietime", + .description = + "The number of seconds that the server will keep the character of a " + "player on the map who seems to have disconnected", + .default_value = "2", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &zombietime }, +}; // disconnect -cvar_t *rcon_password; // password for remote server -cvar_t *admin_password; // password for admin commands +char *rcon_password; +static cvar_t rcon_password_cvar = { + .name = "rcon_password", + .description = + "Set the password for rcon 'root' commands", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &rcon_password }, +}; +char *admin_password; +static cvar_t admin_password_cvar = { + .name = "admin_password", + .description = + "Set the password for rcon admin commands", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &admin_password }, +}; -cvar_t *password; // password for entering the game -cvar_t *spectator_password; // password for entering as a +char *password; +static cvar_t password_cvar = { + .name = "password", + .description = + "Set the server password for players", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &password }, +}; +char *spectator_password; +static cvar_t spectator_password_cvar = { + .name = "spectator_password", + .description = + "Set the spectator password", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &spectator_password }, +}; // spectator -cvar_t *allow_download; -cvar_t *allow_download_skins; -cvar_t *allow_download_models; -cvar_t *allow_download_sounds; -cvar_t *allow_download_maps; -cvar_t *allow_download_demos; +int allow_download; +static cvar_t allow_download_cvar = { + .name = "allow_download", + .description = + "Toggle if clients can download game data from the server", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &allow_download }, +}; +int allow_download_skins; +static cvar_t allow_download_skins_cvar = { + .name = "allow_download_skins", + .description = + "Toggle if clients can download skins from the server", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &allow_download_skins }, +}; +int allow_download_models; +static cvar_t allow_download_models_cvar = { + .name = "allow_download_models", + .description = + "Toggle if clients can download models from the server", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &allow_download_models }, +}; +int allow_download_sounds; +static cvar_t allow_download_sounds_cvar = { + .name = "allow_download_sounds", + .description = + "Toggle if clients can download sounds from the server", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &allow_download_sounds }, +}; +int allow_download_maps; +static cvar_t allow_download_maps_cvar = { + .name = "allow_download_maps", + .description = + "Toggle if clients can download maps from the server", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &allow_download_maps }, +}; +char *allow_download_demos; +static cvar_t allow_download_demos_cvar = { + .name = "allow_download_demos", + .description = + "Toggle if clients can download maps from the server", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &allow_download_demos }, +}; -cvar_t *sv_highchars; -cvar_t *sv_phs; +int sv_highchars; +static cvar_t sv_highchars_cvar = { + .name = "sv_highchars", + .description = + "Toggle the use of high character color names for players", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_highchars }, +}; +int sv_phs; +static cvar_t sv_phs_cvar = { + .name = "sv_phs", + .description = + "Possibly Hearable Set. If set to zero, the server calculates sound " + "hearability in realtime", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_phs }, +}; -cvar_t *pausable; +int pausable; +static cvar_t pausable_cvar = { + .name = "pausable", + .description = + "None", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &pausable }, +}; -cvar_t *sv_minqfversion; // Minimum QF version allowed to +char *sv_minqfversion; +static cvar_t sv_minqfversion_cvar = { + .name = "sv_minqfversion", + .description = + "Minimum QF version on client", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = 0, .value = &sv_minqfversion }, +}; // connect -cvar_t *sv_maxrate; // Maximum allowable rate (silently - // capped) -cvar_t *sv_timestamps; -cvar_t *sv_timefmt; +int sv_timestamps; +static cvar_t sv_timestamps_cvar = { + .name = "sv_timestamps", + .description = + "Time/date stamps in log entries", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_timestamps }, +}; +char *sv_timefmt; +static cvar_t sv_timefmt_cvar = { + .name = "sv_timefmt", + .description = + "Time/date format to use", + .default_value = "[%b %e %X] ", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_timefmt }, +}; // game rules mirrored in svs.info -cvar_t *fraglimit; -cvar_t *timelimit; -cvar_t *teamplay; -cvar_t *samelevel; -cvar_t *maxclients; -cvar_t *maxspectators; -cvar_t *deathmatch; // 0, 1, or 2 -cvar_t *coop; -cvar_t *skill; -cvar_t *spawn; -cvar_t *watervis; +char *fraglimit; +static cvar_t fraglimit_cvar = { + .name = "fraglimit", + .description = + "None", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = 0/* not used */, .value = &fraglimit }, +}; +int timelimit; +static cvar_t timelimit_cvar = { + .name = "timelimit", + .description = + "None", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &timelimit }, +}; +int teamplay; +static cvar_t teamplay_cvar = { + .name = "teamplay", + .description = + "None", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &teamplay }, +}; +char *samelevel; +static cvar_t samelevel_cvar = { + .name = "samelevel", + .description = + "None", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = 0/* not used */, .value = &samelevel }, +}; +int maxclients; +static cvar_t maxclients_cvar = { + .name = "maxclients", + .description = + "Sets how many clients can connect to your server, this includes " + "spectators and players", + .default_value = "8", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &maxclients }, +}; +int maxspectators; +static cvar_t maxspectators_cvar = { + .name = "maxspectators", + .description = + "Sets how many spectators can connect to your server. The maxclients " + "value takes precedence over this value so this value should always be" + " equal-to or less-then the maxclients value", + .default_value = "8", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &maxspectators }, +}; +int deathmatch; +static cvar_t deathmatch_cvar = { + .name = "deathmatch", + .description = + "0, 1, or 2", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &deathmatch }, +}; +int coop; +static cvar_t coop_cvar = { + .name = "coop", + .description = + "0 or 1", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &coop }, +}; +int skill; +static cvar_t skill_cvar = { + .name = "skill", + .description = + "0 - 3", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &skill }, +}; +char *spawn; +static cvar_t spawn_cvar = { + .name = "spawn", + .description = + "Spawn the player entity", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = 0/* not used */, .value = &spawn }, +}; +char *watervis; +static cvar_t watervis_cvar = { + .name = "watervis", + .description = + "Set nonzero to enable r_wateralpha on clients", + .default_value = "0", + .flags = CVAR_SERVERINFO, + .value = { .type = 0/* not used */, .value = &watervis }, +}; -cvar_t *hostname; +char *hostname; +static cvar_t hostname_cvar = { + .name = "hostname", + .description = + "None", + .default_value = "UNNAMED", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &hostname }, +}; QFile *sv_fraglogfile; -cvar_t *pr_gc; -cvar_t *pr_gc_interval; -int pr_gc_count = 0; - int sv_net_initialized; const char *client_info_filters[] = { // Info keys needed by client @@ -479,7 +795,7 @@ CheckForFlood (flood_enum_t cmdtype) int oldest, i; static qboolean firsttime = true; - if (!sv_netdosprotect->int_val) + if (!sv_netdosprotect) return 0; oldestTime = 0x7fffffff; @@ -545,7 +861,7 @@ SVC_Status (void) client_t *cl; int ping, bottom, top, i; - if (!sv_allow_status->int_val) + if (!sv_allow_status) return; if (CheckForFlood (FLOOD_STATUS)) return; @@ -610,7 +926,7 @@ SVC_Log (void) char data[MAX_DATAGRAM + 64]; int seq; - if (!sv_allow_log->int_val) + if (!sv_allow_log) return; if (CheckForFlood (FLOOD_LOG)) return; @@ -650,7 +966,7 @@ SVC_Ping (void) { char data; - if (!sv_allow_ping->int_val) + if (!sv_allow_ping) return; if (CheckForFlood (FLOOD_PING)) return; @@ -696,7 +1012,7 @@ SVC_GetChallenge (void) i = oldest; } - if (sv_extensions->int_val) { + if (sv_extensions) { extended = " QF qtv EXT"; } @@ -730,8 +1046,8 @@ SV_AllocClient (int spectator, int server) // if at server limits, refuse connection if (!free || - (!server && ((spectator && spectators >= maxspectators->int_val) - || (!spectator && clients >= maxclients->int_val)))) { + (!server && ((spectator && spectators >= maxspectators) + || (!spectator && clients >= maxclients)))) { return 0; } // find a client slot @@ -789,7 +1105,7 @@ SVC_DirectConnect (void) if (strlen (Cmd_Argv (4)) < MAX_INFO_STRING) userinfo = Info_ParseString (Cmd_Argv (4), 1023, - !sv_highchars->int_val); + !sv_highchars); // Validate the userinfo string. if (!userinfo) { @@ -819,25 +1135,25 @@ SVC_DirectConnect (void) } s = Info_ValueForKey (userinfo, "*qf_version"); - if ((!s[0]) || sv_minqfversion->string[0]) { // kick old clients? - if (ver_compare (s, sv_minqfversion->string) < 0) { + if ((!s[0]) || sv_minqfversion[0]) { // kick old clients? + if (ver_compare (s, sv_minqfversion) < 0) { SV_Printf ("%s: Version %s is less than minimum version %s.\n", NET_AdrToString (net_from), s, - sv_minqfversion->string); + sv_minqfversion); SV_OutOfBandPrint (net_from, "%c\nserver requires QuakeForge " "v%s or greater. Get it from " "http://www.quakeforge.net/\n", A2C_PRINT, - sv_minqfversion->string); + sv_minqfversion); return; } } // check for password or spectator_password s = Info_ValueForKey (userinfo, "spectator"); if (s[0] && strcmp (s, "0")) { - if (spectator_password->string[0] && - !strcaseequal (spectator_password->string, "none") && - !strequal (spectator_password->string, s)) { // failed + if (spectator_password[0] && + !strcaseequal (spectator_password, "none") && + !strequal (spectator_password, s)) { // failed SV_Printf ("%s: spectator password failed\n", NET_AdrToString (net_from)); SV_OutOfBandPrint (net_from, @@ -847,13 +1163,13 @@ SVC_DirectConnect (void) } Info_RemoveKey (userinfo, "spectator"); // remove passwd Info_SetValueForStarKey (userinfo, "*spectator", "1", - !sv_highchars->int_val); + !sv_highchars); spectator = true; } else { s = Info_ValueForKey (userinfo, "password"); - if (password->string[0] - && !strcaseequal (password->string, "none") - && !strequal (password->string, s)) { + if (password[0] + && !strcaseequal (password, "none") + && !strequal (password, s)) { SV_Printf ("%s:password failed\n", NET_AdrToString (net_from)); SV_OutOfBandPrint (net_from, "%c\nserver requires a password\n\n", @@ -948,12 +1264,12 @@ SVC_DirectConnect (void) } static int -Rcon_Validate (cvar_t *pass) +Rcon_Validate (const char *pass) { - if (!strlen (pass->string)) + if (!strlen (pass)) return 0; - if (strcmp (Cmd_Argv (1), pass->string)) + if (strcmp (Cmd_Argv (1), pass)) return 0; return 1; @@ -1146,8 +1462,28 @@ typedef struct { #define MAX_IPFILTERS 1024 -cvar_t *filterban; -cvar_t *sv_filter_automask; +int filterban; +static cvar_t filterban_cvar = { + .name = "filterban", + .description = + "Determines the rules for the IP list 0 Only IP addresses on the Ban " + "list will be allowed onto the server, 1 Only IP addresses NOT on the " + "Ban list will be allowed onto the server", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &filterban }, +}; +int sv_filter_automask; +static cvar_t sv_filter_automask_cvar = { + .name = "sv_filter_automask", + .description = + "Automatically determine the mask length when it is not explicitely " + "given. e.g. \"addip 1.2.0.0\" would be the same as \"addip " + "1.2.0.0/16\"", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_filter_automask }, +}; int numipfilters; ipfilter_t ipfilters[MAX_IPFILTERS]; unsigned int ipmasks[33]; // network byte order @@ -1314,7 +1650,7 @@ SV_StringToFilter (const char *address, ipfilter_t *f) // change trailing 0 segments to be a mask, eg 1.2.0.0 gives a /16 mask if (mask == -1) { - if (sv_filter_automask->int_val) { + if (sv_filter_automask) { mask = sizeof (b) * 8; i = sizeof (b); while (i > 0 && !b[i - 1]) { @@ -1563,7 +1899,7 @@ SV_netDoSexpire_f (void) for (i = 0; i < DOSFLOODCMDS; i++) SV_Printf ("%f ", netdosexpire[i]); SV_Printf ("\n"); - if (!sv_netdosprotect->int_val) + if (!sv_netdosprotect) SV_Printf ("(disabled)\n"); return; } @@ -1592,7 +1928,7 @@ SV_netDoSvalues_f (void) for (i = 0; i < DOSFLOODCMDS; i++) SV_Printf ("%f ", netdosvalues[i]); SV_Printf ("\n"); - if (!sv_netdosprotect->int_val) + if (!sv_netdosprotect) SV_Printf ("(disabled)\n"); return; } @@ -1611,33 +1947,6 @@ SV_netDoSvalues_f (void) return; } -static void -SV_MaxRate_f (cvar_t *var) -{ - client_t *cl; - int maxrate = var->int_val; - int i, rate = 2500; - const char *val; - - Cvar_Info (var); - for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { - if (!cl->userinfo) - continue; - val = Info_ValueForKey (cl->userinfo, "rate"); - if (strlen (val)) { - rate = atoi (val); - - if (maxrate) { - rate = bound (500, rate, maxrate); - } else { - rate = max (500, rate); - } - cl->netchan.rate = 1.0 / rate; - } - SV_ClientPrintf (1, cl, PRINT_HIGH, "Net rate set to %i\n", rate); - } -} - static void SV_SendBan (double till) { @@ -1680,7 +1989,7 @@ SV_FilterIP (byte *ip, double *until) if (SV_MaskIPCompare (ip, ipfilters[i].ip, ipfilters[i].mask)) { if (!ipfilters[i].time) { // normal ban - return filterban->int_val; + return filterban; } else if (ipfilters[i].time > realtime) { *until = ipfilters[i].time; return true; // banned no matter what @@ -1691,7 +2000,7 @@ SV_FilterIP (byte *ip, double *until) } } } - return !filterban->int_val; + return !filterban; } void @@ -1746,7 +2055,7 @@ SV_RestorePenaltyFilter (client_t *cl, filtertype_t type) void SV_OutOfBand (netadr_t adr, unsigned length, byte *data) { - if (net_packetlog->int_val) { + if (net_packetlog) { Log_Outgoing_Packet (data, length, 0); } Netchan_OutOfBand (adr, length, data); @@ -1779,7 +2088,7 @@ SV_ReadPackets (void) double until; while (NET_GetPacket ()) { - if (net_packetlog->int_val) + if (net_packetlog) Log_Incoming_Packet (net_message->message->data, net_message->message->cursize, 1); if (SV_FilterIP (net_from.ip, &until)) { @@ -1857,7 +2166,7 @@ SV_CheckTimeouts (void) float droptime; int nclients, i; - droptime = realtime - sv_timeout->value; + droptime = realtime - sv_timeout; nclients = 0; for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { @@ -1872,7 +2181,7 @@ SV_CheckTimeouts (void) } } if (cl->state == cs_zombie && - realtime - cl->connection_started > zombietime->value) { + realtime - cl->connection_started > zombietime) { cl->state = cs_free; // can now be reused svs.num_clients--; } @@ -1893,10 +2202,10 @@ SV_CheckVars (void) static char const *pw, *spw; int v; - if (password->string == pw && spectator_password->string == spw) + if (password == pw && spectator_password == spw) return; - pw = password->string; - spw = spectator_password->string; + pw = password; + spw = spectator_password; v = 0; if (pw && pw[0] && strcmp (pw, "none")) @@ -1907,23 +2216,10 @@ SV_CheckVars (void) SV_Printf ("Updated needpass.\n"); if (!v) Info_SetValueForKey (svs.info, "needpass", "", - !sv_highchars->int_val); + !sv_highchars); else Info_SetValueForKey (svs.info, "needpass", va (0, "%i", v), - !sv_highchars->int_val); -} - -/* - SV_GarbageCollect - - Run string GC on progs every pr_gc_interval frames - - //snax: run QFobject GC as well -*/ -static void -SV_GarbageCollect (void) -{ - //Object_Garbage_Collect (); + !sv_highchars); } void @@ -1959,12 +2255,12 @@ SV_Frame (float time) // don't bother running a frame if sys_ticrate seconds haven't passed sv_frametime = sv.time - old_time; if (sv_frametime < 0) { - old_time = sv.time - sv_mintic->value; - sv_frametime = sv_mintic->value; + old_time = sv.time - sv_mintic; + sv_frametime = sv_mintic; } - if (sv_frametime >= sv_mintic->value) { - if (sv_frametime > sv_maxtic->value) - sv_frametime = sv_maxtic->value; + if (sv_frametime >= sv_mintic) { + if (sv_frametime > sv_maxtic) + sv_frametime = sv_maxtic; old_time = sv.time; *sv_globals.frametime = sv_frametime; @@ -2001,8 +2297,6 @@ SV_Frame (float time) // send a heartbeat to the master if needed Master_Heartbeat (); - SV_GarbageCollect (); - // collect timing statistics end = Sys_DoubleTime (); svs.stats.active += end - start; @@ -2021,34 +2315,26 @@ SV_Frame (float time) } static void -maxspectators_f (cvar_t *var) +maxspectators_f (void *data, const cvar_t *cvar) { - if (var->int_val > MAX_CLIENTS) - Cvar_SetValue (var, maxclients->int_val); - else if (var->int_val + maxclients->int_val > MAX_CLIENTS) - Cvar_SetValue (var, MAX_CLIENTS - maxclients->int_val); - else if (var->int_val < 0) - Cvar_SetValue (var, 0); - else if (var->int_val != var->value) - Cvar_SetValue (var, var->int_val); - else - Cvar_Info (var); + if (maxspectators > MAX_CLIENTS) + maxspectators = maxclients; + else if (maxspectators + maxclients > MAX_CLIENTS) + maxspectators = MAX_CLIENTS - maxclients; + else if (maxspectators < 0) + maxspectators = 0; + Cvar_Info (data, cvar); } static void -maxclients_f (cvar_t *var) +maxclients_f (void *data, const cvar_t *cvar) { - if (var->int_val > MAX_CLIENTS) - Cvar_SetValue (var, MAX_CLIENTS); - else if (var->int_val < 1) - Cvar_SetValue (var, 1); - else if (var->int_val != var->value) - Cvar_SetValue (var, var->int_val); - else { - Cvar_Info (var); - if (maxspectators) - maxspectators_f (maxspectators); - } + if (maxclients > MAX_CLIENTS) + maxclients = MAX_CLIENTS; + else if (maxclients < 1) + maxclients = 1; + Cvar_Info (data, cvar); + maxspectators_f (0, &maxspectators_cvar); } static void @@ -2070,172 +2356,45 @@ SV_InitLocal (void) SV_UserInit (); - rcon_password = Cvar_Get ("rcon_password", "", CVAR_NONE, NULL, "Set the " - "password for rcon 'root' commands"); - admin_password = Cvar_Get ("admin_password", "", CVAR_NONE, NULL, "Set " - "the password for rcon admin commands"); - password = Cvar_Get ("password", "", CVAR_NONE, NULL, "Set the server " - "password for players"); - spectator_password = Cvar_Get ("spectator_password", "", CVAR_NONE, NULL, - "Set the spectator password"); - sv_mintic = Cvar_Get ("sv_mintic", "0.03", CVAR_NONE, NULL, "The minimum " - "amount of time the server will wait before sending " - "packets to a client. Set to .5 to make modem users " - "happy"); - sv_maxtic = Cvar_Get ("sv_maxtic", "0.1", CVAR_NONE, NULL, "The maximum " - "amount of time in seconds before a client a " - "receives an update from the server"); - fraglimit = Cvar_Get ("fraglimit", "0", CVAR_SERVERINFO, Cvar_Info, - "Amount of frags a player must attain in order to " - "exit the level"); - timelimit = Cvar_Get ("timelimit", "0", CVAR_SERVERINFO, Cvar_Info, - "Sets the amount of time in minutes that is needed " - "before advancing to the next level"); - teamplay = Cvar_Get ("teamplay", "0", CVAR_SERVERINFO, Cvar_Info, - "Determines teamplay rules. 0 off, 1 You cannot hurt " - "yourself nor your teammates, 2 You can hurt " - "yourself, your teammates, and you will lose one " - "frag for killing a teammate, 3 You can hurt " - "yourself but you cannot hurt your teammates"); - samelevel = Cvar_Get ("samelevel", "0", CVAR_SERVERINFO, Cvar_Info, - "Determines the rules for level changing and " - "exiting. 0 Allows advancing to the next level," - "1 The same level will be played until someone " - "exits, 2 The same level will be played and the " - "exit will kill anybody that tries to exit, 3 The " - "same level will be played and the exit will kill " - "anybody that tries to exit, except on the Start " - "map."); - maxclients = Cvar_Get ("maxclients", "8", CVAR_SERVERINFO, maxclients_f, - "Sets how many clients can connect to your " - "server, this includes spectators and players"); - maxspectators = Cvar_Get ("maxspectators", "8", CVAR_SERVERINFO, - maxspectators_f, - "Sets how many spectators can connect to your " - "server. The maxclients value takes precedence " - "over this value so this value should always be " - "equal-to or less-then the maxclients value"); - hostname = Cvar_Get ("hostname", "unnamed", CVAR_SERVERINFO, Cvar_Info, - "Report or sets the server name"); - deathmatch = Cvar_Get ("deathmatch", "1", CVAR_SERVERINFO, Cvar_Info, - "Sets the rules for weapon and item respawning. " - "1 Does not leave weapons on the map. You can " - "pickup weapons and items and they will respawn, " - "2 Leaves weapons on the map. You can pick up a " - "weapon only once. Picked up items will not " - "respawn, 3 Leaves weapons on the map. You can " - "pick up a weapon only once. Picked up items will " - "respawn."); - coop = Cvar_Get ("coop", "0", CVAR_NONE, NULL, "co-op mode for progs that " - "support it"); - skill = Cvar_Get ("skill", "0", CVAR_NONE, NULL, "skill setting for progs " - "that support it"); - spawn = Cvar_Get ("spawn", "0", CVAR_SERVERINFO, Cvar_Info, - "Spawn the player entity"); - watervis = Cvar_Get ("watervis", "0", CVAR_SERVERINFO, Cvar_Info, - "Set nonzero to enable r_wateralpha on clients"); - sv_timeout = Cvar_Get ("timeout", "65", CVAR_NONE, NULL, "Sets the amount " - "of time in seconds before a client is considered " - "disconnected if the server does not receive a " - "packet"); - zombietime = Cvar_Get ("zombietime", "2", CVAR_NONE, NULL, "The number of " - "seconds that the server will keep the character " - "of a player on the map who seems to have " - "disconnected"); - sv_maxvelocity = Cvar_Get ("sv_maxvelocity", "2000", CVAR_NONE, NULL, - "Sets the maximum velocity an object can " - "travel"); - sv_extensions = Cvar_Get ("sv_extensions", "1", CVAR_NONE, NULL, - "Use protocol extensions for QuakeForge " - "clients"); - sv_gravity = Cvar_Get ("sv_gravity", "800", CVAR_NONE, NULL, - "Sets the global value for the amount of gravity"); - sv_jump_any = Cvar_Get ("sv_jump_any", "1", CVAR_NONE, NULL, "None"); - sv_stopspeed = Cvar_Get ("sv_stopspeed", "100", CVAR_NONE, NULL, - "Sets the value that determines how fast the " - "player should come to a complete stop"); - sv_maxspeed = Cvar_Get ("sv_maxspeed", "320", CVAR_NONE, NULL, - "Sets the maximum speed a player can move"); - sv_spectatormaxspeed = Cvar_Get ("sv_spectatormaxspeed", "500", CVAR_NONE, - NULL, "Sets the maximum speed a " - "spectator can move"); - sv_accelerate = Cvar_Get ("sv_accelerate", "10", CVAR_NONE, NULL, - "Sets the acceleration value for the players"); - sv_airaccelerate = Cvar_Get ("sv_airaccelerate", "0.7", CVAR_NONE, NULL, - "Sets how quickly the players accelerate in " - "air"); - sv_wateraccelerate = Cvar_Get ("sv_wateraccelerate", "10", CVAR_NONE, NULL, - "Sets the water acceleration value"); - sv_friction = Cvar_Get ("sv_friction", "4", CVAR_NONE, NULL, - "Sets the friction value for the players"); - sv_waterfriction = Cvar_Get ("sv_waterfriction", "4", CVAR_NONE, NULL, - "Sets the water friction value"); - sv_aim = Cvar_Get ("sv_aim", "2", CVAR_NONE, NULL, - "Sets the value for auto-aiming leniency"); - sv_minqfversion = Cvar_Get ("sv_minqfversion", "0", CVAR_SERVERINFO, - Cvar_Info, "Minimum QF version on client"); - sv_maxrate = Cvar_Get ("sv_maxrate", "10000", CVAR_SERVERINFO, SV_MaxRate_f, - "Maximum allowable rate"); - sv_allow_log = Cvar_Get ("sv_allow_log", "1", CVAR_NONE, NULL, - "Allow remote logging"); - sv_allow_status = Cvar_Get ("sv_allow_status", "1", CVAR_NONE, NULL, - "Allow remote status queries (qstat etc)"); - sv_allow_ping = Cvar_Get ("sv_allow_pings", "1", CVAR_NONE, NULL, - "Allow remote pings (qstat etc)"); - sv_netdosprotect = Cvar_Get ("sv_netdosprotect", "0", CVAR_NONE, NULL, - "DoS flood attack protection"); - sv_timestamps = Cvar_Get ("sv_timestamps", "0", CVAR_NONE, NULL, - "Time/date stamps in log entries"); - sv_timefmt = Cvar_Get ("sv_timefmt", "[%b %e %X] ", CVAR_NONE, NULL, - "Time/date format to use"); - filterban = Cvar_Get ("filterban", "1", CVAR_NONE, NULL, - "Determines the rules for the IP list " - "0 Only IP addresses on the Ban list will be " - "allowed onto the server, 1 Only IP addresses NOT " - "on the Ban list will be allowed onto the server"); - sv_filter_automask = Cvar_Get ("sv_filter_automask", "1", CVAR_NONE, NULL, - "Automatically determine the mask length " - "when it is not explicitely given. e.g. " - "\"addip 1.2.0.0\" would be the same as " - "\"addip 1.2.0.0/16\""); - allow_download = Cvar_Get ("allow_download", "1", CVAR_NONE, NULL, - "Toggle if clients can download game data from " - "the server"); - allow_download_skins = Cvar_Get ("allow_download_skins", "1", CVAR_NONE, - NULL, "Toggle if clients can download " - "skins from the server"); - allow_download_models = Cvar_Get ("allow_download_models", "1", CVAR_NONE, - NULL, "Toggle if clients can download " - "models from the server"); - allow_download_sounds = Cvar_Get ("allow_download_sounds", "1", CVAR_NONE, - NULL, "Toggle if clients can download " - "sounds from the server"); - allow_download_maps = Cvar_Get ("allow_download_maps", "1", CVAR_NONE, - NULL, "Toggle if clients can download " - "maps from the server"); - allow_download_demos = Cvar_Get ("allow_download_demos", "1", CVAR_NONE, - NULL, "Toggle if clients can download " - "maps from the server"); - sv_highchars = Cvar_Get ("sv_highchars", "1", CVAR_NONE, NULL, - "Toggle the use of high character color names " - "for players"); - sv_phs = Cvar_Get ("sv_phs", "1", CVAR_NONE, NULL, "Possibly Hearable " - "Set. If set to zero, the server calculates sound " - "hearability in realtime"); - pausable = Cvar_Get ("pausable", "1", CVAR_NONE, NULL, - "Toggle if server can be paused 1 is on, 0 is off"); - pr_gc = Cvar_Get ("pr_gc", "2", CVAR_NONE, NULL, "Enable/disable the " - "garbage collector. 0 is off, 1 is on, 2 is auto (on " - "for newer qfcc progs, off otherwise)"); - pr_gc_interval = Cvar_Get ("pr_gc_interval", "50", CVAR_NONE, NULL, - "Number of frames to wait before running " - "string garbage collector."); - pr_double_remove = Cvar_Get ("pr_double_remove", "1", CVAR_NONE, NULL, - "Handling of double entity remove. " - "0 is silently ignore, 1 prints a " - "traceback, and 2 gives an error.\n" - "works Only if debugging is available " - "and enabled"); + Cvar_Register (&rcon_password_cvar, 0, 0); + Cvar_Register (&admin_password_cvar, 0, 0); + Cvar_Register (&password_cvar, 0, 0); + Cvar_Register (&spectator_password_cvar, 0, 0); + Cvar_Register (&sv_mintic_cvar, 0, 0); + Cvar_Register (&sv_maxtic_cvar, 0, 0); + Cvar_Register (&fraglimit_cvar, Cvar_Info, &fraglimit); + Cvar_Register (&timelimit_cvar, Cvar_Info, &timelimit); + Cvar_Register (&teamplay_cvar, Cvar_Info, &teamplay); + Cvar_Register (&samelevel_cvar, 0, 0); + Cvar_Register (&maxclients_cvar, maxclients_f, 0); + Cvar_Register (&maxspectators_cvar, maxspectators_f, 0); + Cvar_Register (&hostname_cvar, 0, 0); + Cvar_Register (&deathmatch_cvar, 0, 0); + Cvar_Register (&coop_cvar, 0, 0); + Cvar_Register (&skill_cvar, 0, 0); + Cvar_Register (&spawn_cvar, Cvar_Info, &spawn); + Cvar_Register (&watervis_cvar, Cvar_Info, &watervis); + Cvar_Register (&sv_timeout_cvar, 0, 0); + Cvar_Register (&zombietime_cvar, 0, 0); + Cvar_Register (&sv_extensions_cvar, 0, 0); + Cvar_Register (&sv_minqfversion_cvar, Cvar_Info, &sv_minqfversion); + Cvar_Register (&sv_allow_log_cvar, 0, 0); + Cvar_Register (&sv_allow_status_cvar, 0, 0); + Cvar_Register (&sv_allow_ping_cvar, 0, 0); + Cvar_Register (&sv_netdosprotect_cvar, 0, 0); + Cvar_Register (&sv_timestamps_cvar, 0, 0); + Cvar_Register (&sv_timefmt_cvar, 0, 0); + Cvar_Register (&filterban_cvar, 0, 0); + Cvar_Register (&sv_filter_automask_cvar, 0, 0); + Cvar_Register (&allow_download_cvar, 0, 0); + Cvar_Register (&allow_download_skins_cvar, 0, 0); + Cvar_Register (&allow_download_models_cvar, 0, 0); + Cvar_Register (&allow_download_sounds_cvar, 0, 0); + Cvar_Register (&allow_download_maps_cvar, 0, 0); + Cvar_Register (&allow_download_demos_cvar, 0, 0); + Cvar_Register (&sv_highchars_cvar, 0, 0); + Cvar_Register (&sv_phs_cvar, 0, 0); + Cvar_Register (&pausable_cvar, 0, 0); // DoS protection Cmd_AddCommand ("netdosexpire", SV_netDoSexpire_f, "FIXME: part of DoS " "protection obviously, but I don't know what it does. No " @@ -2257,13 +2416,13 @@ SV_InitLocal (void) snprintf (localmodels[i], sizeof (localmodels[i]), "*%i", i); Info_SetValueForStarKey (svs.info, "*version", QW_VERSION, - !sv_highchars->int_val); + !sv_highchars); // Brand server as QF, with appropriate QSG standards version --KB Info_SetValueForStarKey (svs.info, "*qf_version", PACKAGE_VERSION, - !sv_highchars->int_val); + !sv_highchars); Info_SetValueForStarKey (svs.info, "*qsg_version", QW_QSG_VERSION, - !sv_highchars->int_val); + !sv_highchars); CF_Init (); @@ -2386,7 +2545,7 @@ SV_ExtractFromUserinfo (client_t *cl) // set the name if (strcmp (newname, val) || strcmp (cl->name, newname)) { Info_SetValueForKey (cl->userinfo, "name", newname, - !sv_highchars->int_val); + !sv_highchars); val = Info_ValueForKey (cl->userinfo, "name"); SVstring (cl->edict, netname) = PR_SetString (&sv_pr_state, newname); @@ -2430,8 +2589,8 @@ SV_ExtractFromUserinfo (client_t *cl) if (strlen (val)) { i = atoi (val); - if (sv_maxrate->int_val) { - i = bound (500, i, sv_maxrate->int_val); + if (sv_maxrate) { + i = bound (500, i, sv_maxrate); } else { i = max (500, i); } @@ -2478,18 +2637,15 @@ SV_Init_Memory (void) size_t mem_size; void *mem_base; - sv_mem_size = Cvar_Get ("sv_mem_size", "8", CVAR_NONE, NULL, - "Amount of memory (in MB) to allocate for the " - PACKAGE_NAME " heap"); + Cvar_Register (&sv_mem_size_cvar, 0, 0); if (mem_parm) - Cvar_Set (sv_mem_size, com_argv[mem_parm + 1]); + Cvar_Set ("sv_mem_size", com_argv[mem_parm + 1]); if (COM_CheckParm ("-minmemory")) - Cvar_SetValue (sv_mem_size, MINIMUM_MEMORY / (1024 * 1024.0)); + sv_mem_size = MINIMUM_MEMORY / (1024 * 1024.0); - Cvar_SetFlags (sv_mem_size, sv_mem_size->flags | CVAR_ROM); - mem_size = ((size_t) sv_mem_size->value * 1024 * 1024); + mem_size = (size_t) (sv_mem_size * 1024 * 1024); if (mem_size < MINIMUM_MEMORY) Sys_Error ("Only %4.1f megs of memory reported, can't execute game", @@ -2515,7 +2671,7 @@ SV_Init (void) GIB_Init (true); COM_ParseConfig (sv_cbuf); - Cvar_Get ("cmd_warncmd", "1", CVAR_NONE, NULL, NULL); + cmd_warncmd = 1; // snax: Init experimental object system and run a test //Object_Init(); @@ -2532,10 +2688,9 @@ SV_Init (void) QFS_Init (hunk, "qw"); PI_Init (); - sv_console_plugin = Cvar_Get ("sv_console_plugin", "server", - CVAR_ROM, 0, "Plugin used for the console"); + Cvar_Register (&sv_console_plugin_cvar, 0, 0); PI_RegisterPlugins (server_plugin_list); - Con_Init (sv_console_plugin->string); + Con_Init (sv_console_plugin); if (con_module) con_module->data->console->cbuf = sv_cbuf; con_list_print = Sys_Printf; @@ -2574,7 +2729,7 @@ SV_Init (void) host_initialized = true; // SV_Printf ("Exe: "__TIME__" "__DATE__"\n"); - SV_Printf ("%4.1f megabyte heap\n", sv_mem_size->value); + SV_Printf ("%4.1f megabyte heap\n", sv_mem_size); SV_Printf ("\n"); SV_Printf ("%s server, Version %s (build %04d)\n", @@ -2585,7 +2740,7 @@ SV_Init (void) SV_Printf ("<==> %s initialized <==>\n", PACKAGE_NAME); // process command line arguments - Cmd_Exec_File (sv_cbuf, fs_usercfg->string, 0); + Cmd_Exec_File (sv_cbuf, fs_usercfg, 0); Cmd_StuffCmds (sv_cbuf); Cbuf_Execute_Stack (sv_cbuf); diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index 5e1122053..560e84ed9 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -53,11 +53,52 @@ solid_edge items clip against only bsp models. */ -cvar_t *sv_friction; -cvar_t *sv_gravity; -cvar_t *sv_jump_any; -cvar_t *sv_maxvelocity; -cvar_t *sv_stopspeed; +float sv_friction; +static cvar_t sv_friction_cvar = { + .name = "sv_friction", + .description = + "Sets the friction value for the players", + .default_value = "4", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_float, .value = &sv_friction }, +}; +float sv_gravity; +static cvar_t sv_gravity_cvar = { + .name = "sv_gravity", + .description = + "Sets the global value for the amount of gravity", + .default_value = "800", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_float, .value = &sv_gravity }, +}; +int sv_jump_any; +static cvar_t sv_jump_any_cvar = { + .name = "sv_jump_any", + .description = + "None", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_jump_any }, +}; +float sv_maxvelocity; +static cvar_t sv_maxvelocity_cvar = { + .name = "sv_maxvelocity", + .description = + "Sets the maximum velocity an object can travel", + .default_value = "2000", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_maxvelocity }, +}; +float sv_stopspeed; +static cvar_t sv_stopspeed_cvar = { + .name = "sv_stopspeed", + .description = + "Sets the value that determines how fast the player should come to a " + "complete stop", + .default_value = "100", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_stopspeed }, +}; #define MOVE_EPSILON 0.01 #if 0 @@ -106,8 +147,8 @@ SV_CheckVelocity (edict_t *ent) } #endif wishspeed = VectorLength (SVvector (ent, velocity)); - if (wishspeed > sv_maxvelocity->value) { - VectorScale (SVvector (ent, velocity), sv_maxvelocity->value / + if (wishspeed > sv_maxvelocity) { + VectorScale (SVvector (ent, velocity), sv_maxvelocity / wishspeed, SVvector (ent, velocity)); } } @@ -207,7 +248,7 @@ SV_EntCanSupportJump (edict_t *ent) int solid = SVfloat (ent, solid); if (solid == SOLID_BSP) return 1; - if (!sv_jump_any->int_val) + if (!sv_jump_any) return 0; if (solid == SOLID_NOT || solid == SOLID_SLIDEBOX) return 0; @@ -351,7 +392,7 @@ SV_AddGravity (edict_t *ent) ent_grav = SVfloat (ent, gravity); else ent_grav = 1.0; - SVvector (ent, velocity)[2] -= ent_grav * sv_gravity->value * sv_frametime; + SVvector (ent, velocity)[2] -= ent_grav * sv_gravity * sv_frametime; SVdata (ent)->add_grav = true; } @@ -364,7 +405,7 @@ SV_FinishGravity (edict_t *ent, vec3_t move) ent_grav = SVfloat (ent, gravity); else ent_grav = 1.0; - ent_grav *= sv_gravity->value; + ent_grav *= sv_gravity; move[2] += ent_grav * sv_frametime * sv_frametime / 2; } @@ -726,7 +767,7 @@ SV_Physics_Toss (edict_t *ent) } fl = 0; - if (sv_antilag->int_val == 2) + if (sv_antilag == 2) fl |= MOVE_LAGGED; trace = SV_PushEntity (ent, move, fl); if (trace.fraction == 1) @@ -776,7 +817,7 @@ SV_Physics_Step (edict_t *ent) // freefall if not on ground if (!((int) SVfloat (ent, flags) & (FL_ONGROUND | FL_FLY | FL_SWIM))) { - if (SVvector (ent, velocity)[2] < sv_gravity->value * -0.1) + if (SVvector (ent, velocity)[2] < sv_gravity * -0.1) hitsound = true; else hitsound = false; @@ -897,3 +938,13 @@ SV_Physics (void) PR_ExecuteProgram (&sv_pr_state, sv_funcs.EndFrame); } } + +void +SV_Physics_Init_Cvars (void) +{ + Cvar_Register (&sv_friction_cvar, Cvar_Info, &sv_friction); + Cvar_Register (&sv_gravity_cvar, Cvar_Info, &sv_gravity); + Cvar_Register (&sv_jump_any_cvar, 0, 0); + Cvar_Register (&sv_maxvelocity_cvar, 0, 0); + Cvar_Register (&sv_stopspeed_cvar, 0, 0); +} diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 9eb50bca6..103b0a3a3 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -389,7 +389,7 @@ PF_traceline (progs_t *pr, void *data) nomonsters = P_FLOAT (pr, 2); ent = P_EDICT (pr, 3); - if (sv_antilag->int_val == 2) + if (sv_antilag == 2) nomonsters |= MOVE_LAGGED; trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent); @@ -692,8 +692,6 @@ PF_spawn (progs_t *pr, void *data) RETURN_EDICT (pr, ed); } -cvar_t *pr_double_remove; - // void (entity e) remove static void PF_remove (progs_t *pr, void *data) @@ -702,14 +700,14 @@ PF_remove (progs_t *pr, void *data) ed = P_EDICT (pr, 0); if (NUM_FOR_EDICT (pr, ed) < *pr->reserved_edicts) { - if (pr_double_remove->int_val == 1) { + if (pr_double_remove == 1) { PR_DumpState (pr); Sys_Printf ("Reserved entity remove\n"); } else // == 2 PR_RunError (pr, "Reserved entity remove\n"); } - if (ed->free && pr_double_remove->int_val) { - if (pr_double_remove->int_val == 1) { + if (ed->free && pr_double_remove) { + if (pr_double_remove == 1) { PR_DumpState (pr); Sys_Printf ("Double entity remove\n"); } else // == 2 @@ -922,8 +920,6 @@ PF_pointcontents (progs_t *pr, void *data) R_FLOAT (pr) = SV_PointContents (v); } -cvar_t *sv_aim; - /* PF_aim @@ -942,7 +938,7 @@ PF_aim (progs_t *pr, void *data) trace_t tr; vec3_t start, dir, end, bestdir; - if (sv_aim->value >= 1.0) { + if (sv_aim >= 1.0) { VectorCopy (*sv_globals.v_forward, R_VECTOR (pr)); return; } @@ -969,7 +965,7 @@ PF_aim (progs_t *pr, void *data) VectorMultAdd (start, 2048, dir, end); tr = SV_Move (start, vec3_origin, vec3_origin, end, false, ent); if (tr.ent && SVfloat (tr.ent, takedamage) == DAMAGE_AIM - && (!teamplay->int_val || SVfloat (ent, team) <= 0 + && (!teamplay || SVfloat (ent, team) <= 0 || SVfloat (ent, team) != SVfloat (tr.ent, team))) { VectorCopy (*sv_globals.v_forward, R_VECTOR (pr)); return; @@ -977,7 +973,7 @@ PF_aim (progs_t *pr, void *data) // try all possible entities VectorCopy (dir, bestdir); - bestdist = sv_aim->value; + bestdist = sv_aim; bestent = NULL; check = NEXT_EDICT (pr, sv.edicts); @@ -986,7 +982,7 @@ PF_aim (progs_t *pr, void *data) continue; if (check == ent) continue; - if (teamplay->int_val && SVfloat (ent, team) > 0 + if (teamplay && SVfloat (ent, team) > 0 && SVfloat (ent, team) == SVfloat (check, team)) continue; // don't aim at teammate @@ -1510,7 +1506,7 @@ PF_infokey (progs_t *pr, void *data) e1 = NUM_FOR_EDICT (pr, e); key = P_GSTRING (pr, 1); - if (sv_hide_version_info->int_val + if (sv_hide_version_info && (strequal (key, "*qf_version") || strequal (key, "*qsg_version") || strequal (key, "no_pogo_stick"))) { @@ -1836,11 +1832,11 @@ PF_sv_cvar (progs_t *pr, void *data) str = P_GSTRING (pr, 0); - if (sv_hide_version_info->int_val + if (sv_hide_version_info && strequal (str, "sv_hide_version_info")) { R_FLOAT (pr) = 0; } else { - R_FLOAT (pr) = Cvar_VariableValue (str); + R_FLOAT (pr) = Cvar_Value (str); } } @@ -1910,7 +1906,7 @@ PF_SV_SetUserinfo (progs_t *pr, void *data) if (entnum < 1 || entnum > MAX_CLIENTS || cl->state != cs_server) PR_RunError (pr, "not a server client"); - cl->userinfo = Info_ParseString (str, 1023, !sv_highchars->int_val); + cl->userinfo = Info_ParseString (str, 1023, !sv_highchars); cl->sendinfo = true; SV_ExtractFromUserinfo (cl); } diff --git a/qw/source/sv_pr_cpqw.c b/qw/source/sv_pr_cpqw.c index f75cddf98..6c72d90cc 100644 --- a/qw/source/sv_pr_cpqw.c +++ b/qw/source/sv_pr_cpqw.c @@ -752,7 +752,7 @@ PF_traceline (progs_t *pr, void *data) nomonsters = TL_ANY_SOLID; nomonsters = tl_to_move[nomonsters]; - if (sv_antilag->int_val == 2) + if (sv_antilag == 2) nomonsters |= MOVE_LAGGED; trace = SV_Move (v1, vec3_origin, vec3_origin, v2, nomonsters, ent); diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 77d7898ff..fe95916b2 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -57,14 +57,100 @@ sv_fields_t sv_fields; edict_t sv_edicts[MAX_EDICTS]; sv_data_t sv_data[MAX_EDICTS]; -cvar_t *r_skyname; -cvar_t *sv_progs; -cvar_t *sv_progs_zone; -cvar_t *sv_progs_stack; -cvar_t *sv_progs_ext; -cvar_t *pr_checkextensions; -cvar_t *sv_old_entity_free; -cvar_t *sv_hide_version_info; +char *r_skyname; +static cvar_t r_skyname_cvar = { + .name = "r_skyname", + .description = + "name of the current skybox", + .default_value = "none", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &r_skyname }, +}; +char *sv_progs; +static cvar_t sv_progs_cvar = { + .name = "sv_progs", + .description = + "Override the default game progs.", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_progs }, +}; +int sv_progs_zone; +static cvar_t sv_progs_zone_cvar = { + .name = "sv_progs_zone", + .description = + "size of the zone for progs in kb", + .default_value = "256", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_progs_zone }, +}; +int sv_progs_stack; +static cvar_t sv_progs_stack_cvar = { + .name = "sv_progs_stack", + .description = + "size of the stack for progs in kb", + .default_value = "256", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_progs_stack }, +}; +char *sv_progs_ext; +static cvar_t sv_progs_ext_cvar = { + .name = "sv_progs_ext", + .description = + "extention mapping to use: none, id, qf", + .default_value = "qf", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_progs_ext }, +}; +char *pr_checkextensions; +static cvar_t pr_checkextensions_cvar = { + .name = "pr_checkextensions", + .description = + "indicate the presence of the checkextentions qc function", + .default_value = "1", + .flags = CVAR_ROM, + .value = { .type = 0/* not used */, .value = &pr_checkextensions }, +}; +int sv_old_entity_free; +static cvar_t sv_old_entity_free_cvar = { + .name = "sv_old_entity_free", + .description = + "set this for buggy mods that rely on the old behaviour of entity " + "freeing (eg, *TF)", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_old_entity_free }, +}; +int sv_hide_version_info; +static cvar_t sv_hide_version_info_cvar = { + .name = "sv_hide_version_info", + .description = + "hide QuakeForge specific serverinfo strings from terminally stupid " + "progs (eg, braindead TF variants)", + .default_value = "0", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &sv_hide_version_info }, +}; +int pr_double_remove; +static cvar_t pr_double_remove_cvar = { + .name = "pr_double_remove", + .description = + "Handling of double entity remove. 0 is silently ignore, 1 prints a " + "traceback, and 2 gives an error.\nworks Only if debugging is " + "available and enabled", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &pr_double_remove }, +}; +float sv_aim; +static cvar_t sv_aim_cvar = { + .name = "sv_aim", + .description = + "None", + .default_value = "0.93", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_aim }, +}; static pr_uint_t reserved_edicts = MAX_CLIENTS; @@ -94,7 +180,7 @@ bi_map (progs_t *pr, unsigned binum) static void free_edict (progs_t *pr, edict_t *ent) { - if (sv_old_entity_free->int_val) { + if (sv_old_entity_free) { E_fld (ent, sv_fields.model).entity_var = 0; E_fld (ent, sv_fields.takedamage).float_var = 0; E_fld (ent, sv_fields.modelindex).float_var = 0; @@ -118,7 +204,7 @@ prune_edict (progs_t *pr, edict_t *ent) return 1; } else { // remove things from different skill levels or deathmatch - if (deathmatch->int_val) { + if (deathmatch) { if (((int) SVfloat (ent, spawnflags) & SPAWNFLAG_NOT_DEATHMATCH)) { return 1; } @@ -526,17 +612,17 @@ SV_LoadProgs (void) const char *progs_name = "qwprogs.dat"; const char *range; - if (strequal (sv_progs_ext->string, "qf")) { + if (strequal (sv_progs_ext, "qf")) { sv_range = PR_RANGE_QF; range = "QF"; - } else if (strequal (sv_progs_ext->string, "id")) { + } else if (strequal (sv_progs_ext, "id")) { sv_range = PR_RANGE_ID; range = "ID"; - } else if (strequal (sv_progs_ext->string, "qwe") - || strequal (sv_progs_ext->string, "ktpro")) { + } else if (strequal (sv_progs_ext, "qwe") + || strequal (sv_progs_ext, "ktpro")) { sv_range = PR_RANGE_QWE; range = "QWE/KTPro"; - } else if (strequal (sv_progs_ext->string, "cpqw")) { + } else if (strequal (sv_progs_ext, "cpqw")) { sv_range = PR_RANGE_CPQW; range = "CPQW"; } else { @@ -548,20 +634,20 @@ SV_LoadProgs (void) memset (&sv_globals, 0, sizeof (sv_funcs)); memset (&sv_funcs, 0, sizeof (sv_funcs)); Info_RemoveKey (svs.info, "sky"); - if (*r_skyname->string) - Info_SetValueForKey (svs.info, "sky", r_skyname->string, 0); + if (*r_skyname) + Info_SetValueForKey (svs.info, "sky", r_skyname, 0); sv_cbuf->unknown_command = 0; ucmd_unknown = 0; if (qfs_gamedir->gamecode && *qfs_gamedir->gamecode) progs_name = qfs_gamedir->gamecode; - if (*sv_progs->string) - progs_name = sv_progs->string; + if (*sv_progs) + progs_name = sv_progs; sv_pr_state.max_edicts = MAX_EDICTS; - sv_pr_state.zone_size = sv_progs_zone->int_val * 1024; - sv_pr_state.stack_size = sv_progs_stack->int_val * 1024; + sv_pr_state.zone_size = sv_progs_zone * 1024; + sv_pr_state.stack_size = sv_progs_stack * 1024; sv.edicts = sv_edicts; PR_LoadProgs (&sv_pr_state, progs_name); @@ -610,27 +696,14 @@ SV_Progs_Init_Cvars (void) { PR_Init_Cvars (); - r_skyname = Cvar_Get ("r_skyname", "", CVAR_NONE, NULL, - "Default name of skybox if none given by map"); - sv_progs = Cvar_Get ("sv_progs", "", CVAR_NONE, NULL, - "Override the default game progs."); - sv_progs_zone = Cvar_Get ("sv_progs_zone", "256", CVAR_NONE, NULL, - "size of the zone for progs in kB"); - sv_progs_stack = Cvar_Get ("sv_progs_stack", "64", CVAR_NONE, NULL, - "size of the stack for progs in kB"); - sv_progs_ext = Cvar_Get ("sv_progs_ext", "qf", CVAR_NONE, NULL, - "extention mapping to use: " - "none, id, qf, qwe, ktpro, cpqw"); - pr_checkextensions = Cvar_Get ("pr_checkextensions", "1", CVAR_ROM, NULL, - "indicate the presence of the " - "checkextentions qc function"); - sv_old_entity_free = Cvar_Get ("sv_old_entity_free", "1", CVAR_NONE, NULL, - "set this for buggy mods that rely on the" - " old behaviour of entity freeing (eg," - " *TF)"); - sv_hide_version_info = Cvar_Get ("sv_hide_version_info", "0", CVAR_ROM, - NULL, "hide QuakeForge specific " - "serverinfo strings from terminally " - "stupid progs (eg, braindead TF " - "variants)"); + Cvar_Register (&r_skyname_cvar, 0, 0); + Cvar_Register (&sv_progs_cvar, 0, 0); + Cvar_Register (&sv_progs_zone_cvar, 0, 0); + Cvar_Register (&sv_progs_stack_cvar, 0, 0); + Cvar_Register (&sv_progs_ext_cvar, 0, 0); + Cvar_Register (&pr_checkextensions_cvar, 0, 0); + Cvar_Register (&sv_old_entity_free_cvar, 0, 0); + Cvar_Register (&sv_hide_version_info_cvar, 0, 0); + Cvar_Register (&sv_aim_cvar, 0, 0); + Cvar_Register (&pr_double_remove_cvar, 0, 0); } diff --git a/qw/source/sv_qtv.c b/qw/source/sv_qtv.c index 1daf1926d..31306072b 100644 --- a/qw/source/sv_qtv.c +++ b/qw/source/sv_qtv.c @@ -456,7 +456,7 @@ SV_qtvCheckTimeouts (void) float droptime; sv_qtv_t *proxy; - droptime = realtime - sv_timeout->value; + droptime = realtime - sv_timeout; for (i = 0; i < MAX_PROXIES; i++) { proxy = proxies + i; diff --git a/qw/source/sv_recorder.c b/qw/source/sv_recorder.c index cd5cdf1c2..517e981e6 100644 --- a/qw/source/sv_recorder.c +++ b/qw/source/sv_recorder.c @@ -121,7 +121,7 @@ static byte datagram_data[MAX_DATAGRAM]; static byte msg_buffer[2][MAX_DATAGRAM]; #define MIN_DEMO_MEMORY 0x100000 -#define USECACHE (sv_demoUseCache->int_val && svs.demomemsize) +#define USECACHE (sv_demoUseCache && svs.demomemsize) #define MAXSIZE (rec.dbuffer.end < rec.dbuffer.last ? \ rec.dbuffer.start - rec.dbuffer.end : \ rec.dbuffer.maxsize - rec.dbuffer.end) @@ -559,7 +559,7 @@ SVR_SendMessages (void) int stats[MAX_CL_STATS]; recorder_t *r; - if (sv_demoPings->value && sv.time - rec.pingtime > sv_demoPings->value) { + if (sv_demoPings && sv.time - rec.pingtime > sv_demoPings) { demo_pings (); rec.pingtime = sv.time; } diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index 87c65837e..42f53169e 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -226,14 +226,13 @@ SV_Print (const char *fmt, va_list args) } if (*msg->str && !con_printf_no_log) { // We want to output to console and maybe logfile - if (sv_timestamps && sv_timefmt && sv_timefmt->string - && sv_timestamps->int_val && !pending) + if (sv_timefmt && sv_timestamps && !pending) timestamps = true; if (timestamps) { mytime = time (NULL); local = localtime (&mytime); - hstrftime (msg3, sizeof (msg3), sv_timefmt->string, local); + hstrftime (msg3, sizeof (msg3), sv_timefmt, local); dsprintf (msg2, "%s%s", msg3, msg->str); } else { @@ -423,7 +422,7 @@ SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, ent = NUM_FOR_EDICT (&sv_pr_state, entity); - if ((channel & 8) || !sv_phs->int_val) // no PHS flag + if ((channel & 8) || !sv_phs) // no PHS flag { if (channel & 8) reliable = true; // sounds that break the phs are diff --git a/qw/source/sv_sys_unix.c b/qw/source/sv_sys_unix.c index cb7aabbdd..96b0c67b9 100644 --- a/qw/source/sv_sys_unix.c +++ b/qw/source/sv_sys_unix.c @@ -139,7 +139,7 @@ main (int argc, const char **argv) SV_Frame (time); // extrasleep is just a way to generate a bad connection on purpose - if (sys_extrasleep->int_val) - usleep (sys_extrasleep->int_val); + if (sys_extrasleep) + usleep (sys_extrasleep); } } diff --git a/qw/source/sv_sys_win.c b/qw/source/sv_sys_win.c index 20fbdfb4e..f8c9dba1a 100644 --- a/qw/source/sv_sys_win.c +++ b/qw/source/sv_sys_win.c @@ -81,7 +81,7 @@ main (int argc, const char **argv) SV_Init (); if (COM_CheckParm ("-nopriority")) { - Cvar_Set (sys_sleep, "0"); + Cvar_Set ("sys_sleep", "0"); } else { if (!SetPriorityClass (GetCurrentProcess (), HIGH_PRIORITY_CLASS)) SV_Printf ("SetPriorityClass() failed\n"); @@ -91,7 +91,7 @@ main (int argc, const char **argv) // sys_sleep > 0 seems to cause packet loss on WinNT (why?) if (WinNT) - Cvar_Set (sys_sleep, "0"); + Cvar_Set ("sys_sleep", "0"); Sys_RegisterShutdown (Net_LogStop, 0); diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 31dc6c142..553ee274c 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -80,34 +80,215 @@ edict_t *sv_player; usercmd_t cmd; -cvar_t *sv_antilag; -cvar_t *sv_antilag_frac; +int sv_maxrate; +static cvar_t sv_maxrate_cvar = { + .name = "sv_maxrate", + .description = + "Maximum allowable rate", + .default_value = "10000", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &sv_maxrate }, +}; + // capped) +int sv_antilag; +static cvar_t sv_antilag_cvar = { + .name = "sv_antilag", + .description = + "Attempt to backdate impacts to compensate for lag. 0=completely off. " + "1=mod-controlled. 2=forced, which might break certain uses of " + "traceline.", + .default_value = "1", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &sv_antilag }, +}; +float sv_antilag_frac; +static cvar_t sv_antilag_frac_cvar = { + .name = "sv_antilag_frac", + .description = + "FIXME something to do with sv_antilag", + .default_value = "1", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_float, .value = &sv_antilag_frac }, +}; -cvar_t *sv_accelerate; -cvar_t *sv_airaccelerate; -cvar_t *sv_maxspeed; -cvar_t *sv_spectatormaxspeed; -cvar_t *sv_wateraccelerate; -cvar_t *sv_waterfriction; +float sv_accelerate; +static cvar_t sv_accelerate_cvar = { + .name = "sv_accelerate", + .description = + "None", + .default_value = "10", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_accelerate }, +}; +float sv_airaccelerate; +static cvar_t sv_airaccelerate_cvar = { + .name = "sv_airaccelerate", + .description = + "Sets how quickly the players accelerate in air", + .default_value = "0.7", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_airaccelerate }, +}; +float sv_maxspeed; +static cvar_t sv_maxspeed_cvar = { + .name = "sv_maxspeed", + .description = + "None", + .default_value = "320", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_float, .value = &sv_maxspeed }, +}; +float sv_spectatormaxspeed; +static cvar_t sv_spectatormaxspeed_cvar = { + .name = "sv_spectatormaxspeed", + .description = + "Sets the maximum speed a spectator can move", + .default_value = "500", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_spectatormaxspeed }, +}; +float sv_wateraccelerate; +static cvar_t sv_wateraccelerate_cvar = { + .name = "sv_wateraccelerate", + .description = + "Sets the water acceleration value", + .default_value = "10", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_wateraccelerate }, +}; +float sv_waterfriction; +static cvar_t sv_waterfriction_cvar = { + .name = "sv_waterfriction", + .description = + "Sets the water friction value", + .default_value = "4", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_waterfriction }, +}; -cvar_t *sv_allowfake; +int sv_allowfake; +static cvar_t sv_allowfake_cvar = { + .name = "sv_allowfake", + .description = + "Allow 'fake' messages (FuhQuake $\\). 1 = always, 2 = only say_team", + .default_value = "2", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_allowfake }, +}; -cvar_t *cl_rollspeed; -cvar_t *cl_rollangle; -cvar_t *sv_spectalk; +float cl_rollspeed; +static cvar_t cl_rollspeed_cvar = { + .name = "cl_rollspeed", + .description = + "How quickly you straighten out after strafing", + .default_value = "200", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_rollspeed }, +}; +float cl_rollangle; +static cvar_t cl_rollangle_cvar = { + .name = "cl_rollangle", + .description = + "How much your screen tilts when strafing", + .default_value = "2.0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_rollangle }, +}; +int sv_spectalk; +static cvar_t sv_spectalk_cvar = { + .name = "sv_spectalk", + .description = + "Toggles the ability of spectators to talk to players", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_spectalk }, +}; -cvar_t *sv_kickfake; +int sv_kickfake; +static cvar_t sv_kickfake_cvar = { + .name = "sv_kickfake", + .description = + "Kick users sending to send fake talk messages", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_kickfake }, +}; -cvar_t *sv_mapcheck; +int sv_mapcheck; +static cvar_t sv_mapcheck_cvar = { + .name = "sv_mapcheck", + .description = + "Toggle the use of map checksumming to check for players who edit maps" + " to cheat", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_mapcheck }, +}; -cvar_t *sv_timecheck_mode; -cvar_t *sv_timekick; -cvar_t *sv_timekick_fuzz; -cvar_t *sv_timekick_interval; -cvar_t *sv_timecheck_fuzz; -cvar_t *sv_timecheck_decay; +int sv_timecheck_mode; +static cvar_t sv_timecheck_mode_cvar = { + .name = "sv_timecheck_mode", + .description = + "select between timekick (0, default) and timecheck (1)", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_timecheck_mode }, +}; +int sv_timekick; +static cvar_t sv_timekick_cvar = { + .name = "sv_timekick", + .description = + "Time cheat protection", + .default_value = "3", + .flags = CVAR_SERVERINFO, + .value = { .type = &cexpr_int, .value = &sv_timekick }, +}; +float sv_timekick_fuzz; +static cvar_t sv_timekick_fuzz_cvar = { + .name = "sv_timekick_fuzz", + .description = + "Time cheat \"fuzz factor\" in milliseconds", + .default_value = "30", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_timekick_fuzz }, +}; +float sv_timekick_interval; +static cvar_t sv_timekick_interval_cvar = { + .name = "sv_timekick_interval", + .description = + "Time cheat check interval in seconds", + .default_value = "30", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &sv_timekick_interval }, +}; +int sv_timecheck_fuzz; +static cvar_t sv_timecheck_fuzz_cvar = { + .name = "sv_timecheck_fuzz", + .description = + "Milliseconds of tolerance before time cheat throttling kicks in.", + .default_value = "250", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_timecheck_fuzz }, +}; +int sv_timecheck_decay; +static cvar_t sv_timecheck_decay_cvar = { + .name = "sv_timecheck_decay", + .description = + "Rate at which time inaccuracies are \"forgiven\".", + .default_value = "2", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &sv_timecheck_decay }, +}; -cvar_t *sv_http_url_base; +char *sv_http_url_base; +static cvar_t sv_http_url_base_cvar = { + .name = "sv_http_url_base", + .description = + "set to base url for http redirects of downloaded files", + .default_value = "", + .flags = CVAR_NONE, + .value = { .type = 0, .value = &sv_http_url_base }, +}; static void OutofBandPrintf (netadr_t where, const char *fmt, ...) __attribute__ ((format (PRINTF, 2, 3))); @@ -335,7 +516,7 @@ SV_PreSpawn_f (void *unused) // Sys_MaskPrintf (SYS_dev, , "Client check = %d\n", check); - if (sv_mapcheck->int_val && check != sv.worldmodel->brush.checksum && + if (sv_mapcheck && check != sv.worldmodel->brush.checksum && check != sv.worldmodel->brush.checksum2) { SV_ClientPrintf (1, host_client, PRINT_HIGH, "Map model file does " "not match (%s), %i != %i/%i.\n" @@ -386,9 +567,9 @@ SV_Spawn (client_t *client) client->entgravity = 1.0; if (sv_fields.gravity != -1) SVfloat (ent, gravity) = 1.0; - client->maxspeed = sv_maxspeed->value; + client->maxspeed = sv_maxspeed; if (sv_fields.maxspeed != -1) - SVfloat (ent, maxspeed) = sv_maxspeed->value; + SVfloat (ent, maxspeed) = sv_maxspeed; } void @@ -715,19 +896,19 @@ SV_BeginDownload_f (void *unused) name = Cmd_Argv (1); // hacked by zoid to allow more conrol over download // first off, no .. or global allow check - if (strstr (name, "..") || !allow_download->int_val + if (strstr (name, "..") || !allow_download // leading dot is no good || *name == '.' // next up, skin check - || (strncmp (name, "skins/", 6) == 0 && !allow_download_skins->int_val) + || (strncmp (name, "skins/", 6) == 0 && !allow_download_skins) // now models || (strncmp (name, "progs/", 6) == 0 && - !allow_download_models->int_val) + !allow_download_models) // now sounds || (strncmp (name, "sound/", 6) == 0 && - !allow_download_sounds->int_val) + !allow_download_sounds) // now maps (note special case for maps, must not be in pak) - || (strncmp (name, "maps/", 5) == 0 && !allow_download_maps->int_val) + || (strncmp (name, "maps/", 5) == 0 && !allow_download_maps) // MUST be in a subdirectory || !strstr (name, "/")) { // don't allow anything with .. path MSG_ReliableWrite_Begin (&host_client->backbuf, svc_download, 4); @@ -742,7 +923,7 @@ SV_BeginDownload_f (void *unused) } zip = strchr (Info_ValueForKey (host_client->userinfo, "*cap"), 'z') != 0; - http = sv_http_url_base->string[0] + http = sv_http_url_base[0] && strchr (Info_ValueForKey (host_client->userinfo, "*cap"), 'h'); file = _QFS_FOpenFile (name, !zip); @@ -770,15 +951,15 @@ SV_BeginDownload_f (void *unused) if (http) { int size; int ren = zip && strcmp (qfs_foundfile.realname, name); - SV_Printf ("http redirect: %s/%s\n", sv_http_url_base->string, + SV_Printf ("http redirect: %s/%s\n", sv_http_url_base, qfs_foundfile.realname); size = ren ? strlen (qfs_foundfile.realname) * 2 : strlen (name); - size += strlen (sv_http_url_base->string) + 7; + size += strlen (sv_http_url_base) + 7; MSG_ReliableWrite_Begin (&host_client->backbuf, svc_download, size); MSG_ReliableWrite_Short (&host_client->backbuf, DL_HTTP); MSG_ReliableWrite_Byte (&host_client->backbuf, 0); MSG_ReliableWrite_String (&host_client->backbuf, - va (0, "%s/%s", sv_http_url_base->string, + va (0, "%s/%s", sv_http_url_base, ren ? qfs_foundfile.realname : name)); MSG_ReliableWrite_String (&host_client->backbuf, ren ? qfs_foundfile.realname : ""); @@ -860,10 +1041,10 @@ SV_Say (qboolean team) p[strlen (p) - 1] = 0; } - if (!sv_allowfake->int_val || (!team && sv_allowfake->int_val == 2)) { + if (!sv_allowfake || (!team && sv_allowfake == 2)) { for (i = p; *i; i++) { if (*i == 13) { // ^M - if (sv_kickfake->int_val) { + if (sv_kickfake) { SV_BroadcastPrintf (PRINT_HIGH, "%s was kicked for " "attempting to fake messages\n", host_client->name); @@ -892,7 +1073,7 @@ SV_Say (qboolean team) } text = dstring_new (); - if (host_client->spectator && (!sv_spectalk->int_val || team)) { + if (host_client->spectator && (!sv_spectalk || team)) { type = "2"; dsprintf (text, "[SPEC] %s: ", host_client->name); } else if (team) { @@ -915,7 +1096,7 @@ SV_Say (qboolean team) for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) { if (client->state < cs_connected) // Clients connecting can hear. //FIXME record to mvd? continue; - if (host_client->spectator && !sv_spectalk->int_val) + if (host_client->spectator && !sv_spectalk) if (!client->spectator) continue; @@ -940,7 +1121,7 @@ SV_Say (qboolean team) } // non-team messages should be seen allways, even if not tracking any // player - if (!team && ((host_client->spectator && sv_spectalk->int_val) + if (!team && ((host_client->spectator && sv_spectalk) || !host_client->spectator)) { dbuf = SVR_WriteBegin (dem_all, 0, strlen (text->str) + 3); } else { @@ -1045,7 +1226,7 @@ SV_Pause_f (void *unused) lastpausetime = currenttime; - if (!pausable->int_val) { + if (!pausable) { SV_ClientPrintf (1, host_client, PRINT_HIGH, "Pause not allowed.\n"); return; } @@ -1139,8 +1320,8 @@ SV_Rate_f (void *unused) } rate = atoi (Cmd_Argv (1)); - if (sv_maxrate->int_val) { - rate = bound (500, rate, sv_maxrate->int_val); + if (sv_maxrate) { + rate = bound (500, rate, sv_maxrate); } else { rate = max (500, rate); } @@ -1179,7 +1360,7 @@ SV_SetUserinfo (client_t *client, const char *key, const char *value) if (sv_setinfo_e->func || sv_funcs.UserInfoChanged) oldvalue = strdup (Info_ValueForKey (client->userinfo, key)); if (!Info_SetValueForKey (client->userinfo, key, value, - !sv_highchars->int_val)) { + !sv_highchars)) { // key hasn't changed if (oldvalue) free (oldvalue); @@ -1487,10 +1668,10 @@ SV_CalcRoll (vec3_t angles, vec3_t velocity) sign = side < 0 ? -1 : 1; side = fabs (side); - value = cl_rollangle->value; + value = cl_rollangle; - if (side < cl_rollspeed->value) - side = side * value / cl_rollspeed->value; + if (side < cl_rollspeed) + side = side * value / cl_rollspeed; else side = value; @@ -1592,12 +1773,12 @@ adjust_usecs (usercmd_t *ucmd) passed = (int) ((realtime - host_client->last_check) * 1000.0); host_client->msecs += passed - ucmd->msec; if (host_client->msecs >= 0) { - host_client->msecs -= sv_timecheck_decay->int_val; + host_client->msecs -= sv_timecheck_decay; } else { - host_client->msecs += sv_timecheck_decay->int_val; + host_client->msecs += sv_timecheck_decay; } - if (abs (host_client->msecs) > sv_timecheck_fuzz->int_val) { - int fuzz = sv_timecheck_fuzz->int_val; + if (abs (host_client->msecs) > sv_timecheck_fuzz) { + int fuzz = sv_timecheck_fuzz; host_client->msecs = bound (-fuzz, host_client->msecs, fuzz); ucmd->msec = passed; } @@ -1616,18 +1797,18 @@ check_usecs (usercmd_t *ucmd) if (host_client->last_check == -1.0) return; tmp_time = realtime - host_client->last_check; - if (tmp_time < sv_timekick_interval->value) + if (tmp_time < sv_timekick_interval) return; host_client->last_check = realtime; - tmp_time1 = tmp_time * (1000 + sv_timekick_fuzz->value); + tmp_time1 = tmp_time * (1000 + sv_timekick_fuzz); if (host_client->msecs >= tmp_time1) { host_client->msec_cheating++; SV_BroadcastPrintf (PRINT_HIGH, "%s thinks there are %d ms " "in %d seconds (Strike %d/%d)\n", host_client->name, host_client->msecs, (int) tmp_time, host_client->msec_cheating, - sv_timekick->int_val); - if (host_client->msec_cheating >= sv_timekick->int_val) { + sv_timekick); + if (host_client->msec_cheating >= sv_timekick) { SV_BroadcastPrintf (PRINT_HIGH, "Strike %d for %s!!\n", host_client->msec_cheating, host_client->name); SV_BroadcastPrintf (PRINT_HIGH, "Please see " @@ -1648,7 +1829,7 @@ SV_RunCmd (usercmd_t *ucmd, qboolean inside) edict_t *ent; if (!inside) { - if (sv_timecheck_mode->int_val) { + if (sv_timecheck_mode) { adjust_usecs (ucmd); } else { check_usecs (ucmd); @@ -1863,7 +2044,7 @@ SV_ExecuteClientMessage (client_t *cl) frame->ping_time = realtime - frame->senttime; cl->laggedents_count = 0; - if (sv_antilag->int_val) { + if (sv_antilag) { int i; for (i = 0; i < MAX_CLIENTS; i++) { @@ -1874,7 +2055,7 @@ SV_ExecuteClientMessage (client_t *cl) } } cl->laggedents_count = MAX_CLIENTS; - cl->laggedents_frac = sv_antilag_frac->value; + cl->laggedents_frac = sv_antilag_frac; } // save time for ping calculations @@ -2000,56 +2181,63 @@ static builtin_t builtins[] = { {0} }; +static void +SV_MaxRate_f (void *data, const cvar_t *cvar) +{ + client_t *cl; + int maxrate = sv_maxrate; + int i, rate = 2500; + const char *val; + + Cvar_Info (data, cvar); + for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { + if (!cl->userinfo) + continue; + val = Info_ValueForKey (cl->userinfo, "rate"); + if (strlen (val)) { + rate = atoi (val); + + if (maxrate) { + rate = bound (500, rate, maxrate); + } else { + rate = max (500, rate); + } + cl->netchan.rate = 1.0 / rate; + } + SV_ClientPrintf (1, cl, PRINT_HIGH, "Net rate set to %i\n", rate); + } +} + void SV_UserInit (void) { ucmd_table = Hash_NewTable (251, ucmds_getkey, ucmds_free, 0, 0); Hash_SetHashCompare (ucmd_table, ucmd_get_hash, ucmd_compare); PR_RegisterBuiltins (&sv_pr_state, builtins, 0); - cl_rollspeed = Cvar_Get ("cl_rollspeed", "200", CVAR_NONE, NULL, - "How quickly a player straightens out after " - "strafing"); - cl_rollangle = Cvar_Get ("cl_rollangle", "2", CVAR_NONE, NULL, "How much " - "a player's screen tilts when strafing"); + Cvar_Register (&cl_rollspeed_cvar, 0, 0); + Cvar_Register (&cl_rollangle_cvar, 0, 0); - sv_antilag = Cvar_Get ("sv_antilag", "1", CVAR_SERVERINFO, Cvar_Info, - "Attempt to backdate impacts to compensate for " - "lag. 0=completely off. 1=mod-controlled. " - "2=forced, which might break certain uses of " - "traceline."); - sv_antilag_frac = Cvar_Get ("sv_antilag_frac", "1", CVAR_SERVERINFO, - Cvar_Info, - "FIXME something to do with sv_antilag"); + Cvar_Register (&sv_antilag_cvar, Cvar_Info, &sv_antilag); + Cvar_Register (&sv_antilag_frac_cvar, Cvar_Info, &sv_antilag_frac); - sv_allowfake = Cvar_Get ("sv_allowfake", "2", CVAR_NONE, NULL, - "Allow 'fake' messages (FuhQuake $\\). 1 = " - "always, 2 = only say_team"); - sv_spectalk = Cvar_Get ("sv_spectalk", "1", CVAR_NONE, NULL, "Toggles " - "the ability of spectators to talk to players"); - sv_mapcheck = Cvar_Get ("sv_mapcheck", "1", CVAR_NONE, NULL, "Toggle the " - "use of map checksumming to check for players who " - "edit maps to cheat"); - sv_timecheck_mode = Cvar_Get ("sv_timecheck_mode", "0", CVAR_NONE, NULL, - "select between timekick (0, default) and " - "timecheck (1)"); - sv_timekick = Cvar_Get ("sv_timekick", "3", CVAR_SERVERINFO, Cvar_Info, - "Time cheat protection"); - sv_timekick_fuzz = Cvar_Get ("sv_timekick_fuzz", "30", CVAR_NONE, NULL, - "Time cheat \"fuzz factor\" in milliseconds"); - sv_timekick_interval = Cvar_Get ("sv_timekick_interval", "30", CVAR_NONE, - NULL, "Time cheat check interval in " - "seconds"); - sv_timecheck_fuzz = Cvar_Get ("sv_timecheck_fuzz", "250", CVAR_NONE, NULL, - "Milliseconds of tolerance before time " - "cheat throttling kicks in."); - sv_timecheck_decay = Cvar_Get ("sv_timecheck_decay", "2", CVAR_NONE, - NULL, "Rate at which time inaccuracies are " - "\"forgiven\"."); - sv_kickfake = Cvar_Get ("sv_kickfake", "0", CVAR_NONE, NULL, - "Kick users sending to send fake talk messages"); - sv_http_url_base = Cvar_Get ("sv_http_url_base", "", CVAR_NONE, NULL, - "set to base url for http redirects of " - "downloaded files"); + Cvar_Register (&sv_allowfake_cvar, 0, 0); + Cvar_Register (&sv_spectalk_cvar, 0, 0); + Cvar_Register (&sv_mapcheck_cvar, 0, 0); + Cvar_Register (&sv_timecheck_mode_cvar, 0, 0); + Cvar_Register (&sv_timekick_cvar, Cvar_Info, &sv_timekick); + Cvar_Register (&sv_timekick_fuzz_cvar, 0, 0); + Cvar_Register (&sv_timekick_interval_cvar, 0, 0); + Cvar_Register (&sv_timecheck_fuzz_cvar, 0, 0); + Cvar_Register (&sv_timecheck_decay_cvar, 0, 0); + Cvar_Register (&sv_kickfake_cvar, 0, 0); + Cvar_Register (&sv_http_url_base_cvar, 0, 0); + Cvar_Register (&sv_maxrate_cvar, SV_MaxRate_f, 0); + Cvar_Register (&sv_maxspeed_cvar, Cvar_Info, &sv_maxspeed); + Cvar_Register (&sv_spectatormaxspeed_cvar, 0, 0); + Cvar_Register (&sv_accelerate_cvar, 0, 0); + Cvar_Register (&sv_airaccelerate_cvar, 0, 0); + Cvar_Register (&sv_wateraccelerate_cvar, 0, 0); + Cvar_Register (&sv_waterfriction_cvar, 0, 0); } static void diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index a2ced2126..926093007 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -61,11 +61,53 @@ static qboolean died = false, recorded_location = false; static vec4f_t death_location, last_recorded_location; -cvar_t *cl_deadbodyfilter; -cvar_t *cl_gibfilter; -cvar_t *cl_parsesay; -cvar_t *cl_nofake; -cvar_t *cl_freply; +int cl_deadbodyfilter; +static cvar_t cl_deadbodyfilter_cvar = { + .name = "cl_deadbodyfilter", + .description = + "Hide dead player models", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_deadbodyfilter }, +}; +int cl_gibfilter; +static cvar_t cl_gibfilter_cvar = { + .name = "cl_gibfilter", + .description = + "Hide gibs", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_gibfilter }, +}; +int cl_parsesay; +static cvar_t cl_parsesay_cvar = { + .name = "cl_parsesay", + .description = + "Use .loc files to find your present location when you put %l in " + "messages", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_parsesay }, +}; +int cl_nofake; +static cvar_t cl_nofake_cvar = { + .name = "cl_nofake", + .description = + "Unhide fake messages", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &cl_nofake }, +}; +float cl_freply; +static cvar_t cl_freply_cvar = { + .name = "cl_freply", + .description = + "Delay between replies to f_*. 0 disables. Minimum suggested setting " + "is 20", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_float, .value = &cl_freply }, +}; void @@ -129,7 +171,7 @@ Team_ParseSay (dstring_t *buf, const char *s) size_t i, bracket; static location_t *location = NULL; - if (!cl_parsesay->int_val || (cl.fpd & FPD_NO_MACROS)) + if (!cl_parsesay || (cl.fpd & FPD_NO_MACROS)) return s; i = 0; @@ -158,7 +200,7 @@ Team_ParseSay (dstring_t *buf, const char *s) break; case 'S': bracket = 0; - t1 = skin->string; + t1 = skin; break; case 'd': bracket = 0; @@ -308,18 +350,11 @@ Team_NewMap (void) void Team_Init_Cvars (void) { - cl_deadbodyfilter = Cvar_Get ("cl_deadbodyfilter", "0", CVAR_NONE, NULL, - "Hide dead player models"); - cl_gibfilter = Cvar_Get ("cl_gibfilter", "0", CVAR_NONE, NULL, - "Hide gibs"); - cl_parsesay = Cvar_Get ("cl_parsesay", "0", CVAR_NONE, NULL, - "Use .loc files to find your present location " - "when you put %l in messages"); - cl_nofake = Cvar_Get ("cl_nofake", "0", CVAR_NONE, NULL, - "Unhide fake messages"); - cl_freply = Cvar_Get ("cl_freply", "0", CVAR_NONE, NULL, - "Delay between replies to f_*. 0 disables. Minimum " - "suggested setting is 20"); + Cvar_Register (&cl_deadbodyfilter_cvar, 0, 0); + Cvar_Register (&cl_gibfilter_cvar, 0, 0); + Cvar_Register (&cl_parsesay_cvar, 0, 0); + Cvar_Register (&cl_nofake_cvar, 0, 0); + Cvar_Register (&cl_freply_cvar, 0, 0); } /* @@ -435,7 +470,7 @@ Team_F_Skins (char *args) int totalfb, l; float allfb = 0.0; - allfb = min (cl.fbskins, cl_fb_players->value); + allfb = min (cl.fbskins, cl_fb_players); if (allfb >= 1.0) { return "say Player models fullbright"; @@ -474,7 +509,7 @@ Team_ParseChat (const char *string) char *s; unsigned int i; - if (!cl_freply->value) + if (!cl_freply) return; if (!(s = strchr (string, ':'))) @@ -485,7 +520,7 @@ Team_ParseChat (const char *string) for (i = 0; i < sizeof (f_replies) / sizeof (f_replies[0]); i++) { if (!strncmp (f_replies[i].name, s, strlen (f_replies[i].name)) - && realtime - f_replies[i].lasttime >= cl_freply->value) { + && realtime - f_replies[i].lasttime >= cl_freply) { while (*s && !isspace ((byte) *s)) s++; Cbuf_AddText (cl_cbuf, f_replies[i].func (s)); @@ -501,6 +536,6 @@ Team_ResetTimers (void) unsigned int i; for (i = 0; i < sizeof (f_replies) / sizeof (f_replies[0]); i++) - f_replies[i].lasttime = realtime - cl_freply->value; + f_replies[i].lasttime = realtime - cl_freply; return; } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 48c404338..b4954a0bb 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -149,9 +149,6 @@ init_qf (void) //Cvar_Set (developer, "1"); Memory_Init (Sys_Alloc (8 * 1024 * 1024), 8 * 1024 * 1024); - - Cvar_Get ("pr_debug", "2", 0, 0, 0); - Cvar_Get ("pr_boundscheck", "0", 0, 0, 0); } static void @@ -212,6 +209,8 @@ create_progs (qwaq_thread_t *thread) pr->hashlink_freelist = &thread->hashlink_freelist; PR_Init_Cvars (); + pr_debug = 2; + pr_boundscheck = 0; PR_Init (pr); PR_Resources_Register (pr, "qwaq_thread", thread, qwaq_thread_clear); RUA_Init (pr, thread->rua_security); diff --git a/tools/misc/cvar2.py b/tools/misc/cvar2.py new file mode 100644 index 000000000..338a25904 --- /dev/null +++ b/tools/misc/cvar2.py @@ -0,0 +1,335 @@ +import re +import sys +from pprint import pprint +from io import StringIO +from textwrap import TextWrapper +import os + +STRING = r'\s*"((\\.|[^"\\])*)"\s*' +QSTRING = r'\s*("(\\.|[^"\\])*")\s*' +ID = r'([a-zA-Z_][a-zA-Z_0-9]*)' +STORE = r'(VISIBLE\s+|static\s+|extern\s+|)' +FIELD = r'(string|value|int_val|vec)\b' +FLAGS = r'\s*(' + ID + r'\s*(\|\s*' + ID + r')*)\s*' +TYPE = r'(cvar_t|struct cvar_s)\s*\*' +STUFF = r'\s*(.*)\s*' +cvar_decl_re = re.compile(r'^' + STORE + TYPE + ID + r';.*') +cvar_get_re = re.compile(r'.*\bCvar_Get\s*\(\s*"') +cvar_get_join_prev_re = re.compile(r'^\s*Cvar_Get\s*\(\s*".*') +cvar_get_assign_re = re.compile(r'\s*' + ID + r'\s*=\s*$') +cvar_get_incomplete_re = re.compile(r'.*Cvar_Get\s*\(\s*"[^;]*$') +cvar_get_complete_re = re.compile(r'.*Cvar_Get\s*\(\s*".*\);.*$') +cvar_create_re = re.compile(r'\s*(\w+)\s*=\s*Cvar_Get\s*\(' + + STRING + + ',(' + STRING + '|\s*(.*)\s*),' + FLAGS + r',\s*([^,]+),\s*' + STUFF + r'\);.*') +cvar_use_re = re.compile(ID + r'\s*\->\s*' + FIELD) +cvar_listener_re = re.compile(ID + r'\s*\(\s*cvar_t\s*\*' + ID + '\s*\)\s*') +string_or_id_re = re.compile(f'({ID}|{QSTRING})') +cvar_setrom_re = re.compile(r'\s*Cvar_SetFlags\s*\(\s*' + ID + '.*CVAR_ROM\);.*') +id_re = re.compile(f'\\b{ID}\\b') + +#cvar_decl_re = re.compile(r'^cvar_t\s+(\w+)\s*=\s*\{\s*("[^"]*")\s*,\s*("[^"]*")(\s*,\s*(\w+)(\s*,\s*(\w+))?)?\s*\}\s*;(\s*//\s*(.*))?\n') +cvar_set_re = re.compile(r'^(\s+)(Cvar_Set|Cvar_SetValue)\s*\(' + ID + ',\s*(.*)\);(.*)') + +wrapper = TextWrapper(width = 69, drop_whitespace = False, + break_long_words = False) + +class cvar: + def __init__(self, c_name, name, default, flags, callback, description): + self.c_name = c_name + self.name = name + self.default = default + self.flags = flags + if callback in ['NULL', '0']: + callback = 0 + self.callback = callback + if description in ['NULL', '0', '']: + description = 'FIXME no description' + self.desc = description + if self.desc==None: + self.desc = 'None' + self.data = 0 + self.files = [] + self.type = None + self.c_type = None + self.used_field = None + self.uses = [] + def guess_type(self): + if self.used_field == "value": + self.type = "&cexpr_float" + self.c_type = "float " + elif self.used_field == "int_val": + self.type = "&cexpr_int" + self.c_type = "int " + elif self.used_field == "vec": + self.type = "&cexpr_vector" + self.c_type = "vec4f_t " + elif self.used_field == "string": + self.type = 0 + self.c_type = "char *" + else: + self.type = "0/* not used */" + self.c_type = "char *" + def add_file(self, file, line): + self.files.append((file, line)) + def add_use(self, field, file, line): + if self.used_field and self.used_field != field: + print(f"{file}:{line}: cvar {self.name} used inconsistently") + self.used_field = field + self.uses.append((field, file, line)) + def __repr__(self): + return f"cvar(({self.c_name}, {self.name}, {self.default}, {self.flags}, {self.callback}, {self.desc})" + def __str__(self): + return self.__repr__() + def struct(self): + A = [ + f'static cvar_t {self.c_name}_cvar = {{\n', + f'\t.name = "{self.name}",\n', + f'\t.description =\n', + ] + B = [ + f'\t.default_value = "{self.default}",\n', + f'\t.flags = {self.flags},\n', + f'\t.value = {{ .type = {self.type}, .value = &{self.c_name} }},\n', + f'}};\n', + ] + desc = [] + dstrings = [m[0].strip() for m in string_or_id_re.findall(self.desc)] + def wrap(string, comma = ""): + if string[0] == '"' and string != '""': + string = string[1:-1] + dlines = wrapper.wrap(string) + desc.extend([f'\t\t"{l}"\n' for l in dlines[:-1]]) + desc.append(f'\t\t"{dlines[-1]}"{comma}\n') + else: + desc.append(f'\t\t{string}{comma}\n') + for dstring in dstrings[:-1]: + wrap (dstring) + wrap(dstrings[-1], ",") + return A + desc + B + def var(self, storage): + if storage: + storage += " " + return [f'{storage}{self.c_type}{self.c_name};\n'] + def set_rom(self): + if self.flags == 'CVAR_NONE': + self.flags = 'CVAR_ROM' + else: + self.flags = '|'.join([self.flags, 'CVAR_ROM']) + def register(self): + return [f'\tCvar_Register (&{self.c_name}_cvar, {self.callback}, {self.data});\n'] + + +cvar_decls = {} +cvar_dict = {} +cvar_sets = [] +cvar_rom = set() +cvar_listeners = {} +cvar_listeners_done = set() +cvar_listeners_multi = set() +files = {} +modified = set() + +cvar_struct = [ +"\tconst char *name;\n", +"\tconst char *description;\n", +"\tconst char *default_value;\n", +"\tunsigned flags;\n", +"\texprval_t value;\n", +"\tint (*validator) (const struct cvar_s *var);\n" +"\tstruct cvar_listener_set_s *listeners;\n" +"\tstruct cvar_s *next;\n" +] +cvar_reg = "void Cvar_Register (cvar_t *var, cvar_listener_t listener, void *data);\n" +cvar_cexpr = '#include "QF/cexpr.h"\n' +cvar_set = 'void Cvar_Set (const char *var, const char *value);\n' +cvar_setvar = 'void Cvar_SetVar (cvar_t *var, const char *value);\n' +cvar_info = 'struct cvar_s;\nvoid Cvar_Info (void *data, const struct cvar_s *cvar);\n' +nq_cl_cvar_info = 'nq/include/client.h' +nq_sv_cvar_info = 'nq/include/server.h' +qw_cl_cvar_info = 'qw/include/client.h' +qw_sv_cvar_info = 'qw/include/server.h' + +cvar_file = "include/QF/cvar.h" +line_substitutions = [ + (cvar_file, (40, 60), cvar_struct), + (cvar_file, (96, 100), cvar_reg), + (cvar_file, (35, 35), cvar_cexpr), + (cvar_file, (109, 110), cvar_set), + (cvar_file, (110, 111), cvar_setvar), + (nq_cl_cvar_info, (294,295), cvar_info), + (nq_sv_cvar_info, (300,301), cvar_info), + (qw_cl_cvar_info, (296,297), cvar_info), + (qw_sv_cvar_info, (634,635), cvar_info), +] + +def get_cvar_defs(fname): + fi = open(fname,'rt') + f = files[fname] = fi.readlines() + i = 0 + while i < len(f): + cr = cvar_setrom_re.match(f[i]) + if cr: + cvar_rom.add(cr[1]) + del(f[i]) + continue + if cvar_get_join_prev_re.match(f[i]): + if cvar_get_assign_re.match(f[i - 1]): + f[i - 1] = f"{f[i - 1].rstrip()} {f[i].lstrip()}" + del(f[i]) + i -= 1 + if cvar_get_incomplete_re.match(f[i]): + while not cvar_get_complete_re.match(f[i]): + f[i + 1] = f[i + 1].lstrip() + f[i] = f[i].rstrip() + if f[i][-1] == '"' and f[i + 1][0] == '"': + #string concatentation + f[i] = f[i][:-1] + f[i + 1][1:] + else: + f[i] = f"{f[i]} {f[i + 1]}" + del(f[i + 1]) + cd = cvar_decl_re.match(f[i]) + if cd: + if cd[3] not in cvar_decls: + cvar_decls[cd[3]] = [] + cvar_decls[cd[3]].append((fname, i)) + cl = cvar_listener_re.match(f[i]) + if cl: + if cl[1] not in cvar_listeners: + cvar_listeners[cl[1]] = [] + cvar_listeners[cl[1]].append((fname, i, cl[2])) + cc = cvar_create_re.match(f[i]) + if cc: + if cc.group(7): + default = 7 + else: + default = 5 + cc = cc.group(1, 2, default, 8, 12, 13) + if cc[0] not in cvar_dict: + cvar_dict[cc[0]] = cvar(*cc) + cvar_dict[cc[0]].add_file(fname, i) + cs = cvar_set_re.match(f[i]) + if cs: + cvar_sets.append((fname, i)) + i += 1 + fi.close() + +for f in sys.argv[1:]: + get_cvar_defs(f) +#for cv in cvar_decls.keys(): +# if cv not in cvar_dict: +# print(f"cvar {cv} declared but never created") +for file in files.items(): + fname,f = file + for i in range(len(f)): + for use in cvar_use_re.finditer(f[i]): + if use[1] in cvar_dict and cvar_dict[use[1]]: + cvar_dict[use[1]].add_use(use[2], fname, i) +keys = list(cvar_dict.keys()) +for cv in keys: + var = cvar_dict[cv] + if cv not in cvar_decls or var.callback not in cvar_listeners: + continue + if var.callback in cvar_listeners: + if var.callback in cvar_listeners_done: + if not var.callback in cvar_listeners_multi: + print(f"WARNING: {var.callback} has multiple uses") + cvar_listeners_multi.add (var.callback) + else: + cvar_listeners_done.add (var.callback); +cvar_listeners_done.clear() +for cv in keys: + var = cvar_dict[cv] + var.guess_type() + if var.c_name in cvar_rom: + print(var.c_name, 'rom') + var.set_rom() + if cv in cvar_decls: + if var.callback in cvar_listeners_multi: + var.data = f'&{var.c_name}' + for d in cvar_decls[cv]: + decl = cvar_decl_re.match(files[d[0]][d[1]]) + storage = decl[1].strip() + if storage == "extern": + subst = var.var(storage) + else: + subst = var.var(storage)+var.struct() + line_substitutions.append((d[0], (d[1], d[1] + 1), subst)) + for c in var.files: + line_substitutions.append((c[0], (c[1], c[1] + 1), var.register())) + for u in var.uses: + # use substitutions are done immediately because they never + # change the number of lines + field, fname, line = u + file = files[fname] + places = [] + for use in cvar_use_re.finditer(file[line]): + cv, field = use.group(1, 2) + if cv == var.c_name: + places.append((use.start(), use.end())) + places.reverse() + for p in places: + file[line] = file[line][:p[0]] + var.c_name + file[line][p[1]:] + modified.add(fname) + else: + #for f in cvar_dict[cv].files: + # print(f"{f[0]}:{f[1]}: {cv} created but not kept") + pass +for cv in keys: + var = cvar_dict[cv] + if cv not in cvar_decls or var.callback not in cvar_listeners: + continue + if var.callback in cvar_listeners_done: + continue + for listener in cvar_listeners[var.callback]: + fname, line, c_name = listener + file = files[fname] + file[line] = f"{var.callback} (void *data," " const cvar_t *cvar)\n" + modified.add(fname) + cvar_listeners_done.add (var.callback); + multi = var.callback in cvar_listeners_multi + line += 1 + while line < len(file) and file[line] != '}\n': + line += 1 + places = [] + for use in cvar_use_re.finditer(file[line]): + cv, field = use.group(1, 2) + if cv == c_name: + subst = f'*({var.c_type}*)data' if multi else var.c_name + places.append((use.start(), use.end(), subst)) + places.reverse() + for p in places: + file[line] = file[line][:p[0]] + p[2] + file[line][p[1]:] + modified.add(fname) + places = [] + for v in id_re.finditer(file[line]): + if v[1] == c_name: + places.append((v.start(), v.end(), "cvar")) + for p in places: + file[line] = file[line][:p[0]] + p[2] + file[line][p[1]:] + modified.add(fname) +for s in cvar_sets: + cs = cvar_set_re.match(files[s[0]][s[1]]) + subst = None + val = cs[4] + if cs[2] == "Cvar_SetValue" and cs[3] in cvar_dict: + if val[0] == '(': + #strip off a cast + val = val[val.index(')') + 1:].strip() + subst = f'{cs[1]}{cs[3]} = {val};{cs[5]}\n' + elif cs[2] == "Cvar_Set" and cs[3] in cvar_dict: + subst = f'{cs[1]}{cs[2]} ("{cvar_dict[cs[3]].name}", {val});{cs[5]}\n' + elif cs[2] == "Cvar_Set": + subst = f'{cs[1]}Cvar_SetVar ({cs[3]}, {val});{cs[5]}\n' + if subst: + line_substitutions.append((s[0], (s[1], s[1] + 1), subst)) +line_substitutions.sort(reverse=True, key=lambda s: s[1][1]) +for substitution in line_substitutions: + file, lines, subst = substitution + modified.add(file) + files[file][lines[0]:lines[1]] = subst +for f in files.keys(): + if f in modified: + file = open(f, "wt") + file.writelines(files[f]) + file.close () diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index b468cc5b3..20e59ea5c 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -234,10 +234,12 @@ init_qf (void) { Sys_Init (); - Cvar_Get ("pr_debug", va (0, "%d", 1+verbosity), 0, 0, ""); - Cvar_Get ("pr_source_path", source_path, 0, 0, ""); PR_Init_Cvars (); + pr_debug = 1 + verbosity; + free (pr_source_path); + pr_source_path = (char *) source_path; + pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; pr.reserved_edicts = &reserved_edicts; diff --git a/tools/qfcc/test/test-harness.c b/tools/qfcc/test/test-harness.c index a0a4bfd0c..b277e99f1 100644 --- a/tools/qfcc/test/test-harness.c +++ b/tools/qfcc/test/test-harness.c @@ -155,18 +155,10 @@ static void init_qf (void) { Sys_Init (); - Cvar_Get ("developer", va (0, "%d", options.developer), 0, 0, 0); + developer = options.developer; Memory_Init (Sys_Alloc (1024 * 1024), 1024 * 1024); - cvar_t *debug = Cvar_Get ("pr_debug", "2", 0, 0, 0); - Cvar_Get ("pr_boundscheck", "2", 0, 0, 0); - Cvar_Get ("pr_deadbeef_locals", "1", 0, 0, 0); - - if (options.trace > 1) { - Cvar_SetValue (debug, 4); - } - test_pr.pr_edicts = &edicts; test_pr.num_edicts = &num_edicts; test_pr.reserved_edicts = &reserved_edicts; @@ -177,6 +169,10 @@ init_qf (void) PR_Init_Cvars (); + pr_debug = options.trace > 1 ? 4 : 2; + pr_boundscheck = 2; + pr_deadbeef_locals = 1; + PR_AddLoadFunc (&test_pr, init_edicts); PR_Init (&test_pr); From 9f876390f08fa1e11f640b476034266819a130cc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 17:57:20 +0900 Subject: [PATCH 2676/3664] [input] Fix up some mistranslated cvars My script didn't know what type to make the cvars since they're not used directly by the code, so they got treated as strings instead of ints or floats. --- include/QF/input.h | 2 +- libs/input/in_common.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index 2b85ee3c4..6b4167aca 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -131,7 +131,7 @@ extern float in_amp; extern float in_pre_amp; extern int in_mouse_accel; extern int in_freelook; -extern char *lookstrafe; +extern int lookstrafe; #endif diff --git a/libs/input/in_common.c b/libs/input/in_common.c index de8e22a68..f2d895e10 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -107,41 +107,41 @@ static cvar_t in_freelook_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &in_freelook }, }; -char *in_mouse_filter; +int in_mouse_filter; static cvar_t in_mouse_filter_cvar = { .name = "in_mouse_filter", .description = "Toggle mouse input filtering.", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &in_mouse_filter }, + .value = { .type = &cexpr_int, .value = &in_mouse_filter }, }; -char *in_mouse_amp; +float in_mouse_amp; static cvar_t in_mouse_amp_cvar = { .name = "in_mouse_amp", .description = "mouse in_mouse_amp multiplier", .default_value = "15", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &in_mouse_amp }, + .value = { .type = &cexpr_float, .value = &in_mouse_amp }, }; -char *in_mouse_pre_amp; +float in_mouse_pre_amp; static cvar_t in_mouse_pre_amp_cvar = { .name = "in_mouse_pre_amp", .description = "mouse in_mouse_pre_amp multiplier", .default_value = "1", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &in_mouse_pre_amp }, + .value = { .type = &cexpr_float, .value = &in_mouse_pre_amp }, }; -char *lookstrafe; +int lookstrafe; static cvar_t lookstrafe_cvar = { .name = "lookstrafe", .description = "when mlook/klook on player will strafe", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &lookstrafe }, + .value = { .type = &cexpr_int, .value = &lookstrafe }, }; int64_t in_timeout = 10000;//10ms default timeout From 90447a5d3b543fab54c807cb2072636b798975d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 19:02:10 +0900 Subject: [PATCH 2677/3664] [quakefs] Ensure fs_sharepath and fs_userpath are never empty Other parts of quakefs treat an empty path as an error, so fs_sharepath and fs_userpath must never be empty or they will effectively be rejected. While the user explicitly setting them to empty strings is one way for them to become empty, another is QFS_CompressPath compressing '.' to an empty path, which makes it rather difficult to set up the traditional quake directory tree (ie, operate from the current directory). --- libs/util/quakefs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 162722a81..af40bfa75 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1436,6 +1436,10 @@ static void qfs_path_cvar (void *data, const cvar_t *cvar) { char *cpath = QFS_CompressPath (*(char **)data); + if (!*cpath) { + free (cpath); + cpath = strdup ("."); + } if (strcmp (cpath, *(char **)data)) { free (*(char **)cvar->value.value); *(char **)cvar->value.value = cpath; From bff0847761e51dc43cc5cce4859c644851a63a14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 20:04:06 +0900 Subject: [PATCH 2678/3664] [cvar] Clean up most misinterpreted cvar types The misinterpretations were due to either the cvar not being accessed directly by the engine, but via only the callback, or the cvars were accesssed only by progs (in which case, they should be float). The remainder are a potential enum (hud gravity) and a "too hard basket" (rcon password: need to figure out how I want to handle secret strings). --- libs/audio/cd_linux.c | 2 +- libs/audio/renderer/midi.c | 4 +-- libs/audio/renderer/snd_dma.c | 8 +++--- libs/console/console.c | 2 +- libs/console/server.c | 2 +- libs/gamecode/pr_debug.c | 2 +- libs/video/targets/context_win.c | 32 ++++++++++----------- libs/video/targets/in_x11.c | 4 +-- libs/video/targets/joy_win.c | 42 ++++++++++++++-------------- nq/include/game.h | 1 - nq/include/server.h | 1 - nq/source/cl_main.c | 8 +++--- nq/source/game.c | 6 ++-- nq/source/host.c | 16 +++++------ nq/source/sv_progs.c | 48 ++++++++++++++++---------------- qw/include/game.h | 1 - qw/include/server.h | 2 -- qw/include/sv_demo.h | 1 - qw/source/cl_main.c | 12 ++++---- qw/source/cl_skin.c | 8 +++--- qw/source/game.c | 4 +-- qw/source/sv_demo.c | 18 ++++++------ qw/source/sv_main.c | 20 ++++++------- qw/source/sv_progs.c | 4 +-- 24 files changed, 121 insertions(+), 127 deletions(-) diff --git a/libs/audio/cd_linux.c b/libs/audio/cd_linux.c index 15452ce8c..add4910be 100644 --- a/libs/audio/cd_linux.c +++ b/libs/audio/cd_linux.c @@ -84,7 +84,7 @@ static cvar_t mus_cddevice_cvar = { "device to use for CD music", .default_value = "/dev/cdrom", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &mus_cddevice }, + .value = { .type = 0, .value = &mus_cddevice }, }; static float bgmvolume; static cvar_t bgmvolume_cvar = { diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index f0dc91b58..3172c8ea2 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -57,14 +57,14 @@ typedef struct { static int midi_intiialized = 0; -static char *wildmidi_volume; +static float wildmidi_volume; static cvar_t wildmidi_volume_cvar = { .name = "wildmidi_volume", .description = "Set the Master Volume", .default_value = "100", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &wildmidi_volume }, + .value = { .type = &cexpr_float, .value = &wildmidi_volume }, }; static char *wildmidi_config; static cvar_t wildmidi_config_cvar = { diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index c8ab69577..0ec153d03 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -69,14 +69,14 @@ static cvar_t snd_volume_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_float, .value = &snd_volume }, }; -static char *nosound; +static int nosound; static cvar_t nosound_cvar = { .name = "nosound", .description = "Set to turn sound off", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &nosound }, + .value = { .type = &cexpr_int, .value = &nosound }, }; static float snd_mixahead; static cvar_t snd_mixahead_cvar = { @@ -97,14 +97,14 @@ static cvar_t snd_noextraupdate_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &snd_noextraupdate }, }; -static char *snd_show; +static int snd_show; static cvar_t snd_show_cvar = { .name = "snd_show", .description = "Toggles display of sounds currently being played", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &snd_show }, + .value = { .type = &cexpr_int, .value = &snd_show }, }; static general_data_t plugin_info_general_data; diff --git a/libs/console/console.c b/libs/console/console.c index 36f137423..7b5dcfeca 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -63,7 +63,7 @@ static cvar_t con_interpreter_cvar = { "Interpreter for the interactive console", .default_value = "id", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &con_interpreter }, + .value = { .type = 0, .value = &con_interpreter }, }; static sys_printf_t saved_sys_printf; diff --git a/libs/console/server.c b/libs/console/server.c index 3b10f64e6..bf2fb09e0 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -90,7 +90,7 @@ static cvar_t sv_logfile_cvar = { "\"filename:gzflags\"", .default_value = "none", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &sv_logfile }, + .value = { .type = 0, .value = &sv_logfile }, }; static exprenum_t sv_conmode_enum; static exprtype_t sv_conmode_type = { diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 101bb92dc..d27255e11 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -133,7 +133,7 @@ static cvar_t pr_source_path_cvar = { "where to look (within gamedir) for source files", .default_value = ".", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &pr_source_path }, + .value = { .type = 0, .value = &pr_source_path }, }; static char *source_path_string; static char **source_paths; diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index 0d3d8e973..ce9eb87b5 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -78,14 +78,14 @@ static cvar_t vid_mode_cvar = { }; // Note that 0 is MODE_WINDOWED -static char *_vid_default_mode; +int _vid_default_mode; static cvar_t _vid_default_mode_cvar = { .name = "_vid_default_mode", .description = "", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &_vid_default_mode }, + .value = { .type = &cexpr_int, .value = &_vid_default_mode }, }; // Note that 3 is MODE_FULLSCREEN_DEFAULT @@ -98,59 +98,59 @@ static cvar_t _vid_default_mode_win_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &_vid_default_mode_win }, }; -static char *vid_wait; +int vid_wait; static cvar_t vid_wait_cvar = { .name = "vid_wait", .description = "", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &vid_wait }, + .value = { .type = &cexpr_int, .value = &vid_wait }, }; -static char *vid_nopageflip; +int vid_nopageflip; static cvar_t vid_nopageflip_cvar = { .name = "vid_nopageflip", .description = "", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &vid_nopageflip }, + .value = { .type = &cexpr_int, .value = &vid_nopageflip }, }; -static char *_vid_wait_override; +int _vid_wait_override; static cvar_t _vid_wait_override_cvar = { .name = "_vid_wait_override", .description = "", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &_vid_wait_override }, + .value = { .type = &cexpr_int, .value = &_vid_wait_override }, }; -static char *vid_config_x; +int vid_config_x; static cvar_t vid_config_x_cvar = { .name = "vid_config_x", .description = "", .default_value = "800", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &vid_config_x }, + .value = { .type = &cexpr_int, .value = &vid_config_x }, }; -static char *vid_config_y; +int vid_config_y; static cvar_t vid_config_y_cvar = { .name = "vid_config_y", .description = "", .default_value = "600", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &vid_config_y }, + .value = { .type = &cexpr_int, .value = &vid_config_y }, }; -static char *vid_stretch_by_2; +int vid_stretch_by_2; static cvar_t vid_stretch_by_2_cvar = { .name = "vid_stretch_by_2", .description = "", .default_value = "1", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &vid_stretch_by_2 }, + .value = { .type = &cexpr_int, .value = &vid_stretch_by_2 }, }; static int _windowed_mouse; static cvar_t _windowed_mouse_cvar = { @@ -179,14 +179,14 @@ static cvar_t vid_windowed_mode_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &vid_windowed_mode }, }; -static char *block_switch; +int block_switch; static cvar_t block_switch_cvar = { .name = "block_switch", .description = "", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &block_switch }, + .value = { .type = &cexpr_int, .value = &block_switch }, }; static int vid_window_x; static cvar_t vid_window_x_cvar = { diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index f7552c424..80e435188 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -151,14 +151,14 @@ static cvar_t in_snd_block_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &in_snd_block }, }; -char *in_dga; +int in_dga; static cvar_t in_dga_cvar = { .name = "in_dga", .description = "DGA Input support", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &in_dga }, + .value = { .type = &cexpr_int, .value = &in_dga }, }; int in_mouse_accel; static cvar_t in_mouse_accel_cvar = { diff --git a/libs/video/targets/joy_win.c b/libs/video/targets/joy_win.c index 65c4d600c..56e8f49ce 100644 --- a/libs/video/targets/joy_win.c +++ b/libs/video/targets/joy_win.c @@ -46,14 +46,14 @@ #include "compat.h" // Joystick variables and structures -char *joy_sensitivity; +float joy_sensitivity; static cvar_t joy_sensitivity_cvar = { .name = "joy_sensitivity", .description = "Joystick sensitivity", .default_value = "1", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &joy_sensitivity }, + .value = { .type = &cexpr_float, .value = &joy_sensitivity }, }; // joystick defines and variables @@ -97,7 +97,7 @@ static cvar_t in_joystick_cvar = { "FIXME: No Description", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &in_joystick }, + .value = { .type = 0, .value = &in_joystick }, }; char *joy_name; static cvar_t joy_name_cvar = { @@ -171,77 +171,77 @@ static cvar_t joy_advaxisv_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &joy_advaxisv }, }; -char *joy_forwardthreshold; +float joy_forwardthreshold; static cvar_t joy_forwardthreshold_cvar = { .name = "joyforwardthreshold", .description = "FIXME: No Description", .default_value = "0.15", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &joy_forwardthreshold }, + .value = { .type = &cexpr_float, .value = &joy_forwardthreshold }, }; -char *joy_sidethreshold; +float joy_sidethreshold; static cvar_t joy_sidethreshold_cvar = { .name = "joysidethreshold", .description = "FIXME: No Description", .default_value = "0.15", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &joy_sidethreshold }, + .value = { .type = &cexpr_float, .value = &joy_sidethreshold }, }; -char *joy_pitchthreshold; +float joy_pitchthreshold; static cvar_t joy_pitchthreshold_cvar = { .name = "joypitchthreshold", .description = "FIXME: No Description", .default_value = "0.15", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &joy_pitchthreshold }, + .value = { .type = &cexpr_float, .value = &joy_pitchthreshold }, }; -char *joy_yawthreshold; +float joy_yawthreshold; static cvar_t joy_yawthreshold_cvar = { .name = "joyyawthreshold", .description = "FIXME: No Description", .default_value = "0.15", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &joy_yawthreshold }, + .value = { .type = &cexpr_float, .value = &joy_yawthreshold }, }; -char *joy_forwardsensitivity; +float joy_forwardsensitivity; static cvar_t joy_forwardsensitivity_cvar = { .name = "joyforwardsensitivity", .description = "FIXME: No Description", .default_value = "-1.0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &joy_forwardsensitivity }, + .value = { .type = &cexpr_float, .value = &joy_forwardsensitivity }, }; -char *joy_sidesensitivity; +float joy_sidesensitivity; static cvar_t joy_sidesensitivity_cvar = { .name = "joysidesensitivity", .description = "FIXME: No Description", .default_value = "-1.0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &joy_sidesensitivity }, + .value = { .type = &cexpr_float, .value = &joy_sidesensitivity }, }; -char *joy_pitchsensitivity; +float joy_pitchsensitivity; static cvar_t joy_pitchsensitivity_cvar = { .name = "joypitchsensitivity", .description = "FIXME: No Description", .default_value = "1.0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &joy_pitchsensitivity }, + .value = { .type = &cexpr_float, .value = &joy_pitchsensitivity }, }; -char *joy_yawsensitivity; +float joy_yawsensitivity; static cvar_t joy_yawsensitivity_cvar = { .name = "joyyawsensitivity", .description = "FIXME: No Description", .default_value = "-1.0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &joy_yawsensitivity }, + .value = { .type = &cexpr_float, .value = &joy_yawsensitivity }, }; int joy_wwhack1; static cvar_t joy_wwhack1_cvar = { @@ -252,14 +252,14 @@ static cvar_t joy_wwhack1_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &joy_wwhack1 }, }; -char *joy_wwhack2; +float joy_wwhack2; static cvar_t joy_wwhack2_cvar = { .name = "joywwhack2", .description = "FIXME: No Description", .default_value = "0.0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &joy_wwhack2 }, + .value = { .type = &cexpr_float, .value = &joy_wwhack2 }, }; int joy_debug; diff --git a/nq/include/game.h b/nq/include/game.h index 485c82426..55c53428f 100644 --- a/nq/include/game.h +++ b/nq/include/game.h @@ -156,7 +156,6 @@ extern int current_skill; // skill level for currently loaded level (in case extern qboolean isDedicated; extern qboolean standard_quake; -extern char *registered; struct memhunk_s; void Game_Init (struct memhunk_s *hunk); diff --git a/nq/include/server.h b/nq/include/server.h index 3518f3257..411768be5 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -206,7 +206,6 @@ extern int teamplay; extern int skill; extern int deathmatch; extern int coop; -extern char *fraglimit; extern int timelimit; extern float sv_rollangle; diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 25163ade7..06ebcb1e1 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -137,23 +137,23 @@ static cvar_t hud_time_cvar = { .value = { .type = &cexpr_int, .value = &hud_time }, }; -static char *r_ambient; +static int r_ambient; static cvar_t r_ambient_cvar = { .name = "r_ambient", .description = "Determines the ambient lighting for a level", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &r_ambient }, + .value = { .type = &cexpr_int, .value = &r_ambient }, }; -static char *r_drawflat; +static int r_drawflat; static cvar_t r_drawflat_cvar = { .name = "r_drawflat", .description = "Toggles the drawing of textures", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &r_drawflat }, + .value = { .type = &cexpr_int, .value = &r_drawflat }, }; int fps_count; diff --git a/nq/source/game.c b/nq/source/game.c index bbac0de20..249c679dc 100644 --- a/nq/source/game.c +++ b/nq/source/game.c @@ -40,14 +40,14 @@ qboolean standard_quake = false; -char *registered; +float registered; static cvar_t registered_cvar = { .name = "registered", .description = "Is the game the registered version. 1 yes 0 no", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = ®istered }, + .value = { .type = &cexpr_float, .value = ®istered }, }; char *cmdline; static cvar_t cmdline_cvar = { @@ -56,7 +56,7 @@ static cvar_t cmdline_cvar = { "None", .default_value = "0", .flags = CVAR_SERVERINFO, - .value = { .type = 0/* not used */, .value = &cmdline }, + .value = { .type = 0, .value = &cmdline }, }; int static_registered = 1; diff --git a/nq/source/host.c b/nq/source/host.c index dc45ef372..c309861fb 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -174,14 +174,14 @@ static cvar_t cl_quakerc_cvar = { .value = { .type = &cexpr_int, .value = &cl_quakerc }, }; -char *fraglimit; +float fraglimit; static cvar_t fraglimit_cvar = { .name = "fraglimit", .description = "None", .default_value = "0", .flags = CVAR_SERVERINFO, - .value = { .type = 0/* not used */, .value = &fraglimit }, + .value = { .type = &cexpr_float, .value = &fraglimit }, }; int timelimit; static cvar_t timelimit_cvar = { @@ -201,23 +201,23 @@ static cvar_t teamplay_cvar = { .flags = CVAR_SERVERINFO, .value = { .type = &cexpr_int, .value = &teamplay }, }; -char *noexit; +float noexit; static cvar_t noexit_cvar = { .name = "noexit", .description = "None", .default_value = "0", .flags = CVAR_SERVERINFO, - .value = { .type = 0/* not used */, .value = &noexit }, + .value = { .type = &cexpr_float, .value = &noexit }, }; -char *samelevel; +float samelevel; static cvar_t samelevel_cvar = { .name = "samelevel", .description = "None", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &samelevel }, + .value = { .type = &cexpr_float, .value = &samelevel }, }; int skill; @@ -258,14 +258,14 @@ static cvar_t pausable_cvar = { .value = { .type = &cexpr_int, .value = &pausable }, }; -char *temp1; +float temp1; static cvar_t temp1_cvar = { .name = "temp1", .description = "None", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &temp1 }, + .value = { .type = &cexpr_float, .value = &temp1 }, }; int cl_usleep; static cvar_t cl_usleep_cvar = { diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index e9e318a28..2637c4992 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -91,114 +91,114 @@ static cvar_t sv_progs_ext_cvar = { .flags = CVAR_NONE, .value = { .type = 0, .value = &sv_progs_ext }, }; -char *pr_checkextensions; +float pr_checkextensions; static cvar_t pr_checkextensions_cvar = { .name = "pr_checkextensions", .description = "indicate the presence of the checkextentions qc function", .default_value = "1", .flags = CVAR_ROM, - .value = { .type = 0/* not used */, .value = &pr_checkextensions }, + .value = { .type = &cexpr_float, .value = &pr_checkextensions }, }; -char *nomonsters; +float nomonsters; static cvar_t nomonsters_cvar = { .name = "nomonsters", .description = "No Description", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &nomonsters }, + .value = { .type = &cexpr_float, .value = &nomonsters }, }; -char *gamecfg; +float gamecfg; static cvar_t gamecfg_cvar = { .name = "gamecfg", .description = "No Description", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &gamecfg }, + .value = { .type = &cexpr_float, .value = &gamecfg }, }; -char *scratch1; +float scratch1; static cvar_t scratch1_cvar = { .name = "scratch1", .description = "No Description", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &scratch1 }, + .value = { .type = &cexpr_float, .value = &scratch1 }, }; -char *scratch2; +float scratch2; static cvar_t scratch2_cvar = { .name = "scratch2", .description = "No Description", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &scratch2 }, + .value = { .type = &cexpr_float, .value = &scratch2 }, }; -char *scratch3; +float scratch3; static cvar_t scratch3_cvar = { .name = "scratch3", .description = "No Description", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &scratch3 }, + .value = { .type = &cexpr_float, .value = &scratch3 }, }; -char *scratch4; +float scratch4; static cvar_t scratch4_cvar = { .name = "scratch4", .description = "No Description", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &scratch4 }, + .value = { .type = &cexpr_float, .value = &scratch4 }, }; -char *savedgamecfg; +float savedgamecfg; static cvar_t savedgamecfg_cvar = { .name = "savedgamecfg", .description = "No Description", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &savedgamecfg }, + .value = { .type = &cexpr_float, .value = &savedgamecfg }, }; -char *saved1; +float saved1; static cvar_t saved1_cvar = { .name = "saved1", .description = "No Description", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &saved1 }, + .value = { .type = &cexpr_float, .value = &saved1 }, }; -char *saved2; +float saved2; static cvar_t saved2_cvar = { .name = "saved2", .description = "No Description", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &saved2 }, + .value = { .type = &cexpr_float, .value = &saved2 }, }; -char *saved3; +float saved3; static cvar_t saved3_cvar = { .name = "saved3", .description = "No Description", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &saved3 }, + .value = { .type = &cexpr_float, .value = &saved3 }, }; -char *saved4; +float saved4; static cvar_t saved4_cvar = { .name = "saved4", .description = "No Description", .default_value = "0", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &saved4 }, + .value = { .type = &cexpr_float, .value = &saved4 }, }; static int sv_range; diff --git a/qw/include/game.h b/qw/include/game.h index 474b11c02..95b1bed1b 100644 --- a/qw/include/game.h +++ b/qw/include/game.h @@ -33,7 +33,6 @@ #include "QF/qtypes.h" #include "QF/qdefs.h" -extern char *registered; void Game_Init (void); void Game_Init_Cvars (void); diff --git a/qw/include/server.h b/qw/include/server.h index 9d00ee13e..44f57e10d 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -437,10 +437,8 @@ extern float sv_timeout; extern netadr_t master_adr[MAX_MASTERS]; // address of the master server -extern char *spawn; extern int teamplay; extern int deathmatch; -extern char *fraglimit; extern int timelimit; extern server_static_t svs; // persistant server info diff --git a/qw/include/sv_demo.h b/qw/include/sv_demo.h index 900362915..c1e608909 100644 --- a/qw/include/sv_demo.h +++ b/qw/include/sv_demo.h @@ -24,7 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern struct recorder_s demo; extern float sv_demofps; extern float sv_demoPings; -extern char *sv_demoMaxSize; void SV_Stop (int reason); void Demo_Init (void); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 73bf69394..bdb2ac24a 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -355,14 +355,14 @@ static cvar_t password_cvar = { .flags = CVAR_NONE, .value = { .type = 0, .value = &password }, }; -char *spectator; +int spectator; static cvar_t spectator_cvar = { .name = "spectator", .description = "Set to 1 before connecting to become a spectator", .default_value = "", .flags = CVAR_USERINFO, - .value = { .type = 0/* not used */, .value = &spectator }, + .value = { .type = &cexpr_int, .value = &spectator }, }; char *cl_name; static cvar_t cl_name_cvar = { @@ -391,23 +391,23 @@ static cvar_t rate_cvar = { .flags = CVAR_ARCHIVE | CVAR_USERINFO, .value = { .type = &cexpr_float, .value = &rate }, }; -char *noaim; +int noaim; static cvar_t noaim_cvar = { .name = "noaim", .description = "Auto aim off switch. Set to 1 to turn off.", .default_value = "0", .flags = CVAR_ARCHIVE | CVAR_USERINFO, - .value = { .type = 0/* not used */, .value = &noaim }, + .value = { .type = &cexpr_int, .value = &noaim }, }; -char *msg; +int msg; static cvar_t msg_cvar = { .name = "msg", .description = "Determines the type of messages reported 0 is maximum, 4 is none", .default_value = "1", .flags = CVAR_ARCHIVE | CVAR_USERINFO, - .value = { .type = 0/* not used */, .value = &msg }, + .value = { .type = &cexpr_int, .value = &msg }, }; /* GIB events */ diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index e509764cc..cbf02c133 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -68,23 +68,23 @@ static cvar_t skin_cvar = { .flags = CVAR_ARCHIVE | CVAR_USERINFO, .value = { .type = 0, .value = &skin }, }; -char *topcolor; +int topcolor; static cvar_t topcolor_cvar = { .name = "topcolor", .description = "Players color on top", .default_value = "0", .flags = CVAR_ARCHIVE | CVAR_USERINFO, - .value = { .type = 0/* not used */, .value = &topcolor }, + .value = { .type = &cexpr_int, .value = &topcolor }, }; -char *bottomcolor; +int bottomcolor; static cvar_t bottomcolor_cvar = { .name = "bottomcolor", .description = "Players color on bottom", .default_value = "0", .flags = CVAR_ARCHIVE | CVAR_USERINFO, - .value = { .type = 0/* not used */, .value = &bottomcolor }, + .value = { .type = &cexpr_int, .value = &bottomcolor }, }; diff --git a/qw/source/game.c b/qw/source/game.c index dba073f3e..fdd9842a2 100644 --- a/qw/source/game.c +++ b/qw/source/game.c @@ -46,14 +46,14 @@ #include "qw/include/game.h" #include "qw/include/server.h" -char *registered; +float registered; static cvar_t registered_cvar = { .name = "registered", .description = "Is the game the registered version. 1 yes 0 no", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = ®istered }, + .value = { .type = &cexpr_float, .value = ®istered }, }; int static_registered = 1; // only for startup check, then set diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index b0b8fb30c..c8e01f86f 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -90,14 +90,14 @@ static cvar_t sv_demoPings_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_float, .value = &sv_demoPings }, }; -char *sv_demoMaxSize; +int sv_demoMaxSize; static cvar_t sv_demoMaxSize_cvar = { .name = "sv_demoMaxSize", .description = "FIXME", .default_value = "20480", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &sv_demoMaxSize }, + .value = { .type = &cexpr_int, .value = &sv_demoMaxSize }, }; static int sv_demoUseCache; static cvar_t sv_demoUseCache_cvar = { @@ -108,23 +108,23 @@ static cvar_t sv_demoUseCache_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &sv_demoUseCache }, }; -static char *sv_demoCacheSize; +int sv_demoCacheSize; static cvar_t sv_demoCacheSize_cvar = { .name = "sv_demoCacheSize", .description = "FIXME", .default_value = 0, .flags = CVAR_ROM, - .value = { .type = 0/* not used */, .value = &sv_demoCacheSize }, + .value = { .type = &cexpr_int, .value = &sv_demoCacheSize }, }; -static char *sv_demoMaxDirSize; +int sv_demoMaxDirSize; static cvar_t sv_demoMaxDirSize_cvar = { .name = "sv_demoMaxDirSize", .description = "FIXME", .default_value = "102400", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &sv_demoMaxDirSize }, + .value = { .type = &cexpr_int, .value = &sv_demoMaxDirSize }, }; static char *sv_demoDir; static cvar_t sv_demoDir_cvar = { @@ -135,14 +135,14 @@ static cvar_t sv_demoDir_cvar = { .flags = CVAR_NONE, .value = { .type = 0, .value = &sv_demoDir }, }; -static char *sv_demoNoVis; +int sv_demoNoVis; static cvar_t sv_demoNoVis_cvar = { .name = "sv_demoNoVis", .description = "FIXME", .default_value = "1", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &sv_demoNoVis }, + .value = { .type = &cexpr_int, .value = &sv_demoNoVis }, }; static char *sv_demoPrefix; static cvar_t sv_demoPrefix_cvar = { @@ -178,7 +178,7 @@ static cvar_t sv_ondemoremove_cvar = { "FIXME", .default_value = "", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &sv_ondemoremove }, + .value = { .type = 0, .value = &sv_ondemoremove }, }; static int sv_demotxt; static cvar_t sv_demotxt_cvar = { diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 651bb8ccf..d5b504ba5 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -319,14 +319,14 @@ static cvar_t allow_download_maps_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &allow_download_maps }, }; -char *allow_download_demos; +int allow_download_demos; static cvar_t allow_download_demos_cvar = { .name = "allow_download_demos", .description = "Toggle if clients can download maps from the server", .default_value = "1", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &allow_download_demos }, + .value = { .type = &cexpr_int, .value = &allow_download_demos }, }; int sv_highchars; @@ -391,14 +391,14 @@ static cvar_t sv_timefmt_cvar = { }; // game rules mirrored in svs.info -char *fraglimit; +float fraglimit; static cvar_t fraglimit_cvar = { .name = "fraglimit", .description = "None", .default_value = "0", .flags = CVAR_SERVERINFO, - .value = { .type = 0/* not used */, .value = &fraglimit }, + .value = { .type = &cexpr_float, .value = &fraglimit }, }; int timelimit; static cvar_t timelimit_cvar = { @@ -418,14 +418,14 @@ static cvar_t teamplay_cvar = { .flags = CVAR_SERVERINFO, .value = { .type = &cexpr_int, .value = &teamplay }, }; -char *samelevel; +float samelevel; static cvar_t samelevel_cvar = { .name = "samelevel", .description = "None", .default_value = "0", .flags = CVAR_NONE, - .value = { .type = 0/* not used */, .value = &samelevel }, + .value = { .type = &cexpr_float, .value = &samelevel }, }; int maxclients; static cvar_t maxclients_cvar = { @@ -475,23 +475,23 @@ static cvar_t skill_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &skill }, }; -char *spawn; +float spawn; static cvar_t spawn_cvar = { .name = "spawn", .description = "Spawn the player entity", .default_value = "0", .flags = CVAR_SERVERINFO, - .value = { .type = 0/* not used */, .value = &spawn }, + .value = { .type = &cexpr_float, .value = &spawn }, }; -char *watervis; +int watervis; static cvar_t watervis_cvar = { .name = "watervis", .description = "Set nonzero to enable r_wateralpha on clients", .default_value = "0", .flags = CVAR_SERVERINFO, - .value = { .type = 0/* not used */, .value = &watervis }, + .value = { .type = &cexpr_int, .value = &watervis }, }; char *hostname; diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index fe95916b2..345efc945 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -102,14 +102,14 @@ static cvar_t sv_progs_ext_cvar = { .flags = CVAR_NONE, .value = { .type = 0, .value = &sv_progs_ext }, }; -char *pr_checkextensions; +float pr_checkextensions; static cvar_t pr_checkextensions_cvar = { .name = "pr_checkextensions", .description = "indicate the presence of the checkextentions qc function", .default_value = "1", .flags = CVAR_ROM, - .value = { .type = 0/* not used */, .value = &pr_checkextensions }, + .value = { .type = &cexpr_float, .value = &pr_checkextensions }, }; int sv_old_entity_free; static cvar_t sv_old_entity_free_cvar = { From bdb1192c13e3b2d16451a10a8e6dcc5686b6e04b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 20:46:06 +0900 Subject: [PATCH 2679/3664] [console] Fix missed changes to console line exec control I think I'd gotten distracted while making the changes to the server, then simply copied the partial changes to the client. It didn't blow up thanks to the backing store bing char * and the type sized for int, so safe on any platform, but useless as it wasn't connected properly. It's actually pretty neat being able to directly, but safely, control a function pointer via a cvar :) --- libs/console/client.c | 5 ++--- libs/console/server.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libs/console/client.c b/libs/console/client.c index 0c4970535..258821a1b 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -119,7 +119,7 @@ static cvar_t con_speed_cvar = { static exprenum_t cl_conmode_enum; static exprtype_t cl_conmode_type = { .name = "cl_conmode", - .size = sizeof (int), + .size = sizeof (con_data.exec_line), .data = &cl_conmode_enum, .get_string = cexpr_enum_get_string, }; @@ -144,14 +144,13 @@ static exprenum_t cl_conmode_enum = { &cl_conmode_type, &cl_conmode_symtab, }; -static char *cl_conmode; static cvar_t cl_conmode_cvar = { .name = "cl_conmode", .description = "Set the console input mode (command, chat, rcon)", .default_value = "command", .flags = CVAR_ARCHIVE, - .value = { .type = &cl_conmode_type, .value = &cl_conmode }, + .value = { .type = &cl_conmode_type, .value = &con_data.exec_line }, }; #define NUM_CON_TIMES 4 diff --git a/libs/console/server.c b/libs/console/server.c index bf2fb09e0..b0ba04a31 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -95,7 +95,7 @@ static cvar_t sv_logfile_cvar = { static exprenum_t sv_conmode_enum; static exprtype_t sv_conmode_type = { .name = "sv_conmode", - .size = sizeof (int), + .size = sizeof (sv_con_data.exec_line), .data = &sv_conmode_enum, .get_string = cexpr_enum_get_string, }; @@ -117,14 +117,13 @@ static exprenum_t sv_conmode_enum = { &sv_conmode_type, &sv_conmode_symtab, }; -static char *sv_conmode; static cvar_t sv_conmode_cvar = { .name = "sv_conmode", .description = "Set the console input mode (command, chat)", .default_value = "command", .flags = CVAR_NONE, - .value = { .type = &sv_conmode_type, .value = &sv_conmode }, + .value = { .type = &sv_conmode_type, .value = &sv_con_data.exec_line }, }; static int sv_use_curses; static cvar_t sv_use_curses_cvar = { From bafe54b0100f2b094ba4bd01d32614928bc46b88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 21:09:58 +0900 Subject: [PATCH 2680/3664] [view] Add a cexpr enum for grav_t And use it for hud_scoreboard_gravity. Putting the enum def in view made the most sense as view does own the base type and the enum is likely to be by useful for other settings. --- include/QF/ui/view.h | 2 ++ include/client/hud.h | 1 - libs/client/hud.c | 28 +++------------------------- libs/ui/view.c | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index d3d6f17e7..2a1e42bb7 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -66,6 +66,8 @@ typedef enum { grav_northwest, ///< +ve X right, +ve Y down, -X left, -ve Y up } grav_t; +extern struct exprtype_s grav_t_type; + /** The view object. */ typedef struct view_s view_t; diff --git a/include/client/hud.h b/include/client/hud.h index 82fa94365..042a78bbc 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -31,7 +31,6 @@ extern int hud_sb_lines; extern int hud_sbar; -extern char *hud_scoreboard_gravity; extern int hud_swap; extern struct view_s *sbar_view; diff --git a/libs/client/hud.c b/libs/client/hud.c index 5011b3a6e..c6ac8659e 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -52,7 +52,7 @@ static cvar_t hud_sbar_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &hud_sbar }, }; -char *hud_scoreboard_gravity; +grav_t hud_scoreboard_gravity; static cvar_t hud_scoreboard_gravity_cvar = { .name = "hud_scoreboard_gravity", .description = @@ -60,7 +60,7 @@ static cvar_t hud_scoreboard_gravity_cvar = { "northeast, west, east, southwest, south, southeast", .default_value = "center", .flags = CVAR_ARCHIVE, - .value = { .type = 0/* not used */, .value = &hud_scoreboard_gravity }, + .value = { .type = &grav_t_type, .value = &hud_scoreboard_gravity }, }; int hud_swap; static cvar_t hud_swap_cvar = { @@ -123,29 +123,7 @@ hud_swap_f (void *data, const cvar_t *cvar) static void hud_scoreboard_gravity_f (void *data, const cvar_t *cvar) { - grav_t grav; - - if (strequal (hud_scoreboard_gravity, "center")) - grav = grav_center; - else if (strequal (hud_scoreboard_gravity, "northwest")) - grav = grav_northwest; - else if (strequal (hud_scoreboard_gravity, "north")) - grav = grav_north; - else if (strequal (hud_scoreboard_gravity, "northeast")) - grav = grav_northeast; - else if (strequal (hud_scoreboard_gravity, "west")) - grav = grav_west; - else if (strequal (hud_scoreboard_gravity, "east")) - grav = grav_east; - else if (strequal (hud_scoreboard_gravity, "southwest")) - grav = grav_southwest; - else if (strequal (hud_scoreboard_gravity, "south")) - grav = grav_south; - else if (strequal (hud_scoreboard_gravity, "southeast")) - grav = grav_southeast; - else - grav = grav_center; - view_setgravity (hud_overlay_view, grav); + view_setgravity (hud_overlay_view, hud_scoreboard_gravity); } void diff --git a/libs/ui/view.c b/libs/ui/view.c index 71c4a3b4b..ac0c4cbfc 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -39,8 +39,47 @@ #endif #include +#include "QF/cexpr.h" #include "QF/ui/view.h" +static exprenum_t grav_t_enum; +exprtype_t grav_t_type = { + .name = "grav_t", + .size = sizeof (grav_t), + .data = &grav_t_enum, + .get_string = cexpr_enum_get_string, +}; +static grav_t grav_t_values[] = { + grav_center, + grav_north, + grav_northeast, + grav_east, + grav_southeast, + grav_south, + grav_southwest, + grav_west, + grav_northwest, +}; +static exprsym_t grav_t_symbols[] = { + { "center", &grav_t_type, grav_t_values + grav_center }, + { "north", &grav_t_type, grav_t_values + grav_north }, + { "northeast", &grav_t_type, grav_t_values + grav_northeast }, + { "east", &grav_t_type, grav_t_values + grav_east }, + { "southeast", &grav_t_type, grav_t_values + grav_southeast }, + { "south", &grav_t_type, grav_t_values + grav_south }, + { "southwest", &grav_t_type, grav_t_values + grav_southwest }, + { "west", &grav_t_type, grav_t_values + grav_west }, + { "northwest", &grav_t_type, grav_t_values + grav_northwest }, + {} +}; +static exprtab_t grav_t_symtab = { + grav_t_symbols, +}; +static exprenum_t grav_t_enum = { + &grav_t_type, + &grav_t_symtab, +}; + static void setgeometry (view_t *view) { From df4116a55d435f0da48046693a8a9914afaa9e06 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 24 Apr 2022 21:13:46 +0900 Subject: [PATCH 2681/3664] [qw] Add a FIXE for rcon_password --- qw/source/sv_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index d5b504ba5..fbb111ab1 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -242,7 +242,7 @@ static cvar_t rcon_password_cvar = { "Set the password for rcon 'root' commands", .default_value = "", .flags = CVAR_NONE, - .value = { .type = 0, .value = &rcon_password }, + .value = { .type=0/*FIXME want secret strings*/, .value = &rcon_password }, }; char *admin_password; static cvar_t admin_password_cvar = { From 8bd626a3e4a919bb5e1ecf3ae82f3ef2674cefcb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 25 Apr 2022 00:18:22 +0900 Subject: [PATCH 2682/3664] [hash] Add a couple of data-oriented functions Hash_Select returns a list of elements that match a given criterion (select callback returning non-0). Hash_ForEach simply calls a function for every element. --- include/QF/hash.h | 28 ++++++++++++++++++++++++++++ libs/util/hash.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/include/QF/hash.h b/include/QF/hash.h index f96682fd9..4a85b7ef2 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -38,6 +38,8 @@ typedef struct hashtab_s hashtab_t; typedef struct hashlink_s hashlink_t; +typedef int (*hash_select_t) (void *ele, void *data); +typedef void (*hash_action_t) (void *ele, void *data); /** create a new hash table. \param tsize table size. larger values will give better distribution, but @@ -213,6 +215,32 @@ size_t Hash_NumElements (hashtab_t *tab) __attribute__((pure)); */ void **Hash_GetList (hashtab_t *tab); +/** list of all matching elements in the table. + \param tab the table to search + \param select function that tests for a match. The expected return value + is 0 for no match, non-zero for a match. + \param data context data passed to the \a select function + \return a null terminated list of element pointers for all matchin + elements in the table + \note it is the caller's responsibilty to free() the list. + + returned list is guaranteed to be in reverse order of insertion for + elements with the same key. ie, deleting items from the list in list order + will delete the correct items. +*/ +void **Hash_Select (hashtab_t *tab, hash_select_t select, void *data); + + +/** call a function for all elements in the table. + \param tab the table to search + \param action function to call for each elelemnt + \param data context data passed to the \a action function + + call order is guaranteed to be in reverse order of insertion for + elements with the same key +*/ +void Hash_ForEach (hashtab_t *tab, hash_action_t action, void *data); + /** dump statistics about the hash table \param tab the table to dump */ diff --git a/libs/util/hash.c b/libs/util/hash.c index 13c090132..29d353c71 100644 --- a/libs/util/hash.c +++ b/libs/util/hash.c @@ -447,6 +447,43 @@ Hash_GetList (hashtab_t *tab) return list; } +VISIBLE void ** +Hash_Select (hashtab_t *tab, hash_select_t select, void *data) +{ + void **list; + void **l; + size_t ind; + + l = list = malloc ((tab->num_ele + 1) * sizeof (void *)); + if (!list) + return 0; + for (ind = 0; ind < tab->tab_size; ind++) { + hashlink_t *lnk; + + for (lnk = tab->tab[ind]; lnk; lnk = lnk->next) { + if (select (lnk->data, data)) { + *l++ = lnk->data; + } + } + } + *l++ = 0; + return list; +} + +VISIBLE void +Hash_ForEach (hashtab_t *tab, hash_action_t action, void *data) +{ + size_t ind; + + for (ind = 0; ind < tab->tab_size; ind++) { + hashlink_t *lnk; + + for (lnk = tab->tab[ind]; lnk; lnk = lnk->next) { + action (lnk->data, data); + } + } +} + static inline double sqr (double x) { From f6baa1608472b7b143390de2aad1f4582616f191 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 25 Apr 2022 00:23:28 +0900 Subject: [PATCH 2683/3664] [cvar] Remove the cvar lists They're really redundant, and removing the next pointer makes for a slightly smaller cvar struct. Cvar_Select was added to allow finding lists of matching cvars. The tab-completion and config saving code was reworked to use the hash table DO functions. Comments removed since the code was completely rewritten, but still many thanks to EvilTypeGuy and Fett. --- include/QF/cvar.h | 8 +- libs/net/nm/net_dgrm.c | 45 +++++-- libs/util/cvar.c | 275 ++++++++++++++++++++++++----------------- 3 files changed, 200 insertions(+), 128 deletions(-) diff --git a/include/QF/cvar.h b/include/QF/cvar.h index de87ee6ff..850c87623 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -46,17 +46,17 @@ typedef struct cvar_s { exprval_t value; int (*validator) (const struct cvar_s *var); struct cvar_listener_set_s *listeners; - struct cvar_s *next; } cvar_t; typedef struct cvar_listener_set_s LISTENER_SET_TYPE (cvar_t) cvar_listener_set_t; typedef void (*cvar_listener_t) (void *data, const cvar_t *cvar); +typedef int (*cvar_select_t) (const cvar_t *cvar, void *data); + typedef struct cvar_alias_s { char *name; ///< The name of the alias. cvar_t *cvar; ///< The cvar to which this alias refers - struct cvar_alias_s *next; ///< \internal LInked list of aliases. } cvar_alias_t; /** \name cvar_flags @@ -133,11 +133,11 @@ const char **Cvar_CompleteBuildList (const char *partial); // Returns a pointer to the Cvar, NULL if not found cvar_t *Cvar_FindVar (const char *var_name); +const cvar_t **Cvar_Select (cvar_select_t select, void *data); + void Cvar_Init_Hash (void); void Cvar_Init (void); -extern cvar_t *cvar_vars; - ///@} #endif//__QF_cvar_h diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index faa762f92..512fb6c7d 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -38,6 +38,7 @@ #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/sys.h" +#include "QF/heapsort.h" #include "QF/keys.h" #include "QF/qendian.h" #include "QF/msg.h" @@ -580,6 +581,26 @@ Datagram_Listen (qboolean state) } } +static const cvar_t **cvar_list; +static int num_cvars; + +static int +dg_cvar_cmp (const void *_a, const void *_b) +{ + const cvar_t * const *a = _a; + const cvar_t * const *b = _b; + return strcmp ((*a)->name, (*b)->name); +} + +static int +dg_cvar_select (const cvar_t *cvar, void *data) +{ + if (cvar->flags & CVAR_SERVERINFO) { + *(int *)data += 1; + return 1; + } + return 0; +} static qsocket_t * _Datagram_CheckNewConnections (void) @@ -690,25 +711,25 @@ _Datagram_CheckNewConnections (void) if (command == CCREQ_RULE_INFO) { const char *prevCvarName; - cvar_t *var; + const cvar_t *var; // find the search start location prevCvarName = MSG_ReadString (net_message); if (*prevCvarName) { - var = Cvar_FindVar (prevCvarName); + cvar_t key = { .name = prevCvarName }; + var = bsearch (&key, cvar_list, num_cvars, sizeof (cvar_t *), + dg_cvar_cmp); if (!var) - return NULL; - var = var->next; + return 0; + var++; } else { - var = cvar_vars; - } - - // search for the next server cvar - while (var) { - if (var->flags & CVAR_SERVERINFO) { - break; + if (cvar_list) { + free (cvar_list); } - var = var->next; + num_cvars = 0; + cvar_list = Cvar_Select (dg_cvar_select, &num_cvars); + heapsort (cvar_list, num_cvars, sizeof (cvar_t *), dg_cvar_cmp); + var = cvar_list[0]; } // send the response diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 8eb2ed3aa..3941d4cad 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -45,6 +45,7 @@ #include "QF/cvar.h" #include "QF/cmem.h" #include "QF/hash.h" +#include "QF/heapsort.h" #include "QF/mathlib.h" #include "QF/plist.h" #include "QF/qargs.h" @@ -97,11 +98,9 @@ static cvar_t developer_cvar = { .flags = CVAR_NONE, .value = { .type = &developer_type, .value = &developer }, }; -VISIBLE cvar_t *cvar_vars; -static cvar_t *user_cvars; static const char *cvar_null_string = ""; -static cvar_alias_t *calias_vars; static hashtab_t *cvar_hash; +static hashtab_t *user_cvar_hash; static hashtab_t *calias_hash; static cvar_t * @@ -115,10 +114,7 @@ cvar_create (const char *name, const char *value) var->value.value = var + 1; *(char **)var->value.value = strdup (value); - var->next = user_cvars; - user_cvars = var; - - Hash_Add (cvar_hash, var); + Hash_Add (user_cvar_hash, var); return var; } @@ -128,7 +124,7 @@ cvar_destroy (cvar_t *var) if (!(var->flags & CVAR_USER_CREATED)) { Sys_Error ("Attempt to destroy non-user cvar"); } - Hash_Del (cvar_hash, var->name); + Hash_Del (user_cvar_hash, var->name); free (*(char **) var->value.value); free ((char *) var->name); free (var); @@ -175,8 +171,6 @@ Cvar_MakeAlias (const char *name, cvar_t *cvar) if (!var) { alias = (cvar_alias_t *) calloc (1, sizeof (cvar_alias_t)); - alias->next = calias_vars; - calias_vars = alias; alias->name = strdup (name); alias->cvar = cvar; Hash_Add (calias_hash, alias); @@ -256,97 +250,90 @@ Cvar_VarString (const cvar_t *var) return cvar_string (var); } -VISIBLE const char * -Cvar_CompleteVariable (const char *partial) +typedef struct { + const char *match; + size_t match_len; + int num_matches; +} cvar_count_ctx_t; + +static void +cvar_match_count (void *ele, void *data) { - cvar_t *cvar; - cvar_alias_t *alias; - int len; + cvar_count_ctx_t *ctx = data; + const cvar_t *cvar = ele; - len = strlen (partial); - - if (!len) - return NULL; - - // check exact match - for (cvar = cvar_vars; cvar; cvar = cvar->next) - if (!strcmp (partial, cvar->name)) - return cvar->name; - - // check aliases too :) - for (alias = calias_vars; alias; alias = alias->next) - if (!strcmp (partial, alias->name)) - return alias->name; - - // check partial match - for (cvar = cvar_vars; cvar; cvar = cvar->next) - if (!strncmp (partial, cvar->name, len)) - return cvar->name; - - // check aliases too :) - for (alias = calias_vars; alias; alias = alias->next) - if (!strncmp (partial, alias->name, len)) - return alias->name; - - return NULL; + if (strncmp (cvar->name, ctx->match, ctx->match_len) == 0) { + ctx->num_matches++; + } } -/* - CVar_CompleteCountPossible - - New function for tab-completion system - Added by EvilTypeGuy - Thanks to Fett erich@heintz.com -*/ VISIBLE int Cvar_CompleteCountPossible (const char *partial) { - cvar_t *cvar; - int len; - int h; + cvar_count_ctx_t ctx = { + .match = partial, + .match_len = strlen (partial), + .num_matches = 0, + }; - h = 0; - len = strlen(partial); + Hash_ForEach (cvar_hash, cvar_match_count, &ctx); + Hash_ForEach (user_cvar_hash, cvar_match_count, &ctx); + // this is a bit of a hack, but both cvar_alias_t and cvar_t have + // name in the first file, so it will work out as that's the only + // criteron for a match + Hash_ForEach (calias_hash, cvar_match_count, &ctx); - if (!len) - return 0; - - // Loop through the cvars and count all possible matches - for (cvar = cvar_vars; cvar; cvar = cvar->next) - if (!strncmp(partial, cvar->name, len)) - h++; - - return h; + return ctx.num_matches; } -/* - CVar_CompleteBuildList +typedef struct { + const char *match; + size_t match_len; + const char **list; + int index; +} cvar_copy_ctx_t; - New function for tab-completion system - Added by EvilTypeGuy - Thanks to Fett erich@heintz.com - Thanks to taniwha -*/ -VISIBLE const char ** +static void +cvar_match_copy (void *ele, void *data) +{ + cvar_copy_ctx_t *ctx = data; + const cvar_t *cvar = ele; + + if (strncmp (cvar->name, ctx->match, ctx->match_len) == 0) { + ctx->list[ctx->index++] = cvar->name; + } +} + +static int +cvar_cmp_name (const void *_a, const void *_b) +{ + const char * const *a = _a; + const char * const *b = _b; + return strcmp (*a, *b); +} + +VISIBLE const char ** Cvar_CompleteBuildList (const char *partial) { - cvar_t *cvar; - int len = 0; - int bpos = 0; - int sizeofbuf = (Cvar_CompleteCountPossible (partial) + 1) * - sizeof (char *); - const char **buf; + int num_matches = Cvar_CompleteCountPossible (partial); - len = strlen(partial); - buf = malloc(sizeofbuf + sizeof (char *)); - SYS_CHECKMEM (buf); - // Loop through the alias list and print all matches - for (cvar = cvar_vars; cvar; cvar = cvar->next) - if (!strncmp(partial, cvar->name, len)) - buf[bpos++] = cvar->name; + cvar_copy_ctx_t ctx = { + .match = partial, + .match_len = strlen (partial), + .list = malloc((num_matches + 1) * sizeof (char *)), + .index = 0, + }; - buf[bpos] = NULL; - return buf; + Hash_ForEach (cvar_hash, cvar_match_copy, &ctx); + Hash_ForEach (user_cvar_hash, cvar_match_copy, &ctx); + // this is a bit of a hack, but both cvar_alias_t and cvar_t have + // name in the first file, so it will work out as that's the only + // criteron for a match + Hash_ForEach (calias_hash, cvar_match_copy, &ctx); + ctx.list[ctx.index] = 0; + fprintf (stderr, "%d %d\n", num_matches, ctx.index); + heapsort (ctx.list, ctx.index, sizeof (char *), cvar_cmp_name); + return ctx.list; } VISIBLE void @@ -464,6 +451,17 @@ Cvar_Command (void) return true; } +static void +cvar_write_variable (void *ele, void *data) +{ + cvar_t *cvar = ele; + QFile *f = data; + + if (cvar->flags & CVAR_ARCHIVE) { + Qprintf (f, "seta %s \"%s\"\n", cvar->name, cvar_string (cvar)); + } +} + /* Cvar_WriteVariables @@ -473,11 +471,19 @@ Cvar_Command (void) VISIBLE void Cvar_WriteVariables (QFile *f) { - cvar_t *var; + Hash_ForEach (cvar_hash, cvar_write_variable, f); + Hash_ForEach (user_cvar_hash, cvar_write_variable, f); +} - for (var = cvar_vars; var; var = var->next) - if (var->flags & CVAR_ARCHIVE) - Qprintf (f, "seta %s \"%s\"\n", var->name, cvar_string (var)); +static void +cvar_write_config (void *ele, void *data) +{ + cvar_t *cvar = ele; + plitem_t *cfg = data; + + if (cvar->flags & CVAR_ARCHIVE) { + PL_D_AddObject (cfg, cvar->name, PL_NewString (cvar_string (cvar))); + } } VISIBLE void @@ -485,11 +491,8 @@ Cvar_SaveConfig (plitem_t *config) { plitem_t *cvars = PL_NewDictionary (0); //FIXME hashlinks PL_D_AddObject (config, "cvars", cvars); - for (cvar_t *var = cvar_vars; var; var = var->next) { - if (var->flags & CVAR_ARCHIVE) { - PL_D_AddObject (cvars, var->name, PL_NewString (cvar_string (var))); - } - } + Hash_ForEach (cvar_hash, cvar_write_config, cvars); + Hash_ForEach (user_cvar_hash, cvar_write_config, cvars); } VISIBLE void @@ -704,35 +707,49 @@ Cvar_Reset_f (void) } } +static void +cvar_reset_var (void *ele, void *data) +{ + cvar_t *var = ele; + if (!(var->flags & CVAR_ROM)) + Cvar_Reset (var); +} + static void Cvar_ResetAll_f (void) { - cvar_t *var; + Hash_ForEach (cvar_hash, cvar_reset_var, 0); +} - for (var = cvar_vars; var; var = var->next) - if (!(var->flags & CVAR_ROM)) - Cvar_Reset (var); +static int +cvar_cmp (const void *_a, const void *_b) +{ + const cvar_t * const *a = _a; + const cvar_t * const *b = _b; + return strcmp ((*a)->name, (*b)->name); } static void Cvar_CvarList_f (void) { - cvar_t *var; - int i; int showhelp = 0; - const char *flags; - if (Cmd_Argc () > 1) { showhelp = 1; if (strequal (Cmd_Argv (1), "cfg")) showhelp++; } - for (var = cvar_vars, i = 0; var; var = var->next, i++) { - flags = va (0, "%c%c%c%c", - var->flags & CVAR_ROM ? 'r' : ' ', - var->flags & CVAR_ARCHIVE ? '*' : ' ', - var->flags & CVAR_USERINFO ? 'u' : ' ', - var->flags & CVAR_SERVERINFO ? 's' : ' '); + + void **cvar_list = Hash_GetList (cvar_hash); + int num_vars = Hash_NumElements (cvar_hash); + heapsort (cvar_list, num_vars, sizeof (void *), cvar_cmp); + + for (cvar_t **cvar = (cvar_t **) cvar_list; *cvar; cvar++) { + cvar_t *var = *cvar; + const char *flags = va (0, "%c%c%c%c", + var->flags & CVAR_ROM ? 'r' : ' ', + var->flags & CVAR_ARCHIVE ? '*' : ' ', + var->flags & CVAR_USERINFO ? 'u' : ' ', + var->flags & CVAR_SERVERINFO ? 's' : ' '); if (showhelp == 2) Sys_Printf ("//%s %s\n%s \"%s\"\n\n", flags, var->description, var->name, cvar_string (var)); @@ -742,7 +759,7 @@ Cvar_CvarList_f (void) Sys_Printf ("%s %s\n", flags, var->name); } - Sys_Printf ("------------\n%d variables\n", i); + Sys_Printf ("------------\n%d variables\n", num_vars); } static const char * @@ -771,6 +788,7 @@ VISIBLE void Cvar_Init_Hash (void) { cvar_hash = Hash_NewTable (1021, cvar_get_key, 0, 0, 0); + user_cvar_hash = Hash_NewTable (1021, cvar_get_key, 0, 0, 0); calias_hash = Hash_NewTable (1021, calias_get_key, calias_free, 0, 0); } @@ -809,15 +827,13 @@ Cvar_Register (cvar_t *var, cvar_listener_t listener, void *data) Sys_Error ("Cvar %s already registered", var->name); } - if ((user_var = Hash_Find (cvar_hash, var->name))) { + if ((user_var = Hash_Find (user_cvar_hash, var->name))) { cvar_setvar (var, cvar_string (user_var)); cvar_destroy (user_var); } else { cvar_setvar (var, var->default_value); } var->flags |= CVAR_REGISTERED; - var->next = cvar_vars; - cvar_vars = var; if (listener) { Cvar_AddListener (var, listener, data); @@ -843,3 +859,38 @@ Cvar_SetFlags (cvar_t *var, int cvarflags) var->flags = cvarflags; } + +typedef struct { + cvar_select_t select; + void *data; + const cvar_t **list; + int index; +} cvar_select_ctx_t; + +static void +cvar_select (void *ele, void *data) +{ + const cvar_t *cvar = ele; + cvar_select_ctx_t *ctx = data; + + if (ctx->select (cvar, ctx->data)) { + ctx->list[ctx->index++] = cvar; + } +} + +VISIBLE const cvar_t ** +Cvar_Select (cvar_select_t select, void *data) +{ + int num_cvars = Hash_NumElements (cvar_hash) + + Hash_NumElements (user_cvar_hash); + cvar_select_ctx_t ctx = { + .select = select, + .data = data, + .list = malloc ((num_cvars + 1) * sizeof (cvar_t *)), + .index = 0, + }; + Hash_ForEach (cvar_hash, cvar_select, &ctx); + Hash_ForEach (user_cvar_hash, cvar_select, &ctx); + ctx.list[num_cvars] = 0; + return ctx.list; +} From 0b912795d0daf33c234b97f7d1cc35ecd991fbe9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 1 Apr 2022 15:14:56 +0900 Subject: [PATCH 2684/3664] [vulkan] Use host-cached memory for staging buffers It makes a significant difference to level load times (approximately halves them for demo1 and demo2). Nicely, it turns out I had implemented the rest of the staging buffer code (in particular, flushing) correctly in that it seems there's no corruption any of the data. --- libs/video/renderer/vulkan/staging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 660e61a64..e16aa49df 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -55,7 +55,7 @@ QFV_CreateStagingBuffer (qfv_device_t *device, const char *name, size_t size, QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, stage->buffer, dsprintf (str, "staging:buffer:%s", name)); stage->memory = QFV_AllocBufferMemory (device, stage->buffer, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, size, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, stage->memory, dsprintf (str, "staging:memory:%s", name)); From 7ef9aab7f3f229b2939d9f63dc4cfc484623c8f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 6 Apr 2022 14:40:40 +0900 Subject: [PATCH 2685/3664] [vulkan] Use cached memory for the bsp index buffer Since it is updated every frame, it needs to be as fast as possible for the cpu code. This seems to make a difference of about 10us (~130 -> ~120) when testing in marcher. Not a huge change, but the timing calculation was wrapped around the entire base world pass, so there was a fair bit of overhead from bsp traversal etc. --- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index d21f10d63..e9ad1abd9 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -522,7 +522,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) "buffer:bsp:index"); bctx->index_memory = QFV_AllocBufferMemory (device, bctx->index_buffer, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, index_buffer_size, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, bctx->index_memory, "memory:bsp:index"); From 98cbacfe9df97fae5a7627a973cea48108c13690 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 07:14:03 +0900 Subject: [PATCH 2686/3664] [renderer] Remove redundant calls to visit_leaf I doubt the calls were ever actually made in a normal map due to the node actually being a node when breaking out of the loop, but when I experimented with an empty world model (no nodes, one infinite empty leaf) I found that visit_leaf was getting called twice instead of once. --- libs/video/renderer/gl/gl_rsurf.c | 2 -- libs/video/renderer/glsl/glsl_bsp.c | 2 -- libs/video/renderer/sw/sw_rbsp.c | 2 -- libs/video/renderer/vulkan/vulkan_bsp.c | 2 -- 4 files changed, 8 deletions(-) diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index c9c143c08..a796c1462 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -712,8 +712,6 @@ R_VisitWorldNodes (glbspctx_t *bctx) } break; } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); } void diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index cfdcec3b9..a4bd95182 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -831,8 +831,6 @@ R_VisitWorldNodes (glslbspctx_t *bctx) } break; } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); } static void diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 81c8efc44..1362f9436 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -513,8 +513,6 @@ R_VisitWorldNodes (swbspctx_t *bctx, int clipflags) } break; } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); } void diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 336c4b08a..c7ee0cd2e 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -746,8 +746,6 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) } break; } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); } static void From a9b8241a744841b5b809a858867b38f53cd911ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 07:19:35 +0900 Subject: [PATCH 2687/3664] [ruamoko] Fix some misnamed parameters IN_GetButtonName and IN_GetButtonNumber mentioned axis instead of button. A tad confusing. --- ruamoko/include/input.h | 4 ++-- ruamoko/lib/input.r | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ruamoko/include/input.h b/ruamoko/include/input.h index 31408cfc9..511d43e4e 100644 --- a/ruamoko/include/input.h +++ b/ruamoko/include/input.h @@ -13,9 +13,9 @@ string IN_GetDeviceId (int devid); //IN_AxisInfo (); //IN_ButtonInfo (); string IN_GetAxisName (int devid, int axis); -string IN_GetButtonName (int devid, int axis); +string IN_GetButtonName (int devid, int button); int IN_GetAxisNumber (int devid, string axis); -int IN_GetButtonNumber (int devid, string axis); +int IN_GetButtonNumber (int devid, string button); void IN_ProcessEvents (void); void IN_ClearStates (void); int IN_GetAxisInfo (int devid, int axis, in_axisinfo_t *info); diff --git a/ruamoko/lib/input.r b/ruamoko/lib/input.r index 34059f853..fa91c6b1f 100644 --- a/ruamoko/lib/input.r +++ b/ruamoko/lib/input.r @@ -9,9 +9,9 @@ string IN_GetDeviceId (int devid) = #0; //IN_AxisInfo () = #0; //IN_ButtonInfo () = #0; string IN_GetAxisName (int devid, int axis) = #0; -string IN_GetButtonName (int devid, int axis) = #0; +string IN_GetButtonName (int devid, int button) = #0; int IN_GetAxisNumber (int devid, string axis) = #0; -int IN_GetButtonNumber (int devid, string axis) = #0; +int IN_GetButtonNumber (int devid, string button) = #0; void IN_ProcessEvents (void) = #0; void IN_ClearStates (void) = #0; int IN_GetAxisInfo (int devid, int axis, in_axisinfo_t *info) = #0; From 5703df00fd27ee81d33888c075d2b445f3192d18 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 07:22:45 +0900 Subject: [PATCH 2688/3664] [renderer] Don't try to draw a nonexistent view model Doing so doesn't end well (segfault). This is a bit of a hack until I come up with a design for configurable scene rendering. --- libs/video/renderer/gl/gl_rmain.c | 4 +++- libs/video/renderer/glsl/glsl_main.c | 4 +++- libs/video/renderer/sw/sw_rmain.c | 4 +++- libs/video/renderer/vulkan/vulkan_main.c | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 720bf9469..6d171ac82 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -278,7 +278,9 @@ gl_R_RenderView (void) gl_R_DrawWorld (); S_ExtraUpdate (); // don't let sound get messed up if going slow gl_R_RenderDlights (); - R_DrawViewModel (); + if (vr_data.view_model) { + R_DrawViewModel (); + } gl_Fog_DisableGFog (); } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index a2fa1f8f6..ba5ef36f2 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -142,7 +142,9 @@ glsl_R_RenderView (void) R_SetupView (); glsl_R_DrawWorld (); glsl_R_DrawSky (); - R_DrawViewModel (); + if (vr_data.view_model) { + R_DrawViewModel (); + } } static void diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 9f9b852a3..e05755a80 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -589,7 +589,9 @@ R_RenderView_ (void) R_EdgeDrawing (r_ent_queue); - R_DrawViewModel (); + if (vr_data.view_model) { + R_DrawViewModel (); + } if (r_aliasstats) R_PrintAliasStats (); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 4bb82ecbc..6acf30d09 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -122,7 +122,9 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) Vulkan_DrawWorld (rFrame); Vulkan_DrawSky (rFrame); - Vulkan_DrawViewModel (ctx); + if (vr_data.view_model) { + Vulkan_DrawViewModel (ctx); + } Vulkan_DrawWaterSurfaces (rFrame); Vulkan_Bsp_Flush (ctx); } From c4d56afd335b0dcb647f479a3a385739d79c4fea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 07:26:32 +0900 Subject: [PATCH 2689/3664] [vulkan] Cope with an empty world model Vulkan doesn't appreciate the empty buffers that result from the model not having any textures or surfaces that can be rendered (rightfully so, for such a bare-metal api). --- libs/models/brush/vulkan_model_brush.c | 4 +++- libs/video/renderer/vulkan/vulkan_bsp.c | 10 ++++++++++ libs/video/renderer/vulkan/vulkan_lighting.c | 18 ++++++++++++------ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index 2fcc9f5bd..b1933de59 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -303,7 +303,9 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) mod->data = mctx; r_notexture_mip->render = &vulkan_notexture; - load_textures (mod, ctx); + if (mod->brush.numtextures) { + load_textures (mod, ctx); + } return; } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index c7ee0cd2e..b202fd988 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -413,6 +413,10 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) bsppoly_t *poly; mod_brush_t *brush; + if (!num_models) { + return; + } + // run through all surfaces, chaining them to their textures, thus // effectively sorting the surfaces by texture (without worrying about // surface order on the same texture chain). @@ -1037,6 +1041,9 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bctx->color = 0; R_VisitWorldNodes (brush, ctx); + if (!bctx->vertex_buffer) { + return; + } if (r_drawentities) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; @@ -1089,6 +1096,9 @@ Vulkan_Bsp_Flush (vulkan_ctx_t *ctx) size_t offset = bframe->index_offset; size_t size = bframe->index_count * sizeof (uint32_t); + if (!bframe->index_count) { + return; + } offset &= ~atom_mask; size = (size + atom_mask) & ~atom_mask; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 83e7e6fdc..33b13a22d 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -927,6 +927,10 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) lightingctx_t *lctx = ctx->lighting_context; plitem_t *entities = 0; + if (!entity_data) { + return; + } + lctx->lights.size = 0; lctx->lightleafs.size = 0; lctx->lightmats.size = 0; @@ -1006,11 +1010,13 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) PL_Free (entities); } Sys_MaskPrintf (SYS_vulkan, "loaded %zd lights\n", lctx->lights.size); - build_shadow_maps (lctx, ctx); - create_light_matrices (lctx); - locate_lights (model, lctx); - for (size_t i = 0; i < lctx->lights.size; i++) { - dump_light (&lctx->lights.a[i], lctx->lightleafs.a[i], - lctx->lightmats.a[i]); + if (lctx->lights.size) { + build_shadow_maps (lctx, ctx); + create_light_matrices (lctx); + locate_lights (model, lctx); + for (size_t i = 0; i < lctx->lights.size; i++) { + dump_light (&lctx->lights.a[i], lctx->lightleafs.a[i], + lctx->lightmats.a[i]); + } } } From 5c67f95edd0ae0d8f2f69ba6cbe2f99f0c63780c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 07:34:53 +0900 Subject: [PATCH 2690/3664] [qwaq] Set the world model to an empty world The goal is to have somewhere to put entities so they can be rendered. I suspect I could have used a bsp tree to partition space for frustum culling, but it's probably not worth it at this stage (but shouldn't require any changes to the engine: just the model). --- ruamoko/qwaq/builtins/graphics.c | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 1d6841998..0e272a07a 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -86,6 +86,40 @@ static progs_t *bi_rprogs; static pr_func_t qc2d; static int event_handler_id; +static mleaf_t empty_leafs[] = { + [1] = { + .contents = CONTENTS_EMPTY, + .mins = {-INFINITY, -INFINITY, -INFINITY}, + .maxs = { INFINITY, INFINITY, INFINITY}, + }, +}; + +static mnode_t *empty_leaf_parents[] = { + [1] = 0, +}; + +static int empty_leaf_flags[] = { + [1] = 0, +}; + +static char empty_entities[] = { 0 }; + +static model_t empty_world = { + .type = mod_brush, + .radius = INFINITY, + .mins = {-INFINITY, -INFINITY, -INFINITY}, + .maxs = { INFINITY, INFINITY, INFINITY}, + .brush = { + .modleafs = 2, + .visleafs = 1, + .nodes = (mnode_t *) &empty_leafs[1], + .leafs = empty_leafs, + .entities = empty_entities, + .leaf_parents = empty_leaf_parents, + .leaf_flags = empty_leaf_flags, + }, +}; + static void bi_2d (void) { @@ -196,4 +230,8 @@ BI_Graphics_Init (progs_t *pr) //CDAudio_Init (); Con_NewMap (); basetime = Sys_DoubleTime (); + if (mod_funcs->Mod_ProcessTexture) { + mod_funcs->Mod_ProcessTexture (&empty_world, 0); + } + r_funcs->R_NewMap (&empty_world, 0, 0); } From 6d62e91ce7d809fed8ba8078d0894b201ab12ebb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 15:10:00 +0900 Subject: [PATCH 2691/3664] [gamecode] Clean up progs data access pr_type_t now contains only the one "value" field, and all the access macros now use their PACKED variant for base access, making access to larger types more consistent with the smaller types. --- include/QF/progs.h | 130 ++++++++++++++++++---------- include/QF/progs/pr_comp.h | 18 ++-- libs/gamecode/pr_debug.c | 60 ++++++------- libs/gamecode/pr_exec.c | 144 ++++++++++++++----------------- libs/gamecode/pr_parse.c | 30 +++---- libs/gamecode/pr_strings.c | 4 +- libs/gib/bi_gib.c | 3 +- libs/ruamoko/pr_cmds.c | 4 +- libs/ruamoko/rua_hash.c | 6 +- libs/ruamoko/rua_obj.c | 8 +- nq/include/sv_progs.h | 8 +- nq/source/sv_pr_cmds.c | 2 +- qw/include/sv_progs.h | 8 +- qw/source/sv_pr_cmds.c | 2 +- qw/source/sv_progs.c | 20 ++--- tools/qfcc/include/obj_file.h | 2 +- tools/qfcc/include/qfcc.h | 11 +-- tools/qfcc/source/def.c | 4 +- tools/qfcc/source/dump_globals.c | 2 +- tools/qfcc/source/obj_file.c | 2 +- tools/qfcc/source/qfcc.c | 4 +- tools/qfcc/source/reloc.c | 4 +- tools/qfcc/source/struct.c | 2 +- tools/qfcc/source/value.c | 2 +- 24 files changed, 248 insertions(+), 232 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index b90c96e99..958bbd767 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -403,16 +403,6 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ ///@{ -/** \internal - \param p pointer to ::progs_t VM struct - \param o offset into global data space - \param t typename prefix (see pr_type_u) - \return lvalue of the appropriate type - - \hideinitializer -*/ -#define G_var(p,o,t) ((p)->pr_globals[o].t##_var) - /** Access a global as an arbitray type. More direct than G_STRUCT @@ -428,6 +418,16 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define G_PACKED(p,t,o) (*(t *) &(p)->pr_globals[o]) +/** \internal + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \param t typename prefix (see pr_type_u) + \return lvalue of the appropriate type + + \hideinitializer +*/ +#define G_var(p,o,t) G_PACKED(p, pr_##t##_t, o) + /** Access a float global. Can be assigned to. \par QC type: @@ -450,7 +450,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_DOUBLE(p,o) (*(double *) ((p)->pr_globals + o)) +#define G_DOUBLE(p,o) G_var (p, o, double) /** Access an int global. Can be assigned to. @@ -486,7 +486,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_VECTOR(p,o) (&G_var (p, o, vector)) +#define G_VECTOR(p,o) (&G_var (p, o, float)) /** Access a quaternion global. Can be assigned to. @@ -498,7 +498,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_QUAT(p,o) (&G_var (p, o, quat)) +#define G_QUAT(p,o) (&G_var (p, o, float)) /** Access a string index global. Can be assigned to. @@ -534,8 +534,31 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define G_POINTER(p,o) G_var (p, o, pointer) +#define G_POINTER(p,o) G_var (p, o, ptr) +/** Access a field global. + + \par QC type: + \c field + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \return field offset + + \hideinitializer +*/ +#define G_FIELD(p,o) G_var (p, o, field) + +/** Access an entity global. + + \par QC type: + \c entity + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \return entity "pointer" + + \hideinitializer +*/ +#define G_ENTITY(p,o) G_var (p, o, entity) /** Access an entity global. @@ -620,16 +643,6 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ ///@{ -/** \internal - \param p pointer to ::progs_t VM struct - \param n parameter number (0-7) - \param t typename prefix (see pr_type_u) - \return lvalue of the appropriate type - - \hideinitializer -*/ -#define P_var(p,n,t) ((p)->pr_params[n]->t##_var) - /** Access a parameter as an arbitray type. \par QC type: @@ -644,6 +657,16 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define P_PACKED(p,t,n) (*(t *) (p)->pr_params[n]) +/** \internal + \param p pointer to ::progs_t VM struct + \param n parameter number (0-7) + \param t typename prefix (see pr_type_u) + \return lvalue of the appropriate type + + \hideinitializer +*/ +#define P_var(p,n,t) P_PACKED(p, pr_##t##_t, n) + /** Access a float parameter. Can be assigned to. \par QC type: @@ -666,7 +689,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_DOUBLE(p,n) P_PACKED(p, double, n) +#define P_DOUBLE(p,n) P_var (p, n, double) /** Access an int parameter. Can be assigned to. @@ -702,7 +725,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_VECTOR(p,n) (&P_var (p, n, vector)) +#define P_VECTOR(p,n) (&P_var (p, n, float)) /** Access a quaterion parameter. Can be used any way a quat_t variable can. @@ -714,7 +737,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_QUAT(p,n) (&P_var (p, n, quat)) +#define P_QUAT(p,n) (&P_var (p, n, float)) /** Access a string index parameter. Can be assigned to. @@ -750,7 +773,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define P_POINTER(p,n) P_var (p, n, pointer) +#define P_POINTER(p,n) P_var (p, n, ptr) /** Access an entity parameter. @@ -839,16 +862,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ ///@{ -/** \internal - \param p pointer to ::progs_t VM struct - \param t typename prefix (see pr_type_u) - \return lvalue of the appropriate type - - \hideinitializer -*/ -#define R_var(p,t) ((p)->pr_return->t##_var) - -/** Access the VM function return value parameter as an arbitray type. +/** Access the VM function return value as an arbitray type. \par QC type: \c struct etc small enough to fit in the return slot @@ -861,6 +875,15 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_PACKED(p,t) (*(t *) (p)->pr_return) +/** \internal + \param p pointer to ::progs_t VM struct + \param t typename prefix (see pr_type_u) + \return lvalue of the appropriate type + + \hideinitializer +*/ +#define R_var(p,t) R_PACKED(p, pr_##t##_t) + /** Access the VM function return value as a \c float \par QC type: @@ -881,7 +904,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_DOUBLE(p) R_PACKED (p, double) +#define R_DOUBLE(p) R_var (p, double) /** Access the VM function return value as a \c ::pr_int_t (AKA int32_t) @@ -914,7 +937,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_VECTOR(p) (&R_var (p, vector)) +#define R_VECTOR(p) (&R_var (p, float)) /** Access the VM function return value as a \c ::quat_t quaternion. @@ -925,7 +948,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_QUAT(p) (&R_var (p, quat)) +#define R_QUAT(p) (&R_var (p, float)) /** Access the VM function return value as a ::pr_string_t (a VM string reference). @@ -958,7 +981,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define R_POINTER(p) R_var (p, pointer) +#define R_POINTER(p) R_var (p, ptr) /** Set the return value to the given C string. The returned string will @@ -1036,6 +1059,19 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define E_fld(e,o) ((e)->pr->pr_edict_area[(e)->edict + (o)]) +/** Access an entity field as an arbitray type. + + \par QC type: + \c struct etc small enough to fit in a single parameter + \param e pointer to the entity + \param t C type of the structure + \param o field offset into entity data space + \return structure lvalue. use & to make a pointer of the + appropriate type. + + \hideinitializer +*/ +#define E_PACKED(e,t,o) (*(t *) &E_fld (e, o)) /** \internal \param e pointer to the entity @@ -1045,7 +1081,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_var(e,o,t) (E_fld (e,o).t##_var) +#define E_var(e,o,t) E_PACKED (e, pr_##t##_t,o) /** Access a float entity field. Can be assigned to. @@ -1070,7 +1106,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_DOUBLE(e,o) (*(double *) ((e)->v + o)) +#define E_DOUBLE(e,o) E_var (e, o, double) /** Access an int entity field. Can be assigned to. @@ -1106,7 +1142,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_VECTOR(e,o) (&E_var (e, o, vector)) +#define E_VECTOR(e,o) (&E_var (e, o, float)) /** Access a quaternion entity field. Can be used any way a quat_t variable can. @@ -1119,7 +1155,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_QUAT(e,o) E_var (e, o, quat) +#define E_QUAT(e,o) E_var (e, o, float) /** Access a string index entity field. Can be assigned to. @@ -1155,7 +1191,7 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ \hideinitializer */ -#define E_POINTER(e,o) E_var (e, o, pointer) +#define E_POINTER(e,o) E_var (e, o, ptr) /** Access a string entity field, converting it to a C string. Kills the diff --git a/include/QF/progs/pr_comp.h b/include/QF/progs/pr_comp.h index bc0c1030e..cef8c3ef6 100644 --- a/include/QF/progs/pr_comp.h +++ b/include/QF/progs/pr_comp.h @@ -39,6 +39,8 @@ typedef int64_t pr_long_t __attribute__((aligned(8))); typedef uint64_t pr_ulong_t __attribute__((aligned(8))); typedef uint16_t pr_ushort_t __attribute__((aligned(2)));; +#define PR_PTR(t, p) (*(pr_##t##_t *) (p)) + #define PR_VEC_TYPE(t,n,s) \ typedef t n __attribute__ ((vector_size (s*sizeof (t)))) @@ -538,16 +540,12 @@ typedef struct dfunction_s { dparmsize_t param_size[PR_MAX_PARAMS]; } dfunction_t; -typedef union pr_type_u { - float float_var; - pr_string_t string_var; - pr_func_t func_var; - pr_uint_t entity_var; - float vector_var; // really [3], but this structure must be 32 bits - float quat_var; // really [4], but this structure must be 32 bits - pr_int_t int_var; - pr_ptr_t pointer_var; - pr_uint_t uint_var; +typedef struct pr_type_s { + union { + pr_int_t value; + pr_uint_t uint_value; + pr_float_t float_value; + }; } pr_type_t; typedef pr_type_t pr_void_t; // so size of void is 1 diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index d27255e11..2f3d4905f 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -337,11 +337,11 @@ parse_expression (progs_t *pr, const char *expr, int conditional) goto error; if (!Script_GetToken (es, 1)) goto error; - pr->wp_val.int_var = strtol (es->token->str, &e, 0); + PR_PTR (int, &pr->wp_val) = strtol (es->token->str, &e, 0); if (e == es->token->str) goto error; if (*e == '.' || *e == 'e' || *e == 'E') - pr->wp_val.float_var = strtod (es->token->str, &e); + PR_PTR (float, &pr->wp_val) = strtod (es->token->str, &e); pr->wp_conditional = 1; } } @@ -385,7 +385,7 @@ pr_debug_clear (progs_t *pr, void *data) pr->watch = 0; pr->wp_conditional = 0; - pr->wp_val.int_var = 0; + PR_PTR (int, &pr->wp_val) = 0; for (int i = 0; i < ev_type_count; i++ ) { res->type_encodings[i] = &res->void_type; @@ -612,7 +612,7 @@ PR_LoadDebug (progs_t *pr) if (!str) return 1; - res->debugfile = PR_GetString (pr, str->string_var); + res->debugfile = PR_GetString (pr, PR_PTR (string, str)); sym_file = QFS_SkipPath (res->debugfile); path_end = QFS_SkipPath (pr->progs_name); sym_path = malloc (strlen (sym_file) + (path_end - pr->progs_name) + 1); @@ -1152,7 +1152,7 @@ pr_debug_string_view (qfot_type_t *type, pr_type_t *value, void *_data) { __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - pr_string_t string = value->string_var; + pr_string_t string = PR_PTR (string, value); if (PR_StringValid (data->pr, string)) { const char *str = PR_GetString (data->pr, string); @@ -1196,11 +1196,11 @@ pr_debug_float_view (qfot_type_t *type, pr_type_t *value, void *_data) dstring_t *dstr = data->dstr; if (data->pr->progs->version == PROG_ID_VERSION - && ISDENORM (value->int_var) - && value->uint_var != 0x80000000) { - dasprintf (dstr, "<%08x>", value->int_var); + && ISDENORM (PR_PTR (int, value)) + && PR_PTR (uint, value) != 0x80000000) { + dasprintf (dstr, "<%08x>", PR_PTR (int, value)); } else { - dasprintf (dstr, "%.9g", value->float_var); + dasprintf (dstr, "%.9g", PR_PTR (float, value)); } } @@ -1210,7 +1210,7 @@ pr_debug_vector_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%.9g %.9g %.9g'", VectorExpand (&value->vector_var)); + dasprintf (dstr, "'%.9g %.9g %.9g'", VectorExpand (&PR_PTR (float, value))); } static void @@ -1221,15 +1221,15 @@ pr_debug_entity_view (qfot_type_t *type, pr_type_t *value, void *_data) dstring_t *dstr = data->dstr; if (pr->pr_edicts - && value->entity_var < pr->max_edicts - && !(value->entity_var % pr->pr_edict_size)) { - edict_t *edict = PROG_TO_EDICT (pr, value->entity_var); + && PR_PTR (entity, value) < pr->max_edicts + && !(PR_PTR (entity, value) % pr->pr_edict_size)) { + edict_t *edict = PROG_TO_EDICT (pr, PR_PTR (entity, value)); if (edict) { dasprintf (dstr, "entity %d", NUM_FOR_BAD_EDICT (pr, edict)); return; } } - dasprintf (dstr, "entity [%x]", value->entity_var); + dasprintf (dstr, "entity [%x]", PR_PTR (entity, value)); } static void @@ -1238,12 +1238,12 @@ pr_debug_field_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - pr_def_t *def = PR_FieldAtOfs (pr, value->int_var); + pr_def_t *def = PR_FieldAtOfs (pr, PR_PTR (int, value)); if (def) { dasprintf (dstr, ".%s", PR_GetString (pr, def->name)); } else { - dasprintf (dstr, ".<$%04x>", value->int_var); + dasprintf (dstr, ".<$%04x>", PR_PTR (int, value)); } } @@ -1254,12 +1254,12 @@ pr_debug_func_view (qfot_type_t *type, pr_type_t *value, void *_data) progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - if (value->func_var >= pr->progs->functions.count) { - dasprintf (dstr, "INVALID:%d", value->func_var); - } else if (!value->func_var) { + if (PR_PTR (func, value) >= pr->progs->functions.count) { + dasprintf (dstr, "INVALID:%d", PR_PTR (func, value)); + } else if (!PR_PTR (func, value)) { dstring_appendstr (dstr, "NULL"); } else { - dfunction_t *f = pr->pr_functions + value->func_var; + dfunction_t *f = pr->pr_functions + PR_PTR (func, value); dasprintf (dstr, "%s()", PR_GetString (pr, f->name)); } } @@ -1270,7 +1270,7 @@ pr_debug_ptr_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; progs_t *pr = data->pr; dstring_t *dstr = data->dstr; - pr_ptr_t offset = value->int_var; + pr_ptr_t offset = PR_PTR (int, value); pr_ptr_t offs = offset; pr_def_t *def = 0; @@ -1292,7 +1292,7 @@ pr_debug_quaternion_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "'%.9g %.9g %.9g %.9g'", QuatExpand (&value->quat_var)); + dasprintf (dstr, "'%.9g %.9g %.9g %.9g'", QuatExpand (&PR_PTR (float, value))); } static void @@ -1301,7 +1301,7 @@ pr_debug_int_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%d", value->int_var); + dasprintf (dstr, "%d", PR_PTR (int, value)); } static void @@ -1310,7 +1310,7 @@ pr_debug_uint_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "$%08x", value->uint_var); + dasprintf (dstr, "$%08x", PR_PTR (uint, value)); } static void @@ -1319,7 +1319,7 @@ pr_debug_short_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%04x", (short)value->int_var); + dasprintf (dstr, "%04x", (short)PR_PTR (int, value)); } static void @@ -1355,7 +1355,7 @@ pr_debug_ushort_view (qfot_type_t *type, pr_type_t *value, void *_data) __auto_type data = (pr_debug_data_t *) _data; dstring_t *dstr = data->dstr; - dasprintf (dstr, "%04x", (pr_ushort_t)value->int_var); + dasprintf (dstr, "%04x", (pr_ushort_t)PR_PTR (int, value)); } static void @@ -1431,7 +1431,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) (int) (intptr_t) (pr->watch - pr->pr_globals)); if (pr->wp_conditional) Sys_Printf (" if new val == %d\n", - pr->wp_val.int_var); + PR_PTR (int, &pr->wp_val)); } else { Sys_Printf (" none active\n"); } return; @@ -1444,7 +1444,7 @@ PR_Debug_Watch (progs_t *pr, const char *expr) if (pr->watch) { Sys_Printf ("watchpoint set to [%d]\n", PR_SetPointer (pr, pr->watch)); if (pr->wp_conditional) - Sys_Printf (" if new val == %d\n", pr->wp_val.int_var); + Sys_Printf (" if new val == %d\n", PR_PTR (int, &pr->wp_val)); } else { Sys_Printf ("watchpoint cleared\n"); } @@ -1683,8 +1683,8 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) case 'E': { edict_t *ed = 0; - opval = pr->pr_globals[s->a].entity_var; - param_ind = pr->pr_globals[s->b].uint_var; + opval = G_ENTITY (pr, s->a); + param_ind = G_FIELD (pr, s->b); if (param_ind < pr->progs->entityfields && opval > 0 && opval < pr->pr_edict_area_size) { diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index a7d4fbac7..e8c4f2551 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -287,7 +287,7 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) if (pr_deadbeef_locals) { for (pr_uint_t i = f->params_start; i < f->params_start + f->locals; i++) { - pr->pr_globals[i].int_var = 0xdeadbeef; + pr->pr_globals[i].value = 0xdeadbeef; } } @@ -304,8 +304,8 @@ PR_EnterFunction (progs_t *pr, bfunction_t *f) copy_param (dstParams[i], pr->pr_params[i], f->param_size[i].size); } copy_args = pr->pr_argc - i; - argc->int_var = copy_args; - argv->int_var = dstParams[i] - pr->pr_globals; + PR_PTR (int, argc) = copy_args; + PR_PTR (ptr, argv) = PR_SetPointer (pr, dstParams[i]); if (i < PR_MAX_PARAMS) { memcpy (dstParams[i], pr->pr_params[i], (copy_args * pr->pr_param_size) * sizeof (pr_type_t)); @@ -517,7 +517,7 @@ static inline void pr_memset (pr_type_t *dst, int val, pr_uint_t count) { while (count-- > 0) { - (*dst++).int_var = val; + (*dst++).value = val; } } @@ -839,7 +839,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->int_var = OPA(int); + ptr->value = OPA(int); break; case OP_STOREP_V_v6p: pointer = OPB(ptr); @@ -847,7 +847,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA(float), &ptr->vector_var); + VectorCopy (&OPA(float), &PR_PTR (float, ptr)); break; case OP_STOREP_Q_v6p: pointer = OPB(ptr); @@ -855,7 +855,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA(float), &ptr->quat_var); + QuatCopy (&OPA(float), &PR_PTR (float, ptr)); break; case OP_STOREP_D_v6p: pointer = OPB(ptr); @@ -910,7 +910,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) "field in an edict"); } fldofs = OPA(entity) + OPB(field); - OPC(int) = pr->pr_edict_area[fldofs].int_var; + OPC(int) = PR_PTR (int, &pr->pr_edict_area[fldofs]); break; case OP_LOAD_V_v6p: if (pr_boundscheck) { @@ -961,23 +961,21 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - OPC(int) = ptr->int_var; + OPC(int) = ptr->value; break; case OP_LOADB_V_v6p: pointer = OPA(entity) + OPB(field); if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_vector); } - ptr = pr->pr_globals + pointer; - VectorCopy (&ptr->vector_var, &OPC(float)); + VectorCopy (G_VECTOR (pr, pointer), &OPC(float)); break; case OP_LOADB_Q_v6p: pointer = OPA(entity) + OPB(field); if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_quaternion); } - ptr = pr->pr_globals + pointer; - QuatCopy (&ptr->quat_var, &OPC(float)); + QuatCopy (G_QUAT (pr, pointer), &OPC(float)); break; case OP_LOADB_D_v6p: pointer = OPA(entity) + OPB(field); @@ -1000,7 +998,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - OPC(int) = ptr->int_var; + OPC(int) = ptr->value; break; case OP_LOADBI_V_v6p: pointer = OPA(ptr) + (short) st->b; @@ -1008,7 +1006,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&ptr->vector_var, &OPC(float)); + VectorCopy (G_VECTOR (pr, pointer), &OPC(float)); break; case OP_LOADBI_Q_v6p: pointer = OPA(ptr) + (short) st->b; @@ -1016,7 +1014,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&ptr->quat_var, &OPC(float)); + QuatCopy (G_QUAT (pr, pointer), &OPC(float)); break; case OP_LOADBI_D_v6p: pointer = OPA(ptr) + (short) st->b; @@ -1049,7 +1047,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->int_var = OPA(int); + ptr->value = OPA(int); break; case OP_STOREB_V_v6p: pointer = OPB(ptr) + OPC(int); @@ -1057,7 +1055,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA(float), &ptr->vector_var); + VectorCopy (&OPA(float), G_VECTOR (pr, pointer)); break; case OP_STOREB_Q_v6p: pointer = OPB(ptr) + OPC(int); @@ -1065,7 +1063,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA(float), &ptr->quat_var); + QuatCopy (&OPA(float), G_QUAT (pr, pointer)); break; case OP_STOREB_D_v6p: pointer = OPB(ptr) + OPC(int); @@ -1088,7 +1086,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } ptr = pr->pr_globals + pointer; - ptr->int_var = OPA(int); + ptr->value = OPA(int); break; case OP_STOREBI_V_v6p: pointer = OPB(ptr) + (short) st->c; @@ -1096,7 +1094,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_vector); } ptr = pr->pr_globals + pointer; - VectorCopy (&OPA(float), &ptr->vector_var); + VectorCopy (&OPA(float), G_VECTOR (pr, pointer)); break; case OP_STOREBI_Q_v6p: pointer = OPB(ptr) + (short) st->c; @@ -1104,7 +1102,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } ptr = pr->pr_globals + pointer; - QuatCopy (&OPA(float), &ptr->quat_var); + QuatCopy (&OPA(float), G_QUAT (pr, pointer)); break; case OP_STOREBI_D_v6p: pointer = OPB(ptr) + (short) st->c; @@ -1128,7 +1126,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); } - stk->int_var = OPA(int); + stk->value = OPA(int); *pr->globals.stack = stack; } break; @@ -1174,14 +1172,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - stk->int_var = ptr->int_var; + stk->value = ptr->value; *pr->globals.stack = stack; } break; case OP_PUSHB_V_v6p: { pr_ptr_t stack = *pr->globals.stack - 3; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; @@ -1191,14 +1188,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - VectorCopy (&ptr->vector_var, &stk->vector_var); + VectorCopy (G_VECTOR (pr, pointer), G_VECTOR (pr, stack)); *pr->globals.stack = stack; } break; case OP_PUSHB_Q_v6p: { pr_ptr_t stack = *pr->globals.stack - 4; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; @@ -1208,7 +1204,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } - QuatCopy (&ptr->quat_var, &stk->quat_var); + QuatCopy (G_QUAT (pr, pointer), G_QUAT (pr, stack)); *pr->globals.stack = stack; } break; @@ -1232,14 +1228,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - stk->int_var = ptr->int_var; + stk->value = ptr->value; *pr->globals.stack = stack; } break; case OP_PUSHBI_V_v6p: { pr_ptr_t stack = *pr->globals.stack - 3; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; @@ -1249,14 +1244,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - VectorCopy (&ptr->vector_var, &stk->vector_var); + VectorCopy (G_VECTOR (pr, pointer), G_VECTOR (pr, stack)); *pr->globals.stack = stack; } break; case OP_PUSHBI_Q_v6p: { pr_ptr_t stack = *pr->globals.stack - 4; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; @@ -1266,7 +1260,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } - QuatCopy (&ptr->quat_var, &stk->quat_var); + QuatCopy (G_QUAT (pr, pointer), G_QUAT (pr, stack)); *pr->globals.stack = stack; } break; @@ -1284,7 +1278,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck) { check_stack_pointer (pr, stack, 1); } - OPA(int) = stk->int_var; + OPA(int) = stk->value; *pr->globals.stack = stack + 1; } break; @@ -1330,14 +1324,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - ptr->int_var = stk->int_var; + ptr->value = stk->value; *pr->globals.stack = stack + 1; } break; case OP_POPB_V_v6p: { pr_ptr_t stack = *pr->globals.stack; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; @@ -1347,14 +1340,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - VectorCopy (&stk->vector_var, &ptr->vector_var); + VectorCopy (G_VECTOR (pr, stack), G_VECTOR (pr, pointer)); *pr->globals.stack = stack + 3; } break; case OP_POPB_Q_v6p: { pr_ptr_t stack = *pr->globals.stack; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + OPB(int); ptr = pr->pr_globals + pointer; @@ -1364,7 +1356,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } - QuatCopy (&stk->quat_var, &ptr->quat_var); + QuatCopy (G_QUAT (pr, stack), G_QUAT (pr, pointer)); *pr->globals.stack = stack + 4; } break; @@ -1388,14 +1380,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - ptr->int_var = stk->int_var; + ptr->value = stk->value; *pr->globals.stack = stack + 1; } break; case OP_POPBI_V_v6p: { pr_ptr_t stack = *pr->globals.stack; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; @@ -1405,14 +1396,13 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_int); } - VectorCopy (&stk->vector_var, &ptr->vector_var); + VectorCopy (G_VECTOR (pr, stack), G_VECTOR (pr, pointer)); *pr->globals.stack = stack + 3; } break; case OP_POPBI_Q_v6p: { pr_ptr_t stack = *pr->globals.stack; - pr_type_t *stk = pr->pr_globals + stack; pointer = OPA(ptr) + st->b; ptr = pr->pr_globals + pointer; @@ -1422,7 +1412,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) PR_BoundsCheck (pr, pointer, ev_quaternion); } - QuatCopy (&stk->quat_var, &ptr->quat_var); + QuatCopy (G_QUAT (pr, stack), G_QUAT (pr, pointer)); *pr->globals.stack = stack + 4; } break; @@ -1481,8 +1471,7 @@ pr_exec_quakec (progs_t *pr, int exitdepth) if (pr_boundscheck) { PR_BoundsCheck (pr, pointer, ev_int); } - ptr = pr->pr_globals + pointer; - pointer = ptr->int_var; + pointer = G_POINTER (pr, pointer); if (pr_boundscheck && (pointer >= pr->progs->statements.count)) { PR_RunError (pr, "Invalid jump destination"); @@ -1551,9 +1540,9 @@ op_call: int frame = pr->fields.frame + self; int think = pr->fields.think + self; float time = *pr->globals.ftime + 0.1; - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = OPB(func); + PR_PTR (float, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (float, &pr->pr_edict_area[frame]) = OPA(float); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; case OP_STATE_F_v6p: @@ -1563,9 +1552,9 @@ op_call: int frame = pr->fields.frame + self; int think = pr->fields.think + self; float time = *pr->globals.ftime + OPC(float); - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = OPB(func); + PR_PTR (float, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (float, &pr->pr_edict_area[frame]) = OPA(float); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; case OP_ADD_I_v6p: @@ -1748,8 +1737,7 @@ op_call: OPC(float) = OPA(double) < OPB(double); break; case OP_NOT_D_v6p: - OPC(int) = (op_a[0].int_var - || (op_a[1].int_var & ~0x80000000u)); + OPC(int) = (op_a[0].value || (op_a[1].value & ~0x80000000u)); break; case OP_EQ_D_v6p: OPC(int) = OPA(double) == OPB(double); @@ -1783,17 +1771,17 @@ op_call: default: PR_RunError (pr, "Bad opcode %i", st->op & ~OP_BREAK); } - if (pr->watch && pr->watch->int_var != old_val.int_var) { + if (pr->watch && pr->watch->value != old_val.value) { if (!pr->wp_conditional - || pr->watch->int_var == pr->wp_val.int_var) { + || pr->watch->value == pr->wp_val.value) { if (pr->debug_handler) { pr->debug_handler (prd_watchpoint, 0, pr->debug_data); } else { PR_RunError (pr, "watchpoint hit: %d -> %d", - old_val.int_var, pr->watch->int_var); + old_val.value, pr->watch->value); } } - old_val.int_var = pr->watch->int_var; + old_val.value = pr->watch->value; } } exit_program: @@ -1877,7 +1865,7 @@ pr_jump_mode (progs_t *pr, const dstatement_t *st, int jump_ind) break; case 1: // variable indexed array: a + *b (only +ve) - jump_offs = (op_a + OPB(uint))->uint_var; + jump_offs = PR_PTR (uint, op_a + OPB(uint)); break; case 2: // constant indexed pointer: *a + b (supports -ve offset) @@ -1963,7 +1951,7 @@ pr_with (progs_t *pr, const dstatement_t *st) case 4: // hard-0 base - pr->pr_bases[st->c & 3] = pr->pr_globals[st->b].pointer_var; + pr->pr_bases[st->c & 3] = G_POINTER (pr, st->b);; return; case 5: pr->pr_bases[st->c & 3] = OPB(ptr); @@ -2571,7 +2559,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_CALL_C: case OP_CALL_D: mm = pr_call_mode (pr, st, st_op - OP_CALL_B + 1); - function = mm->func_var; + function = PR_PTR (func, mm); pr->pr_argc = 0; // op_c specifies the location for the return value if any pr->pr_xfunction->profile += profile - startprofile; @@ -2714,9 +2702,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int frame = pr->fields.frame + self; int think = pr->fields.think + self; float time = *pr->globals.ftime + 0.1; - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = op_b->func_var; + PR_PTR (float, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (float, &pr->pr_edict_area[frame]) = OPA(float); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; OP_cmp_T (GE, U, long, lvec2, lvec4, >=, ulong, ulvec2, ulvec4); @@ -2736,9 +2724,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int frame = pr->fields.frame + self; int think = pr->fields.think + self; float time = *pr->globals.ftime + OPC(float); - pr->pr_edict_area[nextthink].float_var = time; - pr->pr_edict_area[frame].float_var = OPA(float); - pr->pr_edict_area[think].func_var = op_b->func_var; + PR_PTR (float, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (float, &pr->pr_edict_area[frame]) = OPA(float); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; // 1 1110 @@ -2768,9 +2756,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int frame = pr->fields.frame + self; int think = pr->fields.think + self; double time = *pr->globals.dtime + 0.1; - *(double *) (&pr->pr_edict_area[nextthink]) = time; - pr->pr_edict_area[frame].int_var = OPA(int); - pr->pr_edict_area[think].func_var = op_b->func_var; + PR_PTR (double, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (int, &pr->pr_edict_area[frame]) = OPA(int); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; OP_cmp_T (LE, U, long, lvec2, lvec4, <=, ulong, ulvec2, ulvec4); @@ -2799,9 +2787,9 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) int frame = pr->fields.frame + self; int think = pr->fields.think + self; double time = *pr->globals.dtime + OPC(double); - *(double *) (&pr->pr_edict_area[nextthink]) = time; - pr->pr_edict_area[frame].int_var = OPA(int); - pr->pr_edict_area[think].func_var = op_b->func_var; + PR_PTR (double, &pr->pr_edict_area[nextthink]) = time; + PR_PTR (int, &pr->pr_edict_area[frame]) = OPA(int); + PR_PTR (func, &pr->pr_edict_area[think]) = OPB(func); } break; // 1 1111 @@ -2810,7 +2798,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_LEA_C: case OP_LEA_D: mm = pr_address_mode (pr, st, (st_op - OP_LEA_A)); - op_c->pointer_var = mm - pr->pr_globals; + OPC(ptr) = mm - pr->pr_globals; break; case OP_QV4MUL_F: OPC(vec4) = qvmulf (OPA(vec4), OPB(vec4)); @@ -2862,17 +2850,17 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) default: PR_RunError (pr, "Bad opcode o%03o", st->op & OP_MASK); } - if (pr->watch && pr->watch->int_var != old_val.int_var) { + if (pr->watch && pr->watch->value != old_val.value) { if (!pr->wp_conditional - || pr->watch->int_var == pr->wp_val.int_var) { + || pr->watch->value == pr->wp_val.value) { if (pr->debug_handler) { pr->debug_handler (prd_watchpoint, 0, pr->debug_data); } else { PR_RunError (pr, "watchpoint hit: %d -> %d", - old_val.int_var, pr->watch->int_var); + old_val.value, pr->watch->value); } } - old_val.int_var = pr->watch->int_var; + old_val.value = pr->watch->value; } } exit_program: diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index a1c198192..e43aef934 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -68,34 +68,34 @@ PR_UglyValueString (progs_t *pr, etype_t type, pr_type_t *val, dstring_t *line) switch (type) { case ev_string: - dsprintf (line, "%s", PR_GetString (pr, val->string_var)); + dsprintf (line, "%s", PR_GetString (pr, PR_PTR (string, val))); break; case ev_entity: dsprintf (line, "%d", - NUM_FOR_BAD_EDICT (pr, PROG_TO_EDICT (pr, val->entity_var))); + NUM_FOR_BAD_EDICT (pr, PROG_TO_EDICT (pr, PR_PTR (entity, val)))); break; case ev_func: - f = pr->pr_functions + val->func_var; + f = pr->pr_functions + PR_PTR (func, val); dsprintf (line, "%s", PR_GetString (pr, f->name)); break; case ev_field: - def = PR_FieldAtOfs (pr, val->int_var); + def = PR_FieldAtOfs (pr, PR_PTR (int, val)); dsprintf (line, "%s", PR_GetString (pr, def->name)); break; case ev_void: dstring_copystr (line, "void"); break; case ev_float: - dsprintf (line, "%.9g", val->float_var); + dsprintf (line, "%.9g", PR_PTR (float, val)); break; case ev_int: - dsprintf (line, "%d", val->int_var); + dsprintf (line, "%d", PR_PTR (int, val)); break; case ev_vector: - dsprintf (line, "%.9g %.9g %.9g", VectorExpand (&val->vector_var)); + dsprintf (line, "%.9g %.9g %.9g", VectorExpand (&PR_PTR (float, val))); break; case ev_quaternion: - dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (&val->quat_var)); + dsprintf (line, "%.9g %.9g %.9g %.9g", QuatExpand (&PR_PTR (float, val))); break; default: dsprintf (line, "bad type %i", type); @@ -132,7 +132,7 @@ ED_EntityDict (progs_t *pr, edict_t *ed) // if the value is still all 0, skip the field type = d->type & ~DEF_SAVEGLOBAL; for (j = 0; j < pr_type_size[type]; j++) - if (v[j].int_var) + if (v[j].value) break; if (j == pr_type_size[type]) continue; @@ -226,11 +226,11 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) switch (key->type & ~DEF_SAVEGLOBAL) { case ev_string: - d->string_var = ED_NewString (pr, s); + PR_PTR (string, d) = ED_NewString (pr, s); break; case ev_float: - d->float_var = atof (s); + PR_PTR (float, d) = atof (s); break; case ev_vector: @@ -241,14 +241,14 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) while (*v && *v != ' ') v++; *v = 0; - (&d->vector_var)[i] = atof (w); + (&PR_PTR (float, d))[i] = atof (w); w = v = v + 1; } free (string); break; case ev_entity: - d->entity_var = EDICT_TO_PROG (pr, EDICT_NUM (pr, atoi (s))); + PR_PTR (entity, d) = EDICT_TO_PROG (pr, EDICT_NUM (pr, atoi (s))); break; case ev_field: @@ -257,7 +257,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) Sys_Printf ("Can't find field %s\n", s); return false; } - d->int_var = G_INT (pr, def->ofs); + PR_PTR (int, d) = G_INT (pr, def->ofs); break; case ev_func: @@ -266,7 +266,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) Sys_Printf ("Can't find function %s\n", s); return false; } - d->func_var = func - pr->pr_functions; + PR_PTR (func, d) = func - pr->pr_functions; break; default: diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index eb0fcc6ab..7b70e12d4 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -860,9 +860,7 @@ fmt_append_item (fmt_state_t *state) } #undef P_var -#define P_var(p,n,t) (state->args[n]->t##_var) -#undef P_DOUBLE -#define P_DOUBLE(p,n) (*(double *) (state->args[n])) +#define P_var(p,n,t) PR_PTR (t, state->args[n]) /** State machine for PR_Sprintf * diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index c0a59178c..29d95930a 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -86,7 +86,8 @@ bi_gib_builtin_f (void) pr_list = PR_Zone_Malloc (builtin->pr, GIB_Argc() * sizeof (pr_type_t)); for (i = 0; i < GIB_Argc(); i++) - pr_list[i].int_var = PR_SetTempString (builtin->pr, GIB_Argv(i)); + PR_PTR (string, &pr_list[i]) = PR_SetTempString (builtin->pr, + GIB_Argv(i)); PR_RESET_PARAMS (builtin->pr); P_INT (builtin->pr, 0) = GIB_Argc(); diff --git a/libs/ruamoko/pr_cmds.c b/libs/ruamoko/pr_cmds.c index bf8d9c19c..63fc6c1e3 100644 --- a/libs/ruamoko/pr_cmds.c +++ b/libs/ruamoko/pr_cmds.c @@ -62,10 +62,10 @@ PF_VarString (progs_t *pr, int first, int argc) pr_type_t **argv = pr->pr_params; for (len = 0, i = first; i < argc; i++) - len += strlen (PR_GetString (pr, argv[i]->string_var)); + len += strlen (PR_GetString (pr, *(pr_string_t *) argv[i])); dst = out = Hunk_TempAlloc (0, len + 1); for (i = first; i < argc; i++) { - src = PR_GetString (pr, argv[i]->string_var); + src = PR_GetString (pr, PR_PTR (string, argv[i])); while (*src) *dst++ = *src++; } diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 6f8b74547..63020060e 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -276,7 +276,7 @@ bi_Hash_FindList (progs_t *pr, void *_res) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].int_var = (intptr_t) *l; + PR_PTR (ptr, &pr_list[count++]) = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } @@ -296,7 +296,7 @@ bi_Hash_FindElementList (progs_t *pr, void *_res) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].int_var = (intptr_t) *l; + PR_PTR (ptr, &pr_list[count++]) = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } @@ -356,7 +356,7 @@ bi_Hash_GetList (progs_t *pr, void *_res) pr_list = PR_Zone_Malloc (pr, count * sizeof (pr_type_t)); // the hash tables stores progs pointers... for (count = 0, l = list; *l; l++) - pr_list[count++].int_var = (intptr_t) *l; + PR_PTR(ptr, &pr_list[count++]) = (intptr_t) *l; free (list); RETURN_POINTER (pr, pr_list); } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 510dff248..c7942c8e0 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1507,25 +1507,27 @@ rua_obj_msg_sendv (progs_t *pr, void *data) RUA_CALL_END (pr, imp) } +#define RETAIN_COUNT(obj) PR_PTR (int, &(obj)[-1]) + static void rua_obj_increment_retaincount (progs_t *pr, void *data) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = ++(*--obj).int_var; + R_INT (pr) = ++RETAIN_COUNT (obj); } static void rua_obj_decrement_retaincount (progs_t *pr, void *data) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = --(*--obj).int_var; + R_INT (pr) = --RETAIN_COUNT (obj); } static void rua_obj_get_retaincount (progs_t *pr, void *data) { pr_type_t *obj = &P_STRUCT (pr, pr_type_t, 0); - R_INT (pr) = (*--obj).int_var; + R_INT (pr) = RETAIN_COUNT (obj); } static void diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 4a09f1c5a..3849adf07 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -186,13 +186,9 @@ extern progs_t sv_pr_state; #define SVstring(e,f) SVFIELD (e, f, string) #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) -#define SVvector(e,f) (&SVFIELD (e, f, vector)) +#define SVvector(e,f) (&SVFIELD (e, f, float)) #define SVint(e,f) SVFIELD (e, f, int) -#if TYPECHECK_PROGS -#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) -#else -#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f) -#endif +#define SVdouble(e,f) SVFIELD (e, f, double) typedef struct edict_leaf_s { struct edict_leaf_s *next; diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index 9984d97ff..b133b0bf4 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -1139,7 +1139,7 @@ PF_WriteBytes (progs_t *pr, void *data) } } for (i = 0; i < argc; i++) { - p = argv[i]->float_var; + p = PR_PTR (float, &argv[i]); MSG_WriteByte (msg, p); } } diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index 701475b7e..47e6b1198 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -193,13 +193,9 @@ extern progs_t sv_pr_state; #define SVstring(e,f) SVFIELD (e, f, string) #define SVfunc(e,f) SVFIELD (e, f, func) #define SVentity(e,f) SVFIELD (e, f, entity) -#define SVvector(e,f) (&SVFIELD (e, f, vector)) +#define SVvector(e,f) (&SVFIELD (e, f, float)) #define SVint(e,f) SVFIELD (e, f, int) -#if TYPECHECK_PROGS -#define SVdouble(e,f) E_DOUBLE (e, PR_AccessField (&sv_pr_state, #f, ev_##t, __FILE__, __LINE__)) -#else -#define SVdouble(e,f) E_DOUBLE (e, sv_fields.f) -#endif +#define SVdouble(e,f) SVFIELD (e, f, double) typedef struct edict_leaf_s { struct edict_leaf_s *next; diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index 103b0a3a3..fe892ea7c 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -1130,7 +1130,7 @@ PF_WriteBytes (progs_t *pr, void *data) } } for (i = 0; i < argc; i++) { - p = argv[i]->float_var; + p = PR_PTR (float, argv[i]); buf[i] = p; } diff --git a/qw/source/sv_progs.c b/qw/source/sv_progs.c index 345efc945..23a9c4061 100644 --- a/qw/source/sv_progs.c +++ b/qw/source/sv_progs.c @@ -181,16 +181,16 @@ static void free_edict (progs_t *pr, edict_t *ent) { if (sv_old_entity_free) { - E_fld (ent, sv_fields.model).entity_var = 0; - E_fld (ent, sv_fields.takedamage).float_var = 0; - E_fld (ent, sv_fields.modelindex).float_var = 0; - E_fld (ent, sv_fields.colormap).float_var = 0; - E_fld (ent, sv_fields.skin).float_var = 0; - E_fld (ent, sv_fields.frame).float_var = 0; - E_fld (ent, sv_fields.nextthink).float_var = -1; - E_fld (ent, sv_fields.solid).float_var = 0; - memset (&E_fld (ent, sv_fields.origin).vector_var, 0, 3*sizeof (float)); - memset (&E_fld (ent, sv_fields.angles).vector_var, 0, 3*sizeof (float)); + E_STRING (ent, sv_fields.model) = 0; + E_FLOAT (ent, sv_fields.takedamage) = 0; + E_FLOAT (ent, sv_fields.modelindex) = 0; + E_FLOAT (ent, sv_fields.colormap) = 0; + E_FLOAT (ent, sv_fields.skin) = 0; + E_FLOAT (ent, sv_fields.frame) = 0; + E_FLOAT (ent, sv_fields.nextthink) = -1; + E_FLOAT (ent, sv_fields.solid) = 0; + VectorZero (E_VECTOR (ent, sv_fields.origin)); + VectorZero (E_VECTOR (ent, sv_fields.angles)); } else { ED_ClearEdict (pr, ent, 0); } diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index e93c3013a..d1bc0a268 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -308,7 +308,7 @@ enum { \hideinitializer */ -#define QFO_var(q, s, t, o) ((q)->spaces[s].data[o].t##_var) +#define QFO_var(q, s, t, o) (*(pr_##t##_t *) &(q)->spaces[s].data[o]) /** Access a double variable in the object file. Can be assigned to. diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index b678cc5a4..a6384c91c 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -97,16 +97,17 @@ typedef struct pr_info_s { extern pr_info_t pr; #define GETSTR(s) (pr.strings->strings + (s)) -#define D_var(t, d) ((d)->space->data[(d)->offset].t##_var) -#define D_DOUBLE(d) (*(double *) ((d)->space->data + (d)->offset)) +#define D_PACKED(t,d) (*(t *) &(d)->space->data[(d)->offset]) +#define D_var(t, d) D_PACKED (pr_##t##_t, d) +#define D_DOUBLE(d) D_var (double, d) #define D_FLOAT(d) D_var (float, d) #define D_INT(d) D_var (int, d) -#define D_VECTOR(d) (&D_var (vector, d)) -#define D_QUAT(d) (&D_var (quat, d)) +#define D_VECTOR(d) (&D_var (float, d)) +#define D_QUAT(d) (&D_var (float, d)) #define D_STRING(d) D_var (string, d) #define D_GETSTR(d) GETSTR (D_STRING (d)) #define D_FUNCTION(d) D_var (func, d) -#define D_POINTER(t,d) ((t *)((d)->space->data + (d)->offset)) +#define D_POINTER(t,d) (&D_PACKED (t, d)) #define D_STRUCT(t,d) (*D_POINTER (t, d)) #define G_POINTER(s,t,o) ((t *)((s)->data + o)) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 7a06a1730..4303eed60 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -401,7 +401,7 @@ init_elements (struct def_s *def, expr_t *eles) internal_error (c, "bogus expression type in init_elements()"); } if (c->e.value->lltype == ev_string) { - EMIT_STRING (def->space, g->string_var, + EMIT_STRING (def->space, *(pr_string_t *) g, c->e.value->v.string_val); } else { memcpy (g, &c->e.value->v, type_size (get_type (c)) * 4); @@ -636,7 +636,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, EMIT_STRING (sym->s.def->space, D_STRING (sym->s.def), v->v.string_val); } else { - memcpy (D_POINTER (void, sym->s.def), &v->v, + memcpy (D_POINTER (pr_type_t, sym->s.def), &v->v, type_size (sym->type) * sizeof (pr_type_t)); } } diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index d95c772cc..77ae2a2bc 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -327,7 +327,7 @@ qfo_globals (qfo_t *qfo) QFO_TYPESTR (qfo, def->type)); if (!(def->flags & QFOD_EXTERNAL) && qfo->spaces[space].data) printf (" %d", - qfo->spaces[space].data[def->offset].int_var); + qfo->spaces[space].data[def->offset].value); puts (""); } } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index d7144ae27..863d56d64 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -433,7 +433,7 @@ qfo_byteswap_space (void *space, int size, qfos_type_t type) case qfos_type: case qfos_debug: for (val = (pr_type_t *) space, c = 0; c < size; c++, val++) - val->int_var = LittleLong (val->int_var); + val->value = LittleLong (val->value); break; } } diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 5cc8c7aa4..98120e825 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -246,7 +246,7 @@ WriteProgs (dprograms_t *progs, int size) fielddefs[i].name = LittleLong (fielddefs[i].name); } for (i = 0; i < progs->globals.count; i++) - globals[i].int_var = LittleLong (globals[i].int_var); + globals[i].value = LittleLong (globals[i].value); if (!(h = Qopen (options.output_file, "wb"))) Sys_Error ("%s: %s\n", options.output_file, strerror(errno)); @@ -307,7 +307,7 @@ WriteSym (pr_debug_header_t *sym, int size) debug_defs[i].type_encoding = LittleLong (debug_defs[i].type_encoding); } for (i = 0; i < sym->debug_data_size; i++) { - debug_data[i].int_var = LittleLong (debug_data[i].int_var); + debug_data[i].value = LittleLong (debug_data[i].value); } if (!(h = Qopen (options.debug_file, "wb"))) diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index d235008d0..674be505f 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -73,7 +73,7 @@ static const char *reloc_name[] = { "rel_def_field_ofs", }; -#define RELOC(r) (r)->space->data[(r)->offset].int_var +#define RELOC(r) (r)->space->data[(r)->offset].value void relocate_refs (reloc_t *reloc, int offset) @@ -169,7 +169,7 @@ relocate_refs (reloc_t *reloc, int offset) case rel_def_field_ofs: //FIXME what is correct here? //RELOC (reloc) += pr.data->data[offset].int_var; - RELOC (reloc) += pr.near_data->data[offset].int_var; + RELOC (reloc) += PR_PTR (int, &pr.near_data->data[offset]); break; } reloc = reloc->next; diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 4a9f64bce..318efb420 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -365,7 +365,7 @@ emit_structure (const char *name, int su, struct_def_t *defs, type_t *type, if (!defs[i].emit) { //FIXME relocs? arrays? structs? pr_type_t *val = (pr_type_t *) data; - memcpy (D_POINTER (void, &field_def), val, + memcpy (D_POINTER (pr_type_t, &field_def), val, type_size (field_def.type) * sizeof (pr_type_t)); data = &val[type_size (field_def.type)]; } else { diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index f96e5c720..c119473c9 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -614,7 +614,7 @@ emit_value (ex_value_t *value, def_t *def) break; } - memcpy (D_POINTER (void, cn), &val.v, 4 * type_size (type)); + memcpy (D_POINTER (pr_type_t, cn), &val.v, 4 * type_size (type)); make_def_imm (cn, tab, &val); From 71ae7aac4af47b561a2a1b2933037cdc2d505ae1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 17:19:47 +0900 Subject: [PATCH 2692/3664] [gamecode] Add macros for long and ulong --- include/QF/progs.h | 94 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 958bbd767..2e18fa3c5 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -476,6 +476,30 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define G_UINT(p,o) G_var (p, o, uint) +/** Access a long global. Can be assigned to. + + \par QC type: + \c long + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \return long lvalue + + \hideinitializer +*/ +#define G_LONG(p,o) G_var (p, o, long) + +/** Access an unsigned long global. Can be assigned to. + + \par QC type: + \c ulong + \param p pointer to ::progs_t VM struct + \param o offset into global data space + \return unsigned long lvalue + + \hideinitializer +*/ +#define G_ULONG(p,o) G_var (p, o, ulong) + /** Access a vector global. Can be assigned to. \par QC type: @@ -715,6 +739,30 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define P_UINT(p,n) P_var (p, n, uint) +/** Access a long parameter. Can be assigned to. + + \par QC type: + \c long + \param p pointer to ::progs_t VM struct + \param n parameter number (0-7) + \return long lvalue + + \hideinitializer +*/ +#define P_LONG(p,n) P_var (p, n, long) + +/** Access an unsigned long parameter. Can be assigned to. + + \par QC type: + \c ulong + \param p pointer to ::progs_t VM struct + \param n parameter number (0-7) + \return unsigned long lvalue + + \hideinitializer +*/ +#define P_ULONG(p,n) P_var (p, n, ulong) + /** Access a vector parameter. Can be used any way a vec3_t variable can. \par QC type: @@ -928,6 +976,28 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define R_UINT(p) R_var (p, uint) +/** Access the VM function return value as a \c ::pr_long_t (AKA int32_t) + + \par QC type: + \c long + \param p pointer to ::progs_t VM struct + \return ::pr_long_t lvalue + + \hideinitializer +*/ +#define R_LONG(p) R_var (p, long) + +/** Access the VM function return value as a \c ::pr_ulong_t (AKA uint32_t) + + \par QC type: + \c ulong + \param p pointer to ::progs_t VM struct + \return ::pr_long_t lvalue + + \hideinitializer +*/ +#define R_ULONG(p) R_var (p, ulong) + /** Access the VM function return value as a \c ::vec3_t vector. \par QC type: @@ -1132,6 +1202,30 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ */ #define E_UINT(e,o) E_var (e, o, uint) +/** Access a long entity field. Can be assigned to. + + \par QC type: + \c long + \param e pointer to the entity + \param o field offset into entity data space + \return long lvalue + + \hideinitializer +*/ +#define E_LONG(e,o) E_var (e, o, long) + +/** Access an unsigned long entity field. Can be assigned to. + + \par QC type: + \c ulong + \param e pointer to the entity + \param o field offset into entity data space + \return unsigned long lvalue + + \hideinitializer +*/ +#define E_ULONG(e,o) E_var (e, o, ulong) + /** Access a vector entity field. Can be used any way a vec3_t variable can. \par QC type: From af2dfde37a192adc0e6f91f4f4778279faed49f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 17:13:18 +0900 Subject: [PATCH 2693/3664] [gamecode] Support printing 64-bit integer types The 'l' modifier always means 64-bit, regardless of the underlying platform. As well, the 32-bit integer types are handled portably too. --- libs/gamecode/pr_strings.c | 66 +++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 7b70e12d4..92129f7ad 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "QF/dstring.h" #include "QF/hash.h" @@ -60,10 +61,12 @@ typedef struct fmt_item_s { int precision; union { const char *string_var; - int integer_var; - unsigned uinteger_var; + pr_int_t int_var; + pr_uint_t uint_var; float float_var; double double_var; + pr_long_t long_var; + pr_ulong_t ulong_var; } data; struct fmt_item_s *next; } fmt_item_t; @@ -769,23 +772,35 @@ I_DoPrint (dstring_t *tmp, dstring_t *result, fmt_item_t *formatting) break; case 'c': dstring_appendstr (tmp, "c"); - PRINT (integer); + PRINT (int); break; case 'i': case 'd': - dstring_appendstr (tmp, "d"); - PRINT (integer); + if (current->flags & FMT_LONG) { + dstring_appendstr (tmp, PRId64); + PRINT (ulong); + } else { + dstring_appendstr (tmp, PRId32); + PRINT (uint); + } break; case 'x': - dstring_appendstr (tmp, "x"); - PRINT (integer); + if (current->flags & FMT_LONG) { + dstring_appendstr (tmp, PRIx64); + PRINT (ulong); + } else { + dstring_appendstr (tmp, PRIx32); + PRINT (uint); + } break; case 'u': - if (current->flags & FMT_HEX) - dstring_appendstr (tmp, "x"); - else - dstring_appendstr (tmp, "u"); - PRINT (uinteger); + if (current->flags & FMT_LONG) { + dstring_appendstr (tmp, PRIu64); + PRINT (ulong); + } else { + dstring_appendstr (tmp, PRIu32); + PRINT (uint); + } break; case 'f': dstring_appendstr (tmp, "f"); @@ -1019,6 +1034,12 @@ static void fmt_state_modifiers (fmt_state_t *state) { // no modifiers supported + if (state->c[0] == 'l' + && (state->c[1] == 'i' || state->c[1] == 'd' || state->c[1] == 'x' + || state->c[1] == 'u')) { + (*state->fi)->flags |= FMT_LONG; + state->c++; + } state->state = fmt_state_conversion; } @@ -1036,8 +1057,7 @@ fmt_state_conversion (fmt_state_t *state) case 'e': // entity (*state->fi)->type = 'i'; - (*state->fi)->data.integer_var = - P_EDICTNUM (pr, state->fmt_count); + (*state->fi)->data.int_var = P_EDICTNUM (pr, state->fmt_count); state->fmt_count++; fmt_append_item (state); @@ -1045,9 +1065,13 @@ fmt_state_conversion (fmt_state_t *state) case 'i': case 'd': case 'c': - // integer + // int (*state->fi)->type = conv; - (*state->fi)->data.integer_var = P_INT (pr, state->fmt_count); + if ((*state->fi)->flags & FMT_LONG) { + (*state->fi)->data.long_var = P_LONG (pr, state->fmt_count); + } else { + (*state->fi)->data.int_var = P_INT (pr, state->fmt_count); + } state->fmt_count++; fmt_append_item (state); @@ -1074,7 +1098,7 @@ fmt_state_conversion (fmt_state_t *state) // pointer (*state->fi)->flags |= FMT_ALTFORM; (*state->fi)->type = 'x'; - (*state->fi)->data.uinteger_var = P_UINT (pr, state->fmt_count); + (*state->fi)->data.uint_var = P_UINT (pr, state->fmt_count); state->fmt_count++; fmt_append_item (state); @@ -1132,9 +1156,13 @@ fmt_state_conversion (fmt_state_t *state) break; case 'u': case 'x': - // integer, unsigned or hex notation + // int, unsigned or hex notation (*state->fi)->type = conv; - (*state->fi)->data.uinteger_var = P_UINT (pr, state->fmt_count); + if ((*state->fi)->flags & FMT_LONG) { + (*state->fi)->data.ulong_var = P_ULONG (pr, state->fmt_count); + } else { + (*state->fi)->data.uint_var = P_UINT (pr, state->fmt_count); + } state->fmt_count++; fmt_append_item (state); From 8912c65029a77838ce791e31553744969022eabf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 19:57:43 +0900 Subject: [PATCH 2694/3664] [qfcc] Indicate type width in type strings Makes for much more informative error messages for type mismatches (confusing when both sides look the same). --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/def.c | 3 ++- tools/qfcc/source/expr_binary.c | 9 +++++---- tools/qfcc/source/type.c | 23 ++++++++++++++++++++++- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 63fb194e3..156189d33 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -166,6 +166,7 @@ type_t *alias_type (type_t *type, type_t *alias_chain, const char *name); const type_t *unalias_type (const type_t *type) __attribute__((pure)); const type_t *dereference_type (const type_t *type) __attribute__((pure)); void print_type_str (struct dstring_s *str, const type_t *type); +const char *get_type_string (const type_t *type); void print_type (const type_t *type); void dump_dot_type (void *t, const char *filename); const char *encode_params (const type_t *type); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 4303eed60..b5d63177a 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -596,7 +596,8 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, } init_type = get_type (init); if (!type_assignable (sym->type, init_type)) { - error (init, "type mismatch in initializer"); + error (init, "type mismatch in initializer: %s = %s", + get_type_string (sym->type), get_type_string (init_type)); return; } if (storage == sc_local && local_expr) { diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 6c792a1de..b2ac9eece 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -828,11 +828,12 @@ entity_compare (int op, expr_t *e1, expr_t *e2) static expr_t * invalid_binary_expr (int op, expr_t *e1, expr_t *e2) { - etype_t t1, t2; - t1 = extract_type (e1); - t2 = extract_type (e2); + type_t *t1, *t2; + t1 = get_type (e1); + t2 = get_type (e2); return error (e1, "invalid binary expression: %s %s %s", - pr_type_name[t1], get_op_string (op), pr_type_name[t2]); + get_type_string (t1), get_op_string (op), + get_type_string (t2)); } static expr_t * diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index a695e9f50..0387f862b 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -711,7 +711,9 @@ print_type_str (dstring_t *str, const type_t *type) case ev_short: case ev_ushort: case ev_double: - dasprintf (str, " %s", pr_type_name[type->type]); + dasprintf (str, " %s%s", pr_type_name[type->type], + type->width > 1 ? va (0, "{%d}", type->width) + : ""); return; case ev_invalid: case ev_type_count: @@ -722,6 +724,25 @@ print_type_str (dstring_t *str, const type_t *type) internal_error (0, "bad type meta:type %d:%d", type->meta, type->type); } +const char * +get_type_string (const type_t *type) +{ + static dstring_t *type_str[8]; + static int str_index; + + if (!type_str[str_index]) { + type_str[str_index] = dstring_newstr (); + } + dstring_clearstr (type_str[str_index]); + print_type_str (type_str[str_index], type); + const char *str = type_str[str_index++]->str; + str_index %= sizeof (type_str) / sizeof (type_str[0]); + while (*str == ' ') { + str++; + } + return str; +} + void print_type (const type_t *type) { From 67bdbc6f7a922b2ba4269fed5106659abbddad65 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Apr 2022 11:25:33 +0900 Subject: [PATCH 2695/3664] [qfcc] Split out vector expression code I plan on extending it for the new vector types and expr.c is just too big to work in nicely. --- tools/qfcc/source/Makemodule.am | 1 + tools/qfcc/source/expr.c | 155 ----------------------- tools/qfcc/source/expr_vector.c | 216 ++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+), 155 deletions(-) create mode 100644 tools/qfcc/source/expr_vector.c diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index d7d85e597..0406cea3e 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -30,6 +30,7 @@ qfcc_SOURCES = \ tools/qfcc/source/expr_bool.c \ tools/qfcc/source/expr_compound.c \ tools/qfcc/source/expr_obj.c \ + tools/qfcc/source/expr_vector.c \ tools/qfcc/source/flow.c \ tools/qfcc/source/function.c \ tools/qfcc/source/grab.c \ diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 746a94f03..8033d6435 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -42,7 +42,6 @@ #include "QF/alloc.h" #include "QF/dstring.h" #include "QF/mathlib.h" -#include "QF/sys.h" #include "QF/va.h" #include "tools/qfcc/include/qfcc.h" @@ -127,88 +126,6 @@ convert: e->e = new->e; } -expr_t * -convert_vector (expr_t *e) -{ - float val[4]; - - if (e->type != ex_vector) - return e; - if (is_vector(e->e.vector.type)) { - // guaranteed to have three elements - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - x = fold_constants (cast_expr (&type_float, x)); - y = fold_constants (cast_expr (&type_float, y)); - z = fold_constants (cast_expr (&type_float, z)); - if (is_constant (x) && is_constant (y) && is_constant (z)) { - val[0] = expr_float(x); - val[1] = expr_float(y); - val[2] = expr_float(z); - return new_vector_expr (val); - } - // at least one of x, y, z is not constant, so rebuild the - // list incase any of them are new expressions - z->next = 0; - y->next = z; - x->next = y; - e->e.vector.list = x; - return e; - } - if (is_quaternion(e->e.vector.type)) { - // guaranteed to have two or four elements - if (e->e.vector.list->next->next) { - // four vals: x, y, z, w - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - expr_t *w = z->next; - x = fold_constants (cast_expr (&type_float, x)); - y = fold_constants (cast_expr (&type_float, y)); - z = fold_constants (cast_expr (&type_float, z)); - w = fold_constants (cast_expr (&type_float, w)); - if (is_constant (x) && is_constant (y) && is_constant (z) - && is_constant (w)) { - val[0] = expr_float(x); - val[1] = expr_float(y); - val[2] = expr_float(z); - val[3] = expr_float(w); - return new_quaternion_expr (val); - } - // at least one of x, y, z, w is not constant, so rebuild the - // list incase any of them are new expressions - w->next = 0; - z->next = w; - y->next = z; - x->next = y; - e->e.vector.list = x; - return e; - } else { - // v, s - expr_t *v = e->e.vector.list; - expr_t *s = v->next; - - v = convert_vector (v); - s = fold_constants (cast_expr (&type_float, s)); - if (is_constant (v) && is_constant (s)) { - memcpy (val, expr_vector (v), 3 * sizeof (float)); - val[3] = expr_float (s); - return new_quaternion_expr (val); - } - // Either v or s is not constant, so can't convert to a quaternion - // constant. - // Rebuild the list in case v or s is a new expression - // the list will always be v, s - s->next = 0; - v->next = s; - e->e.vector.list = v; - return e; - } - } - internal_error (e, "bogus vector expression"); -} - type_t * get_type (expr_t *e) { @@ -827,78 +744,6 @@ new_vector_expr (const float *vector_val) return e; } -expr_t * -new_vector_list (expr_t *e) -{ - expr_t *t; - int count; - type_t *type = &type_vector; - expr_t *vec; - - e = reverse_expr_list (e); // put the elements in the right order - for (t = e, count = 0; t; t = t->next) - count++; - switch (count) { - case 4: - type = &type_quaternion; - case 3: - // quaternion or vector. all expressions must be compatible with - // a float (ie, a scalar) - for (t = e; t; t = t->next) { - if (t->type == ex_error) { - return t; - } - if (!is_scalar (get_type (t))) { - return error (t, "invalid type for vector element"); - } - } - vec = new_expr (); - vec->type = ex_vector; - vec->e.vector.type = type; - vec->e.vector.list = e; - break; - case 2: - if (e->type == ex_error || e->next->type == ex_error) { - return e; - } - if (is_scalar (get_type (e)) && is_scalar (get_type (e->next))) { - // scalar, scalar - // expand [x, y] to [x, y, 0] - e->next->next = new_float_expr (0); - vec = new_expr (); - vec->type = ex_vector; - vec->e.vector.type = type; - vec->e.vector.list = e; - break; - } - // quaternion. either scalar, vector or vector, scalar - if (is_scalar (get_type (e)) - && is_vector (get_type (e->next))) { - // scalar, vector - // swap expressions - t = e; - e = e->next; - e->next = t; - t->next = 0; - } else if (is_vector (get_type (e)) - && is_scalar (get_type (e->next))) { - // vector, scalar - // do nothing - } else { - return error (t, "invalid types for vector elements"); - } - // v, s - vec = new_expr (); - vec->type = ex_vector; - vec->e.vector.type = &type_quaternion; - vec->e.vector.list = e; - break; - default: - return error (e, "invalid number of elements in vector exprssion"); - } - return vec; -} - expr_t * new_entity_expr (int entity_val) { diff --git a/tools/qfcc/source/expr_vector.c b/tools/qfcc/source/expr_vector.c new file mode 100644 index 000000000..8b7cc1495 --- /dev/null +++ b/tools/qfcc/source/expr_vector.c @@ -0,0 +1,216 @@ +/* + expr_vector.c + + vector expressions + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/04/27 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "QF/alloc.h" +#include "QF/dstring.h" +#include "QF/mathlib.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/class.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/defspace.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/emit.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/function.h" +#include "tools/qfcc/include/idstuff.h" +#include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/options.h" +#include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" +#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/struct.h" +#include "tools/qfcc/include/symtab.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" + +#include "tools/qfcc/source/qc-parse.h" + +expr_t * +convert_vector (expr_t *e) +{ + float val[4]; + + if (e->type != ex_vector) + return e; + if (is_vector(e->e.vector.type)) { + // guaranteed to have three elements + expr_t *x = e->e.vector.list; + expr_t *y = x->next; + expr_t *z = y->next; + x = fold_constants (cast_expr (&type_float, x)); + y = fold_constants (cast_expr (&type_float, y)); + z = fold_constants (cast_expr (&type_float, z)); + if (is_constant (x) && is_constant (y) && is_constant (z)) { + val[0] = expr_float(x); + val[1] = expr_float(y); + val[2] = expr_float(z); + return new_vector_expr (val); + } + // at least one of x, y, z is not constant, so rebuild the + // list incase any of them are new expressions + z->next = 0; + y->next = z; + x->next = y; + e->e.vector.list = x; + return e; + } + if (is_quaternion(e->e.vector.type)) { + // guaranteed to have two or four elements + if (e->e.vector.list->next->next) { + // four vals: x, y, z, w + expr_t *x = e->e.vector.list; + expr_t *y = x->next; + expr_t *z = y->next; + expr_t *w = z->next; + x = fold_constants (cast_expr (&type_float, x)); + y = fold_constants (cast_expr (&type_float, y)); + z = fold_constants (cast_expr (&type_float, z)); + w = fold_constants (cast_expr (&type_float, w)); + if (is_constant (x) && is_constant (y) && is_constant (z) + && is_constant (w)) { + val[0] = expr_float(x); + val[1] = expr_float(y); + val[2] = expr_float(z); + val[3] = expr_float(w); + return new_quaternion_expr (val); + } + // at least one of x, y, z, w is not constant, so rebuild the + // list incase any of them are new expressions + w->next = 0; + z->next = w; + y->next = z; + x->next = y; + e->e.vector.list = x; + return e; + } else { + // v, s + expr_t *v = e->e.vector.list; + expr_t *s = v->next; + + v = convert_vector (v); + s = fold_constants (cast_expr (&type_float, s)); + if (is_constant (v) && is_constant (s)) { + memcpy (val, expr_vector (v), 3 * sizeof (float)); + val[3] = expr_float (s); + return new_quaternion_expr (val); + } + // Either v or s is not constant, so can't convert to a quaternion + // constant. + // Rebuild the list in case v or s is a new expression + // the list will always be v, s + s->next = 0; + v->next = s; + e->e.vector.list = v; + return e; + } + } + internal_error (e, "bogus vector expression"); +} + +expr_t * +new_vector_list (expr_t *e) +{ + expr_t *t; + int count; + type_t *type = &type_vector; + expr_t *vec; + + e = reverse_expr_list (e); // put the elements in the right order + for (t = e, count = 0; t; t = t->next) + count++; + switch (count) { + case 4: + type = &type_quaternion; + case 3: + // quaternion or vector. all expressions must be compatible with + // a float (ie, a scalar) + for (t = e; t; t = t->next) { + if (t->type == ex_error) { + return t; + } + if (!is_scalar (get_type (t))) { + return error (t, "invalid type for vector element"); + } + } + vec = new_expr (); + vec->type = ex_vector; + vec->e.vector.type = type; + vec->e.vector.list = e; + break; + case 2: + if (e->type == ex_error || e->next->type == ex_error) { + return e; + } + if (is_scalar (get_type (e)) && is_scalar (get_type (e->next))) { + // scalar, scalar + // expand [x, y] to [x, y, 0] + e->next->next = new_float_expr (0); + vec = new_expr (); + vec->type = ex_vector; + vec->e.vector.type = type; + vec->e.vector.list = e; + break; + } + // quaternion. either scalar, vector or vector, scalar + if (is_scalar (get_type (e)) + && is_vector (get_type (e->next))) { + // scalar, vector + // swap expressions + t = e; + e = e->next; + e->next = t; + t->next = 0; + } else if (is_vector (get_type (e)) + && is_scalar (get_type (e->next))) { + // vector, scalar + // do nothing + } else { + return error (t, "invalid types for vector elements"); + } + // v, s + vec = new_expr (); + vec->type = ex_vector; + vec->e.vector.type = &type_quaternion; + vec->e.vector.list = e; + break; + default: + return error (e, "invalid number of elements in vector exprssion"); + } + return vec; +} From 73d6e97e7b86a257ad1656e3441ba0dcea942ea5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Apr 2022 18:07:30 +0900 Subject: [PATCH 2696/3664] [qwaq] Ensure PR_Init_Cvars is called only once Registering the same cvar more than once is currently a fatal error, but qwaq was calling PR_Init_Cvars for each thread. Oops. --- ruamoko/qwaq/builtins/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index b4954a0bb..02e703822 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -149,6 +149,7 @@ init_qf (void) //Cvar_Set (developer, "1"); Memory_Init (Sys_Alloc (8 * 1024 * 1024), 8 * 1024 * 1024); + PR_Init_Cvars (); } static void @@ -208,7 +209,6 @@ create_progs (qwaq_thread_t *thread) pr->no_exec_limit = 1; pr->hashlink_freelist = &thread->hashlink_freelist; - PR_Init_Cvars (); pr_debug = 2; pr_boundscheck = 0; PR_Init (pr); From 875c9bde7c169aebc5fb4ba7b8169662cbf0298c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Apr 2022 18:10:40 +0900 Subject: [PATCH 2697/3664] [gamecode] Print operand widths when not 1 The widths for all three operands are printed if any is greater than 1. Makes figuring out which instruction is executing a little easier. --- libs/gamecode/pr_debug.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 2f3d4905f..01d9f6ebe 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1490,6 +1490,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) int dump_code = contents & 2; const char *fmt; const char *mnemonic; + const char *width = ""; dfunction_t *call_func = 0; pr_def_t *param_def = 0; pr_auxfunction_t *aux_func = 0; @@ -1558,13 +1559,15 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) print_raw_op (pr, s->a, PR_BASE_IND (s->op, A), op_type[0], op_width[0]), print_raw_op (pr, s->b, PR_BASE_IND (s->op, B), - op_type[0], op_width[0]), + op_type[1], op_width[1]), print_raw_op (pr, s->c, PR_BASE_IND (s->op, C), - op_type[0], op_width[0])); + op_type[2], op_width[2])); } + } else if (op_width[0] > 1 || op_width[1] > 1 || op_width[2] > 1) { + width = va (res->va, "{%d,%d,%d}", VectorExpand (op_width)); } - dasprintf (res->line, "%s ", mnemonic); + dasprintf (res->line, "%s%s ", mnemonic, width); while (*fmt) { if (*fmt == '%') { From c120bf294016c73f2770c3f8a5d564770b63fb7a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Apr 2022 21:24:46 +0900 Subject: [PATCH 2698/3664] [qfcc] Add functions to store and load values This makes working with constant expressions much less tedious, especially when the relevant code needs to work with many types. --- tools/qfcc/include/value.h | 5 +++++ tools/qfcc/source/value.c | 39 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index 21e10f43d..5ff0fa925 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -40,6 +40,7 @@ struct def_s; struct ex_value_s; struct tempop_s; struct type_s; +struct pr_type_s; struct ex_value_s *new_string_val (const char *string_val); struct ex_value_s *new_double_val (double double_val); @@ -57,6 +58,10 @@ struct ex_value_s *new_int_val (int int_val); struct ex_value_s *new_uint_val (int uint_val); struct ex_value_s *new_short_val (short short_val); struct ex_value_s *new_nil_val (struct type_s *type); +struct ex_value_s *new_type_value (const struct type_s *type, + const struct pr_type_s *data); +void value_store (pr_type_t *dst, const struct type_s *dstType, + const struct expr_s *src); struct ex_value_s *convert_value (struct ex_value_s *value, struct type_s *type); diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index c119473c9..a88af6ea3 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -269,6 +269,45 @@ new_nil_val (type_t *type) return find_value (&val); } +ex_value_t * +new_type_value (const type_t *type, const pr_type_t *data) +{ + size_t typeSize = type_size (type) * sizeof (pr_type_t); + ex_value_t val = {}; + set_val_type (&val, (type_t *) type);//FIXME cast + memcpy (&val.v, data, typeSize); + return find_value (&val); +} + +void +value_store (pr_type_t *dst, const type_t *dstType, const expr_t *src) +{ + size_t dstSize = type_size (dstType) * sizeof (pr_type_t); + + if (src->type == ex_nil) { + memset (dst, 0, dstSize); + return; + } + if (src->type == ex_symbol && src->e.symbol->sy_type == sy_var) { + // initialized global def treated as a constant + // from the tests in cast_expr, the def is known to be constant + def_t *def = src->e.symbol->s.def; + memcpy (dst, &D_PACKED (pr_type_t, def), dstSize); + return; + } + ex_value_t *val = 0; + if (src->type == ex_value) { + val = src->e.value; + } + if (src->type == ex_symbol && src->e.symbol->sy_type == sy_const) { + val = src->e.symbol->s.value; + } + if (!val) { + internal_error (src, "unexpected constant expression type"); + } + memcpy (dst, &val->v, dstSize); +} + static hashtab_t *string_imm_defs; static hashtab_t *float_imm_defs; static hashtab_t *vector_imm_defs; From ae0b3a58706ccdc9e7453cfc0bdf6a5bb1b20b2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Apr 2022 21:32:41 +0900 Subject: [PATCH 2699/3664] [qfcc] Add some utility functions for working with vector types Finding vector types from base type and width, and getting the base type for a vector type, as well as basic promotion rules for math types. --- tools/qfcc/include/type.h | 5 +++ tools/qfcc/source/statements.c | 17 ++------ tools/qfcc/source/type.c | 77 ++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 14 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 156189d33..69ca4bc4b 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -160,6 +160,8 @@ type_t *find_type (type_t *new); void new_typedef (const char *name, type_t *type); type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); +type_t *vector_type (const type_t *ele_type, int width) __attribute__((pure)); +type_t *base_type (const type_t *vec_type) __attribute__((pure)); type_t *array_type (type_t *aux, int size); type_t *based_array_type (type_t *aux, int base, int top); type_t *alias_type (type_t *type, type_t *alias_chain, const char *name); @@ -187,6 +189,7 @@ int is_array (const type_t *type) __attribute__((pure)); int is_structural (const type_t *type) __attribute__((pure)); int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); int type_assignable (const type_t *dst, const type_t *src); +int type_promotes (const type_t *dst, const type_t *src) __attribute__((pure)); int type_same (const type_t *dst, const type_t *src) __attribute__((pure)); int type_size (const type_t *type) __attribute__((pure)); int type_width (const type_t *type) __attribute__((pure)); @@ -197,5 +200,7 @@ void chain_initial_types (void); void clear_typedefs (void); extern type_t *ev_types[]; +extern int type_cast_map[]; +#define TYPE_CAST_CODE(from, to, width) (((width) << 6) | ((from) << 3) | (to)) #endif//__type_h diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index fda9e9a2e..7c7ad4d4b 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1760,17 +1760,6 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } -static int type_map[ev_type_count] = { - [ev_int] = 0, - [ev_float] = 1, - [ev_long] = 2, - [ev_double] = 3, - [ev_uint] = 4, - //[ev_bool32] = 5, - [ev_ulong] = 6, - //[ev_bool64] = 7, -}; - static sblock_t * expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1786,10 +1775,10 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) s = new_statement (st_expr, "conv", e); s->opa = src; if (options.code.progsversion == PROG_VERSION) { - int from = type_map[src_type->type]; - int to = type_map[type->type]; + int from = type_cast_map[src_type->type]; + int to = type_cast_map[type->type]; int width = type_width (src_type) - 1; - int conv = (width << 6) | (from << 3) | to; + int conv = TYPE_CAST_CODE (from, to, width); s->opb = short_operand (conv, e); } s->opc = *op; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 0387f862b..f25cb6eba 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -89,6 +89,11 @@ type_t type_invalid = { }; #include "tools/qfcc/include/vec_types.h" +#define VEC_TYPE(type_name, base_type) &type_##type_name, +static type_t *vec_types[] = { +#include "tools/qfcc/include/vec_types.h" + 0 +}; type_t *type_nil; type_t *type_default; type_t *type_long_int; @@ -145,6 +150,17 @@ type_t *ev_types[ev_type_count] = { &type_invalid, }; +int type_cast_map[ev_type_count] = { + [ev_int] = 0, + [ev_float] = 1, + [ev_long] = 2, + [ev_double] = 3, + [ev_uint] = 4, + //[ev_bool32] = 5, + [ev_ulong] = 6, + //[ev_bool64] = 7, +}; + static type_t *types_freelist; etype_t @@ -524,6 +540,38 @@ pointer_type (type_t *aux) return new; } +type_t * +vector_type (const type_t *ele_type, int width) +{ + if (width == 1) { + for (type_t **t = ev_types; t - ev_types < ev_type_count; t++) { + if ((*t)->type == ele_type->type && (*t)->width == 1) { + return *t; + } + } + } + for (type_t **vtype = vec_types; *vtype; vtype++) { + if ((*vtype)->type == ele_type->type + && (*vtype)->width == width) { + return *vtype; + } + } + return 0; +} + +type_t * +base_type (const type_t *vec_type) +{ + if (!is_math (vec_type)) { + return 0; + } + // vec_type->type for quaternion and vector points back to itself + if (is_quaternion (vec_type) || is_vector (vec_type)) { + return &type_float; + } + return ev_types[vec_type->type]; +} + type_t * array_type (type_t *aux, int size) { @@ -1097,6 +1145,35 @@ type_assignable (const type_t *dst, const type_t *src) return 0; } +int +type_promotes (const type_t *dst, const type_t *src) +{ + dst = unalias_type (dst); + src = unalias_type (src); + // nothing promotes to int + if (is_int (dst)) { + return 0; + } + if (is_uint (dst) && is_int (src)) { + return 1; + } + if (is_long (dst) && (is_int (src) || is_uint (src))) { + return 1; + } + if (is_ulong (dst) && (is_int (src) || is_uint (src) || is_long (src))) { + return 1; + } + if (is_float (dst) && (is_int (src) || is_uint (src))) { + return 1; + } + //XXX what to do with (u)long<->float? + // everything promotes to double + if (is_double (dst)) { + return 1; + } + return 0; +} + int type_same (const type_t *dst, const type_t *src) { From 85d851572ffecf46b1a800229d013dd2e62d43d2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Apr 2022 21:36:15 +0900 Subject: [PATCH 2700/3664] [qfcc] Implement constant casts for the new vector types Nicely, I was able to reuse the generated conversion code used by the progs engine to do the work in qfcc, just needed appropriate definitions for the operand macros, and to set up the conversion code. Helped greatly by the new value load/store functions. --- tools/qfcc/include/expr.h | 4 +- tools/qfcc/source/Makemodule.am | 1 + tools/qfcc/source/expr.c | 119 ++++--------------------- tools/qfcc/source/expr_cast.c | 148 ++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+), 102 deletions(-) create mode 100644 tools/qfcc/source/expr_cast.c diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 2b3887ae1..3c2f2a555 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -205,6 +205,8 @@ typedef struct ex_value_s { unsigned uint_val; ///< unsigned int constant int16_t short_val; ///< short constant uint16_t ushort_val; ///< unsigned short constant +#define VEC_TYPE(type_name, base_type) pr_##type_name##_t type_name##_val; +#include "tools/qfcc/include/vec_types.h" } v; } ex_value_t; @@ -309,7 +311,6 @@ expr_t *type_mismatch (expr_t *e1, expr_t *e2, int op); expr_t *param_mismatch (expr_t *e, int param, const char *fn, struct type_s *t1, struct type_s *t2); -expr_t *cast_error (expr_t *e, struct type_s *t1, struct type_s *t2); expr_t *test_error (expr_t *e, struct type_s *t); extern expr_t *local_expr; @@ -640,6 +641,7 @@ unsigned expr_uint (expr_t *e) __attribute__((pure)); */ expr_t *new_short_expr (short short_val); short expr_short (expr_t *e) __attribute__((pure)); +unsigned short expr_ushort (expr_t *e) __attribute__((pure)); int expr_integral (expr_t *e) __attribute__((pure)); diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index 0406cea3e..a070fad67 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -28,6 +28,7 @@ qfcc_SOURCES = \ tools/qfcc/source/expr_assign.c \ tools/qfcc/source/expr_binary.c \ tools/qfcc/source/expr_bool.c \ + tools/qfcc/source/expr_cast.c \ tools/qfcc/source/expr_compound.c \ tools/qfcc/source/expr_obj.c \ tools/qfcc/source/expr_vector.c \ diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 8033d6435..388ab8e14 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -214,16 +214,9 @@ extract_type (expr_t *e) expr_t * type_mismatch (expr_t *e1, expr_t *e2, int op) { - dstring_t *t1 = dstring_newstr (); - dstring_t *t2 = dstring_newstr (); - - print_type_str (t1, get_type (e1)); - print_type_str (t2, get_type (e2)); - e1 = error (e1, "type mismatch: %s %s %s", - t1->str, get_op_string (op), t2->str); - dstring_delete (t1); - dstring_delete (t2); + get_type_string (get_type (e1)), get_op_string (op), + get_type_string (get_type (e2))); return e1; } @@ -243,21 +236,6 @@ param_mismatch (expr_t *e, int param, const char *fn, type_t *t1, type_t *t2) return e; } -expr_t * -cast_error (expr_t *e, type_t *t1, type_t *t2) -{ - dstring_t *s1 = dstring_newstr (); - dstring_t *s2 = dstring_newstr (); - - print_type_str (s1, t1); - print_type_str (s2, t2); - - e = error (e, "cannot cast from %s to %s", s1->str, s2->str); - dstring_delete (s1); - dstring_delete (s2); - return e; -} - expr_t * test_error (expr_t *e, type_t *t) { @@ -1145,6 +1123,22 @@ expr_short (expr_t *e) internal_error (e, "not a short constant"); } +unsigned short +expr_ushort (expr_t *e) +{ + if (e->type == ex_nil) { + return 0; + } + if (e->type == ex_value && e->e.value->lltype == ev_ushort) { + return e->e.value->v.ushort_val; + } + if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const + && e->e.symbol->type->type == ev_ushort) { + return e->e.symbol->s.value->v.ushort_val; + } + internal_error (e, "not a ushort constant"); +} + int is_integral_val (expr_t *e) { @@ -2872,83 +2866,6 @@ think_expr (symbol_t *think_sym) return new_symbol_expr (think_sym); } -expr_t * -cast_expr (type_t *dstType, expr_t *e) -{ - expr_t *c; - type_t *srcType; - - convert_name (e); - - if (e->type == ex_error) - return e; - - dstType = (type_t *) unalias_type (dstType); //FIXME cast - srcType = get_type (e); - - if (dstType == srcType) - return e; - - if ((dstType == type_default && is_enum (srcType)) - || (is_enum (dstType) && srcType == type_default)) - return e; - if ((is_ptr (dstType) && is_string (srcType)) - || (is_string (dstType) && is_ptr (srcType))) { - c = new_alias_expr (dstType, e); - return c; - } - if (!(is_ptr (dstType) && (is_ptr (srcType) || is_integral (srcType) - || is_array (srcType))) - && !(is_integral (dstType) && is_ptr (srcType)) - && !(is_func (dstType) && is_func (srcType)) - && !(is_scalar (dstType) && is_scalar (srcType))) { - return cast_error (e, srcType, dstType); - } - if (is_array (srcType)) { - return address_expr (e, dstType->t.fldptr.type); - } - if (is_constant (e) && is_scalar (dstType) && is_scalar (srcType)) { - ex_value_t *val = 0; - if (e->type == ex_symbol && e->e.symbol->sy_type == sy_const) { - val = e->e.symbol->s.value; - } else if (e->type == ex_symbol - && e->e.symbol->sy_type == sy_var) { - // initialized global def treated as a constant - // from the tests above, the def is known to be constant - // and of one of the three storable scalar types - def_t *def = e->e.symbol->s.def; - if (is_float (def->type)) { - val = new_float_val (D_FLOAT (def)); - } else if (is_double (def->type)) { - val = new_double_val (D_DOUBLE (def)); - } else if (is_integral (def->type)) { - val = new_int_val (D_INT (def)); - } - } else if (e->type == ex_value) { - val = e->e.value; - } else if (e->type == ex_nil) { - convert_nil (e, dstType); - return e; - } - if (!val) - internal_error (e, "unexpected constant expression type"); - e->e.value = convert_value (val, dstType); - e->type = ex_value; - c = e; - } else if (is_integral (dstType) && is_integral (srcType)) { - c = new_alias_expr (dstType, e); - } else if (is_scalar (dstType) && is_scalar (srcType)) { - c = new_unary_expr ('C', e); - c->e.expr.type = dstType; - } else if (e->type == ex_uexpr && e->e.expr.op == '.') { - e->e.expr.type = dstType; - c = e; - } else { - c = new_alias_expr (dstType, e); - } - return c; -} - expr_t * encode_expr (type_t *type) { diff --git a/tools/qfcc/source/expr_cast.c b/tools/qfcc/source/expr_cast.c new file mode 100644 index 000000000..9ec9e9d1a --- /dev/null +++ b/tools/qfcc/source/expr_cast.c @@ -0,0 +1,148 @@ +/* + expr_cast.c + + expression casting + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/04/27 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "QF/mathlib.h" + +#include "tools/qfcc/include/qfcc.h" +#include "tools/qfcc/include/def.h" +#include "tools/qfcc/include/diagnostic.h" +#include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/type.h" +#include "tools/qfcc/include/value.h" + +static expr_t * +cast_error (expr_t *e, type_t *t1, type_t *t2) +{ + e = error (e, "cannot cast from %s to %s", get_type_string (t1), + get_type_string (t2)); + return e; +} + +static void +do_conversion (pr_type_t *dst_value, type_t *dstType, + pr_type_t *src_value, type_t *srcType, expr_t *expr) +{ + int from = type_cast_map[base_type (srcType)->type]; + int to = type_cast_map[base_type (dstType)->type]; + int width = type_width (srcType) - 1; + int conversion = TYPE_CAST_CODE (from, to, width); +#define OPA(type) (*((pr_##type##_t *) (src_value))) +#define OPC(type) (*((pr_##type##_t *) (dst_value))) + switch (conversion) { +#include "libs/gamecode/pr_convert.cinc" + default: + internal_error (expr, "invalid conversion code: %04o", conversion); + } +} + +static expr_t * +cast_math (type_t *dstType, type_t *srcType, expr_t *expr) +{ + pr_type_t src_value[type_size (srcType)]; + pr_type_t dst_value[type_size (dstType)]; + + value_store (src_value, srcType, expr); + + do_conversion (dst_value, dstType, src_value, srcType, expr); + + expr_t *val = new_expr (); + val->type = ex_value; + val->e.value = new_type_value (dstType, dst_value); + return val; +} + +expr_t * +cast_expr (type_t *dstType, expr_t *e) +{ + expr_t *c; + type_t *srcType; + + convert_name (e); + + if (e->type == ex_error) + return e; + + dstType = (type_t *) unalias_type (dstType); //FIXME cast + srcType = get_type (e); + + if (dstType == srcType) + return e; + + if ((dstType == type_default && is_enum (srcType)) + || (is_enum (dstType) && srcType == type_default)) + return e; + if ((is_ptr (dstType) && is_string (srcType)) + || (is_string (dstType) && is_ptr (srcType))) { + c = new_alias_expr (dstType, e); + return c; + } + if (!(is_ptr (dstType) && (is_ptr (srcType) || is_integral (srcType) + || is_array (srcType))) + && !(is_integral (dstType) && is_ptr (srcType)) + && !(is_func (dstType) && is_func (srcType)) + && !(is_math (dstType) && is_math (srcType) + && type_width (dstType) == type_width (srcType)) + && !((is_int (dstType) || is_uint (dstType)) + && (is_short (srcType) || is_ushort (srcType)) + // [u]short is always width 0 + && type_width (dstType) == 1)) { + return cast_error (e, srcType, dstType); + } + if (is_array (srcType)) { + return address_expr (e, dstType->t.fldptr.type); + } + if (is_short (srcType)) { + e = new_int_expr (expr_short (e)); + srcType = &type_int; + } else if (is_ushort (srcType)) { + e = new_int_expr (expr_ushort (e)); + srcType = &type_int; + } + if (is_constant (e) && is_math (dstType) && is_math (srcType)) { + return cast_math (dstType, srcType, e); + } else if (is_integral (dstType) && is_integral (srcType)) { + c = new_alias_expr (dstType, e); + } else if (is_scalar (dstType) && is_scalar (srcType)) { + c = new_unary_expr ('C', e); + c->e.expr.type = dstType; + } else if (e->type == ex_uexpr && e->e.expr.op == '.') { + e->e.expr.type = dstType; + c = e; + } else { + c = new_alias_expr (dstType, e); + } + return c; +} From 04f60e5ff1586eefbcefd498df6ca0923c291b31 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 27 Apr 2022 21:45:05 +0900 Subject: [PATCH 2701/3664] [qfcc] Rework vector expression handling Use with quaternions and vectors is a little broken in that vec4/quaternion and vec3/vector are not the same types (by design) and thus a cast is needed (not what I want, though). However, creating vectors (that happen to be int due to int constants) does seem to be working nicely otherwise. --- tools/qfcc/include/expr.h | 2 - tools/qfcc/source/dot_expr.c | 36 +---- tools/qfcc/source/expr.c | 5 +- tools/qfcc/source/expr_assign.c | 84 +++--------- tools/qfcc/source/expr_binary.c | 2 - tools/qfcc/source/expr_vector.c | 227 +++++++++++++------------------- tools/qfcc/source/statements.c | 71 +++------- 7 files changed, 138 insertions(+), 289 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 3c2f2a555..455f8b4da 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -761,8 +761,6 @@ expr_t *new_param_expr (struct type_s *type, int num); */ void convert_name (expr_t *e); -expr_t *convert_vector (expr_t *e); - expr_t *append_expr (expr_t *block, expr_t *e); expr_t *prepend_expr (expr_t *block, expr_t *e); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 29c5ac319..9a1033df4 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -461,39 +461,9 @@ print_vector (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - if (is_vector(e->e.vector.type)) { - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - _print_expr (dstr, x, level, id, next); - _print_expr (dstr, y, level, id, next); - _print_expr (dstr, z, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, x); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, y); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, z); - } - if (is_quaternion(e->e.vector.type)) { - if (e->e.vector.list->next->next) { - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - expr_t *w = z->next; - _print_expr (dstr, x, level, id, next); - _print_expr (dstr, y, level, id, next); - _print_expr (dstr, z, level, id, next); - _print_expr (dstr, w, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, x); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, y); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, z); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, w); - } else { - expr_t *v = e->e.vector.list; - expr_t *s = v->next; - _print_expr (dstr, v, level, id, next); - _print_expr (dstr, s, level, id, next); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, v); - dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, s); - } + for (expr_t *ele = e->e.vector.list; ele; ele = ele->next) { + _print_expr (dstr, ele, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, ele); } dasprintf (dstr, "%*se_%p [label=\"vector %d\"];\n", indent, "", e, e->line); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 388ab8e14..5a057090b 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2104,15 +2104,14 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) // expression tree // That, or always use a temp, since it should get optimized out if (has_function_call (e)) { - expr_t *cast = cast_expr (arg_types[i], convert_vector (e)); + expr_t *cast = cast_expr (arg_types[i], e); expr_t *tmp = new_temp_def_expr (arg_types[i]); *a = expr_file_line (tmp, e); arg_exprs[arg_expr_count][0] = expr_file_line (cast, e); arg_exprs[arg_expr_count][1] = *a; arg_expr_count++; } else { - *a = expr_file_line (cast_expr (arg_types[i], convert_vector (e)), - e); + *a = expr_file_line (cast_expr (arg_types[i], e), e); } a = &(*a)->next; } diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index e193de6aa..59c69c23a 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -211,73 +211,31 @@ check_types_compatible (expr_t *dst, expr_t *src) return type_mismatch (dst, src, '='); } +static int +copy_elements (expr_t *block, expr_t *dst, expr_t *src, int base) +{ + int index = 0; + for (expr_t *e = src->e.vector.list; e; e = e->next) { + if (e->type == ex_vector) { + index += copy_elements (block, dst, e, index + base); + } else { + expr_t *dst_ele = array_expr (dst, new_int_expr (index + base)); + append_expr (block, assign_expr (dst_ele, e)); + index += type_width (get_type (e)); + } + } + return index; +} + static expr_t * assign_vector_expr (expr_t *dst, expr_t *src) { - expr_t *dx, *sx; - expr_t *dy, *sy; - expr_t *dz, *sz; - expr_t *dw, *sw; - expr_t *ds, *ss; - expr_t *dv, *sv; - expr_t *block; - - if (src->type == ex_vector) { - src = convert_vector (src); - if (src->type != ex_vector) { - // src was constant and thus converted - return assign_expr (dst, src); - } - } if (src->type == ex_vector && dst->type != ex_vector) { - if (is_vector(src->e.vector.type)) { - // guaranteed to have three elements - sx = src->e.vector.list; - sy = sx->next; - sz = sy->next; - dx = field_expr (dst, new_name_expr ("x")); - dy = field_expr (dst, new_name_expr ("y")); - dz = field_expr (dst, new_name_expr ("z")); - block = new_block_expr (); - append_expr (block, assign_expr (dx, sx)); - append_expr (block, assign_expr (dy, sy)); - append_expr (block, assign_expr (dz, sz)); - block->e.block.result = dst; - return block; - } - if (is_quaternion(src->e.vector.type)) { - // guaranteed to have two or four elements - if (src->e.vector.list->next->next) { - // four vals: x, y, z, w - sx = src->e.vector.list; - sy = sx->next; - sz = sy->next; - sw = sz->next; - dx = field_expr (dst, new_name_expr ("x")); - dy = field_expr (dst, new_name_expr ("y")); - dz = field_expr (dst, new_name_expr ("z")); - dw = field_expr (dst, new_name_expr ("w")); - block = new_block_expr (); - append_expr (block, assign_expr (dx, sx)); - append_expr (block, assign_expr (dy, sy)); - append_expr (block, assign_expr (dz, sz)); - append_expr (block, assign_expr (dw, sw)); - block->e.block.result = dst; - return block; - } else { - // v, s - sv = src->e.vector.list; - ss = sv->next; - dv = field_expr (dst, new_name_expr ("v")); - ds = field_expr (dst, new_name_expr ("s")); - block = new_block_expr (); - append_expr (block, assign_expr (dv, sv)); - append_expr (block, assign_expr (ds, ss)); - block->e.block.result = dst; - return block; - } - } - internal_error (src, "bogus vector expression"); + expr_t *block = new_block_expr (); + + copy_elements (block, dst, src, 0); + block->e.block.result = dst; + return block; } return 0; } diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index b2ac9eece..5ba5b7f18 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -958,7 +958,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) expr_type_t *expr_type; convert_name (e1); - e1 = convert_vector (e1); // FIXME this is target-specific info and should not be in the // expression tree if (e1->type == ex_alias && is_call (e1->e.alias.expr)) { @@ -982,7 +981,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return e1; convert_name (e2); - e2 = convert_vector (e2); if (e2->type == ex_error) return e2; diff --git a/tools/qfcc/source/expr_vector.c b/tools/qfcc/source/expr_vector.c index 8b7cc1495..c9d65ced8 100644 --- a/tools/qfcc/source/expr_vector.c +++ b/tools/qfcc/source/expr_vector.c @@ -62,155 +62,110 @@ #include "tools/qfcc/source/qc-parse.h" expr_t * -convert_vector (expr_t *e) +new_vector_list (expr_t *expr_list) { - float val[4]; + type_t *ele_type = type_default; - if (e->type != ex_vector) - return e; - if (is_vector(e->e.vector.type)) { - // guaranteed to have three elements - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - x = fold_constants (cast_expr (&type_float, x)); - y = fold_constants (cast_expr (&type_float, y)); - z = fold_constants (cast_expr (&type_float, z)); - if (is_constant (x) && is_constant (y) && is_constant (z)) { - val[0] = expr_float(x); - val[1] = expr_float(y); - val[2] = expr_float(z); - return new_vector_expr (val); - } - // at least one of x, y, z is not constant, so rebuild the - // list incase any of them are new expressions - z->next = 0; - y->next = z; - x->next = y; - e->e.vector.list = x; - return e; - } - if (is_quaternion(e->e.vector.type)) { - // guaranteed to have two or four elements - if (e->e.vector.list->next->next) { - // four vals: x, y, z, w - expr_t *x = e->e.vector.list; - expr_t *y = x->next; - expr_t *z = y->next; - expr_t *w = z->next; - x = fold_constants (cast_expr (&type_float, x)); - y = fold_constants (cast_expr (&type_float, y)); - z = fold_constants (cast_expr (&type_float, z)); - w = fold_constants (cast_expr (&type_float, w)); - if (is_constant (x) && is_constant (y) && is_constant (z) - && is_constant (w)) { - val[0] = expr_float(x); - val[1] = expr_float(y); - val[2] = expr_float(z); - val[3] = expr_float(w); - return new_quaternion_expr (val); - } - // at least one of x, y, z, w is not constant, so rebuild the - // list incase any of them are new expressions - w->next = 0; - z->next = w; - y->next = z; - x->next = y; - e->e.vector.list = x; - return e; - } else { - // v, s - expr_t *v = e->e.vector.list; - expr_t *s = v->next; + // lists are built in reverse order + expr_list = reverse_expr_list (expr_list); - v = convert_vector (v); - s = fold_constants (cast_expr (&type_float, s)); - if (is_constant (v) && is_constant (s)) { - memcpy (val, expr_vector (v), 3 * sizeof (float)); - val[3] = expr_float (s); - return new_quaternion_expr (val); - } - // Either v or s is not constant, so can't convert to a quaternion - // constant. - // Rebuild the list in case v or s is a new expression - // the list will always be v, s - s->next = 0; - v->next = s; - e->e.vector.list = v; - return e; - } - } - internal_error (e, "bogus vector expression"); -} - -expr_t * -new_vector_list (expr_t *e) -{ - expr_t *t; - int count; - type_t *type = &type_vector; - expr_t *vec; - - e = reverse_expr_list (e); // put the elements in the right order - for (t = e, count = 0; t; t = t->next) + int width = 0; + int count = 0; + for (expr_t *e = expr_list; e; e = e->next) { count++; + type_t *t = get_type (e); + if (!t) { + return e; + } + if (!is_math (t)) { + return error (e, "invalid type for vector element"); + } + width += type_width (t); + if (is_nonscalar (t)) { + t = base_type (t); + } + if (type_promotes (t, ele_type)) { + ele_type = t; + } + } + if (width < 2) { + return error (expr_list, "not a vector"); + } + if (width > 4) { + return error (expr_list, "resulting vector is too large: %d elements", + width); + } + + int all_constant = 1; + expr_t *elements[count + 1]; + elements[count] = 0; + count = 0; + for (expr_t *e = expr_list; e; e = e->next) { + int cast_width = type_width (get_type (e)); + type_t *cast_type = vector_type (ele_type, cast_width); + elements[count] = cast_expr (cast_type, fold_constants (e)); + all_constant = all_constant && is_constant (elements[count]); + count++; + } + switch (count) { case 4: - type = &type_quaternion; + // all scalars (otherwise width would be too large) + break; case 3: - // quaternion or vector. all expressions must be compatible with - // a float (ie, a scalar) - for (t = e; t; t = t->next) { - if (t->type == ex_error) { - return t; - } - if (!is_scalar (get_type (t))) { - return error (t, "invalid type for vector element"); + // shuffle any vectors to the beginning of the list (there should + // be only one, but futhre...) + for (int i = 1; i < count; i++) { + if (is_nonscalar (get_type (elements[i]))) { + expr_t *t = elements[i]; + int j = i; + for (; j > 0 && is_scalar (get_type (elements[j])); j--) { + elements[j] = elements[j - 1]; + } + elements[j] = t; } } - vec = new_expr (); - vec->type = ex_vector; - vec->e.vector.type = type; - vec->e.vector.list = e; break; case 2: - if (e->type == ex_error || e->next->type == ex_error) { - return e; + if (is_scalar (get_type (elements[0])) + && is_nonscalar (get_type (elements[1]))) { + // swap s, v to be v, s (ie, vector always comes before scalar) + expr_t *t = elements[0]; + elements[0] = elements[1]; + elements[1] = t; } - if (is_scalar (get_type (e)) && is_scalar (get_type (e->next))) { - // scalar, scalar - // expand [x, y] to [x, y, 0] - e->next->next = new_float_expr (0); - vec = new_expr (); - vec->type = ex_vector; - vec->e.vector.type = type; - vec->e.vector.list = e; - break; - } - // quaternion. either scalar, vector or vector, scalar - if (is_scalar (get_type (e)) - && is_vector (get_type (e->next))) { - // scalar, vector - // swap expressions - t = e; - e = e->next; - e->next = t; - t->next = 0; - } else if (is_vector (get_type (e)) - && is_scalar (get_type (e->next))) { - // vector, scalar - // do nothing - } else { - return error (t, "invalid types for vector elements"); - } - // v, s - vec = new_expr (); - vec->type = ex_vector; - vec->e.vector.type = &type_quaternion; - vec->e.vector.list = e; break; - default: - return error (e, "invalid number of elements in vector exprssion"); + case 1: + if (is_scalar (get_type (elements[0]))) { + internal_error (expr_list, "confused about vectors"); + } + // it's already a vector + return elements[0]; } + + if (all_constant) { + type_t *vec_type = vector_type (ele_type, width); + pr_type_t value[type_size (vec_type)]; + + for (int i = 0, offs = 0; i < count; i++) { + type_t *src_type = get_type (elements[i]); + value_store (value + offs, src_type, elements[i]); + offs += type_size (src_type); + } + + expr_t *vec = new_expr (); + vec->type = ex_value; + vec->e.value = new_type_value (vec_type, value); + return vec; + } + + for (int i = 0; i < count; i++) { + elements[i]->next = elements[i + 1]; + } + + expr_t *vec = new_expr (); + vec->type = ex_vector; + vec->e.vector.type = vector_type (ele_type, width); + vec->e.vector.list = elements[0]; return vec; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 7c7ad4d4b..140023998 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1926,13 +1926,28 @@ expr_temp (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static int +statement_copy_elements (sblock_t **sblock, expr_t *dst, expr_t *src, int base) +{ + int index = 0; + for (expr_t *e = src->e.vector.list; e; e = e->next) { + if (e->type == ex_vector) { + index += statement_copy_elements (sblock, dst, e, index + base); + } else { + int size = type_size (base_type (get_type (dst))); + type_t *src_type = get_type (e); + expr_t *dst_ele = new_offset_alias_expr (src_type, dst, + size * (index + base)); + index += type_width (src_type); + *sblock = statement_slist (*sblock, assign_expr (dst_ele, e)); + } + } + return index; +} + static sblock_t * expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) { - expr_t *x, *y, *z, *w; - expr_t *s, *v; - expr_t *ax, *ay, *az, *aw; - expr_t *as, *av; expr_t *tmp; type_t *vec_type = get_type (e); int file = pr.source_file; @@ -1942,52 +1957,8 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op) pr.source_line = e->line; tmp = new_temp_def_expr (vec_type); - if (is_vector(vec_type)) { - // guaranteed to have three elements - x = e->e.vector.list; - y = x->next; - z = y->next; - ax = new_name_expr ("x"); - ay = new_name_expr ("y"); - az = new_name_expr ("z"); - ax = assign_expr (field_expr (tmp, ax), x); - ay = assign_expr (field_expr (tmp, ay), y); - az = assign_expr (field_expr (tmp, az), z); - sblock = statement_slist (sblock, ax); - sblock = statement_slist (sblock, ay); - sblock = statement_slist (sblock, az); - } else { - // guaranteed to have two or four elements - if (e->e.vector.list->next->next) { - // four vals: x, y, z, w - x = e->e.vector.list; - y = x->next; - z = y->next; - w = z->next; - ax = new_name_expr ("x"); - ay = new_name_expr ("y"); - az = new_name_expr ("z"); - aw = new_name_expr ("w"); - ax = assign_expr (field_expr (tmp, ax), x); - ay = assign_expr (field_expr (tmp, ay), y); - az = assign_expr (field_expr (tmp, az), z); - aw = assign_expr (field_expr (tmp, aw), w); - sblock = statement_slist (sblock, ax); - sblock = statement_slist (sblock, ay); - sblock = statement_slist (sblock, az); - sblock = statement_slist (sblock, aw); - } else { - // v, s - v = e->e.vector.list; - s = v->next; - av = new_name_expr ("v"); - as = new_name_expr ("s"); - av = assign_expr (field_expr (tmp, av), v); - as = assign_expr (field_expr (tmp, as), s); - sblock = statement_slist (sblock, av); - sblock = statement_slist (sblock, as); - } - } + statement_copy_elements (&sblock, tmp, e, 0); + pr.source_file = file; pr.source_line = line; sblock = statement_subexpr (sblock, tmp, op); From 1eb8b61b838bb1c8dc3ade35a90c151e6bbc5d86 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 28 Apr 2022 17:37:56 +0900 Subject: [PATCH 2702/3664] [qfcc] Clean up handling of value expressions I'd created new_value_expr some time ago, but never used it... Also, replace convert_* with cast_expr to the appropriate type (removes a pile of value check and create code). --- tools/qfcc/include/expr.h | 4 -- tools/qfcc/source/constfold.c | 70 +++------------------ tools/qfcc/source/def.c | 13 ++-- tools/qfcc/source/expr.c | 104 ++++++-------------------------- tools/qfcc/source/expr_binary.c | 8 +-- tools/qfcc/source/expr_cast.c | 5 +- tools/qfcc/source/expr_vector.c | 5 +- 7 files changed, 39 insertions(+), 170 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 455f8b4da..5635141f2 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -768,10 +768,6 @@ expr_t *reverse_expr_list (expr_t *e); void print_expr (expr_t *e); void dump_dot_expr (void *e, const char *filename); -void convert_int (expr_t *e); -void convert_short (expr_t *e); -void convert_short_int (expr_t *e); -void convert_double (expr_t *e); expr_t *convert_nil (expr_t *e, struct type_s *t); expr_t *test_expr (expr_t *e); diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 6b01bc7f4..6f6287f43 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -55,13 +55,6 @@ typedef expr_t *(*operation_t) (int op, expr_t *e, expr_t *e1, expr_t *e2); typedef expr_t *(*unaryop_t) (int op, expr_t *e, expr_t *e1); -static expr_t * -cf_cast_expr (type_t *type, expr_t *e) -{ - e = cast_expr (type, e); - return e; -} - static __attribute__((pure)) int valid_op (int op, int *valid_ops) { @@ -162,33 +155,10 @@ convert_to_float (expr_t *e) if (is_float(get_type (e))) return e; - switch (e->type) { - case ex_value: - switch (e->e.value->lltype) { - case ev_int: - convert_int (e); - return e; - case ev_short: - convert_short (e); - return e; - case ev_double: - convert_double (e); - return e; - default: - internal_error (e, "bad conversion to float: %d", - e->e.value->lltype); - } - break; - case ex_symbol: - case ex_expr: - case ex_uexpr: - case ex_temp: - case ex_block: - e = cf_cast_expr (&type_float, e); - return e; - default: - internal_error (e, 0); - } + expr_t *n = cast_expr (&type_float, e); + n->file = e->file; + n->line = e->line; + return n; } static expr_t * @@ -197,32 +167,10 @@ convert_to_double (expr_t *e) if (is_double(get_type (e))) return e; - switch (e->type) { - case ex_value: - switch (e->e.value->lltype) { - case ev_int: - e->e.value = new_double_val (expr_int (e)); - return e; - case ev_short: - e->e.value = new_double_val (expr_short (e)); - return e; - case ev_float: - e->e.value = new_double_val (expr_float (e)); - return e; - default: - internal_error (e, 0); - } - break; - case ex_symbol: - case ex_expr: - case ex_uexpr: - case ex_temp: - case ex_block: - e = cf_cast_expr (&type_float, e); - return e; - default: - internal_error (e, 0); - } + expr_t *n = cast_expr (&type_double, e); + n->file = e->file; + n->line = e->line; + return n; } static expr_t * @@ -634,7 +582,7 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2) if (op != '.' && extract_type (e1) != extract_type (e2)) return type_mismatch (e1, e2, op); if (op == '.' && is_uint(get_type (e2))) - e->e.expr.e2 = cf_cast_expr (&type_int, e2); + e->e.expr.e2 = cast_expr (&type_int, e2); return e; } diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index b5d63177a..9d9f04d84 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -380,12 +380,13 @@ init_elements (struct def_s *def, expr_t *eles) reloc_def_op (c->e.labelref.label, &dummy); continue; } else if (c->type == ex_value) { - if (c->e.value->lltype == ev_int && is_float (element->type)) { - convert_int (c); - } - if (is_double (get_type (c)) && is_float (element->type) - && c->implicit) { - convert_double (c); + if (is_float (element->type) + && (is_int (get_type (c)) + || (is_double (get_type (c)) && c->implicit))) { + expr_t *n = cast_expr (&type_float, c); + n->line = c->line; + n->file = c->line; + c = n; } if (get_type (c) != element->type) { error (c, "type mismatch in initializer"); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 5a057090b..ca71e4403 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -689,109 +689,73 @@ new_name_expr (const char *name) expr_t * new_string_expr (const char *string_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_string_val (string_val); - return e; + return new_value_expr (new_string_val (string_val)); } expr_t * new_double_expr (double double_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_double_val (double_val); - return e; + return new_value_expr (new_double_val (double_val)); } expr_t * new_float_expr (float float_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_float_val (float_val); - return e; + return new_value_expr (new_float_val (float_val)); } expr_t * new_vector_expr (const float *vector_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_vector_val (vector_val); - return e; + return new_value_expr (new_vector_val (vector_val)); } expr_t * new_entity_expr (int entity_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_entity_val (entity_val); - return e; + return new_value_expr (new_entity_val (entity_val)); } expr_t * new_field_expr (int field_val, type_t *type, def_t *def) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_field_val (field_val, type, def); - return e; + return new_value_expr (new_field_val (field_val, type, def)); } expr_t * new_func_expr (int func_val, type_t *type) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_func_val (func_val, type); - return e; + return new_value_expr (new_func_val (func_val, type)); } expr_t * new_pointer_expr (int val, type_t *type, def_t *def) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_pointer_val (val, type, def, 0); - return e; + return new_value_expr (new_pointer_val (val, type, def, 0)); } expr_t * new_quaternion_expr (const float *quaternion_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_quaternion_val (quaternion_val); - return e; + return new_value_expr (new_quaternion_val (quaternion_val)); } expr_t * new_int_expr (int int_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_int_val (int_val); - return e; + return new_value_expr (new_int_val (int_val)); } expr_t * new_uint_expr (unsigned uint_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_uint_val (uint_val); - return e; + return new_value_expr (new_uint_val (uint_val)); } expr_t * new_short_expr (short short_val) { - expr_t *e = new_expr (); - e->type = ex_value; - e->e.value = new_short_val (short_val); - return e; + return new_value_expr (new_short_val (short_val)); } int @@ -853,11 +817,9 @@ constant_expr (expr_t *e) } else { return e; } - new = new_expr (); - new->type = ex_value; + new = new_value_expr (value); new->line = e->line; new->file = e->file; - new->e.value = value; return new; } @@ -1508,38 +1470,6 @@ convert_from_bool (expr_t *e, type_t *type) return e; } -void -convert_int (expr_t *e) -{ - float float_val = expr_int (e); - e->type = ex_value; - e->e.value = new_float_val (float_val); -} - -void -convert_short (expr_t *e) -{ - float float_val = expr_short (e); - e->type = ex_value; - e->e.value = new_float_val (float_val); -} - -void -convert_short_int (expr_t *e) -{ - float int_val = expr_short (e); - e->type = ex_value; - e->e.value = new_int_val (int_val); -} - -void -convert_double (expr_t *e) -{ - float float_val = expr_double (e); - e->type = ex_value; - e->e.value = new_float_val (float_val); -} - expr_t * convert_nil (expr_t *e, type_t *t) { @@ -2063,7 +1993,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) convert_from_bool (e, get_type (e)); if (is_int_val (e) && options.code.progsversion == PROG_ID_VERSION) - convert_int (e); + e = cast_expr (&type_float, e); if (options.code.promote_float) { if (is_float (get_type (e))) { t = &type_double; @@ -2280,7 +2210,7 @@ return_expr (function_t *f, expr_t *e) e = convert_from_bool (e, (type_t *) ret_type); //FIXME cast } if (is_float(ret_type) && is_int_val (e)) { - convert_int (e); + e = cast_expr (&type_float, e); t = &type_float; } if (is_void(t)) { @@ -2828,7 +2758,7 @@ build_state_expr (expr_t *e) if (think->type == ex_symbol) think = think_expr (think->e.symbol); if (is_int_val (frame)) - convert_int (frame); + frame = cast_expr (&type_float, frame); if (!type_assignable (&type_float, get_type (frame))) return error (frame, "invalid type for frame number"); if (extract_type (think) != ev_func) @@ -2837,7 +2767,7 @@ build_state_expr (expr_t *e) if (step->next) return error (step->next, "too many state arguments"); if (is_int_val (step)) - convert_int (step); + step = cast_expr (&type_float, step); if (!type_assignable (&type_float, get_type (step))) return error (step, "invalid type for step"); } diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 5ba5b7f18..be4b5970f 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -787,11 +787,11 @@ double_compare (int op, expr_t *e1, expr_t *e2) if (is_constant (e1) && e1->implicit && is_double (t1) && is_float (t2)) { t1 = &type_float; - convert_double (e1); + e1 = cast_expr (t1, e1); } if (is_float (t1) && is_constant (e2) && e2->implicit && is_double (t2)) { t2 = &type_float; - convert_double (e2); + e2 = cast_expr (t2, e2); } if (is_double (t1)) { if (is_float (t2)) { @@ -1009,11 +1009,11 @@ binary_expr (int op, expr_t *e1, expr_t *e2) if (is_constant (e1) && is_double (t1) && e1->implicit && is_float (t2)) { t1 = &type_float; - convert_double (e1); + e1 = cast_expr (t1, e1); } if (is_constant (e2) && is_double (t2) && e2->implicit && is_float (t1)) { t2 = &type_float; - convert_double (e2); + e2 = cast_expr (t2, e2); } et1 = low_level_type (t1); diff --git a/tools/qfcc/source/expr_cast.c b/tools/qfcc/source/expr_cast.c index 9ec9e9d1a..a02024c0c 100644 --- a/tools/qfcc/source/expr_cast.c +++ b/tools/qfcc/source/expr_cast.c @@ -78,10 +78,7 @@ cast_math (type_t *dstType, type_t *srcType, expr_t *expr) do_conversion (dst_value, dstType, src_value, srcType, expr); - expr_t *val = new_expr (); - val->type = ex_value; - val->e.value = new_type_value (dstType, dst_value); - return val; + return new_value_expr (new_type_value (dstType, dst_value)); } expr_t * diff --git a/tools/qfcc/source/expr_vector.c b/tools/qfcc/source/expr_vector.c index c9d65ced8..f8e891819 100644 --- a/tools/qfcc/source/expr_vector.c +++ b/tools/qfcc/source/expr_vector.c @@ -153,10 +153,7 @@ new_vector_list (expr_t *expr_list) offs += type_size (src_type); } - expr_t *vec = new_expr (); - vec->type = ex_value; - vec->e.value = new_type_value (vec_type, value); - return vec; + return new_value_expr (new_type_value (vec_type, value)); } for (int i = 0; i < count; i++) { From 8ac53664d7b9b5b8aec092b945979cfa3153ea50 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 28 Apr 2022 23:15:22 +0900 Subject: [PATCH 2703/3664] [simd] Rename VEC_TYPE to QF_VEC_TYPE Makes it less likely to clash with anything (like qfcc's VEC_TYPE :P) --- include/QF/simd/types.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index 43d564745..26aceccd0 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -31,7 +31,7 @@ #include #include -#define VEC_TYPE(t,n,s) \ +#define QF_VEC_TYPE(t,n,s) \ typedef t n __attribute__ ((vector_size (s*sizeof (t)))) /** Three element vector type for interfacing with compact data. @@ -41,8 +41,8 @@ */ typedef double vec3d_t[3]; -VEC_TYPE (double, vec2d_t, 2); -VEC_TYPE (int64_t, vec2l_t, 2); +QF_VEC_TYPE (double, vec2d_t, 2); +QF_VEC_TYPE (int64_t, vec2l_t, 2); /** Four element vector type for horizontal (AOS) vector data. * @@ -53,11 +53,11 @@ VEC_TYPE (int64_t, vec2l_t, 2); * a single component from four vectors, or a single row/column (depending on * context) of an Nx4 or 4xN matrix. */ -VEC_TYPE (double, vec4d_t, 4); +QF_VEC_TYPE (double, vec4d_t, 4); /** Used mostly for __builtin_shuffle. */ -VEC_TYPE (int64_t, vec4l_t, 4); +QF_VEC_TYPE (int64_t, vec4l_t, 4); /** Three element vector type for interfacing with compact data. * @@ -66,8 +66,8 @@ VEC_TYPE (int64_t, vec4l_t, 4); */ typedef float vec3f_t[3]; -VEC_TYPE (float, vec2f_t, 2); -VEC_TYPE (int, vec2i_t, 2); +QF_VEC_TYPE (float, vec2f_t, 2); +QF_VEC_TYPE (int, vec2i_t, 2); /** Four element vector type for horizontal (AOS) vector data. * @@ -78,11 +78,11 @@ VEC_TYPE (int, vec2i_t, 2); * a single component from four vectors, or a single row/column (depending on * context) of an Nx4 or 4xN matrix. */ -VEC_TYPE (float, vec4f_t, 4); +QF_VEC_TYPE (float, vec4f_t, 4); /** Used mostly for __builtin_shuffle. */ -VEC_TYPE (int, vec4i_t, 4); +QF_VEC_TYPE (int, vec4i_t, 4); #define VEC2D_FMT "[%.17g, %.17g]" #define VEC2L_FMT "[%"PRIi64", %"PRIi64"]" From 14545c37cfc7c4990e66d000dbcc9e3ca3b80e18 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 11:22:40 +0900 Subject: [PATCH 2704/3664] [qfcc] Merge printing of values into the one place Having three very similar sets of code for outputting values (just for debug purposes even) got to be a tad annoying. Now there's only one, and in the right place, too (with the other value code). --- tools/qfcc/include/value.h | 1 + tools/qfcc/source/dot_expr.c | 94 ++------------------ tools/qfcc/source/statements.c | 115 +------------------------ tools/qfcc/source/value.c | 151 +++++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 201 deletions(-) diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index 5ff0fa925..197c31514 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -62,6 +62,7 @@ struct ex_value_s *new_type_value (const struct type_s *type, const struct pr_type_s *data); void value_store (pr_type_t *dst, const struct type_s *dstType, const struct expr_s *src); +const char *get_value_string (const struct ex_value_s *value); struct ex_value_s *convert_value (struct ex_value_s *value, struct type_s *type); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 9a1033df4..fdf8238e0 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -49,9 +49,10 @@ #include "tools/qfcc/include/expr.h" #include "tools/qfcc/include/method.h" +#include "tools/qfcc/include/strpool.h" #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" -#include "tools/qfcc/include/strpool.h" +#include "tools/qfcc/include/value.h" #include "tools/qfcc/source/qc-parse.h" @@ -491,96 +492,11 @@ static void print_value (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { int indent = level * 2 + 2; - type_t *type; const char *label = "?!?"; - static dstring_t *type_str; - if (!type_str) { - type_str = dstring_newstr (); - } - - switch (e->e.value->lltype) { - case ev_string: - label = va (0, "\\\"%s\\\"", - quote_string (e->e.value->v.string_val)); - break; - case ev_double: - label = va (0, "f %g", e->e.value->v.double_val); - break; - case ev_float: - label = va (0, "f %g", e->e.value->v.float_val); - break; - case ev_vector: - label = va (0, "'%g %g %g'", - e->e.value->v.vector_val[0], - e->e.value->v.vector_val[1], - e->e.value->v.vector_val[2]); - break; - case ev_quaternion: - label = va (0, "'%g %g %g %g'", - e->e.value->v.quaternion_val[0], - e->e.value->v.quaternion_val[1], - e->e.value->v.quaternion_val[2], - e->e.value->v.quaternion_val[3]); - break; - case ev_ptr: - type = e->e.value->v.pointer.type; - dstring_clearstr(type_str); - if (type) { - print_type_str (type_str, type); - } - if (e->e.value->v.pointer.def) - label = va (0, "(*%s)[%d]<%s>", - type ? type_str->str : "???", - e->e.value->v.pointer.val, - e->e.value->v.pointer.def->name); - else - label = va (0, "(*%s)[%d]", - type ? type_str->str : "???", - e->e.value->v.pointer.val); - break; - case ev_field: - if (e->e.value->v.pointer.def) { - int offset = e->e.value->v.pointer.val; - offset += e->e.value->v.pointer.def->offset; - label = va (0, "field %d", offset); - } else { - label = va (0, "field %d", e->e.value->v.pointer.val); - } - break; - case ev_entity: - label = va (0, "ent %d", e->e.value->v.int_val); - break; - case ev_func: - label = va (0, "func %d", e->e.value->v.int_val); - break; - case ev_int: - label = va (0, "i %d", e->e.value->v.int_val); - break; - case ev_uint: - label = va (0, "u %u", e->e.value->v.uint_val); - break; - case ev_long: - label = va (0, "i %"PRIi64, e->e.value->v.long_val); - break; - case ev_ulong: - label = va (0, "u %"PRIu64, e->e.value->v.ulong_val); - break; - case ev_short: - label = va (0, "s %d", e->e.value->v.short_val); - break; - case ev_ushort: - label = va (0, "us %d", e->e.value->v.ushort_val); - break; - case ev_void: - label = ""; - break; - case ev_invalid: - label = ""; - break; - case ev_type_count: - label = ""; - break; + label = get_value_string (e->e.value); + if (is_string (e->e.value->type)) { + label = quote_string (html_string (label)); } dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, label, e->line); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 140023998..076ef04d5 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -123,63 +123,7 @@ operand_string (operand_t *op) case op_def: return op->def->name; case op_value: - switch (op->value->lltype) { - case ev_string: - return va (0, "\"%s\"", - quote_string (op->value->v.string_val)); - case ev_double: - return va (0, "%g", op->value->v.double_val); - case ev_float: - return va (0, "%g", op->value->v.float_val); - case ev_vector: - return va (0, "'%g %g %g'", - op->value->v.vector_val[0], - op->value->v.vector_val[1], - op->value->v.vector_val[2]); - case ev_quaternion: - return va (0, "'%g %g %g %g'", - op->value->v.quaternion_val[0], - op->value->v.quaternion_val[1], - op->value->v.quaternion_val[2], - op->value->v.quaternion_val[3]); - case ev_ptr: - if (op->value->v.pointer.def) { - return va (0, "ptr %s+%d", - op->value->v.pointer.def->name, - op->value->v.pointer.val); - } else if(op->value->v.pointer.tempop) { - operand_t *tempop = op->value->v.pointer.tempop; - return va (0, "ptr %s+%d", tempop_string (tempop), - op->value->v.pointer.val); - } else { - return va (0, "ptr %d", op->value->v.pointer.val); - } - case ev_field: - return va (0, "field %d", op->value->v.pointer.val); - case ev_entity: - return va (0, "ent %d", op->value->v.int_val); - case ev_func: - return va (0, "func %d", op->value->v.int_val); - case ev_int: - return va (0, "int %d", op->value->v.int_val); - case ev_uint: - return va (0, "uint %u", op->value->v.uint_val); - case ev_long: - return va (0, "long %"PRIi64, op->value->v.long_val); - case ev_ulong: - return va (0, "ulong %"PRIu64, op->value->v.ulong_val); - case ev_short: - return va (0, "short %d", op->value->v.short_val); - case ev_ushort: - return va (0, "ushort %d", op->value->v.ushort_val); - case ev_void: - return "(void)"; - case ev_invalid: - return "(invalid)"; - case ev_type_count: - return "(type_count)"; - } - break; + return get_value_string (op->value); case op_label: return op->label->name; case op_temp: @@ -209,61 +153,8 @@ _print_operand (operand_t *op) printf ("%s", op->def->name); break; case op_value: - printf ("(%s) ", pr_type_name[op->type->type]); - switch (op->value->lltype) { - case ev_string: - printf ("\"%s\"", op->value->v.string_val); - break; - case ev_double: - printf ("%g", op->value->v.double_val); - break; - case ev_float: - printf ("%g", op->value->v.float_val); - break; - case ev_vector: - printf ("'%g", op->value->v.vector_val[0]); - printf (" %g", op->value->v.vector_val[1]); - printf (" %g'", op->value->v.vector_val[2]); - break; - case ev_quaternion: - printf ("'%g", op->value->v.quaternion_val[0]); - printf (" %g", op->value->v.quaternion_val[1]); - printf (" %g", op->value->v.quaternion_val[2]); - printf (" %g'", op->value->v.quaternion_val[3]); - break; - case ev_ptr: - printf ("(%s)[%d]", - pr_type_name[op->value->v.pointer.type->type], - op->value->v.pointer.val); - break; - case ev_field: - printf ("%d", op->value->v.pointer.val); - break; - case ev_entity: - case ev_func: - case ev_int: - printf ("%d", op->value->v.int_val); - break; - case ev_uint: - printf ("%u", op->value->v.uint_val); - break; - case ev_long: - printf ("%"PRIu64, op->value->v.long_val); - break; - case ev_ulong: - printf ("%"PRIu64, op->value->v.ulong_val); - break; - case ev_short: - printf ("%d", op->value->v.short_val); - break; - case ev_ushort: - printf ("%d", op->value->v.ushort_val); - break; - case ev_void: - case ev_invalid: - case ev_type_count: - internal_error (op->expr, "weird value type"); - } + printf ("(%s) %s", pr_type_name[op->type->type], + get_value_string (op->value)); break; case op_label: printf ("block %p", op->label->dest); diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index a88af6ea3..d86b21cbc 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -45,6 +45,8 @@ #include "QF/mathlib.h" #include "QF/va.h" +#include "QF/simd/types.h" + #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/def.h" #include "tools/qfcc/include/defspace.h" @@ -308,6 +310,155 @@ value_store (pr_type_t *dst, const type_t *dstType, const expr_t *src) memcpy (dst, &val->v, dstSize); } +const char * +get_value_string (const ex_value_t *value) +{ + const type_t *type = value->type; + const char *str = ""; + switch (type->type) { + case ev_string: + return va (0, "\"%s\"", quote_string (value->v.string_val)); + case ev_vector: + case ev_quaternion: + case ev_float: + switch (type_width (type)) { + case 1: + str = va (0, "%.9g", value->v.float_val); + break; + case 2: + str = va (0, VEC2F_FMT, VEC2_EXP (value->v.vec2_val)); + break; + case 3: + str = va (0, "[%.9g, %.9g, %.9g]", + VectorExpand (value->v.vec3_val)); + break; + case 4: + str = va (0, VEC4F_FMT, VEC4_EXP (value->v.vec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_entity: + case ev_func: + return va (0, "%s %d", type->name, value->v.int_val); + case ev_field: + if (value->v.pointer.def) { + int offset = value->v.pointer.val; + offset += value->v.pointer.def->offset; + return va (0, "field %d", offset); + } else { + return va (0, "field %d", value->v.pointer.val); + } + case ev_ptr: + if (value->v.pointer.def) { + str = va (0, "<%s>", value->v.pointer.def->name); + } + return va (0, "(* %s)[%d]%s", + value->v.pointer.type + ? get_type_string (value->v.pointer.type) : "???", + value->v.pointer.val, str); + case ev_int: + switch (type_width (type)) { + case 1: + str = va (0, "%"PRIi32, value->v.int_val); + break; + case 2: + str = va (0, VEC2I_FMT, VEC2_EXP (value->v.ivec2_val)); + break; + case 3: + str = va (0, "[%"PRIi32", %"PRIi32", %"PRIi32"]", + VectorExpand (value->v.ivec3_val)); + break; + case 4: + str = va (0, VEC4I_FMT, VEC4_EXP (value->v.ivec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_uint: + switch (type_width (type)) { + case 1: + str = va (0, "%"PRIu32, value->v.uint_val); + break; + case 2: + str = va (0, "[%"PRIu32", %"PRIi32"]", + VEC2_EXP (value->v.uivec2_val)); + break; + case 3: + str = va (0, "[%"PRIu32", %"PRIi32", %"PRIi32"]", + VectorExpand (value->v.uivec3_val)); + break; + case 4: + str = va (0, "[%"PRIu32", %"PRIi32", %"PRIi32", %"PRIi32"]", + VEC4_EXP (value->v.uivec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_short: + return va (0, "%s %"PRIi16, type->name, value->v.short_val); + case ev_ushort: + return va (0, "%s %"PRIu16, type->name, value->v.ushort_val); + case ev_double: + switch (type_width (type)) { + case 1: + str = va (0, "%.17g", value->v.double_val); + break; + case 2: + str = va (0, VEC2D_FMT, VEC2_EXP (value->v.dvec2_val)); + break; + case 3: + str = va (0, "[%.17g, %.17g, %.17g]", + VectorExpand (value->v.dvec3_val)); + break; + case 4: + str = va (0, VEC4D_FMT, VEC4_EXP (value->v.dvec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_long: + switch (type_width (type)) { + case 1: + str = va (0, "%"PRIi64, value->v.long_val); + break; + case 2: + str = va (0, VEC2L_FMT, VEC2_EXP (value->v.lvec2_val)); + break; + case 3: + str = va (0, "[%"PRIi64", %"PRIi64", %"PRIi64"]", + VectorExpand (value->v.lvec3_val)); + break; + case 4: + str = va (0, VEC4L_FMT, VEC4_EXP (value->v.lvec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_ulong: + switch (type_width (type)) { + case 1: + str = va (0, "%"PRIu64, value->v.ulong_val); + break; + case 2: + str = va (0, "[%"PRIu64", %"PRIi64"]", + VEC2_EXP (value->v.ulvec2_val)); + break; + case 3: + str = va (0, "[%"PRIu64", %"PRIi64", %"PRIi64"]", + VectorExpand (value->v.ulvec3_val)); + break; + case 4: + str = va (0, "[%"PRIu64", %"PRIi64", %"PRIi64", %"PRIi64"]", + VEC4_EXP (value->v.ulvec4_val)); + break; + } + return va (0, "%s %s", type->name, str); + case ev_void: + return ""; + case ev_invalid: + return ""; + case ev_type_count: + return ""; + } + return "invalid type"; +} + static hashtab_t *string_imm_defs; static hashtab_t *float_imm_defs; static hashtab_t *vector_imm_defs; From 1da9fff3ae6d70a565d6c0181ed5612b613f6327 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 11:27:27 +0900 Subject: [PATCH 2705/3664] [qfcc] Simplify immediate value emission This gets immediate values working for the new vector types. --- tools/qfcc/source/value.c | 184 +++++++++----------------------------- 1 file changed, 43 insertions(+), 141 deletions(-) diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index d86b21cbc..8661a140b 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -62,16 +62,11 @@ typedef struct { def_t *def; union { - pr_string_t string_val; - float float_val; - float vector_val[3]; - int entity_val; - int field_val; - int func_val; +#define EV_TYPE(type) pr_##type##_t type##_val; +#include "QF/progs/pr_type_names.h" +#define VEC_TYPE(type_name, base_type) pr_##type_name##_t type_name##_val; +#include "tools/qfcc/include/vec_types.h" ex_pointer_t pointer; - float quaternion_val[4]; - int int_val; - double double_val; } i; } immediate_t; @@ -460,15 +455,8 @@ get_value_string (const ex_value_t *value) } static hashtab_t *string_imm_defs; -static hashtab_t *float_imm_defs; -static hashtab_t *vector_imm_defs; -static hashtab_t *entity_imm_defs; -static hashtab_t *field_imm_defs; -static hashtab_t *func_imm_defs; -static hashtab_t *pointer_imm_defs; -static hashtab_t *quaternion_imm_defs; -static hashtab_t *int_imm_defs; -static hashtab_t *double_imm_defs; +static hashtab_t *fldptr_imm_defs; +static hashtab_t *value_imm_defs; static void imm_free (void *_imm, void *unused) @@ -485,27 +473,13 @@ imm_get_hash (const void *_imm, void *_tab) if (tab == &string_imm_defs) { const char *str = pr.strings->strings + imm->i.string_val; return str ? Hash_String (str) : 0; - } else if (tab == &float_imm_defs) { - return imm->i.int_val; - } else if (tab == &vector_imm_defs) { - return Hash_Buffer (&imm->i.vector_val, sizeof (&imm->i.vector_val)); - } else if (tab == &entity_imm_defs) { - return imm->i.int_val; - } else if (tab == &field_imm_defs) { + } else if (tab == &fldptr_imm_defs) { return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer)); - } else if (tab == &func_imm_defs) { - return imm->i.int_val; - } else if (tab == &pointer_imm_defs) { - return Hash_Buffer (&imm->i.pointer, sizeof (&imm->i.pointer)); - } else if (tab == &quaternion_imm_defs) { - return Hash_Buffer (&imm->i.quaternion_val, - sizeof (&imm->i.quaternion_val)); - } else if (tab == &double_imm_defs) { - return Hash_Buffer (&imm->i.double_val, sizeof (&imm->i.double_val)); - } else if (tab == &int_imm_defs) { - return imm->i.int_val; + } else if (tab == &value_imm_defs) { + size_t size = type_size (imm->def->type) * sizeof (pr_type_t); + return Hash_Buffer (&imm->i, size) ^ (uintptr_t) imm->def->type; } else { - internal_error (0, 0); + internal_error (0, "invalid immediate hash table"); } } @@ -520,28 +494,14 @@ imm_compare (const void *_imm1, const void *_imm2, void *_tab) const char *str1 = pr.strings->strings + imm1->i.string_val; const char *str2 = pr.strings->strings + imm2->i.string_val; return (str1 == str2 || (str1 && str2 && !strcmp (str1, str2))); - } else if (tab == &float_imm_defs) { - return imm1->i.float_val == imm2->i.float_val; - } else if (tab == &vector_imm_defs) { - return VectorCompare (imm1->i.vector_val, imm2->i.vector_val); - } else if (tab == &entity_imm_defs) { - return imm1->i.entity_val == imm2->i.entity_val; - } else if (tab == &field_imm_defs) { + } else if (tab == &fldptr_imm_defs) { return !memcmp (&imm1->i.pointer, &imm2->i.pointer, sizeof (imm1->i.pointer)); - } else if (tab == &func_imm_defs) { - return imm1->i.func_val == imm2->i.func_val; - } else if (tab == &pointer_imm_defs) { - return !memcmp (&imm1->i.pointer, &imm2->i.pointer, - sizeof (imm1->i.pointer)); - } else if (tab == &quaternion_imm_defs) { - return QuatCompare (imm1->i.quaternion_val, imm2->i.quaternion_val); - } else if (tab == &double_imm_defs) { - return imm1->i.double_val == imm2->i.double_val; - } else if (tab == &int_imm_defs) { - return imm1->i.int_val == imm2->i.int_val; + } else if (tab == &value_imm_defs) { + size_t size = type_size (imm1->def->type) * sizeof (pr_type_t); + return !memcmp (&imm1->i, &imm2->i, size); } else { - internal_error (0, 0); + internal_error (0, "invalid immediate hash table"); } } @@ -676,7 +636,6 @@ emit_value (ex_value_t *value, def_t *def) hashtab_t *tab = 0; type_t *type; ex_value_t val = *value; - immediate_t *imm, search; if (!string_imm_defs) { clear_immediates (); @@ -686,56 +645,36 @@ emit_value (ex_value_t *value, def_t *def) // val.type = type_nil->type; switch (val.lltype) { case ev_entity: - tab = entity_imm_defs; - type = &type_entity; - break; - case ev_field: - tab = field_imm_defs; - type = &type_field; - break; case ev_func: - tab = func_imm_defs; - type = &type_func; - break; - case ev_ptr: - tab = pointer_imm_defs; - type = &type_ptr; - break; case ev_int: case ev_uint: - if (!def || !is_float(def->type)) { - tab = int_imm_defs; - type = &type_int; - break; - } - val.v.float_val = val.v.int_val; - val.lltype = ev_float; case ev_float: - tab = float_imm_defs; - type = &type_float; + case ev_vector: + case ev_quaternion: + case ev_double: + tab = value_imm_defs; + type = val.type; + break; + case ev_field: + case ev_ptr: + tab = fldptr_imm_defs; + type = ev_types[val.lltype]; break; case ev_string: val.v.int_val = ReuseString (val.v.string_val); tab = string_imm_defs; type = &type_string; break; - case ev_vector: - tab = vector_imm_defs; - type = &type_vector; - break; - case ev_quaternion: - tab = quaternion_imm_defs; - type = &type_quaternion; - break; - case ev_double: - tab = double_imm_defs; - type = &type_double; - break; default: - internal_error (0, 0); + internal_error (0, "unexpected value type: %s", + val.type->type < ev_type_count + ? pr_type_name[val.lltype] + : va (0, "%d", val.lltype)); } + def_t search_def = { .type = type }; + immediate_t search = { .def = &search_def }; memcpy (&search.i, &val.v, sizeof (search.i)); - imm = (immediate_t *) Hash_FindElement (tab, &search); + immediate_t *imm = Hash_FindElement (tab, &search); if (imm && strcmp (imm->def->name, ".zero") == 0) { if (def) { imm = 0; //FIXME do full def aliasing @@ -820,15 +759,8 @@ clear_immediates (void) if (value_table) { Hash_FlushTable (value_table); Hash_FlushTable (string_imm_defs); - Hash_FlushTable (float_imm_defs); - Hash_FlushTable (vector_imm_defs); - Hash_FlushTable (entity_imm_defs); - Hash_FlushTable (field_imm_defs); - Hash_FlushTable (func_imm_defs); - Hash_FlushTable (pointer_imm_defs); - Hash_FlushTable (quaternion_imm_defs); - Hash_FlushTable (int_imm_defs); - Hash_FlushTable (double_imm_defs); + Hash_FlushTable (fldptr_imm_defs); + Hash_FlushTable (value_imm_defs); } else { value_table = Hash_NewTable (16381, 0, 0, 0, 0); Hash_SetHashCompare (value_table, value_get_hash, value_compare); @@ -837,49 +769,19 @@ clear_immediates (void) &string_imm_defs, 0); Hash_SetHashCompare (string_imm_defs, imm_get_hash, imm_compare); - float_imm_defs = Hash_NewTable (16381, 0, imm_free, - &float_imm_defs, 0); - Hash_SetHashCompare (float_imm_defs, imm_get_hash, imm_compare); + fldptr_imm_defs = Hash_NewTable (16381, 0, imm_free, + &fldptr_imm_defs, 0); + Hash_SetHashCompare (fldptr_imm_defs, imm_get_hash, imm_compare); - vector_imm_defs = Hash_NewTable (16381, 0, imm_free, - &vector_imm_defs, 0); - Hash_SetHashCompare (vector_imm_defs, imm_get_hash, imm_compare); - - entity_imm_defs = Hash_NewTable (16381, 0, imm_free, - &entity_imm_defs, 0); - Hash_SetHashCompare (entity_imm_defs, imm_get_hash, imm_compare); - - field_imm_defs = Hash_NewTable (16381, 0, imm_free, - &field_imm_defs, 0); - Hash_SetHashCompare (field_imm_defs, imm_get_hash, imm_compare); - - func_imm_defs = Hash_NewTable (16381, 0, imm_free, - &func_imm_defs, 0); - Hash_SetHashCompare (func_imm_defs, imm_get_hash, imm_compare); - - pointer_imm_defs = Hash_NewTable (16381, 0, imm_free, - &pointer_imm_defs, 0); - Hash_SetHashCompare (pointer_imm_defs, imm_get_hash, imm_compare); - - quaternion_imm_defs = Hash_NewTable (16381, 0, imm_free, - &quaternion_imm_defs, 0); - Hash_SetHashCompare (quaternion_imm_defs, imm_get_hash, imm_compare); - - int_imm_defs = Hash_NewTable (16381, 0, imm_free, - &int_imm_defs, 0); - Hash_SetHashCompare (int_imm_defs, imm_get_hash, imm_compare); - - double_imm_defs = Hash_NewTable (16381, 0, imm_free, - &double_imm_defs, 0); - Hash_SetHashCompare (double_imm_defs, imm_get_hash, imm_compare); + value_imm_defs = Hash_NewTable (16381, 0, imm_free, + &value_imm_defs, 0); + Hash_SetHashCompare (value_imm_defs, imm_get_hash, imm_compare); } def = make_symbol (".zero", &type_zero, 0, sc_extern)->s.def; memset (&zero_val, 0, sizeof (zero_val)); make_def_imm (def, string_imm_defs, &zero_val); - make_def_imm (def, float_imm_defs, &zero_val); - make_def_imm (def, entity_imm_defs, &zero_val); - make_def_imm (def, pointer_imm_defs, &zero_val); - make_def_imm (def, int_imm_defs, &zero_val); + make_def_imm (def, fldptr_imm_defs, &zero_val); + make_def_imm (def, value_imm_defs, &zero_val); } From b480590d909132c63f9eba5504975dcf1b4c70f8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 11:29:14 +0900 Subject: [PATCH 2706/3664] [qfcc] Treat long, ulong and ushort as math types Not so sure about the value of treating ushort (and short) as a math type, but long and ulong are definitely necessary. --- tools/qfcc/source/type.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index f25cb6eba..b6ca7da62 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -1010,6 +1010,8 @@ is_integral (const type_t *type) type = unalias_type (type); if (is_int (type) || is_uint (type) || is_short (type)) return 1; + if (is_long (type) || is_ulong (type) || is_ushort (type)) + return 1; return is_enum (type); } From d06185336fb26da2594064f44716e6014376bd27 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 11:31:45 +0900 Subject: [PATCH 2707/3664] [qfcc] Implement component names for the new vector types And simplify vector and quaternion setup as part of the process. Now appropriate x, y, z and w can be used with the new vector types. --- tools/qfcc/source/expr.c | 8 ++++-- tools/qfcc/source/type.c | 60 +++++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index ca71e4403..66dec9f74 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1330,7 +1330,11 @@ get_struct_field (const type_t *t1, expr_t *e1, expr_t *e2) } field = symtab_lookup (strct, sym->name); if (!field && !is_entity(t1)) { - error (e2, "'%s' has no member named '%s'", t1->name + 4, sym->name); + const char *name = t1->name; + if (!strncmp (name, "tag ", 4)) { + name += 4; + } + error (e2, "'%s' has no member named '%s'", name, sym->name); e1->type = ex_error; } return field; @@ -1391,7 +1395,7 @@ field_expr (expr_t *e1, expr_t *e2) e1 = cast_expr (pointer_type (ivar->type), e1); return unary_expr ('.', e1); } - } else if (is_vector (t1) || is_quaternion (t1) || is_struct (t1)) { + } else if (is_nonscalar (t1) || is_struct (t1)) { symbol_t *field; field = get_struct_field (t1, e1, e2); diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index b6ca7da62..ec52bff4c 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -1301,6 +1301,33 @@ chain_initial_types (void) chain_structural_types (); } +static const char *vector_field_names[] = { "x", "y", "z", "w" }; +//static const char *color_field_names[] = { "r", "g", "b", "a" }; +//static const char *texture_field_names[] = { "s", "t", "p", "q" }; + +static void +build_vector_struct (type_t *type) +{ + ty_meta_e meta = type->meta; + etype_t etype = type->type; + type_t *ele_type = base_type (type); + int width = type_width (type); + + if (!ele_type || width < 2) { + internal_error (0, "%s not a vector type: %p %d", type->name, ele_type, width); + } + + struct_def_t fields[width + 1]; + for (int i = 0; i < width; i++) { + fields[i] = (struct_def_t) { vector_field_names[i], ele_type }; + } + fields[width] = (struct_def_t) {}; + + make_structure (va (0, "@%s", type->name), 's', fields, type); + type->type = etype; + type->meta = meta; +} + void init_types (void) { @@ -1334,17 +1361,6 @@ init_types (void) {"double_val", &type_double}, {0, 0} }; - static struct_def_t vector_struct[] = { - {"x", &type_float}, - {"y", &type_float}, - {"z", &type_float}, - {0, 0} - }; - static struct_def_t quaternion_struct[] = { - {"v", &type_vector}, - {"s", &type_float}, - {0, 0} - }; static struct_def_t type_encoding_struct[] = { {"types", &type_ptr}, {"size", &type_uint}, @@ -1390,9 +1406,7 @@ init_types (void) make_structure ("@zero", 'u', zero_struct, &type_zero); make_structure ("@param", 'u', param_struct, &type_param); - make_structure ("@vector", 's', vector_struct, &type_vector); - type_vector.type = ev_vector; - type_vector.meta = ty_basic; + build_vector_struct (&type_vector); make_structure ("@type_encodings", 's', type_encoding_struct, &type_type_encodings); @@ -1402,24 +1416,20 @@ init_types (void) va_list_struct[1].type = pointer_type (&type_param); make_structure ("@va_list", 's', va_list_struct, &type_va_list); - make_structure ("@quaternion", 's', quaternion_struct, &type_quaternion); - type_quaternion.type = ev_quaternion; - type_quaternion.meta = ty_basic; + build_vector_struct (&type_quaternion); { symbol_t *sym; - sym = new_symbol_type ("x", &type_float); + + sym = new_symbol_type ("v", &type_vector); sym->s.offset = 0; symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("y", &type_float); - sym->s.offset = 1; - symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("z", &type_float); - sym->s.offset = 2; - symtab_addsymbol (type_quaternion.t.symtab, sym); - sym = new_symbol_type ("w", &type_float); + + sym = new_symbol_type ("s", &type_float); sym->s.offset = 3; symtab_addsymbol (type_quaternion.t.symtab, sym); } +#define VEC_TYPE(type_name, base_type) build_vector_struct (&type_##type_name); +#include "tools/qfcc/include/vec_types.h" chain_structural_types (); } From f429777918537edad9f24d219609f79d8a84eb78 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 11:49:45 +0900 Subject: [PATCH 2708/3664] [qfcc] Extend vector literal processing With this, all vector widths and types are supported: 2, 3, 4 and int, uint, long, ulong, float and double, along with support for suffixes to make the type explicit: '1 2'd specifies a dvec2 constant, while '1 2 3'u is a uivec3 constant. Default types are double (dvec2, dvec3, dvec4) for literals with float-type components, and int (ivec2...) for those with integer-type components. --- tools/qfcc/source/qc-lex.l | 207 ++++++++++++++++++++++++++++++++++--- 1 file changed, 194 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index c74dcea4a..5a06a64db 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -80,7 +80,9 @@ int yyget_debug (void) __attribute__((pure)); FILE *yyget_in (void) __attribute__((pure)); FILE *yyget_out (void) __attribute__((pure)); -static int keyword_or_id (char *token); +static int keyword_or_id (const char *token); +static expr_t *parse_float_vector (const char *token, int width); +static expr_t *parse_int_vector (const char *token, int width); extern QC_YYSTYPE qc_yylval; @@ -95,7 +97,12 @@ ID [a-zA-Z_][a-zA-Z_0-9]* FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)? FLOATf {FLOAT}[fF] FLOATd {FLOAT}[dD] +FCOMP {m}?{FLOAT} +FD [fFdD] INT ({D}+|0[xX]{X}+|0[bB]{B}) +ICOMP {m}?{INT} +UL ([uU]?([lL][lL]?)?) +ULFD ({UL}|{FD}) RANGE \.\. ELLIPSIS \.\.\. FRAMEID {ID}(\.{ID})* @@ -122,7 +129,7 @@ STRING \"(\\.|[^"\\])*\" ^{s}*#{s}*pragma{s}+ { BEGIN (PRAGMA); } -{INT}+[uU]?([lL][lL]?)? { +{INT}+{UL}? { const char *c = yytext + yyleng - 1; int i; @@ -187,19 +194,33 @@ STRING \"(\\.|[^"\\])*\" } @ return '@'; -'{s}*{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}*' { - vec3_t v; - sscanf (yytext, "' %f %f %f '", - &v[0], &v[1], &v[2]); - qc_yylval.expr = new_vector_expr (v); +'{s}*{ICOMP}{s}+{ICOMP}{s}*'{ULFD}? { + qc_yylval.expr = parse_int_vector (yytext, 2); return VALUE; } -'{s}*{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}+{m}?{FLOAT}{s}*' { - quat_t q; - sscanf (yytext, "' %f %f %f %f'", - &q[0], &q[1], &q[2], &q[3]); - qc_yylval.expr = new_quaternion_expr (q); +'{s}*{ICOMP}{s}+{ICOMP}{s}+{ICOMP}{s}*'{ULFD}? { + qc_yylval.expr = parse_int_vector (yytext, 3); + return VALUE; + } + +'{s}*{ICOMP}{s}+{ICOMP}{s}+{ICOMP}{s}+{ICOMP}{s}*'{ULFD}? { + qc_yylval.expr = parse_int_vector (yytext, 4); + return VALUE; + } + +'{s}*{FCOMP}{s}+{FCOMP}{s}*'{FD}? { + qc_yylval.expr = parse_float_vector (yytext, 2); + return VALUE; + } + +'{s}*{FCOMP}{s}+{FCOMP}{s}+{FCOMP}{s}*'{FD}? { + qc_yylval.expr = parse_float_vector (yytext, 3); + return VALUE; + } + +'{s}*{FCOMP}{s}+{FCOMP}{s}+{FCOMP}{s}+{FCOMP}{s}*'{FD}? { + qc_yylval.expr = parse_float_vector (yytext, 4); return VALUE; } @@ -453,7 +474,7 @@ process_keyword (keyword_t *keyword, const char *token) } static int -keyword_or_id (char *token) +keyword_or_id (const char *token) { static hashtab_t *keyword_tab; static hashtab_t *qf_keyword_tab; @@ -525,6 +546,166 @@ keyword_or_id (char *token) return NAME; } +static expr_t * +parse_int_vector (const char *token, int width) +{ + char t1 = 0, t2 = 0; + type_t *type = 0; + + union { + pr_long_t l[4]; + pr_type_t t[PR_SIZEOF (dvec4)]; + } long_data = {}; + pr_type_t *data = __builtin_choose_expr ( + sizeof (pr_long_t) == sizeof (long), long_data.t, (void) 0); + + switch (width) { + case 4: + sscanf (token, "' %li %li %li %li '%c%c", + &long_data.l[0], &long_data.l[1], + &long_data.l[2], &long_data.l[3], &t1, &t2); + break; + case 3: + sscanf (token, "' %li %li %li '%c%c", + &long_data.l[0], &long_data.l[1], + &long_data.l[2], &t1, &t2); + break; + case 2: + sscanf (token, "' %li %li '%c%c", + &long_data.l[0], &long_data.l[1], &t1, &t2); + break; + } + t1 = tolower (t1); + t2 = tolower (t2); + switch (t1) { + case 'u': + if (t2 == 'l') { + type = &type_ulong; + } else { + type = &type_uint; + volatile union { + pr_uint_t u[4]; + pr_type_t t[PR_SIZEOF (ivec4)]; + } uint_data = { + .u = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) uint_data.t; + } + break; + case 'l': + type = &type_long; + break; + case 'f': + type = &type_float; + volatile union { + pr_float_t f[4]; + pr_type_t t[PR_SIZEOF (vec4)]; + } float_data = { + .f = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) float_data.t; + break; + case 'd': + type = &type_double; + volatile union { + pr_double_t d[4]; + pr_type_t t[PR_SIZEOF (dvec4)]; + } double_data = { + .d = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) double_data.t; + break; + case 0: + type = &type_int; + volatile union { + pr_int_t i[4]; + pr_type_t t[PR_SIZEOF (ivec4)]; + } int_data = { + .i = { + long_data.l[0], + long_data.l[1], + long_data.l[2], + long_data.l[3], + } + }; + data = (pr_type_t *) int_data.t; + break; + } + type = vector_type (type, width); + expr_t *expr = new_value_expr (new_type_value (type, data)); + expr->implicit = !t1; + return expr; +} + +static expr_t * +parse_float_vector (const char *token, int width) +{ + char t = 0; + type_t *type = 0; + + union { + pr_double_t d[4]; + pr_type_t t[PR_SIZEOF (dvec4)]; + } double_data = {}; + pr_type_t *data = __builtin_choose_expr ( + sizeof (pr_double_t) == sizeof (double), double_data.t, (void) 0); + + switch (width) { + case 4: + sscanf (token, "' %lf %lf %lf %lf '%c", + &double_data.d[0], &double_data.d[1], + &double_data.d[2], &double_data.d[3], &t); + break; + case 3: + sscanf (token, "' %lf %lf %lf '%c", + &double_data.d[0], &double_data.d[1], + &double_data.d[1], &t); + type = (t == 'f' || t == 'F') ? &type_vec3 : &type_dvec3; + break; + case 2: + sscanf (token, "' %lf %lf '%c", + &double_data.d[0], &double_data.d[1], &t); + type = (t == 'f' || t == 'F') ? &type_vec2 : &type_dvec2; + break; + } + if (t == 'f' || t == 'F') { + volatile union { + pr_float_t f[4]; + pr_type_t t[PR_SIZEOF (vec4)]; + } float_data = { + .f = { + double_data.d[0], + double_data.d[1], + double_data.d[2], + double_data.d[3], + } + }; + data = (pr_type_t *) float_data.t; + type = &type_float; + } else { + type = &type_double; + } + type = vector_type (type, width); + expr_t *expr = new_value_expr (new_type_value (type, data)); + expr->implicit = !t; + return expr; +} + #ifdef YY_FLEX_REALLOC_HACK static __attribute__ ((used)) void *(*const yy_flex_realloc_hack)(void *,yy_size_t) = yy_flex_realloc; #else From bf53edf5e39006450e00c62a867c765f98039565 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 15:20:37 +0900 Subject: [PATCH 2709/3664] [qfcc] Use correct vector expression size in test Vector expressions no longer auto-widen due to the new vector types (I might add such later, but for now this lets the tests try to build (minus actual fixes in qfcc)). --- tools/qfcc/test/vecexpr.r | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/test/vecexpr.r b/tools/qfcc/test/vecexpr.r index 0365ed589..e4ca4489b 100644 --- a/tools/qfcc/test/vecexpr.r +++ b/tools/qfcc/test/vecexpr.r @@ -39,8 +39,8 @@ main () printf("t3(5) = %v\n", v); ret |= 1; } - v = [x, y] / 2; - if (v != [2, 2.5]) { + v = [x, y, 0] / 2; + if (v != [2, 2.5, 0]) { printf("v = %v\n", v); ret |= 1; } From 9c8e13aa4c6c310572b01f53b653ea1cbd857551 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 15:27:12 +0900 Subject: [PATCH 2710/3664] [qfcc] Implement automatic casting between same-width vectors This allows all the tests to build and pass. I'll need to add tests to ensure warnings happen when they should and that all vec operations are correct (ouch, that'll be a lot of work), but vectors and quaternions are working again. --- tools/qfcc/source/expr.c | 5 ++- tools/qfcc/source/expr_assign.c | 25 ++++++------ tools/qfcc/source/expr_binary.c | 72 +++++++++++++++++++++++++++++++-- tools/qfcc/source/expr_vector.c | 6 ++- tools/qfcc/source/qc-lex.l | 6 ++- tools/qfcc/source/type.c | 12 +++++- 6 files changed, 102 insertions(+), 24 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 66dec9f74..fe6a10dd3 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2231,8 +2231,9 @@ return_expr (function_t *f, expr_t *e) } if (!type_assignable (ret_type, t)) { if (!options.traditional) - return error (e, "type mismatch for return value of %s", - f->sym->name); + return error (e, "type mismatch for return value of %s: %s -> %s", + f->sym->name, get_type_string (t), + get_type_string (ret_type)); if (options.warnings.traditional) warning (e, "type mismatch for return value of %s", f->sym->name); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 59c69c23a..1bc88faf7 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -173,21 +173,20 @@ check_types_compatible (expr_t *dst, expr_t *src) } if (type_assignable (dst_type, src_type)) { - if (is_scalar (dst_type) && is_scalar (src_type)) { - if (!src->implicit) { - if (is_double (src_type)) { - warning (dst, "assignment of double to %s (use a cast)\n", - dst_type->name); - } - } - // the types are different but cast-compatible - expr_t *new = cast_expr (dst_type, src); - // the cast was a no-op, so the types are compatible at the - // low level (very true for default type <-> enum) - if (new != src) { - return assign_expr (dst, new); + debug (dst, "casting %s to %s", src_type->name, dst_type->name); + if (!src->implicit && !type_promotes (dst_type, src_type)) { + if (is_double (src_type)) { + warning (dst, "assignment of %s to %s (use a cast)\n", + src_type->name, dst_type->name); } } + // the types are different but cast-compatible + expr_t *new = cast_expr (dst_type, src); + // the cast was a no-op, so the types are compatible at the + // low level (very true for default type <-> enum) + if (new != src) { + return assign_expr (dst, new); + } return 0; } // traditional qcc is a little sloppy diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index be4b5970f..454f01fdf 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -642,6 +642,27 @@ static expr_type_t **binary_expr_types[ev_type_count] = { [ev_double] = double_x }; +// supported operators for scalar-vector expressions +static int scalar_vec_ops[] = { '*', '/', '%', MOD, 0 }; +static expr_t * +convert_scalar (expr_t *scalar, int op, expr_t *vec) +{ + int *s_op = scalar_vec_ops; + while (*s_op && *s_op != op) { + s_op++; + } + if (!*s_op) { + return 0; + } + // expand the scalar to a vector of the same width as vec + for (int i = 1; i < type_width (get_type (vec)); i++) { + expr_t *s = copy_expr (scalar); + s->next = scalar; + scalar = s; + } + return new_vector_list (scalar); +} + static expr_t * pointer_arithmetic (int op, expr_t *e1, expr_t *e2) { @@ -1025,12 +1046,55 @@ binary_expr (int op, expr_t *e1, expr_t *e2) return invalid_binary_expr(op, e1, e2); if ((t1->width > 1 || t2->width > 1)) { - if (t1 != t2) { + // vector/quaternion and scalar won't get here as vector and quaternion + // are distict types with type.width == 1, but vector and vec3 WILL get + // here because of vec3 being float{3} + if (type_width (t1) == 1) { + // scalar op vec + if (!(e = convert_scalar (e1, op, e2))) { + return invalid_binary_expr (op, e1, e2); + } + e1 = e; + t1 = get_type (e1); + } + if (type_width (t2) == 1) { + // vec op scalar + if (!(e = convert_scalar (e2, op, e1))) { + return invalid_binary_expr (op, e1, e2); + } + e2 = e; + t2 = get_type (e2); + } + if (type_width (t1) != type_width (t2)) { + // vec op vec of different widths return invalid_binary_expr (op, e1, e2); } - e = new_binary_expr (op, e1, e2); - e->e.expr.type = t1; - return e; + if (t1 != t2) { + if (is_float (base_type (t1)) && is_double (base_type (t2)) + && e2->implicit) { + e2 = cast_expr (t1, e2); + } else if (is_double (base_type (t1)) && is_float (base_type (t2)) + && e1->implicit) { + e1 = cast_expr (t2, e1); + } else if (type_promotes (base_type (t1), base_type (t2))) { + e2 = cast_expr (t1, e2); + } else if (type_promotes (base_type (t2), base_type (t1))) { + e1 = cast_expr (t2, e1); + } else { + debug (e1, "%d %d\n", e1->implicit, e2->implicit); + return invalid_binary_expr (op, e1, e2); + } + } + t1 = get_type (e1); + t2 = get_type (e2); + et1 = low_level_type (t1); + et2 = low_level_type (t2); + // both widths are the same at this point + if (t1->width > 1) { + e = new_binary_expr (op, e1, e2); + e->e.expr.type = t1; + return e; + } } expr_type = binary_expr_types[et1][et2]; diff --git a/tools/qfcc/source/expr_vector.c b/tools/qfcc/source/expr_vector.c index f8e891819..0efc2b063 100644 --- a/tools/qfcc/source/expr_vector.c +++ b/tools/qfcc/source/expr_vector.c @@ -97,12 +97,14 @@ new_vector_list (expr_t *expr_list) } int all_constant = 1; + int all_implicit = 1; expr_t *elements[count + 1]; elements[count] = 0; count = 0; for (expr_t *e = expr_list; e; e = e->next) { int cast_width = type_width (get_type (e)); type_t *cast_type = vector_type (ele_type, cast_width); + all_implicit = all_implicit && e->implicit; elements[count] = cast_expr (cast_type, fold_constants (e)); all_constant = all_constant && is_constant (elements[count]); count++; @@ -153,7 +155,9 @@ new_vector_list (expr_t *expr_list) offs += type_size (src_type); } - return new_value_expr (new_type_value (vec_type, value)); + expr_t *vec = new_value_expr (new_type_value (vec_type, value)); + vec->implicit = all_implicit; + return vec; } for (int i = 0; i < count; i++) { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 5a06a64db..ee63d6791 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -137,10 +137,12 @@ STRING \"(\\.|[^"\\])*\" i = strtol (yytext + 2, 0, 2); else i = strtol (yytext, 0, 0); - if (*c == 'u' || *c == 'U') + if (*c == 'u' || *c == 'U') { qc_yylval.expr = new_int_expr (i);//FIXME - else + } else { qc_yylval.expr = new_int_expr (i); + qc_yylval.expr->implicit = 1; + } return VALUE; } diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index ec52bff4c..567823a4a 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -1124,8 +1124,16 @@ type_assignable (const type_t *dst, const type_t *src) return 1; return 0; } - if (!is_ptr (dst) || !is_ptr (src)) - return is_scalar (dst) && is_scalar (src); + if (!is_ptr (dst) || !is_ptr (src)) { + if (is_scalar (dst) && is_scalar (src)) { + return 1; + } + if (is_nonscalar (dst) && is_nonscalar (src) + && type_width (dst) == type_width (src)) { + return 1; + } + return 0; + } // pointer = pointer // give the object system first shot because the pointee types might have From 9cccb7a4d42138fc44e03426c28629b72a6bdfff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 15:38:55 +0900 Subject: [PATCH 2711/3664] [qfcc] Implement ulong, long and uint constants Finally :P --- tools/qfcc/include/expr.h | 3 +++ tools/qfcc/include/value.h | 2 ++ tools/qfcc/source/expr.c | 12 ++++++++++++ tools/qfcc/source/qc-lex.l | 18 +++++++++++++----- tools/qfcc/source/qc-parse.y | 10 ++++++---- tools/qfcc/source/value.c | 16 ++++++++++++++++ 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5635141f2..0f460445d 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -633,6 +633,9 @@ int expr_int (expr_t *e) __attribute__((pure)); expr_t *new_uint_expr (unsigned uint_val); unsigned expr_uint (expr_t *e) __attribute__((pure)); +expr_t *new_long_expr (pr_long_t long_val); +expr_t *new_ulong_expr (pr_ulong_t ulong_val); + /** Create a new short constant expression node. \param short_val The short constant being represented. diff --git a/tools/qfcc/include/value.h b/tools/qfcc/include/value.h index 197c31514..e8eb5a3a7 100644 --- a/tools/qfcc/include/value.h +++ b/tools/qfcc/include/value.h @@ -56,6 +56,8 @@ struct ex_value_s *new_pointer_val (int val, struct type_s *type, struct ex_value_s *new_quaternion_val (const float *quaternion_val); struct ex_value_s *new_int_val (int int_val); struct ex_value_s *new_uint_val (int uint_val); +struct ex_value_s *new_long_val (pr_long_t long_val); +struct ex_value_s *new_ulong_val (pr_ulong_t ulong_val); struct ex_value_s *new_short_val (short short_val); struct ex_value_s *new_nil_val (struct type_s *type); struct ex_value_s *new_type_value (const struct type_s *type, diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index fe6a10dd3..daea88014 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -752,6 +752,18 @@ new_uint_expr (unsigned uint_val) return new_value_expr (new_uint_val (uint_val)); } +expr_t * +new_long_expr (pr_long_t long_val) +{ + return new_value_expr (new_long_val (long_val)); +} + +expr_t * +new_ulong_expr (pr_ulong_t ulong_val) +{ + return new_value_expr (new_ulong_val (ulong_val)); +} + expr_t * new_short_expr (short short_val) { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index ee63d6791..495d69aa9 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -131,17 +131,25 @@ STRING \"(\\.|[^"\\])*\" {INT}+{UL}? { const char *c = yytext + yyleng - 1; - int i; + pr_long_t i; if (yytext[0] == '0' && tolower (yytext[1] == 'b')) i = strtol (yytext + 2, 0, 2); else i = strtol (yytext, 0, 0); - if (*c == 'u' || *c == 'U') { - qc_yylval.expr = new_int_expr (i);//FIXME + if (tolower (*c) == 'u') { + if (tolower (c[1]) == 'l') { + qc_yylval.expr = new_ulong_expr (i); + } else { + qc_yylval.expr = new_uint_expr (i); + } } else { - qc_yylval.expr = new_int_expr (i); - qc_yylval.expr->implicit = 1; + if (tolower (c[1]) == 'l') { + qc_yylval.expr = new_long_expr (i); + } else { + qc_yylval.expr = new_int_expr (i); + qc_yylval.expr->implicit = 1; + } } return VALUE; } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 29029e543..5355a7981 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -94,7 +94,7 @@ int yylex (void); %union { int op; - int size; + unsigned size; specifier_t spec; void *pointer; // for ensuring pointer values are null struct type_s *type; @@ -1131,11 +1131,13 @@ abs_decl array_decl : '[' expr ']' { - if (!is_int_val ($2) || expr_int ($2) < 1) { + if (is_int_val ($2) && expr_int ($2) > 0) { + $$ = expr_int ($2); + } else if (is_uint_val ($2) && expr_uint ($2) > 0) { + $$ = expr_uint ($2); + } else { error (0, "invalid array size"); $$ = 0; - } else { - $$ = expr_int ($2); } } | '[' ']' { $$ = 0; } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 8661a140b..bd8ac599e 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -240,6 +240,22 @@ new_uint_val (int uint_val) return find_value (&val); } +ex_value_t * +new_long_val (pr_long_t long_val) +{ + ex_value_t val = { .v = { .long_val = long_val } }; + set_val_type (&val, &type_long); + return find_value (&val); +} + +ex_value_t * +new_ulong_val (pr_ulong_t ulong_val) +{ + ex_value_t val = { .v = { .ulong_val = ulong_val } }; + set_val_type (&val, &type_ulong); + return find_value (&val); +} + ex_value_t * new_short_val (short short_val) { From 547cae03ae4344864e12e786b497261677e01faa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 19:18:21 +0900 Subject: [PATCH 2712/3664] [qfcc] Copy parameter types when registering new function type This fixes an error that's been lurking for over two years (since I made parameters unlimited internally). The problem was the array was being allocated on the stack and a simple struct copy was used to store type type, resulting in a dangling pointer onto the stack. I'm surprised it didn't cause more problems. --- tools/qfcc/source/type.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 567823a4a..bd5d93e62 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -495,6 +495,20 @@ find_type (type_t *type) // allocate a new one check = new_type (); *check = *type; + if (is_func (type)) { + check->t.func.param_types = 0; + const type_t *t = unalias_type (type); + int num_params = t->t.func.num_params; + if (num_params < 0) { + num_params = ~num_params; + } + if (num_params) { + check->t.func.param_types = malloc (sizeof (type_t *) * num_params); + for (int i = 0; i < num_params; i++) { + check->t.func.param_types[i] = t->t.func.param_types[i]; + } + } + } check->freeable = 0; chain_type (check); From 719fe5a935972137f91664a170c2182f7b9ef376 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 20:46:33 +0900 Subject: [PATCH 2713/3664] [qfcc] Support dot product for all (float) vector types While the code would handle int vector types, there aren't any such instructions, and the expression code shouldn't generate them, but all float (32 and 64 bit) vector types do have a dot product instruction, so check width rather than just vector/quaternion. --- tools/qfcc/source/statements.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 076ef04d5..7d15854f6 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -149,7 +149,7 @@ _print_operand (operand_t *op) { switch (op->op_type) { case op_def: - printf ("(%s) ", pr_type_name[op->type->type]); + printf ("(%s) ", get_type_string (op->type)); printf ("%s", op->def->name); break; case op_value: @@ -160,12 +160,12 @@ _print_operand (operand_t *op) printf ("block %p", op->label->dest); break; case op_temp: - printf ("tmp (%s) %p", pr_type_name[op->type->type], op); + printf ("tmp (%s) %p", get_type_string (op->type), op); if (op->tempop.def) printf (" %s", op->tempop.def->name); break; case op_alias: - printf ("alias(%s,", pr_type_name[op->type->type]); + printf ("alias(%s,", get_type_string (op->type)); _print_operand (op->alias); printf (")"); break; @@ -1633,10 +1633,13 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) opcode = "cmp"; } if (strcmp (opcode, "dot") == 0) { - if (is_vector (get_type (e->e.expr.e1))) { + if (type_width (get_type (e->e.expr.e1)) == 2) { + opcode = "cdot"; + } + if (type_width (get_type (e->e.expr.e1)) == 3) { opcode = "vdot"; } - if (is_quaternion (get_type (e->e.expr.e1))) { + if (type_width (get_type (e->e.expr.e1)) == 4) { opcode = "qdot"; } } From 69ce0e952d2856742b893499367ed162342ac2f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 20:49:18 +0900 Subject: [PATCH 2714/3664] [qfcc] Don't auto-promote vector types through ... Currently, only vector/vec3 and quaternion/vec4 can be printed anyway, but I plan on making explicit format strings for the types, so there should be no need to promote any vector types (and really, any hidden promotion is a bit of a pain, but standards...). --- tools/qfcc/source/expr.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index daea88014..a0037c42a 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -223,16 +223,8 @@ type_mismatch (expr_t *e1, expr_t *e2, int op) expr_t * param_mismatch (expr_t *e, int param, const char *fn, type_t *t1, type_t *t2) { - dstring_t *s1 = dstring_newstr (); - dstring_t *s2 = dstring_newstr (); - - print_type_str (s1, t1); - print_type_str (s2, t2); - e = error (e, "type mismatch for parameter %d of %s: expected %s, got %s", - param, fn, s1->str, s2->str); - dstring_delete (s1); - dstring_delete (s2); + param, fn, get_type_string (t1), get_type_string (t2)); return e; } @@ -2011,11 +2003,11 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) && options.code.progsversion == PROG_ID_VERSION) e = cast_expr (&type_float, e); if (options.code.promote_float) { - if (is_float (get_type (e))) { + if (is_scalar (get_type (e)) && is_float (get_type (e))) { t = &type_double; } } else { - if (is_double (get_type (e))) { + if (is_scalar (get_type (e)) && is_double (get_type (e))) { if (!e->implicit) { warning (e, "passing double into ... function"); } From 8021848b5b6f25f6c10244c1c719632f48a2a45a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 20:52:57 +0900 Subject: [PATCH 2715/3664] [qfcc] Support promotions for struct initializers This allows the various vector types to be used to initialized structures and arrays. --- tools/qfcc/source/def.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 9d9f04d84..8e009cb85 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -380,10 +380,17 @@ init_elements (struct def_s *def, expr_t *eles) reloc_def_op (c->e.labelref.label, &dummy); continue; } else if (c->type == ex_value) { - if (is_float (element->type) - && (is_int (get_type (c)) - || (is_double (get_type (c)) && c->implicit))) { - expr_t *n = cast_expr (&type_float, c); + type_t *ctype = get_type (c); + if (ctype != element->type + && type_assignable (element->type, ctype)) { + if (!c->implicit + && !type_promotes (element->type, ctype)) { + warning (c, "initialization of %s with %s" + " (use a cast)\n)", + get_type_string (element->type), + get_type_string (ctype)); + } + expr_t *n = cast_expr (element->type, c); n->line = c->line; n->file = c->line; c = n; From 709a0a338dfaad8febf5a38e018567df6b38ccba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 29 Apr 2022 20:53:59 +0900 Subject: [PATCH 2716/3664] [qfcc] Return properly from copying a block expression This came up when investigating an internal error from the line above. It turned out the error was correct (problem with converting scalars to vectors), but the break was not. --- tools/qfcc/source/expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index a0037c42a..db2305e83 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -322,7 +322,7 @@ copy_expr (expr_t *e) } if (e->e.block.result && !n->e.block.result) internal_error (e, "bogus block result?"); - break; + return n; case ex_expr: n = new_expr (); *n = *e; From 4ed9fc6820691603f4c642cc078472bd8406e802 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Apr 2022 17:40:06 +0900 Subject: [PATCH 2717/3664] [ruamoko] Switch to 64-bit handles for scene objects The scene id is in the lower 32-bits for all objects (upper 32-bits are 0 for actual scene objects) and entity/transform ids are in the upper 32-bits. Saves having to pass around a second parameter in progs code. --- libs/ruamoko/rua_scene.c | 223 ++++++++++++++++++++------------------- 1 file changed, 113 insertions(+), 110 deletions(-) diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 11aee7eb7..d43a4da7b 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -76,9 +76,13 @@ rua_scene_free (rua_scene_resources_t *res, rua_scene_t *scene) } static rua_scene_t * __attribute__((pure)) -rua__scene_get (rua_scene_resources_t *res, int id, const char *name) +rua__scene_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { - rua_scene_t *scene = PR_RESGET (res->scene_map, id); + rua_scene_t *scene = 0; + + if (id <= 0xffffffffu) { + scene = PR_RESGET (res->scene_map, (pr_int_t) id); + } // scene->prev will be null if the handle is unallocated if (!scene || !scene->prev) { @@ -89,29 +93,42 @@ rua__scene_get (rua_scene_resources_t *res, int id, const char *name) #define rua_scene_get(res, id) rua__scene_get(res, id, __FUNCTION__) static entity_t * __attribute__((pure)) -rua__entity_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) +rua__entity_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { - entity_t *ent = Scene_GetEntity (scene->scene, id); + pr_ulong_t scene_id = id & 0xffffffff; + entity_t *ent = 0; + + rua_scene_t *scene = rua__scene_get (res, scene_id, name); + if (scene) { + pr_int_t entity_id = id >> 32; + ent = Scene_GetEntity (scene->scene, entity_id); + } if (!ent) { - PR_RunError (pr, "invalid entity passed to %s", name + 3); + PR_RunError (res->pr, "invalid entity passed to %s", name + 3); } return ent; } -#define rua_entity_get(pr, scene, id) rua__entity_get(pr, scene, id, __FUNCTION__) +#define rua_entity_get(res, id) rua__entity_get(res, id, __FUNCTION__) static transform_t * __attribute__((pure)) -rua__transform_get (progs_t *pr, rua_scene_t *scene, int id, const char *name) +rua__transform_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { - transform_t *transform = Scene_GetTransform (scene->scene, id); + pr_ulong_t scene_id = id & 0xffffffff; + transform_t *transform = 0; + + rua_scene_t *scene = rua_scene_get (res, scene_id); + if (scene) { + pr_int_t transform_id = id >> 32; + transform = Scene_GetTransform (scene->scene, transform_id); + } if (!transform) { - PR_RunError (pr, "invalid transform passed to %s", name + 3); + PR_RunError (res->pr, "invalid transform passed to %s", name + 3); } return transform; } -#define rua_transform_get(pr, scene, id) \ - rua__transform_get(pr, scene, id, __FUNCTION__) +#define rua_transform_get(res, id) rua__transform_get(res, id, __FUNCTION__) static int __attribute__((pure)) rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene) @@ -119,6 +136,9 @@ rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene) return PR_RESINDEX (res->scene_map, scene); } +#define MAKE_ID(id, sc_id) ((((pr_ulong_t) (id)) << 32) \ + | ((sc_id) & 0xffffffff)) + static void bi_Scene_NewScene (progs_t *pr, void *_res) { @@ -135,7 +155,9 @@ bi_Scene_NewScene (progs_t *pr, void *_res) scene->prev = &res->scenes; res->scenes = scene; - R_INT (pr) = rua_scene_index (res, scene); + // scene id in lower 32-bits for all handles + // zero upper 32-bits zero means scene, otherwise transform or entity + R_ULONG (pr) = MAKE_ID (0, rua_scene_index (res, scene)); } static void @@ -149,7 +171,7 @@ static void bi_Scene_DeleteScene (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + rua_scene_t *scene = rua_scene_get (res, P_ULONG (pr, 0)); rua_delete_scene (res, scene); } @@ -158,17 +180,21 @@ static void bi_Scene_CreateEntity (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); + pr_ulong_t scene_id = P_ULONG (pr, 0); + rua_scene_t *scene = rua_scene_get (res, scene_id); entity_t *ent = Scene_CreateEntity (scene->scene); - R_INT (pr) = ent->id; + R_ULONG (pr) = MAKE_ID (ent->id, scene_id); } static void bi_Scene_DestroyEntity (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - entity_t *ent = rua_entity_get (pr, scene, P_INT (pr, 1)); + pr_ulong_t id = P_ULONG (pr, 0); + entity_t *ent = rua_entity_get (res, id); + pr_ulong_t scene_id = id & 0xffffffff; + // bad scene caught above + rua_scene_t *scene = rua_scene_get (res, scene_id); Scene_DestroyEntity (scene->scene, ent); } @@ -176,18 +202,18 @@ static void bi_Entity_GetTransform (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - entity_t *ent = rua_entity_get (pr, scene, P_INT (pr, 1)); + pr_ulong_t ent_id = P_ULONG (pr, 0); + entity_t *ent = rua_entity_get (res, ent_id); - R_INT (pr) = ent->transform->id; + // ent_id contains scene id + R_ULONG (pr) = MAKE_ID (ent->transform->id, ent_id); } static void bi_Transform_ChildCount (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_UINT (pr) = Transform_ChildCount (transform); } @@ -196,8 +222,7 @@ static void bi_Transform_GetChild (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); transform_t *child = Transform_GetChild (transform, P_UINT (pr, 2)); R_UINT (pr) = child ? child->id : 0; @@ -207,9 +232,8 @@ static void bi_Transform_SetParent (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - transform_t *parent = rua_transform_get (pr, scene, P_INT (pr, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t *parent = rua_transform_get (res, P_ULONG (pr, 1)); Transform_SetParent (transform, parent); } @@ -218,19 +242,19 @@ static void bi_Transform_GetParent (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + pr_ulong_t transform_id = P_ULONG (pr, 0); + transform_t *transform = rua_transform_get (res, transform_id); transform_t *parent = Transform_GetParent (transform); - R_INT (pr) = parent ? parent->id : 0; + // transform_id contains scene id + R_ULONG (pr) = parent ? MAKE_ID (parent->id, transform_id) : 0; } static void bi_Transform_SetTag (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); pr_uint_t tag = P_UINT (pr, 2); Transform_SetTag (transform, tag); } @@ -239,8 +263,7 @@ static void bi_Transform_GetTag (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_UINT (pr) = Transform_GetTag (transform); } @@ -249,8 +272,7 @@ static void bi_Transform_GetLocalMatrix (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetLocalMatrix (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -258,8 +280,7 @@ static void bi_Transform_GetLocalInverse (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetLocalInverse (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -267,8 +288,7 @@ static void bi_Transform_GetWorldMatrix (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetWorldMatrix (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -276,8 +296,7 @@ static void bi_Transform_GetWorldInverse (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetWorldInverse (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -285,17 +304,15 @@ static void bi_Transform_SetLocalPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetLocalPosition (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetLocalPosition (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetLocalPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalPosition (transform); } @@ -303,17 +320,15 @@ static void bi_Transform_SetLocalRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetLocalRotation (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetLocalRotation (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetLocalRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalRotation (transform); } @@ -321,17 +336,15 @@ static void bi_Transform_SetLocalScale (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetLocalScale (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetLocalScale (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetLocalScale (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalScale (transform); } @@ -339,17 +352,15 @@ static void bi_Transform_SetWorldPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetWorldPosition (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetWorldPosition (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetWorldPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldPosition (transform); } @@ -357,17 +368,15 @@ static void bi_Transform_SetWorldRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetWorldRotation (transform, P_PACKED (pr, pr_vec4_t, 2)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetWorldRotation (transform, P_PACKED (pr, pr_vec4_t, 1)); } static void bi_Transform_GetWorldRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldRotation (transform); } @@ -375,8 +384,7 @@ static void bi_Transform_GetWorldScale (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldScale (transform); } @@ -384,18 +392,16 @@ static void bi_Transform_SetLocalTransform (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); - Transform_SetLocalTransform (transform, P_PACKED (pr, pr_vec4_t, 2), - P_PACKED (pr, pr_vec4_t, 3), P_PACKED (pr, pr_vec4_t, 4)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + Transform_SetLocalTransform (transform, P_PACKED (pr, pr_vec4_t, 1), + P_PACKED (pr, pr_vec4_t, 2), P_PACKED (pr, pr_vec4_t, 3)); } static void bi_Transform_Forward (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_Forward (transform); } @@ -403,8 +409,7 @@ static void bi_Transform_Right (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_Right (transform); } @@ -412,8 +417,7 @@ static void bi_Transform_Up (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - rua_scene_t *scene = rua_scene_get (res, P_INT (pr, 0)); - transform_t *transform = rua_transform_get (pr, scene, P_INT (pr, 1)); + transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_Up (transform); } @@ -421,44 +425,43 @@ bi_Transform_Up (progs_t *pr, void *_res) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} static builtin_t builtins[] = { - bi(Scene_NewScene, 0), - bi(Scene_DeleteScene, 1, p(ptr)), - bi(Scene_CreateEntity, 1, p(ptr)), - bi(Scene_DestroyEntity, 2, p(ptr), p(ptr)), + bi(Scene_NewScene, 0), + bi(Scene_DeleteScene, 1, p(ulong)), + bi(Scene_CreateEntity, 1, p(ulong)), + bi(Scene_DestroyEntity, 1, p(ulong)), - bi(Entity_GetTransform, 2, p(ptr), p(ptr)), + bi(Entity_GetTransform, 1, p(ulong)), - bi(Transform_ChildCount, 2, p(ptr), p(ptr)), - bi(Transform_GetChild, 3, p(ptr), p(ptr), p(int)), - bi(Transform_SetParent, 3, p(ptr), p(ptr), p(ptr)), - bi(Transform_GetParent, 2, p(ptr), p(ptr)), + bi(Transform_ChildCount, 1, p(ulong)), + bi(Transform_GetChild, 2, p(ulong), p(int)), + bi(Transform_SetParent, 2, p(ulong), p(ulong)), + bi(Transform_GetParent, 1, p(ulong)), - bi(Transform_SetTag, 3, p(ptr), p(ptr), p(uint)), - bi(Transform_GetTag, 2, p(ptr), p(ptr)), + bi(Transform_SetTag, 2, p(ulong), p(uint)), + bi(Transform_GetTag, 1, p(ulong)), - bi(Transform_GetLocalMatrix, 2, p(ptr), p(ptr)), - bi(Transform_GetLocalInverse, 2, p(ptr), p(ptr)), - bi(Transform_GetWorldMatrix, 2, p(ptr), p(ptr)), - bi(Transform_GetWorldInverse, 2, p(ptr), p(ptr)), + bi(Transform_GetLocalMatrix, 1, p(ulong)), + bi(Transform_GetLocalInverse, 1, p(ulong)), + bi(Transform_GetWorldMatrix, 1, p(ulong)), + bi(Transform_GetWorldInverse, 1, p(ulong)), - bi(Transform_SetLocalPosition, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetLocalPosition, 2, p(ptr), p(ptr)), - bi(Transform_SetLocalRotation, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetLocalRotation, 2, p(ptr), p(ptr)), - bi(Transform_SetLocalScale, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetLocalScale, 2, p(ptr), p(ptr)), + bi(Transform_SetLocalPosition, 2, p(ulong), p(vec4)), + bi(Transform_GetLocalPosition, 1, p(ulong)), + bi(Transform_SetLocalRotation, 2, p(ulong), p(vec4)), + bi(Transform_GetLocalRotation, 1, p(ulong)), + bi(Transform_SetLocalScale, 2, p(ulong), p(vec4)), + bi(Transform_GetLocalScale, 1, p(ulong)), - bi(Transform_SetWorldPosition, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetWorldPosition, 2, p(ptr), p(ptr)), - bi(Transform_SetWorldRotation, 3, p(ptr), p(ptr), p(vec4)), - bi(Transform_GetWorldRotation, 2, p(ptr), p(ptr)), - bi(Transform_GetWorldScale, 2, p(ptr), p(ptr)), + bi(Transform_SetWorldPosition, 2, p(ulong), p(vec4)), + bi(Transform_GetWorldPosition, 1, p(ulong)), + bi(Transform_SetWorldRotation, 2, p(ulong), p(vec4)), + bi(Transform_GetWorldRotation, 1, p(ulong)), + bi(Transform_GetWorldScale, 1, p(ulong)), - bi(Transform_SetLocalTransform, 5, p(ptr), p(ptr), - p(vec4), p(vec4), p(vec4)), - bi(Transform_Forward, 2, p(ptr), p(ptr)), - bi(Transform_Right, 2, p(ptr), p(ptr)), - bi(Transform_Up, 2, p(ptr), p(ptr)), + bi(Transform_SetLocalTransform, 4, p(ulong), p(vec4), p(vec4), p(vec4)), + bi(Transform_Forward, 1, p(ulong)), + bi(Transform_Right, 1, p(ulong)), + bi(Transform_Up, 1, p(ulong)), {0} }; From b87a768c43a822f68ccd38778130ceb3a4d99fb9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 30 Apr 2022 10:06:01 +0900 Subject: [PATCH 2718/3664] [gamecode] Sort debug local defs by address This allows the fuzzy bsearch used to find a def by address to work properly (ie, find the actual def instead of giving some other def + offset). Makes for a much more readable instruction stream. --- libs/gamecode/pr_debug.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 01d9f6ebe..09fec6c90 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -31,8 +31,6 @@ # include "config.h" #endif -#define _GNU_SOURCE // for qsort_r - #ifdef HAVE_STRING_H # include #endif @@ -48,6 +46,7 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/heapsort.h" #include "QF/mathlib.h" #include "QF/progs.h" #include "QF/qendian.h" @@ -478,6 +477,14 @@ process_compunit (prdeb_resources_t *res, pr_def_t *def) } } +static int +def_compare_sort (const void *_da, const void *_db, void *_res) +{ + pr_def_t da = *(const pr_def_t *)_da; + pr_def_t db = *(const pr_def_t *)_db; + return da.ofs - db.ofs; +} + static int func_compare_sort (const void *_fa, const void *_fb, void *_res) { @@ -552,9 +559,12 @@ PR_DebugSetSym (progs_t *pr, pr_debug_header_t *debug) } res->auxfunction_map[res->auxfunctions[i].function] = &res->auxfunctions[i]; + heapsort_r (res->local_defs + res->auxfunctions[i].local_defs, + res->auxfunctions[i].num_locals, sizeof (pr_def_t), + def_compare_sort, res); } - qsort_r (res->sorted_functions, pr->progs->functions.count, - sizeof (pr_func_t), func_compare_sort, res); + heapsort_r (res->sorted_functions, pr->progs->functions.count, + sizeof (pr_func_t), func_compare_sort, res); for (pr_uint_t i = 0; i < debug->num_locals; i++) { if (type_encodings) { From 3c20dd515e74e936d3c11db62dee177e01f4f75e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 30 Apr 2022 21:58:41 +0900 Subject: [PATCH 2719/3664] Revert "Don't bother creating an alias for a def of the same type." This reverts commit 2904c619c1b883a29c2b7ea29210b44ee8f298f0. In order to support swizzle operations, I need to be able to alias defs to larger types (eg, float to vec4), but alias_def rightly won't allow this. However, as the plan is to do this in the final steps before emitting the instruction, I plan on creating an alias to a float then adjusting the type in the alias, but to do so without extra shenanigans, I need alias_def to allow aliases to the same type. As a fringe benefit, it makes the code agree with the comment in def.h :P --- tools/qfcc/source/def.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 8e009cb85..bab482a9f 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -180,8 +180,6 @@ alias_def (def_t *def, type_t *type, int offset) internal_error (0, "aliasing a def to a larger type"); if (offset < 0 || offset + type_size (type) > type_size (def->type)) internal_error (0, "invalid alias offset"); - if (type == def->type) - return def; for (alias = def->alias_defs; alias; alias = alias->next) { if (alias->type == type && alias->offset == offset) return alias; From ef9960c6f905f65400a75160cfec00620212e08f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 May 2022 10:02:26 +0900 Subject: [PATCH 2720/3664] [qfcc] Implement support for the swizzle operator The destination operand must be a full four component vector, but the source can be smaller and small sources do not need to be aligned: the offset of the source operand and the swizzle indices are adjusted. The adjustments are done during final statement emission in order to avoid confusing the data flow analyser (and that's when def offsets are known). --- tools/qfcc/include/expr.h | 14 ++++++ tools/qfcc/include/expr_names.h | 1 + tools/qfcc/include/type.h | 30 ++++++++++++ tools/qfcc/source/dot_expr.c | 37 +++++++++++++++ tools/qfcc/source/emit.c | 84 +++++++++++++++++++++++++++++++++ tools/qfcc/source/expr.c | 80 +++++++++++++++++++++++++++++++ tools/qfcc/source/expr_assign.c | 1 + tools/qfcc/source/expr_binary.c | 25 ++++++++-- tools/qfcc/source/opcodes.c | 22 ++++++++- tools/qfcc/source/statements.c | 27 +++++++++++ tools/qfcc/source/type.c | 32 +++++++++++++ 11 files changed, 347 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 0f460445d..b9534086e 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -258,6 +258,17 @@ typedef struct { struct type_s *type; ///< result type } ex_horizontal_t; +//NOTE always operates on vec4 or dvec4, so needs a suitable destination and +//care must be taken when working with smaller source operands (check aligmnet +//and adjust swizzle operation as needed) +typedef struct { + struct expr_s *src; ///< source expression + unsigned source[4]; ///< src component indices + unsigned neg; ///< bitmask of dst components to negate + unsigned zero; ///< bitmask of dst components to 0 + struct type_s *type; ///< result type +} ex_swizzle_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -293,6 +304,7 @@ typedef struct expr_s { ex_with_t with; ///< with expr param struct type_s *nil; ///< type for nil if known ex_horizontal_t hop; ///< horizontal vector operation + ex_swizzle_t swizzle; ///< vector swizzle operation } e; } expr_t; @@ -480,6 +492,8 @@ expr_t *new_unary_expr (int op, expr_t *e1); */ expr_t *new_horizontal_expr (int op, expr_t *vec, struct type_s *type); +expr_t *new_swizzle_expr (expr_t *src, const char *swizzle); + /** Create a new def reference (non-temporary variable) expression node. \return The new def reference expression node (::def_t). diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index 05d1f197a..8c6db70b6 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -63,5 +63,6 @@ EX_EXPR(adjstk) ///< stack adjust expression (::ex_adjstk_t) EX_EXPR(with) ///< with expression (::ex_with_t) EX_EXPR(args) ///< @args marker in parameter list. no data EX_EXPR(horizontal) ///< horizontal vector operation (::ex_horzontal_t) +EX_EXPR(swizzle) ///< vector swizzle operation (::ex_swizzle_t) ///@} diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 69ca4bc4b..6dde9d55b 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -162,6 +162,36 @@ type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); type_t *vector_type (const type_t *ele_type, int width) __attribute__((pure)); type_t *base_type (const type_t *vec_type) __attribute__((pure)); + +/** Return an integral type of same size as the provided type. + + Any 32-bit type will produce type_int (or one of ivec2, ivec3 or ivec4). + Any 64-bit type will produce type_long (lor one of lvec2, lvec3, or lvec4). + + Both type_width() and type_size() of the returned type will match the + provided type. + + \param base Type on which the return type will be based. + \return Matching integral type (int, long, or a vector form), or + null if no such match can be made. +*/ +type_t *int_type (const type_t *base) __attribute__((pure)); + +/** Return a floating point type of same size as the provided type. + + Any 32-bit type will produce type_float (or one of vec2, vec3 or vec4). + Any 64-bit type will produce type_double (lor one of dvec2, dvec3, or + dvec4). + + Both type_width() and type_size() of the returned type will match the + provided type. + + \param base Type on which the return type will be based. + \return Matching floating point type (float, double, or a vector + form), or null if no such match can be made. +*/ +type_t *float_type (const type_t *base) __attribute__((pure)); + type_t *array_type (type_t *aux, int size); type_t *based_array_type (type_t *aux, int base, int top); type_t *alias_type (type_t *type, type_t *alias_chain, const char *name); diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index fdf8238e0..664796915 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -555,6 +555,41 @@ print_args (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) e->line); } +static void +print_horizontal (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + + _print_expr (dstr, e->e.hop.vec, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, e->e.hop.vec); + dasprintf (dstr, "%*se_%p [label=\"hop %s\\n%d\"];\n", indent, "", e, + get_op_string (e->e.hop.op), e->line); +} + +static void +print_swizzle (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + static char swizzle_components[] = "xyzw"; + int indent = level * 2 + 2; + ex_swizzle_t swiz = e->e.swizzle; + const char *swizzle = ""; + + for (int i = 0; i < 4; i++) { + if (swiz.zero & (1 << i)) { + swizzle = va (0, "%s0", swizzle); + } else { + swizzle = va (0, "%s%s%c", swizzle, + swiz.neg & (1 << i) ? "-" : "", + swizzle_components[swiz.source[i]]); + } + } + + _print_expr (dstr, swiz.src, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, swiz.src); + dasprintf (dstr, "%*se_%p [label=\"swizzle %s\\n%d\"];\n", indent, "", e, + swizzle, e->line); +} + static void _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -584,6 +619,8 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_adjstk] = print_adjstk, [ex_with] = print_with, [ex_args] = print_args, + [ex_horizontal] = print_horizontal, + [ex_swizzle] = print_swizzle, }; int indent = level * 2 + 2; diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 30b2d1b4b..d5615a794 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -179,6 +179,74 @@ use_tempop (operand_t *op, expr_t *expr) bug (expr, "temp users went negative: %s", operand_string (op)); } +static def_t * +cover_def_32 (def_t *def, int *adj) +{ + int offset = def->offset; + def_t *cover = def; + + if (def->alias) { + offset += def->alias->offset; + } + *adj = offset & 3; + if (offset & 3) { + if (def->alias) { + cover = alias_def (def->alias, def->type, def->offset); + } else { + cover = alias_def (def, def->type, 0); + } + cover->offset -= offset & 3; + } + return cover; +} + +static def_t * +cover_def_64 (def_t *def, int *adj) +{ + int offset = def->offset; + def_t *cover = def; + + if (def->alias) { + offset += def->alias->offset; + } + if (offset & 1) { + internal_error (0, "misaligned 64-bit swizzle source"); + } + *adj = (offset & 6) >> 1; + if (offset & 6) { + if (def->alias) { + cover = alias_def (def->alias, def->type, def->offset); + } else { + cover = alias_def (def, def->type, 0); + } + cover->offset -= offset & 6; + } + return cover; +} + +static def_t * +cover_def (def_t *def, int *adj) +{ + if (type_size (base_type (def->type)) == 1) { + return cover_def_32 (def, adj); + } else { + return cover_def_64 (def, adj); + } +} + +static void +adjust_swizzle (def_t *def, int adj) +{ + pr_ushort_t swiz = def->offset; + for (int i = 0; i < 8; i += 2) { + pr_ushort_t mask = 3 << i; + pr_ushort_t ind = swiz & mask; + swiz &= ~mask; + swiz |= (ind + (adj << i)) & mask; + } + def->offset = swiz; +} + static void emit_statement (statement_t *statement) { @@ -202,12 +270,28 @@ emit_statement (statement_t *statement) op_b = statement->opb; op_c = statement->opc; } + def_a = get_operand_def (statement->expr, op_a); use_tempop (op_a, statement->expr); def_b = get_operand_def (statement->expr, op_b); use_tempop (op_b, statement->expr); def_c = get_operand_def (statement->expr, op_c); use_tempop (op_c, statement->expr); + + if (strcmp (opcode, "swizzle") == 0) { + op_c->type = float_type (op_c->type); + op_a->type = float_type (op_a->type); + if (!op_c->type || !op_a->type) { + internal_error (statement->expr, "invalid types in swizzle"); + } + if (op_a->width < 4) { + int adj; + def_a = cover_def (def_a, &adj); + adjust_swizzle (def_b, adj); + op_a->width = 4; + } + } + inst = opcode_find (opcode, op_a, op_b, op_c); if (!inst) { diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index db2305e83..595eb1e87 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -195,6 +195,8 @@ get_type (expr_t *e) return &type_va_list; case ex_horizontal: return e->e.hop.type; + case ex_swizzle: + return e->e.swizzle.type; case ex_count: internal_error (e, "invalid expression"); } @@ -425,6 +427,11 @@ copy_expr (expr_t *e) *n = *e; e->e.hop.vec = copy_expr (e->e.hop.vec); return n; + case ex_swizzle: + n = new_expr (); + *n = *e; + e->e.swizzle.src = copy_expr (e->e.swizzle.src); + return n; case ex_count: break; } @@ -611,6 +618,74 @@ new_horizontal_expr (int op, expr_t *vec, type_t *type) return e; } +expr_t * +new_swizzle_expr (expr_t *src, const char *swizzle) +{ + type_t *src_type = get_type (src); + if (!src_type) { + return src; + } + int src_width = type_width (src_type); + // swizzle always generates a *vec4 + ex_swizzle_t swiz = {}; + +#define m(x) (1 << ((x) - 'a')) +#define v(x, mask) (((x) & 0x60) == 0x60 && (m(x) & (mask))) +#define vind(x) ((x) & 3) +#define cind(x) (-(((x) >> 3) ^ (x)) & 3) +#define tind(x) ((((~(x+1)>>2)&1) + x + 1) & 3) + const int color = m('r') | m('g') | m('b') | m('a'); + const int vector = m('x') | m('y') | m('z') | m('w'); + const int texture = m('s') | m('t') | m('p') | m('q'); + + int type_mask = 0; + int comp_count = 0; + + for (const char *s = swizzle; *s; s++) { + if (comp_count >= 4) { + return error (src, "too many components in swizzle"); + } + if (*s == '0') { + swiz.zero |= 1 << comp_count; + comp_count++; + } else if (*s == '-') { + swiz.neg |= 1 << comp_count; + } else { + int ind = 0; + int mask = 0; + if (v (*s, vector)) { + ind = vind (*s); + mask = 1; + } else if (v (*s, color)) { + ind = cind (*s); + mask = 2; + } else if (v (*s, texture)) { + ind = tind (*s); + mask = 4; + } + if (!mask) { + return error (src, "invalid component in swizzle"); + } + if (type_mask & ~mask) { + return error (src, "mixed components in swizzle"); + } + if (ind >= src_width) { + return error (src, "swizzle component out of bounds"); + } + type_mask |= mask; + swiz.source[comp_count++] = ind; + } + } + swiz.zero |= (0xf << comp_count) & 0xf; + swiz.src = new_alias_expr (vector_type (&type_float, src_width), src); + swiz.type = vector_type (base_type (src_type), 4); + + expr_t *expr = new_expr (); + expr->type = ex_swizzle; + expr->e.swizzle = swiz; + return expr; +} + expr_t * new_def_expr (def_t *def) { @@ -1547,6 +1622,8 @@ has_function_call (expr_t *e) return has_function_call (e->e.retrn.ret_val); case ex_horizontal: return has_function_call (e->e.hop.vec); + case ex_swizzle: + return has_function_call (e->e.swizzle.src); case ex_error: case ex_state: case ex_label: @@ -1692,6 +1769,7 @@ unary_expr (int op, expr_t *e) case ex_alias: case ex_assign: case ex_horizontal: + case ex_swizzle: { expr_t *n = new_unary_expr (op, e); @@ -1785,6 +1863,7 @@ unary_expr (int op, expr_t *e) case ex_address: case ex_assign: case ex_horizontal: + case ex_swizzle: if (options.code.progsversion == PROG_VERSION) { return binary_expr (EQ, e, new_nil_expr ()); } else { @@ -1874,6 +1953,7 @@ unary_expr (int op, expr_t *e) case ex_alias: case ex_assign: case ex_horizontal: + case ex_swizzle: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { expr_t *n1 = new_int_expr (-1); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 1bc88faf7..b04a98b36 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -142,6 +142,7 @@ is_lvalue (const expr_t *expr) case ex_with: case ex_args: case ex_horizontal: + case ex_swizzle: break; case ex_count: internal_error (expr, "invalid expression"); diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 454f01fdf..d2e8e59c5 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -654,13 +654,28 @@ convert_scalar (expr_t *scalar, int op, expr_t *vec) if (!*s_op) { return 0; } + // expand the scalar to a vector of the same width as vec - for (int i = 1; i < type_width (get_type (vec)); i++) { - expr_t *s = copy_expr (scalar); - s->next = scalar; - scalar = s; + type_t *vec_type = get_type (vec); + + if (scalar->type == ex_symbol || scalar->type == ex_def + || is_constant (scalar)) { + for (int i = 1; i < type_width (get_type (vec)); i++) { + expr_t *s = copy_expr (scalar); + s->next = scalar; + scalar = s; + } + return new_vector_list (scalar); } - return new_vector_list (scalar); + + char swizzle[] = "xxxx"; + type_t *vec_base = base_type (vec_type); + expr_t *tmp = new_temp_def_expr (vector_type (vec_base, 4)); + expr_t *block = new_block_expr (); + swizzle[type_width (vec_type)] = 0; + append_expr (block, assign_expr (tmp, new_swizzle_expr (scalar, swizzle))); + block->e.block.result = new_alias_expr (vec_type, tmp); + return block; } static expr_t * diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 5c97f780c..d4413e744 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -41,6 +41,7 @@ #include +#include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/opcodes.h" #include "tools/qfcc/include/options.h" #include "tools/qfcc/include/qfcc.h" @@ -302,7 +303,26 @@ operand_width (const char *opname, operand_t *op) } return op->width; } - +#if 0 + if (!strcmp (name, "swizzle")) { + adjust_swizzle_op (&search_op, 0); + adjust_swizzle_op (&search_op, 2); + } +static void +adjust_swizzle_op (opcode_t *op, int opind) +{ + // swizzle instructions require both operands to be 4 components (4 or 8 + // words) in size with the same alignment. + op->widths[opind] = 4; + if (pr_type_size[op->types[opind]] == 1) { + op->types[opind] = ev_float; + } else if (pr_type_size[op->types[opind]] == 2) { + op->types[opind] = ev_double; + } else { + internal_error (0, "unexpected swizzle op size"); + } +} +#endif static opcode_t * rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, operand_t *op_c) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 7d15854f6..4e5010427 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1783,6 +1783,32 @@ expr_horizontal (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_swizzle (sblock_t *sblock, expr_t *e, operand_t **op) +{ + const char *opcode = "swizzle"; + statement_t *s; + int swiz = 0; + type_t *res_type = e->e.swizzle.type; + + for (int i = 0; i < 4; i++) { + swiz |= e->e.swizzle.source[i] & 3; + } + swiz |= (e->e.swizzle.neg & 0xf) << 8; + swiz |= (e->e.swizzle.zero & 0xf) << 12; + + s = new_statement (st_expr, opcode, e); + sblock = statement_subexpr (sblock, e->e.swizzle.src, &s->opa); + s->opb = short_operand (swiz, e); + if (!*op) { + *op = temp_operand (res_type, e); + } + s->opc = *op; + sblock_add_statement (sblock, s); + + return sblock; +} + static sblock_t * expr_def (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1915,6 +1941,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_expr] = expr_expr, [ex_uexpr] = expr_uexpr, [ex_horizontal] = expr_horizontal, + [ex_swizzle] = expr_swizzle, [ex_def] = expr_def, [ex_symbol] = expr_symbol, [ex_temp] = expr_temp, diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index bd5d93e62..8b0901339 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -586,6 +586,38 @@ base_type (const type_t *vec_type) return ev_types[vec_type->type]; } +type_t * +int_type (const type_t *base) +{ + int width = type_width (base); + base = base_type (base); + if (!base) { + return 0; + } + if (type_size (base) == 1) { + base = &type_int; + } else if (type_size (base) == 2) { + base = &type_long; + } + return vector_type (base, width); +} + +type_t * +float_type (const type_t *base) +{ + int width = type_width (base); + base = base_type (base); + if (!base) { + return 0; + } + if (type_size (base) == 1) { + base = &type_float; + } else if (type_size (base) == 2) { + base = &type_double; + } + return vector_type (base, width); +} + type_t * array_type (type_t *aux, int size) { From cdd8739577b776af9c9f4911ac22a71f9d763cfc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 May 2022 14:05:43 +0900 Subject: [PATCH 2721/3664] [qfcc] Improve debug printing of statements and operands Makes it easier to check operand base indices and temporary variable addresses when known. --- tools/qfcc/source/opcodes.c | 7 +++++-- tools/qfcc/source/statements.c | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index d4413e744..23da7490b 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -527,6 +527,9 @@ opcode_print_statement (pr_uint_t addr, dstatement_t *st) } else { mnemonic = pr_opcodes[st_op].mnemonic; } - printf ("%04x (%03x)%-8s %04x %04x %04x\n", - addr, st_op & 0x1ff, mnemonic, st->a, st->b, st->c); + printf ("%04x (%03x)%-8s %d:%04x %d:%04x %d:%04x\n", + addr, st_op & 0x1ff, mnemonic, + (st->op & OP_A_BASE) >> OP_A_SHIFT, st->a, + (st->op & OP_B_BASE) >> OP_B_SHIFT, st->b, + (st->op & OP_C_BASE) >> OP_C_SHIFT, st->c); } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 4e5010427..28114dedf 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -162,7 +162,8 @@ _print_operand (operand_t *op) case op_temp: printf ("tmp (%s) %p", get_type_string (op->type), op); if (op->tempop.def) - printf (" %s", op->tempop.def->name); + printf (" %s:%04x", op->tempop.def->name, + op->tempop.def->offset); break; case op_alias: printf ("alias(%s,", get_type_string (op->type)); From 7518ba0a2756b8b6f5f8e230cbce8966a58d180d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 May 2022 14:07:32 +0900 Subject: [PATCH 2722/3664] [qfcc] Add failing test case for defspace_alloc_aligned_loc qfcc is putting two temps in the same location due to defspace_alloc_aligned_loc returning the same address when there was a hole caused by an earlier aligned alloc: specifically, a size-3 hole and a size-2 allocation with alignment-2. --- tools/qfcc/test/test-defspace.c | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tools/qfcc/test/test-defspace.c b/tools/qfcc/test/test-defspace.c index 17d9ed12e..cbb80d623 100644 --- a/tools/qfcc/test/test-defspace.c +++ b/tools/qfcc/test/test-defspace.c @@ -104,6 +104,39 @@ test_init (void) return pass; } +static int +test_aligned_alloc (void) +{ + defspace_t *space = defspace_new (ds_virtual); + struct { + int size, align; + } allocations[6] = { + { 2, 2 }, + { 2, 2 }, + { 1, 1 }, + { 4, 4 }, + { 2, 2 }, + { 2, 2 }, + }; + int offsets[6]; + for (int i = 0; i < 6; i++) { + offsets[i] = defspace_alloc_aligned_loc (space, allocations[i].size, + allocations[i].align); + } + for (int i = 0; i < 5; i++) { + for (int j = i + 1; j < 6; j++) { + if (offsets[i] == offsets[j]) { + printf ("duplicate offset in allocations"); + printf ("%d %d %d %d %d %d\n", + offsets[0], offsets[1], offsets[2], + offsets[3], offsets[4], offsets[5]); + return 0; + } + } + } + return 1; +} + int main (int argc, const char **argv) { @@ -112,6 +145,7 @@ main (int argc, const char **argv) int pass = 1; pass &= test_init (); + pass &= test_aligned_alloc (); return !pass; } From be4021f8f4cf8e8ef415afd80402d99fd0bfd6de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 May 2022 14:11:11 +0900 Subject: [PATCH 2723/3664] [qfcc] Actually shrink the unaligned hole This fixes the duplicate allocation caused by an exact fit aligned alloc in an unaligned hole where the padding remains free. --- tools/qfcc/source/defspace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index a704b45a3..e1dc3b72a 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -173,7 +173,8 @@ defspace_alloc_aligned_loc (defspace_t *space, int size, int alignment) // exact fit, so just shrink the block or remove it if there is no // padding (any padding remains free) if (size + pad == loc->size) { - if (!pad) { + loc->size -= size; + if (!loc->size) { *l = loc->next; del_locref (loc); } From b9bd45ad992403a7a4622b30898fc461a17a3b2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 1 May 2022 14:12:43 +0900 Subject: [PATCH 2724/3664] [qfcc] Create vector lists only for constants Defs and symbols benefit from swizzling as that's one instruction vs 2-3 for loading a scalar into a vector component by component. Constants are ok because the result gets converted to a vector constant. --- tools/qfcc/source/expr_binary.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index d2e8e59c5..1c0429d09 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -658,8 +658,7 @@ convert_scalar (expr_t *scalar, int op, expr_t *vec) // expand the scalar to a vector of the same width as vec type_t *vec_type = get_type (vec); - if (scalar->type == ex_symbol || scalar->type == ex_def - || is_constant (scalar)) { + if (is_constant (scalar)) { for (int i = 1; i < type_width (get_type (vec)); i++) { expr_t *s = copy_expr (scalar); s->next = scalar; From ef6e4722d52a6ebf6be0763f35a13bcfd4fbdfdf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 13:48:34 +0900 Subject: [PATCH 2725/3664] [simd] Add some comments to mat4fquat Having to refigure out what values are going into the vectors got old very fast. The comments don't help with verifying the values, but at least I can tell at a glance where 2(xy - wz) goes and thus determine the "orientation" of the matrix. --- include/QF/simd/mat4f.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/QF/simd/mat4f.h b/include/QF/simd/mat4f.h index d442bdac9..981d71d22 100644 --- a/include/QF/simd/mat4f.h +++ b/include/QF/simd/mat4f.h @@ -175,7 +175,7 @@ mat4fquat (mat4f_t m, vec4f_t q) vec4f_t b = _mm_xor_ps (shuff103 (yq), (__m128) mpm); vec4f_t c = _mm_xor_ps (shuff230 (zq), (__m128) pmm); vec4f_t d = _mm_xor_ps (shuff321 (wq), (__m128) mmp); - + // column: ww + xx - yy - zz // 2xy + 2wz // 2zx - 2wy // 0 m[0] = _mm_and_ps (a + b - c - d, (__m128) mask); } { @@ -183,6 +183,7 @@ mat4fquat (mat4f_t m, vec4f_t q) vec4f_t b = yq; vec4f_t c = _mm_xor_ps (shuff321 (zq), (__m128) mmp); vec4f_t d = _mm_xor_ps (shuff230 (wq), (__m128) pmm); + // column: 2xy - 2wz // ww - xx + yy - zz // 2yz + 2wx // 0 m[1] = _mm_and_ps (b + c - a - d, (__m128) mask); } { @@ -190,6 +191,7 @@ mat4fquat (mat4f_t m, vec4f_t q) vec4f_t b = _mm_xor_ps (shuff321 (yq), (__m128) mmp); vec4f_t c = zq; vec4f_t d = _mm_xor_ps (shuff103 (wq), (__m128) mpm); + // column: 2xz + 2wy // 2yz - 2wx // ww - xx - yy + zz // 0 m[2] = _mm_and_ps (a - b + c - d, (__m128) mask); } m[3] = (vec4f_t) { 0, 0, 0, 1 }; From 419d91edc5ded36345458385d69271ac9fe9d7d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 13:50:55 +0900 Subject: [PATCH 2726/3664] [image] Set texture type for no-load tga images I might need to do similar for other formats, but i ran into the problem of the texture type being tex_palette instead of the expected tex_rgba when pre-(no-)loading a tga image resulting in Vulkan not liking my attempt at generating mipmaps. --- include/QF/tga.h | 11 +++++++++++ libs/image/tga.c | 31 +++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/include/QF/tga.h b/include/QF/tga.h index 08d610d95..a5a133da3 100644 --- a/include/QF/tga.h +++ b/include/QF/tga.h @@ -44,6 +44,17 @@ # endif #endif +typedef enum { + targa_colormap = 1, + targa_truecolor = 2, + targa_greyscale = 3, + targa_colormap_rle = 9, + targa_truecolor_rle = 10, + targa_greyscale_rle = 11, + + targa_max_image_type = 15 +} TargaImageType; + typedef struct _TargaHeader { unsigned char id_length; // __attribute__((packed)); unsigned char colormap_type; // __attribute__((packed)); diff --git a/libs/image/tga.c b/libs/image/tga.c index 20db43ddd..03368ce6f 100644 --- a/libs/image/tga.c +++ b/libs/image/tga.c @@ -605,19 +605,25 @@ decode_greyscale_rle (TargaHeader *targa, tex_t *tex, byte *dataByte) typedef void (*decoder_t) (TargaHeader *, tex_t *, byte *); static decoder_t decoder_functions[] = { - 0, // 0 invalid - decode_colormap, - decode_truecolor, - decode_greyscale, - 0, 0, 0, 0, // 5-7 invalid - 0, // 8 invalid - decode_colormap_rle, - decode_truecolor_rle, - decode_greyscale_rle, - 0, 0, 0, 0, // 12-15 invalid + [targa_colormap] = decode_colormap, + [targa_truecolor] = decode_truecolor, + [targa_greyscale] = decode_greyscale, + [targa_colormap_rle] = decode_colormap_rle, + [targa_truecolor_rle] = decode_truecolor_rle, + [targa_greyscale_rle] = decode_greyscale_rle, + [targa_max_image_type] = 0 }; #define NUM_DECODERS (sizeof (decoder_functions) \ / sizeof (decoder_functions[0])) +static QFFormat targa_formats[] = { + [targa_colormap] = tex_palette, + [targa_truecolor] = tex_rgba, + [targa_greyscale] = tex_l, + [targa_colormap_rle] = tex_palette, + [targa_truecolor_rle] = tex_rgba, + [targa_greyscale_rle] = tex_l, + [targa_max_image_type] = 0 +}; struct tex_s * LoadTGA (QFile *fin, int load) @@ -669,6 +675,11 @@ LoadTGA (QFile *fin, int load) dataByte += targa->id_length; decode (targa, tex, dataByte); + } else { + //FIXME + // assume the format is valid so we can return a format type without + // having to check individial image type specific data + tex->format = targa_formats[targa->image_type]; } Hunk_FreeToLowMark (0, targa_mark); From a77aa1631804d0b6985ab6bd27de1d41aa87ef93 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 13:55:56 +0900 Subject: [PATCH 2727/3664] [vulkan] Make some headers order-indepenedent In that they don't need Vulkan/qf_vid.h included first. --- include/QF/Vulkan/barrier.h | 5 +++++ include/QF/Vulkan/buffer.h | 5 +++++ include/QF/Vulkan/image.h | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h index a28e07817..52be26b08 100644 --- a/include/QF/Vulkan/barrier.h +++ b/include/QF/Vulkan/barrier.h @@ -1,6 +1,11 @@ #ifndef __QF_Vulkan_barrier_h #define __QF_Vulkan_barrier_h +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + typedef struct { VkPipelineStageFlags srcStages; VkPipelineStageFlags dstStages; diff --git a/include/QF/Vulkan/buffer.h b/include/QF/Vulkan/buffer.h index 374a496b1..2edff6a1d 100644 --- a/include/QF/Vulkan/buffer.h +++ b/include/QF/Vulkan/buffer.h @@ -1,6 +1,11 @@ #ifndef __QF_Vulkan_buffer_h #define __QF_Vulkan_buffer_h +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + #include "QF/darray.h" typedef struct qfv_buffertransition_s { diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index d146b298c..0f10b3092 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -1,6 +1,11 @@ #ifndef __QF_Vulkan_image_h #define __QF_Vulkan_image_h +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + #include "QF/darray.h" typedef struct qfv_imageset_s From 9d7cad420da8689572058b6adda99b248270d91b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 13:57:02 +0900 Subject: [PATCH 2728/3664] [vulkan] Add a function to translate QFFormat to VkFormat It's not great, but it does produce reasonable results for the formats supported by QF's image system. --- include/QF/Vulkan/image.h | 11 +++++++++++ libs/video/renderer/vulkan/image.c | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 0f10b3092..3524b27ee 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -7,6 +7,7 @@ #include #include "QF/darray.h" +#include "QF/image.h" typedef struct qfv_imageset_s DARRAY_TYPE (VkImage) qfv_imageset_t; @@ -100,4 +101,14 @@ void QFV_GenerateMipMaps (struct qfv_device_s *device, VkCommandBuffer cmd, unsigned width, unsigned height, unsigned layers); int QFV_MipLevels (int width, int height) __attribute__((const)); +/** Convert QFFormat to VkFormat + * + * \param format The format to convert. + * \return The corresponding VkFormat. + * + * \note For tex_palette, VK_FORMAT_R8_UINT is returned. If \a format is + * not a valid QFFormat, then VK_FORMAT_R8_SRGB is returned. + */ +VkFormat QFV_ImageFormat (QFFormat format); + #endif//__QF_Vulkan_image_h diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 092af713a..27bb3cf7b 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -266,3 +266,24 @@ QFV_MipLevels (int width, int height) { return ilog2 (max (width, height)) + 1; } + +VkFormat +QFV_ImageFormat (QFFormat format) +{ + switch (format) { + case tex_palette: + return VK_FORMAT_R8_UINT; + case tex_l: + case tex_a: + return VK_FORMAT_R8_UNORM; + case tex_la: + return VK_FORMAT_R8G8_UNORM; + case tex_rgb: + return VK_FORMAT_R8G8B8_UNORM; // SRGB? + case tex_rgba: + return VK_FORMAT_R8G8B8A8_UNORM;// SRGB? + case tex_frgba: + return VK_FORMAT_R32G32B32A32_SFLOAT; + } + return VK_FORMAT_R8_SRGB; +} From a4f500da3c3f3e8b9b51cf680e27db03c865e19d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 13:59:38 +0900 Subject: [PATCH 2729/3664] [vulkan] Add a mini resource subsystem The resource subsystem creates buffers, images, buffer views and image views in a single batch operation, using a single memory object to back all the buffers and images. I had been doing this by hand for a while, but got tired of jumping through all those vulkan hoops. While it's still a little tedious to set up the arrays for QFV_CreateResource (and they need to be kept around for QFV_DestroyResource), it really eases calculation of memory object size and sub-resource offsets. And destroying all the objects is just one call to QFV_DestroyResource. --- include/QF/Vulkan/resource.h | 68 +++++++ libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vulkan/resource.c | 271 ++++++++++++++++++++++++++ 3 files changed, 340 insertions(+) create mode 100644 include/QF/Vulkan/resource.h create mode 100644 libs/video/renderer/vulkan/resource.c diff --git a/include/QF/Vulkan/resource.h b/include/QF/Vulkan/resource.h new file mode 100644 index 000000000..7d1e0dac6 --- /dev/null +++ b/include/QF/Vulkan/resource.h @@ -0,0 +1,68 @@ +#ifndef __QF_Vulkan_resource_h +#define __QF_Vulkan_resource_h + +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + +typedef enum { + qfv_res_buffer = 1, + qfv_res_buffer_view, + qfv_res_image, + qfv_res_image_view, +} qfv_res_type; + +typedef struct qfv_resobj_s { + const char *name; + qfv_res_type type; + union { + struct { + VkDeviceSize size; + VkBufferUsageFlags usage; + VkBuffer buffer; + } buffer; + struct { + unsigned buffer; + VkFormat format; + VkDeviceSize offset; + VkDeviceSize size; + VkBufferView view; + } buffer_view; + struct { + int cubemap; + VkImageType type; + VkFormat format; + VkExtent3D extent; + uint32_t num_mipmaps; + uint32_t num_layers; + VkSampleCountFlags samples; + VkImageUsageFlags usage; + VkImage image; + } image; + struct { + unsigned image; + VkImageViewType type; + VkFormat format; + VkImageAspectFlags aspect; + VkImageView view; + } image_view; + }; +} qfv_resobj_t; + +typedef struct qfv_resource_s { + const char *name; + struct va_ctx_s *va_ctx; + VkMemoryPropertyFlags memory_properties; + unsigned num_objects; + qfv_resobj_t *objects; + VkDeviceMemory memory; +} qfv_resource_t; + +struct qfv_device_s; + +int QFV_CreateResource (struct qfv_device_s *device, qfv_resource_t *resource); +void QFV_DestroyResource (struct qfv_device_s *device, + qfv_resource_t *resource); + +#endif//__QF_Vulkan_resource_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 2743a4a68..eceb2a1c2 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -207,6 +207,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/pipeline.c \ libs/video/renderer/vulkan/projection.c \ libs/video/renderer/vulkan/renderpass.c \ + libs/video/renderer/vulkan/resource.c \ libs/video/renderer/vulkan/scrap.c \ libs/video/renderer/vulkan/shader.c \ libs/video/renderer/vulkan/staging.c \ diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c new file mode 100644 index 000000000..2eb08e6d7 --- /dev/null +++ b/libs/video/renderer/vulkan/resource.c @@ -0,0 +1,271 @@ +/* + resource.c + + Vulkan resource functions + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/va.h" + +#include "QF/Vulkan/buffer.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/resource.h" + +int +QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) +{ + qfv_devfuncs_t *dfunc = device->funcs; + qfv_physdev_t *physdev = device->physDev; + VkPhysicalDeviceMemoryProperties *memprops = &physdev->memory_properties; + VkMemoryRequirements req; + VkDeviceSize size = 0; + + for (unsigned i = 0; i < resource->num_objects; i++) { + __auto_type obj = &resource->objects[i]; + switch (obj->type) { + case qfv_res_buffer: + { + __auto_type buffer = &obj->buffer; + buffer->buffer = QFV_CreateBuffer (device, + buffer->size, + buffer->usage); + const char *name = va (resource->va_ctx, "buffer:%s:%s", + resource->name, obj->name); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, + buffer->buffer, name); + dfunc->vkGetBufferMemoryRequirements (device->dev, + buffer->buffer, &req); + } + break; + case qfv_res_buffer_view: + { + __auto_type buffview = &obj->buffer_view; + __auto_type buffobj = &resource->objects[buffview->buffer]; + if (buffview->buffer >= resource->num_objects + || buffobj->type != qfv_res_buffer) { + Sys_Error ("%s:%s invalid buffer for view", + resource->name, obj->name); + } + } + break; + case qfv_res_image: + { + __auto_type image = &obj->image; + image->image = QFV_CreateImage (device, + image->cubemap, + image->type, + image->format, + image->extent, + image->num_mipmaps, + image->num_layers, + image->samples, + image->usage); + const char *name = va (resource->va_ctx, "image:%s:%s", + resource->name, obj->name); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, + image->image, name); + dfunc->vkGetImageMemoryRequirements (device->dev, + image->image, &req); + } + break; + case qfv_res_image_view: + { + __auto_type imgview = &obj->image_view; + __auto_type imgobj = &resource->objects[imgview->image]; + if (imgview->image >= resource->num_objects + || imgobj->type != qfv_res_image) { + Sys_Error ("%s:%s invalid image for view", + resource->name, obj->name); + } + } + break; + default: + Sys_Error ("%s:%s invalid resource type %d", + resource->name, obj->name, obj->type); + } + size = QFV_NextOffset (size, &req); + size += req.size; + } + VkMemoryPropertyFlags properties = resource->memory_properties; + for (uint32_t type = 0; type < memprops->memoryTypeCount; type++) { + if ((req.memoryTypeBits & (1 << type)) + && ((memprops->memoryTypes[type].propertyFlags & properties) + == properties)) { + VkMemoryAllocateInfo allocate_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = size, + .memoryTypeIndex = type, + }; + VkResult res = dfunc->vkAllocateMemory (device->dev, &allocate_info, + 0, &resource->memory); + if (res == VK_SUCCESS) { + break; + } + } + } + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + resource->memory, va (resource->va_ctx, "memory:%s", + resource->name)); + + VkDeviceSize offset = 0; + for (unsigned i = 0; i < resource->num_objects; i++) { + __auto_type obj = &resource->objects[i]; + switch (obj->type) { + case qfv_res_buffer: + { + __auto_type buffer = &obj->buffer; + dfunc->vkGetBufferMemoryRequirements (device->dev, + buffer->buffer, &req); + } + break; + case qfv_res_image: + { + __auto_type image = &obj->image; + dfunc->vkGetImageMemoryRequirements (device->dev, + image->image, &req); + } + break; + case qfv_res_buffer_view: + case qfv_res_image_view: + break; + } + + offset = QFV_NextOffset (offset, &req); + switch (obj->type) { + case qfv_res_buffer: + { + __auto_type buffer = &obj->buffer; + QFV_BindBufferMemory (device, buffer->buffer, + resource->memory, offset); + } + break; + case qfv_res_image: + { + __auto_type image = &obj->image; + QFV_BindImageMemory (device, image->image, + resource->memory, offset); + } + break; + case qfv_res_buffer_view: + case qfv_res_image_view: + break; + } + offset += req.size; + } + + for (unsigned i = 0; i < resource->num_objects; i++) { + __auto_type obj = &resource->objects[i]; + switch (obj->type) { + case qfv_res_buffer: + case qfv_res_image: + break; + case qfv_res_buffer_view: + { + __auto_type buffview = &obj->buffer_view; + __auto_type buffobj = &resource->objects[buffview->buffer]; + __auto_type buffer = &buffobj->buffer; + buffview->view = QFV_CreateBufferView (device, + buffer->buffer, + buffview->format, + buffview->offset, + buffview->size); + const char *name = va (resource->va_ctx, "bview:%s:%s", + resource->name, obj->name); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER_VIEW, + buffview->view, name); + } + break; + case qfv_res_image_view: + { + __auto_type imgview = &obj->image_view; + __auto_type imgobj = &resource->objects[imgview->image]; + __auto_type image = &imgobj->image; + imgview->view = QFV_CreateImageView (device, + image->image, + imgview->type, + imgview->format, + imgview->aspect); + const char *name = va (resource->va_ctx, "iview:%s:%s", + resource->name, obj->name); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, + imgview->view, name); + } + break; + } + } + return 0; +} + +void +QFV_DestroyResource (qfv_device_t *device, qfv_resource_t *resource) +{ + qfv_devfuncs_t *dfunc = device->funcs; + + for (unsigned i = 0; i < resource->num_objects; i++) { + __auto_type obj = &resource->objects[i]; + switch (obj->type) { + case qfv_res_buffer: + case qfv_res_image: + break; + case qfv_res_buffer_view: + { + __auto_type buffview = &obj->buffer_view; + dfunc->vkDestroyBufferView (device->dev, buffview->view, 0); + } + break; + case qfv_res_image_view: + { + __auto_type imgview = &obj->image_view; + dfunc->vkDestroyImageView (device->dev, imgview->view, 0); + } + break; + } + } + for (unsigned i = 0; i < resource->num_objects; i++) { + __auto_type obj = &resource->objects[i]; + switch (obj->type) { + case qfv_res_buffer: + { + __auto_type buffer = &obj->buffer; + dfunc->vkDestroyBuffer (device->dev, buffer->buffer, 0); + } + break; + case qfv_res_image: + { + __auto_type image = &obj->image; + dfunc->vkDestroyImage (device->dev, image->image, 0); + } + break; + case qfv_res_buffer_view: + case qfv_res_image_view: + break; + } + } + dfunc->vkFreeMemory (device->dev, resource->memory, 0); +} From bbca22c722412dd0b5c297a7cddc3b8947ff1569 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 14:07:27 +0900 Subject: [PATCH 2730/3664] [vulkan] Add support for IQM models Despite the base IQM specification not supporting blend-shapes, I think IQM will become the basis for QF's generic model representation (at least for the more advanced renderers). After my experience with .mu models (KSP) and unity mesh objects (both normal and skinned), and reviewing the IQM spec, it looks like with the addition of support for blend-shapes, IQM is actually pretty good. This is just the preliminary work to get standard IQM models loading in vulkan (seems to work, along with unloading), and they very basics into the renderer (most likely not working: not tested yet). The rest of the renderer seems to be unaffected, though, which is good. --- include/QF/Vulkan/qf_iqm.h | 113 +++++ include/vid_vulkan.h | 1 + libs/models/iqm/vulkan_model_iqm.c | 468 +++++++++++++++++++++ libs/video/renderer/Makemodule.am | 13 +- libs/video/renderer/vid_render_vulkan.c | 2 + libs/video/renderer/vulkan/iqm.plist | 254 +++++++++++ libs/video/renderer/vulkan/shader.c | 6 + libs/video/renderer/vulkan/shader/iqm.frag | 44 ++ libs/video/renderer/vulkan/shader/iqm.vert | 52 +++ libs/video/renderer/vulkan/vulkan_iqm.c | 310 ++++++++++++++ 10 files changed, 1262 insertions(+), 1 deletion(-) create mode 100644 include/QF/Vulkan/qf_iqm.h create mode 100644 libs/video/renderer/vulkan/iqm.plist create mode 100644 libs/video/renderer/vulkan/shader/iqm.frag create mode 100644 libs/video/renderer/vulkan/shader/iqm.vert create mode 100644 libs/video/renderer/vulkan/vulkan_iqm.c diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h new file mode 100644 index 000000000..7de1623d9 --- /dev/null +++ b/include/QF/Vulkan/qf_iqm.h @@ -0,0 +1,113 @@ +/* + qf_iqm.h + + Vulkan specific iqm model stuff + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/5/3 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_iqm_h +#define __QF_Vulkan_qf_iqm_h + +#include "QF/darray.h" +#include "QF/model.h" +#include "QF/modelgen.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" + +// geometry attributes +typedef struct iqmgvert_s { + float vertex[3]; + byte bones[4]; // uint + byte weights[4]; // unorm +} iqmgvert_t; + +// rendering attributes +typedef struct iqmrvert_s { + float uv[2]; + float normal[3]; + float tangent[4]; + byte color[4]; // unorm +} iqmrvert_t; + +typedef struct qfv_iqm_skin_s { + VkImageView view; + byte colora[4]; + byte colorb[4]; + VkDescriptorSet descriptor; +} qfv_iqm_skin_t; + +typedef struct qfv_iqm_s { + VkBuffer geom_buffer; + VkBuffer rend_buffer; + VkBuffer index_buffer; + qfv_iqm_skin_t *skins; + struct qfv_resource_s *mesh; + struct qfv_resource_s *bones; +} qfv_iqm_t; + +typedef enum { + QFV_iqmDepth, + QFV_iqmGBuffer, + QFV_iqmTranslucent, + + QFV_iqmNumPasses +} QFV_IQMSubpass; + +typedef struct iqm_frame_s { + qfv_cmdbufferset_t cmdSet; +} iqm_frame_t; + +typedef struct iqm_frameset_s + DARRAY_TYPE (iqm_frame_t) iqm_frameset_t; + +typedef struct iqmindset_s + DARRAY_TYPE (unsigned) iqmindset_t; + +typedef struct iqmctx_s { + iqm_frameset_t frames; + VkPipeline depth; + VkPipeline gbuf; + VkPipelineLayout layout; + VkSampler sampler; +} iqmctx_t; + +struct vulkan_ctx_s; +struct qfv_renderframe_s; +struct entity_s; +struct mod_iqm_ctx_s; + +void Vulkan_Mod_IQMFinish (struct model_s *mod, struct vulkan_ctx_s *ctx); + +void Vulkan_IQMAddSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); +void Vulkan_IQMRemoveSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); + +void Vulkan_IQMBegin (struct qfv_renderframe_s *rFrame); +void Vulkan_DrawIQM (struct entity_s *ent, struct qfv_renderframe_s *rFrame); +void Vulkan_IQMEnd (struct qfv_renderframe_s *rFrame); + +void Vulkan_IQM_Init (struct vulkan_ctx_s *ctx); +void Vulkan_IQM_Shutdown (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_iqm_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index e5bd29022..df1e4b6bd 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -67,6 +67,7 @@ typedef struct vulkan_ctx_s { struct matrixctx_s *matrix_context; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; + struct iqmctx_s *iqm_context; struct particlectx_s *particle_context; struct spritectx_s *sprite_context; struct drawctx_s *draw_context; diff --git a/libs/models/iqm/vulkan_model_iqm.c b/libs/models/iqm/vulkan_model_iqm.c index e69de29bb..c9c7f79c8 100644 --- a/libs/models/iqm/vulkan_model_iqm.c +++ b/libs/models/iqm/vulkan_model_iqm.c @@ -0,0 +1,468 @@ +/* + vulkan_model_iqm.c + + iqm model processing for Vulkan + + Copyright (C) 2011 Bill Currie + + Author: Bill Currie + Date: 2022/05/03 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include "QF/dstring.h" +#include "QF/image.h" +#include "QF/quakefs.h" +#include "QF/va.h" + +#include "QF/Vulkan/barrier.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/resource.h" +#include "QF/Vulkan/staging.h" +#include "QF/Vulkan/qf_iqm.h" +#include "QF/Vulkan/qf_texture.h" + +#include "mod_internal.h" +#include "r_shared.h" +#include "vid_vulkan.h" + +static byte null_texture[] = { + 204, 204, 204, 255, + 204, 204, 204, 255, + 204, 204, 204, 255, + 204, 204, 204, 255, +}; +#if 0 +static byte null_normmap[] = { + 127, 127, 255, 255, + 127, 127, 255, 255, + 127, 127, 255, 255, + 127, 127, 255, 255, +}; +#endif +static void +vulkan_iqm_clear (model_t *mod, void *data) +{ + vulkan_ctx_t *ctx = data; + qfv_device_t *device = ctx->device; + iqm_t *iqm = (iqm_t *) mod->aliashdr; + qfv_iqm_t *mesh = iqm->extra_data; + + mod->needload = true; + + QFV_DestroyResource (device, mesh->bones); + QFV_DestroyResource (device, mesh->mesh); + free (mesh); + Mod_FreeIQM (iqm); +} + +static void +vulkan_iqm_init_image (iqm_t *iqm, int meshnum, qfv_resobj_t *image) +{ + const char *material = iqm->text + iqm->meshes[meshnum].material; + dstring_t *str = dstring_new (); + dstring_copystr (str, material); + QFS_StripExtension (str->str, str->str); + + tex_t *tex; + if ((tex = LoadImage (va (0, "textures/%s", str->str), 0))) { + *image = (qfv_resobj_t) { + .name = material, + .type = qfv_res_image, + .image = { + .type = VK_IMAGE_TYPE_2D, + .format = QFV_ImageFormat (tex->format), + .extent = { + .width = tex->width, + .height = tex->height, + .depth = 1, + }, + .num_mipmaps = QFV_MipLevels (tex->width, tex->height), + .num_layers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT, + }, + }; + } else { + *image = (qfv_resobj_t) { + .name = material, + .type = qfv_res_image, + .image = { + .type = VK_IMAGE_TYPE_2D, + .format = QFV_ImageFormat (tex_rgba), + .extent = { + .width = 2, + .height = 2, + .depth = 1, + }, + .num_mipmaps = QFV_MipLevels (2, 2), + .num_layers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT, + }, + }; + } + dstring_delete (str); +} + +static void +iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage, + qfv_device_t *device) +{ + qfv_devfuncs_t *dfunc = device->funcs; + + if (tex->format != tex_rgb && tex->format != tex_rgba) { + Sys_Error ("can't transfer iqm image"); + } + // FIXME correct only for rgb and rgba + size_t layer_size = tex->width * tex->height * tex->format; + + qfv_packet_t *packet = QFV_PacketAcquire (stage); + byte *dst = QFV_PacketExtend (packet, layer_size); + + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + memcpy (dst, tex->data, layer_size); + + int mipLevels = QFV_MipLevels (tex->width, tex->height); + if (mipLevels == 1) { + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + } else { + QFV_GenerateMipMaps (device, packet->cmd, image, mipLevels, + tex->width, tex->height, 1); + } + QFV_PacketSubmit (packet); +} + +static void +vulkan_iqm_load_textures (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, + vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + dstring_t *str = dstring_new (); + tex_t *tex; + size_t buff_size = 0; + qfv_resobj_t *objects = mesh->mesh->objects; + + for (int i = 0; i < iqm->num_meshes; i++) { + int image_ind = 3 + 2 * i; + VkExtent3D extent = objects[image_ind].image.extent; + // probably 3 or 4 bytes per pixel FIXME + buff_size = max (buff_size, extent.width * extent.height * 4); + } + + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, + va (ctx->va_ctx, "iqm:%s", + mod->name), + 4 * buff_size, + ctx->cmdpool); + + for (int i = 0; i < iqm->num_meshes; i++) { + int image_ind = 3 + 2 * i; + __auto_type image = &objects[image_ind].image; + __auto_type view = &objects[image_ind + 1].image_view; + qfv_iqm_skin_t *skin = &mesh->skins[i]; + *skin = (qfv_iqm_skin_t) { + .view = view->view, + .colora = { 255, 255, 255, 255 }, + .colorb = { 255, 255, 255, 255 }, + }; + + dstring_copystr (str, iqm->text + iqm->meshes[i].material); + QFS_StripExtension (str->str, str->str); + if (!(tex = LoadImage (va (0, "textures/%s", str->str), 1))) { + tex_t null_tex = { + .width = 2, + .height = 2, + .format = tex_rgba, + .data = null_texture, + }; + tex = &null_tex; + } + iqm_transfer_texture (tex, image->image, stage, device); + } + dstring_delete (str); + QFV_DestroyStagingBuffer (stage); +} + +static void +vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, + vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + size_t geom_size = iqm->num_verts * sizeof (iqmgvert_t); + size_t rend_size = iqm->num_verts * sizeof (iqmrvert_t); + size_t elem_size = iqm->num_elements * sizeof (uint16_t); + size_t buff_size = geom_size + rend_size + elem_size + 1024; + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, + va (ctx->va_ctx, "iqm:%s", + mod->name), + buff_size, ctx->cmdpool); + qfv_packet_t *gpacket = QFV_PacketAcquire (stage); + iqmgvert_t *gverts = QFV_PacketExtend (gpacket, geom_size); + qfv_packet_t *rpacket = QFV_PacketAcquire (stage); + iqmrvert_t *rverts = QFV_PacketExtend (rpacket, rend_size); + qfv_packet_t *epacket = QFV_PacketAcquire (stage); + uint16_t *elements = QFV_PacketExtend (epacket, elem_size); + //FIXME this whole thing is silly, but some person went and interleaved + //all the vertex data prematurely + for (int i = 0; i < iqm->num_verts; i++) { + byte *data = iqm->vertices + i * iqm->stride; + iqmgvert_t *gv = gverts + i; + iqmrvert_t *rv = rverts + i; + for (int j = 0; j < iqm->num_arrays; j++) { + __auto_type va = &iqm->vertexarrays[j]; + // FIXME assumes standard iqm sizes + size_t size = 0; + switch (va->type) { + case IQM_POSITION: + size = sizeof (gv->vertex); + memcpy (gv->vertex, data, size); + break; + case IQM_TEXCOORD: + size = sizeof (rv->uv); + memcpy (rv->uv, data, size); + break; + case IQM_NORMAL: + size = sizeof (rv->normal); + memcpy (rv->normal, data, size); + break; + case IQM_TANGENT: + size = sizeof (rv->tangent); + memcpy (rv->tangent, data, size); + break; + case IQM_BLENDINDEXES: + size = sizeof (gv->bones); + memcpy (gv->bones, data, size); + break; + case IQM_BLENDWEIGHTS: + size = sizeof (gv->weights); + memcpy (gv->weights, data, size); + break; + case IQM_COLOR: + size = sizeof (rv->color); + memcpy (rv->color, data, size); + break; + case IQM_CUSTOM: + // FIXME model loader doesn't handle these, so nothing to do + break; + } + data += size; + } + } + memcpy (elements, iqm->elements, elem_size); + + qfv_bufferbarrier_t bb[] = { + bufferBarriers[qfv_BB_Unknown_to_TransferWrite], + bufferBarriers[qfv_BB_Unknown_to_TransferWrite], + bufferBarriers[qfv_BB_Unknown_to_TransferWrite], + }; + bb[0].barrier.buffer = mesh->geom_buffer; + bb[0].barrier.size = geom_size; + bb[1].barrier.buffer = mesh->rend_buffer; + bb[1].barrier.size = rend_size; + bb[2].barrier.buffer = mesh->index_buffer; + bb[2].barrier.size = elem_size; + VkBufferCopy copy_region[] = { + { gpacket->offset, 0, geom_size }, + { rpacket->offset, 0, rend_size }, + { epacket->offset, 0, elem_size }, + }; + + dfunc->vkCmdPipelineBarrier (gpacket->cmd, bb[0].srcStages, bb[0].dstStages, + 0, 0, 0, 1, &bb[0].barrier, 0, 0); + dfunc->vkCmdPipelineBarrier (rpacket->cmd, bb[0].srcStages, bb[0].dstStages, + 0, 0, 0, 1, &bb[1].barrier, 0, 0); + dfunc->vkCmdPipelineBarrier (epacket->cmd, bb[0].srcStages, bb[0].dstStages, + 0, 0, 0, 1, &bb[2].barrier, 0, 0); + dfunc->vkCmdCopyBuffer (gpacket->cmd, stage->buffer, + mesh->geom_buffer, 1, ©_region[0]); + dfunc->vkCmdCopyBuffer (rpacket->cmd, stage->buffer, + mesh->rend_buffer, 1, ©_region[1]); + dfunc->vkCmdCopyBuffer (epacket->cmd, stage->buffer, + mesh->index_buffer, 1, ©_region[2]); + bb[0] = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead]; + bb[1] = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead]; + bb[2] = bufferBarriers[qfv_BB_TransferWrite_to_VertexAttrRead]; + bb[0].barrier.buffer = mesh->geom_buffer; + bb[0].barrier.size = geom_size; + bb[1].barrier.buffer = mesh->rend_buffer; + bb[1].barrier.size = rend_size; + bb[2].barrier.buffer = mesh->index_buffer; + bb[2].barrier.size = elem_size; + dfunc->vkCmdPipelineBarrier (gpacket->cmd, bb[0].srcStages, bb[0].dstStages, + 0, 0, 0, 1, &bb[0].barrier, 0, 0); + dfunc->vkCmdPipelineBarrier (rpacket->cmd, bb[0].srcStages, bb[0].dstStages, + 0, 0, 0, 1, &bb[1].barrier, 0, 0); + dfunc->vkCmdPipelineBarrier (epacket->cmd, bb[0].srcStages, bb[0].dstStages, + 0, 0, 0, 1, &bb[2].barrier, 0, 0); + QFV_PacketSubmit (gpacket); + QFV_PacketSubmit (rpacket); + QFV_PacketSubmit (epacket); + QFV_DestroyStagingBuffer (stage); + + vec4f_t *bone_data; + dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE, + 0, (void **)&bone_data); + for (int i = 0; i < 3 * iqm->num_joints; i++) { + vec4f_t *bone = bone_data + i * 3; + bone[0] = (vec4f_t) {1, 0, 0, 0}; + bone[1] = (vec4f_t) {0, 1, 0, 0}; + bone[2] = (vec4f_t) {0, 0, 1, 0}; + } + VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + mesh->bones->memory, 0, VK_WHOLE_SIZE, + }; + dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); + + dfunc->vkUnmapMemory (device->dev, mesh->bones->memory); +} + +void +Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + iqm_t *iqm = (iqm_t *) mod->aliashdr; + mod->clear = vulkan_iqm_clear; + mod->data = ctx; + + // FIXME assumes only one texture per mesh (currently the case, but + // when materials are added...) + // 2 is for image + image view + int num_objects = 4 + 2 * iqm->num_meshes; + qfv_iqm_t *mesh = calloc (1, sizeof (qfv_iqm_t) + + 2 * sizeof (qfv_resource_t) + + num_objects * sizeof (qfv_resobj_t) + + iqm->num_meshes * sizeof (qfv_iqm_skin_t)); + mesh->bones = (qfv_resource_t *) &mesh[1]; + mesh->mesh = &mesh->bones[1]; + + mesh->bones[0] = (qfv_resource_t) { + .name = mod->name, + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + .num_objects = 1, + .objects = (qfv_resobj_t *) &mesh->bones[2], + }; + mesh->bones->objects[0] = (qfv_resobj_t) { + .name = "bones", + .type = qfv_res_buffer, + .buffer = { + .size = 3 * iqm->num_joints * 3 * sizeof (vec4f_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + }, + }; + + mesh->mesh[0] = (qfv_resource_t) { + .name = "mesh", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = num_objects - 1, + .objects = mesh->bones->objects + 1, + }; + mesh->mesh->objects[0] = (qfv_resobj_t) { + .name = "geom", + .type = qfv_res_buffer, + .buffer = { + .size = iqm->num_verts * sizeof (iqmgvert_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + }, + }; + mesh->mesh->objects[1] = (qfv_resobj_t) { + .name = "rend", + .type = qfv_res_buffer, + .buffer = { + .size = iqm->num_verts * sizeof (iqmrvert_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + }, + }; + mesh->mesh->objects[2] = (qfv_resobj_t) { + .name = "index", + .type = qfv_res_buffer, + .buffer = { + .size = iqm->num_elements * sizeof (uint16_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + }, + }; + + for (int i = 0; i < iqm->num_meshes; i++) { + int image_ind = 3 + 2 * i; + __auto_type image = &mesh->mesh->objects[image_ind]; + vulkan_iqm_init_image (iqm, i, image); + + mesh->mesh->objects[image_ind + 1] = (qfv_resobj_t) { + .name = "view", + .type = qfv_res_image_view, + .image_view = { + .image = image_ind, + .type = VK_IMAGE_VIEW_TYPE_2D, + .format = mesh->mesh->objects[image_ind].image.format, + .aspect = VK_IMAGE_ASPECT_COLOR_BIT, + }, + }; + } + + mesh->skins = (qfv_iqm_skin_t *) &mesh->bones->objects[num_objects]; + + QFV_CreateResource (device, mesh->mesh); + QFV_CreateResource (device, mesh->bones); + mesh->geom_buffer = mesh->mesh->objects[0].buffer.buffer; + mesh->rend_buffer = mesh->mesh->objects[1].buffer.buffer; + mesh->index_buffer = mesh->mesh->objects[2].buffer.buffer; + + vulkan_iqm_load_textures (mod, iqm, mesh, ctx); + vulkan_iqm_load_arrays (mod, iqm, mesh, ctx); + + iqm->extra_data = mesh; +} diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index eceb2a1c2..5b3c981cd 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -91,7 +91,7 @@ libs_video_renderer_librender_gl_la_SOURCES = \ shader_src= libs/video/renderer/glsl/quakeforge.glsl shader_gen= libs/video/renderer/glsl/quakeforge.slc -SUFFICES += .frag .vert .spv .spvc .fc .vc .slc .glsl +SUFFIXES += .frag .vert .spv .spvc .fc .vc .slc .glsl .glsl.slc: $(V_SED)sed -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\ $(am__mv) $@.t $@ @@ -219,6 +219,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_bsp.c \ libs/video/renderer/vulkan/vulkan_compose.c \ libs/video/renderer/vulkan/vulkan_draw.c \ + libs/video/renderer/vulkan/vulkan_iqm.c \ libs/video/renderer/vulkan/vulkan_lighting.c \ libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ @@ -300,6 +301,10 @@ alias_gbuf_src = $(vkshaderpath)/alias_gbuf.frag alias_gbuf_c = $(vkshaderpath)/alias_gbuf.frag.spvc alias_shadow_src = $(vkshaderpath)/alias_shadow.vert alias_shadow_c = $(vkshaderpath)/alias_shadow.vert.spvc +iqmv_src = $(vkshaderpath)/iqm.vert +iqmv_c = $(vkshaderpath)/iqm.vert.spvc +iqmf_src = $(vkshaderpath)/iqm.frag +iqmf_c = $(vkshaderpath)/iqm.frag.spvc passthrough_src = $(vkshaderpath)/passthrough.vert passthrough_c = $(vkshaderpath)/passthrough.vert.spvc fstriangle_src = $(vkshaderpath)/fstriangle.vert @@ -359,6 +364,10 @@ $(alias_gbuf_c): $(alias_gbuf_src) $(alias_shadow_c): $(alias_shadow_src) +$(iqmv_c): $(iqmv_src) + +$(iqmf_c): $(iqmf_src) + $(passthrough_c): $(passthrough_src) $(fstriangle_c): $(fstriangle_src) @@ -395,6 +404,8 @@ vkshader_c = \ $(aliasf_c) \ $(alias_gbuf_c) \ $(alias_shadow_c) \ + $(iqmv_c) \ + $(iqmf_c) \ $(passthrough_c) \ $(fstriangle_c) \ $(pushcolor_c) \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 006e61d55..a4a880002 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -44,6 +44,7 @@ #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_compose.h" #include "QF/Vulkan/qf_draw.h" +#include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" @@ -560,6 +561,7 @@ vulkan_Mod_LoadExternalSkins (mod_alias_ctx_t *alias_ctx) static void vulkan_Mod_IQMFinish (model_t *mod) { + Vulkan_Mod_IQMFinish (mod, vulkan_ctx); } static void diff --git a/libs/video/renderer/vulkan/iqm.plist b/libs/video/renderer/vulkan/iqm.plist new file mode 100644 index 000000000..4467d8b89 --- /dev/null +++ b/libs/video/renderer/vulkan/iqm.plist @@ -0,0 +1,254 @@ +{ + setLayouts = { + texture_set = { + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + }; + pipelineLayouts = { + iqm_layout = { + setLayouts = (matrix_set, texture_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "3 * 4 + 2 * 4 * 4 + 4"; + }, + ); + }; + }; + + depthStencil = { + test_and_write = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + test_only = { + depthTestEnable = true; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + disable = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + }; + + inputAssembly = { + iqm = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + }; + + vertexInput = { + iqm = { + bindings = ( + { binding = 0; stride = 20; inputRate = vertex; }, + { binding = 1; stride = 40; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position + { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 0; }, // bonindices + { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, // boneweights + + { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord + { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal + { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent + { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color + + ); + }; + }; + + rasterization = { + cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + counter_cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + }; + + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + + attachmentBlendOp = { + disabled = { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + alpha_blend = { + blendEnable = true; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + }; + + pipelines = { + iqm_shadow = { + subpass = 0; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/iqm_shadow.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.vertexInput.iqm.bindings[0]", + "$properties.vertexInput.iqm.bindings[1]", + ); + attributes = ( + "$properties.vertexInput.iqm.attributes[0]", + "$properties.vertexInput.iqm.attributes[1]", + "$properties.vertexInput.iqm.attributes[2]", + "$properties.vertexInput.iqm.attributes[3]", + ); + }; + inputAssembly = $properties.inputAssembly.iqm; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_and_write; + colorBlend = $properties.pipelines.iqm_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = iqm_layout; + }; + iqm_depth = { + subpass = 0; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/iqm_depth.vert; + }, + ); + vertexInput = { + // depth pass doesn't use UVs + bindings = ( + "$properties.vertexInput.iqm.bindings[0]", + "$properties.vertexInput.iqm.bindings[1]", + ); + attributes = ( + "$properties.vertexInput.iqm.attributes[0]", + "$properties.vertexInput.iqm.attributes[1]", + "$properties.vertexInput.iqm.attributes[2]", + "$properties.vertexInput.iqm.attributes[3]", + ); + }; + inputAssembly = $properties.inputAssembly.iqm; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_and_write; + colorBlend = $properties.pipelines.iqm_gbuf.colorBlend; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + layout = iqm_layout; + renderPass = renderpass; + }; + iqm_gbuf = { + subpass = 2; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/iqm_gbuf.frag; + }, + ); + vertexInput = $properties.vertexInput.iqm; + inputAssembly = $properties.inputAssembly.iqm; + viewport = $properties.viewport; + rasterization = $properties.rasterization.cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.test_only; + colorBlend = { + logicOpEnable = false; + attachments = ( + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + ); + }; + dynamic = { + dynamicState = ( viewport, scissor, blend_constants ); + }; + layout = iqm_layout; + renderPass = renderpass; + }; + }; +} diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 8cab2d8a6..0f7e19a7b 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -93,6 +93,10 @@ static static #include "libs/video/renderer/vulkan/shader/alias_shadow.vert.spvc" static +#include "libs/video/renderer/vulkan/shader/iqm.vert.spvc" +static +#include "libs/video/renderer/vulkan/shader/iqm.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc" static #include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc" @@ -135,6 +139,8 @@ static shaderdata_t builtin_shaders[] = { { "alias.frag", alias_frag, sizeof (alias_frag) }, { "alias_gbuf.frag", alias_gbuf_frag, sizeof (alias_gbuf_frag) }, { "alias_shadow.vert", alias_shadow_vert, sizeof (alias_shadow_vert) }, + { "iqm.vert", iqm_vert, sizeof (iqm_vert) }, + { "iqm.frag", iqm_frag, sizeof (iqm_frag) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, diff --git a/libs/video/renderer/vulkan/shader/iqm.frag b/libs/video/renderer/vulkan/shader/iqm.frag new file mode 100644 index 000000000..7f897422c --- /dev/null +++ b/libs/video/renderer/vulkan/shader/iqm.frag @@ -0,0 +1,44 @@ +#version 450 + +layout (set = 1, binding = 0) uniform sampler2DArray Skin; + +layout (push_constant) uniform PushConstants { + layout (offset = 68) + uint colorA; + uint colorB; + vec4 base_color; + vec4 fog; +}; + +layout (location = 0) in vec2 texcoord; +layout (location = 1) in vec4 position; +layout (location = 2) in vec3 normal; +layout (location = 3) in vec3 tangent; +layout (location = 4) in vec3 bitangent; +layout (location = 5) in vec3 color; + +layout (location = 0) out vec4 frag_color; +layout (location = 1) out vec4 frag_emission; +layout (location = 2) out vec4 frag_normal; +layout (location = 3) out vec4 frag_position; + +void +main (void) +{ + vec4 c; + vec4 e; + vec3 n; + int i; + mat3 tbn = mat3 (tangent, bitangent, normal); + + c = texture (Skin, vec3 (texcoord, 0)) * base_color; + c += texture (Skin, vec3 (texcoord, 1)) * unpackUnorm4x8(colorA); + c += texture (Skin, vec3 (texcoord, 2)) * unpackUnorm4x8(colorB); + e = texture (Skin, vec3 (texcoord, 3)); + n = texture (Skin, vec3 (texcoord, 4)).xyz * 2 - 1; + + frag_color = c; + frag_emission = e; + frag_normal = vec4(tbn * n, 1); + frag_position = position; +} diff --git a/libs/video/renderer/vulkan/shader/iqm.vert b/libs/video/renderer/vulkan/shader/iqm.vert new file mode 100644 index 000000000..590c44118 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/iqm.vert @@ -0,0 +1,52 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; +}; + +layout (set = 3, binding = 0) buffer Bones { + // NOTE these are transposed, so v * m + mat3x4 bones[]; +}; + +layout (push_constant) uniform PushConstants { + mat4 Model; + float blend; +}; + +layout (location = 0) in vec3 vposition; +layout (location = 1) in ivec4 vbones; +layout (location = 2) in vec4 vweights; +layout (location = 3) in vec2 vtexcoord; +layout (location = 4) in vec3 vnormal; +layout (location = 5) in vec4 vtangent; +layout (location = 6) in vec4 vcolor; + +layout (location = 0) out vec2 texcoord; +layout (location = 1) out vec4 position; +layout (location = 2) out vec3 normal; +layout (location = 3) out vec3 tangent; +layout (location = 4) out vec3 bitangent; +layout (location = 5) out vec4 color; + +void +main (void) +{ + mat3x4 m = bones[vbones.x] * vweights.x; + m += bones[vbones.y] * vweights.y; + m += bones[vbones.z] * vweights.z; + m += bones[vbones.w] * vweights.w; + vec4 pos = vec4 (Model * vec4(vposition, 1) * m, 1); + gl_Position = Projection3d * (View * pos); + position = pos; + mat3 adjTrans = mat3 (cross(m[1].xyz, m[2].xyz), cross(m[2].xyz, m[0].xyz), + cross(m[0].xyz, m[1].xyz)); + normal = mat3 (Model) * vnormal * adjTrans; + tangent = mat3 (Model) * vtangent.xyz * adjTrans; + bitangent = cross (normal, tangent) * vtangent.w; + texcoord = vtexcoord; + color = vcolor; +} diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c new file mode 100644 index 000000000..0e19d4dd6 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -0,0 +1,310 @@ +/* + vulkan_iqm.c + + Vulkan IQM model pipeline + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/5/3 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/cvar.h" +#include "QF/va.h" + +#include "QF/scene/entity.h" + +#include "QF/Vulkan/qf_iqm.h" +#include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/renderpass.h" + +#include "r_internal.h" +#include "vid_vulkan.h" + +typedef struct { + mat4f_t mat; + float blend; + byte colorA[4]; + byte colorB[4]; + vec4f_t base_color; + vec4f_t fog; +} iqm_push_constants_t; + +static const char * __attribute__((used)) iqm_pass_names[] = { + "depth", + "g-buffer", + "translucent", +}; + +static QFV_Subpass subpass_map[] = { + QFV_passDepth, // QFV_iqmDepth + QFV_passGBuffer, // QFV_iqmGBuffer + QFV_passTranslucent, // QFV_iqmTranslucent +}; + +static void +emit_commands (VkCommandBuffer cmd, int pose1, int pose2, + qfv_iqm_skin_t **skins, + uint32_t numPC, qfv_push_constants_t *constants, + iqm_t *iqm, qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + iqmctx_t *ictx = ctx->iqm_context; + + __auto_type mesh = (qfv_iqm_t *) iqm->extra_data; + + VkDeviceSize offsets[] = { 0, 0, }; + VkBuffer buffers[] = { + mesh->geom_buffer, + mesh->rend_buffer, + }; + int bindingCount = skins ? 2 : 1; + + dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, + VK_INDEX_TYPE_UINT32); + QFV_PushConstants (device, cmd, ictx->layout, numPC, constants); + for (int i = 0; i < iqm->num_meshes; i++) { + if (skins) { + VkDescriptorSet sets[] = { + skins[i]->descriptor, + }; + dfunc->vkCmdBindDescriptorSets (cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + ictx->layout, 1, 1, sets, 0, 0); + } + dfunc->vkCmdDrawIndexed (cmd, 3 * iqm->meshes[i].num_triangles, 1, + 3 * iqm->meshes[i].first_triangle, 0, 0); + } +} + +void +Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + iqmctx_t *ictx = ctx->iqm_context; + iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; + model_t *model = ent->renderer.model; + iqm_t *iqm = (iqm_t *) model->aliashdr; + qfv_iqm_t *mesh = iqm->extra_data; + qfv_iqm_skin_t **skins = &mesh->skins; + iqm_push_constants_t constants = {}; + + constants.blend = R_IQMGetLerpedFrames (ent, iqm); + + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_VERTEX_BIT, + field_offset (iqm_push_constants_t, mat), + sizeof (mat4f_t), Transform_GetWorldMatrixPtr (ent->transform) }, + { VK_SHADER_STAGE_VERTEX_BIT, + field_offset (iqm_push_constants_t, blend), + sizeof (float), &constants.blend }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (iqm_push_constants_t, colorA), + sizeof (constants.colorA), constants.colorA }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (iqm_push_constants_t, colorB), + sizeof (constants.colorB), constants.colorB }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (iqm_push_constants_t, base_color), + sizeof (constants.base_color), &constants.base_color }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (iqm_push_constants_t, fog), + sizeof (constants.fog), &constants.fog }, + }; + + QuatCopy (ent->renderer.colormod, constants.base_color); + QuatCopy (skins[0]->colora, constants.colorA); + QuatCopy (skins[0]->colorb, constants.colorB); + QuatZero (constants.fog); + + emit_commands (aframe->cmdSet.a[QFV_iqmDepth], + ent->animation.pose1, ent->animation.pose2, + 0, 2, push_constants, iqm, rFrame); + emit_commands (aframe->cmdSet.a[QFV_iqmGBuffer], + ent->animation.pose1, ent->animation.pose2, + skins, 6, push_constants, iqm, rFrame); +} + +static void +alias_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, + qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + iqmctx_t *ictx = ctx->iqm_context; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; + iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = aframe->cmdSet.a[subpass]; + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + rFrame->renderpass->renderpass, subpass_map[subpass], + cframe->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "iqm:%s", + iqm_pass_names[subpass]), + { 0.6, 0.5, 0, 1}); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + VkDescriptorSet sets[] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + ictx->layout, 0, 1, sets, 0, 0); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); + + //XXX glsl_Fog_GetColor (fog); + //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; +} + +static void +alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + QFV_duCmdEndLabel (device, cmd); + dfunc->vkEndCommandBuffer (cmd); +} + +void +Vulkan_IQMBegin (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + iqmctx_t *ictx = ctx->iqm_context; + iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; + + //XXX quat_t fog; + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], + aframe->cmdSet.a[QFV_iqmDepth]); + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], + aframe->cmdSet.a[QFV_iqmGBuffer]); + + alias_begin_subpass (QFV_iqmDepth, ictx->depth, rFrame); + alias_begin_subpass (QFV_iqmGBuffer, ictx->gbuf, rFrame); +} + +void +Vulkan_IQMEnd (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + iqmctx_t *ictx = ctx->iqm_context; + iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; + + alias_end_subpass (aframe->cmdSet.a[QFV_iqmDepth], ctx); + alias_end_subpass (aframe->cmdSet.a[QFV_iqmGBuffer], ctx); +} + +void +Vulkan_IQMAddSkin (vulkan_ctx_t *ctx, qfv_iqm_skin_t *skin) +{ + iqmctx_t *ictx = ctx->iqm_context; + skin->descriptor = Vulkan_CreateCombinedImageSampler (ctx, skin->view, + ictx->sampler); +} + +void +Vulkan_IQMRemoveSkin (vulkan_ctx_t *ctx, qfv_iqm_skin_t *skin) +{ + Vulkan_FreeTexture (ctx, skin->descriptor); + skin->descriptor = 0; +} + +void +Vulkan_IQM_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + qfvPushDebug (ctx, "iqm init"); + + iqmctx_t *ictx = calloc (1, sizeof (iqmctx_t)); + ctx->iqm_context = ictx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&ictx->frames, frames); + DARRAY_RESIZE (&ictx->frames, frames); + ictx->frames.grow = 0; + + ictx->depth = Vulkan_CreateGraphicsPipeline (ctx, "alias_depth"); + ictx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "alias_gbuf"); + ictx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); + ictx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); + + for (size_t i = 0; i < frames; i++) { + __auto_type aframe = &ictx->frames.a[i]; + + DARRAY_INIT (&aframe->cmdSet, QFV_iqmNumPasses); + DARRAY_RESIZE (&aframe->cmdSet, QFV_iqmNumPasses); + aframe->cmdSet.grow = 0; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &aframe->cmdSet); + + for (int j = 0; j < QFV_iqmNumPasses; j++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + aframe->cmdSet.a[j], + va (ctx->va_ctx, "cmd:iqm:%zd:%s", i, + iqm_pass_names[j])); + } + } + qfvPopDebug (ctx); +} + +void +Vulkan_IQM_Shutdown (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + iqmctx_t *ictx = ctx->iqm_context; + + for (size_t i = 0; i < ictx->frames.size; i++) { + __auto_type aframe = &ictx->frames.a[i]; + free (aframe->cmdSet.a); + } + + dfunc->vkDestroyPipeline (device->dev, ictx->depth, 0); + dfunc->vkDestroyPipeline (device->dev, ictx->gbuf, 0); + free (ictx->frames.a); + free (ictx); +} From ecf33fe8e33f6ae38f0d41a75e1a88cb4fab83c0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 14:13:18 +0900 Subject: [PATCH 2731/3664] [model] Add a function to "unload" models The model system is rather clunky as it is focused around caching, so unloading is more of a suggestion than anything, but it was good enough for testing loading and unloading of IQM models in Vulkan. --- include/QF/model.h | 1 + libs/models/model.c | 41 ++++++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 66628d37c..2489dfb88 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -438,6 +438,7 @@ void Mod_Init_Cvars (void); void Mod_ClearAll (void); model_t *Mod_ForName (const char *name, qboolean crash); void Mod_TouchModel (const char *name); +void Mod_UnloadModel (model_t *model); // brush specific mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure)); struct set_s *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model); diff --git a/libs/models/model.c b/libs/models/model.c index ee8969543..86e4c7f5b 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -138,22 +138,31 @@ Mod_Init_Cvars (void) Cvar_Register (&gl_textures_external_cvar, 0, 0); } +static void +mod_unload_model (size_t ind) +{ + model_t *mod = mod_known.a[ind]; + + //FIXME this seems to be correct but need to double check the behavior + //with alias models + if (!mod->needload && mod->clear) { + mod->clear (mod, mod->data); + } + if (mod->type != mod_alias) { + mod->needload = true; + } + if (mod->type == mod_sprite) { + mod->cache.data = 0; + } +} + VISIBLE void Mod_ClearAll (void) { size_t i; - model_t **mod; - for (i = 0, mod = mod_known.a; i < mod_numknown; i++, mod++) { - //FIXME this seems to be correct but need to double check the behavior - //with alias models - if (!(*mod)->needload && (*mod)->clear) { - (*mod)->clear (*mod, (*mod)->data); - } - if ((*mod)->type != mod_alias) - (*mod)->needload = true; - if ((*mod)->type == mod_sprite) - (*mod)->cache.data = 0; + for (i = 0; i < mod_numknown; i++) { + mod_unload_model (i); } } @@ -323,6 +332,16 @@ Mod_TouchModel (const char *name) } } +VISIBLE void +Mod_UnloadModel (model_t *model) +{ + for (size_t i = 0; i < mod_numknown; i++) { + if (mod_known.a[i] == model) { + mod_unload_model (i); + } + } +} + VISIBLE void Mod_Print (void) { From 3de10f32c7cddb7d508e86acec0d1c50d94eaa8e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 14:15:45 +0900 Subject: [PATCH 2732/3664] [ruamoko] Add builtins for handling models Just "loading" and "unloading" (both really just hints due to the caching system), and an internal function for converting a handle to a model pointer, but it let me test IQM loading and unloading in Vulkan. --- include/rua_internal.h | 2 + libs/ruamoko/Makemodule.am | 1 + libs/ruamoko/rua_game_init.c | 1 + libs/ruamoko/rua_model.c | 179 +++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+) create mode 100644 libs/ruamoko/rua_model.c diff --git a/include/rua_internal.h b/include/rua_internal.h index b58eb4530..80f97003a 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -62,6 +62,8 @@ struct plitem_s *Plist_GetItem (struct progs_s *pr, int handle); void RUA_Input_Init (struct progs_s *pr, int secure); void RUA_Mersenne_Init (struct progs_s *pr, int secure); +void RUA_Model_Init (struct progs_s *pr, int secure); +struct model_s *Model_GetModel (progs_t *pr, int handle); void RUA_Scene_Init (struct progs_s *pr, int secure); #endif//__rua_internal_h diff --git a/libs/ruamoko/Makemodule.am b/libs/ruamoko/Makemodule.am index 118fde38c..c34590426 100644 --- a/libs/ruamoko/Makemodule.am +++ b/libs/ruamoko/Makemodule.am @@ -38,4 +38,5 @@ libs_ruamoko_libQFruamoko_client_la_SOURCES= \ libs/ruamoko/rua_game_init.c \ libs/ruamoko/rua_input.c \ libs/ruamoko/rua_mersenne.c \ + libs/ruamoko/rua_model.c \ libs/ruamoko/rua_scene.c diff --git a/libs/ruamoko/rua_game_init.c b/libs/ruamoko/rua_game_init.c index ac1628cc8..1312d7ee3 100644 --- a/libs/ruamoko/rua_game_init.c +++ b/libs/ruamoko/rua_game_init.c @@ -36,6 +36,7 @@ static void (*init_funcs[])(progs_t *, int) = { RUA_Input_Init, RUA_Mersenne_Init, + RUA_Model_Init, RUA_Scene_Init, }; diff --git a/libs/ruamoko/rua_model.c b/libs/ruamoko/rua_model.c new file mode 100644 index 000000000..e021ba9d5 --- /dev/null +++ b/libs/ruamoko/rua_model.c @@ -0,0 +1,179 @@ +/* + bi_model.c + + Ruamkoko model builtins + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/model.h" +#include "QF/progs.h" + +#include "rua_internal.h" + +typedef struct rua_model_s { + struct rua_model_s *next; + struct rua_model_s **prev; + model_t *model; +} rua_model_t; + +typedef struct { + PR_RESMAP (rua_model_t) model_map; + rua_model_t *handles; + progs_t *pr; +} rua_model_resources_t; + +static rua_model_t * +rua_model_handle_new (rua_model_resources_t *res) +{ + return PR_RESNEW (res->model_map); +} + +static void +rua_model_handle_free (rua_model_resources_t *res, rua_model_t *handle) +{ + PR_RESFREE (res->model_map, handle); +} + +static void +rua_model_handle_reset (rua_model_resources_t *res) +{ + PR_RESRESET (res->model_map); +} + +static inline rua_model_t * __attribute__((pure)) +rua__model_handle_get (rua_model_resources_t *res, int index, const char *name) +{ + rua_model_t *handle = 0; + + handle = PR_RESGET(res->model_map, index); + if (!handle) { + PR_RunError (res->pr, "invalid model handle passed to %s", name + 3); + } + return handle; +} +#define rua_model_handle_get(res, index) \ + rua__model_handle_get (res, index, __FUNCTION__) + +static inline int __attribute__((pure)) +rua_model_handle_index (rua_model_resources_t *res, rua_model_t *handle) +{ + return PR_RESINDEX(res->model_map, handle); +} + +static void +bi_rua_model_clear (progs_t *pr, void *_res) +{ + rua_model_resources_t *res = (rua_model_resources_t *) _res; + rua_model_t *handle; + + for (handle = res->handles; handle; handle = handle->next) + Mod_UnloadModel (handle->model); + res->handles = 0; + rua_model_handle_reset (res); +} + +static int +alloc_handle (rua_model_resources_t *res, model_t *model) +{ + rua_model_t *handle = rua_model_handle_new (res); + + if (!handle) + return 0; + + handle->next = res->handles; + handle->prev = &res->handles; + if (res->handles) + res->handles->prev = &handle->next; + res->handles = handle; + handle->model = model; + return rua_model_handle_index (res, handle); +} + +static void +bi_Model_Load (progs_t *pr, void *_res) +{ + __auto_type res = (rua_model_resources_t *) _res; + const char *path = P_GSTRING (pr, 0); + model_t *model; + + R_INT (pr) = 0; + if (!(model = Mod_ForName (path, 0))) + return; + if (!(R_INT (pr) = alloc_handle (res, model))) + Mod_UnloadModel (model); +} + +model_t * +Model_GetModel (progs_t *pr, int handle) +{ + rua_model_resources_t *res = PR_Resources_Find (pr, "Model"); + rua_model_t *h = rua_model_handle_get (res, handle); + + return h->model; +} + +static void +bi_Model_Unload (progs_t *pr, void *_res) +{ + __auto_type res = (rua_model_resources_t *) _res; + int handle = P_INT (pr, 0); + rua_model_t *h = rua_model_handle_get (res, handle); + + if (!h) + PR_RunError (pr, "invalid model handle passed to Qclose"); + Mod_UnloadModel (h->model); + *h->prev = h->next; + if (h->next) + h->next->prev = h->prev; + rua_model_handle_free (res, h); +} + +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } +static builtin_t builtins[] = { + bi(Model_Load, 1, p(string)), + bi(Model_Unload, 1, p(ptr)), + {0} +}; + +void +RUA_Model_Init (progs_t *pr, int secure) +{ + rua_model_resources_t *res = calloc (sizeof (rua_model_resources_t), 1); + res->pr = pr; + + PR_Resources_Register (pr, "Model", res, bi_rua_model_clear); + PR_RegisterBuiltins (pr, builtins, res); +} From 0983cc5d8c41f0a2973cb17d026f1d89c0b8762d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 14:17:19 +0900 Subject: [PATCH 2733/3664] [scene] Fix a spelling error in a comment --- libs/scene/hierarchy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 3aa758624..c6b6f7074 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -80,7 +80,7 @@ hierarchy_calcLocalInverse (hierarchy_t *h, uint32_t index) vec4f_t t = h->localMatrix.a[index][3]; // "one" is to ensure both the scalar and translation have 1 in their - // forth components + // fourth components vec4f_t one = { 0, 0, 0, 1 }; vec4f_t nx = { x[0], y[0], z[0], 0 }; vec4f_t ny = { x[1], y[1], z[1], 0 }; From c10e529dfd95a5745602b351093b1f97ef051bed Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 14:18:05 +0900 Subject: [PATCH 2734/3664] [vulkan] Clean up alias pipeline layout spec It didn't really need the extra layer of indirection: now it's much clearer that the alias pipeline uses matrices and textures. --- libs/video/renderer/vulkan/qfpipeline.plist | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 876613b98..ce3a7dcff 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -206,8 +206,6 @@ }, ); }; - quakebsp_set = $properties.setLayouts.texture_set; - alias_set = $properties.setLayouts.texture_set; sprite_set = { bindings = ( { @@ -337,7 +335,7 @@ ); }; alias_layout = { - setLayouts = (matrix_set, alias_set); + setLayouts = (matrix_set, texture_set); pushConstantRanges = ( { stageFlags = vertex; From e95d498b974a510de7dce102c8c524905e056199 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 14:28:20 +0900 Subject: [PATCH 2735/3664] [vulkan] Resurrect the forward render pass spec It's not used yet, and thus may have some incorrect settings, but I decided that I will probably want it at some stage for qwaq. It's essentially was was in the original spec, but updated for some of the niceties added to parsing since I removed it back then. It's also in its own file. --- libs/video/renderer/vulkan/forward.plist | 199 +++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 libs/video/renderer/vulkan/forward.plist diff --git a/libs/video/renderer/vulkan/forward.plist b/libs/video/renderer/vulkan/forward.plist new file mode 100644 index 000000000..e8c703a23 --- /dev/null +++ b/libs/video/renderer/vulkan/forward.plist @@ -0,0 +1,199 @@ +{ + flat_color_image_template = { + imageType = `2d; + samples = $msaaSamples; + extent = { + width = $output.extent.width; + height = $output.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|transient_attachment; + }; + images = { + depth = { + @inherit = @properties.flat_color_image_template; + format = x8_d24_unorm_pack32; + usage = depth_stencil_attachment|transient_attachment; + }; + color = { + @inherit = @properties.flat_color_image_template; + format = $output.format; + }; + }; + flat_color_view_template = { + viewType = `2d; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + imageViews = { + depth = { + @inherit = $properties.flat_color_view_template; + image = depth; + format = $properties.images.depth.format; + subresourceRange = { + aspectMask = depth; + }; + }; + color = { + @inherit = $properties.flat_color_view_template; + image = color; + format = $properties.images.color.format; + }; + }; + framebuffer = { + renderPass = $properties.renderpass; + attachment = ($output.view, depth); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; + }; + framebuffer_msaa = { + renderPass = $properties.renderpass_msaa; + attachment = ($output.view, depth, color); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; + }; + attachment_template = { + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }; + renderpass = { + attachments = ( + { + @inherit = $properties.attachment_template; + format = $output.format; + loadOp = clear; + storeOp = store; + finalLayout = present_src_khr; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.depth.format; + loadOp = clear; + finalLayout = depth_stencil_attachment_optimal; + }, + ); + subpasses = ( + { + pipelineBindPoint = graphics; + colorAttachments = ( + { + attachment = 0; + layout = color_attachment_optimal; + } + ); + depthStencilAttachment = { + attachment = 1; + layout = depth_stencil_attachment_optimal; + }; + preserveAttachments = (); + }, + ); + dependencies = ( + { + srcSubpass = ~0u; // external + dstSubpass = 0; + srcStageMask = top_of_pipe; + dstStageMask = color_attachment_output; + srcAccessMask = memory_read; + dstAccessMask = color_attachment_write; + dependencyFlags = by_region; + }, + { + srcSubpass = 0; + dstSubpass = ~0u; // external + srcStageMask = color_attachment_output; + dstStageMask = bottom_of_pipe; + srcAccessMask = color_attachment_write; + dstAccessMask = memory_read; + dependencyFlags = by_region; + }, + ); + }; + renderpass_msaa = { + attachments = ( + { + @inherit = $properties.attachment_template; + format = $output.format; + storeOp = store; + finalLayout = present_src_khr; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.depth.format; + samples = $msaaSamples; + loadOp = clear; + storeOp = dont_care; + finalLayout = depth_stencil_attachment_optimal; + }, + { + @inherit = $properties.attachment_template; + format = $swapchain.format; + samples = $msaaSamples; + loadOp = clear; + storeOp = store;// dont_care? + finalLayout = color_attachment_optimal; + }, + ); + subpasses = ( + { + pipelineBindPoint = graphics; + colorAttachments = ( + { + attachment = 2; + layout = color_attachment_optimal; + } + ); + resolveAttachments = ( + { + attachment = 0; + layout = color_attachment_optimal; + } + ); + depthStencilAttachment = { + attachment = 1; + layout = depth_stencil_attachment_optimal; + }; + preserveAttachments = (); + }, + ); + dependencies = ( + { + srcSubpass = ~0u; // external + dstSubpass = 0; + srcStageMask = top_of_pipe; + dstStageMask = color_attachment_output; + srcAccessMask = memory_read; + dstAccessMask = color_attachment_write; + dependencyFlags = by_region; + }, + { + srcSubpass = 0; + dstSubpass = ~0u; // external + srcStageMask = color_attachment_output; + dstStageMask = bottom_of_pipe; + srcAccessMask = color_attachment_write; + dstAccessMask = memory_read; + dependencyFlags = by_region; + }, + ); + }; +} From 2d75a652f100d4da13a18da1f789b1c159d76fff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 14:36:14 +0900 Subject: [PATCH 2736/3664] [vulkan] Remove a dead file I guess I forgot to delete draw.h when I added qf_draw.h. --- include/QF/Makemodule.am | 1 - include/QF/Vulkan/draw.h | 237 --------------------------------------- 2 files changed, 238 deletions(-) delete mode 100644 include/QF/Vulkan/draw.h diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index b18a43f55..c9783b4fa 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -178,7 +178,6 @@ include_qf_vulkan = \ include/QF/Vulkan/debug.h \ include/QF/Vulkan/descriptor.h \ include/QF/Vulkan/device.h \ - include/QF/Vulkan/draw.h \ include/QF/Vulkan/funclist.h \ include/QF/Vulkan/image.h \ include/QF/Vulkan/instance.h \ diff --git a/include/QF/Vulkan/draw.h b/include/QF/Vulkan/draw.h deleted file mode 100644 index 8f6b78889..000000000 --- a/include/QF/Vulkan/draw.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - draw.h - - Video buffer handling definitions and prototypes - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ - -#ifndef __QF_draw_h -#define __QF_draw_h - -/** \defgroup video Video Sub-sytem */ - -/** \defgroup video_renderer Renderer Sub-system - \ingroup video -*/ - -/** \defgroup video_renderer_draw Generic draw functions - \ingroup video_renderer -*/ -///@{ - -#include "QF/wad.h" - -extern byte *draw_chars; - -/** Initialize the draw stuff. -*/ -void Draw_Init (void); - -/** Draws one 8*8 graphics character with 0 being transparent. - It can be clipped to the top of the screen to allow the console to be - smoothly scrolled off. - \param x horizontal location of the top left corner of the character. - \param y vertical location of the top left corner of the character. - \param ch 8 bit character to draw. - \note The character drawn is from the quake character set, which is - (by default) standard ascii for 0x20-0x7e (white). 0xa0-0xfe is - also standard ascii (brown). 0x01-0x1f and 0x80-0x9f are - various drawing characters, and 0x7f is a backwards arrow. -*/ -void Draw_Character (int x, int y, unsigned ch); - -/** Draws a character string to the screen. - No line wrapping is performed. - \param x horizontal location of the top left corner of the character. - \param y vertical location of the top left corner of the character. - \param str 8 bit character string to draw. - \note See Draw_Character() for character set description. - String is normal nul terminated C string. -*/ -void Draw_String (int x, int y, const char *str); - -/** Draws a character sub-string to the screen. - No line wrapping is performed. - \param x horizontal location of the top left corner of the character. - \param y vertical location of the top left corner of the character. - \param str 8 bit character string to draw. - \param count Maximum characters of the string to draw. - \note See Draw_Character() for character set description. - Draws up to \p count characters, or stops at the first nul - character. -*/ -void Draw_nString (int x, int y, const char *str, int count); - -/** Draws a character string to the screen. - No line wrapping is performed. - \param x horizontal location of the top left corner of the character. - \param y vertical location of the top left corner of the character. - \param str 8 bit character string to draw. - \note See Draw_Character() for character set description. - String is normal nul terminated C string. - Characters of the string are forced to have their high bit set - (ie, they will be in the range 0x80-0xff). -*/ -void Draw_AltString (int x, int y, const char *str); - -/** Draw the console background with various optional effects. - \param lines Vertical size in pixels of the console. - \param alpha Console transparency level (255 = opaque). - \note \p alpha is effective only in the OpenGL renderer. Effectively - 255 (opaque) for the software renderer. - - \c gl_conspin causes the background to spin. - - \c gl_constretch causes the background to stretch rather than slide. -*/ -void Draw_ConsoleBackground (int lines, byte alpha); - -/** Draw a crosshair at the center of the screen. - \c crosshair specifies which crosshair (1 = '+', 2 = large 'x' shape, - 3 = fancy '+' shape) - \c cl_crossx and \c cl_crossy offset the crosshair from the center of the - screen. -*/ -void Draw_Crosshair (void); - -/** Draw the specified crosshair on the screen. - \param ch crosshair to draw - \param x horizontal position of the center of the crosshair. - \param y vertical position of the center of the crosshair. - - See Draw_Crosshair() for description of crosshair values. -*/ -void Draw_CrosshairAt (int ch, int x, int y); - -/** Clear a rectangle with a tiled background. - \param x horizontal position of the upper left corner of the rectangle - \param y horizontal position of the upper left corner of the rectangle - \param w width of the rectangle - \param h height of the rectangle - - The background used is the "backtile" WAD lump. -*/ -void Draw_TileClear (int x, int y, int w, int h); - -/** Clear a rectangle with a solid color. - \param x horizontal position of the upper left corner of the rectangle - \param y horizontal position of the upper left corner of the rectangle - \param w width of the rectangle - \param h height of the rectangle - \param c 8 bit color index. - - The color comes from the quake palette. -*/ -void Draw_Fill (int x, int y, int w, int h, int c); - -/** Draw a text box on the screen - \param x horizontal location of the upper left corner of the box - \param y vertical location of the upper left corner of the box - \param width horizontal size in character cells of the region - \param lines vertical size in character cells of the region - \param alpha transparency of the box -*/ -void Draw_TextBox (int x, int y, int width, int lines, byte alpha); - -/** Darken the screen. -*/ -void Draw_FadeScreen (void); - -/** Shift the screen colors. -*/ -void Draw_BlendScreen (quat_t color); -///@} - -/** \defgroup video_renderer_draw_qpic QPic functions - \ingroup video_renderer_draw -*/ -///@{ -/** Load a qpic from the filesystem. - \param path path of the file within the quake filesystem - \param alpha transparency level of the pic. - \return pointer qpic data. - \note Up to MAX_CACHED_PICS qpics can be loaded at a time this way -*/ -qpic_t *Draw_CachePic (const char *path, qboolean alpha); - -/** Remove a qpic from the qpic cache. - - This affects only those qpics that were loaded via Draw_CachePic. - - \param path path of the file within the quake filesystem -*/ -void Draw_UncachePic (const char *path); - -/** Create a qpic from raw data. - - \param width The width of the pic. - \param height The height of the pic. - \param data The raw data bytes. The system palette will be used for - colors. - \return pointer qpic data. -*/ -qpic_t *Draw_MakePic (int width, int height, const byte *data); - -/** Destroy a qpic created by Draw_MakePic. - - \param pic The qpic to destory. -*/ -void Draw_DestroyPic (qpic_t *pic); - -/** Load a qpic from gfx.wad. - \param name name of the was lump to load - \return pointer qpic data. -*/ -qpic_t *Draw_PicFromWad (const char *name); - -/** Draw a qpic to the screen - \param x horizontal location of the upper left corner of the qpic - \param y vertical location of the upper left corner of the qpic - \param pic qpic to draw -*/ -void Draw_Pic (int x, int y, qpic_t *pic); - -/** Draw a qpic to the screen - \param x horizontal location of the upper left corner of the qpic - \param y vertical location of the upper left corner of the qpic - \param pic qpic to draw -*/ -void Draw_Picf (float x, float y, qpic_t *pic); - -/** Draw a sub-region of a qpic to the screan - \param x horizontal screen location of the upper left corner of the - sub-region - \param y vertical screen location of the upper left corner of the - sub-region - \param pic qpic to draw - \param srcx horizontal qpic location of the upper left corner of the - sub-region - \param srcy vertical qpic location of the upper left corner of the - sub-region - \param width horizontal size of the sub-region to be drawn - \param height vertical size of the sub-region to be drawn -*/ -void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); -///@} - -#endif//__QF_draw_h From 8e658eac7801cf9ef0bd6e57dfbedf138fd1c669 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 14:39:47 +0900 Subject: [PATCH 2737/3664] [vulkan] Correct a pile of copyright attributions Id Software had pretty much nothing to do with the vulkan renderer (they still get credit for code that's heavily based on the original quake code, of course). --- include/QF/Vulkan/qf_vid.h | 2 +- libs/video/renderer/vid_render_vulkan.c | 3 +-- libs/video/renderer/vulkan/buffer.c | 1 - libs/video/renderer/vulkan/capture.c | 1 - libs/video/renderer/vulkan/command.c | 1 - libs/video/renderer/vulkan/descriptor.c | 1 - libs/video/renderer/vulkan/device.c | 1 - libs/video/renderer/vulkan/image.c | 1 - libs/video/renderer/vulkan/memory.c | 1 - libs/video/renderer/vulkan/pipeline.c | 1 - libs/video/renderer/vulkan/renderpass.c | 1 - 11 files changed, 2 insertions(+), 12 deletions(-) diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index bf76b13d2..6f235d1b6 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -3,7 +3,7 @@ vulkan vid stuff from the renderer. - Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2019 Bill Currie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a4a880002..424363571 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -771,8 +771,7 @@ static plugin_t plugin_info = { QFPLUGIN_VERSION, "0.1", "Vulkan Renderer", - "Copyright (C) 1996-1997 Id Software, Inc.\n" - "Copyright (C) 1999-2019 contributors of the QuakeForge project\n" + "Copyright (C) 2019 Bill Currie \n" "Please see the file \"AUTHORS\" for a list of contributors", &plugin_info_funcs, &plugin_info_data, diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index 729fe914d..30030adee 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -3,7 +3,6 @@ Vulkan buffer functions - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2020 Bill Currie This program is free software; you can redistribute it and/or diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c index d11ea7ad9..974957aa7 100644 --- a/libs/video/renderer/vulkan/capture.c +++ b/libs/video/renderer/vulkan/capture.c @@ -3,7 +3,6 @@ Vulkan frame capture support - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2021 Bill Currie This program is free software; you can redistribute it and/or diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 0dae2bc5e..c35fede96 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -3,7 +3,6 @@ Common Vulkan video driver functions - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2019 Bill Currie This program is free software; you can redistribute it and/or diff --git a/libs/video/renderer/vulkan/descriptor.c b/libs/video/renderer/vulkan/descriptor.c index 356fa5f40..026d5ae9c 100644 --- a/libs/video/renderer/vulkan/descriptor.c +++ b/libs/video/renderer/vulkan/descriptor.c @@ -3,7 +3,6 @@ Vulkan descriptor functions - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2020 Bill Currie This program is free software; you can redistribute it and/or diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 6f632ef34..0ff989511 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -3,7 +3,6 @@ Common Vulkan video driver functions - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2019 Bill Currie This program is free software; you can redistribute it and/or diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 27bb3cf7b..62daaaf38 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -3,7 +3,6 @@ Vulkan image functions - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2020 Bill Currie This program is free software; you can redistribute it and/or diff --git a/libs/video/renderer/vulkan/memory.c b/libs/video/renderer/vulkan/memory.c index dbcc81de6..ee2d6ec01 100644 --- a/libs/video/renderer/vulkan/memory.c +++ b/libs/video/renderer/vulkan/memory.c @@ -3,7 +3,6 @@ Vulkan memory functions - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2020 Bill Currie This program is free software; you can redistribute it and/or diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c index 5130a55c2..b602287f6 100644 --- a/libs/video/renderer/vulkan/pipeline.c +++ b/libs/video/renderer/vulkan/pipeline.c @@ -3,7 +3,6 @@ Vulkan pipeline functions - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2020 Bill Currie This program is free software; you can redistribute it and/or diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index ead9a7363..e0a95db8d 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -3,7 +3,6 @@ Vulkan render pass and frame buffer functions - Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 2020 Bill Currie This program is free software; you can redistribute it and/or From 3b926ec154e3ec157647e6653bacbc6a120f036e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 14:42:50 +0900 Subject: [PATCH 2738/3664] [io_mesh_qfmdl] Update plist parsing for ` This gets it pretty much in line with the C implementation. Certainly good enough for validating a render pass spec :) --- tools/io_mesh_qfmdl/qfplist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/io_mesh_qfmdl/qfplist.py b/tools/io_mesh_qfmdl/qfplist.py index 4f16a2c34..7e5ffc762 100644 --- a/tools/io_mesh_qfmdl/qfplist.py +++ b/tools/io_mesh_qfmdl/qfplist.py @@ -20,7 +20,7 @@ # quotables = ("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - + "abcdefghijklmnopqrstuvwxyz!#$%&*+-./:?@|~_^") + + "`abcdefghijklmnopqrstuvwxyz!#$%&*+-./:?@|~_^") class PListError(Exception): def __init__(self, line, message): From 2493ca71c7257143e640c9c7d9c4974db9b6a427 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 17:38:38 +0900 Subject: [PATCH 2739/3664] [ruamoko] Allow entity model to be set And add header and function definitions for scene to libcsqc. --- libs/ruamoko/rua_model.c | 3 ++ libs/ruamoko/rua_scene.c | 19 ++++++++++++ ruamoko/include/Makemodule.am | 3 +- ruamoko/include/scene.h | 54 +++++++++++++++++++++++++++++++++++ ruamoko/lib/Makemodule.am | 1 + ruamoko/lib/scene.r | 40 ++++++++++++++++++++++++++ 6 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 ruamoko/include/scene.h create mode 100644 ruamoko/lib/scene.r diff --git a/libs/ruamoko/rua_model.c b/libs/ruamoko/rua_model.c index e021ba9d5..4f8d5b8c0 100644 --- a/libs/ruamoko/rua_model.c +++ b/libs/ruamoko/rua_model.c @@ -137,6 +137,9 @@ bi_Model_Load (progs_t *pr, void *_res) model_t * Model_GetModel (progs_t *pr, int handle) { + if (!handle) { + return 0; + } rua_model_resources_t *res = PR_Resources_Find (pr, "Model"); rua_model_t *h = rua_model_handle_get (res, handle); diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index d43a4da7b..1c577d6fd 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -38,7 +38,11 @@ #include "QF/cmem.h" #include "QF/hash.h" +#include "QF/model.h" #include "QF/progs.h" +#include "QF/render.h" + +#include "QF/plugin/vid_render.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" @@ -209,6 +213,20 @@ bi_Entity_GetTransform (progs_t *pr, void *_res) R_ULONG (pr) = MAKE_ID (ent->transform->id, ent_id); } +static void +bi_Entity_SetModel (progs_t *pr, void *_res) +{ + rua_scene_resources_t *res = _res; + pr_ulong_t ent_id = P_ULONG (pr, 0); + pr_int_t model_id = P_INT (pr, 1); + entity_t *ent = rua_entity_get (res, ent_id); + model_t *model = Model_GetModel (pr, model_id); + + R_RemoveEfrags (ent); + ent->renderer.model = model; + R_AddEfrags (&r_data->refdef->worldmodel->brush, ent);//FIXME r_data +} + static void bi_Transform_ChildCount (progs_t *pr, void *_res) { @@ -431,6 +449,7 @@ static builtin_t builtins[] = { bi(Scene_DestroyEntity, 1, p(ulong)), bi(Entity_GetTransform, 1, p(ulong)), + bi(Entity_SetModel, 2, p(ulong), p(int)), bi(Transform_ChildCount, 1, p(ulong)), bi(Transform_GetChild, 2, p(ulong), p(int)), diff --git a/ruamoko/include/Makemodule.am b/ruamoko/include/Makemodule.am index 800c8ba89..8d19564d0 100644 --- a/ruamoko/include/Makemodule.am +++ b/ruamoko/include/Makemodule.am @@ -16,8 +16,9 @@ ruamoko_include = \ ruamoko/include/qw_physics.h \ ruamoko/include/qw_sys.h \ ruamoko/include/server.h \ - ruamoko/include/sound.h \ + ruamoko/include/scene.h \ ruamoko/include/script.h \ + ruamoko/include/sound.h \ ruamoko/include/stdlib.h \ ruamoko/include/string.h \ ruamoko/include/sv_sound.h \ diff --git a/ruamoko/include/scene.h b/ruamoko/include/scene.h new file mode 100644 index 000000000..cf66b5d82 --- /dev/null +++ b/ruamoko/include/scene.h @@ -0,0 +1,54 @@ +#ifndef __ruamoko_scene_h +#define __ruamoko_scene_h + +//FIXME this should be a native type so it can be used in math +typedef struct { + vec4 col[4]; +} mat4x4; + +//FIXME need a handle type +typedef struct { long handle; } scene_t; +typedef struct { long handle; } entity_t; +typedef struct { long handle; } transform_t; +typedef struct { int handle; } model_t; + +scene_t Scene_NewScene (void); +void Scene_DeleteScene (scene_t scene); +entity_t Scene_CreateEntity (scene_t scene); +void Scene_DestroyEntity (entity_t ent); + +transform_t Entity_GetTransform (entity_t ent); +void Entity_SetModel (entity_t ent, model_t model); + +unsigned Transform_ChildCount (transform_t transform); +transform_t Transform_GetChild (transform_t transform, + unsigned childIndex); +void Transform_SetParent (transform_t transform, transform_t parent); +transform_t Transform_GetParent (transform_t transform); +void Transform_SetTag (transform_t transform, unsigned tag); +unsigned Transform_GetTag (transform_t transform); +mat4x4 Transform_GetLocalMatrix (transform_t transform); +mat4x4 Transform_GetLocalInverse (transform_t transform); +mat4x4 Transform_GetWorldMatrix (transform_t transform); +mat4x4 Transform_GetWorldInverse (transform_t transform); +vec4 Transform_GetLocalPosition (transform_t transform); +void Transform_SetLocalPosition (transform_t transform, vec4 position); +vec4 Transform_GetLocalRotation (transform_t transform); +void Transform_SetLocalRotation (transform_t transform, vec4 rotation); +vec4 Transform_GetLocalScale (transform_t transform); +void Transform_SetLocalScale (transform_t transform, vec4 scale); +vec4 Transform_GetWorldPosition (transform_t transform); +void Transform_SetWorldPosition (transform_t transform, vec4 position); +vec4 Transform_GetWorldRotation (transform_t transform); +void Transform_SetWorldRotation (transform_t transform, vec4 rotation); +vec4 Transform_GetWorldScale (transform_t transform); +void Transform_SetLocalTransform (transform_t transform, vec4 scale, + vec4 rotation, vec4 position); +vec4 Transform_Forward (transform_t transform); +vec4 Transform_Right (transform_t transform); +vec4 Transform_Up (transform_t transform); + +model_t Model_Load (string path); +void Model_Unload (model_t model); + +#endif//__ruamoko_scene_h diff --git a/ruamoko/lib/Makemodule.am b/ruamoko/lib/Makemodule.am index 3f879d6e9..2528d5d40 100644 --- a/ruamoko/lib/Makemodule.am +++ b/ruamoko/lib/Makemodule.am @@ -65,6 +65,7 @@ ruamoko_lib_libcsqc_a_src= \ ruamoko/lib/gib.r \ ruamoko/lib/input.r \ ruamoko/lib/mersenne.r \ + ruamoko/lib/scene.r \ ruamoko/lib/key.r ruamoko_lib_common_dep=$(call qcautodep,$(ruamoko_lib_common_src)) diff --git a/ruamoko/lib/scene.r b/ruamoko/lib/scene.r new file mode 100644 index 000000000..6bcf931ed --- /dev/null +++ b/ruamoko/lib/scene.r @@ -0,0 +1,40 @@ +#include + +scene_t Scene_NewScene (void) = #0; +void Scene_DeleteScene (scene_t scene) = #0; +entity_t Scene_CreateEntity (scene_t scene) = #0; +void Scene_DestroyEntity (entity_t ent) = #0; + +transform_t Entity_GetTransform (entity_t ent) = #0; +void Entity_SetModel (entity_t ent, model_t model) = #0; + +unsigned Transform_ChildCount (transform_t transform) = #0; +transform_t Transform_GetChild (transform_t transform, + unsigned childIndex) = #0; +void Transform_SetParent (transform_t transform, transform_t parent) = #0; +transform_t Transform_GetParent (transform_t transform) = #0; +void Transform_SetTag (transform_t transform, unsigned tag) = #0; +unsigned Transform_GetTag (transform_t transform) = #0; +mat4x4 Transform_GetLocalMatrix (transform_t transform) = #0; +mat4x4 Transform_GetLocalInverse (transform_t transform) = #0; +mat4x4 Transform_GetWorldMatrix (transform_t transform) = #0; +mat4x4 Transform_GetWorldInverse (transform_t transform) = #0; +vec4 Transform_GetLocalPosition (transform_t transform) = #0; +void Transform_SetLocalPosition (transform_t transform, vec4 position) = #0; +vec4 Transform_GetLocalRotation (transform_t transform) = #0; +void Transform_SetLocalRotation (transform_t transform, vec4 rotation) = #0; +vec4 Transform_GetLocalScale (transform_t transform) = #0; +void Transform_SetLocalScale (transform_t transform, vec4 scale) = #0; +vec4 Transform_GetWorldPosition (transform_t transform) = #0; +void Transform_SetWorldPosition (transform_t transform, vec4 position) = #0; +vec4 Transform_GetWorldRotation (transform_t transform) = #0; +void Transform_SetWorldRotation (transform_t transform, vec4 rotation) = #0; +vec4 Transform_GetWorldScale (transform_t transform) = #0; +void Transform_SetLocalTransform (transform_t transform, vec4 scale, + vec4 rotation, vec4 position) = #0; +vec4 Transform_Forward (transform_t transform) = #0; +vec4 Transform_Right (transform_t transform) = #0; +vec4 Transform_Up (transform_t transform) = #0; + +model_t Model_Load (string path) = #0; +void Model_Unload (model_t model) = #0; From eaaa0f597f091b488d560688d12461ce61c521c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 18:00:35 +0900 Subject: [PATCH 2740/3664] [scene] Set the color for new entities Black doesn't show up too well on black. Really, this isn't the best fix, but it will do until I can rework entities to use a component system. --- libs/scene/scene.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/scene/scene.c b/libs/scene/scene.c index e08fb718c..13742f2a9 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -35,6 +35,7 @@ # include #endif +#include "QF/mathlib.h" #include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" @@ -84,6 +85,8 @@ Scene_CreateEntity (scene_t *scene) hierarchy_t *h = ent->transform->hierarchy; h->entity.a[ent->transform->index] = ent; + QuatSet (1, 1, 1, 1, ent->renderer.colormod); + return ent; } From fe63d93e8ec698c8abaf17114fb788cc3ae82f74 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 18:01:50 +0900 Subject: [PATCH 2741/3664] [build] Remove some csqc dependencies vkgen and the programs in ruamoko/qwaq just don't need it. --- libs/video/renderer/vulkan/vkgen/Makemodule.am | 4 ++-- ruamoko/qwaq/Makemodule.am | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 39c73f081..a1a0099b1 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -26,8 +26,8 @@ VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen -I$(VKGENUSRINC) vkgen_dat_SOURCES=$(vkgen_dat_src) vkgen_obj=$(vkgen_dat_SOURCES:.r=.o) vkgen_dep=$(call qcautodep,$(vkgen_dat_SOURCES:.o=.Qo)) -vkgen.dat$(EXEEXT): $(vkgen_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(V_QFCCLD)$(QLINK) -o $@ $(vkgen_obj) -lcsqc -lr +vkgen.dat$(EXEEXT): $(vkgen_obj) $(QFCC_DEP) ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(vkgen_obj) -lr include $(vkgen_dep) # am--include-marker r_depfiles_remade += $(vkgen_dep) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 6cbf62829..cd278606b 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -126,32 +126,32 @@ ruamoko_qwaq_qwaq_x11_DEPENDENCIES= $(qwaq_x11_libs) $(QWAQ_DEPS) ruamoko_qwaq_qwaq_app_dat_SOURCES=$(qwaq_app_dat_src) ruamoko_qwaq_qwaq_app_obj=$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.r=.o) ruamoko_qwaq_qwaq_app_dep=$(call qcautodep,$(ruamoko_qwaq_qwaq_app_dat_SOURCES:.o=.Qo)) -ruamoko/qwaq/qwaq-app.dat$(EXEEXT): $(ruamoko_qwaq_qwaq_app_obj) $(QFCC_DEP) $(libui) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_qwaq_app_obj) $(libui) -lcsqc -lr +ruamoko/qwaq/qwaq-app.dat$(EXEEXT): $(ruamoko_qwaq_qwaq_app_obj) $(QFCC_DEP) $(libui) ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_qwaq_app_obj) $(libui) -lr include $(ruamoko_qwaq_qwaq_app_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_qwaq_app_dep) ruamoko_qwaq_input_app_dat_SOURCES=$(qwaq_input_app_dat_src) ruamoko_qwaq_input_app_obj=$(ruamoko_qwaq_input_app_dat_SOURCES:.r=.o) ruamoko_qwaq_input_app_dep=$(call qcautodep,$(ruamoko_qwaq_input_app_dat_SOURCES:.o=.Qo)) -ruamoko/qwaq/input-app.dat$(EXEEXT): $(ruamoko_qwaq_input_app_obj) $(QFCC_DEP) $(libui) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_input_app_obj) $(libui) -lcsqc -lr +ruamoko/qwaq/input-app.dat$(EXEEXT): $(ruamoko_qwaq_input_app_obj) $(QFCC_DEP) $(libui) ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_input_app_obj) $(libui) -lr include $(ruamoko_qwaq_input_app_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_input_app_dep) ruamoko_qwaq_gcd_dat_SOURCES=ruamoko/qwaq/gcd.r ruamoko_qwaq_gcd_obj=$(ruamoko_qwaq_gcd_dat_SOURCES:.r=.o) ruamoko_qwaq_gcd_dep=$(call qcautodep,$(ruamoko_qwaq_gcd_dat_SOURCES:.o=.Qo)) -ruamoko/qwaq/gcd.dat$(EXEEXT): $(ruamoko_qwaq_gcd_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_gcd_obj) -lcsqc -lr +ruamoko/qwaq/gcd.dat$(EXEEXT): $(ruamoko_qwaq_gcd_obj) $(QFCC_DEP) ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_gcd_obj) -lr include $(ruamoko_qwaq_gcd_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_gcd_dep) ruamoko_qwaq_z_transform_dat_SOURCES=ruamoko/qwaq/z-transform.r ruamoko_qwaq_z_transform_obj=$(ruamoko_qwaq_z_transform_dat_SOURCES:.r=.o) ruamoko_qwaq_z_transform_dep=$(call qcautodep,$(ruamoko_qwaq_z_transform_dat_SOURCES:.o=.Qo)) -ruamoko/qwaq/z-transform.dat$(EXEEXT): $(ruamoko_qwaq_z_transform_obj) $(QFCC_DEP) ruamoko/lib/libcsqc.a ruamoko/lib/libr.a - $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_z_transform_obj) -lcsqc -lr +ruamoko/qwaq/z-transform.dat$(EXEEXT): $(ruamoko_qwaq_z_transform_obj) $(QFCC_DEP) ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_qwaq_z_transform_obj) -lr include $(ruamoko_qwaq_z_transform_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_z_transform_dep) From 1891c1c3025d1315cd0ad81251da31da9f35207d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 21:01:39 +0900 Subject: [PATCH 2742/3664] [qflight] Replace a sprintf with va While 16 chars is plenty for a 32-bit int, just seeing sprintf is enough reason to make the change. --- tools/qflight/source/entities.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/qflight/source/entities.c b/tools/qflight/source/entities.c index 85ce43431..0157014f8 100644 --- a/tools/qflight/source/entities.c +++ b/tools/qflight/source/entities.c @@ -125,7 +125,7 @@ MatchTargets (void) // set the style on the source ent for switchable lights if (entities[j].style) { entities[i].style = entities[j].style; - SetKeyValue (&entities[i], "style", va (0, "%i", + SetKeyValue (&entities[i], "style", va (0, "%d", entities[i].style)); } @@ -334,12 +334,9 @@ LoadEntities (void) if (entity->classname && !strcmp (entity->classname, "light")) { if (entity->targetname && entity->targetname[0] && !entity->style) { - char s[16]; - entity->style = LightStyleForTargetname (entity->targetname, true); - sprintf (s, "%i", entity->style); - SetKeyValue (entity, "style", s); + SetKeyValue (entity, "style", va (0, "%d", entity->style)); } } } From 675c82b47b23796080fb3890c6ff3951011e5808 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 21:03:34 +0900 Subject: [PATCH 2743/3664] [nq,qw] Do a little more diff reduction on sbar.c It's rather difficult due to hipnotic and roque in nq, but still, progress is progress. --- nq/source/sbar.c | 234 +++++++++++++++++++++++++++++++++++--- qw/source/sbar.c | 286 +++++++++++++++++++++++++---------------------- 2 files changed, 369 insertions(+), 151 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index df3762ed6..8e298f6aa 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -216,13 +216,13 @@ draw_altstring (view_t *view, int x, int y, const char *str) { r_funcs->Draw_AltString (view->xabs + x, view->yabs + y, str); } - +#endif static inline void draw_nstring (view_t *view, int x, int y, const char *str, int n) { r_funcs->Draw_nString (view->xabs + x, view->yabs + y, str, n); } -#endif + static inline void draw_fill (view_t *view, int x, int y, int w, int h, int col) { @@ -407,18 +407,25 @@ draw_sigils (view_t *view) static void draw_inventory_sbar (view_t *view) { - printf ("sbar: %d\n", sbar_view->visible); draw_pic (view, 0, 0, sb_ibar); view_draw (view); } +typedef struct { + char team[16 + 1]; + int frags; + int players; + int plow, phigh, ptotal; +} team_t; +team_t teams[MAX_CLIENTS]; +int teamsort[MAX_CLIENTS]; int fragsort[MAX_SCOREBOARD]; char scoreboardtext[MAX_SCOREBOARD][20]; int scoreboardtop[MAX_SCOREBOARD]; int scoreboardbottom[MAX_SCOREBOARD]; int scoreboardcount[MAX_SCOREBOARD]; -int scoreboardlines; +int scoreboardlines, scoreboardteams; static void @@ -436,7 +443,7 @@ Sbar_SortFrags (void) } for (i = 0; i < scoreboardlines; i++) { - for (j = 0; j < (scoreboardlines - 1 - i); j++) { + for (j = 0; j < scoreboardlines - 1 - i; j++) { if (cl.players[fragsort[j]].frags < cl.players[fragsort[j + 1]].frags) { k = fragsort[j]; @@ -447,12 +454,77 @@ Sbar_SortFrags (void) } } +static void +Sbar_SortTeams (void) +{ + char t[16 + 1]; + int i, j, k; + player_info_t *s; + + // request new ping times every two second + scoreboardteams = 0; + + if (!cl.teamplay) + return; + + // sort the teams + memset (teams, 0, sizeof (teams)); + for (i = 0; i < MAX_CLIENTS; i++) + teams[i].plow = 999; + + for (i = 0; i < MAX_CLIENTS; i++) { + s = &cl.players[i]; + if (!s->name || !s->name->value[0]) + continue; + if (s->spectator) + continue; + + // find his team in the list + t[16] = 0; + strncpy (t, s->team->value, 16); + if (!t[0]) + continue; // not on team + for (j = 0; j < scoreboardteams; j++) + if (!strcmp (teams[j].team, t)) { + teams[j].frags += s->frags; + teams[j].players++; + goto addpinginfo; + } + if (j == scoreboardteams) { // must add him + j = scoreboardteams++; + strcpy (teams[j].team, t); + teams[j].frags = s->frags; + teams[j].players = 1; + addpinginfo: + if (teams[j].plow > s->ping) + teams[j].plow = s->ping; + if (teams[j].phigh < s->ping) + teams[j].phigh = s->ping; + teams[j].ptotal += s->ping; + } + } + + // sort + for (i = 0; i < scoreboardteams; i++) + teamsort[i] = i; + + // good 'ol bubble sort + for (i = 0; i < scoreboardteams - 1; i++) { + for (j = i + 1; j < scoreboardteams; j++) { + if (teams[teamsort[i]].frags < teams[teamsort[j]].frags) { + k = teamsort[i]; + teamsort[i] = teamsort[j]; + teamsort[j] = k; + } + } + } +} static void draw_solo (view_t *view) { char str[80]; - int minutes, seconds, tens, units; + int minutes, seconds; int l; draw_pic (view, 0, 0, sb_scorebar); @@ -467,10 +539,8 @@ draw_solo (view_t *view) // time minutes = cl.time / 60; - seconds = cl.time - (60 * minutes); - tens = seconds / 10; - units = seconds - (10 * tens); - snprintf (str, sizeof (str), "Time :%3i:%i%i", minutes, tens, units); + seconds = cl.time - 60 * minutes; + snprintf (str, sizeof (str), "Time :%3i:%02i", minutes, seconds); draw_string (view, 184, 4, str); // draw level name @@ -500,7 +570,7 @@ draw_frags (view_t *view) for (i = 0; i < l; i++) { k = fragsort[i]; s = &cl.players[k]; - if (!s->name->value[0]) + if (!s->name || !s->name->value[0]) continue; // draw background @@ -1191,6 +1261,120 @@ Sbar_DrawCenterPrint (void) Sbar_DrawCenterString (hud_overlay_view, -1); } +/* + draw_minifrags + + frags name + frags team name + displayed to right of status bar if there's room +*/ +static void +draw_minifrags (view_t *view) +{ + int numlines, top, bottom, f, i, k, x, y; + char num[20]; + player_info_t *s; + + r_data->scr_copyeverything = 1; + r_data->scr_fullupdate = 0; + + // scores + Sbar_SortFrags (); + + if (!scoreboardlines) + return; // no one there? + + numlines = view->ylen / 8; + if (numlines < 3) + return; // not enough room + + // find us + for (i = 0; i < scoreboardlines; i++) + if (fragsort[i] == cl.playernum) + break; + + if (i == scoreboardlines) // we're not there, we are probably a + // spectator, just display top + i = 0; + else // figure out start + i = i - numlines / 2; + + if (i > scoreboardlines - numlines) + i = scoreboardlines - numlines; + if (i < 0) + i = 0; + + x = 4; + y = 0; + + for (; i < scoreboardlines && y < view->ylen - 8 + 1; i++) { + k = fragsort[i]; + s = &cl.players[k]; + if (!s->name || !s->name->value[0]) + continue; + + // draw ping + top = s->topcolor; + bottom = s->bottomcolor; + top = Sbar_ColorForMap (top); + bottom = Sbar_ColorForMap (bottom); + + draw_fill (view, x + 2, y + 1, 37, 3, top); + draw_fill (view, x + 2, y + 4, 37, 4, bottom); + + // draw number + f = s->frags; + if (k != cl.playernum) { + snprintf (num, sizeof (num), " %3i ", f); + } else { + snprintf (num, sizeof (num), "\x10%3i\x11", f); + } + + draw_nstring (view, x, y, num, 5); + + // team + if (cl.teamplay) { + draw_nstring (view, x + 48, y, s->team->value, 4); + draw_nstring (view, x + 48 + 40, y, s->name->value, 16); + } else + draw_nstring (view, x + 48, y, s->name->value, 16); + y += 8; + } +} + +static void +draw_miniteam (view_t *view) +{ + int i, k, x, y; + char num[12]; + info_key_t *player_team = cl.players[cl.playernum].team; + team_t *tm; + + if (!cl.teamplay) + return; + Sbar_SortTeams (); + + x = 0; + y = 0; + for (i = 0; i < scoreboardteams && y <= view->ylen; i++) { + k = teamsort[i]; + tm = teams + k; + + // draw pings + draw_nstring (view, x, y, tm->team, 4); + // draw total + snprintf (num, sizeof (num), "%5i", tm->frags); + draw_string (view, x + 40, y, num); + + if (player_team && strnequal (player_team->value, tm->team, 16)) { + draw_character (view, x - 8, y, 16); + draw_character (view, x + 32, y, 17); + } + + y += 8; + } +} + static void init_sbar_views (void) { @@ -1252,16 +1436,36 @@ static void init_hud_views (void) { view_t *view; + view_t *minifrags_view = 0; + view_t *miniteam_view = 0; - hud_view = view_new (0, 0, 320, 48, grav_south); - hud_frags_view = view_new (0, 0, 130, 8, grav_northeast); - hud_frags_view->draw = draw_frags; + if (r_data->vid->conview->xlen < 512) { + hud_view = view_new (0, 0, 320, 48, grav_south); + hud_frags_view = view_new (0, 0, 130, 8, grav_northeast); + hud_frags_view->draw = draw_frags; + } else if (r_data->vid->conview->xlen < 640) { + hud_view = view_new (0, 0, 512, 48, grav_south); + + minifrags_view = view_new (320, 0, 192, 48, grav_southwest); + minifrags_view->draw = draw_minifrags; + minifrags_view->resize_y = 1; + } else { + hud_view = view_new (0, 0, 640, 48, grav_south); + + minifrags_view = view_new (320, 0, 192, 48, grav_southwest); + minifrags_view->draw = draw_minifrags; + minifrags_view->resize_y = 1; + + miniteam_view = view_new (0, 0, 96, 48, grav_southeast); + miniteam_view->draw = draw_miniteam; + miniteam_view->resize_y = 1; + } hud_view->resize_y = 1; hud_armament_view = view_new (0, 48, 42, 156, grav_southeast); - view = view_new (0, 0, 24, 112, grav_northeast); + view = view_new (0, 0, 42, 112, grav_northeast); view->draw = draw_weapons_hud; view_add (hud_armament_view, view); diff --git a/qw/source/sbar.c b/qw/source/sbar.c index bd717a1c2..ebc9d267e 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -292,123 +292,6 @@ draw_num (view_t *view, int x, int y, int num, int digits, int color) } } -typedef struct { - char team[16 + 1]; - int frags; - int players; - int plow, phigh, ptotal; -} team_t; - -team_t teams[MAX_CLIENTS]; -int teamsort[MAX_CLIENTS]; -int fragsort[MAX_CLIENTS]; // ZOID changed this from [MAX_SCOREBOARD] -int scoreboardlines, scoreboardteams; - -static void -Sbar_SortFrags (qboolean includespec) -{ - int i, j, k; - - // sort by frags - scoreboardlines = 0; - for (i = 0; i < MAX_CLIENTS; i++) { - if (cl.players[i].name && cl.players[i].name->value[0] - && (!cl.players[i].spectator || includespec)) { - fragsort[scoreboardlines] = i; - scoreboardlines++; - if (cl.players[i].spectator) - cl.players[i].frags = -999; - } - } - - for (i = 0; i < scoreboardlines; i++) - for (j = 0; j < scoreboardlines - 1 - i; j++) - if (cl.players[fragsort[j]].frags < - cl.players[fragsort[j + 1]].frags) { - k = fragsort[j]; - fragsort[j] = fragsort[j + 1]; - fragsort[j + 1] = k; - } -} - -static void -Sbar_SortTeams (void) -{ - char t[16 + 1]; - int i, j, k; - player_info_t *s; - - // request new ping times every two second - scoreboardteams = 0; - - if (!cl.teamplay) - return; - - // sort the teams - memset (teams, 0, sizeof (teams)); - for (i = 0; i < MAX_CLIENTS; i++) - teams[i].plow = 999; - - for (i = 0; i < MAX_CLIENTS; i++) { - s = &cl.players[i]; - if (!s->name || !s->name->value[0]) - continue; - if (s->spectator) - continue; - - // find his team in the list - t[16] = 0; - strncpy (t, s->team->value, 16); - if (!t[0]) - continue; // not on team - for (j = 0; j < scoreboardteams; j++) - if (!strcmp (teams[j].team, t)) { - teams[j].frags += s->frags; - teams[j].players++; - goto addpinginfo; - } - if (j == scoreboardteams) { // must add him - j = scoreboardteams++; - strcpy (teams[j].team, t); - teams[j].frags = s->frags; - teams[j].players = 1; - addpinginfo: - if (teams[j].plow > s->ping) - teams[j].plow = s->ping; - if (teams[j].phigh < s->ping) - teams[j].phigh = s->ping; - teams[j].ptotal += s->ping; - } - } - - // sort - for (i = 0; i < scoreboardteams; i++) - teamsort[i] = i; - - // good 'ol bubble sort - for (i = 0; i < scoreboardteams - 1; i++) - for (j = i + 1; j < scoreboardteams; j++) - if (teams[teamsort[i]].frags < teams[teamsort[j]].frags) { - k = teamsort[i]; - teamsort[i] = teamsort[j]; - teamsort[j] = k; - } -} - -static void -draw_solo (view_t *view) -{ - char str[80]; - int minutes, seconds; - - draw_pic (view, 0, 0, sb_scorebar); - - minutes = cl.time / 60; - seconds = cl.time - 60 * minutes; - snprintf (str, sizeof (str), "Time :%3i:%02i", minutes, seconds); - draw_string (view, 184, 4, str); -} - static inline void draw_smallnum (view_t *view, int x, int y, int n, int packed, int colored) { @@ -567,6 +450,127 @@ draw_inventory_sbar (view_t *view) view_draw (view); } +typedef struct { + char team[16 + 1]; + int frags; + int players; + int plow, phigh, ptotal; +} team_t; + +team_t teams[MAX_CLIENTS]; +int teamsort[MAX_CLIENTS]; +int fragsort[MAX_CLIENTS]; // ZOID changed this from [MAX_SCOREBOARD] +int scoreboardlines, scoreboardteams; + +static void +Sbar_SortFrags (qboolean includespec) +{ + int i, j, k; + + // sort by frags + scoreboardlines = 0; + for (i = 0; i < MAX_CLIENTS; i++) { + if (cl.players[i].name && cl.players[i].name->value[0] + && (!cl.players[i].spectator || includespec)) { + fragsort[scoreboardlines] = i; + scoreboardlines++; + if (cl.players[i].spectator) + cl.players[i].frags = -999; + } + } + + for (i = 0; i < scoreboardlines; i++) { + for (j = 0; j < scoreboardlines - 1 - i; j++) { + if (cl.players[fragsort[j]].frags < + cl.players[fragsort[j + 1]].frags) { + k = fragsort[j]; + fragsort[j] = fragsort[j + 1]; + fragsort[j + 1] = k; + } + } + } +} + +static void +Sbar_SortTeams (void) +{ + char t[16 + 1]; + int i, j, k; + player_info_t *s; + + // request new ping times every two second + scoreboardteams = 0; + + if (!cl.teamplay) + return; + + // sort the teams + memset (teams, 0, sizeof (teams)); + for (i = 0; i < MAX_CLIENTS; i++) + teams[i].plow = 999; + + for (i = 0; i < MAX_CLIENTS; i++) { + s = &cl.players[i]; + if (!s->name || !s->name->value[0]) + continue; + if (s->spectator) + continue; + + // find his team in the list + t[16] = 0; + strncpy (t, s->team->value, 16); + if (!t[0]) + continue; // not on team + for (j = 0; j < scoreboardteams; j++) + if (!strcmp (teams[j].team, t)) { + teams[j].frags += s->frags; + teams[j].players++; + goto addpinginfo; + } + if (j == scoreboardteams) { // must add him + j = scoreboardteams++; + strcpy (teams[j].team, t); + teams[j].frags = s->frags; + teams[j].players = 1; + addpinginfo: + if (teams[j].plow > s->ping) + teams[j].plow = s->ping; + if (teams[j].phigh < s->ping) + teams[j].phigh = s->ping; + teams[j].ptotal += s->ping; + } + } + + // sort + for (i = 0; i < scoreboardteams; i++) + teamsort[i] = i; + + // good 'ol bubble sort + for (i = 0; i < scoreboardteams - 1; i++) { + for (j = i + 1; j < scoreboardteams; j++) { + if (teams[teamsort[i]].frags < teams[teamsort[j]].frags) { + k = teamsort[i]; + teamsort[i] = teamsort[j]; + teamsort[j] = k; + } + } + } +} + +static void +draw_solo (view_t *view) +{ + char str[80]; + int minutes, seconds; + + draw_pic (view, 0, 0, sb_scorebar); + + minutes = cl.time / 60; + seconds = cl.time - 60 * minutes; + snprintf (str, sizeof (str), "Time :%3i:%02i", minutes, seconds); + draw_string (view, 184, 4, str); +} + static inline void dmo_ping (view_t *view, int x, int y, player_info_t *s) { @@ -697,9 +701,6 @@ draw_frags (view_t *view) continue; // draw background - top = bound (0, s->topcolor, 13); - bottom = bound (0, s->bottomcolor, 13); - top = Sbar_ColorForMap (top); bottom = Sbar_ColorForMap (bottom); @@ -785,18 +786,9 @@ draw_status_bar (view_t *view) draw_pic (view, 0, 0, sb_sbar); } -static void -draw_status (view_t *view) +static inline void +draw_armor (view_t *view) { - if (cl.spectator) { - draw_spectator (view); - if (autocam != CAM_TRACK) - return; - } if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { - draw_solo (view); - return; - } - // armor if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { draw_num (view, 24, 0, 666, 3, 1); } else { @@ -809,15 +801,18 @@ draw_status (view_t *view) else if (cl.stats[STAT_ITEMS] & IT_ARMOR1) draw_pic (view, 0, 0, sb_armor[0]); } +} - // face - draw_face (view); - - // health +static inline void +draw_health (view_t *view) +{ draw_num (view, 136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25); +} - // ammo icon +static inline void +draw_ammo (view_t *view) +{ if (cl.stats[STAT_ITEMS] & IT_SHELLS) draw_pic (view, 224, 0, sb_ammo[0]); else if (cl.stats[STAT_ITEMS] & IT_NAILS) @@ -830,6 +825,25 @@ draw_status (view_t *view) draw_num (view, 248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); } +static void +draw_status (view_t *view) +{ + if (cl.spectator) { + draw_spectator (view); + if (autocam != CAM_TRACK) + return; + } + if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { + draw_solo (view); + return; + } + + draw_armor (view); + draw_face (view); + draw_health (view); + draw_ammo (view); +} + /* Sbar_DeathmatchOverlay From 3bd50c155593fd5ad841121a0a2e24f5c35ff56f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 22:37:52 +0900 Subject: [PATCH 2744/3664] [nq] Fix incorrect handling of argv in PF_WriteBytes This fixes an illegible server message error on going through a teleport in the start map (how I noticed the problem). Funnily enough, I had spotted the mistake when editing the qw version, but forgot to correct the nq version. --- nq/source/sv_pr_cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index b133b0bf4..b555708ff 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -1139,7 +1139,7 @@ PF_WriteBytes (progs_t *pr, void *data) } } for (i = 0; i < argc; i++) { - p = PR_PTR (float, &argv[i]); + p = PR_PTR (float, argv[i]); MSG_WriteByte (msg, p); } } From a4d3352ca1d0953d48d142164cf98ab358f070bb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 23:13:24 +0900 Subject: [PATCH 2745/3664] [qw] Call SV_Physics_Init_Cvars during server init This fixes the broken physics. Really, not that bad considering how extensive the cvar revamp was. --- qw/source/sv_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index fbb111ab1..e2d64d170 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2355,6 +2355,7 @@ SV_InitLocal (void) int i; SV_UserInit (); + SV_Physics_Init_Cvars (); Cvar_Register (&rcon_password_cvar, 0, 0); Cvar_Register (&admin_password_cvar, 0, 0); From bbb66e13f82db4d21adc30ad610e42f530b89cf2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 22:37:52 +0900 Subject: [PATCH 2746/3664] [nq] Fix incorrect handling of argv in PF_WriteBytes This fixes an illegible server message error on going through a teleport in the start map (how I noticed the problem). Funnily enough, I had spotted the mistake when editing the qw version, but forgot to correct the nq version. --- nq/source/sv_pr_cmds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index b133b0bf4..b555708ff 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -1139,7 +1139,7 @@ PF_WriteBytes (progs_t *pr, void *data) } } for (i = 0; i < argc; i++) { - p = PR_PTR (float, &argv[i]); + p = PR_PTR (float, argv[i]); MSG_WriteByte (msg, p); } } From 618453629fc56fd4600b86c5bae9879e6c208743 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 23:13:24 +0900 Subject: [PATCH 2747/3664] [qw] Call SV_Physics_Init_Cvars during server init This fixes the broken physics. Really, not that bad considering how extensive the cvar revamp was. --- qw/source/sv_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index fbb111ab1..e2d64d170 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2355,6 +2355,7 @@ SV_InitLocal (void) int i; SV_UserInit (); + SV_Physics_Init_Cvars (); Cvar_Register (&rcon_password_cvar, 0, 0); Cvar_Register (&admin_password_cvar, 0, 0); From 5dd2ea242e9e3af8d7f86026c7d72b4fb35ad0cf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 23:52:26 +0900 Subject: [PATCH 2748/3664] [qw] Fix inverted chat mode This has been bugging me for a while whenever I tested qw. Just a silly logic error. The whole system needs work, though. --- qw/source/cl_chat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index 5e170c3c9..81e9c8b4b 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -255,7 +255,7 @@ static void cl_chat_on_focus_change (int game) { //FIXME afk mode - CL_ChatInfo (!!game); + CL_ChatInfo (!game); } From e1f4df27c31091856032dfcea64494025feddd87 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 4 May 2022 23:52:26 +0900 Subject: [PATCH 2749/3664] [qw] Fix inverted chat mode This has been bugging me for a while whenever I tested qw. Just a silly logic error. The whole system needs work, though. --- qw/source/cl_chat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index 5e170c3c9..81e9c8b4b 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -255,7 +255,7 @@ static void cl_chat_on_focus_change (int game) { //FIXME afk mode - CL_ChatInfo (!!game); + CL_ChatInfo (!game); } From e323fbbbed7a5441b488f8157f51610cf9362501 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 08:40:02 +0900 Subject: [PATCH 2750/3664] [vulkan] Rework lighting model to be more algebraic This leaves only the one conditional in the shader code, that being the distance check. It doesn't seem to make any noticeable difference to performance, but other than explosion sprites being blue, lighting quality seems to have improved. However, I really need to get shadows working: marcher is just silly-bright without them, and light levels changing as I move around is a bit disconcerting (but reasonable as those lights' leaf nodes go in and out of visibility). --- include/QF/Vulkan/qf_lighting.h | 44 ++-- .../renderer/vulkan/shader/lighting.frag | 127 +++------- libs/video/renderer/vulkan/vulkan_lighting.c | 221 ++++++++++++------ 3 files changed, 192 insertions(+), 200 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index ec4de2c3f..f8b6e5d84 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -39,12 +39,10 @@ #include "QF/simd/types.h" typedef struct qfv_light_s { - vec3_t color; - int data; - vec3_t position; - float light; - vec3_t direction; - float cone; + vec4f_t color; + vec4f_t position; + vec4f_t direction; + vec4f_t attenuation; } qfv_light_t; typedef struct qfv_lightset_s DARRAY_TYPE (qfv_light_t) qfv_lightset_t; @@ -54,32 +52,25 @@ typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t; #define MaxLights 256 -#define StyleMask 0x07f -#define ModelMask 0x380 -#define ShadowMask 0xc00 +#define LM_LINEAR 0 // light - dist (or radius + dist if -ve) +#define LM_INVERSE 1 // distFactor1 * light / dist +#define LM_INVERSE2 2 // distFactor2 * light / (dist * dist) +#define LM_INFINITE 3 // light +#define LM_AMBIENT 4 // light +#define LM_INVERSE3 5 // distFactor2 * light / (dist + distFactor2)**2 -#define LM_LINEAR (0 << 7) // light - dist (or radius + dist if -ve) -#define LM_INVERSE (1 << 7) // distFactor1 * light / dist -#define LM_INVERSE2 (2 << 7) // distFactor2 * light / (dist * dist) -#define LM_INFINITE (3 << 7) // light -#define LM_AMBIENT (4 << 7) // light -#define LM_INVERSE3 (5 << 7) // distFactor2 * light / (dist + distFactor2)**2 - -#define ST_NONE (0 << 10) // no shadows -#define ST_PLANE (1 << 10) // single plane shadow map (small spotlight) -#define ST_CASCADE (2 << 10) // cascaded shadow maps -#define ST_CUBE (3 << 10) // cubemap (omni, large spotlight) +#define ST_NONE 0 // no shadows +#define ST_PLANE 1 // single plane shadow map (small spotlight) +#define ST_CASCADE 2 // cascaded shadow maps +#define ST_CUBE 3 // cubemap (omni, large spotlight) #define NumStyles 64 typedef struct qfv_light_buffer_s { - float intensity[NumStyles + 4]; - float distFactor1; - float distFactor2; - int lightCount; qfv_light_t lights[MaxLights] __attribute__((aligned(16))); - mat4f_t shadowMat[MaxLights]; - vec4f_t shadowCascade[MaxLights]; + int lightCount; + //mat4f_t shadowMat[MaxLights]; + //vec4f_t shadowCascade[MaxLights]; } qfv_light_buffer_t; #define LIGHTING_BUFFER_INFOS 1 @@ -119,6 +110,7 @@ typedef struct lightingctx_s { VkDeviceMemory light_memory; VkDeviceMemory shadow_memory; qfv_lightset_t lights; + qfv_lightintset_t lightstyles; qfv_lightintset_t lightleafs; qfv_lightmatset_t lightmats; qfv_imageset_t lightimages; diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 2d384e622..a9e5cb7d2 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -7,12 +7,10 @@ layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput n layout (input_attachment_index = 4, set = 0, binding = 4) uniform subpassInput position; struct LightData { - vec3 color; - int data;// bits 0-6: intensity key (however, values 0-66) - vec3 position; - float light; // doubles as radius for linear - vec3 direction; - float cone; + vec4 color; // .a is intensity + vec4 position; // .w = 0 -> directional, .w = 1 -> point/cone + vec4 direction; // .w = -cos(cone_angle/2) (1 for omni/dir) + vec4 attenuation; }; #define StyleMask 0x07f @@ -38,13 +36,10 @@ layout (set = 2, binding = 0) uniform sampler2DShadow shadowPlane[MaxLights]; layout (set = 2, binding = 0) uniform samplerCubeShadow shadowCube[MaxLights]; layout (set = 1, binding = 0) uniform Lights { - vec4 intensity[17]; // 68 floats - float distFactor1; // for inverse - float distFactor2; // for inverse2 and inverse3 - int lightCount; LightData lights[MaxLights]; - mat4 shadowMat[MaxLights]; - vec4 shadowCascale[MaxLights]; + int lightCount; + //mat4 shadowMat[MaxLights]; + //vec4 shadowCascale[MaxLights]; }; layout (location = 0) out vec4 frag_color; @@ -52,8 +47,10 @@ layout (location = 0) out vec4 frag_color; float spot_cone (LightData light, vec3 incoming) { - float spotdot = dot (incoming, light.direction); - return smoothstep (spotdot, 1 - (1 - spotdot) * 0.995, light.cone); + vec3 dir = light.direction.xyz; + float cone = light.direction.w; + float spotdot = dot (incoming, dir); + return 1 - smoothstep (cone, cone + 0.02, spotdot); } float @@ -63,50 +60,6 @@ diffuse (vec3 incoming, vec3 normal) return clamp (lightdot, 0, 1); } -float -light_linear (LightData light, float d) -{ - float l = light.light; - if (l < 0) { - return min (l + d, 0); - } else { - return max (l - d, 0); - } -} - -float -light_inverse (LightData light, float d) -{ - float l = light.light; - return l / (distFactor1 * d); -} - -float -light_inverse2 (LightData light, float d) -{ - float l = light.light; - return l / (distFactor2 * d); -} - -float -light_infinite (LightData light) -{ - return light.light; -} - -float -light_ambient (LightData light) -{ - return light.light; -} - -float -light_inverse3 (LightData light, float d) -{ - float l = light.light; - return l / (distFactor2 * d + 1); -} - float shadow_cascade (sampler2DArrayShadow map) { @@ -138,55 +91,31 @@ main (void) if (MaxLights > 0) { vec3 minLight = vec3 (0); for (int i = 0; i < lightCount; i++) { - vec3 dist = lights[i].position - p; - float d = dot (dist, dist); - int model = lights[i].data & ModelMask; + LightData l = lights[i]; + vec3 dir = l.position.xyz - l.position.w * p; + float r2 = dot (dir, dir); + vec4 a = l.attenuation; - if (model != LM_INFINITE - && d > lights[i].light * lights[i].light) { + if (l.position.w * a.w * a.w * r2 >= 1) { continue; } + vec4 r = vec4 (r2, sqrt(r2), 1, 0); + vec3 incoming = dir / r.y; + float I = (1 - a.w * r.y) / dot (a, r); - float l = 0; - if (model == LM_LINEAR) { - d = sqrt (d); - l = light_linear (lights[i], d); - } else if (model == LM_INVERSE) { - d = sqrt (d); - l = light_inverse (lights[i], d); - } else if (model == LM_INVERSE2) { - l = light_inverse2 (lights[i], d); - d = sqrt (d); - } else if (model == LM_INFINITE) { - l = light_infinite (lights[i]); - dist = lights[i].direction; - d = -1; - } else if (model == LM_AMBIENT) { - l = light_ambient (lights[i]); - } else if (model == LM_INVERSE3) { - l = light_inverse3 (lights[i], d); - d = sqrt (d); - } - - int style = lights[i].data & StyleMask; - l *= intensity[style / 4][style % 4]; - - int shadow = lights[i].data & ShadowMask; + /*int shadow = lights[i].data & ShadowMask; if (shadow == ST_CASCADE) { - l *= shadow_cascade (shadowCascade[i]); + I *= shadow_cascade (shadowCascade[i]); } else if (shadow == ST_PLANE) { - l *= shadow_plane (shadowPlane[i]); + I *= shadow_plane (shadowPlane[i]); } else if (shadow == ST_CUBE) { - l *= shadow_cube (shadowCube[i]); - } + I *= shadow_cube (shadowCube[i]); + }*/ - if (model == LM_AMBIENT) { - minLight = max (l * lights[i].color, minLight); - } else { - vec3 incoming = dist / d; - l *= spot_cone (lights[i], incoming) * diffuse (incoming, n); - light += l * lights[i].color; - } + float namb = dot(l.direction.xyz, l.direction.xyz); + I *= spot_cone (l, incoming) * diffuse (incoming, n); + I = mix (1, I, namb); + light += I * l.color.w * l.color.xyz; } light = max (light, minLight); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 33b13a22d..7a97377d3 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -147,17 +147,10 @@ update_lights (vulkan_ctx_t *ctx) qfv_light_buffer_t *light_data = QFV_PacketExtend (packet, sizeof (*light_data)); + float style_intensities[NumStyles]; for (int i = 0; i < NumStyles; i++) { - light_data->intensity[i] = d_lightstylevalue[i] / 65536.0; + style_intensities[i] = d_lightstylevalue[i] / 65536.0; } - // dynamic lights seem a tad faint, so 16x map lights - light_data->intensity[64] = 1 / 16.0; - light_data->intensity[65] = 1 / 16.0; - light_data->intensity[66] = 1 / 16.0; - light_data->intensity[67] = 1 / 16.0; - - light_data->distFactor1 = 1 / 128.0; - light_data->distFactor2 = 1 / 16384.0; light_data->lightCount = 0; R_FindNearLights (r_refdef.frame.position, MaxLights - 1, lights); @@ -167,16 +160,20 @@ update_lights (vulkan_ctx_t *ctx) } light_data->lightCount++; VectorCopy (lights[i]->color, light_data->lights[i].color); + // dynamic lights seem a tad faint, so 16x map lights + light_data->lights[i].color[3] = lights[i]->radius / 16; VectorCopy (lights[i]->origin, light_data->lights[i].position); - light_data->lights[i].light = lights[i]->radius; - light_data->lights[i].data = 64; // default dynamic light - VectorZero (light_data->lights[i].direction); - light_data->lights[i].cone = 1; + light_data->lights[i].attenuation = + (vec4f_t) { 0, 0, 1, 1/lights[i]->radius }; + light_data->lights[i].direction = + (vec4f_t) { 0, 0, 1, 1 }; } for (size_t i = 0; (i < lframe->lightvis.size && light_data->lightCount < MaxLights); i++) { if (lframe->lightvis.a[i]) { - light_data->lights[light_data->lightCount++] = lctx->lights.a[i]; + qfv_light_t *light = &light_data->lights[light_data->lightCount++]; + *light = lctx->lights.a[i]; + light->color[3] *= style_intensities[lctx->lightstyles.a[i]]; } } @@ -303,6 +300,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) ctx->lighting_context = lctx; DARRAY_INIT (&lctx->lights, 16); + DARRAY_INIT (&lctx->lightstyles, 16); DARRAY_INIT (&lctx->lightleafs, 16); DARRAY_INIT (&lctx->lightmats, 16); DARRAY_INIT (&lctx->lightlayers, 16); @@ -462,6 +460,7 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0); dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0); DARRAY_CLEAR (&lctx->lights); + DARRAY_CLEAR (&lctx->lightstyles); DARRAY_CLEAR (&lctx->lightleafs); DARRAY_CLEAR (&lctx->lightmats); DARRAY_CLEAR (&lctx->lightimages); @@ -475,19 +474,17 @@ static void dump_light (qfv_light_t *light, int leaf, mat4f_t mat) { Sys_MaskPrintf (SYS_vulkan, - "[%g, %g, %g] %d %d %d, " - "[%g %g %g] %g, [%g %g %g] %g, %d\n", - VectorExpand (light->color), - (light->data & 0x07f), - (light->data & 0x380) >> 7, - (light->data & 0xc00) >> 10, - VectorExpand (light->position), light->light, - VectorExpand (light->direction), light->cone, + "[%g, %g, %g] %g, " + "[%g, %g, %g, %g], [%g %g %g] %g, [%g, %g, %g, %g] %d\n", + VEC4_EXP (light->color), + VEC4_EXP (light->position), + VEC4_EXP (light->direction), + VEC4_EXP (light->attenuation), leaf); - Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 0)); - Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 1)); - Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 2)); - Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 3)); +// Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 0)); +// Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 1)); +// Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 2)); +// Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 3)); } static float @@ -548,13 +545,17 @@ esin (float ang) return sin (ang * M_PI / 180); } -static void -sun_vector (const vec_t *ang, vec_t *vec) +static vec4f_t +sun_vector (const vec_t *ang) { // ang is yaw, pitch (maybe roll, but ignored - vec[0] = ecos (ang[1]) * ecos (ang[0]); - vec[1] = ecos (ang[1]) * esin (ang[0]); - vec[2] = esin (ang[1]); + vec4f_t vec = { + ecos (ang[1]) * ecos (ang[0]), + ecos (ang[1]) * esin (ang[0]), + esin (ang[1]), + 0, + }; + return vec; } static void @@ -577,11 +578,13 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model) return; } VectorSet (1, 1, 1, light.color); - light.data = LM_INFINITE | ST_CASCADE; - light.light = sunlight; - sun_vector (sunangle, light.direction); - light.cone = 1; + light.color[3] = sunlight; + light.position = sun_vector (sunangle); + light.direction = light.position; + light.direction[3] = 1; + light.attenuation = (vec4f_t) { 0, 0, 1, 0 }; DARRAY_APPEND (&lctx->lights, light); + DARRAY_APPEND (&lctx->lightstyles, 0); DARRAY_APPEND (&lctx->lightleafs, -1); // Any leaf with sky surfaces can potentially see the sun, thus put @@ -597,8 +600,16 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model) expand_pvs (lctx->sun_pvs, model); } +static vec4f_t +parse_position (const char *str) +{ + vec3_t vec = {}; + sscanf (str, "%f %f %f", VectorExpandAddr (vec)); + return (vec4f_t) {vec[0], vec[1], vec[2], 1}; +} + static void -parse_light (qfv_light_t *light, const plitem_t *entity, +parse_light (qfv_light_t *light, int *style, const plitem_t *entity, const plitem_t *targets) { const char *str; @@ -612,48 +623,47 @@ parse_light (qfv_light_t *light, const plitem_t *entity, } Sys_Printf ("}\n");*/ - light->cone = 1; - light->data = 0; - light->light = 300; - VectorSet (1, 1, 1, light->color); + // omnidirectional light (unit length xyz so not treated as ambient) + light->direction = (vec4f_t) { 0, 0, 1, 1 }; + // bright white + light->color = (vec4f_t) { 1, 1, 1, 300 }; if ((str = PL_String (PL_ObjectForKey (entity, "origin")))) { - sscanf (str, "%f %f %f", VectorExpandAddr (light->position)); + light->position = parse_position (str); } if ((str = PL_String (PL_ObjectForKey (entity, "target")))) { - vec3_t position = {}; plitem_t *target = PL_ObjectForKey (targets, str); + vec4f_t dir = { 1, 0, 0, 0 }; if (target) { if ((str = PL_String (PL_ObjectForKey (target, "origin")))) { - sscanf (str, "%f %f %f", VectorExpandAddr (position)); + dir = parse_position (str); + dir = normalf (dir - light->position); } - VectorSubtract (position, light->position, light->direction); - VectorNormalize (light->direction); } float angle = 40; if ((str = PL_String (PL_ObjectForKey (entity, "angle")))) { angle = atof (str); } - light->cone = -cos (angle * M_PI / 360); // half angle + dir[3] = -cos (angle * M_PI / 360); // half angle + light->direction = dir; } if ((str = PL_String (PL_ObjectForKey (entity, "light_lev"))) || (str = PL_String (PL_ObjectForKey (entity, "_light")))) { - light->light = atof (str); + light->color[3] = atof (str); } if ((str = PL_String (PL_ObjectForKey (entity, "style")))) { - light->data = atoi (str) & 0x3f; + *style = atoi (str) & 0x3f; } if ((str = PL_String (PL_ObjectForKey (entity, "delay")))) { - model = (atoi (str) & 0x7) << 7; + model = atoi (str) & 0x7; if (model == LM_INVERSE2) { model = LM_INVERSE3; //FIXME for marcher (need a map) } - light->data |= model; } if ((str = PL_String (PL_ObjectForKey (entity, "color"))) @@ -662,15 +672,29 @@ parse_light (qfv_light_t *light, const plitem_t *entity, VectorScale (light->color, 1/255.0, light->color); } - if (model == LM_INFINITE) { - light->data |= ST_CASCADE; - } else if (model != LM_AMBIENT) { - if (light->cone > -0.5) { - light->data |= ST_CUBE; - } else { - light->data |= ST_PLANE; - } + vec4f_t attenuation = { 1, 0, 0, 0 }; // inverse square + switch (model) { + case LM_LINEAR: + attenuation = (vec4f_t) { 0, 0, 1, 1 / fabsf (light->color[3]) }; + break; + case LM_INVERSE: + attenuation = (vec4f_t) { 0, 1.0 / 128, 0, 0 }; + break; + case LM_INVERSE2: + attenuation = (vec4f_t) { 1.0 / 16384, 0, 0, 0 }; + break; + case LM_INFINITE: + attenuation = (vec4f_t) { 0, 0, 1, 0 }; + break; + case LM_AMBIENT: + attenuation = (vec4f_t) { 0, 0, 1, 0 }; + light->direction = (vec4f_t) { 0, 0, 0, 1 }; + break; + case LM_INVERSE3: + attenuation = (vec4f_t) { 1.0 / 16384, 2.0 / 128, 1, 0 }; + break; } + light->attenuation = attenuation; } static void @@ -681,8 +705,18 @@ create_light_matrices (lightingctx_t *lctx) qfv_light_t *light = &lctx->lights.a[i]; mat4f_t view; mat4f_t proj; + int mode = ST_NONE; - switch (light->data & ShadowMask) { + if (!light->position[3]) { + mode = ST_CASCADE; + } else { + if (light->direction[3] > -0.5) { + mode = ST_CUBE; + } else { + mode = ST_PLANE; + } + } + switch (mode) { default: case ST_NONE: case ST_CUBE: @@ -691,13 +725,14 @@ create_light_matrices (lightingctx_t *lctx) case ST_CASCADE: case ST_PLANE: //FIXME will fail for -ref_direction - mat4fquat (view, qrotf (loadvec3f (light->direction), - ref_direction)); + vec4f_t dir = light->direction; + dir[3] = 0; + mat4fquat (view, qrotf (dir, ref_direction)); break; } VectorNegate (light->position, view[3]); - switch (light->data & ShadowMask) { + switch (mode) { case ST_NONE: mat4fidentity (proj); break; @@ -709,7 +744,7 @@ create_light_matrices (lightingctx_t *lctx) mat4fidentity (proj); break; case ST_PLANE: - QFV_PerspectiveCos (proj, light->cone); + QFV_PerspectiveCos (proj, -light->direction[3]); break; } mmulf (lctx->lightmats.a[i], proj, view); @@ -722,10 +757,11 @@ light_compare (const void *_l2, const void *_l1) const qfv_light_t *l1 = _l1; const qfv_light_t *l2 = _l2; - if (l1->light == l2->light) { - return (l1->data & ShadowMask) - (l2->data & ShadowMask); + if (l1->color[3] == l2->color[3]) { + return (l1->position[3] == l2->position[3]) + && (l1->direction[3] > -0.5) == (l2->direction[3] > -0.5); } - return l1->light - l2->light; + return l1->color[3] - l2->color[3]; } static VkImage @@ -758,7 +794,7 @@ create_map (int size, int layers, int cube, vulkan_ctx_t *ctx) } static VkImageView -create_view (VkImage image, int baseLayer, int data, int id, vulkan_ctx_t *ctx) +create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -767,7 +803,7 @@ create_view (VkImage image, int baseLayer, int data, int id, vulkan_ctx_t *ctx) VkImageViewType type = 0; const char *viewtype = 0; - switch (data & ShadowMask) { + switch (mode) { case ST_NONE: return 0; case ST_PLANE: @@ -827,8 +863,18 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) DARRAY_RESIZE (&lctx->lightlayers, numLights); qsort (lights, numLights, sizeof (qfv_light_t), light_compare); for (int i = 0; i < numLights; i++) { - int shadow = lights[i].data & ShadowMask; int layers = 1; + int shadow = ST_NONE; + + if (!lights[i].position[3]) { + shadow = ST_CASCADE; + } else { + if (lights[i].direction[3] > -0.5) { + shadow = ST_CUBE; + } else { + shadow = ST_PLANE; + } + } if (shadow == ST_CASCADE || shadow == ST_NONE) { // cascade shadows will be handled separately, and "none" has no // shadow map at all @@ -838,13 +884,14 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) if (shadow == ST_CUBE) { layers = 6; } - if (size != (int) lights[i].light || numLayers + layers > maxLayers) { + if (size != (int) lights[i].color[3] + || numLayers + layers > maxLayers) { if (numLayers) { VkImage shadow_map = create_map (size, numLayers, 1, ctx); DARRAY_APPEND (&lctx->lightimages, shadow_map); numLayers = 0; } - size = lights[i].light; + size = lights[i].color[3]; } imageMap[i] = lctx->lightimages.size; lctx->lightlayers.a[i] = numLayers; @@ -859,8 +906,18 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) numLayers = 0; size = 1024; for (int i = 0; i < numLights; i++) { - int shadow = lights[i].data & ShadowMask; int layers = 4; + int shadow = ST_NONE; + + if (!lights[i].position[3]) { + shadow = ST_CASCADE; + } else { + if (lights[i].direction[3] > -0.5) { + shadow = ST_CUBE; + } else { + shadow = ST_PLANE; + } + } if (shadow != ST_CASCADE) { continue; @@ -902,9 +959,20 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) lctx->lightviews.a[i] = 0; continue; } + int mode = ST_NONE; + + if (!lctx->lights.a[i].position[3]) { + mode = ST_CASCADE; + } else { + if (lctx->lights.a[i].direction[3] > -0.5) { + mode = ST_CUBE; + } else { + mode = ST_PLANE; + } + } lctx->lightviews.a[i] = create_view (lctx->lightimages.a[imageMap[i]], lctx->lightlayers.a[i], - lctx->lights.a[i].data, i, ctx); + mode, i, ctx); } Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n", totalLayers, lctx->lightimages.size, memsize); @@ -932,6 +1000,7 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) } lctx->lights.size = 0; + lctx->lightstyles.size = 0; lctx->lightleafs.size = 0; lctx->lightmats.size = 0; if (lctx->sun_pvs) { @@ -989,11 +1058,13 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) parse_sun (lctx, entity, model); } else if (strnequal (classname, "light", 5)) { qfv_light_t light = {}; + int style = 0; - parse_light (&light, entity, targets); + parse_light (&light, &style, entity, targets); // some lights have 0 output, so drop them - if (light.light) { + if (light.color[3]) { DARRAY_APPEND (&lctx->lights, light); + DARRAY_APPEND (&lctx->lightstyles, style); } } } From e9ad7b748bb3e818c73c3c8e10919abf36d6d709 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 14:41:46 +0900 Subject: [PATCH 2751/3664] [renderer] Use scene_t to set the model data This replaces *_NewMap with *_NewScene and adds SCR_NewScene to handle loading a new map (for quake) in the renderer, and will eventually be how any new scene is loaded. --- include/QF/GL/qf_rmain.h | 4 ++-- include/QF/GLSL/qf_main.h | 3 ++- include/QF/Vulkan/qf_main.h | 4 ++-- include/QF/plugin/vid_render.h | 3 ++- include/QF/scene/scene.h | 3 +++ include/QF/screen.h | 3 +++ include/client/world.h | 1 - include/r_internal.h | 3 ++- include/r_local.h | 2 -- libs/client/cl_temp_entities.c | 6 +++--- libs/client/cl_world.c | 11 ++++++++--- libs/video/renderer/gl/gl_rmisc.c | 21 +++++++++++---------- libs/video/renderer/glsl/glsl_main.c | 11 ++++++----- libs/video/renderer/r_screen.c | 14 ++++++++++++++ libs/video/renderer/sw/sw_rmain.c | 4 +++- libs/video/renderer/vid_render_gl.c | 2 +- libs/video/renderer/vid_render_glsl.c | 2 +- libs/video/renderer/vid_render_sw.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 7 ++++--- libs/video/renderer/vulkan/vulkan_main.c | 14 +++++++------- nq/source/cl_demo.c | 4 +++- nq/source/cl_ents.c | 6 +++--- nq/source/cl_main.c | 6 +++--- nq/source/cl_parse.c | 15 +++++++-------- nq/source/cl_screen.c | 5 +++-- nq/source/host.c | 3 ++- qw/source/cl_demo.c | 6 ++++-- qw/source/cl_entparse.c | 4 +++- qw/source/cl_ents.c | 12 ++++++------ qw/source/cl_main.c | 6 +++--- qw/source/cl_parse.c | 16 ++++++++-------- qw/source/cl_screen.c | 5 +++-- qw/source/sbar.c | 4 +++- qw/source/teamplay.c | 12 +++++++----- ruamoko/qwaq/builtins/graphics.c | 2 +- 35 files changed, 134 insertions(+), 92 deletions(-) diff --git a/include/QF/GL/qf_rmain.h b/include/QF/GL/qf_rmain.h index a9aea8770..85048cb05 100644 --- a/include/QF/GL/qf_rmain.h +++ b/include/QF/GL/qf_rmain.h @@ -45,8 +45,8 @@ void gl_R_RotateForEntity (struct entity_s *e); struct model_s; struct entqueue_s; -void gl_R_NewMap (struct model_s *worldmodel, struct model_s **models, - int num_models); +struct scene_s; +void gl_R_NewScene (struct scene_s *scene); void gl_R_RenderView (void); void gl_R_RenderEntities (struct entqueue_s *queue); void gl_R_ClearState (void); diff --git a/include/QF/GLSL/qf_main.h b/include/QF/GLSL/qf_main.h index b194805fb..621c0b2af 100644 --- a/include/QF/GLSL/qf_main.h +++ b/include/QF/GLSL/qf_main.h @@ -29,8 +29,9 @@ #define __QF_GLSL_qf_main_h struct entqueue_s; +struct scene_s; -void glsl_R_NewMap (model_t *worldmodel, model_t **models, int num_models); +void glsl_R_NewScene (struct scene_s *scene); void glsl_R_RenderEntities (struct entqueue_s *queue); void glsl_R_RenderView (void); void glsl_R_ClearState (void); diff --git a/include/QF/Vulkan/qf_main.h b/include/QF/Vulkan/qf_main.h index b52b0a7f3..8d2da31d6 100644 --- a/include/QF/Vulkan/qf_main.h +++ b/include/QF/Vulkan/qf_main.h @@ -31,9 +31,9 @@ struct vulkan_ctx_s; struct qfv_renderframe_s; struct entqueue_s; +struct scene_s; -void Vulkan_NewMap (model_t *worldmodel, struct model_s **models, - int num_models, struct vulkan_ctx_s *ctx); +void Vulkan_NewScene (struct scene_s *scene, struct vulkan_ctx_s *ctx); void Vulkan_RenderView (struct qfv_renderframe_s *rFrame); void Vulkan_RenderEntities (struct entqueue_s *queue, struct qfv_renderframe_s *rFrame); diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 0118df52f..1bcffe276 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -35,6 +35,7 @@ struct plitem_s; struct cvar_s; +struct scene_s; struct skin_s; struct mod_alias_ctx_s; @@ -105,7 +106,7 @@ typedef struct vid_render_funcs_s { void (*R_Init) (void); void (*R_ClearState) (void); void (*R_LoadSkys) (const char *); - void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models); + void (*R_NewScene) (struct scene_s *scene); void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height); void (*begin_frame) (void); diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index b74c29955..66995bb9e 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -43,6 +43,9 @@ typedef struct scene_s { struct scene_resources_s *const resources; struct hierarchy_s *hierarchies; + struct model_s *worldmodel; + int num_models; + struct model_s **models; } scene_t; scene_t *Scene_NewScene (void); diff --git a/include/QF/screen.h b/include/QF/screen.h index 362cae41b..d53b1b1ee 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -29,6 +29,7 @@ #ifndef __QF_screen_h #define __QF_screen_h +struct scene_s; struct transform_s; struct tex_s; @@ -47,6 +48,8 @@ void SCR_SetFOV (float fov); void SCR_SetFullscreen (qboolean fullscreen); void SCR_SetBottomMargin (int lines); +void SCR_NewScene (struct scene_s *scene); + extern int hud_fps; extern int hud_time; extern int r_timegraph; diff --git a/include/client/world.h b/include/client/world.h index 191e313d8..ba67d9c35 100644 --- a/include/client/world.h +++ b/include/client/world.h @@ -43,7 +43,6 @@ typedef struct worldscene_s { struct scene_s *scene; struct plitem_s *edicts; struct plitem_s *worldspawn; - struct model_s *worldmodel; modelset_t models; } worldscene_t; diff --git a/include/r_internal.h b/include/r_internal.h index 8b43dac0a..2d8feccc4 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -45,7 +45,8 @@ struct psystem_s *glsl_ParticleSystem (void); struct psystem_s *sw_ParticleSystem (void); void R_RunParticles (float dT); -void R_NewMap (model_t *worldmodel, model_t **models, int num_models); +struct scene_s; +void R_NewScene (struct scene_s *scene); // LordHavoc: relative bmodel lighting void R_PushDlights (const vec3_t entorigin); diff --git a/include/r_local.h b/include/r_local.h index 486347f0d..4ea9d6795 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -202,8 +202,6 @@ extern void R_RotateBmodel (struct transform_s *transform); extern int c_faceclip; extern int r_polycount; -extern model_t *cl_worldmodel; - extern int *pfrustum_indexes[4]; // !!! if this is changed, it must be changed in asm_draw.h too !!! diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 269a1c9ed..3be60f2bd 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -271,7 +271,7 @@ beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx) } else { Transform_SetLocalPosition (tent->ent->transform, position); } - R_AddEfrags (&cl_world.worldmodel->brush, tent->ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, tent->ent); } } @@ -632,7 +632,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) ent->animation.frame = f; if (!ent->visibility.efrag) { - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } } @@ -721,7 +721,7 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) angles[2] = 0; CL_TransformEntity (tent->ent, 1, angles, position); - R_AddEfrags (&cl_world.worldmodel->brush, tent->ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, tent->ent); } *tail = cl_projectiles; diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index 436013f79..63f92ff5b 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -119,7 +119,7 @@ CL_ParseStatic (qmsg_t *msg, int version) CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin); - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } static void @@ -205,9 +205,14 @@ CL_LoadSky (const char *name) void CL_World_NewMap (const char *mapname, const char *skyname) { + model_t *worldmodel = cl_world.models.a[1]; + cl_world.scene->worldmodel = worldmodel; + cl_static_entities.size = 0; - r_funcs->R_NewMap (cl_world.worldmodel, - cl_world.models.a, cl_world.models.size); + + cl_world.scene->models = cl_world.models.a; + cl_world.scene->num_models = cl_world.models.size; + SCR_NewScene (cl_world.scene); if (cl_world.models.a[1] && cl_world.models.a[1]->brush.entities) { if (cl_world.edicts) { PL_Free (cl_world.edicts); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index f7056bcfb..681ca0771 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -66,6 +66,7 @@ #include "QF/GL/qf_vid.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "mod_internal.h" #include "r_internal.h" @@ -152,7 +153,7 @@ register_textures (mod_brush_t *brush) } void -gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) +gl_R_NewScene (scene_t *scene) { texture_t *tex; mod_brush_t *brush; @@ -160,8 +161,8 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) for (int i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value - r_refdef.worldmodel = worldmodel; - brush = &worldmodel->brush; + r_refdef.worldmodel = scene->worldmodel; + brush = &scene->worldmodel->brush; // clear out efrags in case the level hasn't been reloaded for (unsigned i = 0; i < brush->modleafs; i++) @@ -173,7 +174,7 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) R_ClearParticles (); - GL_BuildLightmaps (models, num_models); + GL_BuildLightmaps (scene->models, scene->num_models); // identify sky texture gl_R_ClearTextures (); @@ -189,13 +190,13 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) gl_R_InitSurfaceChains (brush); gl_R_AddTexture (r_notexture_mip); register_textures (brush); - for (int i = 0; i < num_models; i++) { - if (!models[i]) + for (int i = 0; i < scene->num_models; i++) { + if (!scene->models[i]) continue; - if (*models[i]->path == '*') + if (*scene->models[i]->path == '*') continue; - if (models[i] != r_refdef.worldmodel - && models[i]->type == mod_brush) - register_textures (&models[i]->brush); + if (scene->models[i] != r_refdef.worldmodel + && scene->models[i]->type == mod_brush) + register_textures (&scene->models[i]->brush); } } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index ba5ef36f2..5ea42af56 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -46,6 +46,7 @@ #include "QF/sys.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" @@ -188,23 +189,23 @@ glsl_R_Init (void) } void -glsl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) +glsl_R_NewScene (scene_t *scene) { int i; for (i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value - r_refdef.worldmodel = worldmodel; + r_refdef.worldmodel = scene->worldmodel; // Force a vis update r_refdef.viewleaf = NULL; R_MarkLeaves (); R_ClearParticles (); - glsl_R_RegisterTextures (models, num_models); - glsl_R_BuildLightmaps (models, num_models); - glsl_R_BuildDisplayLists (models, num_models); + glsl_R_RegisterTextures (scene->models, scene->num_models); + glsl_R_BuildLightmaps (scene->models, scene->num_models); + glsl_R_BuildDisplayLists (scene->models, scene->num_models); } void diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 188b0ed93..a199fa368 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -49,6 +49,7 @@ #include "QF/va.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "QF/ui/view.h" @@ -71,6 +72,7 @@ static framebuffer_t *warp_buffer; static float fov_x, fov_y; static float tan_fov_x, tan_fov_y; +static scene_t *scr_scene;//FIXME don't want this here static mat4f_t box_rotations[] = { [BOX_FRONT] = { @@ -505,3 +507,15 @@ SCR_Init (void) Cvar_AddListener (var, viewsize_listener, 0); update_vrect (); } + +void +SCR_NewScene (scene_t *scene) +{ + scr_scene = scene; + if (scene) { + r_funcs->set_fov (tan_fov_x, tan_fov_y); + r_funcs->R_NewScene (scene); + } else { + r_funcs->R_ClearState (); + } +} diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index e05755a80..9bd3c3f1c 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -49,6 +49,7 @@ #include "QF/sys.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "compat.h" #include "mod_internal.h" @@ -151,8 +152,9 @@ sw_R_Init (void) } void -R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) +R_NewScene (scene_t *scene) { + model_t *worldmodel = scene->worldmodel; mod_brush_t *brush = &worldmodel->brush; r_refdef.worldmodel = worldmodel; diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index fa0c7738b..9d99ca43d 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -510,7 +510,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_Init, gl_R_ClearState, gl_R_LoadSkys, - gl_R_NewMap, + gl_R_NewScene, gl_R_LineGraph, gl_begin_frame, gl_render_view, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 4c4aff0d3..132e1f062 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -454,7 +454,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_Init, glsl_R_ClearState, glsl_R_LoadSkys, - glsl_R_NewMap, + glsl_R_NewScene, glsl_R_LineGraph, glsl_begin_frame, glsl_render_view, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 5d8c18f0c..a7d69ada7 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -474,7 +474,7 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_R_Init, R_ClearState, R_LoadSkys, - R_NewMap, + R_NewScene, R_LineGraph, sw_begin_frame, sw_render_view, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 424363571..a52e3b7eb 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -64,6 +64,7 @@ #include "QF/ui/view.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "mod_internal.h" #include "r_internal.h" @@ -118,9 +119,9 @@ vulkan_R_LoadSkys (const char *skyname) } static void -vulkan_R_NewMap (model_t *worldmodel, model_t **models, int num_models) +vulkan_R_NewScene (scene_t *scene) { - Vulkan_NewMap (worldmodel, models, num_models, vulkan_ctx); + Vulkan_NewScene (scene, vulkan_ctx); } static void @@ -727,7 +728,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_R_Init, vulkan_R_ClearState, vulkan_R_LoadSkys, - vulkan_R_NewMap, + vulkan_R_NewScene, vulkan_R_LineGraph, vulkan_begin_frame, vulkan_render_view, diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 6acf30d09..17c74ec6b 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -46,6 +46,7 @@ #include "QF/sys.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_alias.h" @@ -130,8 +131,7 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) } void -Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, - vulkan_ctx_t *ctx) +Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) { int i; @@ -139,17 +139,17 @@ Vulkan_NewMap (model_t *worldmodel, struct model_s **models, int num_models, d_lightstylevalue[i] = 264; // normal light value } - r_refdef.worldmodel = worldmodel; + r_refdef.worldmodel = scene->worldmodel; // Force a vis update r_refdef.viewleaf = NULL; R_MarkLeaves (); R_ClearParticles (); - Vulkan_RegisterTextures (models, num_models, ctx); - //Vulkan_BuildLightmaps (models, num_models, ctx); - Vulkan_BuildDisplayLists (models, num_models, ctx); - Vulkan_LoadLights (worldmodel, worldmodel->brush.entities, ctx); + Vulkan_RegisterTextures (scene->models, scene->num_models, ctx); + //Vulkan_BuildLightmaps (scene->models, scene->num_models, ctx); + Vulkan_BuildDisplayLists (scene->models, scene->num_models, ctx); + Vulkan_LoadLights (scene->worldmodel, scene->worldmodel->brush.entities, ctx); } /*void diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 510ea767c..538ed10bf 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -46,6 +46,8 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/scene.h" + #include "compat.h" #include "client/world.h" @@ -375,7 +377,7 @@ demo_default_name (const char *argv1) strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim)); // the leading path-name is to be removed from cl_world.worldmodel->name - mapname = QFS_SkipPath (cl_world.worldmodel->path); + mapname = QFS_SkipPath (cl_world.scene->worldmodel->path); // the map name is cut off after any "." because this would prevent // an extension being appended diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 9d0a4d357..cdfbe644d 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -263,7 +263,7 @@ CL_RelinkEntities (void) if (ent->visibility.efrag) { R_RemoveEfrags (ent); } - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } ent->old_origin = new->origin; } else { @@ -299,10 +299,10 @@ CL_RelinkEntities (void) = Transform_GetWorldPosition (ent->transform); if (!VectorCompare (org, ent->old_origin)) {//FIXME R_RemoveEfrags (ent); - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } else { - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index e05d98c7d..0d3f0864f 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -295,7 +295,7 @@ CL_ClearState (void) CL_ClearTEnts (); - r_funcs->R_ClearState (); + SCR_NewScene (0); CL_ClearEnts (); @@ -354,7 +354,7 @@ CL_Disconnect (void) Host_ShutdownServer (false); } - cl_world.worldmodel = NULL; + cl_world.scene->worldmodel = NULL; cl.intermission = 0; cl.viewstate.intermission = 0; } @@ -467,7 +467,7 @@ CL_NextDemo (void) static void pointfile_f (void) { - CL_LoadPointFile (cl_world.worldmodel); + CL_LoadPointFile (cl_world.scene->worldmodel); } static void diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index b9c1f0ac6..db35c61fd 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -252,10 +252,13 @@ CL_KeepaliveMessage (void) static void CL_NewMap (const char *mapname) { - Con_NewMap (); - Hunk_Check (0); // make sure nothing is hurt - Sbar_CenterPrint (0); CL_World_NewMap (mapname, 0); + cl.chasestate.worldmodel = cl_world.scene->worldmodel; + + Con_NewMap (); + Sbar_CenterPrint (0); + + Hunk_Check (0); // make sure nothing is hurt } static void @@ -349,9 +352,9 @@ CL_ParseServerInfo (void) strcpy (sound_precache[cl.numsounds], str); } - // now we try to load everything else until a cache allocation fails CL_MapCfg (model_precache[1]); + // now we try to load everything else until a cache allocation fails for (i = 1; i < nummodels; i++) { DARRAY_APPEND (&cl_world.models, Mod_ForName (model_precache[i], false)); @@ -368,16 +371,12 @@ CL_ParseServerInfo (void) } // local state - cl_world.worldmodel = cl_world.models.a[1]; - cl.chasestate.worldmodel = cl_world.worldmodel; if (!centerprint) centerprint = dstring_newstr (); else dstring_clearstr (centerprint); CL_NewMap (model_precache[1]); - Hunk_Check (0); // make sure nothing is hurt - noclip_anglehack = false; // noclip is turned off at start CL_ParticlesGravity (800); // Set up gravity for renderer effects done: diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index 4bbb1f9dd..bd2effd81 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -46,6 +46,7 @@ #include "QF/plugin/vid_render.h" +#include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "QF/ui/view.h" @@ -79,10 +80,10 @@ SCR_CShift (void) mleaf_t *leaf; int contents = CONTENTS_EMPTY; - if (cls.state == ca_active && cl_world.worldmodel) { + if (cls.state == ca_active && cl_world.scene->worldmodel) { vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.worldmodel);//FIXME + leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); diff --git a/nq/source/host.c b/nq/source/host.c index ca58afed5..b1cade921 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -54,6 +54,7 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "buildnum.h" @@ -740,7 +741,7 @@ Host_ClientFrame (void) vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.worldmodel);//FIXME + l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index c7ede77e3..0026b72f5 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -54,6 +54,8 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/scene.h" + #include "compat.h" #include "client/world.h" @@ -669,8 +671,8 @@ demo_default_name (const char *argv1) time (&tim); strftime (timestring, 19, "%Y-%m-%d-%H-%M", localtime (&tim)); - // the leading path-name is to be removed from cl_world.worldmodel->name - mapname = QFS_SkipPath (cl_world.worldmodel->path); + // the leading path-name is to be removed from worldmodel->name + mapname = QFS_SkipPath (cl_world.scene->worldmodel->path); // the map name is cut off after any "." because this would prevent // an extension being appended diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 26486ae41..d9ada8aa8 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -41,6 +41,8 @@ #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/scene.h" + #include "compat.h" #include "client/temp_entities.h" @@ -530,7 +532,7 @@ CL_SetSolidEntities (void) frame_t *frame; packet_entities_t *pak; - pmove.physents[0].model = cl_world.worldmodel; + pmove.physents[0].model = cl_world.scene->worldmodel; VectorZero (pmove.physents[0].origin); VectorZero (pmove.physents[0].angles); pmove.physents[0].info = 0; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index a4955c409..49ad77cc1 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -234,7 +234,7 @@ CL_LinkPacketEntities (void) if (ent->visibility.efrag) { R_RemoveEfrags (ent); } - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } else { vec4f_t delta = new->origin - old->origin; @@ -266,15 +266,15 @@ CL_LinkPacketEntities (void) = Transform_GetWorldPosition (ent->transform); if (!VectorCompare (org, ent->old_origin)) {//FIXME R_RemoveEfrags (ent); - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } else { - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } } if (!ent->visibility.efrag) { - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } // rotate binary objects locally @@ -510,10 +510,10 @@ CL_LinkPlayers (void) } // stuff entity in map - R_AddEfrags (&cl_world.worldmodel->brush, ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); if (player->flag_ent) { CL_UpdateFlagModels (ent, j); - R_AddEfrags (&cl_world.worldmodel->brush, player->flag_ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, player->flag_ent); } } } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index bdb2ac24a..668208e6c 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -501,7 +501,7 @@ CL_Quit_f (void) static void pointfile_f (void) { - CL_LoadPointFile (cl_world.worldmodel); + CL_LoadPointFile (cl_world.scene->worldmodel); } static void @@ -794,7 +794,7 @@ CL_Disconnect (void) Info_Destroy (cl.players[i].userinfo); memset (&cl.players[i], 0, sizeof (cl.players[i])); } - cl_world.worldmodel = NULL; + cl_world.scene->worldmodel = NULL; cl.validsequence = 0; } @@ -1965,7 +1965,7 @@ Host_Frame (float time) vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.worldmodel);//FIXME + l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 5b58202ac..fa3c2075f 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -261,17 +261,19 @@ CL_CheckOrDownloadFile (const char *filename) static void CL_NewMap (const char *mapname) { - Team_NewMap (); - Con_NewMap (); - Hunk_Check (0); // make sure nothing is hurt - Sbar_CenterPrint (0); - const char *skyname = 0; // R_LoadSkys does the right thing with null pointers. if (cl.serverinfo) { skyname = Info_ValueForKey (cl.serverinfo, "sky"); } CL_World_NewMap (mapname, skyname); + cl.chasestate.worldmodel = cl_world.scene->worldmodel; + + Team_NewMap (); + Con_NewMap (); + Sbar_CenterPrint (0); + + Hunk_Check (0); // make sure nothing is hurt } static void @@ -353,8 +355,6 @@ Model_NextDownload (void) } // all done - cl_world.worldmodel = cl_world.models.a[1]; - cl.chasestate.worldmodel = cl_world.worldmodel; CL_NewMap (cl.model_name[1]); // done with modellist, request first of static signon messages @@ -362,7 +362,7 @@ Model_NextDownload (void) MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, va (0, prespawn_name, cl.servercount, - cl_world.worldmodel->brush.checksum2)); + cl_world.scene->worldmodel->brush.checksum2)); } } diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 82fd9b63d..54871dac5 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -44,6 +44,7 @@ #include "QF/pcx.h" #include "QF/screen.h" +#include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "QF/ui/view.h" @@ -78,10 +79,10 @@ SCR_CShift (void) mleaf_t *leaf; int contents = CONTENTS_EMPTY; - if (cls.state == ca_active && cl_world.worldmodel) { + if (cls.state == ca_active && cl_world.scene->worldmodel) { vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.worldmodel);//FIXME + leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); diff --git a/qw/source/sbar.c b/qw/source/sbar.c index ebc9d267e..d016aeb11 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -53,6 +53,8 @@ #include "QF/plugin/console.h" +#include "QF/scene/scene.h" + #include "QF/ui/view.h" #include "compat.h" @@ -1062,7 +1064,7 @@ Sbar_LogFrags (void) Qwrite (file, t, strlen (t)); Qprintf (file, "%s\n%s %s\n", cls.servername->str, - cl_world.worldmodel->path, cl.levelname); + cl_world.scene->worldmodel->path, cl.levelname); // scores Sbar_SortFrags (true); diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index 926093007..5bca2f58d 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -49,6 +49,8 @@ #include "QF/sys.h" #include "QF/teamplay.h" +#include "QF/scene/scene.h" + #include "compat.h" #include "client/locs.h" @@ -332,8 +334,8 @@ Team_NewMap (void) died = false; recorded_location = false; - mapname = strdup (cl_world.worldmodel->path); - t2 = malloc (sizeof (cl_world.worldmodel->path)); + mapname = strdup (cl_world.scene->worldmodel->path); + t2 = malloc (sizeof (cl_world.scene->worldmodel->path)); if (!mapname || !t2) Sys_Error ("Can't duplicate mapname!"); map_to_loc (mapname,t2); @@ -376,16 +378,16 @@ locs_loc (void) "parameter\n"); return; } - if (!cl_world.worldmodel) { + if (!cl_world.scene->worldmodel) { Sys_Printf ("No map loaded. Unable to work with location markers.\n"); return; } if (Cmd_Argc () >= 3) desc = Cmd_Args (2); - mapname = malloc (sizeof (cl_world.worldmodel->path)); + mapname = malloc (sizeof (cl_world.scene->worldmodel->path)); if (!mapname) Sys_Error ("Can't duplicate mapname!"); - map_to_loc (cl_world.worldmodel->path, mapname); + map_to_loc (cl_world.scene->worldmodel->path, mapname); snprintf (locfile, sizeof (locfile), "%s/%s", qfs_gamedir->dir.def, mapname); free (mapname); diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 0e272a07a..6b1737906 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -233,5 +233,5 @@ BI_Graphics_Init (progs_t *pr) if (mod_funcs->Mod_ProcessTexture) { mod_funcs->Mod_ProcessTexture (&empty_world, 0); } - r_funcs->R_NewMap (&empty_world, 0, 0); + //r_funcs->R_NewMap (&empty_world, 0, 0); } From 9ee0eada1f462ce1f6c0e91948148949f6611e70 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 14:58:47 +0900 Subject: [PATCH 2752/3664] [vulkan] Move non-specific lighting code out of Vulkan The parsing of light data from maps is now in the client library, and basic light management is in scene. Putting the light loading code into the Vulkan renderer was a mistake I've wanted to correct for a while. The client code still needs a bit of cleanup, but the basics are working nicely. --- include/QF/Makemodule.am | 1 + include/QF/Vulkan/qf_lighting.h | 39 +- include/QF/render.h | 1 - include/QF/scene/light.h | 80 ++++ include/QF/scene/scene.h | 2 + include/QF/sys_developer.h | 1 + include/client/world.h | 3 + include/r_internal.h | 2 +- libs/client/Makemodule.am | 1 + libs/client/cl_light.c | 320 +++++++++++++ libs/client/cl_world.c | 5 + libs/scene/Makemodule.am | 1 + libs/scene/light.c | 140 ++++++ libs/video/renderer/gl/gl_rmisc.c | 3 +- libs/video/renderer/glsl/glsl_main.c | 3 +- libs/video/renderer/r_bsp.c | 10 +- libs/video/renderer/r_screen.c | 11 +- libs/video/renderer/sw/sw_rmain.c | 3 +- libs/video/renderer/vulkan/vulkan_lighting.c | 458 ++----------------- libs/video/renderer/vulkan/vulkan_main.c | 5 +- 20 files changed, 609 insertions(+), 480 deletions(-) create mode 100644 include/QF/scene/light.h create mode 100644 libs/client/cl_light.c create mode 100644 libs/scene/light.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index c9783b4fa..7c255e882 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -149,6 +149,7 @@ include_qf_scene = \ include/QF/scene/camera.h \ include/QF/scene/entity.h \ include/QF/scene/hierarchy.h \ + include/QF/scene/light.h \ include/QF/scene/transform.h \ include/QF/scene/scene.h \ include/QF/scene/types.h diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index f8b6e5d84..ef6a6bb24 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -33,41 +33,23 @@ #include "QF/darray.h" #include "QF/model.h" #include "QF/modelgen.h" +#include "QF/scene/light.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/image.h" #include "QF/simd/types.h" -typedef struct qfv_light_s { - vec4f_t color; - vec4f_t position; - vec4f_t direction; - vec4f_t attenuation; -} qfv_light_t; - -typedef struct qfv_lightset_s DARRAY_TYPE (qfv_light_t) qfv_lightset_t; -typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightintset_t; -typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t; typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t; #define MaxLights 256 -#define LM_LINEAR 0 // light - dist (or radius + dist if -ve) -#define LM_INVERSE 1 // distFactor1 * light / dist -#define LM_INVERSE2 2 // distFactor2 * light / (dist * dist) -#define LM_INFINITE 3 // light -#define LM_AMBIENT 4 // light -#define LM_INVERSE3 5 // distFactor2 * light / (dist + distFactor2)**2 - #define ST_NONE 0 // no shadows #define ST_PLANE 1 // single plane shadow map (small spotlight) #define ST_CASCADE 2 // cascaded shadow maps #define ST_CUBE 3 // cubemap (omni, large spotlight) -#define NumStyles 64 - typedef struct qfv_light_buffer_s { - qfv_light_t lights[MaxLights] __attribute__((aligned(16))); + light_t lights[MaxLights] __attribute__((aligned(16))); int lightCount; //mat4f_t shadowMat[MaxLights]; //vec4f_t shadowCascade[MaxLights]; @@ -92,11 +74,6 @@ typedef struct lightingframe_s { VkWriteDescriptorSet shadowWrite; }; }; - // A fat PVS of leafs visible from visible leafs so hidden lights can - // illuminate the leafs visible to the player - struct set_s *pvs; - struct mleaf_s *leaf; // the last leaf used to generate the pvs - qfv_lightvisset_t lightvis; } lightingframe_t; typedef struct lightingframeset_s @@ -109,14 +86,13 @@ typedef struct lightingctx_s { VkSampler sampler; VkDeviceMemory light_memory; VkDeviceMemory shadow_memory; - qfv_lightset_t lights; - qfv_lightintset_t lightstyles; - qfv_lightintset_t lightleafs; qfv_lightmatset_t lightmats; qfv_imageset_t lightimages; - qfv_lightintset_t lightlayers; + lightintset_t lightlayers; qfv_imageviewset_t lightviews; - struct set_s *sun_pvs; + + struct lightingdata_s *ldata; + struct scene_s *scene; } lightingctx_t; struct vulkan_ctx_s; @@ -125,7 +101,6 @@ struct qfv_renderframe_s; void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Draw (struct qfv_renderframe_s *rFrame); -void Vulkan_LoadLights (model_t *model, const char *entity_data, - struct vulkan_ctx_s *ctx); +void Vulkan_LoadLights (struct scene_s *scene, struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_lighting_h diff --git a/include/QF/render.h b/include/QF/render.h index 01994d095..9ad381c89 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -167,7 +167,6 @@ typedef struct { int drawflat; struct model_s *worldmodel; - struct mleaf_s *viewleaf; } refdef_t; // REFRESH ==================================================================== diff --git a/include/QF/scene/light.h b/include/QF/scene/light.h new file mode 100644 index 000000000..4c6845c20 --- /dev/null +++ b/include/QF/scene/light.h @@ -0,0 +1,80 @@ +/* + light.h + + Entity management + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/02/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_scene_light_h +#define __QF_scene_light_h + +#include "QF/darray.h" +#include "QF/qtypes.h" +#include "QF/simd/types.h" + +struct mod_brush_s; + +#define NumStyles 64 +#define NoStyle -1 + +#define LM_LINEAR 0 // light - dist (or radius + dist if -ve) +#define LM_INVERSE 1 // distFactor1 * light / dist +#define LM_INVERSE2 2 // distFactor2 * light / (dist * dist) +#define LM_INFINITE 3 // light +#define LM_AMBIENT 4 // light +#define LM_INVERSE3 5 // distFactor2 * light / (dist + distFactor2)**2 + +typedef struct light_s { + vec4f_t color; + vec4f_t position; + vec4f_t direction; + vec4f_t attenuation; +} light_t; + +typedef struct lightset_s DARRAY_TYPE (light_t) lightset_t; +typedef struct lightleafset_s DARRAY_TYPE (int) lightintset_t; +typedef struct lightvisset_s DARRAY_TYPE (byte) lightvisset_t; + +typedef struct lightingdata_s { + lightset_t lights; + lightintset_t lightstyles; + lightintset_t lightleafs; + lightvisset_t lightvis; + struct set_s *sun_pvs; + // A fat PVS of leafs visible from visible leafs so hidden lights can + // illuminate the leafs visible to the player + struct set_s *pvs; + struct mleaf_s *leaf; // the last leaf used to generate the pvs + struct scene_s *scene; +} lightingdata_t; + +lightingdata_t *Light_CreateLightingData (struct scene_s *scene); +void Light_DestroyLightingData (lightingdata_t *ldata); +void Light_ClearLights (lightingdata_t *ldata); +void Light_EnableSun (lightingdata_t *ldata); +void Light_FindVisibleLights (lightingdata_t *ldata); + +#endif//__QF_scene_light_h diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index 66995bb9e..ec95221a2 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -46,6 +46,8 @@ typedef struct scene_s { struct model_s *worldmodel; int num_models; struct model_s **models; + struct mleaf_s *viewleaf; + struct lightingdata_s *lights; } scene_t; scene_t *Scene_NewScene (void); diff --git a/include/QF/sys_developer.h b/include/QF/sys_developer.h index 3dd3ba303..881742430 100644 --- a/include/QF/sys_developer.h +++ b/include/QF/sys_developer.h @@ -44,6 +44,7 @@ SYS_DEVELOPER (glt) SYS_DEVELOPER (glsl) SYS_DEVELOPER (skin) SYS_DEVELOPER (model) +SYS_DEVELOPER (lighting) SYS_DEVELOPER (vulkan) SYS_DEVELOPER (vulkan_parse) diff --git a/include/client/world.h b/include/client/world.h index ba67d9c35..e96ec48e3 100644 --- a/include/client/world.h +++ b/include/client/world.h @@ -50,6 +50,7 @@ extern worldscene_t cl_world; struct msg_s; struct entity_state_s; +struct lightingdata_s; void CL_World_Init (void); @@ -65,5 +66,7 @@ void CL_ParseBaseline (struct msg_s *msg, struct entity_state_s *baseline, void CL_ParseStatic (struct msg_s *msg, int version); void CL_MapCfg (const char *mapname); void CL_World_NewMap (const char *mapname, const char *skyname); +void CL_LoadLights (struct model_s *model, const char *entity_data, + struct lightingdata_s *ldata); #endif//__client_world_h diff --git a/include/r_internal.h b/include/r_internal.h index 2d8feccc4..95a1c26bc 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -74,7 +74,7 @@ struct entity_s; struct animation_s; void R_DrawAliasModel (struct entity_s *e); -void R_MarkLeaves (void); +void R_MarkLeaves (struct mleaf_s *viewleaf); void GL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette); diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 95664df07..92d058458 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -7,6 +7,7 @@ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_effects.c \ libs/client/cl_entities.c \ libs/client/cl_input.c \ + libs/client/cl_light.c \ libs/client/cl_particles.c \ libs/client/cl_temp_entities.c \ libs/client/cl_view.c \ diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c new file mode 100644 index 000000000..8aa9cb39c --- /dev/null +++ b/libs/client/cl_light.c @@ -0,0 +1,320 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/dstring.h" +#include "QF/mathlib.h" +#include "QF/model.h" +#include "QF/plist.h" +#include "QF/progs.h" //for ED_ConvertToPlist +#include "QF/script.h" +#include "QF/set.h" +#include "QF/scene/light.h" +#include "QF/simd/vec4f.h" + +#include "client/world.h" + +static void +dump_light (light_t *light, int leaf) +{ + Sys_MaskPrintf (SYS_lighting, + "[%g, %g, %g] %g, " + "[%g, %g, %g, %g], [%g %g %g] %g, [%g, %g, %g, %g] %d\n", + VEC4_EXP (light->color), + VEC4_EXP (light->position), + VEC4_EXP (light->direction), + VEC4_EXP (light->attenuation), + leaf); +} + +static float +parse_float (const char *str, float defval) +{ + float val = defval; + if (str) { + char *end; + val = strtof (str, &end); + if (end == str) { + val = defval; + } + } + return val; +} + +static void +parse_vector (const char *str, vec_t *val) +{ + if (str) { + int num = sscanf (str, "%f %f %f", VectorExpandAddr (val)); + while (num < 3) { + val[num++] = 0; + } + } +} + +static float +ecos (float ang) +{ + if (ang == 90 || ang == -90) { + return 0; + } + if (ang == 180 || ang == -180) { + return -1; + } + if (ang == 0 || ang == 360) { + return 1; + } + return cos (ang * M_PI / 180); +} + +static float +esin (float ang) +{ + if (ang == 90) { + return 1; + } + if (ang == -90) { + return -1; + } + if (ang == 180 || ang == -180) { + return 0; + } + if (ang == 0 || ang == 360) { + return 0; + } + return sin (ang * M_PI / 180); +} + +static vec4f_t +sun_vector (const vec_t *ang) +{ + // ang is yaw, pitch (maybe roll, but ignored + vec4f_t vec = { + ecos (ang[1]) * ecos (ang[0]), + ecos (ang[1]) * esin (ang[0]), + esin (ang[1]), + 0, + }; + return vec; +} + +static void +parse_sun (lightingdata_t *ldata, plitem_t *entity) +{ + light_t light = {}; + float sunlight; + //float sunlight2; + vec3_t sunangle = { 0, -90, 0 }; + + Light_EnableSun (ldata); + sunlight = parse_float (PL_String (PL_ObjectForKey (entity, + "_sunlight")), 0); + //sunlight2 = parse_float (PL_String (PL_ObjectForKey (entity, + // "_sunlight2")), 0); + parse_vector (PL_String (PL_ObjectForKey (entity, "_sun_mangle")), + sunangle); + if (sunlight <= 0) { + return; + } + VectorSet (1, 1, 1, light.color); + light.color[3] = sunlight; + light.position = sun_vector (sunangle); + light.direction = light.position; + light.direction[3] = 1; + light.attenuation = (vec4f_t) { 0, 0, 1, 0 }; + DARRAY_APPEND (&ldata->lights, light); + DARRAY_APPEND (&ldata->lightstyles, 0); + DARRAY_APPEND (&ldata->lightleafs, -1); +} + +static vec4f_t +parse_position (const char *str) +{ + vec3_t vec = {}; + sscanf (str, "%f %f %f", VectorExpandAddr (vec)); + return (vec4f_t) {vec[0], vec[1], vec[2], 1}; +} + +static void +parse_light (light_t *light, int *style, const plitem_t *entity, + const plitem_t *targets) +{ + const char *str; + int model = 0; + + /*Sys_Printf ("{\n"); + for (int i = PL_D_NumKeys (entity); i-- > 0; ) { + const char *field = PL_KeyAtIndex (entity, i); + const char *value = PL_String (PL_ObjectForKey (entity, field)); + Sys_Printf ("\t%s = %s\n", field, value); + } + Sys_Printf ("}\n");*/ + + // omnidirectional light (unit length xyz so not treated as ambient) + light->direction = (vec4f_t) { 0, 0, 1, 1 }; + // bright white + light->color = (vec4f_t) { 1, 1, 1, 300 }; + + if ((str = PL_String (PL_ObjectForKey (entity, "origin")))) { + light->position = parse_position (str); + } + + if ((str = PL_String (PL_ObjectForKey (entity, "target")))) { + plitem_t *target = PL_ObjectForKey (targets, str); + vec4f_t dir = { 1, 0, 0, 0 }; + if (target) { + if ((str = PL_String (PL_ObjectForKey (target, "origin")))) { + dir = parse_position (str); + dir = normalf (dir - light->position); + } + } + + float angle = 40; + if ((str = PL_String (PL_ObjectForKey (entity, "angle")))) { + angle = atof (str); + } + dir[3] = -cos (angle * M_PI / 360); // half angle + light->direction = dir; + } + + if ((str = PL_String (PL_ObjectForKey (entity, "light_lev"))) + || (str = PL_String (PL_ObjectForKey (entity, "_light")))) { + light->color[3] = atof (str); + } + + if ((str = PL_String (PL_ObjectForKey (entity, "style")))) { + *style = atoi (str) & 0x3f; + } + + if ((str = PL_String (PL_ObjectForKey (entity, "delay")))) { + model = atoi (str) & 0x7; + if (model == LM_INVERSE2) { + model = LM_INVERSE3; //FIXME for marcher (need a map) + } + } + + if ((str = PL_String (PL_ObjectForKey (entity, "color"))) + || (str = PL_String (PL_ObjectForKey (entity, "_color")))) { + sscanf (str, "%f %f %f", VectorExpandAddr (light->color)); + VectorScale (light->color, 1/255.0, light->color); + } + + vec4f_t attenuation = { 1, 0, 0, 0 }; // inverse square + switch (model) { + case LM_LINEAR: + attenuation = (vec4f_t) { 0, 0, 1, 1 / fabsf (light->color[3]) }; + break; + case LM_INVERSE: + attenuation = (vec4f_t) { 0, 1.0 / 128, 0, 0 }; + break; + case LM_INVERSE2: + attenuation = (vec4f_t) { 1.0 / 16384, 0, 0, 0 }; + break; + case LM_INFINITE: + attenuation = (vec4f_t) { 0, 0, 1, 0 }; + break; + case LM_AMBIENT: + attenuation = (vec4f_t) { 0, 0, 1, 0 }; + light->direction = (vec4f_t) { 0, 0, 0, 1 }; + break; + case LM_INVERSE3: + attenuation = (vec4f_t) { 1.0 / 16384, 2.0 / 128, 1, 0 }; + break; + } + light->attenuation = attenuation; +} + +static void +locate_lights (model_t *model, lightingdata_t *ldata) +{ + light_t *lights = ldata->lights.a; + DARRAY_RESIZE (&ldata->lightleafs, ldata->lights.size); + for (size_t i = 0; i < ldata->lights.size; i++) { + mleaf_t *leaf = Mod_PointInLeaf (&lights[i].position[0], model); + ldata->lightleafs.a[i] = leaf - model->brush.leafs - 1; + } +} + +void +CL_LoadLights (model_t *model, const char *entity_data, lightingdata_t *ldata) +{ + plitem_t *entities = 0; + + if (!entity_data) { + return; + } + + Light_ClearLights (ldata); + + ldata->sun_pvs = set_new_size (model->brush.visleafs); + + script_t *script = Script_New (); + Script_Start (script, "ent data", entity_data); + + if (Script_GetToken (script, 1)) { + if (!strcmp (script->token->str, "(")) { + // new style (plist) entity data + entities = PL_GetPropertyList (entity_data, 0); + } else { + // old style entity data + Script_UngetToken (script); + // FIXME ED_ConvertToPlist aborts if an error is encountered. + entities = ED_ConvertToPlist (script, 0, 0); + } + } + Script_Delete (script); + + if (entities) { + plitem_t *targets = PL_NewDictionary (0); + + // find all the targets so spotlights can be aimed + for (int i = 1; i < PL_A_NumObjects (entities); i++) { + plitem_t *entity = PL_ObjectAtIndex (entities, i); + const char *targetname = PL_String (PL_ObjectForKey (entity, + "targetname")); + if (targetname && !PL_ObjectForKey (targets, targetname)) { + PL_D_AddObject (targets, targetname, entity); + } + } + + for (int i = 0; i < PL_A_NumObjects (entities); i++) { + plitem_t *entity = PL_ObjectAtIndex (entities, i); + const char *classname = PL_String (PL_ObjectForKey (entity, + "classname")); + if (!classname) { + continue; + } + if (!strcmp (classname, "worldspawn")) { + // parse_sun can add many lights + parse_sun (ldata, entity); + } else if (!strncmp (classname, "light", 5)) { + light_t light = {}; + int style = 0; + + parse_light (&light, &style, entity, targets); + // some lights have 0 output, so drop them + if (light.color[3]) { + DARRAY_APPEND (&ldata->lights, light); + DARRAY_APPEND (&ldata->lightstyles, style); + } + } + } + DARRAY_RESIZE (&ldata->lightvis, ldata->lights.size); + // targets does not own the objects, so need to remove them before + // freeing targets + for (int i = PL_D_NumKeys (targets); i-- > 0; ) { + PL_RemoveObjectForKey (targets, PL_KeyAtIndex (targets, i)); + } + PL_Free (targets); + PL_Free (entities); + } + if (ldata->lights.size) { + locate_lights (model, ldata); + for (size_t i = 0; i < ldata->lights.size; i++) { + dump_light (&ldata->lights.a[i], ldata->lightleafs.a[i]); + } + } + Sys_MaskPrintf (SYS_lighting, "loaded %zd lights\n", ldata->lights.size); +} diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index 63f92ff5b..1bcb256fa 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -47,6 +47,7 @@ #include "QF/msg.h" #include "QF/scene/entity.h" +#include "QF/scene/light.h" #include "QF/scene/scene.h" #include "QF/simd/vec4f.h" @@ -64,6 +65,7 @@ void CL_World_Init (void) { cl_world.scene = Scene_NewScene (); + cl_world.scene->lights = Light_CreateLightingData (cl_world.scene); } void @@ -210,6 +212,9 @@ CL_World_NewMap (const char *mapname, const char *skyname) cl_static_entities.size = 0; + const char *entity_data = worldmodel->brush.entities; + CL_LoadLights (worldmodel, entity_data, cl_world.scene->lights); + cl_world.scene->models = cl_world.models.a; cl_world.scene->num_models = cl_world.models.size; SCR_NewScene (cl_world.scene); diff --git a/libs/scene/Makemodule.am b/libs/scene/Makemodule.am index 25b3e7562..13cfb6dca 100644 --- a/libs/scene/Makemodule.am +++ b/libs/scene/Makemodule.am @@ -11,5 +11,6 @@ libs_scene_libQFscene_la_SOURCES= \ libs/scene/camera.c \ libs/scene/entity.c \ libs/scene/hierarchy.c \ + libs/scene/light.c \ libs/scene/scene.c \ libs/scene/transform.c diff --git a/libs/scene/light.c b/libs/scene/light.c new file mode 100644 index 000000000..fc38e71af --- /dev/null +++ b/libs/scene/light.c @@ -0,0 +1,140 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/model.h" +#include "QF/set.h" +#include "QF/scene/light.h" +#include "QF/scene/scene.h" +#include "QF/simd/vec4f.h" + +static void +expand_pvs (set_t *pvs, model_t *model) +{ + set_t base_pvs = SET_STATIC_INIT (model->brush.visleafs, alloca); + set_assign (&base_pvs, pvs); + for (unsigned i = 0; i < model->brush.visleafs; i++) { + if (set_is_member (&base_pvs, i)) { + Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, pvs); + } + } +} + +lightingdata_t * +Light_CreateLightingData (scene_t *scene) +{ + lightingdata_t *ldata = calloc (1, sizeof (lightingdata_t)); + + DARRAY_INIT (&ldata->lights, 16); + DARRAY_INIT (&ldata->lightstyles, 16); + DARRAY_INIT (&ldata->lightleafs, 16); + DARRAY_INIT (&ldata->lightvis, 16); + + ldata->scene = scene; + + return ldata; +} + +void +Light_DestroyLightingData (lightingdata_t *ldata) +{ + DARRAY_CLEAR (&ldata->lights); + DARRAY_CLEAR (&ldata->lightstyles); + DARRAY_CLEAR (&ldata->lightleafs); + DARRAY_CLEAR (&ldata->lightvis); + + free (ldata); +} + +void +Light_ClearLights (lightingdata_t *ldata) +{ + ldata->lights.size = 0; + ldata->lightstyles.size = 0; + ldata->lightleafs.size = 0; + ldata->lightvis.size = 0; + if (ldata->sun_pvs) { + set_delete (ldata->sun_pvs); + } + ldata->sun_pvs = 0; + if (ldata->pvs) { + set_delete (ldata->pvs); + } + ldata->pvs = 0; + ldata->leaf = 0; +} + +void +Light_EnableSun (lightingdata_t *ldata) +{ + scene_t *scene = ldata->scene; + model_t *model = scene->worldmodel; + + if (!ldata->sun_pvs) { + ldata->sun_pvs = set_new_size (model->brush.visleafs); + } + set_expand (ldata->sun_pvs, model->brush.visleafs); + set_empty (ldata->sun_pvs); + // Any leaf with sky surfaces can potentially see the sun, thus put + // the sun "in" every leaf with a sky surface + // however, skip leaf 0 as it is the exterior solid leaf + for (unsigned l = 1; l < model->brush.modleafs; l++) { + if (model->brush.leaf_flags[l] & SURF_DRAWSKY) { + set_add (ldata->sun_pvs, l - 1); //pvs is 1-based + } + } + // any leaf visible from a leaf with a sky surface (and thus the sun) + // can receive shadows from the sun + expand_pvs (ldata->sun_pvs, model); +} + +void +Light_FindVisibleLights (lightingdata_t *ldata) +{ + scene_t *scene = ldata->scene; + mleaf_t *leaf = scene->viewleaf; + model_t *model = scene->worldmodel; + + if (!leaf) { + return; + } + if (!ldata->pvs) { + ldata->pvs = set_new_size (model->brush.visleafs); + } + + if (leaf != ldata->leaf) { + //double start = Sys_DoubleTime (); + int flags = 0; + + if (leaf == model->brush.leafs) { + set_everything (ldata->pvs); + } else { + Mod_LeafPVS_set (leaf, model, 0, ldata->pvs); + expand_pvs (ldata->pvs, model); + } + for (unsigned i = 0; i < model->brush.visleafs; i++) { + if (set_is_member (ldata->pvs, i)) { + flags |= model->brush.leaf_flags[i + 1]; + } + } + ldata->leaf = leaf; + + //double end = Sys_DoubleTime (); + //Sys_Printf ("find_visible_lights: %.5gus\n", (end - start) * 1e6); + + int visible = 0; + memset (ldata->lightvis.a, 0, ldata->lightvis.size * sizeof (byte)); + for (size_t i = 0; i < ldata->lightleafs.size; i++) { + int l = ldata->lightleafs.a[i]; + if ((l == -1 && (flags & SURF_DRAWSKY)) + || set_is_member (ldata->pvs, l)) { + ldata->lightvis.a[i] = 1; + visible++; + } + } + //Sys_Printf ("find_visible_lights: %d / %zd visible\n", visible, + // ldata->lightvis.size); + } +} diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 681ca0771..19aea339d 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -169,8 +169,7 @@ gl_R_NewScene (scene_t *scene) brush->leafs[i].efrags = NULL; // Force a vis update - r_refdef.viewleaf = NULL; - R_MarkLeaves (); + R_MarkLeaves (0); R_ClearParticles (); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 5ea42af56..7c8d04502 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -199,8 +199,7 @@ glsl_R_NewScene (scene_t *scene) r_refdef.worldmodel = scene->worldmodel; // Force a vis update - r_refdef.viewleaf = NULL; - R_MarkLeaves (); + R_MarkLeaves (0); R_ClearParticles (); glsl_R_RegisterTextures (scene->models, scene->num_models); diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 31951b46f..2976bda16 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -47,7 +47,7 @@ static mleaf_t *r_oldviewleaf; static set_t *solid; void -R_MarkLeaves (void) +R_MarkLeaves (mleaf_t *viewleaf) { set_t *vis; int c; @@ -56,12 +56,12 @@ R_MarkLeaves (void) msurface_t **mark; mod_brush_t *brush = &r_refdef.worldmodel->brush; - if (r_oldviewleaf == r_refdef.viewleaf && !r_novis) + if (r_oldviewleaf == viewleaf && !r_novis) return; r_visframecount++; - r_oldviewleaf = r_refdef.viewleaf; - if (!r_refdef.viewleaf) + r_oldviewleaf = viewleaf; + if (!viewleaf) return; if (r_novis) { @@ -73,7 +73,7 @@ R_MarkLeaves (void) } vis = solid; } else - vis = Mod_LeafPVS (r_refdef.viewleaf, r_refdef.worldmodel); + vis = Mod_LeafPVS (viewleaf, r_refdef.worldmodel); for (unsigned i = 0; i < brush->visleafs; i++) { if (set_is_member (vis, i)) { diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index a199fa368..365bb9dde 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -270,20 +270,21 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) R_RunParticles (r_data->frametime); R_AnimateLight (); - refdef->viewleaf = 0; - if (refdef->worldmodel) { + if (scr_scene && scr_scene->worldmodel) { + scr_scene->viewleaf = 0; vec4f_t position = refdef->frame.position; - refdef->viewleaf = Mod_PointInLeaf ((vec_t*)&position, refdef->worldmodel);//FIXME + scr_scene->viewleaf = Mod_PointInLeaf ((vec_t*)&position, + scr_scene->worldmodel);//FIXME r_dowarpold = r_dowarp; if (r_waterwarp) { - r_dowarp = refdef->viewleaf->contents <= CONTENTS_WATER; + r_dowarp = scr_scene->viewleaf->contents <= CONTENTS_WATER; } if (r_dowarp && !warp_buffer) { warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, r_data->vid->height); } + R_MarkLeaves (scr_scene->viewleaf); } - R_MarkLeaves (); R_PushDlights (vec3_origin); r_funcs->begin_frame (); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 9bd3c3f1c..03d988965 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -167,8 +167,7 @@ R_NewScene (scene_t *scene) R_InitSky (brush->skytexture); // Force a vis update - r_refdef.viewleaf = NULL; - R_MarkLeaves (); + R_MarkLeaves (0); R_ClearParticles (); diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 7a97377d3..ad8252160 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -50,6 +50,8 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/scene.h" + #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/barrier.h" @@ -68,79 +70,16 @@ #include "r_internal.h" #include "vid_vulkan.h" -static vec4f_t ref_direction = { 0, 0, 1, 0 }; - -static void -expand_pvs (set_t *pvs, model_t *model) -{ - set_t base_pvs = SET_STATIC_INIT (model->brush.visleafs, alloca); - set_assign (&base_pvs, pvs); - for (unsigned i = 0; i < model->brush.visleafs; i++) { - if (set_is_member (&base_pvs, i)) { - Mod_LeafPVS_mix (model->brush.leafs + i + 1, model, 0, pvs); - } - } -} - -static void -find_visible_lights (vulkan_ctx_t *ctx) -{ - //qfv_device_t *device = ctx->device; - //qfv_devfuncs_t *dfunc = device->funcs; - lightingctx_t *lctx = ctx->lighting_context; - lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; - - mleaf_t *leaf = r_refdef.viewleaf; - model_t *model = r_refdef.worldmodel; - - if (!leaf || !model) { - return; - } - - if (leaf != lframe->leaf) { - //double start = Sys_DoubleTime (); - int flags = 0; - - if (leaf == model->brush.leafs) { - set_everything (lframe->pvs); - } else { - Mod_LeafPVS_set (leaf, model, 0, lframe->pvs); - expand_pvs (lframe->pvs, model); - } - for (unsigned i = 0; i < model->brush.visleafs; i++) { - if (set_is_member (lframe->pvs, i)) { - flags |= model->brush.leaf_flags[i + 1]; - } - } - lframe->leaf = leaf; - - //double end = Sys_DoubleTime (); - //Sys_Printf ("find_visible_lights: %.5gus\n", (end - start) * 1e6); - - int visible = 0; - memset (lframe->lightvis.a, 0, lframe->lightvis.size * sizeof (byte)); - for (size_t i = 0; i < lctx->lightleafs.size; i++) { - int l = lctx->lightleafs.a[i]; - if ((l == -1 && (flags & SURF_DRAWSKY)) - || set_is_member (lframe->pvs, l)) { - lframe->lightvis.a[i] = 1; - visible++; - } - } - //Sys_Printf ("find_visible_lights: %d / %zd visible\n", visible, - // lframe->lightvis.size); - } -} - static void update_lights (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; lightingctx_t *lctx = ctx->lighting_context; + lightingdata_t *ldata = lctx->ldata; lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; - find_visible_lights (ctx); + Light_FindVisibleLights (ldata); dlight_t *lights[MaxLights]; qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); @@ -168,12 +107,12 @@ update_lights (vulkan_ctx_t *ctx) light_data->lights[i].direction = (vec4f_t) { 0, 0, 1, 1 }; } - for (size_t i = 0; (i < lframe->lightvis.size + for (size_t i = 0; (i < ldata->lightvis.size && light_data->lightCount < MaxLights); i++) { - if (lframe->lightvis.a[i]) { - qfv_light_t *light = &light_data->lights[light_data->lightCount++]; - *light = lctx->lights.a[i]; - light->color[3] *= style_intensities[lctx->lightstyles.a[i]]; + if (ldata->lightvis.a[i]) { + light_t *light = &light_data->lights[light_data->lightCount++]; + *light = ldata->lights.a[i]; + light->color[3] *= style_intensities[ldata->lightstyles.a[i]]; } } @@ -202,10 +141,13 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; qfv_renderpass_t *renderpass = rFrame->renderpass; + lightingctx_t *lctx = ctx->lighting_context; + if (!lctx->scene) { + return; + } update_lights (ctx); - lightingctx_t *lctx = ctx->lighting_context; __auto_type cframe = &ctx->frames.a[ctx->curFrame]; lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = lframe->cmd; @@ -299,9 +241,6 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); ctx->lighting_context = lctx; - DARRAY_INIT (&lctx->lights, 16); - DARRAY_INIT (&lctx->lightstyles, 16); - DARRAY_INIT (&lctx->lightleafs, 16); DARRAY_INIT (&lctx->lightmats, 16); DARRAY_INIT (&lctx->lightlayers, 16); DARRAY_INIT (&lctx->lightimages, 16); @@ -376,10 +315,6 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) shadow_set->a[i], va (ctx->va_ctx, "lighting:shadow_set:%zd", i)); - DARRAY_INIT (&lframe->lightvis, 16); - lframe->pvs = 0; - lframe->leaf = 0; - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); lframe->cmd = cmdSet->a[0]; @@ -455,13 +390,9 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) for (size_t i = 0; i < lctx->frames.size; i++) { lightingframe_t *lframe = &lctx->frames.a[i]; dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0); - DARRAY_CLEAR (&lframe->lightvis); } dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0); dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0); - DARRAY_CLEAR (&lctx->lights); - DARRAY_CLEAR (&lctx->lightstyles); - DARRAY_CLEAR (&lctx->lightleafs); DARRAY_CLEAR (&lctx->lightmats); DARRAY_CLEAR (&lctx->lightimages); DARRAY_CLEAR (&lctx->lightlayers); @@ -469,240 +400,16 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) free (lctx->frames.a); free (lctx); } - -static void -dump_light (qfv_light_t *light, int leaf, mat4f_t mat) -{ - Sys_MaskPrintf (SYS_vulkan, - "[%g, %g, %g] %g, " - "[%g, %g, %g, %g], [%g %g %g] %g, [%g, %g, %g, %g] %d\n", - VEC4_EXP (light->color), - VEC4_EXP (light->position), - VEC4_EXP (light->direction), - VEC4_EXP (light->attenuation), - leaf); -// Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 0)); -// Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 1)); -// Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 2)); -// Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 3)); -} - -static float -parse_float (const char *str, float defval) -{ - float val = defval; - if (str) { - char *end; - val = strtof (str, &end); - if (end == str) { - val = defval; - } - } - return val; -} - -static void -parse_vector (const char *str, vec_t *val) -{ - if (str) { - int num = sscanf (str, "%f %f %f", VectorExpandAddr (val)); - while (num < 3) { - val[num++] = 0; - } - } -} - -static float -ecos (float ang) -{ - if (ang == 90 || ang == -90) { - return 0; - } - if (ang == 180 || ang == -180) { - return -1; - } - if (ang == 0 || ang == 360) { - return 1; - } - return cos (ang * M_PI / 180); -} - -static float -esin (float ang) -{ - if (ang == 90) { - return 1; - } - if (ang == -90) { - return -1; - } - if (ang == 180 || ang == -180) { - return 0; - } - if (ang == 0 || ang == 360) { - return 0; - } - return sin (ang * M_PI / 180); -} - -static vec4f_t -sun_vector (const vec_t *ang) -{ - // ang is yaw, pitch (maybe roll, but ignored - vec4f_t vec = { - ecos (ang[1]) * ecos (ang[0]), - ecos (ang[1]) * esin (ang[0]), - esin (ang[1]), - 0, - }; - return vec; -} - -static void -parse_sun (lightingctx_t *lctx, plitem_t *entity, model_t *model) -{ - qfv_light_t light = {}; - float sunlight; - //float sunlight2; - vec3_t sunangle = { 0, -90, 0 }; - - set_expand (lctx->sun_pvs, model->brush.visleafs); - set_empty (lctx->sun_pvs); - sunlight = parse_float (PL_String (PL_ObjectForKey (entity, - "_sunlight")), 0); - //sunlight2 = parse_float (PL_String (PL_ObjectForKey (entity, - // "_sunlight2")), 0); - parse_vector (PL_String (PL_ObjectForKey (entity, "_sun_mangle")), - sunangle); - if (sunlight <= 0) { - return; - } - VectorSet (1, 1, 1, light.color); - light.color[3] = sunlight; - light.position = sun_vector (sunangle); - light.direction = light.position; - light.direction[3] = 1; - light.attenuation = (vec4f_t) { 0, 0, 1, 0 }; - DARRAY_APPEND (&lctx->lights, light); - DARRAY_APPEND (&lctx->lightstyles, 0); - DARRAY_APPEND (&lctx->lightleafs, -1); - - // Any leaf with sky surfaces can potentially see the sun, thus put - // the sun "in" every leaf with a sky surface - // however, skip leaf 0 as it is the exterior solid leaf - for (unsigned l = 1; l < model->brush.modleafs; l++) { - if (model->brush.leaf_flags[l] & SURF_DRAWSKY) { - set_add (lctx->sun_pvs, l - 1); //pvs is 1-based - } - } - // any leaf visible from a leaf with a sky surface (and thus the sun) - // can receive shadows from the sun - expand_pvs (lctx->sun_pvs, model); -} - -static vec4f_t -parse_position (const char *str) -{ - vec3_t vec = {}; - sscanf (str, "%f %f %f", VectorExpandAddr (vec)); - return (vec4f_t) {vec[0], vec[1], vec[2], 1}; -} - -static void -parse_light (qfv_light_t *light, int *style, const plitem_t *entity, - const plitem_t *targets) -{ - const char *str; - int model = 0; - - /*Sys_Printf ("{\n"); - for (int i = PL_D_NumKeys (entity); i-- > 0; ) { - const char *field = PL_KeyAtIndex (entity, i); - const char *value = PL_String (PL_ObjectForKey (entity, field)); - Sys_Printf ("\t%s = %s\n", field, value); - } - Sys_Printf ("}\n");*/ - - // omnidirectional light (unit length xyz so not treated as ambient) - light->direction = (vec4f_t) { 0, 0, 1, 1 }; - // bright white - light->color = (vec4f_t) { 1, 1, 1, 300 }; - - if ((str = PL_String (PL_ObjectForKey (entity, "origin")))) { - light->position = parse_position (str); - } - - if ((str = PL_String (PL_ObjectForKey (entity, "target")))) { - plitem_t *target = PL_ObjectForKey (targets, str); - vec4f_t dir = { 1, 0, 0, 0 }; - if (target) { - if ((str = PL_String (PL_ObjectForKey (target, "origin")))) { - dir = parse_position (str); - dir = normalf (dir - light->position); - } - } - - float angle = 40; - if ((str = PL_String (PL_ObjectForKey (entity, "angle")))) { - angle = atof (str); - } - dir[3] = -cos (angle * M_PI / 360); // half angle - light->direction = dir; - } - - if ((str = PL_String (PL_ObjectForKey (entity, "light_lev"))) - || (str = PL_String (PL_ObjectForKey (entity, "_light")))) { - light->color[3] = atof (str); - } - - if ((str = PL_String (PL_ObjectForKey (entity, "style")))) { - *style = atoi (str) & 0x3f; - } - - if ((str = PL_String (PL_ObjectForKey (entity, "delay")))) { - model = atoi (str) & 0x7; - if (model == LM_INVERSE2) { - model = LM_INVERSE3; //FIXME for marcher (need a map) - } - } - - if ((str = PL_String (PL_ObjectForKey (entity, "color"))) - || (str = PL_String (PL_ObjectForKey (entity, "_color")))) { - sscanf (str, "%f %f %f", VectorExpandAddr (light->color)); - VectorScale (light->color, 1/255.0, light->color); - } - - vec4f_t attenuation = { 1, 0, 0, 0 }; // inverse square - switch (model) { - case LM_LINEAR: - attenuation = (vec4f_t) { 0, 0, 1, 1 / fabsf (light->color[3]) }; - break; - case LM_INVERSE: - attenuation = (vec4f_t) { 0, 1.0 / 128, 0, 0 }; - break; - case LM_INVERSE2: - attenuation = (vec4f_t) { 1.0 / 16384, 0, 0, 0 }; - break; - case LM_INFINITE: - attenuation = (vec4f_t) { 0, 0, 1, 0 }; - break; - case LM_AMBIENT: - attenuation = (vec4f_t) { 0, 0, 1, 0 }; - light->direction = (vec4f_t) { 0, 0, 0, 1 }; - break; - case LM_INVERSE3: - attenuation = (vec4f_t) { 1.0 / 16384, 2.0 / 128, 1, 0 }; - break; - } - light->attenuation = attenuation; -} +#if 0 +static vec4f_t ref_direction = { 0, 0, 1, 0 }; static void create_light_matrices (lightingctx_t *lctx) { - DARRAY_RESIZE (&lctx->lightmats, lctx->lights.size); - for (size_t i = 0; i < lctx->lights.size; i++) { - qfv_light_t *light = &lctx->lights.a[i]; + lightingdata_t *ldata = lctx->ldata; + DARRAY_RESIZE (&lctx->lightmats, ldata->lights.size); + for (size_t i = 0; i < ldata->lights.size; i++) { + light_t *light = &ldata->lights.a[i]; mat4f_t view; mat4f_t proj; int mode = ST_NONE; @@ -754,8 +461,8 @@ create_light_matrices (lightingctx_t *lctx) static int light_compare (const void *_l2, const void *_l1) { - const qfv_light_t *l1 = _l1; - const qfv_light_t *l2 = _l2; + const light_t *l1 = _l1; + const light_t *l2 = _l2; if (l1->color[3] == l2->color[3]) { return (l1->position[3] == l2->position[3]) @@ -852,8 +559,9 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; qfv_physdev_t *physDev = device->physDev; int maxLayers = physDev->properties.limits.maxImageArrayLayers; - qfv_light_t *lights = lctx->lights.a; - int numLights = lctx->lights.size; + lightingdata_t *ldata = lctx->ldata; + light_t *lights = ldata->lights.a; + int numLights = ldata->lights.size; int size = -1; int numLayers = 0; int totalLayers = 0; @@ -861,7 +569,7 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) size_t memsize = 0; DARRAY_RESIZE (&lctx->lightlayers, numLights); - qsort (lights, numLights, sizeof (qfv_light_t), light_compare); + qsort (lights, numLights, sizeof (light_t), light_compare); for (int i = 0; i < numLights; i++) { int layers = 1; int shadow = ST_NONE; @@ -961,10 +669,10 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) } int mode = ST_NONE; - if (!lctx->lights.a[i].position[3]) { + if (!ldata->lights.a[i].position[3]) { mode = ST_CASCADE; } else { - if (lctx->lights.a[i].direction[3] > -0.5) { + if (ldata->lights.a[i].direction[3] > -0.5) { mode = ST_CUBE; } else { mode = ST_PLANE; @@ -977,117 +685,13 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n", totalLayers, lctx->lightimages.size, memsize); } - -static void -locate_lights (model_t *model, lightingctx_t *lctx) -{ - qfv_light_t *lights = lctx->lights.a; - DARRAY_RESIZE (&lctx->lightleafs, lctx->lights.size); - for (size_t i = 0; i < lctx->lights.size; i++) { - mleaf_t *leaf = Mod_PointInLeaf (&lights[i].position[0], model); - lctx->lightleafs.a[i] = leaf - model->brush.leafs - 1; - } -} +#endif void -Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx) +Vulkan_LoadLights (scene_t *scene, vulkan_ctx_t *ctx) { lightingctx_t *lctx = ctx->lighting_context; - plitem_t *entities = 0; - if (!entity_data) { - return; - } - - lctx->lights.size = 0; - lctx->lightstyles.size = 0; - lctx->lightleafs.size = 0; - lctx->lightmats.size = 0; - if (lctx->sun_pvs) { - set_delete (lctx->sun_pvs); - } - lctx->sun_pvs = set_new_size (model->brush.visleafs); - for (size_t i = 0; i < ctx->frames.size; i++) { - __auto_type lframe = &lctx->frames.a[i]; - if (lframe->pvs) { - set_delete (lframe->pvs); - } - lframe->pvs = set_new_size (model->brush.visleafs); - } - - clear_shadows (ctx); - - script_t *script = Script_New (); - Script_Start (script, "ent data", entity_data); - - if (Script_GetToken (script, 1)) { - if (strequal (script->token->str, "(")) { - // new style (plist) entity data - entities = PL_GetPropertyList (entity_data, &ctx->hashlinks); - } else { - // old style entity data - Script_UngetToken (script); - // FIXME ED_ConvertToPlist aborts if an error is encountered. - entities = ED_ConvertToPlist (script, 0, &ctx->hashlinks); - } - } - Script_Delete (script); - - if (entities) { - plitem_t *targets = PL_NewDictionary (&ctx->hashlinks); - - // find all the targets so spotlights can be aimed - for (int i = 1; i < PL_A_NumObjects (entities); i++) { - plitem_t *entity = PL_ObjectAtIndex (entities, i); - const char *targetname = PL_String (PL_ObjectForKey (entity, - "targetname")); - if (targetname && !PL_ObjectForKey (targets, targetname)) { - PL_D_AddObject (targets, targetname, entity); - } - } - - for (int i = 0; i < PL_A_NumObjects (entities); i++) { - plitem_t *entity = PL_ObjectAtIndex (entities, i); - const char *classname = PL_String (PL_ObjectForKey (entity, - "classname")); - if (!classname) { - continue; - } - if (strequal (classname, "worldspawn")) { - // parse_sun can add many lights - parse_sun (lctx, entity, model); - } else if (strnequal (classname, "light", 5)) { - qfv_light_t light = {}; - int style = 0; - - parse_light (&light, &style, entity, targets); - // some lights have 0 output, so drop them - if (light.color[3]) { - DARRAY_APPEND (&lctx->lights, light); - DARRAY_APPEND (&lctx->lightstyles, style); - } - } - } - for (size_t i = 0; i < ctx->frames.size; i++) { - lightingframe_t *lframe = &lctx->frames.a[i]; - DARRAY_RESIZE (&lframe->lightvis, lctx->lights.size); - } - // targets does not own the objects, so need to remove them before - // freeing targets - for (int i = PL_D_NumKeys (targets); i-- > 0; ) { - PL_RemoveObjectForKey (targets, PL_KeyAtIndex (targets, i)); - } - PL_Free (targets); - PL_Free (entities); - } - Sys_MaskPrintf (SYS_vulkan, "loaded %zd lights\n", lctx->lights.size); - if (lctx->lights.size) { - build_shadow_maps (lctx, ctx); - create_light_matrices (lctx); - locate_lights (model, lctx); - for (size_t i = 0; i < lctx->lights.size; i++) { - dump_light (&lctx->lights.a[i], lctx->lightleafs.a[i], - lctx->lightmats.a[i]); - } - } + lctx->scene = scene; + lctx->ldata = scene->lights; } diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 17c74ec6b..af5ae3dd1 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -142,14 +142,13 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) r_refdef.worldmodel = scene->worldmodel; // Force a vis update - r_refdef.viewleaf = NULL; - R_MarkLeaves (); + R_MarkLeaves (0); R_ClearParticles (); Vulkan_RegisterTextures (scene->models, scene->num_models, ctx); //Vulkan_BuildLightmaps (scene->models, scene->num_models, ctx); Vulkan_BuildDisplayLists (scene->models, scene->num_models, ctx); - Vulkan_LoadLights (scene->worldmodel, scene->worldmodel->brush.entities, ctx); + Vulkan_LoadLights (scene, ctx); } /*void From 4a4e16399a6fbcd05ca0b3dc936a59352d8f5e7e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 15:22:02 +0900 Subject: [PATCH 2753/3664] [client] Clean up world entity parsing a bit Now the entities are parsed only once and the resulting data reused. --- include/client/world.h | 3 +- libs/client/cl_light.c | 101 +++++++++++++++++------------------------ libs/client/cl_world.c | 11 ++--- 3 files changed, 47 insertions(+), 68 deletions(-) diff --git a/include/client/world.h b/include/client/world.h index e96ec48e3..2e1f79107 100644 --- a/include/client/world.h +++ b/include/client/world.h @@ -66,7 +66,6 @@ void CL_ParseBaseline (struct msg_s *msg, struct entity_state_s *baseline, void CL_ParseStatic (struct msg_s *msg, int version); void CL_MapCfg (const char *mapname); void CL_World_NewMap (const char *mapname, const char *skyname); -void CL_LoadLights (struct model_s *model, const char *entity_data, - struct lightingdata_s *ldata); +void CL_LoadLights (struct plitem_s *entities, struct scene_s *scene); #endif//__client_world_h diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index 8aa9cb39c..ecb946956 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -9,9 +9,9 @@ #include "QF/model.h" #include "QF/plist.h" #include "QF/progs.h" //for ED_ConvertToPlist -#include "QF/script.h" #include "QF/set.h" #include "QF/scene/light.h" +#include "QF/scene/scene.h" #include "QF/simd/vec4f.h" #include "client/world.h" @@ -238,78 +238,59 @@ locate_lights (model_t *model, lightingdata_t *ldata) } void -CL_LoadLights (model_t *model, const char *entity_data, lightingdata_t *ldata) +CL_LoadLights (plitem_t *entities, scene_t *scene) { - plitem_t *entities = 0; + lightingdata_t *ldata = scene->lights; + model_t *model = scene->worldmodel; - if (!entity_data) { + Light_ClearLights (ldata); + ldata->sun_pvs = set_new_size (model->brush.visleafs); + if (!entities) { return; } - Light_ClearLights (ldata); + plitem_t *targets = PL_NewDictionary (0); - ldata->sun_pvs = set_new_size (model->brush.visleafs); - - script_t *script = Script_New (); - Script_Start (script, "ent data", entity_data); - - if (Script_GetToken (script, 1)) { - if (!strcmp (script->token->str, "(")) { - // new style (plist) entity data - entities = PL_GetPropertyList (entity_data, 0); - } else { - // old style entity data - Script_UngetToken (script); - // FIXME ED_ConvertToPlist aborts if an error is encountered. - entities = ED_ConvertToPlist (script, 0, 0); + // find all the targets so spotlights can be aimed + for (int i = 1; i < PL_A_NumObjects (entities); i++) { + plitem_t *entity = PL_ObjectAtIndex (entities, i); + const char *targetname = PL_String (PL_ObjectForKey (entity, + "targetname")); + if (targetname && !PL_ObjectForKey (targets, targetname)) { + PL_D_AddObject (targets, targetname, entity); } } - Script_Delete (script); - if (entities) { - plitem_t *targets = PL_NewDictionary (0); + for (int i = 0; i < PL_A_NumObjects (entities); i++) { + plitem_t *entity = PL_ObjectAtIndex (entities, i); + const char *classname = PL_String (PL_ObjectForKey (entity, + "classname")); + if (!classname) { + continue; + } + if (!strcmp (classname, "worldspawn")) { + // parse_sun can add many lights + parse_sun (ldata, entity); + } else if (!strncmp (classname, "light", 5)) { + light_t light = {}; + int style = 0; - // find all the targets so spotlights can be aimed - for (int i = 1; i < PL_A_NumObjects (entities); i++) { - plitem_t *entity = PL_ObjectAtIndex (entities, i); - const char *targetname = PL_String (PL_ObjectForKey (entity, - "targetname")); - if (targetname && !PL_ObjectForKey (targets, targetname)) { - PL_D_AddObject (targets, targetname, entity); + parse_light (&light, &style, entity, targets); + // some lights have 0 output, so drop them + if (light.color[3]) { + DARRAY_APPEND (&ldata->lights, light); + DARRAY_APPEND (&ldata->lightstyles, style); } } - - for (int i = 0; i < PL_A_NumObjects (entities); i++) { - plitem_t *entity = PL_ObjectAtIndex (entities, i); - const char *classname = PL_String (PL_ObjectForKey (entity, - "classname")); - if (!classname) { - continue; - } - if (!strcmp (classname, "worldspawn")) { - // parse_sun can add many lights - parse_sun (ldata, entity); - } else if (!strncmp (classname, "light", 5)) { - light_t light = {}; - int style = 0; - - parse_light (&light, &style, entity, targets); - // some lights have 0 output, so drop them - if (light.color[3]) { - DARRAY_APPEND (&ldata->lights, light); - DARRAY_APPEND (&ldata->lightstyles, style); - } - } - } - DARRAY_RESIZE (&ldata->lightvis, ldata->lights.size); - // targets does not own the objects, so need to remove them before - // freeing targets - for (int i = PL_D_NumKeys (targets); i-- > 0; ) { - PL_RemoveObjectForKey (targets, PL_KeyAtIndex (targets, i)); - } - PL_Free (targets); - PL_Free (entities); } + DARRAY_RESIZE (&ldata->lightvis, ldata->lights.size); + // targets does not own the objects, so need to remove them before + // freeing targets + for (int i = PL_D_NumKeys (targets); i-- > 0; ) { + PL_RemoveObjectForKey (targets, PL_KeyAtIndex (targets, i)); + } + PL_Free (targets); + if (ldata->lights.size) { locate_lights (model, ldata); for (size_t i = 0; i < ldata->lights.size; i++) { diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index 1bcb256fa..4d17b0f5c 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -212,12 +212,6 @@ CL_World_NewMap (const char *mapname, const char *skyname) cl_static_entities.size = 0; - const char *entity_data = worldmodel->brush.entities; - CL_LoadLights (worldmodel, entity_data, cl_world.scene->lights); - - cl_world.scene->models = cl_world.models.a; - cl_world.scene->num_models = cl_world.models.size; - SCR_NewScene (cl_world.scene); if (cl_world.models.a[1] && cl_world.models.a[1]->brush.entities) { if (cl_world.edicts) { PL_Free (cl_world.edicts); @@ -229,5 +223,10 @@ CL_World_NewMap (const char *mapname, const char *skyname) Fog_ParseWorldspawn (cl_world.worldspawn); } } + CL_LoadLights (cl_world.edicts, cl_world.scene); + + cl_world.scene->models = cl_world.models.a; + cl_world.scene->num_models = cl_world.models.size; + SCR_NewScene (cl_world.scene); map_cfg (mapname, 1); } From a31ff3153cc5f418cbe555ea0ec71e16d722093a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 15:36:22 +0900 Subject: [PATCH 2754/3664] [gamecode] Fail gracefully on invalid entity strings Returning null (and printing some error messages) is far friendlier than aborting. --- libs/gamecode/pr_parse.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index e43aef934..f5031173f 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -299,17 +299,22 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks) plitem_t *value; char *token; int anglehack; + const char *msg = ""; while (Script_GetToken (script, 1)) { token = script->token->str; - if (!strequal (token, "{")) - Sys_Error ("ED_ConvertToPlist: EOF without closing brace"); + if (!strequal (token, "{")) { + msg = "EOF without closing brace"; + goto parse_error; + } ent = PL_NewDictionary (hashlinks); while (1) { int n; - if (!Script_GetToken (script, 1)) - Sys_Error ("ED_ConvertToPlist: EOF without closing brace"); + if (!Script_GetToken (script, 1)) { + msg = "EOF without closing brace"; + goto parse_error; + } token = script->token->str; if (strequal (token, "}")) break; @@ -327,12 +332,16 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks) } else { key = PL_NewString (token); } - if (!Script_TokenAvailable (script, 0)) - Sys_Error ("ED_ConvertToPlist: EOL without value"); + if (!Script_TokenAvailable (script, 0)) { + msg = "EOL without value"; + goto parse_error; + } Script_GetToken (script, 0); token = script->token->str; - if (strequal (token, "}")) - Sys_Error ("ED_ConvertToPlist: closing brace without data"); + if (strequal (token, "}")) { + msg = "closing brace without data"; + goto parse_error; + } if (anglehack) { dsprintf (dstr, "0 %s 0", token); value = PL_NewString (dstr->str); @@ -346,6 +355,11 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks) } dstring_delete (dstr); return plist; +parse_error: + Sys_Printf ("%s:%d: %s", script->file, script->line, msg); + dstring_delete (dstr); + PL_Free (plist); + return 0; } From c26c3b27395a46f32079103b18f473ae79aabf05 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 19:50:14 +0900 Subject: [PATCH 2755/3664] [mdl] Show bytes remaining if not enough for unpack It turns out Abyss of Pandemonium has a truncated mdl file causing buffer overruns. --- tools/misc/mdl.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/misc/mdl.py b/tools/misc/mdl.py index f9b6698c4..924cdb48d 100644 --- a/tools/misc/mdl.py +++ b/tools/misc/mdl.py @@ -29,7 +29,7 @@ for i in range(m[6]): k[2].append (model[:s]) model = model[s:] skins.append (k) -pprint (skins) +#pprint (skins) stverts = [] for i in range(m[9]): @@ -51,7 +51,11 @@ for i in range (m[11]): model = model[4:] if t==0: if m[1] == 6: - x = unpack ("3B B 3B B 16s", model[:24]) + try: + x = unpack ("3B B 3B B 16s", model[:24]) + except: + print(len(model)) + raise f = (t, ((x[:3], x[3]), (x[4:7], x[7]), x[8]), []) model = model[24:] else: From df5b471342dc348651774975eac80ae95947de20 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 19:53:20 +0900 Subject: [PATCH 2756/3664] [scene] Support ambient lighting in worldspawn Abyss of Pandemonium uses global ambient light a lot, but doesn't specify it in every map (nothing extracting entities and adding a reasonable value can't fix). I imagine some further tweaking will be needed. --- include/QF/scene/light.h | 1 - libs/client/cl_light.c | 21 +++++++++++++++++++-- libs/scene/light.c | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/QF/scene/light.h b/include/QF/scene/light.h index 4c6845c20..88033c253 100644 --- a/include/QF/scene/light.h +++ b/include/QF/scene/light.h @@ -38,7 +38,6 @@ struct mod_brush_s; #define NumStyles 64 -#define NoStyle -1 #define LM_LINEAR 0 // light - dist (or radius + dist if -ve) #define LM_INVERSE 1 // distFactor1 * light / dist diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index ecb946956..6cfa2a9ca 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -232,8 +232,16 @@ locate_lights (model_t *model, lightingdata_t *ldata) light_t *lights = ldata->lights.a; DARRAY_RESIZE (&ldata->lightleafs, ldata->lights.size); for (size_t i = 0; i < ldata->lights.size; i++) { - mleaf_t *leaf = Mod_PointInLeaf (&lights[i].position[0], model); - ldata->lightleafs.a[i] = leaf - model->brush.leafs - 1; + if (1 || lights[i].position[3]) { + mleaf_t *leaf = Mod_PointInLeaf (&lights[i].position[0], model); + ldata->lightleafs.a[i] = leaf - model->brush.leafs - 1; + } else { + if (DotProduct (lights[i].direction, lights[i].direction)) { + ldata->lightleafs.a[i] = -1; + } else { + ldata->lightleafs.a[i] = -2; + } + } } } @@ -271,6 +279,15 @@ CL_LoadLights (plitem_t *entities, scene_t *scene) if (!strcmp (classname, "worldspawn")) { // parse_sun can add many lights parse_sun (ldata, entity); + const char *str; + if ((str = PL_String (PL_ObjectForKey (entity, "light_lev")))) { + light_t light = {}; + light.color = (vec4f_t) { 1, 1, 1, atof (str) }; + light.attenuation = (vec4f_t) { 0, 0, 1, 0 }; + light.direction = (vec4f_t) { 0, 0, 0, 1 }; + DARRAY_APPEND (&ldata->lights, light); + DARRAY_APPEND (&ldata->lightstyles, 0); + } } else if (!strncmp (classname, "light", 5)) { light_t light = {}; int style = 0; diff --git a/libs/scene/light.c b/libs/scene/light.c index fc38e71af..7ccc17dda 100644 --- a/libs/scene/light.c +++ b/libs/scene/light.c @@ -128,7 +128,7 @@ Light_FindVisibleLights (lightingdata_t *ldata) memset (ldata->lightvis.a, 0, ldata->lightvis.size * sizeof (byte)); for (size_t i = 0; i < ldata->lightleafs.size; i++) { int l = ldata->lightleafs.a[i]; - if ((l == -1 && (flags & SURF_DRAWSKY)) + if ((l == -2) || (l == -1 && (flags & SURF_DRAWSKY)) || set_is_member (ldata->pvs, l)) { ldata->lightvis.a[i] = 1; visible++; From d60602421b162f2f74ffac5d20ecd9227e89662a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 19:55:35 +0900 Subject: [PATCH 2757/3664] [vulkan] Ensure dynamic lights are positional I'm not sure what's up with the weird lighting that results from dynamic lights being directional (sunlight works nicely in marcher, but it has a unit vector for position). --- libs/video/renderer/vulkan/vulkan_lighting.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index ad8252160..f31322159 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -102,10 +102,12 @@ update_lights (vulkan_ctx_t *ctx) // dynamic lights seem a tad faint, so 16x map lights light_data->lights[i].color[3] = lights[i]->radius / 16; VectorCopy (lights[i]->origin, light_data->lights[i].position); + // dlights are local point sources + light_data->lights[i].position[3] = 1; light_data->lights[i].attenuation = (vec4f_t) { 0, 0, 1, 1/lights[i]->radius }; - light_data->lights[i].direction = - (vec4f_t) { 0, 0, 1, 1 }; + // full sphere, normal light (not ambient) + light_data->lights[i].direction = (vec4f_t) { 0, 0, 1, 1 }; } for (size_t i = 0; (i < ldata->lightvis.size && light_data->lightCount < MaxLights); i++) { From b2928b5ed7707fa1d2de1bdfd60c904b41f689d6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 19:58:37 +0900 Subject: [PATCH 2758/3664] [client] Reverse the direction of sunlight Maps specify sunlight as shining in a specific direction, but the lighting system wants the direction to the sun as it's used directly in shading calculations. Direction correctness confirmed by disabling other lights and checking marcher's outside scene (ensuring the flat ground was lit). As a bonus, I've finally confirmed I actually have the skybox in the correct orientation (sunlight vector more or less matched the position of the sun in marcher's sky). --- libs/client/cl_light.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index 6cfa2a9ca..e06e921f5 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -120,7 +120,7 @@ parse_sun (lightingdata_t *ldata, plitem_t *entity) } VectorSet (1, 1, 1, light.color); light.color[3] = sunlight; - light.position = sun_vector (sunangle); + light.position = -sun_vector (sunangle); light.direction = light.position; light.direction[3] = 1; light.attenuation = (vec4f_t) { 0, 0, 1, 0 }; From 41a12f066b540e372ef69968e7d91831290cd89b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 20:36:25 +0900 Subject: [PATCH 2759/3664] [client] Clean up light loading By adding Light_AddLight to scene light management --- include/QF/scene/light.h | 1 + libs/client/cl_light.c | 37 +++++-------------------------------- libs/scene/light.c | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/include/QF/scene/light.h b/include/QF/scene/light.h index 88033c253..542431bf3 100644 --- a/include/QF/scene/light.h +++ b/include/QF/scene/light.h @@ -73,6 +73,7 @@ typedef struct lightingdata_s { lightingdata_t *Light_CreateLightingData (struct scene_s *scene); void Light_DestroyLightingData (lightingdata_t *ldata); void Light_ClearLights (lightingdata_t *ldata); +void Light_AddLight (lightingdata_t *ldata, const light_t *light, int style); void Light_EnableSun (lightingdata_t *ldata); void Light_FindVisibleLights (lightingdata_t *ldata); diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index e06e921f5..5af325739 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -124,9 +124,7 @@ parse_sun (lightingdata_t *ldata, plitem_t *entity) light.direction = light.position; light.direction[3] = 1; light.attenuation = (vec4f_t) { 0, 0, 1, 0 }; - DARRAY_APPEND (&ldata->lights, light); - DARRAY_APPEND (&ldata->lightstyles, 0); - DARRAY_APPEND (&ldata->lightleafs, -1); + Light_AddLight (ldata, &light, 0); } static vec4f_t @@ -226,25 +224,6 @@ parse_light (light_t *light, int *style, const plitem_t *entity, light->attenuation = attenuation; } -static void -locate_lights (model_t *model, lightingdata_t *ldata) -{ - light_t *lights = ldata->lights.a; - DARRAY_RESIZE (&ldata->lightleafs, ldata->lights.size); - for (size_t i = 0; i < ldata->lights.size; i++) { - if (1 || lights[i].position[3]) { - mleaf_t *leaf = Mod_PointInLeaf (&lights[i].position[0], model); - ldata->lightleafs.a[i] = leaf - model->brush.leafs - 1; - } else { - if (DotProduct (lights[i].direction, lights[i].direction)) { - ldata->lightleafs.a[i] = -1; - } else { - ldata->lightleafs.a[i] = -2; - } - } - } -} - void CL_LoadLights (plitem_t *entities, scene_t *scene) { @@ -285,8 +264,7 @@ CL_LoadLights (plitem_t *entities, scene_t *scene) light.color = (vec4f_t) { 1, 1, 1, atof (str) }; light.attenuation = (vec4f_t) { 0, 0, 1, 0 }; light.direction = (vec4f_t) { 0, 0, 0, 1 }; - DARRAY_APPEND (&ldata->lights, light); - DARRAY_APPEND (&ldata->lightstyles, 0); + Light_AddLight (ldata, &light, 0); } } else if (!strncmp (classname, "light", 5)) { light_t light = {}; @@ -295,12 +273,10 @@ CL_LoadLights (plitem_t *entities, scene_t *scene) parse_light (&light, &style, entity, targets); // some lights have 0 output, so drop them if (light.color[3]) { - DARRAY_APPEND (&ldata->lights, light); - DARRAY_APPEND (&ldata->lightstyles, style); + Light_AddLight (ldata, &light, style); } } } - DARRAY_RESIZE (&ldata->lightvis, ldata->lights.size); // targets does not own the objects, so need to remove them before // freeing targets for (int i = PL_D_NumKeys (targets); i-- > 0; ) { @@ -308,11 +284,8 @@ CL_LoadLights (plitem_t *entities, scene_t *scene) } PL_Free (targets); - if (ldata->lights.size) { - locate_lights (model, ldata); - for (size_t i = 0; i < ldata->lights.size; i++) { - dump_light (&ldata->lights.a[i], ldata->lightleafs.a[i]); - } + for (size_t i = 0; i < ldata->lights.size; i++) { + dump_light (&ldata->lights.a[i], ldata->lightleafs.a[i]); } Sys_MaskPrintf (SYS_lighting, "loaded %zd lights\n", ldata->lights.size); } diff --git a/libs/scene/light.c b/libs/scene/light.c index 7ccc17dda..3b1d1bd3c 100644 --- a/libs/scene/light.c +++ b/libs/scene/light.c @@ -66,6 +66,28 @@ Light_ClearLights (lightingdata_t *ldata) ldata->leaf = 0; } +void +Light_AddLight (lightingdata_t *ldata, const light_t *light, int style) +{ + scene_t *scene = ldata->scene; + model_t *model = scene->worldmodel; + + DARRAY_APPEND (&ldata->lights, *light); + DARRAY_APPEND (&ldata->lightstyles, style); + + int visleaf = -1; // directional light + if (light->position[3]) { + // positional light + mleaf_t *leaf = Mod_PointInLeaf (&light->position[0], model); + visleaf = leaf - model->brush.leafs - 1; + } else if (!DotProduct (light->direction, light->direction)) { + // ambient light + visleaf = -2; + } + DARRAY_APPEND (&ldata->lightleafs, visleaf); + DARRAY_APPEND (&ldata->lightvis, 0); +} + void Light_EnableSun (lightingdata_t *ldata) { From 2818fc12a531e1ab2bfba96b534b1970239caae7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 21:22:44 +0900 Subject: [PATCH 2760/3664] [model] Initialize r_notexture_mip in the right places That being in the renderer. This is why qwaq needed that call to Mod_ProcessTexture (but no longer does :) --- libs/models/brush/gl_model_brush.c | 3 --- libs/models/brush/glsl_model_brush.c | 3 --- libs/models/brush/vulkan_model_brush.c | 3 --- libs/video/renderer/gl/gl_rmisc.c | 4 ++++ libs/video/renderer/glsl/glsl_bsp.c | 3 +++ libs/video/renderer/vulkan/vulkan_bsp.c | 4 ++++ 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/libs/models/brush/gl_model_brush.c b/libs/models/brush/gl_model_brush.c index 4e81f35f1..02ed475a1 100644 --- a/libs/models/brush/gl_model_brush.c +++ b/libs/models/brush/gl_model_brush.c @@ -52,8 +52,6 @@ #include "mod_internal.h" #include "r_internal.h" -static gltex_t gl_notexture = { }; - static tex_t * Mod_LoadAnExternalTexture (const char *tname, const char *mname) { @@ -122,7 +120,6 @@ gl_Mod_ProcessTexture (model_t *mod, texture_t *tx) const char *name; if (!tx) { - r_notexture_mip->render = &gl_notexture; return; } if (gl_textures_external) { diff --git a/libs/models/brush/glsl_model_brush.c b/libs/models/brush/glsl_model_brush.c index 541982f74..da6fad3d0 100644 --- a/libs/models/brush/glsl_model_brush.c +++ b/libs/models/brush/glsl_model_brush.c @@ -60,8 +60,6 @@ #include "mod_internal.h" #include "r_internal.h" -static glsltex_t glsl_notexture = { }; - static void glsl_brush_clear (model_t *m, void *data) { @@ -105,7 +103,6 @@ void glsl_Mod_ProcessTexture (model_t *mod, texture_t *tx) { if (!tx) { - r_notexture_mip->render = &glsl_notexture; return; } glsltex_t *tex = tx->render; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index b1933de59..f706083a2 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -62,8 +62,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -static vulktex_t vulkan_notexture = { }; - static void vulkan_brush_clear (model_t *mod, void *data) { @@ -302,7 +300,6 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) mod->clear = vulkan_brush_clear; mod->data = mctx; - r_notexture_mip->render = &vulkan_notexture; if (mod->brush.numtextures) { load_textures (mod, ctx); } diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 19aea339d..026e0eb77 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -73,6 +73,8 @@ #include "varrays.h" #include "vid_gl.h" +static gltex_t gl_notexture = { }; + static void gl_R_LoadSky_f (void) { @@ -115,6 +117,8 @@ gl_R_TimeRefresh_f (void) void gl_R_Init (void) { + r_notexture_mip->render = &gl_notexture; + R_Init_Cvars (); Cmd_AddCommand ("timerefresh", gl_R_TimeRefresh_f, diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index a4bd95182..76dca2469 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -103,6 +103,7 @@ static double sky_time; static quat_t default_color = { 1, 1, 1, 1 }; static quat_t last_color; +static glsltex_t glsl_notexture = { }; static const char *bsp_vert_effects[] = { @@ -1282,6 +1283,8 @@ glsl_R_InitBsp (void) int vert; int frag; + r_notexture_mip->render = &glsl_notexture; + vert_shader = GLSL_BuildShader (bsp_vert_effects); frag_shader = GLSL_BuildShader (bsp_lit_effects); vert = GLSL_CompileShader ("quakebsp.vert", vert_shader, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index b202fd988..b1e1bda28 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -98,6 +98,8 @@ static float identity[] = { 0, 0, 0, 1, }; +static vulktex_t vulkan_notexture = { }; + #define ALLOC_CHUNK 64 typedef struct bsppoly_s { @@ -1342,6 +1344,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + r_notexture_mip->render = &vulkan_notexture; + qfvPushDebug (ctx, "bsp init"); bspctx_t *bctx = calloc (1, sizeof (bspctx_t)); From 7b275ebab6726e1c4b07afd5c4272b1bcae1bc32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 21:24:22 +0900 Subject: [PATCH 2761/3664] [vulkan] Don't update lights that don't exist However, the lighting pass still needs to be run in order to generate the solid color image. --- libs/video/renderer/vulkan/vulkan_lighting.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index f31322159..ce61d83c2 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -148,7 +148,9 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) if (!lctx->scene) { return; } - update_lights (ctx); + if (lctx->scene->lights) { + update_lights (ctx); + } __auto_type cframe = &ctx->frames.a[ctx->curFrame]; lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; From d850285e3fe04320fe84f772a60a07d454eb644c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 21:26:18 +0900 Subject: [PATCH 2762/3664] [ruamoko] Allow scenes to be fetched by C code Need to clean up that part of the API, though. --- include/rua_internal.h | 1 + libs/ruamoko/rua_scene.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/rua_internal.h b/include/rua_internal.h index 80f97003a..85880d715 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -65,5 +65,6 @@ void RUA_Mersenne_Init (struct progs_s *pr, int secure); void RUA_Model_Init (struct progs_s *pr, int secure); struct model_s *Model_GetModel (progs_t *pr, int handle); void RUA_Scene_Init (struct progs_s *pr, int secure); +struct scene_s *Scene_GetScene (struct progs_s *pr, pr_ulong_t handle); #endif//__rua_internal_h diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 1c577d6fd..57e4543ee 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -180,6 +180,17 @@ bi_Scene_DeleteScene (progs_t *pr, void *_res) rua_delete_scene (res, scene); } +scene_t * +Scene_GetScene (progs_t *pr, pr_ulong_t handle) +{ + if (!handle) { + return 0; + } + rua_scene_resources_t *res = PR_Resources_Find (pr, "Scene"); + rua_scene_t *scene = rua_scene_get (res, P_ULONG (pr, 0)); + return scene->scene; +} + static void bi_Scene_CreateEntity (progs_t *pr, void *_res) { @@ -221,10 +232,13 @@ bi_Entity_SetModel (progs_t *pr, void *_res) pr_int_t model_id = P_INT (pr, 1); entity_t *ent = rua_entity_get (res, ent_id); model_t *model = Model_GetModel (pr, model_id); + pr_ulong_t scene_id = ent_id & 0xffffffff; + // bad scene caught above + rua_scene_t *scene = rua_scene_get (res, scene_id); R_RemoveEfrags (ent); ent->renderer.model = model; - R_AddEfrags (&r_data->refdef->worldmodel->brush, ent);//FIXME r_data + R_AddEfrags (&scene->scene->worldmodel->brush, ent); } static void @@ -502,6 +516,6 @@ RUA_Scene_Init (progs_t *pr, int secure) res->pr = pr; - PR_Resources_Register (pr, "scene", res, bi_scene_clear); + PR_Resources_Register (pr, "Scene", res, bi_scene_clear); PR_RegisterBuiltins (pr, builtins, res); } From 95264b3a54322cc433cb8b8dc2e249981fad8a51 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 21:30:14 +0900 Subject: [PATCH 2763/3664] [ruamoko] Move emtpy_world into scene And use it as the default worldmodel for new scenes. Since it's statically allocated, it shouldn't cause any harm so long as no one tries to free it. --- libs/scene/scene.c | 37 +++++++++++++++++++++ ruamoko/qwaq/builtins/graphics.c | 56 ++++++-------------------------- 2 files changed, 47 insertions(+), 46 deletions(-) diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 13742f2a9..e9620abee 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -38,6 +38,7 @@ #include "QF/mathlib.h" #include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" +#include "QF/model.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" @@ -45,6 +46,40 @@ #include "scn_internal.h" +static mleaf_t empty_leafs[] = { + [1] = { + .contents = CONTENTS_EMPTY, + .mins = {-INFINITY, -INFINITY, -INFINITY}, + .maxs = { INFINITY, INFINITY, INFINITY}, + }, +}; + +static mnode_t *empty_leaf_parents[] = { + [1] = 0, +}; + +static int empty_leaf_flags[] = { + [1] = 0, +}; + +static char empty_entities[] = { 0 }; + +static model_t empty_world = { + .type = mod_brush, + .radius = INFINITY, + .mins = {-INFINITY, -INFINITY, -INFINITY}, + .maxs = { INFINITY, INFINITY, INFINITY}, + .brush = { + .modleafs = 2, + .visleafs = 1, + .nodes = (mnode_t *) &empty_leafs[1], + .leafs = empty_leafs, + .entities = empty_entities, + .leaf_parents = empty_leaf_parents, + .leaf_flags = empty_leaf_flags, + }, +}; + scene_t * Scene_NewScene (void) { @@ -55,6 +90,8 @@ Scene_NewScene (void) res = calloc (1, sizeof (scene_resources_t)); *(scene_resources_t **)&scene->resources = res; + scene->worldmodel = &empty_world; + return scene; } diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 6b1737906..c3a088b99 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -41,26 +41,20 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include #include "QF/cbuf.h" -#include "QF/cdaudio.h" -#include "QF/console.h" #include "QF/draw.h" -#include "QF/dstring.h" #include "QF/input.h" -#include "QF/model.h" -#include "QF/plugin.h" #include "QF/progs.h" #include "QF/quakefs.h" #include "QF/render.h" #include "QF/ruamoko.h" #include "QF/screen.h" #include "QF/sound.h" -#include "QF/sys.h" -#include "QF/vid.h" #include "QF/input/event.h" #include "QF/plugin/console.h" -#include "QF/plugin/vid_render.h" + +#include "rua_internal.h" #include "ruamoko/qwaq/qwaq.h" @@ -86,40 +80,6 @@ static progs_t *bi_rprogs; static pr_func_t qc2d; static int event_handler_id; -static mleaf_t empty_leafs[] = { - [1] = { - .contents = CONTENTS_EMPTY, - .mins = {-INFINITY, -INFINITY, -INFINITY}, - .maxs = { INFINITY, INFINITY, INFINITY}, - }, -}; - -static mnode_t *empty_leaf_parents[] = { - [1] = 0, -}; - -static int empty_leaf_flags[] = { - [1] = 0, -}; - -static char empty_entities[] = { 0 }; - -static model_t empty_world = { - .type = mod_brush, - .radius = INFINITY, - .mins = {-INFINITY, -INFINITY, -INFINITY}, - .maxs = { INFINITY, INFINITY, INFINITY}, - .brush = { - .modleafs = 2, - .visleafs = 1, - .nodes = (mnode_t *) &empty_leafs[1], - .leafs = empty_leafs, - .entities = empty_entities, - .leaf_parents = empty_leaf_parents, - .leaf_flags = empty_leaf_flags, - }, -}; - static void bi_2d (void) { @@ -133,6 +93,13 @@ static SCR_Func bi_2dfuncs[] = { 0, }; +static void +bi_newscene (progs_t *pr, void *_res) +{ + pr_ulong_t scene_id = P_ULONG (pr, 0); + SCR_NewScene (Scene_GetScene (pr, scene_id)); +} + static void bi_refresh (progs_t *pr, void *_res) { @@ -162,6 +129,7 @@ bi_shutdown (progs_t *pr, void *_res) #define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} #define p(type) PR_PARAM(type) static builtin_t builtins[] = { + bi(newscene, -1, 1, p(long)), bi(refresh, -1, 0), bi(refresh_2d, -1, 1, p(func)), bi(shutdown, -1, 0), @@ -230,8 +198,4 @@ BI_Graphics_Init (progs_t *pr) //CDAudio_Init (); Con_NewMap (); basetime = Sys_DoubleTime (); - if (mod_funcs->Mod_ProcessTexture) { - mod_funcs->Mod_ProcessTexture (&empty_world, 0); - } - //r_funcs->R_NewMap (&empty_world, 0, 0); } From d14b17567e910e32ac0ab23fe997b83860282ddc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 23:43:39 +0900 Subject: [PATCH 2764/3664] [ruamoko] Add builtins for adding lights to scenes Pretty much just raw wrappers around the C versions. I'm not sure about Light_EnableSun (even in C), but it does build the sky surf pvs. --- libs/ruamoko/rua_scene.c | 147 ++++++++++++++++++++++++++++++++++++++- ruamoko/include/scene.h | 15 ++++ ruamoko/lib/scene.r | 7 ++ 3 files changed, 166 insertions(+), 3 deletions(-) diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 57e4543ee..71af32449 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -45,6 +45,7 @@ #include "QF/plugin/vid_render.h" #include "QF/scene/entity.h" +#include "QF/scene/light.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" @@ -56,10 +57,18 @@ typedef struct rua_scene_s { scene_t *scene; } rua_scene_t; +typedef struct rua_lighting_s { + struct rua_lighting_s *next; + struct rua_lighting_s **prev; + lightingdata_t *ldata; +} rua_lighting_t; + typedef struct rua_scene_resources_s { progs_t *pr; PR_RESMAP (rua_scene_t) scene_map; + PR_RESMAP (rua_lighting_t) lighting_map; rua_scene_t *scenes; + rua_lighting_t *ldatas; } rua_scene_resources_t; static rua_scene_t * @@ -96,6 +105,12 @@ rua__scene_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) } #define rua_scene_get(res, id) rua__scene_get(res, id, __FUNCTION__) +static int __attribute__((pure)) +rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene) +{ + return PR_RESINDEX (res->scene_map, scene); +} + static entity_t * __attribute__((pure)) rua__entity_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { @@ -134,10 +149,44 @@ rua__transform_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) } #define rua_transform_get(res, id) rua__transform_get(res, id, __FUNCTION__) -static int __attribute__((pure)) -rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene) +static rua_lighting_t * +rua_lighting_new (rua_scene_resources_t *res) { - return PR_RESINDEX (res->scene_map, scene); + return PR_RESNEW (res->lighting_map); +} + +static void +rua_lighting_free (rua_scene_resources_t *res, rua_lighting_t *ldata) +{ + if (ldata->next) { + ldata->next->prev = ldata->prev; + } + *ldata->prev = ldata->next; + ldata->prev = 0; + PR_RESFREE (res->lighting_map, ldata); +} + +static rua_lighting_t * __attribute__((pure)) +rua__lighting_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) +{ + rua_lighting_t *ldata = 0; + + if (id <= 0xffffffffu) { + ldata = PR_RESGET (res->lighting_map, (pr_int_t) id); + } + + // ldata->prev will be null if the handle is unallocated + if (!ldata || !ldata->prev) { + PR_RunError (res->pr, "invalid lighting passed to %s", name + 3); + } + return ldata; +} +#define rua_lighting_get(res, id) rua__lighting_get(res, id, __FUNCTION__) + +static int __attribute__((pure)) +rua_lighting_index (rua_scene_resources_t *res, rua_lighting_t *ldata) +{ + return PR_RESINDEX (res->lighting_map, ldata); } #define MAKE_ID(id, sc_id) ((((pr_ulong_t) (id)) << 32) \ @@ -213,6 +262,22 @@ bi_Scene_DestroyEntity (progs_t *pr, void *_res) Scene_DestroyEntity (scene->scene, ent); } +static void +bi_Scene_SetLighting (progs_t *pr, void *_res) +{ + rua_scene_resources_t *res = _res; + pr_ulong_t scene_id = P_ULONG (pr, 0); + rua_scene_t *scene = rua_scene_get (res, scene_id); + pr_ulong_t ldata_id = P_ULONG (pr, 1); + rua_lighting_t *ldata = 0; + + if (ldata_id) { + ldata = rua_lighting_get (res, ldata_id); + } + + scene->scene->lights = ldata->ldata; +} + static void bi_Entity_GetTransform (progs_t *pr, void *_res) { @@ -453,6 +518,74 @@ bi_Transform_Up (progs_t *pr, void *_res) R_PACKED (pr, pr_vec4_t) = Transform_Up (transform); } +static void +bi_Light_CreateLightingData (progs_t *pr, void *_res) +{ + rua_scene_resources_t *res = _res; + pr_ulong_t scene_id = P_ULONG (pr, 0); + rua_scene_t *scene = rua_scene_get (res, scene_id); + + rua_lighting_t *ldata = rua_lighting_new (res); + + ldata->ldata = Light_CreateLightingData (scene->scene); + + ldata->next = res->ldatas; + if (res->ldatas) { + res->ldatas->prev = &ldata->next; + } + ldata->prev = &res->ldatas; + res->ldatas = ldata; + + // ldata id in lower 32-bits for all handles + // upper 32-bits reserved + R_ULONG (pr) = MAKE_ID (0, rua_lighting_index (res, ldata)); +} + +static void +rua_delete_lighting (rua_scene_resources_t *res, rua_lighting_t *ldata) +{ + Light_DestroyLightingData (ldata->ldata); + rua_lighting_free (res, ldata); +} + +static void +bi_Light_DestroyLightingData (progs_t *pr, void *_res) +{ + rua_scene_resources_t *res = _res; + rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0)); + + rua_delete_lighting (res, ldata); +} + +static void +bi_Light_ClearLights (progs_t *pr, void *_res) +{ + rua_scene_resources_t *res = _res; + rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0)); + + Light_ClearLights (ldata->ldata); +} + +static void +bi_Light_AddLight (progs_t *pr, void *_res) +{ + rua_scene_resources_t *res = _res; + rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0)); + light_t *light = &P_PACKED (pr, light_t, 1); + int style = P_INT (pr, 5); + + Light_AddLight (ldata->ldata, light, style); +} + +static void +bi_Light_EnableSun (progs_t *pr, void *_res) +{ + rua_scene_resources_t *res = _res; + rua_lighting_t *ldata = rua_lighting_get (res, P_ULONG (pr, 0)); + + Light_EnableSun (ldata->ldata); +} + #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} @@ -461,6 +594,7 @@ static builtin_t builtins[] = { bi(Scene_DeleteScene, 1, p(ulong)), bi(Scene_CreateEntity, 1, p(ulong)), bi(Scene_DestroyEntity, 1, p(ulong)), + bi(Scene_SetLighting , 2, p(ulong), p(ulong)), bi(Entity_GetTransform, 1, p(ulong)), bi(Entity_SetModel, 2, p(ulong), p(int)), @@ -496,6 +630,13 @@ static builtin_t builtins[] = { bi(Transform_Right, 1, p(ulong)), bi(Transform_Up, 1, p(ulong)), + bi(Light_CreateLightingData, 1, p(ulong)), + bi(Light_DestroyLightingData, 1, p(ulong)), + bi(Light_ClearLights, 1, p(ulong)), + bi(Light_AddLight, 5, p(ulong),// really, 3 + p(vec4), p(vec4), p(vec4), p(vec4), p(int)), + bi(Light_EnableSun, 1, p(ulong)), + {0} }; diff --git a/ruamoko/include/scene.h b/ruamoko/include/scene.h index cf66b5d82..fabbc1c2f 100644 --- a/ruamoko/include/scene.h +++ b/ruamoko/include/scene.h @@ -6,16 +6,25 @@ typedef struct { vec4 col[4]; } mat4x4; +typedef struct light_s { + vec4 color; + vec4 position; + vec4 direction; + vec4 attenuation; +} light_t; + //FIXME need a handle type typedef struct { long handle; } scene_t; typedef struct { long handle; } entity_t; typedef struct { long handle; } transform_t; +typedef struct { long handle; } lightingdata_t; typedef struct { int handle; } model_t; scene_t Scene_NewScene (void); void Scene_DeleteScene (scene_t scene); entity_t Scene_CreateEntity (scene_t scene); void Scene_DestroyEntity (entity_t ent); +void Scene_SetLighting (scene_t scene, lightingdata_t ldata); transform_t Entity_GetTransform (entity_t ent); void Entity_SetModel (entity_t ent, model_t model); @@ -48,6 +57,12 @@ vec4 Transform_Forward (transform_t transform); vec4 Transform_Right (transform_t transform); vec4 Transform_Up (transform_t transform); +lightingdata_t Light_CreateLightingData (scene_t scene); +void Light_DestroyLightingData (lightingdata_t ldata); +void Light_ClearLights (lightingdata_t ldata); +void Light_AddLight (lightingdata_t ldata, light_t light); +void Light_EnableSun (lightingdata_t ldata); + model_t Model_Load (string path); void Model_Unload (model_t model); diff --git a/ruamoko/lib/scene.r b/ruamoko/lib/scene.r index 6bcf931ed..fd40f2321 100644 --- a/ruamoko/lib/scene.r +++ b/ruamoko/lib/scene.r @@ -4,6 +4,7 @@ scene_t Scene_NewScene (void) = #0; void Scene_DeleteScene (scene_t scene) = #0; entity_t Scene_CreateEntity (scene_t scene) = #0; void Scene_DestroyEntity (entity_t ent) = #0; +void Scene_SetLighting (scene_t scene, lightingdata_t ldata) = #0; transform_t Entity_GetTransform (entity_t ent) = #0; void Entity_SetModel (entity_t ent, model_t model) = #0; @@ -36,5 +37,11 @@ vec4 Transform_Forward (transform_t transform) = #0; vec4 Transform_Right (transform_t transform) = #0; vec4 Transform_Up (transform_t transform) = #0; +lightingdata_t Light_CreateLightingData (scene_t scene) = #0; +void Light_DestroyLightingData (lightingdata_t ldata) = #0; +void Light_ClearLights (lightingdata_t ldata) = #0; +void Light_AddLight (lightingdata_t ldata, light_t light) = #0; +void Light_EnableSun (lightingdata_t ldata) = #0; + model_t Model_Load (string path) = #0; void Model_Unload (model_t model) = #0; From 72cb7d3fdd773cd39fc3d4b1445a2b486ea42db3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 23:45:21 +0900 Subject: [PATCH 2765/3664] [scene] Make the empty world work with lights Needed visibility and a sky surf flag, otherwise no lights were visible (why does this seem familiar?). --- libs/scene/scene.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/scene/scene.c b/libs/scene/scene.c index e9620abee..e2a49a61e 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -46,11 +46,14 @@ #include "scn_internal.h" +static byte empty_visdata[] = { 0x01 }; + static mleaf_t empty_leafs[] = { [1] = { .contents = CONTENTS_EMPTY, .mins = {-INFINITY, -INFINITY, -INFINITY}, .maxs = { INFINITY, INFINITY, INFINITY}, + .compressed_vis = empty_visdata, }, }; @@ -59,7 +62,7 @@ static mnode_t *empty_leaf_parents[] = { }; static int empty_leaf_flags[] = { - [1] = 0, + [1] = SURF_DRAWSKY, }; static char empty_entities[] = { 0 }; @@ -75,6 +78,7 @@ static model_t empty_world = { .nodes = (mnode_t *) &empty_leafs[1], .leafs = empty_leafs, .entities = empty_entities, + .visdata = empty_visdata, .leaf_parents = empty_leaf_parents, .leaf_flags = empty_leaf_flags, }, From 4abcaff9803096236554ec9368aeadce6915ba6e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 May 2022 23:46:24 +0900 Subject: [PATCH 2766/3664] [vulkan] Normalize the normal vectors on alias models I was wondering why scaled-down quake-guy was dimmer than full-size quake-guy. And the per-fragment normalization gives the illusion of smoothness if you don't look at his legs (and even then...). --- libs/video/renderer/vulkan/shader/alias.vert | 2 +- libs/video/renderer/vulkan/shader/alias_gbuf.frag | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/alias.vert b/libs/video/renderer/vulkan/shader/alias.vert index 52f390781..7292bee8e 100644 --- a/libs/video/renderer/vulkan/shader/alias.vert +++ b/libs/video/renderer/vulkan/shader/alias.vert @@ -34,6 +34,6 @@ main (void) pos = (Model * vertex); gl_Position = Projection3d * (View * pos); position = pos; - normal = mat3 (Model) * norm; + normal = normalize (mat3 (Model) * norm); st = uv; } diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index 2b751a0c7..50bc8f4b7 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -33,6 +33,6 @@ main (void) frag_color = c; frag_emission = e; - frag_normal = vec4(normal, 1); + frag_normal = vec4(normalize(normal), 1); frag_position = position; } From ed82b5f299d2ad6a8d413f240737a13c81269233 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 May 2022 08:26:55 +0900 Subject: [PATCH 2767/3664] [ruamoko] Clean up lighting data blocks Don't want to leak memory. --- libs/ruamoko/rua_scene.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 71af32449..c5daeb45f 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -645,6 +645,9 @@ bi_scene_clear (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; + while (res->ldatas) { + rua_delete_lighting (res, res->ldatas); + } while (res->scenes) { rua_delete_scene (res, res->scenes); } From 551c6b82cb1ec0159a9c10da187692059eff6481 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 May 2022 08:32:19 +0900 Subject: [PATCH 2768/3664] [vulkan] Tweak spotlight cone edges a little --- libs/video/renderer/vulkan/shader/lighting.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index a9e5cb7d2..41ee21629 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -50,7 +50,7 @@ spot_cone (LightData light, vec3 incoming) vec3 dir = light.direction.xyz; float cone = light.direction.w; float spotdot = dot (incoming, dir); - return 1 - smoothstep (cone, cone + 0.02, spotdot); + return 1 - smoothstep (cone, .995 * cone + 0.005, spotdot); } float From 9c7c081772d00849f5a234b5c3cebd627aea12d3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 May 2022 15:08:56 +0900 Subject: [PATCH 2769/3664] [io_mesh_qfmdl] Skip space after parsing a value Fixes a bogus error on the likes of offset = { x = 0; y = 0 }; (ie, between the 0 and } ) --- tools/io_mesh_qfmdl/qfplist.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/io_mesh_qfmdl/qfplist.py b/tools/io_mesh_qfmdl/qfplist.py index 7e5ffc762..aaf3b6053 100644 --- a/tools/io_mesh_qfmdl/qfplist.py +++ b/tools/io_mesh_qfmdl/qfplist.py @@ -173,9 +173,11 @@ class pldata: "Unexpected character (expected '=')") self.pos += 1 value = self.parse() + self.skip_space() if self.src[self.pos] == ';': self.pos += 1 elif self.src[self.pos] != '}': + print(self.src[self.pos]) raise PListError(self.line, "Unexpected character (wanted ';' or '}')") item[key] = value From 79add5590b837df74f01fe1338ab3a90c880402c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 May 2022 15:50:13 +0900 Subject: [PATCH 2770/3664] [build] Fix some make distcheck issues The never ending battle against bit-rot. --- include/QF/Makemodule.am | 2 ++ libs/scene/Makemodule.am | 2 +- libs/ui/Makemodule.am | 2 ++ libs/video/renderer/Makemodule.am | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 7c255e882..64a9c3cc0 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -185,10 +185,12 @@ include_qf_vulkan = \ include/QF/Vulkan/memory.h \ include/QF/Vulkan/pipeline.h \ include/QF/Vulkan/projection.h \ + include/QF/Vulkan/resource.h \ include/QF/Vulkan/qf_alias.h \ include/QF/Vulkan/qf_bsp.h \ include/QF/Vulkan/qf_compose.h \ include/QF/Vulkan/qf_draw.h \ + include/QF/Vulkan/qf_iqm.h \ include/QF/Vulkan/qf_lighting.h \ include/QF/Vulkan/qf_lightmap.h \ include/QF/Vulkan/qf_main.h \ diff --git a/libs/scene/Makemodule.am b/libs/scene/Makemodule.am index 13cfb6dca..cbd89b1be 100644 --- a/libs/scene/Makemodule.am +++ b/libs/scene/Makemodule.am @@ -1,6 +1,6 @@ include libs/scene/test/Makemodule.am -scene_deps=libs/util/libQFutil.la +scene_deps=libs/models/libQFmodels.la libs/util/libQFutil.la lib_LTLIBRARIES += libs/scene/libQFscene.la diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am index a1d72a36e..b564ebc8a 100644 --- a/libs/ui/Makemodule.am +++ b/libs/ui/Makemodule.am @@ -2,6 +2,8 @@ include libs/ui/test/Makemodule.am lib_LTLIBRARIES += libs/ui/libQFui.la +ui_deps = libs/util/libQFutil.la + libs_ui_libQFui_la_LDFLAGS= $(lib_ldflags) libs_ui_libQFui_la_LIBADD= $(ui_deps) libs_ui_libQFui_la_DEPENDENCIES= $(ui_deps) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 5b3c981cd..48b4f13d9 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -458,6 +458,8 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/bsp_sky.frag \ libs/video/renderer/vulkan/shader/bsp_turb.frag \ libs/video/renderer/vulkan/shader/compose.frag \ + libs/video/renderer/vulkan/shader/iqm.frag \ + libs/video/renderer/vulkan/shader/iqm.vert \ libs/video/renderer/vulkan/shader/lighting.frag \ libs/video/renderer/vulkan/shader/passthrough.vert \ libs/video/renderer/vulkan/shader/fstriangle.vert \ From b69b7b6a4acdee621a0b35b04d7a8a2cadd3e9ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 May 2022 19:38:14 +0900 Subject: [PATCH 2771/3664] [vulkan] Clean up duplication in qfpipeline That @inherit is pretty useful :) This makes it much easier to see how different pipelines differ or how they are the similar. It also makes it much clearer which sub-pass they're for. --- libs/video/renderer/vulkan/qfpipeline.plist | 262 ++++++-------------- 1 file changed, 77 insertions(+), 185 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index ce3a7dcff..1587727d2 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -558,6 +558,11 @@ }; fstriangle = { + vertexStage = { + stage = vertex; + name = main; + module = $builtin/fstriangle.vert; + }; vertexInput = { bindings = (); attributes = (); @@ -573,8 +578,62 @@ }; pipelines = { - alias_shadow = { + base = { + viewport = $properties.viewport; + rasterization = $properties.rasterization.counter_cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.disable; + colorBlend = { + logicOpEnable = false; + attachments = ( + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + ); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + renderPass = renderpass; + }; + depth_base = { + @inherit = $properties.pipelines.base; subpass = 0; + rasterization = $properties.rasterization.cw_cull_back; + depthStencil = $properties.depthStencil.test_and_write; + }; + trans_base = { + @inherit = $properties.pipelines.base; + subpass = 1; + rasterization = $properties.rasterization.cw_cull_back; + depthStencil = $properties.depthStencil.test_only; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.disabled); + }; + }; + gbuf_base = { + @inherit = $properties.pipelines.base; + subpass = 2; + rasterization = $properties.rasterization.cw_cull_back; + depthStencil = $properties.depthStencil.test_only; + dynamic = {//FIXME why? + dynamicState = ( viewport, scissor ); + }; + }; + comp_base = { + @inherit = $properties.pipelines.base; + vertexInput = $properties.fstriangle.vertexInput; + inputAssembly = $properties.fstriangle.inputAssembly; + colorBlend = $properties.fstriangle.colorBlend; + }; + shadow_base = { + @inherit = $properties.pipelines.depth_base; + }; + + alias_shadow = { + @inherit = $properties.pipelines.shadow_base; stages = ( { stage = vertex; @@ -595,18 +654,10 @@ ); }; inputAssembly = $properties.inputAssembly.alias; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; - colorBlend = $properties.pipelines.alias_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = alias_layout; }; bsp_shadow = { - subpass = 0; + @inherit = $properties.pipelines.shadow_base; stages = ( { stage = vertex; @@ -623,19 +674,9 @@ ); }; inputAssembly = $properties.inputAssembly.brush; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; - colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - layout = quakebsp_layout; - renderPass = renderpass; }; alias_depth = { - subpass = 0; + @inherit = $properties.pipelines.depth_base; stages = ( { stage = vertex; @@ -657,19 +698,10 @@ ); }; inputAssembly = $properties.inputAssembly.alias; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; - colorBlend = $properties.pipelines.alias_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = alias_layout; - renderPass = renderpass; }; alias_gbuf = { - subpass = 2; + @inherit = $properties.pipelines.gbuf_base; stages = ( { stage = vertex; @@ -684,27 +716,10 @@ ); vertexInput = $properties.vertexInput.alias; inputAssembly = $properties.inputAssembly.alias; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; - colorBlend = { - logicOpEnable = false; - attachments = ( - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - ); - }; - dynamic = { - dynamicState = ( viewport, scissor, blend_constants ); - }; layout = alias_layout; - renderPass = renderpass; }; bsp_depth = { - subpass = 0; + @inherit = $properties.pipelines.depth_base; stages = ( { stage = vertex; @@ -721,19 +736,10 @@ ); }; inputAssembly = $properties.inputAssembly.brush; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; - colorBlend = $properties.pipelines.bsp_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = quakebsp_layout; - renderPass = renderpass; }; bsp_gbuf = { - subpass = 2; + @inherit = $properties.pipelines.gbuf_base; stages = ( { stage = vertex; @@ -753,27 +759,10 @@ ); vertexInput = $properties.vertexInput.brush; inputAssembly = $properties.inputAssembly.brush; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; - colorBlend = { - logicOpEnable = false; - attachments = ( - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - ); - }; - dynamic = { - dynamicState = ( viewport, scissor, blend_constants ); - }; layout = quakebsp_layout; - renderPass = renderpass; }; bsp_skybox = { - subpass = 1; + @inherit = $properties.pipelines.trans_base; stages = ( { stage = vertex; @@ -797,22 +786,10 @@ ); vertexInput = $properties.vertexInput.brush; inputAssembly = $properties.inputAssembly.brush; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.disabled); - }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = quakebsp_layout; - renderPass = renderpass; }; bsp_skysheet = { - subpass = 1; + @inherit = $properties.pipelines.trans_base; stages = ( { stage = vertex; @@ -836,22 +813,10 @@ ); vertexInput = $properties.vertexInput.brush; inputAssembly = $properties.inputAssembly.brush; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.disabled); - }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = quakebsp_layout; - renderPass = renderpass; }; bsp_turb = { - subpass = 1; + @inherit = $properties.pipelines.trans_base; stages = ( { stage = vertex; @@ -866,22 +831,10 @@ ); vertexInput = $properties.vertexInput.brush; inputAssembly = $properties.inputAssembly.brush; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.disabled); - }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = quakebsp_layout; - renderPass = renderpass; }; partdraw = { - subpass = 1; + @inherit = $properties.pipelines.trans_base; stages = ( { stage = vertex; @@ -901,19 +854,10 @@ ); vertexInput = $properties.vertexInput.particle; inputAssembly = $properties.inputAssembly.sprite; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; - colorBlend = $properties.pipelines.bsp_turb.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor, blend_constants ); - }; layout = partdraw_layout; - renderPass = renderpass; }; sprite_gbuf = { - subpass = 2; + @inherit = $properties.pipelines.gbuf_base; stages = ( { stage = vertex; @@ -928,19 +872,10 @@ ); vertexInput = $properties.vertexInput.index_only; inputAssembly = $properties.inputAssembly.sprite; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; - colorBlend = $properties.pipelines.alias_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor, blend_constants ); - }; layout = sprite_layout; - renderPass = renderpass; }; sprite_depth = { - subpass = 0; + @inherit = $properties.pipelines.depth_base; stages = ( { stage = vertex; @@ -955,19 +890,10 @@ ); vertexInput = $properties.vertexInput.index_only; inputAssembly = $properties.inputAssembly.alias; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; - colorBlend = $properties.pipelines.alias_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = sprite_layout; - renderPass = renderpass; }; twod = { - subpass = 1; + @inherit = $properties.pipelines.trans_base;//FIXME should be sparate stages = ( { stage = vertex; @@ -982,28 +908,18 @@ ); vertexInput = $properties.vertexInput.twod; inputAssembly = $properties.inputAssembly.twod; - viewport = $properties.viewport; rasterization = $properties.rasterization.counter_cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; colorBlend = { logicOpEnable = false; attachments = ($properties.attachmentBlendOp.alpha_blend); }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = twod_layout; - renderPass = renderpass; }; lighting = { + @inherit = $properties.pipelines.comp_base; subpass = 3; stages = ( - { - stage = vertex; - name = main; - module = $builtin/fstriangle.vert; - }, + $properties.fstriangle.vertexStage, { stage = fragment; name = main; @@ -1016,46 +932,22 @@ }; }, ); - vertexInput = $properties.fstriangle.vertexInput; - inputAssembly = $properties.fstriangle.inputAssembly; - viewport = $properties.viewport; - rasterization = $properties.rasterization.counter_cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.disable; - colorBlend = $properties.fstriangle.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = lighting_layout; - renderPass = renderpass; }; compose = { + @inherit = $properties.pipelines.comp_base; subpass = 4; stages = ( - { - stage = vertex; - name = main; - module = $builtin/fstriangle.vert; - }, + $properties.fstriangle.vertexStage, { stage = fragment; name = main; module = $builtin/compose.frag; }, ); - vertexInput = $properties.fstriangle.vertexInput; - inputAssembly = $properties.fstriangle.inputAssembly; - viewport = $properties.viewport; - rasterization = $properties.rasterization.counter_cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.disable; - colorBlend = $properties.fstriangle.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; layout = compose_layout; - renderPass = renderpass; }; + partphysics = { stage = { stage = compute; From ae9e8f8f4ef132b88ae7b00264163fc35d91ca4f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 6 May 2022 20:09:55 +0900 Subject: [PATCH 2772/3664] [plist] Report line-relative character position in errors Far better than string-relative. --- libs/util/plist.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/libs/util/plist.c b/libs/util/plist.c index 1fd72f8e2..6fe440c68 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -95,6 +95,7 @@ typedef struct pldata_s { // Unparsed property list string unsigned end; unsigned pos; unsigned line; + unsigned line_start; plitem_t *error; va_ctx_t *va_ctx; hashlink_t **hashlinks; @@ -516,6 +517,7 @@ pl_skipspace (pldata_t *pl) if (c == '\n') { pl->line++; + pl->line_start = pl->pos + 1; } else if (c == '*' && pl->pos < pl->end - 1 && pl->ptr[pl->pos+1] == '/') { pl->pos++; @@ -536,6 +538,7 @@ pl_skipspace (pldata_t *pl) } if (c == '\n') { pl->line++; + pl->line_start = pl->pos + 1; } pl->pos++; } @@ -649,6 +652,7 @@ pl_parsequotedstring (pldata_t *pl) if (c == '\n') { pl->line++; + pl->line_start = pl->pos + 1; } pl->pos++; @@ -932,36 +936,32 @@ pl_parsepropertylistitem (pldata_t *pl) VISIBLE plitem_t * PL_GetPropertyList (const char *string, hashlink_t **hashlinks) { - pldata_t *pl = calloc (1, sizeof (pldata_t)); plitem_t *newpl = NULL; if (!quotable_bitmap[0]) init_quotables (); - pl->ptr = string; - pl->pos = 0; - pl->end = strlen (string); - pl->error = NULL; - pl->line = 1; - pl->va_ctx = va_create_context (4); - pl->hashlinks = hashlinks; + pldata_t pl = { + .ptr = string, + .end = strlen (string), + .line = 1, + .va_ctx = va_create_context (4), + .hashlinks = hashlinks, + }; - if ((newpl = pl_parsepropertylistitem (pl))) { - va_destroy_context (pl->va_ctx); - free (pl); - return newpl; - } else { - if (pl && pl->error) { - const char *error = PL_String (pl->error); + if (!(newpl = pl_parsepropertylistitem (&pl))) { + if (pl.error) { + const char *error = PL_String (pl.error); if (error[0]) { - Sys_Printf ("plist: %d,%d: %s\n", pl->line, pl->pos, error); + Sys_Printf ("plist: %d,%d: %s\n", pl.line, + pl.pos - pl.line_start, error); } - PL_Free (pl->error); + PL_Free (pl.error); } - va_destroy_context (pl->va_ctx); - free (pl); return NULL; } + va_destroy_context (pl.va_ctx); + return newpl; } static void From f41031f270c6cc876757b31ec70bbe5b8beb76a6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 00:50:27 +0900 Subject: [PATCH 2773/3664] [ruamoko] Add style parameter to Light_AddLight It's there in the builtin, but I forgot it in the header/lib. --- ruamoko/include/scene.h | 2 +- ruamoko/lib/scene.r | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ruamoko/include/scene.h b/ruamoko/include/scene.h index fabbc1c2f..e2907ae6a 100644 --- a/ruamoko/include/scene.h +++ b/ruamoko/include/scene.h @@ -60,7 +60,7 @@ vec4 Transform_Up (transform_t transform); lightingdata_t Light_CreateLightingData (scene_t scene); void Light_DestroyLightingData (lightingdata_t ldata); void Light_ClearLights (lightingdata_t ldata); -void Light_AddLight (lightingdata_t ldata, light_t light); +void Light_AddLight (lightingdata_t ldata, light_t light, int style); void Light_EnableSun (lightingdata_t ldata); model_t Model_Load (string path); diff --git a/ruamoko/lib/scene.r b/ruamoko/lib/scene.r index fd40f2321..a4ec96db6 100644 --- a/ruamoko/lib/scene.r +++ b/ruamoko/lib/scene.r @@ -40,7 +40,7 @@ vec4 Transform_Up (transform_t transform) = #0; lightingdata_t Light_CreateLightingData (scene_t scene) = #0; void Light_DestroyLightingData (lightingdata_t ldata) = #0; void Light_ClearLights (lightingdata_t ldata) = #0; -void Light_AddLight (lightingdata_t ldata, light_t light) = #0; +void Light_AddLight (lightingdata_t ldata, light_t light, int style) = #0; void Light_EnableSun (lightingdata_t ldata) = #0; model_t Model_Load (string path) = #0; From 91c877b1a1f4e3da4baf14573b224a22d6b021bb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 00:51:44 +0900 Subject: [PATCH 2774/3664] [scene] Zero freshly allocated entity memory I don't remember why I didn't want to clear it. I hope this doesn't cause other trouble. --- libs/scene/scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/scene/scene.c b/libs/scene/scene.c index e2a49a61e..69344f47c 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -119,7 +119,7 @@ Scene_CreateEntity (scene_t *scene) { scene_resources_t *res = scene->resources; - entity_t *ent = PR_RESNEW_NC (res->entities); + entity_t *ent = PR_RESNEW (res->entities); ent->transform = Transform_New (scene, 0); ent->id = PR_RESINDEX (res->entities, ent); From ea8f991bf37ac4b6505ac85ac0371c20426e7346 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 09:53:26 +0900 Subject: [PATCH 2775/3664] [ruamoko] Clear efrags when destroying an entity This ensures the rendering system won't attempt to draw the entity after it has been destroyed. --- libs/ruamoko/rua_scene.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index c5daeb45f..fc42fab61 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -257,6 +257,8 @@ bi_Scene_DestroyEntity (progs_t *pr, void *_res) pr_ulong_t id = P_ULONG (pr, 0); entity_t *ent = rua_entity_get (res, id); pr_ulong_t scene_id = id & 0xffffffff; + + R_RemoveEfrags (ent); // bad scene caught above rua_scene_t *scene = rua_scene_get (res, scene_id); Scene_DestroyEntity (scene->scene, ent); From 3f7cbae4d0913c401a0f4eb38e615c4cd1e130c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 09:56:46 +0900 Subject: [PATCH 2776/3664] [vulkan] Rework builtin plist handing The plists can now be accessed by name and the forward render pass config is available (but not used, or tested beyond syntax). I was going to have the IQM pipeline spec separate but ran into limitations in the system (which needs a lot of polish, really). --- libs/video/renderer/Makemodule.am | 13 +-- .../video/renderer/vulkan/vulkan_vid_common.c | 82 +++++++++++++++++-- 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 48b4f13d9..fd1496752 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -181,8 +181,10 @@ libs_video_renderer_librender_sw_la_SOURCES = \ pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc -renderpass_src = libs/video/renderer/vulkan/deferred.plist -renderpass_gen = libs/video/renderer/vulkan/deferred.plc +deferred_src = libs/video/renderer/vulkan/deferred.plist +deferred_gen = libs/video/renderer/vulkan/deferred.plc +forward_src = libs/video/renderer/vulkan/forward.plist +forward_gen = libs/video/renderer/vulkan/forward.plc video_renderer_vulkan_libs = \ libs/video/renderer/librender_vulkan.la \ @@ -232,7 +234,7 @@ libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vk libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c) -libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${renderpass_gen} +libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${deferred_gen} $(forward_gen) qwaq_cmd = $(top_builddir)/ruamoko/qwaq/qwaq-cmd$(EXEEXT) @@ -441,8 +443,9 @@ BUILT_SOURCES += $(shader_gen) # libs/video/renderer/vulkan/pushcolor.frag.spv EXTRA_DIST += \ - libs/video/renderer/vulkan/deferred.plist \ - libs/video/renderer/vulkan/qfpipeline.plist \ + $(deferred_src) \ + $(forward_src) \ + $(pipeline_src) \ libs/video/renderer/vulkan/vkparse.plist \ libs/video/renderer/vulkan/vkparse.h \ libs/video/renderer/vulkan/shader/alias.frag \ diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 6eccebcd7..0eaccc253 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -83,13 +83,23 @@ #include "libs/video/renderer/vulkan/vkparse.hinc" -static const char quakeforge_pipeline[] = +static exprsym_t builtin_plist_syms[] = { + { .name = "qfpipeline", + .value = (void *) #include "libs/video/renderer/vulkan/qfpipeline.plc" -; - -static const char quakeforge_renderpass[] = + }, + { .name = "deferred", + .value = (void *) #include "libs/video/renderer/vulkan/deferred.plc" -; + }, + { .name = "forward", + .value = (void *) +#include "libs/video/renderer/vulkan/forward.plc" + }, + {} +}; +static plitem_t **builtin_plists; +static exprtab_t builtin_configs = { .symbols = builtin_plist_syms }; int vulkan_frame_count; static cvar_t vulkan_frame_count_cvar = { @@ -298,12 +308,67 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) } } +static void +build_configs (vulkan_ctx_t *ctx) +{ + int num_plists = 0; + for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { + num_plists++; + } + builtin_plists = malloc (num_plists * sizeof (plitem_t *)); + num_plists = 0; + for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { + plitem_t *item = PL_GetPropertyList (sym->value, &ctx->hashlinks); + if (!item) { + // Syntax errors in the compiled-in plists are unrecoverable + Sys_Error ("Error parsing plist for %s", sym->name); + } + builtin_plists[num_plists] = item; + sym->value = &builtin_plists[num_plists]; + sym->type = &cexpr_plitem; + num_plists++; + } + exprctx_t ectx = { .hashlinks = &ctx->hashlinks }; + cexpr_init_symtab (&builtin_configs, &ectx); +} + +static plitem_t * +get_builtin_config (vulkan_ctx_t *ctx, const char *name) +{ + if (!builtin_configs.tab) { + build_configs (ctx); + } + + plitem_t *config = 0; + exprval_t result = { .type = &cexpr_plitem, .value = &config }; + exprctx_t ectx = { + .result = &result, + .symtab = &builtin_configs, + .memsuper = new_memsuper (), + .hashlinks = &ctx->hashlinks, + .messages = PL_NewArray (), + }; + if (cexpr_eval_string (name, &ectx)) { + dstring_t *msg = dstring_newstr (); + + for (int i = 0; i < PL_A_NumObjects (ectx.messages); i++) { + dasprintf (msg, "%s\n", + PL_String (PL_ObjectAtIndex (ectx.messages, i))); + } + Sys_Printf ("%s", msg->str); + dstring_delete (msg); + config = 0; + } + PL_Free (ectx.messages); + delete_memsuper (ectx.memsuper); + return config; +} + static plitem_t * qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) { if (!ctx->pipelineDef) { - ctx->pipelineDef = PL_GetPropertyList (quakeforge_pipeline, - &ctx->hashlinks); + ctx->pipelineDef = get_builtin_config (ctx, "qfpipeline"); } plitem_t *item = ctx->pipelineDef; @@ -319,8 +384,7 @@ static plitem_t * qfv_load_renderpass (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name) { if (!rp->renderpassDef) { - rp->renderpassDef = PL_GetPropertyList (quakeforge_renderpass, - &ctx->hashlinks); + rp->renderpassDef = get_builtin_config (ctx, "deferred"); } plitem_t *item = rp->renderpassDef; From 8795b8eb915c8b8a19c07b3163a6d365521fa938 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 10:08:46 +0900 Subject: [PATCH 2777/3664] [vulkan] Get IQM rendering working The bones aren't animated yet (and I realized I made the mistake of thinking the bone buffer was per-model when it's really per-instance (I think this mistake is in the rest of QF, too)), skin rendering is a mess, need to default vertex attributes that aren't in the model... Still, it's quite satisfying seeing Mr Fixit on screen again :) I wound up moving the pipeline spec in with the rest of the pipelines as the system isn't really ready for separating them. --- include/QF/Vulkan/qf_iqm.h | 8 + include/QF/iqm.h | 2 +- libs/models/iqm/vulkan_model_iqm.c | 34 ++- libs/video/renderer/vid_render_vulkan.c | 5 +- libs/video/renderer/vulkan/iqm.plist | 254 -------------------- libs/video/renderer/vulkan/qfpipeline.plist | 111 +++++++++ libs/video/renderer/vulkan/shader/iqm.frag | 23 +- libs/video/renderer/vulkan/shader/iqm.vert | 26 +- libs/video/renderer/vulkan/vulkan_iqm.c | 110 +++++++-- libs/video/renderer/vulkan/vulkan_main.c | 4 +- 10 files changed, 274 insertions(+), 303 deletions(-) delete mode 100644 libs/video/renderer/vulkan/iqm.plist diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h index 7de1623d9..90a417849 100644 --- a/include/QF/Vulkan/qf_iqm.h +++ b/include/QF/Vulkan/qf_iqm.h @@ -65,6 +65,8 @@ typedef struct qfv_iqm_s { qfv_iqm_skin_t *skins; struct qfv_resource_s *mesh; struct qfv_resource_s *bones; + VkBuffer bones_buffer; + VkDescriptorSet *bones_descriptors; // one per frame FIXME per instance!!! } qfv_iqm_t; typedef enum { @@ -91,15 +93,21 @@ typedef struct iqmctx_s { VkPipeline gbuf; VkPipelineLayout layout; VkSampler sampler; + VkDescriptorPool bones_pool; + VkDescriptorSetLayout bones_setLayout; } iqmctx_t; struct vulkan_ctx_s; struct qfv_renderframe_s; struct entity_s; struct mod_iqm_ctx_s; +struct iqm_s; void Vulkan_Mod_IQMFinish (struct model_s *mod, struct vulkan_ctx_s *ctx); +void Vulkan_IQMAddBones (struct vulkan_ctx_s *ctx, struct iqm_s *iqm); +void Vulkan_IQMRemoveBones (struct vulkan_ctx_s *ctx, struct iqm_s *iqm); + void Vulkan_IQMAddSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); void Vulkan_IQMRemoveSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); diff --git a/include/QF/iqm.h b/include/QF/iqm.h index adc5a3313..e5ab7ce85 100644 --- a/include/QF/iqm.h +++ b/include/QF/iqm.h @@ -127,7 +127,7 @@ typedef struct { byte weights[4]; } iqmblend_t; -typedef struct { +typedef struct iqm_s { char *text; int num_meshes; iqmmesh *meshes; diff --git a/libs/models/iqm/vulkan_model_iqm.c b/libs/models/iqm/vulkan_model_iqm.c index c9c7f79c8..69baa6fcb 100644 --- a/libs/models/iqm/vulkan_model_iqm.c +++ b/libs/models/iqm/vulkan_model_iqm.c @@ -81,6 +81,11 @@ vulkan_iqm_clear (model_t *mod, void *data) mod->needload = true; + for (int i = 0; i < iqm->num_meshes; i++) { + Vulkan_IQMRemoveSkin (ctx, &mesh->skins[i]); + } + Vulkan_IQMRemoveBones (ctx, iqm);//FIXME doesn't belong here (per-instance) + QFV_DestroyResource (device, mesh->bones); QFV_DestroyResource (device, mesh->mesh); free (mesh); @@ -162,6 +167,14 @@ iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage, 0, 0, 0, 0, 0, 1, &ib.barrier); memcpy (dst, tex->data, layer_size); + VkBufferImageCopy copy = { + packet->offset, 0, 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, {tex->width, tex->height, 1}, + }; + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©); int mipLevels = QFV_MipLevels (tex->width, tex->height); if (mipLevels == 1) { @@ -225,6 +238,7 @@ vulkan_iqm_load_textures (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, tex = &null_tex; } iqm_transfer_texture (tex, image->image, stage, device); + Vulkan_IQMAddSkin (ctx, skin); } dstring_delete (str); QFV_DestroyStagingBuffer (stage); @@ -236,6 +250,8 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + iqmctx_t *ictx = ctx->iqm_context; + size_t geom_size = iqm->num_verts * sizeof (iqmgvert_t); size_t rend_size = iqm->num_verts * sizeof (iqmrvert_t); size_t elem_size = iqm->num_elements * sizeof (uint16_t); @@ -350,7 +366,7 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, vec4f_t *bone_data; dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE, 0, (void **)&bone_data); - for (int i = 0; i < 3 * iqm->num_joints; i++) { + for (size_t i = 0; i < ictx->frames.size * iqm->num_joints; i++) { vec4f_t *bone = bone_data + i * 3; bone[0] = (vec4f_t) {1, 0, 0, 0}; bone[1] = (vec4f_t) {0, 1, 0, 0}; @@ -363,12 +379,15 @@ vulkan_iqm_load_arrays (model_t *mod, iqm_t *iqm, qfv_iqm_t *mesh, dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); dfunc->vkUnmapMemory (device->dev, mesh->bones->memory); + + Vulkan_IQMAddBones (ctx, iqm); //FIXME doesn't belong here (per-instance) } void Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + iqmctx_t *ictx = ctx->iqm_context; iqm_t *iqm = (iqm_t *) mod->aliashdr; mod->clear = vulkan_iqm_clear; mod->data = ctx; @@ -378,10 +397,12 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) // 2 is for image + image view int num_objects = 4 + 2 * iqm->num_meshes; qfv_iqm_t *mesh = calloc (1, sizeof (qfv_iqm_t) + + ictx->frames.size * sizeof (VkDescriptorSet) + 2 * sizeof (qfv_resource_t) + num_objects * sizeof (qfv_resobj_t) + iqm->num_meshes * sizeof (qfv_iqm_skin_t)); - mesh->bones = (qfv_resource_t *) &mesh[1]; + mesh->bones_descriptors = (VkDescriptorSet *) &mesh[1]; + mesh->bones = (qfv_resource_t *)&mesh->bones_descriptors[ictx->frames.size]; mesh->mesh = &mesh->bones[1]; mesh->bones[0] = (qfv_resource_t) { @@ -395,9 +416,9 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) .name = "bones", .type = qfv_res_buffer, .buffer = { - .size = 3 * iqm->num_joints * 3 * sizeof (vec4f_t), + .size = ictx->frames.size * iqm->num_joints * 3 * sizeof (vec4f_t), .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT - | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, }, }; @@ -460,9 +481,10 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) mesh->geom_buffer = mesh->mesh->objects[0].buffer.buffer; mesh->rend_buffer = mesh->mesh->objects[1].buffer.buffer; mesh->index_buffer = mesh->mesh->objects[2].buffer.buffer; + mesh->bones_buffer = mesh->bones->objects[0].buffer.buffer; + + iqm->extra_data = mesh; vulkan_iqm_load_textures (mod, iqm, mesh, ctx); vulkan_iqm_load_arrays (mod, iqm, mesh, ctx); - - iqm->extra_data = mesh; } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a52e3b7eb..a50cab69e 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -92,6 +92,7 @@ vulkan_R_Init (void) Vulkan_Matrix_Init (vulkan_ctx); Vulkan_Alias_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); + Vulkan_IQM_Init (vulkan_ctx); Vulkan_Particles_Init (vulkan_ctx); Vulkan_Sprite_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); @@ -686,16 +687,18 @@ vulkan_vid_render_shutdown (void) df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); + Mod_ClearAll (); + Vulkan_Compose_Shutdown (vulkan_ctx); Vulkan_Lighting_Shutdown (vulkan_ctx); Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Sprite_Shutdown (vulkan_ctx); Vulkan_Particles_Shutdown (vulkan_ctx); + Vulkan_IQM_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Alias_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx); - Mod_ClearAll (); Vulkan_Texture_Shutdown (vulkan_ctx); Vulkan_DestroyRenderPasses (vulkan_ctx); Vulkan_Shutdown_Common (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/iqm.plist b/libs/video/renderer/vulkan/iqm.plist deleted file mode 100644 index 4467d8b89..000000000 --- a/libs/video/renderer/vulkan/iqm.plist +++ /dev/null @@ -1,254 +0,0 @@ -{ - setLayouts = { - texture_set = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - }; - pipelineLayouts = { - iqm_layout = { - setLayouts = (matrix_set, texture_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 68; - size = "3 * 4 + 2 * 4 * 4 + 4"; - }, - ); - }; - }; - - depthStencil = { - test_and_write = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - test_only = { - depthTestEnable = true; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - disable = { - depthTestEnable = false; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - }; - - inputAssembly = { - iqm = { - topology = triangle_list; - primitiveRestartEnable = false; - }; - }; - - vertexInput = { - iqm = { - bindings = ( - { binding = 0; stride = 20; inputRate = vertex; }, - { binding = 1; stride = 40; inputRate = vertex; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position - { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 0; }, // bonindices - { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, // boneweights - - { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord - { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal - { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent - { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color - - ); - }; - }; - - rasterization = { - cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - counter_cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - }; - - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - - viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); - }; - - attachmentBlendOp = { - disabled = { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; - alpha_blend = { - blendEnable = true; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; - }; - - pipelines = { - iqm_shadow = { - subpass = 0; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm_shadow.vert; - }, - ); - vertexInput = { - bindings = ( - "$properties.vertexInput.iqm.bindings[0]", - "$properties.vertexInput.iqm.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.iqm.attributes[0]", - "$properties.vertexInput.iqm.attributes[1]", - "$properties.vertexInput.iqm.attributes[2]", - "$properties.vertexInput.iqm.attributes[3]", - ); - }; - inputAssembly = $properties.inputAssembly.iqm; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; - colorBlend = $properties.pipelines.iqm_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - layout = iqm_layout; - }; - iqm_depth = { - subpass = 0; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm_depth.vert; - }, - ); - vertexInput = { - // depth pass doesn't use UVs - bindings = ( - "$properties.vertexInput.iqm.bindings[0]", - "$properties.vertexInput.iqm.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.iqm.attributes[0]", - "$properties.vertexInput.iqm.attributes[1]", - "$properties.vertexInput.iqm.attributes[2]", - "$properties.vertexInput.iqm.attributes[3]", - ); - }; - inputAssembly = $properties.inputAssembly.iqm; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_and_write; - colorBlend = $properties.pipelines.iqm_gbuf.colorBlend; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - layout = iqm_layout; - renderPass = renderpass; - }; - iqm_gbuf = { - subpass = 2; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/iqm_gbuf.frag; - }, - ); - vertexInput = $properties.vertexInput.iqm; - inputAssembly = $properties.inputAssembly.iqm; - viewport = $properties.viewport; - rasterization = $properties.rasterization.cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.test_only; - colorBlend = { - logicOpEnable = false; - attachments = ( - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - ); - }; - dynamic = { - dynamicState = ( viewport, scissor, blend_constants ); - }; - layout = iqm_layout; - renderPass = renderpass; - }; - }; -} diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 1587727d2..33fef28d3 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -97,6 +97,16 @@ }, ); }; + bone_pool = { + flags = free_descriptor_set; + maxSets = 512; + bindings = ( + { + type = storage_buffer; + descriptorCount = $properties.descriptorPools.bone_pool.maxSets; + }, + ); + }; texture_pool = { flags = free_descriptor_set; maxSets = 512; @@ -206,6 +216,16 @@ }, ); }; + bone_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; sprite_set = { bindings = ( { @@ -349,6 +369,21 @@ }, ); }; + iqm_layout = { + setLayouts = (matrix_set, texture_set, bone_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "3 * 4 + 2 * 4 * 4 + 4"; + }, + ); + }; sprite_layout = { setLayouts = (matrix_set, sprite_set); pushConstantRanges = ( @@ -428,6 +463,10 @@ topology = triangle_fan; primitiveRestartEnable = true; }; + iqm = { + topology = triangle_list; + primitiveRestartEnable = false; + }; twod = { topology = triangle_strip; primitiveRestartEnable = true; @@ -466,6 +505,23 @@ { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, ); }; + iqm = { + bindings = ( + { binding = 0; stride = 20; inputRate = vertex; }, + { binding = 1; stride = 40; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position + { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 12; }, // bonindices + { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 16; }, // boneweights + + { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord + { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal + { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent + { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color + + ); + }; particle = { bindings = ( { binding = 0; stride = "4 * 4 * 4"; inputRate = vertex; }, @@ -833,6 +889,61 @@ inputAssembly = $properties.inputAssembly.brush; layout = quakebsp_layout; }; + iqm_depth = { + @inherit = $properties.pipelines.depth_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + mapEntries = ( + // IQMDepthOnly + { size = 4; offset = 0; constantID = 0; }, + ); + data = "array(1)"; + }; + }, + ); + vertexInput = $properties.vertexInput.iqm; + /*vertexInput = { + bindings = ( + "$properties.vertexInput.iqm.bindings[0]", + ); + attributes = ( + "$properties.vertexInput.iqm.attributes[0]", + "$properties.vertexInput.iqm.attributes[1]", + "$properties.vertexInput.iqm.attributes[2]", + ); + };*/ + inputAssembly = $properties.inputAssembly.iqm; + layout = iqm_layout; + }; + iqm_gbuf = { + @inherit = $properties.pipelines.gbuf_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + mapEntries = ( + // !IQMDepthOnly + { size = 4; offset = 0; constantID = 0; }, + ); + data = "array(0)"; + }; + }, + { + stage = fragment; + name = main; + module = $builtin/iqm.frag; + }, + ); + vertexInput = $properties.vertexInput.iqm; + inputAssembly = $properties.inputAssembly.iqm; + layout = iqm_layout; + }; partdraw = { @inherit = $properties.pipelines.trans_base; stages = ( diff --git a/libs/video/renderer/vulkan/shader/iqm.frag b/libs/video/renderer/vulkan/shader/iqm.frag index 7f897422c..2ebc47089 100644 --- a/libs/video/renderer/vulkan/shader/iqm.frag +++ b/libs/video/renderer/vulkan/shader/iqm.frag @@ -1,6 +1,6 @@ #version 450 -layout (set = 1, binding = 0) uniform sampler2DArray Skin; +layout (set = 1, binding = 0) uniform sampler2D Skin; layout (push_constant) uniform PushConstants { layout (offset = 68) @@ -15,7 +15,7 @@ layout (location = 1) in vec4 position; layout (location = 2) in vec3 normal; layout (location = 3) in vec3 tangent; layout (location = 4) in vec3 bitangent; -layout (location = 5) in vec3 color; +layout (location = 5) in vec4 color; layout (location = 0) out vec4 frag_color; layout (location = 1) out vec4 frag_emission; @@ -27,18 +27,19 @@ main (void) { vec4 c; vec4 e; - vec3 n; + //vec3 n; int i; - mat3 tbn = mat3 (tangent, bitangent, normal); + //mat3 tbn = mat3 (tangent, bitangent, normal); - c = texture (Skin, vec3 (texcoord, 0)) * base_color; - c += texture (Skin, vec3 (texcoord, 1)) * unpackUnorm4x8(colorA); - c += texture (Skin, vec3 (texcoord, 2)) * unpackUnorm4x8(colorB); - e = texture (Skin, vec3 (texcoord, 3)); - n = texture (Skin, vec3 (texcoord, 4)).xyz * 2 - 1; + c = texture (Skin, texcoord);// * color; + //c = texture (Skin, vec3 (texcoord, 0)) * color; + //c += texture (Skin, vec3 (texcoord, 1)) * unpackUnorm4x8(colorA); + //c += texture (Skin, vec3 (texcoord, 2)) * unpackUnorm4x8(colorB); + //e = texture (Skin, vec3 (texcoord, 3)); + //n = texture (Skin, vec3 (texcoord, 4)).xyz * 2 - 1; frag_color = c; - frag_emission = e; - frag_normal = vec4(tbn * n, 1); + frag_emission = vec4(0,0,0,1);//e; + frag_normal = vec4(normal,1);//vec4(tbn * n, 1); frag_position = position; } diff --git a/libs/video/renderer/vulkan/shader/iqm.vert b/libs/video/renderer/vulkan/shader/iqm.vert index 590c44118..1f912dcae 100644 --- a/libs/video/renderer/vulkan/shader/iqm.vert +++ b/libs/video/renderer/vulkan/shader/iqm.vert @@ -1,5 +1,7 @@ #version 450 +layout (constant_id = 0) const bool IQMDepthOnly = false; + layout (set = 0, binding = 0) uniform Matrices { mat4 Projection3d; mat4 View; @@ -7,7 +9,7 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 Projection2d; }; -layout (set = 3, binding = 0) buffer Bones { +layout (set = 2, binding = 0) buffer Bones { // NOTE these are transposed, so v * m mat3x4 bones[]; }; @@ -18,7 +20,7 @@ layout (push_constant) uniform PushConstants { }; layout (location = 0) in vec3 vposition; -layout (location = 1) in ivec4 vbones; +layout (location = 1) in uvec4 vbones; layout (location = 2) in vec4 vweights; layout (location = 3) in vec2 vtexcoord; layout (location = 4) in vec3 vnormal; @@ -41,12 +43,16 @@ main (void) m += bones[vbones.w] * vweights.w; vec4 pos = vec4 (Model * vec4(vposition, 1) * m, 1); gl_Position = Projection3d * (View * pos); - position = pos; - mat3 adjTrans = mat3 (cross(m[1].xyz, m[2].xyz), cross(m[2].xyz, m[0].xyz), - cross(m[0].xyz, m[1].xyz)); - normal = mat3 (Model) * vnormal * adjTrans; - tangent = mat3 (Model) * vtangent.xyz * adjTrans; - bitangent = cross (normal, tangent) * vtangent.w; - texcoord = vtexcoord; - color = vcolor; + + if (!IQMDepthOnly) { + position = pos; + mat3 adjTrans = mat3 (cross(m[1].xyz, m[2].xyz), + cross(m[2].xyz, m[0].xyz), + cross(m[0].xyz, m[1].xyz)); + normal = mat3 (Model) * vnormal * adjTrans; + tangent = mat3 (Model) * vtangent.xyz * adjTrans; + bitangent = cross (normal, tangent) * vtangent.w; + texcoord = vtexcoord; + color = vcolor; + } } diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 0e19d4dd6..078667852 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -34,6 +34,7 @@ #include #include "QF/cvar.h" +#include "QF/iqm.h" #include "QF/va.h" #include "QF/scene/entity.h" @@ -42,6 +43,7 @@ #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/renderpass.h" @@ -72,7 +74,7 @@ static QFV_Subpass subpass_map[] = { static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, - qfv_iqm_skin_t **skins, + qfv_iqm_skin_t *skins, uint32_t numPC, qfv_push_constants_t *constants, iqm_t *iqm, qfv_renderframe_t *rFrame) { @@ -88,20 +90,28 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, mesh->geom_buffer, mesh->rend_buffer, }; - int bindingCount = skins ? 2 : 1; + int bindingCount = 2;//skins ? 2 : 1; dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, - VK_INDEX_TYPE_UINT32); + VK_INDEX_TYPE_UINT16); QFV_PushConstants (device, cmd, ictx->layout, numPC, constants); for (int i = 0; i < iqm->num_meshes; i++) { if (skins) { VkDescriptorSet sets[] = { - skins[i]->descriptor, + skins[i].descriptor, + mesh->bones_descriptors[ctx->curFrame], }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - ictx->layout, 1, 1, sets, 0, 0); + ictx->layout, 1, 2, sets, 0, 0); + } else { + VkDescriptorSet sets[] = { + mesh->bones_descriptors[ctx->curFrame], + }; + dfunc->vkCmdBindDescriptorSets (cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + ictx->layout, 2, 1, sets, 0, 0); } dfunc->vkCmdDrawIndexed (cmd, 3 * iqm->meshes[i].num_triangles, 1, 3 * iqm->meshes[i].first_triangle, 0, 0); @@ -117,7 +127,7 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) model_t *model = ent->renderer.model; iqm_t *iqm = (iqm_t *) model->aliashdr; qfv_iqm_t *mesh = iqm->extra_data; - qfv_iqm_skin_t **skins = &mesh->skins; + qfv_iqm_skin_t *skins = mesh->skins; iqm_push_constants_t constants = {}; constants.blend = R_IQMGetLerpedFrames (ent, iqm); @@ -144,8 +154,8 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) }; QuatCopy (ent->renderer.colormod, constants.base_color); - QuatCopy (skins[0]->colora, constants.colorA); - QuatCopy (skins[0]->colorb, constants.colorB); + QuatCopy (skins[0].colora, constants.colorA); + QuatCopy (skins[0].colorb, constants.colorB); QuatZero (constants.fog); emit_commands (aframe->cmdSet.a[QFV_iqmDepth], @@ -157,8 +167,8 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) } static void -alias_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, - qfv_renderframe_t *rFrame) +iqm_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, + qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -200,7 +210,7 @@ alias_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, } static void -alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) +iqm_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -222,8 +232,8 @@ Vulkan_IQMBegin (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], aframe->cmdSet.a[QFV_iqmGBuffer]); - alias_begin_subpass (QFV_iqmDepth, ictx->depth, rFrame); - alias_begin_subpass (QFV_iqmGBuffer, ictx->gbuf, rFrame); + iqm_begin_subpass (QFV_iqmDepth, ictx->depth, rFrame); + iqm_begin_subpass (QFV_iqmGBuffer, ictx->gbuf, rFrame); } void @@ -233,8 +243,69 @@ Vulkan_IQMEnd (qfv_renderframe_t *rFrame) iqmctx_t *ictx = ctx->iqm_context; iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; - alias_end_subpass (aframe->cmdSet.a[QFV_iqmDepth], ctx); - alias_end_subpass (aframe->cmdSet.a[QFV_iqmGBuffer], ctx); + iqm_end_subpass (aframe->cmdSet.a[QFV_iqmDepth], ctx); + iqm_end_subpass (aframe->cmdSet.a[QFV_iqmGBuffer], ctx); +} + +static VkWriteDescriptorSet base_buffer_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + 0, 0, 0 +}; + +void +Vulkan_IQMAddBones (vulkan_ctx_t *ctx, iqm_t *iqm) +{ + qfvPushDebug (ctx, "Vulkan_IQMAddBones"); + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + iqmctx_t *ictx = ctx->iqm_context; + __auto_type mesh = (qfv_iqm_t *) iqm->extra_data; + int num_sets = ictx->frames.size; + + //FIXME kinda dumb + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (num_sets, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = ictx->bones_setLayout; + } + __auto_type sets = QFV_AllocateDescriptorSet (device, ictx->bones_pool, + layouts); + for (size_t i = 0; i < sets->size; i++) { + mesh->bones_descriptors[i] = sets->a[i]; + } + free (sets); + + VkDescriptorBufferInfo bufferInfo[num_sets]; + size_t bones_size = iqm->num_joints * 3 * sizeof (vec4f_t); + for (int i = 0; i < num_sets; i++) { + bufferInfo[i].buffer = mesh->bones_buffer; + bufferInfo[i].offset = i * bones_size; + bufferInfo[i].range = bones_size; + }; + VkWriteDescriptorSet write[num_sets]; + for (int i = 0; i < num_sets; i++) { + write[i] = base_buffer_write; + write[i].dstSet = mesh->bones_descriptors[i]; + write[i].pBufferInfo = &bufferInfo[i]; + } + dfunc->vkUpdateDescriptorSets (device->dev, num_sets, write, 0, 0); + + qfvPopDebug (ctx); +} + +void +Vulkan_IQMRemoveBones (vulkan_ctx_t *ctx, iqm_t *iqm) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + iqmctx_t *ictx = ctx->iqm_context; + __auto_type mesh = (qfv_iqm_t *) iqm->extra_data; + int num_sets = ictx->frames.size; + + dfunc->vkFreeDescriptorSets (device->dev, ictx->bones_pool, num_sets, + mesh->bones_descriptors); } void @@ -267,11 +338,14 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&ictx->frames, frames); ictx->frames.grow = 0; - ictx->depth = Vulkan_CreateGraphicsPipeline (ctx, "alias_depth"); - ictx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "alias_gbuf"); - ictx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); + ictx->depth = Vulkan_CreateGraphicsPipeline (ctx, "iqm_depth"); + ictx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "iqm_gbuf"); + ictx->layout = Vulkan_CreatePipelineLayout (ctx, "iqm_layout"); ictx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); + ictx->bones_pool = Vulkan_CreateDescriptorPool (ctx, "bone_pool"); + ictx->bones_setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "bone_set"); + for (size_t i = 0; i < frames; i++) { __auto_type aframe = &ictx->frames.a[i]; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index af5ae3dd1..a68022c32 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -51,7 +51,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" -//#include "QF/Vulkan/qf_iqm.h" +#include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" @@ -95,7 +95,7 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame) } while (0) RE_LOOP (alias, Alias); - //RE_LOOP (iqm, IQM); + RE_LOOP (iqm, IQM); RE_LOOP (sprite, Sprite); } From 8204e8a8c16272ce9097765bb969dcb49b9ae57d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 12:12:02 +0900 Subject: [PATCH 2778/3664] [vulkan] Clear lights when the scene is cleared Fixes a segfault when shutting down my test program. --- libs/video/renderer/vid_render_vulkan.c | 1 + libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a50cab69e..fd1cc05f1 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -111,6 +111,7 @@ vulkan_R_ClearState (void) R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); + Vulkan_LoadLights (0, vulkan_ctx); } static void diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index ce61d83c2..ddbda0032 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -697,5 +697,5 @@ Vulkan_LoadLights (scene_t *scene, vulkan_ctx_t *ctx) lightingctx_t *lctx = ctx->lighting_context; lctx->scene = scene; - lctx->ldata = scene->lights; + lctx->ldata = scene ? scene->lights : 0; } From c59ab8882d465269d6436085c6a41da1d83b961e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 12:38:31 +0900 Subject: [PATCH 2779/3664] [vulkan] Label renderpass and subpass sections This makes finding the relevant commands in render doc much much easier. --- include/QF/Vulkan/debug.h | 15 ++++ include/QF/Vulkan/renderpass.h | 9 +++ libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vid_render_vulkan.c | 7 ++ libs/video/renderer/vulkan/debug.c | 71 +++++++++++++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 13 ++++ 6 files changed, 116 insertions(+) create mode 100644 libs/video/renderer/vulkan/debug.c diff --git a/include/QF/Vulkan/debug.h b/include/QF/Vulkan/debug.h index 482680eb7..200d2aab2 100644 --- a/include/QF/Vulkan/debug.h +++ b/include/QF/Vulkan/debug.h @@ -1,6 +1,13 @@ #ifndef __QF_Vulkan_debug_h #define __QF_Vulkan_debug_h +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + +#include "QF/simd/types.h" + #if (defined(_WIN32) && !defined(_WIN64)) || (__WORDSIZE < 64) #define QFV_duCmdBeginLabel(device, cmd, name...) #define QFV_duCmdEndLabel(device, cmd) @@ -126,4 +133,12 @@ } while (0) #endif +struct qfv_device_s; + +void QFV_CmdBeginLabel (struct qfv_device_s *device, VkCommandBuffer cmd, + const char *name, vec4f_t color); +void QFV_CmdEndLabel (struct qfv_device_s *device, VkCommandBuffer cmd); +void QFV_CmdInsertLabel (struct qfv_device_s *device, VkCommandBuffer cmd, + const char *name, vec4f_t color); + #endif//__QF_Vulkan_debug_h diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index 5e3daaa26..4aa954c16 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -2,6 +2,7 @@ #define __QF_Vulkan_renderpass_h #include "QF/darray.h" +#include "QF/simd/types.h" typedef struct qfv_attachmentdescription_s DARRAY_TYPE (VkAttachmentDescription) qfv_attachmentdescription_t; @@ -47,11 +48,17 @@ QFV_CreateFramebuffer (struct qfv_device_s *device, struct qfv_imageviewset_s *attachments, VkExtent2D, uint32_t layers); +typedef struct qfv_subpass_s { + vec4f_t color; + const char *name; +} qfv_subpass_t; + typedef struct qfv_renderframe_s { struct vulkan_ctx_s *vulkan_ctx; struct qfv_renderpass_s *renderpass; VkSubpassContents subpassContents; int subpassCount; + qfv_subpass_t *subpassInfo; struct qfv_cmdbufferset_s *subpassCmdSets; } qfv_renderframe_t; @@ -62,6 +69,8 @@ typedef struct clearvalueset_s DARRAY_TYPE (VkClearValue) clearvalueset_t; typedef struct qfv_renderpass_s { + vec4f_t color; // for bebugging + const char *name; // for bebugging struct plitem_s *renderpassDef; VkRenderPass renderpass; clearvalueset_t *clearValues; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index fd1496752..d164eb5f3 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -201,6 +201,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/buffer.c \ libs/video/renderer/vulkan/command.c \ libs/video/renderer/vulkan/capture.c \ + libs/video/renderer/vulkan/debug.c \ libs/video/renderer/vulkan/descriptor.c \ libs/video/renderer/vulkan/device.c \ libs/video/renderer/vulkan/image.c \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index fd1cc05f1..901a55420 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -55,6 +55,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" @@ -348,6 +349,7 @@ vulkan_end_frame (void) __auto_type rp = vulkan_ctx->renderPasses.a[i]; __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color); if (rpFrame->renderpass) { renderPassInfo.framebuffer = frame->framebuffer, renderPassInfo.renderPass = rp->renderpass; @@ -360,8 +362,12 @@ vulkan_end_frame (void) for (int j = 0; j < rpFrame->subpassCount; j++) { __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; if (cmdSet->size) { + QFV_CmdBeginLabel (device, frame->cmdBuffer, + rpFrame->subpassInfo[j].name, + rpFrame->subpassInfo[j].color); dfunc->vkCmdExecuteCommands (frame->cmdBuffer, cmdSet->size, cmdSet->a); + QFV_CmdEndLabel (device, frame->cmdBuffer); } // reset for next time around cmdSet->size = 0; @@ -386,6 +392,7 @@ vulkan_end_frame (void) cmdSet->size = 0; } } + QFV_CmdEndLabel (device, frame->cmdBuffer); } if (vulkan_ctx->capture_callback) { diff --git a/libs/video/renderer/vulkan/debug.c b/libs/video/renderer/vulkan/debug.c new file mode 100644 index 000000000..e8acfed71 --- /dev/null +++ b/libs/video/renderer/vulkan/debug.c @@ -0,0 +1,71 @@ +/* + debug.c + + Vulkan debug support + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/device.h" + +void +QFV_CmdBeginLabel (qfv_device_t *device, VkCommandBuffer cmd, + const char *name, vec4f_t color) +{ + qfv_devfuncs_t *dfunc = device->funcs; + if (dfunc->vkCmdBeginDebugUtilsLabelEXT) { + VkDebugUtilsLabelEXT label = { + VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, + .pLabelName = name, + .color = { color[0], color[1], color[2], color[3] }, + }; + dfunc->vkCmdBeginDebugUtilsLabelEXT (cmd, &label); + } +} + +void +QFV_CmdEndLabel (qfv_device_t *device, VkCommandBuffer cmd) +{ + qfv_devfuncs_t *dfunc = device->funcs; + if (dfunc->vkCmdEndDebugUtilsLabelEXT) { + dfunc->vkCmdEndDebugUtilsLabelEXT (cmd); + } +} + +void +QFV_CmdInsertLabel (qfv_device_t *device, VkCommandBuffer cmd, + const char *name, vec4f_t color) +{ + qfv_devfuncs_t *dfunc = device->funcs; + if (dfunc->vkCmdBeginDebugUtilsLabelEXT) { + VkDebugUtilsLabelEXT label = { + VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, + .pLabelName = name, + .color = { color[0], color[1], color[2], color[3] }, + }; + dfunc->vkCmdInsertDebugUtilsLabelEXT (cmd, &label); + } +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 0eaccc253..af17477b6 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -480,10 +480,20 @@ static void init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, qfv_renderframe_t *rFrame) { + // FIXME should not be hard-coded + static qfv_subpass_t subpass_info[] = { + { .name = "depth", .color = { 0.5, 0.5, 0.5, 1} }, + { .name = "translucent", .color = { 0.25, 0.25, 0.6, 1} }, + { .name = "g-buffef", .color = { 0.3, 0.7, 0.3, 1} }, + { .name = "lighting", .color = { 0.8, 0.8, 0.8, 1} }, + { .name = "compose", .color = { 0.7, 0.3, 0.3, 1} }, + }; + rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; rFrame->vulkan_ctx = ctx; rFrame->renderpass = rp; rFrame->subpassCount = QFV_NumPasses; + rFrame->subpassInfo = subpass_info; //FIXME rFrame->subpassCmdSets = malloc (QFV_NumPasses * sizeof (qfv_cmdbufferset_t)); for (int j = 0; j < QFV_NumPasses; j++) { @@ -499,6 +509,9 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); + rp->name = name; + rp->color = (vec4f_t) { 0, 1, 0, 1 }; //FIXME + hashtab_t *tab = ctx->renderpasses; const char *path; path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); From 18af3401606dd22ec6c96afe8dafc3b99e9b4faa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 13:00:02 +0900 Subject: [PATCH 2780/3664] [vulkan] Normalize iqm normals Same mistake as for alias, I simply forgot to do it for iqm when I got it working. --- libs/video/renderer/vulkan/shader/iqm.frag | 9 ++++++--- libs/video/renderer/vulkan/shader/iqm.vert | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/iqm.frag b/libs/video/renderer/vulkan/shader/iqm.frag index 2ebc47089..543ee0bdb 100644 --- a/libs/video/renderer/vulkan/shader/iqm.frag +++ b/libs/video/renderer/vulkan/shader/iqm.frag @@ -12,9 +12,9 @@ layout (push_constant) uniform PushConstants { layout (location = 0) in vec2 texcoord; layout (location = 1) in vec4 position; -layout (location = 2) in vec3 normal; -layout (location = 3) in vec3 tangent; -layout (location = 4) in vec3 bitangent; +layout (location = 2) in vec3 fnormal; +layout (location = 3) in vec3 ftangent; +layout (location = 4) in vec3 fbitangent; layout (location = 5) in vec4 color; layout (location = 0) out vec4 frag_color; @@ -29,6 +29,9 @@ main (void) vec4 e; //vec3 n; int i; + vec3 normal = normalize (fnormal); + vec3 tangent = normalize (ftangent); + vec3 bitangent = normalize (fbitangent); //mat3 tbn = mat3 (tangent, bitangent, normal); c = texture (Skin, texcoord);// * color; diff --git a/libs/video/renderer/vulkan/shader/iqm.vert b/libs/video/renderer/vulkan/shader/iqm.vert index 1f912dcae..b02c369e9 100644 --- a/libs/video/renderer/vulkan/shader/iqm.vert +++ b/libs/video/renderer/vulkan/shader/iqm.vert @@ -49,8 +49,9 @@ main (void) mat3 adjTrans = mat3 (cross(m[1].xyz, m[2].xyz), cross(m[2].xyz, m[0].xyz), cross(m[0].xyz, m[1].xyz)); - normal = mat3 (Model) * vnormal * adjTrans; + normal = normalize (mat3 (Model) * vnormal * adjTrans); tangent = mat3 (Model) * vtangent.xyz * adjTrans; + tangent = normalize (tangent - dot (tangent, normal) * normal); bitangent = cross (normal, tangent) * vtangent.w; texcoord = vtexcoord; color = vcolor; From 08c8b8d51ba1c99a66734a373505b11b6844eb41 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 14:12:02 +0900 Subject: [PATCH 2781/3664] [vulkan] Add entity labels to command queues Brush models looked a little too tricky due to the very different style of command queue, so that's left for now, but alias, iqm and sprite entities are now labeled. The labels are made up of the lower 5 hex digits of the entity address, the position, and colored by the normalized position vector. Not sure that's the best choice as it does mean the color changes as the entity moves, and can be quite subtle between nearby entities, but it still helps identify the entities in the command buffer. And, as I suspected, I've got multiple draw calls for the one ogre. Now to find out why. --- include/QF/Vulkan/qf_vid.h | 4 ++++ libs/video/renderer/vulkan/vulkan_alias.c | 10 +++++++--- libs/video/renderer/vulkan/vulkan_iqm.c | 10 +++++++--- libs/video/renderer/vulkan/vulkan_sprite.c | 10 +++++++--- libs/video/renderer/vulkan/vulkan_vid_common.c | 17 +++++++++++++++++ 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 6f235d1b6..df818603f 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -81,4 +81,8 @@ VkSampler Vulkan_CreateSampler (struct vulkan_ctx_s *ctx, const char *name); VkDescriptorSetLayout Vulkan_CreateDescriptorSetLayout(struct vulkan_ctx_s*ctx, const char *name); +struct entity_s; +void Vulkan_BeginEntityLabel (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd, + struct entity_s *ent); + #endif // __QF_Vulkan_vid_h diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 8da5de204..b9a683fc6 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -76,7 +76,7 @@ static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_alias_skin_t *skin, uint32_t numPC, qfv_push_constants_t *constants, - aliashdr_t *hdr, qfv_renderframe_t *rFrame) + aliashdr_t *hdr, qfv_renderframe_t *rFrame, entity_t *ent) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -97,6 +97,8 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, }; int bindingCount = skin ? 3 : 2; + Vulkan_BeginEntityLabel (ctx, cmd, ent); + dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, VK_INDEX_TYPE_UINT32); @@ -109,6 +111,8 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, actx->layout, 1, 1, sets, 0, 0); } dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); + + QFV_CmdEndLabel (device, cmd); } void @@ -164,10 +168,10 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) emit_commands (aframe->cmdSet.a[QFV_aliasDepth], ent->animation.pose1, ent->animation.pose2, - 0, 2, push_constants, hdr, rFrame); + 0, 2, push_constants, hdr, rFrame, ent); emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], ent->animation.pose1, ent->animation.pose2, - skin, 6, push_constants, hdr, rFrame); + skin, 6, push_constants, hdr, rFrame, ent); } static void diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 078667852..d1b1ea083 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -76,7 +76,7 @@ static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_iqm_skin_t *skins, uint32_t numPC, qfv_push_constants_t *constants, - iqm_t *iqm, qfv_renderframe_t *rFrame) + iqm_t *iqm, qfv_renderframe_t *rFrame, entity_t *ent) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -92,6 +92,8 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, }; int bindingCount = 2;//skins ? 2 : 1; + Vulkan_BeginEntityLabel (ctx, cmd, ent); + dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, VK_INDEX_TYPE_UINT16); @@ -116,6 +118,8 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, dfunc->vkCmdDrawIndexed (cmd, 3 * iqm->meshes[i].num_triangles, 1, 3 * iqm->meshes[i].first_triangle, 0, 0); } + + QFV_CmdEndLabel (device, cmd); } void @@ -160,10 +164,10 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) emit_commands (aframe->cmdSet.a[QFV_iqmDepth], ent->animation.pose1, ent->animation.pose2, - 0, 2, push_constants, iqm, rFrame); + 0, 2, push_constants, iqm, rFrame, ent); emit_commands (aframe->cmdSet.a[QFV_iqmGBuffer], ent->animation.pose1, ent->animation.pose2, - skins, 6, push_constants, iqm, rFrame); + skins, 6, push_constants, iqm, rFrame, ent); } static void diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index b0d9866cd..cbe714797 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -82,13 +82,15 @@ static QFV_Subpass subpass_map[] = { static void emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, int numPC, qfv_push_constants_t *constants, - qfv_renderframe_t *rFrame) + qfv_renderframe_t *rFrame, entity_t *ent) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; spritectx_t *sctx = ctx->sprite_context; + Vulkan_BeginEntityLabel (ctx, cmd, ent); + QFV_PushConstants (device, cmd, sctx->layout, numPC, constants); VkDescriptorSet sets[] = { sprite->descriptors, @@ -96,6 +98,8 @@ emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, sctx->layout, 1, 1, sets, 0, 0); dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); + + QFV_CmdEndLabel (device, cmd); } void @@ -126,10 +130,10 @@ Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) emit_commands (sframe->cmdSet.a[QFV_spriteDepth], (qfv_sprite_t *) ((byte *) sprite + sprite->data), - 2, push_constants, rFrame); + 2, push_constants, rFrame, ent); emit_commands (sframe->cmdSet.a[QFV_spriteGBuffer], (qfv_sprite_t *) ((byte *) sprite + sprite->data), - 2, push_constants, rFrame); + 2, push_constants, rFrame, ent); } static void diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index af17477b6..36d8de490 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -49,6 +49,8 @@ #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/simd/vec4f.h" +#include "QF/scene/entity.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" @@ -799,3 +801,18 @@ Vulkan_DestroyFrames (vulkan_ctx_t *ctx) DARRAY_CLEAR (&ctx->frames); } + +void +Vulkan_BeginEntityLabel (vulkan_ctx_t *ctx, VkCommandBuffer cmd, + entity_t *ent) +{ + qfv_device_t *device = ctx->device; + int entaddr = (intptr_t) ent & 0xfffff; + vec4f_t pos = Transform_GetWorldPosition (ent->transform); + vec4f_t dir = normalf (pos - (vec4f_t) { 0, 0, 0, 1 }); + vec4f_t color = 0.5 * dir + (vec4f_t) {0.5, 0.5, 0.5, 1 }; + + QFV_CmdBeginLabel (device, cmd, + va (ctx->va_ctx, "ent %05x [%g, %g, %g]", entaddr, + VectorExpand (pos)), color); +} From c92432984302cadeace9dc289d72e88b5f6e0033 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 May 2022 14:35:03 +0900 Subject: [PATCH 2782/3664] [scene] Use same id for entity queue test and add This fixes the multiple draws of the same entity. Should be a small speedup for all renderers :) --- include/QF/scene/entity.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index 2345ac3e2..373c81f1a 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -113,9 +113,10 @@ ENTINLINE void EntQueue_AddEntity (entqueue_t *queue, entity_t *ent, int queue_num) { - if (!set_is_member (queue->queued_ents, ent->id)) { + int id = -ent->id;//FIXME use ~ + if (!set_is_member (queue->queued_ents, id)) { // entity ids are negative (ones-complement) - set_add (queue->queued_ents, -ent->id);//FIXME use ~ + set_add (queue->queued_ents, id); DARRAY_APPEND (&queue->ent_queues[queue_num], ent); } } From 2a0bbfb4e99cf7ed2e435f4a19099516b15fc9cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 May 2022 02:15:50 +0900 Subject: [PATCH 2783/3664] [io_mesh_qfmdl] Use an int for NLA start frame At at some stage blender enforced frames being integers (In the past, there was support for fractional, I think, but I also seem to remember it not working) (yes, for anybody looking, this commit message is more or less copied from io_object_mu). --- tools/io_mesh_qfmdl/import_mdl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/io_mesh_qfmdl/import_mdl.py b/tools/io_mesh_qfmdl/import_mdl.py index 2a7da9a93..76f393424 100644 --- a/tools/io_mesh_qfmdl/import_mdl.py +++ b/tools/io_mesh_qfmdl/import_mdl.py @@ -226,7 +226,7 @@ def build_actions(mdl): ad = sk.animation_data_create() track = ad.nla_tracks.new(); track.name = mdl.name - start_frame = 1.0 + start_frame = 1 for frame in mdl.frames: act = bpy.data.actions.new(frame.name) data = [] @@ -260,7 +260,7 @@ def build_actions(mdl): data.append((k, co)) set_keys(act, data) track.strips.new(act.name, start_frame, act) - start_frame += act.frame_range[1] + start_frame += int(act.frame_range[1]) def merge_frames(mdl): def get_base(name): From 1dff24dbd0573e5164411e65bb3b933045edcedc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 May 2022 11:14:00 +0900 Subject: [PATCH 2784/3664] [scene] Implement Hierarchy_Copy It copies an entire hierarchy (minus actual entities, but I'm as yet unsure how to proceed with them), even across scenes as the source scene is irrelevant and the destination scene is used for creating the new transforms. --- include/QF/scene/hierarchy.h | 3 +- include/scn_internal.h | 2 + libs/scene/hierarchy.c | 107 +++++++++++++++++++++++++++++++++++ libs/scene/transform.c | 13 ++++- 4 files changed, 122 insertions(+), 3 deletions(-) diff --git a/include/QF/scene/hierarchy.h b/include/QF/scene/hierarchy.h index 61a77c36b..1283c6de8 100644 --- a/include/QF/scene/hierarchy.h +++ b/include/QF/scene/hierarchy.h @@ -67,7 +67,8 @@ typedef struct hierarchy_s { } hierarchy_t; hierarchy_t *Hierarchy_New (struct scene_s *scene, int createRoot); -hierarchy_t *Hierarchy_Copy (hierarchy_t *src); +void Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count); +hierarchy_t *Hierarchy_Copy (struct scene_s *scene, const hierarchy_t *src); void Hierarchy_Delete (hierarchy_t *hierarchy); void Hierarchy_UpdateMatrices (hierarchy_t *hierarchy); diff --git a/include/scn_internal.h b/include/scn_internal.h index 9ad3521dc..e2afd9d6f 100644 --- a/include/scn_internal.h +++ b/include/scn_internal.h @@ -13,4 +13,6 @@ typedef struct scene_resources_s { PR_RESMAP (transform_t) transforms; } scene_resources_t; +transform_t *__transform_alloc (struct scene_s *scene); + #endif//__scn_internal_h diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index c6b6f7074..17c161d70 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -455,3 +455,110 @@ Hierarchy_Delete (hierarchy_t *hierarchy) DARRAY_CLEAR (&hierarchy->worldScale); PR_RESFREE (res->hierarchies, hierarchy); } + +void +Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count) +{ + size_t size = hierarchy->transform.size; + + DARRAY_RESIZE (&hierarchy->transform, size + count); + DARRAY_RESIZE (&hierarchy->entity, size + count); + DARRAY_RESIZE (&hierarchy->childCount, size + count); + DARRAY_RESIZE (&hierarchy->childIndex, size + count); + DARRAY_RESIZE (&hierarchy->parentIndex, size + count); + DARRAY_RESIZE (&hierarchy->name, size + count); + DARRAY_RESIZE (&hierarchy->tag, size + count); + DARRAY_RESIZE (&hierarchy->modified, size + count); + DARRAY_RESIZE (&hierarchy->localMatrix, size + count); + DARRAY_RESIZE (&hierarchy->localInverse, size + count); + DARRAY_RESIZE (&hierarchy->worldMatrix, size + count); + DARRAY_RESIZE (&hierarchy->worldInverse, size + count); + DARRAY_RESIZE (&hierarchy->localRotation, size + count); + DARRAY_RESIZE (&hierarchy->localScale, size + count); + DARRAY_RESIZE (&hierarchy->worldRotation, size + count); + DARRAY_RESIZE (&hierarchy->worldScale, size + count); + + DARRAY_RESIZE (&hierarchy->transform, size); + DARRAY_RESIZE (&hierarchy->entity, size); + DARRAY_RESIZE (&hierarchy->childCount, size); + DARRAY_RESIZE (&hierarchy->childIndex, size); + DARRAY_RESIZE (&hierarchy->parentIndex, size); + DARRAY_RESIZE (&hierarchy->name, size); + DARRAY_RESIZE (&hierarchy->tag, size); + DARRAY_RESIZE (&hierarchy->modified, size); + DARRAY_RESIZE (&hierarchy->localMatrix, size); + DARRAY_RESIZE (&hierarchy->localInverse, size); + DARRAY_RESIZE (&hierarchy->worldMatrix, size); + DARRAY_RESIZE (&hierarchy->worldInverse, size); + DARRAY_RESIZE (&hierarchy->localRotation, size); + DARRAY_RESIZE (&hierarchy->localScale, size); + DARRAY_RESIZE (&hierarchy->worldRotation, size); + DARRAY_RESIZE (&hierarchy->worldScale, size); +} + +hierarchy_t * +Hierarchy_Copy (scene_t *scene, const hierarchy_t *src) +{ + hierarchy_t *dst = Hierarchy_New (scene, 0); + size_t count = src->transform.size; + + DARRAY_RESIZE (&dst->transform, count); + DARRAY_RESIZE (&dst->entity, count); + DARRAY_RESIZE (&dst->childCount, count); + DARRAY_RESIZE (&dst->childIndex, count); + DARRAY_RESIZE (&dst->parentIndex, count); + DARRAY_RESIZE (&dst->name, count); + DARRAY_RESIZE (&dst->tag, count); + DARRAY_RESIZE (&dst->modified, count); + DARRAY_RESIZE (&dst->localMatrix, count); + DARRAY_RESIZE (&dst->localInverse, count); + DARRAY_RESIZE (&dst->worldMatrix, count); + DARRAY_RESIZE (&dst->worldInverse, count); + DARRAY_RESIZE (&dst->localRotation, count); + DARRAY_RESIZE (&dst->localScale, count); + DARRAY_RESIZE (&dst->worldRotation, count); + DARRAY_RESIZE (&dst->worldScale, count); + + for (size_t i = 0; i < count; i++) { + dst->transform.a[i] = __transform_alloc (scene); + dst->transform.a[i]->hierarchy = dst; + dst->transform.a[i]->index = i; + } + for (size_t i = 0; i < count; i++) { + dst->entity.a[i] = 0; // FIXME clone entity + } + memcpy (dst->childCount.a, src->childCount.a, + count * sizeof(dst->childCount.a[0])); + memcpy (dst->childIndex.a, src->childIndex.a, + count * sizeof(dst->childIndex.a[0])); + memcpy (dst->parentIndex.a, src->parentIndex.a, + count * sizeof(dst->parentIndex.a[0])); + for (size_t i = 0; i < count; i++) { + // use the transform code so string allocation remains consistent + // regardless how it changes. + Transform_SetName (dst->transform.a[i], src->name.a[i]); + } + memcpy (dst->tag.a, src->tag.a, + count * sizeof(dst->tag.a[0])); + memcpy (dst->modified.a, src->modified.a, + count * sizeof(dst->modified.a[0])); + memcpy (dst->localMatrix.a, src->localMatrix.a, + count * sizeof(dst->localMatrix.a[0])); + memcpy (dst->localInverse.a, src->localInverse.a, + count * sizeof(dst->localInverse.a[0])); + memcpy (dst->worldMatrix.a, src->worldMatrix.a, + count * sizeof(dst->worldMatrix.a[0])); + memcpy (dst->worldInverse.a, src->worldInverse.a, + count * sizeof(dst->worldInverse.a[0])); + memcpy (dst->localRotation.a, src->localRotation.a, + count * sizeof(dst->localRotation.a[0])); + memcpy (dst->localScale.a, src->localScale.a, + count * sizeof(dst->localScale.a[0])); + memcpy (dst->worldRotation.a, src->worldRotation.a, + count * sizeof(dst->worldRotation.a[0])); + memcpy (dst->worldScale.a, src->worldScale.a, + count * sizeof(dst->localScale.a[0])); + // Just in case the source hierarchy has modified transforms + Hierarchy_UpdateMatrices (dst); + return dst; +} diff --git a/libs/scene/transform.c b/libs/scene/transform.c index d855c4dc9..7048536de 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -44,13 +44,22 @@ #include "scn_internal.h" transform_t * -Transform_New (scene_t *scene, transform_t *parent) +__transform_alloc (scene_t *scene) { scene_resources_t *res = scene->resources; transform_t *transform = PR_RESNEW_NC (res->transforms); - transform->scene = scene; transform->id = PR_RESINDEX (res->transforms, transform); + transform->hierarchy = 0; + transform->index = 0; + return transform; +} + +transform_t * +Transform_New (scene_t *scene, transform_t *parent) +{ + transform_t *transform = __transform_alloc (scene); + if (parent) { transform->hierarchy = parent->hierarchy; transform->index = Hierarchy_InsertHierarchy (parent->hierarchy, 0, From e62b7d7b05529afd54619799b96803bfe124cb38 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 May 2022 14:15:20 +0900 Subject: [PATCH 2785/3664] [vulkan] Allow QFV_ImageFormat to select unorm or srgb This is definitely something that should be selectable per image and not hard-coded into the engine. --- include/QF/Vulkan/image.h | 3 ++- libs/models/iqm/vulkan_model_iqm.c | 4 ++-- libs/video/renderer/vulkan/image.c | 10 +++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index 3524b27ee..dd94d9e7d 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -104,11 +104,12 @@ int QFV_MipLevels (int width, int height) __attribute__((const)); /** Convert QFFormat to VkFormat * * \param format The format to convert. + * \param srgb Select SRGB formats (non-zero) or UNORM (0). * \return The corresponding VkFormat. * * \note For tex_palette, VK_FORMAT_R8_UINT is returned. If \a format is * not a valid QFFormat, then VK_FORMAT_R8_SRGB is returned. */ -VkFormat QFV_ImageFormat (QFFormat format); +VkFormat QFV_ImageFormat (QFFormat format, int srgb); #endif//__QF_Vulkan_image_h diff --git a/libs/models/iqm/vulkan_model_iqm.c b/libs/models/iqm/vulkan_model_iqm.c index 69baa6fcb..da21f1c48 100644 --- a/libs/models/iqm/vulkan_model_iqm.c +++ b/libs/models/iqm/vulkan_model_iqm.c @@ -107,7 +107,7 @@ vulkan_iqm_init_image (iqm_t *iqm, int meshnum, qfv_resobj_t *image) .type = qfv_res_image, .image = { .type = VK_IMAGE_TYPE_2D, - .format = QFV_ImageFormat (tex->format), + .format = QFV_ImageFormat (tex->format, 0), .extent = { .width = tex->width, .height = tex->height, @@ -127,7 +127,7 @@ vulkan_iqm_init_image (iqm_t *iqm, int meshnum, qfv_resobj_t *image) .type = qfv_res_image, .image = { .type = VK_IMAGE_TYPE_2D, - .format = QFV_ImageFormat (tex_rgba), + .format = QFV_ImageFormat (tex_rgba, 0), .extent = { .width = 2, .height = 2, diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index 62daaaf38..f60082c7f 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -267,20 +267,20 @@ QFV_MipLevels (int width, int height) } VkFormat -QFV_ImageFormat (QFFormat format) +QFV_ImageFormat (QFFormat format, int srgb) { switch (format) { case tex_palette: return VK_FORMAT_R8_UINT; case tex_l: case tex_a: - return VK_FORMAT_R8_UNORM; + return srgb ? VK_FORMAT_R8_SRGB : VK_FORMAT_R8_UNORM; case tex_la: - return VK_FORMAT_R8G8_UNORM; + return srgb ? VK_FORMAT_R8G8_SRGB : VK_FORMAT_R8G8_UNORM; case tex_rgb: - return VK_FORMAT_R8G8B8_UNORM; // SRGB? + return srgb ? VK_FORMAT_R8G8B8_SRGB : VK_FORMAT_R8G8B8_UNORM; case tex_rgba: - return VK_FORMAT_R8G8B8A8_UNORM;// SRGB? + return srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM; case tex_frgba: return VK_FORMAT_R32G32B32A32_SFLOAT; } From 09d5c76fe939aed36ba1564e85624a5e57c60737 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 May 2022 14:21:40 +0900 Subject: [PATCH 2786/3664] [vulkan] Implement IQM animations Unfortunately, the animations are pre-baked (by the loader) blocking run-time determined animations (IK etc). However, this at least gets everything working so the basics can be verified (the shader posed some issue resulting in horror movies ;). --- libs/video/renderer/vulkan/shader/iqm.vert | 2 +- libs/video/renderer/vulkan/vulkan_iqm.c | 31 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/shader/iqm.vert b/libs/video/renderer/vulkan/shader/iqm.vert index b02c369e9..9b665c283 100644 --- a/libs/video/renderer/vulkan/shader/iqm.vert +++ b/libs/video/renderer/vulkan/shader/iqm.vert @@ -41,7 +41,7 @@ main (void) m += bones[vbones.y] * vweights.y; m += bones[vbones.z] * vweights.z; m += bones[vbones.w] * vweights.w; - vec4 pos = vec4 (Model * vec4(vposition, 1) * m, 1); + vec4 pos = Model * vec4 (vec4(vposition, 1) * m, 1); gl_Position = Projection3d * (View * pos); if (!IQMDepthOnly) { diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index d1b1ea083..3dd3261ff 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -47,6 +47,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/renderpass.h" +#include "QF/Vulkan/resource.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -122,10 +123,14 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, QFV_CmdEndLabel (device, cmd); } +#define a(x) ((x) & ~0x3f) + void Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; iqmctx_t *ictx = ctx->iqm_context; iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; model_t *model = ent->renderer.model; @@ -133,8 +138,34 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) qfv_iqm_t *mesh = iqm->extra_data; qfv_iqm_skin_t *skins = mesh->skins; iqm_push_constants_t constants = {}; + iqmframe_t *frame; constants.blend = R_IQMGetLerpedFrames (ent, iqm); + frame = R_IQMBlendFrames (iqm, ent->animation.pose1, ent->animation.pose2, + constants.blend, 0); + + vec4f_t *bone_data; + dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE, + 0, (void **)&bone_data); + for (int i = 0; i < iqm->num_joints; i++) { + vec4f_t *b = bone_data + (ctx->curFrame * iqm->num_joints + i) * 3; + mat4f_t f; + // R_IQMBlendFrames sets up the frame as a 4x4 matrix for m * v, but + // the shader wants a 3x4 (column x row) matrix for v * m, which is + // just a transpose (and drop of the 4th column) away. + mat4ftranspose (f, (vec4f_t *) &frame[i]); + // copy only the first 3 columns + memcpy (b, f, 3 * sizeof (vec4f_t)); + } + VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + mesh->bones->memory, + a(3 * ctx->curFrame * iqm->num_joints * sizeof (vec4f_t)), + a(3 * iqm->num_joints * sizeof (vec4f_t) + 0x3f), + }; + dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); + dfunc->vkUnmapMemory (device->dev, mesh->bones->memory); + qfv_push_constants_t push_constants[] = { { VK_SHADER_STAGE_VERTEX_BIT, From b33df8b69882001ae0f9d61da354a1b96baef6a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 May 2022 17:57:40 +0900 Subject: [PATCH 2787/3664] [vulkan] Clean up a pile of unnecessary includes --- include/QF/Vulkan/capture.h | 5 ++++ include/QF/Vulkan/command.h | 5 ++++ include/QF/Vulkan/descriptor.h | 5 ++++ libs/video/renderer/vulkan/barrier.c | 1 - libs/video/renderer/vulkan/buffer.c | 1 - libs/video/renderer/vulkan/capture.c | 1 - libs/video/renderer/vulkan/command.c | 1 - libs/video/renderer/vulkan/descriptor.c | 1 - libs/video/renderer/vulkan/device.c | 1 - libs/video/renderer/vulkan/image.c | 1 - libs/video/renderer/vulkan/memory.c | 1 - libs/video/renderer/vulkan/pipeline.c | 1 - libs/video/renderer/vulkan/renderpass.c | 1 - libs/video/renderer/vulkan/scrap.c | 1 - libs/video/renderer/vulkan/staging.c | 1 - libs/video/renderer/vulkan/swapchain.c | 2 -- libs/video/renderer/vulkan/vkparse.c | 1 - libs/video/renderer/vulkan/vulkan_main.c | 25 ----------------- libs/video/renderer/vulkan/vulkan_matrices.c | 4 --- libs/video/renderer/vulkan/vulkan_particles.c | 4 --- libs/video/renderer/vulkan/vulkan_texture.c | 14 ---------- .../video/renderer/vulkan/vulkan_vid_common.c | 27 +++---------------- 22 files changed, 19 insertions(+), 85 deletions(-) diff --git a/include/QF/Vulkan/capture.h b/include/QF/Vulkan/capture.h index 6cfd9d47e..c3043ae59 100644 --- a/include/QF/Vulkan/capture.h +++ b/include/QF/Vulkan/capture.h @@ -1,6 +1,11 @@ #ifndef __QF_Vulkan_capture_h #define __QF_Vulkan_capture_h +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + #include "QF/darray.h" #include "QF/qtypes.h" diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index d568e03f2..452baa9ca 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -1,6 +1,11 @@ #ifndef __QF_Vulkan_command_h #define __QF_Vulkan_command_h +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + #include "QF/darray.h" typedef struct qfv_cmdbufferset_s diff --git a/include/QF/Vulkan/descriptor.h b/include/QF/Vulkan/descriptor.h index 6dd09bff4..14d6be987 100644 --- a/include/QF/Vulkan/descriptor.h +++ b/include/QF/Vulkan/descriptor.h @@ -1,6 +1,11 @@ #ifndef __QF_Vulkan_descriptor_h #define __QF_Vulkan_descriptor_h +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + #include "QF/darray.h" typedef struct qfv_bindingset_s diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c index 7c4f6b788..2ef03860a 100644 --- a/libs/video/renderer/vulkan/barrier.c +++ b/libs/video/renderer/vulkan/barrier.c @@ -28,7 +28,6 @@ # include "config.h" #endif -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" const qfv_imagebarrier_t imageBarriers[] = { diff --git a/libs/video/renderer/vulkan/buffer.c b/libs/video/renderer/vulkan/buffer.c index 30030adee..95f5fea74 100644 --- a/libs/video/renderer/vulkan/buffer.c +++ b/libs/video/renderer/vulkan/buffer.c @@ -29,7 +29,6 @@ #endif #include "QF/mathlib.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c index 974957aa7..53da1560f 100644 --- a/libs/video/renderer/vulkan/capture.c +++ b/libs/video/renderer/vulkan/capture.c @@ -28,7 +28,6 @@ # include "config.h" #endif -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index c35fede96..5c64f851c 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -28,7 +28,6 @@ # include "config.h" #endif -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" diff --git a/libs/video/renderer/vulkan/descriptor.c b/libs/video/renderer/vulkan/descriptor.c index 026d5ae9c..ca7791ea8 100644 --- a/libs/video/renderer/vulkan/descriptor.c +++ b/libs/video/renderer/vulkan/descriptor.c @@ -30,7 +30,6 @@ #include "QF/hash.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 0ff989511..5dc2e331a 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -32,7 +32,6 @@ #include "QF/sys.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" diff --git a/libs/video/renderer/vulkan/image.c b/libs/video/renderer/vulkan/image.c index f60082c7f..9d9bfbb21 100644 --- a/libs/video/renderer/vulkan/image.c +++ b/libs/video/renderer/vulkan/image.c @@ -30,7 +30,6 @@ #include "QF/mathlib.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" diff --git a/libs/video/renderer/vulkan/memory.c b/libs/video/renderer/vulkan/memory.c index ee2d6ec01..12f6d4ab3 100644 --- a/libs/video/renderer/vulkan/memory.c +++ b/libs/video/renderer/vulkan/memory.c @@ -28,7 +28,6 @@ # include "config.h" #endif -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/memory.h" diff --git a/libs/video/renderer/vulkan/pipeline.c b/libs/video/renderer/vulkan/pipeline.c index b602287f6..c83ef4a3b 100644 --- a/libs/video/renderer/vulkan/pipeline.c +++ b/libs/video/renderer/vulkan/pipeline.c @@ -30,7 +30,6 @@ #include "QF/dstring.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/pipeline.h" diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index e0a95db8d..f69c1bd96 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -30,7 +30,6 @@ #include "QF/cvar.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/renderpass.h" diff --git a/libs/video/renderer/vulkan/scrap.c b/libs/video/renderer/vulkan/scrap.c index 6517d2b17..9e89fb050 100644 --- a/libs/video/renderer/vulkan/scrap.c +++ b/libs/video/renderer/vulkan/scrap.c @@ -34,7 +34,6 @@ #include "QF/render.h" #include "QF/ui/vrect.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index e16aa49df..22f96f40b 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -30,7 +30,6 @@ #include "QF/dstring.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 9f48594b2..278b27f70 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -9,13 +9,11 @@ #include "QF/cvar.h" #include "QF/mathlib.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/swapchain.h" -#include "r_internal.h" #include "vid_vulkan.h" qfv_swapchain_t * diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 98effde21..4e7c95a9a 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -36,7 +36,6 @@ #include "QF/mathlib.h" #include "QF/va.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index a68022c32..9af4c5b73 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -150,28 +150,3 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) Vulkan_BuildDisplayLists (scene->models, scene->num_models, ctx); Vulkan_LoadLights (scene, ctx); } - -/*void -glsl_R_LineGraph (int x, int y, int *h_vals, int count) -{ -}*/ - -/*void -glsl_R_TimeRefresh_f (void) -{ - double start, stop, time; - int i; - - glsl_ctx->end_rendering (); - - start = Sys_DoubleTime (); - for (i = 0; i < 128; i++) { - r_refdef.viewangles[1] = i * (360.0 / 128.0); - Vulkan_RenderView (ctx); - glsl_ctx->end_rendering (); - } - - stop = Sys_DoubleTime (); - time = stop - start; - Sys_Printf ("%g seconds (%g fps)\n", time, 128 / time); -}*/ diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 363ca70be..67765734f 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -49,16 +49,12 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/projection.h" #include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/staging.h" -#include "QF/ui/view.h" #include "r_internal.h" #include "vid_vulkan.h" -#include "util.h" - static void setup_view (vulkan_ctx_t *ctx) { diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 461c01c91..e2fe68ac7 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -42,9 +42,6 @@ #include "QF/render.h" #include "QF/va.h" -#include "QF/plugin/vid_render.h" - -#include "QF/Vulkan/qf_vid.h" //FIXME header issues #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" @@ -52,7 +49,6 @@ #include "QF/Vulkan/staging.h" #include "QF/Vulkan/qf_particles.h" -#include "r_internal.h" #include "vid_vulkan.h" //FIXME make dynamic diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index f30d3407e..2033b9182 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -38,30 +38,16 @@ # include #endif -#include "QF/alloc.h" -#include "QF/cvar.h" -#include "QF/dstring.h" -#include "QF/hash.h" -#include "QF/image.h" -#include "QF/mathlib.h" -#include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/sys.h" #include "QF/va.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/barrier.h" -#include "QF/Vulkan/buffer.h" -#include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" -#include "r_scrap.h" #include "vid_vulkan.h" void diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 36d8de490..07a236a0c 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -31,40 +31,22 @@ #ifdef HAVE_MATH_H # include #endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif + +#include #include "QF/cexpr.h" #include "QF/cmem.h" #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" -#include "QF/mathlib.h" #include "QF/plist.h" -#include "QF/qargs.h" -#include "QF/quakefs.h" -#include "QF/sys.h" #include "QF/va.h" -#include "QF/simd/vec4f.h" #include "QF/scene/entity.h" -#include "QF/Vulkan/qf_matrices.h" -#include "QF/Vulkan/qf_vid.h" -#include "QF/Vulkan/barrier.h" -#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/debug.h" -#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" -#include "QF/Vulkan/command.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/image.h" -#include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/renderpass.h" -#include "QF/Vulkan/shader.h" #include "QF/Vulkan/staging.h" #include "QF/Vulkan/swapchain.h" @@ -74,13 +56,12 @@ #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_main.h" +#include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_vid.h" -#include "compat.h" -#include "d_iface.h" #include "r_internal.h" #include "vid_vulkan.h" -#include "util.h" #include "vkparse.h" #include "libs/video/renderer/vulkan/vkparse.hinc" From d1d1cc4362729e41670edf3939ce956a2f50b7f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 May 2022 23:41:12 +0900 Subject: [PATCH 2788/3664] [qwaq] Generate a palette and colormap The palette is a modified version of the default VGA colormap as explained by Noah Johnson (https://github.com/canidlogic/vgapal) and the generation code is heavily influenced by his code. However, I've reversed the HSV groups so I could have the pure bright colors in the fullbright range and added a few colors in the 248-255 range (mostly greens and ambers meant to be close to the old phosphor monitors). The colormap is generated by laying the colors from the palette across the middle of the map (rows 31 and 32) then linearly interpolating from 0 to the color, and the color to 2x the color (clamped) and then converting back to a palette. Mr Fixit actually looks ok still in the software renderer (unaffected in the others) though quakeguy is a hoot in all the renderers :). --- ruamoko/qwaq/builtins/graphics.c | 169 +++++++++++++++++++++++++++++-- 1 file changed, 161 insertions(+), 8 deletions(-) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index c3a088b99..ee9fb8025 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -42,6 +42,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/cbuf.h" #include "QF/draw.h" +#include "QF/image.h" #include "QF/input.h" #include "QF/progs.h" #include "QF/quakefs.h" @@ -51,6 +52,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/sound.h" #include "QF/input/event.h" +#include "QF/math/bitop.h" #include "QF/plugin/console.h" @@ -147,11 +149,166 @@ BI_shutdown (void *data) { } +static byte default_palette[256][3]; + +static byte * +write_raw_rgb (byte *dst, byte r, byte g, byte b) +{ + *dst++ = r; + *dst++ = g; + *dst++ = b; + return dst; +} + +static byte * +write_rgb (byte *dst, byte r, byte g, byte b) +{ +#define shift(x) (((x) << 2) | (((x) & 0x3f) >> 4)) + *dst++ = shift(r); + *dst++ = shift(g); + *dst++ = shift(b); + return dst; +#undef shift +} + +static byte * +write_grey (byte *dst, byte grey) +{ + return write_rgb (dst, grey, grey, grey); +} + +static byte * +genererate_irgb (byte *dst, byte lo, byte melo, byte mehi, byte hi) +{ + for (int i = 0; i < 16; i++) { + byte l = i & 8 ? melo : lo; + byte h = i & 8 ? hi : mehi; + byte r = i & 4 ? h : l; + byte g = i & 2 ? h : l; + byte b = i & 1 ? h : l; + if (i == 6) { // make dim yellow brown + g = melo; + } + dst = write_rgb (dst, r, g, b); + } + return dst; +} + +static byte * +write_run (byte *dst, byte *hue, byte ch, const byte *levels) +{ + byte rgb[3] = { + *hue & 4 ? levels[4] : levels[0], + *hue & 2 ? levels[4] : levels[0], + *hue & 1 ? levels[4] : levels[0], + }; + byte chan = 2 - BITOP_LOG2 (ch); + int ind = *hue & ch ? 4 : 0; + int dir = *hue & ch ? -1 : 1; + + for (int i = 0; i < 4; i++, ind += dir) { + rgb[chan] = levels[ind]; + dst = write_rgb (dst, rgb[0], rgb[1], rgb[2]); + } + + *hue ^= ch; + return dst; +} + +static byte * +write_cycle (byte *dst, byte lo, byte melo, byte me, byte mehi, byte hi) +{ + const byte levels[] = { lo, melo, me, mehi, hi }; + byte hue = 1; + dst = write_run (dst, &hue, 4, levels); + dst = write_run (dst, &hue, 1, levels); + dst = write_run (dst, &hue, 2, levels); + + dst = write_run (dst, &hue, 4, levels); + dst = write_run (dst, &hue, 1, levels); + dst = write_run (dst, &hue, 2, levels); + return dst; +} + +static void +generate_palette (void) +{ + const byte grey[] = { + 0, 5, 8, 11, 14, 17, 20, 24, + 28, 32, 36, 40, 45, 50, 56, 63, + }; + byte *dst = default_palette[0]; + + dst = genererate_irgb (dst, 0, 21, 42, 63); + + for (int i = 0; i < 16; i++) { + dst = write_grey (dst, grey[i]); + } + + dst = write_cycle (dst, 11, 12, 13, 15, 16); + dst = write_cycle (dst, 8, 10, 12, 14, 16); + dst = write_cycle (dst, 0, 4, 8, 12, 16); + + dst = write_cycle (dst, 20, 22, 24, 26, 28); + dst = write_cycle (dst, 14, 17, 21, 24, 28); + dst = write_cycle (dst, 0, 7, 14, 21, 28); + + dst = write_cycle (dst, 45, 49, 54, 58, 63); + dst = write_cycle (dst, 31, 39, 47, 55, 63); + dst = write_cycle (dst, 0, 16, 31, 47, 63); + + // std is black, but want vis trans and some phosphors + dst = write_raw_rgb (dst, 40, 40, 40); + dst = write_raw_rgb (dst, 40, 127, 40); + dst = write_raw_rgb (dst, 51, 255, 51); + dst = write_raw_rgb (dst, 102, 255, 102); + dst = write_raw_rgb (dst, 127, 102, 0); + dst = write_raw_rgb (dst, 255, 176, 0); + dst = write_raw_rgb (dst, 255, 204, 0); + + dst = write_raw_rgb (dst, 176, 160, 176); +} + +static byte default_colormap[64 * 256 + 1] = { [64 * 256] = 32 }; + +static void +generate_colormap (void) +{ + byte colors[64][256][3]; + tex_t tex = { + .width = 256, + .height = 64, + .format = tex_rgb, + .data = colors[0][0], + }; + + // baseline colors + for (int i = 0; i < 256; i++) { + VectorCopy (default_palette[i], colors[31][i]); + VectorCopy (default_palette[i], colors[32][i]); + } + for (int i = 0; i < 64; i++) { + // main colors + if (i < 31 || i > 32) { + float scale = i < 32 ? 2 - i / 31.0 : 1 - (i - 32) / 31.0; + for (int j = 0; j < 224; j++) { + for (int k = 0; k < 3; k++) { + colors[i][j][k] = bound (0, scale * colors[31][j][k], 255); + } + } + } + // fullbrights + memcpy (colors[i][224], colors[31][224], 32 * 3); + } + tex_t *cmap = ConvertImage (&tex, default_palette[0]); + memcpy (default_colormap, cmap->data, sizeof (default_colormap)); + free (cmap); +} + void BI_Graphics_Init (progs_t *pr) { qwaq_thread_t *thread = PR_Resources_Find (pr, "qwaq_thread"); - byte *basepal, *colormap; PR_RegisterBuiltins (pr, builtins, 0); @@ -166,15 +323,11 @@ BI_Graphics_Init (progs_t *pr) Mod_Init_Cvars (); S_Init_Cvars (); - basepal = (byte *) QFS_LoadHunkFile (QFS_FOpenFile ("gfx/palette.lmp")); - if (!basepal) - Sys_Error ("Couldn't load gfx/palette.lmp"); - colormap = (byte *) QFS_LoadHunkFile (QFS_FOpenFile ("gfx/colormap.lmp")); - if (!colormap) - Sys_Error ("Couldn't load gfx/colormap.lmp"); + generate_palette (); + generate_colormap (); W_LoadWadFile ("gfx.wad"); - VID_Init (basepal, colormap); + VID_Init (default_palette[0], default_colormap); IN_Init (); Mod_Init (); R_Init (); From 2ebefd7850976ee9fd5f90de8d4630cb0be64538 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 8 May 2022 23:55:57 +0900 Subject: [PATCH 2789/3664] [wad] Return 0 if no wad file is loaded This allows QF to load without a wad file as it will use the internal character definition. --- libs/util/wad.c | 3 +++ ruamoko/qwaq/builtins/graphics.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/util/wad.c b/libs/util/wad.c index ed0749594..017e48605 100644 --- a/libs/util/wad.c +++ b/libs/util/wad.c @@ -127,6 +127,9 @@ W_GetLumpName (const char *name) { lumpinfo_t *lump; + if (!wad_base) { + return 0; + } lump = W_GetLumpinfo (name); return (void *) (wad_base + lump->filepos); diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index ee9fb8025..709f05b4f 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -326,7 +326,6 @@ BI_Graphics_Init (progs_t *pr) generate_palette (); generate_colormap (); - W_LoadWadFile ("gfx.wad"); VID_Init (default_palette[0], default_colormap); IN_Init (); Mod_Init (); From be7a7d8becf19c3615d9177748ffee6f3559f844 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 May 2022 16:30:05 +0900 Subject: [PATCH 2790/3664] [renderer] Fix the other renderers for qwaq not loading gfx.wad The whole draw system needs an overhaul :/ --- libs/video/renderer/gl/gl_draw.c | 19 +++++++++++++------ libs/video/renderer/glsl/glsl_draw.c | 18 +++++++++++++----- libs/video/renderer/sw/draw.c | 17 +++++++++++++---- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index f131fa0d7..b0d81e9d1 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -171,7 +171,7 @@ qpic_t * gl_Draw_PicFromWad (const char *name) { glpic_t *gl; - qpic_t *p, *pic; + qpic_t *p = 0, *pic; tex_t *targa; pic = W_GetLumpName (name); @@ -187,7 +187,7 @@ gl_Draw_PicFromWad (const char *name) } else gl->texnum = GL_LoadTexture (name, targa->width, targa->height, targa->data, false, true, 4); - } else { + } else if (pic) { p = pic; gl = (glpic_t *) p->data; gl->texnum = GL_LoadTexture (name, p->width, p->height, p->data, @@ -365,16 +365,23 @@ gl_Draw_Init (void) true, 4); width = image->width; height = image->height; - } else { - draw_chars = W_GetLumpName ("conchars"); - for (i = 0; i < 256 * 64; i++) - if (draw_chars[i] == 0) + } else if ((draw_chars = W_GetLumpName ("conchars"))) { + for (i = 0; i < 256 * 64; i++) { + if (draw_chars[i] == 0) { draw_chars[i] = 255; // proper transparent color + } + } char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1); width = 128; height = 128; + } else { + qpic_t *charspic = Draw_Font8x8Pic (); + char_texture = GL_LoadTexture ("charset", 128, 128, charspic->data, + false, true, 1); + width = 128; + height = 128; } // initialize the character cell texture coordinates. diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 1b85edd87..bed1559e5 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -407,11 +407,19 @@ glsl_Draw_Init (void) draw_scrap = GLSL_CreateScrap (2048, GL_LUMINANCE, 0); draw_chars = W_GetLumpName ("conchars"); - for (i = 0; i < 256 * 64; i++) - if (draw_chars[i] == 0) - draw_chars[i] = 255; // proper transparent color - - conchars = pic_data ("conchars", 128, 128, draw_chars); + if (draw_chars) { + for (i = 0; i < 256 * 64; i++) { + if (draw_chars[i] == 0) { + draw_chars[i] = 255; // proper transparent color + } + } + conchars = pic_data ("conchars", 128, 128, draw_chars); + } else { + qpic_t *charspic = Draw_Font8x8Pic (); + conchars = pic_data ("conchars", charspic->width, + charspic->height, charspic->data); + free (charspic); + } pic = (qpic_t *) QFS_LoadFile (QFS_FOpenFile ("gfx/conback.lmp"), 0); if (pic) { diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index bea4c305c..ad09e6315 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -237,10 +237,16 @@ Draw_Init (void) draw_disc = W_GetLumpName ("disc"); draw_backtile = W_GetLumpName ("backtile"); - r_rectdesc.width = draw_backtile->width; - r_rectdesc.height = draw_backtile->height; - r_rectdesc.ptexbytes = draw_backtile->data; - r_rectdesc.rowbytes = draw_backtile->width; + if (!draw_chars) { + qpic_t *pic = Draw_Font8x8Pic (); + draw_chars = pic->data; // FIXME indirect hold on the memory + } + if (draw_backtile) { + r_rectdesc.width = draw_backtile->width; + r_rectdesc.height = draw_backtile->height; + r_rectdesc.ptexbytes = draw_backtile->data; + r_rectdesc.rowbytes = draw_backtile->width; + } } @@ -697,6 +703,9 @@ Draw_TileClear (int x, int y, int w, int h) byte *psrc; vrect_t vr; + if (!r_rectdesc.height) { + return; + } CLIP (x, y, w, h, (int) vid.width, (int) vid.height); vr.y = y; From 600e7ecbeaa158bc04abf7be2707b97d3b231dd1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 May 2022 17:03:14 +0900 Subject: [PATCH 2791/3664] [renderer] Resurrect r_dlightframecount This fixes dynamic light map updates for gl, glsl, and sw, but gl has problems with map submodels not being dynamically lit. --- include/r_local.h | 3 --- libs/video/renderer/r_light.c | 10 +++++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/r_local.h b/include/r_local.h index 4ea9d6795..33ef06469 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -292,7 +292,6 @@ extern int r_maxsurfsseen, r_maxedgesseen; extern qboolean r_dowarpold, r_viewchanged; extern int r_clipflags; -extern int r_dlightframecount; extern struct entqueue_s *r_ent_queue; struct dlight_s; @@ -311,8 +310,6 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1); void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip); void R_RecursiveMarkLights (mod_brush_t *brush, const vec3_t lightorigin, struct dlight_s *light, int bit, mnode_t *node); -void R_MarkLights (const vec3_t lightorigin, struct dlight_s *light, int bit, - model_t *model); void R_LoadSkys (const char *); //void Vulkan_R_LoadSkys (const char *, struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 654748dfb..4949ad3e4 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -50,6 +50,7 @@ dlight_t *r_dlights; vec3_t ambientcolor; unsigned int r_maxdlights; +static int r_dlightframecount; void R_FindNearLights (vec4f_t pos, int count, dlight_t **lights) @@ -179,9 +180,9 @@ real_mark_surfaces (float dist, msurface_t *surf, const vec3_t lightorigin, if (is * is + it * it > dist2) return; - if (surf->dlightframe != r_framecount) { + if (surf->dlightframe != r_dlightframecount) { memset (surf->dlightbits, 0, sizeof (surf->dlightbits)); - surf->dlightframe = r_framecount; + surf->dlightframe = r_dlightframecount; } ind = lightnum / 32; bit = 1 << (lightnum % 32); @@ -260,7 +261,7 @@ loc0: } -void +static void R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, model_t *model) { @@ -321,6 +322,9 @@ R_PushDlights (const vec3_t entorigin) dlight_t *l; vec3_t lightorigin; + // because the count hasn't advanced yet for this frame + r_dlightframecount = r_framecount + 1; + if (!r_dlight_lightmap) return; From 8ce463cbed172307c4c40929d4d55893e3d2489e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 May 2022 17:04:57 +0900 Subject: [PATCH 2792/3664] [gl] Call gl_R_CalcLightmaps after sub-model brushes have been queued This fixes the sub-models not being dynamically lit. --- libs/video/renderer/gl/gl_rsurf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index a796c1462..4dc671354 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -734,8 +734,6 @@ gl_R_DrawWorld (void) R_VisitWorldNodes (&bctx); - gl_R_CalcLightmaps (); - gl_R_DrawSkyChain (sky_chain); if (r_drawentities) { @@ -745,6 +743,8 @@ gl_R_DrawWorld (void) } } + gl_R_CalcLightmaps (); + if (!Fog_GetDensity () || (gl_fb_bmodels && gl_mtex_fullbright) || gl_mtex_active_tmus > 1) { From 0f7e6734f7a825ed9faea4196f63d337bd6b4f90 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 May 2022 14:30:48 +0900 Subject: [PATCH 2793/3664] [model] Make firstmarksurface an int instead of pointer While it takes one extra step to grab the marksurface pointer, R_MarkLeaves and R_MarkLights (the two actual users) seem to be either the same speed or fractionally faster (by a few microseconds). I imagine the loss gone to the extra fetch is made up for by better bandwidth while traversing the leafs array (mleaf_t now fits in a single cache line, so leafs are cache-aligned since hunk allocations are aligned). --- include/QF/model.h | 2 +- libs/models/brush/model_brush.c | 19 +++++++++++++------ libs/video/renderer/r_bsp.c | 2 +- libs/video/renderer/r_light.c | 3 ++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 2489dfb88..3ec574062 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -199,7 +199,7 @@ typedef struct mleaf_s { byte *compressed_vis; efrag_t *efrags; - msurface_t **firstmarksurface; + int firstmarksurface; int nummarksurfaces; int key; // BSP sequence number for leaf's contents byte ambient_sound_level[NUM_AMBIENTS]; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index ee307da3d..a13ed16ba 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -683,8 +683,9 @@ Mod_SetLeafFlags (mod_brush_t *brush) for (unsigned i = 0; i < brush->modleafs; i++) { int flags = 0; mleaf_t *leaf = &brush->leafs[i]; + msurface_t **msurf = brush->marksurfaces + leaf->firstmarksurface; for (int j = 0; j < leaf->nummarksurfaces; j++) { - msurface_t *surf = leaf->firstmarksurface[j]; + msurface_t *surf = *msurf++; flags |= surf->flags; } brush->leaf_flags[i] = flags; @@ -780,7 +781,7 @@ Mod_LoadLeafs (model_t *mod, bsp_t *bsp) p = in->contents; out->contents = p; - out->firstmarksurface = brush->marksurfaces + in->firstmarksurface; + out->firstmarksurface = in->firstmarksurface; out->nummarksurfaces = in->nummarksurfaces; p = in->visofs; @@ -795,12 +796,18 @@ Mod_LoadLeafs (model_t *mod, bsp_t *bsp) // gl underwater warp if (out->contents != CONTENTS_EMPTY) { - for (j = 0; j < out->nummarksurfaces; j++) - out->firstmarksurface[j]->flags |= SURF_UNDERWATER; + msurface_t **msurf = brush->marksurfaces + out->firstmarksurface; + for (j = 0; j < out->nummarksurfaces; j++) { + msurface_t *surf = *msurf++; + surf->flags |= SURF_UNDERWATER; + } } if (isnotmap) { - for (j = 0; j < out->nummarksurfaces; j++) - out->firstmarksurface[j]->flags |= SURF_DONTWARP; + msurface_t **msurf = brush->marksurfaces + out->firstmarksurface; + for (j = 0; j < out->nummarksurfaces; j++) { + msurface_t *surf = *msurf++; + surf->flags |= SURF_DONTWARP; + } } } } diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 2976bda16..f534d4b1b 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -79,7 +79,7 @@ R_MarkLeaves (mleaf_t *viewleaf) if (set_is_member (vis, i)) { leaf = &brush->leafs[i + 1]; if ((c = leaf->nummarksurfaces)) { - mark = leaf->firstmarksurface; + mark = brush->marksurfaces + leaf->firstmarksurface; do { (*mark)->visframe = r_visframecount; mark++; diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 4949ad3e4..5c805fb54 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -304,8 +304,9 @@ R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, continue; if (R_CullBox (r_refdef.frustum, leaf->mins, leaf->maxs)) continue; + msurface_t **msurf = brush->marksurfaces + leaf->firstmarksurface; for (m = 0; m < leaf->nummarksurfaces; m++) { - msurface_t *surf = leaf->firstmarksurface[m]; + msurface_t *surf = *msurf++; if (surf->visframe != r_visframecount) continue; mark_surfaces (surf, lightorigin, light, lightnum); From 7ed452027c50b6a52bc5679a14bc8bcc96d6fe2d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 May 2022 00:16:13 +0900 Subject: [PATCH 2794/3664] [model] Rearrange msurface_t for better efficiency It's down to 128 bytes from 184, which fits nicely in two cache lines. This made a nice difference to glsl, unknown to vulkan (it crashed after about 31/51 timedemo loops), and was a was for sw and gl. --- include/QF/model.h | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 3ec574062..1ba6b0bc2 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -139,36 +139,47 @@ typedef struct glpoly_s { typedef struct msurface_s { int visframe; // should be drawn when node is crossed - plane_t *plane; int flags; + plane_t *plane; int firstedge; // look up in model->surfedges[], negative numbers int numedges; // are backwards edges - struct surfcache_s *cachespots[MIPLEVELS]; + union { + // sw-only + struct surfcache_s *cachespots[MIPLEVELS]; + // gl/glsl/vulkan + struct { + glpoly_t *polys; // multiple if warped + instsurf_t *instsurf;///< null if not part of world model/sub-model + union { + struct { + struct subpic_s *lightpic;///< light map texture ref (glsl) + byte *base; + }; + struct { + int light_s; + int light_t; + int lightmaptexturenum; + }; + }; + }; + }; + mtexinfo_t *texinfo; short texturemins[2]; unsigned short extents[2]; - int light_s, light_t; // gl lightmap coordinates - - glpoly_t *polys; // multiple if warped - instsurf_t *instsurf; ///< null if not part of world model/sub-model - - mtexinfo_t *texinfo; - int model_index; ///< < 0: instance, 0 main, > 0: sub - byte *base; - // lighting info - struct subpic_s *lightpic; ///< light map texture ref (glsl) + byte *samples; // [numstyles*surfsize] int dlightframe; uint32_t dlightbits[(MAX_DLIGHTS + 31) >> 5]; - int lightmaptexturenum; byte styles[MAXLIGHTMAPS]; int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap qboolean cached_dlight; // true if dynamic light in cache - byte *samples; // [numstyles*surfsize] + + int model_index; ///< < 0: instance, 0 main, > 0: sub } msurface_t; typedef struct mnode_s { From 1e65ec22f9918a77f353fc5fe1e5ac796ef8fa49 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 May 2022 00:27:55 +0900 Subject: [PATCH 2795/3664] [gl] Use a scrap for lightmaps This gives a rather significant speed boost to timedemo demo1: from about 2300-2360fps up to 2520-2600fps, at least when using multi-texture. Since it was necessary for testing the scrap, gl got the ability to set the console background texture, too. --- include/QF/GL/qf_funcs_list.h | 1 + include/QF/GL/qf_lightmap.h | 5 +- include/QF/GL/qf_textures.h | 17 +- include/QF/model.h | 13 +- libs/video/renderer/gl/gl_draw.c | 17 +- libs/video/renderer/gl/gl_lightmap.c | 275 +++++++++---------------- libs/video/renderer/gl/gl_rsurf.c | 54 ++--- libs/video/renderer/gl/gl_textures.c | 265 ++++++++++++++++++++++++ libs/video/renderer/gl/vid_common_gl.c | 3 + 9 files changed, 418 insertions(+), 232 deletions(-) diff --git a/include/QF/GL/qf_funcs_list.h b/include/QF/GL/qf_funcs_list.h index d3bfe8063..3550c6f26 100644 --- a/include/QF/GL/qf_funcs_list.h +++ b/include/QF/GL/qf_funcs_list.h @@ -154,6 +154,7 @@ QFGL_NEED (void, glFogfv, (GLenum pname, const GLfloat * params)) QFGL_NEED (void, glFogi, (GLenum pname, GLint param)) QFGL_DONT_NEED (void, glFogiv, (GLenum pname, const GLint * params)) QFGL_NEED (void, glFrontFace, (GLenum mode)) +QFGL_NEED (void, glGenerateMipmap, (GLenum target)) QFGL_NEED (void, glFrustum, (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val)) QFGL_NEED (GLuint, glGenLists, (GLsizei range)) QFGL_NEED (void, glGenTextures, (GLsizei n, GLuint * textures)) diff --git a/include/QF/GL/qf_lightmap.h b/include/QF/GL/qf_lightmap.h index 8518b93fd..c54d41d1c 100644 --- a/include/QF/GL/qf_lightmap.h +++ b/include/QF/GL/qf_lightmap.h @@ -44,7 +44,7 @@ extern model_t *gl_currentmodel; extern GLuint gl_lightmap_textures[MAX_LIGHTMAPS]; extern qboolean gl_lightmap_modified[MAX_LIGHTMAPS]; -extern instsurf_t *gl_lightmap_polys[MAX_LIGHTMAPS]; +extern instsurf_t *gl_lightmap_polys; extern glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; void gl_lightmap_init (void); @@ -54,5 +54,8 @@ void gl_R_CalcLightmaps (void); struct transform_s; extern void (*gl_R_BuildLightMap) (const struct transform_s *transform, mod_brush_t *brush, msurface_t *surf); +int gl_R_LightmapTexture (void) __attribute__((pure)); +void gl_R_FlushLightmaps (void); + #endif // __QF_GL_lightmap_h diff --git a/include/QF/GL/qf_textures.h b/include/QF/GL/qf_textures.h index 9a905b649..7c8b45f53 100644 --- a/include/QF/GL/qf_textures.h +++ b/include/QF/GL/qf_textures.h @@ -48,7 +48,22 @@ int GL_LoadTexture (const char *identifier, int width, int height, const byte *d int GL_FindTexture (const char *identifier); void GL_TextureMode_f (void); - +void GL_ReleaseTexture (int tex); void GDT_Init (void); +void GL_TextureInit (void); + +typedef struct scrap_s scrap_t; + +scrap_t *GL_CreateScrap (int size, int format, int linear); +void GL_DestroyScrap (scrap_t *scrap); +void GL_ScrapClear (scrap_t *scrap); +int GL_ScrapTexture (scrap_t *scrap) __attribute__((pure)); +//XXX slow! +struct subpic_s *GL_ScrapSubpic (scrap_t *scrap, int width, int height); +//XXX slow! +void GL_SubpicDelete (struct subpic_s *subpic); +void GL_SubpicUpdate (struct subpic_s *subpic, byte *data, int batch); +void GL_ScrapFlush (scrap_t *scrap); + #endif // __gl_textures_h diff --git a/include/QF/model.h b/include/QF/model.h index 1ba6b0bc2..308175a5e 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -152,17 +152,8 @@ typedef struct msurface_s { struct { glpoly_t *polys; // multiple if warped instsurf_t *instsurf;///< null if not part of world model/sub-model - union { - struct { - struct subpic_s *lightpic;///< light map texture ref (glsl) - byte *base; - }; - struct { - int light_s; - int light_t; - int lightmaptexturenum; - }; - }; + struct subpic_s *lightpic;///< light map texture ref (glsl) + byte *base; }; }; diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index b0d81e9d1..8cfb4dd56 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -85,6 +85,15 @@ static cc_cell_t char_cells[256]; static GLuint translate_texture; static int char_texture; static int cs_texture; // crosshair texturea +static int gl_conback_texnum; +static cvar_t gl_conback_texnum_cvar = { + .name = "gl_conback_texnum", + .description = + "bind conback to this texture for debugging", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &gl_conback_texnum }, +}; static byte color_0_8[4] = { 204, 204, 204, 255 }; @@ -418,6 +427,8 @@ gl_Draw_Init (void) draw_backtile = gl_Draw_PicFromWad ("backtile"); Draw_InitText (); + + Cvar_Register (&gl_conback_texnum_cvar, 0, 0); } static inline void @@ -817,7 +828,11 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) qfglColor4ubv (color_0_8); // draw the console texture - qfglBindTexture (GL_TEXTURE_2D, gl->texnum); + if (gl_conback_texnum) { + qfglBindTexture (GL_TEXTURE_2D, gl_conback_texnum); + } else { + qfglBindTexture (GL_TEXTURE_2D, gl->texnum); + } qfglBegin (GL_QUADS); qfglTexCoord2f (0, 0 + ofs); qfglVertex2f (0, 0); diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 068f0ce00..4fdbe2840 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -57,6 +57,7 @@ #include "compat.h" #include "r_internal.h" +static scrap_t *light_scrap; static int dlightdivtable[8192]; static int gl_internalformat; // 1 or 3 static int lightmap_bytes; // 1, 3, or 4 @@ -66,11 +67,12 @@ GLuint gl_lightmap_textures[MAX_LIGHTMAPS]; // LordHavoc: changed to be allocated at runtime (typically lower memory usage) static byte *lightmaps[MAX_LIGHTMAPS]; -static unsigned int blocklights[34 * 34 * 3]; //FIXME make dynamic +static unsigned *blocklights; +static int bl_extents[2]; static int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH]; qboolean gl_lightmap_modified[MAX_LIGHTMAPS]; -instsurf_t *gl_lightmap_polys[MAX_LIGHTMAPS]; +instsurf_t *gl_lightmap_polys; glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; static int lmshift = 7; @@ -238,7 +240,7 @@ R_BuildLightMap_1 (const transform_t *transform, mod_brush_t *brush, msurface_t *surf) { byte *dest; - int maps, size, stride, smax, tmax, i, j; + int maps, size, smax, tmax, i; unsigned int scale; unsigned int *bl; @@ -279,19 +281,14 @@ R_BuildLightMap_1 (const transform_t *transform, mod_brush_t *brush, store: // bound and shift // Also, invert because we're using a diff blendfunc now - - stride = (BLOCK_WIDTH - smax) * lightmap_bytes; bl = blocklights; - - dest = lightmaps[surf->lightmaptexturenum] - + (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes; - - for (i = 0; i < tmax; i++, dest += stride) { - for (j = smax; j; j--) { - *dest++ = min (*bl >> lmshift, 255); - bl++; - } + dest = (byte *) blocklights; + for (i = 0; i < tmax * smax; i++) { + *dest++ = min (*bl >> lmshift, 255); + bl++; } + + GL_SubpicUpdate (surf->lightpic, (byte *) blocklights, 1); } static void @@ -299,7 +296,7 @@ R_BuildLightMap_3 (const transform_t *transform, mod_brush_t *brush, msurface_t *surf) { byte *dest; - int maps, size, stride, smax, tmax, i, j; + int maps, size, smax, tmax, i; unsigned int scale; unsigned int *bl; @@ -342,22 +339,18 @@ R_BuildLightMap_3 (const transform_t *transform, mod_brush_t *brush, store: // bound and shift // and invert too - stride = (BLOCK_WIDTH - smax) * lightmap_bytes; bl = blocklights; - - dest = lightmaps[surf->lightmaptexturenum] - + (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes; - - for (i = 0; i < tmax; i++, dest += stride) { - for (j = 0; j < smax; j++) { - *dest++ = min (*bl >> lmshift, 255); - bl++; - *dest++ = min (*bl >> lmshift, 255); - bl++; - *dest++ = min (*bl >> lmshift, 255); - bl++; - } + dest = (byte *) blocklights; + for (i = 0; i < tmax * smax; i++) { + *dest++ = min (*bl >> lmshift, 255); + bl++; + *dest++ = min (*bl >> lmshift, 255); + bl++; + *dest++ = min (*bl >> lmshift, 255); + bl++; } + + GL_SubpicUpdate (surf->lightpic, (byte *) blocklights, 1); } static void @@ -365,7 +358,7 @@ R_BuildLightMap_4 (const transform_t *transform, mod_brush_t *brush, msurface_t *surf) { byte *dest; - int maps, size, smax, tmax, i, j, stride; + int maps, size, smax, tmax, i; unsigned int scale; unsigned int *bl; @@ -408,23 +401,19 @@ R_BuildLightMap_4 (const transform_t *transform, mod_brush_t *brush, store: // bound and shift // and invert too - stride = (BLOCK_WIDTH - smax) * lightmap_bytes; bl = blocklights; - - dest = lightmaps[surf->lightmaptexturenum] - + (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes; - - for (i = 0; i < tmax; i++, dest += stride) { - for (j = 0; j < smax; j++) { - *dest++ = min (*bl >> lmshift, 255); - bl++; - *dest++ = min (*bl >> lmshift, 255); - bl++; - *dest++ = min (*bl >> lmshift, 255); - bl++; - *dest++ = 255; - } + dest = (byte *) blocklights; + for (i = 0; i < tmax * smax; i++) { + *dest++ = min (*bl >> lmshift, 255); + bl++; + *dest++ = min (*bl >> lmshift, 255); + bl++; + *dest++ = min (*bl >> lmshift, 255); + bl++; + *dest++ = 255; } + + GL_SubpicUpdate (surf->lightpic, (byte *) blocklights, 1); } // BRUSH MODELS =============================================================== @@ -449,75 +438,33 @@ do_subimage_2 (int i) gl_lightmap_format, GL_UNSIGNED_BYTE, block); } -static void -GL_UploadLightmap (int i) -{ - switch (gl_lightmap_subimage) { - case 2: - do_subimage_2 (i); - break; - case 1: - qfglTexSubImage2D (GL_TEXTURE_2D, 0, 0, gl_lightmap_rectchange[i].t, - BLOCK_WIDTH, gl_lightmap_rectchange[i].h, - gl_lightmap_format, GL_UNSIGNED_BYTE, - lightmaps[i] + (gl_lightmap_rectchange[i].t * - BLOCK_WIDTH) * lightmap_bytes); - break; - default: - case 0: - qfglTexImage2D (GL_TEXTURE_2D, 0, gl_internalformat, BLOCK_WIDTH, - BLOCK_HEIGHT, 0, gl_lightmap_format, GL_UNSIGNED_BYTE, - lightmaps[i]); - break; - } -} - -void -gl_R_CalcLightmaps (void) -{ - int i; - - for (i = 0; i < MAX_LIGHTMAPS; i++) { - if (!gl_lightmap_polys[i]) - continue; - if (gl_lightmap_modified[i]) { - qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures[i]); - GL_UploadLightmap (i); - gl_lightmap_modified[i] = false; - } - } -} - void gl_R_BlendLightmaps (void) { float *v; - int i, j; instsurf_t *sc; glpoly_t *p; qfglDepthMask (GL_FALSE); // don't bother writing Z qfglBlendFunc (lm_src_blend, lm_dest_blend); - for (i = 0; i < MAX_LIGHTMAPS; i++) { - for (sc = gl_lightmap_polys[i]; sc; sc = sc->lm_chain) { - qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures[i]); - if (sc->transform) { - qfglPushMatrix (); - qfglLoadMatrixf (sc->transform); - } - for (p = sc->surface->polys; p; p = p->next) { - qfglBegin (GL_POLYGON); - v = p->verts[0]; - for (j = 0; j < p->numverts; j++, v += VERTEXSIZE) { - qfglTexCoord2fv (&v[5]); - qfglVertex3fv (v); - } - qfglEnd (); - } - if (sc->transform) - qfglPopMatrix (); + qfglBindTexture (GL_TEXTURE_2D, gl_R_LightmapTexture ()); + for (sc = gl_lightmap_polys; sc; sc = sc->lm_chain) { + if (sc->transform) { + qfglPushMatrix (); + qfglLoadMatrixf (sc->transform); } + for (p = sc->surface->polys; p; p = p->next) { + qfglBegin (GL_POLYGON); + v = p->verts[0]; + for (int j = 0; j < p->numverts; j++, v += VERTEXSIZE) { + qfglTexCoord2fv (&v[5]); + qfglVertex3fv (v); + } + qfglEnd (); + } + if (sc->transform) + qfglPopMatrix (); } // Return to normal blending --KB @@ -528,7 +475,6 @@ gl_R_BlendLightmaps (void) void gl_overbright_f (void *data, const cvar_t *cvar) { - int num; mod_brush_t *brush; if (!cvar) @@ -579,61 +525,12 @@ gl_overbright_f (void *data, const cvar_t *cvar) if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY)) continue; - num = surf->lightmaptexturenum; - gl_lightmap_modified[num] = true; - gl_lightmap_rectchange[num].l = 0; - gl_lightmap_rectchange[num].t = 0; - gl_lightmap_rectchange[num].w = BLOCK_WIDTH; - gl_lightmap_rectchange[num].h = BLOCK_HEIGHT; - gl_R_BuildLightMap (0, brush, surf); } } // LIGHTMAP ALLOCATION ======================================================== -// returns a texture number and the position inside it -static int -AllocBlock (int w, int h, int *x, int *y) -{ - int best, best2, texnum, i, j; - - for (texnum = 0; texnum < MAX_LIGHTMAPS; texnum++) { - best = BLOCK_HEIGHT; - - for (i = 0; i < BLOCK_WIDTH - w; i++) { - best2 = 0; - - for (j = 0; j < w; j++) { - if (allocated[texnum][i + j] >= best) - break; - if (allocated[texnum][i + j] > best2) - best2 = allocated[texnum][i + j]; - } - if (j == w) { - // this is a valid spot - *x = i; - *y = best = best2; - } - } - - if (best + h > BLOCK_HEIGHT) - continue; - - // LordHavoc: allocate lightmaps only as needed - if (!lightmaps[texnum]) - lightmaps[texnum] = calloc (BLOCK_WIDTH * BLOCK_HEIGHT, - lightmap_bytes); - for (i = 0; i < w; i++) - allocated[texnum][*x + i] = best + h; - - return texnum; - } - - Sys_Error ("AllocBlock: full"); - return 0; -} - static void GL_CreateSurfaceLightmap (mod_brush_t *brush, msurface_t *surf) { @@ -645,9 +542,16 @@ GL_CreateSurfaceLightmap (mod_brush_t *brush, msurface_t *surf) smax = (surf->extents[0] >> 4) + 1; tmax = (surf->extents[1] >> 4) + 1; - surf->lightmaptexturenum = - AllocBlock (smax, tmax, &surf->light_s, &surf->light_t); - gl_R_BuildLightMap (0, brush, surf); + surf->lightpic = GL_ScrapSubpic (light_scrap, smax, tmax); + if (!surf->lightpic) { + Sys_Error ("FIXME taniwha is being lazy"); + } + if (smax > bl_extents[0]) { + bl_extents[0] = smax; + } + if (tmax > bl_extents[1]) { + bl_extents[1] = tmax; + } } /* @@ -665,10 +569,6 @@ GL_BuildLightmaps (model_t **models, int num_models) r_framecount = 1; // no dlightcache - if (!gl_lightmap_textures[0]) { - qfglGenTextures (MAX_LIGHTMAPS, gl_lightmap_textures); - } - switch (r_lightmap_components) { case 1: gl_internalformat = 1; @@ -697,6 +597,13 @@ GL_BuildLightmaps (model_t **models, int num_models) break; } + if (!light_scrap) { + light_scrap = GL_CreateScrap (2048, gl_lightmap_format, 1); + } else { + GL_ScrapClear (light_scrap); + } + + bl_extents[1] = bl_extents[0] = 0; for (int j = 1; j < num_models; j++) { m = models[j]; if (!m) @@ -716,23 +623,37 @@ GL_BuildLightmaps (model_t **models, int num_models) } } + int size = bl_extents[0] * bl_extents[1] * 3; // * 3 for rgb support + blocklights = realloc (blocklights, size * sizeof (blocklights[0])); + // upload all lightmaps that were filled - for (int i = 0; i < MAX_LIGHTMAPS; i++) { - if (!allocated[i][0]) - break; // no more used - gl_lightmap_modified[i] = false; - gl_lightmap_rectchange[i].l = BLOCK_WIDTH; - gl_lightmap_rectchange[i].t = BLOCK_HEIGHT; - gl_lightmap_rectchange[i].w = 0; - gl_lightmap_rectchange[i].h = 0; - qfglBindTexture (GL_TEXTURE_2D, gl_lightmap_textures[i]); - qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - if (gl_Anisotropy) - qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - gl_aniso); - qfglTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes, BLOCK_WIDTH, - BLOCK_HEIGHT, 0, gl_lightmap_format, - GL_UNSIGNED_BYTE, lightmaps[i]); + for (int j = 1; j < num_models; j++) { + m = models[j]; + if (!m) + break; + if (m->path[0] == '*' || m->type != mod_brush) { + // sub model surfaces are processed as part of the main model + continue; + } + brush = &m->brush; + // non-bsp models don't have surfaces. + for (unsigned i = 0; i < brush->numsurfaces; i++) { + msurface_t *surf = brush->surfaces + i; + if (surf->lightpic) { + gl_R_BuildLightMap (0, brush, surf); + } + } } } + +int +gl_R_LightmapTexture (void) +{ + return GL_ScrapTexture (light_scrap); +} + +void +gl_R_FlushLightmaps (void) +{ + GL_ScrapFlush (light_scrap); +} diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 4dc671354..309b95950 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -277,12 +277,11 @@ R_RenderBrushPoly_1 (msurface_t *surf) static inline void R_AddToLightmapChain (glbspctx_t *bctx, msurface_t *surf, instsurf_t *sc) { - int maps, smax, tmax; - glRect_t *theRect; + int maps; // add the poly to the proper lightmap chain - sc->lm_chain = gl_lightmap_polys[surf->lightmaptexturenum]; - gl_lightmap_polys[surf->lightmaptexturenum] = sc; + sc->lm_chain = gl_lightmap_polys; + gl_lightmap_polys = sc; // check for lightmap modification for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++) @@ -292,24 +291,6 @@ R_AddToLightmapChain (glbspctx_t *bctx, msurface_t *surf, instsurf_t *sc) if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { dynamic: if (r_dynamic) { - gl_lightmap_modified[surf->lightmaptexturenum] = true; - theRect = &gl_lightmap_rectchange[surf->lightmaptexturenum]; - if (surf->light_t < theRect->t) { - if (theRect->h) - theRect->h += theRect->t - surf->light_t; - theRect->t = surf->light_t; - } - if (surf->light_s < theRect->l) { - if (theRect->w) - theRect->w += theRect->l - surf->light_s; - theRect->l = surf->light_s; - } - smax = (surf->extents[0] >> 4) + 1; - tmax = (surf->extents[1] >> 4) + 1; - if ((theRect->w + theRect->l) < (surf->light_s + smax)) - theRect->w = (surf->light_s - theRect->l) + smax; - if ((theRect->h + theRect->t) < (surf->light_t + tmax)) - theRect->h = (surf->light_t - theRect->t) + tmax; gl_R_BuildLightMap (bctx->entity->transform, bctx->brush, surf); } } @@ -372,6 +353,7 @@ DrawTextureChains (int disable_blend, int do_bind) // Lightmaps qglActiveTexture (gl_mtex_enum + 1); qfglEnable (GL_TEXTURE_2D); + qfglBindTexture (GL_TEXTURE_2D, gl_R_LightmapTexture ()); // Base Texture qglActiveTexture (gl_mtex_enum + 0); @@ -388,7 +370,6 @@ DrawTextureChains (int disable_blend, int do_bind) qfglEnable (GL_TEXTURE_2D); qfglBindTexture (GL_TEXTURE_2D, tex->gl_fb_texturenum); - qglActiveTexture (gl_mtex_enum + 1); for (s = tex->tex_chain; s; s = s->tex_chain) { surf = s->surface; if (s->transform) { @@ -397,8 +378,6 @@ DrawTextureChains (int disable_blend, int do_bind) } if (s->color && do_bind) qfglColor4fv (s->color); - qfglBindTexture (GL_TEXTURE_2D, - gl_lightmap_textures[surf->lightmaptexturenum]); R_RenderBrushPoly_3 (surf); @@ -413,11 +392,8 @@ DrawTextureChains (int disable_blend, int do_bind) qglActiveTexture (gl_mtex_enum + 0); } else { - qglActiveTexture (gl_mtex_enum + 1); for (s = tex->tex_chain; s; s = s->tex_chain) { surf = s->surface; - qfglBindTexture (GL_TEXTURE_2D, - gl_lightmap_textures[surf->lightmaptexturenum]); if (s->transform) { qfglPushMatrix (); @@ -489,7 +465,7 @@ clear_texture_chains (void) tex->tex_chain_tail = &tex->tex_chain; release_instsurfs (); - memset (gl_lightmap_polys, 0, sizeof (gl_lightmap_polys)); + gl_lightmap_polys = 0; } static inline void @@ -743,7 +719,7 @@ gl_R_DrawWorld (void) } } - gl_R_CalcLightmaps (); + gl_R_FlushLightmaps (); if (!Fog_GetDensity () || (gl_fb_bmodels && gl_mtex_fullbright) @@ -859,19 +835,15 @@ GL_BuildSurfaceDisplayList (mod_brush_t *brush, msurface_t *surf) // lightmap texture coordinates s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; - s -= surf->texturemins[0]; - s += surf->light_s * 16; - s += 8; - s /= BLOCK_WIDTH * 16; - t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; + s -= surf->texturemins[0]; t -= surf->texturemins[1]; - t += surf->light_t * 16; - t += 8; - t /= BLOCK_HEIGHT * 16; - - poly->verts[i][5] = s; - poly->verts[i][6] = t; + s += surf->lightpic->rect->x * 16 + 8; + t += surf->lightpic->rect->y * 16 + 8; + s /= 16; + t /= 16; + poly->verts[i][5] = s * surf->lightpic->size; + poly->verts[i][6] = t * surf->lightpic->size; } // remove co-linear points - Ed diff --git a/libs/video/renderer/gl/gl_textures.c b/libs/video/renderer/gl/gl_textures.c index e0c7d893d..0478eed69 100644 --- a/libs/video/renderer/gl/gl_textures.c +++ b/libs/video/renderer/gl/gl_textures.c @@ -48,12 +48,28 @@ #include "QF/GL/funcs.h" #include "QF/GL/qf_textures.h" #include "QF/GL/qf_vid.h" +#include "QF/ui/vrect.h" #include "compat.h" #include "r_internal.h" +#include "r_scrap.h" #include "sbar.h" #include "vid_internal.h" +struct scrap_s { + rscrap_t rscrap; + GLuint tnum; + int format; + int bpp; + byte *data; // local copy of the texture so updates can be batched + vrect_t *batch; + subpic_t *subpics; + struct scrap_s *next; +}; + +static scrap_t *scrap_list; +static int max_tex_size; + typedef struct { GLuint texnum; char identifier[64]; @@ -625,3 +641,252 @@ SetupTexture: return glt->texnum; } + +void +GL_ReleaseTexture (int tex) +{ + GLuint tnum = tex; + qfglDeleteTextures (1, &tnum); +} + +static void +gl_scraps_f (void) +{ + scrap_t *scrap; + int area; + int size; + + if (!scrap_list) { + Sys_Printf ("No scraps\n"); + return; + } + for (scrap = scrap_list; scrap; scrap = scrap->next) { + area = R_ScrapArea (&scrap->rscrap); + // always square + size = scrap->rscrap.width; + Sys_Printf ("tnum=%u size=%d format=%04x bpp=%d free=%d%%\n", + scrap->tnum, size, scrap->format, scrap->bpp, + area * 100 / (size * size)); + if (Cmd_Argc () > 1) { + R_ScrapDump (&scrap->rscrap); + } + } +} + +void +GL_TextureInit (void) +{ + qfglGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_tex_size); + Sys_MaskPrintf (SYS_glt, "max texture size: %d\n", max_tex_size); + + Cmd_AddCommand ("gl_scraps", gl_scraps_f, "Dump GL scrap stats"); +} + +scrap_t * +GL_CreateScrap (int size, int format, int linear) +{ + int i; + int bpp; + scrap_t *scrap; + + for (i = 0; i < 16; i++) + if (size <= 1 << i) + break; + size = 1 << i; + size = min (size, max_tex_size); + switch (format) { + case GL_ALPHA: + case GL_LUMINANCE: + bpp = 1; + break; + case GL_LUMINANCE_ALPHA: + bpp = 2; + break; + case GL_RGB: + bpp = 3; + break; + case GL_RGBA: + bpp = 4; + break; + default: + Sys_Error ("GL_CreateScrap: Invalid texture format"); + } + scrap = malloc (sizeof (scrap_t)); + qfglGenTextures (1, &scrap->tnum); + R_ScrapInit (&scrap->rscrap, size, size); + scrap->format = format; + scrap->bpp = bpp; + scrap->subpics = 0; + scrap->next = scrap_list; + scrap_list = scrap; + + scrap->data = calloc (1, size * size * bpp); + scrap->batch = 0; + + qfglBindTexture (GL_TEXTURE_2D, scrap->tnum); + qfglTexImage2D (GL_TEXTURE_2D, 0, format, + size, size, 0, format, GL_UNSIGNED_BYTE, scrap->data); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (linear) { + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + qfglGenerateMipmap (GL_TEXTURE_2D); + + return scrap; +} + +void +GL_ScrapClear (scrap_t *scrap) +{ + subpic_t *sp; + while (scrap->subpics) { + sp = scrap->subpics; + scrap->subpics = (subpic_t *) sp->next; + free (sp); + } + R_ScrapClear (&scrap->rscrap); +} + +void +GL_DestroyScrap (scrap_t *scrap) +{ + scrap_t **s; + + for (s = &scrap_list; *s; s = &(*s)->next) { + if (*s == scrap) { + *s = scrap->next; + break; + } + } + GL_ScrapClear (scrap); + R_ScrapDelete (&scrap->rscrap); + GL_ReleaseTexture (scrap->tnum); + free (scrap->data); + free (scrap); +} + +int +GL_ScrapTexture (scrap_t *scrap) +{ + return scrap->tnum; +} + +subpic_t * +GL_ScrapSubpic (scrap_t *scrap, int width, int height) +{ + vrect_t *rect; + subpic_t *subpic; + + rect = R_ScrapAlloc (&scrap->rscrap, width, height); + if (!rect) { + return 0; + } + + subpic = malloc (sizeof (subpic_t)); + *((subpic_t **) &subpic->next) = scrap->subpics; + scrap->subpics = subpic; + *((scrap_t **) &subpic->scrap) = scrap; + *((vrect_t **) &subpic->rect) = rect; + *((int *) &subpic->width) = width; + *((int *) &subpic->height) = height; + *((float *) &subpic->size) = 1.0 / scrap->rscrap.width; + return subpic; +} + +void +GL_SubpicDelete (subpic_t *subpic) +{ + scrap_t *scrap = (scrap_t *) subpic->scrap; + vrect_t *rect = (vrect_t *) subpic->rect; + subpic_t **sp; + + for (sp = &scrap->subpics; *sp; sp = (subpic_t **) &(*sp)->next) + if (*sp == subpic) + break; + if (*sp != subpic) + Sys_Error ("GL_ScrapDelSubpic: broken subpic"); + *sp = (subpic_t *) subpic->next; + free (subpic); + R_ScrapFree (&scrap->rscrap, rect); +} + +void +GL_SubpicUpdate (subpic_t *subpic, byte *data, int batch) +{ + scrap_t *scrap = (scrap_t *) subpic->scrap; + vrect_t *rect = (vrect_t *) subpic->rect; + byte *dest; + int step, sbytes; + int i; + + if (batch) { + /*if (scrap->batch) { + vrect_t *r = scrap->batch; + scrap->batch = VRect_Union (r, rect); + VRect_Delete (r); + } else { + scrap->batch = VRect_New (rect->x, rect->y, + rect->width, rect->height); + }*/ + vrect_t *r = VRect_New (rect->x, rect->y, + rect->width, rect->height); + r->next = scrap->batch; + scrap->batch = r; + + step = scrap->rscrap.width * scrap->bpp; + sbytes = subpic->width * scrap->bpp; + dest = scrap->data + rect->y * step + rect->x * scrap->bpp; + for (i = 0; i < subpic->height; i++, dest += step, data += sbytes) + memcpy (dest, data, sbytes); + } else { + qfglBindTexture (GL_TEXTURE_2D, scrap->tnum); + qfglTexSubImage2D (GL_TEXTURE_2D, 0, rect->x, rect->y, + subpic->width, subpic->height, scrap->format, + GL_UNSIGNED_BYTE, data); + } +} + +void +GL_ScrapFlush (scrap_t *scrap) +{ + vrect_t *rect = scrap->batch; + int size = scrap->rscrap.width; + + if (!rect) + return; + //FIXME: it seems gl (as opposed to egl) allows row step to be specified. + //should update to not update the entire horizontal block + qfglBindTexture (GL_TEXTURE_2D, scrap->tnum); + qfglPixelStorei(GL_UNPACK_ROW_LENGTH, size); + //qfglPixelStorei(GL_UNPACK_ALIGNMENT, 1); + while (rect) { + vrect_t *next = rect->next; +#if 1 + int x = rect->x; + int y = rect->y; + int w = rect->width; + int h = rect->height; + qfglTexSubImage2D (GL_TEXTURE_2D, 0, x, y, w, h, scrap->format, + GL_UNSIGNED_BYTE, + scrap->data + (y * size + x) * scrap->bpp); +#else + for (int i = 0; i < rect->height; i++) { + int y = rect->y + i; + qfglTexSubImage2D (GL_TEXTURE_2D, 0, rect->x, y, + rect->width, 1, scrap->format, + GL_UNSIGNED_BYTE, + scrap->data + (y * size + rect->x) * scrap->bpp); + } +#endif + VRect_Delete (rect); + rect = next; + } + qfglPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + //qfglPixelStorei(GL_UNPACK_ALIGNMENT, 4); + scrap->batch = 0; +} diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index 4ff4b85fe..f723e6247 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -49,6 +49,7 @@ #include "QF/GL/extensions.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_rmain.h" +#include "QF/GL/qf_textures.h" #include "QF/GL/qf_vid.h" #include "compat.h" @@ -1031,6 +1032,8 @@ GL_Init_Common (void) GL_Common_Init_Cvars (); + GL_TextureInit (); + qfglClearColor (0, 0, 0, 0); qfglEnable (GL_TEXTURE_2D); From 86faeba31a2afe9fd30396ee8194a14ef8ef96c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 May 2022 01:39:33 +0900 Subject: [PATCH 2796/3664] [vulkan] Plug some leaking sprite descriptors I'd forgotten to free them when unloading a model, thus the segfault after about 31 timedemo runs. --- include/QF/Vulkan/qf_sprite.h | 2 ++ libs/models/sprite/vulkan_model_sprite.c | 2 ++ libs/video/renderer/vulkan/vulkan_sprite.c | 11 +++++++++++ 3 files changed, 15 insertions(+) diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index 31d95a3aa..fb080087b 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -81,6 +81,8 @@ struct qfv_renderframe_s; struct entity_s; struct mod_sprite_ctx_s; +void Vulkan_Sprint_FreeDescriptors (struct vulkan_ctx_s *ctx, + qfv_sprite_t *sprite); void Vulkan_Sprite_DescriptorSet (struct vulkan_ctx_s *ctx, qfv_sprite_t *sprite); void Vulkan_Mod_SpriteLoadFrames (struct mod_sprite_ctx_s *sprite_ctx, diff --git a/libs/models/sprite/vulkan_model_sprite.c b/libs/models/sprite/vulkan_model_sprite.c index 0eaba1534..09fecf76d 100644 --- a/libs/models/sprite/vulkan_model_sprite.c +++ b/libs/models/sprite/vulkan_model_sprite.c @@ -67,6 +67,8 @@ vulkan_sprite_clear (model_t *m, void *data) msprite_t *msprite = m->cache.data; __auto_type sprite = (qfv_sprite_t *) ((byte *) msprite + msprite->data); + Vulkan_Sprint_FreeDescriptors (ctx, sprite); + dfunc->vkDestroyBuffer (device->dev, sprite->verts, 0); dfunc->vkDestroyImageView (device->dev, sprite->view, 0); dfunc->vkDestroyImage (device->dev, sprite->image, 0); diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index cbe714797..c8ed837b0 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -271,6 +271,17 @@ Vulkan_Sprite_DescriptorSet (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); } +void +Vulkan_Sprint_FreeDescriptors (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + spritectx_t *sctx = ctx->sprite_context; + + dfunc->vkFreeDescriptorSets (device->dev, sctx->pool, 1, + &sprite->descriptors); +} + void Vulkan_Sprite_Init (vulkan_ctx_t *ctx) { From 4515b0d7f0452850d3a28974b37d76ee65542397 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 May 2022 14:14:43 +0900 Subject: [PATCH 2797/3664] [nq] Use SCR_NewScene in CL_SetState This was missed when changing CL_ClearState. Fixes segfault on respawn. --- nq/source/cl_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 0d3f0864f..d9ea23659 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -573,10 +573,10 @@ CL_SetState (cactive_t state) cl.viewstate.drift_enabled = !cls.demoplayback; Sys_MaskPrintf (SYS_net, "CL_SetState: %d -> %d\n", old_state, state); if (old_state != state) { - if (old_state == ca_active) { + if (old_state == ca_active && state != ca_disconnected) { // leaving active state S_AmbientOff (); - r_funcs->R_ClearState (); + SCR_NewScene (0); } switch (state) { case ca_disconnected: From ad8599574a2c640bc6d0dae2aa8c99954d677093 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 May 2022 14:16:23 +0900 Subject: [PATCH 2798/3664] [qw] Use SCR_NewScene instead of R_ClearState This is the same issue as in nq, but I'd entirely forgotten to do qw. I imagine similar segfaults would have occurred. --- qw/source/cl_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 668208e6c..1db3559d1 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -699,7 +699,7 @@ CL_ClearState (void) CL_Init_Entity (cl.viewstate.weapon_entity); r_data->view_model = cl.viewstate.weapon_entity; - r_funcs->R_ClearState (); + SCR_NewScene (0); SZ_Clear (&cls.netchan.message); @@ -1434,7 +1434,7 @@ CL_SetState (cactive_t state) if (cl_autorecord && cls.demorecording) CL_StopRecording (); - r_funcs->R_ClearState (); + SCR_NewScene (0); } else if (state == ca_active) { // entering active state VID_SetCaption (cls.servername->str); From 978d0306c0a041b72c77ca71ea98247fd8069646 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 17:54:23 +0900 Subject: [PATCH 2799/3664] [hash] Rename the publicly visible hashlink_t to hashctx_t I think my biggest problem with the hashlink freelist parameter was how much implementation it exposed in just the name. --- include/QF/cexpr.h | 2 +- include/QF/hash.h | 15 +++++++-------- include/QF/plist.h | 10 +++++----- include/QF/progs.h | 6 +++--- include/vid_vulkan.h | 2 +- libs/client/cl_input.c | 1 - libs/gamecode/pr_builtins.c | 5 ++--- libs/gamecode/pr_debug.c | 8 +++----- libs/gamecode/pr_load.c | 11 ++++------- libs/gamecode/pr_parse.c | 12 ++++++------ libs/gamecode/pr_resource.c | 2 +- libs/gamecode/pr_strings.c | 2 +- libs/gib/bi_gib.c | 3 +-- libs/input/in_binding.c | 2 +- libs/input/in_common.c | 2 +- libs/input/in_imt.c | 9 ++++----- libs/ruamoko/rua_cmd.c | 2 +- libs/ruamoko/rua_hash.c | 2 +- libs/ruamoko/rua_input.c | 4 ++-- libs/ruamoko/rua_obj.c | 10 ++++------ libs/ruamoko/rua_plist.c | 9 ++++----- libs/util/cexpr-vars.c | 2 +- libs/util/cvar.c | 2 +- libs/util/hash.c | 13 ++++++------- libs/util/plist.c | 12 ++++++------ libs/video/renderer/r_progs.c | 3 +-- libs/video/renderer/vulkan/vkparse.c | 12 +++++------- libs/video/renderer/vulkan/vulkan_vid_common.c | 6 +++--- nq/source/cl_main.c | 4 ++-- qw/source/cl_main.c | 4 ++-- ruamoko/qwaq/builtins/main.c | 2 +- ruamoko/qwaq/builtins/term-input.c | 2 +- ruamoko/qwaq/qwaq.h | 2 +- 33 files changed, 83 insertions(+), 100 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index b61653eef..5935e37bb 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -103,7 +103,7 @@ typedef struct exprctx_s { struct memsuper_s *memsuper; const struct plitem_s *item; struct plitem_s *messages; - struct hashlink_s **hashlinks; + struct hashctx_s **hashctx; int errors; } exprctx_t; diff --git a/include/QF/hash.h b/include/QF/hash.h index 4a85b7ef2..f846e6c95 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -37,7 +37,7 @@ ///@{ typedef struct hashtab_s hashtab_t; -typedef struct hashlink_s hashlink_t; +typedef struct hashctx_s hashctx_t; typedef int (*hash_select_t) (void *ele, void *data); typedef void (*hash_action_t) (void *ele, void *data); @@ -53,13 +53,13 @@ typedef void (*hash_action_t) (void *ele, void *data); element to be freed and the second is the user data pointer. \param ud user data pointer. set to whatever you want, it will be passed to the get key and free functions as the second parameter. - \param hlfl Address of opaque pointer used for per-thread allocation of + \param hctx Address of opaque pointer used for per-thread allocation of internal memory. If null, a local static pointer will be used, but the hash table will not be thread-safe unless all tables - created with a null \a hlfl (hashlink freelist) are used in - only the one thread. However, this applys only to updating a - hash table; hash tables that are not updated can be safely - shared between threads. + created with a null \a hctx are used in only the one thread. + However, this applys only to updating a hash table; hash + tables that are not updated can be safely shared between + threads. \return pointer to the hash table (to be passed to the other functions) or 0 on error. @@ -69,8 +69,7 @@ typedef void (*hash_action_t) (void *ele, void *data); previous ones until the later one is removed (Hash_Del). */ hashtab_t *Hash_NewTable (int tsize, const char *(*gk)(const void*,void*), - void (*f)(void*,void*), void *ud, - hashlink_t **hlfl); + void (*f)(void*,void*), void *ud, hashctx_t **hctx); /** change the hash and compare functions used by the Hash_*Element functions. the default hash function just returns the address of the element, and the diff --git a/include/QF/plist.h b/include/QF/plist.h index 72b09682b..9e68ed0bb 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -28,7 +28,7 @@ #ifndef __QF_plist_h #define __QF_plist_h -struct hashlink_s; +struct hashctx_s; /** \defgroup plist Property lists \ingroup utils @@ -127,14 +127,14 @@ typedef struct plelement_s { /** Create an in-memory representation of the contents of a property list. \param string the saved plist, as read from a file. - \param hashlinks Hashlink chain to use when creating dictionaries (see + \param hashctx Hashlink chain to use when creating dictionaries (see Hash_NewTable()). May be null. \return Returns an object equivalent to the passed-in string. \note You are responsible for freeing the returned object. */ plitem_t *PL_GetPropertyList (const char *string, - struct hashlink_s **hashlinks); + struct hashctx_s **hashctx); /** Create a property list string from the in-memory representation. @@ -308,11 +308,11 @@ plitem_t *PL_RemoveObjectAtIndex (plitem_t *array, int index); /** Create a new dictionary object. The dictionary will be empty. - \param hashlinks Hashlink chain to use when creating dictionaries (see + \param hashctx Hashlink chain to use when creating dictionaries (see Hash_NewTable()). May be null. \return the new dictionary object */ -plitem_t *PL_NewDictionary (struct hashlink_s **hashlinks); +plitem_t *PL_NewDictionary (struct hashctx_s **hashctx); /** Create a new array object. The array will be empty. diff --git a/include/QF/progs.h b/include/QF/progs.h index 2e18fa3c5..9434685cb 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -337,7 +337,7 @@ void ED_PrintNum (progs_t *pr, pr_int_t ent, const char *fieldname); // pr_parse.c struct script_s; struct plitem_s; -struct hashlink_s; +struct hashctx_s; qboolean ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s); struct plitem_s *ED_EntityDict (progs_t *pr, edict_t *ed); @@ -345,7 +345,7 @@ struct plitem_s *ED_GlobalsDict (progs_t *pr); void ED_InitGlobals (progs_t *pr, struct plitem_s *globals); void ED_InitEntity (progs_t *pr, struct plitem_s *entity, edict_t *ent); struct plitem_s *ED_ConvertToPlist (struct script_s *script, int nohack, - struct hashlink_s **hashlinks); + struct hashctx_s **hashctx); struct plitem_s *ED_Parse (progs_t *pr, const char *data); void ED_LoadFromFile (progs_t *pr, const char *data); void ED_EntityParseFunction (progs_t *pr, void *data); @@ -2006,7 +2006,7 @@ struct progs_s { int null_bad; int no_exec_limit; - struct hashlink_s **hashlink_freelist; + struct hashctx_s **hashctx; void (*file_error) (progs_t *pr, const char *path); void *(*load_file) (progs_t *pr, const char *path, off_t *size); void *(*allocate_progs_mem) (progs_t *pr, int size); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index df1e4b6bd..c3610bb0b 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -48,7 +48,7 @@ typedef struct vulkan_ctx_s { struct qfv_device_s *device; struct qfv_swapchain_s *swapchain; VkSampleCountFlagBits msaaSamples; // FIXME not here? - struct hashlink_s *hashlinks; //FIXME want per thread + struct hashctx_s *hashctx; //FIXME want per thread VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain struct plitem_s *pipelineDef; diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 6feefdf50..81d5e32ac 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -456,7 +456,6 @@ CL_Legacy_Init (void) OK_Init (); Cmd_AddCommand ("bind", cl_bind_f, "compatibility wrapper for in_bind"); Cmd_AddCommand ("unbind", cl_unbind_f, "compatibility wrapper for in_bind"); - // FIXME hashlinks IN_LoadConfig (PL_GetPropertyList (default_input_config, 0)); } diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index 821cc7d56..c026b7154 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -111,9 +111,8 @@ PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins, void *data) pr->builtin_blocks = malloc (sizeof (biblock_t)); DARRAY_INIT (pr->builtin_blocks, 16); pr->builtin_hash = Hash_NewTable (1021, builtin_get_key, 0, pr, - pr->hashlink_freelist); - pr->builtin_num_hash = Hash_NewTable (1021, 0, 0, pr, - pr->hashlink_freelist); + pr->hashctx); + pr->builtin_num_hash = Hash_NewTable (1021, 0, 0, pr, pr->hashctx); Hash_SetHashCompare (pr->builtin_num_hash, builtin_get_hash, builtin_compare); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 09fec6c90..6596e911e 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1948,11 +1948,9 @@ PR_Debug_Init (progs_t *pr) res->type_encodings[i] = &res->void_type; } res->file_hash = Hash_NewTable (509, file_get_key, file_free, 0, - pr->hashlink_freelist); - res->debug_syms = Hash_NewTable (509, def_get_key, 0, pr, - pr->hashlink_freelist); - res->compunits = Hash_NewTable (509, compunit_get_key, 0, pr, - pr->hashlink_freelist); + pr->hashctx); + res->debug_syms = Hash_NewTable (509, def_get_key, 0, pr, pr->hashctx); + res->compunits = Hash_NewTable (509, compunit_get_key, 0, pr, pr->hashctx); PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); pr->pr_debug_resources = res; diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index eabbaa8b9..60154c589 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -544,13 +544,10 @@ PR_Init (progs_t *pr) PR_Strings_Init (pr); PR_Debug_Init (pr); pr->function_hash = Hash_NewTable (1021, function_get_key, 0, pr, - pr->hashlink_freelist); - pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr, - pr->hashlink_freelist); - pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr, - pr->hashlink_freelist); - pr->type_hash = Hash_NewTable (1021, type_get_key, 0, pr, - pr->hashlink_freelist); + pr->hashctx); + pr->global_hash = Hash_NewTable (1021, var_get_key, 0, pr, pr->hashctx); + pr->field_hash = Hash_NewTable (1021, var_get_key, 0, pr, pr->hashctx); + pr->type_hash = Hash_NewTable (1021, type_get_key, 0, pr, pr->hashctx); } VISIBLE void diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index f5031173f..c48617924 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -109,7 +109,7 @@ VISIBLE plitem_t * ED_EntityDict (progs_t *pr, edict_t *ed) { dstring_t *dstr = dstring_newstr (); - plitem_t *entity = PL_NewDictionary (pr->hashlink_freelist); + plitem_t *entity = PL_NewDictionary (pr->hashctx); pr_uint_t i; int j; int type; @@ -155,7 +155,7 @@ VISIBLE plitem_t * ED_GlobalsDict (progs_t *pr) { dstring_t *dstr = dstring_newstr (); - plitem_t *globals = PL_NewDictionary (pr->hashlink_freelist); + plitem_t *globals = PL_NewDictionary (pr->hashctx); pr_uint_t i; const char *name; const char *value; @@ -290,7 +290,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) */ VISIBLE plitem_t * -ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks) +ED_ConvertToPlist (script_t *script, int nohack, struct hashctx_s **hashctx) { dstring_t *dstr = dstring_newstr (); plitem_t *plist = PL_NewArray (); @@ -307,7 +307,7 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashlink_s **hashlinks) msg = "EOF without closing brace"; goto parse_error; } - ent = PL_NewDictionary (hashlinks); + ent = PL_NewDictionary (hashctx); while (1) { int n; @@ -513,11 +513,11 @@ ED_Parse (progs_t *pr, const char *data) if (Script_GetToken (script, 1)) { if (strequal (script->token->str, "(")) { // new style (plist) entity data - entity_list = PL_GetPropertyList (data, pr->hashlink_freelist); + entity_list = PL_GetPropertyList (data, pr->hashctx); } else { // old style entity data Script_UngetToken (script); - entity_list = ED_ConvertToPlist (script, 0, pr->hashlink_freelist); + entity_list = ED_ConvertToPlist (script, 0, pr->hashctx); } } Script_Delete (script); diff --git a/libs/gamecode/pr_resource.c b/libs/gamecode/pr_resource.c index 9a86d2302..aca45cac6 100644 --- a/libs/gamecode/pr_resource.c +++ b/libs/gamecode/pr_resource.c @@ -54,7 +54,7 @@ VISIBLE void PR_Resources_Init (progs_t *pr) { pr->resource_hash = Hash_NewTable (1021, resource_get_key, 0, 0, - pr->hashlink_freelist); + pr->hashctx); pr->resources = 0; } diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 92129f7ad..2d8c21696 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -265,7 +265,7 @@ PR_LoadStrings (progs_t *pr) Hash_FlushTable (res->strref_hash); } else { res->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free, - res, pr->hashlink_freelist); + res, pr->hashctx); res->string_map = 0; res->free_string_refs = 0; res->dyn_str_size = 0; diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index 29d95930a..a8a40ca35 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -195,8 +195,7 @@ GIB_Progs_Init (progs_t *pr) res->builtins = 0; bi_gib_builtins = Hash_NewTable (1021, bi_gib_builtin_get_key, - bi_gib_builtin_free, 0, - pr->hashlink_freelist); + bi_gib_builtin_free, 0, pr->hashctx); PR_Resources_Register (pr, "GIB", res, bi_gib_builtin_clear); PR_RegisterBuiltins (pr, builtins, res); diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 74459481c..a8ea9d72f 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -794,7 +794,7 @@ IN_Binding_SaveConfig (plitem_t *config) plitem_t *devices = PL_NewArray (); PL_D_AddObject (config, "devices", devices); for (in_devbindings_t *db = devbindings_list; db; db = db->next) { - plitem_t *db_cfg = PL_NewDictionary (0); //FIXME hashlinks + plitem_t *db_cfg = PL_NewDictionary (0); PL_A_AddObject (devices, db_cfg); PL_D_AddObject (db_cfg, "name", PL_NewString (db->name)); PL_D_AddObject (db_cfg, "devname", PL_NewString (db->devname)); diff --git a/libs/input/in_common.c b/libs/input/in_common.c index f2d895e10..65d53637f 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -508,7 +508,7 @@ IN_ProcessEvents (void) void IN_SaveConfig (plitem_t *config) { - plitem_t *input_config = PL_NewDictionary (0); //FIXME hashlinks + plitem_t *input_config = PL_NewDictionary (0); PL_D_AddObject (config, "input", input_config); IMT_SaveConfig (input_config); diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 554053df4..435315d01 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -947,14 +947,14 @@ IMT_SaveConfig (plitem_t *config) PL_D_AddObject (config, "contexts", ctx_list); for (size_t i = 0; i < in_contexts.size; i++) { in_context_t *context = &in_contexts.a[i]; - plitem_t *ctx = PL_NewDictionary (0); //FIXME hashlinks + plitem_t *ctx = PL_NewDictionary (0); PL_A_AddObject (ctx_list, ctx); PL_D_AddObject (ctx, "name", PL_NewString (context->name)); if (context->imts) { plitem_t *imt_list = PL_NewArray (); PL_D_AddObject (ctx, "imts", imt_list); for (imt_t *imt = context->imts; imt; imt = imt->next) { - plitem_t *imt_cfg = PL_NewDictionary (0); //FIXME hashlinks + plitem_t *imt_cfg = PL_NewDictionary (0); PL_D_AddObject (imt_cfg, "name", PL_NewString (imt->name)); if (imt->chain) { PL_D_AddObject (imt_cfg, "chain", @@ -976,7 +976,6 @@ IMT_SaveConfig (plitem_t *config) PL_D_AddObject (ctx, "switchers", switcher_list); for (imt_switcher_t *switcher = context->switchers; switcher; switcher = switcher->next) { - //FIXME hashlinks plitem_t *switcher_cfg = PL_NewDictionary (0); PL_A_AddObject (switcher_list, switcher_cfg); @@ -1020,7 +1019,7 @@ IMT_SaveAxisConfig (plitem_t *axes, int axis_ind, int dev_axis) in_axisbinding_t *a = imt->axis_bindings.a[axis_ind]; if (a) { in_recipe_t *recipe = a->recipe; - plitem_t *axis = PL_NewDictionary (0); //FIXME hashlinks + plitem_t *axis = PL_NewDictionary (0); PL_A_AddObject (axes, axis); PL_D_AddObject (axis, "imt", PL_NewString (imt->name)); @@ -1054,7 +1053,7 @@ IMT_SaveButtonConfig (plitem_t *buttons, int button_ind, int dev_button) for (imt_t *imt = context->imts; imt; imt = imt->next) { in_buttonbinding_t *b = imt->button_bindings.a[button_ind]; if (b) { - plitem_t *button = PL_NewDictionary (0); //FIXME hashlinks + plitem_t *button = PL_NewDictionary (0); PL_A_AddObject (buttons, button); PL_D_AddObject (button, "imt", PL_NewString (imt->name)); diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index 9391da918..3f3f6f2ee 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -164,7 +164,7 @@ RUA_Cmd_Init (progs_t *pr, int secure) if (!bi_cmds) bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0, - pr->hashlink_freelist); + pr->hashctx); PR_Resources_Register (pr, "Cmd", res, bi_cmd_clear); PR_RegisterBuiltins (pr, builtins, res); diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 63020060e..cc78353d8 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -173,7 +173,7 @@ bi_Hash_NewTable (progs_t *pr, void *_res) gk = ht->gk ? bi_get_key : 0; f = ht->f ? bi_free : 0; - ht->tab = Hash_NewTable (tsize, gk, f, ht, pr->hashlink_freelist); + ht->tab = Hash_NewTable (tsize, gk, f, ht, pr->hashctx); R_INT (pr) = table_index (res, ht); } diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 787fbf66c..f4cfb0cae 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -51,7 +51,7 @@ typedef struct rua_in_cookie_s { } rua_in_cookie_t; typedef struct input_resources_s { - hashlink_t *hash_links; + hashctx_t *hashctx; hashtab_t *cookies; memsuper_t *cookie_super; } input_resources_t; @@ -510,7 +510,7 @@ RUA_Input_Init (progs_t *pr, int secure) res->cookie_super = new_memsuper (); res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, - &res->hash_links); + &res->hashctx); Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies); PR_Resources_Register (pr, "input", res, bi_input_clear); diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index c7942c8e0..6b0cdbfaf 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -2309,13 +2309,11 @@ RUA_Obj_Init (progs_t *pr, int secure) probj->pr = pr; probj->selector_hash = Hash_NewTable (1021, selector_get_key, 0, probj, - pr->hashlink_freelist); - probj->classes = Hash_NewTable (1021, class_get_key, 0, probj, - pr->hashlink_freelist); + pr->hashctx); + probj->classes = Hash_NewTable (1021, class_get_key, 0, probj, pr->hashctx); probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj, - pr->hashlink_freelist); - probj->load_methods = Hash_NewTable (1021, 0, 0, probj, - pr->hashlink_freelist); + pr->hashctx); + probj->load_methods = Hash_NewTable (1021, 0, 0, probj, pr->hashctx); probj->msg = dstring_newstr(); Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, load_methods_compare); diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index c2b7414d3..1246e1510 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -194,7 +194,7 @@ bi_PL_GetFromFile (progs_t *pr, void *_res) Qread (file, buf, len); buf[len] = 0; - plitem = PL_GetPropertyList (buf, pr->hashlink_freelist); + plitem = PL_GetPropertyList (buf, pr->hashctx); R_INT (pr) = plist_retain (res, plitem); } @@ -203,8 +203,7 @@ static void bi_PL_GetPropertyList (progs_t *pr, void *_res) { plist_resources_t *res = _res; - plitem_t *plitem = PL_GetPropertyList (P_GSTRING (pr, 0), - pr->hashlink_freelist); + plitem_t *plitem = PL_GetPropertyList (P_GSTRING (pr, 0), pr->hashctx); R_INT (pr) = plist_retain (res, plitem); } @@ -382,7 +381,7 @@ static void bi_PL_NewDictionary (progs_t *pr, void *_res) { plist_resources_t *res = _res; - plitem_t *plitem = PL_NewDictionary (pr->hashlink_freelist); + plitem_t *plitem = PL_NewDictionary (pr->hashctx); R_INT (pr) = plist_retain (res, plitem); } @@ -484,7 +483,7 @@ void RUA_Plist_Init (progs_t *pr, int secure) { plist_resources_t *res = calloc (1, sizeof (plist_resources_t)); - res->plist_tab = Hash_NewTable (1021, 0, 0, 0, pr->hashlink_freelist); + res->plist_tab = Hash_NewTable (1021, 0, 0, 0, pr->hashctx); Hash_SetHashCompare (res->plist_tab, plist_get_hash, plist_compare); PR_Resources_Register (pr, "plist", res, bi_plist_clear); diff --git a/libs/util/cexpr-vars.c b/libs/util/cexpr-vars.c index 4344c6035..02fbd56db 100644 --- a/libs/util/cexpr-vars.c +++ b/libs/util/cexpr-vars.c @@ -161,7 +161,7 @@ cexpr_init_symtab (exprtab_t *symtab, exprctx_t *ctx) { exprsym_t *sym; - symtab->tab = Hash_NewTable (61, expr_getkey, 0, 0, ctx->hashlinks); + symtab->tab = Hash_NewTable (61, expr_getkey, 0, 0, ctx->hashctx); for (sym = symtab->symbols; sym->name; sym++) { Hash_Add (symtab->tab, sym); } diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 3941d4cad..dd8e64d84 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -489,7 +489,7 @@ cvar_write_config (void *ele, void *data) VISIBLE void Cvar_SaveConfig (plitem_t *config) { - plitem_t *cvars = PL_NewDictionary (0); //FIXME hashlinks + plitem_t *cvars = PL_NewDictionary (0); PL_D_AddObject (config, "cvars", cvars); Hash_ForEach (cvar_hash, cvar_write_config, cvars); Hash_ForEach (user_cvar_hash, cvar_write_config, cvars); diff --git a/libs/util/hash.c b/libs/util/hash.c index 29d353c71..db5add992 100644 --- a/libs/util/hash.c +++ b/libs/util/hash.c @@ -45,11 +45,11 @@ #include "compat.h" -struct hashlink_s { +typedef struct hashlink_s { struct hashlink_s *next; struct hashlink_s **prev; void *data; -}; +} hashlink_t; struct hashtab_s { size_t tab_size; @@ -184,8 +184,7 @@ get_index (uintptr_t hash, size_t size, size_t bits) VISIBLE hashtab_t * Hash_NewTable (int tsize, const char *(*gk)(const void*,void*), - void (*f)(void*,void*), void *ud, - hashlink_t **hashlink_freelist) + void (*f)(void*,void*), void *ud, hashctx_t **hctx) { hashtab_t *tab = calloc (1, field_offset (hashtab_t, tab[tsize])); if (!tab) @@ -194,10 +193,10 @@ Hash_NewTable (int tsize, const char *(*gk)(const void*,void*), tab->user_data = ud; tab->get_key = gk; tab->free_ele = f; - if (!hashlink_freelist) { - hashlink_freelist = &default_hashlink_freelist; + if (!hctx) { + hctx = (hashctx_t **) &default_hashlink_freelist; } - tab->hashlink_freelist = hashlink_freelist; + tab->hashlink_freelist = (hashlink_t **) hctx; while (tsize) { tab->size_bits++; diff --git a/libs/util/plist.c b/libs/util/plist.c index 6fe440c68..be3cc2d47 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -98,7 +98,7 @@ typedef struct pldata_s { // Unparsed property list string unsigned line_start; plitem_t *error; va_ctx_t *va_ctx; - hashlink_t **hashlinks; + hashctx_t **hashctx; } pldata_t; // Ugly defines for fast checking and conversion from char to number @@ -165,11 +165,11 @@ pl_newitem (pltype_t type) } VISIBLE plitem_t * -PL_NewDictionary (hashlink_t **hashlinks) +PL_NewDictionary (hashctx_t **hashctx) { plitem_t *item = pl_newitem (QFDictionary); pldict_t *dict = malloc (sizeof (pldict_t)); - dict->tab = Hash_NewTable (1021, dict_get_key, dict_free, NULL, hashlinks); + dict->tab = Hash_NewTable (1021, dict_get_key, dict_free, NULL, hashctx); DARRAY_INIT (&dict->keys, 8); item->data = dict; return item; @@ -776,7 +776,7 @@ pl_parsepropertylistitem (pldata_t *pl) switch (pl->ptr[pl->pos]) { case '{': { - item = PL_NewDictionary (pl->hashlinks); + item = PL_NewDictionary (pl->hashctx); item->line = pl->line; pl->pos++; @@ -934,7 +934,7 @@ pl_parsepropertylistitem (pldata_t *pl) } VISIBLE plitem_t * -PL_GetPropertyList (const char *string, hashlink_t **hashlinks) +PL_GetPropertyList (const char *string, hashctx_t **hashctx) { plitem_t *newpl = NULL; @@ -946,7 +946,7 @@ PL_GetPropertyList (const char *string, hashlink_t **hashlinks) .end = strlen (string), .line = 1, .va_ctx = va_create_context (4), - .hashlinks = hashlinks, + .hashctx = hashctx, }; if (!(newpl = pl_parsepropertylistitem (&pl))) { diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index c83adb15c..853de0387 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -352,8 +352,7 @@ void R_Progs_Init (progs_t *pr) { draw_resources_t *res = calloc (1, sizeof (draw_resources_t)); - res->pic_hash = Hash_NewTable (61, bi_draw_get_key, 0, 0, - pr->hashlink_freelist); + res->pic_hash = Hash_NewTable (61, bi_draw_get_key, 0, 0, pr->hashctx); PR_Resources_Register (pr, "Draw", res, bi_draw_clear); PR_RegisterBuiltins (pr, builtins, res); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 4e7c95a9a..9ae5d8b40 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -961,8 +961,7 @@ static plfield_t renderpass_fields[] = { static hashtab_t * handlref_symtab (void (*free_func)(void*,void*), vulkan_ctx_t *ctx) { - return Hash_NewTable (23, handleref_getkey, free_func, - ctx, &ctx->hashlinks); + return Hash_NewTable (23, handleref_getkey, free_func, ctx, &ctx->hashctx); } static const char * @@ -978,7 +977,7 @@ static exprtab_t root_symtab = { static void __attribute__((constructor)) root_symtab_init (void) { - // using a null hashlinks here is safe because this function is run before + // using a null hashctx here is safe because this function is run before // main and thus before any possibility of threading. exprctx_t root_context = { .symtab = &root_symtab }; cexpr_init_symtab (&root_symtab, &root_context); @@ -988,9 +987,8 @@ void QFV_InitParse (vulkan_ctx_t *ctx) { exprctx_t context = {}; - enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, - &ctx->hashlinks); - context.hashlinks = &ctx->hashlinks; + enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, &ctx->hashctx); + context.hashctx = &ctx->hashctx; vkgen_init_symtabs (&context); cexpr_init_symtab (&qfv_output_t_symtab, &context); cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); @@ -1034,7 +1032,7 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, exprctx.external_variables = &vars_tab; exprctx.messages = messages; - exprctx.hashlinks = &ctx->hashlinks; + exprctx.hashctx = &ctx->hashctx; exprctx.memsuper = memsuper; cexpr_init_symtab (&vars_tab, &exprctx); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 07a236a0c..a7764b9b3 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -301,7 +301,7 @@ build_configs (vulkan_ctx_t *ctx) builtin_plists = malloc (num_plists * sizeof (plitem_t *)); num_plists = 0; for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { - plitem_t *item = PL_GetPropertyList (sym->value, &ctx->hashlinks); + plitem_t *item = PL_GetPropertyList (sym->value, &ctx->hashctx); if (!item) { // Syntax errors in the compiled-in plists are unrecoverable Sys_Error ("Error parsing plist for %s", sym->name); @@ -311,7 +311,7 @@ build_configs (vulkan_ctx_t *ctx) sym->type = &cexpr_plitem; num_plists++; } - exprctx_t ectx = { .hashlinks = &ctx->hashlinks }; + exprctx_t ectx = { .hashctx = &ctx->hashctx }; cexpr_init_symtab (&builtin_configs, &ectx); } @@ -328,7 +328,7 @@ get_builtin_config (vulkan_ctx_t *ctx, const char *name) .result = &result, .symtab = &builtin_configs, .memsuper = new_memsuper (), - .hashlinks = &ctx->hashlinks, + .hashctx = &ctx->hashctx, .messages = PL_NewArray (), }; if (cexpr_eval_string (name, &ectx)) { diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index d9ea23659..afc421160 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -172,7 +172,7 @@ CL_WriteConfiguration (void) // dedicated servers initialize the host but don't parse and set the // config.cfg cvars if (host_initialized && !isDedicated && cl_writecfg) { - plitem_t *config = PL_NewDictionary (0); //FIXME hashlinks + plitem_t *config = PL_NewDictionary (0); Cvar_SaveConfig (config); IN_SaveConfig (config); @@ -204,7 +204,7 @@ CL_ReadConfiguration (const char *cfg_name) cfg[len] = 0; Qclose (cfg_file); - plitem_t *config = PL_GetPropertyList (cfg, 0); // FIXME hashlinks + plitem_t *config = PL_GetPropertyList (cfg, 0); if (!config) { return 0; } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 1db3559d1..6f9ceb514 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1730,7 +1730,7 @@ void Host_WriteConfiguration (void) { if (host_initialized && cl_writecfg) { - plitem_t *config = PL_NewDictionary (0); //FIXME hashlinks + plitem_t *config = PL_NewDictionary (0); Cvar_SaveConfig (config); IN_SaveConfig (config); @@ -1762,7 +1762,7 @@ Host_ReadConfiguration (const char *cfg_name) cfg[len] = 0; Qclose (cfg_file); - plitem_t *config = PL_GetPropertyList (cfg, 0); // FIXME hashlinks + plitem_t *config = PL_GetPropertyList (cfg, 0); if (!config) { return 0; } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 02e703822..18470bab0 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -207,7 +207,7 @@ create_progs (qwaq_thread_t *thread) pr->allocate_progs_mem = allocate_progs_mem; pr->free_progs_mem = free_progs_mem; pr->no_exec_limit = 1; - pr->hashlink_freelist = &thread->hashlink_freelist; + pr->hashctx = &thread->hashctx; pr_debug = 2; pr_boundscheck = 0; diff --git a/ruamoko/qwaq/builtins/term-input.c b/ruamoko/qwaq/builtins/term-input.c index 4e725a431..ce1bf0ba1 100644 --- a/ruamoko/qwaq/builtins/term-input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -587,7 +587,7 @@ qwaq_input_init (qwaq_input_resources_t *res) Hash_FlushTable (res->key_sequences); } else { res->key_sequences = Hash_NewTable (127, key_sequence_getkey, 0, 0, - res->pr->hashlink_freelist); + res->pr->hashctx); } for (size_t i = 0; i < sizeof (default_keys) / sizeof (default_keys[0]); i++) { diff --git a/ruamoko/qwaq/qwaq.h b/ruamoko/qwaq/qwaq.h index cb16c9af9..1399bb6f8 100644 --- a/ruamoko/qwaq/qwaq.h +++ b/ruamoko/qwaq/qwaq.h @@ -18,7 +18,7 @@ typedef struct qwaq_thread_s { progs_t *pr; int rua_security; struct memhunk_s *hunk; - struct hashlink_s *hashlink_freelist; + struct hashctx_s *hashctx; pr_func_t main_func; void *data; } qwaq_thread_t; From f91167d74aaa906a9fe3de68d183e7b6aad50ecb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 18:10:27 +0900 Subject: [PATCH 2800/3664] [hash] Use uintptr_t for all hashes This fixes the inconsistent hash types and removes all references to "long", making for better portability. --- include/QF/hash.h | 4 ++-- libs/util/hash.c | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/QF/hash.h b/include/QF/hash.h index f846e6c95..d5367be15 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -187,14 +187,14 @@ void Hash_Free (hashtab_t *tab, void *ele); this is the same function as used internally. */ -unsigned long Hash_String (const char *str) __attribute__((pure)); +uintptr_t Hash_String (const char *str) __attribute__((pure)); /** hash a buffer. \param buf the buffer to hash \param len the size of the buffer \return the hash value of the string. */ -unsigned long Hash_Buffer (const void *buf, int len) __attribute__((pure)); +uintptr_t Hash_Buffer (const void *buf, int len) __attribute__((pure)); /** get the size of the table \param tab the table in question diff --git a/libs/util/hash.c b/libs/util/hash.c index db5add992..082672c7d 100644 --- a/libs/util/hash.c +++ b/libs/util/hash.c @@ -93,11 +93,11 @@ free_hashlink (hashlink_t *link, hashlink_t **free_hashlinks) static hashlink_t *default_hashlink_freelist; -VISIBLE unsigned long +VISIBLE uintptr_t Hash_String (const char *str) { #if 0 - unsigned long h = 0; + uintptr_t h = 0; while (*str) { h = (h << 4) + (unsigned char)*str++; if (h&0xf0000000) @@ -119,12 +119,12 @@ Hash_String (const char *str) #endif } -VISIBLE unsigned long +VISIBLE uintptr_t Hash_Buffer (const void *_buf, int len) { const unsigned char *buf = _buf; #if 0 - unsigned long h = 0; + uintptr_t h = 0; while (len-- > 0) { h = (h << 4) + (unsigned char)*buf++; if (h&0xf0000000) @@ -162,8 +162,8 @@ static inline int get_index (uintptr_t hash, size_t size, size_t bits) { #if 0 - unsigned long mask = ~0UL << bits; - unsigned long extract; + uintptr_t mask = ~0UL << bits; + uintptr_t extract; size -= 1; for (extract = (hash & mask) >> bits; @@ -245,7 +245,7 @@ Hash_FlushTable (hashtab_t *tab) VISIBLE int Hash_Add (hashtab_t *tab, void *ele) { - unsigned long h = Hash_String (tab->get_key(ele, tab->user_data)); + uintptr_t h = Hash_String (tab->get_key(ele, tab->user_data)); size_t ind = get_index (h, tab->tab_size, tab->size_bits); hashlink_t *lnk = new_hashlink (tab->hashlink_freelist); @@ -264,7 +264,7 @@ Hash_Add (hashtab_t *tab, void *ele) VISIBLE int Hash_AddElement (hashtab_t *tab, void *ele) { - unsigned long h = tab->get_hash (ele, tab->user_data); + uintptr_t h = tab->get_hash (ele, tab->user_data); size_t ind = get_index (h, tab->tab_size, tab->size_bits); hashlink_t *lnk = new_hashlink (tab->hashlink_freelist); @@ -283,7 +283,7 @@ Hash_AddElement (hashtab_t *tab, void *ele) VISIBLE void * Hash_Find (hashtab_t *tab, const char *key) { - unsigned long h = Hash_String (key); + uintptr_t h = Hash_String (key); size_t ind = get_index (h, tab->tab_size, tab->size_bits); hashlink_t *lnk = tab->tab[ind]; @@ -298,7 +298,7 @@ Hash_Find (hashtab_t *tab, const char *key) VISIBLE void * Hash_FindElement (hashtab_t *tab, const void *ele) { - unsigned long h = tab->get_hash (ele, tab->user_data); + uintptr_t h = tab->get_hash (ele, tab->user_data); size_t ind = get_index (h, tab->tab_size, tab->size_bits); hashlink_t *lnk = tab->tab[ind]; @@ -313,7 +313,7 @@ Hash_FindElement (hashtab_t *tab, const void *ele) VISIBLE void ** Hash_FindList (hashtab_t *tab, const char *key) { - unsigned long h = Hash_String (key); + uintptr_t h = Hash_String (key); size_t ind = get_index (h, tab->tab_size, tab->size_bits); hashlink_t *lnk = tab->tab[ind], *start = 0; int count = 0; @@ -341,7 +341,7 @@ Hash_FindList (hashtab_t *tab, const char *key) VISIBLE void ** Hash_FindElementList (hashtab_t *tab, void *ele) { - unsigned long h = tab->get_hash (ele, tab->user_data); + uintptr_t h = tab->get_hash (ele, tab->user_data); size_t ind = get_index (h, tab->tab_size, tab->size_bits); hashlink_t *lnk = tab->tab[ind], *start = 0; int count = 0; @@ -369,7 +369,7 @@ Hash_FindElementList (hashtab_t *tab, void *ele) VISIBLE void * Hash_Del (hashtab_t *tab, const char *key) { - unsigned long h = Hash_String (key); + uintptr_t h = Hash_String (key); size_t ind = get_index (h, tab->tab_size, tab->size_bits); hashlink_t *lnk = tab->tab[ind]; void *data; @@ -392,7 +392,7 @@ Hash_Del (hashtab_t *tab, const char *key) VISIBLE void * Hash_DelElement (hashtab_t *tab, void *ele) { - unsigned long h = tab->get_hash (ele, tab->user_data); + uintptr_t h = tab->get_hash (ele, tab->user_data); size_t ind = get_index (h, tab->tab_size, tab->size_bits); hashlink_t *lnk = tab->tab[ind]; void *data; From b7b6d4ad12f2cbacfd368bd100d5b940a492ea01 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 18:12:37 +0900 Subject: [PATCH 2801/3664] [hash] Clean up some duplicate code Hash_Add and Hash_AddElement differed by only one line: the hash calculation. --- libs/util/hash.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/libs/util/hash.c b/libs/util/hash.c index 082672c7d..f1d3d3884 100644 --- a/libs/util/hash.c +++ b/libs/util/hash.c @@ -242,10 +242,9 @@ Hash_FlushTable (hashtab_t *tab) tab->num_ele = 0; } -VISIBLE int -Hash_Add (hashtab_t *tab, void *ele) +static int +hash_add_element (hashtab_t *tab, uintptr_t h, void *ele) { - uintptr_t h = Hash_String (tab->get_key(ele, tab->user_data)); size_t ind = get_index (h, tab->tab_size, tab->size_bits); hashlink_t *lnk = new_hashlink (tab->hashlink_freelist); @@ -261,23 +260,18 @@ Hash_Add (hashtab_t *tab, void *ele) return 0; } +VISIBLE int +Hash_Add (hashtab_t *tab, void *ele) +{ + uintptr_t h = Hash_String (tab->get_key(ele, tab->user_data)); + return hash_add_element (tab, h, ele); +} + VISIBLE int Hash_AddElement (hashtab_t *tab, void *ele) { uintptr_t h = tab->get_hash (ele, tab->user_data); - size_t ind = get_index (h, tab->tab_size, tab->size_bits); - hashlink_t *lnk = new_hashlink (tab->hashlink_freelist); - - if (!lnk) - return -1; - if (tab->tab[ind]) - tab->tab[ind]->prev = &lnk->next; - lnk->next = tab->tab[ind]; - lnk->prev = &tab->tab[ind]; - lnk->data = ele; - tab->tab[ind] = lnk; - tab->num_ele++; - return 0; + return hash_add_element (tab, h, ele); } VISIBLE void * From 973ae0ad54aaddccd81466bf15f8c4c6d61b7f17 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 18:23:32 +0900 Subject: [PATCH 2802/3664] [gamecode] Add PR_Shutdown for tearing down a VM This is meant for a "permanent" tear-down before freeing the memory holding the VM state or at program shutdown. As a consequence, builtin sub-systems registering resources are now required to pass a "destroy" function pointer that will be called just before the memory holding those resources is freed by the VM resource manager (ie, the manager owns the resource memory block, but each subsystem is responsible for cleaning up any resources held within that block). This even enhances thread-safety in rua_obj (there are some problems with cmd, cvar, and gib). --- include/QF/progs.h | 24 +++++++- libs/console/bi_inputline.c | 7 ++- libs/gamecode/pr_builtins.c | 15 +++++ libs/gamecode/pr_debug.c | 21 ++++++- libs/gamecode/pr_load.c | 21 +++++++ libs/gamecode/pr_resource.c | 25 +++++++- libs/gamecode/pr_strings.c | 24 ++++---- libs/gib/bi_gib.c | 13 ++++- libs/ruamoko/rua_cbuf.c | 21 ++++--- libs/ruamoko/rua_cmd.c | 15 ++++- libs/ruamoko/rua_cvar.c | 7 ++- libs/ruamoko/rua_hash.c | 7 ++- libs/ruamoko/rua_input.c | 10 +++- libs/ruamoko/rua_mersenne.c | 8 ++- libs/ruamoko/rua_model.c | 8 ++- libs/ruamoko/rua_msgbuf.c | 8 ++- libs/ruamoko/rua_obj.c | 91 +++++++++++++++++------------- libs/ruamoko/rua_plist.c | 9 ++- libs/ruamoko/rua_qfile.c | 7 ++- libs/ruamoko/rua_scene.c | 7 ++- libs/ruamoko/rua_script.c | 8 ++- libs/ruamoko/rua_set.c | 7 ++- libs/video/renderer/r_progs.c | 9 ++- ruamoko/qwaq/builtins/curses.c | 8 ++- ruamoko/qwaq/builtins/debug.c | 16 +++++- ruamoko/qwaq/builtins/editbuffer.c | 8 ++- ruamoko/qwaq/builtins/main.c | 8 ++- ruamoko/qwaq/builtins/term-input.c | 7 ++- 28 files changed, 334 insertions(+), 85 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 9434685cb..b7796a3d3 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -61,6 +61,15 @@ typedef struct edict_s edict_t; */ void PR_Init (progs_t *pr); +/** Shut down the progs engine. + + Shuts down only the specified progs engine. Frees resources allocated + during progs init. + + \param pr The progs engine instance to shut down. +*/ +void PR_Shutdown (progs_t *pr); + /** Initialize the Cvars for the progs engine. Call before calling PR_Init(). */ void PR_Init_Cvars (void); @@ -1692,6 +1701,9 @@ void PR_Sprintf (progs_t *pr, struct dstring_s *result, const char *name, */ void PR_Resources_Init (progs_t *pr); +void PR_Resources_Shutdown (progs_t *pr); +void PR_Builtins_Shutdown (progs_t *pr); + /** Clear all resources before loading a new progs. Calls the clear() callback of all registered resources. @@ -1706,17 +1718,23 @@ void PR_Resources_Clear (progs_t *pr); \param name The name of the resource. Used for retrieving the resource. \param data The resource data. - \param clear Callback for performing any necessary cleanup. Called - by PR_Resources_Clear(). The parameters are the current + \param clear Callback for performing any necessary cleanup before + VM reuse. Called by PR_Resources_Clear(). The parameters + are the current VM (\p pr) and \p data. + \param destroy Callback for when the resource is about to be destryed + due to final VM shutdown. The parameters are the current VM (\p pr) and \p data. \note The name should be unique to the VM, but no checking is done. If the name is not unique, the previous registered resource will break. The name of the sub-system registering the resource is a suitable name, and will probably be unique. + \note During VM shutdown, \a clear is called (for all resources) + before \destroy is called. */ void PR_Resources_Register (progs_t *pr, const char *name, void *data, - void (*clear)(progs_t *, void *)); + void (*clear)(progs_t *, void *), + void (*destroy)(progs_t *, void *)); /** Retrieve a resource registered with the VM. diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index c0da2c4e3..9111945ea 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -102,6 +102,11 @@ bi_il_clear (progs_t *pr, void *_res) il_data_reset (res); } +static void +bi_il_destroy (progs_t *pr, void *_res) +{ +} + static il_data_t * __attribute__((pure)) get_inputline (progs_t *pr, il_resources_t *res, int arg, const char *func) { @@ -341,7 +346,7 @@ InputLine_Progs_Init (progs_t *pr) { il_resources_t *res = calloc (1, sizeof (il_resources_t)); - PR_Resources_Register (pr, "InputLine", res, bi_il_clear); + PR_Resources_Register (pr, "InputLine", res, bi_il_clear, bi_il_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index c026b7154..2e9b9f60f 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -158,6 +158,21 @@ PR_RegisterBuiltins (progs_t *pr, builtin_t *builtins, void *data) } } +void +PR_Builtins_Shutdown (progs_t *pr) +{ + for (size_t i = 0; i < pr->builtin_blocks->size; i++) { + free (pr->builtin_blocks->a[i]); + } + DARRAY_CLEAR (pr->builtin_blocks); + free (pr->builtin_blocks); + pr->builtin_blocks = 0; + Hash_DelTable (pr->builtin_hash); + pr->builtin_hash = 0; + Hash_DelTable (pr->builtin_num_hash); + pr->builtin_num_hash = 0; +} + VISIBLE builtin_t * PR_FindBuiltin (progs_t *pr, const char *name) { diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 6596e911e..1b1484351 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -391,6 +391,24 @@ pr_debug_clear (progs_t *pr, void *data) } } +static void +pr_debug_destroy (progs_t *pr, void *_res) +{ + __auto_type res = (prdeb_resources_t *) _res; + + dstring_delete (res->string); + dstring_delete (res->dva); + dstring_delete (res->line); + dstring_delete (res->dstr); + va_destroy_context (res->va); + + Hash_DelTable (res->file_hash); + Hash_DelTable (res->debug_syms); + Hash_DelTable (res->compunits); + + pr->pr_debug_resources = 0; +} + static file_t * PR_Load_Source_File (progs_t *pr, const char *fname) { @@ -1952,7 +1970,8 @@ PR_Debug_Init (progs_t *pr) res->debug_syms = Hash_NewTable (509, def_get_key, 0, pr, pr->hashctx); res->compunits = Hash_NewTable (509, compunit_get_key, 0, pr, pr->hashctx); - PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear); + PR_Resources_Register (pr, "PR_Debug", res, pr_debug_clear, + pr_debug_destroy); pr->pr_debug_resources = res; } diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 60154c589..961bc1c7a 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -550,6 +550,27 @@ PR_Init (progs_t *pr) pr->type_hash = Hash_NewTable (1021, type_get_key, 0, pr, pr->hashctx); } +VISIBLE void +PR_Shutdown (progs_t *pr) +{ + PR_Resources_Shutdown (pr); + PR_Builtins_Shutdown (pr); + + free (pr->load_funcs); + free (pr->load_finish_funcs); + pr->num_load_funcs = pr->max_load_funcs = 0; + pr->num_load_finish_funcs = pr->max_load_finish_funcs = 0; + + Hash_DelTable (pr->function_hash); + Hash_DelTable (pr->global_hash); + Hash_DelTable (pr->field_hash); + Hash_DelTable (pr->type_hash); + pr->function_hash = 0; + pr->global_hash = 0; + pr->field_hash = 0; + pr->type_hash = 0; +} + VISIBLE void PR_Error (progs_t *pr, const char *error, ...) { diff --git a/libs/gamecode/pr_resource.c b/libs/gamecode/pr_resource.c index aca45cac6..0b0c52ec7 100644 --- a/libs/gamecode/pr_resource.c +++ b/libs/gamecode/pr_resource.c @@ -42,6 +42,7 @@ struct pr_resource_s { pr_resource_t *next; void *data; void (*clear)(progs_t *pr, void *data); + void (*destroy)(progs_t *pr, void *data); }; static const char * @@ -68,9 +69,30 @@ PR_Resources_Clear (progs_t *pr) } } +VISIBLE void +PR_Resources_Shutdown (progs_t *pr) +{ + // Clear resources first in case there are any cross-dependencies + PR_Resources_Clear (pr); + + pr_resource_t *res = pr->resources; + while (res) { + pr_resource_t *t = res->next; + res->destroy (pr, res->data); + free (res->data); + free (res); + res = t; + } + pr->resources = 0; + + Hash_DelTable (pr->resource_hash); + pr->resource_hash = 0; +} + VISIBLE void PR_Resources_Register (progs_t *pr, const char *name, void *data, - void (*clear)(progs_t *, void *)) + void (*clear)(progs_t *, void *), + void (*destroy)(progs_t *, void *)) { pr_resource_t *res = malloc (sizeof (pr_resource_t)); if (!res) @@ -78,6 +100,7 @@ PR_Resources_Register (progs_t *pr, const char *name, void *data, res->name = name; res->data = data; res->clear = clear; + res->destroy = destroy; res->next = pr->resources; pr->resources = res; Hash_Add (pr->resource_hash, res); diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 2d8c21696..840e82662 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -232,6 +232,15 @@ pr_strings_clear (progs_t *pr, void *data) pr->pr_xtstr = 0; } +static void +pr_strings_destroy (progs_t *pr, void *_res) +{ + __auto_type res = (prstr_resources_t *) _res; + dstring_delete (res->print_str); + Hash_DelTable (res->strref_hash); + pr->pr_string_resources = 0; +} + VISIBLE int PR_LoadStrings (progs_t *pr) { @@ -261,15 +270,7 @@ PR_LoadStrings (progs_t *pr) res->ds_mem.realloc = pr_strings_realloc; res->ds_mem.data = pr; - if (res->strref_hash) { - Hash_FlushTable (res->strref_hash); - } else { - res->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free, - res, pr->hashctx); - res->string_map = 0; - res->free_string_refs = 0; - res->dyn_str_size = 0; - } + Hash_FlushTable (res->strref_hash); if (res->static_strings) free (res->static_strings); @@ -1254,7 +1255,10 @@ PR_Strings_Init (progs_t *pr) prstr_resources_t *res = calloc (1, sizeof (*res)); res->pr = pr; res->print_str = dstring_new (); + res->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free, + res, pr->hashctx); - PR_Resources_Register (pr, "Strings", res, pr_strings_clear); + PR_Resources_Register (pr, "Strings", res, pr_strings_clear, + pr_strings_destroy); pr->pr_string_resources = res; } diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index a8a40ca35..b180613e3 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -112,6 +112,13 @@ bi_gib_builtin_clear (progs_t *progs, void *_res) } } +static void +bi_gib_builtin_destroy (progs_t *progs, void *_res) +{ + //bi_gib_resources_t *res = (bi_gib_resources_t *) _res; + Hash_DelTable (bi_gib_builtins); +} + static void bi_GIB_Builtin_Add (progs_t *pr, void *_res) { @@ -194,9 +201,13 @@ GIB_Progs_Init (progs_t *pr) bi_gib_resources_t *res = malloc (sizeof (bi_gib_resources_t)); res->builtins = 0; + if (bi_gib_builtins) { + Sys_Error ("GIB_Progs_Init: only one progs VM supported FIXME"); + } bi_gib_builtins = Hash_NewTable (1021, bi_gib_builtin_get_key, bi_gib_builtin_free, 0, pr->hashctx); - PR_Resources_Register (pr, "GIB", res, bi_gib_builtin_clear); + PR_Resources_Register (pr, "GIB", res, bi_gib_builtin_clear, + bi_gib_builtin_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_cbuf.c b/libs/ruamoko/rua_cbuf.c index b5689461b..c727ae891 100644 --- a/libs/ruamoko/rua_cbuf.c +++ b/libs/ruamoko/rua_cbuf.c @@ -41,13 +41,12 @@ typedef struct { cbuf_t *cbuf; } cbuf_resources_t; -static cbuf_t * -get_cbuf (progs_t *pr, int arg, const char *func) +static cbuf_t * __attribute__((pure)) +_get_cbuf (progs_t *pr, cbuf_resources_t *res, int arg, const char *func) { cbuf_t *cbuf = 0; if (arg == 0) { - cbuf_resources_t *res = PR_Resources_Find (pr, "Cbuf"); cbuf = res->cbuf; } else { PR_RunError (pr, "%s: Invalid cbuf_t", func); @@ -57,12 +56,13 @@ get_cbuf (progs_t *pr, int arg, const char *func) return cbuf; } +#define get_cbuf(pr, res, arg) _get_cbuf(pr, res, arg, __FUNCTION__) static void bi_Cbuf_AddText (progs_t *pr, void *data) { const char *text = P_GSTRING (pr, 0); - cbuf_t *cbuf = get_cbuf (pr, 0, __FUNCTION__); + cbuf_t *cbuf = get_cbuf (pr, data, 0); Cbuf_AddText (cbuf, text); } @@ -70,21 +70,21 @@ static void bi_Cbuf_InsertText (progs_t *pr, void *data) { const char *text = P_GSTRING (pr, 0); - cbuf_t *cbuf = get_cbuf (pr, 0, __FUNCTION__); + cbuf_t *cbuf = get_cbuf (pr, data, 0); Cbuf_InsertText (cbuf, text); } static void bi_Cbuf_Execute (progs_t *pr, void *data) { - cbuf_t *cbuf = get_cbuf (pr, 0, __FUNCTION__); + cbuf_t *cbuf = get_cbuf (pr, data, 0); Cbuf_Execute (cbuf); } static void bi_Cbuf_Execute_Sets (progs_t *pr, void *data) { - cbuf_t *cbuf = get_cbuf (pr, 0, __FUNCTION__); + cbuf_t *cbuf = get_cbuf (pr, data, 0); Cbuf_Execute_Sets (cbuf); } @@ -93,6 +93,11 @@ bi_cbuf_clear (progs_t *pr, void *data) { } +static void +bi_cbuf_destroy (progs_t *pr, void *data) +{ +} + #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } @@ -108,7 +113,7 @@ void RUA_Cbuf_Init (progs_t *pr, int secure) { cbuf_resources_t *res = calloc (sizeof (cbuf_resources_t), 1); - PR_Resources_Register (pr, "Cbuf", res, bi_cbuf_clear); + PR_Resources_Register (pr, "Cbuf", res, bi_cbuf_clear, bi_cbuf_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index 3f3f6f2ee..50e4ba2eb 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -58,6 +58,7 @@ typedef struct { } cmd_resources_t; static hashtab_t *bi_cmds; +static int bi_cmds_refs; static const char * bi_cmd_get_key (const void *c, void *unused) @@ -123,6 +124,14 @@ bi_cmd_clear (progs_t *pr, void *data) } } +static void +bi_cmd_destroy (progs_t *pr, void *data) +{ + if (!--bi_cmds_refs) { + Hash_DelTable (bi_cmds); + } +} + static void bi_Cmd_Argc (progs_t *pr, void *data) { @@ -162,10 +171,12 @@ RUA_Cmd_Init (progs_t *pr, int secure) res->cmds = 0; - if (!bi_cmds) + if (!bi_cmds) { bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0, pr->hashctx); + } + bi_cmds_refs++; - PR_Resources_Register (pr, "Cmd", res, bi_cmd_clear); + PR_Resources_Register (pr, "Cmd", res, bi_cmd_clear, bi_cmd_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_cvar.c b/libs/ruamoko/rua_cvar.c index e81b9241a..716e16172 100644 --- a/libs/ruamoko/rua_cvar.c +++ b/libs/ruamoko/rua_cvar.c @@ -76,6 +76,11 @@ bi_cvar_clear (progs_t *pr, void *_res) } } +static void +bi_cvar_destroy (progs_t *pr, void *_res) +{ +} + static void bi_Cvar_MakeAlias (progs_t *pr, void *_res) { @@ -266,6 +271,6 @@ RUA_Cvar_Init (progs_t *pr, int secure) cvar_resources_t *res = calloc (1, sizeof (cvar_resources_t)); res->aliases = 0; - PR_Resources_Register (pr, "Cvar", res, bi_cvar_clear); + PR_Resources_Register (pr, "Cvar", res, bi_cvar_clear, bi_cvar_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index cc78353d8..8cb1e55a8 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -382,6 +382,11 @@ bi_hash_clear (progs_t *pr, void *_res) table_reset (res); } +static void +bi_hash_destroy (progs_t *pr, void *_res) +{ +} + #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) static builtin_t builtins[] = { @@ -411,6 +416,6 @@ RUA_Hash_Init (progs_t *pr, int secure) hash_resources_t *res = calloc (1, sizeof (hash_resources_t)); res->tabs = 0; - PR_Resources_Register (pr, "Hash", res, bi_hash_clear); + PR_Resources_Register (pr, "Hash", res, bi_hash_clear, bi_hash_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index f4cfb0cae..c7e8e97bc 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -480,6 +480,14 @@ bi_input_clear (progs_t *pr, void *_res) Hash_FlushTable (res->cookies); } +static void +bi_input_destroy (progs_t *pr, void *_res) +{ + input_resources_t *res = _res; + Hash_DelTable (res->cookies); + delete_memsuper (res->cookie_super); +} + static uintptr_t rua_in_hash_cookie (const void *_cookie, void *_res) { @@ -513,7 +521,7 @@ RUA_Input_Init (progs_t *pr, int secure) &res->hashctx); Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies); - PR_Resources_Register (pr, "input", res, bi_input_clear); + PR_Resources_Register (pr, "input", res, bi_input_clear, bi_input_destroy); if (secure & 2) { PR_RegisterBuiltins (pr, secure_builtins, res); } else { diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c index 83be30604..632aa8ccc 100644 --- a/libs/ruamoko/rua_mersenne.c +++ b/libs/ruamoko/rua_mersenne.c @@ -147,6 +147,11 @@ bi_mtwist_clear (progs_t *pr, void *_res) state_reset (res); } +static void +bi_mtwist_destroy (progs_t *pr, void *_res) +{ +} + #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) static builtin_t builtins[] = { @@ -164,6 +169,7 @@ RUA_Mersenne_Init (progs_t *pr, int secure) { mtwist_resources_t *res = calloc (1, sizeof (mtwist_resources_t)); - PR_Resources_Register (pr, "Mersenne Twister", res, bi_mtwist_clear); + PR_Resources_Register (pr, "Mersenne Twister", res, bi_mtwist_clear, + bi_mtwist_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_model.c b/libs/ruamoko/rua_model.c index 4f8d5b8c0..4ea5b564a 100644 --- a/libs/ruamoko/rua_model.c +++ b/libs/ruamoko/rua_model.c @@ -103,6 +103,11 @@ bi_rua_model_clear (progs_t *pr, void *_res) rua_model_handle_reset (res); } +static void +bi_rua_model_destroy (progs_t *pr, void *_res) +{ +} + static int alloc_handle (rua_model_resources_t *res, model_t *model) { @@ -177,6 +182,7 @@ RUA_Model_Init (progs_t *pr, int secure) rua_model_resources_t *res = calloc (sizeof (rua_model_resources_t), 1); res->pr = pr; - PR_Resources_Register (pr, "Model", res, bi_rua_model_clear); + PR_Resources_Register (pr, "Model", res, bi_rua_model_clear, + bi_rua_model_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index d3ad525ab..cf1db72e9 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -94,6 +94,11 @@ bi_msgbuf_clear (progs_t *pr, void *data) msgbuf_reset (res); } +static void +bi_msgbuf_destroy (progs_t *pr, void *_res) +{ +} + static int alloc_msgbuf (msgbuf_resources_t *res, byte *buf, int size) { @@ -481,6 +486,7 @@ RUA_MsgBuf_Init (progs_t *pr, int secure) { msgbuf_resources_t *res = calloc (sizeof (msgbuf_resources_t), 1); - PR_Resources_Register (pr, "MsgBuf", res, bi_msgbuf_clear); + PR_Resources_Register (pr, "MsgBuf", res, bi_msgbuf_clear, + bi_msgbuf_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 6b0cdbfaf..7c9875bdb 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -124,6 +124,7 @@ typedef struct probj_resources_s { hashtab_t *classes; hashtab_t *protocols; hashtab_t *load_methods; + obj_list *obj_list_free_list; obj_list *unresolved_classes; obj_list *unclaimed_categories; obj_list *uninitialized_statics; @@ -175,27 +176,25 @@ get_dtable (probj_t *probj, const char *name, int index) return dtable; } -static obj_list *obj_list_free_list; - static obj_list * -obj_list_new (void) +obj_list_new (probj_t *probj) { int i; obj_list *l; - if (!obj_list_free_list) { - obj_list_free_list = calloc (128, sizeof (obj_list)); + if (!probj->obj_list_free_list) { + probj->obj_list_free_list = calloc (128, sizeof (obj_list)); for (i = 0; i < 127; i++) - obj_list_free_list[i].next = &obj_list_free_list[i + 1]; + probj->obj_list_free_list[i].next = &probj->obj_list_free_list[i + 1]; } - l = obj_list_free_list; - obj_list_free_list = l->next; + l = probj->obj_list_free_list; + probj->obj_list_free_list = l->next; l->next = 0; return l; } static void -obj_list_free (obj_list *l) +obj_list_free (probj_t *probj, obj_list *l) { obj_list *e; @@ -204,29 +203,29 @@ obj_list_free (obj_list *l) for (e = l; e->next; e = e->next) ; - e->next = obj_list_free_list; - obj_list_free_list = l; + e->next = probj->obj_list_free_list; + probj->obj_list_free_list = l; } static inline obj_list * -list_cons (void *data, obj_list *next) +list_cons (probj_t *probj, void *data, obj_list *next) { - obj_list *l = obj_list_new (); + obj_list *l = obj_list_new (probj); l->data = data; l->next = next; return l; } static inline void -list_remove (obj_list **list) +list_remove (probj_t *probj, obj_list **list) { if ((*list)->next) { obj_list *l = *list; *list = (*list)->next; l->next = 0; - obj_list_free (l); + obj_list_free (probj, l); } else { - obj_list_free (*list); + obj_list_free (probj, *list); *list = 0; } } @@ -288,7 +287,7 @@ create_tree_of_subclasses_inherited_from (probj_t *probj, pr_class_t *bottom, while (superclass != upper) { tree = class_tree_new (); tree->class = superclass; - tree->subclasses = list_cons (prev, tree->subclasses); + tree->subclasses = list_cons (probj, prev, tree->subclasses); super_class = PR_GetString (pr, superclass->super_class); superclass = (superclass->super_class ? Hash_Find (probj->classes, super_class) @@ -323,7 +322,7 @@ _obj_tree_insert_class (probj_t *probj, class_tree *tree, pr_class_t *class) } node = class_tree_new (); node->class = class; - tree->subclasses = list_cons (node, tree->subclasses); + tree->subclasses = list_cons (probj, node, tree->subclasses); return tree; } if (!class_is_subclass_of_class (probj, class, tree->class)) @@ -339,7 +338,7 @@ _obj_tree_insert_class (probj_t *probj, class_tree *tree, pr_class_t *class) } new_tree = create_tree_of_subclasses_inherited_from (probj, class, tree->class); - tree->subclasses = list_cons (new_tree, tree->subclasses); + tree->subclasses = list_cons (probj, new_tree, tree->subclasses); return tree; } @@ -361,7 +360,8 @@ obj_tree_insert_class (probj_t *probj, pr_class_t *class) } if (!list_node) { tree = _obj_tree_insert_class (probj, 0, class); - probj->class_tree_list = list_cons (tree, probj->class_tree_list); + probj->class_tree_list = list_cons (probj, tree, + probj->class_tree_list); } } @@ -584,7 +584,7 @@ sel_register_typed_name (probj_t *probj, const char *name, const char *types, sel->sel_id = index; sel->sel_types = PR_SetString (pr, types); - l = obj_list_new (); + l = obj_list_new (probj); l->data = sel; l->next = probj->selector_sels[index]; probj->selector_sels[index] = l; @@ -700,7 +700,7 @@ obj_init_protocols (probj_t *probj, pr_protocol_list_t *protos) return; if (!(proto_class = Hash_Find (probj->classes, "Protocol"))) { - probj->unclaimed_proto_list = list_cons (protos, + probj->unclaimed_proto_list = list_cons (probj, protos, probj->unclaimed_proto_list); return; } @@ -821,7 +821,7 @@ obj_send_load (probj_t *probj) pr_class_t *class = probj->unresolved_classes->data; const char *super_class = PR_GetString (pr, class->super_class); while (Hash_Find (probj->classes, super_class)) { - list_remove (&probj->unresolved_classes); + list_remove (probj, &probj->unresolved_classes); if (probj->unresolved_classes) { class = probj->unresolved_classes->data; super_class = PR_GetString (pr, class->super_class); @@ -842,12 +842,12 @@ obj_send_load (probj_t *probj) send_load); obj_postorder_traverse (probj, probj->class_tree_list->data, 0, obj_destroy_class_tree_node); - list_remove (&probj->class_tree_list); + list_remove (probj, &probj->class_tree_list); } //XXX callback //for (m = probj->module_list; m; m = m->next) // obj_create_classes_tree (probj, m->data); - obj_list_free (probj->module_list); + obj_list_free (probj, probj->module_list); probj->module_list = 0; } @@ -1090,10 +1090,9 @@ obj_verror (probj_t *probj, pr_id_t *object, int code, const char *fmt, int coun { progs_t *pr = probj->pr; __auto_type class = &G_STRUCT (pr, pr_class_t, object->class_pointer); - dstring_t *dstr = dstring_newstr (); - PR_Sprintf (pr, dstr, "obj_verror", fmt, count, args); - PR_RunError (pr, "%s: %s", PR_GetString (pr, class->name), dstr->str); + PR_Sprintf (pr, probj->msg, "obj_verror", fmt, count, args); + PR_RunError (pr, "%s: %s", PR_GetString (pr, class->name), probj->msg->str); } static void @@ -1152,7 +1151,7 @@ obj_init_statics (probj_t *probj) } if (initialized) { - list_remove (cell); + list_remove (probj, cell); } else { cell = &(*cell)->next; } @@ -1188,7 +1187,7 @@ rua___obj_exec_class (progs_t *pr, void *data) symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt] ? "yes" : "no"); - probj->module_list = list_cons (module, probj->module_list); + probj->module_list = list_cons (probj, module, probj->module_list); sel = &G_STRUCT (pr, pr_sel_t, symtab->refs); for (i = 0; i < symtab->sel_ref_cnt; i++) { @@ -1242,7 +1241,7 @@ rua___obj_exec_class (progs_t *pr, void *data) } if (class->super_class && !Hash_Find (probj->classes, super_class)) - probj->unresolved_classes = list_cons (class, + probj->unresolved_classes = list_cons (probj, class, probj->unresolved_classes); } @@ -1265,14 +1264,14 @@ rua___obj_exec_class (progs_t *pr, void *data) finish_category (probj, category, class); } else { probj->unclaimed_categories - = list_cons (category, probj->unclaimed_categories); + = list_cons (probj, category, probj->unclaimed_categories); } } if (*ptr) { Sys_MaskPrintf (SYS_rua_obj, "Static instances lists: %x\n", *ptr); probj->uninitialized_statics - = list_cons (&G_STRUCT (pr, pr_ptr_t, *ptr), + = list_cons (probj, &G_STRUCT (pr, pr_ptr_t, *ptr), probj->uninitialized_statics); } if (probj->uninitialized_statics) { @@ -1285,7 +1284,7 @@ rua___obj_exec_class (progs_t *pr, void *data) pr_class_t *class = Hash_Find (probj->classes, class_name); if (class) { - list_remove (cell); + list_remove (probj, cell); finish_category (probj, category, class); } else { cell = &(*cell)->next; @@ -1296,7 +1295,7 @@ rua___obj_exec_class (progs_t *pr, void *data) && Hash_Find (probj->classes, "Protocol")) { for (cell = &probj->unclaimed_proto_list; *cell; ) { obj_init_protocols (probj, (*cell)->data); - list_remove (cell); + list_remove (probj, cell); } } @@ -2044,14 +2043,13 @@ rua__i_Object_error_error_ (progs_t *pr, void *data) probj_t *probj = pr->pr_objective_resources; pr_id_t *self = &P_STRUCT (pr, pr_id_t, 0); const char *fmt = P_GSTRING (pr, 2); - dstring_t *dstr = dstring_new (); int count = pr->pr_argc - 3; pr_type_t **args = &pr->pr_params[3]; - dsprintf (dstr, "error: %s (%s)\n%s", + dsprintf (probj->msg, "error: %s (%s)\n%s", PR_GetString (pr, object_get_class_name (probj, self)), object_is_instance (probj, self) ? "instance" : "class", fmt); - obj_verror (probj, self, 0, dstr->str, count, args); + obj_verror (probj, self, 0, probj->msg->str, count, args); } static int @@ -2281,7 +2279,7 @@ rua_obj_cleanup (progs_t *pr, void *data) probj->available_selectors = 0; probj->selector_block = 0; for (i = 0; i < probj->selector_index_max; i++) { - obj_list_free (probj->selector_sels[i]); + obj_list_free (probj, probj->selector_sels[i]); probj->selector_sels[i] = 0; probj->selector_names[i] = 0; } @@ -2302,6 +2300,18 @@ rua_obj_cleanup (progs_t *pr, void *data) probj->class_tree_list = 0; } +static void +rua_obj_destroy (progs_t *pr, void *_res) +{ + probj_t *probj = _res; + + dstring_delete (probj->msg); + Hash_DelTable (probj->selector_hash); + Hash_DelTable (probj->classes); + Hash_DelTable (probj->protocols); + Hash_DelTable (probj->load_methods); +} + void RUA_Obj_Init (progs_t *pr, int secure) { @@ -2318,7 +2328,8 @@ RUA_Obj_Init (progs_t *pr, int secure) Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, load_methods_compare); - PR_Resources_Register (pr, "RUA_ObjectiveQuakeC", probj, rua_obj_cleanup); + PR_Resources_Register (pr, "RUA_ObjectiveQuakeC", probj, rua_obj_cleanup, + rua_obj_destroy); PR_RegisterBuiltins (pr, obj_methods, probj); PR_AddLoadFunc (pr, rua_obj_init_runtime); diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 1246e1510..b8a72826d 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -106,6 +106,13 @@ bi_plist_clear (progs_t *pr, void *_res) plist_reset (res); } +static void +bi_plist_destroy (progs_t *pr, void *_res) +{ + __auto_type res = (plist_resources_t *) _res; + Hash_DelTable (res->plist_tab); +} + static inline int plist_handle (plist_resources_t *res, plitem_t *plitem) { @@ -486,6 +493,6 @@ RUA_Plist_Init (progs_t *pr, int secure) res->plist_tab = Hash_NewTable (1021, 0, 0, 0, pr->hashctx); Hash_SetHashCompare (res->plist_tab, plist_get_hash, plist_compare); - PR_Resources_Register (pr, "plist", res, bi_plist_clear); + PR_Resources_Register (pr, "plist", res, bi_plist_clear, bi_plist_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index ef748b914..98636cb36 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -95,6 +95,11 @@ bi_qfile_clear (progs_t *pr, void *_res) handle_reset (res); } +static void +bi_qfile_destroy (progs_t *pr, void *_res) +{ +} + static int alloc_handle (qfile_resources_t *res, QFile *file) { @@ -401,7 +406,7 @@ RUA_QFile_Init (progs_t *pr, int secure) { qfile_resources_t *res = calloc (sizeof (qfile_resources_t), 1); - PR_Resources_Register (pr, "QFile", res, bi_qfile_clear); + PR_Resources_Register (pr, "QFile", res, bi_qfile_clear, bi_qfile_destroy); if (secure) { PR_RegisterBuiltins (pr, secure_builtins, res); } else { diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index fc42fab61..09c4cc662 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -655,6 +655,11 @@ bi_scene_clear (progs_t *pr, void *_res) } } +static void +bi_scene_destroy (progs_t *pr, void *_res) +{ +} + void RUA_Scene_Init (progs_t *pr, int secure) { @@ -662,6 +667,6 @@ RUA_Scene_Init (progs_t *pr, int secure) res->pr = pr; - PR_Resources_Register (pr, "Scene", res, bi_scene_clear); + PR_Resources_Register (pr, "Scene", res, bi_scene_clear, bi_scene_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index 592b412d4..d11b41b49 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -91,6 +91,11 @@ bi_script_clear (progs_t *pr, void *_res) script_reset (res); } +static void +bi_script_destroy (progs_t *pr, void *_res) +{ +} + static void bi_Script_New (progs_t *pr, void *_res) { @@ -206,6 +211,7 @@ RUA_Script_Init (progs_t *pr, int secure) { script_resources_t *res = calloc (1, sizeof (script_resources_t)); - PR_Resources_Register (pr, "Script", res, bi_script_clear); + PR_Resources_Register (pr, "Script", res, bi_script_clear, + bi_script_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 40ed15d12..4e7ea12b6 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -803,6 +803,11 @@ res_set_clear (progs_t *pr, void *_res) res_set_iter_reset (res); } +static void +res_set_destroy (progs_t *pr, void *_res) +{ +} + #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) static builtin_t builtins[] = { @@ -863,6 +868,6 @@ RUA_Set_Init (progs_t *pr, int secure) set_resources_t *res = calloc (1, sizeof (set_resources_t)); res->sets = 0; - PR_Resources_Register (pr, "Set", res, res_set_clear); + PR_Resources_Register (pr, "Set", res, res_set_clear, res_set_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 853de0387..319634505 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -327,6 +327,13 @@ bi_draw_clear (progs_t *pr, void *_res) Hash_FlushTable (res->pic_hash); } +static void +bi_draw_destroy (progs_t *pr, void *_res) +{ + draw_resources_t *res = (draw_resources_t *) _res; + Hash_DelTable (res->pic_hash); +} + #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } @@ -354,6 +361,6 @@ R_Progs_Init (progs_t *pr) draw_resources_t *res = calloc (1, sizeof (draw_resources_t)); res->pic_hash = Hash_NewTable (61, bi_draw_get_key, 0, 0, pr->hashctx); - PR_Resources_Register (pr, "Draw", res, bi_draw_clear); + PR_Resources_Register (pr, "Draw", res, bi_draw_clear, bi_draw_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index e82b37a5f..4c85b115a 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -1861,6 +1861,11 @@ bi_curses_clear (progs_t *pr, void *_res) panel_reset (res); } +static void +bi_curses_destroy (progs_t *pr, void *_res) +{ +} + #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } @@ -1963,7 +1968,8 @@ BI_Curses_Init (progs_t *pr) qwaq_init_pipe (&res->commands); qwaq_init_pipe (&res->results); - PR_Resources_Register (pr, "curses", res, bi_curses_clear); + PR_Resources_Register (pr, "curses", res, bi_curses_clear, + bi_curses_destroy); PR_RegisterBuiltins (pr, builtins, res); Sys_RegisterShutdown (bi_shutdown, pr); } diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 49b5f5ba7..4e3420e1c 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -164,6 +164,11 @@ qwaq_debug_clear (progs_t *pr, void *_res) target_reset (debug); } +static void +qwaq_debug_destroy (progs_t *pr, void *_res) +{ +} + static void qwaq_target_clear (progs_t *pr, void *_res) { @@ -173,6 +178,11 @@ qwaq_target_clear (progs_t *pr, void *_res) } } +static void +qwaq_target_destroy (progs_t *pr, void *_res) +{ +} + static int qwaq_target_load (progs_t *pr) { @@ -718,7 +728,8 @@ QWAQ_Debug_Init (progs_t *pr) debug->input = PR_Resources_Find (pr, "input"); PR_AddLoadFunc (pr, qwaq_debug_load); - PR_Resources_Register (pr, "qwaq-debug", debug, qwaq_debug_clear); + PR_Resources_Register (pr, "qwaq-debug", debug, qwaq_debug_clear, + qwaq_debug_destroy); PR_RegisterBuiltins (pr, builtins, debug); } @@ -726,5 +737,6 @@ void QWAQ_DebugTarget_Init (progs_t *pr) { PR_AddLoadFunc (pr, qwaq_target_load); - PR_Resources_Register (pr, "qwaq-target", 0, qwaq_target_clear); + PR_Resources_Register (pr, "qwaq-target", 0, qwaq_target_clear, + qwaq_target_destroy); } diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index 3bc6b2a26..f7f33db8e 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -1017,6 +1017,11 @@ qwaq_ebresources_clear (progs_t *pr, void *_res) editbuffer_reset (res); } +static void +qwaq_ebresources_destroy (progs_t *pr, void *_res) +{ +} + #define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } @@ -1067,6 +1072,7 @@ QWAQ_EditBuffer_Init (progs_t *pr) qwaq_ebresources_t *res = calloc (sizeof (*res), 1); res->pr = pr; - PR_Resources_Register (pr, "qwaq-editbuffer", res, qwaq_ebresources_clear); + PR_Resources_Register (pr, "qwaq-editbuffer", res, qwaq_ebresources_clear, + qwaq_ebresources_destroy); PR_RegisterBuiltins (pr, builtins, res); } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 18470bab0..3ef07279f 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -197,6 +197,11 @@ qwaq_thread_clear (progs_t *pr, void *_thread) { } +static void +qwaq_thread_destroy (progs_t *pr, void *_res) +{ +} + static progs_t * create_progs (qwaq_thread_t *thread) { @@ -212,7 +217,8 @@ create_progs (qwaq_thread_t *thread) pr_debug = 2; pr_boundscheck = 0; PR_Init (pr); - PR_Resources_Register (pr, "qwaq_thread", thread, qwaq_thread_clear); + PR_Resources_Register (pr, "qwaq_thread", thread, qwaq_thread_clear, + qwaq_thread_destroy); RUA_Init (pr, thread->rua_security); common_builtins_init (pr); while (*funcs) { diff --git a/ruamoko/qwaq/builtins/term-input.c b/ruamoko/qwaq/builtins/term-input.c index ce1bf0ba1..544cd3841 100644 --- a/ruamoko/qwaq/builtins/term-input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -889,6 +889,11 @@ bi_input_clear (progs_t *pr, void *_res) } } +static void +bi_input_destroy (progs_t *pr, void *_res) +{ +} + static void bi_input_shutdown (void *_pr) { @@ -915,7 +920,7 @@ BI_TermInput_Init (progs_t *pr) qwaq_init_cond (&res->events.cond); - PR_Resources_Register (pr, "input", res, bi_input_clear); + PR_Resources_Register (pr, "input", res, bi_input_clear, bi_input_destroy); PR_RegisterBuiltins (pr, builtins, res); Sys_RegisterShutdown (bi_input_shutdown, pr); } From 8db8f91e7d7ebfabb263aefbdbebae5088b42489 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 19:01:45 +0900 Subject: [PATCH 2803/3664] [input] Plug a pile of memory leaks While most were "harmless" in that they were held pointers at shutdown, a few bugs were exposed in the imt code. --- include/QF/input/binding.h | 1 + include/QF/input/imt.h | 1 + libs/input/evdev/inputlib.c | 3 ++- libs/input/in_axis.c | 6 ++++++ libs/input/in_binding.c | 13 +++++++++++++ libs/input/in_button.c | 14 +++++++++++++- libs/input/in_common.c | 5 +++++ libs/input/in_evdev.c | 5 +++++ libs/input/in_event.c | 13 +++++++++++++ libs/input/in_imt.c | 17 ++++++++++++++++- 10 files changed, 75 insertions(+), 3 deletions(-) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 02363abe5..86fde3548 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -365,6 +365,7 @@ struct IE_event_s; int IN_Binding_HandleEvent (const struct IE_event_s *ie_event); void IN_Binding_Activate (void); void IN_Binding_Init (void); +void IN_Binding_Shutdown (void); struct plitem_s; void IN_Binding_SaveConfig (struct plitem_s *config); void IN_Binding_LoadConfig (struct plitem_s *config); diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 5f3f8c2d3..5009a57da 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -130,6 +130,7 @@ void IMT_BindButton (imt_t *imt, int button, const char *binding); qboolean IMT_ProcessAxis (int axis, int value); qboolean IMT_ProcessButton (int button, int state); void IMT_Init (void); +void IMT_Shutdown (void); struct plitem_s; void IMT_SaveConfig (struct plitem_s *config); void IMT_SaveAxisConfig (struct plitem_s *axes, int axis_ind, int dev_axis); diff --git a/libs/input/evdev/inputlib.c b/libs/input/evdev/inputlib.c index 02a3611f8..1ac7d15ab 100644 --- a/libs/input/evdev/inputlib.c +++ b/libs/input/evdev/inputlib.c @@ -191,7 +191,6 @@ check_device (const char *path) { device_t *dev; int fd; - dstring_t *buff = dstring_newstr (); fd = open (path, O_RDWR); if (fd == -1) @@ -208,9 +207,11 @@ check_device (const char *path) dev->path = strdup (path); dev->fd = fd; + dstring_t *buff = dstring_newstr (); dev->name = strdup (get_string (fd, EVIOCGNAME, buff)); dev->phys = strdup (get_string (fd, EVIOCGPHYS, buff)); dev->uniq = strdup (get_string (fd, EVIOCGUNIQ, buff)); + dstring_delete (buff); setup_buttons(dev); setup_axes(dev); diff --git a/libs/input/in_axis.c b/libs/input/in_axis.c index ccf061eeb..303cc75ea 100644 --- a/libs/input/in_axis.c +++ b/libs/input/in_axis.c @@ -93,9 +93,15 @@ IN_AxisRemoveListener (in_axis_t *axis, axis_listener_t listener, void *data) } } +static void +in_axis_shutdown (void *data) +{ + Hash_DelTable (axis_tab); +} static void __attribute__((constructor)) in_axis_init (void) { axis_tab = Hash_NewTable (127, axis_get_key, axis_free, 0, 0); + Sys_RegisterShutdown (in_axis_shutdown, 0); } diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index a8ea9d72f..562ac7636 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -788,6 +788,19 @@ IN_Binding_Init (void) } } +void +IN_Binding_Shutdown () +{ + for (in_devbindings_t *db = devbindings_list; db; db = db->next) { + clear_connection (db); + } + for (unsigned i = 0; i < devbindings._size; i++) { + free (devbindings._map[i]); + } + free (devbindings._map); + DARRAY_CLEAR (&known_devices); +} + void IN_Binding_SaveConfig (plitem_t *config) { diff --git a/libs/input/in_button.c b/libs/input/in_button.c index 15d28160d..97e4339ad 100644 --- a/libs/input/in_button.c +++ b/libs/input/in_button.c @@ -62,7 +62,12 @@ button_get_key (const void *b, void *data) static void button_free (void *b, void *data) { - free (b); + regbutton_t *rb = b; + if (rb->button->listeners) { + DARRAY_CLEAR (rb->button->listeners); + free (rb->button->listeners); + } + free (rb); } static void @@ -222,8 +227,15 @@ IN_ButtonRemoveListener (in_button_t *button, button_listener_t listener, } } +static void +in_button_shutdown (void *data) +{ + Hash_DelTable (button_tab); +} + static void __attribute__((constructor)) in_button_init (void) { button_tab = Hash_NewTable (127, button_get_key, button_free, 0, 0); + Sys_RegisterShutdown (in_button_shutdown, 0); } diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 65d53637f..9d9920641 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -539,6 +539,11 @@ IN_shutdown (void *data) rd->driver.shutdown (rd->data); } } + IN_Binding_Shutdown (); + IMT_Shutdown (); + + DARRAY_CLEAR (&in_drivers); + DARRAY_CLEAR (&in_devices); } void diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 73f6cfe77..af49d2677 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -76,6 +76,11 @@ static void in_evdev_shutdown (void *data) { inputlib_close (); + + for (unsigned i = 0; i < devmap._size; i++) { + free (devmap._map[i]); + } + free (devmap._map); } static void diff --git a/libs/input/in_event.c b/libs/input/in_event.c index caa9e9ccb..e5240f3b9 100644 --- a/libs/input/in_event.c +++ b/libs/input/in_event.c @@ -120,3 +120,16 @@ IE_Get_Focus (void) { return focus; } + +static void +in_event_shutdown (void *data) +{ + DARRAY_CLEAR (&ie_handlers); +} + +static void __attribute__((constructor)) +in_event_init (void) +{ + //FIXME see in_evdev + Sys_RegisterShutdown (in_event_shutdown, 0); +} diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 435315d01..5df45d7b8 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -835,6 +835,8 @@ imt_drop_all_f (void) for (size_t i = 0; i < imt->button_bindings.size; i++) { free_button_binding (imt->button_bindings.a[i]); } + DARRAY_CLEAR (&imt->axis_bindings); + DARRAY_CLEAR (&imt->button_bindings); free ((char *) imt->name); free (imt); } @@ -940,6 +942,19 @@ IMT_Init (void) } } +void +IMT_Shutdown (void) +{ + imt_drop_all_f (); + Hash_DelTable (recipe_tab); + + delete_memsuper (binding_mem); + binding_mem = 0; + DARRAY_CLEAR (&axis_blocks); + DARRAY_CLEAR (&button_blocks); + DARRAY_CLEAR (&in_contexts); +} + void IMT_SaveConfig (plitem_t *config) { @@ -1078,8 +1093,8 @@ IMT_SaveButtonConfig (plitem_t *buttons, int button_ind, int dev_button) void IMT_LoadConfig (plitem_t *config) { - imt_reset_blocks (); imt_drop_all_f (); + imt_reset_blocks (); plitem_t *ctx_list = PL_ObjectForKey (config, "contexts"); if (PL_Type (ctx_list) != QFArray) { From edf5c663219d284faa1474fc65032c4a13a4cccc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 19:08:40 +0900 Subject: [PATCH 2804/3664] [cvar] Plug a pile of memory leaks Mostly in user cvars, but also any string vars. --- libs/util/cvar.c | 51 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index dd8e64d84..8c50febc5 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -124,16 +124,17 @@ cvar_destroy (cvar_t *var) if (!(var->flags & CVAR_USER_CREATED)) { Sys_Error ("Attempt to destroy non-user cvar"); } - Hash_Del (user_cvar_hash, var->name); - free (*(char **) var->value.value); - free ((char *) var->name); - free (var); + Hash_Free (user_cvar_hash, Hash_Del (user_cvar_hash, var->name)); } VISIBLE cvar_t * Cvar_FindVar (const char *var_name) { - return (cvar_t*) Hash_Find (cvar_hash, var_name); + cvar_t *var = Hash_Find (cvar_hash, var_name); + if (!var) { + var = Hash_Find (user_cvar_hash, var_name); + } + return var; } VISIBLE cvar_t * @@ -762,6 +763,31 @@ Cvar_CvarList_f (void) Sys_Printf ("------------\n%d variables\n", num_vars); } +static void +cvar_free_memory (void *ele, void *data) +{ + const cvar_t *cvar = ele; + if (!cvar->value.type) { + char **str_value = cvar->value.value; + free (*str_value); + *str_value = 0; + } + + if (cvar->listeners) { + DARRAY_CLEAR (cvar->listeners); + free (cvar->listeners); + } +} + +static void +cvar_shutdown (void *data) +{ + Hash_ForEach (cvar_hash, cvar_free_memory, 0); + Hash_DelTable (cvar_hash); + Hash_DelTable (user_cvar_hash); + Hash_DelTable (calias_hash); +} + static const char * cvar_get_key (const void *c, void *unused) { @@ -769,6 +795,16 @@ cvar_get_key (const void *c, void *unused) return cvar->name; } +static void +cvar_free (void *c, void *unused) +{ + cvar_t *cvar = (cvar_t*)c; + + free (*(char **) cvar->value.value); + free ((char *) cvar->name); + free (cvar); +} + static void calias_free (void *c, void *unused) { @@ -788,8 +824,11 @@ VISIBLE void Cvar_Init_Hash (void) { cvar_hash = Hash_NewTable (1021, cvar_get_key, 0, 0, 0); - user_cvar_hash = Hash_NewTable (1021, cvar_get_key, 0, 0, 0); + user_cvar_hash = Hash_NewTable (1021, cvar_get_key, cvar_free, 0, 0); calias_hash = Hash_NewTable (1021, calias_get_key, calias_free, 0, 0); + + Sys_RegisterShutdown (cvar_shutdown, 0); + } VISIBLE void From 826d66efaf670c5ad90eabb1152432105274e49b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 19:34:51 +0900 Subject: [PATCH 2805/3664] [gib] Plug some memory leaks Builtins seem to leak a little on shutdown. Not sure how they are in a long running app. --- libs/gib/gib_builtin.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libs/gib/gib_builtin.c b/libs/gib/gib_builtin.c index 190ec8373..44e9c4cf2 100644 --- a/libs/gib/gib_builtin.c +++ b/libs/gib/gib_builtin.c @@ -1039,6 +1039,12 @@ GIB_bp4_f (void) { } +static void +gib_builtin_shutdown (void *data) +{ + Hash_DelTable (gib_builtins); +} + void GIB_Builtin_Init (qboolean sandbox) { @@ -1090,4 +1096,6 @@ GIB_Builtin_Init (qboolean sandbox) GIB_Builtin_Add ("bp2", GIB_bp2_f); GIB_Builtin_Add ("bp3", GIB_bp3_f); GIB_Builtin_Add ("bp4", GIB_bp4_f); + + Sys_RegisterShutdown (gib_builtin_shutdown, 0); } From a1d8319b4872a471b35855bc6b21f30a2b3a5d1f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 19:37:35 +0900 Subject: [PATCH 2806/3664] [sound] Don't free realname in the vorbis loader Luckily, it was almost never hit (error condition), but the code doesn't own the pointer. --- libs/audio/renderer/vorbis.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index 5797c4ce5..25e6c000b 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -293,7 +293,6 @@ SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname) if (ov_open_callbacks (file, &vf, 0, 0, callbacks) < 0) { Sys_Printf ("Input does not appear to be an Ogg bitstream.\n"); - free (realname); return -1; } info = vorbis_get_info (&vf); From 4defba825177157e45b46c390643667fec90c426 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 19:41:22 +0900 Subject: [PATCH 2807/3664] [ui] Free the view's children array This would have leaked memory if views were being created and destroyed dynamically instead of just the once-off in the current code. --- libs/ui/view.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ui/view.c b/libs/ui/view.c index ac0c4cbfc..3ffc70662 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -209,6 +209,7 @@ view_delete (view_t *view) view_remove (view->parent, view); while (view->num_children) view_delete (view->children[0]); + free (view->children); free (view); } From ccb56c93e63d8e529d8dd013632294573c149fbc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 19:43:23 +0900 Subject: [PATCH 2808/3664] [client] Free default input config plist Yet another memory leak. --- libs/client/cl_input.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 81d5e32ac..7830aa830 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -456,7 +456,9 @@ CL_Legacy_Init (void) OK_Init (); Cmd_AddCommand ("bind", cl_bind_f, "compatibility wrapper for in_bind"); Cmd_AddCommand ("unbind", cl_unbind_f, "compatibility wrapper for in_bind"); - IN_LoadConfig (PL_GetPropertyList (default_input_config, 0)); + plitem_t *cfg = PL_GetPropertyList (default_input_config, 0); + IN_LoadConfig (cfg); + PL_Free (cfg); } void From 4562e1ea6cdf1f9db724a1df66aa2f01a3d6a245 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 19:47:11 +0900 Subject: [PATCH 2809/3664] [qw] Plug a pile of memory leaks. Whee. --- qw/source/cl_main.c | 57 ++++++++++++++++++++++++----------------- qw/source/cl_skin.c | 1 + qw/source/cl_sys_sdl.c | 2 -- qw/source/cl_sys_unix.c | 2 -- qw/source/cl_sys_win.c | 2 -- 5 files changed, 35 insertions(+), 29 deletions(-) diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 6f9ceb514..f55e7529f 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -519,7 +519,6 @@ CL_Version_f (void) static void CL_SendConnectPacket (void) { - dstring_t *data; double t1, t2; // JACK: Fixed bug where DNS lookups would cause two connects real fast @@ -545,12 +544,11 @@ CL_SendConnectPacket (void) cls.qport = qport; - data = dstring_new (); - dsprintf (data, "%c%c%c%cconnect %i %i %i \"%s\"\n", - 255, 255, 255, 255, PROTOCOL_VERSION, cls.qport, cls.challenge, - Info_MakeString (cls.userinfo, 0)); - Netchan_SendPacket (strlen (data->str), data->str, cls.server_addr); - dstring_delete (data); + const char *data = va (0, "%c%c%c%cconnect %i %i %i \"%s\"\n", + 255, 255, 255, 255, PROTOCOL_VERSION, + cls.qport, cls.challenge, + Info_MakeString (cls.userinfo, 0)); + Netchan_SendPacket (strlen (data), data, cls.server_addr); } /* @@ -625,15 +623,8 @@ CL_Connect_f (void) static void CL_Rcon_f (void) { - static dstring_t *message; netadr_t to; - if (!message) - message = dstring_new (); - - dsprintf (message, "\377\377\377\377rcon %s %s", rcon_password, - Cmd_Args (1)); - if (cls.state >= ca_connected) to = cls.netchan.remote_address; else { @@ -647,7 +638,10 @@ CL_Rcon_f (void) to.port = BigShort (27500); } - Netchan_SendPacket (strlen (message->str) + 1, message->str, to); + + const char *message; + message = va (0, "\377\377\377\377rcon %s %s", rcon_password, Cmd_Args (1)); + Netchan_SendPacket (strlen (message) + 1, message, to); } void @@ -1479,6 +1473,8 @@ CL_Init (void) con_module->data->console->realtime = &con_realtime; con_module->data->console->frametime = &con_frametime; con_module->data->console->quit = CL_Quit_f; + //FIXME need to rethink cbuf connections (they can form a stack) + Cbuf_DeleteStack (con_module->data->console->cbuf); con_module->data->console->cbuf = cl_cbuf; } @@ -1508,7 +1504,9 @@ CL_Init (void) cls.downloadtempname = dstring_newstr (); cls.downloadname = dstring_newstr (); cls.downloadurl = dstring_newstr (); + Info_Destroy (cl.serverinfo); cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING, 0); + free (cl.players); cl.players = calloc (MAX_CLIENTS, sizeof (player_info_t)); // register our commands @@ -1670,18 +1668,16 @@ CL_Init_Cvars (void) void Host_EndGame (const char *message, ...) { - static dstring_t *str; va_list argptr; - if (!str) - str = dstring_new (); - + dstring_t *str = dstring_new (); va_start (argptr, message); dvsprintf (str, message, argptr); va_end (argptr); Sys_Printf ("\n===========================\n"); Sys_Printf ("Host_EndGame: %s\n", str->str); Sys_Printf ("===========================\n\n"); + dstring_delete (str); CL_Disconnect (); @@ -1696,18 +1692,15 @@ Host_EndGame (const char *message, ...) void Host_Error (const char *error, ...) { - static dstring_t *str; static qboolean inerror = false; va_list argptr; if (inerror) Sys_Error ("Host_Error: recursively entered"); - if (!str) - str = dstring_new (); - inerror = true; + dstring_t *str = dstring_new (); va_start (argptr, error); dvsprintf (str, error, argptr); va_end (argptr); @@ -1724,6 +1717,7 @@ Host_Error (const char *error, ...) } else { Sys_Error ("Host_Error: %s", str->str); } + dstring_delete (str); } void @@ -1763,6 +1757,8 @@ Host_ReadConfiguration (const char *cfg_name) Qclose (cfg_file); plitem_t *config = PL_GetPropertyList (cfg, 0); + free (cfg); + if (!config) { return 0; } @@ -2064,6 +2060,9 @@ Host_Init (void) QFS_GamedirCallback (CL_Autoexec); PI_Init (); + Sys_RegisterShutdown (Host_Shutdown, 0); + Sys_RegisterShutdown (Net_LogStop, 0); + Netchan_Init_Cvars (); PR_Init_Cvars (); // FIXME location @@ -2138,4 +2137,16 @@ Host_Shutdown (void *data) Host_WriteConfiguration (); CL_HTTP_Shutdown (); + + if (cl.serverinfo) { + Info_Destroy (cl.serverinfo); + } + Info_Destroy (cls.userinfo); + Cbuf_DeleteStack (cl_stbuf); + dstring_delete (centerprint); + dstring_delete (cls.servername); + dstring_delete (cls.downloadtempname); + dstring_delete (cls.downloadname); + dstring_delete (cls.downloadurl); + free (cl.players); } diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index cbf02c133..00fe557f6 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -217,6 +217,7 @@ skin_f (void *data, const cvar_t *cvar) { char *s = Hunk_TempAlloc (0, strlen (skin) + 1); QFS_StripExtension (skin, s); + free (skin); // cvar allocated one FIXME do in validator? skin = strdup (s); Cvar_Info (0, cvar); } diff --git a/qw/source/cl_sys_sdl.c b/qw/source/cl_sys_sdl.c index 7894094d5..3b610bb59 100644 --- a/qw/source/cl_sys_sdl.c +++ b/qw/source/cl_sys_sdl.c @@ -124,8 +124,6 @@ SDL_main (int argc, char *argv[]) return 1; } #endif - Sys_RegisterShutdown (Host_Shutdown, 0); - Sys_RegisterShutdown (Net_LogStop, 0); Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/qw/source/cl_sys_unix.c b/qw/source/cl_sys_unix.c index d0ef58225..956be135e 100644 --- a/qw/source/cl_sys_unix.c +++ b/qw/source/cl_sys_unix.c @@ -74,8 +74,6 @@ main (int argc, const char **argv) if (!COM_CheckParm ("-noconinput")) fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) | O_NONBLOCK); - Sys_RegisterShutdown (Host_Shutdown, 0); - Sys_RegisterShutdown (Net_LogStop, 0); Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/qw/source/cl_sys_win.c b/qw/source/cl_sys_win.c index 6fe2fbe06..fae730cfc 100644 --- a/qw/source/cl_sys_win.c +++ b/qw/source/cl_sys_win.c @@ -181,8 +181,6 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, if (!tevent) Sys_Error ("Couldn't create event"); - Sys_RegisterShutdown (Host_Shutdown, 0); - Sys_RegisterShutdown (Net_LogStop, 0); Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); From bc674657cbbf73160d505cdbdb63ef7864d65347 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 19:52:00 +0900 Subject: [PATCH 2810/3664] [plugin] Ensure plugins get unloaded during shutdown This included pre-registered (static) plugins. Surprisingly, PI_Shutdown was never called. --- include/QF/plugin.h | 1 - libs/util/plugin.c | 44 +++++++++++++++++++----------------- libs/video/renderer/r_init.c | 4 +--- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/include/QF/plugin.h b/include/QF/plugin.h index cb73f6b7f..2b73cccc2 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -107,7 +107,6 @@ plugin_t *PI_LoadPlugin (const char *, const char *); qboolean PI_UnloadPlugin (plugin_t *); void PI_RegisterPlugins (plugin_list_t *); void PI_Init (void); -void PI_Shutdown (void); // FIXME: we need a generic function to initialize unused fields diff --git a/libs/util/plugin.c b/libs/util/plugin.c index e5bf0ace2..7f5ec18b9 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -235,27 +235,8 @@ PI_Plugin_Unload_f (void) PI_UnloadPlugin (pi); } -/* - PI_Init - - Eventually this function will likely initialize libltdl. It doesn't, yet, - since we aren't using libltdl yet. -*/ -VISIBLE void -PI_Init (void) -{ - PI_InitCvars (); - registered_plugins = Hash_NewTable (253, plugin_get_key, 0, 0, 0); - loaded_plugins = Hash_NewTable(253, loaded_plugin_get_key, - loaded_plugin_delete, 0, 0); - Cmd_AddCommand("plugin_load", PI_Plugin_Load_f, - "load the plugin of the given type name and name"); - Cmd_AddCommand("plugin_unload", PI_Plugin_Unload_f, - "unload the plugin of the given type name and name"); -} - -void -PI_Shutdown (void) +static void +PI_Shutdown (void *data) { void **elems, **cur; @@ -266,7 +247,28 @@ PI_Shutdown (void) free (elems); Hash_DelTable (loaded_plugins); + Hash_DelTable (registered_plugins); +} +/* + PI_Init + + Eventually this function will likely initialize libltdl. It doesn't, yet, + since we aren't using libltdl yet. +*/ +VISIBLE void +PI_Init (void) +{ + Sys_RegisterShutdown (PI_Shutdown, 0); + + PI_InitCvars (); + registered_plugins = Hash_NewTable (253, plugin_get_key, 0, 0, 0); + loaded_plugins = Hash_NewTable(253, loaded_plugin_get_key, + loaded_plugin_delete, 0, 0); + Cmd_AddCommand("plugin_load", PI_Plugin_Load_f, + "load the plugin of the given type name and name"); + Cmd_AddCommand("plugin_unload", PI_Plugin_Unload_f, + "unload the plugin of the given type name and name"); } VISIBLE plugin_t * diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 5b3b53033..4a2f2d89a 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -76,9 +76,7 @@ static U void (*const r_scrapdelete)(rscrap_t *) = R_ScrapDelete; static void R_shutdown (void *data) { - if (vidrendmodule->functions->general->shutdown) { - vidrendmodule->functions->general->shutdown (); - } + PI_UnloadPlugin (vidrendmodule); } VISIBLE void From 4e526702ddb277ce7b97c0300de402a0016a7676 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 20:15:19 +0900 Subject: [PATCH 2811/3664] [nq] Plug some memory leaks and fix a shutdown error The error was introduced by the input memory leak fixes, but the solution is to ensure CL_Shutdown is called before IN_Shutdown. Some of the memory leaks were quite legitimate this time. --- nq/source/cl_main.c | 6 ++++-- nq/source/host.c | 3 +++ nq/source/sbar.c | 6 ++++++ nq/source/sys_sdl.c | 1 - nq/source/sys_unix.c | 1 - nq/source/sys_unixd.c | 1 - nq/source/sys_win.c | 1 - nq/source/sys_wind.c | 1 - 8 files changed, 13 insertions(+), 7 deletions(-) diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index afc421160..c9cf1d66f 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -205,6 +205,8 @@ CL_ReadConfiguration (const char *cfg_name) Qclose (cfg_file); plitem_t *config = PL_GetPropertyList (cfg, 0); + free (cfg); + if (!config) { return 0; } @@ -620,8 +622,6 @@ CL_Init (cbuf_t *cbuf) { byte *basepal, *colormap; - Sys_RegisterShutdown (CL_Shutdown, 0); - basepal = (byte *) QFS_LoadHunkFile (QFS_FOpenFile ("gfx/palette.lmp")); if (!basepal) Sys_Error ("Couldn't load gfx/palette.lmp"); @@ -662,6 +662,8 @@ CL_Init (cbuf_t *cbuf) Cmd_AddCommand ("force_centerview", Force_CenterView_f, "force the view " "to be level"); + Sys_RegisterShutdown (CL_Shutdown, 0); + SZ_Alloc (&cls.message, 1024); CL_SetState (ca_disconnected); } diff --git a/nq/source/host.c b/nq/source/host.c index b1cade921..f79b29856 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -1012,6 +1012,7 @@ Host_ExecConfig (cbuf_t *cbuf, int skip_quakerc) void Host_Init (void) { + Sys_RegisterShutdown (Host_Shutdown, 0); Sys_Printf ("Host_Init\n"); host_cbuf = Cbuf_New (&id_interp); @@ -1052,6 +1053,8 @@ Host_Init (void) con_module->data->console->realtime = &con_realtime; con_module->data->console->frametime = &con_frametime; con_module->data->console->quit = Host_Quit_f; + //FIXME need to rethink cbuf connections (they can form a stack) + Cbuf_DeleteStack (con_module->data->console->cbuf); con_module->data->console->cbuf = host_cbuf; } diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 8e298f6aa..2532d1611 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1003,6 +1003,7 @@ sbar_update_vis (void) void Sbar_Draw (void) { + if (!cl.players) return; //FIXME draw_miniteam sbar_update_vis (); hud_main_view->draw (hud_main_view); } @@ -1491,6 +1492,11 @@ init_hud_views (void) if (hud_frags_view) view_add (hud_inventory_view, hud_frags_view); + if (minifrags_view) + view_add (hud_view, minifrags_view); + if (miniteam_view) + view_add (hud_view, miniteam_view); + view = view_new (0, 0, r_data->vid->conview->xlen, 48, grav_south); view_add (view, hud_view); hud_view = view; diff --git a/nq/source/sys_sdl.c b/nq/source/sys_sdl.c index 70193fd74..21a850023 100644 --- a/nq/source/sys_sdl.c +++ b/nq/source/sys_sdl.c @@ -113,7 +113,6 @@ SDL_main (int argc, char *argv[]) isDedicated = (COM_CheckParm ("-dedicated") != 0); - Sys_RegisterShutdown (Host_Shutdown, 0); Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/nq/source/sys_unix.c b/nq/source/sys_unix.c index 83d61a105..bcf8b801f 100644 --- a/nq/source/sys_unix.c +++ b/nq/source/sys_unix.c @@ -75,7 +75,6 @@ main (int argc, const char **argv) isDedicated = (COM_CheckParm ("-dedicated") != 0); - Sys_RegisterShutdown (Host_Shutdown, 0); Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/nq/source/sys_unixd.c b/nq/source/sys_unixd.c index 2971e2242..b444eb29b 100644 --- a/nq/source/sys_unixd.c +++ b/nq/source/sys_unixd.c @@ -86,7 +86,6 @@ main (int argc, const char **argv) host_parms.argc = com_argc; host_parms.argv = com_argv; - Sys_RegisterShutdown (Host_Shutdown, 0); Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/nq/source/sys_win.c b/nq/source/sys_win.c index eb543d1c9..99cb143dc 100644 --- a/nq/source/sys_win.c +++ b/nq/source/sys_win.c @@ -207,7 +207,6 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, if (!isDedicated) init_handles (hInstance); - Sys_RegisterShutdown (Host_Shutdown, 0); Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); diff --git a/nq/source/sys_wind.c b/nq/source/sys_wind.c index 0f1681278..964e825bf 100644 --- a/nq/source/sys_wind.c +++ b/nq/source/sys_wind.c @@ -69,7 +69,6 @@ main (int argc, const char **argv) host_parms.argc = com_argc; host_parms.argv = com_argv; - Sys_RegisterShutdown (Host_Shutdown, 0); Sys_RegisterShutdown (shutdown_f, 0); Host_Init (); From aabf3e14f8c59d75006007fed2fc813a5b8931a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 22:46:31 +0900 Subject: [PATCH 2812/3664] [model] Support freeing of skin data I doubt it's enough, but it does seem to cover what's needed for glsl (maybe not the actual textures, unsure there, but I think they're recycled). --- include/QF/plugin/vid_render.h | 1 + include/mod_internal.h | 1 + libs/models/skin.c | 8 ++++++++ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_vulkan.c | 1 + nq/source/cl_ents.c | 1 + 8 files changed, 15 insertions(+) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 1bcffe276..377c0e1a3 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -66,6 +66,7 @@ typedef struct vid_model_funcs_s { int alias_cache; void (*Mod_SpriteLoadFrames) (struct mod_sprite_ctx_s *sprite_ctx); + void (*Skin_Free) (struct skin_s *skin); struct skin_s *(*Skin_SetColormap) (struct skin_s *skin, int cmap); struct skin_s *(*Skin_SetSkin) (struct skin_s *skin, int cmap, const char *skinname); diff --git a/include/mod_internal.h b/include/mod_internal.h index af7581266..242e15666 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -104,6 +104,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer, void Mod_LoadSpriteModel (model_t *mod, void *buffer); void Skin_Init (void); +void Skin_Free (skin_t *skin); skin_t *Skin_SetColormap (skin_t *skin, int cmap); skin_t *Skin_SetSkin (skin_t *skin, int cmap, const char *skinname); void Skin_SetTranslation (int cmap, int top, int bottom); diff --git a/libs/models/skin.c b/libs/models/skin.c index 2cbe90839..ebc16d360 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -71,6 +71,14 @@ new_skin (void) return calloc (1, sizeof (skin_t)); } +VISIBLE void +Skin_Free (skin_t *skin) +{ + if (skin) { + free (skin); + } +} + VISIBLE void Skin_SetTranslation (int cmap, int top, int bottom) { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 9d99ca43d..7944e3ada 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -170,6 +170,7 @@ static vid_model_funcs_t model_funcs = { 1, gl_Mod_SpriteLoadFrames, + Skin_Free, Skin_SetColormap, Skin_SetSkin, gl_Skin_SetupSkin, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 132e1f062..9be89b23a 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -81,6 +81,7 @@ static vid_model_funcs_t model_funcs = { 0, glsl_Mod_SpriteLoadFrames, + Skin_Free, Skin_SetColormap, Skin_SetSkin, glsl_Skin_SetupSkin, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index a7d69ada7..a4a532557 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -90,6 +90,7 @@ static vid_model_funcs_t model_funcs = { 1, sw_Mod_SpriteLoadFrames, + Skin_Free, Skin_SetColormap, Skin_SetSkin, sw_Skin_SetupSkin, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 901a55420..267d19424 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -654,6 +654,7 @@ static vid_model_funcs_t model_funcs = { 0, vulkan_Mod_SpriteLoadFrames, + Skin_Free, Skin_SetColormap, Skin_SetSkin, vulkan_Skin_SetupSkin, diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index cdfbe644d..10121f577 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -73,6 +73,7 @@ CL_ClearEnts (void) for (i = 0; i < MAX_EDICTS; i++) { if (cl_entities[i]) { + mod_funcs->Skin_Free (cl_entities[i]->renderer.skin); Scene_DestroyEntity (cl_world.scene, cl_entities[i]); cl_entities[i] = 0; } From 50226a64c308c602b75a2271964294854716468d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 22:47:55 +0900 Subject: [PATCH 2813/3664] [ruamoko] Free buffer used for loading plists That's definitely a leak. --- libs/ruamoko/rua_plist.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index b8a72826d..36ec50b0c 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -202,6 +202,7 @@ bi_PL_GetFromFile (progs_t *pr, void *_res) buf[len] = 0; plitem = PL_GetPropertyList (buf, pr->hashctx); + free (buf); R_INT (pr) = plist_retain (res, plitem); } From a17deb3ef25c31f8b1ef33451b88823f9f2b8240 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 22:48:31 +0900 Subject: [PATCH 2814/3664] [nq] Don't double-allocate timedemo data buffer Looks like a copy/paste error (wild guess: got my fingers tangled in vim). --- nq/source/cl_demo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 538ed10bf..5226251aa 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -669,7 +669,6 @@ CL_TimeDemo_f (void) free (timedemo_data); timedemo_data = 0; } - timedemo_data = calloc (timedemo_runs, sizeof (td_stats_t)); dstring_copystr (demoname, Cmd_Argv (1)); CL_StartTimeDemo (); timedemo_runs = timedemo_count = max (count, 1); From 1f811e631052acaba11f5c05e82f00d6688b330a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 22:49:48 +0900 Subject: [PATCH 2815/3664] [nq] Fix a particularly nasty memory leak Nasty because it was caused by spaghetti (normally, I like the stuff). Drinking-age spaghetti at that. Nicely, this removes the need for one function in sv_ded.c (which is what I think I was trying to achieve). --- nq/source/cl_main.c | 42 +++++++++++++++++++----------------------- nq/source/host.c | 1 - nq/source/sv_ded.c | 5 ----- 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index c9cf1d66f..3ae1994b5 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -231,9 +231,27 @@ CL_ClearMemory (void) SCR_SetFullscreen (0); cls.signon = 0; + SZ_Clear (&cls.message); + + if (cl.viewstate.weapon_entity) { + Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity); + } + if (cl.players) { + int i; + + for (i = 0; i < cl.maxclients; i++) + Info_Destroy (cl.players[i].userinfo); + } + // wipe the entire cl structure __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); cl.viewstate.camera_transform = cam; + + CL_ClearTEnts (); + + SCR_NewScene (0); + + CL_ClearEnts (); } void @@ -267,24 +285,10 @@ CL_InitCvars (void) void CL_ClearState (void) { + CL_ClearMemory (); if (!sv.active) Host_ClearMemory (); - if (cl.viewstate.weapon_entity) { - Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity); - } - if (cl.players) { - int i; - - for (i = 0; i < cl.maxclients; i++) - Info_Destroy (cl.players[i].userinfo); - } - - // wipe the entire cl structure - __auto_type cam = cl.viewstate.camera_transform; - memset (&cl, 0, sizeof (cl)); - cl.viewstate.camera_transform = cam; - cl.viewstate.player_origin = (vec4f_t) {0, 0, 0, 1}; cl.viewstate.chase = 1; cl.viewstate.chasestate = &cl.chasestate; @@ -293,14 +297,6 @@ CL_ClearState (void) SCR_SetFullscreen (0); r_data->lightstyle = cl.lightstyle; - SZ_Clear (&cls.message); - - CL_ClearTEnts (); - - SCR_NewScene (0); - - CL_ClearEnts (); - cl.viewstate.weapon_entity = Scene_CreateEntity (cl_world.scene); CL_Init_Entity (cl.viewstate.weapon_entity); r_data->view_model = cl.viewstate.weapon_entity; diff --git a/nq/source/host.c b/nq/source/host.c index f79b29856..4f42cdec4 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -627,7 +627,6 @@ void Host_ClearMemory (void) { Sys_MaskPrintf (SYS_dev, "Clearing memory\n"); - CL_ClearMemory (); Mod_ClearAll (); if (host_hunklevel) Hunk_FreeToLowMark (0, host_hunklevel); diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index fd0741a7c..167596e74 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -72,11 +72,6 @@ CL_UpdateScreen (double realtime) { } -void -CL_ClearMemory (void) -{ -} - void CL_Cmd_ForwardToServer (void) { From ef87baf339ff5d1c9ea4523a29e31fdb6fb90f6c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 May 2022 23:40:52 +0900 Subject: [PATCH 2816/3664] [model] Undo brush texture changes in 4f58429137 While gcc was quite correct in its warning, all I needed was to explicitly truncate the string. I don't remember why I didn't do that back when I made the changes in 4f58429137, but it works now, and the surrounding code does expect the string to be no more than 15 chars long. This fixes yet another memory leak (but timedemo over multiple runs still leaks like a sieve). --- include/QF/model.h | 2 +- libs/models/brush/model_brush.c | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 308175a5e..89e0b8730 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -89,7 +89,7 @@ typedef struct instsurf_s { } instsurf_t; typedef struct texture_s { - char *name; + char name[16]; unsigned width, height; void *render; // renderer specific data int anim_total; // total tenths in sequence ( 0 = no) diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index a13ed16ba..7632c07f2 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -219,28 +219,26 @@ Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, static void mod_unique_miptex_name (texture_t **textures, texture_t *tx, int ind) { - char *name; + char name[17]; int num = 0, i; - dstring_t *tag = 0; + const char *tag; - name = tx->name; + strncpy (name, tx->name, 16); + name[16] = 0; do { for (i = 0; i < ind; i++) if (textures[i] && !strcmp (textures[i]->name, tx->name)) break; if (i == ind) break; - if (!tag) { - tag = dstring_new (); - } - dsprintf (tag, "%s~%x", name, num++); - tx->name = tag->str; + tag = va (0, "~%x", num++); + strncpy (tx->name, name, 16); + tx->name[15] = 0; + if (strlen (name) + strlen (tag) <= 15) + strcat (tx->name, tag); + else + strcpy (tx->name + 15 - strlen (tag), tag); } while (1); - - if (tag) { - tx->name = dstring_freeze (tag); - free(name); - } } static void @@ -280,7 +278,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) brush->textures[i] = tx; - tx->name = strndup(mt->name, sizeof (mt->name)); + memcpy (tx->name, mt->name, sizeof (tx->name)); mod_unique_miptex_name (brush->textures, tx, i); tx->width = mt->width; tx->height = mt->height; From 3823ea1858b00add2c94a21f63df666fa853a596 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 May 2022 00:55:37 +0900 Subject: [PATCH 2817/3664] [vulkan] Plug some memory leaks I still can't find the run-time leak. I suspect something that accumulates but gets freed on exit. --- libs/video/renderer/vulkan/vulkan_bsp.c | 1 + libs/video/renderer/vulkan/vulkan_lighting.c | 1 + libs/video/renderer/vulkan/vulkan_vid_common.c | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index b1e1bda28..867a3f732 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -484,6 +484,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) vertex_index_base = 0; // holds all the polygon definitions: vertex indices + poly_count "end of // primitive" markers. + free (bctx->polys); bctx->polys = malloc ((index_count + poly_count) * sizeof (uint32_t)); // All usable surfaces have been chained to the (base) texture they use. diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index ddbda0032..e31216d60 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -357,6 +357,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) device->physDev->properties.limits.maxPerStageDescriptorSamplers); lframe->shadowWrite.pImageInfo = lframe->shadowInfo; } + free (shadow_set); free (attach_set); free (lights_set); qfvPopDebug (ctx); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a7764b9b3..4aea38c07 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -549,6 +549,9 @@ destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); } dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); + + free (rp->attachment_images); + free (rp->attachment_views); } static void @@ -591,6 +594,8 @@ Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) destroy_renderframes (ctx, rp); destroy_framebuffers (ctx, rp); + DARRAY_CLEAR (&rp->frames); + free (rp->clearValues); free (rp); } } From 0dca1e1124026b21cd0d80fd30fc5d5dcac38054 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 May 2022 09:50:24 +0900 Subject: [PATCH 2818/3664] [plugin] Pull plugin from list before calling its shutdown This ensures that the plugin's shutdown function won't get called twice in the event of an error in the plugin's unload sequence triggering a second Sys_Shutdown, especially if the plugin is being unloaded as a part of another sub-system's shutdown sequence (which is probably in itself a design mistake, need to look into that). --- libs/util/plugin.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/util/plugin.c b/libs/util/plugin.c index 7f5ec18b9..366822d88 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -396,6 +396,11 @@ PI_LoadPlugin (const char *type, const char *name) VISIBLE qboolean PI_UnloadPlugin (plugin_t *plugin) { + // Remove the plugin from the set of loaded plugins to ensure that a + // shutdown triggered by an error in the unload process doesn't try to + // unload the plugin a second time + loaded_plugin_t *lp = Hash_Del (loaded_plugins, plugin->full_name); + if (plugin && plugin->functions && plugin->functions->general && plugin->functions->general->shutdown) { plugin->functions->general->shutdown (); @@ -405,8 +410,7 @@ PI_UnloadPlugin (plugin_t *plugin) plugin->type); } - // remove from the table of loaded plugins - Hash_Free (loaded_plugins, Hash_Del (loaded_plugins, plugin->full_name)); + Hash_Free (loaded_plugins, lp); if (!plugin->handle) // we didn't load it return true; From ceaac00453b6dbd1381fc6d7716cdf1fddf07e88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 May 2022 10:19:08 +0900 Subject: [PATCH 2819/3664] [vulkan] Free the staging buffer's command buffers Since the staging buffer allocates the command buffers it uses, it needs to free them when it is freed. I think I was confused by the validation layers not complaining about unfreed buffers when shutting down, but that's because destroying the pool (during program shutdown, when the validation layers would complain) frees all the buffers. Thus, due to staging buffers being created and destroyed during the level load process, (rather large) command buffers were piling up like imps in a Doom level. In the process, it was necessary to rearrange some of the shutdown code because vulkan_vid_render_shutdown destroys the shared command pool, but the pool is required for freeing the command buffers, but there was a minor mess of long-lived staging buffers being freed afterwards. That didn't end particularly well. --- include/QF/Vulkan/staging.h | 1 + libs/video/renderer/vid_render_vulkan.c | 8 ++++++-- libs/video/renderer/vulkan/staging.c | 5 +++++ libs/video/renderer/vulkan/vulkan_vid_common.c | 1 - 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/QF/Vulkan/staging.h b/include/QF/Vulkan/staging.h index 9058e3c9a..5f00b9022 100644 --- a/include/QF/Vulkan/staging.h +++ b/include/QF/Vulkan/staging.h @@ -13,6 +13,7 @@ typedef struct qfv_packet_s { typedef struct qfv_stagebuf_s { struct qfv_device_s *device; + VkCommandPool cmdPool; VkBuffer buffer; VkDeviceMemory memory; RING_BUFFER(qfv_packet_t, 4) packets; ///< packets for controlling access diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 267d19424..a727cbf26 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -60,6 +60,7 @@ #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" +#include "QF/Vulkan/staging.h" #include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/swapchain.h" #include "QF/ui/view.h" @@ -693,8 +694,6 @@ vulkan_vid_render_shutdown (void) qfv_devfuncs_t *df = device->funcs; VkDevice dev = device->dev; QFV_DeviceWaitIdle (device); - df->vkDestroyFence (dev, vulkan_ctx->fence, 0); - df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); Mod_ClearAll (); @@ -710,6 +709,11 @@ vulkan_vid_render_shutdown (void) Vulkan_Texture_Shutdown (vulkan_ctx); Vulkan_DestroyRenderPasses (vulkan_ctx); + + QFV_DestroyStagingBuffer (vulkan_ctx->staging); + df->vkDestroyFence (dev, vulkan_ctx->fence, 0); + df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); + Vulkan_Shutdown_Common (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 22f96f40b..09b54954d 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -49,6 +49,7 @@ QFV_CreateStagingBuffer (qfv_device_t *device, const char *name, size_t size, stage->atom_mask = atom - 1; size = (size + stage->atom_mask) & ~stage->atom_mask; stage->device = device; + stage->cmdPool = cmdPool; stage->buffer = QFV_CreateBuffer (device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, stage->buffer, @@ -96,14 +97,18 @@ QFV_DestroyStagingBuffer (qfv_stagebuf_t *stage) int count = RB_buffer_size (&stage->packets); __auto_type fences = QFV_AllocFenceSet (count, alloca); + __auto_type cmdBuf = QFV_AllocCommandBufferSet (count, alloca); for (int i = 0; i < count; i++) { fences->a[i] = stage->packets.buffer[i].fence; + cmdBuf->a[i] = stage->packets.buffer[i].cmd; } dfunc->vkWaitForFences (device->dev, fences->size, fences->a, VK_TRUE, 5000000000ull); for (int i = 0; i < count; i++) { dfunc->vkDestroyFence (device->dev, fences->a[i], 0); } + dfunc->vkFreeCommandBuffers (device->dev, stage->cmdPool, + cmdBuf->size, cmdBuf->a); dfunc->vkUnmapMemory (device->dev, stage->memory); dfunc->vkFreeMemory (device->dev, stage->memory, 0); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 4aea38c07..a3d299001 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -235,7 +235,6 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } - QFV_DestroyStagingBuffer (ctx->staging); ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, ctx->surface, 0); clear_table (&ctx->pipelineLayouts); From 0b9d36b08d32366a226fb3f54b400e13274ddde9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 May 2022 20:51:37 +0900 Subject: [PATCH 2820/3664] [nq] Fix some level change segfaults I really need to play more while working on the code. Anyway, ca_active works nicely for the status bar in general, and CL_ClearMemory needs to be called before Host_ClearMemory when doing single-player. --- nq/include/host.h | 2 ++ nq/source/cl_main.c | 2 ++ nq/source/host.c | 17 +++++++++++++++++ nq/source/sbar.c | 4 +++- nq/source/sv_main.c | 2 +- 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/nq/include/host.h b/nq/include/host.h index 460188eb4..dae61381e 100644 --- a/nq/include/host.h +++ b/nq/include/host.h @@ -56,6 +56,8 @@ extern double realtime; // not bounded in any way, changed at extern struct cbuf_s *host_cbuf; void Host_ClearMemory (void); +void Host_SpawnServer (void); +void Host_OnServerSpawn (void (*onSpawn)(void)); void Host_ServerFrame (void); void Host_InitCommands (void); void Host_Init (void); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 3ae1994b5..58628e0fd 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -625,6 +625,8 @@ CL_Init (cbuf_t *cbuf) if (!colormap) Sys_Error ("Couldn't load gfx/colormap.lmp"); + Host_OnServerSpawn (CL_ClearMemory); + W_LoadWadFile ("gfx.wad"); VID_Init (basepal, colormap); IN_Init (); diff --git a/nq/source/host.c b/nq/source/host.c index 4f42cdec4..da90dc94a 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -42,6 +42,7 @@ #include "QF/image.h" #include "QF/input.h" #include "QF/keys.h" +#include "QF/listener.h" #include "QF/msg.h" #include "QF/png.h" #include "QF/progs.h" @@ -632,6 +633,22 @@ Host_ClearMemory (void) Hunk_FreeToLowMark (0, host_hunklevel); } +static struct LISTENER_SET_TYPE(void) host_server_spawn = LISTENER_SET_STATIC_INIT(4); + +void +Host_SpawnServer (void) +{ + LISTENER_INVOKE (&host_server_spawn, NULL); + Host_ClearMemory (); +} + +void +Host_OnServerSpawn (void (*onSpawn) (void)) +{ + LISTENER_ADD (&host_server_spawn, + (void(*)(void *, const void*)) onSpawn, 0); +} + /* Host_FilterTime diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 2532d1611..8287adf13 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1003,7 +1003,9 @@ sbar_update_vis (void) void Sbar_Draw (void) { - if (!cl.players) return; //FIXME draw_miniteam + if (cls.state != ca_active) { + return; + } sbar_update_vis (); hud_main_view->draw (hud_main_view); } diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 04a6bf048..e89c8c82b 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -1113,7 +1113,7 @@ SV_SpawnServer (const char *server) skill = current_skill; // set up the new server - Host_ClearMemory (); + Host_SpawnServer (); memset (&sv, 0, sizeof (sv)); From a2d50395d6424d73e90d02d76e5d540e7c401e71 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 18 May 2022 09:41:41 +0900 Subject: [PATCH 2821/3664] [qw] Correct client shutdown order This is similar to the change in nq (and for the same reason), making sure that client shutdown (and thus config writing) happens before input system shutdown. --- qw/include/host.h | 2 -- qw/source/cl_main.c | 63 +++++++++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/qw/include/host.h b/qw/include/host.h index ab0a18770..beda8bec1 100644 --- a/qw/include/host.h +++ b/qw/include/host.h @@ -48,13 +48,11 @@ extern int host_framecount; // incremented every frame, never reset void Host_ServerFrame (void); void Host_InitCommands (void); void Host_Init (void); -void Host_Shutdown(void *data); void Host_Error (const char *error, ...) __attribute__((format(PRINTF,1,2), noreturn)); void Host_EndGame (const char *message, ...) __attribute__((format(PRINTF,1,2), noreturn)); void Host_Frame (float time); void Host_Quit_f (void); void Host_ClientCommands (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); -void Host_ShutdownServer (qboolean crash); typedef struct { diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index f55e7529f..77c39fb4d 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1446,6 +1446,36 @@ CL_SetState (cactive_t state) } } +static void +CL_Shutdown (void *data) +{ + static qboolean isdown = false; + + if (isdown) { + printf ("recursive shutdown\n"); + return; + } + isdown = true; + + SL_Shutdown (); + + Host_WriteConfiguration (); + + CL_HTTP_Shutdown (); + + if (cl.serverinfo) { + Info_Destroy (cl.serverinfo); + } + Info_Destroy (cls.userinfo); + Cbuf_DeleteStack (cl_stbuf); + dstring_delete (centerprint); + dstring_delete (cls.servername); + dstring_delete (cls.downloadtempname); + dstring_delete (cls.downloadname); + dstring_delete (cls.downloadurl); + free (cl.players); +} + void CL_Init (void) { @@ -1497,6 +1527,8 @@ CL_Init (void) Locs_Init (); V_Init (&cl.viewstate); + Sys_RegisterShutdown (CL_Shutdown, 0); + Info_SetValueForStarKey (cls.userinfo, "*ver", QW_VERSION, 0); centerprint = dstring_newstr (); @@ -2060,7 +2092,6 @@ Host_Init (void) QFS_GamedirCallback (CL_Autoexec); PI_Init (); - Sys_RegisterShutdown (Host_Shutdown, 0); Sys_RegisterShutdown (Net_LogStop, 0); Netchan_Init_Cvars (); @@ -2120,33 +2151,3 @@ Host_Init (void) } Cbuf_AddText (cl_cbuf, "set cmd_warncmd 1\n"); } - -void -Host_Shutdown (void *data) -{ - static qboolean isdown = false; - - if (isdown) { - printf ("recursive shutdown\n"); - return; - } - isdown = true; - - SL_Shutdown (); - - Host_WriteConfiguration (); - - CL_HTTP_Shutdown (); - - if (cl.serverinfo) { - Info_Destroy (cl.serverinfo); - } - Info_Destroy (cls.userinfo); - Cbuf_DeleteStack (cl_stbuf); - dstring_delete (centerprint); - dstring_delete (cls.servername); - dstring_delete (cls.downloadtempname); - dstring_delete (cls.downloadname); - dstring_delete (cls.downloadurl); - free (cl.players); -} From 7abdfc421ef02145e6c30e3a80813078845b9adf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 18 May 2022 11:02:42 +0900 Subject: [PATCH 2822/3664] [nq] Enable blue and red lights for quad and invulnerability I got tired of being disappointed that nq didn't have colored lights for the power-ups (especially when I'd waste time thinking it was a bug). The problem is that the server (progs code) specifies only DIMLIGHT (qw adds in the colors). Another problem is that the server tells us only our own stats, so the colors are disabled for multiplayer otherwise it might be confusing. --- nq/source/cl_ents.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 10121f577..6ed56e917 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -317,7 +317,20 @@ CL_RelinkEntities (void) } CL_EntityEffects (i, ent, new, cl.time); vec4f_t org = Transform_GetWorldPosition (ent->transform); - CL_NewDlight (i, org, new->effects, new->glow_size, + int effects = new->effects; + if (cl.maxclients == 1 && effects) { + // Enable blue and red lights for quad and invulnerability, + // but only for single-player as such information isn't provided + // by the server for other players and thus it would probably be + // confusing if the player could see the colored effects but not + // for others. + int it = cl.stats[STAT_ITEMS]; + effects |= (it & IT_QUAD) + >> (BITOP_LOG2(IT_QUAD) - BITOP_LOG2 (EF_BLUE)); + effects |= (it & IT_INVULNERABILITY) + >> (BITOP_LOG2(IT_INVULNERABILITY) - BITOP_LOG2 (EF_RED)); + } + CL_NewDlight (i, org, effects, new->glow_size, new->glow_color, cl.time); if (VectorDistance_fast (old->origin, org) > (256 * 256)) { old->origin = org; From cfe70647080addbd25170ae0b7902b9d2489db09 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 May 2022 13:23:34 +0900 Subject: [PATCH 2823/3664] [nq] Update weapon model for SU_WEAPON2 This fixes the missing view weapon in vulkan and crashes in other renderers when playing Conflagrant Rodent. --- nq/source/cl_parse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index db35c61fd..b8c1df2b2 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -655,8 +655,10 @@ CL_ParseClientdata (void) } } - if (bits & SU_WEAPON2) + if (bits & SU_WEAPON2) { cl.stats[STAT_WEAPON] |= MSG_ReadByte (net_message) << 8; + cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]]; + } if (bits & SU_ARMOR2) cl.stats[STAT_ARMOR] |= MSG_ReadByte (net_message) << 8; if (bits & SU_AMMO2) From 54b65734700e978c3c0dab4932622d171f3ced52 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 May 2022 22:54:47 +0900 Subject: [PATCH 2824/3664] [client] Change location of sun vector negation Moving the negation into the calculation of the sun angle prevents -0 getting into the vector (not that it makes much difference other than minor confusion when reading the light data). --- libs/client/cl_light.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index 5af325739..0bc3e8287 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -91,10 +91,12 @@ static vec4f_t sun_vector (const vec_t *ang) { // ang is yaw, pitch (maybe roll, but ignored + // negative as the vector points *to* the sun, but ang specifies the + // direction from the sun vec4f_t vec = { - ecos (ang[1]) * ecos (ang[0]), - ecos (ang[1]) * esin (ang[0]), - esin (ang[1]), + -ecos (ang[1]) * ecos (ang[0]), + -ecos (ang[1]) * esin (ang[0]), + -esin (ang[1]), 0, }; return vec; @@ -120,7 +122,7 @@ parse_sun (lightingdata_t *ldata, plitem_t *entity) } VectorSet (1, 1, 1, light.color); light.color[3] = sunlight; - light.position = -sun_vector (sunangle); + light.position = sun_vector (sunangle); light.direction = light.position; light.direction[3] = 1; light.attenuation = (vec4f_t) { 0, 0, 1, 0 }; From 9429539f2fde87a686c43dcdb3e3c01ed3040751 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 May 2022 22:56:17 +0900 Subject: [PATCH 2825/3664] [qfbsp] Print node and leaf info Maximum tree depth, number of nodes in a model, and max faces per node and leaf. --- tools/qfbsp/source/info.c | 79 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/tools/qfbsp/source/info.c b/tools/qfbsp/source/info.c index d641dd9d5..5eeef52fd 100644 --- a/tools/qfbsp/source/info.c +++ b/tools/qfbsp/source/info.c @@ -49,6 +49,52 @@ static lumpinfo_t lump_info[] = { { "models", O(models), O(nummodels) }, }; +typedef struct { + int count; + int depth; + uint32_t node_faces; + uint32_t leaf_faces; +} nodedata_t; + +static void +get_nodedata (int node, nodedata_t *data, int depth) +{ + if (node < 0) { + // hit a leaf, no surfaces + if (depth > data->depth) { + data->depth = depth; + } + dleaf_t *leaf = bsp->leafs + ~node; + if (leaf->nummarksurfaces > data->leaf_faces) { + data->leaf_faces = leaf->nummarksurfaces; + } + return; + } + data->count++; + dnode_t *dnode = &bsp->nodes[node]; + if (dnode->numfaces > data->node_faces) { + data->node_faces = dnode->numfaces; + } + get_nodedata (dnode->children[0], data, depth + 1); + get_nodedata (dnode->children[1], data, depth + 1); +} + +static void +get_clipdata (int node, nodedata_t *data, int depth) +{ + if (node < 0 || (uint32_t) node >= bsp->numclipnodes) { + // hit contents + if (depth > data->depth) { + data->depth = depth; + } + return; + } + data->count++; + dclipnode_t *cnode = &bsp->clipnodes[node]; + get_clipdata (cnode->children[0], data, depth + 1); + get_clipdata (cnode->children[1], data, depth + 1); +} + void bspinfo () { @@ -75,10 +121,41 @@ bspinfo () printf (" maxs : [%g, %g, %g]\n", VectorExpand (model->maxs)); printf (" origin : [%g, %g, %g]\n", VectorExpand (model->origin)); printf (" headnode:"); + nodedata_t nodedata[MAX_MAP_HULLS] = {}; for (int j = 0; j < MAX_MAP_HULLS; j++) { - printf (" %d", model->headnode[j]); + int k; + for (k = 1; k < j; k++) { + if (model->headnode[j] == model->headnode[k]) { + nodedata[j] = nodedata[k]; + break; + } + } + if (k >= j) { + if (j) { + get_clipdata (model->headnode[j], &nodedata[j], 0); + } else { + get_nodedata (model->headnode[j], &nodedata[j], 0); + } + } + printf (" %5d", model->headnode[j]); + } + printf ("\n nodes:"); + for (int j = 0; j < MAX_MAP_HULLS; j++) { + if (model->headnode[j] < model->headnode[0]) { + continue; + } + printf (" %5d", nodedata[j].count); + } + printf ("\n depth:"); + for (int j = 0; j < MAX_MAP_HULLS; j++) { + if (model->headnode[j] < model->headnode[0]) { + continue; + } + printf (" %5d", nodedata[j].depth); } printf ("\n"); + printf (" max faces: n: %d l:%d\n", + nodedata[0].node_faces, nodedata[0].leaf_faces); printf (" visleafs: %d\n", model->visleafs); printf (" faces : %7d %7d\n", model->firstface, model->numfaces); } From 9237d83b565d41cbafdc29383426de5591fce4b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 May 2022 22:57:41 +0900 Subject: [PATCH 2826/3664] [vulkan] Fix some comments and developer output --- include/QF/Vulkan/renderpass.h | 4 ++-- libs/video/renderer/vulkan/swapchain.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index 4aa954c16..9648e841e 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -69,8 +69,8 @@ typedef struct clearvalueset_s DARRAY_TYPE (VkClearValue) clearvalueset_t; typedef struct qfv_renderpass_s { - vec4f_t color; // for bebugging - const char *name; // for bebugging + vec4f_t color; // for debugging + const char *name; // for debugging struct plitem_s *renderpassDef; VkRenderPass renderpass; clearvalueset_t *clearValues; diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index 278b27f70..d55c5e4eb 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -71,13 +71,13 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) } else { imageSize = surfCaps.currentExtent; } - Sys_MaskPrintf (SYS_vulkan, "%d [%d, %d]\n", numImages, + Sys_MaskPrintf (SYS_vulkan, "swapchain: %d [%d, %d]\n", numImages, imageSize.width, imageSize.height); VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; imageUsage &= surfCaps.supportedUsageFlags; - Sys_MaskPrintf (SYS_vulkan, "%x %x\n", imageUsage, + Sys_MaskPrintf (SYS_vulkan, " usage:%x supported:%x\n", imageUsage, surfCaps.supportedUsageFlags); VkSurfaceTransformFlagBitsKHR surfTransform From e1e4bf5659e5c3de8b7ac2907d76bffb5db372af Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 May 2022 10:47:51 +0900 Subject: [PATCH 2827/3664] [vulkan] Up the light limit to 768 For now, at least (I have some ideas to possibly reduce the numbers and also to avoid the need for actual limits). I've seen gmsp3v2 use over 500 lights at once (it has over 1300), and I spent too long figuring out that weird light behavior was due to the limit being hit and lights getting dropped (and even longer figuring out that more weird behavior was due to the lack of shadows and the world being too bright in the first place). --- include/QF/Vulkan/qf_lighting.h | 2 +- libs/video/renderer/vulkan/qfpipeline.plist | 16 ++++++++-------- libs/video/renderer/vulkan/shader/lighting.frag | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index ef6a6bb24..9de79a94b 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -41,7 +41,7 @@ typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t; -#define MaxLights 256 +#define MaxLights 768 #define ST_NONE 0 // no shadows #define ST_PLANE 1 // single plane shadow map (small spotlight) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 33fef28d3..2ee0f5846 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -170,7 +170,7 @@ bindings = ( { type = combined_image_sampler; - descriptorCount = "$frames.size * size_t($properties.limits.maxSamplers)"; + descriptorCount = 768;//"$frames.size * size_t($properties.limits.maxSamplers)"; }, ); }; @@ -291,7 +291,7 @@ { binding = 0; descriptorType = combined_image_sampler; - descriptorCount = $properties.limits.maxSamplers; + descriptorCount = 768;//$properties.limits.maxSamplers; stageFlags = fragment; }, ); @@ -1035,12 +1035,12 @@ stage = fragment; name = main; module = $builtin/lighting.frag; - specializationInfo = { - mapEntries = ( - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(uint($properties.limits.maxSamplers))"; - }; + //specializationInfo = { + // mapEntries = ( + // { size = 4; offset = 0; constantID = 0; }, + // ); + // data = "array(uint($properties.limits.maxSamplers))"; + //}; }, ); layout = lighting_layout; diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 41ee21629..4b8e516cf 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -29,7 +29,7 @@ struct LightData { #define ST_CASCADE (2 << 10) // cascaded shadow maps #define ST_CUBE (3 << 10) // cubemap (omni, large spotlight) -layout (constant_id = 0) const int MaxLights = 256; +layout (constant_id = 0) const int MaxLights = 768; layout (set = 2, binding = 0) uniform sampler2DArrayShadow shadowCascade[MaxLights]; layout (set = 2, binding = 0) uniform sampler2DShadow shadowPlane[MaxLights]; From 775f3b87a87e2e593223a8fa923b0c9cd34d1d45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 May 2022 10:54:34 +0900 Subject: [PATCH 2828/3664] [bsp] Add a comment about leaf marksurfaces They should probably be cause leafsurfaces since they are the actual surfaces of the leaf: ie, the faces of the leaf mesh if each leaf was sub-sub-model. --- include/QF/bspfile.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/QF/bspfile.h b/include/QF/bspfile.h index 18586564d..1232c4f09 100644 --- a/include/QF/bspfile.h +++ b/include/QF/bspfile.h @@ -201,6 +201,8 @@ typedef struct dleaf_s { float mins[3]; // for frustum culling float maxs[3]; + // the list of marksurfaces is the surfaces that make up the effective + // mesh of the leaf uint32_t firstmarksurface; uint32_t nummarksurfaces; From d3965af2ae0af6c26c93442b1008ccf59c837e14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 May 2022 10:57:48 +0900 Subject: [PATCH 2829/3664] [scene] Improve directional light handling While it wasn't the root cause of the disappearing lights (even after sorting out the light limit issue), because the cause of that was everything working as designed, I suspect sunlight wasn't reaching as far as it should. Even it it was, this should be slightly faster (especially for larger maps) as leafs can be tested 32 or 64 at a time rather than individually. --- libs/scene/light.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/scene/light.c b/libs/scene/light.c index 3b1d1bd3c..a8e82160f 100644 --- a/libs/scene/light.c +++ b/libs/scene/light.c @@ -132,14 +132,13 @@ Light_FindVisibleLights (lightingdata_t *ldata) if (leaf == model->brush.leafs) { set_everything (ldata->pvs); + flags = SURF_DRAWSKY; } else { Mod_LeafPVS_set (leaf, model, 0, ldata->pvs); - expand_pvs (ldata->pvs, model); - } - for (unsigned i = 0; i < model->brush.visleafs; i++) { - if (set_is_member (ldata->pvs, i)) { - flags |= model->brush.leaf_flags[i + 1]; + if (set_is_intersecting (ldata->pvs, ldata->sun_pvs)) { + flags |= SURF_DRAWSKY; } + expand_pvs (ldata->pvs, model); } ldata->leaf = leaf; @@ -156,7 +155,8 @@ Light_FindVisibleLights (lightingdata_t *ldata) visible++; } } - //Sys_Printf ("find_visible_lights: %d / %zd visible\n", visible, - // ldata->lightvis.size); + Sys_MaskPrintf (SYS_lighting, + "find_visible_lights: %d / %zd visible\n", visible, + ldata->lightvis.size); } } From 27de599ac4a6a8a9b0f7f56bc52466f09327b98e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 10 May 2022 11:15:52 +0900 Subject: [PATCH 2830/3664] [vulkan] Resurrect the shadow map resource creation However, this time it doesn't modify the light array when it sorts the lights by size since the lights are now located before the renderer gets to see them, and having the fix up the light leafs array would be too painful (and probably the completely wrong thing to do anyway: the light array should be treated as constant by the renderer). 1.6GB of memory for gmsp3v2's lights (a little better than marcher: more smaller lights?). For reference: gmsp3v2: shadow maps: 8330 layers in 29 images: 1647706112 marcher: shadow maps: 2440 layers in 11 images: 2358575104 --- .../renderer/vulkan/shader/lighting.frag | 55 ++++++++------- libs/video/renderer/vulkan/vulkan_lighting.c | 67 ++++++++++++------- 2 files changed, 70 insertions(+), 52 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/lighting.frag b/libs/video/renderer/vulkan/shader/lighting.frag index 4b8e516cf..3e100a55c 100644 --- a/libs/video/renderer/vulkan/shader/lighting.frag +++ b/libs/video/renderer/vulkan/shader/lighting.frag @@ -88,36 +88,35 @@ main (void) vec3 p = subpassLoad (position).rgb; vec3 light = vec3 (0); - if (MaxLights > 0) { - vec3 minLight = vec3 (0); - for (int i = 0; i < lightCount; i++) { - LightData l = lights[i]; - vec3 dir = l.position.xyz - l.position.w * p; - float r2 = dot (dir, dir); - vec4 a = l.attenuation; + //vec3 minLight = vec3 (0); + for (int i = 0; i < lightCount; i++) { + LightData l = lights[i]; + vec3 dir = l.position.xyz - l.position.w * p; + float r2 = dot (dir, dir); + vec4 a = l.attenuation; - if (l.position.w * a.w * a.w * r2 >= 1) { - continue; - } - vec4 r = vec4 (r2, sqrt(r2), 1, 0); - vec3 incoming = dir / r.y; - float I = (1 - a.w * r.y) / dot (a, r); - - /*int shadow = lights[i].data & ShadowMask; - if (shadow == ST_CASCADE) { - I *= shadow_cascade (shadowCascade[i]); - } else if (shadow == ST_PLANE) { - I *= shadow_plane (shadowPlane[i]); - } else if (shadow == ST_CUBE) { - I *= shadow_cube (shadowCube[i]); - }*/ - - float namb = dot(l.direction.xyz, l.direction.xyz); - I *= spot_cone (l, incoming) * diffuse (incoming, n); - I = mix (1, I, namb); - light += I * l.color.w * l.color.xyz; + if (l.position.w * a.w * a.w * r2 >= 1) { + continue; } - light = max (light, minLight); + vec4 r = vec4 (r2, sqrt(r2), 1, 0); + vec3 incoming = dir / r.y; + float I = (1 - a.w * r.y) / dot (a, r); + + /*int shadow = lights[i].data & ShadowMask; + if (shadow == ST_CASCADE) { + I *= shadow_cascade (shadowCascade[i]); + } else if (shadow == ST_PLANE) { + I *= shadow_plane (shadowPlane[i]); + } else if (shadow == ST_CUBE) { + I *= shadow_cube (shadowCube[i]); + }*/ + + float namb = dot(l.direction.xyz, l.direction.xyz); + I *= spot_cone (l, incoming) * diffuse (incoming, n); + I = mix (1, I, namb); + light += I * l.color.w * l.color.xyz; } + //light = max (light, minLight); + frag_color = vec4 (c * light + e, 1); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index e31216d60..89d2b6264 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -43,6 +43,7 @@ #include "QF/cvar.h" #include "QF/dstring.h" +#include "QF/heapsort.h" #include "QF/plist.h" #include "QF/progs.h" #include "QF/script.h" @@ -372,6 +373,7 @@ clear_shadows (vulkan_ctx_t *ctx) if (lctx->shadow_memory) { dfunc->vkFreeMemory (device->dev, lctx->shadow_memory, 0); + lctx->shadow_memory = 0; } for (size_t i = 0; i < lctx->lightviews.size; i++) { dfunc->vkDestroyImageView (device->dev, lctx->lightviews.a[i], 0); @@ -405,7 +407,7 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) free (lctx->frames.a); free (lctx); } -#if 0 + static vec4f_t ref_direction = { 0, 0, 1, 0 }; static void @@ -464,10 +466,13 @@ create_light_matrices (lightingctx_t *lctx) } static int -light_compare (const void *_l2, const void *_l1) +light_compare (const void *_li2, const void *_li1, void *_ldata) { - const light_t *l1 = _l1; - const light_t *l2 = _l2; + const int *li1 = _li1; + const int *li2 = _li2; + lightingdata_t *ldata = _ldata; + const light_t *l1 = &ldata->lights.a[*li1]; + const light_t *l2 = &ldata->lights.a[*li2]; if (l1->color[3] == l2->color[3]) { return (l1->position[3] == l2->position[3]) @@ -572,17 +577,22 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) int totalLayers = 0; int *imageMap = alloca (numLights * sizeof (int)); size_t memsize = 0; + int *lightMap = alloca (numLights * sizeof (int)); + for (int i = 0; i < numLights; i++) { + lightMap[i] = i; + } DARRAY_RESIZE (&lctx->lightlayers, numLights); - qsort (lights, numLights, sizeof (light_t), light_compare); + heapsort_r (lightMap, numLights, sizeof (int), light_compare, ldata); for (int i = 0; i < numLights; i++) { int layers = 1; int shadow = ST_NONE; + int li = lightMap[i]; - if (!lights[i].position[3]) { + if (!lights[li].position[3]) { shadow = ST_CASCADE; } else { - if (lights[i].direction[3] > -0.5) { + if (lights[li].direction[3] > -0.5) { shadow = ST_CUBE; } else { shadow = ST_PLANE; @@ -591,23 +601,23 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) if (shadow == ST_CASCADE || shadow == ST_NONE) { // cascade shadows will be handled separately, and "none" has no // shadow map at all - imageMap[i] = -1; + imageMap[li] = -1; continue; } if (shadow == ST_CUBE) { layers = 6; } - if (size != (int) lights[i].color[3] + if (size != (int) lights[li].color[3] || numLayers + layers > maxLayers) { if (numLayers) { VkImage shadow_map = create_map (size, numLayers, 1, ctx); DARRAY_APPEND (&lctx->lightimages, shadow_map); numLayers = 0; } - size = lights[i].color[3]; + size = lights[li].color[3]; } - imageMap[i] = lctx->lightimages.size; - lctx->lightlayers.a[i] = numLayers; + imageMap[li] = lctx->lightimages.size; + lctx->lightlayers.a[li] = numLayers; numLayers += layers; totalLayers += layers; } @@ -621,11 +631,12 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) for (int i = 0; i < numLights; i++) { int layers = 4; int shadow = ST_NONE; + int li = lightMap[i]; - if (!lights[i].position[3]) { + if (!lights[li].position[3]) { shadow = ST_CASCADE; } else { - if (lights[i].direction[3] > -0.5) { + if (lights[li].direction[3] > -0.5) { shadow = ST_CUBE; } else { shadow = ST_PLANE; @@ -640,8 +651,8 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) DARRAY_APPEND (&lctx->lightimages, shadow_map); numLayers = 0; } - imageMap[i] = lctx->lightimages.size; - lctx->lightlayers.a[i] = numLayers; + imageMap[li] = lctx->lightimages.size; + lctx->lightlayers.a[li] = numLayers; numLayers += layers; totalLayers += layers; } @@ -668,29 +679,30 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) DARRAY_RESIZE (&lctx->lightviews, numLights); for (int i = 0; i < numLights; i++) { - if (imageMap[i] == -1) { - lctx->lightviews.a[i] = 0; + int li = lightMap[i]; + + if (imageMap[li] == -1) { + lctx->lightviews.a[li] = 0; continue; } int mode = ST_NONE; - if (!ldata->lights.a[i].position[3]) { + if (!ldata->lights.a[li].position[3]) { mode = ST_CASCADE; } else { - if (ldata->lights.a[i].direction[3] > -0.5) { + if (ldata->lights.a[li].direction[3] > -0.5) { mode = ST_CUBE; } else { mode = ST_PLANE; } } - lctx->lightviews.a[i] = create_view (lctx->lightimages.a[imageMap[i]], - lctx->lightlayers.a[i], - mode, i, ctx); + lctx->lightviews.a[li] = create_view (lctx->lightimages.a[imageMap[li]], + lctx->lightlayers.a[li], + mode, li, ctx); } Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n", totalLayers, lctx->lightimages.size, memsize); } -#endif void Vulkan_LoadLights (scene_t *scene, vulkan_ctx_t *ctx) @@ -699,4 +711,11 @@ Vulkan_LoadLights (scene_t *scene, vulkan_ctx_t *ctx) lctx->scene = scene; lctx->ldata = scene ? scene->lights : 0; + + clear_shadows (ctx); + + if (lctx->ldata && lctx->ldata->lights.size) { + build_shadow_maps (lctx, ctx); + create_light_matrices (lctx); + } } From 45431a0bcc5d1880b34d45ce22fe900043c908ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 May 2022 13:29:17 +0900 Subject: [PATCH 2831/3664] [vulkan] Use absolute light intensity/radius for size Many modders use negative lights for interesting effects, but vulkan doesn't like the result of a negative int treated as unsigned when it comes to texture sizes. --- libs/video/renderer/vulkan/vulkan_lighting.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 89d2b6264..966679238 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -473,12 +473,14 @@ light_compare (const void *_li2, const void *_li1, void *_ldata) lightingdata_t *ldata = _ldata; const light_t *l1 = &ldata->lights.a[*li1]; const light_t *l2 = &ldata->lights.a[*li2]; + int s1 = abs ((int) l1->color[3]); + int s2 = abs ((int) l2->color[3]); - if (l1->color[3] == l2->color[3]) { + if (s1 == s2) { return (l1->position[3] == l2->position[3]) && (l1->direction[3] > -0.5) == (l2->direction[3] > -0.5); } - return l1->color[3] - l2->color[3]; + return s1 - s2; } static VkImage @@ -607,14 +609,14 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) if (shadow == ST_CUBE) { layers = 6; } - if (size != (int) lights[li].color[3] + if (size != abs ((int) lights[li].color[3]) || numLayers + layers > maxLayers) { if (numLayers) { VkImage shadow_map = create_map (size, numLayers, 1, ctx); DARRAY_APPEND (&lctx->lightimages, shadow_map); numLayers = 0; } - size = lights[li].color[3]; + size = abs ((int) lights[li].color[3]); } imageMap[li] = lctx->lightimages.size; lctx->lightlayers.a[li] = numLayers; From 249feb1ae8d51224c455396bf19e78adf4318d2a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 May 2022 19:22:17 +0900 Subject: [PATCH 2832/3664] [glsl] Clean up build_surf_displist This makes it much easier to see just what is being done to build a polygon to be passed to the GPU, and it served as a test for the lightmap st changes since Vulkan currently never used them. --- libs/video/renderer/glsl/glsl_bsp.c | 94 ++++++++++++++--------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 76dca2469..6790cd68b 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -472,75 +472,69 @@ static void build_surf_displist (model_t **models, msurface_t *surf, int base, dstring_t *vert_list) { - int numverts; - int numtris; - int numindices; - int i; - vec_t *vec; - mvertex_t *vertices; - medge_t *edges; - int *surfedges; - int index; - bspvert_t *verts; - glslpoly_t *poly; - GLushort *ind; - float s, t; mod_brush_t *brush; - if (surf->model_index < 0) { brush = &models[-surf->model_index - 1]->brush; } else { brush = &r_refdef.worldmodel->brush; } - vertices = brush->vertexes; - edges = brush->edges; - surfedges = brush->surfedges; + mvertex_t *vertices = brush->vertexes; + medge_t *edges = brush->edges; + int *surfedges = brush->surfedges; - numverts = surf->numedges; - numtris = numverts - 2; - numindices = numtris * 3; - verts = alloca (numverts * sizeof (bspvert_t)); - poly = malloc (field_offset (glslpoly_t, indices[numindices])); + // create triangle soup for the polygon (this was written targeting + // GLES 2, which didn't have primitive restart) + int numverts = surf->numedges; + int numtris = numverts - 2; + int numindices = numtris * 3; + glslpoly_t *poly = malloc (field_offset (glslpoly_t, indices[numindices])); poly->count = numindices; - for (i = 0, ind = poly->indices; i < numtris; i++) { - *ind++ = base; - *ind++ = base + i + 1; - *ind++ = base + i + 2; + for (int i = 0, ind = 0; i < numtris; i++) { + // pretend we can use a triangle fan + poly->indices[ind++] = base; + poly->indices[ind++] = base + i + 1; + poly->indices[ind++] = base + i + 2; } surf->polys = (glpoly_t *) poly; + bspvert_t *verts = alloca (numverts * sizeof (bspvert_t)); mtexinfo_t *texinfo = surf->texinfo; - for (i = 0; i < numverts; i++) { - index = surfedges[surf->firstedge + i]; - if (index > 0) + for (int i = 0; i < numverts; i++) { + vec_t *vec; + int index = surfedges[surf->firstedge + i]; + if (index > 0) { + // forward edge vec = vertices[edges[index].v[0]].position; - else + } else { + // reverse edge vec = vertices[edges[-index].v[1]].position; - - s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; - t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; + } VectorCopy (vec, verts[i].vertex); - verts[i].vertex[3] = 1; - verts[i].tlst[0] = s / texinfo->texture->width; - verts[i].tlst[1] = t / texinfo->texture->height; + verts[i].vertex[3] = 1; // homogeneous coord - //lightmap texture coordinates - if (!surf->lightpic) { - // sky and water textures don't have lightmaps + vec2f_t st = { + DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3], + DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3], + }; + verts[i].tlst[0] = st[0] / texinfo->texture->width; + verts[i].tlst[1] = st[1] / texinfo->texture->height; + + if (surf->lightpic) { + //lightmap texture coordinates + //every lit surface has its own lighmap at a 1/16 resolution + //(ie, 16 albedo pixels for every lightmap pixel) + const vrect_t *rect = surf->lightpic->rect; + vec2f_t lmorg = (vec2f_t) { VEC2_EXP (&rect->x) } * 16 + 8; + vec2f_t texorg = { VEC2_EXP (surf->texturemins) }; + st = ((st - texorg + lmorg) / 16) * surf->lightpic->size; + verts[i].tlst[2] = st[0]; + verts[i].tlst[3] = st[1]; + } else { + // no lightmap for this surface (probably sky or water), so + // make the lightmap texture polygone degenerate verts[i].tlst[2] = 0; verts[i].tlst[3] = 0; - continue; } - s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; - t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; - s -= surf->texturemins[0]; - t -= surf->texturemins[1]; - s += surf->lightpic->rect->x * 16 + 8; - t += surf->lightpic->rect->y * 16 + 8; - s /= 16; - t /= 16; - verts[i].tlst[2] = s * surf->lightpic->size; - verts[i].tlst[3] = t * surf->lightpic->size; } dstring_append (vert_list, (char *) verts, numverts * sizeof (bspvert_t)); } From be635804d1c93a59d70a7bcc95fb80678a588c0a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 May 2022 19:24:39 +0900 Subject: [PATCH 2833/3664] [vulkan] Clean up display list building and add some comments Some very much needed comments :P Still, nicely, I now have a much better understanding of how the display lists are created (10 years is a long time to remember how intricate code works (I do remember fighting to get it working back then)) --- libs/video/renderer/vulkan/vulkan_bsp.c | 148 +++++++++++------------- 1 file changed, 68 insertions(+), 80 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 867a3f732..17afc3f20 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -68,6 +68,8 @@ #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" +#include "QF/simd/types.h" + #include "r_internal.h" #include "vid_vulkan.h" @@ -325,20 +327,7 @@ static bsppoly_t * build_surf_displist (model_t **models, msurface_t *surf, int base, bspvert_t **vert_list) { - int numverts; - int numindices; - int i; - vec_t *vec; - mvertex_t *vertices; - medge_t *edges; - int *surfedges; - int index; - bspvert_t *verts; - bsppoly_t *poly; - uint32_t *ind; - float s, t; mod_brush_t *brush; - if (surf->model_index < 0) { // instance model brush = &models[~surf->model_index]->brush; @@ -346,58 +335,62 @@ build_surf_displist (model_t **models, msurface_t *surf, int base, // main or sub model brush = &r_refdef.worldmodel->brush; } - vertices = brush->vertexes; - edges = brush->edges; - surfedges = brush->surfedges; - // create a triangle fan - numverts = surf->numedges; - numindices = numverts + 1; - verts = *vert_list; + mvertex_t *vertices = brush->vertexes; + medge_t *edges = brush->edges; + int *surfedges = brush->surfedges; + // surf->polys is set to the next slot before the call - poly = (bsppoly_t *) surf->polys; - poly->count = numindices; - for (i = 0, ind = poly->indices; i < numverts; i++) { - *ind++ = base + i; + bsppoly_t *poly = (bsppoly_t *) surf->polys; + // create a triangle fan + int numverts = surf->numedges; + poly->count = numverts + 1; // +1 for primitive restart + for (int i = 0; i < numverts; i++) { + poly->indices[i] = base + i; } - *ind++ = -1; // end of primitive + poly->indices[numverts] = -1; // primitive restart surf->polys = (glpoly_t *) poly; + bspvert_t *verts = *vert_list; mtexinfo_t *texinfo = surf->texinfo; - for (i = 0; i < numverts; i++) { - index = surfedges[surf->firstedge + i]; + for (int i = 0; i < numverts; i++) { + vec_t *vec; + int index = surfedges[surf->firstedge + i]; if (index > 0) { + // forward edge vec = vertices[edges[index].v[0]].position; } else { + // reverse edge vec = vertices[edges[-index].v[1]].position; } - - s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; - t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; VectorCopy (vec, verts[i].vertex); - verts[i].vertex[3] = 1; - verts[i].tlst[0] = s / texinfo->texture->width; - verts[i].tlst[1] = t / texinfo->texture->height; + verts[i].vertex[3] = 1; // homogeneous coord - //lightmap texture coordinates - if (!surf->lightpic) { - // sky and water textures don't have lightmaps + vec2f_t st = { + DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3], + DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3], + }; + verts[i].tlst[0] = st[0] / texinfo->texture->width; + verts[i].tlst[1] = st[1] / texinfo->texture->height; + + if (surf->lightpic) { + //lightmap texture coordinates + //every lit surface has its own lighmap at a 1/16 resolution + //(ie, 16 albedo pixels for every lightmap pixel) + const vrect_t *rect = surf->lightpic->rect; + vec2f_t lmorg = (vec2f_t) { VEC2_EXP (&rect->x) } * 16 + 8; + vec2f_t texorg = { VEC2_EXP (surf->texturemins) }; + st = ((st - texorg + lmorg) / 16) * surf->lightpic->size; + verts[i].tlst[2] = st[0]; + verts[i].tlst[3] = st[1]; + } else { + // no lightmap for this surface (probably sky or water), so + // make the lightmap texture polygone degenerate verts[i].tlst[2] = 0; verts[i].tlst[3] = 0; - continue; } - s = DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3]; - t = DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3]; - s -= surf->texturemins[0]; - t -= surf->texturemins[1]; - s += surf->lightpic->rect->x * 16 + 8; - t += surf->lightpic->rect->y * 16 + 8; - s /= 16; - t /= 16; - verts[i].tlst[2] = s * surf->lightpic->size; - verts[i].tlst[3] = t * surf->lightpic->size; } *vert_list += numverts; - return (bsppoly_t *) &poly->indices[numindices]; + return (bsppoly_t *) &poly->indices[poly->count]; } void @@ -406,14 +399,6 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; - int vertex_index_base; - model_t *m; - dmodel_t *dm; - msurface_t *surf; - qfv_stagebuf_t *stage; - bspvert_t *vertices; - bsppoly_t *poly; - mod_brush_t *brush; if (!num_models) { return; @@ -423,17 +408,14 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) // effectively sorting the surfaces by texture (without worrying about // surface order on the same texture chain). for (int i = 0; i < num_models; i++) { - m = models[i]; - if (!m) - continue; + model_t *m = models[i]; // sub-models are done as part of the main model // and non-bsp models don't have surfaces. - if (*m->path == '*' || m->type != mod_brush) + if (!m || *m->path == '*' || m->type != mod_brush) continue; - brush = &m->brush; - dm = brush->submodels; + mod_brush_t *brush = &m->brush; + dmodel_t *dm = brush->submodels; for (unsigned j = 0; j < brush->numsurfaces; j++) { - vulktex_t *tex; if (j == dm->firstface + dm->numfaces) { // move on to the next sub-model dm++; @@ -445,13 +427,13 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) break; } } - surf = brush->surfaces + j; + msurface_t *surf = brush->surfaces + j; surf->model_index = dm - brush->submodels; if (!surf->model_index && m != r_refdef.worldmodel) { surf->model_index = -1 - i; // instanced model } - tex = surf->texinfo->texture->render; // append surf to the texture chain + vulktex_t *tex = surf->texinfo->texture->render; CHAIN_SURF_F2B (surf, tex->tex_chain); } } @@ -477,29 +459,35 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) size_t vertex_buffer_size = vertex_count * sizeof (bspvert_t); index_buffer_size = (index_buffer_size + atom_mask) & ~atom_mask; - stage = QFV_CreateStagingBuffer (device, "bsp", vertex_buffer_size, - ctx->cmdpool); + qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, "bsp", + vertex_buffer_size, + ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); - vertices = QFV_PacketExtend (packet, vertex_buffer_size); - vertex_index_base = 0; - // holds all the polygon definitions: vertex indices + poly_count "end of - // primitive" markers. + bspvert_t *vertices = QFV_PacketExtend (packet, vertex_buffer_size); + // holds all the polygon definitions: vertex indices + poly_count + // primitive restart markers + poly_count index counts. The primitive + // restart markers are included in index_count, so poly_count below is + // for the per-polygon index count. + // so each polygon within the list: + // count includes the end of primitive marker + // index count-1 indices + // index + // ... + // "end of primitive" (~0u) free (bctx->polys); bctx->polys = malloc ((index_count + poly_count) * sizeof (uint32_t)); // All usable surfaces have been chained to the (base) texture they use. - // Run through the textures, using their chains to build display maps. + // Run through the textures, using their chains to build display lists. // For animated textures, if a surface is on one texture of the group, it - // will be on all. - poly = bctx->polys; - int count = 0; + // will effectively be on all (just one at a time). + int count = 0; + int vertex_index_base = 0; + bsppoly_t *poly = bctx->polys; for (size_t i = 0; i < bctx->texture_chains.size; i++) { - vulktex_t *tex; - instsurf_t *is; + vulktex_t *tex = bctx->texture_chains.a[i]; - tex = bctx->texture_chains.a[i]; - - for (is = tex->tex_chain; is; is = is->tex_chain) { + for (instsurf_t *is = tex->tex_chain; is; is = is->tex_chain) { msurface_t *surf = is->surface; surf->polys = (glpoly_t *) poly; From 8b425a274071bebcaa356d55a1107675dd927587 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 May 2022 19:37:15 +0900 Subject: [PATCH 2834/3664] [tools] Show major file offsets in mdl dumper Handy for debugging the alias model loader. --- tools/misc/mdl.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/misc/mdl.py b/tools/misc/mdl.py index 924cdb48d..2aba831ba 100644 --- a/tools/misc/mdl.py +++ b/tools/misc/mdl.py @@ -3,6 +3,7 @@ from pprint import * import sys model = open(sys.argv[1],"rb").read() +file_bytes = len(model) m = unpack ("4s i 3f 3f f 3f i i i i i i i", model[:76]) model = model[76:] m = m[0:2] + (m[2:5],) + (m[5:8],) + m[8:9] + (m[9:12],) + m[12:20] @@ -11,6 +12,7 @@ if m[1] == 6: model = model[8:] pprint (m) +print(f"skins @ {file_bytes - len(model)}") skins = [] s = m[7] * m[8] for i in range(m[6]): @@ -31,6 +33,7 @@ for i in range(m[6]): skins.append (k) #pprint (skins) +print(f"stverts @ {file_bytes - len(model)}") stverts = [] for i in range(m[9]): x = unpack ("i i i", model[:12]) @@ -38,6 +41,7 @@ for i in range(m[9]): model = model [12:] pprint (stverts) +print(f"tris @ {file_bytes - len(model)}") tris = [] for i in range(m[10]): tris.append (unpack ("i i i i", model[:16])) @@ -45,6 +49,7 @@ for i in range(m[10]): model = model [16:] pprint (tris) +print(f"frames @ {file_bytes - len(model)}") frames = [] for i in range (m[11]): t = unpack ("i", model[:4])[0] From f97fb90d90afe68f1a34056648f366d73a34b2c4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 May 2022 19:38:46 +0900 Subject: [PATCH 2835/3664] [model] Fix alias skin group loading Although the skin pointer was being advanced after recording the information in for the batch array, it was being reset the next time around the loop (due to a mistranslation of the previous code). This fixes the segfault while loading (gl, glsl, vulkan) or rendering (sw) the sphere model from Rogue. --- libs/models/alias/model_alias.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/models/alias/model_alias.c b/libs/models/alias/model_alias.c index 4e1832bd2..a080fc0e9 100644 --- a/libs/models/alias/model_alias.c +++ b/libs/models/alias/model_alias.c @@ -113,7 +113,6 @@ Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx, int numskins, for (gnum = 0; gnum < groupskins; gnum++) { paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE; - skin = (byte *) (pskintype + 1); mod_alias_skin_t askin = { .skin_num = snum, .group_num = gnum, @@ -263,7 +262,7 @@ Mod_LoadAliasModel (model_t *mod, void *buffer, cache_allocator_t allocator) mod->name, version, ALIAS_VERSION_MDL); // allocate space for a working header, plus all the data except the - // frames, skin and group info + // frame data, skin and group info size = field_offset (aliashdr_t, frames[LittleLong (pinmodel->numframes)]); header = Hunk_AllocName (0, size, mod->name); memset (header, 0, size); From 3639ee3d2dbb152f3268ae7ee5e3a609d18b2ee8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 May 2022 21:20:53 +0900 Subject: [PATCH 2836/3664] [vulkan] Just simply exit for validation errors With experience, I have found that trying to continue after a validation error tends to result in a segfault or some other nastiness, and Sys_Shutdown (and the full shutdown sequence) is triggered for any error signal (segfault, abort, etc) so just exit(1). --- libs/video/renderer/vulkan/instance.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index f2dc5ffac..588ea4c34 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -118,6 +118,9 @@ static int message_types = static void debug_breakpoint (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity) { + if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + exit(1); + } } static VKAPI_ATTR VkBool32 VKAPI_CALL From bc82241e1c4836379de5a2551ba9a4ac653b9f44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 May 2022 21:24:45 +0900 Subject: [PATCH 2837/3664] [client] Pre-cache temp entity data after clearing memory This is a particularly ancient bug, sort of introduced by rhamph when he optimized temp entity model handling and later exacerbated by me. However, I suspect the actual problem is limited to nq as qw's gamedir handling would have caused the models to be reloaded, but nq doesn't ever change game directories once running. --- include/client/temp_entities.h | 1 + libs/client/cl_temp_entities.c | 19 ++++++++++++------- nq/source/cl_main.c | 2 ++ qw/source/cl_main.c | 2 ++ 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/include/client/temp_entities.h b/include/client/temp_entities.h index e88a07331..5ce46fc64 100644 --- a/include/client/temp_entities.h +++ b/include/client/temp_entities.h @@ -103,6 +103,7 @@ struct msg_s; struct entity_s; void CL_TEnts_Init (void); +void CL_TEnts_Precache (void); void CL_Init_Entity (struct entity_s *ent); void CL_ClearTEnts (void); void CL_UpdateTEnts (double time, TEntContext_t *ctx); diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 3be60f2bd..16c93c8a9 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -107,12 +107,9 @@ static model_t *cl_spike; static vec4f_t beam_rolls[360]; -static void -CL_TEnts_Precache (int phase) +void +CL_TEnts_Precache (void) { - if (!phase) { - return; - } cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav"); cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav"); cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav"); @@ -134,11 +131,19 @@ CL_TEnts_Precache (int phase) } } +static void +cl_tents_precache (int phase) +{ + if (!phase) { + return; + } + CL_TEnts_Precache (); +} + void CL_TEnts_Init (void) { - QFS_GamedirCallback (CL_TEnts_Precache); - CL_TEnts_Precache (1); + QFS_GamedirCallback (cl_tents_precache); for (int i = 0; i < 360; i++) { float ang = i * M_PI / 360; beam_rolls[i] = (vec4f_t) { sin (ang), 0, 0, cos (ang) }; diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 58628e0fd..070df9f1f 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -300,6 +300,8 @@ CL_ClearState (void) cl.viewstate.weapon_entity = Scene_CreateEntity (cl_world.scene); CL_Init_Entity (cl.viewstate.weapon_entity); r_data->view_model = cl.viewstate.weapon_entity; + + CL_TEnts_Precache (); } /* diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 77c39fb4d..a78a46e46 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -693,6 +693,8 @@ CL_ClearState (void) CL_Init_Entity (cl.viewstate.weapon_entity); r_data->view_model = cl.viewstate.weapon_entity; + CL_TEnts_Precache (); + SCR_NewScene (0); SZ_Clear (&cls.netchan.message); From beb05f28ff2b4f0e1cf2d5de989dec5c563c2a1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 May 2022 22:00:03 +0900 Subject: [PATCH 2838/3664] [glsl,vulkan] More comments in the bsp code And maybe a nano-optimization. Switching from (~side + 1) to (-side) seems to give glsl a very tiny speed boost, but certainly doesn't hurt. Looking at some assembly output for the three cases, the two hacks seem to generate the same code as each other, but 3 instructions vs 6 for ?:. While ?: is more generically robust, the hacks are tuned for the knowledge side is either 0 or 1. The later xor might alter things, but at least I now know that the hack (either version) is worthwhile. --- libs/video/renderer/glsl/glsl_bsp.c | 9 +++++++-- libs/video/renderer/vulkan/vulkan_bsp.c | 12 +++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 6790cd68b..39ae051c7 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -731,6 +731,7 @@ visit_leaf (mleaf_t *leaf) R_StoreEfrags (leaf->efrags); } +// 1 = back side, 0 = front side static inline int get_side (mnode_t *node) { @@ -750,8 +751,10 @@ visit_node (glslbspctx_t *bctx, mnode_t *node, int side) msurface_t *surf; // sneaky hack for side = side ? SURF_PLANEBACK : 0; - side = (~side + 1) & SURF_PLANEBACK; - // draw stuff + // seems to be microscopically faster even on modern hardware + side = (-side) & SURF_PLANEBACK; + // chain any visible surfaces on the node that face the camera. + // not all nodes have any surfaces to draw (purely a split plane) if ((c = node->numsurfaces)) { surf = bctx->brush->surfaces + node->firstsurface; for (; c; c--, surf++) { @@ -759,6 +762,8 @@ visit_node (glslbspctx_t *bctx, mnode_t *node, int side) continue; // side is either 0 or SURF_PLANEBACK + // if side and the surface facing differ, then the camera is + // on backside of the surface if (side ^ (surf->flags & SURF_PLANEBACK)) continue; // wrong side diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 17afc3f20..3663a5ede 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -638,11 +638,13 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) static inline void visit_leaf (mleaf_t *leaf) { - // deal with model fragments in this leaf + // since this leaf will be rendered, any entities in the leaf also need + // to be rendered (the bsp tree doubles as an entity cull structure) if (leaf->efrags) R_StoreEfrags (leaf->efrags); } +// 1 = back side, 0 = front side static inline int get_side (mnode_t *node) { @@ -662,8 +664,10 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) msurface_t *surf; // sneaky hack for side = side ? SURF_PLANEBACK : 0; - side = (~side + 1) & SURF_PLANEBACK; - // draw stuff + // seems to be microscopically faster even on modern hardware + side = (-side) & SURF_PLANEBACK; + // chain any visible surfaces on the node that face the camera. + // not all nodes have any surfaces to draw (purely a split plane) if ((c = node->numsurfaces)) { surf = brush->surfaces + node->firstsurface; for (; c; c--, surf++) { @@ -671,6 +675,8 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) continue; // side is either 0 or SURF_PLANEBACK + // if side and the surface facing differ, then the camera is + // on backside of the surface if (side ^ (surf->flags & SURF_PLANEBACK)) continue; // wrong side From 765b61d133bef70ff56f8ee9b9c9ae6e38063139 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 14 May 2022 00:09:42 +0900 Subject: [PATCH 2839/3664] [vulkan] Remove elements_t type This was one of the biggest reasons I had trouble understanding the bsp display list code, but it turns out it was for dealing with GLES's 16-bit limit on vertex indices. Since vulkan uses 32-bit indices, there's no need for the extra layer of indirection. I'm pretty sure it was that lack of understanding that prevented me from removing it when I first converted the glsl bsp code to vulkan (ie, that 16-bit indices were the only reason for elements_t). It's hard to tell whether the change makes much difference to performance, though it seems it might (noisy stats even over 50 timedemo loops) and the better data localization indicate it should at least be just as good if not better. However, the reason for the change is simplifying the data structures so I can make bsp rendering thread-safe in preparation for rendering shadow maps. --- include/QF/Vulkan/qf_bsp.h | 13 ++------ libs/video/renderer/vulkan/vulkan_bsp.c | 43 ++++++++----------------- 2 files changed, 16 insertions(+), 40 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 380b88e6f..ab823c2fa 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -54,17 +54,11 @@ typedef struct bspvert_s { quat_t tlst; } bspvert_t; -typedef struct elements_s { - struct elements_s *_next; - struct elements_s *next; - uint32_t first_index; - uint32_t index_count; -} elements_t; - typedef struct elechain_s { struct elechain_s *_next; struct elechain_s *next; - elements_t *elements; + uint32_t first_index; + uint32_t index_count; vec_t *transform; float *color; } elechain_t; @@ -120,9 +114,6 @@ typedef struct bspctx_s { elechain_t *elechains; elechain_t **elechains_tail; elechain_t *free_elechains; - elements_t *elementss; - elements_t **elementss_tail; - elements_t *free_elementss; instsurf_t *instsurfs; instsurf_t **instsurfs_tail; instsurf_t *free_instsurfs; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 3663a5ede..12e2d3b22 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -162,7 +162,6 @@ release_##name##s (bspctx_t *bctx) \ } GET_RELEASE (elechain_t, elechain) -GET_RELEASE (elements_t, elements) GET_RELEASE (instsurf_t, static_instsurf) GET_RELEASE (instsurf_t, instsurf) @@ -216,7 +215,6 @@ clear_texture_chains (bspctx_t *bctx) } clear_tex_chain (r_notexture_mip->render); release_elechains (bctx); - release_elementss (bctx); release_instsurfs (bctx); } @@ -225,7 +223,6 @@ Vulkan_ClearElements (vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; release_elechains (bctx); - release_elementss (bctx); } static inline void @@ -307,7 +304,8 @@ add_elechain (vulktex_t *tex, bspctx_t *bctx) elechain_t *ec; ec = get_elechain (bctx); - ec->elements = get_elements (bctx); + ec->first_index = 0; + ec->index_count = 0; ec->transform = 0; ec->color = 0; *tex->elechain_tail = ec; @@ -793,7 +791,6 @@ draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_device_t *device, VkCommandBuffer cmd) { qfv_devfuncs_t *dfunc = device->funcs; - elements_t *el; if (ec->transform) { push_transform (ec->transform, layout, device, cmd); @@ -801,10 +798,8 @@ draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_device_t *device, //FIXME should cache current transform push_transform (identity, layout, device, cmd); } - for (el = ec->elements; el; el = el->next) { - if (!el->index_count) - continue; - dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index, + if (ec->index_count) { + dfunc->vkCmdDrawIndexed (cmd, ec->index_count, 1, ec->first_index, 0, 0); } } @@ -812,14 +807,11 @@ draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_device_t *device, static void reset_elechain (elechain_t *ec) { - elements_t *el; - - for (el = ec->elements; el; el = el->next) { - el->first_index = 0; - el->index_count = 0; - } + ec->first_index = 0; + ec->index_count = 0; } + static void bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, VkPipelineLayout layout, qfv_renderframe_t *rFrame) @@ -975,8 +967,7 @@ sky_end (vulkan_ctx_t *ctx) } static inline void -add_surf_elements (vulktex_t *tex, instsurf_t *is, - elechain_t **ec, elements_t **el, +add_surf_elements (vulktex_t *tex, instsurf_t *is, elechain_t **ec, bspctx_t *bctx, bspframe_t *bframe) { bsppoly_t *poly = (bsppoly_t *) is->surface->polys; @@ -985,19 +976,17 @@ add_surf_elements (vulktex_t *tex, instsurf_t *is, (*ec) = add_elechain (tex, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; - (*el) = (*ec)->elements; - (*el)->first_index = bframe->index_count; + (*ec)->first_index = bframe->index_count; } if (is->transform != (*ec)->transform || is->color != (*ec)->color) { (*ec) = add_elechain (tex, bctx); (*ec)->transform = is->transform; (*ec)->color = is->color; - (*el) = (*ec)->elements; - (*el)->first_index = bframe->index_count; + (*ec)->first_index = bframe->index_count; } memcpy (bframe->index_data + bframe->index_count, poly->indices, poly->count * sizeof (poly->indices[0])); - (*el)->index_count += poly->count; + (*ec)->index_count += poly->count; bframe->index_count += poly->count; } @@ -1006,12 +995,11 @@ build_tex_elechain (vulktex_t *tex, bspctx_t *bctx, bspframe_t *bframe) { instsurf_t *is; elechain_t *ec = 0; - elements_t *el = 0; for (is = tex->tex_chain; is; is = is->tex_chain) { // emit the polygon indices for the surface to the texture's // element chain - add_surf_elements (tex, is, &ec, &el, bctx, bframe); + add_surf_elements (tex, is, &ec, bctx, bframe); } } @@ -1117,7 +1105,6 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) instsurf_t *is; vulktex_t *tex = 0; elechain_t *ec = 0; - elements_t *el = 0; if (!bctx->waterchain) return; @@ -1146,7 +1133,7 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) } // emit the polygon indices for the surface to the texture's // element chain - add_surf_elements (tex, is, &ec, &el, bctx, bframe); + add_surf_elements (tex, is, &ec, bctx, bframe); } if (tex) { bind_texture (tex, 1, bctx->layout, dfunc, @@ -1176,7 +1163,6 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) instsurf_t *is; vulktex_t *tex = 0; elechain_t *ec = 0; - elements_t *el = 0; if (!bctx->sky_chain) return; @@ -1208,7 +1194,7 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) } // emit the polygon indices for the surface to the texture's // element chain - add_surf_elements (tex, is, &ec, &el, bctx, bframe); + add_surf_elements (tex, is, &ec, bctx, bframe); } if (tex) { bind_texture (tex, 1, bctx->layout, dfunc, @@ -1350,7 +1336,6 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->sky_chain_tail = &bctx->sky_chain; bctx->static_instsurfs_tail = &bctx->static_instsurfs; bctx->elechains_tail = &bctx->elechains; - bctx->elementss_tail = &bctx->elementss; bctx->instsurfs_tail = &bctx->instsurfs; bctx->light_scrap = QFV_CreateScrap (device, "lightmap_atlas", 2048, From 495e71193e4f006934fa7a1d59b66a6ec5273c5e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 May 2022 11:59:50 +0900 Subject: [PATCH 2840/3664] [input] Fix some doxygen breakage --- include/QF/input.h | 8 +++++--- include/QF/input/binding.h | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/include/QF/input.h b/include/QF/input.h index a701cdd68..e5ef61f9d 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -29,8 +29,9 @@ #define __QF_input_h /** \defgroup input Input Sub-system */ - ///@{ + +/// input axis info typedef struct in_axisinfo_s { int deviceid; int axis; @@ -39,6 +40,7 @@ typedef struct in_axisinfo_s { int max; } in_axisinfo_t; +/// input button info typedef struct in_buttoninfo_s { int deviceid; int button; @@ -52,6 +54,7 @@ typedef struct in_buttoninfo_s { struct qf_fd_set; +/// driver interface typedef struct in_driver_s { void (*init_cvars) (void *data); void (*init) (void *data); @@ -87,6 +90,7 @@ typedef struct in_driver_s { in_buttoninfo_t *info); } in_driver_t; +/// device info typedef struct in_device_s { int driverid; void *device; @@ -95,8 +99,6 @@ typedef struct in_device_s { void *event_data; } in_device_t; -struct cvar_s; - int IN_RegisterDriver (in_driver_t *driver, void *data); void IN_DriverData (int handlle, void *data); void IN_Init (void); diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index 86fde3548..e901b47a2 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -39,7 +39,7 @@ */ ///@{ -/*** Recipe for converting an axis to a floating point value. +/** Recipe for converting an axis to a floating point value. Absolute axes are converted to the 0..1 range for unbalanced axes, and the -1..1 range for balanced axes, and then scaled. @@ -78,7 +78,7 @@ typedef enum { ina_accumulate, ///< add the axis value to the destination } in_axis_mode; -/*** Logical axis. +/** Logical axis. Logical axes are the inputs defined by the game on which axis inputs (usually "physical" axes) can act. Depending on the mode, the physical @@ -102,12 +102,12 @@ typedef struct in_axis_s { typedef struct axis_listener_set_s LISTENER_SET_TYPE (in_axis_t) axis_listener_set_t; -/*** Function type for axis listeners. +/** Function type for axis listeners. */ typedef void (*axis_listener_t) (void *data, const in_axis_t *axis); #endif -/*** Current state of the logical button. +/** Current state of the logical button. Captures the current state and any transitions during the last frame. Not all combinations are valid (inb_edge_up|inb_down and inb_edge_down @@ -121,7 +121,7 @@ typedef enum { inb_edge_up = 1<<2, ///< button released this frame } in_button_state; -/*** Logical button. +/** Logical button. Logical buttons are the inputs defined by the game on which button inputs (usually "physical" buttons) can act. Up to two button inputs can be @@ -143,7 +143,7 @@ typedef struct in_button_s { typedef struct button_listener_set_s LISTENER_SET_TYPE (in_button_t) button_listener_set_t; -/*** Function type for button listeners. +/** Function type for button listeners. */ typedef void (*button_listener_t) (void *data, const in_button_t *button); @@ -165,7 +165,7 @@ typedef struct in_buttonbinding_s { }; } in_buttonbinding_t; -/*** Represent the button's activity in the last frame as a float. +/** Represent the button's activity in the last frame as a float. The detected activity is: steady off (up) @@ -184,7 +184,7 @@ typedef struct in_buttonbinding_s { */ GNU89INLINE inline float IN_ButtonState (in_button_t *button); -/*** Test whether a button has been pressed in the last frame. +/** Test whether a button has been pressed in the last frame. Both steady-state on, and brief clicks are detected. @@ -196,7 +196,7 @@ GNU89INLINE inline float IN_ButtonState (in_button_t *button); */ GNU89INLINE inline int IN_ButtonPressed (in_button_t *button); -/*** Test whether a button was released in the last frame. +/** Test whether a button was released in the last frame. Valid only if the button is still released. A pulsed off does not count as being released as the button is still held. @@ -209,7 +209,7 @@ GNU89INLINE inline int IN_ButtonPressed (in_button_t *button); */ GNU89INLINE inline int IN_ButtonReleased (in_button_t *button); -/*** Update the axis value based on its mode and clear its relative input. +/** Update the axis value based on its mode and clear its relative input. The absolute and relative inputs are separate because absolute inputs usually get written when the input actually changes (and thus must not @@ -222,7 +222,7 @@ GNU89INLINE inline int IN_ButtonReleased (in_button_t *button); */ GNU89INLINE inline float IN_UpdateAxis (in_axis_t *axis); -/*** Update and clamp the axis value (see IN_UpdateAxis()) +/** Update and clamp the axis value (see IN_UpdateAxis()) Like IN_UpdateAxis(), but clamps the final output to the specified range. This is most useful for \a ina_accumulate axes, but can be used to ensure @@ -235,7 +235,7 @@ GNU89INLINE inline float IN_UpdateAxis (in_axis_t *axis); \param axis Pointer to the axis being updated. \param minval The minimum value to which the axis output will be clamped. - \param minval The minimum value to which the axis output will be clamped. + \param maxval The minimum value to which the axis output will be clamped. \return The resulting output value of the axis. \note The relative input (\a rel_input) is zeroed. The absolute input is not affected by the clamping, only the output From 0ba8d44654de4f3ecff5ae551260de72572fb6ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 May 2022 12:00:14 +0900 Subject: [PATCH 2841/3664] More doxygen tweaks --- include/QF/progs.h | 8 ++++---- include/QF/segtext.h | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index b7796a3d3..233659dd2 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -910,9 +910,9 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ /** \defgroup prda_return Return Values \ingroup progs_data_access - These macros are used to access the value returned by an interpreted VM - function, and to return values from engine functions into progs space - (that is, builtins). + Typed return value access. These macros are used to access the value + returned by an interpreted VM function, and to return values from engine + functions into progs space (that is, builtins). \warning No checking is performed against progs types; for example, if you ask for an \c int from a function that returned a \c float, you're asking for trouble. @@ -1730,7 +1730,7 @@ void PR_Resources_Clear (progs_t *pr); registering the resource is a suitable name, and will probably be unique. \note During VM shutdown, \a clear is called (for all resources) - before \destroy is called. + before \a destroy is called. */ void PR_Resources_Register (progs_t *pr, const char *name, void *data, void (*clear)(progs_t *, void *), diff --git a/include/QF/segtext.h b/include/QF/segtext.h index 79020356c..a8b0be896 100644 --- a/include/QF/segtext.h +++ b/include/QF/segtext.h @@ -33,6 +33,7 @@ /** \defgroup segtext Segmented text files \ingroup utils + Access named sections of a text file. Based on The OpenGL Shader Wrangler: https://prideout.net/blog/old/blog/index.html@p=11.html @@ -66,7 +67,7 @@ typedef struct segchunk_s { Segments are stored sequentially in \a chunk_list are indexed by identifying tag (if present) in \a tab. Segments that have no identifying tag are not in \a tab, but can - be accessed by walking \a chunk_list its \a next field. + be accessed by walking \a chunk_list 's \a next field. */ typedef struct segtext_s { struct segtext_s *next; From ee19a928a08636504fda5d0362b3310a447633b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 May 2022 20:59:07 +0900 Subject: [PATCH 2842/3664] [model] Make the miptex toupper clearer That bit of code got me every time I looked at it. --- libs/models/brush/model_brush.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 7632c07f2..34863d573 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -322,9 +322,13 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) memset (anims, 0, sizeof (anims)); memset (altanims, 0, sizeof (altanims)); +// convert to uppercase, avoiding toupper (table lookup, +// localization issues, etc) +#define QTOUPPER(x) ((x) - ('a' - 'A')) + max = tx->name[1]; if (max >= 'a' && max <= 'z') - max -= 'a' - 'A'; + max = QTOUPPER (max); if (max >= '0' && max <= '9') { max -= '0'; altmax = 0; @@ -347,7 +351,7 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) num = tx2->name[1]; if (num >= 'a' && num <= 'z') - num -= 'a' - 'A'; + num = QTOUPPER (num); if (num >= '0' && num <= '9') { num -= '0'; anims[num] = tx2; From 0bf903afd01833760499d18c248dd147ffa039b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 15 May 2022 11:57:20 +0900 Subject: [PATCH 2843/3664] [bspfile] Document the bsp file data structures While I still have a couple of questions unanswered, this takes care of what I needed to know for now (and then some). --- include/QF/bspfile.h | 894 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 729 insertions(+), 165 deletions(-) diff --git a/include/QF/bspfile.h b/include/QF/bspfile.h index 1232c4f09..61103e3f3 100644 --- a/include/QF/bspfile.h +++ b/include/QF/bspfile.h @@ -30,250 +30,654 @@ #include "QF/qtypes.h" #include "QF/quakeio.h" -// upper design bounds +/** \defgroup formats_bsp BSP Files -#define MAX_MAP_HULLS 4 // format limit (array) + BSP files are used for quake's maps and some pick-up items (health and + ammo boxes in particular). The maps can be quite complicated, usually with + many sub-models, while the pick-up items are usually simple boxes. -#define MAX_MAP_PLANES 32767 // format limit (s16) FIXME u16 ok? -#define MAX_MAP_NODES 65520 // because negative shorts are contents -#define MAX_MAP_CLIPNODES 65520 // but contents "max" is -15, so -#define MAX_MAP_LEAFS 65520 // -32768 to -17 are available -#define MAX_MAP_VERTS 65535 // format limit (u16) -#define MAX_MAP_FACES 65535 // format limit (u16) -#define MAX_MAP_MARKSURFACES 65535 // format limit (u16) + QuakeForge supports two formats for BSP files "BSP 29", (the original + format, with many 16-bit fields), and "BSP 2", all fields 32 bits. Both + formats are little-endian. + + BSP files use a right-handed coordinate system with +Z up but clockwise + winding for face normals. + + The tools used to create a bsp file include qfbsp, qfvis and qflight (or + similar tools from other projects). +*/ + +/** \defgroup bsp_limits BSP File limits + \ingroup formats_bsp + + Other than MAX_MAP_HULLS, these apply only to BSP 29 files as the fields + holding the values are all 16 bits. +*/ +///@{ + +#define MAX_MAP_HULLS 4 ///< fixed length array + +#define MAX_MAP_PLANES 32767 +/** \name nodes and leafs (sic) + negative shorts are contents but contents "max" is -15, so -32768 to -17 + are available +*/ +///@{ +#define MAX_MAP_NODES 65520 +#define MAX_MAP_CLIPNODES 65520 +#define MAX_MAP_LEAFS 65520 +///@} +#define MAX_MAP_VERTS 65535 +#define MAX_MAP_FACES 65535 +#define MAX_MAP_MARKSURFACES 65535 #define MAP_PVS_BYTES (MAX_MAP_LEAFS / 8) +///@} -//============================================================================= +/** \defgroup bsp_lumps BSP File lumps + \ingroup formats_bsp -#define BSPVERSION 29 -#define BSP2VERSION "BSP2" // use memcmp with 4 bytes -#define Q2BSPVERSION 38 -#define TOOLVERSION 2 + All data in a BSP file is separated into lumps. The lump structure gives + the file relative offset of the beginning of the data lump, and the size + of the lump in bytes. +*/ +///@{ +/** Individual data lump descriptor. +*/ typedef struct lump_s { - uint32_t fileofs; - uint32_t filelen; + uint32_t fileofs; ///< File relative offset in bytes + uint32_t filelen; ///< Size of lump in bytes } lump_t; -#define LUMP_ENTITIES 0 -#define LUMP_PLANES 1 -#define LUMP_TEXTURES 2 -#define LUMP_VERTEXES 3 -#define LUMP_VISIBILITY 4 -#define LUMP_NODES 5 -#define LUMP_TEXINFO 6 -#define LUMP_FACES 7 -#define LUMP_LIGHTING 8 -#define LUMP_CLIPNODES 9 -#define LUMP_LEAFS 10 -#define LUMP_MARKSURFACES 11 -#define LUMP_EDGES 12 -#define LUMP_SURFEDGES 13 -#define LUMP_MODELS 14 -#define HEADER_LUMPS 15 +#define LUMP_ENTITIES 0 ///< \ref bsp_entities +#define LUMP_PLANES 1 ///< \ref bsp_planes +#define LUMP_TEXTURES 2 ///< \ref bsp_textures +#define LUMP_VERTEXES 3 ///< \ref bsp_vertices +#define LUMP_VISIBILITY 4 ///< \ref bsp_visibility +#define LUMP_NODES 5 ///< \ref bsp_nodes +#define LUMP_TEXINFO 6 ///< \ref bsp_texinfo +#define LUMP_FACES 7 ///< \ref bsp_face +#define LUMP_LIGHTING 8 ///< \ref bsp_lighting +#define LUMP_CLIPNODES 9 ///< \ref bsp_clipnodes +#define LUMP_LEAFS 10 ///< \ref bsp_leafs +#define LUMP_MARKSURFACES 11 ///< \ref bsp_marksurfaces +#define LUMP_EDGES 12 ///< \ref bsp_edges +#define LUMP_SURFEDGES 13 ///< \ref bsp_surfedges +#define LUMP_MODELS 14 ///< \ref bsp_model +#define HEADER_LUMPS 15 ///< Number of lumps +///@} -typedef struct dmodel_s { - float mins[3], maxs[3]; - float origin[3]; - uint32_t headnode[MAX_MAP_HULLS]; - uint32_t visleafs; // not including the solid leaf 0 - uint32_t firstface, numfaces; -} dmodel_t; +/** \defgroup bsp_header BSP File header + \ingroup formats_bsp +*/ +///@{ +/** Holdes version and lump offset information. + Always at offset 0 of the BSP file. +*/ typedef struct dheader_s { - uint32_t version; - lump_t lumps[HEADER_LUMPS]; + uint32_t version; ///< little-endian or 4-char string + lump_t lumps[HEADER_LUMPS];///< Identical between BSP 2 and BSP 29 } dheader_t; +#define BSPVERSION 29 ///< little-endian uint32_t +#define BSP2VERSION "BSP2" ///< 4-char unterminated string +#define Q2BSPVERSION 38 ///< Not supported +#define TOOLVERSION 2 ///< Not used +///@} + +/** \defgroup bsp_model BSP File sub-model + \ingroup formats_bsp + + The sub-model lump is an array of sub-model descriptors. Every BSP file + has at least one sub-model, with sub-model index 0 being the main model. +*/ +///@{ +typedef struct dmodel_s { + /// \name Bounding box for the model + ///@{ + float mins[3]; ///< minimum X, Y, Z + float maxs[3]; ///< maximum X, Y, Z + ///@} + float origin[3]; ///< unclear + /// Index of the first node for each hull. The first headnode index + /// is for the draw nodes (\ref bsp_nodes), while subsequent headnodes + /// are for the clipnodes (\ref bsp_clipnodes). + /// The engine builds a clip node tree for headnods[0] from the draw + /// nodes at load time. + uint32_t headnode[MAX_MAP_HULLS]; + /// The number of visible leafs in the model. + /// \note Does *not* include leaf 0 (the infinite solid leaf in most maps) + uint32_t visleafs; + /// \name Visible faces + /// A sub-model's visible faces are all in one contiguous block. + ///@{ + uint32_t firstface; ///< Index of first visible face in model + uint32_t numfaces; ///< Number of visible faces in model + ///@} +} dmodel_t; +///@} + +/** \defgroup bsp_textures BSP File texture data + \ingroup formats_bsp + + The texture data in a BSP file forms a sub-file with its own structure. +*/ +///@{ + +/** Header for the textures lump. + + The size is variable as there is one dataofs element for each miptex + block. +*/ typedef struct dmiptexlump_s { + /// Number of miptex blocks in the textures lump. uint32_t nummiptex; - uint32_t dataofs[4]; // [nummiptex] + /// Offsets are relative to the beginning of the dmiptexlump_t structure + /// (ie, the textures lump). One for each miptex block. \ref miptex_s + uint32_t dataofs[4]; } dmiptexlump_t; -#define MIPTEXNAME 16 -#define MIPLEVELS 4 +#define MIPTEXNAME 16 ///< Names have a max length of 15 chars +#define MIPLEVELS 4 ///< Number of mip levels in all miptex +/** Header for individual mip-mapped texture. + + The beginning of the name of the texture specifies some of the texture's + properties: + - sky The texture is used for the dual-layer skies. Expected + to be 256x128. Sky face get special treatment by the + renderer. + - * "Water" face. Texture-warped by the renderer. Usually + unlit (ie, always full-bright). + - + Member of an animation group. The second character of + the texture's name determines to which animation sequence + the texture belongs and the texture's position in that + sequence. The rest of the name specifies the group name. + \ref bsp_texture_animation + + The texture may be rectangular, but the size must be a multiple of 16 + pixels in both directions. +*/ typedef struct miptex_s { - char name[MIPTEXNAME]; - uint32_t width, height; - uint32_t offsets[MIPLEVELS]; // four mip maps stored + char name[MIPTEXNAME]; ///< Texture name. Nul-terminated. + uint32_t width; ///< Width of the full-size texture + uint32_t height; ///< Height of the full-size texture + /// Offsets are relative to the beginning of the individual miptex block. + uint32_t offsets[MIPLEVELS]; } miptex_t; +///@} +/** \defgroup bsp_vertices BSP File vertex lump + \ingroup formats_bsp + Array of unique vertices. + + Vertices are shared between edges and faces. +*/ +///@{ typedef struct dvertex_s { - float point[3]; + float point[3]; ///< X, Y, Z } dvertex_t; +///@} -// 0-2 are axial planes -#define PLANE_X 0 -#define PLANE_Y 1 -#define PLANE_Z 2 -// 3-5 are non-axial planes snapped to the nearest -#define PLANE_ANYX 3 -#define PLANE_ANYY 4 -#define PLANE_ANYZ 5 +/** \defgroup bsp_planes BSP File plane lump + \ingroup formats_bsp + Array of unique planes. + + Planes are shared between nodes and faces. +*/ +///@{ typedef struct dplane_s { - float normal[3]; - float dist; - int32_t type; // PLANE_X - PLANE_ANYZ + float normal[3]; ///< Plane normal + float dist; ///< Distance of the plane from the origin + int32_t type; ///< \ref bsp_plane_definition } dplane_t; +///@} -#define CONTENTS_EMPTY -1 -#define CONTENTS_SOLID -2 -#define CONTENTS_WATER -3 -#define CONTENTS_SLIME -4 -#define CONTENTS_LAVA -5 -#define CONTENTS_SKY -6 -#define CONTENTS_ORIGIN -7 // removed at csg time -#define CONTENTS_CLIP -8 // changed to contents_solid +/** \defgroup bsp_plane_definition Plane definitions + \ingroup bsp_planes + Planes are always canonical in that thier normals always point along + a positive axis for axial planes ((1, 0, 0), (0, 1, 0), or (0, 0, 1)), + or the largest component is positive. +*/ +///@{ +/// \name Axial planes +///@{ +#define PLANE_X 0 ///< Plane normal points along +X axis +#define PLANE_Y 1 ///< Plane normal points along +Y axis +#define PLANE_Z 2 ///< Plane normal points along +Z axis +///@} +/// \name Non-axial planes. Specifies the closest axis. +///@{ +#define PLANE_ANYX 3 ///< Plane normal close to +X +#define PLANE_ANYY 4 ///< Plane normal close to +Y +#define PLANE_ANYZ 5 ///< Plane normal close to +Z +///@} +///@} -#define CONTENTS_CURRENT_0 -9 -#define CONTENTS_CURRENT_90 -10 -#define CONTENTS_CURRENT_180 -11 -#define CONTENTS_CURRENT_270 -12 -#define CONTENTS_CURRENT_UP -13 -#define CONTENTS_CURRENT_DOWN -14 +/** \defgroup bsp_nodes BSP nodes lump + \ingroup formats_bsp -//BSP2 version (bsp 29 version is in bspfile.c) -typedef struct dnode_s { - uint32_t planenum; - int32_t children[2]; // negative numbers are -(leafs+1), not nodes - float mins[3]; // for sphere culling - float maxs[3]; - uint32_t firstface; - uint32_t numfaces; // counting both sides + These nodes form the visible BSP. While not all nodes will have faces, + most (or at least many) will, as the nodes are used for depth-sorting the + faces while traversing the BSP tree using front-depth-first-in-order + traversal. + + They can also be used for collision detection as the leaf nodes indicate + the contents of the volume. The engine takes advantage of this to + construct hull 0 (disk space was still very precious in 1996) +*/ +///@{ + +/** Spit a convex region of space into two convex regions. + + The node's plane divides the space into a front side and a back side, + where a point is in front of the plane if its dot product with the plane + normal is positive or 0, and ond behind (in back of) the plane if the + dot product is negative. +*/ +typedef struct dnode_s { //BSP2 version (bsp 29 version is in bspfile.c) + uint32_t planenum; ///< Index of plane defining this node + /// Indices of the child nodes on the front [0] and back [1] side of this + /// node. Negative indicies indicate leaf nodes, where the leaf index is + /// -(child + 1) (or child is -(leaf + 1)). + int32_t children[2]; + /// \name Node bounding box + ///@{ + float mins[3]; ///< minimum X, Y, Z + float maxs[3]; ///< maximum X, Y, Z + ///@} + /// \name Node plane faces + /// List of \ref bsp_face faces on the node's plane. Used for + /// depth-sorting the faces while traversing the visible BSP tree. + ///@{ + uint32_t firstface; ///< index of first face on nonde plane + uint32_t numfaces; ///< numer of faces on node plane (both sides) + ///@} } dnode_t; +///@} -//BSP2 version (bsp 29 version is in bspfile.c) -typedef struct dclipnode_s { - uint32_t planenum; - int32_t children[2]; // negative numbers are contents +/** \defgroup bsp_clipnodes BSP clipping nodes lump + \ingroup formats_bsp + + Compact BSP tree for collision detection. +*/ +///@{ +typedef struct dclipnode_s { //BSP2 version (bsp 29 version is in bspfile.c) + uint32_t planenum; ///< Index of plane defining this node + /// Indices of the child nodes on the front [0] and back [1] side of this + /// node. Negative indicies indicate leaf contents. + /// \ref bsp_leaf_contents + int32_t children[2]; } dclipnode_t; +///@} +/** \defgroup bsp_texinfo BSP texture information lump + \ingroup formats_bsp + Texture mapping information for visible faces. An individual texinfo may + be shared by many faces. +*/ +///@{ typedef struct texinfo_s { - float vecs[2][4]; // [s/t][xyz offset] + /// The texture plane basis vectors, with the \a s basis vector in index + /// 0 and the \a t basis vector in index 1. + /// For each index, the first three elements are the X, Y, Z components + /// of the basis vector, and the fourth component is the offset. Can be + /// viewed as a 2 row x 4 column matrix (\a M) that is multiplied by + /// a homogeneos vector (\a v) for a face vertex to determine that + /// vertex's UV coordinates (ie, \a M \a v) + float vecs[2][4]; + /// Index of the miptex block in the texture data lump + /// (\ref bsp_textures). If the referenced miptex is a member of + /// an animation group, then the entire group is used by this texinfo. uint32_t miptex; - uint32_t flags; + uint32_t flags; ///< \ref bsp_texinfo_flags } texinfo_t; -#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision -#define TEX_MISSING 2 // this texinfo does not have a texture +///@} -// note that edge 0 is never used, because negative edge nums are used for -// counterclockwise use of the edge in a face -//BSP2 version (bsp 29 version is in bspfile.c) -typedef struct dedge_s { - uint32_t v[2]; // vertex numbers +/** \defgroup bsp_texinfo_flags BSP texture information flags + \ingroup bsp_texinfo +*/ +///@{ +#define TEX_SPECIAL 1 ///< sky or slime, no lightmap, 256 subdivision +#define TEX_MISSING 2 ///< this texinfo does not have a texture (N/U) +///@} + +/** \defgroup bsp_edges BSP edges lump + \ingroup formats_bsp + + \note Edge 0 is never used as negative edge indices are indicate + counterclockwise use of the edge in a face. +*/ +///@{ +typedef struct dedge_s { //BSP2 version (bsp 29 version is in bspfile.c) + uint32_t v[2]; ///< vertex indices in winding order } dedge_t; +///@} -#define MAXLIGHTMAPS 4 -//BSP2 version (bsp 29 version is in bspfile.c) -typedef struct dface_s { - uint32_t planenum; +/** \defgroup bsp_face BSP visible faces + \ingroup formats_bsp +*/ +///@{ +typedef struct dface_s { //BSP2 version (bsp 29 version is in bspfile.c) + uint32_t planenum; ///< Index of the plane containing this face + /// Indicates the side of the plane considered to be the front for this + /// face. 0 indicates the postive normal side, 1 indicates the negative + /// normal side (ie, the face is on the back side of the plane). int32_t side; - uint32_t firstedge; // we must support > 64k edges - uint32_t numedges; + /// \name List of edge indices in clockwise order + /// \ref bsp_surfedges + /// Negative edge indices indicate that the edge is being used in its + /// reverse direction (ie, \a v[1] to \a v[0] instead of \a v[0] to + /// \a v[1]). + /// \note This is a double-indirection. + ///@{ + uint32_t firstedge; ///< Index of first edge index + uint32_t numedges; ///< Number of edge indices + ///@} + /// Index of texinfo block describing texture mapping and miptex reference + /// for this face. uint32_t texinfo; -// lighting info + /// \name lighting info + ///@{ +#define MAXLIGHTMAPS 4 + /// List of lighting styles affecting the lightmaps affecting this face. + /// 255 indicates both no style thus no lightmap and the end of the list. byte styles[MAXLIGHTMAPS]; - uint32_t lightofs; // start of [numstyles*surfsize] samples + /// Offset into the lighting data (ref bsp_lighting) of the first lightmap + /// affecting this face. The number of lightmaps affecting this face is + /// inferred from the \a styles array. The size of each lightmap is + /// determined from the texture extents of the face as (E / 16 + 1) + /// (integer division). Thus the total lightmap data for this face is + /// given by (nummaps * (Es / 16 + 1) * (Et / 16 + 1)) bytes. + /// The lightmap data is 8-bit, ranging from 0 to 255. + /// + /// -1 indicates no lightmap data. + uint32_t lightofs; + ///@} } dface_t; +///@} +/** \defgroup bsp_leafs BSP leafs lump + \ingroup formats_bsp + leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas + all other leafs need visibility info +*/ +///@{ + +/** A convex volume of space delimited by the surrounding node planes. + + With the exception of the generic solid leaf at index 0, *ALL* leafs are + convex polyhedra. However, they will generally not be manifold as + otherwise it would not be possible to see into or out of a leaf, nor for + an entity to pass in or out of one. +*/ +typedef struct dleaf_s { //BSP2 version (bsp 29 version is in bspfile.c) + /// The contents of the leaf. \ref bsp_leaf_contents + int32_t contents; + /// Offset into the \ref bsp_visibility data block for this leaf's + /// visibility data. -1 if the leaf has no visibility data. + int32_t visofs; + + /// \name Bounding box for frustum culling + ///@{ + float mins[3]; ///< minimum X, Y, Z + float maxs[3]; ///< maximum X, Y, Z + ///@} + + /// \name Visible faces of the leaf + /// List of face indices that form the visible faces of the leaf. + /// \note This is a double-indirection. + ///@{ + uint32_t firstmarksurface; ///< index of first visible face index + uint32_t nummarksurfaces; ///< number of indices + ///@} + +#define NUM_AMBIENTS 4 + /// automatic ambient sounds \ref bsp_leaf_ambient + byte ambient_level[NUM_AMBIENTS]; +} dleaf_t; +///@} + +/** \defgroup bsp_leaf_contents BSP leaf contents + \ingroup bsp_leafs +*/ +///@{ +#define CONTENTS_EMPTY -1 ///< Open, transparent, passable space +#define CONTENTS_SOLID -2 ///< Solid, opaque, impassible space +#define CONTENTS_WATER -3 ///< Buoyant, translucent, passable space +#define CONTENTS_SLIME -4 ///< Like water, but toxic +#define CONTENTS_LAVA -5 ///< Like water, but hot +#define CONTENTS_SKY -6 ///< FIXME sky, but... +#define CONTENTS_ORIGIN -7 ///< removed at csg time +#define CONTENTS_CLIP -8 ///< changed to CONTENTS_SOLID + +#define CONTENTS_CURRENT_0 -9 ///< changed to CONTENTS_WATER +#define CONTENTS_CURRENT_90 -10 ///< changed to CONTENTS_WATER +#define CONTENTS_CURRENT_180 -11 ///< changed to CONTENTS_WATER +#define CONTENTS_CURRENT_270 -12 ///< changed to CONTENTS_WATER +#define CONTENTS_CURRENT_UP -13 ///< changed to CONTENTS_WATER +#define CONTENTS_CURRENT_DOWN -14 ///< changed to CONTENTS_WATER +///@} + +/** \defgroup bsp_leaf_ambient BSP leaf ambient sounds + \ingroup bsp_leafs +*/ +///@{ #define AMBIENT_WATER 0 #define AMBIENT_SKY 1 #define AMBIENT_SLIME 2 #define AMBIENT_LAVA 3 +///@} -#define NUM_AMBIENTS 4 // automatic ambient sounds +/** \defgroup bsp_entities Entity data string + \ingroup formats_bsp -// leaf 0 is the generic CONTENTS_SOLID leaf, used for all solid areas -// all other leafs need visibility info -//BSP2 version (bsp 29 version is in bspfile.c) -typedef struct dleaf_s { - int32_t contents; - int32_t visofs; // -1 = no visibility info + Single string containing all the entity dictionaries (edicts). - float mins[3]; // for frustum culling - float maxs[3]; + The format is extremely simple in that is is a series of blocks delimited + by { and }. Blocks cannot be nested. A { after a { but before a } will be + treated as either a key or a value. A } after a } but before a { is not + valid. { must be the first non-whitespace character in the string. } must + be the last non-whitespace character in the string if there is a {. - // the list of marksurfaces is the surfaces that make up the effective - // mesh of the leaf - uint32_t firstmarksurface; - uint32_t nummarksurfaces; + The contents of a block consist of a series of key-value strinng pairs. + Unless the string contains spaces or punctuaiont (one of "{}()':") double + quote (") around the string are optional. Keys and values are separated + by whitespace (optional if quotes are used) but must be on the same line, + but it is best to use a space. Key-value pairs may be on separate lines + (prefered for readability). - byte ambient_level[NUM_AMBIENTS]; -} dleaf_t; + Key strings are Quake-C entity field names. Value strings are interpreted + based on the type of the field. -//============================================================================ + Below is a sample edict + \verbatim + { + "origin" "-2528 -384 512" + "angle" "270" + "classname" "info_player_start" + } + \endverbatim + + As an extention, QuakeForge supports \ref property-list entity string data + if the first non-whitespace character is a (. QuakeForge progs can register + a custom parser for the resulting property list, but the default parser + supports only a single array of dictionaries containing only simple + key-value string pairs. +*/ + +/** \defgroup bsp_lighting Lighting data + \ingroup formats_bsp + + Pre-computed lightmap data. Each byte represents a single lightmap + pixel, thus a lightmap is luminance with values ranging from 0 for + full-dark to 255 for full-bright. The pixels for each lightmap (up + to four) for each visible face form a linear stream. + + Computed using tools such as qflight. +*/ + +/** \defgroup bsp_marksurfaces BSP Leaf faces + \ingroup formats_bsp + + Array of face indices representing the faces on the leafs. The face + indices are grouped by leaf. Because whether a face gets split depends + on how the nodes split space, a face may be shared by multiple leafs. + FIXME needs confirmation, but maps with more leaf face indices than + faces in the face array have observed. +*/ + +/** \defgroup bsp_surfedges BSP face edges + \ingroup formats_bsp + + Array of edge indices specifying the edges used in face polyons. + + The edges are grouped by face polygon, and are listed in clockwise order + from that face's perspective (when looking at the face from that face's + front side). + + As actual edges are reused and thus shared by faces, negative edge + indices indicate that the edge is to be reversed. That is, instead of + going from \a v[0] to \a v[1] for edges referenced by positive indices, + go from \a v[1] to \a v[0] for edges referenced by negative indices. + \ref bsp_edges +*/ + +/** \defgroup bsp_visibility BSP visibility data + \ingroup formats_bsp + + The primary culling data in a Quake BSP. Conceptually, it is just an + array of bit-sets representing the leafs visible from each leaf. + However, leaf 0 is not represented in the data at all: there is now row + for leaf 0 (first row is for leaf 1's visible leafs), and the first bit + in each row represents leaf 1. + + As well, the data within a row is compressed: runs of 0-bytes + (representing eight non-visible leafs) are represented as a 0 followed + by a single count byte. For example, a run of eight 0-bytes will appear + as 0x00 0x08, and a single 0 byte will appear as 0x00 0x01. + + Computed using tools such as \a qfvis. +*/ + +/** \defgroup bsp_texture_animation BSP Texture Animation + \ingroup formats_bsp + + Textures in BSP files can be animated. Animated textures are those + with miptex names in a special format: + + \verbatim + +Sname + \endverbatim + + That is, the miptex name starts with a +, followed by a single sequence + id character (0-9 or A-J (or a-j, case-insensitive)) then the name of the + animation group is formed by the remaining characters. Thus an animation + group can have one or two sequences with one to ten frames per sequence. + The two sequences are the main sequence (0-9) and the alternate sequence + (A-J). Gaps in a sequence are not allowed: there must always be a +0 or +A + miptex in the sequence, and there must be a texture for every digit or + letter up to the highest used. However, the miptex blocks can be in any + order within the textures block: the engine searches for them and sorts + them. + + Single-frame sequences are useful for simple static texture switchinng + based on game state (entity frame: 0 for main, non-zero for alternate). + Multi-frame sequences are played back at ten frames per second. + + For example, the folowing sets up an animitation with a 4-frame main + sequence and a 2-frame alternate sequence. Perhaps a roaring fire in + the main sequence and glowing coals in the alternate. + + \verbatim + +0fire // main sequence + +1fire // main sequence + +2fire // main sequence + +3fire // main sequence + +Afire // alternate sequence + +Bfire // alternate sequence + \endverbatim +*/ + +/** \defgroup bspfile BSP file manipulation + \ingroup utils +*/ +///@{ +/** Memory representation of the BSP file. + All data is in native endian format. +*/ typedef struct bsp_s { - int own_header; - dheader_t *header; + int own_header; ///< \a header is owned by the structure + dheader_t *header; ///< the bsp header block - int own_models; - size_t nummodels; - dmodel_t *models; + int own_models; ///< \a models is owned by the structure + size_t nummodels; ///< number of models + dmodel_t *models; ///< Array of sub-models - int own_visdata; - size_t visdatasize; - byte *visdata; + int own_visdata; ///< \a visdata is owned by the structure + size_t visdatasize; ///< number of bytes in visdata + byte *visdata; ///< \ref bsp_visibility - int own_lightdata; - size_t lightdatasize; - byte *lightdata; + int own_lightdata; ///< \a lightdata is owned by the structure + size_t lightdatasize; ///< number of bytes in lightdata + byte *lightdata; ///< \ref bsp_lighting - int own_texdata; - size_t texdatasize; - byte *texdata; // (dmiptexlump_t) + int own_texdata; ///< \a texdata is owned by the structure + size_t texdatasize; ///< number of bytes in texture data + byte *texdata; ///< \ref bsp_textures - int own_entdata; - size_t entdatasize; - char *entdata; + int own_entdata; ///< \a entdata is owned by the structure + size_t entdatasize; ///< number of bytes in entdata string + char *entdata; ///< \ref bsp_entities - int own_leafs; - size_t numleafs; - dleaf_t *leafs; + int own_leafs; ///< \a leafs is owned by the structure + size_t numleafs; ///< number of leafs + dleaf_t *leafs; ///< array of leafs - int own_planes; - size_t numplanes; - dplane_t *planes; + int own_planes; ///< \a planes is owned by the structure + size_t numplanes; ///< number of planes + dplane_t *planes; ///< array of planes - int own_vertexes; - size_t numvertexes; - dvertex_t *vertexes; + int own_vertexes; ///< \a vertexes is owned by the structure + size_t numvertexes; ///< number of vertices + dvertex_t *vertexes; ///< array of vertices - int own_nodes; - size_t numnodes; - dnode_t *nodes; + int own_nodes; ///< \a nodes is owned by the structure + size_t numnodes; ///< number of nodes + dnode_t *nodes; ///< array of nodes - int own_texinfo; - size_t numtexinfo; - texinfo_t *texinfo; + int own_texinfo; ///< \a texinfo is owned by the structure + size_t numtexinfo; ///< number of texinfo blocks + texinfo_t *texinfo; ///< array of texinfo blocks - int own_faces; - size_t numfaces; - dface_t *faces; + int own_faces; ///< \a faces is owned by the structure + size_t numfaces; ///< number of faces + dface_t *faces; ///< array of faces - int own_clipnodes; - size_t numclipnodes; - dclipnode_t *clipnodes; + int own_clipnodes; ///< \a clipnodes is owned by the structure + size_t numclipnodes; ///< number of clipnodes + dclipnode_t *clipnodes; ///< array of clipnodes - int own_edges; - size_t numedges; - dedge_t *edges; + int own_edges; ///< \a edges is owned by the structure + size_t numedges; ///< number of edges + dedge_t *edges; ///< array of edges - int own_marksurfaces; - size_t nummarksurfaces; - uint32_t *marksurfaces; + int own_marksurfaces;///< \a marksurfaces is owned by the structure + size_t nummarksurfaces; ///< number of marksurface indices + uint32_t *marksurfaces; ///< array of marksurfaces indices - int own_surfedges; - size_t numsurfedges; - int32_t *surfedges; + int own_surfedges; ///< \a surfedge is owned by the structure + size_t numsurfedges; ///< number of surfedge indices + int32_t *surfedges; ///< array of surfedge indices } bsp_t; /** Create a bsp structure from a memory buffer. @@ -294,24 +698,184 @@ typedef struct bsp_s { */ bsp_t *LoadBSPMem (void *mem, size_t size, void (*cb) (const bsp_t *, void *), void *cbdata); +/** Load a bsp file into memory. + The return structre is set up the same as for LoadBSPMem, with the + exception that the BSP data memory is owned by the structure and will be + freed by BSP_Free. + + \param file The open file from which to read the BSP data. + \param size The number of bytes to read. The BSP data may be a section + in a larger file (eg, in a pak file). + \return Initialized bsp structure. +*/ bsp_t *LoadBSPFile (QFile *file, size_t size); +/** Write the bsp data to the given file. + Does any necessary byte-swapping to ensure the written data is in + little-endian format. Automatically selects BSP-2 or BSP-29 based on the + data: if any value is too large for BSP-29, BSP-2 will be written, + otherwise BSP-29 will be written. + + \param bsp The bsp data to be written to the given file. + \param file The file to which the data will be written. + + \note \a file is *not* closes. It is the caller's responsibility to close + \a file. +*/ void WriteBSPFile (const bsp_t *bsp, QFile *file); + +/** Create a fresh BSP struct ready to be populated with data. + Initially, none of the data pointers (which start as null) are owned by + the bsp, but as data is added using the Add functions, the pointers will + become owned. + + \return Pointer to a blank-slate BSP strucutre. + + \note Mixing use of an Add function with a private pointer for the + same data will result in undefined behavior. +*/ bsp_t *BSP_New (void); + +/** Free the BSP data. + + Only memory blocks owned by the BSP structure (and the structure itselve) + will be freed. + + \param bsp Pointer to the BSP structure to be freed. +*/ void BSP_Free (bsp_t *bsp); + +/** Add a single plane to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param plane Pointer to the single plane to be added to the BSP + structure. +*/ void BSP_AddPlane (bsp_t *bsp, const dplane_t *plane); + +/** Add a single leaf to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param leaf Pointer to the single leaf to be added to the BSP + structure. +*/ void BSP_AddLeaf (bsp_t *bsp, const dleaf_t *leaf); + +/** Add a single vertex to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param vertex Pointer to the single vertex to be added to the BSP + structure. +*/ void BSP_AddVertex (bsp_t *bsp, const dvertex_t *vertex); + +/** Add a single node to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param node Pointer to the single node to be added to the BSP + structure. +*/ void BSP_AddNode (bsp_t *bsp, const dnode_t *node); + +/** Add a single texinfo to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param texinfo Pointer to the single texinfo to be added to the BSP + structure. +*/ void BSP_AddTexinfo (bsp_t *bsp, const texinfo_t *texinfo); + +/** Add a single face to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param face Pointer to the single face to be added to the BSP + structure. +*/ void BSP_AddFace (bsp_t *bsp, const dface_t *face); + +/** Add a single clipnode to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param clipnode Pointer to the single clipnode to be added to the BSP + structure. +*/ void BSP_AddClipnode (bsp_t *bsp, const dclipnode_t *clipnode); + +/** Add a single marksurface to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param marksurface The single marksurface to be added to the BSP + structure. +*/ void BSP_AddMarkSurface (bsp_t *bsp, int marksurface); + +/** Add a single surfedge to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param surfedge Pointer to the single surfedge to be added to the BSP + structure. +*/ void BSP_AddSurfEdge (bsp_t *bsp, int surfedge); + +/** Add a single edge to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param edge Pointer to the single edge to be added to the BSP + structure. +*/ void BSP_AddEdge (bsp_t *bsp, const dedge_t *edge); + +/** Add a single model to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param model Pointer to the single model to be added to the BSP + structure. +*/ void BSP_AddModel (bsp_t *bsp, const dmodel_t *model); + +/** Add lighmap data to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param lightdata Pointer to the lightmap data to be added to the BSP + structure. ref bsp_lighting + \param lightdatasize The number of bytes in the lightmap data + + \note Call only once! +*/ void BSP_AddLighting (bsp_t *bsp, const byte *lightdata, size_t lightdatasize); + +/** Add visibilityd data to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param visdata Pointer to the visibility data to be added to the BSP + structure. \ref bsp_visibility + \param visdatasize The number of bytes in the visibility data + + \note Call only once! +*/ void BSP_AddVisibility (bsp_t *bsp, const byte *visdata, size_t visdatasize); + +/** Add an entity data string to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param entdata Pointer to the entity data string to be added to the BSP + structure. \ref bsp_entities + \param entdatasize The number of bytes in the entity data string + + \note Call only once! +*/ void BSP_AddEntities (bsp_t *bsp, const char *entdata, size_t entdatasize); + +/** Add texture data to the BSP data. + + \param bsp Pointer to the BSP structure to be modified. + \param texdata Pointer to the texture data to be added to the BSP + structure. \ref bsp_textures + \param texdatasize The number of bytes in the texture data + + \note Call only once! +*/ void BSP_AddTextures (bsp_t *bsp, const byte *texdata, size_t texdatasize); +///@} + #endif//__QF_bspfile_h From 688f17fda35e9236de4d6080684c4714b6695dbd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 May 2022 11:26:19 +0900 Subject: [PATCH 2844/3664] Correct some typos in comments/docs --- libs/input/in_binding.c | 2 +- libs/input/in_imt.c | 2 +- tools/qfbsp/source/solidbsp.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 562ac7636..8a0319934 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -365,7 +365,7 @@ in_bind_f (void) Sys_Printf ("in_bind imt device type number binding...\n"); Sys_Printf (" imt: the name of the input mapping table in which the" " intput will be bound\n"); - Sys_Printf (" device: the nickname or id of the devise owning" + Sys_Printf (" device: the nickname or id of the device owning" " the input to be bound\n"); Sys_Printf (" type: the type of input to be bound (axis or" " button)\n"); diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 5df45d7b8..2c2981369 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -897,7 +897,7 @@ static imtcmd_t imt_commands[] = { "contexts\n" "The new switcher will be attached to the specified context\n" "default_imt specifies the default imt to be used for all possible\n" - "states and must axis and be in the context.\n" + "states and must exist and be in the context.\n" "input0..inputN specify the inputs (cvar or button) used to set the\n" "switcher's state. As each input forms a bit in the state index,\n" "there will be 2**(N+1) states (so 4 inputs will result in 16\n" diff --git a/tools/qfbsp/source/solidbsp.c b/tools/qfbsp/source/solidbsp.c index a06ad512a..58cf56f62 100644 --- a/tools/qfbsp/source/solidbsp.c +++ b/tools/qfbsp/source/solidbsp.c @@ -110,7 +110,7 @@ FaceSide (const face_t *in, const plane_t *split) return SIDE_ON; } -/** Chose the best plane for dividing the bsp. +/** Choose the best plane for dividing the bsp. The clipping hull BSP doesn't worry about avoiding splits, so this function tries to find the plane that gives the most even split of the From 925300716b796d95855eed8bc9bdc791e44458f2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 May 2022 15:13:07 +0900 Subject: [PATCH 2845/3664] [mode] Go back to using dclipnode_t everywhere It was added only because FitzQuake used it in its pre-bsp2 large-map support. That support has been hidden in bspfile.c for some time now. This doesn't gain much other than having one less type to worry about. Well tested on Conflagrant Rodent (the map that caused the need for mclipnode_t in the first place). --- include/QF/model.h | 9 ++------- include/world.h | 2 +- libs/models/brush/model_brush.c | 4 ++-- libs/models/clip_hull.c | 8 ++++---- libs/models/portal.c | 2 +- libs/models/test/hulls.c | 24 ++++++++++++------------ libs/models/test/trace-id.c | 4 ++-- libs/models/test/trace-qf-bad.c | 2 +- libs/models/trace.c | 4 ++-- nq/source/world.c | 6 +++--- qw/source/pmovetst.c | 6 +++--- qw/source/world.c | 6 +++--- 12 files changed, 36 insertions(+), 41 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 89e0b8730..47a7a8baa 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -207,13 +207,8 @@ typedef struct mleaf_s { byte ambient_sound_level[NUM_AMBIENTS]; } mleaf_t; -typedef struct mclipnode_s { - unsigned planenum; - int children[2]; -} mclipnode_t; - typedef struct hull_s { - mclipnode_t *clipnodes; + dclipnode_t *clipnodes; plane_t *planes; int firstclipnode; int lastclipnode; @@ -256,7 +251,7 @@ typedef struct mod_brush_s { int *surfedges; unsigned numclipnodes; - mclipnode_t *clipnodes; + dclipnode_t *clipnodes; unsigned nummarksurfaces; msurface_t **marksurfaces; diff --git a/include/world.h b/include/world.h index 57bc973a6..cab559011 100644 --- a/include/world.h +++ b/include/world.h @@ -82,7 +82,7 @@ extern areanode_t sv_areanodes[AREA_NODES]; void SV_FreeAllEdictLeafs (void); -void SV_InitHull (hull_t *hull, mclipnode_t *clipnodes, plane_t *planes); +void SV_InitHull (hull_t *hull, dclipnode_t *clipnodes, plane_t *planes); void SV_ClearWorld (void); // called after the world model has been loaded, before linking any entities diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 34863d573..0b88504ab 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -818,7 +818,7 @@ static void Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) { dclipnode_t *in; - mclipnode_t *out; + dclipnode_t *out; hull_t *hull; int count, i; mod_brush_t *brush = &mod->brush; @@ -891,7 +891,7 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) static void Mod_MakeHull0 (model_t *mod) { - mclipnode_t *out; + dclipnode_t *out; hull_t *hull; int count, i, j; mnode_t *in, *child; diff --git a/libs/models/clip_hull.c b/libs/models/clip_hull.c index 0a01b62f1..0c9820eff 100644 --- a/libs/models/clip_hull.c +++ b/libs/models/clip_hull.c @@ -45,7 +45,7 @@ MOD_Alloc_Hull (int nodes, int planes) int size, i; size = sizeof (hull_t); - size += sizeof (mclipnode_t) * nodes + sizeof (plane_t) * planes; + size += sizeof (dclipnode_t) * nodes + sizeof (plane_t) * planes; size *= MAX_MAP_HULLS; size += sizeof (clip_hull_t); @@ -55,11 +55,11 @@ MOD_Alloc_Hull (int nodes, int planes) ch->hulls[0] = (hull_t *) &ch[1]; for (i = 1; i < MAX_MAP_HULLS; i++) ch->hulls[i] = &ch->hulls[i - 1][1]; - ch->hulls[0]->clipnodes = (mclipnode_t *) &ch->hulls[i - 1][1]; + ch->hulls[0]->clipnodes = (dclipnode_t *) &ch->hulls[i - 1][1]; ch->hulls[0]->planes = (plane_t *) &ch->hulls[0]->clipnodes[nodes]; for (i = 1; i < MAX_MAP_HULLS; i++) { ch->hulls[i]->clipnodes = - (mclipnode_t *) &ch->hulls[i - 1]->planes[planes]; + (dclipnode_t *) &ch->hulls[i - 1]->planes[planes]; ch->hulls[i]->planes = (plane_t *) &ch->hulls[i]->clipnodes[nodes]; } return ch; @@ -74,7 +74,7 @@ MOD_Free_Hull (clip_hull_t *ch) static void recurse_clip_tree (hull_t *hull, int num, int depth) { - mclipnode_t *node; + dclipnode_t *node; if (num < 0) { if (depth > hull->depth) diff --git a/libs/models/portal.c b/libs/models/portal.c index ca09be139..2745277b9 100644 --- a/libs/models/portal.c +++ b/libs/models/portal.c @@ -111,7 +111,7 @@ add_portal (clipport_t *portal, clipleaf_t *front, clipleaf_t *back) static clipleaf_t * carve_leaf (hull_t *hull, nodeleaf_t *nodeleafs, clipleaf_t *leaf, int num) { - mclipnode_t *node; + dclipnode_t *node; plane_t *plane; winding_t *winding, *fw, *bw; clipport_t *portal; diff --git a/libs/models/test/hulls.c b/libs/models/test/hulls.c index 1b7fa39ba..02e2db43d 100644 --- a/libs/models/test/hulls.c +++ b/libs/models/test/hulls.c @@ -10,7 +10,7 @@ // |ss\ . // 0 1 -static mclipnode_t clipnodes_simple_wedge[] = { +static dclipnode_t clipnodes_simple_wedge[] = { { 0, { 1, CONTENTS_EMPTY}}, { 1, {CONTENTS_EMPTY, CONTENTS_SOLID}}, }; @@ -34,7 +34,7 @@ hull_t hull_simple_wedge = { // sss|sss| |sss // 0 1 2 -static mclipnode_t clipnodes_tpp1[] = { +static dclipnode_t clipnodes_tpp1[] = { { 0, { 1, CONTENTS_SOLID}}, { 1, { 2, CONTENTS_SOLID}}, { 2, {CONTENTS_SOLID, CONTENTS_EMPTY}}, @@ -60,7 +60,7 @@ hull_t hull_tpp1 = { // sss|sss| |sss // 1 0 2 -static mclipnode_t clipnodes_tpp2[] = { +static dclipnode_t clipnodes_tpp2[] = { { 0, { 2, 1}}, { 1, {CONTENTS_SOLID, CONTENTS_SOLID}}, { 2, {CONTENTS_SOLID, CONTENTS_EMPTY}}, @@ -86,7 +86,7 @@ hull_t hull_tpp2 = { // sss| |www|sss // 1 0 2 -static mclipnode_t clipnodes_tppw[] = { +static dclipnode_t clipnodes_tppw[] = { { 0, { 2, 1}}, { 1, {CONTENTS_EMPTY, CONTENTS_SOLID}}, { 2, {CONTENTS_SOLID, CONTENTS_WATER}}, @@ -112,7 +112,7 @@ hull_t hull_tppw = { // |sss // ---+--- 0 // ss0,0ss -static mclipnode_t clipnodes_step1[] = { +static dclipnode_t clipnodes_step1[] = { { 0, { 1, CONTENTS_SOLID}}, { 1, {CONTENTS_EMPTY, 2}}, { 2, {CONTENTS_SOLID, CONTENTS_EMPTY}}, @@ -139,7 +139,7 @@ hull_t hull_step1 = { // |sss // ---+sss 2 // ss0,0ss -static mclipnode_t clipnodes_step2[] = { +static dclipnode_t clipnodes_step2[] = { { 0, { 1, 2}}, { 1, {CONTENTS_EMPTY, CONTENTS_SOLID}}, { 2, {CONTENTS_EMPTY, CONTENTS_SOLID}}, @@ -166,7 +166,7 @@ hull_t hull_step2 = { // sss| // sss+--- 1 // ss0,0ss -static mclipnode_t clipnodes_step3[] = { +static dclipnode_t clipnodes_step3[] = { { 0, { 1, 2}}, { 1, {CONTENTS_EMPTY, CONTENTS_SOLID}}, { 2, {CONTENTS_EMPTY, CONTENTS_SOLID}}, @@ -195,7 +195,7 @@ hull_t hull_step3 = { // |sss // ---+--- 0 // ss0,0ss -static mclipnode_t clipnodes_covered_step[] = { +static dclipnode_t clipnodes_covered_step[] = { { 0, { 1, CONTENTS_SOLID}}, { 1, { 3, 2}}, { 2, {CONTENTS_SOLID, CONTENTS_EMPTY}}, @@ -225,7 +225,7 @@ hull_t hull_covered_step = { // 0,0+--- 1 // /ssss // 2 ssss -static mclipnode_t clipnodes_ramp[] = { +static dclipnode_t clipnodes_ramp[] = { { 0, { 1, 2}}, { 1, {CONTENTS_EMPTY, CONTENTS_SOLID}}, { 2, {CONTENTS_EMPTY, CONTENTS_SOLID}}, @@ -254,7 +254,7 @@ hull_t hull_ramp = { // ss|sss|ss // -8 8 // looking at plane 0: back of 0 is empty, front of 0 has above hole -static mclipnode_t clipnodes_hole[] = { +static dclipnode_t clipnodes_hole[] = { { 0, { 1, CONTENTS_EMPTY}}, { 1, {CONTENTS_SOLID, 2}}, { 2, { 3, CONTENTS_SOLID}}, @@ -284,7 +284,7 @@ hull_t hull_hole = { // |sss| // ---+---+--- 0 // ss0,0s8,0ss -static mclipnode_t clipnodes_ridge[] = { +static dclipnode_t clipnodes_ridge[] = { { 0, { 1, CONTENTS_SOLID}}, { 1, {CONTENTS_EMPTY, 2}}, { 2, { 3, CONTENTS_EMPTY}}, @@ -320,7 +320,7 @@ hull_t hull_ridge = { // 0 -------.------- -20 // sssssssssssssss // sssssssssssssss -static mclipnode_t clipnodes_cave[] = { +static dclipnode_t clipnodes_cave[] = { { 0, { 1, CONTENTS_SOLID}}, { 1, { 2, 3}}, { 2, {CONTENTS_SOLID, 4}}, diff --git a/libs/models/test/trace-id.c b/libs/models/test/trace-id.c index da85a01d0..52ccb2d37 100644 --- a/libs/models/test/trace-id.c +++ b/libs/models/test/trace-id.c @@ -5,7 +5,7 @@ static int HullPointContents (hull_t *hull, int num, const vec3_t p) { float d; - mclipnode_t *node; + dclipnode_t *node; mplane_t *plane; while (num >= 0) @@ -37,7 +37,7 @@ HullPointContents (hull_t *hull, int num, const vec3_t p) static qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, const vec3_t p1, const vec3_t p2, trace_t *trace) { - mclipnode_t *node; + dclipnode_t *node; mplane_t *plane; float t1, t2; float frac; diff --git a/libs/models/test/trace-qf-bad.c b/libs/models/test/trace-qf-bad.c index 05d31581b..0bf56bbb0 100644 --- a/libs/models/test/trace-qf-bad.c +++ b/libs/models/test/trace-qf-bad.c @@ -94,7 +94,7 @@ MOD_TraceLine (hull_t *hull, int num, int side, empty, solid; tracestack_t *tstack; tracestack_t tracestack[256]; - mclipnode_t *node; + dclipnode_t *node; mplane_t *plane, *split_plane; VectorCopy (start_point, start); diff --git a/libs/models/trace.c b/libs/models/trace.c index d65a06c9a..2ee7cf7a4 100644 --- a/libs/models/trace.c +++ b/libs/models/trace.c @@ -786,7 +786,7 @@ MOD_TraceLine (hull_t *hull, int num, int side; tracestack_t *tstack; tracestack_t *tracestack; - mclipnode_t *node; + dclipnode_t *node; plane_t *plane; clipleaf_t *leaf; trace_state_t trace_state; @@ -927,7 +927,7 @@ MOD_HullContents (hull_t *hull, int num, const vec3_t origin, trace_t *trace) // follow origin down the bsp tree to find the "central" leaf while (num >= 0) { vec_t d; - mclipnode_t *node; + dclipnode_t *node; plane_t *plane; node = hull->clipnodes + num; diff --git a/nq/source/world.c b/nq/source/world.c index b8b423d83..9926abd26 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -135,7 +135,7 @@ typedef struct { /* HULL BOXES */ static hull_t box_hull; -static mclipnode_t box_clipnodes[6]; +static dclipnode_t box_clipnodes[6]; static plane_t box_planes[6]; @@ -146,7 +146,7 @@ static plane_t box_planes[6]; can just be stored out and get a proper hull_t structure. */ void -SV_InitHull (hull_t *hull, mclipnode_t *clipnodes, plane_t *planes) +SV_InitHull (hull_t *hull, dclipnode_t *clipnodes, plane_t *planes) { int side, i; @@ -532,7 +532,7 @@ int SV_HullPointContents (hull_t *hull, int num, const vec3_t p) { float d; - mclipnode_t *node; + dclipnode_t *node; plane_t *plane; while (num >= 0) { diff --git a/qw/source/pmovetst.c b/qw/source/pmovetst.c index b79e860e0..b1f5fb84e 100644 --- a/qw/source/pmovetst.c +++ b/qw/source/pmovetst.c @@ -46,7 +46,7 @@ #include "world.h" static hull_t box_hull; -static mclipnode_t box_clipnodes[6]; +static dclipnode_t box_clipnodes[6]; static plane_t box_planes[6]; @@ -107,7 +107,7 @@ inline int PM_HullPointContents (hull_t *hull, int num, const vec3_t p) { float d; - mclipnode_t *node; + dclipnode_t *node; plane_t *plane; while (num >= 0) { @@ -132,7 +132,7 @@ PM_PointContents (const vec3_t p) { float d; int num; - mclipnode_t *node; + dclipnode_t *node; hull_t *hull; plane_t *plane; diff --git a/qw/source/world.c b/qw/source/world.c index 7024bca6c..1c0de0270 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -135,7 +135,7 @@ typedef struct { /* HULL BOXES */ static hull_t box_hull; -static mclipnode_t box_clipnodes[6]; +static dclipnode_t box_clipnodes[6]; static plane_t box_planes[6]; @@ -146,7 +146,7 @@ static plane_t box_planes[6]; can just be stored out and get a proper hull_t structure. */ void -SV_InitHull (hull_t *hull, mclipnode_t *clipnodes, plane_t *planes) +SV_InitHull (hull_t *hull, dclipnode_t *clipnodes, plane_t *planes) { int side, i; @@ -532,7 +532,7 @@ int SV_HullPointContents (hull_t *hull, int num, const vec3_t p) { float d; - mclipnode_t *node; + dclipnode_t *node; plane_t *plane; while (num >= 0) { From 89f8dfce096240f0f1a637f002936f2665f1e2fa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 May 2022 16:47:47 +0900 Subject: [PATCH 2846/3664] [input] Clear button inputs when IN_ClearStates called This fixes the annoying persistence of inputs when respawning and changing levels. Axis input clearing is hooked up but does nothing as of yet. Active device input clearing has always been hooked up, but also does nothing in the evdev and x11 drivers. --- include/QF/input/binding.h | 2 ++ libs/input/in_axis.c | 12 ++++++++++++ libs/input/in_button.c | 13 +++++++++++++ libs/input/in_common.c | 2 ++ 4 files changed, 29 insertions(+) diff --git a/include/QF/input/binding.h b/include/QF/input/binding.h index e901b47a2..a81f8a05c 100644 --- a/include/QF/input/binding.h +++ b/include/QF/input/binding.h @@ -351,7 +351,9 @@ void IN_ButtonAction (in_button_t *buttin, int id, int pressed); int IN_RegisterButton (in_button_t *button); int IN_RegisterAxis (in_axis_t *axis); in_button_t *IN_FindButton (const char *name); +void IN_ButtonClearStates (void); in_axis_t *IN_FindAxis (const char *name); +void IN_AxisClearStates (void); void IN_ButtonAddListener (in_button_t *button, button_listener_t listener, void *data); void IN_ButtonRemoveListener (in_button_t *button, button_listener_t listener, diff --git a/libs/input/in_axis.c b/libs/input/in_axis.c index 303cc75ea..0c250b4ce 100644 --- a/libs/input/in_axis.c +++ b/libs/input/in_axis.c @@ -75,6 +75,18 @@ IN_FindAxis (const char *name) return Hash_Find (axis_tab, name); } +static void +axis_clear_state (void *_a, void *data) +{ + //FIXME what to do here? +} + +void +IN_AxisClearStates (void) +{ + Hash_ForEach (axis_tab, axis_clear_state, 0); +} + void IN_AxisAddListener (in_axis_t *axis, axis_listener_t listener, void *data) { diff --git a/libs/input/in_button.c b/libs/input/in_button.c index 97e4339ad..4847783eb 100644 --- a/libs/input/in_button.c +++ b/libs/input/in_button.c @@ -227,6 +227,19 @@ IN_ButtonRemoveListener (in_button_t *button, button_listener_t listener, } } +static void +button_clear_state (void *_rb, void *data) +{ + regbutton_t *rb = _rb; + button_release_cmd (rb->button); +} + +void +IN_ButtonClearStates (void) +{ + Hash_ForEach (button_tab, button_clear_state, 0); +} + static void in_button_shutdown (void *data) { diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 9d9920641..f4024c753 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -587,6 +587,8 @@ IN_ClearStates (void) rd->driver.clear_states (rd->data); } } + IN_AxisClearStates (); + IN_ButtonClearStates (); } #ifdef HAVE_EVDEV From 87f3c206f1983947003d5f8f1f19a299649fd729 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 May 2022 11:09:15 +0900 Subject: [PATCH 2847/3664] [simd] Remove some intrinsics uses GCC does a nice enough job compiling the more readable form (though admittedly, hadd is possibly more readable than what's there for dot[fd], hadd is supposedly slower than the shuffles and adds, and qfvis seems to support that). --- include/QF/simd/vec4d.h | 12 +++--------- include/QF/simd/vec4f.h | 31 +++---------------------------- 2 files changed, 6 insertions(+), 37 deletions(-) diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 58c18a8e1..04e4b81a2 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -198,12 +198,8 @@ vec4d_t dotd (vec4d_t a, vec4d_t b) { vec4d_t c = a * b; -#ifndef __AVX__ - c = (vec4d_t) { c[0] + c[1], c[0] + c[1], c[2] + c[3], c[2] + c[3] }; -#else - c = _mm256_hadd_pd (c, c); -#endif - c += (vec4d_t) {c[2], c[3], c[0], c[1]}; + c += (vec4d_t) { c[3], c[0], c[1], c[2] }; + c += (vec4d_t) { c[2], c[3], c[0], c[1] }; return c; } @@ -302,9 +298,7 @@ VISIBLE vec4d_t qconjd (vec4d_t q) { - const uint64_t sign = UINT64_C(1) << 63; - const vec4l_t neg = { sign, sign, sign, 0 }; - return (vec4d_t) ((vec4l_t) q ^ neg); + return (vec4d_t) { -q[0], -q[1], -q[2], q[3] }; } #ifndef IMPLEMENT_VEC4D_Funcs diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index 9ccda895e..ee92d928e 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -211,13 +211,8 @@ vec4f_t dotf (vec4f_t a, vec4f_t b) { vec4f_t c = a * b; -#ifndef __SSE3__ - float x = c[0] + c[1] + c[2] + c[3]; - c = (vec4f_t) { x, x, x, x }; -#else - c = _mm_hadd_ps (c, c); - c = _mm_hadd_ps (c, c); -#endif + c += (vec4f_t) { c[3], c[0], c[1], c[2] }; + c += (vec4f_t) { c[2], c[3], c[0], c[1] }; return c; } @@ -234,11 +229,7 @@ qmulf (vec4f_t a, vec4f_t b) vec4f_t c = crossf (a, b) + a * b[3] + a[3] * b; vec4f_t d = dotf (a, b); // zero out the vector component of dot product so only the scalar remains -#ifndef __SSE4_1__ d = (vec4f_t) { 0, 0, 0, d[3] }; -#else - d = _mm_insert_ps (d, d, 0xf7); -#endif return c - d; } @@ -314,8 +305,7 @@ VISIBLE vec4f_t qconjf (vec4f_t q) { - const vec4i_t neg = { 1u << 31, 1u << 31, 1u << 31, 0 }; - return (vec4f_t) ((vec4i_t) q ^ neg); + return (vec4f_t) { -q[0], -q[1], -q[2], q[3] }; } #ifndef IMPLEMENT_VEC4F_Funcs @@ -348,22 +338,7 @@ loadvec3f (const float *v3) { vec4f_t v4; -#ifndef __SSE4_1__ v4 = (vec4f_t) { v3[0], v3[1], v3[2], 0 }; -#else - // this had to be in asm otherwise gcc thinks v4 is only partially - // initialized, and gcc 10 does not use the zero flags when generating - // the code, resulting in a memory access to load a 0 into v4[3] - // - // The first instruction zeros v4[3] while loading v4[0] - asm ("\n\ - vinsertps $0x08, %1, %0, %0 \n\ - vinsertps $0x10, %2, %0, %0 \n\ - vinsertps $0x20, %3, %0, %0 \n\ - " - : "=v"(v4) - : "m"(v3[0]), "m"(v3[1]), "m"(v3[2])); -#endif return v4; } From 34da36e1cf5d7ce4fcb6a087b4ff7bf6682da0cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 May 2022 16:27:01 +0900 Subject: [PATCH 2848/3664] [gl_stub] Add a bunch of new stubs Gets gl_stub working with recent changes to QF. --- tools/gl_stub/gl_stub.c | 46 +++++++++++++++++++++++++++++++++++++++ tools/gl_stub/gls_norm.c | 42 ++++++++++++++++++++++++++++++----- tools/gl_stub/gls_trace.c | 43 ++++++++++++++++++++++++++++++------ 3 files changed, 118 insertions(+), 13 deletions(-) diff --git a/tools/gl_stub/gl_stub.c b/tools/gl_stub/gl_stub.c index 87ff057c3..97ccfd191 100644 --- a/tools/gl_stub/gl_stub.c +++ b/tools/gl_stub/gl_stub.c @@ -15,6 +15,7 @@ typedef XID GLXDrawable; typedef struct __GLXcontextRec *GLXContext; +typedef struct __GLXFBConfigRec *GLXFBConfig; #define TRACE do { \ puts (__FUNCTION__);\ @@ -149,3 +150,48 @@ glXGetConfig (Display *dpy, XVisualInfo *visual, int attrib, int *value ) TRACE; return 0; } + +GLXFBConfig * +glXChooseFBConfig (Display *dpy, int screen, int *attribList, int *count) +{ + if (trace) + TRACE; + GLXFBConfig *cfg = calloc (1, sizeof (GLXFBConfig)); + *cfg = (GLXFBConfig) (intptr_t) screen; + return cfg; +} + +XVisualInfo * +glXGetVisualFromFBConfig (Display *dpy, GLXFBConfig config) +{ + XVisualInfo template; + int num_visuals; + int template_mask; + int screen; + + if (trace) + TRACE; + + screen = (intptr_t) config; + template_mask = 0; + template.visualid = + XVisualIDFromVisual (XDefaultVisual (dpy, screen)); + template_mask = VisualIDMask; + return XGetVisualInfo (dpy, template_mask, &template, &num_visuals); +} + +int +glXGetFBConfigAttrib (Display *dpy, GLXFBConfig config, int attribute, int *value) +{ + if (trace) + TRACE; + return 0; +} + +GLXContext +glXCreateContextAttribsARB (Display *dpy, GLXFBConfig cfg, GLXContext ctx, Bool direct, const int *attribs) +{ + if (trace) + TRACE; + return (GLXContext)1; +} diff --git a/tools/gl_stub/gls_norm.c b/tools/gl_stub/gls_norm.c index 3fe4c4c67..0a0b55d55 100644 --- a/tools/gl_stub/gls_norm.c +++ b/tools/gl_stub/gls_norm.c @@ -227,11 +227,6 @@ norm_glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderb { } -void -norm_glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) -{ -} - void norm_glGenBuffers (GLsizei n, GLuint* buffers) { @@ -1196,7 +1191,7 @@ norm_glGetIntegerv (GLenum pname, GLint * params) { switch (pname) { case GL_MAX_TEXTURE_SIZE: - *params = 512; + *params = 2048; break; case GL_UNPACK_ALIGNMENT: case GL_PACK_ALIGNMENT: @@ -2466,3 +2461,38 @@ void norm_glPNTrianglesiATI (GLint x, GLint y) { } + +void +norm_glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ +} + +void +norm_glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ +} + +void +norm_glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer) +{ +} + +void +norm_glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level) +{ +} + +void +norm_glNamedFramebufferTexture (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) +{ +} + +void +norm_glCreateVertexArrays (GLsizei n, GLuint *arrays) +{ +} + +void +norm_glBindVertexArray (GLuint array) +{ +} diff --git a/tools/gl_stub/gls_trace.c b/tools/gl_stub/gls_trace.c index c34f69db9..bdc361249 100644 --- a/tools/gl_stub/gls_trace.c +++ b/tools/gl_stub/gls_trace.c @@ -256,12 +256,6 @@ trace_glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum render TRACE; } -void -trace_glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) -{ - TRACE; -} - void trace_glGenBuffers (GLsizei n, GLuint* buffers) { @@ -1413,7 +1407,7 @@ trace_glGetIntegerv (GLenum pname, GLint * params) TRACE; switch (pname) { case GL_MAX_TEXTURE_SIZE: - *params = 512; + *params = 2048; break; case GL_UNPACK_ALIGNMENT: case GL_PACK_ALIGNMENT: @@ -2926,3 +2920,38 @@ trace_glPNTrianglesiATI (GLint x, GLint y) { TRACE; } + +void +trace_glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ +} + +void +trace_glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ +} + +void +trace_glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer) +{ +} + +void +trace_glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level) +{ +} + +void +trace_glNamedFramebufferTexture (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) +{ +} + +void +trace_glCreateVertexArrays (GLsizei n, GLuint *arrays) +{ +} + +void +trace_glBindVertexArray (GLuint array) +{ +} From 78a0075be14a8613dc7e37a69631e44fb7e504fc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 May 2022 12:15:15 +0900 Subject: [PATCH 2849/3664] [gamecode] Plug a nasty buffer overflow This one is ancient: the code was essentially unmodified since release (just some formatting). Malformed vectors could sneak through due to map bugs (eg, "angles -90" instead of "angle -90" as in ad_tears) and the vector parsing code would continue past the end of the string and writing into unowned memory, potentially messing up the libc allocation records. Replacing with the obvious sscanf works nicely. Sometimes, Quake code is brilliant. Other times, it's a real face-palm. --- libs/gamecode/pr_parse.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index c48617924..1f8f3cebd 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -215,10 +215,7 @@ ED_NewString (progs_t *pr, const char *string) VISIBLE qboolean ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) { - int i; - char *string; pr_def_t *def; - char *v, *w; pr_type_t *d; dfunction_t *func; @@ -234,17 +231,18 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) break; case ev_vector: - string = strdup (s); - v = string; - w = string; - for (i = 0; i < 3; i++) { - while (*v && *v != ' ') - v++; - *v = 0; - (&PR_PTR (float, d))[i] = atof (w); - w = v = v + 1; + vec3_t vec = {}; + char *str = alloca (strlen (s) + 1); + strcpy (str, s); + for (char *v = str; *v; v++) { + if (*v == ',') { + *v = ' '; + } } - free (string); + if (sscanf (s, "%f %f %f", VectorExpandAddr (vec)) != 3) { + Sys_Printf ("Malformed vector %s\n", s); + } + VectorCopy (vec, PR_PTR (vector, d)); break; case ev_entity: From 5cfbafc176a1cae9017c637112ea7662784db67f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 May 2022 15:43:18 +0900 Subject: [PATCH 2850/3664] [audio] Fix some minor issues Just little niggles I spotted while sorting out cue points. --- include/QF/sound.h | 2 -- libs/audio/renderer/snd_mem.c | 10 ++++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/QF/sound.h b/include/QF/sound.h index 3e6237962..dc051f193 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -68,8 +68,6 @@ struct sfx_s }; ///@} -struct model_s; - /** \defgroup sound_init Initialization functions \ingroup sound */ diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index c76d3e923..260f16a37 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -134,7 +134,7 @@ SND_StreamRelease (sfx_t *sfx) wavinfo_t * SND_CacheWavinfo (sfx_t *sfx) { - return &sfx->data.stream->wavinfo; + return &sfx->data.block->wavinfo; } wavinfo_t * @@ -161,9 +161,11 @@ read_samples (sfxbuffer_t *buffer, int count) if ((c = stream->read (stream, data, count)) != count) Sys_Printf ("%s nr %d %d\n", sfx->name, count, c); - buffer->head += count; - if (buffer->head >= buffer->length) - buffer->head -= buffer->length; + if (c > 0) { + buffer->head += count; + if (buffer->head >= buffer->length) + buffer->head -= buffer->length; + } } } From e96772419668dd2258ac8fc1df662dad819cbfd5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 May 2022 15:44:34 +0900 Subject: [PATCH 2851/3664] [audio] Handle multiple cue points in wav files Sounds in Arcane Dimensions (at least those used by ad_tears) specify start and end cue points. The code was using only the final point in the list and thus breaking looped sounds. Now, the first cue point is used as the loop start, and the second (if present), the sample length. Both are bounds-checked against the wav's sample count. Fixes sound locking up during the first seconds in ad_tears. --- libs/audio/renderer/wav.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index 51228cf02..2129973f1 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -181,14 +181,13 @@ wav_get_info (QFile *file) riff_data_t *data = 0; riff_cue_t *cue; - riff_d_cue_t *dcue; - riff_d_cue_point_t *cp = 0; + riff_d_cue_t *dcue = 0; riff_list_t *list; riff_d_chunk_t **lck; - riff_ltxt_t *ltxt; - riff_d_ltxt_t *dltxt = 0; + //riff_ltxt_t *ltxt; + //riff_d_ltxt_t *dltxt = 0; wavinfo_t info; @@ -211,8 +210,6 @@ wav_get_info (QFile *file) case RIFF_CASE ('c','u','e',' '): cue = (riff_cue_t *) *ck; dcue = cue->cue; - if (dcue->count) - cp = &dcue->cue_points[dcue->count - 1]; break; case RIFF_CASE ('L','I','S','T'): list = (riff_list_t *) *ck; @@ -221,8 +218,8 @@ wav_get_info (QFile *file) for (lck = list->chunks; *lck; lck++) { RIFF_SWITCH ((*lck)->name) { case RIFF_CASE ('l','t','x','t'): - ltxt = (riff_ltxt_t *) *lck; - dltxt = <xt->ltxt; + //ltxt = (riff_ltxt_t *) *lck; + //dltxt = <xt->ltxt; break; } } @@ -252,15 +249,19 @@ wav_get_info (QFile *file) info.width = dfmt->bits_per_sample / 8; info.channels = dfmt->channels; info.frames = 0; - if (cp) { - info.loopstart = cp->sample_offset; - if (dltxt) - info.frames = info.loopstart + dltxt->len; + info.frames = data->ck.len / (info.width * info.channels); + if (dcue && dcue->count) { + if (dcue->cue_points[0].sample_offset < info.frames) { + info.loopstart = dcue->cue_points[0].sample_offset; + } + if (dcue->count > 1) { + info.frames = min (info.frames, dcue->cue_points[1].sample_offset); + } + //if (dltxt) + // info.frames = info.loopstart + dltxt->len; } else { info.loopstart = -1; } - if (!info.frames) - info.frames = data->ck.len / (info.width * info.channels); info.dataofs = *(int *)data->data; info.datalen = data->ck.len; From 3bb54bc20a6502107fe493eb3245ef5a1ce59724 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 May 2022 17:45:22 +0900 Subject: [PATCH 2852/3664] [renderer] Up some limits so I can test with ad_tears The map uses 41% of a 4k light map scrap, and 512 texture descriptors wasn't enough for vulkan. Ouch. I do need to get cvars on these things, but this will do for now (decades later...) --- libs/video/renderer/gl/gl_lightmap.c | 2 +- libs/video/renderer/glsl/glsl_lightmap.c | 2 +- libs/video/renderer/vulkan/qfpipeline.plist | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 4fdbe2840..a5e112b35 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -598,7 +598,7 @@ GL_BuildLightmaps (model_t **models, int num_models) } if (!light_scrap) { - light_scrap = GL_CreateScrap (2048, gl_lightmap_format, 1); + light_scrap = GL_CreateScrap (4096, gl_lightmap_format, 1); } else { GL_ScrapClear (light_scrap); } diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index 8fa99cb8a..cb57aaf31 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -206,7 +206,7 @@ glsl_R_BuildLightmaps (model_t **models, int num_models) //FIXME RGB support if (!light_scrap) { - light_scrap = GLSL_CreateScrap (2048, GL_LUMINANCE, 1); + light_scrap = GLSL_CreateScrap (4096, GL_LUMINANCE, 1); } else { GLSL_ScrapClear (light_scrap); } diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 2ee0f5846..a6fd3476e 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -109,7 +109,7 @@ }; texture_pool = { flags = free_descriptor_set; - maxSets = 512; + maxSets = 1024; bindings = ( { type = combined_image_sampler; From 0d609efbc6fad8cc1fbb7bc3afd6c4059a744558 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 May 2022 17:48:45 +0900 Subject: [PATCH 2853/3664] [vulkan] Implement water alpha I'm not sure it's working properly, but that compose pass is suspect, especially with respect to lighting. --- libs/video/renderer/vulkan/qfpipeline.plist | 2 +- libs/video/renderer/vulkan/shader/bsp_gbuf.frag | 1 + libs/video/renderer/vulkan/shader/bsp_sky.frag | 1 + libs/video/renderer/vulkan/shader/bsp_turb.frag | 5 ++++- libs/video/renderer/vulkan/shader/quakebsp.frag | 1 + libs/video/renderer/vulkan/vulkan_bsp.c | 11 +++++++++-- 6 files changed, 17 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index a6fd3476e..24ccdf848 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -350,7 +350,7 @@ { stageFlags = fragment; offset = 64; - size = "4 * 4 + 4"; + size = "4 * 4 + 4 + 4"; }, ); }; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index 843148635..b09d7232b 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -6,6 +6,7 @@ layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; + float alpha; }; layout (location = 0) in vec4 tl_st; diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index 357d5d55b..1734b5b12 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -10,6 +10,7 @@ layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; + float alpha; }; layout (location = 0) in vec4 tl_st; diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index 35faa1428..1c78dde73 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -6,6 +6,7 @@ layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; + float alpha; }; layout (location = 0) in vec4 tl_st; @@ -48,5 +49,7 @@ main (void) c = texture (Texture, t_st); e = texture (Texture, e_st); - frag_color = c + e;//fogBlend (c); + c += e; + c.a = alpha; + frag_color = c;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/shader/quakebsp.frag b/libs/video/renderer/vulkan/shader/quakebsp.frag index fe596246e..21a93d530 100644 --- a/libs/video/renderer/vulkan/shader/quakebsp.frag +++ b/libs/video/renderer/vulkan/shader/quakebsp.frag @@ -10,6 +10,7 @@ layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; + float alpha; }; layout (location = 0) in vec4 tl_st; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 12e2d3b22..f5d0d49b6 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -77,6 +77,7 @@ typedef struct bsp_push_constants_s { mat4f_t Model; quat_t fog; float time; + float alpha; } bsp_push_constants_t; static const char * __attribute__((used)) bsp_pass_names[] = { @@ -782,8 +783,11 @@ push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout, { VK_SHADER_STAGE_FRAGMENT_BIT, field_offset (bsp_push_constants_t, time), sizeof (constants->time), &constants->time }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (bsp_push_constants_t, alpha), + sizeof (constants->alpha), &constants->alpha }, }; - QFV_PushConstants (device, cmd, layout, 2, push_constants); + QFV_PushConstants (device, cmd, layout, 3, push_constants); } static void @@ -1112,7 +1116,10 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) turb_begin (rFrame); push_transform (identity, bctx->layout, device, bframe->cmdSet.a[QFV_bspTurb]); - bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; + bsp_push_constants_t frag_constants = { + .time = vr_data.realtime, + .alpha = r_wateralpha + }; push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspTurb]); for (is = bctx->waterchain; is; is = is->tex_chain) { From 8633ffe9d22403baa33c7bedc69154feacb04586 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 May 2022 10:45:48 +0900 Subject: [PATCH 2854/3664] Fix some MXE build issues Just some unused variables when vulkan debug is disabled and some scanf formats for qfcc vectors (and the safety net). --- libs/video/renderer/vulkan/resource.c | 4 ++++ tools/qfcc/source/qc-lex.l | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index 2eb08e6d7..b89b298b9 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -61,6 +61,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) buffer->buffer, name); dfunc->vkGetBufferMemoryRequirements (device->dev, buffer->buffer, &req); + (void) name; // for when QFV_duSetObjectName is empty } break; case qfv_res_buffer_view: @@ -92,6 +93,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) image->image, name); dfunc->vkGetImageMemoryRequirements (device->dev, image->image, &req); + (void) name; // for when QFV_duSetObjectName is empty } break; case qfv_res_image_view: @@ -199,6 +201,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) resource->name, obj->name); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER_VIEW, buffview->view, name); + (void) name; // for when QFV_duSetObjectName is empty } break; case qfv_res_image_view: @@ -215,6 +218,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) resource->name, obj->name); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, imgview->view, name); + (void) name; // for when QFV_duSetObjectName is empty } break; } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 495d69aa9..beaba7b4f 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -567,21 +567,21 @@ parse_int_vector (const char *token, int width) pr_type_t t[PR_SIZEOF (dvec4)]; } long_data = {}; pr_type_t *data = __builtin_choose_expr ( - sizeof (pr_long_t) == sizeof (long), long_data.t, (void) 0); + sizeof (pr_long_t) == sizeof (int64_t), long_data.t, (void) 0); switch (width) { case 4: - sscanf (token, "' %li %li %li %li '%c%c", + sscanf (token, "' %"SCNi64" %"SCNi64" %"SCNi64" %"SCNi64" '%c%c", &long_data.l[0], &long_data.l[1], &long_data.l[2], &long_data.l[3], &t1, &t2); break; case 3: - sscanf (token, "' %li %li %li '%c%c", + sscanf (token, "' %"SCNi64" %"SCNi64" %"SCNi64" '%c%c", &long_data.l[0], &long_data.l[1], &long_data.l[2], &t1, &t2); break; case 2: - sscanf (token, "' %li %li '%c%c", + sscanf (token, "' %"SCNi64" %"SCNi64" '%c%c", &long_data.l[0], &long_data.l[1], &t1, &t2); break; } From 7240d2dc80197c8ba43ef43b5af1eeabf858aebb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 May 2022 11:18:32 +0900 Subject: [PATCH 2855/3664] [model] Move plane info into mnode_t, and visframe out The main goal was to get visframe out of mnode_t to make it thread-safe (each thread can have its own visframe array), but moving the plane info into mnode_t made for better data access patters when traversing the bsp tree as the plane is right there with the child indices. Nicely, the size of mnode_t is the same as before (64 bytes due to alignment), with 4 bytes wasted. Performance-wise, there seems to be very little difference. Maybe slightly slower. The unfortunate thing about the change is the plane distance is negated, possibly leading to some confusion, particularly since the box and sphere culling functions were affected. However, this is so point-plane distance calculations can be done with a single 4d dot product. --- include/QF/mathlib.h | 10 ++- include/QF/model.h | 32 ++++----- include/QF/scene/entity.h | 2 +- include/r_internal.h | 3 +- include/r_local.h | 6 +- libs/models/brush/model_brush.c | 83 ++++++++++++----------- libs/scene/light.c | 2 +- libs/scene/scene.c | 4 +- libs/util/mathlib.c | 4 +- libs/video/renderer/gl/gl_rmain.c | 4 +- libs/video/renderer/gl/gl_rmisc.c | 2 +- libs/video/renderer/gl/gl_rsurf.c | 58 +++++++++------- libs/video/renderer/glsl/glsl_bsp.c | 58 +++++++++------- libs/video/renderer/glsl/glsl_main.c | 2 +- libs/video/renderer/r_bsp.c | 13 ++-- libs/video/renderer/r_efrag.c | 41 +++++------ libs/video/renderer/r_light.c | 62 ++++++++--------- libs/video/renderer/r_main.c | 2 +- libs/video/renderer/r_screen.c | 9 ++- libs/video/renderer/sw/sw_rbsp.c | 86 +++++++++++++----------- libs/video/renderer/sw/sw_rmain.c | 39 ++++++----- libs/video/renderer/vulkan/vulkan_bsp.c | 52 ++++++++------ libs/video/renderer/vulkan/vulkan_main.c | 2 +- nq/source/cl_screen.c | 2 +- nq/source/host.c | 2 +- nq/source/sv_main.c | 28 ++++---- nq/source/sv_pr_cmds.c | 6 +- nq/source/world.c | 19 +++--- qtv/source/client.c | 27 ++++---- qtv/source/sv_parse.c | 18 ++--- qw/source/cl_main.c | 2 +- qw/source/cl_screen.c | 2 +- qw/source/sv_ents.c | 33 ++++----- qw/source/sv_pr_cmds.c | 6 +- qw/source/sv_send.c | 7 +- qw/source/world.c | 19 +++--- 36 files changed, 397 insertions(+), 350 deletions(-) diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index 5f8c900d2..645220b40 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -136,6 +136,7 @@ void AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); void AngleQuat (const vec3_t angles, quat_t q); void VectorVectors (const vec3_t forward, vec3_t right, vec3_t up); +// NOTE expects plane distance is -p.n int BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, const plane_t *plane) __attribute__((pure)); float anglemod (float a) __attribute__((const)); @@ -143,14 +144,15 @@ float anglemod (float a) __attribute__((const)); void RotatePointAroundVector (vec3_t dst, const vec3_t axis, const vec3_t point, float degrees); +// NOTE expects plane distance is -p.n #define BOX_ON_PLANE_SIDE(emins, emaxs, p) \ (((p)->type < 3)? \ ( \ - ((p)->dist <= (emins)[(p)->type])? \ + (-(p)->dist <= (emins)[(p)->type])? \ 1 \ : \ ( \ - ((p)->dist >= (emaxs)[(p)->type])? \ + (-(p)->dist >= (emaxs)[(p)->type])? \ 2 \ : \ 3 \ @@ -185,6 +187,7 @@ R_CullBox (const plane_t *frustum, const vec3_t mins, const vec3_t maxs) int i; for (i=0 ; i < 4 ; i++) { + // NOTE frustum distance is -p.n if (BOX_ON_PLANE_SIDE (mins, maxs, &frustum[i]) == 2) { return true; } @@ -205,7 +208,8 @@ R_CullSphere (const plane_t *frustum, const vec3_t origin, const float radius) for (i = 0; i < 4; i++) { - r = DotProduct (origin, frustum[i].normal) - frustum[i].dist; + // NOTE frustum distance is -p.n + r = DotProduct (origin, frustum[i].normal) + frustum[i].dist; if (r <= -radius) return true; } diff --git a/include/QF/model.h b/include/QF/model.h index 47a7a8baa..e8d9df66a 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -34,6 +34,8 @@ #include "QF/modelgen.h" #include "QF/zone.h" +#include "QF/simd/types.h" + extern struct vid_model_funcs_s *mod_funcs; /* @@ -174,18 +176,18 @@ typedef struct msurface_s { } msurface_t; typedef struct mnode_s { -// common with leaf - int contents; // 0, to differentiate from leafs - int visframe; // node needs to be traversed if current - - float minmaxs[6]; // for bounding box culling - -// node specific - plane_t *plane; - struct mnode_s *children[2]; - - unsigned int firstsurface; - unsigned int numsurfaces; + /// Vector representation of the plane. + /// \note the 4th component is the negative of the plane distance. This + /// makes it so a 4d dot product with a point vector (4th component = 1) + /// gives the distance of the point from the plane. + vec4f_t plane; + byte type; + byte signbits; + byte pad[2]; + int32_t children[2]; ///< Negative values = ~(leaf number) + float minmaxs[6]; + uint32_t firstsurface; + uint32_t numsurfaces; } mnode_t; typedef struct mleaf_s { @@ -267,8 +269,8 @@ typedef struct mod_brush_s { byte *lightdata; char *entities; //FIXME should not be here - mnode_t **node_parents; - mnode_t **leaf_parents; + int32_t *node_parents; + int32_t *leaf_parents; int *leaf_flags; // union of surf flags for surfs in leaf unsigned int checksum; @@ -437,7 +439,7 @@ model_t *Mod_ForName (const char *name, qboolean crash); void Mod_TouchModel (const char *name); void Mod_UnloadModel (model_t *model); // brush specific -mleaf_t *Mod_PointInLeaf (const vec3_t p, model_t *model) __attribute__((pure)); +mleaf_t *Mod_PointInLeaf (vec4f_t p, model_t *model) __attribute__((pure)); struct set_s *Mod_LeafPVS (const mleaf_t *leaf, const model_t *model); void Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index 373c81f1a..6aadfab65 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -59,7 +59,7 @@ typedef struct animation_s { typedef struct visibility_s { struct entity_s *entity; // owning entity struct efrag_s *efrag; // linked list of efrags - struct mnode_s *topnode; // bmodels, first world node that + int topnode_id; // bmodels, first world node that // splits bmodel, or NULL if not split // applies to other models, too // found in an active leaf diff --git a/include/r_internal.h b/include/r_internal.h index 95a1c26bc..35b1fda30 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -74,7 +74,8 @@ struct entity_s; struct animation_s; void R_DrawAliasModel (struct entity_s *e); -void R_MarkLeaves (struct mleaf_s *viewleaf); +void R_MarkLeaves (struct mleaf_s *viewleaf, int *node_visframes); +extern int *r_node_visframes; void GL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette); diff --git a/include/r_local.h b/include/r_local.h index 33ef06469..3e158fe9d 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -159,7 +159,7 @@ texture_t *R_TextureAnimation (const struct entity_s *entity, msurface_t *surf) void R_GenSkyTile (void *pdest); void R_SurfPatch (void); -void R_DrawSubmodelPolygons (struct entity_s *ent, model_t *pmodel, int clipflags, struct mnode_s *topnode); +void R_DrawSubmodelPolygons (struct entity_s *ent, model_t *pmodel, int clipflags, struct mleaf_s *topleaf); void R_DrawSolidClippedSubmodelPolygons (struct entity_s *ent, model_t *pmodel, struct mnode_s *topnode); void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); @@ -308,8 +308,8 @@ void R_SetupFrame (void); void R_cshift_f (void); void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1); void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip); -void R_RecursiveMarkLights (mod_brush_t *brush, const vec3_t lightorigin, - struct dlight_s *light, int bit, mnode_t *node); +void R_RecursiveMarkLights (mod_brush_t *brush, vec4f_t lightorigin, + struct dlight_s *light, int bit, int node_id); void R_LoadSkys (const char *); //void Vulkan_R_LoadSkys (const char *, struct vulkan_ctx_s *ctx); diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 0b88504ab..8e3d652e2 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -52,6 +52,7 @@ #include "QF/va.h" #include "QF/plugin/vid_render.h" +#include "QF/simd/vec4f.h" #include "compat.h" #include "mod_internal.h" @@ -60,25 +61,20 @@ VISIBLE int mod_sky_divide; //FIXME visibility? VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible? VISIBLE mleaf_t * -Mod_PointInLeaf (const vec3_t p, model_t *model) +Mod_PointInLeaf (vec4f_t p, model_t *model) { float d; - mnode_t *node; - plane_t *plane; if (!model || !model->brush.nodes) Sys_Error ("Mod_PointInLeaf: bad model"); - node = model->brush.nodes; + int node_id = 0; while (1) { - if (node->contents < 0) - return (mleaf_t *) node; - plane = node->plane; - d = DotProduct (p, plane->normal) - plane->dist; - if (d >= 0) - node = node->children[0]; - else - node = node->children[1]; + if (node_id < 0) + return model->brush.leafs + ~node_id; + mnode_t *node = model->brush.nodes + node_id; + d = dotf (p, node->plane)[0]; + node_id = node->children[d < 0]; } return NULL; // never reached @@ -668,15 +664,16 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) } static void -Mod_SetParent (mod_brush_t *brush, mnode_t *node, mnode_t *parent) +Mod_SetParent (mod_brush_t *brush, int node_id, int parent_id) { - if (node->contents < 0) { - brush->leaf_parents[(mleaf_t *)node - brush->leafs] = parent; + if (node_id < 0) { + brush->leaf_parents[~node_id] = parent_id; return; } - brush->node_parents[node - brush->nodes] = parent; - Mod_SetParent (brush, node->children[0], node); - Mod_SetParent (brush, node->children[1], node); + brush->node_parents[node_id] = parent_id; + mnode_t *node = brush->nodes + node_id; + Mod_SetParent (brush, node->children[0], node_id); + Mod_SetParent (brush, node->children[1], node_id); } static void @@ -720,8 +717,11 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) out->minmaxs[3 + j] = in->maxs[j]; } - p = in->planenum; - out->plane = brush->planes + p; + plane_t *plane = brush->planes + in->planenum; + out->plane = loadvec3f (plane->normal); + out->plane[3] = -plane->dist; + out->type = plane->type; + out->signbits = plane->signbits; out->firstsurface = in->firstface; out->numsurfaces = in->numfaces; @@ -730,28 +730,27 @@ Mod_LoadNodes (model_t *mod, bsp_t *bsp) p = in->children[j]; // this check is for extended bsp 29 files if (p >= 0) { - out->children[j] = brush->nodes + p; + out->children[j] = p; } else { - p = ~p; - if ((unsigned) p < brush->modleafs) { - out->children[j] = (mnode_t *) (brush->leafs + p); + if ((unsigned) ~p < brush->modleafs) { + out->children[j] = p; } else { Sys_Printf ("Mod_LoadNodes: invalid leaf index %i " - "(file has only %i leafs)\n", p, + "(file has only %i leafs)\n", ~p, brush->modleafs); //map it to the solid leaf - out->children[j] = (mnode_t *)(brush->leafs); + out->children[j] = ~0; } } } } - size_t size = (brush->modleafs + brush->numnodes) * sizeof (mnode_t *); + size_t size = (brush->modleafs + brush->numnodes) * sizeof (int32_t); size += brush->modleafs * sizeof (int); brush->node_parents = Hunk_AllocName (0, size, mod->name); brush->leaf_parents = brush->node_parents + brush->numnodes; brush->leaf_flags = (int *) (brush->leaf_parents + brush->modleafs); - Mod_SetParent (brush, brush->nodes, NULL); // sets nodes and leafs + Mod_SetParent (brush, 0, -1); // sets nodes and leafs Mod_SetLeafFlags (brush); } @@ -889,12 +888,12 @@ Mod_LoadClipnodes (model_t *mod, bsp_t *bsp) Replicate the drawing hull structure as a clipping hull */ static void -Mod_MakeHull0 (model_t *mod) +Mod_MakeHull0 (model_t *mod, bsp_t *bsp) { dclipnode_t *out; hull_t *hull; int count, i, j; - mnode_t *in, *child; + mnode_t *in; mod_brush_t *brush = &mod->brush; hull = &brush->hulls[0]; @@ -910,13 +909,14 @@ Mod_MakeHull0 (model_t *mod) hull->planes = brush->planes; for (i = 0; i < count; i++, out++, in++) { - out->planenum = in->plane - brush->planes; + out->planenum = bsp->nodes[i].planenum; for (j = 0; j < 2; j++) { - child = in->children[j]; - if (child->contents < 0) - out->children[j] = child->contents; - else - out->children[j] = child - brush->nodes; + int child_id = in->children[j]; + if (child_id < 0) { + out->children[j] = bsp->leafs[~child_id].contents; + } else { + out->children[j] = child_id; + } } } } @@ -1026,13 +1026,14 @@ do_checksums (const bsp_t *bsp, void *_mod) } static void -recurse_draw_tree (mod_brush_t *brush, mnode_t *node, int depth) +recurse_draw_tree (mod_brush_t *brush, int node_id, int depth) { - if (!node || node->contents < 0) { + if (node_id < 0) { if (depth > brush->depth) brush->depth = depth; return; } + mnode_t *node = &brush->nodes[node_id]; recurse_draw_tree (brush, node->children[0], depth + 1); recurse_draw_tree (brush, node->children[1], depth + 1); } @@ -1041,7 +1042,7 @@ static void Mod_FindDrawDepth (mod_brush_t *brush) { brush->depth = 0; - recurse_draw_tree (brush, brush->nodes, 1); + recurse_draw_tree (brush, 0, 1); } void @@ -1074,9 +1075,9 @@ Mod_LoadBrushModel (model_t *mod, void *buffer) Mod_LoadEntities (mod, bsp); Mod_LoadSubmodels (mod, bsp); - BSP_Free(bsp); + Mod_MakeHull0 (mod, bsp); - Mod_MakeHull0 (mod); + BSP_Free(bsp); Mod_FindDrawDepth (&mod->brush); for (i = 0; i < MAX_MAP_HULLS; i++) diff --git a/libs/scene/light.c b/libs/scene/light.c index a8e82160f..dfbd026c9 100644 --- a/libs/scene/light.c +++ b/libs/scene/light.c @@ -78,7 +78,7 @@ Light_AddLight (lightingdata_t *ldata, const light_t *light, int style) int visleaf = -1; // directional light if (light->position[3]) { // positional light - mleaf_t *leaf = Mod_PointInLeaf (&light->position[0], model); + mleaf_t *leaf = Mod_PointInLeaf (light->position, model); visleaf = leaf - model->brush.leafs - 1; } else if (!DotProduct (light->direction, light->direction)) { // ambient light diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 69344f47c..bf30a92a3 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -57,8 +57,8 @@ static mleaf_t empty_leafs[] = { }, }; -static mnode_t *empty_leaf_parents[] = { - [1] = 0, +static int empty_leaf_parents[] = { + [1] = -1, }; static int empty_leaf_flags[] = { diff --git a/libs/util/mathlib.c b/libs/util/mathlib.c index 3846f9dd7..e5fda93b3 100644 --- a/libs/util/mathlib.c +++ b/libs/util/mathlib.c @@ -486,9 +486,9 @@ BoxOnPlaneSide (const vec3_t emins, const vec3_t emaxs, const plane_t *p) #endif sides = 0; - if (dist1 >= p->dist) + if (dist1 >= -p->dist) sides = 1; - if (dist2 < p->dist) + if (dist2 < -p->dist) sides |= 2; #ifdef PARANOID diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 6d171ac82..e6d0bd14c 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -122,8 +122,8 @@ gl_R_RenderEntities (entqueue_t *queue) qfglEnable (GL_NORMALIZE); } - for (size_t i = 0; i < queue->ent_queues[mod_alias].size; i++) { \ - entity_t *ent = queue->ent_queues[mod_alias].a[i]; \ + for (size_t i = 0; i < queue->ent_queues[mod_alias].size; i++) { + entity_t *ent = queue->ent_queues[mod_alias].a[i]; gl_R_DrawAliasModel (ent); } qfglColor3ubv (color_white); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 026e0eb77..96d011fa8 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -173,7 +173,7 @@ gl_R_NewScene (scene_t *scene) brush->leafs[i].efrags = NULL; // Force a vis update - R_MarkLeaves (0); + R_MarkLeaves (0, 0); R_ClearParticles (); diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 309b95950..39bd40cb0 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -548,16 +548,16 @@ gl_R_DrawBrushModel (entity_t *e) // calculate dynamic lighting for bmodel if it's not an instanced model if (brush->firstmodelsurface != 0 && r_dlight_lightmap) { - vec3_t lightorigin; - for (unsigned k = 0; k < r_maxdlights; k++) { if ((r_dlights[k].die < vr_data.realtime) || (!r_dlights[k].radius)) continue; + vec4f_t lightorigin; VectorSubtract (r_dlights[k].origin, worldMatrix[3], lightorigin); + lightorigin[3] = 1; R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, - brush->nodes + brush->hulls[0].firstclipnode); + brush->hulls[0].firstclipnode); } } @@ -597,12 +597,9 @@ static inline int get_side (mnode_t *node) { // find which side of the node we are on - plane_t *plane = node->plane; vec4f_t org = r_refdef.frame.position; - if (plane->type < 3) - return (org[plane->type] - plane->dist) < 0; - return (DotProduct (org, plane->normal) - plane->dist) < 0; + return dotf (org, node->plane)[0] < 0; } static inline void @@ -630,12 +627,13 @@ visit_node (glbspctx_t *bctx, mnode_t *node, int side) } static inline int -test_node (mnode_t *node) +test_node (glbspctx_t *bctx, int node_id) { - if (node->contents < 0) + if (node_id < 0) return 0; - if (node->visframe != r_visframecount) + if (r_node_visframes[node_id] != r_visframecount) return 0; + mnode_t *node = bctx->brush->nodes + node_id; if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) return 0; return 1; @@ -645,45 +643,55 @@ static void R_VisitWorldNodes (glbspctx_t *bctx) { typedef struct { - mnode_t *node; + int node_id; int side; } rstack_t; mod_brush_t *brush = bctx->brush; rstack_t *node_ptr; rstack_t *node_stack; - mnode_t *node; - mnode_t *front; + int node_id; + int front; int side; - node = brush->nodes; + node_id = 0; // +2 for paranoia node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_ptr = node_stack; while (1) { - while (test_node (node)) { + while (test_node (bctx, node_id)) { + mnode_t *node = bctx->brush->nodes + node_id; side = get_side (node); front = node->children[side]; - if (test_node (front)) { - node_ptr->node = node; + if (test_node (bctx, front)) { + node_ptr->node_id = node_id; node_ptr->side = side; node_ptr++; - node = front; + node_id = front; continue; } - if (front->contents < 0 && front->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) front); + if (front < 0) { + mleaf_t *leaf = bctx->brush->leafs + ~front; + if (leaf->contents != CONTENTS_SOLID) { + visit_leaf (leaf); + } + } visit_node (bctx, node, side); - node = node->children[!side]; + node_id = node->children[side ^ 1]; + } + if (node_id < 0) { + mleaf_t *leaf = bctx->brush->leafs + ~node_id; + if (leaf->contents != CONTENTS_SOLID) { + visit_leaf (leaf); + } } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); if (node_ptr != node_stack) { node_ptr--; - node = node_ptr->node; + node_id = node_ptr->node_id; + mnode_t *node = bctx->brush->nodes + node_id; side = node_ptr->side; visit_node (bctx, node, side); - node = node->children[!side]; + node_id = node->children[side ^ 1]; continue; } break; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 39ae051c7..06d1b87a0 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -694,16 +694,16 @@ R_DrawBrushModel (entity_t *e) // calculate dynamic lighting for bmodel if it's not an instanced model if (brush->firstmodelsurface != 0 && r_dlight_lightmap) { - vec3_t lightorigin; - for (k = 0; k < r_maxdlights; k++) { if ((r_dlights[k].die < vr_data.realtime) || (!r_dlights[k].radius)) continue; + vec4f_t lightorigin; VectorSubtract (r_dlights[k].origin, mat[3], lightorigin); + lightorigin[3] = 1; R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, - brush->nodes + brush->hulls[0].firstclipnode); + brush->hulls[0].firstclipnode); } } @@ -736,12 +736,9 @@ static inline int get_side (mnode_t *node) { // find the node side on which we are - plane_t *plane = node->plane; vec4f_t org = r_refdef.frame.position; - if (plane->type < 3) - return (org[plane->type] - plane->dist) < 0; - return (DotProduct (org, plane->normal) - plane->dist) < 0; + return dotf (org, node->plane)[0] < 0; } static inline void @@ -773,12 +770,13 @@ visit_node (glslbspctx_t *bctx, mnode_t *node, int side) } static inline int -test_node (mnode_t *node) +test_node (glslbspctx_t *bctx, int node_id) { - if (node->contents < 0) + if (node_id < 0) return 0; - if (node->visframe != r_visframecount) + if (r_node_visframes[node_id] != r_visframecount) return 0; + mnode_t *node = bctx->brush->nodes + node_id; if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) return 0; return 1; @@ -788,45 +786,55 @@ static void R_VisitWorldNodes (glslbspctx_t *bctx) { typedef struct { - mnode_t *node; + int node_id; int side; } rstack_t; mod_brush_t *brush = bctx->brush; rstack_t *node_ptr; rstack_t *node_stack; - mnode_t *node; - mnode_t *front; + int node_id; + int front; int side; - node = brush->nodes; + node_id = 0; // +2 for paranoia node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_ptr = node_stack; while (1) { - while (test_node (node)) { + while (test_node (bctx, node_id)) { + mnode_t *node = bctx->brush->nodes + node_id; side = get_side (node); front = node->children[side]; - if (test_node (front)) { - node_ptr->node = node; + if (test_node (bctx, front)) { + node_ptr->node_id = node_id; node_ptr->side = side; node_ptr++; - node = front; + node_id = front; continue; } - if (front->contents < 0 && front->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) front); + if (front < 0) { + mleaf_t *leaf = bctx->brush->leafs + ~front; + if (leaf->contents != CONTENTS_SOLID) { + visit_leaf (leaf); + } + } visit_node (bctx, node, side); - node = node->children[!side]; + node_id = node->children[side ^ 1]; + } + if (node_id < 0) { + mleaf_t *leaf = bctx->brush->leafs + ~node_id; + if (leaf->contents != CONTENTS_SOLID) { + visit_leaf (leaf); + } } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); if (node_ptr != node_stack) { node_ptr--; - node = node_ptr->node; + node_id = node_ptr->node_id; side = node_ptr->side; + mnode_t *node = bctx->brush->nodes + node_id; visit_node (bctx, node, side); - node = node->children[!side]; + node_id = node->children[side ^ 1]; continue; } break; diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 7c8d04502..fb0996427 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -199,7 +199,7 @@ glsl_R_NewScene (scene_t *scene) r_refdef.worldmodel = scene->worldmodel; // Force a vis update - R_MarkLeaves (0); + R_MarkLeaves (0, 0); R_ClearParticles (); glsl_R_RegisterTextures (scene->models, scene->num_models); diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index f534d4b1b..468357857 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -47,12 +47,11 @@ static mleaf_t *r_oldviewleaf; static set_t *solid; void -R_MarkLeaves (mleaf_t *viewleaf) +R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes) { set_t *vis; int c; mleaf_t *leaf; - mnode_t *node; msurface_t **mark; mod_brush_t *brush = &r_refdef.worldmodel->brush; @@ -86,12 +85,12 @@ R_MarkLeaves (mleaf_t *viewleaf) } while (--c); } leaf->visframe = r_visframecount; - node = brush->leaf_parents[leaf - brush->leafs]; - while (node) { - if (node->visframe == r_visframecount) + int node_id = brush->leaf_parents[leaf - brush->leafs]; + while (node_id >= 0) { + if (node_visframes[node_id] == r_visframecount) break; - node->visframe = r_visframecount; - node = brush->node_parents[node - brush->nodes]; + node_visframes[node_id] = r_visframecount; + node_id = brush->node_parents[node_id]; } } } diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index a1d4e6ea3..8e88222f2 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -140,25 +140,25 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, mleaf_t *leaf; int sides; efrag_t **lastlink; - mnode_t **node_stack; - mnode_t **node_ptr; - mnode_t *node = brush->nodes; + int *node_stack; + int *node_ptr; node_stack = alloca ((brush->depth + 2) * sizeof (mnode_t *)); node_ptr = node_stack; lastlink = &ent->visibility.efrag; - *node_ptr++ = 0; + *node_ptr++ = brush->numnodes; - while (node) { + int node_id = 0; + while (node_id != (int) brush->numnodes) { // add an efrag if the node is a leaf - if (__builtin_expect (node->contents < 0, 0)) { - if (!ent->visibility.topnode) { - ent->visibility.topnode = node; + if (__builtin_expect (node_id < 0, 0)) { + if (ent->visibility.topnode_id == -1) { + ent->visibility.topnode_id = node_id; } - leaf = (mleaf_t *) node; + leaf = brush->leafs + ~node_id; ef = new_efrag (); // ensures ef->entnext is 0 @@ -172,29 +172,30 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, ef->leafnext = leaf->efrags; leaf->efrags = ef; - node = *--node_ptr; + node_id = *--node_ptr; } else { + mnode_t *node = brush->nodes + node_id; // NODE_MIXED - splitplane = node->plane; + splitplane = (plane_t *) &node->plane; sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane); if (sides == 3) { // split on this plane // if this is the first splitter of this bmodel, remember it - if (!ent->visibility.topnode) { - ent->visibility.topnode = node; + if (ent->visibility.topnode_id == -1) { + ent->visibility.topnode_id = node_id; } } // recurse down the contacted sides - if (sides & 1 && node->children[0]->contents != CONTENTS_SOLID) { - if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID) + if (sides & 1) { + if (sides & 2) *node_ptr++ = node->children[1]; - node = node->children[0]; + node_id = node->children[0]; } else { - if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID) - node = node->children[1]; + if (sides & 2) + node_id = node->children[1]; else - node = *--node_ptr; + node_id = *--node_ptr; } } } @@ -216,7 +217,7 @@ R_AddEfrags (mod_brush_t *brush, entity_t *ent) VectorAdd (org, entmodel->mins, emins); VectorAdd (org, entmodel->maxs, emaxs); - ent->visibility.topnode = 0; + ent->visibility.topnode_id = -1; // leaf 0 (solid space) R_SplitEntityOnNode (brush, ent, emins, emaxs); } diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 5c805fb54..614227a92 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -152,7 +152,7 @@ R_AnimateLight (void) } static inline void -real_mark_surfaces (float dist, msurface_t *surf, const vec3_t lightorigin, +real_mark_surfaces (float dist, msurface_t *surf, vec4f_t lightorigin, dlight_t *light, unsigned lightnum) { float dist2, is, it; @@ -190,7 +190,7 @@ real_mark_surfaces (float dist, msurface_t *surf, const vec3_t lightorigin, } static inline void -mark_surfaces (msurface_t *surf, const vec3_t lightorigin, dlight_t *light, +mark_surfaces (msurface_t *surf, vec4f_t lightorigin, dlight_t *light, int lightnum) { float dist; @@ -208,35 +208,33 @@ mark_surfaces (msurface_t *surf, const vec3_t lightorigin, dlight_t *light, // LordHavoc: heavily modified, to eliminate unnecessary texture uploads, // and support bmodel lighting better void -R_RecursiveMarkLights (mod_brush_t *brush, const vec3_t lightorigin, - dlight_t *light, int lightnum, mnode_t *node) +R_RecursiveMarkLights (mod_brush_t *brush, vec4f_t lightorigin, + dlight_t *light, int lightnum, int node_id) { unsigned i; float ndist, maxdist; - plane_t *splitplane; msurface_t *surf; maxdist = light->radius; loc0: - if (node->contents < 0) + if (node_id < 0) return; - splitplane = node->plane; - ndist = DotProduct (lightorigin, splitplane->normal) - splitplane->dist; + mnode_t *node = brush->nodes + node_id; + ndist = dotf (lightorigin, node->plane)[0]; if (ndist > maxdist * maxdist) { // Save time by not pushing another stack frame. - if (node->children[0]->contents >= 0) { - node = node->children[0]; + if (node->children[0] >= 0) { + node_id = node->children[0]; goto loc0; } return; } if (ndist < -maxdist * maxdist) { - // Save time by not pushing another stack frame. - if (node->children[1]->contents >= 0) { - node = node->children[1]; + if (node->children[1] >= 0) { + node_id = node->children[1]; goto loc0; } return; @@ -248,29 +246,29 @@ loc0: mark_surfaces (surf, lightorigin, light, lightnum); } - if (node->children[0]->contents >= 0) { - if (node->children[1]->contents >= 0) + if (node->children[0] >= 0) { + if (node->children[1] >= 0) R_RecursiveMarkLights (brush, lightorigin, light, lightnum, node->children[1]); - node = node->children[0]; + node_id = node->children[0]; goto loc0; - } else if (node->children[1]->contents >= 0) { - node = node->children[1]; + } else if (node->children[1] >= 0) { + node_id = node->children[1]; goto loc0; } } static void -R_MarkLights (const vec3_t lightorigin, dlight_t *light, int lightnum, +R_MarkLights (vec4f_t lightorigin, dlight_t *light, int lightnum, model_t *model) { mod_brush_t *brush = &model->brush; mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model); if (!pvsleaf->compressed_vis) { - mnode_t *node = brush->nodes + brush->hulls[0].firstclipnode; - R_RecursiveMarkLights (brush, lightorigin, light, lightnum, node); + int node_id = brush->hulls[0].firstclipnode; + R_RecursiveMarkLights (brush, lightorigin, light, lightnum, node_id); } else { float radius = light->radius; vec3_t mins, maxs; @@ -321,7 +319,6 @@ R_PushDlights (const vec3_t entorigin) { unsigned int i; dlight_t *l; - vec3_t lightorigin; // because the count hasn't advanced yet for this frame r_dlightframecount = r_framecount + 1; @@ -334,14 +331,15 @@ R_PushDlights (const vec3_t entorigin) for (i = 0; i < r_maxdlights; i++, l++) { if (l->die < r_data->realtime || !l->radius) continue; + vec4f_t lightorigin; VectorSubtract (l->origin, entorigin, lightorigin); + lightorigin[3] = 1; R_MarkLights (lightorigin, l, i, r_refdef.worldmodel); } } /* LIGHT SAMPLING */ -plane_t *lightplane; vec3_t lightspot; static int @@ -408,27 +406,26 @@ calc_lighting_3 (msurface_t *surf, int ds, int dt) } static int -RecursiveLightPoint (mod_brush_t *brush, mnode_t *node, vec4f_t start, +RecursiveLightPoint (mod_brush_t *brush, int node_id, vec4f_t start, vec4f_t end) { unsigned i; int r, s, t, ds, dt, side; float front, back, frac; - plane_t *plane; msurface_t *surf; mtexinfo_t *tex; loop: - if (node->contents < 0) + if (node_id < 0) return -1; // didn't hit anything // calculate mid point - plane = node->plane; - front = DotProduct (start, plane->normal) - plane->dist; - back = DotProduct (end, plane->normal) - plane->dist; + mnode_t *node = brush->nodes + node_id; + front = dotf (start, node->plane)[0]; + back = dotf (end, node->plane)[0]; side = front < 0; if ((back < 0) == side) { - node = node->children[side]; + node_id = node->children[side]; goto loop; } @@ -445,7 +442,6 @@ loop: // check for impact on this node VectorCopy (mid, lightspot); - lightplane = plane; surf = brush->surfaces + node->firstsurface; for (i = 0; i < node->numsurfaces; i++, surf++) { @@ -478,7 +474,7 @@ loop: } // go down back side - return RecursiveLightPoint (brush, node->children[!side], mid, end); + return RecursiveLightPoint (brush, node->children[side ^ 1], mid, end); } int @@ -491,7 +487,7 @@ R_LightPoint (mod_brush_t *brush, vec4f_t p) } vec4f_t end = p - (vec4f_t) { 0, 0, 2048, 0 }; - int r = RecursiveLightPoint (brush, brush->nodes, p, end); + int r = RecursiveLightPoint (brush, 0, p, end); if (r == -1) r = 0; diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index d29bcd1a4..06845c912 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -111,7 +111,7 @@ R_SetFrustum (plane_t *frustum, const refframe_t *frame, vec4f_t origin = frame->position; for (i = 0; i < 4; i++) { frustum[i].type = PLANE_ANYZ; - frustum[i].dist = DotProduct (origin, frustum[i].normal); + frustum[i].dist = -DotProduct (origin, frustum[i].normal); frustum[i].signbits = SignbitsForPlane (&frustum[i]); } } diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 365bb9dde..3255d88ef 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -61,6 +61,7 @@ int scr_copytop; byte *draw_chars; // 8*8 graphic characters FIXME location qboolean r_cache_thrash; // set if surface cache is thrashing +int *r_node_visframes; //FIXME per renderer qboolean scr_skipupdate; static qboolean scr_initialized;// ready to draw @@ -273,8 +274,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) if (scr_scene && scr_scene->worldmodel) { scr_scene->viewleaf = 0; vec4f_t position = refdef->frame.position; - scr_scene->viewleaf = Mod_PointInLeaf ((vec_t*)&position, - scr_scene->worldmodel);//FIXME + scr_scene->viewleaf = Mod_PointInLeaf (position, scr_scene->worldmodel); r_dowarpold = r_dowarp; if (r_waterwarp) { r_dowarp = scr_scene->viewleaf->contents <= CONTENTS_WATER; @@ -283,7 +283,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, r_data->vid->height); } - R_MarkLeaves (scr_scene->viewleaf); + R_MarkLeaves (scr_scene->viewleaf, r_node_visframes); } R_PushDlights (vec3_origin); @@ -514,6 +514,9 @@ SCR_NewScene (scene_t *scene) { scr_scene = scene; if (scene) { + mod_brush_t *brush = &scr_scene->worldmodel->brush; + int size = brush->numnodes * sizeof (int); + r_node_visframes = Hunk_AllocName (0, size, "visframes"); r_funcs->set_fov (tan_fov_x, tan_fov_y); r_funcs->R_NewScene (scene); } else { diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 1362f9436..4947dc24b 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -118,8 +118,8 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode, // transform the BSP plane into model space // FIXME: cache these? - splitplane = pnode->plane; - tplane.dist = splitplane->dist - + splitplane = (plane_t *) &pnode->plane; + tplane.dist = splitplane->dist + DotProduct (r_entorigin, splitplane->normal); tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal); tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal); @@ -132,7 +132,7 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode, // set the status for the last point as the previous point // FIXME: cache this stuff somehow? plastvert = pedges->v[0]; - lastdist = DotProduct (plastvert->position, tplane.normal) - + lastdist = DotProduct (plastvert->position, tplane.normal) + tplane.dist; if (lastdist > 0) @@ -142,7 +142,7 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode, pvert = pedges->v[1]; - dist = DotProduct (pvert->position, tplane.normal) - tplane.dist; + dist = DotProduct (pvert->position, tplane.normal) + tplane.dist; if (dist > 0) side = 0; @@ -228,18 +228,20 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode, if (psideedges[i]) { // draw if we've reached a non-solid leaf, done if all that's left // is a solid leaf, and continue down the tree if it's not a leaf - pn = pnode->children[i]; + int child_id = pnode->children[i]; + pn = r_refdef.worldmodel->brush.nodes + child_id; // we're done with this branch if the node or leaf isn't in the PVS - if (pn->visframe == r_visframecount) { - if (pn->contents < 0) { - if (pn->contents != CONTENTS_SOLID) { - r_currentbkey = ((mleaf_t *) pn)->key; - R_RenderBmodelFace (ent, psideedges[i], psurf); - } - } else { - R_RecursiveClipBPoly (ent, psideedges[i], - pnode->children[i], psurf); + if (child_id < 0) { + mleaf_t *leaf = r_refdef.worldmodel->brush.leafs + ~child_id; + if (leaf->visframe == r_visframecount + && leaf->contents != CONTENTS_SOLID) { + r_currentbkey = leaf->key; + R_RenderBmodelFace (ent, psideedges[i], psurf); + } + } else { + if (r_node_visframes[child_id] == r_visframecount) { + R_RecursiveClipBPoly (ent, psideedges[i], pn, psurf); } } } @@ -320,7 +322,7 @@ R_DrawSolidClippedSubmodelPolygons (entity_t *ent, model_t *model, void R_DrawSubmodelPolygons (entity_t *ent, model_t *model, int clipflags, - mnode_t *topnode) + mleaf_t *topleaf) { int i; vec_t dot; @@ -343,7 +345,7 @@ R_DrawSubmodelPolygons (entity_t *ent, model_t *model, int clipflags, // draw the polygon if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - r_currentkey = ((mleaf_t *) topnode)->key; + r_currentkey = topleaf->key; // FIXME: use bounding-box-based frustum clipping info? R_RenderFace (ent, psurf, clipflags); @@ -365,12 +367,9 @@ static inline int get_side (mnode_t *node) { // find which side of the node we are on - plane_t *plane = node->plane; vec4f_t org = r_refdef.frame.position; - if (plane->type < 3) - return (org[plane->type] - plane->dist) < 0; - return (DotProduct (org, plane->normal) - plane->dist) < 0; + return dotf (org, node->plane)[0] < 0; } static void @@ -414,20 +413,21 @@ visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags) } static inline int -test_node (mnode_t *node, int *clipflags) +test_node (swbspctx_t *bctx, int node_id, int *clipflags) { int i, *pindex; vec3_t acceptpt, rejectpt; double d; - if (node->contents < 0) + if (node_id < 0) return 0; - if (node->visframe != r_visframecount) + if (r_node_visframes[node_id] != r_visframecount) return 0; // cull the clipping planes if not trivial accept // FIXME: the compiler is doing a lousy job of optimizing here; it could be // twice as fast in ASM if (*clipflags) { + mnode_t *node = bctx->brush->nodes + node_id; for (i = 0; i < 4; i++) { if (!(*clipflags & (1 << i))) continue; // don't need to clip against it @@ -465,50 +465,60 @@ static void R_VisitWorldNodes (swbspctx_t *bctx, int clipflags) { typedef struct { - mnode_t *node; + int node_id; int side, clipflags; } rstack_t; rstack_t *node_ptr; rstack_t *node_stack; - mnode_t *node; - mnode_t *front; + int front; int side, cf; + int node_id; mod_brush_t *brush = &bctx->entity->renderer.model->brush; - node = brush->nodes; // +2 for paranoia node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_ptr = node_stack; + node_id = 0; cf = clipflags; while (1) { - while (test_node (node, &cf)) { + while (test_node (bctx, node_id, &cf)) { + mnode_t *node = bctx->brush->nodes + node_id; cf = clipflags; side = get_side (node); front = node->children[side]; - if (test_node (front, &cf)) { - node_ptr->node = node; + if (test_node (bctx, front, &cf)) { + node_ptr->node_id = node_id; node_ptr->side = side; node_ptr->clipflags = clipflags; node_ptr++; clipflags = cf; - node = front; + node_id = front; continue; } - if (front->contents < 0 && front->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) front); + if (front < 0) { + mleaf_t *leaf = bctx->brush->leafs + ~front; + if (leaf->contents != CONTENTS_SOLID) { + visit_leaf (leaf); + } + } visit_node (bctx, node, side, clipflags); - node = node->children[!side]; + node_id = node->children[side ^ 1]; + } + if (node_id < 0) { + mleaf_t *leaf = bctx->brush->leafs + ~node_id; + if (leaf->contents != CONTENTS_SOLID) { + visit_leaf (leaf); + } } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); if (node_ptr != node_stack) { node_ptr--; - node = node_ptr->node; + node_id = node_ptr->node_id; + mnode_t *node = bctx->brush->nodes + node_id; side = node_ptr->side; clipflags = node_ptr->clipflags; visit_node (bctx, node, side, clipflags); - node = node->children[!side]; + node_id = node->children[side ^ 1]; continue; } break; diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 03d988965..f129b2254 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -167,7 +167,7 @@ R_NewScene (scene_t *scene) R_InitSky (brush->skytexture); // Force a vis update - R_MarkLeaves (0); + R_MarkLeaves (0, 0); R_ClearParticles (); @@ -303,8 +303,7 @@ R_DrawEntitiesOnList (entqueue_t *queue) for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ i++) { \ entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \ - VectorCopy (Transform_GetWorldPosition (ent->transform), \ - r_entorigin); \ + r_entorigin = Transform_GetWorldPosition (ent->transform); \ draw_##type_name##_entity (ent); \ } \ } while (0) @@ -473,19 +472,18 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) // calculate dynamic lighting for bmodel if it's not an // instanced model if (brush->firstmodelsurface != 0) { - vec3_t lightorigin; - for (k = 0; k < r_maxdlights; k++) { if ((r_dlights[k].die < vr_data.realtime) || (!r_dlights[k].radius)) { continue; } + vec4f_t lightorigin; VectorSubtract (r_dlights[k].origin, origin, lightorigin); + lightorigin[3] = 1; R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k, - brush->nodes - + brush->hulls[0].firstclipnode); + brush->hulls[0].firstclipnode); } } // if the driver wants polygons, deliver those. @@ -494,20 +492,21 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) if (r_drawpolys | r_drawculledpolys) { R_ZDrawSubmodelPolys (ent, clmodel); } else { - if (ent->visibility.topnode) { - mnode_t *topnode = ent->visibility.topnode; + int topnode_id = ent->visibility.topnode_id; + mod_brush_t *brush = &r_refdef.worldmodel->brush; - if (topnode->contents >= 0) { - // not a leaf; has to be clipped to the world - // BSP - r_clipflags = clipflags; - R_DrawSolidClippedSubmodelPolygons (ent, clmodel, topnode); - } else { - // falls entirely in one leaf, so we just put - // all the edges in the edge list and let 1/z - // sorting handle drawing order - R_DrawSubmodelPolygons (ent, clmodel, clipflags, topnode); - } + if (topnode_id >= 0) { + // not a leaf; has to be clipped to the world + // BSP + mnode_t *node = brush->nodes + topnode_id; + r_clipflags = clipflags; + R_DrawSolidClippedSubmodelPolygons (ent, clmodel, node); + } else { + // falls entirely in one leaf, so we just put + // all the edges in the edge list and let 1/z + // sorting handle drawing order + mleaf_t *leaf = brush->leafs + ~topnode_id; + R_DrawSubmodelPolygons (ent, clmodel, clipflags, leaf); } } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index f5d0d49b6..e92f0d20e 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -648,12 +648,9 @@ static inline int get_side (mnode_t *node) { // find the node side on which we are - plane_t *plane = node->plane; vec4f_t org = r_refdef.frame.position; - if (plane->type < 3) - return (org[plane->type] - plane->dist) < 0; - return (DotProduct (org, plane->normal) - plane->dist) < 0; + return dotf (org, node->plane)[0] < 0; } static inline void @@ -685,12 +682,13 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) } static inline int -test_node (mnode_t *node) +test_node (mod_brush_t *brush, int node_id) { - if (node->contents < 0) + if (node_id < 0) return 0; - if (node->visframe != r_visframecount) + if (r_node_visframes[node_id] != r_visframecount) return 0; + mnode_t *node = brush->nodes + node_id; if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) return 0; return 1; @@ -700,48 +698,58 @@ static void R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) { typedef struct { - mnode_t *node; + int node_id; int side; } rstack_t; rstack_t *node_ptr; rstack_t *node_stack; - mnode_t *node; - mnode_t *front; + int node_id; + int front; int side; - node = brush->nodes; + node_id = 0; // +2 for paranoia node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); node_ptr = node_stack; while (1) { - while (test_node (node)) { + while (test_node (brush, node_id)) { + mnode_t *node = brush->nodes + node_id; side = get_side (node); front = node->children[side]; - if (test_node (front)) { - node_ptr->node = node; + if (test_node (brush, front)) { + node_ptr->node_id = node_id; node_ptr->side = side; node_ptr++; - node = front; + node_id = front; continue; } // front is either not a node (ie, is a leaf) or is not visible // if node is visible, then at least one of its child nodes // must also be visible, and a leaf child in front of the node // will be visible, so no need for vis checks on a leaf - if (front->contents < 0 && front->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) front); + if (front < 0) { + mleaf_t *leaf = brush->leafs + ~front; + if (leaf->contents != CONTENTS_SOLID) { + visit_leaf (leaf); + } + } visit_node (brush, node, side, ctx); - node = node->children[!side]; + node_id = node->children[side ^ 1]; + } + if (node_id < 0) { + mleaf_t *leaf = brush->leafs + ~node_id; + if (leaf->contents != CONTENTS_SOLID) { + visit_leaf (leaf); + } } - if (node->contents < 0 && node->contents != CONTENTS_SOLID) - visit_leaf ((mleaf_t *) node); if (node_ptr != node_stack) { node_ptr--; - node = node_ptr->node; + node_id = node_ptr->node_id; side = node_ptr->side; + mnode_t *node = brush->nodes + node_id; visit_node (brush, node, side, ctx); - node = node->children[!side]; + node_id = node->children[side ^ 1]; continue; } break; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 9af4c5b73..59e327df7 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -142,7 +142,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) r_refdef.worldmodel = scene->worldmodel; // Force a vis update - R_MarkLeaves (0); + R_MarkLeaves (0, 0); R_ClearParticles (); Vulkan_RegisterTextures (scene->models, scene->num_models, ctx); diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index bd2effd81..ea3a3ab50 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -83,7 +83,7 @@ SCR_CShift (void) if (cls.state == ca_active && cl_world.scene->worldmodel) { vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME + leaf = Mod_PointInLeaf (origin, cl_world.scene->worldmodel); contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); diff --git a/nq/source/host.c b/nq/source/host.c index da90dc94a..da393a677 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -757,7 +757,7 @@ Host_ClientFrame (void) vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME + l = Mod_PointInLeaf (origin, cl_world.scene->worldmodel); if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index e89c8c82b..f3ebcb654 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -372,30 +372,29 @@ SV_ClearDatagram (void) static set_t *fatpvs; static void -SV_AddToFatPVS (vec3_t org, mnode_t *node) +SV_AddToFatPVS (vec4f_t org, int node_id) { float d; - plane_t *plane; while (1) { // if this is a leaf, accumulate the pvs bits - if (node->contents < 0) { - if (node->contents != CONTENTS_SOLID) { - set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node, - sv.worldmodel)); + if (node_id < 0) { + mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id; + if (leaf->contents != CONTENTS_SOLID) { + set_union (fatpvs, Mod_LeafPVS (leaf, sv.worldmodel)); } return; } + mnode_t *node = sv.worldmodel->brush.nodes + node_id; - plane = node->plane; - d = DotProduct (org, plane->normal) - plane->dist; + d = dotf (node->plane, org)[0]; if (d > 8) - node = node->children[0]; + node_id = node->children[0]; else if (d < -8) - node = node->children[1]; + node_id = node->children[1]; else { // go down both SV_AddToFatPVS (org, node->children[0]); - node = node->children[1]; + node_id = node->children[1]; } } } @@ -407,14 +406,14 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node) given point. */ static set_t * -SV_FatPVS (vec3_t org) +SV_FatPVS (vec4f_t org) { if (!fatpvs) { fatpvs = set_new_size (sv.worldmodel->brush.visleafs); } set_expand (fatpvs, sv.worldmodel->brush.visleafs); set_empty (fatpvs); - SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); + SV_AddToFatPVS (org, 0); return fatpvs; } @@ -426,13 +425,14 @@ SV_WriteEntitiesToClient (edict_t *clent, sizebuf_t *msg) pr_uint_t bits, e; set_t *pvs; float miss; - vec3_t org; + vec4f_t org; edict_t *ent; entity_state_t *baseline; edict_leaf_t *el; // find the client's PVS VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org); + org[3] = 1; pvs = SV_FatPVS (org); // send over all entities (excpet the client) that touch the pvs diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index b555708ff..dfc0552fd 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -548,7 +548,6 @@ PF_newcheckclient (progs_t *pr, unsigned check) edict_t *ent; unsigned i; mleaf_t *leaf; - vec3_t org; // cycle to the next one if (check < 1) @@ -582,7 +581,9 @@ PF_newcheckclient (progs_t *pr, unsigned check) } // get the PVS for the entity + vec4f_t org; VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); + org[3] = 1; leaf = Mod_PointInLeaf (org, sv.worldmodel); if (!checkpvs) { checkpvs = set_new_size (sv.worldmodel->brush.visleafs); @@ -615,7 +616,6 @@ PF_checkclient (progs_t *pr, void *data) edict_t *ent, *self; int l; mleaf_t *leaf; - vec3_t view; // find a new check if on a new frame if (sv.time - sv.lastchecktime >= 0.1) { @@ -630,7 +630,9 @@ PF_checkclient (progs_t *pr, void *data) } // if current entity can't possibly see the check entity, return 0 self = PROG_TO_EDICT (pr, *sv_globals.self); + vec4f_t view; VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view); + view[3] = 1; leaf = Mod_PointInLeaf (view, sv.worldmodel); l = (leaf - sv.worldmodel->brush.leafs) - 1; if (!set_is_member (checkpvs, l)) { diff --git a/nq/source/world.c b/nq/source/world.c index 9926abd26..13e6df8d0 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -410,19 +410,17 @@ SV_TouchLinks (edict_t *ent, areanode_t *node) } static void -SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) +SV_FindTouchedLeafs (edict_t *ent, int node_id) { int sides; - mleaf_t *leaf; plane_t *splitplane; edict_leaf_t *edict_leaf; - if (node->contents == CONTENTS_SOLID) - return; - - // add an efrag if the node is a leaf - if (node->contents < 0) { - leaf = (mleaf_t *) node; + // add an efrag if the node is a non-solid leaf + if (node_id < 0) { + mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id; + if (leaf->contents == CONTENTS_SOLID) + return; edict_leaf = alloc_edict_leaf (); edict_leaf->leafnum = leaf - sv.worldmodel->brush.leafs - 1; @@ -431,8 +429,9 @@ SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) return; } + mnode_t *node = sv.worldmodel->brush.nodes + node_id; // NODE_MIXED - splitplane = node->plane; + splitplane = (plane_t *) &node->plane; sides = BOX_ON_PLANE_SIDE (SVvector (ent, absmin), SVvector (ent, absmax), splitplane); @@ -497,7 +496,7 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers) // link to PVS leafs free_edict_leafs (&SVdata (ent)->leafs); if (SVfloat (ent, modelindex)) - SV_FindTouchedLeafs (ent, sv.worldmodel->brush.nodes); + SV_FindTouchedLeafs (ent, 0); if (SVfloat (ent, solid) == SOLID_NOT) return; diff --git a/qtv/source/client.c b/qtv/source/client.c index 9113d2b7d..26eda3b92 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -52,6 +52,8 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/simd/vec4f.h" + #include "qw/bothdefs.h" #include "qw/msg_ucmd.h" #include "qw/protocol.h" @@ -978,30 +980,27 @@ emit_entities (client_t *client, packet_entities_t *to, sizebuf_t *msg) } static void -add_to_fat_pvs (vec4f_t org, mnode_t *node, server_t *sv) +add_to_fat_pvs (vec4f_t org, int node_id, server_t *sv) { - float d; - plane_t *plane; - while (1) { // if this is a leaf, accumulate the pvs bits - if (node->contents < 0) { - if (node->contents != CONTENTS_SOLID) { - set_union (sv->fatpvs, Mod_LeafPVS ((mleaf_t *) node, - sv->worldmodel)); + if (node_id < 0) { + mleaf_t *leaf = sv->worldmodel->brush.leafs + ~node_id; + if (leaf->contents != CONTENTS_SOLID) { + set_union (sv->fatpvs, Mod_LeafPVS (leaf, sv->worldmodel)); } return; } - plane = node->plane; - d = DotProduct (org, plane->normal) - plane->dist; + mnode_t *node = sv->worldmodel->brush.nodes + node_id; + float d = dotf (node->plane, org)[0]; if (d > 8) - node = node->children[0]; + node_id = node->children[0]; else if (d < -8) - node = node->children[1]; + node_id = node->children[1]; else { // go down both add_to_fat_pvs (org, node->children[0], sv); - node = node->children[1]; + node_id = node->children[1]; } } } @@ -1015,7 +1014,7 @@ fat_pvs (vec4f_t org, server_t *sv) set_expand (sv->fatpvs, sv->worldmodel->brush.visleafs); set_empty (sv->fatpvs); - add_to_fat_pvs (org, sv->worldmodel->brush.nodes, sv); + add_to_fat_pvs (org, 0, sv); return sv->fatpvs; } diff --git a/qtv/source/sv_parse.c b/qtv/source/sv_parse.c index db4a8c3e7..b0a080a5a 100644 --- a/qtv/source/sv_parse.c +++ b/qtv/source/sv_parse.c @@ -116,15 +116,16 @@ sv_unlink_entity (server_t *sv, qtv_entity_t *ent) } static void -sv_find_touched_leafs (server_t *sv, qtv_entity_t *ent, mnode_t *node) +sv_find_touched_leafs (server_t *sv, qtv_entity_t *ent, int node_id) { - if (node->contents == CONTENTS_SOLID) { - return; - } // add an efrag if the node is a leaf - if (node->contents < 0) { + if (node_id < 0) { + mleaf_t *leaf = sv->worldmodel->brush.leafs + ~node_id; + if (leaf->contents == CONTENTS_SOLID) { + return; + } qtv_leaf_t *ent_leaf = alloc_qtv_leaf (); - ent_leaf->num = (mleaf_t *) node - sv->worldmodel->brush.leafs - 1; + ent_leaf->num = ~node_id - 1; ent_leaf->next = ent->leafs; ent->leafs = ent_leaf; return; @@ -134,7 +135,8 @@ sv_find_touched_leafs (server_t *sv, qtv_entity_t *ent, mnode_t *node) VectorAdd (ent->e.origin, ent->model->mins, emins); VectorAdd (ent->e.origin, ent->model->maxs, emaxs); - plane_t *splitplane = node->plane; + mnode_t *node = sv->worldmodel->brush.nodes + node_id; + plane_t *splitplane = (plane_t *) &node->plane; int sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane); if (sides & 1) { sv_find_touched_leafs (sv, ent, node->children[0]); @@ -153,7 +155,7 @@ sv_link_entity (server_t *sv, qtv_entity_t *ent) ent->model = Mod_ForName (sv->modellist[ent->model_index - 1], false); } if (ent->model) { - sv_find_touched_leafs (sv, ent, sv->worldmodel->brush.nodes); + sv_find_touched_leafs (sv, ent, 0); } } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index a78a46e46..3162b9b74 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1995,7 +1995,7 @@ Host_Frame (float time) vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - l = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME + l = Mod_PointInLeaf (origin, cl_world.scene->worldmodel); if (l) asl = l->ambient_sound_level; S_Update (cl.viewstate.camera_transform, asl); diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 54871dac5..bbab72313 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -82,7 +82,7 @@ SCR_CShift (void) if (cls.state == ca_active && cl_world.scene->worldmodel) { vec4f_t origin; origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - leaf = Mod_PointInLeaf ((vec_t*)&origin, cl_world.scene->worldmodel);//FIXME + leaf = Mod_PointInLeaf (origin, cl_world.scene->worldmodel); contents = leaf->contents; } V_SetContentsColor (&cl.viewstate, contents); diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index b5c7df94c..83768fe84 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -40,6 +40,8 @@ #include "QF/set.h" #include "QF/sys.h" +#include "QF/simd/vec4f.h" + #include "compat.h" #include "qw/msg_ucmd.h" @@ -59,30 +61,29 @@ static set_t *fatpvs; static void -SV_AddToFatPVS (vec3_t org, mnode_t *node) +SV_AddToFatPVS (vec4f_t org, int node_id) { float d; - plane_t *plane; while (1) { // if this is a leaf, accumulate the pvs bits - if (node->contents < 0) { - if (node->contents != CONTENTS_SOLID) { - set_union (fatpvs, Mod_LeafPVS ((mleaf_t *) node, - sv.worldmodel)); + if (node_id < 0) { + mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id; + if (leaf->contents != CONTENTS_SOLID) { + set_union (fatpvs, Mod_LeafPVS (leaf, sv.worldmodel)); } return; } - plane = node->plane; - d = DotProduct (org, plane->normal) - plane->dist; + mnode_t *node = sv.worldmodel->brush.nodes + node_id; + d = dotf (org, node->plane)[0]; if (d > 8) - node = node->children[0]; + node_id = node->children[0]; else if (d < -8) - node = node->children[1]; + node_id = node->children[1]; else { // go down both SV_AddToFatPVS (org, node->children[0]); - node = node->children[1]; + node_id = node->children[1]; } } } @@ -94,14 +95,14 @@ SV_AddToFatPVS (vec3_t org, mnode_t *node) of the given point. */ static set_t * -SV_FatPVS (vec3_t org) +SV_FatPVS (vec4f_t org) { if (!fatpvs) { fatpvs = set_new_size (sv.worldmodel->brush.visleafs); } set_expand (fatpvs, sv.worldmodel->brush.visleafs); set_empty (fatpvs); - SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); + SV_AddToFatPVS (org, 0); return fatpvs; } @@ -710,12 +711,13 @@ static inline set_t * calc_pvs (delta_t *delta) { set_t *pvs = 0; - vec3_t org; + vec4f_t org = {}; // find the client's PVS if (delta->pvs == dt_pvs_normal) { edict_t *clent = delta->client->edict; VectorAdd (SVvector (clent, origin), SVvector (clent, view_ofs), org); + org[3] = 1; pvs = SV_FatPVS (org); } else if (delta->pvs == dt_pvs_fat) { // when recording a demo, send only entities that can be seen. Can help @@ -735,10 +737,11 @@ calc_pvs (delta_t *delta) VectorAdd (SVvector (cl->edict, origin), SVvector (cl->edict, view_ofs), org); + org[3] = 1; if (pvs == NULL) { pvs = SV_FatPVS (org); } else { - SV_AddToFatPVS (org, sv.worldmodel->brush.nodes); + SV_AddToFatPVS (org, 0); } } } diff --git a/qw/source/sv_pr_cmds.c b/qw/source/sv_pr_cmds.c index fe892ea7c..7075bc6cf 100644 --- a/qw/source/sv_pr_cmds.c +++ b/qw/source/sv_pr_cmds.c @@ -469,7 +469,6 @@ PF_newcheckclient (progs_t *pr, int check) edict_t *ent; int i; mleaf_t *leaf; - vec3_t org; // cycle to the next one if (check < 1) @@ -503,7 +502,9 @@ PF_newcheckclient (progs_t *pr, int check) } // get the PVS for the entity + vec4f_t org; VectorAdd (SVvector (ent, origin), SVvector (ent, view_ofs), org); + org[3] = 1; leaf = Mod_PointInLeaf (org, sv.worldmodel); if (!checkpvs) { checkpvs = set_new_size (sv.worldmodel->brush.visleafs); @@ -536,7 +537,6 @@ PF_checkclient (progs_t *pr, void *data) edict_t *ent, *self; int l; mleaf_t *leaf; - vec3_t view; // find a new check if on a new frame if (sv.time - sv.lastchecktime >= 0.1) { @@ -551,7 +551,9 @@ PF_checkclient (progs_t *pr, void *data) } // if current entity can't possibly see the check entity, return 0 self = PROG_TO_EDICT (pr, *sv_globals.self); + vec4f_t view; VectorAdd (SVvector (self, origin), SVvector (self, view_ofs), view); + view[3] = 1; leaf = Mod_PointInLeaf (view, sv.worldmodel); l = (leaf - sv.worldmodel->brush.leafs) - 1; if (!set_is_member (checkpvs, l)) { diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index 42f53169e..112e9b7e8 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -302,7 +302,8 @@ SV_Multicast (const vec3_t origin, int to) qboolean reliable; mod_brush_t *brush = &sv.worldmodel->brush; - leaf = Mod_PointInLeaf (origin, sv.worldmodel); + vec4f_t org = { VectorExpand (origin), 1 }; + leaf = Mod_PointInLeaf (org, sv.worldmodel); if (!leaf) leafnum = 0; else @@ -346,8 +347,8 @@ SV_Multicast (const vec3_t origin, int to) goto inrange; } - leaf = Mod_PointInLeaf (SVvector (client->edict, origin), - sv.worldmodel); + org = (vec4f_t) {VectorExpand (SVvector (client->edict, origin)), 1}; + leaf = Mod_PointInLeaf (org, sv.worldmodel); if (leaf) { // -1 is because pvs rows are 1 based, not 0 based like leafs leafnum = leaf - brush->leafs - 1; diff --git a/qw/source/world.c b/qw/source/world.c index 1c0de0270..f6e0fbd8b 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -410,29 +410,28 @@ SV_TouchLinks (edict_t *ent, areanode_t *node) } static void -SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) +SV_FindTouchedLeafs (edict_t *ent, int node_id) { int sides; - mleaf_t *leaf; plane_t *splitplane; edict_leaf_t *edict_leaf; - if (node->contents == CONTENTS_SOLID) - return; - // add an efrag if the node is a leaf - if (node->contents < 0) { - leaf = (mleaf_t *) node; + if (node_id < 0) { + mleaf_t *leaf = sv.worldmodel->brush.leafs + ~node_id; + if (leaf->contents == CONTENTS_SOLID) + return; edict_leaf = alloc_edict_leaf (); - edict_leaf->leafnum = leaf - sv.worldmodel->brush.leafs - 1; + edict_leaf->leafnum = ~node_id - 1; edict_leaf->next = SVdata (ent)->leafs; SVdata (ent)->leafs = edict_leaf; return; } + mnode_t *node = sv.worldmodel->brush.nodes + node_id; // NODE_MIXED - splitplane = node->plane; + splitplane = (plane_t *) &node->plane; sides = BOX_ON_PLANE_SIDE (SVvector (ent, absmin), SVvector (ent, absmax), splitplane); @@ -497,7 +496,7 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers) // link to PVS leafs free_edict_leafs (&SVdata (ent)->leafs); if (SVfloat (ent, modelindex)) - SV_FindTouchedLeafs (ent, sv.worldmodel->brush.nodes); + SV_FindTouchedLeafs (ent, 0); if (SVfloat (ent, solid) == SOLID_NOT) return; From 7a97a7223288a140eab08a184332bf669b95092e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 May 2022 13:51:55 +0900 Subject: [PATCH 2856/3664] [input] Correct some type-setting issues in command help --- libs/input/in_binding.c | 11 ++++++----- libs/input/in_imt.c | 15 ++++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 8a0319934..76ba7d521 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -728,17 +728,17 @@ static bindcmd_t in_binding_commands[] = { "commands in quotes and separate with semi-colons." }, { "in_unbind", in_unbind_f, - "Remove the bind from the the selected key" + "Remove the bind from the the selected key." }, { "in_clear", in_clear_f, - "Remove all binds from the specified imts" + "Remove all binds from the specified imts." }, { "in_devices", in_devices_f, "List the known devices and their status." }, { "in_connect", in_connect_f, - "Create a device binding connection. Supports hot-plug in that the " - "device will be automatically reconnected when plugged in or" + "Create a device binding connection. Supports hot-plug: the " + "device will be automatically reconnected when plugged in or " PACKAGE_NAME " is restarted." }, { "in_connections", in_connections_f, @@ -746,10 +746,11 @@ static bindcmd_t in_binding_commands[] = { }, { "keyhelp", keyhelp_f, "Identify the next active input axis or button.\n" + "\n" "The identification includes the device binding name, axis or button " "number, and (if known) the name of the axis or button. Axes and " "buttons can always be bound by number, so even those for which a " - "name is not known, but" PACKAGE_NAME " sees, can be bound." + "name is not known, but " PACKAGE_NAME " sees, can be bound." }, { } #if 0 diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 2c2981369..be56369f9 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -879,13 +879,14 @@ static imtcmd_t imt_commands[] = { "Set the active imt of the specified context" }, { "imt_list", imt_list_f, - "List the available input mapping tables" + "List the available input mapping tables." }, { "imt_create", imt_create_f, "create a new imt table:\n" " imt_create [chain_name]\n" "\n" - "The new table will be attached to the specified context\n" + "The new table will be attached to the specified context.\n" + "\n" "imt_name must not already exist.\n" "If given, chain_name must already exist and be in the context.\n" }, @@ -894,15 +895,18 @@ static imtcmd_t imt_commands[] = { " imt_switcher_create " " [..]\n" "name is the name of the switcher and must be unique across all\n" - "contexts\n" + "contexts.\n" + "\n" "The new switcher will be attached to the specified context\n" + "\n" "default_imt specifies the default imt to be used for all possible\n" "states and must exist and be in the context.\n" + "\n" "input0..inputN specify the inputs (cvar or button) used to set the\n" "switcher's state. As each input forms a bit in the state index,\n" "there will be 2**(N+1) states (so 4 inputs will result in 16\n" "states, and 16 inputs will result in 65536 states). Up to 16 inputs\n" - "are allowed\n" + "are allowed.\n" "\n" "Buttons are spefied as +buttonname (eg, +mlook, +strafe).\n" "Cvars are just the cvar name (eg, freelook, lookstrafe).\n" @@ -920,13 +924,14 @@ static imtcmd_t imt_commands[] = { "state_index is the state index formed by the binary number\n" "interpretation of the inputs with input0 being bit 0 and inputN\n" "being bit N.\n" + "\n" "imt is the name of the imt to be assigned to the state and must\n" "exist and be in the same context as the switcher.\n" "\n" "Any number of state_index imt pairs can be specified.\n" }, { "imt_drop_all", imt_drop_all_f, - "delete all imt tables\n" + "Delete all imt tables.\n" }, {}, }; From 4e5eec02772899eec8d53e47ce57305d2e837a9f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 May 2022 13:52:34 +0900 Subject: [PATCH 2857/3664] [input] Correct copyright attribution for in_imt.c Id had nothing to do with imt tables. It was Mercury (Zephaniah) that created the initial design and code, and I took the design further. --- libs/input/in_imt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index be56369f9..02a7463c0 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -3,7 +3,7 @@ Input Mapping Table management - Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2001 Zephaniah E. Hull Copyright (C) 2021 Bill Currie Author: Bill Currie From d40769c21dcbe52989a7856ffe0ec3cc9c218e7e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 May 2022 14:43:07 +0900 Subject: [PATCH 2858/3664] [model] Move visframe out of mleaf_t This is next critical step to making BSP rendering thread-safe. visframe was replaced with cluster (not used yet) in anticipation of BSP cluster reconstruction (which will be necessary for dealing with large maps like ad_tears). --- include/QF/model.h | 2 +- include/r_internal.h | 4 +++- libs/video/renderer/gl/gl_rmisc.c | 2 +- libs/video/renderer/glsl/glsl_main.c | 2 +- libs/video/renderer/r_bsp.c | 4 ++-- libs/video/renderer/r_light.c | 2 +- libs/video/renderer/r_screen.c | 6 ++++-- libs/video/renderer/sw/sw_rbsp.c | 2 +- libs/video/renderer/sw/sw_rmain.c | 2 +- libs/video/renderer/vulkan/vulkan_main.c | 2 +- 10 files changed, 16 insertions(+), 12 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index e8d9df66a..f9dcac3a5 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -193,7 +193,7 @@ typedef struct mnode_s { typedef struct mleaf_s { // common with node int contents; // wil be a negative contents number - int visframe; // node needs to be traversed if current + int cluster; // cluster to which this leaf bleongs XXX // for bounding box culling float mins[3]; diff --git a/include/r_internal.h b/include/r_internal.h index 35b1fda30..36d07f1da 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -74,8 +74,10 @@ struct entity_s; struct animation_s; void R_DrawAliasModel (struct entity_s *e); -void R_MarkLeaves (struct mleaf_s *viewleaf, int *node_visframes); +void R_MarkLeaves (struct mleaf_s *viewleaf, int *node_visframes, + int *leaf_visframes); extern int *r_node_visframes; +extern int *r_leaf_visframes; void GL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 96d011fa8..24d818916 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -173,7 +173,7 @@ gl_R_NewScene (scene_t *scene) brush->leafs[i].efrags = NULL; // Force a vis update - R_MarkLeaves (0, 0); + R_MarkLeaves (0, 0, 0); R_ClearParticles (); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index fb0996427..30f315a95 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -199,7 +199,7 @@ glsl_R_NewScene (scene_t *scene) r_refdef.worldmodel = scene->worldmodel; // Force a vis update - R_MarkLeaves (0, 0); + R_MarkLeaves (0, 0, 0); R_ClearParticles (); glsl_R_RegisterTextures (scene->models, scene->num_models); diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 468357857..f430eea6b 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -47,7 +47,7 @@ static mleaf_t *r_oldviewleaf; static set_t *solid; void -R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes) +R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes, int *leaf_visframes) { set_t *vis; int c; @@ -84,7 +84,7 @@ R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes) mark++; } while (--c); } - leaf->visframe = r_visframecount; + leaf_visframes[i + 1] = r_visframecount; int node_id = brush->leaf_parents[leaf - brush->leafs]; while (node_id >= 0) { if (node_visframes[node_id] == r_visframecount) diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 614227a92..7dade022b 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -294,7 +294,7 @@ R_MarkLights (vec4f_t lightorigin, dlight_t *light, int lightnum, mleaf_t *leaf = &brush->leafs[leafnum + 1]; if (!(vis_bits & b)) continue; - if (leaf->visframe != r_visframecount) + if (r_leaf_visframes[leafnum + 1] != r_visframecount) continue; if (leaf->mins[0] > maxs[0] || leaf->maxs[0] < mins[0] || leaf->mins[1] > maxs[1] || leaf->maxs[1] < mins[1] diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 3255d88ef..6bd37f9ad 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -62,6 +62,7 @@ int scr_copytop; byte *draw_chars; // 8*8 graphic characters FIXME location qboolean r_cache_thrash; // set if surface cache is thrashing int *r_node_visframes; //FIXME per renderer +int *r_leaf_visframes; //FIXME per renderer qboolean scr_skipupdate; static qboolean scr_initialized;// ready to draw @@ -283,7 +284,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, r_data->vid->height); } - R_MarkLeaves (scr_scene->viewleaf, r_node_visframes); + R_MarkLeaves (scr_scene->viewleaf, r_node_visframes, r_leaf_visframes); } R_PushDlights (vec3_origin); @@ -515,8 +516,9 @@ SCR_NewScene (scene_t *scene) scr_scene = scene; if (scene) { mod_brush_t *brush = &scr_scene->worldmodel->brush; - int size = brush->numnodes * sizeof (int); + int size = (brush->numnodes + brush->modleafs) * sizeof (int); r_node_visframes = Hunk_AllocName (0, size, "visframes"); + r_leaf_visframes = r_node_visframes + brush->numnodes; r_funcs->set_fov (tan_fov_x, tan_fov_y); r_funcs->R_NewScene (scene); } else { diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 4947dc24b..1402bae5f 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -234,7 +234,7 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode, // we're done with this branch if the node or leaf isn't in the PVS if (child_id < 0) { mleaf_t *leaf = r_refdef.worldmodel->brush.leafs + ~child_id; - if (leaf->visframe == r_visframecount + if (r_leaf_visframes[~child_id] == r_visframecount && leaf->contents != CONTENTS_SOLID) { r_currentbkey = leaf->key; R_RenderBmodelFace (ent, psideedges[i], psurf); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index f129b2254..11f0f765b 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -167,7 +167,7 @@ R_NewScene (scene_t *scene) R_InitSky (brush->skytexture); // Force a vis update - R_MarkLeaves (0, 0); + R_MarkLeaves (0, 0, 0); R_ClearParticles (); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 59e327df7..f7fb607c3 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -142,7 +142,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) r_refdef.worldmodel = scene->worldmodel; // Force a vis update - R_MarkLeaves (0, 0); + R_MarkLeaves (0, 0, 0); R_ClearParticles (); Vulkan_RegisterTextures (scene->models, scene->num_models, ctx); From c8472755d1b65537a4dc6f024ca0e9604d5b43f9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 May 2022 16:31:24 +0900 Subject: [PATCH 2859/3664] [model] Move visframe out of msurface_t One more step towards BSP thread-safety. This one brought with it a very noticeable speed boost (ie, not lost in the noise) thanks to the face visframes being in tightly packed groups instead of 128 bytes apart, though the sw render's boost is lost in the noise (but it's very fill-rate limited). --- include/QF/model.h | 3 ++- include/r_internal.h | 3 ++- libs/video/renderer/gl/gl_rmisc.c | 2 +- libs/video/renderer/gl/gl_rsurf.c | 7 ++++--- libs/video/renderer/glsl/glsl_bsp.c | 7 ++++--- libs/video/renderer/glsl/glsl_main.c | 2 +- libs/video/renderer/r_bsp.c | 5 +++-- libs/video/renderer/r_light.c | 3 ++- libs/video/renderer/r_screen.c | 9 +++++++-- libs/video/renderer/sw/sw_rbsp.c | 7 ++++--- libs/video/renderer/sw/sw_rmain.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 7 ++++--- libs/video/renderer/vulkan/vulkan_main.c | 2 +- 13 files changed, 36 insertions(+), 23 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index f9dcac3a5..68af9e1f2 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -139,7 +139,8 @@ typedef struct glpoly_s { #define MAX_DLIGHTS 128 typedef struct msurface_s { - int visframe; // should be drawn when node is crossed + int _visframe; // should be drawn when node is crossed/ + // no longer used, see r_face_visframes int flags; plane_t *plane; diff --git a/include/r_internal.h b/include/r_internal.h index 36d07f1da..b3868c677 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -75,9 +75,10 @@ struct animation_s; void R_DrawAliasModel (struct entity_s *e); void R_MarkLeaves (struct mleaf_s *viewleaf, int *node_visframes, - int *leaf_visframes); + int *leaf_visframes, int *face_visframes); extern int *r_node_visframes; extern int *r_leaf_visframes; +extern int *r_face_visframes; void GL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette); diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 24d818916..c2baac427 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -173,7 +173,7 @@ gl_R_NewScene (scene_t *scene) brush->leafs[i].efrags = NULL; // Force a vis update - R_MarkLeaves (0, 0, 0); + R_MarkLeaves (0, 0, 0, 0); R_ClearParticles (); diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 39bd40cb0..b5988557d 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -612,9 +612,10 @@ visit_node (glbspctx_t *bctx, mnode_t *node, int side) side = (~side + 1) & SURF_PLANEBACK; // draw stuff if ((c = node->numsurfaces)) { - surf = bctx->brush->surfaces + node->firstsurface; - for (; c; c--, surf++) { - if (surf->visframe != r_visframecount) + int surf_id = node->firstsurface; + surf = bctx->brush->surfaces + surf_id; + for (; c; c--, surf++, surf_id++) { + if (r_face_visframes[surf_id] != r_visframecount) continue; // side is either 0 or SURF_PLANEBACK diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 06d1b87a0..4a73e13e2 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -753,9 +753,10 @@ visit_node (glslbspctx_t *bctx, mnode_t *node, int side) // chain any visible surfaces on the node that face the camera. // not all nodes have any surfaces to draw (purely a split plane) if ((c = node->numsurfaces)) { - surf = bctx->brush->surfaces + node->firstsurface; - for (; c; c--, surf++) { - if (surf->visframe != r_visframecount) + int surf_id = node->firstsurface; + surf = bctx->brush->surfaces + surf_id; + for (; c; c--, surf++, surf_id++) { + if (r_face_visframes[surf_id] != r_visframecount) continue; // side is either 0 or SURF_PLANEBACK diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 30f315a95..f8d6bf02d 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -199,7 +199,7 @@ glsl_R_NewScene (scene_t *scene) r_refdef.worldmodel = scene->worldmodel; // Force a vis update - R_MarkLeaves (0, 0, 0); + R_MarkLeaves (0, 0, 0, 0); R_ClearParticles (); glsl_R_RegisterTextures (scene->models, scene->num_models); diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index f430eea6b..4c4550649 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -47,7 +47,8 @@ static mleaf_t *r_oldviewleaf; static set_t *solid; void -R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes, int *leaf_visframes) +R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes, int *leaf_visframes, + int *face_visframes) { set_t *vis; int c; @@ -80,7 +81,7 @@ R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes, int *leaf_visframes) if ((c = leaf->nummarksurfaces)) { mark = brush->marksurfaces + leaf->firstmarksurface; do { - (*mark)->visframe = r_visframecount; + face_visframes[*mark - brush->surfaces] = r_visframecount; mark++; } while (--c); } diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 7dade022b..278710005 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -305,7 +305,8 @@ R_MarkLights (vec4f_t lightorigin, dlight_t *light, int lightnum, msurface_t **msurf = brush->marksurfaces + leaf->firstmarksurface; for (m = 0; m < leaf->nummarksurfaces; m++) { msurface_t *surf = *msurf++; - if (surf->visframe != r_visframecount) + int surf_id = surf - brush->surfaces; + if (r_face_visframes[surf_id] != r_visframecount) continue; mark_surfaces (surf, lightorigin, light, lightnum); } diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 6bd37f9ad..f55531c0c 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -63,6 +63,7 @@ byte *draw_chars; // 8*8 graphic characters FIXME location qboolean r_cache_thrash; // set if surface cache is thrashing int *r_node_visframes; //FIXME per renderer int *r_leaf_visframes; //FIXME per renderer +int *r_face_visframes; //FIXME per renderer qboolean scr_skipupdate; static qboolean scr_initialized;// ready to draw @@ -284,7 +285,8 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, r_data->vid->height); } - R_MarkLeaves (scr_scene->viewleaf, r_node_visframes, r_leaf_visframes); + R_MarkLeaves (scr_scene->viewleaf, r_node_visframes, r_leaf_visframes, + r_face_visframes); } R_PushDlights (vec3_origin); @@ -516,9 +518,12 @@ SCR_NewScene (scene_t *scene) scr_scene = scene; if (scene) { mod_brush_t *brush = &scr_scene->worldmodel->brush; - int size = (brush->numnodes + brush->modleafs) * sizeof (int); + int count = brush->numnodes + brush->modleafs + + brush->numsurfaces; + int size = count * sizeof (int); r_node_visframes = Hunk_AllocName (0, size, "visframes"); r_leaf_visframes = r_node_visframes + brush->numnodes; + r_face_visframes = r_leaf_visframes + brush->modleafs; r_funcs->set_fov (tan_fov_x, tan_fov_y); r_funcs->R_NewScene (scene); } else { diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 1402bae5f..7ef8e20fd 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -384,9 +384,10 @@ visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags) side = (~side + 1) & SURF_PLANEBACK; // draw stuff if ((c = node->numsurfaces)) { - surf = brush->surfaces + node->firstsurface; - for (; c; c--, surf++) { - if (surf->visframe != r_visframecount) + int surf_id = node->firstsurface; + surf = brush->surfaces + surf_id; + for (; c; c--, surf++, surf_id++) { + if (r_face_visframes[surf_id] != r_visframecount) continue; // side is either 0 or SURF_PLANEBACK diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 11f0f765b..b75c7efae 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -167,7 +167,7 @@ R_NewScene (scene_t *scene) R_InitSky (brush->skytexture); // Force a vis update - R_MarkLeaves (0, 0, 0); + R_MarkLeaves (0, 0, 0, 0); R_ClearParticles (); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index e92f0d20e..2e4b0b05e 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -665,9 +665,10 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) // chain any visible surfaces on the node that face the camera. // not all nodes have any surfaces to draw (purely a split plane) if ((c = node->numsurfaces)) { - surf = brush->surfaces + node->firstsurface; - for (; c; c--, surf++) { - if (surf->visframe != r_visframecount) + int surf_id = node->firstsurface; + surf = brush->surfaces + surf_id; + for (; c; c--, surf++, surf_id++) { + if (r_face_visframes[surf_id] != r_visframecount) continue; // side is either 0 or SURF_PLANEBACK diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index f7fb607c3..accd40842 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -142,7 +142,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) r_refdef.worldmodel = scene->worldmodel; // Force a vis update - R_MarkLeaves (0, 0, 0); + R_MarkLeaves (0, 0, 0, 0); R_ClearParticles (); Vulkan_RegisterTextures (scene->models, scene->num_models, ctx); From c6f520b743bd909eb7784161f6454eba5917165e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 May 2022 23:38:18 +0900 Subject: [PATCH 2860/3664] [model] Clean out some useless surface flags The gl water warp ones have been useless since very early on due to not doing water warp in gl (vertex warping just didn't work well), and the recent water warp implementation doesn't need those hacks. The rest of the removed flags just aren't needed for anything. SURF_DRAWNOALPHA might get renamed, but should be useful for translucent bsp surfaces (eg, vines in ad_tears). --- include/QF/model.h | 18 +++++++----------- libs/models/brush/model_brush.c | 21 --------------------- libs/video/renderer/gl/gl_rsurf.c | 2 +- 3 files changed, 8 insertions(+), 33 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index 68af9e1f2..4491c2e55 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -102,17 +102,13 @@ typedef struct texture_s { } texture_t; -#define SURF_PLANEBACK 2 -#define SURF_DRAWSKY 4 -#define SURF_DRAWSPRITE 8 -#define SURF_DRAWTURB 0x10 -#define SURF_DRAWTILED 0x20 -#define SURF_DRAWBACKGROUND 0x40 -#define SURF_UNDERWATER 0x80 -#define SURF_DONTWARP 0x100 -#define SURF_DRAWNOALPHA 0x200 -#define SURF_DRAWFULLBRIGHT 0x400 -#define SURF_LIGHTBOTHSIDES 0x800 +#define SURF_PLANEBACK 0x02 +#define SURF_DRAWSKY 0x04 +#define SURF_DRAWTURB 0x08 +#define SURF_DRAWTILED 0x10 +#define SURF_DRAWBACKGROUND 0x20 +#define SURF_DRAWNOALPHA 0x40 +#define SURF_LIGHTBOTHSIDES 0x80 // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 8e3d652e2..2bfa85aa3 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -760,7 +760,6 @@ Mod_LoadLeafs (model_t *mod, bsp_t *bsp) dleaf_t *in; int count, i, j, p; mleaf_t *out; - qboolean isnotmap = true; mod_brush_t *brush = &mod->brush; in = bsp->leafs; @@ -769,10 +768,6 @@ Mod_LoadLeafs (model_t *mod, bsp_t *bsp) brush->leafs = out; brush->modleafs = count; -// snprintf(s, sizeof (s), "maps/%s.bsp", -// Info_ValueForKey(cl.serverinfo,"map")); - if (!strncmp ("maps/", mod->path, 5)) - isnotmap = false; for (i = 0; i < count; i++, in++, out++) { for (j = 0; j < 3; j++) { out->mins[j] = in->mins[j]; @@ -794,22 +789,6 @@ Mod_LoadLeafs (model_t *mod, bsp_t *bsp) for (j = 0; j < 4; j++) out->ambient_sound_level[j] = in->ambient_level[j]; - - // gl underwater warp - if (out->contents != CONTENTS_EMPTY) { - msurface_t **msurf = brush->marksurfaces + out->firstmarksurface; - for (j = 0; j < out->nummarksurfaces; j++) { - msurface_t *surf = *msurf++; - surf->flags |= SURF_UNDERWATER; - } - } - if (isnotmap) { - msurface_t **msurf = brush->marksurfaces + out->firstmarksurface; - for (j = 0; j < out->nummarksurfaces; j++) { - msurface_t *surf = *msurf++; - surf->flags |= SURF_DONTWARP; - } - } } } diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index b5988557d..b173c7679 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -856,7 +856,7 @@ GL_BuildSurfaceDisplayList (mod_brush_t *brush, msurface_t *surf) } // remove co-linear points - Ed - if (!gl_keeptjunctions && !(surf->flags & SURF_UNDERWATER)) { + if (!gl_keeptjunctions) { for (i = 0; i < lnumverts; ++i) { vec3_t v1, v2; float *prev, *this, *next; From 3a2560e4c171335dd147cfefd61f9c3edbf52472 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 May 2022 01:28:43 +0900 Subject: [PATCH 2861/3664] [vulkan] Implement thread-safe rendering for the world model Sub-models and instance models need an instance data buffer, but this gets the basics working (and the proof of concept). Using arrays like this actually simplified a lot of the code, and will make it easy to get transparency without turbulence (just another queue). --- include/QF/Vulkan/qf_bsp.h | 108 +++-- libs/models/brush/vulkan_model_brush.c | 1 - libs/video/renderer/vulkan/vulkan_bsp.c | 565 +++++++++--------------- 3 files changed, 269 insertions(+), 405 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index ab823c2fa..d5b3137de 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -39,30 +39,81 @@ #include "QF/simd/types.h" +typedef struct bsp_face_s { + uint32_t first_index; + uint32_t index_count; + uint32_t tex_id; + uint32_t flags; +} bsp_face_t; + +typedef struct bsp_packet_s { + int first_index; + int index_count; + int transform_id; + int color_id; +} bsp_packet_t; + +typedef struct bsp_packetset_s + DARRAY_TYPE (bsp_packet_t) bsp_packetset_t; + +typedef struct bsp_indexset_s + DARRAY_TYPE (uint32_t) bsp_indexset_t; + +typedef struct bsp_tex_s { + VkDescriptorSet descriptors; + bsp_packetset_t packets; + bsp_indexset_t indices; +} bsp_tex_t; + typedef struct vulktex_s { - struct texture_s *texture; - struct instsurf_s *tex_chain; // for gl_texsort drawing - struct instsurf_s **tex_chain_tail; - struct elechain_s *elechain; - struct elechain_s **elechain_tail; struct qfv_tex_s *tex; VkDescriptorSet descriptor; + int tex_id; } vulktex_t; +typedef struct regtexset_s + DARRAY_TYPE (vulktex_t *) regtexset_t; + +typedef struct bsp_texset_s + DARRAY_TYPE (bsp_tex_t) bsp_texset_t; + +typedef struct bsp_draw_s { + uint32_t tex_id; + uint32_t index_count; + uint32_t instance_count; + uint32_t first_index; + uint32_t first_instance; +} bsp_draw_t; + +typedef struct bsp_drawset_s + DARRAY_TYPE (bsp_draw_t) bsp_drawset_t; + +typedef struct instface_s { + uint32_t inst_id; + uint32_t face; +} instface_t; + +typedef struct bsp_instfaceset_s + DARRAY_TYPE (instface_t) bsp_instfaceset_t; + +typedef struct bsp_pass_s { + uint32_t *indices; // points into index buffer + uint32_t index_count; // number of indices written to buffer + int vis_frame; + int *face_frames; + int *leaf_frames; + int *node_frames; + bsp_instfaceset_t *face_queue; + regtexset_t *textures; + int num_queues; + bsp_drawset_t *draw_queues; +} bsp_pass_t; + typedef struct bspvert_s { quat_t vertex; quat_t tlst; } bspvert_t; -typedef struct elechain_s { - struct elechain_s *_next; - struct elechain_s *next; - uint32_t first_index; - uint32_t index_count; - vec_t *transform; - float *color; -} elechain_t; - typedef enum { qfv_bsp_texture, qfv_bsp_glowmap, @@ -90,33 +141,13 @@ typedef struct bspframe_s { typedef struct bspframeset_s DARRAY_TYPE (bspframe_t) bspframeset_t; -typedef struct texchainset_s - DARRAY_TYPE (vulktex_t *) texchainset_t; - typedef struct bspctx_s { struct entity_s *entity; vec_t *transform; float *color; + uint32_t inst_id; - instsurf_t *waterchain; - instsurf_t **waterchain_tail; - instsurf_t *sky_chain; - instsurf_t **sky_chain_tail; - - texchainset_t texture_chains; - - // for world and non-instance models - instsurf_t *static_instsurfs; - instsurf_t **static_instsurfs_tail; - instsurf_t *free_static_instsurfs; - - // for instance models - elechain_t *elechains; - elechain_t **elechains_tail; - elechain_t *free_elechains; - instsurf_t *instsurfs; - instsurf_t **instsurfs_tail; - instsurf_t *free_instsurfs; + regtexset_t registered_textures; struct qfv_tex_s *default_skysheet; struct qfv_tex_s *skysheet_tex; @@ -131,7 +162,10 @@ typedef struct bspctx_s { struct scrap_s *light_scrap; struct qfv_stagebuf_s *light_stage; - struct bsppoly_s *polys; + bsp_face_t *faces; + uint32_t *poly_indices; + + bsp_pass_t main_pass; // camera view depth, gbuffer, etc VkSampler sampler; VkPipelineLayout layout; diff --git a/libs/models/brush/vulkan_model_brush.c b/libs/models/brush/vulkan_model_brush.c index f706083a2..94e428671 100644 --- a/libs/models/brush/vulkan_model_brush.c +++ b/libs/models/brush/vulkan_model_brush.c @@ -307,7 +307,6 @@ Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, vulkan_ctx_t *ctx) } vulktex_t *tex = tx->render; - tex->texture = tx; tex->tex = (qfv_tex_t *) (tex + 1); VkExtent3D extent = { tx->width, tx->height, 1 }; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 2e4b0b05e..a4e9a340d 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -105,67 +105,6 @@ static vulktex_t vulkan_notexture = { }; #define ALLOC_CHUNK 64 -typedef struct bsppoly_s { - uint32_t count; - uint32_t indices[1]; -} bsppoly_t; - -#define CHAIN_SURF_F2B(surf,chain) \ - ({ \ - instsurf_t *inst = (surf)->instsurf; \ - if (__builtin_expect(!inst, 1)) \ - inst = get_instsurf (bctx); \ - inst->surface = (surf); \ - *(chain##_tail) = inst; \ - (chain##_tail) = &inst->tex_chain; \ - *(chain##_tail) = 0; \ - inst; \ - }) - -#define CHAIN_SURF_B2F(surf,chain) \ - ({ \ - instsurf_t *inst = (surf)->instsurf; \ - if (__builtin_expect(!inst, 1)) \ - inst = get_instsurf (bctx); \ - inst->surface = (surf); \ - inst->tex_chain = (chain); \ - (chain) = inst; \ - inst; \ - }) - -#define GET_RELEASE(type,name) \ -static inline type * \ -get_##name (bspctx_t *bctx) \ -{ \ - type *ele; \ - if (!bctx->free_##name##s) { \ - int i; \ - bctx->free_##name##s = calloc (ALLOC_CHUNK, sizeof (type)); \ - for (i = 0; i < ALLOC_CHUNK - 1; i++) \ - bctx->free_##name##s[i]._next = &bctx->free_##name##s[i + 1]; \ - } \ - ele = bctx->free_##name##s; \ - bctx->free_##name##s = ele->_next; \ - ele->_next = 0; \ - *bctx->name##s_tail = ele; \ - bctx->name##s_tail = &ele->_next; \ - return ele; \ -} \ -static inline void \ -release_##name##s (bspctx_t *bctx) \ -{ \ - if (bctx->name##s) { \ - *bctx->name##s_tail = bctx->free_##name##s; \ - bctx->free_##name##s = bctx->name##s; \ - bctx->name##s = 0; \ - bctx->name##s_tail = &bctx->name##s; \ - } \ -} - -GET_RELEASE (elechain_t, elechain) -GET_RELEASE (instsurf_t, static_instsurf) -GET_RELEASE (instsurf_t, instsurf) - static void add_texture (texture_t *tx, vulkan_ctx_t *ctx) { @@ -173,83 +112,25 @@ add_texture (texture_t *tx, vulkan_ctx_t *ctx) vulktex_t *tex = tx->render; if (tex->tex) { - DARRAY_APPEND (&bctx->texture_chains, tex); + tex->tex_id = bctx->registered_textures.size; + DARRAY_APPEND (&bctx->registered_textures, tex); tex->descriptor = Vulkan_CreateTextureDescriptor (ctx, tex->tex, bctx->sampler); } - tex->tex_chain = 0; - tex->tex_chain_tail = &tex->tex_chain; - tex->elechain = 0; - tex->elechain_tail = &tex->elechain; -} - -static void -init_surface_chains (mod_brush_t *brush, vulkan_ctx_t *ctx) -{ - bspctx_t *bctx = ctx->bsp_context; - - release_static_instsurfs (bctx); - release_instsurfs (bctx); - - for (unsigned i = 0; i < brush->nummodelsurfaces; i++) { - brush->surfaces[i].instsurf = get_static_instsurf (bctx); - brush->surfaces[i].instsurf->surface = &brush->surfaces[i]; - } -} - -static inline void -clear_tex_chain (vulktex_t *tex) -{ - tex->tex_chain = 0; - tex->tex_chain_tail = &tex->tex_chain; - tex->elechain = 0; - tex->elechain_tail = &tex->elechain; -} - -static void -clear_texture_chains (bspctx_t *bctx) -{ - for (size_t i = 0; i < bctx->texture_chains.size; i++) { - if (!bctx->texture_chains.a[i]) - continue; - clear_tex_chain (bctx->texture_chains.a[i]); - } - clear_tex_chain (r_notexture_mip->render); - release_elechains (bctx); - release_instsurfs (bctx); } void Vulkan_ClearElements (vulkan_ctx_t *ctx) { - bspctx_t *bctx = ctx->bsp_context; - release_elechains (bctx); +// bspctx_t *bctx = ctx->bsp_context; } static inline void -chain_surface (msurface_t *surf, vulkan_ctx_t *ctx) +chain_surface (const bsp_face_t *face, bsp_pass_t *pass, bspctx_t *bctx) { - bspctx_t *bctx = ctx->bsp_context; - instsurf_t *is; - if (surf->flags & SURF_DRAWSKY) { - is = CHAIN_SURF_F2B (surf, bctx->sky_chain); - } else if ((surf->flags & SURF_DRAWTURB) - || (bctx->color && bctx->color[3] < 1.0)) { - is = CHAIN_SURF_B2F (surf, bctx->waterchain); - } else { - texture_t *tx; - vulktex_t *tex; - - if (!surf->texinfo->texture->anim_total) - tx = surf->texinfo->texture; - else - tx = R_TextureAnimation (bctx->entity, surf); - tex = tx->render; - is = CHAIN_SURF_F2B (surf, tex->tex_chain); - } - is->transform = bctx->transform; - is->color = bctx->color; + DARRAY_APPEND (&pass->face_queue[face->tex_id], + ((instface_t) { bctx->inst_id, face - bctx->faces })); } static void @@ -269,7 +150,16 @@ static void clear_textures (vulkan_ctx_t *ctx) { bspctx_t *bctx = ctx->bsp_context; - bctx->texture_chains.size = 0; + + if (bctx->main_pass.face_queue) { + for (size_t i = 0; i < bctx->registered_textures.size; i++) { + DARRAY_CLEAR (&bctx->main_pass.face_queue[i]); + } + free (bctx->main_pass.face_queue); + bctx->main_pass.face_queue = 0; + } + + bctx->registered_textures.size = 0; } void @@ -280,7 +170,6 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) mod_brush_t *brush = &r_refdef.worldmodel->brush; clear_textures (ctx); - init_surface_chains (brush, ctx); add_texture (r_notexture_mip, ctx); register_textures (brush, ctx); for (i = 0; i < num_models; i++) { @@ -297,60 +186,67 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) brush->numsubmodels = 1; // no support for submodels in non-world model register_textures (brush, ctx); } + + bspctx_t *bctx = ctx->bsp_context; + int num_tex = bctx->registered_textures.size; + bctx->main_pass.face_queue = malloc (num_tex * sizeof (bsp_instfaceset_t)); + for (int i = 0; i < num_tex; i++) { + bctx->main_pass.face_queue[i] + = (bsp_instfaceset_t) DARRAY_STATIC_INIT (128); + } } -static elechain_t * -add_elechain (vulktex_t *tex, bspctx_t *bctx) -{ - elechain_t *ec; +typedef struct { + msurface_t *face; + model_t *model; + int model_face_base; +} faceref_t; - ec = get_elechain (bctx); - ec->first_index = 0; - ec->index_count = 0; - ec->transform = 0; - ec->color = 0; - *tex->elechain_tail = ec; - tex->elechain_tail = &ec->next; - return ec; -} +typedef struct DARRAY_TYPE (faceref_t) facerefset_t; static void -count_verts_inds (model_t **models, msurface_t *surf, - uint32_t *verts, uint32_t *inds) +count_verts_inds (faceref_t *faceref, uint32_t *verts, uint32_t *inds) { + msurface_t *surf = faceref->face; *verts = surf->numedges; *inds = surf->numedges + 1; } -static bsppoly_t * -build_surf_displist (model_t **models, msurface_t *surf, int base, - bspvert_t **vert_list) -{ - mod_brush_t *brush; - if (surf->model_index < 0) { - // instance model - brush = &models[~surf->model_index]->brush; - } else { - // main or sub model - brush = &r_refdef.worldmodel->brush; - } - mvertex_t *vertices = brush->vertexes; - medge_t *edges = brush->edges; - int *surfedges = brush->surfedges; +typedef struct { + bsp_face_t *faces; + uint32_t *indices; + bspvert_t *vertices; + uint32_t index_base; + uint32_t vertex_base; + int tex_id; +} buildctx_t; - // surf->polys is set to the next slot before the call - bsppoly_t *poly = (bsppoly_t *) surf->polys; +static void +build_surf_displist (faceref_t *faceref, buildctx_t *build) +{ + msurface_t *surf = faceref->face; + mod_brush_t *brush = &faceref->model->brush;; + + int facenum = surf - brush->surfaces; + bsp_face_t *face = &build->faces[facenum + faceref->model_face_base]; // create a triangle fan int numverts = surf->numedges; - poly->count = numverts + 1; // +1 for primitive restart + face->first_index = build->index_base; + face->index_count = numverts + 1; // +1 for primitive restart + face->tex_id = build->tex_id; + face->flags = surf->flags; + build->index_base += face->index_count; for (int i = 0; i < numverts; i++) { - poly->indices[i] = base + i; + build->indices[face->first_index + i] = build->vertex_base + i; } - poly->indices[numverts] = -1; // primitive restart - surf->polys = (glpoly_t *) poly; + build->indices[face->first_index + numverts] = -1; // primitive restart - bspvert_t *verts = *vert_list; + bspvert_t *verts = build->vertices + build->vertex_base; + build->vertex_base += numverts; mtexinfo_t *texinfo = surf->texinfo; + mvertex_t *vertices = brush->vertexes; + medge_t *edges = brush->edges; + int *surfedges = brush->surfedges; for (int i = 0; i < numverts; i++) { vec_t *vec; int index = surfedges[surf->firstedge + i]; @@ -388,8 +284,6 @@ build_surf_displist (model_t **models, msurface_t *surf, int base, verts[i].tlst[3] = 0; } } - *vert_list += numverts; - return (bsppoly_t *) &poly->indices[poly->count]; } void @@ -403,9 +297,16 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) return; } + facerefset_t *face_sets = alloca (bctx->registered_textures.size + * sizeof (facerefset_t)); + for (size_t i = 0; i < bctx->registered_textures.size; i++) { + face_sets[i] = (facerefset_t) DARRAY_STATIC_INIT (1024); + } + // run through all surfaces, chaining them to their textures, thus // effectively sorting the surfaces by texture (without worrying about // surface order on the same texture chain). + int face_base = 0; for (int i = 0; i < num_models; i++) { model_t *m = models[i]; // sub-models are done as part of the main model @@ -421,30 +322,32 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) if (dm == brush->submodels + brush->numsubmodels) { // limit the surfaces // probably never hit - Sys_Printf ("R_BuildDisplayLists: too many surfaces\n"); + Sys_Printf ("Vulkan_BuildDisplayLists: too many faces\n"); brush->numsurfaces = j; break; } } msurface_t *surf = brush->surfaces + j; - surf->model_index = dm - brush->submodels; - if (!surf->model_index && m != r_refdef.worldmodel) { - surf->model_index = -1 - i; // instanced model - } // append surf to the texture chain vulktex_t *tex = surf->texinfo->texture->render; - CHAIN_SURF_F2B (surf, tex->tex_chain); + DARRAY_APPEND (&face_sets[tex->tex_id], + ((faceref_t) { surf, m, face_base })); } + face_base += brush->numsurfaces; } // All vertices from all brush models go into one giant vbo. uint32_t vertex_count = 0; uint32_t index_count = 0; uint32_t poly_count = 0; - for (size_t i = 0; i < bctx->texture_chains.size; i++) { - vulktex_t *tex = bctx->texture_chains.a[i]; - for (instsurf_t *is = tex->tex_chain; is; is = is->tex_chain) { + // This is not optimal as counted vertices are not shared between faces, + // however this greatly simplifies display list creation as no care needs + // to be taken when it comes to UVs, and every vertex needs a unique light + // map UV anyway (when lightmaps are used). + for (size_t i = 0; i < bctx->registered_textures.size; i++) { + for (size_t j = 0; j < face_sets[i].size; j++) { + faceref_t *faceref = &face_sets[i].a[j]; uint32_t verts, inds; - count_verts_inds (models, is->surface, &verts, &inds); + count_verts_inds (faceref, &verts, &inds); vertex_count += verts; index_count += inds; poly_count++; @@ -464,44 +367,39 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) qfv_packet_t *packet = QFV_PacketAcquire (stage); bspvert_t *vertices = QFV_PacketExtend (packet, vertex_buffer_size); // holds all the polygon definitions: vertex indices + poly_count - // primitive restart markers + poly_count index counts. The primitive - // restart markers are included in index_count, so poly_count below is - // for the per-polygon index count. + // primitive restart markers. The primitive restart markers are included + // in index_count. // so each polygon within the list: - // count includes the end of primitive marker // index count-1 indices // index // ... // "end of primitive" (~0u) - free (bctx->polys); - bctx->polys = malloc ((index_count + poly_count) * sizeof (uint32_t)); + free (bctx->faces); + free (bctx->poly_indices); + bctx->faces = malloc (face_base * sizeof (bsp_face_t)); + bctx->poly_indices = malloc (index_count * sizeof (uint32_t)); // All usable surfaces have been chained to the (base) texture they use. // Run through the textures, using their chains to build display lists. // For animated textures, if a surface is on one texture of the group, it // will effectively be on all (just one at a time). - int count = 0; - int vertex_index_base = 0; - bsppoly_t *poly = bctx->polys; - for (size_t i = 0; i < bctx->texture_chains.size; i++) { - vulktex_t *tex = bctx->texture_chains.a[i]; - - for (instsurf_t *is = tex->tex_chain; is; is = is->tex_chain) { - msurface_t *surf = is->surface; - - surf->polys = (glpoly_t *) poly; - poly = build_surf_displist (models, surf, vertex_index_base, - &vertices); - vertex_index_base += surf->numedges; - count++; + buildctx_t build = { + .faces = bctx->faces, + .indices = bctx->poly_indices, + .vertices = vertices, + .index_base = 0, + .vertex_base = 0, + }; + for (size_t i = 0; i < bctx->registered_textures.size; i++) { + build.tex_id = i; + for (size_t j = 0; j < face_sets[i].size; j++) { + faceref_t *faceref = &face_sets[i].a[j]; + build_surf_displist (faceref, &build); } } - clear_texture_chains (bctx); Sys_MaskPrintf (SYS_vulkan, - "R_BuildDisplayLists: verts:%u, inds:%u, " - "polys:%u (%d) %zd\n", - vertex_count, index_count, poly_count, count, - ((size_t) poly - (size_t) bctx->polys) / sizeof(uint32_t)); + "R_BuildDisplayLists: verts:%u, inds:%u, polys:%u\n", + vertex_count, index_count, poly_count); if (index_buffer_size > bctx->index_buffer_size) { if (bctx->index_buffer) { dfunc->vkUnmapMemory (device->dev, bctx->index_memory); @@ -571,6 +469,10 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) 0, 0, 0, 1, &bb.barrier, 0, 0); QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); + for (size_t i = 0; i < bctx->registered_textures.size; i++) { + DARRAY_CLEAR (&face_sets[i]); + } + } static void @@ -629,7 +531,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) // enqueue the polygon if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - chain_surface (surf, ctx); + //chain_surface (surf, ctx); } } } @@ -656,8 +558,9 @@ get_side (mnode_t *node) static inline void visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) { + bspctx_t *bctx = ctx->bsp_context; + bsp_pass_t *pass = &ctx->bsp_context->main_pass; int c; - msurface_t *surf; // sneaky hack for side = side ? SURF_PLANEBACK : 0; // seems to be microscopically faster even on modern hardware @@ -665,19 +568,19 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) // chain any visible surfaces on the node that face the camera. // not all nodes have any surfaces to draw (purely a split plane) if ((c = node->numsurfaces)) { - int surf_id = node->firstsurface; - surf = brush->surfaces + surf_id; - for (; c; c--, surf++, surf_id++) { - if (r_face_visframes[surf_id] != r_visframecount) + const bsp_face_t *face = bctx->faces + node->firstsurface; + const int *frame = pass->face_frames + node->firstsurface; + for (; c; c--, face++, frame++) { + if (*frame != r_visframecount) continue; // side is either 0 or SURF_PLANEBACK // if side and the surface facing differ, then the camera is // on backside of the surface - if (side ^ (surf->flags & SURF_PLANEBACK)) + if (side ^ (face->flags & SURF_PLANEBACK)) continue; // wrong side - chain_surface (surf, ctx); + chain_surface (face, pass, bctx); } } } @@ -799,32 +702,6 @@ push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout, QFV_PushConstants (device, cmd, layout, 3, push_constants); } -static void -draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_device_t *device, - VkCommandBuffer cmd) -{ - qfv_devfuncs_t *dfunc = device->funcs; - - if (ec->transform) { - push_transform (ec->transform, layout, device, cmd); - } else { - //FIXME should cache current transform - push_transform (identity, layout, device, cmd); - } - if (ec->index_count) { - dfunc->vkCmdDrawIndexed (cmd, ec->index_count, 1, ec->first_index, - 0, 0); - } -} - -static void -reset_elechain (elechain_t *ec) -{ - ec->first_index = 0; - ec->index_count = 0; -} - - static void bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, VkPipelineLayout layout, qfv_renderframe_t *rFrame) @@ -979,40 +856,32 @@ sky_end (vulkan_ctx_t *ctx) bsp_end_subpass (bframe->cmdSet.a[QFV_bspSky], ctx); } -static inline void -add_surf_elements (vulktex_t *tex, instsurf_t *is, elechain_t **ec, - bspctx_t *bctx, bspframe_t *bframe) +static void +clear_queues (bspctx_t *bctx, bsp_pass_t *pass) { - bsppoly_t *poly = (bsppoly_t *) is->surface->polys; - - if (!tex->elechain) { - (*ec) = add_elechain (tex, bctx); - (*ec)->transform = is->transform; - (*ec)->color = is->color; - (*ec)->first_index = bframe->index_count; + for (size_t i = 0; i < bctx->registered_textures.size; i++) { + DARRAY_RESIZE (&pass->face_queue[i], 0); } - if (is->transform != (*ec)->transform || is->color != (*ec)->color) { - (*ec) = add_elechain (tex, bctx); - (*ec)->transform = is->transform; - (*ec)->color = is->color; - (*ec)->first_index = bframe->index_count; + for (int j = 0; j < pass->num_queues; j++) { + DARRAY_RESIZE (&pass->draw_queues[j], 0); } - memcpy (bframe->index_data + bframe->index_count, - poly->indices, poly->count * sizeof (poly->indices[0])); - (*ec)->index_count += poly->count; - bframe->index_count += poly->count; + pass->index_count = 0; } static void -build_tex_elechain (vulktex_t *tex, bspctx_t *bctx, bspframe_t *bframe) +draw_queue (bsp_pass_t *pass, int queue, VkPipelineLayout layout, + qfv_device_t *device, VkCommandBuffer cmd) { - instsurf_t *is; - elechain_t *ec = 0; + qfv_devfuncs_t *dfunc = device->funcs; - for (is = tex->tex_chain; is; is = is->tex_chain) { - // emit the polygon indices for the surface to the texture's - // element chain - add_surf_elements (tex, is, &ec, bctx, bframe); + for (size_t i = 0; i < pass->draw_queues[queue].size; i++) { + __auto_type d = pass->draw_queues[queue].a[i]; + if (pass->textures) { + vulktex_t *tex = pass->textures->a[d.tex_id]; + bind_texture (tex, 1, layout, dfunc, cmd); + } + dfunc->vkCmdDrawIndexed (cmd, d.index_count, d.instance_count, + d.first_index, 0, d.first_instance); } } @@ -1021,13 +890,17 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; + //qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; entity_t worldent; mod_brush_t *brush; - clear_texture_chains (bctx); // do this first for water and skys + bctx->main_pass.face_frames = r_face_visframes; + bctx->main_pass.leaf_frames = r_leaf_visframes; + bctx->main_pass.node_frames = r_node_visframes; + + clear_queues (bctx, &bctx->main_pass); // do this first for water and skys bframe->index_count = 0; memset (&worldent, 0, sizeof (worldent)); @@ -1058,27 +931,42 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); - for (size_t i = 0; i < bctx->texture_chains.size; i++) { - vulktex_t *tex; - elechain_t *ec = 0; - - tex = bctx->texture_chains.a[i]; - - build_tex_elechain (tex, bctx, bframe); - - bind_texture (tex, 1, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspGBuffer]); - - for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, device, - bframe->cmdSet.a[QFV_bspDepth]); - draw_elechain (ec, bctx->layout, device, - bframe->cmdSet.a[QFV_bspGBuffer]); - reset_elechain (ec); + __auto_type pass = &bctx->main_pass; + pass->indices = bframe->index_data; + for (size_t i = 0; i < bctx->registered_textures.size; i++) { + __auto_type queue = &pass->face_queue[i]; + if (!queue->size) { + continue; } - tex->elechain = 0; - tex->elechain_tail = &tex->elechain; + //FIXME implement draw_queue selection correctly (per face) + int dq = 0; + if (bctx->faces[queue->a[0].face].flags & SURF_DRAWSKY) { + dq = 1; + } + if (bctx->faces[queue->a[0].face].flags & SURF_DRAWTURB) { + dq = 2; + } + bsp_draw_t draw = { + .tex_id = i, + .instance_count = 1, + .first_index = pass->index_count, + }; + for (size_t j = 0; j < queue->size; j++) { + __auto_type is = queue->a[j]; + __auto_type f = bctx->faces[is.face]; + memcpy (pass->indices + pass->index_count, + bctx->poly_indices + f.first_index, + f.index_count * sizeof (uint32_t)); + draw.index_count += f.index_count; + pass->index_count += f.index_count; + } + DARRAY_APPEND (&pass->draw_queues[dq], draw); } + VkPipelineLayout layout = bctx->layout; + pass->textures = 0; + draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspDepth]); + pass->textures = &bctx->registered_textures; + draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); bsp_end (ctx); } @@ -1112,14 +1000,11 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; + //qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - instsurf_t *is; - vulktex_t *tex = 0; - elechain_t *ec = 0; - if (!bctx->waterchain) + if (!bctx->main_pass.draw_queues[2].size) return; turb_begin (rFrame); @@ -1131,41 +1016,13 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) }; push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspTurb]); - for (is = bctx->waterchain; is; is = is->tex_chain) { - msurface_t *surf = is->surface; - if (tex != surf->texinfo->texture->render) { - if (tex) { - bind_texture (tex, 1, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspTurb]); - for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, device, - bframe->cmdSet.a[QFV_bspTurb]); - reset_elechain (ec); - } - tex->elechain = 0; - tex->elechain_tail = &tex->elechain; - } - tex = surf->texinfo->texture->render; - } - // emit the polygon indices for the surface to the texture's - // element chain - add_surf_elements (tex, is, &ec, bctx, bframe); - } - if (tex) { - bind_texture (tex, 1, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspTurb]); - for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, device, - bframe->cmdSet.a[QFV_bspTurb]); - reset_elechain (ec); - } - tex->elechain = 0; - tex->elechain_tail = &tex->elechain; - } - turb_end (ctx); - bctx->waterchain = 0; - bctx->waterchain_tail = &bctx->waterchain; + VkPipelineLayout layout = bctx->layout; + __auto_type pass = &bctx->main_pass; + pass->textures = &bctx->registered_textures; + draw_queue (pass, 2, layout, device, bframe->cmdSet.a[QFV_bspTurb]); + + turb_end (ctx); } void @@ -1176,11 +1033,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - instsurf_t *is; - vulktex_t *tex = 0; - elechain_t *ec = 0; - if (!bctx->sky_chain) + if (!bctx->main_pass.draw_queues[1].size) return; sky_begin (rFrame); @@ -1192,41 +1046,13 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspSky]); - for (is = bctx->sky_chain; is; is = is->tex_chain) { - msurface_t *surf = is->surface; - if (tex != surf->texinfo->texture->render) { - if (tex) { - bind_texture (tex, 1, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspSky]); - for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, device, - bframe->cmdSet.a[QFV_bspSky]); - reset_elechain (ec); - } - tex->elechain = 0; - tex->elechain_tail = &tex->elechain; - } - tex = surf->texinfo->texture->render; - } - // emit the polygon indices for the surface to the texture's - // element chain - add_surf_elements (tex, is, &ec, bctx, bframe); - } - if (tex) { - bind_texture (tex, 1, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspSky]); - for (ec = tex->elechain; ec; ec = ec->next) { - draw_elechain (ec, bctx->layout, device, - bframe->cmdSet.a[QFV_bspSky]); - reset_elechain (ec); - } - tex->elechain = 0; - tex->elechain_tail = &tex->elechain; - } - sky_end (ctx); - bctx->sky_chain = 0; - bctx->sky_chain_tail = &bctx->sky_chain; + VkPipelineLayout layout = bctx->layout; + __auto_type pass = &bctx->main_pass; + pass->textures = &bctx->registered_textures; + draw_queue (pass, 1, layout, device, bframe->cmdSet.a[QFV_bspSky]); + + sky_end (ctx); } static void @@ -1348,12 +1174,6 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bspctx_t *bctx = calloc (1, sizeof (bspctx_t)); ctx->bsp_context = bctx; - bctx->waterchain_tail = &bctx->waterchain; - bctx->sky_chain_tail = &bctx->sky_chain; - bctx->static_instsurfs_tail = &bctx->static_instsurfs; - bctx->elechains_tail = &bctx->elechains; - bctx->instsurfs_tail = &bctx->instsurfs; - bctx->light_scrap = QFV_CreateScrap (device, "lightmap_atlas", 2048, tex_frgba, ctx->staging); size_t size = QFV_ScrapSize (bctx->light_scrap); @@ -1362,7 +1182,14 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) create_default_skys (ctx); - DARRAY_INIT (&bctx->texture_chains, 64); + DARRAY_INIT (&bctx->registered_textures, 64); + + bctx->main_pass.num_queues = 3; + bctx->main_pass.draw_queues = malloc (bctx->main_pass.num_queues + * sizeof (bsp_drawset_t)); + for (int i = 0; i < bctx->main_pass.num_queues; i++) { + DARRAY_INIT (&bctx->main_pass.draw_queues[i], 64); + } size_t frames = ctx->frames.size; DARRAY_INIT (&bctx->frames, frames); @@ -1418,7 +1245,11 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) dfunc->vkDestroyPipeline (device->dev, bctx->skybox, 0); dfunc->vkDestroyPipeline (device->dev, bctx->skysheet, 0); dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0); - DARRAY_CLEAR (&bctx->texture_chains); + DARRAY_CLEAR (&bctx->registered_textures); + for (int i = 0; i < bctx->main_pass.num_queues; i++) { + DARRAY_CLEAR (&bctx->main_pass.draw_queues[i]); + } + free (bctx->main_pass.draw_queues); DARRAY_CLEAR (&bctx->frames); QFV_DestroyStagingBuffer (bctx->light_stage); QFV_DestroyScrap (bctx->light_scrap); From 26330d0fcb3d2b84497236a018cb292221504a1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 May 2022 01:32:33 +0900 Subject: [PATCH 2862/3664] [scene] Update the empty world for the new mnode_t This gets my qwaq-x11 test scene working again (and makes use of a plane at infinity, yay PGA). --- libs/scene/scene.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libs/scene/scene.c b/libs/scene/scene.c index bf30a92a3..09f2d16bb 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -57,8 +57,23 @@ static mleaf_t empty_leafs[] = { }, }; +static mnode_t empty_nodes[] = { + [0] = { + .plane = { 0, 0, 0, -1 }, + .type = 3, + .children = { ~0, ~1 }, + .minmaxs = {-INFINITY, -INFINITY, -INFINITY, + INFINITY, INFINITY, INFINITY}, + }, +}; + +static int empty_node_parents[] = { + [0] = -1, +}; + static int empty_leaf_parents[] = { - [1] = -1, + [0] = 0, + [1] = 0, }; static int empty_leaf_flags[] = { @@ -75,10 +90,12 @@ static model_t empty_world = { .brush = { .modleafs = 2, .visleafs = 1, - .nodes = (mnode_t *) &empty_leafs[1], + .numnodes = 1, + .nodes = empty_nodes, .leafs = empty_leafs, .entities = empty_entities, .visdata = empty_visdata, + .node_parents = empty_node_parents, .leaf_parents = empty_leaf_parents, .leaf_flags = empty_leaf_flags, }, From 3900e59f1a04f7becc6885112b592216b3a8f370 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 May 2022 20:22:05 +0900 Subject: [PATCH 2863/3664] [client] Support the wait field on lights This was the missing piece for a lot of my lighting woes: it scales the distance when calculating falloff. --- libs/client/cl_light.c | 43 +++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index 0bc3e8287..5e2bf39ca 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -143,6 +143,7 @@ parse_light (light_t *light, int *style, const plitem_t *entity, { const char *str; int model = 0; + float atten = 1; /*Sys_Printf ("{\n"); for (int i = PL_D_NumKeys (entity); i-- > 0; ) { @@ -201,26 +202,54 @@ parse_light (light_t *light, int *style, const plitem_t *entity, VectorScale (light->color, 1/255.0, light->color); } - vec4f_t attenuation = { 1, 0, 0, 0 }; // inverse square + if ((str = PL_String (PL_ObjectForKey (entity, "wait")))) { + atten = atof (str); + if (atten <= 0) { + atten = 1; + } + } + + vec4f_t attenuation = { // inverse square + 1, 0, 0, + 0, + }; switch (model) { case LM_LINEAR: - attenuation = (vec4f_t) { 0, 0, 1, 1 / fabsf (light->color[3]) }; + attenuation = (vec4f_t) { + 0, 0, 1, + atten / fabsf (light->color[3]), + }; break; case LM_INVERSE: - attenuation = (vec4f_t) { 0, 1.0 / 128, 0, 0 }; + attenuation = (vec4f_t) { + 0, atten / 128, 0, + 0, + }; break; case LM_INVERSE2: - attenuation = (vec4f_t) { 1.0 / 16384, 0, 0, 0 }; + attenuation = (vec4f_t) { + atten * atten / 16384, 0, 0, + 0, + }; break; case LM_INFINITE: - attenuation = (vec4f_t) { 0, 0, 1, 0 }; + attenuation = (vec4f_t) { + 0, 0, 1, + 0, + }; break; case LM_AMBIENT: - attenuation = (vec4f_t) { 0, 0, 1, 0 }; + attenuation = (vec4f_t) { + 0, 0, 1, + 0, + }; light->direction = (vec4f_t) { 0, 0, 0, 1 }; break; case LM_INVERSE3: - attenuation = (vec4f_t) { 1.0 / 16384, 2.0 / 128, 1, 0 }; + attenuation = (vec4f_t) { + atten * atten / 16384, 2 * atten / 128, 1, + 0, + }; break; } light->attenuation = attenuation; From a08261c620e8dc32fbbca40d0e34fe349f861d97 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 May 2022 00:17:57 +0900 Subject: [PATCH 2864/3664] [vulkan] Use a buffer for entity transform and color data This allows the use of an entity id to index into the entity data and fetch the transform and colormod data in the vertex shader, thus making instanced rendering possible. Non-world brush entities are still not rendered, but the world entity is using both the entity data buffer and entid buffer. --- include/QF/Makemodule.am | 1 + include/QF/Vulkan/qf_bsp.h | 16 +- include/QF/Vulkan/qf_scene.h | 80 ++++++ include/QF/scene/entity.h | 1 + include/vid_vulkan.h | 1 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vid_render_vulkan.c | 3 + libs/video/renderer/vulkan/qfpipeline.plist | 33 ++- .../renderer/vulkan/shader/bsp_depth.vert | 11 +- .../renderer/vulkan/shader/bsp_gbuf.frag | 3 +- .../renderer/vulkan/shader/bsp_gbuf.vert | 11 +- .../renderer/vulkan/shader/bsp_shadow.vert | 11 +- .../video/renderer/vulkan/shader/bsp_sky.frag | 5 +- .../renderer/vulkan/shader/bsp_turb.frag | 3 +- libs/video/renderer/vulkan/shader/entity.h | 4 + .../renderer/vulkan/shader/quakebsp.frag | 1 - .../renderer/vulkan/shader/quakebsp.vert | 11 +- libs/video/renderer/vulkan/vulkan_bsp.c | 238 ++++++++++-------- libs/video/renderer/vulkan/vulkan_scene.c | 205 +++++++++++++++ 19 files changed, 502 insertions(+), 137 deletions(-) create mode 100644 include/QF/Vulkan/qf_scene.h create mode 100644 libs/video/renderer/vulkan/shader/entity.h create mode 100644 libs/video/renderer/vulkan/vulkan_scene.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 64a9c3cc0..875262cf6 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -197,6 +197,7 @@ include_qf_vulkan = \ include/QF/Vulkan/qf_matrices.h \ include/QF/Vulkan/qf_model.h \ include/QF/Vulkan/qf_particles.h \ + include/QF/Vulkan/qf_scene.h \ include/QF/Vulkan/qf_sprite.h \ include/QF/Vulkan/qf_texture.h \ include/QF/Vulkan/qf_vid.h \ diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index d5b3137de..c55d1aec9 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -99,6 +99,8 @@ typedef struct bsp_instfaceset_s typedef struct bsp_pass_s { uint32_t *indices; // points into index buffer uint32_t index_count; // number of indices written to buffer + uint32_t *entid_data; + uint32_t entid_count; int vis_frame; int *face_frames; int *leaf_frames; @@ -132,9 +134,12 @@ typedef enum { } QFV_BspSubpass; typedef struct bspframe_s { - uint32_t *index_data; // pointer into mega-buffer for this frame (c) - uint32_t index_offset; // offset of index_data within mega-buffer (c) - uint32_t index_count; // number if indices queued (d) + uint32_t *index_data; // pointer into mega-buffer for this frame (c) + uint32_t index_offset; // offset of index_data within mega-buffer (c) + uint32_t index_count; // number if indices queued (d) + uint32_t *entid_data; + uint32_t entid_offset; + uint32_t entid_count; qfv_cmdbufferset_t cmdSet; } bspframe_t; @@ -142,9 +147,6 @@ typedef struct bspframeset_s DARRAY_TYPE (bspframe_t) bspframeset_t; typedef struct bspctx_s { - struct entity_s *entity; - vec_t *transform; - float *color; uint32_t inst_id; regtexset_t registered_textures; @@ -182,6 +184,8 @@ typedef struct bspctx_s { VkDeviceMemory vertex_memory; VkBuffer index_buffer; VkDeviceMemory index_memory; + VkBuffer entid_buffer; + VkDeviceMemory entid_memory; bspframeset_t frames; } bspctx_t; diff --git a/include/QF/Vulkan/qf_scene.h b/include/QF/Vulkan/qf_scene.h new file mode 100644 index 000000000..654c6fa58 --- /dev/null +++ b/include/QF/Vulkan/qf_scene.h @@ -0,0 +1,80 @@ +/* + qf_scene.h + + Vulkan specific scene stuff + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/5/24 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_scene_h +#define __QF_Vulkan_qf_scene_h + +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + +#include "QF/darray.h" +#include "QF/simd/types.h" + +typedef struct entdata_s { + // transpose of entity transform matrix without row 4 + vec4f_t xform[3]; + vec4f_t color; +} entdata_t; + +typedef struct entdataset_s + DARRAY_TYPE (entdata_t) entdataset_t; + +typedef struct scnframe_s { + // used to check if the entity has been pooled this frame (cleared + // every frame) + struct set_s *pooled_entities; + // data for entities pooled this frame (cleared every frame). transfered + // to gpu + entdataset_t entity_pool; + VkDescriptorSet descriptors; +} scnframe_t; + +typedef struct scnframeset_s + DARRAY_TYPE (scnframe_t) scnframeset_t; + +typedef struct scenectx_s { + struct qfv_resource_s *entities; + scnframeset_t frames; + VkDescriptorPool pool; + VkDescriptorSetLayout setLayout; + int max_entities; +} scenectx_t; + +struct vulkan_ctx_s; +struct entity_s; + +void Vulkan_Scene_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Scene_Shutdown (struct vulkan_ctx_s *ctx); +int Vulkan_Scene_MaxEntities (struct vulkan_ctx_s *ctx) __attribute__((pure)); +VkDescriptorSet Vulkan_Scene_Descriptors (struct vulkan_ctx_s *ctx) __attribute__((pure)); +int Vulkan_Scene_AddEntity (struct vulkan_ctx_s *ctx, struct entity_s *entity); + +#endif//__QF_Vulkan_qf_scene_h diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index 6aadfab65..770033f64 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -73,6 +73,7 @@ typedef struct renderer_s { int skinnum; // for Alias models int fullbright; float min_light; + int render_id; mat4_t full_transform; } renderer_t; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index c3610bb0b..749047e24 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -68,6 +68,7 @@ typedef struct vulkan_ctx_s { struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; struct iqmctx_s *iqm_context; + struct scenectx_s *scene_context; struct particlectx_s *particle_context; struct spritectx_s *sprite_context; struct drawctx_s *draw_context; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index d164eb5f3..6a52b1af4 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -227,6 +227,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ libs/video/renderer/vulkan/vulkan_particles.c \ + libs/video/renderer/vulkan/vulkan_scene.c \ libs/video/renderer/vulkan/vulkan_sprite.c \ libs/video/renderer/vulkan/vulkan_texture.c \ libs/video/renderer/vulkan/vulkan_vid_common.c diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a727cbf26..6e66fdc54 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -50,6 +50,7 @@ #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_particles.h" +#include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_sprite.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_vid.h" @@ -92,6 +93,7 @@ vulkan_R_Init (void) Vulkan_Texture_Init (vulkan_ctx); Vulkan_Matrix_Init (vulkan_ctx); + Vulkan_Scene_Init (vulkan_ctx); Vulkan_Alias_Init (vulkan_ctx); Vulkan_Bsp_Init (vulkan_ctx); Vulkan_IQM_Init (vulkan_ctx); @@ -705,6 +707,7 @@ vulkan_vid_render_shutdown (void) Vulkan_IQM_Shutdown (vulkan_ctx); Vulkan_Bsp_Shutdown (vulkan_ctx); Vulkan_Alias_Shutdown (vulkan_ctx); + Vulkan_Scene_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx); Vulkan_Texture_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 24ccdf848..9c16a5556 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -97,6 +97,16 @@ }, ); }; + entity_pool = { + flags = free_descriptor_set; + maxSets = 512; + bindings = ( + { + type = storage_buffer; + descriptorCount = $properties.descriptorPools.entity_pool.maxSets; + }, + ); + }; bone_pool = { flags = free_descriptor_set; maxSets = 512; @@ -216,6 +226,16 @@ }, ); }; + entity_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; bone_set = { bindings = ( { @@ -340,16 +360,11 @@ setLayouts = (matrix_set, twod_set); }; quakebsp_layout = { - setLayouts = (matrix_set, texture_set, texture_set); + setLayouts = (matrix_set, entity_set, texture_set, texture_set); pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4"; - }, { stageFlags = fragment; - offset = 64; + offset = 0; size = "4 * 4 + 4 + 4"; }, ); @@ -499,10 +514,12 @@ brush = { bindings = ( { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 1; stride = "4"; inputRate = instance; }, ); attributes = ( { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 1; format = r32_uint; offset = 0; }, ); }; iqm = { @@ -786,9 +803,11 @@ vertexInput = { bindings = ( "$properties.vertexInput.brush.bindings[0]", + "$properties.vertexInput.brush.bindings[1]", ); attributes = ( "$properties.vertexInput.brush.attributes[0]", + "$properties.vertexInput.brush.attributes[2]", ); }; inputAssembly = $properties.inputAssembly.brush; diff --git a/libs/video/renderer/vulkan/shader/bsp_depth.vert b/libs/video/renderer/vulkan/shader/bsp_depth.vert index 8ee96735f..14f5e802e 100644 --- a/libs/video/renderer/vulkan/shader/bsp_depth.vert +++ b/libs/video/renderer/vulkan/shader/bsp_depth.vert @@ -1,4 +1,7 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "entity.h" layout (set = 0, binding = 0) uniform Matrices { mat4 Projection3d; @@ -7,14 +10,16 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 Projection2d; }; -layout (push_constant) uniform PushConstants { - mat4 Model; +layout (set = 1, binding = 0) buffer Entities { + Entity entities[]; }; layout (location = 0) in vec4 vertex; +layout (location = 2) in uint entid; void main (void) { - gl_Position = Projection3d * (View * (Model * vertex)); + vec3 vert = vertex * entities[entid].transform; + gl_Position = Projection3d * (View * vec4 (vert, 1)); } diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index b09d7232b..f807f52a2 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -1,9 +1,8 @@ #version 450 -layout (set = 1, binding = 0) uniform sampler2DArray Texture; +layout (set = 2, binding = 0) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { - layout (offset = 64) vec4 fog; float time; float alpha; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert index 7b80384c5..b5866d8b6 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert @@ -1,4 +1,7 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "entity.h" layout (set = 0, binding = 0) uniform Matrices { mat4 Projection3d; @@ -7,12 +10,13 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 Projection2d; }; -layout (push_constant) uniform PushConstants { - mat4 Model; +layout (set = 1, binding = 0) buffer Entities { + Entity entities[]; }; layout (location = 0) in vec4 vertex; layout (location = 1) in vec4 tl_uv; +layout (location = 2) in uint entid; layout (location = 0) out vec4 tl_st; layout (location = 1) out vec3 direction; @@ -21,7 +25,8 @@ void main (void) { // geometry shader will take care of Projection and View - gl_Position = Model * vertex; + vec3 vert = vertex * entities[entid].transform; + gl_Position = vec4 (vert, 1); direction = (Sky * vertex).xyz; tl_st = tl_uv; } diff --git a/libs/video/renderer/vulkan/shader/bsp_shadow.vert b/libs/video/renderer/vulkan/shader/bsp_shadow.vert index f80dfd673..ea1dfb8d6 100644 --- a/libs/video/renderer/vulkan/shader/bsp_shadow.vert +++ b/libs/video/renderer/vulkan/shader/bsp_shadow.vert @@ -1,16 +1,21 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (push_constant) uniform PushConstants { - mat4 Model; +#include "entity.h" + +layout (set = 1, binding = 0) buffer Entities { + Entity entities[]; }; layout (location = 0) in vec4 vertex; +layout (location = 2) in uint entid; layout (location = 0) out int InstanceIndex; void main (void) { - gl_Position = Model * vertex; + vec3 vert = vertex * entities[entid].transform; + gl_Position = vec4 (vert, 1);; InstanceIndex = gl_InstanceIndex; } diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index 1734b5b12..897310930 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -3,11 +3,10 @@ layout (constant_id = 0) const bool doSkyBox = false; layout (constant_id = 1) const bool doSkySheet = false; -layout (set = 1, binding = 0) uniform sampler2DArray SkySheet; -layout (set = 2, binding = 0) uniform samplerCube SkyBox; +layout (set = 2, binding = 0) uniform sampler2DArray SkySheet; +layout (set = 3, binding = 0) uniform samplerCube SkyBox; layout (push_constant) uniform PushConstants { - layout (offset = 64) vec4 fog; float time; float alpha; diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index 1c78dde73..fdc7dfc10 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -1,9 +1,8 @@ #version 450 -layout (set = 1, binding = 0) uniform sampler2DArray Texture; +layout (set = 2, binding = 0) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { - layout (offset = 64) vec4 fog; float time; float alpha; diff --git a/libs/video/renderer/vulkan/shader/entity.h b/libs/video/renderer/vulkan/shader/entity.h new file mode 100644 index 000000000..0da5a9d27 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/entity.h @@ -0,0 +1,4 @@ +struct Entity { + mat3x4 transform; + vec4 color; +}; diff --git a/libs/video/renderer/vulkan/shader/quakebsp.frag b/libs/video/renderer/vulkan/shader/quakebsp.frag index 21a93d530..750395c83 100644 --- a/libs/video/renderer/vulkan/shader/quakebsp.frag +++ b/libs/video/renderer/vulkan/shader/quakebsp.frag @@ -7,7 +7,6 @@ layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; layout (set = 0, binding = 5) uniform samplerCube SkyCube; layout (push_constant) uniform PushConstants { - layout (offset = 64) vec4 fog; float time; float alpha; diff --git a/libs/video/renderer/vulkan/shader/quakebsp.vert b/libs/video/renderer/vulkan/shader/quakebsp.vert index 397bd2595..7d1c4024e 100644 --- a/libs/video/renderer/vulkan/shader/quakebsp.vert +++ b/libs/video/renderer/vulkan/shader/quakebsp.vert @@ -1,4 +1,7 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable + +#include "entity.h" layout (set = 0, binding = 0) uniform Matrices { mat4 Projection3d; @@ -7,12 +10,13 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 Projection2d; }; -layout (push_constant) uniform PushConstants { - mat4 Model; +layout (set = 1, binding = 0) buffer Entities { + Entity entities[]; }; layout (location = 0) in vec4 vertex; layout (location = 1) in vec4 tl_uv; +layout (location = 2) in uint entid; layout (location = 0) out vec4 tl_st; layout (location = 1) out vec3 direction; @@ -20,7 +24,8 @@ layout (location = 1) out vec3 direction; void main (void) { - gl_Position = Projection3d * (View * (Model * vertex)); + vec3 vert = vertex * entities[entid].transform; + gl_Position = Projection3d * (View * vec4 (vert, 1)); direction = (Sky * vertex).xyz; tl_st = tl_uv; } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a4e9a340d..cb33837e6 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -55,6 +55,7 @@ #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/barrier.h" @@ -74,7 +75,6 @@ #include "vid_vulkan.h" typedef struct bsp_push_constants_s { - mat4f_t Model; quat_t fog; float time; float alpha; @@ -94,13 +94,6 @@ static QFV_Subpass subpass_map[] = { QFV_passTranslucent, // QFV_bspTurb }; -static float identity[] = { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, -}; - static vulktex_t vulkan_notexture = { }; #define ALLOC_CHUNK 64 @@ -486,11 +479,7 @@ R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) vec3_t mins, maxs; vec4f_t org; mod_brush_t *brush; - bspctx_t *bctx = ctx->bsp_context; - - bctx->entity = e; - bctx->transform = e->renderer.full_transform; - bctx->color = e->renderer.colormod; + //bspctx_t *bctx = ctx->bsp_context; model = e->renderer.model; brush = &model->brush; @@ -660,18 +649,6 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) } } -static void -push_transform (vec_t *transform, VkPipelineLayout layout, - qfv_device_t *device, VkCommandBuffer cmd) -{ - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_VERTEX_BIT, - field_offset (bsp_push_constants_t, Model), - sizeof (mat4f_t), transform }, - }; - QFV_PushConstants (device, cmd, layout, 1, push_constants); -} - static void bind_texture (vulktex_t *tex, uint32_t setnum, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) @@ -737,16 +714,18 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - VkDeviceSize offsets[] = { 0 }; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &bctx->vertex_buffer, offsets); + VkBuffer buffers[] = { bctx->vertex_buffer, bctx->entid_buffer }; + VkDeviceSize offsets[] = { 0, bframe->entid_offset }; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 2, buffers, offsets); dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, VK_INDEX_TYPE_UINT32); VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + Vulkan_Scene_Descriptors (ctx), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 1, sets, 0, 0); + layout, 0, 2, sets, 0, 0); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -869,70 +848,9 @@ clear_queues (bspctx_t *bctx, bsp_pass_t *pass) } static void -draw_queue (bsp_pass_t *pass, int queue, VkPipelineLayout layout, - qfv_device_t *device, VkCommandBuffer cmd) +queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe) { - qfv_devfuncs_t *dfunc = device->funcs; - - for (size_t i = 0; i < pass->draw_queues[queue].size; i++) { - __auto_type d = pass->draw_queues[queue].a[i]; - if (pass->textures) { - vulktex_t *tex = pass->textures->a[d.tex_id]; - bind_texture (tex, 1, layout, dfunc, cmd); - } - dfunc->vkCmdDrawIndexed (cmd, d.index_count, d.instance_count, - d.first_index, 0, d.first_instance); - } -} - -void -Vulkan_DrawWorld (qfv_renderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - //qfv_devfuncs_t *dfunc = device->funcs; - bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - entity_t worldent; - mod_brush_t *brush; - - bctx->main_pass.face_frames = r_face_visframes; - bctx->main_pass.leaf_frames = r_leaf_visframes; - bctx->main_pass.node_frames = r_node_visframes; - - clear_queues (bctx, &bctx->main_pass); // do this first for water and skys - bframe->index_count = 0; - - memset (&worldent, 0, sizeof (worldent)); - worldent.renderer.model = r_refdef.worldmodel; - brush = &r_refdef.worldmodel->brush; - - bctx->entity = &worldent; - bctx->transform = 0; - bctx->color = 0; - - R_VisitWorldNodes (brush, ctx); - if (!bctx->vertex_buffer) { - return; - } - if (r_drawentities) { - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { - entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; - R_DrawBrushModel (ent, ctx); - } - } - - bsp_begin (rFrame); - - push_transform (identity, bctx->layout, device, - bframe->cmdSet.a[QFV_bspDepth]); - push_transform (identity, bctx->layout, device, - bframe->cmdSet.a[QFV_bspGBuffer]); - bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; - push_fragconst (&frag_constants, bctx->layout, device, - bframe->cmdSet.a[QFV_bspGBuffer]); - __auto_type pass = &bctx->main_pass; - pass->indices = bframe->index_data; + pass->indices = bframe->index_data + bframe->index_count; for (size_t i = 0; i < bctx->registered_textures.size; i++) { __auto_type queue = &pass->face_queue[i]; if (!queue->size) { @@ -962,7 +880,88 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) } DARRAY_APPEND (&pass->draw_queues[dq], draw); } + bframe->index_count += pass->index_count; +} + +static void +draw_queue (bsp_pass_t *pass, int queue, VkPipelineLayout layout, + qfv_device_t *device, VkCommandBuffer cmd) +{ + qfv_devfuncs_t *dfunc = device->funcs; + + for (size_t i = 0; i < pass->draw_queues[queue].size; i++) { + __auto_type d = pass->draw_queues[queue].a[i]; + if (pass->textures) { + vulktex_t *tex = pass->textures->a[d.tex_id]; + bind_texture (tex, 2, layout, dfunc, cmd); + } + dfunc->vkCmdDrawIndexed (cmd, d.index_count, d.instance_count, + d.first_index, 0, d.first_instance); + } +} + +static int +add_entity (vulkan_ctx_t *ctx, bsp_pass_t *pass, entity_t *entity) +{ + int entid = Vulkan_Scene_AddEntity (ctx, entity); + if (entid >= 0) { + pass->entid_data[pass->entid_count++] = entid; + } + return entid >= 0; +} + +void +Vulkan_DrawWorld (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + //qfv_devfuncs_t *dfunc = device->funcs; + bspctx_t *bctx = ctx->bsp_context; + bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; + mod_brush_t *brush; + + bctx->main_pass.face_frames = r_face_visframes; + bctx->main_pass.leaf_frames = r_leaf_visframes; + bctx->main_pass.node_frames = r_node_visframes; + bctx->main_pass.entid_data = bframe->entid_data; + bctx->main_pass.entid_count = 0; + + clear_queues (bctx, &bctx->main_pass); // do this first for water and skys + bframe->index_count = 0; + + entity_t worldent = { + .renderer = { + .model = r_refdef.worldmodel, + .colormod = { 1, 1, 1, 1 }, + }, + }; + brush = &r_refdef.worldmodel->brush; + + add_entity (ctx, &bctx->main_pass, &worldent); + + R_VisitWorldNodes (brush, ctx); + if (!bctx->vertex_buffer) { + return; + } + if (r_drawentities) { + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { + entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; + if (add_entity (ctx, &bctx->main_pass, ent)) { + R_DrawBrushModel (ent, ctx); + } + } + } + + queue_faces (&bctx->main_pass, bctx, bframe); + + bsp_begin (rFrame); + + bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; + push_fragconst (&frag_constants, bctx->layout, device, + bframe->cmdSet.a[QFV_bspGBuffer]); VkPipelineLayout layout = bctx->layout; + + __auto_type pass = &bctx->main_pass; pass->textures = 0; draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspDepth]); pass->textures = &bctx->registered_textures; @@ -979,20 +978,28 @@ Vulkan_Bsp_Flush (vulkan_ctx_t *ctx) bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; size_t atom_mask = atom - 1; - size_t offset = bframe->index_offset; - size_t size = bframe->index_count * sizeof (uint32_t); + size_t index_offset = bframe->index_offset; + size_t index_size = bframe->index_count * sizeof (uint32_t); + size_t entid_offset = bframe->entid_offset; + size_t entid_size = bframe->entid_count * sizeof (uint32_t); if (!bframe->index_count) { return; } - offset &= ~atom_mask; - size = (size + atom_mask) & ~atom_mask; + index_offset &= ~atom_mask; + index_size = (index_size + atom_mask) & ~atom_mask; + entid_offset &= ~atom_mask; + entid_size = (entid_size + atom_mask) & ~atom_mask; - VkMappedMemoryRange range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - bctx->index_memory, offset, size + VkMappedMemoryRange ranges[] = { + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + bctx->index_memory, index_offset, index_size + }, + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + bctx->entid_memory, entid_offset, entid_size + }, }; - dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); + dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); } void @@ -1008,8 +1015,6 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) return; turb_begin (rFrame); - push_transform (identity, bctx->layout, device, - bframe->cmdSet.a[QFV_bspTurb]); bsp_push_constants_t frag_constants = { .time = vr_data.realtime, .alpha = r_wateralpha @@ -1039,10 +1044,8 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) sky_begin (rFrame); vulktex_t skybox = { .descriptor = bctx->skybox_descriptor }; - bind_texture (&skybox, 2, bctx->layout, dfunc, + bind_texture (&skybox, 3, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); - push_transform (identity, bctx->layout, device, - bframe->cmdSet.a[QFV_bspSky]); bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, device, bframe->cmdSet.a[QFV_bspSky]); @@ -1166,6 +1169,7 @@ void Vulkan_Bsp_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; r_notexture_mip->render = &vulkan_notexture; @@ -1204,6 +1208,28 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); + size_t entid_size = Vulkan_Scene_MaxEntities (ctx) * sizeof (uint32_t); + size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + size_t atom_mask = atom - 1; + entid_size = (entid_size + atom_mask) & ~atom_mask; + bctx->entid_buffer + = QFV_CreateBuffer (device, frames * entid_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, bctx->entid_buffer, + "buffer:bsp:entid"); + bctx->entid_memory + = QFV_AllocBufferMemory (device, bctx->entid_buffer, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + frames * entid_size, 0); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + bctx->entid_memory, "memory:bsp:entid"); + QFV_BindBufferMemory (device, + bctx->entid_buffer, bctx->entid_memory, 0); + uint32_t *entid_data; + dfunc->vkMapMemory (device->dev, bctx->entid_memory, 0, + frames * entid_size, 0, (void **) &entid_data); + for (size_t i = 0; i < frames; i++) { __auto_type bframe = &bctx->frames.a[i]; @@ -1219,6 +1245,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) va (ctx->va_ctx, "cmd:bsp:%zd:%s", i, bsp_pass_names[j])); } + bframe->entid_data = entid_data + i * entid_size; + bframe->entid_offset = i * entid_size; } bctx->skybox_descriptor @@ -1261,6 +1289,8 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) dfunc->vkDestroyBuffer (device->dev, bctx->index_buffer, 0); dfunc->vkFreeMemory (device->dev, bctx->index_memory, 0); } + dfunc->vkDestroyBuffer (device->dev, bctx->entid_buffer, 0); + dfunc->vkFreeMemory (device->dev, bctx->entid_memory, 0); if (bctx->skybox_tex) { Vulkan_UnloadTex (ctx, bctx->skybox_tex); diff --git a/libs/video/renderer/vulkan/vulkan_scene.c b/libs/video/renderer/vulkan/vulkan_scene.c new file mode 100644 index 000000000..6a8c568ef --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_scene.c @@ -0,0 +1,205 @@ +/* + vulkan_scene.c + + Vulkan scene handling + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/5/24 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/mathlib.h" +#include "QF/set.h" +#include "QF/va.h" + +#include "QF/scene/entity.h" + +#include "QF/Vulkan/qf_scene.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/resource.h" + +#include "vid_vulkan.h" + +static const int qfv_max_entities = 4096; //FIXME should make dynamic + +int +Vulkan_Scene_MaxEntities (vulkan_ctx_t *ctx) +{ + scenectx_t *sctx = ctx->scene_context; + return sctx->max_entities; +} + +VkDescriptorSet +Vulkan_Scene_Descriptors (vulkan_ctx_t *ctx) +{ + scenectx_t *sctx = ctx->scene_context; + scnframe_t *sframe = &sctx->frames.a[ctx->curFrame]; + return sframe->descriptors; +} + +int +Vulkan_Scene_AddEntity (vulkan_ctx_t *ctx, entity_t *entity) +{ + scenectx_t *sctx = ctx->scene_context; + scnframe_t *sframe = &sctx->frames.a[ctx->curFrame]; + + entdata_t *entdata = 0; + //lock + int id = -entity->id; + if (!set_is_member (sframe->pooled_entities, id)) { + if (sframe->entity_pool.size < sframe->entity_pool.maxSize) { + set_add (sframe->pooled_entities, id); + entity->renderer.render_id = sframe->entity_pool.size++; + entdata = sframe->entity_pool.a + entity->renderer.render_id; + } else { + entity->renderer.render_id = -1; + } + } + //unlock + if (entdata) { + mat4f_t f; + if (entity->transform) { //FIXME give world entity an entity :P + mat4ftranspose (f, Transform_GetWorldMatrixPtr (entity->transform)); + entdata->xform[0] = f[0]; + entdata->xform[1] = f[1]; + entdata->xform[2] = f[2]; + } else { + entdata->xform[0] = (vec4f_t) { 1, 0, 0, 0 }; + entdata->xform[1] = (vec4f_t) { 0, 1, 0, 0 }; + entdata->xform[2] = (vec4f_t) { 0, 0, 1, 0 }; + } + entdata->color = (vec4f_t) { QuatExpand (entity->renderer.colormod) }; + } + return entity->renderer.render_id; +} + +static VkWriteDescriptorSet base_buffer_write = { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, + 0, 0, 1, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + 0, 0, 0 +}; + +void +Vulkan_Scene_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + qfvPushDebug (ctx, "scene init"); + + scenectx_t *sctx = calloc (1, sizeof (scenectx_t) + + sizeof (qfv_resource_t) + + sizeof (qfv_resobj_t)); + ctx->scene_context = sctx; + sctx->max_entities = qfv_max_entities; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&sctx->frames, frames); + DARRAY_RESIZE (&sctx->frames, frames); + sctx->frames.grow = 0; + + sctx->entities = (qfv_resource_t *) &sctx[1]; + *sctx->entities = (qfv_resource_t) { + .name = "scene", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + .num_objects = 1, + .objects = (qfv_resobj_t *) &sctx->entities[1], + }; + sctx->entities->objects[0] = (qfv_resobj_t) { + .name = "entities", + .type = qfv_res_buffer, + .buffer = { + .size = frames * qfv_max_entities * sizeof (entdata_t), + .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + }, + }; + + QFV_CreateResource (device, sctx->entities); + + sctx->pool = Vulkan_CreateDescriptorPool (ctx, "entity_pool"); + sctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "entity_set"); + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = sctx->setLayout; + } + __auto_type sets = QFV_AllocateDescriptorSet (device, sctx->pool, layouts); + + entdata_t *entdata; + dfunc->vkMapMemory (device->dev, sctx->entities->memory, 0, VK_WHOLE_SIZE, + 0, (void **) &entdata); + + VkBuffer buffer = sctx->entities->objects[0].buffer.buffer; + size_t entdata_size = qfv_max_entities * sizeof (entdata_t); + for (size_t i = 0; i < frames; i++) { + __auto_type sframe = &sctx->frames.a[i]; + + sframe->descriptors = sets->a[i]; + VkDescriptorBufferInfo bufferInfo = { + buffer, i * entdata_size, entdata_size + }; + VkWriteDescriptorSet write[1]; + write[0] = base_buffer_write; + write[0].dstSet = sframe->descriptors; + write[0].pBufferInfo = &bufferInfo; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + + sframe->entity_pool = (entdataset_t) { + .maxSize = qfv_max_entities, + .a = entdata + i * qfv_max_entities, + }; + sframe->pooled_entities = set_new (); + } + free (sets); + qfvPopDebug (ctx); +} + +void +Vulkan_Scene_Shutdown (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "scene shutdown"); + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + scenectx_t *sctx = ctx->scene_context; + + for (size_t i = 0; i < sctx->frames.size; i++) { + __auto_type sframe = &sctx->frames.a[i]; + set_delete (sframe->pooled_entities); + } + + dfunc->vkUnmapMemory (device->dev, sctx->entities->memory); + QFV_DestroyResource (device, sctx->entities); + + free (sctx->frames.a); + free (sctx); + qfvPopDebug (ctx); +} From 524c1e27c408030a7150f9ba1c1adbb23884988d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 May 2022 13:29:11 +0900 Subject: [PATCH 2865/3664] [vulkan] Use instanced rendering for brush models The models are broken up into N sub-(sub-)models, one for each texture, but all faces using the same texture are drawn as an instance, making for both reduced draw calls and reduced index buffer use (and thus, hopefully, reduced bandwidth). While texture animations are broken, this does mark a significant milestone towards implementing shadows as it should now be possible to use multiple threads (with multiple index and entid buffers) to render the depth buffers for all the lights. --- include/QF/Vulkan/qf_bsp.h | 21 ++- include/QF/Vulkan/qf_scene.h | 1 + include/QF/model.h | 2 + libs/video/renderer/vulkan/vulkan_bsp.c | 191 ++++++++++++++-------- libs/video/renderer/vulkan/vulkan_main.c | 2 + libs/video/renderer/vulkan/vulkan_scene.c | 10 ++ 6 files changed, 157 insertions(+), 70 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index c55d1aec9..fac47e1cf 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -46,6 +46,11 @@ typedef struct bsp_face_s { uint32_t flags; } bsp_face_t; +typedef struct bsp_model_s { + uint32_t first_face; + uint32_t face_count; +} bsp_model_t; + typedef struct bsp_packet_s { int first_index; int index_count; @@ -79,6 +84,7 @@ typedef struct bsp_texset_s typedef struct bsp_draw_s { uint32_t tex_id; + uint32_t inst_id; uint32_t index_count; uint32_t instance_count; uint32_t first_index; @@ -96,6 +102,14 @@ typedef struct instface_s { typedef struct bsp_instfaceset_s DARRAY_TYPE (instface_t) bsp_instfaceset_t; +typedef struct bsp_modelentset_s + DARRAY_TYPE (uint32_t) bsp_modelentset_t; + +typedef struct bsp_instance_s { + int first_instance; + bsp_modelentset_t entities; +} bsp_instance_t; + typedef struct bsp_pass_s { uint32_t *indices; // points into index buffer uint32_t index_count; // number of indices written to buffer @@ -109,6 +123,8 @@ typedef struct bsp_pass_s { regtexset_t *textures; int num_queues; bsp_drawset_t *draw_queues; + uint32_t inst_id; + bsp_instance_t *instances; } bsp_pass_t; typedef struct bspvert_s { @@ -147,8 +163,6 @@ typedef struct bspframeset_s DARRAY_TYPE (bspframe_t) bspframeset_t; typedef struct bspctx_s { - uint32_t inst_id; - regtexset_t registered_textures; struct qfv_tex_s *default_skysheet; @@ -164,9 +178,12 @@ typedef struct bspctx_s { struct scrap_s *light_scrap; struct qfv_stagebuf_s *light_stage; + bsp_model_t *models; bsp_face_t *faces; uint32_t *poly_indices; + int model_id; + bsp_pass_t main_pass; // camera view depth, gbuffer, etc VkSampler sampler; diff --git a/include/QF/Vulkan/qf_scene.h b/include/QF/Vulkan/qf_scene.h index 654c6fa58..3d7673dde 100644 --- a/include/QF/Vulkan/qf_scene.h +++ b/include/QF/Vulkan/qf_scene.h @@ -76,5 +76,6 @@ void Vulkan_Scene_Shutdown (struct vulkan_ctx_s *ctx); int Vulkan_Scene_MaxEntities (struct vulkan_ctx_s *ctx) __attribute__((pure)); VkDescriptorSet Vulkan_Scene_Descriptors (struct vulkan_ctx_s *ctx) __attribute__((pure)); int Vulkan_Scene_AddEntity (struct vulkan_ctx_s *ctx, struct entity_s *entity); +void Vulkan_Scene_Flush (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_scene_h diff --git a/include/QF/model.h b/include/QF/model.h index 4491c2e55..cc219e837 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -425,6 +425,8 @@ typedef struct model_s { cache_user_t cache; void (*clear) (struct model_s *m, void *data); void *data; + + int render_id; } model_t; // ============================================================================ diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index cb33837e6..899d50ab5 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -45,6 +45,7 @@ #include "QF/cvar.h" #include "QF/darray.h" +#include "QF/heapsort.h" #include "QF/image.h" #include "QF/render.h" #include "QF/sys.h" @@ -123,7 +124,7 @@ chain_surface (const bsp_face_t *face, bsp_pass_t *pass, bspctx_t *bctx) { DARRAY_APPEND (&pass->face_queue[face->tex_id], - ((instface_t) { bctx->inst_id, face - bctx->faces })); + ((instface_t) { pass->inst_id, face - bctx->faces })); } static void @@ -215,7 +216,7 @@ typedef struct { } buildctx_t; static void -build_surf_displist (faceref_t *faceref, buildctx_t *build) +build_surf_displist (const faceref_t *faceref, buildctx_t *build) { msurface_t *surf = faceref->face; mod_brush_t *brush = &faceref->model->brush;; @@ -296,6 +297,12 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) face_sets[i] = (facerefset_t) DARRAY_STATIC_INIT (1024); } + for (int i = 0; i < bctx->model_id; i++) { + DARRAY_CLEAR (&bctx->main_pass.instances[i].entities); + } + free (bctx->main_pass.instances); + bctx->model_id = 0; + // run through all surfaces, chaining them to their textures, thus // effectively sorting the surfaces by texture (without worrying about // surface order on the same texture chain). @@ -304,8 +311,13 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) model_t *m = models[i]; // sub-models are done as part of the main model // and non-bsp models don't have surfaces. - if (!m || *m->path == '*' || m->type != mod_brush) + if (!m || m->type != mod_brush) { continue; + } + m->render_id = bctx->model_id++; + if (*m->path == '*') { + continue; + } mod_brush_t *brush = &m->brush; dmodel_t *dm = brush->submodels; for (unsigned j = 0; j < brush->numsurfaces; j++) { @@ -328,6 +340,11 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } face_base += brush->numsurfaces; } + bctx->main_pass.instances = malloc (bctx->model_id + * sizeof (bsp_instance_t)); + for (int i = 0; i < bctx->model_id; i++) { + DARRAY_INIT (&bctx->main_pass.instances[i].entities, 16); + } // All vertices from all brush models go into one giant vbo. uint32_t vertex_count = 0; uint32_t index_count = 0; @@ -369,9 +386,21 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) // "end of primitive" (~0u) free (bctx->faces); free (bctx->poly_indices); + free (bctx->models); + bctx->models = malloc (bctx->model_id * sizeof (bsp_model_t)); bctx->faces = malloc (face_base * sizeof (bsp_face_t)); bctx->poly_indices = malloc (index_count * sizeof (uint32_t)); + face_base = 0; + for (int i = 0; i < num_models; i++) { + if (models[i] && models[i]->type == mod_brush) { + bsp_model_t *m = &bctx->models[models[i]->render_id]; + m->first_face = face_base; + m->face_count = models[i]->brush.nummodelsurfaces; + face_base += m->face_count; + } + } + // All usable surfaces have been chained to the (base) texture they use. // Run through the textures, using their chains to build display lists. // For animated textures, if a surface is on one texture of the group, it @@ -468,61 +497,44 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } -static void -R_DrawBrushModel (entity_t *e, vulkan_ctx_t *ctx) +static int +R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx) { - float dot, radius; + float radius; model_t *model; - plane_t *plane; - msurface_t *surf; - qboolean rotated; vec3_t mins, maxs; - vec4f_t org; - mod_brush_t *brush; - //bspctx_t *bctx = ctx->bsp_context; + bspctx_t *bctx = ctx->bsp_context; model = e->renderer.model; - brush = &model->brush; mat4f_t mat; Transform_GetWorldMatrix (e->transform, mat); - memcpy (e->renderer.full_transform, mat, sizeof (mat));//FIXME if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { - rotated = true; radius = model->radius; if (R_CullSphere (r_refdef.frustum, (vec_t*)&mat[3], radius)) { //FIXME - return; + return 1; } } else { - rotated = false; VectorAdd (mat[3], model->mins, mins); VectorAdd (mat[3], model->maxs, maxs); if (R_CullBox (r_refdef.frustum, mins, maxs)) - return; + return 1; + } + if (Vulkan_Scene_AddEntity (ctx, e) < 0) { + return 0; } - org = r_refdef.frame.position - mat[3]; - if (rotated) { - vec4f_t temp = org; - - org[0] = DotProduct (temp, mat[0]); - org[1] = DotProduct (temp, mat[1]); - org[2] = DotProduct (temp, mat[2]); - } - - surf = &brush->surfaces[brush->firstmodelsurface]; - - for (unsigned i = 0; i < brush->nummodelsurfaces; i++, surf++) { - // find the node side on which we are - plane = surf->plane; - - dot = PlaneDiff (org, plane); - - // enqueue the polygon - if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) - || (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - //chain_surface (surf, ctx); + pass->inst_id = model->render_id; + if (!pass->instances[model->render_id].entities.size) { + bsp_model_t *m = &bctx->models[model->render_id]; + bsp_face_t *face = &bctx->faces[m->first_face]; + for (unsigned i = 0; i < m->face_count; i++, face++) { + // enqueue the polygon + chain_surface (face, pass, bctx); } } + DARRAY_APPEND (&pass->instances[model->render_id].entities, + e->renderer.render_id); + return 1; } static inline void @@ -841,8 +853,12 @@ clear_queues (bspctx_t *bctx, bsp_pass_t *pass) for (size_t i = 0; i < bctx->registered_textures.size; i++) { DARRAY_RESIZE (&pass->face_queue[i], 0); } - for (int j = 0; j < pass->num_queues; j++) { - DARRAY_RESIZE (&pass->draw_queues[j], 0); + for (int i = 0; i < pass->num_queues; i++) { + DARRAY_RESIZE (&pass->draw_queues[i], 0); + } + for (int i = 0; i < bctx->model_id; i++) { + pass->instances[i].first_instance = -1; + DARRAY_RESIZE (&pass->instances[i].entities, 0); } pass->index_count = 0; } @@ -856,29 +872,50 @@ queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe) if (!queue->size) { continue; } - //FIXME implement draw_queue selection correctly (per face) - int dq = 0; - if (bctx->faces[queue->a[0].face].flags & SURF_DRAWSKY) { - dq = 1; - } - if (bctx->faces[queue->a[0].face].flags & SURF_DRAWTURB) { - dq = 2; - } - bsp_draw_t draw = { - .tex_id = i, - .instance_count = 1, - .first_index = pass->index_count, - }; for (size_t j = 0; j < queue->size; j++) { __auto_type is = queue->a[j]; __auto_type f = bctx->faces[is.face]; + + if (pass->instances[is.inst_id].first_instance == -1) { + uint32_t count = pass->instances[is.inst_id].entities.size; + pass->instances[is.inst_id].first_instance = pass->entid_count; + memcpy (pass->entid_data + pass->entid_count, + pass->instances[is.inst_id].entities.a, + count * sizeof (uint32_t)); + pass->entid_count += count; + } + + int dq = 0; + if (bctx->faces[queue->a[0].face].flags & SURF_DRAWSKY) { + dq = 1; + } + if (bctx->faces[queue->a[0].face].flags & SURF_DRAWTURB) { + dq = 2; + } + + size_t dq_size = pass->draw_queues[dq].size; + bsp_draw_t *draw = &pass->draw_queues[dq].a[dq_size - 1]; + if (!pass->draw_queues[dq].size + || draw->tex_id != f.tex_id + || draw->inst_id != is.inst_id) { + bsp_instance_t *instance = &pass->instances[is.inst_id]; + DARRAY_APPEND (&pass->draw_queues[dq], ((bsp_draw_t) { + .tex_id = i, + .inst_id = is.inst_id, + .instance_count = instance->entities.size, + .first_index = pass->index_count, + .first_instance = instance->first_instance, + })); + dq_size = pass->draw_queues[dq].size; + draw = &pass->draw_queues[dq].a[dq_size - 1]; + } + memcpy (pass->indices + pass->index_count, bctx->poly_indices + f.first_index, f.index_count * sizeof (uint32_t)); - draw.index_count += f.index_count; + draw->index_count += f.index_count; pass->index_count += f.index_count; } - DARRAY_APPEND (&pass->draw_queues[dq], draw); } bframe->index_count += pass->index_count; } @@ -901,13 +938,11 @@ draw_queue (bsp_pass_t *pass, int queue, VkPipelineLayout layout, } static int -add_entity (vulkan_ctx_t *ctx, bsp_pass_t *pass, entity_t *entity) +ent_model_cmp (const void *_a, const void *_b) { - int entid = Vulkan_Scene_AddEntity (ctx, entity); - if (entid >= 0) { - pass->entid_data[pass->entid_count++] = entid; - } - return entid >= 0; + const entity_t * const *a = _a; + const entity_t * const *b = _b; + return (*a)->renderer.model->render_id - (*b)->renderer.model->render_id; } void @@ -937,20 +972,29 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) }; brush = &r_refdef.worldmodel->brush; - add_entity (ctx, &bctx->main_pass, &worldent); + Vulkan_Scene_AddEntity (ctx, &worldent); + int world_id = worldent.renderer.model->render_id; + bctx->main_pass.inst_id = world_id; + DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, + worldent.renderer.render_id); R_VisitWorldNodes (brush, ctx); if (!bctx->vertex_buffer) { return; } if (r_drawentities) { + heapsort (r_ent_queue->ent_queues[mod_brush].a, + r_ent_queue->ent_queues[mod_brush].size, + sizeof (entity_t *), ent_model_cmp); for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; - if (add_entity (ctx, &bctx->main_pass, ent)) { - R_DrawBrushModel (ent, ctx); + if (!R_DrawBrushModel (ent, &bctx->main_pass, ctx)) { + Sys_Printf ("Too many entities!\n"); + break; } } } + bframe->entid_count = bctx->main_pass.entid_count; queue_faces (&bctx->main_pass, bctx, bframe); @@ -1188,7 +1232,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&bctx->registered_textures, 64); - bctx->main_pass.num_queues = 3; + bctx->main_pass.num_queues = 3;//solid, sky, water bctx->main_pass.draw_queues = malloc (bctx->main_pass.num_queues * sizeof (bsp_drawset_t)); for (int i = 0; i < bctx->main_pass.num_queues; i++) { @@ -1208,7 +1252,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); - size_t entid_size = Vulkan_Scene_MaxEntities (ctx) * sizeof (uint32_t); + size_t entid_count = Vulkan_Scene_MaxEntities (ctx); + size_t entid_size = entid_count * sizeof (uint32_t); size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; size_t atom_mask = atom - 1; entid_size = (entid_size + atom_mask) & ~atom_mask; @@ -1245,7 +1290,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) va (ctx->va_ctx, "cmd:bsp:%zd:%s", i, bsp_pass_names[j])); } - bframe->entid_data = entid_data + i * entid_size; + bframe->entid_data = entid_data + i * entid_count; bframe->entid_offset = i * entid_size; } @@ -1273,12 +1318,22 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) dfunc->vkDestroyPipeline (device->dev, bctx->skybox, 0); dfunc->vkDestroyPipeline (device->dev, bctx->skysheet, 0); dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0); + DARRAY_CLEAR (&bctx->registered_textures); for (int i = 0; i < bctx->main_pass.num_queues; i++) { DARRAY_CLEAR (&bctx->main_pass.draw_queues[i]); } + + free (bctx->faces); + free (bctx->models); + free (bctx->main_pass.draw_queues); + for (int i = 0; i < bctx->model_id; i++) { + DARRAY_CLEAR (&bctx->main_pass.instances[i].entities); + } + free (bctx->main_pass.instances); DARRAY_CLEAR (&bctx->frames); + QFV_DestroyStagingBuffer (bctx->light_stage); QFV_DestroyScrap (bctx->light_scrap); if (bctx->vertex_buffer) { diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index accd40842..698881205 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -56,6 +56,7 @@ #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_particles.h" +#include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_sprite.h" //#include "QF/Vulkan/qf_textures.h" #include "QF/Vulkan/renderpass.h" @@ -128,6 +129,7 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) } Vulkan_DrawWaterSurfaces (rFrame); Vulkan_Bsp_Flush (ctx); + Vulkan_Scene_Flush (ctx); } void diff --git a/libs/video/renderer/vulkan/vulkan_scene.c b/libs/video/renderer/vulkan/vulkan_scene.c index 6a8c568ef..1fcf12dab 100644 --- a/libs/video/renderer/vulkan/vulkan_scene.c +++ b/libs/video/renderer/vulkan/vulkan_scene.c @@ -101,6 +101,16 @@ Vulkan_Scene_AddEntity (vulkan_ctx_t *ctx, entity_t *entity) return entity->renderer.render_id; } +void +Vulkan_Scene_Flush (vulkan_ctx_t *ctx) +{ + scenectx_t *sctx = ctx->scene_context; + scnframe_t *sframe = &sctx->frames.a[ctx->curFrame]; + + set_empty (sframe->pooled_entities); + sframe->entity_pool.size = 0; +} + static VkWriteDescriptorSet base_buffer_write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, 0, 0, 1, From 70ece6d5bb5511ab39d93f475255202b9270e0f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 May 2022 20:08:36 +0900 Subject: [PATCH 2866/3664] [vulkan] Work around buggy maps with broken brushes Conflagrant Rodent has a sub-model with 0 faces (double bit error?) causing simply counting faces to get out of sync with actual model starts thus breaking *all* brush models that come after it (including other maps). Thus be a little less lazy in figuring out model start faces. --- libs/video/renderer/vulkan/vulkan_bsp.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 899d50ab5..15f946bb1 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -393,12 +393,20 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) face_base = 0; for (int i = 0; i < num_models; i++) { - if (models[i] && models[i]->type == mod_brush) { - bsp_model_t *m = &bctx->models[models[i]->render_id]; - m->first_face = face_base; - m->face_count = models[i]->brush.nummodelsurfaces; - face_base += m->face_count; + if (!models[i] || models[i]->type != mod_brush) { + continue; } + int num_faces = models[i]->brush.numsurfaces; + bsp_model_t *m = &bctx->models[models[i]->render_id]; + m->first_face = face_base + models[i]->brush.firstmodelsurface; + m->face_count = models[i]->brush.nummodelsurfaces; + while (models[i + 1] && models[i + 1]->path[0] == '*') { + i++; + m = &bctx->models[models[i]->render_id]; + m->first_face = face_base + models[i]->brush.firstmodelsurface; + m->face_count = models[i]->brush.nummodelsurfaces; + } + face_base += num_faces;; } // All usable surfaces have been chained to the (base) texture they use. From dcfe0e33a3ac6c3ef88bfc2007c2a1416c90307f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 12:35:50 +0900 Subject: [PATCH 2867/3664] [util] Allow zero-sized lumps to be at end of file This fixes a crash when attempting to load a map with no texture data. --- libs/util/bspfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/bspfile.c b/libs/util/bspfile.c index eb1b50784..1b0e503b5 100644 --- a/libs/util/bspfile.c +++ b/libs/util/bspfile.c @@ -683,7 +683,7 @@ do { \ size_t size = LittleLong (bsp29->header->lumps[l].filelen); \ size_t offs = LittleLong (bsp29->header->lumps[l].fileofs); \ void *data = (byte *) mem + offs; \ - if (offs >= mem_size || (offs + size) > mem_size) \ + if (offs > mem_size || (offs + size) > mem_size) \ Sys_Error ("invalid lump"); \ bsp29->n = 0; \ if (size) \ From c86cb0ac54d4cbffaf52f42b8d2fd07d36fb8177 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 14:41:08 +0900 Subject: [PATCH 2868/3664] [renderer] Clean up some unwanted dependencies Nothing outside of the renderer should be including d_iface.h (locs.c does still for particle defines), and plugin/vid_render.h is more independent. --- include/QF/plugin/vid_render.h | 3 ++- include/d_iface.h | 2 +- include/mod_internal.h | 7 ++++--- include/r_local.h | 4 ++-- qw/source/cl_ents.c | 1 - 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 377c0e1a3..1f19a5278 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -43,6 +43,7 @@ struct mod_sprite_ctx_s; struct entqueue_s; struct framebuffer_s; struct vrect_s; +struct texture_s; /* All video plugins must export these functions @@ -52,7 +53,7 @@ typedef struct vid_model_funcs_s { size_t texture_render_size;// size of renderer specific texture data void (*Mod_LoadLighting) (model_t *mod, bsp_t *bsp); void (*Mod_SubdivideSurface) (model_t *mod, msurface_t *fa); - void (*Mod_ProcessTexture) (model_t *mod, texture_t *tx); + void (*Mod_ProcessTexture) (model_t *mod, struct texture_s *tx); void (*Mod_LoadIQM) (model_t *mod, void *buffer); void (*Mod_LoadAliasModel) (model_t *mod, void *buffer, cache_allocator_t allocator); diff --git a/include/d_iface.h b/include/d_iface.h index 1a0479d44..b687e8df1 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -193,7 +193,7 @@ typedef struct msurface_t *surf; // description for surface to generate fixed8_t lightadj[MAXLIGHTMAPS]; // adjust for lightmap levels for dynamic lighting - texture_t *texture; // corrected for animating textures + struct texture_s *texture; // corrected for animating textures int surfmip; // mipmapped ratio of surface texels / world pixels int surfwidth; // in mipmapped texels int surfheight; // in mipmapped texels diff --git a/include/mod_internal.h b/include/mod_internal.h index 242e15666..a135dff21 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -77,10 +77,11 @@ void sw_Mod_IQMFinish (model_t *mod); void gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp); void gl_Mod_SubdivideSurface (model_t *mod, msurface_t *fa); -void gl_Mod_ProcessTexture (model_t *mod, texture_t *tx); +struct texture_s; +void gl_Mod_ProcessTexture (model_t *mod, struct texture_s *tx); void glsl_Mod_LoadLighting (model_t *mod, bsp_t *bsp); -void glsl_Mod_ProcessTexture (model_t *mod, texture_t *tx); +void glsl_Mod_ProcessTexture (model_t *mod, struct texture_s *tx); void sw_Mod_LoadLighting (model_t *mod, bsp_t *bsp); @@ -88,7 +89,7 @@ void Vulkan_Mod_LoadLighting (model_t *mod, bsp_t *bsp, struct vulkan_ctx_s *ctx); void Vulkan_Mod_SubdivideSurface (model_t *mod, msurface_t *fa, struct vulkan_ctx_s *ctx); -void Vulkan_Mod_ProcessTexture (model_t *mod, texture_t *tx, +void Vulkan_Mod_ProcessTexture (model_t *mod, struct texture_s *tx, struct vulkan_ctx_s *ctx); void Mod_LoadSpriteFrame (mspriteframe_t *frame, const dspriteframe_t *dframe); diff --git a/include/r_local.h b/include/r_local.h index 3e158fe9d..4f5d53185 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -155,7 +155,7 @@ void R_RenderBmodelFace (struct entity_s *ent, bedge_t *pedges, msurface_t *psur void R_TransformFrustum (void); void R_SetSkyFrame (void); void R_DrawSurfaceBlock (void); -texture_t *R_TextureAnimation (const struct entity_s *entity, msurface_t *surf) __attribute__((pure)); +struct texture_s *R_TextureAnimation (const struct entity_s *entity, msurface_t *surf) __attribute__((pure)); void R_GenSkyTile (void *pdest); void R_SurfPatch (void); @@ -184,7 +184,7 @@ void D_DrawSurfaces (void); void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist); void R_StepActiveU (edge_t *pedge); void R_RemoveEdges (edge_t *pedge); -void R_AddTexture (texture_t *tex); +void R_AddTexture (struct texture_s *tex); struct vulkan_ctx_s; void R_ClearTextures (void); void R_InitSurfaceChains (mod_brush_t *brush); diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 49ad77cc1..1907cf15a 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -45,7 +45,6 @@ #include "QF/scene/scene.h" #include "compat.h" -#include "d_iface.h" #include "client/effects.h" #include "client/locs.h" From f65a35da885b84b13ad7c03ece250208155693f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 16:11:50 +0900 Subject: [PATCH 2869/3664] [gib] Clean up some header dependencies --- include/QF/gib.h | 23 ++++++++++------------- libs/gib/bi_gib.c | 1 + libs/gib/gib_classes.c | 1 + libs/gib/gib_function.c | 1 + libs/gib/gib_handle.c | 1 + libs/gib/gib_init.c | 1 + libs/gib/gib_object.c | 2 ++ nq/source/host.c | 1 + qw/source/cl_main.c | 1 + qw/source/sv_gib.c | 1 + qw/source/sv_init.c | 1 + qw/source/teamplay.c | 1 + 12 files changed, 22 insertions(+), 13 deletions(-) diff --git a/include/QF/gib.h b/include/QF/gib.h index 018eabedd..2631bea41 100644 --- a/include/QF/gib.h +++ b/include/QF/gib.h @@ -31,12 +31,7 @@ #ifndef __QF_gib_h #define __QF_gib_h -// Dependencies - -#include "QF/dstring.h" -#include "QF/cbuf.h" -#include "QF/hash.h" -#include "QF/llist.h" +#include "QF/qtypes.h" // Object interface @@ -56,11 +51,11 @@ typedef struct gib_slot_s { typedef struct gib_object_s { struct gib_class_s *class; - hashtab_t *methods; + struct hashtab_s *methods; void **data; unsigned long int handle, refs; - hashtab_t *signals, *vars; - llist_t *slots; + struct hashtab_s *signals, *vars; + struct llist_s *slots; const char *handstr; } gib_object_t; @@ -87,13 +82,13 @@ typedef void (*gib_obj_destructor) (void *data); typedef struct gib_class_s { const char *name; - hashtab_t *methods, *class_methods; + struct hashtab_s *methods, *class_methods; gib_obj_constructor construct, class_construct; gib_obj_destructor destruct; unsigned int depth; struct gib_object_s *classobj; struct gib_class_s *parent; - llist_t *children; + struct llist_s *children; } gib_class_t; typedef struct gib_methodtab_s { @@ -144,6 +139,8 @@ typedef struct gib_script_s { unsigned int refs; } gib_script_t; +struct cbuf_s; + typedef struct gib_buffer_data_s { struct gib_script_s *script; struct gib_tree_s *program, *ip; @@ -163,7 +160,7 @@ typedef struct gib_buffer_data_s { } reply; struct hashtab_s *locals; // Local variables struct hashtab_s *globals; // Current domain - void (*dnotify) (cbuf_t *cbuf, void *data); + void (*dnotify) (struct cbuf_s *cbuf, void *data); void *ddata; } gib_buffer_data_t; @@ -181,7 +178,7 @@ extern char * const gib_null_string; #define GIB_CanReturn() (GIB_DATA(cbuf_active)->waitret) -dstring_t *GIB_Return (const char *str); +struct dstring_s *GIB_Return (const char *str); void GIB_Error (const char *type, const char *fmt, ...) __attribute__((format(PRINTF, 2, 3))); void GIB_Builtin_Add (const char *name, void (*func) (void)); void GIB_Builtin_Remove (const char *name); diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index b180613e3..0a55e8a2d 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -39,6 +39,7 @@ #include "QF/cmd.h" #include "QF/csqc.h" +#include "QF/dstring.h" #include "QF/hash.h" #include "QF/progs.h" #include "QF/sys.h" diff --git a/libs/gib/gib_classes.c b/libs/gib/gib_classes.c index 55087dcdf..3ec8b9f86 100644 --- a/libs/gib/gib_classes.c +++ b/libs/gib/gib_classes.c @@ -38,6 +38,7 @@ #include +#include "QF/cbuf.h" #include "QF/gib.h" #include "QF/va.h" #include "QF/sys.h" diff --git a/libs/gib/gib_function.c b/libs/gib/gib_function.c index c960a7d49..09b662dec 100644 --- a/libs/gib/gib_function.c +++ b/libs/gib/gib_function.c @@ -38,6 +38,7 @@ #include "QF/sys.h" #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/llist.h" #include "QF/cbuf.h" #include "QF/va.h" #include "QF/gib.h" diff --git a/libs/gib/gib_handle.c b/libs/gib/gib_handle.c index b6816396c..3d2c7fd96 100644 --- a/libs/gib/gib_handle.c +++ b/libs/gib/gib_handle.c @@ -31,6 +31,7 @@ #include +#include "QF/cbuf.h" #include "QF/gib.h" #include "gib_handle.h" diff --git a/libs/gib/gib_init.c b/libs/gib/gib_init.c index a50df21c3..668d2fb10 100644 --- a/libs/gib/gib_init.c +++ b/libs/gib/gib_init.c @@ -37,6 +37,7 @@ #include "QF/qtypes.h" #include "QF/cbuf.h" +#include "QF/dstring.h" #include "QF/quakefs.h" #include "QF/cmd.h" #include "QF/sys.h" diff --git a/libs/gib/gib_object.c b/libs/gib/gib_object.c index b9fbf66a9..f73108d26 100644 --- a/libs/gib/gib_object.c +++ b/libs/gib/gib_object.c @@ -39,7 +39,9 @@ #include #include +#include "QF/cbuf.h" #include "QF/hash.h" +#include "QF/llist.h" #include "QF/sys.h" #include "QF/va.h" #include "QF/gib.h" diff --git a/nq/source/host.c b/nq/source/host.c index da393a677..d6de521d3 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -35,6 +35,7 @@ #include "QF/cbuf.h" #include "QF/cdaudio.h" #include "QF/draw.h" +#include "QF/dstring.h" #include "QF/idparse.h" #include "QF/cmd.h" #include "QF/console.h" diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 3162b9b74..6a643b708 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -67,6 +67,7 @@ #include "QF/console.h" #include "QF/cvar.h" #include "QF/draw.h" +#include "QF/dstring.h" #include "QF/image.h" #include "QF/input.h" #include "QF/joystick.h" diff --git a/qw/source/sv_gib.c b/qw/source/sv_gib.c index 3e4d5421c..17a21af7e 100644 --- a/qw/source/sv_gib.c +++ b/qw/source/sv_gib.c @@ -35,6 +35,7 @@ # include #endif +#include "QF/cbuf.h" #include "QF/dstring.h" #include "QF/info.h" #include "QF/gib.h" diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 29ba96c5a..26379b17c 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -35,6 +35,7 @@ # include #endif +#include "QF/cbuf.h" #include "QF/crc.h" #include "QF/cvar.h" #include "QF/info.h" diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index 5bca2f58d..f1c960bf3 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -42,6 +42,7 @@ #include "QF/cbuf.h" #include "QF/cmd.h" #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/gib.h" #include "QF/model.h" #include "QF/va.h" From 521f805edf71fdf66690a025e14056a3acbcebcb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 16:17:00 +0900 Subject: [PATCH 2870/3664] [nq] Move Host_ClientFrame to CL_Frame This removes a bit of mess from sv_ded.c, and is a step towards making host*.c just the minimal interface between client and local server. --- nq/include/client.h | 1 + nq/include/host.h | 1 + nq/source/cl_main.c | 74 +++++++++++++++++++++++++++++- nq/source/host.c | 109 +++----------------------------------------- nq/source/sv_ded.c | 59 ++++-------------------- 5 files changed, 90 insertions(+), 154 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index d059db54f..edfdef8aa 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -241,6 +241,7 @@ struct cbuf_s; void CL_Init (struct cbuf_s *cbuf); void CL_InitCvars (void); void CL_ClearMemory (void); +void CL_Frame (void); int CL_ReadConfiguration (const char *cfg_name); void CL_EstablishConnection (const char *host); diff --git a/nq/include/host.h b/nq/include/host.h index dae61381e..a9a3e7d4a 100644 --- a/nq/include/host.h +++ b/nq/include/host.h @@ -46,6 +46,7 @@ extern int pausable; extern int viewentity; +extern int host_speeds; extern qboolean host_initialized; // true if into command execution extern double host_frametime; extern int host_framecount; // incremented every frame, never reset diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 070df9f1f..f7eb45d3d 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -35,9 +35,11 @@ #include "QF/cvar.h" #include "QF/draw.h" #include "QF/input.h" +#include "QF/image.h" #include "QF/joystick.h" #include "QF/keys.h" #include "QF/msg.h" +#include "QF/png.h" #include "QF/plist.h" #include "QF/render.h" #include "QF/screen.h" @@ -61,7 +63,6 @@ #include "nq/include/cl_skin.h" #include "nq/include/client.h" #include "nq/include/host.h" -#include "nq/include/host.h" #include "nq/include/server.h" CLIENT_PLUGIN_PROTOS @@ -609,6 +610,75 @@ CL_SetState (cactive_t state) } } +static void +write_capture (tex_t *tex, void *data) +{ + QFile *file = QFS_Open (va (0, "%s/qfmv%06d.png", + qfs_gamedir->dir.shots, + cls.demo_capture++), "wb"); + if (file) { + WritePNG (file, tex); + Qclose (file); + } + free (tex); +} + +void +CL_Frame (void) +{ + static double time1 = 0, time2 = 0, time3 = 0; + int pass1, pass2, pass3; + + // fetch results from server + if (cls.state >= ca_connected) + CL_ReadFromServer (); + + // update video + if (host_speeds) + time1 = Sys_DoubleTime (); + + r_data->inhibit_viewmodel = (chase_active + || (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) + || cl.stats[STAT_HEALTH] <= 0); + r_data->frametime = host_frametime; + + CL_UpdateScreen (cl.time); + + if (host_speeds) + time2 = Sys_DoubleTime (); + + // update audio + if (cls.state == ca_active) { + mleaf_t *l; + byte *asl = 0; + vec4f_t origin; + + origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); + l = Mod_PointInLeaf (origin, cl_world.scene->worldmodel); + if (l) + asl = l->ambient_sound_level; + S_Update (cl.viewstate.camera_transform, asl); + R_DecayLights (host_frametime); + } else + S_Update (0, 0); + + CDAudio_Update (); + + if (host_speeds) { + pass1 = (time1 - time3) * 1000; + time3 = Sys_DoubleTime (); + pass2 = (time2 - time1) * 1000; + pass3 = (time3 - time2) * 1000; + Sys_Printf ("%3i tot %3i server %3i gfx %3i snd\n", + pass1 + pass2 + pass3, pass1, pass2, pass3); + } + + if (cls.demo_capture) { + r_funcs->capture_screen (write_capture, 0); + } + fps_count++; +} + static void Force_CenterView_f (void) { @@ -632,9 +702,9 @@ CL_Init (cbuf_t *cbuf) W_LoadWadFile ("gfx.wad"); VID_Init (basepal, colormap); IN_Init (); + GIB_Key_Init (); R_Init (); r_data->lightstyle = cl.lightstyle; - S_Init (&cl.viewentity, &host_frametime); PI_RegisterPlugins (client_plugin_list); diff --git a/nq/source/host.c b/nq/source/host.c index d6de521d3..b8f21e2a7 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -29,45 +29,24 @@ #endif #ifdef HAVE_UNISTD_H -# include "unistd.h" +# include #endif #include "QF/cbuf.h" -#include "QF/cdaudio.h" -#include "QF/draw.h" #include "QF/dstring.h" -#include "QF/idparse.h" #include "QF/cmd.h" -#include "QF/console.h" #include "QF/cvar.h" -#include "QF/image.h" -#include "QF/input.h" -#include "QF/keys.h" -#include "QF/listener.h" -#include "QF/msg.h" -#include "QF/png.h" -#include "QF/progs.h" -#include "QF/qargs.h" -#include "QF/screen.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" +#include "QF/dstring.h" #include "QF/gib.h" +#include "QF/idparse.h" +#include "QF/qargs.h" #include "QF/plugin/console.h" -#include "QF/plugin/vid_render.h" -#include "QF/scene/scene.h" -#include "QF/scene/transform.h" #include "buildnum.h" -#include "compat.h" - -#include "client/chase.h" -#include "client/world.h" #include "nq/include/host.h" #include "nq/include/server.h" -#include "nq/include/sv_progs.h" /* @@ -714,74 +693,6 @@ Host_ServerFrame (void) SV_SendClientMessages (); } -static void -write_capture (tex_t *tex, void *data) -{ - QFile *file = QFS_Open (va (0, "%s/qfmv%06d.png", - qfs_gamedir->dir.shots, - cls.demo_capture++), "wb"); - if (file) { - WritePNG (file, tex); - Qclose (file); - } - free (tex); -} - -static void -Host_ClientFrame (void) -{ - static double time1 = 0, time2 = 0, time3 = 0; - int pass1, pass2, pass3; - - // fetch results from server - if (cls.state >= ca_connected) - CL_ReadFromServer (); - - // update video - if (host_speeds) - time1 = Sys_DoubleTime (); - - r_data->inhibit_viewmodel = (chase_active - || (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) - || cl.stats[STAT_HEALTH] <= 0); - r_data->frametime = host_frametime; - - CL_UpdateScreen (cl.time); - - if (host_speeds) - time2 = Sys_DoubleTime (); - - // update audio - if (cls.state == ca_active) { - mleaf_t *l; - byte *asl = 0; - vec4f_t origin; - - origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - l = Mod_PointInLeaf (origin, cl_world.scene->worldmodel); - if (l) - asl = l->ambient_sound_level; - S_Update (cl.viewstate.camera_transform, asl); - R_DecayLights (host_frametime); - } else - S_Update (0, 0); - - CDAudio_Update (); - - if (host_speeds) { - pass1 = (time1 - time3) * 1000; - time3 = Sys_DoubleTime (); - pass2 = (time2 - time1) * 1000; - pass3 = (time3 - time2) * 1000; - Sys_Printf ("%3i tot %3i server %3i gfx %3i snd\n", - pass1 + pass2 + pass3, pass1, pass2, pass3); - } - - if (cls.demo_capture) { - r_funcs->capture_screen (write_capture, 0); - } -} - /* Host_Frame @@ -834,8 +745,6 @@ _Host_Frame (float time) } else { Con_NewMap (); } - - CL_UpdateScreen (cl.time); } NET_Poll (); @@ -852,11 +761,10 @@ _Host_Frame (float time) } if (!net_is_dedicated) { - Host_ClientFrame (); + CL_Frame (); } host_framecount++; - fps_count++; } void @@ -1037,7 +945,7 @@ Host_Init (void) Sys_Init (); GIB_Init (true); - GIB_Key_Init (); + COM_ParseConfig (host_cbuf); memhunk_t *hunk = Host_Init_Memory (); @@ -1075,9 +983,6 @@ Host_Init (void) con_module->data->console->cbuf = host_cbuf; } - CL_UpdateScreen (cl.time); - CL_UpdateScreen (cl.time); - Host_ExecConfig (host_cbuf, isDedicated || !cl_quakerc); Hunk_AllocName (0, 0, "-HOST_HUNKLEVEL-"); @@ -1090,8 +995,6 @@ Host_Init (void) PACKAGE_NAME); host_initialized = true; - - CL_UpdateScreen (cl.time); } /* diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index 167596e74..d29ef998d 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -51,14 +51,18 @@ int cl_writecfg; float demo_speed; int chase_active; -int fps_count; -int viewentity; - -vid_render_data_t *r_data; -vid_render_funcs_t *r_funcs; +void +CL_Frame (void) +{ +} void -GIB_Key_Init (void) +CL_Init (struct cbuf_s *cbuf) +{ +} + +void +CL_InitCvars (void) { } @@ -77,11 +81,6 @@ CL_Cmd_ForwardToServer (void) { } -void -CDAudio_Update (void) -{ -} - void CL_Disconnect (void) { @@ -97,16 +96,6 @@ CL_EstablishConnection (const char *host) { } -void -CL_Init (struct cbuf_s *cbuf) -{ -} - -void -CL_InitCvars (void) -{ -} - void CL_NextDemo (void) { @@ -118,12 +107,6 @@ CL_ReadConfiguration (const char *cfg_name) return 0; } -__attribute__((const)) int -CL_ReadFromServer (void) -{ - return 0; -} - void CL_SendCmd (void) { @@ -134,16 +117,6 @@ CL_StopPlayback (void) { } -void -IN_ProcessEvents (void) -{ -} - -void -S_Update (struct transform_s *ere, const byte *ambient_sound_level) -{ -} - void S_BlockSound (void) { @@ -153,15 +126,3 @@ void S_UnblockSound (void) { } - -plugin_t *console_client_PluginInfo (void); -__attribute__((const)) plugin_t * -console_client_PluginInfo (void) -{ - return 0; -} - -void -R_DecayLights (double frametime) -{ -} From e86e93551dbdc6840da6deaf3f628749848648eb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 17:10:23 +0900 Subject: [PATCH 2871/3664] [nq] Remove some more bandaids More host cleanup. The client now processes input itself, as does the server, but only if running a dedicated server. The server no longer blocks sound when loading a map as it shouldn't know anything about sound. This will probably need something done in the client, but moving the server into a separate thread will have that effect anyway. --- nq/include/client.h | 1 + nq/include/host.h | 1 - nq/include/server.h | 1 + nq/source/Makemodule.am | 2 +- nq/source/cl_main.c | 13 +++++++++++++ nq/source/host.c | 38 ++------------------------------------ nq/source/sv_ded.c | 15 +++++---------- nq/source/sv_main.c | 37 ++++++++++++++++++++++++++++++++++--- 8 files changed, 57 insertions(+), 51 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index edfdef8aa..963b599a2 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -241,6 +241,7 @@ struct cbuf_s; void CL_Init (struct cbuf_s *cbuf); void CL_InitCvars (void); void CL_ClearMemory (void); +void CL_PreFrame (void); void CL_Frame (void); int CL_ReadConfiguration (const char *cfg_name); diff --git a/nq/include/host.h b/nq/include/host.h index a9a3e7d4a..ad6376c63 100644 --- a/nq/include/host.h +++ b/nq/include/host.h @@ -59,7 +59,6 @@ extern struct cbuf_s *host_cbuf; void Host_ClearMemory (void); void Host_SpawnServer (void); void Host_OnServerSpawn (void (*onSpawn)(void)); -void Host_ServerFrame (void); void Host_InitCommands (void); void Host_Init (void); void Host_Shutdown(void *data); diff --git a/nq/include/server.h b/nq/include/server.h index 411768be5..905c5c548 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -292,6 +292,7 @@ void SV_RunClients (void); void SV_User_Init_Cvars (void); void SV_SaveSpawnparms (void); void SV_SpawnServer (const char *server); +void SV_Frame (void); void SV_LoadProgs (void); void SV_Progs_Init (void); diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 403c29f1c..85ed5939a 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -46,6 +46,7 @@ nq_cl_plugin_LIBS= \ nq_client_LIBFILES= \ libs/gib/libQFgib_client.la \ + libs/input/libQFinput.la \ libs/audio/libQFcd.la \ libs/audio/libQFsound.la @@ -62,7 +63,6 @@ nq_common_LIBFILES= \ libs/ruamoko/libQFruamoko.la \ libs/gamecode/libQFgamecode.la \ libs/ui/libQFui.la \ - libs/input/libQFinput.la \ libs/util/libQFutil.la nq_client_LIBS= $(nq_client_LIBFILES) $(nq_common_LIBFILES) diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index f7eb45d3d..b3d74bd9a 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -34,6 +34,7 @@ #include "QF/console.h" #include "QF/cvar.h" #include "QF/draw.h" +#include "QF/gib.h" #include "QF/input.h" #include "QF/image.h" #include "QF/joystick.h" @@ -623,6 +624,18 @@ write_capture (tex_t *tex, void *data) free (tex); } +void +CL_PreFrame (void) +{ + IN_ProcessEvents (); + + GIB_Thread_Execute (); + cmd_source = src_command; + Cbuf_Execute_Stack (host_cbuf); + + CL_SendCmd (); +} + void CL_Frame (void) { diff --git a/nq/source/host.c b/nq/source/host.c index b8f21e2a7..c0fe78167 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -669,30 +669,6 @@ Host_FilterTime (float time) return 0; } -void -Host_ServerFrame (void) -{ - *sv_globals.frametime = sv_frametime = host_frametime; - - // set the time and clear the general datagram - SV_ClearDatagram (); - - SV_CheckForNewClients (); - - // read client messages - SV_RunClients (); - - // move things around and think - // always pause in single player if in console or menus - if (!sv.paused && (svs.maxclients > 1 || host_in_game)) { - SV_Physics (); - sv.time += host_frametime; - } - - // send all messages to the clients - SV_SendClientMessages (); -} - /* Host_Frame @@ -724,16 +700,6 @@ _Host_Frame (float time) } host_time += host_frametime; //FIXME is this needed? vcr stuff - if (net_is_dedicated) { - Con_ProcessInput (); - } else { - IN_ProcessEvents (); - } - - GIB_Thread_Execute (); - cmd_source = src_command; - Cbuf_Execute_Stack (host_cbuf); - if (first) { first = 0; @@ -753,11 +719,11 @@ _Host_Frame (float time) // Whether or not the server is active, if this is not a dedicated // server, then the client always needs to be able to process input // and send commands to the server before the server runs a frame. - CL_SendCmd (); + CL_PreFrame (); } if (sv.active) { - Host_ServerFrame (); + SV_Frame (); } if (!net_is_dedicated) { diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index d29ef998d..99e8cadc1 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -51,6 +51,11 @@ int cl_writecfg; float demo_speed; int chase_active; +void +CL_PreFrame (void) +{ +} + void CL_Frame (void) { @@ -116,13 +121,3 @@ void CL_StopPlayback (void) { } - -void -S_BlockSound (void) -{ -} - -void -S_UnblockSound (void) -{ -} diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index f3ebcb654..993f00cc1 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -29,7 +29,9 @@ #endif #include "QF/cmd.h" +#include "QF/console.h" #include "QF/cvar.h" +#include "QF/gib.h" #include "QF/msg.h" #include "QF/mathlib.h" #include "QF/set.h" @@ -1087,7 +1089,6 @@ SV_SpawnServer (const char *server) edict_t *ent; - S_BlockSound (); // let's not have any servers with no name if (hostname[0] == 0) Cvar_Set ("hostname", "UNNAMED"); @@ -1156,7 +1157,6 @@ SV_SpawnServer (const char *server) if (!sv.worldmodel) { Sys_Printf ("Couldn't spawn server %s\n", sv.modelname); sv.active = false; - S_UnblockSound (); return; } sv.models[1] = sv.worldmodel; @@ -1230,5 +1230,36 @@ SV_SpawnServer (const char *server) } Sys_MaskPrintf (SYS_dev, "Server spawned.\n"); - S_UnblockSound (); +} + +void +SV_Frame (void) +{ + if (net_is_dedicated) { + Con_ProcessInput (); + + GIB_Thread_Execute (); + cmd_source = src_command; + Cbuf_Execute_Stack (host_cbuf); + } + + *sv_globals.frametime = sv_frametime = host_frametime; + + // set the time and clear the general datagram + SV_ClearDatagram (); + + SV_CheckForNewClients (); + + // read client messages + SV_RunClients (); + + // move things around and think + // always pause in single player if in console or menus + if (!sv.paused && (svs.maxclients > 1 || host_in_game)) { + SV_Physics (); + sv.time += host_frametime; + } + + // send all messages to the clients + SV_SendClientMessages (); } From 4dc1988af1521526f81dad98d63b4f1eef2e88b6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 18:43:15 +0900 Subject: [PATCH 2872/3664] [vulkan] Add a function to load texture arrays I needed to create an array texture and didn't feel like doing all that boilerplate again :P. --- include/QF/Vulkan/qf_texture.h | 2 + libs/video/renderer/vulkan/vulkan_texture.c | 56 +++++++++++++++------ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index eadbc8b16..408118a4f 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -19,6 +19,8 @@ void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, int alpha, int count); qfv_tex_t *Vulkan_LoadTex (struct vulkan_ctx_s *ctx, tex_t *tex, int mip, const char *name); +qfv_tex_t *Vulkan_LoadTexArray (struct vulkan_ctx_s *ctx, tex_t *tex, + int layers, int mip, const char *name); qfv_tex_t *Vulkan_LoadEnvMap (struct vulkan_ctx_s *ctx, tex_t *tex, const char *name); qfv_tex_t *Vulkan_LoadEnvSides (struct vulkan_ctx_s *ctx, tex_t **tex, diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 2033b9182..26e005f08 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -145,7 +145,8 @@ stage_tex_data (qfv_packet_t *packet, tex_t *tex, int bpp) } qfv_tex_t * -Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) +Vulkan_LoadTexArray (vulkan_ctx_t *ctx, tex_t *tex, int layers, int mip, + const char *name) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -156,8 +157,15 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) return 0; } + for (int i = 1; i < layers; i++) { + if (tex[i].width != tex[0].width || tex[i].height != tex[0].height + || tex[i].format != tex[0].format) { + return 0; + } + } + if (mip) { - mip = QFV_MipLevels (tex->width, tex->height); + mip = QFV_MipLevels (tex[0].width, tex[0].height); } else { mip = 1; } @@ -166,9 +174,15 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) //FIXME this whole thing is ineffiecient, especially for small textures qfv_tex_t *qtex = malloc (sizeof (qfv_tex_t)); - VkExtent3D extent = { tex->width, tex->height, 1 }; - qtex->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, format, extent, - mip, 1, VK_SAMPLE_COUNT_1_BIT, + VkExtent3D extent = { tex[0].width, tex[0].height, 1 }; + VkImageType itype = layers > 0 ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_2D; + VkImageType vtype = layers > 0 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY + : VK_IMAGE_VIEW_TYPE_2D; + if (layers < 1) { + layers = 1; + } + qtex->image = QFV_CreateImage (device, 0, itype, format, extent, + mip, layers, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); @@ -180,31 +194,37 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, qtex->memory, va (ctx->va_ctx, "memory:%s", name)); QFV_BindImageMemory (device, qtex->image, qtex->memory, 0); - qtex->view = QFV_CreateImageView (device, qtex->image, - VK_IMAGE_VIEW_TYPE_2D, + qtex->view = QFV_CreateImageView (device, qtex->image, vtype, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, qtex->view, va (ctx->va_ctx, "iview:%s", name)); qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); - stage_tex_data (packet, tex, bpp); + + VkBufferImageCopy copy[layers]; + copy[0] = (VkBufferImageCopy) { + 0, 0, 0, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, {tex[0].width, tex[0].height, 1}, + }; + for (int i = 0; i < layers; i++) { + copy[i] = copy[0]; + copy[i].bufferOffset = stage_tex_data (packet, &tex[i], bpp); + copy[i].imageSubresource.baseArrayLayer = i; + } qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; ib.barrier.image = qtex->image; ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, 1, &ib.barrier); - VkBufferImageCopy copy = { - packet->offset, 0, 0, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, - {0, 0, 0}, {tex->width, tex->height, 1}, - }; dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, qtex->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ©); + layers, copy); if (mip == 1) { ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; ib.barrier.image = qtex->image; @@ -213,12 +233,18 @@ Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) 1, &ib.barrier); } else { QFV_GenerateMipMaps (device, packet->cmd, qtex->image, - mip, tex->width, tex->height, 1); + mip, tex->width, tex->height, layers); } QFV_PacketSubmit (packet); return qtex; } +qfv_tex_t * +Vulkan_LoadTex (vulkan_ctx_t *ctx, tex_t *tex, int mip, const char *name) +{ + return Vulkan_LoadTexArray (ctx, tex, 0, mip, name); +} + static qfv_tex_t * create_cubetex (vulkan_ctx_t *ctx, int size, VkFormat format, const char *name) From 4786594f3c587fdc02b040567c281a0684402cad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 19:14:44 +0900 Subject: [PATCH 2873/3664] [vulkan] Create a "missing" texture for bsps I found a test map with no texture data. Even after fixing the bsp loader, vulkan didn't like it. Now vulkan is happy. The "Missing" text is full-bright magenta on a dim grey background so it should be visible in any lighting conditions. --- libs/video/renderer/vulkan/vulkan_bsp.c | 78 +++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 15f946bb1..7a83fe7cd 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -95,8 +95,6 @@ static QFV_Subpass subpass_map[] = { QFV_passTranslucent, // QFV_bspTurb }; -static vulktex_t vulkan_notexture = { }; - #define ALLOC_CHUNK 64 static void @@ -1217,14 +1215,77 @@ create_default_skys (vulkan_ctx_t *ctx) QFV_PacketSubmit (packet); } +static void +create_notexture (vulkan_ctx_t *ctx) +{ + const char *missing = "Missing"; + byte data[2][64 * 64 * 4]; // 2 * 64x64 rgba (8x8 chars) + tex_t tex[2] = { + { .width = 64, + .height = 64, + .format = tex_rgba, + .loaded = 1, + .data = data[0], + }, + { .width = 64, + .height = 64, + .format = tex_rgba, + .loaded = 1, + .data = data[1], + }, + }; + + for (int i = 0; i < 64 * 64; i++) { + data[0][i * 4 + 0] = 0x20; + data[0][i * 4 + 1] = 0x20; + data[0][i * 4 + 2] = 0x20; + data[0][i * 4 + 3] = 0xff; + + data[1][i * 4 + 0] = 0x00; + data[1][i * 4 + 1] = 0x00; + data[1][i * 4 + 2] = 0x00; + data[1][i * 4 + 3] = 0xff; + } + int x = 4; + int y = 4; + for (const char *c = missing; *c; c++) { + byte *bitmap = font8x8_data + *c * 8; + for (int l = 0; l < 8; l++) { + byte d = *bitmap++; + for (int b = 0; b < 8; b++) { + if (d & 0x80) { + int base = ((y + l) * 64 + x + b) * 4; + data[0][base + 0] = 0x00; + data[0][base + 1] = 0x00; + data[0][base + 2] = 0x00; + data[0][base + 3] = 0xff; + + data[1][base + 0] = 0xff; + data[1][base + 1] = 0x00; + data[1][base + 2] = 0xff; + data[1][base + 3] = 0xff; + } + d <<= 1; + } + } + x += 8; + } + for (int i = 1; i < 7; i++) { + y += 8; + memcpy (data[0] + y * 64 * 4, data[0] + 4 * 64 * 4, 8 * 64 * 4); + memcpy (data[1] + y * 64 * 4, data[1] + 4 * 64 * 4, 8 * 64 * 4); + } + + bspctx_t *bctx = ctx->bsp_context; + bctx->notexture.tex = Vulkan_LoadTexArray (ctx, tex, 2, 1, "notexture"); +} + void Vulkan_Bsp_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - r_notexture_mip->render = &vulkan_notexture; - qfvPushDebug (ctx, "bsp init"); bspctx_t *bctx = calloc (1, sizeof (bspctx_t)); @@ -1237,6 +1298,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) ctx->cmdpool); create_default_skys (ctx); + create_notexture (ctx); DARRAY_INIT (&bctx->registered_textures, 64); @@ -1305,6 +1367,11 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) bctx->skybox_descriptor = Vulkan_CreateTextureDescriptor (ctx, bctx->default_skybox, bctx->sampler); + bctx->notexture.descriptor + = Vulkan_CreateTextureDescriptor (ctx, bctx->notexture.tex, + bctx->sampler); + + r_notexture_mip->render = &bctx->notexture; qfvPopDebug (ctx); } @@ -1358,6 +1425,9 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) if (bctx->skybox_tex) { Vulkan_UnloadTex (ctx, bctx->skybox_tex); } + if (bctx->notexture.tex) { + Vulkan_UnloadTex (ctx, bctx->notexture.tex); + } dfunc->vkDestroyImageView (device->dev, bctx->default_skysheet->view, 0); dfunc->vkDestroyImage (device->dev, bctx->default_skysheet->image, 0); From 847b3199d37ed3b4b4e4ae218437a1e58894f178 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 22:25:18 +0900 Subject: [PATCH 2874/3664] [bsp] Correct documentation about texture frame rate It turns out BSP textures are animated at only five frames per second. --- include/QF/bspfile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/bspfile.h b/include/QF/bspfile.h index 61103e3f3..926c3873a 100644 --- a/include/QF/bspfile.h +++ b/include/QF/bspfile.h @@ -592,7 +592,7 @@ typedef struct dleaf_s { //BSP2 version (bsp 29 version is in bspfile.c) Single-frame sequences are useful for simple static texture switchinng based on game state (entity frame: 0 for main, non-zero for alternate). - Multi-frame sequences are played back at ten frames per second. + Multi-frame sequences are played back at five frames per second. For example, the folowing sets up an animitation with a 4-frame main sequence and a 2-frame alternate sequence. Perhaps a roaring fire in From 77505abd940ff8cb76f15f577534c35c2d3974a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 22:30:29 +0900 Subject: [PATCH 2875/3664] [model] Move ANIM_CYCLE into model.h Need it in the vulkan renderer to undo the scaling --- include/QF/model.h | 1 + libs/models/brush/model_brush.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/model.h b/include/QF/model.h index cc219e837..d8bff2340 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -90,6 +90,7 @@ typedef struct instsurf_s { float *color; } instsurf_t; +#define ANIM_CYCLE 2 typedef struct texture_s { char name[16]; unsigned width, height; diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 2bfa85aa3..377e871f4 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -362,7 +362,6 @@ Mod_LoadTextures (model_t *mod, bsp_t *bsp) Sys_Error ("Bad animating texture %s", tx->name); } -#define ANIM_CYCLE 2 // link them all together for (int j = 0; j < max; j++) { tx2 = anims[j]; From 61178978be96072e33133368414e3f9e7a38bcbf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 26 May 2022 22:31:31 +0900 Subject: [PATCH 2876/3664] [vulkan] Get bsp texture animations working again The texture animation data is compacted into a small struct for each texture, resulting in much less data access when animating the texture. More importantly, no looping over the list of frames. I plan on migrating this to at least the other hardware renderers. --- include/QF/Vulkan/qf_bsp.h | 40 ++++++++--- libs/video/renderer/vulkan/vulkan_bsp.c | 93 ++++++++++++++++++++++--- 2 files changed, 116 insertions(+), 17 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index fac47e1cf..376eaa181 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -64,11 +64,30 @@ typedef struct bsp_packetset_s typedef struct bsp_indexset_s DARRAY_TYPE (uint32_t) bsp_indexset_t; -typedef struct bsp_tex_s { - VkDescriptorSet descriptors; - bsp_packetset_t packets; - bsp_indexset_t indices; -} bsp_tex_t; +typedef struct texname_s { + char name[MIPTEXNAME]; +} texname_t; + +typedef struct texmip_s { + uint32_t width; + uint32_t height; + uint32_t offsets[MIPLEVELS]; +} texmip_t; + +typedef struct texanim_s { + uint16_t base; + byte offset; + byte count; +} texanim_t; + +typedef struct texdata_s { +// texname_t *names; +// texmip_t **mips; + texanim_t *anim_main; + texanim_t *anim_alt; + uint16_t *anim_map; +// int num_tex; +} texdata_t; typedef struct vulktex_s { struct qfv_tex_s *tex; @@ -79,9 +98,6 @@ typedef struct vulktex_s { typedef struct regtexset_s DARRAY_TYPE (vulktex_t *) regtexset_t; -typedef struct bsp_texset_s - DARRAY_TYPE (bsp_tex_t) bsp_texset_t; - typedef struct bsp_draw_s { uint32_t tex_id; uint32_t inst_id; @@ -123,8 +139,9 @@ typedef struct bsp_pass_s { regtexset_t *textures; int num_queues; bsp_drawset_t *draw_queues; - uint32_t inst_id; + uint32_t inst_id; bsp_instance_t *instances; + int ent_frame; } bsp_pass_t; typedef struct bspvert_s { @@ -172,6 +189,8 @@ typedef struct bspctx_s { struct qfv_tex_s *skybox_tex; VkDescriptorSet skybox_descriptor; + vulktex_t notexture; + quat_t default_color; quat_t last_color; @@ -182,6 +201,9 @@ typedef struct bspctx_s { bsp_face_t *faces; uint32_t *poly_indices; + texdata_t texdata; + int anim_index; + int model_id; bsp_pass_t main_pass; // camera view depth, gbuffer, etc diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 7a83fe7cd..070cb3874 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -120,8 +120,14 @@ Vulkan_ClearElements (vulkan_ctx_t *ctx) static inline void chain_surface (const bsp_face_t *face, bsp_pass_t *pass, bspctx_t *bctx) { - - DARRAY_APPEND (&pass->face_queue[face->tex_id], + int ent_frame = pass->ent_frame; + // if the texture has no alt animations, anim_alt holds the sama data + // as anim_main + texanim_t *anim = ent_frame ? &bctx->texdata.anim_alt[face->tex_id] + : &bctx->texdata.anim_main[face->tex_id]; + int anim_ind = (bctx->anim_index + anim->offset) % anim->count; + int tex_id = bctx->texdata.anim_map[anim->base + anim_ind]; + DARRAY_APPEND (&pass->face_queue[tex_id], ((instface_t) { pass->inst_id, face - bctx->faces })); } @@ -157,15 +163,13 @@ clear_textures (vulkan_ctx_t *ctx) void Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) { - int i; - model_t *m; mod_brush_t *brush = &r_refdef.worldmodel->brush; clear_textures (ctx); add_texture (r_notexture_mip, ctx); register_textures (brush, ctx); - for (i = 0; i < num_models; i++) { - m = models[i]; + for (int i = 0; i < num_models; i++) { + model_t *m = models[i]; if (!m) continue; // sub-models are done as part of the main model @@ -181,6 +185,74 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) bspctx_t *bctx = ctx->bsp_context; int num_tex = bctx->registered_textures.size; + + texture_t **textures = alloca (num_tex * sizeof (texture_t *)); + textures[0] = r_notexture_mip; + for (int i = 0, t = 1; i < num_models; i++) { + model_t *m = models[i]; + // sub-models are done as part of the main model + if (!m || *m->path == '*') { + continue; + } + brush = &m->brush; + for (unsigned j = 0; j < brush->numtextures; j++) { + if (brush->textures[j]) { + textures[t++] = brush->textures[j]; + } + } + } + + size_t texdata_size = 2.5 * num_tex * sizeof (texanim_t); + texanim_t *texdata = Hunk_AllocName (0, texdata_size, "texdata"); + bctx->texdata.anim_main = texdata; + bctx->texdata.anim_alt = texdata + num_tex; + bctx->texdata.anim_map = (uint16_t *) (texdata + 2 * num_tex); + int16_t map_index = 0; + for (int i = 0; i < num_tex; i++) { + texanim_t *anim = bctx->texdata.anim_main + i; + if (anim->count) { + // already done as part of an animation group + continue; + } + *anim = (texanim_t) { .base = map_index, .offset = 0, .count = 1 }; + bctx->texdata.anim_map[anim->base] = i; + + if (textures[i]->anim_total > 1) { + // bsp loader multiplies anim_total by ANIM_CYCLE to slow the + // frame rate + anim->count = textures[i]->anim_total / ANIM_CYCLE; + texture_t *tx = textures[i]->anim_next; + for (int j = 1; j < anim->count; j++) { + if (!tx) { + Sys_Error ("broken cycle"); + } + vulktex_t *vtex = tx->render; + texanim_t *a = bctx->texdata.anim_main + vtex->tex_id; + if (a->count) { + Sys_Error ("crossed cycle"); + } + *a = *anim; + a->offset = j; + bctx->texdata.anim_map[a->base + a->offset] = vtex->tex_id; + tx = tx->anim_next; + } + if (tx != textures[i]) { + Sys_Error ("infinite cycle"); + } + }; + map_index += bctx->texdata.anim_main[i].count; + } + for (int i = 0; i < num_tex; i++) { + texanim_t *alt = bctx->texdata.anim_alt + i; + if (textures[i]->alternate_anims) { + texture_t *tx = textures[i]->alternate_anims; + vulktex_t *vtex = tx->render; + *alt = bctx->texdata.anim_main[vtex->tex_id]; + } else { + *alt = bctx->texdata.anim_main[i]; + } + } + bctx->main_pass.face_queue = malloc (num_tex * sizeof (bsp_instfaceset_t)); for (int i = 0; i < num_tex; i++) { bctx->main_pass.face_queue[i] @@ -398,7 +470,8 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) bsp_model_t *m = &bctx->models[models[i]->render_id]; m->first_face = face_base + models[i]->brush.firstmodelsurface; m->face_count = models[i]->brush.nummodelsurfaces; - while (models[i + 1] && models[i + 1]->path[0] == '*') { + while (i < num_models - 1 && models[i + 1] + && models[i + 1]->path[0] == '*') { i++; m = &bctx->models[models[i]->render_id]; m->first_face = face_base + models[i]->brush.firstmodelsurface; @@ -529,6 +602,7 @@ R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx) return 0; } + pass->ent_frame = e->animation.frame & 1; pass->inst_id = model->render_id; if (!pass->instances[model->render_id].entities.size) { bsp_model_t *m = &bctx->models[model->render_id]; @@ -902,7 +976,7 @@ queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe) size_t dq_size = pass->draw_queues[dq].size; bsp_draw_t *draw = &pass->draw_queues[dq].a[dq_size - 1]; if (!pass->draw_queues[dq].size - || draw->tex_id != f.tex_id + || draw->tex_id != i || draw->inst_id != is.inst_id) { bsp_instance_t *instance = &pass->instances[is.inst_id]; DARRAY_APPEND (&pass->draw_queues[dq], ((bsp_draw_t) { @@ -967,6 +1041,8 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bctx->main_pass.entid_data = bframe->entid_data; bctx->main_pass.entid_count = 0; + bctx->anim_index = r_data->realtime * 5; + clear_queues (bctx, &bctx->main_pass); // do this first for water and skys bframe->index_count = 0; @@ -981,6 +1057,7 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) Vulkan_Scene_AddEntity (ctx, &worldent); int world_id = worldent.renderer.model->render_id; + bctx->main_pass.ent_frame = 0; // world is always frame 0 bctx->main_pass.inst_id = world_id; DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, worldent.renderer.render_id); From 45b3ef79c8b1cd5288871309714d3b91069c66ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 May 2022 12:21:50 +0900 Subject: [PATCH 2877/3664] [model] Trim decompressed vis sets I had been trimming for the solid leaf, but not the empty leafs. I had assumed the vis tool would trim the bits, but it seems to not be reliable (though it could be a bug in qfvis, I think the map in question is one of my test maps). --- libs/models/brush/model_brush.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 377e871f4..7037710d3 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -153,13 +153,13 @@ Mod_LeafPVS (const mleaf_t *leaf, const model_t *model) static set_t *novis; static set_t *decompressed; unsigned numvis = model->brush.visleafs; + unsigned excess = SET_SIZE (numvis) - numvis; if (leaf == model->brush.leafs) { if (!novis) { novis = set_new_size (numvis); } if (!novis->map[0] || SET_SIZE (numvis) > novis->size) { - unsigned excess = SET_SIZE (numvis) - numvis; set_expand (novis, numvis); memset (novis->map, 0xff, SET_WORDS (novis) * sizeof (*novis->map)); @@ -173,6 +173,7 @@ Mod_LeafPVS (const mleaf_t *leaf, const model_t *model) set_expand (decompressed, numvis); Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, 0xff, decompressed); + decompressed->map[SET_WORDS (decompressed) - 1] &= (~SET_ZERO) >> excess; return decompressed; } @@ -181,14 +182,16 @@ Mod_LeafPVS_set (const mleaf_t *leaf, const model_t *model, byte defvis, set_t *out) { unsigned numvis = model->brush.visleafs; + unsigned excess = SET_SIZE (numvis) - numvis; + set_expand (out, numvis); if (leaf == model->brush.leafs) { - unsigned excess = SET_SIZE (numvis) - numvis; memset (out->map, defvis, SET_WORDS (out) * sizeof (*out->map)); out->map[SET_WORDS (out) - 1] &= (~SET_ZERO) >> excess; return; } Mod_DecompressVis_set (leaf->compressed_vis, &model->brush, defvis, out); + out->map[SET_WORDS (out) - 1] &= (~SET_ZERO) >> excess; } VISIBLE void @@ -196,9 +199,10 @@ Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, set_t *out) { unsigned numvis = model->brush.visleafs; + unsigned excess = SET_SIZE (numvis) - numvis; + set_expand (out, numvis); if (leaf == model->brush.leafs) { - unsigned excess = SET_SIZE (numvis) - numvis; byte *o = (byte *) out->map; for (int i = SET_WORDS (out) * sizeof (*out->map); i-- > 0; ) { *o++ |= defvis; @@ -207,6 +211,7 @@ Mod_LeafPVS_mix (const mleaf_t *leaf, const model_t *model, byte defvis, return; } Mod_DecompressVis_mix (leaf->compressed_vis, &model->brush, defvis, out); + out->map[SET_WORDS (out) - 1] &= (~SET_ZERO) >> excess; } // BRUSHMODEL LOADING ========================================================= From 9166b08b067380d96d99b900f6a7a3cb070f669f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jun 2022 11:54:53 +0900 Subject: [PATCH 2878/3664] [sound] Move sfx_t definition into snd_internal.h I always wanted it there, there were dependency issues at the time. I guess they got cleaned up for the most part since then (other than cd_file, but it's on my hit-list). --- include/QF/sound.h | 24 ------------------------ include/snd_internal.h | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/include/QF/sound.h b/include/QF/sound.h index dc051f193..62e80d115 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -42,30 +42,6 @@ struct transform_s; */ ///@{ typedef struct sfx_s sfx_t; -struct sfx_s -{ - struct snd_s *snd; //!< ownding snd_t instance - const char *name; - sfx_t *owner; - - unsigned int length; - unsigned int loopstart; - - union { - struct sfxstream_s *stream; - struct sfxblock_s *block; - } data; - - struct sfxbuffer_s *(*touch) (sfx_t *sfx); - struct sfxbuffer_s *(*retain) (sfx_t *sfx); - void (*release) (sfx_t *sfx); - - struct sfxbuffer_s *(*getbuffer) (sfx_t *sfx); - struct wavinfo_s *(*wavinfo) (sfx_t *sfx); - - sfx_t *(*open) (sfx_t *sfx); - void (*close) (sfx_t *sfx); -}; ///@} /** \defgroup sound_init Initialization functions diff --git a/include/snd_internal.h b/include/snd_internal.h index e9558e95e..ba713ce7c 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -52,6 +52,32 @@ typedef struct channel_s channel_t; typedef struct sfxbuffer_s sfxbuffer_t; typedef struct sfxblock_s sfxblock_t; typedef struct sfxstream_s sfxstream_t; + +struct sfx_s +{ + struct snd_s *snd; //!< ownding snd_t instance + const char *name; + sfx_t *owner; + + unsigned int length; + unsigned int loopstart; + + union { + struct sfxstream_s *stream; + struct sfxblock_s *block; + } data; + + struct sfxbuffer_s *(*touch) (sfx_t *sfx); + struct sfxbuffer_s *(*retain) (sfx_t *sfx); + void (*release) (sfx_t *sfx); + + struct sfxbuffer_s *(*getbuffer) (sfx_t *sfx); + struct wavinfo_s *(*wavinfo) (sfx_t *sfx); + + sfx_t *(*open) (sfx_t *sfx); + void (*close) (sfx_t *sfx); +}; + /** paint samples into the mix buffer \param offset offset into the mix buffer at which to start mixing the channel From 3293fcaab0e7d782721c650a5c7f534dd7a91f06 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jun 2022 12:04:27 +0900 Subject: [PATCH 2879/3664] [sys] Add some developer flags for cache/hunk/zone And make Sys_MaskPrintf take the developer enum rather than just a raw int. It was actually getting some nasty hunk corruption errors when under memory pressure that made it clear the sound system needs some work. --- include/QF/sys.h | 8 ++++---- include/QF/sys_developer.h | 3 +++ libs/util/sys.c | 2 +- libs/util/zone.c | 21 +++++++++++---------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index dde61872b..efe621f5d 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -87,8 +87,6 @@ int64_t Sys_TimeBase (void) __attribute__ ((const)); double Sys_DoubleTimeBase (void) __attribute__ ((const)); void Sys_TimeOfDay(date_t *date); -void Sys_MaskPrintf (int mask, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); - #define SYS_DEVELOPER(developer) SYS_DeveloperID_##developer, enum { #include "QF/sys_developer.h" @@ -97,10 +95,12 @@ enum { // bit 0 so developer 1 will pick it up #define SYS_DEVELOPER(developer) \ SYS_##developer = (SYS_dev | (1 << (SYS_DeveloperID_##developer + 1))), -enum { +typedef enum { SYS_dev = 1, #include "QF/sys_developer.h" -}; +} sys_developer_e; + +void Sys_MaskPrintf (sys_developer_e mask, const char *fmt, ...) __attribute__((format(PRINTF,2,3))); struct qf_fd_set; int Sys_Select (int maxfd, struct qf_fd_set *fdset, int64_t usec); diff --git a/include/QF/sys_developer.h b/include/QF/sys_developer.h index 881742430..073f753d8 100644 --- a/include/QF/sys_developer.h +++ b/include/QF/sys_developer.h @@ -30,6 +30,9 @@ #endif SYS_DEVELOPER (warn) +SYS_DEVELOPER (cache) +SYS_DEVELOPER (hunk) +SYS_DEVELOPER (zone) SYS_DEVELOPER (vid) SYS_DEVELOPER (input) SYS_DEVELOPER (fs_nf) diff --git a/libs/util/sys.c b/libs/util/sys.c index f5ebfded5..e08557c81 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -353,7 +353,7 @@ Sys_Printf (const char *fmt, ...) } VISIBLE void -Sys_MaskPrintf (int mask, const char *fmt, ...) +Sys_MaskPrintf (sys_developer_e mask, const char *fmt, ...) { va_list args; diff --git a/libs/util/zone.c b/libs/util/zone.c index 0341af421..1d2c63b24 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -222,7 +222,7 @@ Z_TagMalloc (memzone_t *zone, size_t size, int tag) int requested_size = size; memblock_t *start, *rover, *new, *base; - if (developer & SYS_dev) + if (developer & SYS_zone) Z_CheckHeap (zone); // DEBUG if (!tag) { @@ -291,7 +291,7 @@ Z_Realloc (memzone_t *zone, void *ptr, size_t size) if (!ptr) return Z_Malloc (zone, size); - if (developer & SYS_dev) + if (developer & SYS_zone) Z_CheckHeap (zone); // DEBUG block = (memblock_t *) ((byte *) ptr - sizeof (memblock_t)); @@ -821,7 +821,7 @@ Cache_Move (cache_system_t *c) // we are clearing up space at the bottom, so allocate it late new = Cache_TryAlloc (hunk, c->size, true); if (new) { - Sys_MaskPrintf (SYS_dev, "cache_move ok\n"); + Sys_MaskPrintf (SYS_cache, "cache_move ok\n"); memcpy (new + 1, c + 1, c->size - sizeof (cache_system_t)); new->user = c->user; @@ -829,7 +829,7 @@ Cache_Move (cache_system_t *c) Cache_Free (c->user); new->user->data = (void *) (new + 1); } else { - Sys_MaskPrintf (SYS_dev, "cache_move failed\n"); + Sys_MaskPrintf (SYS_cache, "cache_move failed\n"); Cache_Free (c->user); // tough luck... } @@ -1122,7 +1122,7 @@ Cache_Free (cache_user_t *c) Sys_Error ("Cache_Free: attempt to free locked block"); const int sz = sizeof (cs->name); - Sys_MaskPrintf (SYS_dev, "Cache_Free: freeing '%.*s' %p\n", + Sys_MaskPrintf (SYS_cache, "Cache_Free: freeing '%.*s' %p\n", sz, cs->name, cs); Cache_UnlinkLRU (cs); @@ -1195,16 +1195,17 @@ Cache_Alloc (cache_user_t *c, size_t size, const char *name) static void Cache_Report_r (memhunk_t *hunk) { - if (!hunk) { hunk = global_hunk; } //FIXME clean up callers - Sys_MaskPrintf (SYS_dev, "%4.1f megabyte data cache\n", - (hunk->size - hunk->high_used - - hunk->low_used) / (float) (1024 * 1024)); + Sys_Printf ("%4.1f megabyte data cache\n", + (hunk->size - hunk->high_used - + hunk->low_used) / (float) (1024 * 1024)); } VISIBLE void Cache_Report (void) { - Cache_Report_r (global_hunk); + if (developer & SYS_cache) { + Cache_Report_r (global_hunk); + } } VISIBLE void From 0ebb0717b0e99016561f5c026709f80dce249730 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jun 2022 12:17:34 +0900 Subject: [PATCH 2880/3664] [zone] Add failing test cases The tests fail as they exercise how the cache *SHOULD* work rather than how it does now. The tests do currently pass for the pending work I've done on the cache system, but while working on it, I remembered why I reworked cache allocation... The essential problem is that sounds are loaded into the cache, which is fine for synchronous output targets, but has proven to be a minefield for asynchronous output targets (JACK, ALSA). The reason for the minefield is the hunk takes priority over the cache, and is free to move cache blocks around, and *even dispose of them entirely* in order to satisfy memory allocations from either end of the hunk. Doing this in an entirely single-threaded process (as DOS Quake was) is perfectly safe, as the users of the cache just reload the pointer each time, and bail if it's null (meaning the block has been freed), or even cause the data to be reloaded if possible (I'm a little fuzzy on the details for that as I didn't write that code). However, in multi-threaded code, especially real-time (JACK, possibly ALSA), it's a recipe for disaster. The 4cab5b90e6379 commit was a (mostly) successful attempt to mitigate the problem by allocating the cache blocks from the high-hunk (thus minimizing any movement caused by low-hunk allocations), it resulted in cache allocates and regular high-hunk allocations somehow getting intertwined: while investigating just how much memory ad_tears needs (somewhere between 192MB and 256MB), I got "trashed sentinel" errors and upon investigation, I found what looks very suspiciously like audio data written across a hunk control block. I've decided that the cache allocation *algorithm* should be reverted to how it was originally designed by Id (details will remain "modern"), but while working on the tests, I remembered why I had done the changes in the first place (above story). Thus the work on reverting the cache allocation can't go in until I get sound memory management independent of the cache. The tests are going in now so I have a constant reminder :) --- libs/util/test/Makemodule.am | 7 +- libs/util/test/test-zone.c | 217 +++++++++++++++++++++++++++++++++++ libs/util/zone.c | 2 +- 3 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 libs/util/test/test-zone.c diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 7fa5a5f98..1272b7242 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -23,7 +23,8 @@ libs_util_tests = \ libs/util/test/test-seg \ libs/util/test/test-set \ libs/util/test/test-simd \ - libs/util/test/test-utf8 + libs/util/test/test-utf8 \ + libs/util/test/test-zone TESTS += $(libs_util_tests) @@ -128,3 +129,7 @@ libs_util_test_test_simd_DEPENDENCIES=libs/util/libQFutil.la libs_util_test_test_utf8_SOURCES=libs/util/test/test-utf8.c libs_util_test_test_utf8_LDADD=libs/util/libQFutil.la libs_util_test_test_utf8_DEPENDENCIES=libs/util/libQFutil.la + +libs_util_test_test_zone_SOURCES=libs/util/test/test-zone.c +libs_util_test_test_zone_LDADD=libs/util/libQFutil.la +libs_util_test_test_zone_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-zone.c b/libs/util/test/test-zone.c new file mode 100644 index 000000000..2fecd0218 --- /dev/null +++ b/libs/util/test/test-zone.c @@ -0,0 +1,217 @@ +#define PARANOID +#include "../zone.c" + +static int +check_hunk_block (const memhunk_t *hunk, const void *mem, size_t size) +{ + const hunkblk_t *h = (const hunkblk_t *) mem - 1; + if (h->sentinal1 != HUNK_SENTINAL || h->sentinal2 != HUNK_SENTINAL) { + printf ("invalid sentinals: %u %u\n", h->sentinal1, h->sentinal2); + return 1; + } + if (h->size % HUNK_ALIGN) { + printf ("block size misaligned: %zd %zd\n", + h->size, h->size % HUNK_ALIGN); + return 1; + } + if (h->size - sizeof (hunkblk_t) < size) { + printf ("block size too small: %zd %zd\n", + h->size - sizeof (hunkblk_t), size); + return 1; + } + if (h->size - sizeof (hunkblk_t) - size >= HUNK_ALIGN) { + printf ("block size too small: %zd %d\n", + h->size - sizeof (hunkblk_t) - size, HUNK_ALIGN); + return 1; + } + if ((byte *) h < hunk->base + || (byte *) h + h->size > hunk->base + hunk->size) { + printf ("block outside of hunk: %p %p, %p %p\n", + h, hunk->base, (byte *) h + h->size, hunk->base + hunk->size); + return 1; + } + size_t offset = (byte *) h - hunk->base; + if (offset < hunk->size - hunk->high_used + && offset + h->size > hunk->low_used) { + printf ("block in unallocated region: %zd %zd, %zd %zd\n", + offset, offset + h->size, + hunk->low_used, hunk->size - hunk->high_used); + return 1; + } + return 0; +} + +static int +check_cache_block (const memhunk_t *hunk, const void *c, size_t size) +{ + if (!c) { + printf ("cache block is null\n"); + return 1; + } + + const cache_system_t *cs = (cache_system_t *) c - 1; + + size_t hunk_high = hunk->size - hunk->high_used; + size_t offset = (byte *) cs - hunk->base; + if (offset < hunk->low_used || offset + cs->size > hunk_high) { + printf ("cache block in hunk stack: %zd %zd, %zd, %zd\n", + offset, offset + cs->size, hunk->low_used, hunk_high); + return 1; + } + return 0; +} + +static int +check_cache_order (memhunk_t *hunk) +{ + uint32_t ci; + cache_system_t *c; + int ret = 0; + + cache_system_t *first = cs_ptr (hunk, hunk->cache_head[0].next); + cache_system_t *last = cs_ptr (hunk, hunk->cache_head[0].prev); + + if (first->prev) { + printf ("first cache block does not point back to head: %u\n", + first->prev); + } + if (last->next) { + printf ("last cache block does not point forward to head: %u\n", + last->next); + } + if (first->prev || last->next) { + exit (1); // unsafe to continue + } + uint32_t prev = 0; + for (ci = hunk->cache_head[0].next; ci; prev = ci, ci = c->next) { + c = cs_ptr (hunk, ci); + if ((byte *) c + c->size > hunk->base + hunk->size) { + printf ("cache block outside of hunk (from %u)\n", prev); + exit (1); + } + if (c->readlock) { + printf ("look in cache detected at %u\n", ci); + exit (1); + } + c->readlock = 1; + if (c->next && c->next < ci) { + printf ("cache block sequence incorrect %u -> %u\n", prev, ci); + ret |= 1; + } + } + return ret; +} + +int +main (int argc, const char **argv) +{ + int ret = 0; + + if (sizeof (memhunk_t) != 128) { + ret = 1; + printf ("memhunk_t not 128 bytes: %zd\n", sizeof (memhunk_t)); + } + if (sizeof (hunkblk_t) != 64) { + ret = 1; + printf ("hunkblk_t not 64 bytes: %zd\n", sizeof (memhunk_t)); + } + size_t memsize = 64 * 1024; + void *hunk_mem = Sys_Alloc (memsize); + if ((intptr_t) hunk_mem & 63) { + // (not really part of test, but relied upon) should be 4k + // aligned, but doesn't matter for the tests + printf ("Sys_Alloc returned unaligned memory"); + ret = 1; + } + memhunk_t *hunk = Hunk_Init (hunk_mem, memsize); + if ((void *) hunk != hunk_mem) { + ret = 1; + printf ("hunk moved\n"); + } + if ((void *) hunk->base != (void *)&hunk[1]) { + ret = 1; + printf ("hunk->base does not point to beginning of hunk space\n"); + } + if (hunk->size != memsize - sizeof (memhunk_t)) { + ret = 1; + printf ("hunk size not memsize - sizeof (memhunk_t) (%zd - %zd): %zd\n", + memsize, sizeof (memhunk_t), hunk->size); + } + if (hunk->low_used || hunk->high_used) { + ret = 1; + printf ("hunk low and high used not 0: %zd %zd\n", + hunk->low_used, hunk->high_used); + } + if (hunk->tempmark || hunk->tempactive) { + ret = 1; + printf ("hunk tempmark tempactive not 0: %zd %d\n", + hunk->tempmark, hunk->tempactive); + } + if (ret) { + // no point continuing + return 1; + } + + size_t low_mark = Hunk_LowMark (hunk); + if (low_mark != 0) { + ret = 1; + printf ("initial hunk low mark not 0: %zd\n", low_mark); + } + size_t size = 1024; + void *low = Hunk_AllocName (hunk, size, "low test"); + ret |= check_hunk_block (hunk, low, size); + if (low > (void *) (hunk->base + sizeof (hunkblk_t))) { + ret = 1; + printf ("low memory not at beginning of hunk: %p %p\n", + low, hunk->base + sizeof (hunkblk_t)); + } + + size_t high_mark = Hunk_HighMark (hunk); + if (high_mark != 0) { + ret = 1; + printf ("initial hunk high mark not 0: %zd\n", high_mark); + } + void *high = Hunk_HighAlloc (hunk, size);//FIXME, "high test"); + ret |= check_hunk_block (hunk, high, size); + if (high + size < (void *) (hunk->base + hunk->size)) { + ret = 1; + printf ("high memory not at end of hunk: %p %p\n", + high + size, hunk->base + hunk->size); + } + + global_hunk = hunk;//FIXME put hunk in cache_user_t ? + cache_user_t cu = {}; + void *cm = Cache_Alloc (&cu, 512, "cache test"); + ret |= check_cache_block (hunk, cm, 512); + + size_t mark = Hunk_LowMark (hunk); + void *low2 = Hunk_AllocName (hunk, 61 * 1024, "low test 2"); + ret |= check_hunk_block (hunk, low2, 61 * 1024); + if (cm == Cache_Check (&cu)) { + ret = 1; + printf ("cache block was not moved\n"); + } + cm = Cache_Check (&cu); + ret |= check_cache_block (hunk, cm, 512); + Hunk_FreeToLowMark (hunk, mark); + if (cm != Cache_Check (&cu)) { + ret = 1; + printf ("cache block was moved\n"); + } + + void *high2 = Hunk_HighAlloc (hunk, 2 * 1024); + ret |= check_hunk_block (hunk, high2, 2 * 1024); + if (cm == Cache_Check (&cu)) { + ret = 1; + printf ("cache block was not moved\n"); + } + cm = Cache_Check (&cu); + ret |= check_cache_block (hunk, cm, 512); + printf ("%zd %zd %zd\n", hunk->low_used, hunk->size - hunk->high_used, + (byte *) cm - hunk->base); + check_cache_order (hunk); + Hunk_Print(hunk, 1); + Cache_Print (); + + return ret; +} diff --git a/libs/util/zone.c b/libs/util/zone.c index 1d2c63b24..3d68a037e 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -616,7 +616,7 @@ Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) hunkblk_t *h; #ifdef PARANOID - Hunk_Check (); + Hunk_Check (hunk); #endif size = sizeof (hunkblk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); From 1f16f875f68daa9f5409a2171b74eefc3d3d67e4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jun 2022 15:20:41 +0900 Subject: [PATCH 2881/3664] [sound] Clean up the public API sfx_t is now private, and cd_file no longer accesses channel_t's internals. This is necessary for hiding the code needed to make mixing and channel management *properly* lock-free (I've been getting away with murder thanks to x86's strong memory model and just plain luck with gcc). --- include/QF/plugin/snd_render.h | 7 +++- include/QF/sound.h | 25 ++++++++++++-- include/snd_internal.h | 7 ++-- libs/audio/cd_file.c | 37 +++++++------------- libs/audio/renderer/snd_dma.c | 63 ++++++++++++++++++++++++++++++++-- libs/audio/snd.c | 51 ++++++++++++++++++++++++--- 6 files changed, 152 insertions(+), 38 deletions(-) diff --git a/include/QF/plugin/snd_render.h b/include/QF/plugin/snd_render.h index 8d88163c2..ae96764be 100644 --- a/include/QF/plugin/snd_render.h +++ b/include/QF/plugin/snd_render.h @@ -44,7 +44,12 @@ typedef struct snd_render_funcs_s { void (*stop_sound) (int entnum, int entchannel); struct channel_s *(*alloc_channel) (void); - void (*channel_stop) (struct channel_s *chan); + void (*channel_free) (struct channel_s *chan); + int (*channel_set_sfx) (struct channel_s *chan, struct sfx_s *sfx); + void (*channel_set_paused) (struct channel_s *chan, int paused); + void (*channel_set_looping) (struct channel_s *chan, int looping); + enum chan_state_e (*channel_get_state) (struct channel_s *chan); + void (*channel_set_volume) (struct channel_s *chan, float volume); struct sfx_s *(*precache_sound) (const char *sample); struct sfx_s *(*load_sound) (const char *name); diff --git a/include/QF/sound.h b/include/QF/sound.h index 62e80d115..183ddaede 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -42,6 +42,15 @@ struct transform_s; */ ///@{ typedef struct sfx_s sfx_t; +typedef struct channel_s channel_t; + +typedef enum chan_state_e { + chan_invalid, //!< Channel is in an invalid state and must not be used + chan_pending, //!< Channel is waiting to be initialized + chan_done, //!< Channel is done and should be freed + chan_paused, //!< Channel is paused but can be resumed at any time + chan_playing, //!< Channel is currently playing +} chan_state; ///@} /** \defgroup sound_init Initialization functions @@ -138,12 +147,24 @@ sfx_t *S_LoadSound (const char *name); /** Allocate a sound channel that can be used for playing sounds. */ -struct channel_s *S_AllocChannel (void); +channel_t *S_AllocChannel (void); /** Stop and safely free a channel. \param chan channel to stop */ -void S_ChannelStop (struct channel_s *chan); +void S_ChannelFree (channel_t *chan); + +int S_ChannelSetSfx (channel_t *chan, sfx_t *sfx); +void S_ChannelSetPaused (channel_t *chan, int paused); +void S_ChannelSetLooping (channel_t *chan, int looping); +chan_state S_ChannelGetState (channel_t *chan); + +/** Set a channel's volume. + \param chan The channel for which the volume will be set. + \param volume The overall playback volume of the channel: set to 0 for + silence, 1 for full volume. +*/ +void S_ChannelSetVolume (channel_t *chan, float volume); /** Start a sound local to the client view. \param s name of sound to play diff --git a/include/snd_internal.h b/include/snd_internal.h index ba713ce7c..e8bcb7484 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -48,7 +48,6 @@ struct transform_s; typedef struct portable_samplepair_s portable_samplepair_t; typedef struct snd_s snd_t; typedef struct wavinfo_s wavinfo_t; -typedef struct channel_s channel_t; typedef struct sfxbuffer_s sfxbuffer_t; typedef struct sfxblock_s sfxblock_t; typedef struct sfxstream_s sfxstream_t; @@ -224,7 +223,7 @@ struct sfxblock_s { /** Representation of a sound being played. */ struct channel_s { - struct channel_s *next; //!< next channel in "free" list + channel_t *next; //!< next channel in "free" list sfx_t *sfx; //!< sound played by this channel int leftvol; //!< 0-255 volume int rightvol; //!< 0-255 volume @@ -250,7 +249,7 @@ struct channel_s { can be reused at any time. */ //@{ - int stop; + int stop; int done; //@} }; @@ -342,7 +341,7 @@ extern int snd_total_channels; //!< number of active channels /** Allocate a sound channel that can be used for playing sounds. \param snd sound system state */ -struct channel_s *SND_AllocChannel (snd_t *snd); +channel_t *SND_AllocChannel (snd_t *snd); /** Stop a channel from playing. \param snd sound system state diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index 401c6b59a..26854e244 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -65,7 +65,6 @@ #include "QF/plugin/cd.h" #include "compat.h" -#include "snd_internal.h" /* Generic plugin structures */ static general_data_t plugin_info_general_data; @@ -107,11 +106,8 @@ static cvar_t mus_ogglist_cvar = { static void set_volume (void) { - if (cd_channel && cd_channel->sfx) { - int vol = bgmvolume * 255; - - cd_channel->master_vol = vol; - cd_channel->leftvol = cd_channel->rightvol = cd_channel->master_vol; + if (cd_channel) { + S_ChannelSetVolume (cd_channel, bgmvolume); } } @@ -136,7 +132,7 @@ I_OGGMus_Stop (void) wasPlaying = false; if (cd_channel) { - S_ChannelStop (cd_channel); + S_ChannelFree (cd_channel); cd_channel = NULL; } } @@ -235,8 +231,7 @@ static void I_OGGMus_PlayNext (int looping) { const char *track; - sfx_t *cd_sfx, *sfx; - wavinfo_t *info = 0; + sfx_t *sfx; if (!play_list) return; @@ -252,29 +247,21 @@ I_OGGMus_PlayNext (int looping) } if (cd_channel) { - S_ChannelStop (cd_channel); + S_ChannelFree (cd_channel); cd_channel = 0; } if (!(cd_channel = S_AllocChannel ())) return; - if (!(cd_sfx = S_LoadSound (track)) || !(sfx = cd_sfx->open (cd_sfx))) { - S_ChannelStop (cd_channel); + if (!(sfx = S_LoadSound (track)) || !S_ChannelSetSfx (cd_channel, sfx)) { + S_ChannelFree (cd_channel); cd_channel = 0; return; } - Sys_Printf ("Playing: %s.\n", track); - if (sfx->wavinfo) - info = sfx->wavinfo (sfx); - if (info) { - if (looping == true) - info->loopstart = 0; - else - info->loopstart = -1; - } - cd_channel->sfx = sfx; + S_ChannelSetLooping (cd_channel, looping ? 1 : -1); set_volume (); + Sys_Printf ("Playing: %s.\n", track); playing = true; } @@ -286,7 +273,7 @@ I_OGGMus_Pause (void) return; if (cd_channel) - cd_channel->pause = 1; + S_ChannelSetPaused (cd_channel, 1); wasPlaying = playing; playing = false; @@ -299,7 +286,7 @@ I_OGGMus_Resume (void) return; set_volume (); - cd_channel->pause = 0; + S_ChannelSetPaused (cd_channel, 0); wasPlaying = false; playing = true; } @@ -446,7 +433,7 @@ I_OGG_f (void) static void I_OGGMus_Update (void) { - if (!cd_channel || !cd_channel->done) + if (!cd_channel || S_ChannelGetState (cd_channel) > chan_done) return; // will get here only when multi-tracked I_OGGMus_Stop (); diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 0ec153d03..a201e61b1 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -465,13 +465,67 @@ s_load_sound (const char *name) } static void -s_channel_stop (channel_t *chan) +s_channel_free (channel_t *chan) { if (!sound_started) return; SND_ChannelStop (&snd, chan); } +static int +s_channel_set_sfx (channel_t *chan, sfx_t *sfx) +{ + sfx_t *s = sfx->open (sfx); + if (!s) { + return 0; + } + chan->sfx = s; + return 1; +} + +static void +s_channel_set_paused (channel_t *chan, int paused) +{ + chan->pause = paused != 0; +} + +static void +s_channel_set_looping (channel_t *chan, int looping) +{ + // FIXME implement +} + +static chan_state +s_channel_get_state (channel_t *chan) +{ + // stop means the channel has been "freed" and is waiting for the mixer + // thread to be done with it, thus putting the channel in an invalid state + // from the user's point of view. ie, don't touch (user should set channel + // pointer to null). + if (!chan->stop) { + if (chan->done) { + // The mixer has finished mixing the channel (come to the end). + return chan_done; + } + if (!chan->sfx) { + // channel requires initialization + return chan_pending; + } + if (chan->pause) { + return chan_paused; + } + return chan_playing; + } + return chan_invalid; +} + +static void +s_channel_set_volume (channel_t *chan, float volume) +{ + chan->master_vol = volume * 256; //FIXME + chan->leftvol = chan->rightvol = chan->master_vol; +} + static void s_local_sound (const char *sound) { @@ -506,7 +560,12 @@ static snd_render_funcs_t plugin_info_render_funcs = { .stop_sound = s_stop_sound, .alloc_channel = s_alloc_channel, - .channel_stop = s_channel_stop, + .channel_free = s_channel_free, + .channel_set_sfx = s_channel_set_sfx, + .channel_set_paused = s_channel_set_paused, + .channel_set_looping = s_channel_set_looping, + .channel_get_state = s_channel_get_state, + .channel_set_volume = s_channel_set_volume, .precache_sound = s_precache_sound, .load_sound = s_load_sound, diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 86ddda631..14b005ce7 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -229,7 +229,7 @@ S_LoadSound (const char *name) return 0; } -VISIBLE struct channel_s * +VISIBLE channel_t * S_AllocChannel (void) { if (snd_render_funcs) @@ -238,8 +238,51 @@ S_AllocChannel (void) } VISIBLE void -S_ChannelStop (struct channel_s *chan) +S_ChannelFree (channel_t *chan) { - if (snd_render_funcs) - snd_render_funcs->channel_stop (chan); + if (snd_render_funcs) { + snd_render_funcs->channel_free (chan); + } +} + +VISIBLE int +S_ChannelSetSfx (channel_t *chan, sfx_t *sfx) +{ + if (snd_render_funcs) { + return snd_render_funcs->channel_set_sfx (chan, sfx); + } + return 0; +} + +VISIBLE void +S_ChannelSetPaused (channel_t *chan, int paused) +{ + if (snd_render_funcs) { + snd_render_funcs->channel_set_paused (chan, paused); + } +} + +VISIBLE void +S_ChannelSetLooping (channel_t *chan, int looping) +{ + if (snd_render_funcs) { + snd_render_funcs->channel_set_looping (chan, looping); + } +} + +VISIBLE chan_state +S_ChannelGetState (channel_t *chan) +{ + if (snd_render_funcs) { + return snd_render_funcs->channel_get_state (chan); + } + return 0; +} + +VISIBLE void +S_ChannelSetVolume (channel_t *chan, float volume) +{ + if (snd_render_funcs) { + snd_render_funcs->channel_set_volume (chan, volume); + } } From 6c33fbb85075efdb5eb3eeae5f6376cf3779b622 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jun 2022 15:42:10 +0900 Subject: [PATCH 2882/3664] [nq] Move usercmd_t to protocol.h Removes the need for the server code to include client.h --- nq/include/client.h | 9 --------- nq/include/protocol.h | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/nq/include/client.h b/nq/include/client.h index 963b599a2..9aec5fed3 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -47,15 +47,6 @@ #include "protocol.h" -typedef struct usercmd_s { - vec3_t viewangles; - -// intended velocities - float forwardmove; - float sidemove; - float upmove; -} usercmd_t; - // client_state_t should hold all pieces of the client state typedef enum { diff --git a/nq/include/protocol.h b/nq/include/protocol.h index 2d9d6309d..d3bc67faf 100644 --- a/nq/include/protocol.h +++ b/nq/include/protocol.h @@ -225,4 +225,13 @@ #include "client/entities.h" // for entity_state_t +typedef struct usercmd_s { + vec3_t viewangles; + +// intended velocities + float forwardmove; + float sidemove; + float upmove; +} usercmd_t; + #endif // __protocol_h From e1a0bde5ee8208c8186df8a67c4aa109dde2c258 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jun 2022 15:43:53 +0900 Subject: [PATCH 2883/3664] [sound] Remove a pile of unwanted sound.h includes This does mean that the gl and sw renderers can no longer call S_ExtraUpdate, but really, they shouldn't be anyway. And I seem to remember it not really helping (been way too long since quake ran that slowly for me). --- libs/net/nm/net_dgrm.c | 2 ++ libs/video/renderer/gl/gl_mod_alias.c | 7 ------- libs/video/renderer/gl/gl_rmain.c | 11 ----------- libs/video/renderer/r_ent.c | 6 ------ libs/video/renderer/sw/draw.c | 8 -------- libs/video/renderer/sw/sw_redge.c | 5 ----- libs/video/renderer/sw/sw_rmain.c | 6 ------ nq/include/client.h | 1 - nq/include/server.h | 2 +- nq/source/cl_main.c | 1 + nq/source/cl_parse.c | 2 +- nq/source/host.c | 1 + nq/source/sv_ded.c | 1 + nq/source/sv_main.c | 3 +++ qw/source/sv_send.c | 1 - 15 files changed, 10 insertions(+), 47 deletions(-) diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 512fb6c7d..7004513cc 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -47,6 +47,8 @@ #include "netmain.h" +//FIXME these should not be here!!! +#include "../nq/include/client.h" #include "../nq/include/server.h" // This is enables a simple IP banning mechanism diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 7e28beea9..119d6b0c7 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -39,14 +39,7 @@ #include #include -#include "QF/cvar.h" -#include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/render.h" #include "QF/skin.h" -#include "QF/sound.h" -#include "QF/sys.h" -#include "QF/vid.h" #include "QF/scene/entity.h" diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index e6d0bd14c..3e3f082a8 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -39,16 +39,6 @@ #include #include -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/mathlib.h" -#include "QF/qargs.h" -#include "QF/render.h" -#include "QF/skin.h" -#include "QF/sound.h" -#include "QF/sys.h" -#include "QF/vid.h" - #include "QF/scene/entity.h" #include "QF/GL/defines.h" @@ -276,7 +266,6 @@ gl_R_RenderView (void) gl_Fog_EnableGFog (); gl_R_DrawWorld (); - S_ExtraUpdate (); // don't let sound get messed up if going slow gl_R_RenderDlights (); if (vr_data.view_model) { R_DrawViewModel (); diff --git a/libs/video/renderer/r_ent.c b/libs/video/renderer/r_ent.c index 6868a38ef..df5374e58 100644 --- a/libs/video/renderer/r_ent.c +++ b/libs/video/renderer/r_ent.c @@ -38,12 +38,6 @@ #include #include -#include "QF/model.h" -#include "QF/msg.h" -#include "QF/render.h" -#include "QF/sound.h" -#include "QF/sys.h" - #include "QF/scene/entity.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index ad09e6315..27568d82c 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -37,11 +37,7 @@ #include -#include "QF/cvar.h" -#include "QF/draw.h" #include "QF/quakefs.h" -#include "QF/sound.h" -#include "QF/sys.h" #include "QF/ui/view.h" #include "d_iface.h" @@ -779,8 +775,6 @@ Draw_FadeScreen (void) int width = vid.conview->xlen / 4; uint32_t *pbuf; - S_ExtraUpdate (); - for (y = 0; y < height; y++) { uint32_t mask; @@ -792,8 +786,6 @@ Draw_FadeScreen (void) } } vr_data.scr_copyeverything = 1; - - S_ExtraUpdate (); } void diff --git a/libs/video/renderer/sw/sw_redge.c b/libs/video/renderer/sw/sw_redge.c index 92499477a..339c98bcb 100644 --- a/libs/video/renderer/sw/sw_redge.c +++ b/libs/video/renderer/sw/sw_redge.c @@ -28,9 +28,6 @@ # include "config.h" #endif -#include "QF/render.h" -#include "QF/sound.h" - #include "d_ifacea.h" #include "r_internal.h" #include "vid_internal.h" @@ -520,8 +517,6 @@ R_ScanEdges (void) // flush the span list if we can't be sure we have enough spans left // for the next scan if (span_p > max_span_p) { - S_ExtraUpdate (); // don't let sound get messed up if going slow - if (r_drawculledpolys) R_DrawCulledPolys (); else diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index b75c7efae..7edac2b8d 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -41,12 +41,6 @@ #include #include "QF/cmd.h" -#include "QF/cvar.h" -#include "QF/mathlib.h" -#include "QF/render.h" -#include "QF/screen.h" -#include "QF/sound.h" -#include "QF/sys.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" diff --git a/nq/include/client.h b/nq/include/client.h index 9aec5fed3..33d0c0174 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -33,7 +33,6 @@ #include "QF/mathlib.h" #include "QF/model.h" #include "QF/quakefs.h" -#include "QF/sound.h" #include "QF/render.h" #include "client/chase.h" diff --git a/nq/include/server.h b/nq/include/server.h index 905c5c548..d22a9b331 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -35,7 +35,7 @@ #include "QF/quakeio.h" #include "QF/sizebuf.h" -#include "client.h" +#include "game.h" #include "netmain.h" #include "protocol.h" #include "sv_progs.h" diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index b3d74bd9a..39f3d06a1 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -45,6 +45,7 @@ #include "QF/render.h" #include "QF/screen.h" #include "QF/skin.h" +#include "QF/sound.h" #include "QF/sys.h" #include "QF/va.h" diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index b8c1df2b2..12defffa9 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -48,7 +48,7 @@ #include "QF/sys.h" #include "QF/screen.h" #include "QF/skin.h" -#include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_* +#include "QF/sound.h" #include "QF/va.h" #include "QF/scene/scene.h" diff --git a/nq/source/host.c b/nq/source/host.c index c0fe78167..f943a564a 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -45,6 +45,7 @@ #include "buildnum.h" +#include "nq/include/client.h" #include "nq/include/host.h" #include "nq/include/server.h" diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index 99e8cadc1..0b4e7b88d 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -38,6 +38,7 @@ #include "client/world.h" +#include "nq/include/client.h" #include "nq/include/host.h" #include "nq/include/server.h" diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 993f00cc1..32315d6f5 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -34,10 +34,13 @@ #include "QF/gib.h" #include "QF/msg.h" #include "QF/mathlib.h" +#include "QF/quakefs.h" #include "QF/set.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/simd/vec4f.h" + #include "compat.h" #include "world.h" diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index 112e9b7e8..71e03d593 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -44,7 +44,6 @@ #include "QF/dstring.h" #include "QF/msg.h" #include "QF/set.h" -#include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_* #include "QF/sys.h" #include "compat.h" From 5b38117689e717edce5ea82cd76fd0b314f29f50 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jun 2022 16:54:57 +0900 Subject: [PATCH 2884/3664] [sound] Make all volumes 0-1 (float) instead of 0-255 (int) The scaling up of the volumes when setting a channel's volume bothered me. The biggest issue being it hasn't been necessary for over a decade since the conversion to a float-mixer. Now the volume and attenuation scaling from protocol bytes is entirely in the client's hands. --- include/snd_internal.h | 6 ++-- libs/audio/renderer/snd_channels.c | 48 ++++++++++++++---------------- libs/audio/renderer/snd_dma.c | 4 +-- libs/audio/renderer/snd_mix.c | 36 +++++++++++----------- nq/source/cl_parse.c | 7 +++-- qw/source/cl_parse.c | 7 +++-- 6 files changed, 52 insertions(+), 56 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index e8bcb7484..93a08972a 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -225,8 +225,8 @@ struct sfxblock_s { struct channel_s { channel_t *next; //!< next channel in "free" list sfx_t *sfx; //!< sound played by this channel - int leftvol; //!< 0-255 volume - int rightvol; //!< 0-255 volume + float leftvol; //!< 0-1 volume + float rightvol; //!< 0-1 volume unsigned end; //!< end time in global paintsamples unsigned pos; //!< sample position in sfx unsigned looping; //!< where to loop, -1 = no looping @@ -235,7 +235,7 @@ struct channel_s { vec3_t origin; //!< origin of sound effect vec_t dist_mult; //!< distance multiplier (attenuation/clip) int pause; //!< don't update the channel at all - int master_vol; //!< 0-255 master volume + float volume; //!< 0-1 overall channel volume int phase; //!< phase shift between l-r in samples int oldphase; //!< phase shift between l-r in samples /** signal between main program and mixer thread that the channel is to be diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 66e9f19ab..8e7a68204 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -448,8 +448,8 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) ambient_channel++) { chan = ambient_channels[ambient_channel]; if (chan) { - chan->master_vol = 0; - chan->leftvol = chan->rightvol = chan->master_vol; + chan->volume = 0; + chan->leftvol = chan->rightvol = chan->volume; } } return; @@ -480,24 +480,23 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) // sfx will be written to chan->sfx later to ensure mixer doesn't use // channel prematurely. - vol = ambient_level * ambient_sound_level[ambient_channel]; - if (vol < 8) + vol = ambient_level * ambient_sound_level[ambient_channel] * (1/255.0); + if (vol < 8/255.0) vol = 0; // don't adjust volume too fast - if (chan->master_vol < vol) { - chan->master_vol += *snd_render_data.host_frametime - * ambient_fade; - if (chan->master_vol > vol) - chan->master_vol = vol; - } else if (chan->master_vol > vol) { - chan->master_vol -= *snd_render_data.host_frametime - * ambient_fade; - if (chan->master_vol < vol) - chan->master_vol = vol; + float fade = ambient_fade * (1/255.0); + if (chan->volume < vol) { + chan->volume += *snd_render_data.host_frametime * fade; + if (chan->volume > vol) + chan->volume = vol; + } else if (chan->volume > vol) { + chan->volume -= *snd_render_data.host_frametime * fade; + if (chan->volume < vol) + chan->volume = vol; } - chan->leftvol = chan->rightvol = chan->master_vol; + chan->leftvol = chan->rightvol = chan->volume; chan->sfx = sfx; } } @@ -515,8 +514,8 @@ s_spatialize (snd_t *snd, channel_t *ch) // anything coming from the view entity will always be full volume if (!snd_render_data.viewentity || ch->entnum == *snd_render_data.viewentity) { - ch->leftvol = ch->master_vol; - ch->rightvol = ch->master_vol; + ch->leftvol = ch->volume; + ch->rightvol = ch->volume; ch->phase = 0; return; } @@ -542,12 +541,12 @@ s_spatialize (snd_t *snd, channel_t *ch) // add in distance effect scale = (1.0 - dist) * rscale; - ch->rightvol = (int) (ch->master_vol * scale); + ch->rightvol = ch->volume * scale; if (ch->rightvol < 0) ch->rightvol = 0; scale = (1.0 - dist) * lscale; - ch->leftvol = (int) (ch->master_vol * scale); + ch->leftvol = ch->volume * scale; if (ch->leftvol < 0) ch->leftvol = 0; @@ -647,9 +646,8 @@ snd_check_channels (snd_t *snd, channel_t *target_chan, const channel_t *check, void SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, - vec4f_t origin, float fvol, float attenuation) + vec4f_t origin, float vol, float attenuation) { - int vol; int looped; channel_t *target_chan, *check; sfx_t *osfx; @@ -662,12 +660,10 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, if (!target_chan) return; - vol = fvol * 255; - // spatialize VectorCopy (origin, target_chan->origin); target_chan->dist_mult = attenuation / sound_nominal_clip_dist; - target_chan->master_vol = vol; + target_chan->volume = vol; target_chan->entnum = entnum; target_chan->entchannel = entchannel; s_spatialize (snd, target_chan); @@ -747,8 +743,8 @@ SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol, return; VectorCopy (origin, ss->origin); - ss->master_vol = vol; - ss->dist_mult = (attenuation / 64) / sound_nominal_clip_dist; + ss->volume = vol; + ss->dist_mult = attenuation / sound_nominal_clip_dist; ss->end = 0; s_spatialize (snd, ss); diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index a201e61b1..6d891e291 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -522,8 +522,8 @@ s_channel_get_state (channel_t *chan) static void s_channel_set_volume (channel_t *chan, float volume) { - chan->master_vol = volume * 256; //FIXME - chan->leftvol = chan->rightvol = chan->master_vol; + chan->volume = volume; + chan->leftvol = chan->rightvol = chan->volume; } static void diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index 36ee40527..89dba97a4 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -44,9 +44,7 @@ #include "compat.h" #include "snd_internal.h" -#define VOLSCALE 512.0 // so mixing is less likely to overflow - // note: must be >= 255 due to the channel - // volumes being 0-255. +#define VOLSCALE 0.5 // so mixing is less likely to overflow portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; static int max_overpaint; // number of extra samples painted @@ -226,8 +224,8 @@ snd_paint_mono (int offs, channel_t *ch, float *sfx, unsigned count) unsigned i = 0; portable_samplepair_t *pair; - leftvol = ch->leftvol / VOLSCALE; - rightvol = ch->rightvol / VOLSCALE; + leftvol = ch->leftvol * VOLSCALE; + rightvol = ch->rightvol * VOLSCALE; max_overpaint = max (abs (ch->phase), max (abs (ch->oldphase), max_overpaint)); @@ -320,8 +318,8 @@ static void snd_paint_stereo (int offs, channel_t *ch, float *samp, unsigned count) { portable_samplepair_t *pair; - float leftvol = ch->leftvol / VOLSCALE; - float rightvol = ch->rightvol / VOLSCALE; + float leftvol = ch->leftvol * VOLSCALE; + float rightvol = ch->rightvol * VOLSCALE; pair = snd_paintbuffer + offs; while (count-- > 0) { @@ -338,8 +336,8 @@ static void snd_paint_3 (int offs, channel_t *ch, float *samp, unsigned count) { portable_samplepair_t *pair; - float leftvol = ch->leftvol / VOLSCALE; - float rightvol = ch->rightvol / VOLSCALE; + float leftvol = ch->leftvol * VOLSCALE; + float rightvol = ch->rightvol * VOLSCALE; pair = snd_paintbuffer + offs; while (count-- > 0) { @@ -357,8 +355,8 @@ static void snd_paint_4 (int offs, channel_t *ch, float *samp, unsigned count) { portable_samplepair_t *pair; - float leftvol = ch->leftvol / VOLSCALE; - float rightvol = ch->rightvol / VOLSCALE; + float leftvol = ch->leftvol * VOLSCALE; + float rightvol = ch->rightvol * VOLSCALE; pair = snd_paintbuffer + offs; while (count-- > 0) { @@ -377,8 +375,8 @@ static void snd_paint_5 (int offs, channel_t *ch, float *samp, unsigned count) { portable_samplepair_t *pair; - float leftvol = ch->leftvol / VOLSCALE; - float rightvol = ch->rightvol / VOLSCALE; + float leftvol = ch->leftvol * VOLSCALE; + float rightvol = ch->rightvol * VOLSCALE; pair = snd_paintbuffer + offs; while (count-- > 0) { @@ -398,8 +396,8 @@ static void snd_paint_6 (int offs, channel_t *ch, float *samp, unsigned count) { portable_samplepair_t *pair; - float leftvol = ch->leftvol / VOLSCALE; - float rightvol = ch->rightvol / VOLSCALE; + float leftvol = ch->leftvol * VOLSCALE; + float rightvol = ch->rightvol * VOLSCALE; pair = snd_paintbuffer + offs; while (count-- > 0) { @@ -421,8 +419,8 @@ static void snd_paint_7 (int offs, channel_t *ch, float *samp, unsigned count) { portable_samplepair_t *pair; - float leftvol = ch->leftvol / VOLSCALE; - float rightvol = ch->rightvol / VOLSCALE; + float leftvol = ch->leftvol * VOLSCALE; + float rightvol = ch->rightvol * VOLSCALE; pair = snd_paintbuffer + offs; while (count-- > 0) { @@ -445,8 +443,8 @@ static void snd_paint_8 (int offs, channel_t *ch, float *samp, unsigned count) { portable_samplepair_t *pair; - float leftvol = ch->leftvol / VOLSCALE; - float rightvol = ch->rightvol / VOLSCALE; + float leftvol = ch->leftvol * VOLSCALE; + float rightvol = ch->rightvol * VOLSCALE; pair = snd_paintbuffer + offs; while (count-- > 0) { diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 12defffa9..2a2649e2f 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -685,7 +685,8 @@ CL_ParseClientdata (void) static void CL_ParseStaticSound (int version) { - int sound_num, vol, atten; + int sound_num; + float vol, atten; vec4f_t org = { 0, 0, 0, 1 }; MSG_ReadCoordV (net_message, (vec_t*)&org);//FIXME @@ -693,8 +694,8 @@ CL_ParseStaticSound (int version) sound_num = MSG_ReadShort (net_message); else sound_num = MSG_ReadByte (net_message); - vol = MSG_ReadByte (net_message); - atten = MSG_ReadByte (net_message); + vol = MSG_ReadByte (net_message) / 255.0; + atten = MSG_ReadByte (net_message) / 64.0; S_StaticSound (cl.sound_precache[sound_num], org, vol, atten); } diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index fa3c2075f..7ca2f8f4b 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -900,13 +900,14 @@ CL_ParseModellist (void) static void CL_ParseStaticSound (void) { - int sound_num, vol, atten; + int sound_num; + float vol, atten; vec4f_t org = { 0, 0, 0, 1 }; MSG_ReadCoordV (net_message, (vec_t*)&org);//FIXME sound_num = MSG_ReadByte (net_message); - vol = MSG_ReadByte (net_message); - atten = MSG_ReadByte (net_message); + vol = MSG_ReadByte (net_message) / 255.0; + atten = MSG_ReadByte (net_message) / 64.0; S_StaticSound (cl.sound_precache[sound_num], org, vol, atten); } From 56cd0f3f1d266054437fa9a2d59ab867eff920b0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jun 2022 19:11:25 +0900 Subject: [PATCH 2885/3664] [sound] Rename sndbuffer objects from sc to sb I don't know why I called them sc. Might be a holdover from before the streamed sound support. --- libs/audio/renderer/flac.c | 18 +++++++------- libs/audio/renderer/snd_mem.c | 14 +++++------ libs/audio/renderer/snd_mix.c | 38 +++++++++++++++--------------- libs/audio/renderer/snd_resample.c | 32 ++++++++++++------------- libs/audio/renderer/vorbis.c | 18 +++++++------- 5 files changed, 60 insertions(+), 60 deletions(-) diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index b94660cc8..fbfd28b55 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -282,29 +282,29 @@ static sfxbuffer_t * flac_load (flacfile_t *ff, sfxblock_t *block, cache_allocator_t allocator) { float *data; - sfxbuffer_t *sc = 0; + sfxbuffer_t *sb = 0; sfx_t *sfx = block->sfx; wavinfo_t *info = &block->wavinfo; data = malloc (info->datalen); if (!data) goto bail; - sc = SND_GetCache (info->frames, info->rate, info->channels, + sb = SND_GetCache (info->frames, info->rate, info->channels, block, allocator); - if (!sc) + if (!sb) goto bail; - sc->sfx = sfx; + sb->sfx = sfx; if (flac_read (ff, data, info->frames) < 0) goto bail; - SND_SetPaint (sc); - SND_SetupResampler (sc, 0); - SND_Resample (sc, data, info->frames); - sc->head = sc->length; + SND_SetPaint (sb); + SND_SetupResampler (sb, 0); + SND_Resample (sb, data, info->frames); + sb->head = sb->length; bail: if (data) free (data); flac_close (ff); - return sc; + return sb; } static void diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 260f16a37..49c263ac4 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -351,18 +351,18 @@ SND_GetCache (long frames, int rate, int channels, { int len, size; float stepscale; - sfxbuffer_t *sc; + sfxbuffer_t *sb; sfx_t *sfx = block->sfx; snd_t *snd = sfx->snd; stepscale = (float) rate / snd->speed; len = size = frames / stepscale; size *= sizeof (float) * channels; - sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name); - if (!sc) + sb = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name); + if (!sb) return 0; - memset (sc, 0, sizeof (sfxbuffer_t) + size); - sc->length = len; - memcpy (sc->data + len * channels, "\xde\xad\xbe\xef", 4); - return sc; + memset (sb, 0, sizeof (sfxbuffer_t) + size); + sb->length = len; + memcpy (sb->data + len * channels, "\xde\xad\xbe\xef", 4); + return sb; } diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index 89dba97a4..2ca8bddad 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -68,7 +68,7 @@ check_channel_end (channel_t *ch, sfx_t *sfx, int count, unsigned ltime) } static inline void -snd_paint_channel (channel_t *ch, sfxbuffer_t *sc, int count) +snd_paint_channel (channel_t *ch, sfxbuffer_t *sb, int count) { unsigned pos; int offs = 0; @@ -82,17 +82,17 @@ snd_paint_channel (channel_t *ch, sfxbuffer_t *sc, int count) count -= offs; ch->pos = 0; } - if (ch->pos < sc->pos || ch->pos - sc->pos >= sc->length) - sc->setpos (sc, ch->pos); - pos = (ch->pos - sc->pos + sc->tail) % sc->length; - samps = sc->data + pos * sc->channels; + if (ch->pos < sb->pos || ch->pos - sb->pos >= sb->length) + sb->setpos (sb, ch->pos); + pos = (ch->pos - sb->pos + sb->tail) % sb->length; + samps = sb->data + pos * sb->channels; - if (pos + count > sc->length) { - unsigned sub = sc->length - pos; - sc->paint (offs, ch, samps, sub); - sc->paint (offs + sub, ch, sc->data, count - sub); + if (pos + count > sb->length) { + unsigned sub = sb->length - pos; + sb->paint (offs, ch, samps, sub); + sb->paint (offs + sub, ch, sb->data, count - sub); } else { - sc->paint (offs, ch, samps, count); + sb->paint (offs, ch, samps, count); } ch->pos += count; } @@ -104,7 +104,7 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) int i, count; channel_t *ch; sfx_t *sfx; - sfxbuffer_t *sc; + sfxbuffer_t *sb; // clear the paint buffer for (i = 0; i < PAINTBUFFER_SIZE * 2; i++) { @@ -131,8 +131,8 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) } if (ch->pause) continue; - sc = sfx->getbuffer (sfx); - if (!sc) { // something went wrong with the sfx + sb = sfx->getbuffer (sfx); + if (!sb) { // something went wrong with the sfx printf ("XXXX sfx blew up!!!!\n"); continue; } @@ -146,9 +146,9 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) count = ((ch->end < end) ? ch->end : end) - ltime; if (count > 0) { if (ch->leftvol || ch->rightvol) { - snd_paint_channel (ch, sc, count); - if (sc->advance) { - if (!sc->advance (sc, count)) { + snd_paint_channel (ch, sb, count); + if (sb->advance) { + if (!sb->advance (sb, count)) { // this channel can no longer be used as its // source has died. ch->done = 1; @@ -457,7 +457,7 @@ snd_paint_8 (int offs, channel_t *ch, float *samp, unsigned count) } void -SND_SetPaint (sfxbuffer_t *sc) +SND_SetPaint (sfxbuffer_t *sb) { static sfxpaint_t *painters[] = { 0, @@ -471,8 +471,8 @@ SND_SetPaint (sfxbuffer_t *sc) snd_paint_8, }; - wavinfo_t *info = sc->sfx->wavinfo (sc->sfx); + wavinfo_t *info = sb->sfx->wavinfo (sb->sfx); if (info->channels > 8) Sys_Error ("illegal channel count %d", info->channels); - sc->paint = painters[info->channels]; + sb->paint = painters[info->channels]; } diff --git a/libs/audio/renderer/snd_resample.c b/libs/audio/renderer/snd_resample.c index 2045039e0..9e0848350 100644 --- a/libs/audio/renderer/snd_resample.c +++ b/libs/audio/renderer/snd_resample.c @@ -54,21 +54,21 @@ typedef struct { } snd_null_state_t; static void -check_buffer_integrity (sfxbuffer_t *sc, int width, const char *func) +check_buffer_integrity (sfxbuffer_t *sb, int width, const char *func) { - byte *x = (byte *) sc->data + sc->length * width; + byte *x = (byte *) sb->data + sb->length * width; if (memcmp (x, "\xde\xad\xbe\xef", 4)) Sys_Error ("%s screwed the pooch %02x%02x%02x%02x", func, x[0], x[1], x[2], x[3]); } void -SND_Resample (sfxbuffer_t *sc, float *data, int length) +SND_Resample (sfxbuffer_t *sb, float *data, int length) { int outcount; double stepscale; - wavinfo_t *info = sc->sfx->wavinfo (sc->sfx); - snd_t *snd = sc->sfx->snd; + wavinfo_t *info = sb->sfx->wavinfo (sb->sfx); + snd_t *snd = sb->sfx->snd; int inrate = info->rate; int outwidth; SRC_DATA src_data; @@ -77,15 +77,15 @@ SND_Resample (sfxbuffer_t *sc, float *data, int length) outcount = length * stepscale; src_data.data_in = data; - src_data.data_out = sc->data + sc->head * sc->channels; + src_data.data_out = sb->data + sb->head * sb->channels; src_data.input_frames = length; src_data.output_frames = outcount; src_data.src_ratio = stepscale; - src_simple (&src_data, SRC_LINEAR, sc->channels); + src_simple (&src_data, SRC_LINEAR, sb->channels); outwidth = info->channels * sizeof (float); - check_buffer_integrity (sc, outwidth, __FUNCTION__); + check_buffer_integrity (sb, outwidth, __FUNCTION__); } static int @@ -140,26 +140,26 @@ snd_seek (sfxstream_t *stream, int pos) } void -SND_SetupResampler (sfxbuffer_t *sc, int streamed) +SND_SetupResampler (sfxbuffer_t *sb, int streamed) { double stepscale; - wavinfo_t *info = sc->sfx->wavinfo (sc->sfx); - snd_t *snd = sc->sfx->snd; + wavinfo_t *info = sb->sfx->wavinfo (sb->sfx); + snd_t *snd = sb->sfx->snd; int inrate = info->rate; stepscale = (double) snd->speed / inrate; - sc->sfx->length = info->frames * stepscale; + sb->sfx->length = info->frames * stepscale; if (info->loopstart != (unsigned int)-1) - sc->sfx->loopstart = info->loopstart * stepscale; + sb->sfx->loopstart = info->loopstart * stepscale; else - sc->sfx->loopstart = (unsigned int)-1; + sb->sfx->loopstart = (unsigned int)-1; - sc->channels = info->channels; + sb->channels = info->channels; if (streamed) { int err; - sfxstream_t *stream = sc->sfx->data.stream; + sfxstream_t *stream = sb->sfx->data.stream; if (snd->speed == inrate) { stream->state = calloc (sizeof (snd_null_state_t), 1); diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index 25e6c000b..1477eb303 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -163,29 +163,29 @@ static sfxbuffer_t * vorbis_load (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator) { float *data; - sfxbuffer_t *sc = 0; + sfxbuffer_t *sb = 0; sfx_t *sfx = block->sfx; wavinfo_t *info = &block->wavinfo; data = malloc (info->datalen); if (!data) goto bail; - sc = SND_GetCache (info->frames, info->rate, info->channels, + sb = SND_GetCache (info->frames, info->rate, info->channels, block, allocator); - if (!sc) + if (!sb) goto bail; - sc->sfx = sfx; + sb->sfx = sfx; if (vorbis_read (vf, data, info->frames, info) < 0) goto bail; - SND_SetPaint (sc); - SND_SetupResampler (sc, 0); - SND_Resample (sc, data, info->frames); - sc->head = sc->length; + SND_SetPaint (sb); + SND_SetupResampler (sb, 0); + SND_Resample (sb, data, info->frames); + sb->head = sb->length; bail: if (data) free (data); ov_clear (vf); - return sc; + return sb; } static void From cbc5654b5e9db26d7bd7c8bd715156b2200b9b9c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Jun 2022 20:01:34 +0900 Subject: [PATCH 2886/3664] [sound] Initialize snd_alive_time on connection to JACK Sys_DoubleTime starts at 4Gs in order to keep its precision fixed for a nice long time (about 120 years, iirc). This fixes an instant watchdog trigger when first starting up in testsound. I'm not sure why it didn't happen with nq, but I guess that doesn't really matter --- libs/audio/targets/snd_jack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/audio/targets/snd_jack.c b/libs/audio/targets/snd_jack.c index d484c3e46..90bbd2c57 100644 --- a/libs/audio/targets/snd_jack.c +++ b/libs/audio/targets/snd_jack.c @@ -269,6 +269,7 @@ s_jack_connect (snd_t *snd) snd->channels = 2; s_jack_activate (); sound_started = 1; + snd_alive_time = Sys_DoubleTime (); Sys_Printf ("Connected to JACK: %d Sps\n", snd->speed); return 1; } From 76c62b49e060cf5ee21dc5fd10dd0179f1313a88 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 12:06:34 +0900 Subject: [PATCH 2887/3664] [set] Add a macro to initialize with a static array Nicer than trying to hack one one every time (and it looks like my previous attempt was wrong anyway) --- include/QF/set.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/QF/set.h b/include/QF/set.h index 1d59ed395..e7d75e4f5 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -52,6 +52,7 @@ typedef uint32_t set_bits_t; #define SET_BITS (sizeof (set_bits_t) * 8) //NOTE: x is the element number, so size is x + 1 #define SET_SIZE(x) (((x) + SET_BITS) & ~(SET_BITS - 1)) +#define SET_WORDS_STATIC(x) (SET_SIZE (x) / SET_BITS) #define SET_WORDS(s) ((s)->size / SET_BITS) #define SET_ZERO ((set_bits_t) 0) #define SET_ONE ((set_bits_t) 1) @@ -65,6 +66,14 @@ typedef uint32_t set_bits_t; .size = SET_SIZE (x), \ .map = alloc (SET_SIZE (x) / 8), \ } +#define SET_STATIC_ARRAY(array) { \ + .size = 8 * __builtin_choose_expr ( \ + sizeof (array[0]) == sizeof (set_bits_t), \ + sizeof (array), \ + (void) 0 \ + ), \ + .map = array, \ +} /** Represent a set using a bitmap. From 5fd9098e05f9022e38b279db36cc404ff4775b03 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 12:10:09 +0900 Subject: [PATCH 2888/3664] [sound] Remove the next pointer and entity channel from channel_t This is part of a process to shrink channel_t so it doesn't waste locked memory when it gets moved there. Eventually, only the fields the mixer needs will be in channel_t itself: those needed for spacialization will be moved into a separate array. In the process, I found that channels leak across level changes, but this appears to be due to the cached sounds being removed during loading and the mixer never marking them as done (it sees the null sfx pointer and assumes the channel was never in use). Having the mixer mark the channel as done seems to fix the leak, but cause a free channel list overflow. Rather than fight with that, I'll leave the leak for now and fix it at its root cause: the management of the sound samples themselves. --- include/snd_internal.h | 3 - libs/audio/renderer/snd_channels.c | 334 ++++++++++++++--------------- libs/audio/renderer/snd_mix.c | 4 +- 3 files changed, 170 insertions(+), 171 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index 93a08972a..e3b27bc87 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -223,15 +223,12 @@ struct sfxblock_s { /** Representation of a sound being played. */ struct channel_s { - channel_t *next; //!< next channel in "free" list sfx_t *sfx; //!< sound played by this channel float leftvol; //!< 0-1 volume float rightvol; //!< 0-1 volume unsigned end; //!< end time in global paintsamples unsigned pos; //!< sample position in sfx unsigned looping; //!< where to loop, -1 = no looping - int entnum; //!< to allow overriding a specific sound - int entchannel; // vec3_t origin; //!< origin of sound effect vec_t dist_mult; //!< distance multiplier (attenuation/clip) int pause; //!< don't update the channel at all diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 8e7a68204..0e1962a73 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -4,6 +4,7 @@ main control for any streaming sound output device Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2003-2022 Bill Currie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -45,21 +46,41 @@ #include "QF/dstring.h" #include "QF/model.h" #include "QF/quakefs.h" +#include "QF/set.h" #include "QF/sys.h" #include "QF/scene/transform.h" #include "snd_internal.h" -static channel_t *free_channels; -channel_t snd_channels[MAX_CHANNELS]; +#define SND_STATIC_ID -1 + +typedef struct entchan_s { + int id; // entity id + int channel; // per-entity sound channel +} entchan_t; + int snd_total_channels; +channel_t snd_channels[MAX_CHANNELS]; +static entchan_t snd_entity_channels[MAX_CHANNELS]; +static int snd_free_channels[MAX_CHANNELS]; +static int snd_num_free_channels; +/* Dynamic channels are (usually) short sound bytes, never looped. They do not + * override other dynamic channels even for the same entity channel. However, + * they DO override (stop) looped channels on the same entity channel. + */ +static set_bits_t dynamic_channel_bits[SET_WORDS_STATIC (MAX_CHANNELS)]; +static set_t dynamic_channels = SET_STATIC_ARRAY (dynamic_channel_bits); +/* Looped channels are sounds that automatically repeat until they are stopped. + * They can be stopped via SND_ChannelStop or by starting another sound + * (dynamic or looped) on the same entity channel. + */ +static set_bits_t looped_channel_bits[SET_WORDS_STATIC (MAX_CHANNELS)]; +static set_t looped_channels = SET_STATIC_ARRAY (looped_channel_bits); +static set_bits_t static_channel_bits[SET_WORDS_STATIC (MAX_CHANNELS)]; +static set_t static_channels = SET_STATIC_ARRAY (static_channel_bits); static channel_t *ambient_channels[NUM_AMBIENTS]; -static channel_t *dynamic_channels; -static channel_t *looped_dynamic_channels; -static channel_t *static_channels[MAX_STATIC_CHANNELS]; -static int snd_num_statics; static qboolean snd_ambient = 1; static sfx_t *ambient_sfx[NUM_AMBIENTS]; @@ -117,50 +138,43 @@ static cvar_t ambient_level_cvar = { .value = { .type = &cexpr_float, .value = &ambient_level }, }; -static inline channel_t * -unlink_channel (channel_t **_ch) +static void +snd_free_channel (channel_t *ch) { - channel_t *ch = *_ch; - *_ch = ch->next; - ch->next = 0; - return ch; + ch->sfx = 0; + ch->stop = 0; + ch->done = 0; + int chan_ind = ch - snd_channels; + if (snd_num_free_channels >= MAX_CHANNELS) { + Sys_Error ("snd_num_free_channels: free channel list overflow"); + } + snd_free_channels[snd_num_free_channels++] = chan_ind; + snd_entity_channels[chan_ind] = (entchan_t) {}; } channel_t * SND_AllocChannel (snd_t *snd) { - channel_t **free = &free_channels; channel_t *chan; - while (*free) { - if (!(*free)->sfx) // free channel - break; - if ((*free)->done) // mixer is finished with this channel - break; - if (!(*free)->stop) - Sys_Error ("SND_AllocChannel: bogus channel free list"); - free = &(*free)->next; - } - if (!*free) { - int num_free = 0; - for (free = &free_channels; *free; free = &(*free)->next) { - num_free++; + // chech for any channels that have become available as the mixer thread + // has finished with them + for (int i = 0; i < MAX_CHANNELS; i++) { + channel_t *ch = &snd_channels[i]; + if (ch->done) { + snd_free_channel (ch); } - Sys_MaskPrintf (SYS_warn, "SND_AllocChannel: out of channels. %d\n", - num_free); + } + //Sys_MaskPrintf (SYS_snd, "SND_AllocChannel: free channels: %d\n", + // snd_num_free_channels); + if (!snd_num_free_channels) { + Sys_MaskPrintf (SYS_warn, "SND_AllocChannel: out of channels.\n"); return 0; } - chan = *free; - *free = chan->next; - if (chan->sfx) { - chan->sfx->release (chan->sfx); - chan->sfx->close (chan->sfx); - chan->sfx = 0; // make sure mixer doesn't use channel during memset - } + int chan_ind = snd_free_channels[--snd_num_free_channels]; + chan = &snd_channels[chan_ind]; memset (chan, 0, sizeof (*chan)); - chan->next = 0; - chan->sfx = 0; return chan; } @@ -168,14 +182,14 @@ SND_AllocChannel (snd_t *snd) void SND_ChannelStop (snd_t *snd, channel_t *chan) { - /* if chan->next is set, then this channel may have already been freed. - a rather serious bug as it will create a loop in the free list - */ - if (chan->next) - Sys_Error ("Stopping a freed channel"); + if (!chan->sfx) { + Sys_MaskPrintf (SYS_warn, "Sound: stop called on invalid channel\n"); + } chan->stop = 1; - chan->next = free_channels; - free_channels = chan; + int chan_ind = chan - snd_channels; + set_remove (&dynamic_channels, chan_ind); + set_remove (&looped_channels, chan_ind); + set_remove (&static_channels, chan_ind); } void @@ -240,34 +254,21 @@ SND_FinishChannels (void) void SND_StopAllSounds (snd_t *snd) { - int i; - - snd_num_statics = 0; - while (dynamic_channels) - SND_ChannelStop (snd, unlink_channel (&dynamic_channels)); - while (looped_dynamic_channels) - SND_ChannelStop (snd, unlink_channel (&looped_dynamic_channels)); - for (i = 0; i < NUM_AMBIENTS; i++) { + for (int i = 0; i < MAX_CHANNELS; i++) { + if (set_is_member (&dynamic_channels, i) + || set_is_member (&looped_channels, i) + || set_is_member (&static_channels, i)) { + SND_ChannelStop (snd, &snd_channels[i]); + } + } + set_empty (&dynamic_channels); + set_empty (&looped_channels); + set_empty (&static_channels); + for (int i = 0; i < NUM_AMBIENTS; i++) { if (ambient_channels[i]) SND_ChannelStop (snd, ambient_channels[i]); ambient_channels[i] = 0; } - for (i = 0; i < MAX_STATIC_CHANNELS; i++) { - if (static_channels[i]) - SND_ChannelStop (snd, static_channels[i]); - static_channels[i] = 0; - } - if (0) { - channel_t *ch; - Sys_Printf ("SND_StopAllSounds\n"); - for (i = 0, ch = free_channels; ch; ch = ch->next) - i++; - Sys_Printf (" free channels:%d\n", i); - for (i = 0, ch = free_channels; ch; ch = ch->next) - if (!ch->sfx || ch->done) - i++; - Sys_Printf (" truely free channels:%d\n", i); - } } static void @@ -287,6 +288,7 @@ s_play_f (void *_snd) dsprintf (name, "%s", Cmd_Argv (i)); } sfx = SND_PrecacheSound (snd, name->str); + printf ("%s %p\n", name->str, sfx); SND_StartSound (snd, hash++, 0, sfx, listener_origin, 1.0, 1.0); i++; } @@ -358,8 +360,6 @@ s_channels_gamedir (int phase) void SND_Channels_Init (snd_t *snd) { - int i; - Cvar_Register (&snd_phasesep_cvar, 0, 0); Cvar_Register (&snd_volumesep_cvar, 0, 0); Cvar_Register (&snd_swapchannelside_cvar, 0, 0); @@ -375,47 +375,41 @@ SND_Channels_Init (snd_t *snd) "Play selected sound effect at selected volume " "(playvol pathto/sound.wav num"); - for (i = 0; i < MAX_CHANNELS - 1; i++) - snd_channels[i].next = &snd_channels[i + 1]; - free_channels = &snd_channels[0]; + for (int i = 0; i < MAX_CHANNELS; i++) { + snd_free_channels[i] = MAX_CHANNELS - 1 - i; + } + snd_num_free_channels = MAX_CHANNELS; snd_total_channels = MAX_CHANNELS; - snd_num_statics = 0; - QFS_GamedirCallback (s_channels_gamedir); } static channel_t * s_pick_channel (snd_t *snd, int entnum, int entchannel, int looped) { - channel_t *ch, **_ch; - // check for finished non-looped sounds - for (_ch = &dynamic_channels; *_ch; ) { - if (!(*_ch)->sfx || (*_ch)->done) { - SND_ChannelStop (snd, unlink_channel (_ch)); - continue; + for (int i = 0; i < MAX_CHANNELS; i++) { + channel_t *ch = &snd_channels[i]; + if (set_is_member (&dynamic_channels, i)) { + if (ch->done) { + // mixer is done with the channel, it can be freed + snd_free_channel (ch); + set_remove (&dynamic_channels, i); + } + } else if (set_is_member (&looped_channels, i)) { + // non-looped sounds are used to stop looped sounds on an entity + // channel also clean out any caught by SND_ScanChannels + entchan_t *entchan = &snd_entity_channels[i]; + if (entchan->id == entnum + && (entchan->channel == entchannel || entchannel == -1)) { + // the mixer is still using the channel, so send a request + // for it to stopp + SND_ChannelStop (snd, ch); + } } - _ch = &(*_ch)->next; } - // non-looped sounds are used to stop looped sounds on an ent channel - // also clean out any caught by SND_ScanChannels - for (_ch = &looped_dynamic_channels; *_ch; ) { - if (!(*_ch)->sfx || (*_ch)->done - || ((*_ch)->entnum == entnum - && ((*_ch)->entchannel == entchannel || entchannel == -1))) { - SND_ChannelStop (snd, unlink_channel (_ch)); - continue; - } - _ch = &(*_ch)->next; - } - _ch = looped ? &looped_dynamic_channels : &dynamic_channels; - if ((ch = SND_AllocChannel (snd))) { - ch->next = *_ch; - *_ch = ch; - } - return ch; + return SND_AllocChannel (snd); } void @@ -507,13 +501,14 @@ s_spatialize (snd_t *snd, channel_t *ch) int phase; // in samples vec_t dist, dot, lscale, rscale, scale; vec3_t source_vec; + int chan_ind = ch - snd_channels; // prepare to lerp from prev to next phase ch->oldphase = ch->phase; // anything coming from the view entity will always be full volume if (!snd_render_data.viewentity - || ch->entnum == *snd_render_data.viewentity) { + || snd_entity_channels[chan_ind].id == *snd_render_data.viewentity) { ch->leftvol = ch->volume; ch->rightvol = ch->volume; ch->phase = 0; @@ -575,9 +570,6 @@ s_combine_channel (channel_t *combine, channel_t *ch) void SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level) { - int i, j; - channel_t *combine, *ch; - if (ear) { listener_origin = Transform_GetWorldPosition (ear); listener_forward = Transform_Forward (ear); @@ -593,39 +585,41 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level) // update general area ambient sound sources s_updateAmbientSounds (snd, ambient_sound_level); - // update spatialization for dynamic sounds - for (ch = dynamic_channels; ch; ch = ch->next) - s_update_channel (snd, ch); - for (ch = looped_dynamic_channels; ch; ch = ch->next) - s_update_channel (snd, ch); - - // update spatialization for static sounds - combine = 0; - for (i = 0; i < snd_num_statics; i++) { - ch = static_channels[i]; - if (!s_update_channel (snd, ch)) - continue; - - // try to combine static sounds with a previous channel of the same - // sound effect so we don't mix five torches every frame - // see if it can just use the last one - if (combine && combine->sfx == ch->sfx) { - s_combine_channel (combine, ch); + channel_t *combine = 0; + for (int i = 0; i < MAX_CHANNELS; i++) { + channel_t *ch = &snd_channels[i]; + if (!ch->sfx || ch->done) { continue; } - // search for one - for (j = 0; j < i; j++) { - combine = static_channels[j]; - if (combine->sfx == ch->sfx) - break; - } - - if (j == i) { - combine = 0; - } else { - if (combine != ch) + if (set_is_member (&dynamic_channels, i) + || set_is_member (&looped_channels, i)) { + // update spatialization for dynamic and looped sounds + s_update_channel (snd, ch); + } else if (set_is_member (&static_channels, i)) { + if (!s_update_channel (snd, ch)) { + // too quiet + continue; + } + // try to combine static sounds with a previous channel of + // the same sound effect so we don't mix five torches every + // frame see if it can just use the last one + if (combine && combine->sfx == ch->sfx) { s_combine_channel (combine, ch); - continue; + continue; + } + // search for one + channel_t *c = 0; + for (int j = 0; j < i; j++) { + if (set_is_member (&static_channels, j)) { + if (snd_channels[j].sfx == ch->sfx) { + c = &snd_channels[j]; + break; + } + } + } + if ((combine = c)) { + s_combine_channel (combine, ch); + } } } } @@ -634,7 +628,7 @@ static int snd_check_channels (snd_t *snd, channel_t *target_chan, const channel_t *check, const sfx_t *osfx) { - if (!check || check == target_chan) + if (!check || !check->sfx || check == target_chan) return 0; if (check->sfx->owner == osfx->owner && !check->pos) { int skip = rand () % (int) (0.01 * snd->speed); @@ -649,7 +643,7 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, vec4f_t origin, float vol, float attenuation) { int looped; - channel_t *target_chan, *check; + channel_t *target_chan; sfx_t *osfx; if (!sfx || !snd->speed) @@ -660,18 +654,20 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, if (!target_chan) return; + int chan_ind = target_chan - snd_channels; // spatialize VectorCopy (origin, target_chan->origin); target_chan->dist_mult = attenuation / sound_nominal_clip_dist; target_chan->volume = vol; - target_chan->entnum = entnum; - target_chan->entchannel = entchannel; + snd_entity_channels[chan_ind] = (entchan_t) { + .id = entnum, + .channel = entchannel, + }; s_spatialize (snd, target_chan); - // new channel if (!(osfx = sfx->open (sfx))) { - SND_ChannelStop (snd, unlink_channel (looped ? &looped_dynamic_channels - : &dynamic_channels)); + // because the channel was never started, it's safe to directly free it + snd_free_channel (target_chan); return; } target_chan->pos = 0; @@ -679,25 +675,29 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, // if an identical sound has also been started this frame, offset the pos // a bit to keep it from just making the first one louder - for (check = dynamic_channels; check; check = check->next) - if (snd_check_channels (snd, target_chan, check, osfx)) - break; - for (check = looped_dynamic_channels; check; check = check->next) - if (snd_check_channels (snd, target_chan, check, osfx)) - break; + for (int i = 0; i < MAX_CHANNELS; i++) { + if (set_is_member (&dynamic_channels, i) + || set_is_member (&looped_channels, i)) { + channel_t *check = &snd_channels[i]; + if (snd_check_channels (snd, target_chan, check, osfx)) + break; + } + } if (!osfx->retain (osfx)) { - SND_ChannelStop (snd, unlink_channel (looped ? &looped_dynamic_channels - : &dynamic_channels)); + // because the channel was never started, it's safe to directly free it + snd_free_channel (target_chan); return; // couldn't load the sound's data } target_chan->sfx = osfx; + set_add (looped ? &looped_channels : &dynamic_channels, chan_ind); } static int -s_check_stop (snd_t *snd, channel_t **_ch, int entnum, int entchannel) +s_check_stop (snd_t *snd, int chan_ind, int entnum, int entchannel) { - if ((*_ch)->entnum == entnum && (*_ch)->entchannel == entchannel) { - SND_ChannelStop (snd, unlink_channel (_ch)); + entchan_t *entchan = &snd_entity_channels[chan_ind]; + if (entchan->id == entnum && entchan->channel == entchannel) { + SND_ChannelStop (snd, &snd_channels[chan_ind]); return 1; } return 0; @@ -706,14 +706,12 @@ s_check_stop (snd_t *snd, channel_t **_ch, int entnum, int entchannel) void SND_StopSound (snd_t *snd, int entnum, int entchannel) { - channel_t **_ch; - - for (_ch = &dynamic_channels; *_ch; ) - if (!s_check_stop (snd, _ch, entnum, entchannel)) - _ch = &(*_ch)->next; - for (_ch = &looped_dynamic_channels; *_ch; ) - if (!s_check_stop (snd, _ch, entnum, entchannel)) - _ch = &(*_ch)->next; + for (int i = 0; i < MAX_CHANNELS; i++) { + if (set_is_member (&dynamic_channels, i) + || set_is_member (&looped_channels, i)) { + s_check_stop (snd, i, entnum, entchannel); + } + } } void @@ -730,14 +728,11 @@ SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol, return; } - if (!static_channels[snd_num_statics]) { - if (!(static_channels[snd_num_statics] = SND_AllocChannel (snd))) { - Sys_Printf ("ran out of channels\n"); - return; - } + if (!(ss = SND_AllocChannel (snd))) { + Sys_Printf ("ran out of channels\n"); + return; } - - ss = static_channels[snd_num_statics]; + int ss_ind = ss - snd_channels; if (!(osfx = sfx->open (sfx))) return; @@ -752,7 +747,12 @@ SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol, if (!osfx->retain (osfx)) return; - snd_num_statics++; + + set_add (&static_channels, ss_ind); + snd_entity_channels[ss_ind] = (entchan_t) { + .id = SND_STATIC_ID, + .channel = 0, + }; ss->sfx = osfx; } diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index 2ca8bddad..90630f46d 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -123,8 +123,10 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) // paint in the channels. ch = snd_channels; for (i = 0; i < snd_total_channels; i++, ch++) { - if (!(sfx = ch->sfx)) + if (!(sfx = ch->sfx)) { + // channel is inactive continue; + } if (ch->stop || ch->done) { ch->done = 1; // acknowledge stopped signal continue; From 0c65d294edb9e7c54df1f045e7107ae3991ca5f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 12:24:53 +0900 Subject: [PATCH 2889/3664] [sys] Add a function to lock a region of memory Locked memory is needed for real-time threads (which the sound mixer is when using JACK). --- include/QF/sys.h | 1 + libs/util/sys.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/QF/sys.h b/include/QF/sys.h index efe621f5d..45d818660 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -130,6 +130,7 @@ void Sys_PageIn (void *ptr, size_t size); size_t Sys_PageSize (void); void *Sys_Alloc (size_t size); void Sys_Free (void *mem, size_t size); +int Sys_LockMemory (void *mem, size_t size); int Sys_ProcessorCount (void); diff --git a/libs/util/sys.c b/libs/util/sys.c index e08557c81..937d832b2 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -758,6 +758,19 @@ Sys_Free (void *mem, size_t size) #endif } +VISIBLE int +Sys_LockMemory (void *mem, size_t size) +{ + size_t page_size = Sys_PageSize (); + size_t page_mask = page_size - 1; + size = (size + page_mask) & ~page_mask; +#ifdef _WIN32 + return VirtualLock (mem, size) != 0; +#else + return mlock (mem, size) == 0; +#endif +} + VISIBLE int Sys_ProcessorCount (void) { From 18c64f7319aece00f6e667e16e34b6f52d6c97f2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 12:27:11 +0900 Subject: [PATCH 2890/3664] [sound] Fix some spelling errors in the mixer Triple has only one p, not two :/ --- libs/audio/renderer/snd_mix.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index 90630f46d..c99ca49a5 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -201,7 +201,7 @@ snd_mix_pair (portable_samplepair_t *pair, float **samp, } static inline void -snd_mix_tripple (portable_samplepair_t *pair, float **samp, +snd_mix_triple (portable_samplepair_t *pair, float **samp, float lvol, float rvol) { float left = *(*samp)++; @@ -343,7 +343,7 @@ snd_paint_3 (int offs, channel_t *ch, float *samp, unsigned count) pair = snd_paintbuffer + offs; while (count-- > 0) { - snd_mix_tripple (pair, &samp, leftvol, rightvol); + snd_mix_triple (pair, &samp, leftvol, rightvol); pair++; } } @@ -382,7 +382,7 @@ snd_paint_5 (int offs, channel_t *ch, float *samp, unsigned count) pair = snd_paintbuffer + offs; while (count-- > 0) { - snd_mix_tripple (pair, &samp, leftvol, rightvol); + snd_mix_triple (pair, &samp, leftvol, rightvol); snd_mix_pair (pair, &samp, leftvol, rightvol); pair++; } @@ -403,7 +403,7 @@ snd_paint_6 (int offs, channel_t *ch, float *samp, unsigned count) pair = snd_paintbuffer + offs; while (count-- > 0) { - snd_mix_tripple (pair, &samp, leftvol, rightvol); + snd_mix_triple (pair, &samp, leftvol, rightvol); snd_mix_pair (pair, &samp, leftvol, rightvol); snd_mix_single (pair, &samp, leftvol, rightvol); pair++; @@ -426,7 +426,7 @@ snd_paint_7 (int offs, channel_t *ch, float *samp, unsigned count) pair = snd_paintbuffer + offs; while (count-- > 0) { - snd_mix_tripple (pair, &samp, leftvol, rightvol); + snd_mix_triple (pair, &samp, leftvol, rightvol); snd_mix_pair (pair, &samp, leftvol, rightvol); snd_mix_single (pair, &samp, leftvol, rightvol); snd_mix_single (pair, &samp, leftvol, rightvol); @@ -450,7 +450,7 @@ snd_paint_8 (int offs, channel_t *ch, float *samp, unsigned count) pair = snd_paintbuffer + offs; while (count-- > 0) { - snd_mix_tripple (pair, &samp, leftvol, rightvol); + snd_mix_triple (pair, &samp, leftvol, rightvol); snd_mix_pair (pair, &samp, leftvol, rightvol); snd_mix_pair (pair, &samp, leftvol, rightvol); snd_mix_single (pair, &samp, leftvol, rightvol); From 94db9c8ab18fe553765bd22fb0eb8b3eb3c238b4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 16:06:04 +0900 Subject: [PATCH 2891/3664] [quakefs] Add a data parameter to gamedir callbacks While this didn't fix the problem for which I needed the data pointer, having data pointers in callbacks is far too useful to throw out the change. --- include/QF/quakefs.h | 5 +++-- libs/audio/cd_file.c | 4 ++-- libs/audio/renderer/snd_channels.c | 4 ++-- libs/audio/renderer/snd_sfx.c | 4 ++-- libs/client/cl_temp_entities.c | 4 ++-- libs/util/quakefs.c | 17 +++++++++++------ libs/video/renderer/gl/gl_draw.c | 4 ++-- libs/video/renderer/glsl/glsl_draw.c | 4 ++-- qw/source/cl_main.c | 4 ++-- qw/source/sv_main.c | 4 ++-- 10 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index c95560b10..2719eeb46 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -85,7 +85,7 @@ extern gamedir_t *qfs_gamedir; /** Function type of callback called on gamedir change. \param phase 0 = before Cache_Flush(), 1 = after Cache_Flush() */ -typedef void gamedir_callback_t (int phase); +typedef void gamedir_callback_t (int phase, void *data); /** Base of the QFS user directory tree. The QFS functions, except for QFS_FOpenFile() and _QFS_FOpenFile(), will never access a file outside of @@ -381,8 +381,9 @@ const char *QFS_FileExtension (const char *in) __attribute__((pure)); \param func The function to call every time the gamedir changes via QFS_Gamedir(). + \param data Opaque data pointer passed to the callback. */ -void QFS_GamedirCallback (gamedir_callback_t *func); +void QFS_GamedirCallback (gamedir_callback_t *func, void *data); /** Create a new file list. diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index 26854e244..8e027199a 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -455,7 +455,7 @@ Mus_VolChange (void *data, const cvar_t *bgmvolume) } static void -Mus_gamedir (int phase) +Mus_gamedir (int phase, void *data) { if (phase) Load_Tracklist (); @@ -467,7 +467,7 @@ I_OGGMus_Init (void) /* check list file cvar, open list file, create map, close file. */ Cvar_Register (&mus_ogglist_cvar, Mus_OggChange, 0); Cvar_Register (&bgmvolume_cvar, Mus_VolChange, 0); - QFS_GamedirCallback (Mus_gamedir); + QFS_GamedirCallback (Mus_gamedir, 0); } static general_funcs_t plugin_info_general_funcs = { diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 0e1962a73..f32d1f14f 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -345,7 +345,7 @@ s_playvol_f (void *_snd) } static void -s_channels_gamedir (int phase) +s_channels_gamedir (int phase, void *_snd) { //FIXME for some reason, a gamedir change causes semi-random //"already released" cache errors. fortunatly, servers don't change @@ -381,7 +381,7 @@ SND_Channels_Init (snd_t *snd) snd_num_free_channels = MAX_CHANNELS; snd_total_channels = MAX_CHANNELS; - QFS_GamedirCallback (s_channels_gamedir); + QFS_GamedirCallback (s_channels_gamedir, snd); } static channel_t * diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index b3ad1b602..b632ba6b7 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -219,7 +219,7 @@ SND_PrecacheSound (snd_t *snd, const char *name) } static void -s_gamedir (int phase) +s_gamedir (int phase, void *data) { snd_num_sfx = 0; } @@ -259,7 +259,7 @@ SND_SFX_Init (snd_t *snd) snd_sfx_hash = Hash_NewTable (511, snd_sfx_getkey, snd_sfx_free, 0, 0); Cvar_Register (&precache_cvar, 0, 0); - QFS_GamedirCallback (s_gamedir); + QFS_GamedirCallback (s_gamedir, 0); Cmd_AddCommand ("soundlist", s_soundlist_f, "Reports a list of sounds in the cache"); diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 16c93c8a9..dc907958f 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -132,7 +132,7 @@ CL_TEnts_Precache (void) } static void -cl_tents_precache (int phase) +cl_tents_precache (int phase, void *data) { if (!phase) { return; @@ -143,7 +143,7 @@ cl_tents_precache (int phase) void CL_TEnts_Init (void) { - QFS_GamedirCallback (cl_tents_precache); + QFS_GamedirCallback (cl_tents_precache, 0); for (int i = 0; i < 360; i++) { float ang = i * M_PI / 360; beam_rolls[i] = (vec4f_t) { sin (ang), 0, 0, cos (ang) }; diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index af40bfa75..cb4aa271d 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -259,9 +259,13 @@ static const char *qfs_default_dirconf = " };" "}"; +typedef struct { + gamedir_callback_t *callback; + void *data; +} gdcallback_t; #define GAMEDIR_CALLBACK_CHUNK 16 -static gamedir_callback_t **gamedir_callbacks; +static gdcallback_t *gamedir_callbacks; static int num_gamedir_callbacks; static int max_gamedir_callbacks; @@ -1404,20 +1408,20 @@ QFS_Gamedir (const char *gamedir) // Make sure everyone else knows we've changed gamedirs for (i = 0; i < num_gamedir_callbacks; i++) { - gamedir_callbacks[i] (0); + gamedir_callbacks[i].callback (0, gamedir_callbacks[i].data); } Cache_Flush (); for (i = 0; i < num_gamedir_callbacks; i++) { - gamedir_callbacks[i] (1); + gamedir_callbacks[i].callback (1, gamedir_callbacks[i].data); } } VISIBLE void -QFS_GamedirCallback (gamedir_callback_t *func) +QFS_GamedirCallback (gamedir_callback_t *func, void *data) { if (num_gamedir_callbacks == max_gamedir_callbacks) { size_t size = (max_gamedir_callbacks + GAMEDIR_CALLBACK_CHUNK) - * sizeof (gamedir_callback_t *); + * sizeof (gdcallback_t); gamedir_callbacks = realloc (gamedir_callbacks, size); if (!gamedir_callbacks) Sys_Error ("Too many gamedir callbacks!\n"); @@ -1428,7 +1432,8 @@ QFS_GamedirCallback (gamedir_callback_t *func) Sys_Error ("null gamedir callback\n"); } - gamedir_callbacks[num_gamedir_callbacks] = func; + gamedir_callbacks[num_gamedir_callbacks].callback = func; + gamedir_callbacks[num_gamedir_callbacks].data = data; num_gamedir_callbacks++; } diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 8cfb4dd56..820c83d8e 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -206,7 +206,7 @@ gl_Draw_PicFromWad (const char *name) } static void -Draw_ClearCache (int phase) +Draw_ClearCache (int phase, void *data) { cachepic_t *pic; int i; @@ -356,7 +356,7 @@ gl_Draw_Init (void) Cmd_AddCommand ("gl_texturemode", &GL_TextureMode_f, "Texture mipmap quality."); - QFS_GamedirCallback (Draw_ClearCache); + QFS_GamedirCallback (Draw_ClearCache, 0); // load the console background and the charset by hand, because we need to // write the version string into the background before turning it into a diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index bed1559e5..d24d57f97 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -365,7 +365,7 @@ glsl_Draw_TextBox (int x, int y, int width, int lines, byte alpha) } static void -Draw_ClearCache (int phase) +Draw_ClearCache (int phase, void *data) { if (phase) return; @@ -382,7 +382,7 @@ glsl_Draw_Init (void) //FIXME glpic_t *gl; pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, 0, 0); - QFS_GamedirCallback (Draw_ClearCache); + QFS_GamedirCallback (Draw_ClearCache, 0); //FIXME temporary work around for the timing of cvar creation and palette //loading //crosshaircolor->callback (crosshaircolor); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 6a643b708..cf72e69cd 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -2057,7 +2057,7 @@ CL_Init_Memory (void) } static void -CL_Autoexec (int phase) +CL_Autoexec (int phase, void *data) { if (!phase) return; @@ -2092,7 +2092,7 @@ Host_Init (void) pr_gametype = "quakeworld"; QFS_Init (hunk, "qw"); - QFS_GamedirCallback (CL_Autoexec); + QFS_GamedirCallback (CL_Autoexec, 0); PI_Init (); Sys_RegisterShutdown (Net_LogStop, 0); diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index e2d64d170..511001ba7 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2338,7 +2338,7 @@ maxclients_f (void *data, const cvar_t *cvar) } static void -gamedir_f (int phase) +gamedir_f (int phase, void *data) { if (!phase) return; @@ -2679,7 +2679,7 @@ SV_Init (void) memhunk_t *hunk = SV_Init_Memory (); - QFS_GamedirCallback (gamedir_f); + QFS_GamedirCallback (gamedir_f, 0); svs.maxclients = MAX_CLIENTS; svs.info = Info_ParseString ("", MAX_SERVERINFO_STRING, 0); localinfo = Info_ParseString ("", 0, 0); // unlimited From da90d9313512fd735de74b2e50317cf0539a40eb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 16:17:43 +0900 Subject: [PATCH 2892/3664] [sound] Move most spacialization fields out of channel_t More shrinkage. It turned out the mixer uses the phase fields, so they couldn't be removed, but even at 192kHz, +/- 127 samples produces sufficient phase separation for a 21cm head (which is, actually, pretty big: mine is about 15cm across), but that change can come later. The ambient sound loading has been removed from snd_channels because 1) it doesn't work for nq, 2) it should never have been there in the first place (it belongs in the client, but that needs some more API). --- include/snd_internal.h | 5 +- libs/audio/renderer/snd_channels.c | 78 ++++++++++++++++++------------ libs/audio/renderer/snd_dma.c | 3 +- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index e3b27bc87..0214bfbbe 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -229,10 +229,7 @@ struct channel_s { unsigned end; //!< end time in global paintsamples unsigned pos; //!< sample position in sfx unsigned looping; //!< where to loop, -1 = no looping - vec3_t origin; //!< origin of sound effect - vec_t dist_mult; //!< distance multiplier (attenuation/clip) int pause; //!< don't update the channel at all - float volume; //!< 0-1 overall channel volume int phase; //!< phase shift between l-r in samples int oldphase; //!< phase shift between l-r in samples /** signal between main program and mixer thread that the channel is to be @@ -340,6 +337,8 @@ extern int snd_total_channels; //!< number of active channels */ channel_t *SND_AllocChannel (snd_t *snd); +void SND_ChannelSetVolume (channel_t *chan, float volume); + /** Stop a channel from playing. \param snd sound system state \param chan the channel to stop diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index f32d1f14f..cf04aaeec 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -60,9 +60,16 @@ typedef struct entchan_s { int channel; // per-entity sound channel } entchan_t; +typedef struct spacial_s { + vec3_t origin; //!< origin of sound effect + vec_t dist_mult; //!< distance multiplier (attenuation/clip) + float volume; //!< 0-1 overall channel volume +} spacial_t; + int snd_total_channels; channel_t snd_channels[MAX_CHANNELS]; static entchan_t snd_entity_channels[MAX_CHANNELS]; +static spacial_t snd_spacialization[MAX_CHANNELS]; static int snd_free_channels[MAX_CHANNELS]; static int snd_num_free_channels; /* Dynamic channels are (usually) short sound bytes, never looped. They do not @@ -347,14 +354,6 @@ s_playvol_f (void *_snd) static void s_channels_gamedir (int phase, void *_snd) { - //FIXME for some reason, a gamedir change causes semi-random - //"already released" cache errors. fortunatly, servers don't change - //gamedir often, so I'll put this in the too-hard basket for now. - //XXX FIXME set ambient sounds - //if (phase) { - // ambient_sfx[AMBIENT_WATER] = SND_PrecacheSound (snd, "ambience/water1.wav"); - // ambient_sfx[AMBIENT_SKY] = SND_PrecacheSound (snd, "ambience/wind2.wav"); - //} } void @@ -442,8 +441,10 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) ambient_channel++) { chan = ambient_channels[ambient_channel]; if (chan) { - chan->volume = 0; - chan->leftvol = chan->rightvol = chan->volume; + int chan_ind = chan - snd_channels; + spacial_t *spacial = &snd_spacialization[chan_ind]; + spacial->volume = 0; + chan->leftvol = chan->rightvol = spacial->volume; } } return; @@ -474,23 +475,26 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) // sfx will be written to chan->sfx later to ensure mixer doesn't use // channel prematurely. + int chan_ind = chan - snd_channels; + spacial_t *spacial = &snd_spacialization[chan_ind]; + vol = ambient_level * ambient_sound_level[ambient_channel] * (1/255.0); if (vol < 8/255.0) vol = 0; // don't adjust volume too fast float fade = ambient_fade * (1/255.0); - if (chan->volume < vol) { - chan->volume += *snd_render_data.host_frametime * fade; - if (chan->volume > vol) - chan->volume = vol; - } else if (chan->volume > vol) { - chan->volume -= *snd_render_data.host_frametime * fade; - if (chan->volume < vol) - chan->volume = vol; + if (spacial->volume < vol) { + spacial->volume += *snd_render_data.host_frametime * fade; + if (spacial->volume > vol) + spacial->volume = vol; + } else if (spacial->volume > vol) { + spacial->volume -= *snd_render_data.host_frametime * fade; + if (spacial->volume < vol) + spacial->volume = vol; } - chan->leftvol = chan->rightvol = chan->volume; + chan->leftvol = chan->rightvol = spacial->volume; chan->sfx = sfx; } } @@ -506,19 +510,21 @@ s_spatialize (snd_t *snd, channel_t *ch) // prepare to lerp from prev to next phase ch->oldphase = ch->phase; + spacial_t *spacial = &snd_spacialization[chan_ind]; + // anything coming from the view entity will always be full volume if (!snd_render_data.viewentity || snd_entity_channels[chan_ind].id == *snd_render_data.viewentity) { - ch->leftvol = ch->volume; - ch->rightvol = ch->volume; + ch->leftvol = spacial->volume; + ch->rightvol = spacial->volume; ch->phase = 0; return; } // calculate stereo seperation and distance attenuation - VectorSubtract (ch->origin, listener_origin, source_vec); + VectorSubtract (spacial->origin, listener_origin, source_vec); - dist = VectorNormalize (source_vec) * ch->dist_mult; + dist = VectorNormalize (source_vec) * spacial->dist_mult; dot = DotProduct (listener_right, source_vec); if (snd_swapchannelside) @@ -536,12 +542,12 @@ s_spatialize (snd_t *snd, channel_t *ch) // add in distance effect scale = (1.0 - dist) * rscale; - ch->rightvol = ch->volume * scale; + ch->rightvol = spacial->volume * scale; if (ch->rightvol < 0) ch->rightvol = 0; scale = (1.0 - dist) * lscale; - ch->leftvol = ch->volume * scale; + ch->leftvol = spacial->volume * scale; if (ch->leftvol < 0) ch->leftvol = 0; @@ -656,9 +662,10 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, int chan_ind = target_chan - snd_channels; // spatialize - VectorCopy (origin, target_chan->origin); - target_chan->dist_mult = attenuation / sound_nominal_clip_dist; - target_chan->volume = vol; + spacial_t *spacial = &snd_spacialization[chan_ind]; + VectorCopy (origin, spacial->origin); + spacial->dist_mult = attenuation / sound_nominal_clip_dist; + spacial->volume = vol; snd_entity_channels[chan_ind] = (entchan_t) { .id = entnum, .channel = entchannel, @@ -737,9 +744,10 @@ SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol, if (!(osfx = sfx->open (sfx))) return; - VectorCopy (origin, ss->origin); - ss->volume = vol; - ss->dist_mult = attenuation / sound_nominal_clip_dist; + spacial_t *spacial = &snd_spacialization[ss_ind]; + VectorCopy (origin, spacial->origin); + spacial->volume = vol; + spacial->dist_mult = attenuation / sound_nominal_clip_dist; ss->end = 0; s_spatialize (snd, ss); @@ -771,3 +779,11 @@ SND_LocalSound (snd_t *snd, const char *sound) viewent = *snd_render_data.viewentity; SND_StartSound (snd, viewent, -1, sfx, (vec4f_t) {0, 0, 0, 1}, 1, 1); } + +void +SND_ChannelSetVolume (channel_t *chan, float volume) +{ + int chan_ind = chan - snd_channels; + snd_spacialization[chan_ind].volume = volume; + chan->leftvol = chan->rightvol = volume; +} diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 6d891e291..a78672c8c 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -522,8 +522,7 @@ s_channel_get_state (channel_t *chan) static void s_channel_set_volume (channel_t *chan, float volume) { - chan->volume = volume; - chan->leftvol = chan->rightvol = chan->volume; + SND_ChannelSetVolume (chan, volume); } static void From 632226dd32f8d8df06abef951924680877b52f62 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 17:05:03 +0900 Subject: [PATCH 2893/3664] [sound] Rename sfxbuffer_t's length to size The field is the size of the buffer, while "length" is a bit ambiguous between buffer length or sfx length. --- include/snd_internal.h | 2 +- libs/audio/renderer/flac.c | 2 +- libs/audio/renderer/snd_mem.c | 20 ++++++++++---------- libs/audio/renderer/snd_mix.c | 8 ++++---- libs/audio/renderer/snd_resample.c | 2 +- libs/audio/renderer/snd_sfx.c | 2 +- libs/audio/renderer/vorbis.c | 2 +- libs/audio/renderer/wav.c | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index 0214bfbbe..70420f890 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -143,7 +143,7 @@ struct wavinfo_s { struct sfxbuffer_s { unsigned head; //!< ring buffer head position in sampels unsigned tail; //!< ring buffer tail position in sampels - unsigned length; //!< length of buffer in frames + unsigned size; //!< size of buffer in frames unsigned pos; //!< position of tail within full stream unsigned channels; //!< number of channels per frame sfxpaint_t *paint; //!< channel count specific paint function diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index fbfd28b55..53956e451 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -299,7 +299,7 @@ flac_load (flacfile_t *ff, sfxblock_t *block, cache_allocator_t allocator) SND_SetPaint (sb); SND_SetupResampler (sb, 0); SND_Resample (sb, data, info->frames); - sb->head = sb->length; + sb->head = sb->size; bail: if (data) free (data); diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 49c263ac4..1374f03d3 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -147,9 +147,9 @@ static void read_samples (sfxbuffer_t *buffer, int count) { - if (buffer->head + count > buffer->length) { - count -= buffer->length - buffer->head; - read_samples (buffer, buffer->length - buffer->head); + if (buffer->head + count > buffer->size) { + count -= buffer->size - buffer->head; + read_samples (buffer, buffer->size - buffer->head); read_samples (buffer, count); } else { sfx_t *sfx = buffer->sfx; @@ -163,8 +163,8 @@ read_samples (sfxbuffer_t *buffer, int count) if (c > 0) { buffer->head += count; - if (buffer->head >= buffer->length) - buffer->head -= buffer->length; + if (buffer->head >= buffer->size) + buffer->head -= buffer->size; } } } @@ -179,7 +179,7 @@ fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer, // find out how many samples can be read into the buffer samples = buffer->tail - buffer->head - SAMPLE_GAP; if (buffer->tail <= buffer->head) - samples += buffer->length; + samples += buffer->size; if (headpos + samples > sfx->length) { if (sfx->loopstart == (unsigned int)-1) { @@ -233,7 +233,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count) // find out how many samples the buffer currently holds samples = buffer->head - buffer->tail; if (buffer->head < buffer->tail) - samples += buffer->length; + samples += buffer->size; // find out where head points to in the stream headpos = buffer->pos + samples; @@ -276,8 +276,8 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count) } buffer->tail += count; - if (buffer->tail >= buffer->length) - buffer->tail -= buffer->length; + if (buffer->tail >= buffer->size) + buffer->tail -= buffer->size; } fill_buffer (sfx, stream, buffer, info, headpos); return !stream->error; @@ -362,7 +362,7 @@ SND_GetCache (long frames, int rate, int channels, if (!sb) return 0; memset (sb, 0, sizeof (sfxbuffer_t) + size); - sb->length = len; + sb->size = len; memcpy (sb->data + len * channels, "\xde\xad\xbe\xef", 4); return sb; } diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index c99ca49a5..92789aaa1 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -82,13 +82,13 @@ snd_paint_channel (channel_t *ch, sfxbuffer_t *sb, int count) count -= offs; ch->pos = 0; } - if (ch->pos < sb->pos || ch->pos - sb->pos >= sb->length) + if (ch->pos < sb->pos || ch->pos - sb->pos >= sb->size) sb->setpos (sb, ch->pos); - pos = (ch->pos - sb->pos + sb->tail) % sb->length; + pos = (ch->pos - sb->pos + sb->tail) % sb->size; samps = sb->data + pos * sb->channels; - if (pos + count > sb->length) { - unsigned sub = sb->length - pos; + if (pos + count > sb->size) { + unsigned sub = sb->size - pos; sb->paint (offs, ch, samps, sub); sb->paint (offs + sub, ch, sb->data, count - sub); } else { diff --git a/libs/audio/renderer/snd_resample.c b/libs/audio/renderer/snd_resample.c index 9e0848350..e8121aa23 100644 --- a/libs/audio/renderer/snd_resample.c +++ b/libs/audio/renderer/snd_resample.c @@ -56,7 +56,7 @@ typedef struct { static void check_buffer_integrity (sfxbuffer_t *sb, int width, const char *func) { - byte *x = (byte *) sb->data + sb->length * width; + byte *x = (byte *) sb->data + sb->size * width; if (memcmp (x, "\xde\xad\xbe\xef", 4)) Sys_Error ("%s screwed the pooch %02x%02x%02x%02x", func, x[0], x[1], x[2], x[3]); diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index b632ba6b7..3fde56efe 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -156,7 +156,7 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file, stream->wavinfo = *sfx->wavinfo (sfx); - stream->buffer.length = frames; + stream->buffer.size = frames; stream->buffer.advance = SND_StreamAdvance; stream->buffer.setpos = SND_StreamSetPos; stream->buffer.sfx = new_sfx; diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index 1477eb303..2d1060e02 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -180,7 +180,7 @@ vorbis_load (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator) SND_SetPaint (sb); SND_SetupResampler (sb, 0); SND_Resample (sb, data, info->frames); - sb->head = sb->length; + sb->head = sb->size; bail: if (data) free (data); diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index 2129973f1..59379f295 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -87,7 +87,7 @@ wav_callback_load (void *object, cache_allocator_t allocator) SND_SetPaint (buffer); SND_SetupResampler (buffer, 0); SND_Resample (buffer, fdata, info->frames); - buffer->head = buffer->length; + buffer->head = buffer->size; free (data); } From 855b9dccc08fad27a61113f401480b1d88760b92 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 18:29:37 +0900 Subject: [PATCH 2894/3664] [sound] Don't free channels when allocating SND_AllocChannel is a little too aggressive in freeing channels that have finished as the channel may be externally owned (eg, by cd_file). Get bgm looping working again. --- libs/audio/renderer/snd_channels.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index cf04aaeec..b41f30ae2 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -164,14 +164,6 @@ SND_AllocChannel (snd_t *snd) { channel_t *chan; - // chech for any channels that have become available as the mixer thread - // has finished with them - for (int i = 0; i < MAX_CHANNELS; i++) { - channel_t *ch = &snd_channels[i]; - if (ch->done) { - snd_free_channel (ch); - } - } //Sys_MaskPrintf (SYS_snd, "SND_AllocChannel: free channels: %d\n", // snd_num_free_channels); if (!snd_num_free_channels) { From deab21cb4b2b93c5123a579710989bc80b1d54b0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 18:45:11 +0900 Subject: [PATCH 2895/3664] [sound] Move stream buffers into locked memory Streams are the easy one as they were never in the cache. As a side effect, sfxstream_t is much smaller as it no longer has the buffer embedded in the struct. --- include/snd_internal.h | 17 ++++-- libs/audio/renderer/snd_dma.c | 12 ++-- libs/audio/renderer/snd_mem.c | 90 +++++++++++++++++++++++++++--- libs/audio/renderer/snd_resample.c | 2 +- libs/audio/renderer/snd_sfx.c | 21 ++++--- 5 files changed, 110 insertions(+), 32 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index 70420f890..ace403c75 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -62,15 +62,15 @@ struct sfx_s unsigned int loopstart; union { - struct sfxstream_s *stream; - struct sfxblock_s *block; + sfxstream_t *stream; + sfxblock_t *block; } data; - struct sfxbuffer_s *(*touch) (sfx_t *sfx); - struct sfxbuffer_s *(*retain) (sfx_t *sfx); + sfxbuffer_t *(*touch) (sfx_t *sfx); + sfxbuffer_t *(*retain) (sfx_t *sfx); void (*release) (sfx_t *sfx); - struct sfxbuffer_s *(*getbuffer) (sfx_t *sfx); + sfxbuffer_t *(*getbuffer) (sfx_t *sfx); struct wavinfo_s *(*wavinfo) (sfx_t *sfx); sfx_t *(*open) (sfx_t *sfx); @@ -207,7 +207,7 @@ struct sfxstream_s { \param pos frame position with the stream */ int (*seek)(sfxstream_t *stream, int pos); - sfxbuffer_t buffer; //init (&snd)) { - Sys_Printf ("S_Startup: S_O_Init failed.\n"); - sound_started = 0; + Sys_Printf ("S_Startup: output init failed.\n"); return; } if (!snd.xfer) @@ -362,6 +360,8 @@ s_init_cvars (void) Cvar_Register (&snd_mixahead_cvar, 0, 0); Cvar_Register (&snd_noextraupdate_cvar, 0, 0); Cvar_Register (&snd_show_cvar, 0, 0); + + SND_Memory_Init_Cvars (); } static void @@ -379,8 +379,6 @@ s_init (void) Cmd_AddCommand ("snd_force_unblock", s_snd_force_unblock, "fix permanently blocked sound"); - snd_initialized = true; - s_startup (); if (sound_started == 0) // sound startup failed? Bail out. diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 1374f03d3..d9715a9f8 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -1,9 +1,10 @@ /* snd_mem.c - sound caching + sound memory management Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2003 Bill Currie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -35,10 +36,6 @@ # include #endif -#if defined(_WIN32) && defined(HAVE_MALLOC_H) -#include -#endif - #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/sound.h" @@ -51,6 +48,85 @@ #define SAMPLE_GAP 4 +static uint32_t snd_mem_size; +static cvar_t snd_mem_size_cvar = { + .name = "snd_mem_size", + .description = + "Amount of LOCKED memory to allocate to the sound system in MB. " + "Defaults to 32MB.", + .default_value = "32", + .flags = CVAR_ROM, + .value = { .type = &cexpr_uint, .value = &snd_mem_size }, +}; + +static memzone_t *snd_zone; + +void +SND_Memory_Init_Cvars (void) +{ + Cvar_Register (&snd_mem_size_cvar, 0, 0); +} + +static void +snd_zone_error (void *data, const char *msg) +{ + Sys_Error ("Sound: %s", msg); +} + +static void +snd_memory_shutdown (void *data) +{ + if (snd_zone) { + size_t size = snd_mem_size * 1024 * 1024; + Sys_Free (snd_zone, size); + } +} + +int +SND_Memory_Init (void) +{ + size_t size = snd_mem_size * 1024 * 1024; + + snd_zone = Sys_Alloc (size); + if (!snd_zone) { + Sys_Printf ("Sound: Unable to allocate %uMB buffer\n", snd_mem_size); + return 0; + } + if (!Sys_LockMemory (snd_zone, size)) { + Sys_Printf ("Sound: Unable to lock %uMB buffer\n", snd_mem_size); + Sys_Free (snd_zone, size); + return 0; + } + Z_ClearZone (snd_zone, size, 0, 1); + Z_SetError (snd_zone, snd_zone_error, 0); + + Sys_MaskPrintf (SYS_snd, "Sound: Initialized %uMB buffer\n", snd_mem_size); + + Sys_RegisterShutdown (snd_memory_shutdown, 0); + return 1; +} + +sfxbuffer_t * +SND_Memory_AllocBuffer (unsigned samples) +{ + size_t size = field_offset (sfxbuffer_t, data[samples]); + // Z_Malloc (currently) clears memory, don't need that for the whole + // buffer (just the header), but Z_TagMalloc // does not + // +4 for sentinel + sfxbuffer_t *buffer = Z_TagMalloc (snd_zone, size + 4, 1); + // place a sentinel at the end of the buffer for added safety + memcpy ((byte *) buffer->data + size, "\xde\xad\xbe\xef", 4); + // clear buffer header + memset (buffer, 0, sizeof (sfxbuffer_t)); + return buffer; +} + +void +SND_Memory_FreeBuffer (sfxbuffer_t *buffer) +{ + Z_Free (snd_zone, buffer); +} + static sfxbuffer_t * snd_fail (sfx_t *sfx) { @@ -117,13 +193,13 @@ SND_CacheRelease (sfx_t *sfx) sfxbuffer_t * SND_StreamGetBuffer (sfx_t *sfx) { - return &sfx->data.stream->buffer; + return sfx->data.stream->buffer; } sfxbuffer_t * SND_StreamRetain (sfx_t *sfx) { - return &sfx->data.stream->buffer; + return sfx->data.stream->buffer; } void diff --git a/libs/audio/renderer/snd_resample.c b/libs/audio/renderer/snd_resample.c index e8121aa23..c243df764 100644 --- a/libs/audio/renderer/snd_resample.c +++ b/libs/audio/renderer/snd_resample.c @@ -92,7 +92,7 @@ static int snd_read (sfxstream_t *stream, float *data, int frames) { snd_null_state_t *state = (snd_null_state_t *) stream->state; - int channels = stream->buffer.channels; + int channels = stream->buffer->channels; int framesize = channels * sizeof (float); int count; int read = 0; diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 3fde56efe..3b63fde76 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -124,7 +124,6 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file, sfxstream_t *stream = sfx->data.stream; wavinfo_t *info = &stream->wavinfo; int frames; - int size; // if the speed is 0, there is no sound driver (probably failed to connect // to jackd) @@ -144,11 +143,10 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file, frames = snd->speed * 0.3; frames = (frames + 255) & ~255; - size = frames * info->channels * sizeof (float); - stream = calloc (1, sizeof (sfxstream_t) + size); + stream = calloc (1, sizeof (sfxstream_t)); new_sfx->data.stream = stream; - memcpy ((byte *) stream->buffer.data + size, "\xde\xad\xbe\xef", 4); + stream->buffer = SND_Memory_AllocBuffer (frames * info->channels); stream->file = file; stream->sfx = new_sfx; stream->ll_read = read; @@ -156,14 +154,14 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file, stream->wavinfo = *sfx->wavinfo (sfx); - stream->buffer.size = frames; - stream->buffer.advance = SND_StreamAdvance; - stream->buffer.setpos = SND_StreamSetPos; - stream->buffer.sfx = new_sfx; - SND_SetPaint (&stream->buffer); + stream->buffer->size = frames; + stream->buffer->advance = SND_StreamAdvance; + stream->buffer->setpos = SND_StreamSetPos; + stream->buffer->sfx = new_sfx; + SND_SetPaint (stream->buffer); - SND_SetupResampler (&stream->buffer, 1); // get sfx setup properly - stream->buffer.setpos (&stream->buffer, 0); // pre-fill the buffer + SND_SetupResampler (stream->buffer, 1); // get sfx setup properly + stream->buffer->setpos (stream->buffer, 0); // pre-fill the buffer return new_sfx; } @@ -173,6 +171,7 @@ SND_SFX_StreamClose (sfx_t *sfx) { sfxstream_t *stream = sfx->data.stream; SND_PulldownResampler (stream); + SND_Memory_FreeBuffer (stream->buffer); free (stream); free (sfx); } From 038813e04c975afb12c46886cf7452d7b8fad312 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 21:09:01 +0900 Subject: [PATCH 2896/3664] [sound] Fix midi config path I guess wildmidi has been shipping its own config for a while now. Since QF relies on wildmidi, it should use wildmidi's config by default. --- libs/audio/renderer/midi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index 3172c8ea2..bebb1f9f0 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -70,8 +70,8 @@ static char *wildmidi_config; static cvar_t wildmidi_config_cvar = { .name = "wildmidi_config", .description = - "path/filename of timidity.cfg", - .default_value = "/etc/timidity.cfg", + "path/filename of wildmidi.cfg", + .default_value = "/etc/wildmidi/wildmidi.cfg", .flags = CVAR_ROM, .value = { .type = 0, .value = &wildmidi_config }, }; From 4e550ac9c714091bf98770c14f97dff3f2170209 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Jun 2022 23:55:31 +0900 Subject: [PATCH 2897/3664] [sound] Move block buffers into locked memory Sounds no longer use the cache, which is good for multi-threaded, but a pain for memory management: the buffers are shared between channels that play back the sounds, but when the sounds were cached, they were automagically (thus problematically) freed when the space was needed. That no longer happens, so they leak. I think the solution is to use reference counting and retain/release in sfx->open() and sfx->close(). --- include/snd_internal.h | 32 ++++++++------------- libs/audio/renderer/flac.c | 21 +++++++------- libs/audio/renderer/snd_channels.c | 1 - libs/audio/renderer/snd_mem.c | 45 ++---------------------------- libs/audio/renderer/snd_resample.c | 10 +++++++ libs/audio/renderer/snd_sfx.c | 7 ++--- libs/audio/renderer/vorbis.c | 21 +++++++------- libs/audio/renderer/wav.c | 15 +++++----- 8 files changed, 56 insertions(+), 96 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index ace403c75..352138114 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -164,7 +164,7 @@ struct sfxbuffer_s { /** Sample data. The block at the beginning of the buffer (size depends on sample size) */ - float data[1]; + float data[]; }; /** Representation of sound loaded that is streamed in as needed. @@ -271,8 +271,8 @@ void SND_Memory_FreeBuffer (sfxbuffer_t *buffer); \param info \param loader */ -void SND_SFX_Cache (sfx_t *sfx, char *realname, wavinfo_t info, - cache_loader_t loader); +void SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info, + sfxbuffer_t *(*load) (sfxblock_t *block)); /** Stream sound data. Initializes streaming fields of sfx. \param sfx @@ -455,9 +455,9 @@ void SND_PaintChannels(snd_t *snd, unsigned int endtime); void SND_InitScaletable (snd_t *snd); /** Set the paint function of the sfxbuffer - \param sc sfxbuffer to set. + \param sb sfxbuffer to set. */ -void SND_SetPaint (sfxbuffer_t *sc); +void SND_SetPaint (sfxbuffer_t *sb); ///@} @@ -465,11 +465,14 @@ void SND_SetPaint (sfxbuffer_t *sc); \ingroup sound_render */ ///@{ + +unsigned SND_ResamplerFrames (sfx_t *sfx); + /** Set up the various parameters that depend on the actual sample rate. - \param sc buffer to setup + \param sb buffer to setup \param streamed non-zero if this is for a stream. */ -void SND_SetupResampler (sfxbuffer_t *sc, int streamed); +void SND_SetupResampler (sfxbuffer_t *sb, int streamed); /** Free memory allocated for the resampler. \param stream stream to pulldown @@ -477,11 +480,11 @@ void SND_SetupResampler (sfxbuffer_t *sc, int streamed); void SND_PulldownResampler (sfxstream_t *stream); /** Copy/resample data into buffer, resampling as necessary. - \param sc buffer to write resampled sound + \param sb buffer to write resampled sound \param data raw sample data \param length number of frames to resample */ -void SND_Resample (sfxbuffer_t *sc, float *data, int length); +void SND_Resample (sfxbuffer_t *sb, float *data, int length); /** Convert integer sample data to float sample data. \param idata integer data buffer @@ -612,17 +615,6 @@ int SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count); \param pos sample position with the stream */ void SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos); - -/** Allocate a sound buffer from cache for cached sounds. - \param samples size in samples - \param rate sample rate - \param channels number of channels in input data - \param block cached sound descriptor to initialize - \param allocator cache allocator function - \return pointer to sound sample buffer (setup for block mode) -*/ -sfxbuffer_t *SND_GetCache (long samples, int rate, int channels, - sfxblock_t *block, cache_allocator_t allocator); ///@} #endif//__snd_internal_h diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index 53956e451..9868d12cd 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -279,7 +279,7 @@ flac_read (flacfile_t *ff, float *buf, int len) } static sfxbuffer_t * -flac_load (flacfile_t *ff, sfxblock_t *block, cache_allocator_t allocator) +flac_load (flacfile_t *ff, sfxblock_t *block) { float *data; sfxbuffer_t *sb = 0; @@ -289,10 +289,11 @@ flac_load (flacfile_t *ff, sfxblock_t *block, cache_allocator_t allocator) data = malloc (info->datalen); if (!data) goto bail; - sb = SND_GetCache (info->frames, info->rate, info->channels, - block, allocator); + unsigned buffer_frames = SND_ResamplerFrames (sfx); + sb = SND_Memory_AllocBuffer (buffer_frames * info->channels); if (!sb) goto bail; + sb->size = buffer_frames * info->channels; sb->sfx = sfx; if (flac_read (ff, data, info->frames) < 0) goto bail; @@ -307,31 +308,29 @@ flac_load (flacfile_t *ff, sfxblock_t *block, cache_allocator_t allocator) return sb; } -static void -flac_callback_load (void *object, cache_allocator_t allocator) +static sfxbuffer_t * +flac_callback_load (sfxblock_t *block) { QFile *file; flacfile_t *ff; - sfxblock_t *block = (sfxblock_t *) object; - file = QFS_FOpenFile (block->file); if (!file) - return; //FIXME Sys_Error? + return 0; if (!(ff = flac_open (file))) { Sys_Printf ("Input does not appear to be an Ogg bitstream.\n"); Qclose (file); - return; //FIXME Sys_Error? + return 0; } - flac_load (ff, block, allocator); + return flac_load (ff, block); } static void flac_cache (sfx_t *sfx, char *realname, flacfile_t *ff, wavinfo_t info) { flac_close (ff); - SND_SFX_Cache (sfx, realname, info, flac_callback_load); + SND_SFX_Block (sfx, realname, info, flac_callback_load); } static long diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index b41f30ae2..8b56415ff 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -287,7 +287,6 @@ s_play_f (void *_snd) dsprintf (name, "%s", Cmd_Argv (i)); } sfx = SND_PrecacheSound (snd, name->str); - printf ("%s %p\n", name->str, sfx); SND_StartSound (snd, hash++, 0, sfx, listener_origin, 1.0, 1.0); i++; } diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index d9715a9f8..4d4c5f2f4 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -115,7 +115,7 @@ SND_Memory_AllocBuffer (unsigned samples) // +4 for sentinel sfxbuffer_t *buffer = Z_TagMalloc (snd_zone, size + 4, 1); // place a sentinel at the end of the buffer for added safety - memcpy ((byte *) buffer->data + size, "\xde\xad\xbe\xef", 4); + memcpy (&buffer->data[samples], "\xde\xad\xbe\xef", 4); // clear buffer header memset (buffer, 0, sizeof (sfxbuffer_t)); return buffer; @@ -153,7 +153,7 @@ snd_open_fail (sfx_t *sfx) sfxbuffer_t * SND_CacheTouch (sfx_t *sfx) { - return Cache_Check (&sfx->data.block->cache); + return sfx->data.block->buffer; } sfxbuffer_t * @@ -165,29 +165,12 @@ SND_CacheGetBuffer (sfx_t *sfx) sfxbuffer_t * SND_CacheRetain (sfx_t *sfx) { - sfxblock_t *block = sfx->data.block; - block->buffer = Cache_TryGet (&block->cache); - if (!block->buffer) - Sys_Printf ("failed to cache sound!\n"); - return block->buffer; + return sfx->data.block->buffer; } void SND_CacheRelease (sfx_t *sfx) { - sfxblock_t *block = sfx->data.block; - // due to the possibly asynchronous nature of the mixer, the cache - // may have been flushed behind our backs - if (block->cache.data) { - if (!Cache_ReadLock (&block->cache)) { - Sys_Printf ("WARNING: taniwha screwed up in the sound engine: %s\n", - sfx->name); - return; - } - Cache_Release (&block->cache); - if (!Cache_ReadLock (&block->cache)) - block->buffer = 0; - } } sfxbuffer_t * @@ -420,25 +403,3 @@ bail: free (realname); return -1; } - -sfxbuffer_t * -SND_GetCache (long frames, int rate, int channels, - sfxblock_t *block, cache_allocator_t allocator) -{ - int len, size; - float stepscale; - sfxbuffer_t *sb; - sfx_t *sfx = block->sfx; - snd_t *snd = sfx->snd; - - stepscale = (float) rate / snd->speed; - len = size = frames / stepscale; - size *= sizeof (float) * channels; - sb = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name); - if (!sb) - return 0; - memset (sb, 0, sizeof (sfxbuffer_t) + size); - sb->size = len; - memcpy (sb->data + len * channels, "\xde\xad\xbe\xef", 4); - return sb; -} diff --git a/libs/audio/renderer/snd_resample.c b/libs/audio/renderer/snd_resample.c index c243df764..97f4acbc4 100644 --- a/libs/audio/renderer/snd_resample.c +++ b/libs/audio/renderer/snd_resample.c @@ -62,6 +62,16 @@ check_buffer_integrity (sfxbuffer_t *sb, int width, const char *func) x[0], x[1], x[2], x[3]); } +unsigned +SND_ResamplerFrames (sfx_t *sfx) +{ + wavinfo_t *info = sfx->wavinfo (sfx); + snd_t *snd = sfx->snd; + int inrate = info->rate; + double stepscale = (double) snd->speed / inrate; + return info->frames * stepscale; +} + void SND_Resample (sfxbuffer_t *sb, float *data, int length) { diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 3b63fde76..b801a94a0 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -79,8 +79,8 @@ snd_sfx_free (void *_sfx, void *unused) } void -SND_SFX_Cache (sfx_t *sfx, char *realname, wavinfo_t info, - cache_loader_t loader) +SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info, + sfxbuffer_t *(*load) (sfxblock_t *block)) { sfxblock_t *block = calloc (1, sizeof (sfxblock_t)); @@ -94,8 +94,7 @@ SND_SFX_Cache (sfx_t *sfx, char *realname, wavinfo_t info, block->sfx = sfx; block->file = realname; block->wavinfo = info; - - Cache_Add (&block->cache, block, loader); + block->buffer = load (block); } void diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index 2d1060e02..8c51660df 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -160,7 +160,7 @@ vorbis_read (OggVorbis_File *vf, float *buf, int len, wavinfo_t *info) } static sfxbuffer_t * -vorbis_load (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator) +vorbis_load (OggVorbis_File *vf, sfxblock_t *block) { float *data; sfxbuffer_t *sb = 0; @@ -170,10 +170,11 @@ vorbis_load (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator) data = malloc (info->datalen); if (!data) goto bail; - sb = SND_GetCache (info->frames, info->rate, info->channels, - block, allocator); + unsigned buffer_frames = SND_ResamplerFrames (sfx); + sb = SND_Memory_AllocBuffer (buffer_frames * info->channels); if (!sb) goto bail; + sb->size = buffer_frames * info->channels; sb->sfx = sfx; if (vorbis_read (vf, data, info->frames, info) < 0) goto bail; @@ -188,31 +189,29 @@ vorbis_load (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator) return sb; } -static void -vorbis_callback_load (void *object, cache_allocator_t allocator) +static sfxbuffer_t * +vorbis_callback_load (sfxblock_t *block) { QFile *file; OggVorbis_File vf; - sfxblock_t *block = (sfxblock_t *) object; - file = QFS_FOpenFile (block->file); if (!file) - return; //FIXME Sys_Error? + return 0; if (ov_open_callbacks (file, &vf, 0, 0, callbacks) < 0) { Sys_Printf ("Input does not appear to be an Ogg bitstream.\n"); Qclose (file); - return; //FIXME Sys_Error? + return 0; } - vorbis_load (&vf, block, allocator); + return vorbis_load (&vf, block); } static void vorbis_cache (sfx_t *sfx, char *realname, OggVorbis_File *vf, wavinfo_t info) { ov_clear (vf); - SND_SFX_Cache (sfx, realname, info, vorbis_callback_load); + SND_SFX_Block (sfx, realname, info, vorbis_callback_load); } static long diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index 59379f295..fd27b2af7 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -54,10 +54,9 @@ typedef struct { QFile *file; } wav_file_t; -static void -wav_callback_load (void *object, cache_allocator_t allocator) +static sfxbuffer_t * +wav_callback_load (sfxblock_t *block) { - sfxblock_t *block = (sfxblock_t *) object; sfx_t *sfx = block->sfx; const char *name = (const char *) block->file; QFile *file; @@ -69,7 +68,7 @@ wav_callback_load (void *object, cache_allocator_t allocator) file = QFS_FOpenFile (name); if (!file) - return; //FIXME Sys_Error? + return 0; Qseek (file, info->dataofs, SEEK_SET); fdata_ofs = (info->datalen + sizeof (float) - 1) & ~(sizeof (float) - 1); @@ -81,21 +80,23 @@ wav_callback_load (void *object, cache_allocator_t allocator) SND_Convert (data, fdata, info->frames, info->channels, info->width); - buffer = SND_GetCache (info->frames, info->rate, - info->channels, block, allocator); + unsigned buffer_frames = SND_ResamplerFrames (sfx); + buffer = SND_Memory_AllocBuffer (buffer_frames * info->channels); + buffer->size = buffer_frames * info->channels; buffer->sfx = sfx; SND_SetPaint (buffer); SND_SetupResampler (buffer, 0); SND_Resample (buffer, fdata, info->frames); buffer->head = buffer->size; free (data); + return buffer; } static void wav_cache (sfx_t *sfx, char *realname, void *file, wavinfo_t info) { Qclose (file); - SND_SFX_Cache (sfx, realname, info, wav_callback_load); + SND_SFX_Block (sfx, realname, info, wav_callback_load); } static long From 2bb0f0c1044d57fec0d4955d144d9ec607474359 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jun 2022 01:08:45 +0900 Subject: [PATCH 2898/3664] [zone] Add support for reference counting to Z_* And use it for Ruamoko object reference counts. I need reference counts for dealing with block sound buffers since they can be shared by many channels. I figured I take care of Ruamoko's reference count location at the same time. Fixes #27. --- include/QF/zone.h | 3 +++ libs/ruamoko/rua_obj.c | 6 ++--- libs/util/zone.c | 61 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/include/QF/zone.h b/include/QF/zone.h index 00ff536ab..70d140e25 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -109,6 +109,9 @@ void Z_CheckHeap (memzone_t *zone); void Z_SetError (memzone_t *zone, void (*err) (void *data, const char *msg), void *data); void Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size); +int Z_IncRetainCount (memzone_t *zone, void *ptr); +int Z_DecRetainCount (memzone_t *zone, void *ptr); +int Z_GetRetainCount (memzone_t *zone, void *ptr) __attribute__((pure)); memhunk_t *Hunk_Init (void *buf, size_t size); void Hunk_Print (memhunk_t *hunk, qboolean all); diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 7c9875bdb..ee5555e96 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1783,14 +1783,14 @@ rua_class_pose_as (progs_t *pr, void *data) static inline pr_id_t * class_create_instance (progs_t *pr, pr_class_t *class) { - int size = (class->instance_size + 1) * sizeof (pr_type_t); + int size = class->instance_size * sizeof (pr_type_t); pr_type_t *mem; pr_id_t *id = 0; mem = PR_Zone_TagMalloc (pr, size, class->name); if (mem) { memset (mem, 0, size); - id = (pr_id_t *) (mem + 1); + id = (pr_id_t *) mem; id->class_pointer = PR_SetPointer (pr, class); } return id; @@ -1908,7 +1908,7 @@ rua_object_dispose (progs_t *pr, void *data) { pr_id_t *object = &P_STRUCT (pr, pr_id_t, 0); pr_type_t *mem = (pr_type_t *) object; - PR_Zone_Free (pr, mem - 1); + PR_Zone_Free (pr, mem); } static void diff --git a/libs/util/zone.c b/libs/util/zone.c index 3d68a037e..e2aa67c16 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -75,8 +75,10 @@ typedef struct memblock_s { struct memblock_s *next; struct memblock_s *prev; size_t size; // requested size + byte pad[64 - 3 * 4 - 4 * sizeof (size_t)]; int tag; // a tag of 0 is a free block int id; // should be ZONEID + int retain; // reference counter (optional usage) } __attribute__((aligned (64))) memblock_t; struct memzone_s { @@ -104,10 +106,20 @@ z_offset (memzone_t *zone, memblock_t *block) return offset / zone->ele_size + zone->offset; } +static void +z_error (memzone_t *zone, const char *msg) +{ + if (zone->error) + zone->error (zone->data, msg); + Sys_Error ("%s", msg); +} + VISIBLE void Z_ClearZone (memzone_t *zone, size_t size, size_t zone_offset, size_t ele_size) { - memblock_t *block; + memblock_t *block + = __builtin_choose_expr (__builtin_offsetof (memblock_t, retain) == 60, + 0, (void) 0); // set the entire zone to one free block @@ -170,6 +182,13 @@ Z_Free (memzone_t *zone, void *ptr) zone->error (zone->data, "Z_Free: freed a freed pointer"); Sys_Error ("Z_Free: freed a freed pointer"); } + if (block->retain) { + const char *msg = nva ("Z_Free: freed a retained pointer: %d", + block->retain); + if (zone->error) + zone->error (zone->data, msg); + Sys_Error ("%s", msg); + } block->tag = 0; // mark as free block->size = 0; @@ -265,6 +284,7 @@ Z_TagMalloc (memzone_t *zone, size_t size, int tag) base->block_size = size; } + base->retain = 0; // use is optional, but must be 0 to free base->tag = tag; // no longer a free block base->size = requested_size; @@ -339,9 +359,9 @@ Z_Print (memzone_t *zone) zone->size, zone, zone->used); for (block = zone->blocklist.next ; ; block = block->next) { - Sys_Printf ("block:%p size:%7i tag:%5x ofs:%x\n", + Sys_Printf ("block:%p size:%7i tag:%5x ret: %5d ofs:%x\n", block, z_block_size (block), - block->tag, z_offset (zone, block)); + block->tag, block->retain, z_offset (zone, block)); if (block->next == &zone->blocklist) break; // all blocks have been hit @@ -361,14 +381,6 @@ Z_Print (memzone_t *zone) } } -static void -z_error (memzone_t *zone, const char *msg) -{ - if (zone->error) - zone->error (zone->data, msg); - Sys_Error ("%s", msg); -} - void Z_CheckHeap (memzone_t *zone) { @@ -429,6 +441,33 @@ Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size) } } +VISIBLE int +Z_IncRetainCount (memzone_t *zone, void *ptr) +{ + memblock_t *block = (memblock_t *) ((byte *) ptr - sizeof (memblock_t)); + if (!++block->retain) { + z_error (zone, "inc retain count wrapped to 0"); + } + return block->retain; +} + +VISIBLE int +Z_DecRetainCount (memzone_t *zone, void *ptr) +{ + memblock_t *block = (memblock_t *) ((byte *) ptr - sizeof (memblock_t)); + if (--block->retain == -1) { + z_error (zone, "dec retain count wrapped past 0"); + } + return block->retain; +} + +VISIBLE int +Z_GetRetainCount (memzone_t *zone, void *ptr) +{ + memblock_t *block = (memblock_t *) ((byte *) ptr - sizeof (memblock_t)); + return block->retain; +} + VISIBLE void Z_MemInfo (const memzone_t *zone, size_t *used, size_t *size) { From 4694ee693b311e87989bf980ff4a42e32fc9fd8c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jun 2022 01:17:32 +0900 Subject: [PATCH 2899/3664] [zone] Alight zone allocations to 64 bytes Since Ruamoko got vector types, zone's 8-byte alignment was no longer sufficient due to hardware-enforced alignment requirements of the underlying vector operations. Fixes #28. --- libs/util/zone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index e2aa67c16..3c9de3821 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -254,7 +254,7 @@ Z_TagMalloc (memzone_t *zone, size_t size, int tag) // of sufficient size size += sizeof (memblock_t); // account for size of block header size += 4; // space for memory trash tester - size = (size + 7) & ~7; // align to 8-byte boundary + size = (size + 63) & ~63; // align to 64-byte boundary base = rover = zone->rover; start = base->prev; From 2298227546d8739d789ade668e9513b28b083b62 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jun 2022 01:42:30 +0900 Subject: [PATCH 2900/3664] [sound] Check for allocation failures They're currently treated as non-fatal, those sounds just won't ever play. This allows ad_tears to at least load with only 32MB of locked memory (it needs somewhere between 64 and 96). --- libs/audio/renderer/snd_mem.c | 12 ++++++++---- libs/audio/renderer/snd_sfx.c | 5 +++++ libs/audio/renderer/wav.c | 7 ++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 4d4c5f2f4..aa93b6bd0 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -114,10 +114,14 @@ SND_Memory_AllocBuffer (unsigned samples) // buffer (just the header), but Z_TagMalloc // does not // +4 for sentinel sfxbuffer_t *buffer = Z_TagMalloc (snd_zone, size + 4, 1); - // place a sentinel at the end of the buffer for added safety - memcpy (&buffer->data[samples], "\xde\xad\xbe\xef", 4); - // clear buffer header - memset (buffer, 0, sizeof (sfxbuffer_t)); + if (buffer) { + // place a sentinel at the end of the buffer for added safety + memcpy (&buffer->data[samples], "\xde\xad\xbe\xef", 4); + // clear buffer header + memset (buffer, 0, sizeof (sfxbuffer_t)); + } else { + Sys_Printf ("Sound: out of memory: %uMB exhausted\n", snd_mem_size); + } return buffer; } diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index b801a94a0..79a7af51d 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -146,6 +146,11 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file, stream = calloc (1, sizeof (sfxstream_t)); new_sfx->data.stream = stream; stream->buffer = SND_Memory_AllocBuffer (frames * info->channels); + if (!stream->buffer) { + free (stream); + free (new_sfx); + return 0; + } stream->file = file; stream->sfx = new_sfx; stream->ll_read = read; diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index fd27b2af7..68baae734 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -74,21 +74,26 @@ wav_callback_load (sfxblock_t *block) fdata_ofs = (info->datalen + sizeof (float) - 1) & ~(sizeof (float) - 1); len = fdata_ofs + info->frames * info->channels * sizeof (float); data = malloc (len); + if (!data) + goto bail; fdata = (float *) (data + fdata_ofs); Qread (file, data, info->datalen); - Qclose (file); SND_Convert (data, fdata, info->frames, info->channels, info->width); unsigned buffer_frames = SND_ResamplerFrames (sfx); buffer = SND_Memory_AllocBuffer (buffer_frames * info->channels); + if (!buffer) + goto bail; buffer->size = buffer_frames * info->channels; buffer->sfx = sfx; SND_SetPaint (buffer); SND_SetupResampler (buffer, 0); SND_Resample (buffer, fdata, info->frames); buffer->head = buffer->size; +bail: free (data); + Qclose (file); return buffer; } From 11fee8571ca9d4c54af26469756c05d514353467 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jun 2022 16:48:25 +0900 Subject: [PATCH 2901/3664] [zone] Add functions to get and set the tag Getting the tag is possibly useful in general and definitely in debugging. Setting, I'm not so sure as it should be done when allocated, but that's not always possible. Also, correct the return type of z_block_size, though it affected only Z_Print. While an allocation larger than 4GB is... big for zone, the blocks do support it, so printing should too. --- include/QF/zone.h | 4 ++++ libs/util/zone.c | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/QF/zone.h b/include/QF/zone.h index 70d140e25..96ba13a51 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -112,6 +112,10 @@ void Z_CheckPointer (const memzone_t *zone, const void *ptr, size_t size); int Z_IncRetainCount (memzone_t *zone, void *ptr); int Z_DecRetainCount (memzone_t *zone, void *ptr); int Z_GetRetainCount (memzone_t *zone, void *ptr) __attribute__((pure)); +int Z_GetTag (memzone_t *zone, void *ptr) __attribute__((pure)); +void Z_SetTag (memzone_t *zone, void *ptr, int tag); + + memhunk_t *Hunk_Init (void *buf, size_t size); void Hunk_Print (memhunk_t *hunk, qboolean all); diff --git a/libs/util/zone.c b/libs/util/zone.c index 3c9de3821..584d9f8c1 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -92,7 +92,7 @@ struct memzone_s { memblock_t blocklist; // start / end cap for linked list } __attribute__((aligned (64))); -static int +static size_t z_block_size (memblock_t *block) { return block->block_size - sizeof (memblock_t) - 4; @@ -359,7 +359,7 @@ Z_Print (memzone_t *zone) zone->size, zone, zone->used); for (block = zone->blocklist.next ; ; block = block->next) { - Sys_Printf ("block:%p size:%7i tag:%5x ret: %5d ofs:%x\n", + Sys_Printf ("block:%p size:%8zd tag:%5x ret: %5d ofs:%x\n", block, z_block_size (block), block->tag, block->retain, z_offset (zone, block)); @@ -468,6 +468,22 @@ Z_GetRetainCount (memzone_t *zone, void *ptr) return block->retain; } +VISIBLE int +Z_GetTag (memzone_t *zone, void *ptr) +{ + memblock_t *block = (memblock_t *) ((byte *) ptr - sizeof (memblock_t)); + return block->tag; +} + +VISIBLE void +Z_SetTag (memzone_t *zone, void *ptr, int tag) +{ + if (!tag) { + z_error (zone, "Attept to set tag to 0"); + } + memblock_t *block = (memblock_t *) ((byte *) ptr - sizeof (memblock_t)); + block->tag = tag; +} VISIBLE void Z_MemInfo (const memzone_t *zone, size_t *used, size_t *size) { From 91140acfee9915faebef795e433e6ea224abc4cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jun 2022 16:57:13 +0900 Subject: [PATCH 2902/3664] [sound] Access the buffer directly from the channel This improves the locality of reference when mixing and removes the proxy sfx for streamed sounds. The buffer for streamed sounds is allocated when the stream is opened (since streamed sounds can't share buffers), and freed when the stream is closed. For block sounds, the buffer is reference counted (with the sfx holding one reference, so currently block buffers never get freed), with their reference count getting incremented on open and decremented on close. That the reference counts get to 1 has been confirmed, so all that should be needed is proper destruction of the sfx instances. Still need to sort out just why channels leak across level changes. --- include/snd_internal.h | 66 +++++++++++-------- libs/audio/renderer/flac.c | 18 ++--- libs/audio/renderer/midi.c | 10 +-- libs/audio/renderer/snd_channels.c | 101 ++++++++++++++--------------- libs/audio/renderer/snd_dma.c | 10 +-- libs/audio/renderer/snd_mem.c | 97 +++++++++++++++++---------- libs/audio/renderer/snd_mix.c | 27 +++----- libs/audio/renderer/snd_resample.c | 23 ++++--- libs/audio/renderer/snd_sfx.c | 55 ++++++++-------- libs/audio/renderer/vorbis.c | 18 ++--- libs/audio/renderer/wav.c | 20 +++--- 11 files changed, 240 insertions(+), 205 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index 352138114..fc618c825 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -56,28 +56,29 @@ struct sfx_s { struct snd_s *snd; //!< ownding snd_t instance const char *name; - sfx_t *owner; - unsigned int length; - unsigned int loopstart; + unsigned length; + unsigned loopstart; union { sfxstream_t *stream; sfxblock_t *block; - } data; + }; sfxbuffer_t *(*touch) (sfx_t *sfx); sfxbuffer_t *(*retain) (sfx_t *sfx); void (*release) (sfx_t *sfx); sfxbuffer_t *(*getbuffer) (sfx_t *sfx); - struct wavinfo_s *(*wavinfo) (sfx_t *sfx); + struct wavinfo_s *(*wavinfo) (const sfx_t *sfx); - sfx_t *(*open) (sfx_t *sfx); - void (*close) (sfx_t *sfx); + sfxbuffer_t *(*open) (sfx_t *sfx); }; /** paint samples into the mix buffer + + This is currently used for channel-count specific mixing + \param offset offset into the mix buffer at which to start mixing the channel \param ch sound channel @@ -87,7 +88,7 @@ struct sfx_s typedef void sfxpaint_t (int offset, channel_t *ch, float *buffer, unsigned count); -/** Represent a sound sample in the mixer. +/** Represent a single output frame in the mixer. */ struct portable_samplepair_s { float left; //!< left sample @@ -146,6 +147,14 @@ struct sfxbuffer_s { unsigned size; //!< size of buffer in frames unsigned pos; //!< position of tail within full stream unsigned channels; //!< number of channels per frame + unsigned sfx_length; //!< total length of sfx + union { // owning instance + // the first field of both sfxstream_t and sfxblock_t is a pointer + // to sfx_t + sfx_t const * const * const sfx; + sfxstream_t *stream; + sfxblock_t *block; + }; sfxpaint_t *paint; //!< channel count specific paint function /** Advance the position with the stream, updating the ring buffer as necessary. Null for chached sounds. @@ -160,7 +169,7 @@ struct sfxbuffer_s { \param pos frame position with the stream */ void (*setpos) (sfxbuffer_t *buffer, unsigned int pos); - sfx_t *sfx; //!< owning sfx_t instance + void (*close) (sfxbuffer_t *buffer); /** Sample data. The block at the beginning of the buffer (size depends on sample size) */ @@ -170,7 +179,7 @@ struct sfxbuffer_s { /** Representation of sound loaded that is streamed in as needed. */ struct sfxstream_s { - sfx_t *sfx; //!< owning sfx_t instance + const sfx_t *sfx; //!< owning sfx_t instance void *file; //!< handle for "file" representing the stream wavinfo_t wavinfo; //!< description of sound data unsigned pos; //!< position of next frame full stream @@ -213,25 +222,24 @@ struct sfxstream_s { /** Representation of sound loaded into memory as a full block. */ struct sfxblock_s { - sfx_t *sfx; //!< owning sfx_t instance + const sfx_t *sfx; //!< owning sfx_t instance void *file; //!< handle for "file" representing the block wavinfo_t wavinfo; //!< description of sound data - cache_user_t cache; //!< cached sound buffer (::sfxbuffer_s) sfxbuffer_t *buffer; //!< pointer to cached buffer }; /** Representation of a sound being played. */ struct channel_s { - sfx_t *sfx; //!< sound played by this channel + sfxbuffer_t *buffer; //!< sound played by this channel float leftvol; //!< 0-1 volume float rightvol; //!< 0-1 volume unsigned end; //!< end time in global paintsamples unsigned pos; //!< sample position in sfx - unsigned looping; //!< where to loop, -1 = no looping - int pause; //!< don't update the channel at all + unsigned loopstart; //!< where to loop, -1 = no looping int phase; //!< phase shift between l-r in samples int oldphase; //!< phase shift between l-r in samples + byte pause; //!< don't update the channel at all /** signal between main program and mixer thread that the channel is to be stopped. - both \c stop and \c done are zero: normal operation @@ -243,8 +251,8 @@ struct channel_s { can be reused at any time. */ //@{ - int stop; - int done; + byte stop; + byte done; //@} }; @@ -259,7 +267,11 @@ extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; void SND_Memory_Init_Cvars (void); int SND_Memory_Init (void); sfxbuffer_t *SND_Memory_AllocBuffer (unsigned samples); -void SND_Memory_FreeBuffer (sfxbuffer_t *buffer); +void SND_Memory_Free (void *ptr); +void SND_Memory_SetTag (void *ptr, int tag); +int SND_Memory_Retain (void *ptr); +int SND_Memory_Release (void *ptr); +int SND_Memory_GetRetainCount (void *ptr) __attribute__((pure)); /** \defgroup sound_render_sfx Sound sfx \ingroup sound_render_mix @@ -281,7 +293,7 @@ void SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info, \param open */ void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info, - sfx_t *(*open) (sfx_t *sfx)); + sfxbuffer_t *(*open) (sfx_t *sfx)); /** Open a stream for playback. \param sfx @@ -290,15 +302,15 @@ void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info, \param seek \param close */ -sfx_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file, - long (*read)(void *, float **), - int (*seek)(sfxstream_t *, int), - void (*close) (sfx_t *)); +sfxbuffer_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file, + long (*read)(void *, float **), + int (*seek)(sfxstream_t *, int), + void (*close) (sfxbuffer_t *)); /** Close a stream. \param sfx */ -void SND_SFX_StreamClose (sfx_t *sfx); +void SND_SFX_StreamClose (sfxstream_t *stream); /** Pre-load a sound into the cache. \param snd sound system state @@ -466,7 +478,7 @@ void SND_SetPaint (sfxbuffer_t *sb); */ ///@{ -unsigned SND_ResamplerFrames (sfx_t *sfx); +unsigned SND_ResamplerFrames (const sfx_t *sfx, unsigned frames); /** Set up the various parameters that depend on the actual sample rate. \param sb buffer to setup @@ -549,13 +561,13 @@ int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname); \param sfx sound reference \return pointer to sound's wavinfo */ -wavinfo_t *SND_CacheWavinfo (sfx_t *sfx) __attribute__((pure)); +wavinfo_t *SND_CacheWavinfo (const sfx_t *sfx) __attribute__((pure)); /** Retrieve wavinfo from a streamed sound. \param sfx sound reference \return pointer to sound's wavinfo */ -wavinfo_t *SND_StreamWavinfo (sfx_t *sfx) __attribute__((pure)); +wavinfo_t *SND_StreamWavinfo (const sfx_t *sfx) __attribute__((pure)); /** Ensure a cached sound is in memory. \param sfx sound reference diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index 9868d12cd..4d8ed5a94 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -283,18 +283,20 @@ flac_load (flacfile_t *ff, sfxblock_t *block) { float *data; sfxbuffer_t *sb = 0; - sfx_t *sfx = block->sfx; + const sfx_t *sfx = block->sfx; wavinfo_t *info = &block->wavinfo; data = malloc (info->datalen); if (!data) goto bail; - unsigned buffer_frames = SND_ResamplerFrames (sfx); + unsigned buffer_frames = SND_ResamplerFrames (sfx, info->frames); sb = SND_Memory_AllocBuffer (buffer_frames * info->channels); if (!sb) goto bail; sb->size = buffer_frames * info->channels; - sb->sfx = sfx; + sb->channels = info->channels; + sb->sfx_length = info->frames; + sb->block = sfx->block; if (flac_read (ff, data, info->frames) < 0) goto bail; SND_SetPaint (sb); @@ -358,18 +360,18 @@ flac_stream_seek (sfxstream_t *stream, int pos) } static void -flac_stream_close (sfx_t *sfx) +flac_stream_close (sfxbuffer_t *buffer) { - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = buffer->stream; flac_close (stream->file); - SND_SFX_StreamClose (sfx); + SND_SFX_StreamClose (stream); } -static sfx_t * +static sfxbuffer_t * flac_stream_open (sfx_t *sfx) { - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = sfx->stream; QFile *file; void *f; diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index bebb1f9f0..8185060e6 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -143,20 +143,20 @@ midi_stream_seek (sfxstream_t *stream, int pos) } static void -midi_stream_close (sfx_t *sfx) +midi_stream_close (sfxbuffer_t *buffer) { - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = buffer->stream; midi_file_t *mf = (midi_file_t *) stream->file; WildMidi_Close (mf->handle); free (mf); - SND_SFX_StreamClose (sfx); + SND_SFX_StreamClose (stream); } -static sfx_t * +static sfxbuffer_t * midi_stream_open (sfx_t *sfx) { - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = sfx->stream; QFile *file; midi *handle; unsigned char *local_buffer; diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 8b56415ff..d90b98e8a 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -148,7 +148,8 @@ static cvar_t ambient_level_cvar = { static void snd_free_channel (channel_t *ch) { - ch->sfx = 0; + sfxbuffer_t *buffer = ch->buffer; + ch->buffer = 0; ch->stop = 0; ch->done = 0; int chan_ind = ch - snd_channels; @@ -157,6 +158,10 @@ snd_free_channel (channel_t *ch) } snd_free_channels[snd_num_free_channels++] = chan_ind; snd_entity_channels[chan_ind] = (entchan_t) {}; + + if (buffer) { + buffer->close (buffer); + } } channel_t * @@ -164,8 +169,8 @@ SND_AllocChannel (snd_t *snd) { channel_t *chan; - //Sys_MaskPrintf (SYS_snd, "SND_AllocChannel: free channels: %d\n", - // snd_num_free_channels); + Sys_MaskPrintf (SYS_snd, "SND_AllocChannel: free channels: %d\n", + snd_num_free_channels); if (!snd_num_free_channels) { Sys_MaskPrintf (SYS_warn, "SND_AllocChannel: out of channels.\n"); return 0; @@ -181,7 +186,7 @@ SND_AllocChannel (snd_t *snd) void SND_ChannelStop (snd_t *snd, channel_t *chan) { - if (!chan->sfx) { + if (!chan->buffer) { Sys_MaskPrintf (SYS_warn, "Sound: stop called on invalid channel\n"); } chan->stop = 1; @@ -207,7 +212,7 @@ SND_ScanChannels (snd_t *snd, int wait) count = 0; for (i = 0; i < MAX_CHANNELS; i++) { ch = &snd_channels[i]; - if (!ch->sfx || ch->done) + if (!ch->buffer || ch->done) continue; ch->stop = 1; count++; @@ -221,7 +226,7 @@ SND_ScanChannels (snd_t *snd, int wait) } else { for (i = 0; i < MAX_CHANNELS; i++) { ch = &snd_channels[i]; - if (ch->sfx && ch->stop && !ch->done) { + if (ch->buffer && ch->stop && !ch->done) { ch->done = 1; count++; } @@ -230,11 +235,11 @@ SND_ScanChannels (snd_t *snd, int wait) } for (i = 0; i < MAX_CHANNELS; i++) { ch = &snd_channels[i]; - if (!ch->sfx || !ch->done) + if (!ch->buffer || !ch->done) continue; - ch->sfx->release (ch->sfx); - ch->sfx->close (ch->sfx); - ch->sfx = 0; + sfxbuffer_t *buffer = ch->buffer; + ch->buffer = 0; + buffer->close (buffer); } } @@ -419,8 +424,6 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) { float vol; int ambient_channel; - channel_t *chan; - sfx_t *sfx; if (!snd_ambient) return; @@ -430,7 +433,7 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) // stop all ambient channels. for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++) { - chan = ambient_channels[ambient_channel]; + channel_t *chan = ambient_channels[ambient_channel]; if (chan) { int chan_ind = chan - snd_channels; spacial_t *spacial = &snd_spacialization[chan_ind]; @@ -443,28 +446,28 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS; ambient_channel++) { - sfx = ambient_sfx[ambient_channel]; + sfx_t *sfx = ambient_sfx[ambient_channel]; if (!sfx) continue; - chan = ambient_channels[ambient_channel]; + channel_t *chan = ambient_channels[ambient_channel]; if (!chan) { chan = ambient_channels[ambient_channel] = SND_AllocChannel (snd); if (!chan) continue; } - if (!chan->sfx) { - sfx = sfx->open (sfx); - if (!sfx) + sfxbuffer_t *buffer; + if (!chan->buffer) { + buffer = sfx->open (sfx); + if (!buffer) continue; - sfx->retain (sfx); } else { - sfx = chan->sfx; + buffer = chan->buffer; //sfx->retain (sfx); //FIXME why is this necessary? } - // sfx will be written to chan->sfx later to ensure mixer doesn't use - // channel prematurely. + // buffer will be written to chan->buffer later to ensure mixer + // doesn't use channel prematurely. int chan_ind = chan - snd_channels; spacial_t *spacial = &snd_spacialization[chan_ind]; @@ -486,7 +489,8 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) } chan->leftvol = chan->rightvol = spacial->volume; - chan->sfx = sfx; + chan->loopstart = sfx->loopstart; + chan->buffer = buffer; } } @@ -548,7 +552,7 @@ s_spatialize (snd_t *snd, channel_t *ch) static inline int s_update_channel (snd_t *snd, channel_t *ch) { - if (!ch->sfx) + if (!ch->buffer) return 0; s_spatialize (snd, ch); if (!ch->leftvol && !ch->rightvol) @@ -585,7 +589,7 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level) channel_t *combine = 0; for (int i = 0; i < MAX_CHANNELS; i++) { channel_t *ch = &snd_channels[i]; - if (!ch->sfx || ch->done) { + if (!ch->buffer || ch->done) { continue; } if (set_is_member (&dynamic_channels, i) @@ -597,10 +601,13 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level) // too quiet continue; } + //FIXME does this even work? probably better just to give + //static sounds random offsets (I suspect it worked just fine + //before streams were implemented) // try to combine static sounds with a previous channel of // the same sound effect so we don't mix five torches every // frame see if it can just use the last one - if (combine && combine->sfx == ch->sfx) { + if (combine && combine->buffer == ch->buffer) { s_combine_channel (combine, ch); continue; } @@ -608,7 +615,7 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level) channel_t *c = 0; for (int j = 0; j < i; j++) { if (set_is_member (&static_channels, j)) { - if (snd_channels[j].sfx == ch->sfx) { + if (snd_channels[j].buffer == ch->buffer) { c = &snd_channels[j]; break; } @@ -623,11 +630,11 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level) static int snd_check_channels (snd_t *snd, channel_t *target_chan, const channel_t *check, - const sfx_t *osfx) + const sfx_t *sfx) { - if (!check || !check->sfx || check == target_chan) + if (!check || !check->buffer || check == target_chan) return 0; - if (check->sfx->owner == osfx->owner && !check->pos) { + if (*check->buffer->sfx == sfx && !check->pos) { int skip = rand () % (int) (0.01 * snd->speed); target_chan->pos = -skip; return 1; @@ -639,15 +646,11 @@ void SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, vec4f_t origin, float vol, float attenuation) { - int looped; - channel_t *target_chan; - sfx_t *osfx; - if (!sfx || !snd->speed) return; // pick a channel to play on - looped = sfx->loopstart != (unsigned) -1; - target_chan = s_pick_channel (snd, entnum, entchannel, looped); + int looped = sfx->loopstart != (unsigned) -1; + channel_t *target_chan = s_pick_channel (snd, entnum, entchannel, looped); if (!target_chan) return; @@ -663,7 +666,8 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, }; s_spatialize (snd, target_chan); - if (!(osfx = sfx->open (sfx))) { + sfxbuffer_t *buffer; + if (!(buffer = sfx->open (sfx))) { // because the channel was never started, it's safe to directly free it snd_free_channel (target_chan); return; @@ -677,16 +681,12 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx, if (set_is_member (&dynamic_channels, i) || set_is_member (&looped_channels, i)) { channel_t *check = &snd_channels[i]; - if (snd_check_channels (snd, target_chan, check, osfx)) + if (snd_check_channels (snd, target_chan, check, sfx)) break; } } - if (!osfx->retain (osfx)) { - // because the channel was never started, it's safe to directly free it - snd_free_channel (target_chan); - return; // couldn't load the sound's data - } - target_chan->sfx = osfx; + target_chan->loopstart = sfx->loopstart; + target_chan->buffer = buffer; set_add (looped ? &looped_channels : &dynamic_channels, chan_ind); } @@ -716,9 +716,6 @@ void SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol, float attenuation) { - channel_t *ss; - sfx_t *osfx; - if (!sfx) return; if (sfx->loopstart == (unsigned int) -1) { @@ -726,13 +723,15 @@ SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol, return; } + channel_t *ss; if (!(ss = SND_AllocChannel (snd))) { Sys_Printf ("ran out of channels\n"); return; } int ss_ind = ss - snd_channels; - if (!(osfx = sfx->open (sfx))) + sfxbuffer_t *buffer; + if (!(buffer = sfx->open (sfx))) return; spacial_t *spacial = &snd_spacialization[ss_ind]; @@ -744,15 +743,13 @@ SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol, s_spatialize (snd, ss); ss->oldphase = ss->phase; - if (!osfx->retain (osfx)) - return; - set_add (&static_channels, ss_ind); snd_entity_channels[ss_ind] = (entchan_t) { .id = SND_STATIC_ID, .channel = 0, }; - ss->sfx = osfx; + ss->loopstart = sfx->loopstart; + ss->buffer = buffer; } void diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index f8095688a..7e3fd427f 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -473,11 +473,11 @@ s_channel_free (channel_t *chan) static int s_channel_set_sfx (channel_t *chan, sfx_t *sfx) { - sfx_t *s = sfx->open (sfx); - if (!s) { + sfxbuffer_t *buffer = sfx->open (sfx); + if (!buffer) { return 0; } - chan->sfx = s; + chan->buffer = buffer; return 1; } @@ -505,8 +505,8 @@ s_channel_get_state (channel_t *chan) // The mixer has finished mixing the channel (come to the end). return chan_done; } - if (!chan->sfx) { - // channel requires initialization + if (!chan->buffer) { + // channel has not been started yet return chan_pending; } if (chan->pause) { diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index aa93b6bd0..05ee1d55a 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -126,9 +126,37 @@ SND_Memory_AllocBuffer (unsigned samples) } void -SND_Memory_FreeBuffer (sfxbuffer_t *buffer) +SND_Memory_Free (void *ptr) { - Z_Free (snd_zone, buffer); + Z_Free (snd_zone, ptr); +} + +void +SND_Memory_SetTag (void *ptr, int tag) +{ + Z_SetTag (snd_zone, ptr, tag); +} + +int +SND_Memory_Retain (void *ptr) +{ + return Z_IncRetainCount (snd_zone, ptr); +} + +int +SND_Memory_Release (void *ptr) +{ + int retain = Z_DecRetainCount (snd_zone, ptr); + if (!retain) { + Z_Free (snd_zone, ptr); + } + return retain; +} + +int +SND_Memory_GetRetainCount (void *ptr) +{ + return Z_GetRetainCount (snd_zone, ptr); } static sfxbuffer_t * @@ -142,34 +170,36 @@ snd_noop (sfx_t *sfx) { } -static sfx_t * +static sfxbuffer_t * snd_open (sfx_t *sfx) { - return sfx; + sfxbuffer_t *buffer = sfx->block->buffer; + SND_Memory_Retain (buffer); + return buffer; } -static sfx_t * +static sfxbuffer_t * snd_open_fail (sfx_t *sfx) { return 0; } -sfxbuffer_t * +sfxbuffer_t * __attribute__((pure)) SND_CacheTouch (sfx_t *sfx) { - return sfx->data.block->buffer; + return sfx->block->buffer; } sfxbuffer_t * SND_CacheGetBuffer (sfx_t *sfx) { - return sfx->data.block->buffer; + return sfx->block->buffer; } -sfxbuffer_t * +sfxbuffer_t * __attribute__((pure)) SND_CacheRetain (sfx_t *sfx) { - return sfx->data.block->buffer; + return sfx->block->buffer; } void @@ -180,13 +210,13 @@ SND_CacheRelease (sfx_t *sfx) sfxbuffer_t * SND_StreamGetBuffer (sfx_t *sfx) { - return sfx->data.stream->buffer; + return sfx->stream->buffer; } sfxbuffer_t * SND_StreamRetain (sfx_t *sfx) { - return sfx->data.stream->buffer; + return sfx->stream->buffer; } void @@ -195,15 +225,15 @@ SND_StreamRelease (sfx_t *sfx) } wavinfo_t * -SND_CacheWavinfo (sfx_t *sfx) +SND_CacheWavinfo (const sfx_t *sfx) { - return &sfx->data.block->wavinfo; + return &sfx->block->wavinfo; } wavinfo_t * -SND_StreamWavinfo (sfx_t *sfx) +SND_StreamWavinfo (const sfx_t *sfx) { - return &sfx->data.stream->wavinfo; + return &sfx->stream->wavinfo; } static void @@ -215,8 +245,8 @@ read_samples (sfxbuffer_t *buffer, int count) read_samples (buffer, buffer->size - buffer->head); read_samples (buffer, count); } else { - sfx_t *sfx = buffer->sfx; - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = buffer->stream; + const sfx_t *sfx = stream->sfx; wavinfo_t *info = &stream->wavinfo; float *data = buffer->data + buffer->head * info->channels; int c; @@ -233,7 +263,7 @@ read_samples (sfxbuffer_t *buffer, int count) } static void -fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer, +fill_buffer (const sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer, wavinfo_t *info, unsigned int headpos) { unsigned int samples; @@ -244,11 +274,11 @@ fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer, if (buffer->tail <= buffer->head) samples += buffer->size; - if (headpos + samples > sfx->length) { + if (headpos + samples > buffer->sfx_length) { if (sfx->loopstart == (unsigned int)-1) { - samples = sfx->length - headpos; + samples = buffer->sfx_length - headpos; } else { - loop_samples = headpos + samples - sfx->length; + loop_samples = headpos + samples - buffer->sfx_length; samples -= loop_samples; } } @@ -264,8 +294,8 @@ void SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos) { float stepscale; - sfx_t *sfx = buffer->sfx; - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = buffer->stream; + const sfx_t *sfx = stream->sfx; wavinfo_t *info = &stream->wavinfo; stepscale = (float) info->rate / sfx->snd->speed; @@ -282,8 +312,8 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count) { float stepscale; unsigned int headpos, samples; - sfx_t *sfx = buffer->sfx; - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = buffer->stream; + const sfx_t *sfx = stream->sfx; wavinfo_t *info = &stream->wavinfo; stream->pos += count; @@ -300,23 +330,23 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count) // find out where head points to in the stream headpos = buffer->pos + samples; - if (headpos >= sfx->length) { + if (headpos >= buffer->sfx_length) { if (sfx->loopstart == (unsigned int)-1) - headpos = sfx->length; + headpos = buffer->sfx_length; else - headpos -= sfx->length - sfx->loopstart; + headpos -= buffer->sfx_length - sfx->loopstart; } if (samples < count) { buffer->head = buffer->tail = 0; buffer->pos += count; - if (buffer->pos > sfx->length) { + if (buffer->pos > buffer->sfx_length) { if (sfx->loopstart == (unsigned int)-1) { // reset the buffer and fill it incase it's needed again buffer->pos = 0; } else { buffer->pos -= sfx->loopstart; - buffer->pos %= sfx->length - sfx->loopstart; + buffer->pos %= buffer->sfx_length - sfx->loopstart; buffer->pos += sfx->loopstart; } stream->pos = buffer->pos; @@ -325,7 +355,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count) stream->seek (stream, buffer->pos * stepscale); } else { buffer->pos += count; - if (buffer->pos >= sfx->length) { + if (buffer->pos >= buffer->sfx_length) { if (sfx->loopstart == (unsigned int)-1) { // reset the buffer and fill it in case it's needed again headpos = buffer->pos = 0; @@ -333,7 +363,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count) count = 0; stream->seek (stream, buffer->pos * stepscale); } else { - buffer->pos -= sfx->length - sfx->loopstart; + buffer->pos -= buffer->sfx_length - sfx->loopstart; } stream->pos = buffer->pos; } @@ -355,7 +385,6 @@ SND_Load (sfx_t *sfx) sfx->touch = sfx->retain = snd_fail; sfx->release = snd_noop; - sfx->close = snd_noop; sfx->open = snd_open_fail; file = QFS_FOpenFile (sfx->name); diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index 92789aaa1..4453852a1 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -53,12 +53,12 @@ static int max_overpaint; // number of extra samples painted /* CHANNEL MIXING */ static inline int -check_channel_end (channel_t *ch, sfx_t *sfx, int count, unsigned ltime) +check_channel_end (channel_t *ch, sfxbuffer_t *sb, int count, unsigned ltime) { if (count <= 0 || ltime >= ch->end) { - if (sfx->loopstart != (unsigned) -1) { - ch->pos = sfx->loopstart; - ch->end = ltime + sfx->length - ch->pos; + if (ch->loopstart != (unsigned) -1) { + ch->pos = ch->loopstart; + ch->end = ltime + sb->sfx_length - ch->pos; } else { // channel just stopped ch->done = 1; return 1; @@ -103,7 +103,6 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) unsigned end, ltime; int i, count; channel_t *ch; - sfx_t *sfx; sfxbuffer_t *sb; // clear the paint buffer @@ -123,7 +122,7 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) // paint in the channels. ch = snd_channels; for (i = 0; i < snd_total_channels; i++, ch++) { - if (!(sfx = ch->sfx)) { + if (!(sb = ch->buffer)) { // channel is inactive continue; } @@ -133,14 +132,9 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) } if (ch->pause) continue; - sb = sfx->getbuffer (sfx); - if (!sb) { // something went wrong with the sfx - printf ("XXXX sfx blew up!!!!\n"); - continue; - } if (!ch->end) - ch->end = snd->paintedtime + sfx->length - ch->pos; + ch->end = snd->paintedtime + sb->sfx_length - ch->pos; ltime = snd->paintedtime; @@ -161,7 +155,7 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) ltime += count; } - if (check_channel_end (ch, sfx, count, ltime)) + if (check_channel_end (ch, sb, count, ltime)) break; } } @@ -473,8 +467,7 @@ SND_SetPaint (sfxbuffer_t *sb) snd_paint_8, }; - wavinfo_t *info = sb->sfx->wavinfo (sb->sfx); - if (info->channels > 8) - Sys_Error ("illegal channel count %d", info->channels); - sb->paint = painters[info->channels]; + if (sb->channels > 8 || !sb->channels) + Sys_Error ("invaliid channel count %d", sb->channels); + sb->paint = painters[sb->channels]; } diff --git a/libs/audio/renderer/snd_resample.c b/libs/audio/renderer/snd_resample.c index 97f4acbc4..b11e1ed88 100644 --- a/libs/audio/renderer/snd_resample.c +++ b/libs/audio/renderer/snd_resample.c @@ -63,13 +63,16 @@ check_buffer_integrity (sfxbuffer_t *sb, int width, const char *func) } unsigned -SND_ResamplerFrames (sfx_t *sfx) +SND_ResamplerFrames (const sfx_t *sfx, unsigned frames) { + if (frames == ~0u) { + return frames; + } wavinfo_t *info = sfx->wavinfo (sfx); snd_t *snd = sfx->snd; int inrate = info->rate; double stepscale = (double) snd->speed / inrate; - return info->frames * stepscale; + return frames * stepscale; } void @@ -77,8 +80,8 @@ SND_Resample (sfxbuffer_t *sb, float *data, int length) { int outcount; double stepscale; - wavinfo_t *info = sb->sfx->wavinfo (sb->sfx); - snd_t *snd = sb->sfx->snd; + wavinfo_t *info = (*sb->sfx)->wavinfo (*sb->sfx); + snd_t *snd = (*sb->sfx)->snd; int inrate = info->rate; int outwidth; SRC_DATA src_data; @@ -153,23 +156,19 @@ void SND_SetupResampler (sfxbuffer_t *sb, int streamed) { double stepscale; - wavinfo_t *info = sb->sfx->wavinfo (sb->sfx); - snd_t *snd = sb->sfx->snd; + wavinfo_t *info = (*sb->sfx)->wavinfo (*sb->sfx); + snd_t *snd = (*sb->sfx)->snd; int inrate = info->rate; stepscale = (double) snd->speed / inrate; - sb->sfx->length = info->frames * stepscale; - if (info->loopstart != (unsigned int)-1) - sb->sfx->loopstart = info->loopstart * stepscale; - else - sb->sfx->loopstart = (unsigned int)-1; + sb->sfx_length = info->frames * stepscale; sb->channels = info->channels; if (streamed) { int err; - sfxstream_t *stream = sb->sfx->data.stream; + sfxstream_t *stream = sb->stream; if (snd->speed == inrate) { stream->state = calloc (sizeof (snd_null_state_t), 1); diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 79a7af51d..8a4e9f6c5 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -75,7 +75,12 @@ snd_sfx_free (void *_sfx, void *unused) sfx_t *sfx = (sfx_t *) _sfx; free ((char *) sfx->name); sfx->name = 0; - sfx->owner = 0; +} + +static void +snd_block_close (sfxbuffer_t *buffer) +{ + SND_Memory_Release (buffer); } void @@ -84,22 +89,26 @@ SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info, { sfxblock_t *block = calloc (1, sizeof (sfxblock_t)); - sfx->data.block = block; + sfx->block = block; sfx->wavinfo = SND_CacheWavinfo; sfx->touch = SND_CacheTouch; sfx->retain = SND_CacheRetain; sfx->release = SND_CacheRelease; sfx->getbuffer = SND_CacheGetBuffer; + sfx->loopstart = SND_ResamplerFrames (sfx, info.loopstart); + sfx->length = SND_ResamplerFrames (sfx, info.frames); block->sfx = sfx; block->file = realname; block->wavinfo = info; block->buffer = load (block); + SND_Memory_Retain (block->buffer); + block->buffer->close = snd_block_close; } void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info, - sfx_t *(*open) (sfx_t *sfx)) + sfxbuffer_t *(*open) (sfx_t *sfx)) { sfxstream_t *stream = calloc (1, sizeof (sfxstream_t)); sfx->open = open; @@ -107,20 +116,22 @@ SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info, sfx->touch = sfx->retain = SND_StreamRetain; sfx->release = SND_StreamRelease; sfx->getbuffer = SND_StreamGetBuffer; - sfx->data.stream = stream; + sfx->stream = stream; + sfx->loopstart = SND_ResamplerFrames (sfx, info.loopstart); + sfx->length = SND_ResamplerFrames (sfx, info.frames); stream->file = realname; stream->wavinfo = info; } -sfx_t * +sfxbuffer_t * SND_SFX_StreamOpen (sfx_t *sfx, void *file, long (*read)(void *, float **), int (*seek)(sfxstream_t *, int), - void (*close) (sfx_t *)) + void (*close) (sfxbuffer_t *)) { snd_t *snd = sfx->snd; - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = sfx->stream; wavinfo_t *info = &stream->wavinfo; int frames; @@ -129,55 +140,44 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file, if (!snd->speed) return 0; - sfx_t *new_sfx = calloc (1, sizeof (sfx_t)); - - new_sfx->snd = sfx->snd; - new_sfx->name = sfx->name; - new_sfx->owner = sfx; - new_sfx->wavinfo = SND_CacheWavinfo; - new_sfx->touch = new_sfx->retain = SND_StreamRetain; - new_sfx->release = SND_StreamRelease; - new_sfx->getbuffer = SND_StreamGetBuffer; - new_sfx->close = close; - frames = snd->speed * 0.3; frames = (frames + 255) & ~255; stream = calloc (1, sizeof (sfxstream_t)); - new_sfx->data.stream = stream; stream->buffer = SND_Memory_AllocBuffer (frames * info->channels); if (!stream->buffer) { free (stream); - free (new_sfx); return 0; } + stream->file = file; - stream->sfx = new_sfx; + stream->sfx = sfx; stream->ll_read = read; stream->ll_seek = seek; stream->wavinfo = *sfx->wavinfo (sfx); + stream->buffer->stream = stream; stream->buffer->size = frames; stream->buffer->advance = SND_StreamAdvance; stream->buffer->setpos = SND_StreamSetPos; - stream->buffer->sfx = new_sfx; + stream->buffer->sfx_length = info->frames; + stream->buffer->channels = info->channels; + stream->buffer->close = close; SND_SetPaint (stream->buffer); SND_SetupResampler (stream->buffer, 1); // get sfx setup properly stream->buffer->setpos (stream->buffer, 0); // pre-fill the buffer - return new_sfx; + return stream->buffer; } void -SND_SFX_StreamClose (sfx_t *sfx) +SND_SFX_StreamClose (sfxstream_t *stream) { - sfxstream_t *stream = sfx->data.stream; SND_PulldownResampler (stream); - SND_Memory_FreeBuffer (stream->buffer); + SND_Memory_Free (stream->buffer); free (stream); - free (sfx); } sfx_t * @@ -196,7 +196,6 @@ SND_LoadSound (snd_t *snd, const char *name) sfx = &snd_sfx[snd_num_sfx++]; sfx->snd = snd; sfx->name = strdup (name); - sfx->owner = sfx; if (SND_Load (sfx) == -1) { snd_num_sfx--; return 0; diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index 8c51660df..e7b4565c1 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -164,18 +164,20 @@ vorbis_load (OggVorbis_File *vf, sfxblock_t *block) { float *data; sfxbuffer_t *sb = 0; - sfx_t *sfx = block->sfx; + const sfx_t *sfx = block->sfx; wavinfo_t *info = &block->wavinfo; data = malloc (info->datalen); if (!data) goto bail; - unsigned buffer_frames = SND_ResamplerFrames (sfx); + unsigned buffer_frames = SND_ResamplerFrames (sfx, info->frames); sb = SND_Memory_AllocBuffer (buffer_frames * info->channels); if (!sb) goto bail; sb->size = buffer_frames * info->channels; - sb->sfx = sfx; + sb->channels = info->channels; + sb->sfx_length = info->frames; + sb->block = block; if (vorbis_read (vf, data, info->frames, info) < 0) goto bail; SND_SetPaint (sb); @@ -240,9 +242,9 @@ vorbis_stream_seek (sfxstream_t *stream, int pos) } static void -vorbis_stream_close (sfx_t *sfx) +vorbis_stream_close (sfxbuffer_t *buffer) { - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = buffer->stream; vorbis_file_t *vf = (vorbis_file_t *) stream->file; if (vf->data) @@ -250,13 +252,13 @@ vorbis_stream_close (sfx_t *sfx) ov_clear (vf->vf); free (vf->vf); free (vf); - SND_SFX_StreamClose (sfx); + SND_SFX_StreamClose (stream); } -static sfx_t * +static sfxbuffer_t * vorbis_stream_open (sfx_t *sfx) { - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = sfx->stream; QFile *file; vorbis_file_t *f; diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index 68baae734..24dc27863 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -57,13 +57,13 @@ typedef struct { static sfxbuffer_t * wav_callback_load (sfxblock_t *block) { - sfx_t *sfx = block->sfx; + const sfx_t *sfx = block->sfx; const char *name = (const char *) block->file; QFile *file; int len, fdata_ofs; byte *data; float *fdata; - sfxbuffer_t *buffer; + sfxbuffer_t *buffer = 0; wavinfo_t *info = &block->wavinfo; file = QFS_FOpenFile (name); @@ -81,12 +81,14 @@ wav_callback_load (sfxblock_t *block) SND_Convert (data, fdata, info->frames, info->channels, info->width); - unsigned buffer_frames = SND_ResamplerFrames (sfx); + unsigned buffer_frames = SND_ResamplerFrames (sfx, info->frames); buffer = SND_Memory_AllocBuffer (buffer_frames * info->channels); if (!buffer) goto bail; buffer->size = buffer_frames * info->channels; - buffer->sfx = sfx; + buffer->channels = info->channels; + buffer->sfx_length = info->frames; + buffer->block = block; SND_SetPaint (buffer); SND_SetupResampler (buffer, 0); SND_Resample (buffer, fdata, info->frames); @@ -139,22 +141,22 @@ wav_stream_seek (sfxstream_t *stream, int pos) } static void -wav_stream_close (sfx_t *sfx) +wav_stream_close (sfxbuffer_t *buffer) { - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = buffer->stream; wav_file_t *wf = (wav_file_t *) stream->file; Qclose (wf->file); if (wf->data) free (wf->data); free (wf); - SND_SFX_StreamClose (sfx); + SND_SFX_StreamClose (stream); } -static sfx_t * +static sfxbuffer_t * wav_stream_open (sfx_t *sfx) { - sfxstream_t *stream = sfx->data.stream; + sfxstream_t *stream = sfx->stream; QFile *file; wav_file_t *wf; From 48f704c84eabc69f128331482d62345d6c75e0f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jun 2022 17:39:44 +0900 Subject: [PATCH 2903/3664] [sound] Use SYS_snd for all masked prints SYS_dev is a holdover from when we had only the one flag and is not meant to be used for tests (I seem to remember mentioning an audit was necessary, but obviously forgotten). One step at a time, I guess :) --- libs/audio/renderer/flac.c | 12 ++++++------ libs/audio/renderer/midi.c | 2 +- libs/audio/renderer/snd_channels.c | 6 +++--- libs/audio/renderer/snd_mem.c | 8 ++++---- libs/audio/renderer/vorbis.c | 12 ++++++------ libs/audio/renderer/wav.c | 4 ++-- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index 4d8ed5a94..54068bc78 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -412,7 +412,7 @@ flac_get_info (flacfile_t *ff) vc = &ff->vorbis_info->data.vorbis_comment; for (i = 0, ve = vc->comments; i < vc->num_comments; ve++, i++) { - Sys_MaskPrintf (SYS_dev, "%.*s\n", ve->length, ve->entry); + Sys_MaskPrintf (SYS_snd, "%.*s\n", ve->length, ve->entry); if (strncmp ("CUEPOINT=", (char *) ve->entry, 9) == 0) { char *str = alloca (ve->length + 1); strncpy (str, (char *) ve->entry, ve->length); @@ -433,12 +433,12 @@ flac_get_info (flacfile_t *ff) info.dataofs = 0; info.datalen = samples * info.channels * sizeof (float); - Sys_MaskPrintf (SYS_dev, "\nBitstream is %d channel, %dHz\n", + Sys_MaskPrintf (SYS_snd, "\nBitstream is %d channel, %dHz\n", info.channels, info.rate); - Sys_MaskPrintf (SYS_dev, "\nDecoded length: %d samples (%d bytes)\n", + Sys_MaskPrintf (SYS_snd, "\nDecoded length: %d samples (%d bytes)\n", info.frames, info.width); if (vc) { - Sys_MaskPrintf (SYS_dev, "Encoded by: %.*s\n\n", + Sys_MaskPrintf (SYS_snd, "Encoded by: %.*s\n\n", vc->vendor_string.length, vc->vendor_string.entry); } @@ -461,10 +461,10 @@ SND_LoadFLAC (QFile *file, sfx_t *sfx, char *realname) return -1; } if (info.frames / info.rate < 3) { - Sys_MaskPrintf (SYS_dev, "cache %s\n", realname); + Sys_MaskPrintf (SYS_snd, "cache %s\n", realname); flac_cache (sfx, realname, ff, info); } else { - Sys_MaskPrintf (SYS_dev, "stream %s\n", realname); + Sys_MaskPrintf (SYS_snd, "stream %s\n", realname); flac_stream (sfx, realname, ff, info); } return 0; diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index 8185060e6..6df371b0c 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -213,7 +213,7 @@ SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname) WildMidi_Close (handle); - Sys_MaskPrintf (SYS_dev, "stream %s\n", realname); + Sys_MaskPrintf (SYS_snd, "stream %s\n", realname); // we init stream here cause we will only ever stream SND_SFX_Stream (sfx, realname, info, midi_stream_open); diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index d90b98e8a..679386d3f 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -207,7 +207,7 @@ SND_ScanChannels (snd_t *snd, int wait) return; if (wait) { - Sys_MaskPrintf (SYS_dev, "scanning channels...\n"); + Sys_MaskPrintf (SYS_snd, "scanning channels...\n"); do { count = 0; for (i = 0; i < MAX_CHANNELS; i++) { @@ -217,12 +217,12 @@ SND_ScanChannels (snd_t *snd, int wait) ch->stop = 1; count++; } - Sys_MaskPrintf (SYS_dev, "count = %d\n", count); + Sys_MaskPrintf (SYS_snd, "count = %d\n", count); #ifdef HAVE_USLEEP usleep (1000); #endif } while (count); - Sys_MaskPrintf (SYS_dev, "scanning done.\n"); + Sys_MaskPrintf (SYS_snd, "scanning done.\n"); } else { for (i = 0; i < MAX_CHANNELS; i++) { ch = &snd_channels[i]; diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 05ee1d55a..43d166705 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -402,7 +402,7 @@ SND_Load (sfx_t *sfx) Qseek (file, 0, SEEK_SET); #ifdef HAVE_VORBIS if (strnequal ("OggS", buf, 4)) { - Sys_MaskPrintf (SYS_dev, "SND_Load: ogg file\n"); + Sys_MaskPrintf (SYS_snd, "SND_Load: ogg file\n"); if (SND_LoadOgg (file, sfx, realname) == -1) goto bail; return 0; @@ -410,7 +410,7 @@ SND_Load (sfx_t *sfx) #endif #ifdef HAVE_FLAC if (strnequal ("fLaC", buf, 4)) { - Sys_MaskPrintf (SYS_dev, "SND_Load: flac file\n"); + Sys_MaskPrintf (SYS_snd, "SND_Load: flac file\n"); if (SND_LoadFLAC (file, sfx, realname) == -1) goto bail; return 0; @@ -418,14 +418,14 @@ SND_Load (sfx_t *sfx) #endif #ifdef HAVE_WILDMIDI if (strnequal ("MThd", buf, 4)) { - Sys_MaskPrintf (SYS_dev, "SND_Load: midi file\n"); + Sys_MaskPrintf (SYS_snd, "SND_Load: midi file\n"); if (SND_LoadMidi (file, sfx, realname) == -1) goto bail; return 0; } #endif if (strnequal ("RIFF", buf, 4)) { - Sys_MaskPrintf (SYS_dev, "SND_Load: wav file\n"); + Sys_MaskPrintf (SYS_snd, "SND_Load: wav file\n"); if (SND_LoadWav (file, sfx, realname) == -1) goto bail; return 0; diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index e7b4565c1..acd420beb 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -101,7 +101,7 @@ vorbis_get_info (OggVorbis_File *vf) samples = ov_pcm_total (vf, -1); for (ptr = ov_comment (vf, -1)->user_comments; *ptr; ptr++) { - Sys_MaskPrintf (SYS_dev, "%s\n", *ptr); + Sys_MaskPrintf (SYS_snd, "%s\n", *ptr); if (strncmp ("CUEPOINT=", *ptr, 9) == 0) { sscanf (*ptr + 9, "%d %d", &sample_start, &sample_count); } @@ -118,11 +118,11 @@ vorbis_get_info (OggVorbis_File *vf) info.dataofs = 0; info.datalen = samples * info.channels * info.width; - Sys_MaskPrintf (SYS_dev, "\nBitstream is %d channel, %dHz\n", + Sys_MaskPrintf (SYS_snd, "\nBitstream is %d channel, %dHz\n", info.channels, info.rate); - Sys_MaskPrintf (SYS_dev, "\nDecoded length: %d samples (%d bytes)\n", + Sys_MaskPrintf (SYS_snd, "\nDecoded length: %d samples (%d bytes)\n", info.frames, info.width); - Sys_MaskPrintf (SYS_dev, "Encoded by: %s\n\n", + Sys_MaskPrintf (SYS_snd, "Encoded by: %s\n\n", ov_comment (vf, -1)->vendor); return info; @@ -302,10 +302,10 @@ SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname) return -1; } if (info.frames / info.rate < 3) { - Sys_MaskPrintf (SYS_dev, "cache %s\n", realname); + Sys_MaskPrintf (SYS_snd, "cache %s\n", realname); vorbis_cache (sfx, realname, &vf, info); } else { - Sys_MaskPrintf (SYS_dev, "stream %s\n", realname); + Sys_MaskPrintf (SYS_snd, "stream %s\n", realname); vorbis_stream (sfx, realname, &vf, info); } return 0; diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index 24dc27863..b5fef9bdf 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -289,10 +289,10 @@ SND_LoadWav (QFile *file, sfx_t *sfx, char *realname) } if (info.frames / info.rate < 3) { - Sys_MaskPrintf (SYS_dev, "cache %s\n", realname); + Sys_MaskPrintf (SYS_snd, "cache %s\n", realname); wav_cache (sfx, realname, file, info); } else { - Sys_MaskPrintf (SYS_dev, "stream %s\n", realname); + Sys_MaskPrintf (SYS_snd, "stream %s\n", realname); wav_stream (sfx, realname, file, info); } return 0; From fdd070f6dcb67b9c1da82ec388307aa1a1d3e1df Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jun 2022 18:08:49 +0900 Subject: [PATCH 2904/3664] [sound] Add a threaded field to snd_t Care needs to be taken when freeing channels as doing so while an asynchronous mixer is using them is unlikely to end well. However, whether the mixer is asynchronous depends on the output driver. This lets the driver inform the rest of the system that the output and mixer are running asynchronously. --- include/snd_internal.h | 1 + libs/audio/renderer/snd_dma.c | 2 +- libs/audio/targets/snd_alsa.c | 2 ++ libs/audio/targets/snd_jack.c | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index fc618c825..6789afd75 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -106,6 +106,7 @@ struct snd_s { int submission_chunk; //!< don't mix less than this # unsigned paintedtime; //!< sound clock in samples int framepos; //!< position of dma cursor + int threaded; //!< output runs in a thread unsigned char *buffer; //!< destination for mixed sound /** Transfer mixed samples to the output. \param paintbuffer The buffer of mixed samples to be transferred. diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 7e3fd427f..7ddfd4dc6 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -186,7 +186,7 @@ static void s_stop_all_sounds (void) { SND_StopAllSounds (&snd); - SND_ScanChannels (&snd, 0); + SND_ScanChannels (&snd, snd.threaded); s_clear_buffer (&snd); } diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 8fba39a2c..8235dd271 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -655,6 +655,8 @@ SNDDMA_Init (snd_t *snd) snd->frames = buffer_size; + snd->threaded = 1;//XXX FIXME double check whether it's always true + // send the first period to fill the buffer // also sets snd->buffer if (alsa_process (pcm, snd) < 0) { diff --git a/libs/audio/targets/snd_jack.c b/libs/audio/targets/snd_jack.c index 90bbd2c57..836792c98 100644 --- a/libs/audio/targets/snd_jack.c +++ b/libs/audio/targets/snd_jack.c @@ -278,6 +278,7 @@ static int s_init (snd_t *snd) { snd->xfer = snd_jack_xfer; + snd->threaded = 1; return s_jack_connect (snd); } From 7bbfde03fce0105e308fdffbe373da4323832e0a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jun 2022 18:11:32 +0900 Subject: [PATCH 2905/3664] [sound] Plug the channel leak Turned out the channels simply weren't being freed by SND_ScanChannels when they should have been (probably a good thing, too, as it wasn't being told to wait for the mixer). --- libs/audio/renderer/snd_channels.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 679386d3f..2389b9b7c 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -237,10 +237,10 @@ SND_ScanChannels (snd_t *snd, int wait) ch = &snd_channels[i]; if (!ch->buffer || !ch->done) continue; - sfxbuffer_t *buffer = ch->buffer; - ch->buffer = 0; - buffer->close (buffer); + snd_free_channel (ch); } + Sys_MaskPrintf (SYS_snd, "SND_ScanChannels: free channels: %d\n", + snd_num_free_channels); } void From 5ab88b01375685d895a09029f59b357814b552f7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Jun 2022 18:25:14 +0900 Subject: [PATCH 2906/3664] [sound] Clean up white space in snd_internal.h --- include/snd_internal.h | 45 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index 6789afd75..ecadc4fc1 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -91,34 +91,33 @@ typedef void sfxpaint_t (int offset, channel_t *ch, float *buffer, /** Represent a single output frame in the mixer. */ struct portable_samplepair_s { - float left; //!< left sample - float right; //!< right sample + float left; //!< left sample + float right; //!< right sample }; /** Sound system state */ struct snd_s { - int speed; //!< sample rate - int samplebits; //!< bits per sample - int channels; //!< number of output channels - int frames; //!< frames in buffer - //!< 1 frame = channels samples - int submission_chunk; //!< don't mix less than this # - unsigned paintedtime; //!< sound clock in samples - int framepos; //!< position of dma cursor - int threaded; //!< output runs in a thread - unsigned char *buffer; //!< destination for mixed sound + int speed; //!< sample rate + int samplebits; //!< bits per sample + int channels; //!< number of output channels + int frames; //!< frames in buffer + //!< 1 frame = channels samples + int submission_chunk; //!< don't mix less than this # + unsigned paintedtime; //!< sound clock in samples + int framepos; //!< position of dma cursor + int threaded; //!< output+mixer run asynchronously + byte *buffer; //!< destination for mixed sound /** Transfer mixed samples to the output. \param paintbuffer The buffer of mixed samples to be transferred. \param count The number of sample to transfer. \param volume The gain for the samples. */ - void (*xfer) (struct snd_s *snd, - portable_samplepair_t *paintbuffer, int count, - float volume); + void (*xfer) (struct snd_s *snd, portable_samplepair_t *paintbuffer, + int count, float volume); /** Optional data for the xfer function. */ - void *xfer_data; + void *xfer_data; void (*finish_channels) (void); void (*paint_channels) (struct snd_s *snd, unsigned endtime); @@ -163,14 +162,14 @@ struct sfxbuffer_s { \param count number of frames to advance \return true for success, false if an error occured */ - int (*advance) (sfxbuffer_t *buffer, unsigned int count); + int (*advance) (sfxbuffer_t *buffer, unsigned int count); /** Seek to an absolute position within the stream, resetting the ring buffer. \param buffer "this" \param pos frame position with the stream */ - void (*setpos) (sfxbuffer_t *buffer, unsigned int pos); - void (*close) (sfxbuffer_t *buffer); + void (*setpos) (sfxbuffer_t *buffer, unsigned int pos); + void (*close) (sfxbuffer_t *buffer); /** Sample data. The block at the beginning of the buffer (size depends on sample size) */ @@ -196,12 +195,12 @@ struct sfxstream_s { \param data address of pointer to be set to point to the buffer holding the samples */ - long (*ll_read)(void *cb_data, float **data); + long (*ll_read)(void *cb_data, float **data); /** Seek to an absolute position within the stream (low level). \param stream "this" \param pos frame position with the stream */ - int (*ll_seek)(sfxstream_t *stream, int pos); + int (*ll_seek)(sfxstream_t *stream, int pos); /** Read data from the stream. This is a high-level function for use in the mixer. The read samples will always at be the correct sample rate for the mixer, reguardless @@ -211,12 +210,12 @@ struct sfxstream_s { \param frames maximum number of frames to read from stream \return number of frames read from stream */ - int (*read)(sfxstream_t *stream, float *data, int frames); + int (*read)(sfxstream_t *stream, float *data, int frames); /** Seek to an absolute position within the stream. \param stream "this" \param pos frame position with the stream */ - int (*seek)(sfxstream_t *stream, int pos); + int (*seek)(sfxstream_t *stream, int pos); sfxbuffer_t *buffer; // Date: Mon, 6 Jun 2022 11:33:22 +0900 Subject: [PATCH 2907/3664] [sound] Bring QF into the atomic age Nuclear powered audio ;) More seriously, use _Atomic on a few fields that very obviously need it. That is, channel's buffer pointer (used to signal to the mixer that the channel is ready for use) and "flow control" flags (stop, done and pause), and head and tail in the buffer itself. Since QF has been working without _Atomic (admittedly, thanks to luck and x86's strong memory model), this should do until proven otherwise. I imagine getting stream reading out of the RT thread will highlight any issues. --- include/snd_internal.h | 17 ++++++++++------- libs/audio/renderer/snd_mix.c | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index ecadc4fc1..24302e6f4 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -31,6 +31,7 @@ #ifndef __snd_internal_h #define __snd_internal_h +#include /** \defgroup sound_render Sound rendering sub-system. \ingroup sound @@ -142,10 +143,12 @@ struct wavinfo_s { an ordinary buffer. For streamed sounds, acts as a ring buffer. */ struct sfxbuffer_s { - unsigned head; //!< ring buffer head position in sampels - unsigned tail; //!< ring buffer tail position in sampels - unsigned size; //!< size of buffer in frames + _Atomic unsigned head; //!< ring buffer head position in sampels + _Atomic unsigned tail; //!< ring buffer tail position in sampels + // FIXME should pos be atomic? it's primary use is in the mixer but can + // be used for checking the channel's "time" unsigned pos; //!< position of tail within full stream + unsigned size; //!< size of buffer in frames unsigned channels; //!< number of channels per frame unsigned sfx_length; //!< total length of sfx union { // owning instance @@ -231,7 +234,7 @@ struct sfxblock_s { /** Representation of a sound being played. */ struct channel_s { - sfxbuffer_t *buffer; //!< sound played by this channel + sfxbuffer_t *_Atomic buffer;//!< sound played by this channel float leftvol; //!< 0-1 volume float rightvol; //!< 0-1 volume unsigned end; //!< end time in global paintsamples @@ -239,7 +242,7 @@ struct channel_s { unsigned loopstart; //!< where to loop, -1 = no looping int phase; //!< phase shift between l-r in samples int oldphase; //!< phase shift between l-r in samples - byte pause; //!< don't update the channel at all + _Atomic byte pause; //!< don't update the channel at all /** signal between main program and mixer thread that the channel is to be stopped. - both \c stop and \c done are zero: normal operation @@ -251,8 +254,8 @@ struct channel_s { can be reused at any time. */ //@{ - byte stop; - byte done; + _Atomic byte stop; + _Atomic byte done; //@} }; diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index 4453852a1..0aa8c220b 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -122,11 +122,11 @@ SND_PaintChannels (snd_t *snd, unsigned endtime) // paint in the channels. ch = snd_channels; for (i = 0; i < snd_total_channels; i++, ch++) { - if (!(sb = ch->buffer)) { + if (!(sb = ch->buffer) || ch->done) { // channel is inactive continue; } - if (ch->stop || ch->done) { + if (ch->stop) { ch->done = 1; // acknowledge stopped signal continue; } From 5fa73e7ff25cdea3d4084745328ccc17c8f15fb0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Jun 2022 12:05:44 +0900 Subject: [PATCH 2908/3664] [sound] Rename "cache" to "block" and clean out old code I never liked "cache" as a name because it said where the sound was stored rather than how it was loaded/played, but "stream" is ok, since that's pretty much spot on. I'm not sure "block" is the best, but it at least makes sense because the sounds are loaded as a single block (as opposed to being streamed). An now, neither use the cache system. --- include/snd_internal.h | 68 ++++-------------------------- libs/audio/renderer/flac.c | 6 +-- libs/audio/renderer/snd_channels.c | 2 +- libs/audio/renderer/snd_mem.c | 55 +----------------------- libs/audio/renderer/snd_resample.c | 5 ++- libs/audio/renderer/snd_sfx.c | 45 ++------------------ libs/audio/renderer/vorbis.c | 8 ++-- libs/audio/renderer/wav.c | 6 +-- 8 files changed, 28 insertions(+), 167 deletions(-) diff --git a/include/snd_internal.h b/include/snd_internal.h index 24302e6f4..508075a26 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -66,11 +66,6 @@ struct sfx_s sfxblock_t *block; }; - sfxbuffer_t *(*touch) (sfx_t *sfx); - sfxbuffer_t *(*retain) (sfx_t *sfx); - void (*release) (sfx_t *sfx); - - sfxbuffer_t *(*getbuffer) (sfx_t *sfx); struct wavinfo_s *(*wavinfo) (const sfx_t *sfx); sfxbuffer_t *(*open) (sfx_t *sfx); @@ -139,8 +134,8 @@ struct wavinfo_s { unsigned datalen; //!< chunk bytes }; -/** Buffer for storing sound samples in memory. For cached sounds, acts as - an ordinary buffer. For streamed sounds, acts as a ring buffer. +/** Buffer for storing sound samples in memory. For block-loaded sounds, acts + as an ordinary buffer. For streamed sounds, acts as a ring buffer. */ struct sfxbuffer_s { _Atomic unsigned head; //!< ring buffer head position in sampels @@ -228,7 +223,7 @@ struct sfxblock_s { const sfx_t *sfx; //!< owning sfx_t instance void *file; //!< handle for "file" representing the block wavinfo_t wavinfo; //!< description of sound data - sfxbuffer_t *buffer; //!< pointer to cached buffer + sfxbuffer_t *buffer; //!< pointer to block-loaded buffer }; /** Representation of a sound being played. @@ -280,7 +275,7 @@ int SND_Memory_GetRetainCount (void *ptr) __attribute__((pure)); \ingroup sound_render_mix */ ///@{ -/** Cache sound data. Initializes caching fields of sfx. +/** Block sound data. Initializes block fields of sfx. \param sfx \param realname \param info @@ -315,9 +310,9 @@ sfxbuffer_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file, */ void SND_SFX_StreamClose (sfxstream_t *stream); -/** Pre-load a sound into the cache. +/** Load a sound into the system. \param snd sound system state - \param sample name of sound to precache + \param sample name of sound to load */ sfx_t *SND_PrecacheSound (snd_t *snd, const char *sample); @@ -556,15 +551,15 @@ int SND_LoadWav (QFile *file, sfx_t *sfx, char *realname); int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname); ///@} -/** \defgroup sound_render_cache_stream Cache/Stream Functions. +/** \defgroup sound_render_block_stream Block/Stream Functions. \ingroup sound_render */ ///@{ -/** Retrieve wavinfo from a cached sound. +/** Retrieve wavinfo from a block-loaded sound. \param sfx sound reference \return pointer to sound's wavinfo */ -wavinfo_t *SND_CacheWavinfo (const sfx_t *sfx) __attribute__((pure)); +wavinfo_t *SND_BlockWavinfo (const sfx_t *sfx) __attribute__((pure)); /** Retrieve wavinfo from a streamed sound. \param sfx sound reference @@ -572,51 +567,6 @@ wavinfo_t *SND_CacheWavinfo (const sfx_t *sfx) __attribute__((pure)); */ wavinfo_t *SND_StreamWavinfo (const sfx_t *sfx) __attribute__((pure)); -/** Ensure a cached sound is in memory. - \param sfx sound reference - \return poitner to sound buffer -*/ -sfxbuffer_t *SND_CacheTouch (sfx_t *sfx); - -/** Get the pointer to the sound buffer. - \param sfx sound reference - \return sound buffer or null - \note The sound must be retained with SND_CacheRetain() for the returned - buffer to be valid. -*/ -sfxbuffer_t *SND_CacheGetBuffer (sfx_t *sfx) __attribute__((pure)); - -/** Lock a cached sound into memory. After calling this, SND_CacheGetBffer() - will return a valid buffer. - \param sfx sound reference - \return poitner to sound buffer -*/ -sfxbuffer_t *SND_CacheRetain (sfx_t *sfx); - -/** Unlock a cached sound from memory. After calling this, SND_CacheGetBffer() - will return a null buffer. - \param sfx sound reference -*/ -void SND_CacheRelease (sfx_t *sfx); - -/** Get the pointer to the sound buffer. - \param sfx sound reference - \return poitner to sound buffer -*/ -sfxbuffer_t *SND_StreamGetBuffer (sfx_t *sfx) __attribute__((pure)); - -/** Lock a streamed sound into memory. Doesn't actually do anything other than - return a pointer to the buffer. - \param sfx sound reference - \return poitner to sound buffer -*/ -sfxbuffer_t *SND_StreamRetain (sfx_t *sfx) __attribute__((pure)); - -/** Unlock a streamed sound from memory. Doesn't actually do anything. - \param sfx sound reference -*/ -void SND_StreamRelease (sfx_t *sfx); - /** Advance the position with the stream, updating the ring buffer as necessary. Null for chached sounds. \param buffer "this" diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index 54068bc78..b757994ae 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -329,7 +329,7 @@ flac_callback_load (sfxblock_t *block) } static void -flac_cache (sfx_t *sfx, char *realname, flacfile_t *ff, wavinfo_t info) +flac_block (sfx_t *sfx, char *realname, flacfile_t *ff, wavinfo_t info) { flac_close (ff); SND_SFX_Block (sfx, realname, info, flac_callback_load); @@ -461,8 +461,8 @@ SND_LoadFLAC (QFile *file, sfx_t *sfx, char *realname) return -1; } if (info.frames / info.rate < 3) { - Sys_MaskPrintf (SYS_snd, "cache %s\n", realname); - flac_cache (sfx, realname, ff, info); + Sys_MaskPrintf (SYS_snd, "block %s\n", realname); + flac_block (sfx, realname, ff, info); } else { Sys_MaskPrintf (SYS_snd, "stream %s\n", realname); flac_stream (sfx, realname, ff, info); diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 2389b9b7c..93796ea59 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -760,7 +760,7 @@ SND_LocalSound (snd_t *snd, const char *sound) sfx = SND_PrecacheSound (snd, sound); if (!sfx) { - Sys_Printf ("S_LocalSound: can't cache %s\n", sound); + Sys_Printf ("S_LocalSound: can't load %s\n", sound); return; } if (snd_render_data.viewentity) diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index 43d166705..86f248be5 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -159,17 +159,6 @@ SND_Memory_GetRetainCount (void *ptr) return Z_GetRetainCount (snd_zone, ptr); } -static sfxbuffer_t * -snd_fail (sfx_t *sfx) -{ - return 0; -} - -static void -snd_noop (sfx_t *sfx) -{ -} - static sfxbuffer_t * snd_open (sfx_t *sfx) { @@ -184,48 +173,8 @@ snd_open_fail (sfx_t *sfx) return 0; } -sfxbuffer_t * __attribute__((pure)) -SND_CacheTouch (sfx_t *sfx) -{ - return sfx->block->buffer; -} - -sfxbuffer_t * -SND_CacheGetBuffer (sfx_t *sfx) -{ - return sfx->block->buffer; -} - -sfxbuffer_t * __attribute__((pure)) -SND_CacheRetain (sfx_t *sfx) -{ - return sfx->block->buffer; -} - -void -SND_CacheRelease (sfx_t *sfx) -{ -} - -sfxbuffer_t * -SND_StreamGetBuffer (sfx_t *sfx) -{ - return sfx->stream->buffer; -} - -sfxbuffer_t * -SND_StreamRetain (sfx_t *sfx) -{ - return sfx->stream->buffer; -} - -void -SND_StreamRelease (sfx_t *sfx) -{ -} - wavinfo_t * -SND_CacheWavinfo (const sfx_t *sfx) +SND_BlockWavinfo (const sfx_t *sfx) { return &sfx->block->wavinfo; } @@ -383,8 +332,6 @@ SND_Load (sfx_t *sfx) char buf[4]; QFile *file; - sfx->touch = sfx->retain = snd_fail; - sfx->release = snd_noop; sfx->open = snd_open_fail; file = QFS_FOpenFile (sfx->name); diff --git a/libs/audio/renderer/snd_resample.c b/libs/audio/renderer/snd_resample.c index b11e1ed88..c3cbfd185 100644 --- a/libs/audio/renderer/snd_resample.c +++ b/libs/audio/renderer/snd_resample.c @@ -1,9 +1,10 @@ /* - snd_mem.c + snd_resample.c - sound caching + sound resampling Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2010 Bill Currie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 8a4e9f6c5..538c7aa58 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -53,16 +53,6 @@ static sfx_t snd_sfx[MAX_SFX]; static int snd_num_sfx; static hashtab_t *snd_sfx_hash; -static int precache; -static cvar_t precache_cvar = { - .name = "precache", - .description = - "Toggle the use of a precache", - .default_value = "1", - .flags = CVAR_NONE, - .value = { .type = &cexpr_int, .value = &precache }, -}; - static const char * snd_sfx_getkey (const void *sfx, void *unused) { @@ -90,11 +80,7 @@ SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info, sfxblock_t *block = calloc (1, sizeof (sfxblock_t)); sfx->block = block; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = SND_CacheTouch; - sfx->retain = SND_CacheRetain; - sfx->release = SND_CacheRelease; - sfx->getbuffer = SND_CacheGetBuffer; + sfx->wavinfo = SND_BlockWavinfo; sfx->loopstart = SND_ResamplerFrames (sfx, info.loopstart); sfx->length = SND_ResamplerFrames (sfx, info.frames); @@ -112,10 +98,7 @@ SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info, { sfxstream_t *stream = calloc (1, sizeof (sfxstream_t)); sfx->open = open; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = sfx->retain = SND_StreamRetain; - sfx->release = SND_StreamRelease; - sfx->getbuffer = SND_StreamGetBuffer; + sfx->wavinfo = SND_StreamWavinfo; sfx->stream = stream; sfx->loopstart = SND_ResamplerFrames (sfx, info.loopstart); sfx->length = SND_ResamplerFrames (sfx, info.frames); @@ -213,10 +196,6 @@ SND_PrecacheSound (snd_t *snd, const char *name) Sys_Error ("SND_PrecacheSound: NULL"); sfx = SND_LoadSound (snd, va (0, "sound/%s", name)); - if (sfx && precache) { - if (sfx->retain (sfx)) - sfx->release (sfx); - } return sfx; } @@ -229,28 +208,13 @@ s_gamedir (int phase, void *data) static void s_soundlist_f (void) { - int load, total, i; + int total, i; sfx_t *sfx; - if (Cmd_Argc() >= 2 && Cmd_Argv (1)[0]) - load = 1; - else - load = 0; - total = 0; for (sfx = snd_sfx, i = 0; i < snd_num_sfx; i++, sfx++) { - if (load) { - if (!sfx->retain (sfx)) - continue; - } else { - if (!sfx->touch (sfx)) - continue; - } total += sfx->length; Sys_Printf ("%6d %6d %s\n", sfx->loopstart, sfx->length, sfx->name); - - if (load) - sfx->release (sfx); } Sys_Printf ("Total resident: %i\n", total); } @@ -259,10 +223,9 @@ void SND_SFX_Init (snd_t *snd) { snd_sfx_hash = Hash_NewTable (511, snd_sfx_getkey, snd_sfx_free, 0, 0); - Cvar_Register (&precache_cvar, 0, 0); QFS_GamedirCallback (s_gamedir, 0); Cmd_AddCommand ("soundlist", s_soundlist_f, - "Reports a list of sounds in the cache"); + "Reports a list of loaded sounds"); } diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index acd420beb..436fdd5c7 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -209,8 +209,8 @@ vorbis_callback_load (sfxblock_t *block) return vorbis_load (&vf, block); } -static void -vorbis_cache (sfx_t *sfx, char *realname, OggVorbis_File *vf, wavinfo_t info) +static void//extra _ in name because vorbis_block is a vorbis type +vorbis__block (sfx_t *sfx, char *realname, OggVorbis_File *vf, wavinfo_t info) { ov_clear (vf); SND_SFX_Block (sfx, realname, info, vorbis_callback_load); @@ -302,8 +302,8 @@ SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname) return -1; } if (info.frames / info.rate < 3) { - Sys_MaskPrintf (SYS_snd, "cache %s\n", realname); - vorbis_cache (sfx, realname, &vf, info); + Sys_MaskPrintf (SYS_snd, "block %s\n", realname); + vorbis__block (sfx, realname, &vf, info); } else { Sys_MaskPrintf (SYS_snd, "stream %s\n", realname); vorbis_stream (sfx, realname, &vf, info); diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index b5fef9bdf..4d2131f85 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -100,7 +100,7 @@ bail: } static void -wav_cache (sfx_t *sfx, char *realname, void *file, wavinfo_t info) +wav_block (sfx_t *sfx, char *realname, void *file, wavinfo_t info) { Qclose (file); SND_SFX_Block (sfx, realname, info, wav_callback_load); @@ -289,8 +289,8 @@ SND_LoadWav (QFile *file, sfx_t *sfx, char *realname) } if (info.frames / info.rate < 3) { - Sys_MaskPrintf (SYS_snd, "cache %s\n", realname); - wav_cache (sfx, realname, file, info); + Sys_MaskPrintf (SYS_snd, "block %s\n", realname); + wav_block (sfx, realname, file, info); } else { Sys_MaskPrintf (SYS_snd, "stream %s\n", realname); wav_stream (sfx, realname, file, info); From 5c94c409851e012702c85271693229965300a8d2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Jun 2022 13:25:43 +0900 Subject: [PATCH 2909/3664] [zone] Revert cache behavior to its original design My reason for using Hunk_HighAlloc for allocating cache blocks was to lock them down so they were safe for the sound mixer to access when running in a real-time thread. However, I had never tested under tight memory constraints, which proved that the design (or maybe just implementation) just wasn't robust. However, now that sounds are loaded into a completely separate region, it's safe to put the cache back to its original behaviour (still with 64-byte alignment and such, of course). This will even allow the high hunk to be used again, though it effectively was anyway with Hunk_TempAlloc. --- libs/util/zone.c | 343 +++++++++++++++++++++++++---------------------- 1 file changed, 182 insertions(+), 161 deletions(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index 584d9f8c1..92ba4b2e6 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -37,6 +37,7 @@ #include #include +#include #include "QF/cmd.h" #include "QF/cvar.h" @@ -48,7 +49,8 @@ #include "compat.h" -static void Cache_FreeLow (memhunk_t *hunk, int new_low_hunk); +static void Cache_FreeLow (memhunk_t *hunk, size_t new_low_hunk); +static void Cache_FreeHigh (memhunk_t *hunk, size_t new_high_hunk); static void Cache_Profile_r (memhunk_t *hunk); static qboolean Cache_FreeLRU (memhunk_t *hunk); @@ -537,6 +539,51 @@ cs_ind (memhunk_t *hunk, cache_system_t *cs_ptr) static memhunk_t *global_hunk; +static int +hunk_check (memhunk_t *hunk, hunkblk_t *h, int err) +{ + const char *msg = 0; + if (h->sentinal1 != HUNK_SENTINAL || h->sentinal2 != HUNK_SENTINAL) { + msg = "Hunk_Check: trashed sentinel"; + } + if (!msg && (h->size < sizeof (hunkblk_t) + || h->size + (byte *) h > hunk->base + hunk->size)) { + msg = "Hunk_Check: bad size"; + } + if (!msg) { + return 1; + } + + byte *buf = (byte *) h; + int len = sizeof (*h); + int pos = 0, llen, i; + + fflush (stdout); + fprintf (stderr, "\n"); + while (pos < len) { + llen = (len - pos < 16 ? len - pos : 16); + fprintf (stderr, "%08x: ", pos); + for (i = 0; i < llen; i++) + fprintf (stderr, "%02x ", buf[pos + i]); + for (i = 0; i < 16 - llen; i++) + fprintf (stderr, " "); + fprintf (stderr, " | "); + + for (i = 0; i < llen; i++) + fprintf (stderr, "%c", isprint (buf[pos + i]) ? buf[pos + i] : '.'); + for (i = 0; i < 16 - llen; i++) + fprintf (stderr, " "); + fprintf (stderr, "\n"); + pos += llen; + } + + if (err) { + Sys_Error ("%p: %zd: %s", h, (byte *) h - (byte *) hunk, msg); + } + fprintf (stderr, "%p: %zd: %s", h, (byte *) h - (byte *) hunk, msg); + return 0; +} + /* Hunk_Check @@ -550,11 +597,7 @@ Hunk_Check (memhunk_t *hunk) byte *hunk_end = hunk->base + hunk->low_used; for (h = (hunkblk_t *) hunk->base; (byte *) h < hunk_end; ) { - if (h->sentinal1 != HUNK_SENTINAL || h->sentinal2 != HUNK_SENTINAL) - Sys_Error ("Hunk_Check: trashed sentinal"); - if (h->size < sizeof (hunkblk_t) - || h->size + (byte *) h > hunk->base + hunk->size) - Sys_Error ("Hunk_Check: bad size"); + hunk_check (hunk, h, 1); h = (hunkblk_t *) ((byte *) h + h->size); } } @@ -600,11 +643,9 @@ Hunk_Print (memhunk_t *hunk, qboolean all) break; // run consistancy checks - if (h->sentinal1 != HUNK_SENTINAL || h->sentinal2 != HUNK_SENTINAL) - Sys_Error ("Hunk_Check: trahsed sentinal"); - if (h->size < (int) sizeof (hunkblk_t) - || h->size + (byte *) h > hunk->base + hunk->size) - Sys_Error ("Hunk_Check: bad size"); + if (!hunk_check (hunk, h, 0)) { + break; + } next = (hunkblk_t *) ((byte *) h + h->size); count++; @@ -776,6 +817,7 @@ Hunk_HighAlloc (memhunk_t *hunk, size_t size) } hunk->high_used += size; + Cache_FreeHigh (hunk, hunk->high_used); h = (void *) (hunk->base + hunk->size - hunk->high_used); h->sentinal1 = HUNK_SENTINAL; @@ -843,74 +885,6 @@ Hunk_PointerIsValid (memhunk_t *hunk, void *ptr) /* CACHE MEMORY */ - -static cache_system_t *Cache_TryAlloc (memhunk_t *hunk, size_t size, - qboolean nobottom); -#if 0 -static void -check_cache (void) -{ - cache_system_t *cs; - int used = hunk_tempactive ? hunk_tempmark : hunk_high_used; - - for (cs = cache_head.prev; cs != &cache_head; cs = cs->prev) - if (cs->prev != &cache_head) { - if ((byte *) cs + cs->size != (byte *) cs->prev) - Sys_Error ("inconsistent cache %p %p %d %d", cs, cs->prev, - (int)cs->size, - (int) ((char *)cs->prev - (char *)cs)); - if (hunk_size - ((byte*)cs - hunk_base) > used) - Sys_Error ("cache block out of high hunk"); - } - if (cache_head.prev != &cache_head && - hunk_size - ((byte*) cache_head.prev - hunk_base) != used) - Sys_Error ("cache bottom not at bottom of high hunk"); -} -#endif -static void -Cache_Move (cache_system_t *c) -{ - memhunk_t *hunk = c->hunk; - cache_system_t *new; - - // we are clearing up space at the bottom, so allocate it late - new = Cache_TryAlloc (hunk, c->size, true); - if (new) { - Sys_MaskPrintf (SYS_cache, "cache_move ok\n"); - - memcpy (new + 1, c + 1, c->size - sizeof (cache_system_t)); - new->user = c->user; - memccpy (new->name, c->name, 0, sizeof (new->name)); - Cache_Free (c->user); - new->user->data = (void *) (new + 1); - } else { - Sys_MaskPrintf (SYS_cache, "cache_move failed\n"); - - Cache_Free (c->user); // tough luck... - } -} - -/* - Cache_FreeLow - - Throw things out until the hunk can be expanded to the given point -*/ -static void -Cache_FreeLow (memhunk_t *hunk, int new_low_hunk) -{ - cache_system_t *c; - - while (1) { - c = cs_ptr (hunk, hunk->cache_head[0].prev); - if (c == hunk->cache_head) - return; // nothing in cache at all - if ((byte *) c >= hunk->base + new_low_hunk) - return; // there is space to grow the hunk - Sys_Error ("FIXME: Cache_FreeLow: not enough memory"); - Cache_Move (c); // reclaim the space - } -} - static inline void Cache_UnlinkLRU (cache_system_t * cs) { @@ -932,22 +906,6 @@ Cache_MakeLRU (cache_system_t * cs) hunk->cache_head[0].lru_next = cs_ind (hunk, cs); } -static qboolean -Cache_FreeLRU (memhunk_t *hunk) -{ - cache_system_t *cs; - - //check_cache (); - for (cs = cs_ptr (hunk, hunk->cache_head[0].lru_prev); - cs != hunk->cache_head && cs->readlock; - cs = cs_ptr (hunk, cs->lru_prev)) { - } - if (cs == hunk->cache_head) - return 0; - Cache_Free (cs->user); - return 1; -} - static void link_cache_system (cache_system_t *new, cache_system_t *cs) { @@ -956,7 +914,6 @@ link_cache_system (cache_system_t *new, cache_system_t *cs) new->prev = cs->prev; cs_ptr (hunk, cs->prev)->next = cs_ind (hunk, new); cs->prev = cs_ind (hunk, new); - } /* @@ -966,16 +923,23 @@ link_cache_system (cache_system_t *new, cache_system_t *cs) Size should already include the header and padding */ static cache_system_t * -Cache_TryAlloc (memhunk_t *hunk, size_t size, qboolean nobottom) +Cache_TryAlloc (memhunk_t *hunk, size_t size, + size_t low_space, size_t high_space) { cache_system_t *cs, *new; - //check_cache (); - // is the cache completely empty? - if (!nobottom && hunk->cache_head[0].prev == 0) { - new = (cache_system_t *) Hunk_HighAlloc (hunk, size); - if (!new) + low_space = max (low_space, hunk->low_used); + high_space = max (high_space, hunk->high_used); + + if (hunk->cache_head[0].prev == 0) { + // The cache is completely empty, so just check for space + if (hunk->size - high_space < low_space + size) { return 0; + } + // cache memory comes from the free region of the hunk. Should either + // end of the hunk need to grow, interfering cache blocks will be + // either moved or freed if there is nowhere to move the block. + new = (cache_system_t *) (hunk->base + hunk->low_used); new->size = size; new->hunk = hunk; hunk->cache_head[0].prev = cs_ind (hunk, new); @@ -984,55 +948,132 @@ Cache_TryAlloc (memhunk_t *hunk, size_t size, qboolean nobottom) new->readlock = 0; new->name[0] = 0; Cache_MakeLRU (new); - //check_cache (); return new; } - // search for space in existing cache - for (cs = cs_ptr (hunk, hunk->cache_head[0].next); - cs != hunk->cache_head; - cs = cs_ptr (hunk, cs->next)) { - if (cs->user) - continue; // block isn't free - if (cs->size >= size) { - // found a big enough free block. If possible, carve it up for - // later reuse, using the upper portion of the block for the - // newly allocated block. - new = cs; - if (size - cs->size >= sizeof (cache_system_t)) { - new = (cache_system_t *) ((char *) cs + cs->size - size); - new->readlock = 0; - new->name[0] = 0; - new->size = size; - new->hunk = hunk; - cs->size -= size; - link_cache_system (new, cs); - //check_cache (); - } + new = (cache_system_t *) (hunk->base + low_space); + uint32_t csi = hunk->cache_head[0].next; + do { + cs = cs_ptr (hunk, csi); + if ((byte *) cs >= (byte *) new + size) { + + new->size = size; + new->hunk = hunk; + + link_cache_system (new, cs); + + new->readlock = 0; + new->name[0] = 0; + Cache_MakeLRU (new); return new; } + + // try next block. If it is a hole, then the resulting cs will be + // greater than new (though possibly not sufficiently so), but if + // it's not a hole, then they'll be the same and the difference in + // the test above will be 0 + new = (cache_system_t *) ((byte *) cs + cs->size); + csi = cs->next; + } while (csi); + + // came to the end of the cache. try to allocate from between the cache + // and the high hunk + if ((byte *) new < hunk->base + low_space) { + new = (cache_system_t *) (hunk->base + low_space); } - - if (nobottom) - return 0; - - // didn't find a free block, so make a new one. - new = Hunk_HighAlloc (hunk, size); - if (new) { - new->readlock = 0; - new->name[0] = 0; + if (hunk->base + hunk->size - high_space >= (byte *) new + size) { new->size = size; new->hunk = hunk; + link_cache_system (new, hunk->cache_head); + + new->readlock = 0; + new->name[0] = 0; + Cache_MakeLRU (new); - //check_cache (); return new; } return 0; // couldn't allocate } +static void +Cache_Move (cache_system_t *c, size_t new_low_hunk, size_t new_high_hunk) +{ + memhunk_t *hunk = c->hunk; + cache_system_t *new; + + new = Cache_TryAlloc (hunk, c->size, new_low_hunk, new_high_hunk); + if (new) { + Sys_MaskPrintf (SYS_cache, "cache_move ok\n"); + + memcpy (new + 1, c + 1, c->size - sizeof (cache_system_t)); + new->user = c->user; + memccpy (new->name, c->name, 0, sizeof (new->name)); + Cache_Free (c->user); + new->user->data = (void *) (new + 1); + } else { + Sys_MaskPrintf (SYS_cache, "cache_move failed\n"); + + Cache_Free (c->user); // tough luck... + } +} + +/* + Cache_FreeLow + + Throw things out until the hunk can be expanded to the given point +*/ +static void +Cache_FreeLow (memhunk_t *hunk, size_t new_low_hunk) +{ + cache_system_t *c; + uint32_t ci; + + // if next is 0, then there is nothing in the cache + while ((ci = hunk->cache_head[0].next)) { + c = cs_ptr (hunk, ci); + if ((byte *) c >= hunk->base + new_low_hunk) { + // there is space to grow the hunk + return; + } + // reclaim the space (the block will be moved or freed) + Cache_Move (c, new_low_hunk, 0); + } +} + +static void +Cache_FreeHigh (memhunk_t *hunk, size_t new_high_hunk) +{ + cache_system_t *c; + uint32_t ci; + while ((ci = hunk->cache_head[0].prev)) { + c = cs_ptr (hunk, ci); + if ((byte *) c + c->size <= hunk->base + hunk->size - new_high_hunk) { + // there is space to grow the hunk + return; + } + // reclaim the space (the block will be moved or freed) + Cache_Move (c, 0, new_high_hunk); + } +} + +static qboolean +Cache_FreeLRU (memhunk_t *hunk) +{ + cache_system_t *cs; + + for (cs = cs_ptr (hunk, hunk->cache_head[0].lru_prev); + cs != hunk->cache_head && cs->readlock; + cs = cs_ptr (hunk, cs->lru_prev)) { + } + if (cs == hunk->cache_head) + return 0; + Cache_Free (cs->user); + return 1; +} + static void Cache_Profile_r (memhunk_t *hunk) { @@ -1180,35 +1221,15 @@ Cache_Free (cache_user_t *c) Sys_MaskPrintf (SYS_cache, "Cache_Free: freeing '%.*s' %p\n", sz, cs->name, cs); - Cache_UnlinkLRU (cs); + memhunk_t *hunk = cs->hunk; - memhunk_t *h = cs->hunk; - //check_cache (); - cs->user = 0; - if (!cs_ptr (h, cs->prev)->user) { - cs->size += cs_ptr (h, cs->prev)->size; - cs_ptr (h, cs_ptr (h, cs->prev)->prev)->next = cs_ind (h, cs); - cs->prev = cs_ptr (h, cs->prev)->prev; - } - if (!cs_ptr (h, cs->next)->user) { - cs = cs_ptr (h, cs->next); - cs->size += cs_ptr (h, cs->prev)->size; - cs_ptr (h, cs_ptr (h, cs->prev)->prev)->next = cs_ind (h, cs); - cs->prev = cs_ptr (h, cs->prev)->prev; - } - if (!cs->next) { - cs_ptr (h, cs->next)->prev = cs->prev; - cs_ptr (h, cs->prev)->next = cs->next; - if (cs->prev) { - __auto_type ptr = (byte *) cs_ptr (h, cs->prev); - Hunk_FreeToHighMark (h, h->size - (ptr - h->base)); - } else { - Hunk_FreeToHighMark (h, 0); - } - } - //check_cache (); + cs_ptr (hunk, cs->prev)->next = cs->next; + cs_ptr (hunk, cs->next)->prev = cs->prev; + cs->next = cs->prev = 0; c->data = NULL; + + Cache_UnlinkLRU (cs); } static void * @@ -1226,7 +1247,7 @@ Cache_Alloc_r (memhunk_t *hunk, cache_user_t *c, size_t size, const char *name) // find memory for it while (1) { - cs = Cache_TryAlloc (hunk, size, false); + cs = Cache_TryAlloc (hunk, size, 0, 0); if (cs) { memccpy (cs->name, name, 0, sizeof (cs->name)); c->data = (void *) (cs + 1); From ef64161835009c08f72e2a92bcdbaedfc46adeff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Jun 2022 13:33:54 +0900 Subject: [PATCH 2910/3664] [zone] Make Hunk_RawAlloc the core hunk allocator It turns out that copying just "unknown" is a significant performance hit when doing over 100M allocations. Making Hunk_RawAlloc the core and initializing the name field with a single 0 shaved about a second off `qfvis gmsp3v2.bsp` (from about 39s to about 38s). --- libs/util/zone.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index 92ba4b2e6..11dedb7a3 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -655,7 +655,8 @@ Hunk_Print (memhunk_t *hunk, qboolean all) // print the single block if (all) { const int sz = sizeof (h->name); - Sys_Printf ("%8p :%8zd %*.*s\n", h, h->size, sz, sz, h->name); + Sys_Printf ("%8p :%8zd %*.*s\n", h, h->size, sz, sz, + h->name[0] ? h->name : "unknown"); } // print the total @@ -664,7 +665,7 @@ Hunk_Print (memhunk_t *hunk, qboolean all) if (!all) { const int sz = sizeof (h->name); Sys_Printf (" :%8i %*.*s (TOTAL)\n", - sum, sz, sz, h->name); + sum, sz, sz, h->name[0] ? h->name : "unknown"); } count = 0; sum = 0; @@ -707,7 +708,7 @@ Hunk_HighMark (memhunk_t *hunk) } VISIBLE void * -Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) +Hunk_RawAlloc (memhunk_t *hunk, size_t size) { hunkblk_t *h; @@ -718,13 +719,13 @@ Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) size = sizeof (hunkblk_t) + ((size + HUNK_ALIGN - 1) & ~(HUNK_ALIGN - 1)); if (hunk->size - hunk->low_used - hunk->high_used < size) { - Hunk_HighMark (hunk); - Cache_FreeLRU (hunk); + Hunk_HighMark (hunk); // force free of temp hunk } if (hunk->size - hunk->low_used - hunk->high_used < size) { int mem = hunk->size / (1024 * 1024); mem += 8; mem &= ~7; + Hunk_Print (hunk, 1); Cache_Profile_r (hunk); Sys_Error ("Not enough RAM allocated. Try starting using \"-mem %d\" on " @@ -740,11 +741,20 @@ Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) h->size = size; h->sentinal1 = HUNK_SENTINAL; h->sentinal2 = HUNK_SENTINAL; - memccpy (h->name, name, 0, sizeof (h->name)); + h->name[0] = 0; return (void *) (h + 1); } +VISIBLE void * +Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) +{ + void *mem = Hunk_RawAlloc (hunk, size); + hunkblk_t *h = ((hunkblk_t *) mem) - 1; + memccpy (h->name, name, 0, sizeof (h->name)); + return mem; +} + VISIBLE void * Hunk_AllocName (memhunk_t *hunk, size_t size, const char *name) { @@ -754,17 +764,13 @@ Hunk_AllocName (memhunk_t *hunk, size_t size, const char *name) return mem; } -VISIBLE void * -Hunk_RawAlloc (memhunk_t *hunk, size_t size) -{ - return Hunk_RawAllocName (hunk, size, "unknown"); -} - VISIBLE void * Hunk_Alloc (memhunk_t *hunk, size_t size) { if (!hunk) { hunk = global_hunk; } //FIXME clean up callers - return Hunk_AllocName (hunk, size, "unknown"); + void *mem = Hunk_RawAlloc (hunk, size); + memset (mem, 0, size); + return mem; } VISIBLE size_t From 520371a3aaa4ab9a6d7ece7919da4dc80624c86b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 May 2022 20:48:50 +0900 Subject: [PATCH 2911/3664] [zone] Fix bad suggested mem calculation Because the calculation didn't take the hunk header size (which is not included in the hunk size) into account, the conversion to MB was one short and thus the rounding up to the next 8 MB boundary was giving the current total hunk size (ie, the already given size). Most confusing to a user ("But I already asked for 128MB!"). --- libs/util/zone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/zone.c b/libs/util/zone.c index 11dedb7a3..37f54e5b1 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -722,7 +722,7 @@ Hunk_RawAlloc (memhunk_t *hunk, size_t size) Hunk_HighMark (hunk); // force free of temp hunk } if (hunk->size - hunk->low_used - hunk->high_used < size) { - int mem = hunk->size / (1024 * 1024); + int mem = (hunk->size + sizeof (memhunk_t)) / (1024 * 1024); mem += 8; mem &= ~7; Hunk_Print (hunk, 1); From c72b04a522209014291e553ef070a57a7be56221 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Jun 2022 14:28:28 +0900 Subject: [PATCH 2912/3664] [cvar] Remove a debug print --- libs/util/cvar.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 8c50febc5..2fb374183 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -332,7 +332,6 @@ Cvar_CompleteBuildList (const char *partial) // criteron for a match Hash_ForEach (calias_hash, cvar_match_copy, &ctx); ctx.list[ctx.index] = 0; - fprintf (stderr, "%d %d\n", num_matches, ctx.index); heapsort (ctx.list, ctx.index, sizeof (char *), cvar_cmp_name); return ctx.list; } From 330569a3fbca9cf92d5fefc4516d3b0fc4734c3b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Jun 2022 14:29:14 +0900 Subject: [PATCH 2913/3664] [sound] Add a function to set ambient sounds This gets ambient sounds (in particular, water and sky) working again for quakeworld after the recent sound changes, and again for nq after I don't know how long. --- include/QF/plugin/snd_render.h | 1 + include/QF/sound.h | 2 ++ include/snd_internal.h | 2 ++ libs/audio/renderer/snd_channels.c | 9 +++++++++ libs/audio/renderer/snd_dma.c | 9 +++++++++ libs/audio/snd.c | 7 +++++++ libs/client/cl_temp_entities.c | 2 ++ 7 files changed, 32 insertions(+) diff --git a/include/QF/plugin/snd_render.h b/include/QF/plugin/snd_render.h index ae96764be..465415e09 100644 --- a/include/QF/plugin/snd_render.h +++ b/include/QF/plugin/snd_render.h @@ -38,6 +38,7 @@ typedef struct snd_render_funcs_s { void (*init) (void); void (*ambient_off) (void); void (*ambient_on) (void); + void (*set_ambient) (int amb_channel, struct sfx_s *sfx); void (*static_sound) (struct sfx_s *sfx, vec4f_t origin, float vol, float attenuation); void (*start_sound) (int entnum, int entchannel, struct sfx_s *sfx, const vec4f_t, float vol, float attenuation); void (*local_sound) (const char *s); diff --git a/include/QF/sound.h b/include/QF/sound.h index 183ddaede..c8a86bb71 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -181,6 +181,8 @@ void S_AmbientOff (void); */ void S_AmbientOn (void); +void S_SetAmbient (int amb_channel, sfx_t *sfx); + /** Link sound engine builtins into the specified progs vm \param pr the vm to link the builtins into. */ diff --git a/include/snd_internal.h b/include/snd_internal.h index 508075a26..481b44551 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -386,6 +386,8 @@ void SND_AmbientOff (snd_t *snd); */ void SND_AmbientOn (snd_t *snd); +void SND_SetAmbient (snd_t *snd, int amb_channel, sfx_t *sfx); + /** Update the sound engine with the client's position and orientation and render some sound. \param snd sound system state diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 93796ea59..6fdd3bca2 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -419,6 +419,15 @@ SND_AmbientOn (snd_t *snd) snd_ambient = true; } +void +SND_SetAmbient (snd_t *snd, int amb_channel, sfx_t *sfx) +{ + if (amb_channel < 0 || amb_channel > NUM_AMBIENTS) { + return; + } + ambient_sfx[amb_channel] = sfx; +} + static void s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level) { diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index 7ddfd4dc6..dc8dfb481 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -418,6 +418,14 @@ s_ambient_on (void) SND_AmbientOn (&snd); } +static void +s_set_ambient (int amb_channel, sfx_t *sfx) +{ + if (!sound_started) + return; + SND_SetAmbient (&snd, amb_channel, sfx); +} + static void s_static_sound (sfx_t *sfx, vec4f_t origin, float vol, float attenuation) @@ -551,6 +559,7 @@ static snd_render_funcs_t plugin_info_render_funcs = { .init = s_init, .ambient_off = s_ambient_off, .ambient_on = s_ambient_on, + .set_ambient = s_set_ambient, .static_sound = s_static_sound, .start_sound = s_start_sound, .local_sound = s_local_sound, diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 14b005ce7..8cb7d331f 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -148,6 +148,13 @@ S_AmbientOn (void) snd_render_funcs->ambient_on (); } +VISIBLE void +S_SetAmbient (int amb_channel, sfx_t *sfx) +{ + if (snd_render_funcs) + snd_render_funcs->set_ambient (amb_channel, sfx); +} + VISIBLE void S_StaticSound (sfx_t *sfx, vec4f_t origin, float vol, float attenuation) { diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index dc907958f..74e5374bc 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -129,6 +129,8 @@ CL_TEnts_Precache (void) if (!cl_mod_beam) { cl_mod_beam = cl_mod_bolt; } + S_SetAmbient (AMBIENT_WATER, S_PrecacheSound ("ambience/water1.wav")); + S_SetAmbient (AMBIENT_SKY, S_PrecacheSound ("ambience/wind2.wav")); } static void From 2c8bec27c73cbf0ea291a1e68b063966bd03a43b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jul 2022 21:14:28 +0900 Subject: [PATCH 2914/3664] Fix a pile of warnings for gcc 12 Most were pretty easy and fairly logical, but gib's regex was a bit of a pain until I figured out the real problem was the conditional assignments. However, libs/gamecode/test/test-conv4 fails when optimizing due to gcc using vcvttps2dq (which is nice, actually) for vector forms, but not the single equivalent other times. I haven't decided what to do with the test (I might abandon it as it does seem to be UD). --- include/QF/sys.h | 2 +- libs/audio/targets/snd_alsa.c | 3 +++ libs/gamecode/convert.py | 6 +++--- libs/gamecode/test/main.c | 10 ++++++++++ libs/gib/regex.c | 27 +++++++++++++++------------ libs/models/brush/model_brush.c | 6 ++++-- libs/video/renderer/sw/d_sprite.c | 18 +++++------------- libs/video/renderer/sw/sw_rdraw.c | 4 ++-- libs/video/renderer/vulkan/util.h | 2 +- qw/source/cl_parse.c | 3 +-- tools/qfcc/include/class.h | 4 ++-- tools/qfcc/include/function.h | 2 +- tools/qfcc/include/statements.h | 4 ++-- tools/qfcc/source/obj_file.c | 2 +- tools/qfcc/source/statements.c | 4 ++-- tools/qfcc/source/symtab.c | 2 +- 16 files changed, 54 insertions(+), 45 deletions(-) diff --git a/include/QF/sys.h b/include/QF/sys.h index 45d818660..dd8c53e0c 100644 --- a/include/QF/sys.h +++ b/include/QF/sys.h @@ -80,7 +80,7 @@ void Sys_FatalError (const char *error, ...) __attribute__((format(PRINTF,1,2), void Sys_Quit (void) __attribute__((noreturn)); void Sys_Shutdown (void); void Sys_RegisterShutdown (void (*func) (void *), void *data); -int64_t Sys_StartTime (void) __attribute__ ((const)); +int64_t Sys_StartTime (void) __attribute__ ((pure)); int64_t Sys_LongTime (void); double Sys_DoubleTime (void); int64_t Sys_TimeBase (void) __attribute__ ((const)); diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 8235dd271..371ccba27 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -311,6 +311,7 @@ alsa_process (snd_pcm_t *pcm, snd_t *snd) if ((res = alsa_recover (pcm, -EPIPE)) < 0) { Sys_Printf ("snd_alsa: XRUN recovery failed: %s\n", qfsnd_strerror (res)); + snd->xfer_data = 0; return res; } ret = 0; @@ -323,6 +324,7 @@ alsa_process (snd_pcm_t *pcm, snd_t *snd) if ((res = alsa_recover (pcm, res >= 0 ? -EPIPE : res)) < 0) { Sys_Printf ("snd_alsa: XRUN recovery failed: %s\n", qfsnd_strerror (res)); + snd->xfer_data = 0; return res; } ret = 0; @@ -330,6 +332,7 @@ alsa_process (snd_pcm_t *pcm, snd_t *snd) size -= packet.nframes; } + snd->xfer_data = 0; return ret; } diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index 333846c66..ce3637c7c 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -72,8 +72,8 @@ def dst_str(width, src_type, dst_type): return f"OPC({types[dst_type]})" def zero_str(width, src_type): - ones = "{%s}" % (", ".join(["0"] * (width + 1))) - return f"{cast_str(width, src_type, src_type)} {ones}" + zeros = "{%s}" % (", ".join(["0"] * (width + 1))) + return f"{cast_str(width, src_type, src_type)} {zeros}" def one_str(width, src_type): ones = "{%s}" % (", ".join(["1"] * (width + 1))) @@ -110,7 +110,7 @@ for width in range(4): elif width == 2: print(f"{case} VectorCompUop(&{dst},{cast},&{src}); break;") else: - expand = expand_str(width, src) + expand = expand_str(width, src, f"({types[dst_type]})") print(f"{case} {dst} = {cast} {expand}; break;") elif mode == 2: one = one_str(width, src_type) diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 4c8299e17..9344025d0 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -5,6 +5,8 @@ #include "QF/va.h" +#include "QF/simd/types.h" + #define num_tests (sizeof (tests) / sizeof (tests[0])) static int test_enabled[num_tests] = { 0 }; @@ -156,6 +158,14 @@ check_result (test_t *test) printf ("test #%zd: %s: OK\n", test - tests, test->desc); } else { printf ("test #%zd: %s: words differ\n", test - tests, test->desc); + for (pr_uint_t i = 0; i < test->num_globals; i += 4) { + pr_ivec4_t *a = (pr_ivec4_t *) &test->expect_globals[i]; + pr_ivec4_t *b = (pr_ivec4_t *) &test_pr.pr_globals[i]; + if (memcmp (a, b, sizeof (pr_ivec4_t))) { + printf ("-%4x { %8x, %8x %8x %8x }\n", i, VEC4_EXP (*a)); + printf ("+%4x { %8x, %8x %8x %8x }\n", i, VEC4_EXP (*b)); + } + } } return ret; } diff --git a/libs/gib/regex.c b/libs/gib/regex.c index 74a16b1a2..346c1fb8d 100644 --- a/libs/gib/regex.c +++ b/libs/gib/regex.c @@ -963,7 +963,11 @@ static reg_errcode_t compile_range (const char **p_ptr, const char *pend, char * being larger than MAX_BUF_SIZE, then flag memory exhausted. */ #define EXTEND_BUFFER() \ do { \ - unsigned char *old_buffer = bufp->buffer; \ + intptr_t b_offs = b - bufp->buffer; \ + intptr_t begalt_offs = b - begalt; \ + intptr_t fixup_alt_jump_offs = b - fixup_alt_jump; \ + intptr_t laststart_offs = b - laststart; \ + intptr_t pending_exact_offs = b - pending_exact; \ if (bufp->allocated == MAX_BUF_SIZE) \ return REG_ESIZE; \ bufp->allocated <<= 1; \ @@ -971,19 +975,18 @@ static reg_errcode_t compile_range (const char **p_ptr, const char *pend, char * bufp->allocated = MAX_BUF_SIZE; \ bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ if (bufp->buffer == NULL) \ - return REG_ESPACE; \ - /* If the buffer moved, move all the pointers into it. */ \ - if (old_buffer != bufp->buffer) \ { \ - b = (b - old_buffer) + bufp->buffer; \ - begalt = (begalt - old_buffer) + bufp->buffer; \ - if (fixup_alt_jump) \ - fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ - if (laststart) \ - laststart = (laststart - old_buffer) + bufp->buffer; \ - if (pending_exact) \ - pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + laststart = fixup_alt_jump = 0; \ + return REG_ESPACE; \ } \ + b = b_offs + bufp->buffer; \ + begalt = b - begalt_offs; \ + if (fixup_alt_jump) \ + fixup_alt_jump = b - fixup_alt_jump_offs; \ + if (laststart) \ + laststart = b - laststart_offs; \ + if (pending_exact) \ + pending_exact = b - pending_exact_offs; \ } while (0) diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 7037710d3..2c5ad0243 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -637,8 +637,10 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) out->samples = brush->lightdata + (i * mod_lightmap_bytes); // set the drawing flags flag - if (!out->texinfo->texture || !out->texinfo->texture->name) - continue; // avoid crashing on null textures + if (!out->texinfo->texture) { + // avoid crashing on null textures (which do exist) + continue; + } if (!strncmp (out->texinfo->texture->name, "sky", 3)) { // sky out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); diff --git a/libs/video/renderer/sw/d_sprite.c b/libs/video/renderer/sw/d_sprite.c index c17e5957f..c39a056a3 100644 --- a/libs/video/renderer/sw/d_sprite.c +++ b/libs/video/renderer/sw/d_sprite.c @@ -35,8 +35,6 @@ static int sprite_height; static int minindex, maxindex; -static sspan_t *sprite_spans; - #ifdef PIC #undef USE_INTEL_ASM //XXX asm pic hack @@ -195,15 +193,13 @@ D_SpriteDrawSpans (sspan_t *pspan) #endif static void -D_SpriteScanLeftEdge (void) +D_SpriteScanLeftEdge (sspan_t *pspan) { int i, v, itop, ibottom, lmaxindex; emitpoint_t *pvert, *pnext; - sspan_t *pspan; float du, dv, vtop, vbottom, slope; fixed16_t u, u_step; - pspan = sprite_spans; i = minindex; if (i == 0) i = r_spritedesc.nump; @@ -249,15 +245,13 @@ D_SpriteScanLeftEdge (void) } static void -D_SpriteScanRightEdge (void) +D_SpriteScanRightEdge (sspan_t *pspan) { int i, v, itop, ibottom; emitpoint_t *pvert, *pnext; - sspan_t *pspan; float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext; fixed16_t u, u_step; - pspan = sprite_spans; i = minindex; vvert = r_spritedesc.pverts[i].v; @@ -371,8 +365,6 @@ D_DrawSprite (const vec3_t relvieworg) emitpoint_t *pverts; sspan_t spans[MAXHEIGHT + 1]; - sprite_spans = spans; - // find the top and bottom vertices, and make sure there's at least one // scan to draw ymin = 999999.9; @@ -410,7 +402,7 @@ D_DrawSprite (const vec3_t relvieworg) pverts[nump] = pverts[0]; D_SpriteCalculateGradients (relvieworg); - D_SpriteScanLeftEdge (); - D_SpriteScanRightEdge (); - D_SpriteDrawSpans (sprite_spans); + D_SpriteScanLeftEdge (spans); + D_SpriteScanRightEdge (spans); + D_SpriteDrawSpans (spans); } diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index 1d7a2a545..9fc454ca4 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -49,7 +49,7 @@ static polydesc_t r_polydesc; clipplane_t view_clipplanes[4]; -medge_t *r_pedge; +medge_t *r_pedge; // FIXME used by asm qboolean r_leftclipped, r_rightclipped; static qboolean makeleftedge, makerightedge; @@ -518,7 +518,6 @@ R_RenderBmodelFace (entity_t *ent, bedge_t *pedges, msurface_t *psurf) plane_t *pplane; float distinv; vec3_t p_normal; - medge_t tedge; clipplane_t *pclip; // skip out if no more surfs @@ -535,6 +534,7 @@ R_RenderBmodelFace (entity_t *ent, bedge_t *pedges, msurface_t *psurf) c_faceclip++; // this is a dummy to give the caching mechanism someplace to write to + static medge_t tedge; r_pedge = &tedge; // set up clip planes diff --git a/libs/video/renderer/vulkan/util.h b/libs/video/renderer/vulkan/util.h index 41181ff9e..944e34cfe 100644 --- a/libs/video/renderer/vulkan/util.h +++ b/libs/video/renderer/vulkan/util.h @@ -5,7 +5,7 @@ typedef struct strset_s strset_t; -int count_strings (const char * const *str) __attribute__((const)); +int count_strings (const char * const *str) __attribute__((pure)); void merge_strings (const char **out, const char * const *in1, const char * const *in2); void prune_strings (strset_t *strset, const char **strings, uint32_t *count); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 7ca2f8f4b..027e5e9e4 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -297,8 +297,7 @@ Model_NextDownload (void) return; // started a download } - if (cl.model_name[1]) - CL_MapCfg (cl.model_name[1]); + CL_MapCfg (cl.model_name[1]); for (i = 1; i < cl.nummodels; i++) { const char *info_key = 0; diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index 217227a73..ef223334f 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -118,9 +118,9 @@ struct selector_s; int is_id (const struct type_s *type) __attribute__((pure)); int is_class (const struct type_s *type) __attribute__((pure)); -int is_Class (const struct type_s *type) __attribute__((const)); +int is_Class (const struct type_s *type) __attribute__((pure)); int is_classptr (const struct type_s *type) __attribute__((pure)); -int is_SEL (const struct type_s *type) __attribute__((const)); +int is_SEL (const struct type_s *type) __attribute__((pure)); int is_object (const struct type_s *type) __attribute__((const)); int is_method (const struct type_s *type) __attribute__((const)); int is_method_description (const struct type_s *type) __attribute__((const)); diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 15f32ddc3..5871945e4 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -153,7 +153,7 @@ param_t *check_params (param_t *params); enum storage_class_e; struct defspace_s; -int value_too_large (struct type_s *val_type) __attribute__((const)); +int value_too_large (struct type_s *val_type) __attribute__((pure)); void make_function (struct symbol_s *sym, const char *nice_name, struct defspace_s *space, enum storage_class_e storage); struct symbol_s *function_symbol (struct symbol_s *sym, diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index a1fc6914e..896732dda 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -135,8 +135,8 @@ struct expr_s; struct type_s; struct dstring_s; -extern const char *op_type_names[]; -extern const char *st_type_names[]; +extern const char * const op_type_names[]; +extern const char * const st_type_names[]; const char *optype_str (op_type_e type) __attribute__((const)); diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 863d56d64..997d4a9a5 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -960,7 +960,7 @@ typedef struct globals_info_s { } globals_info_t; -static globals_info_t +static globals_info_t __attribute__((pure)) qfo_count_globals (qfo_t *qfo, dprograms_t *progs, int word_align) { globals_info_t info = {}; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 28114dedf..190464202 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -65,7 +65,7 @@ #include "tools/qfcc/source/qc-parse.h" -const char *op_type_names[] = { +const char * const op_type_names[] = { "op_def", "op_value", "op_label", @@ -75,7 +75,7 @@ const char *op_type_names[] = { "op_pseudo", }; -const char *st_type_names[] = { +const char * const st_type_names[] = { "st_none", "st_expr", "st_assign", diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 6261b66ee..49fc4fa0d 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -51,7 +51,7 @@ static symtab_t *symtabs_freelist; static symbol_t *symbols_freelist; -static const char *sy_type_names[] = { +static const char * const sy_type_names[] = { "sy_name", "sy_var", "sy_const", From 732ea3a5fd84f48b9f9d24f41e553ff71411f239 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 26 Jul 2022 21:36:56 +0900 Subject: [PATCH 2915/3664] Fix a bunch of issues for clang One *actual* error (wrong enum type), and some memory alignment issues. The rest just clang being lame. --- include/QF/cexpr.h | 8 +++++++- libs/audio/renderer/snd_channels.c | 2 +- libs/client/cl_light.c | 7 ++++++- libs/gamecode/pr_parse.c | 1 + libs/video/renderer/gl/gl_lightmap.c | 20 -------------------- libs/video/renderer/vulkan/vulkan_lighting.c | 1 + libs/video/renderer/vulkan/vulkan_texture.c | 4 ++-- tools/qfcc/source/value.c | 5 ++++- 8 files changed, 22 insertions(+), 26 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 5935e37bb..4299b7ead 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -29,6 +29,12 @@ #include +#ifdef __clang__ +#define DESIGNATED_INIT +#else +#define DESIGNATED_INIT __attribute__((designated_init)) +#endif + struct exprval_s; struct exprctx_s; struct va_ctx_s; @@ -57,7 +63,7 @@ typedef struct exprtype_s { binop_t *binops; unop_t *unops; void *data; -} __attribute__((designated_init)) exprtype_t; +} DESIGNATED_INIT exprtype_t; typedef struct exprval_s { exprtype_t *type; diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 6fdd3bca2..f7043de83 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -149,7 +149,7 @@ static void snd_free_channel (channel_t *ch) { sfxbuffer_t *buffer = ch->buffer; - ch->buffer = 0; + ch->buffer = (sfxbuffer_t *) 0; ch->stop = 0; ch->done = 0; int chan_ind = ch - snd_channels; diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index 5e2bf39ca..fd8831783 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -198,7 +198,12 @@ parse_light (light_t *light, int *style, const plitem_t *entity, if ((str = PL_String (PL_ObjectForKey (entity, "color"))) || (str = PL_String (PL_ObjectForKey (entity, "_color")))) { - sscanf (str, "%f %f %f", VectorExpandAddr (light->color)); + union { + float a[4]; + vec4f_t v; + } color = {}; + sscanf (str, "%f %f %f", VectorExpandAddr (color.a)); + light->color = color.v; VectorScale (light->color, 1/255.0, light->color); } diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 1f8f3cebd..6f7a032ed 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -231,6 +231,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) break; case ev_vector: + (void)0;//FIXME for clang vec3_t vec = {}; char *str = alloca (strlen (s) + 1); strcpy (str, s); diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index a5e112b35..a6de23b33 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -418,26 +418,6 @@ R_BuildLightMap_4 (const transform_t *transform, mod_brush_t *brush, // BRUSH MODELS =============================================================== -static inline void -do_subimage_2 (int i) -{ - byte *block, *lm, *b; - int stride, width; - glRect_t *rect = &gl_lightmap_rectchange[i]; - - width = rect->w * lightmap_bytes; - stride = BLOCK_WIDTH * lightmap_bytes; - b = block = Hunk_TempAlloc (0, rect->h * width); - lm = lightmaps[i] + (rect->t * BLOCK_WIDTH + rect->l) * lightmap_bytes; - for (i = rect->h; i > 0; i--) { - memcpy (b, lm, width); - b += width; - lm += stride; - } - qfglTexSubImage2D (GL_TEXTURE_2D, 0, rect->l, rect->t, rect->w, rect->h, - gl_lightmap_format, GL_UNSIGNED_BYTE, block); -} - void gl_R_BlendLightmaps (void) { diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 966679238..b92ae2a67 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -438,6 +438,7 @@ create_light_matrices (lightingctx_t *lctx) break; case ST_CASCADE: case ST_PLANE: + (void)0;//FIXME for clang //FIXME will fail for -ref_direction vec4f_t dir = light->direction; dir[3] = 0; diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 26e005f08..699b3af3d 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -176,8 +176,8 @@ Vulkan_LoadTexArray (vulkan_ctx_t *ctx, tex_t *tex, int layers, int mip, VkExtent3D extent = { tex[0].width, tex[0].height, 1 }; VkImageType itype = layers > 0 ? VK_IMAGE_TYPE_2D : VK_IMAGE_TYPE_2D; - VkImageType vtype = layers > 0 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY - : VK_IMAGE_VIEW_TYPE_2D; + VkImageViewType vtype = layers > 0 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY + : VK_IMAGE_VIEW_TYPE_2D; if (layers < 1) { layers = 1; } diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index bd8ac599e..59de51d21 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -94,7 +94,9 @@ static ex_value_t * new_value (void) { ex_value_t *value; +#define malloc(x) aligned_alloc (__alignof__(ex_value_t), x) ALLOC (256, ex_value_t, values, value); +#undef malloc return value; } @@ -636,7 +638,8 @@ make_def_imm (def_t *def, hashtab_t *tab, ex_value_t *val) { immediate_t *imm; - imm = calloc (1, sizeof (immediate_t)); + imm = aligned_alloc (__alignof__(immediate_t), sizeof (immediate_t)); + memset (imm, 0, sizeof (immediate_t)); imm->def = def; memcpy (&imm->i, &val->v, sizeof (imm->i)); From f4ae24e0e050f095452e599d39e7cfaa1eec417f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 30 Jul 2022 21:21:31 +0900 Subject: [PATCH 2916/3664] [qfcc] Support alignment in qfo spaces The alignment is specified as a power of 2 (ie, actual alignment = 1 << alignment) allowing old object files to be compatible (as their alignment is 0). This is necessary for (in part for #30) as it turned out even global vectors were not aligned correctly. Currently, only data spaces even vaguely respect alignment. This may need to be fixed in the future. --- tools/qfcc/include/defspace.h | 1 + tools/qfcc/include/obj_file.h | 4 +- tools/qfcc/include/reloc.h | 2 + tools/qfcc/source/defspace.c | 8 +++- tools/qfcc/source/linker.c | 73 +++++++++++++++++++++++------------ tools/qfcc/source/obj_file.c | 6 ++- tools/qfcc/source/reloc.c | 2 +- 7 files changed, 68 insertions(+), 28 deletions(-) diff --git a/tools/qfcc/include/defspace.h b/tools/qfcc/include/defspace.h index eea13bf71..1152bf5a5 100644 --- a/tools/qfcc/include/defspace.h +++ b/tools/qfcc/include/defspace.h @@ -56,6 +56,7 @@ typedef struct defspace_s { struct def_s *defs; ///< list of defs using this space struct def_s **def_tail; ///< for appending to \a defs pr_type_t *data; ///< backing memory for this space + int alignment; ///< minimum alignment of the whole space int size; ///< current high-water mark for alloced data int max_size; ///< size of backing memory, or highwater mark ///< for ds_virtual diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index d1bc0a268..4c4eee75d 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -91,7 +91,8 @@ typedef struct qfo_space_s { pr_uint_t data; ///< byte offset in qfo pr_uint_t data_size; ///< in elements. zero for entity spaces pr_uint_t id; - pr_int_t reserved[2]; + pr_uint_t alignment; ///< min alignment for space (1<size; pad = alignment * ((ofs + alignment - 1) / alignment) - ofs; + if (alignment > space->alignment) { + space->alignment = alignment; + } space->size += size + pad; if (space->size > space->max_size) { if (!space->grow || !space->grow (space)) @@ -263,7 +266,7 @@ defspace_add_data (defspace_t *space, pr_type_t *data, int size) { int loc; - loc = defspace_alloc_loc (space, size); + loc = defspace_alloc_highwater (space, size); if (data) memcpy (space->data + loc, data, size * sizeof (pr_type_t)); return loc; @@ -285,6 +288,9 @@ defspace_alloc_aligned_highwater (defspace_t *space, int size, int alignment) int ofs = space->size; int pad = alignment * ((ofs + alignment - 1) / alignment) - ofs; + if (alignment > space->alignment) { + space->alignment = alignment; + } space->size += size + pad; if (space->size > space->max_size) { if (!space->grow || !space->grow (space)) diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index cc34e79b6..e058f190d 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -559,6 +559,17 @@ add_code (qfo_mspace_t *code) work->spaces[qfo_code_space].data_size = work_code->size; } +static void +align_data (int space, qfo_mspace_t *data) +{ + if (space < 0 || space >= qfo_num_spaces || !work_spaces[space]) + linker_internal_error ("bad space for align_data (): %d", space); + defspace_alloc_aligned_highwater (*work_spaces[space], 0, + 1 << data->alignment); + work->spaces[space].data = (*work_spaces[space])->data; + work->spaces[space].data_size = (*work_spaces[space])->size; +} + /** Add the data in a data space to the working qfo. \param space The space to which the data will be added. @@ -603,6 +614,7 @@ add_data_space (qfo_t *qfo, qfo_mspace_t *space) } ws->data_size = space->data_size; ws->id = space->id; + ws->alignment = space->alignment; } static defref_t * @@ -765,18 +777,25 @@ process_code_space (qfo_t *qfo, qfo_mspace_t *space, int pass) static int process_data_space (qfo_t *qfo, qfo_mspace_t *space, int pass) { - if (pass != 1) - return 0; - if (space->id == qfo_near_data_space) { - add_defs (qfo, space, work->spaces + qfo_near_data_space, - process_data_def); - add_data (qfo_near_data_space, space); - } else if (space->id == qfo_far_data_space) { - add_defs (qfo, space, work->spaces + qfo_far_data_space, - process_data_def); - add_data (qfo_far_data_space, space); - } else { - add_data_space (qfo, space); + if (pass == 0) { + if (space->id == qfo_near_data_space) { + align_data (qfo_near_data_space, space); + } else if (space->id == qfo_far_data_space) { + align_data (qfo_far_data_space, space); + } else { + } + } else if (pass == 1) { + if (space->id == qfo_near_data_space) { + add_defs (qfo, space, work->spaces + qfo_near_data_space, + process_data_def); + add_data (qfo_near_data_space, space); + } else if (space->id == qfo_far_data_space) { + add_defs (qfo, space, work->spaces + qfo_far_data_space, + process_data_def); + add_data (qfo_far_data_space, space); + } else { + add_data_space (qfo, space); + } } return 0; } @@ -797,10 +816,12 @@ process_strings_space (qfo_t *qfo, qfo_mspace_t *space, int pass) static int process_entity_space (qfo_t *qfo, qfo_mspace_t *space, int pass) { - if (pass != 1) - return 0; - add_defs (qfo, space, work->spaces + qfo_entity_space, process_field_def); - add_data (qfo_entity_space, space); + if (pass == 0) { + align_data (qfo_entity_space, space); + } else if (pass == 1) { + add_defs (qfo, space, work->spaces + qfo_entity_space, process_field_def); + add_data (qfo_entity_space, space); + } return 0; } @@ -915,14 +936,16 @@ process_type_space (qfo_t *qfo, qfo_mspace_t *space, int pass) static int process_debug_space (qfo_t *qfo, qfo_mspace_t *space, int pass) { - if (pass != 1) - return 0; if (space->type != qfos_debug) { - linker_internal_error ("bad space type for add_data_space (): %d", + linker_internal_error ("bad space type for process_debug_space (): %d", space->type); } - add_defs (qfo, space, work->spaces + qfo_debug_space, process_data_def); - add_data (qfo_debug_space, space); + if (pass == 0) { + align_data (qfo_debug_space, space); + } else if (pass == 1) { + add_defs (qfo, space, work->spaces + qfo_debug_space, process_data_def); + add_data (qfo_debug_space, space); + } return 0; } @@ -1032,9 +1055,6 @@ linker_add_qfo (qfo_t *qfo) qfo_mspace_t *space; qfo_type_defs = 0; - for (i = 0; i < qfo_num_spaces; i++) { - work_base[i] = work->spaces[i].data_size; - } work_func_base = work->num_funcs; for (pass = 0; pass < 2; pass++) { for (i = 0, space = qfo->spaces; i < qfo->num_spaces; i++, space++) { @@ -1045,6 +1065,11 @@ linker_add_qfo (qfo_t *qfo) if (funcs[space->type] (qfo, space, pass)) return 1; } + for (i = 0; i < qfo_num_spaces; i++) { + if (pass == 0) { + work_base[i] = work->spaces[i].data_size; + } + } } process_funcs (qfo); process_lines (qfo); diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 997d4a9a5..c19520c46 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -237,6 +237,7 @@ qfo_init_data_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, memcpy (space->data, data->data, size); } space->data_size = data->size; + space->alignment = qfo_log2 (data->alignment); } static void @@ -250,6 +251,7 @@ qfo_init_entity_space (qfo_t *qfo, qfo_def_t **defs, qfo_reloc_t **relocs, space->data = 0; space->data_size = data->size; space->id = qfo_entity_space; + space->alignment = qfo_log2 (data->alignment); } static void @@ -501,6 +503,7 @@ qfo_write (qfo_t *qfo, const char *filename) } spaces[i].data_size = LittleLong (qfo->spaces[i].data_size); spaces[i].id = LittleLong (qfo->spaces[i].id); + spaces[i].alignment = LittleLong (qfo->spaces[i].alignment); } for (i = 0; i < qfo->num_relocs; i++) { relocs[i].space = LittleLong (qfo->relocs[i].space); @@ -608,6 +611,7 @@ qfo_read (QFile *file) qfo->spaces[i].data_size, qfo->spaces[i].type); } qfo->spaces[i].id = LittleLong (spaces[i].id); + qfo->spaces[i].alignment = LittleLong (spaces[i].alignment); } for (i = 0; i < qfo->num_relocs; i++) { qfo->relocs[i].space = LittleLong (qfo->relocs[i].space); @@ -1041,7 +1045,7 @@ qfo_to_progs (qfo_t *in_qfo, int *size) // these are in order in which they usually appear in the file rather // than the order they appear in the struct, though with the offsets // it doesn't matter too much. However, as people expect a certain - // layout, ti does matter enough to preserve the traditional file order. + // layout, it does matter enough to preserve the traditional file order. progs->strings.offset = *size; progs->strings.count = qfo->spaces[qfo_strings_space].data_size; diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 674be505f..252b8e404 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -53,7 +53,7 @@ static reloc_t *refs_freelist; -static const char *reloc_name[] = { +const char * const reloc_name[] = { "rel_none", "rel_op_a_def", "rel_op_b_def", From 6253d775e65129cc0b82d5c953f4947ecd0dd90e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 31 Jul 2022 16:56:18 +0900 Subject: [PATCH 2917/3664] [qfcc] Adjust ivar offsets to preserve alignment As a class's ivars are built up by inheritance, but with only that class's ivars in the symbol table, is is necessary to include an offset based on the super class's ivars in order to ensure alignments are respected. This is achieved via the new `base` parameter to build_struct(), which is used to offset the current size while calculating the aligned offset of the symbols. The parameter is ignored for unions, as they always start at 0. The ivars for the current class still have a base offset of 0 until they are actually added to the class. Fixes #29 --- tools/qfcc/include/struct.h | 3 ++- tools/qfcc/source/qc-parse.y | 8 ++++++-- tools/qfcc/source/struct.c | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/include/struct.h b/tools/qfcc/include/struct.h index 4438ec600..54cf1b045 100644 --- a/tools/qfcc/include/struct.h +++ b/tools/qfcc/include/struct.h @@ -46,7 +46,8 @@ typedef struct { struct symbol_s *find_struct (int su, struct symbol_s *tag, struct type_s *type); struct symbol_s *build_struct (int su, struct symbol_s *tag, - struct symtab_s *symtab, struct type_s *type); + struct symtab_s *symtab, struct type_s *type, + int base); struct symbol_s *find_enum (struct symbol_s *tag); struct symtab_s *start_enum (struct symbol_s *enm); struct symbol_s *finish_enum (struct symbol_s *sym); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 5355a7981..1bab1798b 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -846,7 +846,7 @@ struct_specifier current_symtab = symtab->parent; if ($1) { - sym = build_struct ($1, $2, symtab, 0); + sym = build_struct ($1, $2, symtab, 0, 0); $$ = make_spec (sym->type, 0, 0, 0); if (!sym->table) symtab_addsymbol (current_symtab, sym); @@ -2051,7 +2051,11 @@ ivar_decl_list tab->parent = 0; tab = $$->parent; // preserve the ivars inheritance chain - build_struct ('s', 0, $$, 0); + int base = 0; + if ($0->super_class) { + base = type_size ($0->super_class->type); + } + build_struct ('s', 0, $$, 0, base); $$->parent = tab; current_visibility = vis_public; } diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 318efb420..db5b05352 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -110,7 +110,7 @@ find_struct (int su, symbol_t *tag, type_t *type) } symbol_t * -build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) +build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type, int base) { symbol_t *sym = find_struct (su, tag, type); symbol_t *s; @@ -131,7 +131,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type) s->type->t.class->name); } if (su == 's') { - symtab->size = RUP (symtab->size, s->type->alignment); + symtab->size = RUP (symtab->size + base, s->type->alignment) - base; s->s.offset = symtab->size; symtab->size += type_size (s->type); } else { @@ -304,7 +304,7 @@ make_structure (const char *name, int su, struct_def_t *defs, type_t *type) internal_error (0, "duplicate symbol: %s", defs->name); defs++; } - sym = build_struct (su, sym, strct, type); + sym = build_struct (su, sym, strct, type, 0); return sym; } From 0897952a579f2119415dde6c702336a79f398ee1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 31 Jul 2022 17:34:09 +0900 Subject: [PATCH 2918/3664] Fix windows compile issues ulong seems to be defined somewhere on Linux, thus I missed that, and of course there's the fun with aligned memory allocation :/ --- libs/gamecode/convert.py | 2 +- tools/qfcc/source/value.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/gamecode/convert.py b/libs/gamecode/convert.py index ce3637c7c..b148eb1c2 100644 --- a/libs/gamecode/convert.py +++ b/libs/gamecode/convert.py @@ -110,7 +110,7 @@ for width in range(4): elif width == 2: print(f"{case} VectorCompUop(&{dst},{cast},&{src}); break;") else: - expand = expand_str(width, src, f"({types[dst_type]})") + expand = expand_str(width, src, f"(pr_{types[dst_type]}_t)") print(f"{case} {dst} = {cast} {expand}; break;") elif mode == 2: one = one_str(width, src_type) diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 59de51d21..54972f4d0 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -59,6 +59,12 @@ #include "tools/qfcc/include/type.h" #include "tools/qfcc/include/value.h" +//FIXME I don't like this being here (or aligned_alloc being necessary in +//the first place, but not at all sure what to do about that) +#ifdef _WIN32 +#define aligned_alloc(al, sz) _aligned_malloc(sz, al) +#endif + typedef struct { def_t *def; union { From 42287f1e0ef5985f4880fb419b79eb76867bfa61 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 17 Aug 2022 16:03:51 +0900 Subject: [PATCH 2919/3664] [qfcc] Allow binary operations between vector and vec3 While I might need to tighten up the rules later, this allows binary operations between vector (the type) and explicitly typed vec3 constants (and non-constants, about which I am undecided). The idea is that explicit constants such as '1 2 3'f should be compatible with either type. This applies to quaternions as well. --- tools/qfcc/source/expr_binary.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 1c0429d09..d8888dc7f 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -1094,6 +1094,12 @@ binary_expr (int op, expr_t *e1, expr_t *e2) e2 = cast_expr (t1, e2); } else if (type_promotes (base_type (t2), base_type (t1))) { e1 = cast_expr (t2, e1); + } else if (base_type (t1) == base_type (t2)) { + if (is_vector (t1) || is_quaternion (t1)) { + e2 = cast_expr (t1, e2); + } else if (is_vector (t2) || is_quaternion (t2)) { + e1 = cast_expr (t2, e1); + } } else { debug (e1, "%d %d\n", e1->implicit, e2->implicit); return invalid_binary_expr (op, e1, e2); From 59b73353dd78f6f1a17365c58d368d1059e6eeb3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 17 Aug 2022 16:23:33 +0900 Subject: [PATCH 2920/3664] [qfcc] Fix integer vector constants for clang It seems clang loses track of the usage of the referenced unions by the time the code leaves the switch. Due to the misoptimization, "random" values would get into the vector constants. This puts the usages in the same blocks as the unions, causing clang to "get it right" (though I strongly suspect I was running into UB). --- tools/qfcc/source/qc-lex.l | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index beaba7b4f..9f0a9fee6 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -587,13 +587,16 @@ parse_int_vector (const char *token, int width) } t1 = tolower (t1); t2 = tolower (t2); + expr_t *expr = 0; switch (t1) { case 'u': if (t2 == 'l') { type = &type_ulong; + type = vector_type (type, width); + expr = new_value_expr (new_type_value (type, data)); } else { type = &type_uint; - volatile union { + union { pr_uint_t u[4]; pr_type_t t[PR_SIZEOF (ivec4)]; } uint_data = { @@ -604,15 +607,19 @@ parse_int_vector (const char *token, int width) long_data.l[3], } }; - data = (pr_type_t *) uint_data.t; + data = uint_data.t; + type = vector_type (type, width); + expr = new_value_expr (new_type_value (type, data)); } break; case 'l': type = &type_long; + type = vector_type (type, width); + expr = new_value_expr (new_type_value (type, data)); break; case 'f': type = &type_float; - volatile union { + union { pr_float_t f[4]; pr_type_t t[PR_SIZEOF (vec4)]; } float_data = { @@ -623,11 +630,13 @@ parse_int_vector (const char *token, int width) long_data.l[3], } }; - data = (pr_type_t *) float_data.t; + data = float_data.t; + type = vector_type (type, width); + expr = new_value_expr (new_type_value (type, data)); break; case 'd': type = &type_double; - volatile union { + union { pr_double_t d[4]; pr_type_t t[PR_SIZEOF (dvec4)]; } double_data = { @@ -638,11 +647,13 @@ parse_int_vector (const char *token, int width) long_data.l[3], } }; - data = (pr_type_t *) double_data.t; + data = double_data.t; + type = vector_type (type, width); + expr = new_value_expr (new_type_value (type, data)); break; case 0: type = &type_int; - volatile union { + union { pr_int_t i[4]; pr_type_t t[PR_SIZEOF (ivec4)]; } int_data = { @@ -653,11 +664,11 @@ parse_int_vector (const char *token, int width) long_data.l[3], } }; - data = (pr_type_t *) int_data.t; + data = int_data.t; + type = vector_type (type, width); + expr = new_value_expr (new_type_value (type, data)); break; } - type = vector_type (type, width); - expr_t *expr = new_value_expr (new_type_value (type, data)); expr->implicit = !t1; return expr; } From d9d0a80752f1150833f0e4d9f66b9216422f5d55 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Aug 2022 14:48:53 +0900 Subject: [PATCH 2921/3664] [gamecode] Add an extend instruction The extend instruction is for loading narrower data types into wider data types, eg, single element into 2, 3, or 4 element types, with a small set of extension schemes: 0, 1, -1, copy (for 1->any and 2 -> 4). Possibly most importantly, it works with unaligned data. Progress towards #30 --- libs/gamecode/Makemodule.am | 16 ++- libs/gamecode/extend.py | 77 +++++++++++ libs/gamecode/opcodes.py | 11 +- libs/gamecode/pr_exec.c | 11 +- libs/gamecode/test/Makemodule.am | 6 + libs/gamecode/test/test-extend.c | 223 +++++++++++++++++++++++++++++++ 6 files changed, 339 insertions(+), 5 deletions(-) create mode 100644 libs/gamecode/extend.py create mode 100644 libs/gamecode/test/test-extend.c diff --git a/libs/gamecode/Makemodule.am b/libs/gamecode/Makemodule.am index b3d26d62f..748fdb635 100644 --- a/libs/gamecode/Makemodule.am +++ b/libs/gamecode/Makemodule.am @@ -21,7 +21,12 @@ libs_gamecode_libQFgamecode_la_SOURCES= \ libs/gamecode/pr_v6p_opcode.c \ libs/gamecode/pr_zone.c -noinst_PYTHON += $(opcodes_py) $(convert_py) $(hops_py) $(swizzle_py) +noinst_PYTHON += \ + $(opcodes_py) \ + $(convert_py) \ + ${extend_py} \ + $(hops_py) \ + $(swizzle_py) opcodes_py = $(srcdir)/libs/gamecode/opcodes.py pr_opcode_cinc = $(top_builddir)/libs/gamecode/pr_opcode.cinc @@ -34,6 +39,9 @@ libs/gamecode/pr_opcode.lo: libs/gamecode/pr_opcode.c ${pr_opcode_src} convert_py = $(srcdir)/libs/gamecode/convert.py pr_convert_cinc = $(top_builddir)/libs/gamecode/pr_convert.cinc +extend_py = $(srcdir)/libs/gamecode/extend.py +pr_extend_cinc = $(top_builddir)/libs/gamecode/pr_extend.cinc + hops_py = $(srcdir)/libs/gamecode/hops.py pr_hops_cinc = $(top_builddir)/libs/gamecode/pr_hops.cinc @@ -45,6 +53,7 @@ BUILT_SOURCES += \ $(pr_opcode_cinc) \ $(pr_opcode_hinc) \ $(pr_convert_cinc) \ + $(pr_extend_cinc) \ $(pr_hops_cinc) \ $(pr_swizzle32_cinc) \ $(pr_swizzle64_cinc) @@ -53,6 +62,7 @@ CLEANFILES += \ $(pr_opcode_cinc) \ $(pr_opcode_hinc) \ $(pr_convert_cinc) \ + $(pr_extend_cinc) \ $(pr_hops_cinc) \ $(pr_swizzle32_cinc) \ $(pr_swizzle64_cinc) @@ -70,6 +80,10 @@ $(pr_convert_cinc): $(convert_py) $(V_PY)$(PYTHON) $(convert_py) table > $(pr_convert_cinc).t && \ $(am__mv) $(pr_convert_cinc).t $(pr_convert_cinc) +$(pr_extend_cinc): $(extend_py) + $(V_PY)$(PYTHON) $(extend_py) table > $(pr_extend_cinc).t && \ + $(am__mv) $(pr_extend_cinc).t $(pr_extend_cinc) + $(pr_hops_cinc): $(hops_py) $(V_PY)$(PYTHON) $(hops_py) table > $(pr_hops_cinc).t && \ $(am__mv) $(pr_hops_cinc).t $(pr_hops_cinc) diff --git a/libs/gamecode/extend.py b/libs/gamecode/extend.py new file mode 100644 index 000000000..99aa9ed81 --- /dev/null +++ b/libs/gamecode/extend.py @@ -0,0 +1,77 @@ +print("""// encoding is teemmm +// t = 0: 32-bit, t = 1: 64-bit +// e = 00: 0 +// e = 01: 1.0 +// e = 10: copy (1-n, 2-4, otherwise 0) +// e = 11: -1.0 +// mmm = 000: 1 -> 2 +// mmm = 001: 1 -> 3 +// mmm = 010: 1 -> 4 +// mmm = 011: 2 -> 3 +// mmm = 100: 2 -> 4 +// mmm = 101: 3 -> 4 +// mmm = 110: reserved +// mmm = 111: reserved +""") + +types = [ + ["ivec2", "ivec3", "ivec4", "ivec3", "ivec4", "ivec4"], + ["lvec2", "lvec3", "lvec4", "lvec3", "lvec4", "lvec4"], +] + +src_types = [ + ["int", "int", "int", "ivec2", "ivec2", "ivec3"], + ["long", "long", "long", "lvec2", "lvec2", "lvec3"], +] + +extend = [ + ["0", "INT32_C(0x3f800000)", "0", "INT32_C(0xbf800000)"], + ["0", "INT64_C(0x3ff0000000000000)", "0", "INT64_C(0xbff0000000000000)"], +] + +def case_str(type, ext, mode): + case = (type << 5) | (ext << 3) | (mode) + return f"case {case:03o}:" + +def dst_str(type, ext, mode): + return f"OPC({types[type][mode]})" + +def cast_str(type, ext, mode): + return f"(pr_{types[type][mode]}_t)" + +def init_str(type, ext, mode): + ext_str = extend[type][ext] + src = f"OPA({src_types[type][mode]})" + if mode == 0: + if ext == 2: + ext_str = src + return f"{src}, {ext_str}" + elif mode == 1: + if ext == 2: + ext_str = src + return f"{src}, {ext_str}, {ext_str}" + elif mode == 2: + if ext == 2: + ext_str = src + return f"{src}, {ext_str}, {ext_str}, {ext_str}" + elif mode == 3: + return f"{src}[0], {src}[1], {ext_str}" + elif mode == 4: + if ext == 2: + return f"{src}[0], {src}[1], {src}[0], {src}[1]" + else: + return f"{src}[0], {src}[1], {ext_str}, {ext_str}" + elif mode == 5: + return f"{src}[0], {src}[1], {src}[2], {ext_str}" + +for type in range(2): + for ext in range(4): + for mode in range(6): # 6, 7 are reserved + case = case_str(type, ext, mode) + dst = dst_str(type, ext, mode) + cast = cast_str(type, ext, mode) + init = init_str(type, ext, mode) + if mode in [1, 3]: + print(f"{case} VectorSet({init}, {dst}); break;"); + else: + print(f"{case} {dst} = {cast} {{ {init} }}; break;"); diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 4ec39a71f..79e1949d9 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -34,7 +34,7 @@ bitmap_txt = """ 1 1111 10oo fbitops 1 1111 1100 convert (conversion mode in st->b) 1 1111 1101 with (mode in st->a, value in st->b, reg in st->c) -1 1111 1110 +1 1111 1110 extend 1 1111 1111 hops """ @@ -204,6 +204,14 @@ fbitops_formats = { ], }, } +extend_formats = { + "opcode": "OP_EXTEND", + "mnemonic": "extend", + "opname": "extend", + "format": "%Ga %Hb %gc", + "widths": "-1, 0, -1", + "types": "ev_void, ev_short, ev_void", +} hops_formats = { "opcode": "OP_HOPS", "mnemonic": "hops", @@ -566,6 +574,7 @@ group_map = { "compare2": compare2_formats, "constant": constant_formats, "convert": convert_formats, + "extend": extend_formats, "fbitops": fbitops_formats, "hops": hops_formats, "jump": jump_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index e8c4f2551..cab230ad6 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -2835,7 +2835,13 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) case OP_WITH: pr_with (pr, st); break; - // 1110 spare + case OP_EXTEND: + switch (st->b) { +#include "libs/gamecode/pr_extend.cinc" + default: + PR_RunError (pr, "invalid extend code: %04o", st->b); + } + break; #define OP_hop2(vec, op) ((vec)[0] op (vec)[1]) #define OP_hop3(vec, op) ((vec)[0] op (vec)[1] op (vec)[2]) #define OP_hop4(vec, op) ((vec)[0] op (vec)[1] op (vec)[2] op (vec)[3]) @@ -2843,8 +2849,7 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) switch (st->b) { #include "libs/gamecode/pr_hops.cinc" default: - PR_RunError (pr, "invalid hops code: %04o", - st->b); + PR_RunError (pr, "invalid hops code: %04o", st->b); } break; default: diff --git a/libs/gamecode/test/Makemodule.am b/libs/gamecode/test/Makemodule.am index 2cfd9fbf9..dfccd91ae 100644 --- a/libs/gamecode/test/Makemodule.am +++ b/libs/gamecode/test/Makemodule.am @@ -11,6 +11,7 @@ libs_gamecode_tests = \ libs/gamecode/test/test-conv6 \ libs/gamecode/test/test-conv7 \ libs/gamecode/test/test-double \ + libs/gamecode/test/test-extend \ libs/gamecode/test/test-float \ libs/gamecode/test/test-hops \ libs/gamecode/test/test-int \ @@ -101,6 +102,11 @@ libs_gamecode_test_test_double_SOURCES= \ libs_gamecode_test_test_double_LDADD= $(test_gamecode_libs) libs_gamecode_test_test_double_DEPENDENCIES=$(test_gamecode_libs) +libs_gamecode_test_test_extend_SOURCES= \ + libs/gamecode/test/test-extend.c +libs_gamecode_test_test_extend_LDADD= $(test_gamecode_libs) +libs_gamecode_test_test_extend_DEPENDENCIES= $(test_gamecode_libs) + libs_gamecode_test_test_float_SOURCES= \ libs/gamecode/test/test-float.c libs_gamecode_test_test_float_LDADD= $(test_gamecode_libs) diff --git a/libs/gamecode/test/test-extend.c b/libs/gamecode/test/test-extend.c new file mode 100644 index 000000000..bd05ab394 --- /dev/null +++ b/libs/gamecode/test/test-extend.c @@ -0,0 +1,223 @@ +#include "head.c" + +#include "QF/mathlib.h" + +#define _ -6.259853398707798e+18 // 0xdeadbeef + +static pr_vec4_t float_extend_init[] = { + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { 2, 3, 4, 5 }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, +}; + +static pr_vec4_t float_extend_expect[] = { + { 5, 0, _, _ }, + { 4, 0, 0, _ }, + { 3, 0, 0, 0 }, + { 4, 5, 0, _ }, + { 2, 3, 0, 0 }, + { 3, 4, 5, 0 }, + { 2, 3, 4, 5 }, + { _, _, 4, 1 }, + { _, 3, 1, 1 }, + { 2, 1, 1, 1 }, + { _, 4, 5, 1 }, + { 2, 3, 1, 1 }, + { 2, 3, 4, 1 }, + { _, _, _, _ }, + { 5, 5, _, _ }, + { 4, 4, 4, _ }, + { 3, 3, 3, 3 }, + { 4, 5, 0, _ }, + { 2, 3, 2, 3 }, + { 3, 4, 5, 0 }, + { _, _, _, _ }, + { _, _, 4, -1 }, + { _, 3, -1, -1 }, + { 2, -1, -1, -1 }, + { _, 4, 5, -1 }, + { 2, 3, -1, -1 }, + { 2, 3, 4, -1 }, + { _, _, _, _ }, +}; + +static dstatement_t float_extend_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 0, 28, 1 }, + { OP(0, 0, 0, OP_WITH), 0, 56, 2 }, + { OP(0, 0, 0, OP_WITH), 0, 84, 3 }, + + { OP(0, 0, 0, OP_EXTEND), 27, 000, 0 }, + { OP(0, 0, 0, OP_EXTEND), 26, 001, 4 }, + { OP(0, 0, 0, OP_EXTEND), 25, 002, 8 }, + { OP(0, 0, 0, OP_EXTEND), 26, 003, 12 }, + { OP(0, 0, 0, OP_EXTEND), 24, 004, 16 }, + { OP(0, 0, 0, OP_EXTEND), 25, 005, 20 }, + + { OP(0, 0, 1, OP_EXTEND), 26, 010, 2 }, + { OP(0, 0, 1, OP_EXTEND), 25, 011, 5 }, + { OP(0, 0, 1, OP_EXTEND), 24, 012, 8 }, + { OP(0, 0, 1, OP_EXTEND), 26, 013, 13 }, + { OP(0, 0, 1, OP_EXTEND), 24, 014, 16 }, + { OP(0, 0, 1, OP_EXTEND), 24, 015, 20 }, + + { OP(0, 0, 2, OP_EXTEND), 27, 020, 0 }, + { OP(0, 0, 2, OP_EXTEND), 26, 021, 4 }, + { OP(0, 0, 2, OP_EXTEND), 25, 022, 8 }, + { OP(0, 0, 2, OP_EXTEND), 26, 023, 12 }, + { OP(0, 0, 2, OP_EXTEND), 24, 024, 16 }, + { OP(0, 0, 2, OP_EXTEND), 25, 025, 20 }, + + { OP(0, 0, 3, OP_EXTEND), 26, 030, 2 }, + { OP(0, 0, 3, OP_EXTEND), 25, 031, 5 }, + { OP(0, 0, 3, OP_EXTEND), 24, 032, 8 }, + { OP(0, 0, 3, OP_EXTEND), 26, 033, 13 }, + { OP(0, 0, 3, OP_EXTEND), 24, 034, 16 }, + { OP(0, 0, 3, OP_EXTEND), 24, 035, 20 }, +}; + +#undef _ +#define _ -1.1885959257070704e+148 // 0xdeadbeefdeadbeef + +static pr_dvec4_t double_extend_init[] = { + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { 2, 3, 4, 5 }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, + { _, _, _, _ }, +}; + +static pr_dvec4_t double_extend_expect[] = { + { 5, 0, _, _ }, + { 4, 0, 0, _ }, + { 3, 0, 0, 0 }, + { 4, 5, 0, _ }, + { 2, 3, 0, 0 }, + { 3, 4, 5, 0 }, + { 2, 3, 4, 5 }, + { _, _, 4, 1 }, + { _, 3, 1, 1 }, + { 2, 1, 1, 1 }, + { _, 4, 5, 1 }, + { 2, 3, 1, 1 }, + { 2, 3, 4, 1 }, + { _, _, _, _ }, + { 5, 5, _, _ }, + { 4, 4, 4, _ }, + { 3, 3, 3, 3 }, + { 4, 5, 0, _ }, + { 2, 3, 2, 3 }, + { 3, 4, 5, 0 }, + { _, _, _, _ }, + { _, _, 4, -1 }, + { _, 3, -1, -1 }, + { 2, -1, -1, -1 }, + { _, 4, 5, -1 }, + { 2, 3, -1, -1 }, + { 2, 3, 4, -1 }, + { _, _, _, _ }, +}; + +static dstatement_t double_extend_statements[] = { + { OP(0, 0, 0, OP_WITH), 0, 0, 0 }, + { OP(0, 0, 0, OP_WITH), 0, 56, 1 }, + { OP(0, 0, 0, OP_WITH), 0, 112, 2 }, + { OP(0, 0, 0, OP_WITH), 0, 168, 3 }, + + { OP(0, 0, 0, OP_EXTEND), 54, 040, 0 }, + { OP(0, 0, 0, OP_EXTEND), 52, 041, 8 }, + { OP(0, 0, 0, OP_EXTEND), 50, 042, 16 }, + { OP(0, 0, 0, OP_EXTEND), 52, 043, 24 }, + { OP(0, 0, 0, OP_EXTEND), 48, 044, 32 }, + { OP(0, 0, 0, OP_EXTEND), 50, 045, 40 }, + + { OP(0, 0, 1, OP_EXTEND), 52, 050, 4 }, + { OP(0, 0, 1, OP_EXTEND), 50, 051, 10 }, + { OP(0, 0, 1, OP_EXTEND), 48, 052, 16 }, + { OP(0, 0, 1, OP_EXTEND), 52, 053, 26 }, + { OP(0, 0, 1, OP_EXTEND), 48, 054, 32 }, + { OP(0, 0, 1, OP_EXTEND), 48, 055, 40 }, + + { OP(0, 0, 2, OP_EXTEND), 54, 060, 0 }, + { OP(0, 0, 2, OP_EXTEND), 52, 061, 8 }, + { OP(0, 0, 2, OP_EXTEND), 50, 062, 16 }, + { OP(0, 0, 2, OP_EXTEND), 52, 063, 24 }, + { OP(0, 0, 2, OP_EXTEND), 48, 064, 32 }, + { OP(0, 0, 2, OP_EXTEND), 50, 065, 40 }, + + { OP(0, 0, 3, OP_EXTEND), 52, 070, 4 }, + { OP(0, 0, 3, OP_EXTEND), 50, 071, 10 }, + { OP(0, 0, 3, OP_EXTEND), 48, 072, 16 }, + { OP(0, 0, 3, OP_EXTEND), 52, 073, 26 }, + { OP(0, 0, 3, OP_EXTEND), 48, 074, 32 }, + { OP(0, 0, 3, OP_EXTEND), 48, 075, 40 }, +}; + +test_t tests[] = { + { + .desc = "float extend", + .num_globals = num_globals(float_extend_init,float_extend_expect), + .num_statements = num_statements (float_extend_statements), + .statements = float_extend_statements, + .init_globals = (pr_int_t *) float_extend_init, + .expect_globals = (pr_int_t *) float_extend_expect, + }, + { + .desc = "double extend", + .num_globals = num_globals(double_extend_init,double_extend_expect), + .num_statements = num_statements (double_extend_statements), + .statements = double_extend_statements, + .init_globals = (pr_int_t *) double_extend_init, + .expect_globals = (pr_int_t *) double_extend_expect, + }, +}; + +#include "main.c" From 95b8424ddfd10bc353aa31bd3efa52746e766758 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Aug 2022 17:46:14 +0900 Subject: [PATCH 2922/3664] [qfcc] Use new extend instruction instead of swizzle While swizzle does work, it requires the source to be properly aligned and thus is not really the best choice. The extend instruction has no alignment requirements (at all) and thus is much better suited to converting a scalar to a vector type. Fixes #30 --- tools/qfcc/include/expr.h | 9 +++++++++ tools/qfcc/include/expr_names.h | 1 + tools/qfcc/source/expr.c | 23 +++++++++++++++++++++ tools/qfcc/source/expr_assign.c | 1 + tools/qfcc/source/expr_binary.c | 9 +-------- tools/qfcc/source/statements.c | 36 +++++++++++++++++++++++++++++++++ 6 files changed, 71 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index b9534086e..43dc6a255 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -269,6 +269,12 @@ typedef struct { struct type_s *type; ///< result type } ex_swizzle_t; +typedef struct { + struct expr_s *src; ///< source expression + int extend; ///< extend mode 0: 0, 1: 1, 2: copy/0 3:-1 + struct type_s *type; ///< result type; +} ex_extend_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -305,6 +311,7 @@ typedef struct expr_s { struct type_s *nil; ///< type for nil if known ex_horizontal_t hop; ///< horizontal vector operation ex_swizzle_t swizzle; ///< vector swizzle operation + ex_extend_t extend; ///< vector extend operation } e; } expr_t; @@ -494,6 +501,8 @@ expr_t *new_horizontal_expr (int op, expr_t *vec, struct type_s *type); expr_t *new_swizzle_expr (expr_t *src, const char *swizzle); +expr_t *new_extend_expr (expr_t *src, struct type_s *type, int ext); + /** Create a new def reference (non-temporary variable) expression node. \return The new def reference expression node (::def_t). diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index 8c6db70b6..978684073 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -64,5 +64,6 @@ EX_EXPR(with) ///< with expression (::ex_with_t) EX_EXPR(args) ///< @args marker in parameter list. no data EX_EXPR(horizontal) ///< horizontal vector operation (::ex_horzontal_t) EX_EXPR(swizzle) ///< vector swizzle operation (::ex_swizzle_t) +EX_EXPR(extend) ///< vector extend operation (::ex_extend_t) ///@} diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 595eb1e87..b112d7296 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -197,6 +197,8 @@ get_type (expr_t *e) return e->e.hop.type; case ex_swizzle: return e->e.swizzle.type; + case ex_extend: + return e->e.extend.type; case ex_count: internal_error (e, "invalid expression"); } @@ -432,6 +434,11 @@ copy_expr (expr_t *e) *n = *e; e->e.swizzle.src = copy_expr (e->e.swizzle.src); return n; + case ex_extend: + n = new_expr (); + *n = *e; + e->e.extend.src = copy_expr (e->e.extend.src); + return n; case ex_count: break; } @@ -686,6 +693,17 @@ new_swizzle_expr (expr_t *src, const char *swizzle) return expr; } +expr_t * +new_extend_expr (expr_t *src, type_t *type, int ext) +{ + expr_t *expr = new_expr (); + expr->type = ex_extend; + expr->e.extend.src = src; + expr->e.extend.extend = ext; + expr->e.extend.type = type; + return expr; +} + expr_t * new_def_expr (def_t *def) { @@ -1624,6 +1642,8 @@ has_function_call (expr_t *e) return has_function_call (e->e.hop.vec); case ex_swizzle: return has_function_call (e->e.swizzle.src); + case ex_extend: + return has_function_call (e->e.extend.src); case ex_error: case ex_state: case ex_label: @@ -1770,6 +1790,7 @@ unary_expr (int op, expr_t *e) case ex_assign: case ex_horizontal: case ex_swizzle: + case ex_extend: { expr_t *n = new_unary_expr (op, e); @@ -1864,6 +1885,7 @@ unary_expr (int op, expr_t *e) case ex_assign: case ex_horizontal: case ex_swizzle: + case ex_extend: if (options.code.progsversion == PROG_VERSION) { return binary_expr (EQ, e, new_nil_expr ()); } else { @@ -1954,6 +1976,7 @@ unary_expr (int op, expr_t *e) case ex_assign: case ex_horizontal: case ex_swizzle: + case ex_extend: bitnot_expr: if (options.code.progsversion == PROG_ID_VERSION) { expr_t *n1 = new_int_expr (-1); diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index b04a98b36..b1a8c3e5a 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -143,6 +143,7 @@ is_lvalue (const expr_t *expr) case ex_args: case ex_horizontal: case ex_swizzle: + case ex_extend: break; case ex_count: internal_error (expr, "invalid expression"); diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index d8888dc7f..f01e165b2 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -667,14 +667,7 @@ convert_scalar (expr_t *scalar, int op, expr_t *vec) return new_vector_list (scalar); } - char swizzle[] = "xxxx"; - type_t *vec_base = base_type (vec_type); - expr_t *tmp = new_temp_def_expr (vector_type (vec_base, 4)); - expr_t *block = new_block_expr (); - swizzle[type_width (vec_type)] = 0; - append_expr (block, assign_expr (tmp, new_swizzle_expr (scalar, swizzle))); - block->e.block.result = new_alias_expr (vec_type, tmp); - return block; + return new_extend_expr (scalar, vec_type, 2);//2 = copy } static expr_t * diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 190464202..ec011d1e4 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1810,6 +1810,41 @@ expr_swizzle (sblock_t *sblock, expr_t *e, operand_t **op) return sblock; } +static sblock_t * +expr_extend (sblock_t *sblock, expr_t *e, operand_t **op) +{ + type_t *src_type = get_type (e->e.extend.src); + type_t *res_type = e->e.extend.type; + int src_width = type_width (src_type); + int res_width = type_width (res_type); + type_t *src_base = base_type (src_type); + type_t *res_base = base_type (res_type); + static int mode[4][4] = { + {-1, 0, 1, 2}, + {-1,-1, 3, 4}, + {-1,-1,-1, 5}, + {-1,-1,-1,-1}, + }; + int ext = mode[src_width - 1][res_width - 1]; + ext |= (e->e.extend.extend & 3) << 3; + ext |= (pr_type_size[res_base->type] - 1) << 5; + if (ext < 0 || res_base != src_base) { + internal_error (e, "invalid type combination for extend %d %d %d", + ext, src_width, res_width); + } + + statement_t *s = new_statement (st_expr, "extend", e); + sblock = statement_subexpr (sblock, e->e.extend.src, &s->opa); + s->opb = short_operand (ext, e); + if (!*op) { + *op = temp_operand (res_type, e); + } + s->opc = *op; + sblock_add_statement (sblock, s); + + return sblock; +} + static sblock_t * expr_def (sblock_t *sblock, expr_t *e, operand_t **op) { @@ -1954,6 +1989,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op) [ex_address] = expr_address, [ex_assign] = expr_assign, [ex_branch] = expr_branch, + [ex_extend] = expr_extend, }; if (!e) { *op = 0; From 1e54799f69c4f20d6a5ecbfeeeb115716b73cbcc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 Aug 2022 18:13:39 +0900 Subject: [PATCH 2923/3664] [gamecode] Take care of failing uint conversion tests By not doing the unrepresentable conversions, since they seem to be undefined behavior and even gcc 12 is inconsistent with them --- libs/gamecode/test/test-conv4.c | 12 ++++++++---- libs/gamecode/test/test-conv6.c | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c index 3fb1b8d47..35cc00979 100644 --- a/libs/gamecode/test/test-conv4.c +++ b/libs/gamecode/test/test-conv4.c @@ -4,10 +4,12 @@ static pr_ivec4_t uint_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 0x3fc00000, 0xbfc00000, 0, 0}, //float { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0, 0, 0}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 @@ -35,10 +37,12 @@ static pr_ivec4_t uint_conv_init[] = { */ static pr_ivec4_t uint_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 0x3fc00000, 0xbfc00000, 0, 0}, //float { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0, 0, 0}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c index 76bb018ed..72f1c6b9f 100644 --- a/libs/gamecode/test/test-conv6.c +++ b/libs/gamecode/test/test-conv6.c @@ -4,10 +4,12 @@ static pr_ivec4_t ulong_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 0x3fc00000, 0xbfc00000, 0, 0}, //float 1e30, -1e30 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0, 0, 0}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 @@ -41,10 +43,12 @@ static pr_ivec4_t ulong_conv_init[] = { */ static pr_ivec4_t ulong_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 0x3fc00000, 0xbfc00000, 0, 0}, //float 1e30, -1e30 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 + { 0, 0, 0, 0}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 @@ -55,10 +59,12 @@ static pr_ivec4_t ulong_conv_expect[] = { { 5, 0, -5, 0xffffffff}, // int { 0x80000000, 0xffffffff, 0x7fffffff, 0}, { 1, 0, -1, -1}, // float - { 0, 0, 0, 0x80000000}, // undef? + //XXX{ 0, 0, 0, 0x80000000}, // undef? + { 0, 0, 0, 0}, // undef? { 99, 0x80000000, 0x80000000, 99}, // long { 256, 0, 0x7fffffff, 0}, - { 0, 0, 0, 0x80000000}, // double undef? + //XXX{ 0, 0, 0, 0x80000000}, // double undef? + { 0, 0, 0, 0}, // double undef? { 1, 0, -1, -1}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, From f611b0d5a106ef349a9f9b8c0033a5442f2a1124 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Aug 2022 20:14:02 +0900 Subject: [PATCH 2924/3664] [client] Preserve intensity when parsing light color Due to the mis-initialization of the union used to parse the color vector, the intensity was incorrectly set to zero and thus the light dropped, meaning that all lights in ad_tears were lost. --- libs/client/cl_light.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index fd8831783..83c8fa53b 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -201,7 +201,7 @@ parse_light (light_t *light, int *style, const plitem_t *entity, union { float a[4]; vec4f_t v; - } color = {}; + } color = { .v = light->color }; sscanf (str, "%f %f %f", VectorExpandAddr (color.a)); light->color = color.v; VectorScale (light->color, 1/255.0, light->color); From 630dde6df7dc879ab3bcf946b5d624113455f517 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 May 2022 18:14:26 +0900 Subject: [PATCH 2925/3664] [render] Add basic 2d line drawing The software renderer uses Bresenham's line slice algorithm as presented by Michael Abrash in his Graphics Programming Black Book Special Edition with the serial numbers filed off (as such, more just so *I* can read the code easily), along with the Chen-Sutherland line clipping algorithm. The other renderers were more or less trivial in comparison. --- include/QF/GL/qf_draw.h | 1 + include/QF/GLSL/qf_draw.h | 1 + include/QF/Vulkan/qf_draw.h | 2 + include/QF/draw.h | 11 ++ include/QF/plugin/vid_render.h | 1 + libs/video/renderer/gl/gl_draw.c | 16 ++ libs/video/renderer/glsl/glsl_draw.c | 55 ++++++- libs/video/renderer/r_progs.c | 29 ++++ libs/video/renderer/sw/draw.c | 159 ++++++++++++++++++++ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_vulkan.c | 7 + libs/video/renderer/vulkan/qfpipeline.plist | 8 + libs/video/renderer/vulkan/vulkan_bsp.c | 6 +- libs/video/renderer/vulkan/vulkan_draw.c | 96 +++++++++--- ruamoko/include/draw.h | 4 + ruamoko/lib/draw.r | 4 + 18 files changed, 375 insertions(+), 28 deletions(-) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index 65f1a03da..d348e2534 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -41,6 +41,7 @@ void gl_Draw_Crosshair (void); void gl_Draw_CrosshairAt (int ch, int x, int y); void gl_Draw_TileClear (int x, int y, int w, int h); void gl_Draw_Fill (int x, int y, int w, int h, int c); +void gl_Draw_Line (int x0, int y0, int x1, int y1, int c); void gl_Draw_TextBox (int x, int y, int width, int lines, byte alpha); void gl_Draw_FadeScreen (void); void gl_Draw_BlendScreen (quat_t color); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index 653e2bc5f..5c93713fc 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -41,6 +41,7 @@ void glsl_Draw_Crosshair (void); void glsl_Draw_CrosshairAt (int ch, int x, int y); void glsl_Draw_TileClear (int x, int y, int w, int h); void glsl_Draw_Fill (int x, int y, int w, int h, int c); +void glsl_Draw_Line (int x0, int y0, int x1, int y1, int c); void glsl_Draw_TextBox (int x, int y, int width, int lines, byte alpha); void glsl_Draw_FadeScreen (void); void glsl_Draw_BlendScreen (quat_t color); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 26f9d2a28..216f4b3a0 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -50,6 +50,8 @@ void Vulkan_Draw_TileClear (int x, int y, int w, int h, struct vulkan_ctx_s *ctx); void Vulkan_Draw_Fill (int x, int y, int w, int h, int c, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, + struct vulkan_ctx_s *ctx); void Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, struct vulkan_ctx_s *ctx); void Vulkan_Draw_FadeScreen (struct vulkan_ctx_s *ctx); diff --git a/include/QF/draw.h b/include/QF/draw.h index 8f6b78889..5f6037e15 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -144,6 +144,17 @@ void Draw_TileClear (int x, int y, int w, int h); */ void Draw_Fill (int x, int y, int w, int h, int c); +/** Clear a line with a solid color. + \param x0 horizontal position of the line start point + \param y0 horizontal position of the line start point + \param x1 horizontal position of the line end point + \param y1 horizontal position of the line end point + \param c 8 bit color index. + + The color comes from the quake palette. +*/ +void Draw_Line (int x0, int y0, int x1, int y1, int c); + /** Draw a text box on the screen \param x horizontal location of the upper left corner of the box \param y vertical location of the upper left corner of the box diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 1f19a5278..3d6774d08 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -91,6 +91,7 @@ typedef struct vid_render_funcs_s { void (*Draw_CrosshairAt) (int ch, int x, int y); void (*Draw_TileClear) (int x, int y, int w, int h); void (*Draw_Fill) (int x, int y, int w, int h, int c); + void (*Draw_Line) (int x0, int y0, int x1, int y1, int c); void (*Draw_TextBox) (int x, int y, int width, int lines, byte alpha); void (*Draw_FadeScreen) (void); void (*Draw_BlendScreen) (quat_t color); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 820c83d8e..c4abb9753 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -910,6 +910,22 @@ gl_Draw_Fill (int x, int y, int w, int h, int c) qfglEnable (GL_TEXTURE_2D); } +void +gl_Draw_Line (int x0, int y0, int x1, int y1, int c) +{ + qfglDisable (GL_TEXTURE_2D); + qfglColor3ubv (vid.palette + c * 3); + + qfglBegin (GL_LINES); + + qfglVertex2f (x0, y0); + qfglVertex2f (x1, y1); + + qfglEnd (); + qfglColor3ubv (color_white); + qfglEnable (GL_TEXTURE_2D); +} + void gl_Draw_FadeScreen (void) { diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index d24d57f97..a150fe20f 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -104,6 +104,7 @@ static struct { static scrap_t *draw_scrap; // hold all 2d images static byte white_block[8 * 8]; static dstring_t *draw_queue; +static dstring_t *line_queue; static qpic_t *conchars; static int conback_texture; static qpic_t *crosshair_pic; @@ -388,6 +389,7 @@ glsl_Draw_Init (void) //crosshaircolor->callback (crosshaircolor); draw_queue = dstring_new (); + line_queue = dstring_new (); vert_shader = GLSL_BuildShader (twod_vert_effects); frag_shader = GLSL_BuildShader (twod_frag_effects); @@ -461,14 +463,26 @@ static void flush_2d (void) { GLSL_ScrapFlush (draw_scrap); - qfeglBindTexture (GL_TEXTURE_2D, GLSL_ScrapTexture (draw_scrap)); - qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT, - 0, 32, draw_queue->str); - qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT, - 0, 32, draw_queue->str + 16); - qfeglDrawArrays (GL_TRIANGLES, 0, draw_queue->size / 32); + qfeglBindTexture (GL_TEXTURE_2D, GLSL_ScrapTexture (draw_scrap)); + if (draw_queue->size) { + qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT, + 0, 32, draw_queue->str); + qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT, + 0, 32, draw_queue->str + 16); + + qfeglDrawArrays (GL_TRIANGLES, 0, draw_queue->size / 32); + } + if (line_queue->size) { + qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT, + 0, 32, line_queue->str); + qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT, + 0, 32, line_queue->str + 16); + + qfeglDrawArrays (GL_LINES, 0, line_queue->size / 32); + } draw_queue->size = 0; + line_queue->size = 0; } void @@ -693,6 +707,32 @@ glsl_Draw_Fill (int x, int y, int w, int h, int c) draw_pic (x, y, w, h, white_pic, 0, 0, 8, 8, color); } +void +glsl_Draw_Line (int x0, int y0, int x1, int y1, int c) +{ + glpic_t *gl = (glpic_t *) white_pic->data; + subpic_t *sp = gl->subpic; + float sl = sp->rect->x * sp->size; + float sh = sp->rect->x * sp->size; + float tl = sp->rect->y * sp->size; + float th = sp->rect->y * sp->size; + + quat_t color = { VectorExpand (vid.palette + c * 3), 255 }; + QuatScale (color, 1/255.0, color); + drawvert_t verts[2] = { + { .xyst = { x0, y0, sl, tl }, .color = { QuatExpand (color) }, }, + { .xyst = { x1, y1, sh, th }, .color = { QuatExpand (color) }, }, + }; + + void *v; + int size = sizeof (verts); + + line_queue->size += size; + dstring_adjust (line_queue); + v = line_queue->str + line_queue->size - size; + memcpy (v, verts, size); +} + static inline void draw_blendscreen (quat_t color) { @@ -784,12 +824,13 @@ void GLSL_DrawReset (void) { draw_queue->size = 0; + line_queue->size = 0; } void GLSL_FlushText (void) { - if (draw_queue->size) + if (draw_queue->size || line_queue->size) flush_2d (); } diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 319634505..db9760e37 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -42,6 +42,8 @@ #include "QF/render.h" #include "QF/sys.h" +#include "QF/ui/view.h" + #include "r_internal.h" typedef struct { @@ -296,6 +298,18 @@ bi_Draw_Fill (progs_t *pr, void *_res) r_funcs->Draw_Fill (x, y, w, h, color); } +static void +bi_Draw_Line (progs_t *pr, void *_res) +{ + int x0 = P_INT (pr, 0); + int y0 = P_INT (pr, 1); + int x1 = P_INT (pr, 2); + int y1 = P_INT (pr, 3); + int color = P_INT (pr, 4); + + r_funcs->Draw_Line (x0, y0, x1, y1, color); +} + static void bi_Draw_Crosshair (progs_t *pr, void *_res) { @@ -306,6 +320,18 @@ bi_Draw_Crosshair (progs_t *pr, void *_res) r_funcs->Draw_CrosshairAt (ch, x, y); } +static void +bi_Draw_Width (progs_t *pr, void *_res) +{ + R_INT (pr) = r_data->vid->conview->xlen; +} + +static void +bi_Draw_Height (progs_t *pr, void *_res) +{ + R_INT (pr) = r_data->vid->conview->ylen; +} + static const char * bi_draw_get_key (const void *p, void *unused) { @@ -338,6 +364,8 @@ bi_draw_destroy (progs_t *pr, void *_res) #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { + bi(Draw_Width, 0), + bi(Draw_Height, 0), bi(Draw_FreePic, 1, p(ptr)), bi(Draw_MakePic, 3, p(int), p(int), p(string)), bi(Draw_CachePic, 2, p(string), p(int)), @@ -351,6 +379,7 @@ static builtin_t builtins[] = { bi(Draw_nString, 4, p(int), p(int), p(string), p(int)), bi(Draw_AltString, 3, p(int), p(int), p(string)), bi(Draw_Fill, 5, p(int), p(int), p(int), p(int), p(int)), + bi(Draw_Line, 5, p(int), p(int), p(int), p(int), p(int)), bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)), {0} }; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 27568d82c..c861da9b4 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -766,6 +766,165 @@ Draw_Fill (int x, int y, int w, int h, int c) dest[u] = c; } +static inline byte * +draw_horizontal (byte *dest, int xs, int len, int c) +{ + while (len-- > 0) { + *dest = c; + dest += xs; + } + return dest; +} + +static inline byte * +draw_vertical (byte *dest, int len, int c) +{ + while (len-- > 0) { + *dest = c; + dest += d_rowbytes; + } + return dest; +} + +static void +draw_line (int x0, int y0, int x1, int y1, int c) +{ + // Bresenham's line slice algorith (ala Michael Abrash) + int dx, dy, sx; + // always go top to bottom + if (y1 < y0) { + int t; + t = y1; y1 = y0; y0 = t; + t = x1; x1 = x0; x0 = t; + } + dy = y1 - y0; + + if ((dx = x1 - x0) < 0) { + sx = -1; + dx = -dx; + } else { + sx = 1; + } + + byte *dest = d_viewbuffer + y0 * d_rowbytes + x0; + + if (!dx) { + draw_vertical (dest, dy, c); + return; + } + if (!dy) { + draw_horizontal (dest, sx, dx, c); + return; + } + if (dx == dy) { + while (dy-- > 0) { + *dest = c; + dest += d_rowbytes + sx; + } + return; + } + if (dx > dy) { + int step = dx / dy; + int adj_up = (dx % dy) * 2; + int adj_down = dy * 2; + int error = (dx % dy) - adj_down; + int initial = step / 2 + 1; + int final = initial; + + if (!adj_up && !(step & 1)) { + initial--; + } + if (step & 1) { + error += dy; + } + dest = draw_horizontal (dest, sx, initial, c); + dest += d_rowbytes; + while (dy-- > 1) { + int run = step; + if ((error += adj_up) > 0) { + run++; + error -= adj_down; + } + dest = draw_horizontal (dest, sx, run, c); + dest += d_rowbytes; + } + dest = draw_horizontal (dest, sx, final, c); + } else { + int step = dy / dx; + int adj_up = (dy % dx) * 2; + int adj_down = dx * 2; + int error = (dy % dx) - adj_down; + int initial = step / 2 + 1; + int final = initial; + + if (!adj_up && !(step & 1)) { + initial--; + } + if (step & 1) { + error += dx; + } + dest = draw_vertical (dest, initial, c); + dest += sx; + while (dx-- > 1) { + int run = step; + if ((error += adj_up) > 0) { + run++; + error -= adj_down; + } + dest = draw_vertical (dest, run, c); + dest += sx; + } + dest = draw_vertical (dest, final, c); + } +} + +static inline byte +test_point (int x, int y) +{ + byte c = 0; + + if (x < 0) { + c |= 1; + } else if (x >= vid.conview->xlen) { + c |= 2; + } + if (y < 0) { + c |= 4; + } else if (y >= vid.conview->ylen) { + c |= 8; + } + return c; +} + +void +Draw_Line (int x0, int y0, int x1, int y1, int c) +{ + byte c0 = test_point (x0, y0); + byte c1 = test_point (x1, y1); + int xmax = vid.conview->xlen - 1; + int ymax = vid.conview->ylen - 1; + + while (c0 | c1) { + // Cohen-Sutherland line clipping + if (c0 & c1) { + return; + } + int dx = x1 - x0; + int dy = y1 - y0; + if (c0 & 1) { y0 = (( 0 - x0) * dy + dx * y0) / dx; x0 = 0; } + if (c0 & 2) { y0 = ((xmax - x0) * dy + dx * y0) / dx; x0 = xmax; } + if (c1 & 1) { y1 = (( 0 - x1) * dy + dx * y1) / dx; x1 = 0; } + if (c1 & 2) { y1 = ((xmax - x1) * dy + dx * y1) / dx; x1 = xmax; } + + if (c0 & 4) { x0 = (( 0 - y0) * dx + dy * x0) / dy; y0 = 0; } + if (c0 & 8) { x0 = ((ymax - y0) * dx + dy * x0) / dy; y0 = ymax; } + if (c1 & 4) { x1 = (( 0 - y1) * dx + dy * x1) / dy; y1 = 0; } + if (c1 & 8) { x1 = ((ymax - y1) * dx + dy * x1) / dy; y1 = ymax; } + c0 = test_point (x0, y0); + c1 = test_point (x1, y1); + } + draw_line (x0, y0, x1, y1, c); +} void Draw_FadeScreen (void) diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 7944e3ada..3fe390bf9 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -495,6 +495,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_CrosshairAt, gl_Draw_TileClear, gl_Draw_Fill, + gl_Draw_Line, gl_Draw_TextBox, gl_Draw_FadeScreen, gl_Draw_BlendScreen, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 9be89b23a..958cfbfdc 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -439,6 +439,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_CrosshairAt, glsl_Draw_TileClear, glsl_Draw_Fill, + glsl_Draw_Line, glsl_Draw_TextBox, glsl_Draw_FadeScreen, glsl_Draw_BlendScreen, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index a4a532557..e1398bc72 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -459,6 +459,7 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_CrosshairAt, Draw_TileClear, Draw_Fill, + Draw_Line, Draw_TextBox, Draw_FadeScreen, Draw_BlendScreen, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 6e66fdc54..cce63d511 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -189,6 +189,12 @@ vulkan_Draw_Fill (int x, int y, int w, int h, int c) Vulkan_Draw_Fill (x, y, w, h, c, vulkan_ctx); } +static void +vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c) +{ + Vulkan_Draw_Line (x0, y0, x1, y1, c, vulkan_ctx); +} + static void vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha) { @@ -731,6 +737,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_CrosshairAt, vulkan_Draw_TileClear, vulkan_Draw_Fill, + vulkan_Draw_Line, vulkan_Draw_TextBox, vulkan_Draw_FadeScreen, vulkan_Draw_BlendScreen, diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 9c16a5556..e7b45bebd 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -482,6 +482,10 @@ topology = triangle_list; primitiveRestartEnable = false; }; + lines = { + topology = line_list; + primitiveRestartEnable = false; + }; twod = { topology = triangle_strip; primitiveRestartEnable = true; @@ -1045,6 +1049,10 @@ }; layout = twod_layout; }; + lines = { + @inherit = $properties.pipelines.twod; + inputAssembly = $properties.inputAssembly.lines; + }; lighting = { @inherit = $properties.pipelines.comp_base; subpass = 3; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 070cb3874..75d3df33f 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1059,8 +1059,10 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) int world_id = worldent.renderer.model->render_id; bctx->main_pass.ent_frame = 0; // world is always frame 0 bctx->main_pass.inst_id = world_id; - DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, - worldent.renderer.render_id); + if (bctx->main_pass.instances) { + DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, + worldent.renderer.render_id); + } R_VisitWorldNodes (brush, ctx); if (!bctx->vertex_buffer) { return; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 46604ae24..c042d814f 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -82,8 +82,11 @@ typedef struct cachepic_s { typedef struct drawframe_s { size_t vert_offset; - drawvert_t *verts; + size_t line_offset; + drawvert_t *quad_verts; + drawvert_t *line_verts; uint32_t num_quads; + uint32_t num_lines; VkCommandBuffer cmd; VkDescriptorSet descriptors; } drawframe_t; @@ -109,7 +112,8 @@ typedef struct drawctx_s { VkDeviceMemory vert_memory; VkBuffer ind_buffer; VkDeviceMemory ind_memory; - VkPipeline pipeline; + VkPipeline quad_pipeline; + VkPipeline line_pipeline; VkPipelineLayout layout; drawframeset_t frames; } drawctx_t; @@ -119,6 +123,11 @@ typedef struct drawctx_s { #define VERTS_PER_QUAD (4) #define INDS_PER_QUAD (5) // one per vert plus primitive reset +#define MAX_LINES (32768) +#define VERTS_PER_LINE (2) + +#define VERTS_PER_FRAME (MAX_LINES*VERTS_PER_LINE + MAX_QUADS*VERTS_PER_QUAD) + static void create_quad_buffers (vulkan_ctx_t *ctx) { @@ -133,7 +142,7 @@ create_quad_buffers (vulkan_ctx_t *ctx) VkBuffer vbuf, ibuf; VkDeviceMemory vmem, imem; - vert_size = frames * MAX_QUADS * VERTS_PER_QUAD * sizeof (drawvert_t); + vert_size = frames * VERTS_PER_FRAME * sizeof (drawvert_t); ind_size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t); vbuf = QFV_CreateBuffer (device, vert_size, @@ -161,10 +170,14 @@ create_quad_buffers (vulkan_ctx_t *ctx) for (size_t f = 0; f < frames; f++) { drawframe_t *frame = &dctx->frames.a[f]; - size_t ind = f * MAX_QUADS * VERTS_PER_QUAD; + size_t ind = f * VERTS_PER_FRAME; + size_t lind = ind + MAX_QUADS * VERTS_PER_QUAD; frame->vert_offset = ind * sizeof (drawvert_t); - frame->verts = vert_data + ind; + frame->line_offset = lind; + frame->quad_verts = vert_data + ind; + frame->line_verts = frame->quad_verts + MAX_QUADS * VERTS_PER_QUAD; frame->num_quads = 0; + frame->num_lines = 0; } // The indices will never change so pre-generate and stash them @@ -347,7 +360,8 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) destroy_quad_buffers (ctx); - dfunc->vkDestroyPipeline (device->dev, dctx->pipeline, 0); + dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); + dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0); Hash_DelTable (dctx->pic_cache); delete_memsuper (dctx->pic_memsuper); delete_memsuper (dctx->string_memsuper); @@ -409,7 +423,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); - dctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); + dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); + dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines"); dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout"); @@ -457,7 +472,7 @@ draw_pic (float x, float y, int w, int h, qpic_t *pic, return; } - drawvert_t *verts = frame->verts + frame->num_quads * VERTS_PER_QUAD; + drawvert_t *verts = frame->quad_verts + frame->num_quads * VERTS_PER_QUAD; frame->num_quads++; subpic_t *subpic = *(subpic_t **) pic->data; @@ -767,6 +782,32 @@ Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) draw_pic (x, y, w, h, dctx->white_pic, 0, 0, 1, 1, color, frame); } +void +Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + + if (frame->num_quads >= MAX_QUADS) { + return; + } + + quat_t color = { VectorExpand (vid.palette + c * 3), 255 }; + QuatScale (color, 1/255.0, color); + drawvert_t *verts = frame->line_verts + frame->num_lines * VERTS_PER_LINE; + + verts[0] = (drawvert_t) { + .xy = { x0, y0 }, + .color = { QuatExpand (color) }, + }; + verts[1] = (drawvert_t) { + .xy = { x1, y1 }, + .color = { QuatExpand (color) }, + }; + + frame->num_lines++; +} + static inline void draw_blendscreen (quat_t color, vulkan_ctx_t *ctx) { @@ -816,16 +857,23 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + if (!dframe->num_quads && !dframe->num_lines) { + return; + } + VkCommandBuffer cmd = dframe->cmd; //FIXME which pass? DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], cmd); - VkMappedMemoryRange range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - dctx->vert_memory, dframe->vert_offset, - dframe->num_quads * VERTS_PER_QUAD * sizeof (drawvert_t), + VkMappedMemoryRange ranges[] = { + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + dctx->vert_memory, dframe->vert_offset, + dframe->num_quads * VERTS_PER_QUAD * sizeof (drawvert_t) }, + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + dctx->vert_memory, dframe->line_offset, + dframe->num_lines * VERTS_PER_LINE * sizeof (drawvert_t) }, }; - dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); + dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { @@ -843,10 +891,6 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) QFV_duCmdBeginLabel (device, cmd, "twod", { 0.6, 0.2, 0, 1}); - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - dctx->pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); VkDeviceSize offsets[] = {dframe->vert_offset}; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets); dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, @@ -858,13 +902,27 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) VkPipelineLayout layout = dctx->layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 2, set, 0, 0); - dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD, - 1, 0, 0, 0); + if (dframe->num_quads) { + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + dctx->quad_pipeline); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); + dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD, + 1, 0, 0, 0); + } + + if (dframe->num_lines) { + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + dctx->line_pipeline); + dfunc->vkCmdDraw (cmd, dframe->num_lines * VERTS_PER_LINE, + 1, MAX_QUADS * VERTS_PER_QUAD, 0); + } QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); dframe->num_quads = 0; + dframe->num_lines = 0; } void diff --git a/ruamoko/include/draw.h b/ruamoko/include/draw.h index ae868ff36..a5369375e 100644 --- a/ruamoko/include/draw.h +++ b/ruamoko/include/draw.h @@ -10,6 +10,9 @@ struct _qpic_t { }; typedef struct _qpic_t *qpic_t; +@extern int Draw_Width (void); +@extern int Draw_Height (void); + @extern void Draw_FreePic (qpic_t pic); @extern qpic_t Draw_MakePic (int width, int heiight, string data); @extern qpic_t Draw_CachePic (string name, int alpha); @@ -24,6 +27,7 @@ typedef struct _qpic_t *qpic_t; @extern void Draw_nString (int x, int y, string text, int n); @extern void Draw_AltString (int x, int y, string text); @extern void Draw_Fill (int x, int y, int w, int h, int c); +@extern void Draw_Line (int x0, int y0, int x1, int y1, int c); @extern void Draw_Crosshair (int ch, int x, int y); @extern void text_box (int x, int y, int width, int lines); diff --git a/ruamoko/lib/draw.r b/ruamoko/lib/draw.r index 5aef3ab75..65311595f 100644 --- a/ruamoko/lib/draw.r +++ b/ruamoko/lib/draw.r @@ -1,5 +1,8 @@ #include +int Draw_Width (void) = #0; +int Draw_Height (void) = #0; + void Draw_FreePic (qpic_t pic) = #0; qpic_t Draw_MakePic (int width, int heiight, string data) = #0; qpic_t (string name, int alpha) Draw_CachePic = #0; @@ -14,6 +17,7 @@ void (int x, int y, string text) Draw_String = #0; void (int x, int y, string text, int n) Draw_nString = #0; void (int x, int y, string text) Draw_AltString = #0; void (int x, int y, int w, int h, int c) Draw_Fill = #0; +void (int x0, int y0, int x1, int y1, int c) Draw_Line = #0; void (int ch, int x, int y) Draw_Crosshair = #0; void (int x, int y, int width, int lines) text_box = From af4c120d3d6777555ad8fb85ce700a4ee21d6189 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Aug 2022 17:42:08 +0900 Subject: [PATCH 2926/3664] [qfcc] Don't check parameter size for arrays Arrays are passed as a pointer to the first element, so are always valid parameters. Fixes a bogus "formal parameter N is too large to be passed by value" error. --- tools/qfcc/source/expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index b112d7296..1fc1249d3 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2081,7 +2081,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) err = error (e, "type of formal parameter %d is incomplete", i + 1); } - if (value_too_large (t)) { + if (!is_array (t) && value_too_large (t)) { err = error (e, "formal parameter %d is too large to be passed by" " value", i + 1); } From d39f02ecfcf55667cb400e5f8a9a629809256f95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Aug 2022 17:46:14 +0900 Subject: [PATCH 2927/3664] [renderer] Don't round up scrap allocations I will need to do more work to improve the 2d allocation, but rounding up the requested sizes to the next power of two proved to be excessively wasteful: I was able to allocate spots for only half of the sub-pics I needed (though I did still need to double the number of pixels in the end). --- libs/video/renderer/r_scrap.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/r_scrap.c b/libs/video/renderer/r_scrap.c index 9bb6518d7..8d01ee175 100644 --- a/libs/video/renderer/r_scrap.c +++ b/libs/video/renderer/r_scrap.c @@ -72,16 +72,12 @@ R_ScrapDelete (rscrap_t *scrap) VISIBLE vrect_t * R_ScrapAlloc (rscrap_t *scrap, int width, int height) { - int w, h; vrect_t **t, **best; vrect_t *old, *frags, *rect; - w = pow2rup (width); - h = pow2rup (height); - best = 0; for (t = &scrap->free_rects; *t; t = &(*t)->next) { - if ((*t)->width < w || (*t)->height < h) + if ((*t)->width < width || (*t)->height < height) continue; // won't fit if (!best) { best = t; @@ -94,7 +90,7 @@ R_ScrapAlloc (rscrap_t *scrap, int width, int height) return 0; // couldn't find a spot old = *best; *best = old->next; - rect = VRect_New (old->x, old->y, w, h); + rect = VRect_New (old->x, old->y, width, height); frags = VRect_Difference (old, rect); VRect_Delete (old); if (frags) { From 4d5b38f0c9ca8b5bb88d9d81f06b03d23aca025a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Aug 2022 17:53:03 +0900 Subject: [PATCH 2928/3664] [renderer] Star work on adding FreeType support Right now, this just initializes the library and loads a font into memory, preloading a given set of characters (specified by unicode values). --- Makefile.am | 2 +- config.d/freetype.m4 | 15 +++ configure.ac | 1 + include/r_font.h | 66 +++++++++++ libs/video/renderer/Makemodule.am | 4 +- libs/video/renderer/r_font.c | 186 ++++++++++++++++++++++++++++++ libs/video/renderer/r_progs.c | 16 +++ ruamoko/qwaq/builtins/graphics.c | 3 + 8 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 config.d/freetype.m4 create mode 100644 include/r_font.h create mode 100644 libs/video/renderer/r_font.c diff --git a/Makefile.am b/Makefile.am index 33aa5b689..194fcd984 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,7 @@ NOCONV_DIST= \ BUILT_SOURCES = $(top_srcdir)/.version #AM_CFLAGS= @PREFER_NON_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) $(FREETYPE_CFLAGS) common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@ diff --git a/config.d/freetype.m4 b/config.d/freetype.m4 new file mode 100644 index 000000000..7f13bf1ee --- /dev/null +++ b/config.d/freetype.m4 @@ -0,0 +1,15 @@ +AC_ARG_ENABLE(freetype, + AS_HELP_STRING([--disable-freetype], [disable freetype support])) +if test "x$enable_freetype" != "xno"; then + if test "x$PKG_CONFIG" != "x"; then + PKG_CHECK_MODULES([FREETYPE], [freetype2], HAVE_FREETYPE=yes, HAVE_FREETYPE=no) + fi +else + HAVE_FREETYPE=no + FREETYPE_LIBS= +fi +AC_SUBST(FREETYPE_LIBS) + +if test "x$HAVE_FREETYPE" == "xyes"; then + AC_DEFINE(HAVE_FREETYPE, 1, [Define if you have the freetype library]) +fi diff --git a/configure.ac b/configure.ac index 17c225b2e..79f74edac 100644 --- a/configure.ac +++ b/configure.ac @@ -68,6 +68,7 @@ m4_include(config.d/x11.m4) m4_include(config.d/sdl.m4) m4_include(config.d/curses.m4) +m4_include(config.d/freetype.m4) dnl ================================================================== dnl Checks for system type diff --git a/include/r_font.h b/include/r_font.h new file mode 100644 index 000000000..a27281b5d --- /dev/null +++ b/include/r_font.h @@ -0,0 +1,66 @@ +/* + r_font.h + + Renderer font management + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/8/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __r_font_h +#define __r_font_h + +#include +#include FT_FREETYPE_H + +#include "QF/hash.h" +#include "QF/progs.h" //FIXME for PR_RESMAP + +#include "QF/ui/vrect.h" +#include "QF/simd/types.h" + +#include "r_scrap.h" + +typedef struct rglyph_s { + struct rfont_s *font; + vrect_t *rect; + vec2i_t bearing; + int advance; + int charcode; +} rglyph_t; + +typedef struct rfont_s { + void *font_resource; + FT_Face face; + rscrap_t scrap; + byte *scrap_bitmap; + hashtab_t *glyphmap; + PR_RESMAP(rglyph_t) glyphs; +} rfont_t; + +void R_FontInit (void); +void R_FontFree (rfont_t *font); +rfont_t *R_FontLoad (QFile *font_file, int size, const int *preload); + +#endif//__r_font_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 6a52b1af4..49e229b1a 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -30,13 +30,15 @@ video_renderer_common_sources = \ libs/video/renderer/r_billboard.c \ libs/video/renderer/r_dyn_textures.c \ libs/video/renderer/r_ent.c \ + libs/video/renderer/r_font.c \ libs/video/renderer/r_iqm.c \ libs/video/renderer/r_sprite.c \ libs/video/renderer/vid_common.c renderer_libs= \ @vid_render_static_plugin_libs@ \ - libs/util/libQFutil.la + libs/util/libQFutil.la \ + $(FREETYPE_LIBS) libs_video_renderer_libQFrenderer_la_LDFLAGS= @STATIC@ libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libs) diff --git a/libs/video/renderer/r_font.c b/libs/video/renderer/r_font.c new file mode 100644 index 000000000..fb053dcda --- /dev/null +++ b/libs/video/renderer/r_font.c @@ -0,0 +1,186 @@ +/* + r_font.c + + Renderer font management management + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/8/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/quakefs.h" +#include "QF/sys.h" +#include "QF/math/bitop.h" + +#include "r_font.h" + +#include "compat.h" + +static FT_Library ft; + +static uintptr_t +glyph_get_hash (const void *_glyph, void *unused) +{ + __auto_type glyph = (const rglyph_t *) _glyph; + return glyph->charcode; +} + +static int +glyph_compare (const void *_a, const void *_b, void *unused) +{ + __auto_type a = (const rglyph_t *) _a; + __auto_type b = (const rglyph_t *) _b; + return a->charcode == b->charcode; +} + +static rglyph_t * +alloc_glyph (rfont_t *font) +{ + return PR_RESNEW(font->glyphs); +} + +static void +free_glyph (rfont_t *font, rglyph_t *glyph) +{ + PR_RESFREE (font->glyphs, glyph); +} + +static void +copy_glypn (rglyph_t *glyph, FT_GlyphSlot src_glyph) +{ + int dst_pitch = glyph->font->scrap.width; + byte *dst = glyph->font->scrap_bitmap + glyph->rect->x + glyph->rect->y * dst_pitch; + int src_pitch = src_glyph->bitmap.pitch; + byte *src = src_glyph->bitmap.buffer; + + for (unsigned i = 0; i < src_glyph->bitmap.rows; i++) { + memcpy (dst, src, src_glyph->bitmap.width); + dst += dst_pitch; + src += src_pitch; + } +} + +static void +glyphmap_free_glyph (void *_g, void *_f) +{ + rglyph_t *glyph = _g; + rfont_t *font = _f; + free_glyph (font, glyph); +} + +VISIBLE void +R_FontInit (void) +{ + if (FT_Init_FreeType (&ft)) { + Sys_Error ("Could not init FreeType library"); + } +} + +VISIBLE void +R_FontFree (rfont_t *font) +{ + if (font->face) { + FT_Done_Face (font->face); + } + if (font->glyphmap) { + Hash_DelTable (font->glyphmap); + } + if (font->scrap.rects || font->scrap.free_rects) { + R_ScrapDelete (&font->scrap); + } + free (font->scrap_bitmap); + free (font->font_resource); + free (font); +} + +VISIBLE rfont_t * +R_FontLoad (QFile *font_file, int size, const int *preload) +{ + byte *font_data = QFS_LoadFile (font_file, 0); + if (!font_data) { + return 0; + } + size_t font_size = Qfilesize (font_file);; + rfont_t *font = calloc (1, sizeof (rfont_t)); + font->font_resource = font_data; + if (FT_New_Memory_Face (ft, font_data, font_size, 0, &font->face)) { + R_FontFree (font); + return 0; + } + + font->glyphmap = Hash_NewTable (0x10000, 0, glyphmap_free_glyph, font, 0); + Hash_SetHashCompare (font->glyphmap, glyph_get_hash, glyph_compare); + + FT_Set_Pixel_Sizes(font->face, 0, size); + int pixels = 0; + for (const int *c = preload; *c; c++) { + rglyph_t search = { .charcode = *c }; + rglyph_t *glyph = Hash_FindElement (font->glyphmap, &search); + if (glyph) { + continue; + } + if (FT_Load_Char(font->face, *c, FT_LOAD_DEFAULT)) { + continue; + } + __auto_type g = font->face->glyph; + pixels += g->bitmap.width * g->bitmap.rows; + + glyph = alloc_glyph (font); + glyph->charcode = *c; + Hash_AddElement (font->glyphmap, glyph); + } + Hash_FlushTable (font->glyphmap); + pixels = sqrt (2 * pixels); + pixels = BITOP_RUP (pixels); + R_ScrapInit (&font->scrap, pixels, pixels); + font->scrap_bitmap = calloc (1, pixels * pixels); + + for (const int *c = preload; *c; c++) { + rglyph_t search = { .charcode = *c }; + rglyph_t *glyph = Hash_FindElement (font->glyphmap, &search); + if (glyph) { + continue; + } + if (FT_Load_Char(font->face, *c, FT_LOAD_RENDER)) { + continue; + } + __auto_type g = font->face->glyph; + int width = g->bitmap.width; + int height = g->bitmap.rows; + glyph = alloc_glyph (font); + glyph->font = font; + glyph->rect = R_ScrapAlloc (&font->scrap, width, height); + glyph->bearing = (vec2i_t) { g->bitmap_left, g->bitmap_top }; + glyph->advance = g->advance.x; + glyph->charcode = *c; + Hash_AddElement (font->glyphmap, glyph); + + copy_glypn (glyph, g); + } + + return font; +} diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index db9760e37..f7d884c4f 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -39,12 +39,14 @@ #include "QF/draw.h" #include "QF/hash.h" #include "QF/progs.h" +#include "QF/quakefs.h" #include "QF/render.h" #include "QF/sys.h" #include "QF/ui/view.h" #include "r_internal.h" +#include "r_font.h" typedef struct { pr_int_t width; @@ -332,6 +334,18 @@ bi_Draw_Height (progs_t *pr, void *_res) R_INT (pr) = r_data->vid->conview->ylen; } +static void +bi_Font_Load (progs_t *pr, void *_res) +{ + const char *font_path = P_GSTRING (pr, 0); + int font_size = P_INT (pr, 1); + int *preload = (int *) P_GPOINTER (pr, 2); + + QFile *font_file = QFS_FOpenFile (font_path); + rfont_t *font = R_FontLoad (font_file, font_size, preload); + (void)font; +} + static const char * bi_draw_get_key (const void *p, void *unused) { @@ -381,6 +395,8 @@ static builtin_t builtins[] = { bi(Draw_Fill, 5, p(int), p(int), p(int), p(int), p(int)), bi(Draw_Line, 5, p(int), p(int), p(int), p(int), p(int)), bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)), + + bi(Font_Load, 3, p(string), p(int), p(ptr)), {0} }; diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 709f05b4f..47f51a9cc 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -57,6 +57,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/plugin/console.h" #include "rua_internal.h" +#include "r_font.h" #include "ruamoko/qwaq/qwaq.h" @@ -330,6 +331,8 @@ BI_Graphics_Init (progs_t *pr) IN_Init (); Mod_Init (); R_Init (); + R_FontInit (); + R_Progs_Init (pr); RUA_Game_Init (pr, thread->rua_security); S_Progs_Init (pr); From 8c270a0a9efd3e95db312eeffea079a47f3d7e32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 30 Aug 2022 14:29:22 +0900 Subject: [PATCH 2929/3664] [vulkan] Switch to pre-multiplied alpha for 2d I have recently learned that pre-multiplied alpha is the correct way to do compositing, which is pretty much what the 2d pass does (actually, all passes, but...). This required ensuring the color factor passed to the fragment shader is pre-multiplied (a little silly for cshifts as they used to be pre-multiplied but were un-pre-multiplied early in QF's history and I don't feel like fixing that right now as it affects all renderers), and also pre-multiplying alpha when converting from 8-bit palette to rgba as the palette entry for transparent has that funky pink (which is used in full-brights). --- libs/video/renderer/vulkan/qfpipeline.plist | 4 ++-- libs/video/renderer/vulkan/vulkan_draw.c | 23 +++++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index e7b45bebd..9c78e01cb 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -624,10 +624,10 @@ }; alpha_blend = { blendEnable = true; - srcColorBlendFactor = src_alpha; + srcColorBlendFactor = one; dstColorBlendFactor = one_minus_src_alpha; colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; + srcAlphaBlendFactor = one; dstAlphaBlendFactor = one_minus_src_alpha; alphaBlendOp = add; colorWriteMask = r|g|b|a; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index c042d814f..b4d8b2ac4 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -284,10 +284,12 @@ pic_data (const char *name, int w, int h, const byte *data, drawctx_t *dctx) for (size_t i = 0; i < size; i++) { byte pix = *data++; byte *col = vid.palette + pix * 3; - *picdata++ = *col++; - *picdata++ = *col++; - *picdata++ = *col++; - *picdata++ = (pix == 255) - 1; + byte alpha = (pix == 255) - 1; + // pre-multiply alpha. + *picdata++ = *col++ & alpha; + *picdata++ = *col++ & alpha; + *picdata++ = *col++ & alpha; + *picdata++ = alpha; } //FIXME live updates of the scrap aren't //syncronized properly for some reason and result in stale texels being @@ -755,7 +757,9 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - quat_t color = { 1, 1, 1, bound (0, alpha, 255) / 255.0}; + float a = bound (0, alpha, 255) / 255.0; + // use pre-multiplied alpha + quat_t color = { a, a, a, a}; qpic_t *cpic; cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx); int ofs = max (0, cpic->height - lines); @@ -929,6 +933,13 @@ void Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) { if (color[3]) { - draw_blendscreen (color, ctx); + quat_t c; + // pre-multiply alpha. + // FIXME this is kind of silly because q1source pre-multiplies alpha + // for blends, but this was un-done early in QF's history in order + // to avoid a pair of state changes + VectorScale (color, color[3], c); + c[3] = color[3]; + draw_blendscreen (c, ctx); } } From 096ecc77103bbbaa61bf36e84f53be77be814657 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Aug 2022 18:14:24 +0900 Subject: [PATCH 2930/3664] [vulkan] Fix incorrect image view format R8G8B8A8 was hard-coded by accident when creating Vulkan_LoadTexArray (or probably even the original Vulkan_LoadTex). This wasn't a problem while everything was loaded in that format, but attempting to load an R8 texture didn't go so well. The same format as the image itself is used now (correctly so). --- libs/video/renderer/vulkan/vulkan_texture.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 699b3af3d..5c4b9cba3 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -195,8 +195,7 @@ Vulkan_LoadTexArray (vulkan_ctx_t *ctx, tex_t *tex, int layers, int mip, va (ctx->va_ctx, "memory:%s", name)); QFV_BindImageMemory (device, qtex->image, qtex->memory, 0); qtex->view = QFV_CreateImageView (device, qtex->image, vtype, - VK_FORMAT_R8G8B8A8_UNORM, - VK_IMAGE_ASPECT_COLOR_BIT); + format, VK_IMAGE_ASPECT_COLOR_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, qtex->view, va (ctx->va_ctx, "iview:%s", name)); From 599c09e77e3c25c8f572304c4695da380ed71f6d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 31 Aug 2022 19:23:30 +0900 Subject: [PATCH 2931/3664] [renderer] Add Draw_AddFont for registering a font It's implemented only in the Vulkan renderer, partly because there's a lot of experimenting going on with it, but the glyphs do get transferred to the GPU (checked in render doc). No rendering is done yet: still thinking about whether to do a quick-and-dirty test, or to add HarfBuzz immediately, and the design surrounding that. --- include/QF/GL/qf_draw.h | 2 ++ include/QF/GLSL/qf_draw.h | 2 ++ include/QF/Vulkan/qf_draw.h | 2 ++ include/QF/draw.h | 4 ++++ include/QF/plugin/vid_render.h | 2 ++ libs/video/renderer/gl/gl_draw.c | 5 ++++ libs/video/renderer/glsl/glsl_draw.c | 5 ++++ libs/video/renderer/r_progs.c | 2 +- libs/video/renderer/sw/draw.c | 5 ++++ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_vulkan.c | 7 ++++++ libs/video/renderer/vulkan/vulkan_draw.c | 29 ++++++++++++++++++++++++ 14 files changed, 67 insertions(+), 1 deletion(-) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index d348e2534..9e2f4e8d6 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -29,6 +29,7 @@ #define __gl_draw_h struct qpic_s; +struct rfont_s; void gl_Draw_Init (void); void gl_Draw_Shutdown (void); @@ -54,6 +55,7 @@ void gl_Draw_Pic (int x, int y, struct qpic_s *pic); void gl_Draw_Picf (float x, float y, struct qpic_s *pic); void gl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); +void gl_Draw_AddFont (struct rfont_s *font); void GL_Set2D (void); void GL_Set2DScaled (void); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index 5c93713fc..e38b39d92 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -29,6 +29,7 @@ #define __QF_GLSL_qf_draw_h struct qpic_s; +struct rfont_s; void glsl_Draw_Init (void); void glsl_Draw_Shutdown (void); @@ -54,6 +55,7 @@ void glsl_Draw_Pic (int x, int y, struct qpic_s *pic); void glsl_Draw_Picf (float x, float y, struct qpic_s *pic); void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); +void glsl_Draw_AddFont (struct rfont_s *font); void GLSL_Set2D (void); void GLSL_Set2DScaled (void); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 216f4b3a0..e8a28e40f 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -31,6 +31,7 @@ struct vulkan_ctx_s; struct qfv_renderframe_s; struct qpic_s; +struct rfont_s; void Vulkan_Draw_Init (struct vulkan_ctx_s *ctx); void Vulkan_Draw_Shutdown (struct vulkan_ctx_s *ctx); @@ -71,6 +72,7 @@ void Vulkan_Draw_Picf (float x, float y, struct qpic_s *pic, void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_AddFont (struct rfont_s *font, struct vulkan_ctx_s *ctx); void Vulkan_Set2D (struct vulkan_ctx_s *ctx); void Vulkan_Set2DScaled (struct vulkan_ctx_s *ctx); diff --git a/include/QF/draw.h b/include/QF/draw.h index 5f6037e15..9e0bf654e 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -243,6 +243,10 @@ void Draw_Picf (float x, float y, qpic_t *pic); \param height vertical size of the sub-region to be drawn */ void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); + +struct rfont_s; +void Draw_AddFont (struct rfont_s *font); + ///@} #endif//__QF_draw_h diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 3d6774d08..a8a6c418e 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -78,6 +78,7 @@ typedef struct vid_model_funcs_s { } vid_model_funcs_t; struct tex_s; +struct rfont_s; typedef void (*capfunc_t) (struct tex_s *screencap, void *data); typedef struct vid_render_funcs_s { @@ -103,6 +104,7 @@ typedef struct vid_render_funcs_s { void (*Draw_Pic) (int x, int y, qpic_t *pic); void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); + void (*Draw_AddFont) (struct rfont_s *font); struct psystem_s *(*ParticleSystem) (void); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index c4abb9753..084104165 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -1018,3 +1018,8 @@ gl_Draw_BlendScreen (quat_t color) qfglColor3ubv (color_white); qfglEnable (GL_TEXTURE_2D); } + +void +gl_Draw_AddFont (struct rfont_s *font) +{ +} diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index a150fe20f..707fcdcb8 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -841,3 +841,8 @@ glsl_Draw_BlendScreen (quat_t color) return; draw_blendscreen (color); } + +void +glsl_Draw_AddFont (struct rfont_s *font) +{ +} diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index f7d884c4f..387b2989e 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -343,7 +343,7 @@ bi_Font_Load (progs_t *pr, void *_res) QFile *font_file = QFS_FOpenFile (font_path); rfont_t *font = R_FontLoad (font_file, font_size, preload); - (void)font; + r_funcs->Draw_AddFont (font); } static const char * diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index c861da9b4..4a9ba34cc 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -974,3 +974,8 @@ Draw_BlendScreen (quat_t color) } vid.vid_internal->set_palette (vid.vid_internal->data, pal); } + +void +Draw_AddFont (struct rfont_s *font) +{ +} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 3fe390bf9..3e165bdf7 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -507,6 +507,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_Pic, gl_Draw_Picf, gl_Draw_SubPic, + gl_Draw_AddFont, gl_ParticleSystem, gl_R_Init, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 958cfbfdc..12b0425eb 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -451,6 +451,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_Pic, glsl_Draw_Picf, glsl_Draw_SubPic, + glsl_Draw_AddFont, glsl_ParticleSystem, glsl_R_Init, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index e1398bc72..b9bb753d1 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -471,6 +471,7 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_Pic, Draw_Picf, Draw_SubPic, + Draw_AddFont, sw_ParticleSystem, sw_R_Init, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index cce63d511..85033e9c7 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -261,6 +261,12 @@ vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, in Vulkan_Draw_SubPic (x, y, pic, srcx, srcy, width, height, vulkan_ctx); } +static void +vulkan_Draw_AddFont (struct rfont_s *font) +{ + Vulkan_Draw_AddFont (font, vulkan_ctx); +} + static void vulkan_begin_frame (void) { @@ -749,6 +755,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_Pic, vulkan_Draw_Picf, vulkan_Draw_SubPic, + vulkan_Draw_AddFont, vulkan_ParticleSystem, vulkan_R_Init, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index b4d8b2ac4..29d93f65d 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -52,6 +52,7 @@ #include "compat.h" #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" @@ -66,6 +67,7 @@ #include "QF/Vulkan/staging.h" #include "QF/ui/view.h" +#include "r_font.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -97,6 +99,8 @@ typedef struct drawframeset_s typedef struct drawctx_s { VkSampler sampler; scrap_t *scrap; + rfont_t *font; + qfv_tex_t *font_tex; qfv_stagebuf_t *stage; qpic_t *crosshair; qpic_t *conchars; @@ -369,6 +373,9 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) delete_memsuper (dctx->string_memsuper); QFV_DestroyScrap (dctx->scrap); QFV_DestroyStagingBuffer (dctx->stage); + if (dctx->font_tex) { + Vulkan_UnloadTex (ctx, dctx->font_tex); + } } void @@ -943,3 +950,25 @@ Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) draw_blendscreen (c, ctx); } } + +void +Vulkan_Draw_AddFont (rfont_t *font, vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + + if (dctx->font_tex) { + Vulkan_UnloadTex (ctx, dctx->font_tex); + dctx->font_tex = 0; + } + dctx->font = font; + if (dctx->font) { + tex_t tex = { + .width = font->scrap.width, + .height = font->scrap.height, + .format = tex_l, + .loaded = 1, + .data = font->scrap_bitmap, + }; + dctx->font_tex = Vulkan_LoadTex (ctx, &tex, 0, "draw.font"); + } +} From 73635d84bf3527c6b3cbd8d5c139b10f888a2bd4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Sep 2022 11:38:09 +0900 Subject: [PATCH 2932/3664] [renderer] Add stubs for Draw_FontString Draw_FontString is for font-based text rendering. Nothing is implemented at this stage. --- include/QF/GL/qf_draw.h | 1 + include/QF/GLSL/qf_draw.h | 1 + include/QF/Vulkan/qf_draw.h | 2 ++ include/QF/draw.h | 1 + include/QF/plugin/vid_render.h | 1 + libs/video/renderer/gl/gl_draw.c | 5 +++++ libs/video/renderer/glsl/glsl_draw.c | 5 +++++ libs/video/renderer/r_progs.c | 10 ++++++++++ libs/video/renderer/sw/draw.c | 5 +++++ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_vulkan.c | 7 +++++++ libs/video/renderer/vulkan/vulkan_draw.c | 5 +++++ 14 files changed, 46 insertions(+) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index 9e2f4e8d6..30315e7b0 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -56,6 +56,7 @@ void gl_Draw_Picf (float x, float y, struct qpic_s *pic); void gl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); void gl_Draw_AddFont (struct rfont_s *font); +void gl_Draw_FontString (int x, int y, const char *str); void GL_Set2D (void); void GL_Set2DScaled (void); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index e38b39d92..ea9b3e5dc 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -56,6 +56,7 @@ void glsl_Draw_Picf (float x, float y, struct qpic_s *pic); void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); void glsl_Draw_AddFont (struct rfont_s *font); +void glsl_Draw_FontString (int x, int y, const char *str); void GLSL_Set2D (void); void GLSL_Set2DScaled (void); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index e8a28e40f..8006d1007 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -73,6 +73,8 @@ void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height, struct vulkan_ctx_s *ctx); void Vulkan_Draw_AddFont (struct rfont_s *font, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_FontString (int x, int y, const char *str, + struct vulkan_ctx_s *ctx); void Vulkan_Set2D (struct vulkan_ctx_s *ctx); void Vulkan_Set2DScaled (struct vulkan_ctx_s *ctx); diff --git a/include/QF/draw.h b/include/QF/draw.h index 9e0bf654e..532ea7a54 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -246,6 +246,7 @@ void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int h struct rfont_s; void Draw_AddFont (struct rfont_s *font); +void Draw_FontString (int x, int y, const char *str); ///@} diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index a8a6c418e..81365fbcd 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -105,6 +105,7 @@ typedef struct vid_render_funcs_s { void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); void (*Draw_AddFont) (struct rfont_s *font); + void (*Draw_FontString) (int x, int y, const char *str); struct psystem_s *(*ParticleSystem) (void); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 084104165..a12cdf86c 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -1023,3 +1023,8 @@ void gl_Draw_AddFont (struct rfont_s *font) { } + +void +gl_Draw_FontString (int x, int y, const char *str) +{ +} diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 707fcdcb8..dcd9b0fb7 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -846,3 +846,8 @@ void glsl_Draw_AddFont (struct rfont_s *font) { } + +void +glsl_Draw_FontString (int x, int y, const char *str) +{ +} diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 387b2989e..b8ee72019 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -346,6 +346,15 @@ bi_Font_Load (progs_t *pr, void *_res) r_funcs->Draw_AddFont (font); } +static void +bi_Font_String (progs_t *pr, void *_res) +{ + int x = P_INT (pr, 0); + int y = P_INT (pr, 1); + const char *str = P_GSTRING (pr, 2); + r_funcs->Draw_FontString (x, y, str); +} + static const char * bi_draw_get_key (const void *p, void *unused) { @@ -397,6 +406,7 @@ static builtin_t builtins[] = { bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)), bi(Font_Load, 3, p(string), p(int), p(ptr)), + bi(Font_String, 3, p(int), p(int), p(string)), {0} }; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 4a9ba34cc..671244755 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -979,3 +979,8 @@ void Draw_AddFont (struct rfont_s *font) { } + +void +Draw_FontString (int x, int y, const char *str) +{ +} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 3e165bdf7..ea8a10049 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -508,6 +508,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_Picf, gl_Draw_SubPic, gl_Draw_AddFont, + gl_Draw_FontString, gl_ParticleSystem, gl_R_Init, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 12b0425eb..2ffb0cf22 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -452,6 +452,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_Picf, glsl_Draw_SubPic, glsl_Draw_AddFont, + glsl_Draw_FontString, glsl_ParticleSystem, glsl_R_Init, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index b9bb753d1..2dc9b8a42 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -472,6 +472,7 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_Picf, Draw_SubPic, Draw_AddFont, + Draw_FontString, sw_ParticleSystem, sw_R_Init, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 85033e9c7..6519f1740 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -267,6 +267,12 @@ vulkan_Draw_AddFont (struct rfont_s *font) Vulkan_Draw_AddFont (font, vulkan_ctx); } +static void +vulkan_Draw_FontString (int x, int y, const char *str) +{ + Vulkan_Draw_FontString (x, y, str, vulkan_ctx); +} + static void vulkan_begin_frame (void) { @@ -756,6 +762,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_Picf, vulkan_Draw_SubPic, vulkan_Draw_AddFont, + vulkan_Draw_FontString, vulkan_ParticleSystem, vulkan_R_Init, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 29d93f65d..6b78a9b5d 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -972,3 +972,8 @@ Vulkan_Draw_AddFont (rfont_t *font, vulkan_ctx_t *ctx) dctx->font_tex = Vulkan_LoadTex (ctx, &tex, 0, "draw.font"); } } + +void +Vulkan_Draw_FontString (int x, int y, const char *str, vulkan_ctx_t *ctx) +{ +} From cd66dbfc9767d1b9765f4e24bfce158a8c3c7c90 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Sep 2022 14:23:19 +0900 Subject: [PATCH 2933/3664] [vulkan] Implement font rendering It is currently an ugly hack for dealing with the separate quad queue, and the pipeline handling code needs a lot of cleanup, but it works quite well, though I do plan on moving to HarfBuzz for text shaping. One nice development is I got updating of descriptor sets working (just need to ensure the set is no longer in use by the command queue, which the multiple frames in flight makes easy). --- libs/video/renderer/Makemodule.am | 5 + libs/video/renderer/vulkan/qfpipeline.plist | 17 ++- libs/video/renderer/vulkan/shader.c | 3 + .../renderer/vulkan/shader/twod_impalpha.frag | 17 +++ libs/video/renderer/vulkan/vulkan_draw.c | 140 ++++++++++++++++-- 5 files changed, 167 insertions(+), 15 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/twod_impalpha.frag diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 49e229b1a..0b525df97 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -270,6 +270,8 @@ sprite_depthv_src = $(vkshaderpath)/sprite_depth.vert sprite_depthv_c = $(vkshaderpath)/sprite_depth.vert.spvc sprite_depthf_src = $(vkshaderpath)/sprite_depth.frag sprite_depthf_c = $(vkshaderpath)/sprite_depth.frag.spvc +twod_impalpha_src = $(vkshaderpath)/twod_impalpha.frag +twod_impalpha_c = $(vkshaderpath)/twod_impalpha.frag.spvc twodv_src = $(vkshaderpath)/twod.vert twodv_c = $(vkshaderpath)/twod.vert.spvc twodf_src = $(vkshaderpath)/twod.frag @@ -334,6 +336,8 @@ $(sprite_depthv_c): $(sprite_depthv_src) $(sprite_depthf_c): $(sprite_depthf_src) +$(twod_impalpha_c): $(twod_impalpha_src) + $(twodv_c): $(twodv_src) $(twodf_c): $(twodf_src) @@ -392,6 +396,7 @@ vkshader_c = \ $(sprite_gbuff_c) \ $(sprite_depthv_c) \ $(sprite_depthf_c) \ + $(twod_impalpha_c) \ $(twodv_c) \ $(twodf_c) \ $(quakebspv_c) \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 9c78e01cb..287b48b2e 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -89,7 +89,7 @@ }; twod_pool = { flags = 0; - maxSets = $frames.size; + maxSets = "$frames.size * 2z"; bindings = ( { type = combined_image_sampler; @@ -1049,6 +1049,21 @@ }; layout = twod_layout; }; + twod_impalpha = { + @inherit = $properties.pipelines.twod; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/twod.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/twod_impalpha.frag; + }, + ); + }; lines = { @inherit = $properties.pipelines.twod; inputAssembly = $properties.inputAssembly.lines; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 0f7e19a7b..cfb62a7a8 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -57,6 +57,8 @@ static static #include "libs/video/renderer/vulkan/shader/sprite_depth.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/twod_impalpha.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/twod.vert.spvc" static #include "libs/video/renderer/vulkan/shader/twod.frag.spvc" @@ -121,6 +123,7 @@ static shaderdata_t builtin_shaders[] = { { "sprite_gbuf.frag", sprite_gbuf_frag, sizeof (sprite_gbuf_frag) }, { "sprite_depth.vert", sprite_depth_vert, sizeof (sprite_depth_vert) }, { "sprite_depth.frag", sprite_depth_frag, sizeof (sprite_depth_frag) }, + { "twod_impalpha.frag", twod_impalpha_frag, sizeof (twod_impalpha_frag) }, { "twod.vert", twod_vert, sizeof (twod_vert) }, { "twod.frag", twod_frag, sizeof (twod_frag) }, { "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) }, diff --git a/libs/video/renderer/vulkan/shader/twod_impalpha.frag b/libs/video/renderer/vulkan/shader/twod_impalpha.frag new file mode 100644 index 000000000..5f3c50865 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/twod_impalpha.frag @@ -0,0 +1,17 @@ +#version 450 + +layout (set = 1, binding = 0) uniform sampler2D Texture; + +layout (location = 0) in vec2 st; +layout (location = 1) in vec4 color; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + vec4 pix; + + pix = texture(Texture, st).rrrr; + frag_color = pix * color; +} diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 6b78a9b5d..da7f528e5 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -84,13 +84,17 @@ typedef struct cachepic_s { typedef struct drawframe_s { size_t vert_offset; + size_t iavert_offset; size_t line_offset; drawvert_t *quad_verts; + drawvert_t *iaquad_verts; drawvert_t *line_verts; uint32_t num_quads; + uint32_t num_iaquads; uint32_t num_lines; VkCommandBuffer cmd; VkDescriptorSet descriptors; + VkDescriptorSet iadescriptors; } drawframe_t; typedef struct drawframeset_s @@ -117,6 +121,7 @@ typedef struct drawctx_s { VkBuffer ind_buffer; VkDeviceMemory ind_memory; VkPipeline quad_pipeline; + VkPipeline iaquad_pipeline; VkPipeline line_pipeline; VkPipelineLayout layout; drawframeset_t frames; @@ -130,7 +135,11 @@ typedef struct drawctx_s { #define MAX_LINES (32768) #define VERTS_PER_LINE (2) -#define VERTS_PER_FRAME (MAX_LINES*VERTS_PER_LINE + MAX_QUADS*VERTS_PER_QUAD) +#define QUADS_OFFSET 0 +#define IAQUADS_OFFSET (MAX_QUADS * VERTS_PER_QUAD) +#define LINES_OFFSET (IAQUADS_OFFSET + (MAX_QUADS * VERTS_PER_QUAD)) + +#define VERTS_PER_FRAME (LINES_OFFSET + MAX_LINES*VERTS_PER_LINE) static void create_quad_buffers (vulkan_ctx_t *ctx) @@ -175,11 +184,14 @@ create_quad_buffers (vulkan_ctx_t *ctx) for (size_t f = 0; f < frames; f++) { drawframe_t *frame = &dctx->frames.a[f]; size_t ind = f * VERTS_PER_FRAME; - size_t lind = ind + MAX_QUADS * VERTS_PER_QUAD; + size_t iaind = ind + IAQUADS_OFFSET; + size_t lind = ind + LINES_OFFSET; frame->vert_offset = ind * sizeof (drawvert_t); + frame->iavert_offset = iaind; frame->line_offset = lind; frame->quad_verts = vert_data + ind; - frame->line_verts = frame->quad_verts + MAX_QUADS * VERTS_PER_QUAD; + frame->iaquad_verts = frame->quad_verts + IAQUADS_OFFSET; + frame->line_verts = frame->quad_verts + LINES_OFFSET; frame->num_quads = 0; frame->num_lines = 0; } @@ -367,6 +379,7 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) destroy_quad_buffers (ctx); dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); + dfunc->vkDestroyPipeline (device->dev, dctx->iaquad_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0); Hash_DelTable (dctx->pic_cache); delete_memsuper (dctx->pic_memsuper); @@ -433,6 +446,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); + dctx->iaquad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, + "twod_impalpha"); dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines"); dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout"); @@ -448,21 +463,32 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) QFV_ScrapImageView (dctx->scrap), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; + VkDescriptorImageInfo iaimageInfo = { + dctx->sampler, + Vulkan_TexImageView (ctx->default_magenta), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); + __auto_type iasets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 0; i < frames; i++) { __auto_type dframe = &dctx->frames.a[i]; dframe->descriptors = sets->a[i]; + dframe->iadescriptors = iasets->a[i]; VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, dframe->descriptors, 0, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo, 0, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + dframe->iadescriptors, 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &iaimageInfo, 0, 0 }, }; - dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); dframe->cmd = cmdBuffers->a[i]; QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, dframe->cmd, @@ -868,7 +894,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - if (!dframe->num_quads && !dframe->num_lines) { + if (!dframe->num_quads && !dframe->num_iaquads && !dframe->num_lines) { return; } @@ -880,6 +906,9 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, dctx->vert_memory, dframe->vert_offset, dframe->num_quads * VERTS_PER_QUAD * sizeof (drawvert_t) }, + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + dctx->vert_memory, dframe->iavert_offset, + dframe->num_iaquads * VERTS_PER_QUAD * sizeof (drawvert_t) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, dctx->vert_memory, dframe->line_offset, dframe->num_lines * VERTS_PER_LINE * sizeof (drawvert_t) }, @@ -906,33 +935,72 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets); dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, VK_INDEX_TYPE_UINT32); - VkDescriptorSet set[2] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dframe->descriptors, - }; - VkPipelineLayout layout = dctx->layout; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); if (dframe->num_quads) { + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + dframe->descriptors, + }; + VkPipelineLayout layout = dctx->layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dctx->quad_pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD, - 1, 0, 0, 0); + 1, 0, QUADS_OFFSET, 0); + } + if (dframe->num_iaquads) { + VkDescriptorImageInfo iaimageInfo = { + dctx->sampler, + Vulkan_TexImageView (dctx->font_tex), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + dframe->iadescriptors, 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &iaimageInfo, 0, 0 }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + dframe->iadescriptors, + }; + VkPipelineLayout layout = dctx->layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + dctx->iaquad_pipeline); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); + dfunc->vkCmdDrawIndexed (cmd, dframe->num_iaquads * INDS_PER_QUAD, + 1, 0, IAQUADS_OFFSET, 0); } if (dframe->num_lines) { + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + dframe->descriptors, + }; + VkPipelineLayout layout = dctx->layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dctx->line_pipeline); dfunc->vkCmdDraw (cmd, dframe->num_lines * VERTS_PER_LINE, - 1, MAX_QUADS * VERTS_PER_QUAD, 0); + 1, LINES_OFFSET, 0); } QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); dframe->num_quads = 0; + dframe->num_iaquads = 0; dframe->num_lines = 0; } @@ -976,4 +1044,48 @@ Vulkan_Draw_AddFont (rfont_t *font, vulkan_ctx_t *ctx) void Vulkan_Draw_FontString (int x, int y, const char *str, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + if (!dctx->font) { + return; + } + //FIXME ewwwwwww + drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + uint32_t num_quads = dframe->num_quads; + drawvert_t *quad_verts = dframe->quad_verts; + dframe->num_quads = dframe->num_iaquads; + dframe->quad_verts = dframe->iaquad_verts; + subpic_t glyph_subpic = { + .width = dctx->font->scrap.width, + .height = dctx->font->scrap.height, + .size = 1.0 / dctx->font->scrap.width, + }; + struct { + qpic_t pic; + subpic_t *subpic; + } glyph_pic = { + .pic = { + .width = 1, + .height = 1, + }, + .subpic = &glyph_subpic, + }; + quat_t color = { 0.5, 1, 0.6, 1 }; + for (const char *c = str; *c; c++) { + rglyph_t search = { .charcode = *c }; + rglyph_t *glyph = Hash_FindElement (dctx->font->glyphmap, &search); + if (!glyph) { + continue; + } + *((vrect_t **) &glyph_subpic.rect) = glyph->rect; + int gw = glyph->rect->width; + int gh = glyph->rect->height; + vec2i_t pos = (vec2i_t) { x, y } + glyph->bearing * (vec2i_t) { 1, -1 }; + draw_pic (pos[0], pos[1], gw, gh, &glyph_pic.pic, + 0, 0, gw, gh, color, dframe); + x += glyph->advance / 64; + } + dframe->num_iaquads = dframe->num_quads; + dframe->iaquad_verts = dframe->quad_verts; + dframe->num_quads = num_quads; + dframe->quad_verts = quad_verts; } From 28e9a0a9ba250bc3c029f25716c2d45a30ff18db Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Sep 2022 17:47:27 +0900 Subject: [PATCH 2934/3664] [ui] Add a specialized function for subrect allocation While VRect_Difference worked for subrect allocation, it wasn't ideal as it tended to produce a lot of long, narrow strips that were difficult to reuse and thus wasted a lot of the super-rectangle's area. This is because it always does horizontal splits first. However, rewriting VRect_Difference didn't seem to be the best option. VRect_SubRect (the new function) takes only width and height, and splits the given rectangle such that if there are two off-cuts, they will be both the minimum and maximum possible area. This does seem to make for much better utilization of the available area. It's also faster as it does only the two splits, rather than four. --- include/QF/ui/vrect.h | 23 +++++++++++++++++++++++ libs/ui/vrect.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/include/QF/ui/vrect.h b/include/QF/ui/vrect.h index 64d3b6302..c05bc51f9 100644 --- a/include/QF/ui/vrect.h +++ b/include/QF/ui/vrect.h @@ -165,4 +165,27 @@ vrect_t *VRect_Union (const vrect_t *r1, const vrect_t *r2); */ vrect_t *VRect_Merge (const vrect_t *r1, const vrect_t *r2); +/** Return up to three rectangles resulting from carving out the upper-left + rectangle of the specified width and height. + + The first rectangle in the list will be the part of the supplied rectangle + that is covered by \a width and \a height (if either parameter is larger + than the supplied rectangle, then the returned rectangle will have the same + size as the supplied rectangle in that dimension). The other rectangles, + if there are any, will be the remainder of the supplied rectangle such that + the areas are min-max (to avoid creating long narrow rectangles). + + \param rect The rectangle to carve. + \param width Width of the sub-rectangle carved from \a rect. + \param height Height of the sub-rectangle carved from \a rect. + \return The carved-out sub-rectangle, plus up to two rectangles + representing the remainder of \a rect, with splits such + that the two rectangles are both minimum and maximum area. + The larger of the two remainder rectangles will allways be + last. + \note It is the caller's responsibility to delete the returned + rectangles. +*/ +vrect_t *VRect_SubRect (const vrect_t *rect, int width, int height); + #endif//__QF_ui_vrect_h diff --git a/libs/ui/vrect.c b/libs/ui/vrect.c index cbfe72595..f9ff47763 100644 --- a/libs/ui/vrect.c +++ b/libs/ui/vrect.c @@ -258,3 +258,44 @@ cleanup: } return 0; } + +VISIBLE vrect_t * +VRect_SubRect (const vrect_t *rect, int width, int height) +{ + if (width > rect->width) { + width = rect->width; + } + if (height > rect->height) { + height = rect->height; + } + int a = rect->height - height; + int b = rect->width - width; + vrect_t *r, *s; + if (b * height > a * width) { + // a horizontal cut produces a larger off-cut rectangle than a vertical + // cut, so do a vertical cut first so the off-cut is as small as + // possible + r = VRect_VSplit (rect, rect->x + width); + if (VRect_IsEmpty (r->next)) { + VRect_Delete (r->next); + r->next = 0; + } + s = VRect_HSplit (r, r->y + height); + } else { + r = VRect_HSplit (rect, rect->y + height); + if (VRect_IsEmpty (r->next)) { + VRect_Delete (r->next); + r->next = 0; + } + s = VRect_VSplit (r, r->x + width); + } + + if (VRect_IsEmpty (s->next)) { + VRect_Delete (s->next); + s->next = r->next; + } else { + s->next->next = r->next; + } + VRect_Delete (r); + return s; +} From db69f5fd23bfb32a01cf2bfb7b786cd3b820f4e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Sep 2022 19:08:58 +0900 Subject: [PATCH 2935/3664] [renderer] Use VRect_SubRect for scrap allocation While the results are a little surprising (tends to alternate between left side and top for allocations), there is much less wasted space in the partially allocated regions, and the main free region seems to always be quite big. --- libs/video/renderer/r_scrap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/r_scrap.c b/libs/video/renderer/r_scrap.c index 8d01ee175..5165cb35b 100644 --- a/libs/video/renderer/r_scrap.c +++ b/libs/video/renderer/r_scrap.c @@ -90,8 +90,8 @@ R_ScrapAlloc (rscrap_t *scrap, int width, int height) return 0; // couldn't find a spot old = *best; *best = old->next; - rect = VRect_New (old->x, old->y, width, height); - frags = VRect_Difference (old, rect); + rect = VRect_SubRect (old, width, height); + frags = rect->next; VRect_Delete (old); if (frags) { // old was bigger than the requested size From 935e883d8d461a88d8c2a8f36f84c2e6f4263e40 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Sep 2022 20:56:38 +0900 Subject: [PATCH 2936/3664] [renderer] Switch to using HarfBuzz for glyph positioning This means that QF should support more exotic fonts without any issue (once the rest of the text handling system is up to snuff) as HarfBuzz does all the hard work of handling OpenType, Graphite, etc text shaping, including kerning (when enabled). Also, font loading now loads all the glyphs into the atlas (preload is gone). --- Makefile.am | 2 +- config.d/freetype.m4 | 17 ++++ include/Makemodule.am | 2 + include/r_font.h | 9 +- include/r_text.h | 73 +++++++++++++++ libs/video/renderer/Makemodule.am | 4 +- libs/video/renderer/r_font.c | 94 ++++--------------- libs/video/renderer/r_progs.c | 5 +- libs/video/renderer/r_text.c | 113 +++++++++++++++++++++++ libs/video/renderer/vulkan/vulkan_draw.c | 54 +++++++---- 10 files changed, 268 insertions(+), 105 deletions(-) create mode 100644 include/r_text.h create mode 100644 libs/video/renderer/r_text.c diff --git a/Makefile.am b/Makefile.am index 194fcd984..e3c3933cd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,7 @@ NOCONV_DIST= \ BUILT_SOURCES = $(top_srcdir)/.version #AM_CFLAGS= @PREFER_NON_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) $(FREETYPE_CFLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) $(FREETYPE_CFLAGS) $(HARFBUZZ_CFLAGS) common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@ diff --git a/config.d/freetype.m4 b/config.d/freetype.m4 index 7f13bf1ee..38618e5d0 100644 --- a/config.d/freetype.m4 +++ b/config.d/freetype.m4 @@ -13,3 +13,20 @@ AC_SUBST(FREETYPE_LIBS) if test "x$HAVE_FREETYPE" == "xyes"; then AC_DEFINE(HAVE_FREETYPE, 1, [Define if you have the freetype library]) fi + + +AC_ARG_ENABLE(harfbuzz, + AS_HELP_STRING([--disable-harfbuzz], [disable HarfBuzz support])) +if test "x$enable_harfbuzz" != "xno"; then + if test "x$PKG_CONFIG" != "x"; then + PKG_CHECK_MODULES([HARFBUZZ], [harfbuzz], HAVE_HARFBUZZ=yes, HAVE_HARFBUZZ=no) + fi +else + HAVE_HARFBUZZ=no + HARFBUZZ_LIBS= +fi +AC_SUBST(HARFBUZZ_LIBS) + +if test "x$HAVE_HARFBUZZ" == "xyes"; then + AC_DEFINE(HAVE_HARFBUZZ, 1, [Define if you have the HarfBuzz library]) +fi diff --git a/include/Makemodule.am b/include/Makemodule.am index 1a5ba7216..b5ab8df07 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -61,10 +61,12 @@ EXTRA_DIST += \ include/quicksort.h \ include/r_cvar.h \ include/r_dynamic.h \ + include/r_font.h \ include/r_internal.h \ include/r_local.h \ include/r_scrap.h \ include/r_shared.h \ + include/r_text.h \ include/regex.h \ include/rua_internal.h \ include/sbar.h \ diff --git a/include/r_font.h b/include/r_font.h index a27281b5d..dd47e358c 100644 --- a/include/r_font.h +++ b/include/r_font.h @@ -34,9 +34,6 @@ #include #include FT_FREETYPE_H -#include "QF/hash.h" -#include "QF/progs.h" //FIXME for PR_RESMAP - #include "QF/ui/vrect.h" #include "QF/simd/types.h" @@ -55,12 +52,12 @@ typedef struct rfont_s { FT_Face face; rscrap_t scrap; byte *scrap_bitmap; - hashtab_t *glyphmap; - PR_RESMAP(rglyph_t) glyphs; + FT_Long num_glyphs; + rglyph_t *glyphs; } rfont_t; void R_FontInit (void); void R_FontFree (rfont_t *font); -rfont_t *R_FontLoad (QFile *font_file, int size, const int *preload); +rfont_t *R_FontLoad (QFile *font_file, int size); #endif//__r_font_h diff --git a/include/r_text.h b/include/r_text.h new file mode 100644 index 000000000..2052b9950 --- /dev/null +++ b/include/r_text.h @@ -0,0 +1,73 @@ +/* + r_text.h + + Renderer text management + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/9/4 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __r_text_h +#define __r_text_h + +#include +#include + +#include "QF/darray.h" + +typedef struct rtext_s { + const char *text; + const char *language; + hb_script_t script; + hb_direction_t direction; +} rtext_t; + +typedef struct r_hb_featureset_s DARRAY_TYPE (hb_feature_t) r_hb_featureset_t; + +struct rfont_s; +struct rglyph_s; +typedef void rtext_render_t (struct rglyph_s *glyph, int x, int y, void *data); + +typedef struct rshaper_s { + struct rfont_s *rfont; + hb_font_t *font; + hb_buffer_t *buffer; + r_hb_featureset_t features; +} rshaper_t; + +extern hb_feature_t LiagureOff; +extern hb_feature_t LiagureOn; +extern hb_feature_t KerningOff; +extern hb_feature_t KerningOn; +extern hb_feature_t CligOff; +extern hb_feature_t CligOn; + +rshaper_t *RText_NewShaper (struct rfont_s *font); +void RText_DeleteShaper (rshaper_t *shaper); +void RText_AddFeature (rshaper_t *shaper, hb_feature_t feature); +void RText_ShapeText (rshaper_t *shaper, rtext_t *text); +void RText_RenderText (rshaper_t *shaper, rtext_t *text, int x, int y, + rtext_render_t *render, void *data); + +#endif//__r_text_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 0b525df97..c611cd7fe 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -33,12 +33,14 @@ video_renderer_common_sources = \ libs/video/renderer/r_font.c \ libs/video/renderer/r_iqm.c \ libs/video/renderer/r_sprite.c \ + libs/video/renderer/r_text.c \ libs/video/renderer/vid_common.c renderer_libs= \ @vid_render_static_plugin_libs@ \ libs/util/libQFutil.la \ - $(FREETYPE_LIBS) + $(FREETYPE_LIBS) \ + $(HARFBUZZ_LIBS) libs_video_renderer_libQFrenderer_la_LDFLAGS= @STATIC@ libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libs) diff --git a/libs/video/renderer/r_font.c b/libs/video/renderer/r_font.c index fb053dcda..e7c0ddf52 100644 --- a/libs/video/renderer/r_font.c +++ b/libs/video/renderer/r_font.c @@ -42,35 +42,8 @@ static FT_Library ft; -static uintptr_t -glyph_get_hash (const void *_glyph, void *unused) -{ - __auto_type glyph = (const rglyph_t *) _glyph; - return glyph->charcode; -} - -static int -glyph_compare (const void *_a, const void *_b, void *unused) -{ - __auto_type a = (const rglyph_t *) _a; - __auto_type b = (const rglyph_t *) _b; - return a->charcode == b->charcode; -} - -static rglyph_t * -alloc_glyph (rfont_t *font) -{ - return PR_RESNEW(font->glyphs); -} - static void -free_glyph (rfont_t *font, rglyph_t *glyph) -{ - PR_RESFREE (font->glyphs, glyph); -} - -static void -copy_glypn (rglyph_t *glyph, FT_GlyphSlot src_glyph) +copy_glyph (rglyph_t *glyph, FT_GlyphSlot src_glyph) { int dst_pitch = glyph->font->scrap.width; byte *dst = glyph->font->scrap_bitmap + glyph->rect->x + glyph->rect->y * dst_pitch; @@ -84,14 +57,6 @@ copy_glypn (rglyph_t *glyph, FT_GlyphSlot src_glyph) } } -static void -glyphmap_free_glyph (void *_g, void *_f) -{ - rglyph_t *glyph = _g; - rfont_t *font = _f; - free_glyph (font, glyph); -} - VISIBLE void R_FontInit (void) { @@ -106,19 +71,17 @@ R_FontFree (rfont_t *font) if (font->face) { FT_Done_Face (font->face); } - if (font->glyphmap) { - Hash_DelTable (font->glyphmap); - } if (font->scrap.rects || font->scrap.free_rects) { R_ScrapDelete (&font->scrap); } + free (font->glyphs); free (font->scrap_bitmap); free (font->font_resource); free (font); } VISIBLE rfont_t * -R_FontLoad (QFile *font_file, int size, const int *preload) +R_FontLoad (QFile *font_file, int size) { byte *font_data = QFS_LoadFile (font_file, 0); if (!font_data) { @@ -132,54 +95,35 @@ R_FontLoad (QFile *font_file, int size, const int *preload) return 0; } - font->glyphmap = Hash_NewTable (0x10000, 0, glyphmap_free_glyph, font, 0); - Hash_SetHashCompare (font->glyphmap, glyph_get_hash, glyph_compare); - FT_Set_Pixel_Sizes(font->face, 0, size); int pixels = 0; - for (const int *c = preload; *c; c++) { - rglyph_t search = { .charcode = *c }; - rglyph_t *glyph = Hash_FindElement (font->glyphmap, &search); - if (glyph) { - continue; - } - if (FT_Load_Char(font->face, *c, FT_LOAD_DEFAULT)) { - continue; - } + for (FT_Long gind = 0; gind < font->face->num_glyphs; gind++) { + FT_Load_Glyph (font->face, gind, FT_LOAD_DEFAULT); + __auto_type g = font->face->glyph; pixels += g->bitmap.width * g->bitmap.rows; - - glyph = alloc_glyph (font); - glyph->charcode = *c; - Hash_AddElement (font->glyphmap, glyph); } - Hash_FlushTable (font->glyphmap); pixels = sqrt (2 * pixels); pixels = BITOP_RUP (pixels); R_ScrapInit (&font->scrap, pixels, pixels); font->scrap_bitmap = calloc (1, pixels * pixels); + font->num_glyphs = font->face->num_glyphs; + font->glyphs = malloc (font->num_glyphs * sizeof (rglyph_t)); - for (const int *c = preload; *c; c++) { - rglyph_t search = { .charcode = *c }; - rglyph_t *glyph = Hash_FindElement (font->glyphmap, &search); - if (glyph) { - continue; - } - if (FT_Load_Char(font->face, *c, FT_LOAD_RENDER)) { - continue; - } - __auto_type g = font->face->glyph; - int width = g->bitmap.width; - int height = g->bitmap.rows; - glyph = alloc_glyph (font); + for (FT_Long gind = 0; gind < font->face->num_glyphs; gind++) { + rglyph_t *glyph = &font->glyphs[gind]; + FT_Load_Glyph (font->face, gind, FT_LOAD_DEFAULT); + __auto_type slot = font->face->glyph; + FT_Render_Glyph (slot, FT_RENDER_MODE_NORMAL); + int width = slot->bitmap.width; + int height = slot->bitmap.rows; glyph->font = font; glyph->rect = R_ScrapAlloc (&font->scrap, width, height); - glyph->bearing = (vec2i_t) { g->bitmap_left, g->bitmap_top }; - glyph->advance = g->advance.x; - glyph->charcode = *c; - Hash_AddElement (font->glyphmap, glyph); + glyph->bearing = (vec2i_t) { slot->bitmap_left, slot->bitmap_top }; + glyph->advance = slot->advance.x; + glyph->charcode = gind; - copy_glypn (glyph, g); + copy_glyph (glyph, slot); } return font; diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index b8ee72019..95f199242 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -339,10 +339,9 @@ bi_Font_Load (progs_t *pr, void *_res) { const char *font_path = P_GSTRING (pr, 0); int font_size = P_INT (pr, 1); - int *preload = (int *) P_GPOINTER (pr, 2); QFile *font_file = QFS_FOpenFile (font_path); - rfont_t *font = R_FontLoad (font_file, font_size, preload); + rfont_t *font = R_FontLoad (font_file, font_size); r_funcs->Draw_AddFont (font); } @@ -405,7 +404,7 @@ static builtin_t builtins[] = { bi(Draw_Line, 5, p(int), p(int), p(int), p(int), p(int)), bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)), - bi(Font_Load, 3, p(string), p(int), p(ptr)), + bi(Font_Load, 2, p(string), p(int)), bi(Font_String, 3, p(int), p(int), p(string)), {0} }; diff --git a/libs/video/renderer/r_text.c b/libs/video/renderer/r_text.c new file mode 100644 index 000000000..f86994670 --- /dev/null +++ b/libs/video/renderer/r_text.c @@ -0,0 +1,113 @@ +/* + r_font.c + + Renderer font management management + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/8/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/quakefs.h" +#include "QF/sys.h" + +#include "r_font.h" +#include "r_text.h" + +#include "compat.h" + +rshaper_t * +RText_NewShaper (rfont_t *font) +{ + rshaper_t *shaper = malloc (sizeof (rshaper_t)); + shaper->rfont = font; + shaper->font = hb_ft_font_create (font->face, 0); + shaper->buffer = hb_buffer_create (); + shaper->features = (r_hb_featureset_t) DARRAY_STATIC_INIT (4); + + hb_buffer_allocation_successful (shaper->buffer); + return shaper; +} + +void +RText_DeleteShaper (rshaper_t *shaper) +{ + hb_buffer_destroy (shaper->buffer); + hb_font_destroy (shaper->font); + DARRAY_CLEAR (&shaper->features); + free (shaper); +} + +void +RText_AddFeature (rshaper_t *shaper, hb_feature_t feature) +{ + DARRAY_APPEND (&shaper->features, feature); +} + +void +RText_ShapeText (rshaper_t *shaper, rtext_t *text) +{ + hb_buffer_reset (shaper->buffer); + hb_buffer_set_direction (shaper->buffer, text->direction); + hb_buffer_set_script (shaper->buffer, text->script); + const char *lang = text->language; + hb_buffer_set_language (shaper->buffer, + hb_language_from_string (lang, strlen (lang))); + size_t length = strlen (text->text); + hb_buffer_add_utf8 (shaper->buffer, text->text, length, 0, length); + + hb_shape (shaper->font, shaper->buffer, + shaper->features.a, shaper->features.size); +} + +void +RText_RenderText (rshaper_t *shaper, rtext_t *text, int x, int y, + rtext_render_t *render, void *data) +{ + RText_ShapeText (shaper, text); + + unsigned count; + __auto_type glyphInfo = hb_buffer_get_glyph_infos (shaper->buffer, &count); + __auto_type glyphPos = hb_buffer_get_glyph_positions (shaper->buffer, + &count); + + rfont_t *font = shaper->rfont; + for (unsigned i = 0; i < count; i++) { + rglyph_t *glyph = &font->glyphs[glyphInfo[i].codepoint]; + + int xp = x + glyphPos[i].x_offset / 64; + int yp = y + glyphPos[i].y_offset / 64; + int xa = glyphPos[i].x_advance / 64; + int ya = glyphPos[i].y_advance / 64; + + xp += glyph->bearing[0]; + yp -= glyph->bearing[1]; + render (glyph, xp, yp, data); + x += xa; + y += ya; + } +} diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index da7f528e5..806d66def 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -68,6 +68,7 @@ #include "QF/ui/view.h" #include "r_font.h" +#include "r_text.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -1041,6 +1042,25 @@ Vulkan_Draw_AddFont (rfont_t *font, vulkan_ctx_t *ctx) } } +typedef struct { + drawframe_t *dframe; + qpic_t pic; + subpic_t *subpic; + quat_t color; +} rgctx_t; + +static void +vulkan_render_glyph (rglyph_t *glyph, int x, int y, void *_rgctx) +{ + rgctx_t *rgctx = _rgctx; + + *((vrect_t **) &rgctx->subpic->rect) = glyph->rect; + int gw = glyph->rect->width; + int gh = glyph->rect->height; + draw_pic (x, y, gw, gh, &rgctx->pic, 0, 0, gw, gh, rgctx->color, + rgctx->dframe); +} + void Vulkan_Draw_FontString (int x, int y, const char *str, vulkan_ctx_t *ctx) { @@ -1054,36 +1074,32 @@ Vulkan_Draw_FontString (int x, int y, const char *str, vulkan_ctx_t *ctx) drawvert_t *quad_verts = dframe->quad_verts; dframe->num_quads = dframe->num_iaquads; dframe->quad_verts = dframe->iaquad_verts; + subpic_t glyph_subpic = { .width = dctx->font->scrap.width, .height = dctx->font->scrap.height, .size = 1.0 / dctx->font->scrap.width, }; - struct { - qpic_t pic; - subpic_t *subpic; - } glyph_pic = { + rgctx_t rgctx = { + .dframe = dframe, .pic = { .width = 1, .height = 1, }, .subpic = &glyph_subpic, + .color = { 0.5, 1, 0.6, 1 }, }; - quat_t color = { 0.5, 1, 0.6, 1 }; - for (const char *c = str; *c; c++) { - rglyph_t search = { .charcode = *c }; - rglyph_t *glyph = Hash_FindElement (dctx->font->glyphmap, &search); - if (!glyph) { - continue; - } - *((vrect_t **) &glyph_subpic.rect) = glyph->rect; - int gw = glyph->rect->width; - int gh = glyph->rect->height; - vec2i_t pos = (vec2i_t) { x, y } + glyph->bearing * (vec2i_t) { 1, -1 }; - draw_pic (pos[0], pos[1], gw, gh, &glyph_pic.pic, - 0, 0, gw, gh, color, dframe); - x += glyph->advance / 64; - } + rtext_t text = { + .text = str, + .language = "en", + .script = HB_SCRIPT_LATIN, + .direction = HB_DIRECTION_LTR, + }; + + rshaper_t *shaper = RText_NewShaper (dctx->font); + RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx); + RText_DeleteShaper (shaper); + dframe->num_iaquads = dframe->num_quads; dframe->iaquad_verts = dframe->quad_verts; dframe->num_quads = num_quads; From 1f9553d13e7480d75599269d82213cfcae24409f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Sep 2022 23:15:58 +0900 Subject: [PATCH 2937/3664] [qfcc] Add support for \uXXXX and \UXXXXXXXX The resultant unicode is encoded as utf-8, which does conflict with the quake character map, but right now unicode is useful only with font text, and those support only standard unicode (currently only as utf-8), but something will need to be sorted out. --- tools/qfcc/source/strpool.c | 46 ++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index fa30c74d5..7d773a9d7 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -43,6 +43,7 @@ #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/msg.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/options.h" @@ -161,11 +162,16 @@ save_cwd (void) const char * make_string (char *token, char **end) { - char s[2]; + char s[7]; // utf8 needs 6 + nul + sizebuf_t utf8str = { + .maxsize = sizeof (s), + .data = (byte *) s, + }; int c; int i; int mask; int boldnext; + int unicount; int quote; static dstring_t *str; @@ -177,6 +183,7 @@ make_string (char *token, char **end) mask = 0x00; boldnext = 0; + unicount = 0; quote = *token++; do { @@ -252,7 +259,33 @@ make_string (char *token, char **end) } if (!*token) error (0, "EOF inside quote"); - c ^= mask; + c ^= mask; // cancel mask below + break; + case 'U': + unicount += 4; + case 'u': + unicount += 4; + boldnext = 0; + c = 0; + while (unicount && *token + && isxdigit ((unsigned char)*token)) { + c *= 16; + if (*token <= '9') + c += *token - '0'; + else if (*token <= 'F') + c += *token - 'A' + 10; + else + c += *token - 'a' + 10; + token++; + --unicount; + } + if (!*token) { + error (0, "EOF inside quote"); + } else if (unicount) { + error (0, "incomplete unicode sequence: %x %d", c, unicount); + } + unicount = 1; // signal need to encode to utf8 + c ^= mask; // cancel mask below break; case 'a': boldnext = 0; @@ -371,7 +404,14 @@ make_string (char *token, char **end) c = c ^ 0x80; boldnext = 0; c = c ^ mask; - s[0] = c; + if (unicount) { + SZ_Clear (&utf8str); + MSG_WriteUTF8 (&utf8str, c); + MSG_WriteByte (&utf8str, 0); // nul-terminate string + unicount = 0; + } else { + s[0] = c; + } dstring_appendstr (str, s); } while (1); From 6db44afedce647023008bf7156cb99a82bc378e3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 09:27:36 +0900 Subject: [PATCH 2938/3664] [gamecode] Add optional support for %@ strings If no handler has been registered, then the corresponding parameter is printed as a pointer but with surrounding brackets (eg, [0xfc48]). This will allow the ruamoko runtime to implement object printing. --- include/QF/progs.h | 26 ++++++++++++++++++++++++++ libs/gamecode/pr_strings.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 233659dd2..76b8e0000 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1628,6 +1628,32 @@ void PR_FreeString (progs_t *pr, pr_string_t str); */ void PR_FreeTempStrings (progs_t *pr); +/** Callback for handling %@ in PR_Sprintf format strings. + + \param pr pointer to ::progs_t VM struct + \param at_param Parameter to be converted to a string. Usually a progs + pointer value. It is the callee's responsibility to + interpret the value as a pointer. + \param data User data pointer as passed to PR_Sprintf_SetAtHandler + \return String to be printed in place of %@ +*/ +typedef const char *(*prstr_at_handler_t) (progs_t *pr, pr_ptr_t at_param, + void *data); + +/** Set the at_handler callback and its user data pointer. + + The at_handler callback defaults to null resulting in [ptr] in the output + string. Setting the callback allows the at_handler to interpret the value + (nominally pr_ptr_t, but always a 32-bit value) as it chooses. + + \param pr pointer to ::progs_t VM struct + \param at_handler Function pointer for callback to interpret the parameter + corresponding to the %@ format specifier. + \param data User data pointer, passed to \a at_handler. +*/ +void PR_Sprintf_SetAtHandler (progs_t *pr, prstr_at_handler_t at_handler, + void *data); + /** Formatted printing similar to C's vsprintf, but using QC types. The format string is a string of characters (other than \c \%) to be printed that includes optional format specifiers, one for each arg to be diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 840e82662..d4f423c4e 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -90,6 +90,8 @@ typedef struct prstr_resources_s { int num_strings; fmt_item_t *free_fmt_items; dstring_t *print_str; + prstr_at_handler_t at_handler; + void *at_handler_data; } prstr_resources_t; typedef enum { @@ -866,6 +868,8 @@ typedef struct fmt_state_s { fmt_item_t *fmt_items; fmt_item_t **fi; int fmt_count; + prstr_at_handler_t at_handler; + void *at_handler_data; } fmt_state_t; static inline void @@ -1052,6 +1056,25 @@ fmt_state_conversion (fmt_state_t *state) switch ((conv = *state->c++)) { case '@': // object + pr_ptr_t at_param = P_UINT (pr, state->fmt_count); + if (state->at_handler) { + const char *at_str = state->at_handler (pr, at_param, + state->at_handler_data); + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = at_str; + } else { + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = "["; + fmt_append_item (state); + + (*state->fi)->flags |= FMT_ALTFORM; + (*state->fi)->type = 'x'; + (*state->fi)->data.uint_var = at_param; + fmt_append_item (state); + + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = "]"; + } state->fmt_count++; fmt_append_item (state); break; @@ -1200,6 +1223,15 @@ fmt_state_format (fmt_state_t *state) } ///@} +VISIBLE void +PR_Sprintf_SetAtHandler (progs_t *pr, prstr_at_handler_t at_handler, + void *data) +{ + prstr_resources_t *res = pr->pr_string_resources; + res->at_handler = at_handler; + res->at_handler_data = data; +} + VISIBLE void PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, const char *format, int count, pr_type_t **args) @@ -1214,6 +1246,8 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, *state.fi = new_fmt_item (res); state.c = format; state.state = fmt_state_format; + state.at_handler = res->at_handler; + state.at_handler_data = res->at_handler_data; if (!name) name = "PR_Sprintf"; From 54bd8f5a0291e92d2c85dd27a817c276a8c1658b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 13:51:42 +0900 Subject: [PATCH 2939/3664] [ruamoko] Implement %@ handing in the ruamoko runtime -describe is sent to the object, and the returned string passed back. There is a worry about the lifetime of the returned string as there's currently no way of both ensuring it doesn't get freed prematurely and ensuring it does eventually get freed. --- libs/ruamoko/rua_obj.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index ee5555e96..1d0872798 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1314,7 +1314,7 @@ rua___obj_forward (progs_t *pr, void *data) pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 1); pr_sel_t *fwd_sel = probj->forward_selector; pr_sel_t *err_sel; - pr_class_t *class =&G_STRUCT (pr, pr_class_t, obj->class_pointer); + pr_class_t *class = &G_STRUCT (pr, pr_class_t, obj->class_pointer); pr_func_t imp; if (!fwd_sel) { @@ -1444,6 +1444,28 @@ rua_obj_set_error_handler (progs_t *pr, void *data) PR_RunError (pr, "%s, not implemented", __FUNCTION__); } +static const char * +rua_at_handler (progs_t *pr, pr_ptr_t at_param, void *_probj) +{ + probj_t *probj = _probj; + pr_id_t *obj = &G_STRUCT (pr, pr_id_t, at_param); + pr_class_t *class = &G_STRUCT (pr, pr_class_t, obj->class_pointer); + //FIXME sel_register_typed_name is really not the way to go about + //looking for a selector by name + pr_sel_t *describe_sel=sel_register_typed_name (probj, "describe", "", 0); + pr_func_t imp = get_imp (probj, class, describe_sel); + + PR_PushFrame (pr); + PR_RESET_PARAMS (pr); + P_POINTER (pr, 0) = at_param; + P_POINTER (pr, 1) = PR_SetPointer (pr, describe_sel); + pr->pr_argc = 2; + PR_ExecuteProgram (pr, imp); + PR_PopFrame (pr); + //FIXME the lifetime of the string may be a problem + return PR_GetString (pr, R_STRING (pr)); +} + static void rua_obj_msg_lookup (progs_t *pr, void *data) { @@ -2328,6 +2350,8 @@ RUA_Obj_Init (progs_t *pr, int secure) Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, load_methods_compare); + PR_Sprintf_SetAtHandler (pr, rua_at_handler, probj); + PR_Resources_Register (pr, "RUA_ObjectiveQuakeC", probj, rua_obj_cleanup, rua_obj_destroy); PR_RegisterBuiltins (pr, obj_methods, probj); From b298bf6dcb305847919e9d88efe254e769f403d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 14:03:30 +0900 Subject: [PATCH 2940/3664] [ruamoko] Implement default -describe method on Object It returns [classname@address], which is probably a reasonable default. --- ruamoko/lib/Object.r | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index 711721d1d..83ed07755 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -1,5 +1,6 @@ #include #include +#include static void link__obj_forward (void) { @@ -367,4 +368,9 @@ typedef void arIMP(id, SEL, id); return self; } +- (string) describe +{ + return sprintf ("[%s@%p]", object_get_class_name (self), self); +} + @end From 53d86e2a5309c7bd50cc52158229b0b4340b6171 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 Aug 2022 17:42:08 +0900 Subject: [PATCH 2941/3664] [qfcc] Don't check parameter size for arrays Arrays are passed as a pointer to the first element, so are always valid parameters. Fixes a bogus "formal parameter N is too large to be passed by value" error. --- tools/qfcc/source/expr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index b112d7296..1fc1249d3 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2081,7 +2081,7 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params) err = error (e, "type of formal parameter %d is incomplete", i + 1); } - if (value_too_large (t)) { + if (!is_array (t) && value_too_large (t)) { err = error (e, "formal parameter %d is too large to be passed by" " value", i + 1); } From 5ae782bf89297b482739cb568f8c20774a5a8860 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Sep 2022 23:15:58 +0900 Subject: [PATCH 2942/3664] [qfcc] Add support for \uXXXX and \UXXXXXXXX The resultant unicode is encoded as utf-8, which does conflict with the quake character map, but right now unicode is useful only with font text, and those support only standard unicode (currently only as utf-8), but something will need to be sorted out. --- tools/qfcc/source/strpool.c | 46 ++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index fa30c74d5..7d773a9d7 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -43,6 +43,7 @@ #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/msg.h" #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/options.h" @@ -161,11 +162,16 @@ save_cwd (void) const char * make_string (char *token, char **end) { - char s[2]; + char s[7]; // utf8 needs 6 + nul + sizebuf_t utf8str = { + .maxsize = sizeof (s), + .data = (byte *) s, + }; int c; int i; int mask; int boldnext; + int unicount; int quote; static dstring_t *str; @@ -177,6 +183,7 @@ make_string (char *token, char **end) mask = 0x00; boldnext = 0; + unicount = 0; quote = *token++; do { @@ -252,7 +259,33 @@ make_string (char *token, char **end) } if (!*token) error (0, "EOF inside quote"); - c ^= mask; + c ^= mask; // cancel mask below + break; + case 'U': + unicount += 4; + case 'u': + unicount += 4; + boldnext = 0; + c = 0; + while (unicount && *token + && isxdigit ((unsigned char)*token)) { + c *= 16; + if (*token <= '9') + c += *token - '0'; + else if (*token <= 'F') + c += *token - 'A' + 10; + else + c += *token - 'a' + 10; + token++; + --unicount; + } + if (!*token) { + error (0, "EOF inside quote"); + } else if (unicount) { + error (0, "incomplete unicode sequence: %x %d", c, unicount); + } + unicount = 1; // signal need to encode to utf8 + c ^= mask; // cancel mask below break; case 'a': boldnext = 0; @@ -371,7 +404,14 @@ make_string (char *token, char **end) c = c ^ 0x80; boldnext = 0; c = c ^ mask; - s[0] = c; + if (unicount) { + SZ_Clear (&utf8str); + MSG_WriteUTF8 (&utf8str, c); + MSG_WriteByte (&utf8str, 0); // nul-terminate string + unicount = 0; + } else { + s[0] = c; + } dstring_appendstr (str, s); } while (1); From be447fc9d6e1929fe7aecb399f64122ccb854527 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 09:27:36 +0900 Subject: [PATCH 2943/3664] [gamecode] Add optional support for %@ strings If no handler has been registered, then the corresponding parameter is printed as a pointer but with surrounding brackets (eg, [0xfc48]). This will allow the ruamoko runtime to implement object printing. --- include/QF/progs.h | 26 ++++++++++++++++++++++++++ libs/gamecode/pr_strings.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 233659dd2..76b8e0000 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1628,6 +1628,32 @@ void PR_FreeString (progs_t *pr, pr_string_t str); */ void PR_FreeTempStrings (progs_t *pr); +/** Callback for handling %@ in PR_Sprintf format strings. + + \param pr pointer to ::progs_t VM struct + \param at_param Parameter to be converted to a string. Usually a progs + pointer value. It is the callee's responsibility to + interpret the value as a pointer. + \param data User data pointer as passed to PR_Sprintf_SetAtHandler + \return String to be printed in place of %@ +*/ +typedef const char *(*prstr_at_handler_t) (progs_t *pr, pr_ptr_t at_param, + void *data); + +/** Set the at_handler callback and its user data pointer. + + The at_handler callback defaults to null resulting in [ptr] in the output + string. Setting the callback allows the at_handler to interpret the value + (nominally pr_ptr_t, but always a 32-bit value) as it chooses. + + \param pr pointer to ::progs_t VM struct + \param at_handler Function pointer for callback to interpret the parameter + corresponding to the %@ format specifier. + \param data User data pointer, passed to \a at_handler. +*/ +void PR_Sprintf_SetAtHandler (progs_t *pr, prstr_at_handler_t at_handler, + void *data); + /** Formatted printing similar to C's vsprintf, but using QC types. The format string is a string of characters (other than \c \%) to be printed that includes optional format specifiers, one for each arg to be diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 840e82662..d4f423c4e 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -90,6 +90,8 @@ typedef struct prstr_resources_s { int num_strings; fmt_item_t *free_fmt_items; dstring_t *print_str; + prstr_at_handler_t at_handler; + void *at_handler_data; } prstr_resources_t; typedef enum { @@ -866,6 +868,8 @@ typedef struct fmt_state_s { fmt_item_t *fmt_items; fmt_item_t **fi; int fmt_count; + prstr_at_handler_t at_handler; + void *at_handler_data; } fmt_state_t; static inline void @@ -1052,6 +1056,25 @@ fmt_state_conversion (fmt_state_t *state) switch ((conv = *state->c++)) { case '@': // object + pr_ptr_t at_param = P_UINT (pr, state->fmt_count); + if (state->at_handler) { + const char *at_str = state->at_handler (pr, at_param, + state->at_handler_data); + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = at_str; + } else { + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = "["; + fmt_append_item (state); + + (*state->fi)->flags |= FMT_ALTFORM; + (*state->fi)->type = 'x'; + (*state->fi)->data.uint_var = at_param; + fmt_append_item (state); + + (*state->fi)->type = 's'; + (*state->fi)->data.string_var = "]"; + } state->fmt_count++; fmt_append_item (state); break; @@ -1200,6 +1223,15 @@ fmt_state_format (fmt_state_t *state) } ///@} +VISIBLE void +PR_Sprintf_SetAtHandler (progs_t *pr, prstr_at_handler_t at_handler, + void *data) +{ + prstr_resources_t *res = pr->pr_string_resources; + res->at_handler = at_handler; + res->at_handler_data = data; +} + VISIBLE void PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, const char *format, int count, pr_type_t **args) @@ -1214,6 +1246,8 @@ PR_Sprintf (progs_t *pr, dstring_t *result, const char *name, *state.fi = new_fmt_item (res); state.c = format; state.state = fmt_state_format; + state.at_handler = res->at_handler; + state.at_handler_data = res->at_handler_data; if (!name) name = "PR_Sprintf"; From 019b40fb81e8824770a9a160a53b11a4a1ea7d7b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 13:51:42 +0900 Subject: [PATCH 2944/3664] [ruamoko] Implement %@ handing in the ruamoko runtime -describe is sent to the object, and the returned string passed back. There is a worry about the lifetime of the returned string as there's currently no way of both ensuring it doesn't get freed prematurely and ensuring it does eventually get freed. --- libs/ruamoko/rua_obj.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index ee5555e96..1d0872798 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1314,7 +1314,7 @@ rua___obj_forward (progs_t *pr, void *data) pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 1); pr_sel_t *fwd_sel = probj->forward_selector; pr_sel_t *err_sel; - pr_class_t *class =&G_STRUCT (pr, pr_class_t, obj->class_pointer); + pr_class_t *class = &G_STRUCT (pr, pr_class_t, obj->class_pointer); pr_func_t imp; if (!fwd_sel) { @@ -1444,6 +1444,28 @@ rua_obj_set_error_handler (progs_t *pr, void *data) PR_RunError (pr, "%s, not implemented", __FUNCTION__); } +static const char * +rua_at_handler (progs_t *pr, pr_ptr_t at_param, void *_probj) +{ + probj_t *probj = _probj; + pr_id_t *obj = &G_STRUCT (pr, pr_id_t, at_param); + pr_class_t *class = &G_STRUCT (pr, pr_class_t, obj->class_pointer); + //FIXME sel_register_typed_name is really not the way to go about + //looking for a selector by name + pr_sel_t *describe_sel=sel_register_typed_name (probj, "describe", "", 0); + pr_func_t imp = get_imp (probj, class, describe_sel); + + PR_PushFrame (pr); + PR_RESET_PARAMS (pr); + P_POINTER (pr, 0) = at_param; + P_POINTER (pr, 1) = PR_SetPointer (pr, describe_sel); + pr->pr_argc = 2; + PR_ExecuteProgram (pr, imp); + PR_PopFrame (pr); + //FIXME the lifetime of the string may be a problem + return PR_GetString (pr, R_STRING (pr)); +} + static void rua_obj_msg_lookup (progs_t *pr, void *data) { @@ -2328,6 +2350,8 @@ RUA_Obj_Init (progs_t *pr, int secure) Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, load_methods_compare); + PR_Sprintf_SetAtHandler (pr, rua_at_handler, probj); + PR_Resources_Register (pr, "RUA_ObjectiveQuakeC", probj, rua_obj_cleanup, rua_obj_destroy); PR_RegisterBuiltins (pr, obj_methods, probj); From ee5e38b46ce247e9e1c12147ea5351875f391909 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 14:03:30 +0900 Subject: [PATCH 2945/3664] [ruamoko] Implement default -describe method on Object It returns [classname@address], which is probably a reasonable default. --- ruamoko/lib/Object.r | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruamoko/lib/Object.r b/ruamoko/lib/Object.r index 711721d1d..83ed07755 100644 --- a/ruamoko/lib/Object.r +++ b/ruamoko/lib/Object.r @@ -1,5 +1,6 @@ #include #include +#include static void link__obj_forward (void) { @@ -367,4 +368,9 @@ typedef void arIMP(id, SEL, id); return self; } +- (string) describe +{ + return sprintf ("[%s@%p]", object_get_class_name (self), self); +} + @end From a76f6c812c8efdad45709c6af8e0c1cea7a27d4f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 14:57:30 +0900 Subject: [PATCH 2946/3664] [gamecode] Fix a clang compile issue Silly clang not being actually compatible :P --- libs/gamecode/pr_strings.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index d4f423c4e..47321c39b 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -1056,6 +1056,7 @@ fmt_state_conversion (fmt_state_t *state) switch ((conv = *state->c++)) { case '@': // object + (void)0;// silly clang pr_ptr_t at_param = P_UINT (pr, state->fmt_count); if (state->at_handler) { const char *at_str = state->at_handler (pr, at_param, From a6611fc827ce9be52f7f8563806d1a4d90d66458 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 14:57:30 +0900 Subject: [PATCH 2947/3664] [gamecode] Fix a clang compile issue Silly clang not being actually compatible :P --- libs/gamecode/pr_strings.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index d4f423c4e..47321c39b 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -1056,6 +1056,7 @@ fmt_state_conversion (fmt_state_t *state) switch ((conv = *state->c++)) { case '@': // object + (void)0;// silly clang pr_ptr_t at_param = P_UINT (pr, state->fmt_count); if (state->at_handler) { const char *at_str = state->at_handler (pr, at_param, From 936f6d91e4d86cfd7568d428a0a76ca358bb5e89 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 17:06:33 +0900 Subject: [PATCH 2948/3664] [vulkan] Use vertex queue objects for Draw This makes working with quads, implied alpha quads, and lines much cleaner (and gets rid of the bulk of the "eww" fixme), and will probably make it easier to support multiple scraps and fonts, and potentially more flexible ordering between pipelines. --- libs/video/renderer/vulkan/vulkan_draw.c | 107 ++++++++++++----------- 1 file changed, 56 insertions(+), 51 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 806d66def..87cdb0c2c 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -83,16 +83,19 @@ typedef struct cachepic_s { qpic_t *pic; } cachepic_t; +typedef struct vertqueue_s { + drawvert_t *verts; + int count; + int size; +} vertqueue_t; + typedef struct drawframe_s { size_t vert_offset; size_t iavert_offset; size_t line_offset; - drawvert_t *quad_verts; - drawvert_t *iaquad_verts; - drawvert_t *line_verts; - uint32_t num_quads; - uint32_t num_iaquads; - uint32_t num_lines; + vertqueue_t quad_verts; + vertqueue_t iaquad_verts; + vertqueue_t line_verts; VkCommandBuffer cmd; VkDescriptorSet descriptors; VkDescriptorSet iadescriptors; @@ -190,11 +193,18 @@ create_quad_buffers (vulkan_ctx_t *ctx) frame->vert_offset = ind * sizeof (drawvert_t); frame->iavert_offset = iaind; frame->line_offset = lind; - frame->quad_verts = vert_data + ind; - frame->iaquad_verts = frame->quad_verts + IAQUADS_OFFSET; - frame->line_verts = frame->quad_verts + LINES_OFFSET; - frame->num_quads = 0; - frame->num_lines = 0; + frame->quad_verts = (vertqueue_t) { + .verts = vert_data + ind, + .size = MAX_QUADS, + }; + frame->iaquad_verts = (vertqueue_t) { + .verts = frame->quad_verts.verts + IAQUADS_OFFSET, + .size = MAX_QUADS, + }; + frame->line_verts = (vertqueue_t) { + .verts = frame->quad_verts.verts + LINES_OFFSET, + .size = MAX_LINES, + }; } // The indices will never change so pre-generate and stash them @@ -502,14 +512,14 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) static inline void draw_pic (float x, float y, int w, int h, qpic_t *pic, int srcx, int srcy, int srcw, int srch, - float *color, drawframe_t *frame) + float *color, vertqueue_t *queue) { - if (frame->num_quads >= MAX_QUADS) { + if (queue->count >= queue->size) { return; } - drawvert_t *verts = frame->quad_verts + frame->num_quads * VERTS_PER_QUAD; - frame->num_quads++; + drawvert_t *verts = queue->verts + queue->count * VERTS_PER_QUAD; + queue->count++; subpic_t *subpic = *(subpic_t **) pic->data; srcx += subpic->rect->x; @@ -557,7 +567,8 @@ queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx) cx = chr % 16; cy = chr / 16; - draw_pic (x, y, 8, 8, dctx->conchars, cx * 8, cy * 8, 8, 8, color, frame); + draw_pic (x, y, 8, 8, dctx->conchars, cx * 8, cy * 8, 8, 8, color, + &frame->quad_verts); } void @@ -656,7 +667,7 @@ draw_crosshair_pic (int ch, int x, int y, vulkan_ctx_t *ctx) draw_pic (x - CROSSHAIR_WIDTH + 1, y - CROSSHAIR_HEIGHT + 1, CROSSHAIR_WIDTH * 2, CROSSHAIR_HEIGHT * 2, dctx->crosshair, - p[0], p[1], p[2], p[3], crosshair_color, frame); + p[0], p[1], p[2], p[3], crosshair_color, &frame->quad_verts); } static void (*crosshair_func[]) (int ch, int x, int y, vulkan_ctx_t *ctx) = { @@ -701,7 +712,7 @@ Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, int cx, cy, n; #define draw(px, py, pp) \ draw_pic (px, py, pp->width, pp->height, pp, \ - 0, 0, pp->width, pp->height, color, frame); + 0, 0, pp->width, pp->height, color, &frame->quad_verts); color[3] = alpha; // draw left side @@ -758,7 +769,7 @@ Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) static quat_t color = { 1, 1, 1, 1}; draw_pic (x, y, pic->width, pic->height, pic, - 0, 0, pic->width, pic->height, color, frame); + 0, 0, pic->width, pic->height, color, &frame->quad_verts); } void @@ -769,7 +780,7 @@ Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) static quat_t color = { 1, 1, 1, 1}; draw_pic (x, y, pic->width, pic->height, pic, - 0, 0, pic->width, pic->height, color, frame); + 0, 0, pic->width, pic->height, color, &frame->quad_verts); } void @@ -782,7 +793,7 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, static quat_t color = { 1, 1, 1, 1}; draw_pic (x, y, width, height, pic, srcx, srcy, width, height, - color, frame); + color, &frame->quad_verts); } void @@ -799,7 +810,7 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) int ofs = max (0, cpic->height - lines); lines = min (lines, cpic->height); draw_pic (0, 0, vid.conview->xlen, lines, cpic, - 0, ofs, cpic->width, lines, color, frame); + 0, ofs, cpic->width, lines, color, &frame->quad_verts); } void @@ -817,7 +828,8 @@ Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) VectorScale (vid.palette + c * 3, 1.0f/255.0f, color); color[3] = 1; - draw_pic (x, y, w, h, dctx->white_pic, 0, 0, 1, 1, color, frame); + draw_pic (x, y, w, h, dctx->white_pic, 0, 0, 1, 1, color, + &frame->quad_verts); } void @@ -825,14 +837,15 @@ Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) { drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + vertqueue_t *queue = &frame->line_verts; - if (frame->num_quads >= MAX_QUADS) { + if (queue->count >= queue->size) { return; } quat_t color = { VectorExpand (vid.palette + c * 3), 255 }; QuatScale (color, 1/255.0, color); - drawvert_t *verts = frame->line_verts + frame->num_lines * VERTS_PER_LINE; + drawvert_t *verts = queue->verts + queue->count * VERTS_PER_LINE; verts[0] = (drawvert_t) { .xy = { x0, y0 }, @@ -843,7 +856,7 @@ Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) .color = { QuatExpand (color) }, }; - frame->num_lines++; + queue->count++; } static inline void @@ -853,7 +866,7 @@ draw_blendscreen (quat_t color, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; draw_pic (0, 0, vid.conview->xlen, vid.conview->ylen, dctx->white_pic, - 0, 0, 1, 1, color, frame); + 0, 0, 1, 1, color, &frame->quad_verts); } void @@ -895,7 +908,8 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - if (!dframe->num_quads && !dframe->num_iaquads && !dframe->num_lines) { + if (!dframe->quad_verts.count && !dframe->iaquad_verts.count + && !dframe->line_verts.count) { return; } @@ -906,13 +920,13 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) VkMappedMemoryRange ranges[] = { { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, dctx->vert_memory, dframe->vert_offset, - dframe->num_quads * VERTS_PER_QUAD * sizeof (drawvert_t) }, + dframe->quad_verts.count * VERTS_PER_QUAD * sizeof (drawvert_t) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, dctx->vert_memory, dframe->iavert_offset, - dframe->num_iaquads * VERTS_PER_QUAD * sizeof (drawvert_t) }, + dframe->iaquad_verts.count * VERTS_PER_QUAD * sizeof (drawvert_t) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, dctx->vert_memory, dframe->line_offset, - dframe->num_lines * VERTS_PER_LINE * sizeof (drawvert_t) }, + dframe->line_verts.count * VERTS_PER_LINE * sizeof (drawvert_t) }, }; dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); @@ -936,7 +950,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets); dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, VK_INDEX_TYPE_UINT32); - if (dframe->num_quads) { + if (dframe->quad_verts.count) { VkDescriptorSet set[2] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), dframe->descriptors, @@ -949,10 +963,10 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dctx->quad_pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD, + dfunc->vkCmdDrawIndexed (cmd, dframe->quad_verts.count * INDS_PER_QUAD, 1, 0, QUADS_OFFSET, 0); } - if (dframe->num_iaquads) { + if (dframe->iaquad_verts.count) { VkDescriptorImageInfo iaimageInfo = { dctx->sampler, Vulkan_TexImageView (dctx->font_tex), @@ -978,11 +992,11 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dctx->iaquad_pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - dfunc->vkCmdDrawIndexed (cmd, dframe->num_iaquads * INDS_PER_QUAD, + dfunc->vkCmdDrawIndexed (cmd, dframe->iaquad_verts.count*INDS_PER_QUAD, 1, 0, IAQUADS_OFFSET, 0); } - if (dframe->num_lines) { + if (dframe->line_verts.count) { VkDescriptorSet set[2] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), dframe->descriptors, @@ -993,16 +1007,16 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dctx->line_pipeline); - dfunc->vkCmdDraw (cmd, dframe->num_lines * VERTS_PER_LINE, + dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE, 1, LINES_OFFSET, 0); } QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); - dframe->num_quads = 0; - dframe->num_iaquads = 0; - dframe->num_lines = 0; + dframe->quad_verts.count = 0; + dframe->iaquad_verts.count = 0; + dframe->line_verts.count = 0; } void @@ -1058,7 +1072,7 @@ vulkan_render_glyph (rglyph_t *glyph, int x, int y, void *_rgctx) int gw = glyph->rect->width; int gh = glyph->rect->height; draw_pic (x, y, gw, gh, &rgctx->pic, 0, 0, gw, gh, rgctx->color, - rgctx->dframe); + &rgctx->dframe->iaquad_verts); } void @@ -1068,13 +1082,9 @@ Vulkan_Draw_FontString (int x, int y, const char *str, vulkan_ctx_t *ctx) if (!dctx->font) { return; } - //FIXME ewwwwwww drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - uint32_t num_quads = dframe->num_quads; - drawvert_t *quad_verts = dframe->quad_verts; - dframe->num_quads = dframe->num_iaquads; - dframe->quad_verts = dframe->iaquad_verts; + //FIXME ewwwwwww subpic_t glyph_subpic = { .width = dctx->font->scrap.width, .height = dctx->font->scrap.height, @@ -1099,9 +1109,4 @@ Vulkan_Draw_FontString (int x, int y, const char *str, vulkan_ctx_t *ctx) rshaper_t *shaper = RText_NewShaper (dctx->font); RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx); RText_DeleteShaper (shaper); - - dframe->num_iaquads = dframe->num_quads; - dframe->iaquad_verts = dframe->quad_verts; - dframe->num_quads = num_quads; - dframe->quad_verts = quad_verts; } From 71efbba628905f40ad9e07ba76bc5a8f26ca6fe3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Sep 2022 20:05:31 +0900 Subject: [PATCH 2949/3664] [vulkan] Switch draw_pic to take subpic_t instead of qpic_t While this does pull the grovelling for the subpic out to the callers, the real problem is the excessive use of qpic_t in the internal code: qpic_t is really just the image format in wad files, and shouldn't be used as a generic image handle. Cleans up more of the icky code in the font drawing functions. --- libs/video/renderer/vulkan/vulkan_draw.c | 43 +++++++++++++----------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 87cdb0c2c..a3693426a 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -510,7 +510,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) } static inline void -draw_pic (float x, float y, int w, int h, qpic_t *pic, +draw_pic (float x, float y, int w, int h, subpic_t *subpic, int srcx, int srcy, int srcw, int srch, float *color, vertqueue_t *queue) { @@ -521,7 +521,6 @@ draw_pic (float x, float y, int w, int h, qpic_t *pic, drawvert_t *verts = queue->verts + queue->count * VERTS_PER_QUAD; queue->count++; - subpic_t *subpic = *(subpic_t **) pic->data; srcx += subpic->rect->x; srcy += subpic->rect->y; @@ -567,7 +566,8 @@ queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx) cx = chr % 16; cy = chr / 16; - draw_pic (x, y, 8, 8, dctx->conchars, cx * 8, cy * 8, 8, 8, color, + subpic_t *subpic = *(subpic_t **) dctx->conchars->data; + draw_pic (x, y, 8, 8, subpic, cx * 8, cy * 8, 8, 8, color, &frame->quad_verts); } @@ -665,8 +665,9 @@ draw_crosshair_pic (int ch, int x, int y, vulkan_ctx_t *ctx) }; const int *p = pos[ch - 1]; + subpic_t *subpic = *(subpic_t **) dctx->crosshair->data; draw_pic (x - CROSSHAIR_WIDTH + 1, y - CROSSHAIR_HEIGHT + 1, - CROSSHAIR_WIDTH * 2, CROSSHAIR_HEIGHT * 2, dctx->crosshair, + CROSSHAIR_WIDTH * 2, CROSSHAIR_HEIGHT * 2, subpic, p[0], p[1], p[2], p[3], crosshair_color, &frame->quad_verts); } @@ -710,9 +711,12 @@ Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, quat_t color = {1, 1, 1, 1}; qpic_t *p; int cx, cy, n; -#define draw(px, py, pp) \ - draw_pic (px, py, pp->width, pp->height, pp, \ - 0, 0, pp->width, pp->height, color, &frame->quad_verts); +#define draw(px, py, pp) \ + do { \ + subpic_t *subpic = *(subpic_t **) (pp)->data; \ + draw_pic (px, py, pp->width, pp->height, subpic, \ + 0, 0, pp->width, pp->height, color, &frame->quad_verts); \ + } while (0) color[3] = alpha; // draw left side @@ -768,7 +772,8 @@ Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; static quat_t color = { 1, 1, 1, 1}; - draw_pic (x, y, pic->width, pic->height, pic, + subpic_t *subpic = *(subpic_t **) pic->data; + draw_pic (x, y, pic->width, pic->height, subpic, 0, 0, pic->width, pic->height, color, &frame->quad_verts); } @@ -779,7 +784,8 @@ Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; static quat_t color = { 1, 1, 1, 1}; - draw_pic (x, y, pic->width, pic->height, pic, + subpic_t *subpic = *(subpic_t **) pic->data; + draw_pic (x, y, pic->width, pic->height, subpic, 0, 0, pic->width, pic->height, color, &frame->quad_verts); } @@ -792,7 +798,8 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; static quat_t color = { 1, 1, 1, 1}; - draw_pic (x, y, width, height, pic, srcx, srcy, width, height, + subpic_t *subpic = *(subpic_t **) pic->data; + draw_pic (x, y, width, height, subpic, srcx, srcy, width, height, color, &frame->quad_verts); } @@ -809,7 +816,8 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx); int ofs = max (0, cpic->height - lines); lines = min (lines, cpic->height); - draw_pic (0, 0, vid.conview->xlen, lines, cpic, + subpic_t *subpic = *(subpic_t **) cpic->data; + draw_pic (0, 0, vid.conview->xlen, lines, subpic, 0, ofs, cpic->width, lines, color, &frame->quad_verts); } @@ -828,7 +836,8 @@ Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) VectorScale (vid.palette + c * 3, 1.0f/255.0f, color); color[3] = 1; - draw_pic (x, y, w, h, dctx->white_pic, 0, 0, 1, 1, color, + subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; + draw_pic (x, y, w, h, subpic, 0, 0, 1, 1, color, &frame->quad_verts); } @@ -865,7 +874,8 @@ draw_blendscreen (quat_t color, vulkan_ctx_t *ctx) drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - draw_pic (0, 0, vid.conview->xlen, vid.conview->ylen, dctx->white_pic, + subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; + draw_pic (0, 0, vid.conview->xlen, vid.conview->ylen, subpic, 0, 0, 1, 1, color, &frame->quad_verts); } @@ -1058,7 +1068,6 @@ Vulkan_Draw_AddFont (rfont_t *font, vulkan_ctx_t *ctx) typedef struct { drawframe_t *dframe; - qpic_t pic; subpic_t *subpic; quat_t color; } rgctx_t; @@ -1071,7 +1080,7 @@ vulkan_render_glyph (rglyph_t *glyph, int x, int y, void *_rgctx) *((vrect_t **) &rgctx->subpic->rect) = glyph->rect; int gw = glyph->rect->width; int gh = glyph->rect->height; - draw_pic (x, y, gw, gh, &rgctx->pic, 0, 0, gw, gh, rgctx->color, + draw_pic (x, y, gw, gh, rgctx->subpic, 0, 0, gw, gh, rgctx->color, &rgctx->dframe->iaquad_verts); } @@ -1092,10 +1101,6 @@ Vulkan_Draw_FontString (int x, int y, const char *str, vulkan_ctx_t *ctx) }; rgctx_t rgctx = { .dframe = dframe, - .pic = { - .width = 1, - .height = 1, - }, .subpic = &glyph_subpic, .color = { 0.5, 1, 0.6, 1 }, }; From 99196550d101b619e3e0c263ace411f591a98150 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 12 Sep 2022 08:43:28 +0900 Subject: [PATCH 2950/3664] [renderer] Move r_font.c to correct library Fixes the linker error in the standard build. --- libs/video/renderer/Makemodule.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index c611cd7fe..07397bfa8 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -30,7 +30,6 @@ video_renderer_common_sources = \ libs/video/renderer/r_billboard.c \ libs/video/renderer/r_dyn_textures.c \ libs/video/renderer/r_ent.c \ - libs/video/renderer/r_font.c \ libs/video/renderer/r_iqm.c \ libs/video/renderer/r_sprite.c \ libs/video/renderer/r_text.c \ @@ -50,6 +49,7 @@ libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_cvar.c \ libs/video/renderer/r_efrag.c \ libs/video/renderer/r_fog.c \ + libs/video/renderer/r_font.c \ libs/video/renderer/r_graph.c \ libs/video/renderer/r_init.c \ libs/video/renderer/r_light.c \ From bf7ef354d550c43e39821366fd9d09168f0c35aa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Sep 2022 17:09:42 +0900 Subject: [PATCH 2951/3664] [audio] Ensure FLAC doesn't use dll imports For whatever reason, building under MXE (for windows) causes FLAC to try to use dll import references, but setting FLAC__NO_DLL before including FLAC/export.h fixes the issue. --- libs/audio/renderer/flac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index b757994ae..000ec4867 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -39,6 +39,7 @@ #endif #include +#define FLAC__NO_DLL #include #include "qfalloca.h" From 6ed045cd9cb1e1d10799e632b913d7fcd357a480 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Sep 2022 17:09:42 +0900 Subject: [PATCH 2952/3664] [audio] Ensure FLAC doesn't use dll imports For whatever reason, building under MXE (for windows) causes FLAC to try to use dll import references, but setting FLAC__NO_DLL before including FLAC/export.h fixes the issue. --- libs/audio/renderer/flac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index b757994ae..000ec4867 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -39,6 +39,7 @@ #endif #include +#define FLAC__NO_DLL #include #include "qfalloca.h" From c771bfa58cedd08c75c5a81a01639b8a35c4468a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Sep 2022 17:38:58 +0900 Subject: [PATCH 2953/3664] [renderer] Correct freetype and harfbuzz lib linking renderer_libs was in both LIBADD and DEPENDENCIES, so make was trying to build the freetype and harfbuzz libs when building for windows. --- libs/video/renderer/Makemodule.am | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 07397bfa8..ca603d9e1 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -37,12 +37,15 @@ video_renderer_common_sources = \ renderer_libs= \ @vid_render_static_plugin_libs@ \ - libs/util/libQFutil.la \ + libs/util/libQFutil.la + +renderer_libadd= \ + $(renderer_libs) \ $(FREETYPE_LIBS) \ $(HARFBUZZ_LIBS) libs_video_renderer_libQFrenderer_la_LDFLAGS= @STATIC@ -libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libs) +libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libadd) libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs) libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_bsp.c \ From 47ac7b924f7364911f4fec99192a5d978dc3b30f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Sep 2022 21:31:54 +0900 Subject: [PATCH 2954/3664] [qfcc] Skip recording defs for binary expressions For now, anyway, as the generated code looks good. There might be problems with actual pointer expressions, but it allows entity.field to work as expected rather than generate an ICE. --- tools/qfcc/source/statements.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ec011d1e4..7f5134318 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1238,6 +1238,8 @@ find_def_operand (expr_t *ref) expr_symbol (0, ref, &op); } else if (ref->type == ex_def) { expr_def (0, ref, &op); + } else if (ref->type == ex_expr) { + debug (ref, "unexpected expr type: %s", expr_names[ref->type]); } else { internal_error (ref, "unexpected expr type: %s", expr_names[ref->type]); From 942ea22266b83aa3b2a07fc360a01baa46df32b0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Sep 2022 14:39:09 +0900 Subject: [PATCH 2955/3664] [qfcc] Promote types before expanding scalars This fixes the internal error generated by the likes of `(sv_gravity * '0 0 1')` where sv_gravity is a float and `'0 0 1'` is an ivec3: the vector is promoted to vec3 first so that expanding sv_gravity is expanded to vec3 instead of ivec3 (which is not permitted for a float: expansion requires the destination base type to be the same as the source). --- tools/qfcc/source/expr_binary.c | 70 ++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index f01e165b2..9f96ef741 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -853,13 +853,16 @@ entity_compare (int op, expr_t *e1, expr_t *e2) return e; } +#define invalid_binary_expr(_op, _e1, _e2) \ + _invalid_binary_expr(_op, _e1, _e2, __FILE__, __LINE__) static expr_t * -invalid_binary_expr (int op, expr_t *e1, expr_t *e2) +_invalid_binary_expr (int op, expr_t *e1, expr_t *e2, + const char *file, int line) { type_t *t1, *t2; t1 = get_type (e1); t2 = get_type (e2); - return error (e1, "invalid binary expression: %s %s %s", + return _error (e1, file, line, "invalid binary expression: %s %s %s", get_type_string (t1), get_op_string (op), get_type_string (t2)); } @@ -977,6 +980,15 @@ static int is_call (expr_t *e) return e->type == ex_block && e->e.block.is_call; } +static type_t * +promote_type (type_t *dst, type_t *src) +{ + if (is_vector (dst) || is_quaternion (dst)) { + return dst; + } + return vector_type (base_type (dst), type_width (src)); +} + expr_t * binary_expr (int op, expr_t *e1, expr_t *e2) { @@ -1056,6 +1068,38 @@ binary_expr (int op, expr_t *e1, expr_t *e2) // vector/quaternion and scalar won't get here as vector and quaternion // are distict types with type.width == 1, but vector and vec3 WILL get // here because of vec3 being float{3} + if (t1 != t2) { + type_t *pt1 = t1; + type_t *pt2 = t2; + if (is_float (base_type (t1)) && is_double (base_type (t2)) + && e2->implicit) { + pt2 = promote_type (t1, t2); + } else if (is_double (base_type (t1)) && is_float (base_type (t2)) + && e1->implicit) { + pt1 = promote_type (t2, t1); + } else if (type_promotes (base_type (t1), base_type (t2))) { + pt2 = promote_type (t1, t2); + } else if (type_promotes (base_type (t2), base_type (t1))) { + pt1 = promote_type (t2, t1); + } else if (base_type (t1) == base_type (t2)) { + if (is_vector (t1) || is_quaternion (t1)) { + pt2 = t1; + } else if (is_vector (t2) || is_quaternion (t2)) { + pt1 = t2; + } + } else { + debug (e1, "%d %d\n", e1->implicit, e2->implicit); + return invalid_binary_expr (op, e1, e2); + } + if (pt1 != t1) { + e1 = cast_expr (pt1, e1); + t1 = pt1; + } + if (pt2 != t2) { + e2 = cast_expr (pt2, e2); + t2 = pt2; + } + } if (type_width (t1) == 1) { // scalar op vec if (!(e = convert_scalar (e1, op, e2))) { @@ -1076,28 +1120,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) // vec op vec of different widths return invalid_binary_expr (op, e1, e2); } - if (t1 != t2) { - if (is_float (base_type (t1)) && is_double (base_type (t2)) - && e2->implicit) { - e2 = cast_expr (t1, e2); - } else if (is_double (base_type (t1)) && is_float (base_type (t2)) - && e1->implicit) { - e1 = cast_expr (t2, e1); - } else if (type_promotes (base_type (t1), base_type (t2))) { - e2 = cast_expr (t1, e2); - } else if (type_promotes (base_type (t2), base_type (t1))) { - e1 = cast_expr (t2, e1); - } else if (base_type (t1) == base_type (t2)) { - if (is_vector (t1) || is_quaternion (t1)) { - e2 = cast_expr (t1, e2); - } else if (is_vector (t2) || is_quaternion (t2)) { - e1 = cast_expr (t2, e1); - } - } else { - debug (e1, "%d %d\n", e1->implicit, e2->implicit); - return invalid_binary_expr (op, e1, e2); - } - } t1 = get_type (e1); t2 = get_type (e2); et1 = low_level_type (t1); From 5747ddb77fd9d992e335b183125b35c5c62813ab Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Sep 2022 21:31:54 +0900 Subject: [PATCH 2956/3664] [qfcc] Skip recording defs for binary expressions For now, anyway, as the generated code looks good. There might be problems with actual pointer expressions, but it allows entity.field to work as expected rather than generate an ICE. --- tools/qfcc/source/statements.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ec011d1e4..7f5134318 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1238,6 +1238,8 @@ find_def_operand (expr_t *ref) expr_symbol (0, ref, &op); } else if (ref->type == ex_def) { expr_def (0, ref, &op); + } else if (ref->type == ex_expr) { + debug (ref, "unexpected expr type: %s", expr_names[ref->type]); } else { internal_error (ref, "unexpected expr type: %s", expr_names[ref->type]); From a8a8c567a2548fe5680e0588641b128b6fc0fda3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Sep 2022 14:39:09 +0900 Subject: [PATCH 2957/3664] [qfcc] Promote types before expanding scalars This fixes the internal error generated by the likes of `(sv_gravity * '0 0 1')` where sv_gravity is a float and `'0 0 1'` is an ivec3: the vector is promoted to vec3 first so that expanding sv_gravity is expanded to vec3 instead of ivec3 (which is not permitted for a float: expansion requires the destination base type to be the same as the source). --- tools/qfcc/source/expr_binary.c | 70 ++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index f01e165b2..9f96ef741 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -853,13 +853,16 @@ entity_compare (int op, expr_t *e1, expr_t *e2) return e; } +#define invalid_binary_expr(_op, _e1, _e2) \ + _invalid_binary_expr(_op, _e1, _e2, __FILE__, __LINE__) static expr_t * -invalid_binary_expr (int op, expr_t *e1, expr_t *e2) +_invalid_binary_expr (int op, expr_t *e1, expr_t *e2, + const char *file, int line) { type_t *t1, *t2; t1 = get_type (e1); t2 = get_type (e2); - return error (e1, "invalid binary expression: %s %s %s", + return _error (e1, file, line, "invalid binary expression: %s %s %s", get_type_string (t1), get_op_string (op), get_type_string (t2)); } @@ -977,6 +980,15 @@ static int is_call (expr_t *e) return e->type == ex_block && e->e.block.is_call; } +static type_t * +promote_type (type_t *dst, type_t *src) +{ + if (is_vector (dst) || is_quaternion (dst)) { + return dst; + } + return vector_type (base_type (dst), type_width (src)); +} + expr_t * binary_expr (int op, expr_t *e1, expr_t *e2) { @@ -1056,6 +1068,38 @@ binary_expr (int op, expr_t *e1, expr_t *e2) // vector/quaternion and scalar won't get here as vector and quaternion // are distict types with type.width == 1, but vector and vec3 WILL get // here because of vec3 being float{3} + if (t1 != t2) { + type_t *pt1 = t1; + type_t *pt2 = t2; + if (is_float (base_type (t1)) && is_double (base_type (t2)) + && e2->implicit) { + pt2 = promote_type (t1, t2); + } else if (is_double (base_type (t1)) && is_float (base_type (t2)) + && e1->implicit) { + pt1 = promote_type (t2, t1); + } else if (type_promotes (base_type (t1), base_type (t2))) { + pt2 = promote_type (t1, t2); + } else if (type_promotes (base_type (t2), base_type (t1))) { + pt1 = promote_type (t2, t1); + } else if (base_type (t1) == base_type (t2)) { + if (is_vector (t1) || is_quaternion (t1)) { + pt2 = t1; + } else if (is_vector (t2) || is_quaternion (t2)) { + pt1 = t2; + } + } else { + debug (e1, "%d %d\n", e1->implicit, e2->implicit); + return invalid_binary_expr (op, e1, e2); + } + if (pt1 != t1) { + e1 = cast_expr (pt1, e1); + t1 = pt1; + } + if (pt2 != t2) { + e2 = cast_expr (pt2, e2); + t2 = pt2; + } + } if (type_width (t1) == 1) { // scalar op vec if (!(e = convert_scalar (e1, op, e2))) { @@ -1076,28 +1120,6 @@ binary_expr (int op, expr_t *e1, expr_t *e2) // vec op vec of different widths return invalid_binary_expr (op, e1, e2); } - if (t1 != t2) { - if (is_float (base_type (t1)) && is_double (base_type (t2)) - && e2->implicit) { - e2 = cast_expr (t1, e2); - } else if (is_double (base_type (t1)) && is_float (base_type (t2)) - && e1->implicit) { - e1 = cast_expr (t2, e1); - } else if (type_promotes (base_type (t1), base_type (t2))) { - e2 = cast_expr (t1, e2); - } else if (type_promotes (base_type (t2), base_type (t1))) { - e1 = cast_expr (t2, e1); - } else if (base_type (t1) == base_type (t2)) { - if (is_vector (t1) || is_quaternion (t1)) { - e2 = cast_expr (t1, e2); - } else if (is_vector (t2) || is_quaternion (t2)) { - e1 = cast_expr (t2, e1); - } - } else { - debug (e1, "%d %d\n", e1->implicit, e2->implicit); - return invalid_binary_expr (op, e1, e2); - } - } t1 = get_type (e1); t2 = get_type (e2); et1 = low_level_type (t1); From aa41e6c4c62769c6e33724b0e7314663d758ec61 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Sep 2022 19:23:59 +0900 Subject: [PATCH 2958/3664] [gamecode] Expose value_string as PR_Debug_ValueString PR_Debug_ValueString prints the value at the given offset using the provided type to format the string. The formatted string is appended to the provided dstring. --- include/QF/progs.h | 3 +++ libs/gamecode/pr_debug.c | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 76b8e0000..adae471f9 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1984,6 +1984,9 @@ int PR_LoadDebug (progs_t *pr); const char *PR_Debug_GetBaseDirectory (progs_t *pr, const char *file); void PR_Debug_Watch (progs_t *pr, const char *expr); void PR_Debug_Print (progs_t *pr, const char *expr); +const char *PR_Debug_ValueString (progs_t *pr, pr_ptr_t offset, + struct qfot_type_s *type, + struct dstring_s *dstr); pr_auxfunction_t *PR_Debug_AuxFunction (progs_t *pr, pr_uint_t func) __attribute__((pure)); pr_auxfunction_t *PR_Debug_MappedAuxFunction (progs_t *pr, pr_uint_t func) __attribute__((pure)); pr_def_t *PR_Debug_LocalDefs (progs_t *pr, pr_auxfunction_t *aux_function) __attribute__((pure)); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 1b1484351..2a07ba9cd 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1168,6 +1168,15 @@ global_string (pr_debug_data_t *data, pr_ptr_t offset, qfot_type_t *type, return dstr->str; } +const char * +PR_Debug_ValueString (progs_t *pr, pr_ptr_t offset, qfot_type_t *type, + dstring_t *dstr) +{ + pr_debug_data_t data = {pr, dstr}; + value_string (&data, type, pr->pr_globals + offset); + return dstr->str; +} + static void pr_debug_void_view (qfot_type_t *type, pr_type_t *value, void *_data) { From 3c797e15e6c1e7d0776c68b35c566f52e64a600b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Sep 2022 19:26:17 +0900 Subject: [PATCH 2959/3664] [qfcc] Use PR_Debug_ValueString when dumping globals While it does get a bit cluttered currently, being able to see the contents of structures makes a huge difference. Also highlights that vector immediates do not get the correct type encodings. --- tools/qfcc/source/dump_globals.c | 79 +++----------------------------- 1 file changed, 6 insertions(+), 73 deletions(-) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 77ae2a2bc..3801bcc5d 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -65,8 +65,6 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) const char *type; pr_uint_t offset; const char *comment; - pr_string_t string; - const char *str; int saveglobal; if (!def->type && !def->ofs && !def->name) @@ -80,78 +78,13 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) comment = " invalid offset"; if (offset < pr->progs->globals.count) { - comment = ""; - switch (def->type & ~DEF_SAVEGLOBAL) { - case ev_void: - break; - case ev_string: - string = G_INT (pr, offset); - // at runtime, strings can be negative (thus pr_string_t is - // signed), but negative strings means they have been - // dynamically allocated, thus a negative string index should - // never appear in compiled code - if (string < 0 - || (pr_uint_t) string >= pr->progs->strings.count) { - str = "invalid string offset"; - comment = va (0, " %d %s", string, str); - } else { - str = quote_string (pr->pr_strings + G_INT (pr, offset)); - comment = va (0, " %d \"%s\"", string, str); - } - break; - case ev_float: - comment = va (0, " %g", G_FLOAT (pr, offset)); - break; - case ev_double: - comment = va (0, " %.17g", G_DOUBLE (pr, offset)); - break; - case ev_vector: - comment = va (0, " '%g %g %g'", - G_VECTOR (pr, offset)[0], - G_VECTOR (pr, offset)[1], - G_VECTOR (pr, offset)[2]); - break; - case ev_entity: - break; - case ev_field: - comment = va (0, " %x", G_INT (pr, offset)); - break; - case ev_func: - { - pr_func_t func = G_FUNCTION (pr, offset); - int start; - if (func < pr->progs->functions.count) { - start = pr->pr_functions[func].first_statement; - if (start > 0) - comment = va (0, " %d @ %x", func, start); - else - comment = va (0, " %d = #%d", func, -start); - } else { - comment = va (0, " %d = illegal function", func); - } - } - break; - case ev_ptr: - comment = va (0, " %x", G_INT (pr, offset)); - break; - case ev_quaternion: - comment = va (0, " '%g %g %g %g'", - G_QUAT (pr, offset)[0], - G_QUAT (pr, offset)[1], - G_QUAT (pr, offset)[2], - G_QUAT (pr, offset)[3]); - break; - case ev_int: - comment = va (0, " %d", G_INT (pr, offset)); - break; - case ev_short: - break; - case ev_invalid: - comment = " struct?"; - break; - case ev_type_count: - break; + static dstring_t *value_dstr; + if (!value_dstr) { + value_dstr = dstring_newstr (); } + dstring_clearstr (value_dstr); + qfot_type_t *ty = &G_STRUCT (pr, qfot_type_t, def->type_encoding); + comment = PR_Debug_ValueString (pr, offset, ty, value_dstr); } printf ("%*s %x:%d %d %s %s:%x %s\n", indent * 12, "", offset, def->size, saveglobal, name, type, def->type_encoding, From 6d64195a7b4a175393b43100e95186f978a55d18 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Sep 2022 22:10:11 +0900 Subject: [PATCH 2960/3664] [qfcc] Fix incorrect progs source path handling The cvar rewrite changed how to deal with cvar setting in code and I messed it up for qfprogs. --- tools/qfcc/source/qfprogs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 20e59ea5c..3b8a62581 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -237,8 +237,7 @@ init_qf (void) PR_Init_Cvars (); pr_debug = 1 + verbosity; - free (pr_source_path); - pr_source_path = (char *) source_path; + Cvar_Set ("pr_source_path", source_path); pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; From 98f773b0ed10cc69e7aefaae6be617c93de1850a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Sep 2022 19:23:59 +0900 Subject: [PATCH 2961/3664] [gamecode] Expose value_string as PR_Debug_ValueString PR_Debug_ValueString prints the value at the given offset using the provided type to format the string. The formatted string is appended to the provided dstring. --- include/QF/progs.h | 3 +++ libs/gamecode/pr_debug.c | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/include/QF/progs.h b/include/QF/progs.h index 76b8e0000..adae471f9 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1984,6 +1984,9 @@ int PR_LoadDebug (progs_t *pr); const char *PR_Debug_GetBaseDirectory (progs_t *pr, const char *file); void PR_Debug_Watch (progs_t *pr, const char *expr); void PR_Debug_Print (progs_t *pr, const char *expr); +const char *PR_Debug_ValueString (progs_t *pr, pr_ptr_t offset, + struct qfot_type_s *type, + struct dstring_s *dstr); pr_auxfunction_t *PR_Debug_AuxFunction (progs_t *pr, pr_uint_t func) __attribute__((pure)); pr_auxfunction_t *PR_Debug_MappedAuxFunction (progs_t *pr, pr_uint_t func) __attribute__((pure)); pr_def_t *PR_Debug_LocalDefs (progs_t *pr, pr_auxfunction_t *aux_function) __attribute__((pure)); diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 1b1484351..2a07ba9cd 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1168,6 +1168,15 @@ global_string (pr_debug_data_t *data, pr_ptr_t offset, qfot_type_t *type, return dstr->str; } +const char * +PR_Debug_ValueString (progs_t *pr, pr_ptr_t offset, qfot_type_t *type, + dstring_t *dstr) +{ + pr_debug_data_t data = {pr, dstr}; + value_string (&data, type, pr->pr_globals + offset); + return dstr->str; +} + static void pr_debug_void_view (qfot_type_t *type, pr_type_t *value, void *_data) { From b65a269f3cfc2fb3a28ef8d1de478d3d7a144f92 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Sep 2022 19:26:17 +0900 Subject: [PATCH 2962/3664] [qfcc] Use PR_Debug_ValueString when dumping globals While it does get a bit cluttered currently, being able to see the contents of structures makes a huge difference. Also highlights that vector immediates do not get the correct type encodings. --- tools/qfcc/source/dump_globals.c | 79 +++----------------------------- 1 file changed, 6 insertions(+), 73 deletions(-) diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 77ae2a2bc..3801bcc5d 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -65,8 +65,6 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) const char *type; pr_uint_t offset; const char *comment; - pr_string_t string; - const char *str; int saveglobal; if (!def->type && !def->ofs && !def->name) @@ -80,78 +78,13 @@ dump_def (progs_t *pr, pr_def_t *def, int indent) comment = " invalid offset"; if (offset < pr->progs->globals.count) { - comment = ""; - switch (def->type & ~DEF_SAVEGLOBAL) { - case ev_void: - break; - case ev_string: - string = G_INT (pr, offset); - // at runtime, strings can be negative (thus pr_string_t is - // signed), but negative strings means they have been - // dynamically allocated, thus a negative string index should - // never appear in compiled code - if (string < 0 - || (pr_uint_t) string >= pr->progs->strings.count) { - str = "invalid string offset"; - comment = va (0, " %d %s", string, str); - } else { - str = quote_string (pr->pr_strings + G_INT (pr, offset)); - comment = va (0, " %d \"%s\"", string, str); - } - break; - case ev_float: - comment = va (0, " %g", G_FLOAT (pr, offset)); - break; - case ev_double: - comment = va (0, " %.17g", G_DOUBLE (pr, offset)); - break; - case ev_vector: - comment = va (0, " '%g %g %g'", - G_VECTOR (pr, offset)[0], - G_VECTOR (pr, offset)[1], - G_VECTOR (pr, offset)[2]); - break; - case ev_entity: - break; - case ev_field: - comment = va (0, " %x", G_INT (pr, offset)); - break; - case ev_func: - { - pr_func_t func = G_FUNCTION (pr, offset); - int start; - if (func < pr->progs->functions.count) { - start = pr->pr_functions[func].first_statement; - if (start > 0) - comment = va (0, " %d @ %x", func, start); - else - comment = va (0, " %d = #%d", func, -start); - } else { - comment = va (0, " %d = illegal function", func); - } - } - break; - case ev_ptr: - comment = va (0, " %x", G_INT (pr, offset)); - break; - case ev_quaternion: - comment = va (0, " '%g %g %g %g'", - G_QUAT (pr, offset)[0], - G_QUAT (pr, offset)[1], - G_QUAT (pr, offset)[2], - G_QUAT (pr, offset)[3]); - break; - case ev_int: - comment = va (0, " %d", G_INT (pr, offset)); - break; - case ev_short: - break; - case ev_invalid: - comment = " struct?"; - break; - case ev_type_count: - break; + static dstring_t *value_dstr; + if (!value_dstr) { + value_dstr = dstring_newstr (); } + dstring_clearstr (value_dstr); + qfot_type_t *ty = &G_STRUCT (pr, qfot_type_t, def->type_encoding); + comment = PR_Debug_ValueString (pr, offset, ty, value_dstr); } printf ("%*s %x:%d %d %s %s:%x %s\n", indent * 12, "", offset, def->size, saveglobal, name, type, def->type_encoding, From 62ccafca8c5250c08b8a1d4a943118bf66763de4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Sep 2022 22:10:11 +0900 Subject: [PATCH 2963/3664] [qfcc] Fix incorrect progs source path handling The cvar rewrite changed how to deal with cvar setting in code and I messed it up for qfprogs. --- tools/qfcc/source/qfprogs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 20e59ea5c..3b8a62581 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -237,8 +237,7 @@ init_qf (void) PR_Init_Cvars (); pr_debug = 1 + verbosity; - free (pr_source_path); - pr_source_path = (char *) source_path; + Cvar_Set ("pr_source_path", source_path); pr.pr_edicts = &edicts; pr.num_edicts = &num_edicts; From 25a14eb2325e994caa69d78ce06ef24d372b1642 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Sep 2022 14:24:33 +0900 Subject: [PATCH 2964/3664] [renderer] Add a cell-based character buffer This is intended for the built-in 8x8 bitmap characters and quake's "conchars", but could potentially be used for any simple (non-composed characters) mono-spaced font. Currently, the buffers can be created, destroyed, cleared, scrolled vertically in either direction, and rendered to the screen in a single blast. One of the reasons for creating the buffer is to make it so scaling can be supported in the sw renderer. --- include/QF/GL/qf_draw.h | 2 + include/QF/GLSL/qf_draw.h | 2 + include/QF/Vulkan/qf_draw.h | 3 + include/QF/draw.h | 17 ++++ include/QF/plugin/vid_render.h | 3 + include/d_iface.h | 3 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/gl/gl_draw.c | 15 +++ libs/video/renderer/glsl/glsl_draw.c | 15 +++ libs/video/renderer/r_draw.c | 88 +++++++++++++++++ libs/video/renderer/r_progs.c | 121 +++++++++++++++++++++++ libs/video/renderer/sw/draw.c | 16 ++- libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_vulkan.c | 7 ++ libs/video/renderer/vulkan/vulkan_draw.c | 16 +++ 17 files changed, 311 insertions(+), 1 deletion(-) create mode 100644 libs/video/renderer/r_draw.c diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index 30315e7b0..7a7283c5c 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -30,9 +30,11 @@ struct qpic_s; struct rfont_s; +struct draw_charbuffer_s; void gl_Draw_Init (void); void gl_Draw_Shutdown (void); +void gl_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer); void gl_Draw_Character (int x, int y, unsigned ch); void gl_Draw_String (int x, int y, const char *str); void gl_Draw_nString (int x, int y, const char *str, int count); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index ea9b3e5dc..59ecb1668 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -30,9 +30,11 @@ struct qpic_s; struct rfont_s; +struct draw_charbuffer_s; void glsl_Draw_Init (void); void glsl_Draw_Shutdown (void); +void glsl_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer); void glsl_Draw_Character (int x, int y, unsigned ch); void glsl_Draw_String (int x, int y, const char *str); void glsl_Draw_nString (int x, int y, const char *str, int count); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 8006d1007..1da531fb1 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -32,7 +32,10 @@ struct vulkan_ctx_s; struct qfv_renderframe_s; struct qpic_s; struct rfont_s; +struct draw_charbuffer_s; +void Vulkan_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer, + struct vulkan_ctx_s *ctx); void Vulkan_Draw_Init (struct vulkan_ctx_s *ctx); void Vulkan_Draw_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Draw_Character (int x, int y, unsigned ch, diff --git a/include/QF/draw.h b/include/QF/draw.h index 532ea7a54..6646ad90a 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -41,6 +41,23 @@ #include "QF/wad.h" +/** Buffer for drawing text using quake conchars or the default 8x8 font. + + Characters are stored with the first character in the upper left, scanning + horizontally to the right. +*/ +typedef struct draw_charbuffer_s { + int width; ///< width in character cells + int height; ///< height in character cells + char *chars; ///< width * height characters +} draw_charbuffer_t; + +draw_charbuffer_t *Draw_CreateBuffer (int width, int height); +void Draw_DestroyBuffer (draw_charbuffer_t *buffer); +void Draw_ClearBuffer (draw_charbuffer_t *buffer); +void Draw_ScrollBuffer (draw_charbuffer_t *buffer, int lines); +void Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer); + extern byte *draw_chars; /** Initialize the draw stuff. diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 81365fbcd..b8b0bbda0 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -79,10 +79,13 @@ typedef struct vid_model_funcs_s { struct tex_s; struct rfont_s; +struct draw_charbuffer_s; + typedef void (*capfunc_t) (struct tex_s *screencap, void *data); typedef struct vid_render_funcs_s { void (*init) (void); + void (*Draw_CharBuffer) (int x, int y, struct draw_charbuffer_s *buffer); void (*Draw_Character) (int x, int y, unsigned ch); void (*Draw_String) (int x, int y, const char *str); void (*Draw_nString) (int x, int y, const char *str, int count); diff --git a/include/d_iface.h b/include/d_iface.h index b687e8df1..7f05c38bf 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -226,4 +226,7 @@ extern float r_skytime; extern int c_surf; +struct draw_charbuffer_s; +void sw_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer); + #endif // _D_IFACE_H diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index ca603d9e1..6d3db7023 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -50,6 +50,7 @@ libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs) libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_bsp.c \ libs/video/renderer/r_cvar.c \ + libs/video/renderer/r_draw.c \ libs/video/renderer/r_efrag.c \ libs/video/renderer/r_fog.c \ libs/video/renderer/r_font.c \ diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index a12cdf86c..9ee389775 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -486,6 +486,21 @@ tVA_increment (void) flush_text (); } +void +gl_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer) +{ + const byte *line = (byte *) buffer->chars; + int width = buffer->width; + int height = buffer->height; + while (height-- > 0) { + for (int i = 0; i < width; i++) { + gl_Draw_Character (x + i * 8, y, line[i]); + } + line += width; + y += 8; + } +} + /* Draw_Character diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index dcd9b0fb7..6258d3048 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -485,6 +485,21 @@ flush_2d (void) line_queue->size = 0; } +void +glsl_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer) +{ + const byte *line = (byte *) buffer->chars; + int width = buffer->width; + int height = buffer->height; + while (height-- > 0) { + for (int i = 0; i < width; i++) { + glsl_Draw_Character (x + i * 8, y, line[i]); + } + line += width; + y += 8; + } +} + void glsl_Draw_Character (int x, int y, unsigned int chr) { diff --git a/libs/video/renderer/r_draw.c b/libs/video/renderer/r_draw.c new file mode 100644 index 000000000..207980f88 --- /dev/null +++ b/libs/video/renderer/r_draw.c @@ -0,0 +1,88 @@ +/* + r_draw.c + + Renderer general draw support + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include + +#include "QF/draw.h" +#include "QF/render.h" + +#include "QF/plugin/vid_render.h" + +VISIBLE draw_charbuffer_t * +Draw_CreateBuffer (int width, int height) +{ + size_t size = width * height; + draw_charbuffer_t *buffer = malloc (sizeof (draw_charbuffer_t) + size); + buffer->width = width; + buffer->height = height; + buffer->chars = (char *) (buffer + 1); + return buffer; +} + +VISIBLE void +Draw_DestroyBuffer (draw_charbuffer_t *buffer) +{ + free (buffer); +} + +VISIBLE void +Draw_ClearBuffer (draw_charbuffer_t *buffer) +{ + memset (buffer->chars, ' ', buffer->height * buffer->width); +} + +VISIBLE void +Draw_ScrollBuffer (draw_charbuffer_t *buffer, int lines) +{ + int down = 0; + if (lines < 0) { + lines = -lines; + down = 1; + } + if (lines > buffer->height) { + lines = buffer->height; + } + if (down) { + memmove (buffer->chars + lines * buffer->width, buffer->chars, + (buffer->height - lines) * buffer->width); + memset (buffer->chars, ' ', lines * buffer->width); + } else { + memmove (buffer->chars, buffer->chars + lines * buffer->width, + (buffer->height - lines) * buffer->width); + memset (buffer->chars + (buffer->height - lines) * buffer->width, ' ', + lines * buffer->width); + } +} + +VISIBLE void +Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer) +{ + r_funcs->Draw_CharBuffer (x, y, buffer); +} diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 95f199242..7f20c0663 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -63,10 +63,17 @@ typedef struct qpic_res_s { char *name; } qpic_res_t; +typedef struct bi_charbuff_s { + struct bi_charbuff_s *next; + draw_charbuffer_t *buffer; +} bi_charbuff_t; + typedef struct { PR_RESMAP (qpic_res_t) qpic_map; + PR_RESMAP (bi_charbuff_t) charbuff_map; qpic_res_t *qpics; hashtab_t *pic_hash; + bi_charbuff_t *charbuffs; } draw_resources_t; static qpic_res_t * @@ -121,6 +128,47 @@ get_qpic (progs_t *pr, draw_resources_t *res, const char *name, int qpic_handle) return qp; } +static bi_charbuff_t * +charbuff_new (draw_resources_t *res) +{ + return PR_RESNEW (res->charbuff_map); +} + +static void +charbuff_free (draw_resources_t *res, bi_charbuff_t *cbuff) +{ + Draw_DestroyBuffer (cbuff->buffer); + PR_RESFREE (res->charbuff_map, cbuff); +} + +static void +charbuff_reset (draw_resources_t *res) +{ + PR_RESRESET (res->charbuff_map); +} + +static inline bi_charbuff_t * +charbuff_get (draw_resources_t *res, int index) +{ + return PR_RESGET (res->charbuff_map, index); +} + +static inline int __attribute__((pure)) +charbuff_index (draw_resources_t *res, bi_charbuff_t *qp) +{ + return PR_RESINDEX (res->charbuff_map, qp); +} + +static bi_charbuff_t * __attribute__((pure)) +get_charbuff (progs_t *pr, draw_resources_t *res, const char *name, int charbuff_handle) +{ + bi_charbuff_t *cbuff = charbuff_get (res, charbuff_handle); + + if (!cbuff) + PR_RunError (pr, "invalid charbuff handle passed to %s", name + 3); + return cbuff; +} + static void bi_Draw_FreePic (progs_t *pr, void *_res) { @@ -354,6 +402,66 @@ bi_Font_String (progs_t *pr, void *_res) r_funcs->Draw_FontString (x, y, str); } +static void +bi_Draw_CreateBuffer (progs_t *pr, void *_res) +{ + draw_resources_t *res = _res; + int width = P_INT (pr, 0); + int height = P_INT (pr, 1); + draw_charbuffer_t *buffer; + bi_charbuff_t *cbuff; + + buffer = Draw_CreateBuffer (width, height); + cbuff = charbuff_new (res); + cbuff->next = res->charbuffs; + res->charbuffs = cbuff; + cbuff->buffer = buffer; + R_INT (pr) = charbuff_index (res, cbuff); +} + +static void +bi_Draw_DestroyBuffer (progs_t *pr, void *_res) +{ + draw_resources_t *res = _res; + pr_ptr_t cbuff_handle = P_POINTER (pr, 0); + bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle); + + charbuff_free (res, cbuff); +} + +static void +bi_Draw_ClearBuffer (progs_t *pr, void *_res) +{ + draw_resources_t *res = _res; + pr_ptr_t cbuff_handle = P_POINTER (pr, 0); + bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle); + + Draw_ClearBuffer (cbuff->buffer); +} + +static void +bi_Draw_ScrollBuffer (progs_t *pr, void *_res) +{ + draw_resources_t *res = _res; + pr_ptr_t cbuff_handle = P_POINTER (pr, 0); + bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle); + int lines = P_INT (pr, 1); + + Draw_ScrollBuffer (cbuff->buffer, lines); +} + +static void +bi_Draw_CharBuffer (progs_t *pr, void *_res) +{ + draw_resources_t *res = _res; + int x = P_INT (pr, 0); + int y = P_INT (pr, 1); + pr_ptr_t cbuff_handle = P_POINTER (pr, 2); + bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle); + + Draw_CharBuffer (x, y, cbuff->buffer); +} + static const char * bi_draw_get_key (const void *p, void *unused) { @@ -365,13 +473,20 @@ bi_draw_clear (progs_t *pr, void *_res) { draw_resources_t *res = (draw_resources_t *) _res; qpic_res_t *qp; + bi_charbuff_t *cbuff; for (qp = res->qpics; qp; qp = qp->next) { bi_draw_free_qpic (qp); } res->qpics = 0; + for (cbuff = res->charbuffs; cbuff; cbuff = cbuff->next) { + Draw_DestroyBuffer (cbuff->buffer); + } + res->charbuffs = 0; + qpic_reset (res); + charbuff_reset (res); Hash_FlushTable (res->pic_hash); } @@ -406,6 +521,12 @@ static builtin_t builtins[] = { bi(Font_Load, 2, p(string), p(int)), bi(Font_String, 3, p(int), p(int), p(string)), + + bi(Draw_CreateBuffer, 2, p(int), p(int)), + bi(Draw_DestroyBuffer, 1, p(ptr)), + bi(Draw_ClearBuffer, 1, p(ptr)), + bi(Draw_ScrollBuffer, 2, p(ptr), p(int)), + bi(Draw_CharBuffer, 3, p(int), p(int), p(ptr)), {0} }; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 671244755..06db109af 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -245,7 +245,6 @@ Draw_Init (void) } } - /* Draw_Character @@ -306,6 +305,21 @@ Draw_Character (int x, int y, unsigned int chr) } } +void +sw_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer) +{ + const byte *line = (byte *) buffer->chars; + int width = buffer->width; + int height = buffer->height; + while (height-- > 0) { + for (int i = 0; i < width; i++) { + Draw_Character (x + i * 8, y, line[i]); + } + line += width; + y += 8; + } +} + void Draw_String (int x, int y, const char *str) diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index ea8a10049..dac319acf 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -486,6 +486,7 @@ gl_capture_screen (capfunc_t callback, void *data) vid_render_funcs_t gl_vid_render_funcs = { gl_vid_render_init, + gl_Draw_CharBuffer, gl_Draw_Character, gl_Draw_String, gl_Draw_nString, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 2ffb0cf22..02242755c 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -430,6 +430,7 @@ glsl_capture_screen (capfunc_t callback, void *data) vid_render_funcs_t glsl_vid_render_funcs = { glsl_vid_render_init, + glsl_Draw_CharBuffer, glsl_Draw_Character, glsl_Draw_String, glsl_Draw_nString, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 2dc9b8a42..060c9ac0a 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -450,6 +450,7 @@ sw_capture_screen (capfunc_t callback, void *data) vid_render_funcs_t sw_vid_render_funcs = { sw_vid_render_init, + sw_Draw_CharBuffer, Draw_Character, Draw_String, Draw_nString, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 6519f1740..acb38d4d6 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -135,6 +135,12 @@ vulkan_R_LineGraph (int x, int y, int *h_vals, int count, int height) { } +static void +vulkan_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer) +{ + Vulkan_Draw_CharBuffer (x, y, buffer, vulkan_ctx); +} + static void vulkan_Draw_Character (int x, int y, unsigned ch) { @@ -740,6 +746,7 @@ vulkan_vid_render_shutdown (void) vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_vid_render_init, + vulkan_Draw_CharBuffer, vulkan_Draw_Character, vulkan_Draw_String, vulkan_Draw_nString, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index a3693426a..7a604860a 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -571,6 +571,22 @@ queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx) &frame->quad_verts); } +void +Vulkan_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer, + vulkan_ctx_t *ctx) +{ + const byte *line = (byte *) buffer->chars; + int width = buffer->width; + int height = buffer->height; + while (height-- > 0) { + for (int i = 0; i < width; i++) { + Vulkan_Draw_Character (x + i * 8, y, line[i], ctx); + } + line += width; + y += 8; + } +} + void Vulkan_Draw_Character (int x, int y, unsigned int chr, vulkan_ctx_t *ctx) { From c5099d30b18d67d896c7ca34c145a675c0f4c992 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Sep 2022 14:32:16 +0900 Subject: [PATCH 2965/3664] [renderer] Fix access to freed memory loading fonts QFS_LoadFile closes its file argument (this is a design error resulting from changing QFS_LoadFile to take a file instead of a path and not completing the update), resulting in the call to Qfilesize accessing freed memory. --- libs/video/renderer/r_font.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/r_font.c b/libs/video/renderer/r_font.c index e7c0ddf52..2421925a5 100644 --- a/libs/video/renderer/r_font.c +++ b/libs/video/renderer/r_font.c @@ -87,7 +87,7 @@ R_FontLoad (QFile *font_file, int size) if (!font_data) { return 0; } - size_t font_size = Qfilesize (font_file);; + size_t font_size = qfs_filesize; rfont_t *font = calloc (1, sizeof (rfont_t)); font->font_resource = font_data; if (FT_New_Memory_Face (ft, font_data, font_size, 0, &font->face)) { From 437e447b6bbe4ad139c8098d60a547fd9921546b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Sep 2022 00:58:25 +0900 Subject: [PATCH 2966/3664] [renderer] Add a buffer print function It handles basic cursor motion respecting \r \n \f and \t (might be a problem for id chars), wraps at the right edge, and automatically scrolls when the cursor tries to pass the bottom of the screen. Clearing the buffer resets its cursor to the upper left. --- include/QF/draw.h | 3 +++ libs/video/renderer/r_draw.c | 50 +++++++++++++++++++++++++++++++++++ libs/video/renderer/r_progs.c | 12 +++++++++ 3 files changed, 65 insertions(+) diff --git a/include/QF/draw.h b/include/QF/draw.h index 6646ad90a..bbbbf8e9d 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -50,6 +50,8 @@ typedef struct draw_charbuffer_s { int width; ///< width in character cells int height; ///< height in character cells char *chars; ///< width * height characters + int cursx; ///< horizontal cursor position + int cursy; ///< vertical cursor position } draw_charbuffer_t; draw_charbuffer_t *Draw_CreateBuffer (int width, int height); @@ -57,6 +59,7 @@ void Draw_DestroyBuffer (draw_charbuffer_t *buffer); void Draw_ClearBuffer (draw_charbuffer_t *buffer); void Draw_ScrollBuffer (draw_charbuffer_t *buffer, int lines); void Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer); +void Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str); extern byte *draw_chars; diff --git a/libs/video/renderer/r_draw.c b/libs/video/renderer/r_draw.c index 207980f88..3b2285ad5 100644 --- a/libs/video/renderer/r_draw.c +++ b/libs/video/renderer/r_draw.c @@ -43,6 +43,7 @@ Draw_CreateBuffer (int width, int height) buffer->width = width; buffer->height = height; buffer->chars = (char *) (buffer + 1); + buffer->cursx = buffer->cursy = 0; return buffer; } @@ -56,6 +57,7 @@ VISIBLE void Draw_ClearBuffer (draw_charbuffer_t *buffer) { memset (buffer->chars, ' ', buffer->height * buffer->width); + buffer->cursx = buffer->cursy = 0; } VISIBLE void @@ -86,3 +88,51 @@ Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer) { r_funcs->Draw_CharBuffer (x, y, buffer); } + +#define TAB 8 + +VISIBLE void +Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str) +{ + char *dst = buffer->chars; + char c; + int tab; + dst += buffer->cursy * buffer->width + buffer->cursx; + while ((c = *str++)) { + switch (c) { + case '\r': + dst -= buffer->cursx; + buffer->cursx = 0; + break; + case '\n': + dst -= buffer->cursx; + buffer->cursx = 0; + dst += buffer->width; + buffer->cursy++; + break; + case '\f': + dst += buffer->width; + buffer->cursy++; + break; + case '\t': + tab = TAB - buffer->cursx % TAB; + buffer->cursx += tab; + dst += tab; + break; + default: + *dst++ = c; + buffer->cursx++; + break; + } + if (buffer->cursx >= buffer->width) { + buffer->cursx -= buffer->width; + buffer->cursy++; + } + if (buffer->cursy >= buffer->height) { + int lines = buffer->cursy - buffer->height + 1; + Draw_ScrollBuffer (buffer, lines); + dst -= lines * buffer->width; + buffer->cursy -= lines; + } + } +} diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 7f20c0663..2b33da012 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -462,6 +462,17 @@ bi_Draw_CharBuffer (progs_t *pr, void *_res) Draw_CharBuffer (x, y, cbuff->buffer); } +static void +bi_Draw_PrintBuffer (progs_t *pr, void *_res) +{ + draw_resources_t *res = _res; + pr_ptr_t cbuff_handle = P_POINTER (pr, 0); + bi_charbuff_t *cbuff = get_charbuff (pr, res, __FUNCTION__, cbuff_handle); + const char *str = P_GSTRING (pr, 1); + + Draw_PrintBuffer (cbuff->buffer, str); +} + static const char * bi_draw_get_key (const void *p, void *unused) { @@ -527,6 +538,7 @@ static builtin_t builtins[] = { bi(Draw_ClearBuffer, 1, p(ptr)), bi(Draw_ScrollBuffer, 2, p(ptr), p(int)), bi(Draw_CharBuffer, 3, p(int), p(int), p(ptr)), + bi(Draw_PrintBuffer, 2, p(ptr), p(string)), {0} }; From d13df6cd3777f53ba6c97005bfadd1aadba816f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 17 Sep 2022 12:59:36 +0900 Subject: [PATCH 2967/3664] [console] Add failing unit test for con_buffer I was looking through the code for Con_BufferAddText trying to figure out what it was doing (answer: ring buffer for both text and lines) and got suspicious about its handling of the line objects. I decided an automated test was in order. It turns out I was right: filling the buffer with a single long line causes the tail line to trample the current line, setting its pointer and length to 0 when the final character is put in the buffer. --- libs/console/Makemodule.am | 2 + libs/console/test/Makemodule.am | 15 +++++ libs/console/test/test-buffer.c | 111 ++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 libs/console/test/Makemodule.am create mode 100644 libs/console/test/test-buffer.c diff --git a/libs/console/Makemodule.am b/libs/console/Makemodule.am index fee9f194d..bf8a24f30 100644 --- a/libs/console/Makemodule.am +++ b/libs/console/Makemodule.am @@ -1,3 +1,5 @@ +include libs/console/test/Makemodule.am + lib_LTLIBRARIES += libs/console/libQFconsole.la plugin_LTLIBRARIES += @console_plugins@ noinst_LTLIBRARIES += @client_static_plugins@ @server_static_plugins@ diff --git a/libs/console/test/Makemodule.am b/libs/console/test/Makemodule.am new file mode 100644 index 000000000..2116b5919 --- /dev/null +++ b/libs/console/test/Makemodule.am @@ -0,0 +1,15 @@ +libs_console_tests = \ + libs/console/test/test-buffer + +TESTS += $(libs_console_tests) + +check_PROGRAMS += $(libs_console_tests) + +test_console_libs= \ + libs/console/libQFconsole.la \ + libs/util/libQFutil.la + +libs_console_test_test_buffer_SOURCES= \ + libs/console/test/test-buffer.c +libs_console_test_test_buffer_LDADD= $(test_console_libs) +libs_console_test_test_buffer_DEPENDENCIES=$(test_console_libs) diff --git a/libs/console/test/test-buffer.c b/libs/console/test/test-buffer.c new file mode 100644 index 000000000..692a9c780 --- /dev/null +++ b/libs/console/test/test-buffer.c @@ -0,0 +1,111 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "QF/console.h" + +static int +test_1 (void) +{ + int ret = 1; + __auto_type con = Con_CreateBuffer (1024, 25); + if (!con) { + printf ("con_buffer allocation failed\n"); + goto fail; + } + if (!con->buffer) { + printf ("con_buffer buffer not set\n"); + goto fail; + } + if (!con->lines) { + printf ("con_buffer lines not set\n"); + goto fail; + } + if (con->buffer_size != 1024) { + printf ("con_buffer buffer_size incorrect: %zd\n", con->buffer_size); + goto fail; + } + if (con->max_lines != 25) { + printf ("con_buffer max_lines incorrect: %d\n", con->max_lines); + goto fail; + } + if (con->num_lines != 1) { + printf ("con_buffer num_lines incorrect: %d\n", con->num_lines); + goto fail; + } + if (con->cur_line != 0) { + printf ("con_buffer cur_line incorrect: %d\n", con->cur_line); + goto fail; + } + if (con->lines[con->cur_line].text != con->buffer) { + printf ("con_buffer cur_line.text incorrect: %p, %p\n", + con->lines[con->cur_line].text, con->buffer); + goto fail; + } + if (con->lines[con->cur_line].len != 0) { + printf ("con_buffer cur_line.line incorrect: %zd\n", + con->lines[con->cur_line].len); + goto fail; + } + + ret = 0; +fail: + Con_DestroyBuffer (con); + return ret; +} + +static int +test_2 (void) +{ + int ret = 1; + char text[2049]; + + for (size_t i = 0; i < sizeof (text); i++) { + int x = i % 13; + text[i] = x + (x > 9 ? 'a' - 10 : '0'); + } + text[sizeof(text) - 1] = 0; + + __auto_type con = Con_CreateBuffer (1024, 25); + Con_BufferAddText (con, text); + + if (con->num_lines != 1) { + printf ("con_buffer num_lines incorrect: %d\n", con->num_lines); + goto fail; + } + if (con->cur_line != 0) { + printf ("con_buffer cur_line incorrect: %d\n", con->cur_line); + goto fail; + } + if (con->lines[con->cur_line].text != con->buffer) { + printf ("con_buffer cur_line.text incorrect: %p, %p\n", + con->lines[con->cur_line].text, con->buffer); + goto fail; + } + if (con->lines[con->cur_line].len != 1024) { + printf ("con_buffer cur_line.line incorrect: %zd\n", + con->lines[con->cur_line].len); + goto fail; + } + + ret = 0; +fail: + if (ret) { + printf ("%s failed\n", __FUNCTION__); + } + Con_DestroyBuffer (con); + return ret; +} + +int +main (void) +{ + int ret = 0; + ret |= test_1 (); + ret |= test_2 (); + return ret; +} From 9a92496662726da1af29ab252218808e5628463d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 17 Sep 2022 13:56:23 +0900 Subject: [PATCH 2968/3664] [console] Don't overwrite tail line if same as current line This fixes the current line object getting corrupted by the tail line update when the buffer is filled with a single line. There are probably more tests to write and bugs to fix :) --- libs/console/buffer.c | 13 ++++++------- libs/console/test/test-buffer.c | 4 ++++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libs/console/buffer.c b/libs/console/buffer.c index 2aa477abc..5f2d46ddf 100644 --- a/libs/console/buffer.c +++ b/libs/console/buffer.c @@ -91,19 +91,18 @@ Con_BufferAddText (con_buffer_t *buf, const char *text) len = buf->buffer_size; } while (len--) { - byte c = *pos++ = *text++; - if (pos >= buf->buffer + buf->buffer_size) - pos = buf->buffer; - cur_line->len++; - if (pos == tail_line->text) { - if (buf->num_lines > 0) - buf->num_lines--; + if (buf->num_lines > 1 && pos == tail_line->text) { + buf->num_lines--; tail_line->text = 0; tail_line->len = 0; tail_line++; if (tail_line - buf->lines >= buf->max_lines) tail_line = buf->lines; } + byte c = *pos++ = *text++; + if (pos >= buf->buffer + buf->buffer_size) + pos = buf->buffer; + cur_line->len++; if (c == '\n') { if (buf->num_lines < buf->max_lines) buf->num_lines++; diff --git a/libs/console/test/test-buffer.c b/libs/console/test/test-buffer.c index 692a9c780..21738d350 100644 --- a/libs/console/test/test-buffer.c +++ b/libs/console/test/test-buffer.c @@ -91,6 +91,10 @@ test_2 (void) con->lines[con->cur_line].len); goto fail; } + if (memcmp (con->buffer, text + 1024, 1024)) { + printf ("con_buffer incorrect\n"); + goto fail; + } ret = 0; fail: From c8c1d2e642bc2f06ddf62632563649490e9f17ca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 17 Sep 2022 14:22:28 +0900 Subject: [PATCH 2969/3664] [console] Add a pile of of comments to Con_BufferAddText And make tail_line setup a little clearer. --- libs/console/buffer.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libs/console/buffer.c b/libs/console/buffer.c index 5f2d46ddf..01fe7412a 100644 --- a/libs/console/buffer.c +++ b/libs/console/buffer.c @@ -78,19 +78,27 @@ VISIBLE void Con_BufferAddText (con_buffer_t *buf, const char *text) { con_line_t *cur_line = &buf->lines[buf->cur_line]; - con_line_t *tail_line; size_t len = strlen (text); - byte *pos = cur_line->text + cur_line->len; + // Point to the oldest line in the buffer (first to be dropped when + // the buffer overflows). + con_line_t *tail_line = buf->lines + (buf->cur_line + 1 - buf->num_lines + + buf->max_lines) % buf->max_lines; + byte *pos = cur_line->text + cur_line->len; if (pos >= buf->buffer + buf->buffer_size) pos -= buf->buffer_size; - tail_line = buf->lines + (buf->cur_line + buf->max_lines + 1 - - buf->num_lines) % buf->max_lines; + + // Limit the appended text to the size of the buffer. The entire buffer + // may be overwritten. if (len > buf->buffer_size) { text += len - buf->buffer_size; len = buf->buffer_size; } while (len--) { + // Drop the oldest line if it will be overwritten by the next + // character to be inserted. However, if there is only one line, + // then tail_line is effectively invalid and should not be touched. + // This happens when the buffer is filled with a single line of text. if (buf->num_lines > 1 && pos == tail_line->text) { buf->num_lines--; tail_line->text = 0; @@ -99,10 +107,14 @@ Con_BufferAddText (con_buffer_t *buf, const char *text) if (tail_line - buf->lines >= buf->max_lines) tail_line = buf->lines; } + + // Copy character into the buffer, updating the current line length + // (trailing \n is part of the line). byte c = *pos++ = *text++; if (pos >= buf->buffer + buf->buffer_size) pos = buf->buffer; cur_line->len++; + if (c == '\n') { if (buf->num_lines < buf->max_lines) buf->num_lines++; From 5e8d18a7745c53d35fac54b2507d62ac9cbc9ab2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 17 Sep 2022 15:31:52 +0900 Subject: [PATCH 2970/3664] [console] Add failing test for adding to full 1-line buffer I've decided that appending to a full single-line buffer should simply scroll through the existing text. Unsurprisingly, the existing code doesn't handle the situation all that well. While I've already got a fix for it, I think I've got a better idea that will handle full buffers more gracefully. --- libs/console/test/test-buffer.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/libs/console/test/test-buffer.c b/libs/console/test/test-buffer.c index 21738d350..5ebeca7a5 100644 --- a/libs/console/test/test-buffer.c +++ b/libs/console/test/test-buffer.c @@ -96,6 +96,35 @@ test_2 (void) goto fail; } + // add a single char at the end of the full buffer the buffer should + // just effectively scroll through the text as chars are added (via + // the single line object maintaining constant length but updating its + // text pointer) + Con_BufferAddText (con, "N"); + if (con->num_lines != 1) { + printf ("con_buffer num_lines incorrect: %d\n", con->num_lines); + goto fail; + } + if (con->cur_line != 0) { + printf ("con_buffer cur_line incorrect: %d\n", con->cur_line); + goto fail; + } + if (con->lines[con->cur_line].text != con->buffer + 1) { + printf ("con_buffer cur_line.text incorrect: %p, %p\n", + con->lines[con->cur_line].text, con->buffer + 1); + goto fail; + } + if (con->lines[con->cur_line].len != 1024) { + printf ("con_buffer cur_line.line incorrect: %zd\n", + con->lines[con->cur_line].len); + goto fail; + } + if (memcmp (con->buffer + 1, text + 1024 + 1, 1024 - 1) + || con->buffer[0] != 'N') { + printf ("con_buffer incorrect\n"); + goto fail; + } + ret = 0; fail: if (ret) { From 48e5848a41105d3c2ba96e68a5023141417a05c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Sep 2022 11:30:40 +0900 Subject: [PATCH 2971/3664] [console] Rework con_buffer ring buffers to have gaps I really don't know why I tried to do ring-buffers without gaps, the code complication is just not worth the tiny savings in memory. In fact, just the switch from pointers to 32-bit offsets saves more memory than not having gaps (on 64-bit systems, no change on 32-bit). --- include/QF/console.h | 19 ++++--- libs/client/cl_input.c | 1 + libs/console/buffer.c | 87 ++++++++++++++++----------------- libs/console/menu.c | 1 + libs/console/server.c | 15 +++--- libs/console/test/test-buffer.c | 75 ++++++++++++++-------------- 6 files changed, 101 insertions(+), 97 deletions(-) diff --git a/include/QF/console.h b/include/QF/console.h index 372263803..79aac8e69 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -28,9 +28,8 @@ #ifndef __QF_console_h #define __QF_console_h -#include +#include -#include "QF/keys.h" #include "QF/qtypes.h" /** \defgroup console 2d Console Stuff @@ -47,17 +46,17 @@ typedef struct } old_console_t; typedef struct { - byte *text; - size_t len; + uint32_t text; + uint32_t len; } con_line_t; typedef struct { - byte *buffer; - size_t buffer_size; - con_line_t *lines; - int max_lines; // size of lines array - int num_lines; // number of lines used - int cur_line; // current line + byte *buffer; + con_line_t *lines; + uint32_t buffer_size; + uint32_t max_lines; // size of lines array + uint32_t line_head; // number of lines used + uint32_t line_tail; // current line } con_buffer_t; typedef enum { diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 7830aa830..008297eb2 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -43,6 +43,7 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/input.h" +#include "QF/keys.h" #include "QF/plist.h" #include "QF/sys.h" diff --git a/libs/console/buffer.c b/libs/console/buffer.c index 01fe7412a..b484bcfa9 100644 --- a/libs/console/buffer.c +++ b/libs/console/buffer.c @@ -55,9 +55,8 @@ Con_CreateBuffer (size_t buffer_size, int max_lines) if (!(buffer->lines = calloc (max_lines, sizeof (con_line_t)))) goto err; buffer->max_lines = max_lines; - buffer->num_lines = 1; - buffer->cur_line = 0; - buffer->lines[0].text = buffer->buffer; + buffer->line_head = 1; + buffer->line_tail = 0; return buffer; err: if (buffer->buffer) @@ -77,54 +76,52 @@ Con_DestroyBuffer (con_buffer_t *buffer) VISIBLE void Con_BufferAddText (con_buffer_t *buf, const char *text) { - con_line_t *cur_line = &buf->lines[buf->cur_line]; - size_t len = strlen (text); - // Point to the oldest line in the buffer (first to be dropped when - // the buffer overflows). - con_line_t *tail_line = buf->lines + (buf->cur_line + 1 - buf->num_lines - + buf->max_lines) % buf->max_lines; + con_line_t *cur_line = &buf->lines[(buf->line_head - 1 + buf->max_lines) + % buf->max_lines]; + con_line_t *tail_line = &buf->lines[buf->line_tail]; + uint32_t text_head = (cur_line->text + cur_line->len) % buf->buffer_size; + byte c; - byte *pos = cur_line->text + cur_line->len; - if (pos >= buf->buffer + buf->buffer_size) - pos -= buf->buffer_size; - - // Limit the appended text to the size of the buffer. The entire buffer - // may be overwritten. - if (len > buf->buffer_size) { - text += len - buf->buffer_size; - len = buf->buffer_size; - } - while (len--) { - // Drop the oldest line if it will be overwritten by the next - // character to be inserted. However, if there is only one line, - // then tail_line is effectively invalid and should not be touched. - // This happens when the buffer is filled with a single line of text. - if (buf->num_lines > 1 && pos == tail_line->text) { - buf->num_lines--; - tail_line->text = 0; - tail_line->len = 0; - tail_line++; - if (tail_line - buf->lines >= buf->max_lines) - tail_line = buf->lines; - } - - // Copy character into the buffer, updating the current line length - // (trailing \n is part of the line). - byte c = *pos++ = *text++; - if (pos >= buf->buffer + buf->buffer_size) - pos = buf->buffer; + while ((c = *text++)) { cur_line->len++; + buf->buffer[text_head++] = c; + if (text_head >= buf->buffer_size) { + text_head -= buf->buffer_size; + } + if (text_head == tail_line->text) { + tail_line->len--; + buf->buffer[tail_line->text++] = 0; + if (tail_line->text >= buf->buffer_size) { + tail_line->text -= buf->buffer_size; + } + if (!tail_line->len) { + buf->line_tail++; + buf->line_tail %= buf->max_lines; + tail_line = &buf->lines[buf->line_tail]; + } + } if (c == '\n') { - if (buf->num_lines < buf->max_lines) - buf->num_lines++; cur_line++; - buf->cur_line++; - if (cur_line - buf->lines >= buf->max_lines) - cur_line = buf->lines; - cur_line->text = pos; + if (cur_line - buf->lines >= buf->max_lines) { + cur_line -= buf->max_lines; + } + cur_line->text = text_head; cur_line->len = 0; + + buf->line_head++; + if (buf->line_head >= buf->max_lines) { + buf->line_head -= buf->max_lines; + } + + if (buf->line_head == buf->line_tail) { + buf->lines[buf->line_tail].text = 0; + buf->lines[buf->line_tail].len = 0; + buf->line_tail++; + if (buf->line_tail >= buf->max_lines) { + buf->line_tail -= buf->max_lines; + } + } } } - buf->cur_line %= buf->max_lines; } diff --git a/libs/console/menu.c b/libs/console/menu.c index ef57dc8de..093caf8d0 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -40,6 +40,7 @@ #include "QF/cvar.h" #include "QF/draw.h" #include "QF/hash.h" +#include "QF/keys.h" #include "QF/progs.h" #include "QF/quakefs.h" #include "QF/render.h" diff --git a/libs/console/server.c b/libs/console/server.c index b0ba04a31..173b422ee 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -277,7 +277,7 @@ draw_output (view_t *view) // this is not the most efficient way to update the screen, but oh well int lines = view->ylen - 1; // leave a blank line int width = view->xlen; - int cur_line = output_buffer->cur_line + view_offset; + int cur_line = output_buffer->line_head - 1 + view_offset; int i, y; if (lines < 1) @@ -297,7 +297,7 @@ draw_output (view_t *view) wmove (win, 0, 0); do { con_line_t *l = Con_BufferLine (output_buffer, cur_line++); - byte *text = l->text; + byte *text = output_buffer->buffer + l->text; int len = l->len; if (y > 0) { @@ -306,12 +306,12 @@ draw_output (view_t *view) y = 0; if (len < 1) { len = 1; - text = l->text + l->len - 1; + text = output_buffer->buffer + l->text + l->len - 1; } } while (len--) draw_fun_char (win, *text++, 0); - } while (cur_line < output_buffer->cur_line + view_offset); + } while (cur_line < (int) output_buffer->line_head - 1 + view_offset); } static void @@ -526,14 +526,17 @@ key_event (knum_t key, short unicode, qboolean down) int ovf = view_offset; sv_view_t *sv_view; con_buffer_t *buffer; + int num_lines; switch (key) { case QFK_PAGEUP: view_offset -= 10; sv_view = output->data; buffer = sv_view->obj; - if (view_offset <= -(buffer->num_lines - (screen_y - 3))) - view_offset = -(buffer->num_lines - (screen_y - 3)) + 1; + num_lines = (buffer->line_head - buffer->line_tail + + buffer->max_lines) % buffer->max_lines; + if (view_offset <= -(num_lines - (screen_y - 3))) + view_offset = -(num_lines - (screen_y - 3)) + 1; if (ovf != view_offset) sv_draw (output); break; diff --git a/libs/console/test/test-buffer.c b/libs/console/test/test-buffer.c index 5ebeca7a5..3285297b0 100644 --- a/libs/console/test/test-buffer.c +++ b/libs/console/test/test-buffer.c @@ -26,29 +26,29 @@ test_1 (void) goto fail; } if (con->buffer_size != 1024) { - printf ("con_buffer buffer_size incorrect: %zd\n", con->buffer_size); + printf ("con_buffer buffer_size incorrect: %u\n", con->buffer_size); goto fail; } if (con->max_lines != 25) { printf ("con_buffer max_lines incorrect: %d\n", con->max_lines); goto fail; } - if (con->num_lines != 1) { - printf ("con_buffer num_lines incorrect: %d\n", con->num_lines); + if (con->line_head != 1) { + printf ("con_buffer line_head incorrect: %d\n", con->line_head); goto fail; } - if (con->cur_line != 0) { - printf ("con_buffer cur_line incorrect: %d\n", con->cur_line); + if (con->line_tail != 0) { + printf ("con_buffer line_tail incorrect: %d\n", con->line_tail); goto fail; } - if (con->lines[con->cur_line].text != con->buffer) { - printf ("con_buffer cur_line.text incorrect: %p, %p\n", - con->lines[con->cur_line].text, con->buffer); + if (con->lines[con->line_tail].text != 0) { + printf ("con_buffer line_tail.text incorrect: %u\n", + con->lines[con->line_tail].text); goto fail; } - if (con->lines[con->cur_line].len != 0) { - printf ("con_buffer cur_line.line incorrect: %zd\n", - con->lines[con->cur_line].len); + if (con->lines[con->line_tail].len != 0) { + printf ("con_buffer line_tail.len incorrect: %u\n", + con->lines[con->line_tail].len); goto fail; } @@ -73,55 +73,58 @@ test_2 (void) __auto_type con = Con_CreateBuffer (1024, 25); Con_BufferAddText (con, text); - if (con->num_lines != 1) { - printf ("con_buffer num_lines incorrect: %d\n", con->num_lines); + if (con->line_head != 1) { + printf ("con_buffer num_lines incorrect: %d\n", con->line_head); goto fail; } - if (con->cur_line != 0) { - printf ("con_buffer cur_line incorrect: %d\n", con->cur_line); + if (con->line_tail != 0) { + printf ("con_buffer line_tail incorrect: %d\n", con->line_tail); goto fail; } - if (con->lines[con->cur_line].text != con->buffer) { - printf ("con_buffer cur_line.text incorrect: %p, %p\n", - con->lines[con->cur_line].text, con->buffer); + if (con->lines[con->line_tail].text != 1) { + printf ("con_buffer line_tail.text incorrect: %u\n", + con->lines[con->line_tail].text); goto fail; } - if (con->lines[con->cur_line].len != 1024) { - printf ("con_buffer cur_line.line incorrect: %zd\n", - con->lines[con->cur_line].len); + if (con->lines[con->line_tail].len != 1023) { + printf ("con_buffer line_tail.len incorrect: %u\n", + con->lines[con->line_tail].len); goto fail; } - if (memcmp (con->buffer, text + 1024, 1024)) { + if (memcmp (con->buffer + 1, text + 1025, 1023) + || con->buffer[0] != 0) { printf ("con_buffer incorrect\n"); goto fail; } - // add a single char at the end of the full buffer the buffer should + // Add a single char at the end of the full buffer. The buffer should // just effectively scroll through the text as chars are added (via // the single line object maintaining constant length but updating its // text pointer) Con_BufferAddText (con, "N"); - if (con->num_lines != 1) { - printf ("con_buffer num_lines incorrect: %d\n", con->num_lines); + + if (con->line_head != 1) { + printf ("2 con_buffer num_lines incorrect: %d\n", con->line_head); goto fail; } - if (con->cur_line != 0) { - printf ("con_buffer cur_line incorrect: %d\n", con->cur_line); + if (con->line_tail != 0) { + printf ("2 con_buffer line_tail incorrect: %d\n", con->line_tail); goto fail; } - if (con->lines[con->cur_line].text != con->buffer + 1) { - printf ("con_buffer cur_line.text incorrect: %p, %p\n", - con->lines[con->cur_line].text, con->buffer + 1); + if (con->lines[con->line_tail].text != 2) { + printf ("2 con_buffer line_tail.text incorrect: %u\n", + con->lines[con->line_tail].text); goto fail; } - if (con->lines[con->cur_line].len != 1024) { - printf ("con_buffer cur_line.line incorrect: %zd\n", - con->lines[con->cur_line].len); + if (con->lines[con->line_tail].len != 1023) { + printf ("2 con_buffer line_tail.len incorrect: %u\n", + con->lines[con->line_tail].len); goto fail; } - if (memcmp (con->buffer + 1, text + 1024 + 1, 1024 - 1) - || con->buffer[0] != 'N') { - printf ("con_buffer incorrect\n"); + if (memcmp (con->buffer + 2, text + 1026, 1022) + || con->buffer[0] != 'N' + || con->buffer[1] != 0) { + printf ("2 con_buffer incorrect\n"); goto fail; } From 3eceb444d35385bb1faa70bd4a3127cc94ef3ff3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Sep 2022 16:07:22 +0900 Subject: [PATCH 2972/3664] [console] Add test for buffer line tracking Seems to work, so I guess con_buffer is ok now. --- libs/console/test/test-buffer.c | 93 ++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/libs/console/test/test-buffer.c b/libs/console/test/test-buffer.c index 3285297b0..176e019a2 100644 --- a/libs/console/test/test-buffer.c +++ b/libs/console/test/test-buffer.c @@ -74,7 +74,7 @@ test_2 (void) Con_BufferAddText (con, text); if (con->line_head != 1) { - printf ("con_buffer num_lines incorrect: %d\n", con->line_head); + printf ("con_buffer line_head incorrect: %d\n", con->line_head); goto fail; } if (con->line_tail != 0) { @@ -104,7 +104,7 @@ test_2 (void) Con_BufferAddText (con, "N"); if (con->line_head != 1) { - printf ("2 con_buffer num_lines incorrect: %d\n", con->line_head); + printf ("2 con_buffer line_head incorrect: %d\n", con->line_head); goto fail; } if (con->line_tail != 0) { @@ -137,11 +137,100 @@ fail: return ret; } +static int +test_3 (void) +{ + int ret = 1; + static char text[] = R"(01 don't forget this line +02 and some more lines here +03 adsf +04 adfa +06 hi there +06 don't forget there's line 07 +)"; + static uint32_t lengths[] = { 26, 28, 9, 8, 12, 32, 0 }; + static uint32_t lengths2[] = { 1, 5, 2 }; + + __auto_type con = Con_CreateBuffer (256, 8); + Con_BufferAddText (con, text); + + if (con->line_head != 7) { + printf ("con_buffer line_head incorrect: %d\n", con->line_head); + goto fail; + } + if (con->line_tail != 0) { + printf ("con_buffer line_tail incorrect: %d\n", con->line_tail); + goto fail; + } + uint32_t offs = 0; + for (uint32_t i = 0; i < 7; i++) { + if (con->lines[i].text != offs) { + printf ("con_buffer lines[%d].text incorrect: %u %u\n", + i, con->lines[i].text, offs); + goto fail; + } + if (con->lines[i].len != lengths[i]) { + printf ("con_buffer lines[%d].len incorrect: %u %u\n", + i, con->lines[i].len, lengths[i]); + goto fail; + } + offs += lengths[i]; + } + + Con_BufferAddText (con, "\nasdf\nas"); + if (con->line_head != 1) { + printf ("2 con_buffer line_head incorrect: %d\n", con->line_head); + goto fail; + } + if (con->line_tail != 2) { + printf ("2 con_buffer line_tail incorrect: %d\n", con->line_tail); + goto fail; + } + offs = lengths[0] + lengths[1]; + for (uint32_t i = 0; i < 4; i++) { + uint32_t n = i + 2; + if (con->lines[n].text != offs) { + printf ("2 con_buffer lines[%d].text incorrect: %u %u\n", + n, con->lines[n].text, offs); + goto fail; + } + if (con->lines[n].len != lengths[n]) { + printf ("2 con_buffer lines[%d].len incorrect: %u %u\n", + n, con->lines[n].len, lengths[n]); + goto fail; + } + offs += lengths[n]; + } + for (uint32_t i = 0; i < 3; i++) { + uint32_t n = (i + 6) % con->max_lines; + if (con->lines[n].text != offs) { + printf ("3 con_buffer lines[%d].text incorrect: %u %u\n", + n, con->lines[n].text, offs); + goto fail; + } + if (con->lines[n].len != lengths2[i]) { + printf ("3 con_buffer lines[%d].len incorrect: %u %u\n", + n, con->lines[n].len, lengths2[i]); + goto fail; + } + offs += lengths2[i]; + } + + ret = 0; +fail: + if (ret) { + printf ("%s failed\n", __FUNCTION__); + } + Con_DestroyBuffer (con); + return ret; +} + int main (void) { int ret = 0; ret |= test_1 (); ret |= test_2 (); + ret |= test_3 (); return ret; } From feba7903480cb61125572a6c1232de039b5e4e4e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Sep 2022 13:37:08 +0100 Subject: [PATCH 2973/3664] [qfcc] Use _algined_free when using _aligned_malloc Windows requires the two to be paired. I think this is the first time I really tested windows qfcc on windows. --- tools/qfcc/source/value.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 54972f4d0..7ea649782 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -63,6 +63,7 @@ //the first place, but not at all sure what to do about that) #ifdef _WIN32 #define aligned_alloc(al, sz) _aligned_malloc(sz, al) +#define free(x) _aligned_free(x) #endif typedef struct { From 745778979aab98145bb5c31f2b12188a88235ba0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Sep 2022 13:38:58 +0100 Subject: [PATCH 2974/3664] [image] Update stub WritePNG's definition Fixes some bitrot for when libpng is unavailable --- libs/image/png.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/image/png.c b/libs/image/png.c index 3b67983cd..83a443472 100644 --- a/libs/image/png.c +++ b/libs/image/png.c @@ -206,7 +206,7 @@ LoadPNG (QFile *infile, int load) #define WRITEPNG_BIT_DEPTH 8 -int +VISIBLE int WritePNG (QFile *outfile, const tex_t *tex) { int i; @@ -299,9 +299,10 @@ LoadPNG (QFile *infile, int load) return 0; } -VISIBLE void -WritePNG (QFile *outfile, const byte *data, int width, int height) +VISIBLE int +WritePNG (QFile *outfile, const tex_t *tex) { + return 0; } #endif From ead14d72683c6c13211318b42817fd7e3e172b8e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Sep 2022 13:41:24 +0100 Subject: [PATCH 2975/3664] [build] Fix a pile of issues building under cygwin Many thanks to jdp_ for finding them initially and getting me to take a look at things. --- Makefile.am | 6 +++--- config.d/build_control.m4 | 2 +- config.d/windows.m4 | 3 +++ configure.ac | 2 +- ruamoko/gui/Makemodule.am | 2 +- ruamoko/lib/Makemodule.am | 8 ++++---- ruamoko/qwaq/Makemodule.am | 2 +- ruamoko/scheme/Makemodule.am | 2 +- 8 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Makefile.am b/Makefile.am index 33aa5b689..404ccea76 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,7 +28,7 @@ BUILT_SOURCES = $(top_srcdir)/.version #AM_CFLAGS= @PREFER_NON_PIC@ AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) -common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@ +common_ldflags= -export-dynamic @STATIC@ @PTHREAD_LDFLAGS@ SUFFICES = TESTS = @@ -166,11 +166,11 @@ CLEANFILES += $(shader_DATA) $(r_depfiles_remade): $(MKDIR_P) $(@D) - echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.r qfcc@' >$@-t && $(am__mv) $@-t $@ + echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.r $(QFCC)@' >$@-t && $(am__mv) $@-t $@ $(pas_depfiles_remade): $(MKDIR_P) $(@D) - echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.pas qfcc@' >$@-t && $(am__mv) $@-t $@ + echo '$@' | sed -e 's@\$(DEPDIR)/@@' -e 's@\(.*\)\.Qo$$@\1.o: $(top_srcdir)/\1.pas $(QFCC)@' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) $(r_depfiles_remade) $(pas_depfiles_remade) echo findme $(ruamoko_gui_libgui_a_dep) diff --git a/config.d/build_control.m4 b/config.d/build_control.m4 index 48adc0b03..db8efb6e8 100644 --- a/config.d/build_control.m4 +++ b/config.d/build_control.m4 @@ -246,7 +246,7 @@ if test "x$ENABLE_tools_qfbsp" = xyes; then QF_NEED(libs,[models image util]) fi if test "x$ENABLE_tools_qfcc" = xyes; then - QFCC_TARGETS="qfcc qfprogs\$(EXEEXT)" + QFCC_TARGETS="qfcc\$(EXEEXT) qfprogs\$(EXEEXT)" QF_NEED(tools,[qfcc]) QF_NEED(libs,[gamecode util]) fi diff --git a/config.d/windows.m4 b/config.d/windows.m4 index e0ee907c8..8718d4355 100644 --- a/config.d/windows.m4 +++ b/config.d/windows.m4 @@ -19,6 +19,9 @@ case "$host_os" in ;; cygwin*) cygwin=yes + SYSTYPE=WIN32 + AC_DEFINE(NEED_GNUPRINTF) + FNM_FLAGS="-I\$(top_srcdir)/include/win32" if test "x$host" != "x$build"; then CC="$host_cpu-$host_os-gcc" AS="$CC" diff --git a/configure.ac b/configure.ac index 17c225b2e..56b006597 100644 --- a/configure.ac +++ b/configure.ac @@ -90,7 +90,7 @@ case "${host}" in fi ;; - i?86-*-cygwin*) + i?86-*-cygwin*|x86_64-*-cygwin*) SYSTYPE=WIN32 AC_MSG_RESULT([Win32 driver]) WIN32_LIBS=' $(NET_LIBS)' diff --git a/ruamoko/gui/Makemodule.am b/ruamoko/gui/Makemodule.am index ee25d5111..4f18772ac 100644 --- a/ruamoko/gui/Makemodule.am +++ b/ruamoko/gui/Makemodule.am @@ -15,7 +15,7 @@ ruamoko_gui_libgui_a_SOURCES= \ ruamoko/gui/View.r ruamoko_gui_libgui_a_dep=$(call qcautodep,$(ruamoko_gui_libgui_a_SOURCES)) ruamoko_gui_libgui_a_AR= $(PAK) -cf -EXTRA_ruamoko_gui_libgui_a_DEPENDENCIES=pak +EXTRA_ruamoko_gui_libgui_a_DEPENDENCIES=$(PAK) include $(ruamoko_gui_libgui_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_gui_libgui_a_dep) diff --git a/ruamoko/lib/Makemodule.am b/ruamoko/lib/Makemodule.am index 2528d5d40..eb110b6d9 100644 --- a/ruamoko/lib/Makemodule.am +++ b/ruamoko/lib/Makemodule.am @@ -33,7 +33,7 @@ ruamoko_lib_libr_a_SOURCES=\ ruamoko/lib/Set.r ruamoko_lib_libr_a_dep=$(call qcautodep,$(ruamoko_lib_libr_a_SOURCES)) ruamoko_lib_libr_a_AR=$(PAK) -cf -EXTRA_ruamoko_lib_libr_a_DEPENDENCIES=pak +EXTRA_ruamoko_lib_libr_a_DEPENDENCIES=$(PAK) include $(ruamoko_lib_libr_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_lib_libr_a_dep) @@ -83,7 +83,7 @@ ruamoko_lib_libqw_a_SOURCES= \ ruamoko/lib/math.r ruamoko_lib_libqw_a_dep=$(call qcautodep,$(ruamoko_lib_libqw_a_src)) ruamoko_lib_libqw_a_AR=$(PAK) -cf -EXTRA_ruamoko_lib_libqw_a_DEPENDENCIES=pak +EXTRA_ruamoko_lib_libqw_a_DEPENDENCIES=$(PAK) include $(ruamoko_lib_libqw_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_lib_libqw_a_dep) @@ -94,7 +94,7 @@ ruamoko_lib_libnq_a_SOURCES=\ ruamoko/lib/math.r ruamoko_lib_libnq_a_dep=$(call qcautodep,$(ruamoko_lib_libnq_a_src)) ruamoko_lib_libnq_a_AR=$(PAK) -cf -EXTRA_ruamoko_lib_libnq_a_DEPENDENCIES=pak +EXTRA_ruamoko_lib_libnq_a_DEPENDENCIES=$(PAK) include $(ruamoko_lib_libnq_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_lib_libnq_a_dep) @@ -103,7 +103,7 @@ ruamoko_lib_libcsqc_a_SOURCES=\ $(ruamoko_lib_common_src) ruamoko_lib_libcsqc_a_dep=$(call qcautodep,$(ruamoko_lib_libcsqc_a_src)) ruamoko_lib_libcsqc_a_AR= $(PAK) -cf -EXTRA_ruamoko_lib_libcsqc_a_DEPENDENCIES=pak +EXTRA_ruamoko_lib_libcsqc_a_DEPENDENCIES=$(PAK) include $(ruamoko_lib_libcsqc_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_lib_libcsqc_a_dep) diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index cd278606b..5c32944ff 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -24,7 +24,7 @@ ruamoko_qwaq_libui_a_SOURCES= \ ruamoko/qwaq/ui/window.r ruamoko_qwaq_libui_a_dep=$(call qcautodep,$(ruamoko_qwaq_libui_a_SOURCES)) ruamoko_qwaq_libui_a_AR=$(PAK) -cf -EXTRA_ruamoko_qwaq_libui_a_DEPENDENCIES=pak +EXTRA_ruamoko_qwaq_libui_a_DEPENDENCIES=$(PAK) include $(ruamoko_qwaq_libui_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_qwaq_libui_a_dep) diff --git a/ruamoko/scheme/Makemodule.am b/ruamoko/scheme/Makemodule.am index 8c1d43622..19b23cae4 100644 --- a/ruamoko/scheme/Makemodule.am +++ b/ruamoko/scheme/Makemodule.am @@ -33,7 +33,7 @@ ruamoko_scheme_libscheme_a_SOURCES=\ ruamoko/scheme/BaseContinuation.r ruamoko_scheme_libscheme_a_dep=$(call qcautodep,$(ruamoko_scheme_libscheme_a_SOURCES)) ruamoko_scheme_libscheme_a_AR=$(PAK) -cf -EXTRA_ruamoko_scheme_libscheme_a_DEPENDENCIES=pak +EXTRA_ruamoko_scheme_libscheme_a_DEPENDENCIES=$(PAK) include $(ruamoko_scheme_libscheme_a_dep) # am--include-marker r_depfiles_remade += $(ruamoko_scheme_libscheme_a_dep) From fb5477e0ab734be138b9957bf8667080d94ed2cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Sep 2022 14:13:16 +0100 Subject: [PATCH 2976/3664] [build] Remove -no-cygwin from mingw builds It seems to have been deprecated. This gets --host builds working, although some libs don't work properly due to having only dlls and I guess mingw stuff isn'n on any paths. --- config.d/windows.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.d/windows.m4 b/config.d/windows.m4 index 8718d4355..e78fd8e15 100644 --- a/config.d/windows.m4 +++ b/config.d/windows.m4 @@ -8,7 +8,7 @@ case "$host_os" in if test "x$host" != "x$build"; then case "$build_os" in cygwin*) - CFLAGS="$CFLAGS -mno-cygwin -mconsole -D__USE_MINGW_ANSI_STDIO" + CFLAGS="$CFLAGS -mconsole -D__USE_MINGW_ANSI_STDIO" CPPFLAGS="$CPPFLAGS $CFLAGS" ;; esac From 08328f40765c1bf2b2ddda008bbb1d4a2d57b1ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Sep 2022 16:31:08 +0100 Subject: [PATCH 2977/3664] Fix some cygwin portability issues Cygwin's headers seem to be rather out of date with respect to linux with regards to signed types, especially ctype. --- libs/gamecode/pr_debug.c | 2 +- libs/net/nm/net_udp.c | 2 +- tools/qfcc/source/dags.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 2a07ba9cd..7f62831fc 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1629,7 +1629,7 @@ PR_PrintStatement (progs_t *pr, dstatement_t *s, int contents) goto err; } if (mode == 'M' || mode == 'm') { - if (!isxdigit (fmt[3])) { + if (!isxdigit ((byte) fmt[3])) { goto err; } shift = fmt[3]; diff --git a/libs/net/nm/net_udp.c b/libs/net/nm/net_udp.c index 8701214cd..74815bd61 100644 --- a/libs/net/nm/net_udp.c +++ b/libs/net/nm/net_udp.c @@ -537,7 +537,7 @@ UDP_Read (int socket, byte *buf, int len, netadr_t *from) } SockadrToNetadr (&addr, from); Sys_MaskPrintf (SYS_net, "got %d bytes from %s on iface %d (%s)\n", ret, - UDP_AddrToString (from), info ? info->ipi_ifindex - 1 : -1, + UDP_AddrToString (from), info ? (int) info->ipi_ifindex - 1 : -1, last_iface ? inet_ntoa (info->ipi_addr) : "?"); #else socklen_t addrlen = sizeof (AF_address_t); diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 6c787fdc6..1c3ad201f 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -494,7 +494,7 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n, statement_t *s) set_remove (gn->edges, n->number); } } - if (num_params && isdigit (*num_params)) { + if (num_params && isdigit ((byte) *num_params)) { for (i = first_param; i < *num_params - '0'; i++) { flowvar_t *var = flowvars[i + 1]; def_t *param_def = var->op->def; From e36adb07eca1e16d039e378fe1350408ce056cfc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Sep 2022 16:32:45 +0100 Subject: [PATCH 2978/3664] [net] Don't include windows.h or winsock.h directly Including them kills the definition for CMSG_DATA. --- libs/net/nm/net_udp.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libs/net/nm/net_udp.c b/libs/net/nm/net_udp.c index 74815bd61..e960d44eb 100644 --- a/libs/net/nm/net_udp.c +++ b/libs/net/nm/net_udp.c @@ -58,12 +58,6 @@ #ifdef HAVE_SYS_IOCTL_H # include #endif -#ifdef HAVE_WINDOWS_H -# include -#endif -#ifdef HAVE_WINSOCK_H -# include -#endif #ifdef HAVE_UNISTD_H # include #endif From 1cd6a174fe65732162c60482ac8c7f550e1a7353 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Sep 2022 16:36:29 +0100 Subject: [PATCH 2979/3664] [build] Correct cygwin system type cygwin is not windows, so trying to build a win32 app on cygwin-native doesn't work too well. --- config.d/cdrom.m4 | 2 ++ config.d/sound.m4 | 40 +++++++++++++++++++++------------------- config.d/windows.m4 | 2 -- configure.ac | 2 +- libs/util/sys.c | 4 ++++ 5 files changed, 28 insertions(+), 22 deletions(-) diff --git a/config.d/cdrom.m4 b/config.d/cdrom.m4 index 5b50743d5..e7c66f80e 100644 --- a/config.d/cdrom.m4 +++ b/config.d/cdrom.m4 @@ -59,10 +59,12 @@ AC_SUBST(SGI_CD_LIBS) AC_EGREP_CPP([QF_maGiC_VALUE], [ +#ifdef _WIN32 #include #include #if defined(MCI_SET_DOOR_OPEN) QF_maGiC_VALUE +#endif #endif ], CDTYPE="$CDTYPE WIN32" diff --git a/config.d/sound.m4 b/config.d/sound.m4 index e2cd663d2..1abc1c311 100644 --- a/config.d/sound.m4 +++ b/config.d/sound.m4 @@ -238,26 +238,28 @@ QF_maGiC_VALUE fi dnl Win32 - if test "x$ac_cv_header_windows_h" = "xyes"; then - SOUND_TYPES="$SOUND_TYPES Win32" - QF_NEED(snd_output, [win]) - QF_NEED(snd_render, [default]) - WINSND_LIBS="-lwinmm" - if test "x$ac_cv_header_dsound_h" = "xyes"; then - AC_EGREP_CPP([QF_maGiC_VALUE], - [ -#include -#include -#ifdef GMEM_MOVEABLE -# ifdef DirectSoundEnumerate -QF_maGiC_VALUE -# endif -#endif - ], - SOUND_TYPES="$SOUND_TYPES DirectX" - QF_NEED(snd_output, [dx]) + if test "x$SYSTYPE" = xWIN32; then + if test "x$ac_cv_header_windows_h" = "xyes"; then + SOUND_TYPES="$SOUND_TYPES Win32" + QF_NEED(snd_output, [win]) QF_NEED(snd_render, [default]) - ) + WINSND_LIBS="-lwinmm" + if test "x$ac_cv_header_dsound_h" = "xyes"; then + AC_EGREP_CPP([QF_maGiC_VALUE], + [ + #include + #include + #ifdef GMEM_MOVEABLE + # ifdef DirectSoundEnumerate + QF_maGiC_VALUE + # endif + #endif + ], + SOUND_TYPES="$SOUND_TYPES DirectX" + QF_NEED(snd_output, [dx]) + QF_NEED(snd_render, [default]) + ) + fi fi fi AC_SUBST(WINSND_LIBS) diff --git a/config.d/windows.m4 b/config.d/windows.m4 index e78fd8e15..d1e0b32a1 100644 --- a/config.d/windows.m4 +++ b/config.d/windows.m4 @@ -19,9 +19,7 @@ case "$host_os" in ;; cygwin*) cygwin=yes - SYSTYPE=WIN32 AC_DEFINE(NEED_GNUPRINTF) - FNM_FLAGS="-I\$(top_srcdir)/include/win32" if test "x$host" != "x$build"; then CC="$host_cpu-$host_os-gcc" AS="$CC" diff --git a/configure.ac b/configure.ac index 56b006597..01fed1590 100644 --- a/configure.ac +++ b/configure.ac @@ -91,7 +91,7 @@ case "${host}" in ;; i?86-*-cygwin*|x86_64-*-cygwin*) - SYSTYPE=WIN32 + #SYSTYPE=WIN32 AC_MSG_RESULT([Win32 driver]) WIN32_LIBS=' $(NET_LIBS)' ;; diff --git a/libs/util/sys.c b/libs/util/sys.c index 937d832b2..d4d6f23d3 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -940,7 +940,11 @@ Sys_ConsoleInput (void) #endif } +#ifdef _WIN32 static jmp_buf aiee_abort; +#else +static sigjmp_buf aiee_abort; +#endif typedef struct sh_stack_s { struct sh_stack_s *next; From 1fa202608ebbb7c10abed8ec032fa29b8ca92cd2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 19 Sep 2022 16:39:25 +0100 Subject: [PATCH 2980/3664] [qfcc] Don't free duplicate method when merging The method is still held by known_methods, so freeing it causes grief. However, it may cause a leak thus the free is only commented out. More investigation is needed. I'm surprised the problem didn't show on linux, but cygwin-native hit it and valgrind on linux found the spot :) --- tools/qfcc/source/method.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index f36a1fd20..1034ab337 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -279,7 +279,10 @@ merge_method_lists (methodlist_t *dst, methodlist_t *src) s->next = 0; if (method_in_list (dst, s)) { debug (0, "dropping duplicate method: %s", s->name); - free (s); + //FIXME this free is currently erroneous as it remains in + //known_methods, but it may also be a leak, thus only + //commented out for now. + //free (s); } else { // add_method does the duplicate check *dst->tail = s; From 474f01d321e83f55ee17c763996929eba2004b85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Sep 2022 10:27:24 +0900 Subject: [PATCH 2981/3664] [renderer] Return count of lines printed to char buffer This allows users to know the number of terminated lines in the printed text without having to redundantly count the lines. --- include/QF/draw.h | 2 +- libs/video/renderer/r_draw.c | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/QF/draw.h b/include/QF/draw.h index bbbbf8e9d..aabbf7e16 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -59,7 +59,7 @@ void Draw_DestroyBuffer (draw_charbuffer_t *buffer); void Draw_ClearBuffer (draw_charbuffer_t *buffer); void Draw_ScrollBuffer (draw_charbuffer_t *buffer, int lines); void Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer); -void Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str); +int Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str); extern byte *draw_chars; diff --git a/libs/video/renderer/r_draw.c b/libs/video/renderer/r_draw.c index 3b2285ad5..5a18b99b0 100644 --- a/libs/video/renderer/r_draw.c +++ b/libs/video/renderer/r_draw.c @@ -91,12 +91,13 @@ Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer) #define TAB 8 -VISIBLE void +VISIBLE int Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str) { char *dst = buffer->chars; char c; int tab; + int lines = 0; dst += buffer->cursy * buffer->width + buffer->cursx; while ((c = *str++)) { switch (c) { @@ -109,10 +110,12 @@ Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str) buffer->cursx = 0; dst += buffer->width; buffer->cursy++; + lines++; break; case '\f': dst += buffer->width; buffer->cursy++; + lines++; break; case '\t': tab = TAB - buffer->cursx % TAB; @@ -127,12 +130,14 @@ Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str) if (buffer->cursx >= buffer->width) { buffer->cursx -= buffer->width; buffer->cursy++; + lines++; } if (buffer->cursy >= buffer->height) { - int lines = buffer->cursy - buffer->height + 1; - Draw_ScrollBuffer (buffer, lines); - dst -= lines * buffer->width; - buffer->cursy -= lines; + int excess = buffer->cursy - buffer->height + 1; + Draw_ScrollBuffer (buffer, excess); + dst -= excess * buffer->width; + buffer->cursy -= excess; } } + return lines; } From 11e978b4dbb97feb928fd3b3b5f2ed1268d73787 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Sep 2022 10:50:15 +0900 Subject: [PATCH 2982/3664] [console] Fix a signed comparison warning I'm not sure why that didn't trigger in a linux build. Maybe gcc 12 assumed the result would be positive (I think I'm still using 11 for mxe). --- libs/console/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/console/buffer.c b/libs/console/buffer.c index b484bcfa9..006a2c7bb 100644 --- a/libs/console/buffer.c +++ b/libs/console/buffer.c @@ -103,7 +103,7 @@ Con_BufferAddText (con_buffer_t *buf, const char *text) } if (c == '\n') { cur_line++; - if (cur_line - buf->lines >= buf->max_lines) { + if ((uint32_t) (cur_line - buf->lines) >= buf->max_lines) { cur_line -= buf->max_lines; } cur_line->text = text_head; From d6d45bf07cc6ca77821368ba4182dffa7c1a8dc0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Sep 2022 12:14:01 +0900 Subject: [PATCH 2983/3664] [console] Add a function to clear the scroll-back buffer Needed for when the console display is cleared. --- include/QF/console.h | 1 + libs/console/buffer.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/QF/console.h b/include/QF/console.h index 79aac8e69..8839f1b73 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -98,6 +98,7 @@ con_buffer_t *Con_CreateBuffer (size_t buffer_size, int max_lines); void Con_DestroyBuffer (con_buffer_t *buffer); void Con_BufferAddText (con_buffer_t *buf, const char *text); #define Con_BufferLine(b,l) ((b)->lines + ((l) + (b)->max_lines) % (b)->max_lines) +void Con_ClearBuffer (con_buffer_t *buffer); // init/shutdown functions void Con_Init (const char *plugin_name); diff --git a/libs/console/buffer.c b/libs/console/buffer.c index 006a2c7bb..9f0b08c5e 100644 --- a/libs/console/buffer.c +++ b/libs/console/buffer.c @@ -125,3 +125,12 @@ Con_BufferAddText (con_buffer_t *buf, const char *text) } } } + +VISIBLE void +Con_ClearBuffer (con_buffer_t *buffer) +{ + buffer->line_head = 1; + buffer->line_tail = 0; + buffer->lines[0].text = 0; + buffer->lines[0].len = 0; +} From 398405c8d61d827929a71f422dc06a6153b13434 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Sep 2022 12:57:22 +0900 Subject: [PATCH 2984/3664] [console] Remove old_console_t struct This replaces old_console_t with con_buffer_t for managing scrollback, and draw_charbuffer_t for actual character drawing, reducing the number of calls into the renderer. There are numerous issues with placement and sizing, but the basics are working nicely. --- include/QF/console.h | 10 -- libs/console/client.c | 399 +++++++++++++++++++++--------------------- 2 files changed, 198 insertions(+), 211 deletions(-) diff --git a/include/QF/console.h b/include/QF/console.h index 8839f1b73..d3cd87945 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -35,16 +35,6 @@ /** \defgroup console 2d Console Stuff */ -#define CON_TEXTSIZE 32764 -typedef struct -{ - char text[CON_TEXTSIZE]; - int current; // line where next message will be printed - int x; // offset in current line for next print - int display; // bottom of console displays this line - int numlines; // number of non-blank text lines, used for backscroling -} old_console_t; - typedef struct { uint32_t text; uint32_t len; diff --git a/libs/console/client.c b/libs/console/client.c index 258821a1b..62a50c967 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -1,7 +1,7 @@ /* - console.c + client.c - (description) + Client console routines Copyright (C) 1996-1997 Id Software, Inc. @@ -42,22 +42,15 @@ # include #endif -#include "QF/cbuf.h" #include "QF/cmd.h" #include "QF/console.h" #include "QF/cvar.h" -#include "QF/draw.h" #include "QF/dstring.h" #include "QF/gib.h" -#include "QF/input.h" #include "QF/keys.h" #include "QF/qargs.h" #include "QF/quakefs.h" -#include "QF/render.h" -#include "QF/screen.h" -#include "QF/sys.h" #include "QF/va.h" -#include "QF/vid.h" #include "QF/input/event.h" @@ -65,20 +58,18 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" -#include "QF/ui/view.h" - #include "QF/ui/inputline.h" +#include "QF/ui/view.h" #include "compat.h" static general_data_t plugin_info_general_data; console_data_t con_data; -static old_console_t con_main; -static old_console_t con_chat; -static old_console_t *con; +//static con_buffer_t *con_chat; +static con_buffer_t *con; -static float con_cursorspeed = 4; +static float con_cursorspeed = 4; static float con_notifytime; static cvar_t con_notifytime_cvar = { @@ -153,10 +144,6 @@ static cvar_t cl_conmode_cvar = { .value = { .type = &cl_conmode_type, .value = &con_data.exec_line }, }; -#define NUM_CON_TIMES 4 -static float con_times[NUM_CON_TIMES]; // realtime time the line was generated - // for transparent notify lines - static int con_totallines; // total lines in console scrollback static con_state_t con_state; static int con_event_id; @@ -167,12 +154,27 @@ static qboolean chat_team; #define MAXCMDLINE 256 static inputline_t *input_line; + +#define CON_BUFFER_SIZE 32768 +#define CON_LINES 1024 +static view_t *console_view; +static draw_charbuffer_t *console_buffer; +static con_buffer_t *con_main; +static int view_offset; + +static view_t *say_view; +static draw_charbuffer_t *say_buffer; static inputline_t *say_line; static inputline_t *say_team_line; -static view_t *console_view; -static view_t *say_view; +#define NOTIFY_LINES 4 static view_t *notify_view; +static draw_charbuffer_t *notify_buffer; +// ring buffer holding realtime time the line was generated +static float notify_times[NOTIFY_LINES + 1]; +static int notify_head; +static int notify_tail; + static view_t *menu_view; static view_t *hud_view; @@ -181,10 +183,8 @@ static qboolean con_initialized; static void ClearNotify (void) { - int i; - - for (i = 0; i < NUM_CON_TIMES; i++) - con_times[i] = 0; + Draw_ClearBuffer (notify_buffer); + notify_head = notify_tail = 0; } static void @@ -198,6 +198,16 @@ C_SetState (con_state_t state) con_saved_focos = IE_Get_Focus (); IE_Set_Focus (con_event_id); } + + if (state == con_message) { + const char *prompt = "say:"; + if (chat_team) { + prompt = "say_team:"; + } + say_buffer->cursx = 0; + Draw_PrintBuffer (say_buffer, prompt); + } + if (con_state == con_menu && old_state != con_menu) { Menu_Enter (); } @@ -227,11 +237,8 @@ ToggleConsole_f (void) static void Clear_f (void) { - con_main.numlines = 0; - con_chat.numlines = 0; - memset (con_main.text, ' ', CON_TEXTSIZE); - memset (con_chat.text, ' ', CON_TEXTSIZE); - con_main.display = con_main.current; + Con_ClearBuffer (con_main); + //Con_ClearBuffer (con_chat); } static void @@ -253,23 +260,19 @@ MessageMode2_f (void) } static void -Resize (old_console_t *con) +Resize (con_buffer_t *con) { - char tbuf[CON_TEXTSIZE]; - int width, oldwidth, oldtotallines, numlines, numchars, i, j; + int width, oldwidth, oldtotallines, numlines, numchars; width = (r_data->vid->conview->xlen >> 3) - 2; if (width < 1) { // video hasn't been initialized yet width = 38; con_linewidth = width; - con_totallines = CON_TEXTSIZE / con_linewidth; - memset (con->text, ' ', CON_TEXTSIZE); } else { oldwidth = con_linewidth; con_linewidth = width; oldtotallines = con_totallines; - con_totallines = CON_TEXTSIZE / con_linewidth; numlines = oldtotallines; if (con_totallines < numlines) @@ -280,25 +283,9 @@ Resize (old_console_t *con) if (con_linewidth < numchars) numchars = con_linewidth; - memcpy (tbuf, con->text, CON_TEXTSIZE); - memset (con->text, ' ', CON_TEXTSIZE); - - for (i = 0; i < numlines; i++) { - for (j = 0; j < numchars; j++) { - con->text[(con_totallines - 1 - i) * con_linewidth + j] = - tbuf[((con->current - i + oldtotallines) % - oldtotallines) * oldwidth + j]; - } - } - ClearNotify (); } - say_team_line->width = con_linewidth - 9; - say_line->width = con_linewidth - 4; input_line->width = con_linewidth; - - con->current = con_totallines - 1; - con->display = con->current; } /* @@ -309,8 +296,8 @@ Resize (old_console_t *con) static void C_CheckResize (void) { - Resize (&con_main); - Resize (&con_chat); + Resize (con_main); + //Resize (con_chat); view_resize (con_data.view, r_data->vid->conview->xlen, r_data->vid->conview->ylen); @@ -319,8 +306,6 @@ C_CheckResize (void) static void Condump_f (void) { - int line = con->current - con->numlines; - const char *start, *end; QFile *file; const char *name; @@ -341,13 +326,10 @@ Condump_f (void) return; } - while (line < con->current) { - start = &con->text[(line % con_totallines) * con_linewidth]; - end = start + con_linewidth; - while (end > start && end[-1] != ' ') - end--; - Qprintf (file, "%.*s\n", (int)(end - start), start); - line++; + for (uint32_t line_ind = con->line_tail; line_ind != con->line_head; + line_ind = (line_ind + 1) % con->max_lines) { + con_line_t *line = &con->lines[line_ind]; + Qwrite (file, con->buffer + line->text, line->len); } Qclose (file); @@ -412,19 +394,6 @@ C_SayTeam (inputline_t *il) con_end_message (il); } -static void -Linefeed (void) -{ - con->x = 0; - if (con->display == con->current) - con->display++; - con->current++; - if (con->numlines < con_totallines) - con->numlines++; - memset (&con->text[(con->current % con_totallines) * con_linewidth], - ' ', con_linewidth); -} - /* C_Print @@ -437,8 +406,7 @@ C_Print (const char *fmt, va_list args) { char *s; static dstring_t *buffer; - int mask, c, l, y; - static int cr; + int mask, c; if (!buffer) buffer = dstring_new (); @@ -455,55 +423,42 @@ C_Print (const char *fmt, va_list args) s = buffer->str; - if (s[0] == 1 || s[0] == 2) { + mask = 0; + if (buffer->str[0] == 1 || buffer->str[0] == 2) { mask = 128; // go to colored text s++; - } else - mask = 0; - - while ((c = (byte)*s)) { - // count word length - for (l = 0; l < con_linewidth; l++) - if (s[l] <= ' ') - break; - - // word wrap - if (l != con_linewidth && (con->x + l > con_linewidth)) - con->x = 0; - - *s++ = sys_char_map[c]; - - if (cr) { - con->current--; - cr = false; + } + if (mask || con_data.ormask) { + for (char *m = s; *m; m++) { + if (*m >= ' ') { + *m |= mask | con_data.ormask; + } } + } - if (!con->x) { - Linefeed (); - // mark time for transparent overlay - if (con->current >= 0 && con_data.realtime) - con_times[con->current % NUM_CON_TIMES] = *con_data.realtime; - } - - switch (c) { - case '\n': - con->x = 0; - break; - - case '\r': - con->x = 0; - cr = 1; - break; - - default: // display character and advance - y = con->current % con_totallines; - con->text[y * con_linewidth + con->x] = c | mask | con_data.ormask; - con->x++; - if (con->x >= con_linewidth) - con->x = 0; - break; + if (con_data.realtime) { + c = Draw_PrintBuffer (notify_buffer, s); + while (c-- > 0) { + notify_times[notify_head++] = *con_data.realtime; + if (notify_head >= NOTIFY_LINES + 1) { + notify_head -= NOTIFY_LINES + 1; + } + if (notify_head == notify_tail) { + notify_tail++; + if (notify_tail >= NOTIFY_LINES + 1) { + notify_tail -= NOTIFY_LINES + 1; + } + } } + } + Con_BufferAddText (con_main, s); + if (!view_offset) { + Draw_PrintBuffer (console_buffer, s); + } + while (*s) { + *s = sys_char_map[(byte) *s]; + s++; } // echo to debugging console @@ -591,7 +546,8 @@ draw_download (view_t *view) } } - dsprintf (dlbar, "%.*s%s: \x80%s\x82 %02d%%", txt_size, text, ellipsis, dots, *con_data.dl_percent); + dsprintf (dlbar, "%.*s%s: \x80%s\x82 %02d%%", + txt_size, text, ellipsis, dots, *con_data.dl_percent); // draw it r_funcs->Draw_String (view->xabs, view->yabs, dlbar->str); @@ -600,34 +556,29 @@ draw_download (view_t *view) static void draw_console_text (view_t *view) { - char *text; - int row, rows, i, x, y; + Draw_CharBuffer (view->xabs, view->yabs, console_buffer); +} - rows = view->ylen >> 3; // rows of text to draw +static void +draw_con_scrollback (void) +{ + __auto_type cb = console_buffer; + char *dst = cb->chars + (cb->height - 1) * cb->width; + int rows = cb->height; + int cur_line = con_main->line_head - 1 + view_offset; - x = view->xabs + 8; - y = view->yabs + view->ylen - 8; - - // draw from the bottom up - if (con->display != con->current) { + if (view_offset) { // draw arrows to show the buffer is backscrolled - for (i = 0; i < con_linewidth; i += 4) - r_funcs->Draw_Character (x + (i << 3), y, '^'); - - y -= 8; + memset (dst, '^' | 0x80, cb->width); + dst -= cb->width; rows--; } - - row = con->display; - for (i = 0; i < rows; i++, y -= 8, row--) { - if (row < 0) - break; - if (con->current - row >= con_totallines) - break; // past scrollback wrap point - - text = con->text + (row % con_totallines) * con_linewidth; - - r_funcs->Draw_nString(x, y, text, con_linewidth); + for (int i = 0; i < rows; i++) { + con_line_t *l = Con_BufferLine (con_main, cur_line - i); + int len = max (min ((int) l->len, cb->width + 1) - 1, 0); + memcpy (dst, con_main->buffer + l->text, len); + memset (dst + len, ' ', cb->width - len); + dst -= cb->width; } } @@ -655,43 +606,80 @@ draw_say (view_t *view) { r_data->scr_copytop = 1; - if (chat_team) { - r_funcs->Draw_String (view->xabs + 8, view->yabs, "say_team:"); - DrawInputLine (view->xabs + 80, view->yabs, 1, say_team_line); - } else { - r_funcs->Draw_String (view->xabs + 8, view->yabs, "say:"); - DrawInputLine (view->xabs + 40, view->yabs, 1, say_line); + Draw_CharBuffer (view->xabs, view->yabs, say_buffer); +} + +static void +draw_input_line (inputline_t *il, draw_charbuffer_t *buffer) +{ + char *dst = buffer->chars + buffer->cursx; + char *src = il->lines[il->edit_line] + il->scroll; + size_t i; + + *dst++ = il->scroll ? '<' | 0x80 : ' '; + for (i = 0; i < il->width - 2 && *src; i++) { + *dst++ = *src++; } + while (i++ < il->width - 2) { + *dst++ = ' '; + } + *dst++ = *src ? '>' | 0x80 : ' '; +} + +static void +say_line_draw (inputline_t *il) +{ + say_buffer->cursx = 4; + draw_input_line (il, say_buffer); +} + +static void +say_team_line_draw (inputline_t *il) +{ + say_buffer->cursx = 9; + draw_input_line (il, say_buffer); +} + +static void +resize_console (view_t *view) +{ + Draw_DestroyBuffer (console_buffer); + console_buffer = Draw_CreateBuffer (view->xlen / 8, view->ylen / 8); + Draw_ClearBuffer (console_buffer); +} + +static void +resize_say (view_t *view) +{ + Draw_DestroyBuffer (say_buffer); + say_buffer = Draw_CreateBuffer (view->xlen / 8, 1); + Draw_ClearBuffer (say_buffer); + + say_team_line->width = say_buffer->width - 9; + say_line->width = say_buffer->width - 4; } static void draw_notify (view_t *view) { - int i, x, y; - char *text; - float time; - - if (!con_data.realtime) - return; - - x = view->xabs + 8; - y = view->yabs; - for (i = con->current - NUM_CON_TIMES + 1; i <= con->current; i++) { - if (i < 0) - continue; - time = con_times[i % NUM_CON_TIMES]; - if (time == 0) - continue; - time = *con_data.realtime - time; - if (time > con_notifytime) - continue; - text = con->text + (i % con_totallines) * con_linewidth; - - r_data->scr_copytop = 1; - - r_funcs->Draw_nString (x, y, text, con_linewidth); - y += 8; + if (con_data.realtime && notify_tail != notify_head + && *con_data.realtime - notify_times[notify_tail] > con_notifytime) { + Draw_ScrollBuffer (notify_buffer, 1); + notify_buffer->cursy--; + notify_tail++; + if (notify_tail >= (NOTIFY_LINES + 1)) { + notify_tail -= NOTIFY_LINES + 1; + } } + Draw_CharBuffer (view->xabs, view->yabs, notify_buffer); +} + +static void +resize_notify (view_t *view) +{ + Draw_DestroyBuffer (notify_buffer); + notify_buffer = Draw_CreateBuffer (view->xlen / 8, NOTIFY_LINES + 1); + ClearNotify (); } static void @@ -787,6 +775,7 @@ con_key_event (const IE_event_t *event) { inputline_t *il; __auto_type key = &event->key; + int old_view_offset = view_offset; #if 0 if (con_curr_keydest == key_menu) { @@ -812,43 +801,40 @@ con_key_event (const IE_event_t *event) return; } } else { + con_buffer_t *cb = con_main; + int num_lines = (cb->line_head - cb->line_tail + + cb->max_lines) % cb->max_lines; + int con_lines = con_data.lines / 8; switch (key->code) { case QFK_ESCAPE: ToggleConsole_f (); break; case QFK_PAGEUP: - if (key->shift & ies_control) - con->display = 0; - else - con->display -= 10; - if (con->display < con->current - con->numlines) - con->display = con->current - con->numlines; - return; + view_offset -= 10; + if (view_offset <= -(num_lines - con_lines)) { + view_offset = -(num_lines - con_lines) + 1; + } + break; case QFK_PAGEDOWN: - if (key->shift & ies_control) - con->display = con->current; - else - con->display += 10; - if (con->display > con->current) - con->display = con->current; - return; + view_offset += 10; + if (view_offset > 0) { + view_offset = 0; + } + break; #if 0 case QFM_WHEEL_UP: - con->display -= 3; - if (con->display < con->current - con->numlines) - con->display = con->current - con->numlines; - return; + break; case QFM_WHEEL_DOWN: - con->display += 3; - if (con->display > con->current) - con->display = con->current; - return; + break; #endif default: break; } il = input_line; } + if (old_view_offset != view_offset) { + draw_con_scrollback (); + } if (key->unicode) { Con_ProcessInputLine (il, key->code >= 256 ? (int) key->code @@ -907,7 +893,7 @@ C_Init (void) con_data.view = view_new (0, 0, 320, 200, grav_northeast); console_view = view_new (0, 0, 320, 200, grav_northwest); say_view = view_new (0, 0, 320, 8, grav_northwest); - notify_view = view_new (0, 8, 320, 32, grav_northwest); + notify_view = view_new (8, 8, 312, NOTIFY_LINES * 8, grav_northwest); menu_view = view_new (0, 0, 320, 200, grav_center); hud_view = view_new (0, 0, 320, 200, grav_northeast); @@ -917,15 +903,26 @@ C_Init (void) view_add (con_data.view, console_view); view_add (con_data.view, menu_view); + console_buffer = Draw_CreateBuffer (console_view->xlen / 8, + console_view->ylen / 8); + Draw_ClearBuffer (console_buffer); + con_main = Con_CreateBuffer (CON_BUFFER_SIZE, CON_LINES); console_view->draw = draw_console; + say_view->setgeometry = resize_console; console_view->visible = 0; console_view->resize_x = console_view->resize_y = 1; + say_buffer = Draw_CreateBuffer (say_view->xlen / 8, 1); + Draw_ClearBuffer (say_buffer); say_view->draw = draw_say; + say_view->setgeometry = resize_say; say_view->visible = 0; say_view->resize_x = 1; + notify_buffer = Draw_CreateBuffer (notify_view->xlen / 8, NOTIFY_LINES + 1); + Draw_ClearBuffer (notify_buffer); notify_view->draw = draw_notify; + notify_view->setgeometry = resize_notify; notify_view->resize_x = 1; menu_view->draw = Menu_Draw; @@ -949,7 +946,7 @@ C_Init (void) view->resize_x = 1; view_add (console_view, view); - con = &con_main; + con = con_main; con_linewidth = -1; input_line = Con_CreateInputLine (32, MAXCMDLINE, ']'); @@ -964,14 +961,14 @@ C_Init (void) say_line->enter = C_Say; say_line->width = con_linewidth - 5; say_line->user_data = 0; - say_line->draw = 0; + say_line->draw = say_line_draw; say_team_line = Con_CreateInputLine (32, MAXCMDLINE, ' '); say_team_line->complete = 0; say_team_line->enter = C_SayTeam; say_team_line->width = con_linewidth - 10; say_team_line->user_data = 0; - say_team_line->draw = 0; + say_team_line->draw = say_team_line_draw; C_CheckResize (); From 1fdedbaf33bcb50d1cf2dff58adfad4e7ec777f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Sep 2022 19:30:43 +0900 Subject: [PATCH 2985/3664] [renderer] Report scrap rectangle counts Stats are good. More stats even better :) I wanted to see just how many lightmaps were being created in e1m3. --- include/r_scrap.h | 2 +- libs/video/renderer/gl/gl_textures.c | 7 ++++--- libs/video/renderer/glsl/glsl_textures.c | 7 ++++--- libs/video/renderer/r_scrap.c | 7 ++++++- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/r_scrap.h b/include/r_scrap.h index 5539d7480..7648f2b39 100644 --- a/include/r_scrap.h +++ b/include/r_scrap.h @@ -43,7 +43,7 @@ void R_ScrapDelete (rscrap_t *scrap); struct vrect_s *R_ScrapAlloc (rscrap_t *scrap, int width, int height); void R_ScrapFree (rscrap_t *scrap, struct vrect_s *rect); void R_ScrapClear (rscrap_t *scrap); -size_t R_ScrapArea (rscrap_t *scrap) __attribute__((pure)); +size_t R_ScrapArea (rscrap_t *scrap, int *count) __attribute__((pure)); void R_ScrapDump (rscrap_t *scrap); #endif//__r_scrap_h diff --git a/libs/video/renderer/gl/gl_textures.c b/libs/video/renderer/gl/gl_textures.c index 0478eed69..c65760890 100644 --- a/libs/video/renderer/gl/gl_textures.c +++ b/libs/video/renderer/gl/gl_textures.c @@ -655,18 +655,19 @@ gl_scraps_f (void) scrap_t *scrap; int area; int size; + int count; if (!scrap_list) { Sys_Printf ("No scraps\n"); return; } for (scrap = scrap_list; scrap; scrap = scrap->next) { - area = R_ScrapArea (&scrap->rscrap); + area = R_ScrapArea (&scrap->rscrap, &count); // always square size = scrap->rscrap.width; - Sys_Printf ("tnum=%u size=%d format=%04x bpp=%d free=%d%%\n", + Sys_Printf ("tnum=%u size=%d format=%04x bpp=%d free=%d%% rects=%d\n", scrap->tnum, size, scrap->format, scrap->bpp, - area * 100 / (size * size)); + area * 100 / (size * size), count); if (Cmd_Argc () > 1) { R_ScrapDump (&scrap->rscrap); } diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index 2aa971734..efebdc6e0 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -251,18 +251,19 @@ glsl_scraps_f (void) scrap_t *scrap; int area; int size; + int count; if (!scrap_list) { Sys_Printf ("No scraps\n"); return; } for (scrap = scrap_list; scrap; scrap = scrap->next) { - area = R_ScrapArea (&scrap->rscrap); + area = R_ScrapArea (&scrap->rscrap, &count); // always square size = scrap->rscrap.width; - Sys_Printf ("tnum=%u size=%d format=%04x bpp=%d free=%d%%\n", + Sys_Printf ("tnum=%u size=%d format=%04x bpp=%d free=%d%% rects=%d\n", scrap->tnum, size, scrap->format, scrap->bpp, - area * 100 / (size * size)); + area * 100 / (size * size), count); if (Cmd_Argc () > 1) { R_ScrapDump (&scrap->rscrap); } diff --git a/libs/video/renderer/r_scrap.c b/libs/video/renderer/r_scrap.c index 5165cb35b..61641f355 100644 --- a/libs/video/renderer/r_scrap.c +++ b/libs/video/renderer/r_scrap.c @@ -157,13 +157,18 @@ R_ScrapClear (rscrap_t *scrap) } VISIBLE size_t -R_ScrapArea (rscrap_t *scrap) +R_ScrapArea (rscrap_t *scrap, int *count) { vrect_t *rect; size_t area; + int c = 0; for (rect = scrap->free_rects, area = 0; rect; rect = rect->next) { area += rect->width * rect->height; + c++; + } + if (count) { + *count = c; } return area; } From 058e919273f559e69da8cd7737c485d8f526d4a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Sep 2022 19:32:49 +0900 Subject: [PATCH 2986/3664] [renderer] Use better heuristics for scrap allocation More tuning is needed on the actual splits as it falls over when the lower rect gets too low for the subrects being allocated. However, the scrap allocator itself will prefer exact width/height fits with larger cutoff over inexact cuts with smaller cutoff. Many thanks to tdb for the suggestions. Fixes the fps dropping from ~3700fps down to ~450fps (cumulative due to loss of POT rounding and very poor splitting layout), with a bonus boost to about 4900fps (all speeds at 800x450). The 2d sprites were mostly ok, but the lightmaps forming a capital gamma shape in a 4k texture really hurt. Now the lightmaps are a nice dense bar at the top of the texture, and 2d sprites are pretty good (slight improvement coming next). --- libs/ui/vrect.c | 36 +++++++++++++++++++++++++++-------- libs/video/renderer/r_scrap.c | 17 ++++++++++++++++- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/libs/ui/vrect.c b/libs/ui/vrect.c index f9ff47763..226472d47 100644 --- a/libs/ui/vrect.c +++ b/libs/ui/vrect.c @@ -268,10 +268,37 @@ VRect_SubRect (const vrect_t *rect, int width, int height) if (height > rect->height) { height = rect->height; } + // First check for exact fits as no heuristics are necessary + if (width == rect->width) { + if (height == rect->height) { + // Exact fit, return a new rect of the same size + return VRect_New (rect->x, rect->y, rect->width, rect->height); + } + + vrect_t *r = VRect_HSplit (rect, rect->y + height); + if (VRect_IsEmpty (r->next)) { + VRect_Delete (r->next); + r->next = 0; + } + return r; + } else if (height == rect->height) { + // Because rect's width ks known to be greater than the requested + // width, the split is guaranteed to produce two non-empty rectangles. + return VRect_VSplit (rect, rect->x + width); + } + int a = rect->height - height; int b = rect->width - width; vrect_t *r, *s; - if (b * height > a * width) { + if (b * height <= a * width || 16 * a > 15 * rect->height) { + // horizontal cuts produce better memory locality so favor them + r = VRect_HSplit (rect, rect->y + height); + if (VRect_IsEmpty (r->next)) { + VRect_Delete (r->next); + r->next = 0; + } + s = VRect_VSplit (r, r->x + width); + } else { // a horizontal cut produces a larger off-cut rectangle than a vertical // cut, so do a vertical cut first so the off-cut is as small as // possible @@ -281,13 +308,6 @@ VRect_SubRect (const vrect_t *rect, int width, int height) r->next = 0; } s = VRect_HSplit (r, r->y + height); - } else { - r = VRect_HSplit (rect, rect->y + height); - if (VRect_IsEmpty (r->next)) { - VRect_Delete (r->next); - r->next = 0; - } - s = VRect_VSplit (r, r->x + width); } if (VRect_IsEmpty (s->next)) { diff --git a/libs/video/renderer/r_scrap.c b/libs/video/renderer/r_scrap.c index 61641f355..591720a8f 100644 --- a/libs/video/renderer/r_scrap.c +++ b/libs/video/renderer/r_scrap.c @@ -83,8 +83,23 @@ R_ScrapAlloc (rscrap_t *scrap, int width, int height) best = t; continue; } - if ((*t)->width <= (*best)->width || (*t)->height <= (*best)->height) + if ((*t)->width == width && (*t)->height == height) { + // exact fit best = t; + break; + } + if ((*best)->height == height) { + if ((*t)->height == height && (*t)->width < (*best)->width) { + best = t; + } + } else if ((*best)->width == width) { + if ((*t)->width == width && (*t)->height < (*best)->height) { + best = t; + } + } + if ((*t)->width <= (*best)->width || (*t)->height <= (*best)->height) { + best = t; + } } if (!best) return 0; // couldn't find a spot From e407cfa91836cd12f0d932c7c88715ac6bd17b61 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Sep 2022 19:43:53 +0900 Subject: [PATCH 2987/3664] [cl_menu] Reorder menu pic loading for better layout The scrap allocator works better if taller rects are allocated first (so long as they're not too tall, more tuning needed) and qplaque is taller than mainmenu (but draw order is reversed). --- ruamoko/cl_menu/client_menu.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/cl_menu/client_menu.r b/ruamoko/cl_menu/client_menu.r index a962f4305..9a162e2a7 100644 --- a/ruamoko/cl_menu/client_menu.r +++ b/ruamoko/cl_menu/client_menu.r @@ -598,12 +598,12 @@ void () main_menu = Menu_LeaveHook (menu_leave_sound); Menu_KeyEvent (menu_key_sound); Menu_FadeScreen (1); - Menu_Pic (16, 4, "gfx/qplaque.lmp"); Menu_CenterPic (160, 4, "gfx/ttl_main.lmp"); if (do_single_player) Menu_Pic (71,32, "gfx/mainmenu.lmp"); else Menu_SubPic (71,52, "gfx/mainmenu.lmp", 0, 20, 240, 92); + Menu_Pic (16, 4, "gfx/qplaque.lmp"); Menu_Cursor (spinner); if (do_single_player) single_player_menu (); From 8be5d35b0d848a57920808231d6107cdc17ed1fc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Sep 2022 11:53:49 +0900 Subject: [PATCH 2988/3664] [ui] Add support for setting view data early view_new sets the geometry, but any setgeometry that need a valid data pointer would get null. It might be better to always have the data pointer, but I didn't feel like doing such a change at this stage as there are quite a lot of calls to view_new. Thus view_new_data which sets the data pointer before calling setgeometry. --- include/QF/ui/view.h | 15 +++++++++++++++ libs/ui/view.c | 9 ++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index 2a1e42bb7..2ae69e3d7 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -137,6 +137,21 @@ struct view_s { */ view_t *view_new (int xp, int yp, int xl, int yl, grav_t grav); +/** Create a new view. view_t::draw is set to view_draw() and the view is made + visible. All coordinates are set appropriately for the new view being a + root view. All other fields not set by the parameters are 0. + + \param xp The X coordinate of the view's origin. + \param yp The Y coordinate of the view's origin. + \param xl The width of the view. + \param yl The height of the view. + \param grav The gravity of the view. determines the view's origin and + its positioning within the view's parent. + \param data Pointer with which the view\s data pointer will be + initialized. +*/ +view_t *view_new_data (int xp, int yp, int xl, int yl, grav_t grav, void *data); + /** Insert a view into a parent view at the specified location. If \c pos is negative, it is taken to be relative to the end of the parent's list of views (view_insert (par, view, -1) is equivalent to view_add (par, view)). diff --git a/libs/ui/view.c b/libs/ui/view.c index 3ffc70662..0676840cd 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -143,7 +143,7 @@ setgeometry (view_t *view) } VISIBLE view_t * -view_new (int xp, int yp, int xl, int yl, grav_t grav) +view_new_data (int xp, int yp, int xl, int yl, grav_t grav, void *data) { view_t *view = calloc (1, sizeof (view_t)); view->xpos = xp; @@ -153,10 +153,17 @@ view_new (int xp, int yp, int xl, int yl, grav_t grav) view->gravity = grav; view->visible = 1; view->draw = view_draw; + view->data = data; setgeometry (view); return view; } +VISIBLE view_t * +view_new (int xp, int yp, int xl, int yl, grav_t grav) +{ + return view_new_data (xp, yp, xl, yl, grav, 0); +} + VISIBLE void view_insert (view_t *par, view_t *view, int pos) { From 230e23db5d093b30f433559475eeedbe6d62482a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Sep 2022 12:13:06 +0900 Subject: [PATCH 2989/3664] [console] Update a little for event handling Con_CheckResize is no longer necessary thanks to the ie_app_window event, and the client doesn't need C_ProcessInput so that is now optional. --- include/QF/console.h | 1 - include/QF/plugin/console.h | 1 - libs/console/client.c | 22 ---------------------- libs/console/console.c | 11 +++-------- libs/console/server.c | 6 ------ libs/video/targets/vid.c | 2 -- libs/video/targets/vid_x11_sw.c | 1 - 7 files changed, 3 insertions(+), 41 deletions(-) diff --git a/include/QF/console.h b/include/QF/console.h index d3cd87945..c4972e667 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -65,7 +65,6 @@ extern struct console_data_s con_data; //extern qboolean con_initialized; //extern byte *con_chars; -void Con_CheckResize (void); void Con_DrawConsole (void); void Con_Printf (const char *fmt, ...) __attribute__((format(PRINTF, 1, 2))); diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index e14c4d7dc..d24fabca8 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -38,7 +38,6 @@ typedef struct console_funcs_s { void (*print) (const char *fmt, va_list args) __attribute__((format(PRINTF, 1, 0))); void (*process_input) (void); void (*draw_console) (void); - void (*check_resize) (void); void (*new_map) (void); void (*set_state) (con_state_t state); } console_funcs_t; diff --git a/libs/console/client.c b/libs/console/client.c index 62a50c967..315192184 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -288,21 +288,6 @@ Resize (con_buffer_t *con) input_line->width = con_linewidth; } -/* - C_CheckResize - - If the line width has changed, reformat the buffer. -*/ -static void -C_CheckResize (void) -{ - Resize (con_main); - //Resize (con_chat); - - view_resize (con_data.view, r_data->vid->conview->xlen, - r_data->vid->conview->ylen); -} - static void Condump_f (void) { @@ -735,11 +720,6 @@ C_DrawConsole (void) con_data.view->draw (con_data.view); } -static void -C_ProcessInput (void) -{ -} - static void C_NewMap (void) { @@ -1007,9 +987,7 @@ static general_funcs_t plugin_info_general_funcs = { static console_funcs_t plugin_info_console_funcs = { .print = C_Print, - .process_input = C_ProcessInput, .draw_console = C_DrawConsole, - .check_resize = C_CheckResize, .new_map = C_NewMap, .set_state = C_SetState, }; diff --git a/libs/console/console.c b/libs/console/console.c index 7b5dcfeca..fbf535253 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -180,7 +180,9 @@ VISIBLE void Con_ProcessInput (void) { if (con_module) { - con_module->functions->console->process_input (); + if (con_module->functions->console->process_input) { + con_module->functions->console->process_input (); + } } else { static int been_there_done_that = 0; @@ -205,13 +207,6 @@ Con_DrawConsole (void) con_module->functions->console->draw_console (); } -VISIBLE void -Con_CheckResize (void) -{ - if (con_module) - con_module->functions->console->check_resize (); -} - VISIBLE void Con_NewMap (void) { diff --git a/libs/console/server.c b/libs/console/server.c index 173b422ee..86a40230e 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -803,11 +803,6 @@ C_DrawConsole (void) sv_con_data.status_view->draw (sv_con_data.status_view); } -static void -C_CheckResize (void) -{ -} - static void C_NewMap (void) { @@ -823,7 +818,6 @@ static console_funcs_t plugin_info_console_funcs = { .print = C_Print, .process_input = C_ProcessInput, .draw_console = C_DrawConsole, - .check_resize = C_CheckResize, .new_map = C_NewMap, }; diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index d13da102e..fe2a62333 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -192,8 +192,6 @@ VID_GetWindowSize (int def_w, int def_h) // make con_height >= 200 con_height = max (con_height & ~7, 200); viddef.conview->ylen = con_height; - - Con_CheckResize (); // Now that we have a window size, fix console } /* GAMMA FUNCTIONS */ diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 7601d72d0..455d2b8e9 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -686,7 +686,6 @@ x11_create_context (sw_ctx_t *ctx) // No console scaling in the sw renderer viddef.conview->xlen = viddef.width; viddef.conview->ylen = viddef.height; - Con_CheckResize (); viddef.vid_internal->init_buffers = x11_init_buffers; // XSynchronize (x_disp, False); From 0921235aa6525bb186bfe9700d30a0c00302048e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Sep 2022 12:17:44 +0900 Subject: [PATCH 2990/3664] [console] Fix a lot of the console view placement issues Things seem to be at least close to the right place now. Input line handling has been made more object-oriented in that the collection of objects required for a single input line (command, say, say_team) are bundled into one object with just one set of handlers for resize and draw. Much tidier. --- libs/console/client.c | 425 +++++++++++++++++++++--------------------- 1 file changed, 217 insertions(+), 208 deletions(-) diff --git a/libs/console/client.c b/libs/console/client.c index 315192184..75eeae97b 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -66,7 +66,6 @@ static general_data_t plugin_info_general_data; console_data_t con_data; -//static con_buffer_t *con_chat; static con_buffer_t *con; static float con_cursorspeed = 4; @@ -144,7 +143,6 @@ static cvar_t cl_conmode_cvar = { .value = { .type = &cl_conmode_type, .value = &con_data.exec_line }, }; -static int con_totallines; // total lines in console scrollback static con_state_t con_state; static int con_event_id; static int con_saved_focos; @@ -152,8 +150,18 @@ static int con_saved_focos; static qboolean con_debuglog; static qboolean chat_team; -#define MAXCMDLINE 256 -static inputline_t *input_line; +typedef struct { + const char *prompt; + inputline_t *input_line; + view_t *view; + draw_charbuffer_t *buffer; +} con_input_t; + +#define MAXCMDLINE 256 + +static con_input_t cmd_line; +static con_input_t say_line; +static con_input_t team_line; #define CON_BUFFER_SIZE 32768 #define CON_LINES 1024 @@ -162,11 +170,6 @@ static draw_charbuffer_t *console_buffer; static con_buffer_t *con_main; static int view_offset; -static view_t *say_view; -static draw_charbuffer_t *say_buffer; -static inputline_t *say_line; -static inputline_t *say_team_line; - #define NOTIFY_LINES 4 static view_t *notify_view; static draw_charbuffer_t *notify_buffer; @@ -200,12 +203,12 @@ C_SetState (con_state_t state) } if (state == con_message) { - const char *prompt = "say:"; + say_line.prompt = "say:"; if (chat_team) { - prompt = "say_team:"; + say_line.prompt = "say_team:"; } - say_buffer->cursx = 0; - Draw_PrintBuffer (say_buffer, prompt); + say_line.buffer->cursx = 0; + Draw_PrintBuffer (say_line.buffer, say_line.prompt); } if (con_state == con_menu && old_state != con_menu) { @@ -229,97 +232,11 @@ ToggleConsole_f (void) case con_fullscreen: break; } - Con_ClearTyping (input_line, 0); + Con_ClearTyping (cmd_line.input_line, 0); ClearNotify (); } -static void -Clear_f (void) -{ - Con_ClearBuffer (con_main); - //Con_ClearBuffer (con_chat); -} - -static void -MessageMode_f (void) -{ - if (con_state != con_inactive) - return; - chat_team = false; - C_SetState (con_message); -} - -static void -MessageMode2_f (void) -{ - if (con_state != con_inactive) - return; - chat_team = true; - C_SetState (con_message); -} - -static void -Resize (con_buffer_t *con) -{ - int width, oldwidth, oldtotallines, numlines, numchars; - - width = (r_data->vid->conview->xlen >> 3) - 2; - - if (width < 1) { // video hasn't been initialized yet - width = 38; - con_linewidth = width; - } else { - oldwidth = con_linewidth; - con_linewidth = width; - oldtotallines = con_totallines; - numlines = oldtotallines; - - if (con_totallines < numlines) - numlines = con_totallines; - - numchars = oldwidth; - - if (con_linewidth < numchars) - numchars = con_linewidth; - - ClearNotify (); - } - input_line->width = con_linewidth; -} - -static void -Condump_f (void) -{ - QFile *file; - const char *name; - - if (Cmd_Argc () != 2) { - Sys_Printf ("usage: condump \n"); - return; - } - - if (strchr (Cmd_Argv (1), '/') || strchr (Cmd_Argv (1), '\\')) { - Sys_Printf ("invalid character in filename\n"); - return; - } - name = va (0, "%s/%s.txt", qfs_gamedir->dir.def, Cmd_Argv (1));//FIXME - - if (!(file = QFS_WOpen (name, 0))) { - Sys_Printf ("could not open %s for writing: %s\n", name, - strerror (errno)); - return; - } - - for (uint32_t line_ind = con->line_tail; line_ind != con->line_head; - line_ind = (line_ind + 1) % con->max_lines) { - con_line_t *line = &con->lines[line_ind]; - Qwrite (file, con->buffer + line->text, line->len); - } - - Qclose (file); -} - static int cl_exec_line_command (void *data, const char *line) { @@ -456,6 +373,18 @@ C_Print (const char *fmt, va_list args) /* DRAWING */ +static void +draw_cursor (int x, int y, inputline_t *il) +{ + if (!con_data.realtime) { + return; + } + + float t = *con_data.realtime * con_cursorspeed; + int ch = 10 + ((int) (t) & 1); + r_funcs->Draw_Character (x + ((il->linepos - il->scroll) * 8), y, ch); +} + static void DrawInputLine (int x, int y, int cursor, inputline_t *il) { @@ -467,13 +396,11 @@ DrawInputLine (int x, int y, int cursor, inputline_t *il) } else { r_funcs->Draw_nString (x, y, s, il->width - 1); } - if (cursor && con_data.realtime) { - float t = *con_data.realtime * con_cursorspeed; - int ch = 10 + ((int) (t) & 1); - r_funcs->Draw_Character (x + ((il->linepos - il->scroll) << 3), y, ch); + if (cursor) { + draw_cursor (x, y, il); } if (strlen (s) >= il->width) - r_funcs->Draw_Character (x + ((il->width - 1) << 3), y, '>' | 0x80); + r_funcs->Draw_Character (x + ((il->width - 1) * 8), y, '>' | 0x80); } void @@ -482,13 +409,53 @@ C_DrawInputLine (inputline_t *il) DrawInputLine (il->x, il->y, il->cursor, il); } +static void +draw_input_line (inputline_t *il, draw_charbuffer_t *buffer) +{ + char *dst = buffer->chars + buffer->cursx; + char *src = il->lines[il->edit_line] + il->scroll + 1; + size_t i; + + *dst++ = il->scroll ? '<' | 0x80 : il->lines[il->edit_line][0]; + for (i = 0; i < il->width - 2 && *src; i++) { + *dst++ = *src++; + } + while (i++ < il->width - 2) { + *dst++ = ' '; + } + *dst++ = *src ? '>' | 0x80 : ' '; +} + static void draw_input (view_t *view) { - if (con_state == con_inactive) - return; + __auto_type inp = (con_input_t *) view->data; - DrawInputLine (view->xabs + 8, view->yabs, 1, input_line); + Draw_CharBuffer (view->xabs, view->yabs, inp->buffer); + draw_cursor (view->xabs + inp->buffer->cursx * 8, view->yabs, + inp->input_line); +} + +static void +input_line_draw (inputline_t *il) +{ + __auto_type inp = (con_input_t *) il->user_data; + draw_input_line (il, inp->buffer); +} + +static void +resize_input (view_t *view) +{ + __auto_type inp = (con_input_t *) view->data; + + if (inp->buffer) { + Draw_DestroyBuffer (inp->buffer); + } + inp->buffer = Draw_CreateBuffer (view->xlen / 8, 1); + Draw_ClearBuffer (inp->buffer); + Draw_PrintBuffer (inp->buffer, inp->prompt); + inp->buffer->chars[inp->buffer->cursx] = inp->input_line->prompt_char; + inp->input_line->width = inp->buffer->width - inp->buffer->cursx; } static void @@ -544,6 +511,27 @@ draw_console_text (view_t *view) Draw_CharBuffer (view->xabs, view->yabs, console_buffer); } +static void +clear_console_text (void) +{ + Draw_ClearBuffer (console_buffer); + console_buffer->cursy = console_buffer->height - 1; +} + +static void +resize_console_text (view_t *view) +{ + int width = view->xlen / 8; + int height = view->ylen / 8; + + ClearNotify (); + + con_linewidth = width; + Draw_DestroyBuffer (console_buffer); + console_buffer = Draw_CreateBuffer (width, height); + clear_console_text (); +} + static void draw_con_scrollback (void) { @@ -586,64 +574,6 @@ draw_console (view_t *view) view_draw (view); } -static void -draw_say (view_t *view) -{ - r_data->scr_copytop = 1; - - Draw_CharBuffer (view->xabs, view->yabs, say_buffer); -} - -static void -draw_input_line (inputline_t *il, draw_charbuffer_t *buffer) -{ - char *dst = buffer->chars + buffer->cursx; - char *src = il->lines[il->edit_line] + il->scroll; - size_t i; - - *dst++ = il->scroll ? '<' | 0x80 : ' '; - for (i = 0; i < il->width - 2 && *src; i++) { - *dst++ = *src++; - } - while (i++ < il->width - 2) { - *dst++ = ' '; - } - *dst++ = *src ? '>' | 0x80 : ' '; -} - -static void -say_line_draw (inputline_t *il) -{ - say_buffer->cursx = 4; - draw_input_line (il, say_buffer); -} - -static void -say_team_line_draw (inputline_t *il) -{ - say_buffer->cursx = 9; - draw_input_line (il, say_buffer); -} - -static void -resize_console (view_t *view) -{ - Draw_DestroyBuffer (console_buffer); - console_buffer = Draw_CreateBuffer (view->xlen / 8, view->ylen / 8); - Draw_ClearBuffer (console_buffer); -} - -static void -resize_say (view_t *view) -{ - Draw_DestroyBuffer (say_buffer); - say_buffer = Draw_CreateBuffer (view->xlen / 8, 1); - Draw_ClearBuffer (say_buffer); - - say_team_line->width = say_buffer->width - 9; - say_line->width = say_buffer->width - 4; -} - static void draw_notify (view_t *view) { @@ -710,10 +640,8 @@ C_DrawConsole (void) { setup_console (); - if (console_view->ylen != con_data.lines) - view_resize (console_view, console_view->xlen, con_data.lines); - - say_view->visible = con_state == con_message; + say_line.view->visible = con_state == con_message ? !chat_team : 0; + team_line.view->visible = con_state == con_message ? chat_team : 0; console_view->visible = con_data.lines != 0; menu_view->visible = con_state == con_menu; @@ -750,6 +678,21 @@ exec_line (inputline_t *il) Con_ExecLine (il->line); } +static void +con_app_window (const IE_event_t *event) +{ + static int old_xlen; + static int old_ylen; + if (old_xlen != event->app_window.xlen + || old_ylen != event->app_window.ylen) { + old_xlen = event->app_window.xlen; + old_ylen = event->app_window.ylen; + + view_resize (con_data.view, r_data->vid->conview->xlen, + r_data->vid->conview->ylen); + } +} + static void con_key_event (const IE_event_t *event) { @@ -772,9 +715,9 @@ con_key_event (const IE_event_t *event) #endif if (con_state == con_message) { if (chat_team) { - il = say_team_line; + il = team_line.input_line; } else { - il = say_line; + il = say_line.input_line; } if (key->code == QFK_ESCAPE) { con_end_message (il); @@ -810,7 +753,7 @@ con_key_event (const IE_event_t *event) default: break; } - il = input_line; + il = cmd_line.input_line; } if (old_view_offset != view_offset) { draw_con_scrollback (); @@ -836,6 +779,7 @@ con_event_handler (const IE_event_t *ie_event, void *data) return Menu_EventHandler (ie_event); } static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { + [ie_app_window] = con_app_window, [ie_key] = con_key_event, [ie_mouse] = con_mouse_event, }; @@ -847,6 +791,63 @@ con_event_handler (const IE_event_t *ie_event, void *data) return 1; } +static void +Clear_f (void) +{ + Con_ClearBuffer (con_main); + clear_console_text (); +} + +static void +MessageMode_f (void) +{ + if (con_state != con_inactive) + return; + chat_team = false; + C_SetState (con_message); +} + +static void +MessageMode2_f (void) +{ + if (con_state != con_inactive) + return; + chat_team = true; + C_SetState (con_message); +} + +static void +Condump_f (void) +{ + QFile *file; + const char *name; + + if (Cmd_Argc () != 2) { + Sys_Printf ("usage: condump \n"); + return; + } + + if (strchr (Cmd_Argv (1), '/') || strchr (Cmd_Argv (1), '\\')) { + Sys_Printf ("invalid character in filename\n"); + return; + } + name = va (0, "%s/%s.txt", qfs_gamedir->dir.def, Cmd_Argv (1));//FIXME + + if (!(file = QFS_WOpen (name, 0))) { + Sys_Printf ("could not open %s for writing: %s\n", name, + strerror (errno)); + return; + } + + for (uint32_t line_ind = con->line_tail; line_ind != con->line_head; + line_ind = (line_ind + 1) % con->max_lines) { + con_line_t *line = &con->lines[line_ind]; + Qwrite (file, con->buffer + line->text, line->len); + } + + Qclose (file); +} + static void C_Init (void) { @@ -872,12 +873,51 @@ C_Init (void) // The console will get resized, so assume initial size is 320x200 con_data.view = view_new (0, 0, 320, 200, grav_northeast); console_view = view_new (0, 0, 320, 200, grav_northwest); - say_view = view_new (0, 0, 320, 8, grav_northwest); notify_view = view_new (8, 8, 312, NOTIFY_LINES * 8, grav_northwest); menu_view = view_new (0, 0, 320, 200, grav_center); hud_view = view_new (0, 0, 320, 200, grav_northeast); - view_add (con_data.view, say_view); + cmd_line.prompt = ""; + cmd_line.input_line = Con_CreateInputLine (32, MAXCMDLINE, ']'); + cmd_line.input_line->complete = Con_BasicCompleteCommandLine; + cmd_line.input_line->enter = exec_line; + cmd_line.input_line->width = con_linewidth; + cmd_line.input_line->user_data = &cmd_line; + cmd_line.input_line->draw = input_line_draw; + cmd_line.view = view_new_data (0, 12, 320, 10, grav_southwest, &cmd_line); + cmd_line.view->draw = draw_input; + cmd_line.view->setgeometry = resize_input; + cmd_line.view->resize_x = 1; + view_add (console_view, cmd_line.view); + + say_line.prompt = "say:"; + say_line.input_line = Con_CreateInputLine (32, MAXCMDLINE, ' '); + say_line.input_line->complete = 0; + say_line.input_line->enter = C_Say; + say_line.input_line->width = con_linewidth - 5; + say_line.input_line->user_data = &say_line; + say_line.input_line->draw = input_line_draw; + say_line.view = view_new_data (0, 0, 320, 8, grav_northwest, &say_line); + say_line.view->draw = draw_input; + say_line.view->setgeometry = resize_input; + say_line.view->visible = 0; + say_line.view->resize_x = 1; + view_add (con_data.view, say_line.view); + + team_line.prompt = "say_team:"; + team_line.input_line = Con_CreateInputLine (32, MAXCMDLINE, ' '); + team_line.input_line->complete = 0; + team_line.input_line->enter = C_SayTeam; + team_line.input_line->width = con_linewidth - 10; + team_line.input_line->user_data = &team_line; + team_line.input_line->draw = input_line_draw; + team_line.view = view_new_data (0, 0, 320, 8, grav_northwest, &team_line); + team_line.view->draw = draw_input; + team_line.view->setgeometry = resize_input; + team_line.view->visible = 0; + team_line.view->resize_x = 1; + view_add (con_data.view, team_line.view); + view_add (con_data.view, notify_view); view_add (con_data.view, hud_view); view_add (con_data.view, console_view); @@ -888,16 +928,9 @@ C_Init (void) Draw_ClearBuffer (console_buffer); con_main = Con_CreateBuffer (CON_BUFFER_SIZE, CON_LINES); console_view->draw = draw_console; - say_view->setgeometry = resize_console; console_view->visible = 0; console_view->resize_x = console_view->resize_y = 1; - say_buffer = Draw_CreateBuffer (say_view->xlen / 8, 1); - Draw_ClearBuffer (say_buffer); - say_view->draw = draw_say; - say_view->setgeometry = resize_say; - say_view->visible = 0; - say_view->resize_x = 1; notify_buffer = Draw_CreateBuffer (notify_view->xlen / 8, NOTIFY_LINES + 1); Draw_ClearBuffer (notify_buffer); @@ -911,16 +944,12 @@ C_Init (void) hud_view->draw = Menu_Draw_Hud; hud_view->visible = 0; - view = view_new (0, 0, 320, 170, grav_northwest); + view = view_new (8, 16, 320, 168, grav_southwest); view->draw = draw_console_text; + view->setgeometry = resize_console_text; view->resize_x = view->resize_y = 1; view_add (console_view, view); - view = view_new (0, 12, 320, 10, grav_southwest); - view->draw = draw_input; - view->resize_x = 1; - view_add (console_view, view); - view = view_new (0, 2, 320, 11, grav_southwest); view->draw = draw_download; view->resize_x = 1; @@ -929,28 +958,8 @@ C_Init (void) con = con_main; con_linewidth = -1; - input_line = Con_CreateInputLine (32, MAXCMDLINE, ']'); - input_line->complete = Con_BasicCompleteCommandLine; - input_line->enter = exec_line; - input_line->width = con_linewidth; - input_line->user_data = 0; - input_line->draw = 0; - say_line = Con_CreateInputLine (32, MAXCMDLINE, ' '); - say_line->complete = 0; - say_line->enter = C_Say; - say_line->width = con_linewidth - 5; - say_line->user_data = 0; - say_line->draw = say_line_draw; - say_team_line = Con_CreateInputLine (32, MAXCMDLINE, ' '); - say_team_line->complete = 0; - say_team_line->enter = C_SayTeam; - say_team_line->width = con_linewidth - 10; - say_team_line->user_data = 0; - say_team_line->draw = say_team_line_draw; - - C_CheckResize (); Sys_Printf ("Console initialized.\n"); From 2473584759616c3a6b664bf4a5023067a162206e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Sep 2022 12:20:56 +0900 Subject: [PATCH 2991/3664] [vid] Clean out an unused variable from context_win It's dead, Jim. --- libs/video/targets/context_win.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index ce9eb87b5..207278f0a 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -222,7 +222,6 @@ static qboolean startwindowed = 0; //static qboolean windowed_mode_set; //static int vid_fulldib_on_focus_mode; static qboolean force_minimized; -static qboolean in_mode_set; static qboolean force_mode_set; static qboolean vid_mode_set; //static HICON hIcon; @@ -663,7 +662,6 @@ VID_RestoreOldMode (int original_mode) if (inerror) return; - in_mode_set = false; inerror = true; // make sure mode set happens (video mode changes) vid_modenum = original_mode - 1; @@ -738,8 +736,6 @@ VID_SetMode (int modenum, const byte *palette) if (!force_mode_set && (modenum == vid_modenum)) return true; - // so Con_Printfs don't mess us up by forcing vid and snd updates - in_mode_set = true; //FIXME CDAudio_Pause (); //FIXME S_ClearBuffer (); @@ -812,8 +808,6 @@ VID_SetMode (int modenum, const byte *palette) Sys_Printf ("%s\n", VID_GetModeDescription (vid_modenum)); - in_mode_set = false; - viddef.recalc_refdef = 1; //FIXME SCR_StretchInit(); @@ -886,8 +880,6 @@ Win_CreateWindow (int width, int height) Sys_Printf ("%s\n", VID_GetModeDescription (vid_modenum)); - in_mode_set = false; - viddef.recalc_refdef = 1; } From 4578b1af0dbeb1599fe63c9729f1c99527c403b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Sep 2022 17:31:18 +0900 Subject: [PATCH 2992/3664] [vid] Remove console view from viddef_t This breaks console scaling for now (con_width and con_height are gone), but is a major step towards window resize support as console stuff should never have been in viddef_t in the first place. The client screen init code now sets up a screen view (actually the renderer's scr_view) that is passed to the client console so it can know the size of the screen. The same view is used by the status bar code. Also, the ram/cache/paused icon drawing is moved into the client screen update code. A bit of duplication, but I do plan on merging that eventually. --- include/QF/plugin/console.h | 1 + include/QF/screen.h | 4 - include/QF/vid.h | 1 - libs/console/client.c | 16 +-- libs/video/renderer/gl/gl_draw.c | 26 ++-- libs/video/renderer/glsl/glsl_draw.c | 17 ++- libs/video/renderer/r_cvar.c | 30 ---- libs/video/renderer/r_progs.c | 4 +- libs/video/renderer/r_screen.c | 62 +-------- libs/video/renderer/sw/draw.c | 44 +++--- libs/video/renderer/vid_render_vulkan.c | 4 +- libs/video/renderer/vulkan/vulkan_draw.c | 24 ++-- libs/video/targets/vid.c | 55 ++------ libs/video/targets/vid_x11_sw.c | 5 - nq/include/client.h | 2 + nq/source/cl_main.c | 1 + nq/source/cl_screen.c | 167 ++++++++++++++++++----- nq/source/sbar.c | 48 +++---- qw/include/client.h | 2 + qw/source/cl_main.c | 1 + qw/source/cl_screen.c | 160 ++++++++++++++++++---- qw/source/sbar.c | 35 +++-- 22 files changed, 388 insertions(+), 321 deletions(-) diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index d24fabca8..1c9f02f5c 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -51,6 +51,7 @@ typedef struct console_data_s { int ormask; void (*quit) (void); struct cbuf_s *cbuf; + struct view_s *screen_view; struct view_s *view; struct view_s *status_view; float lines; diff --git a/include/QF/screen.h b/include/QF/screen.h index d53b1b1ee..bf0c60ee1 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -35,10 +35,6 @@ struct tex_s; void SCR_Init (void); -void SCR_DrawRam (void); -void SCR_DrawTurtle (void); -void SCR_DrawPause (void); - typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array void SCR_UpdateScreen (struct transform_s *camera, double realtime, diff --git a/include/QF/vid.h b/include/QF/vid.h index c8ce3b226..6b03b3c9b 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -49,7 +49,6 @@ typedef struct { unsigned height; int numpages; qboolean recalc_refdef; // if true, recalc vid-based stuff - struct view_s *conview; struct vid_internal_s *vid_internal; struct viddef_listener_set_s *onPaletteChanged; diff --git a/libs/console/client.c b/libs/console/client.c index 75eeae97b..91f512cd1 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -563,7 +563,7 @@ draw_console (view_t *view) if (con_state == con_fullscreen) { alpha = 255; } else { - float y = r_data->vid->conview->ylen * con_size; + float y = con_data.screen_view->ylen * con_size; alpha = 255 * con_alpha * view->ylen / y; alpha = min (alpha, 255); } @@ -609,11 +609,11 @@ setup_console (void) lines = 0; break; case con_active: - lines = r_data->vid->conview->ylen * bound (0.2, con_size, + lines = con_data.screen_view->ylen * bound (0.2, con_size, 1); break; case con_fullscreen: - lines = con_data.lines = r_data->vid->conview->ylen; + lines = con_data.lines = con_data.screen_view->ylen; break; } @@ -628,10 +628,10 @@ setup_console (void) } else { con_data.lines = lines; } - if (con_data.lines > r_data->vid->conview->ylen) { - con_data.lines = r_data->vid->conview->ylen; + if (con_data.lines > con_data.screen_view->ylen) { + con_data.lines = con_data.screen_view->ylen; } - if (con_data.lines >= r_data->vid->conview->ylen - r_data->lineadj) + if (con_data.lines >= con_data.screen_view->ylen - r_data->lineadj) r_data->scr_copyeverything = 1; } @@ -688,8 +688,8 @@ con_app_window (const IE_event_t *event) old_xlen = event->app_window.xlen; old_ylen = event->app_window.ylen; - view_resize (con_data.view, r_data->vid->conview->xlen, - r_data->vid->conview->ylen); + view_resize (con_data.view, con_data.screen_view->xlen, + con_data.screen_view->ylen); } } diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 9ee389775..7b79dfc13 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -711,8 +711,8 @@ gl_Draw_Crosshair (void) if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) return; - x = vid.conview->xlen / 2 + cl_crossx; - y = vid.conview->ylen / 2 + cl_crossy; + x = vid.width / 2 + cl_crossx; + y = vid.height / 2 + cl_crossy; crosshair_func[ch] (x, y); } @@ -837,7 +837,7 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) if (gl_constretch) { ofs = 0; } else - ofs = (vid.conview->ylen - lines) / (float) vid.conview->ylen; + ofs = (vid.height - lines) / (float) vid.height; color_0_8[3] = alpha; qfglColor4ubv (color_0_8); @@ -852,9 +852,9 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) qfglTexCoord2f (0, 0 + ofs); qfglVertex2f (0, 0); qfglTexCoord2f (1, 0 + ofs); - qfglVertex2f (vid.conview->xlen, 0); + qfglVertex2f (vid.width, 0); qfglTexCoord2f (1, 1); - qfglVertex2f (vid.conview->xlen, lines); + qfglVertex2f (vid.width, lines); qfglTexCoord2f (0, 1); qfglVertex2f (0, lines); qfglEnd (); @@ -871,7 +871,7 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) } int len = strlen (cl_verstring); - gl_Draw_AltString (vid.conview->xlen - len * 8 - 11, lines - 14, + gl_Draw_AltString (vid.width - len * 8 - 11, lines - 14, cl_verstring); qfglColor3ubv (color_white); } @@ -951,9 +951,9 @@ gl_Draw_FadeScreen (void) qfglBegin (GL_QUADS); qfglVertex2f (0, 0); - qfglVertex2f (vid.conview->xlen, 0); - qfglVertex2f (vid.conview->xlen, vid.conview->ylen); - qfglVertex2f (0, vid.conview->ylen); + qfglVertex2f (vid.width, 0); + qfglVertex2f (vid.width, vid.height); + qfglVertex2f (0, vid.height); qfglEnd (); qfglColor3ubv (color_white); @@ -993,7 +993,7 @@ GL_Set2D (void) void GL_Set2DScaled (void) { - set_2d (vid.conview->xlen, vid.conview->ylen); + set_2d (vid.width, vid.height); } void @@ -1024,9 +1024,9 @@ gl_Draw_BlendScreen (quat_t color) qfglColor4fv (color); qfglVertex2f (0, 0); - qfglVertex2f (vid.conview->xlen, 0); - qfglVertex2f (vid.conview->xlen, vid.conview->ylen); - qfglVertex2f (0, vid.conview->ylen); + qfglVertex2f (vid.width, 0); + qfglVertex2f (vid.width, vid.height); + qfglVertex2f (0, vid.height); qfglEnd (); diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 6258d3048..c58352a03 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -611,8 +611,8 @@ glsl_Draw_Crosshair (void) { int x, y; - x = vid.conview->xlen / 2 + cl_crossx; - y = vid.conview->ylen / 2 + cl_crossy; + x = vid.width / 2 + cl_crossx; + y = vid.height / 2 + cl_crossy; glsl_Draw_CrosshairAt (crosshair, x, y); } @@ -644,14 +644,14 @@ glsl_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, void glsl_Draw_ConsoleBackground (int lines, byte alpha) { - float ofs = (vid.conview->ylen - lines) / (float) vid.conview->ylen; + float ofs = (vid.height - lines) / (float) vid.height; quat_t color = {1, 1, 1, bound (0, alpha, 255) / 255.0}; drawvert_t verts[] = { {{ 0, 0, 0, ofs}}, - {{vid.conview->xlen, 0, 1, ofs}}, - {{vid.conview->xlen, lines, 1, 1}}, + {{vid.width, 0, 1, ofs}}, + {{vid.width, lines, 1, 1}}, {{ 0, 0, 0, ofs}}, - {{vid.conview->xlen, lines, 1, 1}}, + {{vid.width, lines, 1, 1}}, {{ 0, lines, 0, 1}}, }; @@ -751,8 +751,7 @@ glsl_Draw_Line (int x0, int y0, int x1, int y1, int c) static inline void draw_blendscreen (quat_t color) { - draw_pic (0, 0, vid.conview->xlen, vid.conview->ylen, white_pic, - 0, 0, 8, 8, color); + draw_pic (0, 0, vid.width, vid.height, white_pic, 0, 0, 8, 8, color); } void @@ -825,7 +824,7 @@ GLSL_Set2D (void) void GLSL_Set2DScaled (void) { - set_2d (vid.conview->xlen, vid.conview->ylen); + set_2d (vid.width, vid.height); } void diff --git a/libs/video/renderer/r_cvar.c b/libs/video/renderer/r_cvar.c index 76937ebae..41c666d0a 100644 --- a/libs/video/renderer/r_cvar.c +++ b/libs/video/renderer/r_cvar.c @@ -463,33 +463,6 @@ static cvar_t scr_ffov_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_float, .value = &scr_ffov }, }; -int scr_showpause; -static cvar_t scr_showpause_cvar = { - .name = "showpause", - .description = - "Toggles display of pause graphic", - .default_value = "1", - .flags = CVAR_NONE, - .value = { .type = &cexpr_int, .value = &scr_showpause }, -}; -int scr_showram; -static cvar_t scr_showram_cvar = { - .name = "showram", - .description = - "Show RAM icon if game is running low on memory", - .default_value = "1", - .flags = CVAR_NONE, - .value = { .type = &cexpr_int, .value = &scr_showram }, -}; -int scr_showturtle; -static cvar_t scr_showturtle_cvar = { - .name = "showturtle", - .description = - "Show a turtle icon if your fps is below 10", - .default_value = "0", - .flags = CVAR_NONE, - .value = { .type = &cexpr_int, .value = &scr_showturtle }, -}; int scr_viewsize; static cvar_t scr_viewsize_cvar = { .name = "viewsize", @@ -651,9 +624,6 @@ R_Init_Cvars (void) Cvar_Register (&scr_fisheye_cvar, scr_fisheye_f, 0); Cvar_Register (&scr_fviews_cvar, 0, 0); Cvar_Register (&scr_ffov_cvar, scr_ffov_f, 0); - Cvar_Register (&scr_showpause_cvar, 0, 0); - Cvar_Register (&scr_showram_cvar, 0, 0); - Cvar_Register (&scr_showturtle_cvar, 0, 0); Cvar_Register (&scr_viewsize_cvar, viewsize_f, 0); r_data->graphheight = &r_graphheight; diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 2b33da012..b7a1004f3 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -373,13 +373,13 @@ bi_Draw_Crosshair (progs_t *pr, void *_res) static void bi_Draw_Width (progs_t *pr, void *_res) { - R_INT (pr) = r_data->vid->conview->xlen; + R_INT (pr) = r_data->vid->width; } static void bi_Draw_Height (progs_t *pr, void *_res) { - R_INT (pr) = r_data->vid->conview->ylen; + R_INT (pr) = r_data->vid->height; } static void diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index f55531c0c..4106220f8 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -67,8 +67,6 @@ int *r_face_visframes; //FIXME per renderer qboolean scr_skipupdate; static qboolean scr_initialized;// ready to draw -static qpic_t *scr_ram; -static qpic_t *scr_turtle; static framebuffer_t *fisheye_cube_map; static framebuffer_t *warp_buffer; @@ -431,60 +429,6 @@ SCR_SizeDown_f (void) r_data->vid->recalc_refdef = 1; } -void -SCR_DrawRam (void) -{ - if (!scr_showram) - return; - - if (!r_cache_thrash) - return; - - //FIXME view - r_funcs->Draw_Pic (r_data->scr_view->xpos + 32, r_data->scr_view->ypos, - scr_ram); -} - -void -SCR_DrawTurtle (void) -{ - static int count; - - if (!scr_showturtle) - return; - - if (r_data->frametime < 0.1) { - count = 0; - return; - } - - count++; - if (count < 3) - return; - - //FIXME view - r_funcs->Draw_Pic (r_data->scr_view->xpos, r_data->scr_view->ypos, - scr_turtle); -} - -void -SCR_DrawPause (void) -{ - qpic_t *pic; - - if (!scr_showpause) // turn off for screenshots - return; - - if (!r_data->paused) - return; - - //FIXME view conwidth - pic = r_funcs->Draw_CachePic ("gfx/pause.lmp", true); - r_funcs->Draw_Pic ((r_data->vid->conview->xlen - pic->width) / 2, - (r_data->vid->conview->ylen - 48 - pic->height) / 2, - pic); -} - static void viewsize_listener (void *data, const cvar_t *cvar) { @@ -494,15 +438,15 @@ viewsize_listener (void *data, const cvar_t *cvar) void SCR_Init (void) { + r_data->scr_view->xlen = r_data->vid->width; + r_data->scr_view->ylen = r_data->vid->height; + // register our commands Cmd_AddCommand ("screenshot", ScreenShot_f, "Take a screenshot, " "saves as qfxxxx.png in the QF directory"); Cmd_AddCommand ("sizeup", SCR_SizeUp_f, "Increases the screen size"); Cmd_AddCommand ("sizedown", SCR_SizeDown_f, "Decreases the screen size"); - scr_ram = r_funcs->Draw_PicFromWad ("ram"); - scr_turtle = r_funcs->Draw_PicFromWad ("turtle"); - scr_initialized = true; r_ent_queue = EntQueue_New (mod_num_types); diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 06db109af..1edbd5a51 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -265,7 +265,7 @@ Draw_Character (int x, int y, unsigned int chr) if (y <= -8) return; // totally off screen - if (y > vid.conview->ylen - 8 || x < 0 || x > vid.conview->xlen - 8) + if (y > (int) vid.height - 8 || x < 0 || x > (int) vid.width - 8) return; if (chr > 255) return; @@ -478,8 +478,8 @@ Draw_Crosshair (void) if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) return; - x = vid.conview->xlen / 2 + cl_crossx; - y = vid.conview->ylen / 2 + cl_crossy; + x = vid.width / 2 + cl_crossx; + y = vid.height / 2 + cl_crossy; crosshair_func[ch] (x, y); } @@ -501,8 +501,8 @@ Draw_Pic (int x, int y, qpic_t *pic) byte *dest, *source, tbyte; int v, u; - if (x < 0 || (x + pic->width) > vid.conview->xlen - || y < 0 || (y + pic->height) > vid.conview->ylen) { + if (x < 0 || (x + pic->width) > (int) vid.width + || y < 0 || (y + pic->height) > (int) vid.height) { Sys_MaskPrintf (SYS_vid, "Draw_Pic: bad coordinates"); Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height); return; @@ -560,8 +560,8 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, byte *dest, *source, tbyte; int u, v; - if ((x < 0) || (x + width > vid.conview->xlen) - || (y < 0) || (y + height > vid.conview->ylen)) { + if ((x < 0) || (x + width > (int) vid.width) + || (y < 0) || (y + height > (int) vid.height)) { Sys_MaskPrintf (SYS_vid, "Draw_SubPic: bad coordinates"); } // first, clip to screen @@ -629,7 +629,6 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, void Draw_ConsoleBackground (int lines, byte alpha) { - int x, y, v; byte *src, *dest; int f, fstep; qpic_t *conback; @@ -639,15 +638,15 @@ Draw_ConsoleBackground (int lines, byte alpha) // draw the pic dest = d_viewbuffer; - for (y = 0; y < lines; y++, dest += d_rowbytes) { - v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; + for (int y = 0; y < lines; y++, dest += d_rowbytes) { + int v = (vid.height - lines + y) * 200 / vid.height; src = conback->data + v * 320; - if (vid.conview->xlen == 320) - memcpy (dest, src, vid.conview->xlen); + if (vid.width == 320) + memcpy (dest, src, vid.width); else { f = 0; - fstep = 320 * 0x10000 / vid.conview->xlen; - for (x = 0; x < vid.conview->xlen; x += 4) { + fstep = 320 * 0x10000 / vid.width; + for (unsigned x = 0; x < vid.width; x += 4) { dest[x] = src[f >> 16]; f += fstep; dest[x + 1] = src[f >> 16]; @@ -660,7 +659,7 @@ Draw_ConsoleBackground (int lines, byte alpha) } } - Draw_AltString (vid.conview->xlen - strlen (cl_verstring) * 8 - 11, + Draw_AltString (vid.width - strlen (cl_verstring) * 8 - 11, lines - 14, cl_verstring); } @@ -767,8 +766,7 @@ Draw_Fill (int x, int y, int w, int h, int c) byte *dest; int u, v; - if (x < 0 || x + w > vid.conview->xlen - || y < 0 || y + h > vid.conview->ylen) { + if (x < 0 || x + w > (int) vid.width || y < 0 || y + h > (int) vid.height) { Sys_MaskPrintf (SYS_vid, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); } @@ -899,12 +897,12 @@ test_point (int x, int y) if (x < 0) { c |= 1; - } else if (x >= vid.conview->xlen) { + } else if (x >= (int) vid.width) { c |= 2; } if (y < 0) { c |= 4; - } else if (y >= vid.conview->ylen) { + } else if (y >= (int) vid.height) { c |= 8; } return c; @@ -915,8 +913,8 @@ Draw_Line (int x0, int y0, int x1, int y1, int c) { byte c0 = test_point (x0, y0); byte c1 = test_point (x1, y1); - int xmax = vid.conview->xlen - 1; - int ymax = vid.conview->ylen - 1; + int xmax = vid.width - 1; + int ymax = vid.height - 1; while (c0 | c1) { // Cohen-Sutherland line clipping @@ -944,8 +942,8 @@ void Draw_FadeScreen (void) { int x, y; - int height = vid.conview->ylen; - int width = vid.conview->xlen / 4; + int height = vid.height; + int width = vid.width / 4; uint32_t *pbuf; for (y = 0; y < height; y++) { diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index acb38d4d6..bdad0f499 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -346,8 +346,8 @@ vulkan_set_2d (int scaled) __auto_type mctx = vulkan_ctx->matrix_context; __auto_type mat = &mctx->matrices; - int width = vid.conview->xlen; //FIXME vid - int height = vid.conview->ylen; + int width = vid.width; //FIXME vid + int height = vid.height; QFV_Orthographic (mat->Projection2d, 0, width, 0, height, 0, 99999); mctx->dirty = mctx->frames.size; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 7a604860a..5a0fba012 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -593,10 +593,10 @@ Vulkan_Draw_Character (int x, int y, unsigned int chr, vulkan_ctx_t *ctx) if (chr == ' ') { return; } - if (y <= -8 || y >= vid.conview->ylen) { + if (y <= -8 || y >= (int) vid.height) { return; } - if (x <= -8 || x >= vid.conview->xlen) { + if (x <= -8 || x >= (int) vid.width) { return; } queue_character (x, y, chr, ctx); @@ -610,11 +610,11 @@ Vulkan_Draw_String (int x, int y, const char *str, vulkan_ctx_t *ctx) if (!str || !str[0]) { return; } - if (y <= -8 || y >= vid.conview->ylen) { + if (y <= -8 || y >= (int) vid.height) { return; } while (*str) { - if ((chr = *str++) != ' ' && x >= -8 && x < vid.conview->xlen) { + if ((chr = *str++) != ' ' && x >= -8 && x < (int) vid.width) { queue_character (x, y, chr, ctx); } x += 8; @@ -630,11 +630,11 @@ Vulkan_Draw_nString (int x, int y, const char *str, int count, if (!str || !str[0]) { return; } - if (y <= -8 || y >= vid.conview->ylen) { + if (y <= -8 || y >= (int) vid.height) { return; } while (count-- > 0 && *str) { - if ((chr = *str++) != ' ' && x >= -8 && x < vid.conview->xlen) { + if ((chr = *str++) != ' ' && x >= -8 && x < (int) vid.width) { queue_character (x, y, chr, ctx); } x += 8; @@ -649,12 +649,12 @@ Vulkan_Draw_AltString (int x, int y, const char *str, vulkan_ctx_t *ctx) if (!str || !str[0]) { return; } - if (y <= -8 || y >= vid.conview->ylen) { + if (y <= -8 || y >= (int) vid.height) { return; } while (*str) { if ((chr = *str++ | 0x80) != (' ' | 0x80) - && x >= -8 && x < vid.conview->xlen) { + && x >= -8 && x < (int) vid.width) { queue_character (x, y, chr, ctx); } x += 8; @@ -711,8 +711,8 @@ Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx) { int x, y; - x = vid.conview->xlen / 2 + cl_crossx; - y = vid.conview->ylen / 2 + cl_crossy; + x = vid.width / 2 + cl_crossx; + y = vid.height / 2 + cl_crossy; Vulkan_Draw_CrosshairAt (crosshair, x, y, ctx); } @@ -833,7 +833,7 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) int ofs = max (0, cpic->height - lines); lines = min (lines, cpic->height); subpic_t *subpic = *(subpic_t **) cpic->data; - draw_pic (0, 0, vid.conview->xlen, lines, subpic, + draw_pic (0, 0, vid.width, lines, subpic, 0, ofs, cpic->width, lines, color, &frame->quad_verts); } @@ -891,7 +891,7 @@ draw_blendscreen (quat_t color, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; - draw_pic (0, 0, vid.conview->xlen, vid.conview->ylen, subpic, + draw_pic (0, 0, vid.width, vid.height, subpic, 0, 0, 1, 1, color, &frame->quad_verts); } diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index fe2a62333..d6547250a 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -69,24 +69,6 @@ static cvar_t vid_system_gamma_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &vid_system_gamma }, }; -int con_width; -static cvar_t con_width_cvar = { - .name = "con_width", - .description = - "console effective width (GL only)", - .default_value = 0, - .flags = CVAR_ROM, - .value = { .type = &cexpr_int, .value = &con_width }, -}; -int con_height; -static cvar_t con_height_cvar = { - .name = "con_height", - .description = - "console effective height (GL only)", - .default_value = 0, - .flags = CVAR_ROM, - .value = { .type = &cexpr_int, .value = &con_height }, -}; qboolean vid_gamma_avail; // hardware gamma availability VISIBLE unsigned int d_8to24table[256]; @@ -121,12 +103,10 @@ static cvar_t vid_fullscreen_cvar = { .value = { .type = &cexpr_int, .value = &vid_fullscreen }, }; -static view_t conview; - void VID_GetWindowSize (int def_w, int def_h) { - int pnum, conheight; + int pnum; vid_width_cvar.default_value = nva ("%d", def_w); vid_height_cvar.default_value = nva ("%d", def_h); @@ -168,30 +148,21 @@ VID_GetWindowSize (int def_w, int def_h) viddef.width = vid_width; viddef.height = vid_height; - viddef.conview = &conview; +} - con_width_cvar.default_value = nva ("%d", vid_width); - Cvar_Register (&con_width_cvar, 0, 0); - if ((pnum = COM_CheckParm ("-conwidth"))) { - if (pnum >= com_argc - 1) - Sys_Error ("VID: -conwidth "); - con_width = atoi(com_argv[pnum + 1]); +void +VID_SetWindowSize (int width, int height) +{ + if (width < 0 || height < 0) { + Sys_Error ("VID_SetWindowSize: invalid size: %d, %d", width, height); } - con_width = max (con_width & ~7, 320); - // make con_width a multiple of 8 and >= 320 - viddef.conview->xlen = con_width; - - conheight = (viddef.conview->xlen * viddef.height) / viddef.width; - con_height_cvar.default_value = nva ("%d", conheight); - Cvar_Register (&con_height_cvar, 0, 0); - if ((pnum = COM_CheckParm ("-conheight"))) { - if (pnum >= com_argc - 1) - Sys_Error ("VID: -conheight "); - con_height = atoi (com_argv[pnum + 1]); + if (width != (int) viddef.width || height != (int) viddef.height) { + viddef.width = width; + viddef.height = height; + if (viddef.onVidResize) { + LISTENER_INVOKE (viddef.onVidResize, &viddef); + } } - // make con_height >= 200 - con_height = max (con_height & ~7, 200); - viddef.conview->ylen = con_height; } /* GAMMA FUNCTIONS */ diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 455d2b8e9..658a11ac2 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -682,11 +682,6 @@ x11_create_context (sw_ctx_t *ctx) x_shmeventtype = XShmGetEventBase (x_disp) + ShmCompletion; } - // FIXME this really shouldn't be here (ideally, scale console in sw) - // No console scaling in the sw renderer - viddef.conview->xlen = viddef.width; - viddef.conview->ylen = viddef.height; - viddef.vid_internal->init_buffers = x11_init_buffers; // XSynchronize (x_disp, False); // X11_AddEvent (x_shmeventtype, event_shm); diff --git a/nq/include/client.h b/nq/include/client.h index 33d0c0174..44391c545 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -287,6 +287,8 @@ extern qboolean recording; struct cvar_s; void Cvar_Info (void *data, const struct cvar_s *cvar); +extern struct view_s *cl_screen_view; +void CL_Init_Screen (void); void CL_UpdateScreen (double realtime); void CL_SetState (cactive_t state); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 39f3d06a1..225876f9c 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -723,6 +723,7 @@ CL_Init (cbuf_t *cbuf) PI_RegisterPlugins (client_plugin_list); Con_Init ("client"); + CL_Init_Screen (); CDAudio_Init (); diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index ea3a3ab50..ccaa2a31c 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -44,6 +44,7 @@ #include "QF/pcx.h" #include "QF/screen.h" +#include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" #include "QF/scene/scene.h" @@ -52,15 +53,49 @@ #include "sbar.h" +#include "r_local.h" //FIXME for r_cache_thrash + #include "client/world.h" #include "nq/include/client.h" +int scr_showpause; +static cvar_t scr_showpause_cvar = { + .name = "showpause", + .description = + "Toggles display of pause graphic", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_showpause }, +}; +int scr_showram; +static cvar_t scr_showram_cvar = { + .name = "showram", + .description = + "Show RAM icon if game is running low on memory", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_showram }, +}; +int scr_showturtle; +static cvar_t scr_showturtle_cvar = { + .name = "showturtle", + .description = + "Show a turtle icon if your fps is below 10", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_showturtle }, +}; + +view_t *cl_screen_view; static view_t *net_view; static view_t *timegraph_view; static view_t *zgraph_view; static view_t *loading_view; +static qpic_t *scr_ram; +static qpic_t *scr_turtle; + static void draw_pic (view_t *view) { @@ -90,6 +125,60 @@ SCR_CShift (void) r_funcs->Draw_BlendScreen (cl.viewstate.cshift_color); } +static void +SCR_DrawRam (void) +{ + if (!scr_showram) + return; + + if (!r_cache_thrash) + return; + + //FIXME view + r_funcs->Draw_Pic (cl_screen_view->xpos + 32, cl_screen_view->ypos, + scr_ram); +} + +static void +SCR_DrawTurtle (void) +{ + static int count; + + if (!scr_showturtle) + return; + + if (r_data->frametime < 0.1) { + count = 0; + return; + } + + count++; + if (count < 3) + return; + + //FIXME view + r_funcs->Draw_Pic (cl_screen_view->xpos, cl_screen_view->ypos, + scr_turtle); +} + +static void +SCR_DrawPause (void) +{ + qpic_t *pic; + + if (!scr_showpause) // turn off for screenshots + return; + + if (!r_data->paused) + return; + + //FIXME view conwidth + pic = r_funcs->Draw_CachePic ("gfx/pause.lmp", true); + r_funcs->Draw_Pic ((cl_screen_view->xlen - pic->width) / 2, + (cl_screen_view->ylen - 48 - pic->height) / 2, + pic); +} + static void scr_draw_views (void) { @@ -99,7 +188,7 @@ scr_draw_views (void) timegraph_view->visible = r_timegraph; zgraph_view->visible = r_zgraph; - view_draw (r_data->vid->conview); + view_draw (cl_screen_view); } static SCR_Func scr_funcs_normal[] = { @@ -133,6 +222,47 @@ static SCR_Func *scr_funcs[] = { scr_funcs_finale, }; +void +CL_Init_Screen (void) +{ + qpic_t *pic; + + cl_screen_view = r_data->scr_view; + con_module->data->console->screen_view = cl_screen_view; + + scr_ram = r_funcs->Draw_PicFromWad ("ram"); + scr_turtle = r_funcs->Draw_PicFromWad ("turtle"); + + Cvar_Register (&scr_showpause_cvar, 0, 0); + Cvar_Register (&scr_showram_cvar, 0, 0); + Cvar_Register (&scr_showturtle_cvar, 0, 0); + + pic = r_funcs->Draw_PicFromWad ("net"); + net_view = view_new (64, 0, pic->width, pic->height, grav_northwest); + net_view->draw = draw_pic; + net_view->data = pic; + net_view->visible = 0; + view_add (cl_screen_view, net_view); + + timegraph_view = view_new (0, 0, cl_screen_view->xlen, 100, grav_southwest); + timegraph_view->draw = R_TimeGraph; + timegraph_view->visible = 0; + view_add (cl_screen_view, timegraph_view); + + zgraph_view = view_new (0, 0, cl_screen_view->xlen, 100, grav_southwest); + zgraph_view->draw = R_ZGraph; + zgraph_view->visible = 0; + view_add (cl_screen_view, zgraph_view); + + const char *name = "gfx/loading.lmp"; + pic = r_funcs->Draw_CachePic (name, 1); + loading_view = view_new (0, -24, pic->width, pic->height, grav_center); + loading_view->draw = draw_cachepic; + loading_view->data = (void *) name; + loading_view->visible = 0; + view_add (cl_screen_view, loading_view); +} + void CL_UpdateScreen (double realtime) { @@ -141,41 +271,6 @@ CL_UpdateScreen (double realtime) if (index >= sizeof (scr_funcs) / sizeof (scr_funcs[0])) index = 0; - if (!net_view) { - qpic_t *pic = r_funcs->Draw_PicFromWad ("net"); - net_view = view_new (64, 0, pic->width, pic->height, grav_northwest); - net_view->draw = draw_pic; - net_view->data = pic; - net_view->visible = 0; - view_add (r_data->scr_view, net_view); - } - - if (!timegraph_view) { - view_t *parent = r_data->scr_view; - timegraph_view = view_new (0, 0, parent->xlen, 100, grav_southwest); - timegraph_view->draw = R_TimeGraph; - timegraph_view->visible = 0; - view_add (parent, timegraph_view); - } - - if (!zgraph_view) { - view_t *parent = r_data->scr_view; - zgraph_view = view_new (0, 0, parent->xlen, 100, grav_southwest); - zgraph_view->draw = R_ZGraph; - zgraph_view->visible = 0; - view_add (parent, zgraph_view); - } - - if (!loading_view) { - const char *name = "gfx/loading.lmp"; - qpic_t *pic = r_funcs->Draw_CachePic (name, 1); - loading_view = view_new (0, -24, pic->width, pic->height, grav_center); - loading_view->draw = draw_cachepic; - loading_view->data = (void *) name; - loading_view->visible = 0; - view_add (r_data->vid->conview, loading_view); - } - //FIXME not every time if (cls.state == ca_active) { if (cl.watervis) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 8287adf13..fa46defa6 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -354,7 +354,7 @@ draw_weapons_hud (view_t *view) if (view->parent->gravity == grav_southeast) x = view->xlen - 24; - for (i = r_data->vid->conview->ylen < 204; i < 7; i++) { + for (i = cl_screen_view->ylen < 204; i < 7; i++) { if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); draw_subpic (view, x, i * 16, sb_weapons[flashon][i], 0, 0, 24, 16); @@ -711,7 +711,7 @@ draw_rogue_weapons_hud (view_t *view) int flashon, i, j; qpic_t *pic; - for (i = r_data->vid->conview->ylen < 204; i < 7; i++) { + for (i = cl_screen_view->ylen < 204; i < 7; i++) { if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); if (i >= 2) { @@ -982,7 +982,7 @@ sbar_update_vis (void) return; if (con_module && - con_module->data->console->lines == r_data->vid->conview->ylen) + con_module->data->console->lines == cl_screen_view->ylen) return; // console is full screen if (cls.state == ca_active @@ -1420,8 +1420,8 @@ init_sbar_views (void) view->draw = draw_status; view_add (sbar_view, view); - if (r_data->vid->conview->xlen > 320) { - int l = (r_data->vid->conview->xlen - 320) / 2; + if (cl_screen_view->xlen > 320) { + int l = (cl_screen_view->xlen - 320) / 2; view = view_new (-l, 0, l, 48, grav_southwest); view->draw = draw_tile; @@ -1442,12 +1442,12 @@ init_hud_views (void) view_t *minifrags_view = 0; view_t *miniteam_view = 0; - if (r_data->vid->conview->xlen < 512) { + if (cl_screen_view->xlen < 512) { hud_view = view_new (0, 0, 320, 48, grav_south); hud_frags_view = view_new (0, 0, 130, 8, grav_northeast); hud_frags_view->draw = draw_frags; - } else if (r_data->vid->conview->xlen < 640) { + } else if (cl_screen_view->xlen < 640) { hud_view = view_new (0, 0, 512, 48, grav_south); minifrags_view = view_new (320, 0, 192, 48, grav_southwest); @@ -1499,7 +1499,7 @@ init_hud_views (void) if (miniteam_view) view_add (hud_view, miniteam_view); - view = view_new (0, 0, r_data->vid->conview->xlen, 48, grav_south); + view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); view_add (view, hud_view); hud_view = view; @@ -1550,8 +1550,8 @@ init_hipnotic_sbar_views (void) view->draw = draw_hipnotic_status; view_add (sbar_view, view); - if (r_data->vid->conview->xlen > 320) { - int l = (r_data->vid->conview->xlen - 320) / 2; + if (cl_screen_view->xlen > 320) { + int l = (cl_screen_view->xlen - 320) / 2; view = view_new (-l, 0, l, 48, grav_southwest); view->draw = draw_tile; @@ -1576,10 +1576,8 @@ init_hipnotic_hud_views (void) hud_view->resize_y = 1; - if (r_data->vid->conview->ylen < 252) { - hud_armament_view = view_new (0, - min (r_data->vid->conview->ylen - 160, - 48), + if (cl_screen_view->ylen < 252) { + hud_armament_view = view_new (0, min (cl_screen_view->ylen - 160, 48), 66, 160, grav_southeast); } else { hud_armament_view = view_new (0, 48, 42, 204, grav_southeast); @@ -1611,7 +1609,7 @@ init_hipnotic_hud_views (void) if (hud_frags_view) view_add (hud_inventory_view, hud_frags_view); - view = view_new (0, 0, r_data->vid->conview->xlen, 48, grav_south); + view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); view_add (view, hud_view); hud_view = view; @@ -1658,8 +1656,8 @@ init_rogue_sbar_views (void) view->draw = draw_rogue_status; view_add (sbar_view, view); - if (r_data->vid->conview->xlen > 320) { - int l = (r_data->vid->conview->xlen - 320) / 2; + if (cl_screen_view->xlen > 320) { + int l = (cl_screen_view->xlen - 320) / 2; view = view_new (-l, 0, l, 48, grav_southwest); view->draw = draw_tile; @@ -1708,7 +1706,7 @@ init_rogue_hud_views (void) if (hud_frags_view) view_add (hud_inventory_view, hud_frags_view); - view = view_new (0, 0, r_data->vid->conview->xlen, 48, grav_south); + view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); view_add (view, hud_view); hud_view = view; @@ -1720,19 +1718,17 @@ init_rogue_hud_views (void) static void init_views (void) { - hud_main_view = view_new (0, 0, r_data->vid->conview->xlen, - r_data->vid->conview->ylen, - grav_northwest); - if (con_module) - view_insert (con_module->data->console->view, hud_main_view, 0); + hud_main_view = view_new (0, 0, cl_screen_view->xlen, cl_screen_view->ylen, + grav_northwest); + view_insert (cl_screen_view, hud_main_view, 0); hud_main_view->resize_x = 1; // get resized if the 2d view resizes hud_main_view->resize_y = 1; hud_main_view->visible = 0; // but don't let the console draw our stuff - if (r_data->vid->conview->ylen > 300) + if (cl_screen_view->ylen > 300) hud_overlay_view = view_new (0, 0, 320, 300, grav_center); else - hud_overlay_view = view_new (0, 0, 320, r_data->vid->conview->ylen, - grav_center); + hud_overlay_view = view_new (0, 0, 320, cl_screen_view->ylen, + grav_center); hud_overlay_view->draw = draw_overlay; hud_overlay_view->visible = 0; diff --git a/qw/include/client.h b/qw/include/client.h index 7951338cb..bac651e15 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -301,6 +301,8 @@ extern struct view_s *cl_netgraph_view; void CL_NetGraph (struct view_s *view); void CL_NetGraph_Init_Cvars (void); +extern struct view_s *cl_screen_view; +void CL_Init_Screen (void); void CL_UpdateScreen (double realtime); void CL_SetState (cactive_t state); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index cf72e69cd..cc3bf4c82 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1500,6 +1500,7 @@ CL_Init (void) PI_RegisterPlugins (client_plugin_list); Con_Init ("client"); + CL_Init_Screen (); if (con_module) { con_module->data->console->dl_name = cls.downloadname; con_module->data->console->dl_percent = &cls.downloadpercent; diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index bbab72313..d8084ef8f 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -44,12 +44,16 @@ #include "QF/pcx.h" #include "QF/screen.h" +#include "QF/plugin/console.h" + #include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "QF/ui/view.h" #include "sbar.h" +#include "r_local.h" //FIXME for r_cache_thrash + #include "client/hud.h" #include "client/view.h" #include "client/world.h" @@ -57,9 +61,41 @@ #include "qw/include/client.h" #include "qw/include/cl_parse.h" +int scr_showpause; +static cvar_t scr_showpause_cvar = { + .name = "showpause", + .description = + "Toggles display of pause graphic", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_showpause }, +}; +int scr_showram; +static cvar_t scr_showram_cvar = { + .name = "showram", + .description = + "Show RAM icon if game is running low on memory", + .default_value = "1", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_showram }, +}; +int scr_showturtle; +static cvar_t scr_showturtle_cvar = { + .name = "showturtle", + .description = + "Show a turtle icon if your fps is below 10", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &scr_showturtle }, +}; + +view_t *cl_screen_view; static view_t *net_view; static view_t *loading_view; +static qpic_t *scr_ram; +static qpic_t *scr_turtle; + static void draw_pic (view_t *view) { @@ -89,6 +125,60 @@ SCR_CShift (void) r_funcs->Draw_BlendScreen (cl.viewstate.cshift_color); } +static void +SCR_DrawRam (void) +{ + if (!scr_showram) + return; + + if (!r_cache_thrash) + return; + + //FIXME view + r_funcs->Draw_Pic (cl_screen_view->xpos + 32, cl_screen_view->ypos, + scr_ram); +} + +static void +SCR_DrawTurtle (void) +{ + static int count; + + if (!scr_showturtle) + return; + + if (r_data->frametime < 0.1) { + count = 0; + return; + } + + count++; + if (count < 3) + return; + + //FIXME view + r_funcs->Draw_Pic (cl_screen_view->xpos, cl_screen_view->ypos, + scr_turtle); +} + +static void +SCR_DrawPause (void) +{ + qpic_t *pic; + + if (!scr_showpause) // turn off for screenshots + return; + + if (!r_data->paused) + return; + + //FIXME view conwidth + pic = r_funcs->Draw_CachePic ("gfx/pause.lmp", true); + r_funcs->Draw_Pic ((cl_screen_view->xlen - pic->width) / 2, + (cl_screen_view->ylen - 48 - pic->height) / 2, + pic); +} + static void scr_draw_views (void) { @@ -104,7 +194,7 @@ scr_draw_views (void) view_setgravity (cl_netgraph_view, hud_swap ? grav_southeast : grav_southwest); - view_draw (r_data->vid->conview); + view_draw (cl_screen_view); } static SCR_Func scr_funcs_normal[] = { @@ -140,6 +230,45 @@ static SCR_Func *scr_funcs[] = { scr_funcs_finale, }; +void +CL_Init_Screen (void) +{ + qpic_t *pic; + + cl_screen_view = r_data->scr_view; + con_module->data->console->screen_view = cl_screen_view; + + scr_ram = r_funcs->Draw_PicFromWad ("ram"); + scr_turtle = r_funcs->Draw_PicFromWad ("turtle"); + + Cvar_Register (&scr_showpause_cvar, 0, 0); + Cvar_Register (&scr_showram_cvar, 0, 0); + Cvar_Register (&scr_showturtle_cvar, 0, 0); + + pic = r_funcs->Draw_PicFromWad ("net"); + net_view = view_new (64, 0, pic->width, pic->height, grav_northwest); + net_view->draw = draw_pic; + net_view->data = pic; + net_view->visible = 0; + view_add (cl_screen_view, net_view); + + const char *name = "gfx/loading.lmp"; + pic = r_funcs->Draw_CachePic (name, 1); + loading_view = view_new (0, -24, pic->width, pic->height, grav_center); + loading_view->draw = draw_cachepic; + loading_view->data = (void *) name; + loading_view->visible = 0; + view_add (cl_screen_view, loading_view); + + cl_netgraph_view = view_new (0, hud_sb_lines, + NET_TIMINGS + 16, + cl_netgraph_height + 25, + grav_southwest); + cl_netgraph_view->draw = CL_NetGraph; + cl_netgraph_view->visible = 0; + view_add (cl_screen_view, cl_netgraph_view); +} + void CL_UpdateScreen (double realtime) { @@ -148,35 +277,6 @@ CL_UpdateScreen (double realtime) if (index >= sizeof (scr_funcs) / sizeof (scr_funcs[0])) index = 0; - if (!net_view) { - qpic_t *pic = r_funcs->Draw_PicFromWad ("net"); - net_view = view_new (64, 0, pic->width, pic->height, grav_northwest); - net_view->draw = draw_pic; - net_view->data = pic; - net_view->visible = 0; - view_add (r_data->scr_view, net_view); - } - - if (!loading_view) { - const char *name = "gfx/loading.lmp"; - qpic_t *pic = r_funcs->Draw_CachePic (name, 1); - loading_view = view_new (0, -24, pic->width, pic->height, grav_center); - loading_view->draw = draw_cachepic; - loading_view->data = (void *) name; - loading_view->visible = 0; - view_add (r_data->vid->conview, loading_view); - } - - if (!cl_netgraph_view) { - cl_netgraph_view = view_new (0, hud_sb_lines, - NET_TIMINGS + 16, - cl_netgraph_height + 25, - grav_southwest); - cl_netgraph_view->draw = CL_NetGraph; - cl_netgraph_view->visible = 0; - view_add (r_data->vid->conview, cl_netgraph_view); - } - //FIXME not every time if (cls.state == ca_active) { if (cl.watervis) diff --git a/qw/source/sbar.c b/qw/source/sbar.c index d016aeb11..e58113595 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -390,7 +390,7 @@ draw_weapons_hud (view_t *view) if (view->parent->gravity == grav_southeast) x = view->xlen - 24; - for (i = r_data->vid->conview->ylen < 204; i < 7; i++) { + for (i = cl_screen_view->ylen < 204; i < 7; i++) { if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); draw_subpic (view, x, i * 16, sb_weapons[flashon][i], 0, 0, 24, 16); @@ -857,7 +857,7 @@ Sbar_DeathmatchOverlay (view_t *view, int start) int l, y; int skip = 10; - if (r_data->vid->conview->xlen < 244) // FIXME: magic number, gained through experimentation + if (cl_screen_view->xlen < 244) // FIXME: magic number, gained through experimentation return; if (largegame) @@ -1009,8 +1009,7 @@ sbar_update_vis (void) if ((sb_updates >= r_data->vid->numpages) && !headsup) return; - if (con_module - && con_module->data->console->lines == r_data->vid->conview->ylen) + if (con_module && con_module->data->console->lines == cl_screen_view->ylen) return; // console is full screen if (!hud_sb_lines) @@ -1698,12 +1697,12 @@ init_sbar_views (void) view_t *minifrags_view = 0; view_t *miniteam_view = 0; - if (r_data->vid->conview->xlen < 512) { + if (cl_screen_view->xlen < 512) { sbar_view = view_new (0, 0, 320, 48, grav_south); sbar_frags_view = view_new (0, 0, 130, 8, grav_northeast); sbar_frags_view->draw = draw_frags; - } else if (r_data->vid->conview->xlen < 640) { + } else if (cl_screen_view->xlen < 640) { sbar_view = view_new (0, 0, 512, 48, grav_south); minifrags_view = view_new (320, 0, 192, 48, grav_southwest); minifrags_view->draw = draw_minifrags; @@ -1765,8 +1764,8 @@ init_sbar_views (void) if (miniteam_view) view_add (sbar_view, miniteam_view); - if (r_data->vid->conview->xlen > 640) { - int l = (r_data->vid->conview->xlen - 640) / 2; + if (cl_screen_view->xlen > 640) { + int l = (cl_screen_view->xlen - 640) / 2; view = view_new (-l, 0, l, 48, grav_southwest); view->draw = draw_tile; @@ -1787,12 +1786,12 @@ init_hud_views (void) view_t *minifrags_view = 0; view_t *miniteam_view = 0; - if (r_data->vid->conview->xlen < 512) { + if (cl_screen_view->xlen < 512) { hud_view = view_new (0, 0, 320, 48, grav_south); hud_frags_view = view_new (0, 0, 130, 8, grav_northeast); hud_frags_view->draw = draw_frags; - } else if (r_data->vid->conview->xlen < 640) { + } else if (cl_screen_view->xlen < 640) { hud_view = view_new (0, 0, 512, 48, grav_south); minifrags_view = view_new (320, 0, 192, 48, grav_southwest); @@ -1844,7 +1843,7 @@ init_hud_views (void) if (miniteam_view) view_add (hud_view, miniteam_view); - view = view_new (0, 0, r_data->vid->conview->xlen, 48, grav_south); + view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); view_add (view, hud_view); hud_view = view; @@ -1856,19 +1855,17 @@ init_hud_views (void) static void init_views (void) { - hud_main_view = view_new (0, 0, r_data->vid->conview->xlen, - r_data->vid->conview->ylen, - grav_northwest); - if (con_module) - view_insert (con_module->data->console->view, hud_main_view, 0); + hud_main_view = view_new (0, 0, cl_screen_view->xlen, cl_screen_view->ylen, + grav_northwest); + view_insert (cl_screen_view, hud_main_view, 0); hud_main_view->resize_x = 1; // get resized if the 2d view resizes hud_main_view->resize_y = 1; hud_main_view->visible = 0; // but don't let the console draw our stuff - if (r_data->vid->conview->ylen > 300) + if (cl_screen_view->ylen > 300) hud_overlay_view = view_new (0, 0, 320, 300, grav_center); else - hud_overlay_view = view_new (0, 0, 320, r_data->vid->conview->ylen, - grav_center); + hud_overlay_view = view_new (0, 0, 320, cl_screen_view->ylen, + grav_center); hud_overlay_view->draw = draw_overlay; hud_overlay_view->visible = 0; From fdfdf9056a6aabbd6d949124b434e3935d056b66 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Sep 2022 23:47:14 +0900 Subject: [PATCH 2993/3664] [renderer] Add function to destroy frame buffers Needed for window resizing for fisheye and warp buffers (main buffers will be taken care of by the drivers). --- include/QF/GL/qf_funcs_list.h | 2 +- include/QF/plugin/vid_render.h | 1 + libs/video/renderer/vid_render_gl.c | 13 +++++++++++++ libs/video/renderer/vid_render_glsl.c | 13 +++++++++++++ libs/video/renderer/vid_render_sw.c | 7 +++++++ libs/video/renderer/vid_render_vulkan.c | 6 ++++++ 6 files changed, 41 insertions(+), 1 deletion(-) diff --git a/include/QF/GL/qf_funcs_list.h b/include/QF/GL/qf_funcs_list.h index 3550c6f26..d30b5c873 100644 --- a/include/QF/GL/qf_funcs_list.h +++ b/include/QF/GL/qf_funcs_list.h @@ -422,7 +422,7 @@ QFGL_WANT (void, glPNTrianglesiATI, (GLint x, GLint y)) // frame buffers QFGL_DONT_NEED (GLboolean, glIsFramebuffer, (GLuint framebuffer)) QFGL_NEED (void, glBindFramebuffer, (GLenum target, GLuint framebuffer)) -QFGL_DONT_NEED (void, glDeleteFramebuffers, (GLsizei n, const GLuint *framebuffers)) +QFGL_NEED (void, glDeleteFramebuffers, (GLsizei n, const GLuint *framebuffers)) QFGL_NEED (void, glGenFramebuffers, (GLsizei n, GLuint *framebuffers)) QFGL_DONT_NEED (GLenum, glCheckFramebufferStatus, (GLenum target)) QFGL_DONT_NEED (void, glFramebufferTexture1D, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index b8b0bbda0..59482fa69 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -129,6 +129,7 @@ typedef struct vid_render_funcs_s { struct framebuffer_s *(*create_cube_map) (int side); struct framebuffer_s *(*create_frame_buffer) (int width, int height); + void (*destroy_frame_buffer) (struct framebuffer_s *framebuffer); void (*bind_framebuffer) (struct framebuffer_s *framebuffer); void (*set_viewport) (const struct vrect_s *view); // x and y are tan(f/2) for fov_x and fov_y diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index dac319acf..9fe8cafed 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -406,6 +406,18 @@ gl_create_frame_buffer (int width, int height) return fb; } +static void +gl_destroy_frame_buffer (framebuffer_t *framebuffer) +{ + __auto_type fb = (gl_framebuffer_t *) framebuffer->buffer; + + qfglDeleteFramebuffers (1, &fb->handle); + + GLuint tex[2] = { fb->color, fb->depth }; + qfglDeleteTextures (2, tex); + free (framebuffer); +} + static void gl_bind_framebuffer (framebuffer_t *framebuffer) { @@ -528,6 +540,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_create_cube_map, gl_create_frame_buffer, + gl_destroy_frame_buffer, gl_bind_framebuffer, gl_set_viewport, gl_set_fov, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 02242755c..6f9747fb9 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -353,6 +353,18 @@ glsl_create_frame_buffer (int width, int height) return fb; } +static void +glsl_destroy_frame_buffer (framebuffer_t *framebuffer) +{ + __auto_type fb = (gl_framebuffer_t *) framebuffer->buffer; + + qfeglDeleteFramebuffers (1, &fb->handle); + + GLuint tex[2] = { fb->color, fb->depth }; + qfeglDeleteTextures (2, tex); + free (framebuffer); +} + static void glsl_bind_framebuffer (framebuffer_t *framebuffer) { @@ -472,6 +484,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_create_cube_map, glsl_create_frame_buffer, + glsl_destroy_frame_buffer, glsl_bind_framebuffer, glsl_set_viewport, glsl_set_fov, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 060c9ac0a..2a6fb60c4 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -262,6 +262,12 @@ sw_create_frame_buffer (int width, int height) return fb; } +static void +sw_destroy_frame_buffer (framebuffer_t *framebuffer) +{ + free (framebuffer); +} + static void sw_set_viewport (const vrect_t *view); static void @@ -492,6 +498,7 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_create_cube_map, sw_create_frame_buffer, + sw_destroy_frame_buffer, sw_bind_framebuffer, sw_set_viewport, sw_set_fov, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index bdad0f499..f20f7cff2 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -476,6 +476,11 @@ vulkan_create_frame_buffer (int width, int height) return 0; } +static void +vulkan_destroy_frame_buffer (framebuffer_t *framebuffer) +{ +} + static void vulkan_bind_framebuffer (framebuffer_t *framebuffer) { @@ -788,6 +793,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_create_cube_map, vulkan_create_frame_buffer, + vulkan_destroy_frame_buffer, vulkan_bind_framebuffer, vulkan_set_viewport, vulkan_set_fov, From d14945724114e9d9dcf602276061ae5454337c3c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 01:05:55 +0900 Subject: [PATCH 2994/3664] [vid] Add a listener for window size changes A listener is used instead of (really, as well as) ie_app_window events because systems that need to know about windows sizes may not have anything to do with input and the event system. --- include/QF/vid.h | 3 +++ include/vid_internal.h | 1 + libs/video/targets/vid.c | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/include/QF/vid.h b/include/QF/vid.h index 6b03b3c9b..6987ebfc8 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -52,6 +52,7 @@ typedef struct { struct vid_internal_s *vid_internal; struct viddef_listener_set_s *onPaletteChanged; + struct viddef_listener_set_s *onVidResize; } viddef_t; typedef struct viddef_listener_set_s LISTENER_SET_TYPE (viddef_t) @@ -76,5 +77,7 @@ void VID_ClearMemory (void); void VID_OnPaletteChange_AddListener (viddef_listener_t listener, void *data); void VID_OnPaletteChange_RemoveListener (viddef_listener_t listener, void *data); +void VID_OnVidResize_AddListener (viddef_listener_t listener, void *data); +void VID_OnVidResize_RemoveListener (viddef_listener_t listener, void *data); #endif//__QF_vid_h diff --git a/include/vid_internal.h b/include/vid_internal.h index f413d4d66..e79fa9a9b 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -33,6 +33,7 @@ extern int vid_system_gamma; extern float vid_gamma; void VID_GetWindowSize (int def_w, int def_h); +void VID_SetWindowSize (int width, int height); void VID_InitGamma (const byte *); qboolean VID_SetGamma (double); diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index d6547250a..51c235440 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -291,6 +291,24 @@ VID_OnPaletteChange_RemoveListener (viddef_listener_t listener, void *data) } } +VISIBLE void +VID_OnVidResize_AddListener (viddef_listener_t listener, void *data) +{ + if (!viddef.onVidResize) { + viddef.onVidResize = malloc (sizeof (*viddef.onVidResize)); + LISTENER_SET_INIT (viddef.onVidResize, 8); + } + LISTENER_ADD (viddef.onVidResize, listener, data); +} + +VISIBLE void +VID_OnVidResize_RemoveListener (viddef_listener_t listener, void *data) +{ + if (viddef.onVidResize) { + LISTENER_REMOVE (viddef.onVidResize, listener, data); + } +} + VISIBLE void VID_Init (byte *palette, byte *colormap) { From ef8b267826db8296fb6f0540906a5b701d90f4d2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 01:09:27 +0900 Subject: [PATCH 2995/3664] [x11] Allow the window to be resized There's no maximum size, but the minimum size is currently 32x20. --- libs/video/targets/context_x11.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 468d29da7..93fac7372 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -188,6 +188,7 @@ configure_notify (XEvent *event) }, }; IE_Send_Event (&ie_event); + VID_SetWindowSize (c->width, c->height); } qboolean @@ -519,7 +520,6 @@ X11_CreateWindow (int width, int height) unsigned long mask; XSetWindowAttributes attr; XClassHint *ClassHint; - XSizeHints *SizeHints; X11_AddEvent (ConfigureNotify, configure_notify); @@ -540,17 +540,13 @@ X11_CreateWindow (int width, int height) IN_X11_Postinit (); // Set window size hints - SizeHints = XAllocSizeHints (); - if (SizeHints) { - SizeHints->flags = (PMinSize | PMaxSize); - SizeHints->min_width = width; - SizeHints->min_height = height; - SizeHints->max_width = width; - SizeHints->max_height = height; - XSetWMNormalHints (x_disp, x_win, SizeHints); + XSizeHints SizeHints = { + .flags = PMinSize, + .min_width = 32, + .min_height = 20, + }; + XSetWMNormalHints (x_disp, x_win, &SizeHints); - XFree (SizeHints); - } // Set window title X11_SetCaption (va (0, "%s", PACKAGE_STRING)); From f758f5fb701dd57fa67c139686f0d8f0aab470ae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 01:11:56 +0900 Subject: [PATCH 2996/3664] [renderer] Respond to window size changes Currently, only gl, glsl and sw are working, vulkan needs its swapchain to be rebuilt, and there are minor issues with the hud and console resizing. --- libs/video/renderer/r_screen.c | 17 +++++++++++++++++ libs/video/renderer/sw/d_init.c | 28 ++++++++++++++++++---------- libs/video/targets/vid_x11_sw.c | 6 ++++++ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 4106220f8..541cb3abb 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -183,6 +183,7 @@ SCR_CalcRefdef (void) // force a background redraw r_data->scr_fullupdate = 0; + r_funcs->bind_framebuffer (0); } static void @@ -435,6 +436,21 @@ viewsize_listener (void *data, const cvar_t *cvar) update_vrect (); } +static void +vidsize_listener (void *data, const viddef_t *vdef) +{ + update_vrect (); + if (fisheye_cube_map) { + r_funcs->destroy_frame_buffer (fisheye_cube_map); + fisheye_cube_map = 0; + } + if (warp_buffer) { + r_funcs->destroy_frame_buffer (warp_buffer); + warp_buffer = 0; + } + r_funcs->set_fov (tan_fov_x, tan_fov_y); +} + void SCR_Init (void) { @@ -453,6 +469,7 @@ SCR_Init (void) cvar_t *var = Cvar_FindVar ("viewsize"); Cvar_AddListener (var, viewsize_listener, 0); + VID_OnVidResize_AddListener (vidsize_listener, 0); update_vrect (); } diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index e5daaf439..b7e475ac1 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -49,6 +49,22 @@ static byte *surfcache; void (*d_drawspans) (espan_t *pspan); +static void +d_vidsize_listener (void *data, const viddef_t *vid) +{ + int cachesize = D_SurfaceCacheForRes (vid->width, vid->height); + + if (surfcache) { + D_FlushCaches (vid->vid_internal->data); + free (surfcache); + surfcache = 0; + } + surfcache = calloc (cachesize, 1); + vid->vid_internal->init_buffers (vid->vid_internal->data); + D_InitCaches (surfcache, cachesize); + + viddef.recalc_refdef = 1; +} void D_Init (void) @@ -61,16 +77,8 @@ D_Init (void) vid->vid_internal->flush_caches = D_FlushCaches; - int cachesize = D_SurfaceCacheForRes (vid->width, vid->height); - - if (surfcache) { - D_FlushCaches (vid->vid_internal->data); - free (surfcache); - surfcache = 0; - } - surfcache = calloc (cachesize, 1); - vid->vid_internal->init_buffers (vid->vid_internal->data); - D_InitCaches (surfcache, cachesize); + VID_OnVidResize_AddListener (d_vidsize_listener, 0); + d_vidsize_listener (0, vr_data.vid); } void diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 658a11ac2..3d5ef4526 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -640,13 +640,19 @@ x11_init_buffers (void *data) if (x_visinfo->depth != 8) { if (swfb.color) free (swfb.color); + if (swfb.depth) + free (swfb.depth); swfb.rowbytes = viddef.width; swfb.color = calloc (swfb.rowbytes, viddef.height); + swfb.depth = 0; if (!swfb.color) Sys_Error ("Not enough memory for video mode"); } else { swfb.rowbytes = x_framebuffer[current_framebuffer]->bytes_per_line; swfb.color = (byte *) x_framebuffer[current_framebuffer]->data; + if (swfb.depth) + free (swfb.depth); + swfb.depth = 0; } } From 918d648053e37f8523490601eef4680ac561b21e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 01:40:30 +0900 Subject: [PATCH 2997/3664] [client] Fix sbar hud resizing with window size hud_view has an extra layer that hid its missing resize_x --- nq/source/sbar.c | 3 +++ qw/source/sbar.c | 1 + 2 files changed, 4 insertions(+) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index fa46defa6..15b0351b3 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1500,6 +1500,7 @@ init_hud_views (void) view_add (hud_view, miniteam_view); view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); + view->resize_x = 1; view_add (view, hud_view); hud_view = view; @@ -1610,6 +1611,7 @@ init_hipnotic_hud_views (void) view_add (hud_inventory_view, hud_frags_view); view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); + view->resize_x = 1; view_add (view, hud_view); hud_view = view; @@ -1707,6 +1709,7 @@ init_rogue_hud_views (void) view_add (hud_inventory_view, hud_frags_view); view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); + view->resize_x = 1; view_add (view, hud_view); hud_view = view; diff --git a/qw/source/sbar.c b/qw/source/sbar.c index e58113595..e73c6629a 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -1844,6 +1844,7 @@ init_hud_views (void) view_add (hud_view, miniteam_view); view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); + view->resize_x = 1; view_add (view, hud_view); hud_view = view; From 3a03cc9fdaedbe8534ce542b5ef2114c7c4335ae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 01:49:18 +0900 Subject: [PATCH 2998/3664] [sw] Use vid instead of dev for a debug print --- libs/video/renderer/sw/d_surf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index f16122d79..26ee3c5bb 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -99,7 +99,7 @@ D_ClearCacheGuard (void) void D_InitCaches (void *buffer, int size) { - Sys_MaskPrintf (SYS_dev, "D_InitCaches: %ik surface cache\n", size/1024); + Sys_MaskPrintf (SYS_vid, "D_InitCaches: %ik surface cache\n", size/1024); sc_size = size - GUARDSIZE; sc_base = (surfcache_t *) buffer; From a936336e840036c37e3ed858b6d919dc2eb97881 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 May 2022 08:07:50 +0900 Subject: [PATCH 2999/3664] [model] Support the transparent texture marker Textures whose names start with a { are meant to be rendered with transparency. Surfaces using those textures are marked with SURF_DRAWALPHA. Unfortunately, the mip levels of ad_tears' transparent textures use the wrong color so only the highest LOD works properly, but those textures are meant to be loaded from external files anyway, it seems. --- include/QF/model.h | 10 +++++----- libs/models/brush/model_brush.c | 30 +++++++++++++++++------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/include/QF/model.h b/include/QF/model.h index d8bff2340..cea1e99ee 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -103,13 +103,13 @@ typedef struct texture_s { } texture_t; -#define SURF_PLANEBACK 0x02 -#define SURF_DRAWSKY 0x04 -#define SURF_DRAWTURB 0x08 +#define SURF_DRAWSKY 0x01 +#define SURF_DRAWALPHA 0x02 +#define SURF_DRAWTURB 0x04 +#define SURF_PLANEBACK 0x08 #define SURF_DRAWTILED 0x10 #define SURF_DRAWBACKGROUND 0x20 -#define SURF_DRAWNOALPHA 0x40 -#define SURF_LIGHTBOTHSIDES 0x80 +#define SURF_LIGHTBOTHSIDES 0x40 // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index 2c5ad0243..b7f8d4fff 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -652,19 +652,23 @@ Mod_LoadFaces (model_t *mod, bsp_t *bsp) continue; } - if (out->texinfo->texture->name[0] == '*') { // turbulent - out->flags |= (SURF_DRAWTURB - | SURF_DRAWTILED - | SURF_LIGHTBOTHSIDES); - for (i = 0; i < 2; i++) { - out->extents[i] = 16384; - out->texturemins[i] = -8192; - } - if (mod_funcs && mod_funcs->Mod_SubdivideSurface) { - // cut up polygon for warps - mod_funcs->Mod_SubdivideSurface (mod, out); - } - continue; + switch (out->texinfo->texture->name[0]) { + case '*': // turbulent + out->flags |= (SURF_DRAWTURB + | SURF_DRAWTILED + | SURF_LIGHTBOTHSIDES); + for (i = 0; i < 2; i++) { + out->extents[i] = 16384; + out->texturemins[i] = -8192; + } + if (mod_funcs && mod_funcs->Mod_SubdivideSurface) { + // cut up polygon for warps + mod_funcs->Mod_SubdivideSurface (mod, out); + } + break; + case '{': + out->flags |= SURF_DRAWALPHA; + break; } } } From 3603f90718ca7be7788f73bb694645efc3231deb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 May 2022 08:12:21 +0900 Subject: [PATCH 3000/3664] [vulkan] Implement BSP surface transparency Surfaces marked with SURF_DRAWALPHA but not SURF_DRAWTURB are put in a separate queue for the water shader and run with a turb scale of 0. Also, entities with colormod alpha < 1 are marked to go in the same queue as SURF_DRAWALPHA surfaces (ie, no SURF_DRAWTURB unless the model's texture indicated such). --- include/QF/Vulkan/qf_bsp.h | 1 + libs/video/renderer/vulkan/qfpipeline.plist | 2 +- .../renderer/vulkan/shader/bsp_gbuf.frag | 3 +- .../renderer/vulkan/shader/bsp_gbuf.geom | 3 ++ .../renderer/vulkan/shader/bsp_gbuf.vert | 2 + .../video/renderer/vulkan/shader/bsp_sky.frag | 2 + .../renderer/vulkan/shader/bsp_turb.frag | 9 ++-- .../renderer/vulkan/shader/quakebsp.vert | 2 + libs/video/renderer/vulkan/vulkan_bsp.c | 43 ++++++++++++++----- 9 files changed, 51 insertions(+), 16 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 376eaa181..a6d2b379a 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -110,6 +110,7 @@ typedef struct bsp_draw_s { typedef struct bsp_drawset_s DARRAY_TYPE (bsp_draw_t) bsp_drawset_t; +#define INST_ALPHA (1u<<31) typedef struct instface_s { uint32_t inst_id; uint32_t face; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 9c16a5556..4e4f59e9e 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -365,7 +365,7 @@ { stageFlags = fragment; offset = 0; - size = "4 * 4 + 4 + 4"; + size = "4 * 4 + 4 + 4 + 4"; }, ); }; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index f807f52a2..0c1df1795 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -12,6 +12,7 @@ layout (location = 0) in vec4 tl_st; layout (location = 1) in vec3 direction; layout (location = 2) in vec3 normal; layout (location = 3) in vec4 position; +layout (location = 4) in vec4 color; layout (location = 0) out vec4 frag_color; layout (location = 1) out vec4 frag_emission; @@ -37,7 +38,7 @@ main (void) vec3 e_st = vec3 (tl_st.xy, 1); vec2 l_st = vec2 (tl_st.zw); - c = texture (Texture, t_st); + c = texture (Texture, t_st) * color; e = texture (Texture, e_st); frag_color = c;//fogBlend (c); frag_emission = e; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom index 44f17a3b1..15cb5a537 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom @@ -11,11 +11,13 @@ layout (triangles) in; layout (triangle_strip, max_vertices = 3) out; layout (location = 0) in vec4 v_tl_st[]; layout (location = 1) in vec3 v_direction[]; +layout (location = 2) in vec4 v_color[]; layout (location = 0) out vec4 tl_st; layout (location = 1) out vec3 direction; layout (location = 2) out vec3 normal; layout (location = 3) out vec4 position; +layout (location = 4) out vec4 color; void main() @@ -31,6 +33,7 @@ main() gl_Position = Projection3d * (View * (p)); tl_st = v_tl_st[vert]; direction = v_direction[vert]; + color = v_color[vert]; normal = n; position = p; EmitVertex (); diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert index b5866d8b6..6cb8efb28 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert @@ -20,6 +20,7 @@ layout (location = 2) in uint entid; layout (location = 0) out vec4 tl_st; layout (location = 1) out vec3 direction; +layout (location = 2) out vec4 color; void main (void) @@ -29,4 +30,5 @@ main (void) gl_Position = vec4 (vert, 1); direction = (Sky * vertex).xyz; tl_st = tl_uv; + color = entities[entid].color; } diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index 897310930..f6e35ceee 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -10,10 +10,12 @@ layout (push_constant) uniform PushConstants { vec4 fog; float time; float alpha; + float turb_scale; }; layout (location = 0) in vec4 tl_st; layout (location = 1) in vec3 direction; +layout (location = 2) in vec4 color; layout (location = 0) out vec4 frag_color; diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index fdc7dfc10..fe7e50b71 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -6,10 +6,12 @@ layout (push_constant) uniform PushConstants { vec4 fog; float time; float alpha; + float turb_scale; }; layout (location = 0) in vec4 tl_st; layout (location = 1) in vec3 direction; +layout (location = 2) in vec4 color; layout (location = 0) out vec4 frag_color; @@ -25,7 +27,7 @@ warp_st (vec2 st, float time) { vec2 angle = st.ts * CYCLE / 2.0; vec2 phase = vec2 (time, time) * SPEED; - return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; + return st + turb_scale * (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; } vec4 @@ -48,7 +50,8 @@ main (void) c = texture (Texture, t_st); e = texture (Texture, e_st); + float a = c.a * e.a * alpha; c += e; - c.a = alpha; - frag_color = c;//fogBlend (c); + c.a = a; + frag_color = c * color;//fogBlend (c); } diff --git a/libs/video/renderer/vulkan/shader/quakebsp.vert b/libs/video/renderer/vulkan/shader/quakebsp.vert index 7d1c4024e..4b379a06a 100644 --- a/libs/video/renderer/vulkan/shader/quakebsp.vert +++ b/libs/video/renderer/vulkan/shader/quakebsp.vert @@ -20,6 +20,7 @@ layout (location = 2) in uint entid; layout (location = 0) out vec4 tl_st; layout (location = 1) out vec3 direction; +layout (location = 2) out vec4 color; void main (void) @@ -28,4 +29,5 @@ main (void) gl_Position = Projection3d * (View * vec4 (vert, 1)); direction = (Sky * vertex).xyz; tl_st = tl_uv; + color = entities[entid].color; } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 070cb3874..a5beec50a 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -51,6 +51,7 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/math/bitop.h" #include "QF/scene/entity.h" #include "QF/Vulkan/qf_bsp.h" @@ -79,6 +80,7 @@ typedef struct bsp_push_constants_s { quat_t fog; float time; float alpha; + float turb_scale; } bsp_push_constants_t; static const char * __attribute__((used)) bsp_pass_names[] = { @@ -604,6 +606,7 @@ R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx) pass->ent_frame = e->animation.frame & 1; pass->inst_id = model->render_id; + pass->inst_id |= e->renderer.colormod[3] < 1 ? INST_ALPHA : 0; if (!pass->instances[model->render_id].entities.size) { bsp_model_t *m = &bctx->models[model->render_id]; bsp_face_t *face = &bctx->faces[m->first_face]; @@ -767,8 +770,11 @@ push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout, { VK_SHADER_STAGE_FRAGMENT_BIT, field_offset (bsp_push_constants_t, alpha), sizeof (constants->alpha), &constants->alpha }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (bsp_push_constants_t, turb_scale), + sizeof (constants->turb_scale), &constants->turb_scale }, }; - QFV_PushConstants (device, cmd, layout, 3, push_constants); + QFV_PushConstants (device, cmd, layout, 4, push_constants); } static void @@ -956,6 +962,10 @@ queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe) __auto_type is = queue->a[j]; __auto_type f = bctx->faces[is.face]; + f.flags |= ((is.inst_id & INST_ALPHA) + >> (BITOP_LOG2(INST_ALPHA) + - BITOP_LOG2(SURF_DRAWALPHA))) & SURF_DRAWALPHA; + is.inst_id &= ~INST_ALPHA; if (pass->instances[is.inst_id].first_instance == -1) { uint32_t count = pass->instances[is.inst_id].entities.size; pass->instances[is.inst_id].first_instance = pass->entid_count; @@ -966,12 +976,15 @@ queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe) } int dq = 0; - if (bctx->faces[queue->a[0].face].flags & SURF_DRAWSKY) { + if (f.flags & SURF_DRAWSKY) { dq = 1; } - if (bctx->faces[queue->a[0].face].flags & SURF_DRAWTURB) { + if (f.flags & SURF_DRAWALPHA) { dq = 2; } + if (f.flags & SURF_DRAWTURB) { + dq = 3; + } size_t dq_size = pass->draw_queues[dq].size; bsp_draw_t *draw = &pass->draw_queues[dq].a[dq_size - 1]; @@ -1138,22 +1151,30 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - if (!bctx->main_pass.draw_queues[2].size) + if (!bctx->main_pass.draw_queues[3].size) return; turb_begin (rFrame); - bsp_push_constants_t frag_constants = { - .time = vr_data.realtime, - .alpha = r_wateralpha - }; - push_fragconst (&frag_constants, bctx->layout, device, - bframe->cmdSet.a[QFV_bspTurb]); VkPipelineLayout layout = bctx->layout; + bsp_push_constants_t frag_constants = { + .time = vr_data.realtime, + .alpha = 1, + .turb_scale = 0, + }; + push_fragconst (&frag_constants, layout, device, + bframe->cmdSet.a[QFV_bspTurb]); + __auto_type pass = &bctx->main_pass; pass->textures = &bctx->registered_textures; draw_queue (pass, 2, layout, device, bframe->cmdSet.a[QFV_bspTurb]); + frag_constants.alpha = r_wateralpha; + frag_constants.turb_scale = 1; + push_fragconst (&frag_constants, bctx->layout, device, + bframe->cmdSet.a[QFV_bspTurb]); + draw_queue (pass, 3, layout, device, bframe->cmdSet.a[QFV_bspTurb]); + turb_end (ctx); } @@ -1379,7 +1400,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&bctx->registered_textures, 64); - bctx->main_pass.num_queues = 3;//solid, sky, water + bctx->main_pass.num_queues = 4;//solid, sky, water, transparent bctx->main_pass.draw_queues = malloc (bctx->main_pass.num_queues * sizeof (bsp_drawset_t)); for (int i = 0; i < bctx->main_pass.num_queues; i++) { From fb4bb220485553fdbf907b2c361e4544c7485e9e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 May 2022 10:17:10 +0900 Subject: [PATCH 3001/3664] [client] Add cl_(min|max)(pitch|roll) cvars The pitch cvars are taken from quakespasm because I ran into a button I couldn't shoot with the 80 degree limit, but I figured I'd add roll limits while I was at it. --- libs/client/cl_input.c | 44 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index 7830aa830..52164213e 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -286,6 +286,42 @@ static cvar_t cl_yawspeed_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_float, .value = &cl_yawspeed }, }; +float cl_maxpitch; +static cvar_t cl_maxpitch_cvar = { + .name = "cl_maxpitch", + .description = + "turning speed", + .default_value = "90", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_maxpitch }, +}; +float cl_minpitch; +static cvar_t cl_minpitch_cvar = { + .name = "cl_minpitch", + .description = + "turning speed", + .default_value = "-90", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_minpitch }, +}; +float cl_maxroll; +static cvar_t cl_maxroll_cvar = { + .name = "cl_maxroll", + .description = + "turning speed", + .default_value = "50", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_maxroll }, +}; +float cl_minroll; +static cvar_t cl_minroll_cvar = { + .name = "cl_minroll", + .description = + "turning speed", + .default_value = "-50", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_float, .value = &cl_minroll }, +}; int lookspring; static cvar_t lookspring_cvar = { @@ -375,10 +411,10 @@ CL_AdjustAngles (float frametime, movestate_t *ms, viewstate_t *vs) if (delta[PITCH]) { V_StopPitchDrift (vs); - ms->angles[PITCH] = bound (-70, ms->angles[PITCH], 80); + ms->angles[PITCH] = bound (cl_minpitch, ms->angles[PITCH], cl_maxpitch); } if (delta[ROLL]) { - ms->angles[ROLL] = bound (-50, ms->angles[ROLL], 50); + ms->angles[ROLL] = bound (cl_minroll, ms->angles[ROLL], cl_maxroll); } if (delta[YAW]) { ms->angles[YAW] = anglemod (ms->angles[YAW]); @@ -599,6 +635,10 @@ CL_Input_Init_Cvars (void) Cvar_Register (&cl_sidespeed_cvar, 0, 0); Cvar_Register (&cl_upspeed_cvar, 0, 0); Cvar_Register (&cl_yawspeed_cvar, 0, 0); + Cvar_Register (&cl_maxpitch_cvar, 0, 0); + Cvar_Register (&cl_minpitch_cvar, 0, 0); + Cvar_Register (&cl_maxroll_cvar, 0, 0); + Cvar_Register (&cl_minroll_cvar, 0, 0); } void From c6d73eaf64512c1621126638a53871cba4930bf2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 May 2022 10:19:15 +0900 Subject: [PATCH 3002/3664] [vulkan] Add light count display Enabled by 'developer lighting'. It was good for confirming that the lights in ad_e1m1 (Doom Hangar 16) were actually being output (over 600 of them sometimes, ouch). Turned out to be the color scale ambiguity. --- libs/video/renderer/vulkan/vulkan_lighting.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index b92ae2a67..cf22da875 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -52,7 +52,9 @@ #include "QF/va.h" #include "QF/scene/scene.h" +#include "QF/ui/view.h" +#include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/barrier.h" @@ -118,6 +120,11 @@ update_lights (vulkan_ctx_t *ctx) light->color[3] *= style_intensities[ldata->lightstyles.a[i]]; } } + if (developer & SYS_lighting) { + Vulkan_Draw_String (vid.conview->xlen - 32, 8, + va (ctx->va_ctx, "%3d", light_data->lightCount), + ctx); + } qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; bb.barrier.buffer = lframe->light_buffer; From 2e14300a1142714c3b2f6da386a328ddb7a4b545 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 May 2022 12:20:31 +0900 Subject: [PATCH 3003/3664] [client] Auto-detect light color range Some mappers use 0-255 and others use 0-1. Detection method adapted from ericw light (seems to be a good bet as it seems to be popular). --- libs/client/cl_light.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index 83c8fa53b..8aaba5526 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -204,7 +204,9 @@ parse_light (light_t *light, int *style, const plitem_t *entity, } color = { .v = light->color }; sscanf (str, "%f %f %f", VectorExpandAddr (color.a)); light->color = color.v; - VectorScale (light->color, 1/255.0, light->color); + if (light->color[0] > 1 || light->color[1] > 1 || light->color[2] > 1) { + VectorScale (light->color, 1/255.0, light->color); + } } if ((str = PL_String (PL_ObjectForKey (entity, "wait")))) { From 6e8a3b8153790247ca1ee1fce1996877ee861b6b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 May 2022 20:06:33 +0900 Subject: [PATCH 3004/3664] [qfmap] Parse field info from quaked comments Id's comments are a little inconsistent, but for the most part usable info can be extracted. While not yet supported, Arcane Dimensions' comments are extremely consistent (just some issues with hyphen counts in separators), so parsing out usable info will be fairly easy. The hard part will be presenting it. --- tools/io_mesh_qfmdl/qfplist.py | 2 +- tools/io_qfmap/entity.py | 39 +++++---- tools/io_qfmap/entityclass.py | 146 ++++++++++++++++++++++++++++++--- tools/io_qfmap/script.py | 13 ++- 4 files changed, 162 insertions(+), 38 deletions(-) diff --git a/tools/io_mesh_qfmdl/qfplist.py b/tools/io_mesh_qfmdl/qfplist.py index aaf3b6053..b1852dab7 100644 --- a/tools/io_mesh_qfmdl/qfplist.py +++ b/tools/io_mesh_qfmdl/qfplist.py @@ -253,7 +253,7 @@ class pldata: elif type(item) in [int, float]: self.write_string(str(item)) else: - raise PListError(0, "unsupported type") + raise PListError(0, f"unsupported type {type(item)}") def write(self, item): self.data = [] self.write_item(item, 0) diff --git a/tools/io_qfmap/entity.py b/tools/io_qfmap/entity.py index 86a316234..7657fbf40 100644 --- a/tools/io_qfmap/entity.py +++ b/tools/io_qfmap/entity.py @@ -25,6 +25,9 @@ from bpy.props import BoolProperty, FloatProperty, StringProperty, EnumProperty from bpy.props import BoolVectorProperty, CollectionProperty, PointerProperty from bpy.props import FloatVectorProperty, IntProperty from mathutils import Vector +from math import ceil + +from textwrap import TextWrapper from .entityclass import EntityClass @@ -158,23 +161,6 @@ class QFEntpropRemove(bpy.types.Operator): qfentity.fields.remove(qfentity.field_idx) return {'FINISHED'} -def reflow_text(text, max_width): - lines = [] - for text_line in text.split("\n"): - if not text_line: - continue - words = text_line.split(" ") - flowed_line = "" - while words: - if len(flowed_line) + len(words[0]) > max_width: - lines.append(flowed_line) - flowed_line = "" - flowed_line += (" " if flowed_line else "") + words[0] - del words[0] - if flowed_line: - lines.append(flowed_line) - return lines - class OBJECT_PT_EntityPanel(bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' @@ -198,9 +184,22 @@ class OBJECT_PT_EntityPanel(bpy.types.Panel): row = layout.row() row.prop(qfentity, "classname") box=layout.box() - lines = reflow_text(ec.comment, 40) - for l in lines: - box.label(text=l) + width = int(ceil(context.region.width / 6)) + mainwrap = TextWrapper(width = width) + subwrap = TextWrapper(width = width - 8) + for c in ec.comment: + clines = mainwrap.wrap(c) + for l in clines: + box.label(text=l) + for f in ec.fields.values(): + print(f.name) + flines = subwrap.wrap(f.comment) + box.label(text=f"{f.name}") + for l in flines: + box.label(text=f" {l}") + if hasattr(f, "sounds"): + for s in f.sounds: + box.label(text=f" {s[0]} {s[1]}") row = layout.row() for c in range(3): col = row.column() diff --git a/tools/io_qfmap/entityclass.py b/tools/io_qfmap/entityclass.py index c7b9cbd0e..43e0b6604 100644 --- a/tools/io_qfmap/entityclass.py +++ b/tools/io_qfmap/entityclass.py @@ -20,9 +20,14 @@ # import os -from .script import Script -from .qfplist import pldata -from . import quakechr +try: + from .script import Script + from .qfplist import pldata + from . import quakechr +except ImportError: + from script import Script + from qfplist import pldata + import quakechr MAX_FLAGS = 8 @@ -34,16 +39,46 @@ class EntityClassError(Exception): def entclass_error(self, msg): raise EntityClassError(self.filename, self.line, msg) +class EntityField: + def __init__(self, name, default, comment): + self.name = name + self.default = default + self.comment = comment + def to_dictionary(self): + d = {} + if self.default != None: + d["default"] = self.default + if self.comment: + d["comment"] = self.comment + if hasattr(self, "sounds"): + d["sounds"] = self.sounds + return d + @classmethod + def from_dictionary(cls, name, d): + if "default" in d: + default = d["default"] + else: + default = None + if "comment" in d: + comment = d["comment"] + else: + comment = "" + field = cls(name, default, comment) + if "sounds" in d: + field.sounds = d["sounds"] + return field + class EntityClass: - def __init__(self, name, color, size, flagnames, comment): + def __init__(self, name, color, size, flagnames, comment, fields): self.name = name self.color = color self.size = size self.flagnames = flagnames self.comment = comment + self.fields = fields @classmethod def null(cls): - return cls('', (1, 1, 1), None, (), "") + return cls('', (1, 1, 1), None, (), "", {}) @classmethod def from_quaked(cls, text, filename, line = 0): script = Script(filename, text) @@ -59,8 +94,49 @@ class EntityClass: else: size = None flagnames = () - comment = cls.extract_comment(script) - return cls(name, color, size, flagnames, comment) + comment = [] + fields = {} + script.quotes = False + script.single = "" + while script.tokenAvailable(True): + line = [] + while script.tokenAvailable(): + script.getToken() + if script.token[-2:] == "*/": + break; + line.append(script.token) + if line: + if ((line[0][0] == '"' and line[0][-1] == '"') + or (len(line) > 1 and line[1] == '=')): + if line[0][0] == '"': + fname = line[0][1:-1] + line = line[1:] + else: + fname = line[0] + line = line[2:] + default = None + for i, t in enumerate(line[:-1]): + if t[0] == '(' and line[i + 1] == "default)": + default = t[1:] + break + line = " ".join(line) + fields[fname] = EntityField(fname, default, line) + line = None + elif "sounds" in fields: + sounds = fields["sounds"] + if not hasattr(sounds, "sounds"): + sounds.sounds = [] + if line[0][-1] == ')': + line[0] = line[0][:-1] + sounds.sounds.append((line[0], " ".join(line[1:]))) + line = None + else: + line = " ".join(line) + if line: + comment.append(line) + if script.token[-2:] == "*/": + break; + return cls(name, color, size, flagnames, comment, fields) @classmethod def from_dictionary(cls, name, d): if "color" in d: @@ -81,11 +157,21 @@ class EntityClass: if "comment" in d: comment = d["comment"] else: - comment = "" - return cls(name, color, size, flagnames, comment) + comment = [] + if "fields" in d: + field_dict = d["fields"] + fields = {} + for f in field_dict: + fields[f] = EntityField.from_dictionary(f, field_dict[f]) + else: + fields = {} + return cls(name, color, size, flagnames, comment, fields) def to_dictionary(self): + fields = {} + for f in self.fields: + fields[f] = self.fields[f].to_dictionary() d = {"color":self.color, "flagnames":self.flagnames, - "comment":self.comment} + "comment":self.comment, "fields":fields} if self.size: d["size"] = self.size return d @@ -93,8 +179,11 @@ class EntityClass: def parse_vector(cls, script): if script.getToken() != "(": script.error("Missing (") - v = (float(script.getToken()), float(script.getToken()), - float(script.getToken())) + s = script.getToken(), script.getToken(), script.getToken() + try: + v = (float(s[0]), float(s[1]), float(s[2])) + except ValueError: + v = s if script.getToken() != ")": script.error("Missing )") return v @@ -118,7 +207,6 @@ class EntityClass: if len(flagnames) < MAX_FLAGS: flagnames.append(script.token) return tuple(flagnames) - @classmethod def extract_comment(cls, script): if not script.tokenAvailable(True): return "" @@ -203,3 +291,35 @@ class EntityClassDict: self.entity_classes = {} for k in ec.keys(): self.entity_classes[k] = EntityClass.from_dictionary(k, ec[k]) + +if __name__ == "__main__": + import sys + from pprint import pprint + from textwrap import TextWrapper + + mainwrap = TextWrapper(width = 70) + fieldwrap = TextWrapper(width = 50) + + ecd = EntityClassDict() + for fname in sys.argv[1:]: + ecd.scan_source(fname) + text = ecd.to_plist() + print(text) + ecd.from_plist(text) + for ec in ecd.entity_classes.values(): + print(f"{ec.name}: {ec.color} {ec.size} {ec.flagnames}") + for c in ec.comment: + mlines = mainwrap.wrap(c) + for m in mlines: + print(f" {m}") + print() + for f in ec.fields.values(): + print(f" {f.name}: {f.default}") + flines = fieldwrap.wrap(f.comment) + for l in flines: + print(f" {l}") + if f.name == "sounds": + for s in f.sounds: + print(f" {s[0]} {s[1]}") + print() + print() diff --git a/tools/io_qfmap/script.py b/tools/io_qfmap/script.py index fc030e3e5..873384052 100644 --- a/tools/io_qfmap/script.py +++ b/tools/io_qfmap/script.py @@ -26,17 +26,19 @@ class ScriptError(Exception): class Script: def __init__(self, filename, text, single="{}()':", quotes=True): - self.filename = filename if text[0:3] == "\xef\xbb\xbf": text = text[3:] elif text[0] == u"\ufeff": text = text[1:] + self.token = "" + self.unget = False self.text = text + self.pos = 0 + self.filename = filename + self.line = 1 + self.no_quote_lines = False self.single = single self.quotes = quotes - self.pos = 0 - self.line = 1 - self.unget = False def error(self, msg): raise ScriptError(self.filename, self.line, msg) def tokenAvailable(self, crossline=False): @@ -102,6 +104,9 @@ class Script: self.error("EOF inside quoted string") return None if self.text[self.pos] == "\n": + if self.no_quote_lines: + self.error("EOL inside quoted string") + return None self.line += 1 self.pos += 1 self.token = self.text[start:self.pos] From ea781c9dccc3704b46f183c62bfb3540e44a9905 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 May 2022 20:20:03 +0900 Subject: [PATCH 3005/3664] [qfmap] Fix some blender bit-rot. --- tools/io_qfmap/entity.py | 2 +- tools/io_qfmap/import_map.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/io_qfmap/entity.py b/tools/io_qfmap/entity.py index 7657fbf40..58c6d8953 100644 --- a/tools/io_qfmap/entity.py +++ b/tools/io_qfmap/entity.py @@ -268,7 +268,7 @@ def set_entity_props(obj, ent): qfe.classname = ent.d["classname"] except TypeError: #FIXME hmm, maybe an enum wasn't the most brilliant idea? - qfe.classname = '' + qfe.classname = '.' if "spawnflags" in ent.d: flags = int(float(ent.d["spawnflags"])) for i in range(12): diff --git a/tools/io_qfmap/import_map.py b/tools/io_qfmap/import_map.py index c247d4920..e814cf380 100644 --- a/tools/io_qfmap/import_map.py +++ b/tools/io_qfmap/import_map.py @@ -175,8 +175,8 @@ def process_entity(ent, wads): obj = bpy.data.objects.new(name, mesh) else: obj = bpy.data.objects.new(name, None) - obj.empty_draw_type = 'CUBE' - obj.empty_draw_size = 8 + obj.empty_display_type = 'CUBE' + obj.empty_display_size = 8 obj.show_name = True if "origin" in ent.d: obj.location = parse_vector (ent.d["origin"]) From 125821fcdd7788ee4b261c9de65759aa9b62047e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 May 2022 18:14:26 +0900 Subject: [PATCH 3006/3664] [render] Add basic 2d line drawing The software renderer uses Bresenham's line slice algorithm as presented by Michael Abrash in his Graphics Programming Black Book Special Edition with the serial numbers filed off (as such, more just so *I* can read the code easily), along with the Chen-Sutherland line clipping algorithm. The other renderers were more or less trivial in comparison. --- include/QF/GL/qf_draw.h | 1 + include/QF/GLSL/qf_draw.h | 1 + include/QF/Vulkan/qf_draw.h | 2 + include/QF/draw.h | 11 ++ include/QF/plugin/vid_render.h | 1 + libs/video/renderer/gl/gl_draw.c | 16 ++ libs/video/renderer/glsl/glsl_draw.c | 55 ++++++- libs/video/renderer/r_progs.c | 29 ++++ libs/video/renderer/sw/draw.c | 159 ++++++++++++++++++++ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_vulkan.c | 7 + libs/video/renderer/vulkan/qfpipeline.plist | 8 + libs/video/renderer/vulkan/vulkan_bsp.c | 6 +- libs/video/renderer/vulkan/vulkan_draw.c | 96 +++++++++--- ruamoko/include/draw.h | 4 + ruamoko/lib/draw.r | 4 + 18 files changed, 375 insertions(+), 28 deletions(-) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index 65f1a03da..d348e2534 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -41,6 +41,7 @@ void gl_Draw_Crosshair (void); void gl_Draw_CrosshairAt (int ch, int x, int y); void gl_Draw_TileClear (int x, int y, int w, int h); void gl_Draw_Fill (int x, int y, int w, int h, int c); +void gl_Draw_Line (int x0, int y0, int x1, int y1, int c); void gl_Draw_TextBox (int x, int y, int width, int lines, byte alpha); void gl_Draw_FadeScreen (void); void gl_Draw_BlendScreen (quat_t color); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index 653e2bc5f..5c93713fc 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -41,6 +41,7 @@ void glsl_Draw_Crosshair (void); void glsl_Draw_CrosshairAt (int ch, int x, int y); void glsl_Draw_TileClear (int x, int y, int w, int h); void glsl_Draw_Fill (int x, int y, int w, int h, int c); +void glsl_Draw_Line (int x0, int y0, int x1, int y1, int c); void glsl_Draw_TextBox (int x, int y, int width, int lines, byte alpha); void glsl_Draw_FadeScreen (void); void glsl_Draw_BlendScreen (quat_t color); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 26f9d2a28..216f4b3a0 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -50,6 +50,8 @@ void Vulkan_Draw_TileClear (int x, int y, int w, int h, struct vulkan_ctx_s *ctx); void Vulkan_Draw_Fill (int x, int y, int w, int h, int c, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, + struct vulkan_ctx_s *ctx); void Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, struct vulkan_ctx_s *ctx); void Vulkan_Draw_FadeScreen (struct vulkan_ctx_s *ctx); diff --git a/include/QF/draw.h b/include/QF/draw.h index 8f6b78889..5f6037e15 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -144,6 +144,17 @@ void Draw_TileClear (int x, int y, int w, int h); */ void Draw_Fill (int x, int y, int w, int h, int c); +/** Clear a line with a solid color. + \param x0 horizontal position of the line start point + \param y0 horizontal position of the line start point + \param x1 horizontal position of the line end point + \param y1 horizontal position of the line end point + \param c 8 bit color index. + + The color comes from the quake palette. +*/ +void Draw_Line (int x0, int y0, int x1, int y1, int c); + /** Draw a text box on the screen \param x horizontal location of the upper left corner of the box \param y vertical location of the upper left corner of the box diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 1f19a5278..3d6774d08 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -91,6 +91,7 @@ typedef struct vid_render_funcs_s { void (*Draw_CrosshairAt) (int ch, int x, int y); void (*Draw_TileClear) (int x, int y, int w, int h); void (*Draw_Fill) (int x, int y, int w, int h, int c); + void (*Draw_Line) (int x0, int y0, int x1, int y1, int c); void (*Draw_TextBox) (int x, int y, int width, int lines, byte alpha); void (*Draw_FadeScreen) (void); void (*Draw_BlendScreen) (quat_t color); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 820c83d8e..c4abb9753 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -910,6 +910,22 @@ gl_Draw_Fill (int x, int y, int w, int h, int c) qfglEnable (GL_TEXTURE_2D); } +void +gl_Draw_Line (int x0, int y0, int x1, int y1, int c) +{ + qfglDisable (GL_TEXTURE_2D); + qfglColor3ubv (vid.palette + c * 3); + + qfglBegin (GL_LINES); + + qfglVertex2f (x0, y0); + qfglVertex2f (x1, y1); + + qfglEnd (); + qfglColor3ubv (color_white); + qfglEnable (GL_TEXTURE_2D); +} + void gl_Draw_FadeScreen (void) { diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index d24d57f97..a150fe20f 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -104,6 +104,7 @@ static struct { static scrap_t *draw_scrap; // hold all 2d images static byte white_block[8 * 8]; static dstring_t *draw_queue; +static dstring_t *line_queue; static qpic_t *conchars; static int conback_texture; static qpic_t *crosshair_pic; @@ -388,6 +389,7 @@ glsl_Draw_Init (void) //crosshaircolor->callback (crosshaircolor); draw_queue = dstring_new (); + line_queue = dstring_new (); vert_shader = GLSL_BuildShader (twod_vert_effects); frag_shader = GLSL_BuildShader (twod_frag_effects); @@ -461,14 +463,26 @@ static void flush_2d (void) { GLSL_ScrapFlush (draw_scrap); - qfeglBindTexture (GL_TEXTURE_2D, GLSL_ScrapTexture (draw_scrap)); - qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT, - 0, 32, draw_queue->str); - qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT, - 0, 32, draw_queue->str + 16); - qfeglDrawArrays (GL_TRIANGLES, 0, draw_queue->size / 32); + qfeglBindTexture (GL_TEXTURE_2D, GLSL_ScrapTexture (draw_scrap)); + if (draw_queue->size) { + qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT, + 0, 32, draw_queue->str); + qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT, + 0, 32, draw_queue->str + 16); + + qfeglDrawArrays (GL_TRIANGLES, 0, draw_queue->size / 32); + } + if (line_queue->size) { + qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT, + 0, 32, line_queue->str); + qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT, + 0, 32, line_queue->str + 16); + + qfeglDrawArrays (GL_LINES, 0, line_queue->size / 32); + } draw_queue->size = 0; + line_queue->size = 0; } void @@ -693,6 +707,32 @@ glsl_Draw_Fill (int x, int y, int w, int h, int c) draw_pic (x, y, w, h, white_pic, 0, 0, 8, 8, color); } +void +glsl_Draw_Line (int x0, int y0, int x1, int y1, int c) +{ + glpic_t *gl = (glpic_t *) white_pic->data; + subpic_t *sp = gl->subpic; + float sl = sp->rect->x * sp->size; + float sh = sp->rect->x * sp->size; + float tl = sp->rect->y * sp->size; + float th = sp->rect->y * sp->size; + + quat_t color = { VectorExpand (vid.palette + c * 3), 255 }; + QuatScale (color, 1/255.0, color); + drawvert_t verts[2] = { + { .xyst = { x0, y0, sl, tl }, .color = { QuatExpand (color) }, }, + { .xyst = { x1, y1, sh, th }, .color = { QuatExpand (color) }, }, + }; + + void *v; + int size = sizeof (verts); + + line_queue->size += size; + dstring_adjust (line_queue); + v = line_queue->str + line_queue->size - size; + memcpy (v, verts, size); +} + static inline void draw_blendscreen (quat_t color) { @@ -784,12 +824,13 @@ void GLSL_DrawReset (void) { draw_queue->size = 0; + line_queue->size = 0; } void GLSL_FlushText (void) { - if (draw_queue->size) + if (draw_queue->size || line_queue->size) flush_2d (); } diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 319634505..db9760e37 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -42,6 +42,8 @@ #include "QF/render.h" #include "QF/sys.h" +#include "QF/ui/view.h" + #include "r_internal.h" typedef struct { @@ -296,6 +298,18 @@ bi_Draw_Fill (progs_t *pr, void *_res) r_funcs->Draw_Fill (x, y, w, h, color); } +static void +bi_Draw_Line (progs_t *pr, void *_res) +{ + int x0 = P_INT (pr, 0); + int y0 = P_INT (pr, 1); + int x1 = P_INT (pr, 2); + int y1 = P_INT (pr, 3); + int color = P_INT (pr, 4); + + r_funcs->Draw_Line (x0, y0, x1, y1, color); +} + static void bi_Draw_Crosshair (progs_t *pr, void *_res) { @@ -306,6 +320,18 @@ bi_Draw_Crosshair (progs_t *pr, void *_res) r_funcs->Draw_CrosshairAt (ch, x, y); } +static void +bi_Draw_Width (progs_t *pr, void *_res) +{ + R_INT (pr) = r_data->vid->conview->xlen; +} + +static void +bi_Draw_Height (progs_t *pr, void *_res) +{ + R_INT (pr) = r_data->vid->conview->ylen; +} + static const char * bi_draw_get_key (const void *p, void *unused) { @@ -338,6 +364,8 @@ bi_draw_destroy (progs_t *pr, void *_res) #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { + bi(Draw_Width, 0), + bi(Draw_Height, 0), bi(Draw_FreePic, 1, p(ptr)), bi(Draw_MakePic, 3, p(int), p(int), p(string)), bi(Draw_CachePic, 2, p(string), p(int)), @@ -351,6 +379,7 @@ static builtin_t builtins[] = { bi(Draw_nString, 4, p(int), p(int), p(string), p(int)), bi(Draw_AltString, 3, p(int), p(int), p(string)), bi(Draw_Fill, 5, p(int), p(int), p(int), p(int), p(int)), + bi(Draw_Line, 5, p(int), p(int), p(int), p(int), p(int)), bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)), {0} }; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 27568d82c..c861da9b4 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -766,6 +766,165 @@ Draw_Fill (int x, int y, int w, int h, int c) dest[u] = c; } +static inline byte * +draw_horizontal (byte *dest, int xs, int len, int c) +{ + while (len-- > 0) { + *dest = c; + dest += xs; + } + return dest; +} + +static inline byte * +draw_vertical (byte *dest, int len, int c) +{ + while (len-- > 0) { + *dest = c; + dest += d_rowbytes; + } + return dest; +} + +static void +draw_line (int x0, int y0, int x1, int y1, int c) +{ + // Bresenham's line slice algorith (ala Michael Abrash) + int dx, dy, sx; + // always go top to bottom + if (y1 < y0) { + int t; + t = y1; y1 = y0; y0 = t; + t = x1; x1 = x0; x0 = t; + } + dy = y1 - y0; + + if ((dx = x1 - x0) < 0) { + sx = -1; + dx = -dx; + } else { + sx = 1; + } + + byte *dest = d_viewbuffer + y0 * d_rowbytes + x0; + + if (!dx) { + draw_vertical (dest, dy, c); + return; + } + if (!dy) { + draw_horizontal (dest, sx, dx, c); + return; + } + if (dx == dy) { + while (dy-- > 0) { + *dest = c; + dest += d_rowbytes + sx; + } + return; + } + if (dx > dy) { + int step = dx / dy; + int adj_up = (dx % dy) * 2; + int adj_down = dy * 2; + int error = (dx % dy) - adj_down; + int initial = step / 2 + 1; + int final = initial; + + if (!adj_up && !(step & 1)) { + initial--; + } + if (step & 1) { + error += dy; + } + dest = draw_horizontal (dest, sx, initial, c); + dest += d_rowbytes; + while (dy-- > 1) { + int run = step; + if ((error += adj_up) > 0) { + run++; + error -= adj_down; + } + dest = draw_horizontal (dest, sx, run, c); + dest += d_rowbytes; + } + dest = draw_horizontal (dest, sx, final, c); + } else { + int step = dy / dx; + int adj_up = (dy % dx) * 2; + int adj_down = dx * 2; + int error = (dy % dx) - adj_down; + int initial = step / 2 + 1; + int final = initial; + + if (!adj_up && !(step & 1)) { + initial--; + } + if (step & 1) { + error += dx; + } + dest = draw_vertical (dest, initial, c); + dest += sx; + while (dx-- > 1) { + int run = step; + if ((error += adj_up) > 0) { + run++; + error -= adj_down; + } + dest = draw_vertical (dest, run, c); + dest += sx; + } + dest = draw_vertical (dest, final, c); + } +} + +static inline byte +test_point (int x, int y) +{ + byte c = 0; + + if (x < 0) { + c |= 1; + } else if (x >= vid.conview->xlen) { + c |= 2; + } + if (y < 0) { + c |= 4; + } else if (y >= vid.conview->ylen) { + c |= 8; + } + return c; +} + +void +Draw_Line (int x0, int y0, int x1, int y1, int c) +{ + byte c0 = test_point (x0, y0); + byte c1 = test_point (x1, y1); + int xmax = vid.conview->xlen - 1; + int ymax = vid.conview->ylen - 1; + + while (c0 | c1) { + // Cohen-Sutherland line clipping + if (c0 & c1) { + return; + } + int dx = x1 - x0; + int dy = y1 - y0; + if (c0 & 1) { y0 = (( 0 - x0) * dy + dx * y0) / dx; x0 = 0; } + if (c0 & 2) { y0 = ((xmax - x0) * dy + dx * y0) / dx; x0 = xmax; } + if (c1 & 1) { y1 = (( 0 - x1) * dy + dx * y1) / dx; x1 = 0; } + if (c1 & 2) { y1 = ((xmax - x1) * dy + dx * y1) / dx; x1 = xmax; } + + if (c0 & 4) { x0 = (( 0 - y0) * dx + dy * x0) / dy; y0 = 0; } + if (c0 & 8) { x0 = ((ymax - y0) * dx + dy * x0) / dy; y0 = ymax; } + if (c1 & 4) { x1 = (( 0 - y1) * dx + dy * x1) / dy; y1 = 0; } + if (c1 & 8) { x1 = ((ymax - y1) * dx + dy * x1) / dy; y1 = ymax; } + c0 = test_point (x0, y0); + c1 = test_point (x1, y1); + } + draw_line (x0, y0, x1, y1, c); +} void Draw_FadeScreen (void) diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 7944e3ada..3fe390bf9 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -495,6 +495,7 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_CrosshairAt, gl_Draw_TileClear, gl_Draw_Fill, + gl_Draw_Line, gl_Draw_TextBox, gl_Draw_FadeScreen, gl_Draw_BlendScreen, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 9be89b23a..958cfbfdc 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -439,6 +439,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_CrosshairAt, glsl_Draw_TileClear, glsl_Draw_Fill, + glsl_Draw_Line, glsl_Draw_TextBox, glsl_Draw_FadeScreen, glsl_Draw_BlendScreen, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index a4a532557..e1398bc72 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -459,6 +459,7 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_CrosshairAt, Draw_TileClear, Draw_Fill, + Draw_Line, Draw_TextBox, Draw_FadeScreen, Draw_BlendScreen, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 6e66fdc54..cce63d511 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -189,6 +189,12 @@ vulkan_Draw_Fill (int x, int y, int w, int h, int c) Vulkan_Draw_Fill (x, y, w, h, c, vulkan_ctx); } +static void +vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c) +{ + Vulkan_Draw_Line (x0, y0, x1, y1, c, vulkan_ctx); +} + static void vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha) { @@ -731,6 +737,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_CrosshairAt, vulkan_Draw_TileClear, vulkan_Draw_Fill, + vulkan_Draw_Line, vulkan_Draw_TextBox, vulkan_Draw_FadeScreen, vulkan_Draw_BlendScreen, diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 4e4f59e9e..accc4e366 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -482,6 +482,10 @@ topology = triangle_list; primitiveRestartEnable = false; }; + lines = { + topology = line_list; + primitiveRestartEnable = false; + }; twod = { topology = triangle_strip; primitiveRestartEnable = true; @@ -1045,6 +1049,10 @@ }; layout = twod_layout; }; + lines = { + @inherit = $properties.pipelines.twod; + inputAssembly = $properties.inputAssembly.lines; + }; lighting = { @inherit = $properties.pipelines.comp_base; subpass = 3; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a5beec50a..43dbd4a67 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1072,8 +1072,10 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) int world_id = worldent.renderer.model->render_id; bctx->main_pass.ent_frame = 0; // world is always frame 0 bctx->main_pass.inst_id = world_id; - DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, - worldent.renderer.render_id); + if (bctx->main_pass.instances) { + DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, + worldent.renderer.render_id); + } R_VisitWorldNodes (brush, ctx); if (!bctx->vertex_buffer) { return; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 46604ae24..c042d814f 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -82,8 +82,11 @@ typedef struct cachepic_s { typedef struct drawframe_s { size_t vert_offset; - drawvert_t *verts; + size_t line_offset; + drawvert_t *quad_verts; + drawvert_t *line_verts; uint32_t num_quads; + uint32_t num_lines; VkCommandBuffer cmd; VkDescriptorSet descriptors; } drawframe_t; @@ -109,7 +112,8 @@ typedef struct drawctx_s { VkDeviceMemory vert_memory; VkBuffer ind_buffer; VkDeviceMemory ind_memory; - VkPipeline pipeline; + VkPipeline quad_pipeline; + VkPipeline line_pipeline; VkPipelineLayout layout; drawframeset_t frames; } drawctx_t; @@ -119,6 +123,11 @@ typedef struct drawctx_s { #define VERTS_PER_QUAD (4) #define INDS_PER_QUAD (5) // one per vert plus primitive reset +#define MAX_LINES (32768) +#define VERTS_PER_LINE (2) + +#define VERTS_PER_FRAME (MAX_LINES*VERTS_PER_LINE + MAX_QUADS*VERTS_PER_QUAD) + static void create_quad_buffers (vulkan_ctx_t *ctx) { @@ -133,7 +142,7 @@ create_quad_buffers (vulkan_ctx_t *ctx) VkBuffer vbuf, ibuf; VkDeviceMemory vmem, imem; - vert_size = frames * MAX_QUADS * VERTS_PER_QUAD * sizeof (drawvert_t); + vert_size = frames * VERTS_PER_FRAME * sizeof (drawvert_t); ind_size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t); vbuf = QFV_CreateBuffer (device, vert_size, @@ -161,10 +170,14 @@ create_quad_buffers (vulkan_ctx_t *ctx) for (size_t f = 0; f < frames; f++) { drawframe_t *frame = &dctx->frames.a[f]; - size_t ind = f * MAX_QUADS * VERTS_PER_QUAD; + size_t ind = f * VERTS_PER_FRAME; + size_t lind = ind + MAX_QUADS * VERTS_PER_QUAD; frame->vert_offset = ind * sizeof (drawvert_t); - frame->verts = vert_data + ind; + frame->line_offset = lind; + frame->quad_verts = vert_data + ind; + frame->line_verts = frame->quad_verts + MAX_QUADS * VERTS_PER_QUAD; frame->num_quads = 0; + frame->num_lines = 0; } // The indices will never change so pre-generate and stash them @@ -347,7 +360,8 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) destroy_quad_buffers (ctx); - dfunc->vkDestroyPipeline (device->dev, dctx->pipeline, 0); + dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); + dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0); Hash_DelTable (dctx->pic_cache); delete_memsuper (dctx->pic_memsuper); delete_memsuper (dctx->string_memsuper); @@ -409,7 +423,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); - dctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); + dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); + dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines"); dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout"); @@ -457,7 +472,7 @@ draw_pic (float x, float y, int w, int h, qpic_t *pic, return; } - drawvert_t *verts = frame->verts + frame->num_quads * VERTS_PER_QUAD; + drawvert_t *verts = frame->quad_verts + frame->num_quads * VERTS_PER_QUAD; frame->num_quads++; subpic_t *subpic = *(subpic_t **) pic->data; @@ -767,6 +782,32 @@ Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) draw_pic (x, y, w, h, dctx->white_pic, 0, 0, 1, 1, color, frame); } +void +Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + + if (frame->num_quads >= MAX_QUADS) { + return; + } + + quat_t color = { VectorExpand (vid.palette + c * 3), 255 }; + QuatScale (color, 1/255.0, color); + drawvert_t *verts = frame->line_verts + frame->num_lines * VERTS_PER_LINE; + + verts[0] = (drawvert_t) { + .xy = { x0, y0 }, + .color = { QuatExpand (color) }, + }; + verts[1] = (drawvert_t) { + .xy = { x1, y1 }, + .color = { QuatExpand (color) }, + }; + + frame->num_lines++; +} + static inline void draw_blendscreen (quat_t color, vulkan_ctx_t *ctx) { @@ -816,16 +857,23 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + if (!dframe->num_quads && !dframe->num_lines) { + return; + } + VkCommandBuffer cmd = dframe->cmd; //FIXME which pass? DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], cmd); - VkMappedMemoryRange range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - dctx->vert_memory, dframe->vert_offset, - dframe->num_quads * VERTS_PER_QUAD * sizeof (drawvert_t), + VkMappedMemoryRange ranges[] = { + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + dctx->vert_memory, dframe->vert_offset, + dframe->num_quads * VERTS_PER_QUAD * sizeof (drawvert_t) }, + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + dctx->vert_memory, dframe->line_offset, + dframe->num_lines * VERTS_PER_LINE * sizeof (drawvert_t) }, }; - dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); + dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { @@ -843,10 +891,6 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) QFV_duCmdBeginLabel (device, cmd, "twod", { 0.6, 0.2, 0, 1}); - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - dctx->pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); VkDeviceSize offsets[] = {dframe->vert_offset}; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets); dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, @@ -858,13 +902,27 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) VkPipelineLayout layout = dctx->layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 2, set, 0, 0); - dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD, - 1, 0, 0, 0); + if (dframe->num_quads) { + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + dctx->quad_pipeline); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); + dfunc->vkCmdDrawIndexed (cmd, dframe->num_quads * INDS_PER_QUAD, + 1, 0, 0, 0); + } + + if (dframe->num_lines) { + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + dctx->line_pipeline); + dfunc->vkCmdDraw (cmd, dframe->num_lines * VERTS_PER_LINE, + 1, MAX_QUADS * VERTS_PER_QUAD, 0); + } QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); dframe->num_quads = 0; + dframe->num_lines = 0; } void diff --git a/ruamoko/include/draw.h b/ruamoko/include/draw.h index ae868ff36..a5369375e 100644 --- a/ruamoko/include/draw.h +++ b/ruamoko/include/draw.h @@ -10,6 +10,9 @@ struct _qpic_t { }; typedef struct _qpic_t *qpic_t; +@extern int Draw_Width (void); +@extern int Draw_Height (void); + @extern void Draw_FreePic (qpic_t pic); @extern qpic_t Draw_MakePic (int width, int heiight, string data); @extern qpic_t Draw_CachePic (string name, int alpha); @@ -24,6 +27,7 @@ typedef struct _qpic_t *qpic_t; @extern void Draw_nString (int x, int y, string text, int n); @extern void Draw_AltString (int x, int y, string text); @extern void Draw_Fill (int x, int y, int w, int h, int c); +@extern void Draw_Line (int x0, int y0, int x1, int y1, int c); @extern void Draw_Crosshair (int ch, int x, int y); @extern void text_box (int x, int y, int width, int lines); diff --git a/ruamoko/lib/draw.r b/ruamoko/lib/draw.r index 5aef3ab75..65311595f 100644 --- a/ruamoko/lib/draw.r +++ b/ruamoko/lib/draw.r @@ -1,5 +1,8 @@ #include +int Draw_Width (void) = #0; +int Draw_Height (void) = #0; + void Draw_FreePic (qpic_t pic) = #0; qpic_t Draw_MakePic (int width, int heiight, string data) = #0; qpic_t (string name, int alpha) Draw_CachePic = #0; @@ -14,6 +17,7 @@ void (int x, int y, string text) Draw_String = #0; void (int x, int y, string text, int n) Draw_nString = #0; void (int x, int y, string text) Draw_AltString = #0; void (int x, int y, int w, int h, int c) Draw_Fill = #0; +void (int x0, int y0, int x1, int y1, int c) Draw_Line = #0; void (int ch, int x, int y) Draw_Crosshair = #0; void (int x, int y, int width, int lines) text_box = From e5932d1f92ebb131ba4110ac2bf1e109189354f9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 May 2022 21:53:38 +0900 Subject: [PATCH 3007/3664] [vulkan] Support Vulkan's pNext in vkparse/vkgen The real reason for the delay in implementing support for pNext is I didn't know how to approach it at the time, but with the experience I've gained using and modifying vkparse, the solution turned out to be fairly simple. This allows for the use of various extensions (eg, multiview, which was used for testing, though none of the hookup is in this commit). No checking is done on the struct type being valid other than it must be of a chainable type (ie, have its own pNext). --- libs/video/renderer/Makemodule.am | 15 ++-- libs/video/renderer/vulkan/shader.c | 3 - libs/video/renderer/vulkan/shadow.plist | 12 ++-- libs/video/renderer/vulkan/vkgen/vkstruct.h | 1 + libs/video/renderer/vulkan/vkgen/vkstruct.r | 30 ++++++-- libs/video/renderer/vulkan/vkparse.c | 68 +++++++++++++++++++ libs/video/renderer/vulkan/vkparse.plist | 19 ++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 4 ++ 8 files changed, 134 insertions(+), 18 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 6a52b1af4..41a940649 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -183,6 +183,8 @@ pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc deferred_src = libs/video/renderer/vulkan/deferred.plist deferred_gen = libs/video/renderer/vulkan/deferred.plc +shadow_src = libs/video/renderer/vulkan/shadow.plist +shadow_gen = libs/video/renderer/vulkan/shadow.plc forward_src = libs/video/renderer/vulkan/forward.plist forward_gen = libs/video/renderer/vulkan/forward.plc @@ -236,7 +238,13 @@ libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vk libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c) -libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${deferred_gen} $(forward_gen) +libs/video/renderer/vulkan/vulkan_vid_common.lo: \ + libs/video/renderer/vulkan/vulkan_vid_common.c \ + $(vkparse_src) \ + $(pipeline_gen) \ + ${deferred_gen} \ + ${shadow_gen} \ + $(forward_gen) qwaq_cmd = $(top_builddir)/ruamoko/qwaq/qwaq-cmd$(EXEEXT) @@ -315,8 +323,6 @@ fstriangle_src = $(vkshaderpath)/fstriangle.vert fstriangle_c = $(vkshaderpath)/fstriangle.vert.spvc pushcolor_src = $(vkshaderpath)/pushcolor.frag pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc -shadow_src = $(vkshaderpath)/shadow.geom -shadow_c = $(vkshaderpath)/shadow.geom.spvc $(partphysicsc_c): $(partphysicsc_src) $(partupdatec_c): $(partupdatec_src) @@ -378,8 +384,6 @@ $(fstriangle_c): $(fstriangle_src) $(pushcolor_c): $(pushcolor_src) -$(shadow_c): $(shadow_src) - vkshader_c = \ $(partphysicsc_c) \ $(partupdatec_c) \ @@ -446,6 +450,7 @@ BUILT_SOURCES += $(shader_gen) EXTRA_DIST += \ $(deferred_src) \ + $(shadow_src) \ $(forward_src) \ $(pipeline_src) \ libs/video/renderer/vulkan/vkparse.plist \ diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 0f7e19a7b..a567b735c 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -102,8 +102,6 @@ static #include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc" static #include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc" -static -#include "libs/video/renderer/vulkan/shader/shadow.geom.spvc" typedef struct shaderdata_s { const char *name; @@ -144,7 +142,6 @@ static shaderdata_t builtin_shaders[] = { { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, - { "shadow.geom", shadow_geom, sizeof (shadow_geom) }, {} }; diff --git a/libs/video/renderer/vulkan/shadow.plist b/libs/video/renderer/vulkan/shadow.plist index 93eb8da31..5db23260c 100644 --- a/libs/video/renderer/vulkan/shadow.plist +++ b/libs/video/renderer/vulkan/shadow.plist @@ -23,10 +23,7 @@ viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; format = $properties.images.shadow.format; components = { - r = identity; - g = identity; - b = identity; - a = identity; + r = identity; g = identity; b = identity; a = identity; }; subresourceRange = { aspectMask = depth; @@ -37,7 +34,7 @@ }; framebuffer = { renderPass = $properties.renderpass; - attachments = (shadown); + attachments = (shadow); width = $properties.images.shadow.extent.width; height = $properties.images.shadow.extent.height; layers = $properties.images.shadow.arrayLayers; @@ -46,9 +43,12 @@ { depthStencil = { depth = 1; stencil = 0; }; }, ); renderpass = { + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0xffffffff); + }); attachments = ( { - format = $properties.images.depth.format; + format = $properties.images.shadow.format; samples = 1; loadOp = dont_care; storeOp = store; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index 445c9fc34..5ed901e9e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -11,6 +11,7 @@ @interface Struct: Type { string outname; + int write_symtab; } -(void) queueFieldTypes; -(qfot_var_t *)findField:(string) fieldName; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 077b19cfb..ec6530b5e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -84,6 +84,7 @@ PLItem *new_name = [field_dict getObjectForKey:".name"]; Array *field_defs = [Array array]; int have_sType = 0; + int have_pNext = 0; if ([parse string] == "skip") { return; @@ -97,6 +98,10 @@ if (field.name == "sType") { have_sType = 1; } + if (field.name == "pNext") { + have_pNext = 1; + write_symtab = 1; + } } if (field_dict) { PLItem *field_keys = [field_dict allKeys]; @@ -133,6 +138,11 @@ fprintf (output_file, "\t{\"@inherit\", 0, QFString, parse_inherit, &%s_fields},\n", [self outname]); + if (have_pNext) { + fprintf (output_file, + "\t{\"@next\", field_offset (%s, pNext), " + "QFArray, parse_next, 0},", [self outname]); + } for (int i = [field_defs count]; i-- > 0; ) { FieldDef *field_def = [field_defs objectAtIndex:i]; [field_def writeField]; @@ -140,14 +150,14 @@ fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); - fprintf (header_file, "int parse_%s (const plfield_t *field," + fprintf (header_file, "int %s (const plfield_t *field," " const plitem_t *item, void *data, plitem_t *messages," " void *context);\n", - [self outname]); - fprintf (output_file, "int parse_%s (const plfield_t *field," + [self parseFunc]); + fprintf (output_file, "int %s (const plfield_t *field," " const plitem_t *item, void *data, plitem_t *messages," " void *context)\n", - [self outname]); + [self parseFunc]); fprintf (output_file, "{\n"); if (have_sType) { fprintf (output_file, "\t((%s *) data)->sType", [self outname]); @@ -162,6 +172,12 @@ " context);\n", [self outname], [self outname]); fprintf (output_file, "}\n"); + if (have_pNext) { + fprintf (output_file, "static parserref_t %s_parser = ", + [self outname]); + fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", + [self outname], [self parseFunc], [self outname]); + } fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self outname]); if (field_defs) { @@ -216,6 +232,12 @@ -(void) writeSymtabEntry { + if (!write_symtab || [parse string] == "skip") { + return; + } + fprintf (output_file, + "\tHash_Add (parser_table, &%s_parser);\n", + [self outname]); } -(string) outname diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 9ae5d8b40..c75681f8b 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -56,6 +56,12 @@ typedef struct parseres_s { size_t offset; } parseres_t; +typedef struct parseref_s { + const char *name; + plparser_t parse; + size_t size; +} parserref_t; + typedef struct handleref_s { char *name; uint64_t handle; @@ -169,6 +175,33 @@ parse_basic (const plfield_t *field, const plitem_t *item, return ret; } +static int +parse_int32_t (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + int ret = 1; + // use size_t (and cexpr_size_t) for val so references to array sizes + // can be used + size_t val = 0; + exprval_t result = { &cexpr_size_t, &val }; + exprctx_t ectx = *((parsectx_t *) context)->ectx; + ectx.result = &result; + const char *valstr = PL_String (item); + //Sys_MaskPrintf (SYS_vulkan_parse, + // "parse_int32_t: %s %zd %d %p %p %s\n", + // field->name, field->offset, field->type, field->parser, + // field->data, valstr); + ret = !cexpr_eval_string (valstr, &ectx); + if (!ret) { + PL_Message (messages, item, "error parsing %s: %s", + field->name, valstr); + } + *(int32_t *) data = val; + //Sys_MaskPrintf (SYS_vulkan_parse, " %d\n", *(int32_t *)data); + + return ret; +} + static int parse_uint32_t (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -393,6 +426,33 @@ parse_inherit (const plfield_t *field, const plitem_t *item, return ret; } +static hashtab_t *parser_table; + +static int +parse_next (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages, void *context) +{ + const char *type_name = PL_String (PL_ObjectAtIndex (item, 0)); + plitem_t *next_def = PL_ObjectAtIndex (item, 1); + + if (!type_name || PL_Type (next_def) != QFDictionary) { + PL_Message (messages, item, "invalid @next"); + return 0; + } + parserref_t *parser = Hash_Find (parser_table, type_name); + if (!parser) { + PL_Message (messages, item, "Invalid type for @next: %s", type_name); + return 0; + } + void *data_ptr = vkparse_alloc (context, parser->size); + memset (data_ptr, 0, parser->size); + if (!parser->parse (field, next_def, data_ptr, messages, context)) { + return 0; + } + *(void **) data = data_ptr; + return 1; +} + static int parse_RGBA (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *context) @@ -971,6 +1031,13 @@ enum_symtab_getkey (const void *e, void *unused) return enm->type->name; } +static const char * +parser_getkey (const void *e, void *unused) +{ + __auto_type parser = (const parserref_t *) e; + return parser->name; +} + static exprtab_t root_symtab = { .symbols = cexpr_lib_symbols, }; @@ -988,6 +1055,7 @@ QFV_InitParse (vulkan_ctx_t *ctx) { exprctx_t context = {}; enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, &ctx->hashctx); + parser_table = Hash_NewTable (61, parser_getkey, 0, 0, &ctx->hashctx); context.hashctx = &ctx->hashctx; vkgen_init_symtabs (&context); cexpr_init_symtab (&qfv_output_t_symtab, &context); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 4379d39c4..e2d622940 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -28,6 +28,8 @@ VkFramebufferCreateInfo, VkClearValue, VkPhysicalDeviceLimits, + VkRenderPassCreateInfo, + VkRenderPassMultiviewCreateInfo, ); parse = { VkSubpassDescription = { @@ -359,5 +361,22 @@ }; depthStencil = auto; }; + VkRenderPassMultiviewCreateInfo = { + viewMasks = { + type = (array, uint32_t); + size = subpassCount; + values = pViewMasks; + }; + viewOffsets = { + type = (array, int32_t); + size = dependencyCount; + values = pViewOffsets; + }; + correlationMasks = { + type = (array, uint32_t); + size = correlationMaskCount; + values = pCorrelationMasks; + }; + } } } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a3d299001..2cd5fa1fe 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -75,6 +75,10 @@ static exprsym_t builtin_plist_syms[] = { .value = (void *) #include "libs/video/renderer/vulkan/deferred.plc" }, + { .name = "shadow", + .value = (void *) +#include "libs/video/renderer/vulkan/shadow.plc" + }, { .name = "forward", .value = (void *) #include "libs/video/renderer/vulkan/forward.plc" From f04108ae3e0cbb3247dfbc51fcda6a82ce00c7f4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 May 2022 22:13:36 +0900 Subject: [PATCH 3008/3664] [vulkan] Switch to using vkGetPhysicalDeviceProperties2 Necessary for getting VkPhysicalDeviceMultiviewProperties (and others, but not at this time). --- include/QF/Vulkan/funclist.h | 2 +- include/QF/Vulkan/instance.h | 4 +++- libs/video/renderer/vulkan/device.c | 1 + libs/video/renderer/vulkan/instance.c | 14 +++++++++++--- libs/video/renderer/vulkan/staging.c | 2 +- libs/video/renderer/vulkan/vkparse.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 6 +++--- libs/video/renderer/vulkan/vulkan_lighting.c | 4 ++-- 8 files changed, 23 insertions(+), 12 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 94189143d..42da63794 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -22,7 +22,7 @@ GLOBAL_LEVEL_VULKAN_FUNCTION (vkCreateInstance) #endif INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumeratePhysicalDevices) -INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties2) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceQueueFamilyProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateDevice) diff --git a/include/QF/Vulkan/instance.h b/include/QF/Vulkan/instance.h index 692dd5964..c4b18a73a 100644 --- a/include/QF/Vulkan/instance.h +++ b/include/QF/Vulkan/instance.h @@ -42,7 +42,9 @@ typedef struct DARRAY_TYPE(const char *) qfv_debugstack_t; typedef struct qfv_physdev_s { struct qfv_instance_s *instance; VkPhysicalDevice dev; - VkPhysicalDeviceProperties properties; + VkPhysicalDeviceProperties2 properties2; + VkPhysicalDeviceProperties *properties; + VkPhysicalDeviceMultiviewProperties multiViewProperties; VkPhysicalDeviceMemoryProperties memory_properties; } qfv_physdev_t; diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 5dc2e331a..47df21745 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -151,6 +151,7 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) }; VkPhysicalDeviceFeatures features = { .geometryShader = 1, + .multiViewport = 1, }; VkDeviceCreateInfo dCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0, diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index 588ea4c34..562063e89 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -279,7 +279,15 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, qfv_physdev_t *dev = &inst->devices[i]; dev->instance = inst; dev->dev = physDev; - ifunc->vkGetPhysicalDeviceProperties (physDev, &dev->properties); + dev->properties2 = (VkPhysicalDeviceProperties2) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &dev->multiViewProperties, + }; + dev->multiViewProperties = (VkPhysicalDeviceMultiviewProperties) { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, + }; + ifunc->vkGetPhysicalDeviceProperties2 (physDev, &dev->properties2); + dev->properties = &dev->properties2.properties; ifunc->vkGetPhysicalDeviceMemoryProperties (physDev, &dev->memory_properties); } @@ -306,8 +314,8 @@ QFV_GetMaxSampleCount (qfv_physdev_t *physdev) { VkSampleCountFlagBits maxSamples = VK_SAMPLE_COUNT_64_BIT; VkSampleCountFlagBits counts; - counts = min (physdev->properties.limits.framebufferColorSampleCounts, - physdev->properties.limits.framebufferDepthSampleCounts); + counts = min (physdev->properties->limits.framebufferColorSampleCounts, + physdev->properties->limits.framebufferDepthSampleCounts); while (maxSamples && maxSamples > counts) { maxSamples >>= 1; } diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index 09b54954d..cf3073959 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -41,7 +41,7 @@ qfv_stagebuf_t * QFV_CreateStagingBuffer (qfv_device_t *device, const char *name, size_t size, VkCommandPool cmdPool) { - size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; qfv_devfuncs_t *dfunc = device->funcs; dstring_t *str = dstring_new (); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index c75681f8b..f9a462c0e 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1092,7 +1092,7 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {"physDevLimits", &VkPhysicalDeviceLimits_type, - &ctx->device->physDev->properties.limits }, + &ctx->device->physDev->properties->limits }, {QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties}, {} }; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 43dbd4a67..a3f7582bf 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -436,7 +436,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } } - size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; size_t atom_mask = atom - 1; size_t frames = bctx->frames.size; size_t index_buffer_size = index_count * frames * sizeof (uint32_t); @@ -1118,7 +1118,7 @@ Vulkan_Bsp_Flush (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; size_t atom_mask = atom - 1; size_t index_offset = bframe->index_offset; size_t index_size = bframe->index_count * sizeof (uint32_t); @@ -1424,7 +1424,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) size_t entid_count = Vulkan_Scene_MaxEntities (ctx); size_t entid_size = entid_count * sizeof (uint32_t); - size_t atom = device->physDev->properties.limits.nonCoherentAtomSize; + size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; size_t atom_mask = atom - 1; entid_size = (entid_size + atom_mask) & ~atom_mask; bctx->entid_buffer diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index cf22da875..414031f8f 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -362,7 +362,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->shadowWrite.dstBinding = 0; lframe->shadowWrite.descriptorCount = min (MaxLights, - device->physDev->properties.limits.maxPerStageDescriptorSamplers); + device->physDev->properties->limits.maxPerStageDescriptorSamplers); lframe->shadowWrite.pImageInfo = lframe->shadowInfo; } free (shadow_set); @@ -578,7 +578,7 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; qfv_physdev_t *physDev = device->physDev; - int maxLayers = physDev->properties.limits.maxImageArrayLayers; + int maxLayers = physDev->properties->limits.maxImageArrayLayers; lightingdata_t *ldata = lctx->ldata; light_t *lights = ldata->lights.a; int numLights = ldata->lights.size; From 78437c2c909899e784731ba1c4c5bf530811616c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 May 2022 23:15:51 +0900 Subject: [PATCH 3009/3664] [vulkan] Parse VkRenderPass directly QFV_CreateRenderPass doesn't support pNext and I don't particularly feel like making it do so at this stage (tempted to remove it). --- libs/video/renderer/vulkan/vkparse.c | 62 ++++------------------------ 1 file changed, 7 insertions(+), 55 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index f9a462c0e..a403dc7c1 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -978,46 +978,6 @@ exprtype_t vulkan_frameset_t_type = { .data = &vulkan_frameset_t_symtab, }; -typedef struct { - qfv_attachmentdescription_t *attachments; - qfv_subpassparametersset_t *subpasses; - qfv_subpassdependency_t *dependencies; -} vkparse_renderpass_t; - -static plelement_t parse_qfv_renderpass_attachments_data = { - QFDictionary, - sizeof (VkAttachmentDescription), - vkparse_alloc, - parse_VkAttachmentDescription, - 0, -}; - -static plelement_t parse_qfv_renderpass_subpasses_data = { - QFDictionary, - sizeof (VkSubpassDescription), - vkparse_alloc, - parse_VkSubpassDescription, - 0, -}; - -static plelement_t parse_qfv_renderpass_dependencies_data = { - QFDictionary, - sizeof (VkSubpassDependency), - vkparse_alloc, - parse_VkSubpassDependency, - 0, -}; - -static plfield_t renderpass_fields[] = { - { "attachments", field_offset(vkparse_renderpass_t,attachments), QFArray, - PL_ParseArray, &parse_qfv_renderpass_attachments_data }, - { "subpasses", field_offset(vkparse_renderpass_t,subpasses), QFArray, - PL_ParseArray, &parse_qfv_renderpass_subpasses_data }, - { "dependencies", field_offset(vkparse_renderpass_t,dependencies), QFArray, - PL_ParseArray, &parse_qfv_renderpass_dependencies_data }, - {} -}; - static hashtab_t * handlref_symtab (void (*free_func)(void*,void*), vulkan_ctx_t *ctx) { @@ -1118,33 +1078,25 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, return 1; } -static int -parse_qfv_renderpass (const plfield_t *field, const plitem_t *item, void *data, - plitem_t *messages, void *context) -{ - return PL_ParseStruct (renderpass_fields, item, data, messages, context); -} - VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) { memsuper_t *memsuper = new_memsuper (); qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; - vkparse_renderpass_t renderpass_data = {}; + VkRenderPassCreateInfo cInfo = {}; - if (!parse_object (ctx, memsuper, plist, parse_qfv_renderpass, - &renderpass_data, properties)) { + if (!parse_object (ctx, memsuper, plist, parse_VkRenderPassCreateInfo, + &cInfo, properties)) { delete_memsuper (memsuper); return 0; } VkRenderPass renderpass; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseRenderPass: %d", PL_Line (plist))); - renderpass = QFV_CreateRenderPass (device, - renderpass_data.attachments, - renderpass_data.subpasses, - renderpass_data.dependencies); + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseRenderPass: %d", + PL_Line (plist))); + dfunc->vkCreateRenderPass (device->dev, &cInfo, 0, &renderpass); qfvPopDebug (ctx); delete_memsuper (memsuper); From 6a7c2cb2a1a59e5cf90bf800fb0223ff8cf629c8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 May 2022 11:06:13 +0900 Subject: [PATCH 3010/3664] [vulkan] Clean out the old render pass creation code QFV_CreateRenderPass is no longer used, and QFV_CreateFramebuffer hasn't been used for a long time. The C file is still there for now but is basically empty. --- include/QF/Vulkan/renderpass.h | 40 +-------- libs/video/renderer/vulkan/renderpass.c | 106 ------------------------ 2 files changed, 1 insertion(+), 145 deletions(-) diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/renderpass.h index 9648e841e..ca14f889c 100644 --- a/include/QF/Vulkan/renderpass.h +++ b/include/QF/Vulkan/renderpass.h @@ -4,50 +4,12 @@ #include "QF/darray.h" #include "QF/simd/types.h" -typedef struct qfv_attachmentdescription_s - DARRAY_TYPE (VkAttachmentDescription) qfv_attachmentdescription_t; - -#define QFV_AllocAttachmentDescription(num, allocator) \ - DARRAY_ALLOCFIXED (qfv_attachmentdescription_t, num, allocator) - -typedef struct qfv_attachmentreference_s - DARRAY_TYPE (VkAttachmentReference) qfv_attachmentreference_t; - -#define QFV_AllocAttachmentReference(num, allocator) \ - DARRAY_ALLOCFIXED (qfv_attachmentreference_t, num, allocator) - -typedef struct qfv_subpassparametersset_s - DARRAY_TYPE (VkSubpassDescription) qfv_subpassparametersset_t; - -#define QFV_AllocSubpassParametersSet(num, allocator) \ - DARRAY_ALLOCFIXED (qfv_subpassparametersset_t, num, allocator) - -typedef struct qfv_subpassdependency_s - DARRAY_TYPE (VkSubpassDependency) qfv_subpassdependency_t; - -#define QFV_AllocSubpassDependencies(num, allocator) \ - DARRAY_ALLOCFIXED (qfv_subpassdependency_t, num, allocator) - typedef struct qfv_framebufferset_s DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t; #define QFV_AllocFrameBuffers(num, allocator) \ DARRAY_ALLOCFIXED (qfv_framebufferset_t, num, allocator) -struct qfv_device_s; -struct qfv_imageviewset_s; -VkRenderPass -QFV_CreateRenderPass (struct qfv_device_s *device, - qfv_attachmentdescription_t *attachments, - qfv_subpassparametersset_t *subpasses, - qfv_subpassdependency_t *dependencies); - -VkFramebuffer -QFV_CreateFramebuffer (struct qfv_device_s *device, - VkRenderPass renderPass, - struct qfv_imageviewset_s *attachments, - VkExtent2D, uint32_t layers); - typedef struct qfv_subpass_s { vec4f_t color; const char *name; @@ -57,7 +19,7 @@ typedef struct qfv_renderframe_s { struct vulkan_ctx_s *vulkan_ctx; struct qfv_renderpass_s *renderpass; VkSubpassContents subpassContents; - int subpassCount; + int subpassCount; qfv_subpass_t *subpassInfo; struct qfv_cmdbufferset_s *subpassCmdSets; } qfv_renderframe_t; diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/renderpass.c index f69c1bd96..e2f7ff2e9 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/renderpass.c @@ -33,109 +33,3 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/renderpass.h" - -VkRenderPass -QFV_CreateRenderPass (qfv_device_t *device, - qfv_attachmentdescription_t *attachments, - qfv_subpassparametersset_t *subpassparams, - qfv_subpassdependency_t *dependencies) -{ - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - if (developer & SYS_vulkan) { - Sys_Printf ("attachments: %zd\n", attachments->size); - for (size_t i = 0; i < attachments->size; i++) { - Sys_Printf (" attachment: %zd\n", i); - Sys_Printf (" flags: %x\n", attachments->a[i].flags); - Sys_Printf (" format: %d\n", attachments->a[i].format); - Sys_Printf (" samples: %x\n", attachments->a[i].samples); - Sys_Printf (" loadOp: %d\n", attachments->a[i].loadOp); - Sys_Printf (" storeOp: %d\n", attachments->a[i].storeOp); - Sys_Printf (" stencilLoadOp: %d\n", - attachments->a[i].stencilLoadOp); - Sys_Printf (" stencilStoreOp: %d\n", - attachments->a[i].stencilStoreOp); - Sys_Printf (" initialLayout: %d\n", - attachments->a[i].initialLayout); - Sys_Printf (" finalLayout: %d\n", - attachments->a[i].finalLayout); - } - Sys_Printf ("subpassparams: %zd\n", subpassparams->size); - for (size_t i = 0; i < subpassparams->size; i++) { - VkSubpassDescription *sp = &subpassparams->a[i]; - Sys_Printf (" flags: %x\n", sp->flags); - Sys_Printf (" piplineBindPoint: %d\n", sp->pipelineBindPoint); - Sys_Printf (" inputAttachmentCount: %d\n", - sp->inputAttachmentCount); - for (size_t j = 0; j < sp->inputAttachmentCount; j++) { - const VkAttachmentReference *ref = &sp->pInputAttachments[j]; - Sys_Printf (" c %d %d\n", ref->attachment, ref->layout); - } - Sys_Printf (" colorAttachmentCount: %d\n", - sp->colorAttachmentCount); - for (size_t j = 0; j < sp->colorAttachmentCount; j++) { - const VkAttachmentReference *ref = &sp->pColorAttachments[j]; - Sys_Printf (" c %d %d\n", ref->attachment, ref->layout); - } - if (sp->pResolveAttachments) { - for (size_t j = 0; j < sp->colorAttachmentCount; j++) { - const VkAttachmentReference *ref - = &sp->pResolveAttachments[j]; - Sys_Printf (" r %d %d\n", ref->attachment, - ref->layout); - } - } - Sys_Printf (" pDepthStencilAttachment: %p\n", - sp->pDepthStencilAttachment); - if (sp->pDepthStencilAttachment) { - const VkAttachmentReference *ref = sp->pDepthStencilAttachment; - Sys_Printf (" %d %d\n", ref->attachment, ref->layout); - } - Sys_Printf (" preserveAttachmentCount: %d\n", - sp->preserveAttachmentCount); - for (size_t j = 0; j < sp->preserveAttachmentCount; j++) { - Sys_Printf (" %d\n", sp->pPreserveAttachments[j]); - } - } - Sys_Printf ("dependencies: %zd\n", dependencies->size); - for (size_t i = 0; i < dependencies->size; i++) { - Sys_Printf (" srcSubpass: %d\n", dependencies->a[i].srcSubpass); - Sys_Printf (" dstSubpass: %d\n", dependencies->a[i].dstSubpass); - Sys_Printf (" srcStageMask: %x\n", dependencies->a[i].srcStageMask); - Sys_Printf (" dstStageMask: %x\n", dependencies->a[i].dstStageMask); - Sys_Printf (" srcAccessMask: %x\n", dependencies->a[i].srcAccessMask); - Sys_Printf (" dstAccessMask: %x\n", dependencies->a[i].dstAccessMask); - Sys_Printf (" dependencyFlags: %x\n", dependencies->a[i].dependencyFlags); - } - } - VkRenderPassCreateInfo createInfo = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 0, 0, - attachments->size, attachments->a, - subpassparams->size, subpassparams->a, - dependencies->size, dependencies->a, - }; - - VkRenderPass renderpass; - dfunc->vkCreateRenderPass (dev, &createInfo, 0, &renderpass); - return renderpass; -} - -VkFramebuffer -QFV_CreateFramebuffer (qfv_device_t *device, VkRenderPass renderPass, - qfv_imageviewset_t *attachments, - VkExtent2D extent, uint32_t layers) -{ - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - - VkFramebufferCreateInfo createInfo = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 0, 0, - renderPass, attachments->size, attachments->a, - extent.width, extent.height, layers, - }; - - VkFramebuffer framebuffer; - dfunc->vkCreateFramebuffer (dev, &createInfo, 0, &framebuffer); - return framebuffer; -} From 08f33d2f3a0091f8452e8b367b3654090ee44ee1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 May 2022 12:10:00 +0900 Subject: [PATCH 3011/3664] [vulkan] Rename the renderpass files I plan on moving the current hard-coded render pass creation from vulkan_vid_common and this maintains the (possibly silly) naming convention). --- include/QF/Makemodule.am | 2 +- include/QF/Vulkan/{renderpass.h => qf_renderpass.h} | 0 libs/video/renderer/Makemodule.am | 2 +- libs/video/renderer/vid_render_vulkan.c | 2 +- libs/video/renderer/vulkan/vkparse.c | 3 ++- libs/video/renderer/vulkan/vulkan_alias.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- libs/video/renderer/vulkan/vulkan_compose.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- libs/video/renderer/vulkan/vulkan_iqm.c | 2 +- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- libs/video/renderer/vulkan/vulkan_main.c | 3 +-- libs/video/renderer/vulkan/vulkan_matrices.c | 2 +- .../renderer/vulkan/{renderpass.c => vulkan_renderpass.c} | 2 +- libs/video/renderer/vulkan/vulkan_sprite.c | 2 +- libs/video/renderer/vulkan/vulkan_vid_common.c | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) rename include/QF/Vulkan/{renderpass.h => qf_renderpass.h} (100%) rename libs/video/renderer/vulkan/{renderpass.c => vulkan_renderpass.c} (96%) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 875262cf6..fff9fd24c 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -197,11 +197,11 @@ include_qf_vulkan = \ include/QF/Vulkan/qf_matrices.h \ include/QF/Vulkan/qf_model.h \ include/QF/Vulkan/qf_particles.h \ + include/QF/Vulkan/qf_renderpass.h \ include/QF/Vulkan/qf_scene.h \ include/QF/Vulkan/qf_sprite.h \ include/QF/Vulkan/qf_texture.h \ include/QF/Vulkan/qf_vid.h \ - include/QF/Vulkan/renderpass.h \ include/QF/Vulkan/scrap.h \ include/QF/Vulkan/shader.h \ include/QF/Vulkan/staging.h \ diff --git a/include/QF/Vulkan/renderpass.h b/include/QF/Vulkan/qf_renderpass.h similarity index 100% rename from include/QF/Vulkan/renderpass.h rename to include/QF/Vulkan/qf_renderpass.h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 41a940649..102d4a393 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -211,7 +211,6 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/memory.c \ libs/video/renderer/vulkan/pipeline.c \ libs/video/renderer/vulkan/projection.c \ - libs/video/renderer/vulkan/renderpass.c \ libs/video/renderer/vulkan/resource.c \ libs/video/renderer/vulkan/scrap.c \ libs/video/renderer/vulkan/shader.c \ @@ -229,6 +228,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ libs/video/renderer/vulkan/vulkan_particles.c \ + libs/video/renderer/vulkan/vulkan_renderpass.c \ libs/video/renderer/vulkan/vulkan_scene.c \ libs/video/renderer/vulkan/vulkan_sprite.c \ libs/video/renderer/vulkan/vulkan_texture.c \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index cce63d511..cae6db2ea 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -50,6 +50,7 @@ #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_particles.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_sprite.h" #include "QF/Vulkan/qf_texture.h" @@ -62,7 +63,6 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" #include "QF/Vulkan/staging.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/swapchain.h" #include "QF/ui/view.h" diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index a403dc7c1..344820e54 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -41,9 +41,10 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/pipeline.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/shader.h" +#include "QF/Vulkan/qf_renderpass.h" + #include "vid_vulkan.h" #define vkparse_internal diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index b9a683fc6..26e5b404e 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -42,11 +42,11 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/renderpass.h" #include "r_internal.h" #include "vid_vulkan.h" diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a3f7582bf..e73f920a0 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -57,6 +57,7 @@ #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" @@ -67,7 +68,6 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 6d8ad105e..52ff735e8 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -45,12 +45,12 @@ #include "QF/sys.h" #include "QF/Vulkan/qf_compose.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/renderpass.h" #include "r_internal.h" #include "vid_vulkan.h" diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index c042d814f..0712a50ca 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -52,6 +52,7 @@ #include "compat.h" #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" @@ -61,7 +62,6 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" #include "QF/ui/view.h" diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 3dd3261ff..f2491aca5 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -41,12 +41,12 @@ #include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/resource.h" #include "r_internal.h" diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 414031f8f..8da92aa58 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -56,6 +56,7 @@ #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_lighting.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" @@ -65,7 +66,6 @@ #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/staging.h" #include "compat.h" diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 698881205..8fa6a91e3 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -56,10 +56,9 @@ #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_particles.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_sprite.h" -//#include "QF/Vulkan/qf_textures.h" -#include "QF/Vulkan/renderpass.h" #include "mod_internal.h" #include "r_internal.h" diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 67765734f..e22f1ff3b 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -43,13 +43,13 @@ #include "QF/sys.h" #include "QF/va.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/staging.h" #include "r_internal.h" diff --git a/libs/video/renderer/vulkan/renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c similarity index 96% rename from libs/video/renderer/vulkan/renderpass.c rename to libs/video/renderer/vulkan/vulkan_renderpass.c index e2f7ff2e9..a3068d42a 100644 --- a/libs/video/renderer/vulkan/renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -32,4 +32,4 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" -#include "QF/Vulkan/renderpass.h" +#include "QF/Vulkan/qf_renderpass.h" diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index c8ed837b0..d5fa35454 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -54,6 +54,7 @@ #include "QF/scene/entity.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_sprite.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" @@ -62,7 +63,6 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/renderpass.h" #include "r_internal.h" #include "vid_vulkan.h" diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 2cd5fa1fe..fcd9919fc 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -46,7 +46,6 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" -#include "QF/Vulkan/renderpass.h" #include "QF/Vulkan/staging.h" #include "QF/Vulkan/swapchain.h" @@ -57,6 +56,7 @@ #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_vid.h" #include "r_internal.h" From e14e8050dce910fb8e0f47ff092895c3033b4d90 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 May 2022 12:22:34 +0900 Subject: [PATCH 3012/3664] [vulkan] Remove vkparse.hinc from vkparse.h Kind of silly having the vkparse_internal define when it was just bypassed anyway. --- libs/video/renderer/vulkan/vkparse.c | 3 +-- libs/video/renderer/vulkan/vkparse.h | 3 --- libs/video/renderer/vulkan/vulkan_vid_common.c | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 344820e54..1b93e0d80 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -47,9 +47,8 @@ #include "vid_vulkan.h" -#define vkparse_internal #include "vkparse.h" -#undef vkparse_internal +#include "libs/video/renderer/vulkan/vkparse.hinc" typedef struct parseres_s { const char *name; diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 730094e3b..52ab2cf47 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -10,9 +10,6 @@ typedef struct parsectx_s { #include "QF/cexpr.h" #include "QF/plist.h" -#ifdef vkparse_internal -#include "libs/video/renderer/vulkan/vkparse.hinc" -#endif #define QFV_PROPERTIES "properties" diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index fcd9919fc..7a6149d9e 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -63,7 +63,6 @@ #include "vid_vulkan.h" #include "vkparse.h" - #include "libs/video/renderer/vulkan/vkparse.hinc" static exprsym_t builtin_plist_syms[] = { From 3603fa75cd27ec111b56549ad065047ff9bda7fc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 May 2022 15:58:22 +0900 Subject: [PATCH 3013/3664] [vulkan] Make Vulkan_CreateRenderPass more generally useful It now lives in vulkan_renderpass.c and takes most of its parameters from plist configs (just the name (which is used to find the config), output spec, and draw function from C). Even the debug colors and names are taken from the config. --- include/QF/Vulkan/qf_renderpass.h | 17 +- include/QF/Vulkan/qf_vid.h | 4 +- include/vid_vulkan.h | 2 +- libs/video/renderer/vid_render_vulkan.c | 2 +- libs/video/renderer/vulkan/deferred.plist | 12 +- libs/video/renderer/vulkan/qfpipeline.plist | 2 +- libs/video/renderer/vulkan/vkgen/vulkan.r | 8 +- libs/video/renderer/vulkan/vkparse.c | 64 ++++- libs/video/renderer/vulkan/vkparse.h | 6 +- libs/video/renderer/vulkan/vkparse.plist | 18 +- .../video/renderer/vulkan/vulkan_renderpass.c | 238 ++++++++++++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 230 +---------------- 12 files changed, 374 insertions(+), 229 deletions(-) diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index ca14f889c..8a4d68a1b 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -15,6 +15,9 @@ typedef struct qfv_subpass_s { const char *name; } qfv_subpass_t; +typedef struct qfv_subpassset_s + DARRAY_TYPE (qfv_subpass_t) qfv_subpassset_t; + typedef struct qfv_renderframe_s { struct vulkan_ctx_s *vulkan_ctx; struct qfv_renderpass_s *renderpass; @@ -30,6 +33,8 @@ typedef struct qfv_renderframeset_s typedef struct clearvalueset_s DARRAY_TYPE (VkClearValue) clearvalueset_t; +typedef void (*qfv_draw_t) (qfv_renderframe_t *rFrame); + typedef struct qfv_renderpass_s { vec4f_t color; // for debugging const char *name; // for debugging @@ -44,9 +49,19 @@ typedef struct qfv_renderpass_s { VkViewport viewport; VkRect2D scissor; + size_t subpassCount; + qfv_subpassset_t *subpass_info; qfv_renderframeset_t frames; - void (*draw) (qfv_renderframe_t *rFrame); + qfv_draw_t draw; } qfv_renderpass_t; +struct qfv_output_s; +qfv_renderpass_t *Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx, + const char *name, + struct qfv_output_s *output, + qfv_draw_t draw); +void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx, + qfv_renderpass_t *renderpass); + #endif//__QF_Vulkan_renderpass_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index df818603f..04e4a49d6 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -61,7 +61,7 @@ struct vulkan_ctx_s; void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateCapture (struct vulkan_ctx_s *ctx); -void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); +void Vulkan_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); @@ -85,4 +85,6 @@ struct entity_s; void Vulkan_BeginEntityLabel (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd, struct entity_s *ent); +struct plitem_s *Vulkan_GetConfig (struct vulkan_ctx_s *ctx, const char *name); + #endif // __QF_Vulkan_vid_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 749047e24..fc6dcc463 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -98,7 +98,7 @@ typedef struct vulkan_ctx_s { int window_width; int window_height; - //FIXME not sure I like it being here (also, type name) + //FIXME this is for the parser qfv_output_t output; #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index cae6db2ea..720813da3 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -89,7 +89,7 @@ vulkan_R_Init (void) Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); - Vulkan_CreateRenderPass (vulkan_ctx); + Vulkan_CreateRenderPasses (vulkan_ctx); Vulkan_Texture_Init (vulkan_ctx); Vulkan_Matrix_Init (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/deferred.plist index f846b1799..de793c6e9 100644 --- a/libs/video/renderer/vulkan/deferred.plist +++ b/libs/video/renderer/vulkan/deferred.plist @@ -99,7 +99,7 @@ }; }; framebuffer = { - renderPass = $properties.renderpass; + renderPass = deferred; attachments = (depth, color, emission, normal, position, opaque, translucent, $output.view); width = $output.extent.width; @@ -125,6 +125,16 @@ initialLayout = undefined; finalLayout = color_attachment_optimal; }; + info = { + color = "[0, 1, 0, 1]"; + subpass_info = ( + { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, + { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, + { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, + { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, + { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, + ); + }; renderpass = { attachments = ( { diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index accc4e366..1bc3618be 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -672,7 +672,7 @@ dynamic = { dynamicState = ( viewport, scissor ); }; - renderPass = renderpass; + renderPass = deferred; }; depth_base = { @inherit = $properties.pipelines.base; diff --git a/libs/video/renderer/vulkan/vkgen/vulkan.r b/libs/video/renderer/vulkan/vkgen/vulkan.r index b42b8e75c..9d2a20a4c 100644 --- a/libs/video/renderer/vulkan/vkgen/vulkan.r +++ b/libs/video/renderer/vulkan/vkgen/vulkan.r @@ -1,3 +1,9 @@ #define __x86_64__ #include -#include "QF/Vulkan/swapchain.h" + +//FIXME copy of qfv_subpass_t in qf_renderpass.h +//except it doesn't really matter because a custom spec is used +typedef struct qfv_subpass_s { + vec4 color; + string name; +} qfv_subpass_t; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 1b93e0d80..c6da43b55 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -531,7 +531,7 @@ parse_VkRenderPass (const plitem_t *item, void **data, // path not guaranteed to survive cexpr_eval_string due to va path = resource_path (ctx, 0, name); - QFV_AddHandle (ctx->setLayouts, path, (uint64_t) setLayout); + QFV_AddHandle (ctx->renderpasses, path, (uint64_t) setLayout); } return ret; } @@ -1516,3 +1516,65 @@ QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) delete_memsuper (memsuper); return cv; } + +static int +parse_subpassset (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages, void *context) +{ + plelement_t element = { + QFDictionary, + sizeof (qfv_subpass_t), + vkparse_alloc, + parse_qfv_subpass_t, + 0, + }; + plfield_t f = { 0, 0, 0, 0, &element }; + + if (!PL_ParseArray (&f, item, data, messages, context)) { + return 0; + } + return 1; +} + +qfv_subpassset_t * +QFV_ParseSubpasses (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) +{ + qfv_subpassset_t *sp = 0; + memsuper_t *memsuper = new_memsuper (); + qfv_subpassset_t *subpasses = 0; + + if (parse_object (ctx, memsuper, plist, parse_subpassset, &subpasses, + properties)) { + sp = DARRAY_ALLOCFIXED (qfv_subpassset_t, subpasses->size, malloc); + memcpy (sp->a, subpasses->a, sp->size * sizeof (sp->a[0])); + // the name is in memsuper which is about to be freed + for (size_t i = 0; i < sp->size; i++) { + sp->a[i].name = strdup (sp->a[i].name); + } + } + delete_memsuper (memsuper); + return sp; +} + +static int +parse_rgba (const plfield_t *field, const plitem_t *item, void *data, + plitem_t *messages, void *context) +{ + return parse_RGBA (item, &data, messages, context); +} + +int +QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, + plitem_t *properties) +{ + memsuper_t *memsuper = new_memsuper (); + int ret = 0; + vec4f_t color; + + if (parse_object (ctx, memsuper, plist, parse_rgba, &color, properties)) { + memcpy (rgba, &color, sizeof (color)); + ret = 1; + } + delete_memsuper (memsuper); + return ret; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 52ab2cf47..101dfdad4 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -49,5 +49,9 @@ struct clearvalueset_s *QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties); - +struct qfv_subpassset_s *QFV_ParseSubpasses (vulkan_ctx_t *ctx, + plitem_t *plist, + plitem_t *properties); +int QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, + plitem_t *properties); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index e2d622940..b65e1b53f 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -30,6 +30,8 @@ VkPhysicalDeviceLimits, VkRenderPassCreateInfo, VkRenderPassMultiviewCreateInfo, + + qfv_subpass_t, ); parse = { VkSubpassDescription = { @@ -377,6 +379,18 @@ size = correlationMaskCount; values = pCorrelationMasks; }; - } - } + }; + + qfv_subpass_s = { + .name = qfv_subpass_t; + color = { + type = (custom, QFString, parse_RGBA); + fields = (color); + }; + name = { + type = string; + string = name; + }; + }; + }; } diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index a3068d42a..de32ead05 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -29,7 +29,245 @@ #endif #include "QF/cvar.h" +#include "QF/hash.h" +#include "QF/plist.h" +#include "QF/va.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" +#include "QF/Vulkan/swapchain.h" #include "QF/Vulkan/qf_renderpass.h" + +#include "vid_vulkan.h" +#include "vkparse.h" + +static plitem_t * +get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name) +{ + if (!rp->renderpassDef) { + rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); + } + + plitem_t *item = rp->renderpassDef; + if (!item || !(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading %s\n", name); + } else { + Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name); + } + return item; +} + +static size_t +get_image_size (VkImage image, qfv_device_t *device) +{ + qfv_devfuncs_t *dfunc = device->funcs; + size_t size; + size_t align; + + VkMemoryRequirements requirements; + dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements); + size = requirements.size; + align = requirements.alignment - 1; + size = (size + align) & ~(align); + return size; +} + +static void +create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +{ + qfv_device_t *device = ctx->device; + + plitem_t *item = get_rp_item (ctx, rp, "images"); + if (!item) { + return; + } + + __auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef); + rp->attachment_images = images; + size_t memSize = 0; + for (size_t i = 0; i < images->size; i++) { + memSize += get_image_size (images->a[i], device); + } + VkDeviceMemory mem; + mem = QFV_AllocImageMemory (device, images->a[0], + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + memSize, 0); + rp->attachmentMemory = mem; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + mem, "memory:framebuffers"); + size_t offset = 0; + for (size_t i = 0; i < images->size; i++) { + QFV_BindImageMemory (device, images->a[i], mem, offset); + offset += get_image_size (images->a[i], device); + } + + item = get_rp_item (ctx, rp, "imageViews"); + if (!item) { + return; + } + + __auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef); + rp->attachment_views = views; + + item = get_rp_item (ctx, rp, "framebuffer"); + if (!item) { + return; + } + + rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, + malloc); + for (size_t i = 0; i < rp->framebuffers->size; i++) { + ctx->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[i], + .format = ctx->swapchain->format, + }; + rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, + rp->renderpassDef); + } +} + +static void +init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, + qfv_renderframe_t *rFrame) +{ + rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; + rFrame->vulkan_ctx = ctx; + rFrame->renderpass = rp; + rFrame->subpassCount = rp->subpassCount; + if (rp->subpass_info) { + rFrame->subpassInfo = rp->subpass_info->a; + } + rFrame->subpassCmdSets = malloc (rp->subpassCount + * sizeof (qfv_cmdbufferset_t)); + for (size_t j = 0; j < rp->subpassCount; j++) { + DARRAY_INIT (&rFrame->subpassCmdSets[j], 4); + } +} + +static void +destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + for (size_t i = 0; i < rp->attachment_views->size; i++) { + dfunc->vkDestroyImageView (device->dev, rp->attachment_views->a[i], 0); + } + for (size_t i = 0; i < rp->attachment_images->size; i++) { + dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); + } + dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); + + free (rp->attachment_images); + free (rp->attachment_views); +} + +static void +destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +{ + for (size_t i = 0; i < rp->frames.size; i++) { + __auto_type rFrame = &rp->frames.a[i]; + for (int j = 0; j < rFrame->subpassCount; j++) { + DARRAY_CLEAR (&rFrame->subpassCmdSets[j]); + } + free (rFrame->subpassCmdSets); + } +} + +static void +destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + for (size_t i = 0; i < rp->framebuffers->size; i++) { + dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0); + } + free (rp->framebuffers); +} + +qfv_renderpass_t * +Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, + qfv_output_t *output, qfv_draw_t draw) +{ + plitem_t *item; + + qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); + + rp->name = name; + + plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass"); + hashtab_t *tab = ctx->renderpasses; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); + __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); + if (renderpass) { + rp->renderpass = renderpass; + } else { + ctx->output = *output; + rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, rp->renderpassDef); + QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, + rp->renderpass, va (ctx->va_ctx, "renderpass:%s", + name)); + } + rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, "subpasses")); + plitem_t *rp_info = get_rp_item (ctx, rp, "info"); + if (rp_info) { + plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_info"); + if (subpass_info) { + rp->subpass_info = QFV_ParseSubpasses (ctx, subpass_info, + rp->renderpassDef); + if (rp->subpass_info->size > rp->subpassCount) { + Sys_Printf ("warning:%s:%d: insufficient entries in " + "subpass_info\n", name, PL_Line (subpass_info)); + } + } + + plitem_t *color = PL_ObjectForKey (rp_info, "color"); + if (color) { + QFV_ParseRGBA (ctx, (float *)&rp->color, color, rp->renderpassDef); + } + } + + int width = output->extent.width; + int height = output->extent.height; + rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; + rp->scissor = (VkRect2D) { {0, 0}, {width, height} }; + + DARRAY_INIT (&rp->frames, 4); + DARRAY_RESIZE (&rp->frames, ctx->frames.size); + for (size_t i = 0; i < rp->frames.size; i++) { + init_renderframe (ctx, rp, &rp->frames.a[i]); + } + + create_attachements (ctx, rp); + + item = get_rp_item (ctx, rp, "clearValues"); + rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef); + + rp->draw = draw; + + return rp; +} + +void +Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + PL_Free (renderpass->renderpassDef); + + destroy_attachments (ctx, renderpass); + dfunc->vkDestroyRenderPass (device->dev, renderpass->renderpass, 0); + destroy_renderframes (ctx, renderpass); + destroy_framebuffers (ctx, renderpass); + + DARRAY_CLEAR (&renderpass->frames); + free (renderpass->clearValues); + free (renderpass); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 7a6149d9e..fa9d5cfbf 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -317,8 +317,8 @@ build_configs (vulkan_ctx_t *ctx) cexpr_init_symtab (&builtin_configs, &ectx); } -static plitem_t * -get_builtin_config (vulkan_ctx_t *ctx, const char *name) +plitem_t * +Vulkan_GetConfig (vulkan_ctx_t *ctx, const char *name) { if (!builtin_configs.tab) { build_configs (ctx); @@ -353,7 +353,7 @@ static plitem_t * qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) { if (!ctx->pipelineDef) { - ctx->pipelineDef = get_builtin_config (ctx, "qfpipeline"); + ctx->pipelineDef = Vulkan_GetConfig (ctx, "qfpipeline"); } plitem_t *item = ctx->pipelineDef; @@ -365,37 +365,6 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) return item; } -static plitem_t * -qfv_load_renderpass (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name) -{ - if (!rp->renderpassDef) { - rp->renderpassDef = get_builtin_config (ctx, "deferred"); - } - - plitem_t *item = rp->renderpassDef; - if (!item || !(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading %s\n", name); - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name); - } - return item; -} - -static size_t -get_image_size (VkImage image, qfv_device_t *device) -{ - qfv_devfuncs_t *dfunc = device->funcs; - size_t size; - size_t align; - - VkMemoryRequirements requirements; - dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements); - size = requirements.size; - align = requirements.alignment - 1; - size = (size + align) & ~(align); - return size; -} - static void renderpass_draw (qfv_renderframe_t *rFrame) { @@ -406,199 +375,24 @@ renderpass_draw (qfv_renderframe_t *rFrame) Vulkan_Compose_Draw (rFrame); } -static void -create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) -{ - qfv_device_t *device = ctx->device; - - plitem_t *item = qfv_load_renderpass (ctx, rp, "images"); - if (!item) { - return; - } - - __auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef); - rp->attachment_images = images; - size_t memSize = 0; - for (size_t i = 0; i < images->size; i++) { - memSize += get_image_size (images->a[i], device); - } - VkDeviceMemory mem; - mem = QFV_AllocImageMemory (device, images->a[0], - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - memSize, 0); - rp->attachmentMemory = mem; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - mem, "memory:framebuffers"); - size_t offset = 0; - for (size_t i = 0; i < images->size; i++) { - QFV_BindImageMemory (device, images->a[i], mem, offset); - offset += get_image_size (images->a[i], device); - } - - item = qfv_load_renderpass (ctx, rp, "imageViews"); - if (!item) { - return; - } - - __auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef); - rp->attachment_views = views; - - item = qfv_load_renderpass (ctx, rp, "framebuffer"); - if (!item) { - return; - } - - rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, - malloc); - for (size_t i = 0; i < rp->framebuffers->size; i++) { - ctx->output = (qfv_output_t) { - .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[i], - .format = ctx->swapchain->format, - }; - rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, - rp->renderpassDef); - } -} - -static void -init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, - qfv_renderframe_t *rFrame) -{ - // FIXME should not be hard-coded - static qfv_subpass_t subpass_info[] = { - { .name = "depth", .color = { 0.5, 0.5, 0.5, 1} }, - { .name = "translucent", .color = { 0.25, 0.25, 0.6, 1} }, - { .name = "g-buffef", .color = { 0.3, 0.7, 0.3, 1} }, - { .name = "lighting", .color = { 0.8, 0.8, 0.8, 1} }, - { .name = "compose", .color = { 0.7, 0.3, 0.3, 1} }, - }; - - rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; - rFrame->vulkan_ctx = ctx; - rFrame->renderpass = rp; - rFrame->subpassCount = QFV_NumPasses; - rFrame->subpassInfo = subpass_info; //FIXME - rFrame->subpassCmdSets = malloc (QFV_NumPasses - * sizeof (qfv_cmdbufferset_t)); - for (int j = 0; j < QFV_NumPasses; j++) { - DARRAY_INIT (&rFrame->subpassCmdSets[j], 4); - } -} - void -Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) +Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) { - const char *name = "renderpass";//FIXME - plitem_t *item; - - qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); - - rp->name = name; - rp->color = (vec4f_t) { 0, 1, 0, 1 }; //FIXME - - hashtab_t *tab = ctx->renderpasses; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); - __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); - if (renderpass) { - rp->renderpass = renderpass; - } else { - ctx->output = (qfv_output_t) { - .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[0], - .format = ctx->swapchain->format, - }; - item = qfv_load_renderpass (ctx, rp, name); - rp->renderpass = QFV_ParseRenderPass (ctx, item, rp->renderpassDef); - QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, - rp->renderpass, va (ctx->va_ctx, "renderpass:%s", - name)); - } - - int width = ctx->window_width; - int height = ctx->window_height; - rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; - rp->scissor = (VkRect2D) { {0, 0}, {width, height} }; - - DARRAY_INIT (&rp->frames, 4); - DARRAY_RESIZE (&rp->frames, ctx->frames.size); - for (size_t i = 0; i < rp->frames.size; i++) { - init_renderframe (ctx, rp, &rp->frames.a[i]); - } - - create_attachements (ctx, rp); - - item = qfv_load_renderpass (ctx, rp, "clearValues"); - rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef); - - rp->draw = renderpass_draw; - + qfv_output_t output = { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[0], + .format = ctx->swapchain->format, + }; + __auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred", + &output, renderpass_draw); DARRAY_APPEND (&ctx->renderPasses, rp); } -static void -destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - for (size_t i = 0; i < rp->attachment_views->size; i++) { - dfunc->vkDestroyImageView (device->dev, rp->attachment_views->a[i], 0); - } - for (size_t i = 0; i < rp->attachment_images->size; i++) { - dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); - } - dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); - - free (rp->attachment_images); - free (rp->attachment_views); -} - -static void -destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) -{ - for (size_t i = 0; i < rp->frames.size; i++) { - __auto_type rFrame = &rp->frames.a[i]; - for (int j = 0; j < rFrame->subpassCount; j++) { - DARRAY_CLEAR (&rFrame->subpassCmdSets[j]); - } - free (rFrame->subpassCmdSets); - } -} - -static void -destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - for (size_t i = 0; i < rp->framebuffers->size; i++) { - dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0); - } - free (rp->framebuffers); -} - void Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - for (size_t i = 0; i < ctx->renderPasses.size; i++) { - __auto_type rp = ctx->renderPasses.a[i]; - - PL_Free (rp->renderpassDef); - - destroy_attachments (ctx, rp); - dfunc->vkDestroyRenderPass (device->dev, rp->renderpass, 0); - destroy_renderframes (ctx, rp); - destroy_framebuffers (ctx, rp); - - DARRAY_CLEAR (&rp->frames); - free (rp->clearValues); - free (rp); + Vulkan_DestroyRenderPass (ctx, ctx->renderPasses.a[i]); } } From e1c4428c8e0bcd8fbeac5c8d60325a07641d5fa1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 May 2022 16:12:42 +0900 Subject: [PATCH 3014/3664] [vulkan] Set source item for cexpr errors It's always nice getting at least line numbers from an error message (even if I still have to hunt for the right source "file"). --- libs/video/renderer/vulkan/vkparse.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index c6da43b55..642f0d00d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -156,6 +156,7 @@ parse_basic (const plfield_t *field, const plitem_t *item, exprctx_t ectx = *((parsectx_t *) context)->ectx; exprval_t result = { etype, data }; ectx.result = &result; + ectx.item = item; const char *valstr = PL_String (item); //Sys_MaskPrintf (SYS_vulkan_parse, "parse_basic: %s %zd %d %p %p: %s\n", // field->name, field->offset, field->type, field->parser, @@ -186,6 +187,7 @@ parse_int32_t (const plfield_t *field, const plitem_t *item, exprval_t result = { &cexpr_size_t, &val }; exprctx_t ectx = *((parsectx_t *) context)->ectx; ectx.result = &result; + ectx.item = item; const char *valstr = PL_String (item); //Sys_MaskPrintf (SYS_vulkan_parse, // "parse_int32_t: %s %zd %d %p %p %s\n", @@ -213,6 +215,7 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, exprval_t result = { &cexpr_size_t, &val }; exprctx_t ectx = *((parsectx_t *) context)->ectx; ectx.result = &result; + ectx.item = item; const char *valstr = PL_String (item); //Sys_MaskPrintf (SYS_vulkan_parse, "parse_uint32_t: %s %zd %d %p %p: %s\n", // field->name, field->offset, field->type, field->parser, @@ -268,6 +271,7 @@ parse_reference (const plitem_t *item, const char *type, plitem_t *messages, plitem_t *refItem = 0; exprval_t result = { &cexpr_plitem, &refItem }; ectx.result = &result; + ectx.item = item; const char *name = PL_String (item); if (cexpr_eval_string (name, &ectx)) { PL_Message (messages, item, "not a %s reference", type); @@ -416,6 +420,7 @@ parse_inherit (const plfield_t *field, const plitem_t *item, plitem_t *inheritItem = 0; exprval_t result = { &cexpr_plitem, &inheritItem }; ectx.result = &result; + ectx.item = item; const char *inheritstr = PL_String (item); Sys_MaskPrintf (SYS_vulkan_parse, "parse_inherit: %s\n", inheritstr); int ret = !cexpr_eval_string (inheritstr, &ectx); @@ -461,6 +466,7 @@ parse_RGBA (const plitem_t *item, void **data, exprctx_t ectx = *context->ectx; exprval_t result = { &cexpr_vector, data[0] }; ectx.result = &result; + ectx.item = item; const char *valstr = PL_String (item); Sys_MaskPrintf (SYS_vulkan_parse, "parse_RGBA: %s\n", valstr); ret = !cexpr_eval_string (valstr, &ectx); @@ -523,6 +529,7 @@ parse_VkRenderPass (const plitem_t *item, void **data, plitem_t *setItem = 0; exprval_t result = { &cexpr_plitem, &setItem }; ectx.result = &result; + ectx.item = item; ret = !cexpr_eval_string (path, &ectx); if (ret) { VkRenderPass setLayout; @@ -583,6 +590,7 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, plitem_t *setItem = 0; exprval_t result = { &cexpr_plitem, &setItem }; ectx.result = &result; + ectx.item = item; ret = !cexpr_eval_string (path, &ectx); if (ret) { VkDescriptorSetLayout setLayout; @@ -618,6 +626,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, plitem_t *setItem = 0; exprval_t result = { &cexpr_plitem, &setItem }; ectx.result = &result; + ectx.item = item; ret = !cexpr_eval_string (path, &ectx); if (ret) { VkPipelineLayout layout; @@ -652,6 +661,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, plitem_t *imageItem = 0; exprval_t result = { &cexpr_plitem, &imageItem }; ectx.result = &result; + ectx.item = item; ret = !cexpr_eval_string (path, &ectx); if (ret) { VkImage image; @@ -695,6 +705,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, exprval_t *value = 0; exprval_t result = { &cexpr_exprval, &value }; ectx.result = &result; + ectx.item = item; ret = !cexpr_eval_string (path, &ectx); plitem_t *imageViewItem = 0; @@ -924,6 +935,7 @@ parse_specialization_data (const plitem_t *item, void **data, ectx.parent = ((parsectx_t *)context)->ectx; ectx.symtab = &data_array_symtab; ectx.result = &result; + ectx.item = item; const char *valstr = PL_String (item); //Sys_MaskPrintf (SYS_vulkan_parse, // "parse_specialization_data: %s %zd %d %p %p %s\n", From 3b72c9847a2558d969aff317b07f095ef65fb3de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 May 2022 17:28:24 +0900 Subject: [PATCH 3015/3664] [vulkan] Add list of views to qfv_output_t I'm not sure I like it, but it was an easy solution to dealing with per-frame views when setting up a renderpass that has a framebuffer spec. --- include/vid_vulkan.h | 1 + libs/video/renderer/vulkan/vulkan_renderpass.c | 6 +----- libs/video/renderer/vulkan/vulkan_vid_common.c | 7 ++++--- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index fc6dcc463..95ace93b0 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -14,6 +14,7 @@ typedef struct qfv_output_s { VkExtent2D extent; VkImageView view; VkFormat format; + VkImageView *view_list; // per frame } qfv_output_t; typedef struct vulkan_frame_s { diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index de32ead05..df6cbe2cb 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -119,11 +119,7 @@ create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, malloc); for (size_t i = 0; i < rp->framebuffers->size; i++) { - ctx->output = (qfv_output_t) { - .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[i], - .format = ctx->swapchain->format, - }; + ctx->output.view = ctx->output.view_list[i]; rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, rp->renderpassDef); } diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index fa9d5cfbf..d87e4ce72 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -379,9 +379,10 @@ void Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) { qfv_output_t output = { - .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[0], - .format = ctx->swapchain->format, + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[0], + .format = ctx->swapchain->format, + .view_list = ctx->swapchain->imageViews->a, }; __auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred", &output, renderpass_draw); From e45867d335fa153d95fa28ac801481aebc8a2633 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 May 2022 17:29:48 +0900 Subject: [PATCH 3016/3664] [vulkan] Fix some segfaults for render passes with no framebuffer specs --- libs/video/renderer/vulkan/vulkan_renderpass.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index df6cbe2cb..688050427 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -149,11 +149,16 @@ destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - for (size_t i = 0; i < rp->attachment_views->size; i++) { - dfunc->vkDestroyImageView (device->dev, rp->attachment_views->a[i], 0); + if (rp->attachment_views) { + for (size_t i = 0; i < rp->attachment_views->size; i++) { + dfunc->vkDestroyImageView (device->dev, + rp->attachment_views->a[i], 0); + } } - for (size_t i = 0; i < rp->attachment_images->size; i++) { - dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); + if (rp->attachment_images) { + for (size_t i = 0; i < rp->attachment_images->size; i++) { + dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); + } } dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); @@ -261,7 +266,9 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) destroy_attachments (ctx, renderpass); dfunc->vkDestroyRenderPass (device->dev, renderpass->renderpass, 0); destroy_renderframes (ctx, renderpass); - destroy_framebuffers (ctx, renderpass); + if (renderpass->framebuffers) { + destroy_framebuffers (ctx, renderpass); + } DARRAY_CLEAR (&renderpass->frames); free (renderpass->clearValues); From 5e1ce5b46e11124aa73d31c8779d68bf7e03a48c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 May 2022 10:41:19 +0900 Subject: [PATCH 3017/3664] [vulkan] Move main render pass setup to Vulkan_Main And support sorting of render passes by an order index. --- include/QF/Vulkan/qf_main.h | 1 + include/QF/Vulkan/qf_renderpass.h | 1 + include/QF/Vulkan/qf_vid.h | 4 +++ libs/video/renderer/vulkan/vulkan_main.c | 31 +++++++++++++++++- .../video/renderer/vulkan/vulkan_vid_common.c | 32 +++++++------------ 5 files changed, 47 insertions(+), 22 deletions(-) diff --git a/include/QF/Vulkan/qf_main.h b/include/QF/Vulkan/qf_main.h index 8d2da31d6..b666ce017 100644 --- a/include/QF/Vulkan/qf_main.h +++ b/include/QF/Vulkan/qf_main.h @@ -33,6 +33,7 @@ struct qfv_renderframe_s; struct entqueue_s; struct scene_s; +void Vulkan_Main_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_NewScene (struct scene_s *scene, struct vulkan_ctx_s *ctx); void Vulkan_RenderView (struct qfv_renderframe_s *rFrame); void Vulkan_RenderEntities (struct entqueue_s *queue, diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index 8a4d68a1b..ddbc70764 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -48,6 +48,7 @@ typedef struct qfv_renderpass_s { qfv_framebufferset_t *framebuffers; VkViewport viewport; VkRect2D scissor; + int order; size_t subpassCount; qfv_subpassset_t *subpass_info; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 04e4a49d6..eb12a2ce2 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -35,6 +35,10 @@ #endif #include +enum { + QFV_rp_main, +}; + //FIXME location typedef enum { QFV_passDepth, // geometry diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 8fa6a91e3..fa0fcd53b 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -48,17 +48,21 @@ #include "QF/scene/entity.h" #include "QF/scene/scene.h" -#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" +#include "QF/Vulkan/qf_compose.h" +#include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" +#include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_sprite.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/swapchain.h" #include "mod_internal.h" #include "r_internal.h" @@ -151,3 +155,28 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) Vulkan_BuildDisplayLists (scene->models, scene->num_models, ctx); Vulkan_LoadLights (scene, ctx); } + +static void +main_draw (qfv_renderframe_t *rFrame) +{ + Vulkan_Matrix_Draw (rFrame); + Vulkan_RenderView (rFrame); + Vulkan_FlushText (rFrame);//FIXME delayed by a frame? + Vulkan_Lighting_Draw (rFrame); + Vulkan_Compose_Draw (rFrame); +} + +void +Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) +{ + qfv_output_t output = { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[0], + .format = ctx->swapchain->format, + .view_list = ctx->swapchain->imageViews->a, + }; + __auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred", + &output, main_draw); + rp->order = QFV_rp_main; + DARRAY_APPEND (&ctx->renderPasses, rp); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index d87e4ce72..f95aa3b43 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -39,23 +39,20 @@ #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/heapsort.h" #include "QF/plist.h" #include "QF/va.h" #include "QF/scene/entity.h" #include "QF/Vulkan/capture.h" +#include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/staging.h" #include "QF/Vulkan/swapchain.h" -#include "QF/Vulkan/qf_alias.h" -#include "QF/Vulkan/qf_bsp.h" -#include "QF/Vulkan/qf_compose.h" -#include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_main.h" -#include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_vid.h" @@ -365,28 +362,21 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) return item; } -static void -renderpass_draw (qfv_renderframe_t *rFrame) +static int +renderpass_cmp (const void *_a, const void *_b) { - Vulkan_Matrix_Draw (rFrame); - Vulkan_RenderView (rFrame); - Vulkan_FlushText (rFrame);//FIXME delayed by a frame? - Vulkan_Lighting_Draw (rFrame); - Vulkan_Compose_Draw (rFrame); + const qfv_renderpass_t *a = _a; + const qfv_renderpass_t *b = _b; + return a->order - b->order; } void Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) { - qfv_output_t output = { - .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[0], - .format = ctx->swapchain->format, - .view_list = ctx->swapchain->imageViews->a, - }; - __auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred", - &output, renderpass_draw); - DARRAY_APPEND (&ctx->renderPasses, rp); + Vulkan_Main_CreateRenderPasses (ctx); + + heapsort (ctx->renderPasses.a, ctx->renderPasses.size, + sizeof (qfv_renderpass_t *), renderpass_cmp); } void From 3058a5103ffc54e8db47ca51fbf8e61768f5036d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 May 2022 10:49:40 +0900 Subject: [PATCH 3018/3664] [renderer] Move entity drawing in with view rendering I really don't remember why I made it separate, though it may have been to do with r_ent_queue. However, putting it together with the rest is needed for the "render pass" rework. --- include/QF/plugin/vid_render.h | 1 - libs/video/renderer/r_screen.c | 1 - libs/video/renderer/vid_render_gl.c | 2 +- libs/video/renderer/vid_render_glsl.c | 2 +- libs/video/renderer/vid_render_sw.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 15 --------------- libs/video/renderer/vulkan/vulkan_main.c | 1 + 7 files changed, 4 insertions(+), 20 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 3d6774d08..5502d6220 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -114,7 +114,6 @@ typedef struct vid_render_funcs_s { void (*begin_frame) (void); void (*render_view) (void); - void (*draw_entities) (struct entqueue_s *queue); void (*draw_particles) (struct psystem_s *psystem); void (*draw_transparent) (void); void (*post_process) (struct framebuffer_s *src); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index f55531c0c..0959b0c82 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -193,7 +193,6 @@ render_scene (void) r_framecount++; EntQueue_Clear (r_ent_queue); r_funcs->render_view (); - r_funcs->draw_entities (r_ent_queue); r_funcs->draw_particles (&r_psystem); r_funcs->draw_transparent (); } diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 3fe390bf9..59d7a019a 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -264,6 +264,7 @@ gl_render_view (void) // do 3D refresh drawing, and then update the screen qfglClear (GL_DEPTH_BUFFER_BIT); gl_R_RenderView (); + gl_R_RenderEntities (r_ent_queue); } static void @@ -516,7 +517,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_R_LineGraph, gl_begin_frame, gl_render_view, - gl_R_RenderEntities, gl_R_DrawParticles, gl_draw_transparent, gl_post_process, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 958cfbfdc..102c8f53f 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -225,6 +225,7 @@ glsl_render_view (void) { qfeglClear (GL_DEPTH_BUFFER_BIT); glsl_R_RenderView (); + glsl_R_RenderEntities (r_ent_queue); } static void @@ -460,7 +461,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_R_LineGraph, glsl_begin_frame, glsl_render_view, - glsl_R_RenderEntities, glsl_R_DrawParticles, glsl_draw_transparent, glsl_post_process, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index e1398bc72..b88435a08 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -160,6 +160,7 @@ static void sw_render_view (void) { R_RenderView (); + R_DrawEntitiesOnList (r_ent_queue); } static void @@ -480,7 +481,6 @@ vid_render_funcs_t sw_vid_render_funcs = { R_LineGraph, sw_begin_frame, sw_render_view, - R_DrawEntitiesOnList, R_DrawParticles, sw_draw_transparent, sw_post_process, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 720813da3..0b4ccf1e1 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -292,20 +292,6 @@ vulkan_render_view (void) } } -static void -vulkan_draw_entities (entqueue_t *queue) -{ - __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; - uint32_t imageIndex = vulkan_ctx->swapImageIndex; - - for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { - __auto_type rp = vulkan_ctx->renderPasses.a[i]; - __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - frame->framebuffer = rp->framebuffers->a[imageIndex]; - Vulkan_RenderEntities (queue, rpFrame); - } -} - static void vulkan_draw_particles (struct psystem_s *psystem) { @@ -758,7 +744,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_R_LineGraph, vulkan_begin_frame, vulkan_render_view, - vulkan_draw_entities, vulkan_draw_particles, vulkan_draw_transparent, vulkan_post_process, diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index fa0fcd53b..4098a4336 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -132,6 +132,7 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) } Vulkan_DrawWaterSurfaces (rFrame); Vulkan_Bsp_Flush (ctx); + Vulkan_RenderEntities (r_ent_queue, rFrame); Vulkan_Scene_Flush (ctx); } From 71813af0905684537f6191c614fdc722b7e0523b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 May 2022 10:56:00 +0900 Subject: [PATCH 3019/3664] [vulkan] Support creating render passes with no render pass Sounds odd, but it's part of the problem with calling two different things with essentially the same name. The "high level" render pass in question may be a compute pass, or a complex series of (Vulkan) render passes and so won't create a Vulkan render pass for the "high level" render pass (I do need to come up with a better name for it). --- include/QF/Vulkan/qf_renderpass.h | 2 +- libs/video/renderer/vid_render_vulkan.c | 26 +++++++++-- .../video/renderer/vulkan/vulkan_renderpass.c | 43 +++++++++++-------- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index ddbc70764..3cd50ae30 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -49,7 +49,7 @@ typedef struct qfv_renderpass_s { VkViewport viewport; VkRect2D scissor; int order; - + int primary_commands; size_t subpassCount; qfv_subpassset_t *subpass_info; qfv_renderframeset_t frames; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 0b4ccf1e1..07ef97e15 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -29,6 +29,7 @@ #endif #include +#include #include "QF/cvar.h" #include "QF/darray.h" @@ -111,6 +112,7 @@ vulkan_R_Init (void) static void vulkan_R_ClearState (void) { + QFV_DeviceWaitIdle (vulkan_ctx->device); r_refdef.worldmodel = 0; R_ClearEfrags (); R_ClearDlights (); @@ -287,7 +289,9 @@ vulkan_render_view (void) for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { __auto_type rp = vulkan_ctx->renderPasses.a[i]; __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - frame->framebuffer = rp->framebuffers->a[imageIndex]; + if (rp->framebuffers) { + frame->framebuffer = rp->framebuffers->a[imageIndex]; + } rp->draw (rpFrame); } } @@ -339,13 +343,27 @@ vulkan_end_frame (void) .renderArea = { {0, 0}, vulkan_ctx->swapchain->extent }, }; + __auto_type cmdBufs = (qfv_cmdbufferset_t) DARRAY_STATIC_INIT (4); + DARRAY_APPEND (&cmdBufs, frame->cmdBuffer); + dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { __auto_type rp = vulkan_ctx->renderPasses.a[i]; __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + if (rp->primary_commands) { + for (int j = 0; j < rpFrame->subpassCount; j++) { + __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; + size_t base = cmdBufs.size; + DARRAY_RESIZE (&cmdBufs, base + cmdSet->size); + memcpy (&cmdBufs.a[base], cmdSet->a, + cmdSet->size * sizeof (VkCommandBuffer)); + } + continue; + } + QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color); - if (rpFrame->renderpass) { + if (rpFrame->renderpass && rp->renderpass) { renderPassInfo.framebuffer = frame->framebuffer, renderPassInfo.renderPass = rp->renderpass; renderPassInfo.clearValueCount = rp->clearValues->size; @@ -403,12 +421,14 @@ vulkan_end_frame (void) VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, 1, &frame->imageAvailableSemaphore, &waitStage, - 1, &frame->cmdBuffer, + cmdBufs.size, cmdBufs.a, 1, &frame->renderDoneSemaphore, }; dfunc->vkResetFences (dev, 1, &frame->fence); dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); + DARRAY_CLEAR (&cmdBufs); + if (vulkan_ctx->capture_callback) { //FIXME look into "threading" this rather than waiting here dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE, diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 688050427..6ddf82136 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -51,9 +51,9 @@ get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name) } plitem_t *item = rp->renderpassDef; - if (!item || !(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading %s\n", name); - } else { + if (!item) { + Sys_Printf ("error loading %s\n", rp->name); + } else if ((item = PL_ObjectForKey (item, name))) { Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name); } return item; @@ -201,31 +201,38 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, rp->name = name; plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass"); - hashtab_t *tab = ctx->renderpasses; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); - __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); - if (renderpass) { - rp->renderpass = renderpass; - } else { - ctx->output = *output; - rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, rp->renderpassDef); - QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, - rp->renderpass, va (ctx->va_ctx, "renderpass:%s", - name)); + if (rp_cfg) { + hashtab_t *tab = ctx->renderpasses; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); + __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); + if (renderpass) { + rp->renderpass = renderpass; + } else { + ctx->output = *output; + rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, + rp->renderpassDef); + QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, + rp->renderpass, va (ctx->va_ctx, + "renderpass:%s", name)); + } + rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, + "subpasses")); } - rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, "subpasses")); plitem_t *rp_info = get_rp_item (ctx, rp, "info"); if (rp_info) { plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_info"); if (subpass_info) { rp->subpass_info = QFV_ParseSubpasses (ctx, subpass_info, rp->renderpassDef); - if (rp->subpass_info->size > rp->subpassCount) { + if (rp->subpass_info->size < rp->subpassCount) { Sys_Printf ("warning:%s:%d: insufficient entries in " "subpass_info\n", name, PL_Line (subpass_info)); } + if (!rp->subpassCount) { + rp->subpassCount = rp->subpass_info->size; + } } plitem_t *color = PL_ObjectForKey (rp_info, "color"); From c58a2e5f540a0521ee6780ce7dcd7d2985f5e300 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 May 2022 11:05:12 +0900 Subject: [PATCH 3020/3664] [vulkan] Remove unused command buffer and fence --- include/vid_vulkan.h | 2 -- libs/video/renderer/vid_render_vulkan.c | 8 +------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 95ace93b0..89e888d2e 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -77,8 +77,6 @@ typedef struct vulkan_ctx_s { struct composectx_s *compose_context; VkCommandPool cmdpool; - VkCommandBuffer cmdbuffer; - VkFence fence; // for ctx->cmdbuffer only struct qfv_stagebuf_s *staging; size_t curFrame; vulkan_frameset_t frames; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 07ef97e15..1c115a4e2 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -631,11 +631,6 @@ vulkan_vid_render_choose_visual (void *data) vulkan_ctx->cmdpool = QFV_CreateCommandPool (vulkan_ctx->device, vulkan_ctx->device->queue.queueFamily, 0, 1); - __auto_type cmdset = QFV_AllocCommandBufferSet (1, alloca); - QFV_AllocateCommandBuffers (vulkan_ctx->device, vulkan_ctx->cmdpool, 0, - cmdset); - vulkan_ctx->cmdbuffer = cmdset->a[0]; - vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1); Sys_MaskPrintf (SYS_vulkan, "vk choose visual %p %p %d %#zx\n", vulkan_ctx->device->dev, vulkan_ctx->device->queue.queue, vulkan_ctx->device->queue.queueFamily, @@ -647,7 +642,7 @@ vulkan_vid_render_create_context (void *data) { vulkan_ctx->create_window (vulkan_ctx); vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx); - Sys_MaskPrintf (SYS_vulkan, "vk create context %#zx\n", + Sys_MaskPrintf (SYS_vulkan, "vk create context: surface:%#zx\n", (size_t) vulkan_ctx->surface); } @@ -726,7 +721,6 @@ vulkan_vid_render_shutdown (void) Vulkan_DestroyRenderPasses (vulkan_ctx); QFV_DestroyStagingBuffer (vulkan_ctx->staging); - df->vkDestroyFence (dev, vulkan_ctx->fence, 0); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); Vulkan_Shutdown_Common (vulkan_ctx); From 8e7474f614db176764ebd6eed169c56c6baa7de9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 May 2022 12:43:04 +0900 Subject: [PATCH 3021/3664] [vulkan] Hook up the shadow map render pass There are some issues with the light renderers getting mangled, and only the first light is even touched (just begin and end of render pass), but this gets a lot of the framework into place. --- include/QF/Vulkan/qf_lighting.h | 30 ++- include/QF/Vulkan/qf_vid.h | 1 + libs/video/renderer/vulkan/shadow.plist | 71 ++--- libs/video/renderer/vulkan/vulkan_lighting.c | 254 ++++++++++++------ .../video/renderer/vulkan/vulkan_vid_common.c | 1 + 5 files changed, 233 insertions(+), 124 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 9de79a94b..c0ca5c67c 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -35,6 +35,7 @@ #include "QF/modelgen.h" #include "QF/scene/light.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/image.h" #include "QF/simd/types.h" @@ -79,6 +80,20 @@ typedef struct lightingframe_s { typedef struct lightingframeset_s DARRAY_TYPE (lightingframe_t) lightingframeset_t; +typedef struct light_renderer_s { + VkRenderPass renderPass; // shared + VkFramebuffer framebuffer; + VkImage image; // shared + VkImageView view; + uint32_t size; + uint32_t layer; + uint32_t numLayers; + int mode; +} light_renderer_t; + +typedef struct light_renderer_set_s + DARRAY_TYPE (light_renderer_t) light_renderer_set_t; + typedef struct lightingctx_s { lightingframeset_t frames; VkPipeline pipeline; @@ -86,10 +101,16 @@ typedef struct lightingctx_s { VkSampler sampler; VkDeviceMemory light_memory; VkDeviceMemory shadow_memory; - qfv_lightmatset_t lightmats; - qfv_imageset_t lightimages; - lightintset_t lightlayers; - qfv_imageviewset_t lightviews; + qfv_lightmatset_t light_mats; + qfv_imageset_t light_images; + light_renderer_set_t light_renderers; + + qfv_renderpass_t *qfv_renderpass; + VkRenderPass renderpass_6; + VkRenderPass renderpass_4; + VkRenderPass renderpass_1; + + VkCommandPool cmdpool; struct lightingdata_s *ldata; struct scene_s *scene; @@ -98,6 +119,7 @@ typedef struct lightingctx_s { struct vulkan_ctx_s; struct qfv_renderframe_s; +void Vulkan_Lighting_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Draw (struct qfv_renderframe_s *rFrame); diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index eb12a2ce2..19d62795d 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -36,6 +36,7 @@ #include enum { + QFV_rp_shadowmap, QFV_rp_main, }; diff --git a/libs/video/renderer/vulkan/shadow.plist b/libs/video/renderer/vulkan/shadow.plist index 5db23260c..e2f6e5778 100644 --- a/libs/video/renderer/vulkan/shadow.plist +++ b/libs/video/renderer/vulkan/shadow.plist @@ -1,54 +1,17 @@ { - images = { - shadow = { - flags = cube_compatible; - imageType = `2d; - format = x8_d24_unorm_pack32; - samples = 1; - extent = { - width = 256; // FIXME config - height = 256; // FIXME config - depth = 1; - }; - mipLevels = 1; - arrayLayers = 2048; // FIXME config - tiling = optimal; - usage = depth_stencil_attachment|sampled; - initialLayout = undefined; - }; - }; - imageViews = { - shadow = { - image = depth; - viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; - format = $properties.images.shadow.format; - components = { - r = identity; g = identity; b = identity; a = identity; - }; - subresourceRange = { - aspectMask = depth; - levelCount = 1; - layerCount = $properties.images.shadow.arrayLayers; - }; - }; - }; - framebuffer = { - renderPass = $properties.renderpass; - attachments = (shadow); - width = $properties.images.shadow.extent.width; - height = $properties.images.shadow.extent.height; - layers = $properties.images.shadow.arrayLayers; - }; clearValues = ( { depthStencil = { depth = 1; stencil = 0; }; }, ); - renderpass = { - @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = (0xffffffff); - }); + info = { + color = "[0.2, 0.2, 0.2, 1]"; + subpass_info = ( + { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, + ); + }; + renderpass_base = { attachments = ( { - format = $properties.images.shadow.format; + format = $output.format; samples = 1; loadOp = dont_care; storeOp = store; @@ -68,4 +31,22 @@ } ); }; + renderpass_6 = { + @inherit = $properties.renderpass_base; + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0x0000003fu); + }); + }; + renderpass_4 = { + @inherit = $properties.renderpass_base; + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0x0000000fu); + }); + }; + renderpass_1 = { + @inherit = $properties.renderpass_base; + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0x00000001u); + }); + }; } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 8da92aa58..6696e5db8 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -72,6 +72,7 @@ #include "r_internal.h" #include "vid_vulkan.h" +#include "vkparse.h" static void update_lights (vulkan_ctx_t *ctx) @@ -217,6 +218,75 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) dfunc->vkEndCommandBuffer (cmd); } +static void +lighting_draw_maps (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + lightingctx_t *lctx = ctx->lighting_context; + + if (rFrame->subpassCmdSets[0].size) { + __auto_type sets = &rFrame->subpassCmdSets[0]; + dfunc->vkFreeCommandBuffers (device->dev, lctx->cmdpool, + sets->size, sets->a); + sets->size = 0; + } + + if (!lctx->ldata) { + return; + } + + __auto_type bufferset = QFV_AllocCommandBufferSet (1, alloca); + QFV_AllocateCommandBuffers (device, lctx->cmdpool, 0, bufferset); + VkCommandBuffer cmd = bufferset->a[0]; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + cmd, va (ctx->va_ctx, "lighting:%zd", ctx->curFrame)); + + VkCommandBufferBeginInfo beginInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + __auto_type rp = rFrame->renderpass; + QFV_CmdBeginLabel (device, cmd, rp->name, rp->color); + + __auto_type lr = &lctx->light_renderers.a[0]; + VkRenderPassBeginInfo renderPassInfo = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderArea = { {0, 0}, {lr->size, lr->size} }, + .framebuffer = lr->framebuffer, + .renderPass = lr->renderPass, + .pClearValues = lctx->qfv_renderpass->clearValues->a, + }; + __auto_type subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; + dfunc->vkCmdBeginRenderPass (cmd, &renderPassInfo, subpassContents); + //... + dfunc->vkCmdEndRenderPass (cmd); + QFV_CmdEndLabel (device, cmd); + dfunc->vkEndCommandBuffer (cmd); + + DARRAY_APPEND (&rFrame->subpassCmdSets[0], cmd); +} + +void +Vulkan_Lighting_CreateRenderPasses (vulkan_ctx_t *ctx) +{ + lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); + ctx->lighting_context = lctx; + + // extents are dynamic and filled in for each light + // frame buffers are highly dynamic + qfv_output_t output = {}; + __auto_type rp = Vulkan_CreateRenderPass (ctx, "shadow", + &output, lighting_draw_maps); + rp->primary_commands = 1; + rp->order = QFV_rp_shadowmap; + DARRAY_APPEND (&ctx->renderPasses, rp); + + lctx->qfv_renderpass = rp; +} + static VkDescriptorBufferInfo base_buffer_info = { 0, 0, VK_WHOLE_SIZE }; @@ -250,13 +320,24 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) qfvPushDebug (ctx, "lighting init"); - lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); - ctx->lighting_context = lctx; + // lighting_context initialized in Vulkan_Lighting_CreateRenderPasses - DARRAY_INIT (&lctx->lightmats, 16); - DARRAY_INIT (&lctx->lightlayers, 16); - DARRAY_INIT (&lctx->lightimages, 16); - DARRAY_INIT (&lctx->lightviews, 16); + ctx->output = (qfv_output_t) {.format = VK_FORMAT_X8_D24_UNORM_PACK32 }; + lightingctx_t *lctx = ctx->lighting_context; + plitem_t *rp_def = lctx->qfv_renderpass->renderpassDef; + plitem_t *rp_cfg = PL_ObjectForKey (rp_def, "renderpass_6"); + lctx->renderpass_6 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def); + rp_cfg = PL_ObjectForKey (rp_def, "renderpass_4"); + lctx->renderpass_4 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def); + rp_cfg = PL_ObjectForKey (rp_def, "renderpass_1"); + lctx->renderpass_1 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def); + + lctx->cmdpool = QFV_CreateCommandPool (device, device->queue.queueFamily, + 1, 1); + + DARRAY_INIT (&lctx->light_mats, 16); + DARRAY_INIT (&lctx->light_images, 16); + DARRAY_INIT (&lctx->light_renderers, 16); size_t frames = ctx->frames.size; DARRAY_INIT (&lctx->frames, frames); @@ -382,14 +463,16 @@ clear_shadows (vulkan_ctx_t *ctx) dfunc->vkFreeMemory (device->dev, lctx->shadow_memory, 0); lctx->shadow_memory = 0; } - for (size_t i = 0; i < lctx->lightviews.size; i++) { - dfunc->vkDestroyImageView (device->dev, lctx->lightviews.a[i], 0); + for (size_t i = 0; i < lctx->light_renderers.size; i++) { + __auto_type lr = &lctx->light_renderers.a[i]; + dfunc->vkDestroyFramebuffer (device->dev, lr->framebuffer, 0); + dfunc->vkDestroyImageView (device->dev, lr->view, 0); } - for (size_t i = 0; i < lctx->lightimages.size; i++) { - dfunc->vkDestroyImage (device->dev, lctx->lightimages.a[i], 0); + for (size_t i = 0; i < lctx->light_images.size; i++) { + dfunc->vkDestroyImage (device->dev, lctx->light_images.a[i], 0); } - lctx->lightimages.size = 0; - lctx->lightviews.size = 0; + lctx->light_images.size = 0; + lctx->light_renderers.size = 0; } void @@ -401,16 +484,20 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) clear_shadows (ctx); + dfunc->vkDestroyCommandPool (device->dev, lctx->cmdpool, 0); + dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_6, 0); + dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_4, 0); + dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_1, 0); + for (size_t i = 0; i < lctx->frames.size; i++) { lightingframe_t *lframe = &lctx->frames.a[i]; dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0); } dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0); dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0); - DARRAY_CLEAR (&lctx->lightmats); - DARRAY_CLEAR (&lctx->lightimages); - DARRAY_CLEAR (&lctx->lightlayers); - DARRAY_CLEAR (&lctx->lightviews); + DARRAY_CLEAR (&lctx->light_mats); + DARRAY_CLEAR (&lctx->light_images); + DARRAY_CLEAR (&lctx->light_renderers); free (lctx->frames.a); free (lctx); } @@ -421,7 +508,7 @@ static void create_light_matrices (lightingctx_t *lctx) { lightingdata_t *ldata = lctx->ldata; - DARRAY_RESIZE (&lctx->lightmats, ldata->lights.size); + DARRAY_RESIZE (&lctx->light_mats, ldata->lights.size); for (size_t i = 0; i < ldata->lights.size; i++) { light_t *light = &ldata->lights.a[i]; mat4f_t view; @@ -469,7 +556,7 @@ create_light_matrices (lightingctx_t *lctx) QFV_PerspectiveCos (proj, -light->direction[3]); break; } - mmulf (lctx->lightmats.a[i], proj, view); + mmulf (lctx->light_mats.a[i], proj, view); } } @@ -521,30 +608,26 @@ create_map (int size, int layers, int cube, vulkan_ctx_t *ctx) } static VkImageView -create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx) +create_view (const light_renderer_t *lr, int id, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - int layers = 0; VkImageViewType type = 0; const char *viewtype = 0; - switch (mode) { + switch (lr->mode) { case ST_NONE: return 0; case ST_PLANE: - layers = 1; type = VK_IMAGE_VIEW_TYPE_2D; viewtype = "plane"; break; case ST_CASCADE: - layers = 4; type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; viewtype = "cascade"; break; case ST_CUBE: - layers = 6; type = VK_IMAGE_VIEW_TYPE_CUBE; viewtype = "cube"; break; @@ -553,14 +636,14 @@ create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx) VkImageViewCreateInfo createInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0, 0, - image, type, VK_FORMAT_X8_D24_UNORM_PACK32, + lr->image, type, VK_FORMAT_X8_D24_UNORM_PACK32, { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, }, - { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, baseLayer, layers } + { VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, lr->layer, lr->numLayers } }; VkImageView view; @@ -572,6 +655,26 @@ create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx) return view; } +static VkFramebuffer +create_framebuffer (const light_renderer_t *lr, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + VkFramebuffer framebuffer; + VkFramebufferCreateInfo cInfo = { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .renderPass = lr->renderPass, + .attachmentCount = 1, + .pAttachments = &lr->view, + .width = lr->size, + .height = lr->size, + .layers = 1, + }; + dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); + return framebuffer; +} + static void build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) { @@ -592,126 +695,127 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) for (int i = 0; i < numLights; i++) { lightMap[i] = i; } - DARRAY_RESIZE (&lctx->lightlayers, numLights); heapsort_r (lightMap, numLights, sizeof (int), light_compare, ldata); + + DARRAY_RESIZE (&lctx->light_renderers, numLights); for (int i = 0; i < numLights; i++) { int layers = 1; - int shadow = ST_NONE; int li = lightMap[i]; + __auto_type lr = &lctx->light_renderers.a[li]; + lr->mode = ST_NONE; if (!lights[li].position[3]) { - shadow = ST_CASCADE; + lr->mode = ST_CASCADE; } else { if (lights[li].direction[3] > -0.5) { - shadow = ST_CUBE; + lr->mode = ST_CUBE; } else { - shadow = ST_PLANE; + lr->mode = ST_PLANE; } } - if (shadow == ST_CASCADE || shadow == ST_NONE) { + if (lr->mode == ST_CASCADE || lr->mode == ST_NONE) { // cascade shadows will be handled separately, and "none" has no // shadow map at all imageMap[li] = -1; continue; } - if (shadow == ST_CUBE) { + if (lr->mode == ST_CUBE) { layers = 6; } if (size != abs ((int) lights[li].color[3]) || numLayers + layers > maxLayers) { if (numLayers) { VkImage shadow_map = create_map (size, numLayers, 1, ctx); - DARRAY_APPEND (&lctx->lightimages, shadow_map); + DARRAY_APPEND (&lctx->light_images, shadow_map); numLayers = 0; } size = abs ((int) lights[li].color[3]); } - imageMap[li] = lctx->lightimages.size; - lctx->lightlayers.a[li] = numLayers; + imageMap[li] = lctx->light_images.size; + lr->size = size; + lr->layer = numLayers; + lr->numLayers = layers; numLayers += layers; totalLayers += layers; } if (numLayers) { VkImage shadow_map = create_map (size, numLayers, 1, ctx); - DARRAY_APPEND (&lctx->lightimages, shadow_map); + DARRAY_APPEND (&lctx->light_images, shadow_map); } numLayers = 0; size = 1024; for (int i = 0; i < numLights; i++) { int layers = 4; - int shadow = ST_NONE; int li = lightMap[i]; + __auto_type lr = &lctx->light_renderers.a[li]; - if (!lights[li].position[3]) { - shadow = ST_CASCADE; - } else { - if (lights[li].direction[3] > -0.5) { - shadow = ST_CUBE; - } else { - shadow = ST_PLANE; - } - } - - if (shadow != ST_CASCADE) { + if (lr->mode != ST_CASCADE) { continue; } if (numLayers + layers > maxLayers) { VkImage shadow_map = create_map (size, numLayers, 0, ctx); - DARRAY_APPEND (&lctx->lightimages, shadow_map); + DARRAY_APPEND (&lctx->light_images, shadow_map); numLayers = 0; } - imageMap[li] = lctx->lightimages.size; - lctx->lightlayers.a[li] = numLayers; + imageMap[li] = lctx->light_images.size; + lr->size = size; + lr->layer = numLayers; + lr->numLayers = layers; numLayers += layers; totalLayers += layers; } if (numLayers) { VkImage shadow_map = create_map (size, numLayers, 0, ctx); - DARRAY_APPEND (&lctx->lightimages, shadow_map); + DARRAY_APPEND (&lctx->light_images, shadow_map); } - for (size_t i = 0; i < lctx->lightimages.size; i++) { - memsize += QFV_GetImageSize (device, lctx->lightimages.a[i]); + for (size_t i = 0; i < lctx->light_images.size; i++) { + memsize += QFV_GetImageSize (device, lctx->light_images.a[i]); } - lctx->shadow_memory = QFV_AllocImageMemory (device, lctx->lightimages.a[0], + lctx->shadow_memory = QFV_AllocImageMemory (device, lctx->light_images.a[0], VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, memsize, 0); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, lctx->shadow_memory, "memory:shadowmap"); size_t offset = 0; - for (size_t i = 0; i < lctx->lightimages.size; i++) { - dfunc->vkBindImageMemory (device->dev, lctx->lightimages.a[i], + for (size_t i = 0; i < lctx->light_images.size; i++) { + dfunc->vkBindImageMemory (device->dev, lctx->light_images.a[i], lctx->shadow_memory, offset); - offset += QFV_GetImageSize (device, lctx->lightimages.a[i]); + offset += QFV_GetImageSize (device, lctx->light_images.a[i]); } - DARRAY_RESIZE (&lctx->lightviews, numLights); for (int i = 0; i < numLights; i++) { int li = lightMap[i]; + __auto_type lr = &lctx->light_renderers.a[li]; if (imageMap[li] == -1) { - lctx->lightviews.a[li] = 0; + *lr = (light_renderer_t) {}; continue; } - int mode = ST_NONE; - if (!ldata->lights.a[li].position[3]) { - mode = ST_CASCADE; - } else { - if (ldata->lights.a[li].direction[3] > -0.5) { - mode = ST_CUBE; - } else { - mode = ST_PLANE; - } + switch (lr->numLayers) { + case 6: + lr->renderPass = lctx->renderpass_6; + break; + case 4: + lr->renderPass = lctx->renderpass_4; + break; + case 1: + lr->renderPass = lctx->renderpass_1; + break; + default: + Sys_Error ("build_shadow_maps: invalid light layer count: %u", + lr->numLayers); } - lctx->lightviews.a[li] = create_view (lctx->lightimages.a[imageMap[li]], - lctx->lightlayers.a[li], - mode, li, ctx); + lr->image = lctx->light_images.a[imageMap[li]]; + lr->view = create_view (lr, li, ctx); + lr->framebuffer = create_framebuffer(lr, ctx); } - Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n", - totalLayers, lctx->lightimages.size, memsize); + Sys_MaskPrintf (SYS_vulkan, + "shadow maps: %d layers in %zd images: %zd\n", + totalLayers, lctx->light_images.size, memsize); } void diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index f95aa3b43..c107a080a 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -374,6 +374,7 @@ void Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) { Vulkan_Main_CreateRenderPasses (ctx); + Vulkan_Lighting_CreateRenderPasses (ctx); heapsort (ctx->renderPasses.a, ctx->renderPasses.size, sizeof (qfv_renderpass_t *), renderpass_cmp); From b8070e01412497984cb0e255cbd567c4191c6224 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 May 2022 12:56:59 +0900 Subject: [PATCH 3022/3664] [vulkan] Check for ambient lights Ambient lights are represented by a point at infinity and a zero direction vector (spherical lights have a non-zero direction vector but the cone angle is 360 degrees). This fixes what appeared to be mangled light renderers (it was actually just an ambient light being treated as a directional light (point at infinity, but non-zero direction vector). --- libs/video/renderer/vulkan/vulkan_lighting.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 6696e5db8..09145ae25 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -702,10 +702,12 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) int layers = 1; int li = lightMap[i]; __auto_type lr = &lctx->light_renderers.a[li]; + *lr = (light_renderer_t) {}; - lr->mode = ST_NONE; if (!lights[li].position[3]) { - lr->mode = ST_CASCADE; + if (!VectorIsZero (lights[li].direction)) { + lr->mode = ST_CASCADE; + } } else { if (lights[li].direction[3] > -0.5) { lr->mode = ST_CUBE; @@ -791,7 +793,6 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) __auto_type lr = &lctx->light_renderers.a[li]; if (imageMap[li] == -1) { - *lr = (light_renderer_t) {}; continue; } From 035595dd7eb00f9ec6671db00115fce58b09485f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 May 2022 15:32:12 +0900 Subject: [PATCH 3023/3664] [vulkan] Clean up bsp global access This makes bsp traversal even more re-entrant (needed for shadows). Everything needed for a "pass" is taken from bsp_pass_t (or indirectly through bspctx_t (though that too might need some revising)). --- include/QF/Vulkan/qf_bsp.h | 38 +++-------- libs/video/renderer/vulkan/vulkan_bsp.c | 84 +++++++++++++------------ 2 files changed, 51 insertions(+), 71 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index a6d2b379a..f1713fcbf 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -51,19 +51,7 @@ typedef struct bsp_model_s { uint32_t face_count; } bsp_model_t; -typedef struct bsp_packet_s { - int first_index; - int index_count; - int transform_id; - int color_id; -} bsp_packet_t; - -typedef struct bsp_packetset_s - DARRAY_TYPE (bsp_packet_t) bsp_packetset_t; - -typedef struct bsp_indexset_s - DARRAY_TYPE (uint32_t) bsp_indexset_t; - +#if 0 typedef struct texname_s { char name[MIPTEXNAME]; } texname_t; @@ -73,7 +61,7 @@ typedef struct texmip_s { uint32_t height; uint32_t offsets[MIPLEVELS]; } texmip_t; - +#endif typedef struct texanim_s { uint16_t base; byte offset; @@ -128,9 +116,13 @@ typedef struct bsp_instance_s { } bsp_instance_t; typedef struct bsp_pass_s { + vec4f_t position; + plane_t *frustum; + const struct mod_brush_s *brush; + struct bspctx_s *bsp_context; uint32_t *indices; // points into index buffer uint32_t index_count; // number of indices written to buffer - uint32_t *entid_data; + uint32_t *entid_data; // points into entid buffer uint32_t entid_count; int vis_frame; int *face_frames; @@ -145,19 +137,6 @@ typedef struct bsp_pass_s { int ent_frame; } bsp_pass_t; -typedef struct bspvert_s { - quat_t vertex; - quat_t tlst; -} bspvert_t; - -typedef enum { - qfv_bsp_texture, - qfv_bsp_glowmap, - qfv_bsp_lightmap, - qfv_bsp_skysheet, - qfv_bsp_skycube, -} qfv_bsp_tex; - typedef enum { QFV_bspDepth, QFV_bspGBuffer, @@ -192,9 +171,6 @@ typedef struct bspctx_s { vulktex_t notexture; - quat_t default_color; - quat_t last_color; - struct scrap_s *light_scrap; struct qfv_stagebuf_s *light_stage; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index e73f920a0..1020bbefa 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -120,13 +120,13 @@ Vulkan_ClearElements (vulkan_ctx_t *ctx) } static inline void -chain_surface (const bsp_face_t *face, bsp_pass_t *pass, bspctx_t *bctx) +chain_surface (const bsp_face_t *face, bsp_pass_t *pass, const bspctx_t *bctx) { int ent_frame = pass->ent_frame; // if the texture has no alt animations, anim_alt holds the sama data // as anim_main - texanim_t *anim = ent_frame ? &bctx->texdata.anim_alt[face->tex_id] - : &bctx->texdata.anim_main[face->tex_id]; + const texanim_t *anim = ent_frame ? &bctx->texdata.anim_alt[face->tex_id] + : &bctx->texdata.anim_main[face->tex_id]; int anim_ind = (bctx->anim_index + anim->offset) % anim->count; int tex_id = bctx->texdata.anim_map[anim->base + anim_ind]; DARRAY_APPEND (&pass->face_queue[tex_id], @@ -165,11 +165,15 @@ clear_textures (vulkan_ctx_t *ctx) void Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) { - mod_brush_t *brush = &r_refdef.worldmodel->brush; clear_textures (ctx); add_texture (r_notexture_mip, ctx); - register_textures (brush, ctx); + { + // FIXME make worldmodel non-special. needs smarter handling of + // textures on sub-models but not on main model. + mod_brush_t *brush = &r_refdef.worldmodel->brush; + register_textures (brush, ctx); + } for (int i = 0; i < num_models; i++) { model_t *m = models[i]; if (!m) @@ -178,9 +182,10 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) if (*m->path == '*') continue; // world has already been done, not interested in non-brush models + // FIXME see above if (m == r_refdef.worldmodel || m->type != mod_brush) continue; - brush = &m->brush; + mod_brush_t *brush = &m->brush; brush->numsubmodels = 1; // no support for submodels in non-world model register_textures (brush, ctx); } @@ -196,7 +201,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!m || *m->path == '*') { continue; } - brush = &m->brush; + mod_brush_t *brush = &m->brush; for (unsigned j = 0; j < brush->numtextures; j++) { if (brush->textures[j]) { textures[t++] = brush->textures[j]; @@ -271,13 +276,18 @@ typedef struct { typedef struct DARRAY_TYPE (faceref_t) facerefset_t; static void -count_verts_inds (faceref_t *faceref, uint32_t *verts, uint32_t *inds) +count_verts_inds (const faceref_t *faceref, uint32_t *verts, uint32_t *inds) { msurface_t *surf = faceref->face; *verts = surf->numedges; *inds = surf->numedges + 1; } +typedef struct bspvert_s { + quat_t vertex; + quat_t tlst; +} bspvert_t; + typedef struct { bsp_face_t *faces; uint32_t *indices; @@ -591,13 +601,13 @@ R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx) Transform_GetWorldMatrix (e->transform, mat); if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { radius = model->radius; - if (R_CullSphere (r_refdef.frustum, (vec_t*)&mat[3], radius)) { //FIXME + if (R_CullSphere (pass->frustum, (vec_t*)&mat[3], radius)) { //FIXME return 1; } } else { VectorAdd (mat[3], model->mins, mins); VectorAdd (mat[3], model->maxs, maxs); - if (R_CullBox (r_refdef.frustum, mins, maxs)) + if (R_CullBox (pass->frustum, mins, maxs)) return 1; } if (Vulkan_Scene_AddEntity (ctx, e) < 0) { @@ -631,19 +641,18 @@ visit_leaf (mleaf_t *leaf) // 1 = back side, 0 = front side static inline int -get_side (mnode_t *node) +get_side (const bsp_pass_t *pass, const mnode_t *node) { // find the node side on which we are - vec4f_t org = r_refdef.frame.position; + vec4f_t org = pass->position; return dotf (org, node->plane)[0] < 0; } static inline void -visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) +visit_node (bsp_pass_t *pass, const mnode_t *node, int side) { - bspctx_t *bctx = ctx->bsp_context; - bsp_pass_t *pass = &ctx->bsp_context->main_pass; + bspctx_t *bctx = pass->bsp_context; int c; // sneaky hack for side = side ? SURF_PLANEBACK : 0; @@ -654,8 +663,9 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) if ((c = node->numsurfaces)) { const bsp_face_t *face = bctx->faces + node->firstsurface; const int *frame = pass->face_frames + node->firstsurface; + int vis_frame = pass->vis_frame; for (; c; c--, face++, frame++) { - if (*frame != r_visframecount) + if (*frame != vis_frame) continue; // side is either 0 or SURF_PLANEBACK @@ -670,21 +680,22 @@ visit_node (mod_brush_t *brush, mnode_t *node, int side, vulkan_ctx_t *ctx) } static inline int -test_node (mod_brush_t *brush, int node_id) +test_node (const bsp_pass_t *pass, int node_id) { if (node_id < 0) return 0; - if (r_node_visframes[node_id] != r_visframecount) + if (pass->node_frames[node_id] != pass->vis_frame) return 0; - mnode_t *node = brush->nodes + node_id; - if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3)) + mnode_t *node = pass->brush->nodes + node_id; + if (R_CullBox (pass->frustum, node->minmaxs, node->minmaxs + 3)) return 0; return 1; } static void -R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) +R_VisitWorldNodes (bsp_pass_t *pass, vulkan_ctx_t *ctx) { + const mod_brush_t *brush = pass->brush; typedef struct { int node_id; int side; @@ -701,11 +712,11 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) node_ptr = node_stack; while (1) { - while (test_node (brush, node_id)) { + while (test_node (pass, node_id)) { mnode_t *node = brush->nodes + node_id; - side = get_side (node); + side = get_side (pass, node); front = node->children[side]; - if (test_node (brush, front)) { + if (test_node (pass, front)) { node_ptr->node_id = node_id; node_ptr->side = side; node_ptr++; @@ -722,7 +733,7 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) visit_leaf (leaf); } } - visit_node (brush, node, side, ctx); + visit_node (pass, node, side); node_id = node->children[side ^ 1]; } if (node_id < 0) { @@ -736,7 +747,7 @@ R_VisitWorldNodes (mod_brush_t *brush, vulkan_ctx_t *ctx) node_id = node_ptr->node_id; side = node_ptr->side; mnode_t *node = brush->nodes + node_id; - visit_node (brush, node, side, ctx); + visit_node (pass, node, side); node_id = node->children[side ^ 1]; continue; } @@ -846,9 +857,6 @@ bsp_begin (qfv_renderframe_t *rFrame) bspctx_t *bctx = ctx->bsp_context; //XXX quat_t fog; - bctx->default_color[3] = 1; - QuatCopy (bctx->default_color, bctx->last_color); - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], @@ -878,10 +886,6 @@ turb_begin (qfv_renderframe_t *rFrame) vulkan_ctx_t *ctx = rFrame->vulkan_ctx; bspctx_t *bctx = ctx->bsp_context; - bctx->default_color[3] = bound (0, r_wateralpha, 1); - - QuatCopy (bctx->default_color, bctx->last_color); - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], @@ -907,9 +911,6 @@ sky_begin (qfv_renderframe_t *rFrame) vulkan_ctx_t *ctx = rFrame->vulkan_ctx; bspctx_t *bctx = ctx->bsp_context; - bctx->default_color[3] = 1; - QuatCopy (bctx->default_color, bctx->last_color); - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], @@ -950,7 +951,7 @@ clear_queues (bspctx_t *bctx, bsp_pass_t *pass) } static void -queue_faces (bsp_pass_t *pass, bspctx_t *bctx, bspframe_t *bframe) +queue_faces (bsp_pass_t *pass, const bspctx_t *bctx, bspframe_t *bframe) { pass->indices = bframe->index_data + bframe->index_count; for (size_t i = 0; i < bctx->registered_textures.size; i++) { @@ -1046,8 +1047,11 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) //qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - mod_brush_t *brush; + bctx->main_pass.bsp_context = bctx; + bctx->main_pass.position = r_refdef.frame.position; + bctx->main_pass.frustum = r_refdef.frustum; + bctx->main_pass.vis_frame = r_visframecount; bctx->main_pass.face_frames = r_face_visframes; bctx->main_pass.leaf_frames = r_leaf_visframes; bctx->main_pass.node_frames = r_node_visframes; @@ -1065,18 +1069,18 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) .colormod = { 1, 1, 1, 1 }, }, }; - brush = &r_refdef.worldmodel->brush; Vulkan_Scene_AddEntity (ctx, &worldent); int world_id = worldent.renderer.model->render_id; bctx->main_pass.ent_frame = 0; // world is always frame 0 bctx->main_pass.inst_id = world_id; + bctx->main_pass.brush = &worldent.renderer.model->brush; if (bctx->main_pass.instances) { DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, worldent.renderer.render_id); } - R_VisitWorldNodes (brush, ctx); + R_VisitWorldNodes (&bctx->main_pass, ctx); if (!bctx->vertex_buffer) { return; } From be4978dc161080c9950acaf62ecf65d780e54731 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 31 May 2022 23:25:49 +0900 Subject: [PATCH 3024/3664] [vulkan] Update staging test for properties2 --- libs/video/renderer/vulkan/test/test-staging.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/test/test-staging.c b/libs/video/renderer/vulkan/test/test-staging.c index d8c772222..93ae15ce4 100644 --- a/libs/video/renderer/vulkan/test/test-staging.c +++ b/libs/video/renderer/vulkan/test/test-staging.c @@ -155,11 +155,14 @@ qfv_devfuncs_t dfuncs = { .vkQueueSubmit = vkQueueSubmit, }; qfv_physdev_t physDev = { - .properties = { - .limits = { - .nonCoherentAtomSize = 256, + .properties2 = { + .properties = { + .limits = { + .nonCoherentAtomSize = 256, + }, }, }, + .properties = &physDev.properties2.properties, }; qfv_device_t device = { .physDev = &physDev, From 2a47a61bc340185fde4873eac45ae258df707543 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Jun 2022 01:57:06 +0900 Subject: [PATCH 3025/3664] [util] Add atomic ring buffer and automated tests Just head and tail are atomic, but it seems to work nicely (at least on intel). I actually had more trouble with gcc (due to accidentally testing lock-free with the wrong ring buffer... oops, but yup, gcc will happily optimize your loop to spin really really fast). Also served as a nice test for C11 threading. --- include/QF/ringbuffer.h | 34 +++- libs/util/test/Makemodule.am | 6 + libs/util/test/test-ringbuffer.c | 313 +++++++++++++++++++++++++++++++ 3 files changed, 349 insertions(+), 4 deletions(-) create mode 100644 libs/util/test/test-ringbuffer.c diff --git a/include/QF/ringbuffer.h b/include/QF/ringbuffer.h index 60eb5d440..d6ffa4a9b 100644 --- a/include/QF/ringbuffer.h +++ b/include/QF/ringbuffer.h @@ -37,6 +37,8 @@ * \param size The number of objects in the ring buffer. Note that the * actual capacity of the buffer is `size - 1` due to the * way ring buffers work. + * + * \note On its own, this is not thread-safe. Suitable locking is required. */ #define RING_BUFFER(type, size) \ struct { \ @@ -45,6 +47,26 @@ unsigned tail; \ } +/** Type declaration for a type-safe ring buffer with atomic head and tail. + * + * \param type The type of data element stored in the ring buffer. + * \param size The number of objects in the ring buffer. Note that the + * actual capacity of the buffer is `size - 1` due to the + * way ring buffers work. + * + * \note This is suitable only for single-reader/single-writer unless + * additional locking is provided for multi-user side. This means `head` must + * have an associated lock for multiple writers, and `tail` must have an + * associated lock for multiple readers. For multi-reader + multi-writer, it + * may be better to use RING_BUFFER with suitable locking. + */ +#define RING_BUFFER_ATOMIC(type, size) \ + struct { \ + type buffer[size]; \ + _Atomic unsigned head; \ + _Atomic unsigned tail; \ + } + #define RB_buffer_size(ring_buffer) \ ({ __auto_type rb_s = (ring_buffer); \ sizeof (rb_s->buffer) / sizeof (rb_s->buffer[0]); \ @@ -95,7 +117,7 @@ const typeof (rb->buffer[0]) *d = (data); \ unsigned c = (count); \ unsigned h = rb->head; \ - rb->head = (h + c) % RB_buffer_size (rb); \ + unsigned new_head = (h + c) % RB_buffer_size (rb); \ if (c > RB_buffer_size (rb) - h) { \ memcpy (rb->buffer + h, d, \ (RB_buffer_size (rb) - h) * sizeof (rb->buffer[0])); \ @@ -104,6 +126,7 @@ h = 0; \ } \ memcpy (rb->buffer + h, d, c * sizeof (rb->buffer[0])); \ + rb->head = new_head; \ }) /** Acquire \a count objects from the buffer, wrapping if necessary. @@ -122,8 +145,10 @@ ({ __auto_type rb = &(ring_buffer); \ unsigned c = (count); \ unsigned h = rb->head; \ - rb->head = (h + c) % RB_buffer_size (rb); \ - &rb->buffer[h]; \ + unsigned new_head = (h + c) % RB_buffer_size (rb); \ + __auto_type head_addr = &rb->buffer[h]; \ + rb->head = new_head; \ + head_addr; \ }) /** Read \a count objects from the buffer to \a data, wrapping if necessary. @@ -145,6 +170,7 @@ unsigned c = (count); \ unsigned oc = c; \ unsigned t = rb->tail; \ + unsigned new_tail = (t + oc) % RB_buffer_size (rb); \ if (c > RB_buffer_size (rb) - t) { \ memcpy (d, rb->buffer + t, \ (RB_buffer_size (rb) - t) * sizeof (rb->buffer[0])); \ @@ -153,7 +179,7 @@ t = 0; \ } \ memcpy (d, rb->buffer + t, c * sizeof (rb->buffer[0])); \ - rb->tail = (t + oc) % RB_buffer_size (rb); \ + rb->tail = new_tail; \ }) /** Discard \a count objects from the ring buffer. diff --git a/libs/util/test/Makemodule.am b/libs/util/test/Makemodule.am index 1272b7242..64cc8b9e4 100644 --- a/libs/util/test/Makemodule.am +++ b/libs/util/test/Makemodule.am @@ -18,6 +18,7 @@ libs_util_tests = \ libs/util/test/test-pqueue \ libs/util/test/test-qfs \ libs/util/test/test-quat \ + libs/util/test/test-ringbuffer \ libs/util/test/test-seb \ libs/util/test/test-sebvf \ libs/util/test/test-seg \ @@ -106,6 +107,11 @@ libs_util_test_test_quat_SOURCES=libs/util/test/test-quat.c libs_util_test_test_quat_LDADD=libs/util/libQFutil.la libs_util_test_test_quat_DEPENDENCIES=libs/util/libQFutil.la +libs_util_test_test_ringbuffer_SOURCES=libs/util/test/test-ringbuffer.c +libs_util_test_test_ringbuffer_LDADD=libs/util/libQFutil.la +libs_util_test_test_ringbuffer_LDFLAGS=-pthread +libs_util_test_test_ringbuffer_DEPENDENCIES=libs/util/libQFutil.la + libs_util_test_test_seb_SOURCES=libs/util/test/test-seb.c libs_util_test_test_seb_LDADD=libs/util/libQFutil.la libs_util_test_test_seb_DEPENDENCIES=libs/util/libQFutil.la diff --git a/libs/util/test/test-ringbuffer.c b/libs/util/test/test-ringbuffer.c new file mode 100644 index 000000000..ece04c992 --- /dev/null +++ b/libs/util/test/test-ringbuffer.c @@ -0,0 +1,313 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include "QF/dstring.h" +#include "QF/mathlib.h" +#include "QF/ringbuffer.h" +#include "QF/sys.h" + +typedef int (*test_func) (int a, int b); + +typedef RING_BUFFER (int, 8) ringbuffer_t; +typedef RING_BUFFER (char, 8) ringbuffer_char_t; +typedef RING_BUFFER_ATOMIC (char, 8) ringbuffer_atomic_t; + +static ringbuffer_t int_ringbuffer = { .buffer = { [0 ... 7] = 0xdeadbeef } }; +static ringbuffer_char_t ringbuffer_char; +static ringbuffer_atomic_t ringbuffer_atomic; +mtx_t rb_mtx; +cnd_t rb_write_cnd; +cnd_t rb_read_cnd; + +ringbuffer_atomic_t int_ringbuffer_atomic; + +static int +get_size (int a, int b) +{ + return RB_buffer_size (&int_ringbuffer); +} + +static int +space_available (int a, int b) +{ + return RB_SPACE_AVAILABLE (int_ringbuffer); +} + +static int +data_available (int a, int b) +{ + return RB_DATA_AVAILABLE (int_ringbuffer); +} + +static int +write_data (int value, int b) +{ + return RB_WRITE_DATA (int_ringbuffer, &value, 1); +} + +static int +acquire (int count, int b) +{ + return *RB_ACQUIRE (int_ringbuffer, count); +} + +static int +read_data (int a, int b) +{ + int ret; + RB_READ_DATA (int_ringbuffer, &ret, 1); + return ret; +} + +static int +release (int count, int b) +{ + return RB_RELEASE (int_ringbuffer, count); +} + +static int +peek_data (int offset, int b) +{ + return *RB_PEEK_DATA (int_ringbuffer, offset); +} + +static int +poke_data (int offset, int value) +{ + return RB_POKE_DATA (int_ringbuffer, offset, value); +} + +static int +init_threading (int a, int b) +{ + if (mtx_init (&rb_mtx, mtx_plain) != thrd_success) { + return -1; + } + if (cnd_init (&rb_write_cnd) != thrd_success) { + return -1; + } + if (cnd_init (&rb_read_cnd) != thrd_success) { + return -1; + } + return 0; +} + +static const char *text = "Sometimes, it is necessary to write long gibberish " +"in order to test things. Hopefully, this may be an exception, though it's " +"not exactly the most useful or intersting text around."; + +static dstring_t *out_text; + +static int +compare_strings (int a, int b) +{ + int ret = strcmp (out_text->str, text); + dstring_delete (out_text); + out_text = 0; + return ret; +} + +static int +locked_reader (void *data) +{ + if (!out_text) { + out_text = dstring_new (); + } + dstring_clear (out_text); + + do { + mtx_lock (&rb_mtx); + while (RB_DATA_AVAILABLE (ringbuffer_char) < 1) { + cnd_wait (&rb_read_cnd, &rb_mtx); + } + unsigned len = RB_DATA_AVAILABLE (ringbuffer_char); + RB_READ_DATA (ringbuffer_char, dstring_reserve (out_text, len), len); + cnd_signal (&rb_write_cnd); + mtx_unlock (&rb_mtx); + } while (out_text->str[out_text->size - 1]); + + return 0; +} + +static int +locked_writer (void *data) +{ + size_t data_len = strlen (text) + 1; // send nul terminator too + const char *str = text; + + while (data_len > 0) { + mtx_lock (&rb_mtx); + while (RB_SPACE_AVAILABLE (ringbuffer_char) < 1) { + cnd_wait (&rb_write_cnd, &rb_mtx); + } + unsigned len = RB_SPACE_AVAILABLE (ringbuffer_char); + len = min (len, data_len); + RB_WRITE_DATA (ringbuffer_char, str, len); + str += len; + data_len -= len; + cnd_signal (&rb_read_cnd); + mtx_unlock (&rb_mtx); + } + + return 0; +} + +static int +run_locked (int a, int b) +{ + thrd_t writer; + thrd_t reader; + + if (thrd_create (&writer, locked_writer, 0) != thrd_success) { + return -1; + } + if (thrd_create (&reader, locked_reader, 0) != thrd_success) { + return -1; + } + + int res; + if (thrd_join (writer, &res) != thrd_success) { + return -1; + } + if (thrd_join (reader, &res) != thrd_success) { + return -1; + } + return 0; +} + +static int +free_reader (void *data) +{ + if (!out_text) { + out_text = dstring_new (); + } + dstring_clear (out_text); + + do { + while (RB_DATA_AVAILABLE (ringbuffer_atomic) < 1) { + } + unsigned len = RB_DATA_AVAILABLE (ringbuffer_atomic); + RB_READ_DATA (ringbuffer_atomic, dstring_reserve (out_text, len), len); + } while (out_text->str[out_text->size - 1]); + + return 0; +} + +static int +free_writer (void *data) +{ + size_t data_len = strlen (text) + 1; // send nul terminator too + const char *str = text; + + while (data_len > 0) { + while (RB_SPACE_AVAILABLE (ringbuffer_atomic) < 1) { + } + unsigned len = RB_SPACE_AVAILABLE (ringbuffer_atomic); + len = min (len, data_len); + RB_WRITE_DATA (ringbuffer_atomic, str, len); + str += len; + data_len -= len; + } + + return 0; +} + +static int +run_free (int a, int b) +{ + thrd_t writer; + thrd_t reader; + + if (thrd_create (&writer, free_writer, 0) != thrd_success) { + return -1; + } + if (thrd_create (&reader, free_reader, 0) != thrd_success) { + return -1; + } + + int res; + if (thrd_join (writer, &res) != thrd_success) { + return -1; + } + if (thrd_join (reader, &res) != thrd_success) { + return -1; + } + return 0; +} + +#define _ 0 // unused parameter + +struct { + test_func test; + int param1, param2; + int test_expect; +} tests[] = { + { get_size, _, _, 8 }, + { space_available, _, _, 7 }, + { data_available, _, _, 0 }, + { write_data, 0x600dc0de, _, 1 }, + { space_available, _, _, 6 }, + { data_available, _, _, 1 }, + { acquire, 0, _, 0xdeadbeef }, // iffy test: 0 count + { space_available, _, _, 6 }, + { data_available, _, _, 1 }, + { read_data, 1, _, 0x600dc0de }, + { space_available, _, _, 7 }, + { data_available, _, _, 0 }, + { release, 0, _, 1 }, + { space_available, _, _, 7 }, + { data_available, _, _, 0 }, + { poke_data, 0, 1, 1 }, + { poke_data, 1, 2, 2 }, + { poke_data, 2, 3, 3 }, + { poke_data, 3, 4, 4 }, + { poke_data, 4, 5, 5 }, + { poke_data, 5, 6, 6 }, + { acquire, 6, _, 1 }, + { space_available, _, _, 1 }, + { data_available, _, _, 6 }, + { write_data, 7, _, 0 }, // head wrapped to 0 + { space_available, _, _, 0 }, + { data_available, _, _, 7 }, + { peek_data, 0, _, 1 }, + { peek_data, 1, _, 2 }, + { peek_data, 2, _, 3 }, + { peek_data, 3, _, 4 }, + { peek_data, 4, _, 5 }, + { peek_data, 5, _, 6 }, + { peek_data, 6, _, 7 }, + { space_available, _, _, 0 }, + { data_available, _, _, 7 }, + { init_threading, _, _, 0 }, + { run_locked, _, _, 0 }, + { compare_strings, _, _, 0 }, + { run_free, _, _, 0 }, + { compare_strings, _, _, 0 }, +}; +#define num_tests (sizeof (tests) / sizeof (tests[0])) +int test_start_line = __LINE__ - num_tests - 2; + +int +main (int argc, const char **argv) +{ + int res = 0; + + for (size_t i = 0; i < num_tests; i++) { + int test_res; + test_res = tests[i].test (tests[i].param1, tests[i].param2); + if (test_res != tests[i].test_expect) { + res |= 1; + printf ("test %zd (line %zd) failed\n", i, i + test_start_line); + printf ("expect: %d\n", tests[i].test_expect); + printf ("got : %d\n", test_res); + } + } + + return res; +} From ed209c3aa497341a736d2c3e3053010f63b867ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Jun 2022 02:00:32 +0900 Subject: [PATCH 3026/3664] [util] Add a comment to darray test Linux libc has its own "remove" (POSIX, even). --- libs/util/test/test-darray.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/util/test/test-darray.c b/libs/util/test/test-darray.c index 59d3a2ddc..95ac207bb 100644 --- a/libs/util/test/test-darray.c +++ b/libs/util/test/test-darray.c @@ -1,6 +1,7 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +// because libc has its own remove #define remove remove_renamed #include #include From 3e7f2f0578f79ecb3e077a40a7c4ef7e1a499e3d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Jun 2022 16:14:12 +0900 Subject: [PATCH 3027/3664] Fix some doxygen issues Updating parameter names for renamed parameters and adding docs for new parameters. --- include/QF/quakefs.h | 1 + include/snd_internal.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index 2719eeb46..fdd73b6b4 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -84,6 +84,7 @@ extern gamedir_t *qfs_gamedir; /** Function type of callback called on gamedir change. \param phase 0 = before Cache_Flush(), 1 = after Cache_Flush() + \param data data pointer passed on to the callback */ typedef void gamedir_callback_t (int phase, void *data); diff --git a/include/snd_internal.h b/include/snd_internal.h index 481b44551..59d0d2fc2 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -279,7 +279,7 @@ int SND_Memory_GetRetainCount (void *ptr) __attribute__((pure)); \param sfx \param realname \param info - \param loader + \param load */ void SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info, sfxbuffer_t *(*load) (sfxblock_t *block)); @@ -306,7 +306,7 @@ sfxbuffer_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file, void (*close) (sfxbuffer_t *)); /** Close a stream. - \param sfx + \param stream */ void SND_SFX_StreamClose (sfxstream_t *stream); From aafb3c1d98c39463b5f91d4c0b0c97db83b9e0ca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Jun 2022 18:16:10 +0900 Subject: [PATCH 3028/3664] [vulkan] Partially document bsp rendering This did involve changing some field names and a little bit of cleanup, but I've got a better handle on what's going on (I think I was in one of those coding trances where I quickly forget how things work). --- include/QF/Vulkan/qf_bsp.h | 293 +++++++++++++++++++----- include/QF/Vulkan/qf_vid.h | 3 + libs/video/renderer/vulkan/vulkan_bsp.c | 44 ++-- 3 files changed, 259 insertions(+), 81 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index f1713fcbf..3f3973033 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -39,13 +39,27 @@ #include "QF/simd/types.h" +/** \defgroup vulkan_bsp Brush model rendering + \ingroup vulkan +*/ + +/** Represent a single face (polygon) of a brush model. + * + * There is one of these for each face in the bsp (brush) model, built at run + * time when the model is loaded (actually, after all models are loaded but + * before rendering begins). + */ typedef struct bsp_face_s { - uint32_t first_index; - uint32_t index_count; - uint32_t tex_id; - uint32_t flags; + uint32_t first_index; ///< index of first index in poly_indices + uint32_t index_count; ///< includes primitive restart + uint32_t tex_id; ///< texture bound to this face (maybe animated) + uint32_t flags; ///< face drawing (alpha, side, sky, turb) } bsp_face_t; +/** Represent a brush model, both main and sub-model. + * + * Used for rendering non-world models. + */ typedef struct bsp_model_s { uint32_t first_face; uint32_t face_count; @@ -62,21 +76,57 @@ typedef struct texmip_s { uint32_t offsets[MIPLEVELS]; } texmip_t; #endif +/** \defgroup vulkan_bsp_texanim Animated Textures + * \ingroup vulkan_bsp + * + * Brush models support texture animations. For general details, see + * \ref bsp_texture_animation. These structures allow for quick lookup + * of the correct texture to use in an animation cycle, or even whether there + * is an animation cycle. + */ +///@{ +/** Represent a texture's animation group. + * + * Every texture is in an animation group, even when not animated. When the + * texture is not animated, `count` is 1, otherwise `count` is the number of + * frames in the group, thus every texture has at least one frame. + * + * Each texture in a particular groupp shares the same `base` frame, with + * `offset` giving the texture's relative frame number within the group. + * The current frame is given by `base + (anim_index + offset) % count` where + * `anim_index` is the global time-based texture animation frame. + */ typedef struct texanim_s { - uint16_t base; - byte offset; - byte count; + uint16_t base; ///< first frame in group + byte offset; ///< relative frame in group + byte count; ///< number of frames in group } texanim_t; +/** Holds texture animation data for brush models. + * + * Brush models support one or two texture animation groups, based on the + * entity's frame (0 or non-0). When the entity's frame is 0, group 0 is used, + * otherwise group 1 is used. If there is no alternate (group 1) animation + * data for the texture, then the texture's group 0 data is copied to group 1 + * in order to avoid coplications in selecting which texture a face is to use. + * + * As all of a group's frames are together, `frame_map` is used to get the + * actual texture id for the frame. + */ typedef struct texdata_s { // texname_t *names; // texmip_t **mips; - texanim_t *anim_main; - texanim_t *anim_alt; - uint16_t *anim_map; + texanim_t *anim_main; ///< group 0 animations + texanim_t *anim_alt; ///< group 1 animations + uint16_t *frame_map; ///< map from texture frame to texture id // int num_tex; } texdata_t; +///@} +/** \defgroup vulkan_bsp_draw Brush model drawing + * \ingroup vulkan_bsp + */ +///@{ typedef struct vulktex_s { struct qfv_tex_s *tex; VkDescriptorSet descriptor; @@ -86,57 +136,186 @@ typedef struct vulktex_s { typedef struct regtexset_s DARRAY_TYPE (vulktex_t *) regtexset_t; +/** Represent a single draw call. + * + * For each texture that has faces to be rendered, one or more draw calls is + * made. Normally, only one call per texture is made, but if different models + * use the same texture, then a separate draw call is made for each model. + * When multiple entities use the same model, instanced rendering is used to + * draw all the faces sharing a texture for all the entities using that model. + * Thus when there are multiple draw calls for a single texture, they are + * grouped together so there is only one bind per texture. + * + * The index buffer is populated every frame with the vertex indices of the + * faces to be rendered for the current frame, grouped by texture and instance + * id (model render id). + * + * The model render id is assigned after models are loaded but before rendering + * begins and remains constant until the next time models are loaded (level + * change). + * + * The entid buffer is also populated every frame with the render id of the + * entities to be drawn that frame, It is used to map gl_InstanceIndex to + * entity id so as to look up the entity's transform and color (and any other + * data in the future). + * + * \dot + * digraph vulkan_bsp_draw_call { + * layout=dot; rankdir=LR; compound=true; nodesep=1.0; + * vertices [shape=none,label=< + * + * + * + * + * + *
vertex
vertex
...
vertex
vertex
>]; + * indices [shape=none,label=< + * + * + * + * + * + *
index
index
...
index
index
>]; + * entids [shape=none,label=< + * + * + * + * + * + * + *
entid
...
entid
entid
...
entid
>]; + * entdata [shape=none,label=< + * + * + * + * + * + * + *
transformcolor
transformcolor
...
transformcolor
...
transformcolor
>]; + * drawcall [shape=none,label=< + * + * + * + * + * + * + *
tex_id
inst_id
first_index
index_count
first_instance
instance_count
>]; + * textures [shape=none,label=< + * + * + * + * + * + *
texture
texture
texture
...
texture
>]; + * vertex [label="vertex shader"]; + * fragment [label="fragment shader"]; + * drawcall:tex -> textures:p; + * drawcall:ind -> indices:p; + * drawcall:inst -> entids:p; + * entids:p -> entdata:p; + * indices:p -> vertices:p; + * vertex -> entdata [label="storage buffer"]; + * vertex -> entids [label="per instance"]; + * vertex -> indices [label="index buffer"]; + * vertex -> vertices [label="per vertex"]; + * fragment -> textures [label="per call"]; + * } + * \enddot + */ +///@{ typedef struct bsp_draw_s { - uint32_t tex_id; - uint32_t inst_id; - uint32_t index_count; - uint32_t instance_count; - uint32_t first_index; - uint32_t first_instance; + uint32_t tex_id; ///< texture to bind for this draw call + uint32_t inst_id; ///< model render id owning this draw call + uint32_t index_count; ///< number of indices for this draw call + uint32_t instance_count; ///< number of instances to draw + uint32_t first_index; ///< index into index buffer + uint32_t first_instance; ///< index into entid buffer } bsp_draw_t; typedef struct bsp_drawset_s DARRAY_TYPE (bsp_draw_t) bsp_drawset_t; +///@} +/** Tag models that are to be queued for translucent drawing. + */ #define INST_ALPHA (1u<<31) + +/** Representation of a single face queued for drawing. + */ +///@{ typedef struct instface_s { - uint32_t inst_id; - uint32_t face; + uint32_t inst_id; ///< model render id owning this face + uint32_t face; ///< index of face in context array } instface_t; typedef struct bsp_instfaceset_s DARRAY_TYPE (instface_t) bsp_instfaceset_t; +///@} +/** Track entities using a model. + */ +///@{ typedef struct bsp_modelentset_s DARRAY_TYPE (uint32_t) bsp_modelentset_t; +/** Represent a single model and the entities using it. + */ typedef struct bsp_instance_s { - int first_instance; - bsp_modelentset_t entities; + int first_instance; ///< index into entid buffer + bsp_modelentset_t entities; ///< list of entity render ids using this model } bsp_instance_t; +///@} typedef struct bsp_pass_s { - vec4f_t position; - plane_t *frustum; - const struct mod_brush_s *brush; - struct bspctx_s *bsp_context; - uint32_t *indices; // points into index buffer - uint32_t index_count; // number of indices written to buffer - uint32_t *entid_data; // points into entid buffer - uint32_t entid_count; - int vis_frame; - int *face_frames; - int *leaf_frames; - int *node_frames; - bsp_instfaceset_t *face_queue; - regtexset_t *textures; - int num_queues; - bsp_drawset_t *draw_queues; - uint32_t inst_id; - bsp_instance_t *instances; - int ent_frame; + vec4f_t position; ///< view position + plane_t *frustum; ///< view frustum for culling + const struct mod_brush_s *brush;///< data for current model + struct bspctx_s *bsp_context; ///< owning bsp context + /** \name GPU data + * + * The indices to be drawn and the entity ids associated with each draw + * instance are updated each frame. The pointers are to the per-frame + * mapped buffers for the respective data. + */ + ///@{ + uint32_t *indices; ///< polygon vertex indices + uint32_t index_count; ///< number of indices written to buffer + uint32_t *entid_data; ///< instance id to entity id map + uint32_t entid_count; ///< numer of entids written to buffer + ///@} + /** \name Potentially Visible Sets + * + * For an object to be in the PVS, its frame id must match the current + * visibility frame id, thus clearing all sets is done by incrementing + * `vis_frame`, and adding an object to the PVS is done by setting its + * current frame id to the current visibility frame id. + */ + ///@{ + int vis_frame; ///< current visibility frame id + int *face_frames; ///< per-face visibility frame ids + int *leaf_frames; ///< per-leaf visibility frame ids + int *node_frames; ///< per-node visibility frame ids + ///@} + bsp_instfaceset_t *face_queue; ///< per-texture face queues + regtexset_t *textures; ///< textures to bind when emitting calls + int num_queues; ///< number of pipeline queues + bsp_drawset_t *draw_queues; ///< per-pipeline draw queues + uint32_t inst_id; ///< render id of current model + bsp_instance_t *instances; ///< per-model entid lists + // FIXME There are several potential optimizations here: + // 1) ent_frame could be forced to be 0 or 1 and then used to index a + // two-element array of texanim pointers + // 2) ent_frame could be a pointer to the correct texanim array + // 3) could update a tex_id map each frame and unconditionally index that + // + // As the texture id is used for selecting the face queue, 3 could be used + // for mapping all textures to 1 or two queues for shadow rendering + int ent_frame; ///< animation frame of current entity } bsp_pass_t; +///@} +/// \ingroup vulkan_bsp +///@{ typedef enum { QFV_bspDepth, QFV_bspGBuffer, @@ -159,31 +338,33 @@ typedef struct bspframe_s { typedef struct bspframeset_s DARRAY_TYPE (bspframe_t) bspframeset_t; +/** Main BSP context structure + * + * This holds all the state and resources needed for rendering brush models. + */ typedef struct bspctx_s { - regtexset_t registered_textures; - struct qfv_tex_s *default_skysheet; - struct qfv_tex_s *skysheet_tex; - - struct qfv_tex_s *default_skybox; - struct qfv_tex_s *skybox_tex; - VkDescriptorSet skybox_descriptor; - - vulktex_t notexture; + vulktex_t notexture; ///< replacement for invalid textures struct scrap_s *light_scrap; struct qfv_stagebuf_s *light_stage; - bsp_model_t *models; - bsp_face_t *faces; - uint32_t *poly_indices; + int num_models; ///< number of loaded brush models + bsp_model_t *models; ///< all loaded brush models + bsp_face_t *faces; ///< all faces from all loaded brush models + uint32_t *poly_indices; ///< face indices from all loaded brush models - texdata_t texdata; - int anim_index; + regtexset_t registered_textures;///< textures for all loaded brush models + texdata_t texdata; ///< texture animation data + int anim_index; ///< texture animation frame (5fps) + struct qfv_tex_s *default_skysheet; + struct qfv_tex_s *skysheet_tex; ///< scrolling sky texture for current map - int model_id; + struct qfv_tex_s *default_skybox; + struct qfv_tex_s *skybox_tex; ///< sky box texture for current map + VkDescriptorSet skybox_descriptor; - bsp_pass_t main_pass; // camera view depth, gbuffer, etc + bsp_pass_t main_pass; ///< camera view depth, gbuffer, etc VkSampler sampler; VkPipelineLayout layout; @@ -207,7 +388,6 @@ typedef struct bspctx_s { struct vulkan_ctx_s; struct qfv_renderframe_s; -void Vulkan_ClearElements (struct vulkan_ctx_s *ctx); void Vulkan_DrawWorld (struct qfv_renderframe_s *rFrame); void Vulkan_DrawSky (struct qfv_renderframe_s *rFrame); void Vulkan_DrawWaterSurfaces (struct qfv_renderframe_s *rFrame); @@ -219,5 +399,6 @@ void Vulkan_BuildDisplayLists (model_t **models, int num_models, struct vulkan_ctx_s *ctx); void Vulkan_Bsp_Init (struct vulkan_ctx_s *ctx); void Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx); +///@} #endif//__QF_Vulkan_qf_bsp_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 19d62795d..7df68837b 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -35,6 +35,9 @@ #endif #include +/** \defgroup vulkan Vulkan Renderer +*/ + enum { QFV_rp_shadowmap, QFV_rp_main, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 1020bbefa..96101e26f 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -91,14 +91,12 @@ static const char * __attribute__((used)) bsp_pass_names[] = { }; static QFV_Subpass subpass_map[] = { - QFV_passDepth, // QFV_bspDepth - QFV_passGBuffer, // QFV_bspGBuffer - QFV_passTranslucent, // QFV_bspSky - QFV_passTranslucent, // QFV_bspTurb + [QFV_bspDepth] = QFV_passDepth, + [QFV_bspGBuffer] = QFV_passGBuffer, + [QFV_bspSky] = QFV_passTranslucent, + [QFV_bspTurb] = QFV_passTranslucent, }; -#define ALLOC_CHUNK 64 - static void add_texture (texture_t *tx, vulkan_ctx_t *ctx) { @@ -113,12 +111,6 @@ add_texture (texture_t *tx, vulkan_ctx_t *ctx) } } -void -Vulkan_ClearElements (vulkan_ctx_t *ctx) -{ -// bspctx_t *bctx = ctx->bsp_context; -} - static inline void chain_surface (const bsp_face_t *face, bsp_pass_t *pass, const bspctx_t *bctx) { @@ -128,7 +120,7 @@ chain_surface (const bsp_face_t *face, bsp_pass_t *pass, const bspctx_t *bctx) const texanim_t *anim = ent_frame ? &bctx->texdata.anim_alt[face->tex_id] : &bctx->texdata.anim_main[face->tex_id]; int anim_ind = (bctx->anim_index + anim->offset) % anim->count; - int tex_id = bctx->texdata.anim_map[anim->base + anim_ind]; + int tex_id = bctx->texdata.frame_map[anim->base + anim_ind]; DARRAY_APPEND (&pass->face_queue[tex_id], ((instface_t) { pass->inst_id, face - bctx->faces })); } @@ -165,7 +157,6 @@ clear_textures (vulkan_ctx_t *ctx) void Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) { - clear_textures (ctx); add_texture (r_notexture_mip, ctx); { @@ -209,11 +200,13 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) } } + // 2.5 for two texanim_t structs (32-bits each) and 1 uint16_t for each + // element size_t texdata_size = 2.5 * num_tex * sizeof (texanim_t); texanim_t *texdata = Hunk_AllocName (0, texdata_size, "texdata"); bctx->texdata.anim_main = texdata; bctx->texdata.anim_alt = texdata + num_tex; - bctx->texdata.anim_map = (uint16_t *) (texdata + 2 * num_tex); + bctx->texdata.frame_map = (uint16_t *) (texdata + 2 * num_tex); int16_t map_index = 0; for (int i = 0; i < num_tex; i++) { texanim_t *anim = bctx->texdata.anim_main + i; @@ -222,7 +215,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) continue; } *anim = (texanim_t) { .base = map_index, .offset = 0, .count = 1 }; - bctx->texdata.anim_map[anim->base] = i; + bctx->texdata.frame_map[anim->base] = i; if (textures[i]->anim_total > 1) { // bsp loader multiplies anim_total by ANIM_CYCLE to slow the @@ -240,7 +233,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) } *a = *anim; a->offset = j; - bctx->texdata.anim_map[a->base + a->offset] = vtex->tex_id; + bctx->texdata.frame_map[a->base + a->offset] = vtex->tex_id; tx = tx->anim_next; } if (tx != textures[i]) { @@ -260,6 +253,7 @@ Vulkan_RegisterTextures (model_t **models, int num_models, vulkan_ctx_t *ctx) } } + // create face queue arrays bctx->main_pass.face_queue = malloc (num_tex * sizeof (bsp_instfaceset_t)); for (int i = 0; i < num_tex; i++) { bctx->main_pass.face_queue[i] @@ -379,11 +373,11 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) face_sets[i] = (facerefset_t) DARRAY_STATIC_INIT (1024); } - for (int i = 0; i < bctx->model_id; i++) { + for (int i = 0; i < bctx->num_models; i++) { DARRAY_CLEAR (&bctx->main_pass.instances[i].entities); } free (bctx->main_pass.instances); - bctx->model_id = 0; + bctx->num_models = 0; // run through all surfaces, chaining them to their textures, thus // effectively sorting the surfaces by texture (without worrying about @@ -396,7 +390,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) if (!m || m->type != mod_brush) { continue; } - m->render_id = bctx->model_id++; + m->render_id = bctx->num_models++; if (*m->path == '*') { continue; } @@ -422,9 +416,9 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } face_base += brush->numsurfaces; } - bctx->main_pass.instances = malloc (bctx->model_id + bctx->main_pass.instances = malloc (bctx->num_models * sizeof (bsp_instance_t)); - for (int i = 0; i < bctx->model_id; i++) { + for (int i = 0; i < bctx->num_models; i++) { DARRAY_INIT (&bctx->main_pass.instances[i].entities, 16); } // All vertices from all brush models go into one giant vbo. @@ -469,7 +463,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) free (bctx->faces); free (bctx->poly_indices); free (bctx->models); - bctx->models = malloc (bctx->model_id * sizeof (bsp_model_t)); + bctx->models = malloc (bctx->num_models * sizeof (bsp_model_t)); bctx->faces = malloc (face_base * sizeof (bsp_face_t)); bctx->poly_indices = malloc (index_count * sizeof (uint32_t)); @@ -943,7 +937,7 @@ clear_queues (bspctx_t *bctx, bsp_pass_t *pass) for (int i = 0; i < pass->num_queues; i++) { DARRAY_RESIZE (&pass->draw_queues[i], 0); } - for (int i = 0; i < bctx->model_id; i++) { + for (int i = 0; i < bctx->num_models; i++) { pass->instances[i].first_instance = -1; DARRAY_RESIZE (&pass->instances[i].entities, 0); } @@ -1507,7 +1501,7 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) free (bctx->models); free (bctx->main_pass.draw_queues); - for (int i = 0; i < bctx->model_id; i++) { + for (int i = 0; i < bctx->num_models; i++) { DARRAY_CLEAR (&bctx->main_pass.instances[i].entities); } free (bctx->main_pass.instances); From 4b38d75f2c87e491c9b5ba4b8dcf5dc738880933 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Jun 2022 02:42:30 +0900 Subject: [PATCH 3029/3664] [input] Initialize the axis/button callback fields Found these while trying to use the new code in my KSP addon. --- libs/input/evdev/inputlib.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/input/evdev/inputlib.c b/libs/input/evdev/inputlib.c index 1ac7d15ab..1f678b9b2 100644 --- a/libs/input/evdev/inputlib.c +++ b/libs/input/evdev/inputlib.c @@ -218,6 +218,11 @@ check_device (const char *path) dev->event_count = 0; + dev->data = 0; + dev->axis_event = 0; + dev->button_event = 0; + + //Sys_Printf ("%s:\n", path); //Sys_Printf ("\tname: %s\n", dev->name); //Sys_Printf ("\tbuttons: %d\n", dev->num_buttons); From 784af2bab26c7bf63ba1c5e301dfd0a885fcfe32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 31 Jul 2022 17:05:41 +0900 Subject: [PATCH 3030/3664] [vulkan] Enable the multiview feature As of a recent nvidia driver update, it became necessary to enable the feature. I guess older drivers (or vulkan validation layers?) were a bit slack in their checking (or perhaps I didn't actually get those lighting changes working at the time despite having committed them). --- libs/video/renderer/vulkan/device.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 47df21745..1d42f0c87 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -149,12 +149,16 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 0, 0, family, 1, &priority }; + VkPhysicalDeviceMultiviewFeatures multiview_features = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, + .multiview = 1, + }; VkPhysicalDeviceFeatures features = { .geometryShader = 1, .multiViewport = 1, }; VkDeviceCreateInfo dCreateInfo = { - VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 0, 0, + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, &multiview_features, 0, 1, &qCreateInfo, nlay, lay, next, ext, From 41a6ea35343d6c53efa8dc3b39a9e2fb9c3d417d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 Aug 2022 18:59:51 +0900 Subject: [PATCH 3031/3664] [gamecode] Use adjusted vector string for sscanf There's not much point in converting commas to spaces if the result isn't used. Fixes several malformed vector errors in ad_tears. --- libs/gamecode/pr_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 6f7a032ed..f94f56c62 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -240,7 +240,7 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) *v = ' '; } } - if (sscanf (s, "%f %f %f", VectorExpandAddr (vec)) != 3) { + if (sscanf (str, "%f %f %f", VectorExpandAddr (vec)) != 3) { Sys_Printf ("Malformed vector %s\n", s); } VectorCopy (vec, PR_PTR (vector, d)); From d7be237af956ad4192d76306302cd1284e6bbb49 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 10:33:21 +0900 Subject: [PATCH 3032/3664] [vulkan] Fix a merge dropping that missed a conview change --- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 09145ae25..f1f782277 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -122,7 +122,7 @@ update_lights (vulkan_ctx_t *ctx) } } if (developer & SYS_lighting) { - Vulkan_Draw_String (vid.conview->xlen - 32, 8, + Vulkan_Draw_String (vid.width - 32, 8, va (ctx->va_ctx, "%3d", light_data->lightCount), ctx); } From 3147443617d04c62f81eb465b952e7c71335ce93 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 10:12:12 +0900 Subject: [PATCH 3033/3664] [qwaq] Set the console's screen view I had forgotten to test qwaq when removing console view from viddef_t. --- ruamoko/qwaq/builtins/graphics.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 47f51a9cc..e31aa1d27 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -55,6 +55,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/math/bitop.h" #include "QF/plugin/console.h" +#include "QF/plugin/vid_render.h" #include "rua_internal.h" #include "r_font.h" @@ -346,6 +347,7 @@ BI_Graphics_Init (progs_t *pr) con_module->data->console->frametime = &con_frametime; con_module->data->console->quit = quit_f; con_module->data->console->cbuf = qwaq_cbuf; + con_module->data->console->screen_view = r_data->scr_view; } //Key_SetKeyDest (key_game); From a1813868fcba6e0e990fa294e3d8d7682d66aefb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 10:19:30 +0900 Subject: [PATCH 3034/3664] [qwaq] Copy only those bytes in the colormap tex The fullbright count byte in a colormap is not in the generated colormap texture data. Attempting to read it results in an angry valgrind. --- ruamoko/qwaq/builtins/graphics.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index e31aa1d27..1f408344c 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -303,7 +303,10 @@ generate_colormap (void) memcpy (colors[i][224], colors[31][224], 32 * 3); } tex_t *cmap = ConvertImage (&tex, default_palette[0]); - memcpy (default_colormap, cmap->data, sizeof (default_colormap)); + // the colormap has an extra byte indicating the number of fullbright + // entries, but that byte is not in the image, so don't try to copy it, + // thus the - 1 + memcpy (default_colormap, cmap->data, sizeof (default_colormap) - 1); free (cmap); } From d1f69457470ba524a2e76e65adec14fbc180d819 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 10:33:32 +0900 Subject: [PATCH 3035/3664] [renderer] Avoid gl/glsl segfault when resizing qwaq qwaq doesn't supply a backtile pic, so Draw_TileClear in the gl and glsl renderers would segfault when qwaq's window width changed due to some back-tile being drawn. --- libs/video/renderer/gl/gl_draw.c | 3 +++ libs/video/renderer/glsl/glsl_draw.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 7b79dfc13..a6836c4aa 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -885,6 +885,9 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) void gl_Draw_TileClear (int x, int y, int w, int h) { + if (!draw_backtile) { + return; + } glpic_t *gl; qfglColor3ubv (color_0_8); gl = (glpic_t *) draw_backtile->data; diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index c58352a03..33220a559 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -440,6 +440,9 @@ glsl_Draw_Init (void) white_pic = pic_data ("white_block", 8, 8, white_block); backtile_pic = glsl_Draw_PicFromWad ("backtile"); + if (!backtile_pic) { + backtile_pic = white_pic; + } //FIXME gl = (glpic_t *) backtile_pic->data; //FIXME qfeglBindTexture (GL_TEXTURE_2D, gl->texnum); //FIXME qfeglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); From 4be532dcba7e453b352addb96243c6c89e59013d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 13:01:50 +0900 Subject: [PATCH 3036/3664] [models] Include fullbright in vulkan lib I'm not sure why the other renderers are ok with Mod_CalcFullbright, but the vulkan plugin couldn't find it. --- libs/models/Makemodule.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/models/Makemodule.am b/libs/models/Makemodule.am index 982e96a3a..069066ca8 100644 --- a/libs/models/Makemodule.am +++ b/libs/models/Makemodule.am @@ -73,4 +73,4 @@ vulkan_libs= \ libs_models_libmodels_vulkan_la_LDFLAGS= libs_models_libmodels_vulkan_la_LIBADD= $(vulkan_libs) libs_models_libmodels_vulkan_la_DEPENDENCIES= $(vulkan_libs) -libs_models_libmodels_vulkan_la_SOURCES= libs/models/vulkan_skin.c libs/models/skin.c +libs_models_libmodels_vulkan_la_SOURCES= libs/models/vulkan_skin.c libs/models/skin.c libs/models/fullbright.c From 7c09f86d8da7ec30347f27a05364aa52f47b5323 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 13:01:50 +0900 Subject: [PATCH 3037/3664] [models] Include fullbright in vulkan lib I'm not sure why the other renderers are ok with Mod_CalcFullbright, but the vulkan plugin couldn't find it. --- libs/models/Makemodule.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/models/Makemodule.am b/libs/models/Makemodule.am index 982e96a3a..069066ca8 100644 --- a/libs/models/Makemodule.am +++ b/libs/models/Makemodule.am @@ -73,4 +73,4 @@ vulkan_libs= \ libs_models_libmodels_vulkan_la_LDFLAGS= libs_models_libmodels_vulkan_la_LIBADD= $(vulkan_libs) libs_models_libmodels_vulkan_la_DEPENDENCIES= $(vulkan_libs) -libs_models_libmodels_vulkan_la_SOURCES= libs/models/vulkan_skin.c libs/models/skin.c +libs_models_libmodels_vulkan_la_SOURCES= libs/models/vulkan_skin.c libs/models/skin.c libs/models/fullbright.c From 7e03f23146085d47fd637f98f6296c2c43ce3524 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 15:05:49 +0900 Subject: [PATCH 3038/3664] [renderer] Link plugins against external libraries With the addition of dependencies on freetype and harfbuzz, it became clear that the renderer plugins need to be explicitly linked against external dependencies (and that I need to do more installed testing, rather than just my static local builds). This fixes the unresolved symbols when attempting to load any of the plugins. --- libs/video/renderer/Makemodule.am | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index dc43c2874..49999b2ad 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -40,12 +40,13 @@ renderer_libs= \ libs/util/libQFutil.la renderer_libadd= \ - $(renderer_libs) \ $(FREETYPE_LIBS) \ $(HARFBUZZ_LIBS) libs_video_renderer_libQFrenderer_la_LDFLAGS= @STATIC@ -libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libadd) +libs_video_renderer_libQFrenderer_la_LIBADD=\ + $(renderer_libs) \ + $(renderer_libadd) libs_video_renderer_libQFrenderer_la_DEPENDENCIES= $(renderer_libs) libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_bsp.c \ @@ -67,7 +68,9 @@ video_renderer_gl_libs= \ libs/video/renderer/librender_gl.la \ libs/models/libmodels_gl.la libs_video_renderer_vid_render_gl_la_LDFLAGS= $(plugin_ldflags) -libs_video_renderer_vid_render_gl_la_LIBADD= $(video_renderer_gl_libs) +libs_video_renderer_vid_render_gl_la_LIBADD=\ + $(video_renderer_gl_libs) \ + $(renderer_libadd) libs_video_renderer_vid_render_gl_la_DEPENDENCIES= $(video_renderer_gl_libs) libs_video_renderer_vid_render_gl_la_SOURCES=\ $(video_renderer_common_sources) \ @@ -108,7 +111,9 @@ video_renderer_glsl_libs= \ libs/video/renderer/librender_glsl.la \ libs/models/libmodels_glsl.la libs_video_renderer_vid_render_glsl_la_LDFLAGS= $(plugin_ldflags) -libs_video_renderer_vid_render_glsl_la_LIBADD= $(video_renderer_glsl_libs) +libs_video_renderer_vid_render_glsl_la_LIBADD=\ + $(video_renderer_glsl_libs) \ + $(renderer_libadd) libs_video_renderer_vid_render_glsl_la_DEPENDENCIES=$(video_renderer_glsl_libs) libs_video_renderer_vid_render_glsl_la_SOURCES=\ $(video_renderer_common_sources) \ @@ -135,7 +140,9 @@ video_renderer_sw_libs= \ libs/video/renderer/librender_sw.la \ libs/models/libmodels_sw.la libs_video_renderer_vid_render_sw_la_LDFLAGS= $(plugin_ldflags) -libs_video_renderer_vid_render_sw_la_LIBADD= $(video_renderer_sw_libs) +libs_video_renderer_vid_render_sw_la_LIBADD=\ + $(video_renderer_sw_libs) \ + $(renderer_libadd) libs_video_renderer_vid_render_sw_la_DEPENDENCIES= $(video_renderer_sw_libs) libs_video_renderer_vid_render_sw_la_SOURCES=\ $(video_renderer_common_sources) \ @@ -200,7 +207,9 @@ video_renderer_vulkan_libs = \ libs/video/renderer/librender_vulkan.la \ libs/models/libmodels_vulkan.la libs_video_renderer_vid_render_vulkan_la_LDFLAGS= $(plugin_ldflags) -libs_video_renderer_vid_render_vulkan_la_LIBADD= $(video_renderer_vulkan_libs) +libs_video_renderer_vid_render_vulkan_la_LIBADD=\ + $(video_renderer_vulkan_libs) \ + $(renderer_libadd) libs_video_renderer_vid_render_vulkan_la_DEPENDENCIES=$(video_renderer_vulkan_libs) libs_video_renderer_vid_render_vulkan_la_SOURCES = \ $(video_renderer_common_sources) \ From c580fb9ec79198d644339ef59190acb2e380092b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Sep 2022 16:18:53 +0900 Subject: [PATCH 3039/3664] [console] Add a comment about console resizing Due to design issues in the console API that I don't feel like addressing at this stage, the console view is not a child of the client's screen view (not even sure it should be in the first place), so it won't get resized automatically when the client's screen view resizes. However, ie_app_window is sent when the screen size changes, and the console has to process input events anyway, so it's quite reasonable to handle the event. --- libs/console/client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/console/client.c b/libs/console/client.c index 91f512cd1..40ad2ebf2 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -678,6 +678,10 @@ exec_line (inputline_t *il) Con_ExecLine (il->line); } +// The console view is not a child of the client's screen view, so it won't +// get resized automatically when the screen changes size. However, since the +// console has to process input events anyway, handling ie_app_window is a +// reasonable alternative. static void con_app_window (const IE_event_t *event) { From 5e154bf1b772174e97c4747524d871e9797b894f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Sep 2022 18:26:25 +0900 Subject: [PATCH 3040/3664] [cvar] Remove reliance on line number for developer parsing I must have forgotten about the SYS_DeveloperID_... enum values, when I wrote that code, because relying on the line number is not really for the best. --- libs/util/cvar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 2fb374183..155b6a78a 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -74,7 +74,7 @@ static int developer_values[] = { #include "QF/sys_developer.h" }; #undef SYS_DEVELOPER -#define SYS_DEVELOPER(dev) {#dev, &developer_type, developer_values + __LINE__ - 31}, +#define SYS_DEVELOPER(dev) {#dev, &developer_type, developer_values + SYS_DeveloperID_##dev + 1}, static exprsym_t developer_symbols[] = { {"dev", &developer_type, developer_values + 0}, #include "QF/sys_developer.h" From 3f0c257bc1072fafdbe061ee8243f0b3eb8608d2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Sep 2022 18:26:25 +0900 Subject: [PATCH 3041/3664] [cvar] Remove reliance on line number for developer parsing I must have forgotten about the SYS_DeveloperID_... enum values, when I wrote that code, because relying on the line number is not really for the best. --- libs/util/cvar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 2fb374183..155b6a78a 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -74,7 +74,7 @@ static int developer_values[] = { #include "QF/sys_developer.h" }; #undef SYS_DEVELOPER -#define SYS_DEVELOPER(dev) {#dev, &developer_type, developer_values + __LINE__ - 31}, +#define SYS_DEVELOPER(dev) {#dev, &developer_type, developer_values + SYS_DeveloperID_##dev + 1}, static exprsym_t developer_symbols[] = { {"dev", &developer_type, developer_values + 0}, #include "QF/sys_developer.h" From 9e440ff3308d3c3a6bd94fc55279d664d4daa536 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Sep 2022 10:18:06 +0900 Subject: [PATCH 3042/3664] [renderer] Use designated inits on more structs Finally, the model_funcs and render_funcs struts use designated initializers. Not only are they good for ensuring correct initialization, they're great for the programmer finding the right initializer. --- libs/video/renderer/vid_render_gl.c | 136 ++++++++++++------------ libs/video/renderer/vid_render_glsl.c | 136 ++++++++++++------------ libs/video/renderer/vid_render_sw.c | 136 ++++++++++++------------ libs/video/renderer/vid_render_vulkan.c | 136 ++++++++++++------------ 4 files changed, 276 insertions(+), 268 deletions(-) diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 1855d34f8..7ec796c66 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -153,30 +153,31 @@ gl_vid_render_create_context (void *data) } static vid_model_funcs_t model_funcs = { - sizeof (gltex_t), - gl_Mod_LoadLighting, - gl_Mod_SubdivideSurface, - gl_Mod_ProcessTexture, + .texture_render_size = sizeof (gltex_t), - Mod_LoadIQM, - Mod_LoadAliasModel, - Mod_LoadSpriteModel, + .Mod_LoadLighting = gl_Mod_LoadLighting, + .Mod_SubdivideSurface = gl_Mod_SubdivideSurface, + .Mod_ProcessTexture = gl_Mod_ProcessTexture, - gl_Mod_MakeAliasModelDisplayLists, - gl_Mod_LoadAllSkins, - gl_Mod_FinalizeAliasModel, - gl_Mod_LoadExternalSkins, - gl_Mod_IQMFinish, - 1, - gl_Mod_SpriteLoadFrames, + .Mod_LoadIQM = Mod_LoadIQM, + .Mod_LoadAliasModel = Mod_LoadAliasModel, + .Mod_LoadSpriteModel = Mod_LoadSpriteModel, - Skin_Free, - Skin_SetColormap, - Skin_SetSkin, - gl_Skin_SetupSkin, - Skin_SetTranslation, - gl_Skin_ProcessTranslation, - gl_Skin_InitTranslations, + .Mod_MakeAliasModelDisplayLists = gl_Mod_MakeAliasModelDisplayLists, + .Mod_LoadAllSkins = gl_Mod_LoadAllSkins, + .Mod_FinalizeAliasModel = gl_Mod_FinalizeAliasModel, + .Mod_LoadExternalSkins = gl_Mod_LoadExternalSkins, + .Mod_IQMFinish = gl_Mod_IQMFinish, + .alias_cache = 1, + .Mod_SpriteLoadFrames = gl_Mod_SpriteLoadFrames, + + .Skin_Free = Skin_Free, + .Skin_SetColormap = Skin_SetColormap, + .Skin_SetSkin = Skin_SetSkin, + .Skin_SetupSkin = gl_Skin_SetupSkin, + .Skin_SetTranslation = Skin_SetTranslation, + .Skin_ProcessTranslation = gl_Skin_ProcessTranslation, + .Skin_InitTranslations = gl_Skin_InitTranslations, }; static void @@ -498,56 +499,57 @@ gl_capture_screen (capfunc_t callback, void *data) } vid_render_funcs_t gl_vid_render_funcs = { - gl_vid_render_init, - gl_Draw_CharBuffer, - gl_Draw_Character, - gl_Draw_String, - gl_Draw_nString, - gl_Draw_AltString, - gl_Draw_ConsoleBackground, - gl_Draw_Crosshair, - gl_Draw_CrosshairAt, - gl_Draw_TileClear, - gl_Draw_Fill, - gl_Draw_Line, - gl_Draw_TextBox, - gl_Draw_FadeScreen, - gl_Draw_BlendScreen, - gl_Draw_CachePic, - gl_Draw_UncachePic, - gl_Draw_MakePic, - gl_Draw_DestroyPic, - gl_Draw_PicFromWad, - gl_Draw_Pic, - gl_Draw_Picf, - gl_Draw_SubPic, - gl_Draw_AddFont, - gl_Draw_FontString, + .init = gl_vid_render_init, - gl_ParticleSystem, - gl_R_Init, - gl_R_ClearState, - gl_R_LoadSkys, - gl_R_NewScene, - gl_R_LineGraph, - gl_begin_frame, - gl_render_view, - gl_R_DrawParticles, - gl_draw_transparent, - gl_post_process, - gl_set_2d, - gl_end_frame, + .Draw_CharBuffer = gl_Draw_CharBuffer, + .Draw_Character = gl_Draw_Character, + .Draw_String = gl_Draw_String, + .Draw_nString = gl_Draw_nString, + .Draw_AltString = gl_Draw_AltString, + .Draw_ConsoleBackground = gl_Draw_ConsoleBackground, + .Draw_Crosshair = gl_Draw_Crosshair, + .Draw_CrosshairAt = gl_Draw_CrosshairAt, + .Draw_TileClear = gl_Draw_TileClear, + .Draw_Fill = gl_Draw_Fill, + .Draw_Line = gl_Draw_Line, + .Draw_TextBox = gl_Draw_TextBox, + .Draw_FadeScreen = gl_Draw_FadeScreen, + .Draw_BlendScreen = gl_Draw_BlendScreen, + .Draw_CachePic = gl_Draw_CachePic, + .Draw_UncachePic = gl_Draw_UncachePic, + .Draw_MakePic = gl_Draw_MakePic, + .Draw_DestroyPic = gl_Draw_DestroyPic, + .Draw_PicFromWad = gl_Draw_PicFromWad, + .Draw_Pic = gl_Draw_Pic, + .Draw_Picf = gl_Draw_Picf, + .Draw_SubPic = gl_Draw_SubPic, + .Draw_AddFont = gl_Draw_AddFont, + .Draw_FontString = gl_Draw_FontString, - gl_create_cube_map, - gl_create_frame_buffer, - gl_destroy_frame_buffer, - gl_bind_framebuffer, - gl_set_viewport, - gl_set_fov, + .ParticleSystem = gl_ParticleSystem, + .R_Init = gl_R_Init, + .R_ClearState = gl_R_ClearState, + .R_LoadSkys = gl_R_LoadSkys, + .R_NewScene = gl_R_NewScene, + .R_LineGraph = gl_R_LineGraph, + .begin_frame = gl_begin_frame, + .render_view = gl_render_view, + .draw_particles = gl_R_DrawParticles, + .draw_transparent = gl_draw_transparent, + .post_process = gl_post_process, + .set_2d = gl_set_2d, + .end_frame = gl_end_frame, - gl_capture_screen, + .create_cube_map = gl_create_cube_map, + .create_frame_buffer = gl_create_frame_buffer, + .destroy_frame_buffer = gl_destroy_frame_buffer, + .bind_framebuffer = gl_bind_framebuffer, + .set_viewport = gl_set_viewport, + .set_fov = gl_set_fov, - &model_funcs + .capture_screen = gl_capture_screen, + + .model_funcs = &model_funcs }; static general_funcs_t plugin_info_general_funcs = { diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 178ccc83b..5c95998bd 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -64,30 +64,31 @@ glsl_vid_render_create_context (void *data) } static vid_model_funcs_t model_funcs = { - sizeof (glsltex_t), - glsl_Mod_LoadLighting, - 0,//Mod_SubdivideSurface, - glsl_Mod_ProcessTexture, + .texture_render_size = sizeof (glsltex_t), - Mod_LoadIQM, - Mod_LoadAliasModel, - Mod_LoadSpriteModel, + .Mod_LoadLighting = glsl_Mod_LoadLighting, + //.Mod_SubdivideSurface = 0, + .Mod_ProcessTexture = glsl_Mod_ProcessTexture, - glsl_Mod_MakeAliasModelDisplayLists, - glsl_Mod_LoadAllSkins, - glsl_Mod_FinalizeAliasModel, - glsl_Mod_LoadExternalSkins, - glsl_Mod_IQMFinish, - 0, - glsl_Mod_SpriteLoadFrames, + .Mod_LoadIQM = Mod_LoadIQM, + .Mod_LoadAliasModel = Mod_LoadAliasModel, + .Mod_LoadSpriteModel = Mod_LoadSpriteModel, - Skin_Free, - Skin_SetColormap, - Skin_SetSkin, - glsl_Skin_SetupSkin, - Skin_SetTranslation, - glsl_Skin_ProcessTranslation, - glsl_Skin_InitTranslations, + .Mod_MakeAliasModelDisplayLists = glsl_Mod_MakeAliasModelDisplayLists, + .Mod_LoadAllSkins = glsl_Mod_LoadAllSkins, + .Mod_FinalizeAliasModel = glsl_Mod_FinalizeAliasModel, + .Mod_LoadExternalSkins = glsl_Mod_LoadExternalSkins, + .Mod_IQMFinish = glsl_Mod_IQMFinish, + .alias_cache = 0, + .Mod_SpriteLoadFrames = glsl_Mod_SpriteLoadFrames, + + .Skin_Free = Skin_Free, + .Skin_SetColormap = Skin_SetColormap, + .Skin_SetSkin = Skin_SetSkin, + .Skin_SetupSkin = glsl_Skin_SetupSkin, + .Skin_SetTranslation = Skin_SetTranslation, + .Skin_ProcessTranslation = glsl_Skin_ProcessTranslation, + .Skin_InitTranslations = glsl_Skin_InitTranslations, }; static void @@ -442,56 +443,57 @@ glsl_capture_screen (capfunc_t callback, void *data) } vid_render_funcs_t glsl_vid_render_funcs = { - glsl_vid_render_init, - glsl_Draw_CharBuffer, - glsl_Draw_Character, - glsl_Draw_String, - glsl_Draw_nString, - glsl_Draw_AltString, - glsl_Draw_ConsoleBackground, - glsl_Draw_Crosshair, - glsl_Draw_CrosshairAt, - glsl_Draw_TileClear, - glsl_Draw_Fill, - glsl_Draw_Line, - glsl_Draw_TextBox, - glsl_Draw_FadeScreen, - glsl_Draw_BlendScreen, - glsl_Draw_CachePic, - glsl_Draw_UncachePic, - glsl_Draw_MakePic, - glsl_Draw_DestroyPic, - glsl_Draw_PicFromWad, - glsl_Draw_Pic, - glsl_Draw_Picf, - glsl_Draw_SubPic, - glsl_Draw_AddFont, - glsl_Draw_FontString, + .init = glsl_vid_render_init, - glsl_ParticleSystem, - glsl_R_Init, - glsl_R_ClearState, - glsl_R_LoadSkys, - glsl_R_NewScene, - glsl_R_LineGraph, - glsl_begin_frame, - glsl_render_view, - glsl_R_DrawParticles, - glsl_draw_transparent, - glsl_post_process, - glsl_set_2d, - glsl_end_frame, + .Draw_CharBuffer = glsl_Draw_CharBuffer, + .Draw_Character = glsl_Draw_Character, + .Draw_String = glsl_Draw_String, + .Draw_nString = glsl_Draw_nString, + .Draw_AltString = glsl_Draw_AltString, + .Draw_ConsoleBackground = glsl_Draw_ConsoleBackground, + .Draw_Crosshair = glsl_Draw_Crosshair, + .Draw_CrosshairAt = glsl_Draw_CrosshairAt, + .Draw_TileClear = glsl_Draw_TileClear, + .Draw_Fill = glsl_Draw_Fill, + .Draw_Line = glsl_Draw_Line, + .Draw_TextBox = glsl_Draw_TextBox, + .Draw_FadeScreen = glsl_Draw_FadeScreen, + .Draw_BlendScreen = glsl_Draw_BlendScreen, + .Draw_CachePic = glsl_Draw_CachePic, + .Draw_UncachePic = glsl_Draw_UncachePic, + .Draw_MakePic = glsl_Draw_MakePic, + .Draw_DestroyPic = glsl_Draw_DestroyPic, + .Draw_PicFromWad = glsl_Draw_PicFromWad, + .Draw_Pic = glsl_Draw_Pic, + .Draw_Picf = glsl_Draw_Picf, + .Draw_SubPic = glsl_Draw_SubPic, + .Draw_AddFont = glsl_Draw_AddFont, + .Draw_FontString = glsl_Draw_FontString, - glsl_create_cube_map, - glsl_create_frame_buffer, - glsl_destroy_frame_buffer, - glsl_bind_framebuffer, - glsl_set_viewport, - glsl_set_fov, + .ParticleSystem = glsl_ParticleSystem, + .R_Init = glsl_R_Init, + .R_ClearState = glsl_R_ClearState, + .R_LoadSkys = glsl_R_LoadSkys, + .R_NewScene = glsl_R_NewScene, + .R_LineGraph = glsl_R_LineGraph, + .begin_frame = glsl_begin_frame, + .render_view = glsl_render_view, + .draw_particles = glsl_R_DrawParticles, + .draw_transparent = glsl_draw_transparent, + .post_process = glsl_post_process, + .set_2d = glsl_set_2d, + .end_frame = glsl_end_frame, - glsl_capture_screen, + .create_cube_map = glsl_create_cube_map, + .create_frame_buffer = glsl_create_frame_buffer, + .destroy_frame_buffer = glsl_destroy_frame_buffer, + .bind_framebuffer = glsl_bind_framebuffer, + .set_viewport = glsl_set_viewport, + .set_fov = glsl_set_fov, - &model_funcs + .capture_screen = glsl_capture_screen, + + .model_funcs = &model_funcs }; static general_funcs_t plugin_info_general_funcs = { diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index cc237c815..2ac60f9d6 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -73,30 +73,31 @@ sw_vid_render_set_colormap (void *data, const byte *colormap) } static vid_model_funcs_t model_funcs = { - 0, - sw_Mod_LoadLighting, - 0,//Mod_SubdivideSurface, - 0,//Mod_ProcessTexture, + .texture_render_size = 0, - Mod_LoadIQM, - Mod_LoadAliasModel, - Mod_LoadSpriteModel, + .Mod_LoadLighting = sw_Mod_LoadLighting, + .Mod_SubdivideSurface = 0, + .Mod_ProcessTexture = 0, - sw_Mod_MakeAliasModelDisplayLists, - sw_Mod_LoadAllSkins, - 0, - 0, - sw_Mod_IQMFinish, - 1, - sw_Mod_SpriteLoadFrames, + .Mod_LoadIQM = Mod_LoadIQM, + .Mod_LoadAliasModel = Mod_LoadAliasModel, + .Mod_LoadSpriteModel = Mod_LoadSpriteModel, - Skin_Free, - Skin_SetColormap, - Skin_SetSkin, - sw_Skin_SetupSkin, - Skin_SetTranslation, - sw_Skin_ProcessTranslation, - sw_Skin_InitTranslations, + .Mod_MakeAliasModelDisplayLists = sw_Mod_MakeAliasModelDisplayLists, + .Mod_LoadAllSkins = sw_Mod_LoadAllSkins, + .Mod_FinalizeAliasModel = 0, + .Mod_LoadExternalSkins = 0, + .Mod_IQMFinish = sw_Mod_IQMFinish, + .alias_cache = 1, + .Mod_SpriteLoadFrames = sw_Mod_SpriteLoadFrames, + + .Skin_Free = Skin_Free, + .Skin_SetColormap = Skin_SetColormap, + .Skin_SetSkin = Skin_SetSkin, + .Skin_SetupSkin = sw_Skin_SetupSkin, + .Skin_SetTranslation = Skin_SetTranslation, + .Skin_ProcessTranslation = sw_Skin_ProcessTranslation, + .Skin_InitTranslations = sw_Skin_InitTranslations, }; static void @@ -456,56 +457,57 @@ sw_capture_screen (capfunc_t callback, void *data) } vid_render_funcs_t sw_vid_render_funcs = { - sw_vid_render_init, - sw_Draw_CharBuffer, - Draw_Character, - Draw_String, - Draw_nString, - Draw_AltString, - Draw_ConsoleBackground, - Draw_Crosshair, - Draw_CrosshairAt, - Draw_TileClear, - Draw_Fill, - Draw_Line, - Draw_TextBox, - Draw_FadeScreen, - Draw_BlendScreen, - Draw_CachePic, - Draw_UncachePic, - Draw_MakePic, - Draw_DestroyPic, - Draw_PicFromWad, - Draw_Pic, - Draw_Picf, - Draw_SubPic, - Draw_AddFont, - Draw_FontString, + .init = sw_vid_render_init, - sw_ParticleSystem, - sw_R_Init, - R_ClearState, - R_LoadSkys, - R_NewScene, - R_LineGraph, - sw_begin_frame, - sw_render_view, - R_DrawParticles, - sw_draw_transparent, - sw_post_process, - sw_set_2d, - sw_end_frame, + .Draw_CharBuffer = sw_Draw_CharBuffer, + .Draw_Character = Draw_Character, + .Draw_String = Draw_String, + .Draw_nString = Draw_nString, + .Draw_AltString = Draw_AltString, + .Draw_ConsoleBackground = Draw_ConsoleBackground, + .Draw_Crosshair = Draw_Crosshair, + .Draw_CrosshairAt = Draw_CrosshairAt, + .Draw_TileClear = Draw_TileClear, + .Draw_Fill = Draw_Fill, + .Draw_Line = Draw_Line, + .Draw_TextBox = Draw_TextBox, + .Draw_FadeScreen = Draw_FadeScreen, + .Draw_BlendScreen = Draw_BlendScreen, + .Draw_CachePic = Draw_CachePic, + .Draw_UncachePic = Draw_UncachePic, + .Draw_MakePic = Draw_MakePic, + .Draw_DestroyPic = Draw_DestroyPic, + .Draw_PicFromWad = Draw_PicFromWad, + .Draw_Pic = Draw_Pic, + .Draw_Picf = Draw_Picf, + .Draw_SubPic = Draw_SubPic, + .Draw_AddFont = Draw_AddFont, + .Draw_FontString = Draw_FontString, - sw_create_cube_map, - sw_create_frame_buffer, - sw_destroy_frame_buffer, - sw_bind_framebuffer, - sw_set_viewport, - sw_set_fov, + .ParticleSystem = sw_ParticleSystem, + .R_Init = sw_R_Init, + .R_ClearState = R_ClearState, + .R_LoadSkys = R_LoadSkys, + .R_NewScene = R_NewScene, + .R_LineGraph = R_LineGraph, + .begin_frame = sw_begin_frame, + .render_view = sw_render_view, + .draw_particles = R_DrawParticles, + .draw_transparent = sw_draw_transparent, + .post_process = sw_post_process, + .set_2d = sw_set_2d, + .end_frame = sw_end_frame, - sw_capture_screen, + .create_cube_map = sw_create_cube_map, + .create_frame_buffer = sw_create_frame_buffer, + .destroy_frame_buffer = sw_destroy_frame_buffer, + .bind_framebuffer = sw_bind_framebuffer, + .set_viewport = sw_set_viewport, + .set_fov = sw_set_fov, - &model_funcs + .capture_screen = sw_capture_screen, + + .model_funcs = &model_funcs }; static general_funcs_t plugin_info_general_funcs = { diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 664f22216..6f9e2104d 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -670,30 +670,31 @@ vulkan_vid_render_create_context (void *data) } static vid_model_funcs_t model_funcs = { - sizeof (vulktex_t) + 2 * sizeof (qfv_tex_t), - vulkan_Mod_LoadLighting, - vulkan_Mod_SubdivideSurface, - vulkan_Mod_ProcessTexture, + .texture_render_size = sizeof (vulktex_t) + 2 * sizeof (qfv_tex_t), - Mod_LoadIQM, - Mod_LoadAliasModel, - Mod_LoadSpriteModel, + .Mod_LoadLighting = vulkan_Mod_LoadLighting, + .Mod_SubdivideSurface = vulkan_Mod_SubdivideSurface, + .Mod_ProcessTexture = vulkan_Mod_ProcessTexture, - vulkan_Mod_MakeAliasModelDisplayLists, - vulkan_Mod_LoadAllSkins, - vulkan_Mod_FinalizeAliasModel, - vulkan_Mod_LoadExternalSkins, - vulkan_Mod_IQMFinish, - 0, - vulkan_Mod_SpriteLoadFrames, + .Mod_LoadIQM = Mod_LoadIQM, + .Mod_LoadAliasModel = Mod_LoadAliasModel, + .Mod_LoadSpriteModel = Mod_LoadSpriteModel, - Skin_Free, - Skin_SetColormap, - Skin_SetSkin, - vulkan_Skin_SetupSkin, - Skin_SetTranslation, - vulkan_Skin_ProcessTranslation, - vulkan_Skin_InitTranslations, + .Mod_MakeAliasModelDisplayLists = vulkan_Mod_MakeAliasModelDisplayLists, + .Mod_LoadAllSkins = vulkan_Mod_LoadAllSkins, + .Mod_FinalizeAliasModel = vulkan_Mod_FinalizeAliasModel, + .Mod_LoadExternalSkins = vulkan_Mod_LoadExternalSkins, + .Mod_IQMFinish = vulkan_Mod_IQMFinish, + .alias_cache = 0, + .Mod_SpriteLoadFrames = vulkan_Mod_SpriteLoadFrames, + + .Skin_Free = Skin_Free, + .Skin_SetColormap = Skin_SetColormap, + .Skin_SetSkin = Skin_SetSkin, + .Skin_SetupSkin = vulkan_Skin_SetupSkin, + .Skin_SetTranslation = Skin_SetTranslation, + .Skin_ProcessTranslation = vulkan_Skin_ProcessTranslation, + .Skin_InitTranslations = vulkan_Skin_InitTranslations, }; static void @@ -750,56 +751,57 @@ vulkan_vid_render_shutdown (void) } vid_render_funcs_t vulkan_vid_render_funcs = { - vulkan_vid_render_init, - vulkan_Draw_CharBuffer, - vulkan_Draw_Character, - vulkan_Draw_String, - vulkan_Draw_nString, - vulkan_Draw_AltString, - vulkan_Draw_ConsoleBackground, - vulkan_Draw_Crosshair, - vulkan_Draw_CrosshairAt, - vulkan_Draw_TileClear, - vulkan_Draw_Fill, - vulkan_Draw_Line, - vulkan_Draw_TextBox, - vulkan_Draw_FadeScreen, - vulkan_Draw_BlendScreen, - vulkan_Draw_CachePic, - vulkan_Draw_UncachePic, - vulkan_Draw_MakePic, - vulkan_Draw_DestroyPic, - vulkan_Draw_PicFromWad, - vulkan_Draw_Pic, - vulkan_Draw_Picf, - vulkan_Draw_SubPic, - vulkan_Draw_AddFont, - vulkan_Draw_FontString, + .init = vulkan_vid_render_init, - vulkan_ParticleSystem, - vulkan_R_Init, - vulkan_R_ClearState, - vulkan_R_LoadSkys, - vulkan_R_NewScene, - vulkan_R_LineGraph, - vulkan_begin_frame, - vulkan_render_view, - vulkan_draw_particles, - vulkan_draw_transparent, - vulkan_post_process, - vulkan_set_2d, - vulkan_end_frame, + .Draw_CharBuffer = vulkan_Draw_CharBuffer, + .Draw_Character = vulkan_Draw_Character, + .Draw_String = vulkan_Draw_String, + .Draw_nString = vulkan_Draw_nString, + .Draw_AltString = vulkan_Draw_AltString, + .Draw_ConsoleBackground = vulkan_Draw_ConsoleBackground, + .Draw_Crosshair = vulkan_Draw_Crosshair, + .Draw_CrosshairAt = vulkan_Draw_CrosshairAt, + .Draw_TileClear = vulkan_Draw_TileClear, + .Draw_Fill = vulkan_Draw_Fill, + .Draw_Line = vulkan_Draw_Line, + .Draw_TextBox = vulkan_Draw_TextBox, + .Draw_FadeScreen = vulkan_Draw_FadeScreen, + .Draw_BlendScreen = vulkan_Draw_BlendScreen, + .Draw_CachePic = vulkan_Draw_CachePic, + .Draw_UncachePic = vulkan_Draw_UncachePic, + .Draw_MakePic = vulkan_Draw_MakePic, + .Draw_DestroyPic = vulkan_Draw_DestroyPic, + .Draw_PicFromWad = vulkan_Draw_PicFromWad, + .Draw_Pic = vulkan_Draw_Pic, + .Draw_Picf = vulkan_Draw_Picf, + .Draw_SubPic = vulkan_Draw_SubPic, + .Draw_AddFont = vulkan_Draw_AddFont, + .Draw_FontString = vulkan_Draw_FontString, - vulkan_create_cube_map, - vulkan_create_frame_buffer, - vulkan_destroy_frame_buffer, - vulkan_bind_framebuffer, - vulkan_set_viewport, - vulkan_set_fov, + .ParticleSystem = vulkan_ParticleSystem, + .R_Init = vulkan_R_Init, + .R_ClearState = vulkan_R_ClearState, + .R_LoadSkys = vulkan_R_LoadSkys, + .R_NewScene = vulkan_R_NewScene, + .R_LineGraph = vulkan_R_LineGraph, + .begin_frame = vulkan_begin_frame, + .render_view = vulkan_render_view, + .draw_particles = vulkan_draw_particles, + .draw_transparent = vulkan_draw_transparent, + .post_process = vulkan_post_process, + .set_2d = vulkan_set_2d, + .end_frame = vulkan_end_frame, - vulkan_capture_screen, + .create_cube_map = vulkan_create_cube_map, + .create_frame_buffer = vulkan_create_frame_buffer, + .destroy_frame_buffer = vulkan_destroy_frame_buffer, + .bind_framebuffer = vulkan_bind_framebuffer, + .set_viewport = vulkan_set_viewport, + .set_fov = vulkan_set_fov, - &model_funcs + .capture_screen = vulkan_capture_screen, + + .model_funcs = &model_funcs }; static general_funcs_t plugin_info_general_funcs = { From 0ecdd0e86be525de3f0d8620d440d81cd957d90f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Sep 2022 09:52:14 +0900 Subject: [PATCH 3043/3664] [vulkan] Rearrange init code in preparation for resizing I've found and mostly isolated the parts of the code that will be affected by window resizing, minus pipelines but they use dynamic viewport and scissor settings and thus shouldn't be affected so long as the swapchain format doesn't change (how does that happen?) --- include/QF/Vulkan/qf_renderpass.h | 2 ++ libs/video/renderer/vid_render_vulkan.c | 5 +++-- libs/video/renderer/vulkan/vulkan_renderpass.c | 9 +++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index 3cd50ae30..d459f8d99 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -64,5 +64,7 @@ qfv_renderpass_t *Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx, qfv_draw_t draw); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx, qfv_renderpass_t *renderpass); +void Vulkan_CreateAttachments (struct vulkan_ctx_s *ctx, + qfv_renderpass_t *renderpass); #endif//__QF_Vulkan_renderpass_h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 6f9e2104d..59a038056 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -87,11 +87,12 @@ static void vulkan_R_Init (void) { Vulkan_CreateStagingBuffers (vulkan_ctx); - Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx); + Vulkan_Texture_Init (vulkan_ctx); + + Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); Vulkan_CreateRenderPasses (vulkan_ctx); - Vulkan_Texture_Init (vulkan_ctx); Vulkan_Matrix_Init (vulkan_ctx); Vulkan_Scene_Init (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 6ddf82136..2b53e83ae 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -74,10 +74,11 @@ get_image_size (VkImage image, qfv_device_t *device) return size; } -static void -create_attachements (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +void +Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) { qfv_device_t *device = ctx->device; + __auto_type rp = renderpass; plitem_t *item = get_rp_item (ctx, rp, "images"); if (!item) { @@ -252,13 +253,13 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, init_renderframe (ctx, rp, &rp->frames.a[i]); } - create_attachements (ctx, rp); - item = get_rp_item (ctx, rp, "clearValues"); rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef); rp->draw = draw; + Vulkan_CreateAttachments (ctx, rp); + return rp; } From d5586730a44e260c522a4112101c3cfab2cdc6d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Sep 2022 10:07:12 +0900 Subject: [PATCH 3044/3664] [vulkan] Remove redundant pipeline dynamic setting As gbuf_base derives from the base pipeline, it inherits base's dynamic setting, and thus doesn't need its own. I had a FIXME there as I wasn't sure why I had a redundant setting, but I really can't see why I'd want it different from any of the other main renderpass pipelines. --- libs/video/renderer/vulkan/qfpipeline.plist | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index f5d5bfc10..a73647418 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -695,9 +695,6 @@ subpass = 2; rasterization = $properties.rasterization.cw_cull_back; depthStencil = $properties.depthStencil.test_only; - dynamic = {//FIXME why? - dynamicState = ( viewport, scissor ); - }; }; comp_base = { @inherit = $properties.pipelines.base; From 22276ad35649202ecac3fd93aa5334a1677d926f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Sep 2022 11:49:11 +0900 Subject: [PATCH 3045/3664] [vulkan] Remove double destroy of the old swapchain I had forgotten that QFV_CreateSwapchain destroys the old swapchain when I wrote Vulkan_CreateSwapchain. --- libs/video/renderer/vulkan/vulkan_vid_common.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index c107a080a..bc3036736 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -284,10 +284,6 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) free (ctx->swapchain); } ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain); - if (old_swapchain && ctx->swapchain->swapchain != old_swapchain) { - ctx->device->funcs->vkDestroySwapchainKHR (ctx->device->dev, - old_swapchain, 0); - } } static void From 1d50940c2a61b4e1c0bed656c7c19bc511d3f167 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Sep 2022 13:04:56 +0900 Subject: [PATCH 3046/3664] [vulkan] Implement window resize support There's a problem with screenshot capture in that the image is sheared after window resize, but the screen view looks good, and vulkan is happy with the state changes. --- include/QF/Vulkan/qf_renderpass.h | 1 + include/vid_vulkan.h | 2 + libs/video/renderer/vid_render_vulkan.c | 29 ++++++++- libs/video/renderer/vulkan/swapchain.c | 2 + libs/video/renderer/vulkan/vulkan_main.c | 1 + .../video/renderer/vulkan/vulkan_renderpass.c | 65 +++++++++++++------ .../video/renderer/vulkan/vulkan_vid_common.c | 9 +++ 7 files changed, 87 insertions(+), 22 deletions(-) diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index d459f8d99..98a178cf3 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -44,6 +44,7 @@ typedef struct qfv_renderpass_s { struct qfv_imageset_s *attachment_images; struct qfv_imageviewset_s *attachment_views; VkDeviceMemory attachmentMemory; + size_t attachmentMemory_size; qfv_framebufferset_t *framebuffers; VkViewport viewport; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 89e888d2e..709755538 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -81,6 +81,8 @@ typedef struct vulkan_ctx_s { size_t curFrame; vulkan_frameset_t frames; qfv_renderpassset_t renderPasses; + //FIXME for resize, but should be a set + struct qfv_renderpass_s *main_renderpass; struct qfv_capture_s *capture; void (*capture_callback) (const byte *data, int width, int height); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 59a038056..3ad5d3f82 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -293,9 +293,32 @@ vulkan_begin_frame (void) __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); - QFV_AcquireNextImage (vulkan_ctx->swapchain, - frame->imageAvailableSemaphore, - 0, &imageIndex); + if (!QFV_AcquireNextImage (vulkan_ctx->swapchain, + frame->imageAvailableSemaphore, + 0, &imageIndex)) { + QFV_DeviceWaitIdle (device); + if (vulkan_ctx->capture) { + QFV_DestroyCapture (vulkan_ctx->capture); + } + Vulkan_CreateSwapchain (vulkan_ctx); + Vulkan_CreateCapture (vulkan_ctx); + + //FIXME + qfv_output_t output = { + .extent = vulkan_ctx->swapchain->extent, + .view = vulkan_ctx->swapchain->imageViews->a[0], + .format = vulkan_ctx->swapchain->format, + .view_list = vulkan_ctx->swapchain->imageViews->a, + }; + vulkan_ctx->main_renderpass->viewport.width = output.extent.width; + vulkan_ctx->main_renderpass->viewport.height = output.extent.height; + vulkan_ctx->main_renderpass->scissor.extent = output.extent; + vulkan_ctx->output = output; + Vulkan_CreateAttachments (vulkan_ctx, vulkan_ctx->main_renderpass); + QFV_AcquireNextImage (vulkan_ctx->swapchain, + frame->imageAvailableSemaphore, + 0, &imageIndex); + } vulkan_ctx->swapImageIndex = imageIndex; } diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index d55c5e4eb..a2a962409 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -8,7 +8,9 @@ #include "QF/cvar.h" #include "QF/mathlib.h" +#include "QF/va.h" +#include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 4098a4336..877e45d03 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -180,4 +180,5 @@ Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) &output, main_draw); rp->order = QFV_rp_main; DARRAY_APPEND (&ctx->renderPasses, rp); + ctx->main_renderpass = rp; } diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 2b53e83ae..6a72b447a 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -74,10 +74,24 @@ get_image_size (VkImage image, qfv_device_t *device) return size; } +static void +destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + for (size_t i = 0; i < rp->framebuffers->size; i++) { + dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0); + } + free (rp->framebuffers); + rp->framebuffers = 0; +} + void Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) { qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; __auto_type rp = renderpass; plitem_t *item = get_rp_item (ctx, rp, "images"); @@ -85,19 +99,44 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) return; } + if (renderpass->framebuffers) { + destroy_framebuffers (ctx, renderpass); + } + if (rp->attachment_views) { + for (size_t i = 0; i < rp->attachment_views->size; i++) { + dfunc->vkDestroyImageView (device->dev, + rp->attachment_views->a[i], 0); + } + free (rp->attachment_views); + rp->attachment_views = 0; + } + if (rp->attachment_images) { + for (size_t i = 0; i < rp->attachment_images->size; i++) { + dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); + } + free (rp->attachment_images); + rp->attachment_images = 0; + } + __auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef); rp->attachment_images = images; size_t memSize = 0; for (size_t i = 0; i < images->size; i++) { memSize += get_image_size (images->a[i], device); } - VkDeviceMemory mem; - mem = QFV_AllocImageMemory (device, images->a[0], - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - memSize, 0); - rp->attachmentMemory = mem; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - mem, "memory:framebuffers"); + VkDeviceMemory mem = rp->attachmentMemory; + if (memSize > rp->attachmentMemory_size) { + if (rp->attachmentMemory) { + dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); + } + rp->attachmentMemory_size = memSize; + mem = QFV_AllocImageMemory (device, images->a[0], + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + memSize, 0); + rp->attachmentMemory = mem; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, + mem, "memory:framebuffers"); + } size_t offset = 0; for (size_t i = 0; i < images->size; i++) { QFV_BindImageMemory (device, images->a[i], mem, offset); @@ -179,18 +218,6 @@ destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } } -static void -destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - for (size_t i = 0; i < rp->framebuffers->size; i++) { - dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0); - } - free (rp->framebuffers); -} - qfv_renderpass_t * Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, qfv_output_t *output, qfv_draw_t draw) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index bc3036736..a62e84f58 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -280,7 +280,16 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) { VkSwapchainKHR old_swapchain = 0; if (ctx->swapchain) { + //FIXME this shouldn't be here + qfv_device_t *device = ctx->swapchain->device; + VkDevice dev = device->dev; + qfv_devfuncs_t *dfunc = device->funcs; old_swapchain = ctx->swapchain->swapchain; + for (size_t i = 0; i < ctx->swapchain->imageViews->size; i++) { + dfunc->vkDestroyImageView(dev, ctx->swapchain->imageViews->a[i], 0); + } + free (ctx->swapchain->images); + free (ctx->swapchain->imageViews); free (ctx->swapchain); } ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain); From 950d6d14723b42b0903c5d22c18032d39be2a4b6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Sep 2022 13:08:02 +0900 Subject: [PATCH 3047/3664] [vulkan] Name the default magenta array view It hasn't caused any problems, but the more objects I can name, the better. --- libs/video/renderer/vulkan/vulkan_texture.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 5c4b9cba3..8c38805ec 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -481,6 +481,9 @@ Vulkan_Texture_Init (vulkan_ctx_t *ctx) VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); + qfv_device_t *device = ctx->device; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, tex->view, + "iview:default_magenta_array"); qfvPopDebug (ctx); } From 71e07e645414652893d8aa9e71f1c4377724146c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Sep 2022 15:54:20 +0900 Subject: [PATCH 3048/3664] [vulkan] Use vkCmdCopyImageToBuffer for screenshot capture I had missed that vkCmdCopyImage requires the source and destination images to have exactly the same size, and I guess assumed that the swapchain images would always be the size they said they were, but this is not the case for tiled-optimal images. However, vkCmdCopyImageToBuffer does the right thing regardless of the source image size. This fixes the skewed screenshots when the window size is not a multiple of 8 (for me, might differ for others). --- include/QF/Vulkan/capture.h | 4 +- libs/video/renderer/vid_render_vulkan.c | 3 +- libs/video/renderer/vulkan/capture.c | 131 ++++++++---------------- 3 files changed, 46 insertions(+), 92 deletions(-) diff --git a/include/QF/Vulkan/capture.h b/include/QF/Vulkan/capture.h index c3043ae59..7210154bc 100644 --- a/include/QF/Vulkan/capture.h +++ b/include/QF/Vulkan/capture.h @@ -10,9 +10,8 @@ #include "QF/qtypes.h" typedef struct qfv_capture_image_s { - VkImage image; - VkImageLayout layout; VkCommandBuffer cmd; + VkBuffer buffer; byte *data; } qfv_capture_image_t; @@ -25,7 +24,6 @@ typedef struct qfv_capture_image_set_s typedef struct qfv_capture_s { struct qfv_device_s *device; - int canBlit; VkExtent2D extent; qfv_capture_image_set_t *image_set; size_t imgsize; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 3ad5d3f82..2b2f29e34 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -558,8 +558,7 @@ capture_screenshot (const byte *data, int width, int height) tex->flagbits = 0; tex->loaded = 1; - if (!vulkan_ctx->capture->canBlit || - is_bgr (vulkan_ctx->swapchain->format)) { + if (is_bgr (vulkan_ctx->swapchain->format)) { tex->bgr = 1; } const byte *src = data; diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c index 53da1560f..694ddb491 100644 --- a/libs/video/renderer/vulkan/capture.c +++ b/libs/video/renderer/vulkan/capture.c @@ -28,6 +28,7 @@ # include "config.h" #endif +#include "QF/Vulkan/buffer.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" @@ -42,7 +43,6 @@ QFV_CreateCapture (qfv_device_t *device, int numframes, qfv_instfuncs_t *ifunc = device->physDev->instance->funcs; qfv_devfuncs_t *dfunc = device->funcs; VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; - int canBlit = 1; VkFormatProperties format_props; ifunc->vkGetPhysicalDeviceFormatProperties (device->physDev->dev, @@ -52,66 +52,38 @@ QFV_CreateCapture (qfv_device_t *device, int numframes, Sys_Printf ("Swapchain does not support reading. FIXME\n"); return 0; } - if (!(format_props.optimalTilingFeatures - & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) { - Sys_MaskPrintf (SYS_vulkan, - "Device does not support blitting from optimal tiled " - "images.\n"); - canBlit = 0; - } ifunc->vkGetPhysicalDeviceFormatProperties (device->physDev->dev, format, &format_props); - if (!(format_props.linearTilingFeatures - & VK_FORMAT_FEATURE_BLIT_DST_BIT)) { - Sys_MaskPrintf (SYS_vulkan, - "Device does not support blitting from optimal tiled " - "images.\n"); - canBlit = 0; - } qfv_capture_t *capture = malloc (sizeof (qfv_capture_t)); capture->device = device; - capture->canBlit = canBlit; capture->extent = swapchain->extent; capture->image_set = QFV_AllocCaptureImageSet (numframes, malloc); __auto_type cmdset = QFV_AllocCommandBufferSet (numframes, alloca); QFV_AllocateCommandBuffers (device, cmdPool, 1, cmdset); - VkImageCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .imageType = VK_IMAGE_TYPE_2D, - .format = format, - .extent = { swapchain->extent.width, swapchain->extent.height, 1 }, - .arrayLayers = 1, - .mipLevels = 1, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_LINEAR, - .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT, - }; - + capture->imgsize = QFV_GetImageSize (device, + swapchain->images->a[0]); for (int i = 0; i < numframes; i++) { __auto_type image = &capture->image_set->a[i]; - dfunc->vkCreateImage (device->dev, &createInfo, 0, &image->image); - image->layout = VK_IMAGE_LAYOUT_UNDEFINED; - image->cmd = cmdset->a[i]; + image->buffer = QFV_CreateBuffer (device, capture->imgsize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT); } - capture->imgsize = QFV_GetImageSize (device, - capture->image_set->a[0].image); capture->memsize = numframes * capture->imgsize; - capture->memory = QFV_AllocImageMemory (device, - capture->image_set->a[0].image, - VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - capture->memsize, 0); + capture->memory = QFV_AllocBufferMemory (device, + capture->image_set->a[0].buffer, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + capture->memsize, 0); dfunc->vkMapMemory (device->dev, capture->memory, 0, capture->memsize, 0, (void **) &capture->data); for (int i = 0; i < numframes; i++) { __auto_type image = &capture->image_set->a[i]; + image->cmd = cmdset->a[i]; image->data = capture->data + i * capture->imgsize; - dfunc->vkBindImageMemory (device->dev, image->image, capture->memory, - image->data - capture->data); + QFV_BindBufferMemory (device, image->buffer, capture->memory, + i * capture->imgsize); } return capture; } @@ -124,7 +96,7 @@ QFV_DestroyCapture (qfv_capture_t *capture) for (size_t i = 0; i < capture->image_set->size; i++) { __auto_type image = &capture->image_set->a[i]; - dfunc->vkDestroyImage (device->dev, image->image, 0); + dfunc->vkDestroyBuffer (device->dev, image->buffer, 0); } dfunc->vkUnmapMemory (device->dev, capture->memory); dfunc->vkFreeMemory (device->dev, capture->memory, 0); @@ -132,35 +104,21 @@ QFV_DestroyCapture (qfv_capture_t *capture) free (capture); } -static void -blit_image (qfv_capture_t *capture, qfv_devfuncs_t *dfunc, - VkImage scImage, qfv_capture_image_t *image) -{ - VkImageBlit blit = { - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, - { { }, { capture->extent.width, capture->extent.height, 1 } }, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, - { { }, { capture->extent.width, capture->extent.height, 1 } }, - }; - dfunc->vkCmdBlitImage (image->cmd, - scImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - 1, &blit, VK_FILTER_NEAREST); -} - static void copy_image (qfv_capture_t *capture, qfv_devfuncs_t *dfunc, VkImage scImage, qfv_capture_image_t *image) { - VkImageCopy copy = { - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, { }, - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, { }, - { capture->extent.width, capture->extent.height, 1 }, + VkBufferImageCopy copy = { + .bufferOffset = 0, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, + .imageOffset = { }, + .imageExtent = { capture->extent.width, capture->extent.height, 1 }, }; - dfunc->vkCmdCopyImage (image->cmd, - scImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ©); + dfunc->vkCmdCopyImageToBuffer (image->cmd, scImage, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image->buffer, 1, ©); } VkCommandBuffer @@ -181,16 +139,17 @@ QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame) }; dfunc->vkBeginCommandBuffer (image->cmd, &beginInfo); - VkImageMemoryBarrier start_barriers[] = { + VkBufferMemoryBarrier start_buffer_barriers[] = { { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .srcAccessMask = 0, .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .oldLayout = image->layout, - .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .image = image->image, - .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }, + .buffer = image->buffer, + .offset = 0, + .size = VK_WHOLE_SIZE, }, + }; + VkImageMemoryBarrier start_image_barriers[] = { { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .srcAccessMask = VK_ACCESS_MEMORY_READ_BIT, @@ -201,16 +160,17 @@ QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame) .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }, }, }; - VkImageMemoryBarrier end_barriers[] = { + VkBufferMemoryBarrier end_buffer_barriers[] = { { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - .newLayout = VK_IMAGE_LAYOUT_GENERAL, - .image = image->image, - .subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }, + .buffer = image->buffer, + .offset = 0, + .size = VK_WHOLE_SIZE, }, + }; + VkImageMemoryBarrier end_image_barriers[] = { { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT, @@ -225,21 +185,18 @@ QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame) dfunc->vkCmdPipelineBarrier (image->cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, 0, 0, 0, - 2, start_barriers); + 0, 0, 0, + 1, start_buffer_barriers, + 1, start_image_barriers); - if (capture->canBlit) { - blit_image (capture, dfunc, scImage, image); - } else { - copy_image (capture, dfunc, scImage, image); - } + copy_image (capture, dfunc, scImage, image); dfunc->vkCmdPipelineBarrier (image->cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, - 0, 0, 0, 0, 0, - 2, end_barriers); - image->layout = VK_IMAGE_LAYOUT_GENERAL; + 0, 0, 0, + 1, end_buffer_barriers, + 1, end_image_barriers); dfunc->vkEndCommandBuffer (image->cmd); From 10f85edb212699bfe33ff5a91e258c7a22d6cf82 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Sep 2022 02:46:09 +0900 Subject: [PATCH 3049/3664] [vulkan] Calculate the size of the capture buffer It turns out that using the swapchain image for the size requirements is unreliable: when running under renderdoc, vkGetImageMemoryRequirements sets the memory requirements fields to 0, leading eventually to a null memory object being passed to vkMapMemory, which does not end well. --- libs/video/renderer/vulkan/capture.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c index 694ddb491..c61a139fb 100644 --- a/libs/video/renderer/vulkan/capture.c +++ b/libs/video/renderer/vulkan/capture.c @@ -42,7 +42,6 @@ QFV_CreateCapture (qfv_device_t *device, int numframes, { qfv_instfuncs_t *ifunc = device->physDev->instance->funcs; qfv_devfuncs_t *dfunc = device->funcs; - VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; VkFormatProperties format_props; ifunc->vkGetPhysicalDeviceFormatProperties (device->physDev->dev, @@ -52,8 +51,6 @@ QFV_CreateCapture (qfv_device_t *device, int numframes, Sys_Printf ("Swapchain does not support reading. FIXME\n"); return 0; } - ifunc->vkGetPhysicalDeviceFormatProperties (device->physDev->dev, format, - &format_props); qfv_capture_t *capture = malloc (sizeof (qfv_capture_t)); capture->device = device; @@ -63,13 +60,19 @@ QFV_CreateCapture (qfv_device_t *device, int numframes, __auto_type cmdset = QFV_AllocCommandBufferSet (numframes, alloca); QFV_AllocateCommandBuffers (device, cmdPool, 1, cmdset); - capture->imgsize = QFV_GetImageSize (device, - swapchain->images->a[0]); + //FIXME assumes the swapchain is 32bpp + capture->imgsize = swapchain->extent.width * swapchain->extent.height * 4; + for (int i = 0; i < numframes; i++) { __auto_type image = &capture->image_set->a[i]; image->buffer = QFV_CreateBuffer (device, capture->imgsize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); } + VkMemoryRequirements req; + dfunc->vkGetBufferMemoryRequirements (device->dev, + capture->image_set->a[0].buffer, + &req); + capture->imgsize = QFV_NextOffset (capture->imgsize, &req); capture->memsize = numframes * capture->imgsize; capture->memory = QFV_AllocBufferMemory (device, capture->image_set->a[0].buffer, From df6f51b89149bbd2cbd7283871383c2e3b923d0d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Sep 2022 18:29:13 +0900 Subject: [PATCH 3050/3664] [glsl] Fix some mangled whitespace --- libs/video/renderer/glsl/glsl_draw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 33220a559..7fb50c965 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -650,12 +650,12 @@ glsl_Draw_ConsoleBackground (int lines, byte alpha) float ofs = (vid.height - lines) / (float) vid.height; quat_t color = {1, 1, 1, bound (0, alpha, 255) / 255.0}; drawvert_t verts[] = { - {{ 0, 0, 0, ofs}}, + {{ 0, 0, 0, ofs}}, {{vid.width, 0, 1, ofs}}, {{vid.width, lines, 1, 1}}, - {{ 0, 0, 0, ofs}}, + {{ 0, 0, 0, ofs}}, {{vid.width, lines, 1, 1}}, - {{ 0, lines, 0, 1}}, + {{ 0, lines, 0, 1}}, }; GLSL_FlushText (); // Flush text that should be rendered before the console From 49acf7035df238fe1f4df1d31c90ec76aebb4fc0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Sep 2022 18:29:53 +0900 Subject: [PATCH 3051/3664] [vulkaan] Fix incorrect conback drawing Putting the console background image in the scrap needed different calculations for the sliding console, but I rather messed things up. --- libs/video/renderer/vulkan/vulkan_draw.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index bfb7dea2c..65bd3955e 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -830,11 +830,12 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) quat_t color = { a, a, a, a}; qpic_t *cpic; cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx); - int ofs = max (0, cpic->height - lines); - lines = min (lines, cpic->height); + float frac = (vid.height - lines) / (float) vid.height; + int ofs = frac * cpic->height; subpic_t *subpic = *(subpic_t **) cpic->data; draw_pic (0, 0, vid.width, lines, subpic, - 0, ofs, cpic->width, lines, color, &frame->quad_verts); + 0, ofs, cpic->width, cpic->height - ofs, color, + &frame->quad_verts); } void From 60e712f2248cf0db3f7ae1a27cecd96c88812472 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Sep 2022 21:53:22 +0900 Subject: [PATCH 3052/3664] [vulkan] Use the right uvs for lines UVs being 0 meant that lines were picking up the upper left pixel of char 0 of conchars. With quake data, this meant a transparent pixel. Fixes invisible debug lines :P. --- libs/video/renderer/vulkan/vulkan_draw.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 65bd3955e..f5da3468b 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -873,12 +873,25 @@ Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) QuatScale (color, 1/255.0, color); drawvert_t *verts = queue->verts + queue->count * VERTS_PER_LINE; + subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; + int srcx = subpic->rect->x; + int srcy = subpic->rect->y; + int srcw = subpic->rect->width; + int srch = subpic->rect->height; + float size = subpic->size; + float sl = (srcx + 0.03125) * size; + float sr = (srcx + srcw - 0.03125) * size; + float st = (srcy + 0.03125) * size; + float sb = (srcy + srch - 0.03125) * size; + verts[0] = (drawvert_t) { .xy = { x0, y0 }, + .st = {sl, st}, .color = { QuatExpand (color) }, }; verts[1] = (drawvert_t) { .xy = { x1, y1 }, + .st = {sr, sb}, .color = { QuatExpand (color) }, }; From ba9a071b1c467685990f9dce86ef7160235b1822 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Sep 2022 21:57:10 +0900 Subject: [PATCH 3053/3664] [console] Fix console sliding and resize Due to the changes related to console views, the console was either fully visible or not at all visible, so it took several seconds to disappear whenever closed. Taking the screen data from the event fixes the console size being out due to screen_view updating after the app_window event fires. Really, this makes it independent of the order. --- libs/console/client.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/libs/console/client.c b/libs/console/client.c index 40ad2ebf2..9ca080e0a 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -524,12 +524,12 @@ resize_console_text (view_t *view) int width = view->xlen / 8; int height = view->ylen / 8; - ClearNotify (); - - con_linewidth = width; - Draw_DestroyBuffer (console_buffer); - console_buffer = Draw_CreateBuffer (width, height); - clear_console_text (); + if (console_buffer->width != width || console_buffer->height != height) { + con_linewidth = width; + Draw_DestroyBuffer (console_buffer); + console_buffer = Draw_CreateBuffer (width, height); + clear_console_text (); + } } static void @@ -568,7 +568,7 @@ draw_console (view_t *view) alpha = min (alpha, 255); } // draw the background - r_funcs->Draw_ConsoleBackground (view->ylen, alpha); + r_funcs->Draw_ConsoleBackground (con_data.lines, alpha); // draw everything else view_draw (view); @@ -640,6 +640,11 @@ C_DrawConsole (void) { setup_console (); + int ypos = con_data.lines - con_data.screen_view->ylen; + if (console_view->ypos != ypos) { + view_move (console_view, 0, ypos); + } + say_line.view->visible = con_state == con_message ? !chat_team : 0; team_line.view->visible = con_state == con_message ? chat_team : 0; console_view->visible = con_data.lines != 0; @@ -692,8 +697,7 @@ con_app_window (const IE_event_t *event) old_xlen = event->app_window.xlen; old_ylen = event->app_window.ylen; - view_resize (con_data.view, con_data.screen_view->xlen, - con_data.screen_view->ylen); + view_resize (con_data.view, old_xlen, old_ylen); } } @@ -780,6 +784,9 @@ static int con_event_handler (const IE_event_t *ie_event, void *data) { if (con_state == con_menu) { + if (ie_event->type == ie_app_window) { + con_app_window (ie_event); + } return Menu_EventHandler (ie_event); } static void (*handlers[ie_event_count]) (const IE_event_t *ie_event) = { From 2d634b7cf765bb719326860fb60caedd6007c610 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Sep 2022 22:24:22 +0900 Subject: [PATCH 3054/3664] [vulkan] Shift the 2d view by 0.5 pixels in X and Y Lines drawn along the top and left edges were not displayed because they were just off screen. --- libs/video/renderer/vid_render_vulkan.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 2b2f29e34..f7a6c103b 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -360,9 +360,11 @@ vulkan_set_2d (int scaled) __auto_type mctx = vulkan_ctx->matrix_context; __auto_type mat = &mctx->matrices; - int width = vid.width; //FIXME vid - int height = vid.height; - QFV_Orthographic (mat->Projection2d, 0, width, 0, height, 0, 99999); + float left = -0.5; + float top = -0.5; + float right = left + vid.width; //FIXME vid + float bottom = top + vid.height; + QFV_Orthographic (mat->Projection2d, left, right, top, bottom, 0, 99999); mctx->dirty = mctx->frames.size; } From c0e3821fa6f51a8da8fcb91b7b808257f0b309f3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 28 Sep 2022 22:50:44 +0900 Subject: [PATCH 3055/3664] [gl/glsl] Shift the 2d view by 0.5 pixels in X and Y Fixes top and left edge lines not being visible (same story as vulkan). --- libs/video/renderer/gl/gl_draw.c | 2 +- libs/video/renderer/glsl/glsl_draw.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index a6836c4aa..d22ef1fed 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -970,7 +970,7 @@ set_2d (int width, int height) qfglMatrixMode (GL_PROJECTION); qfglLoadIdentity (); - qfglOrtho (0, width, height, 0, -99999, 99999); + qfglOrtho (-0.5, width - 0.5, height - 0.5, -0.5, -99999, 99999); qfglMatrixMode (GL_MODELVIEW); qfglLoadIdentity (); diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 7fb50c965..f9bc2504b 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -799,7 +799,8 @@ set_2d (int width, int height) qfeglDisable (GL_DEPTH_TEST); qfeglDisable (GL_CULL_FACE); - ortho_mat (proj_matrix, 0, width, height, 0, -99999, 99999); + ortho_mat (proj_matrix, -0.5, width - 0.5, height - 0.5, -0.5, + -99999, 99999); qfeglUseProgram (quake_2d.program); qfeglEnableVertexAttribArray (quake_2d.vertex.location); From 31945c6e01153339540ac8d87e9f89d65f9a5c3e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Sep 2022 15:48:23 +0900 Subject: [PATCH 3056/3664] [ui] Rearrange fields in view_t slightly Moving the flags bitfields up with the gravity field makes for better packing in 64-bit builds. --- include/QF/ui/view.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index 2ae69e3d7..a2486ccdd 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -93,6 +93,9 @@ struct view_s { int xrel, yrel; //@} grav_t gravity; ///< The gravity of the view. + unsigned visible:1; ///< If false, view_draw() skips this view. + unsigned resize_x:1; ///< If true, view's width follows parent's. + unsigned resize_y:1; ///< If true, view's height follows parent's. view_t *parent; ///< The parent view. view_t **children; ///< The child views. int num_children; ///< Number of child views in view. @@ -119,9 +122,6 @@ struct view_s { touch this at all except view_new(), which just sets it to 0. */ void *data; - unsigned visible:1; ///< If false, view_draw() skips this view. - unsigned resize_x:1; ///< If true, view's width follows parent's. - unsigned resize_y:1; ///< If true, view's height follows parent's. }; /** Create a new view. view_t::draw is set to view_draw() and the view is made From 378584f41da89d1580e5ab5de962dcc532a7245e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 29 Sep 2022 23:54:12 +0900 Subject: [PATCH 3057/3664] [ui] Add functions for flow-based automatic layout This should be suitable for laying out text objects with word-wrap, where each view is a "word" or break between "words". This should be useful for any other objects that could benefit from similar layout rules. All eight flows are supported left-right-top-down (English and most European languages), right-left-top-down (Arabic and similar), top-down-right-left (Chinese, Japanese, Korean), top-down-left-right, as well as bottom-up variants of those four. More work is needed for support of things like views being centered on the flow line rather than on one edge (depends on flow direction), offset views, and others. Suppression of "spaces" at the beginning of a line is supported but not tested. --- include/QF/ui/view.h | 11 ++ libs/ui/test/Makemodule.am | 5 + libs/ui/test/test-flow.c | 284 +++++++++++++++++++++++++++++++++++++ libs/ui/view.c | 211 +++++++++++++++++++++++++++ 4 files changed, 511 insertions(+) create mode 100644 libs/ui/test/test-flow.c diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index a2486ccdd..2795a588f 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -64,6 +64,7 @@ typedef enum { grav_southwest, ///< +ve X right, +ve Y up, -X left, -ve Y down grav_west, ///< +ve X right, +ve Y down, -X left, -ve Y up grav_northwest, ///< +ve X right, +ve Y down, -X left, -ve Y up + grav_flow, ///< controlled by view_flow } grav_t; extern struct exprtype_s grav_t_type; @@ -96,6 +97,7 @@ struct view_s { unsigned visible:1; ///< If false, view_draw() skips this view. unsigned resize_x:1; ///< If true, view's width follows parent's. unsigned resize_y:1; ///< If true, view's height follows parent's. + unsigned bol_suppress:1; ///< If true, view_flow skips at start of line. view_t *parent; ///< The parent view. view_t **children; ///< The child views. int num_children; ///< Number of child views in view. @@ -254,6 +256,15 @@ void view_setgeometry (view_t *view, int xp, int yp, int xl, int yl); */ void view_setgravity (view_t *view, grav_t grav); +void view_flow_right_down (view_t *view); +void view_flow_right_up (view_t *view); +void view_flow_left_down (view_t *view); +void view_flow_left_up (view_t *view); +void view_flow_down_right (view_t *view); +void view_flow_up_right (view_t *view); +void view_flow_down_left (view_t *view); +void view_flow_up_left (view_t *view); + ///@} #endif//__QF_ui_view_h diff --git a/libs/ui/test/Makemodule.am b/libs/ui/test/Makemodule.am index 7922c9439..fb4b93c7d 100644 --- a/libs/ui/test/Makemodule.am +++ b/libs/ui/test/Makemodule.am @@ -1,4 +1,5 @@ libs_ui_tests = \ + libs/ui/test/test-flow \ libs/ui/test/test-txtbuffer \ libs/ui/test/test-vrect @@ -6,6 +7,10 @@ TESTS += $(libs_ui_tests) check_PROGRAMS += $(libs_ui_tests) +libs_ui_test_test_flow_SOURCES=libs/ui/test/test-flow.c +libs_ui_test_test_flow_LDADD=libs/ui/libQFui.la +libs_ui_test_test_flow_DEPENDENCIES=libs/ui/libQFui.la + libs_ui_test_test_txtbuffer_SOURCES=libs/ui/test/test-txtbuffer.c libs_ui_test_test_txtbuffer_LDADD=libs/ui/libQFui.la libs_ui_test_test_txtbuffer_DEPENDENCIES=libs/ui/libQFui.la diff --git a/libs/ui/test/test-flow.c b/libs/ui/test/test-flow.c new file mode 100644 index 000000000..3861e5ed0 --- /dev/null +++ b/libs/ui/test/test-flow.c @@ -0,0 +1,284 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/ui/view.h" + +typedef struct { + struct { + int xlen, ylen; + }; + int bol_suppress; + struct { + struct { + int xpos, ypos; + }; + struct { + int xrel, yrel; + }; + struct { + int xabs, yabs; + }; + } expect; +} testdata_t; + +#define array_size(array) (sizeof (array) / sizeof(array[0])) + +static testdata_t right_down_views[] = { + {{ 48, 8}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 0 + {{128, 8}, 0, { { 48, 0}, { 48, 0}, { 56, 16} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 0}, {184, 16} }}, + + {{ 32, 8}, 0, { { 0, 0}, { 0, 8}, { 8, 24} }}, // 3 + {{224, 8}, 0, { { 32, 0}, { 32, 8}, { 40, 24} }}, + + {{ 64, 8}, 0, { { 0, 0}, { 0, 16}, { 8, 32} }}, // 5 + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 32, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, + + {{288, 8}, 0, { { 0, 0}, { 0, 24}, { 8, 40} }}, // 9 + + {{ 48, 8}, 0, { { 0, 0}, { 0, 32}, { 8, 48} }}, // 10 + {{128, 8}, 0, { { 48, 0}, { 48, 32}, { 56, 48} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 32}, {184, 48} }}, +}; +#define right_down_count array_size(right_down_views) + +static testdata_t right_up_views[] = { + {{ 48, 8}, 0, { { 0, 0}, { 0,248}, { 8,264} }}, // 0 + {{128, 8}, 0, { { 48, 0}, { 48,248}, { 56,264} }}, + {{ 64, 8}, 0, { {176, 0}, {176,248}, {184,264} }}, + + {{ 32, 8}, 0, { { 0, 0}, { 0,240}, { 8,256} }}, // 3 + {{224, 8}, 0, { { 32, 0}, { 32,240}, { 40,256} }}, + + {{ 64, 8}, 0, { { 0, 0}, { 0,232}, { 8,248} }}, // 5 + {{ 64, 8}, 0, { { 64, 0}, { 64,232}, { 72,248} }}, + {{ 64, 8}, 0, { {128, 0}, {128,232}, {136,248} }}, + {{ 32, 8}, 0, { {192, 0}, {192,232}, {200,248} }}, + + {{288, 8}, 0, { { 0, 0}, { 0,224}, { 8,240} }}, // 9 + + {{ 48, 8}, 0, { { 0, 0}, { 0,216}, { 8,232} }}, // 10 + {{128, 8}, 0, { { 48, 0}, { 48,216}, { 56,232} }}, + {{ 64, 8}, 0, { {176, 0}, {176,216}, {184,232} }}, +}; +#define right_up_count array_size(right_up_views) + +static testdata_t left_down_views[] = { + {{ 48, 8}, 0, { {208, 0}, {208, 0}, {216, 16} }}, // 0 + {{128, 8}, 0, { { 80, 0}, { 80, 0}, { 88, 16} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 0}, { 24, 16} }}, + + {{ 32, 8}, 0, { {224, 0}, {224, 8}, {232, 24} }}, // 3 + {{224, 8}, 0, { { 0, 0}, { 0, 8}, { 8, 24} }}, + + {{ 64, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, // 5 + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 32, 8}, 0, { { 32, 0}, { 32, 16}, { 40, 32} }}, + + {{288, 8}, 0, { {-32, 0}, {-32, 24}, {-24, 40} }}, // 9 + + {{ 48, 8}, 0, { {208, 0}, {208, 32}, {216, 48} }}, // 10 + {{128, 8}, 0, { { 80, 0}, { 80, 32}, { 88, 48} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 32}, { 24, 48} }}, +}; +#define left_down_count array_size(left_down_views) + +static testdata_t left_up_views[] = { + {{ 48, 8}, 0, { {208, 0}, {208,248}, {216,264} }}, // 0 + {{128, 8}, 0, { { 80, 0}, { 80,248}, { 88,264} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16,248}, { 24,264} }}, + + {{ 32, 8}, 0, { {224, 0}, {224,240}, {232,256} }}, // 3 + {{224, 8}, 0, { { 0, 0}, { 0,240}, { 8,256} }}, + + {{ 64, 8}, 0, { {192, 0}, {192,232}, {200,248} }}, // 5 + {{ 64, 8}, 0, { {128, 0}, {128,232}, {136,248} }}, + {{ 64, 8}, 0, { { 64, 0}, { 64,232}, { 72,248} }}, + {{ 32, 8}, 0, { { 32, 0}, { 32,232}, { 40,248} }}, + + {{288, 8}, 0, { {-32, 0}, {-32,224}, {-24,240} }}, // 9 + + {{ 48, 8}, 0, { {208, 0}, {208,216}, {216,232} }}, // 10 + {{128, 8}, 0, { { 80, 0}, { 80,216}, { 88,232} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16,216}, { 24,232} }}, +}; +#define left_up_count array_size(left_up_views) + +static testdata_t down_right_views[] = { + {{ 8, 48}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 0 + {{ 8,128}, 0, { { 0, 48}, { 0, 48}, { 8, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 0,176}, { 8,192} }}, + + {{ 8, 32}, 0, { { 0, 0}, { 8, 0}, { 16, 16} }}, // 3 + {{ 8,224}, 0, { { 0, 32}, { 8, 32}, { 16, 48} }}, + + {{ 8, 64}, 0, { { 0, 0}, { 16, 0}, { 24, 16} }}, // 5 + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 32}, 0, { { 0,192}, { 16,192}, { 24,208} }}, + + {{ 8,288}, 0, { { 0, 0}, { 24, 0}, { 32, 16} }}, // 9 + + {{ 8, 48}, 0, { { 0, 0}, { 32, 0}, { 40, 16} }}, // 10 + {{ 8,128}, 0, { { 0, 48}, { 32, 48}, { 40, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 32,176}, { 40,192} }}, +}; +#define down_right_count array_size(down_right_views) + +static testdata_t up_right_views[] = { + {{ 8, 48}, 0, { { 0,208}, { 0,208}, { 8,224} }}, // 0 + {{ 8,128}, 0, { { 0, 80}, { 0, 80}, { 8, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 0, 16}, { 8, 32} }}, + + {{ 8, 32}, 0, { { 0,224}, { 8,224}, { 16,240} }}, // 3 + {{ 8,224}, 0, { { 0, 0}, { 8, 0}, { 16, 16} }}, + + {{ 8, 64}, 0, { { 0,192}, { 16,192}, { 24,208} }}, // 5 + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 32}, 0, { { 0, 32}, { 16, 32}, { 24, 48} }}, + + {{ 8,288}, 0, { { 0,-32}, { 24,-32}, { 32,-16} }}, // 9 + + {{ 8, 48}, 0, { { 0,208}, { 32,208}, { 40,224} }}, // 10 + {{ 8,128}, 0, { { 0, 80}, { 32, 80}, { 40, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 32, 16}, { 40, 32} }}, +}; +#define up_right_count array_size(up_right_views) + +static testdata_t down_left_views[] = { + {{ 8, 48}, 0, { { 0, 0}, {248, 0}, {256, 16} }}, // 0 + {{ 8,128}, 0, { { 0, 48}, {248, 48}, {256, 64} }}, + {{ 8, 64}, 0, { { 0,176}, {248,176}, {256,192} }}, + + {{ 8, 32}, 0, { { 0, 0}, {240, 0}, {248, 16} }}, // 3 + {{ 8,224}, 0, { { 0, 32}, {240, 32}, {248, 48} }}, + + {{ 8, 64}, 0, { { 0, 0}, {232, 0}, {240, 16} }}, // 5 + {{ 8, 64}, 0, { { 0, 64}, {232, 64}, {240, 80} }}, + {{ 8, 64}, 0, { { 0,128}, {232,128}, {240,144} }}, + {{ 8, 32}, 0, { { 0,192}, {232,192}, {240,208} }}, + + {{ 8,288}, 0, { { 0, 0}, {224, 0}, {232, 16} }}, // 9 + + {{ 8, 48}, 0, { { 0, 0}, {216, 0}, {224, 16} }}, // 10 + {{ 8,128}, 0, { { 0, 48}, {216, 48}, {224, 64} }}, + {{ 8, 64}, 0, { { 0,176}, {216,176}, {224,192} }}, +}; +#define down_left_count array_size(down_left_views) + +static testdata_t up_left_views[] = { + {{ 8, 48}, 0, { { 0,208}, {248,208}, {256,224} }}, // 0 + {{ 8,128}, 0, { { 0, 80}, {248, 80}, {256, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, {248, 16}, {256, 32} }}, + + {{ 8, 32}, 0, { { 0,224}, {240,224}, {248,240} }}, // 3 + {{ 8,224}, 0, { { 0, 0}, {240, 0}, {248, 16} }}, + + {{ 8, 64}, 0, { { 0,192}, {232,192}, {240,208} }}, // 5 + {{ 8, 64}, 0, { { 0,128}, {232,128}, {240,144} }}, + {{ 8, 64}, 0, { { 0, 64}, {232, 64}, {240, 80} }}, + {{ 8, 32}, 0, { { 0, 32}, {232, 32}, {240, 48} }}, + + {{ 8,288}, 0, { { 0,-32}, {224,-32}, {232,-16} }}, // 9 + + {{ 8, 48}, 0, { { 0,208}, {216,208}, {224,224} }}, // 10 + {{ 8,128}, 0, { { 0, 80}, {216, 80}, {224, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, {216, 16}, {224, 32} }}, +}; +#define up_left_count array_size(up_left_views) + +static void +print_view (view_t *view) +{ + printf ("%s[%3d %3d %3d %3d %3d %3d %3d %3d]\n", + view->parent ? " " : "****", + view->xpos, view->ypos, view->xlen, view->ylen, + view->xrel, view->yrel, view->xabs, view->yabs); + view_draw (view); +} + +static int +test_flow (testdata_t *child_views, int count, void (*flow) (view_t *)) +{ + view_t *flow_view = view_new (0, 0, 256, 256, grav_northwest); + flow_view->setgeometry = flow; + flow_view->draw = print_view; + + for (int i = 0; i < count; i++) { + testdata_t *td = &child_views[i]; + view_t *child = view_new (0, 0, td->xlen, td->ylen, grav_flow); + child->bol_suppress = td->bol_suppress; + child->draw = print_view; + view_add (flow_view, child); + } + + view_move (flow_view, 8, 16); + int ret = 0; + + for (int i = 0; i < flow_view->num_children; i++) { + testdata_t *td = &child_views[i]; + view_t *child = flow_view->children[i]; + if (child->xpos != td->expect.xpos + || child->ypos != td->expect.ypos + || child->xrel != td->expect.xrel + || child->yrel != td->expect.yrel + || child->xabs != td->expect.xabs + || child->yabs != td->expect.yabs) { + ret = 1; + printf ("child %d misflowed:\n" + " [%3d %3d %3d %3d %3d %3d]\n", i, + td->expect.xpos, td->expect.ypos, + td->expect.xrel, td->expect.yrel, + td->expect.xabs, td->expect.yabs); + print_view (child); + } + } + return ret; +} + +int +main (void) +{ + int ret = 0; + + if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { + printf ("right-down failed\n"); + ret = 1; + } + if (test_flow (right_up_views, right_up_count, view_flow_right_up)) { + printf ("right-up failed\n"); + ret = 1; + } + if (test_flow (left_down_views, left_down_count, view_flow_left_down)) { + printf ("left-down failed\n"); + ret = 1; + } + if (test_flow (left_up_views, left_up_count, view_flow_left_up)) { + printf ("left-up failed\n"); + ret = 1; + } + + if (test_flow (down_right_views, down_right_count, view_flow_down_right)) { + printf ("down-right failed\n"); + ret = 1; + } + if (test_flow (up_right_views, up_right_count, view_flow_up_right)) { + printf ("up-right failed\n"); + ret = 1; + } + if (test_flow (down_left_views, down_left_count, view_flow_down_left)) { + printf ("down-left failed\n"); + ret = 1; + } + if (test_flow (up_left_views, up_left_count, view_flow_up_left)) { + printf ("up-left failed\n"); + ret = 1; + } + return ret; +} diff --git a/libs/ui/view.c b/libs/ui/view.c index 0676840cd..198463fd3 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -40,6 +40,7 @@ #include #include "QF/cexpr.h" +#include "QF/mathlib.h" #include "QF/ui/view.h" static exprenum_t grav_t_enum; @@ -133,6 +134,8 @@ setgeometry (view_t *view) view->xrel = view->xpos; view->yrel = view->ypos; break; + case grav_flow: + break; } view->xabs = par->xabs + view->xrel; view->yabs = par->yabs + view->yrel; @@ -284,3 +287,211 @@ view_setgravity (view_t *view, grav_t grav) view->gravity = grav; setgeometry (view); } + +typedef struct flowline_s { + struct flowline_s *next; + int first_child; + int child_count; + int cursor; + int height; +} flowline_t; + +#define NEXT_LINE(line, child_index) \ + do { \ + line->next = alloca (sizeof (flowline_t)); \ + memset (line->next, 0, sizeof (flowline_t)); \ + line = line->next; \ + line->first_child = child_index; \ + } while (0) + +static void +flow_right (view_t *view, void (*set_rows) (view_t *, flowline_t *)) +{ + flowline_t flowline = {}; + flowline_t *line = &flowline; + for (int i = 0; i < view->num_children; i++) { + view_t *child = view->children[i]; + if (line->cursor && line->cursor + child->xlen > view->xlen) { + NEXT_LINE(line, i); + } + child->xpos = line->cursor; + if (child->xpos || !child->bol_suppress) { + line->cursor += child->xlen; + } + line->height = max (child->ylen, line->height); + line->child_count++; + } + set_rows (view, &flowline); +} + +static void +flow_left (view_t *view, void (*set_rows) (view_t *, flowline_t *)) +{ + flowline_t flowline = {}; + flowline_t *line = &flowline; + line->cursor = view->xlen; + for (int i = 0; i < view->num_children; i++) { + view_t *child = view->children[i]; + if (line->cursor < view->xlen && line->cursor - child->xlen < 0) { + NEXT_LINE(line, i); + line->cursor = view->xlen; + } + if (child->xpos < view->xlen || !child->bol_suppress) { + line->cursor -= child->xlen; + } + child->xpos = line->cursor; + line->height = max (child->ylen, line->height); + line->child_count++; + } + set_rows (view, &flowline); +} + +static void +flow_down (view_t *view, void (*set_rows) (view_t *, flowline_t *)) +{ + flowline_t flowline = {}; + flowline_t *line = &flowline; + for (int i = 0; i < view->num_children; i++) { + view_t *child = view->children[i]; + if (line->cursor && line->cursor + child->ylen > view->ylen) { + NEXT_LINE(line, i); + } + child->ypos = line->cursor; + if (child->ypos || !child->bol_suppress) { + line->cursor += child->ylen; + } + line->height = max (child->xlen, line->height); + line->child_count++; + } + set_rows (view, &flowline); +} + +static void +flow_up (view_t *view, void (*set_rows) (view_t *, flowline_t *)) +{ + flowline_t flowline = {}; + flowline_t *line = &flowline; + line->cursor = view->ylen; + for (int i = 0; i < view->num_children; i++) { + view_t *child = view->children[i]; + if (line->cursor < view->ylen && line->cursor - child->ylen < 0) { + NEXT_LINE(line, i); + line->cursor = view->ylen; + } + if (child->ypos < view->ylen || !child->bol_suppress) { + line->cursor -= child->ylen; + } + child->ypos = line->cursor; + line->height = max (child->xlen, line->height); + line->child_count++; + } + set_rows (view, &flowline); +} + +static void +set_rows_down (view_t *view, flowline_t *flowlines) +{ + int cursor = 0; + for (flowline_t *line = flowlines; line; line = line->next) { + cursor += line->height; + for (int i = 0; i < line->child_count; i++) { + view_t *child = view->children[line->first_child + i]; + + child->xrel = child->xpos; + child->yrel = cursor + child->ypos - child->ylen; + } + } +} + +static void +set_rows_up (view_t *view, flowline_t *flowlines) +{ + int cursor = view->ylen; + for (flowline_t *line = flowlines; line; line = line->next) { + for (int i = 0; i < line->child_count; i++) { + view_t *child = view->children[line->first_child + i]; + + child->xrel = child->xpos; + child->yrel = cursor + child->ypos - child->ylen; + } + cursor -= line->height; + } +} + +static void +set_columns_right (view_t *view, flowline_t *flowlines) +{ + int cursor = 0; + for (flowline_t *line = flowlines; line; line = line->next) { + for (int i = 0; i < line->child_count; i++) { + view_t *child = view->children[line->first_child + i]; + + child->xrel = cursor + child->xpos; + child->yrel = child->ypos; + } + cursor += line->height; + } +} + +static void +set_columns_left (view_t *view, flowline_t *flowlines) +{ + int cursor = view->xlen; + for (flowline_t *line = flowlines; line; line = line->next) { + cursor -= line->height; + for (int i = 0; i < line->child_count; i++) { + view_t *child = view->children[line->first_child + i]; + + child->xrel = cursor + child->xpos; + child->yrel = child->ypos; + } + } +} + +VISIBLE void +view_flow_right_down (view_t *view) +{ + flow_right (view, set_rows_down); +} + +VISIBLE void +view_flow_right_up (view_t *view) +{ + flow_right (view, set_rows_up); +} + +VISIBLE void +view_flow_left_down (view_t *view) +{ + flow_left (view, set_rows_down); +} + +VISIBLE void +view_flow_left_up (view_t *view) +{ + flow_left (view, set_rows_up); +} + +VISIBLE void +view_flow_down_right (view_t *view) +{ + flow_down (view, set_columns_right); +} + +VISIBLE void +view_flow_up_right (view_t *view) +{ + flow_up (view, set_columns_right); +} + +VISIBLE void +view_flow_down_left (view_t *view) +{ + flow_down (view, set_columns_left); +} + +VISIBLE void +view_flow_up_left (view_t *view) +{ + flow_up (view, set_columns_left); +} From ec64bd8e20966f1b3dfdd46b53ed2c204e22aa43 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 30 Sep 2022 11:28:54 +0900 Subject: [PATCH 3058/3664] [ui] Add documentation for the flow functions --- include/QF/ui/view.h | 69 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index 2795a588f..3d1865ae6 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -256,15 +256,84 @@ void view_setgeometry (view_t *view, int xp, int yp, int xl, int yl); */ void view_setgravity (view_t *view, grav_t grav); +/** Automatic layout of child views by flowing them. + + The child views are layed out linearly in the first indicated direction, + and when a child view exceeds the bounds of the view, a new flow line is + started in the second indicated direction. Flow lines always start at the + edge of the view, and the first flow line is at the appropriate edge of + the view such that at least one child view on the line touches the view's + edge and no child view exceeds that edge. + + All child views must have gravity set to grav_flow, or their behavior will + be undefined. + + A child view with bol_suppress set will not contribute to a flow-line's + length when that child view is the first view on the line, otherwise it + behaves as if bol_suppress is not set. +*/ +///@{ + +/** Flow child views from left to right, top to bottom. + + Suitable for English and most European scripts. + + \param view The parent view containing the children to be flowed. +*/ void view_flow_right_down (view_t *view); + +/** Flow child views from right to left, bottom to top. + + \param view The parent view containing the children to be flowed. +*/ void view_flow_right_up (view_t *view); + +/** Flow child views from right to left, top to bottom. + + Suitable for Arabic and similar scripts. + + \param view The parent view containing the children to be flowed. +*/ void view_flow_left_down (view_t *view); + +/** Flow child views from left to left, bottom to top. + + \param view The parent view containing the children to be flowed. +*/ void view_flow_left_up (view_t *view); + +/** Flow child views from top to bottom, left to right. + + \param view The parent view containing the children to be flowed. +*/ void view_flow_down_right (view_t *view); + +/** Flow child views from bottom to top, left to right. + + Suitable for English and most European scripts. + + \param view The parent view containing the children to be flowed. +*/ void view_flow_up_right (view_t *view); + +/** Flow child views from top to bottom, right to left. + + Suitable for Asian lanauges (Japanese, Korean, Chinese). + + \param view The parent view containing the children to be flowed. +*/ void view_flow_down_left (view_t *view); + +/** Flow child views from bottom to top, right to left. + + Suitable for English and most European scripts. + + \param view The parent view containing the children to be flowed. +*/ void view_flow_up_left (view_t *view); ///@} +///@} + #endif//__QF_ui_view_h From a24fb0ff6a99a4f8c173bde43ab14b44846ddf26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 30 Sep 2022 11:59:21 +0900 Subject: [PATCH 3059/3664] [ui] Add option to auto-fit container to flowed views Adjusting the size of the parent (container) view to the views it contains will be useful for automatic layout and knowing how large the view is for scrolling. New tests added so testing both with and without the option is still possible. --- include/QF/ui/view.h | 5 + libs/ui/test/Makemodule.am | 5 + libs/ui/test/test-flow-size.c | 285 ++++++++++++++++++++++++++++++++++ libs/ui/view.c | 30 ++++ 4 files changed, 325 insertions(+) create mode 100644 libs/ui/test/test-flow-size.c diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index 3d1865ae6..ed3d09776 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -98,6 +98,7 @@ struct view_s { unsigned resize_x:1; ///< If true, view's width follows parent's. unsigned resize_y:1; ///< If true, view's height follows parent's. unsigned bol_suppress:1; ///< If true, view_flow skips at start of line. + unsigned flow_size:1; ///< If true, view's size is adjusted to flow. view_t *parent; ///< The parent view. view_t **children; ///< The child views. int num_children; ///< Number of child views in view. @@ -271,6 +272,10 @@ void view_setgravity (view_t *view, grav_t grav); A child view with bol_suppress set will not contribute to a flow-line's length when that child view is the first view on the line, otherwise it behaves as if bol_suppress is not set. + + If the view's flow_size is set, then its secondary axis size is adjusted + so the child views fill the view along that axis. The primary axis size is + never adjusted. */ ///@{ diff --git a/libs/ui/test/Makemodule.am b/libs/ui/test/Makemodule.am index fb4b93c7d..d1475be63 100644 --- a/libs/ui/test/Makemodule.am +++ b/libs/ui/test/Makemodule.am @@ -1,5 +1,6 @@ libs_ui_tests = \ libs/ui/test/test-flow \ + libs/ui/test/test-flow-size \ libs/ui/test/test-txtbuffer \ libs/ui/test/test-vrect @@ -11,6 +12,10 @@ libs_ui_test_test_flow_SOURCES=libs/ui/test/test-flow.c libs_ui_test_test_flow_LDADD=libs/ui/libQFui.la libs_ui_test_test_flow_DEPENDENCIES=libs/ui/libQFui.la +libs_ui_test_test_flow_size_SOURCES=libs/ui/test/test-flow-size.c +libs_ui_test_test_flow_size_LDADD=libs/ui/libQFui.la +libs_ui_test_test_flow_size_DEPENDENCIES=libs/ui/libQFui.la + libs_ui_test_test_txtbuffer_SOURCES=libs/ui/test/test-txtbuffer.c libs_ui_test_test_txtbuffer_LDADD=libs/ui/libQFui.la libs_ui_test_test_txtbuffer_DEPENDENCIES=libs/ui/libQFui.la diff --git a/libs/ui/test/test-flow-size.c b/libs/ui/test/test-flow-size.c new file mode 100644 index 000000000..e37a2d44d --- /dev/null +++ b/libs/ui/test/test-flow-size.c @@ -0,0 +1,285 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/ui/view.h" + +typedef struct { + struct { + int xlen, ylen; + }; + int bol_suppress; + struct { + struct { + int xpos, ypos; + }; + struct { + int xrel, yrel; + }; + struct { + int xabs, yabs; + }; + } expect; +} testdata_t; + +#define array_size(array) (sizeof (array) / sizeof(array[0])) + +static testdata_t right_down_views[] = { + {{ 48, 8}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 0 + {{128, 8}, 0, { { 48, 0}, { 48, 0}, { 56, 16} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 0}, {184, 16} }}, + + {{ 32, 8}, 0, { { 0, 0}, { 0, 8}, { 8, 24} }}, // 3 + {{224, 8}, 0, { { 32, 0}, { 32, 8}, { 40, 24} }}, + + {{ 64, 8}, 0, { { 0, 0}, { 0, 16}, { 8, 32} }}, // 5 + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 32, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, + + {{288, 8}, 0, { { 0, 0}, { 0, 24}, { 8, 40} }}, // 9 + + {{ 48, 8}, 0, { { 0, 0}, { 0, 32}, { 8, 48} }}, // 10 + {{128, 8}, 0, { { 48, 0}, { 48, 32}, { 56, 48} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 32}, {184, 48} }}, +}; +#define right_down_count array_size(right_down_views) + +static testdata_t right_up_views[] = { + {{ 48, 8}, 0, { { 0, 0}, { 0, 32}, { 8, 48} }}, // 0 + {{128, 8}, 0, { { 48, 0}, { 48, 32}, { 56, 48} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 32}, {184, 48} }}, + + {{ 32, 8}, 0, { { 0, 0}, { 0, 24}, { 8, 40} }}, // 3 + {{224, 8}, 0, { { 32, 0}, { 32, 24}, { 40, 40} }}, + + {{ 64, 8}, 0, { { 0, 0}, { 0, 16}, { 8, 32} }}, // 5 + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 32, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, + + {{288, 8}, 0, { { 0, 0}, { 0, 8}, { 8, 24} }}, // 9 + + {{ 48, 8}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 10 + {{128, 8}, 0, { { 48, 0}, { 48, 0}, { 56, 16} }}, + {{ 64, 8}, 0, { {176, 0}, {176, 0}, {184, 16} }}, +}; +#define right_up_count array_size(right_up_views) + +static testdata_t left_down_views[] = { + {{ 48, 8}, 0, { {208, 0}, {208, 0}, {216, 16} }}, // 0 + {{128, 8}, 0, { { 80, 0}, { 80, 0}, { 88, 16} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 0}, { 24, 16} }}, + + {{ 32, 8}, 0, { {224, 0}, {224, 8}, {232, 24} }}, // 3 + {{224, 8}, 0, { { 0, 0}, { 0, 8}, { 8, 24} }}, + + {{ 64, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, // 5 + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 32, 8}, 0, { { 32, 0}, { 32, 16}, { 40, 32} }}, + + {{288, 8}, 0, { {-32, 0}, {-32, 24}, {-24, 40} }}, // 9 + + {{ 48, 8}, 0, { {208, 0}, {208, 32}, {216, 48} }}, // 10 + {{128, 8}, 0, { { 80, 0}, { 80, 32}, { 88, 48} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 32}, { 24, 48} }}, +}; +#define left_down_count array_size(left_down_views) + +static testdata_t left_up_views[] = { + {{ 48, 8}, 0, { {208, 0}, {208, 32}, {216, 48} }}, // 0 + {{128, 8}, 0, { { 80, 0}, { 80, 32}, { 88, 48} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 32}, { 24, 48} }}, + + {{ 32, 8}, 0, { {224, 0}, {224, 24}, {232, 40} }}, // 3 + {{224, 8}, 0, { { 0, 0}, { 0, 24}, { 8, 40} }}, + + {{ 64, 8}, 0, { {192, 0}, {192, 16}, {200, 32} }}, // 5 + {{ 64, 8}, 0, { {128, 0}, {128, 16}, {136, 32} }}, + {{ 64, 8}, 0, { { 64, 0}, { 64, 16}, { 72, 32} }}, + {{ 32, 8}, 0, { { 32, 0}, { 32, 16}, { 40, 32} }}, + + {{288, 8}, 0, { {-32, 0}, {-32, 8}, {-24, 24} }}, // 9 + + {{ 48, 8}, 0, { {208, 0}, {208, 0}, {216, 16} }}, // 10 + {{128, 8}, 0, { { 80, 0}, { 80, 0}, { 88, 16} }}, + {{ 64, 8}, 0, { { 16, 0}, { 16, 0}, { 24, 16} }}, +}; +#define left_up_count array_size(left_up_views) + +static testdata_t down_right_views[] = { + {{ 8, 48}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 0 + {{ 8,128}, 0, { { 0, 48}, { 0, 48}, { 8, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 0,176}, { 8,192} }}, + + {{ 8, 32}, 0, { { 0, 0}, { 8, 0}, { 16, 16} }}, // 3 + {{ 8,224}, 0, { { 0, 32}, { 8, 32}, { 16, 48} }}, + + {{ 8, 64}, 0, { { 0, 0}, { 16, 0}, { 24, 16} }}, // 5 + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 32}, 0, { { 0,192}, { 16,192}, { 24,208} }}, + + {{ 8,288}, 0, { { 0, 0}, { 24, 0}, { 32, 16} }}, // 9 + + {{ 8, 48}, 0, { { 0, 0}, { 32, 0}, { 40, 16} }}, // 10 + {{ 8,128}, 0, { { 0, 48}, { 32, 48}, { 40, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 32,176}, { 40,192} }}, +}; +#define down_right_count array_size(down_right_views) + +static testdata_t up_right_views[] = { + {{ 8, 48}, 0, { { 0,208}, { 0,208}, { 8,224} }}, // 0 + {{ 8,128}, 0, { { 0, 80}, { 0, 80}, { 8, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 0, 16}, { 8, 32} }}, + + {{ 8, 32}, 0, { { 0,224}, { 8,224}, { 16,240} }}, // 3 + {{ 8,224}, 0, { { 0, 0}, { 8, 0}, { 16, 16} }}, + + {{ 8, 64}, 0, { { 0,192}, { 16,192}, { 24,208} }}, // 5 + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 32}, 0, { { 0, 32}, { 16, 32}, { 24, 48} }}, + + {{ 8,288}, 0, { { 0,-32}, { 24,-32}, { 32,-16} }}, // 9 + + {{ 8, 48}, 0, { { 0,208}, { 32,208}, { 40,224} }}, // 10 + {{ 8,128}, 0, { { 0, 80}, { 32, 80}, { 40, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 32, 16}, { 40, 32} }}, +}; +#define up_right_count array_size(up_right_views) + +static testdata_t down_left_views[] = { + {{ 8, 48}, 0, { { 0, 0}, { 32, 0}, { 40, 16} }}, // 0 + {{ 8,128}, 0, { { 0, 48}, { 32, 48}, { 40, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 32,176}, { 40,192} }}, + + {{ 8, 32}, 0, { { 0, 0}, { 24, 0}, { 32, 16} }}, // 3 + {{ 8,224}, 0, { { 0, 32}, { 24, 32}, { 32, 48} }}, + + {{ 8, 64}, 0, { { 0, 0}, { 16, 0}, { 24, 16} }}, // 5 + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 32}, 0, { { 0,192}, { 16,192}, { 24,208} }}, + + {{ 8,288}, 0, { { 0, 0}, { 8, 0}, { 16, 16} }}, // 9 + + {{ 8, 48}, 0, { { 0, 0}, { 0, 0}, { 8, 16} }}, // 10 + {{ 8,128}, 0, { { 0, 48}, { 0, 48}, { 8, 64} }}, + {{ 8, 64}, 0, { { 0,176}, { 0,176}, { 8,192} }}, +}; +#define down_left_count array_size(down_left_views) + +static testdata_t up_left_views[] = { + {{ 8, 48}, 0, { { 0,208}, { 32,208}, { 40,224} }}, // 0 + {{ 8,128}, 0, { { 0, 80}, { 32, 80}, { 40, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 32, 16}, { 40, 32} }}, + + {{ 8, 32}, 0, { { 0,224}, { 24,224}, { 32,240} }}, // 3 + {{ 8,224}, 0, { { 0, 0}, { 24, 0}, { 32, 16} }}, + + {{ 8, 64}, 0, { { 0,192}, { 16,192}, { 24,208} }}, // 5 + {{ 8, 64}, 0, { { 0,128}, { 16,128}, { 24,144} }}, + {{ 8, 64}, 0, { { 0, 64}, { 16, 64}, { 24, 80} }}, + {{ 8, 32}, 0, { { 0, 32}, { 16, 32}, { 24, 48} }}, + + {{ 8,288}, 0, { { 0,-32}, { 8,-32}, { 16,-16} }}, // 9 + + {{ 8, 48}, 0, { { 0,208}, { 0,208}, { 8,224} }}, // 10 + {{ 8,128}, 0, { { 0, 80}, { 0, 80}, { 8, 96} }}, + {{ 8, 64}, 0, { { 0, 16}, { 0, 16}, { 8, 32} }}, +}; +#define up_left_count array_size(up_left_views) + +static void +print_view (view_t *view) +{ + printf ("%s[%3d %3d %3d %3d %3d %3d %3d %3d]\n", + view->parent ? " " : "****", + view->xpos, view->ypos, view->xlen, view->ylen, + view->xrel, view->yrel, view->xabs, view->yabs); + view_draw (view); +} + +static int +test_flow (testdata_t *child_views, int count, void (*flow) (view_t *)) +{ + view_t *flow_view = view_new (0, 0, 256, 256, grav_northwest); + flow_view->setgeometry = flow; + flow_view->flow_size = 1; + flow_view->draw = print_view; + + for (int i = 0; i < count; i++) { + testdata_t *td = &child_views[i]; + view_t *child = view_new (0, 0, td->xlen, td->ylen, grav_flow); + child->bol_suppress = td->bol_suppress; + child->draw = print_view; + view_add (flow_view, child); + } + + view_move (flow_view, 8, 16); + int ret = 0; + + for (int i = 0; i < flow_view->num_children; i++) { + testdata_t *td = &child_views[i]; + view_t *child = flow_view->children[i]; + if (child->xpos != td->expect.xpos + || child->ypos != td->expect.ypos + || child->xrel != td->expect.xrel + || child->yrel != td->expect.yrel + || child->xabs != td->expect.xabs + || child->yabs != td->expect.yabs) { + ret = 1; + printf ("child %d misflowed:\n" + " [%3d %3d %3d %3d %3d %3d]\n", i, + td->expect.xpos, td->expect.ypos, + td->expect.xrel, td->expect.yrel, + td->expect.xabs, td->expect.yabs); + print_view (child); + } + } + return ret; +} + +int +main (void) +{ + int ret = 0; + + if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { + printf ("right-down failed\n"); + ret = 1; + } + if (test_flow (right_up_views, right_up_count, view_flow_right_up)) { + printf ("right-up failed\n"); + ret = 1; + } + if (test_flow (left_down_views, left_down_count, view_flow_left_down)) { + printf ("left-down failed\n"); + ret = 1; + } + if (test_flow (left_up_views, left_up_count, view_flow_left_up)) { + printf ("left-up failed\n"); + ret = 1; + } + + if (test_flow (down_right_views, down_right_count, view_flow_down_right)) { + printf ("down-right failed\n"); + ret = 1; + } + if (test_flow (up_right_views, up_right_count, view_flow_up_right)) { + printf ("up-right failed\n"); + ret = 1; + } + if (test_flow (down_left_views, down_left_count, view_flow_down_left)) { + printf ("down-left failed\n"); + ret = 1; + } + if (test_flow (up_left_views, up_left_count, view_flow_up_left)) { + printf ("up-left failed\n"); + ret = 1; + } + return ret; +} diff --git a/libs/ui/view.c b/libs/ui/view.c index 198463fd3..411d13802 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -388,9 +388,33 @@ flow_up (view_t *view, void (*set_rows) (view_t *, flowline_t *)) set_rows (view, &flowline); } +static void +flow_view_height (view_t *view, flowline_t *flowlines) +{ + if (view->flow_size) { + view->ylen = 0; + for (flowline_t *line = flowlines; line; line = line->next) { + view->ylen += line->height; + } + } +} + +static void +flow_view_width (view_t *view, flowline_t *flowlines) +{ + if (view->flow_size) { + view->xlen = 0; + for (flowline_t *line = flowlines; line; line = line->next) { + view->xlen += line->height; + } + } +} + static void set_rows_down (view_t *view, flowline_t *flowlines) { + flow_view_height (view, flowlines); + int cursor = 0; for (flowline_t *line = flowlines; line; line = line->next) { cursor += line->height; @@ -406,6 +430,8 @@ set_rows_down (view_t *view, flowline_t *flowlines) static void set_rows_up (view_t *view, flowline_t *flowlines) { + flow_view_height (view, flowlines); + int cursor = view->ylen; for (flowline_t *line = flowlines; line; line = line->next) { for (int i = 0; i < line->child_count; i++) { @@ -421,6 +447,8 @@ set_rows_up (view_t *view, flowline_t *flowlines) static void set_columns_right (view_t *view, flowline_t *flowlines) { + flow_view_width (view, flowlines); + int cursor = 0; for (flowline_t *line = flowlines; line; line = line->next) { for (int i = 0; i < line->child_count; i++) { @@ -436,6 +464,8 @@ set_columns_right (view_t *view, flowline_t *flowlines) static void set_columns_left (view_t *view, flowline_t *flowlines) { + flow_view_width (view, flowlines); + int cursor = view->xlen; for (flowline_t *line = flowlines; line; line = line->next) { cursor -= line->height; From 9798400cfba0dfd810df927ebe7afcd8193082b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 30 Sep 2022 19:05:18 +0900 Subject: [PATCH 3060/3664] [ui] Add a sub-system for parsing text passages A passage object has a list of all the text objects in the given string, where the objects represent either white space or "words", as well as a view_t object representing the entire passage, with paragraphs split into child views of the passage view, and each paragraph has a child view for every text/space object in the paragraph. Paragraphs are split by '\n' (not included in any object). White space is grouped into clumps such that multiple adjacent spaces form a single object. The standard ASCII space (0x20) and all of the Unicode characters marked "WS; 0020" are counted as white space. Unless a white space object is the first in the paragraph, its view is marked for suppression by the view flow code. Contiguous non-white space characters are grouped into single objects, and their views are not suppressed. All text object views (both white space and "word") have their data pointer set to the psg_text_t object representing the text for that view. This should be suitable for simple text-mode unattributed display. More advanced rendering would probably want to create suitable objects and set the view data pointers to those objects. No assumption is made about text direction. Passage and paragraph views need to have their primary axis sizes set appropriately, as well as their resize flags. Their xlen and ylen are both set to 10, and xpos,ypos is 0,0. Paragraph views need their setgeometry pointer set to the appropriate view_flow_* function. However, they are set up to have their secondary axis set automatically when flowed. Text object views are set up for automatic flowing: grav_flow, 0,0 for xpos,ypos. However, xlen and ylen are also both 0, so need to be set by the renderer before attempting to flow the text. --- include/QF/ui/passage.h | 58 +++++++++++ libs/ui/Makemodule.am | 1 + libs/ui/passage.c | 189 ++++++++++++++++++++++++++++++++++++ libs/ui/test/Makemodule.am | 5 + libs/ui/test/test-passage.c | 124 +++++++++++++++++++++++ 5 files changed, 377 insertions(+) create mode 100644 include/QF/ui/passage.h create mode 100644 libs/ui/passage.c create mode 100644 libs/ui/test/test-passage.c diff --git a/include/QF/ui/passage.h b/include/QF/ui/passage.h new file mode 100644 index 000000000..76232bd51 --- /dev/null +++ b/include/QF/ui/passage.h @@ -0,0 +1,58 @@ +/* + passage.h + + Text passage formatting. + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_ui_passage_h +#define __QF_ui_passage_h + +#include + +/** \defgroup passage Text passages + \ingroup utils +*/ +///@{ + +typedef struct psg_text_s { + /// beginning of text for this segment relative to passage_t.text + uint32_t text; + /// length of text segment in bytes rather than chars as text may be utf-8 + uint32_t size; +} psg_text_t; + +typedef struct passage_s { + const char *text; ///< Not owned by passage + struct view_s *view; ///< hierarchy of views representing passage + psg_text_t *text_objects; ///< all text objects in passage + unsigned num_text_objects; ///< number of text objects in passage +} passage_t; + +passage_t *Passage_ParseText (const char *text); +void Passage_Delete (passage_t *passage); +int Passage_IsSpace (const char *text) __attribute__((pure)); + +///@} + +#endif//__QF_ui_passage_h diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am index b564ebc8a..e0b54c30b 100644 --- a/libs/ui/Makemodule.am +++ b/libs/ui/Makemodule.am @@ -9,6 +9,7 @@ libs_ui_libQFui_la_LIBADD= $(ui_deps) libs_ui_libQFui_la_DEPENDENCIES= $(ui_deps) libs_ui_libQFui_la_SOURCES= \ libs/ui/inputline.c \ + libs/ui/passage.c \ libs/ui/txtbuffer.c \ libs/ui/view.c \ libs/ui/vrect.c diff --git a/libs/ui/passage.c b/libs/ui/passage.c new file mode 100644 index 000000000..ea289ad47 --- /dev/null +++ b/libs/ui/passage.c @@ -0,0 +1,189 @@ +/* + passage.c + + Text passage formatting. + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/alloc.h" +#include "QF/qtypes.h" +#include "QF/sys.h" + +#include "QF/ui/view.h" +#include "QF/ui/passage.h" + +VISIBLE int +Passage_IsSpace (const char *text) +{ + if (text[0] == ' ') { + return 1; + } + // 2002;EN SPACE;Zs;0;WS; 0020;;;;N;;;;; + // 2003;EM SPACE;Zs;0;WS; 0020;;;;N;;;;; + // 2004;THREE-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; + // 2005;FOUR-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; + // 2006;SIX-PER-EM SPACE;Zs;0;WS; 0020;;;;N;;;;; + // 2008;PUNCTUATION SPACE;Zs;0;WS; 0020;;;;N;;;;; + // 2009;THIN SPACE;Zs;0;WS; 0020;;;;N;;;;; + // 200A;HAIR SPACE;Zs;0;WS; 0020;;;;N;;;;; + if ((byte)text[0] == 0xe2 && (byte)text[1] == 0x80 + && ((byte)text[2] >= 0x80 && (byte)text[2] < 0x90 + && ((1 << (text[2] & 0xf)) & 0x077c))) { + return 3; + } + // 205F;MEDIUM MATHEMATICAL SPACE;Zs;0;WS; 0020;;;;N;;;;; + if ((byte)text[0] == 0xe2 && (byte)text[1] == 0x81 + && (byte)text[2] == 0x9f) { + return 3; + } + return 0; +} + +static void +add_text_view (view_t *paragraph_view, psg_text_t *text_object, int suppress) +{ + view_t *text_view = view_new (0, 0, 0, 0, grav_flow); + text_view->data = text_object; + text_view->bol_suppress = suppress; + view_add (paragraph_view, text_view); +} + +VISIBLE passage_t * +Passage_ParseText (const char *text) +{ + passage_t *passage = malloc (sizeof (passage_t)); + passage->text = text; + passage->num_text_objects = 0; + passage->view = view_new (0, 0, 10, 10, grav_northwest); + passage->text_objects = 0; + + if (!*text) { + return passage; + } + + unsigned num_paragraphs = 1; + int parsing_space = Passage_IsSpace (text); + passage->num_text_objects = 1; + for (const char *c = text; *c; c++) { + int size; + if ((size = Passage_IsSpace (c))) { + if (!parsing_space) { + passage->num_text_objects++; + } + parsing_space = 1; + c += size - 1; + } else if (*c == '\n') { + if (c[1]) { + num_paragraphs++; + passage->num_text_objects += !Passage_IsSpace (c + 1); + } + } else { + if (parsing_space) { + passage->num_text_objects++; + } + parsing_space = 0; + } + } +#if 0 + printf ("num_paragraphs %d, num_text_objects %d\n", num_paragraphs, + passage->num_text_objects); +#endif + passage->text_objects = malloc (passage->num_text_objects + * sizeof (psg_text_t)); + for (unsigned i = 0; i < num_paragraphs; i++) { + view_t *view = view_new (0, 0, 10, 10, grav_northwest); + view->flow_size = 1; + view_add (passage->view, view); + } + + num_paragraphs = 0; + parsing_space = Passage_IsSpace (text); + psg_text_t *text_object = passage->text_objects; + text_object->text = 0; + text_object->size = 0; + view_t *paragraph_view = passage->view->children[num_paragraphs++]; + add_text_view (paragraph_view, text_object, parsing_space); + for (const char *c = text; *c; c++) { + int size; + if ((size = Passage_IsSpace (c))) { + if (!parsing_space) { + text_object->size = c - text - text_object->text; + (++text_object)->text = c - text; + add_text_view (paragraph_view, text_object, 1); + } + parsing_space = 1; + c += size - 1; + } else if (*c == '\n') { + text_object->size = c - text - text_object->text; + if (c[1]) { + (++text_object)->text = c + 1 - text; + paragraph_view = passage->view->children[num_paragraphs++]; + add_text_view (paragraph_view, text_object, 0); + parsing_space = Passage_IsSpace (c + 1); + } + } else { + if (parsing_space) { + text_object->size = c - text - text_object->text; + (++text_object)->text = c - text; + add_text_view (paragraph_view, text_object, 0); + } + parsing_space = 0; + if (!c[1]) { + text_object->size = c + 1 - text - text_object->text; + } + } + } +#if 0 + for (int i = 0; i < passage->view->num_children; i++) { + paragraph_view = passage->view->children[i]; + for (int j = 0; j < paragraph_view->num_children; j++) { + view_t *text_view = paragraph_view->children[j]; + psg_text_t *to = text_view->data; + printf ("%3d %3d %d %4d %4d '%.*s'\n", i, j, + text_view->bol_suppress, + to->text, to->size, to->size, text + to->text); + } + } +#endif + return passage; +} + +VISIBLE void +Passage_Delete (passage_t *passage) +{ + if (passage->view) { + view_delete (passage->view); + } + free (passage->text_objects); + free (passage); +} diff --git a/libs/ui/test/Makemodule.am b/libs/ui/test/Makemodule.am index d1475be63..5ac206552 100644 --- a/libs/ui/test/Makemodule.am +++ b/libs/ui/test/Makemodule.am @@ -1,6 +1,7 @@ libs_ui_tests = \ libs/ui/test/test-flow \ libs/ui/test/test-flow-size \ + libs/ui/test/test-passage \ libs/ui/test/test-txtbuffer \ libs/ui/test/test-vrect @@ -16,6 +17,10 @@ libs_ui_test_test_flow_size_SOURCES=libs/ui/test/test-flow-size.c libs_ui_test_test_flow_size_LDADD=libs/ui/libQFui.la libs_ui_test_test_flow_size_DEPENDENCIES=libs/ui/libQFui.la +libs_ui_test_test_passage_SOURCES=libs/ui/test/test-passage.c +libs_ui_test_test_passage_LDADD=libs/ui/libQFui.la +libs_ui_test_test_passage_DEPENDENCIES=libs/ui/libQFui.la + libs_ui_test_test_txtbuffer_SOURCES=libs/ui/test/test-txtbuffer.c libs_ui_test_test_txtbuffer_LDADD=libs/ui/libQFui.la libs_ui_test_test_txtbuffer_DEPENDENCIES=libs/ui/libQFui.la diff --git a/libs/ui/test/test-passage.c b/libs/ui/test/test-passage.c new file mode 100644 index 000000000..4b3fddd98 --- /dev/null +++ b/libs/ui/test/test-passage.c @@ -0,0 +1,124 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/ui/view.h" +#include "QF/ui/passage.h" + +static const char test_text[] = { + "Guarding the entrance to the Grendal " + "Gorge is the Shadow Gate, a small keep " + "and monastary which was once the home " + "of the Shadow cult.\n" + " For years the Shadow Gate existed in " + "obscurity but after the cult discovered " + "the \u00c2\u00ec\u00e1\u00e3\u00eb\u2002\u00c7\u00e1\u00f4\u00e5 " + "in the caves below the empire took notice. " + "A batallion of Imperial Knights were " + "sent to the gate to destroy the cult " + "and claim the artifact for the King.\nasdf", +}; + +static int __attribute__((pure)) +check_non_space (const char *text, psg_text_t *to) +{ + int size; + + for (uint32_t offs = 0; offs < to->size; offs += size) { + if (!(size = Passage_IsSpace (text + to->text + offs))) { + return 1; + } + } + return 0; +} + +static int __attribute__((pure)) +check_space_or_nl (const char *text, psg_text_t *to) +{ + for (uint32_t offs = 0; offs < to->size; offs++) { + if (text[to->text + offs] == '\n' + || Passage_IsSpace (text + to->text + offs)) { + return 1; + } + } + return 0; +} + +int +main (void) +{ + int ret = 0; + + passage_t *passage = Passage_ParseText (test_text); + if (passage->view->num_children != 3) { + ret = 1; + printf ("incorrect number of paragraphs: %d\n", + passage->view->num_children); + } + if (passage->num_text_objects != 140) { + ret = 1; + printf ("incorrect number of text objects: %d\n", + passage->num_text_objects); + } + if (passage->view->children[0]->num_children != 49) { + ret = 1; + printf ("incorrect number of text objects in first paragraph: %d\n", + passage->view->children[0]->num_children); + } + if (passage->view->children[1]->num_children != 90) { + ret = 1; + printf ("incorrect number of text objects in second paragraph: %d\n", + passage->view->children[1]->num_children); + } + if (passage->view->children[2]->num_children != 1) { + ret = 1; + printf ("incorrect number of text objects in third paragraph: %d\n", + passage->view->children[1]->num_children); + } + view_t *text_view = passage->view->children[1]->children[0]; + psg_text_t *to = text_view->data; + if (to->size != 2 && (passage->text[to->text] != ' ' + && passage->text[to->text + 1] != ' ')) { + ret = 1; + printf ("second paragram does not begin with double space: %d '%.*s'\n", + to->size, to->size, passage->text + to->text); + } + if (text_view->bol_suppress) { + ret = 1; + printf ("second paragram indent suppressed\n"); + } + for (int i = 0; i < passage->view->num_children; i++) { + view_t *paragraph_view = passage->view->children[i]; + for (int j = 0; j < paragraph_view->num_children; j++) { + view_t *text_view = paragraph_view->children[j]; + psg_text_t *to = text_view->data; + unsigned is_space = Passage_IsSpace (passage->text + to->text); + if (i == 1 && j == 0) { + // second paragraph indent, tested above + continue; + } + if ((!!is_space) != text_view->bol_suppress) { + ret = 1; + printf ("text/suppress mismatch %d [%d '%.*s'] %d %d\n", + text_view->bol_suppress, to->size, to->size, + passage->text + to->text, i, j); + } + if (is_space) { + if (!check_non_space (passage->text, to)) { + continue; + } + } else { + if (!check_space_or_nl (passage->text, to)) { + continue; + } + } + ret = 1; + printf ("mixed space/text/\\n [%d '%.*s'] %d %d\n", + to->size, to->size, passage->text + to->text, i, j); + } + } + Passage_Delete (passage); + + return ret; +} From ac8d71733e50c29334718260655aba25bd709cb2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Oct 2022 15:07:04 +0900 Subject: [PATCH 3061/3664] [vulkan] Clean up QFV_duSetObjectName usage a little Moving the param calculations into QFV_duSetObjectName params prevents warnings when debug is disabled without having to use (void) hacks. --- libs/video/renderer/vulkan/resource.c | 28 +++++++++------------ libs/video/renderer/vulkan/vulkan_texture.c | 3 +-- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index b89b298b9..54e1fafc6 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -55,13 +55,12 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) buffer->buffer = QFV_CreateBuffer (device, buffer->size, buffer->usage); - const char *name = va (resource->va_ctx, "buffer:%s:%s", - resource->name, obj->name); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, - buffer->buffer, name); + buffer->buffer, + va (resource->va_ctx, "buffer:%s:%s", + resource->name, obj->name)); dfunc->vkGetBufferMemoryRequirements (device->dev, buffer->buffer, &req); - (void) name; // for when QFV_duSetObjectName is empty } break; case qfv_res_buffer_view: @@ -87,13 +86,12 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) image->num_layers, image->samples, image->usage); - const char *name = va (resource->va_ctx, "image:%s:%s", - resource->name, obj->name); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, - image->image, name); + image->image, + va (resource->va_ctx, "image:%s:%s", + resource->name, obj->name)); dfunc->vkGetImageMemoryRequirements (device->dev, image->image, &req); - (void) name; // for when QFV_duSetObjectName is empty } break; case qfv_res_image_view: @@ -197,11 +195,10 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) buffview->format, buffview->offset, buffview->size); - const char *name = va (resource->va_ctx, "bview:%s:%s", - resource->name, obj->name); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER_VIEW, - buffview->view, name); - (void) name; // for when QFV_duSetObjectName is empty + buffview->view, + va (resource->va_ctx, "bview:%s:%s", + resource->name, obj->name)); } break; case qfv_res_image_view: @@ -214,11 +211,10 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) imgview->type, imgview->format, imgview->aspect); - const char *name = va (resource->va_ctx, "iview:%s:%s", - resource->name, obj->name); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, - imgview->view, name); - (void) name; // for when QFV_duSetObjectName is empty + imgview->view, + va (resource->va_ctx, "iview:%s:%s", + resource->name, obj->name)); } break; } diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 8c38805ec..378ab5013 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -481,8 +481,7 @@ Vulkan_Texture_Init (vulkan_ctx_t *ctx) VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT); - qfv_device_t *device = ctx->device; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, tex->view, + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE_VIEW, tex->view, "iview:default_magenta_array"); qfvPopDebug (ctx); } From 0352af45420fc6b00fc1a6c6663af51746a28c44 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 2 Oct 2022 15:24:38 +0900 Subject: [PATCH 3062/3664] [vulkan] Initialize resource image from tex_t This moves the qfv_resobj_t image initialization code from the IQM loader into the resource management code. This will allow me to reuse the code for setting up glyph data. As a bonus, it cleans up the IQM code nicely. --- include/QF/Vulkan/resource.h | 3 ++ libs/models/iqm/vulkan_model_iqm.c | 46 +++++---------------------- libs/video/renderer/vulkan/resource.c | 25 +++++++++++++++ 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/include/QF/Vulkan/resource.h b/include/QF/Vulkan/resource.h index 7d1e0dac6..595613fa4 100644 --- a/include/QF/Vulkan/resource.h +++ b/include/QF/Vulkan/resource.h @@ -64,5 +64,8 @@ struct qfv_device_s; int QFV_CreateResource (struct qfv_device_s *device, qfv_resource_t *resource); void QFV_DestroyResource (struct qfv_device_s *device, qfv_resource_t *resource); +struct tex_s; +void QFV_ResourceInitTexImage (qfv_resobj_t *image, const char *name, + int mips, const struct tex_s *tex); #endif//__QF_Vulkan_resource_h diff --git a/libs/models/iqm/vulkan_model_iqm.c b/libs/models/iqm/vulkan_model_iqm.c index da21f1c48..42f8f867b 100644 --- a/libs/models/iqm/vulkan_model_iqm.c +++ b/libs/models/iqm/vulkan_model_iqm.c @@ -100,47 +100,17 @@ vulkan_iqm_init_image (iqm_t *iqm, int meshnum, qfv_resobj_t *image) dstring_copystr (str, material); QFS_StripExtension (str->str, str->str); + tex_t dummy_tex; tex_t *tex; - if ((tex = LoadImage (va (0, "textures/%s", str->str), 0))) { - *image = (qfv_resobj_t) { - .name = material, - .type = qfv_res_image, - .image = { - .type = VK_IMAGE_TYPE_2D, - .format = QFV_ImageFormat (tex->format, 0), - .extent = { - .width = tex->width, - .height = tex->height, - .depth = 1, - }, - .num_mipmaps = QFV_MipLevels (tex->width, tex->height), - .num_layers = 1, - .samples = VK_SAMPLE_COUNT_1_BIT, - .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT - | VK_IMAGE_USAGE_TRANSFER_SRC_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT, - }, - }; - } else { - *image = (qfv_resobj_t) { - .name = material, - .type = qfv_res_image, - .image = { - .type = VK_IMAGE_TYPE_2D, - .format = QFV_ImageFormat (tex_rgba, 0), - .extent = { - .width = 2, - .height = 2, - .depth = 1, - }, - .num_mipmaps = QFV_MipLevels (2, 2), - .num_layers = 1, - .samples = VK_SAMPLE_COUNT_1_BIT, - .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT, - }, + if (!(tex = LoadImage (va (0, "textures/%s", str->str), 0))) { + dummy_tex = (tex_t) { + .width = 2, + .height = 2, + .format = tex_rgba, }; + tex = &dummy_tex; } + QFV_ResourceInitTexImage (image, material, 1, tex); dstring_delete (str); } diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index 54e1fafc6..d217cbe58 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -269,3 +269,28 @@ QFV_DestroyResource (qfv_device_t *device, qfv_resource_t *resource) } dfunc->vkFreeMemory (device->dev, resource->memory, 0); } + +void +QFV_ResourceInitTexImage (qfv_resobj_t *image, const char *name, + int mips, const tex_t *tex) +{ + *image = (qfv_resobj_t) { + .name = name, + .type = qfv_res_image, + .image = { + .type = VK_IMAGE_TYPE_2D, + .format = QFV_ImageFormat (tex->format, 0), + .extent = { + .width = tex->width, + .height = tex->height, + .depth = 1, + }, + .num_mipmaps = mips ? QFV_MipLevels (tex->width, tex->height) : 1, + .num_layers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT + | VK_IMAGE_USAGE_TRANSFER_SRC_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT, + }, + }; +} From 51b73eee73c1e563cf7cd99314f74ebeb8759f33 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Oct 2022 08:58:27 +0900 Subject: [PATCH 3063/3664] [renderer] Add fontid to Draw_AddFont and Draw_FontString It's not used yet, but the vulkan draw implementation will eventually support multiple fonts being loaded (and rendered at a time). --- include/QF/GL/qf_draw.h | 4 ++-- include/QF/GLSL/qf_draw.h | 4 ++-- include/QF/Vulkan/qf_draw.h | 4 ++-- include/QF/draw.h | 4 ++-- include/QF/plugin/vid_render.h | 4 ++-- libs/video/renderer/gl/gl_draw.c | 5 +++-- libs/video/renderer/glsl/glsl_draw.c | 5 +++-- libs/video/renderer/r_progs.c | 9 +++++---- libs/video/renderer/sw/draw.c | 5 +++-- libs/video/renderer/vid_render_vulkan.c | 8 ++++---- libs/video/renderer/vulkan/vulkan_draw.c | 7 +++++-- 11 files changed, 33 insertions(+), 26 deletions(-) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index 7a7283c5c..ff7b9a30a 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -57,8 +57,8 @@ void gl_Draw_Pic (int x, int y, struct qpic_s *pic); void gl_Draw_Picf (float x, float y, struct qpic_s *pic); void gl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); -void gl_Draw_AddFont (struct rfont_s *font); -void gl_Draw_FontString (int x, int y, const char *str); +int gl_Draw_AddFont (struct rfont_s *font); +void gl_Draw_FontString (int x, int y, int fontid, const char *str); void GL_Set2D (void); void GL_Set2DScaled (void); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index 59ecb1668..6481cf7aa 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -57,8 +57,8 @@ void glsl_Draw_Pic (int x, int y, struct qpic_s *pic); void glsl_Draw_Picf (float x, float y, struct qpic_s *pic); void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); -void glsl_Draw_AddFont (struct rfont_s *font); -void glsl_Draw_FontString (int x, int y, const char *str); +int glsl_Draw_AddFont (struct rfont_s *font); +void glsl_Draw_FontString (int x, int y, int fontid, const char *str); void GLSL_Set2D (void); void GLSL_Set2DScaled (void); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 1da531fb1..fa4f83772 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -75,8 +75,8 @@ void Vulkan_Draw_Picf (float x, float y, struct qpic_s *pic, void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height, struct vulkan_ctx_s *ctx); -void Vulkan_Draw_AddFont (struct rfont_s *font, struct vulkan_ctx_s *ctx); -void Vulkan_Draw_FontString (int x, int y, const char *str, +int Vulkan_Draw_AddFont (struct rfont_s *font, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, struct vulkan_ctx_s *ctx); void Vulkan_Set2D (struct vulkan_ctx_s *ctx); diff --git a/include/QF/draw.h b/include/QF/draw.h index aabbf7e16..3c439f190 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -265,8 +265,8 @@ void Draw_Picf (float x, float y, qpic_t *pic); void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); struct rfont_s; -void Draw_AddFont (struct rfont_s *font); -void Draw_FontString (int x, int y, const char *str); +int Draw_AddFont (struct rfont_s *font); +void Draw_FontString (int x, int y, int fontid, const char *str); ///@} diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index eaf74c599..b3e591ad4 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -107,8 +107,8 @@ typedef struct vid_render_funcs_s { void (*Draw_Pic) (int x, int y, qpic_t *pic); void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); - void (*Draw_AddFont) (struct rfont_s *font); - void (*Draw_FontString) (int x, int y, const char *str); + int (*Draw_AddFont) (struct rfont_s *font); + void (*Draw_FontString) (int x, int y, int fontid, const char *str); struct psystem_s *(*ParticleSystem) (void); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index d22ef1fed..d27d3deaa 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -1037,12 +1037,13 @@ gl_Draw_BlendScreen (quat_t color) qfglEnable (GL_TEXTURE_2D); } -void +int gl_Draw_AddFont (struct rfont_s *font) { + return 0; } void -gl_Draw_FontString (int x, int y, const char *str) +gl_Draw_FontString (int x, int y, int fontid, const char *str) { } diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index f9bc2504b..835b93948 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -860,12 +860,13 @@ glsl_Draw_BlendScreen (quat_t color) draw_blendscreen (color); } -void +int glsl_Draw_AddFont (struct rfont_s *font) { + return 0; } void -glsl_Draw_FontString (int x, int y, const char *str) +glsl_Draw_FontString (int x, int y, int fontid, const char *str) { } diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index b7a1004f3..9c00c35f9 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -390,7 +390,7 @@ bi_Font_Load (progs_t *pr, void *_res) QFile *font_file = QFS_FOpenFile (font_path); rfont_t *font = R_FontLoad (font_file, font_size); - r_funcs->Draw_AddFont (font); + R_INT (pr) = r_funcs->Draw_AddFont (font); } static void @@ -398,8 +398,9 @@ bi_Font_String (progs_t *pr, void *_res) { int x = P_INT (pr, 0); int y = P_INT (pr, 1); - const char *str = P_GSTRING (pr, 2); - r_funcs->Draw_FontString (x, y, str); + int fontid = P_INT (pr, 2); + const char *str = P_GSTRING (pr, 3); + r_funcs->Draw_FontString (x, y, fontid, str); } static void @@ -531,7 +532,7 @@ static builtin_t builtins[] = { bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)), bi(Font_Load, 2, p(string), p(int)), - bi(Font_String, 3, p(int), p(int), p(string)), + bi(Font_String, 4, p(int), p(int), p(int), p(string)), bi(Draw_CreateBuffer, 2, p(int), p(int)), bi(Draw_DestroyBuffer, 1, p(ptr)), diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 1edbd5a51..303678cff 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -987,12 +987,13 @@ Draw_BlendScreen (quat_t color) vid.vid_internal->set_palette (vid.vid_internal->data, pal); } -void +int Draw_AddFont (struct rfont_s *font) { + return 0; } void -Draw_FontString (int x, int y, const char *str) +Draw_FontString (int x, int y, int fontid, const char *str) { } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index f7a6c103b..6457ba8bc 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -270,16 +270,16 @@ vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, in Vulkan_Draw_SubPic (x, y, pic, srcx, srcy, width, height, vulkan_ctx); } -static void +static int vulkan_Draw_AddFont (struct rfont_s *font) { - Vulkan_Draw_AddFont (font, vulkan_ctx); + return Vulkan_Draw_AddFont (font, vulkan_ctx); } static void -vulkan_Draw_FontString (int x, int y, const char *str) +vulkan_Draw_FontString (int x, int y, int fontid, const char *str) { - Vulkan_Draw_FontString (x, y, str, vulkan_ctx); + Vulkan_Draw_FontString (x, y, fontid, str, vulkan_ctx); } static void diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index f5da3468b..2fed1cb1f 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1074,7 +1074,7 @@ Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) } } -void +int Vulkan_Draw_AddFont (rfont_t *font, vulkan_ctx_t *ctx) { drawctx_t *dctx = ctx->draw_context; @@ -1094,6 +1094,8 @@ Vulkan_Draw_AddFont (rfont_t *font, vulkan_ctx_t *ctx) }; dctx->font_tex = Vulkan_LoadTex (ctx, &tex, 0, "draw.font"); } + + return 0; } typedef struct { @@ -1115,7 +1117,8 @@ vulkan_render_glyph (rglyph_t *glyph, int x, int y, void *_rgctx) } void -Vulkan_Draw_FontString (int x, int y, const char *str, vulkan_ctx_t *ctx) +Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, + vulkan_ctx_t *ctx) { drawctx_t *dctx = ctx->draw_context; if (!dctx->font) { From c028e159430baf123729fd8d1307a6f035b2f26b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Oct 2022 09:09:34 +0900 Subject: [PATCH 3064/3664] [vulkan] Add a couple of staging helper functions I got tired of writing the same 13 or so lines of code over and over (it actually put me off experimenting with Vulkan). Thus... QFV_PacketCopyBuffer does the work of handling barriers and a (full packet) copy from the staging buffer to a GPU buffer. QFV_PacketCopyImage does a similar job, but for images. However, it still needs a lot of work, but it does make getting a basic texture onto the GPU much less of a hassle. Both functions should make staging data much less error-prone. --- include/QF/Vulkan/barrier.h | 4 +-- include/QF/Vulkan/staging.h | 7 ++++ libs/video/renderer/vulkan/staging.c | 52 ++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h index 52be26b08..b4f555ea0 100644 --- a/include/QF/Vulkan/barrier.h +++ b/include/QF/Vulkan/barrier.h @@ -6,13 +6,13 @@ #endif #include -typedef struct { +typedef struct qfv_imagebarrier_s { VkPipelineStageFlags srcStages; VkPipelineStageFlags dstStages; VkImageMemoryBarrier barrier; } qfv_imagebarrier_t; -typedef struct { +typedef struct qfv_bufferbarrier_s { VkPipelineStageFlags srcStages; VkPipelineStageFlags dstStages; VkBufferMemoryBarrier barrier; diff --git a/include/QF/Vulkan/staging.h b/include/QF/Vulkan/staging.h index 5f00b9022..60ba40d13 100644 --- a/include/QF/Vulkan/staging.h +++ b/include/QF/Vulkan/staging.h @@ -34,5 +34,12 @@ void QFV_FlushStagingBuffer (qfv_stagebuf_t *stage, size_t offset, size_t size); qfv_packet_t *QFV_PacketAcquire (qfv_stagebuf_t *stage); void *QFV_PacketExtend (qfv_packet_t *packet, size_t size); void QFV_PacketSubmit (qfv_packet_t *packet); +struct qfv_bufferbarrier_s; +void QFV_PacketCopyBuffer (qfv_packet_t *packet, VkBuffer dstBuffer, + const struct qfv_bufferbarrier_s *dstBarrier); +struct qfv_imagebarrier_s; +void QFV_PacketCopyImage (qfv_packet_t *packet, VkImage dstImage, + int width, int height, + const struct qfv_imagebarrier_s *dstBarrier); #endif//__QF_Vulkan_staging_h diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index cf3073959..a0c48f7f5 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -30,6 +30,7 @@ #include "QF/dstring.h" +#include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" @@ -279,3 +280,54 @@ QFV_PacketSubmit (qfv_packet_t *packet) // The fence was reset when the packet was acquired dfunc->vkQueueSubmit (device->queue.queue, 1, &submitInfo, packet->fence); } + +void +QFV_PacketCopyBuffer (qfv_packet_t *packet, VkBuffer dstBuffer, + const qfv_bufferbarrier_t *dstBarrier) +{ + qfv_devfuncs_t *dfunc = packet->stage->device->funcs; + qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; + bb.barrier.buffer = dstBuffer; + bb.barrier.size = packet->length; + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); + VkBufferCopy copy_region = { packet->offset, 0, packet->length }; + dfunc->vkCmdCopyBuffer (packet->cmd, packet->stage->buffer, dstBuffer, + 1, ©_region); + bb = *dstBarrier; + bb.barrier.buffer = dstBuffer; + bb.barrier.size = packet->length; + dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, + 0, 0, 0, 1, &bb.barrier, 0, 0); +} + +void +QFV_PacketCopyImage (qfv_packet_t *packet, VkImage dstImage, + int width, int height, + const qfv_imagebarrier_t *dstBarrier) +{ + qfv_devfuncs_t *dfunc = packet->stage->device->funcs; + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = dstImage; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, 1, &ib.barrier); + VkBufferImageCopy copy_region = { + .bufferOffset = packet->offset, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}, + {0, 0, 0}, {width, height, 1}, + }; + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + dstImage, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©_region); + ib = *dstBarrier; + ib.barrier.image = dstImage; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, 1, &ib.barrier); +} From c9e781086477ec7ec5e105a6138e7768f4986240 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Oct 2022 09:14:29 +0900 Subject: [PATCH 3065/3664] [vulkan] Add resource memory offset to qfv_resobj_s Its value on input is ignored. QFV_CreateResource writes the resource object's offset relative to the beginning of the shared memory block. Needed for the Draw overhaul. --- include/QF/Vulkan/resource.h | 2 ++ libs/video/renderer/vulkan/resource.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/QF/Vulkan/resource.h b/include/QF/Vulkan/resource.h index 595613fa4..4cc7c78c5 100644 --- a/include/QF/Vulkan/resource.h +++ b/include/QF/Vulkan/resource.h @@ -21,6 +21,7 @@ typedef struct qfv_resobj_s { VkDeviceSize size; VkBufferUsageFlags usage; VkBuffer buffer; + VkDeviceSize offset; } buffer; struct { unsigned buffer; @@ -39,6 +40,7 @@ typedef struct qfv_resobj_s { VkSampleCountFlags samples; VkImageUsageFlags usage; VkImage image; + VkDeviceSize offset; } image; struct { unsigned image; diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index d217cbe58..45906199d 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -163,6 +163,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) __auto_type buffer = &obj->buffer; QFV_BindBufferMemory (device, buffer->buffer, resource->memory, offset); + buffer->offset = offset; } break; case qfv_res_image: @@ -170,6 +171,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) __auto_type image = &obj->image; QFV_BindImageMemory (device, image->image, resource->memory, offset); + image->offset = offset; } break; case qfv_res_buffer_view: From f477f2b96e0333467699fee0cedd2a03d5bd18b1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 3 Oct 2022 10:29:49 +0900 Subject: [PATCH 3066/3664] [vullkan] Rework Draw implementation Line rendering now has its own pipeline (removing the texture issue). Glyph rendering (for fonts) has been reworked to use instanced quad rendering, with the geometry (position and texture coords) in a static buffer (uniform texture buffer), and each instance has a glyph index, color, and 2d base position. Multiple fonts can be loaded, but aren't used yet: still just the one (work needs to be done on the queues to support multiple textures/fonts). Quads haven't changed much, but buffer creation and destruction has been cleaned up to use the resource functions. --- libs/video/renderer/Makemodule.am | 27 +- libs/video/renderer/vulkan/qfpipeline.plist | 96 +++- libs/video/renderer/vulkan/shader.c | 18 +- libs/video/renderer/vulkan/shader/glyph.vert | 32 ++ .../{twod_impalpha.frag => glyph_color.frag} | 6 +- .../vulkan/shader/glyph_coverage.frag | 17 + libs/video/renderer/vulkan/shader/line.frag | 11 + libs/video/renderer/vulkan/shader/line.vert | 20 + libs/video/renderer/vulkan/vulkan_draw.c | 508 ++++++++++++------ 9 files changed, 535 insertions(+), 200 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/glyph.vert rename libs/video/renderer/vulkan/shader/{twod_impalpha.frag => glyph_color.frag} (56%) create mode 100644 libs/video/renderer/vulkan/shader/glyph_coverage.frag create mode 100644 libs/video/renderer/vulkan/shader/line.frag create mode 100644 libs/video/renderer/vulkan/shader/line.vert diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 49999b2ad..dc360ec12 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -275,6 +275,16 @@ vkparse_plist = \ vkshaderpath = libs/video/renderer/vulkan/shader +glyph_src = $(vkshaderpath)/glyph.vert +glyph_c = $(vkshaderpath)/glyph.vert.spvc +glyph_color_src = $(vkshaderpath)/glyph_color.frag +glyph_color_c = $(vkshaderpath)/glyph_color.frag.spvc +glyph_coverage_src = $(vkshaderpath)/glyph_coverage.frag +glyph_coverage_c = $(vkshaderpath)/glyph_coverage.frag.spvc +linev_src = $(vkshaderpath)/line.vert +linev_c = $(vkshaderpath)/line.vert.spvc +linef_src = $(vkshaderpath)/line.frag +linef_c = $(vkshaderpath)/line.frag.spvc partphysicsc_src = $(vkshaderpath)/partphysics.comp partphysicsc_c = $(vkshaderpath)/partphysics.comp.spvc partupdatec_src = $(vkshaderpath)/partupdate.comp @@ -293,8 +303,6 @@ sprite_depthv_src = $(vkshaderpath)/sprite_depth.vert sprite_depthv_c = $(vkshaderpath)/sprite_depth.vert.spvc sprite_depthf_src = $(vkshaderpath)/sprite_depth.frag sprite_depthf_c = $(vkshaderpath)/sprite_depth.frag.spvc -twod_impalpha_src = $(vkshaderpath)/twod_impalpha.frag -twod_impalpha_c = $(vkshaderpath)/twod_impalpha.frag.spvc twodv_src = $(vkshaderpath)/twod.vert twodv_c = $(vkshaderpath)/twod.vert.spvc twodf_src = $(vkshaderpath)/twod.frag @@ -343,6 +351,13 @@ fstriangle_c = $(vkshaderpath)/fstriangle.vert.spvc pushcolor_src = $(vkshaderpath)/pushcolor.frag pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc +$(glyph_vert_c): $(glyph_vert_src) +$(glyph_color_c): $(glyph_color_src) +$(glyph_coverage_c): $(glyph_coverage_src) + +$(linev_c): $(linev_src) +$(linef_c): $(linef_src) + $(partphysicsc_c): $(partphysicsc_src) $(partupdatec_c): $(partupdatec_src) $(particlev_c): $(particlev_src) @@ -357,8 +372,6 @@ $(sprite_depthv_c): $(sprite_depthv_src) $(sprite_depthf_c): $(sprite_depthf_src) -$(twod_impalpha_c): $(twod_impalpha_src) - $(twodv_c): $(twodv_src) $(twodf_c): $(twodf_src) @@ -406,6 +419,11 @@ $(fstriangle_c): $(fstriangle_src) $(pushcolor_c): $(pushcolor_src) vkshader_c = \ + $(glyph_c) \ + $(glyph_color_c) \ + $(glyph_coverage_c) \ + $(linev_c) \ + $(linef_c) \ $(partphysicsc_c) \ $(partupdatec_c) \ $(particlev_c) \ @@ -415,7 +433,6 @@ vkshader_c = \ $(sprite_gbuff_c) \ $(sprite_depthv_c) \ $(sprite_depthf_c) \ - $(twod_impalpha_c) \ $(twodv_c) \ $(twodf_c) \ $(quakebspv_c) \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index a73647418..1046818e0 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -97,6 +97,21 @@ }, ); }; + glyph_pool = { + maxSets = 16; + bindings = ( + { + // glyph geometry data (offset and uv) + type = uniform_texel_buffer; + descriptorCount = 16; + }, + { + // glyph texture data + type = combined_image_sampler; + descriptorCount = 16; + }, + ); + }; entity_pool = { flags = free_descriptor_set; maxSets = 512; @@ -216,6 +231,24 @@ }, ); }; + glyph_data_set = { + bindings = ( + { + // glyph geometry data (offset and uv) + binding = 0; + descriptorType = uniform_texel_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + // glyph texture data + binding = 1; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; texture_set = { bindings = ( { @@ -359,6 +392,12 @@ twod_layout = { setLayouts = (matrix_set, twod_set); }; + glyph_layout = { + setLayouts = (matrix_set, glyph_data_set); + }; + lines_layout = { + setLayouts = (matrix_set); + }; quakebsp_layout = { setLayouts = (matrix_set, entity_set, texture_set, texture_set); pushConstantRanges = ( @@ -526,6 +565,19 @@ { location = 2; binding = 1; format = r32_uint; offset = 0; }, ); }; + glyph = { + bindings = ( + { binding = 0; stride = "4 + 4 + 2 * 4"; inputRate = instance; }, + ); + attributes = ( + // glyph index + { location = 0; binding = 0; format = r32_uint; offset = 0; }, + // glyph color + { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, + // glyph position (2d) + { location = 2; binding = 0; format = r32g32_sfloat; offset = 8; }, + ); + }; iqm = { bindings = ( { binding = 0; stride = 20; inputRate = vertex; }, @@ -1046,24 +1098,44 @@ }; layout = twod_layout; }; - twod_impalpha = { - @inherit = $properties.pipelines.twod; + glyph = { + @inherit = $properties.pipelines.trans_base;//FIXME should be sparate + vertexInput = $properties.vertexInput.glyph; + inputAssembly = { + // glyphs are drawn using instanced quads, so primitive restart + // is not needed as only four vertices are drawn per instance. + topology = triangle_strip; + primitiveRestartEnable = false; + }; + rasterization = $properties.rasterization.counter_cw_cull_back; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.alpha_blend); + }; + layout = glyph_layout; + }; + glyph_color = { + @inherit = $properties.pipelines.glyph; stages = ( - { - stage = vertex; - name = main; - module = $builtin/twod.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/twod_impalpha.frag; - }, + { stage = vertex; name = main; module = $builtin/glyph.vert; }, + { stage = fragment; name = main; module = $builtin/glyph_color.frag; }, + ); + }; + glyph_coverage = { + @inherit = $properties.pipelines.glyph; + stages = ( + { stage = vertex; name = main; module = $builtin/glyph.vert; }, + { stage = fragment; name = main; module = $builtin/glyph_coverage.frag; }, ); }; lines = { @inherit = $properties.pipelines.twod; + stages = ( + { stage = vertex; name = main; module = $builtin/line.vert; }, + { stage = fragment; name = main; module = $builtin/line.frag; }, + ); inputAssembly = $properties.inputAssembly.lines; + layout = lines_layout; }; lighting = { @inherit = $properties.pipelines.comp_base; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 43cf4959f..95c733cfd 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -38,6 +38,16 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/shader.h" +static +#include "libs/video/renderer/vulkan/shader/glyph.vert.spvc" +static +#include "libs/video/renderer/vulkan/shader/glyph_color.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/glyph_coverage.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/line.vert.spvc" +static +#include "libs/video/renderer/vulkan/shader/line.frag.spvc" static #include "libs/video/renderer/vulkan/shader/particle.vert.spvc" static @@ -57,8 +67,6 @@ static static #include "libs/video/renderer/vulkan/shader/sprite_depth.frag.spvc" static -#include "libs/video/renderer/vulkan/shader/twod_impalpha.frag.spvc" -static #include "libs/video/renderer/vulkan/shader/twod.vert.spvc" static #include "libs/video/renderer/vulkan/shader/twod.frag.spvc" @@ -112,6 +120,11 @@ typedef struct shaderdata_s { } shaderdata_t; static shaderdata_t builtin_shaders[] = { + { "glyph.vert", glyph_vert, sizeof (glyph_vert) }, + { "glyph_color.frag", glyph_color_frag, sizeof (glyph_color_frag) }, + { "glyph_coverage.frag", glyph_coverage_frag, sizeof (glyph_coverage_frag) }, + { "line.vert", line_vert, sizeof (line_vert) }, + { "line.frag", line_frag, sizeof (line_frag) }, { "particle.vert", particle_vert, sizeof (particle_vert) }, { "particle.geom", particle_geom, sizeof (particle_geom) }, { "particle.frag", particle_frag, sizeof (particle_frag) }, @@ -121,7 +134,6 @@ static shaderdata_t builtin_shaders[] = { { "sprite_gbuf.frag", sprite_gbuf_frag, sizeof (sprite_gbuf_frag) }, { "sprite_depth.vert", sprite_depth_vert, sizeof (sprite_depth_vert) }, { "sprite_depth.frag", sprite_depth_frag, sizeof (sprite_depth_frag) }, - { "twod_impalpha.frag", twod_impalpha_frag, sizeof (twod_impalpha_frag) }, { "twod.vert", twod_vert, sizeof (twod_vert) }, { "twod.frag", twod_frag, sizeof (twod_frag) }, { "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) }, diff --git a/libs/video/renderer/vulkan/shader/glyph.vert b/libs/video/renderer/vulkan/shader/glyph.vert new file mode 100644 index 000000000..65cea66dc --- /dev/null +++ b/libs/video/renderer/vulkan/shader/glyph.vert @@ -0,0 +1,32 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; +}; +layout (set = 1, binding = 0) uniform textureBuffer glyph_data; + +// per instance data +layout (location = 0) in uint glyph_index; +layout (location = 1) in vec4 glyph_color; +layout (location = 2) in vec2 glyph_position; + +// rg -> offset x,y +// ba -> texture u,v + +layout (location = 0) out vec2 uv; +layout (location = 1) out vec4 color; + +void +main (void) +{ + vec4 glyph = texelFetch (glyph_data, int(glyph_index) * 4 + gl_VertexIndex); + // offset stored in glyph components 0 and 1 + vec2 position = glyph_position + glyph.xy; + gl_Position = Projection2d * vec4 (position.xy, 0.0, 1.0); + // texture uv stored in glyph components 2 and 3 + uv = glyph.pq; + color = glyph_color; +} diff --git a/libs/video/renderer/vulkan/shader/twod_impalpha.frag b/libs/video/renderer/vulkan/shader/glyph_color.frag similarity index 56% rename from libs/video/renderer/vulkan/shader/twod_impalpha.frag rename to libs/video/renderer/vulkan/shader/glyph_color.frag index 5f3c50865..08941cd10 100644 --- a/libs/video/renderer/vulkan/shader/twod_impalpha.frag +++ b/libs/video/renderer/vulkan/shader/glyph_color.frag @@ -1,8 +1,8 @@ #version 450 -layout (set = 1, binding = 0) uniform sampler2D Texture; +layout (set = 1, binding = 1) uniform sampler2D Texture; -layout (location = 0) in vec2 st; +layout (location = 0) in vec2 uv; layout (location = 1) in vec4 color; layout (location = 0) out vec4 frag_color; @@ -12,6 +12,6 @@ main (void) { vec4 pix; - pix = texture(Texture, st).rrrr; + pix = texture (Texture, uv); frag_color = pix * color; } diff --git a/libs/video/renderer/vulkan/shader/glyph_coverage.frag b/libs/video/renderer/vulkan/shader/glyph_coverage.frag new file mode 100644 index 000000000..526b39dfb --- /dev/null +++ b/libs/video/renderer/vulkan/shader/glyph_coverage.frag @@ -0,0 +1,17 @@ +#version 450 + +layout (set = 1, binding = 1) uniform sampler2D Texture; + +layout (location = 0) in vec2 uv; +layout (location = 1) in vec4 color; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + vec4 pix; + + pix = texture (Texture, uv).rrrr; + frag_color = pix * color; +} diff --git a/libs/video/renderer/vulkan/shader/line.frag b/libs/video/renderer/vulkan/shader/line.frag new file mode 100644 index 000000000..080248de6 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/line.frag @@ -0,0 +1,11 @@ +#version 450 + +layout (location = 0) in vec4 color; + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + frag_color = color; +} diff --git a/libs/video/renderer/vulkan/shader/line.vert b/libs/video/renderer/vulkan/shader/line.vert new file mode 100644 index 000000000..754ba5cfb --- /dev/null +++ b/libs/video/renderer/vulkan/shader/line.vert @@ -0,0 +1,20 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; +}; +layout (location = 0) in vec2 vertex; +layout (location = 1) in vec2 uv; +layout (location = 2) in vec4 vcolor; + +layout (location = 0) out vec4 color; + +void +main (void) +{ + gl_Position = Projection2d * vec4 (vertex.xy, 0.0, 1.0); + color = vcolor; +} diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 2fed1cb1f..42e76a493 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -63,6 +63,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/resource.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" #include "QF/ui/view.h" @@ -78,6 +79,17 @@ typedef struct { float color[4]; } drawvert_t; +typedef struct { + uint32_t index; + byte color[4]; + float position[2]; +} glyphinst_t; + +typedef struct { + float offset[2]; + float uv[2]; +} glyphvert_t; + typedef struct cachepic_s { char *name; qpic_t *pic; @@ -89,26 +101,48 @@ typedef struct vertqueue_s { int size; } vertqueue_t; +typedef struct glyphqueue_s { + glyphinst_t *glyphs; + int count; + int size; +} glyphqueue_t; + typedef struct drawframe_s { - size_t vert_offset; - size_t iavert_offset; + size_t quad_offset; + size_t glyph_offset; size_t line_offset; + VkBuffer quad_buffer; + VkBuffer glyph_buffer; + VkBuffer line_buffer; vertqueue_t quad_verts; - vertqueue_t iaquad_verts; + glyphqueue_t glyph_insts; vertqueue_t line_verts; VkCommandBuffer cmd; - VkDescriptorSet descriptors; - VkDescriptorSet iadescriptors; } drawframe_t; typedef struct drawframeset_s DARRAY_TYPE (drawframe_t) drawframeset_t; +typedef struct drawfontres_s { + qfv_resource_t resource; + qfv_resobj_t glyph_data; + qfv_resobj_t glyph_bview; + qfv_resobj_t glyph_image; + qfv_resobj_t glyph_iview; +} drawfontres_t; + +typedef struct drawfont_s { + VkDescriptorSet set; + drawfontres_t *resource; + rfont_t *font; +} drawfont_t; + +typedef struct drawfontset_s + DARRAY_TYPE (drawfont_t) drawfontset_t; + typedef struct drawctx_s { VkSampler sampler; scrap_t *scrap; - rfont_t *font; - qfv_tex_t *font_tex; qfv_stagebuf_t *stage; qpic_t *crosshair; qpic_t *conchars; @@ -120,15 +154,18 @@ typedef struct drawctx_s { memsuper_t *pic_memsuper; memsuper_t *string_memsuper; hashtab_t *pic_cache; - VkBuffer vert_buffer; - VkDeviceMemory vert_memory; - VkBuffer ind_buffer; - VkDeviceMemory ind_memory; + qfv_resource_t *draw_resource; + qfv_resobj_t *quad_objects; + qfv_resobj_t *glyph_objects; + qfv_resobj_t *line_objects; VkPipeline quad_pipeline; - VkPipeline iaquad_pipeline; + VkPipeline glyph_coverage_pipeline; VkPipeline line_pipeline; VkPipelineLayout layout; + VkPipelineLayout glyph_layout; + VkDescriptorSet quad_set; drawframeset_t frames; + drawfontset_t fonts; } drawctx_t; // enough for a full screen of 8x8 chars at 1920x1080 plus some extras (368) @@ -136,6 +173,8 @@ typedef struct drawctx_s { #define VERTS_PER_QUAD (4) #define INDS_PER_QUAD (5) // one per vert plus primitive reset +#define MAX_GLYPHS (32768) + #define MAX_LINES (32768) #define VERTS_PER_LINE (2) @@ -150,66 +189,108 @@ create_quad_buffers (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - drawctx_t *dctx = ctx->draw_context; - - size_t vert_size; - size_t ind_size; size_t frames = ctx->frames.size; - VkBuffer vbuf, ibuf; - VkDeviceMemory vmem, imem; - vert_size = frames * VERTS_PER_FRAME * sizeof (drawvert_t); - ind_size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t); + dctx->draw_resource = malloc (2 * sizeof (qfv_resource_t) + // quads: index + frames vertex buffers + + (1 + frames) * sizeof (qfv_resobj_t) + // glyphs: frames instance vertex buffers + + (frames) * sizeof (qfv_resobj_t) + // lines: frames vertex buffers + + (frames) * sizeof (qfv_resobj_t)); + dctx->quad_objects = (qfv_resobj_t *) &dctx->draw_resource[2]; + dctx->glyph_objects = &dctx->quad_objects[1 + frames]; + dctx->line_objects = &dctx->glyph_objects[frames]; - vbuf = QFV_CreateBuffer (device, vert_size, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - ibuf = QFV_CreateBuffer (device, ind_size, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT - | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - vmem = QFV_AllocBufferMemory (device, vbuf, - VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - vert_size, 0); - imem = QFV_AllocBufferMemory (device, ibuf, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - ind_size, 0); - QFV_BindBufferMemory (device, vbuf, vmem, 0); - QFV_BindBufferMemory (device, ibuf, imem, 0); + dctx->draw_resource[0] = (qfv_resource_t) { + .name = "draw", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = 1, // has only the quad index buffer + .objects = dctx->quad_objects, + }; + dctx->draw_resource[1] = (qfv_resource_t) { + .name = "draw", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + .num_objects = (frames) + (frames) + (frames), + .objects = dctx->quad_objects + 1, + }; - dctx->vert_buffer = vbuf; - dctx->vert_memory = vmem; - dctx->ind_buffer = ibuf; - dctx->ind_memory = imem; + dctx->quad_objects[0] = (qfv_resobj_t) { + .name = "quads.index", + .type = qfv_res_buffer, + .buffer = { + .size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + }, + }; + __auto_type ind_buffer = &dctx->quad_objects[0]; + + for (size_t i = 0; i < frames; i++) { + dctx->quad_objects[i + 1] = (qfv_resobj_t) { + .name = "quads.geom", + .type = qfv_res_buffer, + .buffer = { + .size = MAX_QUADS * VERTS_PER_QUAD * sizeof (drawvert_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + }, + }; + dctx->glyph_objects[i] = (qfv_resobj_t) { + .name = "glyphs.inst", + .type = qfv_res_buffer, + .buffer = { + .size = MAX_GLYPHS * sizeof (glyphinst_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + }, + }; + dctx->line_objects[i] = (qfv_resobj_t) { + .name = "lines.geom", + .type = qfv_res_buffer, + .buffer = { + .size = MAX_LINES * VERTS_PER_LINE * sizeof (drawvert_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + }, + }; + } + QFV_CreateResource (device, &dctx->draw_resource[0]); + QFV_CreateResource (device, &dctx->draw_resource[1]); void *data; - dfunc->vkMapMemory (device->dev, vmem, 0, vert_size, 0, &data); - drawvert_t *vert_data = data; + VkDeviceMemory memory = dctx->draw_resource[1].memory; + dfunc->vkMapMemory (device->dev, memory, 0, VK_WHOLE_SIZE, 0, &data); for (size_t f = 0; f < frames; f++) { drawframe_t *frame = &dctx->frames.a[f]; - size_t ind = f * VERTS_PER_FRAME; - size_t iaind = ind + IAQUADS_OFFSET; - size_t lind = ind + LINES_OFFSET; - frame->vert_offset = ind * sizeof (drawvert_t); - frame->iavert_offset = iaind; - frame->line_offset = lind; + frame->quad_buffer = dctx->quad_objects[1 + f].buffer.buffer; + frame->quad_offset = dctx->quad_objects[1 + f].buffer.offset; + frame->glyph_buffer = dctx->glyph_objects[f].buffer.buffer; + frame->glyph_offset = dctx->glyph_objects[f].buffer.offset; + frame->line_buffer = dctx->line_objects[f].buffer.buffer; + frame->line_offset = dctx->line_objects[f].buffer.offset; + frame->quad_verts = (vertqueue_t) { - .verts = vert_data + ind, + .verts = (drawvert_t *) ((byte *)data + frame->quad_offset), .size = MAX_QUADS, }; - frame->iaquad_verts = (vertqueue_t) { - .verts = frame->quad_verts.verts + IAQUADS_OFFSET, + frame->glyph_insts = (glyphqueue_t) { + .glyphs = (glyphinst_t *) ((byte *)data + frame->glyph_offset), .size = MAX_QUADS, }; frame->line_verts = (vertqueue_t) { - .verts = frame->quad_verts.verts + LINES_OFFSET, - .size = MAX_LINES, + .verts = (drawvert_t *) ((byte *)data + frame->line_offset), + .size = MAX_QUADS, }; } // The indices will never change so pre-generate and stash them qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); - uint32_t *ind = QFV_PacketExtend (packet, ind_size); + uint32_t *ind = QFV_PacketExtend (packet, ind_buffer->buffer.size); for (int i = 0; i < MAX_QUADS; i++) { for (int j = 0; j < VERTS_PER_QUAD; j++) { *ind++ = i * VERTS_PER_QUAD + j; @@ -217,37 +298,11 @@ create_quad_buffers (vulkan_ctx_t *ctx) // mark end of primitive *ind++ = -1; } - - qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; - bb.barrier.buffer = ibuf; - bb.barrier.size = ind_size; - dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, - 0, 0, 0, 1, &bb.barrier, 0, 0); - VkBufferCopy copy_region = { packet->offset, 0, ind_size }; - dfunc->vkCmdCopyBuffer (packet->cmd, ctx->staging->buffer, ibuf, - 1, ©_region); - bb = bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]; - bb.barrier.buffer = ibuf; - bb.barrier.size = ind_size; - dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, - 0, 0, 0, 1, &bb.barrier, 0, 0); + QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, + &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); QFV_PacketSubmit (packet); } -static void -destroy_quad_buffers (vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - drawctx_t *dctx = ctx->draw_context; - - dfunc->vkUnmapMemory (device->dev, dctx->vert_memory); - dfunc->vkFreeMemory (device->dev, dctx->vert_memory, 0); - dfunc->vkFreeMemory (device->dev, dctx->ind_memory, 0); - dfunc->vkDestroyBuffer (device->dev, dctx->vert_buffer, 0); - dfunc->vkDestroyBuffer (device->dev, dctx->ind_buffer, 0); -} - static void flush_draw_scrap (vulkan_ctx_t *ctx) { @@ -387,19 +442,21 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; drawctx_t *dctx = ctx->draw_context; - destroy_quad_buffers (ctx); + QFV_DestroyResource (device, &dctx->draw_resource[0]); + QFV_DestroyResource (device, &dctx->draw_resource[1]); + for (size_t i = 0; i < dctx->fonts.size; i++) { + QFV_DestroyResource (device, &dctx->fonts.a[i].resource->resource); + free (dctx->fonts.a[i].resource); + } dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); - dfunc->vkDestroyPipeline (device->dev, dctx->iaquad_pipeline, 0); + dfunc->vkDestroyPipeline (device->dev, dctx->glyph_coverage_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0); Hash_DelTable (dctx->pic_cache); delete_memsuper (dctx->pic_memsuper); delete_memsuper (dctx->string_memsuper); QFV_DestroyScrap (dctx->scrap); QFV_DestroyStagingBuffer (dctx->stage); - if (dctx->font_tex) { - Vulkan_UnloadTex (ctx, dctx->font_tex); - } } void @@ -417,6 +474,10 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&dctx->frames, frames); DARRAY_RESIZE (&dctx->frames, frames); dctx->frames.grow = 0; + DARRAY_INIT (&dctx->fonts, 16); + DARRAY_RESIZE (&dctx->fonts, 16); + dctx->fonts.grow = 0; + dctx->fonts.size = 0; dctx->pic_memsuper = new_memsuper (); dctx->string_memsuper = new_memsuper (); @@ -457,16 +518,15 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); - dctx->iaquad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, - "twod_impalpha"); + dctx->glyph_coverage_pipeline + = Vulkan_CreateGraphicsPipeline (ctx, "glyph_coverage"); dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines"); dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout"); + dctx->glyph_layout = Vulkan_CreatePipelineLayout (ctx, "glyph_layout"); - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "twod_set"); - } + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); + layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "twod_set"); __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "twod_pool"); VkDescriptorImageInfo imageInfo = { @@ -474,38 +534,27 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) QFV_ScrapImageView (dctx->scrap), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; - VkDescriptorImageInfo iaimageInfo = { - dctx->sampler, - Vulkan_TexImageView (ctx->default_magenta), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }; __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); - __auto_type iasets = QFV_AllocateDescriptorSet (device, pool, layouts); + dctx->quad_set = sets->a[0]; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + dctx->quad_set, 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo, 0, 0 }, + }; + free (sets); + + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); for (size_t i = 0; i < frames; i++) { __auto_type dframe = &dctx->frames.a[i]; - dframe->descriptors = sets->a[i]; - dframe->iadescriptors = iasets->a[i]; - - VkWriteDescriptorSet write[] = { - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - dframe->descriptors, 0, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &imageInfo, 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - dframe->iadescriptors, 0, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &iaimageInfo, 0, 0 }, - }; - dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); dframe->cmd = cmdBuffers->a[i]; QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, dframe->cmd, va (ctx->va_ctx, "cmd:draw:%zd", i)); } - free (sets); qfvPopDebug (ctx); } @@ -948,7 +997,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - if (!dframe->quad_verts.count && !dframe->iaquad_verts.count + if (!dframe->quad_verts.count && !dframe->glyph_insts.count && !dframe->line_verts.count) { return; } @@ -957,18 +1006,19 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) //FIXME which pass? DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], cmd); + VkDeviceMemory memory = dctx->draw_resource[1].memory; VkMappedMemoryRange ranges[] = { { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - dctx->vert_memory, dframe->vert_offset, + memory, dframe->quad_offset, dframe->quad_verts.count * VERTS_PER_QUAD * sizeof (drawvert_t) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - dctx->vert_memory, dframe->iavert_offset, - dframe->iaquad_verts.count * VERTS_PER_QUAD * sizeof (drawvert_t) }, + memory, dframe->glyph_offset, + dframe->glyph_insts.count * VERTS_PER_QUAD * sizeof (drawvert_t) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - dctx->vert_memory, dframe->line_offset, + memory, dframe->line_offset, dframe->line_verts.count * VERTS_PER_LINE * sizeof (drawvert_t) }, }; - dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); + dfunc->vkFlushMappedMemoryRanges (device->dev, 3, ranges); dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { @@ -986,14 +1036,15 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) QFV_duCmdBeginLabel (device, cmd, "twod", { 0.6, 0.2, 0, 1}); - VkDeviceSize offsets[] = {dframe->vert_offset}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &dctx->vert_buffer, offsets); - dfunc->vkCmdBindIndexBuffer (cmd, dctx->ind_buffer, 0, - VK_INDEX_TYPE_UINT32); if (dframe->quad_verts.count) { + VkBuffer quad_buffer = dframe->quad_buffer; + VkBuffer ind_buffer = dctx->quad_objects[0].buffer.buffer; + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &quad_buffer, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); VkDescriptorSet set[2] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dframe->descriptors, + dctx->quad_set, }; VkPipelineLayout layout = dctx->layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, @@ -1004,58 +1055,50 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); dfunc->vkCmdDrawIndexed (cmd, dframe->quad_verts.count * INDS_PER_QUAD, - 1, 0, QUADS_OFFSET, 0); + 1, 0, 0, 0); } - if (dframe->iaquad_verts.count) { - VkDescriptorImageInfo iaimageInfo = { - dctx->sampler, - Vulkan_TexImageView (dctx->font_tex), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }; - VkWriteDescriptorSet write[] = { - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - dframe->iadescriptors, 0, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &iaimageInfo, 0, 0 }, - }; - dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + if (dframe->glyph_insts.count) { + VkBuffer glyph_buffer = dframe->glyph_buffer; + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &glyph_buffer, offsets); VkDescriptorSet set[2] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dframe->iadescriptors, + dctx->fonts.a[0].set, }; - VkPipelineLayout layout = dctx->layout; + VkPipelineLayout layout = dctx->glyph_layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 2, set, 0, 0); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - dctx->iaquad_pipeline); + dctx->glyph_coverage_pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - dfunc->vkCmdDrawIndexed (cmd, dframe->iaquad_verts.count*INDS_PER_QUAD, - 1, 0, IAQUADS_OFFSET, 0); + dfunc->vkCmdDraw (cmd, 4, dframe->glyph_insts.count, 0, 0); } if (dframe->line_verts.count) { - VkDescriptorSet set[2] = { + VkBuffer line_buffer = dframe->line_buffer; + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &line_buffer, offsets); + VkDescriptorSet set[1] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dframe->descriptors, }; VkPipelineLayout layout = dctx->layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); + layout, 0, 1, set, 0, 0); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dctx->line_pipeline); dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE, - 1, LINES_OFFSET, 0); + 1, 0, 0); } QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); dframe->quad_verts.count = 0; - dframe->iaquad_verts.count = 0; + dframe->glyph_insts.count = 0; dframe->line_verts.count = 0; } @@ -1075,45 +1118,161 @@ Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) } int -Vulkan_Draw_AddFont (rfont_t *font, vulkan_ctx_t *ctx) +Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx) { + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; drawctx_t *dctx = ctx->draw_context; + int fontid = dctx->fonts.size; + DARRAY_OPEN_AT (&dctx->fonts, fontid, 1); + drawfont_t *font = &dctx->fonts.a[fontid]; - if (dctx->font_tex) { - Vulkan_UnloadTex (ctx, dctx->font_tex); - dctx->font_tex = 0; - } - dctx->font = font; - if (dctx->font) { - tex_t tex = { - .width = font->scrap.width, - .height = font->scrap.height, - .format = tex_l, - .loaded = 1, - .data = font->scrap_bitmap, + font->font = rfont; + + font->resource = malloc (sizeof (drawfontres_t)); + font->resource->resource = (qfv_resource_t) { + .name = "glyph_data", //FIXME include font info + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = 4, + .objects = &font->resource->glyph_data, + }; + + font->resource->glyph_data = (qfv_resobj_t) { + .name = "geom", + .type = qfv_res_buffer, + .buffer = { + .size = rfont->num_glyphs * 4 * sizeof (glyphvert_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, + }, + }; + __auto_type glyph_data = &font->resource->glyph_data; + + font->resource->glyph_bview = (qfv_resobj_t) { + .name = "geom_view", + .type = qfv_res_buffer_view, + .buffer_view = { + .buffer = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = 0, + .size = font->resource->glyph_data.buffer.size, + }, + }; + __auto_type glyph_bview = &font->resource->glyph_bview; + + tex_t tex = { + .width = rfont->scrap.width, + .height = rfont->scrap.height, + .format = tex_l, + .loaded = 1, + .data = rfont->scrap_bitmap, + }; + QFV_ResourceInitTexImage (&font->resource->glyph_image, "image", 0, &tex); + __auto_type glyph_image = &font->resource->glyph_image; + + font->resource->glyph_iview = (qfv_resobj_t) { + .name = "image_view", + .type = qfv_res_image_view, + .image_view = { + .image = 2, + .type = VK_IMAGE_VIEW_TYPE_2D, + .format = font->resource->glyph_image.image.format, + .aspect = VK_IMAGE_ASPECT_COLOR_BIT, + }, + }; + __auto_type glyph_iview = &font->resource->glyph_iview; + + QFV_CreateResource (ctx->device, &font->resource->resource); + + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + glyphvert_t *verts = QFV_PacketExtend (packet, glyph_data->buffer.size); + for (FT_Long i = 0; i < rfont->num_glyphs; i++) { + rglyph_t *glyph = &rfont->glyphs[i]; + float x = 0;//glyph->bearing[0]; + float y = 0;//-glyph->bearing[1]; // glyph +Y goes up + float w = glyph->rect->width; + float h = glyph->rect->height; + float u = glyph->rect->x; + float v = glyph->rect->y; + // assumes the glyph image is square + float s = 1.0 / rfont->scrap.width; + verts[i * 4 + 0] = (glyphvert_t) { + .offset = { x + 0, y + 0 }, + .uv = {(u + 0.25) * s, (v + 0.25) * s }, + }; + verts[i * 4 + 1] = (glyphvert_t) { + .offset = { x + 0, y + h }, + .uv = {(u + 0.25) * s, (v + h - 0.25) * s }, + }; + verts[i * 4 + 2] = (glyphvert_t) { + .offset = { x + w, y + 0 }, + .uv = {(u + w - 0.25) * s, (v + 0.25) * s }, + }; + verts[i * 4 + 3] = (glyphvert_t) { + .offset = { x + w, y + h }, + .uv = {(u + w - 0.25) * s, (v + h - 0.25) * s }, }; - dctx->font_tex = Vulkan_LoadTex (ctx, &tex, 0, "draw.font"); } + QFV_PacketCopyBuffer (packet, glyph_data->buffer.buffer, + &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]); + QFV_PacketSubmit (packet); + + packet = QFV_PacketAcquire (ctx->staging); + byte *texels = QFV_PacketExtend (packet, tex.width * tex.height); + memcpy (texels, tex.data, tex.width * tex.height); + QFV_PacketCopyImage (packet, glyph_image->image.image, + tex.width, tex.height, + &imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]); + QFV_PacketSubmit (packet); + + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); + layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "glyph_data_set"); + __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "glyph_pool"); + __auto_type glyph_sets = QFV_AllocateDescriptorSet (device, pool, layouts); + font->set = glyph_sets->a[0]; + VkDescriptorImageInfo imageInfo = { + dctx->sampler, + glyph_iview->image_view.view, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + font->set, 0, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 0, 0, &glyph_bview->buffer_view.view }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + font->set, 1, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo, 0, 0 }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + free (glyph_sets); return 0; } typedef struct { - drawframe_t *dframe; - subpic_t *subpic; - quat_t color; + drawframe_t *dframe; + drawfont_t *font; + byte color[4]; } rgctx_t; static void vulkan_render_glyph (rglyph_t *glyph, int x, int y, void *_rgctx) { rgctx_t *rgctx = _rgctx; + glyphqueue_t *queue = &rgctx->dframe->glyph_insts;; - *((vrect_t **) &rgctx->subpic->rect) = glyph->rect; - int gw = glyph->rect->width; - int gh = glyph->rect->height; - draw_pic (x, y, gw, gh, rgctx->subpic, 0, 0, gw, gh, rgctx->color, - &rgctx->dframe->iaquad_verts); + if (queue->count >= queue->size) { + return; + } + + glyphinst_t *inst = &queue->glyphs[queue->count++]; + inst->index = glyph->charcode; + QuatCopy (rgctx->color, inst->color); + inst->position[0] = x; + inst->position[1] = y; } void @@ -1121,21 +1280,16 @@ Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, vulkan_ctx_t *ctx) { drawctx_t *dctx = ctx->draw_context; - if (!dctx->font) { + if (fontid < 0 || (unsigned) fontid > dctx->fonts.size) { return; } drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; //FIXME ewwwwwww - subpic_t glyph_subpic = { - .width = dctx->font->scrap.width, - .height = dctx->font->scrap.height, - .size = 1.0 / dctx->font->scrap.width, - }; rgctx_t rgctx = { .dframe = dframe, - .subpic = &glyph_subpic, - .color = { 0.5, 1, 0.6, 1 }, + .font = &dctx->fonts.a[fontid], + .color = { 127, 255, 153, 255 }, }; rtext_t text = { .text = str, @@ -1144,7 +1298,7 @@ Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, .direction = HB_DIRECTION_LTR, }; - rshaper_t *shaper = RText_NewShaper (dctx->font); + rshaper_t *shaper = RText_NewShaper (rgctx.font->font); RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx); RText_DeleteShaper (shaper); } From 4feffd2de5b19319d01de2026512750f33b3a826 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Oct 2022 16:53:13 +0900 Subject: [PATCH 3067/3664] [vulkan] Support multiple loaded fonts Currently, only 16 fonts can be loaded (I need to sort out descriptor set pools), but glyphs are grouped into batches of the same font. While not quite optimal as it can result in bouncing between descriptor sets a lot, it's still reasonably efficient. --- libs/video/renderer/vulkan/vulkan_draw.c | 62 +++++++++++++++++------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 42e76a493..b2639eb24 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -73,6 +73,14 @@ #include "r_internal.h" #include "vid_vulkan.h" +typedef struct descbatch_s { + int32_t descid; // texture or font descriptor id + uint32_t count; // number of objects in batch +} descbatch_t; + +typedef struct descbatchset_s + DARRAY_TYPE (descbatch_t) descbatchset_t; + typedef struct { float xy[2]; float st[2]; @@ -112,7 +120,9 @@ typedef struct drawframe_s { size_t glyph_offset; size_t line_offset; VkBuffer quad_buffer; + descbatchset_t quad_batch; VkBuffer glyph_buffer; + descbatchset_t glyph_batch; VkBuffer line_buffer; vertqueue_t quad_verts; glyphqueue_t glyph_insts; @@ -278,10 +288,12 @@ create_quad_buffers (vulkan_ctx_t *ctx) .verts = (drawvert_t *) ((byte *)data + frame->quad_offset), .size = MAX_QUADS, }; + DARRAY_INIT (&frame->quad_batch, 16); frame->glyph_insts = (glyphqueue_t) { .glyphs = (glyphinst_t *) ((byte *)data + frame->glyph_offset), .size = MAX_QUADS, }; + DARRAY_INIT (&frame->glyph_batch, 16); frame->line_verts = (vertqueue_t) { .verts = (drawvert_t *) ((byte *)data + frame->line_offset), .size = MAX_QUADS, @@ -1062,19 +1074,28 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) VkBuffer glyph_buffer = dframe->glyph_buffer; VkDeviceSize offsets[] = {0}; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &glyph_buffer, offsets); - VkDescriptorSet set[2] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dctx->fonts.a[0].set, - }; - VkPipelineLayout layout = dctx->glyph_layout; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dctx->glyph_coverage_pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - dfunc->vkCmdDraw (cmd, 4, dframe->glyph_insts.count, 0, 0); + + uint32_t inst_start = 0; + for (size_t i = 0; i < dframe->glyph_batch.size; i++) { + int fontid = dframe->glyph_batch.a[i].descid; + uint32_t inst_count = dframe->glyph_batch.a[i].count; + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + dctx->fonts.a[fontid].set, + }; + VkPipelineLayout layout = dctx->glyph_layout; + dfunc->vkCmdBindDescriptorSets (cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + + dfunc->vkCmdDraw (cmd, 4, inst_count, 0, inst_start); + inst_start += inst_count; + } + DARRAY_RESIZE (&dframe->glyph_batch, 0); } if (dframe->line_verts.count) { @@ -1131,7 +1152,7 @@ Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx) font->resource = malloc (sizeof (drawfontres_t)); font->resource->resource = (qfv_resource_t) { - .name = "glyph_data", //FIXME include font info + .name = va (ctx->va_ctx, "glyph_data:%d", fontid), .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, .num_objects = 4, @@ -1249,13 +1270,13 @@ Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx) dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); free (glyph_sets); - return 0; + return fontid; } typedef struct { - drawframe_t *dframe; - drawfont_t *font; - byte color[4]; + drawframe_t *dframe; + descbatch_t *batch; + byte color[4]; } rgctx_t; static void @@ -1268,6 +1289,7 @@ vulkan_render_glyph (rglyph_t *glyph, int x, int y, void *_rgctx) return; } + rgctx->batch->count++; glyphinst_t *inst = &queue->glyphs[queue->count++]; inst->index = glyph->charcode; QuatCopy (rgctx->color, inst->color); @@ -1285,12 +1307,11 @@ Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, } drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - //FIXME ewwwwwww rgctx_t rgctx = { .dframe = dframe, - .font = &dctx->fonts.a[fontid], .color = { 127, 255, 153, 255 }, }; + //FIXME ewwwwwww rtext_t text = { .text = str, .language = "en", @@ -1298,7 +1319,14 @@ Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, .direction = HB_DIRECTION_LTR, }; - rshaper_t *shaper = RText_NewShaper (rgctx.font->font); + rgctx.batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1]; + if (!dframe->glyph_batch.size || rgctx.batch->descid != fontid) { + DARRAY_APPEND(&dframe->glyph_batch, + ((descbatch_t) { .descid = fontid })); + rgctx.batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1]; + } + + rshaper_t *shaper = RText_NewShaper (dctx->fonts.a[fontid].font); RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx); RText_DeleteShaper (shaper); } From 8120adb455799ab309a5d5a6db779e944041fe4c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 7 Oct 2022 16:58:04 +0900 Subject: [PATCH 3068/3664] [renderer] Reduce glyph pixel area padding from 2x to 1.2x With the improved atlas allocation, 2x is no longer needed and 1.2x seems to be sufficient. Most importantly, it reduced the texture for amiri-regular.ttf at 72 pix height from 8x to 4x (the staging buffer isn't big enough for 8k textures). --- libs/video/renderer/r_font.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/r_font.c b/libs/video/renderer/r_font.c index 2421925a5..6f30d27c0 100644 --- a/libs/video/renderer/r_font.c +++ b/libs/video/renderer/r_font.c @@ -103,7 +103,7 @@ R_FontLoad (QFile *font_file, int size) __auto_type g = font->face->glyph; pixels += g->bitmap.width * g->bitmap.rows; } - pixels = sqrt (2 * pixels); + pixels = sqrt (5 * pixels / 4); pixels = BITOP_RUP (pixels); R_ScrapInit (&font->scrap, pixels, pixels); font->scrap_bitmap = calloc (1, pixels * pixels); From f16fc15605a72d3a0de1479b52bbfa0be3c5ae32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 9 Oct 2022 01:08:48 +0900 Subject: [PATCH 3069/3664] [scene] Correct some typos in hierarchy.h Lost the y somewhere --- include/QF/scene/hierarchy.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/QF/scene/hierarchy.h b/include/QF/scene/hierarchy.h index 1283c6de8..4ac088591 100644 --- a/include/QF/scene/hierarchy.h +++ b/include/QF/scene/hierarchy.h @@ -1,5 +1,5 @@ /* - hierarch.h + hierarchy.h Hierarchy management @@ -28,8 +28,8 @@ */ -#ifndef __QF_scene_hierarch_h -#define __QF_scene_hierarch_h +#ifndef __QF_scene_hierarchy_h +#define __QF_scene_hierarchy_h #include "QF/darray.h" #include "QF/qtypes.h" @@ -77,4 +77,4 @@ uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); ///@} -#endif//__QF_scene_hierarch_h +#endif//__QF_scene_hierarchy_h From 8464d712645a5a51684c9d87221dc01eefb74b34 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Oct 2022 02:00:33 +0900 Subject: [PATCH 3070/3664] [scene] Move hierarchies to an ECS-based system This is the beginning of adding ECS to QF. While the previous iteration of hierarchies was a start in the direction towards ECS, this pulls most of the 3d-specific transform stuff out of the hierarchy "objects", making all the matrices and vectors/quaternions actual components (in the ECS sense). There's more work to be done with respect to the transform and entity members of hierarchy_t (entity should probably go away entirely, and transform should become hierref_t (or whatever its final name becomes), but I wanted to get things working sooner than later. The motivation for the effort was to allow views to use hierarchy_t, which should be possible once I get entity and transform sorted out. I am really glad I already had automated tests for hierarchies, as things proved to be a little tricky to get working due to forgetting why certain things were there. --- include/QF/scene/component.h | 124 ++++++++ include/QF/scene/hierarchy.h | 42 +-- include/QF/scene/transform.h | 72 +++-- libs/scene/Makemodule.am | 1 + libs/scene/component.c | 32 ++ libs/scene/hierarchy.c | 489 +++++++++++-------------------- libs/scene/scene.c | 8 +- libs/scene/test/test-hierarchy.c | 216 +++++++------- libs/scene/transform.c | 280 +++++++++++++++--- 9 files changed, 763 insertions(+), 501 deletions(-) create mode 100644 include/QF/scene/component.h create mode 100644 libs/scene/component.c diff --git a/include/QF/scene/component.h b/include/QF/scene/component.h new file mode 100644 index 000000000..472851ee3 --- /dev/null +++ b/include/QF/scene/component.h @@ -0,0 +1,124 @@ +/* + component.h + + Component management + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/10/07 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_scene_component_h +#define __QF_scene_component_h + +#include +#include + +#include "QF/qtypes.h" + +/** \defgroup entity Hierarchy management + \ingroup utils +*/ +///@{ + +#define null_transform (~0u) + +typedef struct component_s { + size_t size; + void (*create) (void *); + void (*destroy) (void *); + const char *name; +} component_t; + +#define COMPINLINE GNU89INLINE inline + +COMPINLINE void Component_ResizeArray (const component_t *component, + void **array, uint32_t count); +COMPINLINE void Component_MoveElements (const component_t *component, + void *array, uint32_t dstIndex, + uint32_t srcIndex, uint32_t count); +COMPINLINE void Component_CopyElements (const component_t *component, + void *dstArray, uint32_t dstIndex, + const void *srcArray, uint32_t srcIndex, + uint32_t count); +COMPINLINE void Component_CreateElements (const component_t *component, + void *array, + uint32_t index, uint32_t count); + +#undef COMPINLINE +#ifndef IMPLEMENT_COMPONENT_Funcs +#define COMPINLINE GNU89INLINE inline +#else +#define COMPINLINE VISIBLE +#endif + +COMPINLINE +void +Component_ResizeArray (const component_t *component, + void **array, uint32_t count) +{ + *array = realloc (*array, count * component->size); +} + +COMPINLINE +void +Component_MoveElements (const component_t *component, + void *array, uint32_t dstIndex, uint32_t srcIndex, + uint32_t count) +{ + __auto_type dst = (byte *) array + dstIndex * component->size; + __auto_type src = (byte *) array + srcIndex * component->size; + memmove (dst, src, count * component->size); +} + +COMPINLINE +void +Component_CopyElements (const component_t *component, + void *dstArray, uint32_t dstIndex, + const void *srcArray, uint32_t srcIndex, + uint32_t count) +{ + __auto_type dst = (byte *) dstArray + dstIndex * component->size; + __auto_type src = (byte *) srcArray + srcIndex * component->size; + memcpy (dst, src, count * component->size); +} + +COMPINLINE +void +Component_CreateElements (const component_t *component, void *array, + uint32_t index, uint32_t count) +{ + if (component->create) { + for (uint32_t i = index; count-- > 0; i++) { + __auto_type dst = (byte *) array + i * component->size; + component->create (dst); + } + } else { + __auto_type dst = (byte *) array + index * component->size; + memset (dst, 0, count * component->size); + } +} + +///@} + +#endif//__QF_scene_component_h diff --git a/include/QF/scene/hierarchy.h b/include/QF/scene/hierarchy.h index 4ac088591..47d946540 100644 --- a/include/QF/scene/hierarchy.h +++ b/include/QF/scene/hierarchy.h @@ -42,36 +42,42 @@ */ ///@{ +/** Descriptors for components attached to every entity in the hierarchy. +*/ +typedef struct hierarchy_type_s { + uint32_t num_components; + const struct component_s *components; +} hierarchy_type_t; + #define null_transform (~0u) +typedef struct hierref_s { + struct hierarchy_s *hierarchy; + uint32_t index; ///< index in hierarchy + int32_t id; ///< scene id +} hierref_t; + typedef struct hierarchy_s { struct hierarchy_s *next; struct hierarchy_s **prev; struct scene_s *scene; - xformset_t transform; - entityset_t entity; - uint32set_t childCount; - uint32set_t childIndex; - uint32set_t parentIndex; - stringset_t name; - uint32set_t tag; - byteset_t modified; - mat4fset_t localMatrix; - mat4fset_t localInverse; - mat4fset_t worldMatrix; - mat4fset_t worldInverse; - vec4fset_t localRotation; - vec4fset_t localScale; - vec4fset_t worldRotation; - vec4fset_t worldScale; + uint32_t num_objects; + uint32_t max_objects; + struct transform_s **transform; //FIXME use hierref_t + struct entity_s **entity; //FIXME should not exist + uint32_t *childCount; + uint32_t *childIndex; + uint32_t *parentIndex; + const hierarchy_type_t *type; + void **components; } hierarchy_t; -hierarchy_t *Hierarchy_New (struct scene_s *scene, int createRoot); +hierarchy_t *Hierarchy_New (struct scene_s *scene, + const hierarchy_type_t *type, int createRoot); void Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count); hierarchy_t *Hierarchy_Copy (struct scene_s *scene, const hierarchy_t *src); void Hierarchy_Delete (hierarchy_t *hierarchy); -void Hierarchy_UpdateMatrices (hierarchy_t *hierarchy); uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstParent, uint32_t srcRoot); void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index 66f552df8..3bd933168 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -42,6 +42,22 @@ */ ///@{ +enum { + transform_type_name, + transform_type_tag, + transform_type_modified, + transform_type_localMatrix, + transform_type_localInverse, + transform_type_worldMatrix, + transform_type_worldInverse, + transform_type_localRotation, + transform_type_localScale, + transform_type_worldRotation, + transform_type_worldScale, + + transform_type_count +}; + typedef struct transform_s { hierarchy_t *hierarchy; struct scene_s *scene; ///< owning scene @@ -103,7 +119,7 @@ uint32_t Transform_ChildCount (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->childCount.a[transform->index]; + return h->childCount[transform->index]; } XFORMINLINE @@ -111,10 +127,10 @@ transform_t * Transform_GetChild (const transform_t *transform, uint32_t childIndex) { hierarchy_t *h = transform->hierarchy; - if (childIndex >= h->childCount.a[transform->index]) { + if (childIndex >= h->childCount[transform->index]) { return 0; } - return h->transform.a[h->childIndex.a[transform->index] + childIndex]; + return h->transform[h->childIndex[transform->index] + childIndex]; } XFORMINLINE @@ -125,7 +141,7 @@ Transform_GetParent (const transform_t *transform) return 0; } hierarchy_t *h = transform->hierarchy; - return h->transform.a[h->parentIndex.a[transform->index]]; + return h->transform[h->parentIndex[transform->index]]; } XFORMINLINE @@ -133,7 +149,8 @@ const char * Transform_GetName (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->name.a[transform->index]; + char **name = h->components[transform_type_name]; + return name[transform->index]; } XFORMINLINE @@ -141,7 +158,8 @@ uint32_t Transform_GetTag (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->tag.a[transform->index]; + uint32_t *tag = h->components[transform_type_tag]; + return tag[transform->index]; } XFORMINLINE @@ -149,7 +167,8 @@ void Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat) { hierarchy_t *h = transform->hierarchy; - vec4f_t *src = h->localMatrix.a[transform->index]; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + vec4f_t *src = localMatrix[transform->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -161,7 +180,8 @@ void Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat) { hierarchy_t *h = transform->hierarchy; - vec4f_t *src = h->localInverse.a[transform->index]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + vec4f_t *src = localInverse[transform->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -173,7 +193,8 @@ void Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat) { hierarchy_t *h = transform->hierarchy; - vec4f_t *src = h->worldMatrix.a[transform->index]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + vec4f_t *src = worldMatrix[transform->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -185,7 +206,8 @@ const vec4f_t * Transform_GetWorldMatrixPtr (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return worldMatrix[transform->index]; } XFORMINLINE @@ -193,7 +215,8 @@ void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat) { hierarchy_t *h = transform->hierarchy; - vec4f_t *src = h->worldInverse.a[transform->index]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *src = worldInverse[transform->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -205,7 +228,8 @@ vec4f_t Transform_GetLocalPosition (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->localMatrix.a[transform->index][3]; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + return localMatrix[transform->index][3]; } XFORMINLINE @@ -213,7 +237,8 @@ vec4f_t Transform_GetLocalRotation (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->localRotation.a[transform->index]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + return localRotation[transform->index]; } XFORMINLINE @@ -221,7 +246,8 @@ vec4f_t Transform_GetLocalScale (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->localScale.a[transform->index]; + vec4f_t *localScale = h->components[transform_type_localScale]; + return localScale[transform->index]; } XFORMINLINE @@ -229,7 +255,8 @@ vec4f_t Transform_GetWorldPosition (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][3]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return worldMatrix[transform->index][3]; } XFORMINLINE @@ -237,7 +264,8 @@ vec4f_t Transform_GetWorldRotation (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldRotation.a[transform->index]; + vec4f_t *worldRotation = h->components[transform_type_worldRotation]; + return worldRotation[transform->index]; } XFORMINLINE @@ -245,7 +273,8 @@ vec4f_t Transform_GetWorldScale (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldScale.a[transform->index]; + vec4f_t *worldScale = h->components[transform_type_worldScale]; + return worldScale[transform->index]; } XFORMINLINE @@ -253,7 +282,8 @@ vec4f_t Transform_Forward (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][0]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return worldMatrix[transform->index][0]; } XFORMINLINE @@ -261,7 +291,8 @@ vec4f_t Transform_Right (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return -h->worldMatrix.a[transform->index][1]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return -worldMatrix[transform->index][1]; } XFORMINLINE @@ -269,7 +300,8 @@ vec4f_t Transform_Up (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][2]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return worldMatrix[transform->index][2]; } ///@} diff --git a/libs/scene/Makemodule.am b/libs/scene/Makemodule.am index cbd89b1be..b1778c200 100644 --- a/libs/scene/Makemodule.am +++ b/libs/scene/Makemodule.am @@ -9,6 +9,7 @@ libs_scene_libQFscene_la_LIBADD= $(scene_deps) libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps) libs_scene_libQFscene_la_SOURCES= \ libs/scene/camera.c \ + libs/scene/component.c \ libs/scene/entity.c \ libs/scene/hierarchy.c \ libs/scene/light.c \ diff --git a/libs/scene/component.c b/libs/scene/component.c new file mode 100644 index 000000000..85ddc0cf9 --- /dev/null +++ b/libs/scene/component.c @@ -0,0 +1,32 @@ +/* + component.c + + Component handling + + Copyright (C) 2022 Bill Currke + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define IMPLEMENT_COMPONENT_Funcs +#include "QF/scene/component.h" diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 17c161d70..092a3bf3b 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -35,18 +35,25 @@ # include #endif +#include "QF/scene/component.h" #include "QF/scene/hierarchy.h" #include "QF/scene/transform.h" #include "scn_internal.h" +static component_t transform_component = { .size = sizeof (transform_t *) }; +static component_t entity_component = { .size = sizeof (entity_t *) }; +static component_t childCount_component = { .size = sizeof (uint32_t) }; +static component_t childIndex_component = { .size = sizeof (uint32_t) }; +static component_t parentIndex_component = { .size = sizeof (uint32_t) }; + static void hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { - for (size_t i = start; i < hierarchy->transform.size; i++) { - if (hierarchy->transform.a[i]) { - hierarchy->transform.a[i]->index += offset; + for (size_t i = start; i < hierarchy->num_objects; i++) { + if (hierarchy->transform[i]) { + hierarchy->transform[i]->index += offset; } } } @@ -55,8 +62,8 @@ static void hierarchy_UpdateChildIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { - for (size_t i = start; i < hierarchy->childIndex.size; i++) { - hierarchy->childIndex.a[i] += offset; + for (size_t i = start; i < hierarchy->num_objects; i++) { + hierarchy->childIndex[i] += offset; } } @@ -64,127 +71,86 @@ static void hierarchy_UpdateParentIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { - for (size_t i = start; i < hierarchy->parentIndex.size; i++) { - hierarchy->parentIndex.a[i] += offset; + for (size_t i = start; i < hierarchy->num_objects; i++) { + hierarchy->parentIndex[i] += offset; } } -static void -hierarchy_calcLocalInverse (hierarchy_t *h, uint32_t index) -{ - // This takes advantage of the fact that localMatrix is a simple - // homogenous scale/rotate/translate matrix with no shear - vec4f_t x = h->localMatrix.a[index][0]; - vec4f_t y = h->localMatrix.a[index][1]; - vec4f_t z = h->localMatrix.a[index][2]; - vec4f_t t = h->localMatrix.a[index][3]; - - // "one" is to ensure both the scalar and translation have 1 in their - // fourth components - vec4f_t one = { 0, 0, 0, 1 }; - vec4f_t nx = { x[0], y[0], z[0], 0 }; - vec4f_t ny = { x[1], y[1], z[1], 0 }; - vec4f_t nz = { x[2], y[2], z[2], 0 }; - vec4f_t nt = one - t[0] * nx - t[1] * ny - t[2] * nz; - // vertical dot product!!! - vec4f_t s = 1 / (nx * nx + ny * ny + nz * nz + one); - h->localInverse.a[index][0] = nx * s; - h->localInverse.a[index][1] = ny * s; - h->localInverse.a[index][2] = nz * s; - h->localInverse.a[index][3] = nt * s; -} - void -Hierarchy_UpdateMatrices (hierarchy_t *h) +Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count) { - for (size_t i = 0; i < h->localInverse.size; i++) { - if (h->modified.a[i]) { - hierarchy_calcLocalInverse (h, i); - } - } - if (h->modified.a[0]) { - memcpy (h->worldMatrix.a[0], - h->localMatrix.a[0], sizeof (mat4_t)); - memcpy (h->worldInverse.a[0], - h->localInverse.a[0], sizeof (mat4_t)); - h->worldRotation.a[0] = h->localRotation.a[0]; - h->worldScale.a[0] = h->localScale.a[0]; - } - for (size_t i = 1; i < h->worldMatrix.size; i++) { - uint32_t parent = h->parentIndex.a[i]; + if (hierarchy->num_objects + count > hierarchy->max_objects) { + uint32_t new_max = hierarchy->num_objects + count; + new_max += 15; + new_max &= ~15; - if (h->modified.a[i] || h->modified.a[parent]) { - mmulf (h->worldMatrix.a[i], - h->worldMatrix.a[parent], h->localMatrix.a[i]); - h->modified.a[i] = 1; - } - } - for (size_t i = 1; i < h->worldInverse.size; i++) { - uint32_t parent = h->parentIndex.a[i]; + Component_ResizeArray (&transform_component, + (void **) &hierarchy->transform, new_max); + Component_ResizeArray (&entity_component, + (void **) &hierarchy->entity, new_max); + Component_ResizeArray (&childCount_component, + (void **) &hierarchy->childCount, new_max); + Component_ResizeArray (&childIndex_component, + (void **) &hierarchy->childIndex, new_max); + Component_ResizeArray (&parentIndex_component, + (void **) &hierarchy->parentIndex, new_max); - if (h->modified.a[i] || h->modified.a[parent]) { - mmulf (h->worldInverse.a[i], - h->localInverse.a[i], h->worldInverse.a[parent]); + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + Component_ResizeArray (&hierarchy->type->components[i], + &hierarchy->components[i], new_max); } + hierarchy->max_objects = new_max; } - for (size_t i = 1; i < h->worldRotation.size; i++) { - uint32_t parent = h->parentIndex.a[i]; - if (h->modified.a[i] || h->modified.a[parent]) { - h->worldRotation.a[i] = qmulf (h->worldRotation.a[parent], - h->localRotation.a[i]); - } - } - for (size_t i = 1; i < h->worldScale.size; i++) { - uint32_t parent = h->parentIndex.a[i]; - if (h->modified.a[i] || h->modified.a[parent]) { - h->worldScale.a[i] = m3vmulf (h->worldMatrix.a[parent], - h->localScale.a[i]); - } - } - memset (h->modified.a, 0, h->modified.size); } static void hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t count) { - DARRAY_OPEN_AT (&hierarchy->transform, index, count); - DARRAY_OPEN_AT (&hierarchy->entity, index, count); - DARRAY_OPEN_AT (&hierarchy->childCount, index, count); - DARRAY_OPEN_AT (&hierarchy->childIndex, index, count); - DARRAY_OPEN_AT (&hierarchy->parentIndex, index, count); - DARRAY_OPEN_AT (&hierarchy->name, index, count); - DARRAY_OPEN_AT (&hierarchy->tag, index, count); - DARRAY_OPEN_AT (&hierarchy->modified, index, count); - DARRAY_OPEN_AT (&hierarchy->localMatrix, index, count); - DARRAY_OPEN_AT (&hierarchy->localInverse, index, count); - DARRAY_OPEN_AT (&hierarchy->worldMatrix, index, count); - DARRAY_OPEN_AT (&hierarchy->worldInverse, index, count); - DARRAY_OPEN_AT (&hierarchy->localRotation, index, count); - DARRAY_OPEN_AT (&hierarchy->localScale, index, count); - DARRAY_OPEN_AT (&hierarchy->worldRotation, index, count); - DARRAY_OPEN_AT (&hierarchy->worldScale, index, count); + Hierarchy_Reserve (hierarchy, count); + + hierarchy->num_objects += count; + uint32_t dstIndex = index + count; + count = hierarchy->num_objects - index - count; + Component_MoveElements (&transform_component, + hierarchy->transform, dstIndex, index, count); + Component_MoveElements (&entity_component, + hierarchy->entity, dstIndex, index, count); + Component_MoveElements (&childCount_component, + hierarchy->childCount, dstIndex, index, count); + Component_MoveElements (&childIndex_component, + hierarchy->childIndex, dstIndex, index, count); + Component_MoveElements (&parentIndex_component, + hierarchy->parentIndex, dstIndex, index, count); + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + Component_MoveElements (&hierarchy->type->components[i], + hierarchy->components[i], + dstIndex, index, count); + } } static void hierarchy_close (hierarchy_t *hierarchy, uint32_t index, uint32_t count) { - if (count) { - DARRAY_CLOSE_AT (&hierarchy->transform, index, count); - DARRAY_CLOSE_AT (&hierarchy->entity, index, count); - DARRAY_CLOSE_AT (&hierarchy->childCount, index, count); - DARRAY_CLOSE_AT (&hierarchy->childIndex, index, count); - DARRAY_CLOSE_AT (&hierarchy->parentIndex, index, count); - DARRAY_CLOSE_AT (&hierarchy->name, index, count); - DARRAY_CLOSE_AT (&hierarchy->tag, index, count); - DARRAY_CLOSE_AT (&hierarchy->modified, index, count); - DARRAY_CLOSE_AT (&hierarchy->localMatrix, index, count); - DARRAY_CLOSE_AT (&hierarchy->localInverse, index, count); - DARRAY_CLOSE_AT (&hierarchy->worldMatrix, index, count); - DARRAY_CLOSE_AT (&hierarchy->worldInverse, index, count); - DARRAY_CLOSE_AT (&hierarchy->localRotation, index, count); - DARRAY_CLOSE_AT (&hierarchy->localScale, index, count); - DARRAY_CLOSE_AT (&hierarchy->worldRotation, index, count); - DARRAY_CLOSE_AT (&hierarchy->worldScale, index, count); + if (!count) { + return; + } + hierarchy->num_objects -= count; + uint32_t srcIndex = index + count; + count = hierarchy->num_objects - index; + Component_MoveElements (&transform_component, + hierarchy->transform, index, srcIndex, count); + Component_MoveElements (&entity_component, + hierarchy->entity, index, srcIndex, count); + Component_MoveElements (&childCount_component, + hierarchy->childCount, index, srcIndex, count); + Component_MoveElements (&childIndex_component, + hierarchy->childIndex, index, srcIndex, count); + Component_MoveElements (&parentIndex_component, + hierarchy->parentIndex, index, srcIndex, count); + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + Component_MoveElements (&hierarchy->type->components[i], + hierarchy->components[i], + index, srcIndex, count); } } @@ -192,29 +158,25 @@ static void hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstIndex, uint32_t srcIndex, uint32_t count) { - memcpy (&dst->transform.a[dstIndex], &src->transform.a[srcIndex], - count * sizeof(dst->transform.a[0])); - memset (&src->transform.a[srcIndex], 0, - count * sizeof(dst->transform.a[0])); - memcpy (&dst->entity.a[dstIndex], &src->entity.a[srcIndex], - count * sizeof(dst->entity.a[0])); - memcpy (&dst->name.a[dstIndex], &src->name.a[srcIndex], - count * sizeof(dst->name.a[0])); - memcpy (&dst->tag.a[dstIndex], &src->tag.a[srcIndex], - count * sizeof(dst->tag.a[0])); - memset (&dst->modified.a[dstIndex], 1, count * sizeof(dst->modified.a[0])); - memcpy (&dst->localMatrix.a[dstIndex], &src->localMatrix.a[srcIndex], - count * sizeof(dst->localMatrix.a[0])); - memcpy (&dst->localInverse.a[dstIndex], &src->localInverse.a[srcIndex], - count * sizeof(dst->localInverse.a[0])); - memcpy (&dst->localRotation.a[dstIndex], &src->localRotation.a[srcIndex], - count * sizeof(dst->localRotation.a[0])); - memcpy (&dst->localScale.a[dstIndex], &src->localScale.a[srcIndex], - count * sizeof(dst->localScale.a[0])); + Component_CopyElements (&transform_component, + dst->transform, dstIndex, + src->transform, srcIndex, count); + Component_CopyElements (&entity_component, + dst->entity, dstIndex, + src->entity, srcIndex, count); + // Actually move (as in C++ move semantics) source hierarchy object + // references so that their indices do not get updated when the objects + // are removed from the source hierarcy + memset (&src->transform[srcIndex], 0, count * sizeof(dst->transform[0])); for (uint32_t i = 0; i < count; i++) { - dst->transform.a[dstIndex + i]->hierarchy = dst; - dst->transform.a[dstIndex + i]->index = dstIndex + i; + dst->transform[dstIndex + i]->hierarchy = dst; + dst->transform[dstIndex + i]->index = dstIndex + i; + } + for (uint32_t i = 0; i < dst->type->num_components; i++) { + Component_CopyElements (&dst->type->components[i], + dst->components[i], dstIndex, + src->components[i], srcIndex, count); } } @@ -222,22 +184,17 @@ static void hierarchy_init (hierarchy_t *dst, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t count) { - memset (&dst->transform.a[index], 0, - count * sizeof(dst->transform.a[0])); - memset (&dst->entity.a[index], 0, count * sizeof(dst->entity.a[0])); - memset (&dst->name.a[index], 0, count * sizeof(dst->name.a[0])); - memset (&dst->tag.a[index], 0, count * sizeof(dst->tag.a[0])); - memset (&dst->modified.a[index], 1, count * sizeof(dst->modified.a[0])); + memset (&dst->transform[index], 0, + count * sizeof(dst->transform[0])); for (uint32_t i = 0; i < count; i++) { - mat4fidentity (dst->localMatrix.a[index]); - mat4fidentity (dst->localInverse.a[index]); - dst->localRotation.a[index] = (vec4f_t) { 0, 0, 0, 1 }; - dst->localScale.a[index] = (vec4f_t) { 1, 1, 1, 1 }; - - dst->parentIndex.a[index + i] = parentIndex; - dst->childCount.a[index + i] = 0; - dst->childIndex.a[index + i] = childIndex; + dst->parentIndex[index + i] = parentIndex; + dst->childCount[index + i] = 0; + dst->childIndex[index + i] = childIndex; + } + for (uint32_t i = 0; i < dst->type->num_components; i++) { + Component_CreateElements (&dst->type->components[i], + dst->components[i], index, count); } } @@ -245,34 +202,33 @@ static uint32_t hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstParent, uint32_t srcRoot, uint32_t count) { - uint32_t insertIndex; // where the transforms will be inserted - uint32_t childIndex; // where the transforms' children will inserted + uint32_t insertIndex; // where the objects will be inserted + uint32_t childIndex; // where the objects' children will inserted - // The newly added transforms are always last children of the parent - // transform - insertIndex = dst->childIndex.a[dstParent] + dst->childCount.a[dstParent]; - - // By design, all of a transform's children are in one contiguous block, - // and the blocks of children for each transform are ordered by their - // parents. Thus the child index of each transform increases monotonically + // The newly added objects are always last children of the parent + // object + insertIndex = dst->childIndex[dstParent] + dst->childCount[dstParent]; + // By design, all of a object's children are in one contiguous block, + // and the blocks of children for each object are ordered by their + // parents. Thus the child index of each object increases monotonically // for each child index in the array, regardless of the level of the owning - // transform (higher levels always come before lower levels). + // object (higher levels always come before lower levels). uint32_t neighbor = insertIndex - 1; // insertIndex never zero - childIndex = dst->childIndex.a[neighbor] + dst->childCount.a[neighbor]; + childIndex = dst->childIndex[neighbor] + dst->childCount[neighbor]; - // Any transforms that come after the inserted transforms need to have + // Any objects that come after the inserted objects need to have // thier indices adjusted. hierarchy_UpdateTransformIndices (dst, insertIndex, count); - // The parent transform's child index is not affected, but the child - // indices of all transforms immediately after the parent transform are. + // The parent object's child index is not affected, but the child + // indices of all objects immediately after the parent object are. hierarchy_UpdateChildIndices (dst, dstParent + 1, count); hierarchy_UpdateParentIndices (dst, childIndex, count); - // The beginning of the block of children for the new transforms was - // computed from the pre-insert indices of the related transforms, thus - // the index must be updated by the number of transforms being inserted + // The beginning of the block of children for the new objects was + // computed from the pre-insert indices of the related objects, thus + // the index must be updated by the number of objects being inserted // (it would have been updated thusly if the insert was done before - // updating the indices of the other transforms). + // updating the indices of the other objects). childIndex += count; hierarchy_open (dst, insertIndex, count); @@ -282,12 +238,12 @@ hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, hierarchy_init (dst, insertIndex, dstParent, childIndex, count); } for (uint32_t i = 0; i < count; i++) { - dst->parentIndex.a[insertIndex + i] = dstParent; - dst->childIndex.a[insertIndex + i] = childIndex; - dst->childCount.a[insertIndex + i] = 0; + dst->parentIndex[insertIndex + i] = dstParent; + dst->childIndex[insertIndex + i] = childIndex; + dst->childCount[insertIndex + i] = 0; } - dst->childCount.a[dstParent] += count; + dst->childCount[dstParent] += count; return insertIndex; } @@ -296,8 +252,8 @@ hierarchy_insert_children (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstParent, uint32_t srcRoot) { uint32_t insertIndex; - uint32_t childIndex = src->childIndex.a[srcRoot]; - uint32_t childCount = src->childCount.a[srcRoot]; + uint32_t childIndex = src->childIndex[srcRoot]; + uint32_t childCount = src->childCount[srcRoot]; if (childCount) { insertIndex = hierarchy_insert (dst, src, dstParent, @@ -316,47 +272,46 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, uint32_t insertIndex; if (dstParent == null_transform) { - if (dst->transform.size) { + if (dst->num_objects) { Sys_Error ("attempt to insert root in non-empty hierarchy"); } hierarchy_open (dst, 0, 1); hierarchy_move (dst, src, 0, srcRoot, 1); - dst->parentIndex.a[0] = null_transform; - dst->childIndex.a[0] = 1; - dst->childCount.a[0] = 0; + dst->parentIndex[0] = null_transform; + dst->childIndex[0] = 1; + dst->childCount[0] = 0; insertIndex = 0; } else { - if (!dst->transform.size) { + if (!dst->num_objects) { Sys_Error ("attempt to insert non-root in empty hierarchy"); } insertIndex = hierarchy_insert (dst, src, dstParent, srcRoot, 1); } - // if src is null, then inserting a new transform which has no children + // if src is null, then inserting a new object which has no children if (src) { hierarchy_insert_children (dst, src, insertIndex, srcRoot); } - Hierarchy_UpdateMatrices (dst); return insertIndex; } static void hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) { - uint32_t childIndex = hierarchy->childIndex.a[index]; - uint32_t childCount = hierarchy->childCount.a[index]; - uint32_t parentIndex = hierarchy->parentIndex.a[index]; + uint32_t childIndex = hierarchy->childIndex[index]; + uint32_t childCount = hierarchy->childCount[index]; + uint32_t parentIndex = hierarchy->parentIndex[index]; uint32_t nieceIndex = null_transform; if (parentIndex != null_transform) { - uint32_t siblingIndex = hierarchy->childIndex.a[parentIndex]; - siblingIndex += hierarchy->childCount.a[parentIndex] - 1; - nieceIndex = hierarchy->childIndex.a[siblingIndex]; + uint32_t siblingIndex = hierarchy->childIndex[parentIndex]; + siblingIndex += hierarchy->childCount[parentIndex] - 1; + nieceIndex = hierarchy->childIndex[siblingIndex]; } for (uint32_t i = childCount; i-- > 0; ) { hierarchy_remove_children (hierarchy, childIndex + i); } hierarchy_close (hierarchy, childIndex, childCount); - hierarchy->childCount.a[index] = 0; + hierarchy->childCount[index] = 0; if (childCount) { hierarchy_UpdateTransformIndices (hierarchy, childIndex, -childCount); @@ -370,11 +325,11 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) { - uint32_t parentIndex = hierarchy->parentIndex.a[index]; - uint32_t childIndex = hierarchy->childIndex.a[index]; + uint32_t parentIndex = hierarchy->parentIndex[index]; + uint32_t childIndex = hierarchy->childIndex[index]; uint32_t siblingIndex = null_transform; if (parentIndex != null_transform) { - siblingIndex = hierarchy->childIndex.a[parentIndex]; + siblingIndex = hierarchy->childIndex[parentIndex]; } hierarchy_remove_children (hierarchy, index); hierarchy_close (hierarchy, index, 1); @@ -386,10 +341,10 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) } hierarchy_t * -Hierarchy_New (scene_t *scene, int createRoot) +Hierarchy_New (scene_t *scene, const hierarchy_type_t *type, int createRoot) { scene_resources_t *res = scene->resources; - hierarchy_t *hierarchy = PR_RESNEW_NC (res->hierarchies); + hierarchy_t *hierarchy = PR_RESNEW (res->hierarchies); hierarchy->scene = scene; hierarchy->prev = &scene->hierarchies; @@ -399,23 +354,9 @@ Hierarchy_New (scene_t *scene, int createRoot) } scene->hierarchies = hierarchy; - size_t grow = 16; - DARRAY_INIT (&hierarchy->transform, grow); - DARRAY_INIT (&hierarchy->entity, grow); - DARRAY_INIT (&hierarchy->childCount, grow); - DARRAY_INIT (&hierarchy->childIndex, grow); - DARRAY_INIT (&hierarchy->parentIndex, grow); - DARRAY_INIT (&hierarchy->name, grow); - DARRAY_INIT (&hierarchy->tag, grow); - DARRAY_INIT (&hierarchy->modified, grow); - DARRAY_INIT (&hierarchy->localMatrix, grow); - DARRAY_INIT (&hierarchy->localInverse, grow); - DARRAY_INIT (&hierarchy->worldMatrix, grow); - DARRAY_INIT (&hierarchy->worldInverse, grow); - DARRAY_INIT (&hierarchy->localRotation, grow); - DARRAY_INIT (&hierarchy->localScale, grow); - DARRAY_INIT (&hierarchy->worldRotation, grow); - DARRAY_INIT (&hierarchy->worldScale, grow); + hierarchy->type = type; + hierarchy->components = calloc (hierarchy->type->num_components, + sizeof (void *)); if (createRoot) { hierarchy_open (hierarchy, 0, 1); @@ -434,131 +375,47 @@ Hierarchy_Delete (hierarchy_t *hierarchy) *hierarchy->prev = hierarchy->next; scene_resources_t *res = hierarchy->scene->resources; - for (size_t i = 0; i < hierarchy->transform.size; i++) { - PR_RESFREE (res->transforms, hierarchy->transform.a[i]); + for (uint32_t i = 0; i < hierarchy->num_objects; i++) { + PR_RESFREE (res->transforms, hierarchy->transform[i]); } - DARRAY_CLEAR (&hierarchy->transform); - DARRAY_CLEAR (&hierarchy->entity); - DARRAY_CLEAR (&hierarchy->childCount); - DARRAY_CLEAR (&hierarchy->childIndex); - DARRAY_CLEAR (&hierarchy->parentIndex); - DARRAY_CLEAR (&hierarchy->name); - DARRAY_CLEAR (&hierarchy->tag); - DARRAY_CLEAR (&hierarchy->modified); - DARRAY_CLEAR (&hierarchy->localMatrix); - DARRAY_CLEAR (&hierarchy->localInverse); - DARRAY_CLEAR (&hierarchy->worldMatrix); - DARRAY_CLEAR (&hierarchy->worldInverse); - DARRAY_CLEAR (&hierarchy->localRotation); - DARRAY_CLEAR (&hierarchy->localScale); - DARRAY_CLEAR (&hierarchy->worldRotation); - DARRAY_CLEAR (&hierarchy->worldScale); + free (hierarchy->transform); + free (hierarchy->childCount); + free (hierarchy->childIndex); + free (hierarchy->parentIndex); + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + free (hierarchy->components[i]); + } + free (hierarchy->components); + PR_RESFREE (res->hierarchies, hierarchy); } -void -Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count) -{ - size_t size = hierarchy->transform.size; - - DARRAY_RESIZE (&hierarchy->transform, size + count); - DARRAY_RESIZE (&hierarchy->entity, size + count); - DARRAY_RESIZE (&hierarchy->childCount, size + count); - DARRAY_RESIZE (&hierarchy->childIndex, size + count); - DARRAY_RESIZE (&hierarchy->parentIndex, size + count); - DARRAY_RESIZE (&hierarchy->name, size + count); - DARRAY_RESIZE (&hierarchy->tag, size + count); - DARRAY_RESIZE (&hierarchy->modified, size + count); - DARRAY_RESIZE (&hierarchy->localMatrix, size + count); - DARRAY_RESIZE (&hierarchy->localInverse, size + count); - DARRAY_RESIZE (&hierarchy->worldMatrix, size + count); - DARRAY_RESIZE (&hierarchy->worldInverse, size + count); - DARRAY_RESIZE (&hierarchy->localRotation, size + count); - DARRAY_RESIZE (&hierarchy->localScale, size + count); - DARRAY_RESIZE (&hierarchy->worldRotation, size + count); - DARRAY_RESIZE (&hierarchy->worldScale, size + count); - - DARRAY_RESIZE (&hierarchy->transform, size); - DARRAY_RESIZE (&hierarchy->entity, size); - DARRAY_RESIZE (&hierarchy->childCount, size); - DARRAY_RESIZE (&hierarchy->childIndex, size); - DARRAY_RESIZE (&hierarchy->parentIndex, size); - DARRAY_RESIZE (&hierarchy->name, size); - DARRAY_RESIZE (&hierarchy->tag, size); - DARRAY_RESIZE (&hierarchy->modified, size); - DARRAY_RESIZE (&hierarchy->localMatrix, size); - DARRAY_RESIZE (&hierarchy->localInverse, size); - DARRAY_RESIZE (&hierarchy->worldMatrix, size); - DARRAY_RESIZE (&hierarchy->worldInverse, size); - DARRAY_RESIZE (&hierarchy->localRotation, size); - DARRAY_RESIZE (&hierarchy->localScale, size); - DARRAY_RESIZE (&hierarchy->worldRotation, size); - DARRAY_RESIZE (&hierarchy->worldScale, size); -} - hierarchy_t * Hierarchy_Copy (scene_t *scene, const hierarchy_t *src) { - hierarchy_t *dst = Hierarchy_New (scene, 0); - size_t count = src->transform.size; + hierarchy_t *dst = Hierarchy_New (scene, src->type, 0); + size_t count = src->num_objects; - DARRAY_RESIZE (&dst->transform, count); - DARRAY_RESIZE (&dst->entity, count); - DARRAY_RESIZE (&dst->childCount, count); - DARRAY_RESIZE (&dst->childIndex, count); - DARRAY_RESIZE (&dst->parentIndex, count); - DARRAY_RESIZE (&dst->name, count); - DARRAY_RESIZE (&dst->tag, count); - DARRAY_RESIZE (&dst->modified, count); - DARRAY_RESIZE (&dst->localMatrix, count); - DARRAY_RESIZE (&dst->localInverse, count); - DARRAY_RESIZE (&dst->worldMatrix, count); - DARRAY_RESIZE (&dst->worldInverse, count); - DARRAY_RESIZE (&dst->localRotation, count); - DARRAY_RESIZE (&dst->localScale, count); - DARRAY_RESIZE (&dst->worldRotation, count); - DARRAY_RESIZE (&dst->worldScale, count); + Hierarchy_Reserve (dst, count); for (size_t i = 0; i < count; i++) { - dst->transform.a[i] = __transform_alloc (scene); - dst->transform.a[i]->hierarchy = dst; - dst->transform.a[i]->index = i; + dst->transform[i] = __transform_alloc (scene); + dst->transform[i]->hierarchy = dst; + dst->transform[i]->index = i; } - for (size_t i = 0; i < count; i++) { - dst->entity.a[i] = 0; // FIXME clone entity + + Component_CopyElements (&childCount_component, + dst->childCount, 0, src->childCount, 0, count); + Component_CopyElements (&childIndex_component, + dst->childIndex, 0, src->childIndex, 0, count); + Component_CopyElements (&parentIndex_component, + dst->parentIndex, 0, src->parentIndex, 0, count); + for (uint32_t i = 0; i < dst->type->num_components; i++) { + Component_CopyElements (&dst->type->components[i], + dst->components[i], 0, + src->components[i], 0, count); } - memcpy (dst->childCount.a, src->childCount.a, - count * sizeof(dst->childCount.a[0])); - memcpy (dst->childIndex.a, src->childIndex.a, - count * sizeof(dst->childIndex.a[0])); - memcpy (dst->parentIndex.a, src->parentIndex.a, - count * sizeof(dst->parentIndex.a[0])); - for (size_t i = 0; i < count; i++) { - // use the transform code so string allocation remains consistent - // regardless how it changes. - Transform_SetName (dst->transform.a[i], src->name.a[i]); - } - memcpy (dst->tag.a, src->tag.a, - count * sizeof(dst->tag.a[0])); - memcpy (dst->modified.a, src->modified.a, - count * sizeof(dst->modified.a[0])); - memcpy (dst->localMatrix.a, src->localMatrix.a, - count * sizeof(dst->localMatrix.a[0])); - memcpy (dst->localInverse.a, src->localInverse.a, - count * sizeof(dst->localInverse.a[0])); - memcpy (dst->worldMatrix.a, src->worldMatrix.a, - count * sizeof(dst->worldMatrix.a[0])); - memcpy (dst->worldInverse.a, src->worldInverse.a, - count * sizeof(dst->worldInverse.a[0])); - memcpy (dst->localRotation.a, src->localRotation.a, - count * sizeof(dst->localRotation.a[0])); - memcpy (dst->localScale.a, src->localScale.a, - count * sizeof(dst->localScale.a[0])); - memcpy (dst->worldRotation.a, src->worldRotation.a, - count * sizeof(dst->worldRotation.a[0])); - memcpy (dst->worldScale.a, src->worldScale.a, - count * sizeof(dst->localScale.a[0])); - // Just in case the source hierarchy has modified transforms - Hierarchy_UpdateMatrices (dst); + // Just in case the source hierarchy has modified objects + //Hierarchy_UpdateMatrices (dst); return dst; } diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 09f2d16bb..215eb7b5e 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -141,7 +141,7 @@ Scene_CreateEntity (scene_t *scene) ent->id = PR_RESINDEX (res->entities, ent); hierarchy_t *h = ent->transform->hierarchy; - h->entity.a[ent->transform->index] = ent; + h->entity[ent->transform->index] = ent; QuatSet (1, 1, 1, 1, ent->renderer.colormod); @@ -165,8 +165,8 @@ destroy_entity (scene_t *scene, entity_t *ent) // Transform_Delete takes care of all hierarchy stuff (transforms // themselves, name strings, hierarchy table) hierarchy_t *h = transform->hierarchy; - for (size_t i = 0; i < h->entity.size; i++) { - entity_t *e = h->entity.a[0]; + for (size_t i = 0; i < h->num_objects; i++) { + entity_t *e = h->entity[0]; e->transform = 0; PR_RESFREE (res->entities, ent); } @@ -193,7 +193,7 @@ Scene_FreeAllEntities (scene_t *scene) while (scene->hierarchies) { hierarchy_t *h = scene->hierarchies; // deleting the root entity deletes all child entities - entity_t *ent = h->entity.a[0]; + entity_t *ent = h->entity[0]; destroy_entity (scene, ent); } scene_resources_t *res = scene->resources; diff --git a/libs/scene/test/test-hierarchy.c b/libs/scene/test/test-hierarchy.c index c8adb529e..47fdf0814 100644 --- a/libs/scene/test/test-hierarchy.c +++ b/libs/scene/test/test-hierarchy.c @@ -43,30 +43,15 @@ mat4_equal (const mat4f_t a, const mat4f_t b) static int check_hierarchy_size (hierarchy_t *h, uint32_t size) { - if (h->transform.size != size - || h->entity.size != size - || h->childCount.size != size - || h->childIndex.size != size - || h->parentIndex.size != size - || h->name.size != size - || h->tag.size != size - || h->modified.size != size - || h->localMatrix.size != size - || h->localInverse.size != size - || h->worldMatrix.size != size - || h->worldInverse.size != size - || h->localRotation.size != size - || h->localScale.size != size - || h->worldRotation.size != size - || h->worldScale.size != size) { - printf ("hierarchy does not have exactly %u" - " transform or array sizes are inconsistent\n", size); + if (h->num_objects != size) { + printf ("hierarchy does not have exactly %u transform\n", size); return 0; } - for (size_t i = 0; i < h->transform.size; i++) { - if (h->transform.a[i]->hierarchy != h) { - printf ("transform %zd (%s) does not point to hierarchy\n", - i, h->name.a[i]); + char **name = h->components[transform_type_name]; + for (uint32_t i = 0; i < h->num_objects; i++) { + if (h->transform[i]->hierarchy != h) { + printf ("transform %d (%s) does not point to hierarchy\n", + i, name[i]); } } return 1; @@ -75,10 +60,11 @@ check_hierarchy_size (hierarchy_t *h, uint32_t size) static void dump_hierarchy (hierarchy_t *h) { - for (size_t i = 0; i < h->transform.size; i++) { - printf ("%2zd: %5s %2u %2u %2u %2u\n", i, h->name.a[i], - h->transform.a[i]->index, h->parentIndex.a[i], - h->childIndex.a[i], h->childCount.a[i]); + char **name = h->components[transform_type_name]; + for (uint32_t i = 0; i < h->num_objects; i++) { + printf ("%2d: %5s %2u %2u %2u %2u\n", i, name[i], + h->transform[i]->index, h->parentIndex[i], + h->childIndex[i], h->childCount[i]); } puts (""); } @@ -88,25 +74,26 @@ check_indices (transform_t *transform, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t childCount) { hierarchy_t *h = transform->hierarchy; + char **name = h->components[transform_type_name]; if (transform->index != index) { printf ("%s/%s index incorrect: expect %u got %u\n", - h->name.a[transform->index], h->name.a[index], + name[transform->index], name[index], index, transform->index); return 0; } - if (h->parentIndex.a[index] != parentIndex) { + if (h->parentIndex[index] != parentIndex) { printf ("%s parent index incorrect: expect %u got %u\n", - h->name.a[index], parentIndex, h->parentIndex.a[index]); + name[index], parentIndex, h->parentIndex[index]); return 0; } - if (h->childIndex.a[index] != childIndex) { + if (h->childIndex[index] != childIndex) { printf ("%s child index incorrect: expect %u got %u\n", - h->name.a[index], childIndex, h->childIndex.a[index]); + name[index], childIndex, h->childIndex[index]); return 0; } - if (h->childCount.a[index] != childCount) { + if (h->childCount[index] != childCount) { printf ("%s child count incorrect: expect %u got %u\n", - h->name.a[index], childCount, h->childCount.a[index]); + name[index], childCount, h->childCount[index]); return 0; } return 1; @@ -126,19 +113,25 @@ test_single_transform (void) printf ("New transform has no hierarchy\n"); return 1; } + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; if (!check_hierarchy_size (h, 1)) { return 1; } if (!check_indices (transform, 0, null_transform, 1, 0)) { return 1; } - if (!mat4_equal (h->localMatrix.a[0], identity) - || !mat4_equal (h->localInverse.a[0], identity) - || !mat4_equal (h->worldMatrix.a[0], identity) - || !mat4_equal (h->worldInverse.a[0], identity)) { + if (!mat4_equal (localMatrix[0], identity) + || !mat4_equal (localInverse[0], identity) + || !mat4_equal (worldMatrix[0], identity) + || !mat4_equal (worldInverse[0], identity)) { printf ("New transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[0], identity[3]) - || !vec4_equal (h->localScale.a[0], one)) { + if (!vec4_equal (localRotation[0], identity[3]) + || !vec4_equal (localScale[0], one)) { printf ("New transform rotation or scale not identity\n"); return 1; } @@ -166,30 +159,36 @@ test_parent_child_init (void) if (!check_indices (child, 1, 0, 2, 0)) { return 1; } hierarchy_t *h = parent->hierarchy; - if (!mat4_equal (h->localMatrix.a[0], identity) - || !mat4_equal (h->localInverse.a[0], identity) - || !mat4_equal (h->worldMatrix.a[0], identity) - || !mat4_equal (h->worldInverse.a[0], identity)) { + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + if (!mat4_equal (localMatrix[0], identity) + || !mat4_equal (localInverse[0], identity) + || !mat4_equal (worldMatrix[0], identity) + || !mat4_equal (worldInverse[0], identity)) { printf ("Parent transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[0], identity[3]) - || !vec4_equal (h->localScale.a[0], one)) { + if (!vec4_equal (localRotation[0], identity[3]) + || !vec4_equal (localScale[0], one)) { printf ("Parent transform rotation or scale not identity\n"); return 1; } - if (!mat4_equal (h->localMatrix.a[1], identity) - || !mat4_equal (h->localInverse.a[1], identity) - || !mat4_equal (h->worldMatrix.a[1], identity) - || !mat4_equal (h->worldInverse.a[1], identity)) { + if (!mat4_equal (localMatrix[1], identity) + || !mat4_equal (localInverse[1], identity) + || !mat4_equal (worldMatrix[1], identity) + || !mat4_equal (worldInverse[1], identity)) { printf ("Child transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[1], identity[3]) - || !vec4_equal (h->localScale.a[1], one)) { + if (!vec4_equal (localRotation[1], identity[3]) + || !vec4_equal (localScale[1], one)) { printf ("Child transform rotation or scale not identity\n"); return 1; } @@ -231,30 +230,36 @@ test_parent_child_setparent (void) if (!check_indices (child, 1, 0, 2, 0)) { return 1; } hierarchy_t *h = parent->hierarchy; - if (!mat4_equal (h->localMatrix.a[0], identity) - || !mat4_equal (h->localInverse.a[0], identity) - || !mat4_equal (h->worldMatrix.a[0], identity) - || !mat4_equal (h->worldInverse.a[0], identity)) { + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + if (!mat4_equal (localMatrix[0], identity) + || !mat4_equal (localInverse[0], identity) + || !mat4_equal (worldMatrix[0], identity) + || !mat4_equal (worldInverse[0], identity)) { printf ("Parent transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[0], identity[3]) - || !vec4_equal (h->localScale.a[0], one)) { + if (!vec4_equal (localRotation[0], identity[3]) + || !vec4_equal (localScale[0], one)) { printf ("Parent transform rotation or scale not identity\n"); return 1; } - if (!mat4_equal (h->localMatrix.a[1], identity) - || !mat4_equal (h->localInverse.a[1], identity) - || !mat4_equal (h->worldMatrix.a[1], identity) - || !mat4_equal (h->worldInverse.a[1], identity)) { + if (!mat4_equal (localMatrix[1], identity) + || !mat4_equal (localInverse[1], identity) + || !mat4_equal (worldMatrix[1], identity) + || !mat4_equal (worldInverse[1], identity)) { printf ("Child transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[1], identity[3]) - || !vec4_equal (h->localScale.a[1], one)) { + if (!vec4_equal (localRotation[1], identity[3]) + || !vec4_equal (localScale[1], one)) { printf ("Child transform rotation or scale not identity\n"); return 1; } @@ -530,65 +535,70 @@ test_frames (void) Transform_SetLocalRotation (B1, (vec4f_t) { -0.5, 0.5, -0.5, 0.5 }); hierarchy_t *h = root->hierarchy; - for (size_t i = 0; i < h->transform.size; i++) { + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + char **name = h->components[transform_type_name]; + for (uint32_t i = 0; i < h->num_objects; i++) { mat4f_t res; - mmulf (res, h->localMatrix.a[i], h->localInverse.a[i]); + mmulf (res, localMatrix[i], localInverse[i]); if (!mat4_equal (res, identity)) { printf ("%s: localInverse not inverse of localMatrix\n", - h->name.a[i]); - printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 3)); - printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 3)); + name[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 3)); printf ("r: " VEC4F_FMT "\n", MAT4_ROW(res, 0)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 1)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 2)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 3)); return 1; } - puts (h->name.a[i]); - printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 3)); - printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 3)); + puts (name[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 3)); } - for (size_t i = 0; i < h->transform.size; i++) { + for (uint32_t i = 0; i < h->num_objects; i++) { mat4f_t res; - mmulf (res, h->worldMatrix.a[i], h->worldInverse.a[i]); + mmulf (res, worldMatrix[i], worldInverse[i]); if (!mat4_equal (res, identity)) { printf ("%s: worldInverse not inverse of worldMatrix\n", - h->name.a[i]); - printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 3)); - printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 3)); + name[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 3)); printf ("r: " VEC4F_FMT "\n", MAT4_ROW(res, 0)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 1)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 2)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 3)); return 1; } - puts (h->name.a[i]); - printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 3)); - printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 3)); + puts (name[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 3)); } if (!check_vector (root, Transform_GetLocalPosition, diff --git a/libs/scene/transform.c b/libs/scene/transform.c index 7048536de..82ad54557 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -37,12 +37,102 @@ #define IMPLEMENT_TRANSFORM_Funcs +#include "QF/scene/component.h" #include "QF/scene/hierarchy.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "scn_internal.h" +static void +transform_mat4f_identity (void *_mat) +{ + vec4f_t *mat = _mat; + mat4fidentity (mat); +} + +static void +transform_rotation_identity (void *_rot) +{ + vec4f_t *rot = _rot; + *rot = (vec4f_t) { 0, 0, 0, 1 }; +} + +static void +transform_scale_identity (void *_scale) +{ + vec4f_t *scale = _scale; + *scale = (vec4f_t) { 1, 1, 1, 1 }; +} + +static void +transform_modified_init (void *_modified) +{ + byte *modified = _modified; + *modified = 1; +} + +static const component_t transform_components[transform_type_count] = { + [transform_type_name] = { + .size = sizeof (char *), + .name = "Name", + }, + [transform_type_tag] = { + .size = sizeof (uint32_t), + .name = "Tag", + }, + [transform_type_modified] = { + .size = sizeof (byte), + .create = transform_modified_init, + .name = "Modified", + }, + [transform_type_localMatrix] = { + .size = sizeof (mat4f_t), + .create = transform_mat4f_identity, + .name = "Local Matrix", + }, + [transform_type_localInverse] = { + .size = sizeof (mat4f_t), + .create = transform_mat4f_identity, + .name = "Local Inverse", + }, + [transform_type_worldMatrix] = { + .size = sizeof (mat4f_t), + .create = transform_mat4f_identity, + .name = "World Matrix", + }, + [transform_type_worldInverse] = { + .size = sizeof (mat4f_t), + .create = transform_mat4f_identity, + .name = "World Inverse", + }, + [transform_type_localRotation] = { + .size = sizeof (vec4f_t), + .create = transform_rotation_identity, + .name = "Local Rotation", + }, + [transform_type_localScale] = { + .size = sizeof (vec4f_t), + .create = transform_scale_identity, + .name = "Local Scale", + }, + [transform_type_worldRotation] = { + .size = sizeof (vec4f_t), + .create = transform_rotation_identity, + .name = "World Rotation", + }, + [transform_type_worldScale] = { + .size = sizeof (vec4f_t), + .create = transform_scale_identity, + .name = "World Scale", + }, +}; + +static const hierarchy_type_t transform_type = { + .num_components = transform_type_count, + .components = transform_components, +}; + transform_t * __transform_alloc (scene_t *scene) { @@ -55,6 +145,93 @@ __transform_alloc (scene_t *scene) return transform; } +static void +transform_calcLocalInverse (hierarchy_t *h, uint32_t index) +{ + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + // This takes advantage of the fact that localMatrix is a simple + // homogenous scale/rotate/translate matrix with no shear + vec4f_t x = localMatrix[index][0]; + vec4f_t y = localMatrix[index][1]; + vec4f_t z = localMatrix[index][2]; + vec4f_t t = localMatrix[index][3]; + + // "one" is to ensure both the scalar and translation have 1 in their + // fourth components + vec4f_t one = { 0, 0, 0, 1 }; + vec4f_t nx = { x[0], y[0], z[0], 0 }; + vec4f_t ny = { x[1], y[1], z[1], 0 }; + vec4f_t nz = { x[2], y[2], z[2], 0 }; + vec4f_t nt = one - t[0] * nx - t[1] * ny - t[2] * nz; + // vertical dot product!!! + vec4f_t s = 1 / (nx * nx + ny * ny + nz * nz + one); + localInverse[index][0] = nx * s; + localInverse[index][1] = ny * s; + localInverse[index][2] = nz * s; + localInverse[index][3] = nt * s; +} + +static void +Transform_UpdateMatrices (hierarchy_t *h) +{ + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + vec4f_t *worldRotation = h->components[transform_type_worldRotation]; + vec4f_t *worldScale = h->components[transform_type_worldScale]; + byte *modified = h->components[transform_type_modified]; + + for (uint32_t i = 0; i < h->num_objects; i++) { + if (modified[i]) { + transform_calcLocalInverse (h, i); + } + } + if (modified[0]) { + memcpy (worldMatrix[0], + localMatrix[0], sizeof (mat4_t)); + memcpy (worldInverse[0], + localInverse[0], sizeof (mat4_t)); + worldRotation[0] = localRotation[0]; + worldScale[0] = localScale[0]; + } + for (size_t i = 1; i < h->num_objects; i++) { + uint32_t parent = h->parentIndex[i]; + + if (modified[i] || modified[parent]) { + mmulf (worldMatrix[i], + worldMatrix[parent], localMatrix[i]); + modified[i] = 1; + } + } + for (size_t i = 1; i < h->num_objects; i++) { + uint32_t parent = h->parentIndex[i]; + + if (modified[i] || modified[parent]) { + mmulf (worldInverse[i], + localInverse[i], worldInverse[parent]); + } + } + for (size_t i = 1; i < h->num_objects; i++) { + uint32_t parent = h->parentIndex[i]; + if (modified[i] || modified[parent]) { + worldRotation[i] = qmulf (worldRotation[parent], + localRotation[i]); + } + } + for (size_t i = 1; i < h->num_objects; i++) { + uint32_t parent = h->parentIndex[i]; + if (modified[i] || modified[parent]) { + worldScale[i] = m3vmulf (worldMatrix[parent], + localScale[i]); + } + } + memset (modified, 0, h->num_objects); +} + transform_t * Transform_New (scene_t *scene, transform_t *parent) { @@ -65,11 +242,11 @@ Transform_New (scene_t *scene, transform_t *parent) transform->index = Hierarchy_InsertHierarchy (parent->hierarchy, 0, parent->index, 0); } else { - transform->hierarchy = Hierarchy_New (scene, 1); + transform->hierarchy = Hierarchy_New (scene, &transform_type, 1); transform->index = 0; } - transform->hierarchy->transform.a[transform->index] = transform; - Hierarchy_UpdateMatrices (transform->hierarchy); + transform->hierarchy->transform[transform->index] = transform; + Transform_UpdateMatrices (transform->hierarchy); return transform; } @@ -102,7 +279,7 @@ Transform_SetParent (transform_t *transform, transform_t *parent) Hierarchy_InsertHierarchy (parent->hierarchy, hierarchy, parent->index, index); Hierarchy_RemoveHierarchy (hierarchy, index); - if (!hierarchy->name.size) { + if (!hierarchy->num_objects) { Hierarchy_Delete (hierarchy); } } else { @@ -114,72 +291,89 @@ Transform_SetParent (transform_t *transform, transform_t *parent) hierarchy_t *hierarchy = transform->hierarchy; uint32_t index = transform->index; - hierarchy_t *new_hierarchy = Hierarchy_New (transform->scene, 0); + hierarchy_t *new_hierarchy = Hierarchy_New (transform->scene, + &transform_type, 0); Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, null_transform, index); Hierarchy_RemoveHierarchy (hierarchy, index); } + hierarchy_t *h = transform->hierarchy; + byte *modified = h->components[transform_type_modified]; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); } void -Transform_SetName (transform_t *transform, const char *name) +Transform_SetName (transform_t *transform, const char *_name) { hierarchy_t *h = transform->hierarchy; + char **name = h->components[transform_type_name]; //FIXME create a string pool (similar to qfcc's, or even move that to util) - if (h->name.a[transform->index]) { - free (h->name.a[transform->index]); + if (name[transform->index]) { + free (name[transform->index]); } - h->name.a[transform->index] = strdup (name); + name[transform->index] = strdup (_name); } void -Transform_SetTag (transform_t *transform, uint32_t tag) +Transform_SetTag (transform_t *transform, uint32_t _tag) { hierarchy_t *h = transform->hierarchy; - h->tag.a[transform->index] = tag; + uint32_t *tag = h->components[transform_type_tag]; + tag[transform->index] = _tag; } void Transform_SetLocalPosition (transform_t *transform, vec4f_t position) { hierarchy_t *h = transform->hierarchy; - h->localMatrix.a[transform->index][3] = position; - h->modified.a[transform->index] = 1; - Hierarchy_UpdateMatrices (h); + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + byte *modified = h->components[transform_type_modified]; + localMatrix[transform->index][3] = position; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); } void Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation) { hierarchy_t *h = transform->hierarchy; - vec4f_t scale = h->localScale.a[transform->index]; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + byte *modified = h->components[transform_type_modified]; + vec4f_t scale = localScale[transform->index]; mat4f_t mat; mat4fquat (mat, rotation); - h->localRotation.a[transform->index] = rotation; - h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; - h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; - h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; - h->modified.a[transform->index] = 1; - Hierarchy_UpdateMatrices (h); + localRotation[transform->index] = rotation; + localMatrix[transform->index][0] = mat[0] * scale[0]; + localMatrix[transform->index][1] = mat[1] * scale[1]; + localMatrix[transform->index][2] = mat[2] * scale[2]; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); } void Transform_SetLocalScale (transform_t *transform, vec4f_t scale) { hierarchy_t *h = transform->hierarchy; - vec4f_t rotation = h->localRotation.a[transform->index]; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + byte *modified = h->components[transform_type_modified]; + vec4f_t rotation = localRotation[transform->index]; mat4f_t mat; mat4fquat (mat, rotation); - h->localScale.a[transform->index] = scale; - h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; - h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; - h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; - h->modified.a[transform->index] = 1; - Hierarchy_UpdateMatrices (h); + localScale[transform->index] = scale; + localMatrix[transform->index][0] = mat[0] * scale[0]; + localMatrix[transform->index][1] = mat[1] * scale[1]; + localMatrix[transform->index][2] = mat[2] * scale[2]; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); } void @@ -187,8 +381,9 @@ Transform_SetWorldPosition (transform_t *transform, vec4f_t position) { if (transform->index) { hierarchy_t *h = transform->hierarchy; - uint32_t parent = h->parentIndex.a[transform->index]; - position = mvmulf (h->worldInverse.a[parent], position); + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + uint32_t parent = h->parentIndex[transform->index]; + position = mvmulf (worldInverse[parent], position); } Transform_SetLocalPosition (transform, position); } @@ -198,8 +393,9 @@ Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation) { if (transform->index) { hierarchy_t *h = transform->hierarchy; - uint32_t parent = h->parentIndex.a[transform->index]; - rotation = qmulf (qconjf (h->worldRotation.a[parent]), rotation); + vec4f_t *worldRotation = h->components[transform_type_worldRotation]; + uint32_t parent = h->parentIndex[transform->index]; + rotation = qmulf (qconjf (worldRotation[parent]), rotation); } Transform_SetLocalRotation (transform, rotation); } @@ -209,16 +405,20 @@ Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, vec4f_t rotation, vec4f_t position) { hierarchy_t *h = transform->hierarchy; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + byte *modified = h->components[transform_type_modified]; mat4f_t mat; mat4fquat (mat, rotation); position[3] = 1; - h->localRotation.a[transform->index] = rotation; - h->localScale.a[transform->index] = scale; - h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; - h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; - h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; - h->localMatrix.a[transform->index][3] = position; - h->modified.a[transform->index] = 1; - Hierarchy_UpdateMatrices (h); + localRotation[transform->index] = rotation; + localScale[transform->index] = scale; + localMatrix[transform->index][0] = mat[0] * scale[0]; + localMatrix[transform->index][1] = mat[1] * scale[1]; + localMatrix[transform->index][2] = mat[2] * scale[2]; + localMatrix[transform->index][3] = position; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); } From 2c59a400e490154b9f266fe8631cce4d3ccc034e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 14 Oct 2022 19:36:21 +0900 Subject: [PATCH 3071/3664] [vulkan] Ensure memory size is aligned While the base of a memory object was aligned when calculating the memory block size, the top end was not, which could result in the memory block not getting enough bytes allocated to satisfy alignment requirements (eg, for flushing). While fixing that, I noticed the offsets of objects were not being aligned when binding, so that is fixed as well. Fixes Mr Fixit on my VersaPro. --- libs/video/renderer/vulkan/resource.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index 45906199d..90451e5ef 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -110,7 +110,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) resource->name, obj->name, obj->type); } size = QFV_NextOffset (size, &req); - size += req.size; + size += QFV_NextOffset (req.size, &req); } VkMemoryPropertyFlags properties = resource->memory_properties; for (uint32_t type = 0; type < memprops->memoryTypeCount; type++) { @@ -178,7 +178,8 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) case qfv_res_image_view: break; } - offset += req.size; + offset = QFV_NextOffset (offset, &req); + offset += QFV_NextOffset (req.size, &req); } for (unsigned i = 0; i < resource->num_objects; i++) { From 2c9da25e17a875c6ff7ed6bdf9bb0e718ac25607 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Oct 2022 14:40:29 +0900 Subject: [PATCH 3072/3664] Clean up some FIXMEs and XXXs They seemed to be generally unnecessary. Also fixes some typos in related comments. --- include/QF/GL/qf_textures.h | 2 -- include/QF/GLSL/qf_textures.h | 2 -- include/QF/plugin.h | 2 -- libs/models/test/testclip.c | 2 +- libs/models/test/testcontents.c | 2 +- nq/source/cl_screen.c | 3 --- nq/source/game.c | 2 ++ qw/source/cl_screen.c | 3 --- 8 files changed, 4 insertions(+), 14 deletions(-) diff --git a/include/QF/GL/qf_textures.h b/include/QF/GL/qf_textures.h index 7c8b45f53..ea5a8c9ac 100644 --- a/include/QF/GL/qf_textures.h +++ b/include/QF/GL/qf_textures.h @@ -59,9 +59,7 @@ scrap_t *GL_CreateScrap (int size, int format, int linear); void GL_DestroyScrap (scrap_t *scrap); void GL_ScrapClear (scrap_t *scrap); int GL_ScrapTexture (scrap_t *scrap) __attribute__((pure)); -//XXX slow! struct subpic_s *GL_ScrapSubpic (scrap_t *scrap, int width, int height); -//XXX slow! void GL_SubpicDelete (struct subpic_s *subpic); void GL_SubpicUpdate (struct subpic_s *subpic, byte *data, int batch); void GL_ScrapFlush (scrap_t *scrap); diff --git a/include/QF/GLSL/qf_textures.h b/include/QF/GLSL/qf_textures.h index 3a5f0b8b7..946d4d0c9 100644 --- a/include/QF/GLSL/qf_textures.h +++ b/include/QF/GLSL/qf_textures.h @@ -47,9 +47,7 @@ scrap_t *GLSL_CreateScrap (int size, int format, int linear); void GLSL_DestroyScrap (scrap_t *scrap); void GLSL_ScrapClear (scrap_t *scrap); int GLSL_ScrapTexture (scrap_t *scrap) __attribute__((pure)); -//XXX slow! struct subpic_s *GLSL_ScrapSubpic (scrap_t *scrap, int width, int height); -//XXX slow! void GLSL_SubpicDelete (struct subpic_s *subpic); void GLSL_SubpicUpdate (struct subpic_s *subpic, byte *data, int batch); void GLSL_ScrapFlush (scrap_t *scrap); diff --git a/include/QF/plugin.h b/include/QF/plugin.h index 2b73cccc2..e5fee9fa9 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -108,8 +108,6 @@ qboolean PI_UnloadPlugin (plugin_t *); void PI_RegisterPlugins (plugin_list_t *); void PI_Init (void); -// FIXME: we need a generic function to initialize unused fields - ///@} #endif//__QF_plugin_h diff --git a/libs/models/test/testclip.c b/libs/models/test/testclip.c index f0f774c1e..a5738f015 100644 --- a/libs/models/test/testclip.c +++ b/libs/models/test/testclip.c @@ -218,7 +218,7 @@ do_trace (box_t *box, hull_t *hull, vec3_t start, vec3_t end) trace.inwater = false; trace.fraction = 1; VectorCopy (box->extents, trace.extents); - // FIXME specify tract type in test spec + // FIXME specify trace type in test spec trace.type = box == &point ? tr_point : tr_box; VectorCopy (end, trace.endpos); MOD_TraceLine (hull, 0, start, end, &trace); diff --git a/libs/models/test/testcontents.c b/libs/models/test/testcontents.c index 17b20f3ae..7f69624b8 100644 --- a/libs/models/test/testcontents.c +++ b/libs/models/test/testcontents.c @@ -114,7 +114,7 @@ do_contents (box_t *box, hull_t *hull, vec3_t origin, trace_t *trace) { memset (trace, 0xff, sizeof (*trace)); VectorCopy (box->extents, trace->extents); - // FIXME specify tract type in test spec + // FIXME specify trace type in test spec trace->type = box == &point ? tr_point : tr_box; return MOD_HullContents (hull, 0, origin, trace); } diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index ccaa2a31c..c906b153f 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -134,7 +134,6 @@ SCR_DrawRam (void) if (!r_cache_thrash) return; - //FIXME view r_funcs->Draw_Pic (cl_screen_view->xpos + 32, cl_screen_view->ypos, scr_ram); } @@ -156,7 +155,6 @@ SCR_DrawTurtle (void) if (count < 3) return; - //FIXME view r_funcs->Draw_Pic (cl_screen_view->xpos, cl_screen_view->ypos, scr_turtle); } @@ -172,7 +170,6 @@ SCR_DrawPause (void) if (!r_data->paused) return; - //FIXME view conwidth pic = r_funcs->Draw_CachePic ("gfx/pause.lmp", true); r_funcs->Draw_Pic ((cl_screen_view->xlen - pic->width) / 2, (cl_screen_view->ylen - 48 - pic->height) / 2, diff --git a/nq/source/game.c b/nq/source/game.c index 249c679dc..7dd438660 100644 --- a/nq/source/game.c +++ b/nq/source/game.c @@ -94,6 +94,8 @@ Game_Init (memhunk_t *hunk) const char *game = "nq"; // FIXME: make this dependant on QF metadata in the mission packs + // better yet, make its actions part of the metadata and remove + // entirely standard_quake = true; if ((i = COM_CheckParm ("-hipnotic"))) { diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index d8084ef8f..5d1360cc3 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -134,7 +134,6 @@ SCR_DrawRam (void) if (!r_cache_thrash) return; - //FIXME view r_funcs->Draw_Pic (cl_screen_view->xpos + 32, cl_screen_view->ypos, scr_ram); } @@ -156,7 +155,6 @@ SCR_DrawTurtle (void) if (count < 3) return; - //FIXME view r_funcs->Draw_Pic (cl_screen_view->xpos, cl_screen_view->ypos, scr_turtle); } @@ -172,7 +170,6 @@ SCR_DrawPause (void) if (!r_data->paused) return; - //FIXME view conwidth pic = r_funcs->Draw_CachePic ("gfx/pause.lmp", true); r_funcs->Draw_Pic ((cl_screen_view->xlen - pic->width) / 2, (cl_screen_view->ylen - 48 - pic->height) / 2, From 6552d76a5f396a5ad87c116c8fdbbff75e318dc3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Oct 2022 14:42:04 +0900 Subject: [PATCH 3073/3664] Clarify FIXME on qdefs.h include --- include/QF/render.h | 2 +- include/client/state.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/QF/render.h b/include/QF/render.h index 9ad381c89..94e1f0a29 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -30,7 +30,7 @@ #include "QF/mathlib.h" #include "QF/model.h" -#include "QF/qdefs.h" // FIXME +#include "QF/qdefs.h" // FIXME for MAX_STYLESTRING #include "QF/vid.h" #include "QF/simd/types.h" #include "QF/ui/vrect.h" diff --git a/include/client/state.h b/include/client/state.h index 23be2bbe4..e6d4deb06 100644 --- a/include/client/state.h +++ b/include/client/state.h @@ -31,6 +31,8 @@ #ifndef __client_state_h #define __client_state_h +#include "QF/qdefs.h" // FIXME for MAX_CL_STATS + typedef struct player_info_s { int userid; struct info_s *userinfo; From 87dd4ee33da8776af8100351c48751ea03415289 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Oct 2022 14:44:54 +0900 Subject: [PATCH 3074/3664] [gamecode] Remove some rather strange code As indicated, I have no idea why the code was like that, but removing it seems to have no effect as it seems to copy the data in the wrong direction. --- libs/gamecode/pr_exec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index cab230ad6..83e64fd57 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -109,9 +109,6 @@ _PR_SaveParams (progs_t *pr, pr_stashed_params_t *params) for (i = 0; i < pr->pr_argc; i++) { memcpy (params->params + i * pr->pr_param_size, pr->pr_real_params[i], size); - if (i < 2) { //XXX FIXME what the what?!? - memcpy (pr->pr_real_params[i], params->param_ptrs[0], size); - } } params->argc = pr->pr_argc; return params; From 8868a5facf64c08959ea9afaa0fe7fc424b24196 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Oct 2022 14:46:49 +0900 Subject: [PATCH 3075/3664] [renderer] Clean up a weird default case I don't know why I used the void 0 instead of a break when clang complained (probably rightly) about the default case hitting the end of the switch. --- libs/video/renderer/r_efrag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 8e88222f2..3f2036d97 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -239,7 +239,7 @@ R_StoreEfrags (const efrag_t *efrag) EntQueue_AddEntity (r_ent_queue, ent, model->type); break; default: - (void)0;//FIXME for clang + break; } efrag = efrag->leafnext; } From 76124ab8680801ac090127d9f2af0025d8d555c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Oct 2022 14:47:53 +0900 Subject: [PATCH 3076/3664] [qw] Document most of the mvd cvars Many are unused, but it's nice to have the info there. --- qw/source/sv_demo.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index c8e01f86f..7ee4f4d4e 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -76,7 +76,7 @@ float sv_demofps; static cvar_t sv_demofps_cvar = { .name = "sv_demofps", .description = - "FIXME", + "Minimum frame rate of packets written to the demo", .default_value = "20", .flags = CVAR_NONE, .value = { .type = &cexpr_float, .value = &sv_demofps }, @@ -85,7 +85,7 @@ float sv_demoPings; static cvar_t sv_demoPings_cvar = { .name = "sv_demoPings", .description = - "FIXME", + "Time in seconds between player ping updates. 0 disables.", .default_value = "3", .flags = CVAR_NONE, .value = { .type = &cexpr_float, .value = &sv_demoPings }, @@ -94,7 +94,7 @@ int sv_demoMaxSize; static cvar_t sv_demoMaxSize_cvar = { .name = "sv_demoMaxSize", .description = - "FIXME", + "FIXME not used", .default_value = "20480", .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &sv_demoMaxSize }, @@ -103,7 +103,7 @@ static int sv_demoUseCache; static cvar_t sv_demoUseCache_cvar = { .name = "sv_demoUseCache", .description = - "FIXME", + "FIXME not used", .default_value = "0", .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &sv_demoUseCache }, @@ -112,7 +112,7 @@ int sv_demoCacheSize; static cvar_t sv_demoCacheSize_cvar = { .name = "sv_demoCacheSize", .description = - "FIXME", + "FIXME not used", .default_value = 0, .flags = CVAR_ROM, .value = { .type = &cexpr_int, .value = &sv_demoCacheSize }, @@ -121,7 +121,7 @@ int sv_demoMaxDirSize; static cvar_t sv_demoMaxDirSize_cvar = { .name = "sv_demoMaxDirSize", .description = - "FIXME", + "FIXME not used", .default_value = "102400", .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &sv_demoMaxDirSize }, @@ -130,7 +130,7 @@ static char *sv_demoDir; static cvar_t sv_demoDir_cvar = { .name = "sv_demoDir", .description = - "FIXME", + "Name of subdirectory in which demos will be saved", .default_value = "demos", .flags = CVAR_NONE, .value = { .type = 0, .value = &sv_demoDir }, @@ -139,7 +139,7 @@ int sv_demoNoVis; static cvar_t sv_demoNoVis_cvar = { .name = "sv_demoNoVis", .description = - "FIXME", + "FIXME not used", .default_value = "1", .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &sv_demoNoVis }, @@ -148,7 +148,7 @@ static char *sv_demoPrefix; static cvar_t sv_demoPrefix_cvar = { .name = "sv_demoPrefix", .description = - "FIXME", + "Prefix for demo file names", .default_value = "", .flags = CVAR_NONE, .value = { .type = 0, .value = &sv_demoPrefix }, @@ -157,7 +157,7 @@ static char *sv_demoSuffix; static cvar_t sv_demoSuffix_cvar = { .name = "sv_demoSuffix", .description = - "FIXME", + "Suffix for demo file names", .default_value = "", .flags = CVAR_NONE, .value = { .type = 0, .value = &sv_demoSuffix }, @@ -166,7 +166,7 @@ static char *sv_onrecordfinish; static cvar_t sv_onrecordfinish_cvar = { .name = "sv_onrecordfinish", .description = - "FIXME", + "Command to execute when recording has finished. FIXME not used", .default_value = "", .flags = CVAR_NONE, .value = { .type = 0, .value = &sv_onrecordfinish }, @@ -175,7 +175,7 @@ static char *sv_ondemoremove; static cvar_t sv_ondemoremove_cvar = { .name = "sv_ondemoremove", .description = - "FIXME", + "Command to execute when a demo is removed. FIXME not used", .default_value = "", .flags = CVAR_NONE, .value = { .type = 0, .value = &sv_ondemoremove }, @@ -184,7 +184,7 @@ static int sv_demotxt; static cvar_t sv_demotxt_cvar = { .name = "sv_demotxt", .description = - "FIXME", + "Write brief description of demo to text file", .default_value = "1", .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &sv_demotxt }, @@ -193,7 +193,7 @@ static char *serverdemo; static cvar_t serverdemo_cvar = { .name = "serverdemo", .description = - "FIXME", + "Cvar for passing server demo file name to progs", .default_value = "", .flags = CVAR_SERVERINFO, .value = { .type = 0, .value = &serverdemo }, From 8ec4a18f5dbbaacedcc236c90c090af01dc4a2a4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Oct 2022 14:48:39 +0900 Subject: [PATCH 3077/3664] [scene] Swtich from - to ~ for entity id index It saves only 1 bit in the set, but it could save on allocations. Also takes care of a FIXME :P --- include/QF/scene/entity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index 770033f64..cfb445c70 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -114,7 +114,7 @@ ENTINLINE void EntQueue_AddEntity (entqueue_t *queue, entity_t *ent, int queue_num) { - int id = -ent->id;//FIXME use ~ + int id = ~ent->id; if (!set_is_member (queue->queued_ents, id)) { // entity ids are negative (ones-complement) set_add (queue->queued_ents, id); From 31dd419fde795fae34742f5732c52f9b96cf622d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 15 Oct 2022 22:54:24 +0900 Subject: [PATCH 3078/3664] [util] Reject non-shortest encoded utf-8 sequences While chatting about utf-8, I noticed that QF doesn't ensure the input sequences are the shortest possible encodings. It turns out that the check is easy in that only the second byte needs to be checked if the first byte's data bits are 0, and the second byte must have a data value larger than that representable by the next lower leading byte. --- libs/util/msg.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libs/util/msg.c b/libs/util/msg.c index b221d63c1..cc0b7f56a 100644 --- a/libs/util/msg.c +++ b/libs/util/msg.c @@ -529,7 +529,7 @@ MSG_ReadAngle16V (qmsg_t *msg, vec3_t angles) VISIBLE int MSG_ReadUTF8 (qmsg_t *msg) { - byte *buf, *start, c; + byte *buf, *start, c, min_follow = 0x80; int val = 0; unsigned count; @@ -543,7 +543,7 @@ MSG_ReadUTF8 (qmsg_t *msg) if (c < 0x80) { // 0x00 - 0x7f 1,7,7 val = c; count = 1; - } else if (c < 0xc0) { // 0x80 - 0xbf not a valid first byte + } else if (c < 0xc2) { // 0x80 - 0xc1 not a valid first byte msg->badread = true; return -1; } else if (c < 0xe0) { // 0xc0 - 0xdf 2,5,11 @@ -552,15 +552,19 @@ MSG_ReadUTF8 (qmsg_t *msg) } else if (c < 0xf0) { // 0xe0 - 0xef 3,4,16 count = 3; val = c & 0x0f; + min_follow = val == 0xe0 ? 0xa0 : 0x80; } else if (c < 0xf8) { // 0xf0 - 0xf7 4,3,21 count = 4; val = c & 0x07; + min_follow = val == 0xf0 ? 0x90 : 0x80; } else if (c < 0xfc) { // 0xf8 - 0xfb 5,2,26 count = 5; val = c & 0x03; + min_follow = val == 0xf8 ? 0x88 : 0x80; } else if (c < 0xfe) { // 0xfc - 0xfd 6,1,31 count = 6; val = c & 0x01; + min_follow = val == 0xfc ? 0x84 : 0x80; } else { // 0xfe - 0xff never valid msg->badread = true; return -1; @@ -569,6 +573,10 @@ MSG_ReadUTF8 (qmsg_t *msg) msg->badread = true; return -1; } + if (count > 2 && *buf < min_follow) { + msg->badread = true; + return -1; + } while (--count) { c = *buf++; if ((c & 0xc0) != 0x80) { From 0c54b0652bba9716c4d13b764fa562147c319544 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Oct 2022 18:02:25 +0900 Subject: [PATCH 3079/3664] Abandon support for clang The inconsistencies in clang's handling of casts was bad enough, and its silliness with certain extensions, but discovering that it doesn't support raw strings was just too much. Yes, it gives a 3s boost to qfvis on gmsp3v2.bsp, but it's not worth the hassle. --- include/QF/cexpr.h | 8 +------- libs/gamecode/pr_exec.c | 5 ----- libs/gamecode/pr_parse.c | 1 - libs/gamecode/pr_strings.c | 1 - libs/gamecode/test/main.c | 1 - libs/video/renderer/vulkan/vulkan_lighting.c | 1 - 6 files changed, 1 insertion(+), 16 deletions(-) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 4299b7ead..5935e37bb 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -29,12 +29,6 @@ #include -#ifdef __clang__ -#define DESIGNATED_INIT -#else -#define DESIGNATED_INIT __attribute__((designated_init)) -#endif - struct exprval_s; struct exprctx_s; struct va_ctx_s; @@ -63,7 +57,7 @@ typedef struct exprtype_s { binop_t *binops; unop_t *unops; void *data; -} DESIGNATED_INIT exprtype_t; +} __attribute__((designated_init)) exprtype_t; typedef struct exprval_s { exprtype_t *type; diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index 83e64fd57..ee7c100f1 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1782,7 +1782,6 @@ op_call: } } exit_program: - (void)0;//FIXME for clang } #define MM(type) (*((pr_##type##_t *) (mm))) @@ -1802,7 +1801,6 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 1: // entity.field (equivalent to OP_LOAD_t_v6p) - (void)0;//FIXME for clang pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; mm_offs = edict_area + OPA(entity) + OPB(field); break; @@ -1840,7 +1838,6 @@ pr_call_mode (progs_t *pr, const dstatement_t *st, int mm_ind) break; case 4: // entity.field (equivalent to OP_LOAD_t_v6p) - (void)0;//FIXME for clang pr_ptr_t edict_area = pr->pr_edict_area - pr->pr_globals; mm_offs = edict_area + OPA(entity) + OPB(field); break; @@ -2535,7 +2532,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) break; OP_cmp_T (LT, U, long, lvec2, lvec4, <, ulong, ulvec2, ulvec4); case OP_RETURN: - (void)0;//FIXME for clang int ret_size = (st->c & 0x1f) + 1; // up to 32 words if (st->c != 0xffff) { mm = pr_address_mode (pr, st, st->c >> 5); @@ -2866,7 +2862,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) } } exit_program: - (void)0;//FIXME for clang } /* PR_ExecuteProgram diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index f94f56c62..94bff9f58 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -231,7 +231,6 @@ ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) break; case ev_vector: - (void)0;//FIXME for clang vec3_t vec = {}; char *str = alloca (strlen (s) + 1); strcpy (str, s); diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 47321c39b..d4f423c4e 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -1056,7 +1056,6 @@ fmt_state_conversion (fmt_state_t *state) switch ((conv = *state->c++)) { case '@': // object - (void)0;// silly clang pr_ptr_t at_param = P_UINT (pr, state->fmt_count); if (state->at_handler) { const char *at_str = state->at_handler (pr, at_param, diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 9344025d0..6186c4ac9 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -44,7 +44,6 @@ test_debug_handler (prdebug_t event, void *param, void *data) case prd_subexit: break; case prd_trace: - (void)0;//FIXME for clang dstatement_t *st = test_pr.pr_statements + test_pr.pr_xstatement; if (verbose > 1) { printf ("---\n"); diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index f1f782277..e1e287c9d 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -532,7 +532,6 @@ create_light_matrices (lightingctx_t *lctx) break; case ST_CASCADE: case ST_PLANE: - (void)0;//FIXME for clang //FIXME will fail for -ref_direction vec4f_t dir = light->direction; dir[3] = 0; From 06ccc3023bde5f2aaa79aaec381ef9cf39129262 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 16 Oct 2022 18:29:25 +0900 Subject: [PATCH 3080/3664] [scene] Start work on a full-on ECS system That does feel a little redundant, but I think the System in ECS is referring to the systems that run on the components, while the other system is the support code for the ECS. Anyway... This is based heavily on the information provided by @skipjack in his github blog about EnTT. Currently, entity recycling and sparse arrays for component pools have been implemented, and adding components to an entity has been tested. --- include/QF/scene/component.h | 85 +++++++++++++++-- libs/scene/component.c | 128 +++++++++++++++++++++++++ libs/scene/test/Makemodule.am | 18 +++- libs/scene/test/test-components.c | 133 ++++++++++++++++++++++++++ libs/scene/test/test-registry.c | 151 ++++++++++++++++++++++++++++++ 5 files changed, 504 insertions(+), 11 deletions(-) create mode 100644 libs/scene/test/test-components.c create mode 100644 libs/scene/test/test-registry.c diff --git a/include/QF/scene/component.h b/include/QF/scene/component.h index 472851ee3..6d05f835d 100644 --- a/include/QF/scene/component.h +++ b/include/QF/scene/component.h @@ -36,12 +36,22 @@ #include "QF/qtypes.h" -/** \defgroup entity Hierarchy management +/** \defgroup component Entity Component System \ingroup utils */ ///@{ -#define null_transform (~0u) +#define ENT_GROW 1024 +#define COMP_GROW 128 +#define ENT_IDBITS 20 + +typedef struct ecs_pool_s { + uint32_t *sparse; // indexed by entity id, holds index to dense/data + uint32_t *dense; // holds entity id + void *data; // component data + uint32_t count; // number of components/dense entity ids + uint32_t max_count; // current capacity for components/entity ids +} ecs_pool_t; typedef struct component_s { size_t size; @@ -50,6 +60,17 @@ typedef struct component_s { const char *name; } component_t; +typedef struct ecs_registry_s { + uint32_t *entities; + uint32_t next; + uint32_t available; + uint32_t num_entities; + uint32_t max_entities; + const component_t *components; + ecs_pool_t *comp_pools; + uint32_t num_components; +} ecs_registry_t; + #define COMPINLINE GNU89INLINE inline COMPINLINE void Component_ResizeArray (const component_t *component, @@ -64,6 +85,12 @@ COMPINLINE void Component_CopyElements (const component_t *component, COMPINLINE void Component_CreateElements (const component_t *component, void *array, uint32_t index, uint32_t count); +COMPINLINE void Component_DestroyElements (const component_t *component, + void *array, + uint32_t index, uint32_t count); +COMPINLINE uint32_t Ent_Index (uint32_t id); +COMPINLINE uint32_t Ent_Generation (uint32_t id); +COMPINLINE uint32_t Ent_NextGen(uint32_t id); #undef COMPINLINE #ifndef IMPLEMENT_COMPONENT_Funcs @@ -72,16 +99,14 @@ COMPINLINE void Component_CreateElements (const component_t *component, #define COMPINLINE VISIBLE #endif -COMPINLINE -void +COMPINLINE void Component_ResizeArray (const component_t *component, void **array, uint32_t count) { *array = realloc (*array, count * component->size); } -COMPINLINE -void +COMPINLINE void Component_MoveElements (const component_t *component, void *array, uint32_t dstIndex, uint32_t srcIndex, uint32_t count) @@ -91,8 +116,7 @@ Component_MoveElements (const component_t *component, memmove (dst, src, count * component->size); } -COMPINLINE -void +COMPINLINE void Component_CopyElements (const component_t *component, void *dstArray, uint32_t dstIndex, const void *srcArray, uint32_t srcIndex, @@ -103,8 +127,7 @@ Component_CopyElements (const component_t *component, memcpy (dst, src, count * component->size); } -COMPINLINE -void +COMPINLINE void Component_CreateElements (const component_t *component, void *array, uint32_t index, uint32_t count) { @@ -119,6 +142,48 @@ Component_CreateElements (const component_t *component, void *array, } } +COMPINLINE void +Component_DestroyElements (const component_t *component, void *array, + uint32_t index, uint32_t count) +{ + if (component->destroy) { + for (uint32_t i = index; count-- > 0; i++) { + __auto_type dst = (byte *) array + i * component->size; + component->destroy (dst); + } + } +} + +COMPINLINE uint32_t +Ent_Index (uint32_t id) +{ + return id & ((1 << ENT_IDBITS) - 1); +} + +COMPINLINE uint32_t +Ent_Generation (uint32_t id) +{ + return id & ~((1 << ENT_IDBITS) - 1); +} + +COMPINLINE uint32_t +Ent_NextGen(uint32_t id) +{ + return id + (1 << ENT_IDBITS); +} + +ecs_registry_t *ECS_NewRegistry (void); +void ECS_DelRegistry (ecs_registry_t *registry); +void ECS_RegisterComponents (ecs_registry_t *registry, + const component_t *components, uint32_t count); + +uint32_t ECS_NewEntity (ecs_registry_t *registry); +void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent); + +void Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry); +void Ent_RemoveComponent (uint32_t ent, uint32_t comp, + ecs_registry_t *registry); + ///@} #endif//__QF_scene_component_h diff --git a/libs/scene/component.c b/libs/scene/component.c index 85ddc0cf9..e8e83fa24 100644 --- a/libs/scene/component.c +++ b/libs/scene/component.c @@ -28,5 +28,133 @@ # include "config.h" #endif +#include "QF/sys.h" + #define IMPLEMENT_COMPONENT_Funcs #include "QF/scene/component.h" + +VISIBLE ecs_registry_t * +ECS_NewRegistry (void) +{ + ecs_registry_t *reg = calloc (1, sizeof (ecs_registry_t)); + reg->next = Ent_Index (~0); + return reg; +} + +VISIBLE void +ECS_DelRegistry (ecs_registry_t *registry) +{ + free (registry->entities); + for (uint32_t i = 0; i < registry->num_components; i++) { + free (registry->comp_pools[i].sparse); + free (registry->comp_pools[i].dense); + free (registry->comp_pools[i].data); + } + free (registry->comp_pools); + free (registry); +} + +VISIBLE void +ECS_RegisterComponents (ecs_registry_t *registry, + const component_t *components, uint32_t count) +{ + registry->num_components = count; + registry->components = components; + registry->comp_pools = calloc (count, sizeof (ecs_pool_t)); + size_t size = registry->max_entities * sizeof (uint32_t); + for (uint32_t i = 0; i < registry->num_components; i++) { + registry->comp_pools[i].sparse = malloc (size); + memset (registry->comp_pools[i].sparse, ~0, size); + } +} + +VISIBLE void +Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) +{ + uint32_t id = Ent_Index (ent); + ecs_pool_t *pool = ®istry->comp_pools[comp]; + if (pool->sparse[id] < pool->count) { + //Sys_Error ("Ent_AddComponent: component %s already on entity %x\n", + // registry->components[i].name, ent); + return; + } + if (pool->count == pool->max_count) { + pool->max_count += COMP_GROW; + pool->dense = realloc (pool->dense, + pool->max_count * sizeof (uint32_t)); + Component_ResizeArray (®istry->components[comp], &pool->data, + pool->max_count); + } + uint32_t ind = pool->count++; + pool->sparse[id] = ind; + pool->dense[ind] = ent; + Component_CreateElements (®istry->components[comp], pool->data, ind, 1); +} + +VISIBLE void +Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) +{ + uint32_t id = Ent_Index (ent); + ecs_pool_t *pool = ®istry->comp_pools[comp]; + uint32_t ind = pool->sparse[id]; + if (ind < pool->count) { + uint32_t last = pool->count - 1; + Component_DestroyElements (®istry->components[comp], pool->data, + ind, 1); + if (last > ind) { + pool->sparse[Ent_Index (pool->dense[last])] = ind; + pool->dense[ind] = pool->dense[last]; + Component_MoveElements (®istry->components[comp], pool->data, + ind, last, 1); + } + pool->count--; + pool->sparse[id] = ~0; + } +} + +VISIBLE uint32_t +ECS_NewEntity (ecs_registry_t *registry) +{ + uint32_t ent; + if (registry->available) { + registry->available--; + uint32_t next = registry->next; + ent = next | Ent_Generation (registry->entities[next]); + registry->next = Ent_Index (registry->entities[next]); + registry->entities[next] = ent; + } else { + if (registry->num_entities == Ent_Index (~0)) { + Sys_Error ("ECS_NewEntity: out of entities"); + } + if (registry->num_entities == registry->max_entities) { + registry->max_entities += ENT_GROW; + size_t size = registry->max_entities * sizeof (uint32_t); + registry->entities = realloc (registry->entities, size); + for (uint32_t i = 0; i < registry->num_components; i++) { + uint32_t *sparse = registry->comp_pools[i].sparse; + sparse = realloc (sparse, size); + memset (sparse + registry->max_entities - ENT_GROW, ~0, + ENT_GROW * sizeof (uint32_t)); + registry->comp_pools[i].sparse = sparse; + } + } + ent = registry->num_entities++; + // ent starts out with generation 0 + registry->entities[ent] = ent; + } + return ent; +} + +VISIBLE void +ECS_DelEntity (ecs_registry_t *registry, uint32_t ent) +{ + uint32_t next = registry->next | Ent_NextGen (Ent_Generation (ent)); + uint32_t id = Ent_Index (ent); + registry->entities[id] = next; + registry->next = id; + registry->available++; + + for (uint32_t i = 0; i < registry->num_components; i++) { + Ent_RemoveComponent (ent, i, registry); + } +} diff --git a/libs/scene/test/Makemodule.am b/libs/scene/test/Makemodule.am index 76f5c9dcf..b9ee3dd9d 100644 --- a/libs/scene/test/Makemodule.am +++ b/libs/scene/test/Makemodule.am @@ -1,5 +1,7 @@ libs_scene_tests = \ - libs/scene/test/test-hierarchy + libs/scene/test/test-components \ + libs/scene/test/test-hierarchy \ + libs/scene/test/test-registry TESTS += $(libs_scene_tests) @@ -9,9 +11,23 @@ libs_scene_test_libs= \ libs/scene/libQFscene.la \ libs/util/libQFutil.la +libs_scene_test_test_components_SOURCES= \ + libs/scene/test/test-components.c +libs_scene_test_test_components_LDADD= \ + $(libs_scene_test_libs) +libs_scene_test_test_components_DEPENDENCIES= \ + $(libs_scene_test_libs) + libs_scene_test_test_hierarchy_SOURCES= \ libs/scene/test/test-hierarchy.c libs_scene_test_test_hierarchy_LDADD= \ $(libs_scene_test_libs) libs_scene_test_test_hierarchy_DEPENDENCIES= \ $(libs_scene_test_libs) + +libs_scene_test_test_registry_SOURCES= \ + libs/scene/test/test-registry.c +libs_scene_test_test_registry_LDADD= \ + $(libs_scene_test_libs) +libs_scene_test_test_registry_DEPENDENCIES= \ + $(libs_scene_test_libs) diff --git a/libs/scene/test/test-components.c b/libs/scene/test/test-components.c new file mode 100644 index 000000000..b2d2c11b9 --- /dev/null +++ b/libs/scene/test/test-components.c @@ -0,0 +1,133 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "QF/simd/types.h" +#include "QF/mathlib.h" +#include "QF/scene/component.h" + +enum test_components { + test_position, + test_scale, + test_rotation, + + test_num_components +}; + +static void +create_position (void *data) +{ + vec4f_t *pos = data; + *pos = (vec4f_t) { 0, 0, 0, 1 }; +} + +static void +create_scale (void *data) +{ + vec_t *scale = data; + VectorSet (1, 1, 1, scale); +} + +static void +create_rotation (void *data) +{ + vec4f_t *rot = data; + *rot = (vec4f_t) { 0, 0, 0, 1 }; +} + +static const component_t test_components[] = { + [test_position] = { + .size = sizeof (vec4f_t), + .create = create_position, + .name = "position", + }, + [test_scale] = { + .size = sizeof (vec3_t), + .create = create_scale, + .name = "scale", + }, + [test_rotation] = { + .size = sizeof (vec4f_t), + .create = create_rotation, + .name = "rotation", + }, +}; + +static int +check_ent_components (const uint32_t *ents, uint32_t count, uint32_t comp, + ecs_registry_t *reg) +{ + ecs_pool_t *pool = ®->comp_pools[comp]; + const component_t *component = ®->components[comp]; + if (pool->count != count) { + printf ("%s pool has wrong object count: %d %d\n", component->name, + pool->count, count); + return 0; + } + uint32_t num_entities = 0; + for (uint32_t i = 0; i < reg->max_entities; i++) { + if (pool->sparse[i] == ~0u) { + continue; + } + if (pool->sparse[i] < pool->count) { + num_entities++; + continue; + } + printf ("invalid index in sparse array of %s: %d %d\n", component->name, + pool->sparse[i], pool->count); + return 0; + } + if (num_entities != count) { + printf ("%s sparse has wrong entity count: %d %d\n", component->name, + num_entities, count); + return 0; + } + + for (uint32_t i = 0; i < count; i++) { + if (pool->sparse[Ent_Index (ents[i])] == ~0u) { + printf ("ent not in %s sparse: %x\n", component->name, ents[i]); + return 0; + } + if (pool->dense[pool->sparse[Ent_Index (ents[i])]] != ents[i]) { + printf ("indexed %s dense does have ent: %x %x\n", component->name, + pool->dense[pool->sparse[Ent_Index (ents[i])]], ents[i]); + return 0; + } + } + return 1; +} + +int +main (void) +{ + ecs_registry_t *reg = ECS_NewRegistry (); + ECS_RegisterComponents (reg, test_components, test_num_components); + uint32_t enta = ECS_NewEntity (reg); + uint32_t entb = ECS_NewEntity (reg); + uint32_t entc = ECS_NewEntity (reg); + Ent_AddComponent (enta, test_position, reg); + Ent_AddComponent (entb, test_position, reg); + Ent_AddComponent (entc, test_position, reg); + Ent_AddComponent (enta, test_rotation, reg); + Ent_AddComponent (entb, test_rotation, reg); + Ent_AddComponent (enta, test_scale, reg); + + if (!check_ent_components ((uint32_t[]){enta, entb, entc}, 3, + test_position, reg)) { + return 1; + } + if (!check_ent_components ((uint32_t[]){enta, entb}, 2, + test_rotation, reg)) { + return 1; + } + if (!check_ent_components ((uint32_t[]){enta}, 1, test_scale, reg)) { + return 1; + } + + ECS_DelRegistry (reg); + return 0; +} diff --git a/libs/scene/test/test-registry.c b/libs/scene/test/test-registry.c new file mode 100644 index 000000000..b9625dfc2 --- /dev/null +++ b/libs/scene/test/test-registry.c @@ -0,0 +1,151 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "QF/scene/component.h" + +static int +test_new_del (void) +{ + ecs_registry_t *reg = ECS_NewRegistry (); + if (!reg) { + printf ("could not create registry\n"); + return 0; + } + if (reg->max_entities && !reg->entities) { + printf ("Non-zero max_entities with null entities pointer\n"); + return 0; + } + if (!reg->max_entities && reg->entities) { + printf ("Zero max_entities with non-null entities pointer\n"); + return 0; + } + if (reg->num_entities > reg->max_entities) { + printf ("num_entities > max_entities\n"); + return 0; + } + if (reg->num_entities) { + printf ("Fresh registry has entities\n"); + return 0; + } + if (reg->available) { + printf ("Fresh registry has recycled entities\n"); + return 0; + } + ECS_DelRegistry (reg); + return 1; +} + +#define NUM_ENTS 5 + +static int +test_entities (void) +{ + ecs_registry_t *reg = ECS_NewRegistry (); + + uint32_t entities[NUM_ENTS]; + + for (int i = 0; i < NUM_ENTS; i++) { + entities[i] = ECS_NewEntity (reg); + } + if (!reg->max_entities || !reg->entities) { + printf ("Zero max_entities or non-null entities pointer\n"); + return 0; + } + if (reg->available) { + printf ("unexpected recycled entities\n"); + return 0; + } + if (reg->num_entities != NUM_ENTS) { + printf ("wrong number of entities in registry: %d vs %d\n", NUM_ENTS, + reg->num_entities); + return 0; + } + for (int i = 0; i < NUM_ENTS; i++) { + if (Ent_Index (entities[i]) > reg->num_entities) { + printf ("bad entity returned: %d > %d\n", Ent_Index (entities[i]), + reg->num_entities); + return 0; + } + if (Ent_Generation (entities[i])) { + printf ("fresh entity not generation 0\n"); + return 0; + } + for (int j = 0; j < i; j++) { + if (Ent_Index (entities[j]) == Ent_Index (entities[i])) { + printf ("duplicate entity id\n"); + return 0; + } + } + if (reg->entities[Ent_Index (entities[i])] != entities[i]) { + printf ("wrong entity in entities array: %d %d\n", + entities[i], reg->entities[Ent_Index (entities[i])]); + return 0; + } + } + ECS_DelEntity (reg, entities[2]); + ECS_DelEntity (reg, entities[0]); + if (reg->entities[Ent_Index (entities[2])] == entities[2]) { + printf ("deleted entity not deleted: %d %d\n", + entities[2], reg->entities[Ent_Index (entities[2])]); + return 0; + } + if (reg->entities[Ent_Index (entities[0])] == entities[0]) { + printf ("deleted entity not deleted: %d %d\n", + entities[0], reg->entities[Ent_Index (entities[0])]); + return 0; + } + if (reg->available != 2) { + printf ("not 2 available entity for recycling\n"); + return 0; + } + for (uint32_t i = reg->next, c = 0; i != Ent_Index (~0); + i = Ent_Index (reg->entities[i]), c++) { + if (c >= reg->available || i >= reg->num_entities) { + printf ("invalid deleted entity chain\n"); + return 0; + } + if (Ent_Index (reg->entities[i]) == i) { + printf ("deleted entity points to itself\n"); + return 0; + } + //printf ("%x\n", reg->entities[i]); + } + entities[2] = ECS_NewEntity (reg); + if (reg->available != 1) { + printf ("not 1 available entity for recycling\n"); + return 0; + } + entities[0] = ECS_NewEntity (reg); + if (reg->available != 0) { + printf ("not 0 available entities for recycling\n"); + return 0; + } + if (reg->num_entities != NUM_ENTS) { + printf ("wrong number of entities in registry: %d vs %d\n", NUM_ENTS, + reg->num_entities); + return 0; + } + if (!Ent_Generation (entities[2]) || !Ent_Generation (entities[0])) { + printf ("recycled entity generations not updated\n"); + return 0; + } + //for (int i = 0; i < NUM_ENTS; i++) { + // printf ("%x\n", entities[i]); + //} + + ECS_DelRegistry (reg); + return 1; +} + +int +main (void) +{ + if (!test_new_del ()) { return 1; } + if (!test_entities ()) { return 1; } + return 0; +} From 6189142c60014c6ba683dc4988a8da413b1c6031 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Oct 2022 15:50:53 +0900 Subject: [PATCH 3081/3664] [renderer] Remove rglyph_t struct It didn't really add anything of value as the glyph bitmap rects and the bearings were never used together, and the rest of the fields were entirely redundant. A small step towards using a component system for text. --- include/r_font.h | 10 ++------- include/r_text.h | 2 +- libs/video/renderer/r_font.c | 24 ++++++++++---------- libs/video/renderer/r_text.c | 8 +++---- libs/video/renderer/vulkan/vulkan_draw.c | 28 ++++++++++++------------ 5 files changed, 33 insertions(+), 39 deletions(-) diff --git a/include/r_font.h b/include/r_font.h index dd47e358c..3ed303ed0 100644 --- a/include/r_font.h +++ b/include/r_font.h @@ -39,13 +39,6 @@ #include "r_scrap.h" -typedef struct rglyph_s { - struct rfont_s *font; - vrect_t *rect; - vec2i_t bearing; - int advance; - int charcode; -} rglyph_t; typedef struct rfont_s { void *font_resource; @@ -53,7 +46,8 @@ typedef struct rfont_s { rscrap_t scrap; byte *scrap_bitmap; FT_Long num_glyphs; - rglyph_t *glyphs; + vrect_t *glyph_rects; + vec2i_t *glyph_bearings; } rfont_t; void R_FontInit (void); diff --git a/include/r_text.h b/include/r_text.h index 2052b9950..f440dc985 100644 --- a/include/r_text.h +++ b/include/r_text.h @@ -47,7 +47,7 @@ typedef struct r_hb_featureset_s DARRAY_TYPE (hb_feature_t) r_hb_featureset_t; struct rfont_s; struct rglyph_s; -typedef void rtext_render_t (struct rglyph_s *glyph, int x, int y, void *data); +typedef void rtext_render_t (uint32_t glyphid, int x, int y, void *data); typedef struct rshaper_s { struct rfont_s *rfont; diff --git a/libs/video/renderer/r_font.c b/libs/video/renderer/r_font.c index 6f30d27c0..f667491bd 100644 --- a/libs/video/renderer/r_font.c +++ b/libs/video/renderer/r_font.c @@ -43,10 +43,10 @@ static FT_Library ft; static void -copy_glyph (rglyph_t *glyph, FT_GlyphSlot src_glyph) +copy_glyph (vrect_t *rect, FT_GlyphSlot src_glyph, rfont_t *font) { - int dst_pitch = glyph->font->scrap.width; - byte *dst = glyph->font->scrap_bitmap + glyph->rect->x + glyph->rect->y * dst_pitch; + int dst_pitch = font->scrap.width; + byte *dst = font->scrap_bitmap + rect->x + rect->y * dst_pitch; int src_pitch = src_glyph->bitmap.pitch; byte *src = src_glyph->bitmap.buffer; @@ -74,7 +74,8 @@ R_FontFree (rfont_t *font) if (font->scrap.rects || font->scrap.free_rects) { R_ScrapDelete (&font->scrap); } - free (font->glyphs); + free (font->glyph_rects); + free (font->glyph_bearings); free (font->scrap_bitmap); free (font->font_resource); free (font); @@ -108,22 +109,21 @@ R_FontLoad (QFile *font_file, int size) R_ScrapInit (&font->scrap, pixels, pixels); font->scrap_bitmap = calloc (1, pixels * pixels); font->num_glyphs = font->face->num_glyphs; - font->glyphs = malloc (font->num_glyphs * sizeof (rglyph_t)); + font->glyph_rects = malloc (font->num_glyphs * sizeof (vrect_t)); + font->glyph_bearings = malloc (font->num_glyphs * sizeof (vec2i_t)); for (FT_Long gind = 0; gind < font->face->num_glyphs; gind++) { - rglyph_t *glyph = &font->glyphs[gind]; + vrect_t *rect = &font->glyph_rects[gind]; + vec2i_t *bearing = &font->glyph_bearings[gind]; FT_Load_Glyph (font->face, gind, FT_LOAD_DEFAULT); __auto_type slot = font->face->glyph; FT_Render_Glyph (slot, FT_RENDER_MODE_NORMAL); int width = slot->bitmap.width; int height = slot->bitmap.rows; - glyph->font = font; - glyph->rect = R_ScrapAlloc (&font->scrap, width, height); - glyph->bearing = (vec2i_t) { slot->bitmap_left, slot->bitmap_top }; - glyph->advance = slot->advance.x; - glyph->charcode = gind; + *rect = *R_ScrapAlloc (&font->scrap, width, height); + *bearing = (vec2i_t) { slot->bitmap_left, slot->bitmap_top }; - copy_glyph (glyph, slot); + copy_glyph (rect, slot, font); } return font; diff --git a/libs/video/renderer/r_text.c b/libs/video/renderer/r_text.c index f86994670..ac2cd3a9d 100644 --- a/libs/video/renderer/r_text.c +++ b/libs/video/renderer/r_text.c @@ -97,16 +97,16 @@ RText_RenderText (rshaper_t *shaper, rtext_t *text, int x, int y, rfont_t *font = shaper->rfont; for (unsigned i = 0; i < count; i++) { - rglyph_t *glyph = &font->glyphs[glyphInfo[i].codepoint]; + vec2i_t bearing = font->glyph_bearings[glyphInfo[i].codepoint]; int xp = x + glyphPos[i].x_offset / 64; int yp = y + glyphPos[i].y_offset / 64; int xa = glyphPos[i].x_advance / 64; int ya = glyphPos[i].y_advance / 64; - xp += glyph->bearing[0]; - yp -= glyph->bearing[1]; - render (glyph, xp, yp, data); + xp += bearing[0]; + yp -= bearing[1]; + render (glyphInfo[i].codepoint, xp, yp, data); x += xa; y += ya; } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index b2639eb24..127b6645e 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1209,30 +1209,30 @@ Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx) qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); glyphvert_t *verts = QFV_PacketExtend (packet, glyph_data->buffer.size); for (FT_Long i = 0; i < rfont->num_glyphs; i++) { - rglyph_t *glyph = &rfont->glyphs[i]; - float x = 0;//glyph->bearing[0]; - float y = 0;//-glyph->bearing[1]; // glyph +Y goes up - float w = glyph->rect->width; - float h = glyph->rect->height; - float u = glyph->rect->x; - float v = glyph->rect->y; - // assumes the glyph image is square + vrect_t *rect = &rfont->glyph_rects[i]; + float x = 0; + float y = 0; + float w = rect->width; + float h = rect->height; + float u = rect->x; + float v = rect->y; float s = 1.0 / rfont->scrap.width; + float t = 1.0 / rfont->scrap.height; verts[i * 4 + 0] = (glyphvert_t) { .offset = { x + 0, y + 0 }, - .uv = {(u + 0.25) * s, (v + 0.25) * s }, + .uv = {(u + 0.25) * s, (v + 0.25) * t }, }; verts[i * 4 + 1] = (glyphvert_t) { .offset = { x + 0, y + h }, - .uv = {(u + 0.25) * s, (v + h - 0.25) * s }, + .uv = {(u + 0.25) * s, (v + h - 0.25) * t }, }; verts[i * 4 + 2] = (glyphvert_t) { .offset = { x + w, y + 0 }, - .uv = {(u + w - 0.25) * s, (v + 0.25) * s }, + .uv = {(u + w - 0.25) * s, (v + 0.25) * t }, }; verts[i * 4 + 3] = (glyphvert_t) { .offset = { x + w, y + h }, - .uv = {(u + w - 0.25) * s, (v + h - 0.25) * s }, + .uv = {(u + w - 0.25) * s, (v + h - 0.25) * t }, }; } QFV_PacketCopyBuffer (packet, glyph_data->buffer.buffer, @@ -1280,7 +1280,7 @@ typedef struct { } rgctx_t; static void -vulkan_render_glyph (rglyph_t *glyph, int x, int y, void *_rgctx) +vulkan_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) { rgctx_t *rgctx = _rgctx; glyphqueue_t *queue = &rgctx->dframe->glyph_insts;; @@ -1291,7 +1291,7 @@ vulkan_render_glyph (rglyph_t *glyph, int x, int y, void *_rgctx) rgctx->batch->count++; glyphinst_t *inst = &queue->glyphs[queue->count++]; - inst->index = glyph->charcode; + inst->index = glyphid; QuatCopy (rgctx->color, inst->color); inst->position[0] = x; inst->position[1] = y; From b607fe0878e7b67462dc8f5e63f58ee5fcc54bc5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 21 Oct 2022 19:12:20 +0900 Subject: [PATCH 3082/3664] [scene] Add has/get component functions And define nullent as 0 is a valid entity. --- include/QF/scene/component.h | 23 ++++++++++++++++++++++- libs/scene/component.c | 10 +++++----- libs/scene/test/test-components.c | 4 ++-- libs/scene/test/test-registry.c | 2 +- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/include/QF/scene/component.h b/include/QF/scene/component.h index 6d05f835d..45fb86d16 100644 --- a/include/QF/scene/component.h +++ b/include/QF/scene/component.h @@ -44,6 +44,7 @@ #define ENT_GROW 1024 #define COMP_GROW 128 #define ENT_IDBITS 20 +#define nullent (~0u) typedef struct ecs_pool_s { uint32_t *sparse; // indexed by entity id, holds index to dense/data @@ -90,7 +91,11 @@ COMPINLINE void Component_DestroyElements (const component_t *component, uint32_t index, uint32_t count); COMPINLINE uint32_t Ent_Index (uint32_t id); COMPINLINE uint32_t Ent_Generation (uint32_t id); -COMPINLINE uint32_t Ent_NextGen(uint32_t id); +COMPINLINE uint32_t Ent_NextGen (uint32_t id); +COMPINLINE int Ent_HasComponent (uint32_t ent, uint32_t comp, + ecs_registry_t *reg); +COMPINLINE void *Ent_GetComponent (uint32_t ent, uint32_t comp, + ecs_registry_t *reg); #undef COMPINLINE #ifndef IMPLEMENT_COMPONENT_Funcs @@ -172,6 +177,22 @@ Ent_NextGen(uint32_t id) return id + (1 << ENT_IDBITS); } +COMPINLINE int +Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) +{ + uint32_t ind = reg->comp_pools[comp].sparse[Ent_Index (ent)]; + return ind != nullent; +} + +COMPINLINE void * +Ent_GetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) +{ + const component_t *component = ®->components[comp]; + uint32_t ind = reg->comp_pools[comp].sparse[Ent_Index (ent)]; + byte *data = reg->comp_pools[comp].data; + return data + ind * component->size; +} + ecs_registry_t *ECS_NewRegistry (void); void ECS_DelRegistry (ecs_registry_t *registry); void ECS_RegisterComponents (ecs_registry_t *registry, diff --git a/libs/scene/component.c b/libs/scene/component.c index e8e83fa24..0860896ce 100644 --- a/libs/scene/component.c +++ b/libs/scene/component.c @@ -37,7 +37,7 @@ VISIBLE ecs_registry_t * ECS_NewRegistry (void) { ecs_registry_t *reg = calloc (1, sizeof (ecs_registry_t)); - reg->next = Ent_Index (~0); + reg->next = Ent_Index (nullent); return reg; } @@ -64,7 +64,7 @@ ECS_RegisterComponents (ecs_registry_t *registry, size_t size = registry->max_entities * sizeof (uint32_t); for (uint32_t i = 0; i < registry->num_components; i++) { registry->comp_pools[i].sparse = malloc (size); - memset (registry->comp_pools[i].sparse, ~0, size); + memset (registry->comp_pools[i].sparse, nullent, size); } } @@ -108,7 +108,7 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) ind, last, 1); } pool->count--; - pool->sparse[id] = ~0; + pool->sparse[id] = nullent; } } @@ -123,7 +123,7 @@ ECS_NewEntity (ecs_registry_t *registry) registry->next = Ent_Index (registry->entities[next]); registry->entities[next] = ent; } else { - if (registry->num_entities == Ent_Index (~0)) { + if (registry->num_entities == Ent_Index (nullent)) { Sys_Error ("ECS_NewEntity: out of entities"); } if (registry->num_entities == registry->max_entities) { @@ -133,7 +133,7 @@ ECS_NewEntity (ecs_registry_t *registry) for (uint32_t i = 0; i < registry->num_components; i++) { uint32_t *sparse = registry->comp_pools[i].sparse; sparse = realloc (sparse, size); - memset (sparse + registry->max_entities - ENT_GROW, ~0, + memset (sparse + registry->max_entities - ENT_GROW, nullent, ENT_GROW * sizeof (uint32_t)); registry->comp_pools[i].sparse = sparse; } diff --git a/libs/scene/test/test-components.c b/libs/scene/test/test-components.c index b2d2c11b9..354fbab6c 100644 --- a/libs/scene/test/test-components.c +++ b/libs/scene/test/test-components.c @@ -70,7 +70,7 @@ check_ent_components (const uint32_t *ents, uint32_t count, uint32_t comp, } uint32_t num_entities = 0; for (uint32_t i = 0; i < reg->max_entities; i++) { - if (pool->sparse[i] == ~0u) { + if (pool->sparse[i] == nullent) { continue; } if (pool->sparse[i] < pool->count) { @@ -88,7 +88,7 @@ check_ent_components (const uint32_t *ents, uint32_t count, uint32_t comp, } for (uint32_t i = 0; i < count; i++) { - if (pool->sparse[Ent_Index (ents[i])] == ~0u) { + if (pool->sparse[Ent_Index (ents[i])] == nullent) { printf ("ent not in %s sparse: %x\n", component->name, ents[i]); return 0; } diff --git a/libs/scene/test/test-registry.c b/libs/scene/test/test-registry.c index b9625dfc2..2ffff8a92 100644 --- a/libs/scene/test/test-registry.c +++ b/libs/scene/test/test-registry.c @@ -103,7 +103,7 @@ test_entities (void) printf ("not 2 available entity for recycling\n"); return 0; } - for (uint32_t i = reg->next, c = 0; i != Ent_Index (~0); + for (uint32_t i = reg->next, c = 0; i != Ent_Index (nullent); i = Ent_Index (reg->entities[i]), c++) { if (c >= reg->available || i >= reg->num_entities) { printf ("invalid deleted entity chain\n"); From 394018b3c53e4ffad2c4b95a92426f5ad28ccd28 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Oct 2022 12:42:32 +0900 Subject: [PATCH 3083/3664] [qw] Fix carried flag handling I guess some of the earlier entity/scene handling hadn't been tested for flags as no entity was ever being created for a flag. This fixes a segfault when another player carrying a flag is potentially visible. Also make the -16 Z offset local. It looks better than global, and the global was quite wrong anyway as it was incorrectly updating W (which caused me to spend way too long figuring out why positions were breaking). There are still issues with flag handling, and things are likely to change with the ECS updates, but at least this lets me test. --- qw/source/cl_ents.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 1907cf15a..333394dc2 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -100,6 +100,16 @@ CL_GetEntity (int num) return cl_entities[num]; } +static entity_t * +CL_GetFlagEnt (int key) +{ + if (!cl_flag_ents[key]) { + cl_flag_ents[key] = Scene_CreateEntity (cl_world.scene); + CL_Init_Entity (cl_flag_ents[key]); + } + return cl_flag_ents[key]; +} + // Hack hack hack static inline int is_dead_body (entity_state_t *s1) @@ -305,7 +315,7 @@ CL_UpdateFlagModels (entity_t *ent, int key) float f; entity_t *fent; - fent = cl_flag_ents[key]; + fent = CL_GetFlagEnt (key); if (!fent->active) { return; @@ -325,13 +335,9 @@ CL_UpdateFlagModels (entity_t *ent, int key) vec4f_t scale = { 1, 1, 1, 1 }; // -45 degree roll (x is forward) vec4f_t rotation = { -0.382683432, 0, 0, 0.923879533 }; - vec4f_t position = { -f, -22, 0, 1}; + vec4f_t position = { -f, -22, -16, 1}; - Transform_SetLocalPosition (fent->transform, position); Transform_SetLocalTransform (fent->transform, scale, rotation, position); - position = Transform_GetWorldPosition (fent->transform); - position[3] -= 16; - Transform_SetWorldPosition (fent->transform, position); } static entity_t * @@ -339,7 +345,7 @@ CL_AddFlagModels (entity_t *ent, int team, int key) { entity_t *fent; - fent = cl_flag_ents[key]; + fent = CL_GetFlagEnt (key); if (cl_flagindex == -1) { fent->active = 0; @@ -349,7 +355,7 @@ CL_AddFlagModels (entity_t *ent, int team, int key) fent->active = 1; if (!Transform_GetParent (fent->transform)) { - Transform_SetParent (fent->transform, ent->transform); + Transform_SetParent (cl_world.scene, fent->transform, ent->transform); } CL_UpdateFlagModels (ent, key); @@ -364,9 +370,9 @@ CL_RemoveFlagModels (int key) { entity_t *fent; - fent = cl_flag_ents[key]; + fent = CL_GetFlagEnt (key); fent->active = 0; - Transform_SetParent (fent->transform, 0); + Transform_SetParent (cl_world.scene, fent->transform, 0); } /* From ac8c6b631e38cb126c5a96e18be344bf5194cf92 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Oct 2022 12:59:18 +0900 Subject: [PATCH 3084/3664] [vulkan] Skip ambient lights for shadow maps Not that anything is actually rendered yet, but the validation layers don't like the null render pass. Came up now because ctf1 seems to make the first light an ambient light. --- libs/video/renderer/vulkan/vulkan_lighting.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index e1e287c9d..927d77728 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -260,9 +260,11 @@ lighting_draw_maps (qfv_renderframe_t *rFrame) .pClearValues = lctx->qfv_renderpass->clearValues->a, }; __auto_type subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; - dfunc->vkCmdBeginRenderPass (cmd, &renderPassInfo, subpassContents); - //... - dfunc->vkCmdEndRenderPass (cmd); + if (renderPassInfo.renderPass) { + dfunc->vkCmdBeginRenderPass (cmd, &renderPassInfo, subpassContents); + //... + dfunc->vkCmdEndRenderPass (cmd); + } QFV_CmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); From de786ce1973a1360b487a8308a2c5ef5435fa0ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Oct 2022 13:04:07 +0900 Subject: [PATCH 3085/3664] [scene] Use hierref_t instead of transform_t in hierarchy Hierarchies are now much closer to being more general in that they are not tied to 3d transforms. This is a major step to moving the whole entity/transform system into an ECS. --- include/QF/scene/hierarchy.h | 4 +- include/QF/scene/transform.h | 109 ++++++++++++---------- include/scn_internal.h | 4 +- libs/ruamoko/rua_scene.c | 14 +-- libs/scene/camera.c | 2 +- libs/scene/hierarchy.c | 61 +++++++------ libs/scene/scene.c | 12 +-- libs/scene/test/test-hierarchy.c | 112 +++++++++++------------ libs/scene/transform.c | 149 ++++++++++++++++--------------- 9 files changed, 246 insertions(+), 221 deletions(-) diff --git a/include/QF/scene/hierarchy.h b/include/QF/scene/hierarchy.h index 47d946540..5a7d11f7e 100644 --- a/include/QF/scene/hierarchy.h +++ b/include/QF/scene/hierarchy.h @@ -49,8 +49,6 @@ typedef struct hierarchy_type_s { const struct component_s *components; } hierarchy_type_t; -#define null_transform (~0u) - typedef struct hierref_s { struct hierarchy_s *hierarchy; uint32_t index; ///< index in hierarchy @@ -63,7 +61,7 @@ typedef struct hierarchy_s { struct scene_s *scene; uint32_t num_objects; uint32_t max_objects; - struct transform_s **transform; //FIXME use hierref_t + hierref_t **ref; struct entity_s **entity; //FIXME should not exist uint32_t *childCount; uint32_t *childIndex; diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index 3bd933168..c448905a8 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -59,23 +59,21 @@ enum { }; typedef struct transform_s { - hierarchy_t *hierarchy; - struct scene_s *scene; ///< owning scene - uint32_t index; ///< index in hierarchy - int32_t id; ///< scene id + hierref_t ref; } transform_t; #define XFORMINLINE GNU89INLINE inline __attribute__((pure)) transform_t *Transform_New (struct scene_s *scene, transform_t *parent); /* Deletes all child transforms, and transform names */ -void Transform_Delete (transform_t *transform); +void Transform_Delete (struct scene_s *scene, transform_t *transform); transform_t *Transform_NewNamed (struct scene_s *scene, transform_t *parent, const char *name); XFORMINLINE uint32_t Transform_ChildCount (const transform_t *transform); XFORMINLINE transform_t *Transform_GetChild (const transform_t *transform, uint32_t childIndex); -void Transform_SetParent (transform_t *transform, transform_t *parent); +void Transform_SetParent (struct scene_s *scene, + transform_t *transform, transform_t *parent); XFORMINLINE transform_t *Transform_GetParent (const transform_t *transform); void Transform_SetName (transform_t *transform, const char *name); XFORMINLINE const char *Transform_GetName (const transform_t *transform); @@ -118,57 +116,63 @@ XFORMINLINE uint32_t Transform_ChildCount (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; - return h->childCount[transform->index]; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; + return h->childCount[ref->index]; } XFORMINLINE transform_t * Transform_GetChild (const transform_t *transform, uint32_t childIndex) { - hierarchy_t *h = transform->hierarchy; - if (childIndex >= h->childCount[transform->index]) { + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; + if (childIndex >= h->childCount[ref->index]) { return 0; } - return h->transform[h->childIndex[transform->index] + childIndex]; + return (transform_t *) h->ref[h->childIndex[ref->index] + childIndex]; } XFORMINLINE transform_t * Transform_GetParent (const transform_t *transform) { - if (transform->index == 0) { + __auto_type ref = (const hierref_t *) transform; + if (ref->index == 0) { return 0; } - hierarchy_t *h = transform->hierarchy; - return h->transform[h->parentIndex[transform->index]]; + hierarchy_t *h = ref->hierarchy; + return (transform_t *) h->ref[h->parentIndex[ref->index]]; } XFORMINLINE const char * Transform_GetName (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; char **name = h->components[transform_type_name]; - return name[transform->index]; + return name[ref->index]; } XFORMINLINE uint32_t Transform_GetTag (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; uint32_t *tag = h->components[transform_type_tag]; - return tag[transform->index]; + return tag[ref->index]; } XFORMINLINE void Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; - vec4f_t *src = localMatrix[transform->index]; + vec4f_t *src = localMatrix[ref->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -179,9 +183,10 @@ XFORMINLINE void Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *localInverse = h->components[transform_type_localInverse]; - vec4f_t *src = localInverse[transform->index]; + vec4f_t *src = localInverse[ref->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -192,9 +197,10 @@ XFORMINLINE void Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; - vec4f_t *src = worldMatrix[transform->index]; + vec4f_t *src = worldMatrix[ref->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -205,18 +211,20 @@ XFORMINLINE const vec4f_t * Transform_GetWorldMatrixPtr (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; - return worldMatrix[transform->index]; + return worldMatrix[ref->index]; } XFORMINLINE void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *worldInverse = h->components[transform_type_worldInverse]; - vec4f_t *src = worldInverse[transform->index]; + vec4f_t *src = worldInverse[ref->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -227,81 +235,90 @@ XFORMINLINE vec4f_t Transform_GetLocalPosition (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; - return localMatrix[transform->index][3]; + return localMatrix[ref->index][3]; } XFORMINLINE vec4f_t Transform_GetLocalRotation (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; vec4f_t *localRotation = h->components[transform_type_localRotation]; - return localRotation[transform->index]; + return localRotation[ref->index]; } XFORMINLINE vec4f_t Transform_GetLocalScale (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; vec4f_t *localScale = h->components[transform_type_localScale]; - return localScale[transform->index]; + return localScale[ref->index]; } XFORMINLINE vec4f_t Transform_GetWorldPosition (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; - return worldMatrix[transform->index][3]; + return worldMatrix[ref->index][3]; } XFORMINLINE vec4f_t Transform_GetWorldRotation (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; vec4f_t *worldRotation = h->components[transform_type_worldRotation]; - return worldRotation[transform->index]; + return worldRotation[ref->index]; } XFORMINLINE vec4f_t Transform_GetWorldScale (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; vec4f_t *worldScale = h->components[transform_type_worldScale]; - return worldScale[transform->index]; + return worldScale[ref->index]; } XFORMINLINE vec4f_t Transform_Forward (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; - return worldMatrix[transform->index][0]; + return worldMatrix[ref->index][0]; } XFORMINLINE vec4f_t Transform_Right (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; - return -worldMatrix[transform->index][1]; + return -worldMatrix[ref->index][1]; } XFORMINLINE vec4f_t Transform_Up (const transform_t *transform) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; - return worldMatrix[transform->index][2]; + return worldMatrix[ref->index][2]; } ///@} diff --git a/include/scn_internal.h b/include/scn_internal.h index e2afd9d6f..5247b51f5 100644 --- a/include/scn_internal.h +++ b/include/scn_internal.h @@ -10,9 +10,9 @@ typedef struct scene_resources_s { PR_RESMAP (entity_t) entities; PR_RESMAP (hierarchy_t) hierarchies; - PR_RESMAP (transform_t) transforms; + PR_RESMAP (hierref_t) transforms; } scene_resources_t; -transform_t *__transform_alloc (struct scene_s *scene); +hierref_t *__transform_alloc (struct scene_s *scene); #endif//__scn_internal_h diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 09c4cc662..b19b3003c 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -93,9 +93,8 @@ rua__scene_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { rua_scene_t *scene = 0; - if (id <= 0xffffffffu) { - scene = PR_RESGET (res->scene_map, (pr_int_t) id); - } + id &= 0xffffffffu; + scene = PR_RESGET (res->scene_map, (pr_int_t) id); // scene->prev will be null if the handle is unallocated if (!scene || !scene->prev) { @@ -288,7 +287,7 @@ bi_Entity_GetTransform (progs_t *pr, void *_res) entity_t *ent = rua_entity_get (res, ent_id); // ent_id contains scene id - R_ULONG (pr) = MAKE_ID (ent->transform->id, ent_id); + R_ULONG (pr) = MAKE_ID (ent->transform->ref.id, ent_id); } static void @@ -324,7 +323,7 @@ bi_Transform_GetChild (progs_t *pr, void *_res) transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); transform_t *child = Transform_GetChild (transform, P_UINT (pr, 2)); - R_UINT (pr) = child ? child->id : 0; + R_UINT (pr) = child ? child->ref.id : 0; } static void @@ -333,8 +332,9 @@ bi_Transform_SetParent (progs_t *pr, void *_res) rua_scene_resources_t *res = _res; transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); transform_t *parent = rua_transform_get (res, P_ULONG (pr, 1)); + rua_scene_t *scene = rua_scene_get (res, P_ULONG (pr, 1)); - Transform_SetParent (transform, parent); + Transform_SetParent (scene->scene, transform, parent); } static void @@ -346,7 +346,7 @@ bi_Transform_GetParent (progs_t *pr, void *_res) transform_t *parent = Transform_GetParent (transform); // transform_id contains scene id - R_ULONG (pr) = parent ? MAKE_ID (parent->id, transform_id) : 0; + R_ULONG (pr) = parent ? MAKE_ID (parent->ref.id, transform_id) : 0; } static void diff --git a/libs/scene/camera.c b/libs/scene/camera.c index 1526abb19..0909f66f0 100644 --- a/libs/scene/camera.c +++ b/libs/scene/camera.c @@ -41,7 +41,7 @@ void Camera_GetViewMatrix (const camera_t *camera, mat4f_t view) { scene_resources_t *res = camera->scene->resources; - transform_t *transform = PR_RESGET (res->transforms, camera->transform); + transform_t *transform = (transform_t *) PR_RESGET (res->transforms, camera->transform); vec4f_t rotation = Transform_GetWorldRotation (transform); vec4f_t position = Transform_GetWorldPosition (transform); mat4fquat (view, qconjf (rotation)); diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 092a3bf3b..69d9acf8c 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -41,7 +41,7 @@ #include "scn_internal.h" -static component_t transform_component = { .size = sizeof (transform_t *) }; +static component_t ref_component = { .size = sizeof (hierref_t *) }; static component_t entity_component = { .size = sizeof (entity_t *) }; static component_t childCount_component = { .size = sizeof (uint32_t) }; static component_t childIndex_component = { .size = sizeof (uint32_t) }; @@ -52,8 +52,8 @@ hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { for (size_t i = start; i < hierarchy->num_objects; i++) { - if (hierarchy->transform[i]) { - hierarchy->transform[i]->index += offset; + if (hierarchy->ref[i]) { + hierarchy->ref[i]->index += offset; } } } @@ -84,8 +84,8 @@ Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count) new_max += 15; new_max &= ~15; - Component_ResizeArray (&transform_component, - (void **) &hierarchy->transform, new_max); + Component_ResizeArray (&ref_component, + (void **) &hierarchy->ref, new_max); Component_ResizeArray (&entity_component, (void **) &hierarchy->entity, new_max); Component_ResizeArray (&childCount_component, @@ -111,8 +111,8 @@ hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t count) hierarchy->num_objects += count; uint32_t dstIndex = index + count; count = hierarchy->num_objects - index - count; - Component_MoveElements (&transform_component, - hierarchy->transform, dstIndex, index, count); + Component_MoveElements (&ref_component, + hierarchy->ref, dstIndex, index, count); Component_MoveElements (&entity_component, hierarchy->entity, dstIndex, index, count); Component_MoveElements (&childCount_component, @@ -137,8 +137,8 @@ hierarchy_close (hierarchy_t *hierarchy, uint32_t index, uint32_t count) hierarchy->num_objects -= count; uint32_t srcIndex = index + count; count = hierarchy->num_objects - index; - Component_MoveElements (&transform_component, - hierarchy->transform, index, srcIndex, count); + Component_MoveElements (&ref_component, + hierarchy->ref, index, srcIndex, count); Component_MoveElements (&entity_component, hierarchy->entity, index, srcIndex, count); Component_MoveElements (&childCount_component, @@ -158,20 +158,20 @@ static void hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstIndex, uint32_t srcIndex, uint32_t count) { - Component_CopyElements (&transform_component, - dst->transform, dstIndex, - src->transform, srcIndex, count); + Component_CopyElements (&ref_component, + dst->ref, dstIndex, + src->ref, srcIndex, count); Component_CopyElements (&entity_component, dst->entity, dstIndex, src->entity, srcIndex, count); // Actually move (as in C++ move semantics) source hierarchy object // references so that their indices do not get updated when the objects // are removed from the source hierarcy - memset (&src->transform[srcIndex], 0, count * sizeof(dst->transform[0])); + memset (&src->ref[srcIndex], 0, count * sizeof(dst->ref[0])); for (uint32_t i = 0; i < count; i++) { - dst->transform[dstIndex + i]->hierarchy = dst; - dst->transform[dstIndex + i]->index = dstIndex + i; + dst->ref[dstIndex + i]->hierarchy = dst; + dst->ref[dstIndex + i]->index = dstIndex + i; } for (uint32_t i = 0; i < dst->type->num_components; i++) { Component_CopyElements (&dst->type->components[i], @@ -184,8 +184,7 @@ static void hierarchy_init (hierarchy_t *dst, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t count) { - memset (&dst->transform[index], 0, - count * sizeof(dst->transform[0])); + memset (&dst->ref[index], 0, count * sizeof(dst->ref[0])); for (uint32_t i = 0; i < count; i++) { dst->parentIndex[index + i] = parentIndex; @@ -271,13 +270,13 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, { uint32_t insertIndex; - if (dstParent == null_transform) { + if (dstParent == nullent) { if (dst->num_objects) { Sys_Error ("attempt to insert root in non-empty hierarchy"); } hierarchy_open (dst, 0, 1); hierarchy_move (dst, src, 0, srcRoot, 1); - dst->parentIndex[0] = null_transform; + dst->parentIndex[0] = nullent; dst->childIndex[0] = 1; dst->childCount[0] = 0; insertIndex = 0; @@ -300,9 +299,9 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) uint32_t childIndex = hierarchy->childIndex[index]; uint32_t childCount = hierarchy->childCount[index]; uint32_t parentIndex = hierarchy->parentIndex[index]; - uint32_t nieceIndex = null_transform; + uint32_t nieceIndex = nullent; - if (parentIndex != null_transform) { + if (parentIndex != nullent) { uint32_t siblingIndex = hierarchy->childIndex[parentIndex]; siblingIndex += hierarchy->childCount[parentIndex] - 1; nieceIndex = hierarchy->childIndex[siblingIndex]; @@ -316,7 +315,7 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) if (childCount) { hierarchy_UpdateTransformIndices (hierarchy, childIndex, -childCount); hierarchy_UpdateChildIndices (hierarchy, index, -childCount); - if (nieceIndex != null_transform) { + if (nieceIndex != nullent) { hierarchy_UpdateParentIndices (hierarchy, nieceIndex, -childCount); } } @@ -327,13 +326,13 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) { uint32_t parentIndex = hierarchy->parentIndex[index]; uint32_t childIndex = hierarchy->childIndex[index]; - uint32_t siblingIndex = null_transform; - if (parentIndex != null_transform) { + uint32_t siblingIndex = nullent; + if (parentIndex != nullent) { siblingIndex = hierarchy->childIndex[parentIndex]; } hierarchy_remove_children (hierarchy, index); hierarchy_close (hierarchy, index, 1); - if (siblingIndex != null_transform) { + if (siblingIndex != nullent) { hierarchy_UpdateTransformIndices (hierarchy, index, -1); hierarchy_UpdateChildIndices (hierarchy, siblingIndex, -1); hierarchy_UpdateParentIndices (hierarchy, childIndex - 1, -1); @@ -360,7 +359,7 @@ Hierarchy_New (scene_t *scene, const hierarchy_type_t *type, int createRoot) if (createRoot) { hierarchy_open (hierarchy, 0, 1); - hierarchy_init (hierarchy, 0, null_transform, 1, 1); + hierarchy_init (hierarchy, 0, nullent, 1, 1); } return hierarchy; @@ -376,9 +375,9 @@ Hierarchy_Delete (hierarchy_t *hierarchy) scene_resources_t *res = hierarchy->scene->resources; for (uint32_t i = 0; i < hierarchy->num_objects; i++) { - PR_RESFREE (res->transforms, hierarchy->transform[i]); + PR_RESFREE (res->transforms, hierarchy->ref[i]); } - free (hierarchy->transform); + free (hierarchy->ref); free (hierarchy->childCount); free (hierarchy->childIndex); free (hierarchy->parentIndex); @@ -399,9 +398,9 @@ Hierarchy_Copy (scene_t *scene, const hierarchy_t *src) Hierarchy_Reserve (dst, count); for (size_t i = 0; i < count; i++) { - dst->transform[i] = __transform_alloc (scene); - dst->transform[i]->hierarchy = dst; - dst->transform[i]->index = i; + dst->ref[i] = __transform_alloc (scene); + dst->ref[i]->hierarchy = dst; + dst->ref[i]->index = i; } Component_CopyElements (&childCount_component, diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 215eb7b5e..54f3f4bc9 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -140,8 +140,8 @@ Scene_CreateEntity (scene_t *scene) ent->transform = Transform_New (scene, 0); ent->id = PR_RESINDEX (res->entities, ent); - hierarchy_t *h = ent->transform->hierarchy; - h->entity[ent->transform->index] = ent; + hierarchy_t *h = ent->transform->ref.hierarchy; + h->entity[ent->transform->ref.index] = ent; QuatSet (1, 1, 1, 1, ent->renderer.colormod); @@ -164,13 +164,13 @@ destroy_entity (scene_t *scene, entity_t *ent) // Transform_Delete takes care of all hierarchy stuff (transforms // themselves, name strings, hierarchy table) - hierarchy_t *h = transform->hierarchy; + hierarchy_t *h = transform->ref.hierarchy; for (size_t i = 0; i < h->num_objects; i++) { entity_t *e = h->entity[0]; e->transform = 0; PR_RESFREE (res->entities, ent); } - Transform_Delete (transform); + Transform_Delete (scene, transform); } void @@ -183,7 +183,7 @@ Scene_DestroyEntity (scene_t *scene, entity_t *ent) } // pull the transform out of the hierarchy to make it easier to destory // all the child entities - Transform_SetParent (ent->transform, 0); + Transform_SetParent (scene, ent->transform, 0); destroy_entity (scene, ent); } @@ -204,5 +204,5 @@ transform_t * Scene_GetTransform (scene_t *scene, int id) { scene_resources_t *res = scene->resources; - return PR_RESGET (res->transforms, id); + return (transform_t *) PR_RESGET (res->transforms, id); } diff --git a/libs/scene/test/test-hierarchy.c b/libs/scene/test/test-hierarchy.c index 47fdf0814..b7c7a6ec3 100644 --- a/libs/scene/test/test-hierarchy.c +++ b/libs/scene/test/test-hierarchy.c @@ -6,6 +6,7 @@ #include #include +#include "QF/scene/component.h" #include "QF/scene/hierarchy.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" @@ -49,7 +50,7 @@ check_hierarchy_size (hierarchy_t *h, uint32_t size) } char **name = h->components[transform_type_name]; for (uint32_t i = 0; i < h->num_objects; i++) { - if (h->transform[i]->hierarchy != h) { + if (h->ref[i]->hierarchy != h) { printf ("transform %d (%s) does not point to hierarchy\n", i, name[i]); } @@ -63,7 +64,7 @@ dump_hierarchy (hierarchy_t *h) char **name = h->components[transform_type_name]; for (uint32_t i = 0; i < h->num_objects; i++) { printf ("%2d: %5s %2u %2u %2u %2u\n", i, name[i], - h->transform[i]->index, h->parentIndex[i], + h->ref[i]->index, h->parentIndex[i], h->childIndex[i], h->childCount[i]); } puts (""); @@ -73,12 +74,13 @@ static int check_indices (transform_t *transform, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t childCount) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = &transform->ref; + hierarchy_t *h = ref->hierarchy; char **name = h->components[transform_type_name]; - if (transform->index != index) { + if (ref->index != index) { printf ("%s/%s index incorrect: expect %u got %u\n", - name[transform->index], name[index], - index, transform->index); + name[ref->index], name[index], + index, ref->index); return 0; } if (h->parentIndex[index] != parentIndex) { @@ -109,7 +111,7 @@ test_single_transform (void) printf ("Transform_New returned null\n"); return 1; } - if (!(h = transform->hierarchy)) { + if (!(h = transform->ref.hierarchy)) { printf ("New transform has no hierarchy\n"); return 1; } @@ -120,7 +122,7 @@ test_single_transform (void) vec4f_t *localRotation = h->components[transform_type_localRotation]; vec4f_t *localScale = h->components[transform_type_localScale]; if (!check_hierarchy_size (h, 1)) { return 1; } - if (!check_indices (transform, 0, null_transform, 1, 0)) { return 1; } + if (!check_indices (transform, 0, nullent, 1, 0)) { return 1; } if (!mat4_equal (localMatrix[0], identity) || !mat4_equal (localInverse[0], identity) @@ -137,7 +139,7 @@ test_single_transform (void) } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (transform->hierarchy); + Hierarchy_Delete (transform->ref.hierarchy); return 0; } @@ -148,17 +150,17 @@ test_parent_child_init (void) transform_t *parent = Transform_New (scene, 0); transform_t *child = Transform_New (scene, parent); - if (parent->hierarchy != child->hierarchy) { + if (parent->ref.hierarchy != child->ref.hierarchy) { printf ("parent and child transforms have separate hierarchies\n"); return 1; } - if (!check_hierarchy_size (parent->hierarchy, 2)) { return 1; } + if (!check_hierarchy_size (parent->ref.hierarchy, 2)) { return 1; } - if (!check_indices (parent, 0, null_transform, 1, 1)) { return 1; } + if (!check_indices (parent, 0, nullent, 1, 1)) { return 1; } if (!check_indices (child, 1, 0, 2, 0)) { return 1; } - hierarchy_t *h = parent->hierarchy; + hierarchy_t *h = parent->ref.hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; mat4f_t *localInverse = h->components[transform_type_localInverse]; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; @@ -194,7 +196,7 @@ test_parent_child_init (void) } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (parent->hierarchy); + Hierarchy_Delete (parent->ref.hierarchy); return 0; } @@ -208,28 +210,28 @@ test_parent_child_setparent (void) Transform_SetName (parent, "parent"); Transform_SetName (child, "child"); - if (!check_indices (parent, 0, null_transform, 1, 0)) { return 1; } - if (!check_indices (child, 0, null_transform, 1, 0)) { return 1; } + if (!check_indices (parent, 0, nullent, 1, 0)) { return 1; } + if (!check_indices (child, 0, nullent, 1, 0)) { return 1; } - if (parent->hierarchy == child->hierarchy) { + if (parent->ref.hierarchy == child->ref.hierarchy) { printf ("parent and child transforms have same hierarchy before" " set paret\n"); return 1; } - Transform_SetParent (child, parent); + Transform_SetParent (scene,child, parent); - if (parent->hierarchy != child->hierarchy) { + if (parent->ref.hierarchy != child->ref.hierarchy) { printf ("parent and child transforms have separate hierarchies\n"); return 1; } - if (!check_hierarchy_size (parent->hierarchy, 2)) { return 1; } + if (!check_hierarchy_size (parent->ref.hierarchy, 2)) { return 1; } - if (!check_indices (parent, 0, null_transform, 1, 1)) { return 1; } + if (!check_indices (parent, 0, nullent, 1, 1)) { return 1; } if (!check_indices (child, 1, 0, 2, 0)) { return 1; } - hierarchy_t *h = parent->hierarchy; + hierarchy_t *h = parent->ref.hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; mat4f_t *localInverse = h->components[transform_type_localInverse]; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; @@ -265,7 +267,7 @@ test_parent_child_setparent (void) } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (parent->hierarchy); + Hierarchy_Delete (parent->ref.hierarchy); return 0; } @@ -280,14 +282,14 @@ test_build_hierarchy (void) transform_t *B = Transform_NewNamed (scene, root, "B"); transform_t *C = Transform_NewNamed (scene, root, "C"); - if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices (A, 1, 0, 4, 0)) { return 1; } if (!check_indices (B, 2, 0, 4, 0)) { return 1; } if (!check_indices (C, 3, 0, 4, 0)) { return 1; } transform_t *B1 = Transform_NewNamed (scene, B, "B1"); - if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 0)) { return 1; } if (!check_indices ( B, 2, 0, 4, 1)) { return 1; } if (!check_indices ( C, 3, 0, 5, 0)) { return 1; } @@ -295,7 +297,7 @@ test_build_hierarchy (void) transform_t *A1 = Transform_NewNamed (scene, A, "A1"); - if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 1)) { return 1; } if (!check_indices ( B, 2, 0, 5, 1)) { return 1; } if (!check_indices ( C, 3, 0, 6, 0)) { return 1; } @@ -307,9 +309,9 @@ test_build_hierarchy (void) transform_t *B3 = Transform_NewNamed (scene, B, "B3"); transform_t *B2a = Transform_NewNamed (scene, B2, "B2a"); - if (!check_hierarchy_size (root->hierarchy, 11)) { return 1; } + if (!check_hierarchy_size (root->ref.hierarchy, 11)) { return 1; } - if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 2)) { return 1; } if (!check_indices ( B, 2, 0, 6, 3)) { return 1; } if (!check_indices ( C, 3, 0, 9, 0)) { return 1; } @@ -323,9 +325,9 @@ test_build_hierarchy (void) transform_t *D = Transform_NewNamed (scene, root, "D"); - if (!check_hierarchy_size (root->hierarchy, 12)) { return 1; } + if (!check_hierarchy_size (root->ref.hierarchy, 12)) { return 1; } - if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } if (!check_indices ( C, 3, 0, 10, 0)) { return 1; } @@ -338,12 +340,12 @@ test_build_hierarchy (void) if (!check_indices (A1a, 10, 5, 12, 0)) { return 1; } if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; } - dump_hierarchy (root->hierarchy); + dump_hierarchy (root->ref.hierarchy); transform_t *C1 = Transform_NewNamed (scene, C, "C1"); - dump_hierarchy (root->hierarchy); - if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; } + dump_hierarchy (root->ref.hierarchy); + if (!check_hierarchy_size (root->ref.hierarchy, 13)) { return 1; } - if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } @@ -358,7 +360,7 @@ test_build_hierarchy (void) if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (root->hierarchy); + Hierarchy_Delete (root->ref.hierarchy); return 0; } @@ -382,9 +384,9 @@ test_build_hierarchy2 (void) transform_t *D = Transform_NewNamed (scene, root, "D"); transform_t *C1 = Transform_NewNamed (scene, C, "C1"); - if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; } + if (!check_hierarchy_size (root->ref.hierarchy, 13)) { return 1; } - if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } @@ -411,10 +413,10 @@ test_build_hierarchy2 (void) transform_t *Y2a = Transform_NewNamed (scene, Y2, "Y2a"); transform_t *Z1 = Transform_NewNamed (scene, Z, "Z1"); - dump_hierarchy (T->hierarchy); - if (!check_hierarchy_size (T->hierarchy, 12)) { return 1; } + dump_hierarchy (T->ref.hierarchy); + if (!check_hierarchy_size (T->ref.hierarchy, 12)) { return 1; } - if (!check_indices ( T, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices ( T, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( X, 1, 0, 4, 2)) { return 1; } if (!check_indices ( Y, 2, 0, 6, 3)) { return 1; } if (!check_indices ( Z, 3, 0, 9, 1)) { return 1; } @@ -427,13 +429,13 @@ test_build_hierarchy2 (void) if (!check_indices (X1a, 10, 4, 12, 0)) { return 1; } if (!check_indices (Y2a, 11, 7, 12, 0)) { return 1; } - Transform_SetParent (T, B); + Transform_SetParent (scene,T, B); - dump_hierarchy (root->hierarchy); + dump_hierarchy (root->ref.hierarchy); - if (!check_hierarchy_size (root->hierarchy, 25)) { return 1; } + if (!check_hierarchy_size (root->ref.hierarchy, 25)) { return 1; } - if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } if (!check_indices ( B, 2, 0, 7, 4)) { return 1; } if (!check_indices ( C, 3, 0, 11, 1)) { return 1; } @@ -459,14 +461,14 @@ test_build_hierarchy2 (void) if (!check_indices (X1a, 23, 17, 25, 0)) { return 1; } if (!check_indices (Y2a, 24, 20, 25, 0)) { return 1; } - Transform_SetParent (Y, 0); + Transform_SetParent (scene,Y, 0); - dump_hierarchy (root->hierarchy); - dump_hierarchy (Y->hierarchy); - if (!check_hierarchy_size (root->hierarchy, 20)) { return 1; } - if (!check_hierarchy_size (Y->hierarchy, 5)) { return 1; } + dump_hierarchy (root->ref.hierarchy); + dump_hierarchy (Y->ref.hierarchy); + if (!check_hierarchy_size (root->ref.hierarchy, 20)) { return 1; } + if (!check_hierarchy_size (Y->ref.hierarchy, 5)) { return 1; } - if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } if (!check_indices ( B, 2, 0, 7, 4)) { return 1; } if (!check_indices ( C, 3, 0, 11, 1)) { return 1; } @@ -487,15 +489,15 @@ test_build_hierarchy2 (void) if (!check_indices ( Z1, 18, 15, 20, 0)) { return 1; } if (!check_indices (X1a, 19, 16, 20, 0)) { return 1; } - if (!check_indices ( Y, 0, null_transform, 1, 3)) { return 1; } + if (!check_indices ( Y, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( Y1, 1, 0, 4, 0)) { return 1; } if (!check_indices ( Y2, 2, 0, 4, 1)) { return 1; } if (!check_indices ( Y3, 3, 0, 5, 0)) { return 1; } if (!check_indices (Y2a, 4, 2, 5, 0)) { return 1; } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (root->hierarchy); - Hierarchy_Delete (Y->hierarchy); + Hierarchy_Delete (root->ref.hierarchy); + Hierarchy_Delete (Y->ref.hierarchy); return 0; } @@ -534,7 +536,7 @@ test_frames (void) Transform_SetLocalPosition (B1, (vec4f_t) { 0, 1, 0, 1 }); Transform_SetLocalRotation (B1, (vec4f_t) { -0.5, 0.5, -0.5, 0.5 }); - hierarchy_t *h = root->hierarchy; + hierarchy_t *h = root->ref.hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; mat4f_t *localInverse = h->components[transform_type_localInverse]; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; @@ -704,7 +706,7 @@ test_frames (void) return 1; } - Transform_Delete (root); + Transform_Delete (scene,root); return 0; } diff --git a/libs/scene/transform.c b/libs/scene/transform.c index 82ad54557..b1bef0234 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -133,16 +133,15 @@ static const hierarchy_type_t transform_type = { .components = transform_components, }; -transform_t * +hierref_t * __transform_alloc (scene_t *scene) { scene_resources_t *res = scene->resources; - transform_t *transform = PR_RESNEW_NC (res->transforms); - transform->scene = scene; - transform->id = PR_RESINDEX (res->transforms, transform); - transform->hierarchy = 0; - transform->index = 0; - return transform; + hierref_t *ref = PR_RESNEW_NC (res->transforms); + ref->id = PR_RESINDEX (res->transforms, ref); + ref->hierarchy = 0; + ref->index = 0; + return ref; } static void @@ -235,31 +234,32 @@ Transform_UpdateMatrices (hierarchy_t *h) transform_t * Transform_New (scene_t *scene, transform_t *parent) { - transform_t *transform = __transform_alloc (scene); + hierref_t *transform = __transform_alloc (scene); + __auto_type ref = (hierref_t *) transform; if (parent) { - transform->hierarchy = parent->hierarchy; - transform->index = Hierarchy_InsertHierarchy (parent->hierarchy, 0, - parent->index, 0); + ref->hierarchy = parent->ref.hierarchy; + ref->index = Hierarchy_InsertHierarchy (parent->ref.hierarchy, 0, + parent->ref.index, 0); } else { - transform->hierarchy = Hierarchy_New (scene, &transform_type, 1); - transform->index = 0; + ref->hierarchy = Hierarchy_New (scene, &transform_type, 1); + ref->index = 0; } - transform->hierarchy->transform[transform->index] = transform; - Transform_UpdateMatrices (transform->hierarchy); - return transform; + ref->hierarchy->ref[ref->index] = transform; + Transform_UpdateMatrices (ref->hierarchy); + return (transform_t *) transform; } void -Transform_Delete (transform_t *transform) +Transform_Delete (scene_t *scene, transform_t *transform) { - if (transform->index != 0) { + if (transform->ref.index != 0) { // The transform is not the root, so pull it out of its current // hierarchy so deleting it is easier - Transform_SetParent (transform, 0); + Transform_SetParent (scene, transform, 0); } // Takes care of freeing the transforms - Hierarchy_Delete (transform->hierarchy); + Hierarchy_Delete (transform->ref.hierarchy); } transform_t * @@ -271,118 +271,125 @@ Transform_NewNamed (scene_t *scene, transform_t *parent, const char *name) } void -Transform_SetParent (transform_t *transform, transform_t *parent) +Transform_SetParent (scene_t *scene, transform_t *transform, + transform_t *parent) { if (parent) { - hierarchy_t *hierarchy = transform->hierarchy; - uint32_t index = transform->index; - Hierarchy_InsertHierarchy (parent->hierarchy, hierarchy, - parent->index, index); + hierarchy_t *hierarchy = transform->ref.hierarchy; + uint32_t index = transform->ref.index; + Hierarchy_InsertHierarchy (parent->ref.hierarchy, hierarchy, + parent->ref.index, index); Hierarchy_RemoveHierarchy (hierarchy, index); if (!hierarchy->num_objects) { Hierarchy_Delete (hierarchy); } } else { // null parent -> make transform root - if (!transform->index) { + if (!transform->ref.index) { // already root return; } - hierarchy_t *hierarchy = transform->hierarchy; - uint32_t index = transform->index; + hierarchy_t *hierarchy = transform->ref.hierarchy; + uint32_t index = transform->ref.index; - hierarchy_t *new_hierarchy = Hierarchy_New (transform->scene, - &transform_type, 0); - Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, null_transform, + hierarchy_t *new_hierarchy = Hierarchy_New (scene, &transform_type, 0); + Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, nullent, index); Hierarchy_RemoveHierarchy (hierarchy, index); } - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; byte *modified = h->components[transform_type_modified]; - modified[transform->index] = 1; + modified[ref->index] = 1; Transform_UpdateMatrices (h); } void Transform_SetName (transform_t *transform, const char *_name) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; char **name = h->components[transform_type_name]; //FIXME create a string pool (similar to qfcc's, or even move that to util) - if (name[transform->index]) { - free (name[transform->index]); + if (name[ref->index]) { + free (name[ref->index]); } - name[transform->index] = strdup (_name); + name[ref->index] = strdup (_name); } void Transform_SetTag (transform_t *transform, uint32_t _tag) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; uint32_t *tag = h->components[transform_type_tag]; - tag[transform->index] = _tag; + tag[ref->index] = _tag; } void Transform_SetLocalPosition (transform_t *transform, vec4f_t position) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; byte *modified = h->components[transform_type_modified]; - localMatrix[transform->index][3] = position; - modified[transform->index] = 1; + localMatrix[ref->index][3] = position; + modified[ref->index] = 1; Transform_UpdateMatrices (h); } void Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; vec4f_t *localRotation = h->components[transform_type_localRotation]; vec4f_t *localScale = h->components[transform_type_localScale]; byte *modified = h->components[transform_type_modified]; - vec4f_t scale = localScale[transform->index]; + vec4f_t scale = localScale[ref->index]; mat4f_t mat; mat4fquat (mat, rotation); - localRotation[transform->index] = rotation; - localMatrix[transform->index][0] = mat[0] * scale[0]; - localMatrix[transform->index][1] = mat[1] * scale[1]; - localMatrix[transform->index][2] = mat[2] * scale[2]; - modified[transform->index] = 1; + localRotation[ref->index] = rotation; + localMatrix[ref->index][0] = mat[0] * scale[0]; + localMatrix[ref->index][1] = mat[1] * scale[1]; + localMatrix[ref->index][2] = mat[2] * scale[2]; + modified[ref->index] = 1; Transform_UpdateMatrices (h); } void Transform_SetLocalScale (transform_t *transform, vec4f_t scale) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; vec4f_t *localRotation = h->components[transform_type_localRotation]; vec4f_t *localScale = h->components[transform_type_localScale]; byte *modified = h->components[transform_type_modified]; - vec4f_t rotation = localRotation[transform->index]; + vec4f_t rotation = localRotation[ref->index]; mat4f_t mat; mat4fquat (mat, rotation); - localScale[transform->index] = scale; - localMatrix[transform->index][0] = mat[0] * scale[0]; - localMatrix[transform->index][1] = mat[1] * scale[1]; - localMatrix[transform->index][2] = mat[2] * scale[2]; - modified[transform->index] = 1; + localScale[ref->index] = scale; + localMatrix[ref->index][0] = mat[0] * scale[0]; + localMatrix[ref->index][1] = mat[1] * scale[1]; + localMatrix[ref->index][2] = mat[2] * scale[2]; + modified[ref->index] = 1; Transform_UpdateMatrices (h); } void Transform_SetWorldPosition (transform_t *transform, vec4f_t position) { - if (transform->index) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + if (ref->index) { + hierarchy_t *h = ref->hierarchy; mat4f_t *worldInverse = h->components[transform_type_worldInverse]; - uint32_t parent = h->parentIndex[transform->index]; + uint32_t parent = h->parentIndex[ref->index]; position = mvmulf (worldInverse[parent], position); } Transform_SetLocalPosition (transform, position); @@ -391,10 +398,11 @@ Transform_SetWorldPosition (transform_t *transform, vec4f_t position) void Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation) { - if (transform->index) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + if (ref->index) { + hierarchy_t *h = ref->hierarchy; vec4f_t *worldRotation = h->components[transform_type_worldRotation]; - uint32_t parent = h->parentIndex[transform->index]; + uint32_t parent = h->parentIndex[ref->index]; rotation = qmulf (qconjf (worldRotation[parent]), rotation); } Transform_SetLocalRotation (transform, rotation); @@ -404,7 +412,8 @@ void Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, vec4f_t rotation, vec4f_t position) { - hierarchy_t *h = transform->hierarchy; + __auto_type ref = (const hierref_t *) transform; + hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; vec4f_t *localRotation = h->components[transform_type_localRotation]; vec4f_t *localScale = h->components[transform_type_localScale]; @@ -413,12 +422,12 @@ Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, mat4fquat (mat, rotation); position[3] = 1; - localRotation[transform->index] = rotation; - localScale[transform->index] = scale; - localMatrix[transform->index][0] = mat[0] * scale[0]; - localMatrix[transform->index][1] = mat[1] * scale[1]; - localMatrix[transform->index][2] = mat[2] * scale[2]; - localMatrix[transform->index][3] = position; - modified[transform->index] = 1; + localRotation[ref->index] = rotation; + localScale[ref->index] = scale; + localMatrix[ref->index][0] = mat[0] * scale[0]; + localMatrix[ref->index][1] = mat[1] * scale[1]; + localMatrix[ref->index][2] = mat[2] * scale[2]; + localMatrix[ref->index][3] = position; + modified[ref->index] = 1; Transform_UpdateMatrices (h); } From dd1554aed3a9d39c8ce8098075aa9ae887e83ac4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 22 Oct 2022 14:14:57 +0900 Subject: [PATCH 3086/3664] [qw] Set cl.viewstate.time when setting cl.time Fixes cshifts not fading. I'm sure there is a better fix, but this at least gets qw mostly usable (for testing, at least: something is wonky with roll). --- qw/source/cl_pred.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index 53435937f..d1219821d 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -136,6 +136,7 @@ CL_PredictMove (void) cl.time = realtime - cls.latency - cl_pushlatency * 0.001; if (cl.time > realtime) cl.time = realtime; + cl.viewstate.time = cl.time; if (cl.intermission) { return; From 8acd5c558bb82110a2835f37c9508376a5be04d7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Oct 2022 10:32:09 +0900 Subject: [PATCH 3087/3664] [scene] Make entity_t just an entity id for ECS This puts the hierarchy (transform) reference, animation, visibility, renderer, active, and old_origin data in separate components. There are a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately in sw, reasons known, missing brush models in vulkan). While quake doesn't really need an ECS, the direction I want to take QF does, and it does seem to have improved memory bandwidth a little (uncertain). However, there's a lot more work to go (especially fixing the above bugs), but this seems to be a good start. --- include/QF/GL/qf_alias.h | 2 +- include/QF/GL/qf_iqm.h | 2 +- include/QF/GL/qf_lightmap.h | 2 +- include/QF/GL/qf_rmain.h | 3 +- include/QF/GL/qf_rsurf.h | 2 +- include/QF/GL/qf_sprite.h | 2 +- include/QF/GLSL/qf_alias.h | 2 +- include/QF/GLSL/qf_bsp.h | 3 +- include/QF/GLSL/qf_iqm.h | 2 +- include/QF/GLSL/qf_lightmap.h | 2 +- include/QF/GLSL/qf_sprite.h | 2 +- include/QF/Vulkan/qf_alias.h | 2 +- include/QF/Vulkan/qf_iqm.h | 2 +- include/QF/Vulkan/qf_scene.h | 2 +- include/QF/Vulkan/qf_sprite.h | 2 +- include/QF/Vulkan/qf_vid.h | 2 +- include/QF/model.h | 11 +- include/QF/plugin/snd_render.h | 2 +- include/QF/plugin/vid_render.h | 4 +- include/QF/render.h | 1 + include/QF/scene/camera.h | 3 +- include/QF/scene/component.h | 20 +- include/QF/scene/entity.h | 61 ++++-- include/QF/scene/hierarchy.h | 4 +- include/QF/scene/scene.h | 20 +- include/QF/scene/transform.h | 192 ++++++++++------- include/QF/scene/types.h | 1 - include/QF/screen.h | 2 +- include/QF/sound.h | 2 +- include/client/effects.h | 4 +- include/client/entities.h | 2 +- include/client/state.h | 2 +- include/client/temp_entities.h | 2 +- include/client/view.h | 7 +- include/d_iface.h | 2 +- include/d_local.h | 2 +- include/r_internal.h | 3 +- include/r_local.h | 27 +-- include/r_shared.h | 2 +- include/scn_internal.h | 4 - include/snd_internal.h | 2 +- libs/audio/renderer/snd_channels.c | 4 +- libs/audio/renderer/snd_dma.c | 4 +- libs/audio/snd.c | 4 +- libs/audio/test/testsound.c | 3 +- libs/client/cl_effects.c | 36 ++-- libs/client/cl_entities.c | 14 +- libs/client/cl_temp_entities.c | 72 ++++--- libs/client/cl_view.c | 41 ++-- libs/client/cl_world.c | 12 +- libs/ruamoko/rua_scene.c | 102 ++++----- libs/scene/camera.c | 7 +- libs/scene/component.c | 7 +- libs/scene/hierarchy.c | 65 +++--- libs/scene/scene.c | 140 ++++++------- libs/scene/test/test-hierarchy.c | 195 ++++++++++-------- libs/scene/transform.c | 123 ++++++----- libs/video/renderer/gl/gl_lightmap.c | 18 +- libs/video/renderer/gl/gl_mod_alias.c | 95 +++++---- libs/video/renderer/gl/gl_mod_iqm.c | 17 +- libs/video/renderer/gl/gl_mod_sprite.c | 43 ++-- libs/video/renderer/gl/gl_rmain.c | 20 +- libs/video/renderer/gl/gl_rmisc.c | 1 + libs/video/renderer/gl/gl_rsurf.c | 52 ++--- libs/video/renderer/gl/gl_sky_clip.c | 8 +- libs/video/renderer/glsl/glsl_alias.c | 39 ++-- libs/video/renderer/glsl/glsl_bsp.c | 46 +++-- libs/video/renderer/glsl/glsl_iqm.c | 17 +- libs/video/renderer/glsl/glsl_lightmap.c | 8 +- libs/video/renderer/glsl/glsl_main.c | 12 +- libs/video/renderer/glsl/glsl_sprite.c | 19 +- libs/video/renderer/r_billboard.c | 6 +- libs/video/renderer/r_bsp.c | 4 +- libs/video/renderer/r_efrag.c | 55 +++-- libs/video/renderer/r_iqm.c | 7 +- libs/video/renderer/r_screen.c | 4 +- libs/video/renderer/sw/d_edge.c | 37 ++-- libs/video/renderer/sw/d_surf.c | 10 +- libs/video/renderer/sw/sw_ralias.c | 76 ++++--- libs/video/renderer/sw/sw_rbsp.c | 22 +- libs/video/renderer/sw/sw_rdraw.c | 18 +- libs/video/renderer/sw/sw_riqm.c | 35 ++-- libs/video/renderer/sw/sw_rmain.c | 62 ++++-- libs/video/renderer/sw/sw_rsprite.c | 16 +- libs/video/renderer/sw/sw_rsurf.c | 8 +- libs/video/renderer/vid_common.c | 4 +- libs/video/renderer/vulkan/vulkan_alias.c | 24 ++- libs/video/renderer/vulkan/vulkan_bsp.c | 51 ++--- libs/video/renderer/vulkan/vulkan_iqm.c | 25 ++- libs/video/renderer/vulkan/vulkan_main.c | 20 +- libs/video/renderer/vulkan/vulkan_scene.c | 32 ++- libs/video/renderer/vulkan/vulkan_sprite.c | 18 +- .../video/renderer/vulkan/vulkan_vid_common.c | 15 +- nq/include/client.h | 7 +- nq/source/cl_ents.c | 59 +++--- nq/source/cl_main.c | 18 +- nq/source/cl_parse.c | 14 +- qw/include/cl_ents.h | 2 +- qw/include/client.h | 4 +- qw/source/cl_entparse.c | 10 +- qw/source/cl_ents.c | 175 +++++++++------- qw/source/cl_main.c | 5 +- qw/source/cl_screen.c | 1 + ruamoko/qwaq/builtins/graphics.c | 2 +- 104 files changed, 1410 insertions(+), 1076 deletions(-) diff --git a/include/QF/GL/qf_alias.h b/include/QF/GL/qf_alias.h index 644f58a74..1fbfbbb94 100644 --- a/include/QF/GL/qf_alias.h +++ b/include/QF/GL/qf_alias.h @@ -39,6 +39,6 @@ typedef struct aliasvrt_s { } aliasvrt_t; struct entity_s; -void gl_R_DrawAliasModel (struct entity_s *ent); +void gl_R_DrawAliasModel (struct entity_s ent); #endif//__QF_GL_qf_alias_h diff --git a/include/QF/GL/qf_iqm.h b/include/QF/GL/qf_iqm.h index f661bcde7..a65188670 100644 --- a/include/QF/GL/qf_iqm.h +++ b/include/QF/GL/qf_iqm.h @@ -45,6 +45,6 @@ typedef struct glsliqm_s { } gliqm_t; struct entity_s; -void gl_R_DrawIQMModel (struct entity_s *ent); +void gl_R_DrawIQMModel (struct entity_s ent); #endif//__QF_GL_qf_iqm_h diff --git a/include/QF/GL/qf_lightmap.h b/include/QF/GL/qf_lightmap.h index c54d41d1c..e40c50d2c 100644 --- a/include/QF/GL/qf_lightmap.h +++ b/include/QF/GL/qf_lightmap.h @@ -52,7 +52,7 @@ void GL_BuildLightmaps (struct model_s **models, int num_models); void gl_R_BlendLightmaps (void); void gl_R_CalcLightmaps (void); struct transform_s; -extern void (*gl_R_BuildLightMap) (const struct transform_s *transform, +extern void (*gl_R_BuildLightMap) (const vec4f_t *transform, mod_brush_t *brush, msurface_t *surf); int gl_R_LightmapTexture (void) __attribute__((pure)); void gl_R_FlushLightmaps (void); diff --git a/include/QF/GL/qf_rmain.h b/include/QF/GL/qf_rmain.h index 85048cb05..6f3e7ce96 100644 --- a/include/QF/GL/qf_rmain.h +++ b/include/QF/GL/qf_rmain.h @@ -29,6 +29,7 @@ #define __QF_GL_rmain_h #include "QF/qtypes.h" +#include "QF/simd/types.h" struct cvar_s; struct entity_s; @@ -41,7 +42,7 @@ extern float gl_modelalpha; extern void gl_multitexture_f (void *data, const struct cvar_s *var); void glrmain_init (void); -void gl_R_RotateForEntity (struct entity_s *e); +void gl_R_RotateForEntity (const vec4f_t *mat); struct model_s; struct entqueue_s; diff --git a/include/QF/GL/qf_rsurf.h b/include/QF/GL/qf_rsurf.h index 8a2d012ad..e42cdd56f 100644 --- a/include/QF/GL/qf_rsurf.h +++ b/include/QF/GL/qf_rsurf.h @@ -44,7 +44,7 @@ struct mod_brush_s; void GL_BuildSurfaceDisplayList (struct mod_brush_s *brush, struct msurface_s *fa); -void gl_R_DrawBrushModel (struct entity_s *e); +void gl_R_DrawBrushModel (struct entity_s e); void gl_R_DrawWorld (void); void gl_R_DrawWaterSurfaces (void); diff --git a/include/QF/GL/qf_sprite.h b/include/QF/GL/qf_sprite.h index 38498d127..8050f9369 100644 --- a/include/QF/GL/qf_sprite.h +++ b/include/QF/GL/qf_sprite.h @@ -32,6 +32,6 @@ struct entity_s; void gl_R_InitSprites (void); -extern void (*gl_R_DrawSpriteModel) (struct entity_s *ent); +extern void (*gl_R_DrawSpriteModel) (struct entity_s ent); #endif//__QF_GL_qf_sprite_h diff --git a/include/QF/GLSL/qf_alias.h b/include/QF/GLSL/qf_alias.h index 491207783..a7129547d 100644 --- a/include/QF/GLSL/qf_alias.h +++ b/include/QF/GLSL/qf_alias.h @@ -40,7 +40,7 @@ typedef struct aliasvrt_s { void glsl_R_InitAlias (void); struct entity_s; -void glsl_R_DrawAlias (struct entity_s *ent); +void glsl_R_DrawAlias (struct entity_s ent); void glsl_R_AliasBegin (void); void glsl_R_AliasEnd (void); diff --git a/include/QF/GLSL/qf_bsp.h b/include/QF/GLSL/qf_bsp.h index 482484b6a..582c0b025 100644 --- a/include/QF/GLSL/qf_bsp.h +++ b/include/QF/GLSL/qf_bsp.h @@ -30,6 +30,7 @@ #ifndef __QF_GLSL_qf_bsp_h #define __QF_GLSL_qf_bsp_h +#include "QF/simd/types.h" #include "QF/GLSL/types.h" typedef struct glsltex_s { @@ -59,7 +60,7 @@ typedef struct elechain_s { struct elechain_s *next; int model_index; elements_t *elements; - vec_t *transform; + vec4f_t *transform; float *color; } elechain_t; diff --git a/include/QF/GLSL/qf_iqm.h b/include/QF/GLSL/qf_iqm.h index b8a1c41a1..41ff0f1b8 100644 --- a/include/QF/GLSL/qf_iqm.h +++ b/include/QF/GLSL/qf_iqm.h @@ -41,7 +41,7 @@ typedef struct glsliqm_s { void glsl_R_InitIQM (void); struct entity_s; -void glsl_R_DrawIQM (struct entity_s *ent); +void glsl_R_DrawIQM (struct entity_s ent); void glsl_R_IQMBegin (void); void glsl_R_IQMEnd (void); diff --git a/include/QF/GLSL/qf_lightmap.h b/include/QF/GLSL/qf_lightmap.h index e3442bab1..2d2a22af2 100644 --- a/include/QF/GLSL/qf_lightmap.h +++ b/include/QF/GLSL/qf_lightmap.h @@ -37,7 +37,7 @@ void glsl_lightmap_init (void); struct transform_s; void glsl_R_BuildLightmaps (struct model_s **models, int num_models); void glsl_R_CalcLightmaps (void); -extern void (*glsl_R_BuildLightMap) (const struct transform_s *transform, +extern void (*glsl_R_BuildLightMap) (const vec4f_t *transform, mod_brush_t *brush, msurface_t *surf); int glsl_R_LightmapTexture (void) __attribute__((pure)); void glsl_R_FlushLightmaps (void); diff --git a/include/QF/GLSL/qf_sprite.h b/include/QF/GLSL/qf_sprite.h index 12f14a858..82ed43d6b 100644 --- a/include/QF/GLSL/qf_sprite.h +++ b/include/QF/GLSL/qf_sprite.h @@ -31,7 +31,7 @@ #define __QF_GLSL_qf_sprite_h struct entity_s; -void glsl_R_DrawSprite (struct entity_s *ent); +void glsl_R_DrawSprite (struct entity_s ent); void glsl_R_SpriteBegin (void); void glsl_R_SpriteEnd (void); void glsl_R_InitSprites (void); diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 24f8a6944..b5fad64e0 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -108,7 +108,7 @@ void Vulkan_AliasAddSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); void Vulkan_AliasRemoveSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); void Vulkan_AliasBegin (struct qfv_renderframe_s *rFrame); -void Vulkan_DrawAlias (struct entity_s *ent, struct qfv_renderframe_s *rFrame); +void Vulkan_DrawAlias (struct entity_s ent, struct qfv_renderframe_s *rFrame); void Vulkan_AliasEnd (struct qfv_renderframe_s *rFrame); void Vulkan_Alias_Init (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h index 90a417849..2dde7cfb4 100644 --- a/include/QF/Vulkan/qf_iqm.h +++ b/include/QF/Vulkan/qf_iqm.h @@ -112,7 +112,7 @@ void Vulkan_IQMAddSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); void Vulkan_IQMRemoveSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); void Vulkan_IQMBegin (struct qfv_renderframe_s *rFrame); -void Vulkan_DrawIQM (struct entity_s *ent, struct qfv_renderframe_s *rFrame); +void Vulkan_DrawIQM (struct entity_s ent, struct qfv_renderframe_s *rFrame); void Vulkan_IQMEnd (struct qfv_renderframe_s *rFrame); void Vulkan_IQM_Init (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_scene.h b/include/QF/Vulkan/qf_scene.h index 3d7673dde..428b5ceab 100644 --- a/include/QF/Vulkan/qf_scene.h +++ b/include/QF/Vulkan/qf_scene.h @@ -75,7 +75,7 @@ void Vulkan_Scene_Init (struct vulkan_ctx_s *ctx); void Vulkan_Scene_Shutdown (struct vulkan_ctx_s *ctx); int Vulkan_Scene_MaxEntities (struct vulkan_ctx_s *ctx) __attribute__((pure)); VkDescriptorSet Vulkan_Scene_Descriptors (struct vulkan_ctx_s *ctx) __attribute__((pure)); -int Vulkan_Scene_AddEntity (struct vulkan_ctx_s *ctx, struct entity_s *entity); +int Vulkan_Scene_AddEntity (struct vulkan_ctx_s *ctx, struct entity_s entity); void Vulkan_Scene_Flush (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_scene_h diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index fb080087b..874cb0e3b 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -89,7 +89,7 @@ void Vulkan_Mod_SpriteLoadFrames (struct mod_sprite_ctx_s *sprite_ctx, struct vulkan_ctx_s *ctx); void Vulkan_SpriteBegin (struct qfv_renderframe_s *rFrame); -void Vulkan_DrawSprite (struct entity_s *ent, struct qfv_renderframe_s *rFrame); +void Vulkan_DrawSprite (struct entity_s ent, struct qfv_renderframe_s *rFrame); void Vulkan_SpriteEnd (struct qfv_renderframe_s *rFrame); void Vulkan_Sprite_Init (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 7df68837b..3a6498d05 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -91,7 +91,7 @@ VkDescriptorSetLayout Vulkan_CreateDescriptorSetLayout(struct vulkan_ctx_s*ctx, struct entity_s; void Vulkan_BeginEntityLabel (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd, - struct entity_s *ent); + struct entity_s ent); struct plitem_s *Vulkan_GetConfig (struct vulkan_ctx_s *ctx, const char *name); diff --git a/include/QF/model.h b/include/QF/model.h index cea1e99ee..f36d23346 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -56,13 +56,6 @@ extern struct vid_model_funcs_s *mod_funcs; // BRUSH MODELS =============================================================== -typedef struct efrag_s { - struct mleaf_s *leaf; - struct efrag_s *leafnext; - struct entity_s *entity; - struct efrag_s *entnext; -} efrag_t; - // in memory representation =================================================== // !!! if this is changed, it must be changed in asm_draw.h too !!! @@ -86,7 +79,7 @@ typedef struct instsurf_s { struct instsurf_s *tex_chain; ///< next in texture chain struct instsurf_s *lm_chain; ///< next in lightmap chain struct msurface_s *surface; ///< surface to render - vec_t *transform; + vec4f_t *transform; float *color; } instsurf_t; @@ -199,7 +192,7 @@ typedef struct mleaf_s { // leaf specific byte *compressed_vis; - efrag_t *efrags; + struct efrag_s *efrags; int firstmarksurface; int nummarksurfaces; diff --git a/include/QF/plugin/snd_render.h b/include/QF/plugin/snd_render.h index 465415e09..b06c42eb9 100644 --- a/include/QF/plugin/snd_render.h +++ b/include/QF/plugin/snd_render.h @@ -55,7 +55,7 @@ typedef struct snd_render_funcs_s { struct sfx_s *(*precache_sound) (const char *sample); struct sfx_s *(*load_sound) (const char *name); - void (*update) (struct transform_s *ear, + void (*update) (struct transform_s ear, const byte *ambient_sound_levels); void (*stop_all_sounds) (void); void (*extra_update) (void); diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index b3e591ad4..0b1f0b022 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -33,6 +33,8 @@ #include #include +#include "QF/scene/entity.h"//FIXME + struct plitem_s; struct cvar_s; struct scene_s; @@ -154,7 +156,7 @@ typedef struct vid_render_data_s { qboolean inhibit_viewmodel; qboolean paused; int lineadj; - struct entity_s *view_model; + entity_t view_model; //FIXME still?!? double frametime; double realtime; lightstyle_t *lightstyle; diff --git a/include/QF/render.h b/include/QF/render.h index 94e1f0a29..555ace94f 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -166,6 +166,7 @@ typedef struct { int ambientlight; int drawflat; + struct scene_s *scene; struct model_s *worldmodel; } refdef_t; diff --git a/include/QF/scene/camera.h b/include/QF/scene/camera.h index 5584f397c..8593896ea 100644 --- a/include/QF/scene/camera.h +++ b/include/QF/scene/camera.h @@ -33,6 +33,7 @@ #include "QF/qtypes.h" #include "QF/simd/mat4f.h" +#include "QF/scene/transform.h" /** \defgroup scene_camera Camera data \ingroup scene @@ -43,7 +44,7 @@ typedef struct camera_s { struct scene_s *scene; ///< owning scene struct framebuffer_s *framebuffer; int32_t id; ///< id in scene - int32_t transform; + transform_t transform; float field_of_view; float aspect; float near_clip; diff --git a/include/QF/scene/component.h b/include/QF/scene/component.h index 45fb86d16..0f17be66e 100644 --- a/include/QF/scene/component.h +++ b/include/QF/scene/component.h @@ -83,15 +83,17 @@ COMPINLINE void Component_CopyElements (const component_t *component, void *dstArray, uint32_t dstIndex, const void *srcArray, uint32_t srcIndex, uint32_t count); -COMPINLINE void Component_CreateElements (const component_t *component, - void *array, - uint32_t index, uint32_t count); +COMPINLINE void *Component_CreateElements (const component_t *component, + void *array, + uint32_t index, uint32_t count); COMPINLINE void Component_DestroyElements (const component_t *component, void *array, uint32_t index, uint32_t count); COMPINLINE uint32_t Ent_Index (uint32_t id); COMPINLINE uint32_t Ent_Generation (uint32_t id); COMPINLINE uint32_t Ent_NextGen (uint32_t id); + +COMPINLINE int ECS_EntValid (uint32_t id, ecs_registry_t *reg); COMPINLINE int Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg); COMPINLINE void *Ent_GetComponent (uint32_t ent, uint32_t comp, @@ -132,7 +134,7 @@ Component_CopyElements (const component_t *component, memcpy (dst, src, count * component->size); } -COMPINLINE void +COMPINLINE void * Component_CreateElements (const component_t *component, void *array, uint32_t index, uint32_t count) { @@ -145,6 +147,7 @@ Component_CreateElements (const component_t *component, void *array, __auto_type dst = (byte *) array + index * component->size; memset (dst, 0, count * component->size); } + return (byte *) array + index * component->size; } COMPINLINE void @@ -177,6 +180,13 @@ Ent_NextGen(uint32_t id) return id + (1 << ENT_IDBITS); } +COMPINLINE int +ECS_EntValid (uint32_t id, ecs_registry_t *reg) +{ + uint32_t ind = Ent_Index (id); + return ind < reg->num_entities && reg->entities[ind] == id; +} + COMPINLINE int Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) { @@ -201,7 +211,7 @@ void ECS_RegisterComponents (ecs_registry_t *registry, uint32_t ECS_NewEntity (ecs_registry_t *registry); void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent); -void Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry); +void *Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry); void Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry); diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index cfb445c70..48bc8a36d 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -42,9 +42,16 @@ */ ///@{ -#include "QF/scene/hierarchy.h" +#include "QF/scene/scene.h" #include "QF/scene/transform.h" +typedef struct entity_s { + ecs_registry_t *reg; + uint32_t id; +} entity_t; + +#define nullentity ((entity_t) {}) + typedef struct animation_s { int frame; float syncbase; // randomize time base for local animations @@ -57,7 +64,6 @@ typedef struct animation_s { } animation_t; typedef struct visibility_s { - struct entity_s *entity; // owning entity struct efrag_s *efrag; // linked list of efrags int topnode_id; // bmodels, first world node that // splits bmodel, or NULL if not split @@ -74,20 +80,18 @@ typedef struct renderer_s { int fullbright; float min_light; int render_id; - mat4_t full_transform; + mat4f_t full_transform; } renderer_t; -typedef struct entity_s { - struct entity_s *next; - struct transform_s *transform; - int id; ///< scene id - animation_t animation; - visibility_t visibility; - renderer_t renderer; - int active; - //XXX FIXME XXX should not be here - vec4f_t old_origin; -} entity_t; +typedef struct entityset_s DARRAY_TYPE (entity_t) entityset_t; + +typedef struct efrag_s { + struct mleaf_s *leaf; + struct efrag_s *leafnext; + entity_t entity; + uint32_t queue_num; + struct efrag_s *entnext; +} efrag_t; typedef struct entqueue_s { set_t *queued_ents; @@ -99,9 +103,11 @@ typedef struct entqueue_s { entqueue_t *EntQueue_New (int num_queues); void EntQueue_Delete (entqueue_t *queue); -ENTINLINE void EntQueue_AddEntity (entqueue_t *queue, entity_t *ent, +ENTINLINE void EntQueue_AddEntity (entqueue_t *queue, entity_t ent, int queue_num); void EntQueue_Clear (entqueue_t *queue); +ENTINLINE int Entity_Valid (entity_t ent); +ENTINLINE transform_t Entity_Transform (entity_t ent); #undef ENTINLINE #ifndef IMPLEMENT_ENTITY_Funcs @@ -112,18 +118,35 @@ void EntQueue_Clear (entqueue_t *queue); ENTINLINE void -EntQueue_AddEntity (entqueue_t *queue, entity_t *ent, int queue_num) +EntQueue_AddEntity (entqueue_t *queue, entity_t ent, int queue_num) { - int id = ~ent->id; + int id = Ent_Index (ent.id); if (!set_is_member (queue->queued_ents, id)) { // entity ids are negative (ones-complement) set_add (queue->queued_ents, id); DARRAY_APPEND (&queue->ent_queues[queue_num], ent); } } + +ENTINLINE +int +Entity_Valid (entity_t ent) +{ + return ent.reg && ECS_EntValid (ent.id, ent.reg); +} + +ENTINLINE +transform_t +Entity_Transform (entity_t ent) +{ + // The transform hierarchy reference is a component on the entity thus + // the entity id is the transform id. + return (transform_t) { .reg = ent.reg, .id = ent.id, .comp = scene_href }; +} + struct mod_brush_s; -void R_AddEfrags (struct mod_brush_s *, entity_t *ent); -void R_RemoveEfrags (entity_t *ent); +void R_AddEfrags (struct mod_brush_s *, entity_t ent); +void R_RemoveEfrags (entity_t ent); ///@} diff --git a/include/QF/scene/hierarchy.h b/include/QF/scene/hierarchy.h index 5a7d11f7e..54dd950e9 100644 --- a/include/QF/scene/hierarchy.h +++ b/include/QF/scene/hierarchy.h @@ -52,7 +52,6 @@ typedef struct hierarchy_type_s { typedef struct hierref_s { struct hierarchy_s *hierarchy; uint32_t index; ///< index in hierarchy - int32_t id; ///< scene id } hierref_t; typedef struct hierarchy_s { @@ -61,8 +60,7 @@ typedef struct hierarchy_s { struct scene_s *scene; uint32_t num_objects; uint32_t max_objects; - hierref_t **ref; - struct entity_s **entity; //FIXME should not exist + uint32_t *ent; uint32_t *childCount; uint32_t *childIndex; uint32_t *parentIndex; diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index ec95221a2..14983c62c 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -40,9 +40,23 @@ */ ///@{ +enum scene_components { + scene_href, //hierarchical transform + scene_animation, + scene_visibility, + scene_renderer, + scene_active, + scene_old_origin, //XXX FIXME XXX should not be here + + scene_num_components +}; + typedef struct scene_s { + struct ecs_registry_s *reg; + struct scene_resources_s *const resources; struct hierarchy_s *hierarchies; + struct model_s *worldmodel; int num_models; struct model_s **models; @@ -52,10 +66,8 @@ typedef struct scene_s { scene_t *Scene_NewScene (void); void Scene_DeleteScene (scene_t *scene); -struct entity_s *Scene_CreateEntity (scene_t *scene); -struct entity_s *Scene_GetEntity (scene_t *scene, int id) __attribute__((pure)); -struct transform_s *Scene_GetTransform (scene_t *scene, int id) __attribute__((pure)); -void Scene_DestroyEntity (scene_t *scene, struct entity_s *entity); +struct entity_s Scene_CreateEntity (scene_t *scene); +void Scene_DestroyEntity (scene_t *scene, struct entity_s entity); void Scene_FreeAllEntities (scene_t *scene); diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index c448905a8..6c7c059aa 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -33,6 +33,7 @@ #include "QF/darray.h" #include "QF/qtypes.h" +#include "QF/scene/component.h" #include "QF/scene/hierarchy.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" @@ -59,50 +60,61 @@ enum { }; typedef struct transform_s { - hierref_t ref; + ecs_registry_t *reg; + uint32_t id; + uint32_t comp; } transform_t; +#define nulltransform ((transform_t) {}) + #define XFORMINLINE GNU89INLINE inline __attribute__((pure)) -transform_t *Transform_New (struct scene_s *scene, transform_t *parent); +XFORMINLINE int Transform_Valid (transform_t transform); + +transform_t Transform_New (struct scene_s *scene, transform_t parent); /* Deletes all child transforms, and transform names */ -void Transform_Delete (struct scene_s *scene, transform_t *transform); -transform_t *Transform_NewNamed (struct scene_s *scene, transform_t *parent, - const char *name); -XFORMINLINE uint32_t Transform_ChildCount (const transform_t *transform); -XFORMINLINE transform_t *Transform_GetChild (const transform_t *transform, - uint32_t childIndex); +void Transform_Delete (struct scene_s *scene, transform_t transform); +transform_t Transform_NewNamed (struct scene_s *scene, transform_t parent, + const char *name); +XFORMINLINE hierref_t *Transform_GetRef (transform_t transform); +XFORMINLINE uint32_t Transform_ChildCount (transform_t transform); +XFORMINLINE transform_t Transform_GetChild (transform_t transform, + uint32_t childIndex); void Transform_SetParent (struct scene_s *scene, - transform_t *transform, transform_t *parent); -XFORMINLINE transform_t *Transform_GetParent (const transform_t *transform); -void Transform_SetName (transform_t *transform, const char *name); -XFORMINLINE const char *Transform_GetName (const transform_t *transform); -void Transform_SetTag (transform_t *transform, uint32_t tag); -XFORMINLINE uint32_t Transform_GetTag (const transform_t *transform); -GNU89INLINE inline void Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat); -GNU89INLINE inline void Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat); -GNU89INLINE inline void Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat); + transform_t transform, transform_t parent); +XFORMINLINE transform_t Transform_GetParent (transform_t transform); +void Transform_SetName (transform_t transform, const char *name); +XFORMINLINE const char *Transform_GetName (transform_t transform); +void Transform_SetTag (transform_t transform, uint32_t tag); +XFORMINLINE uint32_t Transform_GetTag (transform_t transform); +GNU89INLINE inline void Transform_GetLocalMatrix (transform_t transform, + mat4f_t mat); +GNU89INLINE inline void Transform_GetLocalInverse (transform_t transform, + mat4f_t mat); +GNU89INLINE inline void Transform_GetWorldMatrix (transform_t transform, + mat4f_t mat); // XXX the pointer may be invalidated by hierarchy updates -XFORMINLINE const vec4f_t *Transform_GetWorldMatrixPtr (const transform_t *transform); -GNU89INLINE inline void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat); -XFORMINLINE vec4f_t Transform_GetLocalPosition (const transform_t *transform); -void Transform_SetLocalPosition (transform_t *transform, vec4f_t position); -XFORMINLINE vec4f_t Transform_GetLocalRotation (const transform_t *transform); -void Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation); -XFORMINLINE vec4f_t Transform_GetLocalScale (const transform_t *transform); -void Transform_SetLocalScale (transform_t *transform, vec4f_t scale); -XFORMINLINE vec4f_t Transform_GetWorldPosition (const transform_t *transform); -void Transform_SetWorldPosition (transform_t *transform, vec4f_t position); -XFORMINLINE vec4f_t Transform_GetWorldRotation (const transform_t *transform); -void Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation); -XFORMINLINE vec4f_t Transform_GetWorldScale (const transform_t *transform); -void Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, +XFORMINLINE const vec4f_t *Transform_GetWorldMatrixPtr (transform_t transform); +GNU89INLINE inline void Transform_GetWorldInverse (transform_t transform, + mat4f_t mat); +XFORMINLINE vec4f_t Transform_GetLocalPosition (transform_t transform); +void Transform_SetLocalPosition (transform_t transform, vec4f_t position); +XFORMINLINE vec4f_t Transform_GetLocalRotation (transform_t transform); +void Transform_SetLocalRotation (transform_t transform, vec4f_t rotation); +XFORMINLINE vec4f_t Transform_GetLocalScale (transform_t transform); +void Transform_SetLocalScale (transform_t transform, vec4f_t scale); +XFORMINLINE vec4f_t Transform_GetWorldPosition (transform_t transform); +void Transform_SetWorldPosition (transform_t transform, vec4f_t position); +XFORMINLINE vec4f_t Transform_GetWorldRotation (transform_t transform); +void Transform_SetWorldRotation (transform_t transform, vec4f_t rotation); +XFORMINLINE vec4f_t Transform_GetWorldScale (transform_t transform); +void Transform_SetLocalTransform (transform_t transform, vec4f_t scale, vec4f_t rotation, vec4f_t position); // NOTE: these use X: forward, -Y: right, Z:up // aslo, not guaranteed to be normalized or even orthogonal -XFORMINLINE vec4f_t Transform_Forward (const transform_t *transform); -XFORMINLINE vec4f_t Transform_Right (const transform_t *transform); -XFORMINLINE vec4f_t Transform_Up (const transform_t *transform); +XFORMINLINE vec4f_t Transform_Forward (transform_t transform); +XFORMINLINE vec4f_t Transform_Right (transform_t transform); +XFORMINLINE vec4f_t Transform_Up (transform_t transform); // no SetWorldScale because after rotations, non uniform scale becomes shear #undef XFORMINLINE @@ -113,43 +125,65 @@ XFORMINLINE vec4f_t Transform_Up (const transform_t *transform); #endif XFORMINLINE -uint32_t -Transform_ChildCount (const transform_t *transform) +int +Transform_Valid (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + return transform.reg && ECS_EntValid (transform.id, transform.reg); +} + +XFORMINLINE +hierref_t * +Transform_GetRef (transform_t transform) +{ + return Ent_GetComponent (transform.id, transform.comp, transform.reg); +} + +XFORMINLINE +uint32_t +Transform_ChildCount (transform_t transform) +{ + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; return h->childCount[ref->index]; } XFORMINLINE -transform_t * -Transform_GetChild (const transform_t *transform, uint32_t childIndex) +transform_t +Transform_GetChild (transform_t transform, uint32_t childIndex) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; if (childIndex >= h->childCount[ref->index]) { - return 0; + return nulltransform; } - return (transform_t *) h->ref[h->childIndex[ref->index] + childIndex]; + return (transform_t) { + .reg = transform.reg, + .id = h->ent[h->childIndex[ref->index] + childIndex], + .comp = transform.comp, + }; } XFORMINLINE -transform_t * -Transform_GetParent (const transform_t *transform) +transform_t +Transform_GetParent (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); if (ref->index == 0) { - return 0; + return nulltransform; } hierarchy_t *h = ref->hierarchy; - return (transform_t *) h->ref[h->parentIndex[ref->index]]; + return (transform_t) { + .reg = transform.reg, + .id = h->ent[h->parentIndex[ref->index]], + .comp = transform.comp, + }; } XFORMINLINE const char * -Transform_GetName (const transform_t *transform) +Transform_GetName (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; char **name = h->components[transform_type_name]; return name[ref->index]; @@ -157,9 +191,9 @@ Transform_GetName (const transform_t *transform) XFORMINLINE uint32_t -Transform_GetTag (const transform_t *transform) +Transform_GetTag (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; uint32_t *tag = h->components[transform_type_tag]; return tag[ref->index]; @@ -167,9 +201,9 @@ Transform_GetTag (const transform_t *transform) XFORMINLINE void -Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat) +Transform_GetLocalMatrix (transform_t transform, mat4f_t mat) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; vec4f_t *src = localMatrix[ref->index]; @@ -181,9 +215,9 @@ Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat) XFORMINLINE void -Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat) +Transform_GetLocalInverse (transform_t transform, mat4f_t mat) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *localInverse = h->components[transform_type_localInverse]; vec4f_t *src = localInverse[ref->index]; @@ -195,9 +229,9 @@ Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat) XFORMINLINE void -Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat) +Transform_GetWorldMatrix (transform_t transform, mat4f_t mat) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; vec4f_t *src = worldMatrix[ref->index]; @@ -209,9 +243,9 @@ Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat) XFORMINLINE const vec4f_t * -Transform_GetWorldMatrixPtr (const transform_t *transform) +Transform_GetWorldMatrixPtr (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; return worldMatrix[ref->index]; @@ -219,9 +253,9 @@ Transform_GetWorldMatrixPtr (const transform_t *transform) XFORMINLINE void -Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat) +Transform_GetWorldInverse (transform_t transform, mat4f_t mat) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *worldInverse = h->components[transform_type_worldInverse]; vec4f_t *src = worldInverse[ref->index]; @@ -233,9 +267,9 @@ Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat) XFORMINLINE vec4f_t -Transform_GetLocalPosition (const transform_t *transform) +Transform_GetLocalPosition (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; return localMatrix[ref->index][3]; @@ -243,9 +277,9 @@ Transform_GetLocalPosition (const transform_t *transform) XFORMINLINE vec4f_t -Transform_GetLocalRotation (const transform_t *transform) +Transform_GetLocalRotation (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; vec4f_t *localRotation = h->components[transform_type_localRotation]; return localRotation[ref->index]; @@ -253,9 +287,9 @@ Transform_GetLocalRotation (const transform_t *transform) XFORMINLINE vec4f_t -Transform_GetLocalScale (const transform_t *transform) +Transform_GetLocalScale (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; vec4f_t *localScale = h->components[transform_type_localScale]; return localScale[ref->index]; @@ -263,9 +297,9 @@ Transform_GetLocalScale (const transform_t *transform) XFORMINLINE vec4f_t -Transform_GetWorldPosition (const transform_t *transform) +Transform_GetWorldPosition (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; return worldMatrix[ref->index][3]; @@ -273,9 +307,9 @@ Transform_GetWorldPosition (const transform_t *transform) XFORMINLINE vec4f_t -Transform_GetWorldRotation (const transform_t *transform) +Transform_GetWorldRotation (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; vec4f_t *worldRotation = h->components[transform_type_worldRotation]; return worldRotation[ref->index]; @@ -283,9 +317,9 @@ Transform_GetWorldRotation (const transform_t *transform) XFORMINLINE vec4f_t -Transform_GetWorldScale (const transform_t *transform) +Transform_GetWorldScale (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; vec4f_t *worldScale = h->components[transform_type_worldScale]; return worldScale[ref->index]; @@ -293,9 +327,9 @@ Transform_GetWorldScale (const transform_t *transform) XFORMINLINE vec4f_t -Transform_Forward (const transform_t *transform) +Transform_Forward (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; return worldMatrix[ref->index][0]; @@ -303,9 +337,9 @@ Transform_Forward (const transform_t *transform) XFORMINLINE vec4f_t -Transform_Right (const transform_t *transform) +Transform_Right (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; return -worldMatrix[ref->index][1]; @@ -313,9 +347,9 @@ Transform_Right (const transform_t *transform) XFORMINLINE vec4f_t -Transform_Up (const transform_t *transform) +Transform_Up (transform_t transform) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; return worldMatrix[ref->index][2]; diff --git a/include/QF/scene/types.h b/include/QF/scene/types.h index 550262302..fa371a65a 100644 --- a/include/QF/scene/types.h +++ b/include/QF/scene/types.h @@ -47,7 +47,6 @@ typedef struct uint32set_s DARRAY_TYPE (uint32_t) uint32set_t; typedef struct byteset_s DARRAY_TYPE (byte) byteset_t; typedef struct stringset_s DARRAY_TYPE (char *) stringset_t; typedef struct xformset_s DARRAY_TYPE (struct transform_s *) xformset_t; -typedef struct entityset_s DARRAY_TYPE (struct entity_s *) entityset_t; ///@} diff --git a/include/QF/screen.h b/include/QF/screen.h index bf0c60ee1..a98f2f4d6 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -37,7 +37,7 @@ void SCR_Init (void); typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array -void SCR_UpdateScreen (struct transform_s *camera, double realtime, +void SCR_UpdateScreen (struct transform_s camera, double realtime, SCR_Func *scr_funcs); void SCR_SetFOV (float fov); // control whether the 3d viewport is user-controlled or always fullscreen diff --git a/include/QF/sound.h b/include/QF/sound.h index c8a86bb71..8bfad49e0 100644 --- a/include/QF/sound.h +++ b/include/QF/sound.h @@ -119,7 +119,7 @@ void S_StopAllSounds(void); \param ambient_sound_level NUM_AMBIENTS bytes indicating current ambient sound levels */ -void S_Update (struct transform_s *ear, const byte *ambient_sound_level); +void S_Update (struct transform_s ear, const byte *ambient_sound_level); /** Render some more sound without updating the client's position/orientation. */ diff --git a/include/client/effects.h b/include/client/effects.h index dbec75769..45e103410 100644 --- a/include/client/effects.h +++ b/include/client/effects.h @@ -37,9 +37,9 @@ struct entity_state_s; void CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size, byte glow_color, double time); -void CL_ModelEffects (struct entity_s *ent, int num, int glow_color, +void CL_ModelEffects (struct entity_s ent, int num, int glow_color, double time); -void CL_EntityEffects (int num, struct entity_s *ent, +void CL_EntityEffects (int num, struct entity_s ent, struct entity_state_s *state, double time); void CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num, double time); diff --git a/include/client/entities.h b/include/client/entities.h index d93107bec..c0c2912dd 100644 --- a/include/client/entities.h +++ b/include/client/entities.h @@ -78,7 +78,7 @@ extern entstates_t qw_entstates; extern vec3_t ent_colormod[256]; struct entity_s; -void CL_TransformEntity (struct entity_s *ent, float scale, +void CL_TransformEntity (struct entity_s ent, float scale, const vec3_t angles, vec4f_t position); #endif//__client_entities_h diff --git a/include/client/state.h b/include/client/state.h index e6d4deb06..46f0f8d88 100644 --- a/include/client/state.h +++ b/include/client/state.h @@ -52,7 +52,7 @@ typedef struct player_info_s { struct info_key_s *skinname; struct skin_s *skin; - struct entity_s *flag_ent; + entity_t flag_ent; int spectator; int stats[MAX_CL_STATS]; // health, etc diff --git a/include/client/temp_entities.h b/include/client/temp_entities.h index 5ce46fc64..87ffd369c 100644 --- a/include/client/temp_entities.h +++ b/include/client/temp_entities.h @@ -104,7 +104,7 @@ struct entity_s; void CL_TEnts_Init (void); void CL_TEnts_Precache (void); -void CL_Init_Entity (struct entity_s *ent); +void CL_Init_Entity (struct entity_s ent); void CL_ClearTEnts (void); void CL_UpdateTEnts (double time, TEntContext_t *ctx); void CL_ParseTEnt_nq (struct msg_s *net_message, double time, diff --git a/include/client/view.h b/include/client/view.h index edea89758..43e82ec05 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -31,6 +31,7 @@ #include "QF/mathlib.h" #include "QF/simd/types.h" +#include "QF/scene/entity.h" typedef struct { int destcolor[3]; @@ -58,7 +59,7 @@ typedef struct viewstate_s { vec4f_t velocity; vec4f_t punchangle; float frametime; - struct transform_s *camera_transform; + transform_t camera_transform; double time; float height; int weaponframe; @@ -85,8 +86,8 @@ typedef struct viewstate_s { double laststop; struct model_s *weapon_model; - struct entity_s *weapon_entity; - struct entity_s *player_entity; + entity_t weapon_entity; + entity_t player_entity; struct chasestate_s *chasestate; } viewstate_t; diff --git a/include/d_iface.h b/include/d_iface.h index 7f05c38bf..454502fb2 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -201,7 +201,7 @@ typedef struct extern drawsurf_t r_drawsurf; struct transform_s; -void R_DrawSurface (struct transform_s *transform); +void R_DrawSurface (struct transform_s transform); void R_GenTile (msurface_t *psurf, void *pdest); // !!! if this is changed, it must be changed in d_iface.h too !!! diff --git a/include/d_local.h b/include/d_local.h index 7b9cc3fac..cd06ab0ae 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -92,7 +92,7 @@ void D_DrawSkyScans (struct espan_s *pspan); void R_ShowSubDiv (void); extern void (*prealspandrawer)(void); struct entity_s; -surfcache_t *D_CacheSurface (struct entity_s *ent, +surfcache_t *D_CacheSurface (struct entity_s ent, msurface_t *surface, int miplevel); int D_MipLevelForScale (float scale) __attribute__((pure)); diff --git a/include/r_internal.h b/include/r_internal.h index b3868c677..1f1d72c77 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -72,6 +72,7 @@ int R_InitGraphTextures (int base); struct entity_s; struct animation_s; +struct transform_s; void R_DrawAliasModel (struct entity_s *e); void R_MarkLeaves (struct mleaf_s *viewleaf, int *node_visframes, @@ -83,7 +84,7 @@ extern int *r_face_visframes; void GL_SetPalette (void *data, const byte *palette); void GLSL_SetPalette (void *data, const byte *palette); -int R_BillboardFrame (struct entity_s *ent, int orientation, +int R_BillboardFrame (struct transform_s transform, int orientation, vec4f_t cameravec, vec4f_t *bbup, vec4f_t *bbright, vec4f_t *bbfwd); mspriteframe_t *R_GetSpriteFrame (const msprite_t *sprite, diff --git a/include/r_local.h b/include/r_local.h index 4f5d53185..fbb7e74d3 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -145,33 +145,34 @@ void R_SetFrustum (plane_t *frustum, const union refframe_s *frame, float fov_x, float fov_y); struct entity_s; +struct animation_s; void R_SpriteBegin (void); void R_SpriteEnd (void); -void R_DrawSprite (struct entity_s *ent); -void R_RenderFace (struct entity_s *ent, msurface_t *fa, int clipflags); -void R_RenderPoly (struct entity_s *ent, msurface_t *fa, int clipflags); -void R_RenderBmodelFace (struct entity_s *ent, bedge_t *pedges, msurface_t *psurf); +void R_DrawSprite (struct entity_s ent); +void R_RenderFace (struct entity_s ent, msurface_t *fa, int clipflags); +void R_RenderPoly (struct entity_s ent, msurface_t *fa, int clipflags); +void R_RenderBmodelFace (struct entity_s ent, bedge_t *pedges, msurface_t *psurf); void R_TransformFrustum (void); void R_SetSkyFrame (void); void R_DrawSurfaceBlock (void); -struct texture_s *R_TextureAnimation (const struct entity_s *entity, msurface_t *surf) __attribute__((pure)); +struct texture_s *R_TextureAnimation (const struct animation_s *animation, msurface_t *surf) __attribute__((pure)); void R_GenSkyTile (void *pdest); void R_SurfPatch (void); -void R_DrawSubmodelPolygons (struct entity_s *ent, model_t *pmodel, int clipflags, struct mleaf_s *topleaf); -void R_DrawSolidClippedSubmodelPolygons (struct entity_s *ent, model_t *pmodel, struct mnode_s *topnode); +void R_DrawSubmodelPolygons (struct entity_s ent, model_t *pmodel, int clipflags, struct mleaf_s *topleaf); +void R_DrawSolidClippedSubmodelPolygons (struct entity_s ent, model_t *pmodel, struct mnode_s *topnode); void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); surf_t *R_GetSurf (void); void R_AliasClipAndProjectFinalVert (finalvert_t *fv, auxvert_t *av); -void R_AliasDrawModel (struct entity_s *ent, alight_t *plighting); -void R_IQMDrawModel (struct entity_s *ent, alight_t *plighting); +void R_AliasDrawModel (struct entity_s ent, alight_t *plighting); +void R_IQMDrawModel (struct entity_s ent, alight_t *plighting); struct animation_s; maliasskindesc_t *R_AliasGetSkindesc (struct animation_s *animation, int skinnum, aliashdr_t *hdr); maliasframedesc_t *R_AliasGetFramedesc (struct animation_s *animation, aliashdr_t *hdr); float R_AliasGetLerpedFrames (struct animation_s *animation, aliashdr_t *hdr); -float R_IQMGetLerpedFrames (struct entity_s *ent, iqm_t *hdr); +float R_IQMGetLerpedFrames (struct animation_s *animation, iqm_t *hdr); iqmframe_t *R_IQMBlendFrames (const iqm_t *iqm, int frame1, int frame2, float blend, int extra); iqmframe_t *R_IQMBlendPalette (const iqm_t *iqm, int frame1, int frame2, @@ -197,7 +198,7 @@ extern void R_EdgeCodeStart (void); extern void R_EdgeCodeEnd (void); struct transform_s; -extern void R_RotateBmodel (struct transform_s *transform); +extern void R_RotateBmodel (struct transform_s transform); extern int c_faceclip; extern int r_polycount; @@ -229,7 +230,7 @@ typedef struct btofpoly_s { extern int numbtofpolys; void R_InitTurb (void); -void R_ZDrawSubmodelPolys (struct entity_s *ent, model_t *clmodel); +void R_ZDrawSubmodelPolys (struct entity_s ent, model_t *clmodel); // Alias models =========================================== @@ -244,7 +245,7 @@ extern auxvert_t *pauxverts; extern float ziscale; extern float aliastransform[3][4]; -qboolean R_AliasCheckBBox (struct entity_s *ent); +qboolean R_AliasCheckBBox (struct entity_s ent); // turbulence stuff ======================================= diff --git a/include/r_shared.h b/include/r_shared.h index 16bb3bbb2..90f69aa03 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -99,7 +99,7 @@ typedef struct surf_s { // start) int flags; // currentface flags void *data; // associated data like msurface_t - struct entity_s *entity; + entity_t entity; float nearzi; // nearest 1/z on surface, for mipmapping qboolean insubmodel; float d_ziorigin, d_zistepu, d_zistepv; diff --git a/include/scn_internal.h b/include/scn_internal.h index 5247b51f5..e60d9d2a9 100644 --- a/include/scn_internal.h +++ b/include/scn_internal.h @@ -8,11 +8,7 @@ #include "QF/scene/transform.h" typedef struct scene_resources_s { - PR_RESMAP (entity_t) entities; PR_RESMAP (hierarchy_t) hierarchies; - PR_RESMAP (hierref_t) transforms; } scene_resources_t; -hierref_t *__transform_alloc (struct scene_s *scene); - #endif//__scn_internal_h diff --git a/include/snd_internal.h b/include/snd_internal.h index 59d0d2fc2..b1f23a3f1 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -396,7 +396,7 @@ void SND_SetAmbient (snd_t *snd, int amb_channel, sfx_t *sfx); \param ambient_sound_level Pointer to 4 bytes indicating the levels at which to play the ambient sounds. */ -void SND_SetListener (snd_t *snd, struct transform_s *ear, +void SND_SetListener (snd_t *snd, struct transform_s ear, const byte *ambient_sound_level); /** Stop all sounds from playing. diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index f7043de83..1b2fb64ce 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -578,9 +578,9 @@ s_combine_channel (channel_t *combine, channel_t *ch) } void -SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level) +SND_SetListener (snd_t *snd, transform_t ear, const byte *ambient_sound_level) { - if (ear) { + if (Transform_Valid (ear)) { listener_origin = Transform_GetWorldPosition (ear); listener_forward = Transform_Forward (ear); listener_right = Transform_Right (ear); diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index dc8dfb481..ee432247c 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -50,6 +50,8 @@ #include "QF/va.h" #include "QF/quakefs.h" +#include "QF/scene/transform.h" + #include "snd_internal.h" static int snd_blocked = 0; @@ -252,7 +254,7 @@ s_update_ (void) Called once each time through the main loop */ static void -s_update (struct transform_s *ear, const byte *ambient_sound_level) +s_update (transform_t ear, const byte *ambient_sound_level) { if (!sound_started || (snd_blocked > 0)) return; diff --git a/libs/audio/snd.c b/libs/audio/snd.c index 8cb7d331f..c665e7f72 100644 --- a/libs/audio/snd.c +++ b/libs/audio/snd.c @@ -35,6 +35,8 @@ #include "QF/qargs.h" #include "QF/sys.h" +#include "QF/scene/transform.h" + #include "snd_internal.h" static char *snd_output; @@ -187,7 +189,7 @@ S_PrecacheSound (const char *sample) } VISIBLE void -S_Update (struct transform_s *ear, const byte *ambient_sound_level) +S_Update (transform_t ear, const byte *ambient_sound_level) { if (snd_render_funcs) snd_render_funcs->update (ear, ambient_sound_level); diff --git a/libs/audio/test/testsound.c b/libs/audio/test/testsound.c index f917a4440..8e52bc6b3 100644 --- a/libs/audio/test/testsound.c +++ b/libs/audio/test/testsound.c @@ -46,6 +46,7 @@ #include "QF/zone.h" #include "QF/sound.h" +#include "QF/scene/transform.h" #ifdef _WIN32 # include "winquake.h" @@ -88,7 +89,7 @@ main (int argc, const char *argv[]) while (1) { Cbuf_Execute_Stack (testsound_cbuf); - S_Update (0, 0); + S_Update (nulltransform, 0); usleep(20 * 1000); } Sys_Quit (); diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index 083d955ed..5b352c139 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -41,11 +41,14 @@ #include "QF/render.h" #include "QF/plugin/vid_render.h" //FIXME +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "client/entities.h" #include "client/effects.h" #include "client/particles.h" +#include "client/world.h" void CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size, @@ -115,12 +118,14 @@ CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size, } void -CL_ModelEffects (entity_t *ent, int num, int glow_color, double time) +CL_ModelEffects (entity_t ent, int num, int glow_color, double time) { dlight_t *dl; - model_t *model = ent->renderer.model; - vec4f_t old_origin = ent->old_origin; - vec4f_t ent_origin = Transform_GetWorldPosition (ent->transform); + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); + model_t *model = renderer->model; + vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, cl_world.scene->reg); + vec4f_t ent_origin = Transform_GetWorldPosition (transform); // add automatic particle trails if (model->flags & EF_ROCKET) { @@ -133,21 +138,21 @@ CL_ModelEffects (entity_t *ent, int num, int glow_color, double time) VectorSet (0.9, 0.7, 0.0, dl->color); dl->color[3] = 0.7; } - clp_funcs->RocketTrail (old_origin, ent_origin); + clp_funcs->RocketTrail (*old_origin, ent_origin); } else if (model->flags & EF_GRENADE) - clp_funcs->GrenadeTrail (old_origin, ent_origin); + clp_funcs->GrenadeTrail (*old_origin, ent_origin); else if (model->flags & EF_GIB) - clp_funcs->BloodTrail (old_origin, ent_origin); + clp_funcs->BloodTrail (*old_origin, ent_origin); else if (model->flags & EF_ZOMGIB) - clp_funcs->SlightBloodTrail (old_origin, ent_origin); + clp_funcs->SlightBloodTrail (*old_origin, ent_origin); else if (model->flags & EF_TRACER) - clp_funcs->WizTrail (old_origin, ent_origin); + clp_funcs->WizTrail (*old_origin, ent_origin); else if (model->flags & EF_TRACER2) - clp_funcs->FlameTrail (old_origin, ent_origin); + clp_funcs->FlameTrail (*old_origin, ent_origin); else if (model->flags & EF_TRACER3) - clp_funcs->VoorTrail (old_origin, ent_origin); + clp_funcs->VoorTrail (*old_origin, ent_origin); else if (model->flags & EF_GLOWTRAIL) - clp_funcs->GlowTrail (old_origin, ent_origin, glow_color); + clp_funcs->GlowTrail (*old_origin, ent_origin, glow_color); } void @@ -170,13 +175,14 @@ CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num, } void -CL_EntityEffects (int num, entity_t *ent, entity_state_t *state, double time) +CL_EntityEffects (int num, entity_t ent, entity_state_t *state, double time) { - vec4f_t position = Transform_GetWorldPosition (ent->transform); + transform_t transform = Entity_Transform (ent); + vec4f_t position = Transform_GetWorldPosition (transform); if (state->effects & EF_BRIGHTFIELD) clp_funcs->EntityParticles (position); if (state->effects & EF_MUZZLEFLASH) { - vec4f_t fv = Transform_Forward (ent->transform); + vec4f_t fv = Transform_Forward (transform); CL_MuzzleFlash (position, fv, 16, num, time); } } diff --git a/libs/client/cl_entities.c b/libs/client/cl_entities.c index 01ffd7d6b..12a56a96d 100644 --- a/libs/client/cl_entities.c +++ b/libs/client/cl_entities.c @@ -39,8 +39,13 @@ #include "QF/plugin/vid_render.h" //FIXME +#include "QF/scene/component.h" +#include "QF/scene/entity.h" +#include "QF/scene/scene.h" + #include "client/entities.h" #include "client/temp_entities.h" +#include "client/world.h" entitystateset_t cl_static_entities = DARRAY_STATIC_INIT (32); @@ -353,7 +358,7 @@ vec3_t ent_colormod[256] = { }; void -CL_TransformEntity (entity_t *ent, float scale, const vec3_t angles, +CL_TransformEntity (entity_t ent, float scale, const vec3_t angles, vec4f_t position) { vec4f_t rotation; @@ -364,7 +369,9 @@ CL_TransformEntity (entity_t *ent, float scale, const vec3_t angles, } else { vec3_t ang; VectorCopy (angles, ang); - if (ent->renderer.model && ent->renderer.model->type == mod_alias) { + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + ent.reg); + if (renderer->model && renderer->model->type == mod_alias) { // stupid quake bug // why, oh, why, do alias models pitch in the opposite direction // to everything else? @@ -372,5 +379,6 @@ CL_TransformEntity (entity_t *ent, float scale, const vec3_t angles, } AngleQuat (ang, (vec_t*)&rotation);//FIXME } - Transform_SetLocalTransform (ent->transform, scalevec, rotation, position); + transform_t transform = Entity_Transform (ent); + Transform_SetLocalTransform (transform, scalevec, rotation, position); } diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 74e5374bc..47e125509 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -45,6 +45,8 @@ #include "QF/sound.h" #include "QF/plugin/vid_render.h" //FIXME + // +#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" @@ -56,7 +58,7 @@ typedef struct tent_s { struct tent_s *next; - entity_t *ent; + entity_t ent; } tent_t; typedef struct { @@ -153,17 +155,22 @@ CL_TEnts_Init (void) } void -CL_Init_Entity (entity_t *ent) +CL_Init_Entity (entity_t ent) { - memset (&ent->animation, 0, sizeof (ent->animation)); - memset (&ent->visibility, 0, sizeof (ent->visibility)); - memset (&ent->renderer, 0, sizeof (ent->renderer)); - ent->active = 1; - ent->old_origin = (vec4f_t) {}; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); + byte *active = Ent_GetComponent (ent.id, scene_active, cl_world.scene->reg); + vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, cl_world.scene->reg); + memset (animation, 0, sizeof (*animation)); + memset (visibility, 0, sizeof (*visibility)); + memset (renderer, 0, sizeof (*renderer)); + *active = 1; + *old_origin = (vec4f_t) {0, 0, 0, 1}; - ent->renderer.skin = 0; - QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod); - ent->animation.pose1 = ent->animation.pose2 = -1; + renderer->skin = 0; + QuatSet (1.0, 1.0, 1.0, 1.0, renderer->colormod); + animation->pose1 = animation->pose2 = -1; } static tent_t * @@ -221,7 +228,6 @@ beam_clear (beam_t *b) for (t = b->tents; t; t = t->next) { R_RemoveEfrags (t->ent); - t->ent->visibility.efrag = 0; } free_temp_entities (b->tents); b->tents = 0; @@ -229,7 +235,7 @@ beam_clear (beam_t *b) } static inline void -beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx) +beam_setup (beam_t *b, qboolean settransform, double time, TEntContext_t *ctx) { tent_t *tent; float d; @@ -268,15 +274,17 @@ beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx) vec4f_t position = org + d * dist; d += 1.0; - tent->ent->renderer.model = b->model; - if (transform) { + transform_t transform = Entity_Transform (tent->ent); + renderer_t *renderer = Ent_GetComponent (tent->ent.id, scene_renderer, cl_world.scene->reg); + renderer->model = b->model; + if (settransform) { seed = seed * BEAM_SEED_PRIME; - Transform_SetLocalTransform (tent->ent->transform, scale, + Transform_SetLocalTransform (transform, scale, qmulf (rotation, beam_rolls[seed % 360]), position); } else { - Transform_SetLocalPosition (tent->ent->transform, position); + Transform_SetLocalPosition (transform, position); } R_AddEfrags (&cl_world.scene->worldmodel->brush, tent->ent); } @@ -382,9 +390,10 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, if (!cl_spr_explod->cache.data) { cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true); } - ex->tent->ent->renderer.model = cl_spr_explod; - Transform_SetLocalPosition (ex->tent->ent->transform,//FIXME - (vec4f_t) {VectorExpand (position), 1}); + transform_t transform = Entity_Transform (ex->tent->ent); + renderer_t *renderer = Ent_GetComponent (ex->tent->ent.id, scene_renderer, cl_world.scene->reg); + renderer->model = cl_spr_explod; + Transform_SetLocalPosition (transform, position); break; case TE_Explosion2: MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME @@ -606,7 +615,8 @@ CL_UpdateBeams (double time, TEntContext_t *ctx) // add new entities for the lightning for (t = b->tents; t; t = t->next) { seed = seed * BEAM_SEED_PRIME; - Transform_SetLocalRotation (t->ent->transform, + transform_t transform = Entity_Transform (t->ent); + Transform_SetLocalRotation (transform, qmulf (b->rotation, beam_rolls[seed % 360])); } @@ -619,16 +629,18 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) int f; tent_obj_t **to; explosion_t *ex; - entity_t *ent; + entity_t ent; for (to = &cl_explosions; *to; ) { ex = &(*to)->to.ex; ent = ex->tent->ent; f = 10 * (time - ex->start); - if (f >= ent->renderer.model->numframes) { + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); + if (f >= renderer->model->numframes) { tent_obj_t *_to; R_RemoveEfrags (ent); - ent->visibility.efrag = 0; free_temp_entities (ex->tent); _to = *to; *to = _to->next; @@ -637,8 +649,8 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) } to = &(*to)->next; - ent->animation.frame = f; - if (!ent->visibility.efrag) { + animation->frame = f; + if (!visibility->efrag) { R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } @@ -681,7 +693,6 @@ CL_ClearProjectiles (void) for (tent = cl_projectiles; tent; tent = tent->next) { R_RemoveEfrags (tent->ent); - tent->ent->visibility.efrag = 0; } free_temp_entities (cl_projectiles); cl_projectiles = 0; @@ -697,7 +708,7 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) tent_t *head = 0, **tail = &head; byte bits[6]; int i, c, j, num; - entity_t *pr; + entity_t pr; vec4f_t position = { 0, 0, 0, 1 }; vec3_t angles; @@ -718,8 +729,9 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) tail = &tent->next; pr = tent->ent; - pr->renderer.model = cl_spike; - pr->renderer.skin = 0; + renderer_t *renderer = Ent_GetComponent (pr.id, scene_renderer, cl_world.scene->reg); + renderer->model = cl_spike; + renderer->skin = 0; position[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096; position[1] = (((bits[1] >> 4) + (bits[2] << 4)) << 1) - 4096; position[2] = ((bits[3] + ((bits[4] & 15) << 8)) << 1) - 4096; @@ -728,7 +740,7 @@ CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) angles[2] = 0; CL_TransformEntity (tent->ent, 1, angles, position); - R_AddEfrags (&cl_world.scene->worldmodel->brush, tent->ent); + R_AddEfrags (&cl_world.scene->worldmodel->brush, pr); } *tail = cl_projectiles; diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index b163efa65..4233d8cd7 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -34,8 +34,9 @@ #include "QF/screen.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/transform.h" +#include "QF/scene/scene.h" #include "QF/simd/vec4f.h" #include "compat.h" @@ -672,7 +673,8 @@ CalcGunAngle (viewstate_t *vs) { vec4f_t rotation = Transform_GetWorldRotation (vs->camera_transform); //FIXME make child of camera - Transform_SetWorldRotation (vs->weapon_entity->transform, rotation); + transform_t wep_form = Entity_Transform (vs->weapon_entity); + Transform_SetWorldRotation (wep_form, rotation); } static void @@ -726,9 +728,9 @@ V_AddIdle (viewstate_t *vs) Transform_SetWorldRotation (vs->camera_transform, qmulf (rot, rotation)); // counter-rotate the weapon - rot = qmulf (qconjf (rot), - Transform_GetWorldRotation (vs->weapon_entity->transform)); - Transform_SetWorldRotation (vs->weapon_entity->transform, rot); + transform_t wep_form = Entity_Transform (vs->weapon_entity); + rot = qmulf (qconjf (rot), Transform_GetWorldRotation (wep_form)); + Transform_SetWorldRotation (wep_form, rot); } /* @@ -765,18 +767,20 @@ static void V_CalcIntermissionRefdef (viewstate_t *vs) { // vs->player_entity is the player model (visible when out of body) - entity_t *ent = vs->player_entity; - entity_t *view; + entity_t ent = vs->player_entity; + entity_t view; float old; - vec4f_t origin = Transform_GetWorldPosition (ent->transform); - vec4f_t rotation = Transform_GetWorldRotation (ent->transform); + transform_t transform = Entity_Transform (ent); + vec4f_t origin = Transform_GetWorldPosition (transform); + vec4f_t rotation = Transform_GetWorldRotation (transform); // view is the weapon model (visible only from inside body) view = vs->weapon_entity; Transform_SetWorldPosition (vs->camera_transform, origin); Transform_SetWorldRotation (vs->camera_transform, rotation); - view->renderer.model = NULL; + renderer_t *renderer = Ent_GetComponent (view.id, scene_renderer, cl_world.scene->reg); + renderer->model = NULL; // always idle in intermission old = v_idlescale; @@ -789,13 +793,16 @@ static void V_CalcRefdef (viewstate_t *vs) { // view is the weapon model (visible only from inside body) - entity_t *view = vs->weapon_entity; + entity_t view = vs->weapon_entity; float bob; static float oldz = 0; vec4f_t forward = {}, right = {}, up = {}; vec4f_t origin = vs->player_origin; vec_t *viewangles = vs->player_angles; + renderer_t *renderer = Ent_GetComponent (view.id, scene_renderer, cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (view.id, scene_animation, cl_world.scene->reg); + V_DriftPitch (vs); bob = V_CalcBob (vs); @@ -851,12 +858,12 @@ V_CalcRefdef (viewstate_t *vs) if (vs->flags & (VF_GIB | VF_DEAD)) { model = NULL; } - if (view->renderer.model != model) { - view->animation.pose2 = -1; + if (renderer->model != model) { + animation->pose2 = -1; } - view->renderer.model = model; - view->animation.frame = vs->weaponframe; - view->renderer.skin = 0; + renderer->model = model; + animation->frame = vs->weaponframe; + renderer->skin = 0; // set up the refresh position Transform_SetWorldRotation (vs->camera_transform, @@ -954,7 +961,7 @@ V_Init (viewstate_t *viewstate) "Used when you are underwater, hit, have the Ring of " "Shadows, or Quad Damage. (v_cshift r g b intensity)"); - viewstate->camera_transform = Transform_New (cl_world.scene, 0); + viewstate->camera_transform = Transform_New (cl_world.scene, nulltransform); } void diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index 4d17b0f5c..6c0595515 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -46,6 +46,7 @@ #include "QF/progs.h" #include "QF/msg.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/light.h" #include "QF/scene/scene.h" @@ -105,7 +106,7 @@ CL_ParseBaseline (qmsg_t *msg, entity_state_t *baseline, int version) void CL_ParseStatic (qmsg_t *msg, int version) { - entity_t *ent; + entity_t ent; entity_state_t es; ent = Scene_CreateEntity (cl_world.scene); @@ -114,10 +115,13 @@ CL_ParseStatic (qmsg_t *msg, int version) CL_ParseBaseline (msg, &es, version); DARRAY_APPEND (&cl_static_entities, es); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); + // copy it to the current state - ent->renderer.model = cl_world.models.a[es.modelindex]; - ent->animation.frame = es.frame; - ent->renderer.skinnum = es.skinnum; + renderer->model = cl_world.models.a[es.modelindex]; + animation->frame = es.frame; + renderer->skinnum = es.skinnum; CL_TransformEntity (ent, es.scale / 16.0, es.angles, es.origin); diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index b19b3003c..09d81bcce 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -44,6 +44,7 @@ #include "QF/plugin/vid_render.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/light.h" #include "QF/scene/scene.h" @@ -110,38 +111,38 @@ rua_scene_index (rua_scene_resources_t *res, rua_scene_t *scene) return PR_RESINDEX (res->scene_map, scene); } -static entity_t * __attribute__((pure)) +static entity_t __attribute__((pure)) rua__entity_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { pr_ulong_t scene_id = id & 0xffffffff; - entity_t *ent = 0; + entity_t ent = nullentity; rua_scene_t *scene = rua__scene_get (res, scene_id, name); if (scene) { pr_int_t entity_id = id >> 32; - ent = Scene_GetEntity (scene->scene, entity_id); + ent.id = entity_id; } - if (!ent) { + if (!Entity_Valid (ent)) { PR_RunError (res->pr, "invalid entity passed to %s", name + 3); } return ent; } #define rua_entity_get(res, id) rua__entity_get(res, id, __FUNCTION__) -static transform_t * __attribute__((pure)) +static transform_t __attribute__((pure)) rua__transform_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) { pr_ulong_t scene_id = id & 0xffffffff; - transform_t *transform = 0; + transform_t transform = nulltransform; rua_scene_t *scene = rua_scene_get (res, scene_id); if (scene) { - pr_int_t transform_id = id >> 32; - transform = Scene_GetTransform (scene->scene, transform_id); + entity_t transform_id = { .reg = scene->scene->reg, .id = id >> 32 }; + transform = Entity_Transform (transform_id); } - if (!transform) { + if (!Transform_Valid (transform)) { PR_RunError (res->pr, "invalid transform passed to %s", name + 3); } return transform; @@ -245,8 +246,8 @@ bi_Scene_CreateEntity (progs_t *pr, void *_res) rua_scene_resources_t *res = _res; pr_ulong_t scene_id = P_ULONG (pr, 0); rua_scene_t *scene = rua_scene_get (res, scene_id); - entity_t *ent = Scene_CreateEntity (scene->scene); - R_ULONG (pr) = MAKE_ID (ent->id, scene_id); + entity_t ent = Scene_CreateEntity (scene->scene); + R_ULONG (pr) = MAKE_ID (ent.id, scene_id); } static void @@ -254,12 +255,12 @@ bi_Scene_DestroyEntity (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; pr_ulong_t id = P_ULONG (pr, 0); - entity_t *ent = rua_entity_get (res, id); + entity_t ent = rua_entity_get (res, id); pr_ulong_t scene_id = id & 0xffffffff; + rua_scene_t *scene = rua_scene_get (res, scene_id); R_RemoveEfrags (ent); // bad scene caught above - rua_scene_t *scene = rua_scene_get (res, scene_id); Scene_DestroyEntity (scene->scene, ent); } @@ -282,12 +283,10 @@ bi_Scene_SetLighting (progs_t *pr, void *_res) static void bi_Entity_GetTransform (progs_t *pr, void *_res) { - rua_scene_resources_t *res = _res; pr_ulong_t ent_id = P_ULONG (pr, 0); - entity_t *ent = rua_entity_get (res, ent_id); - // ent_id contains scene id - R_ULONG (pr) = MAKE_ID (ent->transform->ref.id, ent_id); + // ent_id is used to fetch the transform every time + R_ULONG (pr) = ent_id; } static void @@ -296,14 +295,15 @@ bi_Entity_SetModel (progs_t *pr, void *_res) rua_scene_resources_t *res = _res; pr_ulong_t ent_id = P_ULONG (pr, 0); pr_int_t model_id = P_INT (pr, 1); - entity_t *ent = rua_entity_get (res, ent_id); + entity_t ent = rua_entity_get (res, ent_id); model_t *model = Model_GetModel (pr, model_id); pr_ulong_t scene_id = ent_id & 0xffffffff; // bad scene caught above rua_scene_t *scene = rua_scene_get (res, scene_id); R_RemoveEfrags (ent); - ent->renderer.model = model; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, scene->scene->reg); + renderer->model = model; R_AddEfrags (&scene->scene->worldmodel->brush, ent); } @@ -311,7 +311,7 @@ static void bi_Transform_ChildCount (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_UINT (pr) = Transform_ChildCount (transform); } @@ -320,18 +320,19 @@ static void bi_Transform_GetChild (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); - transform_t *child = Transform_GetChild (transform, P_UINT (pr, 2)); - - R_UINT (pr) = child ? child->ref.id : 0; + pr_ulong_t transform_id = P_ULONG (pr, 0); + transform_t transform = rua_transform_get (res, transform_id); + transform_t child = Transform_GetChild (transform, P_UINT (pr, 2)); + R_ULONG (pr) = Transform_Valid (child) ? MAKE_ID (child.id, transform_id) + : 0; } static void bi_Transform_SetParent (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); - transform_t *parent = rua_transform_get (res, P_ULONG (pr, 1)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t parent = rua_transform_get (res, P_ULONG (pr, 1)); rua_scene_t *scene = rua_scene_get (res, P_ULONG (pr, 1)); Transform_SetParent (scene->scene, transform, parent); @@ -342,18 +343,19 @@ bi_Transform_GetParent (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; pr_ulong_t transform_id = P_ULONG (pr, 0); - transform_t *transform = rua_transform_get (res, transform_id); - transform_t *parent = Transform_GetParent (transform); + transform_t transform = rua_transform_get (res, transform_id); + transform_t parent = Transform_GetParent (transform); // transform_id contains scene id - R_ULONG (pr) = parent ? MAKE_ID (parent->ref.id, transform_id) : 0; + R_ULONG (pr) = Transform_Valid (parent) ? MAKE_ID (parent.id, transform_id) + : 0; } static void bi_Transform_SetTag (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); pr_uint_t tag = P_UINT (pr, 2); Transform_SetTag (transform, tag); } @@ -362,7 +364,7 @@ static void bi_Transform_GetTag (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_UINT (pr) = Transform_GetTag (transform); } @@ -371,7 +373,7 @@ static void bi_Transform_GetLocalMatrix (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetLocalMatrix (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -379,7 +381,7 @@ static void bi_Transform_GetLocalInverse (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetLocalInverse (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -387,7 +389,7 @@ static void bi_Transform_GetWorldMatrix (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetWorldMatrix (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -395,7 +397,7 @@ static void bi_Transform_GetWorldInverse (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_GetWorldInverse (transform, &R_PACKED (pr, pr_vec4_t)); } @@ -403,7 +405,7 @@ static void bi_Transform_SetLocalPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_SetLocalPosition (transform, P_PACKED (pr, pr_vec4_t, 1)); } @@ -411,7 +413,7 @@ static void bi_Transform_GetLocalPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalPosition (transform); } @@ -419,7 +421,7 @@ static void bi_Transform_SetLocalRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_SetLocalRotation (transform, P_PACKED (pr, pr_vec4_t, 1)); } @@ -427,7 +429,7 @@ static void bi_Transform_GetLocalRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalRotation (transform); } @@ -435,7 +437,7 @@ static void bi_Transform_SetLocalScale (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_SetLocalScale (transform, P_PACKED (pr, pr_vec4_t, 1)); } @@ -443,7 +445,7 @@ static void bi_Transform_GetLocalScale (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetLocalScale (transform); } @@ -451,7 +453,7 @@ static void bi_Transform_SetWorldPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_SetWorldPosition (transform, P_PACKED (pr, pr_vec4_t, 1)); } @@ -459,7 +461,7 @@ static void bi_Transform_GetWorldPosition (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldPosition (transform); } @@ -467,7 +469,7 @@ static void bi_Transform_SetWorldRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_SetWorldRotation (transform, P_PACKED (pr, pr_vec4_t, 1)); } @@ -475,7 +477,7 @@ static void bi_Transform_GetWorldRotation (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldRotation (transform); } @@ -483,7 +485,7 @@ static void bi_Transform_GetWorldScale (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_GetWorldScale (transform); } @@ -491,7 +493,7 @@ static void bi_Transform_SetLocalTransform (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); Transform_SetLocalTransform (transform, P_PACKED (pr, pr_vec4_t, 1), P_PACKED (pr, pr_vec4_t, 2), P_PACKED (pr, pr_vec4_t, 3)); } @@ -500,7 +502,7 @@ static void bi_Transform_Forward (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_Forward (transform); } @@ -508,7 +510,7 @@ static void bi_Transform_Right (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_Right (transform); } @@ -516,7 +518,7 @@ static void bi_Transform_Up (progs_t *pr, void *_res) { rua_scene_resources_t *res = _res; - transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0)); + transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); R_PACKED (pr, pr_vec4_t) = Transform_Up (transform); } diff --git a/libs/scene/camera.c b/libs/scene/camera.c index 0909f66f0..adc2c787b 100644 --- a/libs/scene/camera.c +++ b/libs/scene/camera.c @@ -32,6 +32,7 @@ #endif #include "QF/scene/camera.h" +#include "QF/scene/component.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" @@ -40,10 +41,8 @@ void Camera_GetViewMatrix (const camera_t *camera, mat4f_t view) { - scene_resources_t *res = camera->scene->resources; - transform_t *transform = (transform_t *) PR_RESGET (res->transforms, camera->transform); - vec4f_t rotation = Transform_GetWorldRotation (transform); - vec4f_t position = Transform_GetWorldPosition (transform); + vec4f_t rotation = Transform_GetWorldRotation (camera->transform); + vec4f_t position = Transform_GetWorldPosition (camera->transform); mat4fquat (view, qconjf (rotation)); // qconjf negates xyz but leaves w alone, which is what we want for // inverting the translation (essentially, rotation+position form a diff --git a/libs/scene/component.c b/libs/scene/component.c index 0860896ce..31048f667 100644 --- a/libs/scene/component.c +++ b/libs/scene/component.c @@ -68,7 +68,7 @@ ECS_RegisterComponents (ecs_registry_t *registry, } } -VISIBLE void +VISIBLE void* Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) { uint32_t id = Ent_Index (ent); @@ -76,7 +76,7 @@ Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) if (pool->sparse[id] < pool->count) { //Sys_Error ("Ent_AddComponent: component %s already on entity %x\n", // registry->components[i].name, ent); - return; + return 0; } if (pool->count == pool->max_count) { pool->max_count += COMP_GROW; @@ -88,7 +88,8 @@ Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) uint32_t ind = pool->count++; pool->sparse[id] = ind; pool->dense[ind] = ent; - Component_CreateElements (®istry->components[comp], pool->data, ind, 1); + return Component_CreateElements (®istry->components[comp], pool->data, + ind, 1); } VISIBLE void diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 69d9acf8c..f5e62f07c 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -41,8 +41,7 @@ #include "scn_internal.h" -static component_t ref_component = { .size = sizeof (hierref_t *) }; -static component_t entity_component = { .size = sizeof (entity_t *) }; +static component_t ent_component = { .size = sizeof (uint32_t) }; static component_t childCount_component = { .size = sizeof (uint32_t) }; static component_t childIndex_component = { .size = sizeof (uint32_t) }; static component_t parentIndex_component = { .size = sizeof (uint32_t) }; @@ -51,10 +50,10 @@ static void hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { + ecs_registry_t *reg = hierarchy->scene->reg; for (size_t i = start; i < hierarchy->num_objects; i++) { - if (hierarchy->ref[i]) { - hierarchy->ref[i]->index += offset; - } + hierref_t *ref = Ent_GetComponent (hierarchy->ent[i], scene_href, reg); + ref->index += offset; } } @@ -84,10 +83,8 @@ Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count) new_max += 15; new_max &= ~15; - Component_ResizeArray (&ref_component, - (void **) &hierarchy->ref, new_max); - Component_ResizeArray (&entity_component, - (void **) &hierarchy->entity, new_max); + Component_ResizeArray (&ent_component, + (void **) &hierarchy->ent, new_max); Component_ResizeArray (&childCount_component, (void **) &hierarchy->childCount, new_max); Component_ResizeArray (&childIndex_component, @@ -111,10 +108,8 @@ hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t count) hierarchy->num_objects += count; uint32_t dstIndex = index + count; count = hierarchy->num_objects - index - count; - Component_MoveElements (&ref_component, - hierarchy->ref, dstIndex, index, count); - Component_MoveElements (&entity_component, - hierarchy->entity, dstIndex, index, count); + Component_MoveElements (&ent_component, + hierarchy->ent, dstIndex, index, count); Component_MoveElements (&childCount_component, hierarchy->childCount, dstIndex, index, count); Component_MoveElements (&childIndex_component, @@ -137,10 +132,8 @@ hierarchy_close (hierarchy_t *hierarchy, uint32_t index, uint32_t count) hierarchy->num_objects -= count; uint32_t srcIndex = index + count; count = hierarchy->num_objects - index; - Component_MoveElements (&ref_component, - hierarchy->ref, index, srcIndex, count); - Component_MoveElements (&entity_component, - hierarchy->entity, index, srcIndex, count); + Component_MoveElements (&ent_component, + hierarchy->ent, index, srcIndex, count); Component_MoveElements (&childCount_component, hierarchy->childCount, index, srcIndex, count); Component_MoveElements (&childIndex_component, @@ -158,20 +151,20 @@ static void hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstIndex, uint32_t srcIndex, uint32_t count) { - Component_CopyElements (&ref_component, - dst->ref, dstIndex, - src->ref, srcIndex, count); - Component_CopyElements (&entity_component, - dst->entity, dstIndex, - src->entity, srcIndex, count); + ecs_registry_t *reg = dst->scene->reg; + Component_CopyElements (&ent_component, + dst->ent, dstIndex, + src->ent, srcIndex, count); // Actually move (as in C++ move semantics) source hierarchy object // references so that their indices do not get updated when the objects // are removed from the source hierarcy - memset (&src->ref[srcIndex], 0, count * sizeof(dst->ref[0])); + memset (&src->ent[srcIndex], 0, count * sizeof(dst->ent[0])); for (uint32_t i = 0; i < count; i++) { - dst->ref[dstIndex + i]->hierarchy = dst; - dst->ref[dstIndex + i]->index = dstIndex + i; + uint32_t ent = dst->ent[dstIndex + i]; + hierref_t *ref = Ent_GetComponent (ent, scene_href, reg); + ref->hierarchy = dst; + ref->index = dstIndex + i; } for (uint32_t i = 0; i < dst->type->num_components; i++) { Component_CopyElements (&dst->type->components[i], @@ -184,7 +177,7 @@ static void hierarchy_init (hierarchy_t *dst, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t count) { - memset (&dst->ref[index], 0, count * sizeof(dst->ref[0])); + memset (&dst->ent[index], nullent, count * sizeof(uint32_t)); for (uint32_t i = 0; i < count; i++) { dst->parentIndex[index + i] = parentIndex; @@ -207,7 +200,7 @@ hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, // The newly added objects are always last children of the parent // object insertIndex = dst->childIndex[dstParent] + dst->childCount[dstParent]; - // By design, all of a object's children are in one contiguous block, + // By design, all of an object's children are in one contiguous block, // and the blocks of children for each object are ordered by their // parents. Thus the child index of each object increases monotonically // for each child index in the array, regardless of the level of the owning @@ -373,11 +366,7 @@ Hierarchy_Delete (hierarchy_t *hierarchy) } *hierarchy->prev = hierarchy->next; - scene_resources_t *res = hierarchy->scene->resources; - for (uint32_t i = 0; i < hierarchy->num_objects; i++) { - PR_RESFREE (res->transforms, hierarchy->ref[i]); - } - free (hierarchy->ref); + free (hierarchy->ent); free (hierarchy->childCount); free (hierarchy->childIndex); free (hierarchy->parentIndex); @@ -386,21 +375,25 @@ Hierarchy_Delete (hierarchy_t *hierarchy) } free (hierarchy->components); + scene_resources_t *res = hierarchy->scene->resources; PR_RESFREE (res->hierarchies, hierarchy); } hierarchy_t * Hierarchy_Copy (scene_t *scene, const hierarchy_t *src) { + ecs_registry_t *dstReg = scene->reg; + //ecs_registry_t *srcReg = src->scene->reg; hierarchy_t *dst = Hierarchy_New (scene, src->type, 0); size_t count = src->num_objects; Hierarchy_Reserve (dst, count); for (size_t i = 0; i < count; i++) { - dst->ref[i] = __transform_alloc (scene); - dst->ref[i]->hierarchy = dst; - dst->ref[i]->index = i; + dst->ent[i] = ECS_NewEntity (dstReg); + hierref_t *ref = Ent_AddComponent (dst->ent[i], scene_href, dstReg); + ref->hierarchy = dst; + ref->index = i; } Component_CopyElements (&childCount_component, diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 54f3f4bc9..1b514b33a 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -36,16 +36,63 @@ #endif #include "QF/mathlib.h" -#include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" #include "QF/model.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "scn_internal.h" +static void +create_active (void *_active) +{ + byte *active = _active; + *active = 1; +} + +static void +create_old_origin (void *_old_origin) +{ + vec4f_t *old_origin = _old_origin; + *old_origin = (vec4f_t) {0, 0, 0, 1}; +} + +static const component_t scene_components[] = { + [scene_href] = { + .size = sizeof (hierref_t), + .create = 0,//create_href, + .name = "href", + }, + [scene_animation] = { + .size = sizeof (animation_t), + .create = 0,//create_animation, + .name = "animation", + }, + [scene_visibility] = { + .size = sizeof (visibility_t), + .create = 0,//create_visibility, + .name = "visibility", + }, + [scene_renderer] = { + .size = sizeof (renderer_t), + .create = 0,//create_renderer, + .name = "renderer", + }, + [scene_active] = { + .size = sizeof (byte), + .create = create_active, + .name = "active", + }, + [scene_old_origin] = { + .size = sizeof (vec4f_t), + .create = create_old_origin, + .name = "old_origin", + }, +}; + static byte empty_visdata[] = { 0x01 }; static mleaf_t empty_leafs[] = { @@ -104,11 +151,12 @@ static model_t empty_world = { scene_t * Scene_NewScene (void) { - scene_t *scene; - scene_resources_t *res; + scene_t *scene = calloc (1, sizeof (scene_t)); - scene = calloc (1, sizeof (scene_t)); - res = calloc (1, sizeof (scene_resources_t)); + scene->reg = ECS_NewRegistry (); + ECS_RegisterComponents (scene->reg, scene_components, scene_num_components); + + scene_resources_t *res = calloc (1, sizeof (scene_resources_t)); *(scene_resources_t **)&scene->resources = res; scene->worldmodel = &empty_world; @@ -119,90 +167,38 @@ Scene_NewScene (void) void Scene_DeleteScene (scene_t *scene) { - Scene_FreeAllEntities (scene); - - scene_resources_t *res = scene->resources; - for (unsigned i = 0; i < res->entities._size; i++) { - free (res->entities._map[i]); - } - free (res->entities._map); + ECS_DelRegistry (scene->reg); free (scene->resources); free (scene); } -entity_t * +entity_t Scene_CreateEntity (scene_t *scene) { - scene_resources_t *res = scene->resources; + transform_t trans = Transform_New (scene, nulltransform); + uint32_t id = trans.id; - entity_t *ent = PR_RESNEW (res->entities); - ent->transform = Transform_New (scene, 0); - ent->id = PR_RESINDEX (res->entities, ent); + Ent_AddComponent (id, scene_href, scene->reg); + Ent_AddComponent (id, scene_animation, scene->reg); + Ent_AddComponent (id, scene_visibility, scene->reg); + Ent_AddComponent (id, scene_renderer, scene->reg); + Ent_AddComponent (id, scene_active, scene->reg); + Ent_AddComponent (id, scene_old_origin, scene->reg); - hierarchy_t *h = ent->transform->ref.hierarchy; - h->entity[ent->transform->ref.index] = ent; + renderer_t *renderer = Ent_GetComponent (id, scene_renderer, scene->reg); + QuatSet (1, 1, 1, 1, renderer->colormod); - QuatSet (1, 1, 1, 1, ent->renderer.colormod); - - return ent; -} - -entity_t * -Scene_GetEntity (scene_t *scene, int id) -{ - scene_resources_t *res = scene->resources; - return PR_RESGET (res->entities, id); -} - -static void -destroy_entity (scene_t *scene, entity_t *ent) -{ - scene_resources_t *res = scene->resources; - // ent->transform will be trampled by the loop below - transform_t *transform = ent->transform; - - // Transform_Delete takes care of all hierarchy stuff (transforms - // themselves, name strings, hierarchy table) - hierarchy_t *h = transform->ref.hierarchy; - for (size_t i = 0; i < h->num_objects; i++) { - entity_t *e = h->entity[0]; - e->transform = 0; - PR_RESFREE (res->entities, ent); - } - Transform_Delete (scene, transform); + return (entity_t) { .reg = scene->reg, .id = id }; } void -Scene_DestroyEntity (scene_t *scene, entity_t *ent) +Scene_DestroyEntity (scene_t *scene, entity_t ent) { - scene_resources_t *res = scene->resources; - - if (PR_RESGET (res->entities, ent->id) != ent) { - Sys_Error ("Scene_DestroyEntity: entity not owned by scene"); - } - // pull the transform out of the hierarchy to make it easier to destory - // all the child entities - Transform_SetParent (scene, ent->transform, 0); - destroy_entity (scene, ent); + ECS_DelEntity (scene->reg, ent.id); } void Scene_FreeAllEntities (scene_t *scene) { - while (scene->hierarchies) { - hierarchy_t *h = scene->hierarchies; - // deleting the root entity deletes all child entities - entity_t *ent = h->entity[0]; - destroy_entity (scene, ent); - } - scene_resources_t *res = scene->resources; - PR_RESRESET (res->entities); -} - -transform_t * -Scene_GetTransform (scene_t *scene, int id) -{ - scene_resources_t *res = scene->resources; - return (transform_t *) PR_RESGET (res->transforms, id); } diff --git a/libs/scene/test/test-hierarchy.c b/libs/scene/test/test-hierarchy.c index b7c7a6ec3..968c83494 100644 --- a/libs/scene/test/test-hierarchy.c +++ b/libs/scene/test/test-hierarchy.c @@ -42,15 +42,18 @@ mat4_equal (const mat4f_t a, const mat4f_t b) } static int -check_hierarchy_size (hierarchy_t *h, uint32_t size) +check_hierarchy_size (transform_t t, uint32_t size) { + hierarchy_t *h = Transform_GetRef (t)->hierarchy; if (h->num_objects != size) { printf ("hierarchy does not have exactly %u transform\n", size); return 0; } char **name = h->components[transform_type_name]; + ecs_registry_t *reg = h->scene->reg; for (uint32_t i = 0; i < h->num_objects; i++) { - if (h->ref[i]->hierarchy != h) { + hierref_t *ref = Ent_GetComponent (h->ent[i], scene_href, reg); + if (ref->hierarchy != h) { printf ("transform %d (%s) does not point to hierarchy\n", i, name[i]); } @@ -59,22 +62,25 @@ check_hierarchy_size (hierarchy_t *h, uint32_t size) } static void -dump_hierarchy (hierarchy_t *h) +dump_hierarchy (transform_t t) { + hierarchy_t *h = Transform_GetRef (t)->hierarchy; char **name = h->components[transform_type_name]; + ecs_registry_t *reg = h->scene->reg; for (uint32_t i = 0; i < h->num_objects; i++) { - printf ("%2d: %5s %2u %2u %2u %2u\n", i, name[i], - h->ref[i]->index, h->parentIndex[i], + hierref_t *ref = Ent_GetComponent (h->ent[i], scene_href, reg); + printf ("%2d: %5s %2u %2u %2u %2u %2u\n", i, name[i], h->ent[i], + ref->index, h->parentIndex[i], h->childIndex[i], h->childCount[i]); } puts (""); } static int -check_indices (transform_t *transform, uint32_t index, uint32_t parentIndex, +check_indices (transform_t transform, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t childCount) { - __auto_type ref = &transform->ref; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; char **name = h->components[transform_type_name]; if (ref->index != index) { @@ -104,14 +110,18 @@ check_indices (transform_t *transform, uint32_t index, uint32_t parentIndex, static int test_single_transform (void) { - transform_t *transform = Transform_New (scene, 0); + transform_t transform = Transform_New (scene, (transform_t) {}); hierarchy_t *h; - if (!transform) { + if (!transform.reg || transform.id == nullent) { printf ("Transform_New returned null\n"); return 1; } - if (!(h = transform->ref.hierarchy)) { + if (!Transform_GetRef (transform)) { + printf ("Transform_GetRef returned null\n"); + return 1; + } + if (!(h = Transform_GetRef (transform)->hierarchy)) { printf ("New transform has no hierarchy\n"); return 1; } @@ -121,7 +131,7 @@ test_single_transform (void) mat4f_t *worldInverse = h->components[transform_type_worldInverse]; vec4f_t *localRotation = h->components[transform_type_localRotation]; vec4f_t *localScale = h->components[transform_type_localScale]; - if (!check_hierarchy_size (h, 1)) { return 1; } + if (!check_hierarchy_size (transform, 1)) { return 1; } if (!check_indices (transform, 0, nullent, 1, 0)) { return 1; } if (!mat4_equal (localMatrix[0], identity) @@ -139,7 +149,7 @@ test_single_transform (void) } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (transform->ref.hierarchy); + Hierarchy_Delete (h); return 0; } @@ -147,20 +157,21 @@ test_single_transform (void) static int test_parent_child_init (void) { - transform_t *parent = Transform_New (scene, 0); - transform_t *child = Transform_New (scene, parent); + transform_t parent = Transform_New (scene, (transform_t) {}); + transform_t child = Transform_New (scene, parent); - if (parent->ref.hierarchy != child->ref.hierarchy) { + if (Transform_GetRef (parent)->hierarchy + != Transform_GetRef (child)->hierarchy) { printf ("parent and child transforms have separate hierarchies\n"); return 1; } - if (!check_hierarchy_size (parent->ref.hierarchy, 2)) { return 1; } + if (!check_hierarchy_size (parent, 2)) { return 1; } if (!check_indices (parent, 0, nullent, 1, 1)) { return 1; } if (!check_indices (child, 1, 0, 2, 0)) { return 1; } - hierarchy_t *h = parent->ref.hierarchy; + hierarchy_t *h = Transform_GetRef (parent)->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; mat4f_t *localInverse = h->components[transform_type_localInverse]; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; @@ -196,7 +207,7 @@ test_parent_child_init (void) } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (parent->ref.hierarchy); + Hierarchy_Delete (Transform_GetRef (parent)->hierarchy); return 0; } @@ -204,8 +215,8 @@ test_parent_child_init (void) static int test_parent_child_setparent (void) { - transform_t *parent = Transform_New (scene, 0); - transform_t *child = Transform_New (scene, 0); + transform_t parent = Transform_New (scene, (transform_t) {}); + transform_t child = Transform_New (scene, (transform_t) {}); Transform_SetName (parent, "parent"); Transform_SetName (child, "child"); @@ -213,25 +224,27 @@ test_parent_child_setparent (void) if (!check_indices (parent, 0, nullent, 1, 0)) { return 1; } if (!check_indices (child, 0, nullent, 1, 0)) { return 1; } - if (parent->ref.hierarchy == child->ref.hierarchy) { + if (Transform_GetRef (parent)->hierarchy + == Transform_GetRef (child)->hierarchy) { printf ("parent and child transforms have same hierarchy before" " set paret\n"); return 1; } - Transform_SetParent (scene,child, parent); + Transform_SetParent (scene, child, parent); - if (parent->ref.hierarchy != child->ref.hierarchy) { + if (Transform_GetRef (parent)->hierarchy + != Transform_GetRef (child)->hierarchy) { printf ("parent and child transforms have separate hierarchies\n"); return 1; } - if (!check_hierarchy_size (parent->ref.hierarchy, 2)) { return 1; } + if (!check_hierarchy_size (parent, 2)) { return 1; } if (!check_indices (parent, 0, nullent, 1, 1)) { return 1; } if (!check_indices (child, 1, 0, 2, 0)) { return 1; } - hierarchy_t *h = parent->ref.hierarchy; + hierarchy_t *h = Transform_GetRef (parent)->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; mat4f_t *localInverse = h->components[transform_type_localInverse]; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; @@ -267,7 +280,7 @@ test_parent_child_setparent (void) } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (parent->ref.hierarchy); + Hierarchy_Delete (Transform_GetRef (parent)->hierarchy); return 0; } @@ -277,17 +290,17 @@ test_build_hierarchy (void) { printf ("test_build_hierarchy\n"); - transform_t *root = Transform_NewNamed (scene, 0, "root"); - transform_t *A = Transform_NewNamed (scene, root, "A"); - transform_t *B = Transform_NewNamed (scene, root, "B"); - transform_t *C = Transform_NewNamed (scene, root, "C"); + transform_t root = Transform_NewNamed (scene, (transform_t) {}, "root"); + transform_t A = Transform_NewNamed (scene, root, "A"); + transform_t B = Transform_NewNamed (scene, root, "B"); + transform_t C = Transform_NewNamed (scene, root, "C"); if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices (A, 1, 0, 4, 0)) { return 1; } if (!check_indices (B, 2, 0, 4, 0)) { return 1; } if (!check_indices (C, 3, 0, 4, 0)) { return 1; } - transform_t *B1 = Transform_NewNamed (scene, B, "B1"); + transform_t B1 = Transform_NewNamed (scene, B, "B1"); if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 0)) { return 1; } @@ -295,7 +308,7 @@ test_build_hierarchy (void) if (!check_indices ( C, 3, 0, 5, 0)) { return 1; } if (!check_indices (B1, 4, 2, 5, 0)) { return 1; } - transform_t *A1 = Transform_NewNamed (scene, A, "A1"); + transform_t A1 = Transform_NewNamed (scene, A, "A1"); if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 1)) { return 1; } @@ -303,13 +316,13 @@ test_build_hierarchy (void) if (!check_indices ( C, 3, 0, 6, 0)) { return 1; } if (!check_indices (A1, 4, 1, 6, 0)) { return 1; } if (!check_indices (B1, 5, 2, 6, 0)) { return 1; } - transform_t *A1a = Transform_NewNamed (scene, A1, "A1a"); - transform_t *B2 = Transform_NewNamed (scene, B, "B2"); - transform_t *A2 = Transform_NewNamed (scene, A, "A2"); - transform_t *B3 = Transform_NewNamed (scene, B, "B3"); - transform_t *B2a = Transform_NewNamed (scene, B2, "B2a"); + transform_t A1a = Transform_NewNamed (scene, A1, "A1a"); + transform_t B2 = Transform_NewNamed (scene, B, "B2"); + transform_t A2 = Transform_NewNamed (scene, A, "A2"); + transform_t B3 = Transform_NewNamed (scene, B, "B3"); + transform_t B2a = Transform_NewNamed (scene, B2, "B2a"); - if (!check_hierarchy_size (root->ref.hierarchy, 11)) { return 1; } + if (!check_hierarchy_size (root, 11)) { return 1; } if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 2)) { return 1; } @@ -323,9 +336,9 @@ test_build_hierarchy (void) if (!check_indices (A1a, 9, 4, 11, 0)) { return 1; } if (!check_indices (B2a, 10, 7, 11, 0)) { return 1; } - transform_t *D = Transform_NewNamed (scene, root, "D"); + transform_t D = Transform_NewNamed (scene, root, "D"); - if (!check_hierarchy_size (root->ref.hierarchy, 12)) { return 1; } + if (!check_hierarchy_size (root, 12)) { return 1; } if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } @@ -340,10 +353,10 @@ test_build_hierarchy (void) if (!check_indices (A1a, 10, 5, 12, 0)) { return 1; } if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; } - dump_hierarchy (root->ref.hierarchy); - transform_t *C1 = Transform_NewNamed (scene, C, "C1"); - dump_hierarchy (root->ref.hierarchy); - if (!check_hierarchy_size (root->ref.hierarchy, 13)) { return 1; } + dump_hierarchy (root); + transform_t C1 = Transform_NewNamed (scene, C, "C1"); + dump_hierarchy (root); + if (!check_hierarchy_size (root, 13)) { return 1; } if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } @@ -360,7 +373,7 @@ test_build_hierarchy (void) if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (root->ref.hierarchy); + Hierarchy_Delete (Transform_GetRef (root)->hierarchy); return 0; } @@ -370,21 +383,21 @@ test_build_hierarchy2 (void) { printf ("test_build_hierarchy2\n"); - transform_t *root = Transform_NewNamed (scene, 0, "root"); - transform_t *A = Transform_NewNamed (scene, root, "A"); - transform_t *B = Transform_NewNamed (scene, root, "B"); - transform_t *C = Transform_NewNamed (scene, root, "C"); - transform_t *B1 = Transform_NewNamed (scene, B, "B1"); - transform_t *A1 = Transform_NewNamed (scene, A, "A1"); - transform_t *A1a = Transform_NewNamed (scene, A1, "A1a"); - transform_t *B2 = Transform_NewNamed (scene, B, "B2"); - transform_t *A2 = Transform_NewNamed (scene, A, "A2"); - transform_t *B3 = Transform_NewNamed (scene, B, "B3"); - transform_t *B2a = Transform_NewNamed (scene, B2, "B2a"); - transform_t *D = Transform_NewNamed (scene, root, "D"); - transform_t *C1 = Transform_NewNamed (scene, C, "C1"); + transform_t root = Transform_NewNamed (scene, (transform_t) {}, "root"); + transform_t A = Transform_NewNamed (scene, root, "A"); + transform_t B = Transform_NewNamed (scene, root, "B"); + transform_t C = Transform_NewNamed (scene, root, "C"); + transform_t B1 = Transform_NewNamed (scene, B, "B1"); + transform_t A1 = Transform_NewNamed (scene, A, "A1"); + transform_t A1a = Transform_NewNamed (scene, A1, "A1a"); + transform_t B2 = Transform_NewNamed (scene, B, "B2"); + transform_t A2 = Transform_NewNamed (scene, A, "A2"); + transform_t B3 = Transform_NewNamed (scene, B, "B3"); + transform_t B2a = Transform_NewNamed (scene, B2, "B2a"); + transform_t D = Transform_NewNamed (scene, root, "D"); + transform_t C1 = Transform_NewNamed (scene, C, "C1"); - if (!check_hierarchy_size (root->ref.hierarchy, 13)) { return 1; } + if (!check_hierarchy_size (root, 13)) { return 1; } if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } @@ -400,21 +413,21 @@ test_build_hierarchy2 (void) if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } - transform_t *T = Transform_NewNamed (scene, 0, "T"); - transform_t *X = Transform_NewNamed (scene, T, "X"); - transform_t *Y = Transform_NewNamed (scene, T, "Y"); - transform_t *Z = Transform_NewNamed (scene, T, "Z"); - transform_t *Y1 = Transform_NewNamed (scene, Y, "Y1"); - transform_t *X1 = Transform_NewNamed (scene, X, "X1"); - transform_t *X1a = Transform_NewNamed (scene, X1, "X1a"); - transform_t *Y2 = Transform_NewNamed (scene, Y, "Y2"); - transform_t *X2 = Transform_NewNamed (scene, X, "X2"); - transform_t *Y3 = Transform_NewNamed (scene, Y, "Y3"); - transform_t *Y2a = Transform_NewNamed (scene, Y2, "Y2a"); - transform_t *Z1 = Transform_NewNamed (scene, Z, "Z1"); + transform_t T = Transform_NewNamed (scene, (transform_t) {}, "T"); + transform_t X = Transform_NewNamed (scene, T, "X"); + transform_t Y = Transform_NewNamed (scene, T, "Y"); + transform_t Z = Transform_NewNamed (scene, T, "Z"); + transform_t Y1 = Transform_NewNamed (scene, Y, "Y1"); + transform_t X1 = Transform_NewNamed (scene, X, "X1"); + transform_t X1a = Transform_NewNamed (scene, X1, "X1a"); + transform_t Y2 = Transform_NewNamed (scene, Y, "Y2"); + transform_t X2 = Transform_NewNamed (scene, X, "X2"); + transform_t Y3 = Transform_NewNamed (scene, Y, "Y3"); + transform_t Y2a = Transform_NewNamed (scene, Y2, "Y2a"); + transform_t Z1 = Transform_NewNamed (scene, Z, "Z1"); - dump_hierarchy (T->ref.hierarchy); - if (!check_hierarchy_size (T->ref.hierarchy, 12)) { return 1; } + dump_hierarchy (T); + if (!check_hierarchy_size (T, 12)) { return 1; } if (!check_indices ( T, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( X, 1, 0, 4, 2)) { return 1; } @@ -429,11 +442,11 @@ test_build_hierarchy2 (void) if (!check_indices (X1a, 10, 4, 12, 0)) { return 1; } if (!check_indices (Y2a, 11, 7, 12, 0)) { return 1; } - Transform_SetParent (scene,T, B); + Transform_SetParent (scene, T, B); - dump_hierarchy (root->ref.hierarchy); + dump_hierarchy (root); - if (!check_hierarchy_size (root->ref.hierarchy, 25)) { return 1; } + if (!check_hierarchy_size (root, 25)) { return 1; } if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } @@ -461,12 +474,12 @@ test_build_hierarchy2 (void) if (!check_indices (X1a, 23, 17, 25, 0)) { return 1; } if (!check_indices (Y2a, 24, 20, 25, 0)) { return 1; } - Transform_SetParent (scene,Y, 0); + Transform_SetParent (scene, Y, (transform_t) {}); - dump_hierarchy (root->ref.hierarchy); - dump_hierarchy (Y->ref.hierarchy); - if (!check_hierarchy_size (root->ref.hierarchy, 20)) { return 1; } - if (!check_hierarchy_size (Y->ref.hierarchy, 5)) { return 1; } + dump_hierarchy (root); + dump_hierarchy (Y); + if (!check_hierarchy_size (root, 20)) { return 1; } + if (!check_hierarchy_size (Y, 5)) { return 1; } if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } @@ -496,15 +509,15 @@ test_build_hierarchy2 (void) if (!check_indices (Y2a, 4, 2, 5, 0)) { return 1; } // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (root->ref.hierarchy); - Hierarchy_Delete (Y->ref.hierarchy); + Hierarchy_Delete (Transform_GetRef (root)->hierarchy); + Hierarchy_Delete (Transform_GetRef (Y)->hierarchy); return 0; } static int -check_vector (const transform_t *transform, - vec4f_t (*func) (const transform_t *t), +check_vector (transform_t transform, + vec4f_t (*func) (transform_t t), vec4f_t expect, const char *msg) { vec4f_t res = func(transform); @@ -520,11 +533,11 @@ check_vector (const transform_t *transform, static int test_frames (void) { - transform_t *root = Transform_NewNamed (scene, 0, "root"); - transform_t *A = Transform_NewNamed (scene, root, "A"); - transform_t *B = Transform_NewNamed (scene, root, "B"); - transform_t *A1 = Transform_NewNamed (scene, A, "A1"); - transform_t *B1 = Transform_NewNamed (scene, B, "B1"); + transform_t root = Transform_NewNamed (scene, (transform_t) {}, "root"); + transform_t A = Transform_NewNamed (scene, root, "A"); + transform_t B = Transform_NewNamed (scene, root, "B"); + transform_t A1 = Transform_NewNamed (scene, A, "A1"); + transform_t B1 = Transform_NewNamed (scene, B, "B1"); Transform_SetLocalPosition (root, (vec4f_t) { 0, 0, 1, 1 }); Transform_SetLocalPosition (A, (vec4f_t) { 1, 0, 0, 1 }); @@ -536,7 +549,7 @@ test_frames (void) Transform_SetLocalPosition (B1, (vec4f_t) { 0, 1, 0, 1 }); Transform_SetLocalRotation (B1, (vec4f_t) { -0.5, 0.5, -0.5, 0.5 }); - hierarchy_t *h = root->ref.hierarchy; + hierarchy_t *h = Transform_GetRef (root)->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; mat4f_t *localInverse = h->components[transform_type_localInverse]; mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; diff --git a/libs/scene/transform.c b/libs/scene/transform.c index b1bef0234..cb38a1967 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -133,17 +133,6 @@ static const hierarchy_type_t transform_type = { .components = transform_components, }; -hierref_t * -__transform_alloc (scene_t *scene) -{ - scene_resources_t *res = scene->resources; - hierref_t *ref = PR_RESNEW_NC (res->transforms); - ref->id = PR_RESINDEX (res->transforms, ref); - ref->hierarchy = 0; - ref->index = 0; - return ref; -} - static void transform_calcLocalInverse (hierarchy_t *h, uint32_t index) { @@ -231,73 +220,81 @@ Transform_UpdateMatrices (hierarchy_t *h) memset (modified, 0, h->num_objects); } -transform_t * -Transform_New (scene_t *scene, transform_t *parent) +transform_t +Transform_New (scene_t *scene, transform_t parent) { - hierref_t *transform = __transform_alloc (scene); - __auto_type ref = (hierref_t *) transform; + ecs_registry_t *reg = scene->reg; + uint32_t transform = ECS_NewEntity (reg); + hierref_t *ref = Ent_AddComponent (transform, scene_href, reg); - if (parent) { - ref->hierarchy = parent->ref.hierarchy; - ref->index = Hierarchy_InsertHierarchy (parent->ref.hierarchy, 0, - parent->ref.index, 0); + if (parent.reg && parent.id != nullent) { + hierref_t *pref = Transform_GetRef (parent); + ref->hierarchy = pref->hierarchy; + ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, 0, + pref->index, 0); } else { ref->hierarchy = Hierarchy_New (scene, &transform_type, 1); ref->index = 0; } - ref->hierarchy->ref[ref->index] = transform; + ref->hierarchy->ent[ref->index] = transform; Transform_UpdateMatrices (ref->hierarchy); - return (transform_t *) transform; + return (transform_t) { .reg = reg, .id = transform, .comp = scene_href }; } void -Transform_Delete (scene_t *scene, transform_t *transform) +Transform_Delete (scene_t *scene, transform_t transform) { - if (transform->ref.index != 0) { + hierref_t *ref = Transform_GetRef (transform); + if (ref->index != 0) { // The transform is not the root, so pull it out of its current // hierarchy so deleting it is easier - Transform_SetParent (scene, transform, 0); + Transform_SetParent (scene, transform, (transform_t) {}); } // Takes care of freeing the transforms - Hierarchy_Delete (transform->ref.hierarchy); + Hierarchy_Delete (ref->hierarchy); } -transform_t * -Transform_NewNamed (scene_t *scene, transform_t *parent, const char *name) +transform_t +Transform_NewNamed (scene_t *scene, transform_t parent, const char *name) { - transform_t *transform = Transform_New (scene, parent); + transform_t transform = Transform_New (scene, parent); Transform_SetName (transform, name); return transform; } void -Transform_SetParent (scene_t *scene, transform_t *transform, - transform_t *parent) +Transform_SetParent (scene_t *scene, transform_t transform, + transform_t parent) { - if (parent) { - hierarchy_t *hierarchy = transform->ref.hierarchy; - uint32_t index = transform->ref.index; - Hierarchy_InsertHierarchy (parent->ref.hierarchy, hierarchy, - parent->ref.index, index); - Hierarchy_RemoveHierarchy (hierarchy, index); - if (!hierarchy->num_objects) { - Hierarchy_Delete (hierarchy); + if (parent.reg && parent.id != nullent) { + __auto_type ref = Transform_GetRef (transform); + __auto_type tref = *ref; + __auto_type pref = Transform_GetRef (parent); + ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, + tref.hierarchy, + pref->index, tref.index); + ref->hierarchy = pref->hierarchy; + Hierarchy_RemoveHierarchy (tref.hierarchy, tref.index); + if (!tref.hierarchy->num_objects) { + Hierarchy_Delete (tref.hierarchy); } } else { + __auto_type ref = Transform_GetRef (transform); + __auto_type tref = *ref; // null parent -> make transform root - if (!transform->ref.index) { + if (!tref.index) { // already root return; } - hierarchy_t *hierarchy = transform->ref.hierarchy; - uint32_t index = transform->ref.index; - - hierarchy_t *new_hierarchy = Hierarchy_New (scene, &transform_type, 0); - Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, nullent, - index); - Hierarchy_RemoveHierarchy (hierarchy, index); + ref->hierarchy = Hierarchy_New (scene, &transform_type, 0); + Hierarchy_InsertHierarchy (ref->hierarchy, tref.hierarchy, nullent, + tref.index); + Hierarchy_RemoveHierarchy (tref.hierarchy, tref.index); + if (!tref.hierarchy->num_objects) { + Hierarchy_Delete (tref.hierarchy); + } } - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; byte *modified = h->components[transform_type_modified]; modified[ref->index] = 1; @@ -305,9 +302,9 @@ Transform_SetParent (scene_t *scene, transform_t *transform, } void -Transform_SetName (transform_t *transform, const char *_name) +Transform_SetName (transform_t transform, const char *_name) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; char **name = h->components[transform_type_name]; //FIXME create a string pool (similar to qfcc's, or even move that to util) @@ -318,18 +315,18 @@ Transform_SetName (transform_t *transform, const char *_name) } void -Transform_SetTag (transform_t *transform, uint32_t _tag) +Transform_SetTag (transform_t transform, uint32_t _tag) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; uint32_t *tag = h->components[transform_type_tag]; tag[ref->index] = _tag; } void -Transform_SetLocalPosition (transform_t *transform, vec4f_t position) +Transform_SetLocalPosition (transform_t transform, vec4f_t position) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; byte *modified = h->components[transform_type_modified]; @@ -339,9 +336,9 @@ Transform_SetLocalPosition (transform_t *transform, vec4f_t position) } void -Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation) +Transform_SetLocalRotation (transform_t transform, vec4f_t rotation) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; vec4f_t *localRotation = h->components[transform_type_localRotation]; @@ -361,9 +358,9 @@ Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation) } void -Transform_SetLocalScale (transform_t *transform, vec4f_t scale) +Transform_SetLocalScale (transform_t transform, vec4f_t scale) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; vec4f_t *localRotation = h->components[transform_type_localRotation]; @@ -383,9 +380,9 @@ Transform_SetLocalScale (transform_t *transform, vec4f_t scale) } void -Transform_SetWorldPosition (transform_t *transform, vec4f_t position) +Transform_SetWorldPosition (transform_t transform, vec4f_t position) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); if (ref->index) { hierarchy_t *h = ref->hierarchy; mat4f_t *worldInverse = h->components[transform_type_worldInverse]; @@ -396,9 +393,9 @@ Transform_SetWorldPosition (transform_t *transform, vec4f_t position) } void -Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation) +Transform_SetWorldRotation (transform_t transform, vec4f_t rotation) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); if (ref->index) { hierarchy_t *h = ref->hierarchy; vec4f_t *worldRotation = h->components[transform_type_worldRotation]; @@ -409,10 +406,10 @@ Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation) } void -Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, +Transform_SetLocalTransform (transform_t transform, vec4f_t scale, vec4f_t rotation, vec4f_t position) { - __auto_type ref = (const hierref_t *) transform; + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; mat4f_t *localMatrix = h->components[transform_type_localMatrix]; vec4f_t *localRotation = h->components[transform_type_localRotation]; diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index a6de23b33..3d7b3631b 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -77,7 +77,7 @@ glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; static int lmshift = 7; -void (*gl_R_BuildLightMap) (const transform_t *transform, mod_brush_t *brush, +void (*gl_R_BuildLightMap) (const vec4f_t *transform, mod_brush_t *brush, msurface_t *surf); void @@ -92,7 +92,7 @@ gl_lightmap_init (void) } static inline void -R_AddDynamicLights_1 (const transform_t *transform, msurface_t *surf) +R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf) { float dist; unsigned int maxdist, maxdist2, maxdist3; @@ -110,7 +110,7 @@ R_AddDynamicLights_1 (const transform_t *transform, msurface_t *surf) if (transform) { //FIXME give world entity a transform - entorigin = Transform_GetWorldPosition (transform); + entorigin = transform[3]; } for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -163,7 +163,7 @@ R_AddDynamicLights_1 (const transform_t *transform, msurface_t *surf) } static inline void -R_AddDynamicLights_3 (const transform_t *transform, msurface_t *surf) +R_AddDynamicLights_3 (const vec4f_t *transform, msurface_t *surf) { float dist; unsigned int maxdist, maxdist2, maxdist3; @@ -180,7 +180,7 @@ R_AddDynamicLights_3 (const transform_t *transform, msurface_t *surf) tmax = (surf->extents[1] >> 4) + 1; if (transform) { - entorigin = Transform_GetWorldPosition (transform); + entorigin = transform[3]; } for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -236,7 +236,7 @@ R_AddDynamicLights_3 (const transform_t *transform, msurface_t *surf) } static void -R_BuildLightMap_1 (const transform_t *transform, mod_brush_t *brush, +R_BuildLightMap_1 (const vec4f_t *transform, mod_brush_t *brush, msurface_t *surf) { byte *dest; @@ -292,7 +292,7 @@ R_BuildLightMap_1 (const transform_t *transform, mod_brush_t *brush, } static void -R_BuildLightMap_3 (const transform_t *transform, mod_brush_t *brush, +R_BuildLightMap_3 (const vec4f_t *transform, mod_brush_t *brush, msurface_t *surf) { byte *dest; @@ -354,7 +354,7 @@ R_BuildLightMap_3 (const transform_t *transform, mod_brush_t *brush, } static void -R_BuildLightMap_4 (const transform_t *transform, mod_brush_t *brush, +R_BuildLightMap_4 (const vec4f_t *transform, mod_brush_t *brush, msurface_t *surf) { byte *dest; @@ -432,7 +432,7 @@ gl_R_BlendLightmaps (void) for (sc = gl_lightmap_polys; sc; sc = sc->lm_chain) { if (sc->transform) { qfglPushMatrix (); - qfglLoadMatrixf (sc->transform); + qfglLoadMatrixf ((vec_t*)&sc->transform[0]);//FIXME } for (p = sc->surface->polys; p; p = p->next) { qfglBegin (GL_POLYGON); diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 119d6b0c7..66ddd49cd 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -41,7 +41,9 @@ #include "QF/skin.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" @@ -182,8 +184,8 @@ GL_DrawAliasFrameMulti (vert_order_t *vo) Standard shadow drawing (triangles version) */ static void -GL_DrawAliasShadowTri (const transform_t *transform, - const aliashdr_t *paliashdr, const vert_order_t *vo) +GL_DrawAliasShadowTri (transform_t transform, const aliashdr_t *paliashdr, + const vert_order_t *vo) { int count = vo->count; const blended_vert_t *verts = vo->verts; @@ -222,7 +224,7 @@ GL_DrawAliasShadowTri (const transform_t *transform, Standard shadow drawing */ static void -GL_DrawAliasShadow (const transform_t *transform, const aliashdr_t *paliashdr, +GL_DrawAliasShadow (transform_t transform, const aliashdr_t *paliashdr, const vert_order_t *vo) { float height, lheight; @@ -270,9 +272,10 @@ GL_DrawAliasShadow (const transform_t *transform, const aliashdr_t *paliashdr, } static inline vert_order_t * -GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t *e) +GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t e) { - animation_t *animation = &e->animation; + animation_t *animation = Ent_GetComponent (e.id, scene_animation, + r_refdef.scene->reg); float blend; int count, i; trivertx16_t *verts; @@ -300,14 +303,14 @@ GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t *e) if (blend == 0.0) { - verts = verts + e->animation.pose1 * count; + verts = verts + animation->pose1 * count; } else if (blend == 1.0) { - verts = verts + e->animation.pose2 * count; + verts = verts + animation->pose2 * count; } else { trivertx16_t *verts1, *verts2; - verts1 = verts + e->animation.pose1 * count; - verts2 = verts + e->animation.pose2 * count; + verts1 = verts + animation->pose1 * count; + verts2 = verts + animation->pose2 * count; for (i = 0, vo_v = vo->verts; i < count; i++, vo_v++, verts1++, verts2++) { @@ -336,9 +339,10 @@ GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t *e) } static inline vert_order_t * -GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t *e) +GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t e) { - animation_t *animation = &e->animation; + animation_t *animation = Ent_GetComponent (e.id, scene_animation, + r_refdef.scene->reg); float blend; int count, i; trivertx_t *verts; @@ -364,14 +368,14 @@ GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t *e) blend = 1.0; if (blend == 0.0) { - verts = verts + e->animation.pose1 * count; + verts = verts + animation->pose1 * count; } else if (blend == 1.0) { - verts = verts + e->animation.pose2 * count; + verts = verts + animation->pose2 * count; } else { trivertx_t *verts1, *verts2; - verts1 = verts + e->animation.pose1 * count; - verts2 = verts + e->animation.pose2 * count; + verts1 = verts + animation->pose1 * count; + verts2 = verts + animation->pose2 * count; for (i = 0, vo_v = vo->verts; i < count; i++, vo_v++, verts1++, verts2++) { @@ -400,7 +404,7 @@ GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t *e) } void -gl_R_DrawAliasModel (entity_t *e) +gl_R_DrawAliasModel (entity_t e) { float radius, minlight, d; float position[4] = {0.0, 0.0, 0.0, 1.0}, @@ -417,12 +421,15 @@ gl_R_DrawAliasModel (entity_t *e) vec3_t dist, scale; vec4f_t origin; vert_order_t *vo; + transform_t transform = Entity_Transform (e); + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, + r_refdef.scene->reg); - model = e->renderer.model; + model = renderer->model; radius = model->radius; - origin = Transform_GetWorldPosition (e->transform); - VectorCopy (Transform_GetWorldScale (e->transform), scale); + origin = Transform_GetWorldPosition (transform); + VectorCopy (Transform_GetWorldScale (transform), scale); //FIXME assumes uniform scale if (scale[0] != 1.0) { radius *= scale[0]; @@ -431,12 +438,12 @@ gl_R_DrawAliasModel (entity_t *e) return; } - gl_modelalpha = e->renderer.colormod[3]; + gl_modelalpha = renderer->colormod[3]; - is_fullbright = (model->fullbright || e->renderer.fullbright); - minlight = max (model->min_light, e->renderer.min_light); + is_fullbright = (model->fullbright || renderer->fullbright); + minlight = max (model->min_light, renderer->min_light); - qfglColor4fv (e->renderer.colormod); + qfglColor4fv (renderer->colormod); if (!is_fullbright) { float lightadj; @@ -536,25 +543,25 @@ gl_R_DrawAliasModel (entity_t *e) VectorScale (emission, 1.5 / d, emission); } - emission[0] *= e->renderer.colormod[0]; - emission[1] *= e->renderer.colormod[1]; - emission[2] *= e->renderer.colormod[2]; - emission[3] *= e->renderer.colormod[3]; + emission[0] *= renderer->colormod[0]; + emission[1] *= renderer->colormod[1]; + emission[2] *= renderer->colormod[2]; + emission[3] *= renderer->colormod[3]; qfglColor4fv (emission); } } // locate the proper data - if (!(paliashdr = e->renderer.model->aliashdr)) { - paliashdr = Cache_Get (&e->renderer.model->cache); + if (!(paliashdr = renderer->model->aliashdr)) { + paliashdr = Cache_Get (&renderer->model->cache); } gl_ctx->alias_polys += paliashdr->mdl.numtris; // if the model has a colorised/external skin, use it, otherwise use // the skin embedded in the model data - if (e->renderer.skin && e->renderer.skin->texnum && !gl_nocolors) { - skin_t *skin = e->renderer.skin; + if (renderer->skin && renderer->skin->texnum && !gl_nocolors) { + skin_t *skin = renderer->skin; texture = skin->texnum; if (gl_fb_models) { @@ -562,9 +569,9 @@ gl_R_DrawAliasModel (entity_t *e) } } else { maliasskindesc_t *skindesc; - animation_t *animation = &e->animation; - - skindesc = R_AliasGetSkindesc (animation, e->renderer.skinnum, + animation_t *animation = Ent_GetComponent (e.id, scene_animation, + r_refdef.scene->reg); + skindesc = R_AliasGetSkindesc (animation, renderer->skinnum, paliashdr); texture = skindesc->texnum; if (gl_fb_models && !is_fullbright) { @@ -586,7 +593,7 @@ gl_R_DrawAliasModel (entity_t *e) // setup the transform qfglPushMatrix (); - gl_R_RotateForEntity (e); + gl_R_RotateForEntity (Transform_GetWorldMatrixPtr (transform)); qfglTranslatef (paliashdr->mdl.scale_origin[0], paliashdr->mdl.scale_origin[1], @@ -652,7 +659,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglDisable (GL_NORMALIZE); } - qfglColor4fv (e->renderer.colormod); + qfglColor4fv (renderer->colormod); qfglBindTexture (GL_TEXTURE_2D, fb_texture); GL_DrawAliasFrameTri (vo); @@ -672,7 +679,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglDisable (GL_NORMALIZE); } - qfglColor4fv (e->renderer.colormod); + qfglColor4fv (renderer->colormod); qfglBindTexture (GL_TEXTURE_2D, fb_texture); GL_DrawAliasFrame (vo); @@ -693,7 +700,7 @@ gl_R_DrawAliasModel (entity_t *e) mat4f_t shadow_mat; qfglPushMatrix (); - gl_R_RotateForEntity (e); + gl_R_RotateForEntity (Transform_GetWorldMatrixPtr (transform)); if (!gl_tess) qfglDisable (GL_NORMALIZE); @@ -702,7 +709,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglDepthMask (GL_FALSE); if (gl_modelalpha < 1.0) { - VectorBlend (e->renderer.colormod, dark, 0.5, color); + VectorBlend (renderer->colormod, dark, 0.5, color); color[3] = gl_modelalpha * (model->shadow_alpha / 255.0); qfglColor4fv (color); } else { @@ -711,14 +718,14 @@ gl_R_DrawAliasModel (entity_t *e) } //FIXME fully vectorize vec4f_t vec = { 0.707106781, 0, 0.707106781, 0 }; - Transform_GetWorldMatrix (e->transform, shadow_mat); + Transform_GetWorldMatrix (transform, shadow_mat); mat4ftranspose (shadow_mat, shadow_mat); vec = m3vmulf (shadow_mat, vec); VectorCopy (vec, shadevector); if (vo->tex_coord) - GL_DrawAliasShadowTri (e->transform, paliashdr, vo); + GL_DrawAliasShadowTri (transform, paliashdr, vo); else - GL_DrawAliasShadow (e->transform, paliashdr, vo); + GL_DrawAliasShadow (transform, paliashdr, vo); qfglDepthMask (GL_TRUE); qfglEnable (GL_TEXTURE_2D); @@ -734,7 +741,7 @@ gl_R_DrawAliasModel (entity_t *e) qfglDisable (GL_LIGHT0 + used_lights); } - if (!e->renderer.model->aliashdr) { - Cache_Release (&e->renderer.model->cache); + if (!renderer->model->aliashdr) { + Cache_Release (&renderer->model->cache); } } diff --git a/libs/video/renderer/gl/gl_mod_iqm.c b/libs/video/renderer/gl/gl_mod_iqm.c index 2b2555020..e294e73e5 100644 --- a/libs/video/renderer/gl/gl_mod_iqm.c +++ b/libs/video/renderer/gl/gl_mod_iqm.c @@ -49,7 +49,9 @@ #include "QF/GL/qf_iqm.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_vid.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "r_internal.h" @@ -86,21 +88,26 @@ gl_draw_iqm_frame (iqm_t *iqm, gliqm_t *gl, iqmframe_t *frame, iqmmesh *mesh) } void -gl_R_DrawIQMModel (entity_t *ent) +gl_R_DrawIQMModel (entity_t ent) { - model_t *model = ent->renderer.model; + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); + model_t *model = renderer->model; iqm_t *iqm = (iqm_t *) model->aliashdr; gliqm_t *gl = (gliqm_t *) iqm->extra_data; float blend; iqmframe_t *frame; int i; - blend = R_IQMGetLerpedFrames (ent, iqm); - frame = R_IQMBlendPalette (iqm, ent->animation.pose1, ent->animation.pose2, + blend = R_IQMGetLerpedFrames (animation, iqm); + frame = R_IQMBlendPalette (iqm, animation->pose1, animation->pose2, blend, 0, gl->blend_palette, gl->palette_size); qfglPushMatrix (); - gl_R_RotateForEntity (ent); + gl_R_RotateForEntity (Transform_GetWorldMatrixPtr (transform)); for (i = 0; i < iqm->num_meshes; i++) { qfglBindTexture (GL_TEXTURE_2D, gl->textures[i]); diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index 226a4443b..dff4e325d 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -39,7 +39,9 @@ #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" @@ -53,31 +55,37 @@ static int sVAsize; static int *sVAindices; varray_t2f_c4ub_v3f_t *gl_spriteVertexArray; -void (*gl_R_DrawSpriteModel) (struct entity_s *ent); +void (*gl_R_DrawSpriteModel) (struct entity_s ent); static void -R_DrawSpriteModel_f (entity_t *e) +R_DrawSpriteModel_f (entity_t e) { + transform_t transform = Entity_Transform (e); + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (e.id, scene_animation, + r_refdef.scene->reg); float modelalpha, color[4]; vec4f_t cameravec = {}; vec4f_t up = {}, right = {}, pn = {}; vec4f_t origin, point; - msprite_t *sprite = e->renderer.model->cache.data; + msprite_t *sprite = renderer->model->cache.data; mspriteframe_t *frame; - origin = Transform_GetWorldPosition (e->transform); + origin = Transform_GetWorldPosition (transform); cameravec = r_refdef.frame.position - origin; // don't bother culling, it's just a single polygon without a surface cache - frame = R_GetSpriteFrame (sprite, &e->animation); + frame = R_GetSpriteFrame (sprite, animation); - if (!R_BillboardFrame (e, sprite->type, cameravec, &up, &right, &pn)) { + if (!R_BillboardFrame (transform, sprite->type, cameravec, + &up, &right, &pn)) { // the orientation is undefined so can't draw the sprite return; } - VectorCopy (e->renderer.colormod, color); - modelalpha = color[3] = e->renderer.colormod[3]; + VectorCopy (renderer->colormod, color); + modelalpha = color[3] = renderer->colormod[3]; if (modelalpha < 1.0) qfglDepthMask (GL_FALSE); @@ -112,27 +120,32 @@ R_DrawSpriteModel_f (entity_t *e) } static void -R_DrawSpriteModel_VA_f (entity_t *e) +R_DrawSpriteModel_VA_f (entity_t e) { + transform_t transform = Entity_Transform (e); + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (e.id, scene_animation, + r_refdef.scene->reg); unsigned char modelalpha, color[4]; vec4f_t up = {}, right = {}; vec4f_t origin, point; int i; // unsigned int vacount; - msprite_t *psprite = e->renderer.model->cache.data; + msprite_t *psprite = renderer->model->cache.data; mspriteframe_t *frame; varray_t2f_c4ub_v3f_t *VA; VA = gl_spriteVertexArray; // FIXME: Despair // don't bother culling, it's just a single polygon without a surface cache - frame = R_GetSpriteFrame (psprite, &e->animation); + frame = R_GetSpriteFrame (psprite, animation); qfglBindTexture (GL_TEXTURE_2D, frame->gl_texturenum); // FIXME: DESPAIR if (psprite->type == SPR_ORIENTED) { // bullet marks on walls - up = Transform_Up (e->transform); - right = Transform_Right (e->transform); + up = Transform_Up (transform); + right = Transform_Right (transform); } else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) { up = (vec4f_t) { 0, 0, 1, 0 }; VectorCopy (r_refdef.frame.right, right); @@ -142,7 +155,7 @@ R_DrawSpriteModel_VA_f (entity_t *e) } for (i = 0; i < 4; i++) { - color[i] = e->renderer.colormod[i] * 255; + color[i] = renderer->colormod[i] * 255; } memcpy (VA[0].color, color, 4); memcpy (VA[1].color, color, 4); @@ -153,7 +166,7 @@ R_DrawSpriteModel_VA_f (entity_t *e) if (modelalpha < 255) qfglDepthMask (GL_FALSE); - origin = Transform_GetWorldPosition (e->transform); + origin = Transform_GetWorldPosition (transform); point = origin + frame->down * up + frame->left * right; VectorCopy (point, VA[0].vertex); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 3e3f082a8..4d5c51ed6 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -39,7 +39,9 @@ #include #include +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" @@ -77,10 +79,8 @@ glrmain_init (void) } void -gl_R_RotateForEntity (entity_t *e) +gl_R_RotateForEntity (const vec4f_t *mat) { - mat4f_t mat; - Transform_GetWorldMatrix (e->transform, mat); qfglMultMatrixf ((vec_t*)&mat[0]);//FIXME } @@ -113,7 +113,7 @@ gl_R_RenderEntities (entqueue_t *queue) } for (size_t i = 0; i < queue->ent_queues[mod_alias].size; i++) { - entity_t *ent = queue->ent_queues[mod_alias].a[i]; + entity_t ent = queue->ent_queues[mod_alias].a[i]; gl_R_DrawAliasModel (ent); } qfglColor3ubv (color_white); @@ -142,7 +142,7 @@ gl_R_RenderEntities (entqueue_t *queue) } for (size_t i = 0; i < queue->ent_queues[mod_iqm].size; i++) { \ - entity_t *ent = queue->ent_queues[mod_iqm].a[i]; \ + entity_t ent = queue->ent_queues[mod_iqm].a[i]; \ gl_R_DrawIQMModel (ent); } qfglColor3ubv (color_white); @@ -152,7 +152,7 @@ gl_R_RenderEntities (entqueue_t *queue) if (gl_va_capable) qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray); for (size_t i = 0; i < queue->ent_queues[mod_sprite].size; i++) { \ - entity_t *ent = queue->ent_queues[mod_sprite].a[i]; \ + entity_t ent = queue->ent_queues[mod_sprite].a[i]; \ gl_R_DrawSpriteModel (ent); } qfglDisable (GL_ALPHA_TEST); @@ -161,11 +161,13 @@ gl_R_RenderEntities (entqueue_t *queue) static void R_DrawViewModel (void) { - entity_t *ent = vr_data.view_model; + entity_t ent = vr_data.view_model; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); if (vr_data.inhibit_viewmodel || !r_drawviewmodel || !r_drawentities - || !ent->renderer.model) + || !renderer->model) return; // hack the depth range to prevent view model from poking into walls @@ -267,7 +269,7 @@ gl_R_RenderView (void) gl_R_DrawWorld (); gl_R_RenderDlights (); - if (vr_data.view_model) { + if (Entity_Valid (vr_data.view_model)) { R_DrawViewModel (); } diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index c2baac427..506e6163e 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -165,6 +165,7 @@ gl_R_NewScene (scene_t *scene) for (int i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value + r_refdef.scene = scene; r_refdef.worldmodel = scene->worldmodel; brush = &scene->worldmodel->brush; diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index b173c7679..bc0878158 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -45,7 +45,9 @@ #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" @@ -67,8 +69,8 @@ static instsurf_t **sky_chain_tail; typedef struct glbspctx_s { mod_brush_t *brush; - entity_t *entity; - vec_t *transform; + animation_t *animation; + vec4f_t *transform; float *color; } glbspctx_t; @@ -192,7 +194,7 @@ R_RenderFullbrights (void) for (sc = tex->tex_chain; sc; sc = sc->tex_chain) { if (sc->transform) { qfglPushMatrix (); - qfglLoadMatrixf (sc->transform); + qfglLoadMatrixf ((vec_t*)&sc->transform[0]);//FIXME } if (sc->color) qfglColor4fv (sc->color); @@ -291,7 +293,7 @@ R_AddToLightmapChain (glbspctx_t *bctx, msurface_t *surf, instsurf_t *sc) if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { dynamic: if (r_dynamic) { - gl_R_BuildLightMap (bctx->entity->transform, bctx->brush, surf); + gl_R_BuildLightMap (bctx->transform, bctx->brush, surf); } } } @@ -319,7 +321,7 @@ gl_R_DrawWaterSurfaces (void) surf = s->surface; if (s->transform) { qfglPushMatrix (); - qfglLoadMatrixf (s->transform); + qfglLoadMatrixf ((vec_t*)&s->transform[0]);//FIXME } tex = surf->texinfo->texture->render; if (i != tex->gl_texturenum) { @@ -374,7 +376,7 @@ DrawTextureChains (int disable_blend, int do_bind) surf = s->surface; if (s->transform) { qfglPushMatrix (); - qfglLoadMatrixf (s->transform); + qfglLoadMatrixf ((vec_t*)&s->transform[0]);//FIXME } if (s->color && do_bind) qfglColor4fv (s->color); @@ -397,7 +399,7 @@ DrawTextureChains (int disable_blend, int do_bind) if (s->transform) { qfglPushMatrix (); - qfglLoadMatrixf (s->transform); + qfglLoadMatrixf ((vec_t*)&s->transform[0]);//FIXME } if (s->color && do_bind) qfglColor4fv (s->color); @@ -432,7 +434,7 @@ DrawTextureChains (int disable_blend, int do_bind) for (s = tex->tex_chain; s; s = s->tex_chain) { if (s->transform) { qfglPushMatrix (); - qfglLoadMatrixf (s->transform); + qfglLoadMatrixf ((vec_t*)&s->transform[0]);//FIXME } R_RenderBrushPoly_1 (s->surface); @@ -484,7 +486,7 @@ chain_surface (glbspctx_t *bctx, msurface_t *surf) if (!surf->texinfo->texture->anim_total) tx = surf->texinfo->texture; else - tx = R_TextureAnimation (bctx->entity, surf); + tx = R_TextureAnimation (bctx->animation, surf); tex = tx->render; sc = CHAIN_SURF_F2B (surf, tex->tex_chain); @@ -495,23 +497,28 @@ chain_surface (glbspctx_t *bctx, msurface_t *surf) } void -gl_R_DrawBrushModel (entity_t *e) +gl_R_DrawBrushModel (entity_t e) { float dot, radius; + transform_t transform = Entity_Transform (e); + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (e.id, scene_animation, + r_refdef.scene->reg); msurface_t *surf; qboolean rotated; vec3_t mins, maxs; mat4f_t worldMatrix; - model_t *model = e->renderer.model; + model_t *model = renderer->model; mod_brush_t *brush = &model->brush; glbspctx_t bspctx = { brush, - e, - e->renderer.full_transform, - e->renderer.colormod, + animation, + renderer->full_transform, + renderer->colormod, }; - Transform_GetWorldMatrix (e->transform, worldMatrix); + Transform_GetWorldMatrix (transform, worldMatrix); if (worldMatrix[0][0] != 1 || worldMatrix[1][1] != 1 || worldMatrix[2][2] != 1) { rotated = true; @@ -562,8 +569,8 @@ gl_R_DrawBrushModel (entity_t *e) } qfglPushMatrix (); - gl_R_RotateForEntity (e); - qfglGetFloatv (GL_MODELVIEW_MATRIX, e->renderer.full_transform); + gl_R_RotateForEntity (Transform_GetWorldMatrixPtr (transform)); + qfglGetFloatv (GL_MODELVIEW_MATRIX, (vec_t*)&renderer->full_transform[0]); qfglPopMatrix (); surf = &brush->surfaces[brush->firstmodelsurface]; @@ -702,20 +709,17 @@ R_VisitWorldNodes (glbspctx_t *bctx) void gl_R_DrawWorld (void) { - entity_t worldent; + animation_t animation = {}; glbspctx_t bctx = { }; - memset (&worldent, 0, sizeof (worldent)); - worldent.renderer.model = r_refdef.worldmodel; - sky_chain = 0; sky_chain_tail = &sky_chain; if (!gl_sky_clip) { gl_R_DrawSky (); } - bctx.brush = &worldent.renderer.model->brush; - bctx.entity = &worldent; + bctx.brush = &r_refdef.worldmodel->brush; + bctx.animation = &animation; R_VisitWorldNodes (&bctx); @@ -723,7 +727,7 @@ gl_R_DrawWorld (void) if (r_drawentities) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { \ - entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; \ + entity_t ent = r_ent_queue->ent_queues[mod_brush].a[i]; \ gl_R_DrawBrushModel (ent); } } diff --git a/libs/video/renderer/gl/gl_sky_clip.c b/libs/video/renderer/gl/gl_sky_clip.c index e069c8768..64aea23f4 100644 --- a/libs/video/renderer/gl/gl_sky_clip.c +++ b/libs/video/renderer/gl/gl_sky_clip.c @@ -692,7 +692,7 @@ draw_black_sky_polys (const instsurf_t *sky_chain) if (sc->transform) { qfglPushMatrix (); - qfglLoadMatrixf (sc->transform); + qfglLoadMatrixf ((vec_t*)&sc->transform[0]);//FIXME } while (p) { draw_poly (p); @@ -778,7 +778,7 @@ draw_z_sky_polys (const instsurf_t *sky_chain) if (sc->transform) { qfglPushMatrix (); - qfglLoadMatrixf (sc->transform); + qfglLoadMatrixf ((vec_t*)&sc->transform[0]);//FIXME } while (p) { draw_poly (p); @@ -829,7 +829,7 @@ gl_R_DrawSkyChain (const instsurf_t *sky_chain) if (sc->transform) { qfglPushMatrix (); - qfglLoadMatrixf (sc->transform); + qfglLoadMatrixf ((vec_t*)&sc->transform[0]);//FIXME } while (p) { int i; @@ -855,7 +855,7 @@ gl_R_DrawSkyChain (const instsurf_t *sky_chain) if (sc->transform) { qfglPushMatrix (); - qfglLoadMatrixf (sc->transform); + qfglLoadMatrixf ((vec_t*)&sc->transform[0]);//FIXME } while (p) { int i; diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index efb814251..8040e9e2b 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -44,7 +44,9 @@ #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" @@ -149,7 +151,7 @@ glsl_R_InitAlias (void) } static void -calc_lighting (entity_t *ent, float *ambient, float *shadelight, +calc_lighting (entity_t ent, float *ambient, float *shadelight, vec3_t lightvec) { unsigned i; @@ -157,13 +159,16 @@ calc_lighting (entity_t *ent, float *ambient, float *shadelight, vec3_t dist; vec4f_t entorigin; int light; + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); - entorigin = Transform_GetWorldPosition (ent->transform); + entorigin = Transform_GetWorldPosition (transform); VectorSet ( -1, 0, 0, lightvec); //FIXME light = R_LightPoint (&r_refdef.worldmodel->brush, entorigin); - *ambient = max (light, max (ent->renderer.model->min_light, - ent->renderer.min_light) * 128); + *ambient = max (light, max (renderer->model->min_light, + renderer->min_light) * 128); *shadelight = *ambient; for (i = 0; i < r_maxdlights; i++) { @@ -208,7 +213,7 @@ set_arrays (const shaderparam_t *vert, const shaderparam_t *norm, } //#define TETRAHEDRON void -glsl_R_DrawAlias (entity_t *ent) +glsl_R_DrawAlias (entity_t ent) { #ifdef TETRAHEDRON static aliasvrt_t debug_verts[] = { @@ -230,8 +235,6 @@ glsl_R_DrawAlias (entity_t *ent) float shadelight; float skin_size[2]; float blend; - animation_t *animation = &ent->animation; - model_t *model = ent->renderer.model; aliashdr_t *hdr; vec_t norm_mat[9]; int skin_tex; @@ -240,12 +243,18 @@ glsl_R_DrawAlias (entity_t *ent) aliasvrt_t *pose2 = 0; // VBO's are null based mat4f_t worldMatrix; + calc_lighting (ent, &ambient, &shadelight, lightvec); + + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); + model_t *model = renderer->model; if (!(hdr = model->aliashdr)) hdr = Cache_Get (&model->cache); - calc_lighting (ent, &ambient, &shadelight, lightvec); - - Transform_GetWorldMatrix (ent->transform, worldMatrix); + Transform_GetWorldMatrix (transform, worldMatrix); // we need only the rotation for normals. VectorCopy (worldMatrix[0], norm_mat + 0); VectorCopy (worldMatrix[1], norm_mat + 3); @@ -263,14 +272,14 @@ glsl_R_DrawAlias (entity_t *ent) mmulf (mvp_mat, alias_vp, mvp_mat); colormap = glsl_colormap; - if (ent->renderer.skin && ent->renderer.skin->auxtex) - colormap = ent->renderer.skin->auxtex; - if (ent->renderer.skin && ent->renderer.skin->texnum) { - skin_t *skin = ent->renderer.skin; + if (renderer->skin && renderer->skin->auxtex) + colormap = renderer->skin->auxtex; + if (renderer->skin && renderer->skin->texnum) { + skin_t *skin = renderer->skin; skin_tex = skin->texnum; } else { maliasskindesc_t *skindesc; - skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr); + skindesc = R_AliasGetSkindesc (animation, renderer->skinnum, hdr); skin_tex = skindesc->texnum; } blend = R_AliasGetLerpedFrames (animation, hdr); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 4a73e13e2..6f10491b6 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -48,7 +48,9 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" @@ -238,8 +240,8 @@ static struct { typedef struct glslbspctx_s { mod_brush_t *brush; - entity_t *entity; - vec_t *transform; + animation_t *animation; + vec4f_t *transform; float *color; } glslbspctx_t; @@ -376,7 +378,7 @@ update_lightmap (glslbspctx_t *bctx, msurface_t *surf) if ((surf->dlightframe == r_framecount) || surf->cached_dlight) { dynamic: if (r_dynamic) - glsl_R_BuildLightMap (bctx->entity->transform, bctx->brush, surf); + glsl_R_BuildLightMap (bctx->transform, bctx->brush, surf); } } @@ -397,7 +399,7 @@ chain_surface (glslbspctx_t *bctx, msurface_t *surf) if (!surf->texinfo->texture->anim_total) tx = surf->texinfo->texture; else - tx = R_TextureAnimation (bctx->entity, surf); + tx = R_TextureAnimation (bctx->animation, surf); tex = tx->render; is = CHAIN_SURF_F2B (surf, tex->tex_chain); @@ -648,11 +650,16 @@ glsl_R_BuildDisplayLists (model_t **models, int num_models) } static void -R_DrawBrushModel (entity_t *e) +R_DrawBrushModel (entity_t e) { float dot, radius; unsigned k; - model_t *model = e->renderer.model; + transform_t transform = Entity_Transform (e); + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (e.id, scene_animation, + r_refdef.scene->reg); + model_t *model = renderer->model; mod_brush_t *brush = &model->brush; plane_t *plane; msurface_t *surf; @@ -661,14 +668,14 @@ R_DrawBrushModel (entity_t *e) vec4f_t org; glslbspctx_t bctx = { brush, - e, - e->renderer.full_transform, - e->renderer.colormod, + animation, + renderer->full_transform, + renderer->colormod, }; mat4f_t mat; - Transform_GetWorldMatrix (e->transform, mat); - memcpy (e->renderer.full_transform, mat, sizeof (mat));//FIXME + Transform_GetWorldMatrix (transform, mat); + memcpy (renderer->full_transform, mat, sizeof (mat));//FIXME if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { rotated = true; radius = model->radius; @@ -846,7 +853,7 @@ static void draw_elechain (elechain_t *ec, int matloc, int vertloc, int tlstloc, int colloc) { - mat4_t mat; + mat4f_t mat; elements_t *el; int count; float *color; @@ -861,8 +868,8 @@ draw_elechain (elechain_t *ec, int matloc, int vertloc, int tlstloc, } } if (ec->transform) { - Mat4Mult ((vec_t*)&bsp_vp[0], ec->transform, mat);//FIXME - qfeglUniformMatrix4fv (matloc, 1, false, mat); + mmulf (mat, bsp_vp, ec->transform); + qfeglUniformMatrix4fv (matloc, 1, false, (vec_t*)&mat[0]);//FIXME } else { qfeglUniformMatrix4fv (matloc, 1, false, (vec_t*)&bsp_vp[0]);//FIXME } @@ -1140,22 +1147,19 @@ build_tex_elechain (glsltex_t *tex) void glsl_R_DrawWorld (void) { - entity_t worldent; + animation_t animation = {}; glslbspctx_t bctx = { }; int i; clear_texture_chains (); // do this first for water and skys - memset (&worldent, 0, sizeof (worldent)); - worldent.renderer.model = r_refdef.worldmodel; - - bctx.brush = &worldent.renderer.model->brush; - bctx.entity = &worldent; + bctx.brush = &r_refdef.worldmodel->brush; + bctx.animation = &animation; R_VisitWorldNodes (&bctx); if (r_drawentities) { for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { - entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; + entity_t ent = r_ent_queue->ent_queues[mod_brush].a[i]; R_DrawBrushModel (ent); } } diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index 21f44243b..95c91e969 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -44,7 +44,9 @@ #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" @@ -202,10 +204,15 @@ set_arrays (iqm_t *iqm) } void -glsl_R_DrawIQM (entity_t *ent) +glsl_R_DrawIQM (entity_t ent) { + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); static quat_t color = { 1, 1, 1, 1}; - model_t *model = ent->renderer.model; + model_t *model = renderer->model; iqm_t *iqm = (iqm_t *) model->aliashdr; glsliqm_t *glsl = (glsliqm_t *) iqm->extra_data; dlight_t *lights[MAX_IQM_LIGHTS]; @@ -218,7 +225,7 @@ glsl_R_DrawIQM (entity_t *ent) // we need only the rotation for normals. mat4f_t mat; - Transform_GetWorldMatrix (ent->transform, mat); + Transform_GetWorldMatrix (transform, mat); VectorCopy (mat[0], norm_mat + 0); VectorCopy (mat[1], norm_mat + 3); VectorCopy (mat[2], norm_mat + 6); @@ -229,8 +236,8 @@ glsl_R_DrawIQM (entity_t *ent) VectorScale (ambientcolor, 1/255.0, ambientcolor); R_FindNearLights (entorigin, MAX_IQM_LIGHTS, lights); - blend = R_IQMGetLerpedFrames (ent, iqm); - frame = R_IQMBlendFrames (iqm, ent->animation.pose1, ent->animation.pose2, + blend = R_IQMGetLerpedFrames (animation, iqm); + frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2, blend, 0); qfeglUniform3fv (iqm_shader.ambient.location, 1, ambientcolor); diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index cb57aaf31..30522a264 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -60,11 +60,11 @@ static scrap_t *light_scrap; static unsigned *blocklights; static int bl_extents[2]; -void (*glsl_R_BuildLightMap) (const transform_t *transform, mod_brush_t *brush, +void (*glsl_R_BuildLightMap) (const vec4f_t *transform, mod_brush_t *brush, msurface_t *surf); static void -R_AddDynamicLights_1 (const transform_t *transform, msurface_t *surf) +R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf) { unsigned lnum; int sd, td; @@ -81,7 +81,7 @@ R_AddDynamicLights_1 (const transform_t *transform, msurface_t *surf) if (transform) { //FIXME give world entity a transform - entorigin = Transform_GetWorldPosition (transform); + entorigin = transform[3]; } for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -126,7 +126,7 @@ R_AddDynamicLights_1 (const transform_t *transform, msurface_t *surf) } static void -R_BuildLightMap_1 (const transform_t *transform, mod_brush_t *brush, +R_BuildLightMap_1 (const vec4f_t *transform, mod_brush_t *brush, msurface_t *surf) { int smax, tmax, size; diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index f8d6bf02d..1a4cf90e4 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -45,6 +45,7 @@ #include "QF/screen.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" @@ -97,7 +98,7 @@ glsl_R_RenderEntities (entqueue_t *queue) begun = 0; \ for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ i++) { \ - entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \ + entity_t ent = queue->ent_queues[mod_##type_name].a[i]; \ if (!begun) { \ glsl_R_##Type##Begin (); \ begun = 1; \ @@ -116,11 +117,13 @@ glsl_R_RenderEntities (entqueue_t *queue) static void R_DrawViewModel (void) { - entity_t *ent = vr_data.view_model; + entity_t ent = vr_data.view_model; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); if (vr_data.inhibit_viewmodel || !r_drawviewmodel || !r_drawentities - || !ent->renderer.model) + || !renderer->model) return; // hack the depth range to prevent view model from poking into walls @@ -143,7 +146,7 @@ glsl_R_RenderView (void) R_SetupView (); glsl_R_DrawWorld (); glsl_R_DrawSky (); - if (vr_data.view_model) { + if (Entity_Valid (vr_data.view_model)) { R_DrawViewModel (); } } @@ -196,6 +199,7 @@ glsl_R_NewScene (scene_t *scene) for (i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value + r_refdef.scene = scene; r_refdef.worldmodel = scene->worldmodel; // Force a vis update diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index baac6108e..a9a73aa33 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -45,7 +45,9 @@ #include "QF/sys.h" #include "QF/vid.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" @@ -128,10 +130,11 @@ glsl_R_InitSprites (void) } static void -R_GetSpriteFrames (entity_t *ent, msprite_t *sprite, mspriteframe_t **frame1, +R_GetSpriteFrames (entity_t ent, msprite_t *sprite, mspriteframe_t **frame1, mspriteframe_t **frame2, float *blend) { - animation_t *animation = &ent->animation; + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); int framenum = animation->frame; int pose; int i, numframes; @@ -206,9 +209,12 @@ make_quad (mspriteframe_t *frame, vec4f_t origin, vec4f_t sright, vec4f_t sup, f } void -glsl_R_DrawSprite (entity_t *ent) +glsl_R_DrawSprite (entity_t ent) { - msprite_t *sprite = (msprite_t *) ent->renderer.model->cache.data; + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + msprite_t *sprite = (msprite_t *) renderer->model->cache.data; mspriteframe_t *frame1, *frame2; float blend; vec4f_t cameravec = {}; @@ -224,10 +230,11 @@ glsl_R_DrawSprite (entity_t *ent) { 0, 1, 0, 1 }, }; - vec4f_t origin = Transform_GetWorldPosition (ent->transform); + vec4f_t origin = Transform_GetWorldPosition (transform); cameravec = r_refdef.frame.position - origin; - if (!R_BillboardFrame (ent, sprite->type, cameravec, &sup, &sright, &spn)) { + if (!R_BillboardFrame (transform, sprite->type, cameravec, + &sup, &sright, &spn)) { // the orientation is undefined so can't draw the sprite return; } diff --git a/libs/video/renderer/r_billboard.c b/libs/video/renderer/r_billboard.c index 9fe3653bd..aacf5112d 100644 --- a/libs/video/renderer/r_billboard.c +++ b/libs/video/renderer/r_billboard.c @@ -46,7 +46,7 @@ int -R_BillboardFrame (entity_t *ent, int orientation, vec4f_t cameravec, +R_BillboardFrame (transform_t transform, int orientation, vec4f_t cameravec, vec4f_t *bbup, vec4f_t *bbright, vec4f_t *bbfwd) { vec4f_t tvec; @@ -90,7 +90,7 @@ R_BillboardFrame (entity_t *ent, int orientation, vec4f_t cameravec, // The billboard's orientation is fully specified by the // entity's orientation. mat4f_t mat; - Transform_GetWorldMatrix (ent->transform, mat); + Transform_GetWorldMatrix (transform, mat); *bbfwd = mat[0]; *bbright = mat[1]; *bbup = mat[2]; @@ -102,7 +102,7 @@ R_BillboardFrame (entity_t *ent, int orientation, vec4f_t cameravec, // the entity's local rotation. mat4f_t entmat; mat4f_t spmat; - Transform_GetLocalMatrix (ent->transform, entmat); + Transform_GetLocalMatrix (transform, entmat); // FIXME needs proper testing (need to find, make, or fake a // parallel oriented sprite) mmulf (spmat, r_refdef.camera, entmat); diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index 4c4550649..e2b8b951e 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -103,12 +103,12 @@ R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes, int *leaf_visframes, Returns the proper texture for a given time and base texture */ texture_t * -R_TextureAnimation (const entity_t *entity, msurface_t *surf) +R_TextureAnimation (const animation_t *animation, msurface_t *surf) { texture_t *base = surf->texinfo->texture; int count, relative; - if (entity->animation.frame) { + if (animation->frame) { if (base->alternate_anims) base = base->alternate_anims; } diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 3f2036d97..3c9845906 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -101,11 +101,12 @@ R_ClearEfrags (void) Call when removing an object from the world or moving it to another position */ void -R_RemoveEfrags (entity_t *ent) +R_RemoveEfrags (entity_t ent) { efrag_t *ef, *old, *walk, **prev; + visibility_t *vis = Ent_GetComponent (ent.id, scene_visibility, ent.reg); - ef = ent->visibility.efrag; + ef = vis->efrag; while (ef) { prev = &ef->leaf->efrags; @@ -128,12 +129,12 @@ R_RemoveEfrags (entity_t *ent) r_free_efrags = old; } - ent->visibility.efrag = 0; + vis->efrag = 0; } static void -R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, - vec3_t emins, vec3_t emaxs) +R_SplitEntityOnNode (mod_brush_t *brush, entity_t ent, uint32_t queue, + visibility_t *visibility, vec3_t emins, vec3_t emaxs) { efrag_t *ef; plane_t *splitplane; @@ -146,7 +147,7 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, node_stack = alloca ((brush->depth + 2) * sizeof (mnode_t *)); node_ptr = node_stack; - lastlink = &ent->visibility.efrag; + lastlink = &visibility->efrag; *node_ptr++ = brush->numnodes; @@ -154,8 +155,8 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, while (node_id != (int) brush->numnodes) { // add an efrag if the node is a leaf if (__builtin_expect (node_id < 0, 0)) { - if (ent->visibility.topnode_id == -1) { - ent->visibility.topnode_id = node_id; + if (visibility->topnode_id == -1) { + visibility->topnode_id = node_id; } leaf = brush->leafs + ~node_id; @@ -164,6 +165,7 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, // add the link to the chain of links on the entity ef->entity = ent; + ef->queue_num = queue; *lastlink = ef; lastlink = &ef->entnext; @@ -182,8 +184,8 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, if (sides == 3) { // split on this plane // if this is the first splitter of this bmodel, remember it - if (ent->visibility.topnode_id == -1) { - ent->visibility.topnode_id = node_id; + if (visibility->topnode_id == -1) { + visibility->topnode_id = node_id; } } // recurse down the contacted sides @@ -202,45 +204,34 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, } void -R_AddEfrags (mod_brush_t *brush, entity_t *ent) +R_AddEfrags (mod_brush_t *brush, entity_t ent) { model_t *entmodel; vec3_t emins, emaxs; + transform_t transform = Entity_Transform (ent); + renderer_t *rend = Ent_GetComponent (ent.id, scene_renderer, ent.reg); + visibility_t *vis = Ent_GetComponent (ent.id, scene_visibility, ent.reg); - if (!ent->renderer.model) { + if (!rend->model) { return; } - entmodel = ent->renderer.model; + entmodel = rend->model; - vec4f_t org = Transform_GetWorldPosition (ent->transform); + vec4f_t org = Transform_GetWorldPosition (transform); VectorAdd (org, entmodel->mins, emins); VectorAdd (org, entmodel->maxs, emaxs); - ent->visibility.topnode_id = -1; // leaf 0 (solid space) - R_SplitEntityOnNode (brush, ent, emins, emaxs); + vis->topnode_id = -1; // leaf 0 (solid space) + R_SplitEntityOnNode (brush, ent, rend->model->type, vis, emins, emaxs); } void R_StoreEfrags (const efrag_t *efrag) { - entity_t *ent; - model_t *model; - while (efrag) { - ent = efrag->entity; - model = ent->renderer.model; - - switch (model->type) { - case mod_alias: - case mod_brush: - case mod_sprite: - case mod_iqm: - EntQueue_AddEntity (r_ent_queue, ent, model->type); - break; - default: - break; - } + entity_t ent = efrag->entity; + EntQueue_AddEntity (r_ent_queue, ent, efrag->queue_num); efrag = efrag->leafnext; } } diff --git a/libs/video/renderer/r_iqm.c b/libs/video/renderer/r_iqm.c index aaecb5aab..488deb051 100644 --- a/libs/video/renderer/r_iqm.c +++ b/libs/video/renderer/r_iqm.c @@ -48,10 +48,9 @@ #include "r_internal.h" float -R_IQMGetLerpedFrames (entity_t *ent, iqm_t *iqm) +R_IQMGetLerpedFrames (animation_t *animation, iqm_t *iqm) { - animation_t *animation = &ent->animation; - int frame = ent->animation.frame; + int frame = animation->frame; float time, fullinterval; iqmanim *anim; @@ -64,7 +63,7 @@ R_IQMGetLerpedFrames (entity_t *ent, iqm_t *iqm) } anim = &iqm->anims[frame]; fullinterval = anim->num_frames / anim->framerate; - time = vr_data.realtime + ent->animation.syncbase; + time = vr_data.realtime + animation->syncbase; time -= ((int) (time / fullinterval)) * fullinterval; frame = (int) (time * anim->framerate) + anim->first_frame; return R_EntityBlend (animation, frame, 1.0 / anim->framerate); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 0d65bbea8..0dcd89afe 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -226,7 +226,7 @@ render_side (int side) } void -SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) +SCR_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) { if (scr_skipupdate || !scr_initialized) { return; @@ -241,7 +241,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) } refdef_t *refdef = r_data->refdef; - if (camera) { + if (Transform_Valid (camera)) { Transform_GetWorldMatrix (camera, refdef->camera); Transform_GetWorldInverse (camera, refdef->camera_inverse); } else { diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 84787f981..80f7c9671 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -31,7 +31,9 @@ #include "QF/cvar.h" #include "QF/render.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "d_local.h" #include "r_internal.h" @@ -143,6 +145,19 @@ D_CalcGradients (msurface_t *pface) bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; } +static void +transform_submodel_poly (surf_t *s) +{ + // FIXME: we don't want to do all this for every polygon! + // TODO: store once at start of frame + transform_t transform = Entity_Transform (s->entity); + vec4f_t local_modelorg = r_refdef.frame.position - + Transform_GetWorldPosition (transform); + TransformVector ((vec_t*)&local_modelorg, transformed_modelorg);//FIXME + + R_RotateBmodel (transform); // FIXME: don't mess with the + // frustum, make entity passed in +} void D_DrawSurfaces (void) @@ -151,7 +166,6 @@ D_DrawSurfaces (void) msurface_t *pface; surfcache_t *pcurrentcache; vec3_t world_transformed_modelorg; - vec4f_t local_modelorg; TransformVector (modelorg, transformed_modelorg); VectorCopy (transformed_modelorg, world_transformed_modelorg); @@ -204,16 +218,7 @@ D_DrawSurfaces (void) cachewidth = 64; if (s->insubmodel) { - // FIXME: we don't want to do all this for every polygon! - // TODO: store once at start of frame - transform_t *transform = s->entity->transform; - transform = s->entity->transform; - local_modelorg = r_refdef.frame.position - - Transform_GetWorldPosition (transform); - TransformVector ((vec_t*)&local_modelorg, transformed_modelorg);//FIXME - - R_RotateBmodel (transform); // FIXME: don't mess with the - // frustum, make entity passed in + transform_submodel_poly (s); } D_CalcGradients (pface); @@ -236,15 +241,7 @@ D_DrawSurfaces (void) } } else { if (s->insubmodel) { - // FIXME: we don't want to do all this for every polygon! - // TODO: store once at start of frame - transform_t *transform = s->entity->transform; - local_modelorg = r_refdef.frame.position - - Transform_GetWorldPosition (transform); - TransformVector ((vec_t*)&local_modelorg, transformed_modelorg);//FIXME - - R_RotateBmodel (transform); // FIXME: don't mess with the - // frustum, make entity passed in + transform_submodel_poly (s); } pface = s->data; diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 26ee3c5bb..777af38d3 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -33,7 +33,9 @@ #include "QF/qargs.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "compat.h" #include "d_local.h" @@ -225,12 +227,14 @@ D_SCDump (void) #endif surfcache_t * -D_CacheSurface (entity_t *ent, msurface_t *surface, int miplevel) +D_CacheSurface (entity_t ent, msurface_t *surface, int miplevel) { surfcache_t *cache; + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, r_refdef.scene->reg); + transform_t transform = Entity_Transform (ent); // if the surface is animating or flashing, flush the cache - r_drawsurf.texture = R_TextureAnimation (ent, surface); + r_drawsurf.texture = R_TextureAnimation (animation, surface); r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; @@ -281,7 +285,7 @@ D_CacheSurface (entity_t *ent, msurface_t *surface, int miplevel) r_drawsurf.surf = surface; c_surf++; - R_DrawSurface (ent->transform); + R_DrawSurface (transform); return surface->cachespots[miplevel]; } diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 05ae2c1fa..d713b0462 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -36,7 +36,9 @@ #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "d_ifacea.h" #include "r_internal.h" @@ -83,10 +85,10 @@ static aedge_t aedges[12] = { {0, 5}, {1, 4}, {2, 7}, {3, 6} }; -static void R_AliasSetUpTransform (entity_t *ent, int trivial_accept); +static void R_AliasSetUpTransform (entity_t ent, int trivial_accept); qboolean -R_AliasCheckBBox (entity_t *ent) +R_AliasCheckBBox (entity_t ent) { int i, flags, frame, numv; aliashdr_t *pahdr; @@ -97,10 +99,16 @@ R_AliasCheckBBox (entity_t *ent) qboolean zclipped, zfullyclipped; unsigned int anyclip, allclip; int minz; + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); // expand, rotate, and translate points into worldspace - ent->visibility.trivial_accept = 0; - pmodel = ent->renderer.model; + visibility->trivial_accept = 0; + pmodel = renderer->model; if (!(pahdr = pmodel->aliashdr)) pahdr = Cache_Get (&pmodel->cache); pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model); @@ -108,7 +116,7 @@ R_AliasCheckBBox (entity_t *ent) R_AliasSetUpTransform (ent, 0); // construct the base bounding box for this frame - frame = ent->animation.frame; + frame = animation->frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { Sys_MaskPrintf (SYS_dev, "No such frame %d %s\n", frame, pmodel->path); @@ -223,11 +231,11 @@ R_AliasCheckBBox (entity_t *ent) return false; // trivial reject off one side } - ent->visibility.trivial_accept = !anyclip & !zclipped; + visibility->trivial_accept = !anyclip & !zclipped; - if (ent->visibility.trivial_accept) { + if (visibility->trivial_accept) { if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) { - ent->visibility.trivial_accept |= 2; + visibility->trivial_accept |= 2; } } @@ -354,13 +362,14 @@ R_AliasPreparePoints (void) } static void -R_AliasSetUpTransform (entity_t *ent, int trivial_accept) +R_AliasSetUpTransform (entity_t ent, int trivial_accept) { int i; float rotationmatrix[3][4]; - mat4f_t mat; + transform_t transform = Entity_Transform (ent); - Transform_GetWorldMatrix (ent->transform, mat); + mat4f_t mat; + Transform_GetWorldMatrix (transform, mat); VectorCopy (mat[0], alias_forward); VectorCopy (mat[1], alias_left); VectorCopy (mat[2], alias_up); @@ -520,18 +529,22 @@ R_AliasPrepareUnclippedPoints (void) } static void -R_AliasSetupSkin (entity_t *ent) +R_AliasSetupSkin (entity_t ent) { int skinnum; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); - skinnum = ent->renderer.skinnum; + skinnum = renderer->skinnum; if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { Sys_MaskPrintf (SYS_dev, "R_AliasSetupSkin: no such skin # %d\n", skinnum); skinnum = 0; } - pskindesc = R_AliasGetSkindesc (&ent->animation, skinnum, paliashdr); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); + pskindesc = R_AliasGetSkindesc (animation, skinnum, paliashdr); a_skinwidth = pmdl->skinwidth; @@ -541,16 +554,16 @@ R_AliasSetupSkin (entity_t *ent) r_affinetridesc.skinheight = pmdl->skinheight; acolormap = r_colormap; - if (ent->renderer.skin) { + if (renderer->skin) { tex_t *base; - base = ent->renderer.skin->texels; + base = renderer->skin->texels; if (base) { r_affinetridesc.pskin = base->data; r_affinetridesc.skinwidth = base->width; r_affinetridesc.skinheight = base->height; } - acolormap = ent->renderer.skin->colormap; + acolormap = renderer->skin->colormap; } } @@ -589,25 +602,31 @@ R_AliasSetupLighting (alight_t *lighting) set r_apverts */ static void -R_AliasSetupFrame (entity_t *ent) +R_AliasSetupFrame (entity_t ent) { maliasframedesc_t *frame; - frame = R_AliasGetFramedesc (&ent->animation, paliashdr); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); + frame = R_AliasGetFramedesc (animation, paliashdr); r_apverts = (trivertx_t *) ((byte *) paliashdr + frame->frame); } void -R_AliasDrawModel (entity_t *ent, alight_t *lighting) +R_AliasDrawModel (entity_t ent, alight_t *lighting) { int size; finalvert_t *finalverts; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + r_refdef.scene->reg); r_amodels_drawn++; - if (!(paliashdr = ent->renderer.model->aliashdr)) - paliashdr = Cache_Get (&ent->renderer.model->cache); + if (!(paliashdr = renderer->model->aliashdr)) + paliashdr = Cache_Get (&renderer->model->cache); pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model); size = (CACHE_SIZE - 1) @@ -623,11 +642,11 @@ R_AliasDrawModel (entity_t *ent, alight_t *lighting) pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1]; R_AliasSetupSkin (ent); - R_AliasSetUpTransform (ent, ent->visibility.trivial_accept); + R_AliasSetUpTransform (ent, visibility->trivial_accept); R_AliasSetupLighting (lighting); R_AliasSetupFrame (ent); - r_affinetridesc.drawtype = ((ent->visibility.trivial_accept == 3) + r_affinetridesc.drawtype = ((visibility->trivial_accept == 3) && r_recursiveaffinetriangles); if (!acolormap) @@ -641,18 +660,19 @@ R_AliasDrawModel (entity_t *ent, alight_t *lighting) #endif } - if (ent != vr_data.view_model) + //FIXME depth hack + if (ent.id != vr_data.view_model.id) ziscale = (float) 0x8000 *(float) 0x10000; else ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - if (ent->visibility.trivial_accept && pmdl->ident != HEADER_MDL16) { + if (visibility->trivial_accept && pmdl->ident != HEADER_MDL16) { R_AliasPrepareUnclippedPoints (); } else { R_AliasPreparePoints (); } - if (!ent->renderer.model->aliashdr) { - Cache_Release (&ent->renderer.model->cache); + if (!renderer->model->aliashdr) { + Cache_Release (&renderer->model->cache); } } diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 7ef8e20fd..e8544abd5 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -36,13 +36,15 @@ #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "r_internal.h" typedef struct glbspctx_s { mod_brush_t *brush; - entity_t *entity; + entity_t entity; } swbspctx_t; // current entity info @@ -83,7 +85,7 @@ R_EntityRotate (vec3_t vec) void -R_RotateBmodel (transform_t *transform) +R_RotateBmodel (transform_t transform) { mat4f_t mat; Transform_GetWorldMatrix (transform, mat); @@ -102,7 +104,7 @@ R_RotateBmodel (transform_t *transform) static void -R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode, +R_RecursiveClipBPoly (entity_t ent, bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) { bedge_t *psideedges[2], *pnextedge, *ptedge; @@ -250,7 +252,7 @@ R_RecursiveClipBPoly (entity_t *ent, bedge_t *pedges, mnode_t *pnode, void -R_DrawSolidClippedSubmodelPolygons (entity_t *ent, model_t *model, +R_DrawSolidClippedSubmodelPolygons (entity_t ent, model_t *model, mnode_t *topnode) { int i, j, lindex; @@ -321,7 +323,7 @@ R_DrawSolidClippedSubmodelPolygons (entity_t *ent, model_t *model, void -R_DrawSubmodelPolygons (entity_t *ent, model_t *model, int clipflags, +R_DrawSubmodelPolygons (entity_t ent, model_t *model, int clipflags, mleaf_t *topleaf) { int i; @@ -377,8 +379,8 @@ visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags) { int c; msurface_t *surf; - entity_t *ent = bctx->entity; - mod_brush_t *brush = &ent->renderer.model->brush; + entity_t ent = bctx->entity; + mod_brush_t *brush = bctx->brush; // sneaky hack for side = side ? SURF_PLANEBACK : 0; side = (~side + 1) & SURF_PLANEBACK; @@ -474,7 +476,7 @@ R_VisitWorldNodes (swbspctx_t *bctx, int clipflags) int front; int side, cf; int node_id; - mod_brush_t *brush = &bctx->entity->renderer.model->brush; + mod_brush_t *brush = bctx->brush; // +2 for paranoia node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t)); @@ -531,14 +533,12 @@ R_RenderWorld (void) { int i; btofpoly_t btofpolys[MAX_BTOFPOLYS]; - static entity_t worldent = {}; - entity_t *ent = &worldent; + entity_t ent = nullentity; mod_brush_t *brush = &r_refdef.worldmodel->brush; swbspctx_t bspctx = { brush, ent, }; - worldent.renderer.model = r_refdef.worldmodel; pbtofpolys = btofpolys; diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index 9fc454ca4..d6b544512 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -29,7 +29,9 @@ #endif #include "QF/render.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "r_internal.h" @@ -345,7 +347,7 @@ R_EmitCachedEdge (void) void -R_RenderFace (entity_t *ent, msurface_t *fa, int clipflags) +R_RenderFace (entity_t ent, msurface_t *fa, int clipflags) { int i, lindex; unsigned int mask; @@ -354,7 +356,9 @@ R_RenderFace (entity_t *ent, msurface_t *fa, int clipflags) vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; - mod_brush_t *brush = &ent->renderer.model->brush; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + mod_brush_t *brush = &renderer->model->brush; // skip out if no more surfs if ((surface_p) >= surf_max) { @@ -511,7 +515,7 @@ R_RenderFace (entity_t *ent, msurface_t *fa, int clipflags) void -R_RenderBmodelFace (entity_t *ent, bedge_t *pedges, msurface_t *psurf) +R_RenderBmodelFace (entity_t ent, bedge_t *pedges, msurface_t *psurf) { int i; unsigned int mask; @@ -610,7 +614,7 @@ R_RenderBmodelFace (entity_t *ent, bedge_t *pedges, msurface_t *psurf) void -R_RenderPoly (entity_t *ent, msurface_t *fa, int clipflags) +R_RenderPoly (entity_t ent, msurface_t *fa, int clipflags) { int i, lindex, lnumverts, s_axis, t_axis; float dist, lastdist, lzi, scale, u, v, frac; @@ -623,7 +627,9 @@ R_RenderPoly (entity_t *ent, msurface_t *fa, int clipflags) polyvert_t pverts[100]; // FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; qboolean visible; - mod_brush_t *brush = &ent->renderer.model->brush; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + mod_brush_t *brush = &renderer->model->brush; // FIXME: clean this up and make it faster // FIXME: guard against running out of vertices @@ -778,7 +784,7 @@ R_RenderPoly (entity_t *ent, msurface_t *fa, int clipflags) void -R_ZDrawSubmodelPolys (entity_t *ent, model_t *model) +R_ZDrawSubmodelPolys (entity_t ent, model_t *model) { int i, numsurfaces; msurface_t *psurf; diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index 6c6a5608b..64f3230d7 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -45,7 +45,9 @@ #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "d_ifacea.h" #include "r_internal.h" @@ -211,7 +213,7 @@ R_IQMPreparePoints (iqm_t *iqm, swiqm_t *sw, iqmframe_t *frame) } static void -R_IQMSetupLighting (entity_t *ent, alight_t *plighting) +R_IQMSetupLighting (entity_t ent, alight_t *plighting) { // guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't // have to clamp off the bottom @@ -234,7 +236,8 @@ R_IQMSetupLighting (entity_t *ent, alight_t *plighting) // rotate the lighting vector into the model's frame of reference mat4f_t mat; - Transform_GetWorldMatrix (ent->transform, mat); + transform_t transform = Entity_Transform (ent); + Transform_GetWorldMatrix (transform, mat); //FIXME vectorize r_lightvec[0] = DotProduct (plighting->lightvec, mat[0]); r_lightvec[1] = DotProduct (plighting->lightvec, mat[1]); @@ -242,14 +245,15 @@ R_IQMSetupLighting (entity_t *ent, alight_t *plighting) } static void -R_IQMSetUpTransform (entity_t *ent, int trivial_accept) +R_IQMSetUpTransform (entity_t ent, int trivial_accept) { int i; float rotationmatrix[3][4]; vec3_t forward, left, up; mat4f_t mat; - Transform_GetWorldMatrix (ent->transform, mat); + transform_t transform = Entity_Transform (ent); + Transform_GetWorldMatrix (transform, mat); VectorCopy (mat[0], forward); VectorCopy (mat[1], left); VectorCopy (mat[2], up); @@ -286,9 +290,15 @@ R_IQMSetUpTransform (entity_t *ent, int trivial_accept) } void -R_IQMDrawModel (entity_t *ent, alight_t *plighting) +R_IQMDrawModel (entity_t ent, alight_t *plighting) { - model_t *model = ent->renderer.model; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); + model_t *model = renderer->model; iqm_t *iqm = (iqm_t *) model->aliashdr; swiqm_t *sw = (swiqm_t *) iqm->extra_data; int size; @@ -298,8 +308,8 @@ R_IQMDrawModel (entity_t *ent, alight_t *plighting) size = (CACHE_SIZE - 1) + sizeof (finalvert_t) * (iqm->num_verts + 1) + sizeof (auxvert_t) * iqm->num_verts; - blend = R_IQMGetLerpedFrames (ent, iqm); - frame = R_IQMBlendPalette (iqm, ent->animation.pose1, ent->animation.pose2, + blend = R_IQMGetLerpedFrames (animation, iqm); + frame = R_IQMBlendPalette (iqm, animation->pose1, animation->pose2, blend, size, sw->blend_palette, sw->palette_size); @@ -308,21 +318,22 @@ R_IQMDrawModel (entity_t *ent, alight_t *plighting) (((intptr_t) &pfinalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); pauxverts = (auxvert_t *) &pfinalverts[iqm->num_verts + 1]; - R_IQMSetUpTransform (ent, ent->visibility.trivial_accept); + R_IQMSetUpTransform (ent, visibility->trivial_accept); R_IQMSetupLighting (ent, plighting); - r_affinetridesc.drawtype = (ent->visibility.trivial_accept == 3) && + r_affinetridesc.drawtype = (visibility->trivial_accept == 3) && r_recursiveaffinetriangles; //if (!acolormap) acolormap = r_colormap; - if (ent != vr_data.view_model) + //FIXME depth hack + if (ent.id != vr_data.view_model.id) ziscale = (float) 0x8000 *(float) 0x10000; else ziscale = (float) 0x8000 *(float) 0x10000 *3.0; - if (ent->visibility.trivial_accept) + if (visibility->trivial_accept) R_IQMPrepareUnclippedPoints (iqm, sw, frame); else R_IQMPreparePoints (iqm, sw, frame); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 7edac2b8d..32e00c85a 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -42,6 +42,7 @@ #include "QF/cmd.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" @@ -151,6 +152,7 @@ R_NewScene (scene_t *scene) model_t *worldmodel = scene->worldmodel; mod_brush_t *brush = &worldmodel->brush; + r_refdef.scene = scene; r_refdef.worldmodel = worldmodel; // clear out efrags in case the level hasn't been reloaded @@ -217,13 +219,13 @@ R_SetColormap (const byte *cmap) } static inline void -draw_sprite_entity (entity_t *ent) +draw_sprite_entity (entity_t ent) { R_DrawSprite (ent); } static inline void -setup_lighting (entity_t *ent, alight_t *lighting) +setup_lighting (entity_t ent, alight_t *lighting) { float minlight = 0; int j; @@ -232,7 +234,9 @@ setup_lighting (entity_t *ent, alight_t *lighting) float add; float lightvec[3] = { -1, 0, 0 }; - minlight = max (ent->renderer.model->min_light, ent->renderer.min_light); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + minlight = max (renderer->model->min_light, renderer->min_light); // 128 instead of 255 due to clamping below j = max (R_LightPoint (&r_refdef.worldmodel->brush, r_entorigin), @@ -261,11 +265,13 @@ setup_lighting (entity_t *ent, alight_t *lighting) } static inline void -draw_alias_entity (entity_t *ent) +draw_alias_entity (entity_t ent) { // see if the bounding box lets us trivially reject, also // sets trivial accept status - ent->visibility.trivial_accept = 0; //FIXME + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + r_refdef.scene->reg); + visibility->trivial_accept = 0; //FIXME if (R_AliasCheckBBox (ent)) { alight_t lighting; setup_lighting (ent, &lighting); @@ -274,11 +280,13 @@ draw_alias_entity (entity_t *ent) } static inline void -draw_iqm_entity (entity_t *ent) +draw_iqm_entity (entity_t ent) { // see if the bounding box lets us trivially reject, also // sets trivial accept status - ent->visibility.trivial_accept = 0; //FIXME + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + r_refdef.scene->reg); + visibility->trivial_accept = 0; //FIXME alight_t lighting; setup_lighting (ent, &lighting); @@ -296,8 +304,9 @@ R_DrawEntitiesOnList (entqueue_t *queue) do { \ for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ i++) { \ - entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \ - r_entorigin = Transform_GetWorldPosition (ent->transform); \ + entity_t ent = queue->ent_queues[mod_##type_name].a[i]; \ + transform_t transform = Entity_Transform (ent); \ + r_entorigin = Transform_GetWorldPosition (transform); \ draw_##type_name##_entity (ent); \ } \ } while (0) @@ -319,7 +328,7 @@ R_DrawViewModel (void) float add; float minlight; dlight_t *dl; - entity_t *viewent; + entity_t viewent; alight_t lighting; if (vr_data.inhibit_viewmodel @@ -328,15 +337,18 @@ R_DrawViewModel (void) return; viewent = vr_data.view_model; - if (!viewent->renderer.model) + + renderer_t *renderer = Ent_GetComponent (viewent.id, scene_renderer, + r_refdef.scene->reg); + transform_t transform = Entity_Transform (viewent); + if (!renderer->model) return; - VectorCopy (Transform_GetWorldPosition (viewent->transform), r_entorigin); + VectorCopy (Transform_GetWorldPosition (transform), r_entorigin); VectorNegate (vup, lighting.lightvec); - minlight = max (viewent->renderer.min_light, - viewent->renderer.model->min_light); + minlight = max (renderer->min_light, renderer->model->min_light); j = max (R_LightPoint (&r_refdef.worldmodel->brush, r_entorigin), minlight * 128); @@ -370,7 +382,7 @@ R_DrawViewModel (void) } static int -R_BmodelCheckBBox (entity_t *ent, model_t *clmodel, float *minmaxs) +R_BmodelCheckBBox (entity_t ent, model_t *clmodel, float *minmaxs) { int i, *pindex, clipflags; vec3_t acceptpt, rejectpt; @@ -379,7 +391,8 @@ R_BmodelCheckBBox (entity_t *ent, model_t *clmodel, float *minmaxs) clipflags = 0; - Transform_GetWorldMatrix (ent->transform, mat); + transform_t transform = Entity_Transform (ent); + Transform_GetWorldMatrix (transform, mat); if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { for (i = 0; i < 4; i++) { d = DotProduct (mat[3], view_clipplanes[i].normal); @@ -439,10 +452,15 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) insubmodel = true; for (size_t i = 0; i < queue->ent_queues[mod_brush].size; i++) { - entity_t *ent = queue->ent_queues[mod_brush].a[i]; + entity_t ent = queue->ent_queues[mod_brush].a[i]; - VectorCopy (Transform_GetWorldPosition (ent->transform), origin); - clmodel = ent->renderer.model; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + transform_t transform = Entity_Transform (ent); + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + r_refdef.scene->reg); + VectorCopy (Transform_GetWorldPosition (transform), origin); + clmodel = renderer->model; // see if the bounding box lets us trivially reject, also // sets trivial accept status @@ -461,7 +479,7 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) r_pcurrentvertbase = brush->vertexes; // FIXME: stop transforming twice - R_RotateBmodel (ent->transform); + R_RotateBmodel (transform); // calculate dynamic lighting for bmodel if it's not an // instanced model @@ -486,7 +504,7 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) if (r_drawpolys | r_drawculledpolys) { R_ZDrawSubmodelPolys (ent, clmodel); } else { - int topnode_id = ent->visibility.topnode_id; + int topnode_id = visibility->topnode_id; mod_brush_t *brush = &r_refdef.worldmodel->brush; if (topnode_id >= 0) { @@ -583,7 +601,7 @@ R_RenderView_ (void) R_EdgeDrawing (r_ent_queue); - if (vr_data.view_model) { + if (Entity_Valid (vr_data.view_model)) { R_DrawViewModel (); } diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index f5e612dfb..7a536483c 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -40,7 +40,9 @@ #include "QF/render.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "r_internal.h" @@ -241,13 +243,18 @@ R_SetupAndDrawSprite (const vec3_t relvieworg) } void -R_DrawSprite (entity_t *ent) +R_DrawSprite (entity_t ent) { - msprite_t *sprite = ent->renderer.model->cache.data; + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); + msprite_t *sprite = renderer->model->cache.data; vec4f_t cameravec = r_refdef.frame.position - r_entorigin; - r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, &ent->animation); + r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, animation); sprite_width = r_spritedesc.pspriteframe->width; sprite_height = r_spritedesc.pspriteframe->height; @@ -255,7 +262,8 @@ R_DrawSprite (entity_t *ent) vec4f_t up = {}; vec4f_t right = {}; vec4f_t fwd = {}; - if (!R_BillboardFrame (ent, sprite->type, cameravec, &up, &right, &fwd)) { + if (!R_BillboardFrame (transform, sprite->type, cameravec, + &up, &right, &fwd)) { // the orientation is undefined so can't draw the sprite return; } diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 601bf2d8d..2b111cdf4 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -73,7 +73,7 @@ static unsigned int blocklights[34 * 34]; //FIXME make dynamic static void -R_AddDynamicLights (transform_t *transform) +R_AddDynamicLights (transform_t transform) { msurface_t *surf; unsigned int lnum; @@ -91,7 +91,7 @@ R_AddDynamicLights (transform_t *transform) tmax = (surf->extents[1] >> 4) + 1; tex = surf->texinfo; - if (transform) { + if (Transform_Valid (transform)) { //FIXME give world entity a transform entorigin = Transform_GetWorldPosition (transform); } @@ -144,7 +144,7 @@ R_AddDynamicLights (transform_t *transform) Combine and scale multiple lightmaps into the 8.8 format in blocklights */ static void -R_BuildLightMap (transform_t *transform) +R_BuildLightMap (transform_t transform) { int smax, tmax; int t; @@ -194,7 +194,7 @@ R_BuildLightMap (transform_t *transform) } void -R_DrawSurface (transform_t *transform) +R_DrawSurface (transform_t transform) { byte *basetptr; int smax, tmax, twidth; diff --git a/libs/video/renderer/vid_common.c b/libs/video/renderer/vid_common.c index c8edf8067..40707b60a 100644 --- a/libs/video/renderer/vid_common.c +++ b/libs/video/renderer/vid_common.c @@ -31,6 +31,8 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" +#include "QF/scene/component.h" + #include "QF/ui/view.h" #include "mod_internal.h" @@ -54,7 +56,7 @@ vid_render_data_t vid_render_data = { .inhibit_viewmodel = false, .paused = false, .lineadj = 0, - .view_model = 0, + .view_model = nullentity, .frametime = 0.0, .realtime = 0.0, .lightstyle = 0, diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 26e5b404e..1496023e6 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -38,7 +38,9 @@ #include "QF/cvar.h" #include "QF/va.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_matrices.h" @@ -76,7 +78,7 @@ static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_alias_skin_t *skin, uint32_t numPC, qfv_push_constants_t *constants, - aliashdr_t *hdr, qfv_renderframe_t *rFrame, entity_t *ent) + aliashdr_t *hdr, qfv_renderframe_t *rFrame, entity_t ent) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -116,15 +118,19 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, } void -Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) +Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) { + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); vulkan_ctx_t *ctx = rFrame->vulkan_ctx; aliasctx_t *actx = ctx->alias_context; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - model_t *model = ent->renderer.model; + model_t *model = renderer->model; aliashdr_t *hdr; qfv_alias_skin_t *skin; - animation_t *animation = &ent->animation; alias_push_constants_t constants = {}; if (!(hdr = model->aliashdr)) { @@ -136,7 +142,7 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) qfv_push_constants_t push_constants[] = { { VK_SHADER_STAGE_VERTEX_BIT, field_offset (alias_push_constants_t, mat), - sizeof (mat4f_t), Transform_GetWorldMatrixPtr (ent->transform) }, + sizeof (mat4f_t), Transform_GetWorldMatrixPtr (transform) }, { VK_SHADER_STAGE_VERTEX_BIT, field_offset (alias_push_constants_t, blend), sizeof (float), &constants.blend }, @@ -158,19 +164,19 @@ Vulkan_DrawAlias (entity_t *ent, qfv_renderframe_t *rFrame) //skin = ent->skin->tex; } else { maliasskindesc_t *skindesc; - skindesc = R_AliasGetSkindesc (animation, ent->renderer.skinnum, hdr); + skindesc = R_AliasGetSkindesc (animation, renderer->skinnum, hdr); skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } - QuatCopy (ent->renderer.colormod, constants.base_color); + QuatCopy (renderer->colormod, constants.base_color); QuatCopy (skin->colora, constants.colorA); QuatCopy (skin->colorb, constants.colorB); QuatZero (constants.fog); emit_commands (aframe->cmdSet.a[QFV_aliasDepth], - ent->animation.pose1, ent->animation.pose2, + animation->pose1, animation->pose2, 0, 2, push_constants, hdr, rFrame, ent); emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], - ent->animation.pose1, ent->animation.pose2, + animation->pose1, animation->pose2, skin, 6, push_constants, hdr, rFrame, ent); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 96101e26f..985afec79 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -52,7 +52,9 @@ #include "QF/va.h" #include "QF/math/bitop.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" @@ -583,16 +585,20 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } static int -R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx) +R_DrawBrushModel (entity_t ent, bsp_pass_t *pass, vulkan_ctx_t *ctx) { + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); float radius; - model_t *model; + model_t *model = renderer->model; vec3_t mins, maxs; bspctx_t *bctx = ctx->bsp_context; - model = e->renderer.model; mat4f_t mat; - Transform_GetWorldMatrix (e->transform, mat); + Transform_GetWorldMatrix (transform, mat); if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { radius = model->radius; if (R_CullSphere (pass->frustum, (vec_t*)&mat[3], radius)) { //FIXME @@ -604,13 +610,13 @@ R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx) if (R_CullBox (pass->frustum, mins, maxs)) return 1; } - if (Vulkan_Scene_AddEntity (ctx, e) < 0) { + if (Vulkan_Scene_AddEntity (ctx, ent) < 0) { return 0; } - pass->ent_frame = e->animation.frame & 1; + pass->ent_frame = animation->frame & 1; pass->inst_id = model->render_id; - pass->inst_id |= e->renderer.colormod[3] < 1 ? INST_ALPHA : 0; + pass->inst_id |= renderer->colormod[3] < 1 ? INST_ALPHA : 0; if (!pass->instances[model->render_id].entities.size) { bsp_model_t *m = &bctx->models[model->render_id]; bsp_face_t *face = &bctx->faces[m->first_face]; @@ -620,7 +626,7 @@ R_DrawBrushModel (entity_t *e, bsp_pass_t *pass, vulkan_ctx_t *ctx) } } DARRAY_APPEND (&pass->instances[model->render_id].entities, - e->renderer.render_id); + renderer->render_id); return 1; } @@ -1028,9 +1034,13 @@ draw_queue (bsp_pass_t *pass, int queue, VkPipelineLayout layout, static int ent_model_cmp (const void *_a, const void *_b) { - const entity_t * const *a = _a; - const entity_t * const *b = _b; - return (*a)->renderer.model->render_id - (*b)->renderer.model->render_id; + const entity_t *a = _a; + const entity_t *b = _b; + renderer_t *ra = Ent_GetComponent (a->id, scene_renderer, + r_refdef.scene->reg); + renderer_t *rb = Ent_GetComponent (b->id, scene_renderer, + r_refdef.scene->reg); + return ra->model->render_id - rb->model->render_id; } void @@ -1057,22 +1067,15 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) clear_queues (bctx, &bctx->main_pass); // do this first for water and skys bframe->index_count = 0; - entity_t worldent = { - .renderer = { - .model = r_refdef.worldmodel, - .colormod = { 1, 1, 1, 1 }, - }, - }; + entity_t worldent = nullentity; - Vulkan_Scene_AddEntity (ctx, &worldent); + int world_id = Vulkan_Scene_AddEntity (ctx, worldent); - int world_id = worldent.renderer.model->render_id; bctx->main_pass.ent_frame = 0; // world is always frame 0 bctx->main_pass.inst_id = world_id; - bctx->main_pass.brush = &worldent.renderer.model->brush; + bctx->main_pass.brush = &r_refdef.worldmodel->brush; if (bctx->main_pass.instances) { - DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, - worldent.renderer.render_id); + DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, world_id); } R_VisitWorldNodes (&bctx->main_pass, ctx); if (!bctx->vertex_buffer) { @@ -1081,9 +1084,9 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) if (r_drawentities) { heapsort (r_ent_queue->ent_queues[mod_brush].a, r_ent_queue->ent_queues[mod_brush].size, - sizeof (entity_t *), ent_model_cmp); + sizeof (entity_t), ent_model_cmp); for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { - entity_t *ent = r_ent_queue->ent_queues[mod_brush].a[i]; + entity_t ent = r_ent_queue->ent_queues[mod_brush].a[i]; if (!R_DrawBrushModel (ent, &bctx->main_pass, ctx)) { Sys_Printf ("Too many entities!\n"); break; diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index f2491aca5..7b9f743d9 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -37,7 +37,9 @@ #include "QF/iqm.h" #include "QF/va.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_matrices.h" @@ -77,7 +79,7 @@ static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_iqm_skin_t *skins, uint32_t numPC, qfv_push_constants_t *constants, - iqm_t *iqm, qfv_renderframe_t *rFrame, entity_t *ent) + iqm_t *iqm, qfv_renderframe_t *rFrame, entity_t ent) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -126,22 +128,27 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, #define a(x) ((x) & ~0x3f) void -Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) +Vulkan_DrawIQM (entity_t ent, qfv_renderframe_t *rFrame) { + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; iqmctx_t *ictx = ctx->iqm_context; iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; - model_t *model = ent->renderer.model; + model_t *model = renderer->model; iqm_t *iqm = (iqm_t *) model->aliashdr; qfv_iqm_t *mesh = iqm->extra_data; qfv_iqm_skin_t *skins = mesh->skins; iqm_push_constants_t constants = {}; iqmframe_t *frame; - constants.blend = R_IQMGetLerpedFrames (ent, iqm); - frame = R_IQMBlendFrames (iqm, ent->animation.pose1, ent->animation.pose2, + constants.blend = R_IQMGetLerpedFrames (animation, iqm); + frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2, constants.blend, 0); vec4f_t *bone_data; @@ -170,7 +177,7 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) qfv_push_constants_t push_constants[] = { { VK_SHADER_STAGE_VERTEX_BIT, field_offset (iqm_push_constants_t, mat), - sizeof (mat4f_t), Transform_GetWorldMatrixPtr (ent->transform) }, + sizeof (mat4f_t), Transform_GetWorldMatrixPtr (transform) }, { VK_SHADER_STAGE_VERTEX_BIT, field_offset (iqm_push_constants_t, blend), sizeof (float), &constants.blend }, @@ -188,16 +195,16 @@ Vulkan_DrawIQM (entity_t *ent, qfv_renderframe_t *rFrame) sizeof (constants.fog), &constants.fog }, }; - QuatCopy (ent->renderer.colormod, constants.base_color); + QuatCopy (renderer->colormod, constants.base_color); QuatCopy (skins[0].colora, constants.colorA); QuatCopy (skins[0].colorb, constants.colorB); QuatZero (constants.fog); emit_commands (aframe->cmdSet.a[QFV_iqmDepth], - ent->animation.pose1, ent->animation.pose2, + animation->pose1, animation->pose2, 0, 2, push_constants, iqm, rFrame, ent); emit_commands (aframe->cmdSet.a[QFV_iqmGBuffer], - ent->animation.pose1, ent->animation.pose2, + animation->pose1, animation->pose2, skins, 6, push_constants, iqm, rFrame, ent); } diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 877e45d03..c5c232b5a 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -45,6 +45,7 @@ #include "QF/screen.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" @@ -78,19 +79,19 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame) int begun = 0; \ for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ i++) { \ - entity_t *ent = queue->ent_queues[mod_##type_name].a[i]; \ + entity_t ent = queue->ent_queues[mod_##type_name].a[i]; \ if (!begun) { \ Vulkan_##Type##Begin (rFrame); \ begun = 1; \ } \ - /* hack the depth range to prevent view model */\ + /* FIXME hack the depth range to prevent view model */\ /* from poking into walls */\ - if (ent == vr_data.view_model) { \ + if (ent.id == vr_data.view_model.id) { \ Vulkan_AliasDepthRange (rFrame, 0, 0.3); \ } \ Vulkan_Draw##Type (ent, rFrame); \ /* unhack in case the view_model is not the last */\ - if (ent == vr_data.view_model) { \ + if (ent.id == vr_data.view_model.id) { \ Vulkan_AliasDepthRange (rFrame, 0, 1); \ } \ } \ @@ -106,14 +107,16 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame) static void Vulkan_DrawViewModel (vulkan_ctx_t *ctx) { - entity_t *ent = vr_data.view_model; + entity_t ent = vr_data.view_model; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); if (vr_data.inhibit_viewmodel || !r_drawviewmodel || !r_drawentities - || !ent->renderer.model) + || !renderer->model) return; - EntQueue_AddEntity (r_ent_queue, ent, ent->renderer.model->type); + EntQueue_AddEntity (r_ent_queue, ent, renderer->model->type); } void @@ -127,7 +130,7 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) Vulkan_DrawWorld (rFrame); Vulkan_DrawSky (rFrame); - if (vr_data.view_model) { + if (Entity_Valid (vr_data.view_model)) { Vulkan_DrawViewModel (ctx); } Vulkan_DrawWaterSurfaces (rFrame); @@ -145,6 +148,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) d_lightstylevalue[i] = 264; // normal light value } + r_refdef.scene = scene; r_refdef.worldmodel = scene->worldmodel; // Force a vis update diff --git a/libs/video/renderer/vulkan/vulkan_scene.c b/libs/video/renderer/vulkan/vulkan_scene.c index 1fcf12dab..4713cf8e6 100644 --- a/libs/video/renderer/vulkan/vulkan_scene.c +++ b/libs/video/renderer/vulkan/vulkan_scene.c @@ -37,7 +37,9 @@ #include "QF/set.h" #include "QF/va.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/debug.h" @@ -46,6 +48,7 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/resource.h" +#include "r_internal.h" #include "vid_vulkan.h" static const int qfv_max_entities = 4096; //FIXME should make dynamic @@ -66,39 +69,50 @@ Vulkan_Scene_Descriptors (vulkan_ctx_t *ctx) } int -Vulkan_Scene_AddEntity (vulkan_ctx_t *ctx, entity_t *entity) +Vulkan_Scene_AddEntity (vulkan_ctx_t *ctx, entity_t entity) { scenectx_t *sctx = ctx->scene_context; scnframe_t *sframe = &sctx->frames.a[ctx->curFrame]; entdata_t *entdata = 0; //lock - int id = -entity->id; + int id = Ent_Index (entity.id + 1);//nullent -> 0 if (!set_is_member (sframe->pooled_entities, id)) { if (sframe->entity_pool.size < sframe->entity_pool.maxSize) { set_add (sframe->pooled_entities, id); - entity->renderer.render_id = sframe->entity_pool.size++; - entdata = sframe->entity_pool.a + entity->renderer.render_id; + id = sframe->entity_pool.size++; + entdata = sframe->entity_pool.a + id; } else { - entity->renderer.render_id = -1; + id = -1; } } + if (Entity_Valid (entity)) { + renderer_t *renderer = Ent_GetComponent (entity.id, scene_renderer, + r_refdef.scene->reg); + renderer->render_id = -1; + } //unlock if (entdata) { mat4f_t f; - if (entity->transform) { //FIXME give world entity an entity :P - mat4ftranspose (f, Transform_GetWorldMatrixPtr (entity->transform)); + vec4f_t color; + if (Entity_Valid (entity)) { //FIXME give world entity an entity :P + transform_t transform = Entity_Transform (entity); + renderer_t *renderer = Ent_GetComponent (entity.id, scene_renderer, + r_refdef.scene->reg); + mat4ftranspose (f, Transform_GetWorldMatrixPtr (transform)); entdata->xform[0] = f[0]; entdata->xform[1] = f[1]; entdata->xform[2] = f[2]; + color = (vec4f_t) { QuatExpand (renderer->colormod) }; } else { entdata->xform[0] = (vec4f_t) { 1, 0, 0, 0 }; entdata->xform[1] = (vec4f_t) { 0, 1, 0, 0 }; entdata->xform[2] = (vec4f_t) { 0, 0, 1, 0 }; + color = (vec4f_t) { 1, 1, 1, 1 }; } - entdata->color = (vec4f_t) { QuatExpand (entity->renderer.colormod) }; + entdata->color = color; } - return entity->renderer.render_id; + return id; } void diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index d5fa35454..bb95f6cbe 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -51,7 +51,9 @@ #include "QF/sys.h" #include "QF/va.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_renderpass.h" @@ -82,7 +84,7 @@ static QFV_Subpass subpass_map[] = { static void emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, int numPC, qfv_push_constants_t *constants, - qfv_renderframe_t *rFrame, entity_t *ent) + qfv_renderframe_t *rFrame, entity_t ent) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -103,14 +105,18 @@ emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, } void -Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) +Vulkan_DrawSprite (entity_t ent, qfv_renderframe_t *rFrame) { + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + r_refdef.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + r_refdef.scene->reg); vulkan_ctx_t *ctx = rFrame->vulkan_ctx; spritectx_t *sctx = ctx->sprite_context; spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; - model_t *model = ent->renderer.model; + model_t *model = renderer->model; msprite_t *sprite = model->cache.data; - animation_t *animation = &ent->animation; mat4f_t mat = {}; uint32_t frame; @@ -122,9 +128,9 @@ Vulkan_DrawSprite (entity_t *ent, qfv_renderframe_t *rFrame) frame = (ptrdiff_t) R_GetSpriteFrame (sprite, animation); - mat[3] = Transform_GetWorldPosition (ent->transform); + mat[3] = Transform_GetWorldPosition (transform); vec4f_t cameravec = r_refdef.frame.position - mat[3]; - R_BillboardFrame (ent, sprite->type, cameravec, + R_BillboardFrame (transform, sprite->type, cameravec, &mat[2], &mat[1], &mat[0]); mat[0] = -mat[0]; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a62e84f58..a893c64ce 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -42,7 +42,9 @@ #include "QF/heapsort.h" #include "QF/plist.h" #include "QF/va.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" +#include "QF/scene/scene.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" @@ -582,16 +584,17 @@ Vulkan_DestroyFrames (vulkan_ctx_t *ctx) } void -Vulkan_BeginEntityLabel (vulkan_ctx_t *ctx, VkCommandBuffer cmd, - entity_t *ent) +Vulkan_BeginEntityLabel (vulkan_ctx_t *ctx, VkCommandBuffer cmd, entity_t ent) { qfv_device_t *device = ctx->device; - int entaddr = (intptr_t) ent & 0xfffff; - vec4f_t pos = Transform_GetWorldPosition (ent->transform); + uint32_t entgen = Ent_Generation (ent.id); + uint32_t entind = Ent_Index (ent.id); + transform_t transform = Entity_Transform (ent); + vec4f_t pos = Transform_GetWorldPosition (transform); vec4f_t dir = normalf (pos - (vec4f_t) { 0, 0, 0, 1 }); vec4f_t color = 0.5 * dir + (vec4f_t) {0.5, 0.5, 0.5, 1 }; QFV_CmdBeginLabel (device, cmd, - va (ctx->va_ctx, "ent %05x [%g, %g, %g]", entaddr, - VectorExpand (pos)), color); + va (ctx->va_ctx, "ent %03x.%05x [%g, %g, %g]", + entgen, entind, VectorExpand (pos)), color); } diff --git a/nq/include/client.h b/nq/include/client.h index 44391c545..2a654da98 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -35,6 +35,9 @@ #include "QF/quakefs.h" #include "QF/render.h" +#include "QF/scene/component.h" +#include "QF/scene/entity.h" + #include "client/chase.h" #include "client/entities.h" #include "client/input.h" @@ -218,7 +221,7 @@ extern int noskins; extern client_state_t cl; -extern struct entity_s *cl_entities[MAX_EDICTS]; +extern struct entity_s cl_entities[MAX_EDICTS]; extern double cl_msgtime[MAX_EDICTS]; extern struct set_s cl_forcelink; @@ -278,7 +281,7 @@ void CL_NewTranslation (int slot, struct skin_s *skin); void CL_SignonReply (void); void CL_RelinkEntities (void); void CL_ClearEnts (void); -struct entity_s *CL_GetEntity (int num); +struct entity_s CL_GetEntity (int num); extern double realtime; diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 6ed56e917..22484832d 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -59,7 +59,7 @@ #include "nq/include/host.h" #include "nq/include/server.h" -entity_t *cl_entities[MAX_EDICTS]; +entity_t cl_entities[MAX_EDICTS]; double cl_msgtime[MAX_EDICTS]; static byte forcelink_bytes[SET_SIZE(MAX_EDICTS)]; #define alloc_forcelink(s) (set_bits_t *)forcelink_bytes @@ -72,10 +72,14 @@ CL_ClearEnts (void) size_t i; for (i = 0; i < MAX_EDICTS; i++) { - if (cl_entities[i]) { - mod_funcs->Skin_Free (cl_entities[i]->renderer.skin); + if (Entity_Valid (cl_entities[i])) { + entity_t ent = cl_entities[i]; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); + if (renderer && renderer->skin) { + mod_funcs->Skin_Free (renderer->skin); + } Scene_DestroyEntity (cl_world.scene, cl_entities[i]); - cl_entities[i] = 0; + cl_entities[i] = nullentity; } } @@ -86,10 +90,10 @@ CL_ClearEnts (void) set_empty (&cl_forcelink); } -entity_t * +entity_t CL_GetEntity (int num) { - if (!cl_entities[num]) { + if (!Entity_Valid (cl_entities[num])) { cl_entities[num] = Scene_CreateEntity (cl_world.scene); CL_Init_Entity (cl_entities[num]); } @@ -136,9 +140,9 @@ CL_LerpPoint (void) static void set_entity_model (int ent_ind, int modelindex) { - entity_t *ent = cl_entities[ent_ind]; - renderer_t *renderer = &ent->renderer; - animation_t *animation = &ent->animation; + entity_t ent = cl_entities[ent_ind]; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); renderer->model = cl_world.models.a[modelindex]; // automatic animation (torches, etc) can be either all together // or randomized @@ -161,10 +165,8 @@ set_entity_model (int ent_ind, int modelindex) void CL_RelinkEntities (void) { - entity_t *ent; + entity_t ent; entity_state_t *new, *old; - renderer_t *renderer; - animation_t *animation; float bobjrotate, frac, f; int i, j; int entvalid; @@ -199,8 +201,11 @@ CL_RelinkEntities (void) new = &nq_entstates.frame[0 + cl.frameIndex][i]; old = &nq_entstates.frame[1 - cl.frameIndex][i]; ent = CL_GetEntity (i); - renderer = &ent->renderer; - animation = &ent->animation; + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, cl_world.scene->reg); + vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, cl_world.scene->reg); // if the object wasn't included in the last packet, remove it entvalid = cl_msgtime[i] == cl.mtime[0]; @@ -212,7 +217,7 @@ CL_RelinkEntities (void) if (!entvalid) { renderer->model = NULL; animation->pose1 = animation->pose2 = -1; - if (ent->visibility.efrag) { + if (visibility->efrag) { R_RemoveEfrags (ent); // just became empty } continue; @@ -261,16 +266,16 @@ CL_RelinkEntities (void) CL_TransformEntity (ent, new->scale / 16.0, new->angles, new->origin); if (i != cl.viewentity || chase_active) { - if (ent->visibility.efrag) { + if (visibility->efrag) { R_RemoveEfrags (ent); } R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } - ent->old_origin = new->origin; + *old_origin = new->origin; } else { vec4f_t delta = new->origin - old->origin; f = frac; - ent->old_origin = Transform_GetWorldPosition (ent->transform); + *old_origin = Transform_GetWorldPosition (transform); // If the delta is large, assume a teleport and don't lerp if (fabs (delta[0]) > 100 || fabs (delta[1]) > 100 || fabs (delta[2]) > 100) { @@ -295,10 +300,9 @@ CL_RelinkEntities (void) CL_TransformEntity (ent, new->scale / 16.0, angles, origin); } if (i != cl.viewentity || chase_active) { - if (ent->visibility.efrag) { - vec4f_t org - = Transform_GetWorldPosition (ent->transform); - if (!VectorCompare (org, ent->old_origin)) {//FIXME + vec4f_t org = Transform_GetWorldPosition (transform); + if (visibility->efrag) { + if (!VectorCompare (org, *old_origin)) {//FIXME R_RemoveEfrags (ent); R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } @@ -316,7 +320,7 @@ CL_RelinkEntities (void) CL_TransformEntity (ent, new->scale / 16.0, angles, new->origin); } CL_EntityEffects (i, ent, new, cl.time); - vec4f_t org = Transform_GetWorldPosition (ent->transform); + vec4f_t org = Transform_GetWorldPosition (transform); int effects = new->effects; if (cl.maxclients == 1 && effects) { // Enable blue and red lights for quad and invulnerability, @@ -340,7 +344,10 @@ CL_RelinkEntities (void) SET_REMOVE (&cl_forcelink, i); } - cl.viewstate.player_entity = CL_GetEntity (cl.viewentity); - cl.viewstate.player_origin - = Transform_GetWorldPosition (cl.viewstate.player_entity->transform); + { + entity_t player_entity = CL_GetEntity (cl.viewentity); + transform_t transform = Entity_Transform (player_entity); + cl.viewstate.player_entity = player_entity; + cl.viewstate.player_origin = Transform_GetWorldPosition (transform); + } } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 225876f9c..6bdb40530 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -236,8 +236,9 @@ CL_ClearMemory (void) cls.signon = 0; SZ_Clear (&cls.message); - if (cl.viewstate.weapon_entity) { + if (Entity_Valid (cl.viewstate.weapon_entity)) { Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity); + cl.viewstate.weapon_entity = nullentity; } if (cl.players) { int i; @@ -479,16 +480,19 @@ CL_PrintEntities_f (void) int i; for (i = 0; i < cl.num_entities; i++) { - entity_t *ent = cl_entities[i]; + entity_t ent = cl_entities[i]; + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); Sys_Printf ("%3i:", i); - if (!ent || !ent->renderer.model) { + if (!Entity_Valid (ent) || !renderer->model) { Sys_Printf ("EMPTY\n"); continue; } - vec4f_t org = Transform_GetWorldPosition (ent->transform); - vec4f_t rot = Transform_GetWorldRotation (ent->transform); + vec4f_t org = Transform_GetWorldPosition (transform); + vec4f_t rot = Transform_GetWorldRotation (transform); Sys_Printf ("%s:%2i "VEC4F_FMT" "VEC4F_FMT"\n", - ent->renderer.model->path, ent->animation.frame, + renderer->model->path, animation->frame, VEC4_EXP (org), VEC4_EXP (rot)); } } @@ -674,7 +678,7 @@ CL_Frame (void) S_Update (cl.viewstate.camera_transform, asl); R_DecayLights (host_frametime); } else - S_Update (0, 0); + S_Update (nulltransform, 0); CDAudio_Update (); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 2a2649e2f..300bcfa23 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -673,12 +673,14 @@ CL_ParseClientdata (void) cl.stats[STAT_CELLS] |= MSG_ReadByte (net_message) << 8; if (bits & SU_WEAPONFRAME2) cl.stats[STAT_WEAPONFRAME] |= MSG_ReadByte (net_message) << 8; + + renderer_t *renderer = Ent_GetComponent (cl.viewstate.weapon_entity.id, scene_renderer, cl_world.scene->reg); if (bits & SU_WEAPONALPHA) { byte alpha = MSG_ReadByte (net_message); float a = ENTALPHA_DECODE (alpha); - cl.viewstate.weapon_entity->renderer.colormod[3] = a; + renderer->colormod[3] = a; } else { - cl.viewstate.weapon_entity->renderer.colormod[3] = 1; + renderer->colormod[3] = 1; } } @@ -904,7 +906,8 @@ CL_ParseServerMessage (void) Host_Error ("CL_ParseServerMessage: svc_updatecolors > " "MAX_SCOREBOARD"); } else { - entity_t *ent = CL_GetEntity (i + 1); + entity_t ent = CL_GetEntity (i + 1); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); byte col = MSG_ReadByte (net_message); byte top = col >> 4; byte bot = col & 0xf; @@ -913,9 +916,8 @@ CL_ParseServerMessage (void) mod_funcs->Skin_SetTranslation (i + 1, top, bot); cl.players[i].topcolor = top; cl.players[i].bottomcolor = bot; - ent->renderer.skin - = mod_funcs->Skin_SetColormap (ent->renderer.skin, - i + 1); + renderer->skin + = mod_funcs->Skin_SetColormap (renderer->skin, i + 1); } break; diff --git a/qw/include/cl_ents.h b/qw/include/cl_ents.h index b6d5bc283..23398273d 100644 --- a/qw/include/cl_ents.h +++ b/qw/include/cl_ents.h @@ -41,7 +41,7 @@ void CL_ParsePacketEntities (qboolean delta); void CL_SetSolidEntities (void); void CL_ParsePlayerinfo (void); void CL_Ents_Init (void); -struct entity_s *CL_GetEntity (int num); +struct entity_s CL_GetEntity (int num); extern int cl_deadbodyfilter; extern int cl_gibfilter; diff --git a/qw/include/client.h b/qw/include/client.h index bac651e15..d0f694c9b 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -282,8 +282,8 @@ extern int hud_scoreboard_uid; extern client_state_t cl; -extern entity_t *cl_entities[512]; -extern byte cl_entity_valid[2][512]; +extern entity_t cl_entities[512]; +extern byte cl_entity_valid[2][512]; extern qboolean nomaster; extern char *server_version; // version of server we connected to diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index d9ada8aa8..4bf5bf4cd 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -41,6 +41,8 @@ #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/component.h" +#include "QF/scene/entity.h" #include "QF/scene/scene.h" #include "compat.h" @@ -482,13 +484,15 @@ CL_ParsePlayerinfo (void) // QSG2 int bits; byte val; - entity_t *ent; + entity_t ent; ent = CL_GetEntity (num + 1); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + cl_world.scene->reg); bits = MSG_ReadByte (net_message); if (bits & PF_ALPHA) { val = MSG_ReadByte (net_message); - ent->renderer.colormod[3] = val / 255.0; + renderer->colormod[3] = val / 255.0; } if (bits & PF_SCALE) { val = MSG_ReadByte (net_message); @@ -511,7 +515,7 @@ CL_ParsePlayerinfo (void) g = (float) ((val >> 2) & 7) * (1.0 / 7.0); b = (float) (val & 3) * (1.0 / 3.0); } - VectorSet (r, g, b, ent->renderer.colormod); + VectorSet (r, g, b, renderer->colormod); } if (bits & PF_FRAME2) { state->pls.es.frame |= MSG_ReadByte (net_message) << 8; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 333394dc2..58af6e757 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -41,6 +41,7 @@ #include "QF/skin.h" #include "QF/sys.h" +#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" @@ -63,8 +64,8 @@ #include "qw/include/cl_pred.h" #include "qw/include/host.h" -entity_t *cl_flag_ents[MAX_CLIENTS]; -entity_t *cl_entities[512]; // FIXME: magic number +entity_t cl_flag_ents[MAX_CLIENTS]; +entity_t cl_entities[512]; // FIXME: magic number byte cl_entity_valid[2][512]; void @@ -73,16 +74,16 @@ CL_ClearEnts (void) size_t i; for (i = 0; i < MAX_CLIENTS; i++) { - if (cl_flag_ents[i]) { + if (Entity_Valid (cl_flag_ents[i])) { Scene_DestroyEntity (cl_world.scene, cl_flag_ents[i]); - cl_flag_ents[i] = 0; + cl_flag_ents[i] = nullentity; } } for (i = 0; i < 512; i++) { - if (cl_entities[i]) { + if (Entity_Valid (cl_entities[i])) { Scene_DestroyEntity (cl_world.scene, cl_entities[i]); - cl_entities[i] = 0; + cl_entities[i] = nullentity; } } i = qw_entstates.num_frames * qw_entstates.num_entities; @@ -90,20 +91,20 @@ CL_ClearEnts (void) memset (cl_entity_valid, 0, sizeof (cl_entity_valid)); } -entity_t * +entity_t CL_GetEntity (int num) { - if (!cl_entities[num]) { + if (!Entity_Valid (cl_entities[num])) { cl_entities[num] = Scene_CreateEntity (cl_world.scene); CL_Init_Entity (cl_entities[num]); } return cl_entities[num]; } -static entity_t * +static entity_t CL_GetFlagEnt (int key) { - if (!cl_flag_ents[key]) { + if (!Entity_Valid (cl_flag_ents[key])) { cl_flag_ents[key] = Scene_CreateEntity (cl_world.scene); CL_Init_Entity (cl_flag_ents[key]); } @@ -133,10 +134,12 @@ is_gib (entity_state_t *s1) } static void -set_entity_model (entity_t *ent, int modelindex) +set_entity_model (entity_t ent, int modelindex) { - renderer_t *renderer = &ent->renderer; - animation_t *animation = &ent->animation; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + cl_world.scene->reg); renderer->model = cl_world.models.a[modelindex]; // automatic animation (torches, etc) can be either all together // or randomized @@ -155,25 +158,30 @@ CL_LinkPacketEntities (void) { int i, j, forcelink; float frac, f; - entity_t *ent; + entity_t ent; entity_state_t *new, *old; - renderer_t *renderer; - animation_t *animation; frac = 1; for (i = MAX_CLIENTS + 1; i < 512; i++) { new = &qw_entstates.frame[cl.link_sequence & UPDATE_MASK][i]; old = &qw_entstates.frame[cl.prev_sequence & UPDATE_MASK][i]; ent = CL_GetEntity (i); - renderer = &ent->renderer; - animation = &ent->animation; + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + cl_world.scene->reg); + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + cl_world.scene->reg); + vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, + cl_world.scene->reg); forcelink = cl_entity_valid[0][i] != cl_entity_valid[1][i]; cl_entity_valid[1][i] = cl_entity_valid[0][i]; // if the object wasn't included in the last packet, remove it if (!cl_entity_valid[0][i]) { renderer->model = NULL; animation->pose1 = animation->pose2 = -1; - if (ent->visibility.efrag) { + if (visibility->efrag) { R_RemoveEfrags (ent); // just became empty } continue; @@ -187,7 +195,7 @@ CL_LinkPacketEntities (void) if (!new->modelindex || (cl_deadbodyfilter && is_dead_body (new)) || (cl_gibfilter && is_gib (new))) { - if (ent->visibility.efrag) { + if (visibility->efrag) { R_RemoveEfrags (ent); } continue; @@ -234,13 +242,13 @@ CL_LinkPacketEntities (void) } } - ent->old_origin = Transform_GetWorldPosition (ent->transform); + *old_origin = Transform_GetWorldPosition (transform); if (forcelink) { animation->pose1 = animation->pose2 = -1; CL_TransformEntity (ent, new->scale / 16, new->angles, new->origin); if (i != cl.viewentity || chase_active) { - if (ent->visibility.efrag) { + if (visibility->efrag) { R_RemoveEfrags (ent); } R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); @@ -270,10 +278,9 @@ CL_LinkPacketEntities (void) CL_TransformEntity (ent, new->scale / 16.0, angles, origin); } if (i != cl.viewentity || chase_active) { - if (ent->visibility.efrag) { - vec4f_t org - = Transform_GetWorldPosition (ent->transform); - if (!VectorCompare (org, ent->old_origin)) {//FIXME + vec4f_t org = Transform_GetWorldPosition (transform); + if (visibility->efrag) { + if (!VectorCompare (org, *old_origin)) {//FIXME R_RemoveEfrags (ent); R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } @@ -282,7 +289,7 @@ CL_LinkPacketEntities (void) } } } - if (!ent->visibility.efrag) { + if (!visibility->efrag) { R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } @@ -296,7 +303,7 @@ CL_LinkPacketEntities (void) } //CL_EntityEffects (i, ent, new); //CL_NewDlight (i, ent->origin, new->effects, 0, 0, cl.time); - vec4f_t org = Transform_GetWorldPosition (ent->transform); + vec4f_t org = Transform_GetWorldPosition (transform); if (VectorDistance_fast (old->origin, org) > (256 * 256)) old->origin = org; if (renderer->model->flags & ~EF_ROTATE) { @@ -306,26 +313,28 @@ CL_LinkPacketEntities (void) } static void -CL_UpdateFlagModels (entity_t *ent, int key) +CL_UpdateFlagModels (entity_t ent, int key) { static float flag_offsets[] = { 16.0, 22.0, 26.0, 25.0, 24.0, 18.0, // 29-34 axpain 16.0, 24.0, 24.0, 22.0, 18.0, 16.0, // 35-40 pain }; float f; - entity_t *fent; + entity_t fent = CL_GetFlagEnt (key); + byte *active = Ent_GetComponent (fent.id, scene_active, + cl_world.scene->reg); - fent = CL_GetFlagEnt (key); - - if (!fent->active) { + if (!*active) { return; } + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + cl_world.scene->reg); f = 14.0; - if (ent->animation.frame >= 29 && ent->animation.frame <= 40) { - f = flag_offsets[ent->animation.frame - 29]; - } else if (ent->animation.frame >= 103 && ent->animation.frame <= 118) { - if (ent->animation.frame <= 106) { // 103-104 nailattack + if (animation->frame >= 29 && animation->frame <= 40) { + f = flag_offsets[animation->frame - 29]; + } else if (animation->frame >= 103 && animation->frame <= 118) { + if (animation->frame <= 106) { // 103-104 nailattack f = 20.0; // 105-106 light } else { // 107-112 rocketattack f = 21.0; // 112-118 shotattack @@ -337,30 +346,37 @@ CL_UpdateFlagModels (entity_t *ent, int key) vec4f_t rotation = { -0.382683432, 0, 0, 0.923879533 }; vec4f_t position = { -f, -22, -16, 1}; - Transform_SetLocalTransform (fent->transform, scale, rotation, position); + transform_t transform = Entity_Transform (fent); + Transform_SetLocalTransform (transform, scale, rotation, position); } -static entity_t * -CL_AddFlagModels (entity_t *ent, int team, int key) +static entity_t +CL_AddFlagModels (entity_t ent, int team, int key) { - entity_t *fent; + entity_t fent; fent = CL_GetFlagEnt (key); + byte *active = Ent_GetComponent (fent.id, scene_active, + cl_world.scene->reg); if (cl_flagindex == -1) { - fent->active = 0; - return 0; + *active = 0; + return nullentity; } - fent->active = 1; + *active = 1; - if (!Transform_GetParent (fent->transform)) { - Transform_SetParent (cl_world.scene, fent->transform, ent->transform); + transform_t ftransform = Entity_Transform (fent); + transform_t transform = Entity_Transform (ent); + if (!Transform_Valid (Transform_GetParent (ftransform))) { + Transform_SetParent (cl_world.scene, ftransform, transform); } CL_UpdateFlagModels (ent, key); - fent->renderer.model = cl_world.models.a[cl_flagindex]; - fent->renderer.skinnum = team; + renderer_t *renderer = Ent_GetComponent (fent.id, scene_renderer, + cl_world.scene->reg); + renderer->model = cl_world.models.a[cl_flagindex]; + renderer->skinnum = team; return fent; } @@ -368,11 +384,14 @@ CL_AddFlagModels (entity_t *ent, int team, int key) static void CL_RemoveFlagModels (int key) { - entity_t *fent; + entity_t fent; fent = CL_GetFlagEnt (key); - fent->active = 0; - Transform_SetParent (cl_world.scene, fent->transform, 0); + byte *active = Ent_GetComponent (fent.id, scene_active, + cl_world.scene->reg); + transform_t transform = Entity_Transform (fent); + *active = 0; + Transform_SetParent (cl_world.scene, transform, nulltransform); } /* @@ -386,7 +405,7 @@ CL_LinkPlayers (void) { double playertime; int msec, oldphysent, j; - entity_t *ent; + entity_t ent; frame_t *frame; player_info_t *player; player_state_t exact; @@ -404,10 +423,21 @@ CL_LinkPlayers (void) for (j = 0, player = cl.players, state = frame->playerstate; j < MAX_CLIENTS; j++, player++, state++) { ent = CL_GetEntity (j + 1); - if (ent->visibility.efrag) + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + cl_world.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + cl_world.scene->reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + cl_world.scene->reg); + if (visibility->efrag) R_RemoveEfrags (ent); - if (player->flag_ent && player->flag_ent->visibility.efrag) { - R_RemoveEfrags (player->flag_ent); + if (Entity_Valid (player->flag_ent)) { + visibility_t *fvis = Ent_GetComponent (player->flag_ent.id, + scene_visibility, + cl_world.scene->reg); + if (fvis->efrag) { + R_RemoveEfrags (player->flag_ent); + } } if (state->messagenum != cl.parsecount) continue; // not present this frame @@ -475,39 +505,39 @@ CL_LinkPlayers (void) } ang[ROLL] = V_CalcRoll (ang, state->pls.es.velocity) * 4.0; - if (ent->renderer.model + if (renderer->model != cl_world.models.a[state->pls.es.modelindex]) { - ent->renderer.model = cl_world.models.a[state->pls.es.modelindex]; - ent->animation.nolerp = 1; + renderer->model = cl_world.models.a[state->pls.es.modelindex]; + animation->nolerp = 1; } - ent->animation.frame = state->pls.es.frame; - ent->renderer.skinnum = state->pls.es.skinnum; + animation->frame = state->pls.es.frame; + renderer->skinnum = state->pls.es.skinnum; //FIXME scale CL_TransformEntity (ent, 1, ang, exact.pls.es.origin); - ent->renderer.min_light = 0; - ent->renderer.fullbright = 0; + renderer->min_light = 0; + renderer->fullbright = 0; if (state->pls.es.modelindex == cl_playerindex) { //XXX // use custom skin - ent->renderer.skin = player->skin; + renderer->skin = player->skin; - ent->renderer.min_light = min (cl.fbskins, cl_fb_players); + renderer->min_light = min (cl.fbskins, cl_fb_players); - if (ent->renderer.min_light >= 1.0) { - ent->renderer.fullbright = 1; + if (renderer->min_light >= 1.0) { + renderer->fullbright = 1; } } else { // FIXME no team colors on nonstandard player models - ent->renderer.skin = 0; + renderer->skin = 0; } int flag_state = state->pls.es.effects & (EF_FLAG1 | EF_FLAG2); - if (player->flag_ent && !flag_state) { + if (Entity_Valid (player->flag_ent) && !flag_state) { CL_RemoveFlagModels (j); - player->flag_ent = 0; - } else if (!player->flag_ent && flag_state) { + player->flag_ent = (entity_t) nullentity; + } else if (!Entity_Valid (player->flag_ent) && flag_state) { if (flag_state & EF_FLAG1) player->flag_ent = CL_AddFlagModels (ent, 0, j); else if (flag_state & EF_FLAG2) @@ -516,9 +546,10 @@ CL_LinkPlayers (void) // stuff entity in map R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); - if (player->flag_ent) { + if (Entity_Valid (player->flag_ent)) { CL_UpdateFlagModels (ent, j); - R_AddEfrags (&cl_world.scene->worldmodel->brush, player->flag_ent); + entity_t fent = player->flag_ent; + R_AddEfrags (&cl_world.scene->worldmodel->brush, fent); } } } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index cc3bf4c82..a5f485b0f 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -91,6 +91,7 @@ #include "QF/gib.h" #include "QF/plugin/console.h" +#include "QF/scene/component.h" #include "QF/scene/transform.h" #include "QF/scene/scene.h" @@ -652,7 +653,7 @@ CL_ClearState (void) S_StopAllSounds (); - if (cl.viewstate.weapon_entity) { + if (Entity_Valid (cl.viewstate.weapon_entity)) { Scene_DestroyEntity (cl_world.scene, cl.viewstate.weapon_entity); } // wipe the entire cl structure @@ -2003,7 +2004,7 @@ Host_Frame (float time) S_Update (cl.viewstate.camera_transform, asl); R_DecayLights (host_frametime); } else - S_Update (0, 0); + S_Update (nulltransform, 0); CDAudio_Update (); diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 5d1360cc3..b2152266d 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -46,6 +46,7 @@ #include "QF/plugin/console.h" +#include "QF/scene/entity.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "QF/ui/view.h" diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 1f408344c..110a79e58 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -114,7 +114,7 @@ bi_refresh (progs_t *pr, void *_res) IN_ProcessEvents (); //GIB_Thread_Execute (); Cbuf_Execute_Stack (qwaq_cbuf); - SCR_UpdateScreen (0, con_realtime, bi_2dfuncs); + SCR_UpdateScreen (nulltransform, con_realtime, bi_2dfuncs); R_FLOAT (pr) = con_frametime; } From cf4a3399c431bf3d65139999c52fb654286ff46a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Oct 2022 22:43:45 +0900 Subject: [PATCH 3088/3664] [nq] Reduce entity churn While chasing down the grenade explosion bug, I noticed that entities were being created and destroyed (or really, not destroyed) just to check of the entity was valid. In the old system, this wasn't *horrible*, but with the ECS, it does mean entities and components are getting churned up, which wouldn't be good for the entity generation counter (only 12 bits). --- nq/source/cl_ents.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 22484832d..130d1edd7 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -86,10 +86,16 @@ CL_ClearEnts (void) // clear other arrays i = nq_entstates.num_frames * nq_entstates.num_entities; memset (nq_entstates.frame[0], 0, i * sizeof (entity_state_t)); - memset (cl_msgtime, 0, sizeof (cl_msgtime)); + memset (cl_msgtime, -1, sizeof (cl_msgtime)); set_empty (&cl_forcelink); } +static entity_t +CL_GetInvalidEntity (int num) +{ + return cl_entities[num]; +} + entity_t CL_GetEntity (int num) { @@ -200,29 +206,34 @@ CL_RelinkEntities (void) for (i = 1; i < cl.num_entities; i++) { new = &nq_entstates.frame[0 + cl.frameIndex][i]; old = &nq_entstates.frame[1 - cl.frameIndex][i]; - ent = CL_GetEntity (i); - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, cl_world.scene->reg); - vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, cl_world.scene->reg); // if the object wasn't included in the last packet, remove it entvalid = cl_msgtime[i] == cl.mtime[0]; if (entvalid && !new->modelindex) { + ent = CL_GetEntity (i); CL_TransformEntity (ent, new->scale / 16.0, new->angles, new->origin); entvalid = 0; } if (!entvalid) { - renderer->model = NULL; - animation->pose1 = animation->pose2 = -1; - if (visibility->efrag) { - R_RemoveEfrags (ent); // just became empty + ent = CL_GetInvalidEntity (i); + if (Entity_Valid (ent)) { + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, ent.reg); + if (visibility->efrag) { + R_RemoveEfrags (ent); // just became empty + } + Scene_DestroyEntity (cl_world.scene, ent); } continue; } + ent = CL_GetEntity (i); + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, ent.reg); + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, ent.reg); + vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, ent.reg); + if (SET_TEST_MEMBER (&cl_forcelink, i)) { *old = *new; } From 9f9e21f1dc158d368500b7d0d58cf97d690ed6ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Oct 2022 23:02:16 +0900 Subject: [PATCH 3089/3664] [nq] Relink entities when there model changes This is the fix for the grenade explosion bug. It was rather difficult to track down because *two* explosions are rendered for the one grenade (but that's actually another bug due to the nq/qw merge). It's also correct as changing the model can change the BSP leafs the entity touches. --- nq/source/cl_ents.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 130d1edd7..a5db5d3e6 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -242,6 +242,9 @@ CL_RelinkEntities (void) || new->modelindex != old->modelindex) { old->modelindex = new->modelindex; set_entity_model (i, new->modelindex); + if (visibility->efrag) { + R_RemoveEfrags (ent); + } } animation->frame = new->frame; if (SET_TEST_MEMBER (&cl_forcelink, i) From f37c31a2dce7b0a376c9a153898f36a19000445d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 23 Oct 2022 23:38:21 +0900 Subject: [PATCH 3090/3664] [vulkan] Set entity render id correctly It was being set to -1 unconditionally due to forgetting to use id. However, I decided I didn't like reusing the id var and did some renaming while I was at it. --- libs/video/renderer/vulkan/vulkan_scene.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_scene.c b/libs/video/renderer/vulkan/vulkan_scene.c index 4713cf8e6..0e31fd49a 100644 --- a/libs/video/renderer/vulkan/vulkan_scene.c +++ b/libs/video/renderer/vulkan/vulkan_scene.c @@ -75,21 +75,20 @@ Vulkan_Scene_AddEntity (vulkan_ctx_t *ctx, entity_t entity) scnframe_t *sframe = &sctx->frames.a[ctx->curFrame]; entdata_t *entdata = 0; + int render_id = -1; //lock - int id = Ent_Index (entity.id + 1);//nullent -> 0 - if (!set_is_member (sframe->pooled_entities, id)) { + int ent_id = Ent_Index (entity.id + 1);//nullent -> 0 + if (!set_is_member (sframe->pooled_entities, ent_id)) { if (sframe->entity_pool.size < sframe->entity_pool.maxSize) { - set_add (sframe->pooled_entities, id); - id = sframe->entity_pool.size++; - entdata = sframe->entity_pool.a + id; - } else { - id = -1; + set_add (sframe->pooled_entities, ent_id); + render_id = sframe->entity_pool.size++; + entdata = sframe->entity_pool.a + render_id; } } if (Entity_Valid (entity)) { renderer_t *renderer = Ent_GetComponent (entity.id, scene_renderer, - r_refdef.scene->reg); - renderer->render_id = -1; + entity.reg); + renderer->render_id = render_id; } //unlock if (entdata) { @@ -98,7 +97,7 @@ Vulkan_Scene_AddEntity (vulkan_ctx_t *ctx, entity_t entity) if (Entity_Valid (entity)) { //FIXME give world entity an entity :P transform_t transform = Entity_Transform (entity); renderer_t *renderer = Ent_GetComponent (entity.id, scene_renderer, - r_refdef.scene->reg); + entity.reg); mat4ftranspose (f, Transform_GetWorldMatrixPtr (transform)); entdata->xform[0] = f[0]; entdata->xform[1] = f[1]; @@ -112,7 +111,7 @@ Vulkan_Scene_AddEntity (vulkan_ctx_t *ctx, entity_t entity) } entdata->color = color; } - return id; + return render_id; } void From 9e83ded0acdfc9e08dd019215f4d67ae995bff27 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Oct 2022 09:50:14 +0900 Subject: [PATCH 3091/3664] [scene] Return existing component instead of null While checking on how Ent_AddComponent behaved (I don't remember what I was looking for, though), I realized that instead of treating adding the same component to an entity as an error, Ent_AddComponent should just return the existing component. --- libs/scene/component.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libs/scene/component.c b/libs/scene/component.c index 31048f667..f5b9ec5f1 100644 --- a/libs/scene/component.c +++ b/libs/scene/component.c @@ -68,15 +68,14 @@ ECS_RegisterComponents (ecs_registry_t *registry, } } -VISIBLE void* +VISIBLE void * Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) { uint32_t id = Ent_Index (ent); ecs_pool_t *pool = ®istry->comp_pools[comp]; - if (pool->sparse[id] < pool->count) { - //Sys_Error ("Ent_AddComponent: component %s already on entity %x\n", - // registry->components[i].name, ent); - return 0; + if (pool->sparse[id] < pool->count + && pool->dense[pool->sparse[id]] == ent) { + return Ent_GetComponent (ent, comp, registry); } if (pool->count == pool->max_count) { pool->max_count += COMP_GROW; From 4759be449fe57f824dd82a8f0089556f363721da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Oct 2022 09:55:08 +0900 Subject: [PATCH 3092/3664] [scene] Ensure entity owns component before removing I realized I should check that the entity owns the component before treating it as existing when adding an existing component, then noticed that Ent_RemoveComponent didn't check before removing the component. I imagine that would have been a fun debug session :P --- libs/scene/component.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/scene/component.c b/libs/scene/component.c index f5b9ec5f1..3f1601989 100644 --- a/libs/scene/component.c +++ b/libs/scene/component.c @@ -97,7 +97,7 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) uint32_t id = Ent_Index (ent); ecs_pool_t *pool = ®istry->comp_pools[comp]; uint32_t ind = pool->sparse[id]; - if (ind < pool->count) { + if (ind < pool->count && pool->dense[ind] == ent) { uint32_t last = pool->count - 1; Component_DestroyElements (®istry->components[comp], pool->data, ind, 1); From 5b0810f4c2bf6b2f53732769254a05d781164212 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Oct 2022 11:34:24 +0900 Subject: [PATCH 3093/3664] [scene] Make Ent_AddComponent more raw It no longer initializes the new component. For that, use Ent_SetComponent which will copy in the provided data or call the component's create function if the data pointer is null (in which case, Ent_SetComponent acts as Ent_SetComponent used to). --- include/QF/scene/component.h | 39 ++++++++++++++++++++++++++---------- libs/scene/component.c | 30 +++++++++++++-------------- libs/scene/scene.c | 13 ++++++------ 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/include/QF/scene/component.h b/include/QF/scene/component.h index 0f17be66e..6baf76b37 100644 --- a/include/QF/scene/component.h +++ b/include/QF/scene/component.h @@ -76,13 +76,14 @@ typedef struct ecs_registry_s { COMPINLINE void Component_ResizeArray (const component_t *component, void **array, uint32_t count); -COMPINLINE void Component_MoveElements (const component_t *component, - void *array, uint32_t dstIndex, - uint32_t srcIndex, uint32_t count); -COMPINLINE void Component_CopyElements (const component_t *component, - void *dstArray, uint32_t dstIndex, - const void *srcArray, uint32_t srcIndex, - uint32_t count); +COMPINLINE void *Component_MoveElements (const component_t *component, + void *array, uint32_t dstIndex, + uint32_t srcIndex, uint32_t count); +COMPINLINE void *Component_CopyElements (const component_t *component, + void *dstArray, uint32_t dstIndex, + const void *srcArray, + uint32_t srcIndex, + uint32_t count); COMPINLINE void *Component_CreateElements (const component_t *component, void *array, uint32_t index, uint32_t count); @@ -98,6 +99,8 @@ COMPINLINE int Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg); COMPINLINE void *Ent_GetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg); +COMPINLINE void *Ent_SetComponent (uint32_t ent, uint32_t comp, + ecs_registry_t *registry, const void *data); #undef COMPINLINE #ifndef IMPLEMENT_COMPONENT_Funcs @@ -113,17 +116,17 @@ Component_ResizeArray (const component_t *component, *array = realloc (*array, count * component->size); } -COMPINLINE void +COMPINLINE void * Component_MoveElements (const component_t *component, void *array, uint32_t dstIndex, uint32_t srcIndex, uint32_t count) { __auto_type dst = (byte *) array + dstIndex * component->size; __auto_type src = (byte *) array + srcIndex * component->size; - memmove (dst, src, count * component->size); + return memmove (dst, src, count * component->size); } -COMPINLINE void +COMPINLINE void * Component_CopyElements (const component_t *component, void *dstArray, uint32_t dstIndex, const void *srcArray, uint32_t srcIndex, @@ -131,7 +134,7 @@ Component_CopyElements (const component_t *component, { __auto_type dst = (byte *) dstArray + dstIndex * component->size; __auto_type src = (byte *) srcArray + srcIndex * component->size; - memcpy (dst, src, count * component->size); + return memcpy (dst, src, count * component->size); } COMPINLINE void * @@ -215,6 +218,20 @@ void *Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry); void Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry); +COMPINLINE void * +Ent_SetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry, + const void *data) +{ + void *dst = Ent_AddComponent (ent, comp, registry); + if (data) { + return Component_CopyElements (®istry->components[comp], + dst, 0, data, 0, 1); + } else { + return Component_CreateElements (®istry->components[comp], + dst, 0, 1); + } +} + ///@} #endif//__QF_scene_component_h diff --git a/libs/scene/component.c b/libs/scene/component.c index 3f1601989..246872078 100644 --- a/libs/scene/component.c +++ b/libs/scene/component.c @@ -71,24 +71,22 @@ ECS_RegisterComponents (ecs_registry_t *registry, VISIBLE void * Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) { - uint32_t id = Ent_Index (ent); ecs_pool_t *pool = ®istry->comp_pools[comp]; - if (pool->sparse[id] < pool->count - && pool->dense[pool->sparse[id]] == ent) { - return Ent_GetComponent (ent, comp, registry); + uint32_t id = Ent_Index (ent); + uint32_t ind = pool->sparse[id]; + if (ind >= pool->count || pool->dense[ind] != ent) { + if (pool->count == pool->max_count) { + pool->max_count += COMP_GROW; + pool->dense = realloc (pool->dense, + pool->max_count * sizeof (uint32_t)); + Component_ResizeArray (®istry->components[comp], &pool->data, + pool->max_count); + } + uint32_t ind = pool->count++; + pool->sparse[id] = ind; + pool->dense[ind] = ent; } - if (pool->count == pool->max_count) { - pool->max_count += COMP_GROW; - pool->dense = realloc (pool->dense, - pool->max_count * sizeof (uint32_t)); - Component_ResizeArray (®istry->components[comp], &pool->data, - pool->max_count); - } - uint32_t ind = pool->count++; - pool->sparse[id] = ind; - pool->dense[ind] = ent; - return Component_CreateElements (®istry->components[comp], pool->data, - ind, 1); + return Ent_GetComponent (ent, comp, registry); } VISIBLE void diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 1b514b33a..1800b87c8 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -176,15 +176,16 @@ Scene_DeleteScene (scene_t *scene) entity_t Scene_CreateEntity (scene_t *scene) { + // Transform_New creates an entity and adds a scene_href component to the + // entity transform_t trans = Transform_New (scene, nulltransform); uint32_t id = trans.id; - Ent_AddComponent (id, scene_href, scene->reg); - Ent_AddComponent (id, scene_animation, scene->reg); - Ent_AddComponent (id, scene_visibility, scene->reg); - Ent_AddComponent (id, scene_renderer, scene->reg); - Ent_AddComponent (id, scene_active, scene->reg); - Ent_AddComponent (id, scene_old_origin, scene->reg); + Ent_SetComponent (id, scene_animation, scene->reg, 0); + Ent_SetComponent (id, scene_visibility, scene->reg, 0); + Ent_SetComponent (id, scene_renderer, scene->reg, 0); + Ent_SetComponent (id, scene_active, scene->reg, 0); + Ent_SetComponent (id, scene_old_origin, scene->reg, 0); renderer_t *renderer = Ent_GetComponent (id, scene_renderer, scene->reg); QuatSet (1, 1, 1, 1, renderer->colormod); From 2a9fcf4f5f7fcc447a70b2a113d0a046fccc6136 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Oct 2022 12:53:30 +0900 Subject: [PATCH 3094/3664] [renderer] Tidy up entity component access Since entity_t has a pointer to the registry owning the entity, there's no need to access a global to get at the registry. Also move component getting closer to where it's used. --- include/QF/render.h | 1 - libs/video/renderer/gl/gl_mod_alias.c | 26 +++++--------- libs/video/renderer/gl/gl_mod_iqm.c | 9 +++-- libs/video/renderer/gl/gl_mod_sprite.c | 20 +++++------ libs/video/renderer/gl/gl_rmain.c | 3 +- libs/video/renderer/gl/gl_rmisc.c | 1 - libs/video/renderer/gl/gl_rsurf.c | 7 ++-- libs/video/renderer/glsl/glsl_alias.c | 17 ++++----- libs/video/renderer/glsl/glsl_bsp.c | 9 ++--- libs/video/renderer/glsl/glsl_iqm.c | 11 +++--- libs/video/renderer/glsl/glsl_main.c | 4 +-- libs/video/renderer/glsl/glsl_sprite.c | 7 ++-- libs/video/renderer/sw/d_surf.c | 5 +-- libs/video/renderer/sw/sw_ralias.c | 30 +++++++--------- libs/video/renderer/sw/sw_rdraw.c | 6 ++-- libs/video/renderer/sw/sw_riqm.c | 12 +++---- libs/video/renderer/sw/sw_rmain.c | 41 ++++++++++------------ libs/video/renderer/sw/sw_rsprite.c | 16 ++++----- libs/video/renderer/vulkan/vulkan_alias.c | 9 +++-- libs/video/renderer/vulkan/vulkan_bsp.c | 15 ++++---- libs/video/renderer/vulkan/vulkan_iqm.c | 10 +++--- libs/video/renderer/vulkan/vulkan_main.c | 4 +-- libs/video/renderer/vulkan/vulkan_sprite.c | 9 +++-- 23 files changed, 111 insertions(+), 161 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index 555ace94f..94e1f0a29 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -166,7 +166,6 @@ typedef struct { int ambientlight; int drawflat; - struct scene_s *scene; struct model_s *worldmodel; } refdef_t; diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 66ddd49cd..79f5de3c6 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -274,15 +274,13 @@ GL_DrawAliasShadow (transform_t transform, const aliashdr_t *paliashdr, static inline vert_order_t * GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t e) { - animation_t *animation = Ent_GetComponent (e.id, scene_animation, - r_refdef.scene->reg); - float blend; + animation_t *animation = Ent_GetComponent (e.id, scene_animation, e.reg); + float blend = R_AliasGetLerpedFrames (animation, paliashdr); int count, i; trivertx16_t *verts; vert_order_t *vo; blended_vert_t *vo_v; - blend = R_AliasGetLerpedFrames (animation, paliashdr); verts = (trivertx16_t *) ((byte *) paliashdr + paliashdr->posedata); @@ -341,15 +339,13 @@ GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t e) static inline vert_order_t * GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t e) { - animation_t *animation = Ent_GetComponent (e.id, scene_animation, - r_refdef.scene->reg); - float blend; + animation_t *animation = Ent_GetComponent (e.id, scene_animation, e.reg); + float blend = R_AliasGetLerpedFrames (animation, paliashdr); int count, i; trivertx_t *verts; vert_order_t *vo; blended_vert_t *vo_v; - blend = R_AliasGetLerpedFrames (animation, paliashdr); verts = (trivertx_t *) ((byte *) paliashdr + paliashdr->posedata); @@ -417,17 +413,14 @@ gl_R_DrawAliasModel (entity_t e) unsigned lnum; aliashdr_t *paliashdr; dlight_t *l; - model_t *model; vec3_t dist, scale; vec4f_t origin; vert_order_t *vo; - transform_t transform = Entity_Transform (e); - renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, - r_refdef.scene->reg); - - model = renderer->model; + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, e.reg); + model_t *model = renderer->model; radius = model->radius; + transform_t transform = Entity_Transform (e); origin = Transform_GetWorldPosition (transform); VectorCopy (Transform_GetWorldScale (transform), scale); //FIXME assumes uniform scale @@ -570,9 +563,8 @@ gl_R_DrawAliasModel (entity_t e) } else { maliasskindesc_t *skindesc; animation_t *animation = Ent_GetComponent (e.id, scene_animation, - r_refdef.scene->reg); - skindesc = R_AliasGetSkindesc (animation, renderer->skinnum, - paliashdr); + e.reg); + skindesc = R_AliasGetSkindesc (animation, renderer->skinnum, paliashdr); texture = skindesc->texnum; if (gl_fb_models && !is_fullbright) { fb_texture = skindesc->fb_texnum; diff --git a/libs/video/renderer/gl/gl_mod_iqm.c b/libs/video/renderer/gl/gl_mod_iqm.c index e294e73e5..0052fa977 100644 --- a/libs/video/renderer/gl/gl_mod_iqm.c +++ b/libs/video/renderer/gl/gl_mod_iqm.c @@ -90,11 +90,7 @@ gl_draw_iqm_frame (iqm_t *iqm, gliqm_t *gl, iqmframe_t *frame, iqmmesh *mesh) void gl_R_DrawIQMModel (entity_t ent) { - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; iqm_t *iqm = (iqm_t *) model->aliashdr; gliqm_t *gl = (gliqm_t *) iqm->extra_data; @@ -102,11 +98,14 @@ gl_R_DrawIQMModel (entity_t ent) iqmframe_t *frame; int i; + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); blend = R_IQMGetLerpedFrames (animation, iqm); frame = R_IQMBlendPalette (iqm, animation->pose1, animation->pose2, blend, 0, gl->blend_palette, gl->palette_size); qfglPushMatrix (); + transform_t transform = Entity_Transform (ent); gl_R_RotateForEntity (Transform_GetWorldMatrixPtr (transform)); for (i = 0; i < iqm->num_meshes; i++) { diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index dff4e325d..62c955136 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -60,22 +60,20 @@ void (*gl_R_DrawSpriteModel) (struct entity_s ent); static void R_DrawSpriteModel_f (entity_t e) { - transform_t transform = Entity_Transform (e); - renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (e.id, scene_animation, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, e.reg); + msprite_t *sprite = renderer->model->cache.data; float modelalpha, color[4]; vec4f_t cameravec = {}; vec4f_t up = {}, right = {}, pn = {}; vec4f_t origin, point; - msprite_t *sprite = renderer->model->cache.data; mspriteframe_t *frame; + transform_t transform = Entity_Transform (e); origin = Transform_GetWorldPosition (transform); cameravec = r_refdef.frame.position - origin; // don't bother culling, it's just a single polygon without a surface cache + animation_t *animation = Ent_GetComponent (e.id, scene_animation, e.reg); frame = R_GetSpriteFrame (sprite, animation); if (!R_BillboardFrame (transform, sprite->type, cameravec, @@ -122,27 +120,25 @@ R_DrawSpriteModel_f (entity_t e) static void R_DrawSpriteModel_VA_f (entity_t e) { - transform_t transform = Entity_Transform (e); - renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (e.id, scene_animation, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, e.reg); + msprite_t *psprite = renderer->model->cache.data; unsigned char modelalpha, color[4]; vec4f_t up = {}, right = {}; vec4f_t origin, point; int i; // unsigned int vacount; - msprite_t *psprite = renderer->model->cache.data; mspriteframe_t *frame; varray_t2f_c4ub_v3f_t *VA; VA = gl_spriteVertexArray; // FIXME: Despair // don't bother culling, it's just a single polygon without a surface cache + animation_t *animation = Ent_GetComponent (e.id, scene_animation, e.reg); frame = R_GetSpriteFrame (psprite, animation); qfglBindTexture (GL_TEXTURE_2D, frame->gl_texturenum); // FIXME: DESPAIR + transform_t transform = Entity_Transform (e); if (psprite->type == SPR_ORIENTED) { // bullet marks on walls up = Transform_Up (transform); right = Transform_Right (transform); diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 4d5c51ed6..a1e1bff3a 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -162,8 +162,7 @@ static void R_DrawViewModel (void) { entity_t ent = vr_data.view_model; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); if (vr_data.inhibit_viewmodel || !r_drawviewmodel || !r_drawentities diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 506e6163e..c2baac427 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -165,7 +165,6 @@ gl_R_NewScene (scene_t *scene) for (int i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value - r_refdef.scene = scene; r_refdef.worldmodel = scene->worldmodel; brush = &scene->worldmodel->brush; diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index bc0878158..73af64ca9 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -501,19 +501,16 @@ gl_R_DrawBrushModel (entity_t e) { float dot, radius; transform_t transform = Entity_Transform (e); - renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (e.id, scene_animation, - r_refdef.scene->reg); msurface_t *surf; qboolean rotated; vec3_t mins, maxs; mat4f_t worldMatrix; + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, e.reg); model_t *model = renderer->model; mod_brush_t *brush = &model->brush; glbspctx_t bspctx = { brush, - animation, + Ent_GetComponent (e.id, scene_animation, e.reg), renderer->full_transform, renderer->colormod, }; diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 8040e9e2b..82b9ee216 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -157,16 +157,14 @@ calc_lighting (entity_t ent, float *ambient, float *shadelight, unsigned i; float add; vec3_t dist; - vec4f_t entorigin; int light; - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - entorigin = Transform_GetWorldPosition (transform); + transform_t transform = Entity_Transform (ent); + vec4f_t entorigin = Transform_GetWorldPosition (transform); VectorSet ( -1, 0, 0, lightvec); //FIXME light = R_LightPoint (&r_refdef.worldmodel->brush, entorigin); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); *ambient = max (light, max (renderer->model->min_light, renderer->min_light) * 128); *shadelight = *ambient; @@ -245,15 +243,12 @@ glsl_R_DrawAlias (entity_t ent) calc_lighting (ent, &ambient, &shadelight, lightvec); - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; if (!(hdr = model->aliashdr)) hdr = Cache_Get (&model->cache); + transform_t transform = Entity_Transform (ent); Transform_GetWorldMatrix (transform, worldMatrix); // we need only the rotation for normals. VectorCopy (worldMatrix[0], norm_mat + 0); @@ -271,6 +266,8 @@ glsl_R_DrawAlias (entity_t ent) mmulf (mvp_mat, worldMatrix, mvp_mat); mmulf (mvp_mat, alias_vp, mvp_mat); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); colormap = glsl_colormap; if (renderer->skin && renderer->skin->auxtex) colormap = renderer->skin->auxtex; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 6f10491b6..1d31f81f2 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -654,11 +654,7 @@ R_DrawBrushModel (entity_t e) { float dot, radius; unsigned k; - transform_t transform = Entity_Transform (e); - renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (e.id, scene_animation, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, e.reg); model_t *model = renderer->model; mod_brush_t *brush = &model->brush; plane_t *plane; @@ -668,12 +664,13 @@ R_DrawBrushModel (entity_t e) vec4f_t org; glslbspctx_t bctx = { brush, - animation, + Ent_GetComponent (e.id, scene_animation, e.reg), renderer->full_transform, renderer->colormod, }; mat4f_t mat; + transform_t transform = Entity_Transform (e); Transform_GetWorldMatrix (transform, mat); memcpy (renderer->full_transform, mat, sizeof (mat));//FIXME if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index 95c91e969..e962c51a7 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -206,13 +206,9 @@ set_arrays (iqm_t *iqm) void glsl_R_DrawIQM (entity_t ent) { - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); - static quat_t color = { 1, 1, 1, 1}; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; + static quat_t color = { 1, 1, 1, 1}; iqm_t *iqm = (iqm_t *) model->aliashdr; glsliqm_t *glsl = (glsliqm_t *) iqm->extra_data; dlight_t *lights[MAX_IQM_LIGHTS]; @@ -225,6 +221,7 @@ glsl_R_DrawIQM (entity_t ent) // we need only the rotation for normals. mat4f_t mat; + transform_t transform = Entity_Transform (ent); Transform_GetWorldMatrix (transform, mat); VectorCopy (mat[0], norm_mat + 0); VectorCopy (mat[1], norm_mat + 3); @@ -236,6 +233,8 @@ glsl_R_DrawIQM (entity_t ent) VectorScale (ambientcolor, 1/255.0, ambientcolor); R_FindNearLights (entorigin, MAX_IQM_LIGHTS, lights); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); blend = R_IQMGetLerpedFrames (animation, iqm); frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2, blend, 0); diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 1a4cf90e4..7f71bca33 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -118,8 +118,7 @@ static void R_DrawViewModel (void) { entity_t ent = vr_data.view_model; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); if (vr_data.inhibit_viewmodel || !r_drawviewmodel || !r_drawentities @@ -199,7 +198,6 @@ glsl_R_NewScene (scene_t *scene) for (i = 0; i < 256; i++) d_lightstylevalue[i] = 264; // normal light value - r_refdef.scene = scene; r_refdef.worldmodel = scene->worldmodel; // Force a vis update diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index a9a73aa33..6a5095737 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -134,7 +134,7 @@ R_GetSpriteFrames (entity_t ent, msprite_t *sprite, mspriteframe_t **frame1, mspriteframe_t **frame2, float *blend) { animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); + ent.reg); int framenum = animation->frame; int pose; int i, numframes; @@ -211,9 +211,7 @@ make_quad (mspriteframe_t *frame, vec4f_t origin, vec4f_t sright, vec4f_t sup, f void glsl_R_DrawSprite (entity_t ent) { - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); msprite_t *sprite = (msprite_t *) renderer->model->cache.data; mspriteframe_t *frame1, *frame2; float blend; @@ -230,6 +228,7 @@ glsl_R_DrawSprite (entity_t ent) { 0, 1, 0, 1 }, }; + transform_t transform = Entity_Transform (ent); vec4f_t origin = Transform_GetWorldPosition (transform); cameravec = r_refdef.frame.position - origin; diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 777af38d3..4a38de885 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -230,8 +230,8 @@ surfcache_t * D_CacheSurface (entity_t ent, msurface_t *surface, int miplevel) { surfcache_t *cache; - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, r_refdef.scene->reg); - transform_t transform = Entity_Transform (ent); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); // if the surface is animating or flashing, flush the cache r_drawsurf.texture = R_TextureAnimation (animation, surface); @@ -285,6 +285,7 @@ D_CacheSurface (entity_t ent, msurface_t *surface, int miplevel) r_drawsurf.surf = surface; c_surf++; + transform_t transform = Entity_Transform (ent); R_DrawSurface (transform); return surface->cachespots[miplevel]; diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index d713b0462..df99a1fe2 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -99,15 +99,13 @@ R_AliasCheckBBox (entity_t ent) qboolean zclipped, zfullyclipped; unsigned int anyclip, allclip; int minz; - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, - r_refdef.scene->reg); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); // expand, rotate, and translate points into worldspace + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + ent.reg); visibility->trivial_accept = 0; + + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); pmodel = renderer->model; if (!(pahdr = pmodel->aliashdr)) pahdr = Cache_Get (&pmodel->cache); @@ -116,6 +114,8 @@ R_AliasCheckBBox (entity_t ent) R_AliasSetUpTransform (ent, 0); // construct the base bounding box for this frame + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); frame = animation->frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { @@ -531,11 +531,8 @@ R_AliasPrepareUnclippedPoints (void) static void R_AliasSetupSkin (entity_t ent) { - int skinnum; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - - skinnum = renderer->skinnum; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); + int skinnum = renderer->skinnum; if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { Sys_MaskPrintf (SYS_dev, "R_AliasSetupSkin: no such skin # %d\n", skinnum); @@ -543,7 +540,7 @@ R_AliasSetupSkin (entity_t ent) } animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); + ent.reg); pskindesc = R_AliasGetSkindesc (animation, skinnum, paliashdr); a_skinwidth = pmdl->skinwidth; @@ -607,7 +604,7 @@ R_AliasSetupFrame (entity_t ent) maliasframedesc_t *frame; animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); + ent.reg); frame = R_AliasGetFramedesc (animation, paliashdr); r_apverts = (trivertx_t *) ((byte *) paliashdr + frame->frame); } @@ -618,13 +615,10 @@ R_AliasDrawModel (entity_t ent, alight_t *lighting) { int size; finalvert_t *finalverts; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, - r_refdef.scene->reg); r_amodels_drawn++; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); if (!(paliashdr = renderer->model->aliashdr)) paliashdr = Cache_Get (&renderer->model->cache); pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model); @@ -642,6 +636,8 @@ R_AliasDrawModel (entity_t ent, alight_t *lighting) pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1]; R_AliasSetupSkin (ent); + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + ent.reg); R_AliasSetUpTransform (ent, visibility->trivial_accept); R_AliasSetupLighting (lighting); R_AliasSetupFrame (ent); diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index d6b544512..2c2d4451f 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -356,8 +356,7 @@ R_RenderFace (entity_t ent, msurface_t *fa, int clipflags) vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); mod_brush_t *brush = &renderer->model->brush; // skip out if no more surfs @@ -627,8 +626,7 @@ R_RenderPoly (entity_t ent, msurface_t *fa, int clipflags) polyvert_t pverts[100]; // FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; qboolean visible; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); mod_brush_t *brush = &renderer->model->brush; // FIXME: clean this up and make it faster diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index 64f3230d7..2277a4983 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -292,12 +292,7 @@ R_IQMSetUpTransform (entity_t ent, int trivial_accept) void R_IQMDrawModel (entity_t ent, alight_t *plighting) { - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; iqm_t *iqm = (iqm_t *) model->aliashdr; swiqm_t *sw = (swiqm_t *) iqm->extra_data; @@ -308,6 +303,9 @@ R_IQMDrawModel (entity_t ent, alight_t *plighting) size = (CACHE_SIZE - 1) + sizeof (finalvert_t) * (iqm->num_verts + 1) + sizeof (auxvert_t) * iqm->num_verts; + + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); blend = R_IQMGetLerpedFrames (animation, iqm); frame = R_IQMBlendPalette (iqm, animation->pose1, animation->pose2, blend, size, sw->blend_palette, @@ -318,6 +316,8 @@ R_IQMDrawModel (entity_t ent, alight_t *plighting) (((intptr_t) &pfinalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); pauxverts = (auxvert_t *) &pfinalverts[iqm->num_verts + 1]; + visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, + ent.reg); R_IQMSetUpTransform (ent, visibility->trivial_accept); R_IQMSetupLighting (ent, plighting); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 32e00c85a..45f5debd2 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -152,7 +152,6 @@ R_NewScene (scene_t *scene) model_t *worldmodel = scene->worldmodel; mod_brush_t *brush = &worldmodel->brush; - r_refdef.scene = scene; r_refdef.worldmodel = worldmodel; // clear out efrags in case the level hasn't been reloaded @@ -234,8 +233,7 @@ setup_lighting (entity_t ent, alight_t *lighting) float add; float lightvec[3] = { -1, 0, 0 }; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); minlight = max (renderer->model->min_light, renderer->min_light); // 128 instead of 255 due to clamping below @@ -270,7 +268,7 @@ draw_alias_entity (entity_t ent) // see if the bounding box lets us trivially reject, also // sets trivial accept status visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, - r_refdef.scene->reg); + ent.reg); visibility->trivial_accept = 0; //FIXME if (R_AliasCheckBBox (ent)) { alight_t lighting; @@ -285,7 +283,7 @@ draw_iqm_entity (entity_t ent) // see if the bounding box lets us trivially reject, also // sets trivial accept status visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, - r_refdef.scene->reg); + ent.reg); visibility->trivial_accept = 0; //FIXME alight_t lighting; @@ -339,11 +337,11 @@ R_DrawViewModel (void) viewent = vr_data.view_model; renderer_t *renderer = Ent_GetComponent (viewent.id, scene_renderer, - r_refdef.scene->reg); - transform_t transform = Entity_Transform (viewent); + viewent.reg); if (!renderer->model) return; + transform_t transform = Entity_Transform (viewent); VectorCopy (Transform_GetWorldPosition (transform), r_entorigin); VectorNegate (vup, lighting.lightvec); @@ -382,7 +380,7 @@ R_DrawViewModel (void) } static int -R_BmodelCheckBBox (entity_t ent, model_t *clmodel, float *minmaxs) +R_BmodelCheckBBox (transform_t transform, model_t *clmodel, float *minmaxs) { int i, *pindex, clipflags; vec3_t acceptpt, rejectpt; @@ -391,7 +389,6 @@ R_BmodelCheckBBox (entity_t ent, model_t *clmodel, float *minmaxs) clipflags = 0; - transform_t transform = Entity_Transform (ent); Transform_GetWorldMatrix (transform, mat); if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { for (i = 0; i < 4; i++) { @@ -443,7 +440,6 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) int j, clipflags; unsigned int k; vec3_t origin; - model_t *clmodel; float minmaxs[6]; if (!r_drawentities) @@ -454,25 +450,23 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) for (size_t i = 0; i < queue->ent_queues[mod_brush].size; i++) { entity_t ent = queue->ent_queues[mod_brush].a[i]; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); transform_t transform = Entity_Transform (ent); - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, - r_refdef.scene->reg); VectorCopy (Transform_GetWorldPosition (transform), origin); - clmodel = renderer->model; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + ent.reg); + model_t *model = renderer->model; // see if the bounding box lets us trivially reject, also // sets trivial accept status for (j = 0; j < 3; j++) { - minmaxs[j] = origin[j] + clmodel->mins[j]; - minmaxs[3 + j] = origin[j] + clmodel->maxs[j]; + minmaxs[j] = origin[j] + model->mins[j]; + minmaxs[3 + j] = origin[j] + model->maxs[j]; } - clipflags = R_BmodelCheckBBox (ent, clmodel, minmaxs); + clipflags = R_BmodelCheckBBox (transform, model, minmaxs); if (clipflags != BMODEL_FULLY_CLIPPED) { - mod_brush_t *brush = &clmodel->brush; + mod_brush_t *brush = &model->brush; VectorCopy (origin, r_entorigin); VectorSubtract (r_refdef.frame.position, r_entorigin, modelorg); @@ -502,8 +496,11 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) // Z-buffering is on at this point, so no clipping to the // world tree is needed, just frustum clipping if (r_drawpolys | r_drawculledpolys) { - R_ZDrawSubmodelPolys (ent, clmodel); + R_ZDrawSubmodelPolys (ent, model); } else { + visibility_t *visibility = Ent_GetComponent (ent.id, + scene_visibility, + ent.reg); int topnode_id = visibility->topnode_id; mod_brush_t *brush = &r_refdef.worldmodel->brush; @@ -512,13 +509,13 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) // BSP mnode_t *node = brush->nodes + topnode_id; r_clipflags = clipflags; - R_DrawSolidClippedSubmodelPolygons (ent, clmodel, node); + R_DrawSolidClippedSubmodelPolygons (ent, model, node); } else { // falls entirely in one leaf, so we just put // all the edges in the edge list and let 1/z // sorting handle drawing order mleaf_t *leaf = brush->leafs + ~topnode_id; - R_DrawSubmodelPolygons (ent, clmodel, clipflags, leaf); + R_DrawSubmodelPolygons (ent, model, clipflags, leaf); } } diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 7a536483c..987eccfc2 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -245,23 +245,19 @@ R_SetupAndDrawSprite (const vec3_t relvieworg) void R_DrawSprite (entity_t ent) { - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); msprite_t *sprite = renderer->model->cache.data; - vec4f_t cameravec = r_refdef.frame.position - r_entorigin; - + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); r_spritedesc.pspriteframe = R_GetSpriteFrame (sprite, animation); sprite_width = r_spritedesc.pspriteframe->width; sprite_height = r_spritedesc.pspriteframe->height; - vec4f_t up = {}; - vec4f_t right = {}; - vec4f_t fwd = {}; + vec4f_t up = {}, right = {}, fwd = {}; + vec4f_t cameravec = r_refdef.frame.position - r_entorigin; + transform_t transform = Entity_Transform (ent); if (!R_BillboardFrame (transform, sprite->type, cameravec, &up, &right, &fwd)) { // the orientation is undefined so can't draw the sprite diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 1496023e6..e2c8371fc 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -120,14 +120,10 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, void Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) { - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); vulkan_ctx_t *ctx = rFrame->vulkan_ctx; aliasctx_t *actx = ctx->alias_context; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; aliashdr_t *hdr; qfv_alias_skin_t *skin; @@ -137,8 +133,11 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) hdr = Cache_Get (&model->cache); } + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); constants.blend = R_AliasGetLerpedFrames (animation, hdr); + transform_t transform = Entity_Transform (ent); qfv_push_constants_t push_constants[] = { { VK_SHADER_STAGE_VERTEX_BIT, field_offset (alias_push_constants_t, mat), diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 985afec79..499574a09 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -588,12 +588,9 @@ static int R_DrawBrushModel (entity_t ent, bsp_pass_t *pass, vulkan_ctx_t *ctx) { transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); - float radius; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; + float radius; vec3_t mins, maxs; bspctx_t *bctx = ctx->bsp_context; @@ -614,6 +611,8 @@ R_DrawBrushModel (entity_t ent, bsp_pass_t *pass, vulkan_ctx_t *ctx) return 0; } + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); pass->ent_frame = animation->frame & 1; pass->inst_id = model->render_id; pass->inst_id |= renderer->colormod[3] < 1 ? INST_ALPHA : 0; @@ -1036,10 +1035,8 @@ ent_model_cmp (const void *_a, const void *_b) { const entity_t *a = _a; const entity_t *b = _b; - renderer_t *ra = Ent_GetComponent (a->id, scene_renderer, - r_refdef.scene->reg); - renderer_t *rb = Ent_GetComponent (b->id, scene_renderer, - r_refdef.scene->reg); + renderer_t *ra = Ent_GetComponent (a->id, scene_renderer, a->reg); + renderer_t *rb = Ent_GetComponent (b->id, scene_renderer, b->reg); return ra->model->render_id - rb->model->render_id; } diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 7b9f743d9..e85aabf8e 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -130,16 +130,12 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, void Vulkan_DrawIQM (entity_t ent, qfv_renderframe_t *rFrame) { - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; iqmctx_t *ictx = ctx->iqm_context; iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; iqm_t *iqm = (iqm_t *) model->aliashdr; qfv_iqm_t *mesh = iqm->extra_data; @@ -147,6 +143,8 @@ Vulkan_DrawIQM (entity_t ent, qfv_renderframe_t *rFrame) iqm_push_constants_t constants = {}; iqmframe_t *frame; + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); constants.blend = R_IQMGetLerpedFrames (animation, iqm); frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2, constants.blend, 0); @@ -173,7 +171,7 @@ Vulkan_DrawIQM (entity_t ent, qfv_renderframe_t *rFrame) dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); dfunc->vkUnmapMemory (device->dev, mesh->bones->memory); - + transform_t transform = Entity_Transform (ent); qfv_push_constants_t push_constants[] = { { VK_SHADER_STAGE_VERTEX_BIT, field_offset (iqm_push_constants_t, mat), diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index c5c232b5a..035910678 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -108,8 +108,7 @@ static void Vulkan_DrawViewModel (vulkan_ctx_t *ctx) { entity_t ent = vr_data.view_model; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); if (vr_data.inhibit_viewmodel || !r_drawviewmodel || !r_drawentities @@ -148,7 +147,6 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) d_lightstylevalue[i] = 264; // normal light value } - r_refdef.scene = scene; r_refdef.worldmodel = scene->worldmodel; // Force a vis update diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index bb95f6cbe..07c2a3d16 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -107,14 +107,10 @@ emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, void Vulkan_DrawSprite (entity_t ent, qfv_renderframe_t *rFrame) { - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - r_refdef.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - r_refdef.scene->reg); vulkan_ctx_t *ctx = rFrame->vulkan_ctx; spritectx_t *sctx = ctx->sprite_context; spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; msprite_t *sprite = model->cache.data; @@ -126,8 +122,11 @@ Vulkan_DrawSprite (entity_t ent, qfv_renderframe_t *rFrame) 64, sizeof (frame), &frame }, }; + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); frame = (ptrdiff_t) R_GetSpriteFrame (sprite, animation); + transform_t transform = Entity_Transform (ent); mat[3] = Transform_GetWorldPosition (transform); vec4f_t cameravec = r_refdef.frame.position - mat[3]; R_BillboardFrame (transform, sprite->type, cameravec, From 20c861027e2047e32384ab1ef7ab476cd1860669 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 25 Oct 2022 19:36:09 +0900 Subject: [PATCH 3095/3664] [sw] Take advantage of the ECS for edge rendering This fixes the segfault due to the world entity not actually existing, without adding a world entity. It takes advantage of the ECS in that the edge renderer needs only the world matrix, brush model pointer, and the animation frame number (which is just 0/1 for brush models), thus the inherent SOA of ECS helps out, though benchmarking is needed to see if it made any real difference. With this, all 4 renderers are working again. --- include/QF/render.h | 1 + include/QF/scene/scene.h | 7 +++ include/d_iface.h | 2 +- include/d_local.h | 2 +- include/r_internal.h | 1 + include/r_local.h | 16 +++--- include/r_shared.h | 4 +- libs/scene/scene.c | 37 +++++++++++++ libs/video/renderer/gl/gl_rsurf.c | 2 +- libs/video/renderer/glsl/glsl_bsp.c | 2 +- libs/video/renderer/r_bsp.c | 4 +- libs/video/renderer/sw/d_edge.c | 9 ++-- libs/video/renderer/sw/d_surf.c | 10 ++-- libs/video/renderer/sw/sw_rbsp.c | 33 +++++------- libs/video/renderer/sw/sw_rdraw.c | 21 ++++---- libs/video/renderer/sw/sw_redge.c | 4 +- libs/video/renderer/sw/sw_rmain.c | 80 +++++++++++++++++++++++------ libs/video/renderer/sw/sw_rsurf.c | 15 +++--- 18 files changed, 168 insertions(+), 82 deletions(-) diff --git a/include/QF/render.h b/include/QF/render.h index 94e1f0a29..cd06fb44f 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -166,6 +166,7 @@ typedef struct { int ambientlight; int drawflat; + struct ecs_registry_s *registry; struct model_s *worldmodel; } refdef_t; diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index 14983c62c..ae9a03871 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -48,6 +48,13 @@ enum scene_components { scene_active, scene_old_origin, //XXX FIXME XXX should not be here + //FIXME these should probably be private to the sw renderer (and in a + //group, which needs to be implemented), but need to sort out a good + //scheme for semi-dynamic components + scene_sw_matrix, // world transform matrix + scene_sw_frame, // animation frame + scene_sw_brush, // brush model data pointer + scene_num_components }; diff --git a/include/d_iface.h b/include/d_iface.h index 454502fb2..7970064ed 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -201,7 +201,7 @@ typedef struct extern drawsurf_t r_drawsurf; struct transform_s; -void R_DrawSurface (struct transform_s transform); +void R_DrawSurface (uint32_t render_id); void R_GenTile (msurface_t *psurf, void *pdest); // !!! if this is changed, it must be changed in d_iface.h too !!! diff --git a/include/d_local.h b/include/d_local.h index cd06ab0ae..20ae2cb73 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -92,7 +92,7 @@ void D_DrawSkyScans (struct espan_s *pspan); void R_ShowSubDiv (void); extern void (*prealspandrawer)(void); struct entity_s; -surfcache_t *D_CacheSurface (struct entity_s ent, +surfcache_t *D_CacheSurface (uint32_t render_id, msurface_t *surface, int miplevel); int D_MipLevelForScale (float scale) __attribute__((pure)); diff --git a/include/r_internal.h b/include/r_internal.h index 1f1d72c77..4800384f4 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -21,6 +21,7 @@ extern vid_render_funcs_t *vid_render_funcs; #define vr_funcs vid_render_funcs extern refdef_t r_refdef; +#define SW_COMP(comp, id) ((void *)((byte *)r_refdef.registry->comp_pools[comp].data + (id) * r_refdef.registry->components[comp].size)) extern int r_viewsize; void R_LineGraph (int x, int y, int *h_vals, int count, int height); diff --git a/include/r_local.h b/include/r_local.h index fbb7e74d3..01fe81733 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -150,18 +150,18 @@ struct animation_s; void R_SpriteBegin (void); void R_SpriteEnd (void); void R_DrawSprite (struct entity_s ent); -void R_RenderFace (struct entity_s ent, msurface_t *fa, int clipflags); -void R_RenderPoly (struct entity_s ent, msurface_t *fa, int clipflags); -void R_RenderBmodelFace (struct entity_s ent, bedge_t *pedges, msurface_t *psurf); +void R_RenderFace (uint32_t render_id, msurface_t *fa, int clipflags); +void R_RenderPoly (uint32_t render_id, msurface_t *fa, int clipflags); +void R_RenderBmodelFace (uint32_t render_id, bedge_t *pedges, msurface_t *psurf); void R_TransformFrustum (void); void R_SetSkyFrame (void); void R_DrawSurfaceBlock (void); -struct texture_s *R_TextureAnimation (const struct animation_s *animation, msurface_t *surf) __attribute__((pure)); +struct texture_s *R_TextureAnimation (int frame, msurface_t *surf) __attribute__((pure)); void R_GenSkyTile (void *pdest); void R_SurfPatch (void); -void R_DrawSubmodelPolygons (struct entity_s ent, model_t *pmodel, int clipflags, struct mleaf_s *topleaf); -void R_DrawSolidClippedSubmodelPolygons (struct entity_s ent, model_t *pmodel, struct mnode_s *topnode); +void R_DrawSubmodelPolygons (uint32_t render_id, mod_brush_t *brush, int clipflags, struct mleaf_s *topleaf); +void R_DrawSolidClippedSubmodelPolygons (uint32_t render_id, mod_brush_t *brush, struct mnode_s *topnode); void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel); surf_t *R_GetSurf (void); @@ -198,7 +198,7 @@ extern void R_EdgeCodeStart (void); extern void R_EdgeCodeEnd (void); struct transform_s; -extern void R_RotateBmodel (struct transform_s transform); +extern void R_RotateBmodel (vec4f_t *mat); extern int c_faceclip; extern int r_polycount; @@ -230,7 +230,7 @@ typedef struct btofpoly_s { extern int numbtofpolys; void R_InitTurb (void); -void R_ZDrawSubmodelPolys (struct entity_s ent, model_t *clmodel); +void R_ZDrawSubmodelPolys (uint32_t render_id, mod_brush_t *brush); // Alias models =========================================== diff --git a/include/r_shared.h b/include/r_shared.h index 90f69aa03..c189d876a 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -99,7 +99,7 @@ typedef struct surf_s { // start) int flags; // currentface flags void *data; // associated data like msurface_t - entity_t entity; + uint32_t render_id; float nearzi; // nearest 1/z on surface, for mipmapping qboolean insubmodel; float d_ziorigin, d_zistepu, d_zistepv; @@ -163,4 +163,6 @@ typedef struct edge_s extern float r_avertexnormals[NUMVERTEXNORMALS][3]; extern vec3_t ambientcolor; +uint32_t SW_AddEntity (entity_t ent); + #endif // _R_SHARED_H diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 1800b87c8..4f1a0b22a 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -60,6 +60,27 @@ create_old_origin (void *_old_origin) *old_origin = (vec4f_t) {0, 0, 0, 1}; } +static void +sw_identity_matrix (void *_mat) +{ + mat4f_t *mat = _mat; + mat4fidentity (*mat); +} + +static void +sw_frame_0 (void *_frame) +{ + byte *frame = _frame; + *frame = 0; +} + +static void +sw_null_brush (void *_brush) +{ + struct mod_brush_s **brush = _brush; + *brush = 0; +} + static const component_t scene_components[] = { [scene_href] = { .size = sizeof (hierref_t), @@ -91,6 +112,22 @@ static const component_t scene_components[] = { .create = create_old_origin, .name = "old_origin", }, + + [scene_sw_matrix] = { + .size = sizeof (mat4f_t), + .create = sw_identity_matrix, + .name = "sw world transform", + }, + [scene_sw_frame] = { + .size = sizeof (byte), + .create = sw_frame_0, + .name = "sw brush model animation frame", + }, + [scene_sw_brush] = { + .size = sizeof (struct mod_brush_s *), + .create = sw_null_brush, + .name = "sw brush model data pointer", + }, }; static byte empty_visdata[] = { 0x01 }; diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 73af64ca9..5d199d214 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -486,7 +486,7 @@ chain_surface (glbspctx_t *bctx, msurface_t *surf) if (!surf->texinfo->texture->anim_total) tx = surf->texinfo->texture; else - tx = R_TextureAnimation (bctx->animation, surf); + tx = R_TextureAnimation (bctx->animation->frame, surf); tex = tx->render; sc = CHAIN_SURF_F2B (surf, tex->tex_chain); diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 1d31f81f2..6215498f7 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -399,7 +399,7 @@ chain_surface (glslbspctx_t *bctx, msurface_t *surf) if (!surf->texinfo->texture->anim_total) tx = surf->texinfo->texture; else - tx = R_TextureAnimation (bctx->animation, surf); + tx = R_TextureAnimation (bctx->animation->frame, surf); tex = tx->render; is = CHAIN_SURF_F2B (surf, tex->tex_chain); diff --git a/libs/video/renderer/r_bsp.c b/libs/video/renderer/r_bsp.c index e2b8b951e..19b5475e9 100644 --- a/libs/video/renderer/r_bsp.c +++ b/libs/video/renderer/r_bsp.c @@ -103,12 +103,12 @@ R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes, int *leaf_visframes, Returns the proper texture for a given time and base texture */ texture_t * -R_TextureAnimation (const animation_t *animation, msurface_t *surf) +R_TextureAnimation (int frame, msurface_t *surf) { texture_t *base = surf->texinfo->texture; int count, relative; - if (animation->frame) { + if (frame) { if (base->alternate_anims) base = base->alternate_anims; } diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 80f7c9671..401349419 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -150,12 +150,11 @@ transform_submodel_poly (surf_t *s) { // FIXME: we don't want to do all this for every polygon! // TODO: store once at start of frame - transform_t transform = Entity_Transform (s->entity); - vec4f_t local_modelorg = r_refdef.frame.position - - Transform_GetWorldPosition (transform); + vec4f_t *transform = SW_COMP(scene_sw_matrix, s->render_id); + vec4f_t local_modelorg = r_refdef.frame.position - transform[3]; TransformVector ((vec_t*)&local_modelorg, transformed_modelorg);//FIXME - R_RotateBmodel (transform); // FIXME: don't mess with the + R_RotateBmodel (transform); // FIXME: don't mess with the // frustum, make entity passed in } @@ -249,7 +248,7 @@ D_DrawSurfaces (void) * pface->texinfo->mipadjust); // FIXME: make this passed in to D_CacheSurface - pcurrentcache = D_CacheSurface (s->entity, pface, miplevel); + pcurrentcache = D_CacheSurface (s->render_id, pface, miplevel); cacheblock = (byte *) pcurrentcache->data; cachewidth = pcurrentcache->width; diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 4a38de885..2c7b327b3 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -227,14 +227,13 @@ D_SCDump (void) #endif surfcache_t * -D_CacheSurface (entity_t ent, msurface_t *surface, int miplevel) +D_CacheSurface (uint32_t render_id, msurface_t *surface, int miplevel) { surfcache_t *cache; - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - ent.reg); + byte frame = *(byte *) SW_COMP (scene_sw_frame, render_id); // if the surface is animating or flashing, flush the cache - r_drawsurf.texture = R_TextureAnimation (animation, surface); + r_drawsurf.texture = R_TextureAnimation (frame, surface); r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; @@ -285,8 +284,7 @@ D_CacheSurface (entity_t ent, msurface_t *surface, int miplevel) r_drawsurf.surf = surface; c_surf++; - transform_t transform = Entity_Transform (ent); - R_DrawSurface (transform); + R_DrawSurface (render_id); return surface->cachespots[miplevel]; } diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index e8544abd5..7e8a7e69a 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -44,7 +44,7 @@ typedef struct glbspctx_s { mod_brush_t *brush; - entity_t entity; + uint32_t render_id; } swbspctx_t; // current entity info @@ -85,10 +85,8 @@ R_EntityRotate (vec3_t vec) void -R_RotateBmodel (transform_t transform) +R_RotateBmodel (vec4f_t *mat) { - mat4f_t mat; - Transform_GetWorldMatrix (transform, mat); VectorCopy (mat[0], entity_rotation[0]); VectorCopy (mat[1], entity_rotation[1]); VectorCopy (mat[2], entity_rotation[2]); @@ -104,7 +102,7 @@ R_RotateBmodel (transform_t transform) static void -R_RecursiveClipBPoly (entity_t ent, bedge_t *pedges, mnode_t *pnode, +R_RecursiveClipBPoly (uint32_t render_id, bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) { bedge_t *psideedges[2], *pnextedge, *ptedge; @@ -239,11 +237,11 @@ R_RecursiveClipBPoly (entity_t ent, bedge_t *pedges, mnode_t *pnode, if (r_leaf_visframes[~child_id] == r_visframecount && leaf->contents != CONTENTS_SOLID) { r_currentbkey = leaf->key; - R_RenderBmodelFace (ent, psideedges[i], psurf); + R_RenderBmodelFace (render_id, psideedges[i], psurf); } } else { if (r_node_visframes[child_id] == r_visframecount) { - R_RecursiveClipBPoly (ent, psideedges[i], pn, psurf); + R_RecursiveClipBPoly (render_id, psideedges[i], pn, psurf); } } } @@ -252,7 +250,7 @@ R_RecursiveClipBPoly (entity_t ent, bedge_t *pedges, mnode_t *pnode, void -R_DrawSolidClippedSubmodelPolygons (entity_t ent, model_t *model, +R_DrawSolidClippedSubmodelPolygons (uint32_t render_id, mod_brush_t *brush, mnode_t *topnode) { int i, j, lindex; @@ -263,7 +261,6 @@ R_DrawSolidClippedSubmodelPolygons (entity_t ent, model_t *model, mvertex_t bverts[MAX_BMODEL_VERTS]; bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; medge_t *pedge, *pedges; - mod_brush_t *brush = &model->brush; // FIXME: use bounding-box-based frustum clipping info? @@ -313,7 +310,7 @@ R_DrawSolidClippedSubmodelPolygons (entity_t ent, model_t *model, pbedge[j - 1].pnext = NULL; // mark end of edges - R_RecursiveClipBPoly (ent, pbedge, topnode, psurf); + R_RecursiveClipBPoly (render_id, pbedge, topnode, psurf); } else { Sys_Error ("no edges in bmodel"); } @@ -323,7 +320,7 @@ R_DrawSolidClippedSubmodelPolygons (entity_t ent, model_t *model, void -R_DrawSubmodelPolygons (entity_t ent, model_t *model, int clipflags, +R_DrawSubmodelPolygons (uint32_t render_id, mod_brush_t *brush, int clipflags, mleaf_t *topleaf) { int i; @@ -331,7 +328,6 @@ R_DrawSubmodelPolygons (entity_t ent, model_t *model, int clipflags, msurface_t *psurf; int numsurfaces; plane_t *pplane; - mod_brush_t *brush = &model->brush; // FIXME: use bounding-box-based frustum clipping info? @@ -350,7 +346,7 @@ R_DrawSubmodelPolygons (entity_t ent, model_t *model, int clipflags, r_currentkey = topleaf->key; // FIXME: use bounding-box-based frustum clipping info? - R_RenderFace (ent, psurf, clipflags); + R_RenderFace (render_id, psurf, clipflags); } } } @@ -379,7 +375,7 @@ visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags) { int c; msurface_t *surf; - entity_t ent = bctx->entity; + uint32_t render_id = bctx->render_id; mod_brush_t *brush = bctx->brush; // sneaky hack for side = side ? SURF_PLANEBACK : 0; @@ -404,10 +400,10 @@ visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags) numbtofpolys++; } } else { - R_RenderPoly (ent, surf, clipflags); + R_RenderPoly (render_id, surf, clipflags); } } else { - R_RenderFace (ent, surf, clipflags); + R_RenderFace (render_id, surf, clipflags); } } // all surfaces on the same node share the same sequence number @@ -533,11 +529,10 @@ R_RenderWorld (void) { int i; btofpoly_t btofpolys[MAX_BTOFPOLYS]; - entity_t ent = nullentity; mod_brush_t *brush = &r_refdef.worldmodel->brush; swbspctx_t bspctx = { brush, - ent, + 0, }; pbtofpolys = btofpolys; @@ -551,7 +546,7 @@ R_RenderWorld (void) // back in that order if (r_worldpolysbacktofront) { for (i = numbtofpolys - 1; i >= 0; i--) { - R_RenderPoly (ent, btofpolys[i].psurf, btofpolys[i].clipflags); + R_RenderPoly (0, btofpolys[i].psurf, btofpolys[i].clipflags); } } } diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index 2c2d4451f..bc5cb4670 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -347,7 +347,7 @@ R_EmitCachedEdge (void) void -R_RenderFace (entity_t ent, msurface_t *fa, int clipflags) +R_RenderFace (uint32_t render_id, msurface_t *fa, int clipflags) { int i, lindex; unsigned int mask; @@ -356,8 +356,7 @@ R_RenderFace (entity_t ent, msurface_t *fa, int clipflags) vec3_t p_normal; medge_t *pedges, tedge; clipplane_t *pclip; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); - mod_brush_t *brush = &renderer->model->brush; + mod_brush_t *brush = *(mod_brush_t **) SW_COMP (scene_sw_brush, render_id); // skip out if no more surfs if ((surface_p) >= surf_max) { @@ -494,7 +493,7 @@ R_RenderFace (entity_t ent, msurface_t *fa, int clipflags) surface_p->flags = fa->flags; surface_p->insubmodel = insubmodel; surface_p->spanstate = 0; - surface_p->entity = ent; + surface_p->render_id = render_id; surface_p->key = r_currentkey++; surface_p->spans = NULL; @@ -514,7 +513,7 @@ R_RenderFace (entity_t ent, msurface_t *fa, int clipflags) void -R_RenderBmodelFace (entity_t ent, bedge_t *pedges, msurface_t *psurf) +R_RenderBmodelFace (uint32_t render_id, bedge_t *pedges, msurface_t *psurf) { int i; unsigned int mask; @@ -593,7 +592,7 @@ R_RenderBmodelFace (entity_t ent, bedge_t *pedges, msurface_t *psurf) surface_p->flags = psurf->flags; surface_p->insubmodel = true; surface_p->spanstate = 0; - surface_p->entity = ent; + surface_p->render_id = render_id; surface_p->key = r_currentbkey; surface_p->spans = NULL; @@ -613,7 +612,7 @@ R_RenderBmodelFace (entity_t ent, bedge_t *pedges, msurface_t *psurf) void -R_RenderPoly (entity_t ent, msurface_t *fa, int clipflags) +R_RenderPoly (uint32_t render_id, msurface_t *fa, int clipflags) { int i, lindex, lnumverts, s_axis, t_axis; float dist, lastdist, lzi, scale, u, v, frac; @@ -626,8 +625,7 @@ R_RenderPoly (entity_t ent, msurface_t *fa, int clipflags) polyvert_t pverts[100]; // FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; qboolean visible; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); - mod_brush_t *brush = &renderer->model->brush; + mod_brush_t *brush = *(mod_brush_t **) SW_COMP (scene_sw_brush, render_id); // FIXME: clean this up and make it faster // FIXME: guard against running out of vertices @@ -782,13 +780,12 @@ R_RenderPoly (entity_t ent, msurface_t *fa, int clipflags) void -R_ZDrawSubmodelPolys (entity_t ent, model_t *model) +R_ZDrawSubmodelPolys (uint32_t render_id, mod_brush_t *brush) { int i, numsurfaces; msurface_t *psurf; float dot; plane_t *pplane; - mod_brush_t *brush = &model->brush; psurf = &brush->surfaces[brush->firstmodelsurface]; numsurfaces = brush->nummodelsurfaces; @@ -803,7 +800,7 @@ R_ZDrawSubmodelPolys (entity_t ent, model_t *model) if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { // FIXME: use bounding-box-based frustum clipping info? - R_RenderPoly (ent, psurf, 15); + R_RenderPoly (render_id, psurf, 15); } } } diff --git a/libs/video/renderer/sw/sw_redge.c b/libs/video/renderer/sw/sw_redge.c index 339c98bcb..df49f89ad 100644 --- a/libs/video/renderer/sw/sw_redge.c +++ b/libs/video/renderer/sw/sw_redge.c @@ -89,7 +89,7 @@ R_DrawCulledPolys (void) if (!(s->flags & SURF_DRAWBACKGROUND)) { pface = (msurface_t *) s->data; - R_RenderPoly (s->entity, pface, 15); + R_RenderPoly (s->render_id, pface, 15); } } } else { @@ -99,7 +99,7 @@ R_DrawCulledPolys (void) if (!(s->flags & SURF_DRAWBACKGROUND)) { pface = (msurface_t *) s->data; - R_RenderPoly (s->entity, pface, 15); + R_RenderPoly (s->render_id, pface, 15); } } } diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 45f5debd2..61e9aa680 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -146,12 +146,58 @@ sw_R_Init (void) Skin_Init (); } +uint32_t +SW_AddEntity (entity_t ent) +{ + // This takes advantage of the implicit (FIXME, make explicit) grouping of + // the sw components: as all entities that get added here will always have + // all three components, the three component pools are always in sync, thus + // the pool count can be used as a render id which can in turn be used to + // index the components within the pools. + ecs_registry_t *reg = ent.reg; + ecs_pool_t *pool = ®->comp_pools[scene_sw_matrix]; + uint32_t render_id = pool->count; + + transform_t transform = Entity_Transform (ent); + Ent_SetComponent (ent.id, scene_sw_matrix, reg, + Transform_GetWorldMatrixPtr (transform)); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, reg); + Ent_SetComponent (ent.id, scene_sw_frame, reg, &animation->frame); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, reg); + mod_brush_t *brush = &renderer->model->brush; + Ent_SetComponent (ent.id, scene_sw_brush, reg, &brush); + + return render_id; +} + +static void +reset_sw_components (ecs_registry_t *reg) +{ + static uint32_t sw_comps[] = { + scene_sw_matrix, + scene_sw_frame, + scene_sw_brush, + }; + + for (int i = 0; i < 3; i++) { + ecs_pool_t *pool = ®->comp_pools[sw_comps[i]]; + pool->count = 0; // remove component from every entity + // reserve first component object (render id 0) for the world + // pseudo-entity. + Ent_SetComponent (0, sw_comps[i], reg, 0); + // make sure entity 0 gets allocated a new component object as the + // world pseudo-entity currently has no actual entity (FIXME) + pool->dense[0] = nullent; + } +} + void R_NewScene (scene_t *scene) { model_t *worldmodel = scene->worldmodel; mod_brush_t *brush = &worldmodel->brush; + r_refdef.registry = scene->reg; r_refdef.worldmodel = worldmodel; // clear out efrags in case the level hasn't been reloaded @@ -380,25 +426,23 @@ R_DrawViewModel (void) } static int -R_BmodelCheckBBox (transform_t transform, model_t *clmodel, float *minmaxs) +R_BmodelCheckBBox (const vec4f_t *transform, float radius, float *minmaxs) { int i, *pindex, clipflags; vec3_t acceptpt, rejectpt; double d; - mat4f_t mat; clipflags = 0; - Transform_GetWorldMatrix (transform, mat); - if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { + if (transform[0][0] != 1 || transform[1][1] != 1 || transform[2][2] != 1) { for (i = 0; i < 4; i++) { - d = DotProduct (mat[3], view_clipplanes[i].normal); + d = DotProduct (transform[3], view_clipplanes[i].normal); d -= view_clipplanes[i].dist; - if (d <= -clmodel->radius) + if (d <= -radius) return BMODEL_FULLY_CLIPPED; - if (d <= clmodel->radius) + if (d <= radius) clipflags |= (1 << i); } } else { @@ -449,9 +493,11 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) for (size_t i = 0; i < queue->ent_queues[mod_brush].size; i++) { entity_t ent = queue->ent_queues[mod_brush].a[i]; + uint32_t render_id = SW_AddEntity (ent); - transform_t transform = Entity_Transform (ent); - VectorCopy (Transform_GetWorldPosition (transform), origin); + vec4f_t *transform = Ent_GetComponent (ent.id, scene_sw_matrix, + ent.reg); + VectorCopy (transform[3], origin); renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; @@ -463,7 +509,7 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) minmaxs[3 + j] = origin[j] + model->maxs[j]; } - clipflags = R_BmodelCheckBBox (transform, model, minmaxs); + clipflags = R_BmodelCheckBBox (transform, model->radius, minmaxs); if (clipflags != BMODEL_FULLY_CLIPPED) { mod_brush_t *brush = &model->brush; @@ -496,26 +542,26 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue) // Z-buffering is on at this point, so no clipping to the // world tree is needed, just frustum clipping if (r_drawpolys | r_drawculledpolys) { - R_ZDrawSubmodelPolys (ent, model); + R_ZDrawSubmodelPolys (render_id, brush); } else { visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, ent.reg); int topnode_id = visibility->topnode_id; - mod_brush_t *brush = &r_refdef.worldmodel->brush; + mod_brush_t *world_brush = &r_refdef.worldmodel->brush; if (topnode_id >= 0) { // not a leaf; has to be clipped to the world // BSP - mnode_t *node = brush->nodes + topnode_id; + mnode_t *node = world_brush->nodes + topnode_id; r_clipflags = clipflags; - R_DrawSolidClippedSubmodelPolygons (ent, model, node); + R_DrawSolidClippedSubmodelPolygons (render_id, brush, node); } else { // falls entirely in one leaf, so we just put // all the edges in the edge list and let 1/z // sorting handle drawing order - mleaf_t *leaf = brush->leafs + ~topnode_id; - R_DrawSubmodelPolygons (ent, model, clipflags, leaf); + mleaf_t *leaf = world_brush->leafs + ~topnode_id; + R_DrawSubmodelPolygons (render_id, brush, clipflags, leaf); } } @@ -588,6 +634,8 @@ R_RenderView_ (void) return; } + reset_sw_components (r_refdef.registry); + *(mod_brush_t **) SW_COMP (scene_sw_brush, 0) = &r_refdef.worldmodel->brush; R_SetupFrame (); // make FDIV fast. This reduces timing precision after we've been running for a diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 2b111cdf4..0cb651c15 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -73,7 +73,7 @@ static unsigned int blocklights[34 * 34]; //FIXME make dynamic static void -R_AddDynamicLights (transform_t transform) +R_AddDynamicLights (uint32_t render_id) { msurface_t *surf; unsigned int lnum; @@ -91,9 +91,10 @@ R_AddDynamicLights (transform_t transform) tmax = (surf->extents[1] >> 4) + 1; tex = surf->texinfo; - if (Transform_Valid (transform)) { + if (render_id) { //FIXME give world entity a transform - entorigin = Transform_GetWorldPosition (transform); + vec4f_t *transform = SW_COMP (scene_sw_matrix, render_id); + entorigin = transform[3]; } for (lnum = 0; lnum < r_maxdlights; lnum++) { @@ -144,7 +145,7 @@ R_AddDynamicLights (transform_t transform) Combine and scale multiple lightmaps into the 8.8 format in blocklights */ static void -R_BuildLightMap (transform_t transform) +R_BuildLightMap (uint32_t render_id) { int smax, tmax; int t; @@ -180,7 +181,7 @@ R_BuildLightMap (transform_t transform) } // add all the dynamic lights if (surf->dlightframe == r_framecount) - R_AddDynamicLights (transform); + R_AddDynamicLights (render_id); // bound, invert, and shift for (i = 0; i < size; i++) { @@ -194,7 +195,7 @@ R_BuildLightMap (transform_t transform) } void -R_DrawSurface (transform_t transform) +R_DrawSurface (uint32_t render_id) { byte *basetptr; int smax, tmax, twidth; @@ -206,7 +207,7 @@ R_DrawSurface (transform_t transform) texture_t *mt; // calculate the lightings - R_BuildLightMap (transform); + R_BuildLightMap (render_id); surfrowbytes = r_drawsurf.rowbytes; From 52b7f7f30838286ebf0b50b83c335e4a40f177b4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Oct 2022 12:32:09 +0900 Subject: [PATCH 3096/3664] [renderer] Fix a comment typo and add a fixme --- libs/video/renderer/glsl/quakeforge.glsl | 2 +- libs/video/renderer/sw/sw_rmain.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index 7b284c302..b99f142e2 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -598,7 +598,7 @@ in vec2 uv; void main () { - // slight offset on y is to avoid the singularity straight aheat + // slight offset on y is to avoid the singularity straight ahead vec2 xy = (2.0 * uv - vec2 (1, 1.00002)) * (vec2(1, -aspect)); float r = sqrt (dot (xy, xy)); vec2 cs = vec2 (cos (r * fov), sin (r * fov)); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 61e9aa680..6fc5069ba 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -184,6 +184,8 @@ reset_sw_components (ecs_registry_t *reg) pool->count = 0; // remove component from every entity // reserve first component object (render id 0) for the world // pseudo-entity. + //FIXME takes advantage of the lack of checks for the validity of the + //entity id. Ent_SetComponent (0, sw_comps[i], reg, 0); // make sure entity 0 gets allocated a new component object as the // world pseudo-entity currently has no actual entity (FIXME) From 4df145d76a33b8189b55c376b4e1e64cbbfb93f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Oct 2022 12:34:09 +0900 Subject: [PATCH 3097/3664] [scene] Improve entity component check For a component to be on an entity, the entity id in the component pool's dense array must match the entity. --- include/QF/scene/component.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/scene/component.h b/include/QF/scene/component.h index 6baf76b37..827633184 100644 --- a/include/QF/scene/component.h +++ b/include/QF/scene/component.h @@ -194,7 +194,7 @@ COMPINLINE int Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) { uint32_t ind = reg->comp_pools[comp].sparse[Ent_Index (ent)]; - return ind != nullent; + return reg->comp_pools[comp].dense[ind] == ent; } COMPINLINE void * From db7f8a461e114ac1caa46e16e6befb6f70e6243d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Oct 2022 15:22:09 +0900 Subject: [PATCH 3098/3664] [ecs] Move ECS core into its own library While the libraries are probably getting a little out of hand, the separation into its own directory is probably a good thing as an ECS should not be tied to scenes. This should make the ECS more generally useful. --- include/QF/Makemodule.am | 6 ++- include/QF/{scene => ecs}/component.h | 11 ++-- include/QF/{scene => ecs}/hierarchy.h | 19 +++---- include/QF/scene/transform.h | 14 ++--- include/scn_internal.h | 7 +-- libs/Makemodule.am | 1 + libs/client/cl_effects.c | 1 - libs/client/cl_entities.c | 1 - libs/client/cl_temp_entities.c | 1 - libs/client/cl_view.c | 4 +- libs/client/cl_world.c | 1 - libs/ecs/Makemodule.am | 12 +++++ libs/{scene => ecs}/component.c | 2 +- libs/{scene => ecs}/hierarchy.c | 51 ++++++++----------- libs/ecs/test/Makemodule.am | 25 +++++++++ libs/{scene => ecs}/test/test-components.c | 0 libs/{scene => ecs}/test/test-registry.c | 0 libs/ruamoko/rua_scene.c | 4 +- libs/scene/Makemodule.am | 7 +-- libs/scene/camera.c | 1 - libs/scene/scene.c | 4 +- libs/scene/test/Makemodule.am | 19 +------ libs/scene/transform.c | 20 +++----- libs/video/renderer/gl/gl_mod_alias.c | 2 - libs/video/renderer/gl/gl_mod_iqm.c | 2 - libs/video/renderer/gl/gl_mod_sprite.c | 2 - libs/video/renderer/gl/gl_rmain.c | 2 - libs/video/renderer/gl/gl_rsurf.c | 2 - libs/video/renderer/glsl/glsl_alias.c | 2 - libs/video/renderer/glsl/glsl_bsp.c | 2 - libs/video/renderer/glsl/glsl_iqm.c | 2 - libs/video/renderer/glsl/glsl_main.c | 2 - libs/video/renderer/glsl/glsl_sprite.c | 2 - libs/video/renderer/sw/d_edge.c | 2 - libs/video/renderer/sw/d_surf.c | 2 - libs/video/renderer/sw/sw_ralias.c | 2 - libs/video/renderer/sw/sw_rbsp.c | 2 - libs/video/renderer/sw/sw_rdraw.c | 2 - libs/video/renderer/sw/sw_riqm.c | 2 - libs/video/renderer/sw/sw_rmain.c | 2 - libs/video/renderer/sw/sw_rsprite.c | 2 - libs/video/renderer/vid_common.c | 2 +- libs/video/renderer/vulkan/vulkan_alias.c | 2 - libs/video/renderer/vulkan/vulkan_bsp.c | 2 - libs/video/renderer/vulkan/vulkan_iqm.c | 2 - libs/video/renderer/vulkan/vulkan_main.c | 2 - libs/video/renderer/vulkan/vulkan_scene.c | 2 - libs/video/renderer/vulkan/vulkan_sprite.c | 2 - .../video/renderer/vulkan/vulkan_vid_common.c | 2 - nq/include/client.h | 1 - nq/source/Makemodule.am | 1 + qw/source/Makemodule.am | 1 + qw/source/cl_entparse.c | 2 - qw/source/cl_ents.c | 6 +-- qw/source/cl_main.c | 2 - ruamoko/qwaq/Makemodule.am | 1 + 56 files changed, 112 insertions(+), 165 deletions(-) rename include/QF/{scene => ecs}/component.h (96%) rename include/QF/{scene => ecs}/hierarchy.h (82%) create mode 100644 libs/ecs/Makemodule.am rename libs/{scene => ecs}/component.c (99%) rename libs/{scene => ecs}/hierarchy.c (90%) create mode 100644 libs/ecs/test/Makemodule.am rename libs/{scene => ecs}/test/test-components.c (100%) rename libs/{scene => ecs}/test/test-registry.c (100%) diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index fff9fd24c..36ddd9f6f 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -75,6 +75,10 @@ include_qf = \ include/QF/winding.h \ include/QF/zone.h +include_qf_ecs = \ + include/QF/ecs/component.h \ + include/QF/ecs/hierarchy.h + include_qf_gl = \ include/QF/GL/ati.h \ include/QF/GL/defines.h \ @@ -148,7 +152,6 @@ include_qf_progs = \ include_qf_scene = \ include/QF/scene/camera.h \ include/QF/scene/entity.h \ - include/QF/scene/hierarchy.h \ include/QF/scene/light.h \ include/QF/scene/transform.h \ include/QF/scene/scene.h \ @@ -246,6 +249,7 @@ ruamoko_qf_progs_include_HEADERS = @qfac_qfcc_include_qf_progs@ EXTRA_DIST += \ $(include_qf) \ + $(include_qf_ecs) \ $(include_qf_gl) \ $(include_qf_glsl) \ $(include_qf_input) \ diff --git a/include/QF/scene/component.h b/include/QF/ecs/component.h similarity index 96% rename from include/QF/scene/component.h rename to include/QF/ecs/component.h index 827633184..47e5dbf6c 100644 --- a/include/QF/scene/component.h +++ b/include/QF/ecs/component.h @@ -28,13 +28,16 @@ */ -#ifndef __QF_scene_component_h -#define __QF_scene_component_h +#ifndef __QF_ecs_component_h +#define __QF_ecs_component_h #include #include #include "QF/qtypes.h" +#include "QF/progs.h"//FIXME for PR_RESMAP + +#include "QF/ecs/hierarchy.h" /** \defgroup component Entity Component System \ingroup utils @@ -70,6 +73,8 @@ typedef struct ecs_registry_s { const component_t *components; ecs_pool_t *comp_pools; uint32_t num_components; + uint32_t href_comp;//FIXME find a better way + PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way } ecs_registry_t; #define COMPINLINE GNU89INLINE inline @@ -234,4 +239,4 @@ Ent_SetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry, ///@} -#endif//__QF_scene_component_h +#endif//__QF_ecs_component_h diff --git a/include/QF/scene/hierarchy.h b/include/QF/ecs/hierarchy.h similarity index 82% rename from include/QF/scene/hierarchy.h rename to include/QF/ecs/hierarchy.h index 54dd950e9..2dcde3306 100644 --- a/include/QF/scene/hierarchy.h +++ b/include/QF/ecs/hierarchy.h @@ -28,14 +28,10 @@ */ -#ifndef __QF_scene_hierarchy_h -#define __QF_scene_hierarchy_h +#ifndef __QF_ecs_hierarchy_h +#define __QF_ecs_hierarchy_h -#include "QF/darray.h" #include "QF/qtypes.h" -#include "QF/scene/types.h" -#include "QF/simd/vec4f.h" -#include "QF/simd/mat4f.h" /** \defgroup entity Hierarchy management \ingroup utils @@ -55,9 +51,7 @@ typedef struct hierref_s { } hierref_t; typedef struct hierarchy_s { - struct hierarchy_s *next; - struct hierarchy_s **prev; - struct scene_s *scene; + struct ecs_registry_s *reg; uint32_t num_objects; uint32_t max_objects; uint32_t *ent; @@ -68,10 +62,11 @@ typedef struct hierarchy_s { void **components; } hierarchy_t; -hierarchy_t *Hierarchy_New (struct scene_s *scene, +hierarchy_t *Hierarchy_New (struct ecs_registry_s *reg, const hierarchy_type_t *type, int createRoot); void Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count); -hierarchy_t *Hierarchy_Copy (struct scene_s *scene, const hierarchy_t *src); +hierarchy_t *Hierarchy_Copy (struct ecs_registry_s *reg, + const hierarchy_t *src); void Hierarchy_Delete (hierarchy_t *hierarchy); uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, @@ -79,4 +74,4 @@ uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); ///@} -#endif//__QF_scene_hierarchy_h +#endif//__QF_ecs_hierarchy_h diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index 6c7c059aa..ca71392d3 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -33,8 +33,9 @@ #include "QF/darray.h" #include "QF/qtypes.h" -#include "QF/scene/component.h" -#include "QF/scene/hierarchy.h" +#include "QF/ecs/component.h" +#include "QF/ecs/hierarchy.h" +#include "QF/ecs/hierarchy.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" @@ -71,17 +72,16 @@ typedef struct transform_s { XFORMINLINE int Transform_Valid (transform_t transform); -transform_t Transform_New (struct scene_s *scene, transform_t parent); +transform_t Transform_New (ecs_registry_t *reg, transform_t parent); /* Deletes all child transforms, and transform names */ -void Transform_Delete (struct scene_s *scene, transform_t transform); -transform_t Transform_NewNamed (struct scene_s *scene, transform_t parent, +void Transform_Delete (transform_t transform); +transform_t Transform_NewNamed (ecs_registry_t *reg, transform_t parent, const char *name); XFORMINLINE hierref_t *Transform_GetRef (transform_t transform); XFORMINLINE uint32_t Transform_ChildCount (transform_t transform); XFORMINLINE transform_t Transform_GetChild (transform_t transform, uint32_t childIndex); -void Transform_SetParent (struct scene_s *scene, - transform_t transform, transform_t parent); +void Transform_SetParent (transform_t transform, transform_t parent); XFORMINLINE transform_t Transform_GetParent (transform_t transform); void Transform_SetName (transform_t transform, const char *name); XFORMINLINE const char *Transform_GetName (transform_t transform); diff --git a/include/scn_internal.h b/include/scn_internal.h index e60d9d2a9..102ad794b 100644 --- a/include/scn_internal.h +++ b/include/scn_internal.h @@ -1,14 +1,9 @@ #ifndef __scn_internal_h #define __scn_internal_h -#include "QF/progs.h" -#include "QF/scene/entity.h" -#include "QF/scene/hierarchy.h" -#include "QF/scene/scene.h" -#include "QF/scene/transform.h" +#include "QF/ecs/hierarchy.h" typedef struct scene_resources_s { - PR_RESMAP (hierarchy_t) hierarchies; } scene_resources_t; #endif//__scn_internal_h diff --git a/libs/Makemodule.am b/libs/Makemodule.am index 4dcdc3b36..92eda626e 100644 --- a/libs/Makemodule.am +++ b/libs/Makemodule.am @@ -1,4 +1,5 @@ include libs/util/Makemodule.am +include libs/ecs/Makemodule.am include libs/ui/Makemodule.am include libs/gamecode/Makemodule.am include libs/ruamoko/Makemodule.am diff --git a/libs/client/cl_effects.c b/libs/client/cl_effects.c index 5b352c139..982d381fb 100644 --- a/libs/client/cl_effects.c +++ b/libs/client/cl_effects.c @@ -41,7 +41,6 @@ #include "QF/render.h" #include "QF/plugin/vid_render.h" //FIXME -#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" diff --git a/libs/client/cl_entities.c b/libs/client/cl_entities.c index 12a56a96d..324c1e66d 100644 --- a/libs/client/cl_entities.c +++ b/libs/client/cl_entities.c @@ -39,7 +39,6 @@ #include "QF/plugin/vid_render.h" //FIXME -#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 47e125509..aa25e33ba 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -46,7 +46,6 @@ #include "QF/plugin/vid_render.h" //FIXME // -#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index 4233d8cd7..b64da5cf3 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -34,7 +34,6 @@ #include "QF/screen.h" #include "QF/plugin/vid_render.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" #include "QF/simd/vec4f.h" @@ -961,7 +960,8 @@ V_Init (viewstate_t *viewstate) "Used when you are underwater, hit, have the Ring of " "Shadows, or Quad Damage. (v_cshift r g b intensity)"); - viewstate->camera_transform = Transform_New (cl_world.scene, nulltransform); + viewstate->camera_transform = Transform_New (cl_world.scene->reg, + nulltransform); } void diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index 6c0595515..a6c245aa4 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -46,7 +46,6 @@ #include "QF/progs.h" #include "QF/msg.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/light.h" #include "QF/scene/scene.h" diff --git a/libs/ecs/Makemodule.am b/libs/ecs/Makemodule.am new file mode 100644 index 000000000..b624d2062 --- /dev/null +++ b/libs/ecs/Makemodule.am @@ -0,0 +1,12 @@ +include libs/ecs/test/Makemodule.am + +ecs_deps=libs/models/libQFmodels.la libs/util/libQFutil.la + +lib_LTLIBRARIES += libs/ecs/libQFecs.la + +libs_ecs_libQFecs_la_LDFLAGS= $(lib_ldflags) +libs_ecs_libQFecs_la_LIBADD= $(ecs_deps) +libs_ecs_libQFecs_la_DEPENDENCIES= $(ecs_deps) +libs_ecs_libQFecs_la_SOURCES= \ + libs/ecs/component.c \ + libs/ecs/hierarchy.c diff --git a/libs/scene/component.c b/libs/ecs/component.c similarity index 99% rename from libs/scene/component.c rename to libs/ecs/component.c index 246872078..e842daaee 100644 --- a/libs/scene/component.c +++ b/libs/ecs/component.c @@ -31,7 +31,7 @@ #include "QF/sys.h" #define IMPLEMENT_COMPONENT_Funcs -#include "QF/scene/component.h" +#include "QF/ecs/component.h" VISIBLE ecs_registry_t * ECS_NewRegistry (void) diff --git a/libs/scene/hierarchy.c b/libs/ecs/hierarchy.c similarity index 90% rename from libs/scene/hierarchy.c rename to libs/ecs/hierarchy.c index f5e62f07c..cbea9aaf9 100644 --- a/libs/scene/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -35,11 +35,10 @@ # include #endif -#include "QF/scene/component.h" -#include "QF/scene/hierarchy.h" -#include "QF/scene/transform.h" +#include "QF/sys.h" -#include "scn_internal.h" +#include "QF/ecs/component.h" +#include "QF/ecs/hierarchy.h" static component_t ent_component = { .size = sizeof (uint32_t) }; static component_t childCount_component = { .size = sizeof (uint32_t) }; @@ -50,9 +49,10 @@ static void hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { - ecs_registry_t *reg = hierarchy->scene->reg; + ecs_registry_t *reg = hierarchy->reg; + uint32_t href = reg->href_comp; for (size_t i = start; i < hierarchy->num_objects; i++) { - hierref_t *ref = Ent_GetComponent (hierarchy->ent[i], scene_href, reg); + hierref_t *ref = Ent_GetComponent (hierarchy->ent[i], href, reg); ref->index += offset; } } @@ -151,7 +151,8 @@ static void hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstIndex, uint32_t srcIndex, uint32_t count) { - ecs_registry_t *reg = dst->scene->reg; + ecs_registry_t *reg = dst->reg; + uint32_t href = reg->href_comp; Component_CopyElements (&ent_component, dst->ent, dstIndex, src->ent, srcIndex, count); @@ -162,7 +163,7 @@ hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, for (uint32_t i = 0; i < count; i++) { uint32_t ent = dst->ent[dstIndex + i]; - hierref_t *ref = Ent_GetComponent (ent, scene_href, reg); + hierref_t *ref = Ent_GetComponent (ent, href, reg); ref->hierarchy = dst; ref->index = dstIndex + i; } @@ -333,18 +334,11 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) } hierarchy_t * -Hierarchy_New (scene_t *scene, const hierarchy_type_t *type, int createRoot) +Hierarchy_New (ecs_registry_t *reg, const hierarchy_type_t *type, + int createRoot) { - scene_resources_t *res = scene->resources; - hierarchy_t *hierarchy = PR_RESNEW (res->hierarchies); - hierarchy->scene = scene; - - hierarchy->prev = &scene->hierarchies; - hierarchy->next = scene->hierarchies; - if (scene->hierarchies) { - scene->hierarchies->prev = &hierarchy->next; - } - scene->hierarchies = hierarchy; + hierarchy_t *hierarchy = PR_RESNEW (reg->hierarchies); + hierarchy->reg = reg; hierarchy->type = type; hierarchy->components = calloc (hierarchy->type->num_components, @@ -361,11 +355,6 @@ Hierarchy_New (scene_t *scene, const hierarchy_type_t *type, int createRoot) void Hierarchy_Delete (hierarchy_t *hierarchy) { - if (hierarchy->next) { - hierarchy->next->prev = hierarchy->prev; - } - *hierarchy->prev = hierarchy->next; - free (hierarchy->ent); free (hierarchy->childCount); free (hierarchy->childIndex); @@ -375,23 +364,23 @@ Hierarchy_Delete (hierarchy_t *hierarchy) } free (hierarchy->components); - scene_resources_t *res = hierarchy->scene->resources; - PR_RESFREE (res->hierarchies, hierarchy); + ecs_registry_t *reg = hierarchy->reg; + PR_RESFREE (reg->hierarchies, hierarchy); } hierarchy_t * -Hierarchy_Copy (scene_t *scene, const hierarchy_t *src) +Hierarchy_Copy (ecs_registry_t *dstReg, const hierarchy_t *src) { - ecs_registry_t *dstReg = scene->reg; - //ecs_registry_t *srcReg = src->scene->reg; - hierarchy_t *dst = Hierarchy_New (scene, src->type, 0); + uint32_t href = dstReg->href_comp; + //ecs_registry_t *srcReg = src->reg; + hierarchy_t *dst = Hierarchy_New (dstReg, src->type, 0); size_t count = src->num_objects; Hierarchy_Reserve (dst, count); for (size_t i = 0; i < count; i++) { dst->ent[i] = ECS_NewEntity (dstReg); - hierref_t *ref = Ent_AddComponent (dst->ent[i], scene_href, dstReg); + hierref_t *ref = Ent_AddComponent (dst->ent[i], href, dstReg); ref->hierarchy = dst; ref->index = i; } diff --git a/libs/ecs/test/Makemodule.am b/libs/ecs/test/Makemodule.am new file mode 100644 index 000000000..6c3e6bd8f --- /dev/null +++ b/libs/ecs/test/Makemodule.am @@ -0,0 +1,25 @@ +libs_ecs_tests = \ + libs/ecs/test/test-components \ + libs/ecs/test/test-registry + +TESTS += $(libs_ecs_tests) + +check_PROGRAMS += $(libs_ecs_tests) + +libs_ecs_test_libs= \ + libs/ecs/libQFecs.la \ + libs/util/libQFutil.la + +libs_ecs_test_test_components_SOURCES= \ + libs/ecs/test/test-components.c +libs_ecs_test_test_components_LDADD= \ + $(libs_ecs_test_libs) +libs_ecs_test_test_components_DEPENDENCIES= \ + $(libs_ecs_test_libs) + +libs_ecs_test_test_registry_SOURCES= \ + libs/ecs/test/test-registry.c +libs_ecs_test_test_registry_LDADD= \ + $(libs_ecs_test_libs) +libs_ecs_test_test_registry_DEPENDENCIES= \ + $(libs_ecs_test_libs) diff --git a/libs/scene/test/test-components.c b/libs/ecs/test/test-components.c similarity index 100% rename from libs/scene/test/test-components.c rename to libs/ecs/test/test-components.c diff --git a/libs/scene/test/test-registry.c b/libs/ecs/test/test-registry.c similarity index 100% rename from libs/scene/test/test-registry.c rename to libs/ecs/test/test-registry.c diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 09d81bcce..a7de142b3 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -44,7 +44,6 @@ #include "QF/plugin/vid_render.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/light.h" #include "QF/scene/scene.h" @@ -333,9 +332,8 @@ bi_Transform_SetParent (progs_t *pr, void *_res) rua_scene_resources_t *res = _res; transform_t transform = rua_transform_get (res, P_ULONG (pr, 0)); transform_t parent = rua_transform_get (res, P_ULONG (pr, 1)); - rua_scene_t *scene = rua_scene_get (res, P_ULONG (pr, 1)); - Transform_SetParent (scene->scene, transform, parent); + Transform_SetParent (transform, parent); } static void diff --git a/libs/scene/Makemodule.am b/libs/scene/Makemodule.am index b1778c200..4dffff068 100644 --- a/libs/scene/Makemodule.am +++ b/libs/scene/Makemodule.am @@ -1,6 +1,9 @@ include libs/scene/test/Makemodule.am -scene_deps=libs/models/libQFmodels.la libs/util/libQFutil.la +scene_deps=\ + libs/models/libQFmodels.la \ + libs/ecs/libQFecs.la \ + libs/util/libQFutil.la lib_LTLIBRARIES += libs/scene/libQFscene.la @@ -9,9 +12,7 @@ libs_scene_libQFscene_la_LIBADD= $(scene_deps) libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps) libs_scene_libQFscene_la_SOURCES= \ libs/scene/camera.c \ - libs/scene/component.c \ libs/scene/entity.c \ - libs/scene/hierarchy.c \ libs/scene/light.c \ libs/scene/scene.c \ libs/scene/transform.c diff --git a/libs/scene/camera.c b/libs/scene/camera.c index adc2c787b..327bea646 100644 --- a/libs/scene/camera.c +++ b/libs/scene/camera.c @@ -32,7 +32,6 @@ #endif #include "QF/scene/camera.h" -#include "QF/scene/component.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 4f1a0b22a..3dabbe941 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -39,7 +39,6 @@ #include "QF/sys.h" #include "QF/model.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" @@ -192,6 +191,7 @@ Scene_NewScene (void) scene->reg = ECS_NewRegistry (); ECS_RegisterComponents (scene->reg, scene_components, scene_num_components); + scene->reg->href_comp = scene_href; scene_resources_t *res = calloc (1, sizeof (scene_resources_t)); *(scene_resources_t **)&scene->resources = res; @@ -215,7 +215,7 @@ Scene_CreateEntity (scene_t *scene) { // Transform_New creates an entity and adds a scene_href component to the // entity - transform_t trans = Transform_New (scene, nulltransform); + transform_t trans = Transform_New (scene->reg, nulltransform); uint32_t id = trans.id; Ent_SetComponent (id, scene_animation, scene->reg, 0); diff --git a/libs/scene/test/Makemodule.am b/libs/scene/test/Makemodule.am index b9ee3dd9d..4f5e71533 100644 --- a/libs/scene/test/Makemodule.am +++ b/libs/scene/test/Makemodule.am @@ -1,7 +1,5 @@ libs_scene_tests = \ - libs/scene/test/test-components \ - libs/scene/test/test-hierarchy \ - libs/scene/test/test-registry + libs/scene/test/test-hierarchy TESTS += $(libs_scene_tests) @@ -9,25 +7,12 @@ check_PROGRAMS += $(libs_scene_tests) libs_scene_test_libs= \ libs/scene/libQFscene.la \ + libs/ecs/libQFecs.la \ libs/util/libQFutil.la -libs_scene_test_test_components_SOURCES= \ - libs/scene/test/test-components.c -libs_scene_test_test_components_LDADD= \ - $(libs_scene_test_libs) -libs_scene_test_test_components_DEPENDENCIES= \ - $(libs_scene_test_libs) - libs_scene_test_test_hierarchy_SOURCES= \ libs/scene/test/test-hierarchy.c libs_scene_test_test_hierarchy_LDADD= \ $(libs_scene_test_libs) libs_scene_test_test_hierarchy_DEPENDENCIES= \ $(libs_scene_test_libs) - -libs_scene_test_test_registry_SOURCES= \ - libs/scene/test/test-registry.c -libs_scene_test_test_registry_LDADD= \ - $(libs_scene_test_libs) -libs_scene_test_test_registry_DEPENDENCIES= \ - $(libs_scene_test_libs) diff --git a/libs/scene/transform.c b/libs/scene/transform.c index cb38a1967..b6ab7b2f6 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -37,8 +37,6 @@ #define IMPLEMENT_TRANSFORM_Funcs -#include "QF/scene/component.h" -#include "QF/scene/hierarchy.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" @@ -221,9 +219,8 @@ Transform_UpdateMatrices (hierarchy_t *h) } transform_t -Transform_New (scene_t *scene, transform_t parent) +Transform_New (ecs_registry_t *reg, transform_t parent) { - ecs_registry_t *reg = scene->reg; uint32_t transform = ECS_NewEntity (reg); hierref_t *ref = Ent_AddComponent (transform, scene_href, reg); @@ -233,7 +230,7 @@ Transform_New (scene_t *scene, transform_t parent) ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, 0, pref->index, 0); } else { - ref->hierarchy = Hierarchy_New (scene, &transform_type, 1); + ref->hierarchy = Hierarchy_New (reg, &transform_type, 1); ref->index = 0; } ref->hierarchy->ent[ref->index] = transform; @@ -242,29 +239,28 @@ Transform_New (scene_t *scene, transform_t parent) } void -Transform_Delete (scene_t *scene, transform_t transform) +Transform_Delete (transform_t transform) { hierref_t *ref = Transform_GetRef (transform); if (ref->index != 0) { // The transform is not the root, so pull it out of its current // hierarchy so deleting it is easier - Transform_SetParent (scene, transform, (transform_t) {}); + Transform_SetParent (transform, (transform_t) {}); } // Takes care of freeing the transforms Hierarchy_Delete (ref->hierarchy); } transform_t -Transform_NewNamed (scene_t *scene, transform_t parent, const char *name) +Transform_NewNamed (ecs_registry_t *reg, transform_t parent, const char *name) { - transform_t transform = Transform_New (scene, parent); + transform_t transform = Transform_New (reg, parent); Transform_SetName (transform, name); return transform; } void -Transform_SetParent (scene_t *scene, transform_t transform, - transform_t parent) +Transform_SetParent (transform_t transform, transform_t parent) { if (parent.reg && parent.id != nullent) { __auto_type ref = Transform_GetRef (transform); @@ -286,7 +282,7 @@ Transform_SetParent (scene_t *scene, transform_t transform, // already root return; } - ref->hierarchy = Hierarchy_New (scene, &transform_type, 0); + ref->hierarchy = Hierarchy_New (transform.reg, &transform_type, 0); Hierarchy_InsertHierarchy (ref->hierarchy, tref.hierarchy, nullent, tref.index); Hierarchy_RemoveHierarchy (tref.hierarchy, tref.index); diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 79f5de3c6..266140346 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -41,9 +41,7 @@ #include "QF/skin.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" diff --git a/libs/video/renderer/gl/gl_mod_iqm.c b/libs/video/renderer/gl/gl_mod_iqm.c index 0052fa977..f842f2f8a 100644 --- a/libs/video/renderer/gl/gl_mod_iqm.c +++ b/libs/video/renderer/gl/gl_mod_iqm.c @@ -49,9 +49,7 @@ #include "QF/GL/qf_iqm.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_vid.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "r_internal.h" diff --git a/libs/video/renderer/gl/gl_mod_sprite.c b/libs/video/renderer/gl/gl_mod_sprite.c index 62c955136..d0fc5b138 100644 --- a/libs/video/renderer/gl/gl_mod_sprite.c +++ b/libs/video/renderer/gl/gl_mod_sprite.c @@ -39,9 +39,7 @@ #include "QF/render.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index a1e1bff3a..315eb9af8 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -39,9 +39,7 @@ #include #include -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 5d199d214..242c74d77 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -45,9 +45,7 @@ #include "QF/render.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/GL/defines.h" #include "QF/GL/funcs.h" diff --git a/libs/video/renderer/glsl/glsl_alias.c b/libs/video/renderer/glsl/glsl_alias.c index 82b9ee216..002d78b17 100644 --- a/libs/video/renderer/glsl/glsl_alias.c +++ b/libs/video/renderer/glsl/glsl_alias.c @@ -44,9 +44,7 @@ #include "QF/skin.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 6215498f7..e6aaf5ed5 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -48,9 +48,7 @@ #include "QF/sys.h" #include "QF/va.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" diff --git a/libs/video/renderer/glsl/glsl_iqm.c b/libs/video/renderer/glsl/glsl_iqm.c index e962c51a7..44b0ccbf9 100644 --- a/libs/video/renderer/glsl/glsl_iqm.c +++ b/libs/video/renderer/glsl/glsl_iqm.c @@ -44,9 +44,7 @@ #include "QF/skin.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 7f71bca33..0ce686ef2 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -45,9 +45,7 @@ #include "QF/screen.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" diff --git a/libs/video/renderer/glsl/glsl_sprite.c b/libs/video/renderer/glsl/glsl_sprite.c index 6a5095737..6ea37b01a 100644 --- a/libs/video/renderer/glsl/glsl_sprite.c +++ b/libs/video/renderer/glsl/glsl_sprite.c @@ -45,9 +45,7 @@ #include "QF/sys.h" #include "QF/vid.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/GLSL/defines.h" #include "QF/GLSL/funcs.h" diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 401349419..ea64dbfc4 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -31,9 +31,7 @@ #include "QF/cvar.h" #include "QF/render.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "d_local.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 2c7b327b3..2a867605f 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -33,9 +33,7 @@ #include "QF/qargs.h" #include "QF/render.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "compat.h" #include "d_local.h" diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index df99a1fe2..86e13dd7b 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -36,9 +36,7 @@ #include "QF/skin.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "d_ifacea.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 7e8a7e69a..a9a42a6c3 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -36,9 +36,7 @@ #include "QF/render.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index bc5cb4670..fc2ad1f7e 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -29,9 +29,7 @@ #endif #include "QF/render.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/sw_riqm.c b/libs/video/renderer/sw/sw_riqm.c index 2277a4983..8ae3107b2 100644 --- a/libs/video/renderer/sw/sw_riqm.c +++ b/libs/video/renderer/sw/sw_riqm.c @@ -45,9 +45,7 @@ #include "QF/skin.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "d_ifacea.h" #include "r_internal.h" diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 6fc5069ba..31d33f071 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -42,9 +42,7 @@ #include "QF/cmd.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "compat.h" #include "mod_internal.h" diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index 987eccfc2..2cea869b2 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -40,9 +40,7 @@ #include "QF/render.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "r_internal.h" diff --git a/libs/video/renderer/vid_common.c b/libs/video/renderer/vid_common.c index 40707b60a..189c25cc6 100644 --- a/libs/video/renderer/vid_common.c +++ b/libs/video/renderer/vid_common.c @@ -31,7 +31,7 @@ #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" -#include "QF/scene/component.h" +#include "QF/scene/entity.h" #include "QF/ui/view.h" diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index e2c8371fc..0a5a7ce44 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -38,9 +38,7 @@ #include "QF/cvar.h" #include "QF/va.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_matrices.h" diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 499574a09..3158bdbc1 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -52,9 +52,7 @@ #include "QF/va.h" #include "QF/math/bitop.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index e85aabf8e..ef58255aa 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -37,9 +37,7 @@ #include "QF/iqm.h" #include "QF/va.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_matrices.h" diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 035910678..c8eb00e89 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -45,9 +45,7 @@ #include "QF/screen.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" diff --git a/libs/video/renderer/vulkan/vulkan_scene.c b/libs/video/renderer/vulkan/vulkan_scene.c index 0e31fd49a..0fb6cf3a9 100644 --- a/libs/video/renderer/vulkan/vulkan_scene.c +++ b/libs/video/renderer/vulkan/vulkan_scene.c @@ -37,9 +37,7 @@ #include "QF/set.h" #include "QF/va.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/debug.h" diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 07c2a3d16..aadf48768 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -51,9 +51,7 @@ #include "QF/sys.h" #include "QF/va.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_renderpass.h" diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a893c64ce..e3e2610ea 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -42,9 +42,7 @@ #include "QF/heapsort.h" #include "QF/plist.h" #include "QF/va.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" diff --git a/nq/include/client.h b/nq/include/client.h index 2a654da98..42a522aba 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -35,7 +35,6 @@ #include "QF/quakefs.h" #include "QF/render.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" #include "client/chase.h" diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 85ed5939a..9fac07a69 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -63,6 +63,7 @@ nq_common_LIBFILES= \ libs/ruamoko/libQFruamoko.la \ libs/gamecode/libQFgamecode.la \ libs/ui/libQFui.la \ + libs/ecs/libQFecs.la \ libs/util/libQFutil.la nq_client_LIBS= $(nq_client_LIBFILES) $(nq_common_LIBFILES) diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 145c4a540..afc5ff385 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -98,6 +98,7 @@ qw_client_LIBS= \ libs/ruamoko/libQFruamoko.la \ libs/ui/libQFui.la \ libs/input/libQFinput.la \ + libs/ecs/libQFecs.la \ libs/util/libQFutil.la qw_client_libs= qw/source/libqw_client.a qw/source/libqw_common.a \ libs/client/libQFclient.la diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 4bf5bf4cd..ad84c77f8 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -41,9 +41,7 @@ #include "QF/skin.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "compat.h" diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 58af6e757..ef8eb3ec6 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -41,9 +41,7 @@ #include "QF/skin.h" #include "QF/sys.h" -#include "QF/scene/component.h" #include "QF/scene/entity.h" -#include "QF/scene/scene.h" #include "compat.h" @@ -369,7 +367,7 @@ CL_AddFlagModels (entity_t ent, int team, int key) transform_t ftransform = Entity_Transform (fent); transform_t transform = Entity_Transform (ent); if (!Transform_Valid (Transform_GetParent (ftransform))) { - Transform_SetParent (cl_world.scene, ftransform, transform); + Transform_SetParent (ftransform, transform); } CL_UpdateFlagModels (ent, key); @@ -391,7 +389,7 @@ CL_RemoveFlagModels (int key) cl_world.scene->reg); transform_t transform = Entity_Transform (fent); *active = 0; - Transform_SetParent (cl_world.scene, transform, nulltransform); + Transform_SetParent (transform, nulltransform); } /* diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index a5f485b0f..1a8601205 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -91,9 +91,7 @@ #include "QF/gib.h" #include "QF/plugin/console.h" -#include "QF/scene/component.h" #include "QF/scene/transform.h" -#include "QF/scene/scene.h" #include "buildnum.h" #include "compat.h" diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 5c32944ff..5b844ece2 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -100,6 +100,7 @@ qwaq_client_libs= \ $(top_builddir)/libs/scene/libQFscene.la \ $(top_builddir)/libs/console/libQFconsole.la \ $(top_builddir)/libs/ui/libQFui.la \ + $(top_builddir)/libs/ecs/libQFecs.la \ $(top_builddir)/libs/input/libQFinput.la \ $(top_builddir)/libs/audio/libQFcd.la \ $(top_builddir)/libs/audio/libQFsound.la \ From 600a34220012204ab99c6ba5b2916b0615760e78 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 26 Oct 2022 17:45:45 +0900 Subject: [PATCH 3099/3664] [ruamoko] Fix missing entity registry pointer --- libs/ruamoko/rua_scene.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index a7de142b3..210e19be5 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -120,6 +120,7 @@ rua__entity_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name) if (scene) { pr_int_t entity_id = id >> 32; ent.id = entity_id; + ent.reg = scene->scene->reg; } if (!Entity_Valid (ent)) { From 5d19936387ede9e927a4fe3d508db6c68f6a1d1d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 00:22:15 +0900 Subject: [PATCH 3100/3664] [gl,sw] Don't clear world's efrags on new scene It seems this isn't needed any more (not sure why) as both glsl and vulkan are happy without it. Also unsure why moving to ECS made gl and sw change behavior regarding rendering the test models in my scene. --- libs/video/renderer/gl/gl_rmisc.c | 4 ---- libs/video/renderer/sw/sw_rmain.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index c2baac427..4c7a02e8e 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -168,10 +168,6 @@ gl_R_NewScene (scene_t *scene) r_refdef.worldmodel = scene->worldmodel; brush = &scene->worldmodel->brush; - // clear out efrags in case the level hasn't been reloaded - for (unsigned i = 0; i < brush->modleafs; i++) - brush->leafs[i].efrags = NULL; - // Force a vis update R_MarkLeaves (0, 0, 0, 0); diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 31d33f071..5f5f5d040 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -200,10 +200,6 @@ R_NewScene (scene_t *scene) r_refdef.registry = scene->reg; r_refdef.worldmodel = worldmodel; - // clear out efrags in case the level hasn't been reloaded - for (unsigned i = 0; i < brush->modleafs; i++) - brush->leafs[i].efrags = NULL; - if (brush->skytexture) R_InitSky (brush->skytexture); From 6952f6860db2ef7cc8497dd4241b7897702be9c4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 11:02:45 +0900 Subject: [PATCH 3101/3664] [vulkan] Use the resource functions for shadow maps Another step towards moving all resource creation into the one place. The motivation for doing the change was getting my test scene to work with only ambient lights or no lights at all. --- include/QF/Vulkan/qf_lighting.h | 2 +- libs/video/renderer/vulkan/vulkan_lighting.c | 128 ++++++++++--------- 2 files changed, 70 insertions(+), 60 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index c0ca5c67c..5abb16e92 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -100,7 +100,7 @@ typedef struct lightingctx_s { VkPipelineLayout layout; VkSampler sampler; VkDeviceMemory light_memory; - VkDeviceMemory shadow_memory; + struct qfv_resource_s *shadow_resources; qfv_lightmatset_t light_mats; qfv_imageset_t light_images; light_renderer_set_t light_renderers; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 927d77728..7b2838ced 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -66,6 +66,7 @@ #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" +#include "QF/Vulkan/resource.h" #include "QF/Vulkan/staging.h" #include "compat.h" @@ -233,7 +234,11 @@ lighting_draw_maps (qfv_renderframe_t *rFrame) sets->size = 0; } - if (!lctx->ldata) { + if (!lctx->ldata || !lctx->ldata->lights.size) { + return; + } + if (!lctx->light_renderers.a[0].renderPass) { + //FIXME goes away when lighting implemented properly return; } @@ -461,17 +466,14 @@ clear_shadows (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; lightingctx_t *lctx = ctx->lighting_context; - if (lctx->shadow_memory) { - dfunc->vkFreeMemory (device->dev, lctx->shadow_memory, 0); - lctx->shadow_memory = 0; - } for (size_t i = 0; i < lctx->light_renderers.size; i++) { __auto_type lr = &lctx->light_renderers.a[i]; dfunc->vkDestroyFramebuffer (device->dev, lr->framebuffer, 0); dfunc->vkDestroyImageView (device->dev, lr->view, 0); } - for (size_t i = 0; i < lctx->light_images.size; i++) { - dfunc->vkDestroyImage (device->dev, lctx->light_images.a[i], 0); + if (lctx->shadow_resources) { + QFV_DestroyResource (device, lctx->shadow_resources); + lctx->shadow_resources = 0; } lctx->light_images.size = 0; lctx->light_renderers.size = 0; @@ -579,35 +581,6 @@ light_compare (const void *_li2, const void *_li1, void *_ldata) return s1 - s2; } -static VkImage -create_map (int size, int layers, int cube, vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - if (layers < 6) { - cube = 0; - } - - VkImageCreateInfo createInfo = { - VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 0, - cube ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, VK_IMAGE_TYPE_2D, - VK_FORMAT_X8_D24_UNORM_PACK32, - { size, size, 1 }, 1, layers, - VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT, VK_SHARING_MODE_EXCLUSIVE, - 0, 0, - VK_IMAGE_LAYOUT_UNDEFINED, - }; - VkImage image; - dfunc->vkCreateImage (device->dev, &createInfo, 0, &image); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, image, - va (ctx->va_ctx, "image:shadowmap:%d:%d", - size, layers)); - return image; -} - static VkImageView create_view (const light_renderer_t *lr, int id, vulkan_ctx_t *ctx) { @@ -679,8 +652,13 @@ create_framebuffer (const light_renderer_t *lr, vulkan_ctx_t *ctx) static void build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) { + typedef struct { + int size; + int layers; + int cube; + } mapdesc_t; + qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; qfv_physdev_t *physDev = device->physDev; int maxLayers = physDev->properties->limits.maxImageArrayLayers; lightingdata_t *ldata = lctx->ldata; @@ -692,6 +670,8 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) int *imageMap = alloca (numLights * sizeof (int)); size_t memsize = 0; int *lightMap = alloca (numLights * sizeof (int)); + int numMaps = 0; + mapdesc_t *maps = alloca (numLights * sizeof (mapdesc_t)); for (int i = 0; i < numLights; i++) { lightMap[i] = i; @@ -728,8 +708,11 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) if (size != abs ((int) lights[li].color[3]) || numLayers + layers > maxLayers) { if (numLayers) { - VkImage shadow_map = create_map (size, numLayers, 1, ctx); - DARRAY_APPEND (&lctx->light_images, shadow_map); + maps[numMaps++] = (mapdesc_t) { + .size = size, + .layers = numLayers, + .cube = 0, + }; numLayers = 0; } size = abs ((int) lights[li].color[3]); @@ -742,8 +725,11 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) totalLayers += layers; } if (numLayers) { - VkImage shadow_map = create_map (size, numLayers, 1, ctx); - DARRAY_APPEND (&lctx->light_images, shadow_map); + maps[numMaps++] = (mapdesc_t) { + .size = size, + .layers = numLayers, + .cube = 0, + }; } numLayers = 0; @@ -757,8 +743,11 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) continue; } if (numLayers + layers > maxLayers) { - VkImage shadow_map = create_map (size, numLayers, 0, ctx); - DARRAY_APPEND (&lctx->light_images, shadow_map); + maps[numMaps++] = (mapdesc_t) { + .size = size, + .layers = numLayers, + .cube = 0, + }; numLayers = 0; } imageMap[li] = lctx->light_images.size; @@ -769,24 +758,45 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) totalLayers += layers; } if (numLayers) { - VkImage shadow_map = create_map (size, numLayers, 0, ctx); - DARRAY_APPEND (&lctx->light_images, shadow_map); + maps[numMaps++] = (mapdesc_t) { + .size = size, + .layers = numLayers, + .cube = 0, + }; } - for (size_t i = 0; i < lctx->light_images.size; i++) { - memsize += QFV_GetImageSize (device, lctx->light_images.a[i]); - } - lctx->shadow_memory = QFV_AllocImageMemory (device, lctx->light_images.a[0], - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - memsize, 0); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - lctx->shadow_memory, "memory:shadowmap"); - - size_t offset = 0; - for (size_t i = 0; i < lctx->light_images.size; i++) { - dfunc->vkBindImageMemory (device->dev, lctx->light_images.a[i], - lctx->shadow_memory, offset); - offset += QFV_GetImageSize (device, lctx->light_images.a[i]); + if (numMaps) { + qfv_resource_t *shad = calloc (1, sizeof (qfv_resource_t) + + numMaps * sizeof (qfv_resobj_t)); + lctx->shadow_resources = shad; + *shad = (qfv_resource_t) { + .name = "shadow", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = numMaps, + .objects = (qfv_resobj_t *) &shad[1], + }; + for (int i = 0; i < numMaps; i++) { + shad->objects[i] = (qfv_resobj_t) { + .name = "map", + .type = qfv_res_image, + .image = { + .cubemap = maps[i].layers < 6 ? 0 : maps[i].cube, + .type = VK_IMAGE_TYPE_2D, + .format = VK_FORMAT_X8_D24_UNORM_PACK32, + .extent = { maps[i].size, maps[i].size, 1 }, + .num_mipmaps = 1, + .num_layers = maps[i].layers, + .samples = VK_SAMPLE_COUNT_1_BIT, + .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT + | VK_IMAGE_USAGE_SAMPLED_BIT, + }, + }; + } + QFV_CreateResource (device, shad); + for (int i = 0; i < numMaps; i++) { + DARRAY_APPEND (&lctx->light_images, shad->objects[i].image.image); + } } for (int i = 0; i < numLights; i++) { From 169c282187209c88f256546d5e53d36010fb938f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 11:11:38 +0900 Subject: [PATCH 3102/3664] [vulkan] "Fix" view model check in rendering loop The check for the entity being the view model was checking only the view model id, which is not sufficient when the view model is invalid by never being set to other than 0s. A better system for dealing with the view model is needed. --- libs/video/renderer/vulkan/vulkan_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index c8eb00e89..d334883a7 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -72,6 +72,8 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame) { if (!r_drawentities) return; + //FIXME need a better way (components? but HasComponent isn't free) + int vmod = Entity_Valid (vr_data.view_model); #define RE_LOOP(type_name, Type) \ do { \ int begun = 0; \ @@ -84,12 +86,12 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame) } \ /* FIXME hack the depth range to prevent view model */\ /* from poking into walls */\ - if (ent.id == vr_data.view_model.id) { \ + if (vmod && ent.id == vr_data.view_model.id) { \ Vulkan_AliasDepthRange (rFrame, 0, 0.3); \ } \ Vulkan_Draw##Type (ent, rFrame); \ /* unhack in case the view_model is not the last */\ - if (ent.id == vr_data.view_model.id) { \ + if (vmod && ent.id == vr_data.view_model.id) { \ Vulkan_AliasDepthRange (rFrame, 0, 1); \ } \ } \ From 1f276223096a667b2e3062e68fd61803e55a5297 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 11:23:49 +0900 Subject: [PATCH 3103/3664] [vulkan] Free shadow map resource block I forgot I had to free the memory too. Oops. --- libs/video/renderer/vulkan/vulkan_lighting.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 7b2838ced..68ce564cf 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -473,6 +473,7 @@ clear_shadows (vulkan_ctx_t *ctx) } if (lctx->shadow_resources) { QFV_DestroyResource (device, lctx->shadow_resources); + free (lctx->shadow_resources); lctx->shadow_resources = 0; } lctx->light_images.size = 0; From fa057cb1214cf1c238eb6dc30f29b25e79fc9388 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 11:32:00 +0900 Subject: [PATCH 3104/3664] [vulkan] Record resource memory size It's useful mainly for information reports, but might be useful elsewhere. --- include/QF/Vulkan/resource.h | 1 + libs/video/renderer/vulkan/resource.c | 1 + libs/video/renderer/vulkan/vulkan_lighting.c | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/resource.h b/include/QF/Vulkan/resource.h index 4cc7c78c5..872b52787 100644 --- a/include/QF/Vulkan/resource.h +++ b/include/QF/Vulkan/resource.h @@ -59,6 +59,7 @@ typedef struct qfv_resource_s { unsigned num_objects; qfv_resobj_t *objects; VkDeviceMemory memory; + VkDeviceSize size; } qfv_resource_t; struct qfv_device_s; diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index 90451e5ef..4d9578ae0 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -129,6 +129,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) } } } + resource->size = size; QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, resource->memory, va (resource->va_ctx, "memory:%s", resource->name)); diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 68ce564cf..a48047524 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -669,7 +669,6 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) int numLayers = 0; int totalLayers = 0; int *imageMap = alloca (numLights * sizeof (int)); - size_t memsize = 0; int *lightMap = alloca (numLights * sizeof (int)); int numMaps = 0; mapdesc_t *maps = alloca (numLights * sizeof (mapdesc_t)); @@ -828,7 +827,8 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) } Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n", - totalLayers, lctx->light_images.size, memsize); + totalLayers, lctx->light_images.size, + lctx->shadow_resources->size); } void From c605e50d52c81b34c0edbc9f740b17cf5e371d36 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 12:53:01 +0900 Subject: [PATCH 3105/3664] [renderer] Check view_model entity is valid It usually is in quake, but my test scene does not have a view model. --- libs/video/renderer/gl/gl_rmain.c | 3 +++ libs/video/renderer/glsl/glsl_main.c | 3 +++ libs/video/renderer/sw/sw_rmain.c | 3 +++ libs/video/renderer/vulkan/vulkan_main.c | 3 +++ 4 files changed, 12 insertions(+) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index 315eb9af8..bfe4129d4 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -160,6 +160,9 @@ static void R_DrawViewModel (void) { entity_t ent = vr_data.view_model; + if (!Entity_Valid (ent)) { + return; + } renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); if (vr_data.inhibit_viewmodel || !r_drawviewmodel diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 0ce686ef2..0df960345 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -116,6 +116,9 @@ static void R_DrawViewModel (void) { entity_t ent = vr_data.view_model; + if (!Entity_Valid (ent)) { + return; + } renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); if (vr_data.inhibit_viewmodel || !r_drawviewmodel diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 5f5f5d040..dadc8c254 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -377,6 +377,9 @@ R_DrawViewModel (void) return; viewent = vr_data.view_model; + if (!Entity_Valid (viewent)) { + return; + } renderer_t *renderer = Ent_GetComponent (viewent.id, scene_renderer, viewent.reg); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index d334883a7..9bcc0dc1e 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -108,6 +108,9 @@ static void Vulkan_DrawViewModel (vulkan_ctx_t *ctx) { entity_t ent = vr_data.view_model; + if (!Entity_Valid (ent)) { + return; + } renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); if (vr_data.inhibit_viewmodel || !r_drawviewmodel From 0a3c7b5b7696f2f9d221d5a695b61166bb4f60ae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 13:26:00 +0900 Subject: [PATCH 3106/3664] [vulkan] Don't use QFV_CreateImage for resource images The resource functions assume the requested layers is correct (really, the lighting code assumes that the resource functions assume such), but QFV_CreateImage multiplies the layer count by 6 for cube maps (really, the issue is in QFV_CreateImage, but I want to move away from it anyway). --- libs/video/renderer/vulkan/resource.c | 30 +++++++++++++++++++-------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index 4d9578ae0..7562c1151 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -37,6 +37,26 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/resource.h" +static void +create_image (qfv_device_t *device, qfv_resobj_t *image_obj) +{ + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type image = &image_obj->image; + VkImageCreateInfo createInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 0, + image->cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, + image->type, image->format, image->extent, image->num_mipmaps, + image->num_layers, + image->samples, + VK_IMAGE_TILING_OPTIMAL, + image->usage, + VK_SHARING_MODE_EXCLUSIVE, + 0, 0, + VK_IMAGE_LAYOUT_UNDEFINED, + }; + dfunc->vkCreateImage (device->dev, &createInfo, 0, &image->image); +} + int QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) { @@ -76,16 +96,8 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) break; case qfv_res_image: { + create_image (device, obj); __auto_type image = &obj->image; - image->image = QFV_CreateImage (device, - image->cubemap, - image->type, - image->format, - image->extent, - image->num_mipmaps, - image->num_layers, - image->samples, - image->usage); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, image->image, va (resource->va_ctx, "image:%s:%s", From d8cdaa72374af4f2cbd3f33a8f0ea6bceb6e2439 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 13:29:14 +0900 Subject: [PATCH 3107/3664] [vulkan] Fix some errors in shadow map setup I had forgotten to test with nq, so I had missed that I'd messed up cube map requests and the image map. This gets nq working again. --- libs/video/renderer/vulkan/vulkan_lighting.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index a48047524..6d39c3586 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -711,13 +711,13 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) maps[numMaps++] = (mapdesc_t) { .size = size, .layers = numLayers, - .cube = 0, + .cube = 1, }; numLayers = 0; } size = abs ((int) lights[li].color[3]); } - imageMap[li] = lctx->light_images.size; + imageMap[li] = numMaps; lr->size = size; lr->layer = numLayers; lr->numLayers = layers; @@ -728,7 +728,7 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) maps[numMaps++] = (mapdesc_t) { .size = size, .layers = numLayers, - .cube = 0, + .cube = 1, }; } @@ -750,7 +750,7 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) }; numLayers = 0; } - imageMap[li] = lctx->light_images.size; + imageMap[li] = numMaps; lr->size = size; lr->layer = numLayers; lr->numLayers = layers; From 52b09e81cd760c299a1be949b43d1b977929ef77 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 15:35:29 +0900 Subject: [PATCH 3108/3664] [ecs,scene] Update tests for move to separate ecs lib And fix an issue spotted in hierarchy.c: incorrect move of objects and lack of check for valid entity when updating hierarchy reference indices. --- libs/ecs/hierarchy.c | 8 ++- libs/ecs/test/test-components.c | 2 +- libs/ecs/test/test-registry.c | 2 +- libs/scene/test/test-hierarchy.c | 117 ++++++++++++++++--------------- 4 files changed, 66 insertions(+), 63 deletions(-) diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index cbea9aaf9..4d8786fe7 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -52,8 +52,10 @@ hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, ecs_registry_t *reg = hierarchy->reg; uint32_t href = reg->href_comp; for (size_t i = start; i < hierarchy->num_objects; i++) { - hierref_t *ref = Ent_GetComponent (hierarchy->ent[i], href, reg); - ref->index += offset; + if (ECS_EntValid (hierarchy->ent[i], reg)) { + hierref_t *ref = Ent_GetComponent (hierarchy->ent[i], href, reg); + ref->index += offset; + } } } @@ -159,7 +161,7 @@ hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, // Actually move (as in C++ move semantics) source hierarchy object // references so that their indices do not get updated when the objects // are removed from the source hierarcy - memset (&src->ent[srcIndex], 0, count * sizeof(dst->ent[0])); + memset (&src->ent[srcIndex], nullent, count * sizeof(dst->ent[0])); for (uint32_t i = 0; i < count; i++) { uint32_t ent = dst->ent[dstIndex + i]; diff --git a/libs/ecs/test/test-components.c b/libs/ecs/test/test-components.c index 354fbab6c..e790aab54 100644 --- a/libs/ecs/test/test-components.c +++ b/libs/ecs/test/test-components.c @@ -8,7 +8,7 @@ #include "QF/simd/types.h" #include "QF/mathlib.h" -#include "QF/scene/component.h" +#include "QF/ecs/component.h" enum test_components { test_position, diff --git a/libs/ecs/test/test-registry.c b/libs/ecs/test/test-registry.c index 2ffff8a92..1739f3a42 100644 --- a/libs/ecs/test/test-registry.c +++ b/libs/ecs/test/test-registry.c @@ -6,7 +6,7 @@ #include #include -#include "QF/scene/component.h" +#include "QF/ecs/component.h" static int test_new_del (void) diff --git a/libs/scene/test/test-hierarchy.c b/libs/scene/test/test-hierarchy.c index 968c83494..026a8394d 100644 --- a/libs/scene/test/test-hierarchy.c +++ b/libs/scene/test/test-hierarchy.c @@ -6,12 +6,12 @@ #include #include -#include "QF/scene/component.h" -#include "QF/scene/hierarchy.h" +#include "QF/ecs/component.h" +#include "QF/ecs/hierarchy.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" -scene_t *scene; +ecs_registry_t *reg; // NOTE: these are the columns of the matrix! (not that it matters for a // symmetrical matrix, but...) @@ -50,7 +50,7 @@ check_hierarchy_size (transform_t t, uint32_t size) return 0; } char **name = h->components[transform_type_name]; - ecs_registry_t *reg = h->scene->reg; + ecs_registry_t *reg = h->reg; for (uint32_t i = 0; i < h->num_objects; i++) { hierref_t *ref = Ent_GetComponent (h->ent[i], scene_href, reg); if (ref->hierarchy != h) { @@ -66,7 +66,7 @@ dump_hierarchy (transform_t t) { hierarchy_t *h = Transform_GetRef (t)->hierarchy; char **name = h->components[transform_type_name]; - ecs_registry_t *reg = h->scene->reg; + ecs_registry_t *reg = h->reg; for (uint32_t i = 0; i < h->num_objects; i++) { hierref_t *ref = Ent_GetComponent (h->ent[i], scene_href, reg); printf ("%2d: %5s %2u %2u %2u %2u %2u\n", i, name[i], h->ent[i], @@ -110,7 +110,7 @@ check_indices (transform_t transform, uint32_t index, uint32_t parentIndex, static int test_single_transform (void) { - transform_t transform = Transform_New (scene, (transform_t) {}); + transform_t transform = Transform_New (reg, (transform_t) {}); hierarchy_t *h; if (!transform.reg || transform.id == nullent) { @@ -157,8 +157,8 @@ test_single_transform (void) static int test_parent_child_init (void) { - transform_t parent = Transform_New (scene, (transform_t) {}); - transform_t child = Transform_New (scene, parent); + transform_t parent = Transform_New (reg, (transform_t) {}); + transform_t child = Transform_New (reg, parent); if (Transform_GetRef (parent)->hierarchy != Transform_GetRef (child)->hierarchy) { @@ -215,8 +215,8 @@ test_parent_child_init (void) static int test_parent_child_setparent (void) { - transform_t parent = Transform_New (scene, (transform_t) {}); - transform_t child = Transform_New (scene, (transform_t) {}); + transform_t parent = Transform_New (reg, (transform_t) {}); + transform_t child = Transform_New (reg, (transform_t) {}); Transform_SetName (parent, "parent"); Transform_SetName (child, "child"); @@ -231,7 +231,7 @@ test_parent_child_setparent (void) return 1; } - Transform_SetParent (scene, child, parent); + Transform_SetParent (child, parent); if (Transform_GetRef (parent)->hierarchy != Transform_GetRef (child)->hierarchy) { @@ -290,17 +290,17 @@ test_build_hierarchy (void) { printf ("test_build_hierarchy\n"); - transform_t root = Transform_NewNamed (scene, (transform_t) {}, "root"); - transform_t A = Transform_NewNamed (scene, root, "A"); - transform_t B = Transform_NewNamed (scene, root, "B"); - transform_t C = Transform_NewNamed (scene, root, "C"); + transform_t root = Transform_NewNamed (reg, (transform_t) {}, "root"); + transform_t A = Transform_NewNamed (reg, root, "A"); + transform_t B = Transform_NewNamed (reg, root, "B"); + transform_t C = Transform_NewNamed (reg, root, "C"); if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices (A, 1, 0, 4, 0)) { return 1; } if (!check_indices (B, 2, 0, 4, 0)) { return 1; } if (!check_indices (C, 3, 0, 4, 0)) { return 1; } - transform_t B1 = Transform_NewNamed (scene, B, "B1"); + transform_t B1 = Transform_NewNamed (reg, B, "B1"); if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 0)) { return 1; } @@ -308,7 +308,7 @@ test_build_hierarchy (void) if (!check_indices ( C, 3, 0, 5, 0)) { return 1; } if (!check_indices (B1, 4, 2, 5, 0)) { return 1; } - transform_t A1 = Transform_NewNamed (scene, A, "A1"); + transform_t A1 = Transform_NewNamed (reg, A, "A1"); if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } if (!check_indices ( A, 1, 0, 4, 1)) { return 1; } @@ -316,11 +316,11 @@ test_build_hierarchy (void) if (!check_indices ( C, 3, 0, 6, 0)) { return 1; } if (!check_indices (A1, 4, 1, 6, 0)) { return 1; } if (!check_indices (B1, 5, 2, 6, 0)) { return 1; } - transform_t A1a = Transform_NewNamed (scene, A1, "A1a"); - transform_t B2 = Transform_NewNamed (scene, B, "B2"); - transform_t A2 = Transform_NewNamed (scene, A, "A2"); - transform_t B3 = Transform_NewNamed (scene, B, "B3"); - transform_t B2a = Transform_NewNamed (scene, B2, "B2a"); + transform_t A1a = Transform_NewNamed (reg, A1, "A1a"); + transform_t B2 = Transform_NewNamed (reg, B, "B2"); + transform_t A2 = Transform_NewNamed (reg, A, "A2"); + transform_t B3 = Transform_NewNamed (reg, B, "B3"); + transform_t B2a = Transform_NewNamed (reg, B2, "B2a"); if (!check_hierarchy_size (root, 11)) { return 1; } @@ -336,7 +336,7 @@ test_build_hierarchy (void) if (!check_indices (A1a, 9, 4, 11, 0)) { return 1; } if (!check_indices (B2a, 10, 7, 11, 0)) { return 1; } - transform_t D = Transform_NewNamed (scene, root, "D"); + transform_t D = Transform_NewNamed (reg, root, "D"); if (!check_hierarchy_size (root, 12)) { return 1; } @@ -354,7 +354,7 @@ test_build_hierarchy (void) if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; } dump_hierarchy (root); - transform_t C1 = Transform_NewNamed (scene, C, "C1"); + transform_t C1 = Transform_NewNamed (reg, C, "C1"); dump_hierarchy (root); if (!check_hierarchy_size (root, 13)) { return 1; } @@ -383,19 +383,19 @@ test_build_hierarchy2 (void) { printf ("test_build_hierarchy2\n"); - transform_t root = Transform_NewNamed (scene, (transform_t) {}, "root"); - transform_t A = Transform_NewNamed (scene, root, "A"); - transform_t B = Transform_NewNamed (scene, root, "B"); - transform_t C = Transform_NewNamed (scene, root, "C"); - transform_t B1 = Transform_NewNamed (scene, B, "B1"); - transform_t A1 = Transform_NewNamed (scene, A, "A1"); - transform_t A1a = Transform_NewNamed (scene, A1, "A1a"); - transform_t B2 = Transform_NewNamed (scene, B, "B2"); - transform_t A2 = Transform_NewNamed (scene, A, "A2"); - transform_t B3 = Transform_NewNamed (scene, B, "B3"); - transform_t B2a = Transform_NewNamed (scene, B2, "B2a"); - transform_t D = Transform_NewNamed (scene, root, "D"); - transform_t C1 = Transform_NewNamed (scene, C, "C1"); + transform_t root = Transform_NewNamed (reg, (transform_t) {}, "root"); + transform_t A = Transform_NewNamed (reg, root, "A"); + transform_t B = Transform_NewNamed (reg, root, "B"); + transform_t C = Transform_NewNamed (reg, root, "C"); + transform_t B1 = Transform_NewNamed (reg, B, "B1"); + transform_t A1 = Transform_NewNamed (reg, A, "A1"); + transform_t A1a = Transform_NewNamed (reg, A1, "A1a"); + transform_t B2 = Transform_NewNamed (reg, B, "B2"); + transform_t A2 = Transform_NewNamed (reg, A, "A2"); + transform_t B3 = Transform_NewNamed (reg, B, "B3"); + transform_t B2a = Transform_NewNamed (reg, B2, "B2a"); + transform_t D = Transform_NewNamed (reg, root, "D"); + transform_t C1 = Transform_NewNamed (reg, C, "C1"); if (!check_hierarchy_size (root, 13)) { return 1; } @@ -413,18 +413,18 @@ test_build_hierarchy2 (void) if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } - transform_t T = Transform_NewNamed (scene, (transform_t) {}, "T"); - transform_t X = Transform_NewNamed (scene, T, "X"); - transform_t Y = Transform_NewNamed (scene, T, "Y"); - transform_t Z = Transform_NewNamed (scene, T, "Z"); - transform_t Y1 = Transform_NewNamed (scene, Y, "Y1"); - transform_t X1 = Transform_NewNamed (scene, X, "X1"); - transform_t X1a = Transform_NewNamed (scene, X1, "X1a"); - transform_t Y2 = Transform_NewNamed (scene, Y, "Y2"); - transform_t X2 = Transform_NewNamed (scene, X, "X2"); - transform_t Y3 = Transform_NewNamed (scene, Y, "Y3"); - transform_t Y2a = Transform_NewNamed (scene, Y2, "Y2a"); - transform_t Z1 = Transform_NewNamed (scene, Z, "Z1"); + transform_t T = Transform_NewNamed (reg, (transform_t) {}, "T"); + transform_t X = Transform_NewNamed (reg, T, "X"); + transform_t Y = Transform_NewNamed (reg, T, "Y"); + transform_t Z = Transform_NewNamed (reg, T, "Z"); + transform_t Y1 = Transform_NewNamed (reg, Y, "Y1"); + transform_t X1 = Transform_NewNamed (reg, X, "X1"); + transform_t X1a = Transform_NewNamed (reg, X1, "X1a"); + transform_t Y2 = Transform_NewNamed (reg, Y, "Y2"); + transform_t X2 = Transform_NewNamed (reg, X, "X2"); + transform_t Y3 = Transform_NewNamed (reg, Y, "Y3"); + transform_t Y2a = Transform_NewNamed (reg, Y2, "Y2a"); + transform_t Z1 = Transform_NewNamed (reg, Z, "Z1"); dump_hierarchy (T); if (!check_hierarchy_size (T, 12)) { return 1; } @@ -442,7 +442,7 @@ test_build_hierarchy2 (void) if (!check_indices (X1a, 10, 4, 12, 0)) { return 1; } if (!check_indices (Y2a, 11, 7, 12, 0)) { return 1; } - Transform_SetParent (scene, T, B); + Transform_SetParent (T, B); dump_hierarchy (root); @@ -474,7 +474,7 @@ test_build_hierarchy2 (void) if (!check_indices (X1a, 23, 17, 25, 0)) { return 1; } if (!check_indices (Y2a, 24, 20, 25, 0)) { return 1; } - Transform_SetParent (scene, Y, (transform_t) {}); + Transform_SetParent (Y, (transform_t) {}); dump_hierarchy (root); dump_hierarchy (Y); @@ -533,11 +533,11 @@ check_vector (transform_t transform, static int test_frames (void) { - transform_t root = Transform_NewNamed (scene, (transform_t) {}, "root"); - transform_t A = Transform_NewNamed (scene, root, "A"); - transform_t B = Transform_NewNamed (scene, root, "B"); - transform_t A1 = Transform_NewNamed (scene, A, "A1"); - transform_t B1 = Transform_NewNamed (scene, B, "B1"); + transform_t root = Transform_NewNamed (reg, (transform_t) {}, "root"); + transform_t A = Transform_NewNamed (reg, root, "A"); + transform_t B = Transform_NewNamed (reg, root, "B"); + transform_t A1 = Transform_NewNamed (reg, A, "A1"); + transform_t B1 = Transform_NewNamed (reg, B, "B1"); Transform_SetLocalPosition (root, (vec4f_t) { 0, 0, 1, 1 }); Transform_SetLocalPosition (A, (vec4f_t) { 1, 0, 0, 1 }); @@ -719,7 +719,7 @@ test_frames (void) return 1; } - Transform_Delete (scene,root); + Transform_Delete (root); return 0; } @@ -727,7 +727,8 @@ test_frames (void) int main (void) { - scene = Scene_NewScene (); + scene_t *scene = Scene_NewScene (); + reg = scene->reg; if (test_single_transform ()) { return 1; } if (test_parent_child_init ()) { return 1; } From 80c0beff89958ea959a22cbafd3a18512ff7731d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 19:46:28 +0900 Subject: [PATCH 3109/3664] [ecs] Support adding null hierarchies to non-root As an implementation detail, inserting null hierarchies (src hierarchy is null) is supported for ease of hierarchy construction from data. No component data is copied, only the child and parent indices and counts are updated. --- libs/ecs/hierarchy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 4d8786fe7..38fd4523b 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -271,7 +271,9 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, Sys_Error ("attempt to insert root in non-empty hierarchy"); } hierarchy_open (dst, 0, 1); - hierarchy_move (dst, src, 0, srcRoot, 1); + if (src) { + hierarchy_move (dst, src, 0, srcRoot, 1); + } dst->parentIndex[0] = nullent; dst->childIndex[0] = 1; dst->childCount[0] = 0; From 45e47a6df03f306a391b3776df1586e8b40c5ec3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 27 Oct 2022 19:47:10 +0900 Subject: [PATCH 3110/3664] [ui] Update passage code to use an ECS hierarchy It's not quite complete in that entities need to be created for the objects, and passage text object might get additional components in the hierarchy, but the direct use of views has been replaced by the use of a hierarchy object with the same tree structure, and now has text objects for paragraphs and the entire passage. --- include/QF/ui/passage.h | 8 +-- libs/ui/passage.c | 112 +++++++++++++++++++----------------- libs/ui/test/Makemodule.am | 4 +- libs/ui/test/test-passage.c | 58 ++++++++++--------- 4 files changed, 96 insertions(+), 86 deletions(-) diff --git a/include/QF/ui/passage.h b/include/QF/ui/passage.h index 76232bd51..52a105cdd 100644 --- a/include/QF/ui/passage.h +++ b/include/QF/ui/passage.h @@ -44,12 +44,12 @@ typedef struct psg_text_s { typedef struct passage_s { const char *text; ///< Not owned by passage - struct view_s *view; ///< hierarchy of views representing passage - psg_text_t *text_objects; ///< all text objects in passage - unsigned num_text_objects; ///< number of text objects in passage + + struct ecs_registry_s *reg; ///< Owning ECS registry + struct hierarchy_s *hierarchy; ///< hierarchy of text objects } passage_t; -passage_t *Passage_ParseText (const char *text); +passage_t *Passage_ParseText (const char *text, struct ecs_registry_s *reg); void Passage_Delete (passage_t *passage); int Passage_IsSpace (const char *text) __attribute__((pure)); diff --git a/libs/ui/passage.c b/libs/ui/passage.c index ea289ad47..8fb0f4c74 100644 --- a/libs/ui/passage.c +++ b/libs/ui/passage.c @@ -39,8 +39,29 @@ #include "QF/qtypes.h" #include "QF/sys.h" -#include "QF/ui/view.h" +#include "QF/ecs/component.h" + #include "QF/ui/passage.h" +#include "QF/ui/view.h" + +enum { + passage_type_text_obj, + + passage_type_count +}; + +static const component_t passage_components[passage_type_count] = { + [passage_type_text_obj] = { + .size = sizeof (psg_text_t), + .name = "Text", + }, +}; + +static const hierarchy_type_t passage_type = { + .num_components = passage_type_count, + .components = passage_components, +}; + VISIBLE int Passage_IsSpace (const char *text) @@ -69,110 +90,100 @@ Passage_IsSpace (const char *text) return 0; } -static void -add_text_view (view_t *paragraph_view, psg_text_t *text_object, int suppress) -{ - view_t *text_view = view_new (0, 0, 0, 0, grav_flow); - text_view->data = text_object; - text_view->bol_suppress = suppress; - view_add (paragraph_view, text_view); -} - VISIBLE passage_t * -Passage_ParseText (const char *text) +Passage_ParseText (const char *text, ecs_registry_t *reg) { passage_t *passage = malloc (sizeof (passage_t)); passage->text = text; - passage->num_text_objects = 0; - passage->view = view_new (0, 0, 10, 10, grav_northwest); - passage->text_objects = 0; + passage->reg = reg; if (!*text) { return passage; } unsigned num_paragraphs = 1; + unsigned num_text_objects = 1; int parsing_space = Passage_IsSpace (text); - passage->num_text_objects = 1; for (const char *c = text; *c; c++) { int size; if ((size = Passage_IsSpace (c))) { if (!parsing_space) { - passage->num_text_objects++; + num_text_objects++; } parsing_space = 1; c += size - 1; } else if (*c == '\n') { if (c[1]) { num_paragraphs++; - passage->num_text_objects += !Passage_IsSpace (c + 1); + num_text_objects += !Passage_IsSpace (c + 1); } } else { if (parsing_space) { - passage->num_text_objects++; + num_text_objects++; } parsing_space = 0; } } + passage->hierarchy = Hierarchy_New (reg, &passage_type, 0); + Hierarchy_Reserve (passage->hierarchy, + 1 + num_paragraphs + num_text_objects); #if 0 printf ("num_paragraphs %d, num_text_objects %d\n", num_paragraphs, passage->num_text_objects); #endif - passage->text_objects = malloc (passage->num_text_objects - * sizeof (psg_text_t)); + Hierarchy_InsertHierarchy (passage->hierarchy, 0, nullent, 0); for (unsigned i = 0; i < num_paragraphs; i++) { - view_t *view = view_new (0, 0, 10, 10, grav_northwest); - view->flow_size = 1; - view_add (passage->view, view); + Hierarchy_InsertHierarchy (passage->hierarchy, 0, 0, 0); } num_paragraphs = 0; + hierarchy_t *h = passage->hierarchy; + psg_text_t *passage_obj = h->components[passage_type_text_obj]; + psg_text_t *par_obj = &passage_obj[h->childIndex[0]]; + psg_text_t *text_obj = &passage_obj[h->childIndex[1]]; + *par_obj = *text_obj = (psg_text_t) { }; + + Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0); + parsing_space = Passage_IsSpace (text); - psg_text_t *text_object = passage->text_objects; - text_object->text = 0; - text_object->size = 0; - view_t *paragraph_view = passage->view->children[num_paragraphs++]; - add_text_view (paragraph_view, text_object, parsing_space); for (const char *c = text; *c; c++) { int size; if ((size = Passage_IsSpace (c))) { if (!parsing_space) { - text_object->size = c - text - text_object->text; - (++text_object)->text = c - text; - add_text_view (paragraph_view, text_object, 1); + Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0); + text_obj->size = c - text - text_obj->text; + (++text_obj)->text = c - text; } parsing_space = 1; c += size - 1; } else if (*c == '\n') { - text_object->size = c - text - text_object->text; + text_obj->size = c - text - text_obj->text; + par_obj->size = c - text - par_obj->text; if (c[1]) { - (++text_object)->text = c + 1 - text; - paragraph_view = passage->view->children[num_paragraphs++]; - add_text_view (paragraph_view, text_object, 0); + (++par_obj)->text = c + 1 - text; + Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0); + (++text_obj)->text = c + 1 - text; parsing_space = Passage_IsSpace (c + 1); } } else { if (parsing_space) { - text_object->size = c - text - text_object->text; - (++text_object)->text = c - text; - add_text_view (paragraph_view, text_object, 0); + Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0); + text_obj->size = c - text - text_obj->text; + (++text_obj)->text = c - text; } parsing_space = 0; if (!c[1]) { - text_object->size = c + 1 - text - text_object->text; + text_obj->size = c + 1 - text - text_obj->text; + par_obj->size = c + 1 - text - par_obj->text; + passage_obj->size = c + 1 - text - passage_obj->text; } } } #if 0 - for (int i = 0; i < passage->view->num_children; i++) { - paragraph_view = passage->view->children[i]; - for (int j = 0; j < paragraph_view->num_children; j++) { - view_t *text_view = paragraph_view->children[j]; - psg_text_t *to = text_view->data; - printf ("%3d %3d %d %4d %4d '%.*s'\n", i, j, - text_view->bol_suppress, - to->text, to->size, to->size, text + to->text); - } + for (uint32_t i = 0; i < passage->hierarchy->num_objects; i++) { + psg_text_t *to = &passage_obj[i]; + printf ("%3d %4d %4d '%.*s'\n", i, + to->text, to->size, to->size, text + to->text); } #endif return passage; @@ -181,9 +192,6 @@ Passage_ParseText (const char *text) VISIBLE void Passage_Delete (passage_t *passage) { - if (passage->view) { - view_delete (passage->view); - } - free (passage->text_objects); + Hierarchy_Delete (passage->hierarchy); free (passage); } diff --git a/libs/ui/test/Makemodule.am b/libs/ui/test/Makemodule.am index 5ac206552..4e9465a20 100644 --- a/libs/ui/test/Makemodule.am +++ b/libs/ui/test/Makemodule.am @@ -18,8 +18,8 @@ libs_ui_test_test_flow_size_LDADD=libs/ui/libQFui.la libs_ui_test_test_flow_size_DEPENDENCIES=libs/ui/libQFui.la libs_ui_test_test_passage_SOURCES=libs/ui/test/test-passage.c -libs_ui_test_test_passage_LDADD=libs/ui/libQFui.la -libs_ui_test_test_passage_DEPENDENCIES=libs/ui/libQFui.la +libs_ui_test_test_passage_LDADD=libs/ui/libQFui.la libs/ecs/libQFecs.la +libs_ui_test_test_passage_DEPENDENCIES=libs/ui/libQFui.la libs/ecs/libQFecs.la libs_ui_test_test_txtbuffer_SOURCES=libs/ui/test/test-txtbuffer.c libs_ui_test_test_txtbuffer_LDADD=libs/ui/libQFui.la diff --git a/libs/ui/test/test-passage.c b/libs/ui/test/test-passage.c index 4b3fddd98..726e247c0 100644 --- a/libs/ui/test/test-passage.c +++ b/libs/ui/test/test-passage.c @@ -5,6 +5,7 @@ #include "QF/ui/view.h" #include "QF/ui/passage.h" +#include "QF/ecs/component.h" static const char test_text[] = { "Guarding the entrance to the Grendal " @@ -49,61 +50,61 @@ int main (void) { int ret = 0; + ecs_registry_t *registry = ECS_NewRegistry (); - passage_t *passage = Passage_ParseText (test_text); - if (passage->view->num_children != 3) { + passage_t *passage = Passage_ParseText (test_text, registry); + if (passage->hierarchy->childCount[0] != 3) { ret = 1; printf ("incorrect number of paragraphs: %d\n", - passage->view->num_children); + passage->hierarchy->childCount[0]); } - if (passage->num_text_objects != 140) { + if (passage->hierarchy->num_objects != 144) { ret = 1; printf ("incorrect number of text objects: %d\n", - passage->num_text_objects); + passage->hierarchy->num_objects); } - if (passage->view->children[0]->num_children != 49) { + if (passage->hierarchy->childCount[1] != 49) { ret = 1; printf ("incorrect number of text objects in first paragraph: %d\n", - passage->view->children[0]->num_children); + passage->hierarchy->childCount[1]); } - if (passage->view->children[1]->num_children != 90) { + if (passage->hierarchy->childCount[2] != 90) { ret = 1; printf ("incorrect number of text objects in second paragraph: %d\n", - passage->view->children[1]->num_children); + passage->hierarchy->childCount[2]); } - if (passage->view->children[2]->num_children != 1) { + if (passage->hierarchy->childCount[3] != 1) { ret = 1; printf ("incorrect number of text objects in third paragraph: %d\n", - passage->view->children[1]->num_children); + passage->hierarchy->childCount[3]); } - view_t *text_view = passage->view->children[1]->children[0]; - psg_text_t *to = text_view->data; + uint32_t *childIndex = passage->hierarchy->childIndex; + psg_text_t *text_objs = passage->hierarchy->components[0]; + psg_text_t *to = &text_objs[childIndex[2] + 0]; if (to->size != 2 && (passage->text[to->text] != ' ' && passage->text[to->text + 1] != ' ')) { ret = 1; printf ("second paragram does not begin with double space: %d '%.*s'\n", to->size, to->size, passage->text + to->text); } - if (text_view->bol_suppress) { - ret = 1; - printf ("second paragram indent suppressed\n"); - } - for (int i = 0; i < passage->view->num_children; i++) { - view_t *paragraph_view = passage->view->children[i]; - for (int j = 0; j < paragraph_view->num_children; j++) { - view_t *text_view = paragraph_view->children[j]; - psg_text_t *to = text_view->data; + //if (text_view->bol_suppress) { + // ret = 1; + // printf ("second paragram indent suppressed\n"); + //} + for (uint32_t i = 0; i < passage->hierarchy->childCount[0]; i++) { + for (uint32_t j = 0; j < passage->hierarchy->childCount[1 + i]; j++) { + psg_text_t *to = &text_objs[childIndex[1 + i] + j]; unsigned is_space = Passage_IsSpace (passage->text + to->text); if (i == 1 && j == 0) { // second paragraph indent, tested above continue; } - if ((!!is_space) != text_view->bol_suppress) { - ret = 1; - printf ("text/suppress mismatch %d [%d '%.*s'] %d %d\n", - text_view->bol_suppress, to->size, to->size, - passage->text + to->text, i, j); - } + //if ((!!is_space) != text_view->bol_suppress) { + // ret = 1; + // printf ("text/suppress mismatch %d [%d '%.*s'] %d %d\n", + // text_view->bol_suppress, to->size, to->size, + // passage->text + to->text, i, j); + //} if (is_space) { if (!check_non_space (passage->text, to)) { continue; @@ -120,5 +121,6 @@ main (void) } Passage_Delete (passage); + ECS_DelRegistry (registry); return ret; } From f6820c59e7f843e0f1f8066175f13a047c76ba9a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Oct 2022 11:39:59 +0900 Subject: [PATCH 3111/3664] [ecs] Initialize registry href_comp to nullent This indicates that no hierarchy reference component has been registered, which must be done by the user when hierarchies are used. --- libs/ecs/component.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/ecs/component.c b/libs/ecs/component.c index e842daaee..896ea70f0 100644 --- a/libs/ecs/component.c +++ b/libs/ecs/component.c @@ -38,6 +38,7 @@ ECS_NewRegistry (void) { ecs_registry_t *reg = calloc (1, sizeof (ecs_registry_t)); reg->next = Ent_Index (nullent); + reg->href_comp = nullent; return reg; } From 9e57d5cb771a2340d8bd43956aaba6e13f00a4f8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Oct 2022 11:43:03 +0900 Subject: [PATCH 3112/3664] [ui] Create entities for passage text objects At least, I think I want to do that :) --- libs/ui/passage.c | 29 ++++++++++++++++++++--------- libs/ui/test/test-passage.c | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/libs/ui/passage.c b/libs/ui/passage.c index 8fb0f4c74..02e96a6dc 100644 --- a/libs/ui/passage.c +++ b/libs/ui/passage.c @@ -62,7 +62,6 @@ static const hierarchy_type_t passage_type = { .components = passage_components, }; - VISIBLE int Passage_IsSpace (const char *text) { @@ -90,6 +89,16 @@ Passage_IsSpace (const char *text) return 0; } +static void +add_entity (hierarchy_t *h, uint32_t parent) +{ + uint32_t i = Hierarchy_InsertHierarchy (h, 0, parent, 0); + h->ent[i] = ECS_NewEntity (h->reg); + hierref_t *ref = Ent_AddComponent (h->ent[i], h->reg->href_comp, h->reg); + ref->hierarchy = h; + ref->index = i; +} + VISIBLE passage_t * Passage_ParseText (const char *text, ecs_registry_t *reg) { @@ -131,9 +140,9 @@ Passage_ParseText (const char *text, ecs_registry_t *reg) printf ("num_paragraphs %d, num_text_objects %d\n", num_paragraphs, passage->num_text_objects); #endif - Hierarchy_InsertHierarchy (passage->hierarchy, 0, nullent, 0); + add_entity (passage->hierarchy, nullent); for (unsigned i = 0; i < num_paragraphs; i++) { - Hierarchy_InsertHierarchy (passage->hierarchy, 0, 0, 0); + add_entity (passage->hierarchy, 0); } num_paragraphs = 0; @@ -143,14 +152,14 @@ Passage_ParseText (const char *text, ecs_registry_t *reg) psg_text_t *text_obj = &passage_obj[h->childIndex[1]]; *par_obj = *text_obj = (psg_text_t) { }; - Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0); + add_entity (passage->hierarchy, par_obj - passage_obj); parsing_space = Passage_IsSpace (text); for (const char *c = text; *c; c++) { int size; if ((size = Passage_IsSpace (c))) { if (!parsing_space) { - Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0); + add_entity (passage->hierarchy, par_obj - passage_obj); text_obj->size = c - text - text_obj->text; (++text_obj)->text = c - text; } @@ -161,13 +170,13 @@ Passage_ParseText (const char *text, ecs_registry_t *reg) par_obj->size = c - text - par_obj->text; if (c[1]) { (++par_obj)->text = c + 1 - text; - Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0); + add_entity (passage->hierarchy, par_obj - passage_obj); (++text_obj)->text = c + 1 - text; parsing_space = Passage_IsSpace (c + 1); } } else { if (parsing_space) { - Hierarchy_InsertHierarchy (h, 0, par_obj - passage_obj, 0); + add_entity (passage->hierarchy, par_obj - passage_obj); text_obj->size = c - text - text_obj->text; (++text_obj)->text = c - text; } @@ -180,9 +189,11 @@ Passage_ParseText (const char *text, ecs_registry_t *reg) } } #if 0 - for (uint32_t i = 0; i < passage->hierarchy->num_objects; i++) { + for (uint32_t i = 0; i < h->num_objects; i++) { psg_text_t *to = &passage_obj[i]; - printf ("%3d %4d %4d '%.*s'\n", i, + uint32_t ent = h->ent[i]; + hierref_t *ref = Ent_GetComponent (ent, reg->href_comp, reg); + printf ("%3d %8x %3d %4d %4d '%.*s'\n", i, ent, ref->index, to->text, to->size, to->size, text + to->text); } #endif diff --git a/libs/ui/test/test-passage.c b/libs/ui/test/test-passage.c index 726e247c0..e67223ee0 100644 --- a/libs/ui/test/test-passage.c +++ b/libs/ui/test/test-passage.c @@ -7,6 +7,18 @@ #include "QF/ui/passage.h" #include "QF/ecs/component.h" +enum { + test_href, +}; + +static const component_t test_components[] = { + [test_href] = { + .size = sizeof (hierref_t), + .create = 0,//create_href, + .name = "href", + }, +}; + static const char test_text[] = { "Guarding the entrance to the Grendal " "Gorge is the Shadow Gate, a small keep " @@ -51,6 +63,8 @@ main (void) { int ret = 0; ecs_registry_t *registry = ECS_NewRegistry (); + ECS_RegisterComponents (registry, test_components, 1); + registry->href_comp = test_href; passage_t *passage = Passage_ParseText (test_text, registry); if (passage->hierarchy->childCount[0] != 3) { From 7106411bc076484c9c159b0d693c85d22136914d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 28 Oct 2022 11:45:30 +0900 Subject: [PATCH 3113/3664] [ui] Link with the ECS library Who thought dynamic libs was a good idea... --- libs/ui/Makemodule.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am index e0b54c30b..38d252a35 100644 --- a/libs/ui/Makemodule.am +++ b/libs/ui/Makemodule.am @@ -2,7 +2,9 @@ include libs/ui/test/Makemodule.am lib_LTLIBRARIES += libs/ui/libQFui.la -ui_deps = libs/util/libQFutil.la +ui_deps = \ + libs/ecs/libQFecs.la \ + libs/util/libQFutil.la libs_ui_libQFui_la_LDFLAGS= $(lib_ldflags) libs_ui_libQFui_la_LIBADD= $(ui_deps) From 7c06012383b1f1c38992f3765e7eb6da7cda4c8e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 30 Oct 2022 23:38:14 +0900 Subject: [PATCH 3114/3664] [util] Support custom swap function for heapsort Sorting ECS component pools needs to swap multiple chunks of data for each element being swapped, so the standard swap function isn't enough. --- include/QF/heapsort.h | 13 ++++++++ libs/util/heapsort.c | 71 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/include/QF/heapsort.h b/include/QF/heapsort.h index 153c4faee..77ec0ef33 100644 --- a/include/QF/heapsort.h +++ b/include/QF/heapsort.h @@ -40,22 +40,35 @@ typedef int (*__compar_fn_t)(const void *, const void *); typedef int (*__compar_d_fn_t)(const void *, const void *, void *); #endif +#ifndef __swap_d_fn_t_defined +#define __swap_d_fn_t_defined +typedef void (*__swap_d_fn_t)(void *, void *, void *); +#endif + void heap_sink (void *base, size_t ind, size_t nmemb, size_t size, __compar_fn_t cmp); void heap_sink_r (void *base, size_t ind, size_t nmemb, size_t size, __compar_d_fn_t cmp, void *arg); +void heap_sink_s (void *base, size_t ind, size_t nmemb, size_t size, + __compar_d_fn_t cmp, __swap_d_fn_t swp, void *arg); void heap_swim (void *base, size_t ind, size_t nmemb, size_t size, __compar_fn_t cmp); void heap_swim_r (void *base, size_t ind, size_t nmemb, size_t size, __compar_d_fn_t cmp, void *arg); +void heap_swim_s (void *base, size_t ind, size_t nmemb, size_t size, + __compar_d_fn_t cmp, __swap_d_fn_t swp, void *arg); void heap_build (void *base, size_t nmemb, size_t size, __compar_fn_t cmp); void heap_build_r (void *base, size_t nmemb, size_t size, __compar_d_fn_t cmp, void *arg); +void heap_build_s (void *base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, __swap_d_fn_t swp, void *arg); void heapsort (void *base, size_t nmemb, size_t size, __compar_fn_t cmp); void heapsort_r (void *base, size_t nmemb, size_t size, __compar_d_fn_t cmp, void *arg); +void heapsort_s (void *base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, __swap_d_fn_t swp, void *arg); #endif//__QF_heapsort_h diff --git a/libs/util/heapsort.c b/libs/util/heapsort.c index aca74e574..e7f840433 100644 --- a/libs/util/heapsort.c +++ b/libs/util/heapsort.c @@ -46,7 +46,7 @@ heap_sink (void *base, size_t ind, size_t nmemb, size_t size, VISIBLE void heap_sink_r (void *base, size_t ind, size_t nmemb, size_t size, - __compar_d_fn_t cmp, void *arg) + __compar_d_fn_t cmp, void *arg) { size_t left_ind = 2 * ind + 1; size_t right_ind = 2 * ind + 2; @@ -71,6 +71,33 @@ heap_sink_r (void *base, size_t ind, size_t nmemb, size_t size, } } +VISIBLE void +heap_sink_s (void *base, size_t ind, size_t nmemb, size_t size, + __compar_d_fn_t cmp, __swap_d_fn_t swp, void *arg) +{ + size_t left_ind = 2 * ind + 1; + size_t right_ind = 2 * ind + 2; + void *node = (byte *) base + ind * size; + void *left = (byte *) base + left_ind * size; + void *right = (byte *) base + right_ind * size; + + size_t largest_ind = ind; + void *largest = node; + + if (left_ind < nmemb && cmp (left, node, arg) > 0) { + largest = left; + largest_ind = left_ind; + } + if (right_ind < nmemb && cmp (right, largest, arg) > 0) { + largest = right; + largest_ind = right_ind; + } + if (largest_ind != ind) { + swp (largest, node, arg); + heap_sink_s (base, largest_ind, nmemb, size, cmp, swp, arg); + } +} + VISIBLE void heap_swim (void *base, size_t ind, size_t nmemb, size_t size, __compar_fn_t cmp) @@ -87,7 +114,7 @@ heap_swim (void *base, size_t ind, size_t nmemb, size_t size, VISIBLE void heap_swim_r (void *base, size_t ind, size_t nmemb, size_t size, - __compar_d_fn_t cmp, void *arg) + __compar_d_fn_t cmp, void *arg) { size_t parent_ind = (ind - 1) / 2; void *node = (byte *) base + ind * size; @@ -99,6 +126,20 @@ heap_swim_r (void *base, size_t ind, size_t nmemb, size_t size, } } +VISIBLE void +heap_swim_s (void *base, size_t ind, size_t nmemb, size_t size, + __compar_d_fn_t cmp, __swap_d_fn_t swp, void *arg) +{ + size_t parent_ind = (ind - 1) / 2; + void *node = (byte *) base + ind * size; + void *parent = (byte *) base + parent_ind * size; + + if (ind > 0 && cmp (node, parent, arg) > 0) { + swp (node, parent, arg); + heap_swim_s (base, parent_ind, nmemb, size, cmp, swp, arg); + } +} + VISIBLE void heap_build (void *base, size_t nmemb, size_t size, __compar_fn_t cmp) { @@ -112,7 +153,7 @@ heap_build (void *base, size_t nmemb, size_t size, __compar_fn_t cmp) VISIBLE void heap_build_r (void *base, size_t nmemb, size_t size, - __compar_d_fn_t cmp, void *arg) + __compar_d_fn_t cmp, void *arg) { if (nmemb < 2) { return; @@ -122,6 +163,18 @@ heap_build_r (void *base, size_t nmemb, size_t size, } } +VISIBLE void +heap_build_s (void *base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, __swap_d_fn_t swp, void *arg) +{ + if (nmemb < 2) { + return; + } + for (size_t i = nmemb / 2; i-- > 0; ) { + heap_sink_s (base, i, nmemb, size, cmp, swp, arg); + } +} + VISIBLE void heapsort (void *base, size_t nmemb, size_t size, __compar_fn_t cmp) { @@ -144,3 +197,15 @@ heapsort_r (void *base, size_t nmemb, size_t size, __compar_d_fn_t cmp, heap_sink_r (base, 0, i, size, cmp, arg); } } + +VISIBLE void +heapsort_s (void *base, size_t nmemb, size_t size, __compar_d_fn_t cmp, + __swap_d_fn_t swp, void *arg) +{ + heap_build_s (base, nmemb, size, cmp, swp, arg); + for (size_t i = nmemb; i-- > 1; ) { + void *last = (byte *) base + i * size; + swp (base, last, arg); + heap_sink_s (base, 0, i, size, cmp, swp, arg); + } +} From 962319af09222e12e9f8952262a081289320938e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Oct 2022 13:06:55 +0900 Subject: [PATCH 3115/3664] [ecs] Make Ent_HasComponent more robust It doesn't check that the entity itself is valid, but it does at least check that the index fetched from the sparse array is valid. Fixes a segfault when a valid entity never had the component. --- include/QF/ecs/component.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/QF/ecs/component.h b/include/QF/ecs/component.h index 47e5dbf6c..da6623371 100644 --- a/include/QF/ecs/component.h +++ b/include/QF/ecs/component.h @@ -198,8 +198,9 @@ ECS_EntValid (uint32_t id, ecs_registry_t *reg) COMPINLINE int Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) { - uint32_t ind = reg->comp_pools[comp].sparse[Ent_Index (ent)]; - return reg->comp_pools[comp].dense[ind] == ent; + ecs_pool_t *pool = ®->comp_pools[comp]; + uint32_t ind = pool->sparse[Ent_Index (ent)]; + return ind < pool->count && pool->dense[ind] == ent; } COMPINLINE void * From cf911884c6bf714bff1e15c9d3f142b2ae22f3bb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 31 Oct 2022 13:10:53 +0900 Subject: [PATCH 3116/3664] [ecs] Add support for sorting component pools As the bookkeeping data is spread between three arrays, sorting a component pool is not trivial and thus not something to duplicate around the codebase. --- include/QF/ecs/component.h | 19 ++++++++++++ libs/ecs/component.c | 59 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/include/QF/ecs/component.h b/include/QF/ecs/component.h index da6623371..8e881ec33 100644 --- a/include/QF/ecs/component.h +++ b/include/QF/ecs/component.h @@ -84,6 +84,8 @@ COMPINLINE void Component_ResizeArray (const component_t *component, COMPINLINE void *Component_MoveElements (const component_t *component, void *array, uint32_t dstIndex, uint32_t srcIndex, uint32_t count); +COMPINLINE void Component_SwapElements (const component_t *component, + void *a, void *b); COMPINLINE void *Component_CopyElements (const component_t *component, void *dstArray, uint32_t dstIndex, const void *srcArray, @@ -131,6 +133,16 @@ Component_MoveElements (const component_t *component, return memmove (dst, src, count * component->size); } +COMPINLINE void +Component_SwapElements (const component_t *component, void *a, void *b) +{ + size_t size = component->size; + byte tmp[size]; + memcpy (tmp, a, size); + memcpy (a, b, size); + memcpy (b, tmp, size); +} + COMPINLINE void * Component_CopyElements (const component_t *component, void *dstArray, uint32_t dstIndex, @@ -217,6 +229,13 @@ void ECS_DelRegistry (ecs_registry_t *registry); void ECS_RegisterComponents (ecs_registry_t *registry, const component_t *components, uint32_t count); +#ifndef __compar_d_fn_t_defined +#define __compar_d_fn_t_defined +typedef int (*__compar_d_fn_t)(const void *, const void *, void *); +#endif +void ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, + __compar_d_fn_t cmp, void *arg); + uint32_t ECS_NewEntity (ecs_registry_t *registry); void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent); diff --git a/libs/ecs/component.c b/libs/ecs/component.c index 896ea70f0..b7c13ad3d 100644 --- a/libs/ecs/component.c +++ b/libs/ecs/component.c @@ -28,6 +28,7 @@ # include "config.h" #endif +#include "QF/heapsort.h" #include "QF/sys.h" #define IMPLEMENT_COMPONENT_Funcs @@ -69,6 +70,64 @@ ECS_RegisterComponents (ecs_registry_t *registry, } } +typedef struct { + __compar_d_fn_t cmp; + void *arg; + ecs_pool_t *pool; + const component_t *comp; +} ecs_sort_t; + +static int +ecs_compare (const void *a, const void *b, void *arg) +{ + ecs_sort_t *sortctx = arg; + return sortctx->cmp (a, b, sortctx->arg); +} + +static void +swap_uint32 (uint32_t *a, uint32_t *b) +{ + uint32_t t = *a; + *a = *b; + *b = t; +} + +static void +ecs_swap (void *_a, void *_b, void *arg) +{ + ecs_sort_t *sortctx = arg; + size_t size = sortctx->comp->size; + ecs_pool_t *pool = sortctx->pool; + uint32_t *a = _a; + uint32_t *b = _b; + uint32_t a_ind = a - pool->dense; + uint32_t b_ind = b - pool->dense; + uint32_t a_ent_ind = Ent_Index (pool->dense[a_ind]); + uint32_t b_ent_ind = Ent_Index (pool->dense[b_ind]); + __auto_type a_data = (byte *) pool->data + a_ind * size; + __auto_type b_data = (byte *) pool->data + b_ind * size; + Component_SwapElements (sortctx->comp, a_data, b_data); + swap_uint32 (a, b); + swap_uint32 (&pool->sparse[a_ent_ind], &pool->sparse[b_ent_ind]); +} + +VISIBLE void +ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, + __compar_d_fn_t cmp, void *arg) +{ + if (component >= registry->num_components) { + Sys_Error ("ECS_SortComponentPool: invalid component: %u", component); + } + ecs_pool_t *pool = ®istry->comp_pools[component]; + if (!pool->count) { + return; + } + __auto_type comp = ®istry->components[component]; + ecs_sort_t sortctx = { .cmp = cmp, .arg = arg, .pool = pool, .comp = comp }; + heapsort_s (pool->dense, pool->count, sizeof (uint32_t), + ecs_compare, ecs_swap, &sortctx); +} + VISIBLE void * Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) { From 817aeb334eccfffefefe71853fc6d08372114f01 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Nov 2022 00:40:52 +0900 Subject: [PATCH 3117/3664] [ui] Convert view_t to an ECS entity Much of the nq/qw HUD system is quite broken, but the basic status bar seems to be working nicely. As is the console (both client and server). Possibly the biggest benefit is separating the rendering of HUD elements from the updating of them, and much less traversing of invisible views whose only purpose is to control the positioning of the visible views. The view flow tests are currently disabled until I adapt the flow code to ECS. There seems to be a problem with view resizing in that some gravities don't follow resizing correctly. --- include/QF/plugin/console.h | 2 +- include/QF/plugin/vid_render.h | 1 - include/QF/screen.h | 6 +- include/QF/ui/view.h | 473 ++++++++++---------- include/client/hud.h | 43 +- include/r_font.h | 3 + include/r_text.h | 12 +- include/sbar.h | 12 +- include/sv_console.h | 12 +- libs/client/hud.c | 208 ++++++++- libs/console/client.c | 463 ++++++++++++------- libs/console/menu.c | 4 +- libs/console/server.c | 243 +++++----- libs/ui/test/Makemodule.am | 12 +- libs/ui/test/test-flow-size.c | 10 +- libs/ui/test/test-flow.c | 10 +- libs/ui/view.c | 208 +++++++++ libs/video/renderer/r_graph.c | 11 +- libs/video/renderer/r_screen.c | 11 +- libs/video/renderer/r_text.c | 1 + libs/video/renderer/sw/d_scan.c | 8 +- libs/video/renderer/vid_common.c | 2 - libs/video/renderer/vid_render_sw.c | 8 +- nq/include/client.h | 2 +- nq/source/cl_parse.c | 22 +- nq/source/cl_screen.c | 200 ++++----- nq/source/sbar.c | 658 +++++++++++++++++----------- qtv/source/sbar.c | 46 +- qw/include/client.h | 6 +- qw/source/cl_cam.c | 4 +- qw/source/cl_ngraph.c | 40 +- qw/source/cl_parse.c | 8 +- qw/source/cl_screen.c | 207 +++++---- qw/source/sbar.c | 545 ++++++++++++++--------- qw/source/sv_sbar.c | 65 +-- 35 files changed, 2263 insertions(+), 1303 deletions(-) diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index 1c9f02f5c..7307bb4f8 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -52,7 +52,7 @@ typedef struct console_data_s { void (*quit) (void); struct cbuf_s *cbuf; struct view_s *screen_view; - struct view_s *view; + //struct view_s *view; struct view_s *status_view; float lines; int (*exec_line)(void *data, const char *line); diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 0b1f0b022..a3df2906a 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -144,7 +144,6 @@ typedef struct vid_render_funcs_s { typedef struct vid_render_data_s { viddef_t *vid; refdef_t *refdef; - struct view_s *scr_view; int scr_copytop; int scr_copyeverything; int scr_fullupdate; // set to 0 to force full redraw diff --git a/include/QF/screen.h b/include/QF/screen.h index a98f2f4d6..98c1d4b94 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -53,8 +53,8 @@ extern int r_zgraph; extern int scr_copytop; extern qboolean scr_skipupdate; -struct view_s; -void R_TimeGraph (struct view_s *view); -void R_ZGraph (struct view_s *view); +struct view_pos_s; +void R_TimeGraph (struct view_pos_s abs); +void R_ZGraph (struct view_pos_s abs); #endif//__QF_screen_h diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index ed3d09776..f5ded1ccf 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -31,6 +31,9 @@ #ifndef __QF_ui_view_h #define __QF_ui_view_h +#include "QF/ecs/component.h" +#include "QF/ecs/hierarchy.h" + /** \defgroup console_view Console View Objects \ingroup console */ @@ -69,275 +72,285 @@ typedef enum { extern struct exprtype_s grav_t_type; -/** The view object. -*/ -typedef struct view_s view_t; -struct view_s { - /// Coordinates of view's origin relative to parent's gravity point. - //@{ - int xpos, ypos; - //@} - /// Size of the view. - //@{ - int xlen, ylen; - //@} - /** Absolute coordinates of the top left (northwest) corner of the view. - Set interally. - */ - //@{ - int xabs, yabs; - //@} - /** Coordinates of the top left (northwest) corner of the view relative to - the parent view's top left corner. Set internally. - */ - //@{ - int xrel, yrel; - //@} +typedef struct view_pos_s { + int x; + int y; +} view_pos_t; + +typedef struct viewcont_s { grav_t gravity; ///< The gravity of the view. unsigned visible:1; ///< If false, view_draw() skips this view. unsigned resize_x:1; ///< If true, view's width follows parent's. unsigned resize_y:1; ///< If true, view's height follows parent's. unsigned bol_suppress:1; ///< If true, view_flow skips at start of line. unsigned flow_size:1; ///< If true, view's size is adjusted to flow. - view_t *parent; ///< The parent view. - view_t **children; ///< The child views. - int num_children; ///< Number of child views in view. - int max_children; ///< Size of children array. - /** Callback for drawing the view. defaults to view_draw(). if overridden, - the supplied callback should call view_draw() to draw any child views - unless the view is a leaf view. +} viewcont_t; - \note All coordinates are set appropriately before this is called. - - \param view This view. +enum { + /// Coordinates of view's origin relative to parent's gravity point. + view_pos, + /// Size of the view. + view_len, + /** Absolute coordinates of the top left (northwest) corner of the view. + Set interally. */ - void (*draw)(view_t *view); - /** Callback for when the position and/or size of the view changes. Set - this if the underlying drawing system needs to take any action when - the view's geometry changes (eg, moving/resizing the window in curses). - - \note All coordinates are set appropriately before this is called. - - \param view This view. + view_abs, + /** Coordinates of the top left (northwest) corner of the view relative to + the parent view's top left corner. Set internally. */ - void (*setgeometry)(view_t *view); - /** User supplied data. Purely for external use. The view functions do not - touch this at all except view_new(), which just sets it to 0. - */ - void *data; + view_rel, + view_oldlen, + view_control, + view_modified, + view_onresize, + view_onmove, + + view_type_count }; -/** Create a new view. view_t::draw is set to view_draw() and the view is made - visible. All coordinates are set appropriately for the new view being a - root view. All other fields not set by the parameters are 0. - - \param xp The X coordinate of the view's origin. - \param yp The Y coordinate of the view's origin. - \param xl The width of the view. - \param yl The height of the view. - \param grav The gravity of the view. determines the view's origin and - its positioning within the view's parent. +/** The view object. */ -view_t *view_new (int xp, int yp, int xl, int yl, grav_t grav); +typedef struct view_s { + ecs_registry_t *reg; + uint32_t id; + uint32_t comp; +} view_t; -/** Create a new view. view_t::draw is set to view_draw() and the view is made - visible. All coordinates are set appropriately for the new view being a - root view. All other fields not set by the parameters are 0. +#define nullview ((view_t) {}) - \param xp The X coordinate of the view's origin. - \param yp The Y coordinate of the view's origin. - \param xl The width of the view. - \param yl The height of the view. - \param grav The gravity of the view. determines the view's origin and - its positioning within the view's parent. - \param data Pointer with which the view\s data pointer will be - initialized. -*/ -view_t *view_new_data (int xp, int yp, int xl, int yl, grav_t grav, void *data); +typedef void (*view_resize_f) (view_t view, view_pos_t len); +typedef void (*view_move_f) (view_t view, view_pos_t abs); -/** Insert a view into a parent view at the specified location. If \c pos is - negative, it is taken to be relative to the end of the parent's list of - views (view_insert (par, view, -1) is equivalent to view_add (par, view)). - \c pos is clipped to be within the correct range. +#define VIEWINLINE GNU89INLINE inline - The absolute X and Y coordianates of the inserted view and its child views - are updated based on the view's gravity. +view_t View_New (ecs_registry_t *reg, view_t parent); +void View_SetParent (view_t view, view_t parent); +void View_UpdateHierarchy (view_t view); - The position of the view within the parent view's child view list - determines the draw order (and thus Z order) of the view, with position 0 - being drawn first. +VIEWINLINE hierref_t *View_GetRef (view_t view); +VIEWINLINE int View_Valid (view_t view); - \param par The parent view into which the view is to be inserted. - \param view The view to insert. - \param pos The position at which to insert the view into the parent. -*/ -void view_insert (view_t *par, view_t *view, int pos); +VIEWINLINE view_t View_GetParent (view_t view); +VIEWINLINE uint32_t View_ChildCount (view_t view); +VIEWINLINE view_t View_GetChild (view_t view, uint32_t index); -/** Add a view to a parent view at the end of the parents view list. +VIEWINLINE void View_SetPos (view_t view, int x, int y); +VIEWINLINE view_pos_t View_GetPos (view_t view); +VIEWINLINE view_pos_t View_GetAbs (view_t view); +VIEWINLINE view_pos_t View_GetRel (view_t view); +VIEWINLINE void View_SetLen (view_t view, int x, int y); +VIEWINLINE view_pos_t View_GetLen (view_t view); +VIEWINLINE void View_SetGravity (view_t view, grav_t grav); +VIEWINLINE grav_t View_GetGravity (view_t view); +VIEWINLINE void View_SetVisible (view_t view, int visible); +VIEWINLINE int View_GetVisible (view_t view); +VIEWINLINE void View_SetResize (view_t view, int resize_x, int resize_y); +VIEWINLINE void View_SetOnResize (view_t view, view_resize_f onresize); +VIEWINLINE void View_SetOnMove (view_t view, view_move_f onmove); - The absolute X and Y coordianates of the inserted view and its child views - are updated based on the view's gravity. +#undef VIEWINLINE +#ifndef IMPLEMENT_VIEW_Funcs +#define VIEWINLINE GNU89INLINE inline +#else +#define VIEWINLINE VISIBLE +#endif - The added view will be drawn last (and thus on top of earlier views). +VIEWINLINE +hierref_t * +View_GetRef (view_t view) +{ + return Ent_GetComponent (view.id, view.comp, view.reg); +} - \param par The parent view to which the view is to be added. - \param view The view to add. -*/ -void view_add (view_t *par, view_t *view); +VIEWINLINE +int +View_Valid (view_t view) +{ + return view.reg && ECS_EntValid (view.id, view.reg); +} -/** Remove a view from its parent. +VIEWINLINE +view_t +View_GetParent (view_t view) +{ + __auto_type ref = View_GetRef (view); + if (ref->index == 0) { + return nullview; + } + hierarchy_t *h = ref->hierarchy; + return (view_t) { + .reg = view.reg, + .id = h->ent[h->parentIndex[ref->index]], + .comp = view.comp, + }; +} - \param par The parent view from which the view is to be removed. - \param view The view to remove. -*/ -void view_remove (view_t *par, view_t *view); +VIEWINLINE +uint32_t +View_ChildCount (view_t view) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + return h->childCount[ref->index]; +} -/** Delete a view and all its child views. If the view has a parent, the view - will be removed from its parent. +VIEWINLINE +view_t +View_GetChild (view_t view, uint32_t childIndex) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + if (childIndex >= h->childCount[ref->index]) { + return nullview; + } + return (view_t) { + .reg = view.reg, + .id = h->ent[h->childIndex[ref->index] + childIndex], + .comp = view.comp, + }; +} - \param view The view to delete. -*/ -void view_delete (view_t *view); -/** Draw the child views of a view. If a child view is not visible - (view_t::visible is 0), the child will be skipped. +VIEWINLINE +void +View_SetPos (view_t view, int x, int y) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + byte *modified = h->components[view_modified]; + pos[ref->index] = (view_pos_t) { x, y }; + modified[ref->index] |= 1; +} - \note It is best to always use view_t::draw() to draw a view rather than - calling this directly. This function is really for the view's draw - callback to call to draw its sub-views. +VIEWINLINE +view_pos_t +View_GetPos (view_t view) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + return pos[ref->index]; +} - \param view The view of which to draw the children. -*/ -void view_draw (view_t *view); +VIEWINLINE +view_pos_t +View_GetAbs (view_t view) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *abs = h->components[view_abs]; + return abs[ref->index]; +} -/** Change the size of a view. The view's children are also resized based on - their view_t::resize_x and view_t::resize_y flags. +VIEWINLINE +view_pos_t +View_GetRel (view_t view) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *rel = h->components[view_rel]; + return rel[ref->index]; +} - The absolute X and Y coorinates of the view are updated as necessary to - keep the coordinates of the view's origin correct relative to the view's - geometry. +VIEWINLINE +void +View_SetLen (view_t view, int x, int y) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *len = h->components[view_len]; + view_pos_t *oldlen = h->components[view_oldlen]; + byte *modified = h->components[view_modified]; + if (!(modified[ref->index] & 2)) { + oldlen[ref->index] = len[ref->index]; + } + len[ref->index] = (view_pos_t) { x, y }; + modified[ref->index] |= 2; +} - \param view The view to resize. - \param xl The new width of the view. - \param yl The new height of the view. -*/ -void view_resize (view_t *view, int xl, int yl); +VIEWINLINE +view_pos_t +View_GetLen (view_t view) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *len = h->components[view_len]; + return len[ref->index]; +} -/** Chage the location of a view. +VIEWINLINE +void +View_SetGravity (view_t view, grav_t grav) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + viewcont_t *cont = h->components[view_control]; + byte *modified = h->components[view_modified]; + cont[ref->index].gravity = grav; + modified[ref->index] |= 1; +} - The absolute X and Y coorinates of the view are updated as necessary to - keep the coordinates of the view's origin correct relative to the view's - geometry. +VIEWINLINE +grav_t +View_GetGravity (view_t view) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + viewcont_t *cont = h->components[view_control]; + return cont[ref->index].gravity; +} - \param view The view to move. - \param xp The new X coordinate of the view relative to its gravity. - \param yp The new Y coordinate of the view relative to its gravity. -*/ -void view_move (view_t *view, int xp, int yp); +VIEWINLINE +void +View_SetVisible (view_t view, int visible) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + viewcont_t *cont = h->components[view_control]; + cont[ref->index].visible = !!visible; +} -/** Chage the location and size of a view in a single operation. +VIEWINLINE +int +View_GetVisible (view_t view) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + viewcont_t *cont = h->components[view_control]; + return cont[ref->index].visible; +} - The absolute X and Y coorinates of the view are updated as necessary to - keep the coordinates of the view's origin correct relative to the view's - geometry. +VIEWINLINE +void +View_SetResize (view_t view, int resize_x, int resize_y) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + viewcont_t *cont = h->components[view_control]; + cont[ref->index].resize_x = resize_x; + cont[ref->index].resize_y = resize_y; +} - \param view The view to move. - \param xp The new X coordinate of the view relative to its gravity. - \param yp The new Y coordinate of the view relative to its gravity. - \param xl The new width of the view. - \param yl The new height of the view. -*/ -void view_setgeometry (view_t *view, int xp, int yp, int xl, int yl); +VIEWINLINE +void +View_SetOnResize (view_t view, view_resize_f onresize) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_resize_f *resize = h->components[view_onresize]; + resize[ref->index] = onresize; +} -/** Change the gravity of a view, adjusting its position appropriately - - \param view The view which will have its gravity set.. - \param grav The gravity of the view. determines the view's origin and - its positioning within the view's parent. -*/ -void view_setgravity (view_t *view, grav_t grav); - -/** Automatic layout of child views by flowing them. - - The child views are layed out linearly in the first indicated direction, - and when a child view exceeds the bounds of the view, a new flow line is - started in the second indicated direction. Flow lines always start at the - edge of the view, and the first flow line is at the appropriate edge of - the view such that at least one child view on the line touches the view's - edge and no child view exceeds that edge. - - All child views must have gravity set to grav_flow, or their behavior will - be undefined. - - A child view with bol_suppress set will not contribute to a flow-line's - length when that child view is the first view on the line, otherwise it - behaves as if bol_suppress is not set. - - If the view's flow_size is set, then its secondary axis size is adjusted - so the child views fill the view along that axis. The primary axis size is - never adjusted. -*/ -///@{ - -/** Flow child views from left to right, top to bottom. - - Suitable for English and most European scripts. - - \param view The parent view containing the children to be flowed. -*/ -void view_flow_right_down (view_t *view); - -/** Flow child views from right to left, bottom to top. - - \param view The parent view containing the children to be flowed. -*/ -void view_flow_right_up (view_t *view); - -/** Flow child views from right to left, top to bottom. - - Suitable for Arabic and similar scripts. - - \param view The parent view containing the children to be flowed. -*/ -void view_flow_left_down (view_t *view); - -/** Flow child views from left to left, bottom to top. - - \param view The parent view containing the children to be flowed. -*/ -void view_flow_left_up (view_t *view); - -/** Flow child views from top to bottom, left to right. - - \param view The parent view containing the children to be flowed. -*/ -void view_flow_down_right (view_t *view); - -/** Flow child views from bottom to top, left to right. - - Suitable for English and most European scripts. - - \param view The parent view containing the children to be flowed. -*/ -void view_flow_up_right (view_t *view); - -/** Flow child views from top to bottom, right to left. - - Suitable for Asian lanauges (Japanese, Korean, Chinese). - - \param view The parent view containing the children to be flowed. -*/ -void view_flow_down_left (view_t *view); - -/** Flow child views from bottom to top, right to left. - - Suitable for English and most European scripts. - - \param view The parent view containing the children to be flowed. -*/ -void view_flow_up_left (view_t *view); - -///@} +VIEWINLINE +void +View_SetOnMove (view_t view, view_move_f onmove) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_move_f *move = h->components[view_onmove]; + move[ref->index] = onmove; +} ///@} diff --git a/include/client/hud.h b/include/client/hud.h index 042a78bbc..cc11419fe 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -28,25 +28,48 @@ #ifndef __client_hud_h #define __client_hud_h +enum { + hud_href, + hud_tile, + hud_pic, + hud_subpic, + hud_cachepic, + hud_fill, + hud_charbuff, + hud_func, + + hud_comp_count +}; + +typedef struct hud_subpic_s { + struct qpic_s *pic; + uint32_t x, y; + uint32_t w, h; +} hud_subpic_t; + +extern struct ecs_registry_s *hud_registry; + extern int hud_sb_lines; extern int hud_sbar; extern int hud_swap; -extern struct view_s *sbar_view; -extern struct view_s *sbar_inventory_view; -extern struct view_s *sbar_frags_view; +//extern struct view_s sbar_view; +//extern struct view_s sbar_inventory_view; +//extern struct view_s sbar_frags_view; -extern struct view_s *hud_view; -extern struct view_s *hud_inventory_view; -extern struct view_s *hud_armament_view; -extern struct view_s *hud_frags_view; +extern struct view_s hud_view; +extern struct view_s hud_inventory_view; +extern struct view_s hud_armament_view; +extern struct view_s hud_frags_view; -extern struct view_s *hud_overlay_view; -extern struct view_s *hud_stuff_view; -extern struct view_s *hud_main_view; +extern struct view_s hud_overlay_view; +extern struct view_s hud_stuff_view; +extern struct view_s hud_main_view; +void HUD_Init (void); void HUD_Init_Cvars (void); void HUD_Calc_sb_lines (int view_size); +void HUD_Draw_Views (void); #endif//__client_hud_h diff --git a/include/r_font.h b/include/r_font.h index 3ed303ed0..a39588de1 100644 --- a/include/r_font.h +++ b/include/r_font.h @@ -39,6 +39,9 @@ #include "r_scrap.h" +typedef struct fontent_s { + uint32_t id; +} fontent_t; typedef struct rfont_s { void *font_resource; diff --git a/include/r_text.h b/include/r_text.h index f440dc985..72c5c8386 100644 --- a/include/r_text.h +++ b/include/r_text.h @@ -36,6 +36,14 @@ #include "QF/darray.h" +#include "QF/ecs/component.h" + +typedef struct script_component_s { + hb_language_t language; + hb_script_t script; + hb_direction_t direction; +} script_component_t; + typedef struct rtext_s { const char *text; const char *language; @@ -56,8 +64,8 @@ typedef struct rshaper_s { r_hb_featureset_t features; } rshaper_t; -extern hb_feature_t LiagureOff; -extern hb_feature_t LiagureOn; +extern hb_feature_t LigatureOff; +extern hb_feature_t LigatureOn; extern hb_feature_t KerningOff; extern hb_feature_t KerningOn; extern hb_feature_t CligOff; diff --git a/include/sbar.h b/include/sbar.h index a8d964010..71417406f 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -40,7 +40,17 @@ void Sbar_Init (void); struct cvar_s; void Sbar_DMO_Init_f (void *data, const struct cvar_s *var); -void Sbar_Changed (void); +typedef enum { + sbc_ammo, + sbc_armor, + sbc_frags, + sbc_health, + sbc_info, + sbc_items, + sbc_weapon, +} sbar_changed; + +void Sbar_Changed (sbar_changed change); // call whenever any of the client stats represented on the sbar changes void Sbar_Draw (void); diff --git a/include/sv_console.h b/include/sv_console.h index c6584a90b..28c616dd0 100644 --- a/include/sv_console.h +++ b/include/sv_console.h @@ -1,13 +1,21 @@ #ifndef __sv_console_h #define __sv_console_h +enum { + server_href, + server_view, + server_window, + + server_comp_count +}; + struct view_s; typedef struct sv_view_s { void *win; void *obj; - void (*draw) (struct view_s *view); - void (*setgeometry) (struct view_s *view); + void (*draw) (struct view_s view); + void (*setgeometry) (struct view_s view); } sv_view_t; typedef struct sv_sbar_s { diff --git a/libs/client/hud.c b/libs/client/hud.c index c6ac8659e..7ba7c3354 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -41,6 +41,42 @@ #include "client/hud.h" +static const component_t hud_components[hud_comp_count] = { + [hud_href] = { + .size = sizeof (hierref_t), + .name = "href", + }, + [hud_tile] = { + .size = sizeof (byte), + .name = "pic", + }, + [hud_pic] = { + .size = sizeof (qpic_t *), + .name = "pic", + }, + [hud_subpic] = { + .size = sizeof (hud_subpic_t), + .name = "subpic", + }, + [hud_cachepic] = { + .size = sizeof (const char *), + .name = "cachepic", + }, + [hud_fill] = { + .size = sizeof (uint32_t), + .name = "fill", + }, + [hud_charbuff] = { + .size = sizeof (draw_charbuffer_t *), + .name = "charbuffer", + }, + [hud_func] = { + .size = sizeof (void (*)(view_pos_t)), + .name = "func", + }, +}; + +ecs_registry_t *hud_registry; int hud_sb_lines; int hud_sbar; @@ -72,24 +108,25 @@ static cvar_t hud_swap_cvar = { .value = { .type = &cexpr_int, .value = &hud_swap }, }; -view_t *sbar_view; -view_t *sbar_inventory_view; -view_t *sbar_frags_view; +view_t sbar_view; +view_t sbar_inventory_view; +view_t sbar_frags_view; -view_t *hud_view; -view_t *hud_inventory_view; -view_t *hud_armament_view; -view_t *hud_frags_view; +view_t hud_view; +view_t hud_inventory_view; +view_t hud_armament_view; +view_t hud_frags_view; -view_t *hud_overlay_view; -view_t *hud_stuff_view; -view_t *hud_main_view; +view_t hud_overlay_view; +view_t hud_stuff_view; +view_t hud_main_view; static void hud_sbar_f (void *data, const cvar_t *cvar) { HUD_Calc_sb_lines (*r_data->scr_viewsize); SCR_SetBottomMargin (hud_sbar ? hud_sb_lines : 0); +#if 0//XXX if (hud_sbar) { view_remove (hud_main_view, hud_main_view->children[0]); view_insert (hud_main_view, sbar_view, 0); @@ -97,11 +134,13 @@ hud_sbar_f (void *data, const cvar_t *cvar) view_remove (hud_main_view, hud_main_view->children[0]); view_insert (hud_main_view, hud_view, 0); } +#endif } static void hud_swap_f (void *data, const cvar_t *cvar) { +#if 0//XXX if (hud_swap) { //FIXME why is this needed for nq but not for qw? hud_armament_view->children[0]->gravity = grav_northwest; @@ -118,12 +157,25 @@ hud_swap_f (void *data, const cvar_t *cvar) view_move (hud_armament_view, hud_armament_view->xpos, hud_armament_view->ypos); view_move (hud_stuff_view, hud_stuff_view->xpos, hud_stuff_view->ypos); +#endif } static void hud_scoreboard_gravity_f (void *data, const cvar_t *cvar) { +#if 0//XXX view_setgravity (hud_overlay_view, hud_scoreboard_gravity); +#endif +} + +void +HUD_Init (void) +{ + hud_registry = ECS_NewRegistry (); + ECS_RegisterComponents (hud_registry, hud_components, hud_comp_count); + hud_registry->href_comp = hud_href; + + hud_view = View_New (hud_registry, nullview); } void @@ -137,6 +189,7 @@ HUD_Init_Cvars (void) void HUD_Calc_sb_lines (int view_size) { +#if 0//XXX int stuff_y; if (view_size >= 120) { @@ -165,4 +218,139 @@ HUD_Calc_sb_lines (int view_size) hud_view->visible = 0; } view_move (hud_stuff_view, hud_stuff_view->xpos, stuff_y); +#endif +} + +static void +draw_tile_views (ecs_pool_t *pool) +{ + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + while (count-- > 0) { + view_t view = { .id = *ent++, .reg = hud_registry }; + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + view_pos_t len = View_GetLen (view); + r_funcs->Draw_TileClear (pos.x, pos.y, len.x, len.y); + } + } +} + +static void +draw_pic_views (ecs_pool_t *pool) +{ + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + qpic_t **pic = pool->data; + while (count-- > 0) { + view_t view = { .id = *ent++, .reg = hud_registry }; + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + r_funcs->Draw_Pic (pos.x, pos.y, *pic); + } + pic++; + } +} + +static void +draw_subpic_views (ecs_pool_t *pool) +{ + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + hud_subpic_t *subpic = pool->data; + while (count-- > 0) { + view_t view = { .id = *ent++, .reg = hud_registry }; + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + r_funcs->Draw_SubPic (pos.x, pos.y, subpic->pic, + subpic->x, subpic->y, subpic->w, subpic->h); + } + subpic++; + } +} + +static void +draw_cachepic_views (ecs_pool_t *pool) +{ + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + const char **name = pool->data; + while (count-- > 0) { + view_t view = { .id = *ent++, .reg = hud_registry }; + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + qpic_t *pic = r_funcs->Draw_CachePic (*name, 1); + r_funcs->Draw_Pic (pos.x, pos.y, pic); + } + name++; + } +} + +static void +draw_fill_views (ecs_pool_t *pool) +{ + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + uint32_t *fill = pool->data; + while (count-- > 0) { + view_t view = { .id = *ent++, .reg = hud_registry }; + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + view_pos_t len = View_GetLen (view); + r_funcs->Draw_Fill (pos.x, pos.y, len.x, len.y, *fill); + } + fill++; + } +} + +static void +draw_charbuff_views (ecs_pool_t *pool) +{ + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + draw_charbuffer_t **charbuff = pool->data; + while (count-- > 0) { + view_t view = { .id = *ent++, .reg = hud_registry }; + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + r_funcs->Draw_CharBuffer (pos.x, pos.y, *charbuff); + } + charbuff++; + } +} + +static void +draw_func_views (ecs_pool_t *pool) +{ + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + void (**func) (view_pos_t, view_pos_t) = pool->data; + while (count-- > 0) { + view_t view = { .id = *ent++, .reg = hud_registry }; + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + view_pos_t len = View_GetLen (view); + (*func) (pos, len); + } + func++; + } +} + +void +HUD_Draw_Views (void) +{ + static void (*draw_func[hud_comp_count]) (ecs_pool_t *) = { + [hud_tile] = draw_tile_views, + [hud_pic] = draw_pic_views, + [hud_subpic] = draw_subpic_views, + [hud_cachepic] = draw_cachepic_views, + [hud_fill] = draw_fill_views, + [hud_charbuff] = draw_charbuff_views, + [hud_func] = draw_func_views, + }; + for (int i = 0; i < hud_comp_count; i++) { + if (draw_func[i]) { + draw_func[i] (&hud_registry->comp_pools[i]); + } + } } diff --git a/libs/console/client.c b/libs/console/client.c index 9ca080e0a..f9026a72d 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -143,6 +143,8 @@ static cvar_t cl_conmode_cvar = { .value = { .type = &cl_conmode_type, .value = &con_data.exec_line }, }; +static ecs_registry_t *client_reg; + static con_state_t con_state; static int con_event_id; static int con_saved_focos; @@ -153,36 +155,92 @@ static qboolean chat_team; typedef struct { const char *prompt; inputline_t *input_line; - view_t *view; draw_charbuffer_t *buffer; } con_input_t; +enum { + client_href, + client_input, + client_charbuff, + client_cursor, + + client_comp_count +}; + +static const component_t client_components[client_comp_count] = { + [client_href] = { + .size = sizeof (hierref_t), + .name = "href", + }, + [client_input] = { + .size = sizeof (con_input_t *), + .name = "input", + }, + [client_charbuff] = { + .size = sizeof (draw_charbuffer_t *), + .name = "charbuff", + }, + [client_cursor] = { + .size = sizeof (con_input_t *), + .name = "cursor", + }, +}; + #define MAXCMDLINE 256 static con_input_t cmd_line; static con_input_t say_line; -static con_input_t team_line; +static inputline_t *chat_input; +static inputline_t *team_input; + +static view_t screen_view; +static view_t console_view; +static view_t buffer_view; +static view_t command_view; +static view_t download_view; +static view_t notify_view; +static view_t say_view; #define CON_BUFFER_SIZE 32768 #define CON_LINES 1024 -static view_t *console_view; static draw_charbuffer_t *console_buffer; static con_buffer_t *con_main; static int view_offset; +static draw_charbuffer_t *download_buffer; #define NOTIFY_LINES 4 -static view_t *notify_view; static draw_charbuffer_t *notify_buffer; // ring buffer holding realtime time the line was generated static float notify_times[NOTIFY_LINES + 1]; static int notify_head; static int notify_tail; -static view_t *menu_view; -static view_t *hud_view; - static qboolean con_initialized; +static inline void * +con_getcomponent (view_t view, uint32_t comp) +{ + return Ent_GetComponent (view.id, comp, view.reg); +} + +static inline int +con_hascomponent (view_t view, uint32_t comp) +{ + return Ent_HasComponent (view.id, comp, view.reg); +} + +static inline void * +con_setcomponent (view_t view, uint32_t comp, void *data) +{ + return Ent_SetComponent (view.id, comp, view.reg, data); +} + +static inline void +con_remcomponent (view_t view, uint32_t comp) +{ + Ent_RemoveComponent (view.id, comp, view.reg); +} + static void ClearNotify (void) { @@ -204,11 +262,15 @@ C_SetState (con_state_t state) if (state == con_message) { say_line.prompt = "say:"; + say_line.input_line = chat_input; if (chat_team) { say_line.prompt = "say_team:"; + say_line.input_line = team_input; } - say_line.buffer->cursx = 0; - Draw_PrintBuffer (say_line.buffer, say_line.prompt); + __auto_type buffer = say_line.buffer; + buffer->cursx = 0; + Draw_PrintBuffer (buffer, say_line.prompt); + say_line.input_line->width = buffer->width - buffer->cursx; } if (con_state == con_menu && old_state != con_menu) { @@ -374,19 +436,7 @@ C_Print (const char *fmt, va_list args) /* DRAWING */ static void -draw_cursor (int x, int y, inputline_t *il) -{ - if (!con_data.realtime) { - return; - } - - float t = *con_data.realtime * con_cursorspeed; - int ch = 10 + ((int) (t) & 1); - r_funcs->Draw_Character (x + ((il->linepos - il->scroll) * 8), y, ch); -} - -static void -DrawInputLine (int x, int y, int cursor, inputline_t *il) +DrawInputLine (int x, int y, inputline_t *il) { const char *s = il->lines[il->edit_line] + il->scroll; @@ -396,9 +446,6 @@ DrawInputLine (int x, int y, int cursor, inputline_t *il) } else { r_funcs->Draw_nString (x, y, s, il->width - 1); } - if (cursor) { - draw_cursor (x, y, il); - } if (strlen (s) >= il->width) r_funcs->Draw_Character (x + ((il->width - 1) * 8), y, '>' | 0x80); } @@ -406,7 +453,7 @@ DrawInputLine (int x, int y, int cursor, inputline_t *il) void C_DrawInputLine (inputline_t *il) { - DrawInputLine (il->x, il->y, il->cursor, il); + DrawInputLine (il->x, il->y, il); } static void @@ -426,16 +473,6 @@ draw_input_line (inputline_t *il, draw_charbuffer_t *buffer) *dst++ = *src ? '>' | 0x80 : ' '; } -static void -draw_input (view_t *view) -{ - __auto_type inp = (con_input_t *) view->data; - - Draw_CharBuffer (view->xabs, view->yabs, inp->buffer); - draw_cursor (view->xabs + inp->buffer->cursx * 8, view->yabs, - inp->input_line); -} - static void input_line_draw (inputline_t *il) { @@ -444,29 +481,34 @@ input_line_draw (inputline_t *il) } static void -resize_input (view_t *view) +resize_input (view_t view, view_pos_t len) { - __auto_type inp = (con_input_t *) view->data; + if (!con_hascomponent (view, client_input)) { + return; + } + __auto_type inp = *(con_input_t **) con_getcomponent (view, client_input); if (inp->buffer) { Draw_DestroyBuffer (inp->buffer); } - inp->buffer = Draw_CreateBuffer (view->xlen / 8, 1); + inp->buffer = Draw_CreateBuffer (len.x / 8, 1); Draw_ClearBuffer (inp->buffer); Draw_PrintBuffer (inp->buffer, inp->prompt); - inp->buffer->chars[inp->buffer->cursx] = inp->input_line->prompt_char; - inp->input_line->width = inp->buffer->width - inp->buffer->cursx; + if (inp->input_line) { + inp->input_line->width = inp->buffer->width - inp->buffer->cursx; + printf ("resize_input: %d %zd %d %d %d\n", view.id, + inp->input_line->width, + len.x, inp->buffer->width, inp->buffer->cursx); + inp->buffer->chars[inp->buffer->cursx] = inp->input_line->prompt_char; + } } static void -draw_download (view_t *view) +update_download (void) { static dstring_t *dlbar; const char *text; - if (!con_data.dl_name || !*con_data.dl_name->str) - return; - if (!dlbar) { dlbar = dstring_new (); } @@ -500,15 +542,14 @@ draw_download (view_t *view) dsprintf (dlbar, "%.*s%s: \x80%s\x82 %02d%%", txt_size, text, ellipsis, dots, *con_data.dl_percent); - // draw it - r_funcs->Draw_String (view->xabs, view->yabs, dlbar->str); -} - -static void -draw_console_text (view_t *view) -{ - Draw_CharBuffer (view->xabs, view->yabs, console_buffer); + int i; + for (i = 0; i < download_buffer->width && dlbar->str[i]; i++) { + download_buffer->chars[i] = dlbar->str[i]; + } + for (; i < download_buffer->width; i++) { + download_buffer->chars[i] = ' '; + } } static void @@ -519,15 +560,16 @@ clear_console_text (void) } static void -resize_console_text (view_t *view) +resize_console_text (view_t view, view_pos_t len) { - int width = view->xlen / 8; - int height = view->ylen / 8; + int width = len.x / 8; + int height = len.y / 8; if (console_buffer->width != width || console_buffer->height != height) { con_linewidth = width; Draw_DestroyBuffer (console_buffer); console_buffer = Draw_CreateBuffer (width, height); + con_setcomponent (buffer_view, client_charbuff, &console_buffer); clear_console_text (); } } @@ -556,26 +598,49 @@ draw_con_scrollback (void) } static void -draw_console (view_t *view) +draw_cursor (void) { - byte alpha; - - if (con_state == con_fullscreen) { - alpha = 255; - } else { - float y = con_data.screen_view->ylen * con_size; - alpha = 255 * con_alpha * view->ylen / y; - alpha = min (alpha, 255); + if (!con_data.realtime) { + return; } - // draw the background - r_funcs->Draw_ConsoleBackground (con_data.lines, alpha); - // draw everything else - view_draw (view); + float t = *con_data.realtime * con_cursorspeed; + int ch = 10 + ((int) (t) & 1); + + ecs_pool_t *pool = &client_reg->comp_pools[client_cursor]; + con_input_t **inp = pool->data; + uint32_t *id = pool->dense; + + for (uint32_t i = pool->count; i-- > 0; ) { + __auto_type buff = (*inp)->buffer; + __auto_type il = (*inp++)->input_line; + view_t v = { .reg = client_reg, .id = *id++, + .comp = screen_view.comp }; + if (!il->cursor) { + continue; + } + view_pos_t pos = View_GetAbs (v); + int x = (buff->cursx + il->linepos - il->scroll) * 8; + r_funcs->Draw_Character (pos.x + x, pos.y, ch); + } } static void -draw_notify (view_t *view) +draw_buffer (void) +{ + ecs_pool_t *pool = &client_reg->comp_pools[client_charbuff]; + draw_charbuffer_t **buffer = pool->data; + uint32_t *id = pool->dense; + for (uint32_t i = pool->count; i-- > 0; ) { + view_t v = { .reg = client_reg, .id = *id++, + .comp = screen_view.comp }; + view_pos_t pos = View_GetAbs (v); + Draw_CharBuffer (pos.x, pos.y, *buffer++); + } +} + +static void +update_notify (void) { if (con_data.realtime && notify_tail != notify_head && *con_data.realtime - notify_times[notify_tail] > con_notifytime) { @@ -586,21 +651,53 @@ draw_notify (view_t *view) notify_tail -= NOTIFY_LINES + 1; } } - Draw_CharBuffer (view->xabs, view->yabs, notify_buffer); } static void -resize_notify (view_t *view) +draw_console (view_t view) +{ + byte alpha; + + if (con_state == con_fullscreen) { + alpha = 255; + } else { + view_pos_t len = View_GetLen (screen_view); + float y = len.y * con_size; + alpha = 255 * con_alpha * len.y / y; + alpha = min (alpha, 255); + } + // draw the background + r_funcs->Draw_ConsoleBackground (con_data.lines, alpha); + + update_notify (); + // draw everything else + draw_buffer (); + draw_cursor (); +} + +static void +resize_notify (view_t view, view_pos_t len) { Draw_DestroyBuffer (notify_buffer); - notify_buffer = Draw_CreateBuffer (view->xlen / 8, NOTIFY_LINES + 1); + notify_buffer = Draw_CreateBuffer (len.x / 8, NOTIFY_LINES + 1); + con_setcomponent (notify_view, client_charbuff, ¬ify_buffer); ClearNotify (); } +static void +resize_download (view_t view, view_pos_t len) +{ + if (download_buffer) { + Draw_DestroyBuffer (download_buffer); + download_buffer = Draw_CreateBuffer (len.x / 8, 1); + } +} + static void setup_console (void) { float lines = 0; + view_pos_t screen_len = View_GetLen (screen_view); switch (con_state) { case con_message: @@ -609,11 +706,10 @@ setup_console (void) lines = 0; break; case con_active: - lines = con_data.screen_view->ylen * bound (0.2, con_size, - 1); + lines = screen_len.y * bound (0.2, con_size, 1); break; case con_fullscreen: - lines = con_data.lines = con_data.screen_view->ylen; + lines = con_data.lines = screen_len.y; break; } @@ -628,10 +724,10 @@ setup_console (void) } else { con_data.lines = lines; } - if (con_data.lines > con_data.screen_view->ylen) { - con_data.lines = con_data.screen_view->ylen; + if (con_data.lines > screen_len.y) { + con_data.lines = screen_len.y; } - if (con_data.lines >= con_data.screen_view->ylen - r_data->lineadj) + if (con_data.lines >= screen_len.y - r_data->lineadj) r_data->scr_copyeverything = 1; } @@ -639,18 +735,44 @@ static void C_DrawConsole (void) { setup_console (); + view_pos_t screen_len = View_GetLen (screen_view); - int ypos = con_data.lines - con_data.screen_view->ylen; - if (console_view->ypos != ypos) { - view_move (console_view, 0, ypos); + view_pos_t pos = View_GetPos (console_view); + int ypos = con_data.lines - screen_len.y; + if (pos.y != ypos) { + View_SetPos (console_view, pos.x, ypos); + View_UpdateHierarchy (console_view); } - say_line.view->visible = con_state == con_message ? !chat_team : 0; - team_line.view->visible = con_state == con_message ? chat_team : 0; - console_view->visible = con_data.lines != 0; - menu_view->visible = con_state == con_menu; + if (con_state == con_message) { + con_setcomponent (say_view, client_charbuff, &say_line.buffer); + con_input_t *inp = &say_line; + con_setcomponent (say_view, client_cursor, &inp); + } else { + con_remcomponent (say_view, client_charbuff); + con_remcomponent (say_view, client_cursor); + } + if (con_data.lines) { + con_setcomponent (command_view, client_charbuff, &cmd_line.buffer); + con_input_t *inp = &cmd_line; + con_setcomponent (command_view, client_cursor, &inp); + } else { + con_remcomponent (command_view, client_charbuff); + con_remcomponent (command_view, client_cursor); + } + if (con_data.dl_name && *con_data.dl_name->str) { + if (!download_buffer) { + view_pos_t len = View_GetLen (download_view); + download_buffer = Draw_CreateBuffer (len.x / 8, 1); + con_setcomponent (download_view, client_charbuff, &download_buffer); + } + update_download (); + } else if (download_buffer) { + Draw_DestroyBuffer (download_buffer); + con_remcomponent (download_view, client_charbuff); + } - con_data.view->draw (con_data.view); + draw_console (screen_view); } static void @@ -668,13 +790,13 @@ C_NewMap (void) static void C_GIB_HUD_Enable_f (void) { - hud_view->visible = 1; + //hud_view->visible = 1; } static void C_GIB_HUD_Disable_f (void) { - hud_view->visible = 0; + //hud_view->visible = 0; } static void @@ -690,14 +812,15 @@ exec_line (inputline_t *il) static void con_app_window (const IE_event_t *event) { - static int old_xlen; - static int old_ylen; + static int old_xlen = -1; + static int old_ylen = -1; if (old_xlen != event->app_window.xlen || old_ylen != event->app_window.ylen) { old_xlen = event->app_window.xlen; old_ylen = event->app_window.ylen; - view_resize (con_data.view, old_xlen, old_ylen); + View_SetLen (screen_view, old_xlen, old_ylen); + View_UpdateHierarchy (screen_view); } } @@ -723,9 +846,9 @@ con_key_event (const IE_event_t *event) #endif if (con_state == con_message) { if (chat_team) { - il = team_line.input_line; + il = team_input; } else { - il = say_line.input_line; + il = chat_input; } if (key->code == QFK_ESCAPE) { con_end_message (il); @@ -862,7 +985,9 @@ Condump_f (void) static void C_Init (void) { - view_t *view; + client_reg = ECS_NewRegistry (); + ECS_RegisterComponents (client_reg, client_components, client_comp_count); + client_reg->href_comp = client_href; #ifdef __QNXNTO__ setlocale (LC_ALL, "C-TRADITIONAL"); @@ -882,11 +1007,45 @@ C_Init (void) con_debuglog = COM_CheckParm ("-condebug"); // The console will get resized, so assume initial size is 320x200 - con_data.view = view_new (0, 0, 320, 200, grav_northeast); - console_view = view_new (0, 0, 320, 200, grav_northwest); - notify_view = view_new (8, 8, 312, NOTIFY_LINES * 8, grav_northwest); - menu_view = view_new (0, 0, 320, 200, grav_center); - hud_view = view_new (0, 0, 320, 200, grav_northeast); + screen_view = View_New (client_reg, nullview); + console_view = View_New (client_reg, screen_view); + buffer_view = View_New (client_reg, console_view); + command_view = View_New (client_reg, console_view); + download_view = View_New (client_reg, console_view); + notify_view = View_New (client_reg, screen_view); + say_view = View_New (client_reg, screen_view); + + View_SetGravity (screen_view, grav_northwest); + View_SetGravity (console_view, grav_northwest); + View_SetGravity (buffer_view, grav_southwest); + View_SetGravity (command_view, grav_southwest); + View_SetGravity (download_view, grav_southwest); + View_SetGravity (notify_view, grav_northwest); + View_SetGravity (say_view, grav_northwest); + + View_SetResize (screen_view, 1, 1); + View_SetResize (console_view, 1, 1); + View_SetResize (buffer_view, 1, 1); + View_SetResize (command_view, 1, 0); + View_SetResize (download_view, 1, 0); + View_SetResize (notify_view, 1, 0); + View_SetResize (say_view, 1, 0); + + View_SetPos (screen_view, 0, 0); + View_SetPos (console_view, 0, 0); + View_SetPos (buffer_view, 0, 24); + View_SetPos (command_view, 0, 0); + View_SetPos (download_view, 0, 2); + View_SetPos (notify_view, 8, 8); + View_SetPos (say_view, 0, 0); + + View_SetLen (screen_view, 320, 200); + View_SetLen (console_view, 320, 200); + View_SetLen (buffer_view, 320, 176); + View_SetLen (command_view, 320, 12); + View_SetLen (download_view, 320, 8); + View_SetLen (notify_view, 312, NOTIFY_LINES * 8); + View_SetLen (say_view, 320, 8); cmd_line.prompt = ""; cmd_line.input_line = Con_CreateInputLine (32, MAXCMDLINE, ']'); @@ -895,83 +1054,67 @@ C_Init (void) cmd_line.input_line->width = con_linewidth; cmd_line.input_line->user_data = &cmd_line; cmd_line.input_line->draw = input_line_draw; - cmd_line.view = view_new_data (0, 12, 320, 10, grav_southwest, &cmd_line); - cmd_line.view->draw = draw_input; - cmd_line.view->setgeometry = resize_input; - cmd_line.view->resize_x = 1; - view_add (console_view, cmd_line.view); say_line.prompt = "say:"; - say_line.input_line = Con_CreateInputLine (32, MAXCMDLINE, ' '); - say_line.input_line->complete = 0; - say_line.input_line->enter = C_Say; - say_line.input_line->width = con_linewidth - 5; - say_line.input_line->user_data = &say_line; - say_line.input_line->draw = input_line_draw; - say_line.view = view_new_data (0, 0, 320, 8, grav_northwest, &say_line); - say_line.view->draw = draw_input; - say_line.view->setgeometry = resize_input; - say_line.view->visible = 0; - say_line.view->resize_x = 1; - view_add (con_data.view, say_line.view); + chat_input = Con_CreateInputLine (32, MAXCMDLINE, ' '); + chat_input->complete = 0; + chat_input->enter = C_Say; + chat_input->width = con_linewidth - 5; + chat_input->user_data = &say_line; + chat_input->draw = input_line_draw; - team_line.prompt = "say_team:"; - team_line.input_line = Con_CreateInputLine (32, MAXCMDLINE, ' '); - team_line.input_line->complete = 0; - team_line.input_line->enter = C_SayTeam; - team_line.input_line->width = con_linewidth - 10; - team_line.input_line->user_data = &team_line; - team_line.input_line->draw = input_line_draw; - team_line.view = view_new_data (0, 0, 320, 8, grav_northwest, &team_line); - team_line.view->draw = draw_input; - team_line.view->setgeometry = resize_input; - team_line.view->visible = 0; - team_line.view->resize_x = 1; - view_add (con_data.view, team_line.view); + team_input = Con_CreateInputLine (32, MAXCMDLINE, ' '); + team_input->complete = 0; + team_input->enter = C_SayTeam; + team_input->width = con_linewidth - 10; + team_input->user_data = &say_line; + team_input->draw = input_line_draw; - view_add (con_data.view, notify_view); - view_add (con_data.view, hud_view); - view_add (con_data.view, console_view); - view_add (con_data.view, menu_view); + { + con_input_t *inp = &say_line; + con_setcomponent (say_view, client_input, &inp); + } + { + con_input_t *inp = &cmd_line; + con_setcomponent (command_view, client_input, &inp); + } - console_buffer = Draw_CreateBuffer (console_view->xlen / 8, - console_view->ylen / 8); + + view_pos_t len; + + len = View_GetLen (buffer_view); + console_buffer = Draw_CreateBuffer (len.x / 8, len.y / 8); Draw_ClearBuffer (console_buffer); + con_setcomponent (buffer_view, client_charbuff, &console_buffer); con_main = Con_CreateBuffer (CON_BUFFER_SIZE, CON_LINES); - console_view->draw = draw_console; - console_view->visible = 0; - console_view->resize_x = console_view->resize_y = 1; + len = View_GetLen (command_view); + cmd_line.buffer = Draw_CreateBuffer (len.x / 8, len.y / 8); + Draw_ClearBuffer (cmd_line.buffer); + con_setcomponent (command_view, client_charbuff, &cmd_line.buffer); - notify_buffer = Draw_CreateBuffer (notify_view->xlen / 8, NOTIFY_LINES + 1); + len = View_GetLen (notify_view); + notify_buffer = Draw_CreateBuffer (len.x / 8, NOTIFY_LINES + 1); Draw_ClearBuffer (notify_buffer); - notify_view->draw = draw_notify; - notify_view->setgeometry = resize_notify; - notify_view->resize_x = 1; + con_setcomponent (notify_view, client_charbuff, ¬ify_buffer); - menu_view->draw = Menu_Draw; - menu_view->visible = 0; + len = View_GetLen (say_view); + say_line.buffer = Draw_CreateBuffer (len.x / 8, len.y / 8); + Draw_ClearBuffer (say_line.buffer); - hud_view->draw = Menu_Draw_Hud; - hud_view->visible = 0; + View_UpdateHierarchy (screen_view); - view = view_new (8, 16, 320, 168, grav_southwest); - view->draw = draw_console_text; - view->setgeometry = resize_console_text; - view->resize_x = view->resize_y = 1; - view_add (console_view, view); - - view = view_new (0, 2, 320, 11, grav_southwest); - view->draw = draw_download; - view->resize_x = 1; - view_add (console_view, view); + // set onresize after View_UpdateHierarchy so the callbacks are NOT called + // during init + View_SetOnResize (buffer_view, resize_console_text); + View_SetOnResize (command_view, resize_input); + View_SetOnResize (download_view, resize_download); + View_SetOnResize (notify_view, resize_notify); + View_SetOnResize (say_view, resize_input); con = con_main; con_linewidth = -1; - - - Sys_Printf ("Console initialized.\n"); // register our commands diff --git a/libs/console/menu.c b/libs/console/menu.c index 093caf8d0..7f89626f7 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -679,8 +679,8 @@ Menu_Draw (view_t *view) if (!menu) return; - x = view->xabs; - y = view->yabs; + x = 0;//view->xabs; + y = 0;//view->yabs; if (menu->fadescreen) r_funcs->Draw_FadeScreen (); diff --git a/libs/console/server.c b/libs/console/server.c index 86a40230e..3e5771404 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -148,13 +148,16 @@ enum { static int use_curses = 1; -static view_t *output; -static view_t *status; -static view_t *input; +static view_t sv_view; +static view_t output; +static view_t status; +static view_t input; static int screen_x, screen_y; static volatile sig_atomic_t interrupted; static int batch_print; +static ecs_registry_t *server_reg; + #define MAXCMDLINE 256 #define BUFFER_SIZE 32768 @@ -211,6 +214,21 @@ static const byte attr_map[256] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, }; +static const component_t server_components[server_comp_count] = { + [server_href] = { + .size = sizeof (hierref_t), + .name = "href", + }, + [server_view] = { + .size = sizeof (sv_view_t), + .name = "sv_view", + }, + [server_window] = { + .size = sizeof (sv_view_t), + .name = "sv_window", + }, +}; + static inline void draw_fun_char (WINDOW *win, byte c, int blue) @@ -222,37 +240,45 @@ draw_fun_char (WINDOW *win, byte c, int blue) } static inline void -sv_refresh (view_t *view) +sv_refresh_windows (void) { - sv_view_t *sv_view = view->data; - wnoutrefresh ((WINDOW *) sv_view->win); + sv_view_t *window = server_reg->comp_pools[server_window].data; + uint32_t count = server_reg->comp_pools[server_window].count; + while (count-- > 0) { + wnoutrefresh ((WINDOW *) (window++)->win); + } + doupdate (); } static inline int -sv_getch (view_t *view) +sv_getch (view_t view) { - sv_view_t *sv_view = view->data; - return wgetch ((WINDOW *) sv_view->win); + sv_view_t *window = Ent_GetComponent (view.id, server_window, view.reg); + return wgetch ((WINDOW *) window->win); } static inline void -sv_draw (view_t *view) +sv_draw (view_t view) { - sv_view_t *sv_view = view->data; - if (sv_view->draw) - sv_view->draw (view); - wnoutrefresh ((WINDOW *) sv_view->win); + sv_view_t *window = Ent_GetComponent (view.id, server_window, view.reg); + if (window->draw) + window->draw (view); + wnoutrefresh ((WINDOW *) window->win); + doupdate (); } -static inline void -sv_setgeometry (view_t *view) +static void +sv_setgeometry (view_t view, view_pos_t foo) { - sv_view_t *sv_view = view->data; - WINDOW *win = sv_view->win; - wresize (win, view->ylen, view->xlen); - mvwin (win, view->yabs, view->xabs); - if (sv_view->setgeometry) - sv_view->setgeometry (view); + sv_view_t *window = Ent_GetComponent (view.id, server_window, view.reg); + WINDOW *win = window->win; + + view_pos_t pos = View_GetAbs (view); + view_pos_t len = View_GetLen (view); + wresize (win, len.y, len.x); + mvwin (win, pos.y, pos.x); + if (window->setgeometry) + window->setgeometry (view); } static void @@ -262,21 +288,20 @@ sv_complete (inputline_t *il) Con_BasicCompleteCommandLine (il); batch_print = 0; - sv_refresh (output); - sv_refresh (input); - doupdate (); + sv_refresh_windows (); } static void -draw_output (view_t *view) +draw_output (view_t view) { - sv_view_t *sv_view = view->data; - WINDOW *win = sv_view->win; - con_buffer_t *output_buffer = sv_view->obj; + sv_view_t *window = Ent_GetComponent (view.id, server_window, view.reg); + WINDOW *win = window->win; + con_buffer_t *output_buffer = window->obj; + view_pos_t len = View_GetLen (view); // this is not the most efficient way to update the screen, but oh well - int lines = view->ylen - 1; // leave a blank line - int width = view->xlen; + int lines = len.y - 1; // leave a blank line + int width = len.x; int cur_line = output_buffer->line_head - 1 + view_offset; int i, y; @@ -315,21 +340,28 @@ draw_output (view_t *view) } static void -draw_status (view_t *view) +draw_status (view_t view) { - sv_view_t *sv_view = view->data; - WINDOW *win = sv_view->win; - sv_sbar_t *sb = sv_view->obj; - int i; + sv_view_t *window = Ent_GetComponent (view.id, server_window, view.reg); + WINDOW *win = window->win; + sv_sbar_t *sb = window->obj; char *old = alloca (sb->width); memcpy (old, sb->text, sb->width); memset (sb->text, ' ', sb->width); - view_draw (view); + + ecs_pool_t *pool = &server_reg->comp_pools[server_view]; + sv_view_t *sv_view = pool->data; + for (uint32_t i = 0; i < pool->count; i++) { + view_t v = { .reg = view.reg, .id = pool->dense[i], + .comp = view.comp }; + (sv_view++)->draw (v); + } + if (memcmp (old, sb->text, sb->width)) { wbkgdset (win, COLOR_PAIR (CP_WHITE_BLUE)); wmove (win, 0, 0); - for (i = 0; i < sb->width; i++) + for (int i = 0; i < sb->width; i++) draw_fun_char (win, sb->text[i], 1); } } @@ -337,9 +369,9 @@ draw_status (view_t *view) static void draw_input_line (inputline_t *il) { - view_t *view = il->user_data; - sv_view_t *sv_view = view->data; - WINDOW *win = sv_view->win; + view_t view = *(view_t *) il->user_data; + sv_view_t *window = Ent_GetComponent (view.id, server_window, view.reg); + WINDOW *win = window->win; size_t i; const char *text; @@ -368,26 +400,28 @@ draw_input_line (inputline_t *il) } static void -draw_input (view_t *view) +draw_input (view_t view) { - sv_view_t *sv_view = view->data; - draw_input_line (sv_view->obj); + sv_view_t *window = Ent_GetComponent (view.id, server_window, view.reg); + draw_input_line (window->obj); } static void -setgeometry_input (view_t *view) +setgeometry_input (view_t view) { - sv_view_t *sv_view = view->data; - inputline_t *il = sv_view->obj; - il->width = view->xlen; + sv_view_t *window = Ent_GetComponent (view.id, server_window, view.reg); + view_pos_t len = View_GetLen (view); + inputline_t *il = window->obj; + il->width = len.x; } static void -setgeometry_status (view_t *view) +setgeometry_status (view_t view) { - sv_view_t *sv_view = view->data; - sv_sbar_t *sb = sv_view->obj; - sb->width = view->xlen; + sv_view_t *window = Ent_GetComponent (view.id, server_window, view.reg); + sv_sbar_t *sb = window->obj; + view_pos_t len = View_GetLen (view); + sb->width = len.x; sb->text = realloc (sb->text, sb->width); memset (sb->text, 0, sb->width); // force an update } @@ -427,8 +461,8 @@ process_input (void) Sys_MaskPrintf (SYS_dev, "resizing to %d x %d\n", screen_x, screen_y); resizeterm (screen_y, screen_x); con_linewidth = screen_x; - view_resize (sv_con_data.view, screen_x, screen_y); - sv_con_data.view->draw (sv_con_data.view); + View_SetLen (sv_view, screen_x, screen_y); + sv_refresh_windows (); #endif } @@ -524,15 +558,15 @@ static void key_event (knum_t key, short unicode, qboolean down) { int ovf = view_offset; - sv_view_t *sv_view; + sv_view_t *window; con_buffer_t *buffer; int num_lines; switch (key) { case QFK_PAGEUP: view_offset -= 10; - sv_view = output->data; - buffer = sv_view->obj; + window = Ent_GetComponent (output.id, server_window, output.reg); + buffer = window->obj; num_lines = (buffer->line_head - buffer->line_tail + buffer->max_lines) % buffer->max_lines; if (view_offset <= -(num_lines - (screen_y - 3))) @@ -551,54 +585,53 @@ key_event (knum_t key, short unicode, qboolean down) sv_draw (output); break; default: - sv_view = input->data; - Con_ProcessInputLine (sv_view->obj, key); - sv_refresh (input); + window = Ent_GetComponent (input.id, server_window, input.reg); + Con_ProcessInputLine (window->obj, key); + sv_refresh_windows (); break; } - doupdate (); } static void print (char *txt) { - sv_view_t *sv_view = output->data; - Con_BufferAddText (sv_view->obj, txt); + sv_view_t *window = Ent_GetComponent (output.id, server_window, + output.reg); + Con_BufferAddText (window->obj, txt); if (!view_offset) { while (*txt) - draw_fun_char (sv_view->win, (byte) *txt++, 0); + draw_fun_char (window->win, (byte) *txt++, 0); if (!batch_print) { - sv_refresh (output); - doupdate (); + sv_refresh_windows (); } } } -static view_t * -create_window (view_t *parent, int xpos, int ypos, int xlen, int ylen, - grav_t grav, void *obj, int opts, void (*draw) (view_t *), - void (*setgeometry) (view_t *)) +static view_t +create_window (view_t parent, int xpos, int ypos, int xlen, int ylen, + grav_t grav, void *obj, int opts, void (*draw) (view_t), + void (*setgeometry) (view_t)) { - view_t *view; - sv_view_t *sv_view; + view_t view = View_New (server_reg, parent); + View_SetPos (view, xpos, ypos); + View_SetLen (view, xlen, ylen); + View_SetGravity (view, grav); + View_SetResize (view, !!(opts & sv_resize_x), !!(opts & sv_resize_y)); + View_SetOnResize (view, sv_setgeometry); + View_SetOnMove (view, sv_setgeometry); - sv_view = calloc (1, sizeof (sv_view_t)); - sv_view->obj = obj; - sv_view->win = newwin (ylen, xlen, 0, 0); // will get moved when added - scrollok (sv_view->win, (opts & sv_scroll) ? TRUE : FALSE); - leaveok (sv_view->win, (opts & sv_cursor) ? FALSE : TRUE); - nodelay (sv_view->win, TRUE); - keypad (sv_view->win, TRUE); - sv_view->draw = draw; - sv_view->setgeometry = setgeometry; + sv_view_t window = { + .obj = obj, + .win = newwin (ylen, xlen, 0, 0), // will get moved when updated + .draw = draw, + .setgeometry = setgeometry, + }; + Ent_SetComponent (view.id, server_window, view.reg, &window); - view = view_new (xpos, ypos, xlen, ylen, grav); - view->data = sv_view; - view->draw = sv_draw; - view->setgeometry = sv_setgeometry; - view->resize_x = (opts & sv_resize_x) != 0; - view->resize_y = (opts & sv_resize_y) != 0; - view_add (parent, view); + scrollok (window.win, (opts & sv_scroll) ? TRUE : FALSE); + leaveok (window.win, (opts & sv_cursor) ? FALSE : TRUE); + nodelay (window.win, TRUE); + keypad (window.win, TRUE); return view; } @@ -610,14 +643,14 @@ exec_line (inputline_t *il) } static inputline_t * -create_input_line (int width) +create_input_line (int width, view_t *view) { inputline_t *input_line; input_line = Con_CreateInputLine (16, MAXCMDLINE, ']'); input_line->complete = sv_complete; input_line->enter = exec_line; - input_line->user_data = input; + input_line->user_data = view; input_line->draw = draw_input_line; input_line->width = width; @@ -640,28 +673,37 @@ init (void) nonl (); - get_size (&screen_x, &screen_y); - sv_con_data.view = view_new (0, 0, screen_x, screen_y, grav_northwest); + server_reg = ECS_NewRegistry (); + ECS_RegisterComponents (server_reg, server_components, server_comp_count); + server_reg->href_comp = server_href; - output = create_window (sv_con_data.view, + get_size (&screen_x, &screen_y); + + sv_view = View_New (server_reg, nullview); + View_SetPos (sv_view, 0, 0); + View_SetLen (sv_view, screen_x, screen_y); + View_SetGravity (sv_view, grav_northwest); + + output = create_window (sv_view, 0, 0, screen_x, screen_y - 2, grav_northwest, Con_CreateBuffer (BUFFER_SIZE, MAX_LINES), sv_resize_x | sv_resize_y | sv_scroll, draw_output, 0); - status = create_window (sv_con_data.view, + status = create_window (sv_view, 0, 1, screen_x, 1, grav_southwest, calloc (1, sizeof (sv_sbar_t)), sv_resize_x, draw_status, setgeometry_status); - sv_con_data.status_view = status; + sv_con_data.status_view = &status; - input = create_window (sv_con_data.view, + input = create_window (sv_view, 0, 0, screen_x, 1, grav_southwest, - create_input_line (screen_x), + create_input_line (screen_x, &input), sv_resize_x | sv_cursor, draw_input, setgeometry_input); - ((inputline_t *) ((sv_view_t *) input->data)->obj)->user_data = input; + + View_UpdateHierarchy (sv_view); init_pair (CP_YELLOW_BLACK, COLOR_YELLOW, COLOR_BLACK); init_pair (CP_GREEN_BLACK, COLOR_GREEN, COLOR_BLACK); @@ -678,7 +720,6 @@ init (void) con_linewidth = screen_x; - sv_con_data.view->draw (sv_con_data.view); wrefresh (curscr); } #endif @@ -799,8 +840,8 @@ C_DrawConsole (void) { // only the status bar is drawn because the inputline and output views // take care of themselves - if (sv_con_data.status_view) - sv_con_data.status_view->draw (sv_con_data.status_view); + draw_status (status); + sv_refresh_windows (); } static void diff --git a/libs/ui/test/Makemodule.am b/libs/ui/test/Makemodule.am index 4e9465a20..70972e981 100644 --- a/libs/ui/test/Makemodule.am +++ b/libs/ui/test/Makemodule.am @@ -1,13 +1,17 @@ libs_ui_tests = \ - libs/ui/test/test-flow \ - libs/ui/test/test-flow-size \ libs/ui/test/test-passage \ libs/ui/test/test-txtbuffer \ libs/ui/test/test-vrect -TESTS += $(libs_ui_tests) +libs_ui_xfail_tests = \ + libs/ui/test/test-flow \ + libs/ui/test/test-flow-size -check_PROGRAMS += $(libs_ui_tests) +TESTS += $(libs_ui_tests) $(libs_ui_xfail_tests) + +XFAIL_TESTS += $(libs_ui_xfail_tests) + +check_PROGRAMS += $(libs_ui_tests) $(libs_ui_xfail_tests) libs_ui_test_test_flow_SOURCES=libs/ui/test/test-flow.c libs_ui_test_test_flow_LDADD=libs/ui/libQFui.la diff --git a/libs/ui/test/test-flow-size.c b/libs/ui/test/test-flow-size.c index e37a2d44d..88e304653 100644 --- a/libs/ui/test/test-flow-size.c +++ b/libs/ui/test/test-flow-size.c @@ -4,7 +4,7 @@ #include #include "QF/ui/view.h" - +#if 0 typedef struct { struct { int xlen, ylen; @@ -283,3 +283,11 @@ main (void) } return ret; } +#endif + +int +main (void) +{ + printf ("FIXME: redo for ECS\n"); + return 1; +} diff --git a/libs/ui/test/test-flow.c b/libs/ui/test/test-flow.c index 3861e5ed0..520331857 100644 --- a/libs/ui/test/test-flow.c +++ b/libs/ui/test/test-flow.c @@ -4,7 +4,7 @@ #include #include "QF/ui/view.h" - +#if 0 typedef struct { struct { int xlen, ylen; @@ -282,3 +282,11 @@ main (void) } return ret; } +#endif + +int +main (void) +{ + printf ("FIXME: redo for ECS\n"); + return 1; +} diff --git a/libs/ui/view.c b/libs/ui/view.c index 411d13802..27b2d73c7 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -41,6 +41,8 @@ #include "QF/cexpr.h" #include "QF/mathlib.h" + +#define IMPLEMENT_VIEW_Funcs #include "QF/ui/view.h" static exprenum_t grav_t_enum; @@ -81,6 +83,211 @@ static exprenum_t grav_t_enum = { &grav_t_symtab, }; +static void +view_modified_init (void *_modified) +{ + byte *modified = _modified; + *modified = 1; +} + +static const component_t view_components[view_type_count] = { + [view_pos] = { + .size = sizeof (view_pos_t), + .name = "pos", + }, + [view_len] = { + .size = sizeof (view_pos_t), + .name = "len", + }, + [view_abs] = { + .size = sizeof (view_pos_t), + .name = "abs", + }, + [view_rel] = { + .size = sizeof (view_pos_t), + .name = "rel", + }, + [view_oldlen] = { + .size = sizeof (view_pos_t), + .name = "oldlen", + }, + [view_control] = { + .size = sizeof (viewcont_t), + .name = "control", + }, + [view_modified] = { + .size = sizeof (byte), + .create = view_modified_init, + .name = "modified", + }, + [view_onresize] = { + .size = sizeof (view_resize_f), + .name = "onresize", + }, + [view_onmove] = { + .size = sizeof (view_move_f), + .name = "onmove", + }, +}; + +static const hierarchy_type_t view_type = { + .num_components = view_type_count, + .components = view_components, +}; + +view_t +View_New (ecs_registry_t *reg, view_t parent) +{ + uint32_t view = ECS_NewEntity (reg); + hierref_t *ref = Ent_AddComponent (view, reg->href_comp, reg); + + if (parent.reg && parent.id != nullent) { + hierref_t *pref = View_GetRef (parent); + ref->hierarchy = pref->hierarchy; + ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, 0, + pref->index, 0); + } else { + ref->hierarchy = Hierarchy_New (reg, &view_type, 1); + ref->index = 0; + } + ref->hierarchy->ent[ref->index] = view; + return (view_t) { .reg = reg, .id = view, .comp = reg->href_comp }; +} + +void +View_UpdateHierarchy (view_t view) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + + byte *modified = h->components[view_modified]; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *len = h->components[view_len]; + view_pos_t *abs = h->components[view_abs]; + view_pos_t *rel = h->components[view_rel]; + view_pos_t *oldlen = h->components[view_oldlen]; + viewcont_t *cont = h->components[view_control]; + view_resize_f *onresize = h->components[view_onresize]; + view_resize_f *onmove = h->components[view_onmove]; + uint32_t *parent = h->parentIndex; + uint32_t *id = h->ent; + + if (abs[0].x != pos[0].x || abs[0].y != pos[0].y) { + modified[0] = 1; + abs[0] = pos[0]; + rel[0] = pos[0]; + } + for (uint32_t i = 1; i < h->num_objects; i++) { + uint32_t par = parent[i]; + if (!(modified[i] & 2) && (modified[par] & 2) + && (cont[i].resize_x || cont[i].resize_y)) { + int dx = len[par].x - oldlen[par].x; + int dy = len[par].y - oldlen[par].y; + if (cont[i].resize_x) { + len[i].x += dx; + } + if (cont[i].resize_y) { + len[i].y += dy; + } + modified[i] |= 2; + } + if (modified[i] || modified[par]) { + switch (cont[i].gravity) { + case grav_center: + rel[i].x = pos[i].x + (len[par].x - len[i].x) / 2; + rel[i].y = pos[i].y + (len[par].y - len[i].y) / 2; + break; + case grav_north: + rel[i].x = pos[i].x + (len[par].x - len[i].x) / 2; + rel[i].y = pos[i].y; + break; + case grav_northeast: + rel[i].x = len[par].x - pos[i].x - len[i].x; + rel[i].y = pos[i].y; + break; + case grav_east: + rel[i].x = len[par].x - pos[i].x - len[i].x; + rel[i].y = pos[i].y + (len[par].y - len[i].y) / 2; + break; + case grav_southeast: + rel[i].x = len[par].x - pos[i].x - len[i].x; + rel[i].y = len[par].y - pos[i].y - len[i].y; + break; + case grav_south: + rel[i].x = pos[i].x + (len[par].x - len[i].x) / 2; + rel[i].y = len[par].y - pos[i].y - len[i].y; + break; + case grav_southwest: + rel[i].x = pos[i].x; + rel[i].y = len[par].y - pos[i].y - len[i].y; + break; + case grav_west: + rel[i].x = pos[i].x; + rel[i].y = pos[i].y + (len[par].y - len[i].y) / 2; + break; + case grav_northwest: + rel[i].x = pos[i].x; + rel[i].y = pos[i].y; + break; + case grav_flow: + break; + } + abs[i].x = abs[par].x + rel[i].x; + abs[i].y = abs[par].y + rel[i].y; + } + } + for (uint32_t i = 0; i < h->num_objects; i++) { + if ((modified[i] & 2) && onresize[i]) { + view_t v = { .reg = view.reg, .id = id[i], .comp = view.comp }; + onresize[i] (v, len[i]); + } + if (modified[i] & 2) { + oldlen[i] = len[i]; + } + if ((modified[i] & 1) && onmove[i]) { + view_t v = { .reg = view.reg, .id = id[i], .comp = view.comp }; + onresize[i] (v, abs[i]); + } + modified[i] = 0; + } +} + +void +View_SetParent (view_t view, view_t parent) +{ + if (parent.reg && parent.id != nullent) { + __auto_type ref = View_GetRef (view); + __auto_type vref = *ref; + __auto_type pref = View_GetRef (parent); + ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, + vref.hierarchy, + pref->index, vref.index); + ref->hierarchy = pref->hierarchy; + Hierarchy_RemoveHierarchy (vref.hierarchy, vref.index); + if (!vref.hierarchy->num_objects) { + Hierarchy_Delete (vref.hierarchy); + } + } else { + __auto_type ref = View_GetRef (view); + __auto_type vref = *ref; + if (!vref.index) { + return; + } + ref->hierarchy = Hierarchy_New (view.reg, &view_type, 0); + Hierarchy_InsertHierarchy (ref->hierarchy, vref.hierarchy, nullent, + vref.index); + Hierarchy_RemoveHierarchy (vref.hierarchy, vref.index); + if (!vref.hierarchy->num_objects) { + Hierarchy_Delete (vref.hierarchy); + } + } + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + byte *modified = h->components[view_modified]; + modified[ref->index] = 1; + View_UpdateHierarchy (view); +} +#if 0 static void setgeometry (view_t *view) { @@ -525,3 +732,4 @@ view_flow_up_left (view_t *view) { flow_up (view, set_columns_left); } +#endif diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index ff2aee694..c42736210 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -50,7 +50,7 @@ int graphval; Performance monitoring tool */ void -R_TimeGraph (view_t *view) +R_TimeGraph (view_pos_t abs) { static int timex; int a; @@ -78,14 +78,14 @@ R_TimeGraph (view_t *view) a = 0; } memcpy (timings + o, r_timings + a, l * sizeof (timings[0])); - r_funcs->R_LineGraph (view->xabs, view->yabs, r_timings, - MAX_TIMINGS, 200);//r_data->graphheight->int_val); + r_funcs->R_LineGraph (abs.x, abs.y, r_timings, MAX_TIMINGS, 200); + //r_data->graphheight->int_val); timex = (timex + 1) % MAX_TIMINGS; } void -R_ZGraph (view_t *view) +R_ZGraph (view_pos_t abs) { int w; static int height[256]; @@ -97,6 +97,5 @@ R_ZGraph (view_t *view) height[r_framecount & 255] = ((int) r_refdef.frame.position[2]) & 31; - r_funcs->R_LineGraph (view->xabs, view->yabs, height, - w, *r_data->graphheight); + r_funcs->R_LineGraph (abs.x, abs.y, height, w, *r_data->graphheight); } diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 0dcd89afe..fdcdcc9d8 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -174,13 +174,8 @@ SCR_SetFOV (float fov) static void SCR_CalcRefdef (void) { - view_t *view = r_data->scr_view; - const vrect_t *rect = &r_data->refdef->vrect; - r_data->vid->recalc_refdef = 0; - view_setgeometry (view, rect->x, rect->y, rect->width, rect->height); - // force a background redraw r_data->scr_fullupdate = 0; r_funcs->bind_framebuffer (0); @@ -317,7 +312,7 @@ SCR_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) } } r_funcs->set_2d (0); - view_draw (r_data->scr_view); + //view_draw (r_data->scr_view); r_funcs->set_2d (1); while (*scr_funcs) { (*scr_funcs) (); @@ -453,8 +448,8 @@ vidsize_listener (void *data, const viddef_t *vdef) void SCR_Init (void) { - r_data->scr_view->xlen = r_data->vid->width; - r_data->scr_view->ylen = r_data->vid->height; + //r_data->scr_view->xlen = r_data->vid->width; + //r_data->scr_view->ylen = r_data->vid->height; // register our commands Cmd_AddCommand ("screenshot", ScreenShot_f, "Take a screenshot, " diff --git a/libs/video/renderer/r_text.c b/libs/video/renderer/r_text.c index ac2cd3a9d..2d39ebbf0 100644 --- a/libs/video/renderer/r_text.c +++ b/libs/video/renderer/r_text.c @@ -46,6 +46,7 @@ RText_NewShaper (rfont_t *font) rshaper_t *shaper = malloc (sizeof (rshaper_t)); shaper->rfont = font; shaper->font = hb_ft_font_create (font->face, 0); + hb_ft_font_set_funcs (shaper->font); shaper->buffer = hb_buffer_create (); shaper->features = (r_hb_featureset_t) DARRAY_STATIC_INIT (4); diff --git a/libs/video/renderer/sw/d_scan.c b/libs/video/renderer/sw/d_scan.c index bb3151500..7b2a2b1d8 100644 --- a/libs/video/renderer/sw/d_scan.c +++ b/libs/video/renderer/sw/d_scan.c @@ -53,10 +53,10 @@ D_WarpScreen (framebuffer_t *src) sw_framebuffer_t *buffer = src->buffer; int w, h; int u, v; - int scr_x = vr_data.scr_view->xpos; - int scr_y = vr_data.scr_view->ypos; - int scr_w = vr_data.scr_view->xlen; - int scr_h = vr_data.scr_view->ylen; + int scr_x = vr_data.refdef->vrect.x; + int scr_y = vr_data.refdef->vrect.y; + int scr_w = vr_data.refdef->vrect.width; + int scr_h = vr_data.refdef->vrect.height; byte *dest; int *turb; int *col; diff --git a/libs/video/renderer/vid_common.c b/libs/video/renderer/vid_common.c index 189c25cc6..52bc8ca06 100644 --- a/libs/video/renderer/vid_common.c +++ b/libs/video/renderer/vid_common.c @@ -39,12 +39,10 @@ #include "r_internal.h" viddef_t vid; // global video state -view_t scr_view; vid_render_data_t vid_render_data = { .vid = &vid, .refdef = &r_refdef, - .scr_view = &scr_view, .scr_copytop = 0, .scr_copyeverything = 0, .scr_fullupdate = 0, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 2ac60f9d6..5e4c7a31f 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -208,10 +208,10 @@ sw_end_frame (void) vrect.height = vid.height - vr_data.lineadj; vrect.next = 0; } else { - vrect.x = vr_data.scr_view->xpos; - vrect.y = vr_data.scr_view->ypos; - vrect.width = vr_data.scr_view->xlen; - vrect.height = vr_data.scr_view->ylen; + vrect.x = vr_data.refdef->vrect.x; + vrect.y = vr_data.refdef->vrect.y; + vrect.width = vr_data.refdef->vrect.width; + vrect.height = vr_data.refdef->vrect.height; vrect.next = 0; } sw_ctx->update (sw_ctx, &vrect); diff --git a/nq/include/client.h b/nq/include/client.h index 42a522aba..d9e7ed7d3 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -289,7 +289,7 @@ extern qboolean recording; struct cvar_s; void Cvar_Info (void *data, const struct cvar_s *cvar); -extern struct view_s *cl_screen_view; +extern struct view_s cl_screen_view; void CL_Init_Screen (void); void CL_UpdateScreen (double realtime); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 300bcfa23..fc258161f 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -583,11 +583,11 @@ CL_ParseClientdata (void) i = MSG_ReadLong (net_message); if (cl.stats[STAT_ITEMS] != i) { // set flash times - Sbar_Changed (); for (j = 0; j < 32; j++) if ((i & (1 << j)) && !(cl.stats[STAT_ITEMS] & (1 << j))) cl.item_gettime[j] = cl.time; cl.stats[STAT_ITEMS] = i; + Sbar_Changed (sbc_items); #define IT_POWER (IT_QUAD | IT_SUIT | IT_INVULNERABILITY | IT_INVISIBILITY) cl.viewstate.powerup_index = (cl.stats[STAT_ITEMS] & IT_POWER) >> 19; } @@ -607,7 +607,7 @@ CL_ParseClientdata (void) i = 0; if (cl.stats[STAT_ARMOR] != i) { cl.stats[STAT_ARMOR] = i; - Sbar_Changed (); + Sbar_Changed (sbc_armor); } if (bits & SU_WEAPON) @@ -616,27 +616,27 @@ CL_ParseClientdata (void) i = 0; if (cl.stats[STAT_WEAPON] != i) { cl.stats[STAT_WEAPON] = i; - Sbar_Changed (); cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]]; + Sbar_Changed (sbc_weapon); } i = (short) MSG_ReadShort (net_message); if (cl.stats[STAT_HEALTH] != i) { cl.stats[STAT_HEALTH] = i; - Sbar_Changed (); + Sbar_Changed (sbc_health); } i = MSG_ReadByte (net_message); if (cl.stats[STAT_AMMO] != i) { cl.stats[STAT_AMMO] = i; - Sbar_Changed (); + Sbar_Changed (sbc_ammo); } for (i = 0; i < 4; i++) { j = MSG_ReadByte (net_message); if (cl.stats[STAT_SHELLS + i] != j) { cl.stats[STAT_SHELLS + i] = j; - Sbar_Changed (); + Sbar_Changed (sbc_ammo); } } @@ -645,13 +645,13 @@ CL_ParseClientdata (void) if (standard_quake) { if (cl.stats[STAT_ACTIVEWEAPON] != i) { cl.stats[STAT_ACTIVEWEAPON] = i; - Sbar_Changed (); + Sbar_Changed (sbc_weapon); } } else { // hipnotic/rogue weapon "bit field" (stupid idea) if (cl.stats[STAT_ACTIVEWEAPON] != (1 << i)) { cl.stats[STAT_ACTIVEWEAPON] = (1 << i); - Sbar_Changed (); + Sbar_Changed (sbc_weapon); } } @@ -872,7 +872,7 @@ CL_ParseServerMessage (void) break; case svc_updatename: - Sbar_Changed (); + Sbar_Changed (sbc_info); i = MSG_ReadByte (net_message); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatename > " @@ -882,7 +882,7 @@ CL_ParseServerMessage (void) break; case svc_updatefrags: - Sbar_Changed (); + Sbar_Changed (sbc_frags); i = MSG_ReadByte (net_message); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatefrags > " @@ -900,7 +900,7 @@ CL_ParseServerMessage (void) break; case svc_updatecolors: - Sbar_Changed (); + Sbar_Changed (sbc_info); i = MSG_ReadByte (net_message); if (i >= cl.maxclients) { Host_Error ("CL_ParseServerMessage: svc_updatecolors > " diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index c906b153f..ba77f1b31 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -55,6 +55,7 @@ #include "r_local.h" //FIXME for r_cache_thrash +#include "client/hud.h" #include "client/world.h" #include "nq/include/client.h" @@ -87,27 +88,14 @@ static cvar_t scr_showturtle_cvar = { .value = { .type = &cexpr_int, .value = &scr_showturtle }, }; -view_t *cl_screen_view; -static view_t *net_view; -static view_t *timegraph_view; -static view_t *zgraph_view; -static view_t *loading_view; - -static qpic_t *scr_ram; -static qpic_t *scr_turtle; - -static void -draw_pic (view_t *view) -{ - r_funcs->Draw_Pic (view->xabs, view->yabs, view->data); -} - -static void -draw_cachepic (view_t *view) -{ - qpic_t *pic = r_funcs->Draw_CachePic (view->data, 1); - r_funcs->Draw_Pic (view->xabs, view->yabs, pic); -} +view_t cl_screen_view; +static view_t net_view; +static view_t timegraph_view; +static view_t zgraph_view; +static view_t loading_view; +static view_t ram_view; +static view_t turtle_view; +static view_t pause_view; static void SCR_CShift (void) @@ -125,75 +113,36 @@ SCR_CShift (void) r_funcs->Draw_BlendScreen (cl.viewstate.cshift_color); } -static void -SCR_DrawRam (void) -{ - if (!scr_showram) - return; - - if (!r_cache_thrash) - return; - - r_funcs->Draw_Pic (cl_screen_view->xpos + 32, cl_screen_view->ypos, - scr_ram); -} - -static void -SCR_DrawTurtle (void) -{ - static int count; - - if (!scr_showturtle) - return; - - if (r_data->frametime < 0.1) { - count = 0; - return; - } - - count++; - if (count < 3) - return; - - r_funcs->Draw_Pic (cl_screen_view->xpos, cl_screen_view->ypos, - scr_turtle); -} - -static void -SCR_DrawPause (void) -{ - qpic_t *pic; - - if (!scr_showpause) // turn off for screenshots - return; - - if (!r_data->paused) - return; - - pic = r_funcs->Draw_CachePic ("gfx/pause.lmp", true); - r_funcs->Draw_Pic ((cl_screen_view->xlen - pic->width) / 2, - (cl_screen_view->ylen - 48 - pic->height) / 2, - pic); -} - static void scr_draw_views (void) { - net_view->visible = (!cls.demoplayback - && realtime - cl.last_servermessage >= 0.3); - loading_view->visible = cl.loading; - timegraph_view->visible = r_timegraph; - zgraph_view->visible = r_zgraph; + if (scr_showturtle) { + static int count; + if (r_data->frametime < 0.1) { + count = 0; + } else { + count++; + } + View_SetVisible (turtle_view, count > 2); + } + + // turn off for screenshots + View_SetVisible (pause_view, scr_showpause && r_data->paused); + + View_SetVisible (ram_view, scr_showram && r_cache_thrash); + View_SetVisible (net_view, + (!cls.demoplayback && realtime - cl.last_servermessage >= 0.3)); + View_SetVisible (loading_view, cl.loading); + // FIXME cvar callbacks + View_SetVisible (timegraph_view, r_timegraph); + View_SetVisible (zgraph_view, r_zgraph); - view_draw (cl_screen_view); } static SCR_Func scr_funcs_normal[] = { 0, //Draw_Crosshair, - SCR_DrawRam, - SCR_DrawTurtle, - SCR_DrawPause, Sbar_Draw, + HUD_Draw_Views, SCR_CShift, Sbar_DrawCenterPrint, scr_draw_views, @@ -219,45 +168,90 @@ static SCR_Func *scr_funcs[] = { scr_funcs_finale, }; +static void +cl_vidsize_listener (void *data, const viddef_t *vdef) +{ + View_SetLen (cl_screen_view, vdef->width, vdef->height); + View_UpdateHierarchy (cl_screen_view); +} + void CL_Init_Screen (void) { qpic_t *pic; - cl_screen_view = r_data->scr_view; - con_module->data->console->screen_view = cl_screen_view; + VID_OnVidResize_AddListener (cl_vidsize_listener, 0); - scr_ram = r_funcs->Draw_PicFromWad ("ram"); - scr_turtle = r_funcs->Draw_PicFromWad ("turtle"); + HUD_Init (); + + cl_screen_view = View_New (hud_registry, nullview); + con_module->data->console->screen_view = &cl_screen_view; + + View_SetPos (cl_screen_view, 0, 0); + View_SetLen (cl_screen_view, viddef.width, viddef.height); + View_SetGravity (cl_screen_view, grav_northwest); + View_SetVisible (cl_screen_view, 1); + + pic = r_funcs->Draw_PicFromWad ("ram"); + ram_view = View_New (hud_registry, cl_screen_view); + View_SetPos (ram_view, 32, 0); + View_SetLen (ram_view, pic->width, pic->height); + View_SetGravity (ram_view, grav_northwest); + Ent_SetComponent (ram_view.id, hud_pic, ram_view.reg, &pic); + View_SetVisible (ram_view, 0); + + pic = r_funcs->Draw_PicFromWad ("turtle"); + turtle_view = View_New (hud_registry, cl_screen_view); + View_SetPos (turtle_view, 32, 0); + View_SetLen (turtle_view, pic->width, pic->height); + View_SetGravity (turtle_view, grav_northwest); + Ent_SetComponent (turtle_view.id, hud_pic, turtle_view.reg, &pic); + View_SetVisible (turtle_view, 0); Cvar_Register (&scr_showpause_cvar, 0, 0); Cvar_Register (&scr_showram_cvar, 0, 0); Cvar_Register (&scr_showturtle_cvar, 0, 0); pic = r_funcs->Draw_PicFromWad ("net"); - net_view = view_new (64, 0, pic->width, pic->height, grav_northwest); - net_view->draw = draw_pic; - net_view->data = pic; - net_view->visible = 0; - view_add (cl_screen_view, net_view); + net_view = View_New (hud_registry, cl_screen_view); + View_SetPos (net_view, 64, 0); + View_SetLen (net_view, pic->width, pic->height); + View_SetGravity (net_view, grav_northwest); + Ent_SetComponent (net_view.id, hud_pic, net_view.reg, &pic); + View_SetVisible (net_view, 0); - timegraph_view = view_new (0, 0, cl_screen_view->xlen, 100, grav_southwest); - timegraph_view->draw = R_TimeGraph; - timegraph_view->visible = 0; - view_add (cl_screen_view, timegraph_view); + timegraph_view = View_New (hud_registry, cl_screen_view); + View_SetPos (timegraph_view, 0, 0); + View_SetLen (timegraph_view, r_data->vid->width, 100); + View_SetGravity (timegraph_view, grav_southwest); + Ent_SetComponent (timegraph_view.id, hud_func, timegraph_view.reg, + R_TimeGraph); + View_SetVisible (timegraph_view, r_timegraph); - zgraph_view = view_new (0, 0, cl_screen_view->xlen, 100, grav_southwest); - zgraph_view->draw = R_ZGraph; - zgraph_view->visible = 0; - view_add (cl_screen_view, zgraph_view); + zgraph_view = View_New (hud_registry, cl_screen_view); + View_SetPos (zgraph_view, 0, 0); + View_SetLen (zgraph_view, r_data->vid->width, 100); + View_SetGravity (zgraph_view, grav_southwest); + Ent_SetComponent (zgraph_view.id, hud_func, zgraph_view.reg, R_ZGraph); + View_SetVisible (zgraph_view, r_zgraph); const char *name = "gfx/loading.lmp"; pic = r_funcs->Draw_CachePic (name, 1); - loading_view = view_new (0, -24, pic->width, pic->height, grav_center); - loading_view->draw = draw_cachepic; - loading_view->data = (void *) name; - loading_view->visible = 0; - view_add (cl_screen_view, loading_view); + loading_view = View_New (hud_registry, cl_screen_view); + View_SetPos (loading_view, 0, -24); + View_SetLen (loading_view, pic->width, pic->height); + View_SetGravity (loading_view, grav_center); + Ent_SetComponent (loading_view.id, hud_cachepic, loading_view.reg, &name); + View_SetVisible (loading_view, 0); + + name = "gfx/pause.lmp"; + pic = r_funcs->Draw_CachePic (name, 1); + pause_view = View_New (hud_registry, cl_screen_view); + View_SetPos (pause_view, 0, -24); + View_SetLen (pause_view, pic->width, pic->height); + View_SetGravity (pause_view, grav_center); + Ent_SetComponent (pause_view.id, hud_cachepic, pause_view.reg, &name); + View_SetVisible (pause_view, 0); } void diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 15b0351b3..1ea8f9093 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -64,8 +64,60 @@ #include "nq/include/server.h" int sb_updates; // if >= vid.numpages, no update needed +static int sb_update_flags; static int sb_view_size; +static view_t sbar_main; +static view_t sbar_inventory; +static view_t sbar_frags; +static view_t sbar_sigils; +static view_t sbar_items; +static view_t sbar_armament; +static view_t sbar_weapons; +static view_t sbar_miniammo; +static view_t sbar_statusbar; +static view_t sbar_armor; +static view_t sbar_face; +static view_t sbar_health; +static view_t sbar_ammo; +//static view_t sbar_status; +static view_t sbar_tile[2]; + +static view_t +sbar_view (int x, int y, int w, int h, grav_t gravity, view_t parent) +{ + view_t view = View_New (hud_registry, parent); + View_SetPos (view, x, y); + View_SetLen (view, w, h); + View_SetGravity (view, gravity); + View_SetVisible (view, 1); + return view; +} + +static inline void +sbar_setcomponent (view_t view, uint32_t comp, void *data) +{ + Ent_SetComponent (view.id, comp, view.reg, data); +} + +static inline int +sbar_hascomponent (view_t view, uint32_t comp) +{ + return Ent_HasComponent (view.id, comp, view.reg); +} + +static inline void * +sbar_getcomponent (view_t view, uint32_t comp) +{ + return Ent_GetComponent (view.id, comp, view.reg); +} + +static inline void +sbar_remcomponent (view_t view, uint32_t comp) +{ + Ent_RemoveComponent (view.id, comp, view.reg); +} + #define STAT_MINUS 10 // num frame for '-' stats digit qpic_t *sb_nums[2][11]; @@ -137,8 +189,7 @@ viewsize_f (int view_size) } } - -static int +static int __attribute__((used)) Sbar_ColorForMap (int m) { return (bound (0, m, 13) * 16) + 8; @@ -162,79 +213,18 @@ Sbar_DontShowScores (void) } void -Sbar_Changed (void) +Sbar_Changed (sbar_changed change) { + sb_update_flags |= 1 << change; sb_updates = 0; // update next frame } static void -draw_pic (view_t *view, int x, int y, qpic_t *pic) -{ - r_funcs->Draw_Pic (view->xabs + x, view->yabs + y, pic); -} - -static inline void -draw_cachepic (view_t *view, int x, int y, const char *name, int cent) -{ - qpic_t *pic = r_funcs->Draw_CachePic (name, true); - if (cent) - x += (view->xlen - pic->width) / 2; - r_funcs->Draw_Pic (view->xabs + x, view->yabs + y, pic); -} - -static inline void -draw_subpic (view_t *view, int x, int y, qpic_t *pic, - int srcx, int srcy, int width, int height) -{ - r_funcs->Draw_SubPic (view->xabs + x, view->yabs + y, pic, - srcx, srcy, width, height); -} - -static inline void -draw_transpic (view_t *view, int x, int y, qpic_t *pic) -{ - r_funcs->Draw_Pic (view->xabs + x, view->yabs + y, pic); -} - - -// drawing routines are reletive to the status bar location - -static inline void -draw_character (view_t *view, int x, int y, int c) -{ - r_funcs->Draw_Character (view->xabs + x, view->yabs + y, c); -} - -static inline void -draw_string (view_t *view, int x, int y, const char *str) -{ - r_funcs->Draw_String (view->xabs + x, view->yabs + y, str); -} -#if 0 -static inline void -draw_altstring (view_t *view, int x, int y, const char *str) -{ - r_funcs->Draw_AltString (view->xabs + x, view->yabs + y, str); -} -#endif -static inline void -draw_nstring (view_t *view, int x, int y, const char *str, int n) -{ - r_funcs->Draw_nString (view->xabs + x, view->yabs + y, str, n); -} - -static inline void -draw_fill (view_t *view, int x, int y, int w, int h, int col) -{ - r_funcs->Draw_Fill (view->xabs + x, view->yabs + y, w, h, col); -} - -static void -draw_num (view_t *view, int x, int y, int num, int digits, int color) +draw_num (view_t *view, int num, int digits, int color) { char str[12]; char *ptr; - int l, frame; + int l, frame, x = 0; if (num > 999999999) num = 999999999; @@ -243,8 +233,10 @@ draw_num (view_t *view, int x, int y, int num, int digits, int color) ptr = str; if (l > digits) ptr += (l - digits); - if (l < digits) - x += (digits - l) * 24; + while (digits > l) { + sbar_remcomponent (view[x++], hud_pic); + digits--; + } while (*ptr) { if (*ptr == '-') @@ -252,65 +244,66 @@ draw_num (view_t *view, int x, int y, int num, int digits, int color) else frame = *ptr - '0'; - draw_transpic (view, x, y, sb_nums[color][frame]); - x += 24; + sbar_setcomponent (view[x++], hud_pic, &sb_nums[color][frame]); ptr++; } } static inline void -draw_smallnum (view_t *view, int x, int y, int n, int packed, int colored) +draw_smallnum (view_t view, int x, int y, int n, int packed, int colored) { - char num[12]; + void *comp = sbar_getcomponent (view, hud_charbuff); + __auto_type charbuff = *(draw_charbuffer_t **) comp; + char num[4]; packed = packed != 0; // ensure 0 or 1 - if (n > 999) - n = 999; - + n = bound (-99, n, 999); snprintf (num, sizeof (num), "%3d", n); - if (colored) { - if (num[0] != ' ') - num[0] = 18 + num[0] - '0'; - if (num[1] != ' ') - num[1] = 18 + num[1] - '0'; - if (num[2] != ' ') - num[2] = 18 + num[2] - '0'; + for (int i = 0; i < 3; i++) { + charbuff->chars[i] = num[i] - (colored && num[i] != ' ' ? '0' - 18 : 0); } - draw_character (view, x + packed, y, num[0]); - draw_character (view, x + 8, y, num[1]); - draw_character (view, x + 16 - packed, y, num[2]); } static void -draw_tile (view_t *view) -{ - r_funcs->Draw_TileClear (view->xabs, view->yabs, view->xlen, view->ylen); -} - -static void -draw_ammo_sbar (view_t *view) +draw_miniammo (view_t view) { int i, count; // ammo counts for (i = 0; i < 4; i++) { + view_t v = View_GetChild (view, i); count = cl.stats[STAT_SHELLS + i]; - draw_smallnum (view, (6 * i + 1) * 8 + 2, 0, count, 0, 1); + draw_smallnum (v, (6 * i + 1) * 8 + 2, 0, count, 0, 1); } } static void -draw_ammo_hud (view_t *view) +draw_ammo (view_t view) { - int i, count; + qpic_t *pic = 0; + if (cl.stats[STAT_ITEMS] & IT_SHELLS) + pic = sb_ammo[0]; + else if (cl.stats[STAT_ITEMS] & IT_NAILS) + pic = sb_ammo[1]; + else if (cl.stats[STAT_ITEMS] & IT_ROCKETS) + pic = sb_ammo[2]; + else if (cl.stats[STAT_ITEMS] & IT_CELLS) + pic = sb_ammo[3]; - // ammo counts - for (i = 0; i < 4; i++) { - count = cl.stats[STAT_SHELLS + i]; - draw_subpic (view, 0, i * 11, sb_ibar, 3 + (i * 48), 0, 42, 11); - draw_smallnum (view, 7, i * 11, count, 0, 1); + view_t ammo = View_GetChild (view, 0); + if (pic) { + sbar_setcomponent (ammo, hud_pic, &pic); + } else { + sbar_remcomponent (ammo, hud_pic); } + + view_t num[3] = { + View_GetChild (view, 1), + View_GetChild (view, 2), + View_GetChild (view, 3), + }; + draw_num (num, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); } static int @@ -332,46 +325,33 @@ calc_flashon (float time, int mask) } static void -draw_weapons_sbar (view_t *view) +draw_weapons_sbar (view_t view) { int flashon, i; for (i = 0; i < 7; i++) { + view_t weap = View_GetChild (view, i); if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); - draw_pic (view, i * 24, 0, sb_weapons[flashon][i]); if (flashon > 1) sb_updates = 0; // force update to remove flash + sbar_setcomponent (weap, hud_pic, &sb_weapons[flashon][i]); + } else { + sbar_remcomponent (weap, hud_pic); } } } static void -draw_weapons_hud (view_t *view) +draw_items (view_t view) { - int flashon, i, x = 0; + //float time; + //int flashon = 0, i; - if (view->parent->gravity == grav_southeast) - x = view->xlen - 24; - - for (i = cl_screen_view->ylen < 204; i < 7; i++) { - if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { - flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); - draw_subpic (view, x, i * 16, sb_weapons[flashon][i], 0, 0, 24, 16); - if (flashon > 1) - sb_updates = 0; // force update to remove flash - } - } -} - -static void -draw_items (view_t *view) -{ - float time; - int flashon = 0, i; - - for (i = 0; i < 6; i++) { + for (int i = 0; i < 6; i++) { + view_t item = View_GetChild (view, i); if (cl.stats[STAT_ITEMS] & (1 << (17 + i))) { +#if 0 time = cl.item_gettime[17 + i]; if (time && time > cl.time - 2 && flashon) { // Flash frame sb_updates = 0; @@ -380,18 +360,24 @@ draw_items (view_t *view) } if (time && time > cl.time - 2) sb_updates = 0; +#endif + sbar_setcomponent (item, hud_pic, &sb_items[i]); + } else { + sbar_remcomponent (item, hud_pic); } } } static void -draw_sigils (view_t *view) +draw_sigils (view_t view) { - float time; - int flashon = 0, i; + //float time; + //int flashon = 0, i; - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { + view_t sigil = View_GetChild (view, i); if (cl.stats[STAT_ITEMS] & (1 << (28 + i))) { +#if 0 time = cl.item_gettime[28 + i]; if (time && time > cl.time - 2 && flashon) { // flash frame sb_updates = 0; @@ -400,17 +386,14 @@ draw_sigils (view_t *view) } if (time && time > cl.time - 2) sb_updates = 0; +#endif + sbar_setcomponent (sigil, hud_pic, &sb_sigil[i]); + } else { + sbar_remcomponent (sigil, hud_pic); } } } -static void -draw_inventory_sbar (view_t *view) -{ - draw_pic (view, 0, 0, sb_ibar); - view_draw (view); -} - typedef struct { char team[16 + 1]; int frags; @@ -428,7 +411,7 @@ int scoreboardcount[MAX_SCOREBOARD]; int scoreboardlines, scoreboardteams; -static void +static void __attribute__((used)) Sbar_SortFrags (void) { int i, j, k; @@ -454,7 +437,7 @@ Sbar_SortFrags (void) } } -static void +static void __attribute__((used)) Sbar_SortTeams (void) { char t[16 + 1]; @@ -520,9 +503,10 @@ Sbar_SortTeams (void) } } -static void +static void __attribute__((used)) draw_solo (view_t *view) { +#if 0 char str[80]; int minutes, seconds; int l; @@ -547,11 +531,13 @@ draw_solo (view_t *view) l = strlen (cl.levelname); l = 232 - l * 4; draw_string (view, max (l, 152), 12, cl.levelname); +#endif } static void -draw_frags (view_t *view) +draw_frags (view_t view) { +#if 0 int i, k, l, p = -1; int top, bottom; int x; @@ -591,11 +577,13 @@ draw_frags (view_t *view) draw_character (view, p * 32, 0, 16); draw_character (view, p * 32 + 26, 0, 17); } +#endif } static void -draw_face (view_t *view) +draw_face (view_t view) { +#if 0 int f, anim; if ((cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY)) @@ -627,53 +615,44 @@ draw_face (view_t *view) } else anim = 0; draw_pic (view, 112, 0, sb_faces[f][anim]); -} - -static void -draw_status_bar (view_t *view) -{ - draw_pic (view, 0, 0, sb_sbar); +#endif } static inline void -draw_armor (view_t *view) +draw_armor (view_t view) { + view_t armor = View_GetChild (view, 0); + view_t num[3] = { + View_GetChild (view, 1), + View_GetChild (view, 2), + View_GetChild (view, 3), + }; if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { - draw_num (view, 24, 0, 666, 3, 1); + draw_num (num, 666, 3, 1); } else { - draw_num (view, 24, 0, cl.stats[STAT_ARMOR], 3, - cl.stats[STAT_ARMOR] <= 25); + draw_num (num, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25); if (cl.stats[STAT_ITEMS] & IT_ARMOR3) - draw_pic (view, 0, 0, sb_armor[2]); + sbar_setcomponent (armor, hud_pic, &sb_armor[2]); else if (cl.stats[STAT_ITEMS] & IT_ARMOR2) - draw_pic (view, 0, 0, sb_armor[1]); + sbar_setcomponent (armor, hud_pic, &sb_armor[1]); else if (cl.stats[STAT_ITEMS] & IT_ARMOR1) - draw_pic (view, 0, 0, sb_armor[0]); + sbar_setcomponent (armor, hud_pic, &sb_armor[0]); + else + sbar_remcomponent (armor, hud_pic); } } static inline void -draw_health (view_t *view) +draw_health (view_t view) { - draw_num (view, 136, 0, cl.stats[STAT_HEALTH], 3, - cl.stats[STAT_HEALTH] <= 25); + view_t num[3] = { + View_GetChild (view, 0), + View_GetChild (view, 1), + View_GetChild (view, 2), + }; + draw_num (num, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25); } - -static inline void -draw_ammo (view_t *view) -{ - if (cl.stats[STAT_ITEMS] & IT_SHELLS) - draw_pic (view, 224, 0, sb_ammo[0]); - else if (cl.stats[STAT_ITEMS] & IT_NAILS) - draw_pic (view, 224, 0, sb_ammo[1]); - else if (cl.stats[STAT_ITEMS] & IT_ROCKETS) - draw_pic (view, 224, 0, sb_ammo[2]); - else if (cl.stats[STAT_ITEMS] & IT_CELLS) - draw_pic (view, 224, 0, sb_ammo[3]); - - draw_num (view, 248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); -} - +#if 0 static void draw_status (view_t *view) { @@ -682,15 +661,16 @@ draw_status (view_t *view) return; } - draw_armor (view); - draw_face (view); - draw_health (view); - draw_ammo (view); + draw_armor (sbar_status_armor); + draw_face (sbar_status_face); + draw_health (sbar_status_health); + draw_ammo (sbar_status_ammo); } - -static void +#endif +static void __attribute__((used)) draw_rogue_weapons_sbar (view_t *view) { +#if 0 int i; draw_weapons_sbar (view); @@ -703,11 +683,13 @@ draw_rogue_weapons_sbar (view_t *view) } } } +#endif } -static void +static void __attribute__((used)) draw_rogue_weapons_hud (view_t *view) { +#if 0 int flashon, i, j; qpic_t *pic; @@ -728,11 +710,13 @@ draw_rogue_weapons_hud (view_t *view) sb_updates = 0; // force update to remove flash } } +#endif } -static void +static void __attribute__((used)) draw_rogue_ammo_hud (view_t *view) { +#if 0 int i, count; qpic_t *pic; @@ -746,11 +730,13 @@ draw_rogue_ammo_hud (view_t *view) draw_subpic (view, 0, i * 11, pic, 3 + (i * 48), 0, 42, 11); draw_smallnum (view, 7, i * 11, count, 0, 1); } +#endif } -static void +static void __attribute__((used)) draw_rogue_items (view_t *view) { +#if 0 int i; float time; @@ -764,22 +750,26 @@ draw_rogue_items (view_t *view) sb_updates = 0; } } +#endif } -static void +static void __attribute__((used)) draw_rogue_inventory_sbar (view_t *view) { +#if 0 if (cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) draw_pic (view, 0, 0, rsb_invbar[0]); else draw_pic (view, 0, 0, rsb_invbar[1]); view_draw (view); +#endif } -static void +static void __attribute__((used)) draw_rogue_face (view_t *view) { +#if 0 int top, bottom; player_info_t *s; @@ -795,11 +785,13 @@ draw_rogue_face (view_t *view) draw_fill (view, 113, 12, 22, 9, bottom); draw_smallnum (view, 108, 3, s->frags, 1, top == 8); +#endif } -static void +static void __attribute__((used)) draw_rogue_status (view_t *view) { +#if 0 if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { draw_solo (view); return; @@ -837,11 +829,13 @@ draw_rogue_status (view_t *view) else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS) draw_pic (view, 224, 0, rsb_ammo[2]); draw_num (view, 248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); +#endif } -static void +static void __attribute__((used)) draw_hipnotic_weapons_sbar (view_t *view) { +#if 0 static int x[] = {0, 24, 48, 72, 96, 120, 144, 176, 200, 96}; static int h[] = {0, 1, 3}; int flashon, i; @@ -876,11 +870,13 @@ draw_hipnotic_weapons_sbar (view_t *view) sb_updates = 0; // force update to remove flash } } +#endif } -static void +static void __attribute__((used)) draw_hipnotic_weapons_hud (view_t *view) { +#if 0 int flashon, i; static int y[] = {0, 16, 32, 48, 64, 96, 112, 128, 144, 80}; static int h[] = {0, 1, 3}; @@ -911,11 +907,13 @@ draw_hipnotic_weapons_hud (view_t *view) sb_updates = 0; // force update to remove flash } } +#endif } -static void +static void __attribute__((used)) draw_hipnotic_items (view_t *view) { +#if 0 int i; float time; @@ -938,18 +936,22 @@ draw_hipnotic_items (view_t *view) sb_updates = 0; } } +#endif } -static void +static void __attribute__((used)) draw_hipnotic_inventory_sbar (view_t *view) { +#if 0 draw_pic (view, 0, 0, sb_ibar); view_draw (view); +#endif } -static void +static void __attribute__((used)) draw_hipnotic_status (view_t *view) { +#if 0 if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { draw_solo (view); return; @@ -964,11 +966,13 @@ draw_hipnotic_status (view_t *view) draw_pic (view, 209, 3, sb_items[0]); if (cl.stats[STAT_ITEMS] & IT_KEY2) draw_pic (view, 209, 12, sb_items[1]); +#endif } static void sbar_update_vis (void) { +#if 0 qboolean headsup; if (r_data->scr_copyeverything) @@ -998,21 +1002,13 @@ sbar_update_vis (void) r_data->scr_copyeverything = 1; sb_updates++; -} - -void -Sbar_Draw (void) -{ - if (cls.state != ca_active) { - return; - } - sbar_update_vis (); - hud_main_view->draw (hud_main_view); +#endif } static void Sbar_DeathmatchOverlay (view_t *view) { +#if 0 int i, k, l; int top, bottom; int x, y; @@ -1054,14 +1050,17 @@ Sbar_DeathmatchOverlay (view_t *view) y += 10; } +#endif } static void Sbar_DrawScoreboard (void) { +#if 0 //Sbar_SoloScoreboard (); if (cl.gametype == GAME_DEATHMATCH) Sbar_DeathmatchOverlay (hud_overlay_view); +#endif } static void @@ -1075,6 +1074,7 @@ draw_overlay (view_t *view) static void draw_time (view_t *view) { +#if 0 struct tm *local = 0; time_t utc = 0; char st[80]; //FIXME: overflow @@ -1099,11 +1099,13 @@ draw_time (view_t *view) strftime (st, sizeof (st), HOUR12":%M "PM, local); draw_string (view, 8, 0, st); } +#endif } static void draw_fps (view_t *view) { +#if 0 static char st[80]; double t; static double lastframetime; @@ -1117,6 +1119,7 @@ draw_fps (view_t *view) snprintf (st, sizeof (st), "%5.1f FPS", lastfps); } draw_string (view, 80, 8, st); +#endif } static void @@ -1131,6 +1134,7 @@ draw_stuff (view_t *view) static void draw_intermission (view_t *view) { +#if 0 int dig; int num; @@ -1156,11 +1160,13 @@ draw_intermission (view_t *view) draw_num (view, 160, 144, cl.stats[STAT_MONSTERS], 3, 0); draw_pic (view, 232, 144, sb_slash); draw_num (view, 240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0); +#endif } void Sbar_IntermissionOverlay (void) { +#if 0 r_data->scr_copyeverything = 1; r_data->scr_fullupdate = 0; @@ -1169,6 +1175,7 @@ Sbar_IntermissionOverlay (void) return; } draw_intermission (hud_overlay_view); +#endif } /* CENTER PRINTING */ @@ -1205,8 +1212,9 @@ Sbar_CenterPrint (const char *str) } static void -Sbar_DrawCenterString (view_t *view, int remaining) +Sbar_DrawCenterString (view_t view, int remaining) { +#if 0 const char *start; int j, l, x, y; @@ -1237,11 +1245,13 @@ Sbar_DrawCenterString (view_t *view, int remaining) break; start++; // skip the \n } while (1); +#endif } void Sbar_FinaleOverlay (void) { +#if 0 int remaining; r_data->scr_copyeverything = 1; @@ -1250,6 +1260,7 @@ Sbar_FinaleOverlay (void) // the finale prints the characters one at a time remaining = scr_printspeed * (realtime - centertime_start); Sbar_DrawCenterString (hud_overlay_view, remaining); +#endif } void @@ -1274,6 +1285,7 @@ Sbar_DrawCenterPrint (void) static void draw_minifrags (view_t *view) { +#if 0 int numlines, top, bottom, f, i, k, x, y; char num[20]; player_info_t *s; @@ -1343,11 +1355,13 @@ draw_minifrags (view_t *view) draw_nstring (view, x + 48, y, s->name->value, 16); y += 8; } +#endif } static void draw_miniteam (view_t *view) { +#if 0 int i, k, x, y; char num[12]; info_key_t *player_team = cl.players[cl.playernum].team; @@ -1376,68 +1390,179 @@ draw_miniteam (view_t *view) y += 8; } +#endif +} + +void +Sbar_Draw (void) +{ + if (cls.state != ca_active) { + return; + } + sb_update_flags = ~0; + if (sb_update_flags & (1 << sbc_ammo)) { + draw_miniammo (sbar_miniammo); + draw_ammo (sbar_ammo); + } + if (sb_update_flags & (1 << sbc_armor)) draw_armor (sbar_armor); + if (sb_update_flags & (1 << sbc_frags)) draw_frags (sbar_frags); + if (sb_update_flags & (1 << sbc_health)) draw_health (sbar_health); + if (sb_update_flags & (1 << sbc_info)) { + draw_miniteam (0); + draw_minifrags (0); + draw_stuff (0); + draw_overlay (0); + draw_intermission (0); + Sbar_DeathmatchOverlay (0); + sbar_update_vis (); + } + if (sb_update_flags & (1 << sbc_items)) { + draw_items (sbar_items); + draw_sigils (sbar_items); + } + if (sb_update_flags & (1 << sbc_weapon)) draw_weapons_sbar (sbar_weapons); + if (sb_update_flags & ((1 << sbc_health) | (1 << sbc_items))) { + draw_face (sbar_face); + } +#if 0 + sbar_update_vis (); + hud_main_view->draw (hud_main_view); +#endif + sb_update_flags = 0; +} + +static void +sbar_hud_swap_f (void *data, const cvar_t *cvar) +{ + if (hud_sbar) { + return; + } +} + +static void +sbar_hud_sbar_f (void *data, const cvar_t *cvar) +{ + view_t v; + if (hud_swap) { + View_SetParent (sbar_armament, hud_view); + View_SetPos (sbar_armament, 0, 48); + View_SetLen (sbar_armament, 42, 156); + View_SetGravity (sbar_armament, + hud_swap ? grav_southwest : grav_southeast); + + View_SetLen (sbar_weapons, 24, 112); + View_SetGravity (sbar_weapons, + hud_swap ? grav_northwest : grav_northeast); + + View_SetLen (sbar_miniammo, 42, 44); + View_SetGravity (sbar_weapons, grav_southeast); + + for (int i = 0; i < 7; i++) { + v = View_GetChild (sbar_weapons, i); + View_SetPos (v, 0, i * 16); + View_SetLen (v, 24, 16); + if (sbar_hascomponent (v, hud_subpic)) { + hud_subpic_t subpic = { + sbar_getcomponent (v, hud_pic), 0, 0, 24, 16 + }; + sbar_setcomponent (v, hud_subpic, &subpic); + sbar_remcomponent (v, hud_pic); + } + } + for (int i = 0; i < 4; i++) { + v = View_GetChild (sbar_miniammo, i); + View_SetPos (v, 0, i * 11); + View_SetLen (v, 42, 11); + hud_subpic_t subpic = { sb_ibar, 3 + (i * 48), 0, 42, 11 }; + sbar_setcomponent (v, hud_subpic, &subpic); + } + } else { + View_SetParent (sbar_armament, sbar_inventory); + View_SetPos (sbar_armament, 0, 0); + View_SetLen (sbar_armament, 202, 24); + View_SetGravity (sbar_armament, grav_northwest); + + View_SetLen (sbar_weapons, 32, 192); + View_SetGravity (sbar_weapons, grav_southwest); + + View_SetLen (sbar_miniammo, 42, 44); + View_SetGravity (sbar_weapons, grav_southeast); + + for (int i = 0; i < 7; i++) { + v = View_GetChild (sbar_weapons, i); + View_SetPos (v, i * 24, 0); + View_SetLen (v, 24 + 24 * (i == 6), 16); + + if (sbar_hascomponent (v, hud_subpic)) { + hud_subpic_t *subpic = sbar_getcomponent(v, hud_subpic); + sbar_setcomponent (v, hud_pic, &subpic->pic); + sbar_remcomponent (v, hud_subpic); + } + } + } } static void init_sbar_views (void) { - view_t *view; + sbar_main = sbar_view ( 0, 0, 320, 48, grav_south, cl_screen_view); + sbar_inventory = sbar_view ( 0, 0, 320, 24, grav_northwest, sbar_main); + sbar_frags = sbar_view ( 0, 0, 130, 8, grav_northeast, sbar_inventory); + sbar_sigils = sbar_view ( 0, 0, 32, 16, grav_southeast, sbar_inventory); + sbar_items = sbar_view (32, 0, 96, 16, grav_southeast, sbar_inventory); + sbar_armament = sbar_view ( 0, 0, 202, 24, grav_northwest, sbar_inventory); + sbar_weapons = sbar_view ( 0, 0, 192, 16, grav_southwest, sbar_armament); + sbar_miniammo = sbar_view ( 0, 0, 32, 8, grav_northwest, sbar_armament); + sbar_statusbar = sbar_view ( 0, 0, 320, 24, grav_southwest, sbar_main); + sbar_armor = sbar_view ( 0, 0, 96, 24, grav_northwest, sbar_statusbar); + sbar_face = sbar_view (112, 0, 24, 24, grav_northwest, sbar_statusbar); + sbar_health = sbar_view (136, 0, 72, 24, grav_northwest, sbar_statusbar); + sbar_ammo = sbar_view (224, 0, 96, 24, grav_northwest, sbar_statusbar); + sbar_tile[0] = sbar_view ( 0, 0, 0, 48, grav_southwest, sbar_main); + sbar_tile[1] = sbar_view ( 0, 0, 0, 48, grav_southeast, sbar_main); - sbar_view = view_new (0, 0, 320, 48, grav_south); + View_SetResize (sbar_main, 1, 1); - sbar_frags_view = view_new (0, 0, 130, 8, grav_northeast); - sbar_frags_view->draw = draw_frags; + for (int i = 0; i < 4; i++) { + sbar_view (i * 8, 0, 8, 16, grav_northwest, sbar_sigils); - sbar_inventory_view = view_new (0, 0, 320, 24, grav_northwest); - sbar_inventory_view->draw = draw_inventory_sbar; + sbar_view (i * 24, 0, 24, 24, grav_northwest, sbar_armor); + sbar_view (i * 24, 0, 24, 24, grav_northwest, sbar_ammo); + } + for (int i = 0; i < 6; i++) { + sbar_view (i * 16, 0, 16, 16, grav_northwest, sbar_items); + } + for (int i = 0; i < 7; i++) { + sbar_view (i * 24, 0, 24, 16, grav_northwest, sbar_weapons); + } + for (int i = 0; i < 4; i++) { + sbar_view (i * 24, 0, 24, 16, grav_northwest, sbar_health); + } + for (int i = 0; i < 4; i++) { + view_t v = sbar_view (i * 48 + 10, 0, 8, 8, grav_northwest, + sbar_miniammo); + draw_charbuffer_t *buffer = Draw_CreateBuffer (3, 1); + sbar_setcomponent (v, hud_charbuff, &buffer); + } - view = view_new (0, 0, 32, 16, grav_southwest); - view->draw = draw_weapons_sbar; - view_add (sbar_inventory_view, view); + sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar); + sbar_setcomponent (sbar_statusbar, hud_pic, &sb_sbar); - view = view_new (0, 0, 32, 8, grav_northwest); - view->draw = draw_ammo_sbar; - view_add (sbar_inventory_view, view); - - view = view_new (32, 0, 96, 16, grav_southeast); - view->draw = draw_items; - view_add (sbar_inventory_view, view); - - view = view_new (0, 0, 32, 16, grav_southeast); - view->draw = draw_sigils; - view_add (sbar_inventory_view, view); - - if (sbar_frags_view) - view_add (sbar_inventory_view, sbar_frags_view); - - view_add (sbar_view, sbar_inventory_view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_status_bar; - view_add (sbar_view, view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_status; - view_add (sbar_view, view); - - if (cl_screen_view->xlen > 320) { - int l = (cl_screen_view->xlen - 320) / 2; - - view = view_new (-l, 0, l, 48, grav_southwest); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); - - view = view_new (-l, 0, l, 48, grav_southeast); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); + if (r_data->vid->width > 320) { + int l = (r_data->vid->width - 320) / 2; + View_SetPos (sbar_tile[0], -l, 0); + View_SetLen (sbar_tile[0], l, 48); + View_SetPos (sbar_tile[1], -l, 0); + View_SetLen (sbar_tile[1], l, 48); + sbar_setcomponent (sbar_tile[0], hud_tile, 0); + sbar_setcomponent (sbar_tile[1], hud_tile, 0); } } static void init_hud_views (void) { +#if 0 view_t *view; view_t *minifrags_view = 0; view_t *miniteam_view = 0; @@ -1507,11 +1632,13 @@ init_hud_views (void) view_add (hud_view, hud_armament_view); view_insert (hud_main_view, hud_view, 0); +#endif } static void init_hipnotic_sbar_views (void) { +#if 0 view_t *view; sbar_view = view_new (0, 0, 320, 48, grav_south); @@ -1564,11 +1691,13 @@ init_hipnotic_sbar_views (void) view->resize_y = 1; view_add (sbar_view, view); } +#endif } static void init_hipnotic_hud_views (void) { +#if 0 view_t *view; hud_view = view_new (0, 0, 320, 48, grav_south); @@ -1618,11 +1747,13 @@ init_hipnotic_hud_views (void) view_add (hud_view, hud_armament_view); view_insert (hud_main_view, hud_view, 0); +#endif } static void init_rogue_sbar_views (void) { +#if 0 view_t *view; sbar_view = view_new (0, 0, 320, 48, grav_south); @@ -1671,11 +1802,13 @@ init_rogue_sbar_views (void) view->resize_y = 1; view_add (sbar_view, view); } +#endif } static void init_rogue_hud_views (void) { +#if 0 view_t *view; hud_view = view_new (0, 0, 320, 48, grav_south); @@ -1716,11 +1849,13 @@ init_rogue_hud_views (void) view_add (hud_view, hud_armament_view); view_insert (hud_main_view, hud_view, 0); +#endif } static void init_views (void) { +#if 0 hud_main_view = view_new (0, 0, cl_screen_view->xlen, cl_screen_view->ylen, grav_northwest); view_insert (cl_screen_view, hud_main_view, 0); @@ -1740,7 +1875,7 @@ init_views (void) view_insert (hud_main_view, hud_overlay_view, 0); view_insert (hud_main_view, hud_stuff_view, 0); - +#endif if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) { init_hipnotic_sbar_views (); init_hipnotic_hud_views (); @@ -1762,14 +1897,10 @@ Sbar_GIB_Print_Center_f (void) Sbar_CenterPrint (GIB_Argv(1)); } -void -Sbar_Init (void) +static void +load_pics (void) { - int i; - - init_views (); - - for (i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) { sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); sb_nums[1][i] = r_funcs->Draw_PicFromWad (va (0, "anum_%i", i)); } @@ -1796,7 +1927,7 @@ Sbar_Init (void) sb_weapons[1][5] = r_funcs->Draw_PicFromWad ("inv2_srlaunch"); sb_weapons[1][6] = r_funcs->Draw_PicFromWad ("inv2_lightng"); - for (i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) { sb_weapons[2 + i][0] = r_funcs->Draw_PicFromWad (va (0, "inva%i_shotgun", i + 1)); sb_weapons[2 + i][1] = @@ -1873,7 +2004,7 @@ Sbar_Init (void) hsb_weapons[1][3] = r_funcs->Draw_PicFromWad ("inv2_prox_gren"); hsb_weapons[1][4] = r_funcs->Draw_PicFromWad ("inv2_prox"); - for (i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) { hsb_weapons[2 + i][0] = r_funcs->Draw_PicFromWad (va (0, "inva%i_laser", i + 1)); hsb_weapons[2 + i][1] = @@ -1912,9 +2043,20 @@ Sbar_Init (void) rsb_ammo[1] = r_funcs->Draw_PicFromWad ("r_ammomulti"); rsb_ammo[2] = r_funcs->Draw_PicFromWad ("r_ammoplasma"); } +} + +void +Sbar_Init (void) +{ + HUD_Init_Cvars (); + Cvar_AddListener (Cvar_FindVar ("hud_sbar"), sbar_hud_sbar_f, 0); + Cvar_AddListener (Cvar_FindVar ("hud_swap"), sbar_hud_swap_f, 0); + + load_pics (); + init_views (); + View_UpdateHierarchy (sbar_main); r_data->viewsize_callback = viewsize_f; - HUD_Init_Cvars (); Cvar_Register (&scr_centertime_cvar, 0, 0); Cvar_Register (&scr_printspeed_cvar, 0, 0); diff --git a/qtv/source/sbar.c b/qtv/source/sbar.c index 468a046b7..4100f11bb 100644 --- a/qtv/source/sbar.c +++ b/qtv/source/sbar.c @@ -45,50 +45,62 @@ #include "qtv/include/qtv.h" static void -draw_clients (view_t *view) +draw_clients (view_t view) { - sv_view_t *sv_view = view->data; + sv_view_t *sv_view = Ent_GetComponent (view.id, server_view, view.reg); sv_sbar_t *sb = sv_view->obj; + view_pos_t rel = View_GetRel (view); const char *str; const char *s; char *d; str = va (0, "[CL: %3d]", client_count); - for (s = str, d = sb->text + view->xrel; *s; s++) + for (s = str, d = sb->text + rel.x; *s; s++) *d++ = *s; } static void -draw_servers (view_t *view) +draw_servers (view_t view) { - sv_view_t *sv_view = view->data; + sv_view_t *sv_view = Ent_GetComponent (view.id, server_view, view.reg); sv_sbar_t *sb = sv_view->obj; + view_pos_t rel = View_GetRel (view); const char *str; const char *s; char *d; str = va (0, "[SV: %2d]", server_count); - for (s = str, d = sb->text + view->xrel; *s; s++) + for (s = str, d = sb->text + rel.x; *s; s++) *d++ = *s; } void qtv_sbar_init (void) { - view_t *status; - view_t *view; + view_t status; + view_t view; if (!con_module || !con_module->data->console->status_view) return; - status = con_module->data->console->status_view; - view = view_new (0, 0, 8, 1, grav_northwest); - view->draw = draw_servers; - view->data = status->data; - view_add (status, view); + status = *con_module->data->console->status_view; + void *comp = Ent_GetComponent (status.id, server_window, status.reg); + sv_view_t sv_view = *(sv_view_t *) comp; + sv_view.setgeometry = 0; - view = view_new (8, 0, 9, 1, grav_northwest); - view->draw = draw_clients; - view->data = status->data; - view_add (status, view); + view = View_New (status.reg, status); + View_SetPos (view, 0, 0); + View_SetLen (view, 8, 1); + View_SetGravity (view, grav_northwest); + sv_view.draw = draw_servers; + Ent_SetComponent (view.id, server_view, view.reg, &sv_view); + + view = View_New (status.reg, status); + View_SetPos (view, 8, 0); + View_SetLen (view, 9, 1); + View_SetGravity (view, grav_northwest); + sv_view.draw = draw_clients; + Ent_SetComponent (view.id, server_view, view.reg, &sv_view); + + View_UpdateHierarchy (status); } diff --git a/qw/include/client.h b/qw/include/client.h index d0f694c9b..0e125312d 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -297,11 +297,11 @@ extern struct cbuf_s *cl_stbuf; struct cvar_s; void Cvar_Info (void *data, const struct cvar_s *cvar); -extern struct view_s *cl_netgraph_view; -void CL_NetGraph (struct view_s *view); +extern struct view_s cl_netgraph_view; +void CL_NetGraph (struct view_s view); void CL_NetGraph_Init_Cvars (void); -extern struct view_s *cl_screen_view; +extern struct view_s cl_screen_view; void CL_Init_Screen (void); void CL_UpdateScreen (double realtime); diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index b730011d8..53b7e706a 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -199,7 +199,7 @@ Cam_Unlock (void) } autocam = CAM_NONE; locked = false; - Sbar_Changed (); + Sbar_Changed (~0); } } @@ -221,7 +221,7 @@ Cam_Lock (int playernum) last_lock = realtime; cam_forceview = true; locked = false; - Sbar_Changed (); + Sbar_Changed (~0); } static trace_t diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index fb60fe0c8..06fb9fc1d 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -84,13 +84,13 @@ static cvar_t cl_netgraph_height_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &cl_netgraph_height }, }; -view_t *cl_netgraph_view; +view_t cl_netgraph_view; static void cl_netgraph_f (void *data, const cvar_t *cvar) { - if (cl_netgraph_view) { - cl_netgraph_view->visible = cl_netgraph != 0; + if (View_Valid (cl_netgraph_view)) { + View_SetVisible (cl_netgraph_view, cl_netgraph != 0); } } @@ -98,34 +98,34 @@ static void cl_netgraph_height_f (void *data, const cvar_t *cvar) { cl_netgraph_height = max (32, cl_netgraph_height); - if (cl_netgraph_view) { - view_resize (cl_netgraph_view, cl_netgraph_view->xlen, - cl_netgraph_height + 25); + if (View_Valid (cl_netgraph_view)) { + view_pos_t len = View_GetLen (cl_netgraph_view); + View_SetLen (cl_netgraph_view, len.x, cl_netgraph_height + 25); + View_UpdateHierarchy (cl_netgraph_view); } } void -CL_NetGraph (view_t *view) +CL_NetGraph (view_t view) { int lost, a, l, x, y, i, o; int timings[NET_TIMINGS]; - - x = view->xabs; - y = view->yabs; + view_pos_t abs = View_GetAbs (view); + view_pos_t len = View_GetLen (view); if (cl_netgraph_box) { - r_funcs->Draw_TextBox (x, y, NET_TIMINGS / 8, + r_funcs->Draw_TextBox (abs.x, abs.y, NET_TIMINGS / 8, cl_netgraph_height / 8 + 1, cl_netgraph_alpha * 255); } lost = CL_CalcNet (); - x = view->xabs + 8; - y = view->yabs + view->ylen - 9; + x = abs.x + 8; + y = abs.y + len.y - 9; l = NET_TIMINGS; - if (l > view->xlen - 8) - l = view->xlen - 8; + if (l > len.x - 8) + l = len.x - 8; i = cls.netchan.outgoing_sequence & NET_TIMINGSMASK; a = i - l; o = 0; @@ -140,9 +140,15 @@ CL_NetGraph (view_t *view) r_funcs->R_LineGraph (x, y, timings, NET_TIMINGS, cl_netgraph_height); - x = view->xabs + 8; - y = view->yabs + 8; + x = abs.x + 8; + y = abs.y + 8; r_funcs->Draw_String (x, y, va (0, "%3i%% packet loss", lost)); +/* + //FIXME don't do every frame + view_move (cl_netgraph_view, cl_netgraph_view->xpos, hud_sb_lines); + view_setgravity (cl_netgraph_view, + hud_swap ? grav_southeast : grav_southwest); +*/ } void diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 027e5e9e4..da83589df 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1031,7 +1031,7 @@ CL_ProcessUserInfo (int slot, player_info_t *player) player->skinname->value); player->skin = mod_funcs->Skin_SetColormap (player->skin, slot + 1); - Sbar_Changed (); + Sbar_Changed (sbc_info); } static void @@ -1150,13 +1150,13 @@ CL_SetStat (int stat, int value) return; } - Sbar_Changed (); + Sbar_Changed (~0); switch (stat) { case STAT_ITEMS: - Sbar_Changed (); #define IT_POWER (IT_QUAD | IT_SUIT | IT_INVULNERABILITY | IT_INVISIBILITY) cl.viewstate.powerup_index = (cl.stats[STAT_ITEMS]&IT_POWER) >> 19; + Sbar_Changed (sbc_items); break; case STAT_HEALTH: if (cl_player_health_e->func) @@ -1378,12 +1378,12 @@ CL_ParseServerMessage (void) // svc_updatename case svc_updatefrags: - Sbar_Changed (); i = MSG_ReadByte (net_message); if (i >= MAX_CLIENTS) Host_Error ("CL_ParseServerMessage: svc_updatefrags > " "MAX_SCOREBOARD"); cl.players[i].frags = (short) MSG_ReadShort (net_message); + Sbar_Changed (sbc_frags); break; // svc_clientdata diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index b2152266d..1b13de567 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -90,25 +90,14 @@ static cvar_t scr_showturtle_cvar = { .value = { .type = &cexpr_int, .value = &scr_showturtle }, }; -view_t *cl_screen_view; -static view_t *net_view; -static view_t *loading_view; - -static qpic_t *scr_ram; -static qpic_t *scr_turtle; - -static void -draw_pic (view_t *view) -{ - r_funcs->Draw_Pic (view->xabs, view->yabs, view->data); -} - -static void -draw_cachepic (view_t *view) -{ - qpic_t *pic = r_funcs->Draw_CachePic (view->data, 1); - r_funcs->Draw_Pic (view->xabs, view->yabs, pic); -} +view_t cl_screen_view; +static view_t net_view; +static view_t timegraph_view; +static view_t zgraph_view; +static view_t loading_view; +static view_t ram_view; +static view_t turtle_view; +static view_t pause_view; static void SCR_CShift (void) @@ -126,84 +115,35 @@ SCR_CShift (void) r_funcs->Draw_BlendScreen (cl.viewstate.cshift_color); } -static void -SCR_DrawRam (void) -{ - if (!scr_showram) - return; - - if (!r_cache_thrash) - return; - - r_funcs->Draw_Pic (cl_screen_view->xpos + 32, cl_screen_view->ypos, - scr_ram); -} - -static void -SCR_DrawTurtle (void) -{ - static int count; - - if (!scr_showturtle) - return; - - if (r_data->frametime < 0.1) { - count = 0; - return; - } - - count++; - if (count < 3) - return; - - r_funcs->Draw_Pic (cl_screen_view->xpos, cl_screen_view->ypos, - scr_turtle); -} - -static void -SCR_DrawPause (void) -{ - qpic_t *pic; - - if (!scr_showpause) // turn off for screenshots - return; - - if (!r_data->paused) - return; - - pic = r_funcs->Draw_CachePic ("gfx/pause.lmp", true); - r_funcs->Draw_Pic ((cl_screen_view->xlen - pic->width) / 2, - (cl_screen_view->ylen - 48 - pic->height) / 2, - pic); -} - static void scr_draw_views (void) { - net_view->visible = (!cls.demoplayback - && (cls.netchan.outgoing_sequence - - cls.netchan.incoming_acknowledged) - >= UPDATE_BACKUP - 1); - loading_view->visible = cl.loading; - cl_netgraph_view->visible = cl_netgraph != 0; + if (scr_showturtle) { + static int count; + if (r_data->frametime < 0.1) { + count = 0; + } else { + count++; + } + View_SetVisible (turtle_view, count > 2); + } - //FIXME don't do every frame - view_move (cl_netgraph_view, cl_netgraph_view->xpos, hud_sb_lines); - view_setgravity (cl_netgraph_view, - hud_swap ? grav_southeast : grav_southwest); + // turn off for screenshots + View_SetVisible (pause_view, scr_showpause && r_data->paused); - view_draw (cl_screen_view); + View_SetVisible (ram_view, scr_showram && r_cache_thrash); + View_SetVisible (net_view, + (!cls.demoplayback && realtime - cl.last_servermessage >= 0.3)); + View_SetVisible (loading_view, cl.loading); } static SCR_Func scr_funcs_normal[] = { 0, //Draw_Crosshair, - SCR_DrawRam, - SCR_DrawTurtle, - SCR_DrawPause, Sbar_Draw, + HUD_Draw_Views, SCR_CShift, - scr_draw_views, Sbar_DrawCenterPrint, + scr_draw_views, Con_DrawConsole, 0 }; @@ -228,43 +168,98 @@ static SCR_Func *scr_funcs[] = { scr_funcs_finale, }; +static void +cl_vidsize_listener (void *data, const viddef_t *vdef) +{ + View_SetLen (cl_screen_view, vdef->width, vdef->height); + View_UpdateHierarchy (cl_screen_view); +} + void CL_Init_Screen (void) { qpic_t *pic; - cl_screen_view = r_data->scr_view; - con_module->data->console->screen_view = cl_screen_view; + VID_OnVidResize_AddListener (cl_vidsize_listener, 0); - scr_ram = r_funcs->Draw_PicFromWad ("ram"); - scr_turtle = r_funcs->Draw_PicFromWad ("turtle"); + HUD_Init (); + + cl_screen_view = View_New (hud_registry, nullview); + con_module->data->console->screen_view = &cl_screen_view; + + View_SetPos (cl_screen_view, 0, 0); + View_SetLen (cl_screen_view, viddef.width, viddef.height); + View_SetGravity (cl_screen_view, grav_northwest); + View_SetVisible (cl_screen_view, 1); + + pic = r_funcs->Draw_PicFromWad ("ram"); + ram_view = View_New (hud_registry, cl_screen_view); + View_SetPos (ram_view, 32, 0); + View_SetLen (ram_view, pic->width, pic->height); + View_SetGravity (ram_view, grav_northwest); + Ent_SetComponent (ram_view.id, hud_pic, ram_view.reg, &pic); + View_SetVisible (ram_view, 0); + + pic = r_funcs->Draw_PicFromWad ("turtle"); + turtle_view = View_New (hud_registry, cl_screen_view); + View_SetPos (turtle_view, 32, 0); + View_SetLen (turtle_view, pic->width, pic->height); + View_SetGravity (turtle_view, grav_northwest); + Ent_SetComponent (turtle_view.id, hud_pic, turtle_view.reg, &pic); + View_SetVisible (turtle_view, 0); Cvar_Register (&scr_showpause_cvar, 0, 0); Cvar_Register (&scr_showram_cvar, 0, 0); Cvar_Register (&scr_showturtle_cvar, 0, 0); pic = r_funcs->Draw_PicFromWad ("net"); - net_view = view_new (64, 0, pic->width, pic->height, grav_northwest); - net_view->draw = draw_pic; - net_view->data = pic; - net_view->visible = 0; - view_add (cl_screen_view, net_view); + net_view = View_New (hud_registry, cl_screen_view); + View_SetPos (net_view, 64, 0); + View_SetLen (net_view, pic->width, pic->height); + View_SetGravity (net_view, grav_northwest); + Ent_SetComponent (net_view.id, hud_pic, net_view.reg, &pic); + View_SetVisible (net_view, 0); + + timegraph_view = View_New (hud_registry, cl_screen_view); + View_SetPos (timegraph_view, 0, 0); + View_SetLen (timegraph_view, r_data->vid->width, 100); + View_SetGravity (timegraph_view, grav_southwest); + Ent_SetComponent (timegraph_view.id, hud_func, timegraph_view.reg, + R_TimeGraph); + View_SetVisible (timegraph_view, r_timegraph); + + zgraph_view = View_New (hud_registry, cl_screen_view); + View_SetPos (zgraph_view, 0, 0); + View_SetLen (zgraph_view, r_data->vid->width, 100); + View_SetGravity (zgraph_view, grav_southwest); + Ent_SetComponent (zgraph_view.id, hud_func, zgraph_view.reg, R_ZGraph); + View_SetVisible (zgraph_view, r_zgraph); const char *name = "gfx/loading.lmp"; pic = r_funcs->Draw_CachePic (name, 1); - loading_view = view_new (0, -24, pic->width, pic->height, grav_center); - loading_view->draw = draw_cachepic; - loading_view->data = (void *) name; - loading_view->visible = 0; - view_add (cl_screen_view, loading_view); + loading_view = View_New (hud_registry, cl_screen_view); + View_SetPos (loading_view, 0, -24); + View_SetLen (loading_view, pic->width, pic->height); + View_SetGravity (loading_view, grav_center); + Ent_SetComponent (loading_view.id, hud_cachepic, loading_view.reg, &name); + View_SetVisible (loading_view, 0); - cl_netgraph_view = view_new (0, hud_sb_lines, - NET_TIMINGS + 16, - cl_netgraph_height + 25, - grav_southwest); - cl_netgraph_view->draw = CL_NetGraph; - cl_netgraph_view->visible = 0; - view_add (cl_screen_view, cl_netgraph_view); + name = "gfx/pause.lmp"; + pic = r_funcs->Draw_CachePic (name, 1); + pause_view = View_New (hud_registry, cl_screen_view); + View_SetPos (pause_view, 0, -24); + View_SetLen (pause_view, pic->width, pic->height); + View_SetGravity (pause_view, grav_center); + Ent_SetComponent (pause_view.id, hud_cachepic, pause_view.reg, &name); + View_SetVisible (pause_view, 0); + + cl_netgraph_view = View_New (hud_registry, cl_screen_view); + View_SetPos (cl_netgraph_view, 0, hud_sb_lines); + View_SetLen (cl_netgraph_view, NET_TIMINGS + 16, cl_netgraph_height + 25); + View_SetGravity (cl_netgraph_view, grav_southwest); + Ent_SetComponent (cl_netgraph_view.id, hud_func, cl_netgraph_view.reg, + CL_NetGraph); + View_SetVisible (cl_netgraph_view, cl_netgraph); } void diff --git a/qw/source/sbar.c b/qw/source/sbar.c index e73c6629a..e2cf0f8b7 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -69,8 +69,60 @@ #include "sbar.h" int sb_updates; // if >= vid.numpages, no update needed +static int sb_update_flags; static int sb_view_size; +static view_t sbar_main; +static view_t sbar_inventory; +static view_t sbar_frags; +static view_t sbar_sigils; +static view_t sbar_items; +static view_t sbar_armament; +static view_t sbar_weapons; +static view_t sbar_miniammo; +static view_t sbar_statusbar; +static view_t sbar_armor; +static view_t sbar_face; +static view_t sbar_health; +static view_t sbar_ammo; +//static view_t sbar_status; +static view_t sbar_tile[2]; + +static view_t +sbar_view (int x, int y, int w, int h, grav_t gravity, view_t parent) +{ + view_t view = View_New (hud_registry, parent); + View_SetPos (view, x, y); + View_SetLen (view, w, h); + View_SetGravity (view, gravity); + View_SetVisible (view, 1); + return view; +} + +static inline void +sbar_setcomponent (view_t view, uint32_t comp, void *data) +{ + Ent_SetComponent (view.id, comp, view.reg, data); +} + +static inline int +sbar_hascomponent (view_t view, uint32_t comp) +{ + return Ent_HasComponent (view.id, comp, view.reg); +} + +static inline void * +sbar_getcomponent (view_t view, uint32_t comp) +{ + return Ent_GetComponent (view.id, comp, view.reg); +} + +static inline void +sbar_remcomponent (view_t view, uint32_t comp) +{ + Ent_RemoveComponent (view.id, comp, view.reg); +} + #define STAT_MINUS 10 // num frame for '-' stats digit qpic_t *sb_nums[2][11]; @@ -95,7 +147,7 @@ qpic_t *sb_face_invis_invuln; qboolean sb_showscores; qboolean sb_showteamscores; -static qboolean largegame = false; +//static qboolean largegame = false; char *fs_fraglog; static cvar_t fs_fraglog_cvar = { @@ -144,7 +196,7 @@ static cvar_t scr_printspeed_cvar = { .value = { .type = &cexpr_float, .value = &scr_printspeed }, }; -static void (*Sbar_Draw_DMO_func) (view_t *view, int l, int y, int skip); +//static void (*Sbar_Draw_DMO_func) (view_t *view, int l, int y, int skip); static void viewsize_f (int view_size) @@ -157,7 +209,7 @@ viewsize_f (int view_size) } -static int +static int __attribute__((used)) Sbar_ColorForMap (int m) { return (bound (0, m, 13) * 16) + 8; @@ -198,79 +250,18 @@ Sbar_DontShowScores (void) } void -Sbar_Changed (void) +Sbar_Changed (sbar_changed change) { + sb_update_flags |= 1 << change; sb_updates = 0; // update next frame } static void -draw_pic (view_t *view, int x, int y, qpic_t *pic) -{ - r_funcs->Draw_Pic (view->xabs + x, view->yabs + y, pic); -} - -static inline void -draw_cachepic (view_t *view, int x, int y, const char *name, int cent) -{ - qpic_t *pic = r_funcs->Draw_CachePic (name, true); - if (cent) - x += (view->xlen - pic->width) / 2; - r_funcs->Draw_Pic (view->xabs + x, view->yabs + y, pic); -} - -static inline void -draw_subpic (view_t *view, int x, int y, qpic_t *pic, - int srcx, int srcy, int width, int height) -{ - r_funcs->Draw_SubPic (view->xabs + x, view->yabs + y, pic, - srcx, srcy, width, height); -} - -static inline void -draw_transpic (view_t *view, int x, int y, qpic_t *pic) -{ - r_funcs->Draw_Pic (view->xabs + x, view->yabs + y, pic); -} - - -// drawing routines are reletive to the status bar location - -static inline void -draw_character (view_t *view, int x, int y, int c) -{ - r_funcs->Draw_Character (view->xabs + x, view->yabs + y, c); -} - -static inline void -draw_string (view_t *view, int x, int y, const char *str) -{ - r_funcs->Draw_String (view->xabs + x, view->yabs + y, str); -} -#if 0 -static inline void -draw_altstring (view_t *view, int x, int y, const char *str) -{ - r_funcs->Draw_AltString (view->xabs + x, view->yabs + y, str); -} -#endif -static inline void -draw_nstring (view_t *view, int x, int y, const char *str, int n) -{ - r_funcs->Draw_nString (view->xabs + x, view->yabs + y, str, n); -} - -static inline void -draw_fill (view_t *view, int x, int y, int w, int h, int col) -{ - r_funcs->Draw_Fill (view->xabs + x, view->yabs + y, w, h, col); -} - -static void -draw_num (view_t *view, int x, int y, int num, int digits, int color) +draw_num (view_t *view, int num, int digits, int color) { char str[12]; char *ptr; - int l, frame; + int l, frame, x = 0; if (num > 999999999) num = 999999999; @@ -279,8 +270,10 @@ draw_num (view_t *view, int x, int y, int num, int digits, int color) ptr = str; if (l > digits) ptr += (l - digits); - if (l < digits) - x += (digits - l) * 24; + while (digits > l) { + sbar_remcomponent (view[x++], hud_pic); + digits--; + } while (*ptr) { if (*ptr == '-') @@ -288,65 +281,67 @@ draw_num (view_t *view, int x, int y, int num, int digits, int color) else frame = *ptr - '0'; - draw_transpic (view, x, y, sb_nums[color][frame]); - x += 24; + sbar_setcomponent (view[x++], hud_pic, &sb_nums[color][frame]); ptr++; } } static inline void -draw_smallnum (view_t *view, int x, int y, int n, int packed, int colored) +draw_smallnum (view_t view, int x, int y, int n, int packed, int colored) { - char num[12]; + void *comp = sbar_getcomponent (view, hud_charbuff); + __auto_type charbuff = *(draw_charbuffer_t **) comp; + char num[4]; packed = packed != 0; // ensure 0 or 1 - if (n > 999) - n = 999; - + n = bound (-99, n, 999); snprintf (num, sizeof (num), "%3d", n); - if (colored) { - if (num[0] != ' ') - num[0] = 18 + num[0] - '0'; - if (num[1] != ' ') - num[1] = 18 + num[1] - '0'; - if (num[2] != ' ') - num[2] = 18 + num[2] - '0'; + for (int i = 0; i < 3; i++) { + charbuff->chars[i] = num[i] - (colored && num[i] != ' ' ? '0' - 18 : 0); } - draw_character (view, x + packed, y, num[0]); - draw_character (view, x + 8, y, num[1]); - draw_character (view, x + 16 - packed, y, num[2]); + } static void -draw_tile (view_t *view) -{ - r_funcs->Draw_TileClear (view->xabs, view->yabs, view->xlen, view->ylen); -} - -static void -draw_ammo_sbar (view_t *view) +draw_miniammo (view_t view) { int i, count; // ammo counts for (i = 0; i < 4; i++) { + view_t v = View_GetChild (view, i); count = cl.stats[STAT_SHELLS + i]; - draw_smallnum (view, (6 * i + 1) * 8 + 2, 0, count, 0, 1); + draw_smallnum (v, (6 * i + 1) * 8 + 2, 0, count, 0, 1); } } static void -draw_ammo_hud (view_t *view) +draw_ammo (view_t view) { - int i, count; + qpic_t *pic = 0; + if (cl.stats[STAT_ITEMS] & IT_SHELLS) + pic = sb_ammo[0]; + else if (cl.stats[STAT_ITEMS] & IT_NAILS) + pic = sb_ammo[1]; + else if (cl.stats[STAT_ITEMS] & IT_ROCKETS) + pic = sb_ammo[2]; + else if (cl.stats[STAT_ITEMS] & IT_CELLS) + pic = sb_ammo[3]; - // ammo counts - for (i = 0; i < 4; i++) { - count = cl.stats[STAT_SHELLS + i]; - draw_subpic (view, 0, i * 11, sb_ibar, 3 + (i * 48), 0, 42, 11); - draw_smallnum (view, 7, i * 11, count, 0, 1); + view_t ammo = View_GetChild (view, 0); + if (pic) { + sbar_setcomponent (ammo, hud_pic, &pic); + } else { + sbar_remcomponent (ammo, hud_pic); } + + view_t num[3] = { + View_GetChild (view, 1), + View_GetChild (view, 2), + View_GetChild (view, 3), + }; + draw_num (num, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); } static int @@ -368,46 +363,33 @@ calc_flashon (float time, int mask) } static void -draw_weapons_sbar (view_t *view) +draw_weapons_sbar (view_t view) { int flashon, i; for (i = 0; i < 7; i++) { + view_t weap = View_GetChild (view, i); if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); - draw_pic (view, i * 24, 0, sb_weapons[flashon][i]); if (flashon > 1) - sb_updates = 0; // force update to remove flash + sb_updates = 0; // force update to remove flash + sbar_setcomponent (weap, hud_pic, &sb_weapons[flashon][i]); + } else { + sbar_remcomponent (weap, hud_pic); } } } static void -draw_weapons_hud (view_t *view) +draw_items (view_t view) { - int flashon, i, x = 0; + //float time; + //int flashon = 0, i; - if (view->parent->gravity == grav_southeast) - x = view->xlen - 24; - - for (i = cl_screen_view->ylen < 204; i < 7; i++) { - if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { - flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); - draw_subpic (view, x, i * 16, sb_weapons[flashon][i], 0, 0, 24, 16); - if (flashon > 1) - sb_updates = 0; // force update to remove flash - } - } -} - -static void -draw_items (view_t *view) -{ - float time; - int flashon = 0, i; - - for (i = 0; i < 6; i++) { + for (int i = 0; i < 6; i++) { + view_t item = View_GetChild (view, i); if (cl.stats[STAT_ITEMS] & (1 << (17 + i))) { +#if 0 time = cl.item_gettime[17 + i]; if (time && time > cl.time - 2 && flashon) { // Flash frame sb_updates = 0; @@ -416,18 +398,24 @@ draw_items (view_t *view) } if (time && time > cl.time - 2) sb_updates = 0; +#endif + sbar_setcomponent (item, hud_pic, &sb_items[i]); + } else { + sbar_remcomponent (item, hud_pic); } } } static void -draw_sigils (view_t *view) +draw_sigils (view_t view) { - float time; - int flashon = 0, i; + //float time; + //int flashon = 0, i; - for (i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { + view_t sigil = View_GetChild (view, i); if (cl.stats[STAT_ITEMS] & (1 << (28 + i))) { +#if 0 time = cl.item_gettime[28 + i]; if (time && time > cl.time - 2 && flashon) { // flash frame sb_updates = 0; @@ -436,10 +424,14 @@ draw_sigils (view_t *view) } if (time && time > cl.time - 2) sb_updates = 0; +#endif + sbar_setcomponent (sigil, hud_pic, &sb_sigil[i]); + } else { + sbar_remcomponent (sigil, hud_pic); } } } - +#if 0 static void draw_inventory_sbar (view_t *view) { @@ -451,7 +443,7 @@ draw_inventory_sbar (view_t *view) draw_pic (view, 0, 0, sb_ibar); view_draw (view); } - +#endif typedef struct { char team[16 + 1]; int frags; @@ -493,7 +485,7 @@ Sbar_SortFrags (qboolean includespec) } } -static void +static void __attribute__((used)) Sbar_SortTeams (void) { char t[16 + 1]; @@ -559,9 +551,10 @@ Sbar_SortTeams (void) } } -static void +static void __attribute__((used)) draw_solo (view_t *view) { +#if 0 char str[80]; int minutes, seconds; @@ -571,43 +564,51 @@ draw_solo (view_t *view) seconds = cl.time - 60 * minutes; snprintf (str, sizeof (str), "Time :%3i:%02i", minutes, seconds); draw_string (view, 184, 4, str); +#endif } static inline void dmo_ping (view_t *view, int x, int y, player_info_t *s) { +#if 0 int p; p = s->ping; if (p < 0 || p > 999) p = 999; draw_smallnum (view, x + 8, y, p, 0, 0); +#endif } static inline void dmo_uid (view_t *view, int x, int y, player_info_t *s) { +#if 0 char num[12]; int p; p = s->userid; snprintf (num, sizeof (num), "%4i", p); draw_string (view, x, y, num); +#endif } static inline void dmo_pl (view_t *view, int x, int y, player_info_t *s) { +#if 0 int p; // draw pl p = s->pl; draw_smallnum (view, x, y, p, 0, p > 25); +#endif } static inline int calc_fph (int frags, int total) { +#if 0 int fph; if (total != 0) { @@ -622,11 +623,14 @@ calc_fph (int frags, int total) } return fph; +#endif + return 0; } static inline void dmo_main (view_t *view, int x, int y, player_info_t *s, int is_client) { +#if 0 char num[12]; int fph, minutes, total, top, bottom, f; @@ -665,23 +669,29 @@ dmo_main (view_t *view, int x, int y, player_info_t *s, int is_client) snprintf (num, sizeof (num), "\x10%3i\x11", f); } draw_nstring (view, x + 72, y, num, 5); +#endif } static inline void dmo_team (view_t *view, int x, int y, player_info_t *s) { +#if 0 draw_nstring (view, x, y, s->team->value, 4); +#endif } static inline void dmo_name (view_t *view, int x, int y, player_info_t *s) { +#if 0 draw_string (view, x, y, s->name->value); +#endif } static void -draw_frags (view_t *view) +draw_frags (view_t view) { +#if 0 int i, k, l, p = -1; int top, bottom; int x; @@ -720,11 +730,13 @@ draw_frags (view_t *view) draw_character (view, p * 32, 0, 16); draw_character (view, p * 32 + 26, 0, 17); } +#endif } static void -draw_face (view_t *view) +draw_face (view_t view) { +#if 0 int f, anim; if ((cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY)) @@ -756,11 +768,13 @@ draw_face (view_t *view) } else anim = 0; draw_pic (view, 112, 0, sb_faces[f][anim]); +#endif } -static void +static void __attribute__((used)) draw_spectator (view_t *view) { +#if 0 char st[512]; if (autocam != CAM_TRACK) { @@ -777,8 +791,33 @@ draw_spectator (view_t *view) } draw_string (view, 0, -8, st); } +#endif } +static inline void +draw_armor (view_t view) +{ + view_t armor = View_GetChild (view, 0); + view_t num[3] = { + View_GetChild (view, 1), + View_GetChild (view, 2), + View_GetChild (view, 3), + }; + if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { + draw_num (num, 666, 3, 1); + } else { + draw_num (num, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25); + if (cl.stats[STAT_ITEMS] & IT_ARMOR3) + sbar_setcomponent (armor, hud_pic, &sb_armor[2]); + else if (cl.stats[STAT_ITEMS] & IT_ARMOR2) + sbar_setcomponent (armor, hud_pic, &sb_armor[1]); + else if (cl.stats[STAT_ITEMS] & IT_ARMOR1) + sbar_setcomponent (armor, hud_pic, &sb_armor[0]); + else + sbar_remcomponent (armor, hud_pic); + } +} +#if 0 static void draw_status_bar (view_t *view) { @@ -787,46 +826,18 @@ draw_status_bar (view_t *view) else draw_pic (view, 0, 0, sb_sbar); } - +#endif static inline void -draw_armor (view_t *view) +draw_health (view_t view) { - if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { - draw_num (view, 24, 0, 666, 3, 1); - } else { - draw_num (view, 24, 0, cl.stats[STAT_ARMOR], 3, - cl.stats[STAT_ARMOR] <= 25); - if (cl.stats[STAT_ITEMS] & IT_ARMOR3) - draw_pic (view, 0, 0, sb_armor[2]); - else if (cl.stats[STAT_ITEMS] & IT_ARMOR2) - draw_pic (view, 0, 0, sb_armor[1]); - else if (cl.stats[STAT_ITEMS] & IT_ARMOR1) - draw_pic (view, 0, 0, sb_armor[0]); - } + view_t num[3] = { + View_GetChild (view, 0), + View_GetChild (view, 1), + View_GetChild (view, 2), + }; + draw_num (num, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25); } - -static inline void -draw_health (view_t *view) -{ - draw_num (view, 136, 0, cl.stats[STAT_HEALTH], 3, - cl.stats[STAT_HEALTH] <= 25); -} - -static inline void -draw_ammo (view_t *view) -{ - if (cl.stats[STAT_ITEMS] & IT_SHELLS) - draw_pic (view, 224, 0, sb_ammo[0]); - else if (cl.stats[STAT_ITEMS] & IT_NAILS) - draw_pic (view, 224, 0, sb_ammo[1]); - else if (cl.stats[STAT_ITEMS] & IT_ROCKETS) - draw_pic (view, 224, 0, sb_ammo[2]); - else if (cl.stats[STAT_ITEMS] & IT_CELLS) - draw_pic (view, 224, 0, sb_ammo[3]); - - draw_num (view, 248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); -} - +#if 0 static void draw_status (view_t *view) { @@ -845,7 +856,7 @@ draw_status (view_t *view) draw_health (view); draw_ammo (view); } - +#endif /* Sbar_DeathmatchOverlay @@ -854,6 +865,7 @@ draw_status (view_t *view) static void Sbar_DeathmatchOverlay (view_t *view, int start) { +#if 0 int l, y; int skip = 10; @@ -892,6 +904,7 @@ Sbar_DeathmatchOverlay (view_t *view, int start) if (y >= view->ylen - 10) // we ran over the screen size, squish largegame = true; +#endif } /* @@ -903,6 +916,7 @@ Sbar_DeathmatchOverlay (view_t *view, int start) static void Sbar_TeamOverlay (view_t *view) { +#if 0 char num[20]; int pavg, plow, phigh, i, k, x, y; team_t *tm; @@ -972,6 +986,7 @@ Sbar_TeamOverlay (view_t *view) } y += 8; Sbar_DeathmatchOverlay (view, y); +#endif } static void @@ -997,6 +1012,7 @@ draw_overlay (view_t *view) static void sbar_update_vis (void) { +#if 0 qboolean headsup; if (r_data->scr_copyeverything) @@ -1022,13 +1038,7 @@ sbar_update_vis (void) if (sb_showscores || sb_showteamscores || cl.stats[STAT_HEALTH] <= 0) sb_updates = 0; -} - -void -Sbar_Draw (void) -{ - sbar_update_vis (); - hud_main_view->draw (hud_main_view); +#endif } /* @@ -1131,9 +1141,10 @@ Sbar_LogFrags (void) Qclose (file); } -static void +static void __attribute__((used)) Sbar_Draw_DMO_Team_Ping (view_t *view, int l, int y, int skip) { +#if 0 int i, k, x; player_info_t *s; @@ -1168,11 +1179,13 @@ Sbar_Draw_DMO_Team_Ping (view_t *view, int l, int y, int skip) y += skip; } +#endif } -static void +static void __attribute__((used)) Sbar_Draw_DMO_Team_UID (view_t *view, int l, int y, int skip) { +#if 0 int i, k, x; player_info_t *s; @@ -1207,11 +1220,13 @@ Sbar_Draw_DMO_Team_UID (view_t *view, int l, int y, int skip) y += skip; } +#endif } -static void +static void __attribute__((used)) Sbar_Draw_DMO_Team_Ping_UID (view_t *view, int l, int y, int skip) { +#if 0 int i, k, x; player_info_t *s; @@ -1249,11 +1264,13 @@ Sbar_Draw_DMO_Team_Ping_UID (view_t *view, int l, int y, int skip) y += skip; } +#endif } -static void +static void __attribute__((used)) Sbar_Draw_DMO_Ping (view_t *view, int l, int y, int skip) { +#if 0 int i, k, x; player_info_t *s; @@ -1288,11 +1305,13 @@ Sbar_Draw_DMO_Ping (view_t *view, int l, int y, int skip) y += skip; } +#endif } -static void +static void __attribute__((used)) Sbar_Draw_DMO_UID (view_t *view, int l, int y, int skip) { +#if 0 int i, k, x; player_info_t *s; @@ -1326,11 +1345,13 @@ Sbar_Draw_DMO_UID (view_t *view, int l, int y, int skip) y += skip; } +#endif } -static void +static void __attribute__((used)) Sbar_Draw_DMO_Ping_UID (view_t *view, int l, int y, int skip) { +#if 0 int i, k, x; player_info_t *s; @@ -1365,11 +1386,13 @@ Sbar_Draw_DMO_Ping_UID (view_t *view, int l, int y, int skip) y += skip; } +#endif } void Sbar_DMO_Init_f (void *data, const cvar_t *cvar) { +#if 0 if (cl.teamplay) if (hud_scoreboard_uid > 1) Sbar_Draw_DMO_func = Sbar_Draw_DMO_Team_Ping_UID; @@ -1384,6 +1407,7 @@ Sbar_DMO_Init_f (void *data, const cvar_t *cvar) Sbar_Draw_DMO_func = Sbar_Draw_DMO_UID; else Sbar_Draw_DMO_func = Sbar_Draw_DMO_Ping; +#endif } /* @@ -1396,6 +1420,7 @@ Sbar_DMO_Init_f (void *data, const cvar_t *cvar) static void draw_minifrags (view_t *view) { +#if 0 int numlines, top, bottom, f, i, k, x, y; char num[20]; player_info_t *s; @@ -1465,11 +1490,13 @@ draw_minifrags (view_t *view) draw_nstring (view, x + 48, y, s->name->value, 16); y += 8; } +#endif } static void draw_miniteam (view_t *view) { +#if 0 int i, k, x, y; char num[12]; info_key_t *player_team = cl.players[cl.playernum].team; @@ -1498,11 +1525,13 @@ draw_miniteam (view_t *view) y += 8; } +#endif } static void draw_time (view_t *view) { +#if 0 struct tm *local = 0; time_t utc = 0; char st[80]; @@ -1527,11 +1556,13 @@ draw_time (view_t *view) strftime (st, sizeof (st), HOUR12":%M "PM, local); draw_string (view, 8, 0, st); } +#endif } static void draw_fps (view_t *view) { +#if 0 static char st[80]; double t; static double lastframetime; @@ -1545,11 +1576,13 @@ draw_fps (view_t *view) snprintf (st, sizeof (st), "%5.1f FPS", lastfps); } draw_string (view, 80, 8, st); +#endif } static void draw_net (view_t *view) { +#if 0 // request new ping times every two seconds if (!cls.demoplayback && realtime - cl.last_ping_request > 2) { cl.last_ping_request = realtime; @@ -1572,6 +1605,7 @@ draw_net (view_t *view) lost = bound (0, lost, 999); draw_string (view, 56, 0, va (0, "%3d pl", lost)); } +#endif } static void @@ -1588,6 +1622,7 @@ draw_stuff (view_t *view) void Sbar_IntermissionOverlay (void) { +#if 0 r_data->scr_copyeverything = 1; r_data->scr_fullupdate = 0; @@ -1595,6 +1630,7 @@ Sbar_IntermissionOverlay (void) Sbar_TeamOverlay (hud_overlay_view); else Sbar_DeathmatchOverlay (hud_overlay_view, 0); +#endif } /* CENTER PRINTING */ @@ -1630,9 +1666,10 @@ Sbar_CenterPrint (const char *str) } } -static void +static void __attribute__((used)) Sbar_DrawCenterString (view_t *view, int remaining) { +#if 0 const char *start; int j, l, x, y; @@ -1663,11 +1700,13 @@ Sbar_DrawCenterString (view_t *view, int remaining) break; start++; // skip the \n } while (1); +#endif } void Sbar_FinaleOverlay (void) { +#if 0 int remaining; r_data->scr_copyeverything = 1; @@ -1676,11 +1715,13 @@ Sbar_FinaleOverlay (void) // the finale prints the characters one at a time remaining = scr_printspeed * (realtime - centertime_start); Sbar_DrawCenterString (hud_overlay_view, remaining); +#endif } void Sbar_DrawCenterPrint (void) { +#if 0 r_data->scr_copytop = 1; centertime_off -= r_data->frametime; @@ -1688,11 +1729,51 @@ Sbar_DrawCenterPrint (void) return; Sbar_DrawCenterString (hud_overlay_view, -1); +#endif +} + +void +Sbar_Draw (void) +{ + if (cls.state != ca_active) { + return; + } + sb_update_flags = ~0; + if (sb_update_flags & (1 << sbc_ammo)) { + draw_miniammo (sbar_miniammo); + draw_ammo (sbar_ammo); + } + if (sb_update_flags & (1 << sbc_armor)) draw_armor (sbar_armor); + if (sb_update_flags & (1 << sbc_frags)) draw_frags (sbar_frags); + if (sb_update_flags & (1 << sbc_health)) draw_health (sbar_health); + if (sb_update_flags & (1 << sbc_info)) { + draw_miniteam (0); + draw_minifrags (0); + draw_stuff (0); + draw_overlay (0); + //draw_intermission (0); + Sbar_DeathmatchOverlay (0, 0); + sbar_update_vis (); + } + if (sb_update_flags & (1 << sbc_items)) { + draw_items (sbar_items); + draw_sigils (sbar_items); + } + if (sb_update_flags & (1 << sbc_weapon)) draw_weapons_sbar (sbar_weapons); + if (sb_update_flags & ((1 << sbc_health) | (1 << sbc_items))) { + draw_face (sbar_face); + } +#if 0 + sbar_update_vis (); + hud_main_view->draw (hud_main_view); +#endif + sb_update_flags = 0; } static void init_sbar_views (void) { +#if 0 view_t *view; view_t *minifrags_view = 0; view_t *miniteam_view = 0; @@ -1777,11 +1858,63 @@ init_sbar_views (void) view->resize_y = 1; view_add (sbar_view, view); } +#endif + sbar_main = sbar_view ( 0, 0, 320, 48, grav_south, cl_screen_view); + sbar_inventory = sbar_view ( 0, 0, 320, 24, grav_northwest, sbar_main); + sbar_frags = sbar_view ( 0, 0, 130, 8, grav_northeast, sbar_inventory); + sbar_sigils = sbar_view ( 0, 0, 32, 16, grav_southeast, sbar_inventory); + sbar_items = sbar_view (32, 0, 96, 16, grav_southeast, sbar_inventory); + sbar_armament = sbar_view ( 0, 0, 202, 24, grav_northwest, sbar_inventory); + sbar_weapons = sbar_view ( 0, 0, 192, 16, grav_southwest, sbar_armament); + sbar_miniammo = sbar_view ( 0, 0, 32, 8, grav_northwest, sbar_armament); + sbar_statusbar = sbar_view ( 0, 0, 320, 24, grav_southwest, sbar_main); + sbar_armor = sbar_view ( 0, 0, 96, 24, grav_northwest, sbar_statusbar); + sbar_face = sbar_view (112, 0, 24, 24, grav_northwest, sbar_statusbar); + sbar_health = sbar_view (136, 0, 72, 24, grav_northwest, sbar_statusbar); + sbar_ammo = sbar_view (224, 0, 96, 24, grav_northwest, sbar_statusbar); + sbar_tile[0] = sbar_view ( 0, 0, 0, 48, grav_southwest, sbar_main); + sbar_tile[1] = sbar_view ( 0, 0, 0, 48, grav_southeast, sbar_main); + + for (int i = 0; i < 4; i++) { + sbar_view (i * 8, 0, 8, 16, grav_northwest, sbar_sigils); + + sbar_view (i * 24, 0, 24, 24, grav_northwest, sbar_armor); + sbar_view (i * 24, 0, 24, 24, grav_northwest, sbar_ammo); + } + for (int i = 0; i < 6; i++) { + sbar_view (i * 16, 0, 16, 16, grav_northwest, sbar_items); + } + for (int i = 0; i < 7; i++) { + sbar_view (i * 24, 0, 24, 16, grav_northwest, sbar_weapons); + } + for (int i = 0; i < 4; i++) { + sbar_view (i * 24, 0, 24, 16, grav_northwest, sbar_health); + } + for (int i = 0; i < 4; i++) { + view_t v = sbar_view (i * 48 + 10, 0, 8, 8, grav_northwest, + sbar_miniammo); + draw_charbuffer_t *buffer = Draw_CreateBuffer (3, 1); + sbar_setcomponent (v, hud_charbuff, &buffer); + } + + sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar); + sbar_setcomponent (sbar_statusbar, hud_pic, &sb_sbar); + + if (r_data->vid->width > 320) { + int l = (r_data->vid->width - 320) / 2; + View_SetPos (sbar_tile[0], -l, 0); + View_SetLen (sbar_tile[0], l, 48); + View_SetPos (sbar_tile[1], -l, 0); + View_SetLen (sbar_tile[1], l, 48); + sbar_setcomponent (sbar_tile[0], hud_tile, 0); + sbar_setcomponent (sbar_tile[1], hud_tile, 0); + } } static void init_hud_views (void) { +#if 0 view_t *view; view_t *minifrags_view = 0; view_t *miniteam_view = 0; @@ -1851,11 +1984,13 @@ init_hud_views (void) view_add (hud_view, hud_armament_view); view_insert (hud_main_view, hud_view, 0); +#endif } static void init_views (void) { +#if 0 hud_main_view = view_new (0, 0, cl_screen_view->xlen, cl_screen_view->ylen, grav_northwest); view_insert (cl_screen_view, hud_main_view, 0); @@ -1875,7 +2010,7 @@ init_views (void) view_insert (hud_main_view, hud_overlay_view, 0); view_insert (hud_main_view, hud_stuff_view, 0); - +#endif init_sbar_views (); init_hud_views (); } @@ -1889,14 +2024,10 @@ Sbar_GIB_Print_Center_f (void) Sbar_CenterPrint (GIB_Argv(1)); } -void -Sbar_Init (void) +static void +load_pics (void) { - int i; - - init_views (); - - for (i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) { sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); sb_nums[1][i] = r_funcs->Draw_PicFromWad (va (0, "anum_%i", i)); } @@ -1923,7 +2054,7 @@ Sbar_Init (void) sb_weapons[1][5] = r_funcs->Draw_PicFromWad ("inv2_srlaunch"); sb_weapons[1][6] = r_funcs->Draw_PicFromWad ("inv2_lightng"); - for (i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) { sb_weapons[2 + i][0] = r_funcs->Draw_PicFromWad (va (0, "inva%i_shotgun", i + 1)); @@ -1984,6 +2115,18 @@ Sbar_Init (void) sb_face_invis_invuln = r_funcs->Draw_PicFromWad ("face_inv2"); sb_face_quad = r_funcs->Draw_PicFromWad ("face_quad"); + sb_sbar = r_funcs->Draw_PicFromWad ("sbar"); + sb_ibar = r_funcs->Draw_PicFromWad ("ibar"); + sb_scorebar = r_funcs->Draw_PicFromWad ("scorebar"); +} + +void +Sbar_Init (void) +{ + load_pics (); + init_views (); + View_UpdateHierarchy (sbar_main); + Cmd_AddCommand ("+showscores", Sbar_ShowScores, "Display information on everyone playing"); Cmd_AddCommand ("-showscores", Sbar_DontShowScores, @@ -1993,10 +2136,6 @@ Sbar_Init (void) Cmd_AddCommand ("-showteamscores", Sbar_DontShowTeamScores, "Stop displaying information for your team"); - sb_sbar = r_funcs->Draw_PicFromWad ("sbar"); - sb_ibar = r_funcs->Draw_PicFromWad ("ibar"); - sb_scorebar = r_funcs->Draw_PicFromWad ("scorebar"); - r_data->viewsize_callback = viewsize_f; HUD_Init_Cvars (); diff --git a/qw/source/sv_sbar.c b/qw/source/sv_sbar.c index e742b1c35..f63cd524d 100644 --- a/qw/source/sv_sbar.c +++ b/qw/source/sv_sbar.c @@ -45,10 +45,11 @@ #include "qw/include/sv_recorder.h" static void -draw_cpu (view_t *view) +draw_cpu (view_t view) { - sv_view_t *sv_view = view->data; + sv_view_t *sv_view = Ent_GetComponent (view.id, server_view, view.reg); sv_sbar_t *sb = sv_view->obj; + view_pos_t rel = View_GetRel (view); double cpu; const char *cpu_str; const char *s; @@ -58,34 +59,36 @@ draw_cpu (view_t *view) cpu = 100 * svs.stats.latched_active / cpu; cpu_str = va (0, "[CPU: %3d%%]", (int) cpu); - for (s = cpu_str, d = sb->text + view->xrel; *s; s++) + for (s = cpu_str, d = sb->text + rel.x; *s; s++) *d++ = *s; if (cpu > 70.0) { int i; for (i = 6; i < 9; i++) - sb->text[view->xrel + i] |= 0x80; + sb->text[rel.x + i] |= 0x80; } } static void -draw_rec (view_t *view) +draw_rec (view_t view) { - sv_view_t *sv_view = view->data; + sv_view_t *sv_view = Ent_GetComponent (view.id, server_view, view.reg); sv_sbar_t *sb = sv_view->obj; + view_pos_t rel = View_GetRel (view); const char *str; const char *s; char *d; str = va (0, "[REC: %d]", SVR_NumRecorders ()); - for (s = str, d = sb->text + view->xrel; *s; s++) + for (s = str, d = sb->text + rel.x; *s; s++) *d++ = *s; } static void -draw_mem (view_t *view) +draw_mem (view_t view) { - sv_view_t *sv_view = view->data; + sv_view_t *sv_view = Ent_GetComponent (view.id, server_view, view.reg); sv_sbar_t *sb = sv_view->obj; + view_pos_t rel = View_GetRel (view); const char *str; const char *s; char *d; @@ -97,32 +100,44 @@ draw_mem (view_t *view) if (used / (size / 256) >= 192) { mask = 0x80; } - for (s = str, d = sb->text + view->xrel; *s; s++) + for (s = str, d = sb->text + rel.x; *s; s++) *d++ = *s | mask; } void SV_Sbar_Init (void) { - view_t *status; - view_t *view; + view_t status; + view_t view; if (!con_module || !con_module->data->console->status_view) return; - status = con_module->data->console->status_view; - view = view_new (0, 0, 11, 1, grav_northwest); - view->draw = draw_cpu; - view->data = status->data; - view_add (status, view); + status = *con_module->data->console->status_view; + void *comp = Ent_GetComponent (status.id, server_window, status.reg); + sv_view_t sv_view = *(sv_view_t *) comp; + sv_view.setgeometry = 0; - view = view_new (11, 0, 8, 1, grav_northwest); - view->draw = draw_rec; - view->data = status->data; - view_add (status, view); + view = View_New (status.reg, status); + View_SetPos (view, 0, 0); + View_SetLen (view, 11, 1); + View_SetGravity (view, grav_northwest); + sv_view.draw = draw_cpu; + Ent_SetComponent (view.id, server_view, view.reg, &sv_view); - view = view_new (19, 0, 18, 1, grav_northwest); - view->draw = draw_mem; - view->data = status->data; - view_add (status, view); + view = View_New (status.reg, status); + View_SetPos (view, 11, 0); + View_SetLen (view, 8, 1); + View_SetGravity (view, grav_northwest); + sv_view.draw = draw_rec; + Ent_SetComponent (view.id, server_view, view.reg, &sv_view); + + view = View_New (status.reg, status); + View_SetPos (view, 19, 0); + View_SetLen (view, 18, 1); + View_SetGravity (view, grav_northwest); + sv_view.draw = draw_mem; + Ent_SetComponent (view.id, server_view, view.reg, &sv_view); + + View_UpdateHierarchy (status); } From 81e23b2e522b4b93bd38fec7604c5b6310f05bb3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Nov 2022 10:14:50 +0900 Subject: [PATCH 3118/3664] [console] Remove a debug print --- libs/console/client.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libs/console/client.c b/libs/console/client.c index f9026a72d..bea06d053 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -496,9 +496,6 @@ resize_input (view_t view, view_pos_t len) Draw_PrintBuffer (inp->buffer, inp->prompt); if (inp->input_line) { inp->input_line->width = inp->buffer->width - inp->buffer->cursx; - printf ("resize_input: %d %zd %d %d %d\n", view.id, - inp->input_line->width, - len.x, inp->buffer->width, inp->buffer->cursx); inp->buffer->chars[inp->buffer->cursx] = inp->input_line->prompt_char; } } From 036afba23d679d416d5270a913c7c4b665994697 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Nov 2022 10:15:23 +0900 Subject: [PATCH 3119/3664] [ui] Propagate motion modifications for views With this, the status bar now stays in the correct location as the window is resized. Rather nice that it was just a simple omission. --- libs/ui/view.c | 3 ++- nq/source/sbar.c | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libs/ui/view.c b/libs/ui/view.c index 27b2d73c7..b2df4b215 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -189,9 +189,10 @@ View_UpdateHierarchy (view_t view) if (cont[i].resize_y) { len[i].y += dy; } - modified[i] |= 2; + modified[i] |= 2; // propogate resize modifications } if (modified[i] || modified[par]) { + modified[i] |= 1; // propogate motion modifications switch (cont[i].gravity) { case grav_center: rel[i].x = pos[i].x + (len[par].x - len[i].x) / 2; diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 1ea8f9093..716bc1b33 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1521,8 +1521,6 @@ init_sbar_views (void) sbar_tile[0] = sbar_view ( 0, 0, 0, 48, grav_southwest, sbar_main); sbar_tile[1] = sbar_view ( 0, 0, 0, 48, grav_southeast, sbar_main); - View_SetResize (sbar_main, 1, 1); - for (int i = 0; i < 4; i++) { sbar_view (i * 8, 0, 8, 16, grav_northwest, sbar_sigils); From e504079938292b0013b788e5769e1dfc2f40fdf7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Nov 2022 10:18:47 +0900 Subject: [PATCH 3120/3664] [qwaq] Disable console screen view set for now The renderer currently does not have a view, and the qwaq console isn't used right now anyway. --- ruamoko/qwaq/builtins/graphics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 110a79e58..7aa6d3037 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -350,7 +350,7 @@ BI_Graphics_Init (progs_t *pr) con_module->data->console->frametime = &con_frametime; con_module->data->console->quit = quit_f; con_module->data->console->cbuf = qwaq_cbuf; - con_module->data->console->screen_view = r_data->scr_view; + //con_module->data->console->screen_view = r_data->scr_view; } //Key_SetKeyDest (key_game); From e67b374fd4a26705a038c129369b0117709f3ad6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Nov 2022 10:59:28 +0900 Subject: [PATCH 3121/3664] [ui] Propagate resize deltas in view hierarchies While it hasn't been a problem yet (no multi-level resizing), I'm sure it will be before too long. --- libs/ui/view.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/ui/view.c b/libs/ui/view.c index b2df4b215..ddd572737 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -183,13 +183,14 @@ View_UpdateHierarchy (view_t view) && (cont[i].resize_x || cont[i].resize_y)) { int dx = len[par].x - oldlen[par].x; int dy = len[par].y - oldlen[par].y; + modified[i] |= 2; // propogate resize modifications + oldlen[i] = len[i]; // for child resize calculations if (cont[i].resize_x) { len[i].x += dx; } if (cont[i].resize_y) { len[i].y += dy; } - modified[i] |= 2; // propogate resize modifications } if (modified[i] || modified[par]) { modified[i] |= 1; // propogate motion modifications From efee9c87a932e8f546bf095670b4208b55ba1679 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 1 Nov 2022 21:00:40 +0900 Subject: [PATCH 3122/3664] [nq,qw] Minimize differences in cl_screen.c --- include/r_local.h | 3 ++- include/r_shared.h | 3 ++- nq/source/cl_screen.c | 7 ++++--- qw/source/cl_screen.c | 10 ++++++---- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/r_local.h b/include/r_local.h index 01fe81733..55b093513 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -299,7 +299,8 @@ struct dlight_s; extern vec3_t lightspot; -void R_StoreEfrags (const efrag_t *ppefrag); +struct efrag_s; +void R_StoreEfrags (const struct efrag_s *efrag); void R_TimeRefresh_f (void); void R_PrintAliasStats (void); void R_PrintTimes (void); diff --git a/include/r_shared.h b/include/r_shared.h index c189d876a..4d6205920 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -163,6 +163,7 @@ typedef struct edge_s extern float r_avertexnormals[NUMVERTEXNORMALS][3]; extern vec3_t ambientcolor; -uint32_t SW_AddEntity (entity_t ent); +struct entity_s; +uint32_t SW_AddEntity (struct entity_s ent); #endif // _R_SHARED_H diff --git a/nq/source/cl_screen.c b/nq/source/cl_screen.c index ba77f1b31..b0137cabe 100644 --- a/nq/source/cl_screen.c +++ b/nq/source/cl_screen.c @@ -130,13 +130,12 @@ scr_draw_views (void) View_SetVisible (pause_view, scr_showpause && r_data->paused); View_SetVisible (ram_view, scr_showram && r_cache_thrash); - View_SetVisible (net_view, - (!cls.demoplayback && realtime - cl.last_servermessage >= 0.3)); + View_SetVisible (net_view, (!cls.demoplayback + && realtime - cl.last_servermessage >= 0.3)); View_SetVisible (loading_view, cl.loading); // FIXME cvar callbacks View_SetVisible (timegraph_view, r_timegraph); View_SetVisible (zgraph_view, r_zgraph); - } static SCR_Func scr_funcs_normal[] = { @@ -153,12 +152,14 @@ static SCR_Func scr_funcs_normal[] = { static SCR_Func scr_funcs_intermission[] = { Sbar_IntermissionOverlay, Con_DrawConsole, + scr_draw_views, 0 }; static SCR_Func scr_funcs_finale[] = { Sbar_FinaleOverlay, Con_DrawConsole, + scr_draw_views, 0, }; diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 1b13de567..8477247c6 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -45,8 +45,8 @@ #include "QF/screen.h" #include "QF/plugin/console.h" +#include "QF/plugin/vid_render.h" -#include "QF/scene/entity.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "QF/ui/view.h" @@ -56,7 +56,6 @@ #include "r_local.h" //FIXME for r_cache_thrash #include "client/hud.h" -#include "client/view.h" #include "client/world.h" #include "qw/include/client.h" @@ -132,9 +131,12 @@ scr_draw_views (void) View_SetVisible (pause_view, scr_showpause && r_data->paused); View_SetVisible (ram_view, scr_showram && r_cache_thrash); - View_SetVisible (net_view, - (!cls.demoplayback && realtime - cl.last_servermessage >= 0.3)); + View_SetVisible (net_view, (!cls.demoplayback + && realtime - cl.last_servermessage >= 0.3)); View_SetVisible (loading_view, cl.loading); + // FIXME cvar callbacks + View_SetVisible (timegraph_view, r_timegraph); + View_SetVisible (zgraph_view, r_zgraph); } static SCR_Func scr_funcs_normal[] = { From 9c6c59b37097d8423ba611c7ced22672b1f264c1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Nov 2022 09:52:35 +0900 Subject: [PATCH 3123/3664] [qw] Move view hight adjustment out of screen update cl_screen.c is that little bit closer to being merged. --- include/client/view.h | 2 +- libs/client/cl_view.c | 8 +++++++- qw/source/cl_parse.c | 5 +++++ qw/source/cl_screen.c | 10 ---------- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/client/view.h b/include/client/view.h index 43e82ec05..89280a1f2 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -58,9 +58,9 @@ typedef struct viewstate_s { vec4f_t movecmd; vec4f_t velocity; vec4f_t punchangle; - float frametime; transform_t camera_transform; double time; + float frametime; float height; int weaponframe; int onground; // -1 when in air diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index b64da5cf3..76240c010 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -807,7 +807,13 @@ V_CalcRefdef (viewstate_t *vs) bob = V_CalcBob (vs); // refresh position - origin[2] += vs->height + bob; + if (vs->flags & VF_GIB) { + origin[2] += 8; // gib view height + } else if (vs->flags & VF_DEAD) { + origin[2] += -16; // corpse view height + } else { + origin[2] += vs->height + bob; + } // never let it sit exactly on a node line, because a water plane can // disappear when viewed with the eye exactly on it. diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index da83589df..4f279c4aa 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1168,6 +1168,11 @@ CL_SetStat (int stat, int value) } cl.stats[stat] = value; cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]]; + if (cl.stdver) { + cl.viewstate.height = cl.stats[STAT_VIEWHEIGHT]; + } else { + cl.viewstate.height = DEFAULT_VIEWHEIGHT; // view height + } } static void diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 8477247c6..6be96fe98 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -281,16 +281,6 @@ CL_UpdateScreen (double realtime) } scr_funcs_normal[0] = r_funcs->Draw_Crosshair; - if (cl.viewstate.flags & VF_GIB) { - cl.viewstate.height = 8; // gib view height - } else if (cl.viewstate.flags & VF_DEAD) { - cl.viewstate.height = -16; // corpse view height - } else { - cl.viewstate.height = DEFAULT_VIEWHEIGHT; // view height - if (cl.stdver) - cl.viewstate.height = cl.stats[STAT_VIEWHEIGHT]; - } - cl.viewstate.intermission = cl.intermission != 0; V_PrepBlend (&cl.viewstate); int seq = (cls.netchan.outgoing_sequence - 1) & UPDATE_MASK; From 708978eea9998c3b3cd3afbda0d4e5dda81430ef Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Nov 2022 09:53:52 +0900 Subject: [PATCH 3124/3664] [client] Clean up some entity component accesses --- libs/client/cl_view.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index 76240c010..4951be9b8 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -778,7 +778,7 @@ V_CalcIntermissionRefdef (viewstate_t *vs) Transform_SetWorldPosition (vs->camera_transform, origin); Transform_SetWorldRotation (vs->camera_transform, rotation); - renderer_t *renderer = Ent_GetComponent (view.id, scene_renderer, cl_world.scene->reg); + renderer_t *renderer = Ent_GetComponent (view.id, scene_renderer, view.reg); renderer->model = NULL; // always idle in intermission @@ -799,8 +799,8 @@ V_CalcRefdef (viewstate_t *vs) vec4f_t origin = vs->player_origin; vec_t *viewangles = vs->player_angles; - renderer_t *renderer = Ent_GetComponent (view.id, scene_renderer, cl_world.scene->reg); - animation_t *animation = Ent_GetComponent (view.id, scene_animation, cl_world.scene->reg); + renderer_t *renderer = Ent_GetComponent (view.id, scene_renderer, view.reg); + animation_t *animation = Ent_GetComponent (view.id, scene_animation, view.reg); V_DriftPitch (vs); From 010b61ee8b349b258004e4b8f313600c2ea50a1c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Nov 2022 10:05:58 +0900 Subject: [PATCH 3125/3664] [qw] Move viewstate movecmd setting to input code Cleans up cl_screen and even simplifies the code. Double bonus :) --- qw/source/cl_input.c | 2 ++ qw/source/cl_screen.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index d0c8fef58..f95e316bf 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -316,6 +316,8 @@ CL_SendCmd (void) if (cls.demorecording) CL_WriteDemoCmd (cmd); + cl.viewstate.movecmd[FORWARD] = cmd->forwardmove; + // deliver the message if (pps_check (dontdrop)) Netchan_Transmit (&cls.netchan, buf.cursize, buf.data); diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 6be96fe98..3b8b1c95e 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -283,9 +283,6 @@ CL_UpdateScreen (double realtime) cl.viewstate.intermission = cl.intermission != 0; V_PrepBlend (&cl.viewstate); - int seq = (cls.netchan.outgoing_sequence - 1) & UPDATE_MASK; - frame_t *frame = &cl.frames[seq]; - cl.viewstate.movecmd[FORWARD] = frame->cmd.forwardmove; V_RenderView (&cl.viewstate); SCR_UpdateScreen (cl.viewstate.camera_transform, realtime, scr_funcs[index]); From 9f01cb25fecc740a162789e783bd7ea600171464 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Nov 2022 10:33:06 +0900 Subject: [PATCH 3126/3664] [qw] Move netgraph setup into cl_ngraph This finally gets cl_screen so it can be merged. --- qw/include/client.h | 3 +-- qw/source/cl_main.c | 1 + qw/source/cl_ngraph.c | 23 ++++++++++++++++++----- qw/source/cl_screen.c | 8 -------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/qw/include/client.h b/qw/include/client.h index 0e125312d..2545b6dba 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -297,8 +297,7 @@ extern struct cbuf_s *cl_stbuf; struct cvar_s; void Cvar_Info (void *data, const struct cvar_s *cvar); -extern struct view_s cl_netgraph_view; -void CL_NetGraph (struct view_s view); +void CL_NetGraph_Init (void); void CL_NetGraph_Init_Cvars (void); extern struct view_s cl_screen_view; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 1a8601205..313f9ec7c 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1510,6 +1510,7 @@ CL_Init (void) Cbuf_DeleteStack (con_module->data->console->cbuf); con_module->data->console->cbuf = cl_cbuf; } + CL_NetGraph_Init (); S_Init (&cl.viewentity, &host_frametime); CDAudio_Init (); diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 06fb9fc1d..887aeb8e4 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -42,6 +42,8 @@ #include "QF/va.h" #include "QF/ui/view.h" +#include "client/hud.h" + #include "compat.h" #include "qw/include/cl_parse.h" @@ -84,7 +86,8 @@ static cvar_t cl_netgraph_height_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &cl_netgraph_height }, }; -view_t cl_netgraph_view; + +static view_t cl_netgraph_view; static void cl_netgraph_f (void *data, const cvar_t *cvar) @@ -105,13 +108,11 @@ cl_netgraph_height_f (void *data, const cvar_t *cvar) } } -void -CL_NetGraph (view_t view) +static void +CL_NetGraph (view_pos_t abs, view_pos_t len) { int lost, a, l, x, y, i, o; int timings[NET_TIMINGS]; - view_pos_t abs = View_GetAbs (view); - view_pos_t len = View_GetLen (view); if (cl_netgraph_box) { r_funcs->Draw_TextBox (abs.x, abs.y, NET_TIMINGS / 8, @@ -151,6 +152,18 @@ CL_NetGraph (view_t view) */ } +void +CL_NetGraph_Init (void) +{ + cl_netgraph_view = View_New (hud_registry, cl_screen_view); + View_SetPos (cl_netgraph_view, 0, hud_sb_lines); + View_SetLen (cl_netgraph_view, NET_TIMINGS + 16, cl_netgraph_height + 25); + View_SetGravity (cl_netgraph_view, grav_southwest); + void *f = CL_NetGraph; + Ent_SetComponent (cl_netgraph_view.id, hud_func, cl_netgraph_view.reg, &f); + View_SetVisible (cl_netgraph_view, cl_netgraph); +} + void CL_NetGraph_Init_Cvars (void) { diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index 3b8b1c95e..1171c143f 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -254,14 +254,6 @@ CL_Init_Screen (void) View_SetGravity (pause_view, grav_center); Ent_SetComponent (pause_view.id, hud_cachepic, pause_view.reg, &name); View_SetVisible (pause_view, 0); - - cl_netgraph_view = View_New (hud_registry, cl_screen_view); - View_SetPos (cl_netgraph_view, 0, hud_sb_lines); - View_SetLen (cl_netgraph_view, NET_TIMINGS + 16, cl_netgraph_height + 25); - View_SetGravity (cl_netgraph_view, grav_southwest); - Ent_SetComponent (cl_netgraph_view.id, hud_func, cl_netgraph_view.reg, - CL_NetGraph); - View_SetVisible (cl_netgraph_view, cl_netgraph); } void From 4491ce213b6fc6f76b1070b4670ac07a11f5f449 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Nov 2022 15:08:09 +0900 Subject: [PATCH 3127/3664] [client] Merge cl_screen.c The client state that was accessed by cl_screen is now put in viewstate and maintained by the client before calling CL_UpdateScreen. --- include/client/screen.h | 10 + include/client/view.h | 4 + libs/client/Makemodule.am | 1 + {nq/source => libs/client}/cl_screen.c | 37 ++-- libs/net/nm/net_dgrm.c | 7 +- nq/include/client.h | 8 - nq/source/Makemodule.am | 2 +- nq/source/cl_demo.c | 2 + nq/source/cl_main.c | 21 +- nq/source/cl_parse.c | 2 +- nq/source/host.c | 2 +- nq/source/host_cmd.c | 11 +- nq/source/sbar.c | 1 + nq/source/sv_ded.c | 3 +- qw/include/client.h | 8 - qw/source/Makemodule.am | 2 +- qw/source/cl_demo.c | 2 + qw/source/cl_main.c | 17 +- qw/source/cl_ngraph.c | 1 + qw/source/cl_parse.c | 11 +- qw/source/cl_screen.c | 281 ------------------------- qw/source/cl_skin.c | 4 +- qw/source/sbar.c | 1 + 23 files changed, 92 insertions(+), 346 deletions(-) create mode 100644 include/client/screen.h rename {nq/source => libs/client}/cl_screen.c (90%) delete mode 100644 qw/source/cl_screen.c diff --git a/include/client/screen.h b/include/client/screen.h new file mode 100644 index 000000000..3d02363a5 --- /dev/null +++ b/include/client/screen.h @@ -0,0 +1,10 @@ +#ifndef __client_screen_h +#define __client_screen_h + +extern struct view_s cl_screen_view; + +struct viewstate_s; +void CL_Init_Screen (void); +void CL_UpdateScreen (struct viewstate_s *vs); + +#endif//__client_screen_h diff --git a/include/client/view.h b/include/client/view.h index 89280a1f2..c2ae534d9 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -60,11 +60,15 @@ typedef struct viewstate_s { vec4f_t punchangle; transform_t camera_transform; double time; + double last_servermessage; float frametime; float height; int weaponframe; int onground; // -1 when in air int active:1; + int loading:1; + int watervis:1; + int demoplayback:1; int drift_enabled:1; int voffs_enabled:1; int bob_enabled:1; diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 92d058458..8c60530a0 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -9,6 +9,7 @@ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_input.c \ libs/client/cl_light.c \ libs/client/cl_particles.c \ + libs/client/cl_screen.c \ libs/client/cl_temp_entities.c \ libs/client/cl_view.c \ libs/client/cl_world.c \ diff --git a/nq/source/cl_screen.c b/libs/client/cl_screen.c similarity index 90% rename from nq/source/cl_screen.c rename to libs/client/cl_screen.c index b0137cabe..035dec6db 100644 --- a/nq/source/cl_screen.c +++ b/libs/client/cl_screen.c @@ -56,9 +56,11 @@ #include "r_local.h" //FIXME for r_cache_thrash #include "client/hud.h" +#include "client/screen.h" +#include "client/view.h" #include "client/world.h" -#include "nq/include/client.h" +//#include "nq/include/client.h" int scr_showpause; static cvar_t scr_showpause_cvar = { @@ -97,20 +99,22 @@ static view_t ram_view; static view_t turtle_view; static view_t pause_view; +static viewstate_t *_vs;//FIXME ick + static void SCR_CShift (void) { mleaf_t *leaf; int contents = CONTENTS_EMPTY; - if (cls.state == ca_active && cl_world.scene->worldmodel) { + if (_vs->active && cl_world.scene->worldmodel) { vec4f_t origin; - origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); + origin = Transform_GetWorldPosition (_vs->camera_transform); leaf = Mod_PointInLeaf (origin, cl_world.scene->worldmodel); contents = leaf->contents; } - V_SetContentsColor (&cl.viewstate, contents); - r_funcs->Draw_BlendScreen (cl.viewstate.cshift_color); + V_SetContentsColor (_vs, contents); + r_funcs->Draw_BlendScreen (_vs->cshift_color); } static void @@ -130,9 +134,9 @@ scr_draw_views (void) View_SetVisible (pause_view, scr_showpause && r_data->paused); View_SetVisible (ram_view, scr_showram && r_cache_thrash); - View_SetVisible (net_view, (!cls.demoplayback - && realtime - cl.last_servermessage >= 0.3)); - View_SetVisible (loading_view, cl.loading); + View_SetVisible (net_view, (!_vs->demoplayback + && _vs->time - _vs->last_servermessage >= 0.3)); + View_SetVisible (loading_view, _vs->loading); // FIXME cvar callbacks View_SetVisible (timegraph_view, r_timegraph); View_SetVisible (zgraph_view, r_zgraph); @@ -256,25 +260,24 @@ CL_Init_Screen (void) } void -CL_UpdateScreen (double realtime) +CL_UpdateScreen (viewstate_t *vs) { - unsigned index = cl.intermission; + unsigned index = vs->intermission; + _vs = vs; if (index >= sizeof (scr_funcs) / sizeof (scr_funcs[0])) index = 0; //FIXME not every time - if (cls.state == ca_active) { - if (cl.watervis) + if (vs->active) { + if (vs->watervis) r_data->min_wateralpha = 0.0; else r_data->min_wateralpha = 1.0; } scr_funcs_normal[0] = r_funcs->Draw_Crosshair; - cl.viewstate.intermission = cl.intermission != 0; - V_PrepBlend (&cl.viewstate); - V_RenderView (&cl.viewstate); - SCR_UpdateScreen (cl.viewstate.camera_transform, - realtime, scr_funcs[index]); + V_PrepBlend (vs); + V_RenderView (vs); + SCR_UpdateScreen (vs->camera_transform, vs->time, scr_funcs[index]); } diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 7004513cc..2e1264075 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -48,6 +48,7 @@ #include "netmain.h" //FIXME these should not be here!!! +#include "client/screen.h" #include "../nq/include/client.h" #include "../nq/include/server.h" @@ -1020,7 +1021,8 @@ _Datagram_Connect (const char *host) // send the connection request Sys_Printf ("trying...\n"); - CL_UpdateScreen (cl.time); + cl.viewstate.time = cl.time; + CL_UpdateScreen (&cl.viewstate); start_time = net_time; for (reps = 0; reps < 3; reps++) { @@ -1081,7 +1083,8 @@ _Datagram_Connect (const char *host) break; } Sys_Printf ("still trying...\n"); - CL_UpdateScreen (cl.time); + cl.viewstate.time = cl.time; + CL_UpdateScreen (&cl.viewstate); start_time = SetNetTime (); } diff --git a/nq/include/client.h b/nq/include/client.h index d9e7ed7d3..e0897e2dc 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -127,8 +127,6 @@ extern client_static_t cls; the client_state_t structure is wiped completely at every server signon */ typedef struct client_state_s { - qboolean loading; - int movemessages; // Since connecting to this server throw out // the first couple, so the player doesn't // accidentally do something the first frame @@ -167,7 +165,6 @@ typedef struct client_state_s { // to decay light values and smooth step ups double last_ping_request; // while showing scoreboard - double last_servermessage; // (realtime) for net trouble icon /* information that is static for the entire time connected to a server */ @@ -186,7 +183,6 @@ typedef struct client_state_s { int sv_cshifts; int no_pogo_stick; int teamplay; - int watervis; int fpd; int fbskins; @@ -289,10 +285,6 @@ extern qboolean recording; struct cvar_s; void Cvar_Info (void *data, const struct cvar_s *cvar); -extern struct view_s cl_screen_view; -void CL_Init_Screen (void); -void CL_UpdateScreen (double realtime); - void CL_SetState (cactive_t state); void CL_Cmd_ForwardToServer (void); diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index 9fac07a69..a83a41d17 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -73,7 +73,7 @@ nq_server_LIB_DEPS=$(nq_server_LIBFILES) $(nq_common_LIBFILES) nq_source_libnq_client_a_SOURCES= \ nq/source/cl_cmd.c nq/source/cl_demo.c nq/source/cl_ents.c nq/source/cl_input.c nq/source/cl_main.c \ - nq/source/cl_screen.c nq/source/cl_parse.c nq/source/sbar.c + nq/source/cl_parse.c nq/source/sbar.c nq_source_libnq_server_a_SOURCES= \ nq/source/host.c nq/source/host_cmd.c nq/source/sv_cl_phys.c nq/source/sv_cvar.c nq/source/sv_main.c \ diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 5226251aa..603a21530 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -167,6 +167,7 @@ CL_StopPlayback (void) CL_SetState (ca_disconnected); cls.demo_capture = 0; cls.demoplayback = 0; + cl.viewstate.demoplayback = 0; if (cls.timedemo) CL_FinishTimeDemo (); @@ -515,6 +516,7 @@ CL_StartDemo (void) } cls.demoplayback = true; + cl.viewstate.demoplayback = 1; CL_SetState (ca_connected); cls.forcetrack = 0; diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 6bdb40530..b0f8a6978 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -59,6 +59,7 @@ #include "client/chase.h" #include "client/particles.h" +#include "client/screen.h" #include "client/temp_entities.h" #include "client/world.h" @@ -297,7 +298,7 @@ CL_ClearState (void) cl.viewstate.chase = 1; cl.viewstate.chasestate = &cl.chasestate; cl.chasestate.viewstate = &cl.viewstate; - cl.watervis = 1; + cl.viewstate.watervis = 1; SCR_SetFullscreen (0); r_data->lightstyle = cl.lightstyle; @@ -434,7 +435,7 @@ CL_SignonReply (void) break; case so_active: - cl.loading = false; + cl.viewstate.loading = false; CL_SetState (ca_active); break; } @@ -451,8 +452,9 @@ CL_NextDemo (void) if (cls.demonum == -1) return; // don't play demos - cl.loading = true; - CL_UpdateScreen(cl.time); + cl.viewstate.loading = true; + cl.viewstate.time = cl.time; + CL_UpdateScreen(&cl.viewstate); if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) { cls.demonum = 0; @@ -589,25 +591,25 @@ CL_SetState (cactive_t state) case ca_disconnected: CL_ClearState (); cls.signon = so_none; - cl.loading = false; + cl.viewstate.loading = false; VID_SetCaption ("Disconnected"); break; case ca_connected: cls.signon = so_none; // need all the signon messages // before playing - cl.loading = true; + cl.viewstate.loading = true; IN_ClearStates (); VID_SetCaption ("Connected"); break; case ca_active: // entering active state - cl.loading = false; + cl.viewstate.loading = false; IN_ClearStates (); VID_SetCaption (""); S_AmbientOn (); break; } - CL_UpdateScreen (cl.time); + CL_UpdateScreen (&cl.viewstate); } host_in_game = 0; Con_SetState (state == ca_active ? con_inactive : con_fullscreen); @@ -660,7 +662,8 @@ CL_Frame (void) || cl.stats[STAT_HEALTH] <= 0); r_data->frametime = host_frametime; - CL_UpdateScreen (cl.time); + cl.viewstate.intermission = cl.intermission != 0; + CL_UpdateScreen (&cl.viewstate); if (host_speeds) time2 = Sys_DoubleTime (); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index fc258161f..516b971d2 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -722,7 +722,7 @@ CL_ParseServerMessage (void) static dstring_t *stuffbuf; signon_t so; - cl.last_servermessage = realtime; + cl.viewstate.last_servermessage = realtime; TEntContext_t tentCtx = { cl.viewstate.player_origin, cl.viewentity diff --git a/nq/source/host.c b/nq/source/host.c index f943a564a..a3fde4e6b 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -309,7 +309,7 @@ Host_Error (const char *error, ...) inerror = true; - cl.loading = false; + cl.viewstate.loading = false; va_start (argptr, error); dvsprintf (str, error, argptr); diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index 3bd37b6d0..c6c6a6664 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -50,6 +50,7 @@ #include "QF/sys.h" #include "QF/va.h" +#include "client/screen.h" #include "client/world.h" #include "compat.h" @@ -294,8 +295,9 @@ Host_Map_f (void) CL_Disconnect (); Host_ShutdownServer (false); - cl.loading = true; - CL_UpdateScreen (cl.time); + cl.viewstate.loading = true; + cl.viewstate.time = cl.time; + CL_UpdateScreen (&cl.viewstate); svs.serverflags = 0; // haven't completed an episode yet strcpy (name, Cmd_Argv (1)); @@ -624,8 +626,9 @@ Host_Loadgame_f (void) dsprintf (name, "%s/%s", qfs_gamedir->dir.def, Cmd_Argv (1)); QFS_DefaultExtension (name, ".sav"); - cl.loading = true; - CL_UpdateScreen (cl.time); + cl.viewstate.loading = true; + cl.viewstate.time = cl.time; + CL_UpdateScreen (&cl.viewstate); Sys_Printf ("Loading game from %s...\n", name->str); f = QFS_Open (name->str, "rz"); diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 716bc1b33..77ca0ba55 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -58,6 +58,7 @@ #include "sbar.h" #include "client/hud.h" +#include "client/screen.h" #include "nq/include/client.h" #include "nq/include/game.h" diff --git a/nq/source/sv_ded.c b/nq/source/sv_ded.c index 0b4e7b88d..e37476539 100644 --- a/nq/source/sv_ded.c +++ b/nq/source/sv_ded.c @@ -38,6 +38,7 @@ #include "client/world.h" +#include "client/screen.h" #include "nq/include/client.h" #include "nq/include/host.h" #include "nq/include/server.h" @@ -78,7 +79,7 @@ CL_SetState (cactive_t state) } void -CL_UpdateScreen (double realtime) +CL_UpdateScreen (struct viewstate_s *) { } diff --git a/qw/include/client.h b/qw/include/client.h index 2545b6dba..54292cbab 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -176,8 +176,6 @@ extern client_static_t cls; the client_state_t structure is wiped completely at every server signon */ typedef struct client_state_s { - qboolean loading; - int movemessages; // Since connecting to this server throw out // the first couple, so the player doesn't // accidentally do something the first frame @@ -215,7 +213,6 @@ typedef struct client_state_s { // can't render a frame yet double last_ping_request; // while showing scoreboard - double last_servermessage; // (realtime) for net trouble icon /* information that is static for the entire time connected to a server */ @@ -238,7 +235,6 @@ typedef struct client_state_s { int sv_cshifts; int no_pogo_stick; int teamplay; - int watervis; int fpd; int fbskins; @@ -300,10 +296,6 @@ void Cvar_Info (void *data, const struct cvar_s *cvar); void CL_NetGraph_Init (void); void CL_NetGraph_Init_Cvars (void); -extern struct view_s cl_screen_view; -void CL_Init_Screen (void); -void CL_UpdateScreen (double realtime); - void CL_SetState (cactive_t state); void CL_Cmd_ForwardToServer (void); diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index afc5ff385..8caffdc5e 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -106,7 +106,7 @@ qw_client_libs= qw/source/libqw_client.a qw/source/libqw_common.a \ qw_source_libqw_client_a_SOURCES= \ qw/source/cl_cam.c qw/source/cl_chat.c qw/source/cl_cmd.c qw/source/cl_cvar.c qw/source/cl_demo.c \ qw/source/cl_entparse.c qw/source/cl_ents.c qw/source/cl_http.c qw/source/cl_input.c qw/source/cl_main.c qw/source/cl_ngraph.c \ - qw/source/cl_parse.c qw/source/cl_pred.c qw/source/cl_rss.c qw/source/cl_screen.c qw/source/cl_skin.c qw/source/cl_slist.c \ + qw/source/cl_parse.c qw/source/cl_pred.c qw/source/cl_rss.c qw/source/cl_skin.c qw/source/cl_slist.c \ qw/source/sbar.c qw/source/teamplay.c # Software-rendering clients diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index 0026b72f5..a114c6db5 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -187,6 +187,7 @@ CL_StopPlayback (void) cls.demo_capture = 0; cls.demoplayback = 0; cls.demoplayback2 = 0; + cl.viewstate.demoplayback = 0; demotime_cached = 0; net_blocksend = 0; @@ -1052,6 +1053,7 @@ CL_StartDemo (void) Sys_Printf ("Playing demo from %s.\n", name->str); cls.demoplayback = true; + cl.viewstate.demoplayback = 1; net_blocksend = 1; if (type == 2) { cls.demoplayback2 = true; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 313f9ec7c..3ee98653f 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -98,6 +98,7 @@ #include "sbar.h" #include "client/particles.h" +#include "client/screen.h" #include "client/temp_entities.h" #include "client/view.h" #include "client/world.h" @@ -909,7 +910,7 @@ CL_FullServerinfo_f (void) Sbar_DMO_Init_f (0, 0); // HUD setup, cl.teamplay changed } if ((p = Info_ValueForKey (cl.serverinfo, "watervis")) && *p) { - cl.watervis = atoi (p); + cl.viewstate.watervis = atoi (p); } if ((p = Info_ValueForKey (cl.serverinfo, "fpd")) && *p) { cl.fpd = atoi (p); @@ -1985,7 +1986,8 @@ Host_Frame (float time) || cl.stats[STAT_HEALTH] <= 0); r_data->frametime = host_frametime; - CL_UpdateScreen (realtime); + cl.viewstate.time = realtime; + CL_UpdateScreen (&cl.viewstate); if (host_speeds) time2 = Sys_DoubleTime (); @@ -2126,8 +2128,9 @@ Host_Init (void) CL_Init (); - CL_UpdateScreen (realtime); - CL_UpdateScreen (realtime); + cl.viewstate.time = realtime; + CL_UpdateScreen (&cl.viewstate); + CL_UpdateScreen (&cl.viewstate); Host_ExecConfig (cl_cbuf, !cl_quakerc); @@ -2144,10 +2147,10 @@ Host_Init (void) host_initialized = true; - CL_UpdateScreen (realtime); + CL_UpdateScreen (&cl.viewstate); Con_NewMap (); // force the menus to be loaded - CL_UpdateScreen (realtime); - CL_UpdateScreen (realtime); + CL_UpdateScreen (&cl.viewstate); + CL_UpdateScreen (&cl.viewstate); if (connect_time == -1) { Cbuf_AddText (cl_cbuf, "echo Type connect or use a " diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 887aeb8e4..1d7bf282f 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -43,6 +43,7 @@ #include "QF/ui/view.h" #include "client/hud.h" +#include "client/screen.h" #include "compat.h" diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 4f279c4aa..d532550f9 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -68,6 +68,7 @@ #include "client/effects.h" #include "client/particles.h" +#include "client/screen.h" #include "client/temp_entities.h" #include "client/view.h" #include "client/world.h" @@ -284,7 +285,8 @@ Model_NextDownload (void) if (cls.downloadnumber == 0) { Sys_Printf ("Checking models...\n"); - CL_UpdateScreen (realtime); + cl.viewstate.time = realtime; + CL_UpdateScreen (&cl.viewstate); cls.downloadnumber = 1; } @@ -373,7 +375,8 @@ Sound_NextDownload (void) if (cls.downloadnumber == 0) { Sys_Printf ("Checking sounds...\n"); - CL_UpdateScreen (realtime); + cl.viewstate.time = realtime; + CL_UpdateScreen (&cl.viewstate); cls.downloadnumber = 1; } @@ -1121,7 +1124,7 @@ CL_ServerInfo (void) cl.teamplay = atoi (value); Sbar_DMO_Init_f (0, 0); // HUD setup, cl.teamplay changed } else if (strequal (key, "watervis")) { - cl.watervis = atoi (value); + cl.viewstate.watervis = atoi (value); } else if (strequal (key, "fpd")) { cl.fpd = atoi (value); } else if (strequal (key, "fbskins")) { @@ -1219,7 +1222,7 @@ CL_ParseServerMessage (void) }; received_framecount = host_framecount; - cl.last_servermessage = realtime; + cl.viewstate.last_servermessage = realtime; CL_ClearProjectiles (); // if recording demos, copy the message out diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c deleted file mode 100644 index 1171c143f..000000000 --- a/qw/source/cl_screen.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - cl_screen.c - - master for refresh, status bar, console, chat, notify, etc - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include - -#include "QF/console.h" -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/image.h" -#include "QF/pcx.h" -#include "QF/screen.h" - -#include "QF/plugin/console.h" -#include "QF/plugin/vid_render.h" - -#include "QF/scene/scene.h" -#include "QF/scene/transform.h" -#include "QF/ui/view.h" - -#include "sbar.h" - -#include "r_local.h" //FIXME for r_cache_thrash - -#include "client/hud.h" -#include "client/world.h" - -#include "qw/include/client.h" -#include "qw/include/cl_parse.h" - -int scr_showpause; -static cvar_t scr_showpause_cvar = { - .name = "showpause", - .description = - "Toggles display of pause graphic", - .default_value = "1", - .flags = CVAR_NONE, - .value = { .type = &cexpr_int, .value = &scr_showpause }, -}; -int scr_showram; -static cvar_t scr_showram_cvar = { - .name = "showram", - .description = - "Show RAM icon if game is running low on memory", - .default_value = "1", - .flags = CVAR_NONE, - .value = { .type = &cexpr_int, .value = &scr_showram }, -}; -int scr_showturtle; -static cvar_t scr_showturtle_cvar = { - .name = "showturtle", - .description = - "Show a turtle icon if your fps is below 10", - .default_value = "0", - .flags = CVAR_NONE, - .value = { .type = &cexpr_int, .value = &scr_showturtle }, -}; - -view_t cl_screen_view; -static view_t net_view; -static view_t timegraph_view; -static view_t zgraph_view; -static view_t loading_view; -static view_t ram_view; -static view_t turtle_view; -static view_t pause_view; - -static void -SCR_CShift (void) -{ - mleaf_t *leaf; - int contents = CONTENTS_EMPTY; - - if (cls.state == ca_active && cl_world.scene->worldmodel) { - vec4f_t origin; - origin = Transform_GetWorldPosition (cl.viewstate.camera_transform); - leaf = Mod_PointInLeaf (origin, cl_world.scene->worldmodel); - contents = leaf->contents; - } - V_SetContentsColor (&cl.viewstate, contents); - r_funcs->Draw_BlendScreen (cl.viewstate.cshift_color); -} - -static void -scr_draw_views (void) -{ - if (scr_showturtle) { - static int count; - if (r_data->frametime < 0.1) { - count = 0; - } else { - count++; - } - View_SetVisible (turtle_view, count > 2); - } - - // turn off for screenshots - View_SetVisible (pause_view, scr_showpause && r_data->paused); - - View_SetVisible (ram_view, scr_showram && r_cache_thrash); - View_SetVisible (net_view, (!cls.demoplayback - && realtime - cl.last_servermessage >= 0.3)); - View_SetVisible (loading_view, cl.loading); - // FIXME cvar callbacks - View_SetVisible (timegraph_view, r_timegraph); - View_SetVisible (zgraph_view, r_zgraph); -} - -static SCR_Func scr_funcs_normal[] = { - 0, //Draw_Crosshair, - Sbar_Draw, - HUD_Draw_Views, - SCR_CShift, - Sbar_DrawCenterPrint, - scr_draw_views, - Con_DrawConsole, - 0 -}; - -static SCR_Func scr_funcs_intermission[] = { - Sbar_IntermissionOverlay, - Con_DrawConsole, - scr_draw_views, - 0 -}; - -static SCR_Func scr_funcs_finale[] = { - Sbar_FinaleOverlay, - Con_DrawConsole, - scr_draw_views, - 0, -}; - -static SCR_Func *scr_funcs[] = { - scr_funcs_normal, - scr_funcs_intermission, - scr_funcs_finale, -}; - -static void -cl_vidsize_listener (void *data, const viddef_t *vdef) -{ - View_SetLen (cl_screen_view, vdef->width, vdef->height); - View_UpdateHierarchy (cl_screen_view); -} - -void -CL_Init_Screen (void) -{ - qpic_t *pic; - - VID_OnVidResize_AddListener (cl_vidsize_listener, 0); - - HUD_Init (); - - cl_screen_view = View_New (hud_registry, nullview); - con_module->data->console->screen_view = &cl_screen_view; - - View_SetPos (cl_screen_view, 0, 0); - View_SetLen (cl_screen_view, viddef.width, viddef.height); - View_SetGravity (cl_screen_view, grav_northwest); - View_SetVisible (cl_screen_view, 1); - - pic = r_funcs->Draw_PicFromWad ("ram"); - ram_view = View_New (hud_registry, cl_screen_view); - View_SetPos (ram_view, 32, 0); - View_SetLen (ram_view, pic->width, pic->height); - View_SetGravity (ram_view, grav_northwest); - Ent_SetComponent (ram_view.id, hud_pic, ram_view.reg, &pic); - View_SetVisible (ram_view, 0); - - pic = r_funcs->Draw_PicFromWad ("turtle"); - turtle_view = View_New (hud_registry, cl_screen_view); - View_SetPos (turtle_view, 32, 0); - View_SetLen (turtle_view, pic->width, pic->height); - View_SetGravity (turtle_view, grav_northwest); - Ent_SetComponent (turtle_view.id, hud_pic, turtle_view.reg, &pic); - View_SetVisible (turtle_view, 0); - - Cvar_Register (&scr_showpause_cvar, 0, 0); - Cvar_Register (&scr_showram_cvar, 0, 0); - Cvar_Register (&scr_showturtle_cvar, 0, 0); - - pic = r_funcs->Draw_PicFromWad ("net"); - net_view = View_New (hud_registry, cl_screen_view); - View_SetPos (net_view, 64, 0); - View_SetLen (net_view, pic->width, pic->height); - View_SetGravity (net_view, grav_northwest); - Ent_SetComponent (net_view.id, hud_pic, net_view.reg, &pic); - View_SetVisible (net_view, 0); - - timegraph_view = View_New (hud_registry, cl_screen_view); - View_SetPos (timegraph_view, 0, 0); - View_SetLen (timegraph_view, r_data->vid->width, 100); - View_SetGravity (timegraph_view, grav_southwest); - Ent_SetComponent (timegraph_view.id, hud_func, timegraph_view.reg, - R_TimeGraph); - View_SetVisible (timegraph_view, r_timegraph); - - zgraph_view = View_New (hud_registry, cl_screen_view); - View_SetPos (zgraph_view, 0, 0); - View_SetLen (zgraph_view, r_data->vid->width, 100); - View_SetGravity (zgraph_view, grav_southwest); - Ent_SetComponent (zgraph_view.id, hud_func, zgraph_view.reg, R_ZGraph); - View_SetVisible (zgraph_view, r_zgraph); - - const char *name = "gfx/loading.lmp"; - pic = r_funcs->Draw_CachePic (name, 1); - loading_view = View_New (hud_registry, cl_screen_view); - View_SetPos (loading_view, 0, -24); - View_SetLen (loading_view, pic->width, pic->height); - View_SetGravity (loading_view, grav_center); - Ent_SetComponent (loading_view.id, hud_cachepic, loading_view.reg, &name); - View_SetVisible (loading_view, 0); - - name = "gfx/pause.lmp"; - pic = r_funcs->Draw_CachePic (name, 1); - pause_view = View_New (hud_registry, cl_screen_view); - View_SetPos (pause_view, 0, -24); - View_SetLen (pause_view, pic->width, pic->height); - View_SetGravity (pause_view, grav_center); - Ent_SetComponent (pause_view.id, hud_cachepic, pause_view.reg, &name); - View_SetVisible (pause_view, 0); -} - -void -CL_UpdateScreen (double realtime) -{ - unsigned index = cl.intermission; - - if (index >= sizeof (scr_funcs) / sizeof (scr_funcs[0])) - index = 0; - - //FIXME not every time - if (cls.state == ca_active) { - if (cl.watervis) - r_data->min_wateralpha = 0.0; - else - r_data->min_wateralpha = 1.0; - } - scr_funcs_normal[0] = r_funcs->Draw_Crosshair; - - cl.viewstate.intermission = cl.intermission != 0; - V_PrepBlend (&cl.viewstate); - V_RenderView (&cl.viewstate); - SCR_UpdateScreen (cl.viewstate.camera_transform, - realtime, scr_funcs[index]); -} diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index 00fe557f6..807b98f43 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -43,6 +43,7 @@ #include "QF/sys.h" #include "QF/va.h" +#include "client/screen.h" #include "compat.h" #include "qw/include/cl_parse.h" @@ -99,7 +100,8 @@ Skin_NextDownload (void) if (cls.downloadnumber == 0) { Sys_Printf ("Checking skins...\n"); - CL_UpdateScreen (realtime); + cl.viewstate.time = realtime; + CL_UpdateScreen (&cl.viewstate); } cls.downloadtype = dl_skin; diff --git a/qw/source/sbar.c b/qw/source/sbar.c index e2cf0f8b7..17cc61099 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -60,6 +60,7 @@ #include "compat.h" #include "client/hud.h" +#include "client/screen.h" #include "client/world.h" #include "qw/bothdefs.h" From 0626ec646970e345a7aafcbe07869b235521a50c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Nov 2022 11:38:32 +0900 Subject: [PATCH 3128/3664] [nq] Get scores display working again Now only the time portion updates every frame, and then only when the scores are shown (no real change for that one). Not really a significant optimization, as the information was updated only while the scores were shown, but it's still nice. --- include/sbar.h | 2 +- nq/source/sbar.c | 200 +++++++++++++++++++++++++++++------------------ 2 files changed, 127 insertions(+), 75 deletions(-) diff --git a/include/sbar.h b/include/sbar.h index 71417406f..6c1f74317 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -33,7 +33,7 @@ #define SBAR_HEIGHT 24 -extern int sb_lines; // scan lines to draw +//extern int sb_lines; // scan lines to draw void Sbar_Init (void); diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 77ca0ba55..b6c8584b1 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -81,9 +81,19 @@ static view_t sbar_armor; static view_t sbar_face; static view_t sbar_health; static view_t sbar_ammo; -//static view_t sbar_status; +static view_t sbar_solo; +static view_t sbar_solo_monsters; +static view_t sbar_solo_secrets; +static view_t sbar_solo_time; +static view_t sbar_solo_anchor; +static view_t sbar_solo_name; static view_t sbar_tile[2]; +static draw_charbuffer_t *solo_monsters; +static draw_charbuffer_t *solo_secrets; +static draw_charbuffer_t *solo_time; +static draw_charbuffer_t *solo_name; + static view_t sbar_view (int x, int y, int w, int h, grav_t gravity, view_t parent) { @@ -121,43 +131,43 @@ sbar_remcomponent (view_t view, uint32_t comp) #define STAT_MINUS 10 // num frame for '-' stats digit -qpic_t *sb_nums[2][11]; -qpic_t *sb_colon, *sb_slash; -qpic_t *sb_ibar; -qpic_t *sb_sbar; -qpic_t *sb_scorebar; +static qpic_t *sb_nums[2][11]; +static qpic_t *sb_colon, *sb_slash; +static qpic_t *sb_ibar; +static qpic_t *sb_sbar; +static qpic_t *sb_scorebar; -qpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes -qpic_t *sb_ammo[4]; -qpic_t *sb_sigil[4]; -qpic_t *sb_armor[3]; -qpic_t *sb_items[32]; +static qpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes +static qpic_t *sb_ammo[4]; +static qpic_t *sb_sigil[4]; +static qpic_t *sb_armor[3]; +static qpic_t *sb_items[32]; -qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive +static qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive // 0 is static, 1 is temporary animation -qpic_t *sb_face_invis; -qpic_t *sb_face_quad; -qpic_t *sb_face_invuln; -qpic_t *sb_face_invis_invuln; +static qpic_t *sb_face_invis; +static qpic_t *sb_face_quad; +static qpic_t *sb_face_invuln; +static qpic_t *sb_face_invis_invuln; -qboolean sb_showscores; +static qboolean sb_showscores; -int sb_lines; // scan lines to draw +static int sb_lines; // scan lines to draw -qpic_t *rsb_invbar[2]; -qpic_t *rsb_weapons[5]; -qpic_t *rsb_items[2]; -qpic_t *rsb_ammo[3]; -qpic_t *rsb_teambord; // PGM 01/19/97 - team color border +static qpic_t *rsb_invbar[2]; +static qpic_t *rsb_weapons[5]; +static qpic_t *rsb_items[2]; +static qpic_t *rsb_ammo[3]; +static qpic_t *rsb_teambord; // PGM 01/19/97 - team color border // MED 01/04/97 added two more weapons + 3 // alternates for grenade launcher -qpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes +static qpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes // MED 01/04/97 added array to simplify // weapon parsing -int hipweapons[4] = - { HIT_LASER_CANNON_BIT, HIT_MJOLNIR_BIT, 4, HIT_PROXIMITY_GUN_BIT }; +//static int hipweapons[4] = +// { HIT_LASER_CANNON_BIT, HIT_MJOLNIR_BIT, 4, HIT_PROXIMITY_GUN_BIT }; qpic_t *hsb_items[2]; // MED 01/04/97 added hipnotic items array float scr_centertime; @@ -196,23 +206,6 @@ Sbar_ColorForMap (int m) return (bound (0, m, 13) * 16) + 8; } -static void -Sbar_ShowScores (void) -{ - if (sb_showscores) - return; - - sb_showscores = true; - sb_updates = 0; -} - -static void -Sbar_DontShowScores (void) -{ - sb_showscores = false; - sb_updates = 0; -} - void Sbar_Changed (sbar_changed change) { @@ -504,35 +497,45 @@ Sbar_SortTeams (void) } } -static void __attribute__((used)) -draw_solo (view_t *view) +static int +write_charbuff (draw_charbuffer_t *buffer, int x, int y, const char *str) { -#if 0 - char str[80]; - int minutes, seconds; - int l; + char *dst = buffer->chars; + int count = buffer->width - x; + int chars = 0; + dst += y * buffer->width + x; + while (*str && count-- > 0) { + *dst++ = *str++; + chars++; + } + while (count-- > 0) { + *dst++ = ' '; + } + return chars; +} - draw_pic (view, 0, 0, sb_scorebar); +static void +draw_solo_time (void) +{ + int minutes = cl.time / 60; + int seconds = cl.time - 60 * minutes; + write_charbuff (solo_time, 0, 0, + va (0, "Time :%3i:%02i", minutes, seconds)); +} - snprintf (str, sizeof (str), "Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], - cl.stats[STAT_TOTALMONSTERS]); - draw_string (view, 8, 4, str); - - snprintf (str, sizeof (str), "Secrets :%3i /%3i", cl.stats[STAT_SECRETS], - cl.stats[STAT_TOTALSECRETS]); - draw_string (view, 8, 12, str); - - // time - minutes = cl.time / 60; - seconds = cl.time - 60 * minutes; - snprintf (str, sizeof (str), "Time :%3i:%02i", minutes, seconds); - draw_string (view, 184, 4, str); - - // draw level name - l = strlen (cl.levelname); - l = 232 - l * 4; - draw_string (view, max (l, 152), 12, cl.levelname); -#endif +static void +draw_solo (void) +{ + write_charbuff (solo_monsters, 0, 0, + va (0, "Monsters:%3i /%3i", + cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS])); + write_charbuff (solo_secrets, 0, 0, + va (0, "Secrets :%3i /%3i", + cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS])); + draw_solo_time (); + view_pos_t len = View_GetLen (sbar_solo_name); + len.x = 8 * write_charbuff (solo_name, 0, 0, cl.levelname); + View_SetLen (sbar_solo_name, len.x, len.y); } static void @@ -1425,6 +1428,9 @@ Sbar_Draw (void) if (sb_update_flags & ((1 << sbc_health) | (1 << sbc_items))) { draw_face (sbar_face); } + if (sb_showscores) { + draw_solo_time (); + } #if 0 sbar_update_vis (); hud_main_view->draw (hud_main_view); @@ -1521,6 +1527,12 @@ init_sbar_views (void) sbar_ammo = sbar_view (224, 0, 96, 24, grav_northwest, sbar_statusbar); sbar_tile[0] = sbar_view ( 0, 0, 0, 48, grav_southwest, sbar_main); sbar_tile[1] = sbar_view ( 0, 0, 0, 48, grav_southeast, sbar_main); + sbar_solo = sbar_view ( 0, 0, 320, 24, grav_southwest, sbar_main); + sbar_solo_monsters = sbar_view ( 8, 4, 136, 8, grav_northwest, sbar_solo); + sbar_solo_secrets = sbar_view ( 8, 12, 136, 8, grav_northwest, sbar_solo); + sbar_solo_time = sbar_view (184, 4, 96, 8, grav_northwest, sbar_solo); + sbar_solo_anchor = sbar_view (232, 12, 0, 8, grav_northwest, sbar_solo); + sbar_solo_name = sbar_view (0, 0, 0, 8, grav_center, sbar_solo_anchor); for (int i = 0; i < 4; i++) { sbar_view (i * 8, 0, 8, 16, grav_northwest, sbar_sigils); @@ -1556,6 +1568,11 @@ init_sbar_views (void) sbar_setcomponent (sbar_tile[0], hud_tile, 0); sbar_setcomponent (sbar_tile[1], hud_tile, 0); } + + solo_monsters = Draw_CreateBuffer (17, 1); + solo_secrets = Draw_CreateBuffer (17, 1); + solo_time = Draw_CreateBuffer (12, 1); + solo_name = Draw_CreateBuffer (20, 1); } static void @@ -1980,11 +1997,6 @@ load_pics (void) sb_face_invis_invuln = r_funcs->Draw_PicFromWad ("face_inv2"); sb_face_quad = r_funcs->Draw_PicFromWad ("face_quad"); - Cmd_AddCommand ("+showscores", Sbar_ShowScores, - "Display information on everyone playing"); - Cmd_AddCommand ("-showscores", Sbar_DontShowScores, - "Stop displaying information on everyone playing"); - sb_sbar = r_funcs->Draw_PicFromWad ("sbar"); sb_ibar = r_funcs->Draw_PicFromWad ("ibar"); sb_scorebar = r_funcs->Draw_PicFromWad ("scorebar"); @@ -2044,6 +2056,41 @@ load_pics (void) } } +static void +Sbar_ShowScores (void) +{ + if (sb_showscores) + return; + + sb_showscores = true; + sb_updates = 0; + + sbar_setcomponent (sbar_solo, hud_pic, &sb_scorebar); + sbar_setcomponent (sbar_solo_monsters, hud_charbuff, &solo_monsters); + sbar_setcomponent (sbar_solo_secrets, hud_charbuff, &solo_secrets); + sbar_setcomponent (sbar_solo_time, hud_charbuff, &solo_time); + sbar_setcomponent (sbar_solo_name, hud_charbuff, &solo_name); + + draw_solo (); + View_UpdateHierarchy (sbar_solo); +} + +static void +Sbar_DontShowScores (void) +{ + if (!sb_showscores) + return; + + sb_showscores = false; + sb_updates = 0; + + sbar_remcomponent (sbar_solo, hud_pic); + sbar_remcomponent (sbar_solo_monsters, hud_charbuff); + sbar_remcomponent (sbar_solo_secrets, hud_charbuff); + sbar_remcomponent (sbar_solo_time, hud_charbuff); + sbar_remcomponent (sbar_solo_name, hud_charbuff); +} + void Sbar_Init (void) { @@ -2055,6 +2102,11 @@ Sbar_Init (void) init_views (); View_UpdateHierarchy (sbar_main); + Cmd_AddCommand ("+showscores", Sbar_ShowScores, + "Display information on everyone playing"); + Cmd_AddCommand ("-showscores", Sbar_DontShowScores, + "Stop displaying information on everyone playing"); + r_data->viewsize_callback = viewsize_f; Cvar_Register (&scr_centertime_cvar, 0, 0); Cvar_Register (&scr_printspeed_cvar, 0, 0); From 82d407e3c28d8ed97e95622bdc239d095255e840 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Nov 2022 14:46:44 +0900 Subject: [PATCH 3129/3664] [nq] Get hud time and fps displays working This includes moving the related cvars from botn nq and qw into the client hud code. In addition, the hud code supports update and update-once function components. The update component is for updates that occur every frame, but update-once components (not used yet) are for one-shot updates (eg, when a value updates very infrequently). --- include/QF/screen.h | 2 - include/client/hud.h | 8 ++++ libs/client/hud.c | 87 ++++++++++++++++++++++++++++++++++++++++---- nq/source/cl_main.c | 22 ----------- nq/source/sbar.c | 66 +++++++++++++++++++++++---------- qw/include/client.h | 3 -- qw/source/cl_main.c | 41 --------------------- 7 files changed, 135 insertions(+), 94 deletions(-) diff --git a/include/QF/screen.h b/include/QF/screen.h index 98c1d4b94..d5e7bd81f 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -46,8 +46,6 @@ void SCR_SetBottomMargin (int lines); void SCR_NewScene (struct scene_s *scene); -extern int hud_fps; -extern int hud_time; extern int r_timegraph; extern int r_zgraph; extern int scr_copytop; diff --git a/include/client/hud.h b/include/client/hud.h index cc11419fe..3d3e876a2 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -30,6 +30,8 @@ enum { hud_href, + hud_update, + hud_updateonce, hud_tile, hud_pic, hud_subpic, @@ -53,6 +55,10 @@ extern int hud_sb_lines; extern int hud_sbar; extern int hud_swap; +extern int hud_fps; +extern int hud_pl; +extern int hud_ping; +extern int hud_time; //extern struct view_s sbar_view; //extern struct view_s sbar_inventory_view; @@ -65,6 +71,8 @@ extern struct view_s hud_frags_view; extern struct view_s hud_overlay_view; extern struct view_s hud_stuff_view; +extern struct view_s hud_time_view; +extern struct view_s hud_fps_view; extern struct view_s hud_main_view; void HUD_Init (void); diff --git a/libs/client/hud.c b/libs/client/hud.c index 7ba7c3354..9c375e50d 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -46,6 +46,14 @@ static const component_t hud_components[hud_comp_count] = { .size = sizeof (hierref_t), .name = "href", }, + [hud_update] = { + .size = sizeof (void (*)(view_t)), + .name = "update", + }, + [hud_updateonce] = { + .size = sizeof (void (*)(view_t)), + .name = "updateonce", + }, [hud_tile] = { .size = sizeof (byte), .name = "pic", @@ -107,6 +115,42 @@ static cvar_t hud_swap_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &hud_swap }, }; +int hud_fps; +static cvar_t hud_fps_cvar = { + .name = "hud_fps", + .description = + "display realtime frames per second", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_fps }, +}; +int hud_ping; +static cvar_t hud_ping_cvar = { + .name = "hud_ping", + .description = + "display current ping to server", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_ping }, +}; +int hud_pl; +static cvar_t hud_pl_cvar = { + .name = "hud_pl", + .description = + "display current packet loss to server", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_pl }, +}; +int hud_time; +static cvar_t hud_time_cvar = { + .name = "hud_time", + .description = + "display the current time", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &hud_time }, +}; view_t sbar_view; view_t sbar_inventory_view; @@ -119,6 +163,8 @@ view_t hud_frags_view; view_t hud_overlay_view; view_t hud_stuff_view; +view_t hud_time_view; +view_t hud_fps_view; view_t hud_main_view; static void @@ -181,6 +227,12 @@ HUD_Init (void) void HUD_Init_Cvars (void) { + Cvar_Register (&hud_fps_cvar, 0, 0); + Cvar_MakeAlias ("show_fps", &hud_fps_cvar); + Cvar_Register (&hud_ping_cvar, 0, 0); + Cvar_Register (&hud_pl_cvar, 0, 0); + Cvar_Register (&hud_time_cvar, 0, 0); + Cvar_Register (&hud_sbar_cvar, hud_sbar_f, 0); Cvar_Register (&hud_swap_cvar, hud_swap_f, 0); Cvar_Register (&hud_scoreboard_gravity_cvar, hud_scoreboard_gravity_f, 0); @@ -221,6 +273,25 @@ HUD_Calc_sb_lines (int view_size) #endif } +static void +draw_update (ecs_pool_t *pool) +{ + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + void (**func) (view_t) = pool->data; + while (count-- > 0) { + view_t view = { .id = *ent++, .reg = hud_registry }; + (*func++) (view); + } +} + +static void +draw_updateonce (ecs_pool_t *pool) +{ + draw_update (pool); + pool->count = 0; +} + static void draw_tile_views (ecs_pool_t *pool) { @@ -340,13 +411,15 @@ void HUD_Draw_Views (void) { static void (*draw_func[hud_comp_count]) (ecs_pool_t *) = { - [hud_tile] = draw_tile_views, - [hud_pic] = draw_pic_views, - [hud_subpic] = draw_subpic_views, - [hud_cachepic] = draw_cachepic_views, - [hud_fill] = draw_fill_views, - [hud_charbuff] = draw_charbuff_views, - [hud_func] = draw_func_views, + [hud_update] = draw_update, + [hud_updateonce] = draw_updateonce, + [hud_tile] = draw_tile_views, + [hud_pic] = draw_pic_views, + [hud_subpic] = draw_subpic_views, + [hud_cachepic] = draw_cachepic_views, + [hud_fill] = draw_fill_views, + [hud_charbuff] = draw_charbuff_views, + [hud_func] = draw_func_views, }; for (int i = 0; i < hud_comp_count; i++) { if (draw_func[i]) { diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index b0f8a6978..f7a731ac6 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -122,25 +122,6 @@ static cvar_t cl_nolerp_cvar = { .value = { .type = &cexpr_int, .value = &cl_nolerp }, }; -int hud_fps; -static cvar_t hud_fps_cvar = { - .name = "hud_fps", - .description = - "display realtime frames per second", - .default_value = "0", - .flags = CVAR_ARCHIVE, - .value = { .type = &cexpr_int, .value = &hud_fps }, -}; -int hud_time; -static cvar_t hud_time_cvar = { - .name = "hud_time", - .description = - "display the current time", - .default_value = "0", - .flags = CVAR_ARCHIVE, - .value = { .type = &cexpr_int, .value = &hud_time }, -}; - static int r_ambient; static cvar_t r_ambient_cvar = { .name = "r_ambient", @@ -277,9 +258,6 @@ CL_InitCvars (void) Cvar_Register (&cl_writecfg_cvar, 0, 0); Cvar_Register (&cl_shownet_cvar, 0, 0); Cvar_Register (&cl_nolerp_cvar, 0, 0); - Cvar_Register (&hud_fps_cvar, 0, 0); - Cvar_MakeAlias ("show_fps", &hud_fps_cvar); - Cvar_Register (&hud_time_cvar, 0, 0); //FIXME not hooked up (don't do anything), but should not work in //multi-player diff --git a/nq/source/sbar.c b/nq/source/sbar.c index b6c8584b1..40feea7b3 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -89,6 +89,9 @@ static view_t sbar_solo_anchor; static view_t sbar_solo_name; static view_t sbar_tile[2]; +static draw_charbuffer_t *time_buff; +static draw_charbuffer_t *fps_buff; + static draw_charbuffer_t *solo_monsters; static draw_charbuffer_t *solo_secrets; static draw_charbuffer_t *solo_time; @@ -1078,7 +1081,6 @@ draw_overlay (view_t *view) static void draw_time (view_t *view) { -#if 0 struct tm *local = 0; time_t utc = 0; char st[80]; //FIXME: overflow @@ -1098,18 +1100,15 @@ draw_time (view_t *view) #endif if (hud_time == 1) { // Use international format strftime (st, sizeof (st), HOUR24":%M", local); - draw_string (view, 8, 0, st); } else if (hud_time >= 2) { // US AM/PM display strftime (st, sizeof (st), HOUR12":%M "PM, local); - draw_string (view, 8, 0, st); } -#endif + write_charbuff (time_buff, 0, 0, st); } static void -draw_fps (view_t *view) +draw_fps (view_t view) { -#if 0 static char st[80]; double t; static double lastframetime; @@ -1120,19 +1119,10 @@ draw_fps (view_t *view) lastfps = fps_count / (t - lastframetime); fps_count = 0; lastframetime = t; - snprintf (st, sizeof (st), "%5.1f FPS", lastfps); + int prec = lastfps < 1000 ? 1 : 0; + snprintf (st, sizeof (st), "%5.*f FPS", prec, lastfps); } - draw_string (view, 80, 8, st); -#endif -} - -static void -draw_stuff (view_t *view) -{ - if (hud_time > 0) - draw_time (view); - if (hud_fps > 0) - draw_fps (view); + write_charbuff (fps_buff, 0, 0, st); } static void @@ -1414,7 +1404,6 @@ Sbar_Draw (void) if (sb_update_flags & (1 << sbc_info)) { draw_miniteam (0); draw_minifrags (0); - draw_stuff (0); draw_overlay (0); draw_intermission (0); Sbar_DeathmatchOverlay (0); @@ -1509,6 +1498,32 @@ sbar_hud_sbar_f (void *data, const cvar_t *cvar) } } +static void +sbar_hud_fps_f (void *data, const cvar_t *cvar) +{ + if (hud_fps) { + void *f = draw_fps; + sbar_setcomponent (hud_fps_view, hud_update, &f); + sbar_setcomponent (hud_fps_view, hud_charbuff, &fps_buff); + } else { + sbar_remcomponent (hud_fps_view, hud_update); + sbar_remcomponent (hud_fps_view, hud_charbuff); + } +} + +static void +sbar_hud_time_f (void *data, const cvar_t *cvar) +{ + if (hud_time) { + void *f = draw_time; + sbar_setcomponent (hud_time_view, hud_update, &f); + sbar_setcomponent (hud_time_view, hud_charbuff, &time_buff); + } else { + sbar_remcomponent (hud_time_view, hud_update); + sbar_remcomponent (hud_time_view, hud_charbuff); + } +} + static void init_sbar_views (void) { @@ -1892,6 +1907,13 @@ init_views (void) view_insert (hud_main_view, hud_overlay_view, 0); view_insert (hud_main_view, hud_stuff_view, 0); #endif + hud_stuff_view = sbar_view (0, 48, 152, 16, grav_southwest, cl_screen_view); + hud_time_view = sbar_view (8, 0, 64, 8, grav_northwest, hud_stuff_view); + hud_fps_view = sbar_view (80, 0, 72, 8, grav_northwest, hud_stuff_view); + + time_buff = Draw_CreateBuffer (8, 1); + fps_buff = Draw_CreateBuffer (11, 1); + if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) { init_hipnotic_sbar_views (); init_hipnotic_hud_views (); @@ -2097,11 +2119,17 @@ Sbar_Init (void) HUD_Init_Cvars (); Cvar_AddListener (Cvar_FindVar ("hud_sbar"), sbar_hud_sbar_f, 0); Cvar_AddListener (Cvar_FindVar ("hud_swap"), sbar_hud_swap_f, 0); + Cvar_AddListener (Cvar_FindVar ("hud_fps"), sbar_hud_fps_f, 0); + Cvar_AddListener (Cvar_FindVar ("hud_time"), sbar_hud_time_f, 0); load_pics (); init_views (); + View_UpdateHierarchy (sbar_main); + sbar_hud_fps_f (0, 0); + sbar_hud_time_f (0, 0); + Cmd_AddCommand ("+showscores", Sbar_ShowScores, "Display information on everyone playing"); Cmd_AddCommand ("-showscores", Sbar_DontShowScores, diff --git a/qw/include/client.h b/qw/include/client.h index 54292cbab..a2cd77b56 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -267,9 +267,6 @@ extern int cl_model_crcs; extern float rate; -extern int hud_ping; -extern int hud_pl; - extern char *skin; extern float cl_fb_players; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 3ee98653f..f9a71af68 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -445,42 +445,6 @@ static cvar_t host_speeds_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &host_speeds }, }; -int hud_fps; -static cvar_t hud_fps_cvar = { - .name = "hud_fps", - .description = - "display realtime frames per second", - .default_value = "0", - .flags = CVAR_ARCHIVE, - .value = { .type = &cexpr_int, .value = &hud_fps }, -}; -int hud_ping; -static cvar_t hud_ping_cvar = { - .name = "hud_ping", - .description = - "display current ping to server", - .default_value = "0", - .flags = CVAR_ARCHIVE, - .value = { .type = &cexpr_int, .value = &hud_ping }, -}; -int hud_pl; -static cvar_t hud_pl_cvar = { - .name = "hud_pl", - .description = - "display current packet loss to server", - .default_value = "0", - .flags = CVAR_ARCHIVE, - .value = { .type = &cexpr_int, .value = &hud_pl }, -}; -int hud_time; -static cvar_t hud_time_cvar = { - .name = "hud_time", - .description = - "display the current time", - .default_value = "0", - .flags = CVAR_ARCHIVE, - .value = { .type = &cexpr_int, .value = &hud_time }, -}; int fps_count; @@ -1676,11 +1640,6 @@ CL_Init_Cvars (void) Cvar_Register (&host_speeds_cvar, 0, 0); Cvar_Register (&rcon_password_cvar, 0, 0); Cvar_Register (&rcon_address_cvar, 0, 0); - Cvar_Register (&hud_fps_cvar, 0, 0); - Cvar_MakeAlias ("show_fps", &hud_fps_cvar); - Cvar_Register (&hud_ping_cvar, 0, 0); - Cvar_Register (&hud_pl_cvar, 0, 0); - Cvar_Register (&hud_time_cvar, 0, 0); Cvar_Register (&cl_predict_players_cvar, 0, 0); Cvar_Register (&cl_solid_players_cvar, 0, 0); Cvar_Register (&localid_cvar, 0, 0); From ea3ff47cc5416234e982d8833319055768d02f39 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Nov 2022 15:53:52 +0900 Subject: [PATCH 3130/3664] [nq] Make sbar setup more data-driven I doubt the scheme is final (eg, char buffer setup), but it feels better than a pile of function calls. --- nq/source/sbar.c | 105 +++++++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 39 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 40feea7b3..cbfc19c31 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -87,7 +87,55 @@ static view_t sbar_solo_secrets; static view_t sbar_solo_time; static view_t sbar_solo_anchor; static view_t sbar_solo_name; -static view_t sbar_tile[2]; +static view_t sbar_tile[2]; + +typedef struct { + view_t *view; + struct { + int x; + int y; + int w; + int h; + } rect; + grav_t gravity; + view_t *parent; + int count; + int xstep; + int ystep; +} view_def_t; + +static view_def_t view_defs[] = { + {&sbar_main, { 0, 0,320, 48}, grav_south, &cl_screen_view}, + {&sbar_inventory, { 0, 0,320, 24}, grav_northwest, &sbar_main}, + {&sbar_frags, { 0, 0,130, 8}, grav_northeast, &sbar_inventory}, + {&sbar_sigils, { 0, 0, 32, 16}, grav_southeast, &sbar_inventory}, + {&sbar_items, { 32, 0, 96, 16}, grav_southeast, &sbar_inventory}, + {&sbar_armament, { 0, 0,202, 24}, grav_northwest, &sbar_inventory}, + {&sbar_weapons, { 0, 0,192, 16}, grav_southwest, &sbar_armament}, + {&sbar_miniammo, { 0, 0, 32, 8}, grav_northwest, &sbar_armament}, + {&sbar_statusbar, { 0, 0,320, 24}, grav_southwest, &sbar_main}, + {&sbar_armor, { 0, 0, 96, 24}, grav_northwest, &sbar_statusbar}, + {&sbar_face, {112, 0, 24, 24}, grav_northwest, &sbar_statusbar}, + {&sbar_health, {136, 0, 72, 24}, grav_northwest, &sbar_statusbar}, + {&sbar_ammo, {224, 0, 96, 24}, grav_northwest, &sbar_statusbar}, + {&sbar_tile[0], { 0, 0, 0, 48}, grav_southwest, &sbar_main}, + {&sbar_tile[1], { 0, 0, 0, 48}, grav_southeast, &sbar_main}, + {&sbar_solo, { 0, 0,320, 24}, grav_southwest, &sbar_main}, + {&sbar_solo_monsters, { 8, 4,136, 8}, grav_northwest, &sbar_solo}, + {&sbar_solo_secrets, { 8,12,136, 8}, grav_northwest, &sbar_solo}, + {&sbar_solo_time, {184, 4, 96, 8}, grav_northwest, &sbar_solo}, + {&sbar_solo_anchor, {232,12, 0, 8}, grav_northwest, &sbar_solo}, + {&sbar_solo_name, { 0, 0, 0, 8}, grav_center, &sbar_solo_anchor}, + {0, { 0, 0, 8, 16}, grav_northwest, &sbar_sigils, 4, 8, 0}, + {0, { 0, 0, 24, 24}, grav_northwest, &sbar_armor, 4, 24, 0}, + {0, { 0, 0, 24, 24}, grav_northwest, &sbar_ammo, 4, 24, 0}, + {0, { 0, 0, 16, 16}, grav_northwest, &sbar_items, 6, 16, 0}, + {0, { 0, 0, 24, 16}, grav_northwest, &sbar_weapons, 7, 24, 0}, + {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 4, 24, 0}, + {0, {10, 0, 24, 24}, grav_northwest, &sbar_miniammo, 4, 48, 0}, + + {} +}; static draw_charbuffer_t *time_buff; static draw_charbuffer_t *fps_buff; @@ -1527,46 +1575,25 @@ sbar_hud_time_f (void *data, const cvar_t *cvar) static void init_sbar_views (void) { - sbar_main = sbar_view ( 0, 0, 320, 48, grav_south, cl_screen_view); - sbar_inventory = sbar_view ( 0, 0, 320, 24, grav_northwest, sbar_main); - sbar_frags = sbar_view ( 0, 0, 130, 8, grav_northeast, sbar_inventory); - sbar_sigils = sbar_view ( 0, 0, 32, 16, grav_southeast, sbar_inventory); - sbar_items = sbar_view (32, 0, 96, 16, grav_southeast, sbar_inventory); - sbar_armament = sbar_view ( 0, 0, 202, 24, grav_northwest, sbar_inventory); - sbar_weapons = sbar_view ( 0, 0, 192, 16, grav_southwest, sbar_armament); - sbar_miniammo = sbar_view ( 0, 0, 32, 8, grav_northwest, sbar_armament); - sbar_statusbar = sbar_view ( 0, 0, 320, 24, grav_southwest, sbar_main); - sbar_armor = sbar_view ( 0, 0, 96, 24, grav_northwest, sbar_statusbar); - sbar_face = sbar_view (112, 0, 24, 24, grav_northwest, sbar_statusbar); - sbar_health = sbar_view (136, 0, 72, 24, grav_northwest, sbar_statusbar); - sbar_ammo = sbar_view (224, 0, 96, 24, grav_northwest, sbar_statusbar); - sbar_tile[0] = sbar_view ( 0, 0, 0, 48, grav_southwest, sbar_main); - sbar_tile[1] = sbar_view ( 0, 0, 0, 48, grav_southeast, sbar_main); - sbar_solo = sbar_view ( 0, 0, 320, 24, grav_southwest, sbar_main); - sbar_solo_monsters = sbar_view ( 8, 4, 136, 8, grav_northwest, sbar_solo); - sbar_solo_secrets = sbar_view ( 8, 12, 136, 8, grav_northwest, sbar_solo); - sbar_solo_time = sbar_view (184, 4, 96, 8, grav_northwest, sbar_solo); - sbar_solo_anchor = sbar_view (232, 12, 0, 8, grav_northwest, sbar_solo); - sbar_solo_name = sbar_view (0, 0, 0, 8, grav_center, sbar_solo_anchor); - - for (int i = 0; i < 4; i++) { - sbar_view (i * 8, 0, 8, 16, grav_northwest, sbar_sigils); - - sbar_view (i * 24, 0, 24, 24, grav_northwest, sbar_armor); - sbar_view (i * 24, 0, 24, 24, grav_northwest, sbar_ammo); - } - for (int i = 0; i < 6; i++) { - sbar_view (i * 16, 0, 16, 16, grav_northwest, sbar_items); - } - for (int i = 0; i < 7; i++) { - sbar_view (i * 24, 0, 24, 16, grav_northwest, sbar_weapons); + for (int i = 0; view_defs[i].view || view_defs[i].parent; i++) { + view_def_t *def = &view_defs[i]; + view_t parent = def->parent ? *def->parent : nullview; + int x = def->rect.x; + int y = def->rect.y; + int w = def->rect.w; + int h = def->rect.h; + if (def->view) { + *def->view = sbar_view (x, y, w, h, def->gravity, parent); + } else { + for (int j = 0; j < def->count; j++) { + sbar_view (x, y, w, h, def->gravity, parent); + x += def->xstep; + y += def->ystep; + } + } } for (int i = 0; i < 4; i++) { - sbar_view (i * 24, 0, 24, 16, grav_northwest, sbar_health); - } - for (int i = 0; i < 4; i++) { - view_t v = sbar_view (i * 48 + 10, 0, 8, 8, grav_northwest, - sbar_miniammo); + view_t v = View_GetChild (sbar_miniammo, i); draw_charbuffer_t *buffer = Draw_CreateBuffer (3, 1); sbar_setcomponent (v, hud_charbuff, &buffer); } From a07eccd5c733878b16c9830377aa3efe08a0d97a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Nov 2022 16:42:49 +0900 Subject: [PATCH 3131/3664] [glsl] Fix some GLSL conformance issues I'm not sure when things broke on my laptop (I thought I got warp and fisheye working on my laptop), but it turns out things weren't quite right, thus warp (and presumably fisheye) weren't working properly due to GLSL errors that I only just noticed. This fixes water warp (and probably fisheye). --- libs/video/renderer/glsl/glsl_fisheye.c | 2 ++ libs/video/renderer/glsl/glsl_warp.c | 2 ++ libs/video/renderer/glsl/quakeforge.glsl | 8 +++++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_fisheye.c b/libs/video/renderer/glsl/glsl_fisheye.c index edd7c9871..2291ccdc6 100644 --- a/libs/video/renderer/glsl/glsl_fisheye.c +++ b/libs/video/renderer/glsl/glsl_fisheye.c @@ -53,12 +53,14 @@ static const char *fisheye_vert_effects[] = { + "QuakeForge.version.130", "QuakeForge.Vertex.fstri", 0 }; static const char *fisheye_frag_effects[] = { + "QuakeForge.version.130", "QuakeForge.Math.const", "QuakeForge.Fragment.screen.fisheye", 0 diff --git a/libs/video/renderer/glsl/glsl_warp.c b/libs/video/renderer/glsl/glsl_warp.c index d0e16727d..b4579b606 100644 --- a/libs/video/renderer/glsl/glsl_warp.c +++ b/libs/video/renderer/glsl/glsl_warp.c @@ -53,12 +53,14 @@ static const char *warp_vert_effects[] = { + "QuakeForge.version.130", "QuakeForge.Vertex.fstri", 0 }; static const char *warp_frag_effects[] = { + "QuakeForge.version.130", "QuakeForge.Math.const", "QuakeForge.Fragment.screen.warp", 0 diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index b99f142e2..05001cb83 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -552,8 +552,9 @@ main (void) gl_FragColor = fogBlend (col); } --- Vertex.fstri +-- version.130 #version 130 +-- Vertex.fstri out vec2 uv; @@ -582,8 +583,9 @@ const vec2 B = vec2 (1, 1); void main () { - uv = uv * (1.0 - 2.0*A) + A * (B + sin ((time * S + F * uv.yx) * 2.0*PI)); - vec4 c = texture2D (screenTex, uv); + vec2 st; + st = uv * (1.0 - 2.0*A) + A * (B + sin ((time * S + F * uv.yx) * 2.0*PI)); + vec4 c = texture2D (screenTex, st); gl_FragColor = c;//vec4(uv, c.x, 1); } From bdbb8f1e0b54f8ecd58908ac0628f5c43f5cd74c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 3 Nov 2022 17:49:05 +0900 Subject: [PATCH 3132/3664] [nq] Get intermission view working again This is currently just the basic intermission view (not the finale view or the deathmatch intermission view). --- include/client/view.h | 18 +++---- include/sbar.h | 2 +- libs/client/cl_screen.c | 10 +--- libs/client/hud.c | 6 +-- nq/source/cl_main.c | 3 +- nq/source/cl_parse.c | 6 +-- nq/source/sbar.c | 117 ++++++++++++++++++++++++++++++---------- qw/source/sbar.c | 4 +- 8 files changed, 110 insertions(+), 56 deletions(-) diff --git a/include/client/view.h b/include/client/view.h index c2ae534d9..2bb2c8196 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -65,15 +65,15 @@ typedef struct viewstate_s { float height; int weaponframe; int onground; // -1 when in air - int active:1; - int loading:1; - int watervis:1; - int demoplayback:1; - int drift_enabled:1; - int voffs_enabled:1; - int bob_enabled:1; - int intermission:1; - int decay_punchangle:1; + unsigned active:1; + unsigned loading:1; + unsigned watervis:1; + unsigned demoplayback:1; + unsigned drift_enabled:1; + unsigned voffs_enabled:1; + unsigned bob_enabled:1; + unsigned intermission:1; + unsigned decay_punchangle:1; int force_cshifts; // bitfield of server enforced cshifts uint32_t flags; diff --git a/include/sbar.h b/include/sbar.h index 6c1f74317..95d38ac72 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -56,7 +56,7 @@ void Sbar_Changed (sbar_changed change); void Sbar_Draw (void); // called every frame by screen -void Sbar_IntermissionOverlay (void); +void Sbar_Intermission (int mode); // called each frame after the level has been completed void Sbar_FinaleOverlay (void); diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index 035dec6db..f2d21c454 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -154,23 +154,15 @@ static SCR_Func scr_funcs_normal[] = { }; static SCR_Func scr_funcs_intermission[] = { - Sbar_IntermissionOverlay, + HUD_Draw_Views, Con_DrawConsole, scr_draw_views, 0 }; -static SCR_Func scr_funcs_finale[] = { - Sbar_FinaleOverlay, - Con_DrawConsole, - scr_draw_views, - 0, -}; - static SCR_Func *scr_funcs[] = { scr_funcs_normal, scr_funcs_intermission, - scr_funcs_finale, }; static void diff --git a/libs/client/hud.c b/libs/client/hud.c index 9c375e50d..5473a5b34 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -209,9 +209,9 @@ hud_swap_f (void *data, const cvar_t *cvar) static void hud_scoreboard_gravity_f (void *data, const cvar_t *cvar) { -#if 0//XXX - view_setgravity (hud_overlay_view, hud_scoreboard_gravity); -#endif + if (View_Valid (hud_overlay_view)) { + View_SetGravity (hud_overlay_view, hud_scoreboard_gravity); + } } void diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index f7a731ac6..b6403481a 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -231,6 +231,7 @@ CL_ClearMemory (void) // wipe the entire cl structure __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); + Sbar_Intermission (cl.intermission = 0); cl.viewstate.camera_transform = cam; CL_ClearTEnts (); @@ -338,7 +339,7 @@ CL_Disconnect (void) } cl_world.scene->worldmodel = NULL; - cl.intermission = 0; + Sbar_Intermission (cl.intermission = 0); cl.viewstate.intermission = 0; } diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 516b971d2..c866b0b31 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -986,13 +986,13 @@ CL_ParseServerMessage (void) break; case svc_intermission: - cl.intermission = 1; + Sbar_Intermission (cl.intermission = 1); SCR_SetFullscreen (1); cl.completed_time = cl.time; break; case svc_finale: - cl.intermission = 2; + Sbar_Intermission (cl.intermission = 2); SCR_SetFullscreen (1); cl.completed_time = cl.time; str = MSG_ReadString (net_message); @@ -1018,7 +1018,7 @@ CL_ParseServerMessage (void) break; case svc_cutscene: - cl.intermission = 3; + Sbar_Intermission (cl.intermission = 3); SCR_SetFullscreen (1); cl.completed_time = cl.time; str = MSG_ReadString (net_message); diff --git a/nq/source/sbar.c b/nq/source/sbar.c index cbfc19c31..14ff24e62 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -89,6 +89,11 @@ static view_t sbar_solo_anchor; static view_t sbar_solo_name; static view_t sbar_tile[2]; +static view_t intermission_view; +static view_t intermission_time; +static view_t intermission_secr; +static view_t intermission_kill; + typedef struct { view_t *view; struct { @@ -105,6 +110,23 @@ typedef struct { } view_def_t; static view_def_t view_defs[] = { + {&hud_overlay_view, { 0, 0,320,200}, grav_center, &cl_screen_view}, + {&intermission_view, { 0, 0,320,200}, grav_northwest, &hud_overlay_view}, + {0, {64, 24, 24, 24}, grav_northwest, &intermission_view, 1, 0, 0}, + {0, {0, 56, 24, 24}, grav_northwest, &intermission_view, 1, 0, 0}, + {&intermission_time, {160,64,134,24}, grav_northwest, &intermission_view}, + {0, {0, 0, 24, 24}, grav_northwest, &intermission_time, 3, 24, 0}, + {0, {74, 0, 16, 24}, grav_northwest, &intermission_time, 1, 0, 0}, + {0, {86, 0, 24, 24}, grav_northwest, &intermission_time, 2, 24, 0}, + {&intermission_secr, {160,104,152,24}, grav_northwest, &intermission_view}, + {0, {0, 0, 24, 24}, grav_northwest, &intermission_secr, 3, 24, 0}, + {0, {72, 0, 16, 24}, grav_northwest, &intermission_secr, 1, 0, 0}, + {0, {80, 0, 24, 24}, grav_northwest, &intermission_secr, 3, 24, 0}, + {&intermission_kill, {160,144,152,24}, grav_northwest, &intermission_view}, + {0, {0, 0, 24, 24}, grav_northwest, &intermission_kill, 3, 24, 0}, + {0, {72, 0, 16, 24}, grav_northwest, &intermission_kill, 1, 0, 0}, + {0, {80, 0, 24, 24}, grav_northwest, &intermission_kill, 3, 24, 0}, + {&sbar_main, { 0, 0,320, 48}, grav_south, &cl_screen_view}, {&sbar_inventory, { 0, 0,320, 24}, grav_northwest, &sbar_main}, {&sbar_frags, { 0, 0,130, 8}, grav_northeast, &sbar_inventory}, @@ -1174,50 +1196,89 @@ draw_fps (view_t view) } static void -draw_intermission (view_t *view) +draw_intermission (view_t view) { -#if 0 - int dig; - int num; + const char *n; - r_data->scr_copyeverything = 1; - r_data->scr_fullupdate = 0; + n = "gfx/complete.lmp"; + sbar_setcomponent (View_GetChild (view, 0), hud_cachepic, &n); + n = "gfx/inter.lmp"; + sbar_setcomponent (View_GetChild (view, 1), hud_cachepic, &n); - draw_cachepic (view, 64, 24, "gfx/complete.lmp", 0); + view_t time_views[] = { + View_GetChild (intermission_time, 0), + View_GetChild (intermission_time, 1), + View_GetChild (intermission_time, 2), + View_GetChild (intermission_time, 3), + View_GetChild (intermission_time, 4), + View_GetChild (intermission_time, 5), + }; + int dig = cl.completed_time / 60; + int num = cl.completed_time - dig * 60; + draw_num (time_views + 0, dig, 3, 0); + sbar_setcomponent (time_views[3], hud_pic, &sb_colon); + draw_num (time_views + 4, num, 2, 0); - draw_cachepic (view, 0, 56, "gfx/inter.lmp", 0); + view_t secr_views[] = { + View_GetChild (intermission_secr, 0), + View_GetChild (intermission_secr, 1), + View_GetChild (intermission_secr, 2), + View_GetChild (intermission_secr, 3), + View_GetChild (intermission_secr, 4), + View_GetChild (intermission_secr, 5), + View_GetChild (intermission_secr, 6), + }; + draw_num (secr_views + 0, cl.stats[STAT_SECRETS], 3, 0); + sbar_setcomponent (secr_views[3], hud_pic, &sb_slash); + draw_num (secr_views + 4, cl.stats[STAT_TOTALSECRETS], 3, 0); - // time - dig = cl.completed_time / 60; - draw_num (view, 160, 64, dig, 3, 0); - num = cl.completed_time - dig * 60; - draw_pic (view, 234, 64, sb_colon); - draw_pic (view, 246, 64, sb_nums[0][num / 10]); - draw_pic (view, 266, 64, sb_nums[0][num % 10]); - - draw_num (view, 160, 104, cl.stats[STAT_SECRETS], 3, 0); - draw_pic (view, 232, 104, sb_slash); - draw_num (view, 240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0); - - draw_num (view, 160, 144, cl.stats[STAT_MONSTERS], 3, 0); - draw_pic (view, 232, 144, sb_slash); - draw_num (view, 240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0); -#endif + view_t kill_views[] = { + View_GetChild (intermission_kill, 0), + View_GetChild (intermission_kill, 1), + View_GetChild (intermission_kill, 2), + View_GetChild (intermission_kill, 3), + View_GetChild (intermission_kill, 4), + View_GetChild (intermission_kill, 5), + View_GetChild (intermission_kill, 6), + }; + draw_num (kill_views + 0, cl.stats[STAT_MONSTERS], 3, 0); + sbar_setcomponent (kill_views[3], hud_pic, &sb_slash); + draw_num (kill_views + 4, cl.stats[STAT_TOTALMONSTERS], 3, 0); } +static void +clear_views (view_t view) +{ + sbar_remcomponent (view, hud_cachepic); + sbar_remcomponent (view, hud_pic); + + for (uint32_t i = 0; i < View_ChildCount (view); i++) { + clear_views (View_GetChild (view, i)); + } +} + +#if 0 void Sbar_IntermissionOverlay (void) { -#if 0 r_data->scr_copyeverything = 1; r_data->scr_fullupdate = 0; - if (cl.gametype == GAME_DEATHMATCH) { Sbar_DeathmatchOverlay (hud_overlay_view); return; } - draw_intermission (hud_overlay_view); + draw_intermission (intermission_view); +} #endif + +void +Sbar_Intermission (int mode) +{ + void *f = clear_views; + if (mode == 1) { + f = draw_intermission; + } + sbar_setcomponent (intermission_view, hud_updateonce, &f); } /* CENTER PRINTING */ @@ -1453,7 +1514,6 @@ Sbar_Draw (void) draw_miniteam (0); draw_minifrags (0); draw_overlay (0); - draw_intermission (0); Sbar_DeathmatchOverlay (0); sbar_update_vis (); } @@ -1595,6 +1655,7 @@ init_sbar_views (void) for (int i = 0; i < 4; i++) { view_t v = View_GetChild (sbar_miniammo, i); draw_charbuffer_t *buffer = Draw_CreateBuffer (3, 1); + Draw_ClearBuffer (buffer); sbar_setcomponent (v, hud_charbuff, &buffer); } diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 17cc61099..ba7027742 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -1620,10 +1620,10 @@ draw_stuff (view_t *view) draw_net (view); } +#if 0 void Sbar_IntermissionOverlay (void) { -#if 0 r_data->scr_copyeverything = 1; r_data->scr_fullupdate = 0; @@ -1631,8 +1631,8 @@ Sbar_IntermissionOverlay (void) Sbar_TeamOverlay (hud_overlay_view); else Sbar_DeathmatchOverlay (hud_overlay_view, 0); -#endif } +#endif /* CENTER PRINTING */ static dstring_t center_string = {&dstring_default_mem}; From 6b99697e821d85c0bd6046111b547ca60a3eaaff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Nov 2022 00:29:13 +0900 Subject: [PATCH 3133/3664] [ui] Get flowed views working with ECS I'm not particularly happy with the way onresize is handled, but at this stage a better way of dealing with resizing views and getting the child views to flow correctly hasn't come to mind. However, the system should at least be usable. --- include/QF/ui/view.h | 20 ++ libs/ui/test/Makemodule.am | 8 +- libs/ui/test/test-flow-size.c | 94 ++++--- libs/ui/test/test-flow.c | 93 ++++--- libs/ui/view.c | 464 ++++++++++++---------------------- 5 files changed, 307 insertions(+), 372 deletions(-) diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index f5ded1ccf..9370e3659 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -127,6 +127,15 @@ view_t View_New (ecs_registry_t *reg, view_t parent); void View_SetParent (view_t view, view_t parent); void View_UpdateHierarchy (view_t view); +void view_flow_right_down (view_t view, view_pos_t len); +void view_flow_right_up (view_t view, view_pos_t len); +void view_flow_left_down (view_t view, view_pos_t len); +void view_flow_left_up (view_t view, view_pos_t len); +void view_flow_down_right (view_t view, view_pos_t len); +void view_flow_up_right (view_t view, view_pos_t len); +void view_flow_down_left (view_t view, view_pos_t len); +void view_flow_up_left (view_t view, view_pos_t len); + VIEWINLINE hierref_t *View_GetRef (view_t view); VIEWINLINE int View_Valid (view_t view); @@ -140,6 +149,7 @@ VIEWINLINE view_pos_t View_GetAbs (view_t view); VIEWINLINE view_pos_t View_GetRel (view_t view); VIEWINLINE void View_SetLen (view_t view, int x, int y); VIEWINLINE view_pos_t View_GetLen (view_t view); +VIEWINLINE viewcont_t* View_Control (view_t view); VIEWINLINE void View_SetGravity (view_t view, grav_t grav); VIEWINLINE grav_t View_GetGravity (view_t view); VIEWINLINE void View_SetVisible (view_t view, int visible); @@ -279,6 +289,16 @@ View_GetLen (view_t view) return len[ref->index]; } +VIEWINLINE +viewcont_t * +View_Control (view_t view) +{ + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + viewcont_t *cont = h->components[view_control]; + return &cont[ref->index]; +} + VIEWINLINE void View_SetGravity (view_t view, grav_t grav) diff --git a/libs/ui/test/Makemodule.am b/libs/ui/test/Makemodule.am index 70972e981..e5827dcea 100644 --- a/libs/ui/test/Makemodule.am +++ b/libs/ui/test/Makemodule.am @@ -1,13 +1,11 @@ libs_ui_tests = \ + libs/ui/test/test-flow \ + libs/ui/test/test-flow-size \ libs/ui/test/test-passage \ libs/ui/test/test-txtbuffer \ libs/ui/test/test-vrect -libs_ui_xfail_tests = \ - libs/ui/test/test-flow \ - libs/ui/test/test-flow-size - -TESTS += $(libs_ui_tests) $(libs_ui_xfail_tests) +TESTS += $(libs_ui_tests) XFAIL_TESTS += $(libs_ui_xfail_tests) diff --git a/libs/ui/test/test-flow-size.c b/libs/ui/test/test-flow-size.c index 88e304653..31e322fb7 100644 --- a/libs/ui/test/test-flow-size.c +++ b/libs/ui/test/test-flow-size.c @@ -4,7 +4,21 @@ #include #include "QF/ui/view.h" -#if 0 + +static ecs_registry_t *test_reg; + +enum { + test_href, +}; + +static const component_t test_components[] = { + [test_href] = { + .size = sizeof (hierref_t), + .create = 0,//create_href, + .name = "href", + }, +}; + typedef struct { struct { int xlen, ylen; @@ -194,50 +208,66 @@ static testdata_t up_left_views[] = { #define up_left_count array_size(up_left_views) static void -print_view (view_t *view) +print_view (view_t view) { + view_t parent = View_GetParent (view); + view_pos_t pos = View_GetPos (view); + view_pos_t len = View_GetLen (view); + view_pos_t rel = View_GetRel (view); + view_pos_t abs = View_GetAbs (view); printf ("%s[%3d %3d %3d %3d %3d %3d %3d %3d]\n", - view->parent ? " " : "****", - view->xpos, view->ypos, view->xlen, view->ylen, - view->xrel, view->yrel, view->xabs, view->yabs); - view_draw (view); + View_Valid (parent) ? " " : "****", + pos.x, pos.y, len.x, len.y, rel.x, rel.y, abs.x, abs.y); } static int -test_flow (testdata_t *child_views, int count, void (*flow) (view_t *)) +test_flow (testdata_t *child_views, int count, void (flow) (view_t, view_pos_t)) { - view_t *flow_view = view_new (0, 0, 256, 256, grav_northwest); - flow_view->setgeometry = flow; - flow_view->flow_size = 1; - flow_view->draw = print_view; + view_t flow_view = View_New (test_reg, nullview); + View_SetPos (flow_view, 0, 0); + View_SetLen (flow_view, 256, 256); + View_SetGravity (flow_view, grav_northwest); + View_SetOnResize (flow_view, flow); + View_Control (flow_view)->flow_size = 1; for (int i = 0; i < count; i++) { testdata_t *td = &child_views[i]; - view_t *child = view_new (0, 0, td->xlen, td->ylen, grav_flow); - child->bol_suppress = td->bol_suppress; - child->draw = print_view; - view_add (flow_view, child); + view_t child = View_New (test_reg, flow_view); + View_SetPos (child, 0, 0); + View_SetLen (child, td->xlen, td->ylen); + View_SetGravity (child, grav_flow); + View_Control (child)->bol_suppress = td->bol_suppress; } - view_move (flow_view, 8, 16); - int ret = 0; + View_SetPos (flow_view, 8, 16); + View_UpdateHierarchy (flow_view); - for (int i = 0; i < flow_view->num_children; i++) { + int ret = 0; + __auto_type ref = View_GetRef (flow_view); + hierarchy_t *h = ref->hierarchy; + uint32_t *childIndex = h->childIndex; + uint32_t *childCount = h->childCount; + uint32_t *ent = h->ent; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *rel = h->components[view_rel]; + view_pos_t *abs = h->components[view_abs]; + for (uint32_t i = 0; i < childCount[ref->index]; i++) { testdata_t *td = &child_views[i]; - view_t *child = flow_view->children[i]; - if (child->xpos != td->expect.xpos - || child->ypos != td->expect.ypos - || child->xrel != td->expect.xrel - || child->yrel != td->expect.yrel - || child->xabs != td->expect.xabs - || child->yabs != td->expect.yabs) { + uint32_t child = childIndex[ref->index] + i; + if (pos[child].x != td->expect.xpos + || pos[child].y != td->expect.ypos + || rel[child].x != td->expect.xrel + || rel[child].y != td->expect.yrel + || abs[child].x != td->expect.xabs + || abs[child].y != td->expect.yabs) { ret = 1; printf ("child %d misflowed:\n" " [%3d %3d %3d %3d %3d %3d]\n", i, td->expect.xpos, td->expect.ypos, td->expect.xrel, td->expect.yrel, td->expect.xabs, td->expect.yabs); - print_view (child); + print_view ((view_t) { .reg = test_reg, .id = ent[child], + .comp = flow_view.comp}); } } return ret; @@ -248,6 +278,10 @@ main (void) { int ret = 0; + test_reg = ECS_NewRegistry (); + ECS_RegisterComponents (test_reg, test_components, 1); + test_reg->href_comp = test_href; + if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { printf ("right-down failed\n"); ret = 1; @@ -283,11 +317,3 @@ main (void) } return ret; } -#endif - -int -main (void) -{ - printf ("FIXME: redo for ECS\n"); - return 1; -} diff --git a/libs/ui/test/test-flow.c b/libs/ui/test/test-flow.c index 520331857..831a35677 100644 --- a/libs/ui/test/test-flow.c +++ b/libs/ui/test/test-flow.c @@ -4,7 +4,21 @@ #include #include "QF/ui/view.h" -#if 0 + +static ecs_registry_t *test_reg; + +enum { + test_href, +}; + +static const component_t test_components[] = { + [test_href] = { + .size = sizeof (hierref_t), + .create = 0,//create_href, + .name = "href", + }, +}; + typedef struct { struct { int xlen, ylen; @@ -194,49 +208,66 @@ static testdata_t up_left_views[] = { #define up_left_count array_size(up_left_views) static void -print_view (view_t *view) +print_view (view_t view) { + view_t parent = View_GetParent (view); + view_pos_t pos = View_GetPos (view); + view_pos_t len = View_GetLen (view); + view_pos_t rel = View_GetRel (view); + view_pos_t abs = View_GetAbs (view); printf ("%s[%3d %3d %3d %3d %3d %3d %3d %3d]\n", - view->parent ? " " : "****", - view->xpos, view->ypos, view->xlen, view->ylen, - view->xrel, view->yrel, view->xabs, view->yabs); - view_draw (view); + View_Valid (parent) ? " " : "****", + pos.x, pos.y, len.x, len.y, rel.x, rel.y, abs.x, abs.y); } static int -test_flow (testdata_t *child_views, int count, void (*flow) (view_t *)) +test_flow (testdata_t *child_views, int count, + void (*flow) (view_t, view_pos_t)) { - view_t *flow_view = view_new (0, 0, 256, 256, grav_northwest); - flow_view->setgeometry = flow; - flow_view->draw = print_view; + view_t flow_view = View_New (test_reg, nullview); + View_SetPos (flow_view, 0, 0); + View_SetLen (flow_view, 256, 256); + View_SetGravity (flow_view, grav_northwest); + View_SetOnResize (flow_view, flow); for (int i = 0; i < count; i++) { testdata_t *td = &child_views[i]; - view_t *child = view_new (0, 0, td->xlen, td->ylen, grav_flow); - child->bol_suppress = td->bol_suppress; - child->draw = print_view; - view_add (flow_view, child); + view_t child = View_New (test_reg, flow_view); + View_SetPos (child, 0, 0); + View_SetLen (child, td->xlen, td->ylen); + View_SetGravity (child, grav_flow); + View_Control (child)->bol_suppress = td->bol_suppress; } - view_move (flow_view, 8, 16); - int ret = 0; + View_SetPos (flow_view, 8, 16); + View_UpdateHierarchy (flow_view); - for (int i = 0; i < flow_view->num_children; i++) { + int ret = 0; + __auto_type ref = View_GetRef (flow_view); + hierarchy_t *h = ref->hierarchy; + uint32_t *childIndex = h->childIndex; + uint32_t *childCount = h->childCount; + uint32_t *ent = h->ent; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *rel = h->components[view_rel]; + view_pos_t *abs = h->components[view_abs]; + for (uint32_t i = 0; i < childCount[ref->index]; i++) { testdata_t *td = &child_views[i]; - view_t *child = flow_view->children[i]; - if (child->xpos != td->expect.xpos - || child->ypos != td->expect.ypos - || child->xrel != td->expect.xrel - || child->yrel != td->expect.yrel - || child->xabs != td->expect.xabs - || child->yabs != td->expect.yabs) { + uint32_t child = childIndex[ref->index] + i; + if (pos[child].x != td->expect.xpos + || pos[child].y != td->expect.ypos + || rel[child].x != td->expect.xrel + || rel[child].y != td->expect.yrel + || abs[child].x != td->expect.xabs + || abs[child].y != td->expect.yabs) { ret = 1; printf ("child %d misflowed:\n" " [%3d %3d %3d %3d %3d %3d]\n", i, td->expect.xpos, td->expect.ypos, td->expect.xrel, td->expect.yrel, td->expect.xabs, td->expect.yabs); - print_view (child); + print_view ((view_t) { .reg = test_reg, .id = ent[child], + .comp = flow_view.comp}); } } return ret; @@ -247,6 +278,10 @@ main (void) { int ret = 0; + test_reg = ECS_NewRegistry (); + ECS_RegisterComponents (test_reg, test_components, 1); + test_reg->href_comp = test_href; + if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { printf ("right-down failed\n"); ret = 1; @@ -282,11 +317,3 @@ main (void) } return ret; } -#endif - -int -main (void) -{ - printf ("FIXME: redo for ECS\n"); - return 1; -} diff --git a/libs/ui/view.c b/libs/ui/view.c index ddd572737..712c237e9 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -173,10 +173,17 @@ View_UpdateHierarchy (view_t view) uint32_t *id = h->ent; if (abs[0].x != pos[0].x || abs[0].y != pos[0].y) { - modified[0] = 1; + modified[0] |= 1; abs[0] = pos[0]; rel[0] = pos[0]; } + if (oldlen[0].x != len[0].x || oldlen[0].y != len[0].y) { + modified[0] |= 2; + if (onresize[0]) { + view_t v = { .reg = view.reg, .id = id[0], .comp = view.comp }; + onresize[0] (v, len[0]); + } + } for (uint32_t i = 1; i < h->num_objects; i++) { uint32_t par = parent[i]; if (!(modified[i] & 2) && (modified[par] & 2) @@ -191,6 +198,11 @@ View_UpdateHierarchy (view_t view) if (cont[i].resize_y) { len[i].y += dy; } + if (onresize[i]) { + view_t v = { .reg = view.reg, .id = id[i], + .comp = view.comp }; + onresize[i] (v, len[i]); + } } if (modified[i] || modified[par]) { modified[i] |= 1; // propogate motion modifications @@ -239,16 +251,12 @@ View_UpdateHierarchy (view_t view) } } for (uint32_t i = 0; i < h->num_objects; i++) { - if ((modified[i] & 2) && onresize[i]) { - view_t v = { .reg = view.reg, .id = id[i], .comp = view.comp }; - onresize[i] (v, len[i]); - } if (modified[i] & 2) { oldlen[i] = len[i]; } if ((modified[i] & 1) && onmove[i]) { view_t v = { .reg = view.reg, .id = id[i], .comp = view.comp }; - onresize[i] (v, abs[i]); + onmove[i] (v, abs[i]); } modified[i] = 0; } @@ -289,213 +297,6 @@ View_SetParent (view_t view, view_t parent) modified[ref->index] = 1; View_UpdateHierarchy (view); } -#if 0 -static void -setgeometry (view_t *view) -{ - int i; - view_t *par = view->parent; - - if (!par) { - view->xabs = view->xrel = view->xpos; - view->yabs = view->yrel = view->ypos; - if (view->setgeometry) - view->setgeometry (view); - for (i = 0; i < view->num_children; i++) - setgeometry (view->children[i]); - return; - } - - switch (view->gravity) { - case grav_center: - view->xrel = view->xpos + (par->xlen - view->xlen) / 2; - view->yrel = view->ypos + (par->ylen - view->ylen) / 2; - break; - case grav_north: - view->xrel = view->xpos + (par->xlen - view->xlen) / 2; - view->yrel = view->ypos; - break; - case grav_northeast: - view->xrel = par->xlen - view->xpos - view->xlen; - view->yrel = view->ypos; - break; - case grav_east: - view->xrel = par->xlen - view->xpos - view->xlen; - view->yrel = view->ypos + (par->ylen - view->ylen) / 2; - break; - case grav_southeast: - view->xrel = par->xlen - view->xpos - view->xlen; - view->yrel = par->ylen - view->ypos - view->ylen; - break; - case grav_south: - view->xrel = view->xpos + (par->xlen - view->xlen) / 2; - view->yrel = par->ylen - view->ypos - view->ylen; - break; - case grav_southwest: - view->xrel = view->xpos; - view->yrel = par->ylen - view->ypos - view->ylen; - break; - case grav_west: - view->xrel = view->xpos; - view->yrel = view->ypos + (par->ylen - view->ylen) / 2; - break; - case grav_northwest: - view->xrel = view->xpos; - view->yrel = view->ypos; - break; - case grav_flow: - break; - } - view->xabs = par->xabs + view->xrel; - view->yabs = par->yabs + view->yrel; - if (view->setgeometry) - view->setgeometry (view); - for (i = 0; i < view->num_children; i++) - setgeometry (view->children[i]); -} - -VISIBLE view_t * -view_new_data (int xp, int yp, int xl, int yl, grav_t grav, void *data) -{ - view_t *view = calloc (1, sizeof (view_t)); - view->xpos = xp; - view->ypos = yp; - view->xlen = xl; - view->ylen = yl; - view->gravity = grav; - view->visible = 1; - view->draw = view_draw; - view->data = data; - setgeometry (view); - return view; -} - -VISIBLE view_t * -view_new (int xp, int yp, int xl, int yl, grav_t grav) -{ - return view_new_data (xp, yp, xl, yl, grav, 0); -} - -VISIBLE void -view_insert (view_t *par, view_t *view, int pos) -{ - view->parent = par; - if (pos < 0) - pos = par->num_children + 1 + pos; - if (pos < 0) - pos = 0; - if (pos > par->num_children) - pos = par->num_children; - if (par->num_children == par->max_children) { - par->max_children += 8; - par->children = realloc (par->children, - par->max_children * sizeof (view_t *)); - memset (par->children + par->num_children, 0, - (par->max_children - par->num_children) * sizeof (view_t *)); - } - memmove (par->children + pos + 1, par->children + pos, - (par->num_children - pos) * sizeof (view_t *)); - par->num_children++; - par->children[pos] = view; - setgeometry (view); -} - -VISIBLE void -view_add (view_t *par, view_t *view) -{ - view_insert (par, view, -1); -} - -VISIBLE void -view_remove (view_t *par, view_t *view) -{ - int i; - - for (i = 0; i < par->num_children; i++) { - if (par->children[i] == view) { - memmove (par->children + i, par->children + i + 1, - (par->num_children - i - 1) * sizeof (view_t *)); - par->children [--par->num_children] = 0; - break; - } - } -} - -VISIBLE void -view_delete (view_t *view) -{ - if (view->parent) - view_remove (view->parent, view); - while (view->num_children) - view_delete (view->children[0]); - free (view->children); - free (view); -} - -VISIBLE void -view_draw (view_t *view) -{ - int i; - - for (i = 0; i < view->num_children; i++) { - view_t *v = view->children[i]; - if (v->visible && v->draw) - v->draw (v); - } -} - -static void -_resize (view_t *view, int xl, int yl) -{ - int i, xd, yd; - - xd = xl - view->xlen; - yd = yl - view->ylen; - view->xlen = xl; - view->ylen = yl; - for (i = 0; i < view->num_children; i++) { - view_t *v = view->children[i]; - - if (v->resize_x && v->resize_y) { - _resize (v, v->xlen + xd, v->ylen + yd); - } else if (v->resize_x) { - _resize (v, v->xlen + xd, v->ylen); - } else if (v->resize_y) { - _resize (v, v->xlen, v->ylen + yd); - } - } -} - -VISIBLE void -view_resize (view_t *view, int xl, int yl) -{ - _resize (view, xl, yl); - setgeometry (view); -} - -VISIBLE void -view_move (view_t *view, int xp, int yp) -{ - view->xpos = xp; - view->ypos = yp; - setgeometry (view); -} - -VISIBLE void -view_setgeometry (view_t *view, int xp, int yp, int xl, int yl) -{ - view->xpos = xp; - view->ypos = yp; - _resize (view, xl, yl); - setgeometry (view); -} - -VISIBLE void -view_setgravity (view_t *view, grav_t grav) -{ - view->gravity = grav; - setgeometry (view); -} typedef struct flowline_s { struct flowline_s *next; @@ -514,224 +315,287 @@ typedef struct flowline_s { } while (0) static void -flow_right (view_t *view, void (*set_rows) (view_t *, flowline_t *)) +flow_right (view_t view, void (*set_rows) (view_t, flowline_t *)) { - flowline_t flowline = {}; + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *len = h->components[view_len]; + viewcont_t *cont = h->components[view_control]; + uint32_t vind = ref->index; + + flowline_t flowline = { .first_child = h->childIndex[ref->index] }; flowline_t *line = &flowline; - for (int i = 0; i < view->num_children; i++) { - view_t *child = view->children[i]; - if (line->cursor && line->cursor + child->xlen > view->xlen) { - NEXT_LINE(line, i); + for (uint32_t i = 0; i < h->childCount[vind]; i++) { + uint32_t child = h->childIndex[vind] + i; + if (line->cursor && line->cursor + len[child].x > len[vind].x) { + NEXT_LINE(line, child); } - child->xpos = line->cursor; - if (child->xpos || !child->bol_suppress) { - line->cursor += child->xlen; + pos[child].x = line->cursor; + if (pos[child].x || !cont[child].bol_suppress) { + line->cursor += len[child].x; } - line->height = max (child->ylen, line->height); + line->height = max (len[child].y, line->height); line->child_count++; } set_rows (view, &flowline); } static void -flow_left (view_t *view, void (*set_rows) (view_t *, flowline_t *)) +flow_left (view_t view, void (*set_rows) (view_t, flowline_t *)) { - flowline_t flowline = {}; + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *len = h->components[view_len]; + viewcont_t *cont = h->components[view_control]; + uint32_t vind = ref->index; + + flowline_t flowline = { .first_child = h->childIndex[ref->index] }; flowline_t *line = &flowline; - line->cursor = view->xlen; - for (int i = 0; i < view->num_children; i++) { - view_t *child = view->children[i]; - if (line->cursor < view->xlen && line->cursor - child->xlen < 0) { - NEXT_LINE(line, i); - line->cursor = view->xlen; + line->cursor = len[vind].x; + for (uint32_t i = 0; i < h->childCount[vind]; i++) { + uint32_t child = h->childIndex[ref->index] + i; + if (line->cursor < len[vind].x && line->cursor - len[child].x < 0) { + NEXT_LINE(line, child); + line->cursor = len[vind].x; } - if (child->xpos < view->xlen || !child->bol_suppress) { - line->cursor -= child->xlen; + if (pos[child].x < len[vind].x || !cont[child].bol_suppress) { + line->cursor -= len[child].x; } - child->xpos = line->cursor; - line->height = max (child->ylen, line->height); + pos[child].x = line->cursor; + line->height = max (len[child].y, line->height); line->child_count++; } set_rows (view, &flowline); } static void -flow_down (view_t *view, void (*set_rows) (view_t *, flowline_t *)) +flow_down (view_t view, void (*set_rows) (view_t, flowline_t *)) { - flowline_t flowline = {}; + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *len = h->components[view_len]; + viewcont_t *cont = h->components[view_control]; + uint32_t vind = ref->index; + + flowline_t flowline = { .first_child = h->childIndex[ref->index] }; flowline_t *line = &flowline; - for (int i = 0; i < view->num_children; i++) { - view_t *child = view->children[i]; - if (line->cursor && line->cursor + child->ylen > view->ylen) { - NEXT_LINE(line, i); + for (uint32_t i = 0; i < h->childCount[vind]; i++) { + uint32_t child = h->childIndex[vind] + i; + if (line->cursor && line->cursor + len[child].y > len[vind].y) { + NEXT_LINE(line, child); } - child->ypos = line->cursor; - if (child->ypos || !child->bol_suppress) { - line->cursor += child->ylen; + pos[child].y = line->cursor; + if (pos[child].y || !cont[child].bol_suppress) { + line->cursor += len[child].y; } - line->height = max (child->xlen, line->height); + line->height = max (len[child].x, line->height); line->child_count++; } set_rows (view, &flowline); } static void -flow_up (view_t *view, void (*set_rows) (view_t *, flowline_t *)) +flow_up (view_t view, void (*set_rows) (view_t, flowline_t *)) { - flowline_t flowline = {}; + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *len = h->components[view_len]; + viewcont_t *cont = h->components[view_control]; + uint32_t vind = ref->index; + + flowline_t flowline = { .first_child = h->childIndex[ref->index] }; flowline_t *line = &flowline; - line->cursor = view->ylen; - for (int i = 0; i < view->num_children; i++) { - view_t *child = view->children[i]; - if (line->cursor < view->ylen && line->cursor - child->ylen < 0) { - NEXT_LINE(line, i); - line->cursor = view->ylen; + line->cursor = len[vind].y; + for (uint32_t i = 0; i < h->childCount[vind]; i++) { + uint32_t child = h->childIndex[ref->index] + i; + if (line->cursor < len[vind].y && line->cursor - len[child].y < 0) { + NEXT_LINE(line, child); + line->cursor = len[vind].y; } - if (child->ypos < view->ylen || !child->bol_suppress) { - line->cursor -= child->ylen; + if (pos[child].y < len[vind].y || !cont[child].bol_suppress) { + line->cursor -= len[child].y; } - child->ypos = line->cursor; - line->height = max (child->xlen, line->height); + pos[child].y = line->cursor; + line->height = max (len[child].x, line->height); line->child_count++; } set_rows (view, &flowline); } static void -flow_view_height (view_t *view, flowline_t *flowlines) +flow_view_height (view_pos_t *len, flowline_t *flowlines) { - if (view->flow_size) { - view->ylen = 0; - for (flowline_t *line = flowlines; line; line = line->next) { - view->ylen += line->height; - } + len->y = 0; + for (flowline_t *line = flowlines; line; line = line->next) { + len->y += line->height; } } static void -flow_view_width (view_t *view, flowline_t *flowlines) +flow_view_width (view_pos_t *len, flowline_t *flowlines) { - if (view->flow_size) { - view->xlen = 0; - for (flowline_t *line = flowlines; line; line = line->next) { - view->xlen += line->height; - } + len->x = 0; + for (flowline_t *line = flowlines; line; line = line->next) { + len->x += line->height; } } static void -set_rows_down (view_t *view, flowline_t *flowlines) +set_rows_down (view_t view, flowline_t *flowlines) { - flow_view_height (view, flowlines); + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *rel = h->components[view_rel]; + view_pos_t *len = h->components[view_len]; + viewcont_t *cont = h->components[view_control]; + uint32_t vind = ref->index; + + if (cont[vind].flow_size) { + flow_view_height (&len[ref->index], flowlines); + } int cursor = 0; for (flowline_t *line = flowlines; line; line = line->next) { cursor += line->height; for (int i = 0; i < line->child_count; i++) { - view_t *child = view->children[line->first_child + i]; + uint32_t child = line->first_child + i; - child->xrel = child->xpos; - child->yrel = cursor + child->ypos - child->ylen; + rel[child].x = pos[child].x; + rel[child].y = cursor + pos[child].y - len[child].y; } } } static void -set_rows_up (view_t *view, flowline_t *flowlines) +set_rows_up (view_t view, flowline_t *flowlines) { - flow_view_height (view, flowlines); + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *rel = h->components[view_rel]; + view_pos_t *len = h->components[view_len]; + viewcont_t *cont = h->components[view_control]; + uint32_t vind = ref->index; - int cursor = view->ylen; + if (cont[vind].flow_size) { + flow_view_height (&len[ref->index], flowlines); + } + + int cursor = len[vind].y; for (flowline_t *line = flowlines; line; line = line->next) { for (int i = 0; i < line->child_count; i++) { - view_t *child = view->children[line->first_child + i]; + uint32_t child = line->first_child + i; - child->xrel = child->xpos; - child->yrel = cursor + child->ypos - child->ylen; + rel[child].x = pos[child].x; + rel[child].y = cursor + pos[child].y - len[child].y; } cursor -= line->height; } } static void -set_columns_right (view_t *view, flowline_t *flowlines) +set_columns_right (view_t view, flowline_t *flowlines) { - flow_view_width (view, flowlines); + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *rel = h->components[view_rel]; + view_pos_t *len = h->components[view_len]; + viewcont_t *cont = h->components[view_control]; + uint32_t vind = ref->index; + + if (cont[vind].flow_size) { + flow_view_width (&len[ref->index], flowlines); + } int cursor = 0; for (flowline_t *line = flowlines; line; line = line->next) { for (int i = 0; i < line->child_count; i++) { - view_t *child = view->children[line->first_child + i]; + uint32_t child = line->first_child + i; - child->xrel = cursor + child->xpos; - child->yrel = child->ypos; + rel[child].x = cursor + pos[child].x; + rel[child].y = pos[child].y; } cursor += line->height; } } static void -set_columns_left (view_t *view, flowline_t *flowlines) +set_columns_left (view_t view, flowline_t *flowlines) { - flow_view_width (view, flowlines); + __auto_type ref = View_GetRef (view); + hierarchy_t *h = ref->hierarchy; + view_pos_t *pos = h->components[view_pos]; + view_pos_t *rel = h->components[view_rel]; + view_pos_t *len = h->components[view_len]; + viewcont_t *cont = h->components[view_control]; + uint32_t vind = ref->index; - int cursor = view->xlen; + if (cont[vind].flow_size) { + flow_view_width (&len[ref->index], flowlines); + } + + int cursor = len[vind].x; for (flowline_t *line = flowlines; line; line = line->next) { cursor -= line->height; for (int i = 0; i < line->child_count; i++) { - view_t *child = view->children[line->first_child + i]; + uint32_t child = line->first_child + i; - child->xrel = cursor + child->xpos; - child->yrel = child->ypos; + rel[child].x = cursor + pos[child].x; + rel[child].y = pos[child].y; } } } VISIBLE void -view_flow_right_down (view_t *view) +view_flow_right_down (view_t view, view_pos_t len) { flow_right (view, set_rows_down); } VISIBLE void -view_flow_right_up (view_t *view) +view_flow_right_up (view_t view, view_pos_t len) { flow_right (view, set_rows_up); } VISIBLE void -view_flow_left_down (view_t *view) +view_flow_left_down (view_t view, view_pos_t len) { flow_left (view, set_rows_down); } VISIBLE void -view_flow_left_up (view_t *view) +view_flow_left_up (view_t view, view_pos_t len) { flow_left (view, set_rows_up); } VISIBLE void -view_flow_down_right (view_t *view) +view_flow_down_right (view_t view, view_pos_t len) { flow_down (view, set_columns_right); } VISIBLE void -view_flow_up_right (view_t *view) +view_flow_up_right (view_t view, view_pos_t len) { flow_up (view, set_columns_right); } VISIBLE void -view_flow_down_left (view_t *view) +view_flow_down_left (view_t view, view_pos_t len) { flow_down (view, set_columns_left); } VISIBLE void -view_flow_up_left (view_t *view) +view_flow_up_left (view_t view, view_pos_t len) { flow_up (view, set_columns_left); } -#endif From 70dae21ea613dace08df6ee2fbb1d191b34eddfd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Nov 2022 09:41:23 +0900 Subject: [PATCH 3134/3664] [nq] Get face animations working again --- nq/source/sbar.c | 57 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 14ff24e62..1f2fbb0b6 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -660,39 +660,38 @@ draw_frags (view_t view) static void draw_face (view_t view) { -#if 0 - int f, anim; + qpic_t *face; + if (cl.stats[STAT_HEALTH] <= 0) {//FIXME hide_Face or hide_sbar + sbar_remcomponent (sbar_face, hud_pic); + return; + } if ((cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY)) == (IT_INVISIBILITY | IT_INVULNERABILITY)) { - draw_pic (view, 112, 0, sb_face_invis_invuln); - return; - } - if (cl.stats[STAT_ITEMS] & IT_QUAD) { - draw_pic (view, 112, 0, sb_face_quad); - return; - } - if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) { - draw_pic (view, 112, 0, sb_face_invis); - return; - } - if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { - draw_pic (view, 112, 0, sb_face_invuln); - return; - } + face = sb_face_invis_invuln; + } else if (cl.stats[STAT_ITEMS] & IT_QUAD) { + face = sb_face_quad; + } else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) { + face = sb_face_invis; + } else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { + face = sb_face_invuln; + } else { + int f, anim; + if (cl.stats[STAT_HEALTH] >= 100) { + f = 4; + } else { + f = cl.stats[STAT_HEALTH] / 20; + } - if (cl.stats[STAT_HEALTH] >= 100) - f = 4; - else - f = cl.stats[STAT_HEALTH] / 20; - - if (cl.time <= cl.faceanimtime) { - anim = 1; - sb_updates = 0; // make sure the anim gets drawn over - } else - anim = 0; - draw_pic (view, 112, 0, sb_faces[f][anim]); -#endif + if (cl.time <= cl.faceanimtime) { + anim = 1; + sb_updates = 0; // make sure the anim gets drawn over + } else { + anim = 0; + } + face = sb_faces[f][anim]; + } + sbar_setcomponent (view, hud_pic, &face); } static inline void From 99e12872e59b50a66dc76e60a67734d597240236 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Nov 2022 10:38:07 +0900 Subject: [PATCH 3135/3664] [console] Get menu rendering working again For certain values of working. The whole thing needs a rewrite but it's nice that using an ECS doesn't force everything to conform to that model. --- include/QF/console.h | 4 ++-- libs/console/client.c | 9 +++++++++ libs/console/menu.c | 9 +++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/QF/console.h b/include/QF/console.h index c4972e667..734d2bda1 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -110,8 +110,8 @@ void C_DrawInputLine (struct inputline_s *il); struct view_s; void Menu_Init (void); void Menu_Load (void); -void Menu_Draw (struct view_s *view); -void Menu_Draw_Hud (struct view_s *view); +void Menu_Draw (struct view_s view); +void Menu_Draw_Hud (struct view_s view); struct IE_event_s; int Menu_EventHandler (const struct IE_event_s *ie_event); void Menu_Enter (void); diff --git a/libs/console/client.c b/libs/console/client.c index bea06d053..13fecf267 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -200,6 +200,7 @@ static view_t command_view; static view_t download_view; static view_t notify_view; static view_t say_view; +static view_t menu_view; #define CON_BUFFER_SIZE 32768 #define CON_LINES 1024 @@ -740,6 +741,10 @@ C_DrawConsole (void) View_SetPos (console_view, pos.x, ypos); View_UpdateHierarchy (console_view); } + if (con_state == con_menu) { + Menu_Draw (menu_view); + return; + } if (con_state == con_message) { con_setcomponent (say_view, client_charbuff, &say_line.buffer); @@ -1011,6 +1016,7 @@ C_Init (void) download_view = View_New (client_reg, console_view); notify_view = View_New (client_reg, screen_view); say_view = View_New (client_reg, screen_view); + menu_view = View_New (client_reg, screen_view); View_SetGravity (screen_view, grav_northwest); View_SetGravity (console_view, grav_northwest); @@ -1019,6 +1025,7 @@ C_Init (void) View_SetGravity (download_view, grav_southwest); View_SetGravity (notify_view, grav_northwest); View_SetGravity (say_view, grav_northwest); + View_SetGravity (menu_view, grav_center); View_SetResize (screen_view, 1, 1); View_SetResize (console_view, 1, 1); @@ -1027,6 +1034,7 @@ C_Init (void) View_SetResize (download_view, 1, 0); View_SetResize (notify_view, 1, 0); View_SetResize (say_view, 1, 0); + View_SetResize (menu_view, 0, 0); View_SetPos (screen_view, 0, 0); View_SetPos (console_view, 0, 0); @@ -1043,6 +1051,7 @@ C_Init (void) View_SetLen (download_view, 320, 8); View_SetLen (notify_view, 312, NOTIFY_LINES * 8); View_SetLen (say_view, 320, 8); + View_SetLen (menu_view, 320, 200); cmd_line.prompt = ""; cmd_line.input_line = Con_CreateInputLine (32, MAXCMDLINE, ']'); diff --git a/libs/console/menu.c b/libs/console/menu.c index 7f89626f7..c1c085a03 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -670,7 +670,7 @@ Menu_Load (void) } void -Menu_Draw (view_t *view) +Menu_Draw (view_t view) { menu_pic_t *m_pic; int i, x, y; @@ -679,8 +679,9 @@ Menu_Draw (view_t *view) if (!menu) return; - x = 0;//view->xabs; - y = 0;//view->yabs; + view_pos_t abs = View_GetAbs (view); + x = abs.x; + y = abs.y; if (menu->fadescreen) r_funcs->Draw_FadeScreen (); @@ -743,7 +744,7 @@ Menu_Draw (view_t *view) } void -Menu_Draw_Hud (view_t *view) +Menu_Draw_Hud (view_t view) { run_menu_pre (); *menu_pr_state.globals.ftime = *con_data.realtime;//FIXME double time From 5f01dc9fb5dba3fcbf9e00ff899ce42218f145e6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Nov 2022 11:10:56 +0900 Subject: [PATCH 3136/3664] [client] Make the hud update function type explicit --- include/client/hud.h | 4 ++++ libs/client/hud.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/client/hud.h b/include/client/hud.h index 3d3e876a2..b2f9b14ea 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -28,6 +28,8 @@ #ifndef __client_hud_h #define __client_hud_h +struct view_s; + enum { hud_href, hud_update, @@ -43,6 +45,8 @@ enum { hud_comp_count }; +typedef void (*hud_update_f) (struct view_s); + typedef struct hud_subpic_s { struct qpic_s *pic; uint32_t x, y; diff --git a/libs/client/hud.c b/libs/client/hud.c index 5473a5b34..7c01e2efa 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -278,7 +278,7 @@ draw_update (ecs_pool_t *pool) { uint32_t count = pool->count; uint32_t *ent = pool->dense; - void (**func) (view_t) = pool->data; + hud_update_f *func = pool->data; while (count-- > 0) { view_t view = { .id = *ent++, .reg = hud_registry }; (*func++) (view); From c0cfeec5d6a97cdb28d67d980e5d76864b833864 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Nov 2022 11:31:11 +0900 Subject: [PATCH 3137/3664] [nq] Clean up sbar updates for info changes Most of the update functions are scheduled by Sbar_Changed() using tables to determine what update functions need to be called for which view entities. As hud_updateonce is called, and an entity can have only one of any component, this becomes a set of updates to call when during hud/sbar rendering. --- include/sbar.h | 2 ++ nq/source/sbar.c | 86 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/include/sbar.h b/include/sbar.h index 95d38ac72..7fa011a15 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -48,6 +48,8 @@ typedef enum { sbc_info, sbc_items, sbc_weapon, + + sbc_num_changed } sbar_changed; void Sbar_Changed (sbar_changed change); diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 1f2fbb0b6..9060a761f 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -179,7 +179,7 @@ sbar_view (int x, int y, int w, int h, grav_t gravity, view_t parent) } static inline void -sbar_setcomponent (view_t view, uint32_t comp, void *data) +sbar_setcomponent (view_t view, uint32_t comp, const void *data) { Ent_SetComponent (view.id, comp, view.reg, data); } @@ -279,13 +279,6 @@ Sbar_ColorForMap (int m) return (bound (0, m, 13) * 16) + 8; } -void -Sbar_Changed (sbar_changed change) -{ - sb_update_flags |= 1 << change; - sb_updates = 0; // update next frame -} - static void draw_num (view_t *view, int num, int digits, int color) { @@ -1495,20 +1488,73 @@ draw_miniteam (view_t *view) #endif } +typedef struct { + hud_update_f update; + view_t *view; +} sb_updater_t; + +static const sb_updater_t ammo_update[] = { + {draw_miniammo, &sbar_miniammo}, + {draw_ammo, &sbar_ammo}, + {} +}; +static const sb_updater_t armor_update[] = { + {draw_armor, &sbar_armor}, + {} +}; +static const sb_updater_t frags_update[] = { + {draw_frags, &sbar_frags}, + {} +}; +static const sb_updater_t health_update[] = { + {draw_health, &sbar_health}, + {draw_face, &sbar_face}, + {} +}; +static const sb_updater_t info_update[] = { + {} +}; +static const sb_updater_t items_update[] = { + {draw_items, &sbar_items}, + {draw_sigils, &sbar_sigils}, + {} +}; +static const sb_updater_t weapon_update[] = { + {draw_weapons_sbar, &sbar_weapons}, + {} +}; + +static const sb_updater_t * const sb_updaters[sbc_num_changed] = { + [sbc_ammo] = ammo_update, + [sbc_armor] = armor_update, + [sbc_frags] = frags_update, + [sbc_health] = health_update, + [sbc_info] = info_update, + [sbc_items] = items_update, + [sbc_weapon] = weapon_update, +}; + +void +Sbar_Changed (sbar_changed change) +{ + sb_update_flags |= 1 << change; + sb_updates = 0; // update next frame + if ((unsigned) change >= (unsigned) sbc_num_changed) { + Sys_Error ("invalid sbar changed enum"); + } + const sb_updater_t *ud = sb_updaters[change]; + while (ud->update) { + sbar_setcomponent (*ud->view, hud_updateonce, &ud->update); + ud++; + } +} + void Sbar_Draw (void) { if (cls.state != ca_active) { return; } - sb_update_flags = ~0; - if (sb_update_flags & (1 << sbc_ammo)) { - draw_miniammo (sbar_miniammo); - draw_ammo (sbar_ammo); - } - if (sb_update_flags & (1 << sbc_armor)) draw_armor (sbar_armor); - if (sb_update_flags & (1 << sbc_frags)) draw_frags (sbar_frags); - if (sb_update_flags & (1 << sbc_health)) draw_health (sbar_health); if (sb_update_flags & (1 << sbc_info)) { draw_miniteam (0); draw_minifrags (0); @@ -1516,14 +1562,6 @@ Sbar_Draw (void) Sbar_DeathmatchOverlay (0); sbar_update_vis (); } - if (sb_update_flags & (1 << sbc_items)) { - draw_items (sbar_items); - draw_sigils (sbar_items); - } - if (sb_update_flags & (1 << sbc_weapon)) draw_weapons_sbar (sbar_weapons); - if (sb_update_flags & ((1 << sbc_health) | (1 << sbc_items))) { - draw_face (sbar_face); - } if (sb_showscores) { draw_solo_time (); } From 2a53047007830f7db27fab697832cdbe9d54b43c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Nov 2022 12:51:43 +0900 Subject: [PATCH 3138/3664] [nq,qw] Clean up centerprint dstring It was quite redundant and the optimization it vaguely provided belongs in sbar and not in the protocol parser. --- nq/source/cl_parse.c | 19 +------------------ nq/source/sbar.c | 12 ++++++++---- qw/include/client.h | 2 -- qw/source/cl_main.c | 5 +---- qw/source/cl_parse.c | 9 --------- 5 files changed, 10 insertions(+), 37 deletions(-) diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index c866b0b31..9bf358b68 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -127,8 +127,6 @@ const char *svc_strings[] = { "svc_spawnstaticsound2", }; -dstring_t *centerprint; - /* CL_EntityNum @@ -371,10 +369,7 @@ CL_ParseServerInfo (void) } // local state - if (!centerprint) - centerprint = dstring_newstr (); - else - dstring_clearstr (centerprint); + Sbar_CenterPrint (0); CL_NewMap (model_precache[1]); noclip_anglehack = false; // noclip is turned off at start @@ -966,10 +961,6 @@ CL_ParseServerMessage (void) case svc_centerprint: str = MSG_ReadString (net_message); - if (strcmp (str, centerprint->str)) { - dstring_copystr (centerprint, str); - //FIXME logging - } Sbar_CenterPrint (str); break; @@ -996,10 +987,6 @@ CL_ParseServerMessage (void) SCR_SetFullscreen (1); cl.completed_time = cl.time; str = MSG_ReadString (net_message); - if (strcmp (str, centerprint->str)) { - dstring_copystr (centerprint, str); - //FIXME logging - } Sbar_CenterPrint (str); break; @@ -1022,10 +1009,6 @@ CL_ParseServerMessage (void) SCR_SetFullscreen (1); cl.completed_time = cl.time; str = MSG_ReadString (net_message); - if (strcmp (str, centerprint->str)) { - dstring_copystr (centerprint, str); - //FIXME logging - } Sbar_CenterPrint (str); break; diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 9060a761f..c708c3516 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1288,15 +1288,19 @@ Sbar_CenterPrint (const char *str) { if (!str) { centertime_off = 0; - dstring_clearstr (¢er_string); + return; + } + + centertime_off = scr_centertime; + centertime_start = realtime; + + if (center_string.str && !strcmp (str, center_string.str)) { + // same string as last time, no need to lay out the text again return; } dstring_copystr (¢er_string, str); - centertime_off = scr_centertime; - centertime_start = realtime; - // count the number of lines for centering center_lines = 1; while (*str) { diff --git a/qw/include/client.h b/qw/include/client.h index a2cd77b56..854a5a987 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -303,6 +303,4 @@ void CL_RSShot_f (void); #define RSSHOT_WIDTH 320 #define RSSHOT_HEIGHT 200 -extern struct dstring_s *centerprint; - #endif // _CLIENT_H diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index f9a71af68..70dcb5f4a 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -664,8 +664,7 @@ CL_ClearState (void) SZ_Clear (&cls.netchan.message); - if (centerprint) - dstring_clearstr (centerprint); + Sbar_CenterPrint (0); } /* @@ -1435,7 +1434,6 @@ CL_Shutdown (void *data) } Info_Destroy (cls.userinfo); Cbuf_DeleteStack (cl_stbuf); - dstring_delete (centerprint); dstring_delete (cls.servername); dstring_delete (cls.downloadtempname); dstring_delete (cls.downloadname); @@ -1500,7 +1498,6 @@ CL_Init (void) Info_SetValueForStarKey (cls.userinfo, "*ver", QW_VERSION, 0); - centerprint = dstring_newstr (); cls.servername = dstring_newstr (); cls.downloadtempname = dstring_newstr (); cls.downloadname = dstring_newstr (); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index d532550f9..e534acafc 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -163,7 +163,6 @@ const char *svc_strings[] = { "NEW PROTOCOL" }; -dstring_t *centerprint; int oldparsecountmod; int parsecountmod; double parsecounttime; @@ -1437,10 +1436,6 @@ CL_ParseServerMessage (void) case svc_centerprint: str = MSG_ReadString (net_message); - if (strcmp (str, centerprint->str)) { - dstring_copystr (centerprint, str); - //FIXME logging - } Sbar_CenterPrint (str); break; @@ -1486,10 +1481,6 @@ CL_ParseServerMessage (void) SCR_SetFullscreen (1); cl.completed_time = realtime; str = MSG_ReadString (net_message); - if (strcmp (str, centerprint->str)) { - dstring_copystr (centerprint, str); - //FIXME logging - } Sbar_CenterPrint (str); break; From 1d51c05f906904d2aeb99fed6c426ada24e59dae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Nov 2022 13:06:20 +0900 Subject: [PATCH 3139/3664] [ui] Make passage objects reusable I had intended to do this for a while, but now that I want it for center print strings, it was time to make the change. --- include/QF/ui/passage.h | 3 ++- libs/ui/passage.c | 27 ++++++++++++++++++--------- libs/ui/test/test-passage.c | 3 ++- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/include/QF/ui/passage.h b/include/QF/ui/passage.h index 52a105cdd..09a47b9ee 100644 --- a/include/QF/ui/passage.h +++ b/include/QF/ui/passage.h @@ -49,7 +49,8 @@ typedef struct passage_s { struct hierarchy_s *hierarchy; ///< hierarchy of text objects } passage_t; -passage_t *Passage_ParseText (const char *text, struct ecs_registry_s *reg); +void Passage_ParseText (passage_t *passage, const char *text); +passage_t *Passage_New (struct ecs_registry_s *reg); void Passage_Delete (passage_t *passage); int Passage_IsSpace (const char *text) __attribute__((pure)); diff --git a/libs/ui/passage.c b/libs/ui/passage.c index 02e96a6dc..fd112c56e 100644 --- a/libs/ui/passage.c +++ b/libs/ui/passage.c @@ -99,16 +99,16 @@ add_entity (hierarchy_t *h, uint32_t parent) ref->index = i; } -VISIBLE passage_t * -Passage_ParseText (const char *text, ecs_registry_t *reg) +VISIBLE void +Passage_ParseText (passage_t *passage, const char *text) { - passage_t *passage = malloc (sizeof (passage_t)); - passage->text = text; - passage->reg = reg; - - if (!*text) { - return passage; + if (passage->hierarchy) {//FIXME just empty hierarchy + Hierarchy_Delete (passage->hierarchy); } + if (!*text) { + return; + } + passage->text = text; unsigned num_paragraphs = 1; unsigned num_text_objects = 1; @@ -133,7 +133,7 @@ Passage_ParseText (const char *text, ecs_registry_t *reg) parsing_space = 0; } } - passage->hierarchy = Hierarchy_New (reg, &passage_type, 0); + passage->hierarchy = Hierarchy_New (passage->reg, &passage_type, 0); Hierarchy_Reserve (passage->hierarchy, 1 + num_paragraphs + num_text_objects); #if 0 @@ -197,6 +197,15 @@ Passage_ParseText (const char *text, ecs_registry_t *reg) to->text, to->size, to->size, text + to->text); } #endif +} + +VISIBLE passage_t * +Passage_New (ecs_registry_t *reg) +{ + passage_t *passage = malloc (sizeof (passage_t)); + passage->text = 0; + passage->reg = reg; + passage->hierarchy = 0; return passage; } diff --git a/libs/ui/test/test-passage.c b/libs/ui/test/test-passage.c index e67223ee0..d6bbe8f57 100644 --- a/libs/ui/test/test-passage.c +++ b/libs/ui/test/test-passage.c @@ -66,7 +66,8 @@ main (void) ECS_RegisterComponents (registry, test_components, 1); registry->href_comp = test_href; - passage_t *passage = Passage_ParseText (test_text, registry); + passage_t *passage = Passage_New (registry); + Passage_ParseText (passage, test_text); if (passage->hierarchy->childCount[0] != 3) { ret = 1; printf ("incorrect number of paragraphs: %d\n", From 472b6995b79fccf29ef62b9fef113cbf64ed4ed5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Nov 2022 15:26:01 +0900 Subject: [PATCH 3140/3664] [ui] Set passage text object start and size The text object covering the whole passage was not being initialized, thus center print tried to print rubbish when (incorrectly) printing the entire message. --- include/QF/ui/passage.h | 6 ++++++ libs/ui/passage.c | 9 +++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/QF/ui/passage.h b/include/QF/ui/passage.h index 09a47b9ee..060c09948 100644 --- a/include/QF/ui/passage.h +++ b/include/QF/ui/passage.h @@ -35,6 +35,12 @@ */ ///@{ +enum { + passage_type_text_obj, + + passage_type_count +}; + typedef struct psg_text_s { /// beginning of text for this segment relative to passage_t.text uint32_t text; diff --git a/libs/ui/passage.c b/libs/ui/passage.c index fd112c56e..0157ee754 100644 --- a/libs/ui/passage.c +++ b/libs/ui/passage.c @@ -44,12 +44,6 @@ #include "QF/ui/passage.h" #include "QF/ui/view.h" -enum { - passage_type_text_obj, - - passage_type_count -}; - static const component_t passage_components[passage_type_count] = { [passage_type_text_obj] = { .size = sizeof (psg_text_t), @@ -112,6 +106,7 @@ Passage_ParseText (passage_t *passage, const char *text) unsigned num_paragraphs = 1; unsigned num_text_objects = 1; + psg_text_t root_text = {}; int parsing_space = Passage_IsSpace (text); for (const char *c = text; *c; c++) { int size; @@ -132,6 +127,7 @@ Passage_ParseText (passage_t *passage, const char *text) } parsing_space = 0; } + root_text.size = c - text; } passage->hierarchy = Hierarchy_New (passage->reg, &passage_type, 0); Hierarchy_Reserve (passage->hierarchy, @@ -152,6 +148,7 @@ Passage_ParseText (passage_t *passage, const char *text) psg_text_t *text_obj = &passage_obj[h->childIndex[1]]; *par_obj = *text_obj = (psg_text_t) { }; + *passage_obj = root_text; add_entity (passage->hierarchy, par_obj - passage_obj); parsing_space = Passage_IsSpace (text); From b5087e79e1af9de37a061a884ccd6ef603d42352 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 4 Nov 2022 15:29:34 +0900 Subject: [PATCH 3141/3664] [nq] Get center print working again While the word-level text objects aren't used (because standard center print messages are already flowed as such), using a passage object makes dealing with the lines and incremental printing quite easy and efficient (everything is counted just the once or twice, not every frame). --- nq/source/sbar.c | 66 ++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index c708c3516..ae57b4020 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -52,6 +52,7 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/passage.h" #include "QF/ui/view.h" #include "compat.h" @@ -1275,6 +1276,7 @@ Sbar_Intermission (int mode) /* CENTER PRINTING */ static dstring_t center_string = {&dstring_default_mem}; +static passage_t center_passage; static float centertime_start; // for slow victory printing static float centertime_off; static int center_lines; @@ -1286,7 +1288,7 @@ static int center_lines; void Sbar_CenterPrint (const char *str) { - if (!str) { + if (!str || !*str) { centertime_off = 0; return; } @@ -1300,66 +1302,53 @@ Sbar_CenterPrint (const char *str) } dstring_copystr (¢er_string, str); - - // count the number of lines for centering - center_lines = 1; - while (*str) { - if (*str == '\n') - center_lines++; - str++; - } + Passage_ParseText (¢er_passage, center_string.str); + // Standard centerprint strings are pre-flowed so each line in the message + // is a paragraph in the passage. + center_lines = center_passage.hierarchy->childCount[0]; } static void -Sbar_DrawCenterString (view_t view, int remaining) +Sbar_DrawCenterString (view_t view, unsigned remaining) { -#if 0 - const char *start; - int j, l, x, y; + view_pos_t abs = View_GetAbs (view); + view_pos_t len = View_GetLen (view); - start = center_string.str; + int x, y; if (center_lines <= 4) - y = view->yabs + view->ylen * 0.35; + y = abs.y + len.y * 0.35; else - y = view->yabs + 48; - - do { - // scan the width of the line - for (l = 0; l < 40; l++) - if (start[l] == '\n' || !start[l]) - break; - x = view->xabs + (view->xlen - l * 8) / 2; - for (j = 0; j < l; j++, x += 8) { - r_funcs->Draw_Character (x, y, start[j]); - if (!remaining--) - return; - } + y = abs.y + 48; + __auto_type h = center_passage.hierarchy; + psg_text_t *line = h->components[passage_type_text_obj]; + int line_count = center_lines; + while (line_count-- > 0 && remaining > 0) { + line++; + const char *text = center_passage.text + line->text; + unsigned count = min (40, line->size); + x = abs.x + (len.x - count * 8) / 2; + count = min (count, remaining); + remaining -= count; + r_funcs->Draw_nString (x, y, text, count); y += 8; - - while (*start && *start != '\n') - start++; - if (!*start) - break; - start++; // skip the \n - } while (1); -#endif + } } void Sbar_FinaleOverlay (void) { -#if 0 int remaining; r_data->scr_copyeverything = 1; +#if 0 draw_cachepic (hud_overlay_view, 0, 16, "gfx/finale.lmp", 1); +#endif // the finale prints the characters one at a time remaining = scr_printspeed * (realtime - centertime_start); Sbar_DrawCenterString (hud_overlay_view, remaining); -#endif } void @@ -2245,6 +2234,7 @@ Sbar_DontShowScores (void) void Sbar_Init (void) { + center_passage.reg = hud_registry; HUD_Init_Cvars (); Cvar_AddListener (Cvar_FindVar ("hud_sbar"), sbar_hud_sbar_f, 0); Cvar_AddListener (Cvar_FindVar ("hud_swap"), sbar_hud_swap_f, 0); From 5f98dac214f6ca034b97465bf901e786093b8cac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Nov 2022 10:55:45 +0900 Subject: [PATCH 3142/3664] [client] Add a hud outline component for debug Very handy for verifying views are placed correctly. Also fix some type issues with the func and update components. --- include/client/hud.h | 2 ++ libs/client/hud.c | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/include/client/hud.h b/include/client/hud.h index b2f9b14ea..73584c7a9 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -41,11 +41,13 @@ enum { hud_fill, hud_charbuff, hud_func, + hud_outline, hud_comp_count }; typedef void (*hud_update_f) (struct view_s); +typedef void (*hud_func_f) (struct view_pos_s, struct view_pos_s); typedef struct hud_subpic_s { struct qpic_s *pic; diff --git a/libs/client/hud.c b/libs/client/hud.c index 7c01e2efa..52c860f0a 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -47,11 +47,11 @@ static const component_t hud_components[hud_comp_count] = { .name = "href", }, [hud_update] = { - .size = sizeof (void (*)(view_t)), + .size = sizeof (hud_update_f), .name = "update", }, [hud_updateonce] = { - .size = sizeof (void (*)(view_t)), + .size = sizeof (hud_update_f), .name = "updateonce", }, [hud_tile] = { @@ -71,7 +71,7 @@ static const component_t hud_components[hud_comp_count] = { .name = "cachepic", }, [hud_fill] = { - .size = sizeof (uint32_t), + .size = sizeof (byte), .name = "fill", }, [hud_charbuff] = { @@ -79,9 +79,13 @@ static const component_t hud_components[hud_comp_count] = { .name = "charbuffer", }, [hud_func] = { - .size = sizeof (void (*)(view_pos_t)), + .size = sizeof (hud_func_f), .name = "func", }, + [hud_outline] = { + .size = sizeof (byte), + .name = "outline", + }, }; ecs_registry_t *hud_registry; @@ -362,7 +366,7 @@ draw_fill_views (ecs_pool_t *pool) { uint32_t count = pool->count; uint32_t *ent = pool->dense; - uint32_t *fill = pool->data; + byte *fill = pool->data; while (count-- > 0) { view_t view = { .id = *ent++, .reg = hud_registry }; if (View_GetVisible (view)) { @@ -395,7 +399,7 @@ draw_func_views (ecs_pool_t *pool) { uint32_t count = pool->count; uint32_t *ent = pool->dense; - void (**func) (view_pos_t, view_pos_t) = pool->data; + hud_func_f *func = pool->data; while (count-- > 0) { view_t view = { .id = *ent++, .reg = hud_registry }; if (View_GetVisible (view)) { @@ -407,6 +411,28 @@ draw_func_views (ecs_pool_t *pool) } } +static void +draw_outline_views (ecs_pool_t *pool) +{ + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + byte *col = pool->data; + __auto_type line = r_funcs->Draw_Line; + while (count-- > 0) { + view_t view = { .id = *ent++, .reg = hud_registry }; + byte c = *col++; + if (View_GetVisible (view)) { + view_pos_t p = View_GetAbs (view); + view_pos_t l = View_GetLen (view); + view_pos_t q = { p.x + l.x - 1, p.y + l.y - 1 }; + line (p.x, p.y, q.x, p.y, c); + line (p.x, q.y, q.x, q.y, c); + line (p.x, p.y, p.x, q.y, c); + line (q.x, p.y, q.x, q.y, c); + } + } +} + void HUD_Draw_Views (void) { @@ -420,6 +446,7 @@ HUD_Draw_Views (void) [hud_fill] = draw_fill_views, [hud_charbuff] = draw_charbuff_views, [hud_func] = draw_func_views, + [hud_outline] = draw_outline_views, }; for (int i = 0; i < hud_comp_count; i++) { if (draw_func[i]) { From 3d30e78da9927423c01e889985bd011ba1cd4954 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Nov 2022 16:38:07 +0900 Subject: [PATCH 3143/3664] [client] Add hud_debug cvar to draw view outlines It's much easier to debug the hud when even otherwise invisible views can be seen. --- libs/client/hud.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/libs/client/hud.c b/libs/client/hud.c index 52c860f0a..0598a6fa7 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -155,6 +155,15 @@ static cvar_t hud_time_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &hud_time }, }; +int hud_debug; +static cvar_t hud_debug_cvar = { + .name = "hud_debug", + .description = + "display hud view outlines for debugging", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &hud_debug }, +}; view_t sbar_view; view_t sbar_inventory_view; @@ -169,6 +178,40 @@ view_t hud_overlay_view; view_t hud_stuff_view; view_t hud_time_view; view_t hud_fps_view; + +static void +hud_add_outlines (view_t view) +{ + byte color = 0x6f; + Ent_SetComponent (view.id, hud_outline, view.reg, &color); + uint32_t count = View_ChildCount (view); + for (uint32_t i = 0; i < count; i++) { + hud_add_outlines (View_GetChild (view, i)); + } +} + +static void +hud_remove_outlines (view_t view) +{ + Ent_RemoveComponent (view.id, hud_outline, view.reg); + uint32_t count = View_ChildCount (view); + for (uint32_t i = 0; i < count; i++) { + hud_remove_outlines (View_GetChild (view, i)); + } +} + +static void +hud_debug_f (void *data, const cvar_t *cvar) +{ + if (!View_Valid (hud_view)) { + return; + } + if (hud_debug) { + hud_add_outlines (hud_view); + } else { + hud_remove_outlines (hud_view); + } +} view_t hud_main_view; static void @@ -236,6 +279,7 @@ HUD_Init_Cvars (void) Cvar_Register (&hud_ping_cvar, 0, 0); Cvar_Register (&hud_pl_cvar, 0, 0); Cvar_Register (&hud_time_cvar, 0, 0); + Cvar_Register (&hud_debug_cvar, hud_debug_f, 0); Cvar_Register (&hud_sbar_cvar, hud_sbar_f, 0); Cvar_Register (&hud_swap_cvar, hud_swap_f, 0); From 7b2f14114d5f2648aed636519c05ed663b9ea31d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Nov 2022 16:41:37 +0900 Subject: [PATCH 3144/3664] [nq] Get most of the hud working Frags, minifrags and miniteam now work (mostly, the auto-switching between them is not working yet). Switching between hud and sbar is mostly working, except for some problems with the hierarchies corrupting themselves: setting the parent of an object to another object in the same hierarchy is just completely broken, and working with complex hierarchies seems to mess up something (things getting out of phase). I guess my unit tests were too simple. For nq, all that remains is the various overlays (death-match, intermission and finale) and rogue and hipnotic specific updates. Fortunately, other than the death-match overlay, qw is just a subset of nq for the hud (and even then, I imagine the info in qw would be nice in nq). --- nq/source/sbar.c | 751 +++++++++++++++++++++++------------------------ 1 file changed, 374 insertions(+), 377 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index ae57b4020..b92eb067e 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -69,7 +69,10 @@ int sb_updates; // if >= vid.numpages, no update needed static int sb_update_flags; static int sb_view_size; +// view_t hud_view; +static view_t hud_miniteam; static view_t sbar_main; +static view_t hud_minifrags; // child of sbar_main for positioning static view_t sbar_inventory; static view_t sbar_frags; static view_t sbar_sigils; @@ -95,7 +98,7 @@ static view_t intermission_time; static view_t intermission_secr; static view_t intermission_kill; -typedef struct { +typedef struct view_def_s { view_t *view; struct { int x; @@ -108,9 +111,38 @@ typedef struct { int count; int xstep; int ystep; + struct view_def_s *subviews; } view_def_t; -static view_def_t view_defs[] = { +// used for "current view" +static view_t pseudo_parent = nullview; +static view_def_t frags_defs[] = { + {0, {4, 1, 28, 4}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {0, {4, 5, 28, 3}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {0, {6, 0, 24, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {0, {0, 0, 34, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {} +}; +static view_def_t minifrags_defs[] = { + {0, { 2, 1, 37, 3}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {0, { 2, 4, 37, 4}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {0, { 8, 0, 24, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {0, { 0, 0, 40, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + // teamplay team, name + {0, {48, 0, 32, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {0, {88, 0,104, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + // name + {0, {48, 0,128, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {} +}; +static view_def_t miniteam_defs[] = { + {0, { 0, 0, 32, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {0, {40, 0, 40, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {0, {-8, 0, 48, 8}, grav_northwest, &pseudo_parent, 1, 0, 0}, + {} +}; + +static view_def_t sbar_defs[] = { {&hud_overlay_view, { 0, 0,320,200}, grav_center, &cl_screen_view}, {&intermission_view, { 0, 0,320,200}, grav_northwest, &hud_overlay_view}, {0, {64, 24, 24, 24}, grav_northwest, &intermission_view, 1, 0, 0}, @@ -128,14 +160,22 @@ static view_def_t view_defs[] = { {0, {72, 0, 16, 24}, grav_northwest, &intermission_kill, 1, 0, 0}, {0, {80, 0, 24, 24}, grav_northwest, &intermission_kill, 3, 24, 0}, - {&sbar_main, { 0, 0,320, 48}, grav_south, &cl_screen_view}, + {&hud_view, { 0, 0,320, 48}, grav_south, &cl_screen_view}, + {&hud_miniteam, { 0, 0, 96, 48}, grav_southeast, &hud_view}, + {0, {0,0,96,8}, grav_northwest, &hud_miniteam, 6, 0, 8, miniteam_defs}, + {&sbar_main, { 0, 0,320, 48}, grav_south, &hud_view}, + {&hud_minifrags, {-192, 0,192, 48}, grav_southeast, &sbar_main}, + {0, {0,0,192,8}, grav_northwest, &hud_minifrags, 6, 0, 8, minifrags_defs}, + {&sbar_inventory, { 0, 0,320, 24}, grav_northwest, &sbar_main}, {&sbar_frags, { 0, 0,130, 8}, grav_northeast, &sbar_inventory}, {&sbar_sigils, { 0, 0, 32, 16}, grav_southeast, &sbar_inventory}, {&sbar_items, { 32, 0, 96, 16}, grav_southeast, &sbar_inventory}, + //NOTE sbar_armament moves and gets layed out again on hud_sbar change {&sbar_armament, { 0, 0,202, 24}, grav_northwest, &sbar_inventory}, {&sbar_weapons, { 0, 0,192, 16}, grav_southwest, &sbar_armament}, {&sbar_miniammo, { 0, 0, 32, 8}, grav_northwest, &sbar_armament}, + {&sbar_statusbar, { 0, 0,320, 24}, grav_southwest, &sbar_main}, {&sbar_armor, { 0, 0, 96, 24}, grav_northwest, &sbar_statusbar}, {&sbar_face, {112, 0, 24, 24}, grav_northwest, &sbar_statusbar}, @@ -149,13 +189,14 @@ static view_def_t view_defs[] = { {&sbar_solo_time, {184, 4, 96, 8}, grav_northwest, &sbar_solo}, {&sbar_solo_anchor, {232,12, 0, 8}, grav_northwest, &sbar_solo}, {&sbar_solo_name, { 0, 0, 0, 8}, grav_center, &sbar_solo_anchor}, + {0, { 0, 0, 32, 8}, grav_northwest, &sbar_frags, 4, 32, 0, frags_defs}, {0, { 0, 0, 8, 16}, grav_northwest, &sbar_sigils, 4, 8, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_armor, 4, 24, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_ammo, 4, 24, 0}, {0, { 0, 0, 16, 16}, grav_northwest, &sbar_items, 6, 16, 0}, {0, { 0, 0, 24, 16}, grav_northwest, &sbar_weapons, 7, 24, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 4, 24, 0}, - {0, {10, 0, 24, 24}, grav_northwest, &sbar_miniammo, 4, 48, 0}, + {0, {10, 0, 24, 8}, grav_northwest, &sbar_miniammo, 4, 48, 0}, {} }; @@ -211,7 +252,8 @@ static qpic_t *sb_ibar; static qpic_t *sb_sbar; static qpic_t *sb_scorebar; -static qpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes +// 0 is active, 1 is owned, 2-6 are flashes +static hud_subpic_t sb_weapons[7][8]; static qpic_t *sb_ammo[4]; static qpic_t *sb_sigil[4]; static qpic_t *sb_armor[3]; @@ -311,7 +353,7 @@ draw_num (view_t *view, int num, int digits, int color) } static inline void -draw_smallnum (view_t view, int x, int y, int n, int packed, int colored) +draw_smallnum (view_t view, int n, int packed, int colored) { void *comp = sbar_getcomponent (view, hud_charbuff); __auto_type charbuff = *(draw_charbuffer_t **) comp; @@ -335,7 +377,7 @@ draw_miniammo (view_t view) for (i = 0; i < 4; i++) { view_t v = View_GetChild (view, i); count = cl.stats[STAT_SHELLS + i]; - draw_smallnum (v, (6 * i + 1) * 8 + 2, 0, count, 0, 1); + draw_smallnum (v, count, 0, 1); } } @@ -386,7 +428,7 @@ calc_flashon (float time, int mask) } static void -draw_weapons_sbar (view_t view) +draw_weapons (view_t view) { int flashon, i; @@ -396,9 +438,9 @@ draw_weapons_sbar (view_t view) flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); if (flashon > 1) sb_updates = 0; // force update to remove flash - sbar_setcomponent (weap, hud_pic, &sb_weapons[flashon][i]); + sbar_setcomponent (weap, hud_subpic, &sb_weapons[flashon][i]); } else { - sbar_remcomponent (weap, hud_pic); + sbar_remcomponent (weap, hud_subpic); } } } @@ -465,31 +507,33 @@ typedef struct { team_t teams[MAX_CLIENTS]; int teamsort[MAX_CLIENTS]; int fragsort[MAX_SCOREBOARD]; -char scoreboardtext[MAX_SCOREBOARD][20]; -int scoreboardtop[MAX_SCOREBOARD]; -int scoreboardbottom[MAX_SCOREBOARD]; -int scoreboardcount[MAX_SCOREBOARD]; +static draw_charbuffer_t *frags_buff[MAX_SCOREBOARD]; +static draw_charbuffer_t *team_buff[MAX_SCOREBOARD]; +static draw_charbuffer_t *name_buff[MAX_SCOREBOARD]; +static draw_charbuffer_t *team_frags[MAX_SCOREBOARD]; int scoreboardlines, scoreboardteams; - static void __attribute__((used)) -Sbar_SortFrags (void) +Sbar_SortFrags (qboolean includespec) { int i, j, k; // sort by frags scoreboardlines = 0; for (i = 0; i < cl.maxclients; i++) { - if (cl.players[i].name->value[0]) { + if (cl.players[i].name && cl.players[i].name->value[0] + && (!cl.players[i].spectator || includespec)) { fragsort[scoreboardlines] = i; scoreboardlines++; + if (cl.players[i].spectator) + cl.players[i].frags = -999; } } + player_info_t *p = cl.players; for (i = 0; i < scoreboardlines; i++) { for (j = 0; j < scoreboardlines - 1 - i; j++) { - if (cl.players[fragsort[j]].frags - < cl.players[fragsort[j + 1]].frags) { + if (p[fragsort[j]].frags < p[fragsort[j + 1]].frags) { k = fragsort[j]; fragsort[j] = fragsort[j + 1]; fragsort[j + 1] = k; @@ -605,50 +649,186 @@ draw_solo (void) View_SetLen (sbar_solo_name, len.x, len.y); } +static void +clear_frags_bar (view_t view) +{ + sbar_remcomponent (View_GetChild (view, 0), hud_fill); + sbar_remcomponent (View_GetChild (view, 1), hud_fill); + sbar_remcomponent (View_GetChild (view, 2), hud_charbuff); + sbar_remcomponent (View_GetChild (view, 3), hud_func); +} + +static void +clear_minifrags_bar (view_t view) +{ + clear_frags_bar (view); + sbar_remcomponent (View_GetChild (view, 4), hud_charbuff); + sbar_remcomponent (View_GetChild (view, 5), hud_charbuff); + sbar_remcomponent (View_GetChild (view, 6), hud_charbuff); +} + +static void +set_frags_bar (view_t view, byte top, byte bottom, draw_charbuffer_t *buff, + hud_func_f func) +{ + sbar_setcomponent (View_GetChild (view, 0), hud_fill, &top); + sbar_setcomponent (View_GetChild (view, 1), hud_fill, &bottom); + sbar_setcomponent (View_GetChild (view, 2), hud_charbuff, &buff); + if (func) { + sbar_setcomponent (View_GetChild (view, 3), hud_func, &func); + } else { + sbar_remcomponent (View_GetChild (view, 3), hud_func); + } +} + +static void +set_minifrags_bar (view_t view, byte top, byte bottom, draw_charbuffer_t *buff, + hud_func_f func, draw_charbuffer_t *team, + draw_charbuffer_t *name) +{ + set_frags_bar (view, top, bottom, buff, func); + if (team) { + sbar_setcomponent (View_GetChild (view, 4), hud_charbuff, &team); + sbar_setcomponent (View_GetChild (view, 5), hud_charbuff, &name); + sbar_remcomponent (View_GetChild (view, 6), hud_charbuff); + } else { + sbar_remcomponent (View_GetChild (view, 4), hud_charbuff); + sbar_remcomponent (View_GetChild (view, 5), hud_charbuff); + sbar_setcomponent (View_GetChild (view, 6), hud_charbuff, &name); + } +} + +static void +frags_marker (view_pos_t pos, view_pos_t len) +{ + r_funcs->Draw_Character (pos.x, pos.y, 16); + r_funcs->Draw_Character (pos.x + len.x - 8, pos.y, 17); +} + static void draw_frags (view_t view) { -#if 0 - int i, k, l, p = -1; - int top, bottom; - int x; - player_info_t *s; - - if (cl.maxclients == 1) + if (cl.maxclients == 1) { return; - - Sbar_SortFrags (); - - // draw the text - l = scoreboardlines <= 4 ? scoreboardlines : 4; - - x = 0; - - for (i = 0; i < l; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - // draw background - top = Sbar_ColorForMap (s->topcolor); - bottom = Sbar_ColorForMap (s->bottomcolor); - - draw_fill (view, x + 4, 1, 28, 4, top); - draw_fill (view, x + 4, 5, 28, 3, bottom); - - draw_smallnum (view, x + 6, 0, s->frags, 0, 0); - - if (k == cl.viewentity - 1) - p = i; - - x += 32; } - if (p != -1) { - draw_character (view, p * 32, 0, 16); - draw_character (view, p * 32 + 26, 0, 17); + Sbar_SortFrags (0); + + int numbars = 4; + int count = min (scoreboardlines, numbars); + int i; + + for (i = 0; i < count; i++) { + int k = fragsort[i]; + __auto_type s = &cl.players[k]; + view_t bar = View_GetChild (view, i); + set_frags_bar (bar, + Sbar_ColorForMap (s->topcolor), + Sbar_ColorForMap (s->bottomcolor), + frags_buff[i], + (k == cl.viewentity - 1) ? frags_marker : 0); + draw_smallnum (View_GetChild (bar, 2), s->frags, 0, 0); + } + for (; i < numbars; i++) { + clear_frags_bar (View_GetChild (view, i)); + } +} + +static void +draw_minifrags (view_t view) +{ + if (cl.maxclients == 1) { + return; + } + Sbar_SortFrags (0); + + // find us + view_pos_t len = View_GetLen (view); + int numbars = len.y / 8; + int start = 0; + int i; + + for (i = 0; i < scoreboardlines; i++) { + if (fragsort[i] == cl.playernum) { + start = min (i - numbars / 2, scoreboardlines - numbars); + start = max (0, start); + } + } + + int count = min (scoreboardlines - start, numbars); + + for (i = 0; i < count; i++) { + int k = fragsort[i + start]; + __auto_type s = &cl.players[k]; + view_t bar = View_GetChild (view, i); + set_minifrags_bar (bar, + Sbar_ColorForMap (s->topcolor), + Sbar_ColorForMap (s->bottomcolor), + frags_buff[i], + (k == cl.viewentity - 1) ? frags_marker : 0, + cl.teamplay ? team_buff[i] : 0, + name_buff[i]); + if (cl.teamplay) { + write_charbuff (team_buff[i], 0, 0, s->team->value); + } + write_charbuff (name_buff[i], 0, 0, s->name->value); + draw_smallnum (View_GetChild (bar, 2), s->frags, 0, 0); + } + for (; i < numbars; i++) { + clear_minifrags_bar (View_GetChild (view, i)); + } +} + +static void +clear_miniteam_bar (view_t view) +{ + sbar_remcomponent (View_GetChild (view, 0), hud_charbuff); + sbar_remcomponent (View_GetChild (view, 1), hud_charbuff); + sbar_remcomponent (View_GetChild (view, 2), hud_func); +} + +static void +set_miniteam_bar (view_t view, draw_charbuffer_t *team, + draw_charbuffer_t *frags, hud_func_f func) +{ + sbar_setcomponent (View_GetChild (view, 0), hud_charbuff, &team); + sbar_setcomponent (View_GetChild (view, 1), hud_charbuff, &frags); + if (func) { + sbar_setcomponent (View_GetChild (view, 2), hud_func, &func); + } else { + sbar_remcomponent (View_GetChild (view, 2), hud_func); + } +} + +static void +draw_miniteam (view_t view) +{ + if (!cl.teamplay) { + return; + } + Sbar_SortTeams (); + + view_pos_t len = View_GetLen (view); + int numbars = len.y / 8; + int count = min (scoreboardteams, numbars); + int i; + info_key_t *player_team = cl.players[cl.playernum].team; + + for (i = 0; i < count; i++) { + int k = teamsort[i]; + team_t *tm = teams + k; + __auto_type s = &cl.players[k]; + view_t bar = View_GetChild (view, i); + hud_func_f func = 0; + if (player_team && strnequal (player_team->value, tm->team, 16)) { + func = frags_marker; + } + set_miniteam_bar (bar, team_buff[i], team_frags[i], func); + write_charbuff (team_buff[i], 0, 0, s->team->value); + write_charbuff (team_frags[i], 0, 0, va (0, "%5d", tm->frags)); + } + for (; i < numbars; i++) { + clear_miniteam_bar (View_GetChild (view, i)); } -#endif } static void @@ -1039,42 +1219,6 @@ draw_hipnotic_status (view_t *view) #endif } -static void -sbar_update_vis (void) -{ -#if 0 - qboolean headsup; - - if (r_data->scr_copyeverything) - Sbar_Changed (); - - sbar_view->visible = 0; - - headsup = !(hud_sbar || sb_view_size < 100); - - if ((sb_updates >= r_data->vid->numpages) && !headsup) - return; - - if (con_module && - con_module->data->console->lines == cl_screen_view->ylen) - return; // console is full screen - - if (cls.state == ca_active - && ((cl.stats[STAT_HEALTH] <= 0) || sb_showscores)) - hud_overlay_view->visible = 1; - else - hud_overlay_view->visible = 0; - - if (!sb_lines) - return; - - sbar_view->visible = 1; - - r_data->scr_copyeverything = 1; - sb_updates++; -#endif -} - static void Sbar_DeathmatchOverlay (view_t *view) { @@ -1363,124 +1507,6 @@ Sbar_DrawCenterPrint (void) Sbar_DrawCenterString (hud_overlay_view, -1); } -/* - draw_minifrags - - frags name - frags team name - displayed to right of status bar if there's room -*/ -static void -draw_minifrags (view_t *view) -{ -#if 0 - int numlines, top, bottom, f, i, k, x, y; - char num[20]; - player_info_t *s; - - r_data->scr_copyeverything = 1; - r_data->scr_fullupdate = 0; - - // scores - Sbar_SortFrags (); - - if (!scoreboardlines) - return; // no one there? - - numlines = view->ylen / 8; - if (numlines < 3) - return; // not enough room - - // find us - for (i = 0; i < scoreboardlines; i++) - if (fragsort[i] == cl.playernum) - break; - - if (i == scoreboardlines) // we're not there, we are probably a - // spectator, just display top - i = 0; - else // figure out start - i = i - numlines / 2; - - if (i > scoreboardlines - numlines) - i = scoreboardlines - numlines; - if (i < 0) - i = 0; - - x = 4; - y = 0; - - for (; i < scoreboardlines && y < view->ylen - 8 + 1; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - // draw ping - top = s->topcolor; - bottom = s->bottomcolor; - top = Sbar_ColorForMap (top); - bottom = Sbar_ColorForMap (bottom); - - draw_fill (view, x + 2, y + 1, 37, 3, top); - draw_fill (view, x + 2, y + 4, 37, 4, bottom); - - // draw number - f = s->frags; - if (k != cl.playernum) { - snprintf (num, sizeof (num), " %3i ", f); - } else { - snprintf (num, sizeof (num), "\x10%3i\x11", f); - } - - draw_nstring (view, x, y, num, 5); - - // team - if (cl.teamplay) { - draw_nstring (view, x + 48, y, s->team->value, 4); - draw_nstring (view, x + 48 + 40, y, s->name->value, 16); - } else - draw_nstring (view, x + 48, y, s->name->value, 16); - y += 8; - } -#endif -} - -static void -draw_miniteam (view_t *view) -{ -#if 0 - int i, k, x, y; - char num[12]; - info_key_t *player_team = cl.players[cl.playernum].team; - team_t *tm; - - if (!cl.teamplay) - return; - Sbar_SortTeams (); - - x = 0; - y = 0; - for (i = 0; i < scoreboardteams && y <= view->ylen; i++) { - k = teamsort[i]; - tm = teams + k; - - // draw pings - draw_nstring (view, x, y, tm->team, 4); - // draw total - snprintf (num, sizeof (num), "%5i", tm->frags); - draw_string (view, x + 40, y, num); - - if (player_team && strnequal (player_team->value, tm->team, 16)) { - draw_character (view, x - 8, y, 16); - draw_character (view, x + 32, y, 17); - } - - y += 8; - } -#endif -} - typedef struct { hud_update_f update; view_t *view; @@ -1497,6 +1523,8 @@ static const sb_updater_t armor_update[] = { }; static const sb_updater_t frags_update[] = { {draw_frags, &sbar_frags}, + {draw_minifrags, &hud_minifrags}, + {draw_miniteam, &hud_miniteam}, {} }; static const sb_updater_t health_update[] = { @@ -1505,6 +1533,9 @@ static const sb_updater_t health_update[] = { {} }; static const sb_updater_t info_update[] = { + {draw_frags, &sbar_frags}, + {draw_minifrags, &hud_minifrags}, + {draw_miniteam, &hud_miniteam}, {} }; static const sb_updater_t items_update[] = { @@ -1513,7 +1544,8 @@ static const sb_updater_t items_update[] = { {} }; static const sb_updater_t weapon_update[] = { - {draw_weapons_sbar, &sbar_weapons}, + {draw_weapons, &sbar_weapons}, + {draw_ammo, &sbar_ammo}, {} }; @@ -1549,19 +1581,12 @@ Sbar_Draw (void) return; } if (sb_update_flags & (1 << sbc_info)) { - draw_miniteam (0); - draw_minifrags (0); draw_overlay (0); Sbar_DeathmatchOverlay (0); - sbar_update_vis (); } if (sb_showscores) { draw_solo_time (); } -#if 0 - sbar_update_vis (); - hud_main_view->draw (hud_main_view); -#endif sb_update_flags = 0; } @@ -1571,36 +1596,79 @@ sbar_hud_swap_f (void *data, const cvar_t *cvar) if (hud_sbar) { return; } + grav_t armament_grav = hud_swap ? grav_southwest : grav_southeast; + grav_t weapons_grav = hud_swap ? grav_northwest : grav_northeast; + View_SetGravity (sbar_armament, armament_grav); + View_SetGravity (sbar_weapons, weapons_grav); + View_UpdateHierarchy (hud_view); } static void -sbar_hud_sbar_f (void *data, const cvar_t *cvar) +set_hud_sbar (void) { view_t v; - if (hud_swap) { + + if (hud_sbar) { + View_SetParent (sbar_armament, nullview);//FIXME workaround for same-h + View_SetParent (sbar_armament, sbar_inventory); + View_SetPos (sbar_armament, 0, 0); + View_SetLen (sbar_armament, 202, 24); + View_SetGravity (sbar_armament, grav_northwest); + + View_SetLen (sbar_weapons, 192, 16); + View_SetGravity (sbar_weapons, grav_southwest); + + View_SetLen (sbar_miniammo, 202, 8); + View_SetGravity (sbar_miniammo, grav_northwest); + + for (int i = 0; i < 7; i++) { + v = View_GetChild (sbar_weapons, i); + View_SetPos (v, i * 24, 0); + View_SetLen (v, 24 + 24 * (i == 6), 16); + + if (sbar_hascomponent (v, hud_subpic)) { + hud_subpic_t *subpic = sbar_getcomponent(v, hud_subpic); + subpic->w = subpic->pic->width; + } + } + for (int i = 0; i < 4; i++) { + v = View_GetChild (sbar_miniammo, i); + View_SetPos (v, i * 48 + 10, 0); + View_SetLen (v, 42, 8); + sbar_remcomponent (v, hud_subpic); + } + for (int i = 0; i < 7; i++) { + for (int j = 0; j < 8; j++) { + if (sb_weapons[i][j].pic) { + sb_weapons[i][j].w = sb_weapons[i][j].pic->width; + sb_weapons[i][j].h = sb_weapons[i][j].pic->height; + } + } + } + + sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar); + sbar_setcomponent (sbar_statusbar, hud_pic, &sb_sbar); + } else { + View_SetParent (sbar_armament, nullview);//FIXME workaround for same-h View_SetParent (sbar_armament, hud_view); View_SetPos (sbar_armament, 0, 48); View_SetLen (sbar_armament, 42, 156); - View_SetGravity (sbar_armament, - hud_swap ? grav_southwest : grav_southeast); + View_SetGravity (sbar_armament, grav_southeast); View_SetLen (sbar_weapons, 24, 112); - View_SetGravity (sbar_weapons, - hud_swap ? grav_northwest : grav_northeast); + View_SetGravity (sbar_weapons, grav_northeast); View_SetLen (sbar_miniammo, 42, 44); - View_SetGravity (sbar_weapons, grav_southeast); + View_SetGravity (sbar_miniammo, grav_southeast); for (int i = 0; i < 7; i++) { v = View_GetChild (sbar_weapons, i); View_SetPos (v, 0, i * 16); View_SetLen (v, 24, 16); + if (sbar_hascomponent (v, hud_subpic)) { - hud_subpic_t subpic = { - sbar_getcomponent (v, hud_pic), 0, 0, 24, 16 - }; - sbar_setcomponent (v, hud_subpic, &subpic); - sbar_remcomponent (v, hud_pic); + hud_subpic_t *subpic = sbar_getcomponent(v, hud_subpic); + subpic->w = 24; } } for (int i = 0; i < 4; i++) { @@ -1610,32 +1678,27 @@ sbar_hud_sbar_f (void *data, const cvar_t *cvar) hud_subpic_t subpic = { sb_ibar, 3 + (i * 48), 0, 42, 11 }; sbar_setcomponent (v, hud_subpic, &subpic); } - } else { - View_SetParent (sbar_armament, sbar_inventory); - View_SetPos (sbar_armament, 0, 0); - View_SetLen (sbar_armament, 202, 24); - View_SetGravity (sbar_armament, grav_northwest); - - View_SetLen (sbar_weapons, 32, 192); - View_SetGravity (sbar_weapons, grav_southwest); - - View_SetLen (sbar_miniammo, 42, 44); - View_SetGravity (sbar_weapons, grav_southeast); - for (int i = 0; i < 7; i++) { - v = View_GetChild (sbar_weapons, i); - View_SetPos (v, i * 24, 0); - View_SetLen (v, 24 + 24 * (i == 6), 16); - - if (sbar_hascomponent (v, hud_subpic)) { - hud_subpic_t *subpic = sbar_getcomponent(v, hud_subpic); - sbar_setcomponent (v, hud_pic, &subpic->pic); - sbar_remcomponent (v, hud_subpic); + for (int j = 0; j < 8; j++) { + if (sb_weapons[i][j].pic) { + sb_weapons[i][j].w = 24; + sb_weapons[i][j].h = sb_weapons[i][j].pic->height; + } } } + + sbar_remcomponent (sbar_inventory, hud_pic); + sbar_remcomponent (sbar_statusbar, hud_pic); } } +static void +sbar_hud_sbar_f (void *data, const cvar_t *cvar) +{ + set_hud_sbar (); + View_UpdateHierarchy (hud_view); +} + static void sbar_hud_fps_f (void *data, const cvar_t *cvar) { @@ -1663,25 +1726,45 @@ sbar_hud_time_f (void *data, const cvar_t *cvar) } static void -init_sbar_views (void) +create_views (view_def_t *view_defs, view_t parent) { for (int i = 0; view_defs[i].view || view_defs[i].parent; i++) { view_def_t *def = &view_defs[i]; - view_t parent = def->parent ? *def->parent : nullview; + view_t p = parent; int x = def->rect.x; int y = def->rect.y; int w = def->rect.w; int h = def->rect.h; + if (def->parent != &pseudo_parent) { + p = def->parent ? *def->parent : nullview; + } if (def->view) { - *def->view = sbar_view (x, y, w, h, def->gravity, parent); + *def->view = sbar_view (x, y, w, h, def->gravity, p); + if (def->subviews) { + create_views (def->subviews, *def->view); + } } else { for (int j = 0; j < def->count; j++) { - sbar_view (x, y, w, h, def->gravity, parent); + view_t v = sbar_view (x, y, w, h, def->gravity, p); + if (def->subviews) { + create_views (def->subviews, v); + } x += def->xstep; y += def->ystep; } } } +} + +static void +init_sbar_views (void) +{ + create_views (sbar_defs, nullview); + view_pos_t slen = View_GetLen (cl_screen_view); + view_pos_t hlen = View_GetLen (hud_view); + View_SetLen (hud_view, slen.x, hlen.y); + View_SetResize (hud_view, 1, 0); + for (int i = 0; i < 4; i++) { view_t v = View_GetChild (sbar_miniammo, i); draw_charbuffer_t *buffer = Draw_CreateBuffer (3, 1); @@ -1689,9 +1772,6 @@ init_sbar_views (void) sbar_setcomponent (v, hud_charbuff, &buffer); } - sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar); - sbar_setcomponent (sbar_statusbar, hud_pic, &sb_sbar); - if (r_data->vid->width > 320) { int l = (r_data->vid->width - 320) / 2; View_SetPos (sbar_tile[0], -l, 0); @@ -1708,82 +1788,6 @@ init_sbar_views (void) solo_name = Draw_CreateBuffer (20, 1); } -static void -init_hud_views (void) -{ -#if 0 - view_t *view; - view_t *minifrags_view = 0; - view_t *miniteam_view = 0; - - if (cl_screen_view->xlen < 512) { - hud_view = view_new (0, 0, 320, 48, grav_south); - - hud_frags_view = view_new (0, 0, 130, 8, grav_northeast); - hud_frags_view->draw = draw_frags; - } else if (cl_screen_view->xlen < 640) { - hud_view = view_new (0, 0, 512, 48, grav_south); - - minifrags_view = view_new (320, 0, 192, 48, grav_southwest); - minifrags_view->draw = draw_minifrags; - minifrags_view->resize_y = 1; - } else { - hud_view = view_new (0, 0, 640, 48, grav_south); - - minifrags_view = view_new (320, 0, 192, 48, grav_southwest); - minifrags_view->draw = draw_minifrags; - minifrags_view->resize_y = 1; - - miniteam_view = view_new (0, 0, 96, 48, grav_southeast); - miniteam_view->draw = draw_miniteam; - miniteam_view->resize_y = 1; - } - hud_view->resize_y = 1; - - hud_armament_view = view_new (0, 48, 42, 156, grav_southeast); - - view = view_new (0, 0, 42, 112, grav_northeast); - view->draw = draw_weapons_hud; - view_add (hud_armament_view, view); - - view = view_new (0, 0, 42, 44, grav_southeast); - view->draw = draw_ammo_hud; - view_add (hud_armament_view, view); - - hud_inventory_view = view_new (0, 0, 320, 24, grav_northwest); - view_add (hud_view, hud_inventory_view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_status; - view_add (hud_view, view); - - view = view_new (32, 0, 96, 16, grav_southeast); - view->draw = draw_items; - view_add (hud_inventory_view, view); - - view = view_new (0, 0, 32, 16, grav_southeast); - view->draw = draw_sigils; - view_add (hud_inventory_view, view); - - if (hud_frags_view) - view_add (hud_inventory_view, hud_frags_view); - - if (minifrags_view) - view_add (hud_view, minifrags_view); - if (miniteam_view) - view_add (hud_view, miniteam_view); - - view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); - view->resize_x = 1; - view_add (view, hud_view); - hud_view = view; - - view_add (hud_view, hud_armament_view); - - view_insert (hud_main_view, hud_view, 0); -#endif -} - static void init_hipnotic_sbar_views (void) { @@ -2004,33 +2008,18 @@ init_rogue_hud_views (void) static void init_views (void) { -#if 0 - hud_main_view = view_new (0, 0, cl_screen_view->xlen, cl_screen_view->ylen, - grav_northwest); - view_insert (cl_screen_view, hud_main_view, 0); - hud_main_view->resize_x = 1; // get resized if the 2d view resizes - hud_main_view->resize_y = 1; - hud_main_view->visible = 0; // but don't let the console draw our stuff - if (cl_screen_view->ylen > 300) - hud_overlay_view = view_new (0, 0, 320, 300, grav_center); - else - hud_overlay_view = view_new (0, 0, 320, cl_screen_view->ylen, - grav_center); - hud_overlay_view->draw = draw_overlay; - hud_overlay_view->visible = 0; - - hud_stuff_view = view_new (0, 48, 152, 16, grav_southwest); - hud_stuff_view->draw = draw_stuff; - - view_insert (hud_main_view, hud_overlay_view, 0); - view_insert (hud_main_view, hud_stuff_view, 0); -#endif hud_stuff_view = sbar_view (0, 48, 152, 16, grav_southwest, cl_screen_view); hud_time_view = sbar_view (8, 0, 64, 8, grav_northwest, hud_stuff_view); hud_fps_view = sbar_view (80, 0, 72, 8, grav_northwest, hud_stuff_view); time_buff = Draw_CreateBuffer (8, 1); fps_buff = Draw_CreateBuffer (11, 1); + for (int i = 0; i < MAX_SCOREBOARD; i++) { + frags_buff[i] = Draw_CreateBuffer (3, 1); + team_buff[i] = Draw_CreateBuffer (4, 1); + name_buff[i] = Draw_CreateBuffer (16, 1); + team_frags[i] = Draw_CreateBuffer (5, 1); + } if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) { init_hipnotic_sbar_views (); @@ -2040,7 +2029,6 @@ init_views (void) init_rogue_hud_views (); } else { init_sbar_views (); - init_hud_views (); } } @@ -2067,38 +2055,46 @@ load_pics (void) sb_colon = r_funcs->Draw_PicFromWad ("num_colon"); sb_slash = r_funcs->Draw_PicFromWad ("num_slash"); - sb_weapons[0][0] = r_funcs->Draw_PicFromWad ("inv_shotgun"); - sb_weapons[0][1] = r_funcs->Draw_PicFromWad ("inv_sshotgun"); - sb_weapons[0][2] = r_funcs->Draw_PicFromWad ("inv_nailgun"); - sb_weapons[0][3] = r_funcs->Draw_PicFromWad ("inv_snailgun"); - sb_weapons[0][4] = r_funcs->Draw_PicFromWad ("inv_rlaunch"); - sb_weapons[0][5] = r_funcs->Draw_PicFromWad ("inv_srlaunch"); - sb_weapons[0][6] = r_funcs->Draw_PicFromWad ("inv_lightng"); + sb_weapons[0][0].pic = r_funcs->Draw_PicFromWad ("inv_shotgun"); + sb_weapons[0][1].pic = r_funcs->Draw_PicFromWad ("inv_sshotgun"); + sb_weapons[0][2].pic = r_funcs->Draw_PicFromWad ("inv_nailgun"); + sb_weapons[0][3].pic = r_funcs->Draw_PicFromWad ("inv_snailgun"); + sb_weapons[0][4].pic = r_funcs->Draw_PicFromWad ("inv_rlaunch"); + sb_weapons[0][5].pic = r_funcs->Draw_PicFromWad ("inv_srlaunch"); + sb_weapons[0][6].pic = r_funcs->Draw_PicFromWad ("inv_lightng"); - sb_weapons[1][0] = r_funcs->Draw_PicFromWad ("inv2_shotgun"); - sb_weapons[1][1] = r_funcs->Draw_PicFromWad ("inv2_sshotgun"); - sb_weapons[1][2] = r_funcs->Draw_PicFromWad ("inv2_nailgun"); - sb_weapons[1][3] = r_funcs->Draw_PicFromWad ("inv2_snailgun"); - sb_weapons[1][4] = r_funcs->Draw_PicFromWad ("inv2_rlaunch"); - sb_weapons[1][5] = r_funcs->Draw_PicFromWad ("inv2_srlaunch"); - sb_weapons[1][6] = r_funcs->Draw_PicFromWad ("inv2_lightng"); + sb_weapons[1][0].pic = r_funcs->Draw_PicFromWad ("inv2_shotgun"); + sb_weapons[1][1].pic = r_funcs->Draw_PicFromWad ("inv2_sshotgun"); + sb_weapons[1][2].pic = r_funcs->Draw_PicFromWad ("inv2_nailgun"); + sb_weapons[1][3].pic = r_funcs->Draw_PicFromWad ("inv2_snailgun"); + sb_weapons[1][4].pic = r_funcs->Draw_PicFromWad ("inv2_rlaunch"); + sb_weapons[1][5].pic = r_funcs->Draw_PicFromWad ("inv2_srlaunch"); + sb_weapons[1][6].pic = r_funcs->Draw_PicFromWad ("inv2_lightng"); for (int i = 0; i < 5; i++) { - sb_weapons[2 + i][0] = + sb_weapons[2 + i][0].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_shotgun", i + 1)); - sb_weapons[2 + i][1] = + sb_weapons[2 + i][1].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_sshotgun", i + 1)); - sb_weapons[2 + i][2] = + sb_weapons[2 + i][2].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_nailgun", i + 1)); - sb_weapons[2 + i][3] = + sb_weapons[2 + i][3].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_snailgun", i + 1)); - sb_weapons[2 + i][4] = + sb_weapons[2 + i][4].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_rlaunch", i + 1)); - sb_weapons[2 + i][5] = + sb_weapons[2 + i][5].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_srlaunch", i + 1)); - sb_weapons[2 + i][6] = + sb_weapons[2 + i][6].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_lightng", i + 1)); } + for (int i = 0; i < 7; i++) { + for (int j = 0; j < 8; j++) { + if (sb_weapons[i][j].pic) { + sb_weapons[i][j].w = sb_weapons[i][j].pic->width; + sb_weapons[i][j].h = sb_weapons[i][j].pic->height; + } + } + } sb_ammo[0] = r_funcs->Draw_PicFromWad ("sb_shells"); sb_ammo[1] = r_funcs->Draw_PicFromWad ("sb_nails"); @@ -2244,6 +2240,7 @@ Sbar_Init (void) load_pics (); init_views (); + set_hud_sbar (); View_UpdateHierarchy (sbar_main); sbar_hud_fps_f (0, 0); From 42963f97c0b3cc5077c1260c7852b6222a1e0186 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Nov 2022 16:47:52 +0900 Subject: [PATCH 3145/3664] [client] Clean up some hud redundancies hud_view is set up by sbar, and the other views are no longer used. --- include/client/hud.h | 8 -------- libs/client/hud.c | 6 ------ 2 files changed, 14 deletions(-) diff --git a/include/client/hud.h b/include/client/hud.h index 73584c7a9..95dd86a5d 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -66,20 +66,12 @@ extern int hud_pl; extern int hud_ping; extern int hud_time; -//extern struct view_s sbar_view; -//extern struct view_s sbar_inventory_view; -//extern struct view_s sbar_frags_view; - extern struct view_s hud_view; -extern struct view_s hud_inventory_view; -extern struct view_s hud_armament_view; -extern struct view_s hud_frags_view; extern struct view_s hud_overlay_view; extern struct view_s hud_stuff_view; extern struct view_s hud_time_view; extern struct view_s hud_fps_view; -extern struct view_s hud_main_view; void HUD_Init (void); void HUD_Init_Cvars (void); diff --git a/libs/client/hud.c b/libs/client/hud.c index 0598a6fa7..01eb03597 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -170,9 +170,6 @@ view_t sbar_inventory_view; view_t sbar_frags_view; view_t hud_view; -view_t hud_inventory_view; -view_t hud_armament_view; -view_t hud_frags_view; view_t hud_overlay_view; view_t hud_stuff_view; @@ -212,7 +209,6 @@ hud_debug_f (void *data, const cvar_t *cvar) hud_remove_outlines (hud_view); } } -view_t hud_main_view; static void hud_sbar_f (void *data, const cvar_t *cvar) @@ -267,8 +263,6 @@ HUD_Init (void) hud_registry = ECS_NewRegistry (); ECS_RegisterComponents (hud_registry, hud_components, hud_comp_count); hud_registry->href_comp = hud_href; - - hud_view = View_New (hud_registry, nullview); } void From 57cd30fca3cabcbfef2abdab3e21e1be1ecbddb7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Nov 2022 17:38:14 +0900 Subject: [PATCH 3146/3664] [ecs] Move parent setting logic into hierarchy It should have always been here, but when I first created the hierarchy and transform objects, I didn't know where things would go. Having two chunks of code for setting an entity's parent was too already too much, and I expect to have other hierarchy types. Doesn't fix the issues encountered with sbar, of course. --- include/QF/ecs/hierarchy.h | 3 +++ libs/ecs/hierarchy.c | 28 +++++++++++++++++++++++-- libs/scene/transform.c | 42 ++++++++++++++------------------------ libs/ui/view.c | 40 ++++++++++++++---------------------- 4 files changed, 59 insertions(+), 54 deletions(-) diff --git a/include/QF/ecs/hierarchy.h b/include/QF/ecs/hierarchy.h index 2dcde3306..5a8056617 100644 --- a/include/QF/ecs/hierarchy.h +++ b/include/QF/ecs/hierarchy.h @@ -72,6 +72,9 @@ void Hierarchy_Delete (hierarchy_t *hierarchy); uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstParent, uint32_t srcRoot); void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); + +hierref_t Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, + hierarchy_t *src, uint32_t srcIndex); ///@} #endif//__QF_ecs_hierarchy_h diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 38fd4523b..cc5f0705e 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -400,7 +400,31 @@ Hierarchy_Copy (ecs_registry_t *dstReg, const hierarchy_t *src) dst->components[i], 0, src->components[i], 0, count); } - // Just in case the source hierarchy has modified objects - //Hierarchy_UpdateMatrices (dst); return dst; } + +hierref_t +Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, + hierarchy_t *src, uint32_t srcRoot) +{ + hierref_t r = {}; + if (dst && dstParent != nullent) { + if (dst->type != src->type) { + Sys_Error ("Can't set parent in hierarcy of different type"); + } + } else { + if (!srcRoot) { + r.hierarchy = src; + r.index = 0; + return r; + } + dst = Hierarchy_New (src->reg, src->type, 0); + } + r.hierarchy = dst; + r.index = Hierarchy_InsertHierarchy (dst, src, dstParent, srcRoot); + Hierarchy_RemoveHierarchy (src, srcRoot); + if (!src->num_objects) { + Hierarchy_Delete (src); + } + return r; +} diff --git a/libs/scene/transform.c b/libs/scene/transform.c index b6ab7b2f6..a01867b44 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -262,34 +262,22 @@ Transform_NewNamed (ecs_registry_t *reg, transform_t parent, const char *name) void Transform_SetParent (transform_t transform, transform_t parent) { - if (parent.reg && parent.id != nullent) { - __auto_type ref = Transform_GetRef (transform); - __auto_type tref = *ref; - __auto_type pref = Transform_GetRef (parent); - ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, - tref.hierarchy, - pref->index, tref.index); - ref->hierarchy = pref->hierarchy; - Hierarchy_RemoveHierarchy (tref.hierarchy, tref.index); - if (!tref.hierarchy->num_objects) { - Hierarchy_Delete (tref.hierarchy); - } - } else { - __auto_type ref = Transform_GetRef (transform); - __auto_type tref = *ref; - // null parent -> make transform root - if (!tref.index) { - // already root - return; - } - ref->hierarchy = Hierarchy_New (transform.reg, &transform_type, 0); - Hierarchy_InsertHierarchy (ref->hierarchy, tref.hierarchy, nullent, - tref.index); - Hierarchy_RemoveHierarchy (tref.hierarchy, tref.index); - if (!tref.hierarchy->num_objects) { - Hierarchy_Delete (tref.hierarchy); - } + hierarchy_t *dst = 0; + uint32_t dstParent = nullent; + hierarchy_t *src = 0; + uint32_t srcIndex = 0; + if (Transform_Valid (parent)) { + __auto_type ref = Transform_GetRef (parent); + dst = ref->hierarchy; + dstParent = ref->index; } + { + __auto_type ref = Transform_GetRef (transform); + src = ref->hierarchy; + srcIndex = ref->index; + } + Hierarchy_SetParent (dst, dstParent, src, srcIndex); + __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; byte *modified = h->components[transform_type_modified]; diff --git a/libs/ui/view.c b/libs/ui/view.c index 712c237e9..5c71ec0fc 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -265,32 +265,22 @@ View_UpdateHierarchy (view_t view) void View_SetParent (view_t view, view_t parent) { - if (parent.reg && parent.id != nullent) { - __auto_type ref = View_GetRef (view); - __auto_type vref = *ref; - __auto_type pref = View_GetRef (parent); - ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, - vref.hierarchy, - pref->index, vref.index); - ref->hierarchy = pref->hierarchy; - Hierarchy_RemoveHierarchy (vref.hierarchy, vref.index); - if (!vref.hierarchy->num_objects) { - Hierarchy_Delete (vref.hierarchy); - } - } else { - __auto_type ref = View_GetRef (view); - __auto_type vref = *ref; - if (!vref.index) { - return; - } - ref->hierarchy = Hierarchy_New (view.reg, &view_type, 0); - Hierarchy_InsertHierarchy (ref->hierarchy, vref.hierarchy, nullent, - vref.index); - Hierarchy_RemoveHierarchy (vref.hierarchy, vref.index); - if (!vref.hierarchy->num_objects) { - Hierarchy_Delete (vref.hierarchy); - } + hierarchy_t *dst = 0; + uint32_t dstParent = nullent; + hierarchy_t *src = 0; + uint32_t srcIndex = 0; + if (View_Valid (parent)) { + __auto_type ref = View_GetRef (parent); + dst = ref->hierarchy; + dstParent = ref->index; } + { + __auto_type ref = View_GetRef (view); + src = ref->hierarchy; + srcIndex = ref->index; + } + Hierarchy_SetParent (dst, dstParent, src, srcIndex); + __auto_type ref = View_GetRef (view); hierarchy_t *h = ref->hierarchy; byte *modified = h->components[view_modified]; From 10037927eaa892276dbae10c96d0b78452461c35 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Nov 2022 21:26:47 +0900 Subject: [PATCH 3147/3664] [ecs] Add hierarchy-only tests The hierarchy-specific tests from the transform tests have been moved into the ecs tests and the transform tests renamed appropriately. As part of the process, hierarchies can now have a null type (ie, no additional components maintained by the hierarchy). This should make sorting out the issues highlighted by sbar a bit easier. --- libs/ecs/hierarchy.c | 71 ++- libs/ecs/test/Makemodule.am | 8 + libs/ecs/test/test-hierarchy.c | 477 ++++++++++++++++++ libs/scene/test/Makemodule.am | 10 +- .../{test-hierarchy.c => test-transform.c} | 247 --------- 5 files changed, 534 insertions(+), 279 deletions(-) create mode 100644 libs/ecs/test/test-hierarchy.c rename libs/scene/test/{test-hierarchy.c => test-transform.c} (59%) diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index cc5f0705e..dd35aed04 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -94,9 +94,11 @@ Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count) Component_ResizeArray (&parentIndex_component, (void **) &hierarchy->parentIndex, new_max); - for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { - Component_ResizeArray (&hierarchy->type->components[i], - &hierarchy->components[i], new_max); + if (hierarchy->type) { + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + Component_ResizeArray (&hierarchy->type->components[i], + &hierarchy->components[i], new_max); + } } hierarchy->max_objects = new_max; } @@ -118,10 +120,12 @@ hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t count) hierarchy->childIndex, dstIndex, index, count); Component_MoveElements (&parentIndex_component, hierarchy->parentIndex, dstIndex, index, count); - for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { - Component_MoveElements (&hierarchy->type->components[i], - hierarchy->components[i], - dstIndex, index, count); + if (hierarchy->type) { + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + Component_MoveElements (&hierarchy->type->components[i], + hierarchy->components[i], + dstIndex, index, count); + } } } @@ -142,10 +146,12 @@ hierarchy_close (hierarchy_t *hierarchy, uint32_t index, uint32_t count) hierarchy->childIndex, index, srcIndex, count); Component_MoveElements (&parentIndex_component, hierarchy->parentIndex, index, srcIndex, count); - for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { - Component_MoveElements (&hierarchy->type->components[i], - hierarchy->components[i], - index, srcIndex, count); + if (hierarchy->type) { + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + Component_MoveElements (&hierarchy->type->components[i], + hierarchy->components[i], + index, srcIndex, count); + } } } @@ -169,10 +175,12 @@ hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, ref->hierarchy = dst; ref->index = dstIndex + i; } - for (uint32_t i = 0; i < dst->type->num_components; i++) { - Component_CopyElements (&dst->type->components[i], - dst->components[i], dstIndex, - src->components[i], srcIndex, count); + if (dst->type) { + for (uint32_t i = 0; i < dst->type->num_components; i++) { + Component_CopyElements (&dst->type->components[i], + dst->components[i], dstIndex, + src->components[i], srcIndex, count); + } } } @@ -187,9 +195,11 @@ hierarchy_init (hierarchy_t *dst, uint32_t index, dst->childCount[index + i] = 0; dst->childIndex[index + i] = childIndex; } - for (uint32_t i = 0; i < dst->type->num_components; i++) { - Component_CreateElements (&dst->type->components[i], - dst->components[i], index, count); + if (dst->type) { + for (uint32_t i = 0; i < dst->type->num_components; i++) { + Component_CreateElements (&dst->type->components[i], + dst->components[i], index, count); + } } } @@ -344,9 +354,12 @@ Hierarchy_New (ecs_registry_t *reg, const hierarchy_type_t *type, hierarchy_t *hierarchy = PR_RESNEW (reg->hierarchies); hierarchy->reg = reg; + hierarchy->components = 0; hierarchy->type = type; - hierarchy->components = calloc (hierarchy->type->num_components, - sizeof (void *)); + if (type) { + hierarchy->components = calloc (hierarchy->type->num_components, + sizeof (void *)); + } if (createRoot) { hierarchy_open (hierarchy, 0, 1); @@ -363,10 +376,12 @@ Hierarchy_Delete (hierarchy_t *hierarchy) free (hierarchy->childCount); free (hierarchy->childIndex); free (hierarchy->parentIndex); - for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { - free (hierarchy->components[i]); + if (hierarchy->type) { + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + free (hierarchy->components[i]); + } + free (hierarchy->components); } - free (hierarchy->components); ecs_registry_t *reg = hierarchy->reg; PR_RESFREE (reg->hierarchies, hierarchy); @@ -395,10 +410,12 @@ Hierarchy_Copy (ecs_registry_t *dstReg, const hierarchy_t *src) dst->childIndex, 0, src->childIndex, 0, count); Component_CopyElements (&parentIndex_component, dst->parentIndex, 0, src->parentIndex, 0, count); - for (uint32_t i = 0; i < dst->type->num_components; i++) { - Component_CopyElements (&dst->type->components[i], - dst->components[i], 0, - src->components[i], 0, count); + if (dst->type) { + for (uint32_t i = 0; i < dst->type->num_components; i++) { + Component_CopyElements (&dst->type->components[i], + dst->components[i], 0, + src->components[i], 0, count); + } } return dst; } diff --git a/libs/ecs/test/Makemodule.am b/libs/ecs/test/Makemodule.am index 6c3e6bd8f..9d3479561 100644 --- a/libs/ecs/test/Makemodule.am +++ b/libs/ecs/test/Makemodule.am @@ -1,5 +1,6 @@ libs_ecs_tests = \ libs/ecs/test/test-components \ + libs/ecs/test/test-hierarchy \ libs/ecs/test/test-registry TESTS += $(libs_ecs_tests) @@ -17,6 +18,13 @@ libs_ecs_test_test_components_LDADD= \ libs_ecs_test_test_components_DEPENDENCIES= \ $(libs_ecs_test_libs) +libs_ecs_test_test_hierarchy_SOURCES= \ + libs/ecs/test/test-hierarchy.c +libs_ecs_test_test_hierarchy_LDADD= \ + $(libs_ecs_test_libs) +libs_ecs_test_test_hierarchy_DEPENDENCIES= \ + $(libs_ecs_test_libs) + libs_ecs_test_test_registry_SOURCES= \ libs/ecs/test/test-registry.c libs_ecs_test_test_registry_LDADD= \ diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c new file mode 100644 index 000000000..7ceb1cb7c --- /dev/null +++ b/libs/ecs/test/test-hierarchy.c @@ -0,0 +1,477 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "QF/ecs/component.h" +#include "QF/ecs/hierarchy.h" + +enum { + test_href, + test_name, + + test_num_components +}; + +static const component_t test_components[] = { + [test_href] = { + .size = sizeof (hierref_t), + .create = 0,//create_href, + .name = "href", + }, + [test_name] = { + .size = sizeof (const char *), + .name = "name", + }, +}; + +ecs_registry_t *test_reg; + +static int +check_hierarchy_size (hierarchy_t *h, uint32_t size) +{ + if (h->num_objects != size) { + printf ("hierarchy does not have exactly %u transform\n", size); + return 0; + } + ecs_registry_t *reg = h->reg; + for (uint32_t i = 0; i < h->num_objects; i++) { + hierref_t *ref = Ent_GetComponent (h->ent[i], test_href, reg); + char **name = Ent_GetComponent (h->ent[i], test_name, reg);; + if (ref->hierarchy != h) { + printf ("transform %d (%s) does not point to hierarchy\n", + i, *name); + } + } + return 1; +} + +static void +dump_hierarchy (hierarchy_t *h) +{ + ecs_registry_t *reg = h->reg; + for (uint32_t i = 0; i < h->num_objects; i++) { + hierref_t *ref = Ent_GetComponent (h->ent[i], test_href, reg); + char **name = Ent_GetComponent (h->ent[i], test_name, reg);; + printf ("%2d: %5s %2u %2u %2u %2u %2u\n", i, *name, h->ent[i], + ref->index, h->parentIndex[i], + h->childIndex[i], h->childCount[i]); + } + puts (""); +} + +static int +check_indices (uint32_t ent, uint32_t index, uint32_t parentIndex, + uint32_t childIndex, uint32_t childCount) +{ + ecs_registry_t *reg = test_reg; + char **entname = Ent_GetComponent (ent, test_name, reg);; + hierref_t *ref = Ent_GetComponent (ent, test_href, reg); + hierarchy_t *h = ref->hierarchy; + if (ref->index != index) { + char **name = Ent_GetComponent (h->ent[index], test_name, reg);; + printf ("%s/%s index incorrect: expect %u got %u\n", + *entname, *name, + index, ref->index); + return 0; + } + if (h->parentIndex[index] != parentIndex) { + printf ("%s parent index incorrect: expect %u got %u\n", + *entname, parentIndex, h->parentIndex[index]); + return 0; + } + if (h->childIndex[index] != childIndex) { + printf ("%s child index incorrect: expect %u got %u\n", + *entname, childIndex, h->childIndex[index]); + return 0; + } + if (h->childCount[index] != childCount) { + printf ("%s child count incorrect: expect %u got %u\n", + *entname, childCount, h->childCount[index]); + return 0; + } + return 1; +} + +static uint32_t +create_ent (uint32_t parent, const char *name) +{ + uint32_t ent = ECS_NewEntity (test_reg); + Ent_SetComponent (ent, test_name, test_reg, &name); + hierref_t *ref = Ent_AddComponent (ent, test_href, test_reg); + + if (parent != nullent) { + hierref_t *pref = Ent_GetComponent (parent, test_href, test_reg); + ref->hierarchy = pref->hierarchy; + ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, 0, + pref->index, 0); + } else { + ref->hierarchy = Hierarchy_New (test_reg, 0, 1); + ref->index = 0; + } + ref->hierarchy->ent[ref->index] = ent; + return ent; +} + +static void +set_parent (uint32_t child, uint32_t parent) +{ + if (parent != nullent) { + hierref_t *pref = Ent_GetComponent (parent, test_href, test_reg); + hierref_t *cref = Ent_GetComponent (child, test_href, test_reg); + Hierarchy_SetParent (pref->hierarchy, pref->index, + cref->hierarchy, cref->index); + } else { + hierref_t *cref = Ent_GetComponent (child, test_href, test_reg); + Hierarchy_SetParent (0, nullent, cref->hierarchy, cref->index); + } +} + +static int +test_single_transform (void) +{ + uint32_t ent = create_ent (nullent, "test"); + hierarchy_t *h; + + if (ent == nullent) { + printf ("create_ent returned null\n"); + return 1; + } + hierref_t *ref = Ent_GetComponent (ent, test_href, test_reg); + if (!ref) { + printf ("Ent_GetComponent(test_href) returned null\n"); + return 1; + } + if (!(h = ref->hierarchy)) { + printf ("New entity has no hierarchy\n"); + return 1; + } + if (!check_hierarchy_size (h, 1)) { return 1; } + if (!check_indices (ent, 0, nullent, 1, 0)) { return 1; } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (h); + + return 0; +} + +static int +test_parent_child_init (void) +{ + uint32_t parent = create_ent (nullent, "parent"); + uint32_t child = create_ent (parent, "child"); + + hierref_t *pref = Ent_GetComponent (parent, test_href, test_reg); + hierref_t *cref = Ent_GetComponent (child, test_href, test_reg); + if (pref->hierarchy != cref->hierarchy) { + printf ("parent and child transforms have separate hierarchies\n"); + return 1; + } + + hierarchy_t *h = pref->hierarchy; + + if (!check_hierarchy_size (h, 2)) { return 1; } + + if (!check_indices (parent, 0, nullent, 1, 1)) { return 1; } + if (!check_indices (child, 1, 0, 2, 0)) { return 1; } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (h); + + return 0; +} + +static int +test_parent_child_setparent (void) +{ + uint32_t parent = create_ent (nullent, "parent"); + uint32_t child = create_ent (nullent, "child"); + + if (!check_indices (parent, 0, nullent, 1, 0)) { return 1; } + if (!check_indices (child, 0, nullent, 1, 0)) { return 1; } + + hierref_t *pref = Ent_GetComponent (parent, test_href, test_reg); + hierref_t *cref = Ent_GetComponent (child, test_href, test_reg); + if (pref->hierarchy == cref->hierarchy) { + printf ("parent and child entities have same hierarchy before" + " set paret\n"); + return 1; + } + + set_parent (child, parent); + + if (pref->hierarchy != cref->hierarchy) { + printf ("parent and child transforms have separate hierarchies\n"); + return 1; + } + + hierarchy_t *h = pref->hierarchy; + + if (!check_hierarchy_size (h, 2)) { return 1; } + + if (!check_indices (parent, 0, nullent, 1, 1)) { return 1; } + if (!check_indices (child, 1, 0, 2, 0)) { return 1; } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (h); + + return 0; +} + +static int +test_build_hierarchy (void) +{ + printf ("test_build_hierarchy\n"); + + uint32_t root = create_ent (nullent, "root"); + uint32_t A = create_ent (root, "A"); + uint32_t B = create_ent (root, "B"); + uint32_t C = create_ent (root, "C"); + + hierref_t *ref = Ent_GetComponent (root, test_href, test_reg); + + if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } + if (!check_indices (A, 1, 0, 4, 0)) { return 1; } + if (!check_indices (B, 2, 0, 4, 0)) { return 1; } + if (!check_indices (C, 3, 0, 4, 0)) { return 1; } + + uint32_t B1 = create_ent (B, "B1"); + + if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } + if (!check_indices ( A, 1, 0, 4, 0)) { return 1; } + if (!check_indices ( B, 2, 0, 4, 1)) { return 1; } + if (!check_indices ( C, 3, 0, 5, 0)) { return 1; } + if (!check_indices (B1, 4, 2, 5, 0)) { return 1; } + + uint32_t A1 = create_ent (A, "A1"); + + if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } + if (!check_indices ( A, 1, 0, 4, 1)) { return 1; } + if (!check_indices ( B, 2, 0, 5, 1)) { return 1; } + if (!check_indices ( C, 3, 0, 6, 0)) { return 1; } + if (!check_indices (A1, 4, 1, 6, 0)) { return 1; } + if (!check_indices (B1, 5, 2, 6, 0)) { return 1; } + uint32_t A1a = create_ent (A1, "A1a"); + uint32_t B2 = create_ent (B, "B2"); + uint32_t A2 = create_ent (A, "A2"); + uint32_t B3 = create_ent (B, "B3"); + uint32_t B2a = create_ent (B2, "B2a"); + + if (!check_hierarchy_size (ref->hierarchy, 11)) { return 1; } + + if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } + if (!check_indices ( A, 1, 0, 4, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 6, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 9, 0)) { return 1; } + if (!check_indices ( A1, 4, 1, 9, 1)) { return 1; } + if (!check_indices ( A2, 5, 1, 10, 0)) { return 1; } + if (!check_indices ( B1, 6, 2, 10, 0)) { return 1; } + if (!check_indices ( B2, 7, 2, 10, 1)) { return 1; } + if (!check_indices ( B3, 8, 2, 11, 0)) { return 1; } + if (!check_indices (A1a, 9, 4, 11, 0)) { return 1; } + if (!check_indices (B2a, 10, 7, 11, 0)) { return 1; } + + uint32_t D = create_ent (root, "D"); + + if (!check_hierarchy_size (ref->hierarchy, 12)) { return 1; } + + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 10, 0)) { return 1; } + if (!check_indices ( D, 4, 0, 10, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 10, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 11, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 11, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 11, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 12, 0)) { return 1; } + if (!check_indices (A1a, 10, 5, 12, 0)) { return 1; } + if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; } + + dump_hierarchy (ref->hierarchy); + uint32_t C1 = create_ent (C, "C1"); + dump_hierarchy (ref->hierarchy); + if (!check_hierarchy_size (ref->hierarchy, 13)) { return 1; } + + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 12, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 13, 0)) { return 1; } + if (!check_indices ( C1, 10, 3, 13, 0)) { return 1; } + if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } + if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (ref->hierarchy); + + return 0; +} + +static int +test_build_hierarchy2 (void) +{ + printf ("test_build_hierarchy2\n"); + + uint32_t root = create_ent (nullent, "root"); + uint32_t A = create_ent (root, "A"); + uint32_t B = create_ent (root, "B"); + uint32_t C = create_ent (root, "C"); + uint32_t B1 = create_ent (B, "B1"); + uint32_t A1 = create_ent (A, "A1"); + uint32_t A1a = create_ent (A1, "A1a"); + uint32_t B2 = create_ent (B, "B2"); + uint32_t A2 = create_ent (A, "A2"); + uint32_t B3 = create_ent (B, "B3"); + uint32_t B2a = create_ent (B2, "B2a"); + uint32_t D = create_ent (root, "D"); + uint32_t C1 = create_ent (C, "C1"); + + hierref_t *ref = Ent_GetComponent (root, test_href, test_reg); + + if (!check_hierarchy_size (ref->hierarchy, 13)) { return 1; } + + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 12, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 13, 0)) { return 1; } + if (!check_indices ( C1, 10, 3, 13, 0)) { return 1; } + if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } + if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } + + uint32_t T = create_ent (nullent, "T"); + uint32_t X = create_ent (T, "X"); + uint32_t Y = create_ent (T, "Y"); + uint32_t Z = create_ent (T, "Z"); + uint32_t Y1 = create_ent (Y, "Y1"); + uint32_t X1 = create_ent (X, "X1"); + uint32_t X1a = create_ent (X1, "X1a"); + uint32_t Y2 = create_ent (Y, "Y2"); + uint32_t X2 = create_ent (X, "X2"); + uint32_t Y3 = create_ent (Y, "Y3"); + uint32_t Y2a = create_ent (Y2, "Y2a"); + uint32_t Z1 = create_ent (Z, "Z1"); + + + hierref_t *Tref = Ent_GetComponent (T, test_href, test_reg); + dump_hierarchy (Tref->hierarchy); + if (!check_hierarchy_size (Tref->hierarchy, 12)) { return 1; } + + if (!check_indices ( T, 0, nullent, 1, 3)) { return 1; } + if (!check_indices ( X, 1, 0, 4, 2)) { return 1; } + if (!check_indices ( Y, 2, 0, 6, 3)) { return 1; } + if (!check_indices ( Z, 3, 0, 9, 1)) { return 1; } + if (!check_indices ( X1, 4, 1, 10, 1)) { return 1; } + if (!check_indices ( X2, 5, 1, 11, 0)) { return 1; } + if (!check_indices ( Y1, 6, 2, 11, 0)) { return 1; } + if (!check_indices ( Y2, 7, 2, 11, 1)) { return 1; } + if (!check_indices ( Y3, 8, 2, 12, 0)) { return 1; } + if (!check_indices ( Z1, 9, 3, 12, 0)) { return 1; } + if (!check_indices (X1a, 10, 4, 12, 0)) { return 1; } + if (!check_indices (Y2a, 11, 7, 12, 0)) { return 1; } + + set_parent (T, B); + + dump_hierarchy (ref->hierarchy); + + if (!check_hierarchy_size (ref->hierarchy, 25)) { return 1; } + + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 4)) { return 1; } + if (!check_indices ( C, 3, 0, 11, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 12, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 12, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 13, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 13, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 13, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 14, 0)) { return 1; } + if (!check_indices ( T, 10, 2, 14, 3)) { return 1; } + if (!check_indices ( C1, 11, 3, 17, 0)) { return 1; } + if (!check_indices (A1a, 12, 5, 17, 0)) { return 1; } + if (!check_indices (B2a, 13, 8, 17, 0)) { return 1; } + if (!check_indices ( X, 14, 10, 17, 2)) { return 1; } + if (!check_indices ( Y, 15, 10, 19, 3)) { return 1; } + if (!check_indices ( Z, 16, 10, 22, 1)) { return 1; } + if (!check_indices ( X1, 17, 14, 23, 1)) { return 1; } + if (!check_indices ( X2, 18, 14, 24, 0)) { return 1; } + if (!check_indices ( Y1, 19, 15, 24, 0)) { return 1; } + if (!check_indices ( Y2, 20, 15, 24, 1)) { return 1; } + if (!check_indices ( Y3, 21, 15, 25, 0)) { return 1; } + if (!check_indices ( Z1, 22, 16, 25, 0)) { return 1; } + if (!check_indices (X1a, 23, 17, 25, 0)) { return 1; } + if (!check_indices (Y2a, 24, 20, 25, 0)) { return 1; } + + set_parent (Y, nullent); + + dump_hierarchy (ref->hierarchy); + hierref_t *Yref = Ent_GetComponent (Y, test_href, test_reg); + dump_hierarchy (Yref->hierarchy); + if (!check_hierarchy_size (ref->hierarchy, 20)) { return 1; } + if (!check_hierarchy_size (Yref->hierarchy, 5)) { return 1; } + + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 4)) { return 1; } + if (!check_indices ( C, 3, 0, 11, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 12, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 12, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 13, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 13, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 13, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 14, 0)) { return 1; } + if (!check_indices ( T, 10, 2, 14, 3)) { return 1; } + if (!check_indices ( C1, 11, 3, 17, 0)) { return 1; } + if (!check_indices (A1a, 12, 5, 17, 0)) { return 1; } + if (!check_indices (B2a, 13, 8, 17, 0)) { return 1; } + if (!check_indices ( X, 14, 10, 16, 2)) { return 1; } + if (!check_indices ( Z, 15, 10, 18, 1)) { return 1; } + if (!check_indices ( X1, 16, 14, 19, 1)) { return 1; } + if (!check_indices ( X2, 17, 14, 20, 0)) { return 1; } + if (!check_indices ( Z1, 18, 15, 20, 0)) { return 1; } + if (!check_indices (X1a, 19, 16, 20, 0)) { return 1; } + + if (!check_indices ( Y, 0, nullent, 1, 3)) { return 1; } + if (!check_indices ( Y1, 1, 0, 4, 0)) { return 1; } + if (!check_indices ( Y2, 2, 0, 4, 1)) { return 1; } + if (!check_indices ( Y3, 3, 0, 5, 0)) { return 1; } + if (!check_indices (Y2a, 4, 2, 5, 0)) { return 1; } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (ref->hierarchy); + Hierarchy_Delete (Yref->hierarchy); + + return 0; +} + +int +main (void) +{ + test_reg = ECS_NewRegistry (); + ECS_RegisterComponents (test_reg, test_components, test_num_components); + test_reg->href_comp = test_href; + + if (test_single_transform ()) { return 1; } + if (test_parent_child_init ()) { return 1; } + if (test_parent_child_setparent ()) { return 1; } + if (test_build_hierarchy ()) { return 1; } + if (test_build_hierarchy2 ()) { return 1; } + + ECS_DelRegistry (test_reg); + + return 0; +} diff --git a/libs/scene/test/Makemodule.am b/libs/scene/test/Makemodule.am index 4f5e71533..d1074ed13 100644 --- a/libs/scene/test/Makemodule.am +++ b/libs/scene/test/Makemodule.am @@ -1,5 +1,5 @@ libs_scene_tests = \ - libs/scene/test/test-hierarchy + libs/scene/test/test-transform TESTS += $(libs_scene_tests) @@ -10,9 +10,9 @@ libs_scene_test_libs= \ libs/ecs/libQFecs.la \ libs/util/libQFutil.la -libs_scene_test_test_hierarchy_SOURCES= \ - libs/scene/test/test-hierarchy.c -libs_scene_test_test_hierarchy_LDADD= \ +libs_scene_test_test_transform_SOURCES= \ + libs/scene/test/test-transform.c +libs_scene_test_test_transform_LDADD= \ $(libs_scene_test_libs) -libs_scene_test_test_hierarchy_DEPENDENCIES= \ +libs_scene_test_test_transform_DEPENDENCIES= \ $(libs_scene_test_libs) diff --git a/libs/scene/test/test-hierarchy.c b/libs/scene/test/test-transform.c similarity index 59% rename from libs/scene/test/test-hierarchy.c rename to libs/scene/test/test-transform.c index 026a8394d..6311bb4a8 100644 --- a/libs/scene/test/test-hierarchy.c +++ b/libs/scene/test/test-transform.c @@ -61,21 +61,6 @@ check_hierarchy_size (transform_t t, uint32_t size) return 1; } -static void -dump_hierarchy (transform_t t) -{ - hierarchy_t *h = Transform_GetRef (t)->hierarchy; - char **name = h->components[transform_type_name]; - ecs_registry_t *reg = h->reg; - for (uint32_t i = 0; i < h->num_objects; i++) { - hierref_t *ref = Ent_GetComponent (h->ent[i], scene_href, reg); - printf ("%2d: %5s %2u %2u %2u %2u %2u\n", i, name[i], h->ent[i], - ref->index, h->parentIndex[i], - h->childIndex[i], h->childCount[i]); - } - puts (""); -} - static int check_indices (transform_t transform, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t childCount) @@ -285,236 +270,6 @@ test_parent_child_setparent (void) return 0; } -static int -test_build_hierarchy (void) -{ - printf ("test_build_hierarchy\n"); - - transform_t root = Transform_NewNamed (reg, (transform_t) {}, "root"); - transform_t A = Transform_NewNamed (reg, root, "A"); - transform_t B = Transform_NewNamed (reg, root, "B"); - transform_t C = Transform_NewNamed (reg, root, "C"); - - if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } - if (!check_indices (A, 1, 0, 4, 0)) { return 1; } - if (!check_indices (B, 2, 0, 4, 0)) { return 1; } - if (!check_indices (C, 3, 0, 4, 0)) { return 1; } - - transform_t B1 = Transform_NewNamed (reg, B, "B1"); - - if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } - if (!check_indices ( A, 1, 0, 4, 0)) { return 1; } - if (!check_indices ( B, 2, 0, 4, 1)) { return 1; } - if (!check_indices ( C, 3, 0, 5, 0)) { return 1; } - if (!check_indices (B1, 4, 2, 5, 0)) { return 1; } - - transform_t A1 = Transform_NewNamed (reg, A, "A1"); - - if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } - if (!check_indices ( A, 1, 0, 4, 1)) { return 1; } - if (!check_indices ( B, 2, 0, 5, 1)) { return 1; } - if (!check_indices ( C, 3, 0, 6, 0)) { return 1; } - if (!check_indices (A1, 4, 1, 6, 0)) { return 1; } - if (!check_indices (B1, 5, 2, 6, 0)) { return 1; } - transform_t A1a = Transform_NewNamed (reg, A1, "A1a"); - transform_t B2 = Transform_NewNamed (reg, B, "B2"); - transform_t A2 = Transform_NewNamed (reg, A, "A2"); - transform_t B3 = Transform_NewNamed (reg, B, "B3"); - transform_t B2a = Transform_NewNamed (reg, B2, "B2a"); - - if (!check_hierarchy_size (root, 11)) { return 1; } - - if (!check_indices (root, 0, nullent, 1, 3)) { return 1; } - if (!check_indices ( A, 1, 0, 4, 2)) { return 1; } - if (!check_indices ( B, 2, 0, 6, 3)) { return 1; } - if (!check_indices ( C, 3, 0, 9, 0)) { return 1; } - if (!check_indices ( A1, 4, 1, 9, 1)) { return 1; } - if (!check_indices ( A2, 5, 1, 10, 0)) { return 1; } - if (!check_indices ( B1, 6, 2, 10, 0)) { return 1; } - if (!check_indices ( B2, 7, 2, 10, 1)) { return 1; } - if (!check_indices ( B3, 8, 2, 11, 0)) { return 1; } - if (!check_indices (A1a, 9, 4, 11, 0)) { return 1; } - if (!check_indices (B2a, 10, 7, 11, 0)) { return 1; } - - transform_t D = Transform_NewNamed (reg, root, "D"); - - if (!check_hierarchy_size (root, 12)) { return 1; } - - if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } - if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } - if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } - if (!check_indices ( C, 3, 0, 10, 0)) { return 1; } - if (!check_indices ( D, 4, 0, 10, 0)) { return 1; } - if (!check_indices ( A1, 5, 1, 10, 1)) { return 1; } - if (!check_indices ( A2, 6, 1, 11, 0)) { return 1; } - if (!check_indices ( B1, 7, 2, 11, 0)) { return 1; } - if (!check_indices ( B2, 8, 2, 11, 1)) { return 1; } - if (!check_indices ( B3, 9, 2, 12, 0)) { return 1; } - if (!check_indices (A1a, 10, 5, 12, 0)) { return 1; } - if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; } - - dump_hierarchy (root); - transform_t C1 = Transform_NewNamed (reg, C, "C1"); - dump_hierarchy (root); - if (!check_hierarchy_size (root, 13)) { return 1; } - - if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } - if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } - if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } - if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } - if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } - if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; } - if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; } - if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; } - if (!check_indices ( B2, 8, 2, 12, 1)) { return 1; } - if (!check_indices ( B3, 9, 2, 13, 0)) { return 1; } - if (!check_indices ( C1, 10, 3, 13, 0)) { return 1; } - if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } - if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } - - // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (Transform_GetRef (root)->hierarchy); - - return 0; -} - -static int -test_build_hierarchy2 (void) -{ - printf ("test_build_hierarchy2\n"); - - transform_t root = Transform_NewNamed (reg, (transform_t) {}, "root"); - transform_t A = Transform_NewNamed (reg, root, "A"); - transform_t B = Transform_NewNamed (reg, root, "B"); - transform_t C = Transform_NewNamed (reg, root, "C"); - transform_t B1 = Transform_NewNamed (reg, B, "B1"); - transform_t A1 = Transform_NewNamed (reg, A, "A1"); - transform_t A1a = Transform_NewNamed (reg, A1, "A1a"); - transform_t B2 = Transform_NewNamed (reg, B, "B2"); - transform_t A2 = Transform_NewNamed (reg, A, "A2"); - transform_t B3 = Transform_NewNamed (reg, B, "B3"); - transform_t B2a = Transform_NewNamed (reg, B2, "B2a"); - transform_t D = Transform_NewNamed (reg, root, "D"); - transform_t C1 = Transform_NewNamed (reg, C, "C1"); - - if (!check_hierarchy_size (root, 13)) { return 1; } - - if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } - if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } - if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } - if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } - if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } - if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; } - if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; } - if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; } - if (!check_indices ( B2, 8, 2, 12, 1)) { return 1; } - if (!check_indices ( B3, 9, 2, 13, 0)) { return 1; } - if (!check_indices ( C1, 10, 3, 13, 0)) { return 1; } - if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } - if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } - - transform_t T = Transform_NewNamed (reg, (transform_t) {}, "T"); - transform_t X = Transform_NewNamed (reg, T, "X"); - transform_t Y = Transform_NewNamed (reg, T, "Y"); - transform_t Z = Transform_NewNamed (reg, T, "Z"); - transform_t Y1 = Transform_NewNamed (reg, Y, "Y1"); - transform_t X1 = Transform_NewNamed (reg, X, "X1"); - transform_t X1a = Transform_NewNamed (reg, X1, "X1a"); - transform_t Y2 = Transform_NewNamed (reg, Y, "Y2"); - transform_t X2 = Transform_NewNamed (reg, X, "X2"); - transform_t Y3 = Transform_NewNamed (reg, Y, "Y3"); - transform_t Y2a = Transform_NewNamed (reg, Y2, "Y2a"); - transform_t Z1 = Transform_NewNamed (reg, Z, "Z1"); - - dump_hierarchy (T); - if (!check_hierarchy_size (T, 12)) { return 1; } - - if (!check_indices ( T, 0, nullent, 1, 3)) { return 1; } - if (!check_indices ( X, 1, 0, 4, 2)) { return 1; } - if (!check_indices ( Y, 2, 0, 6, 3)) { return 1; } - if (!check_indices ( Z, 3, 0, 9, 1)) { return 1; } - if (!check_indices ( X1, 4, 1, 10, 1)) { return 1; } - if (!check_indices ( X2, 5, 1, 11, 0)) { return 1; } - if (!check_indices ( Y1, 6, 2, 11, 0)) { return 1; } - if (!check_indices ( Y2, 7, 2, 11, 1)) { return 1; } - if (!check_indices ( Y3, 8, 2, 12, 0)) { return 1; } - if (!check_indices ( Z1, 9, 3, 12, 0)) { return 1; } - if (!check_indices (X1a, 10, 4, 12, 0)) { return 1; } - if (!check_indices (Y2a, 11, 7, 12, 0)) { return 1; } - - Transform_SetParent (T, B); - - dump_hierarchy (root); - - if (!check_hierarchy_size (root, 25)) { return 1; } - - if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } - if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } - if (!check_indices ( B, 2, 0, 7, 4)) { return 1; } - if (!check_indices ( C, 3, 0, 11, 1)) { return 1; } - if (!check_indices ( D, 4, 0, 12, 0)) { return 1; } - if (!check_indices ( A1, 5, 1, 12, 1)) { return 1; } - if (!check_indices ( A2, 6, 1, 13, 0)) { return 1; } - if (!check_indices ( B1, 7, 2, 13, 0)) { return 1; } - if (!check_indices ( B2, 8, 2, 13, 1)) { return 1; } - if (!check_indices ( B3, 9, 2, 14, 0)) { return 1; } - if (!check_indices ( T, 10, 2, 14, 3)) { return 1; } - if (!check_indices ( C1, 11, 3, 17, 0)) { return 1; } - if (!check_indices (A1a, 12, 5, 17, 0)) { return 1; } - if (!check_indices (B2a, 13, 8, 17, 0)) { return 1; } - if (!check_indices ( X, 14, 10, 17, 2)) { return 1; } - if (!check_indices ( Y, 15, 10, 19, 3)) { return 1; } - if (!check_indices ( Z, 16, 10, 22, 1)) { return 1; } - if (!check_indices ( X1, 17, 14, 23, 1)) { return 1; } - if (!check_indices ( X2, 18, 14, 24, 0)) { return 1; } - if (!check_indices ( Y1, 19, 15, 24, 0)) { return 1; } - if (!check_indices ( Y2, 20, 15, 24, 1)) { return 1; } - if (!check_indices ( Y3, 21, 15, 25, 0)) { return 1; } - if (!check_indices ( Z1, 22, 16, 25, 0)) { return 1; } - if (!check_indices (X1a, 23, 17, 25, 0)) { return 1; } - if (!check_indices (Y2a, 24, 20, 25, 0)) { return 1; } - - Transform_SetParent (Y, (transform_t) {}); - - dump_hierarchy (root); - dump_hierarchy (Y); - if (!check_hierarchy_size (root, 20)) { return 1; } - if (!check_hierarchy_size (Y, 5)) { return 1; } - - if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } - if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } - if (!check_indices ( B, 2, 0, 7, 4)) { return 1; } - if (!check_indices ( C, 3, 0, 11, 1)) { return 1; } - if (!check_indices ( D, 4, 0, 12, 0)) { return 1; } - if (!check_indices ( A1, 5, 1, 12, 1)) { return 1; } - if (!check_indices ( A2, 6, 1, 13, 0)) { return 1; } - if (!check_indices ( B1, 7, 2, 13, 0)) { return 1; } - if (!check_indices ( B2, 8, 2, 13, 1)) { return 1; } - if (!check_indices ( B3, 9, 2, 14, 0)) { return 1; } - if (!check_indices ( T, 10, 2, 14, 3)) { return 1; } - if (!check_indices ( C1, 11, 3, 17, 0)) { return 1; } - if (!check_indices (A1a, 12, 5, 17, 0)) { return 1; } - if (!check_indices (B2a, 13, 8, 17, 0)) { return 1; } - if (!check_indices ( X, 14, 10, 16, 2)) { return 1; } - if (!check_indices ( Z, 15, 10, 18, 1)) { return 1; } - if (!check_indices ( X1, 16, 14, 19, 1)) { return 1; } - if (!check_indices ( X2, 17, 14, 20, 0)) { return 1; } - if (!check_indices ( Z1, 18, 15, 20, 0)) { return 1; } - if (!check_indices (X1a, 19, 16, 20, 0)) { return 1; } - - if (!check_indices ( Y, 0, nullent, 1, 3)) { return 1; } - if (!check_indices ( Y1, 1, 0, 4, 0)) { return 1; } - if (!check_indices ( Y2, 2, 0, 4, 1)) { return 1; } - if (!check_indices ( Y3, 3, 0, 5, 0)) { return 1; } - if (!check_indices (Y2a, 4, 2, 5, 0)) { return 1; } - - // Delete the hierarchy directly as setparent isn't fully tested - Hierarchy_Delete (Transform_GetRef (root)->hierarchy); - Hierarchy_Delete (Transform_GetRef (Y)->hierarchy); - - return 0; -} - static int check_vector (transform_t transform, vec4f_t (*func) (transform_t t), @@ -733,8 +488,6 @@ main (void) if (test_single_transform ()) { return 1; } if (test_parent_child_init ()) { return 1; } if (test_parent_child_setparent ()) { return 1; } - if (test_build_hierarchy ()) { return 1; } - if (test_build_hierarchy2 ()) { return 1; } if (test_frames ()) { return 1; } Scene_DeleteScene (scene); From 26438848ceb206d2d3f8aa04c24745bc9503ef46 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Nov 2022 22:23:46 +0900 Subject: [PATCH 3148/3664] [ecs] Add a failing hierarchy test This is the bug that sbar found when pulling a sub-hierarchy out of a larger hierarchy: child indices not getting updated correctly for later siblings and any niece objects. --- libs/ecs/test/test-hierarchy.c | 96 +++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index 7ceb1cb7c..2d4a867d4 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -56,13 +56,37 @@ dump_hierarchy (hierarchy_t *h) for (uint32_t i = 0; i < h->num_objects; i++) { hierref_t *ref = Ent_GetComponent (h->ent[i], test_href, reg); char **name = Ent_GetComponent (h->ent[i], test_name, reg);; - printf ("%2d: %5s %2u %2u %2u %2u %2u\n", i, *name, h->ent[i], + printf ("%2d: %5s %2d %2d %2d %2d %2d\n", i, *name, h->ent[i], ref->index, h->parentIndex[i], h->childIndex[i], h->childCount[i]); } puts (""); } +static void +dump_tree (hierarchy_t *h, uint32_t ind, int level) +{ + if (ind >= h->num_objects) { + printf ("index %d out of bounds (%d)\n", ind, h->num_objects); + return; + } + ecs_registry_t *reg = h->reg; + char **name = Ent_GetComponent (h->ent[ind], test_name, reg);; + if (!level) { + puts ("in: en pa ci cc |name"); + } + printf ("%2d: %2d %2d %2d %2d |%*s%s\n", ind, h->ent[ind], + h->parentIndex[ind], h->childIndex[ind], h->childCount[ind], + level * 3, "", *name); + + for (uint32_t i = 0; i < h->childCount[ind]; i++) { + dump_tree (h, h->childIndex[ind] + i, level + 1); + } + if (!level) { + puts (""); + } +} + static int check_indices (uint32_t ent, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t childCount) @@ -458,6 +482,75 @@ test_build_hierarchy2 (void) return 0; } +static int +test_build_hierarchy3 (void) +{ + printf ("test_build_hierarchy3\n"); + + uint32_t root = create_ent (nullent, "root"); + uint32_t A = create_ent (root, "A"); + uint32_t B = create_ent (root, "B"); + uint32_t C = create_ent (root, "C"); + uint32_t B1 = create_ent (B, "B1"); + uint32_t A1 = create_ent (A, "A1"); + uint32_t A1a = create_ent (A1, "A1a"); + uint32_t B2 = create_ent (B, "B2"); + uint32_t A2 = create_ent (A, "A2"); + uint32_t B3 = create_ent (B, "B3"); + uint32_t B2a = create_ent (B2, "B2a"); + uint32_t D = create_ent (root, "D"); + uint32_t C1 = create_ent (C, "C1"); + + hierref_t *ref = Ent_GetComponent (root, test_href, test_reg); + dump_hierarchy (ref->hierarchy); + dump_tree (ref->hierarchy, 0, 0); + + if (!check_hierarchy_size (ref->hierarchy, 13)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; } + if (!check_indices ( B2, 8, 2, 12, 1)) { return 1; } + if (!check_indices ( B3, 9, 2, 13, 0)) { return 1; } + if (!check_indices ( C1, 10, 3, 13, 0)) { return 1; } + if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } + if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } + + set_parent (B2, nullent); + dump_hierarchy (ref->hierarchy); + dump_tree (ref->hierarchy, 0, 0); + hierref_t *B2ref = Ent_GetComponent (B2, test_href, test_reg); + dump_hierarchy (B2ref->hierarchy); + dump_tree (B2ref->hierarchy, 0, 0); + + if (!check_hierarchy_size (ref->hierarchy, 11)) { return 1; } + if (!check_hierarchy_size (B2ref->hierarchy, 2)) { return 1; } + + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } + if (!check_indices ( C, 3, 0, 9, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 10, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 10, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 11, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 11, 0)) { return 1; } + if (!check_indices ( B3, 8, 2, 11, 0)) { return 1; } + if (!check_indices ( C1, 9, 3, 11, 0)) { return 1; } + if (!check_indices (A1a, 10, 5, 11, 0)) { return 1; } + + if (!check_indices ( B2, 0, nullent, 1, 1)) { return 1; } + if (!check_indices (B2a, 1, 0, 2, 0)) { return 1; } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (ref->hierarchy); + + return 0; +} + int main (void) { @@ -470,6 +563,7 @@ main (void) if (test_parent_child_setparent ()) { return 1; } if (test_build_hierarchy ()) { return 1; } if (test_build_hierarchy2 ()) { return 1; } + if (test_build_hierarchy3 ()) { return 1; } ECS_DelRegistry (test_reg); From f89fbf97241545a64d048442c07aa1fb6a85b7c9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 5 Nov 2022 23:44:01 +0900 Subject: [PATCH 3149/3664] [ecs] Fix a child miscount in the test case Heh, that was a bit funny, actually, but it makes me wonder just how broken sub-hierarchy deletion was. --- libs/ecs/test/test-hierarchy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index 2d4a867d4..916006760 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -532,7 +532,7 @@ test_build_hierarchy3 (void) if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } - if (!check_indices ( B, 2, 0, 7, 3)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 2)) { return 1; } if (!check_indices ( C, 3, 0, 9, 1)) { return 1; } if (!check_indices ( D, 4, 0, 10, 0)) { return 1; } if (!check_indices ( A1, 5, 1, 10, 1)) { return 1; } From 01c67a345f74f9cd8ddd7432a90d0e776e7d0485 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 00:30:55 +0900 Subject: [PATCH 3150/3664] [ecs] Fix some more hierarchy tests Ugh, things were quite bad, it turns out. It seems a lot of trouble would have been saved if these tests had worked (however, something is still not quite right as views are out of place). --- libs/ecs/test/test-hierarchy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index 916006760..a1900eb46 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -458,10 +458,10 @@ test_build_hierarchy2 (void) if (!check_indices ( B1, 7, 2, 13, 0)) { return 1; } if (!check_indices ( B2, 8, 2, 13, 1)) { return 1; } if (!check_indices ( B3, 9, 2, 14, 0)) { return 1; } - if (!check_indices ( T, 10, 2, 14, 3)) { return 1; } - if (!check_indices ( C1, 11, 3, 17, 0)) { return 1; } - if (!check_indices (A1a, 12, 5, 17, 0)) { return 1; } - if (!check_indices (B2a, 13, 8, 17, 0)) { return 1; } + if (!check_indices ( T, 10, 2, 14, 2)) { return 1; } + if (!check_indices ( C1, 11, 3, 16, 0)) { return 1; } + if (!check_indices (A1a, 12, 5, 16, 0)) { return 1; } + if (!check_indices (B2a, 13, 8, 16, 0)) { return 1; } if (!check_indices ( X, 14, 10, 16, 2)) { return 1; } if (!check_indices ( Z, 15, 10, 18, 1)) { return 1; } if (!check_indices ( X1, 16, 14, 19, 1)) { return 1; } From b91568d23453c8fe931e3665bcd23c8d709d7338 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 02:38:59 +0900 Subject: [PATCH 3151/3664] [ecs] Improve the behavior of Hierarchy_RemoveHierarchy Its updates to the various indices were out, but this was missed due to the tests being wrong. I wonder if I got interrupted while working on them last and just assumed the removals were correct. This improves sbar's behavior, but it's still wrong when pulling the armory view out of the inventory. Very unsure what's going on, but the various indices look ok, as do the view positions. --- libs/ecs/hierarchy.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index dd35aed04..7d2057d4e 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -332,19 +332,18 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) { - uint32_t parentIndex = hierarchy->parentIndex[index]; uint32_t childIndex = hierarchy->childIndex[index]; - uint32_t siblingIndex = nullent; - if (parentIndex != nullent) { - siblingIndex = hierarchy->childIndex[parentIndex]; - } + uint32_t parentIndex = hierarchy->parentIndex[index]; + hierarchy_remove_children (hierarchy, index); hierarchy_close (hierarchy, index, 1); - if (siblingIndex != nullent) { - hierarchy_UpdateTransformIndices (hierarchy, index, -1); - hierarchy_UpdateChildIndices (hierarchy, siblingIndex, -1); - hierarchy_UpdateParentIndices (hierarchy, childIndex - 1, -1); + + hierarchy_UpdateTransformIndices (hierarchy, index, -1); + if (parentIndex != nullent) { + hierarchy_UpdateChildIndices (hierarchy, parentIndex + 1, -1); + hierarchy->childCount[parentIndex] -= 1; } + hierarchy_UpdateParentIndices (hierarchy, childIndex - 1, -1); } hierarchy_t * From d5de8bf53f4b91b9fe2056664f89c7f75a6c38ca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 03:08:50 +0900 Subject: [PATCH 3152/3664] [nq] Get hud_sbar working for the most part Setting the parent to another object in the same hierarchy still causes a segfault (worked around for now), but the mangled views were caused by View_UpdateHierarchy not being called prior to the first call to set_hud_sbar (why, though? I suspect something to do with oldlen). And ECS_SortComponentPool finally gets used to ensure the sbar panels are behind the info pics. --- nq/source/sbar.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index b92eb067e..a44a0fb0f 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1603,6 +1603,20 @@ sbar_hud_swap_f (void *data, const cvar_t *cvar) View_UpdateHierarchy (hud_view); } +static int +href_cmp (const void *_a, const void *_b, void *arg) +{ + uint32_t enta = *(const uint32_t *)_a; + uint32_t entb = *(const uint32_t *)_b; + hierref_t *ref_a = Ent_GetComponent (enta, hud_href, hud_registry); + hierref_t *ref_b = Ent_GetComponent (entb, hud_href, hud_registry); + if (ref_a->hierarchy == ref_b->hierarchy) { + return ref_a->index - ref_b->index; + } + ptrdiff_t diff = ref_a->hierarchy - ref_b->hierarchy; + return diff > 0 ? 1 : diff < 0 ? -1 : 0; +} + static void set_hud_sbar (void) { @@ -1690,6 +1704,7 @@ set_hud_sbar (void) sbar_remcomponent (sbar_inventory, hud_pic); sbar_remcomponent (sbar_statusbar, hud_pic); } + ECS_SortComponentPool (hud_registry, hud_pic, href_cmp, 0); } static void @@ -2240,6 +2255,7 @@ Sbar_Init (void) load_pics (); init_views (); + View_UpdateHierarchy (sbar_main); set_hud_sbar (); View_UpdateHierarchy (sbar_main); From 05947c8ac48f1808bfee4e2dfbc3cd0893c9b7da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 08:36:43 +0900 Subject: [PATCH 3153/3664] [ecs] Rework new hierarchy test for same-hierarchy Since test_build_hierarchy2 already tested removal of a sub-hierarchy (once fixed), it seems test_build_hierarchy3 testing parenting within the same hierarchy would be a good idea. Reparenting such that everything moves to later in the arrays works nicely (not very surprising). --- libs/ecs/test/test-hierarchy.c | 35 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index a1900eb46..5d7b31961 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -520,30 +520,25 @@ test_build_hierarchy3 (void) if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } - set_parent (B2, nullent); + set_parent (B2, C); dump_hierarchy (ref->hierarchy); dump_tree (ref->hierarchy, 0, 0); - hierref_t *B2ref = Ent_GetComponent (B2, test_href, test_reg); - dump_hierarchy (B2ref->hierarchy); - dump_tree (B2ref->hierarchy, 0, 0); - if (!check_hierarchy_size (ref->hierarchy, 11)) { return 1; } - if (!check_hierarchy_size (B2ref->hierarchy, 2)) { return 1; } + if (!check_hierarchy_size (ref->hierarchy, 13)) { return 1; } - if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } - if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } - if (!check_indices ( B, 2, 0, 7, 2)) { return 1; } - if (!check_indices ( C, 3, 0, 9, 1)) { return 1; } - if (!check_indices ( D, 4, 0, 10, 0)) { return 1; } - if (!check_indices ( A1, 5, 1, 10, 1)) { return 1; } - if (!check_indices ( A2, 6, 1, 11, 0)) { return 1; } - if (!check_indices ( B1, 7, 2, 11, 0)) { return 1; } - if (!check_indices ( B3, 8, 2, 11, 0)) { return 1; } - if (!check_indices ( C1, 9, 3, 11, 0)) { return 1; } - if (!check_indices (A1a, 10, 5, 11, 0)) { return 1; } - - if (!check_indices ( B2, 0, nullent, 1, 1)) { return 1; } - if (!check_indices (B2a, 1, 0, 2, 0)) { return 1; } + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 2)) { return 1; } + if (!check_indices ( C, 3, 0, 9, 2)) { return 1; } + if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; } + if (!check_indices ( B3, 8, 2, 12, 0)) { return 1; } + if (!check_indices ( C1, 9, 3, 12, 0)) { return 1; } + if (!check_indices ( B2, 10, 3, 12, 1)) { return 1; } + if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } + if (!check_indices (B2a, 12, 10, 13, 0)) { return 1; } // Delete the hierarchy directly as setparent isn't fully tested Hierarchy_Delete (ref->hierarchy); From ecf59c8141ab4921e1bd9dd928e01a8553b6da39 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 08:45:52 +0900 Subject: [PATCH 3154/3664] [ecs] Add failing same-hierarchy parenting test As expected, reparenting a sub-hierarchy such that it (and possibly its children) move up the arrays fails (this is why sbar needs to first remove the sub-hierarchy then insert it). --- libs/ecs/test/test-hierarchy.c | 123 +++++++++++++++++++++++++++------ 1 file changed, 101 insertions(+), 22 deletions(-) diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index 5d7b31961..d2b114e2d 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -53,12 +53,24 @@ static void dump_hierarchy (hierarchy_t *h) { ecs_registry_t *reg = h->reg; + puts ("in: ri pa ci cc en name"); for (uint32_t i = 0; i < h->num_objects; i++) { - hierref_t *ref = Ent_GetComponent (h->ent[i], test_href, reg); - char **name = Ent_GetComponent (h->ent[i], test_name, reg);; - printf ("%2d: %5s %2d %2d %2d %2d %2d\n", i, *name, h->ent[i], - ref->index, h->parentIndex[i], - h->childIndex[i], h->childCount[i]); + if (ECS_EntValid (h->ent[i], reg)) { + hierref_t *ref = Ent_GetComponent (h->ent[i], test_href, reg); + static char fake_name[] = "?"; + static char *fake_nameptr = fake_name; + char **name = &fake_nameptr; + if (Ent_HasComponent (h->ent[i], test_name, reg)) { + name = Ent_GetComponent (h->ent[i], test_name, reg); + } + printf ("%2d: %2d %2d %2d %2d %2d %s\n", i, + ref->index, h->parentIndex[i], + h->childIndex[i], h->childCount[i], h->ent[i], *name); + } else { + printf ("%2d: %2d %2d %2d %2d %2d %s\n", i, + -1, h->parentIndex[i], + h->childIndex[i], h->childCount[i], h->ent[i], "null"); + } } puts (""); } @@ -70,14 +82,20 @@ dump_tree (hierarchy_t *h, uint32_t ind, int level) printf ("index %d out of bounds (%d)\n", ind, h->num_objects); return; } - ecs_registry_t *reg = h->reg; - char **name = Ent_GetComponent (h->ent[ind], test_name, reg);; if (!level) { - puts ("in: en pa ci cc |name"); + puts ("in: pa ci cc en|name"); + } + ecs_registry_t *reg = h->reg; + if (ECS_EntValid (h->ent[ind], reg)) { + char **name = Ent_GetComponent (h->ent[ind], test_name, reg);; + printf ("%2d: %2d %2d %2d %2d|%*s%s\n", ind, + h->parentIndex[ind], h->childIndex[ind], h->childCount[ind], + h->ent[ind], level * 3, "", *name); + } else { + printf ("%2d: %2d %2d %2d %2d|%*s%s\n", ind, + h->parentIndex[ind], h->childIndex[ind], h->childCount[ind], + h->ent[ind], level * 3, "", "null"); } - printf ("%2d: %2d %2d %2d %2d |%*s%s\n", ind, h->ent[ind], - h->parentIndex[ind], h->childIndex[ind], h->childCount[ind], - level * 3, "", *name); for (uint32_t i = 0; i < h->childCount[ind]; i++) { dump_tree (h, h->childIndex[ind] + i, level + 1); @@ -520,7 +538,7 @@ test_build_hierarchy3 (void) if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; } - set_parent (B2, C); + set_parent (B2, C1); dump_hierarchy (ref->hierarchy); dump_tree (ref->hierarchy, 0, 0); @@ -529,16 +547,77 @@ test_build_hierarchy3 (void) if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } if (!check_indices ( B, 2, 0, 7, 2)) { return 1; } - if (!check_indices ( C, 3, 0, 9, 2)) { return 1; } - if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } - if (!check_indices ( A1, 5, 1, 11, 1)) { return 1; } - if (!check_indices ( A2, 6, 1, 12, 0)) { return 1; } - if (!check_indices ( B1, 7, 2, 12, 0)) { return 1; } - if (!check_indices ( B3, 8, 2, 12, 0)) { return 1; } - if (!check_indices ( C1, 9, 3, 12, 0)) { return 1; } - if (!check_indices ( B2, 10, 3, 12, 1)) { return 1; } - if (!check_indices (A1a, 11, 5, 13, 0)) { return 1; } - if (!check_indices (B2a, 12, 10, 13, 0)) { return 1; } + if (!check_indices ( C, 3, 0, 9, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 10, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 10, 1)) { return 1; } + if (!check_indices ( A2, 6, 1, 11, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 11, 0)) { return 1; } + if (!check_indices ( B3, 8, 2, 11, 0)) { return 1; } + if (!check_indices ( C1, 9, 3, 11, 1)) { return 1; } + if (!check_indices (A1a, 10, 5, 12, 0)) { return 1; } + if (!check_indices ( B2, 11, 9, 12, 1)) { return 1; } + if (!check_indices (B2a, 12, 11, 13, 0)) { return 1; } + + uint32_t A1b = create_ent (A1, "A1b"); + uint32_t A1c = create_ent (A1, "A1c"); + uint32_t B2a1 = create_ent (B2a, "B2a1"); + uint32_t B2a2 = create_ent (B2a, "B2a2"); + uint32_t B2b = create_ent (B2, "B2b"); + uint32_t B2b1 = create_ent (B2b, "B2b1"); + uint32_t B2b2 = create_ent (B2b, "B2b2"); + + dump_hierarchy (ref->hierarchy); + dump_tree (ref->hierarchy, 0, 0); + + if (!check_hierarchy_size (ref->hierarchy, 20)) { return 1; } + + if (!check_indices (root, 0, nullent, 1, 4)) { return 1; } + if (!check_indices ( A, 1, 0, 5, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 7, 2)) { return 1; } + if (!check_indices ( C, 3, 0, 9, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 10, 0)) { return 1; } + if (!check_indices ( A1, 5, 1, 10, 3)) { return 1; } + if (!check_indices ( A2, 6, 1, 13, 0)) { return 1; } + if (!check_indices ( B1, 7, 2, 13, 0)) { return 1; } + if (!check_indices ( B3, 8, 2, 13, 0)) { return 1; } + if (!check_indices ( C1, 9, 3, 13, 1)) { return 1; } + if (!check_indices (A1a, 10, 5, 14, 0)) { return 1; } + if (!check_indices (A1b, 11, 5, 14, 0)) { return 1; } + if (!check_indices (A1c, 12, 5, 14, 0)) { return 1; } + if (!check_indices ( B2, 13, 9, 14, 2)) { return 1; } + if (!check_indices (B2a, 14, 13, 16, 2)) { return 1; } + if (!check_indices (B2b, 15, 13, 18, 2)) { return 1; } + if (!check_indices (B2a1, 16, 14, 20, 0)) { return 1; } + if (!check_indices (B2a2, 17, 14, 20, 0)) { return 1; } + if (!check_indices (B2b1, 18, 15, 20, 0)) { return 1; } + if (!check_indices (B2b2, 19, 15, 20, 0)) { return 1; } + + set_parent (B2, root); + dump_hierarchy (ref->hierarchy); + dump_tree (ref->hierarchy, 0, 0); + + if (!check_hierarchy_size (ref->hierarchy, 20)) { return 1; } + + if (!check_indices (root, 0, nullent, 1, 5)) { return 1; } + if (!check_indices ( A, 1, 0, 6, 2)) { return 1; } + if (!check_indices ( B, 2, 0, 8, 2)) { return 1; } + if (!check_indices ( C, 3, 0, 10, 1)) { return 1; } + if (!check_indices ( D, 4, 0, 11, 0)) { return 1; } + if (!check_indices ( B2, 5, 0, 11, 2)) { return 1; } + if (!check_indices ( A1, 6, 1, 13, 3)) { return 1; } + if (!check_indices ( A2, 7, 1, 16, 0)) { return 1; } + if (!check_indices ( B1, 8, 2, 16, 0)) { return 1; } + if (!check_indices ( B3, 9, 2, 16, 0)) { return 1; } + if (!check_indices ( C1, 10, 3, 16, 0)) { return 1; } + if (!check_indices (B2a, 11, 5, 16, 2)) { return 1; } + if (!check_indices (B2b, 12, 5, 18, 2)) { return 1; } + if (!check_indices (A1a, 13, 6, 20, 0)) { return 1; } + if (!check_indices (A1b, 14, 6, 20, 0)) { return 1; } + if (!check_indices (A1c, 15, 6, 20, 0)) { return 1; } + if (!check_indices (B2a1, 16, 11, 20, 0)) { return 1; } + if (!check_indices (B2a2, 17, 11, 20, 0)) { return 1; } + if (!check_indices (B2b1, 18, 12, 20, 0)) { return 1; } + if (!check_indices (B2b2, 19, 12, 20, 0)) { return 1; } // Delete the hierarchy directly as setparent isn't fully tested Hierarchy_Delete (ref->hierarchy); From 97a6ce833efb0a2d8c6a54b8ccd5a5d44b1a14b1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 17:36:49 +0900 Subject: [PATCH 3155/3664] [ecs] Adjust the source root during self insertions This improves the behavior of hierarchies when self-inserting, but nq's sbar still crashes when trying to do so. However, its tree is a fair bit more complex than the test case (that does pass now), so I need to try to replicate the important parts of the tree with fewer objects (180 is too many to work with). --- libs/ecs/hierarchy.c | 50 ++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 7d2057d4e..6061b6dcf 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -170,10 +170,12 @@ hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, memset (&src->ent[srcIndex], nullent, count * sizeof(dst->ent[0])); for (uint32_t i = 0; i < count; i++) { - uint32_t ent = dst->ent[dstIndex + i]; - hierref_t *ref = Ent_GetComponent (ent, href, reg); - ref->hierarchy = dst; - ref->index = dstIndex + i; + if (dst->ent[dstIndex + i] != nullent) { + uint32_t ent = dst->ent[dstIndex + i]; + hierref_t *ref = Ent_GetComponent (ent, href, reg); + ref->hierarchy = dst; + ref->index = dstIndex + i; + } } if (dst->type) { for (uint32_t i = 0; i < dst->type->num_components; i++) { @@ -205,7 +207,7 @@ hierarchy_init (hierarchy_t *dst, uint32_t index, static uint32_t hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, - uint32_t dstParent, uint32_t srcRoot, uint32_t count) + uint32_t dstParent, uint32_t *srcRoot, uint32_t count) { uint32_t insertIndex; // where the objects will be inserted uint32_t childIndex; // where the objects' children will inserted @@ -237,8 +239,11 @@ hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, childIndex += count; hierarchy_open (dst, insertIndex, count); + if (dst == src && insertIndex <= *srcRoot) { + *srcRoot += count; + } if (src) { - hierarchy_move (dst, src, insertIndex, srcRoot, count); + hierarchy_move (dst, src, insertIndex, *srcRoot, count); } else { hierarchy_init (dst, insertIndex, dstParent, childIndex, count); } @@ -254,25 +259,27 @@ hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, static void hierarchy_insert_children (hierarchy_t *dst, const hierarchy_t *src, - uint32_t dstParent, uint32_t srcRoot) + uint32_t dstParent, uint32_t *srcRoot) { uint32_t insertIndex; - uint32_t childIndex = src->childIndex[srcRoot]; - uint32_t childCount = src->childCount[srcRoot]; + uint32_t childIndex = src->childIndex[*srcRoot]; + uint32_t childCount = src->childCount[*srcRoot]; if (childCount) { insertIndex = hierarchy_insert (dst, src, dstParent, - childIndex, childCount); - for (uint32_t i = 0; i < childCount; i++) { - hierarchy_insert_children (dst, src, insertIndex + i, - childIndex + i); + &childIndex, childCount); + if (dst == src && insertIndex <= *srcRoot) { + *srcRoot += childCount; + } + for (uint32_t i = 0; i < childCount; i++, childIndex++) { + hierarchy_insert_children (dst, src, insertIndex + i, &childIndex); } } } -uint32_t -Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, - uint32_t dstParent, uint32_t srcRoot) +static uint32_t +hierarchy_insertHierarchy (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstParent, uint32_t *srcRoot) { uint32_t insertIndex; @@ -282,7 +289,7 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, } hierarchy_open (dst, 0, 1); if (src) { - hierarchy_move (dst, src, 0, srcRoot, 1); + hierarchy_move (dst, src, 0, *srcRoot, 1); } dst->parentIndex[0] = nullent; dst->childIndex[0] = 1; @@ -301,6 +308,13 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, return insertIndex; } +uint32_t +Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, + uint32_t dstParent, uint32_t srcRoot) +{ + return hierarchy_insertHierarchy (dst, src, dstParent, &srcRoot); +} + static void hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) { @@ -437,7 +451,7 @@ Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, dst = Hierarchy_New (src->reg, src->type, 0); } r.hierarchy = dst; - r.index = Hierarchy_InsertHierarchy (dst, src, dstParent, srcRoot); + r.index = hierarchy_insertHierarchy (dst, src, dstParent, &srcRoot); Hierarchy_RemoveHierarchy (src, srcRoot); if (!src->num_objects) { Hierarchy_Delete (src); From cf6b4efe5d4f647eb85d1c374ad5424c51082b85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 20:03:29 +0900 Subject: [PATCH 3156/3664] [ecs] Colorize hierarchy test output Just the tiniest bit of color goes a long way to spotting issues. --- libs/ecs/test/test-hierarchy.c | 116 +++++++++++++++++++++++++++------ 1 file changed, 95 insertions(+), 21 deletions(-) diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index d2b114e2d..292eda235 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -30,6 +30,16 @@ static const component_t test_components[] = { ecs_registry_t *test_reg; +#define DFL "\e[39;49m" +#define BLK "\e[30;40m" +#define RED "\e[31;40m" +#define GRN "\e[32;40m" +#define ONG "\e[33;40m" +#define BLU "\e[34;40m" +#define MAG "\e[35;40m" +#define CYN "\e[36;40m" +#define WHT "\e[37;40m" + static int check_hierarchy_size (hierarchy_t *h, uint32_t size) { @@ -49,28 +59,84 @@ check_hierarchy_size (hierarchy_t *h, uint32_t size) return 1; } +static const char * +ref_index_color (uint32_t i, uint32_t rind) +{ + return rind != i ? RED : DFL; +} + +static const char * +parent_index_color (hierarchy_t *h, uint32_t i) +{ + if (!i && h->parentIndex[i] == nullent) { + return GRN; + } + if (h->parentIndex[i] >= i) { + return RED; + } + uint32_t ci = h->childIndex[h->parentIndex[i]]; + uint32_t cc = h->childCount[h->parentIndex[i]]; + if (i < ci || i >= ci + cc) { + return ONG; + } + return DFL; +} + +static const char * +child_index_color (hierarchy_t *h, uint32_t i) +{ + if (h->childIndex[i] > h->num_objects + || h->childCount[i] > h->num_objects + || h->childIndex[i] + h->childCount[i] > h->num_objects) { + return RED; + } + if (h->childIndex[i] <= i) { + return ONG; + } + return DFL; +} + +static const char * +child_count_color (hierarchy_t *h, uint32_t i) +{ + if (h->childIndex[i] > h->num_objects + || h->childCount[i] > h->num_objects + || h->childIndex[i] + h->childCount[i] > h->num_objects) { + return RED; + } + return DFL; +} + +static const char * +entity_color (hierarchy_t *h, uint32_t i) +{ + return h->ent[i] == nullent ? MAG : DFL; +} + static void dump_hierarchy (hierarchy_t *h) { ecs_registry_t *reg = h->reg; puts ("in: ri pa ci cc en name"); for (uint32_t i = 0; i < h->num_objects; i++) { + uint32_t rind = nullent; + static char fake_name[] = ONG "null" DFL; + static char *fake_nameptr = fake_name; + char **name = &fake_nameptr; if (ECS_EntValid (h->ent[i], reg)) { hierref_t *ref = Ent_GetComponent (h->ent[i], test_href, reg); - static char fake_name[] = "?"; - static char *fake_nameptr = fake_name; - char **name = &fake_nameptr; + rind = ref->index; if (Ent_HasComponent (h->ent[i], test_name, reg)) { name = Ent_GetComponent (h->ent[i], test_name, reg); } - printf ("%2d: %2d %2d %2d %2d %2d %s\n", i, - ref->index, h->parentIndex[i], - h->childIndex[i], h->childCount[i], h->ent[i], *name); - } else { - printf ("%2d: %2d %2d %2d %2d %2d %s\n", i, - -1, h->parentIndex[i], - h->childIndex[i], h->childCount[i], h->ent[i], "null"); } + printf ("%2d: %s%2d %s%2d %s%2d %s%2d %s%2d"DFL" %s\n", i, + ref_index_color (i, rind), rind, + parent_index_color (h, i), h->parentIndex[i], + child_index_color (h, i), h->childIndex[i], + child_count_color (h, i), h->childCount[i], + entity_color (h, i), h->ent[i], + *name); } puts (""); } @@ -85,20 +151,28 @@ dump_tree (hierarchy_t *h, uint32_t ind, int level) if (!level) { puts ("in: pa ci cc en|name"); } + static char fake_name[] = ONG "null" DFL; + static char *fake_nameptr = fake_name; + char **name = &fake_nameptr; ecs_registry_t *reg = h->reg; - if (ECS_EntValid (h->ent[ind], reg)) { - char **name = Ent_GetComponent (h->ent[ind], test_name, reg);; - printf ("%2d: %2d %2d %2d %2d|%*s%s\n", ind, - h->parentIndex[ind], h->childIndex[ind], h->childCount[ind], - h->ent[ind], level * 3, "", *name); - } else { - printf ("%2d: %2d %2d %2d %2d|%*s%s\n", ind, - h->parentIndex[ind], h->childIndex[ind], h->childCount[ind], - h->ent[ind], level * 3, "", "null"); + if (ECS_EntValid (h->ent[ind], reg) + && Ent_HasComponent (h->ent[ind], test_name, reg)) { + name = Ent_GetComponent (h->ent[ind], test_name, reg);; } + printf ("%2d: %s%2d %s%2d %s%2d %s%2d"DFL"|%*s%s\n", ind, + parent_index_color (h, ind), h->parentIndex[ind], + child_index_color (h, ind), h->childIndex[ind], + child_count_color (h, ind), h->childCount[ind], + entity_color (h, ind), h->ent[ind], + level * 3, "", *name); - for (uint32_t i = 0; i < h->childCount[ind]; i++) { - dump_tree (h, h->childIndex[ind] + i, level + 1); + if (h->childIndex[ind] > ind) { + for (uint32_t i = 0; i < h->childCount[ind]; i++) { + if (h->childIndex[ind] + i >= h->num_objects) { + break; + } + dump_tree (h, h->childIndex[ind] + i, level + 1); + } } if (!level) { puts (""); From 1130919049d19d34020394cbc06a89a8461a4e07 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 20:04:34 +0900 Subject: [PATCH 3157/3664] [ecs] Add a simplified test of the sbar hierarchy Even 37 objects is a lot, but it's a whole lot better than 180. Most importantly, it reproduces the problem, which seems to be not all parent indices getting updated. The child indices seem to be working nice, as do the reference object indices (ie, the entity components). I suspect its the parent indices getting corrupted that cause problems on the second switch of the hud/sbar cvar as the parent indices are used to find the child indices that need to be updated. --- libs/ecs/test/test-hierarchy.c | 136 +++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index 292eda235..3c612c16a 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -699,6 +699,141 @@ test_build_hierarchy3 (void) return 0; } +static int +test_build_hierarchy4 (void) +{ + printf ("test_build_hierarchy4\n"); + + uint32_t hud = create_ent (nullent, "hud"); + uint32_t mt = create_ent (hud, "mt"); + uint32_t mt_b = create_ent (mt, "mt_b"); + uint32_t mt_b3 = create_ent (mt_b, "mt_b3"); + uint32_t main = create_ent (hud, "main"); + uint32_t main_mf = create_ent (main, "main_mf"); + uint32_t main_mf_b = create_ent (main_mf, "main_mf_b"); + uint32_t main_mf_b7 = create_ent (main_mf_b, "main_mf_b7"); + uint32_t main_i = create_ent (main, "main_i"); + uint32_t main_i_f = create_ent (main_i, "main_i_f"); + uint32_t main_i_f_b = create_ent (main_i_f, "main_i_f_b"); + uint32_t main_i_f_b4 = create_ent (main_i_f_b, "main_i_f_b4"); + uint32_t main_i_s = create_ent (main_i, "main_i_s"); + uint32_t main_i_s4 = create_ent (main_i_s, "main_i_s4"); + uint32_t main_i_i = create_ent (main_i, "main_i_i"); + uint32_t main_i_i4 = create_ent (main_i_i, "main_i_i4"); + uint32_t main_i_a = create_ent (main_i, "main_i_a"); + uint32_t main_i_a_w = create_ent (main_i_a, "main_i_a_w"); + uint32_t main_i_a_w4 = create_ent (main_i_a_w, "main_i_a_w4"); + uint32_t main_i_a_ma = create_ent (main_i_a, "main_i_a_ma"); + uint32_t main_i_a_ma4 = create_ent (main_i_a_ma, "main_i_a_ma4"); + uint32_t main_sb = create_ent (main, "main_sb"); + uint32_t main_sb_a = create_ent (main_sb, "main_sb_a"); + uint32_t main_sb_a4 = create_ent (main_sb_a, "main_sb_a4"); + uint32_t main_sb_f = create_ent (main_sb, "main_sb_f"); + uint32_t main_sb_h = create_ent (main_sb, "main_sb_h"); + uint32_t main_sb_h3 = create_ent (main_sb_h, "main_sb_h3"); + uint32_t main_sb_A = create_ent (main_sb, "main_sb_A"); + uint32_t main_sb_A4 = create_ent (main_sb_A, "main_sb_A4"); + uint32_t main_t0 = create_ent (main, "main_t0"); + uint32_t main_t1 = create_ent (main, "main_t1"); + uint32_t main_S = create_ent (main, "main_S"); + uint32_t main_S_m = create_ent (main_S, "main_S_m"); + uint32_t main_S_s = create_ent (main_S, "main_S_s"); + uint32_t main_S_t = create_ent (main_S, "main_S_t"); + uint32_t main_S_a = create_ent (main_S, "main_S_a"); + uint32_t main_S_a_n = create_ent (main_S_a, "main_S_a_n"); + + hierref_t *ref = Ent_GetComponent (hud, test_href, test_reg); + dump_hierarchy (ref->hierarchy); + dump_tree (ref->hierarchy, 0, 0); + + if (!check_hierarchy_size (ref->hierarchy, 37)) { return 1; } + + if (!check_indices (hud, 0, nullent, 1, 2)) { return 1; } + if (!check_indices (mt, 1, 0, 3, 1)) { return 1; } + if (!check_indices (main, 2, 0, 4, 6)) { return 1; } + if (!check_indices (mt_b, 3, 1, 10, 1)) { return 1; } + if (!check_indices (main_mf, 4, 2, 11, 1)) { return 1; } + if (!check_indices (main_i, 5, 2, 12, 4)) { return 1; } + if (!check_indices (main_sb, 6, 2, 16, 4)) { return 1; } + if (!check_indices (main_t0, 7, 2, 20, 0)) { return 1; } + if (!check_indices (main_t1, 8, 2, 20, 0)) { return 1; } + if (!check_indices (main_S, 9, 2, 20, 4)) { return 1; } + if (!check_indices (mt_b3, 10, 3, 24, 0)) { return 1; } + if (!check_indices (main_mf_b, 11, 4, 24, 1)) { return 1; } + if (!check_indices (main_i_f, 12, 5, 25, 1)) { return 1; } + if (!check_indices (main_i_s, 13, 5, 26, 1)) { return 1; } + if (!check_indices (main_i_i, 14, 5, 27, 1)) { return 1; } + if (!check_indices (main_i_a, 15, 5, 28, 2)) { return 1; } + if (!check_indices (main_sb_a, 16, 6, 30, 1)) { return 1; } + if (!check_indices (main_sb_f, 17, 6, 31, 0)) { return 1; } + if (!check_indices (main_sb_h, 18, 6, 31, 1)) { return 1; } + if (!check_indices (main_sb_A, 19, 6, 32, 1)) { return 1; } + if (!check_indices (main_S_m, 20, 9, 33, 0)) { return 1; } + if (!check_indices (main_S_s, 21, 9, 33, 0)) { return 1; } + if (!check_indices (main_S_t, 22, 9, 33, 0)) { return 1; } + if (!check_indices (main_S_a, 23, 9, 33, 1)) { return 1; } + if (!check_indices (main_mf_b7, 24, 11, 34, 0)) { return 1; } + if (!check_indices (main_i_f_b, 25, 12, 34, 1)) { return 1; } + if (!check_indices (main_i_s4, 26, 13, 35, 0)) { return 1; } + if (!check_indices (main_i_i4, 27, 14, 35, 0)) { return 1; } + if (!check_indices (main_i_a_w, 28, 15, 35, 1)) { return 1; } + if (!check_indices (main_i_a_ma, 29, 15, 36, 1)) { return 1; } + if (!check_indices (main_sb_a4, 30, 16, 37, 0)) { return 1; } + if (!check_indices (main_sb_h3, 31, 18, 37, 0)) { return 1; } + if (!check_indices (main_sb_A4, 32, 19, 37, 0)) { return 1; } + if (!check_indices (main_S_a_n, 33, 23, 37, 0)) { return 1; } + if (!check_indices (main_i_f_b4, 34, 25, 37, 0)) { return 1; } + if (!check_indices (main_i_a_w4, 35, 28, 37, 0)) { return 1; } + if (!check_indices (main_i_a_ma4, 36, 29, 37, 0)) { return 1; } + + set_parent (main_i_a, hud); + dump_hierarchy (ref->hierarchy); + dump_tree (ref->hierarchy, 0, 0); + + if (!check_indices (hud, 0, nullent, 1, 3)) { return 1; } + if (!check_indices (mt, 1, 0, 4, 1)) { return 1; } + if (!check_indices (main, 2, 0, 5, 6)) { return 1; } + if (!check_indices (main_i_a, 3, 0, 11, 2)) { return 1; } + if (!check_indices (mt_b, 4, 1, 13, 1)) { return 1; } + if (!check_indices (main_mf, 5, 2, 14, 1)) { return 1; } + if (!check_indices (main_i, 6, 2, 15, 3)) { return 1; } + if (!check_indices (main_sb, 7, 2, 18, 4)) { return 1; } + if (!check_indices (main_t0, 8, 2, 22, 0)) { return 1; } + if (!check_indices (main_t1, 9, 2, 22, 0)) { return 1; } + if (!check_indices (main_S, 10, 2, 22, 4)) { return 1; } + if (!check_indices (main_i_a_w, 11, 3, 26, 1)) { return 1; } + if (!check_indices (main_i_a_ma, 12, 3, 27, 1)) { return 1; } + if (!check_indices (mt_b3, 13, 4, 28, 0)) { return 1; } + if (!check_indices (main_mf_b, 14, 5, 28, 1)) { return 1; } + if (!check_indices (main_i_f, 15, 6, 29, 1)) { return 1; } + if (!check_indices (main_i_s, 16, 6, 30, 1)) { return 1; } + if (!check_indices (main_i_i, 17, 6, 31, 1)) { return 1; } + if (!check_indices (main_sb_a, 18, 7, 32, 1)) { return 1; } + if (!check_indices (main_sb_f, 19, 7, 33, 0)) { return 1; } + if (!check_indices (main_sb_h, 20, 7, 33, 1)) { return 1; } + if (!check_indices (main_sb_A, 21, 7, 34, 1)) { return 1; } + if (!check_indices (main_S_m, 22, 10, 35, 0)) { return 1; } + if (!check_indices (main_S_s, 23, 10, 35, 0)) { return 1; } + if (!check_indices (main_S_t, 24, 10, 35, 0)) { return 1; } + if (!check_indices (main_S_a, 25, 10, 35, 1)) { return 1; } + if (!check_indices (main_i_a_w4, 26, 11, 36, 0)) { return 1; } + if (!check_indices (main_i_a_ma4, 27, 12, 36, 0)) { return 1; } + if (!check_indices (main_mf_b7, 28, 14, 36, 0)) { return 1; } + if (!check_indices (main_i_f_b, 29, 15, 36, 1)) { return 1; } + if (!check_indices (main_i_s4, 30, 16, 37, 0)) { return 1; } + if (!check_indices (main_i_i4, 31, 17, 37, 0)) { return 1; } + if (!check_indices (main_sb_a4, 32, 18, 37, 0)) { return 1; } + if (!check_indices (main_sb_h3, 33, 20, 37, 0)) { return 1; } + if (!check_indices (main_sb_A4, 34, 21, 37, 0)) { return 1; } + if (!check_indices (main_S_a_n, 35, 25, 37, 0)) { return 1; } + if (!check_indices (main_i_f_b4, 36, 29, 37, 0)) { return 1; } + + // Delete the hierarchy directly as setparent isn't fully tested + Hierarchy_Delete (ref->hierarchy); + + return 0; +} + int main (void) { @@ -712,6 +847,7 @@ main (void) if (test_build_hierarchy ()) { return 1; } if (test_build_hierarchy2 ()) { return 1; } if (test_build_hierarchy3 ()) { return 1; } + if (test_build_hierarchy4 ()) { return 1; } ECS_DelRegistry (test_reg); From 5ce0f4735cd6b960c8bfbe7f2d40ade218d5b106 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 20:11:45 +0900 Subject: [PATCH 3158/3664] [nq] Correct the number of children for the health view It needs only 3 as the face has its own view. --- nq/source/sbar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index a44a0fb0f..eb6b05924 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -195,7 +195,7 @@ static view_def_t sbar_defs[] = { {0, { 0, 0, 24, 24}, grav_northwest, &sbar_ammo, 4, 24, 0}, {0, { 0, 0, 16, 16}, grav_northwest, &sbar_items, 6, 16, 0}, {0, { 0, 0, 24, 16}, grav_northwest, &sbar_weapons, 7, 24, 0}, - {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 4, 24, 0}, + {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 3, 24, 0}, {0, {10, 0, 24, 8}, grav_northwest, &sbar_miniammo, 4, 48, 0}, {} From ddd6c958a9f6aa44ce873b96737bb1010853c100 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 23:04:40 +0900 Subject: [PATCH 3159/3664] [ecs] Fix parent index updates when removing sub-hierarchies In the end, it was removal of the old entries that corrupted the parent indices. Very nicely, most of the fixes involved removing code. Taking advantage of the ECS to debug the hierarchies was fun, and the resulting colorized entity names helped no end. --- libs/ecs/hierarchy.c | 16 ++------- libs/ecs/test/test-hierarchy.c | 61 ++++++++++++++++++++++++++++++---- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 6061b6dcf..024c0700a 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -320,14 +320,7 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) { uint32_t childIndex = hierarchy->childIndex[index]; uint32_t childCount = hierarchy->childCount[index]; - uint32_t parentIndex = hierarchy->parentIndex[index]; - uint32_t nieceIndex = nullent; - if (parentIndex != nullent) { - uint32_t siblingIndex = hierarchy->childIndex[parentIndex]; - siblingIndex += hierarchy->childCount[parentIndex] - 1; - nieceIndex = hierarchy->childIndex[siblingIndex]; - } for (uint32_t i = childCount; i-- > 0; ) { hierarchy_remove_children (hierarchy, childIndex + i); } @@ -337,16 +330,15 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) if (childCount) { hierarchy_UpdateTransformIndices (hierarchy, childIndex, -childCount); hierarchy_UpdateChildIndices (hierarchy, index, -childCount); - if (nieceIndex != nullent) { - hierarchy_UpdateParentIndices (hierarchy, nieceIndex, -childCount); - } + } + if (childIndex < hierarchy->num_objects) { + hierarchy_UpdateParentIndices (hierarchy, childIndex, -1); } } void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) { - uint32_t childIndex = hierarchy->childIndex[index]; uint32_t parentIndex = hierarchy->parentIndex[index]; hierarchy_remove_children (hierarchy, index); @@ -357,7 +349,6 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) hierarchy_UpdateChildIndices (hierarchy, parentIndex + 1, -1); hierarchy->childCount[parentIndex] -= 1; } - hierarchy_UpdateParentIndices (hierarchy, childIndex - 1, -1); } hierarchy_t * @@ -404,7 +395,6 @@ hierarchy_t * Hierarchy_Copy (ecs_registry_t *dstReg, const hierarchy_t *src) { uint32_t href = dstReg->href_comp; - //ecs_registry_t *srcReg = src->reg; hierarchy_t *dst = Hierarchy_New (dstReg, src->type, 0); size_t count = src->num_objects; diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index 3c612c16a..4ede04af2 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -12,6 +12,7 @@ enum { test_href, test_name, + test_highlight, test_num_components }; @@ -26,6 +27,10 @@ static const component_t test_components[] = { .size = sizeof (const char *), .name = "name", }, + [test_highlight] = { + .size = sizeof (byte), + .name = "highlight", + }, }; ecs_registry_t *test_reg; @@ -113,6 +118,25 @@ entity_color (hierarchy_t *h, uint32_t i) return h->ent[i] == nullent ? MAG : DFL; } +static const char * +highlight_color (hierarchy_t *h, uint32_t i) +{ + uint32_t ent = h->ent[i]; + if (ECS_EntValid (ent, test_reg) + && Ent_HasComponent (ent, test_highlight, test_reg)) { + static char color_str[] = "\e[3.;4.m"; + byte *color = Ent_GetComponent (ent, test_highlight, test_reg); + if (*color) { + byte fg = *color & 0x0f; + byte bg = *color >> 4; + color_str[3] = fg < 8 ? '0' + fg : '9'; + color_str[6] = bg < 8 ? '0' + bg : '9'; + return color_str; + } + } + return ""; +} + static void dump_hierarchy (hierarchy_t *h) { @@ -130,13 +154,13 @@ dump_hierarchy (hierarchy_t *h) name = Ent_GetComponent (h->ent[i], test_name, reg); } } - printf ("%2d: %s%2d %s%2d %s%2d %s%2d %s%2d"DFL" %s\n", i, + printf ("%2d: %s%2d %s%2d %s%2d %s%2d %s%2d"DFL" %s%s"DFL"\n", i, ref_index_color (i, rind), rind, parent_index_color (h, i), h->parentIndex[i], child_index_color (h, i), h->childIndex[i], child_count_color (h, i), h->childCount[i], entity_color (h, i), h->ent[i], - *name); + highlight_color (h, i), *name); } puts (""); } @@ -159,12 +183,12 @@ dump_tree (hierarchy_t *h, uint32_t ind, int level) && Ent_HasComponent (h->ent[ind], test_name, reg)) { name = Ent_GetComponent (h->ent[ind], test_name, reg);; } - printf ("%2d: %s%2d %s%2d %s%2d %s%2d"DFL"|%*s%s\n", ind, + printf ("%2d: %s%2d %s%2d %s%2d %s%2d"DFL"|%*s%s%s"DFL"\n", ind, parent_index_color (h, ind), h->parentIndex[ind], child_index_color (h, ind), h->childIndex[ind], child_count_color (h, ind), h->childCount[ind], entity_color (h, ind), h->ent[ind], - level * 3, "", *name); + level * 3, "", highlight_color (h, ind), *name); if (h->childIndex[ind] > ind) { for (uint32_t i = 0; i < h->childCount[ind]; i++) { @@ -232,6 +256,12 @@ create_ent (uint32_t parent, const char *name) return ent; } +static void +highlight_ent (uint32_t ent, byte color) +{ + Ent_SetComponent (ent, test_highlight, test_reg, &color); +} + static void set_parent (uint32_t child, uint32_t parent) { @@ -722,7 +752,7 @@ test_build_hierarchy4 (void) uint32_t main_i_i4 = create_ent (main_i_i, "main_i_i4"); uint32_t main_i_a = create_ent (main_i, "main_i_a"); uint32_t main_i_a_w = create_ent (main_i_a, "main_i_a_w"); - uint32_t main_i_a_w4 = create_ent (main_i_a_w, "main_i_a_w4"); + uint32_t main_i_a_w7 = create_ent (main_i_a_w, "main_i_a_w7"); uint32_t main_i_a_ma = create_ent (main_i_a, "main_i_a_ma"); uint32_t main_i_a_ma4 = create_ent (main_i_a_ma, "main_i_a_ma4"); uint32_t main_sb = create_ent (main, "main_sb"); @@ -742,6 +772,23 @@ test_build_hierarchy4 (void) uint32_t main_S_a = create_ent (main_S, "main_S_a"); uint32_t main_S_a_n = create_ent (main_S_a, "main_S_a_n"); + highlight_ent (main_i_a, 0x06); + highlight_ent (main_i_a_w, 0x05); + highlight_ent (main_i_a_ma, 0x05); + highlight_ent (main_i_a_w7, 0x02); + highlight_ent (main_i_a_ma4, 0x02); + + highlight_ent (main_sb_a, 0x03); + highlight_ent (main_sb_h, 0x03); + highlight_ent (main_sb_A, 0x03); + highlight_ent (main_S_a, 0x03); + highlight_ent (main_i_f_b, 0x03); + highlight_ent (main_sb_a4, 0x01); + highlight_ent (main_sb_h3, 0x01); + highlight_ent (main_sb_A4, 0x01); + highlight_ent (main_S_a_n, 0x01); + highlight_ent (main_i_f_b4, 0x01); + hierref_t *ref = Ent_GetComponent (hud, test_href, test_reg); dump_hierarchy (ref->hierarchy); dump_tree (ref->hierarchy, 0, 0); @@ -783,7 +830,7 @@ test_build_hierarchy4 (void) if (!check_indices (main_sb_A4, 32, 19, 37, 0)) { return 1; } if (!check_indices (main_S_a_n, 33, 23, 37, 0)) { return 1; } if (!check_indices (main_i_f_b4, 34, 25, 37, 0)) { return 1; } - if (!check_indices (main_i_a_w4, 35, 28, 37, 0)) { return 1; } + if (!check_indices (main_i_a_w7, 35, 28, 37, 0)) { return 1; } if (!check_indices (main_i_a_ma4, 36, 29, 37, 0)) { return 1; } set_parent (main_i_a, hud); @@ -816,7 +863,7 @@ test_build_hierarchy4 (void) if (!check_indices (main_S_s, 23, 10, 35, 0)) { return 1; } if (!check_indices (main_S_t, 24, 10, 35, 0)) { return 1; } if (!check_indices (main_S_a, 25, 10, 35, 1)) { return 1; } - if (!check_indices (main_i_a_w4, 26, 11, 36, 0)) { return 1; } + if (!check_indices (main_i_a_w7, 26, 11, 36, 0)) { return 1; } if (!check_indices (main_i_a_ma4, 27, 12, 36, 0)) { return 1; } if (!check_indices (main_mf_b7, 28, 14, 36, 0)) { return 1; } if (!check_indices (main_i_f_b, 29, 15, 36, 1)) { return 1; } From 4dccad656f52d372126843f24214531e26f940a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 6 Nov 2022 23:18:32 +0900 Subject: [PATCH 3160/3664] [nq] Remove the workarounds for same-hierarchy parenting With the hierarchy code fixed for intra-hierarchy parenting, there's no longer any need to first pull the sub-hierarchy out of the main hierarchy before changing the parent, resulting in less memory churn. --- nq/source/sbar.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index eb6b05924..7ebafcd91 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -1623,7 +1623,6 @@ set_hud_sbar (void) view_t v; if (hud_sbar) { - View_SetParent (sbar_armament, nullview);//FIXME workaround for same-h View_SetParent (sbar_armament, sbar_inventory); View_SetPos (sbar_armament, 0, 0); View_SetLen (sbar_armament, 202, 24); @@ -1663,7 +1662,6 @@ set_hud_sbar (void) sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar); sbar_setcomponent (sbar_statusbar, hud_pic, &sb_sbar); } else { - View_SetParent (sbar_armament, nullview);//FIXME workaround for same-h View_SetParent (sbar_armament, hud_view); View_SetPos (sbar_armament, 0, 48); View_SetLen (sbar_armament, 42, 156); From 4197d4a80032a735dc43c45a7c175d3d7e964272 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 7 Nov 2022 10:36:56 +0900 Subject: [PATCH 3161/3664] [nq] Propagate demoplayback over CL_ClearMemory Because demoplayback seen by the shared client code is in viewstate and that's in cl, it gets set to 0 when connecting, thus the network icon while playing demos. --- nq/source/cl_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index b6403481a..4ee56a8a6 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -233,6 +233,7 @@ CL_ClearMemory (void) memset (&cl, 0, sizeof (cl)); Sbar_Intermission (cl.intermission = 0); cl.viewstate.camera_transform = cam; + cl.viewstate.demoplayback = cls.demoplayback; CL_ClearTEnts (); From 24d8d864a2a21a85aeffe74147581aa5561e775d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Nov 2022 00:16:29 +0900 Subject: [PATCH 3162/3664] [ecs] Optionally delete entities on hierarchy removal Useful for deleting an entire sub-hierarchy of entities. --- include/QF/ecs/hierarchy.h | 3 ++- libs/ecs/hierarchy.c | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/include/QF/ecs/hierarchy.h b/include/QF/ecs/hierarchy.h index 5a8056617..fa5f4ef8d 100644 --- a/include/QF/ecs/hierarchy.h +++ b/include/QF/ecs/hierarchy.h @@ -71,7 +71,8 @@ void Hierarchy_Delete (hierarchy_t *hierarchy); uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstParent, uint32_t srcRoot); -void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); +void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index, + int delEntities); hierref_t Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, hierarchy_t *src, uint32_t srcIndex); diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 024c0700a..3cbaeec18 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -316,13 +316,19 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, } static void -hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) +hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index, + int delEntities) { uint32_t childIndex = hierarchy->childIndex[index]; uint32_t childCount = hierarchy->childCount[index]; for (uint32_t i = childCount; i-- > 0; ) { - hierarchy_remove_children (hierarchy, childIndex + i); + hierarchy_remove_children (hierarchy, childIndex + i, delEntities); + } + if (delEntities) { + for (uint32_t i = 0; i < childCount; i++) { + ECS_DelEntity (hierarchy->reg, hierarchy->ent[childIndex + i]); + } } hierarchy_close (hierarchy, childIndex, childCount); hierarchy->childCount[index] = 0; @@ -337,11 +343,15 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) } void -Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) +Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index, + int delEntities) { uint32_t parentIndex = hierarchy->parentIndex[index]; - hierarchy_remove_children (hierarchy, index); + hierarchy_remove_children (hierarchy, index, delEntities); + if (delEntities) { + ECS_DelEntity (hierarchy->reg, hierarchy->ent[index]); + } hierarchy_close (hierarchy, index, 1); hierarchy_UpdateTransformIndices (hierarchy, index, -1); @@ -442,7 +452,7 @@ Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, } r.hierarchy = dst; r.index = hierarchy_insertHierarchy (dst, src, dstParent, &srcRoot); - Hierarchy_RemoveHierarchy (src, srcRoot); + Hierarchy_RemoveHierarchy (src, srcRoot, 0); if (!src->num_objects) { Hierarchy_Delete (src); } From 9bf506fec640e73dfd555fe0a07964eabba467a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Nov 2022 00:20:02 +0900 Subject: [PATCH 3163/3664] [ui] Implement View_Delete As per the pre-ECS view code, the entire sub-hierarchy of views is deleted along with the parent view. --- include/QF/ui/view.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index 9370e3659..8cc5e64ea 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -124,6 +124,7 @@ typedef void (*view_move_f) (view_t view, view_pos_t abs); #define VIEWINLINE GNU89INLINE inline view_t View_New (ecs_registry_t *reg, view_t parent); +VIEWINLINE void View_Delete (view_t view); void View_SetParent (view_t view, view_t parent); void View_UpdateHierarchy (view_t view); @@ -179,6 +180,17 @@ View_Valid (view_t view) return view.reg && ECS_EntValid (view.id, view.reg); } +VIEWINLINE +void +View_Delete (view_t view) +{ + __auto_type ref = *View_GetRef (view); + Hierarchy_RemoveHierarchy (ref.hierarchy, ref.index, 1); + if (!ref.hierarchy->num_objects) { + Hierarchy_Delete (ref.hierarchy); + } +} + VIEWINLINE view_t View_GetParent (view_t view) From 80c8b377c409816a84526d0f73d2ebec66f1fd5a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Nov 2022 00:21:30 +0900 Subject: [PATCH 3164/3664] [nq] Get the deathmatch overlay working The placement isn't exactly the same as it was (more centered), but it's working and correctly appears and disappears on during bigass1. --- nq/source/sbar.c | 250 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 169 insertions(+), 81 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 7ebafcd91..f62686b11 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -69,34 +69,36 @@ int sb_updates; // if >= vid.numpages, no update needed static int sb_update_flags; static int sb_view_size; -// view_t hud_view; -static view_t hud_miniteam; -static view_t sbar_main; -static view_t hud_minifrags; // child of sbar_main for positioning -static view_t sbar_inventory; -static view_t sbar_frags; -static view_t sbar_sigils; -static view_t sbar_items; -static view_t sbar_armament; -static view_t sbar_weapons; -static view_t sbar_miniammo; -static view_t sbar_statusbar; -static view_t sbar_armor; -static view_t sbar_face; -static view_t sbar_health; -static view_t sbar_ammo; -static view_t sbar_solo; -static view_t sbar_solo_monsters; -static view_t sbar_solo_secrets; -static view_t sbar_solo_time; -static view_t sbar_solo_anchor; -static view_t sbar_solo_name; -static view_t sbar_tile[2]; static view_t intermission_view; static view_t intermission_time; static view_t intermission_secr; static view_t intermission_kill; +// view_t hud_view; +static view_t hud_miniteam; +static view_t sbar_main; +static view_t hud_minifrags; // child of sbar_main for positioning +static view_t sbar_inventory; +static view_t sbar_frags; +static view_t sbar_sigils; +static view_t sbar_items; +static view_t sbar_armament; +static view_t sbar_weapons; +static view_t sbar_miniammo; +static view_t sbar_statusbar; +static view_t sbar_armor; +static view_t sbar_face; +static view_t sbar_health; +static view_t sbar_ammo; +static view_t sbar_solo; +static view_t sbar_solo_monsters; +static view_t sbar_solo_secrets; +static view_t sbar_solo_time; +static view_t sbar_solo_anchor; +static view_t sbar_solo_name; +static view_t sbar_tile[2]; +static view_t sbar_tile[2]; +static view_t dmo_view; typedef struct view_def_s { view_t *view; @@ -198,6 +200,8 @@ static view_def_t sbar_defs[] = { {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 3, 24, 0}, {0, {10, 0, 24, 8}, grav_northwest, &sbar_miniammo, 4, 48, 0}, + {&dmo_view, { 0, 0,320, 200}, grav_north, &cl_screen_view}, + {} }; @@ -506,14 +510,21 @@ typedef struct { team_t teams[MAX_CLIENTS]; int teamsort[MAX_CLIENTS]; -int fragsort[MAX_SCOREBOARD]; -static draw_charbuffer_t *frags_buff[MAX_SCOREBOARD]; -static draw_charbuffer_t *team_buff[MAX_SCOREBOARD]; -static draw_charbuffer_t *name_buff[MAX_SCOREBOARD]; -static draw_charbuffer_t *team_frags[MAX_SCOREBOARD]; +int fragsort[MAX_CLIENTS]; +static view_t sb_views[MAX_CLIENTS]; +static draw_charbuffer_t *sb_fph[MAX_CLIENTS]; +static draw_charbuffer_t *sb_time[MAX_CLIENTS]; +static draw_charbuffer_t *sb_frags[MAX_CLIENTS]; +static draw_charbuffer_t *sb_team[MAX_CLIENTS]; +static draw_charbuffer_t *sb_ping[MAX_CLIENTS]; +static draw_charbuffer_t *sb_pl[MAX_CLIENTS]; +static draw_charbuffer_t *sb_uid[MAX_CLIENTS]; +static draw_charbuffer_t *sb_name[MAX_CLIENTS]; +static draw_charbuffer_t *sb_team_frags[MAX_CLIENTS]; +static draw_charbuffer_t *sb_spectator; int scoreboardlines, scoreboardteams; -static void __attribute__((used)) +static void Sbar_SortFrags (qboolean includespec) { int i, j, k; @@ -724,7 +735,7 @@ draw_frags (view_t view) set_frags_bar (bar, Sbar_ColorForMap (s->topcolor), Sbar_ColorForMap (s->bottomcolor), - frags_buff[i], + sb_frags[k], (k == cl.viewentity - 1) ? frags_marker : 0); draw_smallnum (View_GetChild (bar, 2), s->frags, 0, 0); } @@ -763,14 +774,14 @@ draw_minifrags (view_t view) set_minifrags_bar (bar, Sbar_ColorForMap (s->topcolor), Sbar_ColorForMap (s->bottomcolor), - frags_buff[i], + sb_frags[k], (k == cl.viewentity - 1) ? frags_marker : 0, - cl.teamplay ? team_buff[i] : 0, - name_buff[i]); + cl.teamplay ? sb_team[k] : 0, + sb_name[k]); if (cl.teamplay) { - write_charbuff (team_buff[i], 0, 0, s->team->value); + write_charbuff (sb_team[k], 0, 0, s->team->value); } - write_charbuff (name_buff[i], 0, 0, s->name->value); + write_charbuff (sb_name[k], 0, 0, s->name->value); draw_smallnum (View_GetChild (bar, 2), s->frags, 0, 0); } for (; i < numbars; i++) { @@ -822,9 +833,9 @@ draw_miniteam (view_t view) if (player_team && strnequal (player_team->value, tm->team, 16)) { func = frags_marker; } - set_miniteam_bar (bar, team_buff[i], team_frags[i], func); - write_charbuff (team_buff[i], 0, 0, s->team->value); - write_charbuff (team_frags[i], 0, 0, va (0, "%5d", tm->frags)); + set_miniteam_bar (bar, sb_team[k], sb_team_frags[k], func); + write_charbuff (sb_team[k], 0, 0, s->team->value); + write_charbuff (sb_team_frags[k], 0, 0, va (0, "%5d", tm->frags)); } for (; i < numbars; i++) { clear_miniteam_bar (View_GetChild (view, i)); @@ -1219,52 +1230,121 @@ draw_hipnotic_status (view_t *view) #endif } +static view_t +nq_dmo_line (view_t parent, int player) +{ + view_t line = sbar_view (0, 0, 192, 8, grav_north, parent); + view_t frags = sbar_view (0, 0, 40, 8, grav_northwest, line); + view_t name = sbar_view (64, 0, 128, 8, grav_northwest, line); + sbar_view (0, 0, 40, 4, grav_northwest, frags); + sbar_view (0, 4, 40, 4, grav_northwest, frags); + sbar_view (8, 0, 24, 8, grav_northwest, frags); + sbar_view (0, 0, 40, 8, grav_northwest, frags); + player_info_t *p = &cl.players[player]; + set_frags_bar (frags, + Sbar_ColorForMap (p->topcolor), + Sbar_ColorForMap (p->bottomcolor), + sb_frags[player], + (player == cl.viewentity - 1) ? frags_marker : 0); + sbar_setcomponent (name, hud_charbuff, &sb_name[player]); + return line; +} + static void -Sbar_DeathmatchOverlay (view_t *view) +Sbar_DeathmatchOverlay (view_t view) { #if 0 - int i, k, l; - int top, bottom; - int x, y; - player_info_t *s; + // this should be on a timer and needs nq/qw specific variants + // request new ping times every two seconds + if (!cls.demoplayback && realtime - cl.last_ping_request > 2) { + cl.last_ping_request = realtime; + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + SZ_Print (&cls.netchan.message, "pings"); + } + if (hud_ping) { + int ping = cl.players[cl.playernum].ping; - r_data->scr_copyeverything = 1; - r_data->scr_fullupdate = 0; + ping = bound (0, ping, 999); + draw_string (view, 0, 0, va (0, "%3d ms ", ping)); + } - draw_cachepic (view, 0, 0, "gfx/ranking.lmp", 1); + if (hud_ping && hud_pl) + draw_character (view, 48, 0, '/'); - // scores - Sbar_SortFrags (); + if (hud_pl) { + int lost = CL_CalcNet (); - // draw the text - l = scoreboardlines; - - x = 80; - y = 40; - for (i = 0; i < l; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name->value[0]) - continue; - - // draw background - top = Sbar_ColorForMap (s->topcolor); - bottom = Sbar_ColorForMap (s->bottomcolor); - - draw_fill (view, x, y, 40, 4, top); - draw_fill (view, x, y + 4, 40, 4, bottom); - - draw_smallnum (view, x + 12, y, s->frags, 0, 0); - - if (k == cl.viewentity - 1) - draw_character (view, x - 4, y, 12); - - // draw name - draw_string (view, x + 64, y, s->name->value); - - y += 10; + lost = bound (0, lost, 999); + draw_string (view, 56, 0, va (0, "%3d pl", lost)); } #endif + // 0, 0 "gfx/ranking.lmp" + // 80, 40 + // + // qw t 2+ [ + // ping pl main team uid name + // 0,y 32,y 64,y 184,y 224,y 264,y + // 24,8 24,8 112,8 32,8 32,8 80,8 + // ] + // qw t 1 [ + // uid pl main team name + // 0,y 32,y 64,y 184,y 224,y + // 32,8 24,8 112,8 32,8 96,8 + // ] + // qw t 0 [ + // ping pl main team name + // 0,y 32,y 64,y 184,y 224,y + // 24,8 24,8 112,8 32,8 96,8 + // ] + // qw 2+ [ + // ping pl main uid name + // 0,y 32,y 64,y 184,y 224,y + // 24,8 24,8 112,8 32,8 96,8 + // ] + // qw 1 [ + // ping pl main name + // 0,y 32,y 64,y 184,y + // 24,8 24,8 112,8 136,8 + // ] + // qw 0 [ + // uid pl main name + // 0,y 32,y 64,y 184,y + // 32,8 24,8 112,8 136,8 + // ] + // for all qw, spectator replaces main, team at 72,0 88,8 + + Sbar_SortFrags (0); + printf ("dmo: %d\n", scoreboardlines); + + int y = 40; + view_pos_t len = View_GetLen (view); + int numbars = (len.y - y) / 10; + int count = min (scoreboardlines, numbars); + int i; + + if (cl.stats[STAT_HEALTH] > 0) { + count = 0; + } + + for (i = 0; i < count; i++, y += 10) { + int k = fragsort[i]; + if (!View_Valid (sb_views[k])) { + sb_views[k] = nq_dmo_line (view, k); + } + player_info_t *p = &cl.players[k]; + //FIXME update top/bottom color + write_charbuff (sb_frags[k], 0, 0, va (0, "%3d", p->frags)); + write_charbuff (sb_name[k], 0, 0, p->name->value); + view_pos_t pos = View_GetPos (sb_views[k]); + View_SetPos (sb_views[k], pos.x, y); + } + for (; i < MAX_CLIENTS; i++) { + int k = fragsort[i]; + if (View_Valid (sb_views[k])) { + View_Delete (sb_views[k]); + } + } + View_UpdateHierarchy (view); } static void @@ -1525,6 +1605,7 @@ static const sb_updater_t frags_update[] = { {draw_frags, &sbar_frags}, {draw_minifrags, &hud_minifrags}, {draw_miniteam, &hud_miniteam}, + {Sbar_DeathmatchOverlay, &dmo_view}, {} }; static const sb_updater_t health_update[] = { @@ -1536,6 +1617,7 @@ static const sb_updater_t info_update[] = { {draw_frags, &sbar_frags}, {draw_minifrags, &hud_minifrags}, {draw_miniteam, &hud_miniteam}, + {Sbar_DeathmatchOverlay, &dmo_view}, {} }; static const sb_updater_t items_update[] = { @@ -1582,7 +1664,6 @@ Sbar_Draw (void) } if (sb_update_flags & (1 << sbc_info)) { draw_overlay (0); - Sbar_DeathmatchOverlay (0); } if (sb_showscores) { draw_solo_time (); @@ -2027,12 +2108,19 @@ init_views (void) time_buff = Draw_CreateBuffer (8, 1); fps_buff = Draw_CreateBuffer (11, 1); - for (int i = 0; i < MAX_SCOREBOARD; i++) { - frags_buff[i] = Draw_CreateBuffer (3, 1); - team_buff[i] = Draw_CreateBuffer (4, 1); - name_buff[i] = Draw_CreateBuffer (16, 1); - team_frags[i] = Draw_CreateBuffer (5, 1); + for (int i = 0; i < MAX_CLIENTS; i++) { + sb_fph[i] = Draw_CreateBuffer (3, 1); + sb_time[i] = Draw_CreateBuffer (4, 1); + sb_frags[i] = Draw_CreateBuffer (3, 1); + sb_team[i] = Draw_CreateBuffer (4, 1); + sb_ping[i] = Draw_CreateBuffer (3, 1); + sb_pl[i] = Draw_CreateBuffer (3, 1); + sb_uid[i] = Draw_CreateBuffer (4, 1); + sb_name[i] = Draw_CreateBuffer (16, 1); + sb_team_frags[i] = Draw_CreateBuffer (5, 1); } + sb_spectator = Draw_CreateBuffer (11, 1); + write_charbuff (sb_spectator, 0, 0, "(spectator)"); if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) { init_hipnotic_sbar_views (); From 22b0f75cc273358911ce20ef65c39f482cf71ad0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Nov 2022 11:24:34 +0900 Subject: [PATCH 3165/3664] [nq] Merge in qw deathmatch overlay display Nicely, all the data is already sort-of available (ping and pl will be interesting, and I need to double-check uid), but once I get some issues with the first entry not working, I'll be able to "merge" sbar and concentrate on rogue and hipnotic. --- nq/source/sbar.c | 244 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 206 insertions(+), 38 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index f62686b11..5aba531ff 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -200,7 +200,7 @@ static view_def_t sbar_defs[] = { {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 3, 24, 0}, {0, {10, 0, 24, 8}, grav_northwest, &sbar_miniammo, 4, 48, 0}, - {&dmo_view, { 0, 0,320, 200}, grav_north, &cl_screen_view}, + {&dmo_view, { 0, 0,320, 200}, grav_center, &cl_screen_view}, {} }; @@ -1230,26 +1230,216 @@ draw_hipnotic_status (view_t *view) #endif } -static view_t -nq_dmo_line (view_t parent, int player) +static void +setup_frags (view_t frags, int player) { - view_t line = sbar_view (0, 0, 192, 8, grav_north, parent); - view_t frags = sbar_view (0, 0, 40, 8, grav_northwest, line); - view_t name = sbar_view (64, 0, 128, 8, grav_northwest, line); sbar_view (0, 0, 40, 4, grav_northwest, frags); sbar_view (0, 4, 40, 4, grav_northwest, frags); sbar_view (8, 0, 24, 8, grav_northwest, frags); sbar_view (0, 0, 40, 8, grav_northwest, frags); + player_info_t *p = &cl.players[player]; set_frags_bar (frags, Sbar_ColorForMap (p->topcolor), Sbar_ColorForMap (p->bottomcolor), sb_frags[player], (player == cl.viewentity - 1) ? frags_marker : 0); - sbar_setcomponent (name, hud_charbuff, &sb_name[player]); +} + +static void +setup_spect (view_t spect, int player) +{ + view_t v = sbar_view (0, 0, 88, 4, grav_north, spect); + sbar_setcomponent (v, hud_charbuff, &sb_spectator); +} + +typedef struct dmo_def_s { + int width; // in pixels + draw_charbuffer_t **buffer; + void (*setup) (view_t, int); +} dmo_def_t; + +static dmo_def_t ping_def = { .width = 24, .buffer = sb_ping, }; +static dmo_def_t pl_def = { .width = 24, .buffer = sb_pl, }; +static dmo_def_t fph_def = { .width = 24, .buffer = sb_fph, }; +static dmo_def_t time_def = { .width = 32, .buffer = sb_time, }; +static dmo_def_t frags_def = { .width = 40, .setup = setup_frags, }; +static dmo_def_t team_def = { .width = 32, .buffer = sb_uid, }; +static dmo_def_t uid_def = { .width = 32, .buffer = sb_uid, }; +static dmo_def_t name_def = { .width = 128, .buffer = sb_name, }; +static dmo_def_t spectator_def = { .width = 112, .setup = setup_spect, }; +static dmo_def_t spec_team_def = { .width = 32, }; + +static dmo_def_t *nq_dmo_defs[] = { + &frags_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_team_uid_ping_defs[] = { + &ping_def, + &pl_def, + &fph_def, + &time_def, + &frags_def, + &team_def, + &uid_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_team_uid_defs[] = { + &uid_def, + &pl_def, + &fph_def, + &time_def, + &frags_def, + &team_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_team_ping_defs[] = { + &ping_def, + &pl_def, + &fph_def, + &time_def, + &frags_def, + &team_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_uid_ping_defs[] = { + &ping_def, + &pl_def, + &fph_def, + &time_def, + &frags_def, + &uid_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_uid_defs[] = { + &ping_def, + &pl_def, + &fph_def, + &time_def, + &frags_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_ping_defs[] = { + &uid_def, + &pl_def, + &fph_def, + &time_def, + &frags_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_spect_team_uid_ping_defs[] = { + &ping_def, + &pl_def, + &spectator_def, + &spec_team_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_spect_team_uid_defs[] = { + &ping_def, + &pl_def, + &spectator_def, + &spec_team_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_spect_team_ping_defs[] = { + &ping_def, + &pl_def, + &spectator_def, + &spec_team_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_spect_uid_ping_defs[] = { + &ping_def, + &pl_def, + &spectator_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_spect_uid_defs[] = { + &ping_def, + &pl_def, + &spectator_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_spect_ping_defs[] = { + &ping_def, + &pl_def, + &spectator_def, + &name_def, + 0 +}; +static dmo_def_t **dmo_defs[] = { + nq_dmo_defs, + qw_dmo_ping_defs, + qw_dmo_uid_defs, + qw_dmo_uid_ping_defs, + qw_dmo_team_ping_defs, + qw_dmo_team_uid_defs, + qw_dmo_team_uid_ping_defs, + qw_dmo_spect_ping_defs, + qw_dmo_spect_uid_defs, + qw_dmo_spect_uid_ping_defs, + qw_dmo_spect_team_ping_defs, + qw_dmo_spect_team_uid_defs, + qw_dmo_spect_team_uid_ping_defs, +}; + +static view_t +make_dmo_line (view_t parent, int player) +{ + dmo_def_t **defs = dmo_defs[3]; //FIXME nq/qw/team/spec/cvar + int x = -8; + view_t line = sbar_view (0, 0, 0, 0, grav_north, parent); + + while (*defs) { + dmo_def_t *d = *defs++; + x += 8 + d->width; + if (d->buffer || d->setup) { + view_t v = sbar_view (x - d->width, 0, d->width, 8, + grav_northwest, line); + if (d->buffer) { + draw_charbuffer_t *buff = d->buffer[player]; + sbar_setcomponent (v, hud_charbuff, &buff); + } else if (d->setup) { + d->setup (v, player); + } + } + } + View_SetLen (line, x, 8); return line; } +static inline int +calc_fph (int frags, int total) +{ + int fph; + + if (total != 0) { + fph = (3600 * frags) / total; + + if (fph >= 999) { + fph = 999; + } else if (fph <= -999) { + fph = -999; + } + } else { + fph = 0; + } + + return fph; +} + static void Sbar_DeathmatchOverlay (view_t view) { @@ -1281,36 +1471,6 @@ Sbar_DeathmatchOverlay (view_t view) // 0, 0 "gfx/ranking.lmp" // 80, 40 // - // qw t 2+ [ - // ping pl main team uid name - // 0,y 32,y 64,y 184,y 224,y 264,y - // 24,8 24,8 112,8 32,8 32,8 80,8 - // ] - // qw t 1 [ - // uid pl main team name - // 0,y 32,y 64,y 184,y 224,y - // 32,8 24,8 112,8 32,8 96,8 - // ] - // qw t 0 [ - // ping pl main team name - // 0,y 32,y 64,y 184,y 224,y - // 24,8 24,8 112,8 32,8 96,8 - // ] - // qw 2+ [ - // ping pl main uid name - // 0,y 32,y 64,y 184,y 224,y - // 24,8 24,8 112,8 32,8 96,8 - // ] - // qw 1 [ - // ping pl main name - // 0,y 32,y 64,y 184,y - // 24,8 24,8 112,8 136,8 - // ] - // qw 0 [ - // uid pl main name - // 0,y 32,y 64,y 184,y - // 32,8 24,8 112,8 136,8 - // ] // for all qw, spectator replaces main, team at 72,0 88,8 Sbar_SortFrags (0); @@ -1329,11 +1489,19 @@ Sbar_DeathmatchOverlay (view_t view) for (i = 0; i < count; i++, y += 10) { int k = fragsort[i]; if (!View_Valid (sb_views[k])) { - sb_views[k] = nq_dmo_line (view, k); + sb_views[k] = make_dmo_line (view, k); } player_info_t *p = &cl.players[k]; + write_charbuff (sb_ping[k], 0, 0, va (0, "%3d", p->ping)); + write_charbuff (sb_pl[k], 0, 0, va (0, "%3d", p->pl)); + int total = (cl.intermission ? cl.completed_time : realtime) + - p->entertime; + write_charbuff (sb_fph[k], 0, 0, va (0, "%3d", + calc_fph (p->frags, total))); + write_charbuff (sb_time[k], 0, 0, va (0, "%3d", total / 60)); //FIXME update top/bottom color write_charbuff (sb_frags[k], 0, 0, va (0, "%3d", p->frags)); + write_charbuff (sb_uid[k], 0, 0, va (0, "%3d", p->userid)); write_charbuff (sb_name[k], 0, 0, p->name->value); view_pos_t pos = View_GetPos (sb_views[k]); View_SetPos (sb_views[k], pos.x, y); From 0e06a0c5bdc164503bc0660dc4d9a4ce55a4dde1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Nov 2022 12:49:41 +0900 Subject: [PATCH 3166/3664] [nq] Set unused fragsort entries to -1 The first scoreboard entry not showing was due to it being deleted immediately because unused fragsort array entries had a valid player index (0 in this case) and thus the unused view removal code was removing views it should not. --- nq/source/sbar.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 5aba531ff..c65f54245 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -540,6 +540,9 @@ Sbar_SortFrags (qboolean includespec) cl.players[i].frags = -999; } } + for (i = scoreboardlines; i < cl.maxclients; i++) { + fragsort[i] = -1; + } player_info_t *p = cl.players; for (i = 0; i < scoreboardlines; i++) { @@ -1474,7 +1477,6 @@ Sbar_DeathmatchOverlay (view_t view) // for all qw, spectator replaces main, team at 72,0 88,8 Sbar_SortFrags (0); - printf ("dmo: %d\n", scoreboardlines); int y = 40; view_pos_t len = View_GetLen (view); @@ -1488,10 +1490,10 @@ Sbar_DeathmatchOverlay (view_t view) for (i = 0; i < count; i++, y += 10) { int k = fragsort[i]; + player_info_t *p = &cl.players[k]; if (!View_Valid (sb_views[k])) { sb_views[k] = make_dmo_line (view, k); } - player_info_t *p = &cl.players[k]; write_charbuff (sb_ping[k], 0, 0, va (0, "%3d", p->ping)); write_charbuff (sb_pl[k], 0, 0, va (0, "%3d", p->pl)); int total = (cl.intermission ? cl.completed_time : realtime) @@ -1503,12 +1505,11 @@ Sbar_DeathmatchOverlay (view_t view) write_charbuff (sb_frags[k], 0, 0, va (0, "%3d", p->frags)); write_charbuff (sb_uid[k], 0, 0, va (0, "%3d", p->userid)); write_charbuff (sb_name[k], 0, 0, p->name->value); - view_pos_t pos = View_GetPos (sb_views[k]); - View_SetPos (sb_views[k], pos.x, y); + View_SetPos (sb_views[k], 0, y); } for (; i < MAX_CLIENTS; i++) { int k = fragsort[i]; - if (View_Valid (sb_views[k])) { + if (k >= 0 && View_Valid (sb_views[k])) { View_Delete (sb_views[k]); } } @@ -2286,6 +2287,7 @@ init_views (void) sb_uid[i] = Draw_CreateBuffer (4, 1); sb_name[i] = Draw_CreateBuffer (16, 1); sb_team_frags[i] = Draw_CreateBuffer (5, 1); + fragsort[i] = -1; } sb_spectator = Draw_CreateBuffer (11, 1); write_charbuff (sb_spectator, 0, 0, "(spectator)"); From 34f0a5944181b4e94e0edf8528b5d966b386ba0e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 8 Nov 2022 16:26:47 +0900 Subject: [PATCH 3167/3664] [client] Merge sbar At long last, the status bar code is now shared between nq and qw. There are many bugs to fix, but at least now they're all in the one place. --- include/sbar.h | 4 +- libs/client/Makemodule.am | 3 +- {nq/source => libs/client}/sbar.c | 315 ++++- nq/source/Makemodule.am | 2 +- qw/source/Makemodule.am | 2 +- qw/source/cl_cam.c | 18 +- qw/source/cl_main.c | 2 +- qw/source/cl_parse.c | 11 +- qw/source/sbar.c | 2152 ----------------------------- 9 files changed, 342 insertions(+), 2167 deletions(-) rename {nq/source => libs/client}/sbar.c (90%) delete mode 100644 qw/source/sbar.c diff --git a/include/sbar.h b/include/sbar.h index 7fa011a15..740150afb 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -37,9 +37,6 @@ void Sbar_Init (void); -struct cvar_s; -void Sbar_DMO_Init_f (void *data, const struct cvar_s *var); - typedef enum { sbc_ammo, sbc_armor, @@ -48,6 +45,7 @@ typedef enum { sbc_info, sbc_items, sbc_weapon, + sbc_server, sbc_num_changed } sbar_changed; diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index 8c60530a0..c017cefd9 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -15,7 +15,8 @@ libs_client_libQFclient_la_SOURCES= \ libs/client/cl_world.c \ libs/client/hud.c \ libs/client/locs.c \ - libs/client/old_keys.c + libs/client/old_keys.c \ + libs/client/sbar.c default_input_src = libs/client/default_input.plist default_input_gen = libs/client/default_input.plc diff --git a/nq/source/sbar.c b/libs/client/sbar.c similarity index 90% rename from nq/source/sbar.c rename to libs/client/sbar.c index c65f54245..63936d212 100644 --- a/nq/source/sbar.c +++ b/libs/client/sbar.c @@ -60,6 +60,7 @@ #include "client/hud.h" #include "client/screen.h" +#include "client/world.h" #include "nq/include/client.h" #include "nq/include/game.h" @@ -271,6 +272,7 @@ static qpic_t *sb_face_invuln; static qpic_t *sb_face_invis_invuln; static qboolean sb_showscores; +static qboolean sb_showteamscores; static int sb_lines; // scan lines to draw @@ -290,6 +292,35 @@ static qpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes // { HIT_LASER_CANNON_BIT, HIT_MJOLNIR_BIT, 4, HIT_PROXIMITY_GUN_BIT }; qpic_t *hsb_items[2]; // MED 01/04/97 added hipnotic items array +//static qboolean largegame = false; + +char *fs_fraglog; +static cvar_t fs_fraglog_cvar = { + .name = "fs_fraglog", + .description = + "Filename of the automatic frag-log.", + .default_value = "qw-scores.log", + .flags = CVAR_ARCHIVE, + .value = { .type = 0, .value = &fs_fraglog }, +}; +int cl_fraglog; +static cvar_t cl_fraglog_cvar = { + .name = "cl_fraglog", + .description = + "Automatic fraglogging, non-zero value will switch it on.", + .default_value = "0", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &cl_fraglog }, +}; +int hud_scoreboard_uid; +static cvar_t hud_scoreboard_uid_cvar = { + .name = "hud_scoreboard_uid", + .description = + "Set to 1 to show uid instead of ping. Set to 2 to show both.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &hud_scoreboard_uid }, +}; float scr_centertime; static cvar_t scr_centertime_cvar = { .name = "scr_centertime", @@ -882,6 +913,29 @@ draw_face (view_t view) sbar_setcomponent (view, hud_pic, &face); } +static void __attribute__((used)) +draw_spectator (view_t *view) +{ +#if 0 + char st[512]; + + if (autocam != CAM_TRACK) { + draw_string (view, 160 - 7 * 8, 4, "SPECTATOR MODE"); + draw_string (view, 160 - 14 * 8 + 4, 12, + "Press [ATTACK] for AutoCamera"); + } else { +// Sbar_DrawString (160-14*8+4,4, "SPECTATOR MODE - TRACK CAMERA"); + if (cl.players[spec_track].name) { + snprintf (st, sizeof (st), "Tracking %-.13s, [JUMP] for next", + cl.players[spec_track].name->value); + } else { + snprintf (st, sizeof (st), "Lost player, [JUMP] for next"); + } + draw_string (view, 0, -8, st); + } +#endif +} + static inline void draw_armor (view_t view) { @@ -920,6 +974,11 @@ draw_health (view_t view) static void draw_status (view_t *view) { + if (cl.spectator) { + draw_spectator (view); + if (autocam != CAM_TRACK) + return; + } if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { draw_solo (view); return; @@ -931,6 +990,7 @@ draw_status (view_t *view) draw_ammo (sbar_status_ammo); } #endif + static void __attribute__((used)) draw_rogue_weapons_sbar (view_t *view) { @@ -1516,6 +1576,82 @@ Sbar_DeathmatchOverlay (view_t view) View_UpdateHierarchy (view); } +static void __attribute__((used)) +Sbar_TeamOverlay (view_t *view) +{ +#if 0 + char num[20]; + int pavg, plow, phigh, i, k, x, y; + team_t *tm; + info_key_t *player_team = cl.players[cl.playernum].team; + + if (!cl.teamplay) { // FIXME: if not teamplay, why teamoverlay? + Sbar_DeathmatchOverlay (view, 0); + return; + } + + r_data->scr_copyeverything = 1; + r_data->scr_fullupdate = 0; + + draw_cachepic (view, 0, 0, "gfx/ranking.lmp", 1); + + y = 24; + x = 36; + draw_string (view, x, y, "low/avg/high team total players"); + y += 8; + draw_string (view, x, y, "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f " + "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f " + "\x1d\x1e\x1e\x1e\x1e\x1e\x1f"); + y += 8; + + // sort the teams + Sbar_SortTeams (); + + // draw the text + for (i = 0; i < scoreboardteams && y <= view->ylen - 10; i++) { + k = teamsort[i]; + tm = teams + k; + + // draw pings + plow = tm->plow; + if (plow < 0 || plow > 999) + plow = 999; + phigh = tm->phigh; + if (phigh < 0 || phigh > 999) + phigh = 999; + if (!tm->players) + pavg = 999; + else + pavg = tm->ptotal / tm->players; + if (pavg < 0 || pavg > 999) + pavg = 999; + + snprintf (num, sizeof (num), "%3i/%3i/%3i", plow, pavg, phigh); + draw_string (view, x, y, num); + + // draw team + draw_nstring (view, x + 104, y, tm->team, 4); + + // draw total + snprintf (num, sizeof (num), "%5i", tm->frags); + draw_string (view, x + 104 + 40, y, num); + + // draw players + snprintf (num, sizeof (num), "%5i", tm->players); + draw_string (view, x + 104 + 88, y, num); + + if (player_team && strnequal (player_team->value, tm->team, 16)) { + draw_character (view, x + 104 - 8, y, 16); + draw_character (view, x + 104 + 32, y, 17); + } + + y += 8; + } + y += 8; + Sbar_DeathmatchOverlay (view, y); +#endif +} + static void Sbar_DrawScoreboard (void) { @@ -1532,6 +1668,123 @@ draw_overlay (view_t *view) if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { Sbar_DrawScoreboard (); } +#if 0 + if (cls.state != ca_active + || !((cl.stats[STAT_HEALTH] <= 0 && !cl.spectator) + || sb_showscores || sb_showteamscores)) + return; + // main screen deathmatch rankings + // if we're dead show team scores in team games + if (cl.stats[STAT_HEALTH] <= 0 && !cl.spectator) + if (cl.teamplay > 0 && !sb_showscores) + Sbar_TeamOverlay (view); + else + Sbar_DeathmatchOverlay (view, 0); + else if (sb_showscores) + Sbar_DeathmatchOverlay (view, 0); + else if (sb_showteamscores) + Sbar_TeamOverlay (view); +#endif +} + +/* + Sbar_LogFrags + + autologging of frags after a match ended + (called by recived network packet with command scv_intermission) + TODO: Find a new and better place for this function + (i am nearly shure this is wrong place) + added by Elmex +*/ +void +Sbar_LogFrags (void) +{ + char *name; + char *team; + byte *cp = NULL; + QFile *file = NULL; + int minutes, fph, total, d, f, i, k, l, p; + player_info_t *s = NULL; + const char *t = NULL; + time_t tt = time (NULL); + + if (!cl_fraglog) + return; + + if ((file = QFS_Open (fs_fraglog, "a")) == NULL) + return; + + t = ctime (&tt); + if (t) + Qwrite (file, t, strlen (t)); + + Qprintf (file, "%s\n%s %s\n", "FIXME",//FIXME cls.servername->str, + cl_world.scene->worldmodel->path, cl.levelname); + + // scores + Sbar_SortFrags (true); + + // draw the text + l = scoreboardlines; + + if (cl.teamplay) { + // TODO: test if the teamplay does correct output + Qwrite (file, "pl fph time frags team name\n", + strlen ("pl fph time frags team name\n")); + } else { + Qwrite (file, "pl fph time frags name\n", + strlen ("pl fph time frags name\n")); + } + + for (i = 0; i < l; i++) { + k = fragsort[i]; + s = &cl.players[k]; + if (!s->name || !s->name->value[0]) + continue; + + // draw pl + p = s->pl; + (void) p; //FIXME + + // get time + if (cl.intermission) + total = cl.completed_time - s->entertime; + else + total = realtime - s->entertime; + minutes = total / 60; + + // get frags + f = s->frags; + + fph = calc_fph (f, total); + + name = malloc (strlen (s->name->value) + 1); + for (cp = (byte *) s->name->value, d = 0; *cp; cp++, d++) + name[d] = sys_char_map[*cp]; + name[d] = 0; + + if (s->spectator) { + Qprintf (file, "%-3i%% %s (spectator)", s->pl, name); + } else { + if (cl.teamplay) { + team = malloc (strlen (s->team->value) + 1); + for (cp = (byte *) s->team, d = 0; *cp; cp++, d++) + team[d] = sys_char_map[*cp]; + team[d] = 0; + + Qprintf (file, "%-3i%% %-3i %-4i %-3i %-4s %s", + s->pl, fph, minutes, f, team, name); + free (team); + } else { + Qprintf (file, "%-3i%% %-3i %-4i %-3i %s", + s->pl, fph, minutes, f, name); + } + } + free (name); + Qwrite (file, "\n\n", 1); + } + + Qclose (file); } static void @@ -1581,6 +1834,36 @@ draw_fps (view_t view) write_charbuff (fps_buff, 0, 0, st); } +#if 0 +static void +draw_net (view_t *view) +{ + // request new ping times every two seconds + if (!cls.demoplayback && realtime - cl.last_ping_request > 2) { + cl.last_ping_request = realtime; + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + SZ_Print (&cls.netchan.message, "pings"); + } + if (hud_ping) { + int ping = cl.players[cl.playernum].ping; + + ping = bound (0, ping, 999); + draw_string (view, 0, 0, va (0, "%3d ms ", ping)); + } + + if (hud_ping && hud_pl) + draw_character (view, 48, 0, '/'); + + if (hud_pl) { + int lost = CL_CalcNet (); + + lost = bound (0, lost, 999); + draw_string (view, 56, 0, va (0, "%3d pl", lost)); + } +} +if (cls.state == ca_active && (hud_ping || hud_pl)) +#endif + static void draw_intermission (view_t view) { @@ -1819,9 +2102,11 @@ Sbar_Changed (sbar_changed change) Sys_Error ("invalid sbar changed enum"); } const sb_updater_t *ud = sb_updaters[change]; - while (ud->update) { - sbar_setcomponent (*ud->view, hud_updateonce, &ud->update); - ud++; + if (ud) { + while (ud->update) { + sbar_setcomponent (*ud->view, hud_updateonce, &ud->update); + ud++; + } } } @@ -2498,6 +2783,23 @@ Sbar_DontShowScores (void) sbar_remcomponent (sbar_solo_name, hud_charbuff); } +static void +Sbar_ShowTeamScores (void) +{ + if (sb_showteamscores) + return; + + sb_showteamscores = true; + sb_updates = 0; +} + +static void +Sbar_DontShowTeamScores (void) +{ + sb_showteamscores = false; + sb_updates = 0; +} + void Sbar_Init (void) { @@ -2522,8 +2824,15 @@ Sbar_Init (void) "Display information on everyone playing"); Cmd_AddCommand ("-showscores", Sbar_DontShowScores, "Stop displaying information on everyone playing"); + Cmd_AddCommand ("+showteamscores", Sbar_ShowTeamScores, + "Display information for your team"); + Cmd_AddCommand ("-showteamscores", Sbar_DontShowTeamScores, + "Stop displaying information for your team"); r_data->viewsize_callback = viewsize_f; + Cvar_Register (&hud_scoreboard_uid_cvar, 0/*FIXME Sbar_DMO_Init_f*/, 0); + Cvar_Register (&fs_fraglog_cvar, 0, 0); + Cvar_Register (&cl_fraglog_cvar, 0, 0); Cvar_Register (&scr_centertime_cvar, 0, 0); Cvar_Register (&scr_printspeed_cvar, 0, 0); diff --git a/nq/source/Makemodule.am b/nq/source/Makemodule.am index a83a41d17..e4dd9a47f 100644 --- a/nq/source/Makemodule.am +++ b/nq/source/Makemodule.am @@ -73,7 +73,7 @@ nq_server_LIB_DEPS=$(nq_server_LIBFILES) $(nq_common_LIBFILES) nq_source_libnq_client_a_SOURCES= \ nq/source/cl_cmd.c nq/source/cl_demo.c nq/source/cl_ents.c nq/source/cl_input.c nq/source/cl_main.c \ - nq/source/cl_parse.c nq/source/sbar.c + nq/source/cl_parse.c nq_source_libnq_server_a_SOURCES= \ nq/source/host.c nq/source/host_cmd.c nq/source/sv_cl_phys.c nq/source/sv_cvar.c nq/source/sv_main.c \ diff --git a/qw/source/Makemodule.am b/qw/source/Makemodule.am index 8caffdc5e..be7530c18 100644 --- a/qw/source/Makemodule.am +++ b/qw/source/Makemodule.am @@ -107,7 +107,7 @@ qw_source_libqw_client_a_SOURCES= \ qw/source/cl_cam.c qw/source/cl_chat.c qw/source/cl_cmd.c qw/source/cl_cvar.c qw/source/cl_demo.c \ qw/source/cl_entparse.c qw/source/cl_ents.c qw/source/cl_http.c qw/source/cl_input.c qw/source/cl_main.c qw/source/cl_ngraph.c \ qw/source/cl_parse.c qw/source/cl_pred.c qw/source/cl_rss.c qw/source/cl_skin.c qw/source/cl_slist.c \ - qw/source/sbar.c qw/source/teamplay.c + qw/source/teamplay.c # Software-rendering clients diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 53b7e706a..a65d569bb 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -199,7 +199,14 @@ Cam_Unlock (void) } autocam = CAM_NONE; locked = false; - Sbar_Changed (~0); + Sbar_Changed (sbc_ammo); + Sbar_Changed (sbc_armor); + Sbar_Changed (sbc_frags); + Sbar_Changed (sbc_health); + Sbar_Changed (sbc_info); + Sbar_Changed (sbc_items); + Sbar_Changed (sbc_weapon); + Sbar_Changed (sbc_server); } } @@ -221,7 +228,14 @@ Cam_Lock (int playernum) last_lock = realtime; cam_forceview = true; locked = false; - Sbar_Changed (~0); + Sbar_Changed (sbc_ammo); + Sbar_Changed (sbc_armor); + Sbar_Changed (sbc_frags); + Sbar_Changed (sbc_health); + Sbar_Changed (sbc_info); + Sbar_Changed (sbc_items); + Sbar_Changed (sbc_weapon); + Sbar_Changed (sbc_server); } static trace_t diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 70dcb5f4a..5f0b53218 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -870,7 +870,7 @@ CL_FullServerinfo_f (void) } if ((p = Info_ValueForKey (cl.serverinfo, "teamplay")) && *p) { cl.teamplay = atoi (p); - Sbar_DMO_Init_f (0, 0); // HUD setup, cl.teamplay changed + Sbar_Changed (sbc_server); } if ((p = Info_ValueForKey (cl.serverinfo, "watervis")) && *p) { cl.viewstate.watervis = atoi (p); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index e534acafc..ee5e07d6b 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1121,7 +1121,7 @@ CL_ServerInfo (void) cl.no_pogo_stick = no_pogo_stick; } else if (strequal (key, "teamplay")) { cl.teamplay = atoi (value); - Sbar_DMO_Init_f (0, 0); // HUD setup, cl.teamplay changed + Sbar_Changed (sbc_server); } else if (strequal (key, "watervis")) { cl.viewstate.watervis = atoi (value); } else if (strequal (key, "fpd")) { @@ -1152,8 +1152,6 @@ CL_SetStat (int stat, int value) return; } - Sbar_Changed (~0); - switch (stat) { case STAT_ITEMS: #define IT_POWER (IT_QUAD | IT_SUIT | IT_INVULNERABILITY | IT_INVISIBILITY) @@ -1167,6 +1165,13 @@ CL_SetStat (int stat, int value) if (value <= 0) Team_Dead (); break; + default: + //FIXME smarter checks + Sbar_Changed (sbc_ammo); + Sbar_Changed (sbc_armor); + Sbar_Changed (sbc_frags); + Sbar_Changed (sbc_weapon); + break; } cl.stats[stat] = value; cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]]; diff --git a/qw/source/sbar.c b/qw/source/sbar.c deleted file mode 100644 index ba7027742..000000000 --- a/qw/source/sbar.c +++ /dev/null @@ -1,2152 +0,0 @@ -/* - sbar.c - - Status bar - - Copyright (C) 1996-1997 Id Software, Inc. - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif - -#include -#include - -#include "QF/cmd.h" -#include "QF/console.h" -#include "QF/cvar.h" -#include "QF/draw.h" -#include "QF/dstring.h" -#include "QF/gib.h" -#include "QF/msg.h" -#include "QF/quakefs.h" -#include "QF/screen.h" -#include "QF/sys.h" -#include "QF/va.h" -#include "QF/vid.h" - -#include "QF/plugin/console.h" - -#include "QF/scene/scene.h" - -#include "QF/ui/view.h" - -#include "compat.h" - -#include "client/hud.h" -#include "client/screen.h" -#include "client/world.h" - -#include "qw/bothdefs.h" -#include "qw/include/cl_cam.h" -#include "qw/include/cl_parse.h" -#include "qw/include/client.h" -#include "sbar.h" - -int sb_updates; // if >= vid.numpages, no update needed -static int sb_update_flags; -static int sb_view_size; - -static view_t sbar_main; -static view_t sbar_inventory; -static view_t sbar_frags; -static view_t sbar_sigils; -static view_t sbar_items; -static view_t sbar_armament; -static view_t sbar_weapons; -static view_t sbar_miniammo; -static view_t sbar_statusbar; -static view_t sbar_armor; -static view_t sbar_face; -static view_t sbar_health; -static view_t sbar_ammo; -//static view_t sbar_status; -static view_t sbar_tile[2]; - -static view_t -sbar_view (int x, int y, int w, int h, grav_t gravity, view_t parent) -{ - view_t view = View_New (hud_registry, parent); - View_SetPos (view, x, y); - View_SetLen (view, w, h); - View_SetGravity (view, gravity); - View_SetVisible (view, 1); - return view; -} - -static inline void -sbar_setcomponent (view_t view, uint32_t comp, void *data) -{ - Ent_SetComponent (view.id, comp, view.reg, data); -} - -static inline int -sbar_hascomponent (view_t view, uint32_t comp) -{ - return Ent_HasComponent (view.id, comp, view.reg); -} - -static inline void * -sbar_getcomponent (view_t view, uint32_t comp) -{ - return Ent_GetComponent (view.id, comp, view.reg); -} - -static inline void -sbar_remcomponent (view_t view, uint32_t comp) -{ - Ent_RemoveComponent (view.id, comp, view.reg); -} - -#define STAT_MINUS 10 // num frame for '-' stats digit - -qpic_t *sb_nums[2][11]; -qpic_t *sb_colon, *sb_slash; -qpic_t *sb_ibar; -qpic_t *sb_sbar; -qpic_t *sb_scorebar; - -qpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes -qpic_t *sb_ammo[4]; -qpic_t *sb_sigil[4]; -qpic_t *sb_armor[3]; -qpic_t *sb_items[32]; - -qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive - // 0 is static, 1 is temporary animation -qpic_t *sb_face_invis; -qpic_t *sb_face_quad; -qpic_t *sb_face_invuln; -qpic_t *sb_face_invis_invuln; - -qboolean sb_showscores; -qboolean sb_showteamscores; - -//static qboolean largegame = false; - -char *fs_fraglog; -static cvar_t fs_fraglog_cvar = { - .name = "fs_fraglog", - .description = - "Filename of the automatic frag-log.", - .default_value = "qw-scores.log", - .flags = CVAR_ARCHIVE, - .value = { .type = 0, .value = &fs_fraglog }, -}; -int cl_fraglog; -static cvar_t cl_fraglog_cvar = { - .name = "cl_fraglog", - .description = - "Automatic fraglogging, non-zero value will switch it on.", - .default_value = "0", - .flags = CVAR_ARCHIVE, - .value = { .type = &cexpr_int, .value = &cl_fraglog }, -}; -int hud_scoreboard_uid; -static cvar_t hud_scoreboard_uid_cvar = { - .name = "hud_scoreboard_uid", - .description = - "Set to 1 to show uid instead of ping. Set to 2 to show both.", - .default_value = "0", - .flags = CVAR_NONE, - .value = { .type = &cexpr_int, .value = &hud_scoreboard_uid }, -}; -float scr_centertime; -static cvar_t scr_centertime_cvar = { - .name = "scr_centertime", - .description = - "How long in seconds screen hints are displayed", - .default_value = "2", - .flags = CVAR_NONE, - .value = { .type = &cexpr_float, .value = &scr_centertime }, -}; -float scr_printspeed; -static cvar_t scr_printspeed_cvar = { - .name = "scr_printspeed", - .description = - "How fast the text is displayed at the end of the single player " - "episodes", - .default_value = "8", - .flags = CVAR_NONE, - .value = { .type = &cexpr_float, .value = &scr_printspeed }, -}; - -//static void (*Sbar_Draw_DMO_func) (view_t *view, int l, int y, int skip); - -static void -viewsize_f (int view_size) -{ - sb_view_size = view_size; - HUD_Calc_sb_lines (view_size); - if (hud_sbar) { - SCR_SetBottomMargin (hud_sbar ? hud_sb_lines : 0); - } -} - - -static int __attribute__((used)) -Sbar_ColorForMap (int m) -{ - return (bound (0, m, 13) * 16) + 8; -} - -static void -Sbar_ShowTeamScores (void) -{ - if (sb_showteamscores) - return; - - sb_showteamscores = true; - sb_updates = 0; -} - -static void -Sbar_DontShowTeamScores (void) -{ - sb_showteamscores = false; - sb_updates = 0; -} - -static void -Sbar_ShowScores (void) -{ - if (sb_showscores) - return; - - sb_showscores = true; - sb_updates = 0; -} - -static void -Sbar_DontShowScores (void) -{ - sb_showscores = false; - sb_updates = 0; -} - -void -Sbar_Changed (sbar_changed change) -{ - sb_update_flags |= 1 << change; - sb_updates = 0; // update next frame -} - -static void -draw_num (view_t *view, int num, int digits, int color) -{ - char str[12]; - char *ptr; - int l, frame, x = 0; - - if (num > 999999999) - num = 999999999; - - l = snprintf (str, sizeof (str), "%d", num); - ptr = str; - if (l > digits) - ptr += (l - digits); - while (digits > l) { - sbar_remcomponent (view[x++], hud_pic); - digits--; - } - - while (*ptr) { - if (*ptr == '-') - frame = STAT_MINUS; - else - frame = *ptr - '0'; - - sbar_setcomponent (view[x++], hud_pic, &sb_nums[color][frame]); - ptr++; - } -} - -static inline void -draw_smallnum (view_t view, int x, int y, int n, int packed, int colored) -{ - void *comp = sbar_getcomponent (view, hud_charbuff); - __auto_type charbuff = *(draw_charbuffer_t **) comp; - char num[4]; - - packed = packed != 0; // ensure 0 or 1 - - n = bound (-99, n, 999); - snprintf (num, sizeof (num), "%3d", n); - for (int i = 0; i < 3; i++) { - charbuff->chars[i] = num[i] - (colored && num[i] != ' ' ? '0' - 18 : 0); - } - -} - -static void -draw_miniammo (view_t view) -{ - int i, count; - - // ammo counts - for (i = 0; i < 4; i++) { - view_t v = View_GetChild (view, i); - count = cl.stats[STAT_SHELLS + i]; - draw_smallnum (v, (6 * i + 1) * 8 + 2, 0, count, 0, 1); - } -} - -static void -draw_ammo (view_t view) -{ - qpic_t *pic = 0; - if (cl.stats[STAT_ITEMS] & IT_SHELLS) - pic = sb_ammo[0]; - else if (cl.stats[STAT_ITEMS] & IT_NAILS) - pic = sb_ammo[1]; - else if (cl.stats[STAT_ITEMS] & IT_ROCKETS) - pic = sb_ammo[2]; - else if (cl.stats[STAT_ITEMS] & IT_CELLS) - pic = sb_ammo[3]; - - view_t ammo = View_GetChild (view, 0); - if (pic) { - sbar_setcomponent (ammo, hud_pic, &pic); - } else { - sbar_remcomponent (ammo, hud_pic); - } - - view_t num[3] = { - View_GetChild (view, 1), - View_GetChild (view, 2), - View_GetChild (view, 3), - }; - draw_num (num, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); -} - -static int -calc_flashon (float time, int mask) -{ - int flashon; - - flashon = (int) ((cl.time - time) * 10); - if (flashon < 0) - flashon = 0; - if (flashon >= 10) { - if (cl.stats[STAT_ACTIVEWEAPON] == mask) - flashon = 1; - else - flashon = 0; - } else - flashon = (flashon % 5) + 2; - return flashon; -} - -static void -draw_weapons_sbar (view_t view) -{ - int flashon, i; - - for (i = 0; i < 7; i++) { - view_t weap = View_GetChild (view, i); - if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { - flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); - if (flashon > 1) - sb_updates = 0; // force update to remove flash - sbar_setcomponent (weap, hud_pic, &sb_weapons[flashon][i]); - } else { - sbar_remcomponent (weap, hud_pic); - } - } -} - -static void -draw_items (view_t view) -{ - //float time; - //int flashon = 0, i; - - for (int i = 0; i < 6; i++) { - view_t item = View_GetChild (view, i); - if (cl.stats[STAT_ITEMS] & (1 << (17 + i))) { -#if 0 - time = cl.item_gettime[17 + i]; - if (time && time > cl.time - 2 && flashon) { // Flash frame - sb_updates = 0; - } else { - draw_pic (view, i * 16, 0, sb_items[i]); - } - if (time && time > cl.time - 2) - sb_updates = 0; -#endif - sbar_setcomponent (item, hud_pic, &sb_items[i]); - } else { - sbar_remcomponent (item, hud_pic); - } - } -} - -static void -draw_sigils (view_t view) -{ - //float time; - //int flashon = 0, i; - - for (int i = 0; i < 4; i++) { - view_t sigil = View_GetChild (view, i); - if (cl.stats[STAT_ITEMS] & (1 << (28 + i))) { -#if 0 - time = cl.item_gettime[28 + i]; - if (time && time > cl.time - 2 && flashon) { // flash frame - sb_updates = 0; - } else { - draw_pic (view, i * 8, 0, sb_sigil[i]); - } - if (time && time > cl.time - 2) - sb_updates = 0; -#endif - sbar_setcomponent (sigil, hud_pic, &sb_sigil[i]); - } else { - sbar_remcomponent (sigil, hud_pic); - } - } -} -#if 0 -static void -draw_inventory_sbar (view_t *view) -{ - if (cl.spectator && autocam == CAM_TRACK) { - if (sbar_frags_view) - sbar_frags_view->draw (sbar_frags_view); - return; - } - draw_pic (view, 0, 0, sb_ibar); - view_draw (view); -} -#endif -typedef struct { - char team[16 + 1]; - int frags; - int players; - int plow, phigh, ptotal; -} team_t; - -team_t teams[MAX_CLIENTS]; -int teamsort[MAX_CLIENTS]; -int fragsort[MAX_CLIENTS]; // ZOID changed this from [MAX_SCOREBOARD] -int scoreboardlines, scoreboardteams; - -static void -Sbar_SortFrags (qboolean includespec) -{ - int i, j, k; - - // sort by frags - scoreboardlines = 0; - for (i = 0; i < MAX_CLIENTS; i++) { - if (cl.players[i].name && cl.players[i].name->value[0] - && (!cl.players[i].spectator || includespec)) { - fragsort[scoreboardlines] = i; - scoreboardlines++; - if (cl.players[i].spectator) - cl.players[i].frags = -999; - } - } - - for (i = 0; i < scoreboardlines; i++) { - for (j = 0; j < scoreboardlines - 1 - i; j++) { - if (cl.players[fragsort[j]].frags < - cl.players[fragsort[j + 1]].frags) { - k = fragsort[j]; - fragsort[j] = fragsort[j + 1]; - fragsort[j + 1] = k; - } - } - } -} - -static void __attribute__((used)) -Sbar_SortTeams (void) -{ - char t[16 + 1]; - int i, j, k; - player_info_t *s; - - // request new ping times every two second - scoreboardteams = 0; - - if (!cl.teamplay) - return; - - // sort the teams - memset (teams, 0, sizeof (teams)); - for (i = 0; i < MAX_CLIENTS; i++) - teams[i].plow = 999; - - for (i = 0; i < MAX_CLIENTS; i++) { - s = &cl.players[i]; - if (!s->name || !s->name->value[0]) - continue; - if (s->spectator) - continue; - - // find his team in the list - t[16] = 0; - strncpy (t, s->team->value, 16); - if (!t[0]) - continue; // not on team - for (j = 0; j < scoreboardteams; j++) - if (!strcmp (teams[j].team, t)) { - teams[j].frags += s->frags; - teams[j].players++; - goto addpinginfo; - } - if (j == scoreboardteams) { // must add him - j = scoreboardteams++; - strcpy (teams[j].team, t); - teams[j].frags = s->frags; - teams[j].players = 1; - addpinginfo: - if (teams[j].plow > s->ping) - teams[j].plow = s->ping; - if (teams[j].phigh < s->ping) - teams[j].phigh = s->ping; - teams[j].ptotal += s->ping; - } - } - - // sort - for (i = 0; i < scoreboardteams; i++) - teamsort[i] = i; - - // good 'ol bubble sort - for (i = 0; i < scoreboardteams - 1; i++) { - for (j = i + 1; j < scoreboardteams; j++) { - if (teams[teamsort[i]].frags < teams[teamsort[j]].frags) { - k = teamsort[i]; - teamsort[i] = teamsort[j]; - teamsort[j] = k; - } - } - } -} - -static void __attribute__((used)) -draw_solo (view_t *view) -{ -#if 0 - char str[80]; - int minutes, seconds; - - draw_pic (view, 0, 0, sb_scorebar); - - minutes = cl.time / 60; - seconds = cl.time - 60 * minutes; - snprintf (str, sizeof (str), "Time :%3i:%02i", minutes, seconds); - draw_string (view, 184, 4, str); -#endif -} - -static inline void -dmo_ping (view_t *view, int x, int y, player_info_t *s) -{ -#if 0 - int p; - - p = s->ping; - if (p < 0 || p > 999) - p = 999; - draw_smallnum (view, x + 8, y, p, 0, 0); -#endif -} - -static inline void -dmo_uid (view_t *view, int x, int y, player_info_t *s) -{ -#if 0 - char num[12]; - int p; - - p = s->userid; - snprintf (num, sizeof (num), "%4i", p); - draw_string (view, x, y, num); -#endif -} - -static inline void -dmo_pl (view_t *view, int x, int y, player_info_t *s) -{ -#if 0 - int p; - - // draw pl - p = s->pl; - draw_smallnum (view, x, y, p, 0, p > 25); -#endif -} - -static inline int -calc_fph (int frags, int total) -{ -#if 0 - int fph; - - if (total != 0) { - fph = (3600 * frags) / total; - - if (fph >= 999) - fph = 999; - else if (fph <= -999) - fph = -999; - } else { - fph = 0; - } - - return fph; -#endif - return 0; -} - -static inline void -dmo_main (view_t *view, int x, int y, player_info_t *s, int is_client) -{ -#if 0 - char num[12]; - int fph, minutes, total, top, bottom, f; - - // get time - if (cl.intermission) - total = cl.completed_time - s->entertime; - else - total = realtime - s->entertime; - minutes = total / 60; - - // get frags - f = s->frags; - - // draw fph - fph = calc_fph (f, total); - snprintf (num, sizeof (num), "%3i", fph); - draw_string (view, x, y, num); - - //draw time - snprintf (num, sizeof (num), "%4i", minutes); - draw_string (view, x + 32, y, num); - - // draw background - top = Sbar_ColorForMap (s->topcolor); - bottom = Sbar_ColorForMap (s->bottomcolor); - if (largegame) - draw_fill (view, x + 72, y + 1, 40, 3, top); - else - draw_fill (view, x + 72, y, 40, 4, top); - draw_fill (view, x + 72, y + 4, 40, 4, bottom); - - // draw frags - if (!is_client) { - snprintf (num, sizeof (num), " %3i ", f); - } else { - snprintf (num, sizeof (num), "\x10%3i\x11", f); - } - draw_nstring (view, x + 72, y, num, 5); -#endif -} - -static inline void -dmo_team (view_t *view, int x, int y, player_info_t *s) -{ -#if 0 - draw_nstring (view, x, y, s->team->value, 4); -#endif -} - -static inline void -dmo_name (view_t *view, int x, int y, player_info_t *s) -{ -#if 0 - draw_string (view, x, y, s->name->value); -#endif -} - -static void -draw_frags (view_t view) -{ -#if 0 - int i, k, l, p = -1; - int top, bottom; - int x; - player_info_t *s; - - Sbar_SortFrags (false); - - // draw the text - l = scoreboardlines <= 4 ? scoreboardlines : 4; - - x = 0; - - for (i = 0; i < l; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - if (s->spectator) - continue; - - // draw background - top = Sbar_ColorForMap (top); - bottom = Sbar_ColorForMap (bottom); - - draw_fill (view, x + 4, 1, 28, 4, top); - draw_fill (view, x + 4, 5, 28, 3, bottom); - - draw_smallnum (view, x + 6, 0, s->frags, 0, 0); - - if (k == cl.playernum) - p = i; - - x += 32; - } - if (p != -1) { - draw_character (view, p * 32, 0, 16); - draw_character (view, p * 32 + 26, 0, 17); - } -#endif -} - -static void -draw_face (view_t view) -{ -#if 0 - int f, anim; - - if ((cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY)) - == (IT_INVISIBILITY | IT_INVULNERABILITY)) { - draw_pic (view, 112, 0, sb_face_invis_invuln); - return; - } - if (cl.stats[STAT_ITEMS] & IT_QUAD) { - draw_pic (view, 112, 0, sb_face_quad); - return; - } - if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) { - draw_pic (view, 112, 0, sb_face_invis); - return; - } - if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { - draw_pic (view, 112, 0, sb_face_invuln); - return; - } - - if (cl.stats[STAT_HEALTH] >= 100) - f = 4; - else - f = cl.stats[STAT_HEALTH] / 20; - - if (cl.time <= cl.faceanimtime) { - anim = 1; - sb_updates = 0; // make sure the anim gets drawn over - } else - anim = 0; - draw_pic (view, 112, 0, sb_faces[f][anim]); -#endif -} - -static void __attribute__((used)) -draw_spectator (view_t *view) -{ -#if 0 - char st[512]; - - if (autocam != CAM_TRACK) { - draw_string (view, 160 - 7 * 8, 4, "SPECTATOR MODE"); - draw_string (view, 160 - 14 * 8 + 4, 12, - "Press [ATTACK] for AutoCamera"); - } else { -// Sbar_DrawString (160-14*8+4,4, "SPECTATOR MODE - TRACK CAMERA"); - if (cl.players[spec_track].name) { - snprintf (st, sizeof (st), "Tracking %-.13s, [JUMP] for next", - cl.players[spec_track].name->value); - } else { - snprintf (st, sizeof (st), "Lost player, [JUMP] for next"); - } - draw_string (view, 0, -8, st); - } -#endif -} - -static inline void -draw_armor (view_t view) -{ - view_t armor = View_GetChild (view, 0); - view_t num[3] = { - View_GetChild (view, 1), - View_GetChild (view, 2), - View_GetChild (view, 3), - }; - if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { - draw_num (num, 666, 3, 1); - } else { - draw_num (num, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25); - if (cl.stats[STAT_ITEMS] & IT_ARMOR3) - sbar_setcomponent (armor, hud_pic, &sb_armor[2]); - else if (cl.stats[STAT_ITEMS] & IT_ARMOR2) - sbar_setcomponent (armor, hud_pic, &sb_armor[1]); - else if (cl.stats[STAT_ITEMS] & IT_ARMOR1) - sbar_setcomponent (armor, hud_pic, &sb_armor[0]); - else - sbar_remcomponent (armor, hud_pic); - } -} -#if 0 -static void -draw_status_bar (view_t *view) -{ - if (cl.spectator && autocam != CAM_TRACK) - draw_pic (view, 0, 0, sb_scorebar); - else - draw_pic (view, 0, 0, sb_sbar); -} -#endif -static inline void -draw_health (view_t view) -{ - view_t num[3] = { - View_GetChild (view, 0), - View_GetChild (view, 1), - View_GetChild (view, 2), - }; - draw_num (num, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25); -} -#if 0 -static void -draw_status (view_t *view) -{ - if (cl.spectator) { - draw_spectator (view); - if (autocam != CAM_TRACK) - return; - } - if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { - draw_solo (view); - return; - } - - draw_armor (view); - draw_face (view); - draw_health (view); - draw_ammo (view); -} -#endif -/* - Sbar_DeathmatchOverlay - - ping time frags name -*/ -static void -Sbar_DeathmatchOverlay (view_t *view, int start) -{ -#if 0 - int l, y; - int skip = 10; - - if (cl_screen_view->xlen < 244) // FIXME: magic number, gained through experimentation - return; - - if (largegame) - skip = 8; - - // request new ping times every two second - if (realtime - cl.last_ping_request > 2.0) { - cl.last_ping_request = realtime; - if (!cls.demoplayback) { - MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, "pings"); - } - } - - r_data->scr_copyeverything = 1; - r_data->scr_fullupdate = 0; - - if (!start) { - draw_cachepic (view, 0, 0, "gfx/ranking.lmp", 1); - y = 24; - } else - y = start; - - // scores - Sbar_SortFrags (true); - - // draw the text - l = scoreboardlines; - - // func ptr, avoids absurd if testing - Sbar_Draw_DMO_func (view, l, y, skip); - - if (y >= view->ylen - 10) // we ran over the screen size, squish - largegame = true; -#endif -} - -/* - Sbar_TeamOverlay - - team frags - added by Zoid -*/ -static void -Sbar_TeamOverlay (view_t *view) -{ -#if 0 - char num[20]; - int pavg, plow, phigh, i, k, x, y; - team_t *tm; - info_key_t *player_team = cl.players[cl.playernum].team; - - if (!cl.teamplay) { // FIXME: if not teamplay, why teamoverlay? - Sbar_DeathmatchOverlay (view, 0); - return; - } - - r_data->scr_copyeverything = 1; - r_data->scr_fullupdate = 0; - - draw_cachepic (view, 0, 0, "gfx/ranking.lmp", 1); - - y = 24; - x = 36; - draw_string (view, x, y, "low/avg/high team total players"); - y += 8; - draw_string (view, x, y, "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1e\x1e\x1f"); - y += 8; - - // sort the teams - Sbar_SortTeams (); - - // draw the text - for (i = 0; i < scoreboardteams && y <= view->ylen - 10; i++) { - k = teamsort[i]; - tm = teams + k; - - // draw pings - plow = tm->plow; - if (plow < 0 || plow > 999) - plow = 999; - phigh = tm->phigh; - if (phigh < 0 || phigh > 999) - phigh = 999; - if (!tm->players) - pavg = 999; - else - pavg = tm->ptotal / tm->players; - if (pavg < 0 || pavg > 999) - pavg = 999; - - snprintf (num, sizeof (num), "%3i/%3i/%3i", plow, pavg, phigh); - draw_string (view, x, y, num); - - // draw team - draw_nstring (view, x + 104, y, tm->team, 4); - - // draw total - snprintf (num, sizeof (num), "%5i", tm->frags); - draw_string (view, x + 104 + 40, y, num); - - // draw players - snprintf (num, sizeof (num), "%5i", tm->players); - draw_string (view, x + 104 + 88, y, num); - - if (player_team && strnequal (player_team->value, tm->team, 16)) { - draw_character (view, x + 104 - 8, y, 16); - draw_character (view, x + 104 + 32, y, 17); - } - - y += 8; - } - y += 8; - Sbar_DeathmatchOverlay (view, y); -#endif -} - -static void -draw_overlay (view_t *view) -{ - if (cls.state != ca_active - || !((cl.stats[STAT_HEALTH] <= 0 && !cl.spectator) - || sb_showscores || sb_showteamscores)) - return; - // main screen deathmatch rankings - // if we're dead show team scores in team games - if (cl.stats[STAT_HEALTH] <= 0 && !cl.spectator) - if (cl.teamplay > 0 && !sb_showscores) - Sbar_TeamOverlay (view); - else - Sbar_DeathmatchOverlay (view, 0); - else if (sb_showscores) - Sbar_DeathmatchOverlay (view, 0); - else if (sb_showteamscores) - Sbar_TeamOverlay (view); -} - -static void -sbar_update_vis (void) -{ -#if 0 - qboolean headsup; - - if (r_data->scr_copyeverything) - Sbar_Changed (); - - sbar_view->visible = 0; - - headsup = !(hud_sbar || sb_view_size < 100); - - if ((sb_updates >= r_data->vid->numpages) && !headsup) - return; - - if (con_module && con_module->data->console->lines == cl_screen_view->ylen) - return; // console is full screen - - if (!hud_sb_lines) - return; - - sbar_view->visible = 1; - - r_data->scr_copyeverything = 1; - sb_updates++; - - if (sb_showscores || sb_showteamscores || cl.stats[STAT_HEALTH] <= 0) - sb_updates = 0; -#endif -} - -/* - Sbar_LogFrags - - autologging of frags after a match ended - (called by recived network packet with command scv_intermission) - TODO: Find a new and better place for this function - (i am nearly shure this is wrong place) - added by Elmex -*/ -void -Sbar_LogFrags (void) -{ - char *name; - char *team; - byte *cp = NULL; - QFile *file = NULL; - int minutes, fph, total, d, f, i, k, l, p; - player_info_t *s = NULL; - const char *t = NULL; - time_t tt = time (NULL); - - if (!cl_fraglog) - return; - - if ((file = QFS_Open (fs_fraglog, "a")) == NULL) - return; - - t = ctime (&tt); - if (t) - Qwrite (file, t, strlen (t)); - - Qprintf (file, "%s\n%s %s\n", cls.servername->str, - cl_world.scene->worldmodel->path, cl.levelname); - - // scores - Sbar_SortFrags (true); - - // draw the text - l = scoreboardlines; - - if (cl.teamplay) { - // TODO: test if the teamplay does correct output - Qwrite (file, "pl fph time frags team name\n", - strlen ("pl fph time frags team name\n")); - } else { - Qwrite (file, "pl fph time frags name\n", - strlen ("pl fph time frags name\n")); - } - - for (i = 0; i < l; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - // draw pl - p = s->pl; - (void) p; //FIXME - - // get time - if (cl.intermission) - total = cl.completed_time - s->entertime; - else - total = realtime - s->entertime; - minutes = total / 60; - - // get frags - f = s->frags; - - fph = calc_fph (f, total); - - name = malloc (strlen (s->name->value) + 1); - for (cp = (byte *) s->name->value, d = 0; *cp; cp++, d++) - name[d] = sys_char_map[*cp]; - name[d] = 0; - - if (s->spectator) { - Qprintf (file, "%-3i%% %s (spectator)", s->pl, name); - } else { - if (cl.teamplay) { - team = malloc (strlen (s->team->value) + 1); - for (cp = (byte *) s->team, d = 0; *cp; cp++, d++) - team[d] = sys_char_map[*cp]; - team[d] = 0; - - Qprintf (file, "%-3i%% %-3i %-4i %-3i %-4s %s", - s->pl, fph, minutes, f, team, name); - free (team); - } else { - Qprintf (file, "%-3i%% %-3i %-4i %-3i %s", - s->pl, fph, minutes, f, name); - } - } - free (name); - Qwrite (file, "\n\n", 1); - } - - Qclose (file); -} - -static void __attribute__((used)) -Sbar_Draw_DMO_Team_Ping (view_t *view, int l, int y, int skip) -{ -#if 0 - int i, k, x; - player_info_t *s; - - x = 4; -// 0 40 64 104 152 192 224 - draw_string (view, x, y, "ping pl fph time frags team name"); - y += 8; - draw_string (view, x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); - y += 8; - - for (i = 0; i < l && y <= view->ylen - 10; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - dmo_ping (view, x + 0, y, s); - dmo_pl (view, x + 32, y, s); - - if (s->spectator) { - draw_string (view, x + 72, y, "(spectator)"); - dmo_name (view, x + 224, y, s); - y += skip; - continue; - } - - dmo_main (view, x + 64, y, s, k == cl.playernum); - dmo_team (view, x + 184, y, s); - dmo_name (view, x + 224, y, s); - - y += skip; - } -#endif -} - -static void __attribute__((used)) -Sbar_Draw_DMO_Team_UID (view_t *view, int l, int y, int skip) -{ -#if 0 - int i, k, x; - player_info_t *s; - - x = 4; -// 0 40 64 104 152 192 - draw_string (view, x, y, " uid pl fph time frags team name"); - y += 8; - draw_string (view, x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); - y += 8; - - for (i = 0; i < l && y <= view->ylen - 10; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - dmo_uid (view, x + 0, y, s); - dmo_ping (view, x + 32, y, s); - - if (s->spectator) { - draw_string (view, x + 72, y, "(spectator)"); - dmo_name (view, x + 224, y, s); - y += skip; - continue; - } - - dmo_main (view, x + 64, y, s, k == cl.playernum); - dmo_team (view, x + 184, y, s); - dmo_name (view, x + 224, y, s); - - y += skip; - } -#endif -} - -static void __attribute__((used)) -Sbar_Draw_DMO_Team_Ping_UID (view_t *view, int l, int y, int skip) -{ -#if 0 - int i, k, x; - player_info_t *s; - - x = 4; -// 0 40 64 104 152 192 - draw_string (view, x, y, "ping pl fph time frags team uid name"); - y += 8; - draw_string (view, x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); - y += 8; - - for (i = 0; i < l && y <= view->ylen - 10; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - dmo_ping (view, x + 0, y, s); - dmo_pl (view, x + 32, y, s); - - if (s->spectator) { - draw_string (view, x + 72, y, "(spectator)"); - dmo_uid (view, x + 224, y, s); - dmo_name (view, x + 264, y, s); - y += skip; - continue; - } - - dmo_main (view, x + 64, y, s, k == cl.playernum); - dmo_team (view, x + 184, y, s); - dmo_uid (view, x + 224, y, s); - dmo_name (view, x + 264, y, s); - - y += skip; - } -#endif -} - -static void __attribute__((used)) -Sbar_Draw_DMO_Ping (view_t *view, int l, int y, int skip) -{ -#if 0 - int i, k, x; - player_info_t *s; - - x = 16; -// 0 40 64 104 152 - draw_string (view, x, y, "ping pl fph time frags name"); - y += 8; - draw_string (view, x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1e\x1e\x1e" - "\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); - y += 8; - - for (i = 0; i < l && y <= view->ylen - 10; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - dmo_ping (view, x + 0, y, s); - dmo_pl (view, x + 32, y, s); - - if (s->spectator) { - draw_string (view, x + 72, y, "(spectator)"); - dmo_name (view, x + 184, y, s); - y += skip; - continue; - } - - dmo_main (view, x + 64, y, s, k == cl.playernum); - dmo_name (view, x + 184, y, s); - - y += skip; - } -#endif -} - -static void __attribute__((used)) -Sbar_Draw_DMO_UID (view_t *view, int l, int y, int skip) -{ -#if 0 - int i, k, x; - player_info_t *s; - - x = 16; - draw_string (view, x, y, " uid pl fph time frags name"); - y += 8; - draw_string (view, x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1e\x1e\x1e" - "\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); - y += 8; - - for (i = 0; i < l && y <= view->ylen - 10; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - dmo_uid (view, x + 0, y, s); - dmo_pl (view, x + 32, y, s); - - if (s->spectator) { - draw_string (view, x + 72, y, "(spectator)"); - dmo_name (view, x + 184, y, s); - y += skip; - continue; - } - - dmo_main (view, x + 64, y, s, k == cl.playernum); - dmo_name (view, x + 184, y, s); - - y += skip; - } -#endif -} - -static void __attribute__((used)) -Sbar_Draw_DMO_Ping_UID (view_t *view, int l, int y, int skip) -{ -#if 0 - int i, k, x; - player_info_t *s; - - x = 16; - draw_string (view, x, y, "ping pl fph time frags uid name"); - y += 8; - draw_string (view, x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1e\x1e\x1e" - "\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); - y += 8; - - for (i = 0; i < l && y <= view->ylen - 10; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - dmo_ping (view, x + 0, y, s); - dmo_pl (view, x + 32, y, s); - - if (s->spectator) { - draw_string (view, x + 72, y, "(spectator)"); - dmo_name (view, x + 184, y, s); - y += skip; - continue; - } - - dmo_main (view, x + 64, y, s, k == cl.playernum); - dmo_uid (view, x + 184, y, s); - dmo_name (view, x + 224, y, s); - - y += skip; - } -#endif -} - -void -Sbar_DMO_Init_f (void *data, const cvar_t *cvar) -{ -#if 0 - if (cl.teamplay) - if (hud_scoreboard_uid > 1) - Sbar_Draw_DMO_func = Sbar_Draw_DMO_Team_Ping_UID; - else if (hud_scoreboard_uid > 0) - Sbar_Draw_DMO_func = Sbar_Draw_DMO_Team_UID; - else - Sbar_Draw_DMO_func = Sbar_Draw_DMO_Team_Ping; - else - if (hud_scoreboard_uid > 1) - Sbar_Draw_DMO_func = Sbar_Draw_DMO_Ping_UID; - else if (hud_scoreboard_uid > 0) - Sbar_Draw_DMO_func = Sbar_Draw_DMO_UID; - else - Sbar_Draw_DMO_func = Sbar_Draw_DMO_Ping; -#endif -} - -/* - draw_minifrags - - frags name - frags team name - displayed to right of status bar if there's room -*/ -static void -draw_minifrags (view_t *view) -{ -#if 0 - int numlines, top, bottom, f, i, k, x, y; - char num[20]; - player_info_t *s; - - r_data->scr_copyeverything = 1; - r_data->scr_fullupdate = 0; - - // scores - Sbar_SortFrags (false); - - if (!scoreboardlines) - return; // no one there? - - numlines = view->ylen / 8; - if (numlines < 3) - return; // not enough room - - // find us - for (i = 0; i < scoreboardlines; i++) - if (fragsort[i] == cl.playernum) - break; - - if (i == scoreboardlines) // we're not there, we are probably a - // spectator, just display top - i = 0; - else // figure out start - i = i - numlines / 2; - - if (i > scoreboardlines - numlines) - i = scoreboardlines - numlines; - if (i < 0) - i = 0; - - x = 4; - y = 0; - - for (; i < scoreboardlines && y < view->ylen - 8 + 1; i++) { - k = fragsort[i]; - s = &cl.players[k]; - if (!s->name || !s->name->value[0]) - continue; - - // draw ping - top = s->topcolor; - bottom = s->bottomcolor; - top = Sbar_ColorForMap (top); - bottom = Sbar_ColorForMap (bottom); - - draw_fill (view, x + 2, y + 1, 37, 3, top); - draw_fill (view, x + 2, y + 4, 37, 4, bottom); - - // draw number - f = s->frags; - if (k != cl.playernum) { - snprintf (num, sizeof (num), " %3i ", f); - } else { - snprintf (num, sizeof (num), "\x10%3i\x11", f); - } - - draw_nstring (view, x, y, num, 5); - - // team - if (cl.teamplay) { - draw_nstring (view, x + 48, y, s->team->value, 4); - draw_nstring (view, x + 48 + 40, y, s->name->value, 16); - } else - draw_nstring (view, x + 48, y, s->name->value, 16); - y += 8; - } -#endif -} - -static void -draw_miniteam (view_t *view) -{ -#if 0 - int i, k, x, y; - char num[12]; - info_key_t *player_team = cl.players[cl.playernum].team; - team_t *tm; - - if (!cl.teamplay) - return; - Sbar_SortTeams (); - - x = 0; - y = 0; - for (i = 0; i < scoreboardteams && y <= view->ylen; i++) { - k = teamsort[i]; - tm = teams + k; - - // draw pings - draw_nstring (view, x, y, tm->team, 4); - // draw total - snprintf (num, sizeof (num), "%5i", tm->frags); - draw_string (view, x + 40, y, num); - - if (player_team && strnequal (player_team->value, tm->team, 16)) { - draw_character (view, x - 8, y, 16); - draw_character (view, x + 32, y, 17); - } - - y += 8; - } -#endif -} - -static void -draw_time (view_t *view) -{ -#if 0 - struct tm *local = 0; - time_t utc = 0; - char st[80]; - - // Get local time - utc = time (0); - local = localtime (&utc); - -#if defined(_WIN32) || defined(_WIN64) -# define HOUR12 "%I" -# define HOUR24 "%H" -# define PM "%p" -#else -# define HOUR12 "%l" -# define HOUR24 "%k" -# define PM "%P" -#endif - if (hud_time == 1) { // Use international format - strftime (st, sizeof (st), HOUR24":%M", local); - draw_string (view, 8, 0, st); - } else if (hud_time >= 2) { // US AM/PM display - strftime (st, sizeof (st), HOUR12":%M "PM, local); - draw_string (view, 8, 0, st); - } -#endif -} - -static void -draw_fps (view_t *view) -{ -#if 0 - static char st[80]; - double t; - static double lastframetime; - static double lastfps; - - t = Sys_DoubleTime (); - if ((t - lastframetime) >= 0.2) { - lastfps = fps_count / (t - lastframetime); - fps_count = 0; - lastframetime = t; - snprintf (st, sizeof (st), "%5.1f FPS", lastfps); - } - draw_string (view, 80, 8, st); -#endif -} - -static void -draw_net (view_t *view) -{ -#if 0 - // request new ping times every two seconds - if (!cls.demoplayback && realtime - cl.last_ping_request > 2) { - cl.last_ping_request = realtime; - MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, "pings"); - } - if (hud_ping) { - int ping = cl.players[cl.playernum].ping; - - ping = bound (0, ping, 999); - draw_string (view, 0, 0, va (0, "%3d ms ", ping)); - } - - if (hud_ping && hud_pl) - draw_character (view, 48, 0, '/'); - - if (hud_pl) { - int lost = CL_CalcNet (); - - lost = bound (0, lost, 999); - draw_string (view, 56, 0, va (0, "%3d pl", lost)); - } -#endif -} - -static void -draw_stuff (view_t *view) -{ - if (hud_time > 0) - draw_time (view); - if (hud_fps > 0) - draw_fps (view); - if (cls.state == ca_active && (hud_ping || hud_pl)) - draw_net (view); -} - -#if 0 -void -Sbar_IntermissionOverlay (void) -{ - r_data->scr_copyeverything = 1; - r_data->scr_fullupdate = 0; - - if (cl.teamplay > 0 && !sb_showscores) - Sbar_TeamOverlay (hud_overlay_view); - else - Sbar_DeathmatchOverlay (hud_overlay_view, 0); -} -#endif - -/* CENTER PRINTING */ -static dstring_t center_string = {&dstring_default_mem}; -static float centertime_start; // for slow victory printing -static float centertime_off; -static int center_lines; - -/* - Called for important messages that should stay in the center of the screen - for a few moments -*/ -void -Sbar_CenterPrint (const char *str) -{ - if (!str) { - centertime_off = 0; - dstring_clearstr (¢er_string); - return; - } - - dstring_copystr (¢er_string, str); - - centertime_off = scr_centertime; - centertime_start = realtime; - - // count the number of lines for centering - center_lines = 1; - while (*str) { - if (*str == '\n') - center_lines++; - str++; - } -} - -static void __attribute__((used)) -Sbar_DrawCenterString (view_t *view, int remaining) -{ -#if 0 - const char *start; - int j, l, x, y; - - start = center_string.str; - - if (center_lines <= 4) - y = view->yabs + view->ylen * 0.35; - else - y = view->yabs + 48; - - do { - // scan the width of the line - for (l = 0; l < 40; l++) - if (start[l] == '\n' || !start[l]) - break; - x = view->xabs + (view->xlen - l * 8) / 2; - for (j = 0; j < l; j++, x += 8) { - r_funcs->Draw_Character (x, y, start[j]); - if (!remaining--) - return; - } - - y += 8; - - while (*start && *start != '\n') - start++; - if (!*start) - break; - start++; // skip the \n - } while (1); -#endif -} - -void -Sbar_FinaleOverlay (void) -{ -#if 0 - int remaining; - - r_data->scr_copyeverything = 1; - - draw_cachepic (hud_overlay_view, 0, 16, "gfx/finale.lmp", 1); - // the finale prints the characters one at a time - remaining = scr_printspeed * (realtime - centertime_start); - Sbar_DrawCenterString (hud_overlay_view, remaining); -#endif -} - -void -Sbar_DrawCenterPrint (void) -{ -#if 0 - r_data->scr_copytop = 1; - - centertime_off -= r_data->frametime; - if (centertime_off <= 0) - return; - - Sbar_DrawCenterString (hud_overlay_view, -1); -#endif -} - -void -Sbar_Draw (void) -{ - if (cls.state != ca_active) { - return; - } - sb_update_flags = ~0; - if (sb_update_flags & (1 << sbc_ammo)) { - draw_miniammo (sbar_miniammo); - draw_ammo (sbar_ammo); - } - if (sb_update_flags & (1 << sbc_armor)) draw_armor (sbar_armor); - if (sb_update_flags & (1 << sbc_frags)) draw_frags (sbar_frags); - if (sb_update_flags & (1 << sbc_health)) draw_health (sbar_health); - if (sb_update_flags & (1 << sbc_info)) { - draw_miniteam (0); - draw_minifrags (0); - draw_stuff (0); - draw_overlay (0); - //draw_intermission (0); - Sbar_DeathmatchOverlay (0, 0); - sbar_update_vis (); - } - if (sb_update_flags & (1 << sbc_items)) { - draw_items (sbar_items); - draw_sigils (sbar_items); - } - if (sb_update_flags & (1 << sbc_weapon)) draw_weapons_sbar (sbar_weapons); - if (sb_update_flags & ((1 << sbc_health) | (1 << sbc_items))) { - draw_face (sbar_face); - } -#if 0 - sbar_update_vis (); - hud_main_view->draw (hud_main_view); -#endif - sb_update_flags = 0; -} - -static void -init_sbar_views (void) -{ -#if 0 - view_t *view; - view_t *minifrags_view = 0; - view_t *miniteam_view = 0; - - if (cl_screen_view->xlen < 512) { - sbar_view = view_new (0, 0, 320, 48, grav_south); - - sbar_frags_view = view_new (0, 0, 130, 8, grav_northeast); - sbar_frags_view->draw = draw_frags; - } else if (cl_screen_view->xlen < 640) { - sbar_view = view_new (0, 0, 512, 48, grav_south); - minifrags_view = view_new (320, 0, 192, 48, grav_southwest); - minifrags_view->draw = draw_minifrags; - minifrags_view->resize_y = 1; - - view = view_new (0, 0, 192, 48, grav_southeast); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); - } else { - sbar_view = view_new (0, 0, 640, 48, grav_south); - minifrags_view = view_new (320, 0, 192, 48, grav_southwest); - minifrags_view->draw = draw_minifrags; - minifrags_view->resize_y = 1; - miniteam_view = view_new (0, 0, 96, 48, grav_southeast); - miniteam_view->draw = draw_miniteam; - miniteam_view->resize_y = 1; - - view = view_new (0, 0, 320, 48, grav_southeast); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); - } - - sbar_inventory_view = view_new (0, 0, 320, 24, grav_northwest); - sbar_inventory_view->draw = draw_inventory_sbar; - - view = view_new (0, 0, 32, 16, grav_southwest); - view->draw = draw_weapons_sbar; - view_add (sbar_inventory_view, view); - - view = view_new (0, 0, 32, 8, grav_northwest); - view->draw = draw_ammo_sbar; - view_add (sbar_inventory_view, view); - - view = view_new (32, 0, 96, 16, grav_southeast); - view->draw = draw_items; - view_add (sbar_inventory_view, view); - - view = view_new (0, 0, 32, 16, grav_southeast); - view->draw = draw_sigils; - view_add (sbar_inventory_view, view); - - if (sbar_frags_view) - view_add (sbar_inventory_view, sbar_frags_view); - - view_add (sbar_view, sbar_inventory_view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_status_bar; - view_add (sbar_view, view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_status; - view_add (sbar_view, view); - - if (minifrags_view) - view_add (sbar_view, minifrags_view); - if (miniteam_view) - view_add (sbar_view, miniteam_view); - - if (cl_screen_view->xlen > 640) { - int l = (cl_screen_view->xlen - 640) / 2; - - view = view_new (-l, 0, l, 48, grav_southwest); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); - - view = view_new (-l, 0, l, 48, grav_southeast); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); - } -#endif - sbar_main = sbar_view ( 0, 0, 320, 48, grav_south, cl_screen_view); - sbar_inventory = sbar_view ( 0, 0, 320, 24, grav_northwest, sbar_main); - sbar_frags = sbar_view ( 0, 0, 130, 8, grav_northeast, sbar_inventory); - sbar_sigils = sbar_view ( 0, 0, 32, 16, grav_southeast, sbar_inventory); - sbar_items = sbar_view (32, 0, 96, 16, grav_southeast, sbar_inventory); - sbar_armament = sbar_view ( 0, 0, 202, 24, grav_northwest, sbar_inventory); - sbar_weapons = sbar_view ( 0, 0, 192, 16, grav_southwest, sbar_armament); - sbar_miniammo = sbar_view ( 0, 0, 32, 8, grav_northwest, sbar_armament); - sbar_statusbar = sbar_view ( 0, 0, 320, 24, grav_southwest, sbar_main); - sbar_armor = sbar_view ( 0, 0, 96, 24, grav_northwest, sbar_statusbar); - sbar_face = sbar_view (112, 0, 24, 24, grav_northwest, sbar_statusbar); - sbar_health = sbar_view (136, 0, 72, 24, grav_northwest, sbar_statusbar); - sbar_ammo = sbar_view (224, 0, 96, 24, grav_northwest, sbar_statusbar); - sbar_tile[0] = sbar_view ( 0, 0, 0, 48, grav_southwest, sbar_main); - sbar_tile[1] = sbar_view ( 0, 0, 0, 48, grav_southeast, sbar_main); - - for (int i = 0; i < 4; i++) { - sbar_view (i * 8, 0, 8, 16, grav_northwest, sbar_sigils); - - sbar_view (i * 24, 0, 24, 24, grav_northwest, sbar_armor); - sbar_view (i * 24, 0, 24, 24, grav_northwest, sbar_ammo); - } - for (int i = 0; i < 6; i++) { - sbar_view (i * 16, 0, 16, 16, grav_northwest, sbar_items); - } - for (int i = 0; i < 7; i++) { - sbar_view (i * 24, 0, 24, 16, grav_northwest, sbar_weapons); - } - for (int i = 0; i < 4; i++) { - sbar_view (i * 24, 0, 24, 16, grav_northwest, sbar_health); - } - for (int i = 0; i < 4; i++) { - view_t v = sbar_view (i * 48 + 10, 0, 8, 8, grav_northwest, - sbar_miniammo); - draw_charbuffer_t *buffer = Draw_CreateBuffer (3, 1); - sbar_setcomponent (v, hud_charbuff, &buffer); - } - - sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar); - sbar_setcomponent (sbar_statusbar, hud_pic, &sb_sbar); - - if (r_data->vid->width > 320) { - int l = (r_data->vid->width - 320) / 2; - View_SetPos (sbar_tile[0], -l, 0); - View_SetLen (sbar_tile[0], l, 48); - View_SetPos (sbar_tile[1], -l, 0); - View_SetLen (sbar_tile[1], l, 48); - sbar_setcomponent (sbar_tile[0], hud_tile, 0); - sbar_setcomponent (sbar_tile[1], hud_tile, 0); - } -} - -static void -init_hud_views (void) -{ -#if 0 - view_t *view; - view_t *minifrags_view = 0; - view_t *miniteam_view = 0; - - if (cl_screen_view->xlen < 512) { - hud_view = view_new (0, 0, 320, 48, grav_south); - - hud_frags_view = view_new (0, 0, 130, 8, grav_northeast); - hud_frags_view->draw = draw_frags; - } else if (cl_screen_view->xlen < 640) { - hud_view = view_new (0, 0, 512, 48, grav_south); - - minifrags_view = view_new (320, 0, 192, 48, grav_southwest); - minifrags_view->draw = draw_minifrags; - minifrags_view->resize_y = 1; - } else { - hud_view = view_new (0, 0, 640, 48, grav_south); - - minifrags_view = view_new (320, 0, 192, 48, grav_southwest); - minifrags_view->draw = draw_minifrags; - minifrags_view->resize_y = 1; - - miniteam_view = view_new (0, 0, 96, 48, grav_southeast); - miniteam_view->draw = draw_miniteam; - miniteam_view->resize_y = 1; - } - hud_view->resize_y = 1; - - hud_armament_view = view_new (0, 48, 42, 156, grav_southeast); - - view = view_new (0, 0, 42, 44, grav_northeast); - view->draw = draw_weapons_hud; - view_add (hud_armament_view, view); - - view = view_new (0, 0, 42, 44, grav_southeast); - view->draw = draw_ammo_hud; - view_add (hud_armament_view, view); - - hud_inventory_view = view_new (0, 0, 320, 24, grav_northwest); - view_add (hud_view, hud_inventory_view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_status; - view_add (hud_view, view); - - view = view_new (32, 0, 96, 16, grav_southeast); - view->draw = draw_items; - view_add (hud_inventory_view, view); - - view = view_new (0, 0, 32, 16, grav_southeast); - view->draw = draw_sigils; - view_add (hud_inventory_view, view); - - if (hud_frags_view) - view_add (hud_inventory_view, hud_frags_view); - - if (minifrags_view) - view_add (hud_view, minifrags_view); - if (miniteam_view) - view_add (hud_view, miniteam_view); - - view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); - view->resize_x = 1; - view_add (view, hud_view); - hud_view = view; - - view_add (hud_view, hud_armament_view); - - view_insert (hud_main_view, hud_view, 0); -#endif -} - -static void -init_views (void) -{ -#if 0 - hud_main_view = view_new (0, 0, cl_screen_view->xlen, cl_screen_view->ylen, - grav_northwest); - view_insert (cl_screen_view, hud_main_view, 0); - hud_main_view->resize_x = 1; // get resized if the 2d view resizes - hud_main_view->resize_y = 1; - hud_main_view->visible = 0; // but don't let the console draw our stuff - if (cl_screen_view->ylen > 300) - hud_overlay_view = view_new (0, 0, 320, 300, grav_center); - else - hud_overlay_view = view_new (0, 0, 320, cl_screen_view->ylen, - grav_center); - hud_overlay_view->draw = draw_overlay; - hud_overlay_view->visible = 0; - - hud_stuff_view = view_new (0, 48, 152, 16, grav_southwest); - hud_stuff_view->draw = draw_stuff; - - view_insert (hud_main_view, hud_overlay_view, 0); - view_insert (hud_main_view, hud_stuff_view, 0); -#endif - init_sbar_views (); - init_hud_views (); -} - -static void -Sbar_GIB_Print_Center_f (void) -{ - if (GIB_Argc () != 2) { - GIB_USAGE ("text"); - } else - Sbar_CenterPrint (GIB_Argv(1)); -} - -static void -load_pics (void) -{ - for (int i = 0; i < 10; i++) { - sb_nums[0][i] = r_funcs->Draw_PicFromWad (va (0, "num_%i", i)); - sb_nums[1][i] = r_funcs->Draw_PicFromWad (va (0, "anum_%i", i)); - } - - sb_nums[0][10] = r_funcs->Draw_PicFromWad ("num_minus"); - sb_nums[1][10] = r_funcs->Draw_PicFromWad ("anum_minus"); - - sb_colon = r_funcs->Draw_PicFromWad ("num_colon"); - sb_slash = r_funcs->Draw_PicFromWad ("num_slash"); - - sb_weapons[0][0] = r_funcs->Draw_PicFromWad ("inv_shotgun"); - sb_weapons[0][1] = r_funcs->Draw_PicFromWad ("inv_sshotgun"); - sb_weapons[0][2] = r_funcs->Draw_PicFromWad ("inv_nailgun"); - sb_weapons[0][3] = r_funcs->Draw_PicFromWad ("inv_snailgun"); - sb_weapons[0][4] = r_funcs->Draw_PicFromWad ("inv_rlaunch"); - sb_weapons[0][5] = r_funcs->Draw_PicFromWad ("inv_srlaunch"); - sb_weapons[0][6] = r_funcs->Draw_PicFromWad ("inv_lightng"); - - sb_weapons[1][0] = r_funcs->Draw_PicFromWad ("inv2_shotgun"); - sb_weapons[1][1] = r_funcs->Draw_PicFromWad ("inv2_sshotgun"); - sb_weapons[1][2] = r_funcs->Draw_PicFromWad ("inv2_nailgun"); - sb_weapons[1][3] = r_funcs->Draw_PicFromWad ("inv2_snailgun"); - sb_weapons[1][4] = r_funcs->Draw_PicFromWad ("inv2_rlaunch"); - sb_weapons[1][5] = r_funcs->Draw_PicFromWad ("inv2_srlaunch"); - sb_weapons[1][6] = r_funcs->Draw_PicFromWad ("inv2_lightng"); - - for (int i = 0; i < 5; i++) { - sb_weapons[2 + i][0] = r_funcs->Draw_PicFromWad (va (0, - "inva%i_shotgun", - i + 1)); - sb_weapons[2 + i][1] = r_funcs->Draw_PicFromWad (va (0, - "inva%i_sshotgun", - i + 1)); - sb_weapons[2 + i][2] = r_funcs->Draw_PicFromWad (va (0, - "inva%i_nailgun", - i + 1)); - sb_weapons[2 + i][3] = r_funcs->Draw_PicFromWad (va (0, - "inva%i_snailgun", - i + 1)); - sb_weapons[2 + i][4] = r_funcs->Draw_PicFromWad (va (0, - "inva%i_rlaunch", - i + 1)); - sb_weapons[2 + i][5] = r_funcs->Draw_PicFromWad (va (0, - "inva%i_srlaunch", - i + 1)); - sb_weapons[2 + i][6] = r_funcs->Draw_PicFromWad (va (0, - "inva%i_lightng", - i + 1)); - } - - sb_ammo[0] = r_funcs->Draw_PicFromWad ("sb_shells"); - sb_ammo[1] = r_funcs->Draw_PicFromWad ("sb_nails"); - sb_ammo[2] = r_funcs->Draw_PicFromWad ("sb_rocket"); - sb_ammo[3] = r_funcs->Draw_PicFromWad ("sb_cells"); - - sb_armor[0] = r_funcs->Draw_PicFromWad ("sb_armor1"); - sb_armor[1] = r_funcs->Draw_PicFromWad ("sb_armor2"); - sb_armor[2] = r_funcs->Draw_PicFromWad ("sb_armor3"); - - sb_items[0] = r_funcs->Draw_PicFromWad ("sb_key1"); - sb_items[1] = r_funcs->Draw_PicFromWad ("sb_key2"); - sb_items[2] = r_funcs->Draw_PicFromWad ("sb_invis"); - sb_items[3] = r_funcs->Draw_PicFromWad ("sb_invuln"); - sb_items[4] = r_funcs->Draw_PicFromWad ("sb_suit"); - sb_items[5] = r_funcs->Draw_PicFromWad ("sb_quad"); - - sb_sigil[0] = r_funcs->Draw_PicFromWad ("sb_sigil1"); - sb_sigil[1] = r_funcs->Draw_PicFromWad ("sb_sigil2"); - sb_sigil[2] = r_funcs->Draw_PicFromWad ("sb_sigil3"); - sb_sigil[3] = r_funcs->Draw_PicFromWad ("sb_sigil4"); - - sb_faces[4][0] = r_funcs->Draw_PicFromWad ("face1"); - sb_faces[4][1] = r_funcs->Draw_PicFromWad ("face_p1"); - sb_faces[3][0] = r_funcs->Draw_PicFromWad ("face2"); - sb_faces[3][1] = r_funcs->Draw_PicFromWad ("face_p2"); - sb_faces[2][0] = r_funcs->Draw_PicFromWad ("face3"); - sb_faces[2][1] = r_funcs->Draw_PicFromWad ("face_p3"); - sb_faces[1][0] = r_funcs->Draw_PicFromWad ("face4"); - sb_faces[1][1] = r_funcs->Draw_PicFromWad ("face_p4"); - sb_faces[0][0] = r_funcs->Draw_PicFromWad ("face5"); - sb_faces[0][1] = r_funcs->Draw_PicFromWad ("face_p5"); - - sb_face_invis = r_funcs->Draw_PicFromWad ("face_invis"); - sb_face_invuln = r_funcs->Draw_PicFromWad ("face_invul2"); - sb_face_invis_invuln = r_funcs->Draw_PicFromWad ("face_inv2"); - sb_face_quad = r_funcs->Draw_PicFromWad ("face_quad"); - - sb_sbar = r_funcs->Draw_PicFromWad ("sbar"); - sb_ibar = r_funcs->Draw_PicFromWad ("ibar"); - sb_scorebar = r_funcs->Draw_PicFromWad ("scorebar"); -} - -void -Sbar_Init (void) -{ - load_pics (); - init_views (); - View_UpdateHierarchy (sbar_main); - - Cmd_AddCommand ("+showscores", Sbar_ShowScores, - "Display information on everyone playing"); - Cmd_AddCommand ("-showscores", Sbar_DontShowScores, - "Stop displaying information on everyone playing"); - Cmd_AddCommand ("+showteamscores", Sbar_ShowTeamScores, - "Display information for your team"); - Cmd_AddCommand ("-showteamscores", Sbar_DontShowTeamScores, - "Stop displaying information for your team"); - - r_data->viewsize_callback = viewsize_f; - - HUD_Init_Cvars (); - - Cvar_Register (&hud_scoreboard_uid_cvar, Sbar_DMO_Init_f, 0); - Cvar_Register (&fs_fraglog_cvar, 0, 0); - Cvar_Register (&cl_fraglog_cvar, 0, 0); - Cvar_Register (&scr_centertime_cvar, 0, 0); - Cvar_Register (&scr_printspeed_cvar, 0, 0); - - // register GIB builtins - GIB_Builtin_Add ("print::center", Sbar_GIB_Print_Center_f); -} From 73e62de2fb8ba57b05f5ee03fc1dfe26262823a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Nov 2022 12:50:05 +0900 Subject: [PATCH 3168/3664] [client] Clean up sbar's globals access I had forgotten that the cl structs in nq and qw were different layouts, which resulted in qw's sbar/hud being quite broken. Rather than messing with the structs, I decided it would be far better in the long run to clean up sbar's access to the cl struct and the few other nq/qw specific globals it used. There are still plenty of bugs to fix, but now almost everything is in the one place. --- include/gamedefs.h | 117 ++++++++++ include/qw/bothdefs.h | 64 +---- include/qw/protocol.h | 4 +- include/sbar.h | 21 +- libs/client/cl_screen.c | 1 - libs/client/sbar.c | 388 ++++++++++++++++++------------- libs/video/renderer/gl/gl_draw.c | 1 - nq/include/game.h | 88 +------ nq/source/cl_main.c | 11 +- nq/source/cl_parse.c | 14 +- qw/source/cl_main.c | 12 +- qw/source/cl_parse.c | 7 +- 12 files changed, 385 insertions(+), 343 deletions(-) create mode 100644 include/gamedefs.h diff --git a/include/gamedefs.h b/include/gamedefs.h new file mode 100644 index 000000000..633c67570 --- /dev/null +++ b/include/gamedefs.h @@ -0,0 +1,117 @@ +/* + gamedefs.h + + Game specific definitions + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __gamedefs_h +#define __gamedefs_h + +#define MAX_PLAYERS 32 // maximum players supported by the engine (esp sbar) + +// stats are integers communicated to the client by the server +#define MAX_CL_STATS 32 +#define STAT_HEALTH 0 +#define STAT_FRAGS 1 +#define STAT_WEAPON 2 +#define STAT_AMMO 3 +#define STAT_ARMOR 4 +#define STAT_WEAPONFRAME 5 +#define STAT_SHELLS 6 +#define STAT_NAILS 7 +#define STAT_ROCKETS 8 +#define STAT_CELLS 9 +#define STAT_ACTIVEWEAPON 10 +#define STAT_TOTALSECRETS 11 +#define STAT_TOTALMONSTERS 12 +#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret +#define STAT_MONSTERS 14 // bumped by svc_killedmonster +#define STAT_ITEMS 15 +#define STAT_VIEWHEIGHT 16 +#define STAT_FLYMODE 17 + +// stock defines +#define IT_SHOTGUN 1 +#define IT_SUPER_SHOTGUN 2 +#define IT_NAILGUN 4 +#define IT_SUPER_NAILGUN 8 +#define IT_GRENADE_LAUNCHER 16 +#define IT_ROCKET_LAUNCHER 32 +#define IT_LIGHTNING 64 +#define IT_SUPER_LIGHTNING 128 +#define IT_SHELLS 256 +#define IT_NAILS 512 +#define IT_ROCKETS 1024 +#define IT_CELLS 2048 +#define IT_AXE 4096 +#define IT_ARMOR1 8192 +#define IT_ARMOR2 16384 +#define IT_ARMOR3 32768 +#define IT_SUPERHEALTH 65536 +#define IT_KEY1 131072 +#define IT_KEY2 262144 +#define IT_INVISIBILITY 524288 +#define IT_INVULNERABILITY 1048576 +#define IT_SUIT 2097152 +#define IT_QUAD 4194304 +#define IT_SIGIL1 (1<<28) +#define IT_SIGIL2 (1<<29) +#define IT_SIGIL3 (1<<30) +#define IT_SIGIL4 (1<<31) + +//rogue changed and added defines +#define RIT_SHELLS 128 +#define RIT_NAILS 256 +#define RIT_ROCKETS 512 +#define RIT_CELLS 1024 +#define RIT_AXE 2048 +#define RIT_LAVA_NAILGUN 4096 +#define RIT_LAVA_SUPER_NAILGUN 8192 +#define RIT_MULTI_GRENADE 16384 +#define RIT_MULTI_ROCKET 32768 +#define RIT_PLASMA_GUN 65536 +#define RIT_ARMOR1 8388608 +#define RIT_ARMOR2 16777216 +#define RIT_ARMOR3 33554432 +#define RIT_LAVA_NAILS 67108864 +#define RIT_PLASMA_AMMO 134217728 +#define RIT_MULTI_ROCKETS 268435456 +#define RIT_SHIELD 536870912 +#define RIT_ANTIGRAV 1073741824 +#define RIT_SUPERHEALTH 2147483648 + +//MED 01/04/97 added hipnotic defines +//hipnotic added defines +#define HIT_PROXIMITY_GUN_BIT 16 +#define HIT_MJOLNIR_BIT 7 +#define HIT_LASER_CANNON_BIT 23 +#define HIT_PROXIMITY_GUN (1<= vid.numpages, no update needed static int sb_update_flags; static int sb_view_size; +static int fps_count; +static const char *sbar_levelname; +static const char *sbar_servername; +static player_info_t *sbar_players; +static int *sbar_stats; +static float *sbar_item_gettime; +static double sbar_time; +static double sbar_completed_time; +static double sbar_faceanimtime; +static int sbar_maxplayers; +static int sbar_playernum; +static int sbar_viewplayer; +static int sbar_spectator; +static int sbar_teamplay; +static int sbar_active; +static int sbar_intermission; static view_t intermission_view; static view_t intermission_time; @@ -411,7 +428,7 @@ draw_miniammo (view_t view) // ammo counts for (i = 0; i < 4; i++) { view_t v = View_GetChild (view, i); - count = cl.stats[STAT_SHELLS + i]; + count = sbar_stats[STAT_SHELLS + i]; draw_smallnum (v, count, 0, 1); } } @@ -420,13 +437,13 @@ static void draw_ammo (view_t view) { qpic_t *pic = 0; - if (cl.stats[STAT_ITEMS] & IT_SHELLS) + if (sbar_stats[STAT_ITEMS] & IT_SHELLS) pic = sb_ammo[0]; - else if (cl.stats[STAT_ITEMS] & IT_NAILS) + else if (sbar_stats[STAT_ITEMS] & IT_NAILS) pic = sb_ammo[1]; - else if (cl.stats[STAT_ITEMS] & IT_ROCKETS) + else if (sbar_stats[STAT_ITEMS] & IT_ROCKETS) pic = sb_ammo[2]; - else if (cl.stats[STAT_ITEMS] & IT_CELLS) + else if (sbar_stats[STAT_ITEMS] & IT_CELLS) pic = sb_ammo[3]; view_t ammo = View_GetChild (view, 0); @@ -441,7 +458,7 @@ draw_ammo (view_t view) View_GetChild (view, 2), View_GetChild (view, 3), }; - draw_num (num, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); + draw_num (num, sbar_stats[STAT_AMMO], 3, sbar_stats[STAT_AMMO] <= 10); } static int @@ -449,11 +466,11 @@ calc_flashon (float time, int mask) { int flashon; - flashon = (int) ((cl.time - time) * 10); + flashon = (int) ((sbar_time - time) * 10); if (flashon < 0) flashon = 0; if (flashon >= 10) { - if (cl.stats[STAT_ACTIVEWEAPON] == mask) + if (sbar_stats[STAT_ACTIVEWEAPON] == mask) flashon = 1; else flashon = 0; @@ -469,8 +486,8 @@ draw_weapons (view_t view) for (i = 0; i < 7; i++) { view_t weap = View_GetChild (view, i); - if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { - flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); + if (sbar_stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { + flashon = calc_flashon (sbar_item_gettime[i], IT_SHOTGUN << i); if (flashon > 1) sb_updates = 0; // force update to remove flash sbar_setcomponent (weap, hud_subpic, &sb_weapons[flashon][i]); @@ -488,15 +505,15 @@ draw_items (view_t view) for (int i = 0; i < 6; i++) { view_t item = View_GetChild (view, i); - if (cl.stats[STAT_ITEMS] & (1 << (17 + i))) { + if (sbar_stats[STAT_ITEMS] & (1 << (17 + i))) { #if 0 - time = cl.item_gettime[17 + i]; - if (time && time > cl.time - 2 && flashon) { // Flash frame + time = sbar_item_gettime[17 + i]; + if (time && time > sbar_time - 2 && flashon) { // Flash frame sb_updates = 0; } else { draw_pic (view, i * 16, 0, sb_items[i]); } - if (time && time > cl.time - 2) + if (time && time > sbar_time - 2) sb_updates = 0; #endif sbar_setcomponent (item, hud_pic, &sb_items[i]); @@ -514,15 +531,15 @@ draw_sigils (view_t view) for (int i = 0; i < 4; i++) { view_t sigil = View_GetChild (view, i); - if (cl.stats[STAT_ITEMS] & (1 << (28 + i))) { + if (sbar_stats[STAT_ITEMS] & (1 << (28 + i))) { #if 0 - time = cl.item_gettime[28 + i]; - if (time && time > cl.time - 2 && flashon) { // flash frame + time = sbar_item_gettime[28 + i]; + if (time && time > sbar_time - 2 && flashon) { // flash frame sb_updates = 0; } else { draw_pic (view, i * 8, 0, sb_sigil[i]); } - if (time && time > cl.time - 2) + if (time && time > sbar_time - 2) sb_updates = 0; #endif sbar_setcomponent (sigil, hud_pic, &sb_sigil[i]); @@ -539,19 +556,19 @@ typedef struct { int plow, phigh, ptotal; } team_t; -team_t teams[MAX_CLIENTS]; -int teamsort[MAX_CLIENTS]; -int fragsort[MAX_CLIENTS]; -static view_t sb_views[MAX_CLIENTS]; -static draw_charbuffer_t *sb_fph[MAX_CLIENTS]; -static draw_charbuffer_t *sb_time[MAX_CLIENTS]; -static draw_charbuffer_t *sb_frags[MAX_CLIENTS]; -static draw_charbuffer_t *sb_team[MAX_CLIENTS]; -static draw_charbuffer_t *sb_ping[MAX_CLIENTS]; -static draw_charbuffer_t *sb_pl[MAX_CLIENTS]; -static draw_charbuffer_t *sb_uid[MAX_CLIENTS]; -static draw_charbuffer_t *sb_name[MAX_CLIENTS]; -static draw_charbuffer_t *sb_team_frags[MAX_CLIENTS]; +team_t teams[MAX_PLAYERS]; +int teamsort[MAX_PLAYERS]; +int fragsort[MAX_PLAYERS]; +static view_t sb_views[MAX_PLAYERS]; +static draw_charbuffer_t *sb_fph[MAX_PLAYERS]; +static draw_charbuffer_t *sb_time[MAX_PLAYERS]; +static draw_charbuffer_t *sb_frags[MAX_PLAYERS]; +static draw_charbuffer_t *sb_team[MAX_PLAYERS]; +static draw_charbuffer_t *sb_ping[MAX_PLAYERS]; +static draw_charbuffer_t *sb_pl[MAX_PLAYERS]; +static draw_charbuffer_t *sb_uid[MAX_PLAYERS]; +static draw_charbuffer_t *sb_name[MAX_PLAYERS]; +static draw_charbuffer_t *sb_team_frags[MAX_PLAYERS]; static draw_charbuffer_t *sb_spectator; int scoreboardlines, scoreboardteams; @@ -562,20 +579,20 @@ Sbar_SortFrags (qboolean includespec) // sort by frags scoreboardlines = 0; - for (i = 0; i < cl.maxclients; i++) { - if (cl.players[i].name && cl.players[i].name->value[0] - && (!cl.players[i].spectator || includespec)) { + for (i = 0; i < sbar_maxplayers; i++) { + if (sbar_players[i].name && sbar_players[i].name->value[0] + && (!sbar_players[i].spectator || includespec)) { fragsort[scoreboardlines] = i; scoreboardlines++; - if (cl.players[i].spectator) - cl.players[i].frags = -999; + if (sbar_players[i].spectator) + sbar_players[i].frags = -999; } } - for (i = scoreboardlines; i < cl.maxclients; i++) { + for (i = scoreboardlines; i < sbar_maxplayers; i++) { fragsort[i] = -1; } - player_info_t *p = cl.players; + player_info_t *p = sbar_players; for (i = 0; i < scoreboardlines; i++) { for (j = 0; j < scoreboardlines - 1 - i; j++) { if (p[fragsort[j]].frags < p[fragsort[j + 1]].frags) { @@ -597,16 +614,16 @@ Sbar_SortTeams (void) // request new ping times every two second scoreboardteams = 0; - if (!cl.teamplay) + if (!sbar_teamplay) return; // sort the teams memset (teams, 0, sizeof (teams)); - for (i = 0; i < MAX_CLIENTS; i++) + for (i = 0; i < MAX_PLAYERS; i++) teams[i].plow = 999; - for (i = 0; i < MAX_CLIENTS; i++) { - s = &cl.players[i]; + for (i = 0; i < MAX_PLAYERS; i++) { + s = &sbar_players[i]; if (!s->name || !s->name->value[0]) continue; if (s->spectator) @@ -673,8 +690,8 @@ write_charbuff (draw_charbuffer_t *buffer, int x, int y, const char *str) static void draw_solo_time (void) { - int minutes = cl.time / 60; - int seconds = cl.time - 60 * minutes; + int minutes = sbar_time / 60; + int seconds = sbar_time - 60 * minutes; write_charbuff (solo_time, 0, 0, va (0, "Time :%3i:%02i", minutes, seconds)); } @@ -684,13 +701,13 @@ draw_solo (void) { write_charbuff (solo_monsters, 0, 0, va (0, "Monsters:%3i /%3i", - cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS])); + sbar_stats[STAT_MONSTERS], sbar_stats[STAT_TOTALMONSTERS])); write_charbuff (solo_secrets, 0, 0, va (0, "Secrets :%3i /%3i", - cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS])); + sbar_stats[STAT_SECRETS], sbar_stats[STAT_TOTALSECRETS])); draw_solo_time (); view_pos_t len = View_GetLen (sbar_solo_name); - len.x = 8 * write_charbuff (solo_name, 0, 0, cl.levelname); + len.x = 8 * write_charbuff (solo_name, 0, 0, sbar_levelname); View_SetLen (sbar_solo_name, len.x, len.y); } @@ -753,7 +770,7 @@ frags_marker (view_pos_t pos, view_pos_t len) static void draw_frags (view_t view) { - if (cl.maxclients == 1) { + if (sbar_maxplayers == 1) { return; } Sbar_SortFrags (0); @@ -764,13 +781,13 @@ draw_frags (view_t view) for (i = 0; i < count; i++) { int k = fragsort[i]; - __auto_type s = &cl.players[k]; + __auto_type s = &sbar_players[k]; view_t bar = View_GetChild (view, i); set_frags_bar (bar, Sbar_ColorForMap (s->topcolor), Sbar_ColorForMap (s->bottomcolor), sb_frags[k], - (k == cl.viewentity - 1) ? frags_marker : 0); + (k == sbar_viewplayer) ? frags_marker : 0); draw_smallnum (View_GetChild (bar, 2), s->frags, 0, 0); } for (; i < numbars; i++) { @@ -781,7 +798,7 @@ draw_frags (view_t view) static void draw_minifrags (view_t view) { - if (cl.maxclients == 1) { + if (sbar_maxplayers == 1) { return; } Sbar_SortFrags (0); @@ -793,7 +810,7 @@ draw_minifrags (view_t view) int i; for (i = 0; i < scoreboardlines; i++) { - if (fragsort[i] == cl.playernum) { + if (fragsort[i] == sbar_playernum) { start = min (i - numbars / 2, scoreboardlines - numbars); start = max (0, start); } @@ -803,16 +820,16 @@ draw_minifrags (view_t view) for (i = 0; i < count; i++) { int k = fragsort[i + start]; - __auto_type s = &cl.players[k]; + __auto_type s = &sbar_players[k]; view_t bar = View_GetChild (view, i); set_minifrags_bar (bar, Sbar_ColorForMap (s->topcolor), Sbar_ColorForMap (s->bottomcolor), sb_frags[k], - (k == cl.viewentity - 1) ? frags_marker : 0, - cl.teamplay ? sb_team[k] : 0, + (k == sbar_viewplayer) ? frags_marker : 0, + sbar_teamplay ? sb_team[k] : 0, sb_name[k]); - if (cl.teamplay) { + if (sbar_teamplay) { write_charbuff (sb_team[k], 0, 0, s->team->value); } write_charbuff (sb_name[k], 0, 0, s->name->value); @@ -847,7 +864,7 @@ set_miniteam_bar (view_t view, draw_charbuffer_t *team, static void draw_miniteam (view_t view) { - if (!cl.teamplay) { + if (!sbar_teamplay) { return; } Sbar_SortTeams (); @@ -856,12 +873,12 @@ draw_miniteam (view_t view) int numbars = len.y / 8; int count = min (scoreboardteams, numbars); int i; - info_key_t *player_team = cl.players[cl.playernum].team; + info_key_t *player_team = sbar_players[sbar_playernum].team; for (i = 0; i < count; i++) { int k = teamsort[i]; team_t *tm = teams + k; - __auto_type s = &cl.players[k]; + __auto_type s = &sbar_players[k]; view_t bar = View_GetChild (view, i); hud_func_f func = 0; if (player_team && strnequal (player_team->value, tm->team, 16)) { @@ -881,28 +898,28 @@ draw_face (view_t view) { qpic_t *face; - if (cl.stats[STAT_HEALTH] <= 0) {//FIXME hide_Face or hide_sbar + if (sbar_stats[STAT_HEALTH] <= 0) {//FIXME hide_Face or hide_sbar sbar_remcomponent (sbar_face, hud_pic); return; } - if ((cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY)) + if ((sbar_stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY)) == (IT_INVISIBILITY | IT_INVULNERABILITY)) { face = sb_face_invis_invuln; - } else if (cl.stats[STAT_ITEMS] & IT_QUAD) { + } else if (sbar_stats[STAT_ITEMS] & IT_QUAD) { face = sb_face_quad; - } else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) { + } else if (sbar_stats[STAT_ITEMS] & IT_INVISIBILITY) { face = sb_face_invis; - } else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { + } else if (sbar_stats[STAT_ITEMS] & IT_INVULNERABILITY) { face = sb_face_invuln; } else { int f, anim; - if (cl.stats[STAT_HEALTH] >= 100) { + if (sbar_stats[STAT_HEALTH] >= 100) { f = 4; } else { - f = cl.stats[STAT_HEALTH] / 20; + f = sbar_stats[STAT_HEALTH] / 20; } - if (cl.time <= cl.faceanimtime) { + if (sbar_time <= sbar_faceanimtime) { anim = 1; sb_updates = 0; // make sure the anim gets drawn over } else { @@ -925,9 +942,9 @@ draw_spectator (view_t *view) "Press [ATTACK] for AutoCamera"); } else { // Sbar_DrawString (160-14*8+4,4, "SPECTATOR MODE - TRACK CAMERA"); - if (cl.players[spec_track].name) { + if (sbar_players[spec_track].name) { snprintf (st, sizeof (st), "Tracking %-.13s, [JUMP] for next", - cl.players[spec_track].name->value); + sbar_players[spec_track].name->value); } else { snprintf (st, sizeof (st), "Lost player, [JUMP] for next"); } @@ -945,15 +962,15 @@ draw_armor (view_t view) View_GetChild (view, 2), View_GetChild (view, 3), }; - if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) { + if (sbar_stats[STAT_ITEMS] & IT_INVULNERABILITY) { draw_num (num, 666, 3, 1); } else { - draw_num (num, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25); - if (cl.stats[STAT_ITEMS] & IT_ARMOR3) + draw_num (num, sbar_stats[STAT_ARMOR], 3, sbar_stats[STAT_ARMOR] <= 25); + if (sbar_stats[STAT_ITEMS] & IT_ARMOR3) sbar_setcomponent (armor, hud_pic, &sb_armor[2]); - else if (cl.stats[STAT_ITEMS] & IT_ARMOR2) + else if (sbar_stats[STAT_ITEMS] & IT_ARMOR2) sbar_setcomponent (armor, hud_pic, &sb_armor[1]); - else if (cl.stats[STAT_ITEMS] & IT_ARMOR1) + else if (sbar_stats[STAT_ITEMS] & IT_ARMOR1) sbar_setcomponent (armor, hud_pic, &sb_armor[0]); else sbar_remcomponent (armor, hud_pic); @@ -968,18 +985,18 @@ draw_health (view_t view) View_GetChild (view, 1), View_GetChild (view, 2), }; - draw_num (num, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25); + draw_num (num, sbar_stats[STAT_HEALTH], 3, sbar_stats[STAT_HEALTH] <= 25); } #if 0 static void draw_status (view_t *view) { - if (cl.spectator) { + if (sbar_spectator) { draw_spectator (view); if (autocam != CAM_TRACK) return; } - if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { + if (sb_showscores || sbar_stats[STAT_HEALTH] <= 0) { draw_solo (view); return; } @@ -1000,9 +1017,9 @@ draw_rogue_weapons_sbar (view_t *view) draw_weapons_sbar (view); // check for powered up weapon. - if (cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) { + if (sbar_stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) { for (i = 0; i < 5; i++) { - if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i)) { + if (sbar_stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i)) { draw_pic (view, (i + 2) * 24, 0, rsb_weapons[i]); } } @@ -1018,11 +1035,11 @@ draw_rogue_weapons_hud (view_t *view) qpic_t *pic; for (i = cl_screen_view->ylen < 204; i < 7; i++) { - if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { - flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i); + if (sbar_stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { + flashon = calc_flashon (sbar_item_gettime[i], IT_SHOTGUN << i); if (i >= 2) { j = i - 2; - if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << j)) + if (sbar_stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << j)) pic = rsb_weapons[j]; else pic = sb_weapons[flashon][i]; @@ -1044,13 +1061,13 @@ draw_rogue_ammo_hud (view_t *view) int i, count; qpic_t *pic; - if (cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) + if (sbar_stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) pic = rsb_invbar[0]; else pic = rsb_invbar[1]; for (i = 0; i < 4; i++) { - count = cl.stats[STAT_SHELLS + i]; + count = sbar_stats[STAT_SHELLS + i]; draw_subpic (view, 0, i * 11, pic, 3 + (i * 48), 0, 42, 11); draw_smallnum (view, 7, i * 11, count, 0, 1); } @@ -1067,10 +1084,10 @@ draw_rogue_items (view_t *view) draw_items (view); for (i = 0; i < 2; i++) { - if (cl.stats[STAT_ITEMS] & (1 << (29 + i))) { - time = cl.item_gettime[29 + i]; + if (sbar_stats[STAT_ITEMS] & (1 << (29 + i))) { + time = sbar_item_gettime[29 + i]; draw_pic (view, 96 + i * 16, 0, rsb_items[i]); - if (time && time > (cl.time - 2)) + if (time && time > (sbar_time - 2)) sb_updates = 0; } } @@ -1081,7 +1098,7 @@ static void __attribute__((used)) draw_rogue_inventory_sbar (view_t *view) { #if 0 - if (cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) + if (sbar_stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) draw_pic (view, 0, 0, rsb_invbar[0]); else draw_pic (view, 0, 0, rsb_invbar[1]); @@ -1099,7 +1116,7 @@ draw_rogue_face (view_t *view) // PGM 01/19/97 - team color drawing - s = &cl.players[cl.viewentity - 1]; + s = &sbar_players[sbar_viewplayer]; top = Sbar_ColorForMap (s->topcolor); bottom = Sbar_ColorForMap (s->bottomcolor); @@ -1116,43 +1133,43 @@ static void __attribute__((used)) draw_rogue_status (view_t *view) { #if 0 - if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { + if (sb_showscores || sbar_stats[STAT_HEALTH] <= 0) { draw_solo (view); return; } - draw_num (view, 24, 0, cl.stats[STAT_ARMOR], 3, - cl.stats[STAT_ARMOR] <= 25); - if (cl.stats[STAT_ITEMS] & RIT_ARMOR3) + draw_num (view, 24, 0, sbar_stats[STAT_ARMOR], 3, + sbar_stats[STAT_ARMOR] <= 25); + if (sbar_stats[STAT_ITEMS] & RIT_ARMOR3) draw_pic (view, 0, 0, sb_armor[2]); - else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2) + else if (sbar_stats[STAT_ITEMS] & RIT_ARMOR2) draw_pic (view, 0, 0, sb_armor[1]); - else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1) + else if (sbar_stats[STAT_ITEMS] & RIT_ARMOR1) draw_pic (view, 0, 0, sb_armor[0]); // PGM 03/02/97 - fixed so color swatch appears in only CTF modes - if (cl.maxclients != 1 && teamplay > 3 && teamplay < 7) + if (sbar_maxplayers != 1 && teamplay > 3 && teamplay < 7) draw_rogue_face (view); else draw_face (view); draw_health (view); - if (cl.stats[STAT_ITEMS] & RIT_SHELLS) + if (sbar_stats[STAT_ITEMS] & RIT_SHELLS) draw_pic (view, 224, 0, sb_ammo[0]); - else if (cl.stats[STAT_ITEMS] & RIT_NAILS) + else if (sbar_stats[STAT_ITEMS] & RIT_NAILS) draw_pic (view, 224, 0, sb_ammo[1]); - else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS) + else if (sbar_stats[STAT_ITEMS] & RIT_ROCKETS) draw_pic (view, 224, 0, sb_ammo[2]); - else if (cl.stats[STAT_ITEMS] & RIT_CELLS) + else if (sbar_stats[STAT_ITEMS] & RIT_CELLS) draw_pic (view, 224, 0, sb_ammo[3]); - else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS) + else if (sbar_stats[STAT_ITEMS] & RIT_LAVA_NAILS) draw_pic (view, 224, 0, rsb_ammo[0]); - else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO) + else if (sbar_stats[STAT_ITEMS] & RIT_PLASMA_AMMO) draw_pic (view, 224, 0, rsb_ammo[1]); - else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS) + else if (sbar_stats[STAT_ITEMS] & RIT_MULTI_ROCKETS) draw_pic (view, 224, 0, rsb_ammo[2]); - draw_num (view, 248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10); + draw_num (view, 248, 0, sbar_stats[STAT_AMMO], 3, sbar_stats[STAT_AMMO] <= 10); #endif } @@ -1170,17 +1187,17 @@ draw_hipnotic_weapons_sbar (view_t *view) for (i = 0; i < 10; i++) { if (i < 7) { mask = IT_SHOTGUN << i; - time = cl.item_gettime[i]; + time = sbar_item_gettime[i]; } else { mask = 1 << hipweapons[h[i - 7]]; - time = cl.item_gettime[hipweapons[h[i - 7]]]; + time = sbar_item_gettime[hipweapons[h[i - 7]]]; } - if (cl.stats[STAT_ITEMS] & mask) { + if (sbar_stats[STAT_ITEMS] & mask) { flashon = calc_flashon (time, mask); - if (i == 4 && cl.stats[STAT_ACTIVEWEAPON] == (1 << hipweapons[3])) + if (i == 4 && sbar_stats[STAT_ACTIVEWEAPON] == (1 << hipweapons[3])) continue; - if (i == 9 && cl.stats[STAT_ACTIVEWEAPON] != (1 << hipweapons[3])) + if (i == 9 && sbar_stats[STAT_ACTIVEWEAPON] != (1 << hipweapons[3])) continue; if (i < 7) { pic = sb_weapons[flashon][i]; @@ -1211,12 +1228,12 @@ draw_hipnotic_weapons_hud (view_t *view) for (i = 0; i < 10; i++) { if (i < 7) { mask = IT_SHOTGUN << i; - time = cl.item_gettime[i]; + time = sbar_item_gettime[i]; } else { mask = 1 << hipweapons[h[i - 7]]; - time = cl.item_gettime[hipweapons[h[i - 7]]]; + time = sbar_item_gettime[hipweapons[h[i - 7]]]; } - if (cl.stats[STAT_ITEMS] & mask) { + if (sbar_stats[STAT_ITEMS] & mask) { flashon = calc_flashon (time, mask); if (i < 7) { @@ -1243,20 +1260,20 @@ draw_hipnotic_items (view_t *view) // items for (i = 2; i < 6; i++) { - if (cl.stats[STAT_ITEMS] & (1 << (17 + i))) { - time = cl.item_gettime[17 + i]; + if (sbar_stats[STAT_ITEMS] & (1 << (17 + i))) { + time = sbar_item_gettime[17 + i]; draw_pic (view, 192 + i * 16, 0, sb_items[i]); - if (time && time > cl.time - 2) + if (time && time > sbar_time - 2) sb_updates = 0; } } // hipnotic items for (i = 0; i < 2; i++) { - if (cl.stats[STAT_ITEMS] & (1 << (24 + i))) { - time = cl.item_gettime[24 + i]; + if (sbar_stats[STAT_ITEMS] & (1 << (24 + i))) { + time = sbar_item_gettime[24 + i]; draw_pic (view, 288 + i * 16, 0, hsb_items[i]); - if (time && time > (cl.time - 2)) + if (time && time > (sbar_time - 2)) sb_updates = 0; } } @@ -1276,7 +1293,7 @@ static void __attribute__((used)) draw_hipnotic_status (view_t *view) { #if 0 - if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { + if (sb_showscores || sbar_stats[STAT_HEALTH] <= 0) { draw_solo (view); return; } @@ -1286,9 +1303,9 @@ draw_hipnotic_status (view_t *view) draw_health (view); draw_ammo (view); - if (cl.stats[STAT_ITEMS] & IT_KEY1) + if (sbar_stats[STAT_ITEMS] & IT_KEY1) draw_pic (view, 209, 3, sb_items[0]); - if (cl.stats[STAT_ITEMS] & IT_KEY2) + if (sbar_stats[STAT_ITEMS] & IT_KEY2) draw_pic (view, 209, 12, sb_items[1]); #endif } @@ -1301,12 +1318,12 @@ setup_frags (view_t frags, int player) sbar_view (8, 0, 24, 8, grav_northwest, frags); sbar_view (0, 0, 40, 8, grav_northwest, frags); - player_info_t *p = &cl.players[player]; + player_info_t *p = &sbar_players[player]; set_frags_bar (frags, Sbar_ColorForMap (p->topcolor), Sbar_ColorForMap (p->bottomcolor), sb_frags[player], - (player == cl.viewentity - 1) ? frags_marker : 0); + (player == sbar_viewplayer) ? frags_marker : 0); } static void @@ -1515,7 +1532,7 @@ Sbar_DeathmatchOverlay (view_t view) SZ_Print (&cls.netchan.message, "pings"); } if (hud_ping) { - int ping = cl.players[cl.playernum].ping; + int ping = sbar_players[sbar_playernum].ping; ping = bound (0, ping, 999); draw_string (view, 0, 0, va (0, "%3d ms ", ping)); @@ -1544,19 +1561,19 @@ Sbar_DeathmatchOverlay (view_t view) int count = min (scoreboardlines, numbars); int i; - if (cl.stats[STAT_HEALTH] > 0) { + if (sbar_stats[STAT_HEALTH] > 0) { count = 0; } for (i = 0; i < count; i++, y += 10) { int k = fragsort[i]; - player_info_t *p = &cl.players[k]; + player_info_t *p = &sbar_players[k]; if (!View_Valid (sb_views[k])) { sb_views[k] = make_dmo_line (view, k); } write_charbuff (sb_ping[k], 0, 0, va (0, "%3d", p->ping)); write_charbuff (sb_pl[k], 0, 0, va (0, "%3d", p->pl)); - int total = (cl.intermission ? cl.completed_time : realtime) + int total = (sbar_intermission ? sbar_completed_time : sbar_time) - p->entertime; write_charbuff (sb_fph[k], 0, 0, va (0, "%3d", calc_fph (p->frags, total))); @@ -1567,7 +1584,7 @@ Sbar_DeathmatchOverlay (view_t view) write_charbuff (sb_name[k], 0, 0, p->name->value); View_SetPos (sb_views[k], 0, y); } - for (; i < MAX_CLIENTS; i++) { + for (; i < MAX_PLAYERS; i++) { int k = fragsort[i]; if (k >= 0 && View_Valid (sb_views[k])) { View_Delete (sb_views[k]); @@ -1583,9 +1600,9 @@ Sbar_TeamOverlay (view_t *view) char num[20]; int pavg, plow, phigh, i, k, x, y; team_t *tm; - info_key_t *player_team = cl.players[cl.playernum].team; + info_key_t *player_team = sbar_players[sbar_playernum].team; - if (!cl.teamplay) { // FIXME: if not teamplay, why teamoverlay? + if (!sbar_teamplay) { // FIXME: if not teamplay, why teamoverlay? Sbar_DeathmatchOverlay (view, 0); return; } @@ -1665,18 +1682,18 @@ Sbar_DrawScoreboard (void) static void draw_overlay (view_t *view) { - if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) { + if (sb_showscores || sbar_stats[STAT_HEALTH] <= 0) { Sbar_DrawScoreboard (); } #if 0 - if (cls.state != ca_active - || !((cl.stats[STAT_HEALTH] <= 0 && !cl.spectator) + if (!sbar_active + || !((sbar_stats[STAT_HEALTH] <= 0 && !sbar_spectator) || sb_showscores || sb_showteamscores)) return; // main screen deathmatch rankings // if we're dead show team scores in team games - if (cl.stats[STAT_HEALTH] <= 0 && !cl.spectator) - if (cl.teamplay > 0 && !sb_showscores) + if (sbar_stats[STAT_HEALTH] <= 0 && !sbar_spectator) + if (sbar_teamplay > 0 && !sb_showscores) Sbar_TeamOverlay (view); else Sbar_DeathmatchOverlay (view, 0); @@ -1697,7 +1714,7 @@ draw_overlay (view_t *view) added by Elmex */ void -Sbar_LogFrags (void) +Sbar_LogFrags (double completed_time) { char *name; char *team; @@ -1718,8 +1735,8 @@ Sbar_LogFrags (void) if (t) Qwrite (file, t, strlen (t)); - Qprintf (file, "%s\n%s %s\n", "FIXME",//FIXME cls.servername->str, - cl_world.scene->worldmodel->path, cl.levelname); + Qprintf (file, "%s\n%s %s\n", sbar_servername, + cl_world.scene->worldmodel->path, sbar_levelname); // scores Sbar_SortFrags (true); @@ -1727,7 +1744,7 @@ Sbar_LogFrags (void) // draw the text l = scoreboardlines; - if (cl.teamplay) { + if (sbar_teamplay) { // TODO: test if the teamplay does correct output Qwrite (file, "pl fph time frags team name\n", strlen ("pl fph time frags team name\n")); @@ -1738,7 +1755,7 @@ Sbar_LogFrags (void) for (i = 0; i < l; i++) { k = fragsort[i]; - s = &cl.players[k]; + s = &sbar_players[k]; if (!s->name || !s->name->value[0]) continue; @@ -1747,10 +1764,10 @@ Sbar_LogFrags (void) (void) p; //FIXME // get time - if (cl.intermission) - total = cl.completed_time - s->entertime; + if (sbar_intermission) + total = completed_time - s->entertime; else - total = realtime - s->entertime; + total = sbar_time - s->entertime; minutes = total / 60; // get frags @@ -1766,7 +1783,7 @@ Sbar_LogFrags (void) if (s->spectator) { Qprintf (file, "%-3i%% %s (spectator)", s->pl, name); } else { - if (cl.teamplay) { + if (sbar_teamplay) { team = malloc (strlen (s->team->value) + 1); for (cp = (byte *) s->team, d = 0; *cp; cp++, d++) team[d] = sys_char_map[*cp]; @@ -1845,7 +1862,7 @@ draw_net (view_t *view) SZ_Print (&cls.netchan.message, "pings"); } if (hud_ping) { - int ping = cl.players[cl.playernum].ping; + int ping = sbar_players[sbar_playernum].ping; ping = bound (0, ping, 999); draw_string (view, 0, 0, va (0, "%3d ms ", ping)); @@ -1861,7 +1878,7 @@ draw_net (view_t *view) draw_string (view, 56, 0, va (0, "%3d pl", lost)); } } -if (cls.state == ca_active && (hud_ping || hud_pl)) +if (sbar_active && (hud_ping || hud_pl)) #endif static void @@ -1882,8 +1899,8 @@ draw_intermission (view_t view) View_GetChild (intermission_time, 4), View_GetChild (intermission_time, 5), }; - int dig = cl.completed_time / 60; - int num = cl.completed_time - dig * 60; + int dig = sbar_completed_time / 60; + int num = sbar_completed_time - dig * 60; draw_num (time_views + 0, dig, 3, 0); sbar_setcomponent (time_views[3], hud_pic, &sb_colon); draw_num (time_views + 4, num, 2, 0); @@ -1897,9 +1914,9 @@ draw_intermission (view_t view) View_GetChild (intermission_secr, 5), View_GetChild (intermission_secr, 6), }; - draw_num (secr_views + 0, cl.stats[STAT_SECRETS], 3, 0); + draw_num (secr_views + 0, sbar_stats[STAT_SECRETS], 3, 0); sbar_setcomponent (secr_views[3], hud_pic, &sb_slash); - draw_num (secr_views + 4, cl.stats[STAT_TOTALSECRETS], 3, 0); + draw_num (secr_views + 4, sbar_stats[STAT_TOTALSECRETS], 3, 0); view_t kill_views[] = { View_GetChild (intermission_kill, 0), @@ -1910,9 +1927,9 @@ draw_intermission (view_t view) View_GetChild (intermission_kill, 5), View_GetChild (intermission_kill, 6), }; - draw_num (kill_views + 0, cl.stats[STAT_MONSTERS], 3, 0); + draw_num (kill_views + 0, sbar_stats[STAT_MONSTERS], 3, 0); sbar_setcomponent (kill_views[3], hud_pic, &sb_slash); - draw_num (kill_views + 4, cl.stats[STAT_TOTALMONSTERS], 3, 0); + draw_num (kill_views + 4, sbar_stats[STAT_TOTALMONSTERS], 3, 0); } static void @@ -1941,8 +1958,9 @@ Sbar_IntermissionOverlay (void) #endif void -Sbar_Intermission (int mode) +Sbar_Intermission (int mode, double completed_time) { + sbar_completed_time = completed_time; void *f = clear_views; if (mode == 1) { f = draw_intermission; @@ -1970,7 +1988,7 @@ Sbar_CenterPrint (const char *str) } centertime_off = scr_centertime; - centertime_start = realtime; + centertime_start = sbar_time; if (center_string.str && !strcmp (str, center_string.str)) { // same string as last time, no need to lay out the text again @@ -2023,7 +2041,7 @@ Sbar_FinaleOverlay (void) draw_cachepic (hud_overlay_view, 0, 16, "gfx/finale.lmp", 1); #endif // the finale prints the characters one at a time - remaining = scr_printspeed * (realtime - centertime_start); + remaining = scr_printspeed * (sbar_time - centertime_start); Sbar_DrawCenterString (hud_overlay_view, remaining); } @@ -2111,9 +2129,11 @@ Sbar_Changed (sbar_changed change) } void -Sbar_Draw (void) +Sbar_Update (double time) { - if (cls.state != ca_active) { + fps_count++; + sbar_time = time; + if (!sbar_active) { return; } if (sb_update_flags & (1 << sbc_info)) { @@ -2125,6 +2145,40 @@ Sbar_Draw (void) sb_update_flags = 0; } +void +Sbar_Damage (double time) +{ + sbar_faceanimtime = time + 0.2; +} + +void +Sbar_SetPlayerNum (int playernum, int spectator) +{ + sbar_playernum = playernum; + sbar_spectator = spectator; +} + +void +Sbar_SetViewEntity (int viewentity) +{ + sbar_viewplayer = viewentity - 1; +} + +void +Sbar_SetLevelName (const char *levelname, const char *servername) +{ +} + +void +Sbar_SetTeamplay (int teamplay) +{ +} + +void +Sbar_SetActive (int active) +{ +} + static void sbar_hud_swap_f (void *data, const cvar_t *cvar) { @@ -2562,7 +2616,7 @@ init_views (void) time_buff = Draw_CreateBuffer (8, 1); fps_buff = Draw_CreateBuffer (11, 1); - for (int i = 0; i < MAX_CLIENTS; i++) { + for (int i = 0; i < MAX_PLAYERS; i++) { sb_fph[i] = Draw_CreateBuffer (3, 1); sb_time[i] = Draw_CreateBuffer (4, 1); sb_frags[i] = Draw_CreateBuffer (3, 1); @@ -2801,8 +2855,18 @@ Sbar_DontShowTeamScores (void) } void -Sbar_Init (void) +Sbar_SetPlayers (player_info_t *players, int maxplayers) { + sbar_players = players; + sbar_maxplayers = maxplayers; +} + +void +Sbar_Init (int *stats, float *item_gettime) +{ + sbar_stats = stats; + sbar_item_gettime = item_gettime; + center_passage.reg = hud_registry; HUD_Init_Cvars (); Cvar_AddListener (Cvar_FindVar ("hud_sbar"), sbar_hud_sbar_f, 0); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index d27d3deaa..79115b819 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -60,7 +60,6 @@ #include "compat.h" #include "r_internal.h" -#include "sbar.h" #include "varrays.h" #define CELL_SIZE (1.0 / 16.0) // conchars is 16x16 diff --git a/nq/include/game.h b/nq/include/game.h index 55c53428f..47b33f421 100644 --- a/nq/include/game.h +++ b/nq/include/game.h @@ -59,93 +59,7 @@ #define SAVEGAME_COMMENT_LENGTH 39 -// -// stats are integers communicated to the client by the server -// -#define MAX_CL_STATS 32 -#define STAT_HEALTH 0 -#define STAT_FRAGS 1 -#define STAT_WEAPON 2 -#define STAT_AMMO 3 -#define STAT_ARMOR 4 -#define STAT_WEAPONFRAME 5 -#define STAT_SHELLS 6 -#define STAT_NAILS 7 -#define STAT_ROCKETS 8 -#define STAT_CELLS 9 -#define STAT_ACTIVEWEAPON 10 -#define STAT_TOTALSECRETS 11 -#define STAT_TOTALMONSTERS 12 -#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret -#define STAT_MONSTERS 14 // bumped by svc_killedmonster -#define STAT_ITEMS 15 - -// stock defines - -#define IT_SHOTGUN 1 -#define IT_SUPER_SHOTGUN 2 -#define IT_NAILGUN 4 -#define IT_SUPER_NAILGUN 8 -#define IT_GRENADE_LAUNCHER 16 -#define IT_ROCKET_LAUNCHER 32 -#define IT_LIGHTNING 64 -#define IT_SUPER_LIGHTNING 128 -#define IT_SHELLS 256 -#define IT_NAILS 512 -#define IT_ROCKETS 1024 -#define IT_CELLS 2048 -#define IT_AXE 4096 -#define IT_ARMOR1 8192 -#define IT_ARMOR2 16384 -#define IT_ARMOR3 32768 -#define IT_SUPERHEALTH 65536 -#define IT_KEY1 131072 -#define IT_KEY2 262144 -#define IT_INVISIBILITY 524288 -#define IT_INVULNERABILITY 1048576 -#define IT_SUIT 2097152 -#define IT_QUAD 4194304 -#define IT_SIGIL1 (1<<28) -#define IT_SIGIL2 (1<<29) -#define IT_SIGIL3 (1<<30) -#define IT_SIGIL4 (1<<31) - -//=========================================== -//rogue changed and added defines - -#define RIT_SHELLS 128 -#define RIT_NAILS 256 -#define RIT_ROCKETS 512 -#define RIT_CELLS 1024 -#define RIT_AXE 2048 -#define RIT_LAVA_NAILGUN 4096 -#define RIT_LAVA_SUPER_NAILGUN 8192 -#define RIT_MULTI_GRENADE 16384 -#define RIT_MULTI_ROCKET 32768 -#define RIT_PLASMA_GUN 65536 -#define RIT_ARMOR1 8388608 -#define RIT_ARMOR2 16777216 -#define RIT_ARMOR3 33554432 -#define RIT_LAVA_NAILS 67108864 -#define RIT_PLASMA_AMMO 134217728 -#define RIT_MULTI_ROCKETS 268435456 -#define RIT_SHIELD 536870912 -#define RIT_ANTIGRAV 1073741824 -#define RIT_SUPERHEALTH 2147483648 - -//MED 01/04/97 added hipnotic defines -//=========================================== -//hipnotic added defines -#define HIT_PROXIMITY_GUN_BIT 16 -#define HIT_MJOLNIR_BIT 7 -#define HIT_LASER_CANNON_BIT 23 -#define HIT_PROXIMITY_GUN (1<worldmodel = NULL; - Sbar_Intermission (cl.intermission = 0); + Sbar_Intermission (cl.intermission = 0, cl.time); cl.viewstate.intermission = 0; } @@ -589,6 +587,7 @@ CL_SetState (cactive_t state) S_AmbientOn (); break; } + Sbar_SetActive (state == ca_active); CL_UpdateScreen (&cl.viewstate); } host_in_game = 0; @@ -643,6 +642,7 @@ CL_Frame (void) r_data->frametime = host_frametime; cl.viewstate.intermission = cl.intermission != 0; + Sbar_Update (cl.time); CL_UpdateScreen (&cl.viewstate); if (host_speeds) @@ -677,7 +677,6 @@ CL_Frame (void) if (cls.demo_capture) { r_funcs->capture_screen (write_capture, 0); } - fps_count++; } static void @@ -714,7 +713,7 @@ CL_Init (cbuf_t *cbuf) CDAudio_Init (); - Sbar_Init (); + Sbar_Init (cl.stats, cl.item_gettime); CL_Init_Input (cbuf); CL_Particles_Init (); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 9bf358b68..e65535848 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -304,6 +304,8 @@ CL_ParseServerInfo (void) cl.players[i].topcolor = 0; cl.players[i].bottomcolor = 0; } + Sbar_SetPlayers (cl.players, cl.maxclients); + Sbar_SetTeamplay (0); // parse gametype cl.gametype = MSG_ReadByte (net_message); @@ -311,6 +313,7 @@ CL_ParseServerInfo (void) // parse signon message str = MSG_ReadString (net_message); strncpy (cl.levelname, str, sizeof (cl.levelname) - 1); + Sbar_SetLevelName (cl.levelname, 0); // separate the printfs so the server message can have a color Sys_Printf ("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36" @@ -923,7 +926,7 @@ CL_ParseServerMessage (void) case svc_damage: V_ParseDamage (net_message, &cl.viewstate); // put sbar face into pain frame - cl.faceanimtime = cl.time + 0.2; + Sbar_Damage (cl.time); break; case svc_spawnstatic: @@ -977,15 +980,13 @@ CL_ParseServerMessage (void) break; case svc_intermission: - Sbar_Intermission (cl.intermission = 1); + Sbar_Intermission (cl.intermission = 1, cl.time); SCR_SetFullscreen (1); - cl.completed_time = cl.time; break; case svc_finale: - Sbar_Intermission (cl.intermission = 2); + Sbar_Intermission (cl.intermission = 2, cl.time); SCR_SetFullscreen (1); - cl.completed_time = cl.time; str = MSG_ReadString (net_message); Sbar_CenterPrint (str); break; @@ -1005,9 +1006,8 @@ CL_ParseServerMessage (void) break; case svc_cutscene: - Sbar_Intermission (cl.intermission = 3); + Sbar_Intermission (cl.intermission = 3, cl.time); SCR_SetFullscreen (1); - cl.completed_time = cl.time; str = MSG_ReadString (net_message); Sbar_CenterPrint (str); break; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 5f0b53218..c7411af43 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -622,12 +622,11 @@ CL_ClearState (void) // wipe the entire cl structure if (cl.serverinfo) Info_Destroy (cl.serverinfo); - if (cl.players) - free (cl.players); + __auto_type players = cl.players; __auto_type cam = cl.viewstate.camera_transform; memset (&cl, 0, sizeof (cl)); cl.viewstate.camera_transform = cam; - cl.players = calloc (MAX_CLIENTS, sizeof (player_info_t)); + cl.players = players; SCR_SetFullscreen (0); cl.maxclients = MAX_CLIENTS; @@ -870,7 +869,7 @@ CL_FullServerinfo_f (void) } if ((p = Info_ValueForKey (cl.serverinfo, "teamplay")) && *p) { cl.teamplay = atoi (p); - Sbar_Changed (sbc_server); + Sbar_SetTeamplay (cl.teamplay); } if ((p = Info_ValueForKey (cl.serverinfo, "watervis")) && *p) { cl.viewstate.watervis = atoi (p); @@ -1405,6 +1404,7 @@ CL_SetState (cactive_t state) && !cls.demorecording) CL_Record (0, -1); } + Sbar_SetActive (state == ca_active); } Con_SetState (state == ca_active ? con_inactive : con_fullscreen); if (state != old_state && state == ca_active) { @@ -1478,7 +1478,7 @@ CL_Init (void) S_Init (&cl.viewentity, &host_frametime); CDAudio_Init (); - Sbar_Init (); + Sbar_Init (cl.stats, cl.item_gettime); CL_Init_Input (cl_cbuf); CL_Ents_Init (); @@ -1506,6 +1506,7 @@ CL_Init (void) cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING, 0); free (cl.players); cl.players = calloc (MAX_CLIENTS, sizeof (player_info_t)); + Sbar_SetPlayers (cl.players, MAX_CLIENTS); // register our commands Cmd_AddCommand ("pointfile", pointfile_f, @@ -1943,6 +1944,7 @@ Host_Frame (float time) r_data->frametime = host_frametime; cl.viewstate.time = realtime; + Sbar_Update (cl.time); CL_UpdateScreen (&cl.viewstate); if (host_speeds) diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index ee5e07d6b..c8db70e7c 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -779,6 +779,7 @@ CL_ParseServerData (void) // get the full level name str = MSG_ReadString (net_message); strncpy (cl.levelname, str, sizeof (cl.levelname) - 1); + Sbar_SetLevelName (cl.levelname, cls.servername->str); // get the movevars movevars.gravity = MSG_ReadFloat (net_message); @@ -1121,7 +1122,7 @@ CL_ServerInfo (void) cl.no_pogo_stick = no_pogo_stick; } else if (strequal (key, "teamplay")) { cl.teamplay = atoi (value); - Sbar_Changed (sbc_server); + Sbar_SetTeamplay (cl.teamplay); } else if (strequal (key, "watervis")) { cl.viewstate.watervis = atoi (value); } else if (strequal (key, "fpd")) { @@ -1411,7 +1412,7 @@ CL_ParseServerMessage (void) case svc_damage: V_ParseDamage (net_message, &cl.viewstate); // put sbar face into pain frame - cl.faceanimtime = cl.time + 0.2; + Sbar_Damage (cl.time); break; case svc_spawnstatic: @@ -1478,7 +1479,7 @@ CL_ParseServerMessage (void) // automatic fraglogging (by elmex) // XXX: Should this _really_ called here? if (!cls.demoplayback) - Sbar_LogFrags (); + Sbar_LogFrags (cl.time); break; case svc_finale: From 1b90f2320e07018e431d807a0cb8f004f48473c6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 9 Nov 2022 19:41:59 +0900 Subject: [PATCH 3169/3664] [client] Extend sbar's api I think this makes the purpose of the functions more clear and makes the protocol logic less dependent on the meaning of some of the updates. Most of the update functions are not fully implemented yet. --- include/sbar.h | 4 ++++ libs/client/sbar.c | 54 +++++++++++++++++++++++++++++++++++++------- nq/source/cl_parse.c | 22 +++++++++--------- qw/source/cl_cam.c | 18 ++------------- qw/source/cl_parse.c | 19 ++++++++-------- 5 files changed, 72 insertions(+), 45 deletions(-) diff --git a/include/sbar.h b/include/sbar.h index f63ef31e6..780f92378 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -58,6 +58,10 @@ void Sbar_SetTeamplay (int teamplay); void Sbar_SetActive (int active); void Sbar_Update (double time); +void Sbar_UpdatePings (void); +void Sbar_UpdateFrags (int playernum); +void Sbar_UpdateInfo (int playernum); +void Sbar_UpdateStats (int stat); void Sbar_Damage (double time); void Sbar_Changed (sbar_changed change); diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 8afc73881..8f7e72c8f 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -1565,23 +1565,17 @@ Sbar_DeathmatchOverlay (view_t view) count = 0; } + double cur_time = sbar_intermission ? sbar_completed_time : sbar_time; for (i = 0; i < count; i++, y += 10) { int k = fragsort[i]; player_info_t *p = &sbar_players[k]; if (!View_Valid (sb_views[k])) { sb_views[k] = make_dmo_line (view, k); } - write_charbuff (sb_ping[k], 0, 0, va (0, "%3d", p->ping)); - write_charbuff (sb_pl[k], 0, 0, va (0, "%3d", p->pl)); - int total = (sbar_intermission ? sbar_completed_time : sbar_time) - - p->entertime; + int total = cur_time - p->entertime; write_charbuff (sb_fph[k], 0, 0, va (0, "%3d", calc_fph (p->frags, total))); write_charbuff (sb_time[k], 0, 0, va (0, "%3d", total / 60)); - //FIXME update top/bottom color - write_charbuff (sb_frags[k], 0, 0, va (0, "%3d", p->frags)); - write_charbuff (sb_uid[k], 0, 0, va (0, "%3d", p->userid)); - write_charbuff (sb_name[k], 0, 0, p->name->value); View_SetPos (sb_views[k], 0, y); } for (; i < MAX_PLAYERS; i++) { @@ -2145,6 +2139,46 @@ Sbar_Update (double time) sb_update_flags = 0; } +void +Sbar_UpdatePings () +{ + for (int i = 0; i < sbar_maxplayers; i++) { + player_info_t *p = &sbar_players[i]; + if (!p->name || !p->name->value) { + continue; + } + write_charbuff (sb_ping[i], 0, 0, va (0, "%3d", p->ping)); + write_charbuff (sb_pl[i], 0, 0, va (0, "%3d", p->pl)); + } +} + +void +Sbar_UpdateFrags (int playernum) +{ + player_info_t *p = &sbar_players[playernum]; + write_charbuff (sb_frags[playernum], 0, 0, va (0, "%3d", p->frags)); +} + +void +Sbar_UpdateInfo (int playernum) +{ + player_info_t *p = &sbar_players[playernum]; + //FIXME update top/bottom color + write_charbuff (sb_uid[playernum], 0, 0, va (0, "%3d", p->userid)); + write_charbuff (sb_name[playernum], 0, 0, p->name->value); + if (sbar_teamplay) { + write_charbuff (sb_team[playernum], 0, 0, p->team->value); + } +} + +void +Sbar_UpdateStats (int stat) +{ + if (stat == -1) { + } else { + } +} + void Sbar_Damage (double time) { @@ -2167,16 +2201,20 @@ Sbar_SetViewEntity (int viewentity) void Sbar_SetLevelName (const char *levelname, const char *servername) { + sbar_levelname = levelname; + sbar_servername = servername; } void Sbar_SetTeamplay (int teamplay) { + sbar_teamplay = teamplay; } void Sbar_SetActive (int active) { + sbar_active = active; } static void diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index e65535848..411b8d561 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -585,9 +585,9 @@ CL_ParseClientdata (void) if ((i & (1 << j)) && !(cl.stats[STAT_ITEMS] & (1 << j))) cl.item_gettime[j] = cl.time; cl.stats[STAT_ITEMS] = i; - Sbar_Changed (sbc_items); #define IT_POWER (IT_QUAD | IT_SUIT | IT_INVULNERABILITY | IT_INVISIBILITY) cl.viewstate.powerup_index = (cl.stats[STAT_ITEMS] & IT_POWER) >> 19; + Sbar_UpdateStats (STAT_ITEMS); } cl.viewstate.onground = (bits & SU_ONGROUND) ? 0 : -1; @@ -605,7 +605,7 @@ CL_ParseClientdata (void) i = 0; if (cl.stats[STAT_ARMOR] != i) { cl.stats[STAT_ARMOR] = i; - Sbar_Changed (sbc_armor); + Sbar_UpdateStats (STAT_ITEMS); } if (bits & SU_WEAPON) @@ -615,26 +615,26 @@ CL_ParseClientdata (void) if (cl.stats[STAT_WEAPON] != i) { cl.stats[STAT_WEAPON] = i; cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]]; - Sbar_Changed (sbc_weapon); + Sbar_UpdateStats (STAT_WEAPON); } i = (short) MSG_ReadShort (net_message); if (cl.stats[STAT_HEALTH] != i) { cl.stats[STAT_HEALTH] = i; - Sbar_Changed (sbc_health); + Sbar_UpdateStats (STAT_HEALTH); } i = MSG_ReadByte (net_message); if (cl.stats[STAT_AMMO] != i) { cl.stats[STAT_AMMO] = i; - Sbar_Changed (sbc_ammo); + Sbar_UpdateStats (STAT_AMMO); } for (i = 0; i < 4; i++) { j = MSG_ReadByte (net_message); if (cl.stats[STAT_SHELLS + i] != j) { cl.stats[STAT_SHELLS + i] = j; - Sbar_Changed (sbc_ammo); + Sbar_UpdateStats (STAT_SHELLS + i); } } @@ -643,13 +643,13 @@ CL_ParseClientdata (void) if (standard_quake) { if (cl.stats[STAT_ACTIVEWEAPON] != i) { cl.stats[STAT_ACTIVEWEAPON] = i; - Sbar_Changed (sbc_weapon); + Sbar_UpdateStats (STAT_ACTIVEWEAPON); } } else { // hipnotic/rogue weapon "bit field" (stupid idea) if (cl.stats[STAT_ACTIVEWEAPON] != (1 << i)) { cl.stats[STAT_ACTIVEWEAPON] = (1 << i); - Sbar_Changed (sbc_weapon); + Sbar_UpdateStats (STAT_ACTIVEWEAPON); } } @@ -870,22 +870,22 @@ CL_ParseServerMessage (void) break; case svc_updatename: - Sbar_Changed (sbc_info); i = MSG_ReadByte (net_message); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatename > " "MAX_SCOREBOARD"); Info_SetValueForKey (cl.players[i].userinfo, "name", MSG_ReadString (net_message), 0); + Sbar_UpdateInfo (i); break; case svc_updatefrags: - Sbar_Changed (sbc_frags); i = MSG_ReadByte (net_message); if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatefrags > " "MAX_SCOREBOARD"); cl.players[i].frags = (short) MSG_ReadShort (net_message); + Sbar_UpdateFrags (i); break; case svc_clientdata: @@ -898,7 +898,6 @@ CL_ParseServerMessage (void) break; case svc_updatecolors: - Sbar_Changed (sbc_info); i = MSG_ReadByte (net_message); if (i >= cl.maxclients) { Host_Error ("CL_ParseServerMessage: svc_updatecolors > " @@ -916,6 +915,7 @@ CL_ParseServerMessage (void) cl.players[i].bottomcolor = bot; renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, i + 1); + Sbar_UpdateInfo (i); } break; diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index a65d569bb..a784a9cf1 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -199,14 +199,7 @@ Cam_Unlock (void) } autocam = CAM_NONE; locked = false; - Sbar_Changed (sbc_ammo); - Sbar_Changed (sbc_armor); - Sbar_Changed (sbc_frags); - Sbar_Changed (sbc_health); - Sbar_Changed (sbc_info); - Sbar_Changed (sbc_items); - Sbar_Changed (sbc_weapon); - Sbar_Changed (sbc_server); + Sbar_UpdateStats (-1); // update all stats } } @@ -228,14 +221,7 @@ Cam_Lock (int playernum) last_lock = realtime; cam_forceview = true; locked = false; - Sbar_Changed (sbc_ammo); - Sbar_Changed (sbc_armor); - Sbar_Changed (sbc_frags); - Sbar_Changed (sbc_health); - Sbar_Changed (sbc_info); - Sbar_Changed (sbc_items); - Sbar_Changed (sbc_weapon); - Sbar_Changed (sbc_server); + Sbar_UpdateStats (-1); // update all stats } static trace_t diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index c8db70e7c..469eec6c3 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1034,7 +1034,7 @@ CL_ProcessUserInfo (int slot, player_info_t *player) player->skinname->value); player->skin = mod_funcs->Skin_SetColormap (player->skin, slot + 1); - Sbar_Changed (sbc_info); + Sbar_UpdateInfo (slot); } static void @@ -1157,7 +1157,6 @@ CL_SetStat (int stat, int value) case STAT_ITEMS: #define IT_POWER (IT_QUAD | IT_SUIT | IT_INVULNERABILITY | IT_INVISIBILITY) cl.viewstate.powerup_index = (cl.stats[STAT_ITEMS]&IT_POWER) >> 19; - Sbar_Changed (sbc_items); break; case STAT_HEALTH: if (cl_player_health_e->func) @@ -1166,13 +1165,6 @@ CL_SetStat (int stat, int value) if (value <= 0) Team_Dead (); break; - default: - //FIXME smarter checks - Sbar_Changed (sbc_ammo); - Sbar_Changed (sbc_armor); - Sbar_Changed (sbc_frags); - Sbar_Changed (sbc_weapon); - break; } cl.stats[stat] = value; cl.viewstate.weapon_model = cl_world.models.a[cl.stats[STAT_WEAPON]]; @@ -1181,6 +1173,7 @@ CL_SetStat (int stat, int value) } else { cl.viewstate.height = DEFAULT_VIEWHEIGHT; // view height } + Sbar_UpdateStats (stat); } static void @@ -1220,6 +1213,7 @@ void CL_ParseServerMessage (void) { int cmd = 0, i, j; + int update_pings = 0; const char *str; static dstring_t *stuffbuf; TEntContext_t tentCtx = { @@ -1396,7 +1390,7 @@ CL_ParseServerMessage (void) Host_Error ("CL_ParseServerMessage: svc_updatefrags > " "MAX_SCOREBOARD"); cl.players[i].frags = (short) MSG_ReadShort (net_message); - Sbar_Changed (sbc_frags); + Sbar_UpdateFrags (i); break; // svc_clientdata @@ -1521,6 +1515,7 @@ CL_ParseServerMessage (void) Host_Error ("CL_ParseServerMessage: svc_updateping > " "MAX_SCOREBOARD"); cl.players[i].ping = MSG_ReadShort (net_message); + update_pings = 1; break; case svc_updateentertime: @@ -1604,6 +1599,7 @@ CL_ParseServerMessage (void) Host_Error ("CL_ParseServerMessage: svc_updatepl > " "MAX_SCOREBOARD"); cl.players[i].pl = MSG_ReadByte (net_message); + update_pings = 1; break; case svc_nails2: // FIXME from qwex @@ -1611,6 +1607,9 @@ CL_ParseServerMessage (void) break; } } + if (update_pings) { + Sbar_UpdatePings (); + } CL_SetSolidEntities (); } From e0fa853f472734dbaef6d574e220d7103143ee89 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Nov 2022 01:35:33 +0900 Subject: [PATCH 3170/3664] [client] Implement the update functions nq's frags don't update properly yet, and there's still a lot of optimization to sort out, but it seems to be fairly usable again. --- include/sbar.h | 1 - libs/client/sbar.c | 229 +++++++++++++++++++++++++++---------------- nq/source/cl_parse.c | 5 +- qw/source/cl_parse.c | 2 + 4 files changed, 149 insertions(+), 88 deletions(-) diff --git a/include/sbar.h b/include/sbar.h index 780f92378..1ca13870d 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -64,7 +64,6 @@ void Sbar_UpdateInfo (int playernum); void Sbar_UpdateStats (int stat); void Sbar_Damage (double time); -void Sbar_Changed (sbar_changed change); // call whenever any of the client stats represented on the sbar changes void Sbar_Intermission (int mode, double completed_time); diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 8f7e72c8f..5efa0e743 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -671,7 +671,7 @@ Sbar_SortTeams (void) } static int -write_charbuff (draw_charbuffer_t *buffer, int x, int y, const char *str) +write_charbuff_cl (draw_charbuffer_t *buffer, int x, int y, const char *str) { char *dst = buffer->chars; int count = buffer->width - x; @@ -687,6 +687,20 @@ write_charbuff (draw_charbuffer_t *buffer, int x, int y, const char *str) return chars; } +static int +write_charbuff (draw_charbuffer_t *buffer, int x, int y, const char *str) +{ + char *dst = buffer->chars; + int count = buffer->width - x; + int chars = 0; + dst += y * buffer->width + x; + while (*str && count-- > 0) { + *dst++ = *str++; + chars++; + } + return chars; +} + static void draw_solo_time (void) { @@ -699,15 +713,9 @@ draw_solo_time (void) static void draw_solo (void) { - write_charbuff (solo_monsters, 0, 0, - va (0, "Monsters:%3i /%3i", - sbar_stats[STAT_MONSTERS], sbar_stats[STAT_TOTALMONSTERS])); - write_charbuff (solo_secrets, 0, 0, - va (0, "Secrets :%3i /%3i", - sbar_stats[STAT_SECRETS], sbar_stats[STAT_TOTALSECRETS])); draw_solo_time (); view_pos_t len = View_GetLen (sbar_solo_name); - len.x = 8 * write_charbuff (solo_name, 0, 0, sbar_levelname); + len.x = 8 * solo_name->cursx; View_SetLen (sbar_solo_name, len.x, len.y); } @@ -830,9 +838,9 @@ draw_minifrags (view_t view) sbar_teamplay ? sb_team[k] : 0, sb_name[k]); if (sbar_teamplay) { - write_charbuff (sb_team[k], 0, 0, s->team->value); + write_charbuff_cl (sb_team[k], 0, 0, s->team->value); } - write_charbuff (sb_name[k], 0, 0, s->name->value); + write_charbuff_cl (sb_name[k], 0, 0, s->name->value); draw_smallnum (View_GetChild (bar, 2), s->frags, 0, 0); } for (; i < numbars; i++) { @@ -885,7 +893,7 @@ draw_miniteam (view_t view) func = frags_marker; } set_miniteam_bar (bar, sb_team[k], sb_team_frags[k], func); - write_charbuff (sb_team[k], 0, 0, s->team->value); + write_charbuff_cl (sb_team[k], 0, 0, s->team->value); write_charbuff (sb_team_frags[k], 0, 0, va (0, "%5d", tm->frags)); } for (; i < numbars; i++) { @@ -1823,7 +1831,7 @@ draw_time (view_t *view) } else if (hud_time >= 2) { // US AM/PM display strftime (st, sizeof (st), HOUR12":%M "PM, local); } - write_charbuff (time_buff, 0, 0, st); + write_charbuff_cl (time_buff, 0, 0, st); } static void @@ -2051,77 +2059,6 @@ Sbar_DrawCenterPrint (void) Sbar_DrawCenterString (hud_overlay_view, -1); } -typedef struct { - hud_update_f update; - view_t *view; -} sb_updater_t; - -static const sb_updater_t ammo_update[] = { - {draw_miniammo, &sbar_miniammo}, - {draw_ammo, &sbar_ammo}, - {} -}; -static const sb_updater_t armor_update[] = { - {draw_armor, &sbar_armor}, - {} -}; -static const sb_updater_t frags_update[] = { - {draw_frags, &sbar_frags}, - {draw_minifrags, &hud_minifrags}, - {draw_miniteam, &hud_miniteam}, - {Sbar_DeathmatchOverlay, &dmo_view}, - {} -}; -static const sb_updater_t health_update[] = { - {draw_health, &sbar_health}, - {draw_face, &sbar_face}, - {} -}; -static const sb_updater_t info_update[] = { - {draw_frags, &sbar_frags}, - {draw_minifrags, &hud_minifrags}, - {draw_miniteam, &hud_miniteam}, - {Sbar_DeathmatchOverlay, &dmo_view}, - {} -}; -static const sb_updater_t items_update[] = { - {draw_items, &sbar_items}, - {draw_sigils, &sbar_sigils}, - {} -}; -static const sb_updater_t weapon_update[] = { - {draw_weapons, &sbar_weapons}, - {draw_ammo, &sbar_ammo}, - {} -}; - -static const sb_updater_t * const sb_updaters[sbc_num_changed] = { - [sbc_ammo] = ammo_update, - [sbc_armor] = armor_update, - [sbc_frags] = frags_update, - [sbc_health] = health_update, - [sbc_info] = info_update, - [sbc_items] = items_update, - [sbc_weapon] = weapon_update, -}; - -void -Sbar_Changed (sbar_changed change) -{ - sb_update_flags |= 1 << change; - sb_updates = 0; // update next frame - if ((unsigned) change >= (unsigned) sbc_num_changed) { - Sys_Error ("invalid sbar changed enum"); - } - const sb_updater_t *ud = sb_updaters[change]; - if (ud) { - while (ud->update) { - sbar_setcomponent (*ud->view, hud_updateonce, &ud->update); - ud++; - } - } -} - void Sbar_Update (double time) { @@ -2164,18 +2101,131 @@ Sbar_UpdateInfo (int playernum) { player_info_t *p = &sbar_players[playernum]; //FIXME update top/bottom color - write_charbuff (sb_uid[playernum], 0, 0, va (0, "%3d", p->userid)); - write_charbuff (sb_name[playernum], 0, 0, p->name->value); + write_charbuff (sb_uid[playernum], 0, 0, va (0, "%4d", p->userid)); + write_charbuff_cl (sb_name[playernum], 0, 0, p->name->value); if (sbar_teamplay) { - write_charbuff (sb_team[playernum], 0, 0, p->team->value); + write_charbuff_cl (sb_team[playernum], 0, 0, p->team->value); } } +static inline void +set_update (view_t view, hud_update_f func) +{ + sbar_setcomponent (view, hud_updateonce, &func); +} + +static void +update_health (int stat) +{ + set_update (sbar_health, draw_health); + set_update (sbar_face, draw_face); +} + +static void +update_frags (int stat) +{ + write_charbuff (sb_frags[sbar_playernum], 0, 0, + va (0, "%3d", sbar_stats[stat])); + set_update (sbar_frags, draw_frags);//FIXME + set_update (hud_minifrags, draw_minifrags);//FIXME + set_update (dmo_view, Sbar_DeathmatchOverlay);//FIXME + if (sbar_teamplay) { + set_update (hud_miniteam, draw_miniteam);//FIXME + } +} + +static void +update_weapon (int stat) +{ + set_update (sbar_weapons, draw_weapons); +} + +static void +update_ammo (int stat) +{ + set_update (sbar_ammo, draw_ammo); +} + +static void +update_miniammo (int stat) +{ + set_update (sbar_miniammo, draw_miniammo);//FIXME +} + +static void +update_armor (int stat) +{ + set_update (sbar_armor, draw_armor); +} + +static void +update_totalsecrets (int stat) +{ + write_charbuff (solo_secrets, 14, 0, + va (0, "%3i", sbar_stats[STAT_TOTALSECRETS])); +} + +static void +update_secrets (int stat) +{ + write_charbuff (solo_secrets, 9, 0, + va (0, "%3i", sbar_stats[STAT_SECRETS])); +} + +static void +update_totalmonsters (int stat) +{ + write_charbuff (solo_monsters, 14, 0, + va (0, "%3i", sbar_stats[STAT_TOTALMONSTERS])); +} + +static void +update_monsters (int stat) +{ + write_charbuff (solo_monsters, 9, 0, + va (0, "%3i", sbar_stats[STAT_MONSTERS])); +} + +static void +update_items (int stat) +{ + set_update (sbar_items, draw_items);//FIXME + set_update (sbar_sigils, draw_sigils);//FIXME + set_update (sbar_weapons, draw_weapons);//FIXME +} + +typedef void (*stat_update_f) (int stat); + +static stat_update_f stat_update[MAX_CL_STATS] = { + [STAT_HEALTH] = update_health, + [STAT_FRAGS] = update_frags, + [STAT_AMMO] = update_ammo, + [STAT_ARMOR] = update_armor, + [STAT_SHELLS] = update_miniammo, + [STAT_NAILS] = update_miniammo, + [STAT_ROCKETS] = update_miniammo, + [STAT_CELLS] = update_miniammo, + [STAT_ACTIVEWEAPON] = update_weapon, + [STAT_TOTALSECRETS] = update_totalsecrets, + [STAT_TOTALMONSTERS] = update_totalmonsters, + [STAT_SECRETS] = update_secrets, + [STAT_MONSTERS] = update_monsters, + [STAT_ITEMS] = update_items, +}; + void Sbar_UpdateStats (int stat) { if (stat == -1) { + for (int i = 0; i < MAX_CL_STATS; i++) { + if (stat_update[i]) { + stat_update[i] (i); + } + } } else { + if ((unsigned) stat < MAX_CL_STATS && stat_update[stat]) { + stat_update[stat] (stat); + } } } @@ -2203,6 +2253,7 @@ Sbar_SetLevelName (const char *levelname, const char *servername) { sbar_levelname = levelname; sbar_servername = servername; + solo_name->cursx = write_charbuff_cl (solo_name, 0, 0, sbar_levelname); } void @@ -2288,6 +2339,8 @@ set_hud_sbar (void) sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar); sbar_setcomponent (sbar_statusbar, hud_pic, &sb_sbar); + sbar_setcomponent (sbar_tile[0], hud_tile, 0); + sbar_setcomponent (sbar_tile[1], hud_tile, 0); } else { View_SetParent (sbar_armament, hud_view); View_SetPos (sbar_armament, 0, 48); @@ -2328,6 +2381,8 @@ set_hud_sbar (void) sbar_remcomponent (sbar_inventory, hud_pic); sbar_remcomponent (sbar_statusbar, hud_pic); + sbar_remcomponent (sbar_tile[0], hud_tile); + sbar_remcomponent (sbar_tile[1], hud_tile); } ECS_SortComponentPool (hud_registry, hud_pic, href_cmp, 0); } @@ -2424,6 +2479,8 @@ init_sbar_views (void) solo_monsters = Draw_CreateBuffer (17, 1); solo_secrets = Draw_CreateBuffer (17, 1); + write_charbuff (solo_monsters, 0, 0, "Monsters:xxx /xxx"); + write_charbuff (solo_secrets, 0, 0, "Secrets :xxx /xxx"); solo_time = Draw_CreateBuffer (12, 1); solo_name = Draw_CreateBuffer (20, 1); } diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 411b8d561..88545d559 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -605,7 +605,7 @@ CL_ParseClientdata (void) i = 0; if (cl.stats[STAT_ARMOR] != i) { cl.stats[STAT_ARMOR] = i; - Sbar_UpdateStats (STAT_ITEMS); + Sbar_UpdateStats (STAT_ARMOR); } if (bits & SU_WEAPON) @@ -706,6 +706,7 @@ CL_SetStat (int stat, int value) if (stat < 0 || stat >= MAX_CL_STATS) Host_Error ("CL_SetStat: %i is invalid", stat); cl.stats[stat] = value; + Sbar_UpdateStats (stat); } #define SHOWNET(x) \ @@ -969,10 +970,12 @@ CL_ParseServerMessage (void) case svc_killedmonster: cl.stats[STAT_MONSTERS]++; + Sbar_UpdateStats (STAT_MONSTERS); break; case svc_foundsecret: cl.stats[STAT_SECRETS]++; + Sbar_UpdateStats (STAT_SECRETS); break; case svc_spawnstaticsound: diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 469eec6c3..cb2ef4667 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1441,10 +1441,12 @@ CL_ParseServerMessage (void) case svc_killedmonster: cl.stats[STAT_MONSTERS]++; + Sbar_UpdateStats (STAT_MONSTERS); break; case svc_foundsecret: cl.stats[STAT_SECRETS]++; + Sbar_UpdateStats (STAT_SECRETS); break; case svc_spawnstaticsound: From d9b231e2aaed771a1923867d0e4122f81a8d7ae8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Nov 2022 14:44:08 +0900 Subject: [PATCH 3171/3664] [util] Return null for missing wad lumps Segfaults are not good when a lump can't be found as it makes error checking difficult. --- libs/util/wad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/wad.c b/libs/util/wad.c index 017e48605..1fbb91b39 100644 --- a/libs/util/wad.c +++ b/libs/util/wad.c @@ -132,7 +132,7 @@ W_GetLumpName (const char *name) } lump = W_GetLumpinfo (name); - return (void *) (wad_base + lump->filepos); + return lump ? (wad_base + lump->filepos) : 0; } VISIBLE void From c07b2e4d1f8fadd2e889976d9c244b41e716695a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Nov 2022 15:08:36 +0900 Subject: [PATCH 3172/3664] Make item masks easier to read When values are bit masks, they're much easier to read when expressed as a shift than as a raw decimal number, especially when knowing the index of the bit is important. --- include/gamedefs.h | 84 +++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/include/gamedefs.h b/include/gamedefs.h index 633c67570..7659c349c 100644 --- a/include/gamedefs.h +++ b/include/gamedefs.h @@ -54,54 +54,54 @@ #define STAT_FLYMODE 17 // stock defines -#define IT_SHOTGUN 1 -#define IT_SUPER_SHOTGUN 2 -#define IT_NAILGUN 4 -#define IT_SUPER_NAILGUN 8 -#define IT_GRENADE_LAUNCHER 16 -#define IT_ROCKET_LAUNCHER 32 -#define IT_LIGHTNING 64 -#define IT_SUPER_LIGHTNING 128 -#define IT_SHELLS 256 -#define IT_NAILS 512 -#define IT_ROCKETS 1024 -#define IT_CELLS 2048 -#define IT_AXE 4096 -#define IT_ARMOR1 8192 -#define IT_ARMOR2 16384 -#define IT_ARMOR3 32768 -#define IT_SUPERHEALTH 65536 -#define IT_KEY1 131072 -#define IT_KEY2 262144 -#define IT_INVISIBILITY 524288 -#define IT_INVULNERABILITY 1048576 -#define IT_SUIT 2097152 -#define IT_QUAD 4194304 +#define IT_SHOTGUN (1<<0) +#define IT_SUPER_SHOTGUN (1<<1) +#define IT_NAILGUN (1<<2) +#define IT_SUPER_NAILGUN (1<<3) +#define IT_GRENADE_LAUNCHER (1<<4) +#define IT_ROCKET_LAUNCHER (1<<5) +#define IT_LIGHTNING (1<<6) +#define IT_SUPER_LIGHTNING (1<<7) +#define IT_SHELLS (1<<8) +#define IT_NAILS (1<<9) +#define IT_ROCKETS (1<<10) +#define IT_CELLS (1<<11) +#define IT_AXE (1<<12) +#define IT_ARMOR1 (1<<13) +#define IT_ARMOR2 (1<<14) +#define IT_ARMOR3 (1<<15) +#define IT_SUPERHEALTH (1<<16) +#define IT_KEY1 (1<<17) +#define IT_KEY2 (1<<18) +#define IT_INVISIBILITY (1<<19) +#define IT_INVULNERABILITY (1<<20) +#define IT_SUIT (1<<21) +#define IT_QUAD (1<<22) #define IT_SIGIL1 (1<<28) #define IT_SIGIL2 (1<<29) #define IT_SIGIL3 (1<<30) #define IT_SIGIL4 (1<<31) //rogue changed and added defines -#define RIT_SHELLS 128 -#define RIT_NAILS 256 -#define RIT_ROCKETS 512 -#define RIT_CELLS 1024 -#define RIT_AXE 2048 -#define RIT_LAVA_NAILGUN 4096 -#define RIT_LAVA_SUPER_NAILGUN 8192 -#define RIT_MULTI_GRENADE 16384 -#define RIT_MULTI_ROCKET 32768 -#define RIT_PLASMA_GUN 65536 -#define RIT_ARMOR1 8388608 -#define RIT_ARMOR2 16777216 -#define RIT_ARMOR3 33554432 -#define RIT_LAVA_NAILS 67108864 -#define RIT_PLASMA_AMMO 134217728 -#define RIT_MULTI_ROCKETS 268435456 -#define RIT_SHIELD 536870912 -#define RIT_ANTIGRAV 1073741824 -#define RIT_SUPERHEALTH 2147483648 +#define RIT_SHELLS (1<<7) +#define RIT_NAILS (1<<8) +#define RIT_ROCKETS (1<<9) +#define RIT_CELLS (1<<10) +#define RIT_AXE (1<<11) +#define RIT_LAVA_NAILGUN (1<<12) +#define RIT_LAVA_SUPER_NAILGUN (1<<13) +#define RIT_MULTI_GRENADE (1<<14) +#define RIT_MULTI_ROCKET (1<<15) +#define RIT_PLASMA_GUN (1<<16) +#define RIT_ARMOR1 (1<<23) +#define RIT_ARMOR2 (1<<24) +#define RIT_ARMOR3 (1<<25) +#define RIT_LAVA_NAILS (1<<26) +#define RIT_PLASMA_AMMO (1<<27) +#define RIT_MULTI_ROCKETS (1<<28) +#define RIT_SHIELD (1<<29) +#define RIT_ANTIGRAV (1<<30) +#define RIT_SUPERHEALTH (1<<31) //MED 01/04/97 added hipnotic defines //hipnotic added defines From 39074ba3c1cd732d354905ee0363eeeb7eea2767 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Nov 2022 15:14:29 +0900 Subject: [PATCH 3173/3664] [qw] Implement hud ping and pl indicators As well as the periodic update of pings when the scoreboard or hud ping are shown. --- include/client/hud.h | 2 + include/sbar.h | 3 + libs/client/hud.c | 2 + libs/client/sbar.c | 148 +++++++++++++++--------------------------- qw/include/client.h | 1 + qw/source/cl_main.c | 3 + qw/source/cl_ngraph.c | 16 +++++ 7 files changed, 81 insertions(+), 94 deletions(-) diff --git a/include/client/hud.h b/include/client/hud.h index 95dd86a5d..97efb507b 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -72,6 +72,8 @@ extern struct view_s hud_overlay_view; extern struct view_s hud_stuff_view; extern struct view_s hud_time_view; extern struct view_s hud_fps_view; +extern struct view_s hud_ping_view; +extern struct view_s hud_pl_view; void HUD_Init (void); void HUD_Init_Cvars (void); diff --git a/include/sbar.h b/include/sbar.h index 1ca13870d..94c90e31a 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -48,6 +48,8 @@ typedef enum { sbc_num_changed } sbar_changed; +extern qboolean sbar_showscores; + struct player_info_s; void Sbar_Init (int *stats, float *item_gettime); void Sbar_SetPlayers (struct player_info_s *players, int maxplayers); @@ -59,6 +61,7 @@ void Sbar_SetActive (int active); void Sbar_Update (double time); void Sbar_UpdatePings (void); +void Sbar_UpdatePL (int pl); void Sbar_UpdateFrags (int playernum); void Sbar_UpdateInfo (int playernum); void Sbar_UpdateStats (int stat); diff --git a/libs/client/hud.c b/libs/client/hud.c index 01eb03597..20402f16f 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -175,6 +175,8 @@ view_t hud_overlay_view; view_t hud_stuff_view; view_t hud_time_view; view_t hud_fps_view; +view_t hud_ping_view; +view_t hud_pl_view; static void hud_add_outlines (view_t view) diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 5efa0e743..c07c9de3a 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -68,7 +68,6 @@ #include "gamedefs.h" int sb_updates; // if >= vid.numpages, no update needed -static int sb_update_flags; static int sb_view_size; static int fps_count; @@ -225,6 +224,8 @@ static view_def_t sbar_defs[] = { static draw_charbuffer_t *time_buff; static draw_charbuffer_t *fps_buff; +static draw_charbuffer_t *ping_buff; +static draw_charbuffer_t *pl_buff; static draw_charbuffer_t *solo_monsters; static draw_charbuffer_t *solo_secrets; @@ -288,7 +289,7 @@ static qpic_t *sb_face_quad; static qpic_t *sb_face_invuln; static qpic_t *sb_face_invis_invuln; -static qboolean sb_showscores; +qboolean sbar_showscores; static qboolean sb_showteamscores; static int sb_lines; // scan lines to draw @@ -1004,7 +1005,7 @@ draw_status (view_t *view) if (autocam != CAM_TRACK) return; } - if (sb_showscores || sbar_stats[STAT_HEALTH] <= 0) { + if (sbar_showscores || sbar_stats[STAT_HEALTH] <= 0) { draw_solo (view); return; } @@ -1141,7 +1142,7 @@ static void __attribute__((used)) draw_rogue_status (view_t *view) { #if 0 - if (sb_showscores || sbar_stats[STAT_HEALTH] <= 0) { + if (sbar_showscores || sbar_stats[STAT_HEALTH] <= 0) { draw_solo (view); return; } @@ -1301,7 +1302,7 @@ static void __attribute__((used)) draw_hipnotic_status (view_t *view) { #if 0 - if (sb_showscores || sbar_stats[STAT_HEALTH] <= 0) { + if (sbar_showscores || sbar_stats[STAT_HEALTH] <= 0) { draw_solo (view); return; } @@ -1531,36 +1532,6 @@ calc_fph (int frags, int total) static void Sbar_DeathmatchOverlay (view_t view) { -#if 0 - // this should be on a timer and needs nq/qw specific variants - // request new ping times every two seconds - if (!cls.demoplayback && realtime - cl.last_ping_request > 2) { - cl.last_ping_request = realtime; - MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, "pings"); - } - if (hud_ping) { - int ping = sbar_players[sbar_playernum].ping; - - ping = bound (0, ping, 999); - draw_string (view, 0, 0, va (0, "%3d ms ", ping)); - } - - if (hud_ping && hud_pl) - draw_character (view, 48, 0, '/'); - - if (hud_pl) { - int lost = CL_CalcNet (); - - lost = bound (0, lost, 999); - draw_string (view, 56, 0, va (0, "%3d pl", lost)); - } -#endif - // 0, 0 "gfx/ranking.lmp" - // 80, 40 - // - // for all qw, spectator replaces main, team at 72,0 88,8 - Sbar_SortFrags (0); int y = 40; @@ -1671,45 +1642,32 @@ Sbar_TeamOverlay (view_t *view) #endif } +#if 0 static void Sbar_DrawScoreboard (void) { -#if 0 //Sbar_SoloScoreboard (); if (cl.gametype == GAME_DEATHMATCH) Sbar_DeathmatchOverlay (hud_overlay_view); -#endif -} - -static void -draw_overlay (view_t *view) -{ - if (sb_showscores || sbar_stats[STAT_HEALTH] <= 0) { - Sbar_DrawScoreboard (); - } -#if 0 if (!sbar_active || !((sbar_stats[STAT_HEALTH] <= 0 && !sbar_spectator) - || sb_showscores || sb_showteamscores)) + || sbar_showscores || sb_showteamscores)) return; // main screen deathmatch rankings // if we're dead show team scores in team games if (sbar_stats[STAT_HEALTH] <= 0 && !sbar_spectator) - if (sbar_teamplay > 0 && !sb_showscores) + if (sbar_teamplay > 0 && !sbar_showscores) Sbar_TeamOverlay (view); else Sbar_DeathmatchOverlay (view, 0); - else if (sb_showscores) + else if (sbar_showscores) Sbar_DeathmatchOverlay (view, 0); else if (sb_showteamscores) Sbar_TeamOverlay (view); -#endif } +#endif -/* - Sbar_LogFrags - - autologging of frags after a match ended +/* autologging of frags after a match ended (called by recived network packet with command scv_intermission) TODO: Find a new and better place for this function (i am nearly shure this is wrong place) @@ -1853,36 +1811,6 @@ draw_fps (view_t view) write_charbuff (fps_buff, 0, 0, st); } -#if 0 -static void -draw_net (view_t *view) -{ - // request new ping times every two seconds - if (!cls.demoplayback && realtime - cl.last_ping_request > 2) { - cl.last_ping_request = realtime; - MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - SZ_Print (&cls.netchan.message, "pings"); - } - if (hud_ping) { - int ping = sbar_players[sbar_playernum].ping; - - ping = bound (0, ping, 999); - draw_string (view, 0, 0, va (0, "%3d ms ", ping)); - } - - if (hud_ping && hud_pl) - draw_character (view, 48, 0, '/'); - - if (hud_pl) { - int lost = CL_CalcNet (); - - lost = bound (0, lost, 999); - draw_string (view, 56, 0, va (0, "%3d pl", lost)); - } -} -if (sbar_active && (hud_ping || hud_pl)) -#endif - static void draw_intermission (view_t view) { @@ -2067,17 +1995,13 @@ Sbar_Update (double time) if (!sbar_active) { return; } - if (sb_update_flags & (1 << sbc_info)) { - draw_overlay (0); - } - if (sb_showscores) { + if (sbar_showscores) { draw_solo_time (); } - sb_update_flags = 0; } void -Sbar_UpdatePings () +Sbar_UpdatePings (void) { for (int i = 0; i < sbar_maxplayers; i++) { player_info_t *p = &sbar_players[i]; @@ -2087,6 +2011,14 @@ Sbar_UpdatePings () write_charbuff (sb_ping[i], 0, 0, va (0, "%3d", p->ping)); write_charbuff (sb_pl[i], 0, 0, va (0, "%3d", p->pl)); } + write_charbuff (ping_buff, 0, 0, + va (0, "%3d ms", sbar_players[sbar_playernum].ping)); +} + +void +Sbar_UpdatePL (int pl) +{ + write_charbuff (pl_buff, 0, 0, va (0, "%3d pl", pl)); } void @@ -2407,6 +2339,26 @@ sbar_hud_fps_f (void *data, const cvar_t *cvar) } } +static void +sbar_hud_ping_f (void *data, const cvar_t *cvar) +{ + if (hud_ping) { + sbar_setcomponent (hud_ping_view, hud_charbuff, &ping_buff); + } else { + sbar_remcomponent (hud_ping_view, hud_charbuff); + } +} + +static void +sbar_hud_pl_f (void *data, const cvar_t *cvar) +{ + if (hud_pl) { + sbar_setcomponent (hud_pl_view, hud_charbuff, &pl_buff); + } else { + sbar_remcomponent (hud_pl_view, hud_charbuff); + } +} + static void sbar_hud_time_f (void *data, const cvar_t *cvar) { @@ -2708,9 +2660,13 @@ init_views (void) hud_stuff_view = sbar_view (0, 48, 152, 16, grav_southwest, cl_screen_view); hud_time_view = sbar_view (8, 0, 64, 8, grav_northwest, hud_stuff_view); hud_fps_view = sbar_view (80, 0, 72, 8, grav_northwest, hud_stuff_view); + hud_ping_view = sbar_view (0, 0, 48, 0, grav_northwest, hud_stuff_view); + hud_pl_view = sbar_view (56, 0, 72, 0, grav_northwest, hud_stuff_view); time_buff = Draw_CreateBuffer (8, 1); fps_buff = Draw_CreateBuffer (11, 1); + ping_buff = Draw_CreateBuffer (11, 1); + pl_buff = Draw_CreateBuffer (11, 1); for (int i = 0; i < MAX_PLAYERS; i++) { sb_fph[i] = Draw_CreateBuffer (3, 1); sb_time[i] = Draw_CreateBuffer (4, 1); @@ -2900,10 +2856,10 @@ load_pics (void) static void Sbar_ShowScores (void) { - if (sb_showscores) + if (sbar_showscores) return; - sb_showscores = true; + sbar_showscores = true; sb_updates = 0; sbar_setcomponent (sbar_solo, hud_pic, &sb_scorebar); @@ -2919,10 +2875,10 @@ Sbar_ShowScores (void) static void Sbar_DontShowScores (void) { - if (!sb_showscores) + if (!sbar_showscores) return; - sb_showscores = false; + sbar_showscores = false; sb_updates = 0; sbar_remcomponent (sbar_solo, hud_pic); @@ -2968,6 +2924,8 @@ Sbar_Init (int *stats, float *item_gettime) Cvar_AddListener (Cvar_FindVar ("hud_swap"), sbar_hud_swap_f, 0); Cvar_AddListener (Cvar_FindVar ("hud_fps"), sbar_hud_fps_f, 0); Cvar_AddListener (Cvar_FindVar ("hud_time"), sbar_hud_time_f, 0); + Cvar_AddListener (Cvar_FindVar ("hud_pl"), sbar_hud_pl_f, 0); + Cvar_AddListener (Cvar_FindVar ("hud_ping"), sbar_hud_ping_f, 0); load_pics (); init_views (); @@ -2978,6 +2936,8 @@ Sbar_Init (int *stats, float *item_gettime) sbar_hud_fps_f (0, 0); sbar_hud_time_f (0, 0); + sbar_hud_pl_f (0, 0); + sbar_hud_ping_f (0, 0); Cmd_AddCommand ("+showscores", Sbar_ShowScores, "Display information on everyone playing"); diff --git a/qw/include/client.h b/qw/include/client.h index 854a5a987..b13125acf 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -292,6 +292,7 @@ void Cvar_Info (void *data, const struct cvar_s *cvar); void CL_NetGraph_Init (void); void CL_NetGraph_Init_Cvars (void); +void CL_NetUpdate (void); void CL_SetState (cactive_t state); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index c7411af43..6b49cc528 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1944,6 +1944,9 @@ Host_Frame (float time) r_data->frametime = host_frametime; cl.viewstate.time = realtime; + if (!cls.demoplayback) { + CL_NetUpdate (); + } Sbar_Update (cl.time); CL_UpdateScreen (&cl.viewstate); diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 1d7bf282f..423d092a1 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -173,3 +173,19 @@ CL_NetGraph_Init_Cvars (void) Cvar_Register (&cl_netgraph_box_cvar, 0, 0); Cvar_Register (&cl_netgraph_height_cvar, cl_netgraph_height_f, 0); } + +void +CL_NetUpdate (void) +{ + if ((hud_ping || sbar_showscores) + && realtime - cl.last_ping_request > 2) { + // FIXME this should be on a timer + cl.last_ping_request = realtime; + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + SZ_Print (&cls.netchan.message, "pings"); + } + + if (hud_pl) { + Sbar_UpdatePL (CL_CalcNet ()); + } +} From 74e64d7228c9fcf15386af5a7145ac8abbb37c01 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Nov 2022 15:35:14 +0900 Subject: [PATCH 3174/3664] [client] Implement sbar flashes for items Sigils can't be flashed as they don't have any animations provided, and they're not normally as critical. I don't know why items weren't flashed, but since the pics are there, might as well use them (and the flashing keys do look pretty good). --- libs/client/sbar.c | 79 ++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/libs/client/sbar.c b/libs/client/sbar.c index c07c9de3a..08ee8df8b 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -280,7 +280,8 @@ static hud_subpic_t sb_weapons[7][8]; static qpic_t *sb_ammo[4]; static qpic_t *sb_sigil[4]; static qpic_t *sb_armor[3]; -static qpic_t *sb_items[32]; +// 0 is owned, 1-5 are flashes +static qpic_t *sb_items[6][32]; static qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive // 0 is static, 1 is temporary animation @@ -463,7 +464,7 @@ draw_ammo (view_t view) } static int -calc_flashon (float time, int mask) +calc_flashon (float time, int mask, int base) { int flashon; @@ -475,8 +476,9 @@ calc_flashon (float time, int mask) flashon = 1; else flashon = 0; - } else - flashon = (flashon % 5) + 2; + } else { + flashon = (flashon % 5) + base; + } return flashon; } @@ -488,7 +490,7 @@ draw_weapons (view_t view) for (i = 0; i < 7; i++) { view_t weap = View_GetChild (view, i); if (sbar_stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { - flashon = calc_flashon (sbar_item_gettime[i], IT_SHOTGUN << i); + flashon = calc_flashon (sbar_item_gettime[i], IT_SHOTGUN << i, 2); if (flashon > 1) sb_updates = 0; // force update to remove flash sbar_setcomponent (weap, hud_subpic, &sb_weapons[flashon][i]); @@ -501,23 +503,15 @@ draw_weapons (view_t view) static void draw_items (view_t view) { - //float time; - //int flashon = 0, i; - for (int i = 0; i < 6; i++) { view_t item = View_GetChild (view, i); - if (sbar_stats[STAT_ITEMS] & (1 << (17 + i))) { -#if 0 - time = sbar_item_gettime[17 + i]; - if (time && time > sbar_time - 2 && flashon) { // Flash frame - sb_updates = 0; - } else { - draw_pic (view, i * 16, 0, sb_items[i]); - } - if (time && time > sbar_time - 2) - sb_updates = 0; -#endif - sbar_setcomponent (item, hud_pic, &sb_items[i]); + int item_ind = 17 + i; + if (sbar_stats[STAT_ITEMS] & (1 << item_ind)) { + int flashon = calc_flashon (sbar_item_gettime[item_ind], + -1, 1); + if (flashon > 1) + sb_updates = 0; // force update to remove flash + sbar_setcomponent (item, hud_pic, &sb_items[flashon][i]); } else { sbar_remcomponent (item, hud_pic); } @@ -527,22 +521,9 @@ draw_items (view_t view) static void draw_sigils (view_t view) { - //float time; - //int flashon = 0, i; - for (int i = 0; i < 4; i++) { view_t sigil = View_GetChild (view, i); if (sbar_stats[STAT_ITEMS] & (1 << (28 + i))) { -#if 0 - time = sbar_item_gettime[28 + i]; - if (time && time > sbar_time - 2 && flashon) { // flash frame - sb_updates = 0; - } else { - draw_pic (view, i * 8, 0, sb_sigil[i]); - } - if (time && time > sbar_time - 2) - sb_updates = 0; -#endif sbar_setcomponent (sigil, hud_pic, &sb_sigil[i]); } else { sbar_remcomponent (sigil, hud_pic); @@ -1045,7 +1026,7 @@ draw_rogue_weapons_hud (view_t *view) for (i = cl_screen_view->ylen < 204; i < 7; i++) { if (sbar_stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { - flashon = calc_flashon (sbar_item_gettime[i], IT_SHOTGUN << i); + flashon = calc_flashon (sbar_item_gettime[i], IT_SHOTGUN << i, 2); if (i >= 2) { j = i - 2; if (sbar_stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << j)) @@ -1202,7 +1183,7 @@ draw_hipnotic_weapons_sbar (view_t *view) time = sbar_item_gettime[hipweapons[h[i - 7]]]; } if (sbar_stats[STAT_ITEMS] & mask) { - flashon = calc_flashon (time, mask); + flashon = calc_flashon (time, mask, 2); if (i == 4 && sbar_stats[STAT_ACTIVEWEAPON] == (1 << hipweapons[3])) continue; @@ -1243,7 +1224,7 @@ draw_hipnotic_weapons_hud (view_t *view) time = sbar_item_gettime[hipweapons[h[i - 7]]]; } if (sbar_stats[STAT_ITEMS] & mask) { - flashon = calc_flashon (time, mask); + flashon = calc_flashon (time, mask, 2); if (i < 7) { pic = sb_weapons[flashon][i]; @@ -1998,6 +1979,12 @@ Sbar_Update (double time) if (sbar_showscores) { draw_solo_time (); } + if (sb_updates < r_data->vid->numpages) { + //FIXME find a better way to support animations + sb_updates++; + draw_weapons (sbar_weapons); + draw_items (sbar_items); + } } void @@ -2766,12 +2753,20 @@ load_pics (void) sb_armor[1] = r_funcs->Draw_PicFromWad ("sb_armor2"); sb_armor[2] = r_funcs->Draw_PicFromWad ("sb_armor3"); - sb_items[0] = r_funcs->Draw_PicFromWad ("sb_key1"); - sb_items[1] = r_funcs->Draw_PicFromWad ("sb_key2"); - sb_items[2] = r_funcs->Draw_PicFromWad ("sb_invis"); - sb_items[3] = r_funcs->Draw_PicFromWad ("sb_invuln"); - sb_items[4] = r_funcs->Draw_PicFromWad ("sb_suit"); - sb_items[5] = r_funcs->Draw_PicFromWad ("sb_quad"); + sb_items[0][0] = r_funcs->Draw_PicFromWad ("sb_key1"); + sb_items[0][1] = r_funcs->Draw_PicFromWad ("sb_key2"); + sb_items[0][2] = r_funcs->Draw_PicFromWad ("sb_invis"); + sb_items[0][3] = r_funcs->Draw_PicFromWad ("sb_invuln"); + sb_items[0][4] = r_funcs->Draw_PicFromWad ("sb_suit"); + sb_items[0][5] = r_funcs->Draw_PicFromWad ("sb_quad"); + for (int i = 1; i <= 5; i++) { + sb_items[i][0] = r_funcs->Draw_PicFromWad (va (0, "sba%d_key1", i)); + sb_items[i][1] = r_funcs->Draw_PicFromWad (va (0, "sba%d_key2", i)); + sb_items[i][2] = r_funcs->Draw_PicFromWad (va (0, "sba%d_invis", i)); + sb_items[i][3] = r_funcs->Draw_PicFromWad (va (0, "sba%d_invul", i)); + sb_items[i][4] = r_funcs->Draw_PicFromWad (va (0, "sba%d_suit", i)); + sb_items[i][5] = r_funcs->Draw_PicFromWad (va (0, "sba%d_quad", i)); + } sb_sigil[0] = r_funcs->Draw_PicFromWad ("sb_sigil1"); sb_sigil[1] = r_funcs->Draw_PicFromWad ("sb_sigil2"); From 2fb5b67012bce29f18db917c4ba2ed13f3d25b3f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Nov 2022 21:19:01 +0900 Subject: [PATCH 3175/3664] [vulkan] Implement line graph rendering I should probably just use the line rendering for all renderers and pull the graph drawing out to the client code. --- include/QF/Vulkan/qf_draw.h | 3 +++ libs/video/renderer/vid_render_vulkan.c | 1 + libs/video/renderer/vulkan/vulkan_draw.c | 15 +++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index fa4f83772..1edb16882 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -85,4 +85,7 @@ void Vulkan_End2D (struct vulkan_ctx_s *ctx); void Vulkan_DrawReset (struct vulkan_ctx_s *ctx); void Vulkan_FlushText (struct qfv_renderframe_s *rFrame); +void Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height, + struct vulkan_ctx_s *ctx); + #endif//__QF_Vulkan_qf_draw_h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 6457ba8bc..733ada82d 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -136,6 +136,7 @@ vulkan_R_NewScene (scene_t *scene) static void vulkan_R_LineGraph (int x, int y, int *h_vals, int count, int height) { + Vulkan_LineGraph (x, y, h_vals, count, height, vulkan_ctx); } static void diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 127b6645e..f520e8ba5 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1330,3 +1330,18 @@ Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx); RText_DeleteShaper (shaper); } + +void +Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height, + vulkan_ctx_t *ctx) +{ + static int colors[] = { 0xd0, 0x4f, 0x6f }; + + while (count-- > 0) { + int h = *h_vals++; + int c = h < 9998 || h > 10000 ? 0xfe : colors[h - 9998]; + h = min (h, height); + Vulkan_Draw_Line (x, y, x, y - h, c, ctx); + x++; + } +} From c6b79d49a47500bae40bf6956b93184ea8bfa298 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Nov 2022 21:23:04 +0900 Subject: [PATCH 3176/3664] [client] Fix incorrect function component setup Need to pass the address of the pointer :/ --- include/QF/screen.h | 4 ++-- libs/client/cl_screen.c | 7 ++++--- libs/video/renderer/r_graph.c | 4 ++-- qw/source/cl_ngraph.c | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/QF/screen.h b/include/QF/screen.h index d5e7bd81f..e462b8269 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -52,7 +52,7 @@ extern int scr_copytop; extern qboolean scr_skipupdate; struct view_pos_s; -void R_TimeGraph (struct view_pos_s abs); -void R_ZGraph (struct view_pos_s abs); +void R_TimeGraph (struct view_pos_s abs, struct view_pos_s len); +void R_ZGraph (struct view_pos_s abs, struct view_pos_s len); #endif//__QF_screen_h diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index e48f6236e..84fdde018 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -220,15 +220,16 @@ CL_Init_Screen (void) View_SetPos (timegraph_view, 0, 0); View_SetLen (timegraph_view, r_data->vid->width, 100); View_SetGravity (timegraph_view, grav_southwest); - Ent_SetComponent (timegraph_view.id, hud_func, timegraph_view.reg, - R_TimeGraph); + void *rtg = R_TimeGraph; + Ent_SetComponent (timegraph_view.id, hud_func, timegraph_view.reg, &rtg); View_SetVisible (timegraph_view, r_timegraph); zgraph_view = View_New (hud_registry, cl_screen_view); View_SetPos (zgraph_view, 0, 0); View_SetLen (zgraph_view, r_data->vid->width, 100); View_SetGravity (zgraph_view, grav_southwest); - Ent_SetComponent (zgraph_view.id, hud_func, zgraph_view.reg, R_ZGraph); + void *rzg = R_ZGraph; + Ent_SetComponent (zgraph_view.id, hud_func, zgraph_view.reg, &rzg); View_SetVisible (zgraph_view, r_zgraph); const char *name = "gfx/loading.lmp"; diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index c42736210..a6f051353 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -50,7 +50,7 @@ int graphval; Performance monitoring tool */ void -R_TimeGraph (view_pos_t abs) +R_TimeGraph (view_pos_t abs, view_pos_t len) { static int timex; int a; @@ -85,7 +85,7 @@ R_TimeGraph (view_pos_t abs) } void -R_ZGraph (view_pos_t abs) +R_ZGraph (view_pos_t abs, view_pos_t len) { int w; static int height[256]; diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 423d092a1..f4ec199dc 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -157,7 +157,7 @@ void CL_NetGraph_Init (void) { cl_netgraph_view = View_New (hud_registry, cl_screen_view); - View_SetPos (cl_netgraph_view, 0, hud_sb_lines); + View_SetPos (cl_netgraph_view, 0, 64); View_SetLen (cl_netgraph_view, NET_TIMINGS + 16, cl_netgraph_height + 25); View_SetGravity (cl_netgraph_view, grav_southwest); void *f = CL_NetGraph; From 017bba8869f9f5b82a176cd6596326718b98bbe0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 10 Nov 2022 21:27:49 +0900 Subject: [PATCH 3177/3664] [client] Fix some view placement and buffer sizes --- libs/client/sbar.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 08ee8df8b..42c2dd118 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -1787,7 +1787,7 @@ draw_fps (view_t view) fps_count = 0; lastframetime = t; int prec = lastfps < 1000 ? 1 : 0; - snprintf (st, sizeof (st), "%5.*f FPS", prec, lastfps); + snprintf (st, sizeof (st), "%6.*f FPS", prec, lastfps); } write_charbuff (fps_buff, 0, 0, st); } @@ -2646,14 +2646,14 @@ init_views (void) { hud_stuff_view = sbar_view (0, 48, 152, 16, grav_southwest, cl_screen_view); hud_time_view = sbar_view (8, 0, 64, 8, grav_northwest, hud_stuff_view); - hud_fps_view = sbar_view (80, 0, 72, 8, grav_northwest, hud_stuff_view); - hud_ping_view = sbar_view (0, 0, 48, 0, grav_northwest, hud_stuff_view); - hud_pl_view = sbar_view (56, 0, 72, 0, grav_northwest, hud_stuff_view); + hud_fps_view = sbar_view (80, 0, 80, 8, grav_northwest, hud_stuff_view); + hud_ping_view = sbar_view (0, 8, 48, 0, grav_northwest, hud_stuff_view); + hud_pl_view = sbar_view (56, 8, 48, 0, grav_northwest, hud_stuff_view); time_buff = Draw_CreateBuffer (8, 1); - fps_buff = Draw_CreateBuffer (11, 1); - ping_buff = Draw_CreateBuffer (11, 1); - pl_buff = Draw_CreateBuffer (11, 1); + fps_buff = Draw_CreateBuffer (10, 1); + ping_buff = Draw_CreateBuffer (6, 1); + pl_buff = Draw_CreateBuffer (6, 1); for (int i = 0; i < MAX_PLAYERS; i++) { sb_fph[i] = Draw_CreateBuffer (3, 1); sb_time[i] = Draw_CreateBuffer (4, 1); From a91ae7aeb9d74c1d3d4ee1441c44ba746d1d194d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Nov 2022 13:00:40 +0900 Subject: [PATCH 3178/3664] [client] Implement hipnotic and rogue weapon views The functionality of the hipnotic and rogue weapon power-ups is now done by a various mappings instead of separate functions. In theory, this should make things more flexible, but most importantly, there's a lot less code duplication. --- libs/client/sbar.c | 293 ++++++++++++++++----------------------------- 1 file changed, 101 insertions(+), 192 deletions(-) diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 42c2dd118..ba7057366 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -214,6 +214,7 @@ static view_def_t sbar_defs[] = { {0, { 0, 0, 24, 24}, grav_northwest, &sbar_ammo, 4, 24, 0}, {0, { 0, 0, 16, 16}, grav_northwest, &sbar_items, 6, 16, 0}, {0, { 0, 0, 24, 16}, grav_northwest, &sbar_weapons, 7, 24, 0}, + {0, { 0, 0,176, 16}, grav_northwest, &sbar_weapons, 2, 24, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 3, 24, 0}, {0, {10, 0, 24, 8}, grav_northwest, &sbar_miniammo, 4, 48, 0}, @@ -276,7 +277,11 @@ static qpic_t *sb_sbar; static qpic_t *sb_scorebar; // 0 is active, 1 is owned, 2-6 are flashes -static hud_subpic_t sb_weapons[7][8]; +// 0-6 id, 7-9 hip (laser, mjolnir, prox), 7-11 rogue powerups +static int sb_weapon_count; +static int sb_weapon_view_count; +static int sb_game; +static hud_subpic_t sb_weapons[7][12]; static qpic_t *sb_ammo[4]; static qpic_t *sb_sigil[4]; static qpic_t *sb_armor[3]; @@ -296,17 +301,12 @@ static qboolean sb_showteamscores; static int sb_lines; // scan lines to draw static qpic_t *rsb_invbar[2]; -static qpic_t *rsb_weapons[5]; static qpic_t *rsb_items[2]; static qpic_t *rsb_ammo[3]; static qpic_t *rsb_teambord; // PGM 01/19/97 - team color border // MED 01/04/97 added two more weapons + 3 // alternates for grenade launcher -static qpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes - - // MED 01/04/97 added array to simplify - // weapon parsing //static int hipweapons[4] = // { HIT_LASER_CANNON_BIT, HIT_MJOLNIR_BIT, 4, HIT_PROXIMITY_GUN_BIT }; qpic_t *hsb_items[2]; // MED 01/04/97 added hipnotic items array @@ -486,14 +486,38 @@ static void draw_weapons (view_t view) { int flashon, i; + static byte view_map[2][12] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 4 }, // id/hipnotic + { 0, 1, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6 }, // rogue + }; + static byte item_map[2][12] = { + { 0, 1, 2, 3, 4, 5, 6, // id/hipnotic + HIT_LASER_CANNON_BIT, HIT_MJOLNIR_BIT, HIT_PROXIMITY_GUN_BIT }, + { 0, 1, 2, 3, 4, 5, 6, 12, 13, 14, 15, 16 }, // rogue + }; + static int active_map[2][12] = { + { [9] = HIT_PROXIMITY_GUN }, // id/hipnotic + { [7] = RIT_LAVA_NAILGUN, + [8] = RIT_LAVA_SUPER_NAILGUN, + [9] = RIT_MULTI_GRENADE, + [10] = RIT_MULTI_ROCKET, + [11] = RIT_PLASMA_GUN, + }, // rogue + }; - for (i = 0; i < 7; i++) { - view_t weap = View_GetChild (view, i); - if (sbar_stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { - flashon = calc_flashon (sbar_item_gettime[i], IT_SHOTGUN << i, 2); - if (flashon > 1) - sb_updates = 0; // force update to remove flash - sbar_setcomponent (weap, hud_subpic, &sb_weapons[flashon][i]); + for (i = 0; i < sb_weapon_count; i++) { + view_t weap = View_GetChild (view, view_map[sb_game][i]); + int mask = 1 << item_map[sb_game][i]; + float time = sbar_item_gettime[item_map[sb_game][i]]; + int active = active_map[sb_game][i]; + + if (sbar_stats[STAT_ITEMS] & mask) { + if ((sbar_stats[STAT_ACTIVEWEAPON] & active) == active) { + flashon = calc_flashon (time, mask, 2); + if (flashon > 1) + sb_updates = 0; // force update to remove flash + sbar_setcomponent (weap, hud_subpic, &sb_weapons[flashon][i]); + } } else { sbar_remcomponent (weap, hud_subpic); } @@ -998,52 +1022,6 @@ draw_status (view_t *view) } #endif -static void __attribute__((used)) -draw_rogue_weapons_sbar (view_t *view) -{ -#if 0 - int i; - - draw_weapons_sbar (view); - - // check for powered up weapon. - if (sbar_stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) { - for (i = 0; i < 5; i++) { - if (sbar_stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i)) { - draw_pic (view, (i + 2) * 24, 0, rsb_weapons[i]); - } - } - } -#endif -} - -static void __attribute__((used)) -draw_rogue_weapons_hud (view_t *view) -{ -#if 0 - int flashon, i, j; - qpic_t *pic; - - for (i = cl_screen_view->ylen < 204; i < 7; i++) { - if (sbar_stats[STAT_ITEMS] & (IT_SHOTGUN << i)) { - flashon = calc_flashon (sbar_item_gettime[i], IT_SHOTGUN << i, 2); - if (i >= 2) { - j = i - 2; - if (sbar_stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << j)) - pic = rsb_weapons[j]; - else - pic = sb_weapons[flashon][i]; - } else { - pic = sb_weapons[flashon][i]; - } - draw_subpic (view, 0, i * 16, pic, 0, 0, 24, 16); - if (flashon > 1) - sb_updates = 0; // force update to remove flash - } - } -#endif -} - static void __attribute__((used)) draw_rogue_ammo_hud (view_t *view) { @@ -1163,84 +1141,6 @@ draw_rogue_status (view_t *view) #endif } -static void __attribute__((used)) -draw_hipnotic_weapons_sbar (view_t *view) -{ -#if 0 - static int x[] = {0, 24, 48, 72, 96, 120, 144, 176, 200, 96}; - static int h[] = {0, 1, 3}; - int flashon, i; - qpic_t *pic; - int mask; - float time; - - for (i = 0; i < 10; i++) { - if (i < 7) { - mask = IT_SHOTGUN << i; - time = sbar_item_gettime[i]; - } else { - mask = 1 << hipweapons[h[i - 7]]; - time = sbar_item_gettime[hipweapons[h[i - 7]]]; - } - if (sbar_stats[STAT_ITEMS] & mask) { - flashon = calc_flashon (time, mask, 2); - - if (i == 4 && sbar_stats[STAT_ACTIVEWEAPON] == (1 << hipweapons[3])) - continue; - if (i == 9 && sbar_stats[STAT_ACTIVEWEAPON] != (1 << hipweapons[3])) - continue; - if (i < 7) { - pic = sb_weapons[flashon][i]; - } else { - pic = hsb_weapons[flashon][h[i - 7]]; - } - - draw_subpic (view, x[i], 0, pic, 0, 0, 24, 16); - - if (flashon > 1) - sb_updates = 0; // force update to remove flash - } - } -#endif -} - -static void __attribute__((used)) -draw_hipnotic_weapons_hud (view_t *view) -{ -#if 0 - int flashon, i; - static int y[] = {0, 16, 32, 48, 64, 96, 112, 128, 144, 80}; - static int h[] = {0, 1, 3}; - qpic_t *pic; - int mask; - float time; - - for (i = 0; i < 10; i++) { - if (i < 7) { - mask = IT_SHOTGUN << i; - time = sbar_item_gettime[i]; - } else { - mask = 1 << hipweapons[h[i - 7]]; - time = sbar_item_gettime[hipweapons[h[i - 7]]]; - } - if (sbar_stats[STAT_ITEMS] & mask) { - flashon = calc_flashon (time, mask, 2); - - if (i < 7) { - pic = sb_weapons[flashon][i]; - } else { - pic = hsb_weapons[flashon][h[i - 7]]; - } - - draw_subpic (view, 0, y[i], pic, 0, 0, 24, 16); - - if (flashon > 1) - sb_updates = 0; // force update to remove flash - } - } -#endif -} - static void __attribute__((used)) draw_hipnotic_items (view_t *view) { @@ -2231,10 +2131,12 @@ set_hud_sbar (void) View_SetLen (sbar_miniammo, 202, 8); View_SetGravity (sbar_miniammo, grav_northwest); - for (int i = 0; i < 7; i++) { + int x = 0; + for (int i = 0; i < sb_weapon_view_count; i++) { v = View_GetChild (sbar_weapons, i); - View_SetPos (v, i * 24, 0); - View_SetLen (v, 24 + 24 * (i == 6), 16); + View_SetPos (v, x, 0); + View_SetLen (v, sb_weapons[0][i].pic->width, 16); + x += sb_weapons[0][i].pic->width; if (sbar_hascomponent (v, hud_subpic)) { hud_subpic_t *subpic = sbar_getcomponent(v, hud_subpic); @@ -2248,7 +2150,7 @@ set_hud_sbar (void) sbar_remcomponent (v, hud_subpic); } for (int i = 0; i < 7; i++) { - for (int j = 0; j < 8; j++) { + for (int j = 0; j < sb_weapon_view_count; j++) { if (sb_weapons[i][j].pic) { sb_weapons[i][j].w = sb_weapons[i][j].pic->width; sb_weapons[i][j].h = sb_weapons[i][j].pic->height; @@ -2263,16 +2165,16 @@ set_hud_sbar (void) } else { View_SetParent (sbar_armament, hud_view); View_SetPos (sbar_armament, 0, 48); - View_SetLen (sbar_armament, 42, 156); + View_SetLen (sbar_armament, 42, 44 + 16 * sb_weapon_view_count); View_SetGravity (sbar_armament, grav_southeast); - View_SetLen (sbar_weapons, 24, 112); + View_SetLen (sbar_weapons, 24, 16 * sb_weapon_view_count); View_SetGravity (sbar_weapons, grav_northeast); View_SetLen (sbar_miniammo, 42, 44); View_SetGravity (sbar_miniammo, grav_southeast); - for (int i = 0; i < 7; i++) { + for (int i = 0; i < sb_weapon_view_count; i++) { v = View_GetChild (sbar_weapons, i); View_SetPos (v, 0, i * 16); View_SetLen (v, 24, 16); @@ -2290,7 +2192,7 @@ set_hud_sbar (void) sbar_setcomponent (v, hud_subpic, &subpic); } for (int i = 0; i < 7; i++) { - for (int j = 0; j < 8; j++) { + for (int j = 0; j < sb_weapon_view_count; j++) { if (sb_weapons[i][j].pic) { sb_weapons[i][j].w = 24; sb_weapons[i][j].h = sb_weapons[i][j].pic->height; @@ -2424,10 +2326,10 @@ init_sbar_views (void) solo_name = Draw_CreateBuffer (20, 1); } +#if 0 static void init_hipnotic_sbar_views (void) { -#if 0 view_t *view; sbar_view = view_new (0, 0, 320, 48, grav_south); @@ -2480,13 +2382,13 @@ init_hipnotic_sbar_views (void) view->resize_y = 1; view_add (sbar_view, view); } -#endif } +#endif +#if 0 static void init_hipnotic_hud_views (void) { -#if 0 view_t *view; hud_view = view_new (0, 0, 320, 48, grav_south); @@ -2536,13 +2438,13 @@ init_hipnotic_hud_views (void) view_add (hud_view, hud_armament_view); view_insert (hud_main_view, hud_view, 0); -#endif } +#endif +#if 0 static void init_rogue_sbar_views (void) { -#if 0 view_t *view; sbar_view = view_new (0, 0, 320, 48, grav_south); @@ -2591,13 +2493,13 @@ init_rogue_sbar_views (void) view->resize_y = 1; view_add (sbar_view, view); } -#endif } +#endif +#if 0 static void init_rogue_hud_views (void) { -#if 0 view_t *view; hud_view = view_new (0, 0, 320, 48, grav_south); @@ -2638,8 +2540,8 @@ init_rogue_hud_views (void) view_add (hud_view, hud_armament_view); view_insert (hud_main_view, hud_view, 0); -#endif } +#endif static void init_views (void) @@ -2669,15 +2571,7 @@ init_views (void) sb_spectator = Draw_CreateBuffer (11, 1); write_charbuff (sb_spectator, 0, 0, "(spectator)"); - if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) { - init_hipnotic_sbar_views (); - init_hipnotic_hud_views (); - } else if (!strcmp (qfs_gamedir->hudtype, "rogue")) { - init_rogue_sbar_views (); - init_rogue_hud_views (); - } else { - init_sbar_views (); - } + init_sbar_views (); } static void @@ -2735,14 +2629,6 @@ load_pics (void) sb_weapons[2 + i][6].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_lightng", i + 1)); } - for (int i = 0; i < 7; i++) { - for (int j = 0; j < 8; j++) { - if (sb_weapons[i][j].pic) { - sb_weapons[i][j].w = sb_weapons[i][j].pic->width; - sb_weapons[i][j].h = sb_weapons[i][j].pic->height; - } - } - } sb_ammo[0] = r_funcs->Draw_PicFromWad ("sb_shells"); sb_ammo[1] = r_funcs->Draw_PicFromWad ("sb_nails"); @@ -2792,32 +2678,37 @@ load_pics (void) sb_sbar = r_funcs->Draw_PicFromWad ("sbar"); sb_ibar = r_funcs->Draw_PicFromWad ("ibar"); sb_scorebar = r_funcs->Draw_PicFromWad ("scorebar"); + sb_weapon_count = 7; + sb_weapon_view_count = 7; + sb_game = 0; // MED 01/04/97 added new hipnotic weapons if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) { - hsb_weapons[0][0] = r_funcs->Draw_PicFromWad ("inv_laser"); - hsb_weapons[0][1] = r_funcs->Draw_PicFromWad ("inv_mjolnir"); - hsb_weapons[0][2] = r_funcs->Draw_PicFromWad ("inv_gren_prox"); - hsb_weapons[0][3] = r_funcs->Draw_PicFromWad ("inv_prox_gren"); - hsb_weapons[0][4] = r_funcs->Draw_PicFromWad ("inv_prox"); + sb_weapon_count = 10; + sb_weapon_view_count = 9; + sb_weapons[0][7].pic = r_funcs->Draw_PicFromWad ("inv_laser"); + sb_weapons[0][8].pic = r_funcs->Draw_PicFromWad ("inv_mjolnir"); + sb_weapons[0][9].pic = r_funcs->Draw_PicFromWad ("inv_prox_gren"); + //sb_weapons[0][3].pic = r_funcs->Draw_PicFromWad ("inv_gren_prox"); + //sb_weapons[0][4] = r_funcs->Draw_PicFromWad ("inv_prox"); - hsb_weapons[1][0] = r_funcs->Draw_PicFromWad ("inv2_laser"); - hsb_weapons[1][1] = r_funcs->Draw_PicFromWad ("inv2_mjolnir"); - hsb_weapons[1][2] = r_funcs->Draw_PicFromWad ("inv2_gren_prox"); - hsb_weapons[1][3] = r_funcs->Draw_PicFromWad ("inv2_prox_gren"); - hsb_weapons[1][4] = r_funcs->Draw_PicFromWad ("inv2_prox"); + sb_weapons[1][7].pic = r_funcs->Draw_PicFromWad ("inv2_laser"); + sb_weapons[1][8].pic = r_funcs->Draw_PicFromWad ("inv2_mjolnir"); + sb_weapons[1][9].pic = r_funcs->Draw_PicFromWad ("inv2_prox_gren"); + //sb_weapons[1][3].pic = r_funcs->Draw_PicFromWad ("inv2_gren_prox"); + //sb_weapons[1][4] = r_funcs->Draw_PicFromWad ("inv2_prox"); for (int i = 0; i < 5; i++) { - hsb_weapons[2 + i][0] = + sb_weapons[2 + i][7].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_laser", i + 1)); - hsb_weapons[2 + i][1] = + sb_weapons[2 + i][8].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_mjolnir", i + 1)); - hsb_weapons[2 + i][2] = - r_funcs->Draw_PicFromWad (va (0, "inva%i_gren_prox", i + 1)); - hsb_weapons[2 + i][3] = + sb_weapons[2 + i][9].pic = r_funcs->Draw_PicFromWad (va (0, "inva%i_prox_gren", i + 1)); - hsb_weapons[2 + i][4] = - r_funcs->Draw_PicFromWad (va (0, "inva%i_prox", i + 1)); + //sb_weapons[2 + i][2] = + // r_funcs->Draw_PicFromWad (va (0, "inva%i_gren_prox", i + 1)); + //sb_weapons[2 + i][4] = + // r_funcs->Draw_PicFromWad (va (0, "inva%i_prox", i + 1)); } hsb_items[0] = r_funcs->Draw_PicFromWad ("sb_wsuit"); @@ -2826,14 +2717,23 @@ load_pics (void) // FIXME: MISSIONHUD if (!strcmp (qfs_gamedir->hudtype, "rogue")) { + sb_weapon_count = 12; + sb_game = 1; rsb_invbar[0] = r_funcs->Draw_PicFromWad ("r_invbar1"); rsb_invbar[1] = r_funcs->Draw_PicFromWad ("r_invbar2"); - rsb_weapons[0] = r_funcs->Draw_PicFromWad ("r_lava"); - rsb_weapons[1] = r_funcs->Draw_PicFromWad ("r_superlava"); - rsb_weapons[2] = r_funcs->Draw_PicFromWad ("r_gren"); - rsb_weapons[3] = r_funcs->Draw_PicFromWad ("r_multirock"); - rsb_weapons[4] = r_funcs->Draw_PicFromWad ("r_plasma"); + sb_weapons[0][7].pic = r_funcs->Draw_PicFromWad ("r_lava"); + sb_weapons[0][8].pic = r_funcs->Draw_PicFromWad ("r_superlava"); + sb_weapons[0][9].pic = r_funcs->Draw_PicFromWad ("r_gren"); + sb_weapons[0][10].pic = r_funcs->Draw_PicFromWad ("r_multirock"); + sb_weapons[0][11].pic = r_funcs->Draw_PicFromWad ("r_plasma"); + for (int i = 1; i < 7; i++) { + sb_weapons[i][7].pic = sb_weapons[0][7].pic; + sb_weapons[i][8].pic = sb_weapons[0][8].pic; + sb_weapons[i][9].pic = sb_weapons[0][9].pic; + sb_weapons[i][10].pic = sb_weapons[0][10].pic; + sb_weapons[i][11].pic = sb_weapons[0][11].pic; + } rsb_items[0] = r_funcs->Draw_PicFromWad ("r_shield1"); rsb_items[1] = r_funcs->Draw_PicFromWad ("r_agrav1"); @@ -2846,6 +2746,15 @@ load_pics (void) rsb_ammo[1] = r_funcs->Draw_PicFromWad ("r_ammomulti"); rsb_ammo[2] = r_funcs->Draw_PicFromWad ("r_ammoplasma"); } + + for (int i = 0; i < 7; i++) { + for (int j = 0; j < 12; j++) { + if (sb_weapons[i][j].pic) { + sb_weapons[i][j].w = sb_weapons[i][j].pic->width; + sb_weapons[i][j].h = sb_weapons[i][j].pic->height; + } + } + } } static void From acedc906dd1b8109ceed59e52313b0bb096b250f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Nov 2022 15:18:31 +0900 Subject: [PATCH 3179/3664] [client] Implement hipnotic and rogue items This involved disabling sigils for hipnotic and rogue (not used), adjusting the number of items views, and moving the two keys views for hipnotic. Rogue is not yet using the correct status bar pics. --- libs/client/sbar.c | 250 ++++++++------------------------------------- 1 file changed, 41 insertions(+), 209 deletions(-) diff --git a/libs/client/sbar.c b/libs/client/sbar.c index ba7057366..d5c502f5a 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -212,8 +212,12 @@ static view_def_t sbar_defs[] = { {0, { 0, 0, 8, 16}, grav_northwest, &sbar_sigils, 4, 8, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_armor, 4, 24, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_ammo, 4, 24, 0}, - {0, { 0, 0, 16, 16}, grav_northwest, &sbar_items, 6, 16, 0}, + // hipnotic and rogue have 8 item slots and no sigils, so the two extra + // items overlap the sigils view + {0, { 0, 0, 16, 16}, grav_northwest, &sbar_items, 8, 16, 0}, {0, { 0, 0, 24, 16}, grav_northwest, &sbar_weapons, 7, 24, 0}, + // hipnotic adds two extra weapons that overlapp the keys views (which + // get moved for hipnotic). {0, { 0, 0,176, 16}, grav_northwest, &sbar_weapons, 2, 24, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 3, 24, 0}, {0, {10, 0, 24, 8}, grav_northwest, &sbar_miniammo, 4, 48, 0}, @@ -286,7 +290,8 @@ static qpic_t *sb_ammo[4]; static qpic_t *sb_sigil[4]; static qpic_t *sb_armor[3]; // 0 is owned, 1-5 are flashes -static qpic_t *sb_items[6][32]; +static int sb_item_count; +static qpic_t *sb_items[8][32]; static qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive // 0 is static, 1 is temporary animation @@ -301,16 +306,9 @@ static qboolean sb_showteamscores; static int sb_lines; // scan lines to draw static qpic_t *rsb_invbar[2]; -static qpic_t *rsb_items[2]; static qpic_t *rsb_ammo[3]; static qpic_t *rsb_teambord; // PGM 01/19/97 - team color border - // MED 01/04/97 added two more weapons + 3 - // alternates for grenade launcher -//static int hipweapons[4] = -// { HIT_LASER_CANNON_BIT, HIT_MJOLNIR_BIT, 4, HIT_PROXIMITY_GUN_BIT }; -qpic_t *hsb_items[2]; // MED 01/04/97 added hipnotic items array - //static qboolean largegame = false; char *fs_fraglog; @@ -527,9 +525,13 @@ draw_weapons (view_t view) static void draw_items (view_t view) { - for (int i = 0; i < 6; i++) { + static byte ind_map[2][8] = { + { 17, 18, 19, 20, 21, 22, 25, 26 }, // id/hipnotic + { 17, 18, 19, 20, 21, 22, 29, 30 }, // rogue + }; + for (int i = 0; i < sb_item_count; i++) { view_t item = View_GetChild (view, i); - int item_ind = 17 + i; + int item_ind = ind_map[sb_game][i]; if (sbar_stats[STAT_ITEMS] & (1 << item_ind)) { int flashon = calc_flashon (sbar_item_gettime[item_ind], -1, 1); @@ -1042,26 +1044,6 @@ draw_rogue_ammo_hud (view_t *view) #endif } -static void __attribute__((used)) -draw_rogue_items (view_t *view) -{ -#if 0 - int i; - float time; - - draw_items (view); - - for (i = 0; i < 2; i++) { - if (sbar_stats[STAT_ITEMS] & (1 << (29 + i))) { - time = sbar_item_gettime[29 + i]; - draw_pic (view, 96 + i * 16, 0, rsb_items[i]); - if (time && time > (sbar_time - 2)) - sb_updates = 0; - } - } -#endif -} - static void __attribute__((used)) draw_rogue_inventory_sbar (view_t *view) { @@ -1141,65 +1123,6 @@ draw_rogue_status (view_t *view) #endif } -static void __attribute__((used)) -draw_hipnotic_items (view_t *view) -{ -#if 0 - int i; - float time; - - // items - for (i = 2; i < 6; i++) { - if (sbar_stats[STAT_ITEMS] & (1 << (17 + i))) { - time = sbar_item_gettime[17 + i]; - draw_pic (view, 192 + i * 16, 0, sb_items[i]); - if (time && time > sbar_time - 2) - sb_updates = 0; - } - } - - // hipnotic items - for (i = 0; i < 2; i++) { - if (sbar_stats[STAT_ITEMS] & (1 << (24 + i))) { - time = sbar_item_gettime[24 + i]; - draw_pic (view, 288 + i * 16, 0, hsb_items[i]); - if (time && time > (sbar_time - 2)) - sb_updates = 0; - } - } -#endif -} - -static void __attribute__((used)) -draw_hipnotic_inventory_sbar (view_t *view) -{ -#if 0 - draw_pic (view, 0, 0, sb_ibar); - view_draw (view); -#endif -} - -static void __attribute__((used)) -draw_hipnotic_status (view_t *view) -{ -#if 0 - if (sbar_showscores || sbar_stats[STAT_HEALTH] <= 0) { - draw_solo (view); - return; - } - - draw_armor (view); - draw_face (view); - draw_health (view); - draw_ammo (view); - - if (sbar_stats[STAT_ITEMS] & IT_KEY1) - draw_pic (view, 209, 3, sb_items[0]); - if (sbar_stats[STAT_ITEMS] & IT_KEY2) - draw_pic (view, 209, 12, sb_items[1]); -#endif -} - static void setup_frags (view_t frags, int player) { @@ -2009,7 +1932,10 @@ static void update_items (int stat) { set_update (sbar_items, draw_items);//FIXME - set_update (sbar_sigils, draw_sigils);//FIXME + if (sb_item_count < 7) { + // hipnotic and rogue don't use sigils + set_update (sbar_sigils, draw_sigils);//FIXME + } set_update (sbar_weapons, draw_weapons);//FIXME } @@ -2324,122 +2250,21 @@ init_sbar_views (void) write_charbuff (solo_secrets, 0, 0, "Secrets :xxx /xxx"); solo_time = Draw_CreateBuffer (12, 1); solo_name = Draw_CreateBuffer (20, 1); -} -#if 0 -static void -init_hipnotic_sbar_views (void) -{ - view_t *view; - - sbar_view = view_new (0, 0, 320, 48, grav_south); - - sbar_frags_view = view_new (0, 0, 130, 8, grav_northeast); - sbar_frags_view->draw = draw_frags; - - sbar_inventory_view = view_new (0, 0, 320, 24, grav_northwest); - sbar_inventory_view->draw = draw_hipnotic_inventory_sbar; - - view = view_new (0, 0, 224, 16, grav_southwest); - view->draw = draw_hipnotic_weapons_sbar; - view_add (sbar_inventory_view, view); - - view = view_new (0, 0, 32, 8, grav_northwest); - view->draw = draw_ammo_sbar; - view_add (sbar_inventory_view, view); - - view = view_new (0, 0, 96, 16, grav_southeast); - view->draw = draw_hipnotic_items; - view_add (sbar_inventory_view, view); - - view = view_new (0, 0, 32, 16, grav_southeast); - view->draw = draw_sigils; - view_add (sbar_inventory_view, view); - - if (sbar_frags_view) - view_add (sbar_inventory_view, sbar_frags_view); - - view_add (sbar_view, sbar_inventory_view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_status_bar; - view_add (sbar_view, view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_hipnotic_status; - view_add (sbar_view, view); - - if (cl_screen_view->xlen > 320) { - int l = (cl_screen_view->xlen - 320) / 2; - - view = view_new (-l, 0, l, 48, grav_southwest); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); - - view = view_new (-l, 0, l, 48, grav_southeast); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); + sb_item_count = 6; + if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) { + sb_item_count = 8; + // adjust key view locations and sizes + for (int i = 0; i < 2; i++) { + view_t v = View_GetChild (sbar_items, i); + View_SetPos (v, 16, 16 + 3 + 9 * i); + View_SetLen (v, 16, 9); + } + } + if (!strcmp (qfs_gamedir->hudtype, "rogue")) { + sb_item_count = 8; } } -#endif - -#if 0 -static void -init_hipnotic_hud_views (void) -{ - view_t *view; - - hud_view = view_new (0, 0, 320, 48, grav_south); - hud_frags_view = view_new (0, 0, 130, 8, grav_northeast); - hud_frags_view->draw = draw_frags; - - hud_view->resize_y = 1; - - if (cl_screen_view->ylen < 252) { - hud_armament_view = view_new (0, min (cl_screen_view->ylen - 160, 48), - 66, 160, grav_southeast); - } else { - hud_armament_view = view_new (0, 48, 42, 204, grav_southeast); - } - - view = view_new (0, 0, 24, 160, grav_northeast); - view->draw = draw_hipnotic_weapons_hud; - view_add (hud_armament_view, view); - - view = view_new (0, 0, 42, 44, grav_southeast); - view->draw = draw_ammo_hud; - view_add (hud_armament_view, view); - - hud_inventory_view = view_new (0, 0, 320, 24, grav_northwest); - view_add (hud_view, hud_inventory_view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_hipnotic_status; - view_add (hud_view, view); - - view = view_new (0, 0, 96, 16, grav_southeast); - view->draw = draw_hipnotic_items; - view_add (hud_inventory_view, view); - - view = view_new (0, 0, 32, 16, grav_southeast); - view->draw = draw_sigils; - view_add (hud_inventory_view, view); - - if (hud_frags_view) - view_add (hud_inventory_view, hud_frags_view); - - view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); - view->resize_x = 1; - view_add (view, hud_view); - hud_view = view; - - view_add (hud_view, hud_armament_view); - - view_insert (hud_main_view, hud_view, 0); -} -#endif #if 0 static void @@ -2645,7 +2470,7 @@ load_pics (void) sb_items[0][3] = r_funcs->Draw_PicFromWad ("sb_invuln"); sb_items[0][4] = r_funcs->Draw_PicFromWad ("sb_suit"); sb_items[0][5] = r_funcs->Draw_PicFromWad ("sb_quad"); - for (int i = 1; i <= 5; i++) { + for (int i = 1; i < 6; i++) { sb_items[i][0] = r_funcs->Draw_PicFromWad (va (0, "sba%d_key1", i)); sb_items[i][1] = r_funcs->Draw_PicFromWad (va (0, "sba%d_key2", i)); sb_items[i][2] = r_funcs->Draw_PicFromWad (va (0, "sba%d_invis", i)); @@ -2711,8 +2536,8 @@ load_pics (void) // r_funcs->Draw_PicFromWad (va (0, "inva%i_prox", i + 1)); } - hsb_items[0] = r_funcs->Draw_PicFromWad ("sb_wsuit"); - hsb_items[1] = r_funcs->Draw_PicFromWad ("sb_eshld"); + sb_items[0][6] = r_funcs->Draw_PicFromWad ("sb_wsuit"); + sb_items[0][7] = r_funcs->Draw_PicFromWad ("sb_eshld"); } // FIXME: MISSIONHUD @@ -2735,8 +2560,8 @@ load_pics (void) sb_weapons[i][11].pic = sb_weapons[0][11].pic; } - rsb_items[0] = r_funcs->Draw_PicFromWad ("r_shield1"); - rsb_items[1] = r_funcs->Draw_PicFromWad ("r_agrav1"); + sb_items[0][6] = r_funcs->Draw_PicFromWad ("r_shield1"); + sb_items[0][7] = r_funcs->Draw_PicFromWad ("r_agrav1"); // PGM 01/19/97 - team color border rsb_teambord = r_funcs->Draw_PicFromWad ("r_teambord"); @@ -2755,6 +2580,13 @@ load_pics (void) } } } + for (int i = 1; i < 6; i++) { + for (int j = 0; j < 32; j++) { + if (!sb_items[i][j]) { + sb_items[i][j] = sb_items[0][j]; + } + } + } } static void From 7b167b2f35b619fe264ffde23451aca6a2f56773 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Nov 2022 18:27:51 +0900 Subject: [PATCH 3180/3664] [client] Implement rogue inventory bar switching And fix rogue ammo icons. --- libs/client/sbar.c | 263 +++++++++++---------------------------------- 1 file changed, 63 insertions(+), 200 deletions(-) diff --git a/libs/client/sbar.c b/libs/client/sbar.c index d5c502f5a..ae46540fb 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -276,7 +276,9 @@ sbar_remcomponent (view_t view, uint32_t comp) static qpic_t *sb_nums[2][11]; static qpic_t *sb_colon, *sb_slash; -static qpic_t *sb_ibar; +static qpic_t *sb_ibar[2]; +static int sb_ibar_index; +static hud_subpic_t sb_miniammo[4]; static qpic_t *sb_sbar; static qpic_t *sb_scorebar; @@ -286,7 +288,7 @@ static int sb_weapon_count; static int sb_weapon_view_count; static int sb_game; static hud_subpic_t sb_weapons[7][12]; -static qpic_t *sb_ammo[4]; +static qpic_t *sb_ammo[7]; // rogue adds 3 ammo types static qpic_t *sb_sigil[4]; static qpic_t *sb_armor[3]; // 0 is owned, 1-5 are flashes @@ -305,8 +307,6 @@ static qboolean sb_showteamscores; static int sb_lines; // scan lines to draw -static qpic_t *rsb_invbar[2]; -static qpic_t *rsb_ammo[3]; static qpic_t *rsb_teambord; // PGM 01/19/97 - team color border //static qboolean largegame = false; @@ -437,14 +437,31 @@ static void draw_ammo (view_t view) { qpic_t *pic = 0; - if (sbar_stats[STAT_ITEMS] & IT_SHELLS) - pic = sb_ammo[0]; - else if (sbar_stats[STAT_ITEMS] & IT_NAILS) - pic = sb_ammo[1]; - else if (sbar_stats[STAT_ITEMS] & IT_ROCKETS) - pic = sb_ammo[2]; - else if (sbar_stats[STAT_ITEMS] & IT_CELLS) - pic = sb_ammo[3]; + if (sb_game) { + if (sbar_stats[STAT_ITEMS] & RIT_SHELLS) + pic = sb_ammo[0]; + else if (sbar_stats[STAT_ITEMS] & RIT_NAILS) + pic = sb_ammo[1]; + else if (sbar_stats[STAT_ITEMS] & RIT_ROCKETS) + pic = sb_ammo[2]; + else if (sbar_stats[STAT_ITEMS] & RIT_CELLS) + pic = sb_ammo[3]; + else if (sbar_stats[STAT_ITEMS] & RIT_LAVA_NAILS) + pic = sb_ammo[4]; + else if (sbar_stats[STAT_ITEMS] & RIT_MULTI_ROCKETS) + pic = sb_ammo[5]; + else if (sbar_stats[STAT_ITEMS] & RIT_PLASMA_AMMO) + pic = sb_ammo[6]; + } else { + if (sbar_stats[STAT_ITEMS] & IT_SHELLS) + pic = sb_ammo[0]; + else if (sbar_stats[STAT_ITEMS] & IT_NAILS) + pic = sb_ammo[1]; + else if (sbar_stats[STAT_ITEMS] & IT_ROCKETS) + pic = sb_ammo[2]; + else if (sbar_stats[STAT_ITEMS] & IT_CELLS) + pic = sb_ammo[3]; + } view_t ammo = View_GetChild (view, 0); if (pic) { @@ -1024,39 +1041,6 @@ draw_status (view_t *view) } #endif -static void __attribute__((used)) -draw_rogue_ammo_hud (view_t *view) -{ -#if 0 - int i, count; - qpic_t *pic; - - if (sbar_stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) - pic = rsb_invbar[0]; - else - pic = rsb_invbar[1]; - - for (i = 0; i < 4; i++) { - count = sbar_stats[STAT_SHELLS + i]; - draw_subpic (view, 0, i * 11, pic, 3 + (i * 48), 0, 42, 11); - draw_smallnum (view, 7, i * 11, count, 0, 1); - } -#endif -} - -static void __attribute__((used)) -draw_rogue_inventory_sbar (view_t *view) -{ -#if 0 - if (sbar_stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) - draw_pic (view, 0, 0, rsb_invbar[0]); - else - draw_pic (view, 0, 0, rsb_invbar[1]); - - view_draw (view); -#endif -} - static void __attribute__((used)) draw_rogue_face (view_t *view) { @@ -1079,50 +1063,6 @@ draw_rogue_face (view_t *view) #endif } -static void __attribute__((used)) -draw_rogue_status (view_t *view) -{ -#if 0 - if (sbar_showscores || sbar_stats[STAT_HEALTH] <= 0) { - draw_solo (view); - return; - } - - draw_num (view, 24, 0, sbar_stats[STAT_ARMOR], 3, - sbar_stats[STAT_ARMOR] <= 25); - if (sbar_stats[STAT_ITEMS] & RIT_ARMOR3) - draw_pic (view, 0, 0, sb_armor[2]); - else if (sbar_stats[STAT_ITEMS] & RIT_ARMOR2) - draw_pic (view, 0, 0, sb_armor[1]); - else if (sbar_stats[STAT_ITEMS] & RIT_ARMOR1) - draw_pic (view, 0, 0, sb_armor[0]); - - // PGM 03/02/97 - fixed so color swatch appears in only CTF modes - if (sbar_maxplayers != 1 && teamplay > 3 && teamplay < 7) - draw_rogue_face (view); - else - draw_face (view); - - draw_health (view); - - if (sbar_stats[STAT_ITEMS] & RIT_SHELLS) - draw_pic (view, 224, 0, sb_ammo[0]); - else if (sbar_stats[STAT_ITEMS] & RIT_NAILS) - draw_pic (view, 224, 0, sb_ammo[1]); - else if (sbar_stats[STAT_ITEMS] & RIT_ROCKETS) - draw_pic (view, 224, 0, sb_ammo[2]); - else if (sbar_stats[STAT_ITEMS] & RIT_CELLS) - draw_pic (view, 224, 0, sb_ammo[3]); - else if (sbar_stats[STAT_ITEMS] & RIT_LAVA_NAILS) - draw_pic (view, 224, 0, rsb_ammo[0]); - else if (sbar_stats[STAT_ITEMS] & RIT_PLASMA_AMMO) - draw_pic (view, 224, 0, rsb_ammo[1]); - else if (sbar_stats[STAT_ITEMS] & RIT_MULTI_ROCKETS) - draw_pic (view, 224, 0, rsb_ammo[2]); - draw_num (view, 248, 0, sbar_stats[STAT_AMMO], 3, sbar_stats[STAT_AMMO] <= 10); -#endif -} - static void setup_frags (view_t frags, int player) { @@ -1880,6 +1820,19 @@ static void update_weapon (int stat) { set_update (sbar_weapons, draw_weapons); + sb_ibar_index = (sb_game + && sbar_stats[STAT_ACTIVEWEAPON] < RIT_LAVA_NAILGUN); + if (hud_sbar) { + // shouldn't need to sort the pics because the component is already + // on the entity, so the position in the pool won't be affected + sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar[sb_ibar_index]); + } else { + for (int i = 0; i < 4; i++) { + view_t v = View_GetChild (sbar_miniammo, i); + sb_miniammo[i].pic = sb_ibar[sb_ibar_index]; + sbar_setcomponent (v, hud_subpic, &sb_miniammo[i]); + } + } } static void @@ -2084,7 +2037,7 @@ set_hud_sbar (void) } } - sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar); + sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar[sb_ibar_index]); sbar_setcomponent (sbar_statusbar, hud_pic, &sb_sbar); sbar_setcomponent (sbar_tile[0], hud_tile, 0); sbar_setcomponent (sbar_tile[1], hud_tile, 0); @@ -2114,8 +2067,7 @@ set_hud_sbar (void) v = View_GetChild (sbar_miniammo, i); View_SetPos (v, 0, i * 11); View_SetLen (v, 42, 11); - hud_subpic_t subpic = { sb_ibar, 3 + (i * 48), 0, 42, 11 }; - sbar_setcomponent (v, hud_subpic, &subpic); + sbar_setcomponent (v, hud_subpic, &sb_miniammo[i]); } for (int i = 0; i < 7; i++) { for (int j = 0; j < sb_weapon_view_count; j++) { @@ -2266,108 +2218,6 @@ init_sbar_views (void) } } -#if 0 -static void -init_rogue_sbar_views (void) -{ - view_t *view; - - sbar_view = view_new (0, 0, 320, 48, grav_south); - - sbar_frags_view = view_new (0, 0, 130, 8, grav_northeast); - sbar_frags_view->draw = draw_frags; - - sbar_inventory_view = view_new (0, 0, 320, 24, grav_northwest); - sbar_inventory_view->draw = draw_rogue_inventory_sbar; - - view = view_new (0, 0, 224, 16, grav_southwest); - view->draw = draw_rogue_weapons_sbar; - view_add (sbar_inventory_view, view); - - view = view_new (0, 0, 32, 8, grav_northwest); - view->draw = draw_ammo_sbar; - view_add (sbar_inventory_view, view); - - view = view_new (0, 0, 128, 16, grav_southeast); - view->draw = draw_rogue_items; - view_add (sbar_inventory_view, view); - - if (sbar_frags_view) - view_add (sbar_inventory_view, sbar_frags_view); - - view_add (sbar_view, sbar_inventory_view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_status_bar; - view_add (sbar_view, view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_rogue_status; - view_add (sbar_view, view); - - if (cl_screen_view->xlen > 320) { - int l = (cl_screen_view->xlen - 320) / 2; - - view = view_new (-l, 0, l, 48, grav_southwest); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); - - view = view_new (-l, 0, l, 48, grav_southeast); - view->draw = draw_tile; - view->resize_y = 1; - view_add (sbar_view, view); - } -} -#endif - -#if 0 -static void -init_rogue_hud_views (void) -{ - view_t *view; - - hud_view = view_new (0, 0, 320, 48, grav_south); - hud_frags_view = view_new (0, 0, 130, 8, grav_northeast); - hud_frags_view->draw = draw_frags; - - hud_view->resize_y = 1; - - hud_armament_view = view_new (0, 48, 42, 156, grav_southeast); - - view = view_new (0, 0, 24, 112, grav_northeast); - view->draw = draw_rogue_weapons_hud; - view_add (hud_armament_view, view); - - view = view_new (0, 0, 42, 44, grav_southeast); - view->draw = draw_rogue_ammo_hud; - view_add (hud_armament_view, view); - - hud_inventory_view = view_new (0, 0, 320, 24, grav_northwest); - view_add (hud_view, hud_inventory_view); - - view = view_new (0, 0, 320, 24, grav_southwest); - view->draw = draw_rogue_status; - view_add (hud_view, view); - - view = view_new (0, 0, 128, 16, grav_southeast); - view->draw = draw_rogue_items; - view_add (hud_inventory_view, view); - - if (hud_frags_view) - view_add (hud_inventory_view, hud_frags_view); - - view = view_new (0, 0, cl_screen_view->xlen, 48, grav_south); - view->resize_x = 1; - view_add (view, hud_view); - hud_view = view; - - view_add (hud_view, hud_armament_view); - - view_insert (hud_main_view, hud_view, 0); -} -#endif - static void init_views (void) { @@ -2501,7 +2351,7 @@ load_pics (void) sb_face_quad = r_funcs->Draw_PicFromWad ("face_quad"); sb_sbar = r_funcs->Draw_PicFromWad ("sbar"); - sb_ibar = r_funcs->Draw_PicFromWad ("ibar"); + sb_ibar[0] = r_funcs->Draw_PicFromWad ("ibar"); sb_scorebar = r_funcs->Draw_PicFromWad ("scorebar"); sb_weapon_count = 7; sb_weapon_view_count = 7; @@ -2544,8 +2394,8 @@ load_pics (void) if (!strcmp (qfs_gamedir->hudtype, "rogue")) { sb_weapon_count = 12; sb_game = 1; - rsb_invbar[0] = r_funcs->Draw_PicFromWad ("r_invbar1"); - rsb_invbar[1] = r_funcs->Draw_PicFromWad ("r_invbar2"); + sb_ibar[0] = r_funcs->Draw_PicFromWad ("r_invbar1"); + sb_ibar[1] = r_funcs->Draw_PicFromWad ("r_invbar2"); sb_weapons[0][7].pic = r_funcs->Draw_PicFromWad ("r_lava"); sb_weapons[0][8].pic = r_funcs->Draw_PicFromWad ("r_superlava"); @@ -2567,9 +2417,10 @@ load_pics (void) rsb_teambord = r_funcs->Draw_PicFromWad ("r_teambord"); // PGM 01/19/97 - team color border - rsb_ammo[0] = r_funcs->Draw_PicFromWad ("r_ammolava"); - rsb_ammo[1] = r_funcs->Draw_PicFromWad ("r_ammomulti"); - rsb_ammo[2] = r_funcs->Draw_PicFromWad ("r_ammoplasma"); + // It seems the pics for plasma and multi-rockets are swapped + sb_ammo[4] = r_funcs->Draw_PicFromWad ("r_ammolava"); + sb_ammo[5] = r_funcs->Draw_PicFromWad ("r_ammoplasma"); + sb_ammo[6] = r_funcs->Draw_PicFromWad ("r_ammomulti"); } for (int i = 0; i < 7; i++) { @@ -2587,6 +2438,18 @@ load_pics (void) } } } + if (!sb_ibar[1]) { + sb_ibar[1] = sb_ibar[0]; + } + for (int i = 0; i < 4; i++) { + sb_miniammo[i] = (hud_subpic_t) { + .pic = sb_ibar[0], + .x = 3 + (i * 48), + .y = 0, + .w = 42, + .h = 11, + }; + } } static void From 5333c78f7a535754636f8ea5eb2d567dd502c62b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Nov 2022 19:33:40 +0900 Subject: [PATCH 3181/3664] [client] Implement rogue's team (ctf) face I don't like that teamplay is just a local cvar that doesn't get set by the server. --- libs/client/sbar.c | 60 ++++++++++++++++++++++++-------------------- nq/source/cl_parse.c | 2 +- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/libs/client/sbar.c b/libs/client/sbar.c index ae46540fb..ad3d84233 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -210,13 +210,16 @@ static view_def_t sbar_defs[] = { {&sbar_solo_name, { 0, 0, 0, 8}, grav_center, &sbar_solo_anchor}, {0, { 0, 0, 32, 8}, grav_northwest, &sbar_frags, 4, 32, 0, frags_defs}, {0, { 0, 0, 8, 16}, grav_northwest, &sbar_sigils, 4, 8, 0}, + // for rogue ctf "face" + {0, { 1, 3, 22, 9}, grav_northwest, &sbar_face, 2, 0, 9}, + {0, { 0, 3, 24, 8}, grav_northwest, &sbar_face, 1, 0, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_armor, 4, 24, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_ammo, 4, 24, 0}, // hipnotic and rogue have 8 item slots and no sigils, so the two extra // items overlap the sigils view {0, { 0, 0, 16, 16}, grav_northwest, &sbar_items, 8, 16, 0}, {0, { 0, 0, 24, 16}, grav_northwest, &sbar_weapons, 7, 24, 0}, - // hipnotic adds two extra weapons that overlapp the keys views (which + // hipnotic adds two extra weapons that overlap the keys views (which // get moved for hipnotic). {0, { 0, 0,176, 16}, grav_northwest, &sbar_weapons, 2, 24, 0}, {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 3, 24, 0}, @@ -931,6 +934,10 @@ draw_face (view_t view) { qpic_t *face; + if (sb_game && sbar_maxplayers > 1 + && sbar_teamplay > 3 && sbar_teamplay < 7) { + return; + } if (sbar_stats[STAT_HEALTH] <= 0) {//FIXME hide_Face or hide_sbar sbar_remcomponent (sbar_face, hud_pic); return; @@ -1041,26 +1048,17 @@ draw_status (view_t *view) } #endif -static void __attribute__((used)) -draw_rogue_face (view_t *view) +static void +draw_rogue_ctf_face (view_t view) { -#if 0 - int top, bottom; - player_info_t *s; - - // PGM 01/19/97 - team color drawing - - s = &sbar_players[sbar_viewplayer]; - - top = Sbar_ColorForMap (s->topcolor); - bottom = Sbar_ColorForMap (s->bottomcolor); - - draw_pic (view, 112, 0, rsb_teambord); - draw_fill (view, 113, 3, 22, 9, top); - draw_fill (view, 113, 12, 22, 9, bottom); - - draw_smallnum (view, 108, 3, s->frags, 1, top == 8); -#endif + __auto_type p = &sbar_players[sbar_viewplayer]; + byte top = Sbar_ColorForMap (p->topcolor); + byte bottom = Sbar_ColorForMap (p->bottomcolor); + sbar_setcomponent (View_GetChild (view, 0), hud_fill, &top); + sbar_setcomponent (View_GetChild (view, 1), hud_fill, &bottom); + sbar_setcomponent (View_GetChild (view, 2), hud_charbuff, + &sb_frags[sbar_viewplayer]); + sbar_setcomponent (view, hud_pic, &rsb_teambord); } static void @@ -1778,6 +1776,12 @@ Sbar_UpdateFrags (int playernum) write_charbuff (sb_frags[playernum], 0, 0, va (0, "%3d", p->frags)); } +static inline void +set_update (view_t view, hud_update_f func) +{ + sbar_setcomponent (view, hud_updateonce, &func); +} + void Sbar_UpdateInfo (int playernum) { @@ -1785,15 +1789,13 @@ Sbar_UpdateInfo (int playernum) //FIXME update top/bottom color write_charbuff (sb_uid[playernum], 0, 0, va (0, "%4d", p->userid)); write_charbuff_cl (sb_name[playernum], 0, 0, p->name->value); - if (sbar_teamplay) { + if (sbar_teamplay && p->team) { write_charbuff_cl (sb_team[playernum], 0, 0, p->team->value); } -} - -static inline void -set_update (view_t view, hud_update_f func) -{ - sbar_setcomponent (view, hud_updateonce, &func); + if (sb_game && sbar_maxplayers > 1 + && sbar_teamplay > 3 && sbar_teamplay < 7) { + set_update (sbar_face, draw_rogue_ctf_face); + } } static void @@ -1958,6 +1960,10 @@ void Sbar_SetTeamplay (int teamplay) { sbar_teamplay = teamplay; + if (sb_game && sbar_maxplayers > 1 + && sbar_teamplay > 3 && sbar_teamplay < 7) { + set_update (sbar_face, draw_rogue_ctf_face); + } } void diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 88545d559..8c398bd45 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -305,7 +305,7 @@ CL_ParseServerInfo (void) cl.players[i].bottomcolor = 0; } Sbar_SetPlayers (cl.players, cl.maxclients); - Sbar_SetTeamplay (0); + Sbar_SetTeamplay (teamplay);//FIXME updates? // parse gametype cl.gametype = MSG_ReadByte (net_message); From 749a110b7665e0ada7cbc100f7dc6bebb36d8a6b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 11 Nov 2022 22:04:02 +0900 Subject: [PATCH 3182/3664] [util] Check share path too when filling file lists This fixes maplist showing only those maps in the user directory. However, no checking is done for duplicate files due to earlier search paths overriding later paths. --- libs/util/quakefs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index cb4aa271d..333af44e7 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -1756,6 +1756,9 @@ QFS_FilelistFill (filelist_t *list, const char *path, const char *ext, for (search = vpath->user; search; search = search->next) { qfs_filelistfill_do (list, search, cp, ext, strip); } + for (search = vpath->share; search; search = search->next) { + qfs_filelistfill_do (list, search, cp, ext, strip); + } } free (cpath); } From 0d9b47575911eaf26f9b7b460dc03735a7dcf8e2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 01:47:17 +0900 Subject: [PATCH 3183/3664] [client] Implement finale overlay and death-solo Deathmatch overlay isn't working properly for end of level or death in qw. --- include/sbar.h | 22 +--- libs/client/cl_screen.c | 5 +- libs/client/sbar.c | 282 +++++++++++++++++++++------------------- nq/include/client.h | 1 - nq/source/cl_parse.c | 10 +- qw/source/cl_parse.c | 1 + 6 files changed, 158 insertions(+), 163 deletions(-) diff --git a/include/sbar.h b/include/sbar.h index 94c90e31a..a1733154f 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -31,23 +31,6 @@ #ifndef _SBAR_H #define _SBAR_H -#define SBAR_HEIGHT 24 - -//extern int sb_lines; // scan lines to draw - -typedef enum { - sbc_ammo, - sbc_armor, - sbc_frags, - sbc_health, - sbc_info, - sbc_items, - sbc_weapon, - sbc_server, - - sbc_num_changed -} sbar_changed; - extern qboolean sbar_showscores; struct player_info_s; @@ -57,6 +40,7 @@ void Sbar_SetLevelName (const char *levelname, const char *servername); void Sbar_SetPlayerNum (int playernum, int spectator); void Sbar_SetViewEntity (int viewentity); void Sbar_SetTeamplay (int teamplay); +void Sbar_SetGameType (int gametype); void Sbar_SetActive (int active); void Sbar_Update (double time); @@ -67,12 +51,8 @@ void Sbar_UpdateInfo (int playernum); void Sbar_UpdateStats (int stat); void Sbar_Damage (double time); -// call whenever any of the client stats represented on the sbar changes - void Sbar_Intermission (int mode, double completed_time); -// called each frame after the level has been completed -void Sbar_FinaleOverlay (void); void Sbar_DrawCenterPrint (void); void Sbar_CenterPrint (const char *str); diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index 84fdde018..3afec5d2f 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -154,8 +154,9 @@ static SCR_Func scr_funcs_normal[] = { static SCR_Func scr_funcs_intermission[] = { HUD_Draw_Views, - Con_DrawConsole, + Sbar_DrawCenterPrint, scr_draw_views, + Con_DrawConsole, 0 }; @@ -254,7 +255,7 @@ CL_Init_Screen (void) void CL_UpdateScreen (viewstate_t *vs) { - unsigned index = vs->intermission; + unsigned index = !!vs->intermission; _vs = vs; if (index >= sizeof (scr_funcs) / sizeof (scr_funcs[0])) diff --git a/libs/client/sbar.c b/libs/client/sbar.c index ad3d84233..a17f7b359 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -84,6 +84,7 @@ static int sbar_playernum; static int sbar_viewplayer; static int sbar_spectator; static int sbar_teamplay; +static int sbar_gametype; static int sbar_active; static int sbar_intermission; @@ -164,8 +165,9 @@ static view_def_t miniteam_defs[] = { static view_def_t sbar_defs[] = { {&hud_overlay_view, { 0, 0,320,200}, grav_center, &cl_screen_view}, {&intermission_view, { 0, 0,320,200}, grav_northwest, &hud_overlay_view}, - {0, {64, 24, 24, 24}, grav_northwest, &intermission_view, 1, 0, 0}, - {0, {0, 56, 24, 24}, grav_northwest, &intermission_view, 1, 0, 0}, + {0, {0, 24, 192, 24}, grav_north, &intermission_view, 1, 0, 0}, + {0, {0, 56, 160, 144}, grav_northwest, &intermission_view, 1, 0, 0}, + {0, {0, 16, 288, 24}, grav_north, &intermission_view, 1, 0, 0}, {&intermission_time, {160,64,134,24}, grav_northwest, &intermission_view}, {0, {0, 0, 24, 24}, grav_northwest, &intermission_time, 3, 24, 0}, {0, {74, 0, 16, 24}, grav_northwest, &intermission_time, 1, 0, 0}, @@ -745,6 +747,7 @@ draw_solo (void) view_pos_t len = View_GetLen (sbar_solo_name); len.x = 8 * solo_name->cursx; View_SetLen (sbar_solo_name, len.x, len.y); + View_UpdateHierarchy (sbar_solo); } static void @@ -1027,26 +1030,39 @@ draw_health (view_t view) }; draw_num (num, sbar_stats[STAT_HEALTH], 3, sbar_stats[STAT_HEALTH] <= 25); } -#if 0 + static void -draw_status (view_t *view) +draw_status (void ) { + sb_updates = 0; + + sbar_setcomponent (sbar_solo, hud_pic, &sb_scorebar); + sbar_setcomponent (sbar_solo_monsters, hud_charbuff, &solo_monsters); + sbar_setcomponent (sbar_solo_secrets, hud_charbuff, &solo_secrets); + sbar_setcomponent (sbar_solo_time, hud_charbuff, &solo_time); + sbar_setcomponent (sbar_solo_name, hud_charbuff, &solo_name); + + draw_solo (); +#if 0 if (sbar_spectator) { draw_spectator (view); if (autocam != CAM_TRACK) return; } - if (sbar_showscores || sbar_stats[STAT_HEALTH] <= 0) { - draw_solo (view); - return; - } - - draw_armor (sbar_status_armor); - draw_face (sbar_status_face); - draw_health (sbar_status_health); - draw_ammo (sbar_status_ammo); -} #endif +} + +static void +hide_status (void) +{ + sb_updates = 0; + + sbar_remcomponent (sbar_solo, hud_pic); + sbar_remcomponent (sbar_solo_monsters, hud_charbuff); + sbar_remcomponent (sbar_solo_secrets, hud_charbuff); + sbar_remcomponent (sbar_solo_time, hud_charbuff); + sbar_remcomponent (sbar_solo_name, hud_charbuff); +} static void draw_rogue_ctf_face (view_t view) @@ -1553,93 +1569,6 @@ draw_fps (view_t view) write_charbuff (fps_buff, 0, 0, st); } -static void -draw_intermission (view_t view) -{ - const char *n; - - n = "gfx/complete.lmp"; - sbar_setcomponent (View_GetChild (view, 0), hud_cachepic, &n); - n = "gfx/inter.lmp"; - sbar_setcomponent (View_GetChild (view, 1), hud_cachepic, &n); - - view_t time_views[] = { - View_GetChild (intermission_time, 0), - View_GetChild (intermission_time, 1), - View_GetChild (intermission_time, 2), - View_GetChild (intermission_time, 3), - View_GetChild (intermission_time, 4), - View_GetChild (intermission_time, 5), - }; - int dig = sbar_completed_time / 60; - int num = sbar_completed_time - dig * 60; - draw_num (time_views + 0, dig, 3, 0); - sbar_setcomponent (time_views[3], hud_pic, &sb_colon); - draw_num (time_views + 4, num, 2, 0); - - view_t secr_views[] = { - View_GetChild (intermission_secr, 0), - View_GetChild (intermission_secr, 1), - View_GetChild (intermission_secr, 2), - View_GetChild (intermission_secr, 3), - View_GetChild (intermission_secr, 4), - View_GetChild (intermission_secr, 5), - View_GetChild (intermission_secr, 6), - }; - draw_num (secr_views + 0, sbar_stats[STAT_SECRETS], 3, 0); - sbar_setcomponent (secr_views[3], hud_pic, &sb_slash); - draw_num (secr_views + 4, sbar_stats[STAT_TOTALSECRETS], 3, 0); - - view_t kill_views[] = { - View_GetChild (intermission_kill, 0), - View_GetChild (intermission_kill, 1), - View_GetChild (intermission_kill, 2), - View_GetChild (intermission_kill, 3), - View_GetChild (intermission_kill, 4), - View_GetChild (intermission_kill, 5), - View_GetChild (intermission_kill, 6), - }; - draw_num (kill_views + 0, sbar_stats[STAT_MONSTERS], 3, 0); - sbar_setcomponent (kill_views[3], hud_pic, &sb_slash); - draw_num (kill_views + 4, sbar_stats[STAT_TOTALMONSTERS], 3, 0); -} - -static void -clear_views (view_t view) -{ - sbar_remcomponent (view, hud_cachepic); - sbar_remcomponent (view, hud_pic); - - for (uint32_t i = 0; i < View_ChildCount (view); i++) { - clear_views (View_GetChild (view, i)); - } -} - -#if 0 -void -Sbar_IntermissionOverlay (void) -{ - r_data->scr_copyeverything = 1; - r_data->scr_fullupdate = 0; - if (cl.gametype == GAME_DEATHMATCH) { - Sbar_DeathmatchOverlay (hud_overlay_view); - return; - } - draw_intermission (intermission_view); -} -#endif - -void -Sbar_Intermission (int mode, double completed_time) -{ - sbar_completed_time = completed_time; - void *f = clear_views; - if (mode == 1) { - f = draw_intermission; - } - sbar_setcomponent (intermission_view, hud_updateonce, &f); -} - /* CENTER PRINTING */ static dstring_t center_string = {&dstring_default_mem}; static passage_t center_passage; @@ -1702,19 +1631,104 @@ Sbar_DrawCenterString (view_t view, unsigned remaining) } } -void -Sbar_FinaleOverlay (void) +static void +clear_views (view_t view) { - int remaining; + sbar_remcomponent (view, hud_cachepic); + sbar_remcomponent (view, hud_pic); + + for (uint32_t i = 0; i < View_ChildCount (view); i++) { + clear_views (View_GetChild (view, i)); + } +} + +static void +draw_intermission (view_t view) +{ + clear_views (view); + const char *n; + n = "gfx/complete.lmp"; + sbar_setcomponent (View_GetChild (view, 0), hud_cachepic, &n); + n = "gfx/inter.lmp"; + sbar_setcomponent (View_GetChild (view, 1), hud_cachepic, &n); + + view_t time_views[] = { + View_GetChild (intermission_time, 0), + View_GetChild (intermission_time, 1), + View_GetChild (intermission_time, 2), + View_GetChild (intermission_time, 3), + View_GetChild (intermission_time, 4), + View_GetChild (intermission_time, 5), + }; + int dig = sbar_completed_time / 60; + int num = sbar_completed_time - dig * 60; + draw_num (time_views + 0, dig, 3, 0); + sbar_setcomponent (time_views[3], hud_pic, &sb_colon); + draw_num (time_views + 4, num, 2, 0); + + view_t secr_views[] = { + View_GetChild (intermission_secr, 0), + View_GetChild (intermission_secr, 1), + View_GetChild (intermission_secr, 2), + View_GetChild (intermission_secr, 3), + View_GetChild (intermission_secr, 4), + View_GetChild (intermission_secr, 5), + View_GetChild (intermission_secr, 6), + }; + draw_num (secr_views + 0, sbar_stats[STAT_SECRETS], 3, 0); + sbar_setcomponent (secr_views[3], hud_pic, &sb_slash); + draw_num (secr_views + 4, sbar_stats[STAT_TOTALSECRETS], 3, 0); + + view_t kill_views[] = { + View_GetChild (intermission_kill, 0), + View_GetChild (intermission_kill, 1), + View_GetChild (intermission_kill, 2), + View_GetChild (intermission_kill, 3), + View_GetChild (intermission_kill, 4), + View_GetChild (intermission_kill, 5), + View_GetChild (intermission_kill, 6), + }; + draw_num (kill_views + 0, sbar_stats[STAT_MONSTERS], 3, 0); + sbar_setcomponent (kill_views[3], hud_pic, &sb_slash); + draw_num (kill_views + 4, sbar_stats[STAT_TOTALMONSTERS], 3, 0); +} + +static void +draw_finale (view_t view) +{ + clear_views (view); r_data->scr_copyeverything = 1; -#if 0 - draw_cachepic (hud_overlay_view, 0, 16, "gfx/finale.lmp", 1); -#endif - // the finale prints the characters one at a time - remaining = scr_printspeed * (sbar_time - centertime_start); - Sbar_DrawCenterString (hud_overlay_view, remaining); + const char *n = "gfx/finale.lmp"; + sbar_setcomponent (View_GetChild (view, 2), hud_cachepic, &n); +} + +static void +draw_cutscene (view_t view) +{ + clear_views (view); +} + +static inline void +set_update (view_t view, hud_update_f func) +{ + sbar_setcomponent (view, hud_updateonce, &func); +} + +void +Sbar_Intermission (int mode, double completed_time) +{ + static hud_update_f intermission_funcs[2][4] = { + { clear_views, draw_intermission, draw_finale, draw_cutscene, }, + { clear_views, Sbar_DeathmatchOverlay, draw_finale, draw_cutscene, }, + }; + sbar_completed_time = completed_time; + if ((unsigned) mode > 3) { + mode = 0; + } + sbar_intermission = mode; + set_update (intermission_view, intermission_funcs[sbar_gametype][mode]); } void @@ -1723,10 +1737,17 @@ Sbar_DrawCenterPrint (void) r_data->scr_copytop = 1; centertime_off -= r_data->frametime; - if (centertime_off <= 0) + if (!center_passage.hierarchy + || (centertime_off <= 0 && !sbar_intermission)) return; - Sbar_DrawCenterString (hud_overlay_view, -1); + + int remaining = -1; + if (sbar_intermission) { + // the finale prints the characters one at a time + remaining = scr_printspeed * (sbar_time - centertime_start); + } + Sbar_DrawCenterString (hud_overlay_view, remaining); } void @@ -1776,12 +1797,6 @@ Sbar_UpdateFrags (int playernum) write_charbuff (sb_frags[playernum], 0, 0, va (0, "%3d", p->frags)); } -static inline void -set_update (view_t view, hud_update_f func) -{ - sbar_setcomponent (view, hud_updateonce, &func); -} - void Sbar_UpdateInfo (int playernum) { @@ -1803,6 +1818,11 @@ update_health (int stat) { set_update (sbar_health, draw_health); set_update (sbar_face, draw_face); + if (sbar_stats[STAT_HEALTH] <= 0) { + draw_status (); + } else if (!sbar_showscores) { + hide_status (); + } } static void @@ -1966,6 +1986,12 @@ Sbar_SetTeamplay (int teamplay) } } +void +Sbar_SetGameType (int gametype) +{ + sbar_gametype = gametype; +} + void Sbar_SetActive (int active) { @@ -2465,32 +2491,20 @@ Sbar_ShowScores (void) return; sbar_showscores = true; - sb_updates = 0; - sbar_setcomponent (sbar_solo, hud_pic, &sb_scorebar); - sbar_setcomponent (sbar_solo_monsters, hud_charbuff, &solo_monsters); - sbar_setcomponent (sbar_solo_secrets, hud_charbuff, &solo_secrets); - sbar_setcomponent (sbar_solo_time, hud_charbuff, &solo_time); - sbar_setcomponent (sbar_solo_name, hud_charbuff, &solo_name); - - draw_solo (); - View_UpdateHierarchy (sbar_solo); + draw_status (); } static void Sbar_DontShowScores (void) { - if (!sbar_showscores) + if (!sbar_showscores || sbar_stats[STAT_HEALTH] <= 0) { return; + } sbar_showscores = false; - sb_updates = 0; - sbar_remcomponent (sbar_solo, hud_pic); - sbar_remcomponent (sbar_solo_monsters, hud_charbuff); - sbar_remcomponent (sbar_solo_secrets, hud_charbuff); - sbar_remcomponent (sbar_solo_time, hud_charbuff); - sbar_remcomponent (sbar_solo_name, hud_charbuff); + hide_status (); } static void diff --git a/nq/include/client.h b/nq/include/client.h index e0897e2dc..59deeb9f5 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -177,7 +177,6 @@ typedef struct client_state_s { int viewentity; // cl_entitites[cl.viewentity] = player unsigned protocol; float stdver; - int gametype; int maxclients; // serverinfo mirrors int sv_cshifts; diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 8c398bd45..3c324ece4 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -308,7 +308,7 @@ CL_ParseServerInfo (void) Sbar_SetTeamplay (teamplay);//FIXME updates? // parse gametype - cl.gametype = MSG_ReadByte (net_message); + Sbar_SetGameType (MSG_ReadByte (net_message)); // parse signon message str = MSG_ReadString (net_message); @@ -988,10 +988,10 @@ CL_ParseServerMessage (void) break; case svc_finale: - Sbar_Intermission (cl.intermission = 2, cl.time); - SCR_SetFullscreen (1); str = MSG_ReadString (net_message); Sbar_CenterPrint (str); + Sbar_Intermission (cl.intermission = 2, cl.time); + SCR_SetFullscreen (1); break; case svc_cdtrack: @@ -1009,10 +1009,10 @@ CL_ParseServerMessage (void) break; case svc_cutscene: - Sbar_Intermission (cl.intermission = 3, cl.time); - SCR_SetFullscreen (1); str = MSG_ReadString (net_message); Sbar_CenterPrint (str); + Sbar_Intermission (cl.intermission = 3, cl.time); + SCR_SetFullscreen (1); break; // svc_smallkick (same value as svc_cutscene) diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index cb2ef4667..686e52d0c 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -1139,6 +1139,7 @@ CL_ServerInfo (void) // movevars.ktjump = atof (value); // FIXME: need to set to 0.5 otherwise, outside of else structure } + Sbar_SetGameType (0); } static void From 1a9ec15a41458aefe8fb8053832f26549b787efc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 01:50:31 +0900 Subject: [PATCH 3184/3664] [client] Include hud overlay in hud_debug --- libs/client/hud.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/client/hud.c b/libs/client/hud.c index 20402f16f..a08bc3040 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -207,8 +207,10 @@ hud_debug_f (void *data, const cvar_t *cvar) } if (hud_debug) { hud_add_outlines (hud_view); + hud_add_outlines (hud_overlay_view); } else { hud_remove_outlines (hud_view); + hud_remove_outlines (hud_overlay_view); } } From 0ea5c1fa14d1861803a52e36126feeddabcdef5a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 11:41:09 +0900 Subject: [PATCH 3185/3664] [qw] Call CL_NetUpdate only when active Calling CL_NetUpdate while not active (or more importantly, while not connected) results in a buffer write error (Sys_Error). Active was chosen because that's how the old sbar code worked, and it seems reasonable to stick with it rather than requesting pings etc during the connect process. --- qw/source/cl_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 6b49cc528..2e86d56db 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1944,7 +1944,7 @@ Host_Frame (float time) r_data->frametime = host_frametime; cl.viewstate.time = realtime; - if (!cls.demoplayback) { + if (!cls.demoplayback && cls.state == ca_active) { CL_NetUpdate (); } Sbar_Update (cl.time); From bbd2cdb8c8694b81974f56bc1ddbd6fe3fe9cb15 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 14:37:42 +0900 Subject: [PATCH 3186/3664] [console] Check for curses before calling updaters If curses isn't being used, then there are no entities and thus no components to run. Fixes a segfault when running a server without curses enabled. --- libs/console/server.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libs/console/server.c b/libs/console/server.c index 3e5771404..523effdf4 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -146,7 +146,11 @@ enum { sv_cursor = 8, }; +#ifdef HAVE_NCURSES static int use_curses = 1; +#else +static int use_curses = 0; +#endif static view_t sv_view; static view_t output; @@ -840,8 +844,10 @@ C_DrawConsole (void) { // only the status bar is drawn because the inputline and output views // take care of themselves - draw_status (status); - sv_refresh_windows (); + if (use_curses) { + draw_status (status); + sv_refresh_windows (); + } } static void From 07f897122f3f932a1677af473a3fe6210849d0ea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 14:39:18 +0900 Subject: [PATCH 3187/3664] [ruamoko] Fix several builtin declarations Trying to build and run frikbot with ruamoko progs found a pile off issues. --- ruamoko/include/debug.h | 2 +- ruamoko/include/entities.h | 2 +- ruamoko/include/message.h | 6 +++--- ruamoko/include/server.h | 4 ++-- ruamoko/include/system.h | 4 ++-- ruamoko/lib/debug.r | 2 +- ruamoko/lib/entities.r | 2 +- ruamoko/lib/message.r | 6 +++--- ruamoko/lib/server.r | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ruamoko/include/debug.h b/ruamoko/include/debug.h index 9ea089de0..64e06eb5d 100644 --- a/ruamoko/include/debug.h +++ b/ruamoko/include/debug.h @@ -62,7 +62,7 @@ /** Print a string to the console if the "developer" Cvar is nonzero. */ -@extern void dprint (.../*string str*/); +@extern void dprint (string str); /** Abort (crash) the server. "str" is the message the server crashes with. diff --git a/ruamoko/include/entities.h b/ruamoko/include/entities.h index 117f7d309..2bff9d984 100644 --- a/ruamoko/include/entities.h +++ b/ruamoko/include/entities.h @@ -101,7 +101,7 @@ This function must be called multiple times to get multiple results. Stupid, but functional. */ -@extern entity find (entity start, ...); +@extern @attribute(no_va_list) entity find (entity start, ...); #endif /** diff --git a/ruamoko/include/message.h b/ruamoko/include/message.h index f0cf5c140..15354838f 100644 --- a/ruamoko/include/message.h +++ b/ruamoko/include/message.h @@ -34,8 +34,8 @@ #define MULTICAST_PHS_R 4 #define MULTICAST_PVS_R 5 -@extern void bprint (...); -@extern void sprint (.../*entity client, string s*/); +@extern void bprint (float level, string s); +@extern void sprint (entity client, float level, string s); @extern void WriteBytes (float to, ...); @extern void WriteByte (float to, float f); @extern void WriteChar (float to, float f); @@ -47,6 +47,6 @@ @extern void WriteAngleV (float to, vector v); @extern void WriteString (float to, string s); @extern void WriteEntity (float to, entity s); -@extern void centerprint (...); +@extern void centerprint (entity client, string s); #endif//__ruamoko_message_h diff --git a/ruamoko/include/server.h b/ruamoko/include/server.h index f2e8c2469..2053ca4d2 100644 --- a/ruamoko/include/server.h +++ b/ruamoko/include/server.h @@ -1,8 +1,8 @@ #ifndef __ruamoko_server_h #define __ruamoko_server_h -@extern void precache_sound (string s); -@extern void precache_model (string s); +@extern string precache_sound (string s); +@extern string precache_model (string s); @extern void stuffcmd (entity client, string s); @extern void localcmd (string s); @extern void changelevel (string s); diff --git a/ruamoko/include/system.h b/ruamoko/include/system.h index 64056c8d9..1c99f0035 100644 --- a/ruamoko/include/system.h +++ b/ruamoko/include/system.h @@ -3,8 +3,8 @@ @extern float time; -@extern void precache_sound (string s); -@extern void precache_model (string s); +@extern string precache_sound (string s); +@extern string precache_model (string s); @extern void stuffcmd (entity client, string s); @extern void localcmd (string s); @extern void changelevel (string s); diff --git a/ruamoko/lib/debug.r b/ruamoko/lib/debug.r index 0f2f09375..36dcf43d2 100644 --- a/ruamoko/lib/debug.r +++ b/ruamoko/lib/debug.r @@ -5,6 +5,6 @@ void coredump (void) = #28; void traceon (void) = #29; void traceoff (void) = #30; void eprint (entity e) = #31; -void dprint (.../*string str*/) = #25; +void dprint (string s) = #25; void error (.../*string str*/) = #10; void objerror (.../*string e*/) = #11; diff --git a/ruamoko/lib/entities.r b/ruamoko/lib/entities.r index f49cc9a53..0af69f189 100644 --- a/ruamoko/lib/entities.r +++ b/ruamoko/lib/entities.r @@ -8,7 +8,7 @@ void remove (entity e) = #15; #ifdef __VERSION6__ entity find (entity start, .string field, string match) = #18; #else -entity find (entity start, ...) = #18; +entity @attribute(no_va_list) find (entity start, ...) = #18; #endif entity findradius (vector origin, float radius) = #22; entity nextent (entity e) = #47; diff --git a/ruamoko/lib/message.r b/ruamoko/lib/message.r index d01c641e5..d592335c1 100644 --- a/ruamoko/lib/message.r +++ b/ruamoko/lib/message.r @@ -1,7 +1,7 @@ #include -void (...) bprint = #23; -void (.../*entity client, string s*/) sprint = #24; +void (float level, string s) bprint = #23; +void (entity client, float level, string s) sprint = #24; void (float to, float f) WriteByte = #52; void (float to, float f) WriteChar = #53; void (float to, float f) WriteShort = #54; @@ -13,4 +13,4 @@ void (float to, entity s) WriteEntity = #59; void (float to, ...) WriteBytes = #0; void (float to, vector v) WriteCoordV = #0; void (float to, vector v) WriteAngleV = #0; -void (...) centerprint = #73; +void (entity client, string s) centerprint = #73; diff --git a/ruamoko/lib/server.r b/ruamoko/lib/server.r index b65c3ac7d..ab9ef0e6e 100644 --- a/ruamoko/lib/server.r +++ b/ruamoko/lib/server.r @@ -1,7 +1,7 @@ #include -void (string s) precache_sound = #19; -void (string s) precache_model = #20; +string (string s) precache_sound = #19; +string (string s) precache_model = #20; void (entity client, string s) stuffcmd = #21; void (string s) localcmd = #46; void (string s) changelevel = #70; From 72e57367bf27aca8a5a917d68647161d8317b496 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 14:40:18 +0900 Subject: [PATCH 3188/3664] [qw] Check player name exists in spectator tracking Fixes a segfault when the tracked player disconnects. --- qw/source/cl_cam.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index a784a9cf1..6cfc92d97 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -425,7 +425,8 @@ Cam_Track (usercmd_t *cmd) return; if (locked - && (!cl.players[spec_track].name->value[0] + && (!cl.players[spec_track].name + || !cl.players[spec_track].name->value[0] || cl.players[spec_track].spectator)) { locked = false; if (cl_hightrack) From 71af297a52bbf451ca3fdbd41379c40d3d695921 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 18:51:08 +0900 Subject: [PATCH 3189/3664] [qfcc] Support extend expressions in dot_expr --- tools/qfcc/source/dot_expr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 664796915..a981c7bc0 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -590,6 +590,18 @@ print_swizzle (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) swizzle, e->line); } +static void +print_extend (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) +{ + int indent = level * 2 + 2; + ex_extend_t extend = e->e.extend; + + _print_expr (dstr, extend.src, level, id, next); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, extend.src); + dasprintf (dstr, "%*se_%p [label=\"extend %d\\n%d\"];\n", indent, "", e, + extend.extend, e->line); +} + static void _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) { @@ -621,6 +633,7 @@ _print_expr (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) [ex_args] = print_args, [ex_horizontal] = print_horizontal, [ex_swizzle] = print_swizzle, + [ex_extend] = print_extend, }; int indent = level * 2 + 2; From 2d3c2da64d2b7f472b8199ec342d4dabd96c31b3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 20:04:19 +0900 Subject: [PATCH 3190/3664] [qfcc] Support advanced progs again The support for the new vector types broke compiling code using --advanced. Thus it's necessary to ensure vector constants are float-type and vec3 and vec4 are treated as vector and quaternion, which meant resurrecting the old vector expression code for v6p progs. --- libs/gamecode/pr_v6p_opcode.c | 2 +- tools/qfcc/source/expr_assign.c | 55 ++++++++++++++++++++++++++++++++- tools/qfcc/source/qc-lex.l | 10 ++++++ tools/qfcc/source/type.c | 8 +++++ 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/libs/gamecode/pr_v6p_opcode.c b/libs/gamecode/pr_v6p_opcode.c index 2f57d1ad4..392e5f14b 100644 --- a/libs/gamecode/pr_v6p_opcode.c +++ b/libs/gamecode/pr_v6p_opcode.c @@ -85,7 +85,7 @@ VISIBLE const v6p_opcode_t pr_v6p_opcodes[] = { ev_float, ev_float, ev_float, PROG_ID_VERSION, }, - [OP_MUL_V_v6p] = {"mul", "mul.v", + [OP_MUL_V_v6p] = {"vdot", "mul.v", ev_vector, ev_vector, ev_float, PROG_ID_VERSION, }, diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index b1a8c3e5a..ad9fa86e5 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -212,6 +212,55 @@ check_types_compatible (expr_t *dst, expr_t *src) return type_mismatch (dst, src, '='); } +static void +copy_qv_elements (expr_t *block, expr_t *dst, expr_t *src) +{ + expr_t *dx, *sx; + expr_t *dy, *sy; + expr_t *dz, *sz; + expr_t *dw, *sw; + expr_t *ds, *ss; + expr_t *dv, *sv; + + if (is_vector (src->e.vector.type)) { + // guaranteed to have three elements + sx = src->e.vector.list; + sy = sx->next; + sz = sy->next; + dx = field_expr (dst, new_name_expr ("x")); + dy = field_expr (dst, new_name_expr ("y")); + dz = field_expr (dst, new_name_expr ("z")); + append_expr (block, assign_expr (dx, sx)); + append_expr (block, assign_expr (dy, sy)); + append_expr (block, assign_expr (dz, sz)); + } else { + // guaranteed to have two or four elements + if (src->e.vector.list->next->next) { + // four vals: x, y, z, w + sx = src->e.vector.list; + sy = sx->next; + sz = sy->next; + sw = sz->next; + dx = field_expr (dst, new_name_expr ("x")); + dy = field_expr (dst, new_name_expr ("y")); + dz = field_expr (dst, new_name_expr ("z")); + dw = field_expr (dst, new_name_expr ("w")); + append_expr (block, assign_expr (dx, sx)); + append_expr (block, assign_expr (dy, sy)); + append_expr (block, assign_expr (dz, sz)); + append_expr (block, assign_expr (dw, sw)); + } else { + // v, s + sv = src->e.vector.list; + ss = sv->next; + dv = field_expr (dst, new_name_expr ("v")); + ds = field_expr (dst, new_name_expr ("s")); + append_expr (block, assign_expr (dv, sv)); + append_expr (block, assign_expr (ds, ss)); + } + } +} + static int copy_elements (expr_t *block, expr_t *dst, expr_t *src, int base) { @@ -234,7 +283,11 @@ assign_vector_expr (expr_t *dst, expr_t *src) if (src->type == ex_vector && dst->type != ex_vector) { expr_t *block = new_block_expr (); - copy_elements (block, dst, src, 0); + if (options.code.progsversion <= PROG_VERSION) { + copy_qv_elements (block, dst, src); + } else { + copy_elements (block, dst, src, 0); + } block->e.block.result = dst; return block; } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 9f0a9fee6..dd8c9ff84 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -587,6 +587,11 @@ parse_int_vector (const char *token, int width) } t1 = tolower (t1); t2 = tolower (t2); + if (options.code.progsversion < PROG_VERSION) { + if (!t1) { + t1 = 'f'; + } + } expr_t *expr = 0; switch (t1) { case 'u': @@ -704,6 +709,11 @@ parse_float_vector (const char *token, int width) type = (t == 'f' || t == 'F') ? &type_vec2 : &type_dvec2; break; } + if (options.code.progsversion < PROG_VERSION) { + if (!t) { + t = 'f'; + } + } if (t == 'f' || t == 'F') { volatile union { pr_float_t f[4]; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 8b0901339..61918d220 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -567,6 +567,14 @@ vector_type (const type_t *ele_type, int width) for (type_t **vtype = vec_types; *vtype; vtype++) { if ((*vtype)->type == ele_type->type && (*vtype)->width == width) { + if (options.code.progsversion <= PROG_VERSION) { + if (*vtype == &type_vec3) { + return &type_vector; + } + if (*vtype == &type_vec4) { + return &type_quaternion; + } + } return *vtype; } } From bfda4e776f8114931af1c1e4201c4df4aebf9070 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 20:07:30 +0900 Subject: [PATCH 3191/3664] [qfcc] Add a failing test case for if-super calls The common idiom for self init (below) causes a double-call when compiling with --advanced, resulting in an incorrect retain count. if (!(self = [super init])) { return nil; } --- tools/qfcc/test/Makemodule.am | 11 +++++++ tools/qfcc/test/ifsuper.r | 56 ++++++++++++++++++++++++++++++++++ tools/qfcc/test/test-harness.h | 2 ++ 3 files changed, 69 insertions(+) create mode 100644 tools/qfcc/test/ifsuper.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index f5111177e..e6ada0a81 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -29,6 +29,7 @@ test_progs_dat=\ tools/qfcc/test/func-expr2.dat \ tools/qfcc/test/func-static.dat \ tools/qfcc/test/gcd.dat \ + tools/qfcc/test/ifsuper.dat \ tools/qfcc/test/infloop.dat \ tools/qfcc/test/iterfunc.dat \ tools/qfcc/test/ivar-struct-return.dat \ @@ -369,6 +370,16 @@ tools/qfcc/test/gcd.run: $(qfcc_test_run_deps) include $(gcd_dep) # am--include-marker pas_depfiles_remade += $(gcd_dep) +tools_qfcc_test_ifsuper_dat_SOURCES=tools/qfcc/test/ifsuper.r +ifsuper_obj=$(tools_qfcc_test_ifsuper_dat_SOURCES:.r=.o) +ifsuper_dep=$(call qcautodep,$(tools_qfcc_test_ifsuper_dat_SOURCES)) +tools/qfcc/test/ifsuper.dat$(EXEEXT): $(ifsuper_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) --advanced -o $@ $(ifsuper_obj) +tools/qfcc/test/ifsuper.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(ifsuper_dep) # am--include-marker +r_depfiles_remade += $(ifsuper_dep) + tools_qfcc_test_infloop_dat_SOURCES=tools/qfcc/test/infloop.r infloop_obj=$(tools_qfcc_test_infloop_dat_SOURCES:.r=.o) infloop_dep=$(call qcautodep,$(tools_qfcc_test_infloop_dat_SOURCES)) diff --git a/tools/qfcc/test/ifsuper.r b/tools/qfcc/test/ifsuper.r new file mode 100644 index 000000000..58e916102 --- /dev/null +++ b/tools/qfcc/test/ifsuper.r @@ -0,0 +1,56 @@ +#pragma advanced +#include "test-harness.h" + +int obj_increment_retaincount (id object) = #0; +int obj_get_retaincount (id object) = #0; +id (Class class) class_create_instance = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; + +@interface Object +{ + Class isa; +} ++(id) alloc; +-(id) init; +@end + +@interface Foo : Object +-(id) init; +@end + +@implementation Object ++(id) alloc +{ + return class_create_instance (self); +} +-(id) init +{ + obj_increment_retaincount (self); + return self; +} +@end + +@implementation Foo +-(id) init +{ + if (!(self = [super init])) { + return nil; + } + return self; +} +@end + +int main () +{ + Foo *foo = [[Foo alloc] init]; + if (!foo) { + printf ("foo is nil\n"); + return 1; + } + int retain = obj_get_retaincount (foo); + if (retain != 1) { + printf ("retain count != 1: %d\n", retain); + return 1; + } + return 0; +} diff --git a/tools/qfcc/test/test-harness.h b/tools/qfcc/test/test-harness.h index 63f368416..51c5bde12 100644 --- a/tools/qfcc/test/test-harness.h +++ b/tools/qfcc/test/test-harness.h @@ -3,6 +3,8 @@ void printf (string fmt, ...) = #0; int errno (void) = #0; string strerror (int err) = #0; void exit (int code) = #0; +void traceon (void) = #0; +void traceoff (void) = #0; entity spawn (void) = #0; void remove (entity e) = #0; id obj_msgSend (id receiver, SEL op, ...) = #0; From 76740d213ea6f9c671f8790d032c97dded25c913 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 22:16:57 +0900 Subject: [PATCH 3192/3664] [qfcc] Add link from jump expression to destination Having a dangling jump with no destination in my dot output wasn't very informative. --- tools/qfcc/source/dot_expr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index a981c7bc0..a3a825eb3 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -354,6 +354,8 @@ print_jump (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) _print_expr (dstr, e->e.branch.target, level, id, next); dasprintf (dstr, "%*se_%p [label=\"%s\\n%d\"];\n", indent, "", e, "jump", e->line); + dasprintf (dstr, "%*se_%p -> \"e_%p\";\n", indent, "", e, + e->e.branch.target); } static void From 5b202a17331e6b112e629be3f2bf0713f1bdee94 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 12 Nov 2022 22:18:36 +0900 Subject: [PATCH 3193/3664] [qfcc] Skip over aliases when checking for blocks This fixes the double call to [super init] as tested by ifsuper.r. --- tools/qfcc/source/expr_bool.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 4d3431769..9fd817dc2 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -243,23 +243,34 @@ bool_expr (int op, expr_t *label, expr_t *e1, expr_t *e2) internal_error (e1, 0); } +static int __attribute__((pure)) +has_block_expr (expr_t *e) +{ + while (e->type == ex_alias) { + e = e->e.alias.expr; + } + return e->type == ex_block; +} + expr_t * convert_bool (expr_t *e, int block) { expr_t *b; if (e->type == ex_assign) { - expr_t *src; + expr_t *tst; if (!e->paren && options.warnings.precedence) warning (e, "suggest parentheses around assignment " "used as truth value"); - src = e->e.assign.src; - if (src->type == ex_block) { - src = new_temp_def_expr (get_type (src)); + tst = e->e.assign.src; + if (has_block_expr (tst) && has_block_expr (e->e.assign.dst)) { + tst = new_temp_def_expr (get_type (tst)); e = new_assign_expr (e->e.assign.dst, - assign_expr (src, e->e.assign.src)); + assign_expr (tst, e->e.assign.src)); + } else if (has_block_expr (tst)) { + tst = e->e.assign.dst; } - b = convert_bool (src, 1); + b = convert_bool (tst, 1); if (b->type == ex_error) return b; // insert the assignment into the bool's block From 47fb887724800b618f3fe8270c14a5883e0dca81 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Nov 2022 00:49:47 +0900 Subject: [PATCH 3194/3664] [vulkan] Implement Draw_TileClear The status bar doesn't look right without it when it's supposed to be there. --- libs/video/renderer/vulkan/vulkan_draw.c | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index f520e8ba5..6b65907f8 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -158,6 +158,7 @@ typedef struct drawctx_s { qpic_t *conchars; qpic_t *conback; qpic_t *white_pic; + qpic_t *backtile_pic; // use two separate cmem blocks for pics and strings (cachepic names) // to ensure the names are never in the same cacheline as a pic since the // names are used only for lookup @@ -527,6 +528,11 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) byte white_block = 0xfe; dctx->white_pic = pic_data ("white", 1, 1, &white_block, dctx); + dctx->backtile_pic = Vulkan_Draw_PicFromWad ("backtile", ctx); + if (!dctx->backtile_pic) { + dctx->backtile_pic = dctx->white_pic; + } + flush_draw_scrap (ctx); dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); @@ -902,6 +908,35 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) void Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + + static quat_t color = { 1, 1, 1, 1}; + vrect_t *tile_rect = VRect_New (x, y, w, h); + vrect_t *sub = VRect_New (0, 0, 0, 0); // filled in later + qpic_t *pic = dctx->backtile_pic; + subpic_t *subpic = *(subpic_t **) pic->data; + int sub_sx, sub_sy, sub_ex, sub_ey; + + sub_sx = x / pic->width; + sub_sy = y / pic->height; + sub_ex = (x + w + pic->width - 1) / pic->width; + sub_ey = (y + h + pic->height - 1) / pic->height; + for (int j = sub_sy; j < sub_ey; j++) { + for (int i = sub_sx; i < sub_ex; i++) { + vrect_t *t = sub; + + sub->x = i * pic->width; + sub->y = j * pic->height; + sub->width = pic->width; + sub->height = pic->height; + sub = VRect_Intersect (sub, tile_rect); + VRect_Delete (t); + draw_pic (sub->x, sub->y, sub->width, sub->height, subpic, + sub->x % pic->width, sub->y % pic->height, + sub->width, sub->height, color, &frame->quad_verts); + } + } } void From 767b39b7bd638b516971ef03354f59e4c263446b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Nov 2022 04:04:27 +0900 Subject: [PATCH 3195/3664] [client] Implement the scoreboards and spectator This gets the status bar/hud back into function state. --- include/sbar.h | 1 + libs/client/sbar.c | 550 ++++++++++++++++++++++--------------------- qw/source/cl_cam.c | 5 +- qw/source/cl_parse.c | 3 +- 4 files changed, 288 insertions(+), 271 deletions(-) diff --git a/include/sbar.h b/include/sbar.h index a1733154f..24f359f8a 100644 --- a/include/sbar.h +++ b/include/sbar.h @@ -38,6 +38,7 @@ void Sbar_Init (int *stats, float *item_gettime); void Sbar_SetPlayers (struct player_info_s *players, int maxplayers); void Sbar_SetLevelName (const char *levelname, const char *servername); void Sbar_SetPlayerNum (int playernum, int spectator); +void Sbar_SetAutotrack (int autotrack); void Sbar_SetViewEntity (int viewentity); void Sbar_SetTeamplay (int teamplay); void Sbar_SetGameType (int gametype); diff --git a/libs/client/sbar.c b/libs/client/sbar.c index a17f7b359..b651ae027 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -83,6 +83,7 @@ static int sbar_maxplayers; static int sbar_playernum; static int sbar_viewplayer; static int sbar_spectator; +static int sbar_autotrack = -1; static int sbar_teamplay; static int sbar_gametype; static int sbar_active; @@ -116,7 +117,8 @@ static view_t sbar_solo_anchor; static view_t sbar_solo_name; static view_t sbar_tile[2]; static view_t sbar_tile[2]; -static view_t dmo_view; +static view_t spectator_view; +static view_t deathmatch_view; typedef struct view_def_s { view_t *view; @@ -227,7 +229,12 @@ static view_def_t sbar_defs[] = { {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 3, 24, 0}, {0, {10, 0, 24, 8}, grav_northwest, &sbar_miniammo, 4, 48, 0}, - {&dmo_view, { 0, 0,320, 200}, grav_center, &cl_screen_view}, + {&spectator_view, { 0, 0,320, 32}, grav_south, &cl_screen_view}, + {0, { 0, 0, 312, 8}, grav_north, &spectator_view, 1, 0, 0}, + {0, { 0, 8, 320, 24}, grav_northwest, &spectator_view, 1, 0, 0}, + {0, { 0, 12, 112, 8}, grav_north, &spectator_view, 1, 0, 0}, + {0, { 0, 20, 232, 8}, grav_north, &spectator_view, 1, 0, 0}, + {&deathmatch_view, { 0, 0,320, 200}, grav_center, &cl_screen_view}, {} }; @@ -237,6 +244,8 @@ static draw_charbuffer_t *fps_buff; static draw_charbuffer_t *ping_buff; static draw_charbuffer_t *pl_buff; +static draw_charbuffer_t *spec_buff[4];//0,1 no track, 2 lost track, 3 tracking + static draw_charbuffer_t *solo_monsters; static draw_charbuffer_t *solo_secrets; static draw_charbuffer_t *solo_time; @@ -277,6 +286,12 @@ sbar_remcomponent (view_t view, uint32_t comp) Ent_RemoveComponent (view.id, comp, view.reg); } +static inline void +set_update (view_t view, hud_update_f func) +{ + sbar_setcomponent (view, hud_updateonce, &func); +} + #define STAT_MINUS 10 // num frame for '-' stats digit static qpic_t *sb_nums[2][11]; @@ -308,7 +323,7 @@ static qpic_t *sb_face_invuln; static qpic_t *sb_face_invis_invuln; qboolean sbar_showscores; -static qboolean sb_showteamscores; +static qboolean sbar_showteamscores; static int sb_lines; // scan lines to draw @@ -373,12 +388,43 @@ viewsize_f (int view_size) } } -static int __attribute__((used)) +static int Sbar_ColorForMap (int m) { return (bound (0, m, 13) * 16) + 8; } +static int +write_charbuff_cl (draw_charbuffer_t *buffer, int x, int y, const char *str) +{ + char *dst = buffer->chars; + int count = buffer->width - x; + int chars = 0; + dst += y * buffer->width + x; + while (*str && count-- > 0) { + *dst++ = *str++; + chars++; + } + while (count-- > 0) { + *dst++ = ' '; + } + return chars; +} + +static int +write_charbuff (draw_charbuffer_t *buffer, int x, int y, const char *str) +{ + char *dst = buffer->chars; + int count = buffer->width - x; + int chars = 0; + dst += y * buffer->width + x; + while (*str && count-- > 0) { + *dst++ = *str++; + chars++; + } + return chars; +} + static void draw_num (view_t *view, int num, int digits, int color) { @@ -409,7 +455,7 @@ draw_num (view_t *view, int num, int digits, int color) } } -static inline void +static void draw_smallnum (view_t view, int n, int packed, int colored) { void *comp = sbar_getcomponent (view, hud_charbuff); @@ -599,6 +645,8 @@ static draw_charbuffer_t *sb_pl[MAX_PLAYERS]; static draw_charbuffer_t *sb_uid[MAX_PLAYERS]; static draw_charbuffer_t *sb_name[MAX_PLAYERS]; static draw_charbuffer_t *sb_team_frags[MAX_PLAYERS]; +static draw_charbuffer_t *sb_team_players[MAX_PLAYERS]; +static draw_charbuffer_t *sb_team_stats[MAX_PLAYERS]; static draw_charbuffer_t *sb_spectator; int scoreboardlines, scoreboardteams; @@ -634,7 +682,7 @@ Sbar_SortFrags (qboolean includespec) } } -static void __attribute__((used)) +static void Sbar_SortTeams (void) { char t[16 + 1]; @@ -644,15 +692,13 @@ Sbar_SortTeams (void) // request new ping times every two second scoreboardteams = 0; - if (!sbar_teamplay) - return; // sort the teams memset (teams, 0, sizeof (teams)); - for (i = 0; i < MAX_PLAYERS; i++) + for (i = 0; i < sbar_maxplayers; i++) teams[i].plow = 999; - for (i = 0; i < MAX_PLAYERS; i++) { + for (i = 0; i < sbar_maxplayers; i++) { s = &sbar_players[i]; if (!s->name || !s->name->value[0]) continue; @@ -661,7 +707,8 @@ Sbar_SortTeams (void) // find his team in the list t[16] = 0; - strncpy (t, s->team->value, 16); + if (s->team) + strncpy (t, s->team->value, 16); if (!t[0]) continue; // not on team for (j = 0; j < scoreboardteams; j++) @@ -683,6 +730,24 @@ Sbar_SortTeams (void) teams[j].ptotal += s->ping; } } + for (i = 0; i < sbar_maxplayers; i++) { + team_t *tm = teams + i; + int plow = tm->plow; + if (plow < 0 || plow > 999) + plow = 999; + int phigh = tm->phigh; + if (phigh < 0 || phigh > 999) + phigh = 999; + int pavg = !tm->players ? 999 : tm->ptotal / tm->players; + if (pavg < 0 || pavg > 999) + pavg = 999; + + write_charbuff (sb_team_stats[i], 0, 0, + va (0, "%3i/%3i/%3i", plow, pavg, phigh)); + write_charbuff (sb_team[i], 0, 0, tm->team); + write_charbuff (sb_team_frags[i], 0, 0, va (0, "%5d", tm->frags)); + write_charbuff (sb_team_players[i], 0, 0, va (0, "%5d", tm->players)); + } // sort for (i = 0; i < scoreboardteams; i++) @@ -700,37 +765,6 @@ Sbar_SortTeams (void) } } -static int -write_charbuff_cl (draw_charbuffer_t *buffer, int x, int y, const char *str) -{ - char *dst = buffer->chars; - int count = buffer->width - x; - int chars = 0; - dst += y * buffer->width + x; - while (*str && count-- > 0) { - *dst++ = *str++; - chars++; - } - while (count-- > 0) { - *dst++ = ' '; - } - return chars; -} - -static int -write_charbuff (draw_charbuffer_t *buffer, int x, int y, const char *str) -{ - char *dst = buffer->chars; - int count = buffer->width - x; - int chars = 0; - dst += y * buffer->width + x; - while (*str && count-- > 0) { - *dst++ = *str++; - chars++; - } - return chars; -} - static void draw_solo_time (void) { @@ -741,13 +775,23 @@ draw_solo_time (void) } static void -draw_solo (void) +draw_solo (view_t view) { - draw_solo_time (); - view_pos_t len = View_GetLen (sbar_solo_name); - len.x = 8 * solo_name->cursx; - View_SetLen (sbar_solo_name, len.x, len.y); - View_UpdateHierarchy (sbar_solo); + sbar_setcomponent (sbar_solo, hud_pic, &sb_scorebar); + sbar_setcomponent (sbar_solo_monsters, hud_charbuff, &solo_monsters); + sbar_setcomponent (sbar_solo_secrets, hud_charbuff, &solo_secrets); + sbar_setcomponent (sbar_solo_time, hud_charbuff, &solo_time); + sbar_setcomponent (sbar_solo_name, hud_charbuff, &solo_name); +} + +static void +hide_solo (view_t view) +{ + sbar_remcomponent (sbar_solo, hud_pic); + sbar_remcomponent (sbar_solo_monsters, hud_charbuff); + sbar_remcomponent (sbar_solo_secrets, hud_charbuff); + sbar_remcomponent (sbar_solo_time, hud_charbuff); + sbar_remcomponent (sbar_solo_name, hud_charbuff); } static void @@ -973,30 +1017,46 @@ draw_face (view_t view) sbar_setcomponent (view, hud_pic, &face); } -static void __attribute__((used)) -draw_spectator (view_t *view) +static void +draw_spectator (view_t view) { -#if 0 - char st[512]; + view_t tracking = View_GetChild (view, 0); + view_t back = View_GetChild (view, 1); + view_t notrack[] = { + View_GetChild (view, 2), + View_GetChild (view, 3), + }; - if (autocam != CAM_TRACK) { - draw_string (view, 160 - 7 * 8, 4, "SPECTATOR MODE"); - draw_string (view, 160 - 14 * 8 + 4, 12, - "Press [ATTACK] for AutoCamera"); + if (sbar_autotrack < 0) { + sbar_setcomponent (back, hud_pic, &sb_scorebar); + sbar_setcomponent (notrack[0], hud_charbuff, &spec_buff[0]); + sbar_setcomponent (notrack[1], hud_charbuff, &spec_buff[1]); + sbar_remcomponent (tracking, hud_charbuff); } else { -// Sbar_DrawString (160-14*8+4,4, "SPECTATOR MODE - TRACK CAMERA"); - if (sbar_players[spec_track].name) { - snprintf (st, sizeof (st), "Tracking %-.13s, [JUMP] for next", - sbar_players[spec_track].name->value); + sbar_remcomponent (back, hud_pic); + sbar_remcomponent (notrack[0], hud_charbuff); + sbar_remcomponent (notrack[1], hud_charbuff); + if (sbar_players[sbar_autotrack].name) { + write_charbuff_cl (spec_buff[3], 0, 0, + va (0, "Tracking %.13s, [JUMP] for next", + sbar_players[sbar_autotrack].name->value)); + sbar_setcomponent (tracking, hud_charbuff, &spec_buff[3]); } else { - snprintf (st, sizeof (st), "Lost player, [JUMP] for next"); + sbar_setcomponent (tracking, hud_charbuff, &spec_buff[2]); } - draw_string (view, 0, -8, st); } -#endif } -static inline void +static void +hide_spectator (view_t view) +{ + for (int i = 0; i < 4; i++) { + sbar_remcomponent (View_GetChild (view, i), hud_charbuff); + sbar_remcomponent (View_GetChild (view, i), hud_pic); + } +} + +static void draw_armor (view_t view) { view_t armor = View_GetChild (view, 0); @@ -1020,7 +1080,7 @@ draw_armor (view_t view) } } -static inline void +static void draw_health (view_t view) { view_t num[3] = { @@ -1031,39 +1091,6 @@ draw_health (view_t view) draw_num (num, sbar_stats[STAT_HEALTH], 3, sbar_stats[STAT_HEALTH] <= 25); } -static void -draw_status (void ) -{ - sb_updates = 0; - - sbar_setcomponent (sbar_solo, hud_pic, &sb_scorebar); - sbar_setcomponent (sbar_solo_monsters, hud_charbuff, &solo_monsters); - sbar_setcomponent (sbar_solo_secrets, hud_charbuff, &solo_secrets); - sbar_setcomponent (sbar_solo_time, hud_charbuff, &solo_time); - sbar_setcomponent (sbar_solo_name, hud_charbuff, &solo_name); - - draw_solo (); -#if 0 - if (sbar_spectator) { - draw_spectator (view); - if (autocam != CAM_TRACK) - return; - } -#endif -} - -static void -hide_status (void) -{ - sb_updates = 0; - - sbar_remcomponent (sbar_solo, hud_pic); - sbar_remcomponent (sbar_solo_monsters, hud_charbuff); - sbar_remcomponent (sbar_solo_secrets, hud_charbuff); - sbar_remcomponent (sbar_solo_time, hud_charbuff); - sbar_remcomponent (sbar_solo_name, hud_charbuff); -} - static void draw_rogue_ctf_face (view_t view) { @@ -1106,16 +1133,19 @@ typedef struct dmo_def_s { void (*setup) (view_t, int); } dmo_def_t; -static dmo_def_t ping_def = { .width = 24, .buffer = sb_ping, }; -static dmo_def_t pl_def = { .width = 24, .buffer = sb_pl, }; -static dmo_def_t fph_def = { .width = 24, .buffer = sb_fph, }; -static dmo_def_t time_def = { .width = 32, .buffer = sb_time, }; -static dmo_def_t frags_def = { .width = 40, .setup = setup_frags, }; -static dmo_def_t team_def = { .width = 32, .buffer = sb_uid, }; -static dmo_def_t uid_def = { .width = 32, .buffer = sb_uid, }; -static dmo_def_t name_def = { .width = 128, .buffer = sb_name, }; -static dmo_def_t spectator_def = { .width = 112, .setup = setup_spect, }; +static dmo_def_t ping_def = { .width = 24, .buffer = sb_ping }; +static dmo_def_t pl_def = { .width = 24, .buffer = sb_pl }; +static dmo_def_t fph_def = { .width = 24, .buffer = sb_fph }; +static dmo_def_t time_def = { .width = 32, .buffer = sb_time }; +static dmo_def_t frags_def = { .width = 40, .setup = setup_frags }; +static dmo_def_t team_def = { .width = 32, .buffer = sb_uid }; +static dmo_def_t uid_def = { .width = 32, .buffer = sb_uid }; +static dmo_def_t name_def = { .width = 128, .buffer = sb_name }; +static dmo_def_t spectator_def = { .width = 112, .setup = setup_spect }; static dmo_def_t spec_team_def = { .width = 32, }; +static dmo_def_t team_frags_def = { .width = 40, .buffer = sb_team_frags }; +static dmo_def_t team_stats_def = { .width = 88, .buffer = sb_team_stats }; +static dmo_def_t team_players_def = { .width = 40, .buffer = sb_team_players }; static dmo_def_t *nq_dmo_defs[] = { &frags_def, @@ -1164,15 +1194,6 @@ static dmo_def_t *qw_dmo_uid_ping_defs[] = { 0 }; static dmo_def_t *qw_dmo_uid_defs[] = { - &ping_def, - &pl_def, - &fph_def, - &time_def, - &frags_def, - &name_def, - 0 -}; -static dmo_def_t *qw_dmo_ping_defs[] = { &uid_def, &pl_def, &fph_def, @@ -1181,16 +1202,26 @@ static dmo_def_t *qw_dmo_ping_defs[] = { &name_def, 0 }; -static dmo_def_t *qw_dmo_spect_team_uid_ping_defs[] = { +static dmo_def_t *qw_dmo_ping_defs[] = { &ping_def, &pl_def, + &fph_def, + &time_def, + &frags_def, + &name_def, + 0 +}; +static dmo_def_t *qw_dmo_spect_team_uid_ping_defs[] = { + &uid_def, + &pl_def, &spectator_def, &spec_team_def, + &ping_def, &name_def, 0 }; static dmo_def_t *qw_dmo_spect_team_uid_defs[] = { - &ping_def, + &uid_def, &pl_def, &spectator_def, &spec_team_def, @@ -1209,11 +1240,12 @@ static dmo_def_t *qw_dmo_spect_uid_ping_defs[] = { &ping_def, &pl_def, &spectator_def, + &uid_def, &name_def, 0 }; static dmo_def_t *qw_dmo_spect_uid_defs[] = { - &ping_def, + &uid_def, &pl_def, &spectator_def, &name_def, @@ -1226,26 +1258,38 @@ static dmo_def_t *qw_dmo_spect_ping_defs[] = { &name_def, 0 }; +static dmo_def_t *team_overlay_defs[] = { + &team_stats_def, + &team_def, + &team_frags_def, + &team_players_def, + 0 +}; static dmo_def_t **dmo_defs[] = { nq_dmo_defs, + team_overlay_defs, + qw_dmo_ping_defs, qw_dmo_uid_defs, qw_dmo_uid_ping_defs, + qw_dmo_team_ping_defs, qw_dmo_team_uid_defs, qw_dmo_team_uid_ping_defs, + qw_dmo_spect_ping_defs, qw_dmo_spect_uid_defs, qw_dmo_spect_uid_ping_defs, + qw_dmo_spect_team_ping_defs, qw_dmo_spect_team_uid_defs, qw_dmo_spect_team_uid_ping_defs, }; static view_t -make_dmo_line (view_t parent, int player) +make_dmo_line (view_t parent, int player, int line_type) { - dmo_def_t **defs = dmo_defs[3]; //FIXME nq/qw/team/spec/cvar + dmo_def_t **defs = dmo_defs[line_type]; int x = -8; view_t line = sbar_view (0, 0, 0, 0, grav_north, parent); @@ -1272,14 +1316,9 @@ calc_fph (int frags, int total) { int fph; - if (total != 0) { + if (total) { fph = (3600 * frags) / total; - - if (fph >= 999) { - fph = 999; - } else if (fph <= -999) { - fph = -999; - } + fph = bound (-999, fph, 999); } else { fph = 0; } @@ -1287,32 +1326,46 @@ calc_fph (int frags, int total) return fph; } +static int +dmo_line_type (void) +{ + if (!sbar_servername) { + return 0; + } else if (sbar_showteamscores) { + return 1; + } else { + int team = !!sbar_teamplay; + int spect = !!sbar_spectator; + int mode = bound (0, hud_scoreboard_uid, 2); + + return 2 + mode + team * 3 + spect * mode; + } +} + static void -Sbar_DeathmatchOverlay (view_t view) +draw_deathmatch (view_t view) { Sbar_SortFrags (0); + Sbar_SortTeams (); int y = 40; view_pos_t len = View_GetLen (view); int numbars = (len.y - y) / 10; int count = min (scoreboardlines, numbars); + int line_type = dmo_line_type (); int i; - if (sbar_stats[STAT_HEALTH] > 0) { - count = 0; - } - double cur_time = sbar_intermission ? sbar_completed_time : sbar_time; for (i = 0; i < count; i++, y += 10) { int k = fragsort[i]; player_info_t *p = &sbar_players[k]; if (!View_Valid (sb_views[k])) { - sb_views[k] = make_dmo_line (view, k); + sb_views[k] = make_dmo_line (view, k, line_type); } int total = cur_time - p->entertime; write_charbuff (sb_fph[k], 0, 0, va (0, "%3d", calc_fph (p->frags, total))); - write_charbuff (sb_time[k], 0, 0, va (0, "%3d", total / 60)); + write_charbuff (sb_time[k], 0, 0, va (0, "%4d", total / 60)); View_SetPos (sb_views[k], 0, y); } for (; i < MAX_PLAYERS; i++) { @@ -1324,106 +1377,40 @@ Sbar_DeathmatchOverlay (view_t view) View_UpdateHierarchy (view); } -static void __attribute__((used)) -Sbar_TeamOverlay (view_t *view) -{ -#if 0 - char num[20]; - int pavg, plow, phigh, i, k, x, y; - team_t *tm; - info_key_t *player_team = sbar_players[sbar_playernum].team; - - if (!sbar_teamplay) { // FIXME: if not teamplay, why teamoverlay? - Sbar_DeathmatchOverlay (view, 0); - return; - } - - r_data->scr_copyeverything = 1; - r_data->scr_fullupdate = 0; - - draw_cachepic (view, 0, 0, "gfx/ranking.lmp", 1); - - y = 24; - x = 36; - draw_string (view, x, y, "low/avg/high team total players"); - y += 8; - draw_string (view, x, y, "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1e\x1e\x1f"); - y += 8; - - // sort the teams - Sbar_SortTeams (); - - // draw the text - for (i = 0; i < scoreboardteams && y <= view->ylen - 10; i++) { - k = teamsort[i]; - tm = teams + k; - - // draw pings - plow = tm->plow; - if (plow < 0 || plow > 999) - plow = 999; - phigh = tm->phigh; - if (phigh < 0 || phigh > 999) - phigh = 999; - if (!tm->players) - pavg = 999; - else - pavg = tm->ptotal / tm->players; - if (pavg < 0 || pavg > 999) - pavg = 999; - - snprintf (num, sizeof (num), "%3i/%3i/%3i", plow, pavg, phigh); - draw_string (view, x, y, num); - - // draw team - draw_nstring (view, x + 104, y, tm->team, 4); - - // draw total - snprintf (num, sizeof (num), "%5i", tm->frags); - draw_string (view, x + 104 + 40, y, num); - - // draw players - snprintf (num, sizeof (num), "%5i", tm->players); - draw_string (view, x + 104 + 88, y, num); - - if (player_team && strnequal (player_team->value, tm->team, 16)) { - draw_character (view, x + 104 - 8, y, 16); - draw_character (view, x + 104 + 32, y, 17); - } - - y += 8; - } - y += 8; - Sbar_DeathmatchOverlay (view, y); -#endif -} - -#if 0 static void -Sbar_DrawScoreboard (void) +hide_deathmatch (view_t view) { - //Sbar_SoloScoreboard (); - if (cl.gametype == GAME_DEATHMATCH) - Sbar_DeathmatchOverlay (hud_overlay_view); - if (!sbar_active - || !((sbar_stats[STAT_HEALTH] <= 0 && !sbar_spectator) - || sbar_showscores || sb_showteamscores)) - return; - // main screen deathmatch rankings - // if we're dead show team scores in team games - if (sbar_stats[STAT_HEALTH] <= 0 && !sbar_spectator) - if (sbar_teamplay > 0 && !sbar_showscores) - Sbar_TeamOverlay (view); - else - Sbar_DeathmatchOverlay (view, 0); - else if (sbar_showscores) - Sbar_DeathmatchOverlay (view, 0); - else if (sb_showteamscores) - Sbar_TeamOverlay (view); + uint32_t count = View_ChildCount (view); + while (count-- > 0) { + View_Delete (View_GetChild (view, count)); + } +} + +static void +draw_status (void ) +{ + sb_updates = 0; + + + if (sbar_gametype) { + draw_deathmatch (deathmatch_view); + } else { + if (sbar_spectator) { + if (sbar_autotrack < 0) { + return; + } + } + draw_solo (sbar_solo); + } +} + +static void +hide_status (void) +{ + sb_updates = 0; + hide_solo (sbar_solo); + hide_deathmatch (deathmatch_view); } -#endif /* autologging of frags after a match ended (called by recived network packet with command scv_intermission) @@ -1710,25 +1697,28 @@ draw_cutscene (view_t view) clear_views (view); } -static inline void -set_update (view_t view, hud_update_f func) -{ - sbar_setcomponent (view, hud_updateonce, &func); -} - void Sbar_Intermission (int mode, double completed_time) { - static hud_update_f intermission_funcs[2][4] = { - { clear_views, draw_intermission, draw_finale, draw_cutscene, }, - { clear_views, Sbar_DeathmatchOverlay, draw_finale, draw_cutscene, }, + static hud_update_f intermission_funcs[2][3] = { + { draw_intermission, draw_finale, draw_cutscene, }, + { draw_deathmatch, draw_finale, draw_cutscene, }, + }; + static view_t *views[2][3] = { + { &intermission_view, &intermission_view, &intermission_view }, + { &deathmatch_view, &intermission_view, &intermission_view }, }; sbar_completed_time = completed_time; if ((unsigned) mode > 3) { mode = 0; } sbar_intermission = mode; - set_update (intermission_view, intermission_funcs[sbar_gametype][mode]); + set_update (intermission_view, clear_views); + set_update (deathmatch_view, clear_views); + if (mode > 0) { + set_update (*views[sbar_gametype][mode - 1], + intermission_funcs[sbar_gametype][mode - 1]); + } } void @@ -1766,6 +1756,7 @@ Sbar_Update (double time) sb_updates++; draw_weapons (sbar_weapons); draw_items (sbar_items); + draw_face (sbar_face); } } @@ -1820,7 +1811,7 @@ update_health (int stat) set_update (sbar_face, draw_face); if (sbar_stats[STAT_HEALTH] <= 0) { draw_status (); - } else if (!sbar_showscores) { + } else if (1||!sbar_showscores) { hide_status (); } } @@ -1832,7 +1823,7 @@ update_frags (int stat) va (0, "%3d", sbar_stats[stat])); set_update (sbar_frags, draw_frags);//FIXME set_update (hud_minifrags, draw_minifrags);//FIXME - set_update (dmo_view, Sbar_DeathmatchOverlay);//FIXME + set_update (deathmatch_view, draw_deathmatch);//FIXME if (sbar_teamplay) { set_update (hud_miniteam, draw_miniteam);//FIXME } @@ -1906,12 +1897,12 @@ update_monsters (int stat) static void update_items (int stat) { - set_update (sbar_items, draw_items);//FIXME + set_update (sbar_items, draw_items); + set_update (sbar_weapons, draw_weapons); if (sb_item_count < 7) { // hipnotic and rogue don't use sigils - set_update (sbar_sigils, draw_sigils);//FIXME + set_update (sbar_sigils, draw_sigils); } - set_update (sbar_weapons, draw_weapons);//FIXME } typedef void (*stat_update_f) (int stat); @@ -1936,16 +1927,11 @@ static stat_update_f stat_update[MAX_CL_STATS] = { void Sbar_UpdateStats (int stat) { - if (stat == -1) { - for (int i = 0; i < MAX_CL_STATS; i++) { - if (stat_update[i]) { - stat_update[i] (i); - } - } - } else { - if ((unsigned) stat < MAX_CL_STATS && stat_update[stat]) { - stat_update[stat] (stat); - } + if ((unsigned) stat >= MAX_CL_STATS) { + Sys_Error ("Sbar_UpdateStats: invalid stat: %d", stat); + } + if (stat_update[stat]) { + stat_update[stat] (stat); } } @@ -1960,6 +1946,23 @@ Sbar_SetPlayerNum (int playernum, int spectator) { sbar_playernum = playernum; sbar_spectator = spectator; + + if (sbar_spectator) { + set_update (spectator_view, draw_spectator); + } else { + set_update (spectator_view, hide_spectator); + } +} + +void +Sbar_SetAutotrack (int autotrack) +{ + sbar_autotrack = autotrack; + if (sbar_spectator) { + set_update (spectator_view, draw_spectator); + } else { + set_update (spectator_view, hide_spectator); + } } void @@ -1974,6 +1977,11 @@ Sbar_SetLevelName (const char *levelname, const char *servername) sbar_levelname = levelname; sbar_servername = servername; solo_name->cursx = write_charbuff_cl (solo_name, 0, 0, sbar_levelname); + + view_pos_t len = View_GetLen (sbar_solo_name); + len.x = 8 * solo_name->cursx; + View_SetLen (sbar_solo_name, len.x, len.y); + View_UpdateHierarchy (sbar_solo); } void @@ -2263,21 +2271,33 @@ init_views (void) fps_buff = Draw_CreateBuffer (10, 1); ping_buff = Draw_CreateBuffer (6, 1); pl_buff = Draw_CreateBuffer (6, 1); + for (int i = 0; i < MAX_PLAYERS; i++) { sb_fph[i] = Draw_CreateBuffer (3, 1); sb_time[i] = Draw_CreateBuffer (4, 1); sb_frags[i] = Draw_CreateBuffer (3, 1); - sb_team[i] = Draw_CreateBuffer (4, 1); sb_ping[i] = Draw_CreateBuffer (3, 1); sb_pl[i] = Draw_CreateBuffer (3, 1); sb_uid[i] = Draw_CreateBuffer (4, 1); sb_name[i] = Draw_CreateBuffer (16, 1); + + sb_team[i] = Draw_CreateBuffer (4, 1); + sb_team_stats[i] = Draw_CreateBuffer (11, 1); sb_team_frags[i] = Draw_CreateBuffer (5, 1); + sb_team_players[i] = Draw_CreateBuffer (5, 1); fragsort[i] = -1; } sb_spectator = Draw_CreateBuffer (11, 1); write_charbuff (sb_spectator, 0, 0, "(spectator)"); + spec_buff[0] = Draw_CreateBuffer (14, 1); + spec_buff[1] = Draw_CreateBuffer (29, 1); + spec_buff[2] = Draw_CreateBuffer (28, 1); + spec_buff[3] = Draw_CreateBuffer (39, 1); + write_charbuff (spec_buff[0], 0, 0, "SPECTATOR MODE"); + write_charbuff (spec_buff[1], 0, 0, "Press [ATTACK] for AutoCamera"); + write_charbuff (spec_buff[2], 0, 0, "Lost player, [JUMP] for next"); + init_sbar_views (); } @@ -2487,40 +2507,34 @@ load_pics (void) static void Sbar_ShowScores (void) { - if (sbar_showscores) - return; - sbar_showscores = true; - draw_status (); } static void Sbar_DontShowScores (void) { - if (!sbar_showscores || sbar_stats[STAT_HEALTH] <= 0) { + if (sbar_autotrack >= 0 && sbar_stats[STAT_HEALTH] <= 0) { return; } - sbar_showscores = false; - hide_status (); } static void Sbar_ShowTeamScores (void) { - if (sb_showteamscores) + if (sbar_showteamscores) return; - sb_showteamscores = true; + sbar_showteamscores = true; sb_updates = 0; } static void Sbar_DontShowTeamScores (void) { - sb_showteamscores = false; + sbar_showteamscores = false; sb_updates = 0; } diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 6cfc92d97..ba753a05a 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -199,7 +199,7 @@ Cam_Unlock (void) } autocam = CAM_NONE; locked = false; - Sbar_UpdateStats (-1); // update all stats + Sbar_SetAutotrack (-1); } } @@ -221,7 +221,7 @@ Cam_Lock (int playernum) last_lock = realtime; cam_forceview = true; locked = false; - Sbar_UpdateStats (-1); // update all stats + Sbar_SetAutotrack (spec_track); } static trace_t @@ -681,6 +681,7 @@ Cam_Reset (void) autocam = CAM_NONE; spec_track = 0; ideal_track = 0; + Sbar_SetAutotrack (-1); } void diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 686e52d0c..d6b939e59 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -775,11 +775,13 @@ CL_ParseServerData (void) cl.viewentity = cl.playernum + 1; cl.viewstate.bob_enabled = !cl.spectator; + Sbar_SetPlayerNum (cl.playernum, cl.spectator); // get the full level name str = MSG_ReadString (net_message); strncpy (cl.levelname, str, sizeof (cl.levelname) - 1); Sbar_SetLevelName (cl.levelname, cls.servername->str); + Sbar_SetGameType (1); // get the movevars movevars.gravity = MSG_ReadFloat (net_message); @@ -1139,7 +1141,6 @@ CL_ServerInfo (void) // movevars.ktjump = atof (value); // FIXME: need to set to 0.5 otherwise, outside of else structure } - Sbar_SetGameType (0); } static void From 88e59e72c48e2eb2463bef682e8dc14ba7a436aa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Nov 2022 14:35:47 +0900 Subject: [PATCH 3196/3664] [scene] Make nullentity's id nullent While an entity with a null registry is null regardless of the id, setting the id to nullent is useful for other purposes. Fixes the disappearing brush models in the vulkan renderer (it uses entity id + 1 for indexing), and prevents similar issues in the future. --- include/QF/scene/entity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index 48bc8a36d..950c8b322 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -50,7 +50,7 @@ typedef struct entity_s { uint32_t id; } entity_t; -#define nullentity ((entity_t) {}) +#define nullentity ((entity_t) { .id = nullent }) typedef struct animation_s { int frame; From 0e64f959e2b50418417b01930704e0318504bc58 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Nov 2022 15:08:18 +0900 Subject: [PATCH 3197/3664] [scene] Move visibility management into scene code Well, sort of: it's still really in the renderer, but now calling R_AddEfrags automatically updates the visibility structure as necessary, and deleting an entity cleans up the efrags automatically. I wanted this over twenty years ago. --- include/QF/scene/entity.h | 2 +- libs/client/cl_temp_entities.c | 18 +------ libs/ruamoko/rua_scene.c | 4 +- libs/scene/scene.c | 11 +++- libs/video/renderer/r_efrag.c | 24 ++++----- nq/source/cl_ents.c | 48 +++++------------ nq/source/cl_main.c | 3 +- qw/source/cl_ents.c | 97 ++++++++++++++-------------------- 8 files changed, 80 insertions(+), 127 deletions(-) diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index 950c8b322..488d9ed02 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -146,7 +146,7 @@ Entity_Transform (entity_t ent) struct mod_brush_s; void R_AddEfrags (struct mod_brush_s *, entity_t ent); -void R_RemoveEfrags (entity_t ent); +void R_ClearEfragChain (efrag_t *ef); ///@} diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index aa25e33ba..9cd834d2b 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -157,12 +157,10 @@ void CL_Init_Entity (entity_t ent) { renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, cl_world.scene->reg); animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); byte *active = Ent_GetComponent (ent.id, scene_active, cl_world.scene->reg); vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, cl_world.scene->reg); memset (animation, 0, sizeof (*animation)); - memset (visibility, 0, sizeof (*visibility)); memset (renderer, 0, sizeof (*renderer)); *active = 1; *old_origin = (vec4f_t) {0, 0, 0, 1}; @@ -223,11 +221,6 @@ static inline void beam_clear (beam_t *b) { if (b->tents) { - tent_t *t; - - for (t = b->tents; t; t = t->next) { - R_RemoveEfrags (t->ent); - } free_temp_entities (b->tents); b->tents = 0; } @@ -635,11 +628,9 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) ent = ex->tent->ent; f = 10 * (time - ex->start); renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, cl_world.scene->reg); animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); if (f >= renderer->model->numframes) { tent_obj_t *_to; - R_RemoveEfrags (ent); free_temp_entities (ex->tent); _to = *to; *to = _to->next; @@ -649,9 +640,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx) to = &(*to)->next; animation->frame = f; - if (!visibility->efrag) { - R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); - } + R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } @@ -688,11 +677,6 @@ CL_ParseParticleEffect (qmsg_t *net_message) void CL_ClearProjectiles (void) { - tent_t *tent; - - for (tent = cl_projectiles; tent; tent = tent->next) { - R_RemoveEfrags (tent->ent); - } free_temp_entities (cl_projectiles); cl_projectiles = 0; } diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 210e19be5..0993480a2 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -259,7 +259,6 @@ bi_Scene_DestroyEntity (progs_t *pr, void *_res) pr_ulong_t scene_id = id & 0xffffffff; rua_scene_t *scene = rua_scene_get (res, scene_id); - R_RemoveEfrags (ent); // bad scene caught above Scene_DestroyEntity (scene->scene, ent); } @@ -301,8 +300,7 @@ bi_Entity_SetModel (progs_t *pr, void *_res) // bad scene caught above rua_scene_t *scene = rua_scene_get (res, scene_id); - R_RemoveEfrags (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, scene->scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); renderer->model = model; R_AddEfrags (&scene->scene->worldmodel->brush, ent); } diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 3dabbe941..90266d160 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -59,6 +59,15 @@ create_old_origin (void *_old_origin) *old_origin = (vec4f_t) {0, 0, 0, 1}; } +static void +destroy_visibility (void *_visibility) +{ + visibility_t *visibility = _visibility; + if (visibility->efrag) { + R_ClearEfragChain (visibility->efrag); + } +} + static void sw_identity_matrix (void *_mat) { @@ -94,6 +103,7 @@ static const component_t scene_components[] = { [scene_visibility] = { .size = sizeof (visibility_t), .create = 0,//create_visibility, + .destroy = destroy_visibility, .name = "visibility", }, [scene_renderer] = { @@ -219,7 +229,6 @@ Scene_CreateEntity (scene_t *scene) uint32_t id = trans.id; Ent_SetComponent (id, scene_animation, scene->reg, 0); - Ent_SetComponent (id, scene_visibility, scene->reg, 0); Ent_SetComponent (id, scene_renderer, scene->reg, 0); Ent_SetComponent (id, scene_active, scene->reg, 0); Ent_SetComponent (id, scene_old_origin, scene->reg, 0); diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 3c9845906..89f919358 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -95,18 +95,10 @@ R_ClearEfrags (void) } } -/* - R_RemoveEfrags - - Call when removing an object from the world or moving it to another position -*/ void -R_RemoveEfrags (entity_t ent) +R_ClearEfragChain (efrag_t *ef) { - efrag_t *ef, *old, *walk, **prev; - visibility_t *vis = Ent_GetComponent (ent.id, scene_visibility, ent.reg); - - ef = vis->efrag; + efrag_t *old, *walk, **prev; while (ef) { prev = &ef->leaf->efrags; @@ -128,8 +120,6 @@ R_RemoveEfrags (entity_t ent) old->entnext = r_free_efrags; r_free_efrags = old; } - - vis->efrag = 0; } static void @@ -210,11 +200,19 @@ R_AddEfrags (mod_brush_t *brush, entity_t ent) vec3_t emins, emaxs; transform_t transform = Entity_Transform (ent); renderer_t *rend = Ent_GetComponent (ent.id, scene_renderer, ent.reg); - visibility_t *vis = Ent_GetComponent (ent.id, scene_visibility, ent.reg); if (!rend->model) { + Ent_RemoveComponent (ent.id, scene_visibility, ent.reg); return; } + visibility_t *vis; + if (Ent_HasComponent (ent.id, scene_visibility, ent.reg)) { + vis = Ent_GetComponent (ent.id, scene_visibility, ent.reg); + R_ClearEfragChain (vis->efrag); + } else { + vis = Ent_AddComponent (ent.id, scene_visibility, ent.reg); + } + vis->efrag = 0; entmodel = rend->model; diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index a5db5d3e6..2545ec02e 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -147,8 +147,8 @@ static void set_entity_model (int ent_ind, int modelindex) { entity_t ent = cl_entities[ent_ind]; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, ent.reg); renderer->model = cl_world.models.a[modelindex]; // automatic animation (torches, etc) can be either all together // or randomized @@ -158,10 +158,10 @@ set_entity_model (int ent_ind, int modelindex) } else { animation->syncbase = 0.0; } - } else { - // hack to make null model players work - SET_ADD (&cl_forcelink, ent_ind); } + // Changing the model can change the visibility of the entity and even + // the model type + SET_ADD (&cl_forcelink, ent_ind); animation->nolerp = 1; // don't try to lerp when the model has changed if (ent_ind <= cl.maxclients) { renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, ent_ind); @@ -175,7 +175,6 @@ CL_RelinkEntities (void) entity_state_t *new, *old; float bobjrotate, frac, f; int i, j; - int entvalid; int model_flags; // determine partial update time @@ -207,31 +206,23 @@ CL_RelinkEntities (void) new = &nq_entstates.frame[0 + cl.frameIndex][i]; old = &nq_entstates.frame[1 - cl.frameIndex][i]; - // if the object wasn't included in the last packet, remove it - entvalid = cl_msgtime[i] == cl.mtime[0]; - if (entvalid && !new->modelindex) { - ent = CL_GetEntity (i); - CL_TransformEntity (ent, new->scale / 16.0, new->angles, - new->origin); - entvalid = 0; - } - if (!entvalid) { - ent = CL_GetInvalidEntity (i); + ent = CL_GetInvalidEntity (i); + // if the object wasn't included in the last packet, or the model + // has been removed, remove the entity + if (cl_msgtime[i] != cl.mtime[0] || !new->modelindex) { if (Entity_Valid (ent)) { - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, ent.reg); - if (visibility->efrag) { - R_RemoveEfrags (ent); // just became empty - } Scene_DestroyEntity (cl_world.scene, ent); } continue; } - ent = CL_GetEntity (i); + if (!Entity_Valid (ent)) { + ent = CL_GetEntity (i); + SET_ADD (&cl_forcelink, i); + } transform_t transform = Entity_Transform (ent); renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); animation_t *animation = Ent_GetComponent (ent.id, scene_animation, ent.reg); - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, ent.reg); vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, ent.reg); if (SET_TEST_MEMBER (&cl_forcelink, i)) { @@ -242,9 +233,6 @@ CL_RelinkEntities (void) || new->modelindex != old->modelindex) { old->modelindex = new->modelindex; set_entity_model (i, new->modelindex); - if (visibility->efrag) { - R_RemoveEfrags (ent); - } } animation->frame = new->frame; if (SET_TEST_MEMBER (&cl_forcelink, i) @@ -280,9 +268,6 @@ CL_RelinkEntities (void) CL_TransformEntity (ent, new->scale / 16.0, new->angles, new->origin); if (i != cl.viewentity || chase_active) { - if (visibility->efrag) { - R_RemoveEfrags (ent); - } R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } *old_origin = new->origin; @@ -315,12 +300,7 @@ CL_RelinkEntities (void) } if (i != cl.viewentity || chase_active) { vec4f_t org = Transform_GetWorldPosition (transform); - if (visibility->efrag) { - if (!VectorCompare (org, *old_origin)) {//FIXME - R_RemoveEfrags (ent); - R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); - } - } else { + if (!VectorCompare (org, *old_origin)) {//FIXME R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 267438cf3..e51f0884b 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -234,10 +234,9 @@ CL_ClearMemory (void) cl.viewstate.demoplayback = cls.demoplayback; CL_ClearTEnts (); + CL_ClearEnts (); SCR_NewScene (0); - - CL_ClearEnts (); } void diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index ef8eb3ec6..467fcce23 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -89,6 +89,12 @@ CL_ClearEnts (void) memset (cl_entity_valid, 0, sizeof (cl_entity_valid)); } +static entity_t +CL_GetInvalidEntity (int num) +{ + return cl_entities[num]; +} + entity_t CL_GetEntity (int num) { @@ -163,42 +169,37 @@ CL_LinkPacketEntities (void) for (i = MAX_CLIENTS + 1; i < 512; i++) { new = &qw_entstates.frame[cl.link_sequence & UPDATE_MASK][i]; old = &qw_entstates.frame[cl.prev_sequence & UPDATE_MASK][i]; - ent = CL_GetEntity (i); - transform_t transform = Entity_Transform (ent); - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, - cl_world.scene->reg); - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - cl_world.scene->reg); - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, - cl_world.scene->reg); - vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, - cl_world.scene->reg); + + ent = CL_GetInvalidEntity (i); forcelink = cl_entity_valid[0][i] != cl_entity_valid[1][i]; cl_entity_valid[1][i] = cl_entity_valid[0][i]; - // if the object wasn't included in the last packet, remove it - if (!cl_entity_valid[0][i]) { - renderer->model = NULL; - animation->pose1 = animation->pose2 = -1; - if (visibility->efrag) { - R_RemoveEfrags (ent); // just became empty + // if the object wasn't included in the last packet, or set + // to invisible, remove it + if (!cl_entity_valid[0][i] + || !new->modelindex + || (cl_deadbodyfilter && is_dead_body (new)) + || (cl_gibfilter && is_gib (new))) { + if (Entity_Valid (ent)) { + Scene_DestroyEntity (cl_world.scene, ent); } continue; } + if (!Entity_Valid (ent)) { + ent = CL_GetEntity (i); + forcelink = true; + } + transform_t transform = Entity_Transform (ent); + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, + ent.reg); + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); + vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, + ent.reg); // spawn light flashes, even ones coming from invisible objects CL_NewDlight (i, new->origin, new->effects, new->glow_size, new->glow_color, cl.time); - // if set to invisible, skip - if (!new->modelindex - || (cl_deadbodyfilter && is_dead_body (new)) - || (cl_gibfilter && is_gib (new))) { - if (visibility->efrag) { - R_RemoveEfrags (ent); - } - continue; - } - if (forcelink) *old = *new; @@ -246,9 +247,6 @@ CL_LinkPacketEntities (void) CL_TransformEntity (ent, new->scale / 16, new->angles, new->origin); if (i != cl.viewentity || chase_active) { - if (visibility->efrag) { - R_RemoveEfrags (ent); - } R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } else { @@ -277,19 +275,11 @@ CL_LinkPacketEntities (void) } if (i != cl.viewentity || chase_active) { vec4f_t org = Transform_GetWorldPosition (transform); - if (visibility->efrag) { - if (!VectorCompare (org, *old_origin)) {//FIXME - R_RemoveEfrags (ent); - R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); - } - } else { + if (!VectorCompare (org, *old_origin)) {//FIXME R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); } } } - if (!visibility->efrag) { - R_AddEfrags (&cl_world.scene->worldmodel->brush, ent); - } // rotate binary objects locally if (renderer->model->flags & EF_ROTATE) { @@ -420,28 +410,23 @@ CL_LinkPlayers (void) for (j = 0, player = cl.players, state = frame->playerstate; j < MAX_CLIENTS; j++, player++, state++) { - ent = CL_GetEntity (j + 1); - visibility_t *visibility = Ent_GetComponent (ent.id, scene_visibility, - cl_world.scene->reg); + ent = CL_GetInvalidEntity (j + 1); + if (state->messagenum != cl.parsecount + || !player->name || !player->name->value[0]) { + // not present this frame + if (Entity_Valid (ent)) { + Scene_DestroyEntity (cl_world.scene, ent); + } + continue; + } + + if (!Entity_Valid (ent)) { + ent = CL_GetEntity (j + 1); + } renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg); animation_t *animation = Ent_GetComponent (ent.id, scene_animation, cl_world.scene->reg); - if (visibility->efrag) - R_RemoveEfrags (ent); - if (Entity_Valid (player->flag_ent)) { - visibility_t *fvis = Ent_GetComponent (player->flag_ent.id, - scene_visibility, - cl_world.scene->reg); - if (fvis->efrag) { - R_RemoveEfrags (player->flag_ent); - } - } - if (state->messagenum != cl.parsecount) - continue; // not present this frame - - if (!player->name || !player->name->value[0]) - continue; // spawn light flashes, even ones coming from invisible objects if (j == cl.playernum) { From 9f6c367fce02ce8c52695b1f4f48ef9100d2cef5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 13 Nov 2022 22:23:56 +0900 Subject: [PATCH 3198/3664] [console] Resurrect console scaling Currently only for gl/glsl/vulkan. However, rather than futzing with con_width and con_height (and trying to guess good values), con_scale (currently an integer) gives consistent pixel scaling regardless of window size. --- include/QF/GL/qf_draw.h | 1 + include/QF/GLSL/qf_draw.h | 1 + include/QF/draw.h | 3 ++ include/QF/plugin/console.h | 1 - include/QF/plugin/vid_render.h | 1 + include/vid_vulkan.h | 1 + libs/client/cl_screen.c | 9 ----- libs/console/client.c | 51 ++++++++++++++++++++---- libs/video/renderer/gl/gl_draw.c | 15 +++++-- libs/video/renderer/glsl/glsl_draw.c | 24 +++++++---- libs/video/renderer/r_draw.c | 14 +++++++ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_vulkan.c | 12 +++++- libs/video/renderer/vulkan/vulkan_draw.c | 5 ++- libs/video/targets/vid_win_vulkan.c | 1 + libs/video/targets/vid_x11_vulkan.c | 1 + 17 files changed, 108 insertions(+), 34 deletions(-) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index ff7b9a30a..ea051f356 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -35,6 +35,7 @@ struct draw_charbuffer_s; void gl_Draw_Init (void); void gl_Draw_Shutdown (void); void gl_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer); +void gl_Draw_SetScale (int scale); void gl_Draw_Character (int x, int y, unsigned ch); void gl_Draw_String (int x, int y, const char *str); void gl_Draw_nString (int x, int y, const char *str, int count); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index 6481cf7aa..10f18d6b9 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -35,6 +35,7 @@ struct draw_charbuffer_s; void glsl_Draw_Init (void); void glsl_Draw_Shutdown (void); void glsl_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer); +void glsl_Draw_SetScale (int scale); void glsl_Draw_Character (int x, int y, unsigned ch); void glsl_Draw_String (int x, int y, const char *str); void glsl_Draw_nString (int x, int y, const char *str, int count); diff --git a/include/QF/draw.h b/include/QF/draw.h index 3c439f190..d31f877ab 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -61,6 +61,9 @@ void Draw_ScrollBuffer (draw_charbuffer_t *buffer, int lines); void Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer); int Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str); +void Draw_SetScale (int scale); +int Draw_MaxScale (void) __attribute__((pure)); + extern byte *draw_chars; /** Initialize the draw stuff. diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index 7307bb4f8..5d4393983 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -52,7 +52,6 @@ typedef struct console_data_s { void (*quit) (void); struct cbuf_s *cbuf; struct view_s *screen_view; - //struct view_s *view; struct view_s *status_view; float lines; int (*exec_line)(void *data, const char *line); diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index a3df2906a..64427fe57 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -88,6 +88,7 @@ typedef void (*capfunc_t) (struct tex_s *screencap, void *data); typedef struct vid_render_funcs_s { void (*init) (void); void (*Draw_CharBuffer) (int x, int y, struct draw_charbuffer_s *buffer); + void (*Draw_SetScale) (int scale); void (*Draw_Character) (int x, int y, unsigned ch); void (*Draw_String) (int x, int y, const char *str); void (*Draw_nString) (int x, int y, const char *str, int count); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 709755538..cd714d093 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -98,6 +98,7 @@ typedef struct vulkan_ctx_s { // size of window int window_width; int window_height; + int twod_scale; //FIXME this is for the parser qfv_output_t output; diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index 3afec5d2f..8f5af2de5 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -165,20 +165,11 @@ static SCR_Func *scr_funcs[] = { scr_funcs_intermission, }; -static void -cl_vidsize_listener (void *data, const viddef_t *vdef) -{ - View_SetLen (cl_screen_view, vdef->width, vdef->height); - View_UpdateHierarchy (cl_screen_view); -} - void CL_Init_Screen (void) { qpic_t *pic; - VID_OnVidResize_AddListener (cl_vidsize_listener, 0); - HUD_Init (); cl_screen_view = View_New (hud_registry, nullview); diff --git a/libs/console/client.c b/libs/console/client.c index 13fecf267..5e1433927 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -70,6 +70,16 @@ static con_buffer_t *con; static float con_cursorspeed = 4; +static int con_scale; +static cvar_t con_scale_cvar = { + .name = "con_scale", + .description = + "Pixel scale factor for the console and all 2D user interface " + "elements", + .default_value = "1", + .flags = CVAR_ARCHIVE, + .value = { .type = &cexpr_int, .value = &con_scale }, +}; static float con_notifytime; static cvar_t con_notifytime_cvar = { .name = "con_notifytime", @@ -807,6 +817,24 @@ exec_line (inputline_t *il) Con_ExecLine (il->line); } +static int win_xlen = -1; +static int win_ylen = -1; + +static void +con_set_size (void) +{ + int xlen = win_xlen / con_scale; + int ylen = win_ylen / con_scale; + if (xlen > 0 && ylen > 0) { + View_SetLen (screen_view, xlen, ylen); + View_UpdateHierarchy (screen_view); + if (con_data.screen_view) { + View_SetLen (*con_data.screen_view, xlen, ylen); + View_UpdateHierarchy (*con_data.screen_view); + } + } +} + // The console view is not a child of the client's screen view, so it won't // get resized automatically when the screen changes size. However, since the // console has to process input events anyway, handling ie_app_window is a @@ -814,15 +842,21 @@ exec_line (inputline_t *il) static void con_app_window (const IE_event_t *event) { - static int old_xlen = -1; - static int old_ylen = -1; - if (old_xlen != event->app_window.xlen - || old_ylen != event->app_window.ylen) { - old_xlen = event->app_window.xlen; - old_ylen = event->app_window.ylen; + if (win_xlen != event->app_window.xlen + || win_ylen != event->app_window.ylen) { + win_xlen = event->app_window.xlen; + win_ylen = event->app_window.ylen; + con_set_size (); + } +} - View_SetLen (screen_view, old_xlen, old_ylen); - View_UpdateHierarchy (screen_view); +static void +con_scale_f (void *data, const cvar_t *cvar) +{ + con_scale = bound (1, con_scale, Draw_MaxScale ()); + Draw_SetScale (con_scale); + if (con_initialized) { + con_set_size (); } } @@ -1001,6 +1035,7 @@ C_Init (void) Cvar_Register (&con_notifytime_cvar, 0, 0); + Cvar_Register (&con_scale_cvar, con_scale_f, 0); Cvar_Register (&con_alpha_cvar, 0, 0); Cvar_Register (&con_size_cvar, 0, 0); Cvar_Register (&con_speed_cvar, 0, 0); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 79115b819..bd7d3b38d 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -115,6 +115,7 @@ static int numcachepics; static byte menuplyr_pixels[4096]; +static int gl_2d_scale = 1; static void Draw_InitText (void) @@ -836,7 +837,7 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) if (gl_constretch) { ofs = 0; } else - ofs = (vid.height - lines) / (float) vid.height; + ofs = (vid.height - gl_2d_scale * lines) / (float) vid.height; color_0_8[3] = alpha; qfglColor4ubv (color_0_8); @@ -851,9 +852,9 @@ gl_Draw_ConsoleBackground (int lines, byte alpha) qfglTexCoord2f (0, 0 + ofs); qfglVertex2f (0, 0); qfglTexCoord2f (1, 0 + ofs); - qfglVertex2f (vid.width, 0); + qfglVertex2f (vid.width / gl_2d_scale, 0); qfglTexCoord2f (1, 1); - qfglVertex2f (vid.width, lines); + qfglVertex2f (vid.width / gl_2d_scale, lines); qfglTexCoord2f (0, 1); qfglVertex2f (0, lines); qfglEnd (); @@ -995,7 +996,13 @@ GL_Set2D (void) void GL_Set2DScaled (void) { - set_2d (vid.width, vid.height); + set_2d (vid.width / gl_2d_scale, vid.height / gl_2d_scale); +} + +void +gl_Draw_SetScale (int scale) +{ + gl_2d_scale = scale; } void diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 835b93948..ab4067746 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -112,6 +112,7 @@ static qpic_t *white_pic; static qpic_t *backtile_pic; static hashtab_t *pic_cache; static int glsl_conback_texnum; +static int glsl_2d_scale = 1; static cvar_t glsl_conback_texnum_cvar = { .name = "glsl_conback_texnum", .description = @@ -647,15 +648,16 @@ glsl_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, void glsl_Draw_ConsoleBackground (int lines, byte alpha) { - float ofs = (vid.height - lines) / (float) vid.height; + int s = glsl_2d_scale; + float ofs = (vid.height - s * lines) / (float) vid.height; quat_t color = {1, 1, 1, bound (0, alpha, 255) / 255.0}; drawvert_t verts[] = { - {{ 0, 0, 0, ofs}}, - {{vid.width, 0, 1, ofs}}, - {{vid.width, lines, 1, 1}}, - {{ 0, 0, 0, ofs}}, - {{vid.width, lines, 1, 1}}, - {{ 0, lines, 0, 1}}, + {{ 0, 0, 0, ofs}}, + {{vid.width / s, 0, 1, ofs}}, + {{vid.width / s, lines, 1, 1}}, + {{ 0, 0, 0, ofs}}, + {{vid.width / s, lines, 1, 1}}, + {{ 0, lines, 0, 1}}, }; GLSL_FlushText (); // Flush text that should be rendered before the console @@ -828,7 +830,13 @@ GLSL_Set2D (void) void GLSL_Set2DScaled (void) { - set_2d (vid.width, vid.height); + set_2d (vid.width / glsl_2d_scale, vid.height / glsl_2d_scale); +} + +void +glsl_Draw_SetScale (int scale) +{ + glsl_2d_scale = scale; } void diff --git a/libs/video/renderer/r_draw.c b/libs/video/renderer/r_draw.c index 5a18b99b0..a86a61aa5 100644 --- a/libs/video/renderer/r_draw.c +++ b/libs/video/renderer/r_draw.c @@ -141,3 +141,17 @@ Draw_PrintBuffer (draw_charbuffer_t *buffer, const char *str) } return lines; } + +void +Draw_SetScale (int scale) +{ + if (r_funcs->Draw_SetScale) { + r_funcs->Draw_SetScale (scale); + } +} + +int +Draw_MaxScale (void) +{ + return r_funcs->Draw_SetScale ? 20 : 1; +} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 7ec796c66..6b4d50f12 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -502,6 +502,7 @@ vid_render_funcs_t gl_vid_render_funcs = { .init = gl_vid_render_init, .Draw_CharBuffer = gl_Draw_CharBuffer, + .Draw_SetScale = gl_Draw_SetScale, .Draw_Character = gl_Draw_Character, .Draw_String = gl_Draw_String, .Draw_nString = gl_Draw_nString, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 5c95998bd..87608ab40 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -446,6 +446,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { .init = glsl_vid_render_init, .Draw_CharBuffer = glsl_Draw_CharBuffer, + .Draw_SetScale = glsl_Draw_SetScale, .Draw_Character = glsl_Draw_Character, .Draw_String = glsl_Draw_String, .Draw_nString = glsl_Draw_nString, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 733ada82d..2683a48e4 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -145,6 +145,12 @@ vulkan_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer) Vulkan_Draw_CharBuffer (x, y, buffer, vulkan_ctx); } +static void +vulkan_Draw_SetScale (int scale) +{ + vulkan_ctx->twod_scale = max (1, scale); +} + static void vulkan_Draw_Character (int x, int y, unsigned ch) { @@ -360,11 +366,12 @@ vulkan_set_2d (int scaled) //FIXME this should not be done every frame __auto_type mctx = vulkan_ctx->matrix_context; __auto_type mat = &mctx->matrices; + int scale = vulkan_ctx->twod_scale; float left = -0.5; float top = -0.5; - float right = left + vid.width; //FIXME vid - float bottom = top + vid.height; + float right = left + vid.width / scale; + float bottom = top + vid.height / scale; QFV_Orthographic (mat->Projection2d, left, right, top, bottom, 0, 99999); mctx->dirty = mctx->frames.size; @@ -780,6 +787,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { .init = vulkan_vid_render_init, .Draw_CharBuffer = vulkan_Draw_CharBuffer, + .Draw_SetScale = vulkan_Draw_SetScale, .Draw_Character = vulkan_Draw_Character, .Draw_String = vulkan_Draw_String, .Draw_nString = vulkan_Draw_nString, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 6b65907f8..7eb2a9156 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -897,10 +897,11 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) quat_t color = { a, a, a, a}; qpic_t *cpic; cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx); - float frac = (vid.height - lines) / (float) vid.height; + int s = ctx->twod_scale; + float frac = (vid.height - s * lines) / (float) vid.height; int ofs = frac * cpic->height; subpic_t *subpic = *(subpic_t **) cpic->data; - draw_pic (0, 0, vid.width, lines, subpic, + draw_pic (0, 0, vid.width / s, lines, subpic, 0, ofs, cpic->width, cpic->height - ofs, color, &frame->quad_verts); } diff --git a/libs/video/targets/vid_win_vulkan.c b/libs/video/targets/vid_win_vulkan.c index 2a8618073..5ae2c4d61 100644 --- a/libs/video/targets/vid_win_vulkan.c +++ b/libs/video/targets/vid_win_vulkan.c @@ -185,6 +185,7 @@ Win_Vulkan_Context (void) ctx->create_surface = win_vulkan_create_surface; ctx->required_extensions = required_extensions; ctx->va_ctx = va_create_context (4); + ctx->twod_scale = 1; return ctx; } diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index c8aa494ea..66f15073a 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -224,6 +224,7 @@ X11_Vulkan_Context (void) ctx->create_surface = x11_vulkan_create_surface; ctx->required_extensions = required_extensions; ctx->va_ctx = va_create_context (32); + ctx->twod_scale = 1; return ctx; } From 053c2c47db0932f8b6936dd2d73ed87257fa3fec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Nov 2022 11:35:26 +0900 Subject: [PATCH 3199/3664] [vulkan] Double alias top/bottom color values The bright end of the color map is actually twice the palette value, but I didn't understand this when I came up with the shirt/pants color scheme for vulkan. However, the skin texture can store only 0..1, so the mapping to 0..2 needs to be done in the shader. It looks like it works at least better: the gold key at the end of demo1 doesn't look as bleh, though I do get some weird colors still on ogres etc. --- libs/video/renderer/vulkan/shader/alias_gbuf.frag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index 50bc8f4b7..de554181d 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -27,8 +27,8 @@ main (void) int i; vec3 light = vec3 (0); c = texture (Skin, vec3 (st, 0)) * base_color; - c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA); - c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB); + c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA) * 2; + c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB) * 2; e = texture (Skin, vec3 (st, 3)); frag_color = c; From 7c53a68ad70ce7252b3104bf82cb38858a590883 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Nov 2022 12:43:33 +0900 Subject: [PATCH 3200/3664] [scene] Move efrag code from renderer to scene While culling is very much part of rendering, it's more scene related than renderer related. Fixes the transform test failing to link. --- libs/scene/Makemodule.am | 1 + libs/{video/renderer/r_efrag.c => scene/efrag.c} | 0 libs/video/renderer/Makemodule.am | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename libs/{video/renderer/r_efrag.c => scene/efrag.c} (100%) diff --git a/libs/scene/Makemodule.am b/libs/scene/Makemodule.am index 4dffff068..e614934c1 100644 --- a/libs/scene/Makemodule.am +++ b/libs/scene/Makemodule.am @@ -12,6 +12,7 @@ libs_scene_libQFscene_la_LIBADD= $(scene_deps) libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps) libs_scene_libQFscene_la_SOURCES= \ libs/scene/camera.c \ + libs/scene/efrag.c \ libs/scene/entity.c \ libs/scene/light.c \ libs/scene/scene.c \ diff --git a/libs/video/renderer/r_efrag.c b/libs/scene/efrag.c similarity index 100% rename from libs/video/renderer/r_efrag.c rename to libs/scene/efrag.c diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index dc360ec12..bec2f52d3 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -52,7 +52,6 @@ libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_bsp.c \ libs/video/renderer/r_cvar.c \ libs/video/renderer/r_draw.c \ - libs/video/renderer/r_efrag.c \ libs/video/renderer/r_fog.c \ libs/video/renderer/r_font.c \ libs/video/renderer/r_graph.c \ From 8fa6167a57b942ef5826874d896ac45a1a5cf8b5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 14 Nov 2022 19:39:55 +0900 Subject: [PATCH 3201/3664] [vid] Add a function to set the palette and colormap Mostly for qwaq as it uses the default VGA palette but I need to do some testing with the quake palette. --- include/QF/vid.h | 1 + include/vid_internal.h | 1 + libs/video/targets/vid.c | 18 ++++++++++++++++-- libs/video/targets/vid_win.c | 22 +++++++++++++++------- libs/video/targets/vid_x11.c | 22 +++++++++++++++------- ruamoko/qwaq/builtins/graphics.c | 9 +++++++++ 6 files changed, 57 insertions(+), 16 deletions(-) diff --git a/include/QF/vid.h b/include/QF/vid.h index 6987ebfc8..2f78d7945 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -71,6 +71,7 @@ void VID_Init_Cvars (void); // the palette data will go away after the call, so it must be copied off if // the video driver will need it again void VID_Init (byte *palette, byte *colormap); +void VID_SetPalette (byte *palette, byte *colormap); void VID_SetCaption (const char *text); void VID_ClearMemory (void); diff --git a/include/vid_internal.h b/include/vid_internal.h index e79fa9a9b..967c4eacc 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -6,6 +6,7 @@ typedef struct vid_system_s { void (*init) (byte *palette, byte *colormap); + void (*set_palette) (byte *palette, byte *colormap); void (*init_cvars) (void); void (*update_fullscreen) (int fullscreen); } vid_system_t; diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 51c235440..77cc55f30 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -246,7 +246,11 @@ VID_InitGamma (const byte *pal) { int i; double gamma = 1.0; + static int cvar_initialized; + free (viddef.gammatable); + free (viddef.palette); + free (viddef.palette32); viddef.gammatable = malloc (256); viddef.basepal = pal; viddef.palette = malloc (256 * 3); @@ -256,9 +260,13 @@ VID_InitGamma (const byte *pal) } gamma = bound (0.1, gamma, 9.9); - Cvar_Register (&vid_gamma_cvar, vid_gamma_f, 0); + if (!cvar_initialized) { + cvar_initialized = 1; + Cvar_Register (&vid_gamma_cvar, vid_gamma_f, 0); + } - VID_BuildGammaTable (vid_gamma); + //VID_BuildGammaTable (vid_gamma); + VID_UpdateGamma (); if (viddef.onPaletteChanged) { LISTENER_INVOKE (viddef.onPaletteChanged, &viddef); @@ -315,6 +323,12 @@ VID_Init (byte *palette, byte *colormap) vid_system.init (palette, colormap); } +VISIBLE void +VID_SetPalette (byte *palette, byte *colormap) +{ + vid_system.set_palette (palette, colormap); +} + static void vid_fullscreen_f (void *data, const cvar_t *var) { diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 124a971c3..6b8de7445 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -117,6 +117,19 @@ VID_shutdown (void *data) Win_CloseDisplay (); } +static v oid +Win_VID_SetPalette (byte *palette, byte *colormap) +{ + viddef.colormap8 = colormap; + viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; + if (vid_internal.set_colormap) { + vid_internal.set_colormap (vid_internal.data, colormap); + } + + VID_InitGamma (palette); + viddef.vid_internal->set_palette (win_sw_context, palette); +} + static void Win_VID_Init (byte *palette, byte *colormap) { @@ -131,11 +144,6 @@ Win_VID_Init (byte *palette, byte *colormap) R_LoadModule (&vid_internal); viddef.numpages = 1; - viddef.colormap8 = colormap; - viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; - if (vid_internal.set_colormap) { - vid_internal.set_colormap (vid_internal.data, colormap); - } VID_GetWindowSize (640, 480); Win_OpenDisplay (); @@ -144,8 +152,7 @@ Win_VID_Init (byte *palette, byte *colormap) Win_CreateWindow (viddef.width, viddef.height); vid_internal.create_context (win_sw_context); - VID_InitGamma (palette); - viddef.vid_internal->set_palette (win_sw_context, palette); + Win_VID_SetPalette (palette, colormap); Sys_MaskPrintf (SYS_vid, "Video mode %dx%d initialized.\n", viddef.width, viddef.height); @@ -166,6 +173,7 @@ Win_VID_Init_Cvars (void) vid_system_t vid_system = { .init = Win_VID_Init, + .set_palette = Win_VID_SetPalette, .init_cvars = Win_VID_Init_Cvars, }; diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index e1b674e20..566953940 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -89,6 +89,19 @@ VID_shutdown (void *data) X11_CloseDisplay (); } +static void +X11_VID_SetPalette (byte *palette, byte *colormap) +{ + viddef.colormap8 = colormap; + viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; + if (vid_internal.set_colormap) { + vid_internal.set_colormap (vid_internal.data, colormap); + } + + VID_InitGamma (palette); + vid_internal.set_palette (vid_internal.data, viddef.palette); +} + /* Set up color translation tables and the window. Takes a 256-color 8-bit palette. Palette data will go away after the call, so copy it if you'll @@ -108,11 +121,6 @@ X11_VID_Init (byte *palette, byte *colormap) R_LoadModule (&vid_internal); viddef.numpages = 2; - viddef.colormap8 = colormap; - viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; - if (vid_internal.set_colormap) { - vid_internal.set_colormap (vid_internal.data, colormap); - } srandom (getpid ()); @@ -124,8 +132,7 @@ X11_VID_Init (byte *palette, byte *colormap) X11_CreateNullCursor (); // hide mouse pointer vid_internal.create_context (vid_internal.data); - VID_InitGamma (palette); - vid_internal.set_palette (vid_internal.data, viddef.palette); + X11_VID_SetPalette (palette, colormap); Sys_MaskPrintf (SYS_vid, "Video mode %dx%d initialized.\n", viddef.width, viddef.height); @@ -149,6 +156,7 @@ vid_system_t vid_system = { .init = X11_VID_Init, .init_cvars = X11_VID_Init_Cvars, .update_fullscreen = X11_UpdateFullscreen, + .set_palette = X11_VID_SetPalette, }; #if 0 diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 7aa6d3037..a241e2826 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -124,6 +124,14 @@ bi_refresh_2d (progs_t *pr, void *_res) qc2d = P_FUNCTION (pr, 0); } +static void +bi_setpalette (progs_t *pr, void *_res) +{ + byte *palette = (byte *) P_GPOINTER (pr, 0); + byte *colormap = (byte *) P_GPOINTER (pr, 1); + VID_SetPalette (palette, colormap); +} + static void bi_shutdown (progs_t *pr, void *_res) { @@ -136,6 +144,7 @@ static builtin_t builtins[] = { bi(newscene, -1, 1, p(long)), bi(refresh, -1, 0), bi(refresh_2d, -1, 1, p(func)), + bi(setpalette, -1, 2, p(ptr), p(ptr)), bi(shutdown, -1, 0), {0} }; From 251e47f4d6783e9976739527f835be5a5d946e5e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Nov 2022 09:18:26 +0900 Subject: [PATCH 3202/3664] [vulkan] Add a function to update texture contents It works on only one layer and one mip, and assumes the provided texture data is compatible with the image, but does support sub-image updates (x, y location as parameters, width and height in the texture data). --- include/QF/Vulkan/qf_texture.h | 2 + libs/video/renderer/vulkan/vulkan_texture.c | 49 +++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index 408118a4f..0253365b8 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -26,6 +26,8 @@ qfv_tex_t *Vulkan_LoadEnvMap (struct vulkan_ctx_s *ctx, tex_t *tex, qfv_tex_t *Vulkan_LoadEnvSides (struct vulkan_ctx_s *ctx, tex_t **tex, const char *name); VkImageView Vulkan_TexImageView (qfv_tex_t *tex) __attribute__((pure)); +void Vulkan_UpdateTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex, tex_t *src, + int x, int y, int layer, int mip); void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex); void Vulkan_Texture_Init (struct vulkan_ctx_s *ctx); void Vulkan_Texture_Shutdown (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 378ab5013..7a8c6a3ea 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -410,6 +410,55 @@ Vulkan_TexImageView (qfv_tex_t *tex) return tex->view; } +void +Vulkan_UpdateTex (vulkan_ctx_t *ctx, qfv_tex_t *tex, tex_t *src, + int x, int y, int layer, int mip) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + int bpp; + VkFormat format; + if (!tex_format (src, &format, &bpp)) { + return; + } + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_ShaderReadOnly_to_TransferDst]; + ib.barrier.image = tex->image; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + + VkBufferImageCopy copy = { + .bufferOffset = stage_tex_data (packet, src, bpp), + .imageSubresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = mip, + .baseArrayLayer = layer, + .layerCount = 1, + }, + .imageOffset = { .x = x, .y = y, .z = 0 }, + .imageExtent = { + .width = src->width, + .height = src->height, + .depth = 1, + }, + }; + dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, + tex->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©); + ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; + ib.barrier.image = tex->image; + ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + QFV_PacketSubmit (packet); +} + void Vulkan_UnloadTex (vulkan_ctx_t *ctx, qfv_tex_t *tex) { From 2e21ca4b9a6e07f977c7a36fa584f34c403093a5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Nov 2022 09:26:17 +0900 Subject: [PATCH 3203/3664] [vulkan] Upload palette as a 16x16 image It turns out my approach to alias skin coloring just doesn't work for the quake data due to the color curves not having a linear relationship, especially the bottom colors. --- include/QF/Makemodule.am | 1 + include/QF/Vulkan/qf_palette.h | 49 +++++++++++ include/vid_vulkan.h | 1 + libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vid_render_vulkan.c | 9 +- libs/video/renderer/vulkan/qfpipeline.plist | 17 ++++ libs/video/renderer/vulkan/vulkan_palette.c | 96 +++++++++++++++++++++ 7 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 include/QF/Vulkan/qf_palette.h create mode 100644 libs/video/renderer/vulkan/vulkan_palette.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 36ddd9f6f..0512d7a13 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -199,6 +199,7 @@ include_qf_vulkan = \ include/QF/Vulkan/qf_main.h \ include/QF/Vulkan/qf_matrices.h \ include/QF/Vulkan/qf_model.h \ + include/QF/Vulkan/qf_palette.h \ include/QF/Vulkan/qf_particles.h \ include/QF/Vulkan/qf_renderpass.h \ include/QF/Vulkan/qf_scene.h \ diff --git a/include/QF/Vulkan/qf_palette.h b/include/QF/Vulkan/qf_palette.h new file mode 100644 index 000000000..a6cd01387 --- /dev/null +++ b/include/QF/Vulkan/qf_palette.h @@ -0,0 +1,49 @@ +/* + qf_palette.h + + Vulkan matrix "pass" + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/12/8 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_palette_h +#define __QF_Vulkan_qf_palette_h + +#include "QF/darray.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/image.h" + +typedef struct palettectx_s { + struct qfv_tex_s *palette; + VkSampler sampler; +} palettectx_t; + +struct vulkan_ctx_s; + +void Vulkan_Palette_Update (struct vulkan_ctx_s *ctx, const byte *palette); +void Vulkan_Palette_Init (struct vulkan_ctx_s *ctx, const byte *palette); +void Vulkan_Palette_Shutdown (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_palette_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index cd714d093..b3ecf0a60 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -70,6 +70,7 @@ typedef struct vulkan_ctx_s { struct bspctx_s *bsp_context; struct iqmctx_s *iqm_context; struct scenectx_s *scene_context; + struct palettectx_s *palette_context; struct particlectx_s *particle_context; struct spritectx_s *sprite_context; struct drawctx_s *draw_context; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index bec2f52d3..0eea5d10b 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -243,6 +243,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_lighting.c \ libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ + libs/video/renderer/vulkan/vulkan_palette.c \ libs/video/renderer/vulkan/vulkan_particles.c \ libs/video/renderer/vulkan/vulkan_renderpass.c \ libs/video/renderer/vulkan/vulkan_scene.c \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 2683a48e4..4a614498a 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -50,6 +50,7 @@ #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" @@ -89,6 +90,7 @@ vulkan_R_Init (void) Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx); Vulkan_Texture_Init (vulkan_ctx); + Vulkan_Palette_Init (vulkan_ctx, vid.palette); Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); @@ -669,9 +671,9 @@ vulkan_Skin_InitTranslations (void) static void set_palette (void *data, const byte *palette) { - //FIXME really don't want this here: need an application domain - //so Quake can be separated from QuakeForge (ie, Quake itself becomes - //an app using the QuakeForge engine) + if (vulkan_ctx->palette_context) { + Vulkan_Palette_Update (vulkan_ctx, palette); + } } static void @@ -774,6 +776,7 @@ vulkan_vid_render_shutdown (void) Vulkan_Scene_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx); + Vulkan_Palette_Shutdown (vulkan_ctx); Vulkan_Texture_Shutdown (vulkan_ctx); Vulkan_DestroyRenderPasses (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 1046818e0..02a54335c 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -23,6 +23,23 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; + palette_sampler = { + magFilter = nearest; + minFilter = nearest; + mipmapMode = nearest; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 4; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; quakebsp_sampler = { magFilter = linear; minFilter = linear; diff --git a/libs/video/renderer/vulkan/vulkan_palette.c b/libs/video/renderer/vulkan/vulkan_palette.c new file mode 100644 index 000000000..ac1c17b59 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_palette.c @@ -0,0 +1,96 @@ +/* + vulkan_palette.c + + Vulkan palette image + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#ifdef HAVE_MATH_H +# include +#endif + +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/qf_palette.h" +#include "QF/Vulkan/qf_texture.h" + +#include "vid_vulkan.h" + +void +Vulkan_Palette_Update (vulkan_ctx_t *ctx, const byte *palette) +{ + palettectx_t *pctx = ctx->palette_context; + tex_t tex = { + .width = 16, + .height = 16, + .format = tex_rgb, + .loaded = 1, + .data = (byte *) palette, + }; + Vulkan_UpdateTex (ctx, pctx->palette, &tex, 0, 0, 0, 0); +} + +void +Vulkan_Palette_Init (vulkan_ctx_t *ctx, const byte *palette) +{ + qfvPushDebug (ctx, "palette init"); + + palettectx_t *pctx = calloc (1, sizeof (palettectx_t)); + ctx->palette_context = pctx; + + pctx->sampler = Vulkan_CreateSampler (ctx, "palette_sampler"); + tex_t tex = { + .width = 16, + .height = 16, + .format = tex_rgb, + .loaded = 1, + .data = (byte *) palette, + }; + pctx->palette = Vulkan_LoadTex (ctx, &tex, 0, "palette"); + + qfvPopDebug (ctx); +} + +void +Vulkan_Palette_Shutdown (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "palette shutdown"); + + __auto_type pctx = ctx->palette_context; + + Vulkan_UnloadTex (ctx, pctx->palette); + free (pctx); + + qfvPopDebug (ctx); +} From 4d7f72948d45c127c2e97f72ea1e6ac3a41976e4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Nov 2022 09:28:34 +0900 Subject: [PATCH 3204/3664] [vulkan] Correct alias g-buffer push-constants For whatever reason, I had added an extra 4 bytes to the fragment shader's push-constants. It took me a while to figure out why renderdoc wouldn't stop complaining about me not writing enough data. --- libs/video/renderer/vulkan/qfpipeline.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 02a54335c..aaa8f3f8b 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -436,7 +436,7 @@ { stageFlags = fragment; offset = 68; - size = "3 * 4 + 2 * 4 * 4 + 4"; + size = "3 * 4 + 2 * 4 * 4"; }, ); }; From 668f7f2cd2909d5f9601124c880fd8e2fad5a88b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Nov 2022 11:47:28 +0900 Subject: [PATCH 3205/3664] [vulkan] Use palette lookups for top/bottom colors As the RGB curves for many of the color rows are not linearly related, my idea of scaling the brightest color in the row just didn't work. Using a masked palette lookup works much better as it allows any curves. Also, because the palette is uploaded as a grid and the coordinates are calculated on the CPU, the system is extendable beyond 8-bit palettes. This isn't quite complete as the top and bottom colors are still in separate layers but their indices and masks can fit in just one, but this requires reworking the texture setup (for another commit). --- include/QF/Vulkan/qf_alias.h | 3 +-- include/QF/Vulkan/qf_palette.h | 2 ++ libs/models/alias/vulkan_model_alias.c | 25 ++++++++++++++++--- libs/video/renderer/vulkan/qfpipeline.plist | 2 +- .../renderer/vulkan/shader/alias_gbuf.frag | 15 +++++++---- libs/video/renderer/vulkan/vulkan_alias.c | 21 +++++++--------- libs/video/renderer/vulkan/vulkan_palette.c | 10 ++++++++ 7 files changed, 54 insertions(+), 24 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index b5fad64e0..5c64d00b8 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -58,8 +58,7 @@ typedef struct qfv_alias_skin_s { VkDeviceMemory memory; VkImage image; VkImageView view; - byte colora[4]; - byte colorb[4]; + byte colors[4]; VkDescriptorSet descriptor; } qfv_alias_skin_t; diff --git a/include/QF/Vulkan/qf_palette.h b/include/QF/Vulkan/qf_palette.h index a6cd01387..c1c1a4b33 100644 --- a/include/QF/Vulkan/qf_palette.h +++ b/include/QF/Vulkan/qf_palette.h @@ -38,6 +38,7 @@ typedef struct palettectx_s { struct qfv_tex_s *palette; VkSampler sampler; + VkDescriptorSet descriptor; } palettectx_t; struct vulkan_ctx_s; @@ -45,5 +46,6 @@ struct vulkan_ctx_s; void Vulkan_Palette_Update (struct vulkan_ctx_s *ctx, const byte *palette); void Vulkan_Palette_Init (struct vulkan_ctx_s *ctx, const byte *palette); void Vulkan_Palette_Shutdown (struct vulkan_ctx_s *ctx); +VkDescriptorSet Vulkan_Palette_Descriptor (struct vulkan_ctx_s *ctx) __attribute__((pure)); #endif//__QF_Vulkan_qf_palette_h diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 89cadd84f..44e4e43cf 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -125,8 +125,7 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, int w, h; skin = Hunk_Alloc (0, sizeof (qfv_alias_skin_t)); - QuatCopy (vid.palette32 + (TOP_RANGE + 15) * 4, skin->colora); - QuatCopy (vid.palette32 + (BOTTOM_RANGE + 15) * 4, skin->colorb); + QuatSet (TOP_RANGE + 7, BOTTOM_RANGE + 7, 0, 0, skin->colors); skindesc->skin = (byte *) skin - (byte *) header; //FIXME move all skins into arrays(?) w = header->mdl.skinwidth; @@ -175,13 +174,31 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, skinsize); Mod_ClearFullbright (tskin, tskin, skinsize); + static byte map_palette[] = { + 0x08, 0x00, 0x00, + 0x18, 0xff, 0x00, + 0x28, 0xff, 0x00, + 0x38, 0xff, 0x00, + 0x48, 0xff, 0x00, + 0x58, 0xff, 0x00, + 0x68, 0xff, 0x00, + 0x78, 0xff, 0x00, + 0x88, 0xff, 0x00, + 0x98, 0xff, 0x00, + 0xa8, 0xff, 0x00, + 0xb8, 0xff, 0x00, + 0xc8, 0xff, 0x00, + 0xd8, 0xff, 0x00, + 0xe8, 0xff, 0x00, + 0xf8, 0xff, 0x00, + }; Skin_CalcTopColors (tskin + skinsize, tskin, skinsize); - Vulkan_ExpandPalette (cola_data, tskin + skinsize, vid.palette, 1, + Vulkan_ExpandPalette (cola_data, tskin + skinsize, map_palette, 1, skinsize); Skin_ClearTopColors (tskin, tskin, skinsize); Skin_CalcBottomColors (tskin + skinsize, tskin, skinsize); - Vulkan_ExpandPalette (colb_data, tskin + skinsize, vid.palette, 1, + Vulkan_ExpandPalette (colb_data, tskin + skinsize, map_palette, 1, skinsize); Skin_ClearBottomColors (tskin, tskin, skinsize); diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index aaa8f3f8b..43e3bf646 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -426,7 +426,7 @@ ); }; alias_layout = { - setLayouts = (matrix_set, texture_set); + setLayouts = (matrix_set, texture_set, texture_set); pushConstantRanges = ( { stageFlags = vertex; diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index de554181d..c56f483e2 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -1,11 +1,11 @@ #version 450 -layout (set = 1, binding = 0) uniform sampler2DArray Skin; +layout (set = 1, binding = 0) uniform sampler2D Palette; +layout (set = 2, binding = 0) uniform sampler2DArray Skin; layout (push_constant) uniform PushConstants { layout (offset = 68) - uint colorA; - uint colorB; + uint colors; vec4 base_color; vec4 fog; }; @@ -26,9 +26,14 @@ main (void) vec4 e; int i; vec3 light = vec3 (0); + vec4 rows = unpackUnorm4x8(colors); + vec2 cols = vec2 (texture (Skin, vec3 (st, 1)).r, + texture (Skin, vec3 (st, 2)).r); + vec2 mask = vec2 (texture (Skin, vec3 (st, 1)).g, + texture (Skin, vec3 (st, 2)).g); c = texture (Skin, vec3 (st, 0)) * base_color; - c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA) * 2; - c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB) * 2; + c += texture (Palette, vec2 (cols.x, rows.x)) * mask.x; + c += texture (Palette, vec2 (cols.y, rows.y)) * mask.y; e = texture (Skin, vec3 (st, 3)); frag_color = c; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 0a5a7ce44..8d3630be7 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -42,6 +42,7 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/debug.h" @@ -54,8 +55,7 @@ typedef struct { mat4f_t mat; float blend; - byte colorA[4]; - byte colorB[4]; + byte colors[4]; vec4f_t base_color; vec4f_t fog; } alias_push_constants_t; @@ -108,7 +108,7 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, skin->descriptor, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, 1, 1, sets, 0, 0); + actx->layout, 2, 1, sets, 0, 0); } dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); @@ -144,11 +144,8 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) field_offset (alias_push_constants_t, blend), sizeof (float), &constants.blend }, { VK_SHADER_STAGE_FRAGMENT_BIT, - field_offset (alias_push_constants_t, colorA), - sizeof (constants.colorA), constants.colorA }, - { VK_SHADER_STAGE_FRAGMENT_BIT, - field_offset (alias_push_constants_t, colorB), - sizeof (constants.colorB), constants.colorB }, + field_offset (alias_push_constants_t, colors), + sizeof (constants.colors), constants.colors }, { VK_SHADER_STAGE_FRAGMENT_BIT, field_offset (alias_push_constants_t, base_color), sizeof (constants.base_color), &constants.base_color }, @@ -165,8 +162,7 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin); } QuatCopy (renderer->colormod, constants.base_color); - QuatCopy (skin->colora, constants.colorA); - QuatCopy (skin->colorb, constants.colorB); + QuatCopy (skin->colors, constants.colors); QuatZero (constants.fog); emit_commands (aframe->cmdSet.a[QFV_aliasDepth], @@ -174,7 +170,7 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) 0, 2, push_constants, hdr, rFrame, ent); emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], animation->pose1, animation->pose2, - skin, 6, push_constants, hdr, rFrame, ent); + skin, 5, push_constants, hdr, rFrame, ent); } static void @@ -210,9 +206,10 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + Vulkan_Palette_Descriptor (ctx), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, 0, 1, sets, 0, 0); + actx->layout, 0, 2, sets, 0, 0); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); diff --git a/libs/video/renderer/vulkan/vulkan_palette.c b/libs/video/renderer/vulkan/vulkan_palette.c index ac1c17b59..0b7ce791a 100644 --- a/libs/video/renderer/vulkan/vulkan_palette.c +++ b/libs/video/renderer/vulkan/vulkan_palette.c @@ -78,6 +78,9 @@ Vulkan_Palette_Init (vulkan_ctx_t *ctx, const byte *palette) .data = (byte *) palette, }; pctx->palette = Vulkan_LoadTex (ctx, &tex, 0, "palette"); + pctx->descriptor = Vulkan_CreateCombinedImageSampler (ctx, + pctx->palette->view, + pctx->sampler); qfvPopDebug (ctx); } @@ -94,3 +97,10 @@ Vulkan_Palette_Shutdown (vulkan_ctx_t *ctx) qfvPopDebug (ctx); } + +VkDescriptorSet +Vulkan_Palette_Descriptor (struct vulkan_ctx_s *ctx) +{ + __auto_type pctx = ctx->palette_context; + return pctx->descriptor; +} From a28488d2e1c870e85ef1f730879e732e64b928bf Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Nov 2022 13:09:41 +0900 Subject: [PATCH 3206/3664] [vulkan] Move both alias color maps into the one layer This cuts down on the memory requirements for skins by 25%, and simplifies the shader a bit more, too. While at it, I made alias skins nominally compatible with bsp textures: layer 0 is color, 1 is emissive, and 2 is the color map (emissive was on 3). --- include/mod_internal.h | 6 ++- libs/models/alias/vulkan_model_alias.c | 42 ++++------------ libs/models/skin.c | 50 ++++++++++++++++--- .../renderer/vulkan/shader/alias_gbuf.frag | 15 ++---- 4 files changed, 64 insertions(+), 49 deletions(-) diff --git a/include/mod_internal.h b/include/mod_internal.h index a135dff21..b809426fd 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -109,8 +109,10 @@ void Skin_Free (skin_t *skin); skin_t *Skin_SetColormap (skin_t *skin, int cmap); skin_t *Skin_SetSkin (skin_t *skin, int cmap, const char *skinname); void Skin_SetTranslation (int cmap, int top, int bottom); -int Skin_CalcTopColors (byte *out, const byte *in, size_t pixels); -int Skin_CalcBottomColors (byte *out, const byte *in, size_t pixels); +int Skin_CalcTopColors (byte *out, const byte *in, size_t pixels, int stride); +int Skin_CalcTopMask (byte *out, const byte *in, size_t pixels, int stride); +int Skin_CalcBottomColors(byte *out, const byte *in, size_t pixels, int stride); +int Skin_CalcBottomMask (byte *out, const byte *in, size_t pixels, int stride); int Skin_ClearTopColors (byte *out, const byte *in, size_t pixels); int Skin_ClearBottomColors (byte *out, const byte *in, size_t pixels); diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 44e4e43cf..42c0945af 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -111,6 +111,8 @@ vulkan_alias_clear (model_t *m, void *data) } } +#define SKIN_LAYERS 3 + static void * Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, int snum, int gnum, qboolean group, @@ -138,7 +140,7 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, VkExtent3D extent = { w, h, 1 }; skin->image = QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, extent, - mipLevels, 4, VK_SAMPLE_COUNT_1_BIT, + mipLevels, 3, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); @@ -161,45 +163,23 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, alias_ctx->mod->name, snum, gnum)); qfv_stagebuf_t *stage = QFV_CreateStagingBuffer (device, "alias stage", - 4 * skinsize * 4, + SKIN_LAYERS * skinsize * 4, ctx->cmdpool); qfv_packet_t *packet = QFV_PacketAcquire (stage); byte *base_data = QFV_PacketExtend (packet, skinsize * 4); - byte *cola_data = QFV_PacketExtend (packet, skinsize * 4); - byte *colb_data = QFV_PacketExtend (packet, skinsize * 4); byte *glow_data = QFV_PacketExtend (packet, skinsize * 4); + byte *cmap_data = QFV_PacketExtend (packet, skinsize * 4); Mod_CalcFullbright (tskin + skinsize, tskin, skinsize); Vulkan_ExpandPalette (glow_data, tskin + skinsize, vid.palette, 1, skinsize); Mod_ClearFullbright (tskin, tskin, skinsize); - static byte map_palette[] = { - 0x08, 0x00, 0x00, - 0x18, 0xff, 0x00, - 0x28, 0xff, 0x00, - 0x38, 0xff, 0x00, - 0x48, 0xff, 0x00, - 0x58, 0xff, 0x00, - 0x68, 0xff, 0x00, - 0x78, 0xff, 0x00, - 0x88, 0xff, 0x00, - 0x98, 0xff, 0x00, - 0xa8, 0xff, 0x00, - 0xb8, 0xff, 0x00, - 0xc8, 0xff, 0x00, - 0xd8, 0xff, 0x00, - 0xe8, 0xff, 0x00, - 0xf8, 0xff, 0x00, - }; - Skin_CalcTopColors (tskin + skinsize, tskin, skinsize); - Vulkan_ExpandPalette (cola_data, tskin + skinsize, map_palette, 1, - skinsize); + Skin_CalcTopColors (cmap_data + 0, tskin, skinsize, 4); + Skin_CalcTopMask (cmap_data + 1, tskin, skinsize, 4); + Skin_CalcBottomColors (cmap_data + 2, tskin, skinsize, 4); + Skin_CalcBottomMask (cmap_data + 3, tskin, skinsize, 4); Skin_ClearTopColors (tskin, tskin, skinsize); - - Skin_CalcBottomColors (tskin + skinsize, tskin, skinsize); - Vulkan_ExpandPalette (colb_data, tskin + skinsize, map_palette, 1, - skinsize); Skin_ClearBottomColors (tskin, tskin, skinsize); Vulkan_ExpandPalette (base_data, tskin, vid.palette, 1, skinsize); @@ -214,7 +194,7 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, VkBufferImageCopy copy = { packet->offset, 0, 0, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 4}, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, SKIN_LAYERS}, {0, 0, 0}, {w, h, 1}, }; dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer, @@ -232,7 +212,7 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, 1, &ib.barrier); } else { QFV_GenerateMipMaps (device, packet->cmd, skin->image, - mipLevels, w, h, 4); + mipLevels, w, h, SKIN_LAYERS); } QFV_PacketSubmit (packet); QFV_DestroyStagingBuffer (stage); diff --git a/libs/models/skin.c b/libs/models/skin.c index ebc16d360..0f1e1f7c9 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -256,7 +256,7 @@ Skin_Init (void) } VISIBLE int -Skin_CalcTopColors (byte *out, const byte *in, size_t pixels) +Skin_CalcTopColors (byte *out, const byte *in, size_t pixels, int stride) { byte tc = 0; @@ -264,16 +264,35 @@ Skin_CalcTopColors (byte *out, const byte *in, size_t pixels) byte pix = *in++; if (pix >= TOP_RANGE && pix < TOP_RANGE + 16) { tc = 1; - *out++ = pix - TOP_RANGE; + *out = (pix - TOP_RANGE) * 16 + 8; } else { - *out++ = 0; + *out = 0; } + out += stride; } return tc; } VISIBLE int -Skin_CalcBottomColors (byte *out, const byte *in, size_t pixels) +Skin_CalcTopMask (byte *out, const byte *in, size_t pixels, int stride) +{ + byte tc = 0; + + while (pixels-- > 0) { + byte pix = *in++; + if (pix >= TOP_RANGE && pix < TOP_RANGE + 16) { + tc = 1; + *out = 0xff; + } else { + *out = 0; + } + out += stride; + } + return tc; +} + +VISIBLE int +Skin_CalcBottomColors (byte *out, const byte *in, size_t pixels, int stride) { byte bc = 0; @@ -281,10 +300,29 @@ Skin_CalcBottomColors (byte *out, const byte *in, size_t pixels) byte pix = *in++; if (pix >= BOTTOM_RANGE && pix < BOTTOM_RANGE + 16) { bc = 1; - *out++ = pix - BOTTOM_RANGE; + *out = (pix - BOTTOM_RANGE) * 16 + 8; } else { - *out++ = 0; + *out = 0; } + out += stride; + } + return bc; +} + +VISIBLE int +Skin_CalcBottomMask (byte *out, const byte *in, size_t pixels, int stride) +{ + byte bc = 0; + + while (pixels-- > 0) { + byte pix = *in++; + if (pix >= BOTTOM_RANGE && pix < BOTTOM_RANGE + 16) { + bc = 1; + *out = 0xff; + } else { + *out = 0; + } + out += stride; } return bc; } diff --git a/libs/video/renderer/vulkan/shader/alias_gbuf.frag b/libs/video/renderer/vulkan/shader/alias_gbuf.frag index c56f483e2..446219ad7 100644 --- a/libs/video/renderer/vulkan/shader/alias_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/alias_gbuf.frag @@ -24,17 +24,12 @@ main (void) { vec4 c; vec4 e; - int i; - vec3 light = vec3 (0); - vec4 rows = unpackUnorm4x8(colors); - vec2 cols = vec2 (texture (Skin, vec3 (st, 1)).r, - texture (Skin, vec3 (st, 2)).r); - vec2 mask = vec2 (texture (Skin, vec3 (st, 1)).g, - texture (Skin, vec3 (st, 2)).g); c = texture (Skin, vec3 (st, 0)) * base_color; - c += texture (Palette, vec2 (cols.x, rows.x)) * mask.x; - c += texture (Palette, vec2 (cols.y, rows.y)) * mask.y; - e = texture (Skin, vec3 (st, 3)); + e = texture (Skin, vec3 (st, 1)); + vec4 rows = unpackUnorm4x8(colors); + vec4 cmap = texture (Skin, vec3 (st, 2)); + c += texture (Palette, vec2 (cmap.x, rows.x)) * cmap.y; + c += texture (Palette, vec2 (cmap.z, rows.y)) * cmap.w; frag_color = c; frag_emission = e; From 387f17dc0cff723470768c8d2ec0cec22f01132e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 15 Nov 2022 15:21:20 +0900 Subject: [PATCH 3207/3664] [scene] Add a color map component It's currently used only by the vulkan renderer, as it's the only renderer that can make good use of it for alias models, but now vulkan show shirt/pants colors (finally). --- include/QF/scene/entity.h | 5 +++++ include/QF/scene/scene.h | 1 + libs/scene/scene.c | 12 ++++++++++++ libs/video/renderer/vulkan/vulkan_alias.c | 5 +++++ nq/source/cl_ents.c | 5 +++++ qw/source/cl_ents.c | 12 ++++++++++++ 6 files changed, 40 insertions(+) diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index 488d9ed02..f0453e3d8 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -99,6 +99,11 @@ typedef struct entqueue_s { int num_queues; } entqueue_t; +typedef struct colormap_s { + byte top; + byte bottom; +} colormap_t; + #define ENTINLINE GNU89INLINE inline entqueue_t *EntQueue_New (int num_queues); diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index ae9a03871..9792e4f2e 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -47,6 +47,7 @@ enum scene_components { scene_renderer, scene_active, scene_old_origin, //XXX FIXME XXX should not be here + scene_colormap, //FIXME these should probably be private to the sw renderer (and in a //group, which needs to be implemented), but need to sort out a good diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 90266d160..86932ca15 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -59,6 +59,13 @@ create_old_origin (void *_old_origin) *old_origin = (vec4f_t) {0, 0, 0, 1}; } +static void +create_colormap (void *_colormap) +{ + colormap_t *colormap = _colormap; + *colormap = (colormap_t) {1, 6}; +} + static void destroy_visibility (void *_visibility) { @@ -121,6 +128,11 @@ static const component_t scene_components[] = { .create = create_old_origin, .name = "old_origin", }, + [scene_colormap] = { + .size = sizeof (colormap_t), + .create = create_colormap, + .name = "colormap", + }, [scene_sw_matrix] = { .size = sizeof (mat4f_t), diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 8d3630be7..11dae501a 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -163,6 +163,11 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) } QuatCopy (renderer->colormod, constants.base_color); QuatCopy (skin->colors, constants.colors); + if (Ent_HasComponent (ent.id, scene_colormap, ent.reg)) { + colormap_t *colormap=Ent_GetComponent (ent.id, scene_colormap, ent.reg); + constants.colors[0] = colormap->top * 16 + 8; + constants.colors[1] = colormap->bottom * 16 + 8; + } QuatZero (constants.fog); emit_commands (aframe->cmdSet.a[QFV_aliasDepth], diff --git a/nq/source/cl_ents.c b/nq/source/cl_ents.c index 2545ec02e..b09a2977e 100644 --- a/nq/source/cl_ents.c +++ b/nq/source/cl_ents.c @@ -246,6 +246,11 @@ CL_RelinkEntities (void) old->skinnum = new->skinnum; renderer->skinnum = new->skinnum; if (i <= cl.maxclients) { + colormap_t colormap = { + .top = cl.players[i - 1].topcolor, + .bottom = cl.players[i - 1].bottomcolor, + }; + Ent_SetComponent (ent.id, scene_colormap, ent.reg, &colormap); renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, i); mod_funcs->Skin_SetTranslation (i, cl.players[i - 1].topcolor, diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 467fcce23..b1857f090 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -218,6 +218,11 @@ CL_LinkPacketEntities (void) && cl.players[new->colormap - 1].name->value[0] && new->modelindex == cl_playerindex) { player_info_t *player = &cl.players[new->colormap - 1]; + colormap_t colormap = { + .top = player->topcolor, + .bottom = player->bottomcolor, + }; + Ent_SetComponent (ent.id, scene_colormap, ent.reg, &colormap); renderer->skin = mod_funcs->Skin_SetSkin (renderer->skin, new->colormap, player->skinname->value); @@ -226,6 +231,7 @@ CL_LinkPacketEntities (void) } else { renderer->skin = mod_funcs->Skin_SetColormap (renderer->skin, 0); + Ent_RemoveComponent (ent.id, scene_colormap, ent.reg); } } @@ -462,6 +468,12 @@ CL_LinkPlayers (void) && is_dead_body (&state->pls.es)) continue; + colormap_t colormap = { + .top = player->topcolor, + .bottom = player->bottomcolor, + }; + Ent_SetComponent (ent.id, scene_colormap, ent.reg, &colormap); + // predict only half the move to minimize overruns msec = 500 * (playertime - state->state_time); if (msec <= 0 || (!cl_predict_players) || cls.demoplayback2) { From f323401c10dec7d79c58be71c5de67684c8a52dc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 16 Nov 2022 00:06:21 +0900 Subject: [PATCH 3208/3664] [qfcc] Add an explicit hadamard operator While the option to make '*' mean dot product for vectors is important, it breaks vector scaling in ruamoko progs as the resultant vector op becomes a dot product instead of the indented hadamard product (ie, component-wise). --- tools/qfcc/source/constfold.c | 2 +- tools/qfcc/source/dot_expr.c | 1 + tools/qfcc/source/expr_binary.c | 7 +++++++ tools/qfcc/source/options.c | 2 +- tools/qfcc/source/qc-lex.l | 1 + tools/qfcc/source/qc-parse.y | 3 ++- tools/qfcc/source/statements.c | 1 + 7 files changed, 14 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 6f6287f43..02a0b3cd8 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -394,7 +394,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) { const float *v1, *v2; vec3_t v, float_vec; - static int valid[] = {'+', '-', '*', SCALE, EQ, NE, 0}; + static int valid[] = {'+', '-', '*', HADAMARD, SCALE, EQ, NE, 0}; expr_t *t; if (!is_vector(get_type (e1))) { diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index a3a825eb3..8b5019898 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -94,6 +94,7 @@ get_op_string (int op) case 'C': return ""; case CROSS: return "@cross"; case DOT: return "@dot"; + case HADAMARD: return "@hadamard"; case SCALE: return "@scale"; default: return "unknown"; diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 9f96ef741..cffb1c580 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -150,6 +150,7 @@ static expr_type_t vector_vector[] = { {'-', &type_vector}, {DOT, &type_vector}, {CROSS, &type_vector}, + {HADAMARD, &type_vector}, {'*', 0, 0, 0, vector_multiply}, {EQ, 0, 0, 0, vector_compare}, {NE, 0, 0, 0, vector_compare}, @@ -1100,11 +1101,13 @@ binary_expr (int op, expr_t *e1, expr_t *e2) t2 = pt2; } } + int scalar_op = 0; if (type_width (t1) == 1) { // scalar op vec if (!(e = convert_scalar (e1, op, e2))) { return invalid_binary_expr (op, e1, e2); } + scalar_op = 1; e1 = e; t1 = get_type (e1); } @@ -1113,9 +1116,13 @@ binary_expr (int op, expr_t *e1, expr_t *e2) if (!(e = convert_scalar (e2, op, e1))) { return invalid_binary_expr (op, e1, e2); } + scalar_op = 1; e2 = e; t2 = get_type (e2); } + if (scalar_op && op == '*') { + op = HADAMARD; + } if (type_width (t1) != type_width (t2)) { // vec op vec of different widths return invalid_binary_expr (op, e1, e2); diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index c9cec0127..86586c375 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -742,7 +742,7 @@ DecodeArgs (int argc, char **argv) if (options.code.vector_components == (qboolean) -1) options.code.vector_components = false; if (options.math.vector_mult == 0) - options.math.vector_mult = options.advanced == 1 ? DOT : '*'; + options.math.vector_mult = options.advanced == 1 ? DOT : HADAMARD; } else { options.code.promote_float = 0; } diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index dd8c9ff84..5e50ef5d5 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -428,6 +428,7 @@ static keyword_t qf_keywords[] = { {"@cross", CROSS, 0 }, {"@dot", DOT, 0 }, + {"@hadamard", HADAMARD, 0 }, }; // These keywors are always available. Other than the @ keywords, they diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 1bab1798b..e23f231f8 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -141,7 +141,7 @@ int yylex (void); %left SHL SHR %left '+' '-' %left '*' '/' '%' MOD SCALE -%left CROSS DOT +%left CROSS DOT HADAMARD %right SIZEOF UNARY INCOP %left HYPERUNARY %left '.' '(' '[' @@ -1672,6 +1672,7 @@ expr | expr MOD expr { $$ = binary_expr (MOD, $1, $3); } | expr CROSS expr { $$ = binary_expr (CROSS, $1, $3); } | expr DOT expr { $$ = binary_expr (DOT, $1, $3); } + | expr HADAMARD expr { $$ = binary_expr (HADAMARD, $1, $3); } ; texpr diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 7f5134318..3da2e12a5 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -538,6 +538,7 @@ convert_op (int op) case '.': return "load"; case CROSS: return "cross"; case DOT: return "dot"; + case HADAMARD: return "mul"; case SCALE: return "scale"; default: return 0; From ce64baa92d58a11558d98e79599c961aa99c93b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 16 Nov 2022 11:25:27 +0900 Subject: [PATCH 3209/3664] [qfcc] Add failing test for vector constant init Raw 'x y z' style vector constants that look like ints (no fractional parts) used to initialize vector globals/constants don't get converted to float vectors, resulting in nans for negative values and denormals for positive values. This tends to make game physics... interesting. --- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/vecconst.r | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tools/qfcc/test/vecconst.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index e6ada0a81..1489bd241 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -64,6 +64,7 @@ test_progs_dat=\ tools/qfcc/test/unaryminus.dat \ tools/qfcc/test/vecaddr.dat \ tools/qfcc/test/vecexpr.dat \ + tools/qfcc/test/vecconst.dat \ tools/qfcc/test/vecinit.dat \ tools/qfcc/test/voidfor.dat \ tools/qfcc/test/while.dat \ @@ -720,6 +721,16 @@ tools/qfcc/test/vecexpr.run: $(qfcc_test_run_deps) include $(vecexpr_dep) # am--include-marker r_depfiles_remade += $(vecexpr_dep) +tools_qfcc_test_vecconst_dat_SOURCES=tools/qfcc/test/vecconst.r +vecconst_obj=$(tools_qfcc_test_vecconst_dat_SOURCES:.r=.o) +vecconst_dep=$(call qcautodep,$(tools_qfcc_test_vecconst_dat_SOURCES)) +tools/qfcc/test/vecconst.dat$(EXEEXT): $(vecconst_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(vecconst_obj) +tools/qfcc/test/vecconst.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(vecconst_dep) # am--include-marker +r_depfiles_remade += $(vecconst_dep) + tools_qfcc_test_vecinit_dat_SOURCES=tools/qfcc/test/vecinit.r vecinit_obj=$(tools_qfcc_test_vecinit_dat_SOURCES:.r=.o) vecinit_dep=$(call qcautodep,$(tools_qfcc_test_vecinit_dat_SOURCES)) diff --git a/tools/qfcc/test/vecconst.r b/tools/qfcc/test/vecconst.r new file mode 100644 index 000000000..cddd000ed --- /dev/null +++ b/tools/qfcc/test/vecconst.r @@ -0,0 +1,17 @@ +vector mins = '-16 -16 -24'; +vector maxs = '16 16 32'; + +int +check (vector v, float x, float y, float z) +{ + return v.x != x || v.y != y || v.z != z; +} + +int +main () +{ + int ret = 0; + ret |= check (mins, -16, -16, -24); + ret |= check (maxs, 16, 16, 32); + return ret; +} From 47163ef2c4db5624a36fb07abfb961032a29177d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 16 Nov 2022 11:38:05 +0900 Subject: [PATCH 3210/3664] [qw] Fix packet log svc check Fixes the svc_updatepl name not being printed --- qw/source/net_packetlog.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/qw/source/net_packetlog.c b/qw/source/net_packetlog.c index cd9b6eed6..4ec36d0df 100644 --- a/qw/source/net_packetlog.c +++ b/qw/source/net_packetlog.c @@ -99,6 +99,8 @@ const char *svc_string[] = { "svc_updatename", // [byte] [string] "svc_updatefrags", // [byte] [short] "svc_clientdata", // + + //0x10 "svc_stopsound", // "svc_updatecolors", // [byte] [byte] "svc_particle", // [vec3] @@ -116,6 +118,8 @@ const char *svc_string[] = { "svc_spawnstaticsound", "svc_intermission", "svc_finale", // [string] music [string] text + + //0x20 "svc_cdtrack", // [byte] track [byte] looptrack "svc_sellscreen", "svc_smallkick", // Quake svc_cutscene @@ -132,6 +136,8 @@ const char *svc_string[] = { "svc_modellist", "svc_soundlist", "svc_packetentities", + + //0x30 "svc_deltapacketentities", "svc_maxspeed", "svc_entgravity", @@ -148,9 +154,7 @@ const char *svc_string[] = { "NEW PROTOCOL", "NEW PROTOCOL", "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL", - "NEW PROTOCOL" + }; const char *clc_string[] = { @@ -405,7 +409,7 @@ Parse_Server_Packet (int has_sequence) break; Net_LogPrintf ("<%06x> [0x%02x] ", MSG_GetReadCount (&packet), c); - if (c < 53) + if (c < 0x40) Net_LogPrintf ("%s: ", svc_string[c]); if (MSG_GetReadCount (&packet) > packet.message->cursize) From e1d7854af5b6bac8d84cfe2a406cd5f85e957c17 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 16 Nov 2022 17:53:21 +0900 Subject: [PATCH 3211/3664] [qfcc] Rename G_* macros to Q_* They clash with those in progs.h, which is needed for using progs code in the compiler. --- tools/qfcc/include/qfcc.h | 4 ++-- tools/qfcc/source/class.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index a6384c91c..01263eea6 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -110,8 +110,8 @@ extern pr_info_t pr; #define D_POINTER(t,d) (&D_PACKED (t, d)) #define D_STRUCT(t,d) (*D_POINTER (t, d)) -#define G_POINTER(s,t,o) ((t *)((s)->data + o)) -#define G_STRUCT(s,t,o) (*G_POINTER (s, t, o)) +#define Q_POINTER(s,t,o) ((t *)((s)->data + o)) +#define Q_STRUCT(s,t,o) (*Q_POINTER (s, t, o)) #define POINTER_OFS(s,p) ((pr_type_t *) (p) - (s)->data) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index c19f2dd01..5be3015d9 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1075,7 +1075,7 @@ finish_class (class_t *class) space = class->def->space; cls = &D_STRUCT (pr_class_t, class->def); - meta = &G_STRUCT (space, pr_class_t, cls->class_pointer); + meta = &Q_STRUCT (space, pr_class_t, cls->class_pointer); EMIT_DEF (space, meta->methods, emit_methods (class->methods, class->name, 0)); From 23469029ca38d82f1a752f7582d72063fc9aecd1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 16 Nov 2022 17:55:56 +0900 Subject: [PATCH 3212/3664] [qfcc] Support converting non-scalar values This fixes the basic vecconst test (extending it to other types breaks because long and ulong are not properly supported yet). The conversion is done by the progs VM rather than writing another 256 conversions (though loops could be used). This works nicely as a test for using the VM to help with compiling. --- tools/qfcc/source/def.c | 2 +- tools/qfcc/source/value.c | 185 +++++++++++++++++++++----------------- 2 files changed, 104 insertions(+), 83 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index bab482a9f..76286dce6 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -637,7 +637,7 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, warning (init, "assigning double to %s in initializer " "(use a cast)", sym->type->name); } - if (is_scalar (sym->type)) + if (!type_same (sym->type, init_type)) v = convert_value (v, sym->type); if (v->lltype == ev_string) { EMIT_STRING (sym->s.def->space, D_STRING (sym->s.def), diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 7ea649782..58ca36a35 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -43,6 +43,7 @@ #include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" +#include "QF/progs.h" #include "QF/va.h" #include "QF/simd/types.h" @@ -53,6 +54,7 @@ #include "tools/qfcc/include/diagnostic.h" #include "tools/qfcc/include/emit.h" #include "tools/qfcc/include/expr.h" +#include "tools/qfcc/include/options.h" #include "tools/qfcc/include/reloc.h" #include "tools/qfcc/include/strpool.h" #include "tools/qfcc/include/symtab.h" @@ -80,6 +82,88 @@ typedef struct { static hashtab_t *value_table; static ex_value_t *values_freelist; +//FIXME this (to setup_value_progs) should be in its own file and more +//general (good for constant folding, too, and maybe some others). +static void +value_debug_handler (prdebug_t event, void *param, void *data) +{ + progs_t *pr = data; + switch (event) { + case prd_trace: + dstatement_t *st = pr->pr_statements + pr->pr_xstatement; + PR_PrintStatement (pr, st, 0); + break; + case prd_breakpoint: + case prd_subenter: + case prd_subexit: + case prd_runerror: + case prd_watchpoint: + case prd_begin: + case prd_terminate: + case prd_error: + case prd_none: + break; + } +} + +enum { + vf_null, + vf_convert, +}; + +#define BASE(b, base) (((base) & 3) << OP_##b##_SHIFT) +#define OP(a, b, c, op) ((op) | BASE(A, a) | BASE(B, b) | BASE(C, c)) + +static bfunction_t value_functions[] = { + {}, // null function + [vf_convert] = { .first_statement = vf_convert * 16 }, +}; + +static __attribute__((aligned(64))) +dstatement_t value_statements[] = { + [vf_convert * 16 - 1] = {}, + { OP_CONV, 0, 07777, 16 }, + { OP_RETURN, 16, 0, 0 }, +}; + +#define num_globals 16384 +#define stack_size 8192 +static __attribute__((aligned(64))) +pr_type_t value_globals[num_globals + 128] = { + [num_globals - stack_size] = { .uint_value = num_globals }, +}; + +static dprograms_t value_progs = { + .version = PROG_VERSION, + .statements = { + .count = sizeof (value_statements) / sizeof (value_statements[0]), + }, +}; +static progs_t value_pr = { + .progs = &value_progs, + .debug_handler = value_debug_handler, + .debug_data = &value_pr, + .pr_trace = 1, + .pr_trace_depth = -1, + .function_table = value_functions, + .pr_statements = value_statements, + .globals_size = num_globals, + .pr_globals = value_globals, + .stack_bottom = num_globals - stack_size + 4, + .pr_return_buffer = value_globals + num_globals, + .pr_return = value_globals + num_globals, + .globals = { + .stack = (pr_ptr_t *) (value_globals + num_globals - stack_size), + } +}; + +static void +setup_value_progs (void) +{ + PR_Init (&value_pr); + PR_Debug_Init (&value_pr); +} + static uintptr_t value_get_hash (const void *_val, void *unused) { @@ -536,94 +620,29 @@ ReuseString (const char *str) return strpool_addstr (pr.strings, str); } -static float -value_as_float (ex_value_t *value) -{ - if (value->lltype == ev_uint) - return value->v.uint_val; - if (value->lltype == ev_int) - return value->v.int_val; - if (value->lltype == ev_short) - return value->v.short_val; - if (value->lltype == ev_double) - return value->v.double_val; - if (value->lltype == ev_float) - return value->v.float_val; - return 0; -} - -static double -value_as_double (ex_value_t *value) -{ - if (value->lltype == ev_uint) - return value->v.uint_val; - if (value->lltype == ev_int) - return value->v.int_val; - if (value->lltype == ev_short) - return value->v.short_val; - if (value->lltype == ev_double) - return value->v.double_val; - if (value->lltype == ev_float) - return value->v.float_val; - return 0; -} - -static int -value_as_int (ex_value_t *value) -{ - if (value->lltype == ev_uint) - return value->v.uint_val; - if (value->lltype == ev_int) - return value->v.int_val; - if (value->lltype == ev_short) - return value->v.short_val; - if (value->lltype == ev_double) - return value->v.double_val; - if (value->lltype == ev_float) - return value->v.float_val; - return 0; -} - -static unsigned -value_as_uint (ex_value_t *value) -{ - if (value->lltype == ev_uint) - return value->v.uint_val; - if (value->lltype == ev_int) - return value->v.int_val; - if (value->lltype == ev_short) - return value->v.short_val; - if (value->lltype == ev_double) - return value->v.double_val; - if (value->lltype == ev_float) - return value->v.float_val; - return 0; -} - ex_value_t * convert_value (ex_value_t *value, type_t *type) { - if (!is_scalar (type) || !is_scalar (ev_types[value->lltype])) { - error (0, "unable to convert non-scalar value"); + if (!is_math (type) || !is_math (value->type)) { + error (0, "unable to convert non-math value"); return value; } - if (is_float (type)) { - float val = value_as_float (value); - return new_float_val (val); - } else if (is_double (type)) { - double val = value_as_double (value); - return new_double_val (val); - } else if (type->type == ev_short) { - int val = value_as_int (value); - return new_short_val (val); - } else if (type->type == ev_uint) { - unsigned val = value_as_uint (value); - return new_uint_val (val); - } else { - //FIXME handle enums separately? - int val = value_as_int (value); - return new_int_val (val); + if (type_width (type) != type_width (value->type)) { + error (0, "unable to convert between values of different widths"); + return value; } + int from = type_cast_map[base_type (value->type)->type]; + int to = type_cast_map[base_type (type)->type]; + int width = type_width (value->type) - 1; + int conv = TYPE_CAST_CODE (from, to, width); + int addr = value_functions[vf_convert].first_statement; + value_statements[addr + 0].b = conv; + value_statements[addr + 1].c = width; // width is actual width - 1 + memcpy (value_globals, &value->v, + type_size (value->type) * sizeof (pr_type_t)); + value_pr.pr_trace = options.verbosity > 1; + PR_ExecuteProgram (&value_pr, vf_convert); + return new_type_value (type, value_pr.pr_return_buffer); } ex_value_t * @@ -788,6 +807,8 @@ clear_immediates (void) Hash_FlushTable (fldptr_imm_defs); Hash_FlushTable (value_imm_defs); } else { + setup_value_progs (); + value_table = Hash_NewTable (16381, 0, 0, 0, 0); Hash_SetHashCompare (value_table, value_get_hash, value_compare); From de2cc21c7e3964e0c16db71e47023e0cd5068e2b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 16 Nov 2022 20:48:58 +0900 Subject: [PATCH 3213/3664] [qfcc] Add basic support for (u)long expressions It's woefully incomplete, but sufficient to test initializing non-scalars from ivec constants. Fixes #36 --- tools/qfcc/source/expr_binary.c | 54 ++++++++++++++++++++++++++++++++- tools/qfcc/source/value.c | 4 ++- tools/qfcc/test/vecconst.r | 49 ++++++++++++++++++++++++++++-- 3 files changed, 102 insertions(+), 5 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index cffb1c580..1f6d64a3b 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -533,6 +533,48 @@ static expr_type_t double_double[] = { {0, 0} }; +static expr_type_t long_long[] = { + {'+', &type_long}, + {'-', &type_long}, + {'*', &type_long}, + {'/', &type_long}, + {'&', &type_long}, + {'|', &type_long}, + {'^', &type_long}, + {'%', &type_long}, + {MOD, &type_long}, + {SHL, &type_long}, + {SHR, &type_long}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, + {0, 0} +}; + +static expr_type_t ulong_ulong[] = { + {'+', &type_long}, + {'-', &type_long}, + {'*', &type_long}, + {'/', &type_long}, + {'&', &type_long}, + {'|', &type_long}, + {'^', &type_long}, + {'%', &type_long}, + {MOD, &type_long}, + {SHL, &type_long}, + {SHR, &type_long}, + {EQ, &type_int}, + {NE, &type_int}, + {LE, &type_int}, + {GE, &type_int}, + {LT, &type_int}, + {GT, &type_int}, + {0, 0} +}; + static expr_type_t *string_x[ev_type_count] = { [ev_string] = string_string, }; @@ -628,6 +670,14 @@ static expr_type_t *double_x[ev_type_count] = { [ev_double] = double_double, }; +static expr_type_t *long_x[ev_type_count] = { + [ev_long] = long_long, +}; + +static expr_type_t *ulong_x[ev_type_count] = { + [ev_ulong] = ulong_ulong, +}; + static expr_type_t **binary_expr_types[ev_type_count] = { [ev_string] = string_x, [ev_float] = float_x, @@ -640,7 +690,9 @@ static expr_type_t **binary_expr_types[ev_type_count] = { [ev_int] = int_x, [ev_uint] = uint_x, [ev_short] = short_x, - [ev_double] = double_x + [ev_double] = double_x, + [ev_long] = long_x, + [ev_ulong] = ulong_x, }; // supported operators for scalar-vector expressions diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index 58ca36a35..b4633df74 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -637,7 +637,7 @@ convert_value (ex_value_t *value, type_t *type) int conv = TYPE_CAST_CODE (from, to, width); int addr = value_functions[vf_convert].first_statement; value_statements[addr + 0].b = conv; - value_statements[addr + 1].c = width; // width is actual width - 1 + value_statements[addr + 1].c = type_size (type) - 1; memcpy (value_globals, &value->v, type_size (value->type) * sizeof (pr_type_t)); value_pr.pr_trace = options.verbosity > 1; @@ -697,6 +697,8 @@ emit_value (ex_value_t *value, def_t *def) case ev_vector: case ev_quaternion: case ev_double: + case ev_long: + case ev_ulong: tab = value_imm_defs; type = val.type; break; diff --git a/tools/qfcc/test/vecconst.r b/tools/qfcc/test/vecconst.r index cddd000ed..6beaff9c2 100644 --- a/tools/qfcc/test/vecconst.r +++ b/tools/qfcc/test/vecconst.r @@ -1,17 +1,60 @@ vector mins = '-16 -16 -24'; vector maxs = '16 16 32'; +ivec4 i4 = '1 2 -3 4'; +vec4 v4 = '1 2 -3 4'; +lvec4 l4 = '1 2 -3 4'; +uivec4 ui4 = '1 2 -3 4'; +dvec4 d4 = '1 2 -3 4'; +ulvec4 ul4 = '1 2 -3 4'; int -check (vector v, float x, float y, float z) +check_v (vector v, float x, float y, float z) { return v.x != x || v.y != y || v.z != z; } +int check_ivec4 (ivec4 v, int x, int y, int z, int w) +{ + return v.x != x || v.y != y || v.z != z || v.w != w; +} + +int check_vec4 (vec4 v, float x, float y, float z, float w) +{ + return v.x != x || v.y != y || v.z != z || v.w != w; +} + +int check_lvec4 (lvec4 v, long x, long y, long z, long w) +{ + return v.x != x || v.y != y || v.z != z || v.w != w; +} + +int check_uivec4 (uivec4 v, unsigned x, unsigned y, unsigned z, unsigned w) +{ + return v.x != x || v.y != y || v.z != z || v.w != w; +} + +int check_dvec4 (dvec4 v, double x, double y, double z, double w) +{ + return v.x != x || v.y != y || v.z != z || v.w != w; +} + +int check_ulvec4 (ulvec4 v, unsigned long x, unsigned long y, unsigned long z, + unsigned long w) +{ + return v.x != x || v.y != y || v.z != z || v.w != w; +} + int main () { int ret = 0; - ret |= check (mins, -16, -16, -24); - ret |= check (maxs, 16, 16, 32); + ret |= check_v (mins, -16, -16, -24); + ret |= check_v (maxs, 16, 16, 32); + ret |= check_ivec4 (i4, 1, 2, -3, 4); + ret |= check_vec4 (v4, 1, 2, -3, 4); + ret |= check_lvec4 (l4, 1, 2, -3, 4); + ret |= check_uivec4 (ui4, 1, 2, -3, 4); + ret |= check_dvec4 (d4, 1, 2, -3, 4); + ret |= check_ulvec4 (ul4, 1, 2, -3, 4); return ret; } From ac0079f8728f1e13628d1174bc00fbbdc63af37b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Nov 2022 21:49:38 +0900 Subject: [PATCH 3214/3664] [ecs] Add a function to remove a component from all entities While simple component pools can be cleared simply by zeroing their counts, ones that have a delete function need that function to be called for all the components in the pool otherwise leaks can happen. --- include/QF/ecs/component.h | 1 + libs/ecs/component.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/QF/ecs/component.h b/include/QF/ecs/component.h index 8e881ec33..b82440eba 100644 --- a/include/QF/ecs/component.h +++ b/include/QF/ecs/component.h @@ -238,6 +238,7 @@ void ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, uint32_t ECS_NewEntity (ecs_registry_t *registry); void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent); +void ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component); void *Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry); void Ent_RemoveComponent (uint32_t ent, uint32_t comp, diff --git a/libs/ecs/component.c b/libs/ecs/component.c index b7c13ad3d..24ec85294 100644 --- a/libs/ecs/component.c +++ b/libs/ecs/component.c @@ -216,3 +216,18 @@ ECS_DelEntity (ecs_registry_t *registry, uint32_t ent) Ent_RemoveComponent (ent, i, registry); } } + +VISIBLE void +ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component) +{ + ecs_pool_t *pool = ®istry->comp_pools[component]; + const component_t *comp = ®istry->components[component]; + __auto_type destroy = comp->destroy; + if (destroy) { + byte *data = registry->comp_pools[component].data; + for (uint32_t i = 0; i < pool->count; i++) { + destroy (data + i * comp->size); + } + } + pool->count = 0; +} From 06f410b0b6a837ac95b61e59042a6639692db442 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Nov 2022 21:57:53 +0900 Subject: [PATCH 3215/3664] [renderer] Clear the visibility components on scene reset I don't know why it didn't happen during the demo loop, but going from the start map to e1m1 caused a segfault due to the efrags for a lava ball getting double freed (however, I do think it might be because the ball passed through at least two leafs, while entities in the demos did not). The double free was because SCR_NewScene (indirectly) freed all the efrags without removing them from entities, and then the client code deleting the entities caused the visibility components to get deleted and thus the efrags freed a second time. Using ECS_RemoveEntities on the visibility component ensures the entities don't have a visibility component to remove when they are later deleted. --- libs/scene/efrag.c | 8 +++----- libs/video/renderer/r_screen.c | 3 +++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libs/scene/efrag.c b/libs/scene/efrag.c index 89f919358..898dd2c9b 100644 --- a/libs/scene/efrag.c +++ b/libs/scene/efrag.c @@ -102,15 +102,13 @@ R_ClearEfragChain (efrag_t *ef) while (ef) { prev = &ef->leaf->efrags; - while (1) { - walk = *prev; - if (!walk) - break; + while ((walk = *prev)) { if (walk == ef) { // remove this fragment *prev = ef->leafnext; break; - } else + } else { prev = &walk->leafnext; + } } old = ef; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index fdcdcc9d8..be925c15a 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -470,6 +470,9 @@ SCR_Init (void) void SCR_NewScene (scene_t *scene) { + if (scr_scene) { + ECS_RemoveEntities (scr_scene->reg, scene_visibility); + } scr_scene = scene; if (scene) { mod_brush_t *brush = &scr_scene->worldmodel->brush; From b1d7bad2e3b42d7f8d356f954ca84774075e2cea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 Nov 2022 22:10:04 +0900 Subject: [PATCH 3216/3664] [renderer] Move call to R_ClearEfrags to SCR_NewScene Probably more such should be moved, but efrags is on my mind. There's no need for the call to be spread through all the renderers. --- libs/video/renderer/gl/gl_rmain.c | 1 - libs/video/renderer/glsl/glsl_main.c | 1 - libs/video/renderer/r_screen.c | 1 + libs/video/renderer/sw/sw_rmain.c | 1 - libs/video/renderer/vid_render_vulkan.c | 1 - 5 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index bfe4129d4..23f417745 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -280,7 +280,6 @@ void gl_R_ClearState (void) { r_refdef.worldmodel = 0; - R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 0df960345..1dfbcc6a3 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -219,7 +219,6 @@ void glsl_R_ClearState (void) { r_refdef.worldmodel = 0; - R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); } diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index be925c15a..3e93affdf 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -472,6 +472,7 @@ SCR_NewScene (scene_t *scene) { if (scr_scene) { ECS_RemoveEntities (scr_scene->reg, scene_visibility); + R_ClearEfrags (); } scr_scene = scene; if (scene) { diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index dadc8c254..1a2d3a9e9 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -694,7 +694,6 @@ void R_ClearState (void) { r_refdef.worldmodel = 0; - R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 4a614498a..5e7c06d04 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -117,7 +117,6 @@ vulkan_R_ClearState (void) { QFV_DeviceWaitIdle (vulkan_ctx->device); r_refdef.worldmodel = 0; - R_ClearEfrags (); R_ClearDlights (); R_ClearParticles (); Vulkan_LoadLights (0, vulkan_ctx); From bffe9413b74e5fa4f756c68d5106fe6d40744a77 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Nov 2022 09:44:01 +0900 Subject: [PATCH 3217/3664] [vulkan] Add support for 9-slice rendering There's no API yet as I need to look into the handling of qpic_t before I can get any of this into the other renderers (or even vulkan, for that matter). However, the current design for slice rendering is based on glyphs (ie, using instances and vertex pulling), with 3 strips of 3 quads, 16 verts, and 26 indices (2 reset). Hacky testing seems to work, but real tests need the API. --- libs/video/renderer/Makemodule.am | 5 + libs/video/renderer/vulkan/qfpipeline.plist | 34 ++++ libs/video/renderer/vulkan/shader.c | 3 + libs/video/renderer/vulkan/shader/slice.vert | 34 ++++ libs/video/renderer/vulkan/vulkan_draw.c | 177 +++++++++++++++---- 5 files changed, 221 insertions(+), 32 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/slice.vert diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 0eea5d10b..245989153 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -275,6 +275,8 @@ vkparse_plist = \ vkshaderpath = libs/video/renderer/vulkan/shader +slice_src = $(vkshaderpath)/slice.vert +slice_c = $(vkshaderpath)/slice.vert.spvc glyph_src = $(vkshaderpath)/glyph.vert glyph_c = $(vkshaderpath)/glyph.vert.spvc glyph_color_src = $(vkshaderpath)/glyph_color.frag @@ -351,6 +353,8 @@ fstriangle_c = $(vkshaderpath)/fstriangle.vert.spvc pushcolor_src = $(vkshaderpath)/pushcolor.frag pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc +$(slice_vert_c): $(slice_vert_src) + $(glyph_vert_c): $(glyph_vert_src) $(glyph_color_c): $(glyph_color_src) $(glyph_coverage_c): $(glyph_coverage_src) @@ -419,6 +423,7 @@ $(fstriangle_c): $(fstriangle_src) $(pushcolor_c): $(pushcolor_src) vkshader_c = \ + $(slice_c) \ $(glyph_c) \ $(glyph_color_c) \ $(glyph_coverage_c) \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 43e3bf646..8ae2927d0 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -582,6 +582,21 @@ { location = 2; binding = 1; format = r32_uint; offset = 0; }, ); }; + slice = { + bindings = ( + { binding = 0; stride = "4 + 4 + 4 * 4"; inputRate = instance; }, + ); + attributes = ( + // 9-slice index + { location = 0; binding = 0; format = r32_uint; offset = 0; }, + // 9-slice color + { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, + // 9-slice position (2d) + { location = 2; binding = 0; format = r32g32_sfloat; offset = 8; }, + // 9-slice size delta (2d) + { location = 3; binding = 0; format = r32g32_sfloat; offset = 16; }, + ); + }; glyph = { bindings = ( { binding = 0; stride = "4 + 4 + 2 * 4"; inputRate = instance; }, @@ -1115,6 +1130,25 @@ }; layout = twod_layout; }; + slice = { + @inherit = $properties.pipelines.trans_base;//FIXME should be sparate + stages = ( + { stage = vertex; name = main; module = $builtin/slice.vert; }, + { stage = fragment; name = main; module = $builtin/glyph_color.frag; }, + ); + vertexInput = $properties.vertexInput.slice; + inputAssembly = { + // slices are drawn using instanced slice triples + topology = triangle_strip; + primitiveRestartEnable = true; + }; + rasterization = $properties.rasterization.counter_cw_cull_back; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.alpha_blend); + }; + layout = glyph_layout;//slices use the same descriptors as glyphs + }; glyph = { @inherit = $properties.pipelines.trans_base;//FIXME should be sparate vertexInput = $properties.vertexInput.glyph; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 95c733cfd..be8b0c1eb 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -38,6 +38,8 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/shader.h" +static +#include "libs/video/renderer/vulkan/shader/slice.vert.spvc" static #include "libs/video/renderer/vulkan/shader/glyph.vert.spvc" static @@ -120,6 +122,7 @@ typedef struct shaderdata_s { } shaderdata_t; static shaderdata_t builtin_shaders[] = { + { "slice.vert", slice_vert, sizeof (slice_vert) }, { "glyph.vert", glyph_vert, sizeof (glyph_vert) }, { "glyph_color.frag", glyph_color_frag, sizeof (glyph_color_frag) }, { "glyph_coverage.frag", glyph_coverage_frag, sizeof (glyph_coverage_frag) }, diff --git a/libs/video/renderer/vulkan/shader/slice.vert b/libs/video/renderer/vulkan/shader/slice.vert new file mode 100644 index 000000000..c1009e925 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/slice.vert @@ -0,0 +1,34 @@ +#version 450 + +layout (set = 0, binding = 0) uniform Matrices { + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; +}; +layout (set = 1, binding = 0) uniform textureBuffer glyph_data; + +// per instance data +layout (location = 0) in uint glyph_index; +layout (location = 1) in vec4 glyph_color; +layout (location = 2) in vec2 glyph_position; +layout (location = 3) in vec2 glyph_offset; // for 9-slice + +// rg -> offset x,y +// ba -> texture u,v + +layout (location = 0) out vec2 uv; +layout (location = 1) out vec4 color; + +void +main (void) +{ + vec2 offset = vec2 ((gl_VertexIndex & 4) >> 2, (gl_VertexIndex & 8) >> 3); + vec4 glyph = texelFetch (glyph_data, int(glyph_index) * 4 + gl_VertexIndex); + // offset stored in glyph components 0 and 1 + vec2 position = glyph_position + glyph.xy + offset * glyph_offset; + gl_Position = Projection2d * vec4 (position.xy, 0.0, 1.0); + // texture uv stored in glyph components 2 and 3 + uv = glyph.pq; + color = glyph_color; +} diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 7eb2a9156..1973d8a4b 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -87,6 +87,13 @@ typedef struct { float color[4]; } drawvert_t; +typedef struct { + uint32_t index; + byte color[4]; + float position[2]; + float offset[2]; +} sliceinst_t; + typedef struct { uint32_t index; byte color[4]; @@ -109,6 +116,12 @@ typedef struct vertqueue_s { int size; } vertqueue_t; +typedef struct slicequeue_s { + sliceinst_t *slices; + int count; + int size; +} slicequeue_t; + typedef struct glyphqueue_s { glyphinst_t *glyphs; int count; @@ -117,14 +130,18 @@ typedef struct glyphqueue_s { typedef struct drawframe_s { size_t quad_offset; + size_t slice_offset; size_t glyph_offset; size_t line_offset; VkBuffer quad_buffer; descbatchset_t quad_batch; + VkBuffer slice_buffer; + descbatchset_t slice_batch; VkBuffer glyph_buffer; descbatchset_t glyph_batch; VkBuffer line_buffer; vertqueue_t quad_verts; + slicequeue_t slice_insts; glyphqueue_t glyph_insts; vertqueue_t line_verts; VkCommandBuffer cmd; @@ -166,14 +183,17 @@ typedef struct drawctx_s { memsuper_t *string_memsuper; hashtab_t *pic_cache; qfv_resource_t *draw_resource; + qfv_resobj_t *ind_objects; qfv_resobj_t *quad_objects; + qfv_resobj_t *slice_objects; qfv_resobj_t *glyph_objects; qfv_resobj_t *line_objects; VkPipeline quad_pipeline; + VkPipeline slice_pipeline; VkPipeline glyph_coverage_pipeline; VkPipeline line_pipeline; VkPipelineLayout layout; - VkPipelineLayout glyph_layout; + VkPipelineLayout glyph_layout;//slice pipeline uses same layout VkDescriptorSet quad_set; drawframeset_t frames; drawfontset_t fonts; @@ -195,6 +215,39 @@ typedef struct drawctx_s { #define VERTS_PER_FRAME (LINES_OFFSET + MAX_LINES*VERTS_PER_LINE) +static void +generate_quad_indices (qfv_stagebuf_t *staging, qfv_resobj_t *ind_buffer) +{ + qfv_packet_t *packet = QFV_PacketAcquire (staging); + uint32_t *ind = QFV_PacketExtend (packet, ind_buffer->buffer.size); + for (int i = 0; i < MAX_QUADS; i++) { + for (int j = 0; j < VERTS_PER_QUAD; j++) { + *ind++ = i * VERTS_PER_QUAD + j; + } + // mark end of primitive + *ind++ = -1; + } + QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, + &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); + QFV_PacketSubmit (packet); +} + +static void +generate_slice_indices (qfv_stagebuf_t *staging, qfv_resobj_t *ind_buffer) +{ + qfv_packet_t *packet = QFV_PacketAcquire (staging); + uint32_t *ind = QFV_PacketExtend (packet, ind_buffer->buffer.size); + for (int i = 0; i < 8; i++) { + ind[i] = i; + ind[i + 9] = i + 1 + (i & 1) * 6; + ind[i + 18] = i + 8; + } + ind[8] = ind[17] = ~0; + QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, + &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); + QFV_PacketSubmit (packet); +} + static void create_quad_buffers (vulkan_ctx_t *ctx) { @@ -204,32 +257,38 @@ create_quad_buffers (vulkan_ctx_t *ctx) size_t frames = ctx->frames.size; dctx->draw_resource = malloc (2 * sizeof (qfv_resource_t) - // quads: index + frames vertex buffers - + (1 + frames) * sizeof (qfv_resobj_t) + // index buffers + + 2 * sizeof (qfv_resobj_t) + // quads: frames vertex buffers + + (frames) * sizeof (qfv_resobj_t) + // slicess: frames instance vertex buffers + + (frames) * sizeof (qfv_resobj_t) // glyphs: frames instance vertex buffers + (frames) * sizeof (qfv_resobj_t) // lines: frames vertex buffers + (frames) * sizeof (qfv_resobj_t)); - dctx->quad_objects = (qfv_resobj_t *) &dctx->draw_resource[2]; - dctx->glyph_objects = &dctx->quad_objects[1 + frames]; + dctx->ind_objects = (qfv_resobj_t *) &dctx->draw_resource[2]; + dctx->quad_objects = &dctx->ind_objects[2]; + dctx->slice_objects = &dctx->quad_objects[frames]; + dctx->glyph_objects = &dctx->slice_objects[frames]; dctx->line_objects = &dctx->glyph_objects[frames]; dctx->draw_resource[0] = (qfv_resource_t) { .name = "draw", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .num_objects = 1, // has only the quad index buffer - .objects = dctx->quad_objects, + .num_objects = 2, // quad and 9-slice indices + .objects = dctx->ind_objects, }; dctx->draw_resource[1] = (qfv_resource_t) { .name = "draw", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - .num_objects = (frames) + (frames) + (frames), - .objects = dctx->quad_objects + 1, + .num_objects = (frames) + (frames) + (frames) + (frames), + .objects = dctx->quad_objects, }; - dctx->quad_objects[0] = (qfv_resobj_t) { + dctx->ind_objects[0] = (qfv_resobj_t) { .name = "quads.index", .type = qfv_res_buffer, .buffer = { @@ -238,10 +297,18 @@ create_quad_buffers (vulkan_ctx_t *ctx) | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, }, }; - __auto_type ind_buffer = &dctx->quad_objects[0]; + dctx->ind_objects[1] = (qfv_resobj_t) { + .name = "9-slice.index", + .type = qfv_res_buffer, + .buffer = { + .size = 26 * sizeof (uint32_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + }, + }; for (size_t i = 0; i < frames; i++) { - dctx->quad_objects[i + 1] = (qfv_resobj_t) { + dctx->quad_objects[i] = (qfv_resobj_t) { .name = "quads.geom", .type = qfv_res_buffer, .buffer = { @@ -250,6 +317,15 @@ create_quad_buffers (vulkan_ctx_t *ctx) | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, }, }; + dctx->slice_objects[i] = (qfv_resobj_t) { + .name = "slices.inst", + .type = qfv_res_buffer, + .buffer = { + .size = MAX_GLYPHS * sizeof (sliceinst_t), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + }, + }; dctx->glyph_objects[i] = (qfv_resobj_t) { .name = "glyphs.inst", .type = qfv_res_buffer, @@ -278,8 +354,10 @@ create_quad_buffers (vulkan_ctx_t *ctx) for (size_t f = 0; f < frames; f++) { drawframe_t *frame = &dctx->frames.a[f]; - frame->quad_buffer = dctx->quad_objects[1 + f].buffer.buffer; - frame->quad_offset = dctx->quad_objects[1 + f].buffer.offset; + frame->quad_buffer = dctx->quad_objects[f].buffer.buffer; + frame->quad_offset = dctx->quad_objects[f].buffer.offset; + frame->slice_buffer = dctx->slice_objects[f].buffer.buffer; + frame->slice_offset = dctx->slice_objects[f].buffer.offset; frame->glyph_buffer = dctx->glyph_objects[f].buffer.buffer; frame->glyph_offset = dctx->glyph_objects[f].buffer.offset; frame->line_buffer = dctx->line_objects[f].buffer.buffer; @@ -290,6 +368,11 @@ create_quad_buffers (vulkan_ctx_t *ctx) .size = MAX_QUADS, }; DARRAY_INIT (&frame->quad_batch, 16); + frame->slice_insts = (slicequeue_t) { + .slices = (sliceinst_t *) ((byte *)data + frame->slice_offset), + .size = MAX_QUADS, + }; + DARRAY_INIT (&frame->slice_batch, 16); frame->glyph_insts = (glyphqueue_t) { .glyphs = (glyphinst_t *) ((byte *)data + frame->glyph_offset), .size = MAX_QUADS, @@ -302,18 +385,8 @@ create_quad_buffers (vulkan_ctx_t *ctx) } // The indices will never change so pre-generate and stash them - qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); - uint32_t *ind = QFV_PacketExtend (packet, ind_buffer->buffer.size); - for (int i = 0; i < MAX_QUADS; i++) { - for (int j = 0; j < VERTS_PER_QUAD; j++) { - *ind++ = i * VERTS_PER_QUAD + j; - } - // mark end of primitive - *ind++ = -1; - } - QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, - &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); - QFV_PacketSubmit (packet); + generate_quad_indices (ctx->staging, &dctx->ind_objects[0]); + generate_slice_indices (ctx->staging, &dctx->ind_objects[1]); } static void @@ -463,6 +536,7 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) } dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); + dfunc->vkDestroyPipeline (device->dev, dctx->slice_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->glyph_coverage_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0); Hash_DelTable (dctx->pic_cache); @@ -536,6 +610,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); + dctx->slice_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "slice"); dctx->glyph_coverage_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "glyph_coverage"); dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines"); @@ -1045,8 +1120,8 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - if (!dframe->quad_verts.count && !dframe->glyph_insts.count - && !dframe->line_verts.count) { + if (!dframe->quad_verts.count && !dframe->slice_insts.count + && !dframe->glyph_insts.count && !dframe->line_verts.count) { return; } @@ -1055,17 +1130,24 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], cmd); VkDeviceMemory memory = dctx->draw_resource[1].memory; + size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; + size_t atom_mask = atom - 1; +#define a(x) (((x) + atom_mask) & ~atom_mask) VkMappedMemoryRange ranges[] = { { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, memory, dframe->quad_offset, - dframe->quad_verts.count * VERTS_PER_QUAD * sizeof (drawvert_t) }, + a(dframe->quad_verts.count * VERTS_PER_QUAD * sizeof (drawvert_t)) }, + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + memory, dframe->slice_offset, + a(dframe->slice_insts.count * sizeof (sliceinst_t)) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, memory, dframe->glyph_offset, - dframe->glyph_insts.count * VERTS_PER_QUAD * sizeof (drawvert_t) }, + a(dframe->glyph_insts.count * sizeof (glyphinst_t)) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, memory, dframe->line_offset, - dframe->line_verts.count * VERTS_PER_LINE * sizeof (drawvert_t) }, + a(dframe->line_verts.count * VERTS_PER_LINE * sizeof (drawvert_t)) }, }; +#undef a dfunc->vkFlushMappedMemoryRanges (device->dev, 3, ranges); dfunc->vkResetCommandBuffer (cmd, 0); @@ -1086,7 +1168,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) if (dframe->quad_verts.count) { VkBuffer quad_buffer = dframe->quad_buffer; - VkBuffer ind_buffer = dctx->quad_objects[0].buffer.buffer; + VkBuffer ind_buffer = dctx->ind_objects[0].buffer.buffer; VkDeviceSize offsets[] = {0}; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &quad_buffer, offsets); dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); @@ -1106,6 +1188,36 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) 1, 0, 0, 0); } + if (dframe->slice_insts.count) { + VkBuffer slice_buffer = dframe->slice_buffer; + VkBuffer ind_buffer = dctx->ind_objects[1].buffer.buffer; + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &slice_buffer, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + dctx->slice_pipeline); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); + + uint32_t inst_start = 0; + for (size_t i = 0; i < dframe->slice_batch.size; i++) { + int fontid = dframe->slice_batch.a[i].descid; + uint32_t inst_count = dframe->slice_batch.a[i].count; + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + dctx->fonts.a[fontid].set, + }; + VkPipelineLayout layout = dctx->glyph_layout; + dfunc->vkCmdBindDescriptorSets (cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + + dfunc->vkCmdDrawIndexed (cmd, 26, inst_count, 0, 0, inst_start); + inst_start += inst_count; + } + DARRAY_RESIZE (&dframe->slice_batch, 0); + } + if (dframe->glyph_insts.count) { VkBuffer glyph_buffer = dframe->glyph_buffer; VkDeviceSize offsets[] = {0}; @@ -1155,6 +1267,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dfunc->vkEndCommandBuffer (cmd); dframe->quad_verts.count = 0; + dframe->slice_insts.count = 0; dframe->glyph_insts.count = 0; dframe->line_verts.count = 0; } From 2a1255de596772dd81db1f37f1eb50a4db35ebd5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Nov 2022 11:11:38 +0900 Subject: [PATCH 3218/3664] [renderer] Make cross hair data easier to see in code It is rather hard to pick out an image from a mass of 0xff and 0xfe. --- libs/video/renderer/crosshair.c | 68 +++++++++++++++++---------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/libs/video/renderer/crosshair.c b/libs/video/renderer/crosshair.c index 7870c7aad..60b237a1b 100644 --- a/libs/video/renderer/crosshair.c +++ b/libs/video/renderer/crosshair.c @@ -35,46 +35,50 @@ #include "r_internal.h" +#define _ 0xff +#define X 0xfe // NOTE: this array is INCORRECT for direct uploading in GL // but is optimal for SW byte crosshair_data[CROSSHAIR_WIDTH * CROSSHAIR_HEIGHT * CROSSHAIR_COUNT] = { - 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + _,_,_,X,_,_,_,_, + _,_,_,_,_,_,_,_, + _,_,_,X,_,_,_,_, + X,_,X,_,X,_,X,_, + _,_,_,X,_,_,_,_, + _,_,_,_,_,_,_,_, + _,_,_,X,_,_,_,_, + _,_,_,_,_,_,_,_, - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, - 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + X,_,_,_,_,_,X,_, + _,X,_,_,_,X,_,_, + _,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_, + _,_,_,_,_,_,_,_, + _,X,_,_,_,X,_,_, + X,_,_,_,_,_,X,_, + _,_,_,_,_,_,_,_, //From FitzQuake - 255,255,255,255,255,255,255,255, - 255,255,255, 8, 9,255,255,255, - 255,255,255, 6, 8, 2,255,255, - 255, 6, 8, 8, 6, 8, 8,255, - 255,255, 2, 8, 8, 2, 2, 2, - 255,255,255, 7, 8, 2,255,255, - 255,255,255,255, 2, 2,255,255, - 255,255,255,255,255,255,255,255, + _,_,_,_,_,_,_,_, + _,_,_,8,9,_,_,_, + _,_,_,6,8,2,_,_, + _,6,8,8,6,8,8,_, + _,_,2,8,8,2,2,2, + _,_,_,7,8,2,_,_, + _,_,_,_,2,2,_,_, + _,_,_,_,_,_,_,_, - 0xff,0xff,0xfe,0xfe,0xfe,0xff,0xff,0xff, - 0xff,0xfe,0xff,0xff,0xff,0xfe,0xff,0xff, - 0xfe,0xff,0xff,0xff,0xff,0xff,0xfe,0xff, - 0xfe,0xff,0xff,0xfe,0xff,0xff,0xfe,0xff, - 0xfe,0xff,0xff,0xff,0xff,0xff,0xfe,0xff, - 0xff,0xfe,0xff,0xff,0xff,0xfe,0xff,0xff, - 0xff,0xff,0xfe,0xfe,0xfe,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + _,_,X,X,X,_,_,_, + _,X,_,_,_,X,_,_, + X,_,_,_,_,_,X,_, + X,_,_,X,_,_,X,_, + X,_,_,_,_,_,X,_, + _,X,_,_,_,X,_,_, + _,_,X,X,X,_,_,_, + _,_,_,_,_,_,_,_, }; +#undef _ +#undef X qpic_t * Draw_CrosshairPic (void) From ae200e4e40f2635090ee92a4a2ba9e0c01a9f521 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 18 Nov 2022 11:23:32 +0900 Subject: [PATCH 3219/3664] [renderer] Compensate for scale in cross-hair placement I was wondering where it had gone (south east, actually). --- libs/video/renderer/gl/gl_draw.c | 5 +++-- libs/video/renderer/glsl/glsl_draw.c | 5 +++-- libs/video/renderer/vulkan/vulkan_draw.c | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index bd7d3b38d..f46e9fc0d 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -711,8 +711,9 @@ gl_Draw_Crosshair (void) if ((unsigned) ch >= sizeof (crosshair_func) / sizeof (crosshair_func[0])) return; - x = vid.width / 2 + cl_crossx; - y = vid.height / 2 + cl_crossy; + int s = 2 * gl_2d_scale; + x = vid.width / s + cl_crossx; + y = vid.height / s + cl_crossy; crosshair_func[ch] (x, y); } diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index ab4067746..6e3938c8c 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -614,9 +614,10 @@ void glsl_Draw_Crosshair (void) { int x, y; + int s = 2 * glsl_2d_scale; - x = vid.width / 2 + cl_crossx; - y = vid.height / 2 + cl_crossy; + x = vid.width / s + cl_crossx; + y = vid.height / s + cl_crossy; glsl_Draw_CrosshairAt (crosshair, x, y); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 1973d8a4b..ff343fb99 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -852,9 +852,10 @@ void Vulkan_Draw_Crosshair (vulkan_ctx_t *ctx) { int x, y; + int s = 2 * ctx->twod_scale; - x = vid.width / 2 + cl_crossx; - y = vid.height / 2 + cl_crossy; + x = vid.width / s + cl_crossx; + y = vid.height / s + cl_crossy; Vulkan_Draw_CrosshairAt (crosshair, x, y, ctx); } From b59505b7c1bcf5ae06e92c369f0eabeb68c818ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Nov 2022 00:41:52 +0900 Subject: [PATCH 3220/3664] [glsl] Remove glpic_t struct It hasn't been necessary for a long time and is a tad misleading as all it does is wrap a pointer to subpic_t. --- libs/video/renderer/glsl/glsl_draw.c | 35 +++++++--------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 6e3938c8c..df58b11ca 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -55,10 +55,6 @@ #include "r_internal.h" -typedef struct { - subpic_t *subpic; -} glpic_t; - typedef struct cachepic_s { struct cachepic_s *next; char *name; @@ -126,16 +122,14 @@ static qpic_t * make_glpic (const char *name, qpic_t *p) { qpic_t *pic = 0; - glpic_t *gl; if (p) { - // FIXME is alignment ok? - pic = malloc (sizeof (qpic_t) + sizeof (glpic_t)); + pic = malloc (sizeof (qpic_t) + sizeof (subpic_t *)); pic->width = p->width; pic->height = p->height; - gl = (glpic_t *) pic->data; - gl->subpic = GLSL_ScrapSubpic (draw_scrap, pic->width, pic->height); - GLSL_SubpicUpdate (gl->subpic, p->data, 1); + subpic_t *sp = GLSL_ScrapSubpic (draw_scrap, pic->width, pic->height); + *(subpic_t **) pic->data = sp; + GLSL_SubpicUpdate (sp, p->data, 1); } return pic; } @@ -143,9 +137,9 @@ make_glpic (const char *name, qpic_t *p) static void pic_free (qpic_t *pic) { - glpic_t *gl = (glpic_t *) pic->data; + subpic_t *subpic = *(subpic_t **) pic->data; - GLSL_SubpicDelete (gl->subpic); + GLSL_SubpicDelete (subpic); free (pic); } @@ -196,13 +190,9 @@ make_quad (qpic_t *pic, float x, float y, int w, int h, int srcx, int srcy, int srcw, int srch, drawvert_t verts[6], float *color) { - glpic_t *gl; - subpic_t *sp; + subpic_t *sp = *(subpic_t **) pic->data; float sl, sh, tl, th; - gl = (glpic_t *) pic->data; - sp = gl->subpic; - srcx += sp->rect->x; srcy += sp->rect->y; sl = (srcx) * sp->size; @@ -381,7 +371,6 @@ glsl_Draw_Init (void) int i; int frag, vert; qpic_t *pic; - //FIXME glpic_t *gl; pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, 0, 0); QFS_GamedirCallback (Draw_ClearCache, 0); @@ -444,10 +433,6 @@ glsl_Draw_Init (void) if (!backtile_pic) { backtile_pic = white_pic; } - //FIXME gl = (glpic_t *) backtile_pic->data; - //FIXME qfeglBindTexture (GL_TEXTURE_2D, gl->texnum); - //FIXME qfeglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - //FIXME qfeglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); Cvar_Register (&glsl_conback_texnum_cvar, 0, 0); } @@ -689,8 +674,7 @@ glsl_Draw_TileClear (int x, int y, int w, int h) static quat_t color = { 1, 1, 1, 1 }; vrect_t *tile_rect = VRect_New (x, y, w, h); vrect_t *sub = VRect_New (0, 0, 0, 0); // filled in later; - glpic_t *gl = (glpic_t *) backtile_pic->data; - subpic_t *sp = gl->subpic; + subpic_t *sp = *(subpic_t **) backtile_pic->data; int sub_sx, sub_sy, sub_ex, sub_ey; int i, j; @@ -731,8 +715,7 @@ glsl_Draw_Fill (int x, int y, int w, int h, int c) void glsl_Draw_Line (int x0, int y0, int x1, int y1, int c) { - glpic_t *gl = (glpic_t *) white_pic->data; - subpic_t *sp = gl->subpic; + subpic_t *sp = *(subpic_t **) white_pic->data; float sl = sp->rect->x * sp->size; float sh = sp->rect->x * sp->size; float tl = sp->rect->y * sp->size; From 2a8c12426d7ad05ca70a4b1b1a065ba19234a710 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Nov 2022 14:06:24 +0900 Subject: [PATCH 3221/3664] [sw] Ensure the view model has a visibility component The rest of the system won't add one automatically (since entity creation no longer does), but the alias and iqm rendering code expect there to be one. Fixes a segfault when starting a scene (demo etc). --- libs/video/renderer/sw/sw_rmain.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 1a2d3a9e9..b97c798a1 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -386,6 +386,13 @@ R_DrawViewModel (void) if (!renderer->model) return; + if (!Ent_HasComponent (viewent.id, scene_visibility, viewent.reg)) { + // ensure the view model has a visibility component because one won't + // be added automatically, and the model rendering code expects there + // to be one + Ent_SetComponent (viewent.id, scene_visibility, viewent.reg, 0); + } + transform_t transform = Entity_Transform (viewent); VectorCopy (Transform_GetWorldPosition (transform), r_entorigin); From d283f0789099ee9ade4c6d07f73dbb0c5ef0e950 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Nov 2022 20:49:13 +0900 Subject: [PATCH 3222/3664] [qfvis] Replace modulo and SISD cross-product At least modern gcc produces nice code for ?: (cmov), and a SIMD cross-product uses several fewer instructions. The cross-product shaved off 0.5-1s, but the modulo -> ?: shaved off about 3-4s, for a total of about 10% speedup (1.09 insn/cyc vs 1.01 insn/cyc, so even perf agrees). --- tools/qfvis/source/flow.c | 17 ++++++----------- tools/qfvis/source/qfvis.c | 4 ++-- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 93ee0ec96..35cab6727 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -139,16 +139,11 @@ calc_plane (vec4f_t v1, vec4f_t v2, int flip, vec4f_t p, vec4f_t *plane) if (flip < 0) { //CrossProduct (v2, v1, plane.normal); - (*plane)[0] = v2[1] * v1[2] - v2[2] * v1[1]; - (*plane)[1] = v2[2] * v1[0] - v2[0] * v1[2]; - (*plane)[2] = v2[0] * v1[1] - v2[1] * v1[0]; + *plane = crossf (v2, v1); } else { //CrossProduct (v1, v2, plane.normal); - (*plane)[0] = v1[1] * v2[2] - v1[2] * v2[1]; - (*plane)[1] = v1[2] * v2[0] - v1[0] * v2[2]; - (*plane)[2] = v1[0] * v2[1] - v1[1] * v2[0]; + *plane = crossf (v1, v2); } - (*plane)[3] = 0; length = dotf (*plane, *plane); @@ -162,16 +157,16 @@ calc_plane (vec4f_t v1, vec4f_t v2, int flip, vec4f_t p, vec4f_t *plane) } static inline int -test_plane (vec4f_t plane, const winding_t *pass, int index) +test_plane (vec4f_t plane, const winding_t *pass, unsigned index) { int s1, s2; int k; vec4f_t d; - k = (index + 1) % pass->numpoints; + k = index + 1 == pass->numpoints ? 0 : index + 1; d = dotf (pass->points[k], plane); s1 = test_zero (d[0]); - k = (index + pass->numpoints - 1) % pass->numpoints; + k = (index == 0 ? pass->numpoints : index) - 1; d = dotf (pass->points[k], plane); s2 = test_zero (d[0]); if (s1 == 0 && s2 == 0) @@ -239,7 +234,7 @@ FindSeparators (threaddata_t *thread, sep_t *separators = 0, *sep; for (i = 0; i < source->numpoints; i++) { - l = (i + 1) % source->numpoints; + l = (i + 1) == source->numpoints ? 0 : i + 1; v1 = source->points[l] - source->points[i]; for (j = 0; j < pass->numpoints; j++) { diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index f05b108b8..2e64e9a0d 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -372,8 +372,8 @@ ClipWinding (threaddata_t *thread, winding_t *in, vec4f_t split, if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) { continue; } - vec4f_t mid = split_edge (in->points, dists, i, - (i + 1) % in->numpoints, split); + unsigned j = (i + 1) == in->numpoints ? 0 : i + 1; + vec4f_t mid = split_edge (in->points, dists, i, j, split); neww->points[neww->numpoints++] = mid; } From 1cada2c931c1b3bfe10ccf5850bdb6866db95d87 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 19 Nov 2022 23:16:47 +0900 Subject: [PATCH 3223/3664] [qfvis] Remove (mostly) unnecessary vector normalization Because of the way the plane normal is used (front/on/back checks, and midpoint calculation), other than possible precision, there is no need to normalize the normal. Removing the square root and division resulted in a huge boost: from 34s to 14 seconds. The average clusters visible hasn't change much, and a quick check in-game didn't show any issues. --- tools/qfvis/source/flow.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/qfvis/source/flow.c b/tools/qfvis/source/flow.c index 35cab6727..5bc36edf4 100644 --- a/tools/qfvis/source/flow.c +++ b/tools/qfvis/source/flow.c @@ -151,7 +151,6 @@ calc_plane (vec4f_t v1, vec4f_t v2, int flip, vec4f_t p, vec4f_t *plane) if (length[0] < ON_EPSILON) return 0; - *plane /= vsqrt4f (length); (*plane)[3] = -dotf (p, *plane)[0]; return 1; } From 7e442a9019e16d7287e3ef28cc9254f1ebc953f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Nov 2022 00:50:59 +0900 Subject: [PATCH 3224/3664] [renderer] Correct crosshair sizes I'm pretty sure they're meant to be 8x8 and not 16x16. Certainly they're a tad large at 16x16 when using scaled 2d. --- libs/video/renderer/gl/gl_draw.c | 32 ++++++++++++------------ libs/video/renderer/glsl/glsl_draw.c | 4 +-- libs/video/renderer/vulkan/vulkan_draw.c | 4 +-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index f46e9fc0d..d72673468 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -609,13 +609,13 @@ crosshair_2 (int x, int y) qfglBegin (GL_QUADS); qfglTexCoord2f (0, 0); - qfglVertex2f (x - 7, y - 7); + qfglVertex2f (x - 3, y - 3); qfglTexCoord2f (0.5, 0); - qfglVertex2f (x + 9, y - 7); + qfglVertex2f (x + 5, y - 3); qfglTexCoord2f (0.5, 0.5); - qfglVertex2f (x + 9, y + 9); + qfglVertex2f (x + 5, y + 5); qfglTexCoord2f (0, 0.5); - qfglVertex2f (x - 7, y + 9); + qfglVertex2f (x - 3, y + 5); qfglEnd (); qfglColor3ubv (color_white); @@ -633,13 +633,13 @@ crosshair_3 (int x, int y) qfglBegin (GL_QUADS); qfglTexCoord2f (0.5, 0); - qfglVertex2f (x - 7, y - 7); + qfglVertex2f (x - 3, y - 3); qfglTexCoord2f (1, 0); - qfglVertex2f (x + 9, y - 7); + qfglVertex2f (x + 5, y - 3); qfglTexCoord2f (1, 0.5); - qfglVertex2f (x + 9, y + 9); + qfglVertex2f (x + 5, y + 5); qfglTexCoord2f (0.5, 0.5); - qfglVertex2f (x - 7, y + 9); + qfglVertex2f (x - 3, y + 5); qfglEnd (); qfglColor3ubv (color_white); @@ -657,13 +657,13 @@ crosshair_4 (int x, int y) qfglBegin (GL_QUADS); qfglTexCoord2f (0, 0.5); - qfglVertex2f (x - 7, y - 7); + qfglVertex2f (x - 3, y - 3); qfglTexCoord2f (0.5, 0.5); - qfglVertex2f (x + 9, y - 7); + qfglVertex2f (x + 5, y - 5); qfglTexCoord2f (0.5, 1); - qfglVertex2f (x + 9, y + 9); + qfglVertex2f (x + 5, y + 5); qfglTexCoord2f (0, 1); - qfglVertex2f (x - 7, y + 9); + qfglVertex2f (x - 3, y + 5); qfglEnd (); qfglColor3ubv (color_white); @@ -681,13 +681,13 @@ crosshair_5 (int x, int y) //FIXME don't use until the data is filled in qfglBegin (GL_QUADS); qfglTexCoord2f (0.5, 0.5); - qfglVertex2f (x - 7, y - 7); + qfglVertex2f (x - 3, y - 3); qfglTexCoord2f (1, 0.5); - qfglVertex2f (x + 9, y - 7); + qfglVertex2f (x + 5, y - 3); qfglTexCoord2f (1, 1); - qfglVertex2f (x + 9, y + 9); + qfglVertex2f (x + 5, y + 5); qfglTexCoord2f (0.5, 1); - qfglVertex2f (x - 7, y + 9); + qfglVertex2f (x - 3, y + 5); qfglEnd (); qfglColor3ubv (color_white); diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index df58b11ca..9b2607df4 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -571,8 +571,8 @@ draw_crosshair_pic (int ch, int x, int y) }; const int *p = pos[ch - 1]; - draw_pic (x - CROSSHAIR_WIDTH + 1, y - CROSSHAIR_HEIGHT + 1, - CROSSHAIR_WIDTH * 2, CROSSHAIR_HEIGHT * 2, crosshair_pic, + draw_pic (x - CROSSHAIR_WIDTH / 2 + 1, y - CROSSHAIR_HEIGHT / 2 + 1, + CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT, crosshair_pic, p[0], p[1], p[2], p[3], crosshair_color); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index ff343fb99..1efbf92ed 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -824,8 +824,8 @@ draw_crosshair_pic (int ch, int x, int y, vulkan_ctx_t *ctx) const int *p = pos[ch - 1]; subpic_t *subpic = *(subpic_t **) dctx->crosshair->data; - draw_pic (x - CROSSHAIR_WIDTH + 1, y - CROSSHAIR_HEIGHT + 1, - CROSSHAIR_WIDTH * 2, CROSSHAIR_HEIGHT * 2, subpic, + draw_pic (x - CROSSHAIR_WIDTH / 2 + 1, y - CROSSHAIR_HEIGHT / 2 + 1, + CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT, subpic, p[0], p[1], p[2], p[3], crosshair_color, &frame->quad_verts); } From e0b9e118a019c35b12bd7e15b6cb73adf8937c95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Nov 2022 01:17:09 +0900 Subject: [PATCH 3225/3664] [renderer] Remove the 1/2 pixel shift of the 2d screen It seemed like a good idea at the time, but it exacerbates pixel leakage in atlas textures that have no border pixels (even in nearest sampling modes). --- libs/video/renderer/gl/gl_draw.c | 2 +- libs/video/renderer/glsl/glsl_draw.c | 3 +-- libs/video/renderer/vid_render_vulkan.c | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index d72673468..2ccf8a7c4 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -971,7 +971,7 @@ set_2d (int width, int height) qfglMatrixMode (GL_PROJECTION); qfglLoadIdentity (); - qfglOrtho (-0.5, width - 0.5, height - 0.5, -0.5, -99999, 99999); + qfglOrtho (0, width, height, 0, -99999, 99999); qfglMatrixMode (GL_MODELVIEW); qfglLoadIdentity (); diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 9b2607df4..b6e7e797c 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -785,8 +785,7 @@ set_2d (int width, int height) qfeglDisable (GL_DEPTH_TEST); qfeglDisable (GL_CULL_FACE); - ortho_mat (proj_matrix, -0.5, width - 0.5, height - 0.5, -0.5, - -99999, 99999); + ortho_mat (proj_matrix, 0, width, height, 0, -99999, 99999); qfeglUseProgram (quake_2d.program); qfeglEnableVertexAttribArray (quake_2d.vertex.location); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 5e7c06d04..7c9761bac 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -369,8 +369,8 @@ vulkan_set_2d (int scaled) __auto_type mat = &mctx->matrices; int scale = vulkan_ctx->twod_scale; - float left = -0.5; - float top = -0.5; + float left = 0; + float top = 0; float right = left + vid.width / scale; float bottom = top + vid.height / scale; QFV_Orthographic (mat->Projection2d, left, right, top, bottom, 0, 99999); From 4ff3ca104d9089cd480a9707d0782275d4e7e797 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Nov 2022 01:21:45 +0900 Subject: [PATCH 3226/3664] [gl] Make conchars use nearest sampling Linear sampling in a texture atlas (which is what conchars is) requires the use of border pixels to avoid pixel leakage. --- libs/video/renderer/gl/gl_draw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 2ccf8a7c4..98f47f6ca 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -392,6 +392,8 @@ gl_Draw_Init (void) width = 128; height = 128; } + qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qfglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // initialize the character cell texture coordinates. for (i = 0; i < 256; i++) { From 4cbacc11499b0ff7a98dd1bfd986f8d0d0d60806 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Nov 2022 01:26:14 +0900 Subject: [PATCH 3227/3664] [vulkan] Remove the pic texel offsets It turns out that nearest filtering doesn't need any offsets to avoid texel leaks so long as the screen isn't also offset. With this, the 2d rendering looks good at any scale (minus the inherent blockiness). --- libs/video/renderer/vulkan/vulkan_draw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 1efbf92ed..77e673664 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -667,10 +667,10 @@ draw_pic (float x, float y, int w, int h, subpic_t *subpic, srcy += subpic->rect->y; float size = subpic->size; - float sl = (srcx + 0.03125) * size; - float sr = (srcx + srcw - 0.03125) * size; - float st = (srcy + 0.03125) * size; - float sb = (srcy + srch - 0.03125) * size; + float sl = srcx * size; + float sr = (srcx + srcw) * size; + float st = srcy * size; + float sb = (srcy + srch) * size; verts[0].xy[0] = x; verts[0].xy[1] = y; From 534d5367dea7203721304d796b2ab2e4d2dbff6c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Nov 2022 03:59:01 +0900 Subject: [PATCH 3228/3664] [vulkan] Use linear sampling for glyphs This requires having padding around the glyphs to avoid texel leak, but as the atlas is created at runtime, it's possible to get the padding in. --- libs/video/renderer/r_font.c | 12 ++++++++--- libs/video/renderer/r_progs.c | 9 ++++++++ libs/video/renderer/vulkan/qfpipeline.plist | 17 +++++++++++++++ libs/video/renderer/vulkan/vulkan_draw.c | 24 +++++++++++---------- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/libs/video/renderer/r_font.c b/libs/video/renderer/r_font.c index f667491bd..08131ac74 100644 --- a/libs/video/renderer/r_font.c +++ b/libs/video/renderer/r_font.c @@ -102,7 +102,8 @@ R_FontLoad (QFile *font_file, int size) FT_Load_Glyph (font->face, gind, FT_LOAD_DEFAULT); __auto_type g = font->face->glyph; - pixels += g->bitmap.width * g->bitmap.rows; + // include padding around the glyph to avoid texel leaks + pixels += (g->bitmap.width + 1) * (g->bitmap.rows + 1); } pixels = sqrt (5 * pixels / 4); pixels = BITOP_RUP (pixels); @@ -118,10 +119,15 @@ R_FontLoad (QFile *font_file, int size) FT_Load_Glyph (font->face, gind, FT_LOAD_DEFAULT); __auto_type slot = font->face->glyph; FT_Render_Glyph (slot, FT_RENDER_MODE_NORMAL); - int width = slot->bitmap.width; - int height = slot->bitmap.rows; + // add padding to create a buffer around the glyph to prevent texel + // leaks + int width = slot->bitmap.width + 1; + int height = slot->bitmap.rows + 1; *rect = *R_ScrapAlloc (&font->scrap, width, height); *bearing = (vec2i_t) { slot->bitmap_left, slot->bitmap_top }; + // shrink the rect so as to NOT include the padding + rect->width -= 1; + rect->height -= 1; copy_glyph (rect, slot, font); } diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 9c00c35f9..054629d7a 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -474,6 +474,12 @@ bi_Draw_PrintBuffer (progs_t *pr, void *_res) Draw_PrintBuffer (cbuff->buffer, str); } +static void +bi_Draw_SetScale (progs_t *pr, void *_res) +{ + Draw_SetScale (P_INT (pr, 0)); +} + static const char * bi_draw_get_key (const void *p, void *unused) { @@ -540,6 +546,9 @@ static builtin_t builtins[] = { bi(Draw_ScrollBuffer, 2, p(ptr), p(int)), bi(Draw_CharBuffer, 3, p(int), p(int), p(ptr)), bi(Draw_PrintBuffer, 2, p(ptr), p(string)), + + bi(Draw_SetScale, 1, p(int)), + {0} }; diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 8ae2927d0..4945613c5 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -23,6 +23,23 @@ borderColor = float_transparent_black; unnormalizedCoordinates = false; }; + glyph = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 0; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; palette_sampler = { magFilter = nearest; minFilter = nearest; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 77e673664..c8f13da03 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -168,7 +168,8 @@ typedef struct drawfontset_s DARRAY_TYPE (drawfont_t) drawfontset_t; typedef struct drawctx_s { - VkSampler sampler; + VkSampler pic_sampler; + VkSampler glyph_sampler; scrap_t *scrap; qfv_stagebuf_t *stage; qpic_t *crosshair; @@ -576,7 +577,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) ctx->cmdpool); dctx->scrap = QFV_CreateScrap (device, "draw_atlas", 2048, tex_rgba, dctx->stage); - dctx->sampler = Vulkan_CreateSampler (ctx, "quakepic"); + dctx->pic_sampler = Vulkan_CreateSampler (ctx, "quakepic"); + dctx->glyph_sampler = Vulkan_CreateSampler (ctx, "glyph"); draw_chars = W_GetLumpName ("conchars"); if (draw_chars) { @@ -623,7 +625,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "twod_pool"); VkDescriptorImageInfo imageInfo = { - dctx->sampler, + dctx->pic_sampler, QFV_ScrapImageView (dctx->scrap), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; @@ -1369,20 +1371,20 @@ Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx) float s = 1.0 / rfont->scrap.width; float t = 1.0 / rfont->scrap.height; verts[i * 4 + 0] = (glyphvert_t) { - .offset = { x + 0, y + 0 }, - .uv = {(u + 0.25) * s, (v + 0.25) * t }, + .offset = { x, y }, + .uv = { u * s, v * t }, }; verts[i * 4 + 1] = (glyphvert_t) { - .offset = { x + 0, y + h }, - .uv = {(u + 0.25) * s, (v + h - 0.25) * t }, + .offset = { x, y + h }, + .uv = { u * s, (v + h) * t }, }; verts[i * 4 + 2] = (glyphvert_t) { - .offset = { x + w, y + 0 }, - .uv = {(u + w - 0.25) * s, (v + 0.25) * t }, + .offset = { x + w, y }, + .uv = {(u + w) * s, v * t }, }; verts[i * 4 + 3] = (glyphvert_t) { .offset = { x + w, y + h }, - .uv = {(u + w - 0.25) * s, (v + h - 0.25) * t }, + .uv = {(u + w) * s, (v + h) * t }, }; } QFV_PacketCopyBuffer (packet, glyph_data->buffer.buffer, @@ -1403,7 +1405,7 @@ Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx) __auto_type glyph_sets = QFV_AllocateDescriptorSet (device, pool, layouts); font->set = glyph_sets->a[0]; VkDescriptorImageInfo imageInfo = { - dctx->sampler, + dctx->glyph_sampler, glyph_iview->image_view.view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; From 40b319bf4280b9ffdda8ec6ca21c57516e2cf638 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Nov 2022 15:31:23 +0900 Subject: [PATCH 3229/3664] [vulkan] Support swizzles in resource image views Using swizzles in an image view allows the same shader to be used with different image "types" (eg, color vs coverage). Of course, this needed to abandon QFV_CreateImageView, but that is likely for the best. --- include/QF/Vulkan/resource.h | 1 + libs/video/renderer/vulkan/resource.c | 34 ++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/include/QF/Vulkan/resource.h b/include/QF/Vulkan/resource.h index 872b52787..ac47d0609 100644 --- a/include/QF/Vulkan/resource.h +++ b/include/QF/Vulkan/resource.h @@ -47,6 +47,7 @@ typedef struct qfv_resobj_s { VkImageViewType type; VkFormat format; VkImageAspectFlags aspect; + VkComponentMapping components; VkImageView view; } image_view; }; diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index 7562c1151..029081f71 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -57,6 +57,33 @@ create_image (qfv_device_t *device, qfv_resobj_t *image_obj) dfunc->vkCreateImage (device->dev, &createInfo, 0, &image->image); } +static void +create_image_view (qfv_device_t *device, qfv_resobj_t *imgview_obj, + qfv_resobj_t *imgobj) +{ + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type view = &imgview_obj->image_view; + __auto_type image = &imgobj->image; + + VkImageViewCreateInfo createInfo = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0, + //FIXME flags should be input for both image and image view + .flags = image->cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, + .image = image->image, + .viewType = view->type, + .format = view->format, + .components = view->components, + .subresourceRange = { + .aspectMask = view->aspect, + .baseMipLevel = 0, + .levelCount = VK_REMAINING_MIP_LEVELS, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, + }; + dfunc->vkCreateImageView (device->dev, &createInfo, 0, &view->view); +} + int QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) { @@ -221,12 +248,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) { __auto_type imgview = &obj->image_view; __auto_type imgobj = &resource->objects[imgview->image]; - __auto_type image = &imgobj->image; - imgview->view = QFV_CreateImageView (device, - image->image, - imgview->type, - imgview->format, - imgview->aspect); + create_image_view (device, obj, imgobj); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, imgview->view, va (resource->va_ctx, "iview:%s:%s", From 2828a4ce0c1aa7760dd6f10e0eb3b75313f01cae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 20 Nov 2022 15:46:16 +0900 Subject: [PATCH 3230/3664] [vulkan] Use a swizzle view for coverage-alpha And thus a single pipeline for either colored glyphs or coverage-alpha glyphs, making for better batching when I get to that. --- libs/video/renderer/Makemodule.am | 20 ++++++++----------- libs/video/renderer/vulkan/qfpipeline.plist | 20 +++++-------------- libs/video/renderer/vulkan/shader.c | 7 ++----- .../shader/{glyph_color.frag => glyph.frag} | 0 .../vulkan/shader/glyph_coverage.frag | 17 ---------------- libs/video/renderer/vulkan/vulkan_draw.c | 15 +++++++++----- 6 files changed, 25 insertions(+), 54 deletions(-) rename libs/video/renderer/vulkan/shader/{glyph_color.frag => glyph.frag} (100%) delete mode 100644 libs/video/renderer/vulkan/shader/glyph_coverage.frag diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 245989153..0a2f1f0dc 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -277,12 +277,10 @@ vkshaderpath = libs/video/renderer/vulkan/shader slice_src = $(vkshaderpath)/slice.vert slice_c = $(vkshaderpath)/slice.vert.spvc -glyph_src = $(vkshaderpath)/glyph.vert -glyph_c = $(vkshaderpath)/glyph.vert.spvc -glyph_color_src = $(vkshaderpath)/glyph_color.frag -glyph_color_c = $(vkshaderpath)/glyph_color.frag.spvc -glyph_coverage_src = $(vkshaderpath)/glyph_coverage.frag -glyph_coverage_c = $(vkshaderpath)/glyph_coverage.frag.spvc +glyphv_src = $(vkshaderpath)/glyph.vert +glyphv_c = $(vkshaderpath)/glyph.vert.spvc +glyphf_src = $(vkshaderpath)/glyph.frag +glyphf_c = $(vkshaderpath)/glyph.frag.spvc linev_src = $(vkshaderpath)/line.vert linev_c = $(vkshaderpath)/line.vert.spvc linef_src = $(vkshaderpath)/line.frag @@ -355,9 +353,8 @@ pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc $(slice_vert_c): $(slice_vert_src) -$(glyph_vert_c): $(glyph_vert_src) -$(glyph_color_c): $(glyph_color_src) -$(glyph_coverage_c): $(glyph_coverage_src) +$(glyphv_c): $(glyphv_src) +$(glyphf_c): $(glyphf_src) $(linev_c): $(linev_src) $(linef_c): $(linef_src) @@ -424,9 +421,8 @@ $(pushcolor_c): $(pushcolor_src) vkshader_c = \ $(slice_c) \ - $(glyph_c) \ - $(glyph_color_c) \ - $(glyph_coverage_c) \ + $(glyphv_c) \ + $(glyphf_c) \ $(linev_c) \ $(linef_c) \ $(partphysicsc_c) \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 4945613c5..555b2d024 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -1151,7 +1151,7 @@ @inherit = $properties.pipelines.trans_base;//FIXME should be sparate stages = ( { stage = vertex; name = main; module = $builtin/slice.vert; }, - { stage = fragment; name = main; module = $builtin/glyph_color.frag; }, + { stage = fragment; name = main; module = $builtin/glyph.frag; }, ); vertexInput = $properties.vertexInput.slice; inputAssembly = { @@ -1168,6 +1168,10 @@ }; glyph = { @inherit = $properties.pipelines.trans_base;//FIXME should be sparate + stages = ( + { stage = vertex; name = main; module = $builtin/glyph.vert; }, + { stage = fragment; name = main; module = $builtin/glyph.frag; }, + ); vertexInput = $properties.vertexInput.glyph; inputAssembly = { // glyphs are drawn using instanced quads, so primitive restart @@ -1182,20 +1186,6 @@ }; layout = glyph_layout; }; - glyph_color = { - @inherit = $properties.pipelines.glyph; - stages = ( - { stage = vertex; name = main; module = $builtin/glyph.vert; }, - { stage = fragment; name = main; module = $builtin/glyph_color.frag; }, - ); - }; - glyph_coverage = { - @inherit = $properties.pipelines.glyph; - stages = ( - { stage = vertex; name = main; module = $builtin/glyph.vert; }, - { stage = fragment; name = main; module = $builtin/glyph_coverage.frag; }, - ); - }; lines = { @inherit = $properties.pipelines.twod; stages = ( diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index be8b0c1eb..1a2699b22 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -43,9 +43,7 @@ static static #include "libs/video/renderer/vulkan/shader/glyph.vert.spvc" static -#include "libs/video/renderer/vulkan/shader/glyph_color.frag.spvc" -static -#include "libs/video/renderer/vulkan/shader/glyph_coverage.frag.spvc" +#include "libs/video/renderer/vulkan/shader/glyph.frag.spvc" static #include "libs/video/renderer/vulkan/shader/line.vert.spvc" static @@ -124,8 +122,7 @@ typedef struct shaderdata_s { static shaderdata_t builtin_shaders[] = { { "slice.vert", slice_vert, sizeof (slice_vert) }, { "glyph.vert", glyph_vert, sizeof (glyph_vert) }, - { "glyph_color.frag", glyph_color_frag, sizeof (glyph_color_frag) }, - { "glyph_coverage.frag", glyph_coverage_frag, sizeof (glyph_coverage_frag) }, + { "glyph.frag", glyph_frag, sizeof (glyph_frag) }, { "line.vert", line_vert, sizeof (line_vert) }, { "line.frag", line_frag, sizeof (line_frag) }, { "particle.vert", particle_vert, sizeof (particle_vert) }, diff --git a/libs/video/renderer/vulkan/shader/glyph_color.frag b/libs/video/renderer/vulkan/shader/glyph.frag similarity index 100% rename from libs/video/renderer/vulkan/shader/glyph_color.frag rename to libs/video/renderer/vulkan/shader/glyph.frag diff --git a/libs/video/renderer/vulkan/shader/glyph_coverage.frag b/libs/video/renderer/vulkan/shader/glyph_coverage.frag deleted file mode 100644 index 526b39dfb..000000000 --- a/libs/video/renderer/vulkan/shader/glyph_coverage.frag +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout (set = 1, binding = 1) uniform sampler2D Texture; - -layout (location = 0) in vec2 uv; -layout (location = 1) in vec4 color; - -layout (location = 0) out vec4 frag_color; - -void -main (void) -{ - vec4 pix; - - pix = texture (Texture, uv).rrrr; - frag_color = pix * color; -} diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index c8f13da03..ac3baf843 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -191,7 +191,7 @@ typedef struct drawctx_s { qfv_resobj_t *line_objects; VkPipeline quad_pipeline; VkPipeline slice_pipeline; - VkPipeline glyph_coverage_pipeline; + VkPipeline glyph_pipeline; VkPipeline line_pipeline; VkPipelineLayout layout; VkPipelineLayout glyph_layout;//slice pipeline uses same layout @@ -538,7 +538,7 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->slice_pipeline, 0); - dfunc->vkDestroyPipeline (device->dev, dctx->glyph_coverage_pipeline, 0); + dfunc->vkDestroyPipeline (device->dev, dctx->glyph_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0); Hash_DelTable (dctx->pic_cache); delete_memsuper (dctx->pic_memsuper); @@ -613,8 +613,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); dctx->slice_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "slice"); - dctx->glyph_coverage_pipeline - = Vulkan_CreateGraphicsPipeline (ctx, "glyph_coverage"); + dctx->glyph_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "glyph"); dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines"); dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout"); @@ -1226,7 +1225,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) VkDeviceSize offsets[] = {0}; dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &glyph_buffer, offsets); dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - dctx->glyph_coverage_pipeline); + dctx->glyph_pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); @@ -1352,6 +1351,12 @@ Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx) .type = VK_IMAGE_VIEW_TYPE_2D, .format = font->resource->glyph_image.image.format, .aspect = VK_IMAGE_ASPECT_COLOR_BIT, + .components = { + .r = VK_COMPONENT_SWIZZLE_R, + .g = VK_COMPONENT_SWIZZLE_R, + .b = VK_COMPONENT_SWIZZLE_R, + .a = VK_COMPONENT_SWIZZLE_R, + }, }, }; __auto_type glyph_iview = &font->resource->glyph_iview; From 82d1a6e6cdf5f5b2d8adbea0325377098167d104 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Nov 2022 02:29:03 +0900 Subject: [PATCH 3231/3664] [vulkan] Do a depth pass for 2d objects While the HUD and status bar don't cut out a lot of screen (normally), they might start to make a difference when I get transparency working properly. The main thing is this is a step towards pulling the 2d rendering into another render pass so the main deferred pass is world-only. --- include/QF/Vulkan/qf_draw.h | 7 + libs/video/renderer/Makemodule.am | 8 +- libs/video/renderer/vulkan/qfpipeline.plist | 24 ++ libs/video/renderer/vulkan/shader.c | 3 + .../renderer/vulkan/shader/twod_depth.frag | 17 + libs/video/renderer/vulkan/vulkan_bsp.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 331 ++++++++++++------ 7 files changed, 273 insertions(+), 119 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/twod_depth.frag diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 1edb16882..05d03e398 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -28,6 +28,13 @@ #ifndef __QF_Vulkan_qf_draw_h #define __QF_Vulkan_qf_draw_h +typedef enum { + QFV_drawDepth, + QFV_draw2d, + + QFV_drawNumPasses +} QFV_DrawSubpass; + struct vulkan_ctx_s; struct qfv_renderframe_s; struct qpic_s; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 0a2f1f0dc..1a4e21c5a 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -303,6 +303,8 @@ sprite_depthv_src = $(vkshaderpath)/sprite_depth.vert sprite_depthv_c = $(vkshaderpath)/sprite_depth.vert.spvc sprite_depthf_src = $(vkshaderpath)/sprite_depth.frag sprite_depthf_c = $(vkshaderpath)/sprite_depth.frag.spvc +twod_depthf_src = $(vkshaderpath)/twod_depth.frag +twod_depthf_c = $(vkshaderpath)/twod_depth.frag.spvc twodv_src = $(vkshaderpath)/twod.vert twodv_c = $(vkshaderpath)/twod.vert.spvc twodf_src = $(vkshaderpath)/twod.frag @@ -373,6 +375,8 @@ $(sprite_depthv_c): $(sprite_depthv_src) $(sprite_depthf_c): $(sprite_depthf_src) +$(twod_depthf_c): $(twod_depthf_src) + $(twodv_c): $(twodv_src) $(twodf_c): $(twodf_src) @@ -434,8 +438,7 @@ vkshader_c = \ $(sprite_gbuff_c) \ $(sprite_depthv_c) \ $(sprite_depthf_c) \ - $(twodv_c) \ - $(twodf_c) \ + $(twod_depthf_c) \ $(quakebspv_c) \ $(quakebspf_c) \ $(bsp_depth_c) \ @@ -526,5 +529,6 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/sprite_depth.frag \ libs/video/renderer/vulkan/shader/sprite_gbuf.vert \ libs/video/renderer/vulkan/shader/sprite_gbuf.frag \ + libs/video/renderer/vulkan/shader/twod_depth.frag \ libs/video/renderer/vulkan/shader/twod.frag \ libs/video/renderer/vulkan/shader/twod.vert diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/qfpipeline.plist index 555b2d024..831def819 100644 --- a/libs/video/renderer/vulkan/qfpipeline.plist +++ b/libs/video/renderer/vulkan/qfpipeline.plist @@ -1124,6 +1124,29 @@ inputAssembly = $properties.inputAssembly.alias; layout = sprite_layout; }; + twod_depth = { + @inherit = $properties.pipelines.depth_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/twod.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/twod_depth.frag; + }, + ); + vertexInput = $properties.vertexInput.twod; + inputAssembly = $properties.inputAssembly.twod; + rasterization = $properties.rasterization.counter_cw_cull_back; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.alpha_blend); + }; + layout = twod_layout; + }; twod = { @inherit = $properties.pipelines.trans_base;//FIXME should be sparate stages = ( @@ -1141,6 +1164,7 @@ vertexInput = $properties.vertexInput.twod; inputAssembly = $properties.inputAssembly.twod; rasterization = $properties.rasterization.counter_cw_cull_back; + depthStencil = $properties.depthStencil.disable; colorBlend = { logicOpEnable = false; attachments = ($properties.attachmentBlendOp.alpha_blend); diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 1a2699b22..dadfb897e 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -67,6 +67,8 @@ static static #include "libs/video/renderer/vulkan/shader/sprite_depth.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/twod_depth.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/twod.vert.spvc" static #include "libs/video/renderer/vulkan/shader/twod.frag.spvc" @@ -134,6 +136,7 @@ static shaderdata_t builtin_shaders[] = { { "sprite_gbuf.frag", sprite_gbuf_frag, sizeof (sprite_gbuf_frag) }, { "sprite_depth.vert", sprite_depth_vert, sizeof (sprite_depth_vert) }, { "sprite_depth.frag", sprite_depth_frag, sizeof (sprite_depth_frag) }, + { "twod_depth.frag", twod_depth_frag, sizeof (twod_depth_frag) }, { "twod.vert", twod_vert, sizeof (twod_vert) }, { "twod.frag", twod_frag, sizeof (twod_frag) }, { "quakebsp.vert", quakebsp_vert, sizeof (quakebsp_vert) }, diff --git a/libs/video/renderer/vulkan/shader/twod_depth.frag b/libs/video/renderer/vulkan/shader/twod_depth.frag new file mode 100644 index 000000000..14afa7412 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/twod_depth.frag @@ -0,0 +1,17 @@ +#version 450 + +layout (set = 1, binding = 0) uniform sampler2D Texture; + +layout (location = 0) in vec2 st; +layout (location = 1) in vec4 color; + +void +main (void) +{ + vec4 pix; + + pix = texture (Texture, st); + if (pix.a * color.a < 1) { + discard; + } +} diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 3158bdbc1..f7ab0656b 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1452,7 +1452,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) for (int j = 0; j < QFV_bspNumPasses; j++) { QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - bframe->cmdSet.a[i], + bframe->cmdSet.a[j], va (ctx->va_ctx, "cmd:bsp:%zd:%s", i, bsp_pass_names[j])); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index ac3baf843..32d8db638 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -73,6 +73,16 @@ #include "r_internal.h" #include "vid_vulkan.h" +static const char * __attribute__((used)) draw_pass_names[] = { + "depth", + "2d", +}; + +static QFV_Subpass subpass_map[] = { + [QFV_drawDepth] = QFV_passDepth, + [QFV_draw2d] = QFV_passTranslucent, +}; + typedef struct descbatch_s { int32_t descid; // texture or font descriptor id uint32_t count; // number of objects in batch @@ -144,7 +154,7 @@ typedef struct drawframe_s { slicequeue_t slice_insts; glyphqueue_t glyph_insts; vertqueue_t line_verts; - VkCommandBuffer cmd; + qfv_cmdbufferset_t cmdSet; } drawframe_t; typedef struct drawframeset_s @@ -189,6 +199,7 @@ typedef struct drawctx_s { qfv_resobj_t *slice_objects; qfv_resobj_t *glyph_objects; qfv_resobj_t *line_objects; + VkPipeline depth_pipeline; VkPipeline quad_pipeline; VkPipeline slice_pipeline; VkPipeline glyph_pipeline; @@ -536,6 +547,7 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) free (dctx->fonts.a[i].resource); } + dfunc->vkDestroyPipeline (device->dev, dctx->depth_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->slice_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->glyph_pipeline, 0); @@ -611,6 +623,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); + dctx->depth_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod_depth"); dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); dctx->slice_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "slice"); dctx->glyph_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "glyph"); @@ -628,8 +641,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) QFV_ScrapImageView (dctx->scrap), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; - __auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); dctx->quad_set = sets->a[0]; @@ -644,10 +655,19 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); for (size_t i = 0; i < frames; i++) { __auto_type dframe = &dctx->frames.a[i]; - dframe->cmd = cmdBuffers->a[i]; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - dframe->cmd, - va (ctx->va_ctx, "cmd:draw:%zd", i)); + + DARRAY_INIT (&dframe->cmdSet, QFV_drawNumPasses); + DARRAY_RESIZE (&dframe->cmdSet, QFV_drawNumPasses); + dframe->cmdSet.grow = 0; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &dframe->cmdSet); + + for (int j = 0; j < QFV_drawNumPasses; j++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + dframe->cmdSet.a[j], + va (ctx->va_ctx, "cmd:draw:%zd:%s", i, + draw_pass_names[j])); + } } qfvPopDebug (ctx); } @@ -1110,6 +1130,171 @@ Vulkan_DrawReset (vulkan_ctx_t *ctx) { } +static void +draw_begin_subpass (QFV_DrawSubpass subpass, qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + drawctx_t *dctx = ctx->draw_context; + __auto_type cframe = &ctx->frames.a[ctx->curFrame]; + drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = dframe->cmdSet.a[subpass]; + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + rFrame->renderpass->renderpass, subpass_map[subpass], + cframe->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "draw:%s", + draw_pass_names[subpass]), + {0.5, 0.8, 0.1, 1}); +} + +static void +draw_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + QFV_duCmdEndLabel (device, cmd); + dfunc->vkEndCommandBuffer (cmd); +} + +static void +bind_pipeline (qfv_renderframe_t *rFrame, VkPipeline pipeline, + VkCommandBuffer cmd) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); +} + +static void +draw_quads (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + drawctx_t *dctx = ctx->draw_context; + drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + + VkBuffer quad_buffer = dframe->quad_buffer; + VkBuffer ind_buffer = dctx->ind_objects[0].buffer.buffer; + + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &quad_buffer, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + dctx->quad_set, + }; + VkPipelineLayout layout = dctx->layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + + dfunc->vkCmdDrawIndexed (cmd, dframe->quad_verts.count * INDS_PER_QUAD, + 1, 0, 0, 0); +} + +static void +draw_slices (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + drawctx_t *dctx = ctx->draw_context; + drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + + VkBuffer slice_buffer = dframe->slice_buffer; + VkBuffer ind_buffer = dctx->ind_objects[1].buffer.buffer; + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &slice_buffer, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); + + uint32_t inst_start = 0; + for (size_t i = 0; i < dframe->slice_batch.size; i++) { + int fontid = dframe->slice_batch.a[i].descid; + uint32_t inst_count = dframe->slice_batch.a[i].count; + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + dctx->fonts.a[fontid].set, + }; + VkPipelineLayout layout = dctx->glyph_layout; + dfunc->vkCmdBindDescriptorSets (cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + + dfunc->vkCmdDrawIndexed (cmd, 26, inst_count, 0, 0, inst_start); + inst_start += inst_count; + } + DARRAY_RESIZE (&dframe->slice_batch, 0); +} + +static void +draw_glyphs (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + drawctx_t *dctx = ctx->draw_context; + drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + + VkBuffer glyph_buffer = dframe->glyph_buffer; + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &glyph_buffer, offsets); + + uint32_t inst_start = 0; + for (size_t i = 0; i < dframe->glyph_batch.size; i++) { + int fontid = dframe->glyph_batch.a[i].descid; + uint32_t inst_count = dframe->glyph_batch.a[i].count; + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + dctx->fonts.a[fontid].set, + }; + VkPipelineLayout layout = dctx->glyph_layout; + dfunc->vkCmdBindDescriptorSets (cmd, + VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + + dfunc->vkCmdDraw (cmd, 4, inst_count, 0, inst_start); + inst_start += inst_count; + } + DARRAY_RESIZE (&dframe->glyph_batch, 0); +} + +static void +draw_lines (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + drawctx_t *dctx = ctx->draw_context; + drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + + VkBuffer line_buffer = dframe->line_buffer; + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &line_buffer, offsets); + VkDescriptorSet set[1] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + }; + VkPipelineLayout layout = dctx->layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 1, set, 0, 0); +} + void Vulkan_FlushText (qfv_renderframe_t *rFrame) { @@ -1118,7 +1303,6 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; @@ -1127,10 +1311,6 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) return; } - VkCommandBuffer cmd = dframe->cmd; - //FIXME which pass? - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], cmd); - VkDeviceMemory memory = dctx->draw_resource[1].memory; size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; size_t atom_mask = atom - 1; @@ -1152,121 +1332,40 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) #undef a dfunc->vkFlushMappedMemoryRanges (device->dev, 3, ranges); - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - rFrame->renderpass->renderpass, QFV_passTranslucent, - cframe->framebuffer, - 0, 0, 0 - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + DARRAY_APPEND (&rFrame->subpassCmdSets[subpass_map[QFV_drawDepth]], + dframe->cmdSet.a[QFV_drawDepth]); + DARRAY_APPEND (&rFrame->subpassCmdSets[subpass_map[QFV_draw2d]], + dframe->cmdSet.a[QFV_draw2d]); - QFV_duCmdBeginLabel (device, cmd, "twod", { 0.6, 0.2, 0, 1}); + draw_begin_subpass (QFV_drawDepth, rFrame); + draw_begin_subpass (QFV_draw2d, rFrame); if (dframe->quad_verts.count) { - VkBuffer quad_buffer = dframe->quad_buffer; - VkBuffer ind_buffer = dctx->ind_objects[0].buffer.buffer; - VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &quad_buffer, offsets); - dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); - VkDescriptorSet set[2] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dctx->quad_set, - }; - VkPipelineLayout layout = dctx->layout; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); + bind_pipeline (rFrame, dctx->depth_pipeline, + dframe->cmdSet.a[QFV_drawDepth]); + draw_quads (rFrame, dframe->cmdSet.a[QFV_drawDepth]); - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - dctx->quad_pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - dfunc->vkCmdDrawIndexed (cmd, dframe->quad_verts.count * INDS_PER_QUAD, - 1, 0, 0, 0); + bind_pipeline (rFrame, dctx->quad_pipeline, + dframe->cmdSet.a[QFV_draw2d]); + draw_quads (rFrame, dframe->cmdSet.a[QFV_draw2d]); } - if (dframe->slice_insts.count) { - VkBuffer slice_buffer = dframe->slice_buffer; - VkBuffer ind_buffer = dctx->ind_objects[1].buffer.buffer; - VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &slice_buffer, offsets); - dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - dctx->slice_pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - - uint32_t inst_start = 0; - for (size_t i = 0; i < dframe->slice_batch.size; i++) { - int fontid = dframe->slice_batch.a[i].descid; - uint32_t inst_count = dframe->slice_batch.a[i].count; - VkDescriptorSet set[2] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dctx->fonts.a[fontid].set, - }; - VkPipelineLayout layout = dctx->glyph_layout; - dfunc->vkCmdBindDescriptorSets (cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); - - dfunc->vkCmdDrawIndexed (cmd, 26, inst_count, 0, 0, inst_start); - inst_start += inst_count; - } - DARRAY_RESIZE (&dframe->slice_batch, 0); + bind_pipeline (rFrame, dctx->slice_pipeline, + dframe->cmdSet.a[QFV_draw2d]); + draw_slices (rFrame, dframe->cmdSet.a[QFV_draw2d]); } - if (dframe->glyph_insts.count) { - VkBuffer glyph_buffer = dframe->glyph_buffer; - VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &glyph_buffer, offsets); - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - dctx->glyph_pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - - uint32_t inst_start = 0; - for (size_t i = 0; i < dframe->glyph_batch.size; i++) { - int fontid = dframe->glyph_batch.a[i].descid; - uint32_t inst_count = dframe->glyph_batch.a[i].count; - VkDescriptorSet set[2] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dctx->fonts.a[fontid].set, - }; - VkPipelineLayout layout = dctx->glyph_layout; - dfunc->vkCmdBindDescriptorSets (cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); - - dfunc->vkCmdDraw (cmd, 4, inst_count, 0, inst_start); - inst_start += inst_count; - } - DARRAY_RESIZE (&dframe->glyph_batch, 0); + bind_pipeline (rFrame, dctx->glyph_pipeline, + dframe->cmdSet.a[QFV_draw2d]); + draw_glyphs (rFrame, dframe->cmdSet.a[QFV_draw2d]); } - if (dframe->line_verts.count) { - VkBuffer line_buffer = dframe->line_buffer; - VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &line_buffer, offsets); - VkDescriptorSet set[1] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - }; - VkPipelineLayout layout = dctx->layout; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 1, set, 0, 0); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - dctx->line_pipeline); - dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE, - 1, 0, 0); + bind_pipeline (rFrame, dctx->line_pipeline, + dframe->cmdSet.a[QFV_draw2d]); + draw_lines (rFrame, dframe->cmdSet.a[QFV_draw2d]); } - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); + draw_end_subpass (dframe->cmdSet.a[QFV_drawDepth], ctx); + draw_end_subpass (dframe->cmdSet.a[QFV_draw2d], ctx); dframe->quad_verts.count = 0; dframe->slice_insts.count = 0; From e50be735010aca078ac74ae7edd474514183c4b4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Nov 2022 13:11:50 +0900 Subject: [PATCH 3232/3664] [vulkan] Rename the render pass files Prefixing them with "rp_" helps a little with organization. --- libs/video/renderer/Makemodule.am | 24 +++++++++---------- .../{deferred.plist => rp_deferred.plist} | 0 .../{forward.plist => rp_forward.plist} | 0 .../vulkan/{shadow.plist => rp_shadow.plist} | 0 .../video/renderer/vulkan/vulkan_vid_common.c | 6 ++--- 5 files changed, 15 insertions(+), 15 deletions(-) rename libs/video/renderer/vulkan/{deferred.plist => rp_deferred.plist} (100%) rename libs/video/renderer/vulkan/{forward.plist => rp_forward.plist} (100%) rename libs/video/renderer/vulkan/{shadow.plist => rp_shadow.plist} (100%) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 1a4e21c5a..f2a878d9e 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -195,12 +195,12 @@ libs_video_renderer_librender_sw_la_SOURCES = \ pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc -deferred_src = libs/video/renderer/vulkan/deferred.plist -deferred_gen = libs/video/renderer/vulkan/deferred.plc -shadow_src = libs/video/renderer/vulkan/shadow.plist -shadow_gen = libs/video/renderer/vulkan/shadow.plc -forward_src = libs/video/renderer/vulkan/forward.plist -forward_gen = libs/video/renderer/vulkan/forward.plc +rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist +rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc +rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist +rp_shadow_gen = libs/video/renderer/vulkan/rp_shadow.plc +rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist +rp_forward_gen = libs/video/renderer/vulkan/rp_forward.plc video_renderer_vulkan_libs = \ libs/video/renderer/librender_vulkan.la \ @@ -259,9 +259,9 @@ libs/video/renderer/vulkan/vulkan_vid_common.lo: \ libs/video/renderer/vulkan/vulkan_vid_common.c \ $(vkparse_src) \ $(pipeline_gen) \ - ${deferred_gen} \ - ${shadow_gen} \ - $(forward_gen) + ${rp_deferred_gen} \ + ${rp_shadow_gen} \ + $(rp_forward_gen) qwaq_cmd = $(top_builddir)/ruamoko/qwaq/qwaq-cmd$(EXEEXT) @@ -492,9 +492,9 @@ BUILT_SOURCES += $(shader_gen) # libs/video/renderer/vulkan/pushcolor.frag.spv EXTRA_DIST += \ - $(deferred_src) \ - $(shadow_src) \ - $(forward_src) \ + $(rp_deferred_src) \ + $(rp_shadow_src) \ + $(rp_forward_src) \ $(pipeline_src) \ libs/video/renderer/vulkan/vkparse.plist \ libs/video/renderer/vulkan/vkparse.h \ diff --git a/libs/video/renderer/vulkan/deferred.plist b/libs/video/renderer/vulkan/rp_deferred.plist similarity index 100% rename from libs/video/renderer/vulkan/deferred.plist rename to libs/video/renderer/vulkan/rp_deferred.plist diff --git a/libs/video/renderer/vulkan/forward.plist b/libs/video/renderer/vulkan/rp_forward.plist similarity index 100% rename from libs/video/renderer/vulkan/forward.plist rename to libs/video/renderer/vulkan/rp_forward.plist diff --git a/libs/video/renderer/vulkan/shadow.plist b/libs/video/renderer/vulkan/rp_shadow.plist similarity index 100% rename from libs/video/renderer/vulkan/shadow.plist rename to libs/video/renderer/vulkan/rp_shadow.plist diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index e3e2610ea..28b54c0f1 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -69,15 +69,15 @@ static exprsym_t builtin_plist_syms[] = { }, { .name = "deferred", .value = (void *) -#include "libs/video/renderer/vulkan/deferred.plc" +#include "libs/video/renderer/vulkan/rp_deferred.plc" }, { .name = "shadow", .value = (void *) -#include "libs/video/renderer/vulkan/shadow.plc" +#include "libs/video/renderer/vulkan/rp_shadow.plc" }, { .name = "forward", .value = (void *) -#include "libs/video/renderer/vulkan/forward.plc" +#include "libs/video/renderer/vulkan/rp_forward.plc" }, {} }; From aac4c6ef7a1e139634c1c3f9d54d3460417eeb8a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Nov 2022 17:25:55 +0900 Subject: [PATCH 3233/3664] [vulkan] Get multiple frame buffers working Now each (high level) render pass can have its own frame buffer. The current goal is to get the final output render pass to just transfer the composed output to the swap chain image, potentially with scaling (my laptop might be able to cope). --- include/QF/Vulkan/qf_renderpass.h | 1 + include/QF/Vulkan/qf_vid.h | 1 + include/vid_vulkan.h | 1 - libs/video/renderer/vid_render_vulkan.c | 16 ++++++++-------- libs/video/renderer/vulkan/vulkan_alias.c | 6 +++--- libs/video/renderer/vulkan/vulkan_bsp.c | 3 +-- libs/video/renderer/vulkan/vulkan_compose.c | 3 +-- libs/video/renderer/vulkan/vulkan_draw.c | 3 +-- libs/video/renderer/vulkan/vulkan_iqm.c | 3 +-- libs/video/renderer/vulkan/vulkan_lighting.c | 3 +-- libs/video/renderer/vulkan/vulkan_sprite.c | 3 +-- libs/video/renderer/vulkan/vulkan_vid_common.c | 2 -- 12 files changed, 19 insertions(+), 26 deletions(-) diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index 98a178cf3..affa387ec 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -22,6 +22,7 @@ typedef struct qfv_renderframe_s { struct vulkan_ctx_s *vulkan_ctx; struct qfv_renderpass_s *renderpass; VkSubpassContents subpassContents; + VkFramebuffer framebuffer; int subpassCount; qfv_subpass_t *subpassInfo; struct qfv_cmdbufferset_s *subpassCmdSets; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 3a6498d05..36f9f6e4f 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -41,6 +41,7 @@ enum { QFV_rp_shadowmap, QFV_rp_main, + QFV_rp_output, }; //FIXME location diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index b3ecf0a60..57ccf25e8 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -18,7 +18,6 @@ typedef struct qfv_output_s { } qfv_output_t; typedef struct vulkan_frame_s { - VkFramebuffer framebuffer; VkFence fence; VkSemaphore imageAvailableSemaphore; VkSemaphore renderDoneSemaphore; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 7c9761bac..168604c34 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -333,14 +333,13 @@ vulkan_begin_frame (void) static void vulkan_render_view (void) { - __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; uint32_t imageIndex = vulkan_ctx->swapImageIndex; for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { __auto_type rp = vulkan_ctx->renderPasses.a[i]; __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; if (rp->framebuffers) { - frame->framebuffer = rp->framebuffers->a[imageIndex]; + rpFrame->framebuffer = rp->framebuffers->a[imageIndex]; } rp->draw (rpFrame); } @@ -385,8 +384,9 @@ vulkan_end_frame (void) VkDevice dev = device->dev; qfv_devfuncs_t *dfunc = device->funcs; qfv_queue_t *queue = &device->queue; - __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; - uint32_t imageIndex = vulkan_ctx->swapImageIndex; + uint32_t curFrame = vulkan_ctx->curFrame; + __auto_type frame = &vulkan_ctx->frames.a[curFrame]; + uint32_t imageIndex = vulkan_ctx->swapImageIndex; VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; @@ -402,7 +402,7 @@ vulkan_end_frame (void) dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { __auto_type rp = vulkan_ctx->renderPasses.a[i]; - __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + __auto_type rpFrame = &rp->frames.a[curFrame]; if (rp->primary_commands) { for (int j = 0; j < rpFrame->subpassCount; j++) { @@ -417,7 +417,7 @@ vulkan_end_frame (void) QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color); if (rpFrame->renderpass && rp->renderpass) { - renderPassInfo.framebuffer = frame->framebuffer, + renderPassInfo.framebuffer = rp->framebuffers->a[imageIndex]; renderPassInfo.renderPass = rp->renderpass; renderPassInfo.clearValueCount = rp->clearValues->size; renderPassInfo.pClearValues = rp->clearValues->a; @@ -464,7 +464,7 @@ vulkan_end_frame (void) if (vulkan_ctx->capture_callback) { VkImage srcImage = vulkan_ctx->swapchain->images->a[imageIndex]; VkCommandBuffer cmd = QFV_CaptureImage (vulkan_ctx->capture, srcImage, - vulkan_ctx->curFrame); + curFrame); dfunc->vkCmdExecuteCommands (frame->cmdBuffer, 1, &cmd); } dfunc->vkEndCommandBuffer (frame->cmdBuffer); @@ -487,7 +487,7 @@ vulkan_end_frame (void) dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE, 1000000000ull); vulkan_ctx->capture_callback (QFV_CaptureData (vulkan_ctx->capture, - vulkan_ctx->curFrame), + curFrame), vulkan_ctx->capture->extent.width, vulkan_ctx->capture->extent.height); vulkan_ctx->capture_callback = 0; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 11dae501a..869ff825b 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -186,15 +186,15 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; - aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + uint32_t curFrame = ctx->curFrame; + aliasframe_t *aframe = &actx->frames.a[curFrame]; VkCommandBuffer cmd = aframe->cmdSet.a[subpass]; dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, rFrame->renderpass->renderpass, subpass_map[subpass], - cframe->framebuffer, + rFrame->framebuffer, 0, 0, 0, }; VkCommandBufferBeginInfo beginInfo = { diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index f7ab0656b..4cb3c0b70 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -793,7 +793,6 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; bspctx_t *bctx = ctx->bsp_context; - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = bframe->cmdSet.a[subpass]; @@ -801,7 +800,7 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, rFrame->renderpass->renderpass, subpass_map[subpass], - cframe->framebuffer, + rFrame->framebuffer, 0, 0, 0, }; VkCommandBufferBeginInfo beginInfo = { diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 52ff735e8..c6169df05 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -64,7 +64,6 @@ Vulkan_Compose_Draw (qfv_renderframe_t *rFrame) qfv_renderpass_t *renderpass = rFrame->renderpass; composectx_t *cctx = ctx->compose_context; - __auto_type frame = &ctx->frames.a[ctx->curFrame]; composeframe_t *cframe = &cctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = cframe->cmd; @@ -74,7 +73,7 @@ Vulkan_Compose_Draw (qfv_renderframe_t *rFrame) VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, renderpass->renderpass, QFV_passCompose, - frame->framebuffer, + rFrame->framebuffer, 0, 0, 0, }; VkCommandBufferBeginInfo beginInfo = { diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 32d8db638..713b7e165 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1137,7 +1137,6 @@ draw_begin_subpass (QFV_DrawSubpass subpass, qfv_renderframe_t *rFrame) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; drawctx_t *dctx = ctx->draw_context; - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = dframe->cmdSet.a[subpass]; @@ -1145,7 +1144,7 @@ draw_begin_subpass (QFV_DrawSubpass subpass, qfv_renderframe_t *rFrame) VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, rFrame->renderpass->renderpass, subpass_map[subpass], - cframe->framebuffer, + rFrame->framebuffer, 0, 0, 0, }; VkCommandBufferBeginInfo beginInfo = { diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index ef58255aa..09efc86e7 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -212,7 +212,6 @@ iqm_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; iqmctx_t *ictx = ctx->iqm_context; - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = aframe->cmdSet.a[subpass]; @@ -220,7 +219,7 @@ iqm_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, rFrame->renderpass->renderpass, subpass_map[subpass], - cframe->framebuffer, + rFrame->framebuffer, 0, 0, 0, }; VkCommandBufferBeginInfo beginInfo = { diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 6d39c3586..1d9367d72 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -162,7 +162,6 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) update_lights (ctx); } - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = lframe->cmd; @@ -172,7 +171,7 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, renderpass->renderpass, QFV_passLighting, - cframe->framebuffer, + rFrame->framebuffer, 0, 0, 0, }; VkCommandBufferBeginInfo beginInfo = { diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index aadf48768..992771803 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -147,7 +147,6 @@ sprite_begin_subpass (QFV_SpriteSubpass subpass, VkPipeline pipeline, qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; spritectx_t *sctx = ctx->sprite_context; - __auto_type cframe = &ctx->frames.a[ctx->curFrame]; spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = sframe->cmdSet.a[subpass]; @@ -155,7 +154,7 @@ sprite_begin_subpass (QFV_SpriteSubpass subpass, VkPipeline pipeline, VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, rFrame->renderpass->renderpass, subpass_map[subpass], - cframe->framebuffer, + rFrame->framebuffer, 0, 0, 0, }; VkCommandBufferBeginInfo beginInfo = { diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 28b54c0f1..3e3c367f4 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -548,7 +548,6 @@ Vulkan_CreateFrames (vulkan_ctx_t *ctx) for (size_t i = 0; i < ctx->frames.size; i++) { __auto_type frame = &ctx->frames.a[i]; - frame->framebuffer = 0; frame->fence = QFV_CreateFence (device, 1); frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); frame->renderDoneSemaphore = QFV_CreateSemaphore (device); @@ -575,7 +574,6 @@ Vulkan_DestroyFrames (vulkan_ctx_t *ctx) df->vkDestroyFence (dev, frame->fence, 0); df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0); df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); - frame->framebuffer = 0; } DARRAY_CLEAR (&ctx->frames); From 7a50cdd7a800a2977fcc635abe2a961e8e5aa268 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Nov 2022 17:29:26 +0900 Subject: [PATCH 3234/3664] [vulkan] Correct the render pass order comparison Since pointers are being sorted, need to use double pointer (I often make this mistake). --- libs/video/renderer/vulkan/vulkan_vid_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 3e3c367f4..98d52b9ff 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -370,9 +370,9 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) static int renderpass_cmp (const void *_a, const void *_b) { - const qfv_renderpass_t *a = _a; - const qfv_renderpass_t *b = _b; - return a->order - b->order; + __auto_type a = (const qfv_renderpass_t **) _a; + __auto_type b = (const qfv_renderpass_t **) _b; + return (*a)->order - (*b)->order; } void From 5df9b506e0950fe40d9d2e9f14bab73076c10368 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Nov 2022 17:41:39 +0900 Subject: [PATCH 3235/3664] [vulkan] Rename the pipeline file The pl_prefix helps with organization, and the rest of the name makes it clear it's for the quake deferred renderer. --- libs/video/renderer/Makemodule.am | 8 ++++---- .../vulkan/{qfpipeline.plist => pl_quake_def.plist} | 0 libs/video/renderer/vulkan/vulkan_vid_common.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) rename libs/video/renderer/vulkan/{qfpipeline.plist => pl_quake_def.plist} (100%) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index f2a878d9e..9d094c4e8 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -193,8 +193,8 @@ libs_video_renderer_librender_sw_la_SOURCES = \ libs/video/renderer/sw/transform.S \ libs/video/renderer/sw/vid_common_sw.c -pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist -pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc +pl_quake_def_src = libs/video/renderer/vulkan/pl_quake_def.plist +pl_quake_def_gen = libs/video/renderer/vulkan/pl_quake_def.plc rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist @@ -258,7 +258,7 @@ libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vksh libs/video/renderer/vulkan/vulkan_vid_common.lo: \ libs/video/renderer/vulkan/vulkan_vid_common.c \ $(vkparse_src) \ - $(pipeline_gen) \ + $(pl_quake_def_gen) \ ${rp_deferred_gen} \ ${rp_shadow_gen} \ $(rp_forward_gen) @@ -495,7 +495,7 @@ EXTRA_DIST += \ $(rp_deferred_src) \ $(rp_shadow_src) \ $(rp_forward_src) \ - $(pipeline_src) \ + $(pl_quake_def_src) \ libs/video/renderer/vulkan/vkparse.plist \ libs/video/renderer/vulkan/vkparse.h \ libs/video/renderer/vulkan/shader/alias.frag \ diff --git a/libs/video/renderer/vulkan/qfpipeline.plist b/libs/video/renderer/vulkan/pl_quake_def.plist similarity index 100% rename from libs/video/renderer/vulkan/qfpipeline.plist rename to libs/video/renderer/vulkan/pl_quake_def.plist diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 98d52b9ff..21c466705 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -63,9 +63,9 @@ #include "libs/video/renderer/vulkan/vkparse.hinc" static exprsym_t builtin_plist_syms[] = { - { .name = "qfpipeline", + { .name = "quake_deferred", .value = (void *) -#include "libs/video/renderer/vulkan/qfpipeline.plc" +#include "libs/video/renderer/vulkan/pl_quake_def.plc" }, { .name = "deferred", .value = (void *) @@ -355,7 +355,7 @@ static plitem_t * qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) { if (!ctx->pipelineDef) { - ctx->pipelineDef = Vulkan_GetConfig (ctx, "qfpipeline"); + ctx->pipelineDef = Vulkan_GetConfig (ctx, "quake_deferred"); } plitem_t *item = ctx->pipelineDef; From b7947b48a54d80622d4dac29ae49b663db9c58fc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 21 Nov 2022 20:02:18 +0900 Subject: [PATCH 3236/3664] [vulkan] Move matrices uniform def to a header file Too many places to keep up to date. --- libs/video/renderer/vulkan/shader/alias.vert | 10 ++++------ libs/video/renderer/vulkan/shader/alias_depth.vert | 10 ++++------ libs/video/renderer/vulkan/shader/bsp_depth.vert | 9 +++------ libs/video/renderer/vulkan/shader/bsp_gbuf.vert | 9 +++------ libs/video/renderer/vulkan/shader/glyph.vert | 10 ++++------ libs/video/renderer/vulkan/shader/iqm.vert | 10 ++++------ libs/video/renderer/vulkan/shader/line.vert | 10 ++++------ libs/video/renderer/vulkan/shader/matrices.h | 6 ++++++ libs/video/renderer/vulkan/shader/particle.vert | 10 ++++------ libs/video/renderer/vulkan/shader/quakebsp.vert | 9 +++------ libs/video/renderer/vulkan/shader/slice.vert | 10 ++++------ libs/video/renderer/vulkan/shader/sprite_depth.vert | 10 ++++------ libs/video/renderer/vulkan/shader/sprite_gbuf.vert | 10 ++++------ libs/video/renderer/vulkan/shader/twod.vert | 10 ++++------ 14 files changed, 55 insertions(+), 78 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/matrices.h diff --git a/libs/video/renderer/vulkan/shader/alias.vert b/libs/video/renderer/vulkan/shader/alias.vert index 7292bee8e..ccfa78756 100644 --- a/libs/video/renderer/vulkan/shader/alias.vert +++ b/libs/video/renderer/vulkan/shader/alias.vert @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (push_constant) uniform PushConstants { mat4 Model; diff --git a/libs/video/renderer/vulkan/shader/alias_depth.vert b/libs/video/renderer/vulkan/shader/alias_depth.vert index 2d580cd11..7f14e2ace 100644 --- a/libs/video/renderer/vulkan/shader/alias_depth.vert +++ b/libs/video/renderer/vulkan/shader/alias_depth.vert @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (push_constant) uniform PushConstants { mat4 Model; diff --git a/libs/video/renderer/vulkan/shader/bsp_depth.vert b/libs/video/renderer/vulkan/shader/bsp_depth.vert index 14f5e802e..a3ab262ba 100644 --- a/libs/video/renderer/vulkan/shader/bsp_depth.vert +++ b/libs/video/renderer/vulkan/shader/bsp_depth.vert @@ -3,12 +3,9 @@ #include "entity.h" -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (set = 1, binding = 0) buffer Entities { Entity entities[]; diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert index 6cb8efb28..7b66575a4 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.vert +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.vert @@ -3,12 +3,9 @@ #include "entity.h" -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (set = 1, binding = 0) buffer Entities { Entity entities[]; diff --git a/libs/video/renderer/vulkan/shader/glyph.vert b/libs/video/renderer/vulkan/shader/glyph.vert index 65cea66dc..864df9ebf 100644 --- a/libs/video/renderer/vulkan/shader/glyph.vert +++ b/libs/video/renderer/vulkan/shader/glyph.vert @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (set = 1, binding = 0) uniform textureBuffer glyph_data; // per instance data diff --git a/libs/video/renderer/vulkan/shader/iqm.vert b/libs/video/renderer/vulkan/shader/iqm.vert index 9b665c283..a40d0ba70 100644 --- a/libs/video/renderer/vulkan/shader/iqm.vert +++ b/libs/video/renderer/vulkan/shader/iqm.vert @@ -1,13 +1,11 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable layout (constant_id = 0) const bool IQMDepthOnly = false; -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (set = 2, binding = 0) buffer Bones { // NOTE these are transposed, so v * m diff --git a/libs/video/renderer/vulkan/shader/line.vert b/libs/video/renderer/vulkan/shader/line.vert index 754ba5cfb..25bf0b50c 100644 --- a/libs/video/renderer/vulkan/shader/line.vert +++ b/libs/video/renderer/vulkan/shader/line.vert @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (location = 0) in vec2 vertex; layout (location = 1) in vec2 uv; layout (location = 2) in vec4 vcolor; diff --git a/libs/video/renderer/vulkan/shader/matrices.h b/libs/video/renderer/vulkan/shader/matrices.h new file mode 100644 index 000000000..f54ffab14 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/matrices.h @@ -0,0 +1,6 @@ +Matrices { + mat4 Projection3d; + mat4 View; + mat4 Sky; + mat4 Projection2d; +} diff --git a/libs/video/renderer/vulkan/shader/particle.vert b/libs/video/renderer/vulkan/shader/particle.vert index 655e31042..85c5d12b2 100644 --- a/libs/video/renderer/vulkan/shader/particle.vert +++ b/libs/video/renderer/vulkan/shader/particle.vert @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (push_constant) uniform PushConstants { mat4 Model; diff --git a/libs/video/renderer/vulkan/shader/quakebsp.vert b/libs/video/renderer/vulkan/shader/quakebsp.vert index 4b379a06a..e93c0ea9e 100644 --- a/libs/video/renderer/vulkan/shader/quakebsp.vert +++ b/libs/video/renderer/vulkan/shader/quakebsp.vert @@ -3,12 +3,9 @@ #include "entity.h" -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (set = 1, binding = 0) buffer Entities { Entity entities[]; diff --git a/libs/video/renderer/vulkan/shader/slice.vert b/libs/video/renderer/vulkan/shader/slice.vert index c1009e925..bdf749410 100644 --- a/libs/video/renderer/vulkan/shader/slice.vert +++ b/libs/video/renderer/vulkan/shader/slice.vert @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (set = 1, binding = 0) uniform textureBuffer glyph_data; // per instance data diff --git a/libs/video/renderer/vulkan/shader/sprite_depth.vert b/libs/video/renderer/vulkan/shader/sprite_depth.vert index 430603dd3..20f6dc0d6 100644 --- a/libs/video/renderer/vulkan/shader/sprite_depth.vert +++ b/libs/video/renderer/vulkan/shader/sprite_depth.vert @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (set = 1, binding = 0) uniform Vertices { vec4 xyuv[4]; diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.vert b/libs/video/renderer/vulkan/shader/sprite_gbuf.vert index acbf18a2e..1cdfb0f26 100644 --- a/libs/video/renderer/vulkan/shader/sprite_gbuf.vert +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.vert @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (set = 1, binding = 0) uniform Vertices { vec4 xyuv[4]; diff --git a/libs/video/renderer/vulkan/shader/twod.vert b/libs/video/renderer/vulkan/shader/twod.vert index 8f0a25f57..d6501a633 100644 --- a/libs/video/renderer/vulkan/shader/twod.vert +++ b/libs/video/renderer/vulkan/shader/twod.vert @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; /** Vertex position. x, y, s, t From 0a3417d38eb08b2d8a4ad5cc6e769f450dfbbb7b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 22 Nov 2022 13:25:09 +0900 Subject: [PATCH 3237/3664] [vulkan] Add support for code-only render passes Still very preliminary, but it allows for CPU-only passes to be added to the tasks run for each frame. --- include/QF/Vulkan/qf_renderpass.h | 3 +++ libs/video/renderer/vulkan/vulkan_renderpass.c | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index affa387ec..8dc95fdb2 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -64,6 +64,9 @@ qfv_renderpass_t *Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx, const char *name, struct qfv_output_s *output, qfv_draw_t draw); +qfv_renderpass_t *Vulkan_CreateFunctionPass (struct vulkan_ctx_s *ctx, + const char *name, + qfv_draw_t function); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx, qfv_renderpass_t *renderpass); void Vulkan_CreateAttachments (struct vulkan_ctx_s *ctx, diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 6a72b447a..c779065f8 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -290,6 +290,22 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, return rp; } +qfv_renderpass_t * +Vulkan_CreateFunctionPass (vulkan_ctx_t *ctx, const char *name, + qfv_draw_t function) +{ + qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); + rp->name = name; + rp->draw = function; + + DARRAY_INIT (&rp->frames, 4); + DARRAY_RESIZE (&rp->frames, ctx->frames.size); + for (size_t i = 0; i < rp->frames.size; i++) { + init_renderframe (ctx, rp, &rp->frames.a[i]); + } + return rp; +} + void Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) { From a886b9432ccebeae209576f869cdc2ab83ad5242 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 22 Nov 2022 13:29:11 +0900 Subject: [PATCH 3238/3664] [render] Tidy up Makemodule ever so slightly I really need to find a good way to handle all the non-standard files. --- libs/video/renderer/Makemodule.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 9d094c4e8..c19185a2d 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -197,10 +197,10 @@ pl_quake_def_src = libs/video/renderer/vulkan/pl_quake_def.plist pl_quake_def_gen = libs/video/renderer/vulkan/pl_quake_def.plc rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc -rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist -rp_shadow_gen = libs/video/renderer/vulkan/rp_shadow.plc rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist rp_forward_gen = libs/video/renderer/vulkan/rp_forward.plc +rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist +rp_shadow_gen = libs/video/renderer/vulkan/rp_shadow.plc video_renderer_vulkan_libs = \ libs/video/renderer/librender_vulkan.la \ @@ -260,8 +260,8 @@ libs/video/renderer/vulkan/vulkan_vid_common.lo: \ $(vkparse_src) \ $(pl_quake_def_gen) \ ${rp_deferred_gen} \ - ${rp_shadow_gen} \ - $(rp_forward_gen) + $(rp_forward_gen) \ + ${rp_shadow_gen} qwaq_cmd = $(top_builddir)/ruamoko/qwaq/qwaq-cmd$(EXEEXT) @@ -493,8 +493,8 @@ BUILT_SOURCES += $(shader_gen) EXTRA_DIST += \ $(rp_deferred_src) \ - $(rp_shadow_src) \ $(rp_forward_src) \ + $(rp_shadow_src) \ $(pl_quake_def_src) \ libs/video/renderer/vulkan/vkparse.plist \ libs/video/renderer/vulkan/vkparse.h \ From 7b15caee04dc8d5e59b5d28be309131f69dd0544 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 22 Nov 2022 13:30:29 +0900 Subject: [PATCH 3239/3664] [vulkan] Adjust shutdown order slightly It makes more sense to shutdown the render passes before textures. --- libs/video/renderer/vid_render_vulkan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 168604c34..59cbf75f6 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -775,9 +775,10 @@ vulkan_vid_render_shutdown (void) Vulkan_Scene_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx); + Vulkan_DestroyRenderPasses (vulkan_ctx); + Vulkan_Palette_Shutdown (vulkan_ctx); Vulkan_Texture_Shutdown (vulkan_ctx); - Vulkan_DestroyRenderPasses (vulkan_ctx); QFV_DestroyStagingBuffer (vulkan_ctx->staging); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); From 2cee2f2ab85a983124dd8f2b18b9273ab77c9d53 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 22 Nov 2022 17:47:36 +0900 Subject: [PATCH 3240/3664] [vulkan] Add a module to handle output When working, this will handle the output to the swap-chain images and any final post-processing effects (gamma correction, screen scaling, etc). However, currently the screen is just black because the image for getting the main render pass output isn't hooked up yet. --- include/QF/Vulkan/qf_matrices.h | 3 + include/QF/Vulkan/qf_output.h | 59 +++++ include/QF/Vulkan/qf_vid.h | 1 + include/vid_vulkan.h | 4 +- libs/video/renderer/Makemodule.am | 14 ++ libs/video/renderer/vid_render_vulkan.c | 14 +- libs/video/renderer/vulkan/pl_output.plist | 209 +++++++++++++++++ libs/video/renderer/vulkan/rp_output.plist | 90 ++++++++ libs/video/renderer/vulkan/shader.c | 3 + libs/video/renderer/vulkan/shader/output.frag | 15 ++ libs/video/renderer/vulkan/vulkan_main.c | 1 - libs/video/renderer/vulkan/vulkan_output.c | 211 ++++++++++++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 10 + 13 files changed, 626 insertions(+), 8 deletions(-) create mode 100644 include/QF/Vulkan/qf_output.h create mode 100644 libs/video/renderer/vulkan/pl_output.plist create mode 100644 libs/video/renderer/vulkan/rp_output.plist create mode 100644 libs/video/renderer/vulkan/shader/output.frag create mode 100644 libs/video/renderer/vulkan/vulkan_output.c diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index 4a8d0e413..c9f57abb3 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -42,6 +42,9 @@ typedef struct qfv_matrix_buffer_s { mat4f_t View; mat4f_t Sky; mat4f_t Projection2d; + vec2f_t ScreenSize; + vec2f_t pad; //FIXME shouldn't need this (for gpu align) + vec4f_t pad2[3]; } qfv_matrix_buffer_t; #define LIGHTING_BUFFER_INFOS 1 diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h new file mode 100644 index 000000000..e657fa7c5 --- /dev/null +++ b/include/QF/Vulkan/qf_output.h @@ -0,0 +1,59 @@ +/* + qf_output.h + + Vulkan output pass + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/11/21 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifndef __QF_Vulkan_qf_output_h +#define __QF_Vulkan_qf_output_h + +#include "QF/darray.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/command.h" + +typedef struct outputframe_s { + VkCommandBuffer cmd; + VkImageView view; + VkDescriptorSet set; +} outputframe_t; + +typedef struct outputframeset_s + DARRAY_TYPE (outputframe_t) outputframeset_t; + +typedef struct outputctx_s { + outputframeset_t frames; + VkPipeline pipeline; + VkPipelineLayout layout; + VkSampler sampler; +} outputctx_t; + +struct vulkan_ctx_s; + +void Vulkan_Output_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx); +void Vulkan_Output_CreateRenderPasses (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_output_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 36f9f6e4f..fed5e4928 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -40,6 +40,7 @@ enum { QFV_rp_shadowmap, + QFV_rp_preoutput, QFV_rp_main, QFV_rp_output, }; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 57ccf25e8..58795a201 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -75,14 +75,14 @@ typedef struct vulkan_ctx_s { struct drawctx_s *draw_context; struct lightingctx_s *lighting_context; struct composectx_s *compose_context; + struct outputctx_s *output_context; VkCommandPool cmdpool; struct qfv_stagebuf_s *staging; size_t curFrame; vulkan_frameset_t frames; qfv_renderpassset_t renderPasses; - //FIXME for resize, but should be a set - struct qfv_renderpass_s *main_renderpass; + struct qfv_renderpass_s *output_renderpass; struct qfv_capture_s *capture; void (*capture_callback) (const byte *data, int width, int height); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index c19185a2d..6a1559fc7 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -195,10 +195,14 @@ libs_video_renderer_librender_sw_la_SOURCES = \ pl_quake_def_src = libs/video/renderer/vulkan/pl_quake_def.plist pl_quake_def_gen = libs/video/renderer/vulkan/pl_quake_def.plc +pl_output_src = libs/video/renderer/vulkan/pl_output.plist +pl_output_gen = libs/video/renderer/vulkan/pl_output.plc rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist rp_forward_gen = libs/video/renderer/vulkan/rp_forward.plc +rp_output_src = libs/video/renderer/vulkan/rp_output.plist +rp_output_gen = libs/video/renderer/vulkan/rp_output.plc rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist rp_shadow_gen = libs/video/renderer/vulkan/rp_shadow.plc @@ -243,6 +247,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_lighting.c \ libs/video/renderer/vulkan/vulkan_main.c \ libs/video/renderer/vulkan/vulkan_matrices.c \ + libs/video/renderer/vulkan/vulkan_output.c \ libs/video/renderer/vulkan/vulkan_palette.c \ libs/video/renderer/vulkan/vulkan_particles.c \ libs/video/renderer/vulkan/vulkan_renderpass.c \ @@ -259,8 +264,10 @@ libs/video/renderer/vulkan/vulkan_vid_common.lo: \ libs/video/renderer/vulkan/vulkan_vid_common.c \ $(vkparse_src) \ $(pl_quake_def_gen) \ + $(pl_output_gen) \ ${rp_deferred_gen} \ $(rp_forward_gen) \ + $(rp_output_gen) \ ${rp_shadow_gen} @@ -346,6 +353,8 @@ iqmv_src = $(vkshaderpath)/iqm.vert iqmv_c = $(vkshaderpath)/iqm.vert.spvc iqmf_src = $(vkshaderpath)/iqm.frag iqmf_c = $(vkshaderpath)/iqm.frag.spvc +output_src = $(vkshaderpath)/output.frag +output_c = $(vkshaderpath)/output.frag.spvc passthrough_src = $(vkshaderpath)/passthrough.vert passthrough_c = $(vkshaderpath)/passthrough.vert.spvc fstriangle_src = $(vkshaderpath)/fstriangle.vert @@ -417,6 +426,8 @@ $(iqmv_c): $(iqmv_src) $(iqmf_c): $(iqmf_src) +$(output_c): $(output_src) + $(passthrough_c): $(passthrough_src) $(fstriangle_c): $(fstriangle_src) @@ -457,6 +468,7 @@ vkshader_c = \ $(alias_shadow_c) \ $(iqmv_c) \ $(iqmf_c) \ + $(output_c) \ $(passthrough_c) \ $(fstriangle_c) \ $(pushcolor_c) \ @@ -494,8 +506,10 @@ BUILT_SOURCES += $(shader_gen) EXTRA_DIST += \ $(rp_deferred_src) \ $(rp_forward_src) \ + $(rp_output_src) \ $(rp_shadow_src) \ $(pl_quake_def_src) \ + $(pl_output_src) \ libs/video/renderer/vulkan/vkparse.plist \ libs/video/renderer/vulkan/vkparse.h \ libs/video/renderer/vulkan/shader/alias.frag \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 59cbf75f6..f4c59d61c 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -50,6 +50,7 @@ #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" @@ -94,7 +95,9 @@ vulkan_R_Init (void) Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); + Vulkan_CreateRenderPasses (vulkan_ctx); + Vulkan_Output_Init (vulkan_ctx); Vulkan_Matrix_Init (vulkan_ctx); Vulkan_Scene_Init (vulkan_ctx); @@ -318,11 +321,11 @@ vulkan_begin_frame (void) .format = vulkan_ctx->swapchain->format, .view_list = vulkan_ctx->swapchain->imageViews->a, }; - vulkan_ctx->main_renderpass->viewport.width = output.extent.width; - vulkan_ctx->main_renderpass->viewport.height = output.extent.height; - vulkan_ctx->main_renderpass->scissor.extent = output.extent; + vulkan_ctx->output_renderpass->viewport.width = output.extent.width; + vulkan_ctx->output_renderpass->viewport.height = output.extent.height; + vulkan_ctx->output_renderpass->scissor.extent = output.extent; vulkan_ctx->output = output; - Vulkan_CreateAttachments (vulkan_ctx, vulkan_ctx->main_renderpass); + Vulkan_CreateAttachments (vulkan_ctx, vulkan_ctx->output_renderpass); QFV_AcquireNextImage (vulkan_ctx->swapchain, frame->imageAvailableSemaphore, 0, &imageIndex); @@ -373,7 +376,7 @@ vulkan_set_2d (int scaled) float right = left + vid.width / scale; float bottom = top + vid.height / scale; QFV_Orthographic (mat->Projection2d, left, right, top, bottom, 0, 99999); - + mat->ScreenSize = (vec2f_t) { 1.0 / vid.width, 1.0 / vid.height }; mctx->dirty = mctx->frames.size; } @@ -776,6 +779,7 @@ vulkan_vid_render_shutdown (void) Vulkan_Matrix_Shutdown (vulkan_ctx); Vulkan_DestroyRenderPasses (vulkan_ctx); + Vulkan_Output_Shutdown (vulkan_ctx); Vulkan_Palette_Shutdown (vulkan_ctx); Vulkan_Texture_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/pl_output.plist b/libs/video/renderer/vulkan/pl_output.plist new file mode 100644 index 000000000..001b999c6 --- /dev/null +++ b/libs/video/renderer/vulkan/pl_output.plist @@ -0,0 +1,209 @@ +{ + samplers = { + linear = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 0; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; + }; + descriptorPools = { + output_pool = { + flags = 0; + maxSets = "$frames.size * 2z"; + bindings = ( + { + type = combined_image_sampler; + descriptorCount = "$frames.size * 2z"; + }, + ); + }; + }; + setLayouts = { + matrix_set = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex|geometry|fragment; + }, + ); + }; + output_set = { + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + }; + pipelineLayouts = { + output_layout = { + setLayouts = (matrix_set, output_set); + }; + }; + + depthStencil = { + disable = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + }; + + inputAssembly = { + }; + + vertexInput = { + index_only = { + bindings = (); + attributes = (); + }; + }; + + rasterization = { + cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + counter_cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + }; + + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); + }; + + attachmentBlendOp = { + disabled = { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + alpha_blend = { + blendEnable = true; + srcColorBlendFactor = one; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = one; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + }; + + fstriangle = { + vertexStage = { + stage = vertex; + name = main; + module = $builtin/fstriangle.vert; + }; + vertexInput = { + bindings = (); + attributes = (); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.disabled); + }; + }; + + pipelines = { + base = { + viewport = $properties.viewport; + rasterization = $properties.rasterization.counter_cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.disable; + colorBlend = { + logicOpEnable = false; + attachments = ( + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + ); + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + renderPass = output; + }; + output_base = { + @inherit = $properties.pipelines.base; + vertexInput = $properties.fstriangle.vertexInput; + inputAssembly = $properties.fstriangle.inputAssembly; + colorBlend = $properties.fstriangle.colorBlend; + }; + output = { + @inherit = $properties.pipelines.output_base; + subpass = 0; + stages = ( + $properties.fstriangle.vertexStage, + { + stage = fragment; + name = main; + module = $builtin/output.frag; + }, + ); + layout = output_layout; + }; + }; +} diff --git a/libs/video/renderer/vulkan/rp_output.plist b/libs/video/renderer/vulkan/rp_output.plist new file mode 100644 index 000000000..3ca2a42f4 --- /dev/null +++ b/libs/video/renderer/vulkan/rp_output.plist @@ -0,0 +1,90 @@ +{ + flat_color_image_template = { + imageType = `2d; + samples = 1; + extent = { + width = $output.extent.width; + height = $output.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|sampled; + initialLayout = undefined; + }; + images = { + color = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; + }; + flat_color_view_template = { + viewType = VK_IMAGE_VIEW_TYPE_2D; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + imageViews = { + color = { + @inherit = $properties.flat_color_view_template; + image = color; + format = $properties.images.color.format; + }; + }; + framebuffer = { + renderPass = output; + attachments = ($output.view); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; + }; + clearValues = ( + { color = "[0, 0, 0, 1]"; }, // output + ); + attachment_template = { + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }; + info = { + color = "[0.9, 0.9, 0.9, 1]"; + subpass_info = ( + { name = compose; color = "[ 0.9, 0.9, 0.9, 1]" }, + ); + }; + renderpass = { + attachments = ( + { + @inherit = $properties.attachment_template; + format = $output.format; + loadOp = clear; + storeOp = store; + finalLayout = present_src_khr; + }, + ); + subpasses = ( + { // 0 output + pipelineBindPoint = graphics; + colorAttachments = ( + { // output + attachment = 0; + layout = color_attachment_optimal; + }, + ); + }, + ); + }; +} diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index dadfb897e..fb34c7e05 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -109,6 +109,8 @@ static static #include "libs/video/renderer/vulkan/shader/iqm.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/output.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/passthrough.vert.spvc" static #include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc" @@ -157,6 +159,7 @@ static shaderdata_t builtin_shaders[] = { { "alias_shadow.vert", alias_shadow_vert, sizeof (alias_shadow_vert) }, { "iqm.vert", iqm_vert, sizeof (iqm_vert) }, { "iqm.frag", iqm_frag, sizeof (iqm_frag) }, + { "output.frag", output_frag, sizeof (output_frag) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, diff --git a/libs/video/renderer/vulkan/shader/output.frag b/libs/video/renderer/vulkan/shader/output.frag new file mode 100644 index 000000000..46822c257 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/output.frag @@ -0,0 +1,15 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; + +layout (set = 1, binding = 0) uniform sampler2D Input; +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + frag_color = texture (Input, gl_FragCoord.xy * ScreenSize); +} diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 9bcc0dc1e..824312d3c 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -185,5 +185,4 @@ Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) &output, main_draw); rp->order = QFV_rp_main; DARRAY_APPEND (&ctx->renderPasses, rp); - ctx->main_renderpass = rp; } diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c new file mode 100644 index 000000000..5d9e2c406 --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -0,0 +1,211 @@ +/* + vulkan_main.c + + Vulkan output + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/11/21 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include "string.h" +#endif +#ifdef HAVE_STRINGS_H +# include "strings.h" +#endif + +#include "QF/cvar.h" +#include "QF/render.h" +#include "QF/sys.h" + +#include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_output.h" +#include "QF/Vulkan/qf_renderpass.h" +#include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/swapchain.h" + +#include "vid_vulkan.h" + +static void +update_input (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + outputctx_t *octx = ctx->output_context; + uint32_t curFrame = ctx->curFrame; + outputframe_t *oframe = &octx->frames.a[curFrame]; + qfv_renderpass_t *rp = ctx->output_renderpass; + + if (rp->attachment_views->a[0] == oframe->view) { + return; + } + oframe->view = rp->attachment_views->a[0]; + + VkDescriptorImageInfo imageInfo = { + octx->sampler, oframe->view, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + oframe->set, 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo, 0, 0 } + }; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); +} + +static void +output_draw (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + outputctx_t *octx = ctx->output_context; + outputframe_t *oframe = &octx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = oframe->cmd; + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + rFrame->renderpass->renderpass, 0, + rFrame->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + QFV_duCmdBeginLabel (device, cmd, "output:output"); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + octx->pipeline); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); + + VkDescriptorSet set[] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + oframe->set, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + octx->layout, 0, 2, set, 0, 0); + + dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); + + + QFV_duCmdEndLabel (device, cmd); + dfunc->vkEndCommandBuffer (cmd); +} + +void +Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx) +{ + qfv_output_t output = { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[0], + .format = ctx->swapchain->format, + .view_list = ctx->swapchain->imageViews->a, + }; + __auto_type out = Vulkan_CreateRenderPass (ctx, "output", + &output, output_draw); + out->order = QFV_rp_output; + DARRAY_APPEND (&ctx->renderPasses, out); + ctx->output_renderpass = out; + + __auto_type pre = Vulkan_CreateFunctionPass (ctx, "preoutput", + update_input); + pre->order = QFV_rp_preoutput; + DARRAY_APPEND (&ctx->renderPasses, pre); +} + +void +Vulkan_Output_Init (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + + qfvPushDebug (ctx, "output init"); + + outputctx_t *octx = calloc (1, sizeof (outputctx_t)); + ctx->output_context = octx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&octx->frames, frames); + DARRAY_RESIZE (&octx->frames, frames); + octx->frames.grow = 0; + + __auto_type pld = ctx->pipelineDef; + ctx->pipelineDef = Vulkan_GetConfig (ctx, "qf_output"); + + octx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "output"); + octx->layout = Vulkan_CreatePipelineLayout (ctx, "output_layout"); + octx->sampler = Vulkan_CreateSampler (ctx, "linear"); + + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "output_set"); + for (size_t i = 0; i < frames; i++) { + layouts->a[i] = layouts->a[0]; + } + __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "output_pool"); + __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); + __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); + + for (size_t i = 0; i < frames; i++) { + __auto_type oframe = &octx->frames.a[i]; + + oframe->set = sets->a[i]; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); + oframe->cmd = cmdSet->a[0]; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + oframe->cmd, "cmd:output"); + } + + ctx->pipelineDef = pld; + + free (sets); + qfvPopDebug (ctx); +} + +void +Vulkan_Output_Shutdown (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + outputctx_t *octx = ctx->output_context; + + dfunc->vkDestroyPipeline (device->dev, octx->pipeline, 0); + free (octx->frames.a); + free (octx); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 21c466705..ea1d541bd 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -53,6 +53,7 @@ #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_main.h" +#include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_vid.h" @@ -67,6 +68,10 @@ static exprsym_t builtin_plist_syms[] = { .value = (void *) #include "libs/video/renderer/vulkan/pl_quake_def.plc" }, + { .name = "qf_output", + .value = (void *) +#include "libs/video/renderer/vulkan/pl_output.plc" + }, { .name = "deferred", .value = (void *) #include "libs/video/renderer/vulkan/rp_deferred.plc" @@ -79,6 +84,10 @@ static exprsym_t builtin_plist_syms[] = { .value = (void *) #include "libs/video/renderer/vulkan/rp_forward.plc" }, + { .name = "output", + .value = (void *) +#include "libs/video/renderer/vulkan/rp_output.plc" + }, {} }; static plitem_t **builtin_plists; @@ -378,6 +387,7 @@ renderpass_cmp (const void *_a, const void *_b) void Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) { + Vulkan_Output_CreateRenderPasses (ctx); Vulkan_Main_CreateRenderPasses (ctx); Vulkan_Lighting_CreateRenderPasses (ctx); From 8842db082fa7e6d8384cf22a81eb9a3c922bb40b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 22 Nov 2022 21:06:12 +0900 Subject: [PATCH 3241/3664] [vulkan] Add ScreenSize to shader def This had somehow gotten lost from the previous commit. --- libs/video/renderer/vulkan/shader/matrices.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/video/renderer/vulkan/shader/matrices.h b/libs/video/renderer/vulkan/shader/matrices.h index f54ffab14..b5640cc3f 100644 --- a/libs/video/renderer/vulkan/shader/matrices.h +++ b/libs/video/renderer/vulkan/shader/matrices.h @@ -3,4 +3,6 @@ Matrices { mat4 View; mat4 Sky; mat4 Projection2d; + + vec2 ScreenSize; } From f9e45aec4cdbc35cca9a6b665577b21cbf5ef348 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 23 Nov 2022 11:34:20 +0900 Subject: [PATCH 3242/3664] [vulkan] Be more consistent with parse context naming --- libs/video/renderer/vulkan/vkparse.c | 72 +++++++++++++++------------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 642f0d00d..79fc093a9 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -152,8 +152,9 @@ parse_basic (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { int ret = 1; + parsectx_t *pctx = context; __auto_type etype = (exprtype_t *) field->data; - exprctx_t ectx = *((parsectx_t *) context)->ectx; + exprctx_t ectx = *pctx->ectx; exprval_t result = { etype, data }; ectx.result = &result; ectx.item = item; @@ -184,8 +185,9 @@ parse_int32_t (const plfield_t *field, const plitem_t *item, // use size_t (and cexpr_size_t) for val so references to array sizes // can be used size_t val = 0; + parsectx_t *pctx = context; exprval_t result = { &cexpr_size_t, &val }; - exprctx_t ectx = *((parsectx_t *) context)->ectx; + exprctx_t ectx = *pctx->ectx; ectx.result = &result; ectx.item = item; const char *valstr = PL_String (item); @@ -212,8 +214,9 @@ parse_uint32_t (const plfield_t *field, const plitem_t *item, // use size_t (and cexpr_size_t) for val so references to array sizes // can be used size_t val = 0; + parsectx_t *pctx = context; exprval_t result = { &cexpr_size_t, &val }; - exprctx_t ectx = *((parsectx_t *) context)->ectx; + exprctx_t ectx = *pctx->ectx; ectx.result = &result; ectx.item = item; const char *valstr = PL_String (item); @@ -246,9 +249,10 @@ parse_enum (const plfield_t *field, const plitem_t *item, { int ret = 1; __auto_type enm = (exprenum_t *) field->data; - exprctx_t ectx = *((parsectx_t *)context)->ectx; + parsectx_t *pctx = context; + exprctx_t ectx = *pctx->ectx; exprval_t result = { enm->type, data }; - ectx.parent = ((parsectx_t *)context)->ectx; + ectx.parent = pctx->ectx; ectx.symtab = enm->symtab; ectx.result = &result; const char *valstr = PL_String (item); @@ -416,7 +420,8 @@ static int parse_inherit (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { - exprctx_t ectx = *((parsectx_t *)context)->ectx; + parsectx_t *pctx = context; + exprctx_t ectx = *pctx->ectx; plitem_t *inheritItem = 0; exprval_t result = { &cexpr_plitem, &inheritItem }; ectx.result = &result; @@ -509,11 +514,10 @@ resource_path (vulkan_ctx_t *ctx, const char *prefix, const char *name) static int parse_VkRenderPass (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *context) + plitem_t *messages, parsectx_t *pctx) { __auto_type handle = (VkRenderPass *) data[0]; int ret = 1; - parsectx_t *pctx = context; exprctx_t ectx = *pctx->ectx; vulkan_ctx_t *ctx = pctx->vctx; @@ -545,10 +549,10 @@ parse_VkRenderPass (const plitem_t *item, void **data, static int parse_VkShaderModule (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *context) + plitem_t *messages, parsectx_t *pctx) { __auto_type handle = (VkShaderModule *) data[0]; - vulkan_ctx_t *ctx = context->vctx; + vulkan_ctx_t *ctx = pctx->vctx; qfv_device_t *device = ctx->device; const char *name = PL_String (item); @@ -607,12 +611,12 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, static int parse_VkPipelineLayout (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *context) + plitem_t *messages, parsectx_t *pctx) { __auto_type handle = (VkPipelineLayout *) data[0]; int ret = 1; - exprctx_t ectx = *context->ectx; - vulkan_ctx_t *ctx = context->vctx; + exprctx_t ectx = *pctx->ectx; + vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); const char *path = resource_path (ctx, "pipelineLayouts", name); @@ -630,7 +634,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, ret = !cexpr_eval_string (path, &ectx); if (ret) { VkPipelineLayout layout; - layout = QFV_ParsePipelineLayout (ctx, setItem, context->properties); + layout = QFV_ParsePipelineLayout (ctx, setItem, pctx->properties); *handle = (VkPipelineLayout) layout; // path not guaranteed to survive cexpr_eval_string due to va @@ -642,12 +646,12 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, static int parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, - parsectx_t *context) + parsectx_t *pctx) { __auto_type handle = (VkImage *) data[0]; int ret = 1; - exprctx_t ectx = *context->ectx; - vulkan_ctx_t *ctx = context->vctx; + exprctx_t ectx = *pctx->ectx; + vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); const char *path = resource_path (ctx, "images", name); @@ -665,7 +669,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, ret = !cexpr_eval_string (path, &ectx); if (ret) { VkImage image; - image = QFV_ParseImage (ctx, imageItem, context->properties); + image = QFV_ParseImage (ctx, imageItem, pctx->properties); *handle = (VkImage) image; // path not guaranteed to survive cexpr_eval_string due to va @@ -685,13 +689,13 @@ exprtype_t VkImageView_type = { static int parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, - plitem_t *messages, void *_context) + plitem_t *messages, void *context) { - parsectx_t *context = _context; + parsectx_t *pctx = context; __auto_type handle = (VkImageView *) data; int ret = 1; - exprctx_t ectx = *context->ectx; - vulkan_ctx_t *ctx = context->vctx; + exprctx_t ectx = *pctx->ectx; + vulkan_ctx_t *ctx = pctx->vctx; const char *name = PL_String (item); const char *path = resource_path (ctx, "imageViews", name); @@ -715,7 +719,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, imageView = *(VkImageView *) value->value; } else if (value->type == &cexpr_plitem) { imageView = QFV_ParseImageView (ctx, imageViewItem, - context->properties); + pctx->properties); // path not guaranteed to survive cexpr_eval_string due to va path = resource_path (ctx, "imageViews", name); QFV_AddHandle (ctx->imageViews, path, (uint64_t) imageView); @@ -866,7 +870,7 @@ static hashtab_t *enum_symtab; static int parse_BasePipeline (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *context) + plitem_t *messages, parsectx_t *pctx) { *(VkPipeline *) data = 0; PL_Message (messages, item, "not implemented"); @@ -914,7 +918,7 @@ static exprtab_t data_array_symtab = { static int parse_specialization_data (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *context) + plitem_t *messages, parsectx_t *pctx) { size_t *size_ptr = (size_t *) data[0]; void **data_ptr = (void **) data[1]; @@ -923,16 +927,16 @@ parse_specialization_data (const plitem_t *item, void **data, const void *bindata = PL_BinaryData (item); size_t binsize = PL_BinarySize (item); - *data_ptr = vkparse_alloc (context, binsize); + *data_ptr = vkparse_alloc (pctx, binsize); memcpy (*data_ptr, bindata, binsize); *size_ptr = binsize; return 1; } data_array_t *da= 0; - exprctx_t ectx = *((parsectx_t *)context)->ectx; + exprctx_t ectx = *pctx->ectx; exprval_t result = { &data_array_type, &da }; - ectx.parent = ((parsectx_t *)context)->ectx; + ectx.parent = pctx->ectx; ectx.symtab = &data_array_symtab; ectx.result = &result; ectx.item = item; @@ -1025,14 +1029,14 @@ root_symtab_init (void) void QFV_InitParse (vulkan_ctx_t *ctx) { - exprctx_t context = {}; + exprctx_t ectx = {}; enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, &ctx->hashctx); parser_table = Hash_NewTable (61, parser_getkey, 0, 0, &ctx->hashctx); - context.hashctx = &ctx->hashctx; - vkgen_init_symtabs (&context); - cexpr_init_symtab (&qfv_output_t_symtab, &context); - cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); - cexpr_init_symtab (&data_array_symtab, &context); + ectx.hashctx = &ctx->hashctx; + vkgen_init_symtabs (&ectx); + cexpr_init_symtab (&qfv_output_t_symtab, &ectx); + cexpr_init_symtab (&vulkan_frameset_t_symtab, &ectx); + cexpr_init_symtab (&data_array_symtab, &ectx); if (!ctx->setLayouts) { ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); From 7f25c434726cf13e2231d98eab6b68f844ff08f1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Nov 2022 23:44:07 +0900 Subject: [PATCH 3243/3664] [vulkan] Make script support objects more private This will help keep changes to the scripting system localized once things are further cleaned up. --- include/QF/Vulkan/qf_vid.h | 8 + include/vid_vulkan.h | 23 +- libs/video/renderer/Makemodule.am | 12 +- libs/video/renderer/vid_render_vulkan.c | 3 +- libs/video/renderer/vulkan/vkparse.c | 501 ++++++++++++++++-- libs/video/renderer/vulkan/vkparse.h | 23 +- libs/video/renderer/vulkan/vulkan_lighting.c | 3 +- libs/video/renderer/vulkan/vulkan_output.c | 7 +- .../video/renderer/vulkan/vulkan_renderpass.c | 6 +- .../video/renderer/vulkan/vulkan_vid_common.c | 366 +------------ 10 files changed, 502 insertions(+), 450 deletions(-) diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index fed5e4928..f69875ee4 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -67,6 +67,14 @@ enum { QFV_attachSwapchain, }; +//FIXME name +typedef struct qfv_output_s { + VkExtent2D extent; + VkImageView view; + VkFormat format; + VkImageView *view_list; // per frame +} qfv_output_t; + struct vulkan_ctx_s; void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 58795a201..8f2d03e19 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -9,14 +9,6 @@ #include "QF/darray.h" #include "QF/simd/types.h" -//FIXME name -typedef struct qfv_output_s { - VkExtent2D extent; - VkImageView view; - VkFormat format; - VkImageView *view_list; // per frame -} qfv_output_t; - typedef struct vulkan_frame_s { VkFence fence; VkSemaphore imageAvailableSemaphore; @@ -48,21 +40,11 @@ typedef struct vulkan_ctx_s { struct qfv_device_s *device; struct qfv_swapchain_s *swapchain; VkSampleCountFlagBits msaaSamples; // FIXME not here? - struct hashctx_s *hashctx; //FIXME want per thread VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain - struct plitem_s *pipelineDef; uint32_t swapImageIndex; - struct hashtab_s *shaderModules; - struct hashtab_s *setLayouts; - struct hashtab_s *pipelineLayouts; - struct hashtab_s *descriptorPools; - struct hashtab_s *samplers; - struct hashtab_s *images; - struct hashtab_s *imageViews; - struct hashtab_s *renderpasses; - + struct scriptctx_s *script_context; struct texturectx_s *texture_context; struct matrixctx_s *matrix_context; struct aliasctx_s *alias_context; @@ -100,9 +82,6 @@ typedef struct vulkan_ctx_s { int window_height; int twod_scale; - //FIXME this is for the parser - qfv_output_t output; - #define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; #define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; #include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 6a1559fc7..625e81bb7 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -256,12 +256,8 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_texture.c \ libs/video/renderer/vulkan/vulkan_vid_common.c -libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vkparse_src) - -libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c) - -libs/video/renderer/vulkan/vulkan_vid_common.lo: \ - libs/video/renderer/vulkan/vulkan_vid_common.c \ +libs/video/renderer/vulkan/vkparse.lo: \ + libs/video/renderer/vulkan/vkparse.c \ $(vkparse_src) \ $(pl_quake_def_gen) \ $(pl_output_gen) \ @@ -270,6 +266,10 @@ libs/video/renderer/vulkan/vulkan_vid_common.lo: \ $(rp_output_gen) \ ${rp_shadow_gen} +libs/video/renderer/vulkan/shader.lo: \ + libs/video/renderer/vulkan/shader.c \ + $(vkshader_c) + qwaq_cmd = $(top_builddir)/ruamoko/qwaq/qwaq-cmd$(EXEEXT) vkparse_cinc = $(top_builddir)/libs/video/renderer/vulkan/vkparse.cinc diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index f4c59d61c..bc8188956 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -76,6 +76,7 @@ #include "r_internal.h" #include "vid_internal.h" #include "vid_vulkan.h" +#include "vulkan/vkparse.h" static vulkan_ctx_t *vulkan_ctx; @@ -324,7 +325,7 @@ vulkan_begin_frame (void) vulkan_ctx->output_renderpass->viewport.width = output.extent.width; vulkan_ctx->output_renderpass->viewport.height = output.extent.height; vulkan_ctx->output_renderpass->scissor.extent = output.extent; - vulkan_ctx->output = output; + Vulkan_Script_SetOutput (vulkan_ctx, &output); Vulkan_CreateAttachments (vulkan_ctx, vulkan_ctx->output_renderpass); QFV_AcquireNextImage (vulkan_ctx->swapchain, frame->imageAvailableSemaphore, diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 79fc093a9..d3248a261 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -32,6 +32,7 @@ #include "QF/cmem.h" #include "QF/cvar.h" +#include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" #include "QF/va.h" @@ -520,12 +521,13 @@ parse_VkRenderPass (const plitem_t *item, void **data, int ret = 1; exprctx_t ectx = *pctx->ectx; vulkan_ctx_t *ctx = pctx->vctx; + scriptctx_t *sctx = ctx->script_context; const char *name = PL_String (item); const char *path = resource_path (ctx, 0, name); Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkRenderPass: %s\n", path); - *handle = (VkRenderPass) QFV_GetHandle (ctx->renderpasses, path); + *handle = (VkRenderPass) QFV_GetHandle (sctx->renderpasses, path); if (*handle) { return 1; } @@ -542,7 +544,7 @@ parse_VkRenderPass (const plitem_t *item, void **data, // path not guaranteed to survive cexpr_eval_string due to va path = resource_path (ctx, 0, name); - QFV_AddHandle (ctx->renderpasses, path, (uint64_t) setLayout); + QFV_AddHandle (sctx->renderpasses, path, (uint64_t) setLayout); } return ret; } @@ -554,9 +556,10 @@ parse_VkShaderModule (const plitem_t *item, void **data, __auto_type handle = (VkShaderModule *) data[0]; vulkan_ctx_t *ctx = pctx->vctx; qfv_device_t *device = ctx->device; + scriptctx_t *sctx = ctx->script_context; const char *name = PL_String (item); - *handle = (VkShaderModule) QFV_GetHandle (ctx->shaderModules, name); + *handle = (VkShaderModule) QFV_GetHandle (sctx->shaderModules, name); if (*handle) { return 1; } @@ -567,7 +570,7 @@ parse_VkShaderModule (const plitem_t *item, void **data, PL_Message (messages, item, "could not find shader %s", name); return 0; } - QFV_AddHandle (ctx->shaderModules, name, (uint64_t) *handle); + QFV_AddHandle (sctx->shaderModules, name, (uint64_t) *handle); return 1; } @@ -580,13 +583,14 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, parsectx_t *pctx = context; exprctx_t ectx = *pctx->ectx; vulkan_ctx_t *ctx = pctx->vctx; + scriptctx_t *sctx = ctx->script_context; const char *name = PL_String (item); const char *path = resource_path (ctx, "setLayouts", name); Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkDescriptorSetLayout: %s\n", path); - *handle = (VkDescriptorSetLayout) QFV_GetHandle (ctx->setLayouts, path); + *handle = (VkDescriptorSetLayout) QFV_GetHandle (sctx->setLayouts, path); if (*handle) { return 1; } @@ -604,7 +608,7 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, // path not guaranteed to survive cexpr_eval_string due to va path = resource_path (ctx, "setLayouts", name); - QFV_AddHandle (ctx->setLayouts, path, (uint64_t) setLayout); + QFV_AddHandle (sctx->setLayouts, path, (uint64_t) setLayout); } return ret; } @@ -617,12 +621,13 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, int ret = 1; exprctx_t ectx = *pctx->ectx; vulkan_ctx_t *ctx = pctx->vctx; + scriptctx_t *sctx = ctx->script_context; const char *name = PL_String (item); const char *path = resource_path (ctx, "pipelineLayouts", name); Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkPipelineLayout: %s\n", path); - *handle = (VkPipelineLayout) QFV_GetHandle (ctx->pipelineLayouts, path); + *handle = (VkPipelineLayout) QFV_GetHandle (sctx->pipelineLayouts, path); if (*handle) { return 1; } @@ -639,7 +644,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, // path not guaranteed to survive cexpr_eval_string due to va path = resource_path (ctx, "pipelineLayouts", name); - QFV_AddHandle (ctx->pipelineLayouts, path, (uint64_t) layout); + QFV_AddHandle (sctx->pipelineLayouts, path, (uint64_t) layout); } return ret; } @@ -652,12 +657,13 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, int ret = 1; exprctx_t ectx = *pctx->ectx; vulkan_ctx_t *ctx = pctx->vctx; + scriptctx_t *sctx = ctx->script_context; const char *name = PL_String (item); const char *path = resource_path (ctx, "images", name); Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImage: %s\n", path); - *handle = (VkImage) QFV_GetHandle (ctx->images, path); + *handle = (VkImage) QFV_GetHandle (sctx->images, path); if (*handle) { return 1; } @@ -674,7 +680,7 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, // path not guaranteed to survive cexpr_eval_string due to va path = resource_path (ctx, "images", name); - QFV_AddHandle (ctx->images, path, (uint64_t) image); + QFV_AddHandle (sctx->images, path, (uint64_t) image); } return ret; } @@ -696,12 +702,13 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, int ret = 1; exprctx_t ectx = *pctx->ectx; vulkan_ctx_t *ctx = pctx->vctx; + scriptctx_t *sctx = ctx->script_context; const char *name = PL_String (item); const char *path = resource_path (ctx, "imageViews", name); Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImageView: %s\n", path); - *handle = (VkImageView) QFV_GetHandle (ctx->imageViews, path); + *handle = (VkImageView) QFV_GetHandle (sctx->imageViews, path); if (*handle) { return 1; } @@ -722,7 +729,7 @@ parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, pctx->properties); // path not guaranteed to survive cexpr_eval_string due to va path = resource_path (ctx, "imageViews", name); - QFV_AddHandle (ctx->imageViews, path, (uint64_t) imageView); + QFV_AddHandle (sctx->imageViews, path, (uint64_t) imageView); } else { PL_Message (messages, item, "not a VkImageView"); return 0; @@ -749,9 +756,10 @@ handleref_free (void *hr, void *_ctx) static void setLayout_free (void *hr, void *_ctx) { + scriptctx_t *sctx = _ctx; __auto_type handleref = (handleref_t *) hr; __auto_type layout = (VkDescriptorSetLayout) handleref->handle; - __auto_type ctx = (vulkan_ctx_t *) _ctx; + __auto_type ctx = sctx->vctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -764,9 +772,10 @@ setLayout_free (void *hr, void *_ctx) static void shaderModule_free (void *hr, void *_ctx) { + scriptctx_t *sctx = _ctx; __auto_type handleref = (handleref_t *) hr; __auto_type module = (VkShaderModule) handleref->handle; - __auto_type ctx = (vulkan_ctx_t *) _ctx; + __auto_type ctx = sctx->vctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -779,9 +788,10 @@ shaderModule_free (void *hr, void *_ctx) static void pipelineLayout_free (void *hr, void *_ctx) { + scriptctx_t *sctx = _ctx; __auto_type handleref = (handleref_t *) hr; __auto_type layout = (VkPipelineLayout) handleref->handle; - __auto_type ctx = (vulkan_ctx_t *) _ctx; + __auto_type ctx = sctx->vctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -794,9 +804,10 @@ pipelineLayout_free (void *hr, void *_ctx) static void descriptorPool_free (void *hr, void *_ctx) { + scriptctx_t *sctx = _ctx; __auto_type handleref = (handleref_t *) hr; __auto_type pool = (VkDescriptorPool) handleref->handle; - __auto_type ctx = (vulkan_ctx_t *) _ctx; + __auto_type ctx = sctx->vctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -809,9 +820,10 @@ descriptorPool_free (void *hr, void *_ctx) static void sampler_free (void *hr, void *_ctx) { + scriptctx_t *sctx = _ctx; __auto_type handleref = (handleref_t *) hr; __auto_type sampler = (VkSampler) handleref->handle; - __auto_type ctx = (vulkan_ctx_t *) _ctx; + __auto_type ctx = sctx->vctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -824,9 +836,10 @@ sampler_free (void *hr, void *_ctx) static void image_free (void *hr, void *_ctx) { + scriptctx_t *sctx = _ctx; __auto_type handleref = (handleref_t *) hr; __auto_type image = (VkImage) handleref->handle; - __auto_type ctx = (vulkan_ctx_t *) _ctx; + __auto_type ctx = sctx->vctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -839,9 +852,10 @@ image_free (void *hr, void *_ctx) static void imageView_free (void *hr, void *_ctx) { + scriptctx_t *sctx = _ctx; __auto_type handleref = (handleref_t *) hr; __auto_type imageView = (VkImageView) handleref->handle; - __auto_type ctx = (vulkan_ctx_t *) _ctx; + __auto_type ctx = sctx->vctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -854,9 +868,10 @@ imageView_free (void *hr, void *_ctx) static void renderpass_free (void *hr, void *_ctx) { + scriptctx_t *sctx = _ctx; __auto_type handleref = (handleref_t *) hr; __auto_type renderpass = (VkRenderPass) handleref->handle; - __auto_type ctx = (vulkan_ctx_t *) _ctx; + __auto_type ctx = sctx->vctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -995,9 +1010,10 @@ exprtype_t vulkan_frameset_t_type = { }; static hashtab_t * -handlref_symtab (void (*free_func)(void*,void*), vulkan_ctx_t *ctx) +handlref_symtab (void (*free_func)(void*,void*), scriptctx_t *sctx) { - return Hash_NewTable (23, handleref_getkey, free_func, ctx, &ctx->hashctx); + return Hash_NewTable (23, handleref_getkey, free_func, sctx, + &sctx->hashctx); } static const char * @@ -1026,30 +1042,6 @@ root_symtab_init (void) cexpr_init_symtab (&root_symtab, &root_context); } -void -QFV_InitParse (vulkan_ctx_t *ctx) -{ - exprctx_t ectx = {}; - enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, &ctx->hashctx); - parser_table = Hash_NewTable (61, parser_getkey, 0, 0, &ctx->hashctx); - ectx.hashctx = &ctx->hashctx; - vkgen_init_symtabs (&ectx); - cexpr_init_symtab (&qfv_output_t_symtab, &ectx); - cexpr_init_symtab (&vulkan_frameset_t_symtab, &ectx); - cexpr_init_symtab (&data_array_symtab, &ectx); - - if (!ctx->setLayouts) { - ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); - ctx->setLayouts = handlref_symtab (setLayout_free, ctx); - ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx); - ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx); - ctx->samplers = handlref_symtab (sampler_free, ctx); - ctx->images = handlref_symtab (image_free, ctx); - ctx->imageViews = handlref_symtab (imageView_free, ctx); - ctx->renderpasses = handlref_symtab (renderpass_free, ctx); - } -} - exprenum_t * QFV_GetEnum (const char *name) { @@ -1060,11 +1052,12 @@ static int parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, plparser_t parser, void *object, plitem_t *properties) { + scriptctx_t *sctx = ctx->script_context; plitem_t *messages = PL_NewArray (); exprctx_t exprctx = { .symtab = &root_symtab }; parsectx_t parsectx = { &exprctx, ctx, properties }; exprsym_t var_syms[] = { - {"output", &qfv_output_t_type, &ctx->output}, + {"output", &qfv_output_t_type, &sctx->output}, {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {"physDevLimits", &VkPhysicalDeviceLimits_type, @@ -1076,7 +1069,7 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, exprctx.external_variables = &vars_tab; exprctx.messages = messages; - exprctx.hashctx = &ctx->hashctx; + exprctx.hashctx = &sctx->hashctx; exprctx.memsuper = memsuper; cexpr_init_symtab (&vars_tab, &exprctx); @@ -1395,6 +1388,7 @@ parse_imageviewcreate_dict (const plfield_t *field, const plitem_t *item, qfv_imageset_t * QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) { + scriptctx_t *sctx = ctx->script_context; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; memsuper_t *memsuper = new_memsuper (); @@ -1426,7 +1420,7 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) va (ctx->va_ctx, "image:%s", name)); qfvPopDebug (ctx); name = resource_path (ctx, "images", name); - QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]); + QFV_AddHandle (sctx->images, name, (uint64_t) set->a[i]); } delete_memsuper (memsuper); @@ -1437,6 +1431,7 @@ qfv_imageviewset_t * QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) { + scriptctx_t *sctx = ctx->script_context; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; memsuper_t *memsuper = new_memsuper (); @@ -1465,7 +1460,7 @@ QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, const char *name = PL_KeyAtIndex (item, i); name = resource_path (ctx, "imageViews", name); - QFV_AddHandle (ctx->imageViews, name, (uint64_t) set->a[i]); + QFV_AddHandle (sctx->imageViews, name, (uint64_t) set->a[i]); } delete_memsuper (memsuper); @@ -1594,3 +1589,409 @@ QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, delete_memsuper (memsuper); return ret; } + +int vulkan_frame_count; +static cvar_t vulkan_frame_count_cvar = { + .name = "vulkan_frame_count", + .description = + "Number of frames to render in the background. More frames can " + "increase performance, but at the cost of latency. The default of 3 is" + " recommended.", + .default_value = "3", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &vulkan_frame_count }, +}; +int vulkan_presentation_mode; +static cvar_t vulkan_presentation_mode_cvar = { + .name = "vulkan_presentation_mode", + .description = + "desired presentation mode (may fall back to fifo).", + .default_value = "mailbox", + .flags = CVAR_NONE, + .value = { + .type = &VkPresentModeKHR_type, + .value = &vulkan_presentation_mode, + }, +}; +int msaaSamples; +static cvar_t msaaSamples_cvar = { + .name = "msaaSamples", + .description = + "desired MSAA sample size.", + .default_value = "VK_SAMPLE_COUNT_1_BIT", + .flags = CVAR_NONE, + .value = { .type = &VkSampleCountFlagBits_type, .value = &msaaSamples }, +}; +static exprenum_t validation_enum; +static exprtype_t validation_type = { + .name = "vulkan_use_validation", + .size = sizeof (int), + .binops = cexpr_flag_binops, + .unops = cexpr_flag_unops, + .data = &validation_enum, + .get_string = cexpr_flags_get_string, +}; + +static int validation_values[] = { + 0, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT, +}; +static exprsym_t validation_symbols[] = { + {"none", &validation_type, validation_values + 0}, + {"all", &validation_type, validation_values + 1}, + {} +}; +static exprtab_t validation_symtab = { + validation_symbols, +}; +static exprenum_t validation_enum = { + &validation_type, + &validation_symtab, +}; +static cvar_t vulkan_use_validation_cvar = { + .name = "vulkan_use_validation", + .description = + "enable KRONOS Validation Layer if available (requires instance " + "restart).", + .default_value = "error|warning", + .flags = CVAR_NONE, + .value = { .type = &validation_type, .value = &vulkan_use_validation }, +}; + +static void +vulkan_frame_count_f (void *data, const cvar_t *cvar) +{ + if (vulkan_frame_count < 1) { + Sys_Printf ("Invalid frame count: %d. Setting to 1\n", + vulkan_frame_count); + vulkan_frame_count = 1; + } +} + +void +Vulkan_Init_Cvars (void) +{ + int num_syms = 0; + for (exprsym_t *sym = VkDebugUtilsMessageSeverityFlagBitsEXT_symbols; + sym->name; sym++, num_syms++) { + } + for (exprsym_t *sym = validation_symbols; sym->name; sym++, num_syms++) { + } + validation_symtab.symbols = calloc (num_syms + 1, sizeof (exprsym_t)); + num_syms = 0; + for (exprsym_t *sym = VkDebugUtilsMessageSeverityFlagBitsEXT_symbols; + sym->name; sym++, num_syms++) { + validation_symtab.symbols[num_syms] = *sym; + validation_symtab.symbols[num_syms].type = &validation_type; + } + for (exprsym_t *sym = validation_symbols; sym->name; sym++, num_syms++) { + validation_symtab.symbols[num_syms] = *sym; + } + Cvar_Register (&vulkan_use_validation_cvar, 0, 0); + // FIXME implement fallback choices (instead of just fifo) + Cvar_Register (&vulkan_presentation_mode_cvar, 0, 0); + Cvar_Register (&vulkan_frame_count_cvar, vulkan_frame_count_f, 0); + Cvar_Register (&msaaSamples_cvar, 0, 0); +} + +static exprsym_t builtin_plist_syms[] = { + { .name = "quake_deferred", + .value = (void *) +#include "libs/video/renderer/vulkan/pl_quake_def.plc" + }, + { .name = "qf_output", + .value = (void *) +#include "libs/video/renderer/vulkan/pl_output.plc" + }, + { .name = "deferred", + .value = (void *) +#include "libs/video/renderer/vulkan/rp_deferred.plc" + }, + { .name = "shadow", + .value = (void *) +#include "libs/video/renderer/vulkan/rp_shadow.plc" + }, + { .name = "forward", + .value = (void *) +#include "libs/video/renderer/vulkan/rp_forward.plc" + }, + { .name = "output", + .value = (void *) +#include "libs/video/renderer/vulkan/rp_output.plc" + }, + {} +}; +static plitem_t **builtin_plists; +static exprtab_t builtin_configs = { .symbols = builtin_plist_syms }; + +static void +build_configs (scriptctx_t *sctx) +{ + int num_plists = 0; + for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { + num_plists++; + } + builtin_plists = malloc (num_plists * sizeof (plitem_t *)); + num_plists = 0; + for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { + plitem_t *item = PL_GetPropertyList (sym->value, &sctx->hashctx); + if (!item) { + // Syntax errors in the compiled-in plists are unrecoverable + Sys_Error ("Error parsing plist for %s", sym->name); + } + builtin_plists[num_plists] = item; + sym->value = &builtin_plists[num_plists]; + sym->type = &cexpr_plitem; + num_plists++; + } + exprctx_t ectx = { .hashctx = &sctx->hashctx }; + cexpr_init_symtab (&builtin_configs, &ectx); +} + +static plitem_t * +qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) +{ + scriptctx_t *sctx = ctx->script_context; + if (!sctx->pipelineDef) { + sctx->pipelineDef = Vulkan_GetConfig (ctx, "quake_deferred"); + } + + plitem_t *item = sctx->pipelineDef; + if (!item || !(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading %s\n", name); + } else { + Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name); + } + return item; +} + +plitem_t * +Vulkan_GetConfig (vulkan_ctx_t *ctx, const char *name) +{ + scriptctx_t *sctx = ctx->script_context; + if (!builtin_configs.tab) { + build_configs (sctx); + } + + plitem_t *config = 0; + exprval_t result = { .type = &cexpr_plitem, .value = &config }; + exprctx_t ectx = { + .result = &result, + .symtab = &builtin_configs, + .memsuper = new_memsuper (), + .hashctx = &sctx->hashctx, + .messages = PL_NewArray (), + }; + if (cexpr_eval_string (name, &ectx)) { + dstring_t *msg = dstring_newstr (); + + for (int i = 0; i < PL_A_NumObjects (ectx.messages); i++) { + dasprintf (msg, "%s\n", + PL_String (PL_ObjectAtIndex (ectx.messages, i))); + } + Sys_Printf ("%s", msg->str); + dstring_delete (msg); + config = 0; + } + PL_Free (ectx.messages); + delete_memsuper (ectx.memsuper); + return config; +} + +void Vulkan_Script_Init (vulkan_ctx_t *ctx) +{ + scriptctx_t *sctx = calloc (1, sizeof (scriptctx_t)); + sctx->vctx = ctx; + ctx->script_context = sctx; + + exprctx_t ectx = {}; + enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, &sctx->hashctx); + parser_table = Hash_NewTable (61, parser_getkey, 0, 0, &sctx->hashctx); + ectx.hashctx = &sctx->hashctx; + vkgen_init_symtabs (&ectx); + cexpr_init_symtab (&qfv_output_t_symtab, &ectx); + cexpr_init_symtab (&vulkan_frameset_t_symtab, &ectx); + cexpr_init_symtab (&data_array_symtab, &ectx); + + sctx->shaderModules = handlref_symtab (shaderModule_free, sctx); + sctx->setLayouts = handlref_symtab (setLayout_free, sctx); + sctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, sctx); + sctx->descriptorPools = handlref_symtab (descriptorPool_free, sctx); + sctx->samplers = handlref_symtab (sampler_free, sctx); + sctx->images = handlref_symtab (image_free, sctx); + sctx->imageViews = handlref_symtab (imageView_free, sctx); + sctx->renderpasses = handlref_symtab (renderpass_free, sctx); +} + +static void +clear_table (hashtab_t **table) +{ + if (*table) { + hashtab_t *tab = *table; + *table = 0; + Hash_DelTable (tab); + } +} + +void Vulkan_Script_Shutdown (vulkan_ctx_t *ctx) +{ + scriptctx_t *sctx = ctx->script_context; + + PL_Free (sctx->pipelineDef); + clear_table (&sctx->pipelineLayouts); + clear_table (&sctx->setLayouts); + clear_table (&sctx->shaderModules); + clear_table (&sctx->descriptorPools); + clear_table (&sctx->samplers); + + free (sctx); +} + +void Vulkan_Script_SetOutput (vulkan_ctx_t *ctx, qfv_output_t *output) +{ + scriptctx_t *sctx = ctx->script_context; + sctx->output = *output; +} + +VkPipeline +Vulkan_CreateComputePipeline (vulkan_ctx_t *ctx, const char *name) +{ + scriptctx_t *sctx = ctx->script_context; + plitem_t *item = qfv_load_pipeline (ctx, "pipelines"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading pipeline %s\n", name); + return 0; + } else { + Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline def %s\n", name); + } + VkPipeline pipeline = QFV_ParseComputePipeline (ctx, item, + sctx->pipelineDef); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, + va (ctx->va_ctx, "pipeline:%s", name)); + return pipeline; +} + +VkPipeline +Vulkan_CreateGraphicsPipeline (vulkan_ctx_t *ctx, const char *name) +{ + scriptctx_t *sctx = ctx->script_context; + plitem_t *item = qfv_load_pipeline (ctx, "pipelines"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading pipeline %s\n", name); + return 0; + } else { + Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline def %s\n", name); + } + VkPipeline pipeline = QFV_ParseGraphicsPipeline (ctx, item, + sctx->pipelineDef); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, + va (ctx->va_ctx, "pipeline:%s", name)); + return pipeline; +} + +VkDescriptorPool +Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) +{ + scriptctx_t *sctx = ctx->script_context; + hashtab_t *tab = sctx->descriptorPools; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".descriptorPools.%s", name); + __auto_type pool = (VkDescriptorPool) QFV_GetHandle (tab, path); + if (pool) { + return pool; + } + + plitem_t *item = qfv_load_pipeline (ctx, "descriptorPools"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading descriptor pool %s\n", name); + return 0; + } else { + Sys_MaskPrintf (SYS_vulkan_parse, "Found descriptor pool def %s\n", + name); + } + pool = QFV_ParseDescriptorPool (ctx, item, sctx->pipelineDef); + QFV_AddHandle (tab, path, (uint64_t) pool); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool, + va (ctx->va_ctx, "descriptor_pool:%s", name)); + return pool; +} + +VkPipelineLayout +Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) +{ + scriptctx_t *sctx = ctx->script_context; + hashtab_t *tab = sctx->pipelineLayouts; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); + __auto_type layout = (VkPipelineLayout) QFV_GetHandle (tab, path); + if (layout) { + return layout; + } + + plitem_t *item = qfv_load_pipeline (ctx, "pipelineLayouts"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading pipeline layout %s\n", name); + return 0; + } else { + Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline layout def %s\n", + name); + } + layout = QFV_ParsePipelineLayout (ctx, item, sctx->pipelineDef); + QFV_AddHandle (tab, path, (uint64_t) layout); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, + va (ctx->va_ctx, "pipeline_layout:%s", name)); + return layout; +} + +VkSampler +Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) +{ + scriptctx_t *sctx = ctx->script_context; + hashtab_t *tab = sctx->samplers; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".samplers.%s", name); + __auto_type sampler = (VkSampler) QFV_GetHandle (tab, path); + if (sampler) { + return sampler; + } + + plitem_t *item = qfv_load_pipeline (ctx, "samplers"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading sampler %s\n", name); + return 0; + } else { + Sys_MaskPrintf (SYS_vulkan_parse, "Found sampler def %s\n", name); + } + sampler = QFV_ParseSampler (ctx, item, sctx->pipelineDef); + QFV_AddHandle (tab, path, (uint64_t) sampler); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler, + va (ctx->va_ctx, "sampler:%s", name)); + return sampler; +} + +VkDescriptorSetLayout +Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) +{ + scriptctx_t *sctx = ctx->script_context; + hashtab_t *tab = sctx->setLayouts; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); + __auto_type set = (VkDescriptorSetLayout) QFV_GetHandle (tab, path); + if (set) { + return set; + } + + plitem_t *item = qfv_load_pipeline (ctx, "setLayouts"); + if (!(item = PL_ObjectForKey (item, name))) { + Sys_Printf ("error loading descriptor set %s\n", name); + return 0; + } else { + Sys_MaskPrintf (SYS_vulkan_parse, "Found descriptor set def %s\n", + name); + } + set = QFV_ParseDescriptorSetLayout (ctx, item, sctx->pipelineDef); + QFV_AddHandle (tab, path, (uint64_t) set); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, + set, va (ctx->va_ctx, "descriptor_set:%s", name)); + return set; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 101dfdad4..32480cad0 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -8,12 +8,33 @@ typedef struct parsectx_s { void *data; } parsectx_t; +typedef struct scriptctx_s { + struct vulkan_ctx_s *vctx; + struct hashctx_s *hashctx; + + struct plitem_s *pipelineDef; + struct hashtab_s *shaderModules; + struct hashtab_s *setLayouts; + struct hashtab_s *pipelineLayouts; + struct hashtab_s *descriptorPools; + struct hashtab_s *samplers; + struct hashtab_s *images; + struct hashtab_s *imageViews; + struct hashtab_s *renderpasses; + + qfv_output_t output; +} scriptctx_t; + +void Vulkan_Init_Cvars (void); +void Vulkan_Script_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Script_Shutdown (struct vulkan_ctx_s *ctx); +void Vulkan_Script_SetOutput (struct vulkan_ctx_s *ctx, qfv_output_t *output); + #include "QF/cexpr.h" #include "QF/plist.h" #define QFV_PROPERTIES "properties" -void QFV_InitParse (vulkan_ctx_t *ctx); exprenum_t *QFV_GetEnum (const char *name); uint64_t QFV_GetHandle (struct hashtab_s *tab, const char *name); diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 1d9367d72..d37675753 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -328,7 +328,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) // lighting_context initialized in Vulkan_Lighting_CreateRenderPasses - ctx->output = (qfv_output_t) {.format = VK_FORMAT_X8_D24_UNORM_PACK32 }; + Vulkan_Script_SetOutput (ctx, + &(qfv_output_t) { .format = VK_FORMAT_X8_D24_UNORM_PACK32 }); lightingctx_t *lctx = ctx->lighting_context; plitem_t *rp_def = lctx->qfv_renderpass->renderpassDef; plitem_t *rp_cfg = PL_ObjectForKey (rp_def, "renderpass_6"); diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 5d9e2c406..97493356b 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -54,6 +54,7 @@ #include "QF/Vulkan/swapchain.h" #include "vid_vulkan.h" +#include "vkparse.h"//FIXME static void update_input (qfv_renderframe_t *rFrame) @@ -165,8 +166,8 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&octx->frames, frames); octx->frames.grow = 0; - __auto_type pld = ctx->pipelineDef; - ctx->pipelineDef = Vulkan_GetConfig (ctx, "qf_output"); + __auto_type pld = ctx->script_context->pipelineDef;//FIXME + ctx->script_context->pipelineDef = Vulkan_GetConfig (ctx, "qf_output"); octx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "output"); octx->layout = Vulkan_CreatePipelineLayout (ctx, "output_layout"); @@ -192,7 +193,7 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) oframe->cmd, "cmd:output"); } - ctx->pipelineDef = pld; + ctx->script_context->pipelineDef = pld; free (sets); qfvPopDebug (ctx); diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index c779065f8..3d5c96093 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -159,7 +159,7 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, malloc); for (size_t i = 0; i < rp->framebuffers->size; i++) { - ctx->output.view = ctx->output.view_list[i]; + ctx->script_context->output.view = ctx->script_context->output.view_list[i]; rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, rp->renderpassDef); } @@ -230,14 +230,14 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass"); if (rp_cfg) { - hashtab_t *tab = ctx->renderpasses; + hashtab_t *tab = ctx->script_context->renderpasses; const char *path; path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); if (renderpass) { rp->renderpass = renderpass; } else { - ctx->output = *output; + Vulkan_Script_SetOutput (ctx, output); rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, rp->renderpassDef); QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index ea1d541bd..0f129bf03 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -59,144 +59,7 @@ #include "r_internal.h" #include "vid_vulkan.h" - #include "vkparse.h" -#include "libs/video/renderer/vulkan/vkparse.hinc" - -static exprsym_t builtin_plist_syms[] = { - { .name = "quake_deferred", - .value = (void *) -#include "libs/video/renderer/vulkan/pl_quake_def.plc" - }, - { .name = "qf_output", - .value = (void *) -#include "libs/video/renderer/vulkan/pl_output.plc" - }, - { .name = "deferred", - .value = (void *) -#include "libs/video/renderer/vulkan/rp_deferred.plc" - }, - { .name = "shadow", - .value = (void *) -#include "libs/video/renderer/vulkan/rp_shadow.plc" - }, - { .name = "forward", - .value = (void *) -#include "libs/video/renderer/vulkan/rp_forward.plc" - }, - { .name = "output", - .value = (void *) -#include "libs/video/renderer/vulkan/rp_output.plc" - }, - {} -}; -static plitem_t **builtin_plists; -static exprtab_t builtin_configs = { .symbols = builtin_plist_syms }; - -int vulkan_frame_count; -static cvar_t vulkan_frame_count_cvar = { - .name = "vulkan_frame_count", - .description = - "Number of frames to render in the background. More frames can " - "increase performance, but at the cost of latency. The default of 3 is" - " recommended.", - .default_value = "3", - .flags = CVAR_NONE, - .value = { .type = &cexpr_int, .value = &vulkan_frame_count }, -}; -int vulkan_presentation_mode; -static cvar_t vulkan_presentation_mode_cvar = { - .name = "vulkan_presentation_mode", - .description = - "desired presentation mode (may fall back to fifo).", - .default_value = "mailbox", - .flags = CVAR_NONE, - .value = { - .type = &VkPresentModeKHR_type, - .value = &vulkan_presentation_mode, - }, -}; -int msaaSamples; -static cvar_t msaaSamples_cvar = { - .name = "msaaSamples", - .description = - "desired MSAA sample size.", - .default_value = "VK_SAMPLE_COUNT_1_BIT", - .flags = CVAR_NONE, - .value = { .type = &VkSampleCountFlagBits_type, .value = &msaaSamples }, -}; -static exprenum_t validation_enum; -static exprtype_t validation_type = { - .name = "vulkan_use_validation", - .size = sizeof (int), - .binops = cexpr_flag_binops, - .unops = cexpr_flag_unops, - .data = &validation_enum, - .get_string = cexpr_flags_get_string, -}; - -static int validation_values[] = { - 0, - VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT, -}; -static exprsym_t validation_symbols[] = { - {"none", &validation_type, validation_values + 0}, - {"all", &validation_type, validation_values + 1}, - {} -}; -static exprtab_t validation_symtab = { - validation_symbols, -}; -static exprenum_t validation_enum = { - &validation_type, - &validation_symtab, -}; -static cvar_t vulkan_use_validation_cvar = { - .name = "vulkan_use_validation", - .description = - "enable KRONOS Validation Layer if available (requires instance " - "restart).", - .default_value = "error|warning", - .flags = CVAR_NONE, - .value = { .type = &validation_type, .value = &vulkan_use_validation }, -}; - -static void -vulkan_frame_count_f (void *data, const cvar_t *cvar) -{ - if (vulkan_frame_count < 1) { - Sys_Printf ("Invalid frame count: %d. Setting to 1\n", - vulkan_frame_count); - vulkan_frame_count = 1; - } -} - -static void -Vulkan_Init_Cvars (void) -{ - int num_syms = 0; - for (exprsym_t *sym = VkDebugUtilsMessageSeverityFlagBitsEXT_symbols; - sym->name; sym++, num_syms++) { - } - for (exprsym_t *sym = validation_symbols; sym->name; sym++, num_syms++) { - } - validation_symtab.symbols = calloc (num_syms + 1, sizeof (exprsym_t)); - num_syms = 0; - for (exprsym_t *sym = VkDebugUtilsMessageSeverityFlagBitsEXT_symbols; - sym->name; sym++, num_syms++) { - validation_symtab.symbols[num_syms] = *sym; - validation_symtab.symbols[num_syms].type = &validation_type; - } - for (exprsym_t *sym = validation_symbols; sym->name; sym++, num_syms++) { - validation_symtab.symbols[num_syms] = *sym; - } - Cvar_Register (&vulkan_use_validation_cvar, 0, 0); - // FIXME implement fallback choices (instead of just fifo) - Cvar_Register (&vulkan_presentation_mode_cvar, 0, 0); - Cvar_Register (&vulkan_frame_count_cvar, vulkan_frame_count_f, 0); - Cvar_Register (&msaaSamples_cvar, 0, 0); - R_Init_Cvars (); -} static const char *instance_extensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, @@ -214,27 +77,17 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) { Sys_MaskPrintf (SYS_vulkan, "Vulkan_Init_Common\n"); - QFV_InitParse (ctx); Vulkan_Init_Cvars (); + R_Init_Cvars (); + Vulkan_Script_Init (ctx); ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version DARRAY_INIT (&ctx->renderPasses, 4); } -static void -clear_table (hashtab_t **table) -{ - if (*table) { - hashtab_t *tab = *table; - *table = 0; - Hash_DelTable (tab); - } -} - void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { - PL_Free (ctx->pipelineDef); if (ctx->capture) { QFV_DestroyCapture (ctx->capture); } @@ -246,11 +99,7 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) } ctx->instance->funcs->vkDestroySurfaceKHR (ctx->instance->instance, ctx->surface, 0); - clear_table (&ctx->pipelineLayouts); - clear_table (&ctx->setLayouts); - clear_table (&ctx->shaderModules); - clear_table (&ctx->descriptorPools); - clear_table (&ctx->samplers); + Vulkan_Script_Shutdown (ctx); if (ctx->device) { QFV_DestroyDevice (ctx->device); } @@ -304,78 +153,6 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain); } -static void -build_configs (vulkan_ctx_t *ctx) -{ - int num_plists = 0; - for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { - num_plists++; - } - builtin_plists = malloc (num_plists * sizeof (plitem_t *)); - num_plists = 0; - for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { - plitem_t *item = PL_GetPropertyList (sym->value, &ctx->hashctx); - if (!item) { - // Syntax errors in the compiled-in plists are unrecoverable - Sys_Error ("Error parsing plist for %s", sym->name); - } - builtin_plists[num_plists] = item; - sym->value = &builtin_plists[num_plists]; - sym->type = &cexpr_plitem; - num_plists++; - } - exprctx_t ectx = { .hashctx = &ctx->hashctx }; - cexpr_init_symtab (&builtin_configs, &ectx); -} - -plitem_t * -Vulkan_GetConfig (vulkan_ctx_t *ctx, const char *name) -{ - if (!builtin_configs.tab) { - build_configs (ctx); - } - - plitem_t *config = 0; - exprval_t result = { .type = &cexpr_plitem, .value = &config }; - exprctx_t ectx = { - .result = &result, - .symtab = &builtin_configs, - .memsuper = new_memsuper (), - .hashctx = &ctx->hashctx, - .messages = PL_NewArray (), - }; - if (cexpr_eval_string (name, &ectx)) { - dstring_t *msg = dstring_newstr (); - - for (int i = 0; i < PL_A_NumObjects (ectx.messages); i++) { - dasprintf (msg, "%s\n", - PL_String (PL_ObjectAtIndex (ectx.messages, i))); - } - Sys_Printf ("%s", msg->str); - dstring_delete (msg); - config = 0; - } - PL_Free (ectx.messages); - delete_memsuper (ectx.memsuper); - return config; -} - -static plitem_t * -qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) -{ - if (!ctx->pipelineDef) { - ctx->pipelineDef = Vulkan_GetConfig (ctx, "quake_deferred"); - } - - plitem_t *item = ctx->pipelineDef; - if (!item || !(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading %s\n", name); - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name); - } - return item; -} - static int renderpass_cmp (const void *_a, const void *_b) { @@ -403,143 +180,6 @@ Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) } } -VkPipeline -Vulkan_CreateComputePipeline (vulkan_ctx_t *ctx, const char *name) -{ - plitem_t *item = qfv_load_pipeline (ctx, "pipelines"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading pipeline %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline def %s\n", name); - } - VkPipeline pipeline = QFV_ParseComputePipeline (ctx, item, - ctx->pipelineDef); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, - va (ctx->va_ctx, "pipeline:%s", name)); - return pipeline; -} - -VkPipeline -Vulkan_CreateGraphicsPipeline (vulkan_ctx_t *ctx, const char *name) -{ - plitem_t *item = qfv_load_pipeline (ctx, "pipelines"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading pipeline %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline def %s\n", name); - } - VkPipeline pipeline = QFV_ParseGraphicsPipeline (ctx, item, - ctx->pipelineDef); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, - va (ctx->va_ctx, "pipeline:%s", name)); - return pipeline; -} - -VkDescriptorPool -Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) -{ - hashtab_t *tab = ctx->descriptorPools; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".descriptorPools.%s", name); - __auto_type pool = (VkDescriptorPool) QFV_GetHandle (tab, path); - if (pool) { - return pool; - } - - plitem_t *item = qfv_load_pipeline (ctx, "descriptorPools"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading descriptor pool %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found descriptor pool def %s\n", - name); - } - pool = QFV_ParseDescriptorPool (ctx, item, ctx->pipelineDef); - QFV_AddHandle (tab, path, (uint64_t) pool); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool, - va (ctx->va_ctx, "descriptor_pool:%s", name)); - return pool; -} - -VkPipelineLayout -Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) -{ - hashtab_t *tab = ctx->pipelineLayouts; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); - __auto_type layout = (VkPipelineLayout) QFV_GetHandle (tab, path); - if (layout) { - return layout; - } - - plitem_t *item = qfv_load_pipeline (ctx, "pipelineLayouts"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading pipeline layout %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline layout def %s\n", - name); - } - layout = QFV_ParsePipelineLayout (ctx, item, ctx->pipelineDef); - QFV_AddHandle (tab, path, (uint64_t) layout); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, - va (ctx->va_ctx, "pipeline_layout:%s", name)); - return layout; -} - -VkSampler -Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) -{ - hashtab_t *tab = ctx->samplers; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".samplers.%s", name); - __auto_type sampler = (VkSampler) QFV_GetHandle (tab, path); - if (sampler) { - return sampler; - } - - plitem_t *item = qfv_load_pipeline (ctx, "samplers"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading sampler %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found sampler def %s\n", name); - } - sampler = QFV_ParseSampler (ctx, item, ctx->pipelineDef); - QFV_AddHandle (tab, path, (uint64_t) sampler); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler, - va (ctx->va_ctx, "sampler:%s", name)); - return sampler; -} - -VkDescriptorSetLayout -Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) -{ - hashtab_t *tab = ctx->setLayouts; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); - __auto_type set = (VkDescriptorSetLayout) QFV_GetHandle (tab, path); - if (set) { - return set; - } - - plitem_t *item = qfv_load_pipeline (ctx, "setLayouts"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading descriptor set %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found descriptor set def %s\n", - name); - } - set = QFV_ParseDescriptorSetLayout (ctx, item, ctx->pipelineDef); - QFV_AddHandle (tab, path, (uint64_t) set); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, - set, va (ctx->va_ctx, "descriptor_set:%s", name)); - return set; -} - void Vulkan_CreateFrames (vulkan_ctx_t *ctx) { From d673887bf17ade5e6b7358a21c1b30ab5ab2bc5e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Nov 2022 11:07:08 +0900 Subject: [PATCH 3244/3664] [vulkan] Get two render pass rendering working Things are a bit of a mess with interdependence between sub-module initialization and render pass initialization, and window resizing is broken, but the main render pass rendering to an image that is then post-processed (currently just blitted) is working. This will make it possible to implement fisheye and water warp (and other effects, of course). --- include/QF/Vulkan/qf_output.h | 2 ++ include/QF/Vulkan/qf_vid.h | 1 + libs/video/renderer/vulkan/rp_deferred.plist | 2 +- libs/video/renderer/vulkan/rp_output.plist | 8 ++--- libs/video/renderer/vulkan/vulkan_main.c | 10 ++---- libs/video/renderer/vulkan/vulkan_output.c | 32 ++++++++++++++++--- .../video/renderer/vulkan/vulkan_renderpass.c | 7 ++-- 7 files changed, 42 insertions(+), 20 deletions(-) diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index e657fa7c5..478aae67a 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -48,6 +48,7 @@ typedef struct outputctx_s { VkPipeline pipeline; VkPipelineLayout layout; VkSampler sampler; + qfv_output_t output; } outputctx_t; struct vulkan_ctx_s; @@ -55,5 +56,6 @@ struct vulkan_ctx_s; void Vulkan_Output_Init (struct vulkan_ctx_s *ctx); void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Output_CreateRenderPasses (struct vulkan_ctx_s *ctx); +qfv_output_t *Vulkan_Output_Get (struct vulkan_ctx_s *ctx)__attribute__((pure)); #endif//__QF_Vulkan_qf_output_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index f69875ee4..35023f1ca 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -72,6 +72,7 @@ typedef struct qfv_output_s { VkExtent2D extent; VkImageView view; VkFormat format; + uint32_t frames; VkImageView *view_list; // per frame } qfv_output_t; diff --git a/libs/video/renderer/vulkan/rp_deferred.plist b/libs/video/renderer/vulkan/rp_deferred.plist index de793c6e9..632cef496 100644 --- a/libs/video/renderer/vulkan/rp_deferred.plist +++ b/libs/video/renderer/vulkan/rp_deferred.plist @@ -175,7 +175,7 @@ format = $output.format; loadOp = clear; storeOp = store; - finalLayout = present_src_khr; + finalLayout = shader_read_only_optimal; }, ); subpasses = ( diff --git a/libs/video/renderer/vulkan/rp_output.plist b/libs/video/renderer/vulkan/rp_output.plist index 3ca2a42f4..940ab0579 100644 --- a/libs/video/renderer/vulkan/rp_output.plist +++ b/libs/video/renderer/vulkan/rp_output.plist @@ -14,7 +14,7 @@ initialLayout = undefined; }; images = { - color = { + ocolor = { @inherit = $properties.flat_color_image_template; format = r16g16b16a16_sfloat; }; @@ -34,10 +34,10 @@ }; }; imageViews = { - color = { + ocolor = { @inherit = $properties.flat_color_view_template; - image = color; - format = $properties.images.color.format; + image = ocolor; + format = $properties.images.ocolor.format; }; }; framebuffer = { diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 824312d3c..e5c509179 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -56,6 +56,7 @@ #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" @@ -175,14 +176,9 @@ main_draw (qfv_renderframe_t *rFrame) void Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) { - qfv_output_t output = { - .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[0], - .format = ctx->swapchain->format, - .view_list = ctx->swapchain->imageViews->a, - }; + qfv_output_t *output = Vulkan_Output_Get (ctx); __auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred", - &output, main_draw); + output, main_draw); rp->order = QFV_rp_main; DARRAY_APPEND (&ctx->renderPasses, rp); } diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 97493356b..76bdca10d 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -95,6 +95,8 @@ output_draw (qfv_renderframe_t *rFrame) outputframe_t *oframe = &octx->frames.a[ctx->curFrame]; VkCommandBuffer cmd = oframe->cmd; + DARRAY_APPEND (&rFrame->subpassCmdSets[0], cmd); + dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, @@ -133,18 +135,34 @@ output_draw (qfv_renderframe_t *rFrame) void Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx) { + outputctx_t *octx = calloc (1, sizeof (outputctx_t)); + ctx->output_context = octx; + qfv_output_t output = { .extent = ctx->swapchain->extent, .view = ctx->swapchain->imageViews->a[0], .format = ctx->swapchain->format, + .frames = ctx->swapchain->numImages, .view_list = ctx->swapchain->imageViews->a, }; __auto_type out = Vulkan_CreateRenderPass (ctx, "output", &output, output_draw); - out->order = QFV_rp_output; - DARRAY_APPEND (&ctx->renderPasses, out); ctx->output_renderpass = out; + + out->order = QFV_rp_output; + octx->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .view = out->attachment_views->a[0], + .format = VK_FORMAT_R16G16B16A16_SFLOAT,//FIXME + .frames = ctx->swapchain->numImages, + .view_list = malloc (sizeof (VkImageView) * ctx->swapchain->numImages), + }; + for (int i = 0; i < ctx->swapchain->numImages; i++) { + octx->output.view_list[i] = octx->output.view; + } + DARRAY_APPEND (&ctx->renderPasses, out); + __auto_type pre = Vulkan_CreateFunctionPass (ctx, "preoutput", update_input); pre->order = QFV_rp_preoutput; @@ -158,8 +176,7 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) qfvPushDebug (ctx, "output init"); - outputctx_t *octx = calloc (1, sizeof (outputctx_t)); - ctx->output_context = octx; + outputctx_t *octx = ctx->output_context; size_t frames = ctx->frames.size; DARRAY_INIT (&octx->frames, frames); @@ -210,3 +227,10 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx) free (octx->frames.a); free (octx); } + +qfv_output_t * +Vulkan_Output_Get (vulkan_ctx_t *ctx) +{ + outputctx_t *octx = ctx->output_context; + return &octx->output; +} diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 3d5c96093..6df766bd9 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -37,7 +37,6 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" -#include "QF/Vulkan/swapchain.h" #include "QF/Vulkan/qf_renderpass.h" #include "vid_vulkan.h" @@ -93,6 +92,7 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type rp = renderpass; + scriptctx_t *sctx = ctx->script_context; plitem_t *item = get_rp_item (ctx, rp, "images"); if (!item) { @@ -156,10 +156,9 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) return; } - rp->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages, - malloc); + rp->framebuffers = QFV_AllocFrameBuffers (sctx->output.frames, malloc); for (size_t i = 0; i < rp->framebuffers->size; i++) { - ctx->script_context->output.view = ctx->script_context->output.view_list[i]; + sctx->output.view = sctx->output.view_list[i]; rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, rp->renderpassDef); } From 7a91c905e04f29074f8abbe0ec70cb2c20114fb2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Nov 2022 11:12:05 +0900 Subject: [PATCH 3245/3664] [vulkan] Fix broken line drawing Line drawing was broken with the 2d depth pass (which will go away in the end, but I like the organization of the draw code). --- libs/video/renderer/Makemodule.am | 2 ++ libs/video/renderer/vulkan/vulkan_draw.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 625e81bb7..39716cfcc 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -449,6 +449,8 @@ vkshader_c = \ $(sprite_gbuff_c) \ $(sprite_depthv_c) \ $(sprite_depthf_c) \ + $(twodv_c) \ + $(twodf_c) \ $(twod_depthf_c) \ $(quakebspv_c) \ $(quakebspf_c) \ diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 713b7e165..b14d0e5b4 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1292,6 +1292,8 @@ draw_lines (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) VkPipelineLayout layout = dctx->layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 1, set, 0, 0); + dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE, + 1, 0, 0); } void From edc1326736eb8902c6f817b0a29bc1240c31112a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Nov 2022 12:57:56 +0900 Subject: [PATCH 3246/3664] [vulkan] Search for BGRA8 instead of RGBA8 I guess nvidia gives a non-srgb format as the first in the list, but my laptop gives an srgb format first, thus the unexpected difference in rendering brightness. Hard-coding BGRA isn't any better, but it will do for now. --- libs/video/renderer/vulkan/swapchain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index a2a962409..c8eff4768 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -93,7 +93,7 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) ifuncs->vkGetPhysicalDeviceSurfaceFormatsKHR (physDev, ctx->surface, &numFormats, formats); - VkSurfaceFormatKHR useFormat = {VK_FORMAT_R8G8B8A8_UNORM, + VkSurfaceFormatKHR useFormat = {VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}; if (numFormats > 1) { uint32_t i; From 87f99f90814f1dc18b0f424fdf8b26c18a79a874 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Nov 2022 13:35:07 +0900 Subject: [PATCH 3247/3664] [vulkan] Limit shadow textures to 32 This is the minimum maximum count for sampled images, and with layered shadow maps (with a minimum of 2048 layers supported), that's really way more than enough. --- include/QF/Vulkan/qf_lighting.h | 2 +- include/QF/Vulkan/qf_matrices.h | 5 ----- libs/video/renderer/vulkan/pl_quake_def.plist | 4 ++-- libs/video/renderer/vulkan/vulkan_lighting.c | 4 +--- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 5abb16e92..24296c9ff 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -58,7 +58,7 @@ typedef struct qfv_light_buffer_s { #define LIGHTING_BUFFER_INFOS 1 #define LIGHTING_ATTACH_INFOS 5 -#define LIGHTING_SHADOW_INFOS MaxLights +#define LIGHTING_SHADOW_INFOS 32 #define LIGHTING_DESCRIPTORS (LIGHTING_BUFFER_INFOS + LIGHTING_ATTACH_INFOS + 1) typedef struct lightingframe_s { diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index c9f57abb3..505bb1fe9 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -47,11 +47,6 @@ typedef struct qfv_matrix_buffer_s { vec4f_t pad2[3]; } qfv_matrix_buffer_t; -#define LIGHTING_BUFFER_INFOS 1 -#define LIGHTING_ATTACH_INFOS 5 -#define LIGHTING_SHADOW_INFOS MaxLights -#define LIGHTING_DESCRIPTORS (LIGHTING_BUFFER_INFOS + LIGHTING_ATTACH_INFOS + 1) - typedef struct matrixframe_s { //VkCommandBuffer cmd; VkBuffer buffer; diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 831def819..b4e2c5383 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -229,7 +229,7 @@ bindings = ( { type = combined_image_sampler; - descriptorCount = 768;//"$frames.size * size_t($properties.limits.maxSamplers)"; + descriptorCount = "$frames.size * size_t(32)"; }, ); }; @@ -378,7 +378,7 @@ { binding = 0; descriptorType = combined_image_sampler; - descriptorCount = 768;//$properties.limits.maxSamplers; + descriptorCount = 32; stageFlags = fragment; }, ); diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index d37675753..358a4b6c7 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -448,9 +448,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->shadowWrite = base_image_write; lframe->shadowWrite.dstSet = shadow_set->a[i]; lframe->shadowWrite.dstBinding = 0; - lframe->shadowWrite.descriptorCount - = min (MaxLights, - device->physDev->properties->limits.maxPerStageDescriptorSamplers); + lframe->shadowWrite.descriptorCount = LIGHTING_SHADOW_INFOS; lframe->shadowWrite.pImageInfo = lframe->shadowInfo; } free (shadow_set); From 92b36582ca70dd4e104cbd8d3ed59b2a468d0723 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Nov 2022 16:02:39 +0900 Subject: [PATCH 3248/3664] [vulkan] Change curFrame from size_t to uint32_t I very much doubt that even 4294967295 frames will be needed, let alone more. Saves me having to use %zd or %zu all over the place. --- include/vid_vulkan.h | 2 +- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 8f2d03e19..f5569ed7f 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -61,7 +61,7 @@ typedef struct vulkan_ctx_s { VkCommandPool cmdpool; struct qfv_stagebuf_s *staging; - size_t curFrame; + uint32_t curFrame; vulkan_frameset_t frames; qfv_renderpassset_t renderPasses; struct qfv_renderpass_s *output_renderpass; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 358a4b6c7..192faa38b 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -245,7 +245,7 @@ lighting_draw_maps (qfv_renderframe_t *rFrame) QFV_AllocateCommandBuffers (device, lctx->cmdpool, 0, bufferset); VkCommandBuffer cmd = bufferset->a[0]; QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - cmd, va (ctx->va_ctx, "lighting:%zd", ctx->curFrame)); + cmd, va (ctx->va_ctx, "lighting:%d", ctx->curFrame)); VkCommandBufferBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, From 0fdba75a6e71feecc9feeffeacbb22d348b7564a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Nov 2022 16:08:15 +0900 Subject: [PATCH 3249/3664] [vulkan] Move swap chain image acquisition to the output module Swap chain acquisition is part of final output handling. However, as the correct frame buffers are required for the render passes, the acquisition needs to be performed during the preoutput render pass. Window resize is still broken, but this is a big step towards fixing it. --- libs/video/renderer/vid_render_vulkan.c | 32 +------------- libs/video/renderer/vulkan/vulkan_output.c | 49 +++++++++++++++++++++- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index bc8188956..35c17481e 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -297,7 +297,6 @@ vulkan_Draw_FontString (int x, int y, int fontid, const char *str) static void vulkan_begin_frame (void) { - uint32_t imageIndex = 0; qfv_device_t *device = vulkan_ctx->device; qfv_devfuncs_t *dfunc = device->funcs; VkDevice dev = device->dev; @@ -305,43 +304,16 @@ vulkan_begin_frame (void) __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); - if (!QFV_AcquireNextImage (vulkan_ctx->swapchain, - frame->imageAvailableSemaphore, - 0, &imageIndex)) { - QFV_DeviceWaitIdle (device); - if (vulkan_ctx->capture) { - QFV_DestroyCapture (vulkan_ctx->capture); - } - Vulkan_CreateSwapchain (vulkan_ctx); - Vulkan_CreateCapture (vulkan_ctx); - - //FIXME - qfv_output_t output = { - .extent = vulkan_ctx->swapchain->extent, - .view = vulkan_ctx->swapchain->imageViews->a[0], - .format = vulkan_ctx->swapchain->format, - .view_list = vulkan_ctx->swapchain->imageViews->a, - }; - vulkan_ctx->output_renderpass->viewport.width = output.extent.width; - vulkan_ctx->output_renderpass->viewport.height = output.extent.height; - vulkan_ctx->output_renderpass->scissor.extent = output.extent; - Vulkan_Script_SetOutput (vulkan_ctx, &output); - Vulkan_CreateAttachments (vulkan_ctx, vulkan_ctx->output_renderpass); - QFV_AcquireNextImage (vulkan_ctx->swapchain, - frame->imageAvailableSemaphore, - 0, &imageIndex); - } - vulkan_ctx->swapImageIndex = imageIndex; } static void vulkan_render_view (void) { - uint32_t imageIndex = vulkan_ctx->swapImageIndex; - for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { __auto_type rp = vulkan_ctx->renderPasses.a[i]; __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; + // swapImageIndex may be updated by a render pass + uint32_t imageIndex = vulkan_ctx->swapImageIndex; if (rp->framebuffers) { rpFrame->framebuffer = rp->framebuffers->a[imageIndex]; } diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 76bdca10d..7251d520b 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -46,6 +46,7 @@ #include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_vid.h" +#include "QF/Vulkan/capture.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" @@ -56,6 +57,45 @@ #include "vid_vulkan.h" #include "vkparse.h"//FIXME +static void +acquire_image (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + //qfv_devfuncs_t *dfunc = device->funcs; + __auto_type frame = &ctx->frames.a[ctx->curFrame]; + //outputctx_t *octx = ctx->output_context; + //uint32_t curFrame = ctx->curFrame; + //outputframe_t *oframe = &octx->frames.a[curFrame]; + //qfv_renderpass_t *rp = ctx->output_renderpass; + + uint32_t imageIndex = 0; + while (!QFV_AcquireNextImage (ctx->swapchain, + frame->imageAvailableSemaphore, + 0, &imageIndex)) { + QFV_DeviceWaitIdle (device); + if (ctx->capture) { + QFV_DestroyCapture (ctx->capture); + } + Vulkan_CreateSwapchain (ctx); + Vulkan_CreateCapture (ctx); + + //FIXME + qfv_output_t output = { + .extent = ctx->swapchain->extent, + .view = ctx->swapchain->imageViews->a[0], + .format = ctx->swapchain->format, + .view_list = ctx->swapchain->imageViews->a, + }; + ctx->output_renderpass->viewport.width = output.extent.width; + ctx->output_renderpass->viewport.height = output.extent.height; + ctx->output_renderpass->scissor.extent = output.extent; + Vulkan_Script_SetOutput (ctx, &output); + Vulkan_CreateAttachments (ctx, ctx->output_renderpass); + } + ctx->swapImageIndex = imageIndex; +} + static void update_input (qfv_renderframe_t *rFrame) { @@ -85,6 +125,13 @@ update_input (qfv_renderframe_t *rFrame) dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); } +static void +preoutput_draw (qfv_renderframe_t *rFrame) +{ + acquire_image (rFrame); + update_input (rFrame); +} + static void output_draw (qfv_renderframe_t *rFrame) { @@ -164,7 +211,7 @@ Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx) DARRAY_APPEND (&ctx->renderPasses, out); __auto_type pre = Vulkan_CreateFunctionPass (ctx, "preoutput", - update_input); + preoutput_draw); pre->order = QFV_rp_preoutput; DARRAY_APPEND (&ctx->renderPasses, pre); } From 7e16822f210700ff5aad6be07b0ab1f69c63a939 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 25 Nov 2022 18:14:32 +0900 Subject: [PATCH 3250/3664] [vulkan] Recreate image available semaphore It turns out the semaphore used for vkAcquireNextImageKHR may be left in a signaled state for VK_ERROR_OUT_OF_DATE_KHR. While it seems to be possible to clear the semaphore using an empty queue submission, destroying and recreating the semaphore works well. Still have problems with the frame buffer after window resize, though. --- libs/video/renderer/vulkan/vulkan_output.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 7251d520b..2add01e15 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -62,7 +62,7 @@ acquire_image (qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; - //qfv_devfuncs_t *dfunc = device->funcs; + qfv_devfuncs_t *dfunc = device->funcs; __auto_type frame = &ctx->frames.a[ctx->curFrame]; //outputctx_t *octx = ctx->output_context; //uint32_t curFrame = ctx->curFrame; @@ -92,6 +92,10 @@ acquire_image (qfv_renderframe_t *rFrame) ctx->output_renderpass->scissor.extent = output.extent; Vulkan_Script_SetOutput (ctx, &output); Vulkan_CreateAttachments (ctx, ctx->output_renderpass); + + dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore, + 0); + frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); } ctx->swapImageIndex = imageIndex; } From 0dab26ce8f9405651fdf0c13f013a8b3194c458e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Nov 2022 22:10:29 +0900 Subject: [PATCH 3251/3664] [cexpr] Allow untyped result values If the result object type pointer is null, then the parsed result type and value pointers are written directly to the result object rather than testing the parsed result type against the object type and copying the parsed result value data to the location of the object value. It is then up to the caller to check the type and copy the value data. --- libs/util/cexpr-parse.y | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index f47176b9b..4b8155b45 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -186,7 +186,7 @@ arg_expr exprval_t * cexpr_assign_value (exprval_t *dst, const exprval_t *src, exprctx_t *context) { - binop_t *binop; + binop_t *binop = 0; if (!dst || !src) { return 0; } @@ -194,17 +194,24 @@ cexpr_assign_value (exprval_t *dst, const exprval_t *src, exprctx_t *context) *(exprval_t **) dst->value = (exprval_t *) src; return dst; } - binop = cexpr_find_cast (dst->type, src->type); + if (dst->type) { + binop = cexpr_find_cast (dst->type, src->type); + } if (binop && binop->op) { binop->func (dst, src, dst, context); } else { - if (dst->type != src->type) { - cexpr_error (context, - "type mismatch in expression result: %s = %s", - dst->type->name, src->type->name); - return dst; + if (!dst->type) { + dst->type = src->type; + dst->value = src->value; + } else { + if (dst->type != src->type) { + cexpr_error (context, + "type mismatch in expression result: %s = %s", + dst->type->name, src->type->name); + return dst; + } + memcpy (dst->value, src->value, dst->type->size); } - memcpy (dst->value, src->value, dst->type->size); } return dst; } From 7829ec3adb10912abff61e904d1a96ed0f917c9b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Nov 2022 22:15:15 +0900 Subject: [PATCH 3252/3664] [vkgen] Add support for read-only values This makes it possible to use the parser to read in certain fields, but skip over others. The read-only is for cexpr parsing of the read-only fields. --- .../video/renderer/vulkan/vkgen/Makemodule.am | 2 + libs/video/renderer/vulkan/vkgen/vkfielddef.r | 3 ++ .../renderer/vulkan/vkgen/vkfieldreadonly.h | 14 ++++++ .../renderer/vulkan/vkgen/vkfieldreadonly.r | 45 +++++++++++++++++++ .../video/renderer/vulkan/vkgen/vkfieldtype.h | 2 + .../video/renderer/vulkan/vkgen/vkfieldtype.r | 15 +++++++ libs/video/renderer/vulkan/vkgen/vulkan.r | 12 +++++ 7 files changed, 93 insertions(+) create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldreadonly.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index a1a0099b1..8d8e11f4e 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -11,6 +11,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkfieldcustom.r \ libs/video/renderer/vulkan/vkgen/vkfielddata.r \ libs/video/renderer/vulkan/vkgen/vkfielddef.r \ + libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.r \ libs/video/renderer/vulkan/vkgen/vkfieldstring.r \ libs/video/renderer/vulkan/vkgen/vkfieldtype.r \ @@ -53,6 +54,7 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/vkgen/vkfieldcustom.h \ libs/video/renderer/vulkan/vkgen/vkfielddata.h \ libs/video/renderer/vulkan/vkgen/vkfielddef.h \ + libs/video/renderer/vulkan/vkgen/vkfieldreadonly.h \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.h \ libs/video/renderer/vulkan/vkgen/vkfieldstring.h \ libs/video/renderer/vulkan/vkgen/vkfieldtype.h \ diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.r b/libs/video/renderer/vulkan/vkgen/vkfielddef.r index edf1e8a31..9a7f34bd0 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfielddef.r +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.r @@ -6,6 +6,7 @@ #include "vkfieldcustom.h" #include "vkfielddata.h" #include "vkfielddef.h" +#include "vkfieldreadonly.h" #include "vkfieldsingle.h" #include "vkfieldstring.h" #include "vkstruct.h" @@ -42,6 +43,8 @@ return [[[SingleField alloc] init:item struct:strct field:fname] autorelease]; case "array": return [[[ArrayField alloc] init:item struct:strct field:fname] autorelease]; + case "readonly": + return [[[ReadOnlyField alloc] init:item struct:strct field:fname] autorelease]; } return nil; } diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.h b/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.h new file mode 100644 index 000000000..3489a7b36 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.h @@ -0,0 +1,14 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldreadonly_h +#define __renderer_vulkan_vkgen_vkfieldreadonly_h + +#include "vkfielddef.h" + +@class FieldType; + +@interface ReadOnlyField: FieldDef +{ + FieldType *type; +} +@end + +#endif//__renderer_vulkan_vkgen_vkfieldreadonly_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r b/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r new file mode 100644 index 000000000..0353db7a1 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r @@ -0,0 +1,45 @@ +#include + +#include "vkfieldreadonly.h" +#include "vkfieldtype.h" +#include "vkgen.h" +#include "vktype.h" + +@implementation ReadOnlyField + +-init:(PLItem *) item struct:(Struct *)strct field:(string)fname +{ + self = [super init:item struct:strct field:fname]; + if (!self) { + return self; + } + + PLItem *desc = [item getObjectForKey:"type"]; + type = [[FieldType fieldType:[desc getObjectAtIndex:1]] retain]; + + value_field = [[item getObjectForKey:"value"] string]; + return self; +} + +-writeParseData +{ + return self; +} + +-writeField +{ + string parse_type = [FieldType anyType]; + fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, 0},\n", + field_name, parse_type, "ignore"); + return self; +} + +-writeSymbol +{ + fprintf (output_file, + "\t{\"%s\", %s, (void *) field_offset (%s, %s)},\n", + field_name, [type exprType], struct_name, value_field); + return self; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.h b/libs/video/renderer/vulkan/vkgen/vkfieldtype.h index 8e5d26bf8..88d117d4b 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldtype.h +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.h @@ -14,7 +14,9 @@ +fieldType:(PLItem *)item; -initWithItem:(PLItem *)item; -writeParseData; +-(string)exprType; -(string)parseType; ++(string)anyType; @end string parseItemType (PLItem *item); diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r index 53e75b476..83776a6a5 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r @@ -65,9 +65,24 @@ parseItemType (PLItem *item) return self; } +-(string) exprType +{ + return "&" + type + "_type"; +} + -(string) parseType { return parse_type; } ++(string) anyType +{ + string mask = "QFMultiType" + " | (1 << QFString)" + " | (1 << QFBinary)" + " | (1 << QFArray)" + " | (1 << QFDictionary)"; + return mask; +} + @end diff --git a/libs/video/renderer/vulkan/vkgen/vulkan.r b/libs/video/renderer/vulkan/vkgen/vulkan.r index 9d2a20a4c..47df077e4 100644 --- a/libs/video/renderer/vulkan/vkgen/vulkan.r +++ b/libs/video/renderer/vulkan/vkgen/vulkan.r @@ -7,3 +7,15 @@ typedef struct qfv_subpass_s { vec4 color; string name; } qfv_subpass_t; + +//FIXME copy of qfv_output_t in qf_renderpass.h +//except it doesn't really matter because a custom spec is used +typedef struct qfv_output_s { + VkExtent2D extent; + VkImage image; + VkImageView view; + VkFormat format; + uint32_t frames; + VkImageView *view_list; + VkImageLayout finalLayout; +} qfv_output_t; From 2cb3083f975ddd00b408c13fe1f7f546a723deb6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Nov 2022 22:22:22 +0900 Subject: [PATCH 3253/3664] [vulkan] Support parsing qfv_output_t This will be needed by the revamped render pass code. --- libs/video/renderer/vulkan/vkparse.c | 87 +++++++++++++++--------- libs/video/renderer/vulkan/vkparse.h | 2 + libs/video/renderer/vulkan/vkparse.plist | 17 +++++ 3 files changed, 73 insertions(+), 33 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index d3248a261..3e92b8d1d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -292,6 +292,13 @@ vkparse_alloc (void *context, size_t size) return cmemalloc (pctx->ectx->memsuper, size); } +static int +parse_ignore (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + return 1; +} + static int parse_single (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -649,6 +656,22 @@ parse_VkPipelineLayout (const plitem_t *item, void **data, return ret; } +exprtype_t VkImage_type = { + .name = "VkImage", + .size = sizeof (VkImage), + .binops = 0, + .unops = 0, + .data = 0 +}; + +exprtype_t VkImageView_type = { + .name = "VkImageView", + .size = sizeof (VkImageView), + .binops = 0, + .unops = 0, + .data = 0 +}; + static int parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *pctx) @@ -668,31 +691,29 @@ parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, return 1; } - plitem_t *imageItem = 0; - exprval_t result = { &cexpr_plitem, &imageItem }; + exprval_t result = { }; ectx.result = &result; ectx.item = item; ret = !cexpr_eval_string (path, &ectx); if (ret) { - VkImage image; - image = QFV_ParseImage (ctx, imageItem, pctx->properties); - *handle = (VkImage) image; + if (result.type == &cexpr_plitem) { + plitem_t *imageItem = *(plitem_t **) result.value; + VkImage image; + image = QFV_ParseImage (ctx, imageItem, pctx->properties); + *handle = (VkImage) image; - // path not guaranteed to survive cexpr_eval_string due to va - path = resource_path (ctx, "images", name); - QFV_AddHandle (sctx->images, path, (uint64_t) image); + // path not guaranteed to survive cexpr_eval_string due to va + path = resource_path (ctx, "images", name); + QFV_AddHandle (sctx->images, path, (uint64_t) image); + } else if (result.type == &VkImage_type) { + *handle = *(VkImage *) result.value; + } else { + ret = 0; + } } return ret; } -exprtype_t VkImageView_type = { - .name = "VkImageView", - .size = sizeof (VkImageView), - .binops = 0, - .unops = 0, - .data = 0 -}; - static int parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -977,23 +998,6 @@ parse_specialization_data (const plitem_t *item, void **data, #include "libs/video/renderer/vulkan/vkparse.cinc" -static exprsym_t qfv_output_t_symbols[] = { - {"format", &VkFormat_type, (void *)field_offset (qfv_output_t, format)}, - {"extent", &VkExtent2D_type, (void *)field_offset (qfv_output_t, extent)}, - {"view", &VkImageView_type, (void *)field_offset (qfv_output_t, view)}, - { } -}; -static exprtab_t qfv_output_t_symtab = { - qfv_output_t_symbols, -}; -exprtype_t qfv_output_t_type = { - .name = "qfv_output_t", - .size = sizeof (qfv_output_t), - .binops = cexpr_struct_binops, - .unops = 0, - .data = &qfv_output_t_symtab, -}; - static exprsym_t vulkan_frameset_t_symbols[] = { {"size", &cexpr_size_t, (void *)field_offset (vulkan_frameset_t, size)}, { } @@ -1590,6 +1594,23 @@ QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, return ret; } +int +QFV_ParseOutput (vulkan_ctx_t *ctx, qfv_output_t *output, plitem_t *plist, + plitem_t *properties) +{ + memsuper_t *memsuper = new_memsuper (); + int ret = 0; + qfv_output_t op = {}; + + if (parse_object (ctx, memsuper, plist, parse_qfv_output_t, &op, + properties)) { + memcpy (output, &op, sizeof (*output)); + ret = 1; + } + delete_memsuper (memsuper); + return ret; +} + int vulkan_frame_count; static cvar_t vulkan_frame_count_cvar = { .name = "vulkan_frame_count", diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 32480cad0..922cae566 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -75,4 +75,6 @@ struct qfv_subpassset_s *QFV_ParseSubpasses (vulkan_ctx_t *ctx, plitem_t *properties); int QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, plitem_t *properties); +int QFV_ParseOutput (vulkan_ctx_t *ctx, qfv_output_t *output, plitem_t *plist, + plitem_t *properties); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index b65e1b53f..f22ae092f 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -32,6 +32,7 @@ VkRenderPassMultiviewCreateInfo, qfv_subpass_t, + qfv_output_t, ); parse = { VkSubpassDescription = { @@ -392,5 +393,21 @@ string = name; }; }; + + qfv_output_s = { + .name = qfv_output_t; + extent = auto; + image = { + type = (readonly, VkImage); + value = image; + }; + view = { + type = (readonly, VkImageView); + value = view; + }; + format = auto; + frames = auto; + finalLayout = auto; + }; }; } From 336057887524f5efdf8eafc758765ee0d9c8c9e1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 26 Nov 2022 22:23:59 +0900 Subject: [PATCH 3254/3664] [vulkan] Rework render pass setup This splits up render pass creation so that the creation of the various resources can be tailored to the needs of the actual render pass sub-system. In addition, it gets window resizing mostly working (just some problems with incorrect rendering). --- include/QF/Vulkan/qf_output.h | 6 +- include/QF/Vulkan/qf_renderpass.h | 32 ++- include/QF/Vulkan/qf_vid.h | 9 - libs/video/renderer/vid_render_vulkan.c | 17 +- libs/video/renderer/vulkan/rp_deferred.plist | 20 +- libs/video/renderer/vulkan/rp_output.plist | 41 --- libs/video/renderer/vulkan/swapchain.c | 6 + libs/video/renderer/vulkan/vulkan_lighting.c | 5 +- libs/video/renderer/vulkan/vulkan_main.c | 13 +- libs/video/renderer/vulkan/vulkan_output.c | 49 ++-- .../video/renderer/vulkan/vulkan_renderpass.c | 233 +++++++++++------- .../video/renderer/vulkan/vulkan_vid_common.c | 2 +- 12 files changed, 228 insertions(+), 205 deletions(-) diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index 478aae67a..94b969d42 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -36,7 +36,7 @@ typedef struct outputframe_s { VkCommandBuffer cmd; - VkImageView view; + VkImageView input; VkDescriptorSet set; } outputframe_t; @@ -48,7 +48,7 @@ typedef struct outputctx_s { VkPipeline pipeline; VkPipelineLayout layout; VkSampler sampler; - qfv_output_t output; + VkImageView input; } outputctx_t; struct vulkan_ctx_s; @@ -56,6 +56,6 @@ struct vulkan_ctx_s; void Vulkan_Output_Init (struct vulkan_ctx_s *ctx); void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Output_CreateRenderPasses (struct vulkan_ctx_s *ctx); -qfv_output_t *Vulkan_Output_Get (struct vulkan_ctx_s *ctx)__attribute__((pure)); +void Vulkan_Output_SetInput (struct vulkan_ctx_s *ctx, VkImageView input); #endif//__QF_Vulkan_qf_output_h diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index 8dc95fdb2..e0acf580e 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -36,7 +36,18 @@ typedef struct clearvalueset_s typedef void (*qfv_draw_t) (qfv_renderframe_t *rFrame); +typedef struct qfv_output_s { + VkExtent2D extent; + VkImage image; // only if owned + VkImageView view; + VkFormat format; + uint32_t frames; + VkImageView *view_list; // per frame + VkImageLayout finalLayout; +} qfv_output_t; + typedef struct qfv_renderpass_s { + struct vulkan_ctx_s *vulkan_ctx; vec4f_t color; // for debugging const char *name; // for debugging struct plitem_s *renderpassDef; @@ -47,9 +58,11 @@ typedef struct qfv_renderpass_s { VkDeviceMemory attachmentMemory; size_t attachmentMemory_size; + qfv_output_t output; qfv_framebufferset_t *framebuffers; VkViewport viewport; VkRect2D scissor; + VkRect2D renderArea; int order; int primary_commands; size_t subpassCount; @@ -59,17 +72,12 @@ typedef struct qfv_renderpass_s { qfv_draw_t draw; } qfv_renderpass_t; -struct qfv_output_s; -qfv_renderpass_t *Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx, - const char *name, - struct qfv_output_s *output, - qfv_draw_t draw); -qfv_renderpass_t *Vulkan_CreateFunctionPass (struct vulkan_ctx_s *ctx, - const char *name, - qfv_draw_t function); -void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx, - qfv_renderpass_t *renderpass); -void Vulkan_CreateAttachments (struct vulkan_ctx_s *ctx, - qfv_renderpass_t *renderpass); +qfv_renderpass_t *QFV_RenderPass_New (struct vulkan_ctx_s *ctx, + const char *name, qfv_draw_t draw); +void QFV_RenderPass_Delete (qfv_renderpass_t *renderpass); +void QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass); +void QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass); +void QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass); + #endif//__QF_Vulkan_renderpass_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 35023f1ca..fed5e4928 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -67,15 +67,6 @@ enum { QFV_attachSwapchain, }; -//FIXME name -typedef struct qfv_output_s { - VkExtent2D extent; - VkImageView view; - VkFormat format; - uint32_t frames; - VkImageView *view_list; // per frame -} qfv_output_t; - struct vulkan_ctx_s; void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 35c17481e..0c572e001 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -367,11 +367,6 @@ vulkan_end_frame (void) VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - VkRenderPassBeginInfo renderPassInfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderArea = { {0, 0}, vulkan_ctx->swapchain->extent }, - }; - __auto_type cmdBufs = (qfv_cmdbufferset_t) DARRAY_STATIC_INIT (4); DARRAY_APPEND (&cmdBufs, frame->cmdBuffer); @@ -393,10 +388,14 @@ vulkan_end_frame (void) QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color); if (rpFrame->renderpass && rp->renderpass) { - renderPassInfo.framebuffer = rp->framebuffers->a[imageIndex]; - renderPassInfo.renderPass = rp->renderpass; - renderPassInfo.clearValueCount = rp->clearValues->size; - renderPassInfo.pClearValues = rp->clearValues->a; + VkRenderPassBeginInfo renderPassInfo = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = rp->renderpass, + .framebuffer = rp->framebuffers->a[imageIndex], + .renderArea = rp->renderArea, + .clearValueCount = rp->clearValues->size, + .pClearValues = rp->clearValues->a, + }; dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, rpFrame->subpassContents); diff --git a/libs/video/renderer/vulkan/rp_deferred.plist b/libs/video/renderer/vulkan/rp_deferred.plist index 632cef496..008cb6b5a 100644 --- a/libs/video/renderer/vulkan/rp_deferred.plist +++ b/libs/video/renderer/vulkan/rp_deferred.plist @@ -98,6 +98,20 @@ format = $properties.images.translucent.format; }; }; + output = { + image = { + @inherit = $properties.flat_color_image_template; + usage = color_attachment|input_attachment|sampled; + format = $output.format; + }; + view = { + @inherit = $properties.flat_color_view_template; + image = $output.image; + format = $output.format; + }; + format = r16g16b16a16_sfloat; + finalLayout = shader_read_only_optimal; + }; framebuffer = { renderPass = deferred; attachments = (depth, color, emission, normal, position, opaque, @@ -175,7 +189,7 @@ format = $output.format; loadOp = clear; storeOp = store; - finalLayout = shader_read_only_optimal; + finalLayout = $output.finalLayout; }, ); subpasses = ( @@ -289,14 +303,14 @@ dstAccessMask = input_attachment_read|depth_stencil_attachment_read; dependencyFlags = by_region; }, - { + /*{ srcSubpass = ~0u; // external dstSubpass = 1; // translucent srcStageMask = compute_shader; dstStageMask = vertex_input|draw_indirect; srcAccessMask = shader_write; dstAccessMask = vertex_attribute_read|indirect_command_read; - }, + },*/ { srcSubpass = 0; // depth dstSubpass = 2; // g-buffer diff --git a/libs/video/renderer/vulkan/rp_output.plist b/libs/video/renderer/vulkan/rp_output.plist index 940ab0579..f36286299 100644 --- a/libs/video/renderer/vulkan/rp_output.plist +++ b/libs/video/renderer/vulkan/rp_output.plist @@ -1,45 +1,4 @@ { - flat_color_image_template = { - imageType = `2d; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|sampled; - initialLayout = undefined; - }; - images = { - ocolor = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - }; - flat_color_view_template = { - viewType = VK_IMAGE_VIEW_TYPE_2D; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; - }; - imageViews = { - ocolor = { - @inherit = $properties.flat_color_view_template; - image = ocolor; - format = $properties.images.ocolor.format; - }; - }; framebuffer = { renderPass = output; attachments = ($output.view); diff --git a/libs/video/renderer/vulkan/swapchain.c b/libs/video/renderer/vulkan/swapchain.c index c8eff4768..c29606893 100644 --- a/libs/video/renderer/vulkan/swapchain.c +++ b/libs/video/renderer/vulkan/swapchain.c @@ -148,10 +148,16 @@ QFV_CreateSwapchain (vulkan_ctx_t *ctx, VkSwapchainKHR old_swapchain) sc->imageViews = DARRAY_ALLOCFIXED (qfv_imageviewset_t, numImages, malloc); dfuncs->vkGetSwapchainImagesKHR (dev, swapchain, &numImages, sc->images->a); for (uint32_t i = 0; i < numImages; i++) { + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE, + sc->images->a[i], + va (ctx->va_ctx, "image:swapchain:%d", i)); sc->imageViews->a[i] = QFV_CreateImageView (ctx->device, sc->images->a[i], VK_IMAGE_VIEW_TYPE_2D, sc->format, VK_IMAGE_ASPECT_COLOR_BIT); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE_VIEW, + sc->imageViews->a[i], + va (ctx->va_ctx, "iview:swapchain:%d", i)); } return sc; } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 192faa38b..59c43b09c 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -283,9 +283,8 @@ Vulkan_Lighting_CreateRenderPasses (vulkan_ctx_t *ctx) // extents are dynamic and filled in for each light // frame buffers are highly dynamic - qfv_output_t output = {}; - __auto_type rp = Vulkan_CreateRenderPass (ctx, "shadow", - &output, lighting_draw_maps); + __auto_type rp = QFV_RenderPass_New (ctx, "shadow", lighting_draw_maps); + QFV_RenderPass_CreateRenderPass (rp); rp->primary_commands = 1; rp->order = QFV_rp_shadowmap; DARRAY_APPEND (&ctx->renderPasses, rp); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index e5c509179..e4b783db3 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -176,9 +176,16 @@ main_draw (qfv_renderframe_t *rFrame) void Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) { - qfv_output_t *output = Vulkan_Output_Get (ctx); - __auto_type rp = Vulkan_CreateRenderPass (ctx, "deferred", - output, main_draw); + __auto_type rp = QFV_RenderPass_New (ctx, "deferred", main_draw); + rp->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .frames = ctx->swapchain->numImages, + }; + QFV_RenderPass_CreateAttachments (rp); + QFV_RenderPass_CreateRenderPass (rp); + QFV_RenderPass_CreateFramebuffer (rp); rp->order = QFV_rp_main; DARRAY_APPEND (&ctx->renderPasses, rp); + + Vulkan_Output_SetInput (ctx, rp->output.view); } diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 2add01e15..3266a5bd2 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -80,18 +80,17 @@ acquire_image (qfv_renderframe_t *rFrame) Vulkan_CreateSwapchain (ctx); Vulkan_CreateCapture (ctx); - //FIXME - qfv_output_t output = { + __auto_type out = ctx->output_renderpass; + out->output = (qfv_output_t) { .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[0], .format = ctx->swapchain->format, + .frames = ctx->swapchain->numImages, .view_list = ctx->swapchain->imageViews->a, }; - ctx->output_renderpass->viewport.width = output.extent.width; - ctx->output_renderpass->viewport.height = output.extent.height; - ctx->output_renderpass->scissor.extent = output.extent; - Vulkan_Script_SetOutput (ctx, &output); - Vulkan_CreateAttachments (ctx, ctx->output_renderpass); + out->viewport.width = out->output.extent.width; + out->viewport.height = out->output.extent.height; + out->scissor.extent = out->output.extent; + QFV_RenderPass_CreateFramebuffer (out); dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore, 0); @@ -109,15 +108,14 @@ update_input (qfv_renderframe_t *rFrame) outputctx_t *octx = ctx->output_context; uint32_t curFrame = ctx->curFrame; outputframe_t *oframe = &octx->frames.a[curFrame]; - qfv_renderpass_t *rp = ctx->output_renderpass; - if (rp->attachment_views->a[0] == oframe->view) { + if (oframe->input == octx->input) { return; } - oframe->view = rp->attachment_views->a[0]; + oframe->input = octx->input; VkDescriptorImageInfo imageInfo = { - octx->sampler, oframe->view, + octx->sampler, oframe->input, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; VkWriteDescriptorSet write[] = { @@ -189,33 +187,22 @@ Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx) outputctx_t *octx = calloc (1, sizeof (outputctx_t)); ctx->output_context = octx; - qfv_output_t output = { + __auto_type out = QFV_RenderPass_New (ctx, "output", output_draw); + out->output = (qfv_output_t) { .extent = ctx->swapchain->extent, - .view = ctx->swapchain->imageViews->a[0], .format = ctx->swapchain->format, .frames = ctx->swapchain->numImages, .view_list = ctx->swapchain->imageViews->a, }; - __auto_type out = Vulkan_CreateRenderPass (ctx, "output", - &output, output_draw); + QFV_RenderPass_CreateRenderPass (out); + QFV_RenderPass_CreateFramebuffer (out); ctx->output_renderpass = out; out->order = QFV_rp_output; - octx->output = (qfv_output_t) { - .extent = ctx->swapchain->extent, - .view = out->attachment_views->a[0], - .format = VK_FORMAT_R16G16B16A16_SFLOAT,//FIXME - .frames = ctx->swapchain->numImages, - .view_list = malloc (sizeof (VkImageView) * ctx->swapchain->numImages), - }; - for (int i = 0; i < ctx->swapchain->numImages; i++) { - octx->output.view_list[i] = octx->output.view; - } DARRAY_APPEND (&ctx->renderPasses, out); - __auto_type pre = Vulkan_CreateFunctionPass (ctx, "preoutput", - preoutput_draw); + __auto_type pre = QFV_RenderPass_New (ctx, "preoutput", preoutput_draw); pre->order = QFV_rp_preoutput; DARRAY_APPEND (&ctx->renderPasses, pre); } @@ -279,9 +266,9 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx) free (octx); } -qfv_output_t * -Vulkan_Output_Get (vulkan_ctx_t *ctx) +void +Vulkan_Output_SetInput (vulkan_ctx_t *ctx, VkImageView input) { outputctx_t *octx = ctx->output_context; - return &octx->output; + octx->input = input; } diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 6df766bd9..e7bc13fca 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -45,9 +45,7 @@ static plitem_t * get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name) { - if (!rp->renderpassDef) { - rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); - } + rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); plitem_t *item = rp->renderpassDef; if (!item) { @@ -87,20 +85,21 @@ destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } void -Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) +QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass) { + vulkan_ctx_t *ctx = renderpass->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type rp = renderpass; - scriptctx_t *sctx = ctx->script_context; - plitem_t *item = get_rp_item (ctx, rp, "images"); - if (!item) { - return; - } - - if (renderpass->framebuffers) { - destroy_framebuffers (ctx, renderpass); + if (rp->output.image) { + // if output has an image, then the view is owned by the renderpass + dfunc->vkDestroyImageView (device->dev, rp->output.view, 0); + dfunc->vkDestroyImage (device->dev, rp->output.image, 0); + free (rp->output.view_list); + rp->output.view_list = 0; + rp->output.view = 0; + rp->output.image = 0; } if (rp->attachment_views) { for (size_t i = 0; i < rp->attachment_views->size; i++) { @@ -118,11 +117,35 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) rp->attachment_images = 0; } - __auto_type images = QFV_ParseImageSet (ctx, item, rp->renderpassDef); - rp->attachment_images = images; + plitem_t *output_def = get_rp_item (ctx, rp, "output"); + plitem_t *images_def = get_rp_item (ctx, rp, "images"); + plitem_t *views_def = get_rp_item (ctx, rp, "imageViews"); + + plitem_t *rp_def = rp->renderpassDef; + size_t memSize = 0; - for (size_t i = 0; i < images->size; i++) { - memSize += get_image_size (images->a[i], device); + VkImage ref_image = 0; + if (output_def) { + // QFV_ParseOutput clears the structure, but extent and frames need to + // be preserved + qfv_output_t output = rp->output; + QFV_ParseOutput (ctx, &output, output_def, rp_def); + rp->output.format = output.format; + rp->output.finalLayout = output.finalLayout; + + plitem_t *image = PL_ObjectForKey (output_def, "image"); + Vulkan_Script_SetOutput (ctx, &rp->output); + rp->output.image = QFV_ParseImage (ctx, image, rp_def); + memSize += get_image_size (rp->output.image, device); + ref_image = rp->output.image; + } + if (images_def) { + __auto_type images = QFV_ParseImageSet (ctx, images_def, rp_def); + rp->attachment_images = images; + ref_image = images->a[0]; + for (size_t i = 0; i < images->size; i++) { + memSize += get_image_size (images->a[i], device); + } } VkDeviceMemory mem = rp->attachmentMemory; if (memSize > rp->attachmentMemory_size) { @@ -130,7 +153,7 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); } rp->attachmentMemory_size = memSize; - mem = QFV_AllocImageMemory (device, images->a[0], + mem = QFV_AllocImageMemory (device, ref_image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, memSize, 0); rp->attachmentMemory = mem; @@ -138,40 +161,110 @@ Vulkan_CreateAttachments (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) mem, "memory:framebuffers"); } size_t offset = 0; - for (size_t i = 0; i < images->size; i++) { - QFV_BindImageMemory (device, images->a[i], mem, offset); - offset += get_image_size (images->a[i], device); + if (rp->output.image) { + QFV_BindImageMemory (device, rp->output.image, mem, offset); + offset += get_image_size (rp->output.image, device); + + plitem_t *view = PL_ObjectForKey (output_def, "view"); + Vulkan_Script_SetOutput (ctx, &rp->output); + rp->output.view = QFV_ParseImageView (ctx, view, rp_def); + rp->output.view_list = malloc (rp->output.frames + * sizeof (VkImageView)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, + rp->output.image, + va (ctx->va_ctx, "image:%s:output", rp->name)); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE_VIEW, + rp->output.view, + va (ctx->va_ctx, "iview:%s:output", rp->name)); + for (uint32_t i = 0; i < rp->output.frames; i++) { + rp->output.view_list[i] = rp->output.view; + } + } + if (rp->attachment_images) { + __auto_type images = rp->attachment_images; + for (size_t i = 0; i < images->size; i++) { + QFV_BindImageMemory (device, images->a[i], mem, offset); + offset += get_image_size (images->a[i], device); + } } - item = get_rp_item (ctx, rp, "imageViews"); - if (!item) { - return; + if (views_def) { + __auto_type views = QFV_ParseImageViewSet (ctx, views_def, rp_def); + rp->attachment_views = views; + } +} + +void +QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass) +{ + vulkan_ctx_t *ctx = renderpass->vulkan_ctx; + __auto_type rp = renderpass; + + plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass"); + if (rp_cfg) { + hashtab_t *tab = ctx->script_context->renderpasses; + const char *path; + path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", rp->name); + __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); + if (renderpass) { + rp->renderpass = renderpass; + } else { + Vulkan_Script_SetOutput (ctx, &rp->output); + rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, + rp->renderpassDef); + QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); + QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, + rp->renderpass, va (ctx->va_ctx, + "renderpass:%s", + rp->name)); + } + rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, + "subpasses")); } - __auto_type views = QFV_ParseImageViewSet (ctx, item, rp->renderpassDef); - rp->attachment_views = views; - item = get_rp_item (ctx, rp, "framebuffer"); - if (!item) { - return; + plitem_t *item = get_rp_item (ctx, rp, "clearValues"); + rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef); +} + +void +QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass) +{ + vulkan_ctx_t *ctx = renderpass->vulkan_ctx; + __auto_type rp = renderpass; + + if (renderpass->framebuffers) { + destroy_framebuffers (ctx, renderpass); } - rp->framebuffers = QFV_AllocFrameBuffers (sctx->output.frames, malloc); - for (size_t i = 0; i < rp->framebuffers->size; i++) { - sctx->output.view = sctx->output.view_list[i]; - rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item, - rp->renderpassDef); + plitem_t *fb_def = get_rp_item (ctx, rp, "framebuffer"); + plitem_t *rp_def = rp->renderpassDef; + if (fb_def) { + rp->framebuffers = QFV_AllocFrameBuffers (rp->output.frames, malloc); + for (size_t i = 0; i < rp->framebuffers->size; i++) { + rp->output.view = rp->output.view_list[i]; + Vulkan_Script_SetOutput (ctx, &rp->output); + rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, fb_def, rp_def); + } } + + int width = rp->output.extent.width; + int height = rp->output.extent.height; + rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; + rp->scissor = (VkRect2D) { {0, 0}, {width, height} }; + rp->renderArea = (VkRect2D) { {0, 0}, {width, height} }; } static void init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, qfv_renderframe_t *rFrame) { - rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; rFrame->vulkan_ctx = ctx; rFrame->renderpass = rp; + rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; + rFrame->framebuffer = 0; rFrame->subpassCount = rp->subpassCount; + rFrame->subpassInfo = 0; if (rp->subpass_info) { rFrame->subpassInfo = rp->subpass_info->a; } @@ -188,6 +281,15 @@ destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + if (rp->output.image) { + // if output has an image, then the view is owned by the renderpass + dfunc->vkDestroyImageView (device->dev, rp->output.view, 0); + dfunc->vkDestroyImage (device->dev, rp->output.image, 0); + free (rp->output.view_list); + rp->output.view_list = 0; + rp->output.view = 0; + rp->output.image = 0; + } if (rp->attachment_views) { for (size_t i = 0; i < rp->attachment_views->size; i++) { dfunc->vkDestroyImageView (device->dev, @@ -218,35 +320,14 @@ destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } qfv_renderpass_t * -Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, - qfv_output_t *output, qfv_draw_t draw) +QFV_RenderPass_New (vulkan_ctx_t *ctx, const char *name, qfv_draw_t function) { - plitem_t *item; - qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); - + rp->vulkan_ctx = ctx; rp->name = name; + rp->draw = function; + rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); - plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass"); - if (rp_cfg) { - hashtab_t *tab = ctx->script_context->renderpasses; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); - __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); - if (renderpass) { - rp->renderpass = renderpass; - } else { - Vulkan_Script_SetOutput (ctx, output); - rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, - rp->renderpassDef); - QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, - rp->renderpass, va (ctx->va_ctx, - "renderpass:%s", name)); - } - rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, - "subpasses")); - } plitem_t *rp_info = get_rp_item (ctx, rp, "info"); if (rp_info) { plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_info"); @@ -255,7 +336,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, rp->renderpassDef); if (rp->subpass_info->size < rp->subpassCount) { Sys_Printf ("warning:%s:%d: insufficient entries in " - "subpass_info\n", name, PL_Line (subpass_info)); + "subpass_info\n", rp->name, PL_Line (subpass_info)); } if (!rp->subpassCount) { rp->subpassCount = rp->subpass_info->size; @@ -268,35 +349,6 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx, const char *name, } } - int width = output->extent.width; - int height = output->extent.height; - rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; - rp->scissor = (VkRect2D) { {0, 0}, {width, height} }; - - DARRAY_INIT (&rp->frames, 4); - DARRAY_RESIZE (&rp->frames, ctx->frames.size); - for (size_t i = 0; i < rp->frames.size; i++) { - init_renderframe (ctx, rp, &rp->frames.a[i]); - } - - item = get_rp_item (ctx, rp, "clearValues"); - rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef); - - rp->draw = draw; - - Vulkan_CreateAttachments (ctx, rp); - - return rp; -} - -qfv_renderpass_t * -Vulkan_CreateFunctionPass (vulkan_ctx_t *ctx, const char *name, - qfv_draw_t function) -{ - qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); - rp->name = name; - rp->draw = function; - DARRAY_INIT (&rp->frames, 4); DARRAY_RESIZE (&rp->frames, ctx->frames.size); for (size_t i = 0; i < rp->frames.size; i++) { @@ -306,8 +358,9 @@ Vulkan_CreateFunctionPass (vulkan_ctx_t *ctx, const char *name, } void -Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx, qfv_renderpass_t *renderpass) +QFV_RenderPass_Delete (qfv_renderpass_t *renderpass) { + vulkan_ctx_t *ctx = renderpass->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 0f129bf03..9466fc92f 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -176,7 +176,7 @@ void Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) { for (size_t i = 0; i < ctx->renderPasses.size; i++) { - Vulkan_DestroyRenderPass (ctx, ctx->renderPasses.a[i]); + QFV_RenderPass_Delete (ctx->renderPasses.a[i]); } } From 85d40123e75dc1d19aafa65c5cf73e94320137f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Nov 2022 00:35:38 +0900 Subject: [PATCH 3255/3664] [vulkan] Remove depth pass from 2d rendering I realized afterwards it wasn't really want I want as it would mess with things like water warp and other effects. --- include/QF/Vulkan/qf_draw.h | 1 - libs/video/renderer/vulkan/vulkan_draw.c | 13 ------------- 2 files changed, 14 deletions(-) diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 05d03e398..3c327b308 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -29,7 +29,6 @@ #define __QF_Vulkan_qf_draw_h typedef enum { - QFV_drawDepth, QFV_draw2d, QFV_drawNumPasses diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index b14d0e5b4..051847e82 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -74,12 +74,10 @@ #include "vid_vulkan.h" static const char * __attribute__((used)) draw_pass_names[] = { - "depth", "2d", }; static QFV_Subpass subpass_map[] = { - [QFV_drawDepth] = QFV_passDepth, [QFV_draw2d] = QFV_passTranslucent, }; @@ -199,7 +197,6 @@ typedef struct drawctx_s { qfv_resobj_t *slice_objects; qfv_resobj_t *glyph_objects; qfv_resobj_t *line_objects; - VkPipeline depth_pipeline; VkPipeline quad_pipeline; VkPipeline slice_pipeline; VkPipeline glyph_pipeline; @@ -547,7 +544,6 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) free (dctx->fonts.a[i].resource); } - dfunc->vkDestroyPipeline (device->dev, dctx->depth_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->slice_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->glyph_pipeline, 0); @@ -623,7 +619,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); - dctx->depth_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod_depth"); dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); dctx->slice_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "slice"); dctx->glyph_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "glyph"); @@ -1333,19 +1328,12 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) #undef a dfunc->vkFlushMappedMemoryRanges (device->dev, 3, ranges); - DARRAY_APPEND (&rFrame->subpassCmdSets[subpass_map[QFV_drawDepth]], - dframe->cmdSet.a[QFV_drawDepth]); DARRAY_APPEND (&rFrame->subpassCmdSets[subpass_map[QFV_draw2d]], dframe->cmdSet.a[QFV_draw2d]); - draw_begin_subpass (QFV_drawDepth, rFrame); draw_begin_subpass (QFV_draw2d, rFrame); if (dframe->quad_verts.count) { - bind_pipeline (rFrame, dctx->depth_pipeline, - dframe->cmdSet.a[QFV_drawDepth]); - draw_quads (rFrame, dframe->cmdSet.a[QFV_drawDepth]); - bind_pipeline (rFrame, dctx->quad_pipeline, dframe->cmdSet.a[QFV_draw2d]); draw_quads (rFrame, dframe->cmdSet.a[QFV_draw2d]); @@ -1365,7 +1353,6 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dframe->cmdSet.a[QFV_draw2d]); draw_lines (rFrame, dframe->cmdSet.a[QFV_draw2d]); } - draw_end_subpass (dframe->cmdSet.a[QFV_drawDepth], ctx); draw_end_subpass (dframe->cmdSet.a[QFV_draw2d], ctx); dframe->quad_verts.count = 0; From 22615f25ab04edb4973990b0bdc338a064afcad7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Nov 2022 09:51:01 +0900 Subject: [PATCH 3256/3664] [vulkan] Move 2d to the output render pass This separates 2d UI rendering from 3d world rendering, making way for various post-processing effects on the 3d render. --- libs/video/renderer/vulkan/pl_quake_def.plist | 35 +++++-------------- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- libs/video/renderer/vulkan/vulkan_main.c | 2 -- libs/video/renderer/vulkan/vulkan_output.c | 11 +++++- 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index b4e2c5383..389b31d34 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -1124,31 +1124,10 @@ inputAssembly = $properties.inputAssembly.alias; layout = sprite_layout; }; - twod_depth = { - @inherit = $properties.pipelines.depth_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/twod.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/twod_depth.frag; - }, - ); - vertexInput = $properties.vertexInput.twod; - inputAssembly = $properties.inputAssembly.twod; - rasterization = $properties.rasterization.counter_cw_cull_back; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.alpha_blend); - }; - layout = twod_layout; - }; twod = { - @inherit = $properties.pipelines.trans_base;//FIXME should be sparate + @inherit = $properties.pipelines.trans_base; + renderPass = output; + subpass = 0; stages = ( { stage = vertex; @@ -1172,7 +1151,9 @@ layout = twod_layout; }; slice = { - @inherit = $properties.pipelines.trans_base;//FIXME should be sparate + @inherit = $properties.pipelines.trans_base; + renderPass = output; + subpass = 0; stages = ( { stage = vertex; name = main; module = $builtin/slice.vert; }, { stage = fragment; name = main; module = $builtin/glyph.frag; }, @@ -1191,7 +1172,9 @@ layout = glyph_layout;//slices use the same descriptors as glyphs }; glyph = { - @inherit = $properties.pipelines.trans_base;//FIXME should be sparate + @inherit = $properties.pipelines.trans_base; + renderPass = output; + subpass = 0; stages = ( { stage = vertex; name = main; module = $builtin/glyph.vert; }, { stage = fragment; name = main; module = $builtin/glyph.frag; }, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 051847e82..6e58c3c4b 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -78,7 +78,7 @@ static const char * __attribute__((used)) draw_pass_names[] = { }; static QFV_Subpass subpass_map[] = { - [QFV_draw2d] = QFV_passTranslucent, + [QFV_draw2d] = 0, }; typedef struct descbatch_s { diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index e4b783db3..c5335d290 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -50,7 +50,6 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_compose.h" -#include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_lightmap.h" @@ -168,7 +167,6 @@ main_draw (qfv_renderframe_t *rFrame) { Vulkan_Matrix_Draw (rFrame); Vulkan_RenderView (rFrame); - Vulkan_FlushText (rFrame);//FIXME delayed by a frame? Vulkan_Lighting_Draw (rFrame); Vulkan_Compose_Draw (rFrame); } diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 3266a5bd2..ec7a83470 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -42,6 +42,7 @@ #include "QF/render.h" #include "QF/sys.h" +#include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_renderpass.h" @@ -135,7 +136,7 @@ preoutput_draw (qfv_renderframe_t *rFrame) } static void -output_draw (qfv_renderframe_t *rFrame) +process_input (qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -179,6 +180,14 @@ output_draw (qfv_renderframe_t *rFrame) QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); + +} + +static void +output_draw (qfv_renderframe_t *rFrame) +{ + process_input (rFrame); + Vulkan_FlushText (rFrame); } void From efc3443c61cff472f473c972df253e6e5aba6aa4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 27 Nov 2022 12:48:51 +0900 Subject: [PATCH 3257/3664] [vulkan] Create a water warp output pipeline Although it works as intended (tested via hacking), it's not hooked up as the current frame buffer handling in r_screen is not readily compatible with how vulkan output is handled. This will need some thought to get working. --- libs/video/renderer/Makemodule.am | 16 ++++++++-- libs/video/renderer/vulkan/pl_output.plist | 28 +++++++++++++++++ libs/video/renderer/vulkan/shader.c | 6 ++++ .../renderer/vulkan/shader/fstrianglest.vert | 12 +++++++ .../renderer/vulkan/shader/waterwarp.frag | 31 +++++++++++++++++++ 5 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 libs/video/renderer/vulkan/shader/fstrianglest.vert create mode 100644 libs/video/renderer/vulkan/shader/waterwarp.frag diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 39716cfcc..03f698aa9 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -359,8 +359,12 @@ passthrough_src = $(vkshaderpath)/passthrough.vert passthrough_c = $(vkshaderpath)/passthrough.vert.spvc fstriangle_src = $(vkshaderpath)/fstriangle.vert fstriangle_c = $(vkshaderpath)/fstriangle.vert.spvc +fstrianglest_src = $(vkshaderpath)/fstrianglest.vert +fstrianglest_c = $(vkshaderpath)/fstrianglest.vert.spvc pushcolor_src = $(vkshaderpath)/pushcolor.frag pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc +waterwarp_src = $(vkshaderpath)/waterwarp.frag +waterwarp_c = $(vkshaderpath)/waterwarp.frag.spvc $(slice_vert_c): $(slice_vert_src) @@ -432,8 +436,12 @@ $(passthrough_c): $(passthrough_src) $(fstriangle_c): $(fstriangle_src) +$(fstrianglest_c): $(fstrianglest_src) + $(pushcolor_c): $(pushcolor_src) +$(waterwarp_c): $(waterwarp_src) + vkshader_c = \ $(slice_c) \ $(glyphv_c) \ @@ -473,8 +481,10 @@ vkshader_c = \ $(output_c) \ $(passthrough_c) \ $(fstriangle_c) \ + $(fstrianglest_c) \ $(pushcolor_c) \ - $(shadow_c) + $(shadow_c) \ + $(waterwarp_c) V_VKGEN = $(V_VKGEN_@AM_V@) V_VKGEN_ = $(V_VKGEN_@AM_DEFAULT_V@) @@ -532,6 +542,7 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/lighting.frag \ libs/video/renderer/vulkan/shader/passthrough.vert \ libs/video/renderer/vulkan/shader/fstriangle.vert \ + libs/video/renderer/vulkan/shader/fstrianglest.vert \ libs/video/renderer/vulkan/shader/partphysics.comp \ libs/video/renderer/vulkan/shader/partupdate.comp \ libs/video/renderer/vulkan/shader/particle.vert \ @@ -547,4 +558,5 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/sprite_gbuf.frag \ libs/video/renderer/vulkan/shader/twod_depth.frag \ libs/video/renderer/vulkan/shader/twod.frag \ - libs/video/renderer/vulkan/shader/twod.vert + libs/video/renderer/vulkan/shader/twod.vert \ + libs/video/renderer/vulkan/shader/waterwarp.frag diff --git a/libs/video/renderer/vulkan/pl_output.plist b/libs/video/renderer/vulkan/pl_output.plist index 001b999c6..2262d53f3 100644 --- a/libs/video/renderer/vulkan/pl_output.plist +++ b/libs/video/renderer/vulkan/pl_output.plist @@ -56,6 +56,16 @@ output_layout = { setLayouts = (matrix_set, output_set); }; + waterwarp_layout = { + @inherit = $properties.pipelineLayouts.output_layout; + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "4"; + } + ); + }; }; depthStencil = { @@ -152,6 +162,11 @@ name = main; module = $builtin/fstriangle.vert; }; + vertexStageST = { + stage = vertex; + name = main; + module = $builtin/fstrianglest.vert; + }; vertexInput = { bindings = (); attributes = (); @@ -205,5 +220,18 @@ ); layout = output_layout; }; + waterwarp = { + @inherit = $properties.pipelines.output_base; + subpass = 0; + stages = ( + $properties.fstriangle.vertexStageST, + { + stage = fragment; + name = main; + module = $builtin/waterwarp.frag; + }, + ); + layout = waterwarp_layout; + }; }; } diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index fb34c7e05..133f23517 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -115,7 +115,11 @@ static static #include "libs/video/renderer/vulkan/shader/fstriangle.vert.spvc" static +#include "libs/video/renderer/vulkan/shader/fstrianglest.vert.spvc" +static #include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc" +static +#include "libs/video/renderer/vulkan/shader/waterwarp.frag.spvc" typedef struct shaderdata_s { const char *name; @@ -162,7 +166,9 @@ static shaderdata_t builtin_shaders[] = { { "output.frag", output_frag, sizeof (output_frag) }, { "passthrough.vert", passthrough_vert, sizeof (passthrough_vert) }, { "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) }, + { "fstrianglest.vert", fstrianglest_vert, sizeof (fstrianglest_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, + { "waterwarp.frag", waterwarp_frag, sizeof (waterwarp_frag) }, {} }; diff --git a/libs/video/renderer/vulkan/shader/fstrianglest.vert b/libs/video/renderer/vulkan/shader/fstrianglest.vert new file mode 100644 index 000000000..92a9c7d51 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/fstrianglest.vert @@ -0,0 +1,12 @@ +#version 450 + +layout (location = 0) out vec2 st; + +void +main () +{ + float x = (gl_VertexIndex & 2); + float y = (gl_VertexIndex & 1); + gl_Position = vec4 (2, 4, 0, 1) * vec4 (x, y, 0, 1) - vec4 (1, 1, 0, 0); + st = vec2(1, 2) * vec2(x, y); +} diff --git a/libs/video/renderer/vulkan/shader/waterwarp.frag b/libs/video/renderer/vulkan/shader/waterwarp.frag new file mode 100644 index 000000000..c0dce195f --- /dev/null +++ b/libs/video/renderer/vulkan/shader/waterwarp.frag @@ -0,0 +1,31 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; + +layout (set = 1, binding = 0) uniform sampler2D Input; + +layout (push_constant) uniform PushConstants { + float time; +}; + +layout (location = 0) in vec2 uv; + +layout (location = 0) out vec4 frag_color; + +const float S = 0.15625; +const float F = 2.5; +const float A = 0.01; +const vec2 B = vec2 (1, 1); +const float PI = 3.14159265; + +void +main (void) +{ + vec2 st; + st = uv * (1.0 - 2.0*A) + A * (B + sin ((time * S + F * uv.yx) * 2.0*PI)); + vec4 c = texture (Input, st); + frag_color = c;//vec4(uv, c.x, 1); +} From dd1b15c92f40b32994813db294555e298f587293 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Nov 2022 00:49:32 +0900 Subject: [PATCH 3258/3664] [vulkan] Give staging buffers storage usage Really, additional usage flags should be a parameter. Needed for particles as the particle updates are read directly from the staging buffer. --- libs/video/renderer/vulkan/staging.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index a0c48f7f5..ca40eaab7 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -52,7 +52,9 @@ QFV_CreateStagingBuffer (qfv_device_t *device, const char *name, size_t size, stage->device = device; stage->cmdPool = cmdPool; stage->buffer = QFV_CreateBuffer (device, size, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + VK_BUFFER_USAGE_TRANSFER_SRC_BIT + //FIXME make a param + | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, stage->buffer, dsprintf (str, "staging:buffer:%s", name)); stage->memory = QFV_AllocBufferMemory (device, stage->buffer, From d9b0ee22e68c6455dfac35c9d446098ddfb5b832 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Nov 2022 00:52:07 +0900 Subject: [PATCH 3259/3664] [vulkan] Get particle compute pipelines running I don't yet know whether they actually work (not rendering yet), but the system isn't locking up, and shutdown is clean, so at least resources are handled correctly. --- include/QF/Vulkan/funclist.h | 10 + include/QF/Vulkan/qf_particles.h | 15 +- include/QF/Vulkan/qf_vid.h | 1 + libs/video/renderer/vulkan/pl_quake_def.plist | 6 +- .../renderer/vulkan/shader/partupdate.comp | 47 +-- libs/video/renderer/vulkan/vulkan_particles.c | 280 +++++++++++++++--- .../video/renderer/vulkan/vulkan_vid_common.c | 2 + 7 files changed, 288 insertions(+), 73 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 42da63794..1dedc4c5f 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -101,12 +101,17 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkEndCommandBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkResetCommandBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateSemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateFence) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCreateEvent) DEVICE_LEVEL_VULKAN_FUNCTION (vkWaitForFences) DEVICE_LEVEL_VULKAN_FUNCTION (vkResetFences) DEVICE_LEVEL_VULKAN_FUNCTION (vkGetFenceStatus) +DEVICE_LEVEL_VULKAN_FUNCTION (vkResetEvent) +DEVICE_LEVEL_VULKAN_FUNCTION (vkSetEvent) +DEVICE_LEVEL_VULKAN_FUNCTION (vkGetEventStatus) DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueSubmit) DEVICE_LEVEL_VULKAN_FUNCTION (vkQueueWaitIdle) DEVICE_LEVEL_VULKAN_FUNCTION (vkDeviceWaitIdle) +DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyEvent) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroyFence) DEVICE_LEVEL_VULKAN_FUNCTION (vkDestroySemaphore) DEVICE_LEVEL_VULKAN_FUNCTION (vkFreeCommandBuffers) @@ -171,10 +176,15 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBeginRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdNextSubpass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdEndRenderPass) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindPipeline) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDispatch) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdClearColorImage) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdExecuteCommands) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdPushConstants) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdResetEvent) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetEvent) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdWaitEvents) + DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetViewport) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdSetScissor) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindVertexBuffers) diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index 26feb51fb..9b90863a9 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -3,6 +3,7 @@ #include "QF/darray.h" #include "QF/image.h" +#include "QF/render.h" #include "QF/Vulkan/command.h" @@ -37,14 +38,15 @@ typedef enum { typedef struct particleframe_s { VkCommandBuffer compute; - VkSemaphore physSem; - VkSemaphore drawSem; - VkSemaphore updateSem; - VkBuffer state; + VkEvent physicsEvent; + VkEvent updateEvent; + VkBuffer states; VkBuffer params; VkBuffer system; - VkDescriptorSet descriptors; + VkDescriptorSet curDescriptors; + VkDescriptorSet inDescriptors; + VkDescriptorSet newDescriptors; qfv_cmdbufferset_t cmdSet; } particleframe_t; @@ -58,7 +60,7 @@ typedef struct particlectx_s { VkPipeline update; VkPipeline draw; - VkDeviceMemory memory; + struct qfv_resource_s *resources; struct qfv_stagebuf_s *stage; VkDescriptorPool pool; @@ -77,5 +79,6 @@ struct psystem_s *Vulkan_ParticleSystem (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_DrawParticles (struct vulkan_ctx_s *ctx); +void Vulkan_Particles_CreateRenderPasses (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_particles_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index fed5e4928..1d74e90c1 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -39,6 +39,7 @@ */ enum { + QFV_rp_particles, QFV_rp_shadowmap, QFV_rp_preoutput, QFV_rp_main, diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 389b31d34..7130ea6ac 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -178,11 +178,11 @@ }; particle_pool = { flags = 0; - maxSets = $frames.size; + maxSets = "3z * $frames.size"; bindings = ( { type = storage_buffer; - descriptorCount = 3; + descriptorCount = "3z * 3z * $frames.size"; }, ); }; @@ -499,7 +499,7 @@ { stageFlags = compute; offset = 0; - size = "16 * 4 + 4"; + size = "4 * 4 + 4"; }, ); }; diff --git a/libs/video/renderer/vulkan/shader/partupdate.comp b/libs/video/renderer/vulkan/shader/partupdate.comp index adce81094..5a5ccd56f 100644 --- a/libs/video/renderer/vulkan/shader/partupdate.comp +++ b/libs/video/renderer/vulkan/shader/partupdate.comp @@ -19,38 +19,38 @@ struct Parameters { vec4 ramp; // [rate, max, alpha rate, scale rate] }; -layout(std140, set = 0, binding = 0) buffer InStates { - Particle particles[]; -} inState; - -layout(std140, set = 0, binding = 1) buffer InParameters { - Parameters parameters[]; -} inParameters; - -//doubles as VkDrawIndirectCommand -layout(std140, set = 0, binding = 2) buffer InSystem { - uint vertexCount; - uint particleCount; //instanceCount - uint firstVertex; - uint firstInstance; -} inSystem; - -layout(std140, set = 1, binding = 0) buffer OutStates { +layout(std140, set = 0, binding = 0) buffer OutStates { Particle particles[]; } outStates; -layout(std140, set = 1, binding = 1) buffer OutParameters { +layout(std140, set = 0, binding = 1) buffer OutParameters { Parameters parameters[]; } outParameters; //doubles as VkDrawIndirectCommand -layout(std140, set = 1, binding = 2) buffer OutSystem { +layout(std140, set = 0, binding = 2) buffer OutSystem { uint vertexCount; uint particleCount; //instanceCount uint firstVertex; uint firstInstance; } outSystem; +layout(std140, set = 1, binding = 0) buffer InStates { + Particle particles[]; +} inStates; + +layout(std140, set = 1, binding = 1) buffer InParameters { + Parameters parameters[]; +} inParameters; + +//doubles as VkDrawIndirectCommand +layout(std140, set = 1, binding = 2) buffer InSystem { + uint vertexCount; + uint particleCount; //instanceCount + uint firstVertex; + uint firstInstance; +} inSystem; + layout(std140, set = 2, binding = 0) buffer NewStates { Particle particles[]; } newStates; @@ -85,21 +85,24 @@ main () uint j = 0; // compact existing partles removing dead particles for (uint i = 0; i < inSystem.particleCount; i++) { - if (is_dead (inState.particles[i], inParameters.parameters[i])) { + if (is_dead (inStates.particles[i], inParameters.parameters[i])) { continue; } - outStates.particles[j] = inState.particles[i]; + outStates.particles[j] = inStates.particles[i]; outParameters.parameters[j] = inParameters.parameters[i]; j++; } // inject any new particles that aren't DOA for (uint i = 0; i < newSystem.particleCount && j < MaxParticles; i++) { - if (is_dead (inState.particles[i], inParameters.parameters[i])) { + if (is_dead (newStates.particles[i], newParameters.parameters[i])) { continue; } outStates.particles[j] = newStates.particles[i]; outParameters.parameters[j] = newParameters.parameters[i]; j++; } + outSystem.vertexCount = newSystem.vertexCount; outSystem.particleCount = j; + outSystem.firstVertex = newSystem.firstVertex; + outSystem.firstInstance = newSystem.firstInstance; } diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index e2fe68ac7..ba712f256 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -44,16 +44,25 @@ #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/resource.h" #include "QF/Vulkan/staging.h" #include "QF/Vulkan/qf_particles.h" +#include "QF/Vulkan/qf_renderpass.h" +#include "r_internal.h" #include "vid_vulkan.h" //FIXME make dynamic #define MaxParticles 2048 +typedef struct { + vec4f_t gravity; + float dT; +} particle_push_constants_t; + static const char * __attribute__((used)) particle_pass_names[] = { "draw", }; @@ -69,48 +78,90 @@ create_buffers (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; particlectx_t *pctx = ctx->particle_context; - size_t size = 0; size_t mp = MaxParticles; + size_t frames = ctx->frames.size; - VkMemoryRequirements stReq, parmReq, sysReq; - for (size_t i = 0; i < pctx->frames.size; i++) { - __auto_type pframe = &pctx->frames.a[i]; - pframe->state - = QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT - | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - pframe->params - = QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); - pframe->system - = QFV_CreateBuffer (device, sizeof (qfv_particle_t) * mp, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT - | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); - dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->state, - &stReq); - dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->params, - &parmReq); - dfunc->vkGetBufferMemoryRequirements (device->dev, pframe->system, - &sysReq); - size = QFV_NextOffset (size + stReq.size, &stReq); - size = QFV_NextOffset (size + parmReq.size, &parmReq); - size = QFV_NextOffset (size + sysReq.size, &sysReq); + pctx->resources = malloc (sizeof (qfv_resource_t) + // states buffer + + frames * sizeof (qfv_resobj_t) + // params buffer + + frames * sizeof (qfv_resobj_t) + // system buffer + + frames * sizeof (qfv_resobj_t)); + __auto_type state_objs = (qfv_resobj_t *) &pctx->resources[1]; + __auto_type param_objs = &state_objs[frames]; + __auto_type system_objs = ¶m_objs[frames]; + pctx->resources[0] = (qfv_resource_t) { + .name = "particles", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = 3 * frames, + .objects = state_objs, + }; + for (size_t i = 0; i < frames; i++) { + state_objs[i] = (qfv_resobj_t) { + .name = "states", + .type = qfv_res_buffer, + .buffer = { + .size = mp * sizeof (qfv_particle_t), + .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + }, + }; + param_objs[i] = (qfv_resobj_t) { + .name = "params", + .type = qfv_res_buffer, + .buffer = { + .size = mp * sizeof (qfv_parameters_t), + .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + }, + }; + system_objs[i] = (qfv_resobj_t) { + .name = "system", + .type = qfv_res_buffer, + .buffer = { + .size = sizeof (qfv_particle_system_t), + .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, + }, + }; } - size_t stageSize = (size / pctx->frames.size)*(pctx->frames.size + 1); + QFV_CreateResource (device, pctx->resources); + + size_t stageSize = (pctx->resources->size / frames)*(frames + 1); pctx->stage = QFV_CreateStagingBuffer (device, "particles", stageSize, ctx->cmdpool); - pctx->memory = QFV_AllocBufferMemory (device, pctx->frames.a[0].state, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - size, 0); - size_t offset = 0; - for (size_t i = 0; i < pctx->frames.size; i++) { + for (size_t i = 0; i < frames; i++) { __auto_type pframe = &pctx->frames.a[i]; - QFV_BindBufferMemory (device, pframe->state, pctx->memory, offset); - offset = QFV_NextOffset (offset + stReq.size, &parmReq); - QFV_BindBufferMemory (device, pframe->params, pctx->memory, offset); - offset = QFV_NextOffset (offset + parmReq.size, &sysReq); - QFV_BindBufferMemory (device, pframe->system, pctx->memory, offset); - offset = QFV_NextOffset (offset + sysReq.size, &stReq); + pframe->states = state_objs[i].buffer.buffer; + pframe->params = param_objs[i].buffer.buffer; + pframe->system = system_objs[i].buffer.buffer; + } + + for (size_t i = 0; i < frames; i++) { + __auto_type curr = &pctx->frames.a[i]; + __auto_type prev = &pctx->frames.a[(i + frames - 1) % frames]; + VkDescriptorBufferInfo bufferInfo[] = { + { curr->states, 0, VK_WHOLE_SIZE }, + { curr->params, 0, VK_WHOLE_SIZE }, + { curr->system, 0, VK_WHOLE_SIZE }, + { prev->states, 0, VK_WHOLE_SIZE }, + { prev->params, 0, VK_WHOLE_SIZE }, + { prev->system, 0, VK_WHOLE_SIZE }, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + curr->curDescriptors, 0, 0, 3, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .pBufferInfo = bufferInfo + 0 + }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + curr->inDescriptors, 0, 0, 3, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .pBufferInfo = bufferInfo + 3 + }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); } } @@ -118,6 +169,7 @@ void Vulkan_Particles_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; qfvPushDebug (ctx, "particles init"); @@ -141,9 +193,19 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) pctx->pool = Vulkan_CreateDescriptorPool (ctx, "particle_pool"); pctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "particle_set"); + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (3 * frames, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = pctx->setLayout; + } + __auto_type sets = QFV_AllocateDescriptorSet (device, pctx->pool, layouts); + for (size_t i = 0; i < frames; i++) { __auto_type pframe = &pctx->frames.a[i]; + pframe->curDescriptors = sets->a[i * 3 + 0]; + pframe->inDescriptors = sets->a[i * 3 + 1]; + pframe->newDescriptors = sets->a[i * 3 + 2]; + DARRAY_INIT (&pframe->cmdSet, QFV_particleNumPasses); DARRAY_RESIZE (&pframe->cmdSet, QFV_particleNumPasses); pframe->cmdSet.grow = 0; @@ -156,7 +218,18 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) va (ctx->va_ctx, "cmd:particle:%zd:%s", i, particle_pass_names[j])); } + + VkEventCreateInfo event = { VK_STRUCTURE_TYPE_EVENT_CREATE_INFO }; + dfunc->vkCreateEvent (device->dev, &event, 0, &pframe->physicsEvent); + dfunc->vkCreateEvent (device->dev, &event, 0, &pframe->updateEvent); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_EVENT, + pframe->physicsEvent, + va (ctx->va_ctx, "event:particle:physics:%zd", i)); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_EVENT, + pframe->updateEvent, + va (ctx->va_ctx, "event:particle:update:%zd", i)); } + free (sets); create_buffers (ctx); qfvPopDebug (ctx); } @@ -167,16 +240,17 @@ Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; particlectx_t *pctx = ctx->particle_context; + size_t frames = ctx->frames.size; - for (size_t i = 0; i < pctx->frames.size; i++) { + for (size_t i = 0; i < frames; i++) { __auto_type pframe = &pctx->frames.a[i]; - free (pframe->cmdSet.a); - dfunc->vkDestroyBuffer (device->dev, pframe->state, 0); - dfunc->vkDestroyBuffer (device->dev, pframe->params, 0); - dfunc->vkDestroyBuffer (device->dev, pframe->system, 0); + dfunc->vkDestroyEvent (device->dev, pframe->updateEvent, 0); + dfunc->vkDestroyEvent (device->dev, pframe->physicsEvent, 0); } - dfunc->vkFreeMemory (device->dev, pctx->memory, 0); + QFV_DestroyStagingBuffer (pctx->stage); + QFV_DestroyResource (device, pctx->resources); + free (pctx->resources); dfunc->vkDestroyPipeline (device->dev, pctx->physics, 0); dfunc->vkDestroyPipeline (device->dev, pctx->update, 0); @@ -190,3 +264,125 @@ Vulkan_ParticleSystem (vulkan_ctx_t *ctx) { return &ctx->particle_context->psystem; //FIXME support more } + +static void +particles_update (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + particlectx_t *pctx = ctx->particle_context; + __auto_type pframe = &pctx->frames.a[ctx->curFrame]; + + qfv_packet_t *packet = QFV_PacketAcquire (pctx->stage); + + __auto_type limits = &device->physDev->properties->limits; + VkMemoryRequirements req = { + .alignment = limits->minStorageBufferOffsetAlignment + }; + uint32_t numParticles = min (MaxParticles, pctx->psystem.numparticles); + size_t syssize = sizeof (qfv_particle_system_t); + size_t partoffs = QFV_NextOffset (syssize, &req); + size_t partsize = sizeof (qfv_particle_t) * numParticles; + size_t paramoffs = QFV_NextOffset (partoffs + partsize, &req); + size_t paramsize = sizeof (qfv_parameters_t) * numParticles; + size_t size = paramoffs + paramsize; + + qfv_particle_system_t *system = QFV_PacketExtend (packet, size); + *system = (qfv_particle_system_t) { + .vertexCount = 1, + .particleCount = numParticles, + }; + __auto_type particles = (qfv_particle_t *) ((byte *)system + partoffs); + memcpy (particles, pctx->psystem.particles, partsize); + qfv_parameters_t *params = (qfv_parameters_t *)((byte *)system + paramoffs); + memcpy (params, pctx->psystem.partparams, paramsize); + + VkDescriptorBufferInfo bufferInfo[] = { + { packet->stage->buffer, 0, syssize }, + { packet->stage->buffer, partoffs, partsize ? partsize : 1}, + { packet->stage->buffer, paramoffs, paramsize ? paramsize : 1}, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + pframe->newDescriptors, 0, 0, 3, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .pBufferInfo = bufferInfo + }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + + dfunc->vkResetEvent (device->dev, pframe->updateEvent); + dfunc->vkResetEvent (device->dev, pframe->physicsEvent); + + dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, + pctx->update); + VkDescriptorSet set[3] = { + pframe->curDescriptors, + pframe->inDescriptors, + pframe->newDescriptors, + }; + dfunc->vkCmdBindDescriptorSets (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, + pctx->update_layout, 0, 3, set, 0, 0); + dfunc->vkCmdDispatch (packet->cmd, 1, 1, 1); + dfunc->vkCmdSetEvent (packet->cmd, pframe->updateEvent, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + + VkBufferMemoryBarrier barrier[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT, + 0, 0, + pframe->states, 0, VK_WHOLE_SIZE }, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT, + 0, 0, + pframe->params, 0, VK_WHOLE_SIZE }, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT, + 0, 0, + pframe->system, 0, VK_WHOLE_SIZE }, + }; + dfunc->vkCmdWaitEvents (packet->cmd, 1, &pframe->updateEvent, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + 0, 0, + 3, barrier, + 0, 0); + dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, + pctx->physics); + dfunc->vkCmdBindDescriptorSets (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, + pctx->physics_layout, 0, 1, set, 0, 0); + + particle_push_constants_t constants = { + .gravity = pctx->psystem.gravity, + .dT = vr_data.frametime, + }; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_COMPUTE_BIT, + field_offset (particle_push_constants_t, gravity), + sizeof (vec4f_t), &constants.gravity }, + { VK_SHADER_STAGE_COMPUTE_BIT, + field_offset (particle_push_constants_t, dT), + sizeof (float), &constants.dT }, + }; + QFV_PushConstants (device, packet->cmd, pctx->physics_layout, + 2, push_constants); + dfunc->vkCmdDispatch (packet->cmd, 8, 8, 8); + dfunc->vkCmdSetEvent (packet->cmd, pframe->physicsEvent, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + QFV_PacketSubmit (packet); +} + +void +Vulkan_Particles_CreateRenderPasses (vulkan_ctx_t *ctx) +{ + __auto_type rp = QFV_RenderPass_New (ctx, "particles", particles_update); + rp->order = QFV_rp_particles; + DARRAY_APPEND (&ctx->renderPasses, rp); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 9466fc92f..d1f5153e9 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -54,6 +54,7 @@ #include "QF/Vulkan/qf_lighting.h" #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_output.h" +#include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_vid.h" @@ -166,6 +167,7 @@ Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) { Vulkan_Output_CreateRenderPasses (ctx); Vulkan_Main_CreateRenderPasses (ctx); + Vulkan_Particles_CreateRenderPasses (ctx); Vulkan_Lighting_CreateRenderPasses (ctx); heapsort (ctx->renderPasses.a, ctx->renderPasses.size, From 30b38d7f3fad02dbe1dae29e7b6ca401d57d0cba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Nov 2022 10:21:20 +0900 Subject: [PATCH 3260/3664] [vulkan] Implement particle rendering They sort of kind of maybe try to work, but there's plenty wrong. I suspect synchronization and probably other factors. --- include/QF/Vulkan/funclist.h | 2 + include/QF/Vulkan/qf_particles.h | 7 +- libs/video/renderer/vulkan/pl_quake_def.plist | 12 ++- .../renderer/vulkan/shader/bsp_turb.frag | 10 +- .../renderer/vulkan/shader/particle.frag | 2 +- .../renderer/vulkan/shader/particle.vert | 6 +- libs/video/renderer/vulkan/vulkan_main.c | 1 + libs/video/renderer/vulkan/vulkan_particles.c | 94 +++++++++++++++++-- 8 files changed, 108 insertions(+), 26 deletions(-) diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 1dedc4c5f..6eb8d86bb 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -192,6 +192,8 @@ DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindIndexBuffer) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdBindDescriptorSets) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDraw) DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDrawIndexed) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDrawIndexedIndirect) +DEVICE_LEVEL_VULKAN_FUNCTION (vkCmdDrawIndirect) #undef DEVICE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index 9b90863a9..a805dfdd8 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -69,16 +69,17 @@ typedef struct particlectx_s { VkPipelineLayout update_layout; VkPipelineLayout draw_layout; - psystem_t psystem; + psystem_t *psystem; } particlectx_t; struct cvar_s; -struct vulkan_ctx_s;; +struct vulkan_ctx_s; +struct qfv_renderframe_s; struct psystem_s *Vulkan_ParticleSystem (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_DrawParticles (struct vulkan_ctx_s *ctx); +void Vulkan_DrawParticles (struct qfv_renderframe_s *rFrame); void Vulkan_Particles_CreateRenderPasses (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_particles_h diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 7130ea6ac..62a6be268 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -567,6 +567,10 @@ topology = triangle_strip; primitiveRestartEnable = true; }; + point = { + topology = point_list; + primitiveRestartEnable = false; + }; }; vertexInput = { @@ -646,13 +650,13 @@ }; particle = { bindings = ( - { binding = 0; stride = "4 * 4 * 4"; inputRate = vertex; }, + { binding = 0; stride = "4 * 4 * 4"; inputRate = instance; }, ); attributes = ( { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 32; }, + { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 48; }, ); }; twod = { @@ -1085,7 +1089,7 @@ }, ); vertexInput = $properties.vertexInput.particle; - inputAssembly = $properties.inputAssembly.sprite; + inputAssembly = $properties.inputAssembly.point; layout = partdraw_layout; }; sprite_gbuf = { diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index fe7e50b71..a98d91c02 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -43,13 +43,9 @@ fogBlend (vec4 color) void main (void) { - vec4 c = vec4 (0); - vec4 e; - vec3 t_st = vec3 (warp_st (tl_st.xy, time), 0); - vec3 e_st = vec3 (warp_st (tl_st.xy, time), 1); - - c = texture (Texture, t_st); - e = texture (Texture, e_st); + vec2 st = warp_st (tl_st.xy, time); + vec4 c = texture (Texture, vec3(st, 0)); + vec4 e = texture (Texture, vec3(st, 1)); float a = c.a * e.a * alpha; c += e; c.a = a; diff --git a/libs/video/renderer/vulkan/shader/particle.frag b/libs/video/renderer/vulkan/shader/particle.frag index 167c1f014..573a00a88 100644 --- a/libs/video/renderer/vulkan/shader/particle.frag +++ b/libs/video/renderer/vulkan/shader/particle.frag @@ -8,7 +8,7 @@ layout (location = 0) out vec4 frag_color; void main (void) { - vec4 c = color; + vec4 c = vec4 (1,1,1,1);//color; vec2 x = uv_tr.xy; float a = 1 - dot (x, x); diff --git a/libs/video/renderer/vulkan/shader/particle.vert b/libs/video/renderer/vulkan/shader/particle.vert index 85c5d12b2..2d38b9ffd 100644 --- a/libs/video/renderer/vulkan/shader/particle.vert +++ b/libs/video/renderer/vulkan/shader/particle.vert @@ -21,9 +21,9 @@ layout (location = 2) out vec4 o_ramp; void main (void) { - // geometry shader will take care of Projection and View - gl_Position = Model * position; - o_velocity = Model * velocity; + // geometry shader will take care of Projection + gl_Position = View * (Model * position); + o_velocity = View * (Model * velocity); o_color = color; o_ramp = ramp; } diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index c5335d290..763012428 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -136,6 +136,7 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) Vulkan_DrawViewModel (ctx); } Vulkan_DrawWaterSurfaces (rFrame); + Vulkan_DrawParticles (rFrame); Vulkan_Bsp_Flush (ctx); Vulkan_RenderEntities (r_ent_queue, rFrame); Vulkan_Scene_Flush (ctx); diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index ba712f256..19d9963b2 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -49,6 +49,7 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/resource.h" #include "QF/Vulkan/staging.h" +#include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" @@ -67,9 +68,83 @@ static const char * __attribute__((used)) particle_pass_names[] = { "draw", }; -void -Vulkan_DrawParticles (vulkan_ctx_t *ctx) +static void +particle_begin_subpass (VkPipeline pipeline, qfv_renderframe_t *rFrame) { + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + particlectx_t *pctx = ctx->particle_context; + uint32_t curFrame = ctx->curFrame; + particleframe_t *pframe = &pctx->frames.a[curFrame]; + VkCommandBuffer cmd = pframe->cmdSet.a[0]; + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + rFrame->renderpass->renderpass, QFV_passTranslucent, + rFrame->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "particles:%s", "draw"), + { 0.6, 0.5, 0, 1}); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + VkDescriptorSet sets[] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + pctx->draw_layout, 0, 1, sets, 0, 0); + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); +} + +static void +particle_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + + QFV_duCmdEndLabel (device, cmd); + dfunc->vkEndCommandBuffer (cmd); +} + +void +Vulkan_DrawParticles (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + particlectx_t *pctx = ctx->particle_context; + uint32_t curFrame = ctx->curFrame; + particleframe_t *pframe = &pctx->frames.a[curFrame]; + VkCommandBuffer cmd = pframe->cmdSet.a[0]; + + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], + pframe->cmdSet.a[0]); + + particle_begin_subpass (pctx->draw, rFrame); + + mat4f_t mat; + mat4fidentity (mat); + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat4f_t), &mat }, + }; + QFV_PushConstants (device, cmd, pctx->draw_layout, 1, push_constants); + VkDeviceSize offsets[] = { 0 }; + VkBuffer buffers[] = { + pframe->states, + }; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, buffers, offsets); + dfunc->vkCmdDrawIndirect (cmd, pframe->system, 0, 1, + sizeof (qfv_particle_system_t)); + particle_end_subpass (cmd, ctx); } static void @@ -175,6 +250,7 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) particlectx_t *pctx = calloc (1, sizeof (particlectx_t)); ctx->particle_context = pctx; + pctx->psystem = &r_psystem; size_t frames = ctx->frames.size; DARRAY_INIT (&pctx->frames, frames); @@ -262,7 +338,7 @@ Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx) psystem_t *__attribute__((pure))//FIXME? Vulkan_ParticleSystem (vulkan_ctx_t *ctx) { - return &ctx->particle_context->psystem; //FIXME support more + return ctx->particle_context->psystem; //FIXME support more } static void @@ -280,7 +356,7 @@ particles_update (qfv_renderframe_t *rFrame) VkMemoryRequirements req = { .alignment = limits->minStorageBufferOffsetAlignment }; - uint32_t numParticles = min (MaxParticles, pctx->psystem.numparticles); + uint32_t numParticles = min (MaxParticles, pctx->psystem->numparticles); size_t syssize = sizeof (qfv_particle_system_t); size_t partoffs = QFV_NextOffset (syssize, &req); size_t partsize = sizeof (qfv_particle_t) * numParticles; @@ -294,14 +370,14 @@ particles_update (qfv_renderframe_t *rFrame) .particleCount = numParticles, }; __auto_type particles = (qfv_particle_t *) ((byte *)system + partoffs); - memcpy (particles, pctx->psystem.particles, partsize); + memcpy (particles, pctx->psystem->particles, partsize); qfv_parameters_t *params = (qfv_parameters_t *)((byte *)system + paramoffs); - memcpy (params, pctx->psystem.partparams, paramsize); + memcpy (params, pctx->psystem->partparams, paramsize); VkDescriptorBufferInfo bufferInfo[] = { - { packet->stage->buffer, 0, syssize }, { packet->stage->buffer, partoffs, partsize ? partsize : 1}, { packet->stage->buffer, paramoffs, paramsize ? paramsize : 1}, + { packet->stage->buffer, 0, syssize }, }; VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, @@ -360,7 +436,7 @@ particles_update (qfv_renderframe_t *rFrame) pctx->physics_layout, 0, 1, set, 0, 0); particle_push_constants_t constants = { - .gravity = pctx->psystem.gravity, + .gravity = pctx->psystem->gravity, .dT = vr_data.frametime, }; qfv_push_constants_t push_constants[] = { @@ -377,6 +453,8 @@ particles_update (qfv_renderframe_t *rFrame) dfunc->vkCmdSetEvent (packet->cmd, pframe->physicsEvent, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); QFV_PacketSubmit (packet); + + pctx->psystem->numparticles = 0; } void From 51f3d9b777ab37ba71adbe61fd5123681de14815 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Nov 2022 11:09:20 +0900 Subject: [PATCH 3261/3664] [vulkan] Fix particle local and dispatch sizes This gets particles working in renderdoc, but they're quite broken stand-alone, which I think means that synchronization is a problem. --- libs/video/renderer/vulkan/shader/partphysics.comp | 2 +- libs/video/renderer/vulkan/vulkan_particles.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/partphysics.comp b/libs/video/renderer/vulkan/shader/partphysics.comp index 89dbc3ff6..9c9a933f8 100644 --- a/libs/video/renderer/vulkan/shader/partphysics.comp +++ b/libs/video/renderer/vulkan/shader/partphysics.comp @@ -1,6 +1,6 @@ #version 450 -layout (local_size_x = 32, local_size_y = 32) in; +layout (local_size_x = 1, local_size_y = 1) in; struct Particle { vec4 pos; diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 19d9963b2..adf72185c 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -449,7 +449,7 @@ particles_update (qfv_renderframe_t *rFrame) }; QFV_PushConstants (device, packet->cmd, pctx->physics_layout, 2, push_constants); - dfunc->vkCmdDispatch (packet->cmd, 8, 8, 8); + dfunc->vkCmdDispatch (packet->cmd, MaxParticles, 1, 1); dfunc->vkCmdSetEvent (packet->cmd, pframe->physicsEvent, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); QFV_PacketSubmit (packet); From 24c08a8dc4ad5f882580356eb2d4e3bd5e901269 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Nov 2022 15:16:52 +0900 Subject: [PATCH 3262/3664] [vulkan] Wait on physics event before drawing particles This should be more correct. At least it passes validation on my laptop (intel/llvm): I had trouble with it on nvidia. --- libs/video/renderer/vulkan/vulkan_particles.c | 56 +++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index adf72185c..984eb4c31 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -131,6 +131,34 @@ Vulkan_DrawParticles (qfv_renderframe_t *rFrame) particle_begin_subpass (pctx->draw, rFrame); + VkBufferMemoryBarrier barrier[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + 0, 0, + pframe->states, 0, VK_WHOLE_SIZE }, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + 0, 0, + pframe->params, 0, VK_WHOLE_SIZE }, + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT, + VK_ACCESS_INDIRECT_COMMAND_READ_BIT, + 0, 0, + pframe->system, 0, VK_WHOLE_SIZE }, + }; + dfunc->vkCmdWaitEvents (cmd, 1, &pframe->physicsEvent, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT + | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + 0, 0, + 3, barrier, + 0, 0); + mat4f_t mat; mat4fidentity (mat); qfv_push_constants_t push_constants[] = { @@ -374,9 +402,12 @@ particles_update (qfv_renderframe_t *rFrame) qfv_parameters_t *params = (qfv_parameters_t *)((byte *)system + paramoffs); memcpy (params, pctx->psystem->partparams, paramsize); + partsize = max (1, partsize); + paramsize = max (1, paramsize); + VkDescriptorBufferInfo bufferInfo[] = { - { packet->stage->buffer, partoffs, partsize ? partsize : 1}, - { packet->stage->buffer, paramoffs, paramsize ? paramsize : 1}, + { packet->stage->buffer, partoffs, partsize}, + { packet->stage->buffer, paramoffs, paramsize}, { packet->stage->buffer, 0, syssize }, }; VkWriteDescriptorSet write[] = { @@ -391,6 +422,21 @@ particles_update (qfv_renderframe_t *rFrame) dfunc->vkResetEvent (device->dev, pframe->updateEvent); dfunc->vkResetEvent (device->dev, pframe->physicsEvent); + VkBufferMemoryBarrier pl_barrier[] = { + { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_SHADER_READ_BIT, + 0, 0, + packet->stage->buffer, 0, paramoffs + paramsize }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + 0, + 0, 0, + 1, pl_barrier, + 0, 0); + dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pctx->update); VkDescriptorSet set[3] = { @@ -404,7 +450,7 @@ particles_update (qfv_renderframe_t *rFrame) dfunc->vkCmdSetEvent (packet->cmd, pframe->updateEvent, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - VkBufferMemoryBarrier barrier[] = { + VkBufferMemoryBarrier ev_barrier[] = { { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT @@ -428,7 +474,7 @@ particles_update (qfv_renderframe_t *rFrame) VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, - 3, barrier, + 3, ev_barrier, 0, 0); dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, pctx->physics); @@ -451,7 +497,7 @@ particles_update (qfv_renderframe_t *rFrame) 2, push_constants); dfunc->vkCmdDispatch (packet->cmd, MaxParticles, 1, 1); dfunc->vkCmdSetEvent (packet->cmd, pframe->physicsEvent, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); QFV_PacketSubmit (packet); pctx->psystem->numparticles = 0; From 38b56b4ce8e84474164d93d4d471fc556163b524 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Nov 2022 15:24:40 +0900 Subject: [PATCH 3263/3664] [vulkan] Use correct offsets for new particle descriptors This is probably the biggest reason I had problems with particles not updating correctly: the descriptors were generally point pointing to where the data actually was in the staging buffer. --- libs/video/renderer/vulkan/vulkan_particles.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 984eb4c31..fca17b4b8 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -405,10 +405,11 @@ particles_update (qfv_renderframe_t *rFrame) partsize = max (1, partsize); paramsize = max (1, paramsize); + size_t sysoffs = packet->offset; VkDescriptorBufferInfo bufferInfo[] = { - { packet->stage->buffer, partoffs, partsize}, - { packet->stage->buffer, paramoffs, paramsize}, - { packet->stage->buffer, 0, syssize }, + { packet->stage->buffer, sysoffs + partoffs, partsize}, + { packet->stage->buffer, sysoffs + paramoffs, paramsize}, + { packet->stage->buffer, sysoffs, syssize }, }; VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, @@ -427,7 +428,7 @@ particles_update (qfv_renderframe_t *rFrame) 0, VK_ACCESS_SHADER_READ_BIT, 0, 0, - packet->stage->buffer, 0, paramoffs + paramsize }, + packet->stage->buffer, sysoffs, paramoffs + paramsize }, }; dfunc->vkCmdPipelineBarrier (packet->cmd, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, From 76258906f900cc624e02f9f9e89128faec94e4de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Nov 2022 21:35:46 +0900 Subject: [PATCH 3264/3664] [vulkan] Skip use of the physics event It doesn't want to work on my nvidia (or more recent sid?) and doesn't seem to be necessary. The problem may be multiple event sets before the first wait, but investigation can wait for now. --- libs/video/renderer/vulkan/vulkan_particles.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index fca17b4b8..64079b5f7 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -130,7 +130,7 @@ Vulkan_DrawParticles (qfv_renderframe_t *rFrame) pframe->cmdSet.a[0]); particle_begin_subpass (pctx->draw, rFrame); - +/* VkBufferMemoryBarrier barrier[] = { { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, VK_ACCESS_SHADER_READ_BIT @@ -158,7 +158,7 @@ Vulkan_DrawParticles (qfv_renderframe_t *rFrame) 0, 0, 3, barrier, 0, 0); - +*/ mat4f_t mat; mat4fidentity (mat); qfv_push_constants_t push_constants[] = { @@ -449,7 +449,7 @@ particles_update (qfv_renderframe_t *rFrame) pctx->update_layout, 0, 3, set, 0, 0); dfunc->vkCmdDispatch (packet->cmd, 1, 1, 1); dfunc->vkCmdSetEvent (packet->cmd, pframe->updateEvent, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); VkBufferMemoryBarrier ev_barrier[] = { { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, @@ -497,8 +497,8 @@ particles_update (qfv_renderframe_t *rFrame) QFV_PushConstants (device, packet->cmd, pctx->physics_layout, 2, push_constants); dfunc->vkCmdDispatch (packet->cmd, MaxParticles, 1, 1); - dfunc->vkCmdSetEvent (packet->cmd, pframe->physicsEvent, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + //dfunc->vkCmdSetEvent (packet->cmd, pframe->physicsEvent, + // VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); QFV_PacketSubmit (packet); pctx->psystem->numparticles = 0; From b81a77c3f7df7d60e53b7294de4dd4f00aac49b1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 28 Nov 2022 22:57:22 +0900 Subject: [PATCH 3265/3664] [vulkan] Get particle colors working for id style This required making the texture set accessible to the vertex shader (instead of using a dedicated palette set), which I don't particularly like, but I don't feel like dealing with the texture code's hard-coded use of the texture set. QF style particles need something mostly for the smoke puffs as they expect a texture. --- libs/video/renderer/vulkan/pl_quake_def.plist | 4 ++-- libs/video/renderer/vulkan/shader/particle.frag | 4 ++-- libs/video/renderer/vulkan/shader/particle.vert | 6 +++++- libs/video/renderer/vulkan/vulkan_particles.c | 4 +++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 62a6be268..c747fe651 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -289,7 +289,7 @@ binding = 0; descriptorType = combined_image_sampler; descriptorCount = 1; - stageFlags = fragment; + stageFlags = fragment|vertex; }, ); }; @@ -507,7 +507,7 @@ setLayouts = (particle_set, particle_set, particle_set); }; partdraw_layout = { - setLayouts = (matrix_set); + setLayouts = (matrix_set, texture_set); pushConstantRanges = ( { stageFlags = vertex; diff --git a/libs/video/renderer/vulkan/shader/particle.frag b/libs/video/renderer/vulkan/shader/particle.frag index 573a00a88..5a5f5a887 100644 --- a/libs/video/renderer/vulkan/shader/particle.frag +++ b/libs/video/renderer/vulkan/shader/particle.frag @@ -8,13 +8,13 @@ layout (location = 0) out vec4 frag_color; void main (void) { - vec4 c = vec4 (1,1,1,1);//color; + vec4 c = color; vec2 x = uv_tr.xy; float a = 1 - dot (x, x); if (a <= 0) { discard; } - c.a *= sqrt (a); + c *= (a); frag_color = c; } diff --git a/libs/video/renderer/vulkan/shader/particle.vert b/libs/video/renderer/vulkan/shader/particle.vert index 2d38b9ffd..40a35c2c3 100644 --- a/libs/video/renderer/vulkan/shader/particle.vert +++ b/libs/video/renderer/vulkan/shader/particle.vert @@ -4,6 +4,7 @@ layout (set = 0, binding = 0) uniform #include "matrices.h" ; +layout (set = 1, binding = 0) uniform sampler2D Palette; layout (push_constant) uniform PushConstants { mat4 Model; @@ -24,6 +25,9 @@ main (void) // geometry shader will take care of Projection gl_Position = View * (Model * position); o_velocity = View * (Model * velocity); - o_color = color; + uint c = floatBitsToInt (color.x); + uint x = c & 0x0f; + uint y = (c >> 4) & 0x0f; + o_color = texture (Palette, vec2 (x, y) / 15.0); o_ramp = ramp; } diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 64079b5f7..714f4c492 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -50,6 +50,7 @@ #include "QF/Vulkan/resource.h" #include "QF/Vulkan/staging.h" #include "QF/Vulkan/qf_matrices.h" +#include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" @@ -98,9 +99,10 @@ particle_begin_subpass (VkPipeline pipeline, qfv_renderframe_t *rFrame) dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + Vulkan_Palette_Descriptor (ctx), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - pctx->draw_layout, 0, 1, sets, 0, 0); + pctx->draw_layout, 0, 2, sets, 0, 0); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); } From ecd5e1de9f41b5ecf1116319bf1523ffe0ff3558 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Dec 2022 02:50:07 +0900 Subject: [PATCH 3266/3664] [vulkan] Ensure render passes have at least one subpass Non-graphics render passes don't normally specify render pass info, but still want frames and command buffers. --- libs/video/renderer/vulkan/vulkan_renderpass.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index e7bc13fca..98a388a78 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -348,6 +348,9 @@ QFV_RenderPass_New (vulkan_ctx_t *ctx, const char *name, qfv_draw_t function) QFV_ParseRGBA (ctx, (float *)&rp->color, color, rp->renderpassDef); } } + if (!rp->subpassCount) { + rp->subpassCount = 1; + } DARRAY_INIT (&rp->frames, 4); DARRAY_RESIZE (&rp->frames, ctx->frames.size); From 00cade072ccdbc824d330ac8a5415cca9513806e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Dec 2022 03:00:47 +0900 Subject: [PATCH 3267/3664] [vulkan] Implement order implement transparency It's a bit flaky for particles, especially at higher frame rates, but that's due to supporting only 64 overlapping pixels. A reasonable solution is probably switching to a priority heap for the "sort" and upping the limit. --- include/QF/Vulkan/barrier.h | 3 + include/QF/Vulkan/qf_renderpass.h | 5 + include/QF/Vulkan/qf_translucent.h | 61 +++ include/QF/Vulkan/qf_vid.h | 12 +- include/vid_vulkan.h | 1 + libs/video/renderer/Makemodule.am | 15 +- libs/video/renderer/vid_render_vulkan.c | 3 + libs/video/renderer/vulkan/barrier.c | 36 ++ libs/video/renderer/vulkan/device.c | 1 + libs/video/renderer/vulkan/pl_quake_def.plist | 58 ++- libs/video/renderer/vulkan/rp_deferred.plist | 46 ++- libs/video/renderer/vulkan/shader.c | 3 + .../renderer/vulkan/shader/bsp_gbuf.frag | 2 +- .../video/renderer/vulkan/shader/bsp_sky.frag | 12 +- .../renderer/vulkan/shader/bsp_turb.frag | 10 +- libs/video/renderer/vulkan/shader/oit.h | 20 + .../renderer/vulkan/shader/oit_blend.frag | 40 ++ .../renderer/vulkan/shader/oit_store.finc | 14 + .../renderer/vulkan/shader/particle.frag | 6 +- libs/video/renderer/vulkan/vulkan_alias.c | 2 +- libs/video/renderer/vulkan/vulkan_bsp.c | 19 +- libs/video/renderer/vulkan/vulkan_iqm.c | 2 +- libs/video/renderer/vulkan/vulkan_main.c | 3 + libs/video/renderer/vulkan/vulkan_particles.c | 8 +- libs/video/renderer/vulkan/vulkan_sprite.c | 2 +- .../renderer/vulkan/vulkan_translucent.c | 358 ++++++++++++++++++ .../video/renderer/vulkan/vulkan_vid_common.c | 2 + 27 files changed, 694 insertions(+), 50 deletions(-) create mode 100644 include/QF/Vulkan/qf_translucent.h create mode 100644 libs/video/renderer/vulkan/shader/oit.h create mode 100644 libs/video/renderer/vulkan/shader/oit_blend.frag create mode 100644 libs/video/renderer/vulkan/shader/oit_store.finc create mode 100644 libs/video/renderer/vulkan/vulkan_translucent.c diff --git a/include/QF/Vulkan/barrier.h b/include/QF/Vulkan/barrier.h index b4f555ea0..6288241e2 100644 --- a/include/QF/Vulkan/barrier.h +++ b/include/QF/Vulkan/barrier.h @@ -21,7 +21,9 @@ typedef struct qfv_bufferbarrier_s { // image layout transitions enum { qfv_LT_Undefined_to_TransferDst, + qfv_LT_Undefined_to_General, qfv_LT_TransferDst_to_TransferSrc, + qfv_LT_TransferDst_to_General, qfv_LT_TransferDst_to_ShaderReadOnly, qfv_LT_TransferSrc_to_ShaderReadOnly, qfv_LT_ShaderReadOnly_to_TransferDst, @@ -35,6 +37,7 @@ enum { qfv_BB_TransferWrite_to_VertexAttrRead, qfv_BB_TransferWrite_to_IndexRead, qfv_BB_TransferWrite_to_UniformRead, + qfv_BB_TransferWrite_to_ShaderRW, qfv_BB_ShaderRW_to_ShaderRO, qfv_BB_ShaderRW_to_ShaderRO_VA, qfv_BB_ShaderRO_to_ShaderWrite, diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index e0acf580e..e50f72f3c 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -1,6 +1,11 @@ #ifndef __QF_Vulkan_renderpass_h #define __QF_Vulkan_renderpass_h +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + #include "QF/darray.h" #include "QF/simd/types.h" diff --git a/include/QF/Vulkan/qf_translucent.h b/include/QF/Vulkan/qf_translucent.h new file mode 100644 index 000000000..dcb3c760c --- /dev/null +++ b/include/QF/Vulkan/qf_translucent.h @@ -0,0 +1,61 @@ +#ifndef __QF_Vulkan_qf_translucent_h +#define __QF_Vulkan_qf_translucent_h + +#include "QF/darray.h" + +#include "QF/simd/types.h" + +#include "QF/Vulkan/command.h" + +typedef struct qfv_transfrag_s { + vec4f_t color; + float depth; + int32_t next; +} qfv_transfrag_t; + +typedef struct qfv_transtate_s { + int32_t numFragments; + int32_t maxFragments; +} qfv_transtate_t; + +typedef enum { + QFV_translucentClear, + QFV_translucentBlend, + + QFV_translucentNumPasses +} QFV_TranslucentSubpass; + +typedef struct translucentframe_s { + VkDescriptorSet descriptors; + VkImage heads; + VkBuffer state; + qfv_cmdbufferset_t cmdSet; +} translucentframe_t; + +typedef struct translucentframeset_s + DARRAY_TYPE (translucentframe_t) translucentframeset_t; + +typedef struct translucentctx_s { + translucentframeset_t frames; + + struct qfv_resource_s *resources; + + VkPipeline pipeline; + VkPipelineLayout layout; + VkDescriptorPool pool; + VkDescriptorSetLayout setLayout; +} translucentctx_t; + +struct vulkan_ctx_s; +struct qfv_renderframe_s; + +void Vulkan_Translucent_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Translucent_Shutdown (struct vulkan_ctx_s *ctx); +void Vulkan_Translucent_Draw (struct qfv_renderframe_s *rFrame); +VkDescriptorSet Vulkan_Translucent_Descriptors (struct vulkan_ctx_s *ctx, + int frame)__attribute__((pure)); +void Vulkan_Translucent_CreateBuffers (struct vulkan_ctx_s *ctx, + VkExtent2D extent); +void Vulkan_Translucent_CreateRenderPasses (struct vulkan_ctx_s *ctx); + +#endif//__QF_Vulkan_qf_translucent_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 1d74e90c1..595c920a7 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -42,17 +42,19 @@ enum { QFV_rp_particles, QFV_rp_shadowmap, QFV_rp_preoutput, + QFV_rp_translucent, QFV_rp_main, QFV_rp_output, }; //FIXME location typedef enum { - QFV_passDepth, // geometry - QFV_passTranslucent, // geometry - QFV_passGBuffer, // geometry - QFV_passLighting, // single triangle - QFV_passCompose, // single triangle + QFV_passDepth, // geometry + QFV_passTranslucentFrag, // geometry + QFV_passGBuffer, // geometry + QFV_passLighting, // single triangle + QFV_passTranslucentFinal, // single triangle + QFV_passCompose, // single triangle QFV_NumPasses } QFV_Subpass; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index f5569ed7f..19d8ac3be 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -47,6 +47,7 @@ typedef struct vulkan_ctx_s { struct scriptctx_s *script_context; struct texturectx_s *texture_context; struct matrixctx_s *matrix_context; + struct translucentctx_s *translucent_context; struct aliasctx_s *alias_context; struct bspctx_s *bsp_context; struct iqmctx_s *iqm_context; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 03f698aa9..23d221fda 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -254,6 +254,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_scene.c \ libs/video/renderer/vulkan/vulkan_sprite.c \ libs/video/renderer/vulkan/vulkan_texture.c \ + libs/video/renderer/vulkan/vulkan_translucent.c \ libs/video/renderer/vulkan/vulkan_vid_common.c libs/video/renderer/vulkan/vkparse.lo: \ @@ -339,6 +340,10 @@ lightingf_src = $(vkshaderpath)/lighting.frag lightingf_c = $(vkshaderpath)/lighting.frag.spvc composef_src = $(vkshaderpath)/compose.frag composef_c = $(vkshaderpath)/compose.frag.spvc +oit_store = $(vkshaderpath)/oit_store.finc +oit_h = $(vkshaderpath)/oit.h +oit_blendf_src = $(vkshaderpath)/oit_blend.frag +oit_blendf_c = $(vkshaderpath)/oit_blend.frag.spvc aliasv_src = $(vkshaderpath)/alias.vert aliasv_c = $(vkshaderpath)/alias.vert.spvc aliasf_src = $(vkshaderpath)/alias.frag @@ -378,7 +383,7 @@ $(partphysicsc_c): $(partphysicsc_src) $(partupdatec_c): $(partupdatec_src) $(particlev_c): $(particlev_src) $(particleg_c): $(particleg_src) -$(particlef_c): $(particlef_src) +$(particlef_c): $(particlef_src) $(oit_store) $(oit_h) $(sprite_gbufv_c): $(sprite_gbufv_src) @@ -408,14 +413,16 @@ $(bsp_gbuff_c): $(bsp_gbuff_src) $(bsp_shadow_c): $(bsp_shadow_src) -$(bsp_skyf_c): $(bsp_skyf_src) +$(bsp_skyf_c): $(bsp_skyf_src) $(oit_store) $(oit_h) -$(bsp_turbf_c): $(bsp_turbf_src) +$(bsp_turbf_c): $(bsp_turbf_src) $(oit_store) $(oit_h) $(lightingf_c): $(lightingf_src) $(composef_c): $(composef_src) +$(oit_blendf_c): $(oit_blendf_src) $(oit_h) + $(aliasv_c): $(aliasv_src) $(alias_depth_c): $(alias_depth_src) @@ -471,6 +478,7 @@ vkshader_c = \ $(bsp_turbf_c) \ $(lightingf_c) \ $(composef_c) \ + $(oit_blendf_c) \ $(aliasv_c) \ $(alias_depth_c) \ $(aliasf_c) \ @@ -537,6 +545,7 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/bsp_sky.frag \ libs/video/renderer/vulkan/shader/bsp_turb.frag \ libs/video/renderer/vulkan/shader/compose.frag \ + libs/video/renderer/vulkan/shader/oit_blend.frag \ libs/video/renderer/vulkan/shader/iqm.frag \ libs/video/renderer/vulkan/shader/iqm.vert \ libs/video/renderer/vulkan/shader/lighting.frag \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 0c572e001..f859154b5 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -57,6 +57,7 @@ #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_sprite.h" #include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/qf_translucent.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/command.h" @@ -109,6 +110,7 @@ vulkan_R_Init (void) Vulkan_Sprite_Init (vulkan_ctx); Vulkan_Draw_Init (vulkan_ctx); Vulkan_Lighting_Init (vulkan_ctx); + Vulkan_Translucent_Init (vulkan_ctx); Vulkan_Compose_Init (vulkan_ctx); Skin_Init (); @@ -740,6 +742,7 @@ vulkan_vid_render_shutdown (void) Mod_ClearAll (); Vulkan_Compose_Shutdown (vulkan_ctx); + Vulkan_Translucent_Shutdown (vulkan_ctx); Vulkan_Lighting_Shutdown (vulkan_ctx); Vulkan_Draw_Shutdown (vulkan_ctx); Vulkan_Sprite_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/barrier.c b/libs/video/renderer/vulkan/barrier.c index 2ef03860a..37d45bdf0 100644 --- a/libs/video/renderer/vulkan/barrier.c +++ b/libs/video/renderer/vulkan/barrier.c @@ -44,6 +44,19 @@ const qfv_imagebarrier_t imageBarriers[] = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } }, }, + [qfv_LT_Undefined_to_General] = { + .srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_GENERAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + }, [qfv_LT_TransferDst_to_TransferSrc] = { .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT, @@ -57,6 +70,19 @@ const qfv_imagebarrier_t imageBarriers[] = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } }, }, + [qfv_LT_TransferDst_to_General] = { + .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_GENERAL, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } + }, + }, [qfv_LT_TransferDst_to_ShaderReadOnly] = { .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, .dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, @@ -164,6 +190,16 @@ const qfv_bufferbarrier_t bufferBarriers[] = { VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, }, }, + [qfv_BB_TransferWrite_to_ShaderRW] = { + .srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT, + .dstStages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + .barrier = { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, + VK_ACCESS_TRANSFER_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, + VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, + }, + }, [qfv_BB_ShaderRW_to_ShaderRO] = { .srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, .dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 1d42f0c87..0a43ce36b 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -156,6 +156,7 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) VkPhysicalDeviceFeatures features = { .geometryShader = 1, .multiViewport = 1, + .fragmentStoresAndAtomics = 1, }; VkDeviceCreateInfo dCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, &multiview_features, 0, diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index c747fe651..595ec9f7a 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -233,6 +233,20 @@ }, ); }; + oit_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = storage_buffer; + descriptorCount = "2z * $frames.size"; + }, + { + type = storage_image; + descriptorCount = "1z * $frames.size"; + }, + ); + }; compose_attach_pool = { flags = 0; maxSets = $frames.size; @@ -293,6 +307,28 @@ }, ); }; + oit_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 1; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = storage_image; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; entity_set = { bindings = ( { @@ -433,7 +469,7 @@ setLayouts = (matrix_set); }; quakebsp_layout = { - setLayouts = (matrix_set, entity_set, texture_set, texture_set); + setLayouts = (matrix_set, entity_set, oit_set, texture_set, texture_set); pushConstantRanges = ( { stageFlags = fragment; @@ -490,6 +526,9 @@ lighting_layout = { setLayouts = (lighting_attach, lighting_lights, lighting_shadow); }; + oit_layout = { + setLayouts = (oit_set); + }; compose_layout = { setLayouts = (compose_attach); }; @@ -507,7 +546,7 @@ setLayouts = (particle_set, particle_set, particle_set); }; partdraw_layout = { - setLayouts = (matrix_set, texture_set); + setLayouts = (matrix_set, texture_set, oit_set); pushConstantRanges = ( { stageFlags = vertex; @@ -1225,9 +1264,22 @@ ); layout = lighting_layout; }; - compose = { + oit = { @inherit = $properties.pipelines.comp_base; subpass = 4; + stages = ( + $properties.fstriangle.vertexStage, + { + stage = fragment; + name = main; + module = $builtin/oit_blend.frag; + }, + ); + layout = oit_layout; + }; + compose = { + @inherit = $properties.pipelines.comp_base; + subpass = 5; stages = ( $properties.fstriangle.vertexStage, { diff --git a/libs/video/renderer/vulkan/rp_deferred.plist b/libs/video/renderer/vulkan/rp_deferred.plist index 008cb6b5a..fb2f279eb 100644 --- a/libs/video/renderer/vulkan/rp_deferred.plist +++ b/libs/video/renderer/vulkan/rp_deferred.plist @@ -146,6 +146,7 @@ { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, + { name = translucent; color = "[ 0.25, 0.6, 0.25, 1]" }, { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, ); }; @@ -200,14 +201,8 @@ layout = depth_stencil_attachment_optimal; }; }, - { // 1 translucent + { // 1 translucent-frags pipelineBindPoint = graphics; - colorAttachments = ( - { // translucent - attachment = 6; - layout = color_attachment_optimal; - }, - ); depthStencilAttachment = { attachment = 0; layout = depth_stencil_read_only_optimal; @@ -272,7 +267,17 @@ ); preserveAttachments = (6); }, - { // 4 compose + { // 4 translucent-final + pipelineBindPoint = graphics; + colorAttachments = ( + { // translucent + attachment = 6; + layout = color_attachment_optimal; + }, + ); + preserveAttachments = (1, 2, 3, 4, 5); + }, + { // 5 compose pipelineBindPoint = graphics; inputAttachments = ( { // opaque @@ -305,11 +310,11 @@ }, /*{ srcSubpass = ~0u; // external - dstSubpass = 1; // translucent - srcStageMask = compute_shader; - dstStageMask = vertex_input|draw_indirect; - srcAccessMask = shader_write; - dstAccessMask = vertex_attribute_read|indirect_command_read; + dstSubpass = 1; // translucent-frags + srcStageMask = transfer; + dstStageMask = fragment_shader|early_fragment_tests; + srcAccessMask = transfer_write; + dstAccessMask = shader_read|shader_write; },*/ { srcSubpass = 0; // depth @@ -331,7 +336,7 @@ }, { srcSubpass = 3; // lighting - dstSubpass = 4; // compose + dstSubpass = 5; // compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -339,8 +344,17 @@ dependencyFlags = by_region; }, { - srcSubpass = 1; // translucent - dstSubpass = 4; // compose + srcSubpass = 1; // translucent-frags + dstSubpass = 4; // translucent-final + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 4; // translucent-final + dstSubpass = 5; // compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 133f23517..82d8c3547 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -95,6 +95,8 @@ static static #include "libs/video/renderer/vulkan/shader/compose.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/oit_blend.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/alias.vert.spvc" static #include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc" @@ -156,6 +158,7 @@ static shaderdata_t builtin_shaders[] = { { "bsp_turb.frag", bsp_turb_frag, sizeof (bsp_turb_frag) }, { "lighting.frag", lighting_frag, sizeof (lighting_frag) }, { "compose.frag", compose_frag, sizeof (compose_frag) }, + { "oit_blend.frag", oit_blend_frag, sizeof (oit_blend_frag) }, { "alias.vert", alias_vert, sizeof (alias_vert) }, { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, { "alias.frag", alias_frag, sizeof (alias_frag) }, diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag index 0c1df1795..eeaff7db7 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.frag @@ -1,6 +1,6 @@ #version 450 -layout (set = 2, binding = 0) uniform sampler2DArray Texture; +layout (set = 3, binding = 0) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { vec4 fog; diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index f6e35ceee..c85c42a1f 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -1,10 +1,12 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable +#include "oit_store.finc" layout (constant_id = 0) const bool doSkyBox = false; layout (constant_id = 1) const bool doSkySheet = false; -layout (set = 2, binding = 0) uniform sampler2DArray SkySheet; -layout (set = 3, binding = 0) uniform samplerCube SkyBox; +layout (set = 3, binding = 0) uniform sampler2DArray SkySheet; +layout (set = 4, binding = 0) uniform samplerCube SkyBox; layout (push_constant) uniform PushConstants { vec4 fog; @@ -17,7 +19,8 @@ layout (location = 0) in vec4 tl_st; layout (location = 1) in vec3 direction; layout (location = 2) in vec4 color; -layout (location = 0) out vec4 frag_color; +layout(early_fragment_tests) in; +//layout (location = 0) out vec4 frag_color; const float SCALE = 189.0 / 64.0; @@ -95,5 +98,6 @@ main (void) } else { c = vec4 (0, 0, 0, 1); } - frag_color = c;//fogBlend (c); + //frag_color = c;//fogBlend (c); + StoreFrag (c, gl_FragCoord.z); } diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index a98d91c02..c4726e5eb 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -1,6 +1,8 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable +#include "oit_store.finc" -layout (set = 2, binding = 0) uniform sampler2DArray Texture; +layout (set = 3, binding = 0) uniform sampler2DArray Texture; layout (push_constant) uniform PushConstants { vec4 fog; @@ -13,7 +15,8 @@ layout (location = 0) in vec4 tl_st; layout (location = 1) in vec3 direction; layout (location = 2) in vec4 color; -layout (location = 0) out vec4 frag_color; +layout(early_fragment_tests) in; +//layout (location = 0) out vec4 frag_color; const float PI = 3.14159265; const float SPEED = 20.0; @@ -49,5 +52,6 @@ main (void) float a = c.a * e.a * alpha; c += e; c.a = a; - frag_color = c * color;//fogBlend (c); + //frag_color = c * color;//fogBlend (c); + StoreFrag (c * color, gl_FragCoord.z); } diff --git a/libs/video/renderer/vulkan/shader/oit.h b/libs/video/renderer/vulkan/shader/oit.h new file mode 100644 index 000000000..5569460ea --- /dev/null +++ b/libs/video/renderer/vulkan/shader/oit.h @@ -0,0 +1,20 @@ +#ifndef OIT_SET +#define OIT_SET 2 +#endif + +struct FragData { + vec4 color; + float depth; + int next; +}; + +layout (set = OIT_SET, binding = 0) coherent buffer FragCount { + int numFragments; + int maxFragments; +}; + +layout (set = OIT_SET, binding = 1) buffer Fragments { + FragData fragments[]; +}; + +layout (set = OIT_SET, binding = 2, r32i) coherent uniform iimage2D heads; diff --git a/libs/video/renderer/vulkan/shader/oit_blend.frag b/libs/video/renderer/vulkan/shader/oit_blend.frag new file mode 100644 index 000000000..a32a5459d --- /dev/null +++ b/libs/video/renderer/vulkan/shader/oit_blend.frag @@ -0,0 +1,40 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable +#define OIT_SET 0 +#include "oit.h" + +layout (location = 0) out vec4 frag_color; + +void +main (void) +{ + #define MAX_FRAGMENTS 64 + FragData frags[MAX_FRAGMENTS]; + int numFrags = 0; + ivec2 coord = ivec2(gl_FragCoord.xy); + int index = imageLoad (heads, coord).r; + + //FIXME use a heap and prioritize closer fragments + while (index != -1 && numFrags < MAX_FRAGMENTS) { + frags[numFrags] = fragments[index]; + numFrags++; + index = fragments[index].next; + } + //insertion sort + for (int i = 1; i < numFrags; i++) { + FragData toInsert = frags[i]; + int j = i; + while (j > 0 && toInsert.depth > frags[j - 1].depth) { + frags[j] = frags[j - 1]; + j--; + } + frags[j] = toInsert; + } + + vec4 color = vec4 (0, 0, 0, 0); + for (int i = 0; i < numFrags; i++) { + color = mix (color, frags[i].color, + clamp (frags[i].color.a, 0.0f, 1.0f)); + } + frag_color = color; +} diff --git a/libs/video/renderer/vulkan/shader/oit_store.finc b/libs/video/renderer/vulkan/shader/oit_store.finc new file mode 100644 index 000000000..539ed9e34 --- /dev/null +++ b/libs/video/renderer/vulkan/shader/oit_store.finc @@ -0,0 +1,14 @@ +#include "oit.h" + +void +StoreFrag (vec4 color, float depth) +{ + int index = atomicAdd (numFragments, 1); + ivec2 coord = ivec2(gl_FragCoord.xy); + if (index < maxFragments) { + int prevIndex = imageAtomicExchange (heads, coord, index); + fragments[index].color = color; + fragments[index].depth = depth; + fragments[index].next = prevIndex; + } +} diff --git a/libs/video/renderer/vulkan/shader/particle.frag b/libs/video/renderer/vulkan/shader/particle.frag index 5a5f5a887..6499cdd35 100644 --- a/libs/video/renderer/vulkan/shader/particle.frag +++ b/libs/video/renderer/vulkan/shader/particle.frag @@ -1,9 +1,11 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable +#include "oit_store.finc" layout (location = 0) in vec4 uv_tr; layout (location = 1) in vec4 color; -layout (location = 0) out vec4 frag_color; +layout(early_fragment_tests) in; void main (void) @@ -16,5 +18,5 @@ main (void) discard; } c *= (a); - frag_color = c; + StoreFrag (c, gl_FragCoord.z); } diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 869ff825b..9cf245fff 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -69,7 +69,7 @@ static const char * __attribute__((used)) alias_pass_names[] = { static QFV_Subpass subpass_map[] = { QFV_passDepth, // QFV_aliasDepth QFV_passGBuffer, // QFV_aliasGBuffer - QFV_passTranslucent, // QFV_aliasTranslucent + QFV_passTranslucentFrag,// QFV_aliasTranslucent }; static void diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 4cb3c0b70..5eed63d84 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -60,6 +60,7 @@ #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_texture.h" +#include "QF/Vulkan/qf_translucent.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/command.h" @@ -76,6 +77,9 @@ #include "r_internal.h" #include "vid_vulkan.h" +#define TEX_SET 3 +#define SKYBOX_SET 4 + typedef struct bsp_push_constants_s { quat_t fog; float time; @@ -93,8 +97,8 @@ static const char * __attribute__((used)) bsp_pass_names[] = { static QFV_Subpass subpass_map[] = { [QFV_bspDepth] = QFV_passDepth, [QFV_bspGBuffer] = QFV_passGBuffer, - [QFV_bspSky] = QFV_passTranslucent, - [QFV_bspTurb] = QFV_passTranslucent, + [QFV_bspSky] = QFV_passTranslucentFrag, + [QFV_bspTurb] = QFV_passTranslucentFrag, }; static void @@ -828,9 +832,10 @@ bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), Vulkan_Scene_Descriptors (ctx), + Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, sets, 0, 0); + layout, 0, 3, sets, 0, 0); //XXX glsl_Fog_GetColor (fog); //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; @@ -884,7 +889,7 @@ turb_begin (qfv_renderframe_t *rFrame) bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFrag], bframe->cmdSet.a[QFV_bspTurb]); qfvPushDebug (ctx, "bsp_begin_subpass"); @@ -909,7 +914,7 @@ sky_begin (qfv_renderframe_t *rFrame) bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFrag], bframe->cmdSet.a[QFV_bspSky]); qfvPushDebug (ctx, "bsp_begin_subpass"); @@ -1020,7 +1025,7 @@ draw_queue (bsp_pass_t *pass, int queue, VkPipelineLayout layout, __auto_type d = pass->draw_queues[queue].a[i]; if (pass->textures) { vulktex_t *tex = pass->textures->a[d.tex_id]; - bind_texture (tex, 2, layout, dfunc, cmd); + bind_texture (tex, TEX_SET, layout, dfunc, cmd); } dfunc->vkCmdDrawIndexed (cmd, d.index_count, d.instance_count, d.first_index, 0, d.first_instance); @@ -1189,7 +1194,7 @@ Vulkan_DrawSky (qfv_renderframe_t *rFrame) sky_begin (rFrame); vulktex_t skybox = { .descriptor = bctx->skybox_descriptor }; - bind_texture (&skybox, 3, bctx->layout, dfunc, + bind_texture (&skybox, SKYBOX_SET, bctx->layout, dfunc, bframe->cmdSet.a[QFV_bspSky]); bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; push_fragconst (&frag_constants, bctx->layout, device, diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 09efc86e7..467b4546d 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -70,7 +70,7 @@ static const char * __attribute__((used)) iqm_pass_names[] = { static QFV_Subpass subpass_map[] = { QFV_passDepth, // QFV_iqmDepth QFV_passGBuffer, // QFV_iqmGBuffer - QFV_passTranslucent, // QFV_iqmTranslucent + QFV_passTranslucentFrag,// QFV_iqmTranslucent }; static void diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 763012428..79daf4755 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -60,6 +60,7 @@ #include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_sprite.h" +#include "QF/Vulkan/qf_translucent.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/swapchain.h" @@ -140,6 +141,7 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) Vulkan_Bsp_Flush (ctx); Vulkan_RenderEntities (r_ent_queue, rFrame); Vulkan_Scene_Flush (ctx); + Vulkan_Translucent_Draw (rFrame); } void @@ -187,4 +189,5 @@ Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) DARRAY_APPEND (&ctx->renderPasses, rp); Vulkan_Output_SetInput (ctx, rp->output.view); + Vulkan_Translucent_CreateBuffers (ctx, rp->output.extent); } diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 714f4c492..e624577cb 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -53,6 +53,7 @@ #include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" +#include "QF/Vulkan/qf_translucent.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -83,7 +84,7 @@ particle_begin_subpass (VkPipeline pipeline, qfv_renderframe_t *rFrame) dfunc->vkResetCommandBuffer (cmd, 0); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - rFrame->renderpass->renderpass, QFV_passTranslucent, + rFrame->renderpass->renderpass, QFV_passTranslucentFrag, rFrame->framebuffer, 0, 0, 0, }; @@ -100,9 +101,10 @@ particle_begin_subpass (VkPipeline pipeline, qfv_renderframe_t *rFrame) VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), Vulkan_Palette_Descriptor (ctx), + Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - pctx->draw_layout, 0, 2, sets, 0, 0); + pctx->draw_layout, 0, 3, sets, 0, 0); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); } @@ -128,7 +130,7 @@ Vulkan_DrawParticles (qfv_renderframe_t *rFrame) particleframe_t *pframe = &pctx->frames.a[curFrame]; VkCommandBuffer cmd = pframe->cmdSet.a[0]; - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucent], + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFrag], pframe->cmdSet.a[0]); particle_begin_subpass (pctx->draw, rFrame); diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 992771803..95612b9b6 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -76,7 +76,7 @@ static const char * __attribute__((used)) sprite_pass_names[] = { static QFV_Subpass subpass_map[] = { QFV_passDepth, // QFV_spriteDepth QFV_passGBuffer, // QFV_spriteGBuffer - QFV_passTranslucent, // QFV_spriteTranslucent + QFV_passTranslucentFrag,// QFV_spriteTranslucent }; static void diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c new file mode 100644 index 000000000..1aff84ecd --- /dev/null +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -0,0 +1,358 @@ +/* + vulkan_translucent.c + + Vulkan translucent pass pipeline + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/11/30 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "qfalloca.h" + +#include "QF/cvar.h" +#include "QF/sys.h" +#include "QF/va.h" + +#include "QF/Vulkan/qf_renderpass.h" +#include "QF/Vulkan/qf_translucent.h" +#include "QF/Vulkan/barrier.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/descriptor.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/instance.h" +#include "QF/Vulkan/resource.h" +#include "QF/Vulkan/staging.h" + +#include "r_internal.h" +#include "vid_vulkan.h" + +#define MAX_FRAGMENTS (1<<24) + +static const char * __attribute__((used)) translucent_pass_names[] = { + "clear", + "blend", +}; + +void +Vulkan_Translucent_Draw (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + qfv_renderpass_t *renderpass = rFrame->renderpass; + + translucentctx_t *tctx = ctx->translucent_context; + translucentframe_t *tframe = &tctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = tframe->cmdSet.a[QFV_translucentBlend]; + + DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFinal], cmd); + + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + renderpass->renderpass, QFV_passTranslucentFinal, + rFrame->framebuffer, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + QFV_duCmdBeginLabel (device, cmd, "translucent", { 0, 0.2, 0.6, 1}); + + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + tctx->pipeline); + VkDescriptorSet set[] = { + tframe->descriptors, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + tctx->layout, 0, 1, set, 0, 0); + + + dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); + + dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); + + QFV_duCmdEndLabel (device, cmd); + dfunc->vkEndCommandBuffer (cmd); +} + +void +Vulkan_Translucent_Init (vulkan_ctx_t *ctx) +{ + if (ctx->translucent_context) {//FIXME + return; + } + qfv_device_t *device = ctx->device; + + qfvPushDebug (ctx, "translucent init"); + + translucentctx_t *tctx = calloc (1, sizeof (translucentctx_t)); + ctx->translucent_context = tctx; + + size_t frames = ctx->frames.size; + DARRAY_INIT (&tctx->frames, frames); + DARRAY_RESIZE (&tctx->frames, frames); + tctx->frames.grow = 0; + + tctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "oit"); + tctx->layout = Vulkan_CreatePipelineLayout (ctx, "oit_layout"); + + __auto_type setLayout = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + for (size_t i = 0; i < frames; i++) { + setLayout->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "oit_set"); + } + __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "oit_pool"); + + __auto_type sets = QFV_AllocateDescriptorSet (device, pool, setLayout); + for (size_t i = 0; i < frames; i++) { + __auto_type tframe = &tctx->frames.a[i]; + + DARRAY_INIT (&tframe->cmdSet, QFV_translucentNumPasses); + DARRAY_RESIZE (&tframe->cmdSet, QFV_translucentNumPasses); + tframe->cmdSet.grow = 0; + + QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &tframe->cmdSet); + + tframe->descriptors = sets->a[i]; + + for (int j = 0; j < QFV_translucentNumPasses; j++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, + tframe->cmdSet.a[j], + va (ctx->va_ctx, "cmd:translucent:%zd:%s", i, + translucent_pass_names[j])); + } + } + free (sets); + qfvPopDebug (ctx); +} + +void +Vulkan_Translucent_Shutdown (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + translucentctx_t *tctx = ctx->translucent_context; + + if (tctx->resources) { + QFV_DestroyResource (device, tctx->resources); + free (tctx->resources); + tctx->resources = 0; + } + + dfunc->vkDestroyPipeline (device->dev, tctx->pipeline, 0); + free (tctx->frames.a); + free (tctx); +} + +VkDescriptorSet +Vulkan_Translucent_Descriptors (vulkan_ctx_t *ctx, int frame) +{ + __auto_type tctx = ctx->translucent_context; + return tctx->frames.a[frame].descriptors; +} + +void +Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) +{ + if (!ctx->translucent_context) {//FIXME + Vulkan_Translucent_Init (ctx); + } + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type tctx = ctx->translucent_context; + size_t frames = ctx->frames.size; + + if (tctx->resources) { + QFV_DestroyResource (device, tctx->resources); + free (tctx->resources); + tctx->resources = 0; + } + tctx->resources = malloc (sizeof (qfv_resource_t) + // heads image + + frames * sizeof (qfv_resobj_t) + // heads image view + + frames * sizeof (qfv_resobj_t) + // fragment buffer + + frames * sizeof (qfv_resobj_t) + // fragment count + + frames * sizeof (qfv_resobj_t)); + __auto_type heads_objs = (qfv_resobj_t *) &tctx->resources[1]; + __auto_type head_views_objs = &heads_objs[frames]; + __auto_type buffer_objs = &head_views_objs[frames]; + __auto_type count_objs = &buffer_objs[frames]; + tctx->resources[0] = (qfv_resource_t) { + .name = "oit", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = 4 * frames, + .objects = heads_objs, + }; + for (size_t i = 0; i < frames; i++) { + heads_objs[i] = (qfv_resobj_t) { + .name = va (ctx->va_ctx, "heads:%zd", i), + .type = qfv_res_image, + .image = { + .type = VK_IMAGE_TYPE_2D, + .format = VK_FORMAT_R32_SINT, + .extent = { extent.width, extent.height, 1 }, + .num_mipmaps = 1, + .num_layers = 1, + .samples = VK_SAMPLE_COUNT_1_BIT, + .usage = VK_IMAGE_USAGE_STORAGE_BIT + | VK_IMAGE_USAGE_TRANSFER_DST_BIT, + }, + }; + head_views_objs[i] = (qfv_resobj_t) { + .name = "head view", + .type = qfv_res_image_view, + .image_view = { + .image = i, + .type = VK_IMAGE_VIEW_TYPE_2D, + .format = VK_FORMAT_R32_SINT, + .aspect = VK_IMAGE_ASPECT_COLOR_BIT, + }, + }; + buffer_objs[i] = (qfv_resobj_t) { + .name = va (ctx->va_ctx, "frags:%zd", i), + .type = qfv_res_buffer, + .buffer = { + .size = sizeof (qfv_transfrag_t) * MAX_FRAGMENTS, + .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + }, + }; + count_objs[i] = (qfv_resobj_t) { + .name = va (ctx->va_ctx, "count:%zd", i), + .type = qfv_res_buffer, + .buffer = { + .size = 2 * sizeof (qfv_transtate_t), + .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + }, + }; + } + QFV_CreateResource (device, tctx->resources); + + for (size_t i = 0; i < frames; i++) { + __auto_type tframe = &tctx->frames.a[i]; + tframe->heads = heads_objs[i].image.image; + tframe->state = count_objs[i].buffer.buffer; + + VkDescriptorImageInfo imageInfo[] = { + { 0, head_views_objs[i].image_view.view, VK_IMAGE_LAYOUT_GENERAL }, + }; + VkDescriptorBufferInfo bufferInfo[] = { + { count_objs[i].buffer.buffer, 0, VK_WHOLE_SIZE }, + { buffer_objs[i].buffer.buffer, 0, VK_WHOLE_SIZE }, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + tframe->descriptors, 2, 0, 1, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .pImageInfo = imageInfo }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + tframe->descriptors, 0, 0, 2, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .pBufferInfo = bufferInfo }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + } +} + +static void +translucent_clear (qfv_renderframe_t *rFrame) +{ + vulkan_ctx_t *ctx = rFrame->vulkan_ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + translucentctx_t *tctx = ctx->translucent_context; + __auto_type tframe = &tctx->frames.a[ctx->curFrame]; + VkCommandBuffer cmd = tframe->cmdSet.a[QFV_translucentClear]; + + DARRAY_APPEND (&rFrame->subpassCmdSets[0], cmd); + dfunc->vkResetCommandBuffer (cmd, 0); + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + 0, 0, 0, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = tframe->heads; + dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + VkClearColorValue clear_color[] = { + { .int32 = {-1, -1, -1, -1} }, + }; + VkImageSubresourceRange ranges[] = { + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }, + }; + dfunc->vkCmdClearColorImage (cmd, tframe->heads, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + clear_color, 1, ranges); + ib = imageBarriers[qfv_LT_TransferDst_to_General]; + ib.barrier.image = tframe->heads; + dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + + dfunc->vkEndCommandBuffer (cmd); + + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + qfv_transtate_t *state = QFV_PacketExtend (packet, 2 * sizeof (*state)); + *state = (qfv_transtate_t) { 0, MAX_FRAGMENTS }; + __auto_type bb = &bufferBarriers[qfv_BB_TransferWrite_to_ShaderRW]; + QFV_PacketCopyBuffer (packet, tframe->state, bb); + QFV_PacketSubmit (packet); +} + +void +Vulkan_Translucent_CreateRenderPasses (vulkan_ctx_t *ctx) +{ + __auto_type rp = QFV_RenderPass_New (ctx, "translucent", translucent_clear); + rp->order = QFV_rp_translucent; + DARRAY_APPEND (&ctx->renderPasses, rp); +} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index d1f5153e9..f7df0a5b7 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -56,6 +56,7 @@ #include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_particles.h" #include "QF/Vulkan/qf_renderpass.h" +#include "QF/Vulkan/qf_translucent.h" #include "QF/Vulkan/qf_vid.h" #include "r_internal.h" @@ -169,6 +170,7 @@ Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) Vulkan_Main_CreateRenderPasses (ctx); Vulkan_Particles_CreateRenderPasses (ctx); Vulkan_Lighting_CreateRenderPasses (ctx); + Vulkan_Translucent_CreateRenderPasses (ctx); heapsort (ctx->renderPasses.a, ctx->renderPasses.size, sizeof (qfv_renderpass_t *), renderpass_cmp); From 9ba2d265423073627baf1d0fbeb2438a18877da4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Dec 2022 13:11:16 +0900 Subject: [PATCH 3268/3664] [client] Move sbar.h into client Where it belongs :P --- include/Makemodule.am | 2 +- include/{ => client}/sbar.h | 6 +++--- libs/client/cl_screen.c | 3 +-- libs/client/sbar.c | 2 +- libs/video/renderer/gl/gl_textures.c | 1 - libs/video/renderer/gl/vid_common_gl.c | 1 - libs/video/renderer/r_screen.c | 1 - nq/source/cl_main.c | 2 +- nq/source/cl_parse.c | 4 ++-- qw/source/cl_cam.c | 3 ++- qw/source/cl_main.c | 2 +- qw/source/cl_ngraph.c | 2 +- qw/source/cl_parse.c | 2 +- 13 files changed, 14 insertions(+), 17 deletions(-) rename include/{ => client}/sbar.h (96%) diff --git a/include/Makemodule.am b/include/Makemodule.am index b5ab8df07..11a835523 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -69,7 +69,6 @@ EXTRA_DIST += \ include/r_text.h \ include/regex.h \ include/rua_internal.h \ - include/sbar.h \ include/skin_stencil.h \ include/scn_internal.h \ include/snd_internal.h \ @@ -90,6 +89,7 @@ EXTRA_DIST += \ include/client/input.h \ include/client/locs.h \ include/client/particles.h \ + include/client/sbar.h \ include/client/state.h \ include/client/temp_entities.h \ include/client/view.h \ diff --git a/include/sbar.h b/include/client/sbar.h similarity index 96% rename from include/sbar.h rename to include/client/sbar.h index 24f359f8a..60766c3b1 100644 --- a/include/sbar.h +++ b/include/client/sbar.h @@ -28,8 +28,8 @@ // the status bar is redrawn only if something has changed, but if anything // does, the entire thing will be redrawn for the next vid.numpages frames. -#ifndef _SBAR_H -#define _SBAR_H +#ifndef __client_sbar_h +#define __client_sbar_h extern qboolean sbar_showscores; @@ -59,4 +59,4 @@ void Sbar_CenterPrint (const char *str); void Sbar_LogFrags (double time); -#endif +#endif//__client_sbar_h diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index 8f5af2de5..cf8a37201 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -51,11 +51,10 @@ #include "QF/scene/transform.h" #include "QF/ui/view.h" -#include "sbar.h" - #include "r_local.h" //FIXME for r_cache_thrash #include "client/hud.h" +#include "client/sbar.h" #include "client/screen.h" #include "client/view.h" #include "client/world.h" diff --git a/libs/client/sbar.c b/libs/client/sbar.c index b651ae027..000757b01 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -58,9 +58,9 @@ #include "QF/ui/view.h" #include "compat.h" -#include "sbar.h" #include "client/hud.h" +#include "client/sbar.h" #include "client/screen.h" #include "client/state.h" #include "client/world.h" diff --git a/libs/video/renderer/gl/gl_textures.c b/libs/video/renderer/gl/gl_textures.c index c65760890..68af61db2 100644 --- a/libs/video/renderer/gl/gl_textures.c +++ b/libs/video/renderer/gl/gl_textures.c @@ -53,7 +53,6 @@ #include "compat.h" #include "r_internal.h" #include "r_scrap.h" -#include "sbar.h" #include "vid_internal.h" struct scrap_s { diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index f723e6247..296c36ae0 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -55,7 +55,6 @@ #include "compat.h" #include "d_iface.h" #include "r_internal.h" -#include "sbar.h" #define WARP_WIDTH 320 #define WARP_HEIGHT 200 diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 3e93affdf..e69fb3fe3 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -55,7 +55,6 @@ #include "compat.h" #include "r_internal.h" -#include "sbar.h" // only the refresh window will be updated unless these variables are flagged int scr_copytop; diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index e51f0884b..e0709521c 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -55,10 +55,10 @@ #include "QF/scene/scene.h" #include "compat.h" -#include "sbar.h" #include "client/chase.h" #include "client/particles.h" +#include "client/sbar.h" #include "client/screen.h" #include "client/temp_entities.h" #include "client/world.h" diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 3c324ece4..f91a3b9c6 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -57,11 +57,11 @@ #include "QF/scene/entity.h" #include "client/particles.h" +#include "client/sbar.h" #include "client/temp_entities.h" #include "client/world.h" #include "compat.h" -#include "sbar.h" #include "nq/include/client.h" #include "nq/include/host.h" @@ -721,7 +721,7 @@ CL_ParseServerMessage (void) static dstring_t *stuffbuf; signon_t so; - cl.viewstate.last_servermessage = realtime; + cl.viewstate.last_servermessage = cl.time; TEntContext_t tentCtx = { cl.viewstate.player_origin, cl.viewentity diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index ba753a05a..02cc75b8d 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -46,7 +46,8 @@ #include "QF/msg.h" #include "compat.h" -#include "sbar.h" + +#include "client/sbar.h" #include "qw/include/cl_cam.h" #include "qw/include/cl_input.h" diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 2e86d56db..921ae5061 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -95,9 +95,9 @@ #include "buildnum.h" #include "compat.h" -#include "sbar.h" #include "client/particles.h" +#include "client/sbar.h" #include "client/screen.h" #include "client/temp_entities.h" #include "client/view.h" diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index f4ec199dc..9d1d562ff 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -49,7 +49,7 @@ #include "qw/include/cl_parse.h" #include "qw/include/client.h" -#include "sbar.h" +#include "client/sbar.h" int cl_netgraph; static cvar_t cl_netgraph_cvar = { diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index d6b939e59..9a1f0b334 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -64,10 +64,10 @@ #include "QF/scene/scene.h" #include "compat.h" -#include "sbar.h" #include "client/effects.h" #include "client/particles.h" +#include "client/sbar.h" #include "client/screen.h" #include "client/temp_entities.h" #include "client/view.h" From 07fd93a56f9d7a0fa1971ef171219f3a34e0a5a4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Dec 2022 15:59:14 +0900 Subject: [PATCH 3269/3664] [client] Use a separate explosion type for nq quake changes rocket and grenade models to explosion models, but quakeworld does not. This resulted in nq drawing two explosion sprites instead of one. Separating the types allows nq to skip adding a sprite for the explosion. --- include/client/temp_entities.h | 3 ++- libs/client/cl_temp_entities.c | 41 ++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/include/client/temp_entities.h b/include/client/temp_entities.h index 87ffd369c..e6f3a8406 100644 --- a/include/client/temp_entities.h +++ b/include/client/temp_entities.h @@ -36,7 +36,8 @@ typedef enum TE_Effect { TE_NoEffect, // for invalid nq/qw -> qf mapping TE_Beam, // grappling hook beam TE_Blood, // bullet hitting body - TE_Explosion, // rocket explosion + TE_Explosion, // rocket explosion (nq) + TE_Explosion1, // rocket explosion (qw) TE_Explosion2, // color mapped explosion TE_Explosion3, // Nehahra colored light explosion TE_Gunshot1, // NQ gunshot (20 particles) diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 9cd834d2b..9c93d9886 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -350,26 +350,9 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME clp_funcs->BloodPuffEffect (position, count); break; - case TE_Explosion: + case TE_Explosion1: MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME - // particles - clp_funcs->ParticleExplosion (position); - - // light - dl = R_AllocDlight (0); - if (dl) { - VectorCopy (position, dl->origin); - dl->radius = 350; - dl->die = time + 0.5; - dl->decay = 300; - QuatSet (0.86, 0.31, 0.24, 0.7, dl->color); - //FIXME? nq: QuatSet (1.0, 0.5, 0.25, 0.7, dl->color); - } - - // sound - S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); - // sprite to = new_tent_object (); to->next = cl_explosions; @@ -386,6 +369,26 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx, renderer_t *renderer = Ent_GetComponent (ex->tent->ent.id, scene_renderer, cl_world.scene->reg); renderer->model = cl_spr_explod; Transform_SetLocalPosition (transform, position); + goto TE_Explosion_no_sprite; + case TE_Explosion: + MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME +TE_Explosion_no_sprite: + // particles + clp_funcs->ParticleExplosion (position); + + // light + dl = R_AllocDlight (0); + if (dl) { + VectorCopy (position, dl->origin); + dl->radius = 350; + dl->die = time + 0.5; + dl->decay = 300; + QuatSet (0.86, 0.31, 0.24, 0.7, dl->color); + //FIXME? nq: QuatSet (1.0, 0.5, 0.25, 0.7, dl->color); + } + + // sound + S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1); break; case TE_Explosion2: MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME @@ -548,7 +551,7 @@ static const TE_Effect qwEffects[256] = { [TE_qwSpike] = TE_Spike, [TE_qwSuperSpike] = TE_SuperSpike, [TE_qwGunshot] = TE_Gunshot2, - [TE_qwExplosion] = TE_Explosion, + [TE_qwExplosion] = TE_Explosion1, [TE_qwTarExplosion] = TE_TarExplosion, [TE_qwLightning1] = TE_Lightning1, [TE_qwLightning2] = TE_Lightning2, From 7a64bb11497ee94acd8556a4e7f122b1878d7595 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Dec 2022 17:50:13 +0900 Subject: [PATCH 3270/3664] [client] Use realtime for net icon check viewstate's time is from cl.time which is not what's used to set last_servermessage (that uses realtime). After careful investigation, I found that cl.time is not at all suitable and that the original id code used realtime (I think it was just me being lazy when I merged the code). Fixes the stuck net icon. --- include/client/view.h | 1 + libs/client/cl_screen.c | 4 ++-- nq/source/cl_main.c | 1 + nq/source/host_cmd.c | 2 ++ qw/source/cl_main.c | 2 ++ qw/source/cl_parse.c | 2 ++ qw/source/cl_skin.c | 1 + 7 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/client/view.h b/include/client/view.h index 2bb2c8196..366b641fe 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -60,6 +60,7 @@ typedef struct viewstate_s { vec4f_t punchangle; transform_t camera_transform; double time; + double realtime; double last_servermessage; float frametime; float height; diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index cf8a37201..8fc17c78e 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -133,8 +133,8 @@ scr_draw_views (void) View_SetVisible (pause_view, scr_showpause && r_data->paused); View_SetVisible (ram_view, scr_showram && r_cache_thrash); - View_SetVisible (net_view, (!_vs->demoplayback - && _vs->time - _vs->last_servermessage >= 0.3)); + double msg_time = _vs->realtime - _vs->last_servermessage; + View_SetVisible (net_view, (!_vs->demoplayback && msg_time >= 0.3)); View_SetVisible (loading_view, _vs->loading); // FIXME cvar callbacks View_SetVisible (timegraph_view, r_timegraph); diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index e0709521c..954da6962 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -431,6 +431,7 @@ CL_NextDemo (void) cl.viewstate.loading = true; cl.viewstate.time = cl.time; + cl.viewstate.realtime = realtime; CL_UpdateScreen(&cl.viewstate); if (!cls.demos[cls.demonum][0] || cls.demonum == MAX_DEMOS) { diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index c6c6a6664..a14149190 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -297,6 +297,7 @@ Host_Map_f (void) cl.viewstate.loading = true; cl.viewstate.time = cl.time; + cl.viewstate.realtime = realtime; CL_UpdateScreen (&cl.viewstate); svs.serverflags = 0; // haven't completed an episode yet @@ -628,6 +629,7 @@ Host_Loadgame_f (void) cl.viewstate.loading = true; cl.viewstate.time = cl.time; + cl.viewstate.realtime = realtime; CL_UpdateScreen (&cl.viewstate); Sys_Printf ("Loading game from %s...\n", name->str); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 921ae5061..490e33f41 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1944,6 +1944,7 @@ Host_Frame (float time) r_data->frametime = host_frametime; cl.viewstate.time = realtime; + cl.viewstate.realtime = realtime; if (!cls.demoplayback && cls.state == ca_active) { CL_NetUpdate (); } @@ -2090,6 +2091,7 @@ Host_Init (void) CL_Init (); cl.viewstate.time = realtime; + cl.viewstate.realtime = realtime; CL_UpdateScreen (&cl.viewstate); CL_UpdateScreen (&cl.viewstate); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index 9a1f0b334..e3db33e5e 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -285,6 +285,7 @@ Model_NextDownload (void) if (cls.downloadnumber == 0) { Sys_Printf ("Checking models...\n"); cl.viewstate.time = realtime; + cl.viewstate.realtime = realtime; CL_UpdateScreen (&cl.viewstate); cls.downloadnumber = 1; } @@ -375,6 +376,7 @@ Sound_NextDownload (void) if (cls.downloadnumber == 0) { Sys_Printf ("Checking sounds...\n"); cl.viewstate.time = realtime; + cl.viewstate.realtime = realtime; CL_UpdateScreen (&cl.viewstate); cls.downloadnumber = 1; } diff --git a/qw/source/cl_skin.c b/qw/source/cl_skin.c index 807b98f43..03cb7f309 100644 --- a/qw/source/cl_skin.c +++ b/qw/source/cl_skin.c @@ -101,6 +101,7 @@ Skin_NextDownload (void) if (cls.downloadnumber == 0) { Sys_Printf ("Checking skins...\n"); cl.viewstate.time = realtime; + cl.viewstate.realtime = realtime; CL_UpdateScreen (&cl.viewstate); } cls.downloadtype = dl_skin; From 966ef949c5009cdd0207a8d069b16677be28b347 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 1 Dec 2022 23:03:55 +0900 Subject: [PATCH 3271/3664] [vulkan] Move oit blending into compose subpass I had debated putting the blending in the compose subpass or a separate pass but went with the separate pass originally, but it turns out that removing the separate pass gains 1-3% (5-15/545 fps in a timedemo of demo1). --- include/QF/Vulkan/qf_compose.h | 2 +- include/QF/Vulkan/qf_translucent.h | 2 - include/QF/Vulkan/qf_vid.h | 2 - libs/video/renderer/Makemodule.am | 12 ++-- libs/video/renderer/vulkan/pl_quake_def.plist | 26 +-------- libs/video/renderer/vulkan/rp_deferred.plist | 57 ++----------------- libs/video/renderer/vulkan/shader.c | 3 - .../video/renderer/vulkan/shader/compose.frag | 8 +-- .../shader/{oit_blend.frag => oit_blend.finc} | 12 +--- libs/video/renderer/vulkan/vulkan_compose.c | 6 +- libs/video/renderer/vulkan/vulkan_main.c | 1 - .../renderer/vulkan/vulkan_translucent.c | 53 ----------------- 12 files changed, 23 insertions(+), 161 deletions(-) rename libs/video/renderer/vulkan/shader/{oit_blend.frag => oit_blend.finc} (78%) diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h index 4c4f0507b..001ee3e5c 100644 --- a/include/QF/Vulkan/qf_compose.h +++ b/include/QF/Vulkan/qf_compose.h @@ -36,7 +36,7 @@ #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/command.h" -#define COMPOSE_IMAGE_INFOS 2 +#define COMPOSE_IMAGE_INFOS 1 typedef struct composeframe_s { VkCommandBuffer cmd; diff --git a/include/QF/Vulkan/qf_translucent.h b/include/QF/Vulkan/qf_translucent.h index dcb3c760c..066e99f82 100644 --- a/include/QF/Vulkan/qf_translucent.h +++ b/include/QF/Vulkan/qf_translucent.h @@ -40,8 +40,6 @@ typedef struct translucentctx_s { struct qfv_resource_s *resources; - VkPipeline pipeline; - VkPipelineLayout layout; VkDescriptorPool pool; VkDescriptorSetLayout setLayout; } translucentctx_t; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 595c920a7..ff57d9853 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -53,7 +53,6 @@ typedef enum { QFV_passTranslucentFrag, // geometry QFV_passGBuffer, // geometry QFV_passLighting, // single triangle - QFV_passTranslucentFinal, // single triangle QFV_passCompose, // single triangle QFV_NumPasses @@ -66,7 +65,6 @@ enum { QFV_attachNormal, QFV_attachPosition, QFV_attachOpaque, - QFV_attachTranslucent, QFV_attachSwapchain, }; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 23d221fda..747aa6669 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -340,10 +340,9 @@ lightingf_src = $(vkshaderpath)/lighting.frag lightingf_c = $(vkshaderpath)/lighting.frag.spvc composef_src = $(vkshaderpath)/compose.frag composef_c = $(vkshaderpath)/compose.frag.spvc +oit_blend = $(vkshaderpath)/oit_blend.finc oit_store = $(vkshaderpath)/oit_store.finc oit_h = $(vkshaderpath)/oit.h -oit_blendf_src = $(vkshaderpath)/oit_blend.frag -oit_blendf_c = $(vkshaderpath)/oit_blend.frag.spvc aliasv_src = $(vkshaderpath)/alias.vert aliasv_c = $(vkshaderpath)/alias.vert.spvc aliasf_src = $(vkshaderpath)/alias.frag @@ -419,9 +418,7 @@ $(bsp_turbf_c): $(bsp_turbf_src) $(oit_store) $(oit_h) $(lightingf_c): $(lightingf_src) -$(composef_c): $(composef_src) - -$(oit_blendf_c): $(oit_blendf_src) $(oit_h) +$(composef_c): $(composef_src) $(oit_blend) $(oit_h) $(aliasv_c): $(aliasv_src) @@ -478,7 +475,6 @@ vkshader_c = \ $(bsp_turbf_c) \ $(lightingf_c) \ $(composef_c) \ - $(oit_blendf_c) \ $(aliasv_c) \ $(alias_depth_c) \ $(aliasf_c) \ @@ -530,6 +526,9 @@ EXTRA_DIST += \ $(rp_shadow_src) \ $(pl_quake_def_src) \ $(pl_output_src) \ + $(oit_blend) \ + $(oit_store) \ + $(oit_h) \ libs/video/renderer/vulkan/vkparse.plist \ libs/video/renderer/vulkan/vkparse.h \ libs/video/renderer/vulkan/shader/alias.frag \ @@ -545,7 +544,6 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/shader/bsp_sky.frag \ libs/video/renderer/vulkan/shader/bsp_turb.frag \ libs/video/renderer/vulkan/shader/compose.frag \ - libs/video/renderer/vulkan/shader/oit_blend.frag \ libs/video/renderer/vulkan/shader/iqm.frag \ libs/video/renderer/vulkan/shader/iqm.vert \ libs/video/renderer/vulkan/shader/lighting.frag \ diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 595ec9f7a..56c5ac2c3 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -427,12 +427,6 @@ descriptorCount = 1; stageFlags = fragment; }, - { - binding = 1; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, ); }; particle_set = { @@ -526,11 +520,8 @@ lighting_layout = { setLayouts = (lighting_attach, lighting_lights, lighting_shadow); }; - oit_layout = { - setLayouts = (oit_set); - }; compose_layout = { - setLayouts = (compose_attach); + setLayouts = (compose_attach, oit_set); }; partphysics_layout = { setLayouts = (particle_set); @@ -1264,22 +1255,9 @@ ); layout = lighting_layout; }; - oit = { - @inherit = $properties.pipelines.comp_base; - subpass = 4; - stages = ( - $properties.fstriangle.vertexStage, - { - stage = fragment; - name = main; - module = $builtin/oit_blend.frag; - }, - ); - layout = oit_layout; - }; compose = { @inherit = $properties.pipelines.comp_base; - subpass = 5; + subpass = 4; stages = ( $properties.fstriangle.vertexStage, { diff --git a/libs/video/renderer/vulkan/rp_deferred.plist b/libs/video/renderer/vulkan/rp_deferred.plist index fb2f279eb..13bf88cb8 100644 --- a/libs/video/renderer/vulkan/rp_deferred.plist +++ b/libs/video/renderer/vulkan/rp_deferred.plist @@ -39,10 +39,6 @@ @inherit = $properties.flat_color_image_template; format = r16g16b16a16_sfloat; }; - translucent = { - @inherit = $properties.flat_color_image_template; - format = r8g8b8a8_unorm; - }; }; flat_color_view_template = { viewType = VK_IMAGE_VIEW_TYPE_2D; @@ -92,11 +88,6 @@ image = opaque; format = $properties.images.opaque.format; }; - translucent = { - @inherit = $properties.flat_color_view_template; - image = translucent; - format = $properties.images.translucent.format; - }; }; output = { image = { @@ -115,7 +106,7 @@ framebuffer = { renderPass = deferred; attachments = (depth, color, emission, normal, position, opaque, - translucent, $output.view); + $output.view); width = $output.extent.width; height = $output.extent.height; layers = 1; @@ -127,7 +118,6 @@ { color = "[0, 0, 0, 1]"; }, // normal { color = "[0, 0, 0, 1]"; }, // position { color = "[0, 0, 0, 1]"; }, // opaque - { color = "[0, 0, 0, 0]"; }, // translucent { color = "[0, 0, 0, 1]"; }, // output ); attachment_template = { @@ -146,7 +136,6 @@ { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, - { name = translucent; color = "[ 0.25, 0.6, 0.25, 1]" }, { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, ); }; @@ -180,11 +169,6 @@ @inherit = $properties.attachment_template; format = $properties.images.opaque.format; }, - { - @inherit = $properties.attachment_template; - format = $properties.images.translucent.format; - loadOp = clear; - }, { @inherit = $properties.attachment_template; format = $output.format; @@ -267,31 +251,17 @@ ); preserveAttachments = (6); }, - { // 4 translucent-final - pipelineBindPoint = graphics; - colorAttachments = ( - { // translucent - attachment = 6; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (1, 2, 3, 4, 5); - }, - { // 5 compose + { // 4 compose pipelineBindPoint = graphics; inputAttachments = ( { // opaque attachment = 5; layout = shader_read_only_optimal; }, - { // translucent - attachment = 6; - layout = shader_read_only_optimal; - }, ); colorAttachments = ( { // output - attachment = 7; + attachment = 6; layout = color_attachment_optimal; }, ); @@ -308,14 +278,6 @@ dstAccessMask = input_attachment_read|depth_stencil_attachment_read; dependencyFlags = by_region; }, - /*{ - srcSubpass = ~0u; // external - dstSubpass = 1; // translucent-frags - srcStageMask = transfer; - dstStageMask = fragment_shader|early_fragment_tests; - srcAccessMask = transfer_write; - dstAccessMask = shader_read|shader_write; - },*/ { srcSubpass = 0; // depth dstSubpass = 2; // g-buffer @@ -336,7 +298,7 @@ }, { srcSubpass = 3; // lighting - dstSubpass = 5; // compose + dstSubpass = 4; // compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; @@ -345,16 +307,7 @@ }, { srcSubpass = 1; // translucent-frags - dstSubpass = 4; // translucent-final - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region; - }, - { - srcSubpass = 4; // translucent-final - dstSubpass = 5; // compose + dstSubpass = 4; // translucent-final/compose srcStageMask = color_attachment_output; dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 82d8c3547..133f23517 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -95,8 +95,6 @@ static static #include "libs/video/renderer/vulkan/shader/compose.frag.spvc" static -#include "libs/video/renderer/vulkan/shader/oit_blend.frag.spvc" -static #include "libs/video/renderer/vulkan/shader/alias.vert.spvc" static #include "libs/video/renderer/vulkan/shader/alias_depth.vert.spvc" @@ -158,7 +156,6 @@ static shaderdata_t builtin_shaders[] = { { "bsp_turb.frag", bsp_turb_frag, sizeof (bsp_turb_frag) }, { "lighting.frag", lighting_frag, sizeof (lighting_frag) }, { "compose.frag", compose_frag, sizeof (compose_frag) }, - { "oit_blend.frag", oit_blend_frag, sizeof (oit_blend_frag) }, { "alias.vert", alias_vert, sizeof (alias_vert) }, { "alias_depth.vert", alias_depth_vert, sizeof (alias_depth_vert) }, { "alias.frag", alias_frag, sizeof (alias_frag) }, diff --git a/libs/video/renderer/vulkan/shader/compose.frag b/libs/video/renderer/vulkan/shader/compose.frag index 542ba4c1b..28e7e5d43 100644 --- a/libs/video/renderer/vulkan/shader/compose.frag +++ b/libs/video/renderer/vulkan/shader/compose.frag @@ -1,7 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable +#define OIT_SET 1 +#include "oit_blend.finc" layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput opaque; -layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput translucent; layout (location = 0) out vec4 frag_color; @@ -9,12 +11,10 @@ void main (void) { vec3 o; - vec4 t; vec3 c; o = subpassLoad (opaque).rgb; - t = subpassLoad (translucent); - c = mix (o, t.rgb, t.a); + c = BlendFrags (vec4 (o, 1)).xyz; c = pow (c, vec3(0.83));//FIXME make gamma correction configurable frag_color = vec4 (c, 1); } diff --git a/libs/video/renderer/vulkan/shader/oit_blend.frag b/libs/video/renderer/vulkan/shader/oit_blend.finc similarity index 78% rename from libs/video/renderer/vulkan/shader/oit_blend.frag rename to libs/video/renderer/vulkan/shader/oit_blend.finc index a32a5459d..cfcfad302 100644 --- a/libs/video/renderer/vulkan/shader/oit_blend.frag +++ b/libs/video/renderer/vulkan/shader/oit_blend.finc @@ -1,12 +1,7 @@ -#version 450 -#extension GL_GOOGLE_include_directive : enable -#define OIT_SET 0 #include "oit.h" -layout (location = 0) out vec4 frag_color; - -void -main (void) +vec4 +BlendFrags (vec4 color) { #define MAX_FRAGMENTS 64 FragData frags[MAX_FRAGMENTS]; @@ -31,10 +26,9 @@ main (void) frags[j] = toInsert; } - vec4 color = vec4 (0, 0, 0, 0); for (int i = 0; i < numFrags; i++) { color = mix (color, frags[i].color, clamp (frags[i].color.a, 0.0f, 1.0f)); } - frag_color = color; + return color; } diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index c6169df05..172d69a0f 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -46,6 +46,7 @@ #include "QF/Vulkan/qf_compose.h" #include "QF/Vulkan/qf_renderpass.h" +#include "QF/Vulkan/qf_translucent.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" @@ -90,16 +91,15 @@ Vulkan_Compose_Draw (qfv_renderframe_t *rFrame) cframe->imageInfo[0].imageView = renderpass->attachment_views->a[QFV_attachOpaque]; - cframe->imageInfo[1].imageView - = renderpass->attachment_views->a[QFV_attachTranslucent]; dfunc->vkUpdateDescriptorSets (device->dev, COMPOSE_IMAGE_INFOS, cframe->descriptors, 0, 0); VkDescriptorSet sets[] = { cframe->descriptors[0].dstSet, + Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - cctx->layout, 0, 1, sets, 0, 0); + cctx->layout, 0, 2, sets, 0, 0); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 79daf4755..d06a526d5 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -141,7 +141,6 @@ Vulkan_RenderView (qfv_renderframe_t *rFrame) Vulkan_Bsp_Flush (ctx); Vulkan_RenderEntities (r_ent_queue, rFrame); Vulkan_Scene_Flush (ctx); - Vulkan_Translucent_Draw (rFrame); } void diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index 1aff84ecd..153c48e98 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -66,54 +66,6 @@ static const char * __attribute__((used)) translucent_pass_names[] = { "blend", }; -void -Vulkan_Translucent_Draw (qfv_renderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - qfv_renderpass_t *renderpass = rFrame->renderpass; - - translucentctx_t *tctx = ctx->translucent_context; - translucentframe_t *tframe = &tctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = tframe->cmdSet.a[QFV_translucentBlend]; - - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFinal], cmd); - - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - renderpass->renderpass, QFV_passTranslucentFinal, - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - QFV_duCmdBeginLabel (device, cmd, "translucent", { 0, 0.2, 0.6, 1}); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - tctx->pipeline); - VkDescriptorSet set[] = { - tframe->descriptors, - }; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - tctx->layout, 0, 1, set, 0, 0); - - - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - - dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); -} - void Vulkan_Translucent_Init (vulkan_ctx_t *ctx) { @@ -132,9 +84,6 @@ Vulkan_Translucent_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&tctx->frames, frames); tctx->frames.grow = 0; - tctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "oit"); - tctx->layout = Vulkan_CreatePipelineLayout (ctx, "oit_layout"); - __auto_type setLayout = QFV_AllocDescriptorSetLayoutSet (frames, alloca); for (size_t i = 0; i < frames; i++) { setLayout->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "oit_set"); @@ -168,7 +117,6 @@ void Vulkan_Translucent_Shutdown (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; translucentctx_t *tctx = ctx->translucent_context; if (tctx->resources) { @@ -177,7 +125,6 @@ Vulkan_Translucent_Shutdown (vulkan_ctx_t *ctx) tctx->resources = 0; } - dfunc->vkDestroyPipeline (device->dev, tctx->pipeline, 0); free (tctx->frames.a); free (tctx); } From baed4bb16082798aef3c089e1d049c735fac3999 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Dec 2022 10:12:54 +0900 Subject: [PATCH 3272/3664] [gl] Skip lights that are too far from the surface Where too far is 1024 units as that is the maximum supported, or the radius. The change to using unsigned for the distances meant the simple checks missed the effective max dist going negative, thus leading to a segfault. --- libs/video/renderer/gl/gl_lightmap.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 3d7b3631b..4bbcd40b0 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -119,6 +119,8 @@ R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf) VectorSubtract (r_dlights[lnum].origin, entorigin, local); dist = DotProduct (local, surf->plane->normal) - surf->plane->dist; + if (dist > min (1024, r_dlights[lnum].radius)) + continue; VectorMultSub (r_dlights[lnum].origin, dist, surf->plane->normal, impact); @@ -150,7 +152,7 @@ R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf) if (td < maxdist3) { // ensure part is visible on this line maxdist2 = maxdist - td; for (s = 0; s < smax; s++) { - if (sdtable[s] < maxdist2) { + if (sdtable[s] + td < maxdist2) { j = dlightdivtable[(sdtable[s] + td) >> 7]; *bl++ += (grey * j) >> 7; } else @@ -189,6 +191,8 @@ R_AddDynamicLights_3 (const vec4f_t *transform, msurface_t *surf) VectorSubtract (r_dlights[lnum].origin, entorigin, local); dist = DotProduct (local, surf->plane->normal) - surf->plane->dist; + if (dist > min (1024, r_dlights[lnum].radius)) + continue; VectorMultSub (r_dlights[lnum].origin, dist, surf->plane->normal, impact); @@ -221,7 +225,7 @@ R_AddDynamicLights_3 (const vec4f_t *transform, msurface_t *surf) if (td < maxdist3) { // ensure part is visible on this line maxdist2 = maxdist - td; for (s = 0; s < smax; s++) { - if (sdtable[s] < maxdist2) { + if (sdtable[s] + td < maxdist2) { j = dlightdivtable[(sdtable[s] + td) >> 7]; *bl++ += (red * j) >> 7; *bl++ += (green * j) >> 7; From 958b6ff1d81fd0ec51a950ffc5299a95dab3e692 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Dec 2022 10:51:41 +0900 Subject: [PATCH 3273/3664] [glsl] Implement line graph drawing Finally :/ --- include/QF/GLSL/qf_draw.h | 1 + include/QF/GLSL/qf_main.h | 1 - libs/video/renderer/glsl/glsl_draw.c | 14 ++++++++++++++ libs/video/renderer/glsl/glsl_main.c | 5 ----- libs/video/renderer/vid_render_glsl.c | 2 +- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index 10f18d6b9..78ce7fafa 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -46,6 +46,7 @@ void glsl_Draw_CrosshairAt (int ch, int x, int y); void glsl_Draw_TileClear (int x, int y, int w, int h); void glsl_Draw_Fill (int x, int y, int w, int h, int c); void glsl_Draw_Line (int x0, int y0, int x1, int y1, int c); +void glsl_LineGraph (int x, int y, int *h_vals, int count, int height); void glsl_Draw_TextBox (int x, int y, int width, int lines, byte alpha); void glsl_Draw_FadeScreen (void); void glsl_Draw_BlendScreen (quat_t color); diff --git a/include/QF/GLSL/qf_main.h b/include/QF/GLSL/qf_main.h index 621c0b2af..b51b64103 100644 --- a/include/QF/GLSL/qf_main.h +++ b/include/QF/GLSL/qf_main.h @@ -36,6 +36,5 @@ void glsl_R_RenderEntities (struct entqueue_s *queue); void glsl_R_RenderView (void); void glsl_R_ClearState (void); void glsl_R_ViewChanged (void); -void glsl_R_LineGraph (int x, int y, int *h_vals, int count, int height); #endif//__QF_GLSL_qf_main_h diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index b6e7e797c..b08f97a15 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -737,6 +737,20 @@ glsl_Draw_Line (int x0, int y0, int x1, int y1, int c) memcpy (v, verts, size); } +void +glsl_LineGraph (int x, int y, int *h_vals, int count, int height) +{ + static int colors[] = { 0xd0, 0x4f, 0x6f }; + + while (count-- > 0) { + int h = *h_vals++; + int c = h < 9998 || h > 10000 ? 0xfe : colors[h - 9998]; + h = min (h, height); + glsl_Draw_Line (x, y, x, y - h, c); + x++; + } +} + static inline void draw_blendscreen (quat_t color) { diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 1dfbcc6a3..dec092b1c 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -210,11 +210,6 @@ glsl_R_NewScene (scene_t *scene) glsl_R_BuildDisplayLists (scene->models, scene->num_models); } -void -glsl_R_LineGraph (int x, int y, int *h_vals, int count, int height) -{ -} - void glsl_R_ClearState (void) { diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 87608ab40..3969817db 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -476,7 +476,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { .R_ClearState = glsl_R_ClearState, .R_LoadSkys = glsl_R_LoadSkys, .R_NewScene = glsl_R_NewScene, - .R_LineGraph = glsl_R_LineGraph, + .R_LineGraph = glsl_LineGraph, .begin_frame = glsl_begin_frame, .render_view = glsl_render_view, .draw_particles = glsl_R_DrawParticles, From b35854c70609c179f97a6cc4c09289eb9f21df75 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Dec 2022 10:52:16 +0900 Subject: [PATCH 3274/3664] [renderer] Improve time graph display It now shows 200 frames and markings for 0, 1, 2, 2.5, 3.3, 5 and 10ms. --- libs/video/renderer/r_graph.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index a6f051353..52bbfe570 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -40,7 +40,7 @@ #include "r_internal.h" -#define MAX_TIMINGS 100 +#define MAX_TIMINGS 200 int graphval; @@ -79,6 +79,13 @@ R_TimeGraph (view_pos_t abs, view_pos_t len) } memcpy (timings + o, r_timings + a, l * sizeof (timings[0])); r_funcs->R_LineGraph (abs.x, abs.y, r_timings, MAX_TIMINGS, 200); + r_funcs->Draw_Line (abs.x, abs.y, abs.x + MAX_TIMINGS, abs.y, 0x0f); + r_funcs->Draw_Line (abs.x, abs.y - 10, abs.x + MAX_TIMINGS, abs.y - 10, 0x3f); + r_funcs->Draw_Line (abs.x, abs.y - 20, abs.x + MAX_TIMINGS, abs.y - 20, 0x3f); + r_funcs->Draw_Line (abs.x, abs.y - 25, abs.x + MAX_TIMINGS, abs.y - 25, 0x3f); + r_funcs->Draw_Line (abs.x, abs.y - 33, abs.x + MAX_TIMINGS, abs.y - 33, 0x3f); + r_funcs->Draw_Line (abs.x, abs.y - 50, abs.x + MAX_TIMINGS, abs.y - 50, 0x3f); + r_funcs->Draw_Line (abs.x, abs.y - 100, abs.x + MAX_TIMINGS, abs.y - 100, 0x3f); //r_data->graphheight->int_val); timex = (timex + 1) % MAX_TIMINGS; From 9b609469edab80cb3b3778c4f57786950e6630ca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Dec 2022 12:46:45 +0900 Subject: [PATCH 3275/3664] [vulkan] Prevent particle update buffers escaping the staging buffer The escape was actually harmless as the buffers would not be read due to the particle count being 0 (thus why the buffers were at the end of the staging buffer: no space was allocated for them, only for the system buffer, but their offsets were just past the system buffer). However, the validation layers quite rightly did not like that. Thus, the two buffers are pointed to the system buffer so all three descriptors are always valid. --- libs/video/renderer/vulkan/vulkan_particles.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index e624577cb..5ccdcfe3d 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -406,8 +406,17 @@ particles_update (qfv_renderframe_t *rFrame) qfv_parameters_t *params = (qfv_parameters_t *)((byte *)system + paramoffs); memcpy (params, pctx->psystem->partparams, paramsize); - partsize = max (1, partsize); - paramsize = max (1, paramsize); + if (!numParticles) { + // if there are no particles, then no space for the particle states or + // parameters has been allocated in the staging buffer, so map the + // two buffers over the system buffer. This avoids either buffer being + // just past the end of the staging buffer (which the validation layers + // (correctly) do not like). + // This is fine because the two buffers are only read by the the + // compute shader. + partsize = paramsize = syssize; + partoffs = paramoffs = 0; + } size_t sysoffs = packet->offset; VkDescriptorBufferInfo bufferInfo[] = { From 1d84d54509946a084db21dedce9680eb609ffed6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Dec 2022 13:17:07 +0900 Subject: [PATCH 3276/3664] [vulkan] Add cvars to control vulkan 3d frame buffer size Thanks to the 3d frame buffer output being separate from the swap chain, it's possible to have a different frame buffer size from the window size, allowing for a smaller buffer and thus my laptop can cope (mostly) with the vulkan renderer. --- include/QF/Vulkan/qf_vid.h | 3 +++ libs/video/renderer/vulkan/vulkan_main.c | 6 +++++ .../video/renderer/vulkan/vulkan_vid_common.c | 22 +++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index ff57d9853..8d0e414a1 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -98,4 +98,7 @@ void Vulkan_BeginEntityLabel (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd, struct plitem_s *Vulkan_GetConfig (struct vulkan_ctx_s *ctx, const char *name); +extern int vulkan_frame_width; +extern int vulkan_frame_height; + #endif // __QF_Vulkan_vid_h diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index d06a526d5..f3d5084fa 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -181,6 +181,12 @@ Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) .extent = ctx->swapchain->extent, .frames = ctx->swapchain->numImages, }; + if (vulkan_frame_width > 0) { + rp->output.extent.width = vulkan_frame_width; + } + if (vulkan_frame_height > 0) { + rp->output.extent.height = vulkan_frame_height; + } QFV_RenderPass_CreateAttachments (rp); QFV_RenderPass_CreateRenderPass (rp); QFV_RenderPass_CreateFramebuffer (rp); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index f7df0a5b7..d504c5e3a 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -63,6 +63,26 @@ #include "vid_vulkan.h" #include "vkparse.h" +int vulkan_frame_width; +static cvar_t vulkan_frame_width_cvar = { + .name = "vulkan_frame_width", + .description = + "Width of 3D view buffer. Set to 0 for automatic sizing.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &vulkan_frame_width }, +}; + +int vulkan_frame_height; +static cvar_t vulkan_frame_height_cvar = { + .name = "vulkan_frame_height", + .description = + "Height of 3D view buffer. Set to 0 for automatic sizing.", + .default_value = "0", + .flags = CVAR_NONE, + .value = { .type = &cexpr_int, .value = &vulkan_frame_height }, +}; + static const char *instance_extensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, @@ -79,6 +99,8 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) { Sys_MaskPrintf (SYS_vulkan, "Vulkan_Init_Common\n"); + Cvar_Register (&vulkan_frame_width_cvar, 0, 0); + Cvar_Register (&vulkan_frame_height_cvar, 0, 0); Vulkan_Init_Cvars (); R_Init_Cvars (); Vulkan_Script_Init (ctx); From 17c3f12ba24033d0c1900ba7879a9976c5374b05 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Dec 2022 13:29:15 +0900 Subject: [PATCH 3277/3664] [vulkan] Add a cvar for oit fragment buffer size My laptop can't have a buffer larger than 128MB, but 16M fragments wants 512MB. Also, someone running at 4k will probably want a larger buffer. --- include/QF/Vulkan/qf_translucent.h | 1 + include/QF/Vulkan/qf_vid.h | 1 + libs/video/renderer/vulkan/vulkan_translucent.c | 8 ++++---- libs/video/renderer/vulkan/vulkan_vid_common.c | 10 ++++++++++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/QF/Vulkan/qf_translucent.h b/include/QF/Vulkan/qf_translucent.h index 066e99f82..1c6f72fed 100644 --- a/include/QF/Vulkan/qf_translucent.h +++ b/include/QF/Vulkan/qf_translucent.h @@ -40,6 +40,7 @@ typedef struct translucentctx_s { struct qfv_resource_s *resources; + int maxFragments; VkDescriptorPool pool; VkDescriptorSetLayout setLayout; } translucentctx_t; diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 8d0e414a1..ced3132e3 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -100,5 +100,6 @@ struct plitem_s *Vulkan_GetConfig (struct vulkan_ctx_s *ctx, const char *name); extern int vulkan_frame_width; extern int vulkan_frame_height; +extern int vulkan_oit_fragments; #endif // __QF_Vulkan_vid_h diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index 153c48e98..e2e0d8f09 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -59,8 +59,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -#define MAX_FRAGMENTS (1<<24) - static const char * __attribute__((used)) translucent_pass_names[] = { "clear", "blend", @@ -84,6 +82,8 @@ Vulkan_Translucent_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&tctx->frames, frames); tctx->frames.grow = 0; + tctx->maxFragments = vulkan_oit_fragments * 1024 * 1024; + __auto_type setLayout = QFV_AllocDescriptorSetLayoutSet (frames, alloca); for (size_t i = 0; i < frames; i++) { setLayout->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "oit_set"); @@ -201,7 +201,7 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) .name = va (ctx->va_ctx, "frags:%zd", i), .type = qfv_res_buffer, .buffer = { - .size = sizeof (qfv_transfrag_t) * MAX_FRAGMENTS, + .size = sizeof (qfv_transfrag_t) * tctx->maxFragments, .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, }, }; @@ -290,7 +290,7 @@ translucent_clear (qfv_renderframe_t *rFrame) qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); qfv_transtate_t *state = QFV_PacketExtend (packet, 2 * sizeof (*state)); - *state = (qfv_transtate_t) { 0, MAX_FRAGMENTS }; + *state = (qfv_transtate_t) { 0, tctx->maxFragments }; __auto_type bb = &bufferBarriers[qfv_BB_TransferWrite_to_ShaderRW]; QFV_PacketCopyBuffer (packet, tframe->state, bb); QFV_PacketSubmit (packet); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index d504c5e3a..acffbe622 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -82,6 +82,15 @@ static cvar_t vulkan_frame_height_cvar = { .flags = CVAR_NONE, .value = { .type = &cexpr_int, .value = &vulkan_frame_height }, }; +int vulkan_oit_fragments; +static cvar_t vulkan_oit_fragments_cvar = { + .name = "vulkan_oit_fragments", + .description = + "Size of fragment buffer (M) for order independent transparency.", + .default_value = "16", + .flags = CVAR_ROM, + .value = { .type = &cexpr_int, .value = &vulkan_oit_fragments }, +}; static const char *instance_extensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, @@ -101,6 +110,7 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) Cvar_Register (&vulkan_frame_width_cvar, 0, 0); Cvar_Register (&vulkan_frame_height_cvar, 0, 0); + Cvar_Register (&vulkan_oit_fragments_cvar, 0, 0); Vulkan_Init_Cvars (); R_Init_Cvars (); Vulkan_Script_Init (ctx); From 99b568c208d816d590a75d2461a7c650ce642100 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Dec 2022 17:10:04 +0900 Subject: [PATCH 3278/3664] [build] Fix distcheck once again Probably the hardest part of QF to maintain. --- include/Makemodule.am | 2 + include/QF/Makemodule.am | 3 + libs/ui/test/Makemodule.am | 4 +- libs/video/renderer/Makemodule.am | 117 ++++++++++++++++-------------- tools/qfcc/source/Makemodule.am | 4 +- 5 files changed, 72 insertions(+), 58 deletions(-) diff --git a/include/Makemodule.am b/include/Makemodule.am index 11a835523..dab0b609d 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -22,6 +22,7 @@ EXTRA_DIST += \ include/dga_check.h \ include/exp.h \ include/fbset.h \ + include/gamedefs.h \ include/garbage.h \ include/getopt.h \ include/gib_buffer.h \ @@ -90,6 +91,7 @@ EXTRA_DIST += \ include/client/locs.h \ include/client/particles.h \ include/client/sbar.h \ + include/client/screen.h \ include/client/state.h \ include/client/temp_entities.h \ include/client/view.h \ diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 0512d7a13..4fa305366 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -169,6 +169,7 @@ include_qf_simd = \ include_qf_ui = \ include/QF/ui/inputline.h \ + include/QF/ui/passage.h \ include/QF/ui/txtbuffer.h \ include/QF/ui/view.h \ include/QF/ui/vrect.h @@ -199,12 +200,14 @@ include_qf_vulkan = \ include/QF/Vulkan/qf_main.h \ include/QF/Vulkan/qf_matrices.h \ include/QF/Vulkan/qf_model.h \ + include/QF/Vulkan/qf_output.h \ include/QF/Vulkan/qf_palette.h \ include/QF/Vulkan/qf_particles.h \ include/QF/Vulkan/qf_renderpass.h \ include/QF/Vulkan/qf_scene.h \ include/QF/Vulkan/qf_sprite.h \ include/QF/Vulkan/qf_texture.h \ + include/QF/Vulkan/qf_translucent.h \ include/QF/Vulkan/qf_vid.h \ include/QF/Vulkan/scrap.h \ include/QF/Vulkan/shader.h \ diff --git a/libs/ui/test/Makemodule.am b/libs/ui/test/Makemodule.am index e5827dcea..2e9ac62f1 100644 --- a/libs/ui/test/Makemodule.am +++ b/libs/ui/test/Makemodule.am @@ -12,11 +12,11 @@ XFAIL_TESTS += $(libs_ui_xfail_tests) check_PROGRAMS += $(libs_ui_tests) $(libs_ui_xfail_tests) libs_ui_test_test_flow_SOURCES=libs/ui/test/test-flow.c -libs_ui_test_test_flow_LDADD=libs/ui/libQFui.la +libs_ui_test_test_flow_LDADD=libs/ui/libQFui.la libs/ecs/libQFecs.la libs_ui_test_test_flow_DEPENDENCIES=libs/ui/libQFui.la libs_ui_test_test_flow_size_SOURCES=libs/ui/test/test-flow-size.c -libs_ui_test_test_flow_size_LDADD=libs/ui/libQFui.la +libs_ui_test_test_flow_size_LDADD=libs/ui/libQFui.la libs/ecs/libQFecs.la libs_ui_test_test_flow_size_DEPENDENCIES=libs/ui/libQFui.la libs_ui_test_test_passage_SOURCES=libs/ui/test/test-passage.c diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 747aa6669..d01ed618f 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -343,6 +343,8 @@ composef_c = $(vkshaderpath)/compose.frag.spvc oit_blend = $(vkshaderpath)/oit_blend.finc oit_store = $(vkshaderpath)/oit_store.finc oit_h = $(vkshaderpath)/oit.h +matrices_h = $(vkshaderpath)/matrices.h +entity_h = $(vkshaderpath)/entity.h aliasv_src = $(vkshaderpath)/alias.vert aliasv_c = $(vkshaderpath)/alias.vert.spvc aliasf_src = $(vkshaderpath)/alias.frag @@ -370,47 +372,47 @@ pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc waterwarp_src = $(vkshaderpath)/waterwarp.frag waterwarp_c = $(vkshaderpath)/waterwarp.frag.spvc -$(slice_vert_c): $(slice_vert_src) +$(slice_vert_c): $(slice_vert_src) $(matrices_h) -$(glyphv_c): $(glyphv_src) +$(glyphv_c): $(glyphv_src) $(matrices_h) $(glyphf_c): $(glyphf_src) -$(linev_c): $(linev_src) +$(linev_c): $(linev_src) $(matrices_h) $(linef_c): $(linef_src) $(partphysicsc_c): $(partphysicsc_src) $(partupdatec_c): $(partupdatec_src) -$(particlev_c): $(particlev_src) +$(particlev_c): $(particlev_src) $(matrices_h) $(particleg_c): $(particleg_src) $(particlef_c): $(particlef_src) $(oit_store) $(oit_h) -$(sprite_gbufv_c): $(sprite_gbufv_src) +$(sprite_gbufv_c): $(sprite_gbufv_src) $(matrices_h) $(sprite_gbuff_c): $(sprite_gbuff_src) -$(sprite_depthv_c): $(sprite_depthv_src) +$(sprite_depthv_c): $(sprite_depthv_src) $(matrices_h) $(sprite_depthf_c): $(sprite_depthf_src) $(twod_depthf_c): $(twod_depthf_src) -$(twodv_c): $(twodv_src) +$(twodv_c): $(twodv_src) $(matrices_h) $(twodf_c): $(twodf_src) -$(quakebspv_c): $(quakebspv_src) +$(quakebspv_c): $(quakebspv_src) $(entity_h) $(matrices_h) $(quakebspf_c): $(quakebspf_src) -$(bsp_depth_c): $(bsp_depth_src) +$(bsp_depth_c): $(bsp_depth_src) $(entity_h) $(matrices_h) -$(bsp_gbufv_c): $(bsp_gbufv_src) +$(bsp_gbufv_c): $(bsp_gbufv_src) $(entity_h) $(matrices_h) $(bsp_gbufg_c): $(bsp_gbufg_src) $(bsp_gbuff_c): $(bsp_gbuff_src) -$(bsp_shadow_c): $(bsp_shadow_src) +$(bsp_shadow_c): $(bsp_shadow_src) $(entity_h) $(bsp_skyf_c): $(bsp_skyf_src) $(oit_store) $(oit_h) @@ -420,9 +422,9 @@ $(lightingf_c): $(lightingf_src) $(composef_c): $(composef_src) $(oit_blend) $(oit_h) -$(aliasv_c): $(aliasv_src) +$(aliasv_c): $(aliasv_src) $(matrices_h) -$(alias_depth_c): $(alias_depth_src) +$(alias_depth_c): $(alias_depth_src) $(matrices_h) $(aliasf_c): $(aliasf_src) @@ -430,11 +432,11 @@ $(alias_gbuf_c): $(alias_gbuf_src) $(alias_shadow_c): $(alias_shadow_src) -$(iqmv_c): $(iqmv_src) +$(iqmv_c): $(iqmv_src) $(matrices_h) $(iqmf_c): $(iqmf_src) -$(output_c): $(output_src) +$(output_c): $(output_src) $(matrices_h) $(passthrough_c): $(passthrough_src) @@ -444,7 +446,7 @@ $(fstrianglest_c): $(fstrianglest_src) $(pushcolor_c): $(pushcolor_src) -$(waterwarp_c): $(waterwarp_src) +$(waterwarp_c): $(waterwarp_src) $(matrices_h) vkshader_c = \ $(slice_c) \ @@ -520,6 +522,8 @@ BUILT_SOURCES += $(shader_gen) # libs/video/renderer/vulkan/pushcolor.frag.spv EXTRA_DIST += \ + libs/video/renderer/vulkan/vkparse.plist \ + libs/video/renderer/vulkan/vkparse.h \ $(rp_deferred_src) \ $(rp_forward_src) \ $(rp_output_src) \ @@ -529,41 +533,46 @@ EXTRA_DIST += \ $(oit_blend) \ $(oit_store) \ $(oit_h) \ - libs/video/renderer/vulkan/vkparse.plist \ - libs/video/renderer/vulkan/vkparse.h \ - libs/video/renderer/vulkan/shader/alias.frag \ - libs/video/renderer/vulkan/shader/alias.vert \ - libs/video/renderer/vulkan/shader/alias_depth.vert \ - libs/video/renderer/vulkan/shader/alias_gbuf.frag \ - libs/video/renderer/vulkan/shader/alias_shadow.vert \ - libs/video/renderer/vulkan/shader/bsp_depth.vert \ - libs/video/renderer/vulkan/shader/bsp_gbuf.frag \ - libs/video/renderer/vulkan/shader/bsp_gbuf.geom \ - libs/video/renderer/vulkan/shader/bsp_gbuf.vert \ - libs/video/renderer/vulkan/shader/bsp_shadow.vert \ - libs/video/renderer/vulkan/shader/bsp_sky.frag \ - libs/video/renderer/vulkan/shader/bsp_turb.frag \ - libs/video/renderer/vulkan/shader/compose.frag \ - libs/video/renderer/vulkan/shader/iqm.frag \ - libs/video/renderer/vulkan/shader/iqm.vert \ - libs/video/renderer/vulkan/shader/lighting.frag \ - libs/video/renderer/vulkan/shader/passthrough.vert \ - libs/video/renderer/vulkan/shader/fstriangle.vert \ - libs/video/renderer/vulkan/shader/fstrianglest.vert \ - libs/video/renderer/vulkan/shader/partphysics.comp \ - libs/video/renderer/vulkan/shader/partupdate.comp \ - libs/video/renderer/vulkan/shader/particle.vert \ - libs/video/renderer/vulkan/shader/particle.geom \ - libs/video/renderer/vulkan/shader/particle.frag \ - libs/video/renderer/vulkan/shader/pushcolor.frag \ - libs/video/renderer/vulkan/shader/quakebsp.frag \ - libs/video/renderer/vulkan/shader/quakebsp.vert \ - libs/video/renderer/vulkan/shader/shadow.geom \ - libs/video/renderer/vulkan/shader/sprite_depth.vert \ - libs/video/renderer/vulkan/shader/sprite_depth.frag \ - libs/video/renderer/vulkan/shader/sprite_gbuf.vert \ - libs/video/renderer/vulkan/shader/sprite_gbuf.frag \ - libs/video/renderer/vulkan/shader/twod_depth.frag \ - libs/video/renderer/vulkan/shader/twod.frag \ - libs/video/renderer/vulkan/shader/twod.vert \ - libs/video/renderer/vulkan/shader/waterwarp.frag + $(matrices_h) \ + $(entity_h) \ + $(slice_src) \ + $(glyphv_src) \ + $(glyphf_src) \ + $(linev_src) \ + $(linef_src) \ + $(partphysicsc_src) \ + $(partupdatec_src) \ + $(particlev_src) \ + $(particleg_src) \ + $(particlef_src) \ + $(sprite_gbufv_src) \ + $(sprite_gbuff_src) \ + $(sprite_depthv_src) \ + $(sprite_depthf_src) \ + $(twod_depthf_src) \ + $(twodv_src) \ + $(twodf_src) \ + $(quakebspv_src) \ + $(quakebspf_src) \ + $(bsp_depth_src) \ + $(bsp_gbufv_src) \ + $(bsp_gbufg_src) \ + $(bsp_gbuff_src) \ + $(bsp_shadow_src) \ + $(bsp_skyf_src) \ + $(bsp_turbf_src) \ + $(lightingf_src) \ + $(composef_src) \ + $(aliasv_src) \ + $(aliasf_src) \ + $(alias_depth_src) \ + $(alias_gbuf_src) \ + $(alias_shadow_src) \ + $(iqmv_src) \ + $(iqmf_src) \ + $(output_src) \ + $(passthrough_src) \ + $(fstriangle_src) \ + $(fstrianglest_src) \ + $(pushcolor_src) \ + $(waterwarp_src) diff --git a/tools/qfcc/source/Makemodule.am b/tools/qfcc/source/Makemodule.am index a070fad67..4bb24a6f3 100644 --- a/tools/qfcc/source/Makemodule.am +++ b/tools/qfcc/source/Makemodule.am @@ -85,11 +85,11 @@ BUILT_SOURCES += \ tools/qfcc/source/qc-parse.c: tools/qfcc/source/qc-parse.y $(AM_V_YACC)$(YACCCOMPILE) -Dapi.prefix={qc_yy} $< -o $@ -tools/qfcc/source/qc-lex.c: tools/qfcc/source/qc-lex.l tools/qfcc/source/qc-parse.h +tools/qfcc/source/qc-lex.c: tools/qfcc/source/qc-lex.l $(AM_V_LEX)$(LEXCOMPILE) -Pqc_yy -o$@ $< tools/qfcc/source/qp-parse.c: tools/qfcc/source/qp-parse.y $(AM_V_YACC)$(YACCCOMPILE) -Dapi.prefix={qp_yy} $< -o $@ -tools/qfcc/source/qp-lex.c: tools/qfcc/source/qp-lex.l tools/qfcc/source/qp-parse.h +tools/qfcc/source/qp-lex.c: tools/qfcc/source/qp-lex.l $(AM_V_LEX)$(LEXCOMPILE) -Pqp_yy -o$@ $< EXTRA_DIST += \ From 7c4ee70d9ee6e779d2b5c54229e64bcac4759311 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 2 Dec 2022 17:33:26 +0900 Subject: [PATCH 3279/3664] [build] Fix windows builds More bitrot. --- include/QF/GL/extensions.h | 1 + include/QF/GLSL/types.h | 1 + libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- libs/video/targets/vid_win.c | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/QF/GL/extensions.h b/include/QF/GL/extensions.h index be9fe5dfb..2f667280d 100644 --- a/include/QF/GL/extensions.h +++ b/include/QF/GL/extensions.h @@ -38,6 +38,7 @@ # include # define GLAPIENTRY WINAPI # undef LoadImage +# undef E_POINTER # else # ifdef APIENTRY # define GLAPIENTRY APIENTRY diff --git a/include/QF/GLSL/types.h b/include/QF/GLSL/types.h index 16c04719d..3e0819fa9 100644 --- a/include/QF/GLSL/types.h +++ b/include/QF/GLSL/types.h @@ -14,6 +14,7 @@ # include # define GLAPIENTRY WINAPI # undef LoadImage +# undef E_POINTER # else # ifdef APIENTRY # define GLAPIENTRY APIENTRY diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 59c43b09c..a113b3cb2 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -823,7 +823,7 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) lr->framebuffer = create_framebuffer(lr, ctx); } Sys_MaskPrintf (SYS_vulkan, - "shadow maps: %d layers in %zd images: %zd\n", + "shadow maps: %d layers in %zd images: %"PRId64"\n", totalLayers, lctx->light_images.size, lctx->shadow_resources->size); } diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 6b8de7445..492dfd8f8 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -117,7 +117,7 @@ VID_shutdown (void *data) Win_CloseDisplay (); } -static v oid +static void Win_VID_SetPalette (byte *palette, byte *colormap) { viddef.colormap8 = colormap; From 8e1bf69d5d4258a36839ddf40a481b551735396b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Dec 2022 09:43:11 +0900 Subject: [PATCH 3280/3664] [scene] Correct the calculation of world scale World scale can only be approximate if non-uniform scales and non-orthogonal rotations are involved, but it is still useful information sometimes. However, the calculation is expensive (needs a square root), so remove world scale as a component and instead calculate it on an as-needed basis because it is quite expensive to do for every transform when it is used only by the legacy-GL alias model renderer. --- include/QF/scene/transform.h | 12 +++++++++--- libs/scene/transform.c | 15 --------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index ca71392d3..943509590 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -55,7 +55,6 @@ enum { transform_type_localRotation, transform_type_localScale, transform_type_worldRotation, - transform_type_worldScale, transform_type_count }; @@ -321,8 +320,15 @@ Transform_GetWorldScale (transform_t transform) { __auto_type ref = Transform_GetRef (transform); hierarchy_t *h = ref->hierarchy; - vec4f_t *worldScale = h->components[transform_type_worldScale]; - return worldScale[ref->index]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + vec4f_t *m = worldMatrix[ref->index]; + vec4f_t s = { + dotf (m[0], m[0])[0], + dotf (m[1], m[1])[0], + dotf (m[2], m[2])[0], + 0, + }; + return vsqrt4f (s); } XFORMINLINE diff --git a/libs/scene/transform.c b/libs/scene/transform.c index a01867b44..f00d2d527 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -119,11 +119,6 @@ static const component_t transform_components[transform_type_count] = { .create = transform_rotation_identity, .name = "World Rotation", }, - [transform_type_worldScale] = { - .size = sizeof (vec4f_t), - .create = transform_scale_identity, - .name = "World Scale", - }, }; static const hierarchy_type_t transform_type = { @@ -166,9 +161,7 @@ Transform_UpdateMatrices (hierarchy_t *h) mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; mat4f_t *worldInverse = h->components[transform_type_worldInverse]; vec4f_t *localRotation = h->components[transform_type_localRotation]; - vec4f_t *localScale = h->components[transform_type_localScale]; vec4f_t *worldRotation = h->components[transform_type_worldRotation]; - vec4f_t *worldScale = h->components[transform_type_worldScale]; byte *modified = h->components[transform_type_modified]; for (uint32_t i = 0; i < h->num_objects; i++) { @@ -182,7 +175,6 @@ Transform_UpdateMatrices (hierarchy_t *h) memcpy (worldInverse[0], localInverse[0], sizeof (mat4_t)); worldRotation[0] = localRotation[0]; - worldScale[0] = localScale[0]; } for (size_t i = 1; i < h->num_objects; i++) { uint32_t parent = h->parentIndex[i]; @@ -208,13 +200,6 @@ Transform_UpdateMatrices (hierarchy_t *h) localRotation[i]); } } - for (size_t i = 1; i < h->num_objects; i++) { - uint32_t parent = h->parentIndex[i]; - if (modified[i] || modified[parent]) { - worldScale[i] = m3vmulf (worldMatrix[parent], - localScale[i]); - } - } memset (modified, 0, h->num_objects); } From b987414c1d715f131b29f2222aba8c6165c48a9c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Dec 2022 11:28:48 +0900 Subject: [PATCH 3281/3664] [gl] Implement font rendering It doesn't quite work properly due to the alpha-coverage texture being uploaded as normal quake data, but all the basics are working nicely. --- libs/video/renderer/gl/gl_draw.c | 75 +++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 98f47f6ca..fbe3d28e3 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -59,6 +59,8 @@ #include "QF/ui/view.h" #include "compat.h" +#include "r_font.h" +#include "r_text.h" #include "r_internal.h" #include "varrays.h" @@ -117,6 +119,16 @@ static byte menuplyr_pixels[4096]; static int gl_2d_scale = 1; +typedef struct glfont_s { + rfont_t *font; + GLuint texid; +} glfont_t; + +typedef struct glfontset_s + DARRAY_TYPE (glfont_t) glfontset_t; + +static glfontset_t gl_fonts = DARRAY_STATIC_INIT (16); + static void Draw_InitText (void) { @@ -1047,12 +1059,71 @@ gl_Draw_BlendScreen (quat_t color) } int -gl_Draw_AddFont (struct rfont_s *font) +gl_Draw_AddFont (struct rfont_s *rfont) { - return 0; + int fontid = gl_fonts.size; + DARRAY_OPEN_AT (&gl_fonts, fontid, 1); + glfont_t *font = &gl_fonts.a[fontid]; + + font->font = rfont; + font->texid = GL_LoadTexture ("", rfont->scrap.width, rfont->scrap.height, + rfont->scrap_bitmap, 0, 1, 1); + return fontid; +} + +typedef struct { + int fontid; + byte color[4]; +} glrgctx_t; + +static void +gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) +{ + glrgctx_t *rgctx = _rgctx; + glfont_t *font = &gl_fonts.a[rgctx->fontid]; + rfont_t *rfont = font->font; + vrect_t *rect = &rfont->glyph_rects[glyphid]; + + float w = rect->width; + float h = rect->height; + float u = rect->x; + float v = rect->y; + float s = 1.0 / rfont->scrap.width; + float t = 1.0 / rfont->scrap.height; + qfglTexCoord2f (u * s, v * t); + qfglVertex2f (x, y); + qfglTexCoord2f ((u + w) * s, v * t); + qfglVertex2f (x + w, y); + qfglTexCoord2f ((u + w) * s, (v + h) * t); + qfglVertex2f (x + w, y + h); + qfglTexCoord2f (u * s, (v + h) * t); + qfglVertex2f (x, y + h); } void gl_Draw_FontString (int x, int y, int fontid, const char *str) { + if (fontid < 0 || (unsigned) fontid > gl_fonts.size) { + return; + } + glrgctx_t rgctx = { + .fontid = fontid, + .color = { 127, 255, 153, 255 }, + }; + //FIXME ewwwwwww + rtext_t text = { + .text = str, + .language = "en", + .script = HB_SCRIPT_LATIN, + .direction = HB_DIRECTION_LTR, + }; + + qfglBindTexture (GL_TEXTURE_2D, gl_fonts.a[fontid].texid); + qfglBegin (GL_QUADS); + + rshaper_t *shaper = RText_NewShaper (gl_fonts.a[fontid].font); + RText_RenderText (shaper, &text, x, y, gl_render_glyph, &rgctx); + RText_DeleteShaper (shaper); + + qfglEnd (); } From 022c49035fe765d67bf58ed27b95b74d31225b45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Dec 2022 13:35:44 +0900 Subject: [PATCH 3282/3664] [gl] Add a function to load a tex_t image In theory, it supports all the non-palette formats, but only luminance and alpha (tex_l and tex_a) have been tested. Fixes the rather broken glyph rendering. --- include/QF/GL/qf_textures.h | 2 ++ libs/video/renderer/gl/gl_draw.c | 12 ++++++-- libs/video/renderer/gl/gl_textures.c | 42 ++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/include/QF/GL/qf_textures.h b/include/QF/GL/qf_textures.h index ea5a8c9ac..d5b832850 100644 --- a/include/QF/GL/qf_textures.h +++ b/include/QF/GL/qf_textures.h @@ -41,10 +41,12 @@ extern int gl_filter_max; extern qboolean gl_Anisotropy; extern float gl_aniso; extern GLuint gl_part_tex; +struct tex_s; void GL_Upload8 (const byte *data, int width, int height, qboolean mipmap, qboolean alpha); void GL_Upload8_EXT (const byte *data, int width, int height, qboolean mipmap, qboolean alpha); int GL_LoadTexture (const char *identifier, int width, int height, const byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel); +int GL_LoadTex (const char *identifier, int mips, struct tex_s *tex); int GL_FindTexture (const char *identifier); void GL_TextureMode_f (void); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index fbe3d28e3..c8e311b75 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -1066,8 +1066,14 @@ gl_Draw_AddFont (struct rfont_s *rfont) glfont_t *font = &gl_fonts.a[fontid]; font->font = rfont; - font->texid = GL_LoadTexture ("", rfont->scrap.width, rfont->scrap.height, - rfont->scrap_bitmap, 0, 1, 1); + tex_t tex = { + .width = rfont->scrap.width, + .height = rfont->scrap.height, + .format = tex_a, + .loaded = 1, + .data = rfont->scrap_bitmap, + }; + font->texid = GL_LoadTex ("", 0, &tex); return fontid; } @@ -1090,6 +1096,7 @@ gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) float v = rect->y; float s = 1.0 / rfont->scrap.width; float t = 1.0 / rfont->scrap.height; + qfglColor4ubv (rgctx->color); qfglTexCoord2f (u * s, v * t); qfglVertex2f (x, y); qfglTexCoord2f ((u + w) * s, v * t); @@ -1126,4 +1133,5 @@ gl_Draw_FontString (int x, int y, int fontid, const char *str) RText_DeleteShaper (shaper); qfglEnd (); + qfglColor4ubv (color_white); } diff --git a/libs/video/renderer/gl/gl_textures.c b/libs/video/renderer/gl/gl_textures.c index 68af61db2..80313dcd5 100644 --- a/libs/video/renderer/gl/gl_textures.c +++ b/libs/video/renderer/gl/gl_textures.c @@ -42,6 +42,7 @@ #include "QF/crc.h" #include "QF/cvar.h" #include "QF/draw.h" +#include "QF/image.h" #include "QF/mathlib.h" #include "QF/sys.h" #include "QF/GL/defines.h" @@ -641,6 +642,47 @@ SetupTexture: return glt->texnum; } +int +GL_LoadTex (const char *identifier, int mips, tex_t *tex) +{ + GLuint tnum; + qfglGenTextures (1, &tnum); + int format = GL_RGB; + + switch (tex->format) { + case tex_l: + case tex_a: + format = tex->format; + break; + case tex_la: + format = GL_LUMINANCE_ALPHA; + break; + case tex_rgb: + format = GL_RGB; + break; + case tex_rgba: + format = GL_RGBA; + break; + default: + Sys_Error ("GL_CreateScrap: Invalid texture format"); + } + + qfglBindTexture (GL_TEXTURE_2D, tnum); + qfglTexImage2D (GL_TEXTURE_2D, 0, format, tex->width, tex->height, + 0, format, GL_UNSIGNED_BYTE, tex->data); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (mips) { + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + qfglGenerateMipmap (GL_TEXTURE_2D); + } else { + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qfglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + return tnum; +} + void GL_ReleaseTexture (int tex) { From 113e4d5cf06e549bc5cd2768a6c712c142c64399 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Dec 2022 15:24:14 +0900 Subject: [PATCH 3283/3664] [sw] Implement font rendering That looks better than expected. --- libs/video/renderer/sw/draw.c | 76 ++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 303678cff..0adfdd731 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -42,9 +42,20 @@ #include "d_iface.h" #include "d_local.h" +#include "r_font.h" +#include "r_text.h" #include "r_internal.h" #include "vid_internal.h" +typedef struct swfont_s { + rfont_t *font; +} swfont_t; + +typedef struct swfontset_s + DARRAY_TYPE (swfont_t) swfontset_t; + +static swfontset_t sw_fonts = DARRAY_STATIC_INIT (16); + typedef struct { int width; int height; @@ -988,12 +999,73 @@ Draw_BlendScreen (quat_t color) } int -Draw_AddFont (struct rfont_s *font) +Draw_AddFont (struct rfont_s *rfont) { - return 0; + int fontid = sw_fonts.size; + DARRAY_OPEN_AT (&sw_fonts, fontid, 1); + swfont_t *font = &sw_fonts.a[fontid]; + + font->font = rfont; + return fontid; +} + +typedef struct { + vrect_t *glyph_rects; + byte *bitmap; + int width; + byte color; +} swrgctx_t; + +static void +sw_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) +{ + swrgctx_t *rgctx = _rgctx; + vrect_t *rect = &rgctx->glyph_rects[glyphid]; + + float w = rect->width; + float h = rect->height; + if (x < 0 || y < 0 || x + w > vid.width || y + h > vid.height) { + return; + } + int u = rect->x; + int v = rect->y; + byte c = rgctx->color; + byte *src = rgctx->bitmap + v * rgctx->width + u; + byte *dst = d_viewbuffer + y * d_rowbytes + x; + while (h-- > 0) { + for (int i = 0; i < w; i++) { + if (src[i] > 127) { + dst[i] = c; + } + } + src += rgctx->width; + dst += d_rowbytes; + } } void Draw_FontString (int x, int y, int fontid, const char *str) { + if (fontid < 0 || (unsigned) fontid > sw_fonts.size) { + return; + } + swfont_t *font = &sw_fonts.a[fontid]; + rfont_t *rfont = font->font; + swrgctx_t rgctx = { + .glyph_rects = rfont->glyph_rects, + .bitmap = rfont->scrap_bitmap, + .width = rfont->scrap.width, + .color = 63, + }; + //FIXME ewwwwwww + rtext_t text = { + .text = str, + .language = "en", + .script = HB_SCRIPT_LATIN, + .direction = HB_DIRECTION_LTR, + }; + + rshaper_t *shaper = RText_NewShaper (rfont); + RText_RenderText (shaper, &text, x, y, sw_render_glyph, &rgctx); + RText_DeleteShaper (shaper); } From a9745d054060287b4f88f5917b3f67d46290a9fa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Dec 2022 17:13:32 +0900 Subject: [PATCH 3284/3664] [vulkan] Use tex_a instead of tex_l for glyphs While it doesn't really make any difference to the texture upload (8-bit is 8-bit), and the sampler is in control of the interpretation, this makes vulkan more consistent with the specification of the glyph texture. --- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 6e58c3c4b..1980c37d3 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1423,7 +1423,7 @@ Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx) tex_t tex = { .width = rfont->scrap.width, .height = rfont->scrap.height, - .format = tex_l, + .format = tex_a, .loaded = 1, .data = rfont->scrap_bitmap, }; From 1f5ec68b4a81855cfce363191748776ef0c16f81 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Dec 2022 21:06:42 +0900 Subject: [PATCH 3285/3664] [sw] Convert built in 8x8 font transparent pixels I had done the loader for the GPU renderers, so the CPU renderer didn't draw the characters transparently. Fixes the pink block in my ruamoko test scene (due to the notify text area). --- libs/video/renderer/sw/draw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 0adfdd731..e05eb633d 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -247,6 +247,10 @@ Draw_Init (void) if (!draw_chars) { qpic_t *pic = Draw_Font8x8Pic (); draw_chars = pic->data; // FIXME indirect hold on the memory + //FIXME param to Draw_Font8x8Pic + for (int i = 0; i < pic->width * pic->height; i++) { + pic->data[i] = pic->data[i] == 255 ? 0 : pic->data[i]; + } } if (draw_backtile) { r_rectdesc.width = draw_backtile->width; From 46967dbc05504b4f85f1296fa02c0afb2bf8314f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 6 Dec 2022 01:18:01 +0900 Subject: [PATCH 3286/3664] [glsl] Implement font rendering It's not the best code, but it does the job of getting the basics working. --- include/QF/GLSL/qf_textures.h | 2 + libs/video/renderer/glsl/glsl_draw.c | 172 +++++++++++++++++++++-- libs/video/renderer/glsl/glsl_textures.c | 42 ++++++ libs/video/renderer/glsl/quakeforge.glsl | 17 +++ 4 files changed, 225 insertions(+), 8 deletions(-) diff --git a/include/QF/GLSL/qf_textures.h b/include/QF/GLSL/qf_textures.h index 946d4d0c9..7e28acff3 100644 --- a/include/QF/GLSL/qf_textures.h +++ b/include/QF/GLSL/qf_textures.h @@ -31,6 +31,7 @@ #include "QF/qtypes.h" typedef struct scrap_s scrap_t; +struct tex_s; int GLSL_LoadQuakeTexture (const char *identifier, int width, int height, const byte *data); @@ -40,6 +41,7 @@ int GLSL_LoadRGBTexture (const char *identifier, int width, int height, const byte *data); int GLSL_LoadRGBATexture (const char *identifier, int width, int height, const byte *data); +int GLSL_LoadTex (const char *identifier, int mips, struct tex_s *tex); void GLSL_ReleaseTexture (int tex); void GLSL_TextureInit (void); diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index b08f97a15..1db1547cf 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -42,6 +42,7 @@ #include "QF/draw.h" #include "QF/dstring.h" #include "QF/hash.h" +#include "QF/image.h" #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/vid.h" @@ -53,6 +54,8 @@ #include "QF/GLSL/qf_textures.h" #include "QF/GLSL/qf_vid.h" +#include "r_font.h" +#include "r_text.h" #include "r_internal.h" typedef struct cachepic_s { @@ -66,6 +69,16 @@ typedef struct { float color[4]; } drawvert_t; +typedef struct glslfont_s { + rfont_t *font; + GLuint texid; +} glslfont_t; + +typedef struct glfontset_s + DARRAY_TYPE (glslfont_t) glslfontset_t; + +static glslfontset_t glsl_fonts = DARRAY_STATIC_INIT (16); + static const char *twod_vert_effects[] = { "QuakeForge.Vertex.2d", @@ -79,6 +92,12 @@ static const char *twod_frag_effects[] = 0 }; +static const char *twod_alpha_frag_effects[] = +{ + "QuakeForge.Fragment.2d.alpha", + 0 +}; + static float proj_matrix[16]; static struct { @@ -89,17 +108,30 @@ static struct { shaderparam_t vertex; shaderparam_t color; } quake_2d = { - 0, - {"texture", 1}, - {"palette", 1}, - {"mvp_mat", 1}, - {"vertex", 0}, - {"vcolor", 0}, + .texture = {"texture", 1}, + .palette = {"palette", 1}, + .matrix = {"mvp_mat", 1}, + .vertex = {"vertex", 0}, + .color = {"vcolor", 0}, +}; + +static struct { + int program; + shaderparam_t texture; + shaderparam_t matrix; + shaderparam_t vertex; + shaderparam_t color; +} alpha_2d = { + .texture = {"texture", 1}, + .matrix = {"mvp_mat", 1}, + .vertex = {"vertex", 0}, + .color = {"vcolor", 0}, }; static scrap_t *draw_scrap; // hold all 2d images static byte white_block[8 * 8]; static dstring_t *draw_queue; +static dstring_t *glyph_queue; static dstring_t *line_queue; static qpic_t *conchars; static int conback_texture; @@ -380,6 +412,7 @@ glsl_Draw_Init (void) draw_queue = dstring_new (); line_queue = dstring_new (); + glyph_queue = dstring_new (); vert_shader = GLSL_BuildShader (twod_vert_effects); frag_shader = GLSL_BuildShader (twod_frag_effects); @@ -396,6 +429,20 @@ glsl_Draw_Init (void) GLSL_FreeShader (vert_shader); GLSL_FreeShader (frag_shader); + vert_shader = GLSL_BuildShader (twod_vert_effects); + frag_shader = GLSL_BuildShader (twod_alpha_frag_effects); + vert = GLSL_CompileShader ("quakeico.vert", vert_shader, + GL_VERTEX_SHADER); + frag = GLSL_CompileShader ("alpha2d.frag", frag_shader, + GL_FRAGMENT_SHADER); + alpha_2d.program = GLSL_LinkProgram ("alpha2d", vert, frag); + GLSL_ResolveShaderParam (alpha_2d.program, &alpha_2d.texture); + GLSL_ResolveShaderParam (alpha_2d.program, &alpha_2d.matrix); + GLSL_ResolveShaderParam (alpha_2d.program, &alpha_2d.vertex); + GLSL_ResolveShaderParam (alpha_2d.program, &alpha_2d.color); + GLSL_FreeShader (vert_shader); + GLSL_FreeShader (frag_shader); + draw_scrap = GLSL_CreateScrap (2048, GL_LUMINANCE, 0); draw_chars = W_GetLumpName ("conchars"); @@ -866,12 +913,121 @@ glsl_Draw_BlendScreen (quat_t color) } int -glsl_Draw_AddFont (struct rfont_s *font) +glsl_Draw_AddFont (struct rfont_s *rfont) { - return 0; + int fontid = glsl_fonts.size; + DARRAY_OPEN_AT (&glsl_fonts, fontid, 1); + glslfont_t *font = &glsl_fonts.a[fontid]; + + font->font = rfont; + tex_t tex = { + .width = rfont->scrap.width, + .height = rfont->scrap.height, + .format = tex_a, + .loaded = 1, + .data = rfont->scrap_bitmap, + }; + font->texid = GLSL_LoadTex ("", 1, &tex); + return fontid; +} + +typedef struct { + vrect_t *glyph_rects; + dstring_t *batch; + int width; + int height; + float color[4]; +} glslrgctx_t; + +static void +glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) +{ + glslrgctx_t *rgctx = _rgctx; + vrect_t *rect = &rgctx->glyph_rects[glyphid]; + dstring_t *batch = rgctx->batch; + int size = 6 * sizeof (drawvert_t); + + batch->size += size; + dstring_adjust (batch); + drawvert_t *verts = (drawvert_t *) (batch->str + batch->size - size); + + float w = rect->width; + float h = rect->height; + float u = rect->x; + float v = rect->y; + float s = 1.0 / rgctx->width; + float t = 1.0 / rgctx->height; + + verts[0] = (drawvert_t) { + .xyst = { x, y, u * s, v * t }, + }; + verts[1] = (drawvert_t) { + .xyst = { x + w, y, (u + w) * s, v * t }, + }; + verts[2] = (drawvert_t) { + .xyst = { x + w, y + h, (u + w) * s, (v + h) * t }, + }; + verts[3] = (drawvert_t) { + .xyst = { x, y, u * s, v * t }, + }; + verts[4] = (drawvert_t) { + .xyst = { x + w, y + h, (u + w) * s, (v + h) * t }, + }; + verts[5] = (drawvert_t) { + .xyst = { x, y + h, u * s, (v + h) * t }, + }; + + QuatCopy (rgctx->color, verts[0].color); + QuatCopy (rgctx->color, verts[1].color); + QuatCopy (rgctx->color, verts[2].color); + QuatCopy (rgctx->color, verts[3].color); + QuatCopy (rgctx->color, verts[4].color); + QuatCopy (rgctx->color, verts[5].color); } void glsl_Draw_FontString (int x, int y, int fontid, const char *str) { + if (fontid < 0 || (unsigned) fontid > glsl_fonts.size) { + return; + } + glslfont_t *font = &glsl_fonts.a[fontid]; + rfont_t *rfont = font->font; + glslrgctx_t rgctx = { + .glyph_rects = rfont->glyph_rects, + .batch = glyph_queue, + .width = rfont->scrap.width, + .height = rfont->scrap.height, + }; + quat_t color = { 127, 255, 153, 255 }; + QuatScale (color, 1.0f/255.0f, rgctx.color); + //FIXME ewwwwwww + rtext_t text = { + .text = str, + .language = "en", + .script = HB_SCRIPT_LATIN, + .direction = HB_DIRECTION_LTR, + }; + + rshaper_t *shaper = RText_NewShaper (rfont); + RText_RenderText (shaper, &text, x, y, glsl_render_glyph, &rgctx); + RText_DeleteShaper (shaper); + + qfeglUseProgram (alpha_2d.program); + qfeglEnableVertexAttribArray (alpha_2d.vertex.location); + qfeglEnableVertexAttribArray (alpha_2d.color.location); + qfeglUniformMatrix4fv (alpha_2d.matrix.location, 1, false, proj_matrix); + qfeglBindTexture (GL_TEXTURE_2D, font->texid); + qfeglBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + if (glyph_queue->size) { + qfeglVertexAttribPointer (alpha_2d.vertex.location, 4, GL_FLOAT, + 0, 32, glyph_queue->str); + qfeglVertexAttribPointer (alpha_2d.color.location, 4, GL_FLOAT, + 0, 32, glyph_queue->str + 16); + + qfeglDrawArrays (GL_TRIANGLES, 0, glyph_queue->size / 32); + } + glyph_queue->size = 0; + qfeglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + qfeglUseProgram (quake_2d.program); } diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index efebdc6e0..657ffa3f6 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -39,6 +39,7 @@ #include #include "QF/cmd.h" +#include "QF/image.h" #include "QF/mathlib.h" #include "QF/model.h" #include "QF/render.h" @@ -238,6 +239,47 @@ GLSL_LoadRGBATexture (const char *identifier, int width, int height, return tnum; } +int +GLSL_LoadTex (const char *identifier, int linear, tex_t *tex) +{ + GLuint tnum; + qfeglGenTextures (1, &tnum); + int format = GL_RGB; + + switch (tex->format) { + case tex_l: + case tex_a: + format = GL_LUMINANCE; + break; + case tex_la: + format = GL_LUMINANCE_ALPHA; + break; + case tex_rgb: + format = GL_RGB; + break; + case tex_rgba: + format = GL_RGBA; + break; + default: + Sys_Error ("GL_CreateScrap: Invalid texture format"); + } + + qfeglBindTexture (GL_TEXTURE_2D, tnum); + qfeglTexImage2D (GL_TEXTURE_2D, 0, format, tex->width, tex->height, + 0, format, GL_UNSIGNED_BYTE, tex->data); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (linear) { + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qfeglTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + qfeglGenerateMipmap (GL_TEXTURE_2D); + return tnum; +} + void GLSL_ReleaseTexture (int tex) { diff --git a/libs/video/renderer/glsl/quakeforge.glsl b/libs/video/renderer/glsl/quakeforge.glsl index 05001cb83..b6f16ca0e 100644 --- a/libs/video/renderer/glsl/quakeforge.glsl +++ b/libs/video/renderer/glsl/quakeforge.glsl @@ -432,6 +432,23 @@ main (void) gl_FragColor = palettedColor (pix) * color; } +-- Fragment.2d.alpha + +uniform sampler2D texture; +varying vec4 color; +varying vec2 st; + +void +main (void) +{ + float alpha; + + alpha = texture2D (texture, st).r; + if (alpha == 0.0) + discard; + gl_FragColor = alpha * color; +} + -- Vertex.iqm uniform mat4 mvp_mat; From 136bf882f6b039c2387e3710cdcb1c76f8275a84 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 7 Dec 2022 15:11:08 +0900 Subject: [PATCH 3287/3664] [ui] Move font loading into new gui library Font and text handling is very much part of user interface and at least partially independent of rendering, but does fit it better with GUI than genera UI (ie, both graphics and text mode), thus libQFgui as well as libQFui are built in the ui directory. The existing font related builtins have been moved into the ruamoko client library. --- include/QF/GL/qf_draw.h | 4 +- include/QF/GLSL/qf_draw.h | 4 +- include/QF/Vulkan/qf_draw.h | 4 +- include/QF/draw.h | 4 +- include/QF/plugin/vid_render.h | 4 +- include/{r_font.h => QF/ui/font.h} | 20 ++-- include/r_text.h | 11 +- include/rua_internal.h | 1 + libs/ruamoko/Makemodule.am | 5 +- libs/ruamoko/rua_game_init.c | 1 + libs/ruamoko/rua_gui.c | 105 ++++++++++++++++++++ libs/ui/Makemodule.am | 13 ++- libs/{video/renderer/r_font.c => ui/font.c} | 20 ++-- libs/video/renderer/Makemodule.am | 1 - libs/video/renderer/gl/gl_draw.c | 8 +- libs/video/renderer/glsl/glsl_draw.c | 8 +- libs/video/renderer/r_progs.c | 25 ----- libs/video/renderer/r_text.c | 11 +- libs/video/renderer/sw/draw.c | 8 +- libs/video/renderer/vid_render_vulkan.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 6 +- ruamoko/qwaq/Makemodule.am | 1 + ruamoko/qwaq/builtins/graphics.c | 4 +- 23 files changed, 186 insertions(+), 84 deletions(-) rename include/{r_font.h => QF/ui/font.h} (83%) create mode 100644 libs/ruamoko/rua_gui.c rename libs/{video/renderer/r_font.c => ui/font.c} (91%) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index ea051f356..0188920e5 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -29,7 +29,7 @@ #define __gl_draw_h struct qpic_s; -struct rfont_s; +struct font_s; struct draw_charbuffer_s; void gl_Draw_Init (void); @@ -58,7 +58,7 @@ void gl_Draw_Pic (int x, int y, struct qpic_s *pic); void gl_Draw_Picf (float x, float y, struct qpic_s *pic); void gl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); -int gl_Draw_AddFont (struct rfont_s *font); +int gl_Draw_AddFont (struct font_s *font); void gl_Draw_FontString (int x, int y, int fontid, const char *str); void GL_Set2D (void); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index 78ce7fafa..dffc0bee6 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -29,7 +29,7 @@ #define __QF_GLSL_qf_draw_h struct qpic_s; -struct rfont_s; +struct font_s; struct draw_charbuffer_s; void glsl_Draw_Init (void); @@ -59,7 +59,7 @@ void glsl_Draw_Pic (int x, int y, struct qpic_s *pic); void glsl_Draw_Picf (float x, float y, struct qpic_s *pic); void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); -int glsl_Draw_AddFont (struct rfont_s *font); +int glsl_Draw_AddFont (struct font_s *font); void glsl_Draw_FontString (int x, int y, int fontid, const char *str); void GLSL_Set2D (void); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 3c327b308..bb3081b67 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -37,7 +37,7 @@ typedef enum { struct vulkan_ctx_s; struct qfv_renderframe_s; struct qpic_s; -struct rfont_s; +struct font_s; struct draw_charbuffer_s; void Vulkan_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer, @@ -81,7 +81,7 @@ void Vulkan_Draw_Picf (float x, float y, struct qpic_s *pic, void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height, struct vulkan_ctx_s *ctx); -int Vulkan_Draw_AddFont (struct rfont_s *font, struct vulkan_ctx_s *ctx); +int Vulkan_Draw_AddFont (struct font_s *font, struct vulkan_ctx_s *ctx); void Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, struct vulkan_ctx_s *ctx); diff --git a/include/QF/draw.h b/include/QF/draw.h index d31f877ab..f340183ab 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -267,8 +267,8 @@ void Draw_Picf (float x, float y, qpic_t *pic); */ void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); -struct rfont_s; -int Draw_AddFont (struct rfont_s *font); +struct font_s; +int Draw_AddFont (struct font_s *font); void Draw_FontString (int x, int y, int fontid, const char *str); ///@} diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index 64427fe57..d4ef5d744 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -80,7 +80,7 @@ typedef struct vid_model_funcs_s { } vid_model_funcs_t; struct tex_s; -struct rfont_s; +struct font_s; struct draw_charbuffer_s; typedef void (*capfunc_t) (struct tex_s *screencap, void *data); @@ -110,7 +110,7 @@ typedef struct vid_render_funcs_s { void (*Draw_Pic) (int x, int y, qpic_t *pic); void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); - int (*Draw_AddFont) (struct rfont_s *font); + int (*Draw_AddFont) (struct font_s *font); void (*Draw_FontString) (int x, int y, int fontid, const char *str); diff --git a/include/r_font.h b/include/QF/ui/font.h similarity index 83% rename from include/r_font.h rename to include/QF/ui/font.h index a39588de1..ab526a8ab 100644 --- a/include/r_font.h +++ b/include/QF/ui/font.h @@ -1,7 +1,7 @@ /* - r_font.h + font.h - Renderer font management + Font management Copyright (C) 2022 Bill Currie @@ -28,8 +28,8 @@ */ -#ifndef __r_font_h -#define __r_font_h +#ifndef __QF_ui_font_h +#define __QF_ui_font_h #include #include FT_FREETYPE_H @@ -43,7 +43,7 @@ typedef struct fontent_s { uint32_t id; } fontent_t; -typedef struct rfont_s { +typedef struct font_s { void *font_resource; FT_Face face; rscrap_t scrap; @@ -51,10 +51,10 @@ typedef struct rfont_s { FT_Long num_glyphs; vrect_t *glyph_rects; vec2i_t *glyph_bearings; -} rfont_t; +} font_t; -void R_FontInit (void); -void R_FontFree (rfont_t *font); -rfont_t *R_FontLoad (QFile *font_file, int size); +void Font_Init (void); +void Font_Free (font_t *font); +font_t *Font_Load (QFile *font_file, int size); -#endif//__r_font_h +#endif//__QF_ui_font_h diff --git a/include/r_text.h b/include/r_text.h index 72c5c8386..d4be76f00 100644 --- a/include/r_text.h +++ b/include/r_text.h @@ -44,6 +44,11 @@ typedef struct script_component_s { hb_direction_t direction; } script_component_t; +typedef struct glyph_component_s { + int id; + int x, y; +} glyph_component_t; + typedef struct rtext_s { const char *text; const char *language; @@ -53,12 +58,12 @@ typedef struct rtext_s { typedef struct r_hb_featureset_s DARRAY_TYPE (hb_feature_t) r_hb_featureset_t; -struct rfont_s; +struct font_s; struct rglyph_s; typedef void rtext_render_t (uint32_t glyphid, int x, int y, void *data); typedef struct rshaper_s { - struct rfont_s *rfont; + struct font_s *rfont; hb_font_t *font; hb_buffer_t *buffer; r_hb_featureset_t features; @@ -71,7 +76,7 @@ extern hb_feature_t KerningOn; extern hb_feature_t CligOff; extern hb_feature_t CligOn; -rshaper_t *RText_NewShaper (struct rfont_s *font); +rshaper_t *RText_NewShaper (struct font_s *font); void RText_DeleteShaper (rshaper_t *shaper); void RText_AddFeature (rshaper_t *shaper, hb_feature_t feature); void RText_ShapeText (rshaper_t *shaper, rtext_t *text); diff --git a/include/rua_internal.h b/include/rua_internal.h index 85880d715..c646c1118 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -60,6 +60,7 @@ int QFile_AllocHandle (struct progs_s *pr, QFile *file); QFile *QFile_GetFile (struct progs_s *pr, int handle); struct plitem_s *Plist_GetItem (struct progs_s *pr, int handle); +void RUA_GUI_Init (struct progs_s *pr, int secure); void RUA_Input_Init (struct progs_s *pr, int secure); void RUA_Mersenne_Init (struct progs_s *pr, int secure); void RUA_Model_Init (struct progs_s *pr, int secure); diff --git a/libs/ruamoko/Makemodule.am b/libs/ruamoko/Makemodule.am index c34590426..e0f39850c 100644 --- a/libs/ruamoko/Makemodule.am +++ b/libs/ruamoko/Makemodule.am @@ -30,12 +30,15 @@ libs_ruamoko_libQFruamoko_la_SOURCES= \ libs_ruamoko_libQFruamoko_client_la_LDFLAGS= $(lib_ldflags) libs_ruamoko_libQFruamoko_client_la_LIBADD= \ - libs/ruamoko/libQFruamoko.la + libs/ruamoko/libQFruamoko.la \ + libs/ui/libQFgui.la libs_ruamoko_libQFruamoko_client_la_DEPENDENCIES= \ libs/ruamoko/libQFruamoko.la \ + libs/ui/libQFgui.la \ $(ruamoko_rua_libs) libs_ruamoko_libQFruamoko_client_la_SOURCES= \ libs/ruamoko/rua_game_init.c \ + libs/ruamoko/rua_gui.c \ libs/ruamoko/rua_input.c \ libs/ruamoko/rua_mersenne.c \ libs/ruamoko/rua_model.c \ diff --git a/libs/ruamoko/rua_game_init.c b/libs/ruamoko/rua_game_init.c index 1312d7ee3..81b2dde72 100644 --- a/libs/ruamoko/rua_game_init.c +++ b/libs/ruamoko/rua_game_init.c @@ -34,6 +34,7 @@ #include "rua_internal.h" static void (*init_funcs[])(progs_t *, int) = { + RUA_GUI_Init, RUA_Input_Init, RUA_Mersenne_Init, RUA_Model_Init, diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c new file mode 100644 index 000000000..b9ef12e2f --- /dev/null +++ b/libs/ruamoko/rua_gui.c @@ -0,0 +1,105 @@ +/* + r_gui.c + + Ruamoko GUI support functions + + Copyright (C) 2022 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/draw.h" +#include "QF/progs.h" +#include "QF/quakefs.h" +#include "QF/render.h" + +#include "QF/ui/font.h" +#include "QF/ui/view.h" + +#include "QF/plugin/vid_render.h" + +#include "rua_internal.h" + +typedef struct { +} gui_resources_t; + +#define bi(x) static void bi_##x (progs_t *pr, void *_res) + +bi (Font_Load) +{ + const char *font_path = P_GSTRING (pr, 0); + int font_size = P_INT (pr, 1); + + QFile *font_file = QFS_FOpenFile (font_path); + font_t *font = Font_Load (font_file, font_size); + R_INT (pr) = r_funcs->Draw_AddFont (font); +} + +bi (Font_String) +{ + int x = P_INT (pr, 0); + int y = P_INT (pr, 1); + int fontid = P_INT (pr, 2); + const char *str = P_GSTRING (pr, 3); + r_funcs->Draw_FontString (x, y, fontid, str); +} + +#undef bi +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } +static builtin_t builtins[] = { + bi(Font_Load, 2, p(string), p(int)), + bi(Font_String, 4, p(int), p(int), p(int), p(string)), + + {0} +}; + +static void +bi_gui_clear (progs_t *pr, void *_res) +{ +} + +static void +bi_gui_destroy (progs_t *pr, void *_res) +{ + gui_resources_t *res = _res; + free (res); +} + +void +RUA_GUI_Init (progs_t *pr, int secure) +{ + gui_resources_t *res = calloc (1, sizeof (gui_resources_t)); + + PR_Resources_Register (pr, "Draw", res, bi_gui_clear, bi_gui_destroy); + PR_RegisterBuiltins (pr, builtins, res); +} diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am index 38d252a35..0a973941f 100644 --- a/libs/ui/Makemodule.am +++ b/libs/ui/Makemodule.am @@ -1,11 +1,22 @@ include libs/ui/test/Makemodule.am -lib_LTLIBRARIES += libs/ui/libQFui.la +lib_LTLIBRARIES += \ + libs/ui/libQFgui.la \ + libs/ui/libQFui.la + +gui_deps = \ + libs/ui/libQFui.la ui_deps = \ libs/ecs/libQFecs.la \ libs/util/libQFutil.la +libs_ui_libQFgui_la_LDFLAGS= $(lib_ldflags) +libs_ui_libQFgui_la_LIBADD= $(gui_deps) $(ui_deps) +libs_ui_libQFgui_la_DEPENDENCIES= $(gui_deps) $(ui_deps) +libs_ui_libQFgui_la_SOURCES= \ + libs/ui/font.c + libs_ui_libQFui_la_LDFLAGS= $(lib_ldflags) libs_ui_libQFui_la_LIBADD= $(ui_deps) libs_ui_libQFui_la_DEPENDENCIES= $(ui_deps) diff --git a/libs/video/renderer/r_font.c b/libs/ui/font.c similarity index 91% rename from libs/video/renderer/r_font.c rename to libs/ui/font.c index 08131ac74..29e6704f0 100644 --- a/libs/video/renderer/r_font.c +++ b/libs/ui/font.c @@ -1,7 +1,7 @@ /* - r_font.c + font.c - Renderer font management management + Font management Copyright (C) 2022 Bill Currie @@ -36,14 +36,14 @@ #include "QF/sys.h" #include "QF/math/bitop.h" -#include "r_font.h" +#include "QF/ui/font.h" #include "compat.h" static FT_Library ft; static void -copy_glyph (vrect_t *rect, FT_GlyphSlot src_glyph, rfont_t *font) +copy_glyph (vrect_t *rect, FT_GlyphSlot src_glyph, font_t *font) { int dst_pitch = font->scrap.width; byte *dst = font->scrap_bitmap + rect->x + rect->y * dst_pitch; @@ -58,7 +58,7 @@ copy_glyph (vrect_t *rect, FT_GlyphSlot src_glyph, rfont_t *font) } VISIBLE void -R_FontInit (void) +Font_Init (void) { if (FT_Init_FreeType (&ft)) { Sys_Error ("Could not init FreeType library"); @@ -66,7 +66,7 @@ R_FontInit (void) } VISIBLE void -R_FontFree (rfont_t *font) +Font_Free (font_t *font) { if (font->face) { FT_Done_Face (font->face); @@ -81,18 +81,18 @@ R_FontFree (rfont_t *font) free (font); } -VISIBLE rfont_t * -R_FontLoad (QFile *font_file, int size) +VISIBLE font_t * +Font_Load (QFile *font_file, int size) { byte *font_data = QFS_LoadFile (font_file, 0); if (!font_data) { return 0; } size_t font_size = qfs_filesize; - rfont_t *font = calloc (1, sizeof (rfont_t)); + font_t *font = calloc (1, sizeof (font_t)); font->font_resource = font_data; if (FT_New_Memory_Face (ft, font_data, font_size, 0, &font->face)) { - R_FontFree (font); + Font_Free (font); return 0; } diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index d01ed618f..171225709 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -53,7 +53,6 @@ libs_video_renderer_libQFrenderer_la_SOURCES=\ libs/video/renderer/r_cvar.c \ libs/video/renderer/r_draw.c \ libs/video/renderer/r_fog.c \ - libs/video/renderer/r_font.c \ libs/video/renderer/r_graph.c \ libs/video/renderer/r_init.c \ libs/video/renderer/r_light.c \ diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index c8e311b75..5fe26b23a 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -56,10 +56,10 @@ #include "QF/GL/qf_textures.h" #include "QF/GL/qf_vid.h" #include "QF/GL/types.h" +#include "QF/ui/font.h" #include "QF/ui/view.h" #include "compat.h" -#include "r_font.h" #include "r_text.h" #include "r_internal.h" #include "varrays.h" @@ -120,7 +120,7 @@ static byte menuplyr_pixels[4096]; static int gl_2d_scale = 1; typedef struct glfont_s { - rfont_t *font; + font_t *font; GLuint texid; } glfont_t; @@ -1059,7 +1059,7 @@ gl_Draw_BlendScreen (quat_t color) } int -gl_Draw_AddFont (struct rfont_s *rfont) +gl_Draw_AddFont (font_t *rfont) { int fontid = gl_fonts.size; DARRAY_OPEN_AT (&gl_fonts, fontid, 1); @@ -1087,7 +1087,7 @@ gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) { glrgctx_t *rgctx = _rgctx; glfont_t *font = &gl_fonts.a[rgctx->fontid]; - rfont_t *rfont = font->font; + font_t *rfont = font->font; vrect_t *rect = &rfont->glyph_rects[glyphid]; float w = rect->width; diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 1db1547cf..bc693c02a 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -46,6 +46,7 @@ #include "QF/quakefs.h" #include "QF/sys.h" #include "QF/vid.h" +#include "QF/ui/font.h" #include "QF/ui/view.h" #include "QF/GLSL/defines.h" @@ -54,7 +55,6 @@ #include "QF/GLSL/qf_textures.h" #include "QF/GLSL/qf_vid.h" -#include "r_font.h" #include "r_text.h" #include "r_internal.h" @@ -70,7 +70,7 @@ typedef struct { } drawvert_t; typedef struct glslfont_s { - rfont_t *font; + font_t *font; GLuint texid; } glslfont_t; @@ -913,7 +913,7 @@ glsl_Draw_BlendScreen (quat_t color) } int -glsl_Draw_AddFont (struct rfont_s *rfont) +glsl_Draw_AddFont (font_t *rfont) { int fontid = glsl_fonts.size; DARRAY_OPEN_AT (&glsl_fonts, fontid, 1); @@ -992,7 +992,7 @@ glsl_Draw_FontString (int x, int y, int fontid, const char *str) return; } glslfont_t *font = &glsl_fonts.a[fontid]; - rfont_t *rfont = font->font; + font_t *rfont = font->font; glslrgctx_t rgctx = { .glyph_rects = rfont->glyph_rects, .batch = glyph_queue, diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 054629d7a..9d8309dfa 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -46,7 +46,6 @@ #include "QF/ui/view.h" #include "r_internal.h" -#include "r_font.h" typedef struct { pr_int_t width; @@ -382,27 +381,6 @@ bi_Draw_Height (progs_t *pr, void *_res) R_INT (pr) = r_data->vid->height; } -static void -bi_Font_Load (progs_t *pr, void *_res) -{ - const char *font_path = P_GSTRING (pr, 0); - int font_size = P_INT (pr, 1); - - QFile *font_file = QFS_FOpenFile (font_path); - rfont_t *font = R_FontLoad (font_file, font_size); - R_INT (pr) = r_funcs->Draw_AddFont (font); -} - -static void -bi_Font_String (progs_t *pr, void *_res) -{ - int x = P_INT (pr, 0); - int y = P_INT (pr, 1); - int fontid = P_INT (pr, 2); - const char *str = P_GSTRING (pr, 3); - r_funcs->Draw_FontString (x, y, fontid, str); -} - static void bi_Draw_CreateBuffer (progs_t *pr, void *_res) { @@ -537,9 +515,6 @@ static builtin_t builtins[] = { bi(Draw_Line, 5, p(int), p(int), p(int), p(int), p(int)), bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)), - bi(Font_Load, 2, p(string), p(int)), - bi(Font_String, 4, p(int), p(int), p(int), p(string)), - bi(Draw_CreateBuffer, 2, p(int), p(int)), bi(Draw_DestroyBuffer, 1, p(ptr)), bi(Draw_ClearBuffer, 1, p(ptr)), diff --git a/libs/video/renderer/r_text.c b/libs/video/renderer/r_text.c index 2d39ebbf0..dc274d4be 100644 --- a/libs/video/renderer/r_text.c +++ b/libs/video/renderer/r_text.c @@ -1,7 +1,7 @@ /* - r_font.c + r_text.c - Renderer font management management + Renderer font text management Copyright (C) 2022 Bill Currie @@ -35,13 +35,14 @@ #include "QF/quakefs.h" #include "QF/sys.h" -#include "r_font.h" +#include "QF/ui/font.h" + #include "r_text.h" #include "compat.h" rshaper_t * -RText_NewShaper (rfont_t *font) +RText_NewShaper (font_t *font) { rshaper_t *shaper = malloc (sizeof (rshaper_t)); shaper->rfont = font; @@ -96,7 +97,7 @@ RText_RenderText (rshaper_t *shaper, rtext_t *text, int x, int y, __auto_type glyphPos = hb_buffer_get_glyph_positions (shaper->buffer, &count); - rfont_t *font = shaper->rfont; + font_t *font = shaper->rfont; for (unsigned i = 0; i < count; i++) { vec2i_t bearing = font->glyph_bearings[glyphInfo[i].codepoint]; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index e05eb633d..f86e0a5f7 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -38,17 +38,17 @@ #include #include "QF/quakefs.h" +#include "QF/ui/font.h" #include "QF/ui/view.h" #include "d_iface.h" #include "d_local.h" -#include "r_font.h" #include "r_text.h" #include "r_internal.h" #include "vid_internal.h" typedef struct swfont_s { - rfont_t *font; + font_t *font; } swfont_t; typedef struct swfontset_s @@ -1003,7 +1003,7 @@ Draw_BlendScreen (quat_t color) } int -Draw_AddFont (struct rfont_s *rfont) +Draw_AddFont (struct font_s *rfont) { int fontid = sw_fonts.size; DARRAY_OPEN_AT (&sw_fonts, fontid, 1); @@ -1054,7 +1054,7 @@ Draw_FontString (int x, int y, int fontid, const char *str) return; } swfont_t *font = &sw_fonts.a[fontid]; - rfont_t *rfont = font->font; + font_t *rfont = font->font; swrgctx_t rgctx = { .glyph_rects = rfont->glyph_rects, .bitmap = rfont->scrap_bitmap, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index f859154b5..4f5bb0e7a 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -285,7 +285,7 @@ vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, in } static int -vulkan_Draw_AddFont (struct rfont_s *font) +vulkan_Draw_AddFont (struct font_s *font) { return Vulkan_Draw_AddFont (font, vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 1980c37d3..e3d4ae288 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -66,9 +66,9 @@ #include "QF/Vulkan/resource.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" +#include "QF/ui/font.h" #include "QF/ui/view.h" -#include "r_font.h" #include "r_text.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -169,7 +169,7 @@ typedef struct drawfontres_s { typedef struct drawfont_s { VkDescriptorSet set; drawfontres_t *resource; - rfont_t *font; + font_t *font; } drawfont_t; typedef struct drawfontset_s @@ -1377,7 +1377,7 @@ Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) } int -Vulkan_Draw_AddFont (rfont_t *rfont, vulkan_ctx_t *ctx) +Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; diff --git a/ruamoko/qwaq/Makemodule.am b/ruamoko/qwaq/Makemodule.am index 5b844ece2..0ab3926a4 100644 --- a/ruamoko/qwaq/Makemodule.am +++ b/ruamoko/qwaq/Makemodule.am @@ -110,6 +110,7 @@ qwaq_x11_libs= \ $(qwaq_cl_plugin_libs) \ ${top_builddir}/libs/gib/libQFgib.la \ ${top_builddir}/libs/ruamoko/libQFruamoko_client.la \ + $(top_builddir)/libs/ui/libQFgui.la \ $(top_builddir)/libs/video/renderer/libQFrenderer.la \ $(top_builddir)/libs/models/libQFmodels.la \ $(top_builddir)/libs/video/targets/libQFx11.la \ diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index a241e2826..018301639 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -56,9 +56,9 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/font.h" #include "rua_internal.h" -#include "r_font.h" #include "ruamoko/qwaq/qwaq.h" @@ -344,7 +344,7 @@ BI_Graphics_Init (progs_t *pr) IN_Init (); Mod_Init (); R_Init (); - R_FontInit (); + Font_Init (); R_Progs_Init (pr); RUA_Game_Init (pr, thread->rua_security); From 95f55dfc34abf3a8526bc6f78908aad8abf2d37a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 Dec 2022 15:33:50 +0900 Subject: [PATCH 3288/3664] [ui] Move text handling into gui lib And add a function to process a passage into a set of views with glyphs. The views can be flowed: they have flow gravity and their sizes set to contain all the glyphs within each view (nominally, words). Nothing is tested yet, and font rendering is currently broken completely. --- include/{r_text.h => QF/ui/text.h} | 71 ++++-- libs/ui/Makemodule.am | 3 +- libs/ui/text.c | 282 +++++++++++++++++++++++ libs/video/renderer/Makemodule.am | 1 - libs/video/renderer/gl/gl_draw.c | 7 +- libs/video/renderer/glsl/glsl_draw.c | 7 +- libs/video/renderer/r_text.c | 115 --------- libs/video/renderer/sw/draw.c | 7 +- libs/video/renderer/vulkan/vulkan_draw.c | 7 +- 9 files changed, 350 insertions(+), 150 deletions(-) rename include/{r_text.h => QF/ui/text.h} (53%) create mode 100644 libs/ui/text.c delete mode 100644 libs/video/renderer/r_text.c diff --git a/include/r_text.h b/include/QF/ui/text.h similarity index 53% rename from include/r_text.h rename to include/QF/ui/text.h index d4be76f00..b145a9d60 100644 --- a/include/r_text.h +++ b/include/QF/ui/text.h @@ -1,7 +1,7 @@ /* - r_text.h + text.h - Renderer text management + Text management Copyright (C) 2022 Bill Currie @@ -28,8 +28,8 @@ */ -#ifndef __r_text_h -#define __r_text_h +#ifndef __QF_ui_text_h +#define __QF_ui_text_h #include #include @@ -44,30 +44,54 @@ typedef struct script_component_s { hb_direction_t direction; } script_component_t; -typedef struct glyph_component_s { - int id; +typedef struct glyphobj_s { + int glyphid; int x, y; -} glyph_component_t; + int fontid; +} glyphobj_t; -typedef struct rtext_s { +typedef struct glyphref_s { + uint32_t start; + uint32_t count; +} glyphref_t; + +typedef struct glyphset_s { + glyphobj_t *glyphs; + uint32_t count; +} glyphset_t; + +typedef struct text_s { const char *text; const char *language; hb_script_t script; hb_direction_t direction; -} rtext_t; +} text_t; -typedef struct r_hb_featureset_s DARRAY_TYPE (hb_feature_t) r_hb_featureset_t; +enum { + // covers both view and passage text object hierarcies + text_href, + // all the glyhphs in a passage + text_passage, + text_glyphs, + text_script, + text_font, + text_features, + + text_type_count +}; + +typedef struct featureset_s DARRAY_TYPE (hb_feature_t) featureset_t; struct font_s; struct rglyph_s; -typedef void rtext_render_t (uint32_t glyphid, int x, int y, void *data); +typedef void text_render_t (uint32_t glyphid, int x, int y, void *data); -typedef struct rshaper_s { +typedef struct shaper_s { struct font_s *rfont; hb_font_t *font; hb_buffer_t *buffer; - r_hb_featureset_t features; -} rshaper_t; + featureset_t features; +} shaper_t; extern hb_feature_t LigatureOff; extern hb_feature_t LigatureOn; @@ -76,11 +100,16 @@ extern hb_feature_t KerningOn; extern hb_feature_t CligOff; extern hb_feature_t CligOn; -rshaper_t *RText_NewShaper (struct font_s *font); -void RText_DeleteShaper (rshaper_t *shaper); -void RText_AddFeature (rshaper_t *shaper, hb_feature_t feature); -void RText_ShapeText (rshaper_t *shaper, rtext_t *text); -void RText_RenderText (rshaper_t *shaper, rtext_t *text, int x, int y, - rtext_render_t *render, void *data); +struct font_s; +struct passage_s; -#endif//__r_text_h +shaper_t *Text_NewShaper (struct font_s *font); +void Text_DeleteShaper (shaper_t *shaper); +void Text_AddFeature (shaper_t *shaper, hb_feature_t feature); +void Text_ShapeText (shaper_t *shaper, text_t *text); +void Text_RenderText (shaper_t *shaper, text_t *text, int x, int y, + text_render_t *render, void *data); +void Text_Init (void); +struct view_s Text_View (struct font_s *font, struct passage_s *passage); + +#endif//__QF_ui_text_h diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am index 0a973941f..95c6c8c8a 100644 --- a/libs/ui/Makemodule.am +++ b/libs/ui/Makemodule.am @@ -15,7 +15,8 @@ libs_ui_libQFgui_la_LDFLAGS= $(lib_ldflags) libs_ui_libQFgui_la_LIBADD= $(gui_deps) $(ui_deps) libs_ui_libQFgui_la_DEPENDENCIES= $(gui_deps) $(ui_deps) libs_ui_libQFgui_la_SOURCES= \ - libs/ui/font.c + libs/ui/font.c \ + libs/ui/text.c libs_ui_libQFui_la_LDFLAGS= $(lib_ldflags) libs_ui_libQFui_la_LIBADD= $(ui_deps) diff --git a/libs/ui/text.c b/libs/ui/text.c new file mode 100644 index 000000000..5b65a64ea --- /dev/null +++ b/libs/ui/text.c @@ -0,0 +1,282 @@ +/* + text.c + + Font text management + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/8/26 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include + +#include "QF/mathlib.h" +#include "QF/quakefs.h" +#include "QF/sys.h" + +#include "QF/ui/font.h" +#include "QF/ui/passage.h" +#include "QF/ui/text.h" +#include "QF/ui/view.h" + +#include "compat.h" + +static void +text_features_create (void *_features) +{ + featureset_t *features = _features; + *features = (featureset_t) DARRAY_STATIC_INIT (4); +} + +static const component_t text_components[text_type_count] = { + [text_href] = { + .size = sizeof (hierref_t), + .name = "href", + }, + [text_passage] = { + .size = sizeof (glyphset_t), + .name = "passage glyphs", + }, + [text_glyphs] = { + .size = sizeof (glyphref_t), + .name = "glyphs", + }, + [text_script] = { + .size = sizeof (script_component_t), + .name = "script", + }, + [text_font] = { + .size = sizeof (font_t *), + .name = "font", + }, + [text_features] = { + .size = sizeof (featureset_t), + .name = "features", + .create = text_features_create, + }, +}; +static ecs_registry_t *text_reg; + +void +Text_Init (void) +{ + text_reg = ECS_NewRegistry (); + ECS_RegisterComponents (text_reg, text_components, text_type_count); +} + +typedef struct glyphnode_s { + struct glyphnode_s *next; + uint32_t ent; + uint32_t count; + glyphobj_t *glyphs; + int mins[2]; + int maxs[2]; +} glyphnode_t; + +view_t +Text_View (font_t *font, passage_t *passage) +{ + hierarchy_t *h = passage->hierarchy; + psg_text_t *text_objects = h->components[passage_type_text_obj]; + glyphnode_t *glyph_nodes = 0; + glyphnode_t **head = &glyph_nodes; + + hb_font_t *fnt = hb_ft_font_create (font->face, 0); + hb_buffer_t *buffer = hb_buffer_create (); + hb_buffer_allocation_successful (buffer); + + /*XXX*/hb_script_t script = HB_SCRIPT_LATIN; + /*XXX*/hb_direction_t direction = HB_DIRECTION_LTR; + /*XXX*/hb_language_t language = hb_language_from_string ("en", 2); + hb_buffer_set_direction (buffer, direction); + hb_buffer_set_script (buffer, script); + hb_buffer_set_language (buffer, language); + + uint32_t glyph_count = 0; + + // passages have only the root, paragraphs, and text objects in their + // hierarchies + for (uint32_t i = 0; i < h->childCount[0]; i++) { + uint32_t paragraph = h->childIndex[0] + i; + for (uint32_t j = 0; j < h->childCount[paragraph]; j++) { + uint32_t textind = h->childIndex[0] + j; + psg_text_t *textobj = &text_objects[textind]; + const char *str = passage->text + textobj->text; + uint32_t len = textobj->size; + + hb_buffer_reset (buffer); + hb_buffer_add_utf8 (buffer, str, len, 0, len); + hb_shape (fnt, buffer, 0, 0); + + unsigned c; + __auto_type glyphInfo = hb_buffer_get_glyph_infos (buffer, &c); + __auto_type glyphPos = hb_buffer_get_glyph_positions (buffer, &c); + + *head = alloca (sizeof (glyphnode_t)); + **head = (glyphnode_t) { + .ent = h->ent[textind], + .count = c, + .glyphs = alloca (c * sizeof (glyphobj_t)), + }; + glyph_count += c; + + int x = 0, y = 0; + for (unsigned k = 0; k < c; k++) { + uint32_t glyphid = glyphInfo[k].codepoint; + vec2i_t bearing = font->glyph_bearings[glyphid]; + + int xp = x + glyphPos[k].x_offset / 64; + int yp = y + glyphPos[k].y_offset / 64; + int xa = glyphPos[k].x_advance / 64; + int ya = glyphPos[k].y_advance / 64; + xp += bearing[0]; + yp -= bearing[1]; + int xm = xp + font->glyph_rects[glyphid].width; + int ym = yp + font->glyph_rects[glyphid].height; + + (*head)->mins[0] = min ((*head)->mins[0], xp); + (*head)->mins[1] = min ((*head)->mins[1], yp); + (*head)->maxs[0] = max ((*head)->maxs[0], xm); + (*head)->maxs[1] = max ((*head)->maxs[1], ym); + + (*head)->glyphs[k] = (glyphobj_t) { + .glyphid = glyphid, + .x = xp + bearing[0], + .y = yp - bearing[1], + }; + x += xa; + y += ya; + } + + head = &(*head)->next; + } + } + view_t passage_view = View_New (text_reg, nullview); + glyphref_t passage_ref = {}; + glyphobj_t *glyphs = malloc (glyph_count * sizeof (glyphobj_t)); + glyphnode_t *g = glyph_nodes; + for (uint32_t i = 0; i < h->childCount[0]; i++) { + uint32_t paragraph = h->childIndex[0] + i; + view_t paraview = View_New (text_reg, passage_view); + glyphref_t pararef = { .start = passage_ref.count }; + for (uint32_t j = 0; j < h->childCount[paragraph]; j++, g = g->next) { + view_t textview = View_New (text_reg, paraview); + glyphref_t glyph_ref = { + .start = passage_ref.count, + .count = g->count, + }; + memcpy (glyphs + passage_ref.count, g->glyphs, + g->count * sizeof (glyphobj_t)); + Ent_SetComponent (textview.id, text_glyphs, text_reg, &glyph_ref); + View_SetPos (textview, g->mins[0], g->mins[1]); + View_SetLen (textview, g->maxs[0] - g->mins[0], + g->maxs[1] - g->mins[1]); + View_SetGravity (textview, grav_flow); + passage_ref.count += g->count; + } + pararef.count = passage_ref.count - pararef.start; + Ent_SetComponent (paraview.id, text_glyphs, text_reg, ¶ref); + } + Ent_SetComponent (passage_view.id, text_glyphs, text_reg, &passage_ref); + glyphset_t glyphset = { + .glyphs = glyphs, + .count = glyph_count, + }; + Ent_SetComponent (passage_view.id, text_passage, text_reg, &glyphset); + return passage_view; +} + +shaper_t * +Text_NewShaper (font_t *font) +{ + shaper_t *shaper = malloc (sizeof (shaper_t)); + shaper->rfont = font; + shaper->font = hb_ft_font_create (font->face, 0); + hb_ft_font_set_funcs (shaper->font); + shaper->buffer = hb_buffer_create (); + shaper->features = (featureset_t) DARRAY_STATIC_INIT (4); + + hb_buffer_allocation_successful (shaper->buffer); + return shaper; +} + +void +Text_DeleteShaper (shaper_t *shaper) +{ + hb_buffer_destroy (shaper->buffer); + hb_font_destroy (shaper->font); + DARRAY_CLEAR (&shaper->features); + free (shaper); +} + +void +Text_AddFeature (shaper_t *shaper, hb_feature_t feature) +{ + DARRAY_APPEND (&shaper->features, feature); +} + +void +Text_ShapeText (shaper_t *shaper, text_t *text) +{ + hb_buffer_reset (shaper->buffer); + hb_buffer_set_direction (shaper->buffer, text->direction); + hb_buffer_set_script (shaper->buffer, text->script); + const char *lang = text->language; + hb_buffer_set_language (shaper->buffer, + hb_language_from_string (lang, strlen (lang))); + size_t length = strlen (text->text); + hb_buffer_add_utf8 (shaper->buffer, text->text, length, 0, length); + + hb_shape (shaper->font, shaper->buffer, + shaper->features.a, shaper->features.size); +} + +void +Text_RenderText (shaper_t *shaper, text_t *text, int x, int y, + text_render_t *render, void *data) +{ + Text_ShapeText (shaper, text); + + unsigned count; + __auto_type glyphInfo = hb_buffer_get_glyph_infos (shaper->buffer, &count); + __auto_type glyphPos = hb_buffer_get_glyph_positions (shaper->buffer, + &count); + + font_t *font = shaper->rfont; + for (unsigned i = 0; i < count; i++) { + vec2i_t bearing = font->glyph_bearings[glyphInfo[i].codepoint]; + + int xp = x + glyphPos[i].x_offset / 64; + int yp = y + glyphPos[i].y_offset / 64; + int xa = glyphPos[i].x_advance / 64; + int ya = glyphPos[i].y_advance / 64; + + xp += bearing[0]; + yp -= bearing[1]; + render (glyphInfo[i].codepoint, xp, yp, data); + x += xa; + y += ya; + } +} diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 171225709..17e86d3fc 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -32,7 +32,6 @@ video_renderer_common_sources = \ libs/video/renderer/r_ent.c \ libs/video/renderer/r_iqm.c \ libs/video/renderer/r_sprite.c \ - libs/video/renderer/r_text.c \ libs/video/renderer/vid_common.c renderer_libs= \ diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 5fe26b23a..2e628c8ec 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -60,7 +60,6 @@ #include "QF/ui/view.h" #include "compat.h" -#include "r_text.h" #include "r_internal.h" #include "varrays.h" @@ -1076,7 +1075,7 @@ gl_Draw_AddFont (font_t *rfont) font->texid = GL_LoadTex ("", 0, &tex); return fontid; } - +#if 0 typedef struct { int fontid; byte color[4]; @@ -1106,10 +1105,11 @@ gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) qfglTexCoord2f (u * s, (v + h) * t); qfglVertex2f (x, y + h); } - +#endif void gl_Draw_FontString (int x, int y, int fontid, const char *str) { +#if 0 if (fontid < 0 || (unsigned) fontid > gl_fonts.size) { return; } @@ -1134,4 +1134,5 @@ gl_Draw_FontString (int x, int y, int fontid, const char *str) qfglEnd (); qfglColor4ubv (color_white); +#endif } diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index bc693c02a..cdbe743a7 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -55,7 +55,6 @@ #include "QF/GLSL/qf_textures.h" #include "QF/GLSL/qf_vid.h" -#include "r_text.h" #include "r_internal.h" typedef struct cachepic_s { @@ -930,7 +929,7 @@ glsl_Draw_AddFont (font_t *rfont) font->texid = GLSL_LoadTex ("", 1, &tex); return fontid; } - +#if 0 typedef struct { vrect_t *glyph_rects; dstring_t *batch; @@ -984,10 +983,11 @@ glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) QuatCopy (rgctx->color, verts[4].color); QuatCopy (rgctx->color, verts[5].color); } - +#endif void glsl_Draw_FontString (int x, int y, int fontid, const char *str) { +#if 0 if (fontid < 0 || (unsigned) fontid > glsl_fonts.size) { return; } @@ -1030,4 +1030,5 @@ glsl_Draw_FontString (int x, int y, int fontid, const char *str) glyph_queue->size = 0; qfeglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qfeglUseProgram (quake_2d.program); +#endif } diff --git a/libs/video/renderer/r_text.c b/libs/video/renderer/r_text.c deleted file mode 100644 index dc274d4be..000000000 --- a/libs/video/renderer/r_text.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - r_text.c - - Renderer font text management - - Copyright (C) 2022 Bill Currie - - Author: Bill Currie - Date: 2022/8/26 - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include - -#include "QF/quakefs.h" -#include "QF/sys.h" - -#include "QF/ui/font.h" - -#include "r_text.h" - -#include "compat.h" - -rshaper_t * -RText_NewShaper (font_t *font) -{ - rshaper_t *shaper = malloc (sizeof (rshaper_t)); - shaper->rfont = font; - shaper->font = hb_ft_font_create (font->face, 0); - hb_ft_font_set_funcs (shaper->font); - shaper->buffer = hb_buffer_create (); - shaper->features = (r_hb_featureset_t) DARRAY_STATIC_INIT (4); - - hb_buffer_allocation_successful (shaper->buffer); - return shaper; -} - -void -RText_DeleteShaper (rshaper_t *shaper) -{ - hb_buffer_destroy (shaper->buffer); - hb_font_destroy (shaper->font); - DARRAY_CLEAR (&shaper->features); - free (shaper); -} - -void -RText_AddFeature (rshaper_t *shaper, hb_feature_t feature) -{ - DARRAY_APPEND (&shaper->features, feature); -} - -void -RText_ShapeText (rshaper_t *shaper, rtext_t *text) -{ - hb_buffer_reset (shaper->buffer); - hb_buffer_set_direction (shaper->buffer, text->direction); - hb_buffer_set_script (shaper->buffer, text->script); - const char *lang = text->language; - hb_buffer_set_language (shaper->buffer, - hb_language_from_string (lang, strlen (lang))); - size_t length = strlen (text->text); - hb_buffer_add_utf8 (shaper->buffer, text->text, length, 0, length); - - hb_shape (shaper->font, shaper->buffer, - shaper->features.a, shaper->features.size); -} - -void -RText_RenderText (rshaper_t *shaper, rtext_t *text, int x, int y, - rtext_render_t *render, void *data) -{ - RText_ShapeText (shaper, text); - - unsigned count; - __auto_type glyphInfo = hb_buffer_get_glyph_infos (shaper->buffer, &count); - __auto_type glyphPos = hb_buffer_get_glyph_positions (shaper->buffer, - &count); - - font_t *font = shaper->rfont; - for (unsigned i = 0; i < count; i++) { - vec2i_t bearing = font->glyph_bearings[glyphInfo[i].codepoint]; - - int xp = x + glyphPos[i].x_offset / 64; - int yp = y + glyphPos[i].y_offset / 64; - int xa = glyphPos[i].x_advance / 64; - int ya = glyphPos[i].y_advance / 64; - - xp += bearing[0]; - yp -= bearing[1]; - render (glyphInfo[i].codepoint, xp, yp, data); - x += xa; - y += ya; - } -} diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index f86e0a5f7..17138ec98 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -43,7 +43,6 @@ #include "d_iface.h" #include "d_local.h" -#include "r_text.h" #include "r_internal.h" #include "vid_internal.h" @@ -1012,7 +1011,7 @@ Draw_AddFont (struct font_s *rfont) font->font = rfont; return fontid; } - +#if 0 typedef struct { vrect_t *glyph_rects; byte *bitmap; @@ -1046,10 +1045,11 @@ sw_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) dst += d_rowbytes; } } - +#endif void Draw_FontString (int x, int y, int fontid, const char *str) { +#if 0 if (fontid < 0 || (unsigned) fontid > sw_fonts.size) { return; } @@ -1072,4 +1072,5 @@ Draw_FontString (int x, int y, int fontid, const char *str) rshaper_t *shaper = RText_NewShaper (rfont); RText_RenderText (shaper, &text, x, y, sw_render_glyph, &rgctx); RText_DeleteShaper (shaper); +#endif } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index e3d4ae288..f0d2f6386 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -69,7 +69,6 @@ #include "QF/ui/font.h" #include "QF/ui/view.h" -#include "r_text.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -1516,7 +1515,7 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) return fontid; } - +#if 0 typedef struct { drawframe_t *dframe; descbatch_t *batch; @@ -1540,11 +1539,12 @@ vulkan_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) inst->position[0] = x; inst->position[1] = y; } - +#endif void Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, vulkan_ctx_t *ctx) { +#if 0 drawctx_t *dctx = ctx->draw_context; if (fontid < 0 || (unsigned) fontid > dctx->fonts.size) { return; @@ -1573,6 +1573,7 @@ Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, rshaper_t *shaper = RText_NewShaper (dctx->fonts.a[fontid].font); RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx); RText_DeleteShaper (shaper); +#endif } void From 5fd510ade496b8ff2bb8c62090d961de63d831b0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 Dec 2022 16:57:45 +0900 Subject: [PATCH 3289/3664] [ui] Add font to renderer when loading This causes some problems with linking if libQFgui is linked with libQFrenderer (which is necessary in the long run), but it seems everything gets away with it for now (which, tbh, I don't like). --- include/QF/ui/font.h | 1 + libs/ruamoko/rua_gui.c | 2 +- libs/ui/font.c | 3 +++ libs/ui/text.c | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/QF/ui/font.h b/include/QF/ui/font.h index ab526a8ab..6ea183d6d 100644 --- a/include/QF/ui/font.h +++ b/include/QF/ui/font.h @@ -51,6 +51,7 @@ typedef struct font_s { FT_Long num_glyphs; vrect_t *glyph_rects; vec2i_t *glyph_bearings; + uint32_t fontid; } font_t; void Font_Init (void); diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index b9ef12e2f..95a25be51 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -60,7 +60,7 @@ bi (Font_Load) QFile *font_file = QFS_FOpenFile (font_path); font_t *font = Font_Load (font_file, font_size); - R_INT (pr) = r_funcs->Draw_AddFont (font); + R_INT (pr) = font->fontid; } bi (Font_String) diff --git a/libs/ui/font.c b/libs/ui/font.c index 29e6704f0..afb293670 100644 --- a/libs/ui/font.c +++ b/libs/ui/font.c @@ -36,6 +36,8 @@ #include "QF/sys.h" #include "QF/math/bitop.h" +#include "QF/plugin/vid_render.h" + #include "QF/ui/font.h" #include "compat.h" @@ -131,6 +133,7 @@ Font_Load (QFile *font_file, int size) copy_glyph (rect, slot, font); } + font->fontid = r_funcs->Draw_AddFont (font); return font; } diff --git a/libs/ui/text.c b/libs/ui/text.c index 5b65a64ea..0177f38d4 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -165,6 +165,7 @@ Text_View (font_t *font, passage_t *passage) .glyphid = glyphid, .x = xp + bearing[0], .y = yp - bearing[1], + .fontid = font->fontid, }; x += xa; y += ya; From b93ab95c479b94dd9620309b1e71aa2edbffb097 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Dec 2022 15:18:47 +0900 Subject: [PATCH 3290/3664] [ruamoko] Add some builtins for passages and text Just some basic implementation so I can test shaping of passage text. --- include/QF/ui/text.h | 1 + libs/ruamoko/rua_gui.c | 225 +++++++++++++++++++++++++++---- libs/ui/text.c | 2 +- ruamoko/qwaq/builtins/graphics.c | 2 + 4 files changed, 205 insertions(+), 25 deletions(-) diff --git a/include/QF/ui/text.h b/include/QF/ui/text.h index b145a9d60..6bd7236e8 100644 --- a/include/QF/ui/text.h +++ b/include/QF/ui/text.h @@ -102,6 +102,7 @@ extern hb_feature_t CligOn; struct font_s; struct passage_s; +extern struct ecs_registry_s *text_reg; shaper_t *Text_NewShaper (struct font_s *font); void Text_DeleteShaper (shaper_t *shaper); diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index 95a25be51..55efdb2ce 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -42,50 +42,164 @@ #include "QF/render.h" #include "QF/ui/font.h" +#include "QF/ui/passage.h" +#include "QF/ui/text.h" #include "QF/ui/view.h" #include "QF/plugin/vid_render.h" #include "rua_internal.h" +typedef struct rua_passage_s { + struct rua_passage_s *next; + struct rua_passage_s **prev; + passage_t *passage; +} rua_passage_t; + +typedef struct rua_font_s { + struct rua_font_s *next; + struct rua_font_s **prev; + font_t *font; +} rua_font_t; + typedef struct { + progs_t *pr; + PR_RESMAP (rua_passage_t) passage_map; + rua_passage_t *passages; + PR_RESMAP (rua_font_t) font_map; + rua_font_t *fonts; } gui_resources_t; -#define bi(x) static void bi_##x (progs_t *pr, void *_res) - -bi (Font_Load) +static rua_passage_t * +passage_new (gui_resources_t *res) { - const char *font_path = P_GSTRING (pr, 0); - int font_size = P_INT (pr, 1); - - QFile *font_file = QFS_FOpenFile (font_path); - font_t *font = Font_Load (font_file, font_size); - R_INT (pr) = font->fontid; + return PR_RESNEW (res->passage_map); } -bi (Font_String) +static void +passage_free (gui_resources_t *res, rua_passage_t *passage) { - int x = P_INT (pr, 0); - int y = P_INT (pr, 1); - int fontid = P_INT (pr, 2); - const char *str = P_GSTRING (pr, 3); - r_funcs->Draw_FontString (x, y, fontid, str); + PR_RESFREE (res->passage_map, passage); } -#undef bi -#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} -#define p(type) PR_PARAM(type) -#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } -static builtin_t builtins[] = { - bi(Font_Load, 2, p(string), p(int)), - bi(Font_String, 4, p(int), p(int), p(int), p(string)), +static void +passage_reset (gui_resources_t *res) +{ + PR_RESRESET (res->passage_map); +} - {0} -}; +static inline rua_passage_t * +passage_get (gui_resources_t *res, int index) +{ + return PR_RESGET(res->passage_map, index); +} + +static inline int __attribute__((pure)) +passage_index (gui_resources_t *res, rua_passage_t *passage) +{ + return PR_RESINDEX(res->passage_map, passage); +} + +static int +alloc_passage (gui_resources_t *res, passage_t *passage) +{ + rua_passage_t *psg = passage_new (res); + + psg->next = res->passages; + psg->prev = &res->passages; + if (res->passages) { + res->passages->prev = &psg->next; + } + res->passages = psg; + psg->passage = passage; + return passage_index (res, psg); +} + +static rua_passage_t * +_get_passage (gui_resources_t *res, int handle, const char *func) +{ + rua_passage_t *psg = passage_get (res, handle); + if (!psg) { + PR_RunError (res->pr, "invalid passage handle passed to %s", func); + } + return psg; +} +#define get_passage(res, handle) _get_passage (res, handle, __FUNCTION__ + 3) + +static rua_font_t * +font_new (gui_resources_t *res) +{ + return PR_RESNEW (res->font_map); +} +/* +static void +font_free (gui_resources_t *res, rua_font_t *font) +{ + PR_RESFREE (res->font_map, font); +} +*/ +static void +font_reset (gui_resources_t *res) +{ + PR_RESRESET (res->font_map); +} + +static inline rua_font_t * +font_get (gui_resources_t *res, int index) +{ + return PR_RESGET(res->font_map, index); +} + +static inline int __attribute__((pure)) +font_index (gui_resources_t *res, rua_font_t *font) +{ + return PR_RESINDEX(res->font_map, font); +} + +static int +alloc_font (gui_resources_t *res, font_t *font) +{ + rua_font_t *psg = font_new (res); + + psg->next = res->fonts; + psg->prev = &res->fonts; + if (res->fonts) { + res->fonts->prev = &psg->next; + } + res->fonts = psg; + psg->font = font; + return font_index (res, psg); +} + +static rua_font_t * +_get_font (gui_resources_t *res, int handle, const char *func) +{ + rua_font_t *psg = font_get (res, handle); + if (!psg) { + PR_RunError (res->pr, "invalid font handle passed to %s", func); + } + return psg; +} +#define get_font(res, handle) _get_font (res, handle, __FUNCTION__ + 3) static void bi_gui_clear (progs_t *pr, void *_res) { + gui_resources_t *res = _res; + + rua_passage_t *psg; + for (psg = res->passages; psg; psg = psg->next) { + Passage_Delete (psg->passage); + } + res->passages = 0; + passage_reset (res); + + rua_font_t *font; + for (font = res->fonts; font; font = font->next) { + //FIXME can't unload fonts + } + res->fonts = 0; + font_reset (res); } static void @@ -95,10 +209,73 @@ bi_gui_destroy (progs_t *pr, void *_res) free (res); } +#define bi(x) static void bi_##x (progs_t *pr, void *_res) + +bi (Font_Load) +{ + gui_resources_t *res = _res; + const char *font_path = P_GSTRING (pr, 0); + int font_size = P_INT (pr, 1); + + QFile *font_file = QFS_FOpenFile (font_path); + font_t *font = Font_Load (font_file, font_size); + R_INT (pr) = alloc_font (res, font); +} + +bi (Passage_New) +{ + gui_resources_t *res = _res; + passage_t *passage = Passage_New (text_reg); + R_INT (pr) = alloc_passage (res, passage); +} + +bi (Passage_ParseText) +{ + gui_resources_t *res = _res; + int handle = P_INT (pr, 0); + rua_passage_t *psg = get_passage (res, handle); + const char *text = P_GSTRING (pr, 1); + Passage_ParseText (psg->passage, text); +} + +bi (Passage_Delete) +{ + gui_resources_t *res = _res; + int handle = P_INT (pr, 0); + rua_passage_t *psg = get_passage (res, handle); + Passage_Delete (psg->passage); + passage_free (res, psg); +} + +bi (Text_View) +{ + gui_resources_t *res = _res; + rua_font_t *font = get_font (res, P_INT (pr, 0)); + rua_passage_t *psg = get_passage (res, P_INT (pr, 1)); + view_t view = Text_View (font->font, psg->passage); + R_INT (pr) = view.id;//FIXME +} + +#undef bi +#define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} +#define p(type) PR_PARAM(type) +#define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } +static builtin_t builtins[] = { + bi(Font_Load, 2, p(string), p(int)), + bi(Passage_New, 0), + bi(Passage_ParseText, 2, p(ptr), p(string)), + bi(Passage_Delete, 1, p(ptr)), + + bi(Text_View, 2, p(ptr), p(string)), + + {0} +}; + void RUA_GUI_Init (progs_t *pr, int secure) { gui_resources_t *res = calloc (1, sizeof (gui_resources_t)); + res->pr = pr; PR_Resources_Register (pr, "Draw", res, bi_gui_clear, bi_gui_destroy); PR_RegisterBuiltins (pr, builtins, res); diff --git a/libs/ui/text.c b/libs/ui/text.c index 0177f38d4..0409da22b 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -77,7 +77,7 @@ static const component_t text_components[text_type_count] = { .create = text_features_create, }, }; -static ecs_registry_t *text_reg; +ecs_registry_t *text_reg; void Text_Init (void) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 018301639..86344170e 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -57,6 +57,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" #include "QF/ui/font.h" +#include "QF/ui/text.h" #include "rua_internal.h" @@ -345,6 +346,7 @@ BI_Graphics_Init (progs_t *pr) Mod_Init (); R_Init (); Font_Init (); + Text_Init (); R_Progs_Init (pr); RUA_Game_Init (pr, thread->rua_security); From c5af5728fef4d18867ec4b07f6e79725c695770f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Dec 2022 15:20:10 +0900 Subject: [PATCH 3291/3664] [ui] Fix some passage text shaping bugs Passage_Delete needs to check if the hierarchy is valid as no text may have been added, which results in a null pointer for the hierarchy. Text shaping needs to set language etc every time it resets the buffer. --- libs/ui/passage.c | 4 +++- libs/ui/text.c | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libs/ui/passage.c b/libs/ui/passage.c index 0157ee754..3d960111e 100644 --- a/libs/ui/passage.c +++ b/libs/ui/passage.c @@ -209,6 +209,8 @@ Passage_New (ecs_registry_t *reg) VISIBLE void Passage_Delete (passage_t *passage) { - Hierarchy_Delete (passage->hierarchy); + if (passage->hierarchy) { + Hierarchy_Delete (passage->hierarchy); + } free (passage); } diff --git a/libs/ui/text.c b/libs/ui/text.c index 0409da22b..fa485ab28 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -84,6 +84,7 @@ Text_Init (void) { text_reg = ECS_NewRegistry (); ECS_RegisterComponents (text_reg, text_components, text_type_count); + text_reg->href_comp = text_href; } typedef struct glyphnode_s { @@ -110,9 +111,6 @@ Text_View (font_t *font, passage_t *passage) /*XXX*/hb_script_t script = HB_SCRIPT_LATIN; /*XXX*/hb_direction_t direction = HB_DIRECTION_LTR; /*XXX*/hb_language_t language = hb_language_from_string ("en", 2); - hb_buffer_set_direction (buffer, direction); - hb_buffer_set_script (buffer, script); - hb_buffer_set_language (buffer, language); uint32_t glyph_count = 0; @@ -121,12 +119,15 @@ Text_View (font_t *font, passage_t *passage) for (uint32_t i = 0; i < h->childCount[0]; i++) { uint32_t paragraph = h->childIndex[0] + i; for (uint32_t j = 0; j < h->childCount[paragraph]; j++) { - uint32_t textind = h->childIndex[0] + j; + uint32_t textind = h->childIndex[paragraph] + j; psg_text_t *textobj = &text_objects[textind]; const char *str = passage->text + textobj->text; uint32_t len = textobj->size; hb_buffer_reset (buffer); + hb_buffer_set_direction (buffer, direction); + hb_buffer_set_script (buffer, script); + hb_buffer_set_language (buffer, language); hb_buffer_add_utf8 (buffer, str, len, 0, len); hb_shape (fnt, buffer, 0, 0); From d98eb8abc64193b053ba96a653ed62016fe95136 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 9 Dec 2022 17:42:50 +0900 Subject: [PATCH 3292/3664] [ui] Add support for setting text attributes Font cannot be overridden yet, but script attributes (language, script type, direction) and features can be set at all three levels in a passage. Attributes on the root level act as defaults for the paragraph and word levels, and paragraph attributes act as defaults for the word level. --- include/QF/ui/text.h | 48 +++++++----- libs/ui/text.c | 176 ++++++++++++++++++++++++++----------------- 2 files changed, 134 insertions(+), 90 deletions(-) diff --git a/include/QF/ui/text.h b/include/QF/ui/text.h index 6bd7236e8..1be136596 100644 --- a/include/QF/ui/text.h +++ b/include/QF/ui/text.h @@ -38,10 +38,22 @@ #include "QF/ecs/component.h" +// These can be converted to hb_direction_t simply by oring with 4 +typedef enum { + text_right_down, // left to right, then down horizontal text + text_left_down, // right to left, then down horizontal text + text_down_right, // top to bottom, then right vertical text + text_up_right, // bottom to top, then right vertical text + text_right_up, // left to right, then up horizontal text + text_left_up, // right to left, then up horizontal text + text_down_left, // top to bottom, then left vertical text + text_up_left, // bottom to top, then left vertical text +} text_dir_e; + typedef struct script_component_s { hb_language_t language; hb_script_t script; - hb_direction_t direction; + text_dir_e direction; } script_component_t; typedef struct glyphobj_s { @@ -70,11 +82,19 @@ typedef struct text_s { enum { // covers both view and passage text object hierarcies text_href, - // all the glyhphs in a passage - text_passage, + // all the glyphs in a passage. Always on only the root view of the passage. + text_passage_glyphs, + // glyphs for a single text object text_glyphs, + // text_script, text_font and text_features on the passage root object set + // the defaults for all text objects in the passage. The settings can be + // overridden at the paragraph level or individiual text object level by + // adding the appropriate component to that text object. + // script settings for the text object text_script, + // font id for the text object text_font, + // harfbuzz font features for the text object text_features, text_type_count @@ -82,17 +102,6 @@ enum { typedef struct featureset_s DARRAY_TYPE (hb_feature_t) featureset_t; -struct font_s; -struct rglyph_s; -typedef void text_render_t (uint32_t glyphid, int x, int y, void *data); - -typedef struct shaper_s { - struct font_s *rfont; - hb_font_t *font; - hb_buffer_t *buffer; - featureset_t features; -} shaper_t; - extern hb_feature_t LigatureOff; extern hb_feature_t LigatureOn; extern hb_feature_t KerningOff; @@ -104,13 +113,12 @@ struct font_s; struct passage_s; extern struct ecs_registry_s *text_reg; -shaper_t *Text_NewShaper (struct font_s *font); -void Text_DeleteShaper (shaper_t *shaper); -void Text_AddFeature (shaper_t *shaper, hb_feature_t feature); -void Text_ShapeText (shaper_t *shaper, text_t *text); -void Text_RenderText (shaper_t *shaper, text_t *text, int x, int y, - text_render_t *render, void *data); void Text_Init (void); struct view_s Text_View (struct font_s *font, struct passage_s *passage); +void Text_SetScript (int textid, const char *lang, hb_script_t script, + text_dir_e dir); +void Text_SetFont (int textid, struct font_s *font); +void Text_SetFeatures (int textid, featureset_t *features); +void Text_AddFeature (int textid, hb_feature_t feature); #endif//__QF_ui_text_h diff --git a/libs/ui/text.c b/libs/ui/text.c index fa485ab28..44300c0b5 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -50,12 +50,19 @@ text_features_create (void *_features) *features = (featureset_t) DARRAY_STATIC_INIT (4); } +static void +text_features_destroy (void *_features) +{ + featureset_t *features = _features; + DARRAY_CLEAR (features); +} + static const component_t text_components[text_type_count] = { [text_href] = { .size = sizeof (hierref_t), .name = "href", }, - [text_passage] = { + [text_passage_glyphs] = { .size = sizeof (glyphset_t), .name = "passage glyphs", }, @@ -75,6 +82,7 @@ static const component_t text_components[text_type_count] = { .size = sizeof (featureset_t), .name = "features", .create = text_features_create, + .destroy = text_features_destroy, }, }; ecs_registry_t *text_reg; @@ -96,6 +104,17 @@ typedef struct glyphnode_s { int maxs[2]; } glyphnode_t; +static view_resize_f text_flow_funcs[] = { + [text_right_down] = view_flow_right_down, + [text_left_down] = view_flow_left_down, + [text_down_right] = view_flow_down_right, + [text_up_right] = view_flow_up_right, + [text_right_up] = view_flow_right_up, + [text_left_up] = view_flow_left_up, + [text_down_left] = view_flow_down_left, + [text_up_left] = view_flow_up_left, +}; + view_t Text_View (font_t *font, passage_t *passage) { @@ -108,9 +127,11 @@ Text_View (font_t *font, passage_t *passage) hb_buffer_t *buffer = hb_buffer_create (); hb_buffer_allocation_successful (buffer); - /*XXX*/hb_script_t script = HB_SCRIPT_LATIN; - /*XXX*/hb_direction_t direction = HB_DIRECTION_LTR; - /*XXX*/hb_language_t language = hb_language_from_string ("en", 2); + hb_script_t psg_script = HB_SCRIPT_LATIN; + text_dir_e psg_direction = HB_DIRECTION_LTR; + hb_language_t psg_language = hb_language_from_string ("en", 2); + featureset_t passage_features = DARRAY_STATIC_INIT (0); + featureset_t *psg_features = &passage_features; uint32_t glyph_count = 0; @@ -118,18 +139,54 @@ Text_View (font_t *font, passage_t *passage) // hierarchies for (uint32_t i = 0; i < h->childCount[0]; i++) { uint32_t paragraph = h->childIndex[0] + i; + uint32_t para_ent = h->ent[paragraph]; + + hb_script_t para_script = psg_script; + text_dir_e para_direction = psg_direction; + hb_language_t para_language = psg_language; + featureset_t *para_features = psg_features;; + + if (Ent_HasComponent (para_ent, text_script, text_reg)) { + script_component_t *s = Ent_GetComponent (para_ent, text_script, + text_reg); + para_script = s->script; + para_language = s->language; + para_direction = s->direction; + } + if (Ent_HasComponent (para_ent, text_features, text_reg)) { + para_features = Ent_GetComponent (para_ent, text_features, + text_reg); + } for (uint32_t j = 0; j < h->childCount[paragraph]; j++) { uint32_t textind = h->childIndex[paragraph] + j; + uint32_t text_ent = h->ent[textind]; psg_text_t *textobj = &text_objects[textind]; const char *str = passage->text + textobj->text; uint32_t len = textobj->size; + hb_script_t txt_script = para_script; + text_dir_e txt_direction = para_direction; + hb_language_t txt_language = para_language; + featureset_t *txt_features = para_features;; + + if (Ent_HasComponent (text_ent, text_script, text_reg)) { + script_component_t *s = Ent_GetComponent (text_ent, text_script, + text_reg); + txt_script = s->script; + txt_language = s->language; + txt_direction = s->direction; + } + if (Ent_HasComponent (text_ent, text_features, text_reg)) { + txt_features = Ent_GetComponent (text_ent, text_features, + text_reg); + } + hb_buffer_reset (buffer); - hb_buffer_set_direction (buffer, direction); - hb_buffer_set_script (buffer, script); - hb_buffer_set_language (buffer, language); + hb_buffer_set_direction (buffer, txt_direction | HB_DIRECTION_LTR); + hb_buffer_set_script (buffer, txt_script); + hb_buffer_set_language (buffer, txt_language); hb_buffer_add_utf8 (buffer, str, len, 0, len); - hb_shape (fnt, buffer, 0, 0); + hb_shape (fnt, buffer, txt_features->a, txt_features->size); unsigned c; __auto_type glyphInfo = hb_buffer_get_glyph_infos (buffer, &c); @@ -179,6 +236,8 @@ Text_View (font_t *font, passage_t *passage) glyphref_t passage_ref = {}; glyphobj_t *glyphs = malloc (glyph_count * sizeof (glyphobj_t)); glyphnode_t *g = glyph_nodes; + // paragraph flow + int psg_vertical = !!(psg_direction & 2); for (uint32_t i = 0; i < h->childCount[0]; i++) { uint32_t paragraph = h->childIndex[0] + i; view_t paraview = View_New (text_reg, passage_view); @@ -200,85 +259,62 @@ Text_View (font_t *font, passage_t *passage) } pararef.count = passage_ref.count - pararef.start; Ent_SetComponent (paraview.id, text_glyphs, text_reg, ¶ref); + + uint32_t para_ent = h->ent[paragraph]; + text_dir_e para_direction = psg_direction; + if (Ent_HasComponent (para_ent, text_script, text_reg)) { + script_component_t *s = Ent_GetComponent (para_ent, text_script, + text_reg); + para_direction = s->direction; + } + View_SetOnResize (paraview, text_flow_funcs[para_direction]); + View_SetResize (paraview, psg_vertical, !psg_vertical); } Ent_SetComponent (passage_view.id, text_glyphs, text_reg, &passage_ref); glyphset_t glyphset = { .glyphs = glyphs, .count = glyph_count, }; - Ent_SetComponent (passage_view.id, text_passage, text_reg, &glyphset); + Ent_SetComponent (passage_view.id, text_passage_glyphs, text_reg, + &glyphset); return passage_view; } -shaper_t * -Text_NewShaper (font_t *font) +void +Text_SetScript (int textid, const char *lang, hb_script_t script, + text_dir_e dir) { - shaper_t *shaper = malloc (sizeof (shaper_t)); - shaper->rfont = font; - shaper->font = hb_ft_font_create (font->face, 0); - hb_ft_font_set_funcs (shaper->font); - shaper->buffer = hb_buffer_create (); - shaper->features = (featureset_t) DARRAY_STATIC_INIT (4); - - hb_buffer_allocation_successful (shaper->buffer); - return shaper; + script_component_t scr = { + .language = hb_language_from_string (lang, strlen (lang)), + .script = script, + .direction = dir, + }; + Ent_SetComponent (textid, text_script, text_reg, &scr); } void -Text_DeleteShaper (shaper_t *shaper) +Text_SetFont (int textid, font_t *font) { - hb_buffer_destroy (shaper->buffer); - hb_font_destroy (shaper->font); - DARRAY_CLEAR (&shaper->features); - free (shaper); + Ent_SetComponent (textid, text_font, text_reg, &font); } void -Text_AddFeature (shaper_t *shaper, hb_feature_t feature) +Text_SetFeatures (int textid, featureset_t *features) { - DARRAY_APPEND (&shaper->features, feature); -} - -void -Text_ShapeText (shaper_t *shaper, text_t *text) -{ - hb_buffer_reset (shaper->buffer); - hb_buffer_set_direction (shaper->buffer, text->direction); - hb_buffer_set_script (shaper->buffer, text->script); - const char *lang = text->language; - hb_buffer_set_language (shaper->buffer, - hb_language_from_string (lang, strlen (lang))); - size_t length = strlen (text->text); - hb_buffer_add_utf8 (shaper->buffer, text->text, length, 0, length); - - hb_shape (shaper->font, shaper->buffer, - shaper->features.a, shaper->features.size); -} - -void -Text_RenderText (shaper_t *shaper, text_t *text, int x, int y, - text_render_t *render, void *data) -{ - Text_ShapeText (shaper, text); - - unsigned count; - __auto_type glyphInfo = hb_buffer_get_glyph_infos (shaper->buffer, &count); - __auto_type glyphPos = hb_buffer_get_glyph_positions (shaper->buffer, - &count); - - font_t *font = shaper->rfont; - for (unsigned i = 0; i < count; i++) { - vec2i_t bearing = font->glyph_bearings[glyphInfo[i].codepoint]; - - int xp = x + glyphPos[i].x_offset / 64; - int yp = y + glyphPos[i].y_offset / 64; - int xa = glyphPos[i].x_advance / 64; - int ya = glyphPos[i].y_advance / 64; - - xp += bearing[0]; - yp -= bearing[1]; - render (glyphInfo[i].codepoint, xp, yp, data); - x += xa; - y += ya; + if (Ent_HasComponent (textid, text_features, text_reg)) { + Ent_RemoveComponent (textid, text_features, text_reg); } + featureset_t *f = Ent_SetComponent (textid, text_features, text_reg, 0); + DARRAY_RESIZE (f, features->size); + memcpy (f->a, features->a, features->size * sizeof (hb_feature_t)); +} + +void +Text_AddFeature (int textid, hb_feature_t feature) +{ + if (!Ent_HasComponent (textid, text_features, text_reg)) { + Ent_SetComponent (textid, text_features, text_reg, 0); + } + featureset_t *f = Ent_GetComponent (textid, text_features, text_reg); + DARRAY_APPEND (f, feature); } From 56680060876e8b9113eb14f2e94b68e1149924d6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Dec 2022 18:55:08 +0900 Subject: [PATCH 3293/3664] [renderer] Replace Draw_FontString with Draw_Glyph While Draw_Glyph does draw only one glyph at a time, it doesn't shape the text every time, so is a major win for performance (especially coupled with pre-shaped text). --- include/QF/GL/qf_draw.h | 2 +- include/QF/GLSL/qf_draw.h | 2 +- include/QF/Vulkan/qf_draw.h | 4 +- include/QF/draw.h | 2 +- include/QF/plugin/vid_render.h | 2 +- libs/video/renderer/gl/gl_draw.c | 51 +++++-------------- libs/video/renderer/glsl/glsl_draw.c | 64 +++++++++--------------- libs/video/renderer/sw/draw.c | 41 +++++++-------- libs/video/renderer/vid_render_gl.c | 2 +- libs/video/renderer/vid_render_glsl.c | 2 +- libs/video/renderer/vid_render_sw.c | 2 +- libs/video/renderer/vid_render_vulkan.c | 6 +-- libs/video/renderer/vulkan/vulkan_draw.c | 64 ++++++------------------ 13 files changed, 86 insertions(+), 158 deletions(-) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index 0188920e5..f9f9eb004 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -59,7 +59,7 @@ void gl_Draw_Picf (float x, float y, struct qpic_s *pic); void gl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); int gl_Draw_AddFont (struct font_s *font); -void gl_Draw_FontString (int x, int y, int fontid, const char *str); +void gl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c); void GL_Set2D (void); void GL_Set2DScaled (void); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index dffc0bee6..bc5def658 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -60,7 +60,7 @@ void glsl_Draw_Picf (float x, float y, struct qpic_s *pic); void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); int glsl_Draw_AddFont (struct font_s *font); -void glsl_Draw_FontString (int x, int y, int fontid, const char *str); +void glsl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c); void GLSL_Set2D (void); void GLSL_Set2DScaled (void); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index bb3081b67..b7cb493c2 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -82,8 +82,8 @@ void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height, struct vulkan_ctx_s *ctx); int Vulkan_Draw_AddFont (struct font_s *font, struct vulkan_ctx_s *ctx); -void Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, - struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c, + struct vulkan_ctx_s *ctx); void Vulkan_Set2D (struct vulkan_ctx_s *ctx); void Vulkan_Set2DScaled (struct vulkan_ctx_s *ctx); diff --git a/include/QF/draw.h b/include/QF/draw.h index f340183ab..780063064 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -269,7 +269,7 @@ void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int h struct font_s; int Draw_AddFont (struct font_s *font); -void Draw_FontString (int x, int y, int fontid, const char *str); +void Draw_Glyph (int x, int y, int fontid, int glyphid, int c); ///@} diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index d4ef5d744..cb9a96304 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -111,7 +111,7 @@ typedef struct vid_render_funcs_s { void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); int (*Draw_AddFont) (struct font_s *font); - void (*Draw_FontString) (int x, int y, int fontid, const char *str); + void (*Draw_Glyph) (int x, int y, int fontid, int glyphid, int c); struct psystem_s *(*ParticleSystem) (void); diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 2e628c8ec..7ed383cf6 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -1075,17 +1075,15 @@ gl_Draw_AddFont (font_t *rfont) font->texid = GL_LoadTex ("", 0, &tex); return fontid; } -#if 0 -typedef struct { - int fontid; - byte color[4]; -} glrgctx_t; -static void -gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) +void +gl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c) { - glrgctx_t *rgctx = _rgctx; - glfont_t *font = &gl_fonts.a[rgctx->fontid]; + if (fontid < 0 || (unsigned) fontid > gl_fonts.size) { + return; + } + + glfont_t *font = &gl_fonts.a[fontid]; font_t *rfont = font->font; vrect_t *rect = &rfont->glyph_rects[glyphid]; @@ -1095,7 +1093,12 @@ gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) float v = rect->y; float s = 1.0 / rfont->scrap.width; float t = 1.0 / rfont->scrap.height; - qfglColor4ubv (rgctx->color); + + qfglBindTexture (GL_TEXTURE_2D, gl_fonts.a[fontid].texid); + qfglBegin (GL_QUADS); + + byte color[4] = { VectorExpand (vid.palette + c * 3), 255 }; + qfglColor4ubv (color); qfglTexCoord2f (u * s, v * t); qfglVertex2f (x, y); qfglTexCoord2f ((u + w) * s, v * t); @@ -1104,35 +1107,7 @@ gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) qfglVertex2f (x + w, y + h); qfglTexCoord2f (u * s, (v + h) * t); qfglVertex2f (x, y + h); -} -#endif -void -gl_Draw_FontString (int x, int y, int fontid, const char *str) -{ -#if 0 - if (fontid < 0 || (unsigned) fontid > gl_fonts.size) { - return; - } - glrgctx_t rgctx = { - .fontid = fontid, - .color = { 127, 255, 153, 255 }, - }; - //FIXME ewwwwwww - rtext_t text = { - .text = str, - .language = "en", - .script = HB_SCRIPT_LATIN, - .direction = HB_DIRECTION_LTR, - }; - - qfglBindTexture (GL_TEXTURE_2D, gl_fonts.a[fontid].texid); - qfglBegin (GL_QUADS); - - rshaper_t *shaper = RText_NewShaper (gl_fonts.a[fontid].font); - RText_RenderText (shaper, &text, x, y, gl_render_glyph, &rgctx); - RText_DeleteShaper (shaper); qfglEnd (); qfglColor4ubv (color_white); -#endif } diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index cdbe743a7..428e9db9c 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -944,8 +944,21 @@ glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) glslrgctx_t *rgctx = _rgctx; vrect_t *rect = &rgctx->glyph_rects[glyphid]; dstring_t *batch = rgctx->batch; - int size = 6 * sizeof (drawvert_t); +} +#endif +void +glsl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c) +{ + if (fontid < 0 || (unsigned) fontid > glsl_fonts.size) { + return; + } + glslfont_t *font = &glsl_fonts.a[fontid]; + font_t *rfont = font->font; + vrect_t *rect = &rfont->glyph_rects[glyphid]; + + dstring_t *batch = glyph_queue; + int size = 6 * sizeof (drawvert_t); batch->size += size; dstring_adjust (batch); drawvert_t *verts = (drawvert_t *) (batch->str + batch->size - size); @@ -954,8 +967,8 @@ glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) float h = rect->height; float u = rect->x; float v = rect->y; - float s = 1.0 / rgctx->width; - float t = 1.0 / rgctx->height; + float s = 1.0 / rfont->scrap.width; + float t = 1.0 / rfont->scrap.height; verts[0] = (drawvert_t) { .xyst = { x, y, u * s, v * t }, @@ -976,42 +989,14 @@ glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) .xyst = { x, y + h, u * s, (v + h) * t }, }; - QuatCopy (rgctx->color, verts[0].color); - QuatCopy (rgctx->color, verts[1].color); - QuatCopy (rgctx->color, verts[2].color); - QuatCopy (rgctx->color, verts[3].color); - QuatCopy (rgctx->color, verts[4].color); - QuatCopy (rgctx->color, verts[5].color); -} -#endif -void -glsl_Draw_FontString (int x, int y, int fontid, const char *str) -{ -#if 0 - if (fontid < 0 || (unsigned) fontid > glsl_fonts.size) { - return; - } - glslfont_t *font = &glsl_fonts.a[fontid]; - font_t *rfont = font->font; - glslrgctx_t rgctx = { - .glyph_rects = rfont->glyph_rects, - .batch = glyph_queue, - .width = rfont->scrap.width, - .height = rfont->scrap.height, - }; - quat_t color = { 127, 255, 153, 255 }; - QuatScale (color, 1.0f/255.0f, rgctx.color); - //FIXME ewwwwwww - rtext_t text = { - .text = str, - .language = "en", - .script = HB_SCRIPT_LATIN, - .direction = HB_DIRECTION_LTR, - }; - - rshaper_t *shaper = RText_NewShaper (rfont); - RText_RenderText (shaper, &text, x, y, glsl_render_glyph, &rgctx); - RText_DeleteShaper (shaper); + quat_t color = { VectorExpand (vid.palette + c * 3), 255 }; + QuatScale (color, 1.0f/255.0f, color); + QuatCopy (color, verts[0].color); + QuatCopy (color, verts[1].color); + QuatCopy (color, verts[2].color); + QuatCopy (color, verts[3].color); + QuatCopy (color, verts[4].color); + QuatCopy (color, verts[5].color); qfeglUseProgram (alpha_2d.program); qfeglEnableVertexAttribArray (alpha_2d.vertex.location); @@ -1030,5 +1015,4 @@ glsl_Draw_FontString (int x, int y, int fontid, const char *str) glyph_queue->size = 0; qfeglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qfeglUseProgram (quake_2d.program); -#endif } diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 17138ec98..8a63715b2 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -1023,7 +1023,6 @@ static void sw_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) { swrgctx_t *rgctx = _rgctx; - vrect_t *rect = &rgctx->glyph_rects[glyphid]; float w = rect->width; float h = rect->height; @@ -1047,30 +1046,32 @@ sw_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) } #endif void -Draw_FontString (int x, int y, int fontid, const char *str) +Draw_Glyph (int x, int y, int fontid, int glyphid, int c) { -#if 0 if (fontid < 0 || (unsigned) fontid > sw_fonts.size) { return; } swfont_t *font = &sw_fonts.a[fontid]; font_t *rfont = font->font; - swrgctx_t rgctx = { - .glyph_rects = rfont->glyph_rects, - .bitmap = rfont->scrap_bitmap, - .width = rfont->scrap.width, - .color = 63, - }; - //FIXME ewwwwwww - rtext_t text = { - .text = str, - .language = "en", - .script = HB_SCRIPT_LATIN, - .direction = HB_DIRECTION_LTR, - }; + vrect_t *rect = &rfont->glyph_rects[glyphid]; + int width = rfont->scrap.width; - rshaper_t *shaper = RText_NewShaper (rfont); - RText_RenderText (shaper, &text, x, y, sw_render_glyph, &rgctx); - RText_DeleteShaper (shaper); -#endif + float w = rect->width; + float h = rect->height; + if (x < 0 || y < 0 || x + w > vid.width || y + h > vid.height) { + return; + } + int u = rect->x; + int v = rect->y; + byte *src = rfont->scrap_bitmap + v * width + u; + byte *dst = d_viewbuffer + y * d_rowbytes + x; + while (h-- > 0) { + for (int i = 0; i < w; i++) { + if (src[i] > 127) { + dst[i] = c; + } + } + src += width; + dst += d_rowbytes; + } } diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 6b4d50f12..6c13ad913 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -525,7 +525,7 @@ vid_render_funcs_t gl_vid_render_funcs = { .Draw_Picf = gl_Draw_Picf, .Draw_SubPic = gl_Draw_SubPic, .Draw_AddFont = gl_Draw_AddFont, - .Draw_FontString = gl_Draw_FontString, + .Draw_Glyph = gl_Draw_Glyph, .ParticleSystem = gl_ParticleSystem, .R_Init = gl_R_Init, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 3969817db..26375d469 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -469,7 +469,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { .Draw_Picf = glsl_Draw_Picf, .Draw_SubPic = glsl_Draw_SubPic, .Draw_AddFont = glsl_Draw_AddFont, - .Draw_FontString = glsl_Draw_FontString, + .Draw_Glyph = glsl_Draw_Glyph, .ParticleSystem = glsl_ParticleSystem, .R_Init = glsl_R_Init, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 5e4c7a31f..3ef972ae6 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -482,7 +482,7 @@ vid_render_funcs_t sw_vid_render_funcs = { .Draw_Picf = Draw_Picf, .Draw_SubPic = Draw_SubPic, .Draw_AddFont = Draw_AddFont, - .Draw_FontString = Draw_FontString, + .Draw_Glyph = Draw_Glyph, .ParticleSystem = sw_ParticleSystem, .R_Init = sw_R_Init, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 4f5bb0e7a..093e042ae 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -291,9 +291,9 @@ vulkan_Draw_AddFont (struct font_s *font) } static void -vulkan_Draw_FontString (int x, int y, int fontid, const char *str) +vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c) { - Vulkan_Draw_FontString (x, y, fontid, str, vulkan_ctx); + Vulkan_Draw_Glyph (x, y, fontid, glyphid, c, vulkan_ctx); } static void @@ -792,7 +792,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { .Draw_Picf = vulkan_Draw_Picf, .Draw_SubPic = vulkan_Draw_SubPic, .Draw_AddFont = vulkan_Draw_AddFont, - .Draw_FontString = vulkan_Draw_FontString, + .Draw_Glyph = vulkan_Draw_Glyph, .ParticleSystem = vulkan_ParticleSystem, .R_Init = vulkan_R_Init, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index f0d2f6386..d6bced784 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1515,65 +1515,33 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) return fontid; } -#if 0 -typedef struct { - drawframe_t *dframe; - descbatch_t *batch; - byte color[4]; -} rgctx_t; -static void -vulkan_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx) +void +Vulkan_Draw_Glyph (int x, int y, int fontid, int glyph, int c, + vulkan_ctx_t *ctx) { - rgctx_t *rgctx = _rgctx; - glyphqueue_t *queue = &rgctx->dframe->glyph_insts;; + drawctx_t *dctx = ctx->draw_context; + drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + glyphqueue_t *queue = &dframe->glyph_insts;; if (queue->count >= queue->size) { return; } - rgctx->batch->count++; - glyphinst_t *inst = &queue->glyphs[queue->count++]; - inst->index = glyphid; - QuatCopy (rgctx->color, inst->color); - inst->position[0] = x; - inst->position[1] = y; -} -#endif -void -Vulkan_Draw_FontString (int x, int y, int fontid, const char *str, - vulkan_ctx_t *ctx) -{ -#if 0 - drawctx_t *dctx = ctx->draw_context; - if (fontid < 0 || (unsigned) fontid > dctx->fonts.size) { - return; - } - drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - - rgctx_t rgctx = { - .dframe = dframe, - .color = { 127, 255, 153, 255 }, - }; - //FIXME ewwwwwww - rtext_t text = { - .text = str, - .language = "en", - .script = HB_SCRIPT_LATIN, - .direction = HB_DIRECTION_LTR, - }; - - rgctx.batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1]; - if (!dframe->glyph_batch.size || rgctx.batch->descid != fontid) { + descbatch_t *batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1]; + if (!dframe->glyph_batch.size || batch->descid != fontid) { DARRAY_APPEND(&dframe->glyph_batch, ((descbatch_t) { .descid = fontid })); - rgctx.batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1]; + batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1]; } - rshaper_t *shaper = RText_NewShaper (dctx->fonts.a[fontid].font); - RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx); - RText_DeleteShaper (shaper); -#endif + batch->count++; + glyphinst_t *inst = &queue->glyphs[queue->count++]; + inst->index = glyph; + VectorCopy (vid.palette + c * 3, inst->color); + inst->color[3] = 255; + inst->position[0] = x; + inst->position[1] = y; } void From c316b6b5d193bf27a2abce9e72386c2276846fd3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Dec 2022 18:57:51 +0900 Subject: [PATCH 3294/3664] [ruamoko] Wrap more text and view functions rua_gui.c is still a horrible mess of hacks, but it does the job for testing the text code. --- libs/ruamoko/rua_gui.c | 156 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 153 insertions(+), 3 deletions(-) diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index 55efdb2ce..3e161b4ff 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -115,7 +115,7 @@ alloc_passage (gui_resources_t *res, passage_t *passage) return passage_index (res, psg); } -static rua_passage_t * +static rua_passage_t * __attribute__((pure)) _get_passage (gui_resources_t *res, int handle, const char *func) { rua_passage_t *psg = passage_get (res, handle); @@ -171,7 +171,7 @@ alloc_font (gui_resources_t *res, font_t *font) return font_index (res, psg); } -static rua_font_t * +static rua_font_t * __attribute__((pure)) _get_font (gui_resources_t *res, int handle, const char *func) { rua_font_t *psg = font_get (res, handle); @@ -247,6 +247,26 @@ bi (Passage_Delete) passage_free (res, psg); } +bi (Passage_ChildCount) +{ + gui_resources_t *res = _res; + rua_passage_t *psg = get_passage (res, P_INT (pr, 0)); + + uint32_t par = P_UINT (pr, 1); + R_UINT (pr) = psg->passage->hierarchy->childCount[par]; +} + +bi (Passage_GetChild) +{ + gui_resources_t *res = _res; + rua_passage_t *psg = get_passage (res, P_INT (pr, 0)); + + hierarchy_t *h = psg->passage->hierarchy; + uint32_t par = P_UINT (pr, 1); + uint32_t index = P_UINT (pr, 2); + R_UINT (pr) = h->ent[h->childIndex[par] + index]; +} + bi (Text_View) { gui_resources_t *res = _res; @@ -256,6 +276,124 @@ bi (Text_View) R_INT (pr) = view.id;//FIXME } +bi (Text_SetScript) +{ + uint32_t textent = P_UINT (pr, 0); + const char *lang = P_GSTRING (pr, 1); + int script = P_INT (pr, 1); + int dir = P_INT (pr, 1); + Text_SetScript (textent, lang, script, dir); +} + +static void +draw_glyphs (view_pos_t *abs, glyphset_t *glyphset, glyphref_t *gref) +{ + uint32_t count = gref->count; + glyphobj_t *glyph = glyphset->glyphs + gref->start; + + while (count-- > 0) { + glyphobj_t *g = glyph++; + r_funcs->Draw_Glyph (abs->x + g->x, abs->y + g->y, + g->fontid, g->glyphid, 254); + } +} + +static void +draw_box (view_pos_t *abs, view_pos_t *len, uint32_t ind, int c) +{ + int x = abs[ind].x; + int y = abs[ind].y; + int w = len[ind].x; + int h = len[ind].y; + r_funcs->Draw_Line (x, y, x + w, y, c); + r_funcs->Draw_Line (x, y + h, x + w, y + h, c); + r_funcs->Draw_Line (x, y, x, y + h, c); + r_funcs->Draw_Line (x + w, y, x + w, y + h, c); +} + +bi (Text_Draw) +{ + ecs_pool_t *pool = &text_reg->comp_pools[text_passage_glyphs]; + uint32_t count = pool->count; + uint32_t *ent = pool->dense; + glyphset_t *glyphset = pool->data; + + + while (count-- > 0) { + view_t psg_view = { .id = *ent++, .reg = text_reg, + .comp = text_reg->href_comp}; + // first child is always a paragraph view, and all vies after the + // first paragraph's first child are all text views + view_t para_view = View_GetChild (psg_view, 0); + view_t text_view = View_GetChild (para_view, 0); + hierref_t *href = View_GetRef (text_view); + hierarchy_t *h = href->hierarchy; + view_pos_t *abs = h->components[view_abs]; + view_pos_t *len = h->components[view_len]; + + for (uint32_t i = href->index; i < h->num_objects; i++) { + glyphref_t *gref = Ent_GetComponent (h->ent[i], text_glyphs, + text_reg); + draw_glyphs (&abs[i], glyphset, gref); + + if (0) draw_box (abs, len, i, 253); + } + if (0) { + for (uint32_t i = 1; i < href->index; i++) { + draw_box (abs, len, i, 251); + } + } + } +} + +bi (View_ChildCount) +{ + uint32_t viewid = P_UINT (pr, 0); + view_t view = { .id = viewid, .reg = text_reg }; + R_UINT (pr) = View_ChildCount (view); +} + +bi (View_GetChild) +{ + uint32_t viewid = P_UINT (pr, 0); + uint32_t index = P_UINT (pr, 1); + view_t view = { .id = viewid, .reg = text_reg }; + R_UINT (pr) = View_GetChild (view, index).id; +} + +bi (View_SetPos) +{ + uint32_t viewid = P_UINT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + view_t view = { .id = viewid, .reg = text_reg }; + View_SetPos (view, x, y); +} + +bi (View_SetLen) +{ + uint32_t viewid = P_UINT (pr, 0); + int x = P_INT (pr, 1); + int y = P_INT (pr, 2); + view_t view = { .id = viewid, .reg = text_reg }; + View_SetLen (view, x, y); +} + +bi (View_GetLen) +{ + uint32_t viewid = P_UINT (pr, 0); + view_t view = { .id = viewid, .reg = text_reg }; + view_pos_t l = View_GetLen (view); + R_var (pr, ivec2) = (pr_ivec2_t) { l.x, l.y }; +} + +bi (View_UpdateHierarchy) +{ + uint32_t viewid = P_UINT (pr, 0); + view_t view = { .id = viewid, .reg = text_reg }; + View_UpdateHierarchy (view); +} + #undef bi #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) @@ -265,8 +403,20 @@ static builtin_t builtins[] = { bi(Passage_New, 0), bi(Passage_ParseText, 2, p(ptr), p(string)), bi(Passage_Delete, 1, p(ptr)), + bi(Passage_ChildCount, 2, p(ptr), p(uint)), + bi(Passage_GetChild, 3, p(ptr), p(uint), p(uint)), - bi(Text_View, 2, p(ptr), p(string)), + bi(Text_View, 2, p(ptr), p(int)), + bi(Text_SetScript, 4, p(uint), p(string), p(int), p (int)), + + bi(View_ChildCount, 1, p(uint)), + bi(View_GetChild, 2, p(uint), p(uint)), + bi(View_SetPos, 3, p(uint), p(int), p(int)), + bi(View_SetLen, 3, p(uint), p(int), p(int)), + bi(View_GetLen, 1, p(uint)), + bi(View_UpdateHierarchy,1, p(uint)), + + bi(Text_Draw, 0), {0} }; From 50d588567ba7469c6ad471c9347aec3b281f00b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Dec 2022 18:58:57 +0900 Subject: [PATCH 3295/3664] [ui] Fix a pile of errors in text shaping The main problem was the confusion about the coordinates within a single glyph, and thus the glyphs position within the view's box. With this, flowed text works fairly well except for some issues with spacing between lines (which I think is due to the flow code not having been tested with offset boxes). --- libs/ui/text.c | 47 ++++++++++++++++++++++++++++++++--------------- libs/ui/view.c | 1 + 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/libs/ui/text.c b/libs/ui/text.c index 44300c0b5..7a0587a29 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -128,7 +128,7 @@ Text_View (font_t *font, passage_t *passage) hb_buffer_allocation_successful (buffer); hb_script_t psg_script = HB_SCRIPT_LATIN; - text_dir_e psg_direction = HB_DIRECTION_LTR; + text_dir_e psg_direction = text_right_down; hb_language_t psg_language = hb_language_from_string ("en", 2); featureset_t passage_features = DARRAY_STATIC_INIT (0); featureset_t *psg_features = &passage_features; @@ -197,6 +197,8 @@ Text_View (font_t *font, passage_t *passage) .ent = h->ent[textind], .count = c, .glyphs = alloca (c * sizeof (glyphobj_t)), + .mins = { 0, 0 }, + .maxs = { INT32_MIN, INT32_MIN }, }; glyph_count += c; @@ -205,24 +207,30 @@ Text_View (font_t *font, passage_t *passage) uint32_t glyphid = glyphInfo[k].codepoint; vec2i_t bearing = font->glyph_bearings[glyphid]; - int xp = x + glyphPos[k].x_offset / 64; - int yp = y + glyphPos[k].y_offset / 64; + int xp = glyphPos[k].x_offset / 64; + int yp = glyphPos[k].y_offset / 64; int xa = glyphPos[k].x_advance / 64; int ya = glyphPos[k].y_advance / 64; xp += bearing[0]; - yp -= bearing[1]; + yp += bearing[1]; int xm = xp + font->glyph_rects[glyphid].width; - int ym = yp + font->glyph_rects[glyphid].height; + int ym = yp - font->glyph_rects[glyphid].height; - (*head)->mins[0] = min ((*head)->mins[0], xp); - (*head)->mins[1] = min ((*head)->mins[1], yp); - (*head)->maxs[0] = max ((*head)->maxs[0], xm); - (*head)->maxs[1] = max ((*head)->maxs[1], ym); + if (xm - xp == 0) { + xm = xa; + } + if (ym - yp == 0) { + ym = ya; + } + (*head)->mins[0] = min ((*head)->mins[0], xp + x); + (*head)->mins[1] = min ((*head)->mins[1], ym + y); + (*head)->maxs[0] = max ((*head)->maxs[0], xm + x); + (*head)->maxs[1] = max ((*head)->maxs[1], yp + y); (*head)->glyphs[k] = (glyphobj_t) { .glyphid = glyphid, - .x = xp + bearing[0], - .y = yp - bearing[1], + .x = x + xp, + .y = y - yp, .fontid = font->fontid, }; x += xa; @@ -248,10 +256,17 @@ Text_View (font_t *font, passage_t *passage) .start = passage_ref.count, .count = g->count, }; - memcpy (glyphs + passage_ref.count, g->glyphs, - g->count * sizeof (glyphobj_t)); + for (uint32_t k = 0; k < g->count; k++) { + glyphobj_t *go = g->glyphs + k; + glyphs[passage_ref.count + k] = (glyphobj_t) { + .glyphid = go->glyphid, + .x = go->x + g->mins[0], + .y = go->y + g->maxs[1], + .fontid = go->fontid, + }; + } Ent_SetComponent (textview.id, text_glyphs, text_reg, &glyph_ref); - View_SetPos (textview, g->mins[0], g->mins[1]); + View_SetPos (textview, g->mins[0], -g->mins[1]); View_SetLen (textview, g->maxs[0] - g->mins[0], g->maxs[1] - g->mins[1]); View_SetGravity (textview, grav_flow); @@ -268,7 +283,9 @@ Text_View (font_t *font, passage_t *passage) para_direction = s->direction; } View_SetOnResize (paraview, text_flow_funcs[para_direction]); - View_SetResize (paraview, psg_vertical, !psg_vertical); + View_SetResize (paraview, !psg_vertical, psg_vertical); + View_SetGravity (paraview, grav_northwest); + View_Control (paraview)->flow_size = 1; } Ent_SetComponent (passage_view.id, text_glyphs, text_reg, &passage_ref); glyphset_t glyphset = { diff --git a/libs/ui/view.c b/libs/ui/view.c index 5c71ec0fc..e61343340 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -244,6 +244,7 @@ View_UpdateHierarchy (view_t view) rel[i].y = pos[i].y; break; case grav_flow: + //rel is set by the flow functions break; } abs[i].x = abs[par].x + rel[i].x; From 6a9985c8aac17c2707dec5610e3e1a4aca726ff2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Dec 2022 19:02:40 +0900 Subject: [PATCH 3296/3664] [vulkan] Fix an uninitialized field Yay valgrind. Luckily, there was a very tiny probability for it causing problems, but 0 is better. --- libs/video/renderer/vulkan/vulkan_output.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index ec7a83470..c08aaad42 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -249,6 +249,7 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) for (size_t i = 0; i < frames; i++) { __auto_type oframe = &octx->frames.a[i]; + oframe->input = 0; oframe->set = sets->a[i]; QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); From 6fc2dcae20a07002a7ecbfc502a2bed60a5f5ed8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Dec 2022 21:53:00 +0900 Subject: [PATCH 3297/3664] [qfprogs] Dump hex for non-ascii chars More useful when dealing with non-quake text (especially broken utf-8 strings). --- tools/qfcc/source/dump_strings.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dump_strings.c b/tools/qfcc/source/dump_strings.c index df4ca1b04..e09fd36e0 100644 --- a/tools/qfcc/source/dump_strings.c +++ b/tools/qfcc/source/dump_strings.c @@ -46,7 +46,7 @@ dump_string_block (const char *strblock, size_t size) printf ("%x \"", 0); while ((size_t) (s - strblock) < size) { - char c = *s++; + byte c = *s++; switch (c) { case 0: fputs ("\"\n", stdout); @@ -69,7 +69,12 @@ dump_string_block (const char *strblock, size_t size) fputs ("\\\\", stdout); break; default: - fputc (sys_char_map[(unsigned char)c], stdout); + if (c < 32 || c > 126) { + printf ("\\x%02x", c); + } else { + fputc (c, stdout); + } + //fputc (sys_char_map[c], stdout); break; } } From 490217a1360ce00dd17ca938b6a89c5b499a0b7e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Dec 2022 21:53:45 +0900 Subject: [PATCH 3298/3664] [qfcc] Ensure non-unicode char string is terminated Once a unicode char (ie, > 127) was used, any ascii chars would get the tail of the last unicode char resulting in broken utf-8 streams. The resulting null glyph boxes were not very appealing. --- tools/qfcc/source/strpool.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c index 7d773a9d7..42d7ba6d6 100644 --- a/tools/qfcc/source/strpool.c +++ b/tools/qfcc/source/strpool.c @@ -411,6 +411,7 @@ make_string (char *token, char **end) unicount = 0; } else { s[0] = c; + s[1] = 0; } dstring_appendstr (str, s); } while (1); From 65214fb7f8b10503d2bbd5645dbf1055b4cc6252 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Dec 2022 22:07:54 +0900 Subject: [PATCH 3299/3664] [ui] Split flowed line separation The separation now uses height above (right of) the base line, and depth below (left of) the base line. This puts the text exactly where I want it, but there's still the problem of uneven line spacing caused by descenders and ascenders. However, I suspect that's more up to the text/font handling code to get the boxes right (maybe set spaces to have the right dimensions?). --- libs/ui/view.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/libs/ui/view.c b/libs/ui/view.c index e61343340..d04748410 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -294,7 +294,8 @@ typedef struct flowline_s { int first_child; int child_count; int cursor; - int height; + int height; // from baseline + int depth; // from baseline } flowline_t; #define NEXT_LINE(line, child_index) \ @@ -326,7 +327,8 @@ flow_right (view_t view, void (*set_rows) (view_t, flowline_t *)) if (pos[child].x || !cont[child].bol_suppress) { line->cursor += len[child].x; } - line->height = max (len[child].y, line->height); + line->height = max (len[child].y - pos[child].y, line->height); + line->depth = max (pos[child].y, line->depth); line->child_count++; } set_rows (view, &flowline); @@ -355,7 +357,8 @@ flow_left (view_t view, void (*set_rows) (view_t, flowline_t *)) line->cursor -= len[child].x; } pos[child].x = line->cursor; - line->height = max (len[child].y, line->height); + line->height = max (len[child].y - pos[child].y, line->height); + line->depth = max (pos[child].y, line->depth); line->child_count++; } set_rows (view, &flowline); @@ -382,7 +385,8 @@ flow_down (view_t view, void (*set_rows) (view_t, flowline_t *)) if (pos[child].y || !cont[child].bol_suppress) { line->cursor += len[child].y; } - line->height = max (len[child].x, line->height); + line->height = max (len[child].x - pos[child].x, line->height); + line->depth = max (pos[child].x, line->depth); line->child_count++; } set_rows (view, &flowline); @@ -411,7 +415,8 @@ flow_up (view_t view, void (*set_rows) (view_t, flowline_t *)) line->cursor -= len[child].y; } pos[child].y = line->cursor; - line->height = max (len[child].x, line->height); + line->height = max (len[child].x - pos[child].x, line->height); + line->depth = max (pos[child].x, line->depth); line->child_count++; } set_rows (view, &flowline); @@ -422,7 +427,7 @@ flow_view_height (view_pos_t *len, flowline_t *flowlines) { len->y = 0; for (flowline_t *line = flowlines; line; line = line->next) { - len->y += line->height; + len->y += line->height + line->depth; } } @@ -431,7 +436,7 @@ flow_view_width (view_pos_t *len, flowline_t *flowlines) { len->x = 0; for (flowline_t *line = flowlines; line; line = line->next) { - len->x += line->height; + len->x += line->height + line->depth; } } @@ -459,6 +464,7 @@ set_rows_down (view_t view, flowline_t *flowlines) rel[child].x = pos[child].x; rel[child].y = cursor + pos[child].y - len[child].y; } + cursor += line->depth; } } @@ -479,6 +485,7 @@ set_rows_up (view_t view, flowline_t *flowlines) int cursor = len[vind].y; for (flowline_t *line = flowlines; line; line = line->next) { + cursor -= line->depth; for (int i = 0; i < line->child_count; i++) { uint32_t child = line->first_child + i; @@ -506,6 +513,7 @@ set_columns_right (view_t view, flowline_t *flowlines) int cursor = 0; for (flowline_t *line = flowlines; line; line = line->next) { + cursor += line->depth; for (int i = 0; i < line->child_count; i++) { uint32_t child = line->first_child + i; @@ -540,6 +548,7 @@ set_columns_left (view_t view, flowline_t *flowlines) rel[child].x = cursor + pos[child].x; rel[child].y = pos[child].y; } + cursor -= line->depth; } } From b553c313fe52bca578ac693cf02dbf675ad8d441 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Dec 2022 16:46:58 +0900 Subject: [PATCH 3300/3664] [x11] Don't double-divide for window center I obviously need a better way to test legacy code because the fix for unsigned-int behavior with clang broke mouse warping when using XGrabPointer instead of XInput2's XIGrabEnter. --- libs/video/targets/in_x11.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 80e435188..4f665d650 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -836,8 +836,8 @@ event_motion (XEvent *event) if (!event->xmotion.send_event) { int center_x = viddef.width / 2; int center_y = viddef.height / 2; - unsigned dist_x = abs (center_x / 2 - event->xmotion.x); - unsigned dist_y = abs (center_y / 2 - event->xmotion.y); + unsigned dist_x = abs (center_x - event->xmotion.x); + unsigned dist_y = abs (center_y - event->xmotion.y); x11_mouse_axes[0].value = event->xmotion.x - x11_mouse.x; x11_mouse_axes[1].value = event->xmotion.y - x11_mouse.y; From 203e490be08b2a818725a33b09535c99e6104499 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Dec 2022 17:28:31 +0900 Subject: [PATCH 3301/3664] [x11] Fix a couple of missed XFixes related blocks Disabling XFixes but keeping XInput2 wouldn't compile. --- libs/video/targets/in_x11.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 4f665d650..aaaac8d31 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -1029,6 +1029,7 @@ xi_raw_button_resease (void *event) xi_raw_button (event, 0); } +#ifdef HAVE_XFIXES static void xi_barrier_hit (void *event) { @@ -1052,6 +1053,7 @@ static void xi_barrier_leave (void *event) { } +#endif static void event_generic (XEvent *event) @@ -1063,8 +1065,10 @@ event_generic (XEvent *event) [XI_RawMotion] = xi_raw_motion, [XI_RawButtonPress] = xi_raw_button_press, [XI_RawButtonRelease] = xi_raw_button_resease, +#ifdef HAVE_XFIXES [XI_BarrierHit] = xi_barrier_hit, [XI_BarrierLeave] = xi_barrier_leave, +#endif }; XGenericEventCookie *cookie = &event->xcookie; @@ -1438,6 +1442,7 @@ in_x11_check_xi2 (void) Sys_MaskPrintf (SYS_vid, "XI2 supported: version %d.%d, op: %d err: %d\n", major, minor, xi_opcode, error); +#ifdef HAVE_XFIXES if (!XQueryExtension (x_disp, "XFIXES", &xf_opcode, &event, &error)) { Sys_MaskPrintf (SYS_vid, "X fixes extenions not available.\n"); return 0; @@ -1451,6 +1456,7 @@ in_x11_check_xi2 (void) Sys_MaskPrintf (SYS_vid, "XFixes supported: version %d.%d, op: %d err: %d\n", major, minor, xf_opcode, error); +#endif return 1; } From cb45fe7034746dd1e9f9bf21289ae8d16ef77e5d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 11 Dec 2022 19:14:35 +0900 Subject: [PATCH 3302/3664] [x11] Warp the mouse when it touches a barrier It seems that the mouse escaping the barriers requires some combination of hitting two at once, and holding your mouth just right (something about sliding the mouse up and down one barrier near the other). However, sending the mouse back to the center of the screen when it touches a barrier makes such sliding impossible. This seems to fix #38 --- libs/video/targets/in_x11.c | 65 ++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index aaaac8d31..2b8d547e2 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -688,32 +688,6 @@ in_x11_send_focus_event (int gain) IE_Send_Event (&event); } -static void -event_focusout (XEvent *event) -{ - if (x_have_focus) { - x_have_focus = false; - in_x11_send_focus_event (0); - if (in_snd_block) { - S_BlockSound (); - CDAudio_Pause (); - } - X11_RestoreGamma (); - } -} - -static void -event_focusin (XEvent *event) -{ - in_x11_send_focus_event (1); - x_have_focus = true; - if (in_snd_block) { - S_UnblockSound (); - CDAudio_Resume (); - } - VID_UpdateGamma (); -} - static void center_pointer (void) { @@ -1044,9 +1018,7 @@ xi_barrier_hit (void *event) return; } - if (!x11_have_pointer || !input_grabbed) { - XIBarrierReleasePointer (x_disp, be.deviceid, be.barrier, be.eventid); - } + center_pointer (); } static void @@ -1157,6 +1129,41 @@ in_x11_setup_barriers (int xpos, int ypos, int xlen, int ylen) } #endif +static void +event_focusout (XEvent *event) +{ + if (x_have_focus) { + x_have_focus = false; +#ifdef HAVE_XFIXES + in_x11_remove_barriers (); +#endif + in_x11_send_focus_event (0); + if (in_snd_block) { + S_BlockSound (); + CDAudio_Pause (); + } + X11_RestoreGamma (); + } +} + +static void +event_focusin (XEvent *event) +{ + in_x11_send_focus_event (1); + x_have_focus = true; + if (in_snd_block) { + S_UnblockSound (); + CDAudio_Resume (); + } + if (input_grabbed) { +#ifdef HAVE_XFIXES + in_x11_setup_barriers (x11_aw.xpos, x11_aw.ypos, + x11_aw.xlen, x11_aw.ylen); +#endif + } + VID_UpdateGamma (); +} + static void in_x11_grab_input (void *data, int grab) { From bb677a1a7c0063b42b2aa80542c9a7075783df0b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 12 Dec 2022 00:20:20 +0900 Subject: [PATCH 3303/3664] [ecs] Move href_comp into hierarchy_t This means that the component id used for hierarchy references must be passed to Hierarchy_New and Hierarchy_Copy, but does all an entity to have more than one hierarchy, which is useful for canvases (hierarchies of views) in the 3d world (the canvas root would have a 3d hierarchy reference and a 2d (view) hierarchy reference). --- include/QF/ecs/component.h | 1 - include/QF/ecs/hierarchy.h | 5 +++-- include/QF/ui/passage.h | 3 ++- include/QF/ui/view.h | 2 +- libs/client/cl_screen.c | 16 ++++++++-------- libs/client/hud.c | 1 - libs/client/sbar.c | 2 +- libs/console/client.c | 17 ++++++++--------- libs/console/server.c | 5 ++--- libs/ecs/component.c | 1 - libs/ecs/hierarchy.c | 19 ++++++++++--------- libs/ecs/test/test-hierarchy.c | 3 +-- libs/ruamoko/rua_gui.c | 4 ++-- libs/scene/scene.c | 1 - libs/scene/transform.c | 2 +- libs/ui/passage.c | 10 ++++++---- libs/ui/test/test-flow-size.c | 5 ++--- libs/ui/test/test-flow.c | 5 ++--- libs/ui/test/test-passage.c | 3 +-- libs/ui/text.c | 7 +++---- libs/ui/view.c | 8 ++++---- qtv/source/sbar.c | 4 ++-- qw/source/cl_ngraph.c | 2 +- qw/source/sv_sbar.c | 6 +++--- 24 files changed, 63 insertions(+), 69 deletions(-) diff --git a/include/QF/ecs/component.h b/include/QF/ecs/component.h index b82440eba..58b5cc7da 100644 --- a/include/QF/ecs/component.h +++ b/include/QF/ecs/component.h @@ -73,7 +73,6 @@ typedef struct ecs_registry_s { const component_t *components; ecs_pool_t *comp_pools; uint32_t num_components; - uint32_t href_comp;//FIXME find a better way PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way } ecs_registry_t; diff --git a/include/QF/ecs/hierarchy.h b/include/QF/ecs/hierarchy.h index fa5f4ef8d..4e4ff0551 100644 --- a/include/QF/ecs/hierarchy.h +++ b/include/QF/ecs/hierarchy.h @@ -60,12 +60,13 @@ typedef struct hierarchy_s { uint32_t *parentIndex; const hierarchy_type_t *type; void **components; + uint32_t href_comp; } hierarchy_t; -hierarchy_t *Hierarchy_New (struct ecs_registry_s *reg, +hierarchy_t *Hierarchy_New (struct ecs_registry_s *reg, uint32_t href_comp, const hierarchy_type_t *type, int createRoot); void Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count); -hierarchy_t *Hierarchy_Copy (struct ecs_registry_s *reg, +hierarchy_t *Hierarchy_Copy (struct ecs_registry_s *reg, uint32_t href_comp, const hierarchy_t *src); void Hierarchy_Delete (hierarchy_t *hierarchy); diff --git a/include/QF/ui/passage.h b/include/QF/ui/passage.h index 060c09948..13ff097ed 100644 --- a/include/QF/ui/passage.h +++ b/include/QF/ui/passage.h @@ -52,11 +52,12 @@ typedef struct passage_s { const char *text; ///< Not owned by passage struct ecs_registry_s *reg; ///< Owning ECS registry + uint32_t href_comp; ///< Component for passage hierarcy reference struct hierarchy_s *hierarchy; ///< hierarchy of text objects } passage_t; void Passage_ParseText (passage_t *passage, const char *text); -passage_t *Passage_New (struct ecs_registry_s *reg); +passage_t *Passage_New (struct ecs_registry_s *reg, uint32_t href_comp); void Passage_Delete (passage_t *passage); int Passage_IsSpace (const char *text) __attribute__((pure)); diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index 8cc5e64ea..e2f977264 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -123,7 +123,7 @@ typedef void (*view_move_f) (view_t view, view_pos_t abs); #define VIEWINLINE GNU89INLINE inline -view_t View_New (ecs_registry_t *reg, view_t parent); +view_t View_New (ecs_registry_t *reg, uint32_t href_comp, view_t parent); VIEWINLINE void View_Delete (view_t view); void View_SetParent (view_t view, view_t parent); void View_UpdateHierarchy (view_t view); diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index 8fc17c78e..b73b61cac 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -171,7 +171,7 @@ CL_Init_Screen (void) HUD_Init (); - cl_screen_view = View_New (hud_registry, nullview); + cl_screen_view = View_New (hud_registry, hud_href, nullview); con_module->data->console->screen_view = &cl_screen_view; View_SetPos (cl_screen_view, 0, 0); @@ -180,7 +180,7 @@ CL_Init_Screen (void) View_SetVisible (cl_screen_view, 1); pic = r_funcs->Draw_PicFromWad ("ram"); - ram_view = View_New (hud_registry, cl_screen_view); + ram_view = View_New (hud_registry, hud_href, cl_screen_view); View_SetPos (ram_view, 32, 0); View_SetLen (ram_view, pic->width, pic->height); View_SetGravity (ram_view, grav_northwest); @@ -188,7 +188,7 @@ CL_Init_Screen (void) View_SetVisible (ram_view, 0); pic = r_funcs->Draw_PicFromWad ("turtle"); - turtle_view = View_New (hud_registry, cl_screen_view); + turtle_view = View_New (hud_registry, hud_href, cl_screen_view); View_SetPos (turtle_view, 32, 0); View_SetLen (turtle_view, pic->width, pic->height); View_SetGravity (turtle_view, grav_northwest); @@ -200,14 +200,14 @@ CL_Init_Screen (void) Cvar_Register (&scr_showturtle_cvar, 0, 0); pic = r_funcs->Draw_PicFromWad ("net"); - net_view = View_New (hud_registry, cl_screen_view); + net_view = View_New (hud_registry, hud_href, cl_screen_view); View_SetPos (net_view, 64, 0); View_SetLen (net_view, pic->width, pic->height); View_SetGravity (net_view, grav_northwest); Ent_SetComponent (net_view.id, hud_pic, net_view.reg, &pic); View_SetVisible (net_view, 0); - timegraph_view = View_New (hud_registry, cl_screen_view); + timegraph_view = View_New (hud_registry, hud_href, cl_screen_view); View_SetPos (timegraph_view, 0, 0); View_SetLen (timegraph_view, r_data->vid->width, 100); View_SetGravity (timegraph_view, grav_southwest); @@ -215,7 +215,7 @@ CL_Init_Screen (void) Ent_SetComponent (timegraph_view.id, hud_func, timegraph_view.reg, &rtg); View_SetVisible (timegraph_view, r_timegraph); - zgraph_view = View_New (hud_registry, cl_screen_view); + zgraph_view = View_New (hud_registry, hud_href, cl_screen_view); View_SetPos (zgraph_view, 0, 0); View_SetLen (zgraph_view, r_data->vid->width, 100); View_SetGravity (zgraph_view, grav_southwest); @@ -225,7 +225,7 @@ CL_Init_Screen (void) const char *name = "gfx/loading.lmp"; pic = r_funcs->Draw_CachePic (name, 1); - loading_view = View_New (hud_registry, cl_screen_view); + loading_view = View_New (hud_registry, hud_href, cl_screen_view); View_SetPos (loading_view, 0, -24); View_SetLen (loading_view, pic->width, pic->height); View_SetGravity (loading_view, grav_center); @@ -234,7 +234,7 @@ CL_Init_Screen (void) name = "gfx/pause.lmp"; pic = r_funcs->Draw_CachePic (name, 1); - pause_view = View_New (hud_registry, cl_screen_view); + pause_view = View_New (hud_registry, hud_href, cl_screen_view); View_SetPos (pause_view, 0, -24); View_SetLen (pause_view, pic->width, pic->height); View_SetGravity (pause_view, grav_center); diff --git a/libs/client/hud.c b/libs/client/hud.c index a08bc3040..3d0810979 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -266,7 +266,6 @@ HUD_Init (void) { hud_registry = ECS_NewRegistry (); ECS_RegisterComponents (hud_registry, hud_components, hud_comp_count); - hud_registry->href_comp = hud_href; } void diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 000757b01..95133ad3b 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -254,7 +254,7 @@ static draw_charbuffer_t *solo_name; static view_t sbar_view (int x, int y, int w, int h, grav_t gravity, view_t parent) { - view_t view = View_New (hud_registry, parent); + view_t view = View_New (hud_registry, hud_href, parent); View_SetPos (view, x, y); View_SetLen (view, w, h); View_SetGravity (view, gravity); diff --git a/libs/console/client.c b/libs/console/client.c index 5e1433927..e06a13fa4 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -1023,7 +1023,6 @@ C_Init (void) { client_reg = ECS_NewRegistry (); ECS_RegisterComponents (client_reg, client_components, client_comp_count); - client_reg->href_comp = client_href; #ifdef __QNXNTO__ setlocale (LC_ALL, "C-TRADITIONAL"); @@ -1044,14 +1043,14 @@ C_Init (void) con_debuglog = COM_CheckParm ("-condebug"); // The console will get resized, so assume initial size is 320x200 - screen_view = View_New (client_reg, nullview); - console_view = View_New (client_reg, screen_view); - buffer_view = View_New (client_reg, console_view); - command_view = View_New (client_reg, console_view); - download_view = View_New (client_reg, console_view); - notify_view = View_New (client_reg, screen_view); - say_view = View_New (client_reg, screen_view); - menu_view = View_New (client_reg, screen_view); + screen_view = View_New (client_reg, client_href, nullview); + console_view = View_New (client_reg, client_href, screen_view); + buffer_view = View_New (client_reg, client_href, console_view); + command_view = View_New (client_reg, client_href, console_view); + download_view = View_New (client_reg, client_href, console_view); + notify_view = View_New (client_reg, client_href, screen_view); + say_view = View_New (client_reg, client_href, screen_view); + menu_view = View_New (client_reg, client_href, screen_view); View_SetGravity (screen_view, grav_northwest); View_SetGravity (console_view, grav_northwest); diff --git a/libs/console/server.c b/libs/console/server.c index 523effdf4..81fd50377 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -616,7 +616,7 @@ create_window (view_t parent, int xpos, int ypos, int xlen, int ylen, grav_t grav, void *obj, int opts, void (*draw) (view_t), void (*setgeometry) (view_t)) { - view_t view = View_New (server_reg, parent); + view_t view = View_New (server_reg, server_href, parent); View_SetPos (view, xpos, ypos); View_SetLen (view, xlen, ylen); View_SetGravity (view, grav); @@ -679,11 +679,10 @@ init (void) server_reg = ECS_NewRegistry (); ECS_RegisterComponents (server_reg, server_components, server_comp_count); - server_reg->href_comp = server_href; get_size (&screen_x, &screen_y); - sv_view = View_New (server_reg, nullview); + sv_view = View_New (server_reg, server_href, nullview); View_SetPos (sv_view, 0, 0); View_SetLen (sv_view, screen_x, screen_y); View_SetGravity (sv_view, grav_northwest); diff --git a/libs/ecs/component.c b/libs/ecs/component.c index 24ec85294..dd8be1761 100644 --- a/libs/ecs/component.c +++ b/libs/ecs/component.c @@ -39,7 +39,6 @@ ECS_NewRegistry (void) { ecs_registry_t *reg = calloc (1, sizeof (ecs_registry_t)); reg->next = Ent_Index (nullent); - reg->href_comp = nullent; return reg; } diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 3cbaeec18..3418591c6 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -50,7 +50,7 @@ hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { ecs_registry_t *reg = hierarchy->reg; - uint32_t href = reg->href_comp; + uint32_t href = hierarchy->href_comp; for (size_t i = start; i < hierarchy->num_objects; i++) { if (ECS_EntValid (hierarchy->ent[i], reg)) { hierref_t *ref = Ent_GetComponent (hierarchy->ent[i], href, reg); @@ -160,7 +160,7 @@ hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstIndex, uint32_t srcIndex, uint32_t count) { ecs_registry_t *reg = dst->reg; - uint32_t href = reg->href_comp; + uint32_t href = dst->href_comp; Component_CopyElements (&ent_component, dst->ent, dstIndex, src->ent, srcIndex, count); @@ -362,11 +362,12 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index, } hierarchy_t * -Hierarchy_New (ecs_registry_t *reg, const hierarchy_type_t *type, - int createRoot) +Hierarchy_New (ecs_registry_t *reg, uint32_t href_comp, + const hierarchy_type_t *type, int createRoot) { hierarchy_t *hierarchy = PR_RESNEW (reg->hierarchies); hierarchy->reg = reg; + hierarchy->href_comp = href_comp; hierarchy->components = 0; hierarchy->type = type; @@ -402,17 +403,17 @@ Hierarchy_Delete (hierarchy_t *hierarchy) } hierarchy_t * -Hierarchy_Copy (ecs_registry_t *dstReg, const hierarchy_t *src) +Hierarchy_Copy (ecs_registry_t *dstReg, uint32_t href_comp, + const hierarchy_t *src) { - uint32_t href = dstReg->href_comp; - hierarchy_t *dst = Hierarchy_New (dstReg, src->type, 0); + hierarchy_t *dst = Hierarchy_New (dstReg, href_comp, src->type, 0); size_t count = src->num_objects; Hierarchy_Reserve (dst, count); for (size_t i = 0; i < count; i++) { dst->ent[i] = ECS_NewEntity (dstReg); - hierref_t *ref = Ent_AddComponent (dst->ent[i], href, dstReg); + hierref_t *ref = Ent_AddComponent (dst->ent[i], href_comp, dstReg); ref->hierarchy = dst; ref->index = i; } @@ -448,7 +449,7 @@ Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, r.index = 0; return r; } - dst = Hierarchy_New (src->reg, src->type, 0); + dst = Hierarchy_New (src->reg, src->href_comp, src->type, 0); } r.hierarchy = dst; r.index = hierarchy_insertHierarchy (dst, src, dstParent, &srcRoot); diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index 4ede04af2..c64b4dade 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -249,7 +249,7 @@ create_ent (uint32_t parent, const char *name) ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, 0, pref->index, 0); } else { - ref->hierarchy = Hierarchy_New (test_reg, 0, 1); + ref->hierarchy = Hierarchy_New (test_reg, test_href, 0, 1); ref->index = 0; } ref->hierarchy->ent[ref->index] = ent; @@ -886,7 +886,6 @@ main (void) { test_reg = ECS_NewRegistry (); ECS_RegisterComponents (test_reg, test_components, test_num_components); - test_reg->href_comp = test_href; if (test_single_transform ()) { return 1; } if (test_parent_child_init ()) { return 1; } diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index 3e161b4ff..4f5be5e45 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -225,7 +225,7 @@ bi (Font_Load) bi (Passage_New) { gui_resources_t *res = _res; - passage_t *passage = Passage_New (text_reg); + passage_t *passage = Passage_New (text_reg, text_href); R_INT (pr) = alloc_passage (res, passage); } @@ -321,7 +321,7 @@ bi (Text_Draw) while (count-- > 0) { view_t psg_view = { .id = *ent++, .reg = text_reg, - .comp = text_reg->href_comp}; + .comp = text_href}; // first child is always a paragraph view, and all vies after the // first paragraph's first child are all text views view_t para_view = View_GetChild (psg_view, 0); diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 86932ca15..9e6736e28 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -213,7 +213,6 @@ Scene_NewScene (void) scene->reg = ECS_NewRegistry (); ECS_RegisterComponents (scene->reg, scene_components, scene_num_components); - scene->reg->href_comp = scene_href; scene_resources_t *res = calloc (1, sizeof (scene_resources_t)); *(scene_resources_t **)&scene->resources = res; diff --git a/libs/scene/transform.c b/libs/scene/transform.c index f00d2d527..31ea16137 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -215,7 +215,7 @@ Transform_New (ecs_registry_t *reg, transform_t parent) ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, 0, pref->index, 0); } else { - ref->hierarchy = Hierarchy_New (reg, &transform_type, 1); + ref->hierarchy = Hierarchy_New (reg, scene_href, &transform_type, 1); ref->index = 0; } ref->hierarchy->ent[ref->index] = transform; diff --git a/libs/ui/passage.c b/libs/ui/passage.c index 3d960111e..d17d0bc0a 100644 --- a/libs/ui/passage.c +++ b/libs/ui/passage.c @@ -88,7 +88,7 @@ add_entity (hierarchy_t *h, uint32_t parent) { uint32_t i = Hierarchy_InsertHierarchy (h, 0, parent, 0); h->ent[i] = ECS_NewEntity (h->reg); - hierref_t *ref = Ent_AddComponent (h->ent[i], h->reg->href_comp, h->reg); + hierref_t *ref = Ent_AddComponent (h->ent[i], h->href_comp, h->reg); ref->hierarchy = h; ref->index = i; } @@ -129,7 +129,8 @@ Passage_ParseText (passage_t *passage, const char *text) } root_text.size = c - text; } - passage->hierarchy = Hierarchy_New (passage->reg, &passage_type, 0); + passage->hierarchy = Hierarchy_New (passage->reg, passage->href_comp, + &passage_type, 0); Hierarchy_Reserve (passage->hierarchy, 1 + num_paragraphs + num_text_objects); #if 0 @@ -189,7 +190,7 @@ Passage_ParseText (passage_t *passage, const char *text) for (uint32_t i = 0; i < h->num_objects; i++) { psg_text_t *to = &passage_obj[i]; uint32_t ent = h->ent[i]; - hierref_t *ref = Ent_GetComponent (ent, reg->href_comp, reg); + hierref_t *ref = Ent_GetComponent (ent, h->href_comp, reg); printf ("%3d %8x %3d %4d %4d '%.*s'\n", i, ent, ref->index, to->text, to->size, to->size, text + to->text); } @@ -197,11 +198,12 @@ Passage_ParseText (passage_t *passage, const char *text) } VISIBLE passage_t * -Passage_New (ecs_registry_t *reg) +Passage_New (ecs_registry_t *reg, uint32_t href_comp) { passage_t *passage = malloc (sizeof (passage_t)); passage->text = 0; passage->reg = reg; + passage->href_comp = href_comp; passage->hierarchy = 0; return passage; } diff --git a/libs/ui/test/test-flow-size.c b/libs/ui/test/test-flow-size.c index 31e322fb7..093b52536 100644 --- a/libs/ui/test/test-flow-size.c +++ b/libs/ui/test/test-flow-size.c @@ -223,7 +223,7 @@ print_view (view_t view) static int test_flow (testdata_t *child_views, int count, void (flow) (view_t, view_pos_t)) { - view_t flow_view = View_New (test_reg, nullview); + view_t flow_view = View_New (test_reg, test_href, nullview); View_SetPos (flow_view, 0, 0); View_SetLen (flow_view, 256, 256); View_SetGravity (flow_view, grav_northwest); @@ -232,7 +232,7 @@ test_flow (testdata_t *child_views, int count, void (flow) (view_t, view_pos_t)) for (int i = 0; i < count; i++) { testdata_t *td = &child_views[i]; - view_t child = View_New (test_reg, flow_view); + view_t child = View_New (test_reg, test_href, flow_view); View_SetPos (child, 0, 0); View_SetLen (child, td->xlen, td->ylen); View_SetGravity (child, grav_flow); @@ -280,7 +280,6 @@ main (void) test_reg = ECS_NewRegistry (); ECS_RegisterComponents (test_reg, test_components, 1); - test_reg->href_comp = test_href; if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { printf ("right-down failed\n"); diff --git a/libs/ui/test/test-flow.c b/libs/ui/test/test-flow.c index 831a35677..b5a4e8c08 100644 --- a/libs/ui/test/test-flow.c +++ b/libs/ui/test/test-flow.c @@ -224,7 +224,7 @@ static int test_flow (testdata_t *child_views, int count, void (*flow) (view_t, view_pos_t)) { - view_t flow_view = View_New (test_reg, nullview); + view_t flow_view = View_New (test_reg, test_href, nullview); View_SetPos (flow_view, 0, 0); View_SetLen (flow_view, 256, 256); View_SetGravity (flow_view, grav_northwest); @@ -232,7 +232,7 @@ test_flow (testdata_t *child_views, int count, for (int i = 0; i < count; i++) { testdata_t *td = &child_views[i]; - view_t child = View_New (test_reg, flow_view); + view_t child = View_New (test_reg, test_href, flow_view); View_SetPos (child, 0, 0); View_SetLen (child, td->xlen, td->ylen); View_SetGravity (child, grav_flow); @@ -280,7 +280,6 @@ main (void) test_reg = ECS_NewRegistry (); ECS_RegisterComponents (test_reg, test_components, 1); - test_reg->href_comp = test_href; if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { printf ("right-down failed\n"); diff --git a/libs/ui/test/test-passage.c b/libs/ui/test/test-passage.c index d6bbe8f57..f59acb82b 100644 --- a/libs/ui/test/test-passage.c +++ b/libs/ui/test/test-passage.c @@ -64,9 +64,8 @@ main (void) int ret = 0; ecs_registry_t *registry = ECS_NewRegistry (); ECS_RegisterComponents (registry, test_components, 1); - registry->href_comp = test_href; - passage_t *passage = Passage_New (registry); + passage_t *passage = Passage_New (registry, test_href); Passage_ParseText (passage, test_text); if (passage->hierarchy->childCount[0] != 3) { ret = 1; diff --git a/libs/ui/text.c b/libs/ui/text.c index 7a0587a29..c9b256988 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -92,7 +92,6 @@ Text_Init (void) { text_reg = ECS_NewRegistry (); ECS_RegisterComponents (text_reg, text_components, text_type_count); - text_reg->href_comp = text_href; } typedef struct glyphnode_s { @@ -240,7 +239,7 @@ Text_View (font_t *font, passage_t *passage) head = &(*head)->next; } } - view_t passage_view = View_New (text_reg, nullview); + view_t passage_view = View_New (text_reg, text_href, nullview); glyphref_t passage_ref = {}; glyphobj_t *glyphs = malloc (glyph_count * sizeof (glyphobj_t)); glyphnode_t *g = glyph_nodes; @@ -248,10 +247,10 @@ Text_View (font_t *font, passage_t *passage) int psg_vertical = !!(psg_direction & 2); for (uint32_t i = 0; i < h->childCount[0]; i++) { uint32_t paragraph = h->childIndex[0] + i; - view_t paraview = View_New (text_reg, passage_view); + view_t paraview = View_New (text_reg, text_href, passage_view); glyphref_t pararef = { .start = passage_ref.count }; for (uint32_t j = 0; j < h->childCount[paragraph]; j++, g = g->next) { - view_t textview = View_New (text_reg, paraview); + view_t textview = View_New (text_reg, text_href, paraview); glyphref_t glyph_ref = { .start = passage_ref.count, .count = g->count, diff --git a/libs/ui/view.c b/libs/ui/view.c index d04748410..61a62a9f9 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -136,10 +136,10 @@ static const hierarchy_type_t view_type = { }; view_t -View_New (ecs_registry_t *reg, view_t parent) +View_New (ecs_registry_t *reg, uint32_t href_comp, view_t parent) { uint32_t view = ECS_NewEntity (reg); - hierref_t *ref = Ent_AddComponent (view, reg->href_comp, reg); + hierref_t *ref = Ent_AddComponent (view, href_comp, reg); if (parent.reg && parent.id != nullent) { hierref_t *pref = View_GetRef (parent); @@ -147,11 +147,11 @@ View_New (ecs_registry_t *reg, view_t parent) ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, 0, pref->index, 0); } else { - ref->hierarchy = Hierarchy_New (reg, &view_type, 1); + ref->hierarchy = Hierarchy_New (reg, href_comp, &view_type, 1); ref->index = 0; } ref->hierarchy->ent[ref->index] = view; - return (view_t) { .reg = reg, .id = view, .comp = reg->href_comp }; + return (view_t) { .reg = reg, .id = view, .comp = href_comp }; } void diff --git a/qtv/source/sbar.c b/qtv/source/sbar.c index 4100f11bb..84529940a 100644 --- a/qtv/source/sbar.c +++ b/qtv/source/sbar.c @@ -88,14 +88,14 @@ qtv_sbar_init (void) sv_view_t sv_view = *(sv_view_t *) comp; sv_view.setgeometry = 0; - view = View_New (status.reg, status); + view = View_New (status.reg, status.comp, status); View_SetPos (view, 0, 0); View_SetLen (view, 8, 1); View_SetGravity (view, grav_northwest); sv_view.draw = draw_servers; Ent_SetComponent (view.id, server_view, view.reg, &sv_view); - view = View_New (status.reg, status); + view = View_New (status.reg, status.comp, status); View_SetPos (view, 8, 0); View_SetLen (view, 9, 1); View_SetGravity (view, grav_northwest); diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 9d1d562ff..801872984 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -156,7 +156,7 @@ CL_NetGraph (view_pos_t abs, view_pos_t len) void CL_NetGraph_Init (void) { - cl_netgraph_view = View_New (hud_registry, cl_screen_view); + cl_netgraph_view = View_New (hud_registry, hud_href, cl_screen_view); View_SetPos (cl_netgraph_view, 0, 64); View_SetLen (cl_netgraph_view, NET_TIMINGS + 16, cl_netgraph_height + 25); View_SetGravity (cl_netgraph_view, grav_southwest); diff --git a/qw/source/sv_sbar.c b/qw/source/sv_sbar.c index f63cd524d..45d1615e9 100644 --- a/qw/source/sv_sbar.c +++ b/qw/source/sv_sbar.c @@ -118,21 +118,21 @@ SV_Sbar_Init (void) sv_view_t sv_view = *(sv_view_t *) comp; sv_view.setgeometry = 0; - view = View_New (status.reg, status); + view = View_New (status.reg, status.comp, status); View_SetPos (view, 0, 0); View_SetLen (view, 11, 1); View_SetGravity (view, grav_northwest); sv_view.draw = draw_cpu; Ent_SetComponent (view.id, server_view, view.reg, &sv_view); - view = View_New (status.reg, status); + view = View_New (status.reg, status.comp, status); View_SetPos (view, 11, 0); View_SetLen (view, 8, 1); View_SetGravity (view, grav_northwest); sv_view.draw = draw_rec; Ent_SetComponent (view.id, server_view, view.reg, &sv_view); - view = View_New (status.reg, status); + view = View_New (status.reg, status.comp, status); View_SetPos (view, 19, 0); View_SetLen (view, 18, 1); View_SetGravity (view, grav_northwest); From 1a56376f98920cc3313a6763c664e2186a583739 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 12 Dec 2022 13:37:01 +0900 Subject: [PATCH 3304/3664] [scene,ui] Be more consistent with component enum names Actual registry component counts are *_comp_count while hierarchy type component counts are *_type_count. --- include/QF/scene/scene.h | 2 +- include/QF/ui/text.h | 2 +- libs/scene/scene.c | 4 ++-- libs/ui/text.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index 9792e4f2e..dd96576fc 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -56,7 +56,7 @@ enum scene_components { scene_sw_frame, // animation frame scene_sw_brush, // brush model data pointer - scene_num_components + scene_comp_count }; typedef struct scene_s { diff --git a/include/QF/ui/text.h b/include/QF/ui/text.h index 1be136596..b898527b4 100644 --- a/include/QF/ui/text.h +++ b/include/QF/ui/text.h @@ -97,7 +97,7 @@ enum { // harfbuzz font features for the text object text_features, - text_type_count + text_comp_count }; typedef struct featureset_s DARRAY_TYPE (hb_feature_t) featureset_t; diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 9e6736e28..7fe86f6ba 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -96,7 +96,7 @@ sw_null_brush (void *_brush) *brush = 0; } -static const component_t scene_components[] = { +static const component_t scene_components[scene_comp_count] = { [scene_href] = { .size = sizeof (hierref_t), .create = 0,//create_href, @@ -212,7 +212,7 @@ Scene_NewScene (void) scene_t *scene = calloc (1, sizeof (scene_t)); scene->reg = ECS_NewRegistry (); - ECS_RegisterComponents (scene->reg, scene_components, scene_num_components); + ECS_RegisterComponents (scene->reg, scene_components, scene_comp_count); scene_resources_t *res = calloc (1, sizeof (scene_resources_t)); *(scene_resources_t **)&scene->resources = res; diff --git a/libs/ui/text.c b/libs/ui/text.c index c9b256988..67a3e238b 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -57,7 +57,7 @@ text_features_destroy (void *_features) DARRAY_CLEAR (features); } -static const component_t text_components[text_type_count] = { +static const component_t text_components[text_comp_count] = { [text_href] = { .size = sizeof (hierref_t), .name = "href", @@ -91,7 +91,7 @@ void Text_Init (void) { text_reg = ECS_NewRegistry (); - ECS_RegisterComponents (text_reg, text_components, text_type_count); + ECS_RegisterComponents (text_reg, text_components, text_comp_count); } typedef struct glyphnode_s { From 3c4dccf801b919819397d4defa0b79e2c4619d70 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Dec 2022 13:36:51 +0900 Subject: [PATCH 3305/3664] [ecs] Organize headers and code There's now a main ecs.h file that includes the sub-system headers, removing the need to explicitly include several header files, but the sub-systems are a less cluttered. --- include/QF/Makemodule.am | 2 + include/QF/ecs.h | 95 ++++++++++++++++ include/QF/ecs/component.h | 120 +------------------- include/QF/ecs/entity.h | 128 +++++++++++++++++++++ include/QF/ecs/hierarchy.h | 2 +- include/QF/scene/transform.h | 4 +- include/QF/ui/text.h | 2 +- include/QF/ui/view.h | 3 +- include/scn_internal.h | 2 - libs/ecs/Makemodule.am | 2 + libs/ecs/component.c | 208 +---------------------------------- libs/ecs/ecs.c | 190 ++++++++++++++++++++++++++++++++ libs/ecs/entity.c | 77 +++++++++++++ libs/ecs/hierarchy.c | 5 +- libs/ui/passage.c | 2 +- 15 files changed, 509 insertions(+), 333 deletions(-) create mode 100644 include/QF/ecs.h create mode 100644 include/QF/ecs/entity.h create mode 100644 libs/ecs/ecs.c create mode 100644 libs/ecs/entity.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 4fa305366..07b2d956e 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -15,6 +15,7 @@ include_qf = \ include/QF/darray.h \ include/QF/dstring.h \ include/QF/draw.h \ + include/QF/ecs.h \ include/QF/fbsearch.h \ include/QF/gib.h \ include/QF/hash.h \ @@ -77,6 +78,7 @@ include_qf = \ include_qf_ecs = \ include/QF/ecs/component.h \ + include/QF/ecs/entity.h \ include/QF/ecs/hierarchy.h include_qf_gl = \ diff --git a/include/QF/ecs.h b/include/QF/ecs.h new file mode 100644 index 000000000..2958485ba --- /dev/null +++ b/include/QF/ecs.h @@ -0,0 +1,95 @@ +/* + ecs.h + + Entity Component System + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/10/07 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_ecs_h +#define __QF_ecs_h + +#include +#include + +#include "QF/qtypes.h" +#include "QF/progs.h"//FIXME for PR_RESMAP + +#include "QF/ecs/component.h" +#include "QF/ecs/hierarchy.h" + +/** \defgroup ecs Entity Component System + \ingroup utils +*/ +///@{ + +#define ENT_GROW 1024 +#define COMP_GROW 128 +#define ENT_IDBITS 20 +#define nullent (~0u) + +typedef struct ecs_pool_s { + uint32_t *sparse; // indexed by entity id, holds index to dense/data + uint32_t *dense; // holds entity id + void *data; // component data + uint32_t count; // number of components/dense entity ids + uint32_t max_count; // current capacity for components/entity ids +} ecs_pool_t; + +typedef struct ecs_registry_s { + uint32_t *entities; + uint32_t next; + uint32_t available; + uint32_t num_entities; + uint32_t max_entities; + const component_t *components; + ecs_pool_t *comp_pools; + uint32_t num_components; + PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way +} ecs_registry_t; + +ecs_registry_t *ECS_NewRegistry (void); +void ECS_DelRegistry (ecs_registry_t *registry); +void ECS_RegisterComponents (ecs_registry_t *registry, + const component_t *components, uint32_t count); + +#ifndef __compar_d_fn_t_defined +#define __compar_d_fn_t_defined +typedef int (*__compar_d_fn_t)(const void *, const void *, void *); +#endif +void ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, + __compar_d_fn_t cmp, void *arg); + +uint32_t ECS_NewEntity (ecs_registry_t *registry); +void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent); +void ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component); + +#undef ECSINLINE + +///@} + +#include "QF/ecs/entity.h" + +#endif//__QF_ecs_h diff --git a/include/QF/ecs/component.h b/include/QF/ecs/component.h index 58b5cc7da..302338d9f 100644 --- a/include/QF/ecs/component.h +++ b/include/QF/ecs/component.h @@ -1,7 +1,7 @@ /* component.h - Component management + ECS Component management Copyright (C) 2022 Bill Currie @@ -37,26 +37,11 @@ #include "QF/qtypes.h" #include "QF/progs.h"//FIXME for PR_RESMAP -#include "QF/ecs/hierarchy.h" - -/** \defgroup component Entity Component System +/** \defgroup ecs_component Entity Component System components \ingroup utils */ ///@{ -#define ENT_GROW 1024 -#define COMP_GROW 128 -#define ENT_IDBITS 20 -#define nullent (~0u) - -typedef struct ecs_pool_s { - uint32_t *sparse; // indexed by entity id, holds index to dense/data - uint32_t *dense; // holds entity id - void *data; // component data - uint32_t count; // number of components/dense entity ids - uint32_t max_count; // current capacity for components/entity ids -} ecs_pool_t; - typedef struct component_s { size_t size; void (*create) (void *); @@ -64,18 +49,6 @@ typedef struct component_s { const char *name; } component_t; -typedef struct ecs_registry_s { - uint32_t *entities; - uint32_t next; - uint32_t available; - uint32_t num_entities; - uint32_t max_entities; - const component_t *components; - ecs_pool_t *comp_pools; - uint32_t num_components; - PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way -} ecs_registry_t; - #define COMPINLINE GNU89INLINE inline COMPINLINE void Component_ResizeArray (const component_t *component, @@ -96,20 +69,9 @@ COMPINLINE void *Component_CreateElements (const component_t *component, COMPINLINE void Component_DestroyElements (const component_t *component, void *array, uint32_t index, uint32_t count); -COMPINLINE uint32_t Ent_Index (uint32_t id); -COMPINLINE uint32_t Ent_Generation (uint32_t id); -COMPINLINE uint32_t Ent_NextGen (uint32_t id); - -COMPINLINE int ECS_EntValid (uint32_t id, ecs_registry_t *reg); -COMPINLINE int Ent_HasComponent (uint32_t ent, uint32_t comp, - ecs_registry_t *reg); -COMPINLINE void *Ent_GetComponent (uint32_t ent, uint32_t comp, - ecs_registry_t *reg); -COMPINLINE void *Ent_SetComponent (uint32_t ent, uint32_t comp, - ecs_registry_t *registry, const void *data); #undef COMPINLINE -#ifndef IMPLEMENT_COMPONENT_Funcs +#ifndef IMPLEMENT_ECS_COMPONENT_Funcs #define COMPINLINE GNU89INLINE inline #else #define COMPINLINE VISIBLE @@ -181,81 +143,7 @@ Component_DestroyElements (const component_t *component, void *array, } } -COMPINLINE uint32_t -Ent_Index (uint32_t id) -{ - return id & ((1 << ENT_IDBITS) - 1); -} - -COMPINLINE uint32_t -Ent_Generation (uint32_t id) -{ - return id & ~((1 << ENT_IDBITS) - 1); -} - -COMPINLINE uint32_t -Ent_NextGen(uint32_t id) -{ - return id + (1 << ENT_IDBITS); -} - -COMPINLINE int -ECS_EntValid (uint32_t id, ecs_registry_t *reg) -{ - uint32_t ind = Ent_Index (id); - return ind < reg->num_entities && reg->entities[ind] == id; -} - -COMPINLINE int -Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) -{ - ecs_pool_t *pool = ®->comp_pools[comp]; - uint32_t ind = pool->sparse[Ent_Index (ent)]; - return ind < pool->count && pool->dense[ind] == ent; -} - -COMPINLINE void * -Ent_GetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) -{ - const component_t *component = ®->components[comp]; - uint32_t ind = reg->comp_pools[comp].sparse[Ent_Index (ent)]; - byte *data = reg->comp_pools[comp].data; - return data + ind * component->size; -} - -ecs_registry_t *ECS_NewRegistry (void); -void ECS_DelRegistry (ecs_registry_t *registry); -void ECS_RegisterComponents (ecs_registry_t *registry, - const component_t *components, uint32_t count); - -#ifndef __compar_d_fn_t_defined -#define __compar_d_fn_t_defined -typedef int (*__compar_d_fn_t)(const void *, const void *, void *); -#endif -void ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, - __compar_d_fn_t cmp, void *arg); - -uint32_t ECS_NewEntity (ecs_registry_t *registry); -void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent); -void ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component); - -void *Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry); -void Ent_RemoveComponent (uint32_t ent, uint32_t comp, - ecs_registry_t *registry); - -COMPINLINE void * -Ent_SetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry, - const void *data) -{ - void *dst = Ent_AddComponent (ent, comp, registry); - if (data) { - return Component_CopyElements (®istry->components[comp], - dst, 0, data, 0, 1); - } else { - return Component_CreateElements (®istry->components[comp], - dst, 0, 1); - } -} +#undef COMPINLINE ///@} diff --git a/include/QF/ecs/entity.h b/include/QF/ecs/entity.h new file mode 100644 index 000000000..c0f80c0f5 --- /dev/null +++ b/include/QF/ecs/entity.h @@ -0,0 +1,128 @@ +/* + entity.h + + ECS entity management + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/10/07 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_ecs_entity_h +#define __QF_ecs_entity_h + +/** \defgroup ecs_entity Entity Component System Entities + \ingroup ecs +*/ +///@{ + +#define ENT_IDBITS 20 +#define nullent (~0u) + +#define ENTINLINE GNU89INLINE inline + +ENTINLINE int ECS_EntValid (uint32_t id, ecs_registry_t *reg); + +ENTINLINE uint32_t Ent_Index (uint32_t id); +ENTINLINE uint32_t Ent_Generation (uint32_t id); +ENTINLINE uint32_t Ent_NextGen (uint32_t id); + +ENTINLINE int Ent_HasComponent (uint32_t ent, uint32_t comp, + ecs_registry_t *reg); +ENTINLINE void *Ent_GetComponent (uint32_t ent, uint32_t comp, + ecs_registry_t *reg); +ENTINLINE void *Ent_SetComponent (uint32_t ent, uint32_t comp, + ecs_registry_t *registry, const void *data); + +#undef ENTINLINE +#ifndef IMPLEMENT_ECS_ENTITY_Funcs +#define ENTINLINE GNU89INLINE inline +#else +#define ENTINLINE VISIBLE +#endif + +ENTINLINE uint32_t +Ent_Index (uint32_t id) +{ + return id & ((1 << ENT_IDBITS) - 1); +} + +ENTINLINE uint32_t +Ent_Generation (uint32_t id) +{ + return id & ~((1 << ENT_IDBITS) - 1); +} + +ENTINLINE uint32_t +Ent_NextGen(uint32_t id) +{ + return id + (1 << ENT_IDBITS); +} + +ENTINLINE int +ECS_EntValid (uint32_t id, ecs_registry_t *reg) +{ + uint32_t ind = Ent_Index (id); + return ind < reg->num_entities && reg->entities[ind] == id; +} + +ENTINLINE int +Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) +{ + ecs_pool_t *pool = ®->comp_pools[comp]; + uint32_t ind = pool->sparse[Ent_Index (ent)]; + return ind < pool->count && pool->dense[ind] == ent; +} + +ENTINLINE void * +Ent_GetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) +{ + const component_t *component = ®->components[comp]; + uint32_t ind = reg->comp_pools[comp].sparse[Ent_Index (ent)]; + byte *data = reg->comp_pools[comp].data; + return data + ind * component->size; +} + +void *Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry); +void Ent_RemoveComponent (uint32_t ent, uint32_t comp, + ecs_registry_t *registry); + +ENTINLINE void * +Ent_SetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry, + const void *data) +{ + void *dst = Ent_AddComponent (ent, comp, registry); + if (data) { + return Component_CopyElements (®istry->components[comp], + dst, 0, data, 0, 1); + } else { + return Component_CreateElements (®istry->components[comp], + dst, 0, 1); + } +} + +#undef ENTINLINE + +///@} + +#endif//__QF_ecs_entity_h diff --git a/include/QF/ecs/hierarchy.h b/include/QF/ecs/hierarchy.h index 4e4ff0551..d26e43a74 100644 --- a/include/QF/ecs/hierarchy.h +++ b/include/QF/ecs/hierarchy.h @@ -1,7 +1,7 @@ /* hierarchy.h - Hierarchy management + ECS Hierarchy management Copyright (C) 2021 Bill Currie diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index 943509590..46468e1d3 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -32,10 +32,8 @@ #define __QF_scene_transform_h #include "QF/darray.h" +#include "QF/ecs.h" #include "QF/qtypes.h" -#include "QF/ecs/component.h" -#include "QF/ecs/hierarchy.h" -#include "QF/ecs/hierarchy.h" #include "QF/simd/vec4f.h" #include "QF/simd/mat4f.h" diff --git a/include/QF/ui/text.h b/include/QF/ui/text.h index b898527b4..66ca22db1 100644 --- a/include/QF/ui/text.h +++ b/include/QF/ui/text.h @@ -36,7 +36,7 @@ #include "QF/darray.h" -#include "QF/ecs/component.h" +#include "QF/ecs.h" // These can be converted to hb_direction_t simply by oring with 4 typedef enum { diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index e2f977264..4562ba0ec 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -31,8 +31,7 @@ #ifndef __QF_ui_view_h #define __QF_ui_view_h -#include "QF/ecs/component.h" -#include "QF/ecs/hierarchy.h" +#include "QF/ecs.h" /** \defgroup console_view Console View Objects \ingroup console diff --git a/include/scn_internal.h b/include/scn_internal.h index 102ad794b..906bef517 100644 --- a/include/scn_internal.h +++ b/include/scn_internal.h @@ -1,8 +1,6 @@ #ifndef __scn_internal_h #define __scn_internal_h -#include "QF/ecs/hierarchy.h" - typedef struct scene_resources_s { } scene_resources_t; diff --git a/libs/ecs/Makemodule.am b/libs/ecs/Makemodule.am index b624d2062..ae9360bbc 100644 --- a/libs/ecs/Makemodule.am +++ b/libs/ecs/Makemodule.am @@ -9,4 +9,6 @@ libs_ecs_libQFecs_la_LIBADD= $(ecs_deps) libs_ecs_libQFecs_la_DEPENDENCIES= $(ecs_deps) libs_ecs_libQFecs_la_SOURCES= \ libs/ecs/component.c \ + libs/ecs/ecs.c \ + libs/ecs/entity.c \ libs/ecs/hierarchy.c diff --git a/libs/ecs/component.c b/libs/ecs/component.c index dd8be1761..c466f6b50 100644 --- a/libs/ecs/component.c +++ b/libs/ecs/component.c @@ -1,7 +1,7 @@ /* - component.c + compoent.c - Component handling + ECS Component management Copyright (C) 2022 Bill Currke @@ -28,205 +28,5 @@ # include "config.h" #endif -#include "QF/heapsort.h" -#include "QF/sys.h" - -#define IMPLEMENT_COMPONENT_Funcs -#include "QF/ecs/component.h" - -VISIBLE ecs_registry_t * -ECS_NewRegistry (void) -{ - ecs_registry_t *reg = calloc (1, sizeof (ecs_registry_t)); - reg->next = Ent_Index (nullent); - return reg; -} - -VISIBLE void -ECS_DelRegistry (ecs_registry_t *registry) -{ - free (registry->entities); - for (uint32_t i = 0; i < registry->num_components; i++) { - free (registry->comp_pools[i].sparse); - free (registry->comp_pools[i].dense); - free (registry->comp_pools[i].data); - } - free (registry->comp_pools); - free (registry); -} - -VISIBLE void -ECS_RegisterComponents (ecs_registry_t *registry, - const component_t *components, uint32_t count) -{ - registry->num_components = count; - registry->components = components; - registry->comp_pools = calloc (count, sizeof (ecs_pool_t)); - size_t size = registry->max_entities * sizeof (uint32_t); - for (uint32_t i = 0; i < registry->num_components; i++) { - registry->comp_pools[i].sparse = malloc (size); - memset (registry->comp_pools[i].sparse, nullent, size); - } -} - -typedef struct { - __compar_d_fn_t cmp; - void *arg; - ecs_pool_t *pool; - const component_t *comp; -} ecs_sort_t; - -static int -ecs_compare (const void *a, const void *b, void *arg) -{ - ecs_sort_t *sortctx = arg; - return sortctx->cmp (a, b, sortctx->arg); -} - -static void -swap_uint32 (uint32_t *a, uint32_t *b) -{ - uint32_t t = *a; - *a = *b; - *b = t; -} - -static void -ecs_swap (void *_a, void *_b, void *arg) -{ - ecs_sort_t *sortctx = arg; - size_t size = sortctx->comp->size; - ecs_pool_t *pool = sortctx->pool; - uint32_t *a = _a; - uint32_t *b = _b; - uint32_t a_ind = a - pool->dense; - uint32_t b_ind = b - pool->dense; - uint32_t a_ent_ind = Ent_Index (pool->dense[a_ind]); - uint32_t b_ent_ind = Ent_Index (pool->dense[b_ind]); - __auto_type a_data = (byte *) pool->data + a_ind * size; - __auto_type b_data = (byte *) pool->data + b_ind * size; - Component_SwapElements (sortctx->comp, a_data, b_data); - swap_uint32 (a, b); - swap_uint32 (&pool->sparse[a_ent_ind], &pool->sparse[b_ent_ind]); -} - -VISIBLE void -ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, - __compar_d_fn_t cmp, void *arg) -{ - if (component >= registry->num_components) { - Sys_Error ("ECS_SortComponentPool: invalid component: %u", component); - } - ecs_pool_t *pool = ®istry->comp_pools[component]; - if (!pool->count) { - return; - } - __auto_type comp = ®istry->components[component]; - ecs_sort_t sortctx = { .cmp = cmp, .arg = arg, .pool = pool, .comp = comp }; - heapsort_s (pool->dense, pool->count, sizeof (uint32_t), - ecs_compare, ecs_swap, &sortctx); -} - -VISIBLE void * -Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) -{ - ecs_pool_t *pool = ®istry->comp_pools[comp]; - uint32_t id = Ent_Index (ent); - uint32_t ind = pool->sparse[id]; - if (ind >= pool->count || pool->dense[ind] != ent) { - if (pool->count == pool->max_count) { - pool->max_count += COMP_GROW; - pool->dense = realloc (pool->dense, - pool->max_count * sizeof (uint32_t)); - Component_ResizeArray (®istry->components[comp], &pool->data, - pool->max_count); - } - uint32_t ind = pool->count++; - pool->sparse[id] = ind; - pool->dense[ind] = ent; - } - return Ent_GetComponent (ent, comp, registry); -} - -VISIBLE void -Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) -{ - uint32_t id = Ent_Index (ent); - ecs_pool_t *pool = ®istry->comp_pools[comp]; - uint32_t ind = pool->sparse[id]; - if (ind < pool->count && pool->dense[ind] == ent) { - uint32_t last = pool->count - 1; - Component_DestroyElements (®istry->components[comp], pool->data, - ind, 1); - if (last > ind) { - pool->sparse[Ent_Index (pool->dense[last])] = ind; - pool->dense[ind] = pool->dense[last]; - Component_MoveElements (®istry->components[comp], pool->data, - ind, last, 1); - } - pool->count--; - pool->sparse[id] = nullent; - } -} - -VISIBLE uint32_t -ECS_NewEntity (ecs_registry_t *registry) -{ - uint32_t ent; - if (registry->available) { - registry->available--; - uint32_t next = registry->next; - ent = next | Ent_Generation (registry->entities[next]); - registry->next = Ent_Index (registry->entities[next]); - registry->entities[next] = ent; - } else { - if (registry->num_entities == Ent_Index (nullent)) { - Sys_Error ("ECS_NewEntity: out of entities"); - } - if (registry->num_entities == registry->max_entities) { - registry->max_entities += ENT_GROW; - size_t size = registry->max_entities * sizeof (uint32_t); - registry->entities = realloc (registry->entities, size); - for (uint32_t i = 0; i < registry->num_components; i++) { - uint32_t *sparse = registry->comp_pools[i].sparse; - sparse = realloc (sparse, size); - memset (sparse + registry->max_entities - ENT_GROW, nullent, - ENT_GROW * sizeof (uint32_t)); - registry->comp_pools[i].sparse = sparse; - } - } - ent = registry->num_entities++; - // ent starts out with generation 0 - registry->entities[ent] = ent; - } - return ent; -} - -VISIBLE void -ECS_DelEntity (ecs_registry_t *registry, uint32_t ent) -{ - uint32_t next = registry->next | Ent_NextGen (Ent_Generation (ent)); - uint32_t id = Ent_Index (ent); - registry->entities[id] = next; - registry->next = id; - registry->available++; - - for (uint32_t i = 0; i < registry->num_components; i++) { - Ent_RemoveComponent (ent, i, registry); - } -} - -VISIBLE void -ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component) -{ - ecs_pool_t *pool = ®istry->comp_pools[component]; - const component_t *comp = ®istry->components[component]; - __auto_type destroy = comp->destroy; - if (destroy) { - byte *data = registry->comp_pools[component].data; - for (uint32_t i = 0; i < pool->count; i++) { - destroy (data + i * comp->size); - } - } - pool->count = 0; -} +#define IMPLEMENT_ECS_COMPONENT_Funcs +#include "QF/ecs.h" diff --git a/libs/ecs/ecs.c b/libs/ecs/ecs.c new file mode 100644 index 000000000..395fbdba1 --- /dev/null +++ b/libs/ecs/ecs.c @@ -0,0 +1,190 @@ +/* + ecs.c + + Entity Component System + + Copyright (C) 2022 Bill Currke + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/heapsort.h" +#include "QF/sys.h" + +#define IMPLEMENT_ECS_Funcs +#include "QF/ecs.h" + +VISIBLE ecs_registry_t * +ECS_NewRegistry (void) +{ + ecs_registry_t *reg = calloc (1, sizeof (ecs_registry_t)); + reg->next = Ent_Index (nullent); + return reg; +} + +VISIBLE void +ECS_DelRegistry (ecs_registry_t *registry) +{ + free (registry->entities); + for (uint32_t i = 0; i < registry->num_components; i++) { + free (registry->comp_pools[i].sparse); + free (registry->comp_pools[i].dense); + free (registry->comp_pools[i].data); + } + free (registry->comp_pools); + free (registry); +} + +VISIBLE void +ECS_RegisterComponents (ecs_registry_t *registry, + const component_t *components, uint32_t count) +{ + registry->num_components = count; + registry->components = components; + registry->comp_pools = calloc (count, sizeof (ecs_pool_t)); + size_t size = registry->max_entities * sizeof (uint32_t); + for (uint32_t i = 0; i < registry->num_components; i++) { + registry->comp_pools[i].sparse = malloc (size); + memset (registry->comp_pools[i].sparse, nullent, size); + } +} + +typedef struct { + __compar_d_fn_t cmp; + void *arg; + ecs_pool_t *pool; + const component_t *comp; +} ecs_sort_t; + +static int +ecs_compare (const void *a, const void *b, void *arg) +{ + ecs_sort_t *sortctx = arg; + return sortctx->cmp (a, b, sortctx->arg); +} + +static void +swap_uint32 (uint32_t *a, uint32_t *b) +{ + uint32_t t = *a; + *a = *b; + *b = t; +} + +static void +ecs_swap (void *_a, void *_b, void *arg) +{ + ecs_sort_t *sortctx = arg; + size_t size = sortctx->comp->size; + ecs_pool_t *pool = sortctx->pool; + uint32_t *a = _a; + uint32_t *b = _b; + uint32_t a_ind = a - pool->dense; + uint32_t b_ind = b - pool->dense; + uint32_t a_ent_ind = Ent_Index (pool->dense[a_ind]); + uint32_t b_ent_ind = Ent_Index (pool->dense[b_ind]); + __auto_type a_data = (byte *) pool->data + a_ind * size; + __auto_type b_data = (byte *) pool->data + b_ind * size; + Component_SwapElements (sortctx->comp, a_data, b_data); + swap_uint32 (a, b); + swap_uint32 (&pool->sparse[a_ent_ind], &pool->sparse[b_ent_ind]); +} + +VISIBLE void +ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, + __compar_d_fn_t cmp, void *arg) +{ + if (component >= registry->num_components) { + Sys_Error ("ECS_SortComponentPool: invalid component: %u", component); + } + ecs_pool_t *pool = ®istry->comp_pools[component]; + if (!pool->count) { + return; + } + __auto_type comp = ®istry->components[component]; + ecs_sort_t sortctx = { .cmp = cmp, .arg = arg, .pool = pool, .comp = comp }; + heapsort_s (pool->dense, pool->count, sizeof (uint32_t), + ecs_compare, ecs_swap, &sortctx); +} + +VISIBLE uint32_t +ECS_NewEntity (ecs_registry_t *registry) +{ + uint32_t ent; + if (registry->available) { + registry->available--; + uint32_t next = registry->next; + ent = next | Ent_Generation (registry->entities[next]); + registry->next = Ent_Index (registry->entities[next]); + registry->entities[next] = ent; + } else { + if (registry->num_entities == Ent_Index (nullent)) { + Sys_Error ("ECS_NewEntity: out of entities"); + } + if (registry->num_entities == registry->max_entities) { + registry->max_entities += ENT_GROW; + size_t size = registry->max_entities * sizeof (uint32_t); + registry->entities = realloc (registry->entities, size); + for (uint32_t i = 0; i < registry->num_components; i++) { + uint32_t *sparse = registry->comp_pools[i].sparse; + sparse = realloc (sparse, size); + memset (sparse + registry->max_entities - ENT_GROW, nullent, + ENT_GROW * sizeof (uint32_t)); + registry->comp_pools[i].sparse = sparse; + } + } + ent = registry->num_entities++; + // ent starts out with generation 0 + registry->entities[ent] = ent; + } + return ent; +} + +VISIBLE void +ECS_DelEntity (ecs_registry_t *registry, uint32_t ent) +{ + uint32_t next = registry->next | Ent_NextGen (Ent_Generation (ent)); + uint32_t id = Ent_Index (ent); + registry->entities[id] = next; + registry->next = id; + registry->available++; + + for (uint32_t i = 0; i < registry->num_components; i++) { + Ent_RemoveComponent (ent, i, registry); + } +} + +VISIBLE void +ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component) +{ + ecs_pool_t *pool = ®istry->comp_pools[component]; + const component_t *comp = ®istry->components[component]; + __auto_type destroy = comp->destroy; + if (destroy) { + byte *data = registry->comp_pools[component].data; + for (uint32_t i = 0; i < pool->count; i++) { + destroy (data + i * comp->size); + } + } + pool->count = 0; +} diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c new file mode 100644 index 000000000..ef0441636 --- /dev/null +++ b/libs/ecs/entity.c @@ -0,0 +1,77 @@ +/* + entity.c + + ECS entity management + + Copyright (C) 2022 Bill Currke + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/heapsort.h" +#include "QF/sys.h" + +#define IMPLEMENT_ECS_ENTITY_Funcs +#include "QF/ecs.h" + +VISIBLE void * +Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) +{ + ecs_pool_t *pool = ®istry->comp_pools[comp]; + uint32_t id = Ent_Index (ent); + uint32_t ind = pool->sparse[id]; + if (ind >= pool->count || pool->dense[ind] != ent) { + if (pool->count == pool->max_count) { + pool->max_count += COMP_GROW; + pool->dense = realloc (pool->dense, + pool->max_count * sizeof (uint32_t)); + Component_ResizeArray (®istry->components[comp], &pool->data, + pool->max_count); + } + uint32_t ind = pool->count++; + pool->sparse[id] = ind; + pool->dense[ind] = ent; + } + return Ent_GetComponent (ent, comp, registry); +} + +VISIBLE void +Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) +{ + uint32_t id = Ent_Index (ent); + ecs_pool_t *pool = ®istry->comp_pools[comp]; + uint32_t ind = pool->sparse[id]; + if (ind < pool->count && pool->dense[ind] == ent) { + uint32_t last = pool->count - 1; + Component_DestroyElements (®istry->components[comp], pool->data, + ind, 1); + if (last > ind) { + pool->sparse[Ent_Index (pool->dense[last])] = ind; + pool->dense[ind] = pool->dense[last]; + Component_MoveElements (®istry->components[comp], pool->data, + ind, last, 1); + } + pool->count--; + pool->sparse[id] = nullent; + } +} diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 3418591c6..19b8079fc 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -1,7 +1,7 @@ /* hierarchy.c - General hierarchy handling + ECS hierarchy handling Copyright (C) 2021 Bill Currke @@ -37,8 +37,7 @@ #include "QF/sys.h" -#include "QF/ecs/component.h" -#include "QF/ecs/hierarchy.h" +#include "QF/ecs.h" static component_t ent_component = { .size = sizeof (uint32_t) }; static component_t childCount_component = { .size = sizeof (uint32_t) }; diff --git a/libs/ui/passage.c b/libs/ui/passage.c index d17d0bc0a..163f7de2b 100644 --- a/libs/ui/passage.c +++ b/libs/ui/passage.c @@ -39,7 +39,7 @@ #include "QF/qtypes.h" #include "QF/sys.h" -#include "QF/ecs/component.h" +#include "QF/ecs.h" #include "QF/ui/passage.h" #include "QF/ui/view.h" From b230fe18ce410280f86dbffcb18e2b9067b487f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Dec 2022 22:58:44 +0900 Subject: [PATCH 3306/3664] [ecs] Split component registration from pool creation While this does require an extra call after registering components, it allows for multiple component sets (ie, sub-systems) to be registered before the component pools are created. The base id for the registered component set is returned so it can be passed to the subsystem as needed. --- include/QF/ecs.h | 13 +++++++++---- include/QF/ecs/entity.h | 6 +++--- include/QF/scene/scene.h | 3 +++ include/r_internal.h | 2 +- libs/client/hud.c | 1 + libs/console/client.c | 1 + libs/console/server.c | 1 + libs/ecs/ecs.c | 30 ++++++++++++++++++++---------- libs/ecs/entity.c | 6 +++--- libs/ecs/test/test-components.c | 6 ++++-- libs/ecs/test/test-hierarchy.c | 4 ++-- libs/ecs/test/test-registry.c | 2 +- libs/scene/scene.c | 1 + libs/ui/test/test-flow-size.c | 1 + libs/ui/test/test-flow.c | 1 + libs/ui/test/test-passage.c | 1 + libs/ui/text.c | 1 + 17 files changed, 54 insertions(+), 26 deletions(-) diff --git a/include/QF/ecs.h b/include/QF/ecs.h index 2958485ba..bf9e26748 100644 --- a/include/QF/ecs.h +++ b/include/QF/ecs.h @@ -34,6 +34,7 @@ #include #include +#include "QF/darray.h" #include "QF/qtypes.h" #include "QF/progs.h"//FIXME for PR_RESMAP @@ -58,22 +59,26 @@ typedef struct ecs_pool_s { uint32_t max_count; // current capacity for components/entity ids } ecs_pool_t; +typedef struct DARRAY_TYPE(component_t) componentset_t; + typedef struct ecs_registry_s { uint32_t *entities; uint32_t next; uint32_t available; uint32_t num_entities; uint32_t max_entities; - const component_t *components; + componentset_t components; ecs_pool_t *comp_pools; - uint32_t num_components; PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way } ecs_registry_t; ecs_registry_t *ECS_NewRegistry (void); void ECS_DelRegistry (ecs_registry_t *registry); -void ECS_RegisterComponents (ecs_registry_t *registry, - const component_t *components, uint32_t count); +uint32_t ECS_RegisterComponents (ecs_registry_t *registry, + const component_t *components, + uint32_t count); +void ECS_CreateComponentPools (ecs_registry_t *registry); + #ifndef __compar_d_fn_t_defined #define __compar_d_fn_t_defined diff --git a/include/QF/ecs/entity.h b/include/QF/ecs/entity.h index c0f80c0f5..3ec271b4f 100644 --- a/include/QF/ecs/entity.h +++ b/include/QF/ecs/entity.h @@ -97,7 +97,7 @@ Ent_HasComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) ENTINLINE void * Ent_GetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *reg) { - const component_t *component = ®->components[comp]; + const component_t *component = ®->components.a[comp]; uint32_t ind = reg->comp_pools[comp].sparse[Ent_Index (ent)]; byte *data = reg->comp_pools[comp].data; return data + ind * component->size; @@ -113,10 +113,10 @@ Ent_SetComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry, { void *dst = Ent_AddComponent (ent, comp, registry); if (data) { - return Component_CopyElements (®istry->components[comp], + return Component_CopyElements (®istry->components.a[comp], dst, 0, data, 0, 1); } else { - return Component_CreateElements (®istry->components[comp], + return Component_CreateElements (®istry->components.a[comp], dst, 0, 1); } } diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index dd96576fc..a78adbf77 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -49,6 +49,9 @@ enum scene_components { scene_old_origin, //XXX FIXME XXX should not be here scene_colormap, + scene_canvas, + scene_vref, //view hierarchy reference + //FIXME these should probably be private to the sw renderer (and in a //group, which needs to be implemented), but need to sort out a good //scheme for semi-dynamic components diff --git a/include/r_internal.h b/include/r_internal.h index 4800384f4..0124a14d2 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -21,7 +21,7 @@ extern vid_render_funcs_t *vid_render_funcs; #define vr_funcs vid_render_funcs extern refdef_t r_refdef; -#define SW_COMP(comp, id) ((void *)((byte *)r_refdef.registry->comp_pools[comp].data + (id) * r_refdef.registry->components[comp].size)) +#define SW_COMP(comp, id) ((void *)((byte *)r_refdef.registry->comp_pools[comp].data + (id) * r_refdef.registry->components.a[comp].size)) extern int r_viewsize; void R_LineGraph (int x, int y, int *h_vals, int count, int height); diff --git a/libs/client/hud.c b/libs/client/hud.c index 3d0810979..bb7f0c9df 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -266,6 +266,7 @@ HUD_Init (void) { hud_registry = ECS_NewRegistry (); ECS_RegisterComponents (hud_registry, hud_components, hud_comp_count); + ECS_CreateComponentPools (hud_registry); } void diff --git a/libs/console/client.c b/libs/console/client.c index e06a13fa4..0cc04619c 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -1023,6 +1023,7 @@ C_Init (void) { client_reg = ECS_NewRegistry (); ECS_RegisterComponents (client_reg, client_components, client_comp_count); + ECS_CreateComponentPools (client_reg); #ifdef __QNXNTO__ setlocale (LC_ALL, "C-TRADITIONAL"); diff --git a/libs/console/server.c b/libs/console/server.c index 81fd50377..e84a51d4e 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -679,6 +679,7 @@ init (void) server_reg = ECS_NewRegistry (); ECS_RegisterComponents (server_reg, server_components, server_comp_count); + ECS_CreateComponentPools (server_reg); get_size (&screen_x, &screen_y); diff --git a/libs/ecs/ecs.c b/libs/ecs/ecs.c index 395fbdba1..4aed897c5 100644 --- a/libs/ecs/ecs.c +++ b/libs/ecs/ecs.c @@ -38,6 +38,7 @@ VISIBLE ecs_registry_t * ECS_NewRegistry (void) { ecs_registry_t *reg = calloc (1, sizeof (ecs_registry_t)); + reg->components = (componentset_t) DARRAY_STATIC_INIT (32); reg->next = Ent_Index (nullent); return reg; } @@ -46,7 +47,7 @@ VISIBLE void ECS_DelRegistry (ecs_registry_t *registry) { free (registry->entities); - for (uint32_t i = 0; i < registry->num_components; i++) { + for (uint32_t i = 0; i < registry->components.size; i++) { free (registry->comp_pools[i].sparse); free (registry->comp_pools[i].dense); free (registry->comp_pools[i].data); @@ -55,15 +56,24 @@ ECS_DelRegistry (ecs_registry_t *registry) free (registry); } -VISIBLE void +VISIBLE uint32_t ECS_RegisterComponents (ecs_registry_t *registry, const component_t *components, uint32_t count) { - registry->num_components = count; - registry->components = components; + uint32_t base = registry->components.size; + DARRAY_RESIZE (®istry->components, base + count); + memcpy (registry->components.a + base, components, + count * sizeof (component_t)); + return base; +} + +VISIBLE void +ECS_CreateComponentPools (ecs_registry_t *registry) +{ + uint32_t count = registry->components.size; registry->comp_pools = calloc (count, sizeof (ecs_pool_t)); size_t size = registry->max_entities * sizeof (uint32_t); - for (uint32_t i = 0; i < registry->num_components; i++) { + for (uint32_t i = 0; i < count; i++) { registry->comp_pools[i].sparse = malloc (size); memset (registry->comp_pools[i].sparse, nullent, size); } @@ -114,14 +124,14 @@ VISIBLE void ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, __compar_d_fn_t cmp, void *arg) { - if (component >= registry->num_components) { + if (component >= registry->components.size) { Sys_Error ("ECS_SortComponentPool: invalid component: %u", component); } ecs_pool_t *pool = ®istry->comp_pools[component]; if (!pool->count) { return; } - __auto_type comp = ®istry->components[component]; + __auto_type comp = ®istry->components.a[component]; ecs_sort_t sortctx = { .cmp = cmp, .arg = arg, .pool = pool, .comp = comp }; heapsort_s (pool->dense, pool->count, sizeof (uint32_t), ecs_compare, ecs_swap, &sortctx); @@ -145,7 +155,7 @@ ECS_NewEntity (ecs_registry_t *registry) registry->max_entities += ENT_GROW; size_t size = registry->max_entities * sizeof (uint32_t); registry->entities = realloc (registry->entities, size); - for (uint32_t i = 0; i < registry->num_components; i++) { + for (uint32_t i = 0; i < registry->components.size; i++) { uint32_t *sparse = registry->comp_pools[i].sparse; sparse = realloc (sparse, size); memset (sparse + registry->max_entities - ENT_GROW, nullent, @@ -169,7 +179,7 @@ ECS_DelEntity (ecs_registry_t *registry, uint32_t ent) registry->next = id; registry->available++; - for (uint32_t i = 0; i < registry->num_components; i++) { + for (uint32_t i = 0; i < registry->components.size; i++) { Ent_RemoveComponent (ent, i, registry); } } @@ -178,7 +188,7 @@ VISIBLE void ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component) { ecs_pool_t *pool = ®istry->comp_pools[component]; - const component_t *comp = ®istry->components[component]; + const component_t *comp = ®istry->components.a[component]; __auto_type destroy = comp->destroy; if (destroy) { byte *data = registry->comp_pools[component].data; diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index ef0441636..6039431c9 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -45,7 +45,7 @@ Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) pool->max_count += COMP_GROW; pool->dense = realloc (pool->dense, pool->max_count * sizeof (uint32_t)); - Component_ResizeArray (®istry->components[comp], &pool->data, + Component_ResizeArray (®istry->components.a[comp], &pool->data, pool->max_count); } uint32_t ind = pool->count++; @@ -63,12 +63,12 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) uint32_t ind = pool->sparse[id]; if (ind < pool->count && pool->dense[ind] == ent) { uint32_t last = pool->count - 1; - Component_DestroyElements (®istry->components[comp], pool->data, + Component_DestroyElements (®istry->components.a[comp], pool->data, ind, 1); if (last > ind) { pool->sparse[Ent_Index (pool->dense[last])] = ind; pool->dense[ind] = pool->dense[last]; - Component_MoveElements (®istry->components[comp], pool->data, + Component_MoveElements (®istry->components.a[comp], pool->data, ind, last, 1); } pool->count--; diff --git a/libs/ecs/test/test-components.c b/libs/ecs/test/test-components.c index e790aab54..1ff8dc88a 100644 --- a/libs/ecs/test/test-components.c +++ b/libs/ecs/test/test-components.c @@ -8,7 +8,7 @@ #include "QF/simd/types.h" #include "QF/mathlib.h" -#include "QF/ecs/component.h" +#include "QF/ecs.h" enum test_components { test_position, @@ -62,7 +62,7 @@ check_ent_components (const uint32_t *ents, uint32_t count, uint32_t comp, ecs_registry_t *reg) { ecs_pool_t *pool = ®->comp_pools[comp]; - const component_t *component = ®->components[comp]; + const component_t *component = ®->components.a[comp]; if (pool->count != count) { printf ("%s pool has wrong object count: %d %d\n", component->name, pool->count, count); @@ -106,6 +106,8 @@ main (void) { ecs_registry_t *reg = ECS_NewRegistry (); ECS_RegisterComponents (reg, test_components, test_num_components); + ECS_CreateComponentPools (reg); + uint32_t enta = ECS_NewEntity (reg); uint32_t entb = ECS_NewEntity (reg); uint32_t entc = ECS_NewEntity (reg); diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index c64b4dade..ad3aa28f3 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -6,8 +6,7 @@ #include #include -#include "QF/ecs/component.h" -#include "QF/ecs/hierarchy.h" +#include "QF/ecs.h" enum { test_href, @@ -886,6 +885,7 @@ main (void) { test_reg = ECS_NewRegistry (); ECS_RegisterComponents (test_reg, test_components, test_num_components); + ECS_CreateComponentPools (test_reg); if (test_single_transform ()) { return 1; } if (test_parent_child_init ()) { return 1; } diff --git a/libs/ecs/test/test-registry.c b/libs/ecs/test/test-registry.c index 1739f3a42..9de0220ca 100644 --- a/libs/ecs/test/test-registry.c +++ b/libs/ecs/test/test-registry.c @@ -6,7 +6,7 @@ #include #include -#include "QF/ecs/component.h" +#include "QF/ecs.h" static int test_new_del (void) diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 7fe86f6ba..82e87bb96 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -213,6 +213,7 @@ Scene_NewScene (void) scene->reg = ECS_NewRegistry (); ECS_RegisterComponents (scene->reg, scene_components, scene_comp_count); + ECS_CreateComponentPools (scene->reg); scene_resources_t *res = calloc (1, sizeof (scene_resources_t)); *(scene_resources_t **)&scene->resources = res; diff --git a/libs/ui/test/test-flow-size.c b/libs/ui/test/test-flow-size.c index 093b52536..951183e5e 100644 --- a/libs/ui/test/test-flow-size.c +++ b/libs/ui/test/test-flow-size.c @@ -280,6 +280,7 @@ main (void) test_reg = ECS_NewRegistry (); ECS_RegisterComponents (test_reg, test_components, 1); + ECS_CreateComponentPools (test_reg); if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { printf ("right-down failed\n"); diff --git a/libs/ui/test/test-flow.c b/libs/ui/test/test-flow.c index b5a4e8c08..1e0c22ee7 100644 --- a/libs/ui/test/test-flow.c +++ b/libs/ui/test/test-flow.c @@ -280,6 +280,7 @@ main (void) test_reg = ECS_NewRegistry (); ECS_RegisterComponents (test_reg, test_components, 1); + ECS_CreateComponentPools (test_reg); if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { printf ("right-down failed\n"); diff --git a/libs/ui/test/test-passage.c b/libs/ui/test/test-passage.c index f59acb82b..1998cedeb 100644 --- a/libs/ui/test/test-passage.c +++ b/libs/ui/test/test-passage.c @@ -64,6 +64,7 @@ main (void) int ret = 0; ecs_registry_t *registry = ECS_NewRegistry (); ECS_RegisterComponents (registry, test_components, 1); + ECS_CreateComponentPools (registry); passage_t *passage = Passage_New (registry, test_href); Passage_ParseText (passage, test_text); diff --git a/libs/ui/text.c b/libs/ui/text.c index 67a3e238b..040fded20 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -92,6 +92,7 @@ Text_Init (void) { text_reg = ECS_NewRegistry (); ECS_RegisterComponents (text_reg, text_components, text_comp_count); + ECS_CreateComponentPools (text_reg); } typedef struct glyphnode_s { From ead5e8916507e1d18e6d9b1779929fba7892e550 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Dec 2022 12:40:14 +0900 Subject: [PATCH 3307/3664] [renderer] Don't mark made pics as cached Marking them as cached means that they'll be "uncached" instead of destroyed when freed, which would not be a particularly good thing. I have no memory as to how I found this as I found the change in my git stash. --- libs/video/renderer/r_progs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 9d8309dfa..2a22dd05d 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -194,7 +194,7 @@ bi_Draw_MakePic (progs_t *pr, void *_res) qp = qpic_new (res); qp->name = 0; qp->pic = pic; - qp->cached = 1; + qp->cached = 0; bq = PR_Zone_Malloc (pr, sizeof (bi_qpic_t)); bq->width = pic->width; bq->height = pic->height; From fdc0dba58b94f7268d77d76ab008cb53ea22959e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Dec 2022 22:28:45 +0900 Subject: [PATCH 3308/3664] [ecs] Add a "system" stuct for parameter passing The system struct bundles the registry and component base together, making it easier to reuse systems in multiple registries, or really, easier to separate one set of ECS system components from those of other systems. --- include/QF/ecs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/QF/ecs.h b/include/QF/ecs.h index bf9e26748..cbdcf2852 100644 --- a/include/QF/ecs.h +++ b/include/QF/ecs.h @@ -72,6 +72,16 @@ typedef struct ecs_registry_s { PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way } ecs_registry_t; +/** Tie an ECS system to a registry. + + Keeps the registry using the system and the system's component base + together. +*/ +typedef struct ecs_system_s { + ecs_registry_t *reg; + uint32_t base; +} ecs_system_t; + ecs_registry_t *ECS_NewRegistry (void); void ECS_DelRegistry (ecs_registry_t *registry); uint32_t ECS_RegisterComponents (ecs_registry_t *registry, From 41d25df0d2840b555fd8fe9d243d175e3baf3c49 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 14 Dec 2022 22:38:37 +0900 Subject: [PATCH 3309/3664] [ui] Attach text views to passage entities Instead of creating new entities for the text views. This approximately halves the number of entities required to display flowed text, but also tests the ability to have an entity in multiple hierarchies (the goal of the ECS component and system changes). --- include/QF/ui/text.h | 29 ++++++------ include/QF/ui/view.h | 24 +++++++++- include/client/hud.h | 3 +- libs/client/cl_screen.c | 16 +++---- libs/client/hud.c | 34 ++++++++------ libs/client/sbar.c | 13 ++++-- libs/console/client.c | 24 ++++++---- libs/console/server.c | 17 +++++-- libs/ruamoko/rua_gui.c | 57 +++++++++++++++++------ libs/ui/test/test-flow-size.c | 18 +++---- libs/ui/test/test-flow.c | 18 +++---- libs/ui/text.c | 80 +++++++++++++++----------------- libs/ui/view.c | 30 ++++++++---- qtv/source/sbar.c | 6 ++- qw/source/cl_ngraph.c | 2 +- qw/source/sv_sbar.c | 8 ++-- ruamoko/qwaq/builtins/graphics.c | 1 - 17 files changed, 232 insertions(+), 148 deletions(-) diff --git a/include/QF/ui/text.h b/include/QF/ui/text.h index 66ca22db1..c3817eb9b 100644 --- a/include/QF/ui/text.h +++ b/include/QF/ui/text.h @@ -72,15 +72,8 @@ typedef struct glyphset_s { uint32_t count; } glyphset_t; -typedef struct text_s { - const char *text; - const char *language; - hb_script_t script; - hb_direction_t direction; -} text_t; - enum { - // covers both view and passage text object hierarcies + // passage text object hierarcies text_href, // all the glyphs in a passage. Always on only the root view of the passage. text_passage_glyphs, @@ -100,6 +93,8 @@ enum { text_comp_count }; +extern const component_t text_components[text_comp_count]; + typedef struct featureset_s DARRAY_TYPE (hb_feature_t) featureset_t; extern hb_feature_t LigatureOff; @@ -111,14 +106,16 @@ extern hb_feature_t CligOn; struct font_s; struct passage_s; -extern struct ecs_registry_s *text_reg; -void Text_Init (void); -struct view_s Text_View (struct font_s *font, struct passage_s *passage); -void Text_SetScript (int textid, const char *lang, hb_script_t script, - text_dir_e dir); -void Text_SetFont (int textid, struct font_s *font); -void Text_SetFeatures (int textid, featureset_t *features); -void Text_AddFeature (int textid, hb_feature_t feature); +struct view_s Text_View (ecs_system_t viewsys, + struct font_s *font, struct passage_s *passage); +void Text_SetScript (ecs_system_t textsys, uint32_t textid, + const char *lang, hb_script_t script, text_dir_e dir); +void Text_SetFont (ecs_system_t textsys, uint32_t textid, + struct font_s *font); +void Text_SetFeatures (ecs_system_t textsys, uint32_t textid, + featureset_t *features); +void Text_AddFeature (ecs_system_t textsys, uint32_t textid, + hb_feature_t feature); #endif//__QF_ui_text_h diff --git a/include/QF/ui/view.h b/include/QF/ui/view.h index 4562ba0ec..3a39ee95b 100644 --- a/include/QF/ui/view.h +++ b/include/QF/ui/view.h @@ -85,6 +85,15 @@ typedef struct viewcont_s { unsigned flow_size:1; ///< If true, view's size is adjusted to flow. } viewcont_t; +enum { + view_href, + + view_comp_count +}; + +extern const struct component_s view_components[view_comp_count]; + +// components in the view hierarchy enum { /// Coordinates of view's origin relative to parent's gravity point. view_pos, @@ -122,7 +131,9 @@ typedef void (*view_move_f) (view_t view, view_pos_t abs); #define VIEWINLINE GNU89INLINE inline -view_t View_New (ecs_registry_t *reg, uint32_t href_comp, view_t parent); +VIEWINLINE view_t View_FromEntity (ecs_system_t viewsys, uint32_t ent); +view_t View_New (ecs_system_t viewsys, view_t parent); +view_t View_AddToEntity (uint32_t ent, ecs_system_t viewsys, view_t parent); VIEWINLINE void View_Delete (view_t view); void View_SetParent (view_t view, view_t parent); void View_UpdateHierarchy (view_t view); @@ -165,6 +176,17 @@ VIEWINLINE void View_SetOnMove (view_t view, view_move_f onmove); #define VIEWINLINE VISIBLE #endif +VIEWINLINE +view_t +View_FromEntity (ecs_system_t viewsys, uint32_t ent) +{ + return (view_t) { + .id = ent, + .reg = viewsys.reg, + .comp = viewsys.base + view_href, + }; +} + VIEWINLINE hierref_t * View_GetRef (view_t view) diff --git a/include/client/hud.h b/include/client/hud.h index 97efb507b..6e84b082a 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -55,7 +55,8 @@ typedef struct hud_subpic_s { uint32_t w, h; } hud_subpic_t; -extern struct ecs_registry_s *hud_registry; +extern struct ecs_system_s hud_system; +extern struct ecs_system_s hud_viewsys; extern int hud_sb_lines; diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index b73b61cac..c86b1bd94 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -171,7 +171,7 @@ CL_Init_Screen (void) HUD_Init (); - cl_screen_view = View_New (hud_registry, hud_href, nullview); + cl_screen_view = View_New (hud_viewsys, nullview); con_module->data->console->screen_view = &cl_screen_view; View_SetPos (cl_screen_view, 0, 0); @@ -180,7 +180,7 @@ CL_Init_Screen (void) View_SetVisible (cl_screen_view, 1); pic = r_funcs->Draw_PicFromWad ("ram"); - ram_view = View_New (hud_registry, hud_href, cl_screen_view); + ram_view = View_New (hud_viewsys, cl_screen_view); View_SetPos (ram_view, 32, 0); View_SetLen (ram_view, pic->width, pic->height); View_SetGravity (ram_view, grav_northwest); @@ -188,7 +188,7 @@ CL_Init_Screen (void) View_SetVisible (ram_view, 0); pic = r_funcs->Draw_PicFromWad ("turtle"); - turtle_view = View_New (hud_registry, hud_href, cl_screen_view); + turtle_view = View_New (hud_viewsys, cl_screen_view); View_SetPos (turtle_view, 32, 0); View_SetLen (turtle_view, pic->width, pic->height); View_SetGravity (turtle_view, grav_northwest); @@ -200,14 +200,14 @@ CL_Init_Screen (void) Cvar_Register (&scr_showturtle_cvar, 0, 0); pic = r_funcs->Draw_PicFromWad ("net"); - net_view = View_New (hud_registry, hud_href, cl_screen_view); + net_view = View_New (hud_viewsys, cl_screen_view); View_SetPos (net_view, 64, 0); View_SetLen (net_view, pic->width, pic->height); View_SetGravity (net_view, grav_northwest); Ent_SetComponent (net_view.id, hud_pic, net_view.reg, &pic); View_SetVisible (net_view, 0); - timegraph_view = View_New (hud_registry, hud_href, cl_screen_view); + timegraph_view = View_New (hud_viewsys, cl_screen_view); View_SetPos (timegraph_view, 0, 0); View_SetLen (timegraph_view, r_data->vid->width, 100); View_SetGravity (timegraph_view, grav_southwest); @@ -215,7 +215,7 @@ CL_Init_Screen (void) Ent_SetComponent (timegraph_view.id, hud_func, timegraph_view.reg, &rtg); View_SetVisible (timegraph_view, r_timegraph); - zgraph_view = View_New (hud_registry, hud_href, cl_screen_view); + zgraph_view = View_New (hud_viewsys, cl_screen_view); View_SetPos (zgraph_view, 0, 0); View_SetLen (zgraph_view, r_data->vid->width, 100); View_SetGravity (zgraph_view, grav_southwest); @@ -225,7 +225,7 @@ CL_Init_Screen (void) const char *name = "gfx/loading.lmp"; pic = r_funcs->Draw_CachePic (name, 1); - loading_view = View_New (hud_registry, hud_href, cl_screen_view); + loading_view = View_New (hud_viewsys, cl_screen_view); View_SetPos (loading_view, 0, -24); View_SetLen (loading_view, pic->width, pic->height); View_SetGravity (loading_view, grav_center); @@ -234,7 +234,7 @@ CL_Init_Screen (void) name = "gfx/pause.lmp"; pic = r_funcs->Draw_CachePic (name, 1); - pause_view = View_New (hud_registry, hud_href, cl_screen_view); + pause_view = View_New (hud_viewsys, cl_screen_view); View_SetPos (pause_view, 0, -24); View_SetLen (pause_view, pic->width, pic->height); View_SetGravity (pause_view, grav_center); diff --git a/libs/client/hud.c b/libs/client/hud.c index bb7f0c9df..11cc8c4aa 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -88,7 +88,8 @@ static const component_t hud_components[hud_comp_count] = { }, }; -ecs_registry_t *hud_registry; +ecs_system_t hud_system; +ecs_system_t hud_viewsys; int hud_sb_lines; int hud_sbar; @@ -264,9 +265,13 @@ hud_scoreboard_gravity_f (void *data, const cvar_t *cvar) void HUD_Init (void) { - hud_registry = ECS_NewRegistry (); - ECS_RegisterComponents (hud_registry, hud_components, hud_comp_count); - ECS_CreateComponentPools (hud_registry); + hud_system.reg = ECS_NewRegistry (); + hud_viewsys.reg = hud_system.reg; + hud_system.base = ECS_RegisterComponents (hud_system.reg, hud_components, + hud_comp_count); + hud_viewsys.base = ECS_RegisterComponents (hud_system.reg, view_components, + view_comp_count); + ECS_CreateComponentPools (hud_system.reg); } void @@ -326,8 +331,7 @@ draw_update (ecs_pool_t *pool) uint32_t *ent = pool->dense; hud_update_f *func = pool->data; while (count-- > 0) { - view_t view = { .id = *ent++, .reg = hud_registry }; - (*func++) (view); + (*func++) (View_FromEntity (hud_viewsys, *ent++)); } } @@ -344,7 +348,7 @@ draw_tile_views (ecs_pool_t *pool) uint32_t count = pool->count; uint32_t *ent = pool->dense; while (count-- > 0) { - view_t view = { .id = *ent++, .reg = hud_registry }; + view_t view = View_FromEntity (hud_viewsys, *ent++); if (View_GetVisible (view)) { view_pos_t pos = View_GetAbs (view); view_pos_t len = View_GetLen (view); @@ -360,7 +364,7 @@ draw_pic_views (ecs_pool_t *pool) uint32_t *ent = pool->dense; qpic_t **pic = pool->data; while (count-- > 0) { - view_t view = { .id = *ent++, .reg = hud_registry }; + view_t view = View_FromEntity (hud_viewsys, *ent++); if (View_GetVisible (view)) { view_pos_t pos = View_GetAbs (view); r_funcs->Draw_Pic (pos.x, pos.y, *pic); @@ -376,7 +380,7 @@ draw_subpic_views (ecs_pool_t *pool) uint32_t *ent = pool->dense; hud_subpic_t *subpic = pool->data; while (count-- > 0) { - view_t view = { .id = *ent++, .reg = hud_registry }; + view_t view = View_FromEntity (hud_viewsys, *ent++); if (View_GetVisible (view)) { view_pos_t pos = View_GetAbs (view); r_funcs->Draw_SubPic (pos.x, pos.y, subpic->pic, @@ -393,7 +397,7 @@ draw_cachepic_views (ecs_pool_t *pool) uint32_t *ent = pool->dense; const char **name = pool->data; while (count-- > 0) { - view_t view = { .id = *ent++, .reg = hud_registry }; + view_t view = View_FromEntity (hud_viewsys, *ent++); if (View_GetVisible (view)) { view_pos_t pos = View_GetAbs (view); qpic_t *pic = r_funcs->Draw_CachePic (*name, 1); @@ -410,7 +414,7 @@ draw_fill_views (ecs_pool_t *pool) uint32_t *ent = pool->dense; byte *fill = pool->data; while (count-- > 0) { - view_t view = { .id = *ent++, .reg = hud_registry }; + view_t view = View_FromEntity (hud_viewsys, *ent++); if (View_GetVisible (view)) { view_pos_t pos = View_GetAbs (view); view_pos_t len = View_GetLen (view); @@ -427,7 +431,7 @@ draw_charbuff_views (ecs_pool_t *pool) uint32_t *ent = pool->dense; draw_charbuffer_t **charbuff = pool->data; while (count-- > 0) { - view_t view = { .id = *ent++, .reg = hud_registry }; + view_t view = View_FromEntity (hud_viewsys, *ent++); if (View_GetVisible (view)) { view_pos_t pos = View_GetAbs (view); r_funcs->Draw_CharBuffer (pos.x, pos.y, *charbuff); @@ -443,7 +447,7 @@ draw_func_views (ecs_pool_t *pool) uint32_t *ent = pool->dense; hud_func_f *func = pool->data; while (count-- > 0) { - view_t view = { .id = *ent++, .reg = hud_registry }; + view_t view = View_FromEntity (hud_viewsys, *ent++); if (View_GetVisible (view)) { view_pos_t pos = View_GetAbs (view); view_pos_t len = View_GetLen (view); @@ -461,7 +465,7 @@ draw_outline_views (ecs_pool_t *pool) byte *col = pool->data; __auto_type line = r_funcs->Draw_Line; while (count-- > 0) { - view_t view = { .id = *ent++, .reg = hud_registry }; + view_t view = View_FromEntity (hud_viewsys, *ent++); byte c = *col++; if (View_GetVisible (view)) { view_pos_t p = View_GetAbs (view); @@ -492,7 +496,7 @@ HUD_Draw_Views (void) }; for (int i = 0; i < hud_comp_count; i++) { if (draw_func[i]) { - draw_func[i] (&hud_registry->comp_pools[i]); + draw_func[i] (&hud_system.reg->comp_pools[i + hud_system.base]); } } } diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 95133ad3b..d131f2c76 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -254,7 +254,7 @@ static draw_charbuffer_t *solo_name; static view_t sbar_view (int x, int y, int w, int h, grav_t gravity, view_t parent) { - view_t view = View_New (hud_registry, hud_href, parent); + view_t view = View_New (hud_viewsys, parent); View_SetPos (view, x, y); View_SetLen (view, w, h); View_SetGravity (view, gravity); @@ -2024,8 +2024,10 @@ href_cmp (const void *_a, const void *_b, void *arg) { uint32_t enta = *(const uint32_t *)_a; uint32_t entb = *(const uint32_t *)_b; - hierref_t *ref_a = Ent_GetComponent (enta, hud_href, hud_registry); - hierref_t *ref_b = Ent_GetComponent (entb, hud_href, hud_registry); + ecs_registry_t *reg = hud_viewsys.reg; + uint32_t href = hud_viewsys.base + hud_href; + hierref_t *ref_a = Ent_GetComponent (enta, href, reg); + hierref_t *ref_b = Ent_GetComponent (entb, href, reg); if (ref_a->hierarchy == ref_b->hierarchy) { return ref_a->index - ref_b->index; } @@ -2123,7 +2125,8 @@ set_hud_sbar (void) sbar_remcomponent (sbar_tile[0], hud_tile); sbar_remcomponent (sbar_tile[1], hud_tile); } - ECS_SortComponentPool (hud_registry, hud_pic, href_cmp, 0); + ECS_SortComponentPool (hud_system.reg, hud_system.base + hud_pic, + href_cmp, 0); } static void @@ -2551,7 +2554,7 @@ Sbar_Init (int *stats, float *item_gettime) sbar_stats = stats; sbar_item_gettime = item_gettime; - center_passage.reg = hud_registry; + center_passage.reg = hud_viewsys.reg; HUD_Init_Cvars (); Cvar_AddListener (Cvar_FindVar ("hud_sbar"), sbar_hud_sbar_f, 0); Cvar_AddListener (Cvar_FindVar ("hud_swap"), sbar_hud_swap_f, 0); diff --git a/libs/console/client.c b/libs/console/client.c index 0cc04619c..e1678ce1f 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -154,6 +154,8 @@ static cvar_t cl_conmode_cvar = { }; static ecs_registry_t *client_reg; +static uint32_t client_base; +static uint32_t view_base; static con_state_t con_state; static int con_event_id; @@ -1022,7 +1024,10 @@ static void C_Init (void) { client_reg = ECS_NewRegistry (); - ECS_RegisterComponents (client_reg, client_components, client_comp_count); + client_base = ECS_RegisterComponents (client_reg, client_components, + client_comp_count); + view_base = ECS_RegisterComponents (client_reg, view_components, + view_comp_count); ECS_CreateComponentPools (client_reg); #ifdef __QNXNTO__ @@ -1044,14 +1049,15 @@ C_Init (void) con_debuglog = COM_CheckParm ("-condebug"); // The console will get resized, so assume initial size is 320x200 - screen_view = View_New (client_reg, client_href, nullview); - console_view = View_New (client_reg, client_href, screen_view); - buffer_view = View_New (client_reg, client_href, console_view); - command_view = View_New (client_reg, client_href, console_view); - download_view = View_New (client_reg, client_href, console_view); - notify_view = View_New (client_reg, client_href, screen_view); - say_view = View_New (client_reg, client_href, screen_view); - menu_view = View_New (client_reg, client_href, screen_view); + ecs_system_t sys = { client_reg, view_base }; + screen_view = View_New (sys, nullview); + console_view = View_New (sys, screen_view); + buffer_view = View_New (sys, console_view); + command_view = View_New (sys, console_view); + download_view = View_New (sys, console_view); + notify_view = View_New (sys, screen_view); + say_view = View_New (sys, screen_view); + menu_view = View_New (sys, screen_view); View_SetGravity (screen_view, grav_northwest); View_SetGravity (console_view, grav_northwest); diff --git a/libs/console/server.c b/libs/console/server.c index e84a51d4e..5595e40da 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -161,6 +161,8 @@ static volatile sig_atomic_t interrupted; static int batch_print; static ecs_registry_t *server_reg; +static uint32_t server_base; +static uint32_t view_base; #define MAXCMDLINE 256 @@ -246,8 +248,9 @@ draw_fun_char (WINDOW *win, byte c, int blue) static inline void sv_refresh_windows (void) { - sv_view_t *window = server_reg->comp_pools[server_window].data; - uint32_t count = server_reg->comp_pools[server_window].count; + uint32_t window_comp = server_base + server_window; + sv_view_t *window = server_reg->comp_pools[window_comp].data; + uint32_t count = server_reg->comp_pools[window_comp].count; while (count-- > 0) { wnoutrefresh ((WINDOW *) (window++)->win); } @@ -616,7 +619,8 @@ create_window (view_t parent, int xpos, int ypos, int xlen, int ylen, grav_t grav, void *obj, int opts, void (*draw) (view_t), void (*setgeometry) (view_t)) { - view_t view = View_New (server_reg, server_href, parent); + view_t view = View_New ((ecs_system_t) { server_reg, view_base }, + parent); View_SetPos (view, xpos, ypos); View_SetLen (view, xlen, ylen); View_SetGravity (view, grav); @@ -678,12 +682,15 @@ init (void) nonl (); server_reg = ECS_NewRegistry (); - ECS_RegisterComponents (server_reg, server_components, server_comp_count); + server_base = ECS_RegisterComponents (server_reg, server_components, + server_comp_count); + view_base = ECS_RegisterComponents (server_reg, view_components, + view_comp_count); ECS_CreateComponentPools (server_reg); get_size (&screen_x, &screen_y); - sv_view = View_New (server_reg, server_href, nullview); + sv_view = View_New ((ecs_system_t) { server_reg, view_base }, nullview); View_SetPos (sv_view, 0, 0); View_SetLen (sv_view, screen_x, screen_y); View_SetGravity (sv_view, grav_northwest); diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index 4f5be5e45..a0f027bd5 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -68,6 +68,10 @@ typedef struct { rua_passage_t *passages; PR_RESMAP (rua_font_t) font_map; rua_font_t *fonts; + + ecs_registry_t *reg; + uint32_t text_base; + uint32_t view_base; } gui_resources_t; static rua_passage_t * @@ -206,6 +210,7 @@ static void bi_gui_destroy (progs_t *pr, void *_res) { gui_resources_t *res = _res; + ECS_DelRegistry (res->reg); free (res); } @@ -225,7 +230,7 @@ bi (Font_Load) bi (Passage_New) { gui_resources_t *res = _res; - passage_t *passage = Passage_New (text_reg, text_href); + passage_t *passage = Passage_New (res->reg, res->text_base + text_href); R_INT (pr) = alloc_passage (res, passage); } @@ -272,17 +277,20 @@ bi (Text_View) gui_resources_t *res = _res; rua_font_t *font = get_font (res, P_INT (pr, 0)); rua_passage_t *psg = get_passage (res, P_INT (pr, 1)); - view_t view = Text_View (font->font, psg->passage); + ecs_system_t viewsys = { .reg = res->reg, .base = res->view_base }; + view_t view = Text_View (viewsys, font->font, psg->passage); R_INT (pr) = view.id;//FIXME } bi (Text_SetScript) { + gui_resources_t *res = _res; uint32_t textent = P_UINT (pr, 0); const char *lang = P_GSTRING (pr, 1); int script = P_INT (pr, 1); int dir = P_INT (pr, 1); - Text_SetScript (textent, lang, script, dir); + ecs_system_t textsys = { .reg = res->reg, .base = res->text_base }; + Text_SetScript (textsys, textent, lang, script, dir); } static void @@ -313,15 +321,18 @@ draw_box (view_pos_t *abs, view_pos_t *len, uint32_t ind, int c) bi (Text_Draw) { - ecs_pool_t *pool = &text_reg->comp_pools[text_passage_glyphs]; + gui_resources_t *res = _res; + uint32_t passage_glyphs = res->text_base + text_passage_glyphs; + uint32_t glyphs = res->text_base + text_glyphs; + uint32_t vhref = res->view_base + view_href; + ecs_pool_t *pool = &res->reg->comp_pools[passage_glyphs]; uint32_t count = pool->count; uint32_t *ent = pool->dense; glyphset_t *glyphset = pool->data; while (count-- > 0) { - view_t psg_view = { .id = *ent++, .reg = text_reg, - .comp = text_href}; + view_t psg_view = { .id = *ent++, .reg = res->reg, .comp = vhref}; // first child is always a paragraph view, and all vies after the // first paragraph's first child are all text views view_t para_view = View_GetChild (psg_view, 0); @@ -332,8 +343,7 @@ bi (Text_Draw) view_pos_t *len = h->components[view_len]; for (uint32_t i = href->index; i < h->num_objects; i++) { - glyphref_t *gref = Ent_GetComponent (h->ent[i], text_glyphs, - text_reg); + glyphref_t *gref = Ent_GetComponent (h->ent[i], glyphs, res->reg); draw_glyphs (&abs[i], glyphset, gref); if (0) draw_box (abs, len, i, 253); @@ -348,49 +358,61 @@ bi (Text_Draw) bi (View_ChildCount) { + gui_resources_t *res = _res; uint32_t viewid = P_UINT (pr, 0); - view_t view = { .id = viewid, .reg = text_reg }; + view_t view = { .id = viewid, .reg = res->reg, + .comp = res->view_base + view_href }; R_UINT (pr) = View_ChildCount (view); } bi (View_GetChild) { + gui_resources_t *res = _res; uint32_t viewid = P_UINT (pr, 0); uint32_t index = P_UINT (pr, 1); - view_t view = { .id = viewid, .reg = text_reg }; + view_t view = { .id = viewid, .reg = res->reg, + .comp = res->view_base + view_href }; R_UINT (pr) = View_GetChild (view, index).id; } bi (View_SetPos) { + gui_resources_t *res = _res; uint32_t viewid = P_UINT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); - view_t view = { .id = viewid, .reg = text_reg }; + view_t view = { .id = viewid, .reg = res->reg, + .comp = res->view_base + view_href }; View_SetPos (view, x, y); } bi (View_SetLen) { + gui_resources_t *res = _res; uint32_t viewid = P_UINT (pr, 0); int x = P_INT (pr, 1); int y = P_INT (pr, 2); - view_t view = { .id = viewid, .reg = text_reg }; + view_t view = { .id = viewid, .reg = res->reg, + .comp = res->view_base + view_href }; View_SetLen (view, x, y); } bi (View_GetLen) { + gui_resources_t *res = _res; uint32_t viewid = P_UINT (pr, 0); - view_t view = { .id = viewid, .reg = text_reg }; + view_t view = { .id = viewid, .reg = res->reg, + .comp = res->view_base + view_href }; view_pos_t l = View_GetLen (view); R_var (pr, ivec2) = (pr_ivec2_t) { l.x, l.y }; } bi (View_UpdateHierarchy) { + gui_resources_t *res = _res; uint32_t viewid = P_UINT (pr, 0); - view_t view = { .id = viewid, .reg = text_reg }; + view_t view = { .id = viewid, .reg = res->reg, + .comp = res->view_base + view_href }; View_UpdateHierarchy (view); } @@ -429,4 +451,11 @@ RUA_GUI_Init (progs_t *pr, int secure) PR_Resources_Register (pr, "Draw", res, bi_gui_clear, bi_gui_destroy); PR_RegisterBuiltins (pr, builtins, res); + + res->reg = ECS_NewRegistry (); + res->text_base = ECS_RegisterComponents (res->reg, text_components, + text_comp_count); + res->view_base = ECS_RegisterComponents (res->reg, view_components, + view_comp_count); + ECS_CreateComponentPools (res->reg); } diff --git a/libs/ui/test/test-flow-size.c b/libs/ui/test/test-flow-size.c index 951183e5e..40c133aa8 100644 --- a/libs/ui/test/test-flow-size.c +++ b/libs/ui/test/test-flow-size.c @@ -5,10 +5,12 @@ #include "QF/ui/view.h" -static ecs_registry_t *test_reg; +static ecs_system_t test_sys; enum { test_href, + + test_comp_count }; static const component_t test_components[] = { @@ -223,7 +225,7 @@ print_view (view_t view) static int test_flow (testdata_t *child_views, int count, void (flow) (view_t, view_pos_t)) { - view_t flow_view = View_New (test_reg, test_href, nullview); + view_t flow_view = View_New (test_sys, nullview); View_SetPos (flow_view, 0, 0); View_SetLen (flow_view, 256, 256); View_SetGravity (flow_view, grav_northwest); @@ -232,7 +234,7 @@ test_flow (testdata_t *child_views, int count, void (flow) (view_t, view_pos_t)) for (int i = 0; i < count; i++) { testdata_t *td = &child_views[i]; - view_t child = View_New (test_reg, test_href, flow_view); + view_t child = View_New (test_sys, flow_view); View_SetPos (child, 0, 0); View_SetLen (child, td->xlen, td->ylen); View_SetGravity (child, grav_flow); @@ -266,8 +268,7 @@ test_flow (testdata_t *child_views, int count, void (flow) (view_t, view_pos_t)) td->expect.xpos, td->expect.ypos, td->expect.xrel, td->expect.yrel, td->expect.xabs, td->expect.yabs); - print_view ((view_t) { .reg = test_reg, .id = ent[child], - .comp = flow_view.comp}); + print_view (View_FromEntity (test_sys, ent[child])); } } return ret; @@ -278,9 +279,10 @@ main (void) { int ret = 0; - test_reg = ECS_NewRegistry (); - ECS_RegisterComponents (test_reg, test_components, 1); - ECS_CreateComponentPools (test_reg); + test_sys.reg = ECS_NewRegistry (); + test_sys.base = ECS_RegisterComponents (test_sys.reg, test_components, + test_comp_count); + ECS_CreateComponentPools (test_sys.reg); if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { printf ("right-down failed\n"); diff --git a/libs/ui/test/test-flow.c b/libs/ui/test/test-flow.c index 1e0c22ee7..e082447d8 100644 --- a/libs/ui/test/test-flow.c +++ b/libs/ui/test/test-flow.c @@ -5,10 +5,12 @@ #include "QF/ui/view.h" -static ecs_registry_t *test_reg; +static ecs_system_t test_sys; enum { test_href, + + test_comp_count }; static const component_t test_components[] = { @@ -224,7 +226,7 @@ static int test_flow (testdata_t *child_views, int count, void (*flow) (view_t, view_pos_t)) { - view_t flow_view = View_New (test_reg, test_href, nullview); + view_t flow_view = View_New (test_sys, nullview); View_SetPos (flow_view, 0, 0); View_SetLen (flow_view, 256, 256); View_SetGravity (flow_view, grav_northwest); @@ -232,7 +234,7 @@ test_flow (testdata_t *child_views, int count, for (int i = 0; i < count; i++) { testdata_t *td = &child_views[i]; - view_t child = View_New (test_reg, test_href, flow_view); + view_t child = View_New (test_sys, flow_view); View_SetPos (child, 0, 0); View_SetLen (child, td->xlen, td->ylen); View_SetGravity (child, grav_flow); @@ -266,8 +268,7 @@ test_flow (testdata_t *child_views, int count, td->expect.xpos, td->expect.ypos, td->expect.xrel, td->expect.yrel, td->expect.xabs, td->expect.yabs); - print_view ((view_t) { .reg = test_reg, .id = ent[child], - .comp = flow_view.comp}); + print_view (View_FromEntity (test_sys, ent[child])); } } return ret; @@ -278,9 +279,10 @@ main (void) { int ret = 0; - test_reg = ECS_NewRegistry (); - ECS_RegisterComponents (test_reg, test_components, 1); - ECS_CreateComponentPools (test_reg); + test_sys.reg = ECS_NewRegistry (); + test_sys.base = ECS_RegisterComponents (test_sys.reg, test_components, + test_comp_count); + ECS_CreateComponentPools (test_sys.reg); if (test_flow (right_down_views, right_down_count, view_flow_right_down)) { printf ("right-down failed\n"); diff --git a/libs/ui/text.c b/libs/ui/text.c index 040fded20..ee3c226b0 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -57,7 +57,7 @@ text_features_destroy (void *_features) DARRAY_CLEAR (features); } -static const component_t text_components[text_comp_count] = { +const component_t text_components[text_comp_count] = { [text_href] = { .size = sizeof (hierref_t), .name = "href", @@ -85,15 +85,6 @@ static const component_t text_components[text_comp_count] = { .destroy = text_features_destroy, }, }; -ecs_registry_t *text_reg; - -void -Text_Init (void) -{ - text_reg = ECS_NewRegistry (); - ECS_RegisterComponents (text_reg, text_components, text_comp_count); - ECS_CreateComponentPools (text_reg); -} typedef struct glyphnode_s { struct glyphnode_s *next; @@ -116,8 +107,9 @@ static view_resize_f text_flow_funcs[] = { }; view_t -Text_View (font_t *font, passage_t *passage) +Text_View (ecs_system_t viewsys, font_t *font, passage_t *passage) { + ecs_registry_t *reg = passage->reg; hierarchy_t *h = passage->hierarchy; psg_text_t *text_objects = h->components[passage_type_text_obj]; glyphnode_t *glyph_nodes = 0; @@ -146,16 +138,15 @@ Text_View (font_t *font, passage_t *passage) hb_language_t para_language = psg_language; featureset_t *para_features = psg_features;; - if (Ent_HasComponent (para_ent, text_script, text_reg)) { + if (Ent_HasComponent (para_ent, text_script, reg)) { script_component_t *s = Ent_GetComponent (para_ent, text_script, - text_reg); + reg); para_script = s->script; para_language = s->language; para_direction = s->direction; } - if (Ent_HasComponent (para_ent, text_features, text_reg)) { - para_features = Ent_GetComponent (para_ent, text_features, - text_reg); + if (Ent_HasComponent (para_ent, text_features, reg)) { + para_features = Ent_GetComponent (para_ent, text_features, reg); } for (uint32_t j = 0; j < h->childCount[paragraph]; j++) { uint32_t textind = h->childIndex[paragraph] + j; @@ -169,16 +160,15 @@ Text_View (font_t *font, passage_t *passage) hb_language_t txt_language = para_language; featureset_t *txt_features = para_features;; - if (Ent_HasComponent (text_ent, text_script, text_reg)) { + if (Ent_HasComponent (text_ent, text_script, reg)) { script_component_t *s = Ent_GetComponent (text_ent, text_script, - text_reg); + reg); txt_script = s->script; txt_language = s->language; txt_direction = s->direction; } - if (Ent_HasComponent (text_ent, text_features, text_reg)) { - txt_features = Ent_GetComponent (text_ent, text_features, - text_reg); + if (Ent_HasComponent (text_ent, text_features, reg)) { + txt_features = Ent_GetComponent (text_ent, text_features, reg); } hb_buffer_reset (buffer); @@ -240,7 +230,7 @@ Text_View (font_t *font, passage_t *passage) head = &(*head)->next; } } - view_t passage_view = View_New (text_reg, text_href, nullview); + view_t passage_view = View_AddToEntity (h->ent[0], viewsys, nullview); glyphref_t passage_ref = {}; glyphobj_t *glyphs = malloc (glyph_count * sizeof (glyphobj_t)); glyphnode_t *g = glyph_nodes; @@ -248,10 +238,13 @@ Text_View (font_t *font, passage_t *passage) int psg_vertical = !!(psg_direction & 2); for (uint32_t i = 0; i < h->childCount[0]; i++) { uint32_t paragraph = h->childIndex[0] + i; - view_t paraview = View_New (text_reg, text_href, passage_view); + view_t paraview = View_AddToEntity (h->ent[paragraph], viewsys, + passage_view); glyphref_t pararef = { .start = passage_ref.count }; for (uint32_t j = 0; j < h->childCount[paragraph]; j++, g = g->next) { - view_t textview = View_New (text_reg, text_href, paraview); + uint32_t to = h->childIndex[paragraph] + j; + view_t textview = View_AddToEntity (h->ent[to], viewsys, + paraview); glyphref_t glyph_ref = { .start = passage_ref.count, .count = g->count, @@ -265,7 +258,7 @@ Text_View (font_t *font, passage_t *passage) .fontid = go->fontid, }; } - Ent_SetComponent (textview.id, text_glyphs, text_reg, &glyph_ref); + Ent_SetComponent (textview.id, text_glyphs, reg, &glyph_ref); View_SetPos (textview, g->mins[0], -g->mins[1]); View_SetLen (textview, g->maxs[0] - g->mins[0], g->maxs[1] - g->mins[1]); @@ -273,13 +266,13 @@ Text_View (font_t *font, passage_t *passage) passage_ref.count += g->count; } pararef.count = passage_ref.count - pararef.start; - Ent_SetComponent (paraview.id, text_glyphs, text_reg, ¶ref); + Ent_SetComponent (paraview.id, text_glyphs, reg, ¶ref); uint32_t para_ent = h->ent[paragraph]; text_dir_e para_direction = psg_direction; - if (Ent_HasComponent (para_ent, text_script, text_reg)) { + if (Ent_HasComponent (para_ent, text_script, reg)) { script_component_t *s = Ent_GetComponent (para_ent, text_script, - text_reg); + reg); para_direction = s->direction; } View_SetOnResize (paraview, text_flow_funcs[para_direction]); @@ -287,18 +280,17 @@ Text_View (font_t *font, passage_t *passage) View_SetGravity (paraview, grav_northwest); View_Control (paraview)->flow_size = 1; } - Ent_SetComponent (passage_view.id, text_glyphs, text_reg, &passage_ref); + Ent_SetComponent (passage_view.id, text_glyphs, reg, &passage_ref); glyphset_t glyphset = { .glyphs = glyphs, .count = glyph_count, }; - Ent_SetComponent (passage_view.id, text_passage_glyphs, text_reg, - &glyphset); + Ent_SetComponent (passage_view.id, text_passage_glyphs, reg, &glyphset); return passage_view; } void -Text_SetScript (int textid, const char *lang, hb_script_t script, +Text_SetScript (ecs_system_t textsys, uint32_t textid, const char *lang, hb_script_t script, text_dir_e dir) { script_component_t scr = { @@ -306,32 +298,34 @@ Text_SetScript (int textid, const char *lang, hb_script_t script, .script = script, .direction = dir, }; - Ent_SetComponent (textid, text_script, text_reg, &scr); + Ent_SetComponent (textid, textsys.base + text_script, textsys.reg, &scr); } void -Text_SetFont (int textid, font_t *font) +Text_SetFont (ecs_system_t textsys, uint32_t textid, font_t *font) { - Ent_SetComponent (textid, text_font, text_reg, &font); + Ent_SetComponent (textid, textsys.base + text_font, textsys.reg, &font); } void -Text_SetFeatures (int textid, featureset_t *features) +Text_SetFeatures (ecs_system_t textsys, uint32_t textid, featureset_t *features) { - if (Ent_HasComponent (textid, text_features, text_reg)) { - Ent_RemoveComponent (textid, text_features, text_reg); + uint32_t features_comp = textsys.base + text_features; + if (Ent_HasComponent (textid, features_comp, textsys.reg)) { + Ent_RemoveComponent (textid, features_comp, textsys.reg); } - featureset_t *f = Ent_SetComponent (textid, text_features, text_reg, 0); + featureset_t *f = Ent_SetComponent (textid, features_comp, textsys.reg, 0); DARRAY_RESIZE (f, features->size); memcpy (f->a, features->a, features->size * sizeof (hb_feature_t)); } void -Text_AddFeature (int textid, hb_feature_t feature) +Text_AddFeature (ecs_system_t textsys, uint32_t textid, hb_feature_t feature) { - if (!Ent_HasComponent (textid, text_features, text_reg)) { - Ent_SetComponent (textid, text_features, text_reg, 0); + uint32_t features_comp = textsys.base + text_features; + if (!Ent_HasComponent (textid, features_comp, textsys.reg)) { + Ent_SetComponent (textid, features_comp, textsys.reg, 0); } - featureset_t *f = Ent_GetComponent (textid, text_features, text_reg); + featureset_t *f = Ent_GetComponent (textid, features_comp, textsys.reg); DARRAY_APPEND (f, feature); } diff --git a/libs/ui/view.c b/libs/ui/view.c index 61a62a9f9..70b8d8326 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -90,7 +90,14 @@ view_modified_init (void *_modified) *modified = 1; } -static const component_t view_components[view_type_count] = { +const component_t view_components[view_comp_count] = { + [view_href] = { + .size = sizeof (hierref_t), + .name = "view href", + }, +}; + +static const component_t view_type_components[view_type_count] = { [view_pos] = { .size = sizeof (view_pos_t), .name = "pos", @@ -132,14 +139,14 @@ static const component_t view_components[view_type_count] = { static const hierarchy_type_t view_type = { .num_components = view_type_count, - .components = view_components, + .components = view_type_components, }; view_t -View_New (ecs_registry_t *reg, uint32_t href_comp, view_t parent) +View_AddToEntity (uint32_t ent, ecs_system_t viewsys, view_t parent) { - uint32_t view = ECS_NewEntity (reg); - hierref_t *ref = Ent_AddComponent (view, href_comp, reg); + uint32_t href_comp = viewsys.base + view_href; + hierref_t *ref = Ent_AddComponent (ent, href_comp, viewsys.reg); if (parent.reg && parent.id != nullent) { hierref_t *pref = View_GetRef (parent); @@ -147,11 +154,18 @@ View_New (ecs_registry_t *reg, uint32_t href_comp, view_t parent) ref->index = Hierarchy_InsertHierarchy (pref->hierarchy, 0, pref->index, 0); } else { - ref->hierarchy = Hierarchy_New (reg, href_comp, &view_type, 1); + ref->hierarchy = Hierarchy_New (viewsys.reg, href_comp, &view_type, 1); ref->index = 0; } - ref->hierarchy->ent[ref->index] = view; - return (view_t) { .reg = reg, .id = view, .comp = href_comp }; + ref->hierarchy->ent[ref->index] = ent; + return (view_t) { .reg = viewsys.reg, .id = ent, .comp = href_comp }; +} + +view_t +View_New (ecs_system_t viewsys, view_t parent) +{ + uint32_t view = ECS_NewEntity (viewsys.reg); + return View_AddToEntity (view, viewsys, parent); } void diff --git a/qtv/source/sbar.c b/qtv/source/sbar.c index 84529940a..e9d511dfd 100644 --- a/qtv/source/sbar.c +++ b/qtv/source/sbar.c @@ -88,14 +88,16 @@ qtv_sbar_init (void) sv_view_t sv_view = *(sv_view_t *) comp; sv_view.setgeometry = 0; - view = View_New (status.reg, status.comp, status); + ecs_system_t viewsys = { .reg = status.reg, + .base = status.comp - view_href }; + view = View_New (viewsys, status); View_SetPos (view, 0, 0); View_SetLen (view, 8, 1); View_SetGravity (view, grav_northwest); sv_view.draw = draw_servers; Ent_SetComponent (view.id, server_view, view.reg, &sv_view); - view = View_New (status.reg, status.comp, status); + view = View_New (viewsys, status); View_SetPos (view, 8, 0); View_SetLen (view, 9, 1); View_SetGravity (view, grav_northwest); diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 801872984..4261e5eda 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -156,7 +156,7 @@ CL_NetGraph (view_pos_t abs, view_pos_t len) void CL_NetGraph_Init (void) { - cl_netgraph_view = View_New (hud_registry, hud_href, cl_screen_view); + cl_netgraph_view = View_New (hud_viewsys, cl_screen_view); View_SetPos (cl_netgraph_view, 0, 64); View_SetLen (cl_netgraph_view, NET_TIMINGS + 16, cl_netgraph_height + 25); View_SetGravity (cl_netgraph_view, grav_southwest); diff --git a/qw/source/sv_sbar.c b/qw/source/sv_sbar.c index 45d1615e9..0989ee2b6 100644 --- a/qw/source/sv_sbar.c +++ b/qw/source/sv_sbar.c @@ -118,21 +118,23 @@ SV_Sbar_Init (void) sv_view_t sv_view = *(sv_view_t *) comp; sv_view.setgeometry = 0; - view = View_New (status.reg, status.comp, status); + ecs_system_t viewsys = { .reg = status.reg, + .base = status.comp - view_href }; + view = View_New (viewsys, status); View_SetPos (view, 0, 0); View_SetLen (view, 11, 1); View_SetGravity (view, grav_northwest); sv_view.draw = draw_cpu; Ent_SetComponent (view.id, server_view, view.reg, &sv_view); - view = View_New (status.reg, status.comp, status); + view = View_New (viewsys, status); View_SetPos (view, 11, 0); View_SetLen (view, 8, 1); View_SetGravity (view, grav_northwest); sv_view.draw = draw_rec; Ent_SetComponent (view.id, server_view, view.reg, &sv_view); - view = View_New (status.reg, status.comp, status); + view = View_New (viewsys, status); View_SetPos (view, 19, 0); View_SetLen (view, 18, 1); View_SetGravity (view, grav_northwest); diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 86344170e..96fad8138 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -346,7 +346,6 @@ BI_Graphics_Init (progs_t *pr) Mod_Init (); R_Init (); Font_Init (); - Text_Init (); R_Progs_Init (pr); RUA_Game_Init (pr, thread->rua_security); From 61f61baf486f717cc802737342d2aeaad86110c5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Dec 2022 12:50:27 +0900 Subject: [PATCH 3310/3664] [client] Remove hud_href component I had missed this when adapting the ecs system for modular systems. --- include/client/hud.h | 1 - libs/client/hud.c | 4 ---- libs/client/sbar.c | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/include/client/hud.h b/include/client/hud.h index 6e84b082a..e67d1180b 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -31,7 +31,6 @@ struct view_s; enum { - hud_href, hud_update, hud_updateonce, hud_tile, diff --git a/libs/client/hud.c b/libs/client/hud.c index 11cc8c4aa..68ef57864 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -42,10 +42,6 @@ #include "client/hud.h" static const component_t hud_components[hud_comp_count] = { - [hud_href] = { - .size = sizeof (hierref_t), - .name = "href", - }, [hud_update] = { .size = sizeof (hud_update_f), .name = "update", diff --git a/libs/client/sbar.c b/libs/client/sbar.c index d131f2c76..9d6220d3f 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -2025,7 +2025,7 @@ href_cmp (const void *_a, const void *_b, void *arg) uint32_t enta = *(const uint32_t *)_a; uint32_t entb = *(const uint32_t *)_b; ecs_registry_t *reg = hud_viewsys.reg; - uint32_t href = hud_viewsys.base + hud_href; + uint32_t href = hud_viewsys.base + view_href; hierref_t *ref_a = Ent_GetComponent (enta, href, reg); hierref_t *ref_b = Ent_GetComponent (entb, href, reg); if (ref_a->hierarchy == ref_b->hierarchy) { From 24a85dbadcc133f7cb1cc88ea615f93caeaf58e3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Dec 2022 18:12:38 +0900 Subject: [PATCH 3311/3664] [ui] Add a component set for passage hierarchy refs While "set" is a tad strong (there's just the one component for now), I had missed the changes when adding ECS systems. Fixes the segfault at the end of demo1 (ie, when any center text is printed). --- include/QF/ui/passage.h | 14 ++++++++++++-- include/QF/ui/text.h | 2 -- include/client/hud.h | 1 + libs/client/hud.c | 8 +++++++- libs/client/sbar.c | 3 ++- libs/ruamoko/rua_gui.c | 6 +++++- libs/ui/passage.c | 20 ++++++++++++++------ libs/ui/test/test-passage.c | 25 ++++++++----------------- libs/ui/text.c | 4 ---- 9 files changed, 49 insertions(+), 34 deletions(-) diff --git a/include/QF/ui/passage.h b/include/QF/ui/passage.h index 13ff097ed..ef23dd2f4 100644 --- a/include/QF/ui/passage.h +++ b/include/QF/ui/passage.h @@ -30,11 +30,21 @@ #include +#include "QF/ecs.h" + /** \defgroup passage Text passages \ingroup utils */ ///@{ +enum { + passage_href, + + passage_comp_count +}; + +extern const component_t passage_components[passage_comp_count]; + enum { passage_type_text_obj, @@ -52,12 +62,12 @@ typedef struct passage_s { const char *text; ///< Not owned by passage struct ecs_registry_s *reg; ///< Owning ECS registry - uint32_t href_comp; ///< Component for passage hierarcy reference + uint32_t comp_base; ///< Passage base component struct hierarchy_s *hierarchy; ///< hierarchy of text objects } passage_t; void Passage_ParseText (passage_t *passage, const char *text); -passage_t *Passage_New (struct ecs_registry_s *reg, uint32_t href_comp); +passage_t *Passage_New (ecs_system_t passage_sys); void Passage_Delete (passage_t *passage); int Passage_IsSpace (const char *text) __attribute__((pure)); diff --git a/include/QF/ui/text.h b/include/QF/ui/text.h index c3817eb9b..33ea226e1 100644 --- a/include/QF/ui/text.h +++ b/include/QF/ui/text.h @@ -73,8 +73,6 @@ typedef struct glyphset_s { } glyphset_t; enum { - // passage text object hierarcies - text_href, // all the glyphs in a passage. Always on only the root view of the passage. text_passage_glyphs, // glyphs for a single text object diff --git a/include/client/hud.h b/include/client/hud.h index e67d1180b..c3b7c7388 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -56,6 +56,7 @@ typedef struct hud_subpic_s { extern struct ecs_system_s hud_system; extern struct ecs_system_s hud_viewsys; +extern struct ecs_system_s hud_psgsys; extern int hud_sb_lines; diff --git a/libs/client/hud.c b/libs/client/hud.c index 68ef57864..580ffe45a 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -35,6 +35,7 @@ #include "QF/screen.h" #include "QF/render.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/passage.h" #include "QF/ui/view.h" #include "compat.h" @@ -52,7 +53,7 @@ static const component_t hud_components[hud_comp_count] = { }, [hud_tile] = { .size = sizeof (byte), - .name = "pic", + .name = "tile", }, [hud_pic] = { .size = sizeof (qpic_t *), @@ -86,6 +87,7 @@ static const component_t hud_components[hud_comp_count] = { ecs_system_t hud_system; ecs_system_t hud_viewsys; +ecs_system_t hud_psgsys; int hud_sb_lines; int hud_sbar; @@ -263,10 +265,14 @@ HUD_Init (void) { hud_system.reg = ECS_NewRegistry (); hud_viewsys.reg = hud_system.reg; + hud_psgsys.reg = hud_system.reg; hud_system.base = ECS_RegisterComponents (hud_system.reg, hud_components, hud_comp_count); hud_viewsys.base = ECS_RegisterComponents (hud_system.reg, view_components, view_comp_count); + hud_psgsys.base = ECS_RegisterComponents (hud_system.reg, + passage_components, + passage_comp_count); ECS_CreateComponentPools (hud_system.reg); } diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 9d6220d3f..7711e9437 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -2554,7 +2554,8 @@ Sbar_Init (int *stats, float *item_gettime) sbar_stats = stats; sbar_item_gettime = item_gettime; - center_passage.reg = hud_viewsys.reg; + center_passage.reg = hud_psgsys.reg; + center_passage.comp_base = hud_psgsys.base; HUD_Init_Cvars (); Cvar_AddListener (Cvar_FindVar ("hud_sbar"), sbar_hud_sbar_f, 0); Cvar_AddListener (Cvar_FindVar ("hud_swap"), sbar_hud_swap_f, 0); diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index a0f027bd5..d9994d058 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -72,6 +72,7 @@ typedef struct { ecs_registry_t *reg; uint32_t text_base; uint32_t view_base; + uint32_t passage_base; } gui_resources_t; static rua_passage_t * @@ -230,7 +231,8 @@ bi (Font_Load) bi (Passage_New) { gui_resources_t *res = _res; - passage_t *passage = Passage_New (res->reg, res->text_base + text_href); + ecs_system_t passage_sys = { .reg = res->reg, .base = res->passage_base }; + passage_t *passage = Passage_New (passage_sys); R_INT (pr) = alloc_passage (res, passage); } @@ -457,5 +459,7 @@ RUA_GUI_Init (progs_t *pr, int secure) text_comp_count); res->view_base = ECS_RegisterComponents (res->reg, view_components, view_comp_count); + res->passage_base = ECS_RegisterComponents (res->reg, passage_components, + passage_comp_count); ECS_CreateComponentPools (res->reg); } diff --git a/libs/ui/passage.c b/libs/ui/passage.c index 163f7de2b..089823267 100644 --- a/libs/ui/passage.c +++ b/libs/ui/passage.c @@ -44,7 +44,14 @@ #include "QF/ui/passage.h" #include "QF/ui/view.h" -static const component_t passage_components[passage_type_count] = { +const component_t passage_components[passage_comp_count] = { + [passage_href] = { + .size = sizeof (hierref_t), + .name = "passage href", + }, +}; + +static const component_t passage_type_components[passage_type_count] = { [passage_type_text_obj] = { .size = sizeof (psg_text_t), .name = "Text", @@ -53,7 +60,7 @@ static const component_t passage_components[passage_type_count] = { static const hierarchy_type_t passage_type = { .num_components = passage_type_count, - .components = passage_components, + .components = passage_type_components, }; VISIBLE int @@ -129,7 +136,8 @@ Passage_ParseText (passage_t *passage, const char *text) } root_text.size = c - text; } - passage->hierarchy = Hierarchy_New (passage->reg, passage->href_comp, + passage->hierarchy = Hierarchy_New (passage->reg, + passage->comp_base + passage_href, &passage_type, 0); Hierarchy_Reserve (passage->hierarchy, 1 + num_paragraphs + num_text_objects); @@ -198,12 +206,12 @@ Passage_ParseText (passage_t *passage, const char *text) } VISIBLE passage_t * -Passage_New (ecs_registry_t *reg, uint32_t href_comp) +Passage_New (ecs_system_t passage_sys) { passage_t *passage = malloc (sizeof (passage_t)); passage->text = 0; - passage->reg = reg; - passage->href_comp = href_comp; + passage->reg = passage_sys.reg; + passage->comp_base = passage_sys.base; passage->hierarchy = 0; return passage; } diff --git a/libs/ui/test/test-passage.c b/libs/ui/test/test-passage.c index 1998cedeb..74c917160 100644 --- a/libs/ui/test/test-passage.c +++ b/libs/ui/test/test-passage.c @@ -7,18 +7,6 @@ #include "QF/ui/passage.h" #include "QF/ecs/component.h" -enum { - test_href, -}; - -static const component_t test_components[] = { - [test_href] = { - .size = sizeof (hierref_t), - .create = 0,//create_href, - .name = "href", - }, -}; - static const char test_text[] = { "Guarding the entrance to the Grendal " "Gorge is the Shadow Gate, a small keep " @@ -62,11 +50,14 @@ int main (void) { int ret = 0; - ecs_registry_t *registry = ECS_NewRegistry (); - ECS_RegisterComponents (registry, test_components, 1); - ECS_CreateComponentPools (registry); + ecs_system_t psg_sys = { + .reg = ECS_NewRegistry (), + .base = ECS_RegisterComponents (psg_sys.reg, passage_components, + passage_comp_count), + }; + ECS_CreateComponentPools (psg_sys.reg); - passage_t *passage = Passage_New (registry, test_href); + passage_t *passage = Passage_New (psg_sys); Passage_ParseText (passage, test_text); if (passage->hierarchy->childCount[0] != 3) { ret = 1; @@ -136,6 +127,6 @@ main (void) } Passage_Delete (passage); - ECS_DelRegistry (registry); + ECS_DelRegistry (psg_sys.reg); return ret; } diff --git a/libs/ui/text.c b/libs/ui/text.c index ee3c226b0..3970b45a2 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -58,10 +58,6 @@ text_features_destroy (void *_features) } const component_t text_components[text_comp_count] = { - [text_href] = { - .size = sizeof (hierref_t), - .name = "href", - }, [text_passage_glyphs] = { .size = sizeof (glyphset_t), .name = "passage glyphs", From d67b8cdf059f91743b68b85f8f899e7cf89afe66 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Dec 2022 21:11:21 +0900 Subject: [PATCH 3312/3664] [ecs] Add support for subpools Subpools are for grouping components by some criterion. Any component that has a rangeid callback will be grouped with other components that return the same render id. Note that the ordering of components within a group will be affected by adding a component into a group that comes before that group (or removing a component). Component pools can have multiple groups, added and removed dynamically, but removing a group should (currently) be done only when empty. --- include/QF/ecs.h | 22 ++- include/QF/ecs/component.h | 4 + include/QF/ecs/hierarchy.h | 2 +- include/QF/scene/scene.h | 3 - libs/ecs/Makemodule.am | 3 +- libs/ecs/ecs.c | 5 + libs/ecs/entity.c | 75 +++++++++- libs/ecs/subpool.c | 92 ++++++++++++ libs/ecs/test/Makemodule.am | 10 +- libs/ecs/test/test-subpools.c | 256 ++++++++++++++++++++++++++++++++++ 10 files changed, 460 insertions(+), 12 deletions(-) create mode 100644 libs/ecs/subpool.c create mode 100644 libs/ecs/test/test-subpools.c diff --git a/include/QF/ecs.h b/include/QF/ecs.h index cbdcf2852..540ea09d6 100644 --- a/include/QF/ecs.h +++ b/include/QF/ecs.h @@ -48,6 +48,7 @@ #define ENT_GROW 1024 #define COMP_GROW 128 +#define RANGE_GROW 32 #define ENT_IDBITS 20 #define nullent (~0u) @@ -61,14 +62,29 @@ typedef struct ecs_pool_s { typedef struct DARRAY_TYPE(component_t) componentset_t; +typedef struct ecs_range_s { + uint32_t end; +} ecs_range_t; + +typedef struct ecs_subpool_s { + ecs_range_t *ranges; + uint32_t *rangeids; + uint32_t *sorted; + uint32_t next; + uint32_t available; + uint32_t num_ranges; + uint32_t max_ranges; +} ecs_subpool_t; + typedef struct ecs_registry_s { + ecs_pool_t *comp_pools; uint32_t *entities; + ecs_subpool_t *subpools; uint32_t next; uint32_t available; uint32_t num_entities; uint32_t max_entities; componentset_t components; - ecs_pool_t *comp_pools; PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way } ecs_registry_t; @@ -101,6 +117,10 @@ uint32_t ECS_NewEntity (ecs_registry_t *registry); void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent); void ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component); +uint32_t ECS_NewSubpoolRange (ecs_registry_t *registry, uint32_t component); +void ECS_DelSubpoolRange (ecs_registry_t *registry, uint32_t component, + uint32_t id); + #undef ECSINLINE ///@} diff --git a/include/QF/ecs/component.h b/include/QF/ecs/component.h index 302338d9f..831418dac 100644 --- a/include/QF/ecs/component.h +++ b/include/QF/ecs/component.h @@ -42,10 +42,14 @@ */ ///@{ +struct ecs_registry_s; typedef struct component_s { size_t size; void (*create) (void *); void (*destroy) (void *); + // comp is the registry component id (base + system component id) + uint32_t (*rangeid) (struct ecs_registry_s *reg, uint32_t ent, + uint32_t comp); const char *name; } component_t; diff --git a/include/QF/ecs/hierarchy.h b/include/QF/ecs/hierarchy.h index d26e43a74..6036a8f91 100644 --- a/include/QF/ecs/hierarchy.h +++ b/include/QF/ecs/hierarchy.h @@ -51,7 +51,6 @@ typedef struct hierref_s { } hierref_t; typedef struct hierarchy_s { - struct ecs_registry_s *reg; uint32_t num_objects; uint32_t max_objects; uint32_t *ent; @@ -60,6 +59,7 @@ typedef struct hierarchy_s { uint32_t *parentIndex; const hierarchy_type_t *type; void **components; + struct ecs_registry_s *reg; uint32_t href_comp; } hierarchy_t; diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index a78adbf77..dd96576fc 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -49,9 +49,6 @@ enum scene_components { scene_old_origin, //XXX FIXME XXX should not be here scene_colormap, - scene_canvas, - scene_vref, //view hierarchy reference - //FIXME these should probably be private to the sw renderer (and in a //group, which needs to be implemented), but need to sort out a good //scheme for semi-dynamic components diff --git a/libs/ecs/Makemodule.am b/libs/ecs/Makemodule.am index ae9360bbc..4fc6b63f3 100644 --- a/libs/ecs/Makemodule.am +++ b/libs/ecs/Makemodule.am @@ -11,4 +11,5 @@ libs_ecs_libQFecs_la_SOURCES= \ libs/ecs/component.c \ libs/ecs/ecs.c \ libs/ecs/entity.c \ - libs/ecs/hierarchy.c + libs/ecs/hierarchy.c \ + libs/ecs/subpool.c diff --git a/libs/ecs/ecs.c b/libs/ecs/ecs.c index 4aed897c5..8f91107ea 100644 --- a/libs/ecs/ecs.c +++ b/libs/ecs/ecs.c @@ -51,7 +51,11 @@ ECS_DelRegistry (ecs_registry_t *registry) free (registry->comp_pools[i].sparse); free (registry->comp_pools[i].dense); free (registry->comp_pools[i].data); + + free (registry->subpools[i].ranges); + free (registry->subpools[i].rangeids); } + free (registry->subpools); free (registry->comp_pools); free (registry); } @@ -77,6 +81,7 @@ ECS_CreateComponentPools (ecs_registry_t *registry) registry->comp_pools[i].sparse = malloc (size); memset (registry->comp_pools[i].sparse, nullent, size); } + registry->subpools = calloc (count, sizeof (ecs_subpool_t)); } typedef struct { diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index 6039431c9..c7483dad8 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -34,10 +34,21 @@ #define IMPLEMENT_ECS_ENTITY_Funcs #include "QF/ecs.h" +#include "compat.h" + +static void swap_inds (uint32_t *a, uint32_t *b) +{ + uint32_t t = *a; + *a = *b; + *b = t; +} + VISIBLE void * Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) { ecs_pool_t *pool = ®istry->comp_pools[comp]; + ecs_subpool_t *subpool = ®istry->subpools[comp]; + component_t *c = ®istry->components.a[comp]; uint32_t id = Ent_Index (ent); uint32_t ind = pool->sparse[id]; if (ind >= pool->count || pool->dense[ind] != ent) { @@ -45,31 +56,85 @@ Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) pool->max_count += COMP_GROW; pool->dense = realloc (pool->dense, pool->max_count * sizeof (uint32_t)); - Component_ResizeArray (®istry->components.a[comp], &pool->data, - pool->max_count); + Component_ResizeArray (c, &pool->data, pool->max_count); } uint32_t ind = pool->count++; pool->sparse[id] = ind; pool->dense[ind] = ent; + uint32_t rind = subpool->num_ranges - subpool->available; + if (rind && c->rangeid) { + uint32_t rangeid = c->rangeid (registry, ent, comp); + uint32_t rangeind = subpool->sorted[Ent_Index (rangeid)]; + printf ("ent:%d rangeid:%d rangeind:%d\n", ent, rangeid, rangeind); + while (rind-- > rangeind) { + if (subpool->ranges[rind].end == ind) { + subpool->ranges[rind].end++; + continue; + } + uint32_t end = subpool->ranges[rind].end++; + Component_MoveElements (c, pool->data, ind, end, 1); + swap_inds (&pool->sparse[Ent_Index (pool->dense[end])], + &pool->sparse[Ent_Index (pool->dense[ind])]); + swap_inds (&pool->dense[ind], &pool->dense[end]); + ind = end; + } + } } return Ent_GetComponent (ent, comp, registry); } +static int +range_cmp (const void *_key, const void *_range, void *_subpool) +{ + const uint32_t *key = _key; + const ecs_range_t *range = _range; + ecs_subpool_t *subpool = _subpool; + + if (*key >= range->end) { + return -1; + } + if (range - subpool->ranges > 0) { + return *key >= range[-1].end ? 0 : -1; + } + return 0; +} + +static ecs_range_t * +find_range (ecs_subpool_t *subpool, uint32_t ind) +{ + return bsearch_r (&ind, subpool->ranges, + subpool->num_ranges - subpool->available, + sizeof (ecs_range_t), range_cmp, subpool); +} + VISIBLE void Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) { uint32_t id = Ent_Index (ent); ecs_pool_t *pool = ®istry->comp_pools[comp]; + ecs_subpool_t *subpool = ®istry->subpools[comp]; uint32_t ind = pool->sparse[id]; + component_t *c = ®istry->components.a[comp]; if (ind < pool->count && pool->dense[ind] == ent) { uint32_t last = pool->count - 1; - Component_DestroyElements (®istry->components.a[comp], pool->data, + Component_DestroyElements (c, pool->data, ind, 1); + if (subpool->num_ranges - subpool->available) { + uint32_t range_count = subpool->num_ranges - subpool->available; + ecs_range_t *range = find_range (subpool, ind); + while (range - subpool->ranges < range_count) { + uint32_t end = --range->end; + range++; + pool->sparse[Ent_Index (pool->dense[end])] = ind; + pool->dense[ind] = pool->dense[end]; + Component_MoveElements (c, pool->data, ind, end, 1); + ind = end; + } + } if (last > ind) { pool->sparse[Ent_Index (pool->dense[last])] = ind; pool->dense[ind] = pool->dense[last]; - Component_MoveElements (®istry->components.a[comp], pool->data, - ind, last, 1); + Component_MoveElements (c, pool->data, ind, last, 1); } pool->count--; pool->sparse[id] = nullent; diff --git a/libs/ecs/subpool.c b/libs/ecs/subpool.c new file mode 100644 index 000000000..ba229e805 --- /dev/null +++ b/libs/ecs/subpool.c @@ -0,0 +1,92 @@ +/* + subpool.c + + ECS subpool management + + Copyright (C) 2022 Bill Currke + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/sys.h" + +#include "QF/ecs.h" + +VISIBLE uint32_t +ECS_NewSubpoolRange (ecs_registry_t *registry, uint32_t component) +{ + ecs_subpool_t *subpool = ®istry->subpools[component]; + uint32_t id; + uint32_t num_ranges = subpool->num_ranges - subpool->available; + if (subpool->available) { + subpool->available--; + uint32_t next = subpool->next; + id = next | Ent_Generation (subpool->rangeids[next]); + subpool->next = Ent_Index (subpool->rangeids[next]); + subpool->rangeids[next] = id; + subpool->sorted[next] = num_ranges; + } else { + if (subpool->num_ranges == Ent_Index (nullent)) { + Sys_Error ("ECS_NewEntity: out of rangeids"); + } + if (subpool->num_ranges == subpool->max_ranges) { + subpool->max_ranges += RANGE_GROW; + size_t idsize = subpool->max_ranges * sizeof (uint32_t); + size_t rsize = subpool->max_ranges * sizeof (ecs_range_t); + subpool->rangeids = realloc (subpool->rangeids, idsize); + subpool->sorted = realloc (subpool->sorted, idsize); + subpool->ranges = realloc (subpool->ranges, rsize); + } + id = subpool->num_ranges++; + // id starts out with generation 0 + subpool->rangeids[id] = id; + subpool->sorted[id] = num_ranges; + } + uint32_t end = 0; + if (num_ranges) { + end = subpool->ranges[num_ranges - 1].end; + } + subpool->ranges[Ent_Index (id)] = (ecs_range_t) { + .end = end, + }; + return id; +} + +VISIBLE void +ECS_DelSubpoolRange (ecs_registry_t *registry, uint32_t component, uint32_t id) +{ + ecs_subpool_t *subpool = ®istry->subpools[component]; + uint32_t next = subpool->next | Ent_NextGen (Ent_Generation (id)); + uint32_t ind = Ent_Index (id); + uint32_t count = subpool->num_ranges - subpool->available; + subpool->rangeids[ind] = next; + subpool->next = ind; + subpool->available++; + memmove (subpool->ranges + ind, subpool->ranges + ind + 1, + (count - 1 - ind) * sizeof (ecs_range_t)); + for (uint32_t i = 0; i < count; i++) { + if (subpool->sorted[i] > ind) { + subpool->sorted[i]--; + } + } +} diff --git a/libs/ecs/test/Makemodule.am b/libs/ecs/test/Makemodule.am index 9d3479561..ab574491c 100644 --- a/libs/ecs/test/Makemodule.am +++ b/libs/ecs/test/Makemodule.am @@ -1,7 +1,8 @@ libs_ecs_tests = \ libs/ecs/test/test-components \ libs/ecs/test/test-hierarchy \ - libs/ecs/test/test-registry + libs/ecs/test/test-registry \ + libs/ecs/test/test-subpools TESTS += $(libs_ecs_tests) @@ -31,3 +32,10 @@ libs_ecs_test_test_registry_LDADD= \ $(libs_ecs_test_libs) libs_ecs_test_test_registry_DEPENDENCIES= \ $(libs_ecs_test_libs) + +libs_ecs_test_test_subpools_SOURCES= \ + libs/ecs/test/test-subpools.c +libs_ecs_test_test_subpools_LDADD= \ + $(libs_ecs_test_libs) +libs_ecs_test_test_subpools_DEPENDENCIES= \ + $(libs_ecs_test_libs) diff --git a/libs/ecs/test/test-subpools.c b/libs/ecs/test/test-subpools.c new file mode 100644 index 000000000..16fea08bb --- /dev/null +++ b/libs/ecs/test/test-subpools.c @@ -0,0 +1,256 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "QF/simd/types.h" +#include "QF/mathlib.h" +#include "QF/ecs.h" + +enum test_components { + test_subpool, + test_obj, + + test_num_components +}; + +static uint32_t +obj_rangeid (ecs_registry_t *reg, uint32_t ent, uint32_t comp) +{ + uint32_t sp_comp = comp - (test_obj - test_subpool); + return *(uint32_t *) Ent_GetComponent (ent, sp_comp, reg); +} + +static const component_t test_components[] = { + [test_subpool] = { + .size = sizeof (uint32_t), + .name = "subpool", + }, + [test_obj] = { + .size = sizeof (uint32_t), + .name = "obj", + .rangeid = obj_rangeid, + }, +}; + +static void +dump_sp_ids (ecs_registry_t *reg, uint32_t comp) +{ + ecs_pool_t *pool = ®->comp_pools[comp]; + uint32_t *ent = pool->dense; + uint32_t *id = pool->data; + + for (uint32_t i = 0; i < pool->count; i++) { + printf ("ent[%d]: %d, %d\n", i, ent[i], id[i]); + } +} + +static int +check_subpool_ranges (ecs_subpool_t *subpool, uint32_t *expect) +{ + uint32_t count = subpool->num_ranges - subpool->available; + ecs_range_t *range = subpool->ranges; + + while (count--) { + ecs_range_t *r = range++; + uint32_t e = *expect++; + printf ("%d: %d %d\n", (int)(r - subpool->ranges), r->end, e); + if (r->end != e++) { + return 1; + } + } + return 0; +} + +static int +check_obj_comps (ecs_registry_t *reg, uint32_t comp, uint32_t *expect) +{ + ecs_pool_t *pool = ®->comp_pools[comp]; + uint32_t *val = pool->data; + int fail = 0; + + for (uint32_t i = 0; i < pool->count; i++) { + printf ("val[%d]: %d %d\n", i, val[i], expect[i]); + if (val[i] != expect[i]) { + fail = 1; + } + } + return fail; +} + +int +main (void) +{ + ecs_registry_t *reg = ECS_NewRegistry (); + uint32_t base = ECS_RegisterComponents (reg, test_components, + test_num_components); + ECS_CreateComponentPools (reg); + + uint32_t sp1 = ECS_NewSubpoolRange (reg, base + test_obj); + uint32_t sp2 = ECS_NewSubpoolRange (reg, base + test_obj); + uint32_t sp3 = ECS_NewSubpoolRange (reg, base + test_obj); + + printf ("%d %d %d\n", sp1, sp2, sp3); + if (reg->subpools[base + test_subpool].num_ranges != 0 + || reg->subpools[base + test_subpool].available != 0) { + printf ("subpool not 0 count: %d %d\n", + reg->subpools[base + test_subpool].num_ranges, + reg->subpools[base + test_subpool].available); + return 1; + } + if (reg->subpools[base + test_obj].num_ranges != 3 + || reg->subpools[base + test_obj].available != 0) { + printf ("obj not 3 count: %d %d\n", + reg->subpools[base + test_obj].num_ranges, + reg->subpools[base + test_obj].available); + return 1; + } + for (uint32_t i = 0; i < reg->subpools[base + test_obj].num_ranges; i++) { + if (reg->subpools[base + test_obj].ranges[i].end != 0) { + printf ("end %d not 0 count: %d\n", i, + reg->subpools[base + test_obj].ranges[i].end); + return 1; + } + } + + uint32_t enta = ECS_NewEntity (reg); + uint32_t entb = ECS_NewEntity (reg); + uint32_t entc = ECS_NewEntity (reg); + uint32_t entd = ECS_NewEntity (reg); + uint32_t ente = ECS_NewEntity (reg); + uint32_t entf = ECS_NewEntity (reg); + uint32_t entg = ECS_NewEntity (reg); + uint32_t enth = ECS_NewEntity (reg); + + Ent_SetComponent (enta, base + test_subpool, reg, &sp1); + Ent_SetComponent (entb, base + test_subpool, reg, &sp1); + Ent_SetComponent (entc, base + test_subpool, reg, &sp2); + Ent_SetComponent (entd, base + test_subpool, reg, &sp3); + Ent_SetComponent (ente, base + test_subpool, reg, &sp3); + Ent_SetComponent (entf, base + test_subpool, reg, &sp2); + Ent_SetComponent (entg, base + test_subpool, reg, &sp2); + Ent_SetComponent (enth, base + test_subpool, reg, &sp1); + + dump_sp_ids (reg, base + test_subpool); + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 0, 0, 0 })) { + printf ("oops\n"); + return 1; + } + + uint32_t val = 0; + Ent_SetComponent (enta, base + test_obj, reg, &val); val++; + Ent_SetComponent (entb, base + test_obj, reg, &val); val++; + Ent_SetComponent (entc, base + test_obj, reg, &val); val++; + Ent_SetComponent (entd, base + test_obj, reg, &val); val++; + Ent_SetComponent (ente, base + test_obj, reg, &val); val++; + Ent_SetComponent (entf, base + test_obj, reg, &val); val++; + Ent_SetComponent (entg, base + test_obj, reg, &val); val++; + Ent_SetComponent (enth, base + test_obj, reg, &val); val++; + + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 3, 6, 8 })) { + printf ("oops\n"); + return 1; + } + if (check_obj_comps (reg, base + test_obj, + (uint32_t[]) { 0, 1, 7, 5, 6, 2, 4, 3 })) { + printf ("oops\n"); + return 1; + } + + Ent_RemoveComponent (entb, base + test_obj, reg); + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 2, 5, 7 })) { + printf ("oops\n"); + return 1; + } + if (check_obj_comps (reg, base + test_obj, + (uint32_t[]) { 0, 7, 2, 5, 6, 3, 4 })) { + printf ("oops\n"); + return 1; + } + + Ent_RemoveComponent (entd, base + test_obj, reg); + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 2, 5, 6 })) { + printf ("oops\n"); + return 1; + } + if (check_obj_comps (reg, base + test_obj, + (uint32_t[]) { 0, 7, 2, 5, 6, 4 })) { + printf ("oops\n"); + return 1; + } + + Ent_RemoveComponent (ente, base + test_obj, reg); + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 2, 5, 5 })) { + printf ("oops\n"); + return 1; + } + if (check_obj_comps (reg, base + test_obj, + (uint32_t[]) { 0, 7, 2, 5, 6 })) { + printf ("oops\n"); + return 1; + } + + Ent_SetComponent (entd, base + test_obj, reg, &val); val++; + Ent_SetComponent (ente, base + test_obj, reg, &val); val++; + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 2, 5, 7 })) { + printf ("oops\n"); + return 1; + } + if (check_obj_comps (reg, base + test_obj, + (uint32_t[]) { 0, 7, 2, 5, 6, 8, 9 })) { + printf ("oops\n"); + return 1; + } + + Ent_RemoveComponent (entc, base + test_obj, reg); + Ent_RemoveComponent (entf, base + test_obj, reg); + Ent_RemoveComponent (entg, base + test_obj, reg); + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 2, 2, 4 })) { + printf ("oops\n"); + return 1; + } + if (check_obj_comps (reg, base + test_obj, + (uint32_t[]) { 0, 7, 9, 8 })) { + printf ("oops\n"); + return 1; + } + + ECS_DelSubpoolRange (reg, base + test_obj, sp2); + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 2, 4 })) { + printf ("oops\n"); + return 1; + } + + sp2 = ECS_NewSubpoolRange (reg, base + test_obj); + printf ("sp2: %d\n", sp2); + Ent_SetComponent (entc, base + test_subpool, reg, &sp2); + Ent_SetComponent (entf, base + test_subpool, reg, &sp2); + Ent_SetComponent (entg, base + test_subpool, reg, &sp2); + Ent_SetComponent (entc, base + test_obj, reg, &val); val++; + Ent_SetComponent (entf, base + test_obj, reg, &val); val++; + Ent_SetComponent (entg, base + test_obj, reg, &val); val++; + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 2, 4, 7})) { + printf ("oops\n"); + return 1; + } + if (check_obj_comps (reg, base + test_obj, + (uint32_t[]) { 0, 7, 9, 8, 10, 11, 12 })) { + printf ("oops\n"); + return 1; + } + + ECS_DelRegistry (reg); + return 0; +} From 34930ba195b86711ab20f5bb32487341edb98518 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Dec 2022 10:59:26 +0900 Subject: [PATCH 3313/3664] [ecs] Fix a bit of white space --- libs/ecs/entity.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index c7483dad8..e86898d59 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -117,8 +117,7 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) component_t *c = ®istry->components.a[comp]; if (ind < pool->count && pool->dense[ind] == ent) { uint32_t last = pool->count - 1; - Component_DestroyElements (c, pool->data, - ind, 1); + Component_DestroyElements (c, pool->data, ind, 1); if (subpool->num_ranges - subpool->available) { uint32_t range_count = subpool->num_ranges - subpool->available; ecs_range_t *range = find_range (subpool, ind); From 3a2877dd9a28a88c3abc926ea1cb4cb1ebfbcd28 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Dec 2022 17:56:08 +0900 Subject: [PATCH 3314/3664] [ecs] Adjust subpool range type to return start,end I found I needed the subrange start as well as the end, but I liked that the subpools themselves used only the end of the range, so switching to just a unint32_t for the value and adding a function to return a tuple made sense. I had kept the struct because I thought I might want to store additional information (eg, the entity "owning" the subpool), but found that I didn't need such information as the systems using subpools that way would have access to the entity by other means. Interestingly, the change found a bug in subpool creation: I really don't know why things worked before, but they work better now :) --- include/QF/ecs.h | 31 ++++++++++++++++++++++++++++--- libs/ecs/entity.c | 20 ++++++++++---------- libs/ecs/subpool.c | 6 ++---- libs/ecs/test/test-subpools.c | 19 ++++++++++++------- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/include/QF/ecs.h b/include/QF/ecs.h index 540ea09d6..dc082c016 100644 --- a/include/QF/ecs.h +++ b/include/QF/ecs.h @@ -63,13 +63,14 @@ typedef struct ecs_pool_s { typedef struct DARRAY_TYPE(component_t) componentset_t; typedef struct ecs_range_s { + uint32_t start; uint32_t end; } ecs_range_t; typedef struct ecs_subpool_s { - ecs_range_t *ranges; uint32_t *rangeids; uint32_t *sorted; + uint32_t *ranges; uint32_t next; uint32_t available; uint32_t num_ranges; @@ -98,6 +99,10 @@ typedef struct ecs_system_s { uint32_t base; } ecs_system_t; +#include "QF/ecs/entity.h" + +#define ECSINLINE GNU89INLINE inline + ecs_registry_t *ECS_NewRegistry (void); void ECS_DelRegistry (ecs_registry_t *registry); uint32_t ECS_RegisterComponents (ecs_registry_t *registry, @@ -120,11 +125,31 @@ void ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component); uint32_t ECS_NewSubpoolRange (ecs_registry_t *registry, uint32_t component); void ECS_DelSubpoolRange (ecs_registry_t *registry, uint32_t component, uint32_t id); +ECSINLINE ecs_range_t ECS_GetSubpoolRange (ecs_registry_t *registry, + uint32_t component, uint32_t id); + +#undef ECSINLINE +#ifndef IMPLEMENT_ECS_Funcs +#define ECSINLINE GNU89INLINE inline +#else +#define ECSINLINE VISIBLE +#endif + +ECSINLINE +ecs_range_t +ECS_GetSubpoolRange (ecs_registry_t *registry, uint32_t component, uint32_t id) +{ + ecs_subpool_t *subpool = ®istry->subpools[component]; + uint32_t ind = subpool->sorted[Ent_Index (id)]; + ecs_range_t range = { + .start = ind ? subpool->ranges[ind - 1] : 0, + .end = subpool->ranges[ind], + }; + return range; +} #undef ECSINLINE ///@} -#include "QF/ecs/entity.h" - #endif//__QF_ecs_h diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index e86898d59..1f7892c37 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -67,11 +67,11 @@ Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) uint32_t rangeind = subpool->sorted[Ent_Index (rangeid)]; printf ("ent:%d rangeid:%d rangeind:%d\n", ent, rangeid, rangeind); while (rind-- > rangeind) { - if (subpool->ranges[rind].end == ind) { - subpool->ranges[rind].end++; + if (subpool->ranges[rind] == ind) { + subpool->ranges[rind]++; continue; } - uint32_t end = subpool->ranges[rind].end++; + uint32_t end = subpool->ranges[rind]++; Component_MoveElements (c, pool->data, ind, end, 1); swap_inds (&pool->sparse[Ent_Index (pool->dense[end])], &pool->sparse[Ent_Index (pool->dense[ind])]); @@ -87,24 +87,24 @@ static int range_cmp (const void *_key, const void *_range, void *_subpool) { const uint32_t *key = _key; - const ecs_range_t *range = _range; + const uint32_t *range = _range; ecs_subpool_t *subpool = _subpool; - if (*key >= range->end) { + if (*key >= *range) { return -1; } if (range - subpool->ranges > 0) { - return *key >= range[-1].end ? 0 : -1; + return *key >= range[-1] ? 0 : -1; } return 0; } -static ecs_range_t * +static uint32_t * find_range (ecs_subpool_t *subpool, uint32_t ind) { return bsearch_r (&ind, subpool->ranges, subpool->num_ranges - subpool->available, - sizeof (ecs_range_t), range_cmp, subpool); + sizeof (uint32_t), range_cmp, subpool); } VISIBLE void @@ -120,9 +120,9 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) Component_DestroyElements (c, pool->data, ind, 1); if (subpool->num_ranges - subpool->available) { uint32_t range_count = subpool->num_ranges - subpool->available; - ecs_range_t *range = find_range (subpool, ind); + uint32_t *range = find_range (subpool, ind); while (range - subpool->ranges < range_count) { - uint32_t end = --range->end; + uint32_t end = --*range; range++; pool->sparse[Ent_Index (pool->dense[end])] = ind; pool->dense[ind] = pool->dense[end]; diff --git a/libs/ecs/subpool.c b/libs/ecs/subpool.c index ba229e805..8da0b6f6a 100644 --- a/libs/ecs/subpool.c +++ b/libs/ecs/subpool.c @@ -64,11 +64,9 @@ ECS_NewSubpoolRange (ecs_registry_t *registry, uint32_t component) } uint32_t end = 0; if (num_ranges) { - end = subpool->ranges[num_ranges - 1].end; + end = subpool->ranges[num_ranges - 1]; } - subpool->ranges[Ent_Index (id)] = (ecs_range_t) { - .end = end, - }; + subpool->ranges[subpool->sorted[Ent_Index (id)]] = end; return id; } diff --git a/libs/ecs/test/test-subpools.c b/libs/ecs/test/test-subpools.c index 16fea08bb..9e51d31b7 100644 --- a/libs/ecs/test/test-subpools.c +++ b/libs/ecs/test/test-subpools.c @@ -52,13 +52,13 @@ static int check_subpool_ranges (ecs_subpool_t *subpool, uint32_t *expect) { uint32_t count = subpool->num_ranges - subpool->available; - ecs_range_t *range = subpool->ranges; + uint32_t *range = subpool->ranges; while (count--) { - ecs_range_t *r = range++; - uint32_t e = *expect++; - printf ("%d: %d %d\n", (int)(r - subpool->ranges), r->end, e); - if (r->end != e++) { + uint32_t *r = range++; + uint32_t e = *expect++; + printf ("%d: %d %d\n", (int)(r - subpool->ranges), *r, e); + if (*r != e++) { return 1; } } @@ -109,9 +109,9 @@ main (void) return 1; } for (uint32_t i = 0; i < reg->subpools[base + test_obj].num_ranges; i++) { - if (reg->subpools[base + test_obj].ranges[i].end != 0) { + if (reg->subpools[base + test_obj].ranges[i] != 0) { printf ("end %d not 0 count: %d\n", i, - reg->subpools[base + test_obj].ranges[i].end); + reg->subpools[base + test_obj].ranges[i]); return 1; } } @@ -234,6 +234,11 @@ main (void) sp2 = ECS_NewSubpoolRange (reg, base + test_obj); printf ("sp2: %d\n", sp2); + if (check_subpool_ranges (®->subpools[base + test_obj], + (uint32_t[]) { 2, 4, 4 })) { + printf ("oops\n"); + return 1; + } Ent_SetComponent (entc, base + test_subpool, reg, &sp2); Ent_SetComponent (entf, base + test_subpool, reg, &sp2); Ent_SetComponent (entg, base + test_subpool, reg, &sp2); From 6decbd18c45d29ef85de57ec39e6a1564d068b56 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Dec 2022 19:45:48 +0900 Subject: [PATCH 3315/3664] [ui] Add a canvas system This is the beginning of supporting 2d rendering in 3d space. The idea is that a canvas can be in 2d orthographic space (not attached to any entity with a 3d transform), or in 3d perspective space (attached to an entity with a 3d transform, either as a child of the camera, or of some object in 3d space). It will replace the current HUD code when it's working. --- include/QF/Makemodule.am | 3 + include/QF/ui/canvas.h | 87 ++++++++++ libs/ui/Makemodule.am | 1 + libs/ui/canvas.c | 353 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 444 insertions(+) create mode 100644 include/QF/ui/canvas.h create mode 100644 libs/ui/canvas.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 07b2d956e..8957a39d8 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -170,8 +170,11 @@ include_qf_simd = \ include/QF/simd/vec4i.h include_qf_ui = \ + include/QF/ui/canvas.h \ + include/QF/ui/font.h \ include/QF/ui/inputline.h \ include/QF/ui/passage.h \ + include/QF/ui/text.h \ include/QF/ui/txtbuffer.h \ include/QF/ui/view.h \ include/QF/ui/vrect.h diff --git a/include/QF/ui/canvas.h b/include/QF/ui/canvas.h new file mode 100644 index 000000000..dd63d3699 --- /dev/null +++ b/include/QF/ui/canvas.h @@ -0,0 +1,87 @@ +/* + canvas.h + + Integration of 2d and 3d objects + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/12/12 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_scene_canvas_h +#define __QF_scene_canvas_h + +#include "QF/ecs.h" + +enum { + canvas_update, + canvas_updateonce, + canvas_tile, + canvas_pic, + canvas_subpic, + canvas_cachepic, + canvas_fill, + canvas_charbuff, + canvas_func, + canvas_outline, + + // last so deleting an entity removes the grouped components first + canvas_canvas, + + canvas_comp_count +}; + +typedef struct canvas_s { + ecs_registry_t *reg; + uint32_t ent; + uint32_t base; + uint32_t text_base; + uint32_t view_base; + uint32_t range[canvas_comp_count]; +} canvas_t; + +extern const struct component_s canvas_components[canvas_comp_count]; + +typedef struct canvas_system_s { + ecs_registry_t *reg; + uint32_t text_base; + uint32_t view_base; +} canvas_system_t; + +struct view_s; +struct view_pos_s; + +typedef void (*canvas_update_f) (struct view_s); +typedef void (*canvas_func_f) (struct view_pos_s, struct view_pos_s); + +typedef struct canvas_subpic_s { + struct qpic_s *pic; + uint32_t x, y; + uint32_t w, h; +} canvas_subpic_t; + +void Canvas_AddToEntity (ecs_system_t canvas_sys, uint32_t text_base, + uint32_t view_base, uint32_t ent); +void Canvas_Draw (uint32_t canvas_base, canvas_system_t canvas_sys); + +#endif//__QF_scene_canvas_h diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am index 95c6c8c8a..a4e677aee 100644 --- a/libs/ui/Makemodule.am +++ b/libs/ui/Makemodule.am @@ -15,6 +15,7 @@ libs_ui_libQFgui_la_LDFLAGS= $(lib_ldflags) libs_ui_libQFgui_la_LIBADD= $(gui_deps) $(ui_deps) libs_ui_libQFgui_la_DEPENDENCIES= $(gui_deps) $(ui_deps) libs_ui_libQFgui_la_SOURCES= \ + libs/ui/canvas.c \ libs/ui/font.c \ libs/ui/text.c diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c new file mode 100644 index 000000000..2c8cbe7bb --- /dev/null +++ b/libs/ui/canvas.c @@ -0,0 +1,353 @@ +/* + canvas.c + + Integration of 2d and 3d objects + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/12/12 + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/ui/canvas.h" +#include "QF/ui/text.h" +#include "QF/ui/view.h" + +#include "QF/plugin/vid_render.h" + +#define canvas_rangeid(c) \ +static uint32_t \ +canvas_##c##_rangeid (ecs_registry_t *reg, uint32_t ent, uint32_t comp) \ +{ \ + comp += canvas_canvas - canvas_##c; \ + canvas_t *canvas = Ent_GetComponent (ent, comp, reg); \ + return canvas->range[canvas_##c]; \ +} +canvas_rangeid(update) +canvas_rangeid(updateonce) +canvas_rangeid(tile) +canvas_rangeid(pic) +canvas_rangeid(subpic) +canvas_rangeid(cachepic) +canvas_rangeid(fill) +canvas_rangeid(charbuff) +canvas_rangeid(func) +canvas_rangeid(outline) +#undef canvas_rangeid + +static void +canvas_canvas_destroy (void *_canvas) +{ +} + +const component_t canvas_components[canvas_comp_count] = { + [canvas_update] = { + .size = sizeof (canvas_update_f), + .name = "update", + .rangeid = canvas_update_rangeid, + }, + [canvas_updateonce] = { + .size = sizeof (canvas_update_f), + .name = "updateonce", + .rangeid = canvas_updateonce_rangeid, + }, + [canvas_tile] = { + .size = sizeof (byte), + .name = "pic", + .rangeid = canvas_tile_rangeid, + }, + [canvas_pic] = { + .size = sizeof (qpic_t *), + .name = "pic", + .rangeid = canvas_pic_rangeid, + }, + [canvas_subpic] = { + .size = sizeof (canvas_subpic_t), + .name = "subpic", + .rangeid = canvas_subpic_rangeid, + }, + [canvas_cachepic] = { + .size = sizeof (const char *), + .name = "cachepic", + .rangeid = canvas_cachepic_rangeid, + }, + [canvas_fill] = { + .size = sizeof (byte), + .name = "fill", + .rangeid = canvas_fill_rangeid, + }, + [canvas_charbuff] = { + .size = sizeof (draw_charbuffer_t *), + .name = "charbuffer", + .rangeid = canvas_charbuff_rangeid, + }, + [canvas_func] = { + .size = sizeof (canvas_func_f), + .name = "func", + .rangeid = canvas_func_rangeid, + }, + [canvas_outline] = { + .size = sizeof (byte), + .name = "outline", + .rangeid = canvas_outline_rangeid, + }, + [canvas_canvas] = { + .size = sizeof (canvas_t), + .name = "canvas", + .destroy = canvas_canvas_destroy, + }, +}; + +typedef void (*canvas_sysfunc_f) (canvas_system_t *canvas_sys, + ecs_pool_t *pool, ecs_range_t range); +static void +draw_update (canvas_system_t *canvas_sys, ecs_pool_t *pool, ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + __auto_type func = (canvas_update_f *) pool->data + range.start; + while (count-- > 0) { + (*func++) (View_FromEntity (viewsys, *ent++)); + } +} + +static void +draw_updateonce (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + draw_update (canvas_sys, pool, range); + pool->count = 0;//XXX FIXME hmm, what to do with ranges +} + +static void +draw_tile_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + while (count-- > 0) { + view_t view = View_FromEntity (viewsys, *ent++); + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + view_pos_t len = View_GetLen (view); + r_funcs->Draw_TileClear (pos.x, pos.y, len.x, len.y); + } + } +} + +static void +draw_pic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + __auto_type pic = (qpic_t **) pool->data + range.start; + while (count-- > 0) { + view_t view = View_FromEntity (viewsys, *ent++); + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + r_funcs->Draw_Pic (pos.x, pos.y, *pic); + } + pic++; + } +} + +static void +draw_subpic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + __auto_type subpic = (canvas_subpic_t *) pool->data + range.start; + while (count-- > 0) { + view_t view = View_FromEntity (viewsys, *ent++); + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + r_funcs->Draw_SubPic (pos.x, pos.y, subpic->pic, + subpic->x, subpic->y, subpic->w, subpic->h); + } + subpic++; + } +} + +static void +draw_cachepic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + __auto_type name = (const char **) pool->data + range.start; + while (count-- > 0) { + view_t view = View_FromEntity (viewsys, *ent++); + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + qpic_t *pic = r_funcs->Draw_CachePic (*name, 1); + r_funcs->Draw_Pic (pos.x, pos.y, pic); + } + name++; + } +} + +static void +draw_fill_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + __auto_type fill = (byte *) pool->data + range.start; + while (count-- > 0) { + view_t view = View_FromEntity (viewsys, *ent++); + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + view_pos_t len = View_GetLen (view); + r_funcs->Draw_Fill (pos.x, pos.y, len.x, len.y, *fill); + } + fill++; + } +} + +static void +draw_charbuff_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + __auto_type charbuff = (draw_charbuffer_t **) pool->data + range.start; + while (count-- > 0) { + view_t view = View_FromEntity (viewsys, *ent++); + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + r_funcs->Draw_CharBuffer (pos.x, pos.y, *charbuff); + } + charbuff++; + } +} + +static void +draw_func_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + __auto_type func = (canvas_func_f *) pool->data + range.start; + while (count-- > 0) { + view_t view = View_FromEntity (viewsys, *ent++); + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + view_pos_t len = View_GetLen (view); + (*func) (pos, len); + } + func++; + } +} + +static void +draw_outline_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + __auto_type col = (byte *) pool->data + range.start; + __auto_type line = r_funcs->Draw_Line; + while (count-- > 0) { + view_t view = View_FromEntity (viewsys, *ent++); + byte c = *col++; + if (View_GetVisible (view)) { + view_pos_t p = View_GetAbs (view); + view_pos_t l = View_GetLen (view); + view_pos_t q = { p.x + l.x - 1, p.y + l.y - 1 }; + line (p.x, p.y, q.x, p.y, c); + line (p.x, q.y, q.x, q.y, c); + line (p.x, p.y, p.x, q.y, c); + line (q.x, p.y, q.x, q.y, c); + } + } +} + +void +Canvas_Draw (uint32_t canvas_base, canvas_system_t canvas_sys) +{ + static canvas_sysfunc_f draw_func[canvas_comp_count] = { + [canvas_update] = draw_update, + [canvas_updateonce] = draw_updateonce, + [canvas_tile] = draw_tile_views, + [canvas_pic] = draw_pic_views, + [canvas_subpic] = draw_subpic_views, + [canvas_cachepic] = draw_cachepic_views, + [canvas_fill] = draw_fill_views, + [canvas_charbuff] = draw_charbuff_views, + [canvas_func] = draw_func_views, + [canvas_outline] = draw_outline_views, + }; + + uint32_t comp = canvas_base + canvas_canvas; + ecs_pool_t *pool = &canvas_sys.reg->comp_pools[comp]; + uint32_t count = pool->count; + //uint32_t *entities = pool->dense; + __auto_type canvases = (canvas_t *) pool->data; + + while (count-- > 0) { + canvas_t *canvas = canvases++; + //uint32_t ent = *entities++; + + for (int i = 0; i < canvas_comp_count; i++) { + uint32_t c = canvas_base + i; + uint32_t rid = canvas->range[i]; + ecs_range_t range = ECS_GetSubpoolRange (canvas_sys.reg, c, rid); + if (draw_func[i]) { + ecs_pool_t *pool = &canvas_sys.reg->comp_pools[c]; + draw_func[i] (&canvas_sys, pool, range); + } + } + } + for (int i = 0; i < canvas_comp_count; i++) { + } +} + +void +Canvas_AddToEntity (ecs_system_t canvas_sys, uint32_t text_base, + uint32_t view_base, uint32_t ent) +{ + canvas_t canvas = { + .reg = canvas_sys.reg, + .ent = ent, + .text_base = text_base, + .view_base = view_base, + }; + for (uint32_t i = 0; i < canvas_comp_count; i++) { + canvas.range[i] = ECS_NewSubpoolRange (canvas.reg, canvas.base + i); + } + Ent_SetComponent (ent, canvas.base + canvas_canvas, canvas.reg, &canvas); + View_AddToEntity (ent, (ecs_system_t) { canvas.reg, view_base }, nullview); +} From b5912bba9b49a1387380ef5b5e5c2f99d4c27b27 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Dec 2022 01:54:10 +0900 Subject: [PATCH 3316/3664] [ui] Clean up the canvas component It turns out only the range ids are needed in the canvas component at this stage, and moving the canvas system base into canvas_system_t makes sense. --- include/QF/ui/canvas.h | 11 +++-------- libs/ui/canvas.c | 28 ++++++++++++---------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/include/QF/ui/canvas.h b/include/QF/ui/canvas.h index dd63d3699..e6ab30dc3 100644 --- a/include/QF/ui/canvas.h +++ b/include/QF/ui/canvas.h @@ -52,11 +52,6 @@ enum { }; typedef struct canvas_s { - ecs_registry_t *reg; - uint32_t ent; - uint32_t base; - uint32_t text_base; - uint32_t view_base; uint32_t range[canvas_comp_count]; } canvas_t; @@ -64,6 +59,7 @@ extern const struct component_s canvas_components[canvas_comp_count]; typedef struct canvas_system_s { ecs_registry_t *reg; + uint32_t base; uint32_t text_base; uint32_t view_base; } canvas_system_t; @@ -80,8 +76,7 @@ typedef struct canvas_subpic_s { uint32_t w, h; } canvas_subpic_t; -void Canvas_AddToEntity (ecs_system_t canvas_sys, uint32_t text_base, - uint32_t view_base, uint32_t ent); -void Canvas_Draw (uint32_t canvas_base, canvas_system_t canvas_sys); +void Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent); +void Canvas_Draw (canvas_system_t canvas_sys); #endif//__QF_scene_canvas_h diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index 2c8cbe7bb..84cc40b63 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -296,7 +296,7 @@ draw_outline_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, } void -Canvas_Draw (uint32_t canvas_base, canvas_system_t canvas_sys) +Canvas_Draw (canvas_system_t canvas_sys) { static canvas_sysfunc_f draw_func[canvas_comp_count] = { [canvas_update] = draw_update, @@ -311,7 +311,7 @@ Canvas_Draw (uint32_t canvas_base, canvas_system_t canvas_sys) [canvas_outline] = draw_outline_views, }; - uint32_t comp = canvas_base + canvas_canvas; + uint32_t comp = canvas_sys.base + canvas_canvas; ecs_pool_t *pool = &canvas_sys.reg->comp_pools[comp]; uint32_t count = pool->count; //uint32_t *entities = pool->dense; @@ -322,7 +322,7 @@ Canvas_Draw (uint32_t canvas_base, canvas_system_t canvas_sys) //uint32_t ent = *entities++; for (int i = 0; i < canvas_comp_count; i++) { - uint32_t c = canvas_base + i; + uint32_t c = canvas_sys.base + i; uint32_t rid = canvas->range[i]; ecs_range_t range = ECS_GetSubpoolRange (canvas_sys.reg, c, rid); if (draw_func[i]) { @@ -331,23 +331,19 @@ Canvas_Draw (uint32_t canvas_base, canvas_system_t canvas_sys) } } } - for (int i = 0; i < canvas_comp_count; i++) { - } } void -Canvas_AddToEntity (ecs_system_t canvas_sys, uint32_t text_base, - uint32_t view_base, uint32_t ent) +Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent) { - canvas_t canvas = { - .reg = canvas_sys.reg, - .ent = ent, - .text_base = text_base, - .view_base = view_base, - }; + canvas_t canvas = { }; for (uint32_t i = 0; i < canvas_comp_count; i++) { - canvas.range[i] = ECS_NewSubpoolRange (canvas.reg, canvas.base + i); + canvas.range[i] = ECS_NewSubpoolRange (canvas_sys.reg, + canvas_sys.base + i); } - Ent_SetComponent (ent, canvas.base + canvas_canvas, canvas.reg, &canvas); - View_AddToEntity (ent, (ecs_system_t) { canvas.reg, view_base }, nullview); + Ent_SetComponent (ent, canvas_sys.base + canvas_canvas, canvas_sys.reg, + &canvas); + View_AddToEntity (ent, + (ecs_system_t) { canvas_sys.reg, canvas_sys.view_base }, + nullview); } From 5477749280c07944e6e0e2aa29486f65a1c5f41b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Dec 2022 12:47:28 +0900 Subject: [PATCH 3317/3664] [vulkan] Use correct input assembly for sprite depth I hadn't noticed the problem until playing with early fragment tests for the sprite fragment shaders, but passing data that expects triangle strips to a pipeline that expects triangle lists doesn't work too well when drawing quads. --- libs/video/renderer/vulkan/pl_quake_def.plist | 2 +- libs/video/renderer/vulkan/shader/sprite_gbuf.frag | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 56c5ac2c3..e841070f3 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -1155,7 +1155,7 @@ }, ); vertexInput = $properties.vertexInput.index_only; - inputAssembly = $properties.inputAssembly.alias; + inputAssembly = $properties.inputAssembly.sprite; layout = sprite_layout; }; twod = { diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag index a890ca94d..29d9b65c9 100644 --- a/libs/video/renderer/vulkan/shader/sprite_gbuf.frag +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.frag @@ -14,6 +14,8 @@ layout (location = 0) in vec2 st; layout (location = 1) in vec4 position; layout (location = 2) in vec3 normal; +layout(early_fragment_tests) in; + layout (location = 0) out vec4 frag_color; layout (location = 1) out vec4 frag_emission; layout (location = 2) out vec4 frag_normal; From 70e93bb7e86a62d054c76cb604eae233a6073ca2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 3 Jan 2023 20:20:02 +0900 Subject: [PATCH 3318/3664] [ruamoko] Advance glyphset when working through the pool It seems to help if the right font data is used when rendering glyphs. Fixes use of multiple fonts in different passages. --- libs/ruamoko/rua_gui.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index d9994d058..3b404071b 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -332,21 +332,21 @@ bi (Text_Draw) uint32_t *ent = pool->dense; glyphset_t *glyphset = pool->data; - while (count-- > 0) { view_t psg_view = { .id = *ent++, .reg = res->reg, .comp = vhref}; - // first child is always a paragraph view, and all vies after the + // first child is always a paragraph view, and all views after the // first paragraph's first child are all text views view_t para_view = View_GetChild (psg_view, 0); view_t text_view = View_GetChild (para_view, 0); hierref_t *href = View_GetRef (text_view); + glyphset_t *gs = glyphset++; hierarchy_t *h = href->hierarchy; view_pos_t *abs = h->components[view_abs]; view_pos_t *len = h->components[view_len]; for (uint32_t i = href->index; i < h->num_objects; i++) { glyphref_t *gref = Ent_GetComponent (h->ent[i], glyphs, res->reg); - draw_glyphs (&abs[i], glyphset, gref); + draw_glyphs (&abs[i], gs, gref); if (0) draw_box (abs, len, i, 253); } From 37b6d4da7eed617d12fc9cf88ee042bec29552df Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Jan 2023 13:25:46 +0900 Subject: [PATCH 3319/3664] [vulkan] Switch glyph vertex and texture data bindings With an eye towards merging the 2d pipelines as much as possible, I found that the glyph and basic 2d quad texture descriptors were in different slots for no reason I can think of. Having them in the same slot would mean I could use the same fragment shader for all 2d pipelines (though the plan is to get it down to two: (sliced) quads and lines). --- libs/video/renderer/vulkan/pl_quake_def.plist | 16 ++++++++-------- libs/video/renderer/vulkan/shader/glyph.frag | 2 +- libs/video/renderer/vulkan/shader/glyph.vert | 2 +- libs/video/renderer/vulkan/shader/slice.vert | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index e841070f3..463addd10 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -281,20 +281,20 @@ }; glyph_data_set = { bindings = ( - { - // glyph geometry data (offset and uv) - binding = 0; - descriptorType = uniform_texel_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, { // glyph texture data - binding = 1; + binding = 0; descriptorType = combined_image_sampler; descriptorCount = 1; stageFlags = fragment; }, + { + // glyph geometry data (offset and uv) + binding = 1; + descriptorType = uniform_texel_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, ); }; texture_set = { diff --git a/libs/video/renderer/vulkan/shader/glyph.frag b/libs/video/renderer/vulkan/shader/glyph.frag index 08941cd10..90b52e826 100644 --- a/libs/video/renderer/vulkan/shader/glyph.frag +++ b/libs/video/renderer/vulkan/shader/glyph.frag @@ -1,6 +1,6 @@ #version 450 -layout (set = 1, binding = 1) uniform sampler2D Texture; +layout (set = 1, binding = 0) uniform sampler2D Texture; layout (location = 0) in vec2 uv; layout (location = 1) in vec4 color; diff --git a/libs/video/renderer/vulkan/shader/glyph.vert b/libs/video/renderer/vulkan/shader/glyph.vert index 864df9ebf..7c21dc2a5 100644 --- a/libs/video/renderer/vulkan/shader/glyph.vert +++ b/libs/video/renderer/vulkan/shader/glyph.vert @@ -4,7 +4,7 @@ layout (set = 0, binding = 0) uniform #include "matrices.h" ; -layout (set = 1, binding = 0) uniform textureBuffer glyph_data; +layout (set = 1, binding = 1) uniform textureBuffer glyph_data; // per instance data layout (location = 0) in uint glyph_index; diff --git a/libs/video/renderer/vulkan/shader/slice.vert b/libs/video/renderer/vulkan/shader/slice.vert index bdf749410..676dd0ed5 100644 --- a/libs/video/renderer/vulkan/shader/slice.vert +++ b/libs/video/renderer/vulkan/shader/slice.vert @@ -4,7 +4,7 @@ layout (set = 0, binding = 0) uniform #include "matrices.h" ; -layout (set = 1, binding = 0) uniform textureBuffer glyph_data; +layout (set = 1, binding = 1) uniform textureBuffer glyph_data; // per instance data layout (location = 0) in uint glyph_index; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index d6bced784..67d5a1bee 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1503,12 +1503,12 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, font->set, 0, 0, 1, - VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, - 0, 0, &glyph_bview->buffer_view.view }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - font->set, 1, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo, 0, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + font->set, 1, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 0, 0, &glyph_bview->buffer_view.view }, }; dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); free (glyph_sets); From 3da90b612f3fd7b844ec688c547bd58ab1d92ac6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Jan 2023 13:34:52 +0900 Subject: [PATCH 3320/3664] [vulkan] Remove superfluous glyph fragment shader The main reason I had created in the first place was I hadn't thought of using image view swizzles to handle coverage-alpha textures (for monochrome glyphs), and for whatever reason also had the texture in a different binding slot to the twod fragment shader. With both issues out of the way, there's no reason to have an almost identical (just some naming) shader just for glyphs. --- libs/video/renderer/Makemodule.am | 5 ----- libs/video/renderer/vulkan/pl_quake_def.plist | 4 ++-- libs/video/renderer/vulkan/shader.c | 3 --- libs/video/renderer/vulkan/shader/glyph.frag | 17 ----------------- 4 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 libs/video/renderer/vulkan/shader/glyph.frag diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 17e86d3fc..316f9449e 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -285,8 +285,6 @@ slice_src = $(vkshaderpath)/slice.vert slice_c = $(vkshaderpath)/slice.vert.spvc glyphv_src = $(vkshaderpath)/glyph.vert glyphv_c = $(vkshaderpath)/glyph.vert.spvc -glyphf_src = $(vkshaderpath)/glyph.frag -glyphf_c = $(vkshaderpath)/glyph.frag.spvc linev_src = $(vkshaderpath)/line.vert linev_c = $(vkshaderpath)/line.vert.spvc linef_src = $(vkshaderpath)/line.frag @@ -373,7 +371,6 @@ waterwarp_c = $(vkshaderpath)/waterwarp.frag.spvc $(slice_vert_c): $(slice_vert_src) $(matrices_h) $(glyphv_c): $(glyphv_src) $(matrices_h) -$(glyphf_c): $(glyphf_src) $(linev_c): $(linev_src) $(matrices_h) $(linef_c): $(linef_src) @@ -449,7 +446,6 @@ $(waterwarp_c): $(waterwarp_src) $(matrices_h) vkshader_c = \ $(slice_c) \ $(glyphv_c) \ - $(glyphf_c) \ $(linev_c) \ $(linef_c) \ $(partphysicsc_c) \ @@ -535,7 +531,6 @@ EXTRA_DIST += \ $(entity_h) \ $(slice_src) \ $(glyphv_src) \ - $(glyphf_src) \ $(linev_src) \ $(linef_src) \ $(partphysicsc_src) \ diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 463addd10..dcd8f55fe 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -1190,7 +1190,7 @@ subpass = 0; stages = ( { stage = vertex; name = main; module = $builtin/slice.vert; }, - { stage = fragment; name = main; module = $builtin/glyph.frag; }, + { stage = fragment; name = main; module = $builtin/twod.frag; }, ); vertexInput = $properties.vertexInput.slice; inputAssembly = { @@ -1211,7 +1211,7 @@ subpass = 0; stages = ( { stage = vertex; name = main; module = $builtin/glyph.vert; }, - { stage = fragment; name = main; module = $builtin/glyph.frag; }, + { stage = fragment; name = main; module = $builtin/twod.frag; }, ); vertexInput = $properties.vertexInput.glyph; inputAssembly = { diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 133f23517..954e386ae 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -43,8 +43,6 @@ static static #include "libs/video/renderer/vulkan/shader/glyph.vert.spvc" static -#include "libs/video/renderer/vulkan/shader/glyph.frag.spvc" -static #include "libs/video/renderer/vulkan/shader/line.vert.spvc" static #include "libs/video/renderer/vulkan/shader/line.frag.spvc" @@ -130,7 +128,6 @@ typedef struct shaderdata_s { static shaderdata_t builtin_shaders[] = { { "slice.vert", slice_vert, sizeof (slice_vert) }, { "glyph.vert", glyph_vert, sizeof (glyph_vert) }, - { "glyph.frag", glyph_frag, sizeof (glyph_frag) }, { "line.vert", line_vert, sizeof (line_vert) }, { "line.frag", line_frag, sizeof (line_frag) }, { "particle.vert", particle_vert, sizeof (particle_vert) }, diff --git a/libs/video/renderer/vulkan/shader/glyph.frag b/libs/video/renderer/vulkan/shader/glyph.frag deleted file mode 100644 index 90b52e826..000000000 --- a/libs/video/renderer/vulkan/shader/glyph.frag +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout (set = 1, binding = 0) uniform sampler2D Texture; - -layout (location = 0) in vec2 uv; -layout (location = 1) in vec4 color; - -layout (location = 0) out vec4 frag_color; - -void -main (void) -{ - vec4 pix; - - pix = texture (Texture, uv); - frag_color = pix * color; -} From 82d0b7ecd5fac48cf1c0422adaf18264594ec21c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 5 Jan 2023 16:00:05 +0900 Subject: [PATCH 3321/3664] [vulkan] Use slice pipeline for glyphs It turns out the slice pipeline is compatible with the glyph pipeline in that its vertex attribute data is a superset (just the addition of the offset attributes). While the queues have yet to be merged, this will eventually get glyphs, sliced sprites, and general (static) quads into the one pipeline. Although this is slightly slower for glyph rendering (due to the need to pass an extra 8 bytes per glyph), this should be faster for quad rendering (when done) as it will be 24 bytes per quad instead of 32 bytes per vertex (ie, 128 bytes per quad), but this does serve as a proof of concept for doing quads, glyphs and sprites in the one pipeline. --- libs/video/renderer/Makemodule.am | 6 ---- libs/video/renderer/vulkan/pl_quake_def.plist | 22 -------------- libs/video/renderer/vulkan/shader.c | 3 -- libs/video/renderer/vulkan/shader/glyph.vert | 30 ------------------- libs/video/renderer/vulkan/shader/slice.vert | 8 ++--- libs/video/renderer/vulkan/vulkan_draw.c | 25 ++++++---------- 6 files changed, 13 insertions(+), 81 deletions(-) delete mode 100644 libs/video/renderer/vulkan/shader/glyph.vert diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 316f9449e..d21ecf882 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -283,8 +283,6 @@ vkshaderpath = libs/video/renderer/vulkan/shader slice_src = $(vkshaderpath)/slice.vert slice_c = $(vkshaderpath)/slice.vert.spvc -glyphv_src = $(vkshaderpath)/glyph.vert -glyphv_c = $(vkshaderpath)/glyph.vert.spvc linev_src = $(vkshaderpath)/line.vert linev_c = $(vkshaderpath)/line.vert.spvc linef_src = $(vkshaderpath)/line.frag @@ -370,8 +368,6 @@ waterwarp_c = $(vkshaderpath)/waterwarp.frag.spvc $(slice_vert_c): $(slice_vert_src) $(matrices_h) -$(glyphv_c): $(glyphv_src) $(matrices_h) - $(linev_c): $(linev_src) $(matrices_h) $(linef_c): $(linef_src) @@ -445,7 +441,6 @@ $(waterwarp_c): $(waterwarp_src) $(matrices_h) vkshader_c = \ $(slice_c) \ - $(glyphv_c) \ $(linev_c) \ $(linef_c) \ $(partphysicsc_c) \ @@ -530,7 +525,6 @@ EXTRA_DIST += \ $(matrices_h) \ $(entity_h) \ $(slice_src) \ - $(glyphv_src) \ $(linev_src) \ $(linef_src) \ $(partphysicsc_src) \ diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index dcd8f55fe..76a37030c 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -1205,28 +1205,6 @@ }; layout = glyph_layout;//slices use the same descriptors as glyphs }; - glyph = { - @inherit = $properties.pipelines.trans_base; - renderPass = output; - subpass = 0; - stages = ( - { stage = vertex; name = main; module = $builtin/glyph.vert; }, - { stage = fragment; name = main; module = $builtin/twod.frag; }, - ); - vertexInput = $properties.vertexInput.glyph; - inputAssembly = { - // glyphs are drawn using instanced quads, so primitive restart - // is not needed as only four vertices are drawn per instance. - topology = triangle_strip; - primitiveRestartEnable = false; - }; - rasterization = $properties.rasterization.counter_cw_cull_back; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.alpha_blend); - }; - layout = glyph_layout; - }; lines = { @inherit = $properties.pipelines.twod; stages = ( diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index 954e386ae..cde12f5b8 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -41,8 +41,6 @@ static #include "libs/video/renderer/vulkan/shader/slice.vert.spvc" static -#include "libs/video/renderer/vulkan/shader/glyph.vert.spvc" -static #include "libs/video/renderer/vulkan/shader/line.vert.spvc" static #include "libs/video/renderer/vulkan/shader/line.frag.spvc" @@ -127,7 +125,6 @@ typedef struct shaderdata_s { static shaderdata_t builtin_shaders[] = { { "slice.vert", slice_vert, sizeof (slice_vert) }, - { "glyph.vert", glyph_vert, sizeof (glyph_vert) }, { "line.vert", line_vert, sizeof (line_vert) }, { "line.frag", line_frag, sizeof (line_frag) }, { "particle.vert", particle_vert, sizeof (particle_vert) }, diff --git a/libs/video/renderer/vulkan/shader/glyph.vert b/libs/video/renderer/vulkan/shader/glyph.vert deleted file mode 100644 index 7c21dc2a5..000000000 --- a/libs/video/renderer/vulkan/shader/glyph.vert +++ /dev/null @@ -1,30 +0,0 @@ -#version 450 -#extension GL_GOOGLE_include_directive : enable - -layout (set = 0, binding = 0) uniform -#include "matrices.h" -; -layout (set = 1, binding = 1) uniform textureBuffer glyph_data; - -// per instance data -layout (location = 0) in uint glyph_index; -layout (location = 1) in vec4 glyph_color; -layout (location = 2) in vec2 glyph_position; - -// rg -> offset x,y -// ba -> texture u,v - -layout (location = 0) out vec2 uv; -layout (location = 1) out vec4 color; - -void -main (void) -{ - vec4 glyph = texelFetch (glyph_data, int(glyph_index) * 4 + gl_VertexIndex); - // offset stored in glyph components 0 and 1 - vec2 position = glyph_position + glyph.xy; - gl_Position = Projection2d * vec4 (position.xy, 0.0, 1.0); - // texture uv stored in glyph components 2 and 3 - uv = glyph.pq; - color = glyph_color; -} diff --git a/libs/video/renderer/vulkan/shader/slice.vert b/libs/video/renderer/vulkan/shader/slice.vert index 676dd0ed5..ca67404cd 100644 --- a/libs/video/renderer/vulkan/shader/slice.vert +++ b/libs/video/renderer/vulkan/shader/slice.vert @@ -4,6 +4,9 @@ layout (set = 0, binding = 0) uniform #include "matrices.h" ; + +// rg -> offset x,y +// ba -> texture u,v layout (set = 1, binding = 1) uniform textureBuffer glyph_data; // per instance data @@ -12,9 +15,6 @@ layout (location = 1) in vec4 glyph_color; layout (location = 2) in vec2 glyph_position; layout (location = 3) in vec2 glyph_offset; // for 9-slice -// rg -> offset x,y -// ba -> texture u,v - layout (location = 0) out vec2 uv; layout (location = 1) out vec4 color; @@ -22,7 +22,7 @@ void main (void) { vec2 offset = vec2 ((gl_VertexIndex & 4) >> 2, (gl_VertexIndex & 8) >> 3); - vec4 glyph = texelFetch (glyph_data, int(glyph_index) * 4 + gl_VertexIndex); + vec4 glyph = texelFetch (glyph_data, int(glyph_index + gl_VertexIndex)); // offset stored in glyph components 0 and 1 vec2 position = glyph_position + glyph.xy + offset * glyph_offset; gl_Position = Projection2d * vec4 (position.xy, 0.0, 1.0); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 67d5a1bee..009f78b76 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -101,12 +101,6 @@ typedef struct { float offset[2]; } sliceinst_t; -typedef struct { - uint32_t index; - byte color[4]; - float position[2]; -} glyphinst_t; - typedef struct { float offset[2]; float uv[2]; @@ -130,7 +124,7 @@ typedef struct slicequeue_s { } slicequeue_t; typedef struct glyphqueue_s { - glyphinst_t *glyphs; + sliceinst_t *glyphs; int count; int size; } glyphqueue_t; @@ -198,7 +192,6 @@ typedef struct drawctx_s { qfv_resobj_t *line_objects; VkPipeline quad_pipeline; VkPipeline slice_pipeline; - VkPipeline glyph_pipeline; VkPipeline line_pipeline; VkPipelineLayout layout; VkPipelineLayout glyph_layout;//slice pipeline uses same layout @@ -338,7 +331,7 @@ create_quad_buffers (vulkan_ctx_t *ctx) .name = "glyphs.inst", .type = qfv_res_buffer, .buffer = { - .size = MAX_GLYPHS * sizeof (glyphinst_t), + .size = MAX_GLYPHS * sizeof (sliceinst_t), .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, }, @@ -382,7 +375,7 @@ create_quad_buffers (vulkan_ctx_t *ctx) }; DARRAY_INIT (&frame->slice_batch, 16); frame->glyph_insts = (glyphqueue_t) { - .glyphs = (glyphinst_t *) ((byte *)data + frame->glyph_offset), + .glyphs = (sliceinst_t *) ((byte *)data + frame->glyph_offset), .size = MAX_QUADS, }; DARRAY_INIT (&frame->glyph_batch, 16); @@ -545,7 +538,6 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->slice_pipeline, 0); - dfunc->vkDestroyPipeline (device->dev, dctx->glyph_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0); Hash_DelTable (dctx->pic_cache); delete_memsuper (dctx->pic_memsuper); @@ -620,7 +612,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); dctx->slice_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "slice"); - dctx->glyph_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "glyph"); dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines"); dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout"); @@ -1319,7 +1310,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) a(dframe->slice_insts.count * sizeof (sliceinst_t)) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, memory, dframe->glyph_offset, - a(dframe->glyph_insts.count * sizeof (glyphinst_t)) }, + a(dframe->glyph_insts.count * sizeof (sliceinst_t)) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, memory, dframe->line_offset, a(dframe->line_verts.count * VERTS_PER_LINE * sizeof (drawvert_t)) }, @@ -1343,7 +1334,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) draw_slices (rFrame, dframe->cmdSet.a[QFV_draw2d]); } if (dframe->glyph_insts.count) { - bind_pipeline (rFrame, dctx->glyph_pipeline, + bind_pipeline (rFrame, dctx->slice_pipeline, dframe->cmdSet.a[QFV_draw2d]); draw_glyphs (rFrame, dframe->cmdSet.a[QFV_draw2d]); } @@ -1536,12 +1527,14 @@ Vulkan_Draw_Glyph (int x, int y, int fontid, int glyph, int c, } batch->count++; - glyphinst_t *inst = &queue->glyphs[queue->count++]; - inst->index = glyph; + sliceinst_t *inst = &queue->glyphs[queue->count++]; + inst->index = glyph * 4; // index is actual vertex index VectorCopy (vid.palette + c * 3, inst->color); inst->color[3] = 255; inst->position[0] = x; inst->position[1] = y; + inst->offset[0] = 0; + inst->offset[1] = 0; } void From b310ece7bd5dea797c7dac4e75c07c0c8b1b4191 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 9 Jan 2023 13:31:53 +0900 Subject: [PATCH 3322/3664] [vulkan] Clean up draw a little bit It's just removing some functions that will never be implemented, and an unnecessary field. --- include/QF/Vulkan/qf_draw.h | 4 ---- libs/video/renderer/vulkan/vulkan_draw.c | 23 ----------------------- 2 files changed, 27 deletions(-) diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index b7cb493c2..4182fe5d9 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -85,10 +85,6 @@ int Vulkan_Draw_AddFont (struct font_s *font, struct vulkan_ctx_s *ctx); void Vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c, struct vulkan_ctx_s *ctx); -void Vulkan_Set2D (struct vulkan_ctx_s *ctx); -void Vulkan_Set2DScaled (struct vulkan_ctx_s *ctx); -void Vulkan_End2D (struct vulkan_ctx_s *ctx); -void Vulkan_DrawReset (struct vulkan_ctx_s *ctx); void Vulkan_FlushText (struct qfv_renderframe_s *rFrame); void Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 009f78b76..7e15731c2 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -162,7 +162,6 @@ typedef struct drawfontres_s { typedef struct drawfont_s { VkDescriptorSet set; drawfontres_t *resource; - font_t *font; } drawfont_t; typedef struct drawfontset_s @@ -1095,26 +1094,6 @@ Vulkan_Draw_FadeScreen (vulkan_ctx_t *ctx) draw_blendscreen (color, ctx); } -void -Vulkan_Set2D (vulkan_ctx_t *ctx) -{ -} - -void -Vulkan_Set2DScaled (vulkan_ctx_t *ctx) -{ -} - -void -Vulkan_End2D (vulkan_ctx_t *ctx) -{ -} - -void -Vulkan_DrawReset (vulkan_ctx_t *ctx) -{ -} - static void draw_begin_subpass (QFV_DrawSubpass subpass, qfv_renderframe_t *rFrame) { @@ -1376,8 +1355,6 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) DARRAY_OPEN_AT (&dctx->fonts, fontid, 1); drawfont_t *font = &dctx->fonts.a[fontid]; - font->font = rfont; - font->resource = malloc (sizeof (drawfontres_t)); font->resource->resource = (qfv_resource_t) { .name = va (ctx->va_ctx, "glyph_data:%d", fontid), From c8afad4d3d83748ae894f46b00e1d1a6a474fe12 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Jan 2023 11:32:05 +0900 Subject: [PATCH 3323/3664] [vulkan] Make QFV_PacketCopyBuffer take destination offset It's useful being able to update a subregion of a buffer (needed for the quad drawing changes). --- include/QF/Vulkan/staging.h | 3 ++- libs/video/renderer/vulkan/staging.c | 11 +++++++++-- libs/video/renderer/vulkan/vulkan_draw.c | 6 +++--- libs/video/renderer/vulkan/vulkan_translucent.c | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/staging.h b/include/QF/Vulkan/staging.h index 60ba40d13..9abe5a48c 100644 --- a/include/QF/Vulkan/staging.h +++ b/include/QF/Vulkan/staging.h @@ -35,7 +35,8 @@ qfv_packet_t *QFV_PacketAcquire (qfv_stagebuf_t *stage); void *QFV_PacketExtend (qfv_packet_t *packet, size_t size); void QFV_PacketSubmit (qfv_packet_t *packet); struct qfv_bufferbarrier_s; -void QFV_PacketCopyBuffer (qfv_packet_t *packet, VkBuffer dstBuffer, +void QFV_PacketCopyBuffer (qfv_packet_t *packet, + VkBuffer dstBuffer, VkDeviceSize offset, const struct qfv_bufferbarrier_s *dstBarrier); struct qfv_imagebarrier_s; void QFV_PacketCopyImage (qfv_packet_t *packet, VkImage dstImage, diff --git a/libs/video/renderer/vulkan/staging.c b/libs/video/renderer/vulkan/staging.c index ca40eaab7..f7f0b10f6 100644 --- a/libs/video/renderer/vulkan/staging.c +++ b/libs/video/renderer/vulkan/staging.c @@ -284,20 +284,27 @@ QFV_PacketSubmit (qfv_packet_t *packet) } void -QFV_PacketCopyBuffer (qfv_packet_t *packet, VkBuffer dstBuffer, +QFV_PacketCopyBuffer (qfv_packet_t *packet, + VkBuffer dstBuffer, VkDeviceSize offset, const qfv_bufferbarrier_t *dstBarrier) { qfv_devfuncs_t *dfunc = packet->stage->device->funcs; qfv_bufferbarrier_t bb = bufferBarriers[qfv_BB_Unknown_to_TransferWrite]; bb.barrier.buffer = dstBuffer; + bb.barrier.offset = offset; bb.barrier.size = packet->length; dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, 0, 0, 0, 1, &bb.barrier, 0, 0); - VkBufferCopy copy_region = { packet->offset, 0, packet->length }; + VkBufferCopy copy_region = { + .srcOffset = packet->offset, + .dstOffset = offset, + .size = packet->length, + }; dfunc->vkCmdCopyBuffer (packet->cmd, packet->stage->buffer, dstBuffer, 1, ©_region); bb = *dstBarrier; bb.barrier.buffer = dstBuffer; + bb.barrier.offset = offset; bb.barrier.size = packet->length; dfunc->vkCmdPipelineBarrier (packet->cmd, bb.srcStages, bb.dstStages, 0, 0, 0, 1, &bb.barrier, 0, 0); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 7e15731c2..d35bdf584 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -227,7 +227,7 @@ generate_quad_indices (qfv_stagebuf_t *staging, qfv_resobj_t *ind_buffer) // mark end of primitive *ind++ = -1; } - QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, + QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, 0, &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); QFV_PacketSubmit (packet); } @@ -243,7 +243,7 @@ generate_slice_indices (qfv_stagebuf_t *staging, qfv_resobj_t *ind_buffer) ind[i + 18] = i + 8; } ind[8] = ind[17] = ~0; - QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, + QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, 0, &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); QFV_PacketSubmit (packet); } @@ -1446,7 +1446,7 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) .uv = {(u + w) * s, (v + h) * t }, }; } - QFV_PacketCopyBuffer (packet, glyph_data->buffer.buffer, + QFV_PacketCopyBuffer (packet, glyph_data->buffer.buffer, 0, &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]); QFV_PacketSubmit (packet); diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index e2e0d8f09..1a82b8321 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -292,7 +292,7 @@ translucent_clear (qfv_renderframe_t *rFrame) qfv_transtate_t *state = QFV_PacketExtend (packet, 2 * sizeof (*state)); *state = (qfv_transtate_t) { 0, tctx->maxFragments }; __auto_type bb = &bufferBarriers[qfv_BB_TransferWrite_to_ShaderRW]; - QFV_PacketCopyBuffer (packet, tframe->state, bb); + QFV_PacketCopyBuffer (packet, tframe->state, 0, bb); QFV_PacketSubmit (packet); } From 8fff71ed4bdb7e79605f82da58225bf1e90643c4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Jan 2023 11:34:32 +0900 Subject: [PATCH 3324/3664] [vulkan] Rework quad drawing to use a single pipeline Any performance gains will be utterly swamped by the deferred renderer, but it will allow better control of quad render order by any client code (and should be slightly better for simpler renderers when I get support for them working). Right now, plenty is broken (much of the higher level draw functions are disabled, and pics don't render correctly), but this gets at least the basics in so I'm not bouncing diffs around as much. --- libs/video/renderer/vulkan/pl_quake_def.plist | 78 +-- libs/video/renderer/vulkan/vulkan_draw.c | 662 ++++++++---------- 2 files changed, 308 insertions(+), 432 deletions(-) diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 76a37030c..a8f580f71 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -121,28 +121,18 @@ }, ); }; - twod_pool = { - flags = 0; - maxSets = "$frames.size * 2z"; + quad_pool = { + maxSets = 64; bindings = ( { - type = combined_image_sampler; - descriptorCount = $frames.size; - }, - ); - }; - glyph_pool = { - maxSets = 16; - bindings = ( - { - // glyph geometry data (offset and uv) + // quad geometry data (offset and uv) type = uniform_texel_buffer; - descriptorCount = 16; + descriptorCount = 64; }, { - // glyph texture data + // quad texture data type = combined_image_sampler; - descriptorCount = 16; + descriptorCount = 64; }, ); }; @@ -269,17 +259,7 @@ }, ); }; - twod_set = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - glyph_data_set = { + quad_data_set = { bindings = ( { // glyph texture data @@ -453,11 +433,8 @@ }; }; pipelineLayouts = { - twod_layout = { - setLayouts = (matrix_set, twod_set); - }; - glyph_layout = { - setLayouts = (matrix_set, glyph_data_set); + quad_layout = { + setLayouts = (matrix_set, quad_data_set); }; lines_layout = { setLayouts = (matrix_set); @@ -1159,30 +1136,6 @@ layout = sprite_layout; }; twod = { - @inherit = $properties.pipelines.trans_base; - renderPass = output; - subpass = 0; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/twod.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/twod.frag; - }, - ); - vertexInput = $properties.vertexInput.twod; - inputAssembly = $properties.inputAssembly.twod; - rasterization = $properties.rasterization.counter_cw_cull_back; - depthStencil = $properties.depthStencil.disable; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.alpha_blend); - }; - layout = twod_layout; }; slice = { @inherit = $properties.pipelines.trans_base; @@ -1203,14 +1156,23 @@ logicOpEnable = false; attachments = ($properties.attachmentBlendOp.alpha_blend); }; - layout = glyph_layout;//slices use the same descriptors as glyphs + layout = quad_layout; }; lines = { - @inherit = $properties.pipelines.twod; + @inherit = $properties.pipelines.trans_base; + renderPass = output; + subpass = 0; stages = ( { stage = vertex; name = main; module = $builtin/line.vert; }, { stage = fragment; name = main; module = $builtin/line.frag; }, ); + vertexInput = $properties.vertexInput.twod; + rasterization = $properties.rasterization.counter_cw_cull_back; + depthStencil = $properties.depthStencil.disable; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.alpha_blend); + }; inputAssembly = $properties.inputAssembly.lines; layout = lines_layout; }; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index d35bdf584..b39cbd283 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -72,7 +72,7 @@ #include "r_internal.h" #include "vid_vulkan.h" -static const char * __attribute__((used)) draw_pass_names[] = { +static const char *draw_pass_names[] = { "2d", }; @@ -91,59 +91,47 @@ typedef struct descbatchset_s typedef struct { float xy[2]; float st[2]; - float color[4]; -} drawvert_t; + byte color[4]; +} linevert_t; typedef struct { uint32_t index; byte color[4]; float position[2]; float offset[2]; -} sliceinst_t; +} quadinst_t; typedef struct { float offset[2]; float uv[2]; -} glyphvert_t; +} quadvert_t; + +typedef struct vertqueue_s { + linevert_t *verts; + int count; + int size; +} vertqueue_t; + +typedef struct quadqueue_s { + quadinst_t *quads; + int count; + int size; +} quadqueue_t; typedef struct cachepic_s { char *name; qpic_t *pic; } cachepic_t; -typedef struct vertqueue_s { - drawvert_t *verts; - int count; - int size; -} vertqueue_t; - -typedef struct slicequeue_s { - sliceinst_t *slices; - int count; - int size; -} slicequeue_t; - -typedef struct glyphqueue_s { - sliceinst_t *glyphs; - int count; - int size; -} glyphqueue_t; - typedef struct drawframe_s { - size_t quad_offset; - size_t slice_offset; - size_t glyph_offset; + size_t instance_offset; size_t line_offset; - VkBuffer quad_buffer; + VkBuffer instance_buffer; + VkBufferView dvert_view; + VkDescriptorSet core_quad_set; + descbatchset_t quad_batch; - VkBuffer slice_buffer; - descbatchset_t slice_batch; - VkBuffer glyph_buffer; - descbatchset_t glyph_batch; - VkBuffer line_buffer; - vertqueue_t quad_verts; - slicequeue_t slice_insts; - glyphqueue_t glyph_insts; + quadqueue_t quad_insts; vertqueue_t line_verts; qfv_cmdbufferset_t cmdSet; } drawframe_t; @@ -173,6 +161,7 @@ typedef struct drawctx_s { scrap_t *scrap; qfv_stagebuf_t *stage; qpic_t *crosshair; + int *conchar_inds; qpic_t *conchars; qpic_t *conback; qpic_t *white_pic; @@ -184,53 +173,37 @@ typedef struct drawctx_s { memsuper_t *string_memsuper; hashtab_t *pic_cache; qfv_resource_t *draw_resource; - qfv_resobj_t *ind_objects; - qfv_resobj_t *quad_objects; - qfv_resobj_t *slice_objects; - qfv_resobj_t *glyph_objects; - qfv_resobj_t *line_objects; + qfv_resobj_t *index_object; + qfv_resobj_t *svertex_object; + qfv_resobj_t *instance_objects; + qfv_resobj_t *dvertex_objects; + uint32_t svertex_index; + uint32_t svertex_max; VkPipeline quad_pipeline; - VkPipeline slice_pipeline; VkPipeline line_pipeline; - VkPipelineLayout layout; - VkPipelineLayout glyph_layout;//slice pipeline uses same layout - VkDescriptorSet quad_set; + VkPipelineLayout lines_layout; + VkPipelineLayout quad_layout; + VkDescriptorSetLayout quad_data_set_layout; + VkDescriptorPool quad_pool; drawframeset_t frames; drawfontset_t fonts; } drawctx_t; -// enough for a full screen of 8x8 chars at 1920x1080 plus some extras (368) #define MAX_QUADS (32768) #define VERTS_PER_QUAD (4) -#define INDS_PER_QUAD (5) // one per vert plus primitive reset +#define BYTES_PER_QUAD (VERTS_PER_QUAD * sizeof (quadvert_t)) +#define VERTS_PER_SLICE (16) +#define BYTES_PER_SLICE (VERTS_PER_SLICE * sizeof (quadvert_t)) +#define INDS_PER_QUAD (4) +#define INDS_PER_SLICE (26) -#define MAX_GLYPHS (32768) +#define MAX_INSTANCES (1024*1024) #define MAX_LINES (32768) #define VERTS_PER_LINE (2) +#define BYTES_PER_LINE (VERTS_PER_LINE * sizeof (linevert_t)) -#define QUADS_OFFSET 0 -#define IAQUADS_OFFSET (MAX_QUADS * VERTS_PER_QUAD) -#define LINES_OFFSET (IAQUADS_OFFSET + (MAX_QUADS * VERTS_PER_QUAD)) - -#define VERTS_PER_FRAME (LINES_OFFSET + MAX_LINES*VERTS_PER_LINE) - -static void -generate_quad_indices (qfv_stagebuf_t *staging, qfv_resobj_t *ind_buffer) -{ - qfv_packet_t *packet = QFV_PacketAcquire (staging); - uint32_t *ind = QFV_PacketExtend (packet, ind_buffer->buffer.size); - for (int i = 0; i < MAX_QUADS; i++) { - for (int j = 0; j < VERTS_PER_QUAD; j++) { - *ind++ = i * VERTS_PER_QUAD + j; - } - // mark end of primitive - *ind++ = -1; - } - QFV_PacketCopyBuffer (packet, ind_buffer->buffer.buffer, 0, - &bufferBarriers[qfv_BB_TransferWrite_to_IndexRead]); - QFV_PacketSubmit (packet); -} +#define DVERTS_PER_FRAME (LINES_OFFSET + MAX_LINES*VERTS_PER_LINE) static void generate_slice_indices (qfv_stagebuf_t *staging, qfv_resobj_t *ind_buffer) @@ -249,7 +222,7 @@ generate_slice_indices (qfv_stagebuf_t *staging, qfv_resobj_t *ind_buffer) } static void -create_quad_buffers (vulkan_ctx_t *ctx) +create_buffers (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -257,89 +230,92 @@ create_quad_buffers (vulkan_ctx_t *ctx) size_t frames = ctx->frames.size; dctx->draw_resource = malloc (2 * sizeof (qfv_resource_t) - // index buffers + // index buffer + + sizeof (qfv_resobj_t) + // svertex buffer and view + 2 * sizeof (qfv_resobj_t) - // quads: frames vertex buffers - + (frames) * sizeof (qfv_resobj_t) - // slicess: frames instance vertex buffers - + (frames) * sizeof (qfv_resobj_t) - // glyphs: frames instance vertex buffers - + (frames) * sizeof (qfv_resobj_t) - // lines: frames vertex buffers + // frames dynamic vertex buffers and views + + (frames) * 2 * sizeof (qfv_resobj_t) + // frames instance buffers + (frames) * sizeof (qfv_resobj_t)); - dctx->ind_objects = (qfv_resobj_t *) &dctx->draw_resource[2]; - dctx->quad_objects = &dctx->ind_objects[2]; - dctx->slice_objects = &dctx->quad_objects[frames]; - dctx->glyph_objects = &dctx->slice_objects[frames]; - dctx->line_objects = &dctx->glyph_objects[frames]; + dctx->index_object = (qfv_resobj_t *) &dctx->draw_resource[2]; + dctx->svertex_object = &dctx->index_object[1]; + dctx->dvertex_objects = &dctx->svertex_object[2]; + dctx->instance_objects = &dctx->dvertex_objects[2 * frames]; + + dctx->svertex_index = 0; + dctx->svertex_max = MAX_QUADS * VERTS_PER_QUAD; dctx->draw_resource[0] = (qfv_resource_t) { .name = "draw", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, .num_objects = 2, // quad and 9-slice indices - .objects = dctx->ind_objects, + .objects = dctx->index_object, }; dctx->draw_resource[1] = (qfv_resource_t) { .name = "draw", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - .num_objects = (frames) + (frames) + (frames) + (frames), - .objects = dctx->quad_objects, + .num_objects = (2 * frames) + (frames), + .objects = dctx->dvertex_objects, }; - dctx->ind_objects[0] = (qfv_resobj_t) { + dctx->index_object[0] = (qfv_resobj_t) { .name = "quads.index", .type = qfv_res_buffer, .buffer = { - .size = MAX_QUADS * INDS_PER_QUAD * sizeof (uint32_t), + .size = INDS_PER_SLICE * sizeof (uint32_t), .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, }, }; - dctx->ind_objects[1] = (qfv_resobj_t) { - .name = "9-slice.index", + dctx->svertex_object[0] = (qfv_resobj_t) { + .name = "sverts", .type = qfv_res_buffer, .buffer = { - .size = 26 * sizeof (uint32_t), + .size = MAX_QUADS * BYTES_PER_QUAD, .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT - | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, + }, + }; + dctx->svertex_object[1] = (qfv_resobj_t) { + .name = "sverts", + .type = qfv_res_buffer_view, + .buffer_view = { + .buffer = 1, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = 0, + .size = dctx->svertex_object[0].buffer.size, }, }; for (size_t i = 0; i < frames; i++) { - dctx->quad_objects[i] = (qfv_resobj_t) { - .name = "quads.geom", + dctx->dvertex_objects[i * 2 + 0] = (qfv_resobj_t) { + .name = "dverts", .type = qfv_res_buffer, .buffer = { - .size = MAX_QUADS * VERTS_PER_QUAD * sizeof (drawvert_t), + .size = MAX_QUADS * BYTES_PER_QUAD, .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT - | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, }, }; - dctx->slice_objects[i] = (qfv_resobj_t) { - .name = "slices.inst", - .type = qfv_res_buffer, - .buffer = { - .size = MAX_GLYPHS * sizeof (sliceinst_t), - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT - | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + dctx->dvertex_objects[i * 2 + 1] = (qfv_resobj_t) { + .name = "dverts", + .type = qfv_res_buffer_view, + .buffer_view = { + .buffer = &dctx->dvertex_objects[i * 2 + 0] + - dctx->draw_resource[1].objects, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = 0, + .size = dctx->dvertex_objects[i * 2 + 0].buffer.size, }, }; - dctx->glyph_objects[i] = (qfv_resobj_t) { - .name = "glyphs.inst", + dctx->instance_objects[i] = (qfv_resobj_t) { + .name = "inst", .type = qfv_res_buffer, .buffer = { - .size = MAX_GLYPHS * sizeof (sliceinst_t), - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT - | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - }, - }; - dctx->line_objects[i] = (qfv_resobj_t) { - .name = "lines.geom", - .type = qfv_res_buffer, - .buffer = { - .size = MAX_LINES * VERTS_PER_LINE * sizeof (drawvert_t), + .size = MAX_INSTANCES * sizeof (quadinst_t), .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, }, @@ -354,39 +330,25 @@ create_quad_buffers (vulkan_ctx_t *ctx) for (size_t f = 0; f < frames; f++) { drawframe_t *frame = &dctx->frames.a[f]; - frame->quad_buffer = dctx->quad_objects[f].buffer.buffer; - frame->quad_offset = dctx->quad_objects[f].buffer.offset; - frame->slice_buffer = dctx->slice_objects[f].buffer.buffer; - frame->slice_offset = dctx->slice_objects[f].buffer.offset; - frame->glyph_buffer = dctx->glyph_objects[f].buffer.buffer; - frame->glyph_offset = dctx->glyph_objects[f].buffer.offset; - frame->line_buffer = dctx->line_objects[f].buffer.buffer; - frame->line_offset = dctx->line_objects[f].buffer.offset; + frame->instance_buffer = dctx->instance_objects[f].buffer.buffer; + frame->instance_offset = dctx->instance_objects[f].buffer.offset; + frame->dvert_view = dctx->dvertex_objects[f * 2 + 1].buffer_view.view; + frame->line_offset = dctx->dvertex_objects[f * 2].buffer.offset; - frame->quad_verts = (vertqueue_t) { - .verts = (drawvert_t *) ((byte *)data + frame->quad_offset), - .size = MAX_QUADS, - }; DARRAY_INIT (&frame->quad_batch, 16); - frame->slice_insts = (slicequeue_t) { - .slices = (sliceinst_t *) ((byte *)data + frame->slice_offset), - .size = MAX_QUADS, + frame->quad_insts = (quadqueue_t) { + .quads = (quadinst_t *) ((byte *)data + frame->instance_offset), + .size = MAX_INSTANCES, }; - DARRAY_INIT (&frame->slice_batch, 16); - frame->glyph_insts = (glyphqueue_t) { - .glyphs = (sliceinst_t *) ((byte *)data + frame->glyph_offset), - .size = MAX_QUADS, - }; - DARRAY_INIT (&frame->glyph_batch, 16); + frame->line_verts = (vertqueue_t) { - .verts = (drawvert_t *) ((byte *)data + frame->line_offset), - .size = MAX_QUADS, + .verts = (linevert_t *) ((byte *)data + frame->line_offset), + .size = MAX_INSTANCES, }; } // The indices will never change so pre-generate and stash them - generate_quad_indices (ctx->staging, &dctx->ind_objects[0]); - generate_slice_indices (ctx->staging, &dctx->ind_objects[1]); + generate_slice_indices (ctx->staging, &dctx->index_object[0]); } static void @@ -530,13 +492,14 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) QFV_DestroyResource (device, &dctx->draw_resource[0]); QFV_DestroyResource (device, &dctx->draw_resource[1]); - for (size_t i = 0; i < dctx->fonts.size; i++) { + // the first "font" is reserved for the core quad data set and is dynamic + // and thus does not have its own resources + for (size_t i = 1; i < dctx->fonts.size; i++) { QFV_DestroyResource (device, &dctx->fonts.a[i].resource->resource); free (dctx->fonts.a[i].resource); } dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); - dfunc->vkDestroyPipeline (device->dev, dctx->slice_pipeline, 0); dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0); Hash_DelTable (dctx->pic_cache); delete_memsuper (dctx->pic_memsuper); @@ -545,6 +508,68 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) QFV_DestroyStagingBuffer (dctx->stage); } +static int +create_quad (int x, int y, int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + //qfv_device_t *device = ctx->device; + //qfv_devfuncs_t *dfunc = device->funcs; + + subpic_t *subpic = *(subpic_t **) pic->data; + + x += subpic->rect->x; + y += subpic->rect->y; + float size = subpic->size; + float sl = (x + 0) * size; + float sr = (x + w) * size; + float st = (y + 0) * size; + float sb = (y + h) * size; + + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_QUAD); + verts[0] = (quadvert_t) { {0, 0}, {sl, st} }; + verts[1] = (quadvert_t) { {0, h}, {sl, sb} }; + verts[2] = (quadvert_t) { {w, 0}, {sr, st} }; + verts[3] = (quadvert_t) { {w, h}, {sr, sb} }; + + int ind = dctx->svertex_index; + dctx->svertex_index += VERTS_PER_QUAD; + QFV_PacketCopyBuffer (packet, dctx->svertex_object[0].buffer.buffer, + ind * sizeof (quadvert_t), + &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]); + QFV_PacketSubmit (packet); + + return ind; +} + +static void +load_conchars (vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + + draw_chars = W_GetLumpName ("conchars"); + if (draw_chars) { + for (int i = 0; i < 256 * 64; i++) { + if (draw_chars[i] == 0) { + draw_chars[i] = 255; // proper transparent color + } + } + dctx->conchars = pic_data ("conchars", 128, 128, draw_chars, dctx); + } else { + qpic_t *charspic = Draw_Font8x8Pic (); + dctx->conchars = pic_data ("conchars", charspic->width, + charspic->height, charspic->data, dctx); + free (charspic); + } + dctx->conchar_inds = malloc (256 * sizeof (int)); + for (int i = 0; i < 256; i++) { + int cx = i % 16; + int cy = i / 16; + dctx->conchar_inds[i] = create_quad (cx * 8, cy * 8, 8, 8, + dctx->conchars, ctx); + } +} + void Vulkan_Draw_Init (vulkan_ctx_t *ctx) { @@ -570,7 +595,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, dctx, 0); - create_quad_buffers (ctx); + create_buffers (ctx); dctx->stage = QFV_CreateStagingBuffer (device, "draw", 4 * 1024 * 1024, ctx->cmdpool); dctx->scrap = QFV_CreateScrap (device, "draw_atlas", 2048, tex_rgba, @@ -578,20 +603,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->pic_sampler = Vulkan_CreateSampler (ctx, "quakepic"); dctx->glyph_sampler = Vulkan_CreateSampler (ctx, "glyph"); - draw_chars = W_GetLumpName ("conchars"); - if (draw_chars) { - for (int i = 0; i < 256 * 64; i++) { - if (draw_chars[i] == 0) { - draw_chars[i] = 255; // proper transparent color - } - } - dctx->conchars = pic_data ("conchars", 128, 128, draw_chars, dctx); - } else { - qpic_t *charspic = Draw_Font8x8Pic (); - dctx->conchars = pic_data ("conchars", charspic->width, - charspic->height, charspic->data, dctx); - free (charspic); - } + load_conchars (ctx); { qpic_t *hairpic = Draw_CrosshairPic (); dctx->crosshair = pic_data ("crosshair", hairpic->width, @@ -609,16 +621,19 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); - dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "twod"); - dctx->slice_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "slice"); + dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "slice"); dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines"); - dctx->layout = Vulkan_CreatePipelineLayout (ctx, "twod_layout"); - dctx->glyph_layout = Vulkan_CreatePipelineLayout (ctx, "glyph_layout"); + dctx->lines_layout = Vulkan_CreatePipelineLayout (ctx, "lines_layout"); + dctx->quad_layout = Vulkan_CreatePipelineLayout (ctx, "quad_layout"); + __auto_type sl = Vulkan_CreateDescriptorSetLayout (ctx, "quad_data_set"); + dctx->quad_data_set_layout = sl; + dctx->quad_pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool"); - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "twod_set"); - __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "twod_pool"); + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + for (size_t i = 0; i < layouts->size; i++) { + layouts->a[i] = dctx->quad_data_set_layout; + } VkDescriptorImageInfo imageInfo = { dctx->pic_sampler, @@ -626,17 +641,27 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; + __auto_type pool = dctx->quad_pool; __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); - dctx->quad_set = sets->a[0]; - VkWriteDescriptorSet write[] = { - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - dctx->quad_set, 0, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &imageInfo, 0, 0 }, - }; + for (size_t i = 0; i < sets->size; i++) { + __auto_type frame = &dctx->frames.a[i]; + frame->core_quad_set = sets->a[i]; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + frame->core_quad_set, 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo, 0, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + frame->core_quad_set, 1, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 0, 0, &frame->dvert_view }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + } free (sets); - dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + DARRAY_APPEND (&dctx->fonts, (drawfont_t) {}); + for (size_t i = 0; i < frames; i++) { __auto_type dframe = &dctx->frames.a[i]; @@ -656,50 +681,39 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) qfvPopDebug (ctx); } -static inline void -draw_pic (float x, float y, int w, int h, subpic_t *subpic, - int srcx, int srcy, int srcw, int srch, - float *color, vertqueue_t *queue) +static inline descbatch_t * +get_desc_batch (drawframe_t *frame, int descid, uint32_t ind_count) { + descbatch_t *batch = &frame->quad_batch.a[frame->quad_batch.size - 1]; + if (!frame->quad_batch.size || batch->descid != descid + || ((batch->count & (0xff << 24)) != (ind_count << 24))) { + DARRAY_APPEND(&frame->quad_batch, ((descbatch_t) { .descid = descid })); + batch = &frame->quad_batch.a[frame->quad_batch.size - 1]; + batch->count = ind_count << 24; + } + + return batch; +} + +static inline void +draw_quad (float x, float y, int descid, uint32_t vertid, byte *color, + drawframe_t *frame) +{ + __auto_type queue = &frame->quad_insts; if (queue->count >= queue->size) { return; } - drawvert_t *verts = queue->verts + queue->count * VERTS_PER_QUAD; - queue->count++; + __auto_type batch = get_desc_batch (frame, descid, INDS_PER_QUAD); + batch->count++; - srcx += subpic->rect->x; - srcy += subpic->rect->y; - - float size = subpic->size; - float sl = srcx * size; - float sr = (srcx + srcw) * size; - float st = srcy * size; - float sb = (srcy + srch) * size; - - verts[0].xy[0] = x; - verts[0].xy[1] = y; - verts[0].st[0] = sl; - verts[0].st[1] = st; - QuatCopy (color, verts[0].color); - - verts[1].xy[0] = x; - verts[1].xy[1] = y + h; - verts[1].st[0] = sl; - verts[1].st[1] = sb; - QuatCopy (color, verts[1].color); - - verts[2].xy[0] = x + w; - verts[2].xy[1] = y; - verts[2].st[0] = sr; - verts[2].st[1] = st; - QuatCopy (color, verts[2].color); - - verts[3].xy[0] = x + w; - verts[3].xy[1] = y + h; - verts[3].st[0] = sr; - verts[3].st[1] = sb; - QuatCopy (color, verts[3].color); + quadinst_t *quad = &queue->quads[queue->count++]; + *quad = (quadinst_t) { + .index = vertid, + .color = { QuatExpand (color) }, + .position = { x, y }, + .offset = { 0, 0 }, + }; } static inline void @@ -708,14 +722,8 @@ queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx) drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - quat_t color = {1, 1, 1, 1}; - int cx, cy; - cx = chr % 16; - cy = chr / 16; - - subpic_t *subpic = *(subpic_t **) dctx->conchars->data; - draw_pic (x, y, 8, 8, subpic, cx * 8, cy * 8, 8, 8, color, - &frame->quad_verts); + byte color[4] = {255, 255, 255, 255}; + draw_quad (x, y, 0, dctx->conchar_inds[chr], color, frame); } void @@ -820,18 +828,8 @@ draw_crosshair_pic (int ch, int x, int y, vulkan_ctx_t *ctx) drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - static const int pos[CROSSHAIR_COUNT][4] = { - {0, 0, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT}, - {CROSSHAIR_WIDTH, 0, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT}, - {0, CROSSHAIR_HEIGHT, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT}, - {CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT}, - }; - const int *p = pos[ch - 1]; - - subpic_t *subpic = *(subpic_t **) dctx->crosshair->data; - draw_pic (x - CROSSHAIR_WIDTH / 2 + 1, y - CROSSHAIR_HEIGHT / 2 + 1, - CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT, subpic, - p[0], p[1], p[2], p[3], crosshair_color, &frame->quad_verts); + byte *color = &vid.palette32[bound (0, crosshaircolor, 255) * 4]; + draw_quad (x, y, 0, ch * 4, color, frame); } static void (*crosshair_func[]) (int ch, int x, int y, vulkan_ctx_t *ctx) = { @@ -869,6 +867,7 @@ void Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, vulkan_ctx_t *ctx) { +#if 0 drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; @@ -927,6 +926,7 @@ Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, p = Vulkan_Draw_CachePic ("gfx/box_br.lmp", true, ctx); draw (cx, cy + 8, p); #undef draw +#endif } void @@ -935,10 +935,8 @@ Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - static quat_t color = { 1, 1, 1, 1}; - subpic_t *subpic = *(subpic_t **) pic->data; - draw_pic (x, y, pic->width, pic->height, subpic, - 0, 0, pic->width, pic->height, color, &frame->quad_verts); + static byte color[4] = { 255, 255, 255, 255}; + draw_quad (x, y, 0, 0, color, frame); } void @@ -947,10 +945,8 @@ Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - static quat_t color = { 1, 1, 1, 1}; - subpic_t *subpic = *(subpic_t **) pic->data; - draw_pic (x, y, pic->width, pic->height, subpic, - 0, 0, pic->width, pic->height, color, &frame->quad_verts); + static byte color[4] = { 255, 255, 255, 255}; + draw_quad (x, y, 0, 0, color, frame); } void @@ -961,15 +957,14 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - static quat_t color = { 1, 1, 1, 1}; - subpic_t *subpic = *(subpic_t **) pic->data; - draw_pic (x, y, width, height, subpic, srcx, srcy, width, height, - color, &frame->quad_verts); + static byte color[4] = { 255, 255, 255, 255}; + draw_quad (x, y, 0, 0, color, frame); } void Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) { +#if 0 drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; @@ -985,11 +980,13 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) draw_pic (0, 0, vid.width / s, lines, subpic, 0, ofs, cpic->width, cpic->height - ofs, color, &frame->quad_verts); +#endif } void Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) { +#if 0 drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; @@ -1019,11 +1016,13 @@ Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) sub->width, sub->height, color, &frame->quad_verts); } } +#endif } void Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) { +#if 0 drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; @@ -1034,6 +1033,7 @@ Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; draw_pic (x, y, w, h, subpic, 0, 0, 1, 1, color, &frame->quad_verts); +#endif } void @@ -1047,10 +1047,6 @@ Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) return; } - quat_t color = { VectorExpand (vid.palette + c * 3), 255 }; - QuatScale (color, 1/255.0, color); - drawvert_t *verts = queue->verts + queue->count * VERTS_PER_LINE; - subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; int srcx = subpic->rect->x; int srcy = subpic->rect->y; @@ -1062,15 +1058,16 @@ Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) float st = (srcy + 0.03125) * size; float sb = (srcy + srch - 0.03125) * size; - verts[0] = (drawvert_t) { + linevert_t *verts = queue->verts + queue->count * VERTS_PER_LINE; + verts[0] = (linevert_t) { .xy = { x0, y0 }, .st = {sl, st}, - .color = { QuatExpand (color) }, + .color = { VectorExpand (vid.palette + c * 3), 255 }, }; - verts[1] = (drawvert_t) { + verts[1] = (linevert_t) { .xy = { x1, y1 }, .st = {sr, sb}, - .color = { QuatExpand (color) }, + .color = { VectorExpand (vid.palette + c * 3), 255 }, }; queue->count++; @@ -1079,12 +1076,14 @@ Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) static inline void draw_blendscreen (quat_t color, vulkan_ctx_t *ctx) { +#if 0 drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; draw_pic (0, 0, vid.width, vid.height, subpic, 0, 0, 1, 1, color, &frame->quad_verts); +#endif } void @@ -1154,90 +1153,34 @@ draw_quads (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - VkBuffer quad_buffer = dframe->quad_buffer; - VkBuffer ind_buffer = dctx->ind_objects[0].buffer.buffer; - + VkBuffer instance_buffer = dframe->instance_buffer; VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &quad_buffer, offsets); - dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); - VkDescriptorSet set[2] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dctx->quad_set, - }; - VkPipelineLayout layout = dctx->layout; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &instance_buffer, offsets); - dfunc->vkCmdDrawIndexed (cmd, dframe->quad_verts.count * INDS_PER_QUAD, - 1, 0, 0, 0); -} - -static void -draw_slices (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - drawctx_t *dctx = ctx->draw_context; - drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - - VkBuffer slice_buffer = dframe->slice_buffer; - VkBuffer ind_buffer = dctx->ind_objects[1].buffer.buffer; - VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &slice_buffer, offsets); + VkBuffer ind_buffer = dctx->index_object[0].buffer.buffer; dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); uint32_t inst_start = 0; - for (size_t i = 0; i < dframe->slice_batch.size; i++) { - int fontid = dframe->slice_batch.a[i].descid; - uint32_t inst_count = dframe->slice_batch.a[i].count; + for (size_t i = 0; i < dframe->quad_batch.size; i++) { + int fontid = dframe->quad_batch.a[i].descid; + uint32_t inst_count = dframe->quad_batch.a[i].count; + uint32_t ind_count = inst_count >> 24; + inst_count &= 0xffffff; + printf ("%zd %d %d %d\n", i, fontid, inst_count, ind_count); VkDescriptorSet set[2] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), dctx->fonts.a[fontid].set, }; - VkPipelineLayout layout = dctx->glyph_layout; - dfunc->vkCmdBindDescriptorSets (cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, + VkPipelineLayout layout = dctx->quad_layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 2, set, 0, 0); - dfunc->vkCmdDrawIndexed (cmd, 26, inst_count, 0, 0, inst_start); + dfunc->vkCmdDrawIndexed (cmd, ind_count, inst_count, 0, 0, inst_start); inst_start += inst_count; } - DARRAY_RESIZE (&dframe->slice_batch, 0); + DARRAY_RESIZE (&dframe->quad_batch, 0); } - -static void -draw_glyphs (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - drawctx_t *dctx = ctx->draw_context; - drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - - VkBuffer glyph_buffer = dframe->glyph_buffer; - VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &glyph_buffer, offsets); - - uint32_t inst_start = 0; - for (size_t i = 0; i < dframe->glyph_batch.size; i++) { - int fontid = dframe->glyph_batch.a[i].descid; - uint32_t inst_count = dframe->glyph_batch.a[i].count; - VkDescriptorSet set[2] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dctx->fonts.a[fontid].set, - }; - VkPipelineLayout layout = dctx->glyph_layout; - dfunc->vkCmdBindDescriptorSets (cmd, - VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); - - dfunc->vkCmdDraw (cmd, 4, inst_count, 0, inst_start); - inst_start += inst_count; - } - DARRAY_RESIZE (&dframe->glyph_batch, 0); -} - +#if 0 static void draw_lines (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) { @@ -1253,13 +1196,13 @@ draw_lines (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) VkDescriptorSet set[1] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), }; - VkPipelineLayout layout = dctx->layout; + VkPipelineLayout layout = dctx->lines_layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 1, set, 0, 0); dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE, 1, 0, 0); } - +#endif void Vulkan_FlushText (qfv_renderframe_t *rFrame) { @@ -1271,62 +1214,47 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) drawctx_t *dctx = ctx->draw_context; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - if (!dframe->quad_verts.count && !dframe->slice_insts.count - && !dframe->glyph_insts.count && !dframe->line_verts.count) { + if (!dframe->quad_insts.count && !dframe->line_verts.count) { return; } + dctx->fonts.a[0].set = dframe->core_quad_set; + VkDeviceMemory memory = dctx->draw_resource[1].memory; size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; size_t atom_mask = atom - 1; #define a(x) (((x) + atom_mask) & ~atom_mask) VkMappedMemoryRange ranges[] = { { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - memory, dframe->quad_offset, - a(dframe->quad_verts.count * VERTS_PER_QUAD * sizeof (drawvert_t)) }, - { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - memory, dframe->slice_offset, - a(dframe->slice_insts.count * sizeof (sliceinst_t)) }, - { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - memory, dframe->glyph_offset, - a(dframe->glyph_insts.count * sizeof (sliceinst_t)) }, + memory, dframe->instance_offset, + a(dframe->quad_insts.count * BYTES_PER_QUAD) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, memory, dframe->line_offset, - a(dframe->line_verts.count * VERTS_PER_LINE * sizeof (drawvert_t)) }, + a(dframe->line_verts.count * VERTS_PER_LINE * sizeof (linevert_t)) }, }; #undef a - dfunc->vkFlushMappedMemoryRanges (device->dev, 3, ranges); + dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); DARRAY_APPEND (&rFrame->subpassCmdSets[subpass_map[QFV_draw2d]], dframe->cmdSet.a[QFV_draw2d]); draw_begin_subpass (QFV_draw2d, rFrame); - if (dframe->quad_verts.count) { + if (dframe->quad_insts.count) { bind_pipeline (rFrame, dctx->quad_pipeline, dframe->cmdSet.a[QFV_draw2d]); draw_quads (rFrame, dframe->cmdSet.a[QFV_draw2d]); } - if (dframe->slice_insts.count) { - bind_pipeline (rFrame, dctx->slice_pipeline, - dframe->cmdSet.a[QFV_draw2d]); - draw_slices (rFrame, dframe->cmdSet.a[QFV_draw2d]); - } - if (dframe->glyph_insts.count) { - bind_pipeline (rFrame, dctx->slice_pipeline, - dframe->cmdSet.a[QFV_draw2d]); - draw_glyphs (rFrame, dframe->cmdSet.a[QFV_draw2d]); - } +#if 0 if (dframe->line_verts.count) { bind_pipeline (rFrame, dctx->line_pipeline, dframe->cmdSet.a[QFV_draw2d]); draw_lines (rFrame, dframe->cmdSet.a[QFV_draw2d]); } +#endif draw_end_subpass (dframe->cmdSet.a[QFV_draw2d], ctx); - dframe->quad_verts.count = 0; - dframe->slice_insts.count = 0; - dframe->glyph_insts.count = 0; + dframe->quad_insts.count = 0; dframe->line_verts.count = 0; } @@ -1368,7 +1296,7 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) .name = "geom", .type = qfv_res_buffer, .buffer = { - .size = rfont->num_glyphs * 4 * sizeof (glyphvert_t), + .size = rfont->num_glyphs * 4 * sizeof (quadvert_t), .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, }, @@ -1418,7 +1346,7 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) QFV_CreateResource (ctx->device, &font->resource->resource); qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); - glyphvert_t *verts = QFV_PacketExtend (packet, glyph_data->buffer.size); + quadvert_t *verts = QFV_PacketExtend (packet, glyph_data->buffer.size); for (FT_Long i = 0; i < rfont->num_glyphs; i++) { vrect_t *rect = &rfont->glyph_rects[i]; float x = 0; @@ -1429,19 +1357,19 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) float v = rect->y; float s = 1.0 / rfont->scrap.width; float t = 1.0 / rfont->scrap.height; - verts[i * 4 + 0] = (glyphvert_t) { + verts[i * 4 + 0] = (quadvert_t) { .offset = { x, y }, .uv = { u * s, v * t }, }; - verts[i * 4 + 1] = (glyphvert_t) { + verts[i * 4 + 1] = (quadvert_t) { .offset = { x, y + h }, .uv = { u * s, (v + h) * t }, }; - verts[i * 4 + 2] = (glyphvert_t) { + verts[i * 4 + 2] = (quadvert_t) { .offset = { x + w, y }, .uv = {(u + w) * s, v * t }, }; - verts[i * 4 + 3] = (glyphvert_t) { + verts[i * 4 + 3] = (quadvert_t) { .offset = { x + w, y + h }, .uv = {(u + w) * s, (v + h) * t }, }; @@ -1459,8 +1387,8 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) QFV_PacketSubmit (packet); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "glyph_data_set"); - __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "glyph_pool"); + layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "quad_data_set"); + __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool"); __auto_type glyph_sets = QFV_AllocateDescriptorSet (device, pool, layouts); font->set = glyph_sets->a[0]; VkDescriptorImageInfo imageInfo = { @@ -1489,29 +1417,15 @@ Vulkan_Draw_Glyph (int x, int y, int fontid, int glyph, int c, vulkan_ctx_t *ctx) { drawctx_t *dctx = ctx->draw_context; - drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - glyphqueue_t *queue = &dframe->glyph_insts;; + quadqueue_t *queue = &frame->quad_insts; if (queue->count >= queue->size) { return; } - descbatch_t *batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1]; - if (!dframe->glyph_batch.size || batch->descid != fontid) { - DARRAY_APPEND(&dframe->glyph_batch, - ((descbatch_t) { .descid = fontid })); - batch = &dframe->glyph_batch.a[dframe->glyph_batch.size - 1]; - } - - batch->count++; - sliceinst_t *inst = &queue->glyphs[queue->count++]; - inst->index = glyph * 4; // index is actual vertex index - VectorCopy (vid.palette + c * 3, inst->color); - inst->color[3] = 255; - inst->position[0] = x; - inst->position[1] = y; - inst->offset[0] = 0; - inst->offset[1] = 0; + byte color[4] = { VectorExpand (vid.palette + c * 3), 255 }; + draw_quad (x, y, fontid, glyph * 4, color, frame); } void From 77fc6355cc1ce0d209d9a14722a15f2a5f8217fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Jan 2023 12:47:22 +0900 Subject: [PATCH 3325/3664] [vulkan] Use correct descriptor set for core quads The problem was that I had mixed up the purpose of the per-frame vertex buffers and used them for the core quad data when they were meant for subpic and the like, and forgotten about the static vertex buffer. This gets at least conchars working (pic in general not tested yet). --- libs/video/renderer/vulkan/vulkan_draw.c | 58 +++++++++++++++--------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index b39cbd283..1ff37ea47 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -128,7 +128,7 @@ typedef struct drawframe_s { size_t line_offset; VkBuffer instance_buffer; VkBufferView dvert_view; - VkDescriptorSet core_quad_set; + VkDescriptorSet dyn_quad_set; descbatchset_t quad_batch; quadqueue_t quad_insts; @@ -174,7 +174,7 @@ typedef struct drawctx_s { hashtab_t *pic_cache; qfv_resource_t *draw_resource; qfv_resobj_t *index_object; - qfv_resobj_t *svertex_object; + qfv_resobj_t *svertex_objects; qfv_resobj_t *instance_objects; qfv_resobj_t *dvertex_objects; uint32_t svertex_index; @@ -185,6 +185,7 @@ typedef struct drawctx_s { VkPipelineLayout quad_layout; VkDescriptorSetLayout quad_data_set_layout; VkDescriptorPool quad_pool; + VkDescriptorSet core_quad_set; drawframeset_t frames; drawfontset_t fonts; } drawctx_t; @@ -239,8 +240,8 @@ create_buffers (vulkan_ctx_t *ctx) // frames instance buffers + (frames) * sizeof (qfv_resobj_t)); dctx->index_object = (qfv_resobj_t *) &dctx->draw_resource[2]; - dctx->svertex_object = &dctx->index_object[1]; - dctx->dvertex_objects = &dctx->svertex_object[2]; + dctx->svertex_objects = &dctx->index_object[1]; + dctx->dvertex_objects = &dctx->svertex_objects[2]; dctx->instance_objects = &dctx->dvertex_objects[2 * frames]; dctx->svertex_index = 0; @@ -250,7 +251,7 @@ create_buffers (vulkan_ctx_t *ctx) .name = "draw", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .num_objects = 2, // quad and 9-slice indices + .num_objects = 1 + 2, // quad and 9-slice indices, and static verts .objects = dctx->index_object, }; dctx->draw_resource[1] = (qfv_resource_t) { @@ -270,7 +271,7 @@ create_buffers (vulkan_ctx_t *ctx) | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, }, }; - dctx->svertex_object[0] = (qfv_resobj_t) { + dctx->svertex_objects[0] = (qfv_resobj_t) { .name = "sverts", .type = qfv_res_buffer, .buffer = { @@ -279,14 +280,14 @@ create_buffers (vulkan_ctx_t *ctx) | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, }, }; - dctx->svertex_object[1] = (qfv_resobj_t) { + dctx->svertex_objects[1] = (qfv_resobj_t) { .name = "sverts", .type = qfv_res_buffer_view, .buffer_view = { .buffer = 1, .format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = 0, - .size = dctx->svertex_object[0].buffer.size, + .size = dctx->svertex_objects[0].buffer.size, }, }; @@ -492,9 +493,10 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) QFV_DestroyResource (device, &dctx->draw_resource[0]); QFV_DestroyResource (device, &dctx->draw_resource[1]); - // the first "font" is reserved for the core quad data set and is dynamic - // and thus does not have its own resources - for (size_t i = 1; i < dctx->fonts.size; i++) { + // the first two "fonts" are reserved for the dynamic and core quad data + // sets and thus does not have its own resources (they are created + // separately) + for (size_t i = 2; i < dctx->fonts.size; i++) { QFV_DestroyResource (device, &dctx->fonts.a[i].resource->resource); free (dctx->fonts.a[i].resource); } @@ -534,7 +536,7 @@ create_quad (int x, int y, int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) int ind = dctx->svertex_index; dctx->svertex_index += VERTS_PER_QUAD; - QFV_PacketCopyBuffer (packet, dctx->svertex_object[0].buffer.buffer, + QFV_PacketCopyBuffer (packet, dctx->svertex_objects[0].buffer.buffer, ind * sizeof (quadvert_t), &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]); QFV_PacketSubmit (packet); @@ -630,7 +632,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->quad_data_set_layout = sl; dctx->quad_pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool"); - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); + // core set + dynamic sets + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1 + frames, alloca); for (size_t i = 0; i < layouts->size; i++) { layouts->a[i] = dctx->quad_data_set_layout; } @@ -643,24 +646,38 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) __auto_type pool = dctx->quad_pool; __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); - for (size_t i = 0; i < sets->size; i++) { - __auto_type frame = &dctx->frames.a[i]; - frame->core_quad_set = sets->a[i]; + for (size_t i = 1; i < sets->size; i++) { + __auto_type frame = &dctx->frames.a[i - 1]; + frame->dyn_quad_set = sets->a[i]; VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - frame->core_quad_set, 0, 0, 1, + frame->dyn_quad_set, 0, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageInfo, 0, 0 }, { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - frame->core_quad_set, 1, 0, 1, + frame->dyn_quad_set, 1, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 0, 0, &frame->dvert_view }, }; dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); } + dctx->core_quad_set = sets->a[0]; free (sets); + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + dctx->core_quad_set, 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo, 0, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + dctx->core_quad_set, 1, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 0, 0, &dctx->svertex_objects[1].buffer_view.view }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + DARRAY_APPEND (&dctx->fonts, (drawfont_t) {}); + DARRAY_APPEND (&dctx->fonts, (drawfont_t) { .set = dctx->core_quad_set }); for (size_t i = 0; i < frames; i++) { __auto_type dframe = &dctx->frames.a[i]; @@ -723,7 +740,7 @@ queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; byte color[4] = {255, 255, 255, 255}; - draw_quad (x, y, 0, dctx->conchar_inds[chr], color, frame); + draw_quad (x, y, 1, dctx->conchar_inds[chr], color, frame); } void @@ -1166,7 +1183,6 @@ draw_quads (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) uint32_t inst_count = dframe->quad_batch.a[i].count; uint32_t ind_count = inst_count >> 24; inst_count &= 0xffffff; - printf ("%zd %d %d %d\n", i, fontid, inst_count, ind_count); VkDescriptorSet set[2] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), dctx->fonts.a[fontid].set, @@ -1218,7 +1234,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) return; } - dctx->fonts.a[0].set = dframe->core_quad_set; + dctx->fonts.a[0].set = dframe->dyn_quad_set; VkDeviceMemory memory = dctx->draw_resource[1].memory; size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; From 456003f8cb2bfbc359e4ba8f8b3470d0c47337df Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Jan 2023 13:34:27 +0900 Subject: [PATCH 3326/3664] [vulkan] Create static vertex data for pics This gets full pic rendering working. Subpics and other dynamic quad rendering doesn't work yet. --- libs/video/renderer/vulkan/vulkan_draw.c | 127 ++++++++++++----------- 1 file changed, 66 insertions(+), 61 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 1ff37ea47..2f7d041d5 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -80,6 +80,11 @@ static QFV_Subpass subpass_map[] = { [QFV_draw2d] = 0, }; +typedef struct pic_data_s { + uint32_t vert_index; + subpic_t *subpic; +} picdata_t; + typedef struct descbatch_s { int32_t descid; // texture or font descriptor id uint32_t count; // number of objects in batch @@ -361,8 +366,8 @@ flush_draw_scrap (vulkan_ctx_t *ctx) static void pic_free (drawctx_t *dctx, qpic_t *pic) { - subpic_t *subpic = *(subpic_t **) &pic->data[0]; - QFV_SubpicDelete (subpic); + __auto_type pd = (picdata_t *) pic->data; + QFV_SubpicDelete (pd->subpic); cmemfree (dctx->pic_memsuper, pic); } @@ -395,22 +400,54 @@ cachepic_getkey (const void *_cp, void *unused) return ((cachepic_t *) _cp)->name; } -static qpic_t * -pic_data (const char *name, int w, int h, const byte *data, drawctx_t *dctx) +static int +create_quad (int x, int y, int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + + __auto_type pd = (picdata_t *) pic->data; + + x += pd->subpic->rect->x; + y += pd->subpic->rect->y; + float size = pd->subpic->size; + float sl = (x + 0) * size; + float sr = (x + w) * size; + float st = (y + 0) * size; + float sb = (y + h) * size; + + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_QUAD); + verts[0] = (quadvert_t) { {0, 0}, {sl, st} }; + verts[1] = (quadvert_t) { {0, h}, {sl, sb} }; + verts[2] = (quadvert_t) { {w, 0}, {sr, st} }; + verts[3] = (quadvert_t) { {w, h}, {sr, sb} }; + + int ind = dctx->svertex_index; + dctx->svertex_index += VERTS_PER_QUAD; + QFV_PacketCopyBuffer (packet, dctx->svertex_objects[0].buffer.buffer, + ind * sizeof (quadvert_t), + &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]); + QFV_PacketSubmit (packet); + + return ind; +} + +static qpic_t * +pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; qpic_t *pic; - subpic_t *subpic; byte *picdata; pic = cmemalloc (dctx->pic_memsuper, - field_offset (qpic_t, data[sizeof (subpic_t *)])); + field_offset (qpic_t, data[sizeof (picdata_t)])); pic->width = w; pic->height = h; + __auto_type pd = (picdata_t *) pic->data; + pd->subpic = QFV_ScrapSubpic (dctx->scrap, w, h); + pd->vert_index = create_quad (0, 0, w, h, pic, ctx); - subpic = QFV_ScrapSubpic (dctx->scrap, w, h); - *(subpic_t **) pic->data = subpic; - - picdata = QFV_SubpicBatch (subpic, dctx->stage); + picdata = QFV_SubpicBatch (pd->subpic, dctx->stage); size_t size = w * h; for (size_t i = 0; i < size; i++) { byte pix = *data++; @@ -434,7 +471,7 @@ qpic_t * Vulkan_Draw_MakePic (int width, int height, const byte *data, vulkan_ctx_t *ctx) { - return pic_data (0, width, height, data, ctx->draw_context); + return pic_data (0, width, height, data, ctx); } void @@ -450,8 +487,7 @@ Vulkan_Draw_PicFromWad (const char *name, vulkan_ctx_t *ctx) if (!wadpic) { return 0; } - return pic_data (name, wadpic->width, wadpic->height, wadpic->data, - ctx->draw_context); + return pic_data (name, wadpic->width, wadpic->height, wadpic->data, ctx); } qpic_t * @@ -470,7 +506,7 @@ Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) return 0; } - pic = pic_data (path, p->width, p->height, p->data, dctx); + pic = pic_data (path, p->width, p->height, p->data, ctx); free (p); cpic = new_cachepic (dctx, path, pic); Hash_Add (dctx->pic_cache, cpic); @@ -510,40 +546,6 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) QFV_DestroyStagingBuffer (dctx->stage); } -static int -create_quad (int x, int y, int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) -{ - drawctx_t *dctx = ctx->draw_context; - //qfv_device_t *device = ctx->device; - //qfv_devfuncs_t *dfunc = device->funcs; - - subpic_t *subpic = *(subpic_t **) pic->data; - - x += subpic->rect->x; - y += subpic->rect->y; - float size = subpic->size; - float sl = (x + 0) * size; - float sr = (x + w) * size; - float st = (y + 0) * size; - float sb = (y + h) * size; - - qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); - quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_QUAD); - verts[0] = (quadvert_t) { {0, 0}, {sl, st} }; - verts[1] = (quadvert_t) { {0, h}, {sl, sb} }; - verts[2] = (quadvert_t) { {w, 0}, {sr, st} }; - verts[3] = (quadvert_t) { {w, h}, {sr, sb} }; - - int ind = dctx->svertex_index; - dctx->svertex_index += VERTS_PER_QUAD; - QFV_PacketCopyBuffer (packet, dctx->svertex_objects[0].buffer.buffer, - ind * sizeof (quadvert_t), - &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]); - QFV_PacketSubmit (packet); - - return ind; -} - static void load_conchars (vulkan_ctx_t *ctx) { @@ -556,11 +558,11 @@ load_conchars (vulkan_ctx_t *ctx) draw_chars[i] = 255; // proper transparent color } } - dctx->conchars = pic_data ("conchars", 128, 128, draw_chars, dctx); + dctx->conchars = pic_data ("conchars", 128, 128, draw_chars, ctx); } else { qpic_t *charspic = Draw_Font8x8Pic (); dctx->conchars = pic_data ("conchars", charspic->width, - charspic->height, charspic->data, dctx); + charspic->height, charspic->data, ctx); free (charspic); } dctx->conchar_inds = malloc (256 * sizeof (int)); @@ -609,12 +611,12 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) { qpic_t *hairpic = Draw_CrosshairPic (); dctx->crosshair = pic_data ("crosshair", hairpic->width, - hairpic->height, hairpic->data, dctx); + hairpic->height, hairpic->data, ctx); free (hairpic); } byte white_block = 0xfe; - dctx->white_pic = pic_data ("white", 1, 1, &white_block, dctx); + dctx->white_pic = pic_data ("white", 1, 1, &white_block, ctx); dctx->backtile_pic = Vulkan_Draw_PicFromWad ("backtile", ctx); if (!dctx->backtile_pic) { @@ -953,7 +955,8 @@ Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; static byte color[4] = { 255, 255, 255, 255}; - draw_quad (x, y, 0, 0, color, frame); + __auto_type pd = (picdata_t *) pic->data; + draw_quad (x, y, 1, pd->vert_index, color, frame); } void @@ -963,7 +966,8 @@ Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; static byte color[4] = { 255, 255, 255, 255}; - draw_quad (x, y, 0, 0, color, frame); + __auto_type pd = (picdata_t *) pic->data; + draw_quad (x, y, 1, pd->vert_index, color, frame); } void @@ -975,7 +979,8 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; static byte color[4] = { 255, 255, 255, 255}; - draw_quad (x, y, 0, 0, color, frame); + __auto_type pd = (picdata_t *) pic->data; + draw_quad (x, y, 1, pd->vert_index, color, frame); } void @@ -1064,12 +1069,12 @@ Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) return; } - subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; - int srcx = subpic->rect->x; - int srcy = subpic->rect->y; - int srcw = subpic->rect->width; - int srch = subpic->rect->height; - float size = subpic->size; + __auto_type pd = (picdata_t *) dctx->white_pic->data; + int srcx = pd->subpic->rect->x; + int srcy = pd->subpic->rect->y; + int srcw = pd->subpic->rect->width; + int srch = pd->subpic->rect->height; + float size = pd->subpic->size; float sl = (srcx + 0.03125) * size; float sr = (srcx + srcw - 0.03125) * size; float st = (srcy + 0.03125) * size; From a30fdcdadc24bcb9fbf0beb0abfb705160f3fb37 Mon Sep 17 00:00:00 2001 From: Snakespeed <95513955+Snakespeed@users.noreply.github.com> Date: Wed, 11 Jan 2023 07:17:13 +0000 Subject: [PATCH 3327/3664] small typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f0f4e2f55..3f2bc295d 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ QuakeForge includes several tools for working with Quake data: files. - qfcc is QuakeForge's version of qcc, but is significantly more advanced, with support for standard C syntax, including most C types, - as well as Objective-C object oriented programming (Ruamoko). Mmost of + as well as Objective-C object oriented programming (Ruamoko). Most of the advanced features require the QuakeForge engine, but qfcc can produce progs files compatible with the original Quake engine with limited support for some of the advanced featuers (C syntax, reduced From 89ecde787aa1dfb4c50da1c6d8ae9cfe9318e757 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 11 Jan 2023 17:16:49 +0900 Subject: [PATCH 3328/3664] [vulkan] Use dynamic quad vertices for subpics This gets subpics and the crosshairs working again. --- libs/video/renderer/vulkan/vulkan_draw.c | 86 ++++++++++++++++++------ 1 file changed, 67 insertions(+), 19 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 2f7d041d5..660060933 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -132,9 +132,12 @@ typedef struct drawframe_s { size_t instance_offset; size_t line_offset; VkBuffer instance_buffer; + VkBuffer dvert_buffer; VkBufferView dvert_view; VkDescriptorSet dyn_quad_set; + uint32_t dvertex_index; + uint32_t dvertex_max; descbatchset_t quad_batch; quadqueue_t quad_insts; vertqueue_t line_verts; @@ -165,6 +168,7 @@ typedef struct drawctx_s { VkSampler glyph_sampler; scrap_t *scrap; qfv_stagebuf_t *stage; + int *crosshair_inds; qpic_t *crosshair; int *conchar_inds; qpic_t *conchars; @@ -338,9 +342,13 @@ create_buffers (vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[f]; frame->instance_buffer = dctx->instance_objects[f].buffer.buffer; frame->instance_offset = dctx->instance_objects[f].buffer.offset; + frame->dvert_buffer = dctx->dvertex_objects[f * 2 + 0].buffer.buffer; frame->dvert_view = dctx->dvertex_objects[f * 2 + 1].buffer_view.view; frame->line_offset = dctx->dvertex_objects[f * 2].buffer.offset; + frame->dvertex_index = 0; + frame->dvertex_max = MAX_QUADS * VERTS_PER_QUAD; + DARRAY_INIT (&frame->quad_batch, 16); frame->quad_insts = (quadqueue_t) { .quads = (quadinst_t *) ((byte *)data + frame->instance_offset), @@ -400,11 +408,10 @@ cachepic_getkey (const void *_cp, void *unused) return ((cachepic_t *) _cp)->name; } -static int -create_quad (int x, int y, int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) +static uint32_t +create_quad (int x, int y, int w, int h, qpic_t *pic, uint32_t *vertex_index, + VkBuffer buffer, vulkan_ctx_t *ctx) { - drawctx_t *dctx = ctx->draw_context; - __auto_type pd = (picdata_t *) pic->data; x += pd->subpic->rect->x; @@ -422,16 +429,34 @@ create_quad (int x, int y, int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) verts[2] = (quadvert_t) { {w, 0}, {sr, st} }; verts[3] = (quadvert_t) { {w, h}, {sr, sb} }; - int ind = dctx->svertex_index; - dctx->svertex_index += VERTS_PER_QUAD; - QFV_PacketCopyBuffer (packet, dctx->svertex_objects[0].buffer.buffer, - ind * sizeof (quadvert_t), + int ind = *vertex_index; + *vertex_index += VERTS_PER_QUAD; + QFV_PacketCopyBuffer (packet, buffer, ind * sizeof (quadvert_t), &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]); QFV_PacketSubmit (packet); return ind; } +static int +make_static_quad (int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + + return create_quad (0, 0, w, h, pic, &dctx->svertex_index, + dctx->svertex_objects[0].buffer.buffer, ctx); +} + +static int +make_dyn_quad (int x, int y, int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + + return create_quad (x, y, w, h, pic, &frame->dvertex_index, + frame->dvert_buffer, ctx); +} + static qpic_t * pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) { @@ -445,7 +470,7 @@ pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) pic->height = h; __auto_type pd = (picdata_t *) pic->data; pd->subpic = QFV_ScrapSubpic (dctx->scrap, w, h); - pd->vert_index = create_quad (0, 0, w, h, pic, ctx); + pd->vert_index = make_static_quad (w, h, pic, ctx); picdata = QFV_SubpicBatch (pd->subpic, dctx->stage); size_t size = w * h; @@ -566,14 +591,41 @@ load_conchars (vulkan_ctx_t *ctx) free (charspic); } dctx->conchar_inds = malloc (256 * sizeof (int)); + VkBuffer buffer = dctx->svertex_objects[0].buffer.buffer; for (int i = 0; i < 256; i++) { int cx = i % 16; int cy = i / 16; dctx->conchar_inds[i] = create_quad (cx * 8, cy * 8, 8, 8, - dctx->conchars, ctx); + dctx->conchars, + &dctx->svertex_index, buffer, ctx); } } +static void +load_crosshairs (vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + qpic_t *hairpic = Draw_CrosshairPic (); + dctx->crosshair = pic_data ("crosshair", hairpic->width, + hairpic->height, hairpic->data, ctx); + free (hairpic); + + dctx->crosshair_inds = malloc (4 * sizeof (int)); + VkBuffer buffer = dctx->svertex_objects[0].buffer.buffer; +#define W CROSSHAIR_WIDTH +#define H CROSSHAIR_HEIGHT + dctx->crosshair_inds[0] = create_quad (0, 0, W, H, dctx->crosshair, + &dctx->svertex_index, buffer, ctx); + dctx->crosshair_inds[1] = create_quad (W, 0, W, H, dctx->crosshair, + &dctx->svertex_index, buffer, ctx); + dctx->crosshair_inds[2] = create_quad (0, H, W, H, dctx->crosshair, + &dctx->svertex_index, buffer, ctx); + dctx->crosshair_inds[3] = create_quad (W, H, W, H, dctx->crosshair, + &dctx->svertex_index, buffer, ctx); +#undef W +#undef H +} + void Vulkan_Draw_Init (vulkan_ctx_t *ctx) { @@ -608,12 +660,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->glyph_sampler = Vulkan_CreateSampler (ctx, "glyph"); load_conchars (ctx); - { - qpic_t *hairpic = Draw_CrosshairPic (); - dctx->crosshair = pic_data ("crosshair", hairpic->width, - hairpic->height, hairpic->data, ctx); - free (hairpic); - } + load_crosshairs (ctx); byte white_block = 0xfe; dctx->white_pic = pic_data ("white", 1, 1, &white_block, ctx); @@ -848,7 +895,7 @@ draw_crosshair_pic (int ch, int x, int y, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; byte *color = &vid.palette32[bound (0, crosshaircolor, 255) * 4]; - draw_quad (x, y, 0, ch * 4, color, frame); + draw_quad (x, y, 1, dctx->crosshair_inds[ch - 1], color, frame); } static void (*crosshair_func[]) (int ch, int x, int y, vulkan_ctx_t *ctx) = { @@ -978,9 +1025,9 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + uint32_t vind = make_dyn_quad (srcx, srcy, width, height, pic, ctx); static byte color[4] = { 255, 255, 255, 255}; - __auto_type pd = (picdata_t *) pic->data; - draw_quad (x, y, 1, pd->vert_index, color, frame); + draw_quad (x, y, 0, vind, color, frame); } void @@ -1277,6 +1324,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dframe->quad_insts.count = 0; dframe->line_verts.count = 0; + dframe->dvertex_index = 0; } void From 65005656cb0bd9e248720ebedc1bdbc41eebe311 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Jan 2023 17:06:18 +0900 Subject: [PATCH 3329/3664] [vulkan] Implement tile clear This just takes advantage of the dynamic verts for doing subpics. It's not really the most optimal code as it has to write both the vertices (64 bytes per quad) and the instances (24 bytes per quad), but that's still better than the old 128 bytes per quad (and having a single pipeline is nice). --- libs/video/renderer/vulkan/vulkan_draw.c | 25 +++++++++--------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 660060933..bc346283e 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1055,15 +1055,13 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) void Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) { -#if 0 drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - static quat_t color = { 1, 1, 1, 1}; + static byte color[4] = { 255, 255, 255, 255}; vrect_t *tile_rect = VRect_New (x, y, w, h); vrect_t *sub = VRect_New (0, 0, 0, 0); // filled in later qpic_t *pic = dctx->backtile_pic; - subpic_t *subpic = *(subpic_t **) pic->data; int sub_sx, sub_sy, sub_ex, sub_ey; sub_sx = x / pic->width; @@ -1080,29 +1078,24 @@ Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) sub->height = pic->height; sub = VRect_Intersect (sub, tile_rect); VRect_Delete (t); - draw_pic (sub->x, sub->y, sub->width, sub->height, subpic, - sub->x % pic->width, sub->y % pic->height, - sub->width, sub->height, color, &frame->quad_verts); + int sx = sub->x % pic->width; + int sy = sub->y % pic->height; + int sw = sub->width; + int sh = sub->height; + uint32_t vind = make_dyn_quad (sx, sy, sw, sh, pic, ctx); + draw_quad (sub->x, sub->y, 0, vind, color, frame); } } -#endif } void Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) { -#if 0 drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - quat_t color; - - VectorScale (vid.palette + c * 3, 1.0f/255.0f, color); - color[3] = 1; - subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; - draw_pic (x, y, w, h, subpic, 0, 0, 1, 1, color, - &frame->quad_verts); -#endif + byte color[4] = {VectorExpand (vid.palette + c * 3), 255 }; + draw_slice (x, y, w - 1, h - 1, 1, dctx->white_pic_ind, color, frame); } void From 2f564ca5a63e0bb434eacf6ac847e317506c9f95 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 12 Jan 2023 17:10:43 +0900 Subject: [PATCH 3330/3664] [vulkan] Use slices to implement fills Again, not really the most optimal as 8/9 quads are degenerate, but it went a long way to testing the slice part of the pipeline. --- libs/video/renderer/vulkan/vulkan_draw.c | 100 +++++++++++++++++++---- 1 file changed, 86 insertions(+), 14 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index bc346283e..18ce47256 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -174,6 +174,7 @@ typedef struct drawctx_s { qpic_t *conchars; qpic_t *conback; qpic_t *white_pic; + int white_pic_ind; qpic_t *backtile_pic; // use two separate cmem blocks for pics and strings (cachepic names) // to ensure the names are never in the same cacheline as a pic since the @@ -408,6 +409,46 @@ cachepic_getkey (const void *_cp, void *unused) return ((cachepic_t *) _cp)->name; } +static uint32_t +create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic, + uint32_t *vertex_index, VkBuffer buffer, vulkan_ctx_t *ctx) +{ + __auto_type pd = (picdata_t *) pic->data; + + int x = rect[0] + pd->subpic->rect->x; + int y = rect[1] + pd->subpic->rect->y; + int w = rect[2]; + int h = rect[3]; + int l = border[0]; + int t = border[1]; + int r = w - border[2]; + int b = h - border[3]; + + vec4f_t p[16] = { + { 0, 0, 0, 0 }, { 0, t, 0, t }, { l, 0, l, 0 }, { l, t, l, t }, + { r, 0, r, 0 }, { r, t, r, t }, { w, 0, w, 0 }, { w, t, w, t }, + { 0, b, 0, b }, { 0, h, 0, h }, { l, b, l, b }, { l, h, l, h }, + { r, b, r, b }, { r, h, r, h }, { w, b, w, b }, { w, h, w, h }, + }; + + float s = pd->subpic->size; + vec4f_t size = { 1, 1, s, s }; + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_SLICE); + for (int i = 0; i < VERTS_PER_SLICE; i++) { + vec4f_t v = ((vec4f_t) {0, 0, x, y} + p[i]) * size; + verts[i] = (quadvert_t) { {v[0], v[1]}, {v[2], v[3]} }; + } + + int ind = *vertex_index; + *vertex_index += VERTS_PER_SLICE; + QFV_PacketCopyBuffer (packet, buffer, ind * sizeof (quadvert_t), + &bufferBarriers[qfv_BB_TransferWrite_to_UniformRead]); + QFV_PacketSubmit (packet); + + return ind; +} + static uint32_t create_quad (int x, int y, int w, int h, qpic_t *pic, uint32_t *vertex_index, VkBuffer buffer, vulkan_ctx_t *ctx) @@ -626,6 +667,20 @@ load_crosshairs (vulkan_ctx_t *ctx) #undef H } +static void +load_white_pic (vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + byte white_block = 0xfe; + VkBuffer buffer = dctx->svertex_objects[0].buffer.buffer; + + dctx->white_pic = pic_data ("white", 1, 1, &white_block, ctx); + dctx->white_pic_ind = create_slice ((vec4i_t) {0, 0, 1, 1}, + (vec4i_t) {0, 0, 0, 0}, + dctx->white_pic, + &dctx->svertex_index, buffer, ctx); +} + void Vulkan_Draw_Init (vulkan_ctx_t *ctx) { @@ -661,9 +716,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) load_conchars (ctx); load_crosshairs (ctx); - - byte white_block = 0xfe; - dctx->white_pic = pic_data ("white", 1, 1, &white_block, ctx); + load_white_pic (ctx); dctx->backtile_pic = Vulkan_Draw_PicFromWad ("backtile", ctx); if (!dctx->backtile_pic) { @@ -762,7 +815,28 @@ get_desc_batch (drawframe_t *frame, int descid, uint32_t ind_count) } static inline void -draw_quad (float x, float y, int descid, uint32_t vertid, byte *color, +draw_slice (float x, float y, float ox, float oy, int descid, uint32_t vertid, + const byte *color, drawframe_t *frame) +{ + __auto_type queue = &frame->quad_insts; + if (queue->count >= queue->size) { + return; + } + + __auto_type batch = get_desc_batch (frame, descid, INDS_PER_SLICE); + batch->count++; + + quadinst_t *quad = &queue->quads[queue->count++]; + *quad = (quadinst_t) { + .index = vertid, + .color = { QuatExpand (color) }, + .position = { x, y }, + .offset = { ox, oy }, + }; +} + +static inline void +draw_quad (float x, float y, int descid, uint32_t vertid, const byte *color, drawframe_t *frame) { __auto_type queue = &frame->quad_insts; @@ -1136,22 +1210,20 @@ Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) } static inline void -draw_blendscreen (quat_t color, vulkan_ctx_t *ctx) +draw_blendscreen (const byte *color, vulkan_ctx_t *ctx) { -#if 0 drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + float s = 1.0 / ctx->twod_scale; - subpic_t *subpic = *(subpic_t **) dctx->white_pic->data; - draw_pic (0, 0, vid.width, vid.height, subpic, - 0, 0, 1, 1, color, &frame->quad_verts); -#endif + draw_slice (0, 0, vid.width * s - 1, vid.height * s - 1, + 1, dctx->white_pic_ind, color, frame); } void Vulkan_Draw_FadeScreen (vulkan_ctx_t *ctx) { - static quat_t color = { 0, 0, 0, 0.7 }; + static byte color[4] = { 0, 0, 0, 179 }; draw_blendscreen (color, ctx); } @@ -1324,13 +1396,13 @@ void Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) { if (color[3]) { - quat_t c; + byte c[4]; // pre-multiply alpha. // FIXME this is kind of silly because q1source pre-multiplies alpha // for blends, but this was un-done early in QF's history in order // to avoid a pair of state changes - VectorScale (color, color[3], c); - c[3] = color[3]; + VectorScale (color, color[3] * 255, c); + c[3] = color[3] * 255; draw_blendscreen (c, ctx); } } From 0953446c3eb3f87afba833823248ff5cf342a66f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Jan 2023 11:15:44 +0900 Subject: [PATCH 3331/3664] [vulkan] Load cachepics as separate images They are usually larger images (eg, the main menu graphic) and thus make a mess of the atlas (thus, making them separate means a smaller atlas can be used). All sorts of things are in a mess (descriptor management, subpic rendering not supported, wrong alpha value for the transparent pixel), but this gets the basic loader going. --- libs/video/renderer/vulkan/vulkan_draw.c | 150 +++++++++++++++++++---- 1 file changed, 125 insertions(+), 25 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 18ce47256..6dadbcc08 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -82,6 +82,7 @@ static QFV_Subpass subpass_map[] = { typedef struct pic_data_s { uint32_t vert_index; + uint32_t descid; subpic_t *subpic; } picdata_t; @@ -376,7 +377,9 @@ static void pic_free (drawctx_t *dctx, qpic_t *pic) { __auto_type pd = (picdata_t *) pic->data; - QFV_SubpicDelete (pd->subpic); + if (pd->subpic) { + QFV_SubpicDelete (pd->subpic); + } cmemfree (dctx->pic_memsuper, pic); } @@ -455,13 +458,17 @@ create_quad (int x, int y, int w, int h, qpic_t *pic, uint32_t *vertex_index, { __auto_type pd = (picdata_t *) pic->data; - x += pd->subpic->rect->x; - y += pd->subpic->rect->y; - float size = pd->subpic->size; - float sl = (x + 0) * size; - float sr = (x + w) * size; - float st = (y + 0) * size; - float sb = (y + h) * size; + float sl = 0, sr = 1, st = 0, sb = 1; + + if (pd->subpic) { + x += pd->subpic->rect->x; + y += pd->subpic->rect->y; + float size = pd->subpic->size; + sl = (x + 0) * size; + sr = (x + w) * size; + st = (y + 0) * size; + sb = (y + h) * size; + } qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_QUAD); @@ -512,6 +519,7 @@ pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) __auto_type pd = (picdata_t *) pic->data; pd->subpic = QFV_ScrapSubpic (dctx->scrap, w, h); pd->vert_index = make_static_quad (w, h, pic, ctx); + pd->descid = 1; picdata = QFV_SubpicBatch (pd->subpic, dctx->stage); size_t size = w * h; @@ -556,24 +564,117 @@ Vulkan_Draw_PicFromWad (const char *name, vulkan_ctx_t *ctx) return pic_data (name, wadpic->width, wadpic->height, wadpic->data, ctx); } +static qpic_t * +load_lmp (const char *path, vulkan_ctx_t *ctx) +{ + qpic_t *p; + if (strlen (path) < 4 || strcmp (path + strlen (path) - 4, ".lmp") + || !(p = (qpic_t *) QFS_LoadFile (QFS_FOpenFile (path), 0))) { + return 0; + } + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + drawctx_t *dctx = ctx->draw_context; + int fontid = dctx->fonts.size; + DARRAY_OPEN_AT (&dctx->fonts, fontid, 1); + drawfont_t *font = &dctx->fonts.a[fontid]; + + font->resource = malloc (sizeof (drawfontres_t)); + font->resource->resource = (qfv_resource_t) { + .name = va (ctx->va_ctx, "cachepic:%d", fontid), + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = 2, + .objects = &font->resource->glyph_image, + }; + + tex_t tex = { + .width = p->width, + .height = p->height, + .format = tex_rgba, + .loaded = 1, + .data = p->data, + }; + QFV_ResourceInitTexImage (&font->resource->glyph_image, "image", 0, &tex); + __auto_type cache_image = &font->resource->glyph_image; + + font->resource->glyph_iview = (qfv_resobj_t) { + .name = "image_view", + .type = qfv_res_image_view, + .image_view = { + .image = 0, + .type = VK_IMAGE_VIEW_TYPE_2D, + .format = font->resource->glyph_image.image.format, + .aspect = VK_IMAGE_ASPECT_COLOR_BIT, + .components = { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, + }, + }, + }; + __auto_type cache_iview = &font->resource->glyph_iview; + + QFV_CreateResource (ctx->device, &font->resource->resource); + + __auto_type packet = QFV_PacketAcquire (ctx->staging); + int count = tex.width * tex.height; + byte *texels = QFV_PacketExtend (packet, 4 * count); + Vulkan_ExpandPalette (texels, tex.data, vid.palette32, 2, count); + QFV_PacketCopyImage (packet, cache_image->image.image, + tex.width, tex.height, + &imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]); + QFV_PacketSubmit (packet); + + __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); + layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "quad_data_set"); + __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool"); + __auto_type cache_sets = QFV_AllocateDescriptorSet (device, pool, layouts); + font->set = cache_sets->a[0]; + VkDescriptorImageInfo imageInfo = { + dctx->pic_sampler, + cache_iview->image_view.view, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + font->set, 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo, 0, 0 }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + font->set, 1, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 0, 0, &dctx->svertex_objects[1].buffer_view.view }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + free (cache_sets); + + qpic_t *pic; + pic = cmemalloc (dctx->pic_memsuper, + field_offset (qpic_t, data[sizeof (picdata_t)])); + pic->width = p->width; + pic->height = p->height; + __auto_type pd = (picdata_t *) pic->data; + pd->subpic = 0; + pd->vert_index = make_static_quad (p->width, p->height, pic, ctx); + pd->descid = fontid; + + free (p); + return pic; +} + qpic_t * Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) { - qpic_t *p; - qpic_t *pic; cachepic_t *cpic; drawctx_t *dctx = ctx->draw_context; if ((cpic = Hash_Find (dctx->pic_cache, path))) { return cpic->pic; } - if (strlen (path) < 4 || strcmp (path + strlen (path) - 4, ".lmp") - || !(p = (qpic_t *) QFS_LoadFile (QFS_FOpenFile (path), 0))) { - return 0; - } - - pic = pic_data (path, p->width, p->height, p->data, ctx); - free (p); + qpic_t *pic = load_lmp (path, ctx);; cpic = new_cachepic (dctx, path, pic); Hash_Add (dctx->pic_cache, cpic); return pic; @@ -595,12 +696,11 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) QFV_DestroyResource (device, &dctx->draw_resource[0]); QFV_DestroyResource (device, &dctx->draw_resource[1]); - // the first two "fonts" are reserved for the dynamic and core quad data - // sets and thus does not have its own resources (they are created - // separately) - for (size_t i = 2; i < dctx->fonts.size; i++) { - QFV_DestroyResource (device, &dctx->fonts.a[i].resource->resource); - free (dctx->fonts.a[i].resource); + for (size_t i = 0; i < dctx->fonts.size; i++) { + if (dctx->fonts.a[i].resource) { + QFV_DestroyResource (device, &dctx->fonts.a[i].resource->resource); + free (dctx->fonts.a[i].resource); + } } dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); @@ -1077,7 +1177,7 @@ Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) static byte color[4] = { 255, 255, 255, 255}; __auto_type pd = (picdata_t *) pic->data; - draw_quad (x, y, 1, pd->vert_index, color, frame); + draw_quad (x, y, pd->descid, pd->vert_index, color, frame); } void @@ -1088,7 +1188,7 @@ Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) static byte color[4] = { 255, 255, 255, 255}; __auto_type pd = (picdata_t *) pic->data; - draw_quad (x, y, 1, pd->vert_index, color, frame); + draw_quad (x, y, pd->descid, pd->vert_index, color, frame); } void From 73e5ccd0d53ff30028338e241d3bf66430efd548 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 13 Jan 2023 18:36:14 +0900 Subject: [PATCH 3332/3664] [vulkan] Set transparent color to black I had forgotten that the draw pipeline expects pre-multiplied alpha, thus the pink background for the menu pics. --- libs/video/renderer/vulkan/vulkan_draw.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 6dadbcc08..39982f5f0 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -622,7 +622,12 @@ load_lmp (const char *path, vulkan_ctx_t *ctx) __auto_type packet = QFV_PacketAcquire (ctx->staging); int count = tex.width * tex.height; byte *texels = QFV_PacketExtend (packet, 4 * count); - Vulkan_ExpandPalette (texels, tex.data, vid.palette32, 2, count); + byte palette[256 * 4]; + memcpy (palette, vid.palette32, sizeof (palette)); + palette[255*4 + 0] = 0; + palette[255*4 + 1] = 0; + palette[255*4 + 2] = 0; + Vulkan_ExpandPalette (texels, tex.data, palette, 2, count); QFV_PacketCopyImage (packet, cache_image->image.image, tex.width, tex.height, &imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]); From 2383c12a4aeea335f133196cd53c3570a3338a3f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Jan 2023 00:38:43 +0900 Subject: [PATCH 3333/3664] [renderer] Move r_framecount update out of render_scene This fixes the broken dynamic lighting in fisheye rendering. It does mean that frustum culling of lit surfaces needed to be removed, but if not doing frustum culling on lit surfaces was good enough for a P90, it's probably good enough for an i7-6850K. --- libs/video/renderer/r_light.c | 5 +---- libs/video/renderer/r_screen.c | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 278710005..6875c8cbb 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -300,8 +300,6 @@ R_MarkLights (vec4f_t lightorigin, dlight_t *light, int lightnum, || leaf->mins[1] > maxs[1] || leaf->maxs[1] < mins[1] || leaf->mins[2] > maxs[2] || leaf->maxs[2] < mins[2]) continue; - if (R_CullBox (r_refdef.frustum, leaf->mins, leaf->maxs)) - continue; msurface_t **msurf = brush->marksurfaces + leaf->firstmarksurface; for (m = 0; m < leaf->nummarksurfaces; m++) { msurface_t *surf = *msurf++; @@ -321,8 +319,7 @@ R_PushDlights (const vec3_t entorigin) unsigned int i; dlight_t *l; - // because the count hasn't advanced yet for this frame - r_dlightframecount = r_framecount + 1; + r_dlightframecount = r_framecount; if (!r_dlight_lightmap) return; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index e69fb3fe3..4ccefda0a 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -183,7 +183,6 @@ SCR_CalcRefdef (void) static void render_scene (void) { - r_framecount++; EntQueue_Clear (r_ent_queue); r_funcs->render_view (); r_funcs->draw_particles (&r_psystem); @@ -280,6 +279,7 @@ SCR_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) R_MarkLeaves (scr_scene->viewleaf, r_node_visframes, r_leaf_visframes, r_face_visframes); } + r_framecount++; R_PushDlights (vec3_origin); r_funcs->begin_frame (); From 883351882609c10e8fcd4f266964a83e61846f14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Jan 2023 11:32:12 +0900 Subject: [PATCH 3334/3664] [ecs] Support sorting subpools Sorting the whole pool when subpools are in use could break the subpools (very high probability, depending on the sort criteria and subpool criteria). --- include/QF/ecs.h | 3 +++ include/QF/ui/canvas.h | 3 +++ libs/ecs/ecs.c | 29 ++++++++++++++++++++++------- libs/ui/canvas.c | 37 +++++++++++++++++++++++++++++++++---- 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/include/QF/ecs.h b/include/QF/ecs.h index dc082c016..c5402daaa 100644 --- a/include/QF/ecs.h +++ b/include/QF/ecs.h @@ -117,6 +117,9 @@ typedef int (*__compar_d_fn_t)(const void *, const void *, void *); #endif void ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, __compar_d_fn_t cmp, void *arg); +void ECS_SortComponentPoolRange (ecs_registry_t *registry, uint32_t component, + ecs_range_t range, + __compar_d_fn_t cmp, void *arg); uint32_t ECS_NewEntity (ecs_registry_t *registry); void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent); diff --git a/include/QF/ui/canvas.h b/include/QF/ui/canvas.h index e6ab30dc3..0033ff739 100644 --- a/include/QF/ui/canvas.h +++ b/include/QF/ui/canvas.h @@ -78,5 +78,8 @@ typedef struct canvas_subpic_s { void Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent); void Canvas_Draw (canvas_system_t canvas_sys); +void Canvas_SortComponentPool (canvas_system_t canvas_sys, uint32_t ent, + uint32_t component); + #endif//__QF_scene_canvas_h diff --git a/libs/ecs/ecs.c b/libs/ecs/ecs.c index 8f91107ea..a53d83ae0 100644 --- a/libs/ecs/ecs.c +++ b/libs/ecs/ecs.c @@ -125,6 +125,26 @@ ecs_swap (void *_a, void *_b, void *arg) swap_uint32 (&pool->sparse[a_ent_ind], &pool->sparse[b_ent_ind]); } +VISIBLE void +ECS_SortComponentPoolRange (ecs_registry_t *registry, uint32_t component, + ecs_range_t range, __compar_d_fn_t cmp, void *arg) +{ + if (component >= registry->components.size) { + Sys_Error ("ECS_SortComponentPoolRange: invalid component: %u", + component); + } + ecs_pool_t *pool = ®istry->comp_pools[component]; + if (!pool->count || range.end <= range.start) { + return; + } + uint32_t count = range.end - range.start; + uint32_t *start = pool->dense + range.start; + __auto_type comp = ®istry->components.a[component]; + ecs_sort_t sortctx = { .cmp = cmp, .arg = arg, .pool = pool, .comp = comp }; + heapsort_s (start, count, sizeof (uint32_t), + ecs_compare, ecs_swap, &sortctx); +} + VISIBLE void ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, __compar_d_fn_t cmp, void *arg) @@ -133,13 +153,8 @@ ECS_SortComponentPool (ecs_registry_t *registry, uint32_t component, Sys_Error ("ECS_SortComponentPool: invalid component: %u", component); } ecs_pool_t *pool = ®istry->comp_pools[component]; - if (!pool->count) { - return; - } - __auto_type comp = ®istry->components.a[component]; - ecs_sort_t sortctx = { .cmp = cmp, .arg = arg, .pool = pool, .comp = comp }; - heapsort_s (pool->dense, pool->count, sizeof (uint32_t), - ecs_compare, ecs_swap, &sortctx); + ecs_range_t range = { .start = 0, .end = pool->count }; + ECS_SortComponentPoolRange (registry, component, range, cmp, arg); } VISIBLE uint32_t diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index 84cc40b63..6d7e621bf 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -312,10 +312,10 @@ Canvas_Draw (canvas_system_t canvas_sys) }; uint32_t comp = canvas_sys.base + canvas_canvas; - ecs_pool_t *pool = &canvas_sys.reg->comp_pools[comp]; - uint32_t count = pool->count; - //uint32_t *entities = pool->dense; - __auto_type canvases = (canvas_t *) pool->data; + ecs_pool_t *canvas_pool = &canvas_sys.reg->comp_pools[comp]; + uint32_t count = canvas_pool->count; + //uint32_t *entities = canvas_pool->dense; + __auto_type canvases = (canvas_t *) canvas_pool->data; while (count-- > 0) { canvas_t *canvas = canvases++; @@ -347,3 +347,32 @@ Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent) (ecs_system_t) { canvas_sys.reg, canvas_sys.view_base }, nullview); } + +static int +canvas_href_cmp (const void *_a, const void *_b, void *arg) +{ + uint32_t enta = *(const uint32_t *)_a; + uint32_t entb = *(const uint32_t *)_b; + canvas_system_t *canvas_sys = arg; + ecs_registry_t *reg = canvas_sys->reg; + uint32_t href = canvas_sys->view_base + view_href; + hierref_t *ref_a = Ent_GetComponent (enta, href, reg); + hierref_t *ref_b = Ent_GetComponent (entb, href, reg); + if (ref_a->hierarchy == ref_b->hierarchy) { + return ref_a->index - ref_b->index; + } + ptrdiff_t diff = ref_a->hierarchy - ref_b->hierarchy; + return diff > 0 ? 1 : diff < 0 ? -1 : 0; +} + +void +Canvas_SortComponentPool (canvas_system_t canvas_sys, uint32_t ent, + uint32_t component) +{ + canvas_t *canvas = Ent_GetComponent (ent, canvas_sys.base + canvas_canvas, + canvas_sys.reg); + uint32_t rid = canvas->range[component - canvas_sys.base]; + ecs_range_t range = ECS_GetSubpoolRange (canvas_sys.reg, component, rid); + ECS_SortComponentPoolRange (canvas_sys.reg, component, range, + canvas_href_cmp, &canvas_sys); +} From 31c1420682f95a6e0bae1088a7d6b9f577058b30 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 16 Jan 2023 13:23:44 +0900 Subject: [PATCH 3335/3664] [client] Further decouple screen and console The wording might seem a little odd, but cl_screen is really the full 2D client HUD while the console is completely independent of the client and shouldn't know that the client even exists. Ideally, the resize events would be handled by the canvas system, to which end this is a small step. --- include/QF/plugin/console.h | 1 - libs/client/cl_screen.c | 37 ++++++++++++++++++++++++++++++++++++- libs/console/client.c | 8 -------- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index 5d4393983..8d6e14902 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -51,7 +51,6 @@ typedef struct console_data_s { int ormask; void (*quit) (void); struct cbuf_s *cbuf; - struct view_s *screen_view; struct view_s *status_view; float lines; int (*exec_line)(void *data, const char *line); diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index c86b1bd94..8705735c5 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -164,15 +164,45 @@ static SCR_Func *scr_funcs[] = { scr_funcs_intermission, }; +static int cl_scale; +static int cl_xlen; +static int cl_ylen; + +static void +cl_set_size (void) +{ + int xlen = cl_xlen / cl_scale; + int ylen = cl_ylen / cl_scale; + printf ("cl_set_size: %d %d %d\n", cl_scale, xlen, ylen); + View_SetLen (cl_screen_view, xlen, ylen); + View_UpdateHierarchy (cl_screen_view); +} + +static void +cl_scale_listener (void *data, const cvar_t *cvar) +{ + cl_scale = *(int *) cvar->value.value; + cl_set_size (); +} + +static void +cl_vidsize_listener (void *data, const viddef_t *vdef) +{ + cl_xlen = vdef->width; + cl_ylen = vdef->height; + cl_set_size (); +} + void CL_Init_Screen (void) { qpic_t *pic; HUD_Init (); + cl_xlen = viddef.width; + cl_ylen = viddef.height; cl_screen_view = View_New (hud_viewsys, nullview); - con_module->data->console->screen_view = &cl_screen_view; View_SetPos (cl_screen_view, 0, 0); View_SetLen (cl_screen_view, viddef.width, viddef.height); @@ -240,6 +270,11 @@ CL_Init_Screen (void) View_SetGravity (pause_view, grav_center); Ent_SetComponent (pause_view.id, hud_cachepic, pause_view.reg, &name); View_SetVisible (pause_view, 0); + + cvar_t *con_scale = Cvar_FindVar ("con_scale"); + Cvar_AddListener (con_scale, cl_scale_listener, 0); + cl_scale_listener (0, con_scale); + VID_OnVidResize_AddListener (cl_vidsize_listener, 0); } void diff --git a/libs/console/client.c b/libs/console/client.c index e1678ce1f..b05cb13b9 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -830,17 +830,9 @@ con_set_size (void) if (xlen > 0 && ylen > 0) { View_SetLen (screen_view, xlen, ylen); View_UpdateHierarchy (screen_view); - if (con_data.screen_view) { - View_SetLen (*con_data.screen_view, xlen, ylen); - View_UpdateHierarchy (*con_data.screen_view); - } } } -// The console view is not a child of the client's screen view, so it won't -// get resized automatically when the screen changes size. However, since the -// console has to process input events anyway, handling ie_app_window is a -// reasonable alternative. static void con_app_window (const IE_event_t *event) { From 96c82106f983458091ed3c2462d2c42baa241b48 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Jan 2023 11:31:46 +0900 Subject: [PATCH 3336/3664] [sw] Remove hand loop unrolling from pic and conback GCC has done a better job for about twenty years. Readability for the win :). --- libs/video/renderer/sw/draw.c | 45 ++++++----------------------------- 1 file changed, 7 insertions(+), 38 deletions(-) diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 8a63715b2..778a96002 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -526,38 +526,13 @@ Draw_Pic (int x, int y, qpic_t *pic) dest = d_viewbuffer + y * d_rowbytes + x; - if (pic->width & 7) { // general - for (v = 0; v < pic->height; v++) { - for (u = 0; u < pic->width; u++) - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = tbyte; + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u++) + if ((tbyte = source[u]) != TRANSPARENT_COLOR) + dest[u] = tbyte; - dest += d_rowbytes; - source += pic->width; - } - } else { // unwound - for (v = 0; v < pic->height; v++) { - for (u = 0; u < pic->width; u += 8) { - if ((tbyte = source[u]) != TRANSPARENT_COLOR) - dest[u] = tbyte; - if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR) - dest[u + 1] = tbyte; - if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR) - dest[u + 2] = tbyte; - if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR) - dest[u + 3] = tbyte; - if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR) - dest[u + 4] = tbyte; - if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR) - dest[u + 5] = tbyte; - if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR) - dest[u + 6] = tbyte; - if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) - dest[u + 7] = tbyte; - } - dest += d_rowbytes; - source += pic->width; - } + dest += d_rowbytes; + source += pic->width; } } @@ -660,15 +635,9 @@ Draw_ConsoleBackground (int lines, byte alpha) else { f = 0; fstep = 320 * 0x10000 / vid.width; - for (unsigned x = 0; x < vid.width; x += 4) { + for (unsigned x = 0; x < vid.width; x++) { dest[x] = src[f >> 16]; f += fstep; - dest[x + 1] = src[f >> 16]; - f += fstep; - dest[x + 2] = src[f >> 16]; - f += fstep; - dest[x + 3] = src[f >> 16]; - f += fstep; } } } From 4e1ddaa964f5f818e9a022991a48567ecced519d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Jan 2023 11:33:47 +0900 Subject: [PATCH 3337/3664] [renderer] Add fitted pic rendering The pic is scaled to fill the specified rect (then clipped to the screen (effectively)). Done just for the console background for now, but it will be used for slice-pics as well. Not implemented for vulkan yet as I'm still thinking about the descriptor management needed for the instanced rendering. Making the conback rendering conditional gave an approximately 3% speed boost to glsl with the GL stub (~12200fps to ~12550fps), for either conback render method. --- include/QF/GL/qf_draw.h | 1 + include/QF/GLSL/qf_draw.h | 1 + include/QF/Vulkan/qf_draw.h | 2 + include/QF/draw.h | 9 ++++ include/QF/plugin/vid_render.h | 1 + include/QF/ui/canvas.h | 1 + libs/console/client.c | 22 ++++++---- libs/ui/canvas.c | 28 ++++++++++++- libs/video/renderer/gl/gl_draw.c | 20 +++++++++ libs/video/renderer/glsl/glsl_draw.c | 7 ++++ libs/video/renderer/sw/draw.c | 52 ++++++++++++++++++++++++ libs/video/renderer/vid_render_gl.c | 1 + libs/video/renderer/vid_render_glsl.c | 1 + libs/video/renderer/vid_render_sw.c | 1 + libs/video/renderer/vid_render_vulkan.c | 7 ++++ libs/video/renderer/vulkan/vulkan_draw.c | 6 +++ 16 files changed, 150 insertions(+), 10 deletions(-) diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index f9f9eb004..9674594ba 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -55,6 +55,7 @@ struct qpic_s *gl_Draw_MakePic (int width, int height, const byte *data); void gl_Draw_DestroyPic (struct qpic_s *pic); struct qpic_s *gl_Draw_PicFromWad (const char *name); void gl_Draw_Pic (int x, int y, struct qpic_s *pic); +void gl_Draw_FitPic (int x, int y, int width, int height, struct qpic_s *pic); void gl_Draw_Picf (float x, float y, struct qpic_s *pic); void gl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index bc5def658..3a8ea0276 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -56,6 +56,7 @@ struct qpic_s *glsl_Draw_MakePic (int width, int height, const byte *data); void glsl_Draw_DestroyPic (struct qpic_s *pic); struct qpic_s *glsl_Draw_PicFromWad (const char *name); void glsl_Draw_Pic (int x, int y, struct qpic_s *pic); +void glsl_Draw_FitPic (int x, int y, int width, int height, struct qpic_s *pic); void glsl_Draw_Picf (float x, float y, struct qpic_s *pic); void glsl_Draw_SubPic(int x, int y, struct qpic_s *pic, int srcx, int srcy, int width, int height); diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 4182fe5d9..8b65e114c 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -76,6 +76,8 @@ struct qpic_s *Vulkan_Draw_PicFromWad (const char *name, struct vulkan_ctx_s *ctx); void Vulkan_Draw_Pic (int x, int y, struct qpic_s *pic, struct vulkan_ctx_s *ctx); +void Vulkan_Draw_FitPic (int x, int y, int width, int height, + struct qpic_s *pic, struct vulkan_ctx_s *ctx); void Vulkan_Draw_Picf (float x, float y, struct qpic_s *pic, struct vulkan_ctx_s *ctx); void Vulkan_Draw_SubPic(int x, int y, struct qpic_s *pic, diff --git a/include/QF/draw.h b/include/QF/draw.h index 780063064..82d0eee8a 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -245,6 +245,15 @@ qpic_t *Draw_PicFromWad (const char *name); */ void Draw_Pic (int x, int y, qpic_t *pic); +/** Draw a qpic to the screen, scaled to fit the given width and height + \param x horizontal location of the upper left corner of the qpic + \param y vertical location of the upper left corner of the qpic + \param width horizontal size of the output pic + \param height vertical size of the output pic + \param pic qpic to draw +*/ +void Draw_FitPic (int x, int y, int width, int height, qpic_t *pic); + /** Draw a qpic to the screen \param x horizontal location of the upper left corner of the qpic \param y vertical location of the upper left corner of the qpic diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index cb9a96304..b4a1e441f 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -108,6 +108,7 @@ typedef struct vid_render_funcs_s { void (*Draw_DestroyPic) (qpic_t *pic); qpic_t *(*Draw_PicFromWad) (const char *name); void (*Draw_Pic) (int x, int y, qpic_t *pic); + void (*Draw_FitPic) (int x, int y, int width, int height, qpic_t *pic); void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); int (*Draw_AddFont) (struct font_s *font); diff --git a/include/QF/ui/canvas.h b/include/QF/ui/canvas.h index 0033ff739..2c832120f 100644 --- a/include/QF/ui/canvas.h +++ b/include/QF/ui/canvas.h @@ -38,6 +38,7 @@ enum { canvas_updateonce, canvas_tile, canvas_pic, + canvas_fitpic, // pic is scaled to fit the view canvas_subpic, canvas_cachepic, canvas_fill, diff --git a/libs/console/client.c b/libs/console/client.c index b05cb13b9..23371e14a 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -667,17 +667,21 @@ static void draw_console (view_t view) { byte alpha; + view_pos_t len = View_GetLen (screen_view); - if (con_state == con_fullscreen) { - alpha = 255; - } else { - view_pos_t len = View_GetLen (screen_view); - float y = len.y * con_size; - alpha = 255 * con_alpha * len.y / y; - alpha = min (alpha, 255); + if (con_data.lines > 0) { + // draw the background + if (con_state == con_fullscreen) { + alpha = 255; + } else { + float y = len.y * con_size; + alpha = 255 * con_alpha * len.y / y; + alpha = min (alpha, 255); + } + //r_funcs->Draw_ConsoleBackground (con_data.lines, alpha); + qpic_t *pic = r_funcs->Draw_CachePic ("gfx/conback.lmp", false); + r_funcs->Draw_FitPic (0, con_data.lines - len.y, len.x, len.y, pic); } - // draw the background - r_funcs->Draw_ConsoleBackground (con_data.lines, alpha); update_notify (); // draw everything else diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index 6d7e621bf..c4506fc00 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -49,6 +49,7 @@ canvas_rangeid(update) canvas_rangeid(updateonce) canvas_rangeid(tile) canvas_rangeid(pic) +canvas_rangeid(fitpic) canvas_rangeid(subpic) canvas_rangeid(cachepic) canvas_rangeid(fill) @@ -75,7 +76,7 @@ const component_t canvas_components[canvas_comp_count] = { }, [canvas_tile] = { .size = sizeof (byte), - .name = "pic", + .name = "tile", .rangeid = canvas_tile_rangeid, }, [canvas_pic] = { @@ -83,6 +84,11 @@ const component_t canvas_components[canvas_comp_count] = { .name = "pic", .rangeid = canvas_pic_rangeid, }, + [canvas_fitpic] = { + .size = sizeof (qpic_t *), + .name = "fitpic", + .rangeid = canvas_fitpic_rangeid, + }, [canvas_subpic] = { .size = sizeof (canvas_subpic_t), .name = "subpic", @@ -177,6 +183,25 @@ draw_pic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, } } +static void +draw_fitpic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, + ecs_range_t range) +{ + ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; + uint32_t count = range.end - range.start; + uint32_t *ent = pool->dense; + __auto_type pic = (qpic_t **) pool->data + range.start; + while (count-- > 0) { + view_t view = View_FromEntity (viewsys, *ent++); + if (View_GetVisible (view)) { + view_pos_t pos = View_GetAbs (view); + view_pos_t len = View_GetLen (view); + r_funcs->Draw_FitPic (pos.x, pos.y, len.x, len.y, *pic); + } + pic++; + } +} + static void draw_subpic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, ecs_range_t range) @@ -303,6 +328,7 @@ Canvas_Draw (canvas_system_t canvas_sys) [canvas_updateonce] = draw_updateonce, [canvas_tile] = draw_tile_views, [canvas_pic] = draw_pic_views, + [canvas_fitpic] = draw_fitpic_views, [canvas_subpic] = draw_subpic_views, [canvas_cachepic] = draw_cachepic_views, [canvas_fill] = draw_fill_views, diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 7ed383cf6..61ea1d9a7 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -761,6 +761,26 @@ gl_Draw_Pic (int x, int y, qpic_t *pic) qfglEnd (); } +void +gl_Draw_FitPic (int x, int y, int width, int height, qpic_t *pic) +{ + glpic_t *gl; + + gl = (glpic_t *) pic->data; + + qfglBindTexture (GL_TEXTURE_2D, gl->texnum); + qfglBegin (GL_QUADS); + qfglTexCoord2f (0, 0); + qfglVertex2f (x, y); + qfglTexCoord2f (1, 0); + qfglVertex2f (x + width, y); + qfglTexCoord2f (1, 1); + qfglVertex2f (x + width, y + height); + qfglTexCoord2f (0, 1); + qfglVertex2f (x, y + height); + qfglEnd (); +} + void gl_Draw_Picf (float x, float y, qpic_t *pic) { diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 428e9db9c..73a9b661e 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -661,6 +661,13 @@ glsl_Draw_Pic (int x, int y, qpic_t *pic) 0, 0, pic->width, pic->height, color); } +void +glsl_Draw_FitPic (int x, int y, int width, int height, qpic_t *pic) +{ + static quat_t color = { 1, 1, 1, 1}; + draw_pic (x, y, width, height, pic, 0, 0, pic->width, pic->height, color); +} + void glsl_Draw_Picf (float x, float y, qpic_t *pic) { diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 778a96002..7c19bc473 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -536,6 +536,58 @@ Draw_Pic (int x, int y, qpic_t *pic) } } +void +Draw_FitPic (int x, int y, int width, int height, qpic_t *pic) +{ + int v_width = vid.width; + int v_height = vid.height; + if (x > v_width || y > v_width || x + width <= 0 || y + height <= 0) { + return; + } + if (width == pic->width && height == pic->height) { + Draw_Pic (x, y, pic); + return; + } + int sstep = pic->width * 0x10000 / width; + int tstep = pic->height * 0x10000 / height; + int sx = 0, ex = width; + int sy = 0, ey = height; + + if (x < 0) { + sx -= x; + ex += x; + } + if (y < 0) { + sy -= y; + ey += y; + } + if (x + width > v_width) { + ex -= x + width - v_width; + } + if (y + height > v_height) { + ey -= y + height - v_height; + } + x += sx; + y += sy; + + byte *src, *dst; + + // draw the pic + dst = d_viewbuffer + y * d_rowbytes + x; + + for (int y = sy; y < sy + ey; y++, dst += d_rowbytes) { + src = pic->data + ((y * tstep) >> 16) * pic->width; + if (width == pic->width) + memcpy (dst, src, width); + else { + int f = sx * sstep; + for (int x = 0; x < ex; x++, f += sstep) { + dst[x] = src[f >> 16]; + } + } + } +} + void Draw_Picf (float x, float y, qpic_t *pic) { diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 6c13ad913..51229897d 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -522,6 +522,7 @@ vid_render_funcs_t gl_vid_render_funcs = { .Draw_DestroyPic = gl_Draw_DestroyPic, .Draw_PicFromWad = gl_Draw_PicFromWad, .Draw_Pic = gl_Draw_Pic, + .Draw_FitPic = gl_Draw_FitPic, .Draw_Picf = gl_Draw_Picf, .Draw_SubPic = gl_Draw_SubPic, .Draw_AddFont = gl_Draw_AddFont, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 26375d469..3070b963a 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -466,6 +466,7 @@ vid_render_funcs_t glsl_vid_render_funcs = { .Draw_DestroyPic = glsl_Draw_DestroyPic, .Draw_PicFromWad = glsl_Draw_PicFromWad, .Draw_Pic = glsl_Draw_Pic, + .Draw_FitPic = glsl_Draw_FitPic, .Draw_Picf = glsl_Draw_Picf, .Draw_SubPic = glsl_Draw_SubPic, .Draw_AddFont = glsl_Draw_AddFont, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 3ef972ae6..703eee190 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -479,6 +479,7 @@ vid_render_funcs_t sw_vid_render_funcs = { .Draw_DestroyPic = Draw_DestroyPic, .Draw_PicFromWad = Draw_PicFromWad, .Draw_Pic = Draw_Pic, + .Draw_FitPic = Draw_FitPic, .Draw_Picf = Draw_Picf, .Draw_SubPic = Draw_SubPic, .Draw_AddFont = Draw_AddFont, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 093e042ae..95403632d 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -272,6 +272,12 @@ vulkan_Draw_Pic (int x, int y, qpic_t *pic) Vulkan_Draw_Pic (x, y, pic, vulkan_ctx); } +static void +vulkan_Draw_FitPic (int x, int y, int width, int height, qpic_t *pic) +{ + Vulkan_Draw_FitPic (x, y, width, height, pic, vulkan_ctx); +} + static void vulkan_Draw_Picf (float x, float y, qpic_t *pic) { @@ -789,6 +795,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { .Draw_DestroyPic = vulkan_Draw_DestroyPic, .Draw_PicFromWad = vulkan_Draw_PicFromWad, .Draw_Pic = vulkan_Draw_Pic, + .Draw_FitPic = vulkan_Draw_FitPic, .Draw_Picf = vulkan_Draw_Picf, .Draw_SubPic = vulkan_Draw_SubPic, .Draw_AddFont = vulkan_Draw_AddFont, diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 39982f5f0..b73816d33 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1185,6 +1185,12 @@ Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) draw_quad (x, y, pd->descid, pd->vert_index, color, frame); } +void +Vulkan_Draw_FitPic (int x, int y, int widht, int height, qpic_t *pic, + vulkan_ctx_t *ctx) +{ +} + void Vulkan_Draw_Picf (float x, float y, qpic_t *pic, vulkan_ctx_t *ctx) { From d2467f14247a610b4a90ca63983472d3f25f063f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 17 Jan 2023 20:49:22 +0900 Subject: [PATCH 3338/3664] [vulkan] Use dynamic descriptors for dynamic verts When a pic needs dynamic vertices (eg, for sub-pics), a descriptor set is allocated and updated if one has not been created for the pic. This is done each frame: the descriptor sets are recycled (there currently is rarely a need for more than a small handful of dynamic descriptors, so 64 should be plenty for now). Unfortunately, due to the order of operations issue between draw items getting queued and submitting commands to vulkan (the cause of the pics not rendering correctly per 8fff71ed4bdb7e79605f82da58225bf1e90643c4), the validation layers complain (correctly) about the command buffers being executed with updated descriptor sets. Getting the canvas system up and running will fix that. --- libs/video/renderer/vulkan/vulkan_draw.c | 98 ++++++++++++++++++------ 1 file changed, 74 insertions(+), 24 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index b73816d33..d9b58b24c 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -129,13 +129,26 @@ typedef struct cachepic_s { qpic_t *pic; } cachepic_t; +// core pic atlas + static verts +#define CORE_DESC 0 +// FIXME must match pool size in pl_quake_def.plist descriptorPools.quad_pool +// should do some reflection +#define MAX_DESCIPTORS 64 + +typedef struct descpool_s { + VkDescriptorSet sets[MAX_DESCIPTORS]; + VkDescriptorPool pool; + struct drawctx_s *dctx; + uint32_t users[MAX_DESCIPTORS];// picdata_t.descid + int in_use; +} descpool_t; + typedef struct drawframe_s { size_t instance_offset; size_t line_offset; VkBuffer instance_buffer; VkBuffer dvert_buffer; VkBufferView dvert_view; - VkDescriptorSet dyn_quad_set; uint32_t dvertex_index; uint32_t dvertex_max; @@ -143,6 +156,7 @@ typedef struct drawframe_s { quadqueue_t quad_insts; vertqueue_t line_verts; qfv_cmdbufferset_t cmdSet; + descpool_t dyn_descs; } drawframe_t; typedef struct drawframeset_s @@ -217,6 +231,46 @@ typedef struct drawctx_s { #define DVERTS_PER_FRAME (LINES_OFFSET + MAX_LINES*VERTS_PER_LINE) +static int +get_dyn_descriptor (descpool_t *pool, qpic_t *pic, VkBufferView buffer_view, + vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type pd = (picdata_t *) pic->data; + uint32_t id = pd->descid; + for (int i = 0; i < pool->in_use; i++) { + if (pool->users[i] == id) { + return ~i; + } + } + if (pool->in_use >= MAX_DESCIPTORS) { + Sys_Error ("get_dyn_descriptor: out of dynamic desciptors"); + } + int descid = pool->in_use++; + pool->users[descid] = id; + if (!pool->sets[descid]) { + __auto_type layout = QFV_AllocDescriptorSetLayoutSet (1, alloca); + layout->a[0] = pool->dctx->quad_data_set_layout; + __auto_type set = QFV_AllocateDescriptorSet (device, pool->pool, layout); + pool->sets[descid] = set->a[0];; + free (set);//FIXME allocation + } + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + pool->sets[descid], 1, 0, 1, + VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 0, 0, &buffer_view }, + }; + VkCopyDescriptorSet copy[] = { + { VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET, 0, + pool->dctx->fonts.a[id].set, 0, 0, + pool->sets[descid], 0, 0, 1 }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 1, copy); + return ~descid; +} + static void generate_slice_indices (qfv_stagebuf_t *staging, qfv_resobj_t *ind_buffer) { @@ -519,7 +573,7 @@ pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) __auto_type pd = (picdata_t *) pic->data; pd->subpic = QFV_ScrapSubpic (dctx->scrap, w, h); pd->vert_index = make_static_quad (w, h, pic, ctx); - pd->descid = 1; + pd->descid = CORE_DESC; picdata = QFV_SubpicBatch (pd->subpic, dctx->stage); size_t size = w * h; @@ -855,18 +909,10 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); for (size_t i = 1; i < sets->size; i++) { __auto_type frame = &dctx->frames.a[i - 1]; - frame->dyn_quad_set = sets->a[i]; - VkWriteDescriptorSet write[] = { - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - frame->dyn_quad_set, 0, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &imageInfo, 0, 0 }, - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - frame->dyn_quad_set, 1, 0, 1, - VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, - 0, 0, &frame->dvert_view }, - }; - dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + frame->dyn_descs = (descpool_t) {}; + //FIXME returns same pool every time + frame->dyn_descs.pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool"); + frame->dyn_descs.dctx = dctx; } dctx->core_quad_set = sets->a[0]; free (sets); @@ -883,7 +929,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) }; dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); - DARRAY_APPEND (&dctx->fonts, (drawfont_t) {}); DARRAY_APPEND (&dctx->fonts, (drawfont_t) { .set = dctx->core_quad_set }); for (size_t i = 0; i < frames; i++) { @@ -968,7 +1013,7 @@ queue_character (int x, int y, byte chr, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; byte color[4] = {255, 255, 255, 255}; - draw_quad (x, y, 1, dctx->conchar_inds[chr], color, frame); + draw_quad (x, y, CORE_DESC, dctx->conchar_inds[chr], color, frame); } void @@ -1074,7 +1119,7 @@ draw_crosshair_pic (int ch, int x, int y, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; byte *color = &vid.palette32[bound (0, crosshaircolor, 255) * 4]; - draw_quad (x, y, 1, dctx->crosshair_inds[ch - 1], color, frame); + draw_quad (x, y, CORE_DESC, dctx->crosshair_inds[ch - 1], color, frame); } static void (*crosshair_func[]) (int ch, int x, int y, vulkan_ctx_t *ctx) = { @@ -1212,7 +1257,9 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, uint32_t vind = make_dyn_quad (srcx, srcy, width, height, pic, ctx); static byte color[4] = { 255, 255, 255, 255}; - draw_quad (x, y, 0, vind, color, frame); + int descid = get_dyn_descriptor (&frame->dyn_descs, pic, + frame->dvert_view, ctx); + draw_quad (x, y, descid, vind, color, frame); } void @@ -1248,6 +1295,8 @@ Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) vrect_t *sub = VRect_New (0, 0, 0, 0); // filled in later qpic_t *pic = dctx->backtile_pic; int sub_sx, sub_sy, sub_ex, sub_ey; + int descid = get_dyn_descriptor (&frame->dyn_descs, pic, + frame->dvert_view, ctx); sub_sx = x / pic->width; sub_sy = y / pic->height; @@ -1268,7 +1317,7 @@ Vulkan_Draw_TileClear (int x, int y, int w, int h, vulkan_ctx_t *ctx) int sw = sub->width; int sh = sub->height; uint32_t vind = make_dyn_quad (sx, sy, sw, sh, pic, ctx); - draw_quad (sub->x, sub->y, 0, vind, color, frame); + draw_quad (sub->x, sub->y, descid, vind, color, frame); } } } @@ -1280,7 +1329,8 @@ Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; byte color[4] = {VectorExpand (vid.palette + c * 3), 255 }; - draw_slice (x, y, w - 1, h - 1, 1, dctx->white_pic_ind, color, frame); + draw_slice (x, y, w - 1, h - 1, + CORE_DESC, dctx->white_pic_ind, color, frame); } void @@ -1328,7 +1378,7 @@ draw_blendscreen (const byte *color, vulkan_ctx_t *ctx) float s = 1.0 / ctx->twod_scale; draw_slice (0, 0, vid.width * s - 1, vid.height * s - 1, - 1, dctx->white_pic_ind, color, frame); + CORE_DESC, dctx->white_pic_ind, color, frame); } void @@ -1413,7 +1463,8 @@ draw_quads (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) inst_count &= 0xffffff; VkDescriptorSet set[2] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - dctx->fonts.a[fontid].set, + fontid < 0 ? dframe->dyn_descs.sets[~fontid] + : dctx->fonts.a[fontid].set, }; VkPipelineLayout layout = dctx->quad_layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, @@ -1462,8 +1513,6 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) return; } - dctx->fonts.a[0].set = dframe->dyn_quad_set; - VkDeviceMemory memory = dctx->draw_resource[1].memory; size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; size_t atom_mask = atom - 1; @@ -1501,6 +1550,7 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dframe->quad_insts.count = 0; dframe->line_verts.count = 0; dframe->dvertex_index = 0; + dframe->dyn_descs.in_use = 0; } void From 07d5749a4e21ace07d804c7c0b94ddc9aa55ef1e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 00:09:41 +0900 Subject: [PATCH 3339/3664] [renderer] Make the core of SCR_UpdateScreen dynamic This is a bit of a hack to allow me to work on vulkan's screen update "pipeline" without having to mess with the other renderers, since it turns out they're (currently) fundamentally incompatible. --- include/QF/plugin/vid_render.h | 2 + include/QF/screen.h | 2 + libs/video/renderer/r_screen.c | 96 +++++++++++++------------ libs/video/renderer/vid_render_gl.c | 2 + libs/video/renderer/vid_render_glsl.c | 2 + libs/video/renderer/vid_render_sw.c | 2 + libs/video/renderer/vid_render_vulkan.c | 2 + 7 files changed, 63 insertions(+), 45 deletions(-) diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index b4a1e441f..b581692cb 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -87,6 +87,8 @@ typedef void (*capfunc_t) (struct tex_s *screencap, void *data); typedef struct vid_render_funcs_s { void (*init) (void); + void (*UpdateScreen) (struct transform_s camera, double realtime, + SCR_Func *scr_funcs); void (*Draw_CharBuffer) (int x, int y, struct draw_charbuffer_s *buffer); void (*Draw_SetScale) (int scale); void (*Draw_Character) (int x, int y, unsigned ch); diff --git a/include/QF/screen.h b/include/QF/screen.h index e462b8269..0e4b8b548 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -39,6 +39,8 @@ typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array void SCR_UpdateScreen (struct transform_s camera, double realtime, SCR_Func *scr_funcs); +void SCR_UpdateScreen_legacy (struct transform_s camera, double realtime, + SCR_Func *scr_funcs); void SCR_SetFOV (float fov); // control whether the 3d viewport is user-controlled or always fullscreen void SCR_SetFullscreen (qboolean fullscreen); diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 4ccefda0a..16e95dc72 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -218,6 +218,56 @@ render_side (int side) memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); } +void +SCR_UpdateScreen_legacy (transform_t camera, double realtime, + SCR_Func *scr_funcs) +{ + if (scr_fisheye && !fisheye_cube_map) { + fisheye_cube_map = r_funcs->create_cube_map (r_data->vid->height); + } + if (r_dowarp && !warp_buffer) { + warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, + r_data->vid->height); + } + + r_funcs->begin_frame (); + if (r_dowarp) { + r_funcs->bind_framebuffer (warp_buffer); + } + if (scr_fisheye && fisheye_cube_map) { + int side = fisheye_cube_map->width; + vrect_t feye = { 0, 0, side, side }; + r_funcs->set_viewport (&feye); + r_funcs->set_fov (1, 1); //FIXME shouldn't be every frame (2d stuff) + switch (scr_fviews) { + case 6: render_side (BOX_BEHIND); + case 5: render_side (BOX_BOTTOM); + case 4: render_side (BOX_TOP); + case 3: render_side (BOX_LEFT); + case 2: render_side (BOX_RIGHT); + default:render_side (BOX_FRONT); + } + r_funcs->bind_framebuffer (0); + r_funcs->set_viewport (&r_refdef.vrect); + r_funcs->post_process (fisheye_cube_map); + } else { + r_funcs->set_viewport (&r_refdef.vrect); + render_scene (); + if (r_dowarp) { + r_funcs->bind_framebuffer (0); + r_funcs->post_process (warp_buffer); + } + } + r_funcs->set_2d (0); + //view_draw (r_data->scr_view); + r_funcs->set_2d (1); + while (*scr_funcs) { + (*scr_funcs) (); + scr_funcs++; + } + r_funcs->end_frame (); +} + void SCR_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) { @@ -229,10 +279,6 @@ SCR_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) r_time1 = Sys_DoubleTime (); } - if (scr_fisheye && !fisheye_cube_map) { - fisheye_cube_map = r_funcs->create_cube_map (r_data->vid->height); - } - refdef_t *refdef = r_data->refdef; if (Transform_Valid (camera)) { Transform_GetWorldMatrix (camera, refdef->camera); @@ -272,52 +318,12 @@ SCR_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) if (r_waterwarp) { r_dowarp = scr_scene->viewleaf->contents <= CONTENTS_WATER; } - if (r_dowarp && !warp_buffer) { - warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, - r_data->vid->height); - } R_MarkLeaves (scr_scene->viewleaf, r_node_visframes, r_leaf_visframes, r_face_visframes); } r_framecount++; R_PushDlights (vec3_origin); - - r_funcs->begin_frame (); - if (r_dowarp) { - r_funcs->bind_framebuffer (warp_buffer); - } - if (scr_fisheye && fisheye_cube_map) { - int side = fisheye_cube_map->width; - vrect_t feye = { 0, 0, side, side }; - r_funcs->set_viewport (&feye); - r_funcs->set_fov (1, 1); //FIXME shouldn't be every frame (2d stuff) - switch (scr_fviews) { - case 6: render_side (BOX_BEHIND); - case 5: render_side (BOX_BOTTOM); - case 4: render_side (BOX_TOP); - case 3: render_side (BOX_LEFT); - case 2: render_side (BOX_RIGHT); - default:render_side (BOX_FRONT); - } - r_funcs->bind_framebuffer (0); - r_funcs->set_viewport (&r_refdef.vrect); - r_funcs->post_process (fisheye_cube_map); - } else { - r_funcs->set_viewport (&r_refdef.vrect); - render_scene (); - if (r_dowarp) { - r_funcs->bind_framebuffer (0); - r_funcs->post_process (warp_buffer); - } - } - r_funcs->set_2d (0); - //view_draw (r_data->scr_view); - r_funcs->set_2d (1); - while (*scr_funcs) { - (*scr_funcs) (); - scr_funcs++; - } - r_funcs->end_frame (); + r_funcs->UpdateScreen (camera, realtime, scr_funcs); } static void diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 51229897d..4a2cb08a3 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -501,6 +501,8 @@ gl_capture_screen (capfunc_t callback, void *data) vid_render_funcs_t gl_vid_render_funcs = { .init = gl_vid_render_init, + .UpdateScreen = SCR_UpdateScreen_legacy, + .Draw_CharBuffer = gl_Draw_CharBuffer, .Draw_SetScale = gl_Draw_SetScale, .Draw_Character = gl_Draw_Character, diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 3070b963a..e299883f6 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -445,6 +445,8 @@ glsl_capture_screen (capfunc_t callback, void *data) vid_render_funcs_t glsl_vid_render_funcs = { .init = glsl_vid_render_init, + .UpdateScreen = SCR_UpdateScreen_legacy, + .Draw_CharBuffer = glsl_Draw_CharBuffer, .Draw_SetScale = glsl_Draw_SetScale, .Draw_Character = glsl_Draw_Character, diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 703eee190..5838c5c40 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -459,6 +459,8 @@ sw_capture_screen (capfunc_t callback, void *data) vid_render_funcs_t sw_vid_render_funcs = { .init = sw_vid_render_init, + .UpdateScreen = SCR_UpdateScreen_legacy, + .Draw_CharBuffer = sw_Draw_CharBuffer, .Draw_Character = Draw_Character, .Draw_String = Draw_String, diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 95403632d..f8682e165 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -774,6 +774,8 @@ vulkan_vid_render_shutdown (void) vid_render_funcs_t vulkan_vid_render_funcs = { .init = vulkan_vid_render_init, + .UpdateScreen = SCR_UpdateScreen_legacy, + .Draw_CharBuffer = vulkan_Draw_CharBuffer, .Draw_SetScale = vulkan_Draw_SetScale, .Draw_Character = vulkan_Draw_Character, From 93e5c84a20c3e658373d44693c3d8d7d8cbc9dc0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 00:11:43 +0900 Subject: [PATCH 3340/3664] [gui] Link against freetype and harfbuzz Ran into the issue while testing the screen update change ("release" build couldn't run due to broken plugins). --- libs/ui/Makemodule.am | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am index a4e677aee..b5d2188a3 100644 --- a/libs/ui/Makemodule.am +++ b/libs/ui/Makemodule.am @@ -7,12 +7,16 @@ lib_LTLIBRARIES += \ gui_deps = \ libs/ui/libQFui.la +gui_libadd = \ + $(FREETYPE_LIBS) \ + $(HARFBUZZ_LIBS) + ui_deps = \ libs/ecs/libQFecs.la \ libs/util/libQFutil.la libs_ui_libQFgui_la_LDFLAGS= $(lib_ldflags) -libs_ui_libQFgui_la_LIBADD= $(gui_deps) $(ui_deps) +libs_ui_libQFgui_la_LIBADD= $(gui_deps) $(ui_deps) $(gui_libadd) libs_ui_libQFgui_la_DEPENDENCIES= $(gui_deps) $(ui_deps) libs_ui_libQFgui_la_SOURCES= \ libs/ui/canvas.c \ From 42441e87d4b1632ca08eb5931beca52c86bb1bc6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 11:33:49 +0900 Subject: [PATCH 3341/3664] [vulkan] Create a vulkan-specific UpdateScreen The goal is to get vulkan relying on the "renderpass" abstraction, but this gets vulkan up and running again, and even fixes the rendering issues (in the end, getting canvas working wasn't required, but is still planned). --- libs/video/renderer/vid_render_vulkan.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index f8682e165..faeed851f 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -488,6 +488,20 @@ vulkan_end_frame (void) vulkan_ctx->curFrame %= vulkan_ctx->frames.size; } +static void +vulkan_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) +{ + EntQueue_Clear (r_ent_queue); + vulkan_begin_frame (); + r_funcs->set_2d (1); + while (*scr_funcs) { + (*scr_funcs) (); + scr_funcs++; + } + vulkan_render_view (); + vulkan_end_frame (); +} + static framebuffer_t * vulkan_create_cube_map (int size) { @@ -774,7 +788,7 @@ vulkan_vid_render_shutdown (void) vid_render_funcs_t vulkan_vid_render_funcs = { .init = vulkan_vid_render_init, - .UpdateScreen = SCR_UpdateScreen_legacy, + .UpdateScreen = vulkan_UpdateScreen, .Draw_CharBuffer = vulkan_Draw_CharBuffer, .Draw_SetScale = vulkan_Draw_SetScale, From 9349a739dbaa56be0a6128f8623c9a5f4e987a85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 12:39:26 +0900 Subject: [PATCH 3342/3664] [renderer] Run particle update in renderer update This has little effect on sw/gl/glsl, but makes it so the particle system isn't run on the CPU (redundantly) for vulkan. --- libs/video/renderer/r_screen.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 16e95dc72..b0b4cfcba 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -271,6 +271,8 @@ SCR_UpdateScreen_legacy (transform_t camera, double realtime, void SCR_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) { + R_RunParticles (r_data->frametime); + if (scr_skipupdate || !scr_initialized) { return; } @@ -308,7 +310,6 @@ SCR_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) SCR_CalcRefdef (); } - R_RunParticles (r_data->frametime); R_AnimateLight (); if (scr_scene && scr_scene->worldmodel) { scr_scene->viewleaf = 0; From 7785eebe4c7d6d9b3bd0c0d6744758149c36a266 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 12:58:02 +0900 Subject: [PATCH 3343/3664] [vulkan] Clean up some unnecessary interface functions Not all the empty stubs have been removed as the core model and skin code still needs to be cleaned up. --- libs/video/renderer/r_screen.c | 4 +- libs/video/renderer/vid_render_vulkan.c | 56 +------------------------ 2 files changed, 4 insertions(+), 56 deletions(-) diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index b0b4cfcba..fbdc17611 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -177,7 +177,9 @@ SCR_CalcRefdef (void) // force a background redraw r_data->scr_fullupdate = 0; - r_funcs->bind_framebuffer (0); + if (r_funcs->bind_framebuffer) { + r_funcs->bind_framebuffer (0); + } } static void diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index faeed851f..8ccea1487 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -329,21 +329,6 @@ vulkan_render_view (void) } } -static void -vulkan_draw_particles (struct psystem_s *psystem) -{ -} - -static void -vulkan_draw_transparent (void) -{ -} - -static void -vulkan_post_process (framebuffer_t *src) -{ -} - static void vulkan_set_2d (int scaled) { @@ -493,7 +478,7 @@ vulkan_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) { EntQueue_Clear (r_ent_queue); vulkan_begin_frame (); - r_funcs->set_2d (1); + vulkan_set_2d (1); while (*scr_funcs) { (*scr_funcs) (); scr_funcs++; @@ -502,33 +487,6 @@ vulkan_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) vulkan_end_frame (); } -static framebuffer_t * -vulkan_create_cube_map (int size) -{ - return 0; -} - -static framebuffer_t * -vulkan_create_frame_buffer (int width, int height) -{ - return 0; -} - -static void -vulkan_destroy_frame_buffer (framebuffer_t *framebuffer) -{ -} - -static void -vulkan_bind_framebuffer (framebuffer_t *framebuffer) -{ -} - -static void -vulkan_set_viewport (const vrect_t *view) -{ -} - static void vulkan_set_fov (float x, float y) { @@ -823,19 +781,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = { .R_LoadSkys = vulkan_R_LoadSkys, .R_NewScene = vulkan_R_NewScene, .R_LineGraph = vulkan_R_LineGraph, - .begin_frame = vulkan_begin_frame, - .render_view = vulkan_render_view, - .draw_particles = vulkan_draw_particles, - .draw_transparent = vulkan_draw_transparent, - .post_process = vulkan_post_process, - .set_2d = vulkan_set_2d, - .end_frame = vulkan_end_frame, - .create_cube_map = vulkan_create_cube_map, - .create_frame_buffer = vulkan_create_frame_buffer, - .destroy_frame_buffer = vulkan_destroy_frame_buffer, - .bind_framebuffer = vulkan_bind_framebuffer, - .set_viewport = vulkan_set_viewport, .set_fov = vulkan_set_fov, .capture_screen = vulkan_capture_screen, From e3321643290ffde9b2ba6b0267e58662d8733a4a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 17:18:51 +0900 Subject: [PATCH 3344/3664] [vulkan] Implement fitted pic rendering This makes use of slice rendering to achieve the effective scaling, but the slice data is created only when needed so pics that never use slices don't waste 16 vertices. --- libs/video/renderer/vulkan/vulkan_draw.c | 61 +++++++++++++++++------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index d9b58b24c..9990dce4c 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -82,6 +82,7 @@ static QFV_Subpass subpass_map[] = { typedef struct pic_data_s { uint32_t vert_index; + uint32_t slice_index; uint32_t descid; subpic_t *subpic; } picdata_t; @@ -189,7 +190,6 @@ typedef struct drawctx_s { qpic_t *conchars; qpic_t *conback; qpic_t *white_pic; - int white_pic_ind; qpic_t *backtile_pic; // use two separate cmem blocks for pics and strings (cachepic names) // to ensure the names are never in the same cacheline as a pic since the @@ -245,7 +245,7 @@ get_dyn_descriptor (descpool_t *pool, qpic_t *pic, VkBufferView buffer_view, } } if (pool->in_use >= MAX_DESCIPTORS) { - Sys_Error ("get_dyn_descriptor: out of dynamic desciptors"); + Sys_Error ("get_dyn_descriptor: out of dynamic descriptors"); } int descid = pool->in_use++; pool->users[descid] = id; @@ -472,8 +472,8 @@ create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic, { __auto_type pd = (picdata_t *) pic->data; - int x = rect[0] + pd->subpic->rect->x; - int y = rect[1] + pd->subpic->rect->y; + int x = rect[0]; + int y = rect[1]; int w = rect[2]; int h = rect[3]; int l = border[0]; @@ -481,6 +481,14 @@ create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic, int r = w - border[2]; int b = h - border[3]; + float sx = 1.0 / pic->width; + float sy = 1.0 / pic->height; + if (pd->subpic) { + x += pd->subpic->rect->x; + y += pd->subpic->rect->y; + sx = sy = pd->subpic->size; + } + vec4f_t p[16] = { { 0, 0, 0, 0 }, { 0, t, 0, t }, { l, 0, l, 0 }, { l, t, l, t }, { r, 0, r, 0 }, { r, t, r, t }, { w, 0, w, 0 }, { w, t, w, t }, @@ -488,8 +496,7 @@ create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic, { r, b, r, b }, { r, h, r, h }, { w, b, w, b }, { w, h, w, h }, }; - float s = pd->subpic->size; - vec4f_t size = { 1, 1, s, s }; + vec4f_t size = { 1, 1, sx, sy }; qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); quadvert_t *verts = QFV_PacketExtend (packet, BYTES_PER_SLICE); for (int i = 0; i < VERTS_PER_SLICE; i++) { @@ -506,6 +513,15 @@ create_slice (vec4i_t rect, vec4i_t border, qpic_t *pic, return ind; } +static uint32_t +make_static_slice (vec4i_t rect, vec4i_t border, qpic_t *pic, vulkan_ctx_t *ctx) +{ + drawctx_t *dctx = ctx->draw_context; + VkBuffer buffer = dctx->svertex_objects[0].buffer.buffer; + + return create_slice (rect, border, pic, &dctx->svertex_index, buffer, ctx); +} + static uint32_t create_quad (int x, int y, int w, int h, qpic_t *pic, uint32_t *vertex_index, VkBuffer buffer, vulkan_ctx_t *ctx) @@ -540,7 +556,7 @@ create_quad (int x, int y, int w, int h, qpic_t *pic, uint32_t *vertex_index, return ind; } -static int +static uint32_t make_static_quad (int w, int h, qpic_t *pic, vulkan_ctx_t *ctx) { drawctx_t *dctx = ctx->draw_context; @@ -573,6 +589,7 @@ pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) __auto_type pd = (picdata_t *) pic->data; pd->subpic = QFV_ScrapSubpic (dctx->scrap, w, h); pd->vert_index = make_static_quad (w, h, pic, ctx); + pd->slice_index = ~0; pd->descid = CORE_DESC; picdata = QFV_SubpicBatch (pd->subpic, dctx->stage); @@ -718,6 +735,7 @@ load_lmp (const char *path, vulkan_ctx_t *ctx) __auto_type pd = (picdata_t *) pic->data; pd->subpic = 0; pd->vert_index = make_static_quad (p->width, p->height, pic, ctx); + pd->slice_index = ~0; pd->descid = fontid; free (p); @@ -831,13 +849,12 @@ load_white_pic (vulkan_ctx_t *ctx) { drawctx_t *dctx = ctx->draw_context; byte white_block = 0xfe; - VkBuffer buffer = dctx->svertex_objects[0].buffer.buffer; dctx->white_pic = pic_data ("white", 1, 1, &white_block, ctx); - dctx->white_pic_ind = create_slice ((vec4i_t) {0, 0, 1, 1}, - (vec4i_t) {0, 0, 0, 0}, - dctx->white_pic, - &dctx->svertex_index, buffer, ctx); + __auto_type pd = (picdata_t *) dctx->white_pic->data; + pd->slice_index = make_static_slice ((vec4i_t) {0, 0, 1, 1}, + (vec4i_t) {0, 0, 0, 0}, + dctx->white_pic, ctx); } void @@ -1231,9 +1248,20 @@ Vulkan_Draw_Pic (int x, int y, qpic_t *pic, vulkan_ctx_t *ctx) } void -Vulkan_Draw_FitPic (int x, int y, int widht, int height, qpic_t *pic, +Vulkan_Draw_FitPic (int x, int y, int width, int height, qpic_t *pic, vulkan_ctx_t *ctx) { + drawctx_t *dctx = ctx->draw_context; + drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; + __auto_type pd = (picdata_t *) pic->data; + if (pd->slice_index == ~0u) { + vec4i_t rect = (vec4i_t) {0, 0, pic->width, pic->height}; + vec4i_t border = (vec4i_t) {0, 0, 0, 0}; + pd->slice_index = make_static_slice (rect, border, pic, ctx); + } + static byte color[4] = { 255, 255, 255, 255}; + draw_slice (x, y, width - pic->width, height - pic->height, + pd->descid, pd->slice_index, color, frame); } void @@ -1329,8 +1357,8 @@ Vulkan_Draw_Fill (int x, int y, int w, int h, int c, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; byte color[4] = {VectorExpand (vid.palette + c * 3), 255 }; - draw_slice (x, y, w - 1, h - 1, - CORE_DESC, dctx->white_pic_ind, color, frame); + __auto_type pd = (picdata_t *) dctx->white_pic->data; + draw_slice (x, y, w - 1, h - 1, pd->descid, pd->slice_index, color, frame); } void @@ -1377,8 +1405,9 @@ draw_blendscreen (const byte *color, vulkan_ctx_t *ctx) drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; float s = 1.0 / ctx->twod_scale; + __auto_type pd = (picdata_t *) dctx->white_pic->data; draw_slice (0, 0, vid.width * s - 1, vid.height * s - 1, - CORE_DESC, dctx->white_pic_ind, color, frame); + pd->descid, pd->slice_index, color, frame); } void From 91adb6ad6c233b46f0baef31baa6447c0650a8c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 17:35:30 +0900 Subject: [PATCH 3345/3664] [console] Go back to using Draw_ConsoleBackground Using Draw_FitPic was for testing. --- libs/console/client.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/console/client.c b/libs/console/client.c index 23371e14a..756cb936c 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -678,9 +678,7 @@ draw_console (view_t view) alpha = 255 * con_alpha * len.y / y; alpha = min (alpha, 255); } - //r_funcs->Draw_ConsoleBackground (con_data.lines, alpha); - qpic_t *pic = r_funcs->Draw_CachePic ("gfx/conback.lmp", false); - r_funcs->Draw_FitPic (0, con_data.lines - len.y, len.x, len.y, pic); + r_funcs->Draw_ConsoleBackground (con_data.lines, alpha); } update_notify (); From b91a76cbcc8ac11711f4abe352cdcab7aca6fbea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 17:56:37 +0900 Subject: [PATCH 3346/3664] [vulkan] Get Draw_TextBox working again This needed either more font ids to be supported, or small lump pics (up to 32 x 32) to be loaded into the atlas. I went with both. The menus don't use Draw_TextBox, but quakeworld's netgraph does. --- libs/video/renderer/vulkan/vulkan_draw.c | 37 ++++++++++-------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 9990dce4c..df49c59c8 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -644,6 +644,12 @@ load_lmp (const char *path, vulkan_ctx_t *ctx) return 0; } + if (p->width < 32 && p->height < 32) { + qpic_t *pic = pic_data (path, p->width, p->height, p->data, ctx); + free (p); + return pic; + } + qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; drawctx_t *dctx = ctx->draw_context; @@ -751,7 +757,7 @@ Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) if ((cpic = Hash_Find (dctx->pic_cache, path))) { return cpic->pic; } - qpic_t *pic = load_lmp (path, ctx);; + qpic_t *pic = load_lmp (path, ctx); cpic = new_cachepic (dctx, path, pic); Hash_Add (dctx->pic_cache, cpic); return pic; @@ -874,7 +880,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) dctx->frames.grow = 0; DARRAY_INIT (&dctx->fonts, 16); DARRAY_RESIZE (&dctx->fonts, 16); - dctx->fonts.grow = 0; dctx->fonts.size = 0; dctx->pic_memsuper = new_memsuper (); @@ -1174,18 +1179,16 @@ void Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, vulkan_ctx_t *ctx) { -#if 0 drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - quat_t color = {1, 1, 1, 1}; + byte color[4] = {255, 255, 255, 255}; qpic_t *p; int cx, cy, n; #define draw(px, py, pp) \ do { \ - subpic_t *subpic = *(subpic_t **) (pp)->data; \ - draw_pic (px, py, pp->width, pp->height, subpic, \ - 0, 0, pp->width, pp->height, color, &frame->quad_verts); \ + __auto_type pd = (picdata_t *) pp->data; \ + draw_quad (px, py, pd->descid, pd->vert_index, color, frame); \ } while (0) color[3] = alpha; @@ -1233,7 +1236,6 @@ Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, p = Vulkan_Draw_CachePic ("gfx/box_br.lmp", true, ctx); draw (cx, cy + 8, p); #undef draw -#endif } void @@ -1293,23 +1295,14 @@ Vulkan_Draw_SubPic (int x, int y, qpic_t *pic, void Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) { -#if 0 - drawctx_t *dctx = ctx->draw_context; - drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - - float a = bound (0, alpha, 255) / 255.0; + //FIXME fitpic with color + //float a = bound (0, alpha, 255) / 255.0; // use pre-multiplied alpha - quat_t color = { a, a, a, a}; + //quat_t color = { a, a, a, a}; qpic_t *cpic; cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx); - int s = ctx->twod_scale; - float frac = (vid.height - s * lines) / (float) vid.height; - int ofs = frac * cpic->height; - subpic_t *subpic = *(subpic_t **) cpic->data; - draw_pic (0, 0, vid.width / s, lines, subpic, - 0, ofs, cpic->width, cpic->height - ofs, color, - &frame->quad_verts); -#endif + float s = 1.0 / ctx->twod_scale; + Vulkan_Draw_FitPic (0, -lines, vid.width * s, vid.height * s, cpic, ctx); } void From cdc5f8a91292ad2cbbc3cb2549ff01d725a88bb2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 21:28:49 +0900 Subject: [PATCH 3347/3664] [vulkan] Get line rendering working again Rather important for debugging 2d stuff (draw's lines are 2d-only). Other than translucent console, this gets the vulkan draw api back to full operation. --- libs/video/renderer/vulkan/pl_quake_def.plist | 15 ++--- libs/video/renderer/vulkan/shader/line.vert | 3 +- libs/video/renderer/vulkan/vulkan_draw.c | 60 ++++++++++--------- 3 files changed, 36 insertions(+), 42 deletions(-) diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index a8f580f71..ea93a4a6e 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -566,10 +566,6 @@ topology = line_list; primitiveRestartEnable = false; }; - twod = { - topology = triangle_strip; - primitiveRestartEnable = true; - }; sprite = { topology = triangle_strip; primitiveRestartEnable = true; @@ -666,14 +662,13 @@ { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 48; }, ); }; - twod = { + lines = { bindings = ( - { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 0; stride = "2 * 4 + 4"; inputRate = vertex; }, ); attributes = ( { location = 0; binding = 0; format = r32g32_sfloat; offset = 0; }, - { location = 1; binding = 0; format = r32g32_sfloat; offset = 8; }, - { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 8; }, ); }; }; @@ -1135,8 +1130,6 @@ inputAssembly = $properties.inputAssembly.sprite; layout = sprite_layout; }; - twod = { - }; slice = { @inherit = $properties.pipelines.trans_base; renderPass = output; @@ -1166,7 +1159,7 @@ { stage = vertex; name = main; module = $builtin/line.vert; }, { stage = fragment; name = main; module = $builtin/line.frag; }, ); - vertexInput = $properties.vertexInput.twod; + vertexInput = $properties.vertexInput.lines; rasterization = $properties.rasterization.counter_cw_cull_back; depthStencil = $properties.depthStencil.disable; colorBlend = { diff --git a/libs/video/renderer/vulkan/shader/line.vert b/libs/video/renderer/vulkan/shader/line.vert index 25bf0b50c..3552215f7 100644 --- a/libs/video/renderer/vulkan/shader/line.vert +++ b/libs/video/renderer/vulkan/shader/line.vert @@ -5,8 +5,7 @@ layout (set = 0, binding = 0) uniform #include "matrices.h" ; layout (location = 0) in vec2 vertex; -layout (location = 1) in vec2 uv; -layout (location = 2) in vec4 vcolor; +layout (location = 1) in vec4 vcolor; layout (location = 0) out vec4 color; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index df49c59c8..1aa5b6e85 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -97,7 +97,6 @@ typedef struct descbatchset_s typedef struct { float xy[2]; - float st[2]; byte color[4]; } linevert_t; @@ -113,11 +112,11 @@ typedef struct { float uv[2]; } quadvert_t; -typedef struct vertqueue_s { +typedef struct linequeue_s { linevert_t *verts; int count; int size; -} vertqueue_t; +} linequeue_t; typedef struct quadqueue_s { quadinst_t *quads; @@ -146,16 +145,18 @@ typedef struct descpool_s { typedef struct drawframe_s { size_t instance_offset; + size_t dvert_offset; size_t line_offset; VkBuffer instance_buffer; VkBuffer dvert_buffer; + VkBuffer line_buffer; VkBufferView dvert_view; uint32_t dvertex_index; uint32_t dvertex_max; descbatchset_t quad_batch; quadqueue_t quad_insts; - vertqueue_t line_verts; + linequeue_t line_verts; qfv_cmdbufferset_t cmdSet; descpool_t dyn_descs; } drawframe_t; @@ -202,6 +203,7 @@ typedef struct drawctx_s { qfv_resobj_t *svertex_objects; qfv_resobj_t *instance_objects; qfv_resobj_t *dvertex_objects; + qfv_resobj_t *lvertex_objects; uint32_t svertex_index; uint32_t svertex_max; VkPipeline quad_pipeline; @@ -229,8 +231,6 @@ typedef struct drawctx_s { #define VERTS_PER_LINE (2) #define BYTES_PER_LINE (VERTS_PER_LINE * sizeof (linevert_t)) -#define DVERTS_PER_FRAME (LINES_OFFSET + MAX_LINES*VERTS_PER_LINE) - static int get_dyn_descriptor (descpool_t *pool, qpic_t *pic, VkBufferView buffer_view, vulkan_ctx_t *ctx) @@ -302,12 +302,15 @@ create_buffers (vulkan_ctx_t *ctx) + 2 * sizeof (qfv_resobj_t) // frames dynamic vertex buffers and views + (frames) * 2 * sizeof (qfv_resobj_t) + // frames line vertex buffers + + (frames) * sizeof (qfv_resobj_t) // frames instance buffers + (frames) * sizeof (qfv_resobj_t)); dctx->index_object = (qfv_resobj_t *) &dctx->draw_resource[2]; dctx->svertex_objects = &dctx->index_object[1]; dctx->dvertex_objects = &dctx->svertex_objects[2]; - dctx->instance_objects = &dctx->dvertex_objects[2 * frames]; + dctx->lvertex_objects = &dctx->dvertex_objects[2 * frames]; + dctx->instance_objects = &dctx->lvertex_objects[frames]; dctx->svertex_index = 0; dctx->svertex_max = MAX_QUADS * VERTS_PER_QUAD; @@ -323,7 +326,7 @@ create_buffers (vulkan_ctx_t *ctx) .name = "draw", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - .num_objects = (2 * frames) + (frames), + .num_objects = (2 * frames) + (frames) + (frames), .objects = dctx->dvertex_objects, }; @@ -377,6 +380,15 @@ create_buffers (vulkan_ctx_t *ctx) .size = dctx->dvertex_objects[i * 2 + 0].buffer.size, }, }; + dctx->lvertex_objects[i] = (qfv_resobj_t) { + .name = "line", + .type = qfv_res_buffer, + .buffer = { + .size = MAX_LINES * BYTES_PER_LINE, + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + }, + }; dctx->instance_objects[i] = (qfv_resobj_t) { .name = "inst", .type = qfv_res_buffer, @@ -400,7 +412,8 @@ create_buffers (vulkan_ctx_t *ctx) frame->instance_offset = dctx->instance_objects[f].buffer.offset; frame->dvert_buffer = dctx->dvertex_objects[f * 2 + 0].buffer.buffer; frame->dvert_view = dctx->dvertex_objects[f * 2 + 1].buffer_view.view; - frame->line_offset = dctx->dvertex_objects[f * 2].buffer.offset; + frame->line_buffer = dctx->lvertex_objects[f].buffer.buffer; + frame->line_offset = dctx->lvertex_objects[f].buffer.offset; frame->dvertex_index = 0; frame->dvertex_max = MAX_QUADS * VERTS_PER_QUAD; @@ -411,7 +424,7 @@ create_buffers (vulkan_ctx_t *ctx) .size = MAX_INSTANCES, }; - frame->line_verts = (vertqueue_t) { + frame->line_verts = (linequeue_t) { .verts = (linevert_t *) ((byte *)data + frame->line_offset), .size = MAX_INSTANCES, }; @@ -1359,32 +1372,19 @@ Vulkan_Draw_Line (int x0, int y0, int x1, int y1, int c, vulkan_ctx_t *ctx) { drawctx_t *dctx = ctx->draw_context; drawframe_t *frame = &dctx->frames.a[ctx->curFrame]; - vertqueue_t *queue = &frame->line_verts; + linequeue_t *queue = &frame->line_verts; if (queue->count >= queue->size) { return; } - __auto_type pd = (picdata_t *) dctx->white_pic->data; - int srcx = pd->subpic->rect->x; - int srcy = pd->subpic->rect->y; - int srcw = pd->subpic->rect->width; - int srch = pd->subpic->rect->height; - float size = pd->subpic->size; - float sl = (srcx + 0.03125) * size; - float sr = (srcx + srcw - 0.03125) * size; - float st = (srcy + 0.03125) * size; - float sb = (srcy + srch - 0.03125) * size; - linevert_t *verts = queue->verts + queue->count * VERTS_PER_LINE; verts[0] = (linevert_t) { .xy = { x0, y0 }, - .st = {sl, st}, .color = { VectorExpand (vid.palette + c * 3), 255 }, }; verts[1] = (linevert_t) { .xy = { x1, y1 }, - .st = {sr, sb}, .color = { VectorExpand (vid.palette + c * 3), 255 }, }; @@ -1497,7 +1497,7 @@ draw_quads (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) } DARRAY_RESIZE (&dframe->quad_batch, 0); } -#if 0 + static void draw_lines (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) { @@ -1519,7 +1519,7 @@ draw_lines (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE, 1, 0, 0); } -#endif + void Vulkan_FlushText (qfv_renderframe_t *rFrame) { @@ -1543,9 +1543,12 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, memory, dframe->instance_offset, a(dframe->quad_insts.count * BYTES_PER_QUAD) }, + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + memory, dframe->dvert_offset, + a(dframe->dvertex_index * sizeof (quadvert_t)) }, { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, memory, dframe->line_offset, - a(dframe->line_verts.count * VERTS_PER_LINE * sizeof (linevert_t)) }, + a(dframe->line_verts.count * BYTES_PER_LINE) }, }; #undef a dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); @@ -1560,13 +1563,12 @@ Vulkan_FlushText (qfv_renderframe_t *rFrame) dframe->cmdSet.a[QFV_draw2d]); draw_quads (rFrame, dframe->cmdSet.a[QFV_draw2d]); } -#if 0 if (dframe->line_verts.count) { bind_pipeline (rFrame, dctx->line_pipeline, dframe->cmdSet.a[QFV_draw2d]); draw_lines (rFrame, dframe->cmdSet.a[QFV_draw2d]); } -#endif + draw_end_subpass (dframe->cmdSet.a[QFV_draw2d], ctx); dframe->quad_insts.count = 0; From d7b1fceb12f93e3f96c99b18f76b47d7cdf97629 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 21:36:03 +0900 Subject: [PATCH 3348/3664] [vulkan] Remove a dead FIXME The flashing pink around the Q menu cursor was caused by vulkan command buffer writes and draw queue population being out of phase, which was fixed by the recent screen update changes (specifically, 42441e87d4b1632ca08eb5931beca52c86bb1bc6). --- libs/video/renderer/vulkan/vulkan_draw.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 1aa5b6e85..6316f349b 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -617,11 +617,6 @@ pic_data (const char *name, int w, int h, const byte *data, vulkan_ctx_t *ctx) *picdata++ = *col++ & alpha; *picdata++ = alpha; } - //FIXME live updates of the scrap aren't - //syncronized properly for some reason and result in stale texels being - //rendered (flashing pink around the Q menu cursor the first time it's - //displayed). I suspect simple barriers aren't enough and more - //sophisticated syncronization (events? semaphores?) is needed. return pic; } From ae0b781818b1d1fef3c1344d2a9543bcf3fb9295 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 19 Jan 2023 23:05:06 +0900 Subject: [PATCH 3349/3664] [vulkan] Implement water warp The separated output pass made the implementation very easy, as did having most of the parts already in place. --- include/QF/Vulkan/qf_output.h | 6 ++++-- libs/video/renderer/vulkan/vulkan_output.c | 25 ++++++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index 94b969d42..48fde9f66 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -45,8 +45,10 @@ typedef struct outputframeset_s typedef struct outputctx_s { outputframeset_t frames; - VkPipeline pipeline; - VkPipelineLayout layout; + VkPipeline output; + VkPipeline waterwarp; + VkPipelineLayout output_layout; + VkPipelineLayout warp_layout; VkSampler sampler; VkImageView input; } outputctx_t; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index c08aaad42..9403e8343 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -55,6 +55,8 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/swapchain.h" +#include "r_local.h" +#include "r_internal.h" #include "vid_vulkan.h" #include "vkparse.h"//FIXME @@ -163,8 +165,9 @@ process_input (qfv_renderframe_t *rFrame) QFV_duCmdBeginLabel (device, cmd, "output:output"); - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - octx->pipeline); + __auto_type pipeline = r_dowarp ? octx->waterwarp : octx->output; + __auto_type layout = r_dowarp ? octx->warp_layout : octx->output_layout; + dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); @@ -173,7 +176,14 @@ process_input (qfv_renderframe_t *rFrame) oframe->set, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - octx->layout, 0, 2, set, 0, 0); + layout, 0, 2, set, 0, 0); + if (r_dowarp) { + float time = vr_data.realtime; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &time }, + }; + QFV_PushConstants (device, cmd, layout, 1, push_constants); + } dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); @@ -233,8 +243,10 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) __auto_type pld = ctx->script_context->pipelineDef;//FIXME ctx->script_context->pipelineDef = Vulkan_GetConfig (ctx, "qf_output"); - octx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "output"); - octx->layout = Vulkan_CreatePipelineLayout (ctx, "output_layout"); + octx->output = Vulkan_CreateGraphicsPipeline (ctx, "output"); + octx->waterwarp = Vulkan_CreateGraphicsPipeline (ctx, "waterwarp"); + octx->output_layout = Vulkan_CreatePipelineLayout (ctx, "output_layout"); + octx->warp_layout = Vulkan_CreatePipelineLayout (ctx, "waterwarp_layout"); octx->sampler = Vulkan_CreateSampler (ctx, "linear"); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); @@ -271,7 +283,8 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; outputctx_t *octx = ctx->output_context; - dfunc->vkDestroyPipeline (device->dev, octx->pipeline, 0); + dfunc->vkDestroyPipeline (device->dev, octx->output, 0); + dfunc->vkDestroyPipeline (device->dev, octx->waterwarp, 0); free (octx->frames.a); free (octx); } From 06fdef52e8db7f0ce30613fe33a53380c72e2b2c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Jan 2023 12:59:45 +0900 Subject: [PATCH 3350/3664] Clean up some unneeded console.h includes --- libs/video/targets/vid.c | 1 - libs/video/targets/vid_x11.c | 1 - libs/video/targets/vid_x11_sw.c | 1 - nq/source/world.c | 1 - qw/source/pmovetst.c | 1 - qw/source/world.c | 1 - 6 files changed, 6 deletions(-) diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 77cc55f30..b413f224f 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -36,7 +36,6 @@ #endif #include -#include "QF/console.h" #include "QF/cvar.h" #include "QF/mathlib.h" #include "QF/qargs.h" diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 566953940..324340270 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -54,7 +54,6 @@ #endif #include "QF/cmd.h" -#include "QF/console.h" #include "QF/cvar.h" #include "QF/qendian.h" #include "QF/screen.h" diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 3d5ef4526..6d35fb443 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -55,7 +55,6 @@ #include #include -#include "QF/console.h" #include "QF/cvar.h" #include "QF/qargs.h" #include "QF/sys.h" diff --git a/nq/source/world.c b/nq/source/world.c index 13e6df8d0..6c76e7962 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -38,7 +38,6 @@ #include #include "QF/clip_hull.h" -#include "QF/console.h" #include "QF/crc.h" #include "QF/sys.h" diff --git a/qw/source/pmovetst.c b/qw/source/pmovetst.c index b1f5fb84e..f545f7904 100644 --- a/qw/source/pmovetst.c +++ b/qw/source/pmovetst.c @@ -35,7 +35,6 @@ # include #endif -#include "QF/console.h" #include "QF/model.h" #include "QF/qtypes.h" #include "QF/sys.h" diff --git a/qw/source/world.c b/qw/source/world.c index f6e0fbd8b..1c7494ca0 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -38,7 +38,6 @@ #include #include "QF/clip_hull.h" -#include "QF/console.h" #include "QF/crc.h" #include "QF/sys.h" From 68c7003991f4e5ef3875e1e3da27890f0e9e5b7a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Jan 2023 13:27:17 +0900 Subject: [PATCH 3351/3664] [console] Separate loading and initialization This will make it easy for client code to set up data needed by the console before the console initializes. It already separates console cvar setup and initialization, which has generally been a good thing. --- hw/source/master.c | 3 ++- include/QF/console.h | 3 ++- libs/console/client.c | 22 +++++++++++++--------- libs/console/console.c | 13 ++++++++++--- libs/console/server.c | 14 ++++++++++---- nq/source/cl_main.c | 3 ++- nq/source/host.c | 3 ++- qtv/source/qtv.c | 3 ++- qw/source/cl_main.c | 3 ++- qw/source/sv_main.c | 3 ++- ruamoko/qwaq/builtins/graphics.c | 3 ++- 11 files changed, 49 insertions(+), 24 deletions(-) diff --git a/hw/source/master.c b/hw/source/master.c index f05a34d69..15f5bdc10 100644 --- a/hw/source/master.c +++ b/hw/source/master.c @@ -545,9 +545,10 @@ main (int argc, const char **argv) Cvar_Register (&sv_console_plugin_cvar, 0, 0); PI_RegisterPlugins (server_plugin_list); - Con_Init (sv_console_plugin); + Con_Load (sv_console_plugin); if (con_module) con_module->data->console->cbuf = mst_cbuf; + Con_Init (); con_list_print = Sys_Printf; SV_InitNet (); diff --git a/include/QF/console.h b/include/QF/console.h index 734d2bda1..0a0274664 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -90,7 +90,8 @@ void Con_BufferAddText (con_buffer_t *buf, const char *text); void Con_ClearBuffer (con_buffer_t *buffer); // init/shutdown functions -void Con_Init (const char *plugin_name); +void Con_Load (const char *plugin_name); +void Con_Init (void); void Con_ExecLine (const char *line); void Con_ProcessInput (void); diff --git a/libs/console/client.c b/libs/console/client.c index 756cb936c..99d7f9550 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -1014,6 +1014,17 @@ Condump_f (void) Qclose (file); } +static void +C_InitCvars (void) +{ + Cvar_Register (&con_notifytime_cvar, 0, 0); + Cvar_Register (&con_scale_cvar, con_scale_f, 0); + Cvar_Register (&con_alpha_cvar, 0, 0); + Cvar_Register (&con_size_cvar, 0, 0); + Cvar_Register (&con_speed_cvar, 0, 0); + Cvar_Register (&cl_conmode_cvar, 0, 0); +} + static void C_Init (void) { @@ -1032,14 +1043,6 @@ C_Init (void) Menu_Init (); - Cvar_Register (&con_notifytime_cvar, 0, 0); - - Cvar_Register (&con_scale_cvar, con_scale_f, 0); - Cvar_Register (&con_alpha_cvar, 0, 0); - Cvar_Register (&con_size_cvar, 0, 0); - Cvar_Register (&con_speed_cvar, 0, 0); - Cvar_Register (&cl_conmode_cvar, 0, 0); - con_debuglog = COM_CheckParm ("-condebug"); // The console will get resized, so assume initial size is 320x200 @@ -1185,11 +1188,12 @@ C_shutdown (void) } static general_funcs_t plugin_info_general_funcs = { - .init = C_Init, + .init = C_InitCvars, .shutdown = C_shutdown, }; static console_funcs_t plugin_info_console_funcs = { + .init = C_Init, .print = C_Print, .draw_console = C_DrawConsole, .new_map = C_NewMap, diff --git a/libs/console/console.c b/libs/console/console.c index fbf535253..43964db03 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -108,16 +108,23 @@ Con_shutdown (void *data) } VISIBLE void -Con_Init (const char *plugin_name) +Con_Load (const char *plugin_name) { Sys_RegisterShutdown (Con_shutdown, 0); con_module = PI_LoadPlugin ("console", plugin_name); + if (!con_module) { + setvbuf (stdout, 0, _IOLBF, BUFSIZ); + } +} + +VISIBLE void +Con_Init (void) +{ if (con_module) { __auto_type funcs = con_module->functions->console; + funcs->init (); saved_sys_printf = Sys_SetStdPrintf (funcs->print); - } else { - setvbuf (stdout, 0, _IOLBF, BUFSIZ); } Cvar_Register (&con_interpreter_cvar, Con_Interp_f, 0); } diff --git a/libs/console/server.c b/libs/console/server.c index 5595e40da..fc7e90d12 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -776,9 +776,16 @@ sv_exec_line_chat (void *data, const char *line) } static void -C_Init (void) +C_InitCvars (void) { Cvar_Register (&sv_use_curses_cvar, 0, 0); + Cvar_Register (&sv_logfile_cvar, sv_logfile_f, 0); + Cvar_Register (&sv_conmode_cvar, 0, 0); +} + +static void +C_Init (void) +{ #ifdef HAVE_NCURSES use_curses = sv_use_curses; if (use_curses) { @@ -786,8 +793,6 @@ C_Init (void) } else #endif setvbuf (stdout, 0, _IOLBF, BUFSIZ); - Cvar_Register (&sv_logfile_cvar, sv_logfile_f, 0); - Cvar_Register (&sv_conmode_cvar, 0, 0); } static void @@ -863,12 +868,13 @@ C_NewMap (void) } static general_funcs_t plugin_info_general_funcs = { - .init = C_Init, + .init = C_InitCvars, .shutdown = C_shutdown, }; static general_data_t plugin_info_general_data; static console_funcs_t plugin_info_console_funcs = { + .init = C_Init, .print = C_Print, .process_input = C_ProcessInput, .draw_console = C_DrawConsole, diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index 954da6962..fd8237a85 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -708,8 +708,9 @@ CL_Init (cbuf_t *cbuf) S_Init (&cl.viewentity, &host_frametime); PI_RegisterPlugins (client_plugin_list); - Con_Init ("client"); + Con_Load ("client"); CL_Init_Screen (); + Con_Init (); CDAudio_Init (); diff --git a/nq/source/host.c b/nq/source/host.c index a3fde4e6b..e6db77457 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -926,7 +926,8 @@ Host_Init (void) if (isDedicated) { PI_RegisterPlugins (server_plugin_list); - Con_Init ("server"); + Con_Load ("server"); + Con_Init (); } Host_InitVCR (&host_parms); diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 6c95554a9..220d17c91 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -297,9 +297,10 @@ qtv_init (void) Cvar_Register (&qtv_console_plugin_cvar, 0, 0); PI_RegisterPlugins (server_plugin_list); - Con_Init (qtv_console_plugin); + Con_Load (qtv_console_plugin); if (con_module) con_module->data->console->cbuf = qtv_cbuf; + Con_Init (); Sys_SetStdPrintf (qtv_print); qtv_sbar_init (); diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 490e33f41..6746301f0 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1461,7 +1461,7 @@ CL_Init (void) r_data->lightstyle = cl.lightstyle; PI_RegisterPlugins (client_plugin_list); - Con_Init ("client"); + Con_Load ("client"); CL_Init_Screen (); if (con_module) { con_module->data->console->dl_name = cls.downloadname; @@ -1473,6 +1473,7 @@ CL_Init (void) Cbuf_DeleteStack (con_module->data->console->cbuf); con_module->data->console->cbuf = cl_cbuf; } + Con_Init (); CL_NetGraph_Init (); S_Init (&cl.viewentity, &host_frametime); diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 511001ba7..8740de584 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -2691,9 +2691,10 @@ SV_Init (void) Cvar_Register (&sv_console_plugin_cvar, 0, 0); PI_RegisterPlugins (server_plugin_list); - Con_Init (sv_console_plugin); + Con_Load (sv_console_plugin); if (con_module) con_module->data->console->cbuf = sv_cbuf; + Con_Init (); con_list_print = Sys_Printf; Sys_SetStdPrintf (SV_Print); Sys_SetErrPrintf (SV_Error); diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 96fad8138..1a4da10be 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -354,7 +354,7 @@ BI_Graphics_Init (progs_t *pr) event_handler_id = IE_Add_Handler (event_handler, pr); IE_Set_Focus (event_handler_id); - Con_Init ("client"); + Con_Load ("client"); if (con_module) { con_module->data->console->realtime = &con_realtime; con_module->data->console->frametime = &con_frametime; @@ -363,6 +363,7 @@ BI_Graphics_Init (progs_t *pr) //con_module->data->console->screen_view = r_data->scr_view; } //Key_SetKeyDest (key_game); + Con_Init (); S_Init (0, &con_frametime); //CDAudio_Init (); From 873d4007666be4ae7c8631d041450c9257cafd83 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Jan 2023 15:53:51 +0900 Subject: [PATCH 3352/3664] [scene] Remove scene_resources_t struct It was made unnecessary by the ECS changes. --- include/Makemodule.am | 1 - include/QF/scene/scene.h | 3 --- include/scn_internal.h | 7 ------- libs/scene/camera.c | 2 -- libs/scene/entity.c | 2 -- libs/scene/scene.c | 6 ------ libs/scene/transform.c | 2 -- 7 files changed, 23 deletions(-) delete mode 100644 include/scn_internal.h diff --git a/include/Makemodule.am b/include/Makemodule.am index dab0b609d..30d6f71e9 100644 --- a/include/Makemodule.am +++ b/include/Makemodule.am @@ -71,7 +71,6 @@ EXTRA_DIST += \ include/regex.h \ include/rua_internal.h \ include/skin_stencil.h \ - include/scn_internal.h \ include/snd_internal.h \ include/sv_console.h \ include/varrays.h \ diff --git a/include/QF/scene/scene.h b/include/QF/scene/scene.h index dd96576fc..3a1d281e0 100644 --- a/include/QF/scene/scene.h +++ b/include/QF/scene/scene.h @@ -62,9 +62,6 @@ enum scene_components { typedef struct scene_s { struct ecs_registry_s *reg; - struct scene_resources_s *const resources; - struct hierarchy_s *hierarchies; - struct model_s *worldmodel; int num_models; struct model_s **models; diff --git a/include/scn_internal.h b/include/scn_internal.h deleted file mode 100644 index 906bef517..000000000 --- a/include/scn_internal.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __scn_internal_h -#define __scn_internal_h - -typedef struct scene_resources_s { -} scene_resources_t; - -#endif//__scn_internal_h diff --git a/libs/scene/camera.c b/libs/scene/camera.c index 327bea646..3739305da 100644 --- a/libs/scene/camera.c +++ b/libs/scene/camera.c @@ -35,8 +35,6 @@ #include "QF/scene/scene.h" #include "QF/scene/transform.h" -#include "scn_internal.h" - void Camera_GetViewMatrix (const camera_t *camera, mat4f_t view) { diff --git a/libs/scene/entity.c b/libs/scene/entity.c index 92e5099d7..8d88ea8c1 100644 --- a/libs/scene/entity.c +++ b/libs/scene/entity.c @@ -35,8 +35,6 @@ #include "QF/scene/entity.h" #include "QF/scene/scene.h" -#include "scn_internal.h" - entqueue_t * EntQueue_New (int num_queues) { diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 82e87bb96..6704e7e48 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -43,8 +43,6 @@ #include "QF/scene/scene.h" #include "QF/scene/transform.h" -#include "scn_internal.h" - static void create_active (void *_active) { @@ -215,9 +213,6 @@ Scene_NewScene (void) ECS_RegisterComponents (scene->reg, scene_components, scene_comp_count); ECS_CreateComponentPools (scene->reg); - scene_resources_t *res = calloc (1, sizeof (scene_resources_t)); - *(scene_resources_t **)&scene->resources = res; - scene->worldmodel = &empty_world; return scene; @@ -228,7 +223,6 @@ Scene_DeleteScene (scene_t *scene) { ECS_DelRegistry (scene->reg); - free (scene->resources); free (scene); } diff --git a/libs/scene/transform.c b/libs/scene/transform.c index 31ea16137..c9b532fab 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -40,8 +40,6 @@ #include "QF/scene/scene.h" #include "QF/scene/transform.h" -#include "scn_internal.h" - static void transform_mat4f_identity (void *_mat) { From 32cead5f880e8b52e837bb4dc5ec6432dd58cb68 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 20 Jan 2023 15:57:29 +0900 Subject: [PATCH 3353/3664] [ui] Add a function to create a new canvas entity The entity has only a canvas component and (root) view component attached. The plan is to use it for screen-space canvases. --- include/QF/ui/canvas.h | 22 ++++++++++++++++++++++ libs/ui/canvas.c | 9 +++++++++ 2 files changed, 31 insertions(+) diff --git a/include/QF/ui/canvas.h b/include/QF/ui/canvas.h index 2c832120f..168b31308 100644 --- a/include/QF/ui/canvas.h +++ b/include/QF/ui/canvas.h @@ -32,6 +32,7 @@ #define __QF_scene_canvas_h #include "QF/ecs.h" +#include "QF/ui/view.h" enum { canvas_update, @@ -77,10 +78,31 @@ typedef struct canvas_subpic_s { uint32_t w, h; } canvas_subpic_t; +#define CANVASINLINE GNU89INLINE inline + void Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent); +uint32_t Canvas_New (canvas_system_t canvas_sys); void Canvas_Draw (canvas_system_t canvas_sys); void Canvas_SortComponentPool (canvas_system_t canvas_sys, uint32_t ent, uint32_t component); +CANVASINLINE view_t Canvas_GetRootView (canvas_system_t canvas_sys, + uint32_t ent); +#undef CANVASINLINE +#ifndef IMPLEMENT_CANVAS_Funcs +#define CANVASINLINE GNU89INLINE inline +#else +#define CANVASINLINE VISIBLE +#endif + +CANVASINLINE +view_t +Canvas_GetRootView (canvas_system_t canvas_sys, uint32_t ent) +{ + ecs_system_t viewsys = { canvas_sys.reg, canvas_sys.view_base }; + return View_FromEntity (viewsys, ent); +} + +#undef CANVASINLINE #endif//__QF_scene_canvas_h diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index c4506fc00..866311567 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -31,6 +31,7 @@ # include "config.h" #endif +#define IMPLEMENT_CANVAS_Funcs #include "QF/ui/canvas.h" #include "QF/ui/text.h" #include "QF/ui/view.h" @@ -374,6 +375,14 @@ Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent) nullview); } +uint32_t +Canvas_New (canvas_system_t canvas_sys) +{ + uint32_t ent = ECS_NewEntity (canvas_sys.reg); + Canvas_AddToEntity (canvas_sys, ent); + return ent; +} + static int canvas_href_cmp (const void *_a, const void *_b, void *arg) { From 1c368724e82698d54da1eafac76eeaba3e879bb5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Jan 2023 02:30:26 +0900 Subject: [PATCH 3354/3664] [gib] Fix an struct forward declaration --- include/QF/gib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/gib.h b/include/QF/gib.h index 2631bea41..ef1515388 100644 --- a/include/QF/gib.h +++ b/include/QF/gib.h @@ -196,7 +196,7 @@ void GIB_Event_Callback (gib_event_t *event, unsigned int argc, ...); // Interpreter interface (for creating GIB cbufs) -cbuf_interpreter_t *GIB_Interpreter (void) __attribute__((const)); +struct cbuf_interpreter_s *GIB_Interpreter (void) __attribute__((const)); // Thread interface From 4949f52b58499dc82cf37291949b3af8be32a3c0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Jan 2023 02:57:05 +0900 Subject: [PATCH 3355/3664] [console] Move gib hud control into hud I don't know why it was ever in console. --- libs/client/hud.c | 15 +++++++++++++++ libs/console/client.c | 17 ----------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/libs/client/hud.c b/libs/client/hud.c index 580ffe45a..e1775ac6f 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -32,6 +32,7 @@ #include #include "QF/cvar.h" +#include "QF/gib.h" #include "QF/screen.h" #include "QF/render.h" #include "QF/plugin/vid_render.h" @@ -259,6 +260,17 @@ hud_scoreboard_gravity_f (void *data, const cvar_t *cvar) View_SetGravity (hud_overlay_view, hud_scoreboard_gravity); } } +static void +C_GIB_HUD_Enable_f (void) +{ + //hud_canvas_view->visible = 1; +} + +static void +C_GIB_HUD_Disable_f (void) +{ + //hud_canvas_view->visible = 0; +} void HUD_Init (void) @@ -274,6 +286,9 @@ HUD_Init (void) passage_components, passage_comp_count); ECS_CreateComponentPools (hud_system.reg); + // register GIB builtins + GIB_Builtin_Add ("HUD::enable", C_GIB_HUD_Enable_f); + GIB_Builtin_Add ("HUD::disable", C_GIB_HUD_Disable_f); } void diff --git a/libs/console/client.c b/libs/console/client.c index 99d7f9550..b2e39ee51 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -46,7 +46,6 @@ #include "QF/console.h" #include "QF/cvar.h" #include "QF/dstring.h" -#include "QF/gib.h" #include "QF/keys.h" #include "QF/qargs.h" #include "QF/quakefs.h" @@ -803,18 +802,6 @@ C_NewMap (void) dstring_copystr (old_gamedir, qfs_gamedir->gamedir); } -static void -C_GIB_HUD_Enable_f (void) -{ - //hud_view->visible = 1; -} - -static void -C_GIB_HUD_Disable_f (void) -{ - //hud_view->visible = 0; -} - static void exec_line (inputline_t *il) { @@ -1174,10 +1161,6 @@ C_Init (void) Cmd_AddCommand ("condump", Condump_f, "dump the console text to a " "file"); - // register GIB builtins - GIB_Builtin_Add ("HUD::enable", C_GIB_HUD_Enable_f); - GIB_Builtin_Add ("HUD::disable", C_GIB_HUD_Disable_f); - con_initialized = true; } From 93844428341c65b051d53b89135b6505e5cc8513 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Jan 2023 03:14:27 +0900 Subject: [PATCH 3356/3664] [ecs] Remove a debug print --- libs/ecs/entity.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index 1f7892c37..d34a21a03 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -65,7 +65,6 @@ Ent_AddComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) if (rind && c->rangeid) { uint32_t rangeid = c->rangeid (registry, ent, comp); uint32_t rangeind = subpool->sorted[Ent_Index (rangeid)]; - printf ("ent:%d rangeid:%d rangeind:%d\n", ent, rangeid, rangeind); while (rind-- > rangeind) { if (subpool->ranges[rind] == ind) { subpool->ranges[rind]++; From f0fab885d4a9d2bb72a327ca62ad6bf4b8ad97c8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Jan 2023 03:26:02 +0900 Subject: [PATCH 3357/3664] [ui] Get canvas into a usable state Canvas_SortComponentPool now takes the raw canvas component id as it is specialized to the canvas subpools. Canvas_SetLen resizes the root view and then updates the hierarchy for every canvas in the system. Canvas_InitSys sets up the component system with the systems it needs (canvas, view, text). This is required to ensure view_href is just past the canvas components as it is needed for retrieving the actual canvas component (and thus sub-pool range ids) from arbitrary views in the canvas. Entities are fetched with the correct offset from the pool entities. --- include/QF/ui/canvas.h | 4 +- libs/ui/canvas.c | 84 +++++++++++++++++++++++++++++++++--------- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/include/QF/ui/canvas.h b/include/QF/ui/canvas.h index 168b31308..a08c33605 100644 --- a/include/QF/ui/canvas.h +++ b/include/QF/ui/canvas.h @@ -62,8 +62,8 @@ extern const struct component_s canvas_components[canvas_comp_count]; typedef struct canvas_system_s { ecs_registry_t *reg; uint32_t base; - uint32_t text_base; uint32_t view_base; + uint32_t text_base; } canvas_system_t; struct view_s; @@ -80,11 +80,13 @@ typedef struct canvas_subpic_s { #define CANVASINLINE GNU89INLINE inline +void Canvas_InitSys (canvas_system_t *canvas_sys, ecs_registry_t *reg); void Canvas_AddToEntity (canvas_system_t canvas_sys, uint32_t ent); uint32_t Canvas_New (canvas_system_t canvas_sys); void Canvas_Draw (canvas_system_t canvas_sys); void Canvas_SortComponentPool (canvas_system_t canvas_sys, uint32_t ent, uint32_t component); +void Canvas_SetLen (canvas_system_t canvas_sys, view_pos_t len); CANVASINLINE view_t Canvas_GetRootView (canvas_system_t canvas_sys, uint32_t ent); diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index 866311567..86bf20d57 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -38,13 +38,24 @@ #include "QF/plugin/vid_render.h" +static uint32_t +_canvas_rangeid (ecs_registry_t *reg, uint32_t ent, uint32_t comp, uint32_t c) +{ + comp += canvas_canvas - c; + // view components come immediately after canvas components + uint32_t vcomp = view_href + comp + canvas_comp_count - canvas_canvas; + hierref_t *href = Ent_GetComponent (ent, vcomp, reg); + // the root entity of the hierarchy has the canvas component + uint32_t cent = href->hierarchy->ent[0]; + canvas_t *canvas = Ent_GetComponent (cent, comp, reg); + return canvas->range[c]; +} + #define canvas_rangeid(c) \ static uint32_t \ canvas_##c##_rangeid (ecs_registry_t *reg, uint32_t ent, uint32_t comp) \ { \ - comp += canvas_canvas - canvas_##c; \ - canvas_t *canvas = Ent_GetComponent (ent, comp, reg); \ - return canvas->range[canvas_##c]; \ + return _canvas_rangeid (reg, ent, comp, canvas_##c); \ } canvas_rangeid(update) canvas_rangeid(updateonce) @@ -134,7 +145,7 @@ draw_update (canvas_system_t *canvas_sys, ecs_pool_t *pool, ecs_range_t range) { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; __auto_type func = (canvas_update_f *) pool->data + range.start; while (count-- > 0) { (*func++) (View_FromEntity (viewsys, *ent++)); @@ -146,7 +157,6 @@ draw_updateonce (canvas_system_t *canvas_sys, ecs_pool_t *pool, ecs_range_t range) { draw_update (canvas_sys, pool, range); - pool->count = 0;//XXX FIXME hmm, what to do with ranges } static void @@ -155,7 +165,7 @@ draw_tile_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); if (View_GetVisible (view)) { @@ -172,7 +182,7 @@ draw_pic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; __auto_type pic = (qpic_t **) pool->data + range.start; while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); @@ -190,7 +200,7 @@ draw_fitpic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; __auto_type pic = (qpic_t **) pool->data + range.start; while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); @@ -209,7 +219,7 @@ draw_subpic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; __auto_type subpic = (canvas_subpic_t *) pool->data + range.start; while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); @@ -228,7 +238,7 @@ draw_cachepic_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; __auto_type name = (const char **) pool->data + range.start; while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); @@ -247,7 +257,7 @@ draw_fill_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; __auto_type fill = (byte *) pool->data + range.start; while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); @@ -266,7 +276,7 @@ draw_charbuff_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; __auto_type charbuff = (draw_charbuffer_t **) pool->data + range.start; while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); @@ -284,7 +294,7 @@ draw_func_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; __auto_type func = (canvas_func_f *) pool->data + range.start; while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); @@ -303,13 +313,13 @@ draw_outline_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, { ecs_system_t viewsys = { canvas_sys->reg, canvas_sys->view_base }; uint32_t count = range.end - range.start; - uint32_t *ent = pool->dense; + uint32_t *ent = pool->dense + range.start; __auto_type col = (byte *) pool->data + range.start; __auto_type line = r_funcs->Draw_Line; while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); byte c = *col++; - if (View_GetVisible (view)) { + if (1 || View_GetVisible (view)) { view_pos_t p = View_GetAbs (view); view_pos_t l = View_GetLen (view); view_pos_t q = { p.x + l.x - 1, p.y + l.y - 1 }; @@ -358,6 +368,27 @@ Canvas_Draw (canvas_system_t canvas_sys) } } } + { + ecs_pool_t *pool = &canvas_sys.reg->comp_pools[canvas_updateonce]; + ecs_subpool_t *subpool = &canvas_sys.reg->subpools[canvas_updateonce]; + pool->count = 0; + uint32_t rcount = subpool->num_ranges - subpool->available; + memset (subpool->ranges, 0, rcount * sizeof (*subpool->ranges)); + } +} + +void +Canvas_InitSys (canvas_system_t *canvas_sys, ecs_registry_t *reg) +{ + *canvas_sys = (canvas_system_t) { + .reg = reg, + .base = ECS_RegisterComponents (reg, canvas_components, + canvas_comp_count), + .view_base = ECS_RegisterComponents (reg, view_components, + view_comp_count), + .text_base = ECS_RegisterComponents (reg, text_components, + text_comp_count), + }; } void @@ -406,8 +437,25 @@ Canvas_SortComponentPool (canvas_system_t canvas_sys, uint32_t ent, { canvas_t *canvas = Ent_GetComponent (ent, canvas_sys.base + canvas_canvas, canvas_sys.reg); - uint32_t rid = canvas->range[component - canvas_sys.base]; - ecs_range_t range = ECS_GetSubpoolRange (canvas_sys.reg, component, rid); - ECS_SortComponentPoolRange (canvas_sys.reg, component, range, + uint32_t rid = canvas->range[component]; + uint32_t c = component + canvas_sys.base; + ecs_range_t range = ECS_GetSubpoolRange (canvas_sys.reg, c, rid); + ECS_SortComponentPoolRange (canvas_sys.reg, c, range, canvas_href_cmp, &canvas_sys); } + +void +Canvas_SetLen (canvas_system_t canvas_sys, view_pos_t len) +{ + uint32_t comp = canvas_sys.base + canvas_canvas; + ecs_pool_t *canvas_pool = &canvas_sys.reg->comp_pools[comp]; + uint32_t count = canvas_pool->count; + uint32_t *entities = canvas_pool->dense; + + while (count-- > 0) { + uint32_t ent = *entities++; + view_t view = Canvas_GetRootView (canvas_sys, ent); + View_SetLen (view, len.x, len.y); + View_UpdateHierarchy (view); + } +} From 3c8f02c655336137afce450d1305422bc2818bf2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Jan 2023 03:34:33 +0900 Subject: [PATCH 3358/3664] [client] Switch to using canvases for screen and hud Canvases provide layered rendering as for each canvas all components are rendered in turn. --- include/client/hud.h | 42 +----- include/client/screen.h | 1 + libs/client/Makemodule.am | 5 +- libs/client/cl_screen.c | 92 +++++------ libs/client/hud.c | 310 ++++++-------------------------------- libs/client/sbar.c | 287 ++++++++++++++++++----------------- qw/source/cl_ngraph.c | 10 +- 7 files changed, 252 insertions(+), 495 deletions(-) diff --git a/include/client/hud.h b/include/client/hud.h index c3b7c7388..fdb8e8862 100644 --- a/include/client/hud.h +++ b/include/client/hud.h @@ -30,34 +30,9 @@ struct view_s; -enum { - hud_update, - hud_updateonce, - hud_tile, - hud_pic, - hud_subpic, - hud_cachepic, - hud_fill, - hud_charbuff, - hud_func, - hud_outline, - - hud_comp_count -}; - -typedef void (*hud_update_f) (struct view_s); -typedef void (*hud_func_f) (struct view_pos_s, struct view_pos_s); - -typedef struct hud_subpic_s { - struct qpic_s *pic; - uint32_t x, y; - uint32_t w, h; -} hud_subpic_t; - -extern struct ecs_system_s hud_system; -extern struct ecs_system_s hud_viewsys; extern struct ecs_system_s hud_psgsys; +extern uint32_t hud_canvas; extern int hud_sb_lines; extern int hud_sbar; @@ -67,18 +42,15 @@ extern int hud_pl; extern int hud_ping; extern int hud_time; -extern struct view_s hud_view; +//root view of the hud canvas +extern struct view_s hud_canvas_view; -extern struct view_s hud_overlay_view; -extern struct view_s hud_stuff_view; -extern struct view_s hud_time_view; -extern struct view_s hud_fps_view; -extern struct view_s hud_ping_view; -extern struct view_s hud_pl_view; +struct ecs_registry_s; +struct canvas_system_s; -void HUD_Init (void); +void HUD_Init (struct ecs_registry_s *reg); void HUD_Init_Cvars (void); +void HUD_CreateCanvas (struct canvas_system_s canvas_sys); void HUD_Calc_sb_lines (int view_size); -void HUD_Draw_Views (void); #endif//__client_hud_h diff --git a/include/client/screen.h b/include/client/screen.h index 3d02363a5..1695834cb 100644 --- a/include/client/screen.h +++ b/include/client/screen.h @@ -2,6 +2,7 @@ #define __client_screen_h extern struct view_s cl_screen_view; +extern struct canvas_system_s cl_canvas_sys; struct viewstate_s; void CL_Init_Screen (void); diff --git a/libs/client/Makemodule.am b/libs/client/Makemodule.am index c017cefd9..5b33a1c20 100644 --- a/libs/client/Makemodule.am +++ b/libs/client/Makemodule.am @@ -1,7 +1,10 @@ noinst_LTLIBRARIES += libs/client/libQFclient.la libs_client_libQFclient_la_LDFLAGS= @STATIC@ -libs_client_libQFclient_la_LIBADD= libs/gamecode/libQFgamecode.la libs/util/libQFutil.la +libs_client_libQFclient_la_LIBADD= \ + libs/ui/libQFgui.la \ + libs/gamecode/libQFgamecode.la \ + libs/util/libQFutil.la libs_client_libQFclient_la_SOURCES= \ libs/client/cl_chase.c \ libs/client/cl_effects.c \ diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index 8705735c5..adb48f2f8 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -49,7 +49,7 @@ #include "QF/scene/scene.h" #include "QF/scene/transform.h" -#include "QF/ui/view.h" +#include "QF/ui/canvas.h" #include "r_local.h" //FIXME for r_cache_thrash @@ -90,6 +90,7 @@ static cvar_t scr_showturtle_cvar = { }; view_t cl_screen_view; +uint32_t cl_canvas; static view_t net_view; static view_t timegraph_view; static view_t zgraph_view; @@ -100,6 +101,8 @@ static view_t pause_view; static viewstate_t *_vs;//FIXME ick +canvas_system_t cl_canvas_sys; + static void SCR_CShift (void) { @@ -139,31 +142,21 @@ scr_draw_views (void) // FIXME cvar callbacks View_SetVisible (timegraph_view, r_timegraph); View_SetVisible (zgraph_view, r_zgraph); + + if (!_vs->intermission) { + r_funcs->Draw_Crosshair ();//FIXME canvas_func + } + Canvas_Draw (cl_canvas_sys); + SCR_CShift ();//FIXME canvas_func + Sbar_DrawCenterPrint ();//FIXME canvas_func + Con_DrawConsole ();//FIXME canvas_func } -static SCR_Func scr_funcs_normal[] = { - 0, //Draw_Crosshair, - HUD_Draw_Views, - SCR_CShift, - Sbar_DrawCenterPrint, +static SCR_Func scr_funcs[] = { scr_draw_views, - Con_DrawConsole, 0 }; -static SCR_Func scr_funcs_intermission[] = { - HUD_Draw_Views, - Sbar_DrawCenterPrint, - scr_draw_views, - Con_DrawConsole, - 0 -}; - -static SCR_Func *scr_funcs[] = { - scr_funcs_normal, - scr_funcs_intermission, -}; - static int cl_scale; static int cl_xlen; static int cl_ylen; @@ -174,8 +167,9 @@ cl_set_size (void) int xlen = cl_xlen / cl_scale; int ylen = cl_ylen / cl_scale; printf ("cl_set_size: %d %d %d\n", cl_scale, xlen, ylen); - View_SetLen (cl_screen_view, xlen, ylen); - View_UpdateHierarchy (cl_screen_view); + //View_SetLen (cl_screen_view, xlen, ylen); + //View_UpdateHierarchy (cl_screen_view); + Canvas_SetLen (cl_canvas_sys, (view_pos_t) { xlen, ylen }); } static void @@ -198,31 +192,43 @@ CL_Init_Screen (void) { qpic_t *pic; - HUD_Init (); + __auto_type reg = ECS_NewRegistry (); + Canvas_InitSys (&cl_canvas_sys, reg); + HUD_Init (reg); + ECS_CreateComponentPools (reg); + cl_xlen = viddef.width; cl_ylen = viddef.height; - cl_screen_view = View_New (hud_viewsys, nullview); + ecs_system_t vsys = { + .reg = reg, + .base = cl_canvas_sys.view_base, + }; + + HUD_CreateCanvas (cl_canvas_sys); + + cl_canvas = Canvas_New (cl_canvas_sys); + cl_screen_view = Canvas_GetRootView (cl_canvas_sys, cl_canvas); View_SetPos (cl_screen_view, 0, 0); - View_SetLen (cl_screen_view, viddef.width, viddef.height); + View_SetLen (cl_screen_view, cl_xlen, cl_ylen); View_SetGravity (cl_screen_view, grav_northwest); View_SetVisible (cl_screen_view, 1); pic = r_funcs->Draw_PicFromWad ("ram"); - ram_view = View_New (hud_viewsys, cl_screen_view); + ram_view = View_New (vsys, cl_screen_view); View_SetPos (ram_view, 32, 0); View_SetLen (ram_view, pic->width, pic->height); View_SetGravity (ram_view, grav_northwest); - Ent_SetComponent (ram_view.id, hud_pic, ram_view.reg, &pic); + Ent_SetComponent (ram_view.id, canvas_pic, ram_view.reg, &pic); View_SetVisible (ram_view, 0); pic = r_funcs->Draw_PicFromWad ("turtle"); - turtle_view = View_New (hud_viewsys, cl_screen_view); + turtle_view = View_New (vsys, cl_screen_view); View_SetPos (turtle_view, 32, 0); View_SetLen (turtle_view, pic->width, pic->height); View_SetGravity (turtle_view, grav_northwest); - Ent_SetComponent (turtle_view.id, hud_pic, turtle_view.reg, &pic); + Ent_SetComponent (turtle_view.id, canvas_pic, turtle_view.reg, &pic); View_SetVisible (turtle_view, 0); Cvar_Register (&scr_showpause_cvar, 0, 0); @@ -230,45 +236,46 @@ CL_Init_Screen (void) Cvar_Register (&scr_showturtle_cvar, 0, 0); pic = r_funcs->Draw_PicFromWad ("net"); - net_view = View_New (hud_viewsys, cl_screen_view); + net_view = View_New (vsys, cl_screen_view); View_SetPos (net_view, 64, 0); View_SetLen (net_view, pic->width, pic->height); View_SetGravity (net_view, grav_northwest); - Ent_SetComponent (net_view.id, hud_pic, net_view.reg, &pic); + Ent_SetComponent (net_view.id, canvas_pic, net_view.reg, &pic); View_SetVisible (net_view, 0); - timegraph_view = View_New (hud_viewsys, cl_screen_view); + timegraph_view = View_New (vsys, cl_screen_view); View_SetPos (timegraph_view, 0, 0); View_SetLen (timegraph_view, r_data->vid->width, 100); View_SetGravity (timegraph_view, grav_southwest); void *rtg = R_TimeGraph; - Ent_SetComponent (timegraph_view.id, hud_func, timegraph_view.reg, &rtg); + Ent_SetComponent (timegraph_view.id, canvas_func, timegraph_view.reg, &rtg); View_SetVisible (timegraph_view, r_timegraph); - zgraph_view = View_New (hud_viewsys, cl_screen_view); + zgraph_view = View_New (vsys, cl_screen_view); View_SetPos (zgraph_view, 0, 0); View_SetLen (zgraph_view, r_data->vid->width, 100); View_SetGravity (zgraph_view, grav_southwest); void *rzg = R_ZGraph; - Ent_SetComponent (zgraph_view.id, hud_func, zgraph_view.reg, &rzg); + Ent_SetComponent (zgraph_view.id, canvas_func, zgraph_view.reg, &rzg); View_SetVisible (zgraph_view, r_zgraph); const char *name = "gfx/loading.lmp"; pic = r_funcs->Draw_CachePic (name, 1); - loading_view = View_New (hud_viewsys, cl_screen_view); + loading_view = View_New (vsys, cl_screen_view); View_SetPos (loading_view, 0, -24); View_SetLen (loading_view, pic->width, pic->height); View_SetGravity (loading_view, grav_center); - Ent_SetComponent (loading_view.id, hud_cachepic, loading_view.reg, &name); + Ent_SetComponent (loading_view.id, canvas_cachepic, + loading_view.reg, &name); View_SetVisible (loading_view, 0); name = "gfx/pause.lmp"; pic = r_funcs->Draw_CachePic (name, 1); - pause_view = View_New (hud_viewsys, cl_screen_view); + pause_view = View_New (vsys, cl_screen_view); View_SetPos (pause_view, 0, -24); View_SetLen (pause_view, pic->width, pic->height); View_SetGravity (pause_view, grav_center); - Ent_SetComponent (pause_view.id, hud_cachepic, pause_view.reg, &name); + Ent_SetComponent (pause_view.id, canvas_cachepic, pause_view.reg, &name); View_SetVisible (pause_view, 0); cvar_t *con_scale = Cvar_FindVar ("con_scale"); @@ -280,12 +287,8 @@ CL_Init_Screen (void) void CL_UpdateScreen (viewstate_t *vs) { - unsigned index = !!vs->intermission; _vs = vs; - if (index >= sizeof (scr_funcs) / sizeof (scr_funcs[0])) - index = 0; - //FIXME not every time if (vs->active) { if (vs->watervis) @@ -293,9 +296,8 @@ CL_UpdateScreen (viewstate_t *vs) else r_data->min_wateralpha = 1.0; } - scr_funcs_normal[0] = r_funcs->Draw_Crosshair; V_PrepBlend (vs); V_RenderView (vs); - SCR_UpdateScreen (vs->camera_transform, vs->time, scr_funcs[index]); + SCR_UpdateScreen (vs->camera_transform, vs->time, scr_funcs); } diff --git a/libs/client/hud.c b/libs/client/hud.c index e1775ac6f..f9abd4f1d 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -36,59 +36,17 @@ #include "QF/screen.h" #include "QF/render.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/canvas.h" #include "QF/ui/passage.h" #include "QF/ui/view.h" #include "compat.h" #include "client/hud.h" +#include "client/screen.h" -static const component_t hud_components[hud_comp_count] = { - [hud_update] = { - .size = sizeof (hud_update_f), - .name = "update", - }, - [hud_updateonce] = { - .size = sizeof (hud_update_f), - .name = "updateonce", - }, - [hud_tile] = { - .size = sizeof (byte), - .name = "tile", - }, - [hud_pic] = { - .size = sizeof (qpic_t *), - .name = "pic", - }, - [hud_subpic] = { - .size = sizeof (hud_subpic_t), - .name = "subpic", - }, - [hud_cachepic] = { - .size = sizeof (const char *), - .name = "cachepic", - }, - [hud_fill] = { - .size = sizeof (byte), - .name = "fill", - }, - [hud_charbuff] = { - .size = sizeof (draw_charbuffer_t *), - .name = "charbuffer", - }, - [hud_func] = { - .size = sizeof (hud_func_f), - .name = "func", - }, - [hud_outline] = { - .size = sizeof (byte), - .name = "outline", - }, -}; - -ecs_system_t hud_system; -ecs_system_t hud_viewsys; ecs_system_t hud_psgsys; +uint32_t hud_canvas; int hud_sb_lines; int hud_sbar; @@ -100,7 +58,8 @@ static cvar_t hud_sbar_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &hud_sbar }, }; -grav_t hud_scoreboard_gravity; +grav_t hud_scoreboard_gravity = grav_center; +#if 0 static cvar_t hud_scoreboard_gravity_cvar = { .name = "hud_scoreboard_gravity", .description = @@ -110,6 +69,7 @@ static cvar_t hud_scoreboard_gravity_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &grav_t_type, .value = &hud_scoreboard_gravity }, }; +#endif int hud_swap; static cvar_t hud_swap_cvar = { .name = "hud_swap", @@ -165,34 +125,22 @@ static cvar_t hud_debug_cvar = { .value = { .type = &cexpr_int, .value = &hud_debug }, }; -view_t sbar_view; -view_t sbar_inventory_view; -view_t sbar_frags_view; - -view_t hud_view; - -view_t hud_overlay_view; -view_t hud_stuff_view; -view_t hud_time_view; -view_t hud_fps_view; -view_t hud_ping_view; -view_t hud_pl_view; +view_t hud_canvas_view; static void -hud_add_outlines (view_t view) +hud_add_outlines (view_t view, byte color) { - byte color = 0x6f; - Ent_SetComponent (view.id, hud_outline, view.reg, &color); + Ent_SetComponent (view.id, canvas_outline, view.reg, &color); uint32_t count = View_ChildCount (view); for (uint32_t i = 0; i < count; i++) { - hud_add_outlines (View_GetChild (view, i)); + hud_add_outlines (View_GetChild (view, i), color); } } static void hud_remove_outlines (view_t view) { - Ent_RemoveComponent (view.id, hud_outline, view.reg); + Ent_RemoveComponent (view.id, canvas_outline, view.reg); uint32_t count = View_ChildCount (view); for (uint32_t i = 0; i < count; i++) { hud_remove_outlines (View_GetChild (view, i)); @@ -202,15 +150,15 @@ hud_remove_outlines (view_t view) static void hud_debug_f (void *data, const cvar_t *cvar) { - if (!View_Valid (hud_view)) { + if (!View_Valid (hud_canvas_view)) { return; } if (hud_debug) { - hud_add_outlines (hud_view); - hud_add_outlines (hud_overlay_view); + hud_add_outlines (cl_screen_view, 0xfb); + hud_add_outlines (hud_canvas_view, 0x6f); } else { - hud_remove_outlines (hud_view); - hud_remove_outlines (hud_overlay_view); + hud_remove_outlines (hud_canvas_view); + hud_remove_outlines (cl_screen_view); } } @@ -222,10 +170,9 @@ hud_sbar_f (void *data, const cvar_t *cvar) #if 0//XXX if (hud_sbar) { view_remove (hud_main_view, hud_main_view->children[0]); - view_insert (hud_main_view, sbar_view, 0); } else { view_remove (hud_main_view, hud_main_view->children[0]); - view_insert (hud_main_view, hud_view, 0); + view_insert (hud_main_view, hud_canvas_view, 0); } #endif } @@ -252,7 +199,7 @@ hud_swap_f (void *data, const cvar_t *cvar) view_move (hud_stuff_view, hud_stuff_view->xpos, hud_stuff_view->ypos); #endif } - +#if 0 static void hud_scoreboard_gravity_f (void *data, const cvar_t *cvar) { @@ -260,6 +207,7 @@ hud_scoreboard_gravity_f (void *data, const cvar_t *cvar) View_SetGravity (hud_overlay_view, hud_scoreboard_gravity); } } +#endif static void C_GIB_HUD_Enable_f (void) { @@ -273,19 +221,14 @@ C_GIB_HUD_Disable_f (void) } void -HUD_Init (void) +HUD_Init (ecs_registry_t *reg) { - hud_system.reg = ECS_NewRegistry (); - hud_viewsys.reg = hud_system.reg; - hud_psgsys.reg = hud_system.reg; - hud_system.base = ECS_RegisterComponents (hud_system.reg, hud_components, - hud_comp_count); - hud_viewsys.base = ECS_RegisterComponents (hud_system.reg, view_components, - view_comp_count); - hud_psgsys.base = ECS_RegisterComponents (hud_system.reg, - passage_components, - passage_comp_count); - ECS_CreateComponentPools (hud_system.reg); + hud_psgsys = (ecs_system_t) { + .reg = reg, + .base = ECS_RegisterComponents (reg, passage_components, + passage_comp_count), + }; + // register GIB builtins GIB_Builtin_Add ("HUD::enable", C_GIB_HUD_Enable_f); GIB_Builtin_Add ("HUD::disable", C_GIB_HUD_Disable_f); @@ -303,7 +246,20 @@ HUD_Init_Cvars (void) Cvar_Register (&hud_sbar_cvar, hud_sbar_f, 0); Cvar_Register (&hud_swap_cvar, hud_swap_f, 0); +#if 0 Cvar_Register (&hud_scoreboard_gravity_cvar, hud_scoreboard_gravity_f, 0); +#endif +} + +void +HUD_CreateCanvas (canvas_system_t canvas_sys) +{ + hud_canvas = Canvas_New (canvas_sys); + hud_canvas_view = Canvas_GetRootView (canvas_sys, hud_canvas); + View_SetPos (hud_canvas_view, 0, 0); + View_SetLen (hud_canvas_view, viddef.width, viddef.height); + View_SetGravity (hud_canvas_view, grav_northwest); + View_SetVisible (hud_canvas_view, 1); } void @@ -317,203 +273,21 @@ HUD_Calc_sb_lines (int view_size) stuff_y = 0; } else if (view_size >= 110) { hud_sb_lines = 24; - sbar_inventory_view->visible = 0; hud_inventory_view->visible = 0; hud_armament_view->visible = 0; stuff_y = 32; } else { hud_sb_lines = 48; - sbar_inventory_view->visible = 1; hud_inventory_view->visible = 1; hud_armament_view->visible = 1; stuff_y = 48; } if (hud_sb_lines) { - sbar_view->visible = 1; - hud_view->visible = 1; - view_resize (sbar_view, sbar_view->xlen, hud_sb_lines); - view_resize (hud_view, hud_view->xlen, hud_sb_lines); + hud_canvas_view->visible = 1; + view_resize (hud_canvas_view, hud_canvas_view->xlen, hud_sb_lines); } else { - sbar_view->visible = 0; - hud_view->visible = 0; + hud_canvas_view->visible = 0; } view_move (hud_stuff_view, hud_stuff_view->xpos, stuff_y); #endif } - -static void -draw_update (ecs_pool_t *pool) -{ - uint32_t count = pool->count; - uint32_t *ent = pool->dense; - hud_update_f *func = pool->data; - while (count-- > 0) { - (*func++) (View_FromEntity (hud_viewsys, *ent++)); - } -} - -static void -draw_updateonce (ecs_pool_t *pool) -{ - draw_update (pool); - pool->count = 0; -} - -static void -draw_tile_views (ecs_pool_t *pool) -{ - uint32_t count = pool->count; - uint32_t *ent = pool->dense; - while (count-- > 0) { - view_t view = View_FromEntity (hud_viewsys, *ent++); - if (View_GetVisible (view)) { - view_pos_t pos = View_GetAbs (view); - view_pos_t len = View_GetLen (view); - r_funcs->Draw_TileClear (pos.x, pos.y, len.x, len.y); - } - } -} - -static void -draw_pic_views (ecs_pool_t *pool) -{ - uint32_t count = pool->count; - uint32_t *ent = pool->dense; - qpic_t **pic = pool->data; - while (count-- > 0) { - view_t view = View_FromEntity (hud_viewsys, *ent++); - if (View_GetVisible (view)) { - view_pos_t pos = View_GetAbs (view); - r_funcs->Draw_Pic (pos.x, pos.y, *pic); - } - pic++; - } -} - -static void -draw_subpic_views (ecs_pool_t *pool) -{ - uint32_t count = pool->count; - uint32_t *ent = pool->dense; - hud_subpic_t *subpic = pool->data; - while (count-- > 0) { - view_t view = View_FromEntity (hud_viewsys, *ent++); - if (View_GetVisible (view)) { - view_pos_t pos = View_GetAbs (view); - r_funcs->Draw_SubPic (pos.x, pos.y, subpic->pic, - subpic->x, subpic->y, subpic->w, subpic->h); - } - subpic++; - } -} - -static void -draw_cachepic_views (ecs_pool_t *pool) -{ - uint32_t count = pool->count; - uint32_t *ent = pool->dense; - const char **name = pool->data; - while (count-- > 0) { - view_t view = View_FromEntity (hud_viewsys, *ent++); - if (View_GetVisible (view)) { - view_pos_t pos = View_GetAbs (view); - qpic_t *pic = r_funcs->Draw_CachePic (*name, 1); - r_funcs->Draw_Pic (pos.x, pos.y, pic); - } - name++; - } -} - -static void -draw_fill_views (ecs_pool_t *pool) -{ - uint32_t count = pool->count; - uint32_t *ent = pool->dense; - byte *fill = pool->data; - while (count-- > 0) { - view_t view = View_FromEntity (hud_viewsys, *ent++); - if (View_GetVisible (view)) { - view_pos_t pos = View_GetAbs (view); - view_pos_t len = View_GetLen (view); - r_funcs->Draw_Fill (pos.x, pos.y, len.x, len.y, *fill); - } - fill++; - } -} - -static void -draw_charbuff_views (ecs_pool_t *pool) -{ - uint32_t count = pool->count; - uint32_t *ent = pool->dense; - draw_charbuffer_t **charbuff = pool->data; - while (count-- > 0) { - view_t view = View_FromEntity (hud_viewsys, *ent++); - if (View_GetVisible (view)) { - view_pos_t pos = View_GetAbs (view); - r_funcs->Draw_CharBuffer (pos.x, pos.y, *charbuff); - } - charbuff++; - } -} - -static void -draw_func_views (ecs_pool_t *pool) -{ - uint32_t count = pool->count; - uint32_t *ent = pool->dense; - hud_func_f *func = pool->data; - while (count-- > 0) { - view_t view = View_FromEntity (hud_viewsys, *ent++); - if (View_GetVisible (view)) { - view_pos_t pos = View_GetAbs (view); - view_pos_t len = View_GetLen (view); - (*func) (pos, len); - } - func++; - } -} - -static void -draw_outline_views (ecs_pool_t *pool) -{ - uint32_t count = pool->count; - uint32_t *ent = pool->dense; - byte *col = pool->data; - __auto_type line = r_funcs->Draw_Line; - while (count-- > 0) { - view_t view = View_FromEntity (hud_viewsys, *ent++); - byte c = *col++; - if (View_GetVisible (view)) { - view_pos_t p = View_GetAbs (view); - view_pos_t l = View_GetLen (view); - view_pos_t q = { p.x + l.x - 1, p.y + l.y - 1 }; - line (p.x, p.y, q.x, p.y, c); - line (p.x, q.y, q.x, q.y, c); - line (p.x, p.y, p.x, q.y, c); - line (q.x, p.y, q.x, q.y, c); - } - } -} - -void -HUD_Draw_Views (void) -{ - static void (*draw_func[hud_comp_count]) (ecs_pool_t *) = { - [hud_update] = draw_update, - [hud_updateonce] = draw_updateonce, - [hud_tile] = draw_tile_views, - [hud_pic] = draw_pic_views, - [hud_subpic] = draw_subpic_views, - [hud_cachepic] = draw_cachepic_views, - [hud_fill] = draw_fill_views, - [hud_charbuff] = draw_charbuff_views, - [hud_func] = draw_func_views, - [hud_outline] = draw_outline_views, - }; - for (int i = 0; i < hud_comp_count; i++) { - if (draw_func[i]) { - draw_func[i] (&hud_system.reg->comp_pools[i + hud_system.base]); - } - } -} diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 7711e9437..7d4b0e63d 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -54,6 +54,7 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/canvas.h" #include "QF/ui/passage.h" #include "QF/ui/view.h" @@ -89,11 +90,18 @@ static int sbar_gametype; static int sbar_active; static int sbar_intermission; +static view_t hud_overlay_view; +static view_t hud_stuff_view; +static view_t hud_time_view; +static view_t hud_fps_view; +static view_t hud_ping_view; +static view_t hud_pl_view; + static view_t intermission_view; static view_t intermission_time; static view_t intermission_secr; static view_t intermission_kill; -// view_t hud_view; +static view_t hud_view; static view_t hud_miniteam; static view_t sbar_main; static view_t hud_minifrags; // child of sbar_main for positioning @@ -165,7 +173,7 @@ static view_def_t miniteam_defs[] = { }; static view_def_t sbar_defs[] = { - {&hud_overlay_view, { 0, 0,320,200}, grav_center, &cl_screen_view}, + {&hud_overlay_view, { 0, 0,320,200}, grav_center, &hud_canvas_view}, {&intermission_view, { 0, 0,320,200}, grav_northwest, &hud_overlay_view}, {0, {0, 24, 192, 24}, grav_north, &intermission_view, 1, 0, 0}, {0, {0, 56, 160, 144}, grav_northwest, &intermission_view, 1, 0, 0}, @@ -183,7 +191,7 @@ static view_def_t sbar_defs[] = { {0, {72, 0, 16, 24}, grav_northwest, &intermission_kill, 1, 0, 0}, {0, {80, 0, 24, 24}, grav_northwest, &intermission_kill, 3, 24, 0}, - {&hud_view, { 0, 0,320, 48}, grav_south, &cl_screen_view}, + {&hud_view, { 0, 0,320, 48}, grav_south, &hud_canvas_view}, {&hud_miniteam, { 0, 0, 96, 48}, grav_southeast, &hud_view}, {0, {0,0,96,8}, grav_northwest, &hud_miniteam, 6, 0, 8, miniteam_defs}, {&sbar_main, { 0, 0,320, 48}, grav_south, &hud_view}, @@ -229,12 +237,12 @@ static view_def_t sbar_defs[] = { {0, { 0, 0, 24, 24}, grav_northwest, &sbar_health, 3, 24, 0}, {0, {10, 0, 24, 8}, grav_northwest, &sbar_miniammo, 4, 48, 0}, - {&spectator_view, { 0, 0,320, 32}, grav_south, &cl_screen_view}, + {&spectator_view, { 0, 0,320, 32}, grav_south, &hud_canvas_view}, {0, { 0, 0, 312, 8}, grav_north, &spectator_view, 1, 0, 0}, {0, { 0, 8, 320, 24}, grav_northwest, &spectator_view, 1, 0, 0}, {0, { 0, 12, 112, 8}, grav_north, &spectator_view, 1, 0, 0}, {0, { 0, 20, 232, 8}, grav_north, &spectator_view, 1, 0, 0}, - {&deathmatch_view, { 0, 0,320, 200}, grav_center, &cl_screen_view}, + {&deathmatch_view, { 0, 0,320, 200}, grav_center, &hud_canvas_view}, {} }; @@ -251,10 +259,12 @@ static draw_charbuffer_t *solo_secrets; static draw_charbuffer_t *solo_time; static draw_charbuffer_t *solo_name; +static ecs_system_t sbar_viewsys; + static view_t sbar_view (int x, int y, int w, int h, grav_t gravity, view_t parent) { - view_t view = View_New (hud_viewsys, parent); + view_t view = View_New (sbar_viewsys, parent); View_SetPos (view, x, y); View_SetLen (view, w, h); View_SetGravity (view, gravity); @@ -287,9 +297,9 @@ sbar_remcomponent (view_t view, uint32_t comp) } static inline void -set_update (view_t view, hud_update_f func) +set_update (view_t view, canvas_update_f func) { - sbar_setcomponent (view, hud_updateonce, &func); + sbar_setcomponent (view, canvas_updateonce, &func); } #define STAT_MINUS 10 // num frame for '-' stats digit @@ -298,7 +308,7 @@ static qpic_t *sb_nums[2][11]; static qpic_t *sb_colon, *sb_slash; static qpic_t *sb_ibar[2]; static int sb_ibar_index; -static hud_subpic_t sb_miniammo[4]; +static canvas_subpic_t sb_miniammo[4]; static qpic_t *sb_sbar; static qpic_t *sb_scorebar; @@ -307,7 +317,7 @@ static qpic_t *sb_scorebar; static int sb_weapon_count; static int sb_weapon_view_count; static int sb_game; -static hud_subpic_t sb_weapons[7][12]; +static canvas_subpic_t sb_weapons[7][12]; static qpic_t *sb_ammo[7]; // rogue adds 3 ammo types static qpic_t *sb_sigil[4]; static qpic_t *sb_armor[3]; @@ -440,7 +450,7 @@ draw_num (view_t *view, int num, int digits, int color) if (l > digits) ptr += (l - digits); while (digits > l) { - sbar_remcomponent (view[x++], hud_pic); + sbar_remcomponent (view[x++], canvas_pic); digits--; } @@ -450,7 +460,7 @@ draw_num (view_t *view, int num, int digits, int color) else frame = *ptr - '0'; - sbar_setcomponent (view[x++], hud_pic, &sb_nums[color][frame]); + sbar_setcomponent (view[x++], canvas_pic, &sb_nums[color][frame]); ptr++; } } @@ -458,7 +468,7 @@ draw_num (view_t *view, int num, int digits, int color) static void draw_smallnum (view_t view, int n, int packed, int colored) { - void *comp = sbar_getcomponent (view, hud_charbuff); + void *comp = sbar_getcomponent (view, canvas_charbuff); __auto_type charbuff = *(draw_charbuffer_t **) comp; char num[4]; @@ -516,9 +526,9 @@ draw_ammo (view_t view) view_t ammo = View_GetChild (view, 0); if (pic) { - sbar_setcomponent (ammo, hud_pic, &pic); + sbar_setcomponent (ammo, canvas_pic, &pic); } else { - sbar_remcomponent (ammo, hud_pic); + sbar_remcomponent (ammo, canvas_pic); } view_t num[3] = { @@ -582,10 +592,11 @@ draw_weapons (view_t view) flashon = calc_flashon (time, mask, 2); if (flashon > 1) sb_updates = 0; // force update to remove flash - sbar_setcomponent (weap, hud_subpic, &sb_weapons[flashon][i]); + sbar_setcomponent (weap, canvas_subpic, + &sb_weapons[flashon][i]); } } else { - sbar_remcomponent (weap, hud_subpic); + sbar_remcomponent (weap, canvas_subpic); } } } @@ -605,9 +616,9 @@ draw_items (view_t view) -1, 1); if (flashon > 1) sb_updates = 0; // force update to remove flash - sbar_setcomponent (item, hud_pic, &sb_items[flashon][i]); + sbar_setcomponent (item, canvas_pic, &sb_items[flashon][i]); } else { - sbar_remcomponent (item, hud_pic); + sbar_remcomponent (item, canvas_pic); } } } @@ -618,9 +629,9 @@ draw_sigils (view_t view) for (int i = 0; i < 4; i++) { view_t sigil = View_GetChild (view, i); if (sbar_stats[STAT_ITEMS] & (1 << (28 + i))) { - sbar_setcomponent (sigil, hud_pic, &sb_sigil[i]); + sbar_setcomponent (sigil, canvas_pic, &sb_sigil[i]); } else { - sbar_remcomponent (sigil, hud_pic); + sbar_remcomponent (sigil, canvas_pic); } } } @@ -777,69 +788,69 @@ draw_solo_time (void) static void draw_solo (view_t view) { - sbar_setcomponent (sbar_solo, hud_pic, &sb_scorebar); - sbar_setcomponent (sbar_solo_monsters, hud_charbuff, &solo_monsters); - sbar_setcomponent (sbar_solo_secrets, hud_charbuff, &solo_secrets); - sbar_setcomponent (sbar_solo_time, hud_charbuff, &solo_time); - sbar_setcomponent (sbar_solo_name, hud_charbuff, &solo_name); + sbar_setcomponent (sbar_solo, canvas_pic, &sb_scorebar); + sbar_setcomponent (sbar_solo_monsters, canvas_charbuff, &solo_monsters); + sbar_setcomponent (sbar_solo_secrets, canvas_charbuff, &solo_secrets); + sbar_setcomponent (sbar_solo_time, canvas_charbuff, &solo_time); + sbar_setcomponent (sbar_solo_name, canvas_charbuff, &solo_name); } static void hide_solo (view_t view) { - sbar_remcomponent (sbar_solo, hud_pic); - sbar_remcomponent (sbar_solo_monsters, hud_charbuff); - sbar_remcomponent (sbar_solo_secrets, hud_charbuff); - sbar_remcomponent (sbar_solo_time, hud_charbuff); - sbar_remcomponent (sbar_solo_name, hud_charbuff); + sbar_remcomponent (sbar_solo, canvas_pic); + sbar_remcomponent (sbar_solo_monsters, canvas_charbuff); + sbar_remcomponent (sbar_solo_secrets, canvas_charbuff); + sbar_remcomponent (sbar_solo_time, canvas_charbuff); + sbar_remcomponent (sbar_solo_name, canvas_charbuff); } static void clear_frags_bar (view_t view) { - sbar_remcomponent (View_GetChild (view, 0), hud_fill); - sbar_remcomponent (View_GetChild (view, 1), hud_fill); - sbar_remcomponent (View_GetChild (view, 2), hud_charbuff); - sbar_remcomponent (View_GetChild (view, 3), hud_func); + sbar_remcomponent (View_GetChild (view, 0), canvas_fill); + sbar_remcomponent (View_GetChild (view, 1), canvas_fill); + sbar_remcomponent (View_GetChild (view, 2), canvas_charbuff); + sbar_remcomponent (View_GetChild (view, 3), canvas_func); } static void clear_minifrags_bar (view_t view) { clear_frags_bar (view); - sbar_remcomponent (View_GetChild (view, 4), hud_charbuff); - sbar_remcomponent (View_GetChild (view, 5), hud_charbuff); - sbar_remcomponent (View_GetChild (view, 6), hud_charbuff); + sbar_remcomponent (View_GetChild (view, 4), canvas_charbuff); + sbar_remcomponent (View_GetChild (view, 5), canvas_charbuff); + sbar_remcomponent (View_GetChild (view, 6), canvas_charbuff); } static void set_frags_bar (view_t view, byte top, byte bottom, draw_charbuffer_t *buff, - hud_func_f func) + canvas_func_f func) { - sbar_setcomponent (View_GetChild (view, 0), hud_fill, &top); - sbar_setcomponent (View_GetChild (view, 1), hud_fill, &bottom); - sbar_setcomponent (View_GetChild (view, 2), hud_charbuff, &buff); + sbar_setcomponent (View_GetChild (view, 0), canvas_fill, &top); + sbar_setcomponent (View_GetChild (view, 1), canvas_fill, &bottom); + sbar_setcomponent (View_GetChild (view, 2), canvas_charbuff, &buff); if (func) { - sbar_setcomponent (View_GetChild (view, 3), hud_func, &func); + sbar_setcomponent (View_GetChild (view, 3), canvas_func, &func); } else { - sbar_remcomponent (View_GetChild (view, 3), hud_func); + sbar_remcomponent (View_GetChild (view, 3), canvas_func); } } static void set_minifrags_bar (view_t view, byte top, byte bottom, draw_charbuffer_t *buff, - hud_func_f func, draw_charbuffer_t *team, + canvas_func_f func, draw_charbuffer_t *team, draw_charbuffer_t *name) { set_frags_bar (view, top, bottom, buff, func); if (team) { - sbar_setcomponent (View_GetChild (view, 4), hud_charbuff, &team); - sbar_setcomponent (View_GetChild (view, 5), hud_charbuff, &name); - sbar_remcomponent (View_GetChild (view, 6), hud_charbuff); + sbar_setcomponent (View_GetChild (view, 4), canvas_charbuff, &team); + sbar_setcomponent (View_GetChild (view, 5), canvas_charbuff, &name); + sbar_remcomponent (View_GetChild (view, 6), canvas_charbuff); } else { - sbar_remcomponent (View_GetChild (view, 4), hud_charbuff); - sbar_remcomponent (View_GetChild (view, 5), hud_charbuff); - sbar_setcomponent (View_GetChild (view, 6), hud_charbuff, &name); + sbar_remcomponent (View_GetChild (view, 4), canvas_charbuff); + sbar_remcomponent (View_GetChild (view, 5), canvas_charbuff); + sbar_setcomponent (View_GetChild (view, 6), canvas_charbuff, &name); } } @@ -926,21 +937,21 @@ draw_minifrags (view_t view) static void clear_miniteam_bar (view_t view) { - sbar_remcomponent (View_GetChild (view, 0), hud_charbuff); - sbar_remcomponent (View_GetChild (view, 1), hud_charbuff); - sbar_remcomponent (View_GetChild (view, 2), hud_func); + sbar_remcomponent (View_GetChild (view, 0), canvas_charbuff); + sbar_remcomponent (View_GetChild (view, 1), canvas_charbuff); + sbar_remcomponent (View_GetChild (view, 2), canvas_func); } static void set_miniteam_bar (view_t view, draw_charbuffer_t *team, - draw_charbuffer_t *frags, hud_func_f func) + draw_charbuffer_t *frags, canvas_func_f func) { - sbar_setcomponent (View_GetChild (view, 0), hud_charbuff, &team); - sbar_setcomponent (View_GetChild (view, 1), hud_charbuff, &frags); + sbar_setcomponent (View_GetChild (view, 0), canvas_charbuff, &team); + sbar_setcomponent (View_GetChild (view, 1), canvas_charbuff, &frags); if (func) { - sbar_setcomponent (View_GetChild (view, 2), hud_func, &func); + sbar_setcomponent (View_GetChild (view, 2), canvas_func, &func); } else { - sbar_remcomponent (View_GetChild (view, 2), hud_func); + sbar_remcomponent (View_GetChild (view, 2), canvas_func); } } @@ -963,7 +974,7 @@ draw_miniteam (view_t view) team_t *tm = teams + k; __auto_type s = &sbar_players[k]; view_t bar = View_GetChild (view, i); - hud_func_f func = 0; + canvas_func_f func = 0; if (player_team && strnequal (player_team->value, tm->team, 16)) { func = frags_marker; } @@ -986,7 +997,7 @@ draw_face (view_t view) return; } if (sbar_stats[STAT_HEALTH] <= 0) {//FIXME hide_Face or hide_sbar - sbar_remcomponent (sbar_face, hud_pic); + sbar_remcomponent (sbar_face, canvas_pic); return; } if ((sbar_stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY)) @@ -1014,7 +1025,7 @@ draw_face (view_t view) } face = sb_faces[f][anim]; } - sbar_setcomponent (view, hud_pic, &face); + sbar_setcomponent (view, canvas_pic, &face); } static void @@ -1028,21 +1039,21 @@ draw_spectator (view_t view) }; if (sbar_autotrack < 0) { - sbar_setcomponent (back, hud_pic, &sb_scorebar); - sbar_setcomponent (notrack[0], hud_charbuff, &spec_buff[0]); - sbar_setcomponent (notrack[1], hud_charbuff, &spec_buff[1]); - sbar_remcomponent (tracking, hud_charbuff); + sbar_setcomponent (back, canvas_pic, &sb_scorebar); + sbar_setcomponent (notrack[0], canvas_charbuff, &spec_buff[0]); + sbar_setcomponent (notrack[1], canvas_charbuff, &spec_buff[1]); + sbar_remcomponent (tracking, canvas_charbuff); } else { - sbar_remcomponent (back, hud_pic); - sbar_remcomponent (notrack[0], hud_charbuff); - sbar_remcomponent (notrack[1], hud_charbuff); + sbar_remcomponent (back, canvas_pic); + sbar_remcomponent (notrack[0], canvas_charbuff); + sbar_remcomponent (notrack[1], canvas_charbuff); if (sbar_players[sbar_autotrack].name) { write_charbuff_cl (spec_buff[3], 0, 0, va (0, "Tracking %.13s, [JUMP] for next", sbar_players[sbar_autotrack].name->value)); - sbar_setcomponent (tracking, hud_charbuff, &spec_buff[3]); + sbar_setcomponent (tracking, canvas_charbuff, &spec_buff[3]); } else { - sbar_setcomponent (tracking, hud_charbuff, &spec_buff[2]); + sbar_setcomponent (tracking, canvas_charbuff, &spec_buff[2]); } } } @@ -1051,8 +1062,8 @@ static void hide_spectator (view_t view) { for (int i = 0; i < 4; i++) { - sbar_remcomponent (View_GetChild (view, i), hud_charbuff); - sbar_remcomponent (View_GetChild (view, i), hud_pic); + sbar_remcomponent (View_GetChild (view, i), canvas_charbuff); + sbar_remcomponent (View_GetChild (view, i), canvas_pic); } } @@ -1070,13 +1081,13 @@ draw_armor (view_t view) } else { draw_num (num, sbar_stats[STAT_ARMOR], 3, sbar_stats[STAT_ARMOR] <= 25); if (sbar_stats[STAT_ITEMS] & IT_ARMOR3) - sbar_setcomponent (armor, hud_pic, &sb_armor[2]); + sbar_setcomponent (armor, canvas_pic, &sb_armor[2]); else if (sbar_stats[STAT_ITEMS] & IT_ARMOR2) - sbar_setcomponent (armor, hud_pic, &sb_armor[1]); + sbar_setcomponent (armor, canvas_pic, &sb_armor[1]); else if (sbar_stats[STAT_ITEMS] & IT_ARMOR1) - sbar_setcomponent (armor, hud_pic, &sb_armor[0]); + sbar_setcomponent (armor, canvas_pic, &sb_armor[0]); else - sbar_remcomponent (armor, hud_pic); + sbar_remcomponent (armor, canvas_pic); } } @@ -1097,11 +1108,11 @@ draw_rogue_ctf_face (view_t view) __auto_type p = &sbar_players[sbar_viewplayer]; byte top = Sbar_ColorForMap (p->topcolor); byte bottom = Sbar_ColorForMap (p->bottomcolor); - sbar_setcomponent (View_GetChild (view, 0), hud_fill, &top); - sbar_setcomponent (View_GetChild (view, 1), hud_fill, &bottom); - sbar_setcomponent (View_GetChild (view, 2), hud_charbuff, + sbar_setcomponent (View_GetChild (view, 0), canvas_fill, &top); + sbar_setcomponent (View_GetChild (view, 1), canvas_fill, &bottom); + sbar_setcomponent (View_GetChild (view, 2), canvas_charbuff, &sb_frags[sbar_viewplayer]); - sbar_setcomponent (view, hud_pic, &rsb_teambord); + sbar_setcomponent (view, canvas_pic, &rsb_teambord); } static void @@ -1124,7 +1135,7 @@ static void setup_spect (view_t spect, int player) { view_t v = sbar_view (0, 0, 88, 4, grav_north, spect); - sbar_setcomponent (v, hud_charbuff, &sb_spectator); + sbar_setcomponent (v, canvas_charbuff, &sb_spectator); } typedef struct dmo_def_s { @@ -1301,7 +1312,7 @@ make_dmo_line (view_t parent, int player, int line_type) grav_northwest, line); if (d->buffer) { draw_charbuffer_t *buff = d->buffer[player]; - sbar_setcomponent (v, hud_charbuff, &buff); + sbar_setcomponent (v, canvas_charbuff, &buff); } else if (d->setup) { d->setup (v, player); } @@ -1621,8 +1632,8 @@ Sbar_DrawCenterString (view_t view, unsigned remaining) static void clear_views (view_t view) { - sbar_remcomponent (view, hud_cachepic); - sbar_remcomponent (view, hud_pic); + sbar_remcomponent (view, canvas_cachepic); + sbar_remcomponent (view, canvas_pic); for (uint32_t i = 0; i < View_ChildCount (view); i++) { clear_views (View_GetChild (view, i)); @@ -1635,9 +1646,9 @@ draw_intermission (view_t view) clear_views (view); const char *n; n = "gfx/complete.lmp"; - sbar_setcomponent (View_GetChild (view, 0), hud_cachepic, &n); + sbar_setcomponent (View_GetChild (view, 0), canvas_cachepic, &n); n = "gfx/inter.lmp"; - sbar_setcomponent (View_GetChild (view, 1), hud_cachepic, &n); + sbar_setcomponent (View_GetChild (view, 1), canvas_cachepic, &n); view_t time_views[] = { View_GetChild (intermission_time, 0), @@ -1650,7 +1661,7 @@ draw_intermission (view_t view) int dig = sbar_completed_time / 60; int num = sbar_completed_time - dig * 60; draw_num (time_views + 0, dig, 3, 0); - sbar_setcomponent (time_views[3], hud_pic, &sb_colon); + sbar_setcomponent (time_views[3], canvas_pic, &sb_colon); draw_num (time_views + 4, num, 2, 0); view_t secr_views[] = { @@ -1663,7 +1674,7 @@ draw_intermission (view_t view) View_GetChild (intermission_secr, 6), }; draw_num (secr_views + 0, sbar_stats[STAT_SECRETS], 3, 0); - sbar_setcomponent (secr_views[3], hud_pic, &sb_slash); + sbar_setcomponent (secr_views[3], canvas_pic, &sb_slash); draw_num (secr_views + 4, sbar_stats[STAT_TOTALSECRETS], 3, 0); view_t kill_views[] = { @@ -1676,7 +1687,7 @@ draw_intermission (view_t view) View_GetChild (intermission_kill, 6), }; draw_num (kill_views + 0, sbar_stats[STAT_MONSTERS], 3, 0); - sbar_setcomponent (kill_views[3], hud_pic, &sb_slash); + sbar_setcomponent (kill_views[3], canvas_pic, &sb_slash); draw_num (kill_views + 4, sbar_stats[STAT_TOTALMONSTERS], 3, 0); } @@ -1688,7 +1699,7 @@ draw_finale (view_t view) r_data->scr_copyeverything = 1; const char *n = "gfx/finale.lmp"; - sbar_setcomponent (View_GetChild (view, 2), hud_cachepic, &n); + sbar_setcomponent (View_GetChild (view, 2), canvas_cachepic, &n); } static void @@ -1700,7 +1711,7 @@ draw_cutscene (view_t view) void Sbar_Intermission (int mode, double completed_time) { - static hud_update_f intermission_funcs[2][3] = { + static canvas_update_f intermission_funcs[2][3] = { { draw_intermission, draw_finale, draw_cutscene, }, { draw_deathmatch, draw_finale, draw_cutscene, }, }; @@ -1838,12 +1849,12 @@ update_weapon (int stat) if (hud_sbar) { // shouldn't need to sort the pics because the component is already // on the entity, so the position in the pool won't be affected - sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar[sb_ibar_index]); + sbar_setcomponent (sbar_inventory, canvas_pic, &sb_ibar[sb_ibar_index]); } else { for (int i = 0; i < 4; i++) { view_t v = View_GetChild (sbar_miniammo, i); sb_miniammo[i].pic = sb_ibar[sb_ibar_index]; - sbar_setcomponent (v, hud_subpic, &sb_miniammo[i]); + sbar_setcomponent (v, canvas_subpic, &sb_miniammo[i]); } } } @@ -2019,22 +2030,6 @@ sbar_hud_swap_f (void *data, const cvar_t *cvar) View_UpdateHierarchy (hud_view); } -static int -href_cmp (const void *_a, const void *_b, void *arg) -{ - uint32_t enta = *(const uint32_t *)_a; - uint32_t entb = *(const uint32_t *)_b; - ecs_registry_t *reg = hud_viewsys.reg; - uint32_t href = hud_viewsys.base + view_href; - hierref_t *ref_a = Ent_GetComponent (enta, href, reg); - hierref_t *ref_b = Ent_GetComponent (entb, href, reg); - if (ref_a->hierarchy == ref_b->hierarchy) { - return ref_a->index - ref_b->index; - } - ptrdiff_t diff = ref_a->hierarchy - ref_b->hierarchy; - return diff > 0 ? 1 : diff < 0 ? -1 : 0; -} - static void set_hud_sbar (void) { @@ -2059,8 +2054,8 @@ set_hud_sbar (void) View_SetLen (v, sb_weapons[0][i].pic->width, 16); x += sb_weapons[0][i].pic->width; - if (sbar_hascomponent (v, hud_subpic)) { - hud_subpic_t *subpic = sbar_getcomponent(v, hud_subpic); + if (sbar_hascomponent (v, canvas_subpic)) { + canvas_subpic_t *subpic = sbar_getcomponent(v, canvas_subpic); subpic->w = subpic->pic->width; } } @@ -2068,7 +2063,7 @@ set_hud_sbar (void) v = View_GetChild (sbar_miniammo, i); View_SetPos (v, i * 48 + 10, 0); View_SetLen (v, 42, 8); - sbar_remcomponent (v, hud_subpic); + sbar_remcomponent (v, canvas_subpic); } for (int i = 0; i < 7; i++) { for (int j = 0; j < sb_weapon_view_count; j++) { @@ -2079,10 +2074,10 @@ set_hud_sbar (void) } } - sbar_setcomponent (sbar_inventory, hud_pic, &sb_ibar[sb_ibar_index]); - sbar_setcomponent (sbar_statusbar, hud_pic, &sb_sbar); - sbar_setcomponent (sbar_tile[0], hud_tile, 0); - sbar_setcomponent (sbar_tile[1], hud_tile, 0); + sbar_setcomponent (sbar_inventory, canvas_pic, &sb_ibar[sb_ibar_index]); + sbar_setcomponent (sbar_statusbar, canvas_pic, &sb_sbar); + sbar_setcomponent (sbar_tile[0], canvas_tile, 0); + sbar_setcomponent (sbar_tile[1], canvas_tile, 0); } else { View_SetParent (sbar_armament, hud_view); View_SetPos (sbar_armament, 0, 48); @@ -2100,8 +2095,8 @@ set_hud_sbar (void) View_SetPos (v, 0, i * 16); View_SetLen (v, 24, 16); - if (sbar_hascomponent (v, hud_subpic)) { - hud_subpic_t *subpic = sbar_getcomponent(v, hud_subpic); + if (sbar_hascomponent (v, canvas_subpic)) { + canvas_subpic_t *subpic = sbar_getcomponent(v, canvas_subpic); subpic->w = 24; } } @@ -2109,7 +2104,7 @@ set_hud_sbar (void) v = View_GetChild (sbar_miniammo, i); View_SetPos (v, 0, i * 11); View_SetLen (v, 42, 11); - sbar_setcomponent (v, hud_subpic, &sb_miniammo[i]); + sbar_setcomponent (v, canvas_subpic, &sb_miniammo[i]); } for (int i = 0; i < 7; i++) { for (int j = 0; j < sb_weapon_view_count; j++) { @@ -2120,13 +2115,12 @@ set_hud_sbar (void) } } - sbar_remcomponent (sbar_inventory, hud_pic); - sbar_remcomponent (sbar_statusbar, hud_pic); - sbar_remcomponent (sbar_tile[0], hud_tile); - sbar_remcomponent (sbar_tile[1], hud_tile); + sbar_remcomponent (sbar_inventory, canvas_pic); + sbar_remcomponent (sbar_statusbar, canvas_pic); + sbar_remcomponent (sbar_tile[0], canvas_tile); + sbar_remcomponent (sbar_tile[1], canvas_tile); } - ECS_SortComponentPool (hud_system.reg, hud_system.base + hud_pic, - href_cmp, 0); + Canvas_SortComponentPool (cl_canvas_sys, hud_canvas, canvas_pic); } static void @@ -2141,11 +2135,11 @@ sbar_hud_fps_f (void *data, const cvar_t *cvar) { if (hud_fps) { void *f = draw_fps; - sbar_setcomponent (hud_fps_view, hud_update, &f); - sbar_setcomponent (hud_fps_view, hud_charbuff, &fps_buff); + sbar_setcomponent (hud_fps_view, canvas_update, &f); + sbar_setcomponent (hud_fps_view, canvas_charbuff, &fps_buff); } else { - sbar_remcomponent (hud_fps_view, hud_update); - sbar_remcomponent (hud_fps_view, hud_charbuff); + sbar_remcomponent (hud_fps_view, canvas_update); + sbar_remcomponent (hud_fps_view, canvas_charbuff); } } @@ -2153,9 +2147,9 @@ static void sbar_hud_ping_f (void *data, const cvar_t *cvar) { if (hud_ping) { - sbar_setcomponent (hud_ping_view, hud_charbuff, &ping_buff); + sbar_setcomponent (hud_ping_view, canvas_charbuff, &ping_buff); } else { - sbar_remcomponent (hud_ping_view, hud_charbuff); + sbar_remcomponent (hud_ping_view, canvas_charbuff); } } @@ -2163,9 +2157,9 @@ static void sbar_hud_pl_f (void *data, const cvar_t *cvar) { if (hud_pl) { - sbar_setcomponent (hud_pl_view, hud_charbuff, &pl_buff); + sbar_setcomponent (hud_pl_view, canvas_charbuff, &pl_buff); } else { - sbar_remcomponent (hud_pl_view, hud_charbuff); + sbar_remcomponent (hud_pl_view, canvas_charbuff); } } @@ -2174,11 +2168,11 @@ sbar_hud_time_f (void *data, const cvar_t *cvar) { if (hud_time) { void *f = draw_time; - sbar_setcomponent (hud_time_view, hud_update, &f); - sbar_setcomponent (hud_time_view, hud_charbuff, &time_buff); + sbar_setcomponent (hud_time_view, canvas_update, &f); + sbar_setcomponent (hud_time_view, canvas_charbuff, &time_buff); } else { - sbar_remcomponent (hud_time_view, hud_update); - sbar_remcomponent (hud_time_view, hud_charbuff); + sbar_remcomponent (hud_time_view, canvas_update); + sbar_remcomponent (hud_time_view, canvas_charbuff); } } @@ -2217,7 +2211,7 @@ static void init_sbar_views (void) { create_views (sbar_defs, nullview); - view_pos_t slen = View_GetLen (cl_screen_view); + view_pos_t slen = View_GetLen (hud_canvas_view); view_pos_t hlen = View_GetLen (hud_view); View_SetLen (hud_view, slen.x, hlen.y); View_SetResize (hud_view, 1, 0); @@ -2226,7 +2220,7 @@ init_sbar_views (void) view_t v = View_GetChild (sbar_miniammo, i); draw_charbuffer_t *buffer = Draw_CreateBuffer (3, 1); Draw_ClearBuffer (buffer); - sbar_setcomponent (v, hud_charbuff, &buffer); + sbar_setcomponent (v, canvas_charbuff, &buffer); } if (r_data->vid->width > 320) { @@ -2235,8 +2229,8 @@ init_sbar_views (void) View_SetLen (sbar_tile[0], l, 48); View_SetPos (sbar_tile[1], -l, 0); View_SetLen (sbar_tile[1], l, 48); - sbar_setcomponent (sbar_tile[0], hud_tile, 0); - sbar_setcomponent (sbar_tile[1], hud_tile, 0); + sbar_setcomponent (sbar_tile[0], canvas_tile, 0); + sbar_setcomponent (sbar_tile[1], canvas_tile, 0); } solo_monsters = Draw_CreateBuffer (17, 1); @@ -2264,7 +2258,7 @@ init_sbar_views (void) static void init_views (void) { - hud_stuff_view = sbar_view (0, 48, 152, 16, grav_southwest, cl_screen_view); + hud_stuff_view = sbar_view (0, 48, 152, 16, grav_southwest, hud_canvas_view); hud_time_view = sbar_view (8, 0, 64, 8, grav_northwest, hud_stuff_view); hud_fps_view = sbar_view (80, 0, 80, 8, grav_northwest, hud_stuff_view); hud_ping_view = sbar_view (0, 8, 48, 0, grav_northwest, hud_stuff_view); @@ -2497,7 +2491,7 @@ load_pics (void) sb_ibar[1] = sb_ibar[0]; } for (int i = 0; i < 4; i++) { - sb_miniammo[i] = (hud_subpic_t) { + sb_miniammo[i] = (canvas_subpic_t) { .pic = sb_ibar[0], .x = 3 + (i * 48), .y = 0, @@ -2554,6 +2548,11 @@ Sbar_Init (int *stats, float *item_gettime) sbar_stats = stats; sbar_item_gettime = item_gettime; + sbar_viewsys = (ecs_system_t) { + .reg = cl_canvas_sys.reg, + .base = cl_canvas_sys.view_base, + }; + center_passage.reg = hud_psgsys.reg; center_passage.comp_base = hud_psgsys.base; HUD_Init_Cvars (); diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 4261e5eda..ae734e210 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -40,6 +40,7 @@ #include "QF/render.h" #include "QF/screen.h" #include "QF/va.h" +#include "QF/ui/canvas.h" #include "QF/ui/view.h" #include "client/hud.h" @@ -156,12 +157,17 @@ CL_NetGraph (view_pos_t abs, view_pos_t len) void CL_NetGraph_Init (void) { - cl_netgraph_view = View_New (hud_viewsys, cl_screen_view); + ecs_system_t vsys = { + .reg = cl_canvas_sys.reg, + .base = cl_canvas_sys.view_base, + }; + cl_netgraph_view = View_New (vsys, cl_screen_view); View_SetPos (cl_netgraph_view, 0, 64); View_SetLen (cl_netgraph_view, NET_TIMINGS + 16, cl_netgraph_height + 25); View_SetGravity (cl_netgraph_view, grav_southwest); void *f = CL_NetGraph; - Ent_SetComponent (cl_netgraph_view.id, hud_func, cl_netgraph_view.reg, &f); + Ent_SetComponent (cl_netgraph_view.id, canvas_func, + cl_netgraph_view.reg, &f); View_SetVisible (cl_netgraph_view, cl_netgraph); } From 03e867f0f81f699207edd2a260dd98e559167ea3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Jan 2023 11:20:09 +0900 Subject: [PATCH 3359/3664] [ui] Remove some extra debug outlines Forcing hidden views and doing the outlines for the screen canvas were part of sorting out weirdnesses with canvases and component sub-pools. --- libs/client/hud.c | 2 -- libs/ui/canvas.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/client/hud.c b/libs/client/hud.c index f9abd4f1d..52b6c4048 100644 --- a/libs/client/hud.c +++ b/libs/client/hud.c @@ -154,11 +154,9 @@ hud_debug_f (void *data, const cvar_t *cvar) return; } if (hud_debug) { - hud_add_outlines (cl_screen_view, 0xfb); hud_add_outlines (hud_canvas_view, 0x6f); } else { hud_remove_outlines (hud_canvas_view); - hud_remove_outlines (cl_screen_view); } } diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index 86bf20d57..1bfb2180a 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -319,7 +319,7 @@ draw_outline_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, while (count-- > 0) { view_t view = View_FromEntity (viewsys, *ent++); byte c = *col++; - if (1 || View_GetVisible (view)) { + if (View_GetVisible (view)) { view_pos_t p = View_GetAbs (view); view_pos_t l = View_GetLen (view); view_pos_t q = { p.x + l.x - 1, p.y + l.y - 1 }; From 3d52caadec686725286f0aae67d0e7ada5302b3e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Jan 2023 13:58:43 +0900 Subject: [PATCH 3360/3664] [ecs] Avoid shuffling components in empty ranges When bubbling a component past an empty range, there's no need for any actual movement other than adjusting the range itself, and doing so corrupts the sparse/dense array relationship. Fixes a segfault when hiding the deathmatch overlay (that resulted from the change to using canvases). --- libs/ecs/entity.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index d34a21a03..211811484 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -123,10 +123,12 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) while (range - subpool->ranges < range_count) { uint32_t end = --*range; range++; - pool->sparse[Ent_Index (pool->dense[end])] = ind; - pool->dense[ind] = pool->dense[end]; - Component_MoveElements (c, pool->data, ind, end, 1); - ind = end; + if (ind < end) { + pool->sparse[Ent_Index (pool->dense[end])] = ind; + pool->dense[ind] = pool->dense[end]; + Component_MoveElements (c, pool->data, ind, end, 1); + ind = end; + } } } if (last > ind) { From d10cfb348ebc486b30e8d25c585b5330642d5f9f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Jan 2023 16:33:45 +0900 Subject: [PATCH 3361/3664] [client] Ensure status char buffers are cleared Fixes uninitialized values when hud_pl is enabled for overkill in qw (pl is never updated, so it never gets set). --- libs/client/sbar.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 7d4b0e63d..5cc348513 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -2264,10 +2264,10 @@ init_views (void) hud_ping_view = sbar_view (0, 8, 48, 0, grav_northwest, hud_stuff_view); hud_pl_view = sbar_view (56, 8, 48, 0, grav_northwest, hud_stuff_view); - time_buff = Draw_CreateBuffer (8, 1); - fps_buff = Draw_CreateBuffer (10, 1); - ping_buff = Draw_CreateBuffer (6, 1); - pl_buff = Draw_CreateBuffer (6, 1); + Draw_ClearBuffer (time_buff = Draw_CreateBuffer (8, 1)); + Draw_ClearBuffer (fps_buff = Draw_CreateBuffer (10, 1)); + Draw_ClearBuffer (ping_buff = Draw_CreateBuffer (6, 1)); + Draw_ClearBuffer (pl_buff = Draw_CreateBuffer (6, 1)); for (int i = 0; i < MAX_PLAYERS; i++) { sb_fph[i] = Draw_CreateBuffer (3, 1); From bc041d62911b1836171e587a9d5806d8014a9912 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 21 Jan 2023 16:35:21 +0900 Subject: [PATCH 3362/3664] [vulkan] Zero draw's frame structs Some of the queues start don't get fully initialized, but rather than go through everything making sure they do, it's just easier to zero the whole lot at the beginning. --- libs/video/renderer/vulkan/vulkan_draw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 6316f349b..9625cad17 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -886,6 +886,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&dctx->frames, frames); DARRAY_RESIZE (&dctx->frames, frames); dctx->frames.grow = 0; + memset (dctx->frames.a, 0, dctx->frames.size * sizeof (drawframe_t)); + DARRAY_INIT (&dctx->fonts, 16); DARRAY_RESIZE (&dctx->fonts, 16); dctx->fonts.size = 0; From 254fcff8ff46c2b7d53802dfd07415c18cc4c8d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Jan 2023 01:04:23 +0900 Subject: [PATCH 3363/3664] [ecs] Find correct correct sub-pool range Returning -1 for key > value doesn't work too well for bsearch. --- libs/ecs/entity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index 211811484..a5fc3112f 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -90,7 +90,7 @@ range_cmp (const void *_key, const void *_range, void *_subpool) ecs_subpool_t *subpool = _subpool; if (*key >= *range) { - return -1; + return 1; } if (range - subpool->ranges > 0) { return *key >= range[-1] ? 0 : -1; From 158c45d1208754ac1f1e99a9413c77acbb259626 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Jan 2023 03:28:32 +0900 Subject: [PATCH 3364/3664] [vulkan] Correct calculation of conback position The problem with setting con_size to 0.5 and con_speed to 0 is it's difficult to tell when the console positioning is backwards. --- libs/video/renderer/vulkan/vulkan_draw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 9625cad17..ea0a10e3f 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1312,7 +1312,8 @@ Vulkan_Draw_ConsoleBackground (int lines, byte alpha, vulkan_ctx_t *ctx) qpic_t *cpic; cpic = Vulkan_Draw_CachePic ("gfx/conback.lmp", false, ctx); float s = 1.0 / ctx->twod_scale; - Vulkan_Draw_FitPic (0, -lines, vid.width * s, vid.height * s, cpic, ctx); + int y = lines - vid.height * s; + Vulkan_Draw_FitPic (0, y, vid.width * s, vid.height * s, cpic, ctx); } void From 89afcfcb6d5d0847007b48c2f2440d9d6fce83ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Jan 2023 03:43:58 +0900 Subject: [PATCH 3365/3664] [ui] Add a lateupdate component to canvas Like update, the function takes just a view, but is useful for updates that need to run after the other components are run. --- include/QF/ui/canvas.h | 1 + libs/ui/canvas.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/QF/ui/canvas.h b/include/QF/ui/canvas.h index a08c33605..a4d8f9552 100644 --- a/include/QF/ui/canvas.h +++ b/include/QF/ui/canvas.h @@ -46,6 +46,7 @@ enum { canvas_charbuff, canvas_func, canvas_outline, + canvas_lateupdate, // last so deleting an entity removes the grouped components first canvas_canvas, diff --git a/libs/ui/canvas.c b/libs/ui/canvas.c index 1bfb2180a..b2974da8e 100644 --- a/libs/ui/canvas.c +++ b/libs/ui/canvas.c @@ -67,6 +67,7 @@ canvas_rangeid(cachepic) canvas_rangeid(fill) canvas_rangeid(charbuff) canvas_rangeid(func) +canvas_rangeid(lateupdate) canvas_rangeid(outline) #undef canvas_rangeid @@ -126,6 +127,11 @@ const component_t canvas_components[canvas_comp_count] = { .name = "func", .rangeid = canvas_func_rangeid, }, + [canvas_lateupdate] = { + .size = sizeof (canvas_update_f), + .name = "lateupdate", + .rangeid = canvas_lateupdate_rangeid, + }, [canvas_outline] = { .size = sizeof (byte), .name = "outline", @@ -152,13 +158,6 @@ draw_update (canvas_system_t *canvas_sys, ecs_pool_t *pool, ecs_range_t range) } } -static void -draw_updateonce (canvas_system_t *canvas_sys, ecs_pool_t *pool, - ecs_range_t range) -{ - draw_update (canvas_sys, pool, range); -} - static void draw_tile_views (canvas_system_t *canvas_sys, ecs_pool_t *pool, ecs_range_t range) @@ -336,7 +335,7 @@ Canvas_Draw (canvas_system_t canvas_sys) { static canvas_sysfunc_f draw_func[canvas_comp_count] = { [canvas_update] = draw_update, - [canvas_updateonce] = draw_updateonce, + [canvas_updateonce] = draw_update, [canvas_tile] = draw_tile_views, [canvas_pic] = draw_pic_views, [canvas_fitpic] = draw_fitpic_views, @@ -345,6 +344,7 @@ Canvas_Draw (canvas_system_t canvas_sys) [canvas_fill] = draw_fill_views, [canvas_charbuff] = draw_charbuff_views, [canvas_func] = draw_func_views, + [canvas_lateupdate] = draw_update, [canvas_outline] = draw_outline_views, }; From a561558748e1d80b801b6481c0cce4248029c735 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Jan 2023 03:45:50 +0900 Subject: [PATCH 3366/3664] [console] Switch to using a canvas for the console While the console background is broken in that alpha doesn't work, it's now rendered correctly in all renderers. --- include/QF/plugin/console.h | 4 + libs/client/cl_screen.c | 9 +- libs/console/client.c | 248 +++++++++++++++++-------------- ruamoko/qwaq/builtins/graphics.c | 20 ++- 4 files changed, 164 insertions(+), 117 deletions(-) diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index 8d6e14902..b5f1ab536 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -52,6 +52,10 @@ typedef struct console_data_s { void (*quit) (void); struct cbuf_s *cbuf; struct view_s *status_view; + const struct component_s *components; + uint32_t num_components; + uint32_t component_base; + struct canvas_system_s *canvas_sys; float lines; int (*exec_line)(void *data, const char *line); void *exec_data; diff --git a/libs/client/cl_screen.c b/libs/client/cl_screen.c index adb48f2f8..4ae6e5296 100644 --- a/libs/client/cl_screen.c +++ b/libs/client/cl_screen.c @@ -45,6 +45,7 @@ #include "QF/screen.h" #include "QF/plugin/console.h" +#include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" #include "QF/scene/scene.h" @@ -146,10 +147,10 @@ scr_draw_views (void) if (!_vs->intermission) { r_funcs->Draw_Crosshair ();//FIXME canvas_func } + Con_DrawConsole (); Canvas_Draw (cl_canvas_sys); SCR_CShift ();//FIXME canvas_func Sbar_DrawCenterPrint ();//FIXME canvas_func - Con_DrawConsole ();//FIXME canvas_func } static SCR_Func scr_funcs[] = { @@ -194,6 +195,12 @@ CL_Init_Screen (void) __auto_type reg = ECS_NewRegistry (); Canvas_InitSys (&cl_canvas_sys, reg); + if (con_module) { + __auto_type cd = con_module->data->console; + cd->component_base = ECS_RegisterComponents (reg, cd->components, + cd->num_components); + cd->canvas_sys = &cl_canvas_sys; + } HUD_Init (reg); ECS_CreateComponentPools (reg); diff --git a/libs/console/client.c b/libs/console/client.c index b2e39ee51..b2268be98 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -57,14 +57,12 @@ #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/canvas.h" #include "QF/ui/inputline.h" #include "QF/ui/view.h" #include "compat.h" -static general_data_t plugin_info_general_data; -console_data_t con_data; - static con_buffer_t *con; static float con_cursorspeed = 4; @@ -152,8 +150,8 @@ static cvar_t cl_conmode_cvar = { .value = { .type = &cl_conmode_type, .value = &con_data.exec_line }, }; -static ecs_registry_t *client_reg; static uint32_t client_base; +static uint32_t canvas_base; static uint32_t view_base; static con_state_t con_state; @@ -170,40 +168,37 @@ typedef struct { } con_input_t; enum { - client_href, client_input, - client_charbuff, client_cursor, client_comp_count }; static const component_t client_components[client_comp_count] = { - [client_href] = { - .size = sizeof (hierref_t), - .name = "href", - }, [client_input] = { .size = sizeof (con_input_t *), .name = "input", }, - [client_charbuff] = { - .size = sizeof (draw_charbuffer_t *), - .name = "charbuff", - }, [client_cursor] = { .size = sizeof (con_input_t *), .name = "cursor", }, }; +console_data_t con_data = { + .components = client_components, + .num_components = client_comp_count, +}; + #define MAXCMDLINE 256 +static qpic_t *conback; static con_input_t cmd_line; static con_input_t say_line; static inputline_t *chat_input; static inputline_t *team_input; +static uint32_t screen_canvas; static view_t screen_view; static view_t console_view; static view_t buffer_view; @@ -247,12 +242,84 @@ con_setcomponent (view_t view, uint32_t comp, void *data) return Ent_SetComponent (view.id, comp, view.reg, data); } +static void +con_setfunc (view_t view, uint32_t comp, canvas_update_f func) +{ + con_setcomponent (view, canvas_base + comp, &func); +} + +static void +con_setinput (view_t view, con_input_t *input) +{ + con_setcomponent (view, client_base + client_input, &input); +} + +static con_input_t * +con_getinput (view_t view) +{ + return *(con_input_t**)con_getcomponent (view, client_base + client_input); +} + +static int +con_hasinput (view_t view) +{ + return con_hascomponent (view, client_base + client_input); +} + +static void +con_setfitpic (view_t view, qpic_t *pic) +{ + con_setcomponent (view, canvas_base + canvas_fitpic, &pic); +} + +static void +con_setcharbuf (view_t view, draw_charbuffer_t *buffer) +{ + con_setcomponent (view, canvas_base + canvas_charbuff, &buffer); +} + +static void +con_setcursor (view_t view, con_input_t *input) +{ + con_setcomponent (view, client_base + client_cursor, &input); +} + static inline void con_remcomponent (view_t view, uint32_t comp) { Ent_RemoveComponent (view.id, comp, view.reg); } +static void +con_remfunc (view_t view, uint32_t comp) +{ + con_remcomponent (view, canvas_base + comp); +} + +static inline void +con_remcharbuf (view_t view) +{ + con_remcomponent (view, canvas_base + canvas_charbuff); +} + +static inline void +con_remcursor (view_t view) +{ + con_remcomponent (view, client_base + client_cursor); +} + +static void +load_conback (const char *path) +{ + qpic_t *p; + if (strlen (path) < 4 || strcmp (path + strlen (path) - 4, ".lmp") + || !(p = (qpic_t *) QFS_LoadFile (QFS_FOpenFile (path), 0))) { + return; + } + conback = r_funcs->Draw_MakePic (p->width, p->height, p->data); + free (p); +} + static void ClearNotify (void) { @@ -495,10 +562,10 @@ input_line_draw (inputline_t *il) static void resize_input (view_t view, view_pos_t len) { - if (!con_hascomponent (view, client_input)) { + if (!con_hasinput (view)) { return; } - __auto_type inp = *(con_input_t **) con_getcomponent (view, client_input); + __auto_type inp = con_getinput (view); if (inp->buffer) { Draw_DestroyBuffer (inp->buffer); @@ -578,7 +645,7 @@ resize_console_text (view_t view, view_pos_t len) con_linewidth = width; Draw_DestroyBuffer (console_buffer); console_buffer = Draw_CreateBuffer (width, height); - con_setcomponent (buffer_view, client_charbuff, &console_buffer); + con_setcharbuf (buffer_view, console_buffer); clear_console_text (); } } @@ -607,45 +674,20 @@ draw_con_scrollback (void) } static void -draw_cursor (void) +draw_cursor (view_t view) { - if (!con_data.realtime) { - return; - } - float t = *con_data.realtime * con_cursorspeed; int ch = 10 + ((int) (t) & 1); - ecs_pool_t *pool = &client_reg->comp_pools[client_cursor]; - con_input_t **inp = pool->data; - uint32_t *id = pool->dense; - - for (uint32_t i = pool->count; i-- > 0; ) { - __auto_type buff = (*inp)->buffer; - __auto_type il = (*inp++)->input_line; - view_t v = { .reg = client_reg, .id = *id++, - .comp = screen_view.comp }; - if (!il->cursor) { - continue; - } - view_pos_t pos = View_GetAbs (v); - int x = (buff->cursx + il->linepos - il->scroll) * 8; - r_funcs->Draw_Character (pos.x + x, pos.y, ch); - } -} - -static void -draw_buffer (void) -{ - ecs_pool_t *pool = &client_reg->comp_pools[client_charbuff]; - draw_charbuffer_t **buffer = pool->data; - uint32_t *id = pool->dense; - for (uint32_t i = pool->count; i-- > 0; ) { - view_t v = { .reg = client_reg, .id = *id++, - .comp = screen_view.comp }; - view_pos_t pos = View_GetAbs (v); - Draw_CharBuffer (pos.x, pos.y, *buffer++); + __auto_type inp = con_getinput (view); + __auto_type buff = inp->buffer; + __auto_type il = inp->input_line; + if (!il->cursor) { + return; } + view_pos_t pos = View_GetAbs (view); + int x = (buff->cursx + il->linepos - il->scroll) * 8; + r_funcs->Draw_Character (pos.x + x, pos.y, ch); } static void @@ -662,36 +704,12 @@ update_notify (void) } } -static void -draw_console (view_t view) -{ - byte alpha; - view_pos_t len = View_GetLen (screen_view); - - if (con_data.lines > 0) { - // draw the background - if (con_state == con_fullscreen) { - alpha = 255; - } else { - float y = len.y * con_size; - alpha = 255 * con_alpha * len.y / y; - alpha = min (alpha, 255); - } - r_funcs->Draw_ConsoleBackground (con_data.lines, alpha); - } - - update_notify (); - // draw everything else - draw_buffer (); - draw_cursor (); -} - static void resize_notify (view_t view, view_pos_t len) { Draw_DestroyBuffer (notify_buffer); notify_buffer = Draw_CreateBuffer (len.x / 8, NOTIFY_LINES + 1); - con_setcomponent (notify_view, client_charbuff, ¬ify_buffer); + con_setcharbuf (notify_view, notify_buffer); ClearNotify (); } @@ -759,35 +777,39 @@ C_DrawConsole (void) return; } - if (con_state == con_message) { - con_setcomponent (say_view, client_charbuff, &say_line.buffer); - con_input_t *inp = &say_line; - con_setcomponent (say_view, client_cursor, &inp); + if (!con_data.lines && con_state == con_message) { + con_setcharbuf (say_view, say_line.buffer); + con_setcursor (say_view, &say_line); + con_setfunc (say_view, canvas_lateupdate, draw_cursor); } else { - con_remcomponent (say_view, client_charbuff); - con_remcomponent (say_view, client_cursor); + con_remcharbuf (say_view); + con_remcursor (say_view); + con_remfunc (say_view, canvas_lateupdate); } if (con_data.lines) { - con_setcomponent (command_view, client_charbuff, &cmd_line.buffer); - con_input_t *inp = &cmd_line; - con_setcomponent (command_view, client_cursor, &inp); + con_remcharbuf (notify_view); + con_setcharbuf (command_view, cmd_line.buffer); + con_setcursor (command_view, &cmd_line); + con_setfunc (command_view, canvas_lateupdate, draw_cursor); } else { - con_remcomponent (command_view, client_charbuff); - con_remcomponent (command_view, client_cursor); + con_setcharbuf (notify_view, notify_buffer); + con_remcharbuf (command_view); + con_remcursor (command_view); + con_remfunc (command_view, canvas_lateupdate); } if (con_data.dl_name && *con_data.dl_name->str) { if (!download_buffer) { view_pos_t len = View_GetLen (download_view); download_buffer = Draw_CreateBuffer (len.x / 8, 1); - con_setcomponent (download_view, client_charbuff, &download_buffer); + con_setcharbuf (download_view, download_buffer); } update_download (); } else if (download_buffer) { Draw_DestroyBuffer (download_buffer); - con_remcomponent (download_view, client_charbuff); + con_remcharbuf (download_view); } - draw_console (screen_view); + update_notify (); } static void @@ -1015,13 +1037,9 @@ C_InitCvars (void) static void C_Init (void) { - client_reg = ECS_NewRegistry (); - client_base = ECS_RegisterComponents (client_reg, client_components, - client_comp_count); - view_base = ECS_RegisterComponents (client_reg, view_components, - view_comp_count); - ECS_CreateComponentPools (client_reg); - + client_base = con_data.component_base; + canvas_base = con_data.canvas_sys->base; + view_base = con_data.canvas_sys->view_base; #ifdef __QNXNTO__ setlocale (LC_ALL, "C-TRADITIONAL"); #endif @@ -1033,8 +1051,9 @@ C_Init (void) con_debuglog = COM_CheckParm ("-condebug"); // The console will get resized, so assume initial size is 320x200 - ecs_system_t sys = { client_reg, view_base }; - screen_view = View_New (sys, nullview); + ecs_system_t sys = { con_data.canvas_sys->reg, view_base }; + screen_canvas = Canvas_New (*con_data.canvas_sys); + screen_view = Canvas_GetRootView (*con_data.canvas_sys, screen_canvas); console_view = View_New (sys, screen_view); buffer_view = View_New (sys, console_view); command_view = View_New (sys, console_view); @@ -1043,6 +1062,15 @@ C_Init (void) say_view = View_New (sys, screen_view); menu_view = View_New (sys, screen_view); + View_SetVisible (screen_view, 1); + View_SetVisible (console_view, 1); + View_SetVisible (buffer_view, 1); + View_SetVisible (command_view, 1); + View_SetVisible (download_view, 1); + View_SetVisible (notify_view, 1); + View_SetVisible (say_view, 1); + View_SetVisible (menu_view, 1); + View_SetGravity (screen_view, grav_northwest); View_SetGravity (console_view, grav_northwest); View_SetGravity (buffer_view, grav_southwest); @@ -1078,6 +1106,11 @@ C_Init (void) View_SetLen (say_view, 320, 8); View_SetLen (menu_view, 320, 200); + load_conback ("gfx/conback.lmp"); + if (conback) { + con_setfitpic (console_view, conback); + } + cmd_line.prompt = ""; cmd_line.input_line = Con_CreateInputLine (32, MAXCMDLINE, ']'); cmd_line.input_line->complete = Con_BasicCompleteCommandLine; @@ -1101,14 +1134,8 @@ C_Init (void) team_input->user_data = &say_line; team_input->draw = input_line_draw; - { - con_input_t *inp = &say_line; - con_setcomponent (say_view, client_input, &inp); - } - { - con_input_t *inp = &cmd_line; - con_setcomponent (command_view, client_input, &inp); - } + con_setinput (say_view, &say_line); + con_setinput (command_view, &cmd_line); view_pos_t len; @@ -1116,18 +1143,17 @@ C_Init (void) len = View_GetLen (buffer_view); console_buffer = Draw_CreateBuffer (len.x / 8, len.y / 8); Draw_ClearBuffer (console_buffer); - con_setcomponent (buffer_view, client_charbuff, &console_buffer); + con_setcharbuf (buffer_view, console_buffer); con_main = Con_CreateBuffer (CON_BUFFER_SIZE, CON_LINES); len = View_GetLen (command_view); cmd_line.buffer = Draw_CreateBuffer (len.x / 8, len.y / 8); Draw_ClearBuffer (cmd_line.buffer); - con_setcomponent (command_view, client_charbuff, &cmd_line.buffer); + con_setcharbuf (command_view, cmd_line.buffer); len = View_GetLen (notify_view); notify_buffer = Draw_CreateBuffer (len.x / 8, NOTIFY_LINES + 1); Draw_ClearBuffer (notify_buffer); - con_setcomponent (notify_view, client_charbuff, ¬ify_buffer); len = View_GetLen (say_view); say_line.buffer = Draw_CreateBuffer (len.x / 8, len.y / 8); @@ -1170,6 +1196,8 @@ C_shutdown (void) IE_Remove_Handler (con_event_id); } +static general_data_t plugin_info_general_data; + static general_funcs_t plugin_info_general_funcs = { .init = C_InitCvars, .shutdown = C_shutdown, diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 1a4da10be..49b87abe8 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -56,6 +56,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/plugin/console.h" #include "QF/plugin/vid_render.h" +#include "QF/ui/canvas.h" #include "QF/ui/font.h" #include "QF/ui/text.h" @@ -84,6 +85,7 @@ quit_f (void) static progs_t *bi_rprogs; static pr_func_t qc2d; static int event_handler_id; +static canvas_system_t canvas_sys; static void bi_2d (void) @@ -94,7 +96,7 @@ bi_2d (void) static SCR_Func bi_2dfuncs[] = { bi_2d, - Con_DrawConsole, +// Con_DrawConsole, 0, }; @@ -355,13 +357,19 @@ BI_Graphics_Init (progs_t *pr) IE_Set_Focus (event_handler_id); Con_Load ("client"); + __auto_type reg = ECS_NewRegistry (); + Canvas_InitSys (&canvas_sys, reg); if (con_module) { - con_module->data->console->realtime = &con_realtime; - con_module->data->console->frametime = &con_frametime; - con_module->data->console->quit = quit_f; - con_module->data->console->cbuf = qwaq_cbuf; - //con_module->data->console->screen_view = r_data->scr_view; + __auto_type cd = con_module->data->console; + cd->realtime = &con_realtime; + cd->frametime = &con_frametime; + cd->quit = quit_f; + cd->cbuf = qwaq_cbuf; + cd->component_base = ECS_RegisterComponents (reg, cd->components, + cd->num_components); + cd->canvas_sys = &canvas_sys; } + ECS_CreateComponentPools (reg); //Key_SetKeyDest (key_game); Con_Init (); From 99d32d5e54fe77fc27a563bfa97f15b2f4c34517 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 29 Jan 2023 11:38:04 +0900 Subject: [PATCH 3367/3664] [client] Add a comment on light attenuation Saves me having to look in the shader every time. --- libs/client/cl_light.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index 8aaba5526..f1466f3c2 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -216,6 +216,12 @@ parse_light (light_t *light, int *style, const plitem_t *entity, } } + // The light's intensity is calculated as + // I = (1 - a.w * r.y) / dot (a, r) + // where a is attenuation and r = vec4 (d*d, d, 1, 0) + // thus giving linear falloff for a = vec4 (0, 0, 1, 1/maxdist) + // and 1/(A*d*d + B*d + C) for a = vec4 (A, B, C, 0) + // Other factors contribute to the final intensity (cone angle etc) vec4f_t attenuation = { // inverse square 1, 0, 0, 0, From e974e9d7582ceedcbd64bb5dfd6dda939c320042 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Feb 2023 16:08:53 +0900 Subject: [PATCH 3368/3664] [qfcc] Add some failing typedef redef tests typeredef1 parses properly but fails due to it erroneously complaining that foo is redeclared as a different kind of object (it's the same kind). typeredef2 is the real problem in that it's a syntax error when it should not be. This has proven to be a show-stopper for development on my laptop as it has very recent vulkan headers which have such a duplicate typedef. --- tools/qfcc/test/Makemodule.am | 14 ++++++++++++++ tools/qfcc/test/build-compile-pass-run | 15 +++++++++++++++ tools/qfcc/test/typeredef1.r | 2 ++ tools/qfcc/test/typeredef2.r | 2 ++ 4 files changed, 33 insertions(+) create mode 100755 tools/qfcc/test/build-compile-pass-run create mode 100644 tools/qfcc/test/typeredef1.r create mode 100644 tools/qfcc/test/typeredef2.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 1489bd241..0d4fa5c2a 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -72,6 +72,10 @@ test_progs_dat=\ fail_progs_dat= +test_build_passes=\ + tools/qfcc/test/typeredef1.r \ + tools/qfcc/test/typeredef2.r + test_build_errors=\ tools/qfcc/test/classarray.r \ tools/qfcc/test/dealloc-warn.r \ @@ -96,6 +100,7 @@ test_defspace_src=\ TESTS += \ $(test_bins) \ $(test_progs_dat:.dat=.run) \ + $(test_build_passes:.r=.run) \ $(test_build_errors:.r=.run) XFAIL_TESTS += \ $(fail_bins) \ @@ -118,6 +123,7 @@ tools_qfcc_test_test_harness_LDADD= $(QFCC_TEST_LIBS) tools_qfcc_test_test_harness_DEPENDENCIES= $(QFCC_TEST_DEPS) qfcc_test_run_deps = Makefile tools/qfcc/test/build-run +qfcc_comp_run_deps = Makefile tools/qfcc/test/build-compile-pass-run qfcc_fail_run_deps = Makefile tools/qfcc/test/build-compile-fail-run tools_qfcc_test_address_cast_dat_SOURCES=tools/qfcc/test/address-cast.r address_cast_obj=$(tools_qfcc_test_address_cast_dat_SOURCES:.r=.o) @@ -301,6 +307,12 @@ tools/qfcc/test/double-int-compare.run$(EXEEXT): tools/qfcc/test/double-int-comp tools/qfcc/test/double-float-compare.run$(EXEEXT): tools/qfcc/test/double-float-compare.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< +tools/qfcc/test/typeredef1.run$(EXEEXT): tools/qfcc/test/typeredef1.r $(qfcc_comp_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-pass-run $@ $(QFCC) $(QCFLAGS) $< + +tools/qfcc/test/typeredef2.run$(EXEEXT): tools/qfcc/test/typeredef2.r $(qfcc_comp_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-pass-run $@ $(QFCC) $(QCFLAGS) $< + tools_qfcc_test_enum_dat_SOURCES=tools/qfcc/test/enum.r enum_obj=$(tools_qfcc_test_enum_dat_SOURCES:.r=.o) enum_dep=$(call qcautodep,$(tools_qfcc_test_enum_dat_SOURCES)) @@ -773,6 +785,8 @@ r_depfiles_remade += $(zerolinker_dep) EXTRA_DIST += \ $(test_build_errors) \ + $(test_build_passes) \ + tools/qfcc/test/build-compile-pass-run \ tools/qfcc/test/build-compile-fail-run \ tools/qfcc/test/test-bi.h \ tools/qfcc/test/build-run \ diff --git a/tools/qfcc/test/build-compile-pass-run b/tools/qfcc/test/build-compile-pass-run new file mode 100755 index 000000000..dbb81ba7f --- /dev/null +++ b/tools/qfcc/test/build-compile-pass-run @@ -0,0 +1,15 @@ +#! /bin/sh + +script=$1 +shift + +cat > $script < Date: Sat, 4 Feb 2023 16:44:48 +0900 Subject: [PATCH 3369/3664] [qfcc] Allow redefined typedefs if the same type This fixes typeredef1, and will allow typeredef2 to pass once the grammar is sorted out. --- tools/qfcc/source/qc-parse.y | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index e23f231f8..4939f7c90 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -399,7 +399,14 @@ use_type_name (specifier_t spec) spec.sym = new_symbol (spec.sym->name); spec.sym->type = spec.type; spec.sym->sy_type = sy_var; - symtab_addsymbol (current_symtab, spec.sym); + symbol_t *s = symtab_addsymbol (current_symtab, spec.sym); + // a different symbol being returned means that this is a redefinition + // of that symbol in the same scope. However, typedefs to the same type + // are allowed. + if (s != spec.sym && spec.is_typedef && s->sy_type == sy_type + && type_same (s->type, spec.type)) { + spec.sym = s; + } return !!spec.sym->table; } @@ -420,7 +427,8 @@ check_specifiers (specifier_t spec) bug (0, "wha? %p %p", spec.type, spec.sym); } else { // a type name (id, typedef, etc) was used as a variable name. - // this is allowed in C, so long as it's in a different scope + // this is allowed in C, so long as it's in a different scope, + // or the types are the same if (!use_type_name (spec)) { error (0, "%s redeclared as different kind of symbol", spec.sym->name); From 35f4f2e6923c20ac2089b00a5220218741f72424 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Feb 2023 18:26:54 +0900 Subject: [PATCH 3370/3664] [qfcc] Move basic specifier creation into qc-lex This simplifies type type_specifier rule significantly as now TYPE_SPEC (was TYPE) includes all types and their basic modifiers (long, short, signed, unsigned). This should allow me to make the type system closer to gcc's (as of 3.4 as that seems to be the last version that used a bison parser) and thus fix typeredef2. --- tools/qfcc/source/qc-lex.l | 88 ++++++++++++++++++++---------------- tools/qfcc/source/qc-parse.y | 46 ++++--------------- 2 files changed, 58 insertions(+), 76 deletions(-) diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 5e50ef5d5..99b3b3842 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -340,13 +340,14 @@ yywrap (void) typedef struct { const char *name; int value; - type_t *type; + specifier_t spec; } keyword_t; // These keywords are part of the Ruamoko language and require the QuakeForge // Ruamoko VM. static keyword_t rua_keywords[] = { -#define VEC_TYPE(type_name, base_type) { #type_name, TYPE, &type_##type_name }, +#define VEC_TYPE(type_name, base_type) \ + { #type_name, TYPE_SPEC, .spec = { .type = &type_##type_name } }, #include "tools/qfcc/include/vec_types.h" }; @@ -356,12 +357,12 @@ static keyword_t rua_keywords[] = { // If not compiling for the QuakeForge VM, or if Ruamoko has been disabled, // then they will be unavailable as keywords. static keyword_t obj_keywords[] = { - {"id", OBJECT, &type_id }, - {"Class", TYPE, &type_Class }, - {"Method", TYPE, &type_method }, - {"Super", TYPE, &type_super }, - {"SEL", TYPE, &type_SEL }, - {"IMP", TYPE, &type_IMP }, + {"id", OBJECT, .spec = { .type = &type_id } }, + {"Class", TYPE_SPEC, .spec = { .type = &type_Class } }, + {"Method", TYPE_SPEC, .spec = { .type = &type_method } }, + {"Super", TYPE_SPEC, .spec = { .type = &type_super } }, + {"SEL", TYPE_SPEC, .spec = { .type = &type_SEL } }, + {"IMP", TYPE_SPEC, .spec = { .type = &type_IMP } }, {"@class", CLASS }, {"@defs", DEFS }, @@ -412,42 +413,42 @@ static keyword_t at_keywords[] = { // These keywords require the QuakeForge VM to be of any use. ie, they cannot // be supported (sanely) by v6 progs. static keyword_t qf_keywords[] = { - {"quaternion", TYPE, &type_quaternion}, - {"double", TYPE, &type_double}, - {"int", TYPE, &type_int }, - {"unsigned", UNSIGNED, 0 }, - {"signed", SIGNED, 0 }, - {"long", LONG, 0 }, - {"short", SHORT, 0 }, + {"quaternion", TYPE_SPEC, .spec = { .type = &type_quaternion } }, + {"double", TYPE_SPEC, .spec = { .type = &type_double } }, + {"int", TYPE_SPEC, .spec = { .type = &type_int } }, + {"unsigned", TYPE_SPEC, .spec = { .is_unsigned = 1 } }, + {"signed", TYPE_SPEC, .spec = { .is_signed = 1 } }, + {"long", TYPE_SPEC, .spec = { .is_long = 1 } }, + {"short", TYPE_SPEC, .spec = { .is_short = 1 } }, - {"@function", TYPE, &type_func }, - {"@args", ARGS, 0 }, - {"@va_list", TYPE, &type_va_list }, - {"@param", TYPE, &type_param }, - {"@return", AT_RETURN, 0 }, + {"@function", TYPE_SPEC, .spec = { .type = &type_func } }, + {"@args", ARGS, }, + {"@va_list", TYPE_SPEC, .spec = { .type = &type_va_list } }, + {"@param", TYPE_SPEC, .spec = { .type = &type_param } }, + {"@return", AT_RETURN, }, - {"@cross", CROSS, 0 }, - {"@dot", DOT, 0 }, - {"@hadamard", HADAMARD, 0 }, + {"@cross", CROSS, }, + {"@dot", DOT, }, + {"@hadamard", HADAMARD, }, }; // These keywors are always available. Other than the @ keywords, they // form traditional QuakeC. static keyword_t keywords[] = { - {"void", TYPE, &type_void }, - {"float", TYPE, &type_float }, - {"string", TYPE, &type_string}, - {"vector", TYPE, &type_vector}, - {"entity", TYPE, &type_entity}, - {"local", LOCAL, 0 }, - {"return", RETURN, 0 }, - {"while", WHILE, 0 }, - {"do", DO, 0 }, - {"if", IF, 0 }, - {"else", ELSE, 0 }, - {"@system", SYSTEM, 0 }, - {"@overload", OVERLOAD, 0 }, - {"@attribute", ATTRIBUTE, 0 }, + {"void", TYPE_SPEC, .spec = { .type = &type_void } }, + {"float", TYPE_SPEC, .spec = { .type = &type_float } }, + {"string", TYPE_SPEC, .spec = { .type = &type_string } }, + {"vector", TYPE_SPEC, .spec = { .type = &type_vector } }, + {"entity", TYPE_SPEC, .spec = { .type = &type_entity } }, + {"local", LOCAL, }, + {"return", RETURN, }, + {"while", WHILE, }, + {"do", DO, }, + {"if", IF, }, + {"else", ELSE, }, + {"@system", SYSTEM, }, + {"@overload", OVERLOAD, }, + {"@attribute", ATTRIBUTE, }, }; static const char * @@ -474,12 +475,16 @@ process_keyword (keyword_t *keyword, const char *token) return OBJECT; } else if (sym->sy_type == sy_type) { // id has been redeclared via a typedef + qc_yylval.spec = (specifier_t) { + .type = sym->type, + .sym = sym, + }; return TYPE_NAME; } // id has been redelcared as a variable (hopefully) return NAME; } else { - qc_yylval.type = keyword->type; + qc_yylval.spec = keyword->spec; } return keyword->value; } @@ -550,8 +555,13 @@ keyword_or_id (const char *token) if (!sym) sym = new_symbol (token); qc_yylval.symbol = sym; - if (sym->sy_type == sy_type) + if (sym->sy_type == sy_type) { + qc_yylval.spec = (specifier_t) { + .type = sym->type, + .sym = sym, + }; return TYPE_NAME; + } if (sym->sy_type == sy_class) return CLASS_NAME; return NAME; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 4939f7c90..beecbaae2 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -153,10 +153,9 @@ int yylex (void); %token RETURN AT_RETURN ELLIPSIS %token NIL GOTO SWITCH CASE DEFAULT ENUM %token ARGS TYPEDEF EXTERN STATIC SYSTEM OVERLOAD NOT ATTRIBUTE -%token UNSIGNED SIGNED LONG SHORT %token STRUCT -%token TYPE -%token OBJECT TYPE_NAME +%token TYPE_SPEC TYPE_NAME +%token OBJECT %token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE %token PROTECTED PROTOCOL PUBLIC SELECTOR REFERENCE SELF THIS @@ -700,37 +699,10 @@ type_specifier_or_storage_class ; type_specifier - : TYPE - { - $$ = make_spec ($1, 0, 0, 0); - } - | UNSIGNED - { - $$ = make_spec (0, current_storage, 0, 0); - $$.is_unsigned = 1; - } - | SIGNED - { - $$ = make_spec (0, current_storage, 0, 0); - $$.is_signed = 1; - } - | LONG - { - $$ = make_spec (0, current_storage, 0, 0); - $$.is_long = 1; - } - | SHORT - { - $$ = make_spec (0, current_storage, 0, 0); - $$.is_short = 1; - } + : TYPE_SPEC | enum_specifier | struct_specifier | TYPE_NAME - { - $$ = make_spec ($1->type, 0, 0, 0); - $$.sym = $1; - } | OBJECT protocolrefs { if ($2) { @@ -1023,9 +995,9 @@ function_params qc_func_params : '(' ')' { $$ = 0; } | '(' ps qc_var_list ')' { $$ = check_params ($3); } - | '(' ps TYPE ')' + | '(' ps TYPE_SPEC ')' { - if (!is_void ($3)) + if (!is_void ($3.type)) PARSE_ERROR; $$ = 0; } @@ -1631,7 +1603,7 @@ unary_expr ident_expr : OBJECT { $$ = new_symbol_expr ($1); } | CLASS_NAME { $$ = new_symbol_expr ($1); } - | TYPE_NAME { $$ = new_symbol_expr ($1); } + | TYPE_NAME { $$ = new_symbol_expr ($1.sym); } ; vector_expr @@ -1742,7 +1714,7 @@ identifier : NAME | OBJECT | CLASS_NAME - | TYPE_NAME + | TYPE_NAME { $$ = $1.sym; } ; // Objective-QC stuff @@ -2241,8 +2213,8 @@ selector : NAME { $$ = $1; } | CLASS_NAME { $$ = $1; } | OBJECT { $$ = new_symbol (qc_yytext); } - | TYPE { $$ = new_symbol (qc_yytext); } - | TYPE_NAME { $$ = $1; } + | TYPE_SPEC { $$ = new_symbol (qc_yytext); } + | TYPE_NAME { $$ = $1.sym; } | reserved_word ; From 02432311c5ff093e05cbc18f6e5495c030b6be68 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Feb 2023 20:19:52 +0900 Subject: [PATCH 3371/3664] [qfcc] Add a function to print the source line It's not used anywhere, but it saves me a lot of grief when debugging. --- tools/qfcc/include/diagnostic.h | 2 ++ tools/qfcc/source/diagnostic.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/tools/qfcc/include/diagnostic.h b/tools/qfcc/include/diagnostic.h index 8adec809c..526745f56 100644 --- a/tools/qfcc/include/diagnostic.h +++ b/tools/qfcc/include/diagnostic.h @@ -71,6 +71,8 @@ void _bug (struct expr_s *e, const char *file, int line, const char *fmt, ...) __attribute__ ((format (PRINTF, 4, 5))); #define bug(e, fmt...) _bug(e, __FILE__, __LINE__, fmt) +void print_srcline (int rep, const struct expr_s *e); + ///@} #endif//__diagnostic_h diff --git a/tools/qfcc/source/diagnostic.c b/tools/qfcc/source/diagnostic.c index 6410fae1e..1c5d6451a 100644 --- a/tools/qfcc/source/diagnostic.c +++ b/tools/qfcc/source/diagnostic.c @@ -77,6 +77,21 @@ report_function (const expr_t *e) last_func = current_func; } +void +print_srcline (int rep, const expr_t *e) +{ + pr_string_t file = pr.source_file; + int line = pr.source_line; + if (e) { + file = e->file; + line = e->line; + } + if (rep) { + report_function (e); + } + printf ("%s:%d\n", GETSTR (file), line); +} + static __attribute__((format(PRINTF, 4, 0))) void format_message (dstring_t *message, const char *msg_type, const expr_t *e, const char *fmt, va_list args) From fc7c96d20887ceb0017cd76d7c3217f18dfcb6ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Feb 2023 11:18:42 +0900 Subject: [PATCH 3372/3664] [qfcc] Support C's full type system Along with QuakeC's, of course. This fixes type typeredef2 test (a lot of work for one little syntax error). Unfortunately, it came at the cost of requiring `>>` in front of state expressions on C-style functions (QuakeC-style functions are unaffected). Also, there are now two shift/reduce conflicts with structs and unions (but these same conflicts are in gcc 3.4). This has highlighted the need for having the equivalent of the expression tree for the declaration system as there are now several hacks to deal with the separation of types and declarators. But that's a job for another week. The grammar constructs for declarations come from gcc 3.4's parser (I think it's the last version of gcc that used bison. Also, 3.4 is still GPL 2, so no chance of an issue there). --- tools/qfcc/include/function.h | 2 +- tools/qfcc/include/struct.h | 2 + tools/qfcc/include/symtab.h | 4 + tools/qfcc/include/type.h | 7 +- tools/qfcc/source/function.c | 10 +- tools/qfcc/source/qc-lex.l | 10 +- tools/qfcc/source/qc-parse.y | 1509 ++++++++++++++++----------------- tools/qfcc/source/struct.c | 27 + tools/qfcc/source/symtab.c | 54 ++ tools/qfcc/source/type.c | 76 ++ tools/qfcc/test/state.r | 6 +- 11 files changed, 920 insertions(+), 787 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 5871945e4..aeb70f1b0 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -148,7 +148,7 @@ param_t *param_append_identifiers (param_t *params, struct symbol_s *idents, param_t *reverse_params (param_t *params); param_t *append_params (param_t *params, param_t *more_params); param_t *copy_params (param_t *params); -struct type_s *parse_params (struct type_s *type, param_t *params); +struct type_s *parse_params (struct type_s *return_type, param_t *params); param_t *check_params (param_t *params); enum storage_class_e; diff --git a/tools/qfcc/include/struct.h b/tools/qfcc/include/struct.h index 54cf1b045..e55a75aee 100644 --- a/tools/qfcc/include/struct.h +++ b/tools/qfcc/include/struct.h @@ -43,6 +43,8 @@ typedef struct { void (*emit) (struct def_s *def, void *data, int index); } struct_def_t; +struct symtab_s *start_struct (int *su, struct symbol_s *tag, + struct symtab_s *parent); struct symbol_s *find_struct (int su, struct symbol_s *tag, struct type_s *type); struct symbol_s *build_struct (int su, struct symbol_s *tag, diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index 7a6904f1a..125f77203 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -244,6 +244,10 @@ symtab_t *symtab_flat_copy (symtab_t *symtab, symtab_t *parent); symbol_t *make_symbol (const char *name, struct type_s *type, struct defspace_s *space, enum storage_class_e storage); +struct specifier_s; +symbol_t *declare_symbol (struct specifier_s spec, struct expr_s *init, + symtab_t *symtab); + ///@} #endif//__symtab_h diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 6dde9d55b..bf68f8ad4 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -90,10 +90,10 @@ typedef struct type_s { struct def_s *type_def; ///< offset of qfo encodoing } type_t; -typedef struct { +typedef struct specifier_s { type_t *type; struct param_s *params; - struct symbol_s *sym; ///< for dealing with "int id" etc + struct symbol_s *sym; storage_class_t storage; union { struct { @@ -105,6 +105,7 @@ typedef struct { unsigned is_long:1; unsigned is_typedef:1; unsigned is_overload:1; + unsigned is_function:1;//FIXME do proper void(*)() -> ev_func unsigned nosave:1; unsigned no_va_list:1; unsigned void_return:1; @@ -156,6 +157,8 @@ void chain_type (type_t *type); level. */ type_t *append_type (type_t *type, type_t *new); +void set_func_type_attrs (type_t *func, specifier_t spec); +specifier_t default_type (specifier_t spec, struct symbol_s *sym); type_t *find_type (type_t *new); void new_typedef (const char *name, type_t *type); type_t *field_type (type_t *aux); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index d8642d588..7e89d8fd4 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -100,7 +100,7 @@ new_param (const char *selector, type_t *type, const char *name) ALLOC (4096, param_t, params, param); param->next = 0; param->selector = selector; - param->type = type; + param->type = find_type (type); param->name = name; return param; @@ -173,23 +173,23 @@ copy_params (param_t *params) } type_t * -parse_params (type_t *type, param_t *parms) +parse_params (type_t *return_type, param_t *parms) { param_t *p; type_t *new; type_t *ptype; int count = 0; - if (type && is_class (type)) { + if (return_type && is_class (return_type)) { error (0, "cannot return an object (forgot *?)"); - type = &type_id; + return_type = &type_id; } new = new_type (); new->type = ev_func; new->alignment = 1; new->width = 1; - new->t.func.type = type; + new->t.func.type = return_type; new->t.func.num_params = 0; for (p = parms; p; p = p->next) { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 99b3b3842..20317e960 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -357,7 +357,7 @@ static keyword_t rua_keywords[] = { // If not compiling for the QuakeForge VM, or if Ruamoko has been disabled, // then they will be unavailable as keywords. static keyword_t obj_keywords[] = { - {"id", OBJECT, .spec = { .type = &type_id } }, + {"id", OBJECT_NAME, .spec = { .type = &type_id } }, {"Class", TYPE_SPEC, .spec = { .type = &type_Class } }, {"Method", TYPE_SPEC, .spec = { .type = &type_method } }, {"Super", TYPE_SPEC, .spec = { .type = &type_super } }, @@ -462,7 +462,7 @@ process_keyword (keyword_t *keyword, const char *token) { if (keyword->value == STRUCT) { qc_yylval.op = token[0]; - } else if (keyword->value == OBJECT) { + } else if (keyword->value == OBJECT_NAME) { symbol_t *sym; sym = symtab_lookup (current_symtab, token); @@ -472,7 +472,11 @@ process_keyword (keyword_t *keyword, const char *token) // be redefinable when in an enclosing scope. if (sym->sy_type == sy_name) { // this is the global id (object) - return OBJECT; + qc_yylval.spec = (specifier_t) { + .type = sym->type, + .sym = sym, + }; + return OBJECT_NAME; } else if (sym->sy_type == sy_type) { // id has been redeclared via a typedef qc_yylval.spec = (specifier_t) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index beecbaae2..31191a8e8 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -154,55 +154,55 @@ int yylex (void); %token NIL GOTO SWITCH CASE DEFAULT ENUM %token ARGS TYPEDEF EXTERN STATIC SYSTEM OVERLOAD NOT ATTRIBUTE %token STRUCT -%token TYPE_SPEC TYPE_NAME -%token OBJECT +%token TYPE_SPEC TYPE_NAME TYPE_QUAL +%token OBJECT_NAME %token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE %token PROTECTED PROTOCOL PUBLIC SELECTOR REFERENCE SELF THIS -%type optional_specifiers specifiers local_specifiers -%type storage_class save_storage set_spec_storage -%type type_specifier type_specifier_or_storage_class -%type type +%type storage_class save_storage +%type typespec typespec_reserved typespec_nonreserved +%type declspecs declspecs_nosc declspecs_nots +%type declspecs_ts +%type declspecs_nosc_ts declspecs_nosc_nots +%type declspecs_sc_ts declspecs_sc_nots defspecs +%type declarator notype_declarator after_type_declarator +%type param_declarator param_declarator_starttypename +%type param_declarator_nostarttypename +%type absdecl absdecl1 direct_absdecl typename ptr_spec +%type qc_comma %type attribute_list attribute -%type function_params var_list param_declaration -%type qc_func_params qc_var_list qc_param_decl -%type new_name -%type var_decl function_decl -%type abstract_decl abs_decl +%type function_params +%type qc_func_params qc_param_list qc_first_param qc_param -%type tag optional_tag -%type struct_specifier struct_def struct_decl +%type tag +%type struct_specifier struct_list %type enum_specifier %type optional_enum_list enum_list enumerator_list enumerator %type enum_init %type array_decl -%type func_def_list comma - %type const string -%type ivar_decl decl decl_list +%type ivar_decl +%type decl %type ivars -%type param param_list +%type param_list parameter_list parameter %type methoddef -%type opt_initializer var_initializer local_def +%type var_initializer local_def -%type opt_init opt_expr comma_expr expr +%type opt_init_semi opt_expr comma_expr expr %type compound_init element_list %type element -%type optional_state_expr texpr vector_expr +%type ose optional_state_expr texpr vector_expr %type statement statements compound_statement %type else bool_label break_label continue_label %type unary_expr ident_expr cast_expr expr_list %type opt_arg_list arg_list arg_expr -%type init_var_decl_list init_var_decl %type switch_block %type identifier label -%type overloaded_identifier - %type identifier_list %type protocol_name_list selector reserved_word %type optional_param_list unaryselector keyworddecl @@ -301,70 +301,6 @@ spec_merge (specifier_t spec, specifier_t new) return spec; } -static specifier_t -default_type (specifier_t spec, symbol_t *sym) -{ - if (spec.type) { - if (is_float (spec.type) && !spec.multi_type) { - // no modifieres allowed - if (spec.is_unsigned) { - spec.multi_type = 1; - error (0, "both unsigned and float in declaration specifiers"); - } else if (spec.is_signed) { - spec.multi_type = 1; - error (0, "both signed and float in declaration specifiers"); - } else if (spec.is_short) { - spec.multi_type = 1; - error (0, "both short and float in declaration specifiers"); - } else if (spec.is_long) { - spec.multi_type = 1; - error (0, "both long and float in declaration specifiers"); - } - } - if (is_double (spec.type)) { - // long is allowed but ignored - if (spec.is_unsigned) { - spec.multi_type = 1; - error (0, "both unsigned and double in declaration specifiers"); - } else if (spec.is_signed) { - spec.multi_type = 1; - error (0, "both signed and double in declaration specifiers"); - } else if (spec.is_short) { - spec.multi_type = 1; - error (0, "both short and double in declaration specifiers"); - } - } - if (is_int (spec.type)) { - // signed and short are ignored - if (spec.is_unsigned && spec.is_long) { - spec.type = &type_ulong; - } else if (spec.is_long) { - spec.type = &type_long; - } - } - } else { - if (spec.is_long) { - if (spec.is_unsigned) { - spec.type = type_ulong_uint; - } else { - spec.type = type_long_int; - } - } else { - if (spec.is_unsigned) { - spec.type = &type_uint; - } else if (spec.is_signed || spec.is_short) { - spec.type = &type_int; - } - } - } - if (!spec.type) { - spec.type = type_default; - warning (0, "type defaults to '%s' in declaration of '%s'", - type_default->name, sym->name); - } - return spec; -} - static int is_anonymous_struct (specifier_t spec) { @@ -409,7 +345,7 @@ use_type_name (specifier_t spec) return !!spec.sym->table; } -static void +static void __attribute__((used)) check_specifiers (specifier_t spec) { if (!is_null_spec (spec)) { @@ -436,16 +372,9 @@ check_specifiers (specifier_t spec) } } -static void -set_func_type_attrs (type_t *func, specifier_t spec) -{ - func->t.func.no_va_list = spec.no_va_list; - func->t.func.void_return = spec.void_return; -} - %} -%expect 0 +%expect 2 %% @@ -466,58 +395,11 @@ external_def_list } | external_def_list external_def | external_def_list obj_def - | error END - { - yyerrok; - current_class = 0; - current_symtab = pr.symtab; - current_storage = sc_global; - } - | error ';' - { - yyerrok; - current_class = 0; - current_symtab = pr.symtab; - current_storage = sc_global; - } - | error '}' - { - yyerrok; - current_class = 0; - current_symtab = pr.symtab; - current_storage = sc_global; - } ; external_def - : optional_specifiers external_decl_list ';' { } - | optional_specifiers ';' - { - check_specifiers ($1); - } - | optional_specifiers qc_func_params - { - type_t **type; - type_t *ret_type; - $$ = $1; // copy spec bits and storage - // .float () foo; is a field holding a function variable rather - // than a function that returns a float field. - for (type = &$1.type; *type && (*type)->type == ev_field; - type = &(*type)->t.fldptr.type) { - } - ret_type = *type; - *type = 0; - *type = parse_params (0, $2); - set_func_type_attrs ((*type), $1); - $$.type = find_type (append_type ($1.type, ret_type)); - if ($$.type->type != ev_field) - $$.params = $2; - } - function_def_list - { - (void) ($3); - } - | optional_specifiers function_decl function_body + : fndef + | datadef | storage_class '{' save_storage { current_storage = $1.storage; @@ -528,6 +410,457 @@ external_def } ; +fndef + : declspecs_ts declarator function_body + | declspecs_nots notype_declarator function_body + | defspecs notype_declarator function_body + ; + +datadef + : defspecs notype_initdecls ';' + | declspecs_nots notype_initdecls ';' + | declspecs_ts initdecls ';' + | declspecs_ts qc_func_params + { + specifier_t spec = default_type ($1, 0); + type_t **type; + // .float () foo; is a field holding a function variable rather + // than a function that returns a float field. + for (type = &spec.type; *type && (*type)->type == ev_field; + type = &(*type)->t.fldptr.type) + ; + type_t *ret_type = *type; + *type = 0; + *type = parse_params (ret_type, $2); + set_func_type_attrs ((*type), spec); + if (spec.type->type != ev_field) { + spec.is_function = 1; //FIXME do proper void(*)() -> ev_func + spec.params = $2; + } + $$ = spec; + } + qc_func_decls + | declspecs ';' + | error ';' + | error '}' + | ';' + ; + +qc_func_params + : '(' copy_spec qc_param_list ')' { $$ = check_params ($3); } + | '(' copy_spec typespec_reserved ')' + { + if (!is_void ($3.type)) { + PARSE_ERROR; + } + $$ = 0; + } + | '(' copy_spec ')' { $$ = 0; } + ; + +qc_param_list + : qc_first_param + | qc_param_list ',' qc_param + { + $$ = append_params ($1, $3); + } + ; +// quakec function parameters cannot use a typedef as the return type +// in the first parameter (really, they should't use any as standard quakec +// doesn't support typedef, but that seems overly restrictive), howevery, +// they can stil use a typedef first parameter. This is due to grammar issues +qc_first_param + : typespec identifier + { + $$ = new_param (0, $1.type, $2->name); + } + | typespec_reserved qc_func_params identifier + { + specifier_t spec = default_type ($1, $3); + $3->params = $2; + spec.type = parse_params (spec.type, $2); + + $$ = new_param (0, spec.type, $3->name); + } + | ELLIPSIS { $$ = new_param (0, 0, 0); } + ; + +qc_param + : typespec identifier + { + $$ = new_param (0, $1.type, $2->name); + } + | typespec qc_func_params identifier + { + specifier_t spec = default_type ($1, $3); + $3->params = $2; + spec.type = parse_params (spec.type, $2); + + $$ = new_param (0, spec.type, $3->name); + } + | ELLIPSIS { $$ = new_param (0, 0, 0); } + ; + +/* This rule is used only to get an action before both qc_func_decl and + qc_func_decl_term so that the function spec can be inherited. +*/ +qc_comma + : ',' { $$ = $0; } + ; + +qc_func_decls + : qc_func_decl_list qc_comma qc_func_decl_term + | qc_func_decl_term + ; + +qc_func_decl_term + : qc_nocode_func ';' + | qc_code_func ';' + | qc_code_func %prec IFX + ; + +qc_func_decl_list + : qc_func_decl_list qc_comma qc_func_decl + | qc_func_decl + ; + +qc_func_decl + : qc_nocode_func + | qc_code_func + ; + +qc_nocode_func + : identifier '=' '#' expr + { + specifier_t spec = $0; + symbol_t *sym = $1; + expr_t *expr = $4; + sym->params = spec.params; + sym->type = find_type (spec.type); + sym = function_symbol (sym, spec.is_overload, 1); + build_builtin_function (sym, expr, 0, spec.storage); + } + | identifier '=' expr + { + specifier_t spec = $0; + spec.sym = $1; + spec.sym->params = spec.params; + spec.sym->type = find_type (spec.type); + spec.is_function = 0; + declare_symbol (spec, $3, current_symtab); + } + | identifier + { + specifier_t spec = $0; + symbol_t *sym = $1; + sym->type = find_type (spec.type); + if (!local_expr && sym->type->type != ev_field) { + sym->params = spec.params; + sym = function_symbol (sym, spec.is_overload, 1); + } + if (!local_expr && sym->type->type != ev_field) { + // things might be a confused mess from earlier errors + if (sym->sy_type == sy_func) + make_function (sym, 0, sym->table->space, spec.storage); + } else { + initialize_def (sym, 0, current_symtab->space, spec.storage, + current_symtab); + if (sym->s.def) + sym->s.def->nosave |= spec.nosave; + } + } + ; + +qc_code_func + : identifier '=' optional_state_expr + save_storage + { + specifier_t spec = $0; + symbol_t *sym = $1; + $$ = current_symtab; + sym->params = spec.params; + sym->type = find_type (spec.type); + sym = function_symbol (sym, spec.is_overload, 1); + current_func = begin_function (sym, 0, current_symtab, 0, + spec.storage); + current_symtab = current_func->locals; + current_storage = sc_local; + $1 = sym; + } + compound_statement + { + build_code_function ($1, $3, $6); + current_symtab = $5; + current_storage = $4.storage; + current_func = 0; + } + ; + +declarator + : after_type_declarator + | notype_declarator + ; + +after_type_declarator + : '(' copy_spec after_type_declarator ')' { $$ = $3; } + | after_type_declarator function_params + { + specifier_t spec = default_type ($1, $1.sym); + spec.sym->params = $2; + spec.type = parse_params (spec.type, $2); + spec.is_function = 1; //FIXME do proper void(*)() -> ev_func + $$ = spec; + } + | after_type_declarator array_decl + { + specifier_t spec = default_type ($1, $1.sym); + spec.type = array_type (spec.type, $2); + $$ = spec; + } + | '*' ptr_spec after_type_declarator + { + $$ = $3; + } + | TYPE_NAME + { + $$ = $0; + $$.sym = new_symbol ($1.sym->name); + } + | OBJECT_NAME + { + $$ = $0; + $$.sym = new_symbol ($1.sym->name); + } + ; + +copy_spec + : /* empty */ + { + $$ = $-1; + } + ; + +ptr_spec + : /* empty */ + { + $$ = default_type ($-1, 0); + $$.type = pointer_type ($$.type); + } + ; + +notype_declarator + : '(' copy_spec notype_declarator ')' { $$ = $3; } + | notype_declarator function_params + { + //printf ("notype_declarator p %d\n", pr.source_line); + specifier_t spec = default_type ($1, $1.sym); + spec.sym->params = $2; + spec.type = parse_params (spec.type, $2); + spec.is_function = 1; //FIXME do proper void(*)() -> ev_func + $$ = spec; + } + | notype_declarator array_decl + { + specifier_t spec = default_type ($1, $1.sym); + spec.type = array_type (spec.type, $2); + $$ = spec; + } + | '*' ptr_spec notype_declarator + { + $$ = $3; + } + | NAME + { + $$ = $0; + $$.sym = new_symbol ($1->name); + } + ; + +initdecls + : initdecl + | initdecls ',' { $$ = $0; } initdecl + ; + +initdecl + : declarator '=' var_initializer + { declare_symbol ($1, $3, current_symtab); } + | declarator + { declare_symbol ($1, 0, current_symtab); } + ; + +notype_initdecls + : notype_initdecl + | notype_initdecls ',' { $$ = $0; } notype_initdecl + ; + +notype_initdecl + : notype_declarator '=' var_initializer + { declare_symbol ($1, $3, current_symtab); } + | notype_declarator + { declare_symbol ($1, 0, current_symtab); } + ; + +/* various lists of type specifiers, storage class etc */ +declspecs_ts + : declspecs_nosc_ts + | declspecs_sc_ts + ; + +declspecs_nots + : declspecs_nosc_nots + | declspecs_sc_nots + ; + +declspecs_nosc + : declspecs_nosc_nots + | declspecs_nosc_ts + ; + +declspecs + : declspecs_nosc_nots + | declspecs_nosc_ts + | declspecs_sc_nots + | declspecs_sc_ts + ; + +declspecs_nosc_nots + : TYPE_QUAL + | declspecs_nosc_nots TYPE_QUAL + { + $$ = spec_merge ($1, $2); + } + ; + +declspecs_nosc_ts + : typespec + | declspecs_nosc_ts TYPE_QUAL + { + $$ = spec_merge ($1, $2); + } + | declspecs_nosc_ts typespec_reserved + { + $$ = spec_merge ($1, $2); + } + | declspecs_nosc_nots typespec + { + $$ = spec_merge ($1, $2); + } + ; + +declspecs_sc_nots + : storage_class + | declspecs_sc_nots TYPE_QUAL + { + $$ = spec_merge ($1, $2); + } + | declspecs_nosc_nots storage_class + { + $$ = spec_merge ($1, $2); + } + | declspecs_sc_nots storage_class + { + $$ = spec_merge ($1, $2); + } + ; + +declspecs_sc_ts + : declspecs_sc_ts TYPE_QUAL + { + $$ = spec_merge ($1, $2); + } + | declspecs_sc_ts typespec_reserved + { + $$ = spec_merge ($1, $2); + } + | declspecs_sc_nots typespec + { + $$ = spec_merge ($1, $2); + } + | declspecs_nosc_ts storage_class + { + $$ = spec_merge ($1, $2); + } + | declspecs_sc_ts storage_class + { + $$ = spec_merge ($1, $2); + } + ; + +typespec + : typespec_reserved + { + $$ = $1; + //if (!$$.storage) { + // $$.storage = current_storage; + //} + } + | typespec_nonreserved + { + $$ = $1; + //if (!$$.storage) { + // $$.storage = current_storage; + //} + } + ; + +typespec_reserved + : TYPE_SPEC + | enum_specifier + | struct_specifier + // NOTE: fields don't parse the way they should. This is not a problem + // for basic types, but functions need special treatment + | '.' typespec_reserved + { + // avoid find_type() + $$ = make_spec (field_type (0), 0, 0, 0); + $$.type = append_type ($$.type, $2.type); + } + ; + + +typespec_nonreserved + : TYPE_NAME + | OBJECT_NAME protocolrefs + { + if ($2) { + type_t type = *type_id.t.fldptr.type; + type.next = 0; + type.protos = $2; + $$ = make_spec (pointer_type (find_type (&type)), 0, 0, 0); + } else { + $$ = make_spec (&type_id, 0, 0, 0); + } + $$.sym = $1.sym; + } + | CLASS_NAME protocolrefs + { + if ($2) { + type_t type = *$1->type; + type.next = 0; + type.protos = $2; + $$ = make_spec (find_type (&type), 0, 0, 0); + } else { + $$ = make_spec ($1->type, 0, 0, 0); + } + $$.sym = $1; + } + // NOTE: fields don't parse the way they should. This is not a problem + // for basic types, but functions need special treatment + | '.' typespec_nonreserved + { + // avoid find_type() + $$ = make_spec (field_type (0), 0, 0, 0); + $$.type = append_type ($$.type, $2.type); + } + ; + +defspecs + : /* empty */ + { + $$ = (specifier_t) {}; + } + ; + save_storage : /* emtpy */ { @@ -535,22 +868,14 @@ save_storage } ; -set_spec_storage - : /* emtpy */ - { - $$ = $0; - $$.storage = current_storage; - } - ; - function_body - : optional_state_expr + : ose { - symbol_t *sym = $0; - specifier_t spec = default_type ($-1, sym); + specifier_t spec = default_type ($0, $0.sym); + symbol_t *sym = spec.sym; - set_func_type_attrs (sym->type, spec); - sym->type = find_type (append_type (sym->type, spec.type)); + set_func_type_attrs (spec.type, spec); + sym->type = find_type (spec.type); $$ = function_symbol (sym, spec.is_overload, 1); } save_storage @@ -570,70 +895,16 @@ function_body } | '=' '#' expr ';' { - symbol_t *sym = $0; - specifier_t spec = default_type ($-1, sym); + specifier_t spec = default_type ($0, $0.sym); + symbol_t *sym = spec.sym; - set_func_type_attrs (sym->type, spec); - sym->type = find_type (append_type (sym->type, spec.type)); + set_func_type_attrs (spec.type, spec); + sym->type = find_type (spec.type); sym = function_symbol (sym, spec.is_overload, 1); build_builtin_function (sym, $3, 0, spec.storage); } ; -external_decl_list - : external_decl - | external_decl_list ',' { $$ = $0; } - external_decl { (void) ($3); } - ; - -external_decl - : var_decl - { - specifier_t spec = default_type ($0, $1); - $1->type = find_type (append_type ($1->type, spec.type)); - if (spec.is_typedef) { - $1->sy_type = sy_type; - $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); - symtab_addsymbol (current_symtab, $1); - } else { - initialize_def ($1, 0, current_symtab->space, spec.storage, - current_symtab); - if ($1->s.def) - $1->s.def->nosave |= spec.nosave; - } - } - | var_decl var_initializer - { - specifier_t spec = default_type ($0, $1); - - $1->type = find_type (append_type ($1->type, spec.type)); - if (spec.is_typedef) { - error (0, "typedef %s is initialized", $1->name); - $1->sy_type = sy_type; - $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); - symtab_addsymbol (current_symtab, $1); - } else { - initialize_def ($1, $2, current_symtab->space, spec.storage, - current_symtab); - if ($1->s.def) - $1->s.def->nosave |= spec.nosave; - } - } - | function_decl - { - specifier_t spec = default_type ($0, $1); - set_func_type_attrs ($1->type, spec); - $1->type = find_type (append_type ($1->type, spec.type)); - if (spec.is_typedef) { - $1->sy_type = sy_type; - $1->type=find_type (alias_type ($1->type, $1->type, $1->name)); - symtab_addsymbol (current_symtab, $1); - } else { - $1 = function_symbol ($1, spec.is_overload, 1); - } - } - ; - storage_class : EXTERN { $$ = make_spec (0, sc_extern, 0, 0); } | STATIC { $$ = make_spec (0, sc_static, 0, 0); } @@ -664,84 +935,6 @@ attribute | NAME '(' expr_list ')' { $$ = new_attribute ($1->name, $3); } ; -optional_specifiers - : specifiers - { - $$ = $1; - if (!$$.storage) - $$.storage = current_storage; - } - | /* empty */ - { - $$ = make_spec (0, current_storage, 0, 0); - } - ; - -specifiers - : type_specifier_or_storage_class - | specifiers type_specifier_or_storage_class - { - $$ = spec_merge ($1, $2); - } - ; - -type - : type_specifier - | type type_specifier - { - $$ = spec_merge ($1, $2); - } - ; - -type_specifier_or_storage_class - : type_specifier - | storage_class - ; - -type_specifier - : TYPE_SPEC - | enum_specifier - | struct_specifier - | TYPE_NAME - | OBJECT protocolrefs - { - if ($2) { - type_t type = *type_id.t.fldptr.type; - type.next = 0; - type.protos = $2; - $$ = make_spec (pointer_type (find_type (&type)), 0, 0, 0); - } else { - $$ = make_spec (&type_id, 0, 0, 0); - } - $$.sym = $1; - } - | CLASS_NAME protocolrefs - { - if ($2) { - type_t type = *$1->type; - type.next = 0; - type.protos = $2; - $$ = make_spec (find_type (&type), 0, 0, 0); - } else { - $$ = make_spec ($1->type, 0, 0, 0); - } - $$.sym = $1; - } - // NOTE: fields don't parse the way they should. This is not a problem - // for basic types, but functions need special treatment - | '.' type_specifier - { - // avoid find_type() - $$ = make_spec (field_type (0), 0, 0, 0); - $$.type = append_type ($$.type, $2.type); - } - ; - -optional_tag - : tag - | /* empty */ { $$ = 0; } - ; - tag : NAME ; enum_specifier @@ -787,7 +980,6 @@ enumerator_list enumerator { $$ = $0; - (void) ($3); } ; @@ -797,27 +989,33 @@ enumerator ; struct_specifier - : STRUCT optional_tag '{' + : STRUCT tag struct_list { $$ = $3; } + | STRUCT {$$ = 0;} struct_list { $$ = $3; } + | STRUCT tag { symbol_t *sym; + sym = find_struct ($1, $2, 0); + sym->type = find_type (sym->type); + $$ = make_spec (sym->type, 0, 0, 0); if (!sym->table) { - symtab_addsymbol (current_symtab, sym); - } else { - if (!sym->type) { - internal_error (0, "broken structure symbol?"); - } - if (sym->type->meta == ty_enum - || (sym->type->meta == ty_struct && sym->type->t.symtab)) { - error (0, "%s %s redefined", - $1 == 's' ? "struct" : "union", $2->name); - $1 = 0; - } else if (sym->type->meta != ty_struct) { - internal_error (0, "%s is not a struct or union", - $2->name); + symtab_t *tab = current_symtab; + while (tab->parent && tab->type == stab_struct) { + tab = tab->parent; } + symtab_addsymbol (tab, sym); } - current_symtab = new_symtab (current_symtab, stab_local); + } + ; + +struct_list + : '{' + { + int op = $-1; + symbol_t *sym = $0; + current_symtab = start_struct (&op, sym, current_symtab); + $1 = op; + $$ = sym; } struct_defs '}' { @@ -825,26 +1023,18 @@ struct_specifier symtab_t *symtab = current_symtab; current_symtab = symtab->parent; - if ($1) { - sym = build_struct ($1, $2, symtab, 0, 0); + if ($1) { + sym = $2; + sym = build_struct ($1, sym, symtab, 0, 0); $$ = make_spec (sym->type, 0, 0, 0); if (!sym->table) symtab_addsymbol (current_symtab, sym); } } - | STRUCT tag - { - symbol_t *sym; - - sym = find_struct ($1, $2, 0); - $$ = make_spec (sym->type, 0, 0, 0); - if (!sym->table) - symtab_addsymbol (current_symtab, sym); - } ; struct_defs - : struct_def_list ';' + : component_decl_list | DEFS '(' identifier ')' { $3 = check_undefined ($3); @@ -860,23 +1050,22 @@ struct_defs } ; -struct_def_list - : struct_def - | struct_def_list ';' struct_def +component_decl_list + : component_decl_list2 + | component_decl_list2 component_decl ; -struct_def - : type struct_decl_list - | type +component_decl_list2 + : /* empty */ + | component_decl_list2 component_decl ';' + | component_decl_list2 ';' + ; + +component_decl + : declspecs_nosc_ts components + | declspecs_nosc_ts { - if ($1.sym && $1.sym->type != $1.type) { - // a type name (id, typedef, etc) was used as a field name. - // this is allowed in C - if (!use_type_name ($1)) { - error (0, "duplicate field `%s'", $1.sym->name); - } - } else if (is_anonymous_struct ($1)) { - // anonymous struct/union + if (is_anonymous_struct ($1)) { // type->name always begins with "tag " $1.sym = new_symbol (va (0, ".anonymous.%s", $1.type->name + 4)); @@ -887,224 +1076,176 @@ struct_def if (!$1.sym->table) { error (0, "duplicate field `%s'", $1.sym->name); } - } else { - // bare type - warning (0, "declaration does not declare anything"); - } - $$ = $1; - } - ; - -struct_decl_list - : struct_decl_list ',' { $$ = $0; } - struct_decl { (void) ($3); } - | struct_decl - ; - -struct_decl - : function_decl - { - $0 = default_type ($-0, $1); - $1->type = find_type (append_type ($1->type, $0.type)); - $1->sy_type = sy_var; - $1->visibility = current_visibility; - symtab_addsymbol (current_symtab, $1); - if (!$1->table) { - error (0, "duplicate field `%s'", $1->name); } } - | var_decl + | declspecs_nosc_nots components_notype + | declspecs_nosc_nots { internal_error (0, "not implemented"); } + ; + +components + : component_declarator + | components ',' { $$ = $0; } component_declarator + ; + +component_declarator + : declarator { - $0 = default_type ($-0, $1); - $1->type = find_type (append_type ($1->type, $0.type)); - $1->sy_type = sy_var; - $1->visibility = current_visibility; - symtab_addsymbol (current_symtab, $1); - if (!$1->table) { - error (0, "duplicate field `%s'", $1->name); + symbol_t *s = $1.sym; + specifier_t spec = default_type ($1, s); + s->type = find_type (spec.type); + s->sy_type = sy_var; + s->visibility = current_visibility; + symtab_addsymbol (current_symtab, s); + if (!s->table) { + error (0, "duplicate field `%s'", s->name); } } - | var_decl ':' expr %prec COMMA {} - | ':' expr %prec COMMA {} + | declarator ':' expr + | ':' expr ; -new_name - : NAME %prec COMMA - { - $$ = $1; - // due to the way declarations work, we need a new symbol at all - // times. redelcarations will be checked later - if ($$->table) - $$ = new_symbol ($1->name); - } +components_notype + : component_notype_declarator + | components_notype ',' component_notype_declarator ; -var_decl - : new_name - { - $$ = $1; - $$->type = 0; - } - | var_decl function_params - { - $$->type = append_type ($$->type, parse_params (0, $2)); - } - | var_decl array_decl - { - $$->type = append_type ($$->type, array_type (0, $2)); - } - | '*' var_decl %prec UNARY - { - $$ = $2; - $$->type = append_type ($$->type, pointer_type (0)); - } - | '(' var_decl ')' { $$ = $2; } - ; - -function_decl - : '*' function_decl - { - $$ = $2; - $$->type = append_type ($$->type, pointer_type (0)); - } - | function_decl array_decl - { - $$ = $1; - $$->type = append_type ($$->type, array_type (0, $2)); - } - | '(' function_decl ')' { $$ = $2; } - | function_decl function_params - { - $$ = $1; - $$->params = $2; - $$->type = append_type ($$->type, parse_params (0, $2)); - } - | NAME function_params - { - $$ = $1; - $$->params = $2; - $$->type = parse_params (0, $2); - } +component_notype_declarator + : notype_declarator { internal_error (0, "not implemented"); } + | notype_declarator ':' expr + | ':' expr ; function_params - : '(' ')' { $$ = 0; } - | '(' ps var_list ')' { $$ = check_params ($3); } + : '(' copy_spec param_list ')' { $$ = check_params ($3); } ; -qc_func_params - : '(' ')' { $$ = 0; } - | '(' ps qc_var_list ')' { $$ = check_params ($3); } - | '(' ps TYPE_SPEC ')' +param_list + : /* empty */ { $$ = 0; } + | parameter_list + | parameter_list ',' ELLIPSIS { - if (!is_void ($3.type)) - PARSE_ERROR; - $$ = 0; + $$ = param_append_identifiers ($1, 0, 0); + } + | ELLIPSIS + { + $$ = new_param (0, 0, 0); } ; -ps : ; - -var_list - : param_declaration - | var_list ',' param_declaration +parameter_list + : parameter + | parameter_list ',' parameter { - param_t *p; - - for (p = $1; p->next; p = p->next) - ; - p->next = $3; - $$ = $1; + $$ = append_params ($1, $3); } ; -qc_var_list - : qc_param_decl - | qc_var_list ',' qc_param_decl +parameter + : declspecs_ts param_declarator { - param_t *p; - - for (p = $1; p->next; p = p->next) - ; - p->next = $3; - $$ = $1; + $2 = default_type ($2, $2.sym); + $$ = new_param (0, $2.type, $2.sym->name); + } + | declspecs_ts notype_declarator + { + $2 = default_type ($2, $2.sym); + $$ = new_param (0, $2.type, $2.sym->name); + } + | declspecs_ts absdecl + { + $2 = default_type ($2, $2.sym); + $$ = new_param (0, $2.type, 0); + } + | declspecs_nosc_nots notype_declarator + { + $2 = default_type ($2, $2.sym); + $$ = new_param (0, $2.type, $2.sym->name); + } + | declspecs_nosc_nots absdecl + { + $2 = default_type ($2, 0); + $$ = new_param (0, $2.type, 0); } ; -param_declaration - : type var_decl - { - $1 = default_type ($1, $2); - $2->type = find_type (append_type ($2->type, $1.type)); - $$ = new_param (0, $2->type, $2->name); - } - | abstract_decl { $$ = new_param (0, $1->type, $1->name); } - | ELLIPSIS { $$ = new_param (0, 0, 0); } +absdecl + : /* empty */ { $$ = $0; } + | absdecl1 ; -abstract_decl - : type abs_decl +absdecl1 + : direct_absdecl + | '*' ptr_spec absdecl { - // abs_decl's symbol is just a carrier for the type - if ($2->name) { - bug (0, "unexpected name in abs_decl"); - } - if ($1.sym) { - $1.sym = new_symbol ($1.sym->name); - $1.sym->type = $2->type; - $2 = $1.sym; - } - $$ = $2; - $1 = default_type ($1, $2); - $$->type = find_type (append_type ($$->type, $1.type)); + $$ = $3; } - | error { $$ = new_symbol (0); } ; -qc_param_decl - : type new_name +direct_absdecl + : '(' copy_spec absdecl1 ')' { $$ = $3; } + | direct_absdecl function_params { - $2->type = find_type ($1.type); - $$ = new_param (0, $2->type, $2->name); + specifier_t spec = $1; + spec.type = parse_params (spec.type, $2); + $$ = spec; } - | type qc_func_params new_name + | direct_absdecl array_decl { - type_t **type; - // .float () foo; is a field holding a function variable rather - // than a function that returns a float field. - for (type = &$1.type; *type && (*type)->type == ev_field; - type = &(*type)->t.fldptr.type) - ; - *type = parse_params (*type, $2); - set_func_type_attrs ((*type), $1); - $3->type = find_type ($1.type); - if ($3->type->type != ev_field) - $3->params = $2; - $$ = new_param (0, $3->type, $3->name); + specifier_t spec = default_type ($1, 0); + spec.type = array_type (spec.type, $2); + $$ = spec; + } + | function_params + { + specifier_t spec = default_type ($0, 0); + spec.type = parse_params (spec.type, $1); + $$ = spec; + } + | array_decl + { + specifier_t spec = default_type ($0, 0); + spec.type = array_type (spec.type, $1); + $$ = spec; } - | ELLIPSIS { $$ = new_param (0, 0, 0); } ; -abs_decl - : /* empty */ { $$ = new_symbol (0); } - | '(' abs_decl ')' function_params +param_declarator + : param_declarator_starttypename + | param_declarator_nostarttypename + ; + +param_declarator_starttypename + : param_declarator_starttypename function_params + { $$ = $1; internal_error (0, "not implemented"); } + | param_declarator_starttypename array_decl + { $$ = $1; internal_error (0, "not implemented"); } + | TYPE_NAME + { $$ = $1; internal_error (0, "not implemented"); } + | OBJECT_NAME + { $$ = $1; internal_error (0, "not implemented"); } + ; + +param_declarator_nostarttypename + : param_declarator_nostarttypename function_params + { $$ = $1; internal_error (0, "not implemented"); } + | param_declarator_nostarttypename array_decl + { $$ = $1; internal_error (0, "not implemented"); } + | '*' ptr_spec param_declarator_starttypename + { $$ = $3; internal_error (0, "not implemented"); } + | '*' ptr_spec param_declarator_nostarttypename + { $$ = $3; internal_error (0, "not implemented"); } + | '(' copy_spec param_declarator_nostarttypename ')' { $$ = $3; } + ; + +typename + : declspecs_nosc absdecl { - $$ = $2; - $$->type = append_type ($$->type, parse_params (0, $4)); - } - | '*' abs_decl - { - $$ = $2; - $$->type = append_type ($$->type, pointer_type (0)); - } - | abs_decl array_decl - { - $$ = $1; - $$->type = append_type ($$->type, array_type (0, $2)); - } - | '(' abs_decl ')' - { - $$ = $2; + //printf ("%s:%d:typename %p %p\n", + // pr.strings->strings + pr.source_file, pr.source_line, + // $1.type, $2.type); + //if ($1.type) print_type ($1.type); + //if ($2.type) print_type ($2.type); + $$ = $2.type ? $2 : default_type ($1, 0); } ; @@ -1123,190 +1264,36 @@ array_decl | '[' ']' { $$ = 0; } ; -local_specifiers - : LOCAL specifiers { $$ = $2; } - | specifiers { $$ = $1; } - ; - -param_list - : param { $$ = $1; } - | param_list ',' { $$ = $1; } param - { - $$ = $4; - (void) ($3); - } - ; - -param - : type identifier - { - $2 = check_redefined ($2); - $$ = param_append_identifiers ($0, $2, $1.type); - } - ; - -local_decl_list - : decl_list - | qc_func_params - { - type_t **type; - specifier_t spec = $0; // copy spec bits and storage - // .float () foo; is a field holding a function variable rather - // than a function that returns a float field. - for (type = &spec.type; *type && (*type)->type == ev_field; - type = &(*type)->t.fldptr.type) - ; - *type = parse_params (*type, $1); - set_func_type_attrs ((*type), spec); - spec.type = find_type (spec.type); - $$ = spec; - } - func_def_list - { - (void) ($2); - } - ; - -decl_list - : decl_list ',' { $$ = $0; } decl { (void) ($3); } - | decl - ; - decl - : function_decl {} - | var_decl opt_initializer + : declspecs_ts local_expr initdecls ';' { - specifier_t spec = default_type ($0, $1); - storage_class_t sc = spec.storage; - struct defspace_s *space = current_symtab->space; - - if (sc == sc_static) - space = pr.near_data; - $1->type = find_type (append_type ($1->type, spec.type)); - initialize_def ($1, $2, space, sc, current_symtab); - if ($1->s.def) - $1->s.def->nosave |= spec.nosave; + $$ = local_expr; + local_expr = 0; } - ; - -function_def_list - : func_def_list comma func_def_list_term - | func_def_list_term - ; - -func_def_list - : func_def_list comma func_def { $$ = $2; } - | func_def { $$ = $0; } - ; - -/* This rule is used only to get an action before both func_def and - func_def_list_term so that the function spec can be inherited. -*/ -comma: ',' { $$ = $0; } - -func_def_list_term - : non_code_funcion ';' - | code_function ';' - | code_function %prec IFX - ; - -func_def - : non_code_funcion - | code_function - ; - -code_function - : overloaded_identifier code_func - ; - -non_code_funcion - : overloaded_identifier non_code_func - ; - -overloaded_identifier - : identifier + | declspecs_nots local_expr notype_initdecls ';' { - $$ = $1; - $$->type = $0.type; - if (!local_expr && $$->type->type != ev_field) { - $$ = function_symbol ($$, $0.is_overload, 1); - $$->params = $0.params; - } + $$ = local_expr; + local_expr = 0; } + | declspecs ';' { $$ = 0; } ; -non_code_func - : '=' '#' expr +local_expr + : /* emtpy */ { - build_builtin_function ($0, $3, 0, $-1.storage); + $$ = $0; + local_expr = new_block_expr (); } - | '=' expr - { - if (local_expr) { - symbol_t *sym = $0; - specifier_t spec = $-1; - initialize_def (sym, $2, current_symtab->space, spec.storage, - current_symtab); - if (sym->s.def) - sym->s.def->nosave |= spec.nosave; - } else { - if (is_int_val ($2) || is_float_val ($2)) { - error (0, "invalid function initializer." - " did you forget #?"); - } else { - error (0, "cannot create global function variables"); - } - } - } - | /* emtpy */ - { - symbol_t *sym = $0; - specifier_t spec = $-1; - if (!local_expr && sym->type->type != ev_field) { - // things might be a confused mess from earlier errors - if (sym->sy_type == sy_func) - make_function (sym, 0, sym->table->space, spec.storage); - } else { - initialize_def (sym, 0, current_symtab->space, spec.storage, - current_symtab); - if (sym->s.def) - sym->s.def->nosave |= spec.nosave; - } - } - ; - -code_func - : '=' optional_state_expr - save_storage - { - $$ = current_symtab; - current_func = begin_function ($0, 0, current_symtab, 0, - $-1.storage); - current_symtab = current_func->locals; - current_storage = sc_local; - } - compound_statement - { - build_code_function ($0, $2, $5); - current_symtab = $4; - current_storage = $3.storage; - current_func = 0; - } - ; - -opt_initializer - : /*empty*/ { $$ = 0; } - | var_initializer { $$ = $1; } ; var_initializer - : '=' expr { $$ = $2; } - | '=' compound_init + : expr { $$ = $1; } + | compound_init { - if (!$2 && is_scalar ($-1.type)) { + if (!$1 && is_scalar ($-1.type)) { error (0, "empty scalar initializer"); } - $$ = $2 ? $2 : new_nil_expr (); + $$ = $1 ? $1 : new_nil_expr (); } ; @@ -1315,6 +1302,11 @@ compound_init | '{' '}' { $$ = 0; } ; +ose + : /* emtpy */ { $$ = 0; } + | SHR vector_expr { $$ = build_state_expr ($2); } + ; + optional_state_expr : /* emtpy */ { $$ = 0; } | vector_expr { $$ = build_state_expr ($1); } @@ -1376,24 +1368,8 @@ statements ; local_def - : local_specifiers - { - if (!$1.storage) - $1.storage = sc_local; - $$ = $1; - local_expr = new_block_expr (); - } - local_decl_list ';' - { - $$ = local_expr; - local_expr = 0; - (void) ($2); - } - | specifiers opt_initializer ';' - { - check_specifiers ($1); - $$ = 0; - } + : LOCAL decl { $$ = $2; } + | decl ; statement @@ -1452,12 +1428,12 @@ statement $$ = build_if_statement ($2, $4, $6, $7, $8); } | FOR push_scope break_label continue_label - '(' opt_init ';' opt_expr ';' opt_expr ')' statement pop_scope + '(' opt_init_semi opt_expr ';' opt_expr ')' statement pop_scope { if ($6) { $6 = build_block_expr ($6); } - $$ = build_for_statement ($6, $8, $10, $12, + $$ = build_for_statement ($6, $7, $9, $11, break_label, continue_label); break_label = $3; continue_label = $4; @@ -1531,39 +1507,15 @@ switch_block } ; -opt_init - : comma_expr - | type set_spec_storage init_var_decl_list { $$ = $3; } - | /* empty */ +opt_init_semi + : comma_expr ';' + | decl /* contains ; */ + | ';' { $$ = 0; } ; -init_var_decl_list - : init_var_decl - { - $$ = $1; - } - | init_var_decl_list ',' { $$ = $0; } init_var_decl - { - $4->next = $1; - $$ = $4; - } - ; - -init_var_decl - : var_decl opt_initializer - { - specifier_t spec = $0; - $1->type = find_type (append_type ($1->type, spec.type)); - $1->sy_type = sy_var; - initialize_def ($1, 0, current_symtab->space, spec.storage, - current_symtab); - $$ = assign_expr (new_symbol_expr ($1), $2); - } - ; - opt_expr : comma_expr | /* empty */ @@ -1592,16 +1544,16 @@ unary_expr | '&' cast_expr %prec UNARY { $$ = address_expr ($2, 0); } | '*' cast_expr %prec UNARY { $$ = deref_pointer_expr ($2); } | SIZEOF unary_expr %prec UNARY { $$ = sizeof_expr ($2, 0); } - | SIZEOF '(' abstract_decl ')' %prec HYPERUNARY + | SIZEOF '(' typename ')' %prec HYPERUNARY { - $$ = sizeof_expr (0, $3->type); + $$ = sizeof_expr (0, $3.type); } | vector_expr { $$ = new_vector_list ($1); } | obj_expr { $$ = $1; } ; ident_expr - : OBJECT { $$ = new_symbol_expr ($1); } + : OBJECT_NAME { $$ = new_symbol_expr ($1.sym); } | CLASS_NAME { $$ = new_symbol_expr ($1); } | TYPE_NAME { $$ = new_symbol_expr ($1.sym); } ; @@ -1618,9 +1570,9 @@ vector_expr ; cast_expr - : '(' abstract_decl ')' cast_expr + : '(' typename ')' cast_expr { - $$ = cast_expr ($2->type, $4); + $$ = cast_expr ($2.type, $4); } | unary_expr %prec LOW ; @@ -1712,7 +1664,7 @@ string identifier : NAME - | OBJECT + | OBJECT_NAME { $$ = $1.sym; } | CLASS_NAME | TYPE_NAME { $$ = $1.sym; } ; @@ -1890,8 +1842,6 @@ classdef END { current_class = 0; - (void) ($6); - (void) ($9); } | INTERFACE new_class_name protocolrefs { class_add_protocols ($2, $3); } @@ -1903,7 +1853,6 @@ classdef END { current_class = 0; - (void) ($5); } | INTERFACE new_class_with_super protocolrefs { class_add_protocols ($2, $3);} @@ -1917,8 +1866,6 @@ classdef END { current_class = 0; - (void) ($6); - (void) ($9); } | INTERFACE new_class_with_super protocolrefs { class_add_protocols ($2, $3); } @@ -1930,7 +1877,6 @@ classdef END { current_class = 0; - (void) ($5); } | INTERFACE new_category_name protocolrefs @@ -1942,14 +1888,12 @@ classdef END { current_class = 0; - (void) ($4); } | IMPLEMENTATION class_name { class_begin (&$2->class_type); } '{' { $$ = $2; } ivar_decl_list '}' { class_check_ivars ($2, $6); - (void) ($5); } | IMPLEMENTATION class_name { class_begin (&$2->class_type); } | IMPLEMENTATION class_with_super { class_begin (&$2->class_type); } @@ -1957,7 +1901,6 @@ classdef ivar_decl_list '}' { class_check_ivars ($2, $6); - (void) ($5); } | IMPLEMENTATION class_with_super { class_begin (&$2->class_type); } | IMPLEMENTATION category_name { class_begin (&$2->class_type); } @@ -1984,7 +1927,6 @@ protocoldef END { current_class = $1; - (void) ($4); } ; @@ -1995,7 +1937,7 @@ protocol protocolrefs : /* emtpy */ { $$ = 0; } | LT { $$ = new_protocol_list (); } - protocol_list GT { $$ = $3; (void) ($2); } + protocol_list GT { $$ = $3; } ; protocol_list @@ -2059,11 +2001,10 @@ ivar_decls ; ivar_decl - : type ivars - | type + : declspecs_nosc_ts ivars + | declspecs_nosc_ts { if (is_anonymous_struct ($1)) { - // anonymous struct/union // type->name always begins with "tag " $1.sym = new_symbol (va (0, ".anonymous.%s", $1.type->name + 4)); @@ -2074,20 +2015,47 @@ ivar_decl if (!$1.sym->table) { error (0, "duplicate field `%s'", $1.sym->name); } - } else { - // bare type - warning (0, "declaration does not declare anything"); } } + | declspecs_nosc_nots notype_ivars ; ivars - : struct_decl - | ivars ',' { $$ = $0; } struct_decl { (void) ($3); } + : ivar_declarator { } + | ivars ',' { $$ = $0; } ivar_declarator + ; + +notype_ivars + : notype_ivar_declarator { } + | notype_ivars ',' { $$ = $0; } + notype_ivar_declarator + ; + +ivar_declarator + : declarator + { + symbol_t *s = $1.sym; + specifier_t spec = default_type ($1, s); + s->type = find_type (spec.type); + s->sy_type = sy_var; + s->visibility = current_visibility; + symtab_addsymbol (current_symtab, s); + if (!s->table) { + error (0, "duplicate field `%s'", s->name); + } + } + | declarator ':' expr + | ':' expr + ; + +notype_ivar_declarator + : notype_declarator { internal_error (0, "not implemented"); } + | notype_declarator ':' expr + | ':' expr ; methoddef - : ci methoddecl optional_state_expr + : ci methoddecl ose { method_t *method = $2; @@ -2176,24 +2144,19 @@ methodproto ; methoddecl - : '(' abstract_decl ')' unaryselector - { $$ = new_method ($2->type, $4, 0); } + : '(' typename ')' unaryselector + { $$ = new_method ($2.type, $4, 0); } | unaryselector { $$ = new_method (&type_id, $1, 0); } - | '(' abstract_decl ')' keywordselector optional_param_list - { $$ = new_method ($2->type, $4, $5); } + | '(' typename ')' keywordselector optional_param_list + { $$ = new_method ($2.type, $4, $5); } | keywordselector optional_param_list { $$ = new_method (&type_id, $1, $2); } ; optional_param_list : /* empty */ { $$ = 0; } - | ',' ELLIPSIS { $$ = new_param (0, 0, 0); } | ',' param_list { $$ = $2; } - | ',' param_list ',' ELLIPSIS - { - $$ = param_append_identifiers ($2, 0, 0); - } ; unaryselector @@ -2212,7 +2175,7 @@ protocol_name_list selector : NAME { $$ = $1; } | CLASS_NAME { $$ = $1; } - | OBJECT { $$ = new_symbol (qc_yytext); } + | OBJECT_NAME { $$ = new_symbol (qc_yytext); } | TYPE_SPEC { $$ = new_symbol (qc_yytext); } | TYPE_NAME { $$ = $1.sym; } | reserved_word @@ -2238,12 +2201,12 @@ reserved_word ; keyworddecl - : selector ':' '(' abstract_decl ')' identifier - { $$ = new_param ($1->name, $4->type, $6->name); } + : selector ':' '(' typename ')' identifier + { $$ = new_param ($1->name, $4.type, $6->name); } | selector ':' identifier { $$ = new_param ($1->name, &type_id, $3->name); } - | ':' '(' abstract_decl ')' identifier - { $$ = new_param ("", $3->type, $5->name); } + | ':' '(' typename ')' identifier + { $$ = new_param ("", $3.type, $5->name); } | ':' identifier { $$ = new_param ("", &type_id, $2->name); } ; @@ -2252,7 +2215,7 @@ obj_expr : obj_messageexpr | SELECTOR '(' selectorarg ')' { $$ = selector_expr ($3); } | PROTOCOL '(' identifier ')' { $$ = protocol_expr ($3->name); } - | ENCODE '(' abstract_decl ')' { $$ = encode_expr ($3->type); } + | ENCODE '(' typename ')' { $$ = encode_expr ($3.type); } | obj_string /* FIXME string object? */ ; diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index db5b05352..fbfcb02c5 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -98,6 +98,33 @@ find_tag (ty_meta_e meta, symbol_t *tag, type_t *type) return sym; } +symtab_t * +start_struct (int *su, symbol_t *tag, symtab_t *parent) +{ + symbol_t *sym; + sym = find_struct (*su, tag, 0); + if (!sym->table) { + symtab_addsymbol (parent, sym); + } else { + if (!sym->type) { + internal_error (0, "broken structure symbol?"); + } + if (tag) { + tag->type = sym->type; + } + if (sym->type->meta == ty_enum + || (sym->type->meta == ty_struct && sym->type->t.symtab)) { + error (0, "%s %s redefined", + *su == 's' ? "struct" : "union", tag->name); + *su = 0; + } else if (sym->type->meta != ty_struct) { + internal_error (0, "%s is not a struct or union", + tag->name); + } + } + return new_symtab (parent, stab_struct); +} + symbol_t * find_struct (int su, symbol_t *tag, type_t *type) { diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 49fc4fa0d..ca6fe4bc4 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -44,6 +44,7 @@ #include "tools/qfcc/include/function.h" #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/reloc.h" +#include "tools/qfcc/include/shared.h" #include "tools/qfcc/include/strpool.h" #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" @@ -243,3 +244,56 @@ make_symbol (const char *name, type_t *type, defspace_t *space, sym->sy_type = sy_var; return sym; } + +symbol_t * +declare_symbol (specifier_t spec, expr_t *init, symtab_t *symtab) +{ + symbol_t *s = spec.sym; + defspace_t *space = symtab->space; + + if (s->table) { + // due to the way declarations work, we need a new symbol at all times. + // redelcarations will be checked later + s = new_symbol (s->name); + } + + spec = default_type (spec, s); + if (!spec.storage) { + spec.storage = current_storage; + } + if (spec.storage == sc_static) { + space = pr.near_data; + } + + //FIXME is_function is bad (this whole implementation of handling + //function prototypes is bad) + if (spec.is_function && is_func (spec.type)) { + set_func_type_attrs (spec.type, spec); + } + s->type = spec.type; + + if (spec.is_typedef) { + if (init) { + error (0, "typedef %s is initialized", s->name); + } + s->sy_type = sy_type; + s->type = find_type (s->type); + s->type = find_type (alias_type (s->type, s->type, s->name)); + symtab_addsymbol (symtab, s); + } else { + if (spec.is_function && is_func (s->type)) { + if (init) { + error (0, "function %s is initialized", s->name); + } + s->type = find_type (s->type); + s = function_symbol (s, spec.is_overload, 1); + } else { + s->type = find_type (s->type); + initialize_def (s, init, space, spec.storage, symtab); + if (s->s.def) { + s->s.def->nosave |= spec.nosave; + } + } + } + return s; +} diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 61918d220..99916d604 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -436,6 +436,82 @@ types_same (type_t *a, type_t *b) internal_error (0, "we be broke"); } +void +set_func_type_attrs (type_t *func, specifier_t spec) +{ + func->t.func.no_va_list = spec.no_va_list; + func->t.func.void_return = spec.void_return; +} + +specifier_t +default_type (specifier_t spec, symbol_t *sym) +{ + if (spec.type) { + if (is_float (spec.type) && !spec.multi_type) { + // no modifieres allowed + if (spec.is_unsigned) { + spec.multi_type = 1; + error (0, "both unsigned and float in declaration specifiers"); + } else if (spec.is_signed) { + spec.multi_type = 1; + error (0, "both signed and float in declaration specifiers"); + } else if (spec.is_short) { + spec.multi_type = 1; + error (0, "both short and float in declaration specifiers"); + } else if (spec.is_long) { + spec.multi_type = 1; + error (0, "both long and float in declaration specifiers"); + } + } + if (is_double (spec.type)) { + // long is allowed but ignored + if (spec.is_unsigned) { + spec.multi_type = 1; + error (0, "both unsigned and double in declaration specifiers"); + } else if (spec.is_signed) { + spec.multi_type = 1; + error (0, "both signed and double in declaration specifiers"); + } else if (spec.is_short) { + spec.multi_type = 1; + error (0, "both short and double in declaration specifiers"); + } + } + if (is_int (spec.type)) { + // signed and short are ignored + if (spec.is_unsigned && spec.is_long) { + spec.type = &type_ulong; + } else if (spec.is_long) { + spec.type = &type_long; + } + } + } else { + if (spec.is_long) { + if (spec.is_unsigned) { + spec.type = type_ulong_uint; + } else { + spec.type = type_long_int; + } + } else { + if (spec.is_unsigned) { + spec.type = &type_uint; + } else if (spec.is_signed || spec.is_short) { + spec.type = &type_int; + } + } + } + if (!spec.type) { + spec.type = type_default; + if (sym) { + warning (0, "type defaults to '%s' in declaration of '%s'", + type_default->name, sym->name); + } else { + warning (0, "type defaults to '%s' in abstract declaration", + type_default->name); + } + } + return spec; +} + /* find_type diff --git a/tools/qfcc/test/state.r b/tools/qfcc/test/state.r index 839061e8c..9eca8b7eb 100644 --- a/tools/qfcc/test/state.r +++ b/tools/qfcc/test/state.r @@ -10,7 +10,7 @@ $frame frame0 frame1 frame2 frame3 void state0 (void) -[$frame1, state1] +>> [$frame1, state1] { if (self.frame != $frame1 || self.think != state1 || self.nextthink != 0.1f) { @@ -21,7 +21,7 @@ state0 (void) void state1 (void) -[$frame2, state2, 0.2f] +>> [$frame2, state2, 0.2f] { if (self.frame != $frame2 || self.think != state2 || self.nextthink != 0.2f) { @@ -32,7 +32,7 @@ state1 (void) void state2 (void) -[$frame0, state0, 0.5f] +>> [$frame0, state0, 0.5f] { if (self.frame != $frame0 || self.think != state0 || self.nextthink != 0.5f) { From 35df90cb3f03c10edef2dbfe9f3b6ede88600849 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Feb 2023 14:43:02 +0900 Subject: [PATCH 3373/3664] [ruamoko] Add qfot_basic_t to qfot_type_t qfot_basic_t is necessary for getting at the width of basic value types (int, uint, float, long, ulong, double) in order to distinguish between scalars and vectors of those types. I had forgotten this when doing the Ruamoko VM and qfcc changes. --- ruamoko/include/types.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index 2ff8a123e..6316ecb12 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -30,6 +30,11 @@ typedef struct qfot_fldptr_s { struct qfot_type_s *aux_type; } qfot_fldptr_t; +typedef struct qfot_basic_s { + etype_t type; + int width; +} qfot_basic_t; + typedef struct qfot_func_s { etype_t type; struct qfot_type_s *return_type; @@ -61,6 +66,7 @@ typedef struct qfot_type_s { string encoding; union { etype_t type; + qfot_basic_t basic; qfot_fldptr_t fldptr; qfot_func_t func; qfot_struct_t strct; From d5b93c20b39e3d94c7100b6d996d2f66ef0d8bec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Feb 2023 00:51:06 +0900 Subject: [PATCH 3374/3664] [plist] Pass array index/label to the parse function I ran into the need to get at the label of labeled array element and the best way seemed to be by setting the name field of the plfield_t item passed to the parser function, and then found that PL_ParseSymtab already does this. I then decided passing the array index would also be good, and the offset field made sense. --- include/QF/plist.h | 10 ++++++++++ libs/util/plist.c | 3 +++ 2 files changed, 13 insertions(+) diff --git a/include/QF/plist.h b/include/QF/plist.h index 9e68ed0bb..a663b0344 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -107,6 +107,16 @@ typedef int (*plparser_t) (const struct plfield_s *field, point to a \a plelement_t object. This allows all the parse functions to be used directly as either a \a plfield_t or \a plelement_t object's \a parser. + + \a PL_ParseLabeledArray and \a PL_ParseSymtab pass to the parser a field + with \a name set to the key of the current item and \a offset set to 0. + For \a PL_ParseArray, \a name is set to null and \a offset is set to the + current index. \a PL_ParseLabeledArray also sets \a offset to the current + index. \a type, \a parser, and \a data are taken from the \a plelement_t + passed in to them. + + \a PL_ParseStruct passes the currently parsed field without any + modifications. */ typedef struct plfield_s { const char *name; ///< matched by dictionary key diff --git a/libs/util/plist.c b/libs/util/plist.c index be3cc2d47..9f4ca3292 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -1330,6 +1330,7 @@ PL_ParseArray (const plfield_t *field, const plitem_t *array, void *data, plitem_t *item = plarray->values[i]; void *eledata = &arr->a[i * element->stride]; + f.offset = i; if (!PL_CheckType (element->type, item->type)) { char index[16]; snprintf (index, sizeof(index) - 1, "%d", i); @@ -1381,6 +1382,8 @@ PL_ParseLabeledArray (const plfield_t *field, const plitem_t *item, plitem_t *item = current->value; void *eledata = &arr->a[i * element->stride]; + f.name = current->key; + f.offset = i; if (!PL_CheckType (element->type, item->type)) { char index[16]; snprintf (index, sizeof(index) - 1, "%zd", i); From 9706d2d9ce62193fd1a781b307b1b19039893e7c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Feb 2023 10:57:55 +0900 Subject: [PATCH 3375/3664] [plist] Fix a typo in a comment --- include/QF/plist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/plist.h b/include/QF/plist.h index a663b0344..46179bdc5 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -234,7 +234,7 @@ const char *PL_KeyAtIndex (const plitem_t *dict, int index) __attribute__((pure) \param array The array to get the value from \param index The index within the array to retrieve \return the value at the specified index, or NULL if \a index is out of - range or \a array is not an array (includes in \a array is null). + range or \a array is not an array (includes if \a array is null). \note You are NOT responsible for freeing the returned object. It will be destroyed when its container is. */ From cb99c4d907ed2ef6f9b0045bb997751c2f36e31e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 01:11:45 +0900 Subject: [PATCH 3376/3664] [cexpr] Support casts from plist to vector This makes specifying colors in the vulkan parser a lot easier. --- libs/util/cexpr-type.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 97c15606f..369195d05 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -582,6 +582,7 @@ binop_t vector_binops[] = { { '%', &cexpr_vector, &cexpr_vector, vector_rem }, { MOD, &cexpr_vector, &cexpr_vector, vector_mod }, { '.', &cexpr_field, &cexpr_exprval, vector_swizzle }, + { '=', &cexpr_plitem, &cexpr_vector, cexpr_cast_plitem }, {} }; From 65e15c2dd078bbf6bcc9b100b9a83f1432c8cccb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 12:17:23 +0900 Subject: [PATCH 3377/3664] [cexpr] Keep track of unidentified symbol names At least with a push-parser, by the time the parser has figured out it has an identifier, the lexer has forgotten the token, thus the annoying and uninformative "undefined identifier " error messages. Since identifiers should always have a value (and functions need a function type), setting up a dummy symbol with just the identifier name duplicated seems to do the trick. It is a bit wasteful of memory if there are a lot of such errors between cmem resets, though. --- libs/util/cexpr-lex.l | 7 +++++++ libs/util/cexpr-parse.y | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index 28551b1dc..88dced412 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -312,6 +312,13 @@ parse_name (const char *name, exprctx_t *context) sym = Hash_Find (symtab->tab, name); } + if (!sym) { + sym = cmemalloc (context->memsuper, sizeof (exprsym_t)); + size_t size = strlen (name) + 1; + char *sym_name = cmemalloc (context->memsuper, size); + memcpy (sym_name, name, size); + *sym = (exprsym_t) { .name = sym_name }; + } return sym; } diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index 4b8155b45..caf460f05 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -113,13 +113,13 @@ start uexpr : NAME { - if ($1) { + if ($1->value) { $$ = (exprval_t *) cmemalloc (context->memsuper, sizeof (*$$)); $$->type = $1->type; $$->value = $1->value; } else { - cexpr_error (context, "undefined identifier %s", - cexpr_yyget_text (scanner)); + cexpr_error (context, "undefined identifier %s", $1->name); + $$ = 0; } } | VALUE From bc2204d4461630185f28fb017b8f97357e4469c7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 14:38:37 +0900 Subject: [PATCH 3378/3664] [qfcc] Differentiate symtabs by intended use The symtab code itself cares only about global/not global for the size of the hash table, but other code can use the symtab type for various checks (eg, parameter shadowing). --- tools/qfcc/include/symtab.h | 9 +++++++-- tools/qfcc/source/class.c | 6 +++--- tools/qfcc/source/function.c | 4 ++-- tools/qfcc/source/struct.c | 2 +- tools/qfcc/source/symtab.c | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index 125f77203..6dc2b2fa0 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -84,10 +84,13 @@ typedef struct symbol_s { typedef enum { stab_global, ///< global (many symbols) + stab_param, ///< local (few symbols: func) stab_local, ///< local (few symbols: func) + stab_ivars, stab_struct, stab_union, stab_enum, + stab_label, } stab_type_e; typedef struct symtab_s { @@ -131,7 +134,7 @@ symbol_t *new_symbol_type (const char *name, struct type_s *type); supports both code block scoping and ivar inheritance. \param parent Pointer to parent scope symbol table. - \param type The type of symbol table. Currently governs expected size. + \param type The type of symbol table. \return The new, empty symbol table. */ symtab_t *new_symtab (symtab_t *parent, stab_type_e type); @@ -194,6 +197,7 @@ symbol_t *copy_symbol (symbol_t *symbol); \param symtab The symbol table chain to be copied. \param parent The parent symbol table of the new symbol table, or null. + \param type The type of symbol table. \return The new symbol table. \dot @@ -221,7 +225,8 @@ symbol_t *copy_symbol (symbol_t *symbol); } \enddot */ -symtab_t *symtab_flat_copy (symtab_t *symtab, symtab_t *parent); +symtab_t *symtab_flat_copy (symtab_t *symtab, symtab_t *parent, + stab_type_e type); /** Create a global symbol and allocate space for a variable. diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 5be3015d9..deb17d471 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -1320,7 +1320,7 @@ class_new_ivars (class_t *class) if (class->super_class) super_ivars = class->super_class->ivars; - ivars = new_symtab (super_ivars, stab_local); + ivars = new_symtab (super_ivars, stab_ivars); ivars->class = class; return ivars; } @@ -1903,7 +1903,7 @@ class_to_struct (class_t *class, symtab_t *symtab) // connect the ivars symbol table chain to the struct symbol table ancestor->parent = symtab; // create a new struct symbol table from the ivars symbol table chain - symtab = symtab_flat_copy (ivars, 0); + symtab = symtab_flat_copy (ivars, 0, stab_struct); // disconnect the ivars symbol table chain ancestor->parent = 0; // connect the new struct symbol table to the scope @@ -1917,7 +1917,7 @@ class_ivar_scope (class_type_t *class_type, symtab_t *parent) class_t *class = extract_class (class_type); if (!class->ivars) return 0; - return symtab_flat_copy (class->ivars, parent); + return symtab_flat_copy (class->ivars, parent, stab_ivars); } static expr_t * diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 7e89d8fd4..6ed067765 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -598,9 +598,9 @@ build_scope (symbol_t *fsym, symtab_t *parent) check_function (fsym); - fsym->s.func->label_scope = new_symtab (0, stab_local); + fsym->s.func->label_scope = new_symtab (0, stab_label); - parameters = new_symtab (parent, stab_local); + parameters = new_symtab (parent, stab_param); parameters->space = defspace_new (ds_virtual); fsym->s.func->parameters = parameters; diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index fbfcb02c5..8f4dc6b70 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -220,7 +220,7 @@ start_enum (symbol_t *sym) error (0, "%s defined as wrong kind of tag", sym->name); sym = find_enum (0); } - sym->type->t.symtab = new_symtab (current_symtab, stab_local); + sym->type->t.symtab = new_symtab (current_symtab, stab_enum); sym->type->alignment = 1; sym->type->width = 1; return sym->type->t.symtab; diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index ca6fe4bc4..6470d2682 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -178,13 +178,13 @@ copy_symbol (symbol_t *symbol) } symtab_t * -symtab_flat_copy (symtab_t *symtab, symtab_t *parent) +symtab_flat_copy (symtab_t *symtab, symtab_t *parent, stab_type_e type) { symtab_t *newtab; symbol_t *newsym; symbol_t *symbol; - newtab = new_symtab (parent, stab_local); + newtab = new_symtab (parent, type); do { for (symbol = symtab->symbols; symbol; symbol = symbol->next) { if (symbol->visibility == vis_anonymous From a2b5ebde65b017c61944d7c752eb9fb68adaed38 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 14:44:55 +0900 Subject: [PATCH 3379/3664] [qfcc] Treat parameter shadowing as an error This applies only to the top-level scope of the function. I'm not sure if it's right for traditional quakec code, but that can be adjusted easily enough. --- tools/qfcc/source/def.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 76286dce6..f87803f2c 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -536,6 +536,10 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, symbol_t *check = symtab_lookup (symtab, sym->name); reloc_t *relocs = 0; + if (check && symtab->parent && check->table == symtab->parent->parent + && symtab->parent->parent->type == stab_param) { + error (0, "%s shadows a parameter", sym->name); + } if (check && check->table == symtab) { if (check->sy_type != sy_var || !type_same (check->type, sym->type)) { error (0, "%s redefined", sym->name); From 67eb38173b859a436b85f53dc7d329283e2ecb64 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 15:29:16 +0900 Subject: [PATCH 3380/3664] [qfcc] Back out incorrect precedence check changes The precedence check changes done in 63795e790bef3b202c3c1baa3174c3c0d42821ea seem to have been incorrect (game-source/ctf produced many false positives), so putting that check against '=' back into the code seems like a good idea (no more false positives). That sounds a bit cargo-cult, but I'm really not sure what I was thinking when I did the changes (probably just tired). --- tools/qfcc/source/expr_binary.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 1f6d64a3b..1836d3e9c 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -950,7 +950,7 @@ check_precedence (int op, expr_t *e1, expr_t *e2) { if (e1->type == ex_uexpr && e1->e.expr.op == '!' && !e1->paren) { if (options.traditional) { - if (op != AND && op != OR) { + if (op != AND && op != OR && op != '=') { notice (e1, "precedence of `!' and `%s' inverted for " "traditional code", get_op_string (op)); e1->e.expr.e1->paren = 1; @@ -967,7 +967,8 @@ check_precedence (int op, expr_t *e1, expr_t *e2) if (e2->type == ex_expr && !e2->paren) { if (((op == '&' || op == '|') && (is_math_op (e2->e.expr.op) || is_compare (e2->e.expr.op))) - || (e2->e.expr.op == OR || e2->e.expr.op == AND)) { + || (op == '=' + &&(e2->e.expr.op == OR || e2->e.expr.op == AND))) { notice (e1, "precedence of `%s' and `%s' inverted for " "traditional code", get_op_string (op), get_op_string (e2->e.expr.op)); @@ -988,7 +989,8 @@ check_precedence (int op, expr_t *e1, expr_t *e2) } else if (e1->type == ex_expr && !e1->paren) { if (((op == '&' || op == '|') && (is_math_op (e1->e.expr.op) || is_compare (e1->e.expr.op))) - || (e1->e.expr.op == OR || e1->e.expr.op == AND)) { + || (op == '=' + &&(e2->e.expr.op == OR || e2->e.expr.op == AND))) { notice (e1, "precedence of `%s' and `%s' inverted for " "traditional code", get_op_string (op), get_op_string (e1->e.expr.op)); From b7ad02c71d87fdb513ee758864805c1113f4890d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 20:11:46 +0900 Subject: [PATCH 3381/3664] [qfcc] Use float for v6 comparisons While simple types used floats, functions, vectors and entities used ints. This doesn't go so well when compiling for v6 progs. --- tools/qfcc/source/expr_binary.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 1836d3e9c..8396d4149 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -796,6 +796,9 @@ func_compare (int op, expr_t *e1, expr_t *e2) new_alias_expr (&type_int, e2)); } e->e.expr.type = &type_int; + if (options.code.progsversion == PROG_ID_VERSION) { + e->e.expr.type = &type_float; + } return e; } @@ -814,6 +817,9 @@ vector_compare (int op, expr_t *e1, expr_t *e2) if (options.code.progsversion < PROG_VERSION) { expr_t *e = new_binary_expr (op, e1, e2); e->e.expr.type = &type_int; + if (options.code.progsversion == PROG_ID_VERSION) { + e->e.expr.type = &type_float; + } return e; } int hop = op == EQ ? '&' : '|'; @@ -903,6 +909,9 @@ entity_compare (int op, expr_t *e1, expr_t *e2) } expr_t *e = new_binary_expr (op, e1, e2); e->e.expr.type = &type_int; + if (options.code.progsversion == PROG_ID_VERSION) { + e->e.expr.type = &type_float; + } return e; } From fa97074aff8c956f3053692e3e5a1585cf76b1ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 20:13:44 +0900 Subject: [PATCH 3382/3664] [qfcc] Update vector constant folding checks Internally, * is not really a valid operator for vectors since it can have many meanings. This didn't cause trouble until trying to build everything in game-source (since there's still a lot of legacy code in there). --- tools/qfcc/source/constfold.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index 02a0b3cd8..e52294f05 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -394,13 +394,15 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) { const float *v1, *v2; vec3_t v, float_vec; - static int valid[] = {'+', '-', '*', HADAMARD, SCALE, EQ, NE, 0}; + static int vv_valid[] = {'+', '-', DOT, HADAMARD, EQ, NE, 0}; + static int vs_valid[] = {SCALE, 0}; + static int sv_valid[] = {SCALE, '/', 0}; expr_t *t; if (!is_vector(get_type (e1))) { - if (op != '*') - return error (e1, "invalid operator for vector"); + if (!valid_op (op, sv_valid)) + return error (e1, "invalid operator for scalar-vector"); t = e1; e->e.expr.e1 = e1 = e2; @@ -408,10 +410,10 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) } if (!is_vector(get_type (e2))) { e->e.expr.e2 = e2 = convert_to_float (e2); - if (op != SCALE && op != '/') + if (!valid_op (op, vs_valid)) return error (e1, "invalid operator for vector"); } else { - if (!valid_op (op, valid)) + if (!valid_op (op, vv_valid)) return error (e1, "invalid operator for vector"); } if (is_compare (op) || is_logic (op)) { @@ -419,7 +421,7 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_int; else e->e.expr.type = &type_float; - } else if (op == '*' && is_vector(get_type (e2))) { + } else if (op == DOT && is_vector(get_type (e2))) { e->e.expr.type = &type_float; } else if (op == '/' && !is_constant (e1)) { e2 = fold_constants (binary_expr ('/', new_float_expr (1), e2)); @@ -428,9 +430,9 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) e->e.expr.type = &type_vector; } - if (op == '*' && is_float_val (e2) && expr_float (e2) == 1) + if (op == SCALE && is_float_val (e2) && expr_float (e2) == 1) return e1; - if (op == '*' && is_float_val (e2) && expr_float (e2) == 0) + if (op == SCALE && is_float_val (e2) && expr_float (e2) == 0) return new_vector_expr (vec3_origin); if (op == '/' && is_float_val (e2) && expr_float (e2) == 1) return e1; @@ -483,13 +485,12 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2) VectorScale (v1, 1 / v2[0], v); e = new_vector_expr (v); break; - case '*': - if (is_vector(get_type (e2))) { - e = new_float_expr (DotProduct (v1, v2)); - } else { - VectorScale (v1, v2[0], v); - e = new_vector_expr (v); - } + case DOT: + e = new_float_expr (DotProduct (v1, v2)); + break; + case SCALE: + VectorScale (v1, v2[0], v); + e = new_vector_expr (v); break; case EQ: e = cmp_result_expr (VectorCompare (v1, v2)); From 3a297c70b3b30d3bbce310f814eebd9b6d3b7e87 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 20:23:23 +0900 Subject: [PATCH 3383/3664] [qfcc] Handle qc function field parameters The type system rewrite had lost some of the checks for function fields. This puts the actual code in the one place and covers parameters as well as globals. --- tools/qfcc/include/function.h | 2 ++ tools/qfcc/source/function.c | 20 ++++++++++++++++++++ tools/qfcc/source/qc-parse.y | 26 +++++--------------------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index aeb70f1b0..a82714259 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -149,6 +149,8 @@ param_t *reverse_params (param_t *params); param_t *append_params (param_t *params, param_t *more_params); param_t *copy_params (param_t *params); struct type_s *parse_params (struct type_s *return_type, param_t *params); +struct specifier_s parse_qc_params (struct specifier_s spec, param_t *params); + param_t *check_params (param_t *params); enum storage_class_e; diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 6ed067765..296ecf9fe 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -218,6 +218,26 @@ parse_params (type_t *return_type, param_t *parms) return new; } +specifier_t +parse_qc_params (specifier_t spec, param_t *params) +{ + type_t **type; + // .float () foo; is a field holding a function variable rather + // than a function that returns a float field. + for (type = &spec.type; *type && is_field (*type); + type = &(*type)->t.fldptr.type) { + } + type_t *ret_type = *type; + *type = 0; + *type = parse_params (ret_type, params); + set_func_type_attrs ((*type), spec); + if (spec.type->type != ev_field) { + spec.is_function = 1; //FIXME do proper void(*)() -> ev_func + spec.params = params; + } + return spec; +} + param_t * check_params (param_t *params) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 31191a8e8..994741ce6 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -423,21 +423,7 @@ datadef | declspecs_ts qc_func_params { specifier_t spec = default_type ($1, 0); - type_t **type; - // .float () foo; is a field holding a function variable rather - // than a function that returns a float field. - for (type = &spec.type; *type && (*type)->type == ev_field; - type = &(*type)->t.fldptr.type) - ; - type_t *ret_type = *type; - *type = 0; - *type = parse_params (ret_type, $2); - set_func_type_attrs ((*type), spec); - if (spec.type->type != ev_field) { - spec.is_function = 1; //FIXME do proper void(*)() -> ev_func - spec.params = $2; - } - $$ = spec; + $$ = parse_qc_params (spec, $2); } qc_func_decls | declspecs ';' @@ -476,9 +462,8 @@ qc_first_param } | typespec_reserved qc_func_params identifier { - specifier_t spec = default_type ($1, $3); - $3->params = $2; - spec.type = parse_params (spec.type, $2); + specifier_t spec = default_type ($1, 0); + spec = parse_qc_params (spec, $2); $$ = new_param (0, spec.type, $3->name); } @@ -492,9 +477,8 @@ qc_param } | typespec qc_func_params identifier { - specifier_t spec = default_type ($1, $3); - $3->params = $2; - spec.type = parse_params (spec.type, $2); + specifier_t spec = default_type ($1, 0); + spec = parse_qc_params (spec, $2); $$ = new_param (0, spec.type, $3->name); } From 3da7ca44216de9f9010c11dfe00dbf75370ff085 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 20:29:59 +0900 Subject: [PATCH 3384/3664] [qfcc] Support qc function local variables This had gotten completely lost in the rework. --- tools/qfcc/source/qc-parse.y | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 994741ce6..3cebea392 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -1259,6 +1259,16 @@ decl $$ = local_expr; local_expr = 0; } + | declspecs_ts local_expr qc_func_params + { + specifier_t spec = default_type ($1, 0); + $$ = parse_qc_params (spec, $3); + } + qc_func_decls + { + $$ = local_expr; + local_expr = 0; + } | declspecs ';' { $$ = 0; } ; From c16d0bae7bedaf9819436426aaf0abe87380cf63 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 20:31:08 +0900 Subject: [PATCH 3385/3664] [qfcc] Fix handling of storage class {...} blocks Another victim of the type system, but this one was due to the handling of storage classes in general. --- tools/qfcc/source/qc-parse.y | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 3cebea392..427d0eb4a 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -260,6 +260,12 @@ parse_attributes (attribute_t *attr_list) return spec; } +static int +storage_auto (specifier_t spec) +{ + return spec.storage == sc_global || spec.storage == sc_local; +} + static specifier_t spec_merge (specifier_t spec, specifier_t new) { @@ -275,8 +281,8 @@ spec_merge (specifier_t spec, specifier_t new) spec.multi_type = 1; } } - if (new.is_typedef || new.storage) { - if ((spec.is_typedef || spec.storage) && !spec.multi_store) { + if (new.is_typedef || !storage_auto (new)) { + if ((spec.is_typedef || !storage_auto (spec)) && !spec.multi_store) { error (0, "multiple storage classes in declaration specifiers"); spec.multi_store = 1; } @@ -774,16 +780,16 @@ typespec : typespec_reserved { $$ = $1; - //if (!$$.storage) { - // $$.storage = current_storage; - //} + if (!$$.storage) { + $$.storage = current_storage; + } } | typespec_nonreserved { $$ = $1; - //if (!$$.storage) { - // $$.storage = current_storage; - //} + if (!$$.storage) { + $$.storage = current_storage; + } } ; @@ -1566,7 +1572,7 @@ vector_expr cast_expr : '(' typename ')' cast_expr { - $$ = cast_expr ($2.type, $4); + $$ = cast_expr (find_type ($2.type), $4); } | unary_expr %prec LOW ; From 2748f1c9f7e44e3c5b08158e3ff06ac0189e90d0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Feb 2023 02:30:21 +0900 Subject: [PATCH 3386/3664] [ruamoko] Add support for PL_KeyAtIndex I'd forgotten to wrap the function when I added it, but didn't need it until now. --- libs/ruamoko/rua_plist.c | 13 +++++++++++++ ruamoko/include/PropertyList.h | 1 + ruamoko/include/plist.h | 1 + ruamoko/lib/PropertyList.r | 5 +++++ ruamoko/lib/plist.r | 1 + 5 files changed, 21 insertions(+) diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 36ec50b0c..f146dbb92 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -322,6 +322,18 @@ bi_PL_D_NumKeys (progs_t *pr, void *_res) R_INT (pr) = PL_D_NumKeys (plist->plitem); } +static void +bi_PL_KeyAtIndex (progs_t *pr, void *_res) +{ + plist_resources_t *res = _res; + int handle = P_INT (pr, 0); + int index = P_INT (pr, 1); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); + const char *key = PL_KeyAtIndex (plist->plitem, index); + + RETURN_STRING (pr, key); +} + static void bi_PL_D_AddObject (progs_t *pr, void *_res) { @@ -474,6 +486,7 @@ static builtin_t builtins[] = { bi(PL_ObjectAtIndex, 2, p(ptr), p(int)), bi(PL_D_AllKeys, 1, p(ptr)), bi(PL_D_NumKeys, 1, p(ptr)), + bi(PL_KeyAtIndex, 2, p(ptr), p(int)), bi(PL_D_AddObject, 3, p(ptr), p(string), p(ptr)), bi(PL_A_AddObject, 2, p(ptr), p(ptr)), bi(PL_A_NumObjects, 1, p(ptr)), diff --git a/ruamoko/include/PropertyList.h b/ruamoko/include/PropertyList.h index c61b16ef6..f6c059154 100644 --- a/ruamoko/include/PropertyList.h +++ b/ruamoko/include/PropertyList.h @@ -11,6 +11,7 @@ - (int) numKeys; - (PLItem *) getObjectForKey:(string) key; - (PLItem *) allKeys; +- (string) keyAtIndex:(int) index; - addKey:(string) key value:(PLItem *) value; @end diff --git a/ruamoko/include/plist.h b/ruamoko/include/plist.h index b99e1d19f..5482976fa 100644 --- a/ruamoko/include/plist.h +++ b/ruamoko/include/plist.h @@ -16,6 +16,7 @@ typedef enum {QFDictionary, QFArray, QFBinary, QFString} pltype_t; // possible t @extern plitem_t *PL_RemoveObjectForKey (plitem_t *item, string key); @extern plitem_t *PL_ObjectAtIndex (plitem_t *item, int index); @extern plitem_t *PL_D_AllKeys (plitem_t *item); +@extern string PL_KeyAtIndex (plitem_t *item, int index); @extern int PL_D_NumKeys (plitem_t *item); @extern int PL_D_AddObject (plitem_t *dict, string key, plitem_t *value); @extern int PL_A_AddObject (plitem_t *array_item, plitem_t *item); diff --git a/ruamoko/lib/PropertyList.r b/ruamoko/lib/PropertyList.r index 6197ec325..65e3b9124 100644 --- a/ruamoko/lib/PropertyList.r +++ b/ruamoko/lib/PropertyList.r @@ -128,6 +128,11 @@ return [[PLItem itemClass: PL_D_AllKeys (item)] autorelease]; } +- (string) keyAtIndex:(int) index +{ + return PL_KeyAtIndex (item, index); +} + - addKey:(string) key value:(PLItem *) value { if (!value.own) { diff --git a/ruamoko/lib/plist.r b/ruamoko/lib/plist.r index d1c0838bc..743602888 100644 --- a/ruamoko/lib/plist.r +++ b/ruamoko/lib/plist.r @@ -10,6 +10,7 @@ plitem_t *PL_ObjectForKey (plitem_t *item, string key) = #0; plitem_t *PL_RemoveObjectForKey (plitem_t *item, string key) = #0; plitem_t *PL_ObjectAtIndex (plitem_t *item, int index) = #0; plitem_t *PL_D_AllKeys (plitem_t *item) = #0; +string PL_KeyAtIndex (plitem_t *item, int index) = #0; int PL_D_NumKeys (plitem_t *item) = #0; int PL_D_AddObject (plitem_t *dict, string key, plitem_t *value) = #0; int PL_A_AddObject (plitem_t *array_item, plitem_t *item) = #0; From 6f429311c965b9b48b30e1583e2ba98f13bc6982 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Feb 2023 22:02:38 +0900 Subject: [PATCH 3387/3664] [cexpr] Use func instead of result type for end of list While the cexpr parser itself doesn't support void functions, they have their uses when used with the system, and mixing them into the list of function overloads shouldn't break non-void functions. --- libs/util/cexpr-parse.y | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/util/cexpr-parse.y b/libs/util/cexpr-parse.y index caf460f05..900073038 100644 --- a/libs/util/cexpr-parse.y +++ b/libs/util/cexpr-parse.y @@ -390,7 +390,10 @@ static exprval_t *function_expr (exprsym_t *fsym, exprlist_t *list, *(int *) result->value = 0; return result; } - for (exprfunc_t *f = fsym->value; f->result; f++) { + for (exprfunc_t *f = fsym->value; f->func; f++) { + if (!f->result) { + continue; + } int num_params = f->num_params; if (num_params >= 0 && num_args == num_params) { } else if (num_params < 0 && num_args >= ~num_params) { From d59dcba37d89c5785c2ec9990e9bcf7ef297e876 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Feb 2023 12:41:52 +0900 Subject: [PATCH 3388/3664] [qw] Update http_progress for recent curl CURLOPT_PROGRESSFUNCTION was deprecated in favor of CURLOPT_XFERINFOFUNCTION (and the parameters for the callback adjusted). I'm not sure why this didn't trigger until now. --- qw/source/cl_http.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qw/source/cl_http.c b/qw/source/cl_http.c index b13986cf2..6ee223943 100644 --- a/qw/source/cl_http.c +++ b/qw/source/cl_http.c @@ -47,8 +47,8 @@ static CURL *easy_handle; static CURLM *multi_handle; static int -http_progress (void *clientp, double dltotal, double dlnow, - double ultotal, double uplow) +http_progress (void *clientp, curl_off_t dltotal, curl_off_t dlnow, + curl_off_t ultotal, curl_off_t uplow) { return 0; //non-zero = abort } @@ -87,7 +87,7 @@ CL_HTTP_StartDownload (void) curl_easy_setopt (easy_handle, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt (easy_handle, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt (easy_handle, CURLOPT_PROGRESSFUNCTION, http_progress); + curl_easy_setopt (easy_handle, CURLOPT_XFERINFOFUNCTION, http_progress); curl_easy_setopt (easy_handle, CURLOPT_WRITEFUNCTION, http_write); curl_easy_setopt (easy_handle, CURLOPT_URL, cls.downloadurl->str); From e709eceb7596e51e0657446c79edeb9001faddc0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Jan 2023 17:30:25 +0900 Subject: [PATCH 3389/3664] [vulkan] Use matrices header in geometry shaders I had missed them earlier as I had forgotten about them (looked only at vertex shaders). --- libs/video/renderer/Makemodule.am | 6 +++--- libs/video/renderer/vulkan/shader/bsp_gbuf.geom | 10 ++++------ libs/video/renderer/vulkan/shader/particle.geom | 10 ++++------ 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index d21ecf882..ec158eaf2 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -366,7 +366,7 @@ pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc waterwarp_src = $(vkshaderpath)/waterwarp.frag waterwarp_c = $(vkshaderpath)/waterwarp.frag.spvc -$(slice_vert_c): $(slice_vert_src) $(matrices_h) +$(slice_c): $(slice_src) $(matrices_h) $(linev_c): $(linev_src) $(matrices_h) $(linef_c): $(linef_src) @@ -374,7 +374,7 @@ $(linef_c): $(linef_src) $(partphysicsc_c): $(partphysicsc_src) $(partupdatec_c): $(partupdatec_src) $(particlev_c): $(particlev_src) $(matrices_h) -$(particleg_c): $(particleg_src) +$(particleg_c): $(particleg_src) $(matrices_h) $(particlef_c): $(particlef_src) $(oit_store) $(oit_h) $(sprite_gbufv_c): $(sprite_gbufv_src) $(matrices_h) @@ -399,7 +399,7 @@ $(bsp_depth_c): $(bsp_depth_src) $(entity_h) $(matrices_h) $(bsp_gbufv_c): $(bsp_gbufv_src) $(entity_h) $(matrices_h) -$(bsp_gbufg_c): $(bsp_gbufg_src) +$(bsp_gbufg_c): $(bsp_gbufg_src) $(matrices_h) $(bsp_gbuff_c): $(bsp_gbuff_src) diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom index 15cb5a537..38bba91fa 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (triangles) in; layout (triangle_strip, max_vertices = 3) out; diff --git a/libs/video/renderer/vulkan/shader/particle.geom b/libs/video/renderer/vulkan/shader/particle.geom index 4669408ab..3027f0908 100644 --- a/libs/video/renderer/vulkan/shader/particle.geom +++ b/libs/video/renderer/vulkan/shader/particle.geom @@ -1,11 +1,9 @@ #version 450 +#extension GL_GOOGLE_include_directive : enable -layout (set = 0, binding = 0) uniform Matrices { - mat4 Projection3d; - mat4 View; - mat4 Sky; - mat4 Projection2d; -}; +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; layout (points) in; layout (triangle_strip, max_vertices = 4) out; From 25ac0ff3034184e74e9ae4ed603e520c6d60755d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 22 Jan 2023 19:23:15 +0900 Subject: [PATCH 3390/3664] [vulkan] Adapt the shaders for multi-view Multi-view will be used for shadows and fisheye. --- include/QF/Vulkan/qf_matrices.h | 2 +- libs/video/renderer/vulkan/shader/alias.vert | 3 ++- libs/video/renderer/vulkan/shader/alias_depth.vert | 3 ++- libs/video/renderer/vulkan/shader/bsp_depth.vert | 3 ++- libs/video/renderer/vulkan/shader/bsp_gbuf.geom | 3 ++- libs/video/renderer/vulkan/shader/iqm.vert | 3 ++- libs/video/renderer/vulkan/shader/matrices.h | 2 +- libs/video/renderer/vulkan/shader/particle.vert | 5 +++-- libs/video/renderer/vulkan/shader/quakebsp.vert | 3 ++- libs/video/renderer/vulkan/shader/sprite_depth.vert | 3 ++- libs/video/renderer/vulkan/shader/sprite_gbuf.vert | 3 ++- libs/video/renderer/vulkan/vulkan_matrices.c | 8 +++++--- 12 files changed, 26 insertions(+), 15 deletions(-) diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index 505bb1fe9..9b8e6d3b5 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -39,7 +39,7 @@ typedef struct qfv_matrix_buffer_s { // projection and view matrices (model is push constant) mat4f_t Projection3d; - mat4f_t View; + mat4f_t View[6]; mat4f_t Sky; mat4f_t Projection2d; vec2f_t ScreenSize; diff --git a/libs/video/renderer/vulkan/shader/alias.vert b/libs/video/renderer/vulkan/shader/alias.vert index ccfa78756..4309266f0 100644 --- a/libs/video/renderer/vulkan/shader/alias.vert +++ b/libs/video/renderer/vulkan/shader/alias.vert @@ -1,5 +1,6 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable layout (set = 0, binding = 0) uniform #include "matrices.h" @@ -30,7 +31,7 @@ main (void) vertex = mix (vertexa, vertexb, blend); norm = mix (normala, normalb, blend); pos = (Model * vertex); - gl_Position = Projection3d * (View * pos); + gl_Position = Projection3d * (View[gl_ViewIndex] * pos); position = pos; normal = normalize (mat3 (Model) * norm); st = uv; diff --git a/libs/video/renderer/vulkan/shader/alias_depth.vert b/libs/video/renderer/vulkan/shader/alias_depth.vert index 7f14e2ace..7d01354f3 100644 --- a/libs/video/renderer/vulkan/shader/alias_depth.vert +++ b/libs/video/renderer/vulkan/shader/alias_depth.vert @@ -1,5 +1,6 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable layout (set = 0, binding = 0) uniform #include "matrices.h" @@ -23,5 +24,5 @@ main (void) vertex = mix (vertexa, vertexb, blend); pos = (Model * vertex); - gl_Position = Projection3d * (View * pos); + gl_Position = Projection3d * (View[gl_ViewIndex] * pos); } diff --git a/libs/video/renderer/vulkan/shader/bsp_depth.vert b/libs/video/renderer/vulkan/shader/bsp_depth.vert index a3ab262ba..b454b8787 100644 --- a/libs/video/renderer/vulkan/shader/bsp_depth.vert +++ b/libs/video/renderer/vulkan/shader/bsp_depth.vert @@ -1,5 +1,6 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable #include "entity.h" @@ -18,5 +19,5 @@ void main (void) { vec3 vert = vertex * entities[entid].transform; - gl_Position = Projection3d * (View * vec4 (vert, 1)); + gl_Position = Projection3d * (View[gl_ViewIndex] * vec4 (vert, 1)); } diff --git a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom index 38bba91fa..f5a32ebd2 100644 --- a/libs/video/renderer/vulkan/shader/bsp_gbuf.geom +++ b/libs/video/renderer/vulkan/shader/bsp_gbuf.geom @@ -1,5 +1,6 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable layout (set = 0, binding = 0) uniform #include "matrices.h" @@ -28,7 +29,7 @@ main() for (int vert = 0; vert < 3; vert++) { vec4 p = gl_in[vert].gl_Position; - gl_Position = Projection3d * (View * (p)); + gl_Position = Projection3d * (View[gl_ViewIndex] * (p)); tl_st = v_tl_st[vert]; direction = v_direction[vert]; color = v_color[vert]; diff --git a/libs/video/renderer/vulkan/shader/iqm.vert b/libs/video/renderer/vulkan/shader/iqm.vert index a40d0ba70..4b5d06433 100644 --- a/libs/video/renderer/vulkan/shader/iqm.vert +++ b/libs/video/renderer/vulkan/shader/iqm.vert @@ -1,5 +1,6 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable layout (constant_id = 0) const bool IQMDepthOnly = false; @@ -40,7 +41,7 @@ main (void) m += bones[vbones.z] * vweights.z; m += bones[vbones.w] * vweights.w; vec4 pos = Model * vec4 (vec4(vposition, 1) * m, 1); - gl_Position = Projection3d * (View * pos); + gl_Position = Projection3d * (View[gl_ViewIndex] * pos); if (!IQMDepthOnly) { position = pos; diff --git a/libs/video/renderer/vulkan/shader/matrices.h b/libs/video/renderer/vulkan/shader/matrices.h index b5640cc3f..e66bc265b 100644 --- a/libs/video/renderer/vulkan/shader/matrices.h +++ b/libs/video/renderer/vulkan/shader/matrices.h @@ -1,6 +1,6 @@ Matrices { mat4 Projection3d; - mat4 View; + mat4 View[6]; mat4 Sky; mat4 Projection2d; diff --git a/libs/video/renderer/vulkan/shader/particle.vert b/libs/video/renderer/vulkan/shader/particle.vert index 40a35c2c3..4be3dec33 100644 --- a/libs/video/renderer/vulkan/shader/particle.vert +++ b/libs/video/renderer/vulkan/shader/particle.vert @@ -1,5 +1,6 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable layout (set = 0, binding = 0) uniform #include "matrices.h" @@ -23,8 +24,8 @@ void main (void) { // geometry shader will take care of Projection - gl_Position = View * (Model * position); - o_velocity = View * (Model * velocity); + gl_Position = View[gl_ViewIndex] * (Model * position); + o_velocity = View[gl_ViewIndex] * (Model * velocity); uint c = floatBitsToInt (color.x); uint x = c & 0x0f; uint y = (c >> 4) & 0x0f; diff --git a/libs/video/renderer/vulkan/shader/quakebsp.vert b/libs/video/renderer/vulkan/shader/quakebsp.vert index e93c0ea9e..d10bf89df 100644 --- a/libs/video/renderer/vulkan/shader/quakebsp.vert +++ b/libs/video/renderer/vulkan/shader/quakebsp.vert @@ -1,5 +1,6 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable #include "entity.h" @@ -23,7 +24,7 @@ void main (void) { vec3 vert = vertex * entities[entid].transform; - gl_Position = Projection3d * (View * vec4 (vert, 1)); + gl_Position = Projection3d * (View[gl_ViewIndex] * vec4 (vert, 1)); direction = (Sky * vertex).xyz; tl_st = tl_uv; color = entities[entid].color; diff --git a/libs/video/renderer/vulkan/shader/sprite_depth.vert b/libs/video/renderer/vulkan/shader/sprite_depth.vert index 20f6dc0d6..1eca8e043 100644 --- a/libs/video/renderer/vulkan/shader/sprite_depth.vert +++ b/libs/video/renderer/vulkan/shader/sprite_depth.vert @@ -1,5 +1,6 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable layout (set = 0, binding = 0) uniform #include "matrices.h" @@ -24,6 +25,6 @@ main (void) vec4 pos = Model[3]; pos += v.x * Model[1] + v.y * Model[2]; - gl_Position = Projection3d * (View * pos); + gl_Position = Projection3d * (View[gl_ViewIndex] * pos); st = v.zw; } diff --git a/libs/video/renderer/vulkan/shader/sprite_gbuf.vert b/libs/video/renderer/vulkan/shader/sprite_gbuf.vert index 1cdfb0f26..e96d25848 100644 --- a/libs/video/renderer/vulkan/shader/sprite_gbuf.vert +++ b/libs/video/renderer/vulkan/shader/sprite_gbuf.vert @@ -1,5 +1,6 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable layout (set = 0, binding = 0) uniform #include "matrices.h" @@ -26,7 +27,7 @@ main (void) vec4 pos = Model[3]; pos += v.x * Model[1] + v.y * Model[2]; - gl_Position = Projection3d * (View * pos); + gl_Position = Projection3d * (View[gl_ViewIndex] * pos); st = v.zw; position = pos; normal = -vec3(Model[0]); diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index e22f1ff3b..41f031e2b 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -103,8 +103,8 @@ Vulkan_SetViewMatrix (vulkan_ctx_t *ctx, mat4f_t view) { __auto_type mctx = ctx->matrix_context; - if (memcmp (mctx->matrices.View, view, sizeof (mat4f_t))) { - memcpy (mctx->matrices.View, view, sizeof (mat4f_t)); + if (memcmp (mctx->matrices.View[0], view, sizeof (mat4f_t))) { + memcpy (mctx->matrices.View[0], view, sizeof (mat4f_t)); mctx->dirty = mctx->frames.size; } } @@ -238,7 +238,9 @@ Vulkan_Matrix_Init (vulkan_ctx_t *ctx) mctx->sky_time = vr_data.realtime; mat4fidentity (mctx->matrices.Projection3d); - mat4fidentity (mctx->matrices.View); + for (int i = 0; i < 6; i++) { + mat4fidentity (mctx->matrices.View[i]); + } mat4fidentity (mctx->matrices.Sky); mat4fidentity (mctx->matrices.Projection2d); From 0cf341d1cbfa2e44f5ee74d94db1ed274ec5e370 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Jan 2023 11:01:06 +0900 Subject: [PATCH 3391/3664] [vulkan] Remove brush entity frustum culling It doesn't gain all that much and gets in the way of efficient cube-mapping. --- include/QF/Vulkan/qf_bsp.h | 1 - libs/video/renderer/vulkan/vulkan_bsp.c | 20 -------------------- 2 files changed, 21 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 3f3973033..2e9441711 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -268,7 +268,6 @@ typedef struct bsp_instance_s { typedef struct bsp_pass_s { vec4f_t position; ///< view position - plane_t *frustum; ///< view frustum for culling const struct mod_brush_s *brush;///< data for current model struct bspctx_s *bsp_context; ///< owning bsp context /** \name GPU data diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 5eed63d84..24ecb563b 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -589,26 +589,10 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) static int R_DrawBrushModel (entity_t ent, bsp_pass_t *pass, vulkan_ctx_t *ctx) { - transform_t transform = Entity_Transform (ent); renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); model_t *model = renderer->model; - float radius; - vec3_t mins, maxs; bspctx_t *bctx = ctx->bsp_context; - mat4f_t mat; - Transform_GetWorldMatrix (transform, mat); - if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) { - radius = model->radius; - if (R_CullSphere (pass->frustum, (vec_t*)&mat[3], radius)) { //FIXME - return 1; - } - } else { - VectorAdd (mat[3], model->mins, mins); - VectorAdd (mat[3], model->maxs, maxs); - if (R_CullBox (pass->frustum, mins, maxs)) - return 1; - } if (Vulkan_Scene_AddEntity (ctx, ent) < 0) { return 0; } @@ -687,9 +671,6 @@ test_node (const bsp_pass_t *pass, int node_id) return 0; if (pass->node_frames[node_id] != pass->vis_frame) return 0; - mnode_t *node = pass->brush->nodes + node_id; - if (R_CullBox (pass->frustum, node->minmaxs, node->minmaxs + 3)) - return 0; return 1; } @@ -1053,7 +1034,6 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) bctx->main_pass.bsp_context = bctx; bctx->main_pass.position = r_refdef.frame.position; - bctx->main_pass.frustum = r_refdef.frustum; bctx->main_pass.vis_frame = r_visframecount; bctx->main_pass.face_frames = r_face_visframes; bctx->main_pass.leaf_frames = r_leaf_visframes; From 4cb120e878512a2c9d82b52128978a373e2cfd22 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Jan 2023 11:14:06 +0900 Subject: [PATCH 3392/3664] [vulkan] Implement most of the changes for cube rendering There are some missing parts from this commit as these are the fairly clean changes. Missing is building a separate set of pipelines for the new render pass (might be able to get away from that), OIT heads texture is flat rather than an array, view matrices aren't set up, and the fisheye renderer isn't hooked up to the output pass (code exists but is messy). However, with the missing parts included, testing shows things mostly working: the cube map is rendered correctly even though it's not displayed correctly (incorrect view). This has definitely proven to be a good test for Vulkan's multiview feature (very nice). --- include/QF/Vulkan/qf_output.h | 2 + libs/video/renderer/Makemodule.am | 10 + libs/video/renderer/vulkan/device.c | 1 + libs/video/renderer/vulkan/pl_output.plist | 23 ++ libs/video/renderer/vulkan/rp_defcube.plist | 335 ++++++++++++++++++ libs/video/renderer/vulkan/shader.c | 3 + .../video/renderer/vulkan/shader/bsp_sky.frag | 2 + .../renderer/vulkan/shader/bsp_turb.frag | 2 + .../video/renderer/vulkan/shader/compose.frag | 2 + .../video/renderer/vulkan/shader/fisheye.frag | 30 ++ .../renderer/vulkan/shader/particle.frag | 2 + libs/video/renderer/vulkan/vkparse.c | 4 + libs/video/renderer/vulkan/vulkan_output.c | 3 + 13 files changed, 419 insertions(+) create mode 100644 libs/video/renderer/vulkan/rp_defcube.plist create mode 100644 libs/video/renderer/vulkan/shader/fisheye.frag diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index 48fde9f66..ef4ea0b1b 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -47,8 +47,10 @@ typedef struct outputctx_s { outputframeset_t frames; VkPipeline output; VkPipeline waterwarp; + VkPipeline fisheye; VkPipelineLayout output_layout; VkPipelineLayout warp_layout; + VkPipelineLayout fish_layout; VkSampler sampler; VkImageView input; } outputctx_t; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index ec158eaf2..cbf25d7c0 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -195,6 +195,8 @@ pl_quake_def_src = libs/video/renderer/vulkan/pl_quake_def.plist pl_quake_def_gen = libs/video/renderer/vulkan/pl_quake_def.plc pl_output_src = libs/video/renderer/vulkan/pl_output.plist pl_output_gen = libs/video/renderer/vulkan/pl_output.plc +rp_defcube_src = libs/video/renderer/vulkan/rp_defcube.plist +rp_defcube_gen = libs/video/renderer/vulkan/rp_defcube.plc rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist @@ -260,6 +262,7 @@ libs/video/renderer/vulkan/vkparse.lo: \ $(vkparse_src) \ $(pl_quake_def_gen) \ $(pl_output_gen) \ + ${rp_defcube_gen} \ ${rp_deferred_gen} \ $(rp_forward_gen) \ $(rp_output_gen) \ @@ -363,6 +366,8 @@ fstrianglest_src = $(vkshaderpath)/fstrianglest.vert fstrianglest_c = $(vkshaderpath)/fstrianglest.vert.spvc pushcolor_src = $(vkshaderpath)/pushcolor.frag pushcolor_c = $(vkshaderpath)/pushcolor.frag.spvc +fisheye_src = $(vkshaderpath)/fisheye.frag +fisheye_c = $(vkshaderpath)/fisheye.frag.spvc waterwarp_src = $(vkshaderpath)/waterwarp.frag waterwarp_c = $(vkshaderpath)/waterwarp.frag.spvc @@ -437,6 +442,8 @@ $(fstrianglest_c): $(fstrianglest_src) $(pushcolor_c): $(pushcolor_src) +$(fisheye_c): $(fisheye_src) $(matrices_h) + $(waterwarp_c): $(waterwarp_src) $(matrices_h) vkshader_c = \ @@ -479,6 +486,7 @@ vkshader_c = \ $(fstrianglest_c) \ $(pushcolor_c) \ $(shadow_c) \ + $(fisheye_c) \ $(waterwarp_c) V_VKGEN = $(V_VKGEN_@AM_V@) @@ -513,6 +521,7 @@ BUILT_SOURCES += $(shader_gen) EXTRA_DIST += \ libs/video/renderer/vulkan/vkparse.plist \ libs/video/renderer/vulkan/vkparse.h \ + $(rp_defcube_src) \ $(rp_deferred_src) \ $(rp_forward_src) \ $(rp_output_src) \ @@ -562,4 +571,5 @@ EXTRA_DIST += \ $(fstriangle_src) \ $(fstrianglest_src) \ $(pushcolor_src) \ + $(fisheye_src) \ $(waterwarp_src) diff --git a/libs/video/renderer/vulkan/device.c b/libs/video/renderer/vulkan/device.c index 0a43ce36b..5244a54fe 100644 --- a/libs/video/renderer/vulkan/device.c +++ b/libs/video/renderer/vulkan/device.c @@ -152,6 +152,7 @@ QFV_CreateDevice (vulkan_ctx_t *ctx, const char **extensions) VkPhysicalDeviceMultiviewFeatures multiview_features = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, .multiview = 1, + .multiviewGeometryShader = 1, }; VkPhysicalDeviceFeatures features = { .geometryShader = 1, diff --git a/libs/video/renderer/vulkan/pl_output.plist b/libs/video/renderer/vulkan/pl_output.plist index 2262d53f3..ab3b2e029 100644 --- a/libs/video/renderer/vulkan/pl_output.plist +++ b/libs/video/renderer/vulkan/pl_output.plist @@ -66,6 +66,16 @@ } ); }; + fisheye_layout = { + @inherit = $properties.pipelineLayouts.output_layout; + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "2 * 4"; + } + ); + }; }; depthStencil = { @@ -233,5 +243,18 @@ ); layout = waterwarp_layout; }; + fisheye = { + @inherit = $properties.pipelines.output_base; + subpass = 0; + stages = ( + $properties.fstriangle.vertexStageST, + { + stage = fragment; + name = main; + module = $builtin/fisheye.frag; + }, + ); + layout = fisheye_layout; + }; }; } diff --git a/libs/video/renderer/vulkan/rp_defcube.plist b/libs/video/renderer/vulkan/rp_defcube.plist new file mode 100644 index 000000000..98517f617 --- /dev/null +++ b/libs/video/renderer/vulkan/rp_defcube.plist @@ -0,0 +1,335 @@ +{ + flat_color_image_template = { + imageType = `2d; + samples = 1; + extent = { + width = $output.extent.width; + height = $output.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 6; + tiling = optimal; + usage = color_attachment|input_attachment|transient_attachment; + initialLayout = undefined; + }; + images = { + depth = { + @inherit = $properties.flat_color_image_template; + format = x8_d24_unorm_pack32; + usage = depth_stencil_attachment|input_attachment|transient_attachment; + }; + color = { + @inherit = $properties.flat_color_image_template; + format = r8g8b8a8_unorm; + }; + emission = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; + normal = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; + position = { + @inherit = $properties.flat_color_image_template; + format = r32g32b32a32_sfloat; + }; + opaque = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; + }; + flat_color_view_template = { + viewType = `2d_array; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 6; + }; + }; + imageViews = { + depth = { + @inherit = $properties.flat_color_view_template; + image = depth; + format = $properties.images.depth.format; + subresourceRange = { + aspectMask = depth; + }; + }; + color = { + @inherit = $properties.flat_color_view_template; + image = color; + format = $properties.images.color.format; + }; + emission = { + @inherit = $properties.flat_color_view_template; + image = emission; + format = $properties.images.emission.format; + }; + normal = { + @inherit = $properties.flat_color_view_template; + image = normal; + format = $properties.images.normal.format; + }; + position = { + @inherit = $properties.flat_color_view_template; + image = position; + format = $properties.images.position.format; + }; + opaque = { + @inherit = $properties.flat_color_view_template; + image = opaque; + format = $properties.images.opaque.format; + }; + aview = { + @inherit = $properties.flat_color_view_template; + image = $output.image; + format = $output.format; + }; + }; + output = { + image = { + @inherit = $properties.flat_color_image_template; + flags = cube_compatible; + usage = color_attachment|input_attachment|sampled; + format = $output.format; + }; + view = { + @inherit = $properties.flat_color_view_template; + viewType = cube; + image = $output.image; + format = $output.format; + }; + format = r16g16b16a16_sfloat; + finalLayout = shader_read_only_optimal; + }; + framebuffer = { + renderPass = defcube; + attachments = (depth, color, emission, normal, position, opaque, + $properties.imageViews.aview); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; + }; + clearValues = ( + { depthStencil = { depth = 1; stencil = 0; }; }, + { color = "[0, 0, 0, 1]"; }, // color + { color = "[0, 0, 0, 1]"; }, // emission + { color = "[0, 0, 0, 1]"; }, // normal + { color = "[0, 0, 0, 1]"; }, // position + { color = "[0, 0, 0, 1]"; }, // opaque + { color = "[0, 0, 0, 1]"; }, // output + ); + attachment_template = { + samples = 1; + loadOp = dont_care; + storeOp = store; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + }; + info = { + color = "[0, 1, 0, 1]"; + subpass_info = ( + { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, + { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, + { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, + { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, + { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, + ); + }; + renderpass = { + attachments = ( + { + @inherit = $properties.attachment_template; + format = $properties.images.depth.format; + loadOp = clear; + finalLayout = depth_stencil_attachment_optimal; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.color.format; + loadOp = clear; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.emission.format; + loadOp = clear; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.normal.format; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.position.format; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.opaque.format; + }, + { + @inherit = $properties.attachment_template; + format = $output.format; + loadOp = clear; + storeOp = store; + finalLayout = $output.finalLayout; + }, + ); + subpasses = ( + { // 0 depth + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_attachment_optimal; + }; + }, + { // 1 translucent-frags + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_read_only_optimal; + }; + preserveAttachments = (1, 2, 3, 4, 5); + }, + { // 2 g-buffer generation + pipelineBindPoint = graphics; + colorAttachments = ( + { // color + attachment = 1; + layout = color_attachment_optimal; + }, + { // emission + attachment = 2; + layout = color_attachment_optimal; + }, + { // normal + attachment = 3; + layout = color_attachment_optimal; + }, + { // position + attachment = 4; + layout = color_attachment_optimal; + }, + ); + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_read_only_optimal; + }; + preserveAttachments = (6); + }, + { // 3 lighting + pipelineBindPoint = graphics; + inputAttachments = ( + { // depth + attachment = 0; + layout = shader_read_only_optimal; + }, + { // color + attachment = 1; + layout = shader_read_only_optimal; + }, + { // emission + attachment = 2; + layout = shader_read_only_optimal; + }, + { // normal + attachment = 3; + layout = shader_read_only_optimal; + }, + { // position + attachment = 4; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // opaque + attachment = 5; + layout = color_attachment_optimal; + }, + ); + preserveAttachments = (6); + }, + { // 4 compose + pipelineBindPoint = graphics; + inputAttachments = ( + { // opaque + attachment = 5; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // output + attachment = 6; + layout = color_attachment_optimal; + }, + ); + preserveAttachments = (0, 1, 2, 3, 4); + }, + ); + dependencies = ( + { + srcSubpass = 0; // depth + dstSubpass = 1; // translucent + srcStageMask = late_fragment_tests; + dstStageMask = fragment_shader|early_fragment_tests; + srcAccessMask = depth_stencil_attachment_write; + dstAccessMask = input_attachment_read|depth_stencil_attachment_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 0; // depth + dstSubpass = 2; // g-buffer + srcStageMask = late_fragment_tests; + dstStageMask = early_fragment_tests; + srcAccessMask = depth_stencil_attachment_write; + dstAccessMask = depth_stencil_attachment_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 2; // g-buffer + dstSubpass = 3; // lighting + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 3; // lighting + dstSubpass = 4; // compose + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 1; // translucent-frags + dstSubpass = 4; // translucent-final/compose + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region; + }, + ); + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = ( + 0x0000003fu, + 0x0000003fu, + 0x0000003fu, + 0x0000003fu, + 0x0000003fu, + ); + }); + }; +} diff --git a/libs/video/renderer/vulkan/shader.c b/libs/video/renderer/vulkan/shader.c index cde12f5b8..8331fb01d 100644 --- a/libs/video/renderer/vulkan/shader.c +++ b/libs/video/renderer/vulkan/shader.c @@ -115,6 +115,8 @@ static static #include "libs/video/renderer/vulkan/shader/pushcolor.frag.spvc" static +#include "libs/video/renderer/vulkan/shader/fisheye.frag.spvc" +static #include "libs/video/renderer/vulkan/shader/waterwarp.frag.spvc" typedef struct shaderdata_s { @@ -162,6 +164,7 @@ static shaderdata_t builtin_shaders[] = { { "fstriangle.vert", fstriangle_vert, sizeof (fstriangle_vert) }, { "fstrianglest.vert", fstrianglest_vert, sizeof (fstrianglest_vert) }, { "pushcolor.frag", pushcolor_frag, sizeof (pushcolor_frag) }, + { "fisheye.frag", fisheye_frag, sizeof (fisheye_frag) }, { "waterwarp.frag", waterwarp_frag, sizeof (waterwarp_frag) }, {} }; diff --git a/libs/video/renderer/vulkan/shader/bsp_sky.frag b/libs/video/renderer/vulkan/shader/bsp_sky.frag index c85c42a1f..a574bec37 100644 --- a/libs/video/renderer/vulkan/shader/bsp_sky.frag +++ b/libs/video/renderer/vulkan/shader/bsp_sky.frag @@ -1,5 +1,7 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable + #include "oit_store.finc" layout (constant_id = 0) const bool doSkyBox = false; diff --git a/libs/video/renderer/vulkan/shader/bsp_turb.frag b/libs/video/renderer/vulkan/shader/bsp_turb.frag index c4726e5eb..7254eee87 100644 --- a/libs/video/renderer/vulkan/shader/bsp_turb.frag +++ b/libs/video/renderer/vulkan/shader/bsp_turb.frag @@ -1,5 +1,7 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable + #include "oit_store.finc" layout (set = 3, binding = 0) uniform sampler2DArray Texture; diff --git a/libs/video/renderer/vulkan/shader/compose.frag b/libs/video/renderer/vulkan/shader/compose.frag index 28e7e5d43..1373c849b 100644 --- a/libs/video/renderer/vulkan/shader/compose.frag +++ b/libs/video/renderer/vulkan/shader/compose.frag @@ -1,5 +1,7 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable + #define OIT_SET 1 #include "oit_blend.finc" diff --git a/libs/video/renderer/vulkan/shader/fisheye.frag b/libs/video/renderer/vulkan/shader/fisheye.frag new file mode 100644 index 000000000..a8623c87d --- /dev/null +++ b/libs/video/renderer/vulkan/shader/fisheye.frag @@ -0,0 +1,30 @@ +#version 450 +#extension GL_GOOGLE_include_directive : enable + +layout (set = 0, binding = 0) uniform +#include "matrices.h" +; + +layout (set = 1, binding = 0) uniform samplerCube Input; + +layout (push_constant) uniform PushConstants { + float fov; + float aspect; +}; + +layout (location = 0) in vec2 uv; + +layout (location = 0) out vec4 frag_color; + +void +main () +{ + // slight offset on y is to avoid the singularity straight ahead + vec2 xy = (2.0 * uv - vec2 (1, 1.00002)) * (vec2(1, -aspect)); + float r = sqrt (dot (xy, xy)); + vec2 cs = vec2 (cos (r * fov), sin (r * fov)); + vec3 dir = vec3 (cs.y * xy / r, cs.x); + + vec4 c = texture (Input, dir); + frag_color = c;// * 0.001 + vec4(dir, 1); +} diff --git a/libs/video/renderer/vulkan/shader/particle.frag b/libs/video/renderer/vulkan/shader/particle.frag index 6499cdd35..304f07d2d 100644 --- a/libs/video/renderer/vulkan/shader/particle.frag +++ b/libs/video/renderer/vulkan/shader/particle.frag @@ -1,5 +1,7 @@ #version 450 #extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_multiview : enable + #include "oit_store.finc" layout (location = 0) in vec4 uv_tr; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 3e92b8d1d..81cc281fc 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1724,6 +1724,10 @@ static exprsym_t builtin_plist_syms[] = { .value = (void *) #include "libs/video/renderer/vulkan/pl_output.plc" }, + { .name = "defcube", + .value = (void *) +#include "libs/video/renderer/vulkan/rp_defcube.plc" + }, { .name = "deferred", .value = (void *) #include "libs/video/renderer/vulkan/rp_deferred.plc" diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 9403e8343..f344865d9 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -245,8 +245,10 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) octx->output = Vulkan_CreateGraphicsPipeline (ctx, "output"); octx->waterwarp = Vulkan_CreateGraphicsPipeline (ctx, "waterwarp"); + octx->fisheye = Vulkan_CreateGraphicsPipeline (ctx, "fisheye"); octx->output_layout = Vulkan_CreatePipelineLayout (ctx, "output_layout"); octx->warp_layout = Vulkan_CreatePipelineLayout (ctx, "waterwarp_layout"); + octx->fish_layout = Vulkan_CreatePipelineLayout (ctx, "fisheye_layout"); octx->sampler = Vulkan_CreateSampler (ctx, "linear"); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); @@ -285,6 +287,7 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx) dfunc->vkDestroyPipeline (device->dev, octx->output, 0); dfunc->vkDestroyPipeline (device->dev, octx->waterwarp, 0); + dfunc->vkDestroyPipeline (device->dev, octx->fisheye, 0); free (octx->frames.a); free (octx); } From 759e3455c3de8e985ee5b4916427d808eb0472d3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Jan 2023 13:03:07 +0900 Subject: [PATCH 3393/3664] [vulkan] Hook up fisheye rendering in the output pass It turns out that my laptop doesn't do multiview properly (or I've misconfigured something, later), but the biggest issue I had on my desktop seems to be that I had the push constants wrong: fov in aspect, time in fov, and I had degrees instead of radians (half angle) anyway. --- libs/video/renderer/vulkan/vulkan_output.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index f344865d9..3e19f9a77 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -165,8 +165,15 @@ process_input (qfv_renderframe_t *rFrame) QFV_duCmdBeginLabel (device, cmd, "output:output"); - __auto_type pipeline = r_dowarp ? octx->waterwarp : octx->output; - __auto_type layout = r_dowarp ? octx->warp_layout : octx->output_layout; + __auto_type pipeline = octx->output; + __auto_type layout = octx->output_layout; + if (scr_fisheye) { + pipeline = octx->fisheye; + layout = octx->fish_layout; + } else if (r_dowarp) { + pipeline = octx->waterwarp; + layout = octx->warp_layout; + } dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); @@ -183,6 +190,17 @@ process_input (qfv_renderframe_t *rFrame) { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &time }, }; QFV_PushConstants (device, cmd, layout, 1, push_constants); + } else if (scr_fisheye) { + float width = r_refdef.vrect.width; + float height = r_refdef.vrect.height; + + float ffov = scr_ffov * M_PI / 360; + float aspect = height / width; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &ffov }, + { VK_SHADER_STAGE_FRAGMENT_BIT, 4, sizeof (float), &aspect }, + }; + QFV_PushConstants (device, cmd, layout, 2, push_constants); } dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); From 36f1c26ac1ecc906bdb7640c9bc2466d71b9537a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Jan 2023 17:21:41 +0900 Subject: [PATCH 3394/3664] [vulkan] Fix incorrect render pass for shadow pipelines Noticed while getting fisheye limping. --- libs/video/renderer/vulkan/pl_quake_def.plist | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index ea93a4a6e..729ebf01f 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -811,6 +811,7 @@ }; shadow_base = { @inherit = $properties.pipelines.depth_base; + renderPass = shadow; }; alias_shadow = { From 6d7a9e2bc2c61f4212a3d94463979764d83ee5f1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Jan 2023 00:52:40 +0900 Subject: [PATCH 3395/3664] [vulkan] Prioritize fisheye over waterwarp Pushing waterwarp's constants into fisheye's buffer resulted in some rather weird effects when underwater with fisheye active. --- libs/video/renderer/vulkan/vulkan_output.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 3e19f9a77..b6619d947 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -184,13 +184,7 @@ process_input (qfv_renderframe_t *rFrame) }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 2, set, 0, 0); - if (r_dowarp) { - float time = vr_data.realtime; - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &time }, - }; - QFV_PushConstants (device, cmd, layout, 1, push_constants); - } else if (scr_fisheye) { + if (scr_fisheye) { float width = r_refdef.vrect.width; float height = r_refdef.vrect.height; @@ -201,6 +195,12 @@ process_input (qfv_renderframe_t *rFrame) { VK_SHADER_STAGE_FRAGMENT_BIT, 4, sizeof (float), &aspect }, }; QFV_PushConstants (device, cmd, layout, 2, push_constants); + } else if (r_dowarp) { + float time = vr_data.realtime; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &time }, + }; + QFV_PushConstants (device, cmd, layout, 1, push_constants); } dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); From 0ccee3032e12e6f6688d9ebbf6a283cb47460f9b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 24 Jan 2023 10:09:00 +0900 Subject: [PATCH 3396/3664] [vulkan] Add partial support for cube maps to OIT Partial because frame buffer creation isn't handled yet (using six layers), but using layer a layer capable view and shaders doesn't cause problems (other than maybe slightly slower code). --- libs/video/renderer/vulkan/shader/oit.h | 2 +- libs/video/renderer/vulkan/shader/oit_blend.finc | 2 +- libs/video/renderer/vulkan/shader/oit_store.finc | 2 +- libs/video/renderer/vulkan/vulkan_translucent.c | 6 ++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/shader/oit.h b/libs/video/renderer/vulkan/shader/oit.h index 5569460ea..0147adc77 100644 --- a/libs/video/renderer/vulkan/shader/oit.h +++ b/libs/video/renderer/vulkan/shader/oit.h @@ -17,4 +17,4 @@ layout (set = OIT_SET, binding = 1) buffer Fragments { FragData fragments[]; }; -layout (set = OIT_SET, binding = 2, r32i) coherent uniform iimage2D heads; +layout (set = OIT_SET, binding = 2, r32i) coherent uniform iimage2DArray heads; diff --git a/libs/video/renderer/vulkan/shader/oit_blend.finc b/libs/video/renderer/vulkan/shader/oit_blend.finc index cfcfad302..5e2024be6 100644 --- a/libs/video/renderer/vulkan/shader/oit_blend.finc +++ b/libs/video/renderer/vulkan/shader/oit_blend.finc @@ -6,7 +6,7 @@ BlendFrags (vec4 color) #define MAX_FRAGMENTS 64 FragData frags[MAX_FRAGMENTS]; int numFrags = 0; - ivec2 coord = ivec2(gl_FragCoord.xy); + ivec3 coord = ivec3(gl_FragCoord.xy, gl_ViewIndex); int index = imageLoad (heads, coord).r; //FIXME use a heap and prioritize closer fragments diff --git a/libs/video/renderer/vulkan/shader/oit_store.finc b/libs/video/renderer/vulkan/shader/oit_store.finc index 539ed9e34..b51ba0d11 100644 --- a/libs/video/renderer/vulkan/shader/oit_store.finc +++ b/libs/video/renderer/vulkan/shader/oit_store.finc @@ -4,7 +4,7 @@ void StoreFrag (vec4 color, float depth) { int index = atomicAdd (numFragments, 1); - ivec2 coord = ivec2(gl_FragCoord.xy); + ivec3 coord = ivec3(gl_FragCoord.xy, gl_ViewIndex); if (index < maxFragments) { int prevIndex = imageAtomicExchange (heads, coord, index); fragments[index].color = color; diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index 1a82b8321..e99fba25f 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -192,7 +192,7 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) .type = qfv_res_image_view, .image_view = { .image = i, - .type = VK_IMAGE_VIEW_TYPE_2D, + .type = VK_IMAGE_VIEW_TYPE_2D_ARRAY, .format = VK_FORMAT_R32_SINT, .aspect = VK_IMAGE_ASPECT_COLOR_BIT, }, @@ -268,6 +268,7 @@ translucent_clear (qfv_renderframe_t *rFrame) qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; ib.barrier.image = tframe->heads; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, 1, &ib.barrier); @@ -275,13 +276,14 @@ translucent_clear (qfv_renderframe_t *rFrame) { .int32 = {-1, -1, -1, -1} }, }; VkImageSubresourceRange ranges[] = { - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }, + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, VK_REMAINING_ARRAY_LAYERS }, }; dfunc->vkCmdClearColorImage (cmd, tframe->heads, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear_color, 1, ranges); ib = imageBarriers[qfv_LT_TransferDst_to_General]; ib.barrier.image = tframe->heads; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, 1, &ib.barrier); From f78fcec6896c9b5052478500c483bc950b46163f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Jan 2023 01:02:16 +0900 Subject: [PATCH 3397/3664] [vulkan] Create view matrices for fisheye cube maps Really any cube maps, but currently the check is for fisheye rendering. --- include/QF/Vulkan/qf_matrices.h | 3 +- libs/video/renderer/vulkan/vulkan_matrices.c | 88 ++++++++++++++++---- 2 files changed, 73 insertions(+), 18 deletions(-) diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index 9b8e6d3b5..1eaeed2aa 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -77,7 +77,8 @@ struct vulkan_ctx_s; struct qfv_renderframe_s; void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx); -void Vulkan_SetViewMatrix (struct vulkan_ctx_s *ctx, mat4f_t view); +void Vulkan_SetViewMatrices (struct vulkan_ctx_s *ctx, mat4f_t views[], + int count); void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky); void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky); diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 41f031e2b..76d424711 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -50,26 +50,82 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/projection.h" #include "QF/Vulkan/staging.h" #include "r_internal.h" #include "vid_vulkan.h" +//FIXME? The box rotations (in particular top/bottom) for vulkan are not +//compatible with the other renderers, so need a local version +static mat4f_t box_rotations[] = { + [BOX_FRONT] = { + { 1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} + }, + [BOX_RIGHT] = { + { 0,-1, 0, 0}, + { 1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} + }, + [BOX_BEHIND] = { + {-1, 0, 0, 0}, + { 0,-1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} + }, + [BOX_LEFT] = { + { 0, 1, 0, 0}, + {-1, 0, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1} + }, + [BOX_BOTTOM] = { + { 0, 0, 1, 0}, + { 0, 1, 0, 0}, + {-1, 0, 0, 0}, + { 0, 0, 0, 1} + }, + [BOX_TOP] = { + { 0, 0,-1, 0}, + { 0, 1, 0, 0}, + { 1, 0, 0, 0}, + { 0, 0, 0, 1} + }, +}; + +// Quake's world is z-up, x-forward, y-left, but Vulkan's world is +// z-forward, x-right, y-down. +static mat4f_t z_up = { + { 0, 0, 1, 0}, + {-1, 0, 0, 0}, + { 0,-1, 0, 0}, + { 0, 0, 0, 1}, +}; + static void setup_view (vulkan_ctx_t *ctx) { - mat4f_t view; - // Quake's world is z-up, x-forward, y-left, but Vulkan's world is - // z-forward, x-right, y-down. - static mat4f_t z_up = { - { 0, 0, 1, 0}, - {-1, 0, 0, 0}, - { 0,-1, 0, 0}, - { 0, 0, 0, 1}, - }; - - mmulf (view, z_up, r_refdef.camera_inverse); - Vulkan_SetViewMatrix (ctx, view); + //FIXME this should check for cube map rather than fisheye + if (scr_fisheye) { + __auto_type mctx = ctx->matrix_context; + QFV_PerspectiveTan (mctx->matrices.Projection3d, 1, 1); + mat4f_t views[6]; + for (int i = 0; i < 6; i++) { + mat4f_t rotinv; + mat4ftranspose (rotinv, box_rotations[i]); + mmulf (views[i], rotinv, r_refdef.camera_inverse); + mmulf (views[i], z_up, views[i]); + } + Vulkan_SetViewMatrices (ctx, views, 6); + } else { + mat4f_t view; + mmulf (view, z_up, r_refdef.camera_inverse); + Vulkan_SetViewMatrices (ctx, &view, 1); + } } static void @@ -99,14 +155,12 @@ setup_sky (vulkan_ctx_t *ctx) } void -Vulkan_SetViewMatrix (vulkan_ctx_t *ctx, mat4f_t view) +Vulkan_SetViewMatrices (vulkan_ctx_t *ctx, mat4f_t views[], int count) { __auto_type mctx = ctx->matrix_context; - if (memcmp (mctx->matrices.View[0], view, sizeof (mat4f_t))) { - memcpy (mctx->matrices.View[0], view, sizeof (mat4f_t)); - mctx->dirty = mctx->frames.size; - } + memcpy (mctx->matrices.View, views, count * sizeof (mat4f_t)); + mctx->dirty = mctx->frames.size; } void From 8601e09569673be4a698d375f9396f2fdf7d8f26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 25 Jan 2023 13:05:01 +0900 Subject: [PATCH 3398/3664] [vulkan] Use view local dependencies for cube rendering It doesn't fix the problems on my laptop, but it might improve performance on my 1080 (but I doubt it will make much difference). --- libs/video/renderer/vulkan/rp_defcube.plist | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/libs/video/renderer/vulkan/rp_defcube.plist b/libs/video/renderer/vulkan/rp_defcube.plist index 98517f617..062f12fca 100644 --- a/libs/video/renderer/vulkan/rp_defcube.plist +++ b/libs/video/renderer/vulkan/rp_defcube.plist @@ -283,7 +283,7 @@ dstStageMask = fragment_shader|early_fragment_tests; srcAccessMask = depth_stencil_attachment_write; dstAccessMask = input_attachment_read|depth_stencil_attachment_read; - dependencyFlags = by_region; + dependencyFlags = by_region|view_local; }, { srcSubpass = 0; // depth @@ -292,7 +292,7 @@ dstStageMask = early_fragment_tests; srcAccessMask = depth_stencil_attachment_write; dstAccessMask = depth_stencil_attachment_read; - dependencyFlags = by_region; + dependencyFlags = by_region|view_local; }, { srcSubpass = 2; // g-buffer @@ -301,7 +301,7 @@ dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; dstAccessMask = input_attachment_read; - dependencyFlags = by_region; + dependencyFlags = by_region|view_local; }, { srcSubpass = 3; // lighting @@ -310,7 +310,7 @@ dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; dstAccessMask = input_attachment_read; - dependencyFlags = by_region; + dependencyFlags = by_region|view_local; }, { srcSubpass = 1; // translucent-frags @@ -319,17 +319,12 @@ dstStageMask = fragment_shader; srcAccessMask = color_attachment_write; dstAccessMask = input_attachment_read; - dependencyFlags = by_region; + dependencyFlags = by_region|view_local; }, ); @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = ( - 0x0000003fu, - 0x0000003fu, - 0x0000003fu, - 0x0000003fu, - 0x0000003fu, - ); + viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); + viewOffsets = ( 0, 0, 0, 0, 0); }); }; } From cbb43d8b29fd60e962b19d98de4e3965cfa81d1e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 27 Jan 2023 19:24:47 +0900 Subject: [PATCH 3399/3664] [vulkan] Fix incorrect header guard --- include/QF/Vulkan/qf_renderpass.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index e50f72f3c..7528517ad 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -1,5 +1,5 @@ -#ifndef __QF_Vulkan_renderpass_h -#define __QF_Vulkan_renderpass_h +#ifndef __QF_Vulkan_qf_renderpass_h +#define __QF_Vulkan_qf_renderpass_h #ifndef VK_NO_PROTOTYPES #define VK_NO_PROTOTYPES @@ -85,4 +85,4 @@ void QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass); void QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass); -#endif//__QF_Vulkan_renderpass_h +#endif//__QF_Vulkan_qf_renderpass_h From b08639fc82231af22c79d418625ea55047750184 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 28 Jan 2023 17:21:32 +0900 Subject: [PATCH 3400/3664] [vulkan] Run sky surfaces through the depth pass I suspect this is a hold-over from before the bsp thread safety changes, but with the nicely separated queues, it's easy to pass the sky surfaces through the depth pass as well as the translucency pass (I think the reason for that is lighting). This prevents bits of world being seen through sky surfaces when the sky isn't fully opaque (like skysheet due to the shortcuts in the shader). --- libs/video/renderer/vulkan/vulkan_bsp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 24ecb563b..7a3ab9f99 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1086,6 +1086,7 @@ Vulkan_DrawWorld (qfv_renderframe_t *rFrame) __auto_type pass = &bctx->main_pass; pass->textures = 0; draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspDepth]); + draw_queue (pass, 1, layout, device, bframe->cmdSet.a[QFV_bspDepth]); pass->textures = &bctx->registered_textures; draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); bsp_end (ctx); From 477057a5ada9137c506c839ceac6b2d2a1d2d286 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Jan 2023 13:19:53 +0900 Subject: [PATCH 3401/3664] [vulkan] Fix some forward declarations and namespace issues --- include/QF/Vulkan/command.h | 2 +- include/QF/Vulkan/debug.h | 16 ++++++++-------- include/vid_vulkan.h | 1 + 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 452baa9ca..4820eb141 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -49,7 +49,7 @@ int QFV_QueueSubmit (struct qfv_queue_s *queue, qfv_semaphoreset_t *signalSemaphores, VkFence fence); int QFV_QueueWaitIdle (struct qfv_queue_s *queue); -typedef struct { +typedef struct qfv_push_constants_s { VkShaderStageFlags stageFlags; uint32_t offset; uint32_t size; diff --git a/include/QF/Vulkan/debug.h b/include/QF/Vulkan/debug.h index 200d2aab2..d9029eab6 100644 --- a/include/QF/Vulkan/debug.h +++ b/include/QF/Vulkan/debug.h @@ -25,10 +25,10 @@ do { \ qfv_devfuncs_t *dfunc = device->funcs; \ if (dfunc->vkCmdBeginDebugUtilsLabelEXT) { \ - VkDebugUtilsLabelEXT label = { \ + VkDebugUtilsLabelEXT qfv_du_label = { \ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, name \ }; \ - dfunc->vkCmdBeginDebugUtilsLabelEXT (cmd, &label); \ + dfunc->vkCmdBeginDebugUtilsLabelEXT (cmd, &qfv_du_label); \ } \ } while (0) @@ -44,10 +44,10 @@ do { \ qfv_devfuncs_t *dfunc = device->funcs; \ if (dfunc->vkCmdInsertDebugUtilsLabelEXT) { \ - VkDebugUtilsLabelEXT label = { \ + VkDebugUtilsLabelEXT qfv_du_label = { \ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, name \ }; \ - dfunc->vkCmdInsertDebugUtilsLabelEXT (cmd, &label); \ + dfunc->vkCmdInsertDebugUtilsLabelEXT (cmd, &qfv_du_label); \ } \ } while (0) @@ -74,10 +74,10 @@ do { \ qfv_devfuncs_t *dfunc = device->funcs; \ if (dfunc->vkQueueBeginDebugUtilsLabelEXT) { \ - VkDebugUtilsLabelEXT label = { \ + VkDebugUtilsLabelEXT qfv_du_label = { \ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, name \ }; \ - dfunc->vkQueueBeginDebugUtilsLabelEXT (queue, &label); \ + dfunc->vkQueueBeginDebugUtilsLabelEXT (queue, &qfv_du_label); \ } \ } while (0) @@ -93,10 +93,10 @@ do { \ qfv_devfuncs_t *dfunc = device->funcs; \ if (dfunc->vkQueueInsertDebugUtilsLabelEXT) { \ - VkDebugUtilsLabelEXT label = { \ + VkDebugUtilsLabelEXT qfv_du_label = { \ VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, 0, name \ }; \ - dfunc->vkQueueInsertDebugUtilsLabelEXT (queue, &label); \ + dfunc->vkQueueInsertDebugUtilsLabelEXT (queue, &qfv_du_label); \ } \ } while (0) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 19d8ac3be..2a9936a99 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -7,6 +7,7 @@ #include #include "QF/darray.h" +#include "QF/qtypes.h" #include "QF/simd/types.h" typedef struct vulkan_frame_s { From 7c1aff67367f4f665c6e1955d8a1c40ba8c155fd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Jan 2023 13:00:35 +0900 Subject: [PATCH 3402/3664] [vulkan] Begin work on a new render pass system While the old system did get things going, it felt clunky to set up, especially when it came to variations on render passes (eg, flat vs cube-mapped). Also, much of it felt inside-out, especially the separation of pipelines and render passes: having to specify the render pass and subpass in the pipeline spec made the spec feel overly coupled to the render pass setup. While this is the case in Vulkan, it is not reflected properly in the pipeline spec. The new system will adjust the render pass and subpass parameters of the pipeline spec as needed, making the pipeline specs more reusable, and hopefully less error prone as the pipelines are directly referenced by the subpasses that use them. In addition, subpass dependencies should be much easier to set up as only the dependent subpass specifies the dependency and the subpass source dependency is mentioned by name. Frame buffer attachments also get a similar treatment. The new spec "format" isn't quite finalized (needs to meet the enemy known as parsing) but it feels like a good starting place. --- include/QF/Vulkan/render.h | 66 ++++ libs/video/renderer/vulkan/render.c | 122 ++++++ libs/video/renderer/vulkan/rp_main_def.plist | 371 +++++++++++++++++++ 3 files changed, 559 insertions(+) create mode 100644 include/QF/Vulkan/render.h create mode 100644 libs/video/renderer/vulkan/render.c create mode 100644 libs/video/renderer/vulkan/rp_main_def.plist diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h new file mode 100644 index 000000000..e1280ba05 --- /dev/null +++ b/include/QF/Vulkan/render.h @@ -0,0 +1,66 @@ +#ifndef __QF_Vulkan_render_h +#define __QF_Vulkan_render_h + +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + +#include "QF/darray.h" +#include "QF/simd/types.h" + +typedef struct qfv_label_s { + vec4f_t color; + const char *name; +} qfv_label_t; + +typedef struct qfv_bar_s { + VkBuffer *buffers; + VkDeviceSize *offsets; + uint32_t firstBinding; + uint32_t bindingCount; +} qfv_bar_t; + +typedef struct qfv_pipeline_s { + qfv_label_t label; + VkPipelineBindPoint bindPoint; + VkPipeline pipeline; + VkPipelineLayout layout; + VkViewport viewport; + VkRect2D scissor; + struct qfv_push_constants_s *push_constants; + uint32_t num_push_constants; + uint32_t num_descriptor_sets; + uint32_t first_descriptor_set; + VkDescriptorSet *descriptor_sets; +} qfv_pipeline_t; + +typedef struct qfv_subpass_s { + qfv_label_t label; + VkCommandBufferBeginInfo beginInfo; + VkCommandBuffer cmd; + uint32_t pipline_count; + qfv_pipeline_t *pipelines; +} qfv_subpass_t; + +typedef struct qfv_renderpass_s { + struct vulkan_ctx_s *vulkan_ctx; + qfv_label_t label; // for debugging + + VkCommandBuffer cmd; + VkRenderPassBeginInfo beginInfo; + VkSubpassContents subpassContents; + + //struct qfv_imageset_s *attachment_images; + //struct qfv_imageviewset_s *attachment_views; + //VkDeviceMemory attachmentMemory; + //size_t attachmentMemory_size; + //qfv_output_t output; + + uint32_t subpass_count; + qfv_subpass_t *subpasses; +} qfv_renderpass_t; + +void QFV_RunRenderPass (qfv_renderpass_t *rp, struct vulkan_ctx_s *ctx)m + +#endif//__QF_Vulkan_render_h diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c new file mode 100644 index 000000000..7fc68b5a0 --- /dev/null +++ b/libs/video/renderer/vulkan/render.c @@ -0,0 +1,122 @@ +/* + render.c + + Vulkan render manager + + Copyright (C) 2023 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/render.h" +#include "QF/Vulkan/pipeline.h" +#include "vid_vulkan.h" + +static void +run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + dfunc->vkCmdBindPipeline (cmd, pipeline->bindPoint, pipeline->pipeline); + dfunc->vkCmdSetViewport (cmd, 0, 1, &pipeline->viewport); + dfunc->vkCmdSetScissor (cmd, 0, 1, &pipeline->scissor); + if (pipeline->num_descriptor_sets) { + dfunc->vkCmdBindDescriptorSets (cmd, pipeline->bindPoint, + pipeline->layout, + pipeline->first_descriptor_set, + pipeline->num_descriptor_sets, + pipeline->descriptor_sets, + 0, 0); + } + if (pipeline->num_push_constants) { + QFV_PushConstants (device, cmd, pipeline->layout, + pipeline->num_push_constants, + pipeline->push_constants); + } +} + +// https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/ +static void +run_subpass (qfv_subpass_t *sp, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type cmd = sp->cmd; + dfunc->vkResetCommandBuffer (cmd, 0); + dfunc->vkBeginCommandBuffer (cmd, &sp->beginInfo); + QFV_duCmdBeginLabel (device, cmd, sp->label.name, + {VEC4_EXP (sp->label.color)}); + + for (uint32_t i = 0; i < sp->pipline_count; i++) { + __auto_type pipeline = &sp->pipelines[i]; + run_pipeline (pipeline, cmd, ctx); + } + + QFV_duCmdEndLabel (device, cmd); + dfunc->vkEndCommandBuffer (cmd); +} + +void +QFV_RunRenderPass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type cmd = rp->cmd; + + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + }; + dfunc->vkResetCommandBuffer (cmd, 0); + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + QFV_duCmdBeginLabel (device, cmd, rp->label.name, + {VEC4_EXP (rp->label.color)}); + dfunc->vkCmdBeginRenderPass (cmd, &rp->beginInfo, rp->subpassContents); + for (uint32_t i = 0; i < rp->subpass_count; i++) { + __auto_type sp = &rp->subpasses[i]; + run_subpass (sp, ctx); + dfunc->vkCmdExecuteCommands (cmd, 1, &sp->cmd); + //FIXME comment is a bit off as exactly one buffer is always submitted + // + //Regardless of whether any commands were submitted for this + //subpass, must step through each and every subpass, otherwise + //the attachments won't be transitioned correctly. + //However, only if not the last (or only) subpass. + if (i < rp->subpass_count - 1) { + dfunc->vkCmdNextSubpass (cmd, rp->subpassContents); + } + } + QFV_CmdEndLabel (device, cmd); +} diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist new file mode 100644 index 000000000..046323d97 --- /dev/null +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -0,0 +1,371 @@ +properties { + color = { + bsp = "[0, 0.5, 0.6, 1]"; + alias = "[0.6, 0.5, 0, 1]"; + iqm = "[0.6, 0.5, 0, 1]"; + sprite = "[0.6, 0.5, 0, 1]"; + }; + color_dependency = { + src = { + stage = color_attachment_output; + access = color_attachment_write; + }; + dst = { + stage = fragment_shader; + access = input_attachment_read; + }; + flags = by_region; + }; + depth_dependency = { + src = { + stage = late_fragment_tests; + access = depth_stencil_attachment_write; + }; + dst = { + stage = fragment_shader|early_fragment_tests; + access = input_attachment_read|depth_stencil_attachment_read; + }; + flags = by_region; + }; + image_base = { + imageType = `2d; + samples = 1; + extent = { + width = $output.extent.width; + height = $output.extent.height; + depth = 1; + }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment|transient_attachment; + initialLayout = undefined; + }; + view_base = { + viewType = `2d; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; + }; + attachment_base = { + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; + clearValue = { color = "[0, 0, 0, 1]"; }; + }; +}; +images = { + depth = { + @inherit = image_base; + format = x8_d24_unorm_pack32; + usage = depth_stencil_attachment|input_attachment|transient_attachment; + }; + color = { + @inherit = image_base; + format = r8g8b8a8_unorm; + }; + emission = { + @inherit = image_base; + format = r16g16b16a16_sfloat; + }; + normal = { + @inherit = image_base; + format = r16g16b16a16_sfloat; + }; + position = { + @inherit = image_base; + format = r32g32b32a32_sfloat; + }; + opaque = { + @inherit = image_base; + format = r16g16b16a16_sfloat; + }; +}; +views = { + depth = { + @inherit = view_base; + image = depth; + format = $images.depth.format; + subresourceRange = { + aspectMask = depth; + }; + }; + color = { + @inherit = view_base; + image = color; + format = $images.color.format; + }; + emission = { + @inherit = view_base; + image = color; + format = $images.color.format; + }; + normal = { + @inherit = view_base; + image = color; + format = $images.color.format; + }; + position = { + @inherit = view_base; + image = color; + format = $images.color.format; + }; + opaque = { + @inherit = view_base; + image = color; + format = $images.color.format; + }; + output = { + @inherit = view_base; + image = $output.image; + format = $output.format; + } +}; +renderpasses = { + deferred = { + attachments = { + depth = { + @inherit = $attachment_base; + format = $images.depth.format; + loadOp = clear; + finalLayout = depth_stencil_attachment_optimal; + clearValue = { depthStencil = { depth = 1; stencil = 0; }; }; + }; + color = { + @inherit = $attachment_base; + format = $images.color.format; + loadOp = clear; + finalLayout = depth_stencil_attachment_optimal; + }; + emission = { + @inherit = $attachment_base; + format = $images.emission.format; + loadOp = clear; + }; + normal = { + @inherit = $attachment_base; + format = $images.normal.format; + }; + position = { + @inherit = $attachment_base; + format = $images.position.format; + }; + opaque = { + @inherit = $attachment_base; + format = $images.opaque.format; + }; + output = { + @inherit = $attachment_base; + format = $images.output.format; + loadOp = clear; + storeOp = store; + $output.finalLayout; + }; + }; + framebuffer = { + attachments = (depth, color, emission, normal, position, opaque, + $output.view); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; + }; + subpasses = { + depth = { + color = "[ 0.5, 0.5, 0.5, 1]"; + attachments = { + depth = depth_stencil_read_only_optimal; + preserve = (color, emission, normal, position, output); + }; + pipelines = { + bsp:depth = { + color = $color.bsp; + pipeline = bsp_depth; + tasks = ( + { func = bsp_draw_queue; + params = (main, solid); }, + { func = bsp_draw_queue; + params = (main, sky); }, + ); + }; + alias:depth = { + color = $color.alias; + pipeline = alias_depth; + tasks = ( + { func = "alias_draw"; }, + ); + }; + iqm:depth = { + color = $color.iqm; + pipeline = iqm_depth; + tasks = ( + { func = "iqm_draw"; }, + ); + }; + sprite:depth = { + color = $color.sprite; + pipeline = sprite_depth; + tasks = ( + { func = "sprite_draw"; }, + ); + }; + }; + }; + translucent = { + color = "[ 0.25, 0.25, 0.6, 1]"; + depend = { + depth = $depth_dependency; + } + attachments = { + depth = depth_stencil_read_only_optimal; + preserve = (color, emission, normal, position, output); + }; + pipelines = { + bsp:sky = { + color = $color.bsp; + pipeline = $bsp_sky_pipeline; + tasks = ( + // FIXME sky should not use OIT + { func = bsp_draw_queue; + params = (main, sky); }, + ); + }; + bsp:trans = { + color = $color.bsp; + pipeline = bsp_turb; + tasks = ( + { func = bsp_draw_queue; + params = (main, translucent); }, + { func = bsp_draw_queue; + params = (main, turbulent); }, + ); + }; + particles:trans { + color = $color.particles; + pipline = partdraw; + { func = particles_draw; }, + }; + }; + }; + gbuffer = { + color = "[ 0.3, 0.7, 0.3, 1]"; + depend = { + depth = $depth_dependency; + } + attachments = { + color = { + color = color_attachment_optimal; + emission = color_attachment_optimal; + normal = color_attachment_optimal; + position = color_attachment_optimal; + }; + depth = depth_stencil_read_only_optimal; + preserve = (output); + }; + pipelines = { + bsp:gbuffer = { + color = $color.bsp; + pipeline = bsp_gbuf; + tasks = ( + { func = bsp_draw_queue; + params = (main, solid); }, + { func = bsp_draw_queue; + params = (main, sky); }, + ); + }; + alias:gbuffer = { + color = $color.alias; + pipeline = alias_gbuf; + tasks = ( + { func = "alias_draw"; }, + ); + }; + iqm:gbuffer = { + color = $color.iqm; + pipeline = iqm_gbuf; + tasks = ( + { func = "iqm_draw"; }, + ); + }; + sprite:gbuffer = { + color = $color.sprite; + pipeline = sprite_gbuf; + tasks = ( + { func = "sprite_draw"; }, + ); + }; + }; + }; + lighting = { + color = "[ 0.8, 0.8, 0.8, 1]"; + depend = { + gbuffer = $color_dependency; + } + attachments = { + input = { + depth = shader_read_only_optimal; + color = shader_read_only_optimal; + emission = shader_read_only_optimal; + normal = shader_read_only_optimal; + position = shader_read_only_optimal; + }; + color = { + opaque = color_attachment_optimal; + }; + preserve = (output); + }; + pipelines = { + lights = { + color = $color.lights + pipeline = lighting; + tasks = ( + { func = "lights_draw"; }, + ); + }; + }; + }; + compose = { + color = "[ 0.7, 0.3, 0.3, 1]"; + depend = { + lighting = $color_dependency; + } + attachments = { + input = { + opaque = shader_read_only_optimal; + }; + color = { + output = color_attachment_optimal; + }; + preserve = (depth, color, emission, normal, position); + }; + pipelines = { + compose = { + color = $color.compose + pipeline = compose; + tasks = ( + { func = "lights_draw"; }, + ); + }; + }; + }; + }; + }; + deferred_cube = { + @inherit = deferred; + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); + viewOffsets = ( 0, 0, 0, 0, 0); + }); + }; +}; From d5cd4f6eded4dd1f08fd5fa3cc85f511d73ea76b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 8 Feb 2023 17:32:20 +0900 Subject: [PATCH 3403/3664] [vkgen] Use typedef name for structs Using the typedef name makes using structs declared as typedef struct foo_s { ... } foo_t; easier and cleaner. Sure, I could have written the "struct foo_s" for the output name, but I'm much more likely to look for foo_t than foo_s when checking the generated code. --- libs/video/renderer/vulkan/vkgen/vkalias.r | 9 +++++++++ libs/video/renderer/vulkan/vkgen/vkstruct.r | 3 +++ libs/video/renderer/vulkan/vkgen/vktype.h | 2 ++ libs/video/renderer/vulkan/vkgen/vktype.r | 7 +++++++ 4 files changed, 21 insertions(+) diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index bbb7ffb21..5aeb8cac9 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -6,6 +6,15 @@ #include "vkstruct.h" @implementation Alias +-initWithType: (qfot_type_t *) type +{ + if (!(self = [super initWithType: type])) { + return nil; + } + [[self resolveType] setAlias: self]; + return self; +} + -(string) name { return type.alias.name; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index ec6530b5e..19e977b30 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -245,6 +245,9 @@ if (outname) { return outname; } + if (alias) { + return [alias name]; + } return [self name]; } diff --git a/libs/video/renderer/vulkan/vkgen/vktype.h b/libs/video/renderer/vulkan/vkgen/vktype.h index 0008c83ab..b76be83f6 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.h +++ b/libs/video/renderer/vulkan/vkgen/vktype.h @@ -7,6 +7,7 @@ @interface Type: Object { qfot_type_t *type; + Type *alias; } +fromType: (qfot_type_t *) type; /** \warning returned string is ephemeral @@ -15,6 +16,7 @@ /** \warning returned string is ephemeral */ -(string) name; +-(void) setAlias: (Type *) alias; -(void) addToQueue; -(Type *) resolveType; +(Type *) findType: (qfot_type_t *) type; diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index 70de1fbc7..2acefa3b7 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -86,6 +86,13 @@ static string get_type_key (void *type, void *unused) return type.encoding; } +-(void) setAlias: (Type *) alias +{ + if (!self.alias) { + self.alias = alias; + } +} + -(void) addToQueue { string name = [self name]; From 403c6eea73db0e6b6985e9b5a46aa74575fe5a1e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Feb 2023 11:32:38 +0900 Subject: [PATCH 3404/3664] [vkgen] Recognize `char *` as a string Ruamoko currently doesn't support `const`, so that's not relevant, but recognizing `char *` (via a hack to work around what looks like a bug with type aliasing) allows strings to be handled without having to use a custom parser. Things are still a little clunky for custom parsers, but this seems to be a good start. --- .../video/renderer/vulkan/vkgen/Makemodule.am | 2 ++ libs/video/renderer/vulkan/vkgen/stdint.h | 2 +- .../renderer/vulkan/vkgen/vkfieldstring.h | 1 + .../renderer/vulkan/vkgen/vkfieldstring.r | 11 +++++++- libs/video/renderer/vulkan/vkgen/vkgen.h | 1 + libs/video/renderer/vulkan/vkgen/vkgen.r | 4 ++- libs/video/renderer/vulkan/vkgen/vkstring.h | 9 ++++++ libs/video/renderer/vulkan/vkgen/vkstring.r | 28 +++++++++++++++++++ libs/video/renderer/vulkan/vkgen/vkstruct.r | 13 ++++++--- libs/video/renderer/vulkan/vkgen/vktype.h | 5 ++++ libs/video/renderer/vulkan/vkgen/vktype.r | 14 ++++++++++ 11 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkstring.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkstring.r diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 8d8e11f4e..90d01645e 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -17,6 +17,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkfieldtype.r \ libs/video/renderer/vulkan/vkgen/vkfixedarray.r \ libs/video/renderer/vulkan/vkgen/vkgen.r \ + libs/video/renderer/vulkan/vkgen/vkstring.r \ libs/video/renderer/vulkan/vkgen/vkstruct.r \ libs/video/renderer/vulkan/vkgen/vktype.r \ libs/video/renderer/vulkan/vkgen/vulkan.r @@ -60,6 +61,7 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/vkgen/vkfieldtype.h \ libs/video/renderer/vulkan/vkgen/vkfixedarray.h \ libs/video/renderer/vulkan/vkgen/vkgen.h \ + libs/video/renderer/vulkan/vkgen/vkstring.h \ libs/video/renderer/vulkan/vkgen/vkstruct.h \ libs/video/renderer/vulkan/vkgen/vktype.h diff --git a/libs/video/renderer/vulkan/vkgen/stdint.h b/libs/video/renderer/vulkan/vkgen/stdint.h index e343a15b5..740574d18 100644 --- a/libs/video/renderer/vulkan/vkgen/stdint.h +++ b/libs/video/renderer/vulkan/vkgen/stdint.h @@ -7,4 +7,4 @@ typedef int int16_t; typedef int int32_t; typedef int int64_t; typedef int size_t; -typedef int char; +typedef struct char { int x; } char; diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldstring.h b/libs/video/renderer/vulkan/vkgen/vkfieldstring.h index fead71504..2214d7130 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldstring.h +++ b/libs/video/renderer/vulkan/vkgen/vkfieldstring.h @@ -4,6 +4,7 @@ #include "vkfielddef.h" @interface StringField: FieldDef ++fielddef:(PLItem *)item struct:(Struct *)strct field:(string)fname; @end #endif//__renderer_vulkan_vkgen_vkfieldstring_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldstring.r b/libs/video/renderer/vulkan/vkgen/vkfieldstring.r index ff0ba525d..59a89012f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldstring.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldstring.r @@ -12,10 +12,19 @@ return self; } - value_field = [[item getObjectForKey:"string"] string]; + value_field = fname; + if (item) { + value_field = [[item getObjectForKey:"string"] string]; + } return self; } ++fielddef:(PLItem *)item struct:(Struct *)strct field:(string)fname +{ + return [[[StringField alloc] init:item struct:strct field:fname] + autorelease]; +} + -writeParseData { fprintf (output_file, "static parse_string_t parse_%s_%s_data = {\n", diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.h b/libs/video/renderer/vulkan/vkgen/vkgen.h index 8f9cd5c93..8a9171014 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.h +++ b/libs/video/renderer/vulkan/vkgen/vkgen.h @@ -5,6 +5,7 @@ #include #include #include +#include typedef void varfunc (qfot_var_t *var); diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index a3a5e426f..8b5abd8c2 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -200,7 +200,9 @@ main(int argc, string *argv) id obj = [queue objectAtIndex:0]; [queue removeObjectAtIndex:0]; if ([obj class] == [Struct class]) { - if ([[parse getObjectForKey:[obj name]] string] == "skip") { + string name = [obj name]; + if (name == "char" // char type faked via a struct + || [[parse getObjectForKey:name] string] == "skip") { continue; } [obj queueFieldTypes]; diff --git a/libs/video/renderer/vulkan/vkgen/vkstring.h b/libs/video/renderer/vulkan/vkgen/vkstring.h new file mode 100644 index 000000000..4d9f22486 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkstring.h @@ -0,0 +1,9 @@ +#ifndef __renderer_vulkan_vkgen_vkstring_h +#define __renderer_vulkan_vkgen_vkstring_h + +#include "vktype.h" + +@interface String: Type +@end + +#endif//__renderer_vulkan_vkgen_vkstring_h diff --git a/libs/video/renderer/vulkan/vkgen/vkstring.r b/libs/video/renderer/vulkan/vkgen/vkstring.r new file mode 100644 index 000000000..f0c44c37b --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkstring.r @@ -0,0 +1,28 @@ +#include + +#include "vkfieldstring.h" +#include "vkstring.h" +#include "vkgen.h" + +@implementation String + +-(string) name +{ + return "string"; +} + +-(FieldDef *)fielddef:(Struct *)strct field:(string)fname +{ + return [StringField fielddef:nil struct:strct field:fname]; +} + +-(string) cexprType +{ + return [self name] + "_type"; +} + +-(string) parseType +{ + return "QFString"; +} +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 19e977b30..12b0bfb46 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -124,9 +124,13 @@ if (field.name == "sType" || field.name == "pNext") { continue; } - FieldDef *field_def = [FieldDef fielddef:nil - struct:self - field:field.name]; + Type *field_type = [Type findType: field.type]; + FieldDef *field_def = [field_type fielddef:self field:field.name]; + if (!field_def) { + field_def = [FieldDef fielddef:nil + struct:self + field:field.name]; + } [field_defs addObject: field_def]; } } @@ -197,7 +201,8 @@ Type *field_type = [Type findType: field.type]; fprintf (output_file, "\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n", - field.name, [field_type cexprType], [self outname], field.name); + field.name, [field_type cexprType], [self outname], + field.name); } } fprintf (output_file, "\t{ }\n"); diff --git a/libs/video/renderer/vulkan/vkgen/vktype.h b/libs/video/renderer/vulkan/vkgen/vktype.h index b76be83f6..66cab0d24 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.h +++ b/libs/video/renderer/vulkan/vkgen/vktype.h @@ -4,6 +4,9 @@ #include #include +@class FieldDef; +@class Struct; + @interface Type: Object { qfot_type_t *type; @@ -26,6 +29,8 @@ -(string) parseFunc; -(string) parseData; +-(FieldDef *)fielddef:(Struct *)strct field:(string)fname; + -(int) isPointer; -(Type *) dereference; @end diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index 2acefa3b7..d7d2a9a95 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -4,6 +4,7 @@ #include "vkenum.h" #include "vkfixedarray.h" #include "vkgen.h" +#include "vkstring.h" #include "vkstruct.h" #include "vktype.h" @@ -51,6 +52,14 @@ static string get_type_key (void *type, void *unused) } switch (type.meta) { case ty_basic: + if (type.type == ev_ptr) { + Type *tgt = [Type findType: type.fldptr.aux_type]; + + if (tgt.type.meta == ty_alias + && tgt.type.alias.name == "char") { + return [[String alloc] initWithType: type]; + } + } case ty_class: return [[Type alloc] initWithType: type]; case ty_array: @@ -138,6 +147,11 @@ static string get_type_key (void *type, void *unused) return "0"; } +-(FieldDef *)fielddef:(Struct *)strct field:(string)fname +{ + return nil; +} + -(int) isPointer { if ((type.meta == ty_basic || type.meta == ty_alias) From 97b2f2afb027a04103ea5d2d1daf9221473544b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Feb 2023 14:46:50 +0900 Subject: [PATCH 3405/3664] [vkgen] Support vec4f_t fields It's currently a bit of a hack via aliases, but it fits in with the current support for uint32_t and size_t. --- libs/video/renderer/vulkan/vkgen/vkalias.r | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index 5aeb8cac9..f6c2f17e4 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -80,6 +80,9 @@ if (name == "uint32_t") { return "cexpr_uint"; } + if (name == "vec4f_t") { + return "cexpr_vector"; + } if (name == "size_t") { return "cexpr_size_t"; } @@ -102,7 +105,7 @@ id enumObj = [(id) Hash_Find (available_types, name) resolveType]; return [enumObj parseType]; } - if (name == "uint32_t" || name == "size_t") { + if (name == "uint32_t" || name == "size_t" || name == "vec4f_t") { return "QFString"; } return [alias parseType]; @@ -149,6 +152,9 @@ if (name == "uint32_t") { return "0"; } + if (name == "vec4f_t") { + return "&cexpr_vector"; + } if (name == "size_t") { return "&cexpr_size_t"; } From e10b084d36791237f4a14028160c1cf0987b627d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Feb 2023 14:52:43 +0900 Subject: [PATCH 3406/3664] [vulkan] Generate parse data for new render pass structs There's still a lot of work to do, but the basics are in. The spec will be parsed into info structs that can then be further processed to generate all the actual structs, generally making things a little less timing dependent (eg, image view info refers to its image by name). The new render pass and subpass structs have their names mangled for now until I can switch over to the new system. --- include/QF/Vulkan/render.h | 117 ++++++++++++++- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vulkan/render.c | 4 +- libs/video/renderer/vulkan/rp_main_def.plist | 8 +- libs/video/renderer/vulkan/vkgen/vulkan.r | 4 + libs/video/renderer/vulkan/vkparse.c | 17 +++ libs/video/renderer/vulkan/vkparse.plist | 142 ++++++++++++++++++- 7 files changed, 279 insertions(+), 14 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index e1280ba05..7fe4672ab 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -6,9 +6,112 @@ #endif #include -#include "QF/darray.h" #include "QF/simd/types.h" +typedef struct qfv_imageinfo_s { + const char *name; + VkImageCreateFlags flags; + VkImageType imageType; + VkFormat format; + VkExtent3D extent; + uint32_t mipLevels; + uint32_t arrayLayers; + VkSampleCountFlagBits samples; + VkImageTiling tiling; + VkImageUsageFlags usage; +} qfv_imageinfo_t; + +typedef struct qfv_imageviewinfo_s { + const char *name; + VkImageViewCreateFlags flags; + //VkImage image; + const char *image; + VkImageViewType viewType; + VkFormat format; + VkComponentMapping components; + VkImageSubresourceRange subresourceRange; +} qfv_imageviewinfo_t; + +typedef struct qfv_dependencymask_s { + VkPipelineStageFlags stage; + VkAccessFlags access; +} qfv_dependencymask_t; + +typedef struct qfv_dependencyinfo_s { + const char *name; + qfv_dependencymask_t src; + qfv_dependencymask_t dst; + VkDependencyFlags flags; +} qfv_dependencyinfo_t; + +typedef struct qfv_attachmentinfo_s { + vec4f_t color; + const char *name; + VkAttachmentDescriptionFlags flags; + VkFormat format; + VkSampleCountFlagBits samples; + VkAttachmentLoadOp loadOp; + VkAttachmentStoreOp storeOp; + VkAttachmentLoadOp stencilLoadOp; + VkAttachmentStoreOp stencilStoreOp; + VkImageLayout initialLayout; + VkImageLayout finalLayout; +} qfv_attachmentinfo_t; + +typedef struct qfv_taskinfo_s { + struct exprfunc_s *func; + void *params; +} qfv_taskinfo_t; + +typedef struct qfv_attachmentrefinfo_s { + uint32_t num_input; + const char **input; + uint32_t num_color; + const char **color; + const char **resolve; + const char **depth; + uint32_t num_preserve; + const char **preserve; +} qfv_attachmentrefinfo_t; + +typedef struct qfv_pipelineinfo_s { + vec4f_t color; + const char *name; + VkGraphicsPipelineCreateInfo *pipeline; + uint32_t num_tasks; + qfv_taskinfo_t *tasks; +} qfv_pipelineinfo_t; + +typedef struct qfv_subpassinfo_s { + vec4f_t color; + const char *name; + uint32_t num_dependencies; + qfv_dependencyinfo_t *dependencies; + uint32_t num_attachments; + qfv_attachmentrefinfo_t *attachments; + uint32_t num_pipelines; + qfv_pipelineinfo_t *pipelines; +} qfv_subpassinfo_t; + +typedef struct qfv_renderpassinfo_s { + const char *name; + uint32_t num_attachments; + qfv_attachmentinfo_t *attachments; + VkFramebufferCreateInfo framebuffer; + uint32_t num_subpasses; + qfv_subpassinfo_t *subpasses; +} qfv_renderpassinfo_t; + +typedef struct qfv_renderinfo_s { + struct plitem_s *properties; + uint32_t num_images; + qfv_imageinfo_t *images; + uint32_t num_views; + qfv_imageviewinfo_t *views; + uint32_t num_renderpasses; + qfv_renderpassinfo_t *renderpasses; +} qfv_renderinfo_t; + typedef struct qfv_label_s { vec4f_t color; const char *name; @@ -35,15 +138,15 @@ typedef struct qfv_pipeline_s { VkDescriptorSet *descriptor_sets; } qfv_pipeline_t; -typedef struct qfv_subpass_s { +typedef struct qfv_subpass_s_ { qfv_label_t label; VkCommandBufferBeginInfo beginInfo; VkCommandBuffer cmd; uint32_t pipline_count; qfv_pipeline_t *pipelines; -} qfv_subpass_t; +} qfv_subpass_t_; -typedef struct qfv_renderpass_s { +typedef struct qfv_renderpass_s_ { struct vulkan_ctx_s *vulkan_ctx; qfv_label_t label; // for debugging @@ -58,9 +161,9 @@ typedef struct qfv_renderpass_s { //qfv_output_t output; uint32_t subpass_count; - qfv_subpass_t *subpasses; -} qfv_renderpass_t; + qfv_subpass_t_ *subpasses; +} qfv_renderpass_t_; -void QFV_RunRenderPass (qfv_renderpass_t *rp, struct vulkan_ctx_s *ctx)m +void QFV_RunRenderPass (qfv_renderpass_t_ *rp, struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_render_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index cbf25d7c0..e48676839 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -231,6 +231,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/memory.c \ libs/video/renderer/vulkan/pipeline.c \ libs/video/renderer/vulkan/projection.c \ + libs/video/renderer/vulkan/render.c \ libs/video/renderer/vulkan/resource.c \ libs/video/renderer/vulkan/scrap.c \ libs/video/renderer/vulkan/shader.c \ diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 7fc68b5a0..8333d6ccf 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -70,7 +70,7 @@ run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) // https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/ static void -run_subpass (qfv_subpass_t *sp, vulkan_ctx_t *ctx) +run_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -90,7 +90,7 @@ run_subpass (qfv_subpass_t *sp, vulkan_ctx_t *ctx) } void -QFV_RunRenderPass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) +QFV_RunRenderPass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 046323d97..5b840f30c 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -224,7 +224,7 @@ renderpasses = { }; translucent = { color = "[ 0.25, 0.25, 0.6, 1]"; - depend = { + dependencies = { depth = $depth_dependency; } attachments = { @@ -260,7 +260,7 @@ renderpasses = { }; gbuffer = { color = "[ 0.3, 0.7, 0.3, 1]"; - depend = { + dependencies = { depth = $depth_dependency; } attachments = { @@ -309,7 +309,7 @@ renderpasses = { }; lighting = { color = "[ 0.8, 0.8, 0.8, 1]"; - depend = { + dependencies = { gbuffer = $color_dependency; } attachments = { @@ -337,7 +337,7 @@ renderpasses = { }; compose = { color = "[ 0.7, 0.3, 0.3, 1]"; - depend = { + dependencies = { lighting = $color_dependency; } attachments = { diff --git a/libs/video/renderer/vulkan/vkgen/vulkan.r b/libs/video/renderer/vulkan/vkgen/vulkan.r index 47df077e4..c40e48098 100644 --- a/libs/video/renderer/vulkan/vkgen/vulkan.r +++ b/libs/video/renderer/vulkan/vkgen/vulkan.r @@ -1,6 +1,10 @@ #define __x86_64__ #include +typedef vec4 vec4f_t; +#define __QF_simd_types_h +#include "QF/Vulkan/render.h" + //FIXME copy of qfv_subpass_t in qf_renderpass.h //except it doesn't really matter because a custom spec is used typedef struct qfv_subpass_s { diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 81cc281fc..11219f39a 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -42,6 +42,7 @@ #include "QF/Vulkan/instance.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/pipeline.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/shader.h" #include "QF/Vulkan/qf_renderpass.h" @@ -996,6 +997,22 @@ parse_specialization_data (const plitem_t *item, void **data, return ret; } +static int +parse_task_function (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *pctx) +{ + PL_Message (messages, item, "parse_task_function: not implemented"); + return 0; +} + +static int +parse_task_params (const plitem_t *item, void **data, + plitem_t *messages, parsectx_t *pctx) +{ + PL_Message (messages, item, "parse_task_params: not implemented"); + return 0; +} + #include "libs/video/renderer/vulkan/vkparse.cinc" static exprsym_t vulkan_frameset_t_symbols[] = { diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index f22ae092f..d20a2aad9 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -33,6 +33,17 @@ qfv_subpass_t, qfv_output_t, + + qfv_imageinfo_t, + qfv_imageviewinfo_t, + qfv_dependencyinfo_t, + qfv_attachmentinfo_t, + qfv_attachmentrefinfo_t, + qfv_taskinfo_t, + qfv_pipelineinfo_t, + qfv_subpassinfo_t, + qfv_renderpassinfo_t, + qfv_renderinfo_t, ); parse = { VkSubpassDescription = { @@ -393,7 +404,6 @@ string = name; }; }; - qfv_output_s = { .name = qfv_output_t; extent = auto; @@ -409,5 +419,135 @@ frames = auto; finalLayout = auto; }; + + qfv_taskinfo_s = { + .name = qfv_taskinfo_t; + func = { + type = (custom, QFString, parse_task_function); + fields = (func); + }; + params = { + type = (custom, QFArray, parse_task_params); + fields = (params, func); + }; + }; + qfv_attachmentrefinfo_s = { + .name = qfv_attachmentrefinfo_t; + input = { + type = (array, { + parse_type = QFString; + type = "char *"; + parser = parse_string; + }); + size = num_input; + values = input; + }; + color = { + type = (array, { + parse_type = QFString; + type = "char *"; + parser = parse_string; + }); + size = num_color; + values = color; + }; + resolve = { + type = (array, { + parse_type = QFString; + type = "char *"; + parser = parse_string; + }); + values = resolve; + matchSize = color; + }; + depth = { + type = (single, { + parse_type = QFString; + type = "char *"; + parser = parse_string; + }); + value = depth; + }; + preserve = { + type = (array, { + parse_type = QFString; + type = "char *"; + parser = parse_string; + }); + size = num_preserve; + values = preserve; + }; + }; + qfv_pipelineinfo_s = { + .name = qfv_pipelineinfo_t; + color = auto; + name = { + type = string; + string = name; + }; + pipeline = { + type = (single, VkGraphicsPipelineCreateInfo); + value = pipeline; + }; + tasks = { + type = (array, qfv_taskinfo_t); + size = num_tasks; + values = tasks; + } + }; + qfv_subpassinfo_s = { + .name = qfv_subpassinfo_t; + name = { + type = string; + string = name; + }; + dependencies = { + type = (array, qfv_dependencyinfo_t); + size = num_dependencies; + values = dependencies; + }; + attachments = { + type = (single, qfv_attachmentrefinfo_t); + value = attachments; + }; + pipelines = { + type = (array, qfv_pipelineinfo_t); + size = num_pipelines; + values = pipelines; + }; + }; + qfv_renderpassinfo_s = { + .name = qfv_renderpassinfo_t; + attachments = { + type = (array, qfv_attachmentinfo_t); + size = num_attachments; + values = attachments; + }; + framebuffer = auto; + subpasses = { + type = (array, qfv_subpassinfo_t); + size = num_subpasses; + values = subpasses; + }; + }; + qfv_renderinfo_s = { + .name = qfv_renderinfo_t; + //properties = auto; + images = { + type = (array, qfv_imageinfo_t); + size = num_images; + values = images; + }; + views = { + type = (array, qfv_imageviewinfo_t); + size = num_views; + values = views; + }; + renderpasses = { + type = (array, qfv_renderpassinfo_t); + size = num_renderpasses; + values = renderpasses; + }; + } }; } From 7aa5470c68c3f43221c33ce4e50591cc57206705 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Feb 2023 21:17:04 +0900 Subject: [PATCH 3407/3664] [vulkan] Add initial render info parser It doesn't work yet, but I've some otherwise breaking changes I want in (getting this in now prevents the breakage). --- include/QF/Vulkan/render.h | 2 +- libs/video/renderer/vulkan/vkparse.c | 82 +++++++++++++++++++++++++++- libs/video/renderer/vulkan/vkparse.h | 2 + 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 7fe4672ab..2e75bc44e 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -103,7 +103,7 @@ typedef struct qfv_renderpassinfo_s { } qfv_renderpassinfo_t; typedef struct qfv_renderinfo_s { - struct plitem_s *properties; + struct memsuper_s *memsuper; uint32_t num_images; qfv_imageinfo_t *images; uint32_t num_views; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 11219f39a..27ee9d36b 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -365,7 +365,7 @@ parse_array (const plfield_t *field, const plitem_t *item, return 1; } -static int +static int __attribute__((used)) parse_fixed_array (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) { @@ -2037,3 +2037,83 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) set, va (ctx->va_ctx, "descriptor_set:%s", name)); return set; } + +qfv_renderinfo_t * +QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) +{ + memsuper_t *memsuper = new_memsuper (); + qfv_renderinfo_t *ri = cmemalloc (memsuper, sizeof (qfv_renderinfo_t)); + *ri = (qfv_renderinfo_t) { .memsuper = memsuper }; + + plitem_t *properties = PL_ObjectForKey (item, "properties"); + int num_keys = PL_D_NumKeys (properties); + + scriptctx_t *sctx = ctx->script_context; + plitem_t *messages = PL_NewArray (); + exprctx_t exprctx = { .symtab = &root_symtab }; + parsectx_t parsectx = { &exprctx, ctx, properties }; + plitem_t *pl_items[num_keys + 2]; + exprsym_t var_syms[num_keys + 6 + 1]; + var_syms[num_keys + 6] = (exprsym_t) {}; + exprtab_t vars_tab = { var_syms, 0 }; + + for (int i = 0; i < num_keys; i++) { + var_syms[i] = (exprsym_t) { + .name = PL_KeyAtIndex (properties, i), + .type = &cexpr_plitem, + .value = pl_items + i, + }; + pl_items[i] = PL_ObjectForKey (properties, var_syms[i + 6].name); + } + pl_items[num_keys + 0] = PL_ObjectForKey (item, "images"); + pl_items[num_keys + 1] = PL_ObjectForKey (item, "views"); + + var_syms[num_keys + 0] = (exprsym_t) { + .name = "images", + .type = &cexpr_plitem, + .value = pl_items + 0, + }, + var_syms[num_keys + 1] = (exprsym_t) { + .name = "views", + .type = &cexpr_plitem, + .value = pl_items + 1, + }, + var_syms[num_keys + 2] = (exprsym_t) { + .name = "output", + .type = &qfv_output_t_type, + .value = &sctx->output, + }; + var_syms[num_keys + 3] = (exprsym_t) { + .name = "frames", + .type = &vulkan_frameset_t_type, + .value = &ctx->frames, + }; + var_syms[num_keys + 4] = (exprsym_t) { + .name = "msaaSamples", + .type = &VkSampleCountFlagBits_type, + .value = &ctx->msaaSamples, + }; + var_syms[num_keys + 5] = (exprsym_t) { + .name = "physDevLimits", + .type = &VkPhysicalDeviceLimits_type, + .value = &ctx->device->physDev->properties->limits, + }; + + exprctx.external_variables = &vars_tab; + exprctx.messages = messages; + exprctx.hashctx = &sctx->hashctx; + exprctx.memsuper = memsuper; + + cexpr_init_symtab (&vars_tab, &exprctx); + + int ret; + if (!(ret = parse_qfv_renderinfo_t (0, item, ri, messages, &parsectx))) { + for (int i = 0; i < PL_A_NumObjects (messages); i++) { + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + } + } + Hash_DelTable (vars_tab.tab); + PL_Free (messages); + + return 0; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 922cae566..8b429fdaf 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -77,4 +77,6 @@ int QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, plitem_t *properties); int QFV_ParseOutput (vulkan_ctx_t *ctx, qfv_output_t *output, plitem_t *plist, plitem_t *properties); +struct qfv_renderinfo_s *QFV_ParseRenderInfo (vulkan_ctx_t *ctx, + plitem_t *item); #endif//__vkparse_h From d34e6cffdf5a74020d2a8f6e58c6d0aac2dd5f32 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Feb 2023 21:20:27 +0900 Subject: [PATCH 3408/3664] [vkgen] Clean up most of the generated header I'll probably completely remove it as only vkparse.c includes it, but this tidies things up a bit and even simplifies vkgen's loops a little. --- libs/video/renderer/vulkan/vkgen/vkenum.h | 1 + libs/video/renderer/vulkan/vkgen/vkenum.r | 14 ++-- .../renderer/vulkan/vkgen/vkfixedarray.h | 1 + .../renderer/vulkan/vkgen/vkfixedarray.r | 4 ++ libs/video/renderer/vulkan/vkgen/vkgen.r | 21 +----- libs/video/renderer/vulkan/vkgen/vkstruct.h | 1 + libs/video/renderer/vulkan/vkgen/vkstruct.r | 64 ++++++++++++------- libs/video/renderer/vulkan/vkparse.plist | 1 + 8 files changed, 57 insertions(+), 50 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.h b/libs/video/renderer/vulkan/vkgen/vkenum.h index 5577b8a23..72a711f1c 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.h +++ b/libs/video/renderer/vulkan/vkgen/vkenum.h @@ -9,6 +9,7 @@ { int prefix_length; } +-(void) writeForward; -(void) writeTable; -(void) writeSymtabInit; -(void) writeSymtabEntry; diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index bd12ade7f..8b7bde8f5 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -83,6 +83,11 @@ skip_value(string name) return !num_values; } +-(void) writeForward +{ + fprintf (output_file, "static exprenum_t %s_enum;\n", [self name]); +} + -(void) writeTable { int strip_bit = 0; @@ -123,7 +128,7 @@ skip_value(string name) } fprintf (output_file, "};\n"); } - fprintf (output_file, "exprsym_t %s_symbols[] = {\n", [self name]); + fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self name]); for (int i = 0, index = 0; i < type.strct.num_fields; i++) { qfot_var_t *var = &type.strct.fields[i]; if (skip_value (var.name)) { @@ -151,10 +156,10 @@ skip_value(string name) } fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); - fprintf (output_file, "exprtab_t %s_symtab = {\n", [self name]); + fprintf (output_file, "static exprtab_t %s_symtab = {\n", [self name]); fprintf (output_file, "\t%s_symbols,\n", [self name]); fprintf (output_file, "};\n"); - fprintf (output_file, "exprenum_t %s_enum = {\n", [self name]); + fprintf (output_file, "static exprenum_t %s_enum = {\n", [self name]); fprintf (output_file, "\t&%s_type,\n", [self name]); fprintf (output_file, "\t&%s_symtab,\n", [self name]); fprintf (output_file, "};\n"); @@ -177,10 +182,7 @@ skip_value(string name) " const plitem_t *item, void *data, plitem_t *messages," " void *context);\n", [self name]); - fprintf (header_file, "extern exprenum_t %s_enum;\n", [self name]); fprintf (header_file, "extern exprtype_t %s_type;\n", [self name]); - fprintf (header_file, "extern exprtab_t %s_symtab;\n", [self name]); - fprintf (header_file, "extern exprsym_t %s_symbols[];\n", [self name]); } -(void) writeSymtabInit diff --git a/libs/video/renderer/vulkan/vkgen/vkfixedarray.h b/libs/video/renderer/vulkan/vkgen/vkfixedarray.h index 649dc1308..7e3af6b75 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfixedarray.h +++ b/libs/video/renderer/vulkan/vkgen/vkfixedarray.h @@ -11,6 +11,7 @@ Type *ele_type; int ele_count; } +-(void) writeForward; -(void) writeTable; -(void) writeSymtabInit; -(void) writeSymtabEntry; diff --git a/libs/video/renderer/vulkan/vkgen/vkfixedarray.r b/libs/video/renderer/vulkan/vkgen/vkfixedarray.r index b7cd47463..c467cde86 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfixedarray.r +++ b/libs/video/renderer/vulkan/vkgen/vkfixedarray.r @@ -37,6 +37,10 @@ } } +-(void) writeForward +{ +} + -(void) writeTable { fprintf (output_file, "static parse_fixed_array_t parse_%s_data = {\n", diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 8b5abd8c2..c938bbc5e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -223,12 +223,9 @@ main(int argc, string *argv) if ([obj name] == "VkStructureType") { continue; } - if ([obj class] != [Enum class]) { - continue; - } arp_start (); - [obj writeTable]; + [obj writeForward]; arp_end (); } for (int i = [output_types count]; i-- > 0; ) { @@ -236,22 +233,6 @@ main(int argc, string *argv) if ([obj name] == "VkStructureType") { continue; } - if ([obj class] != [FixedArray class]) { - continue; - } - - arp_start (); - [obj writeTable]; - arp_end (); - } - for (int i = [output_types count]; i-- > 0; ) { - id obj = [output_types objectAtIndex:i]; - if ([obj name] == "VkStructureType") { - continue; - } - if ([obj class] != [Struct class]) { - continue; - } arp_start (); [obj writeTable]; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index 5ed901e9e..9ff3137e4 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -15,6 +15,7 @@ } -(void) queueFieldTypes; -(qfot_var_t *)findField:(string) fieldName; +-(void) writeForward; -(void) writeTable; -(void) writeSymtabInit; -(void) writeSymtabEntry; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 12b0bfb46..3c111b94a 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -31,6 +31,11 @@ { qfot_struct_t *strct =&type.strct; PLItem *field_dict = [parse getObjectForKey:[self name]]; + int readonly = [field_dict string] == "readonly"; + + if (readonly) { + return; + } for (int i = 0; i < strct.num_fields; i++) { qfot_var_t *var = &strct.fields[i]; @@ -78,6 +83,18 @@ return str_upper (s); } +-(void) writeForward +{ + PLItem *field_dict = [parse getObjectForKey:[self name]]; + int readonly = [field_dict string] == "readonly"; + if (!readonly) { + fprintf (output_file, "static int %s (const plfield_t *field," + " const plitem_t *item, void *data, plitem_t *messages," + " void *context);\n", + [self parseFunc]); + } +} + -(void) writeTable { PLItem *field_dict = [parse getObjectForKey:[self name]]; @@ -85,6 +102,7 @@ Array *field_defs = [Array array]; int have_sType = 0; int have_pNext = 0; + int readonly = [field_dict string] == "readonly"; if ([parse string] == "skip") { return; @@ -138,6 +156,7 @@ FieldDef *field_def = [field_defs objectAtIndex:i]; [field_def writeParseData]; } + if (!readonly) { fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self outname]); fprintf (output_file, "\t{\"@inherit\", 0, QFString, parse_inherit, &%s_fields},\n", @@ -154,33 +173,30 @@ fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); - fprintf (header_file, "int %s (const plfield_t *field," - " const plitem_t *item, void *data, plitem_t *messages," - " void *context);\n", - [self parseFunc]); - fprintf (output_file, "int %s (const plfield_t *field," + fprintf (output_file, "static int %s (const plfield_t *field," " const plitem_t *item, void *data, plitem_t *messages," " void *context)\n", [self parseFunc]); - fprintf (output_file, "{\n"); - if (have_sType) { - fprintf (output_file, "\t((%s *) data)->sType", [self outname]); - fprintf (output_file, " = %s;\n", [self sTypeName]); - } - fprintf (output_file, - "\tif (PL_Type (item) == QFString\n" - "\t\t&& !(item = parse_reference (item, \"%s\", messages, context))) {\n" - "\t\treturn 0;\n" - "\t}\n" - "\treturn PL_ParseStruct (%s_fields, item, data, messages," - " context);\n", - [self outname], [self outname]); - fprintf (output_file, "}\n"); - if (have_pNext) { - fprintf (output_file, "static parserref_t %s_parser = ", - [self outname]); - fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", - [self outname], [self parseFunc], [self outname]); + fprintf (output_file, "{\n"); + if (have_sType) { + fprintf (output_file, "\t((%s *) data)->sType", [self outname]); + fprintf (output_file, " = %s;\n", [self sTypeName]); + } + fprintf (output_file, + "\tif (PL_Type (item) == QFString\n" + "\t\t&& !(item = parse_reference (item, \"%s\", messages, context))) {\n" + "\t\treturn 0;\n" + "\t}\n" + "\treturn PL_ParseStruct (%s_fields, item, data, messages," + " context);\n", + [self outname], [self outname]); + fprintf (output_file, "}\n"); + if (have_pNext) { + fprintf (output_file, "static parserref_t %s_parser = ", + [self outname]); + fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", + [self outname], [self parseFunc], [self outname]); + } } fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self outname]); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index d20a2aad9..d3b7be36c 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -74,6 +74,7 @@ values = pPreserveAttachments; }; }; + VkPhysicalDeviceLimits = readonly; VkRenderPassCreateInfo = { //flags = auto; reserved for future use (Bits enum does not exist) attachments = { From c3f8e5bcc572759fc60f99546c305ba067fe800a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Feb 2023 09:37:09 +0900 Subject: [PATCH 3409/3664] [vkgen] Support ignored fields This allows having sections in a spec used for things like `properties` that have no corresponding fields in the actual struct: the field is ignored when parsing and no cexpr field symbol is emitted. --- .../video/renderer/vulkan/vkgen/Makemodule.am | 2 + libs/video/renderer/vulkan/vkgen/vkfielddef.r | 3 + .../renderer/vulkan/vkgen/vkfieldignore.h | 14 +++++ .../renderer/vulkan/vkgen/vkfieldignore.r | 63 +++++++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldignore.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldignore.r diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 90d01645e..83fab1eee 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -11,6 +11,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkfieldcustom.r \ libs/video/renderer/vulkan/vkgen/vkfielddata.r \ libs/video/renderer/vulkan/vkgen/vkfielddef.r \ + libs/video/renderer/vulkan/vkgen/vkfieldignore.r \ libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.r \ libs/video/renderer/vulkan/vkgen/vkfieldstring.r \ @@ -55,6 +56,7 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/vkgen/vkfieldcustom.h \ libs/video/renderer/vulkan/vkgen/vkfielddata.h \ libs/video/renderer/vulkan/vkgen/vkfielddef.h \ + libs/video/renderer/vulkan/vkgen/vkfieldignore.h \ libs/video/renderer/vulkan/vkgen/vkfieldreadonly.h \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.h \ libs/video/renderer/vulkan/vkgen/vkfieldstring.h \ diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.r b/libs/video/renderer/vulkan/vkgen/vkfielddef.r index 9a7f34bd0..71e82e57f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfielddef.r +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.r @@ -6,6 +6,7 @@ #include "vkfieldcustom.h" #include "vkfielddata.h" #include "vkfielddef.h" +#include "vkfieldignore.h" #include "vkfieldreadonly.h" #include "vkfieldsingle.h" #include "vkfieldstring.h" @@ -45,6 +46,8 @@ return [[[ArrayField alloc] init:item struct:strct field:fname] autorelease]; case "readonly": return [[[ReadOnlyField alloc] init:item struct:strct field:fname] autorelease]; + case "ignore": + return [[[IgnoreField alloc] init:item struct:strct field:fname] autorelease]; } return nil; } diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldignore.h b/libs/video/renderer/vulkan/vkgen/vkfieldignore.h new file mode 100644 index 000000000..fd2b34374 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldignore.h @@ -0,0 +1,14 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldignore_h +#define __renderer_vulkan_vkgen_vkfieldignore_h + +#include "vkfielddef.h" + +@class FieldType; + +@interface IgnoreField: FieldDef +{ + FieldType *type; +} +@end + +#endif//__renderer_vulkan_vkgen_vkfieldignore_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldignore.r b/libs/video/renderer/vulkan/vkgen/vkfieldignore.r new file mode 100644 index 000000000..dfbb71387 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldignore.r @@ -0,0 +1,63 @@ +#include +#include + +#include "vkfieldignore.h" +#include "vkfieldtype.h" +#include "vkstruct.h" + +@implementation IgnoreField + +-init:(PLItem *)item struct:(Struct *)strct field:(string)fname +{ + self = [super init]; + if (!self) { + return self; + } + + line = [item line]; + struct_name = str_hold ([strct outname]); + field_name = str_hold (fname); + return self; +} + +-fromField:(qfot_var_t *)field struct:(Struct *)strct +{ + return self; +} + +-(void)dealloc +{ + str_free (struct_name); + str_free (field_name); + [super dealloc]; +} + +-writeParseData +{ + return self; +} + +-writeField +{ + string parse_type = [FieldType anyType]; + fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, 0},\n", + field_name, parse_type, "ignore"); + return self; +} + +-writeSymbol +{ + return self; +} + +-(string) name +{ + return field_name; +} + +-(int) searchType +{ + return 1; +} + +@end From c94e691e7e922a77cedf87c0c13760923882266a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Feb 2023 09:39:13 +0900 Subject: [PATCH 3410/3664] [vkgen] Fix some whitespace I thought I'd indented that block, but I guess I'd gotten confused while doing some before and after checks of the indent. --- libs/video/renderer/vulkan/vkgen/vkstruct.r | 75 +++++++++++---------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 3c111b94a..85309f011 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -157,46 +157,47 @@ [field_def writeParseData]; } if (!readonly) { - fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self outname]); - fprintf (output_file, - "\t{\"@inherit\", 0, QFString, parse_inherit, &%s_fields},\n", - [self outname]); - if (have_pNext) { + fprintf (output_file, "static plfield_t %s_fields[] = {\n", + [self outname]); fprintf (output_file, - "\t{\"@next\", field_offset (%s, pNext), " - "QFArray, parse_next, 0},", [self outname]); - } - for (int i = [field_defs count]; i-- > 0; ) { - FieldDef *field_def = [field_defs objectAtIndex:i]; - [field_def writeField]; - } - fprintf (output_file, "\t{ }\n"); - fprintf (output_file, "};\n"); - - fprintf (output_file, "static int %s (const plfield_t *field," - " const plitem_t *item, void *data, plitem_t *messages," - " void *context)\n", - [self parseFunc]); - fprintf (output_file, "{\n"); - if (have_sType) { - fprintf (output_file, "\t((%s *) data)->sType", [self outname]); - fprintf (output_file, " = %s;\n", [self sTypeName]); - } - fprintf (output_file, - "\tif (PL_Type (item) == QFString\n" - "\t\t&& !(item = parse_reference (item, \"%s\", messages, context))) {\n" - "\t\treturn 0;\n" - "\t}\n" - "\treturn PL_ParseStruct (%s_fields, item, data, messages," - " context);\n", - [self outname], [self outname]); - fprintf (output_file, "}\n"); + "\t{\"@inherit\", 0, QFString, parse_inherit, &%s_fields},\n", + [self outname]); if (have_pNext) { - fprintf (output_file, "static parserref_t %s_parser = ", - [self outname]); - fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", - [self outname], [self parseFunc], [self outname]); + fprintf (output_file, + "\t{\"@next\", field_offset (%s, pNext), " + "QFArray, parse_next, 0},", [self outname]); } + for (int i = [field_defs count]; i-- > 0; ) { + FieldDef *field_def = [field_defs objectAtIndex:i]; + [field_def writeField]; + } + fprintf (output_file, "\t{ }\n"); + fprintf (output_file, "};\n"); + + fprintf (output_file, "static int %s (const plfield_t *field," + " const plitem_t *item, void *data, plitem_t *messages," + " void *context)\n", + [self parseFunc]); + fprintf (output_file, "{\n"); + if (have_sType) { + fprintf (output_file, "\t((%s *) data)->sType", [self outname]); + fprintf (output_file, " = %s;\n", [self sTypeName]); + } + fprintf (output_file, + "\tif (PL_Type (item) == QFString\n" + "\t\t&& !(item = parse_reference (item, \"%s\", messages, context))) {\n" + "\t\treturn 0;\n" + "\t}\n" + "\treturn PL_ParseStruct (%s_fields, item, data, messages," + " context);\n", + [self outname], [self outname]); + fprintf (output_file, "}\n"); + if (have_pNext) { + fprintf (output_file, "static parserref_t %s_parser = ", + [self outname]); + fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", + [self outname], [self parseFunc], [self outname]); + } } fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self outname]); From 9e050ebf9aefba0aed2b2c575cd713235d947e51 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Feb 2023 11:04:11 +0900 Subject: [PATCH 3411/3664] [vulkan] Attempt to load the render info spec It fails due to not supporting labeled arrays yet. I'm currently thinking about the design for vkgen. --- include/QF/Vulkan/render.h | 1 + libs/video/renderer/Makemodule.am | 4 ++++ libs/video/renderer/vid_render_vulkan.c | 2 ++ libs/video/renderer/vulkan/render.c | 11 +++++++++ libs/video/renderer/vulkan/rp_main_def.plist | 24 ++++++++++++-------- libs/video/renderer/vulkan/vkparse.c | 6 ++++- libs/video/renderer/vulkan/vkparse.plist | 2 +- 7 files changed, 38 insertions(+), 12 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 2e75bc44e..4ba23a6a2 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -165,5 +165,6 @@ typedef struct qfv_renderpass_s_ { } qfv_renderpass_t_; void QFV_RunRenderPass (qfv_renderpass_t_ *rp, struct vulkan_ctx_s *ctx); +void QFV_LoadRenderPass (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_render_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index e48676839..52df27996 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -201,6 +201,8 @@ rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist rp_forward_gen = libs/video/renderer/vulkan/rp_forward.plc +rp_main_def_src = libs/video/renderer/vulkan/rp_main_def.plist +rp_main_def_gen = libs/video/renderer/vulkan/rp_main_def.plc rp_output_src = libs/video/renderer/vulkan/rp_output.plist rp_output_gen = libs/video/renderer/vulkan/rp_output.plc rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist @@ -266,6 +268,7 @@ libs/video/renderer/vulkan/vkparse.lo: \ ${rp_defcube_gen} \ ${rp_deferred_gen} \ $(rp_forward_gen) \ + $(rp_main_def_gen) \ $(rp_output_gen) \ ${rp_shadow_gen} @@ -525,6 +528,7 @@ EXTRA_DIST += \ $(rp_defcube_src) \ $(rp_deferred_src) \ $(rp_forward_src) \ + $(rp_main_def_src) \ $(rp_output_src) \ $(rp_shadow_src) \ $(pl_quake_def_src) \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 8ccea1487..701b39031 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -66,6 +66,7 @@ #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/staging.h" #include "QF/Vulkan/swapchain.h" #include "QF/ui/view.h" @@ -98,6 +99,7 @@ vulkan_R_Init (void) Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); + QFV_LoadRenderPass (vulkan_ctx); Vulkan_CreateRenderPasses (vulkan_ctx); Vulkan_Output_Init (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 8333d6ccf..3bd36255b 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -45,6 +45,9 @@ #include "QF/Vulkan/pipeline.h" #include "vid_vulkan.h" +#include "QF/Vulkan/qf_renderpass.h"//FIXME +#include "vkparse.h" + static void run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) { @@ -120,3 +123,11 @@ QFV_RunRenderPass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) } QFV_CmdEndLabel (device, cmd); } + +void +QFV_LoadRenderPass (vulkan_ctx_t *ctx) +{ + plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); + __auto_type ri = QFV_ParseRenderInfo (ctx, item); + printf ("%p\n", ri); +} diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 5b840f30c..0ad65c301 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1,4 +1,5 @@ -properties { +{ +properties = { color = { bsp = "[0, 0.5, 0.6, 1]"; alias = "[0.6, 0.5, 0, 1]"; @@ -171,7 +172,7 @@ renderpasses = { format = $images.output.format; loadOp = clear; storeOp = store; - $output.finalLayout; + finalLayout = $output.finalLayout; }; }; framebuffer = { @@ -226,7 +227,7 @@ renderpasses = { color = "[ 0.25, 0.25, 0.6, 1]"; dependencies = { depth = $depth_dependency; - } + }; attachments = { depth = depth_stencil_read_only_optimal; preserve = (color, emission, normal, position, output); @@ -251,10 +252,12 @@ renderpasses = { params = (main, turbulent); }, ); }; - particles:trans { + particles:trans = { color = $color.particles; pipline = partdraw; - { func = particles_draw; }, + tasks = ( + { func = particles_draw; }, + ); }; }; }; @@ -262,7 +265,7 @@ renderpasses = { color = "[ 0.3, 0.7, 0.3, 1]"; dependencies = { depth = $depth_dependency; - } + }; attachments = { color = { color = color_attachment_optimal; @@ -311,7 +314,7 @@ renderpasses = { color = "[ 0.8, 0.8, 0.8, 1]"; dependencies = { gbuffer = $color_dependency; - } + }; attachments = { input = { depth = shader_read_only_optimal; @@ -327,7 +330,7 @@ renderpasses = { }; pipelines = { lights = { - color = $color.lights + color = $color.lights; pipeline = lighting; tasks = ( { func = "lights_draw"; }, @@ -339,7 +342,7 @@ renderpasses = { color = "[ 0.7, 0.3, 0.3, 1]"; dependencies = { lighting = $color_dependency; - } + }; attachments = { input = { opaque = shader_read_only_optimal; @@ -351,7 +354,7 @@ renderpasses = { }; pipelines = { compose = { - color = $color.compose + color = $color.compose; pipeline = compose; tasks = ( { func = "lights_draw"; }, @@ -369,3 +372,4 @@ renderpasses = { }); }; }; +}; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 27ee9d36b..8dc0157fd 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1757,6 +1757,10 @@ static exprsym_t builtin_plist_syms[] = { .value = (void *) #include "libs/video/renderer/vulkan/rp_forward.plc" }, + { .name = "main_def", + .value = (void *) +#include "libs/video/renderer/vulkan/rp_main_def.plc" + }, { .name = "output", .value = (void *) #include "libs/video/renderer/vulkan/rp_output.plc" @@ -2063,7 +2067,7 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) .type = &cexpr_plitem, .value = pl_items + i, }; - pl_items[i] = PL_ObjectForKey (properties, var_syms[i + 6].name); + pl_items[i] = PL_ObjectForKey (properties, var_syms[i].name); } pl_items[num_keys + 0] = PL_ObjectForKey (item, "images"); pl_items[num_keys + 1] = PL_ObjectForKey (item, "views"); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index d3b7be36c..125ce5b72 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -533,7 +533,7 @@ }; qfv_renderinfo_s = { .name = qfv_renderinfo_t; - //properties = auto; + properties = ignore; images = { type = (array, qfv_imageinfo_t); size = num_images; From 061f90ab839b489d4b14d9f497efab1b106d1efe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Feb 2023 19:33:10 +0900 Subject: [PATCH 3412/3664] [vkgen] Add support for array element data While I wound up not needing it in the end, it's now possible to specify extra data for array element parsing. --- libs/video/renderer/vulkan/vkgen/vkfieldtype.h | 2 ++ libs/video/renderer/vulkan/vkgen/vkfieldtype.r | 12 ++++++++++++ libs/video/renderer/vulkan/vkparse.c | 7 +++++-- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.h b/libs/video/renderer/vulkan/vkgen/vkfieldtype.h index 88d117d4b..c361d44fe 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldtype.h +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.h @@ -10,10 +10,12 @@ string parse_type; string type; string parser; + string data; } +fieldType:(PLItem *)item; -initWithItem:(PLItem *)item; -writeParseData; +-(string)type; -(string)exprType; -(string)parseType; +(string)anyType; diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r index 83776a6a5..0986a8e31 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldtype.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldtype.r @@ -31,6 +31,7 @@ parseItemType (PLItem *item) { str_free (type); str_free (parser); + str_free (data); str_free (parse_type); [super dealloc]; } @@ -52,6 +53,7 @@ parseItemType (PLItem *item) parse_type = str_hold (parseItemType(typeItem)); type = str_hold ([[item getObjectForKey:"type"] string]); parser = str_hold ([[item getObjectForKey:"parser"] string]); + data = str_hold ([[item getObjectForKey:"data"] string]); } return self; @@ -62,9 +64,19 @@ parseItemType (PLItem *item) fprintf (output_file, "\t%s,\n", parse_type); fprintf (output_file, "\tsizeof (%s),\n", type); fprintf (output_file, "\t%s,\n", parser); + if (data) { + fprintf (output_file, "\t&%s,\n", data); + } else { + fprintf (output_file, "\t0,\n"); + } return self; } +-(string) type +{ + return type; +} + -(string) exprType { return "&" + type + "_type"; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 8dc0157fd..49ff4d182 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -115,6 +115,7 @@ typedef struct parse_single_s { pltype_t type; size_t stride; plparser_t parser; + void *data; size_t value_offset; } parse_single_t; @@ -122,6 +123,7 @@ typedef struct parse_array_s { pltype_t type; size_t stride; plparser_t parser; + void *data; size_t value_offset; size_t size_offset; } parse_array_t; @@ -130,6 +132,7 @@ typedef struct parse_fixed_array_s { pltype_t type; size_t stride; plparser_t parser; + void *data; size_t size; } parse_fixed_array_t; @@ -341,7 +344,7 @@ parse_array (const plfield_t *field, const plitem_t *item, array->stride, vkparse_alloc, array->parser, - 0, + array->data, }; plfield_t f = { 0, 0, 0, 0, &element }; @@ -376,7 +379,7 @@ parse_fixed_array (const plfield_t *field, const plitem_t *item, array->stride, vkparse_alloc, array->parser, - 0, + array->data, }; plfield_t f = { 0, 0, 0, 0, &element }; From 3498d8b2aee915510f1a722a4f1e8a9ef96a569e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Feb 2023 19:36:53 +0900 Subject: [PATCH 3413/3664] [vkgen] Add support for labeled array elements This treats dictionary items as arrays ordered by key creation (ie, the order of the key/value pairs in the dictionary is preserved). The label is written to the specified field when parsing the struct. Both actual arrays and single element "arrays" are supported. --- .../video/renderer/vulkan/vkgen/Makemodule.am | 4 + libs/video/renderer/vulkan/vkgen/vkfielddef.r | 6 ++ .../vulkan/vkgen/vkfieldlabeledarray.h | 11 +++ .../vulkan/vkgen/vkfieldlabeledarray.r | 37 +++++++++ .../vulkan/vkgen/vkfieldlabeledsingle.h | 11 +++ .../vulkan/vkgen/vkfieldlabeledsingle.r | 37 +++++++++ libs/video/renderer/vulkan/vkgen/vkstruct.h | 2 + libs/video/renderer/vulkan/vkgen/vkstruct.r | 18 ++++- libs/video/renderer/vulkan/vkparse.c | 78 ++++++++++++++++++- 9 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.r create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.h create mode 100644 libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.r diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 83fab1eee..dd2d82a63 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -12,6 +12,8 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vkfielddata.r \ libs/video/renderer/vulkan/vkgen/vkfielddef.r \ libs/video/renderer/vulkan/vkgen/vkfieldignore.r \ + libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.r \ + libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.r \ libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.r \ libs/video/renderer/vulkan/vkgen/vkfieldstring.r \ @@ -57,6 +59,8 @@ EXTRA_DIST += \ libs/video/renderer/vulkan/vkgen/vkfielddata.h \ libs/video/renderer/vulkan/vkgen/vkfielddef.h \ libs/video/renderer/vulkan/vkgen/vkfieldignore.h \ + libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.h \ + libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.h \ libs/video/renderer/vulkan/vkgen/vkfieldreadonly.h \ libs/video/renderer/vulkan/vkgen/vkfieldsingle.h \ libs/video/renderer/vulkan/vkgen/vkfieldstring.h \ diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.r b/libs/video/renderer/vulkan/vkgen/vkfielddef.r index 71e82e57f..9638dd109 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfielddef.r +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.r @@ -7,6 +7,8 @@ #include "vkfielddata.h" #include "vkfielddef.h" #include "vkfieldignore.h" +#include "vkfieldlabeledarray.h" +#include "vkfieldlabeledsingle.h" #include "vkfieldreadonly.h" #include "vkfieldsingle.h" #include "vkfieldstring.h" @@ -44,6 +46,10 @@ return [[[SingleField alloc] init:item struct:strct field:fname] autorelease]; case "array": return [[[ArrayField alloc] init:item struct:strct field:fname] autorelease]; + case "labeledarray": + return [[[LabeledArrayField alloc] init:item struct:strct field:fname] autorelease]; + case "labeledsingle": + return [[[LabeledSingleField alloc] init:item struct:strct field:fname] autorelease]; case "readonly": return [[[ReadOnlyField alloc] init:item struct:strct field:fname] autorelease]; case "ignore": diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.h b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.h new file mode 100644 index 000000000..db3ec6b15 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.h @@ -0,0 +1,11 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldlabeledarray_h +#define __renderer_vulkan_vkgen_vkfieldlabeledarray_h + +#include "vkfieldarray.h" + +@interface LabeledArrayField: ArrayField +{ +} +@end + +#endif//__renderer_vulkan_vkgen_vkfieldlabeledarray_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.r b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.r new file mode 100644 index 000000000..efb02f782 --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.r @@ -0,0 +1,37 @@ +#include + +#include "vkfieldlabeledarray.h" +#include "vkfieldtype.h" +#include "vkgen.h" +#include "vkstruct.h" +#include "vktype.h" + +@implementation LabeledArrayField + +-init:(PLItem *) item struct:(Struct *)strct field:(string)fname +{ + self = [super init:item struct:strct field:fname]; + if (!self) { + return self; + } + + PLItem *desc = [item getObjectForKey:"type"]; + string label_field = [[desc getObjectAtIndex:2] string]; + Type *t = [[Type lookup:[type type]] resolveType]; + if ([t isKindOfClass:[Struct class]]) { + Struct *s = (Struct *) t; + [s setLabelField:label_field]; + } + + return self; +} + +-writeField +{ + fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", + field_name, "QFDictionary", "labeledarray", struct_name, + field_name); + return self; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.h b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.h new file mode 100644 index 000000000..7685c366c --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.h @@ -0,0 +1,11 @@ +#ifndef __renderer_vulkan_vkgen_vkfieldlabeledsingle_h +#define __renderer_vulkan_vkgen_vkfieldlabeledsingle_h + +#include "vkfieldsingle.h" + +@interface LabeledSingleField: SingleField +{ +} +@end + +#endif//__renderer_vulkan_vkgen_vkfieldlabeledsingle_h diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.r b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.r new file mode 100644 index 000000000..fe3fd9dce --- /dev/null +++ b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledsingle.r @@ -0,0 +1,37 @@ +#include + +#include "vkfieldlabeledsingle.h" +#include "vkfieldtype.h" +#include "vkgen.h" +#include "vkstruct.h" +#include "vktype.h" + +@implementation LabeledSingleField + +-init:(PLItem *) item struct:(Struct *)strct field:(string)fname +{ + self = [super init:item struct:strct field:fname]; + if (!self) { + return self; + } + + PLItem *desc = [item getObjectForKey:"type"]; + string label_field = [[desc getObjectAtIndex:2] string]; + Type *t = [[Type lookup:[type type]] resolveType]; + if ([t isKindOfClass:[Struct class]]) { + Struct *s = (Struct *) t; + [s setLabelField:label_field]; + } + + return self; +} + +-writeField +{ + fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", + field_name, "QFDictionary", "labeledsingle", struct_name, + field_name); + return self; +} + +@end diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index 9ff3137e4..095c22629 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -11,10 +11,12 @@ @interface Struct: Type { string outname; + string label_field; int write_symtab; } -(void) queueFieldTypes; -(qfot_var_t *)findField:(string) fieldName; +-(void) setLabelField:(string) label_field; -(void) writeForward; -(void) writeTable; -(void) writeSymtabInit; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 85309f011..11818209f 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -12,6 +12,12 @@ @implementation Struct +-(void) dealloc +{ + str_free (outname); + str_free (label_field); +} + -(string) name { return str_mid(type.strct.tag, 4); @@ -67,7 +73,7 @@ -(string)sTypeName { string s = "VK_STRUCTURE_TYPE"; - string name = str_hold ([self outname]); + string name = [self outname]; int length = strlen (name); int start, end, c; for (start = 2; start < length; start = end) { @@ -83,6 +89,11 @@ return str_upper (s); } +-(void) setLabelField:(string)label_field +{ + self.label_field = label_field; +} + -(void) writeForward { PLItem *field_dict = [parse getObjectForKey:[self name]]; @@ -183,6 +194,11 @@ fprintf (output_file, "\t((%s *) data)->sType", [self outname]); fprintf (output_file, " = %s;\n", [self sTypeName]); } + if (label_field) { + fprintf (output_file, "\t((%s *) data)->%s", [self outname], + label_field); + fprintf (output_file, " = vkstrdup (context, field->name);\n"); + } fprintf (output_file, "\tif (PL_Type (item) == QFString\n" "\t\t&& !(item = parse_reference (item, \"%s\", messages, context))) {\n" diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 49ff4d182..3d7d3298a 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -303,6 +303,34 @@ parse_ignore (const plfield_t *field, const plitem_t *item, return 1; } +static int __attribute__((used)) +parse_labeledsingle (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + __auto_type single = (parse_single_t *) field->data; + void *flddata = (byte *)data + single->value_offset; + + //Sys_MaskPrintf (SYS_vulkan_parse,"parse_labeledsingle: %s %zd %d %p %p\n", + // field->name, field->offset, + // field->type, field->parser, field->data); + + if (!PL_CheckType (single->type, PL_Type (item))) { + PL_TypeMismatch (messages, item, field->name, single->type, + PL_Type (item)); + return 0; + } + + plfield_t f = { 0, 0, single->type, single->parser, 0 }; + void *value = vkparse_alloc (context, single->stride); + memset (value, 0, single->stride); + if (!single->parser (&f, item, value, messages, context)) { + return 0; + } + + *(void **) flddata = value; + return 1; +} + static int parse_single (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -331,6 +359,43 @@ parse_single (const plfield_t *field, const plitem_t *item, return 1; } +static int __attribute__((used)) +parse_labeledarray (const plfield_t *field, const plitem_t *item, + void *data, plitem_t *messages, void *context) +{ + __auto_type array = (parse_array_t *) field->data; + __auto_type value = (void **) ((byte *)data + array->value_offset); + __auto_type size = (uint32_t *) ((byte *)data + array->size_offset); + + plelement_t element = { + array->type, + array->stride, + vkparse_alloc, + array->parser, + array->data, + }; + plfield_t f = { 0, 0, 0, 0, &element }; + + typedef struct arr_s DARRAY_TYPE(byte) arr_t; + arr_t *arr; + + //Sys_MaskPrintf (SYS_vulkan_parse, "parse_array: %s %zd %d %p %p %p\n", + // field->name, field->offset, field->type, field->parser, + // field->data, data); + //Sys_MaskPrintf (SYS_vulkan_parse, " %d %zd %p %zd %zd\n", array->type, + // array->stride, array->parser, array->value_offset, + // array->size_offset); + if (!PL_ParseLabeledArray (&f, item, &arr, messages, context)) { + return 0; + } + *value = vkparse_alloc (context, array->stride * arr->size); + memcpy (*value, arr->a, array->stride * arr->size); + if ((void *) size >= data) { + *size = arr->size; + } + return 1; +} + static int parse_array (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -395,6 +460,15 @@ parse_fixed_array (const plfield_t *field, const plitem_t *item, return 1; } +static char * +vkstrdup (parsectx_t *context, const char *str) +{ + size_t len = strlen (str) + 1; + char *dup = vkparse_alloc (context, len); + memcpy (dup, str, len); + return dup; +} + static int parse_string (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -410,9 +484,7 @@ parse_string (const plfield_t *field, const plitem_t *item, //Sys_MaskPrintf (SYS_vulkan_parse, " %zd\n", string->value_offset); //Sys_MaskPrintf (SYS_vulkan_parse, " %s\n", str); - size_t len = strlen (str) + 1; - *value = vkparse_alloc (context, len); - memcpy (*value, str, len); + *value = vkstrdup (context, str); return 1; } From 7235fcb5b9a55752414e0646d0f7e488cfcac1f9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Feb 2023 19:41:05 +0900 Subject: [PATCH 3414/3664] [vkgen] Support direct parsing of a single struct field This is most useful when parsing a labeled array where the key/value pairs go into a simple array: key = value; going to: struct foo { const char *key; enumtype value; }; --- libs/video/renderer/vulkan/vkgen/vkstruct.r | 60 ++++++++++++++++----- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 11818209f..baec9cb8c 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -110,6 +110,7 @@ { PLItem *field_dict = [parse getObjectForKey:[self name]]; PLItem *new_name = [field_dict getObjectForKey:".name"]; + PLItem *only = [field_dict getObjectForKey:".only"]; Array *field_defs = [Array array]; int have_sType = 0; int have_pNext = 0; @@ -132,7 +133,25 @@ write_symtab = 1; } } - if (field_dict) { + if (only) { + string field_name = [only string]; + qfot_var_t *field = nil; + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *f = &type.strct.fields[i]; + if (f.name == field_name) { + field = f; + break; + } + } + Type *field_type = [Type findType: field.type]; + FieldDef *field_def = [field_type fielddef:self field:field.name]; + if (!field_def) { + field_def = [FieldDef fielddef:nil + struct:self + field:field.name]; + } + [field_defs addObject: field_def]; + } else if (field_dict) { PLItem *field_keys = [field_dict allKeys]; for (int i = [field_keys count]; i-- > 0; ) { @@ -170,9 +189,11 @@ if (!readonly) { fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self outname]); - fprintf (output_file, - "\t{\"@inherit\", 0, QFString, parse_inherit, &%s_fields},\n", - [self outname]); + if (!only) { + fprintf (output_file, + "\t{\"@inherit\", 0, QFString, parse_inherit, " + "&%s_fields},\n", [self outname]); + } if (have_pNext) { fprintf (output_file, "\t{\"@next\", field_offset (%s, pNext), " @@ -199,14 +220,29 @@ label_field); fprintf (output_file, " = vkstrdup (context, field->name);\n"); } - fprintf (output_file, - "\tif (PL_Type (item) == QFString\n" - "\t\t&& !(item = parse_reference (item, \"%s\", messages, context))) {\n" - "\t\treturn 0;\n" - "\t}\n" - "\treturn PL_ParseStruct (%s_fields, item, data, messages," - " context);\n", - [self outname], [self outname]); + if (only) { + fprintf (output_file, "\tplfield_t *f = &%s_fields[0];\n", + [self outname]); + fprintf (output_file, + "\tif (!PL_CheckType (PL_Type (item), f->type)) {\n" + "\t\tPL_TypeMismatch (messages, item, " + "f->name, f->type, PL_Type (item));\n" + "\t\treturn 0;\n" + "\t}\n" + "\tvoid *flddata = (byte *)data + f->offset;\n" + "\treturn f->parser (f, item, flddata, messages, " + "context);\n"); + } else { + fprintf (output_file, + "\tif (PL_Type (item) == QFString\n" + "\t\t&& !(item = parse_reference (item, \"%s\", " + "messages, context))) {\n" + "\t\treturn 0;\n" + "\t}\n" + "\treturn PL_ParseStruct (%s_fields, item, data, " + "messages, context);\n", + [self outname], [self outname]); + } fprintf (output_file, "}\n"); if (have_pNext) { fprintf (output_file, "static parserref_t %s_parser = ", From 2287a3de3fc5eedcb80ef3cb414815575756e736 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Feb 2023 19:45:02 +0900 Subject: [PATCH 3415/3664] [vulkan] Get render info parsing partially working A bunch of missed struct members, incorrect parse types, and some logic errors in the parse setup. Still not working due to problems with vectors from plist string references and some other errors, but getting there. --- include/QF/Vulkan/render.h | 17 +++++-- libs/video/renderer/vulkan/rp_main_def.plist | 44 ++++++++--------- libs/video/renderer/vulkan/vkparse.c | 4 +- libs/video/renderer/vulkan/vkparse.plist | 52 +++++++------------- 4 files changed, 55 insertions(+), 62 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 4ba23a6a2..bb45ed4ce 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -19,6 +19,7 @@ typedef struct qfv_imageinfo_s { VkSampleCountFlagBits samples; VkImageTiling tiling; VkImageUsageFlags usage; + VkImageLayout initialLayout; } qfv_imageinfo_t; typedef struct qfv_imageviewinfo_s { @@ -56,6 +57,7 @@ typedef struct qfv_attachmentinfo_s { VkAttachmentStoreOp stencilStoreOp; VkImageLayout initialLayout; VkImageLayout finalLayout; + VkClearValue clearValue; } qfv_attachmentinfo_t; typedef struct qfv_taskinfo_s { @@ -64,15 +66,20 @@ typedef struct qfv_taskinfo_s { } qfv_taskinfo_t; typedef struct qfv_attachmentrefinfo_s { + const char *name; + VkImageLayout layout; +} qfv_attachmentrefinfo_t; + +typedef struct qfv_attachmentsetinfo_s { uint32_t num_input; - const char **input; + qfv_attachmentrefinfo_t *input; uint32_t num_color; - const char **color; - const char **resolve; - const char **depth; + qfv_attachmentrefinfo_t *color; + qfv_attachmentrefinfo_t *resolve; + qfv_attachmentrefinfo_t *depth; uint32_t num_preserve; const char **preserve; -} qfv_attachmentrefinfo_t; +} qfv_attachmentsetinfo_t; typedef struct qfv_pipelineinfo_s { vec4f_t color; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 0ad65c301..f5de3da67 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -69,34 +69,34 @@ properties = { }; images = { depth = { - @inherit = image_base; + @inherit = $image_base; format = x8_d24_unorm_pack32; usage = depth_stencil_attachment|input_attachment|transient_attachment; }; color = { - @inherit = image_base; + @inherit = $image_base; format = r8g8b8a8_unorm; }; emission = { - @inherit = image_base; + @inherit = $image_base; format = r16g16b16a16_sfloat; }; normal = { - @inherit = image_base; + @inherit = $image_base; format = r16g16b16a16_sfloat; }; position = { - @inherit = image_base; + @inherit = $image_base; format = r32g32b32a32_sfloat; }; opaque = { - @inherit = image_base; + @inherit = $image_base; format = r16g16b16a16_sfloat; }; }; views = { depth = { - @inherit = view_base; + @inherit = $view_base; image = depth; format = $images.depth.format; subresourceRange = { @@ -104,32 +104,32 @@ views = { }; }; color = { - @inherit = view_base; + @inherit = $view_base; image = color; format = $images.color.format; }; emission = { - @inherit = view_base; - image = color; - format = $images.color.format; + @inherit = $view_base; + image = emission; + format = $images.emission.format; }; normal = { - @inherit = view_base; - image = color; - format = $images.color.format; + @inherit = $view_base; + image = normal; + format = $images.normal.format; }; position = { - @inherit = view_base; - image = color; - format = $images.color.format; + @inherit = $view_base; + image = position; + format = $images.position.format; }; opaque = { - @inherit = view_base; - image = color; - format = $images.color.format; + @inherit = $view_base; + image = opaque; + format = $images.opaque.format; }; output = { - @inherit = view_base; + @inherit = $view_base; image = $output.image; format = $output.format; } @@ -169,7 +169,7 @@ renderpasses = { }; output = { @inherit = $attachment_base; - format = $images.output.format; + format = $output.format; loadOp = clear; storeOp = store; finalLayout = $output.finalLayout; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 3d7d3298a..1f09f0e3f 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -2150,12 +2150,12 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) var_syms[num_keys + 0] = (exprsym_t) { .name = "images", .type = &cexpr_plitem, - .value = pl_items + 0, + .value = pl_items + num_keys + 0, }, var_syms[num_keys + 1] = (exprsym_t) { .name = "views", .type = &cexpr_plitem, - .value = pl_items + 1, + .value = pl_items + num_keys + 1, }, var_syms[num_keys + 2] = (exprsym_t) { .name = "output", diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 125ce5b72..05f875f98 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -39,6 +39,7 @@ qfv_dependencyinfo_t, qfv_attachmentinfo_t, qfv_attachmentrefinfo_t, + qfv_attachmentsetinfo_t, qfv_taskinfo_t, qfv_pipelineinfo_t, qfv_subpassinfo_t, @@ -434,47 +435,31 @@ }; qfv_attachmentrefinfo_s = { .name = qfv_attachmentrefinfo_t; + .only = layout; + }; + qfv_attachmentsetinfo_s = { + .name = qfv_attachmentsetinfo_t; input = { - type = (array, { - parse_type = QFString; - type = "char *"; - parser = parse_string; - }); + type = (labeledarray, qfv_attachmentrefinfo_t, name); size = num_input; values = input; }; color = { - type = (array, { - parse_type = QFString; - type = "char *"; - parser = parse_string; - }); + type = (labeledarray, qfv_attachmentrefinfo_t, name); size = num_color; values = color; }; resolve = { - type = (array, { - parse_type = QFString; - type = "char *"; - parser = parse_string; - }); + type = (labeledarray, qfv_attachmentrefinfo_t, name); values = resolve; matchSize = color; }; depth = { - type = (single, { - parse_type = QFString; - type = "char *"; - parser = parse_string; - }); + type = (labeledsingle, qfv_attachmentrefinfo_t, name); value = depth; }; preserve = { - type = (array, { - parse_type = QFString; - type = "char *"; - parser = parse_string; - }); + type = (labeledarray, qfv_attachmentrefinfo_t, name); size = num_preserve; values = preserve; }; @@ -502,17 +487,18 @@ type = string; string = name; }; + color = auto; dependencies = { - type = (array, qfv_dependencyinfo_t); + type = (labeledarray, qfv_dependencyinfo_t, name); size = num_dependencies; values = dependencies; }; attachments = { - type = (single, qfv_attachmentrefinfo_t); + type = (single, qfv_attachmentsetinfo_t); value = attachments; }; pipelines = { - type = (array, qfv_pipelineinfo_t); + type = (labeledarray, qfv_pipelineinfo_t, name); size = num_pipelines; values = pipelines; }; @@ -520,13 +506,13 @@ qfv_renderpassinfo_s = { .name = qfv_renderpassinfo_t; attachments = { - type = (array, qfv_attachmentinfo_t); + type = (labeledarray, qfv_attachmentinfo_t, name); size = num_attachments; values = attachments; }; framebuffer = auto; subpasses = { - type = (array, qfv_subpassinfo_t); + type = (labeledarray, qfv_subpassinfo_t, name); size = num_subpasses; values = subpasses; }; @@ -535,17 +521,17 @@ .name = qfv_renderinfo_t; properties = ignore; images = { - type = (array, qfv_imageinfo_t); + type = (labeledarray, qfv_imageinfo_t, name); size = num_images; values = images; }; views = { - type = (array, qfv_imageviewinfo_t); + type = (labeledarray, qfv_imageviewinfo_t, name); size = num_views; values = views; }; renderpasses = { - type = (array, qfv_renderpassinfo_t); + type = (labeledarray, qfv_renderpassinfo_t, name); size = num_renderpasses; values = renderpasses; }; From cd1b20dc22646b0ca678e6fb5953995954140da8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 11 Feb 2023 01:15:19 +0900 Subject: [PATCH 3416/3664] [vulkan] Get render info parsing mostly working Just frame buffer and pipeline info to clean up before worrying about tasks. --- libs/video/renderer/vulkan/rp_main_def.plist | 25 +++++++++++++------- libs/video/renderer/vulkan/vkparse.c | 11 ++++++++- libs/video/renderer/vulkan/vkparse.plist | 7 +++++- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index f5de3da67..82c07e2b2 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1,10 +1,13 @@ { properties = { color = { - bsp = "[0, 0.5, 0.6, 1]"; - alias = "[0.6, 0.5, 0, 1]"; - iqm = "[0.6, 0.5, 0, 1]"; - sprite = "[0.6, 0.5, 0, 1]"; + bsp = "[0.0, 0.5, 0.6, 1]"; + alias = "[0.6, 0.5, 0.0, 1]"; + iqm = "[0.6, 0.5, 0.0, 1]"; + sprite = "[0.6, 0.5, 0.0, 1]"; + particles = "[0.4, 0.5, 0.8, 1]"; + lights = "[0.8, 0.6, 0.2, 1]"; + compose = "[0.7, 0.7, 0.7, 1]"; }; color_dependency = { src = { @@ -186,7 +189,9 @@ renderpasses = { depth = { color = "[ 0.5, 0.5, 0.5, 1]"; attachments = { - depth = depth_stencil_read_only_optimal; + depth = { + depth = depth_stencil_attachment_optimal; + }; preserve = (color, emission, normal, position, output); }; pipelines = { @@ -229,7 +234,9 @@ renderpasses = { depth = $depth_dependency; }; attachments = { - depth = depth_stencil_read_only_optimal; + depth = { + depth = depth_stencil_read_only_optimal; + }; preserve = (color, emission, normal, position, output); }; pipelines = { @@ -254,7 +261,7 @@ renderpasses = { }; particles:trans = { color = $color.particles; - pipline = partdraw; + pipeline = partdraw; tasks = ( { func = particles_draw; }, ); @@ -273,7 +280,9 @@ renderpasses = { normal = color_attachment_optimal; position = color_attachment_optimal; }; - depth = depth_stencil_read_only_optimal; + depth = { + depth = depth_stencil_read_only_optimal; + }; preserve = (output); }; pipelines = { diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 1f09f0e3f..fb11ad67d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -314,13 +314,20 @@ parse_labeledsingle (const plfield_t *field, const plitem_t *item, // field->name, field->offset, // field->type, field->parser, field->data); + const char *key = PL_KeyAtIndex (item, 0); + if (!key) { + PL_Message (messages, item, "missing item"); + return 0; + } + item = PL_ObjectForKey (item, key); + if (!PL_CheckType (single->type, PL_Type (item))) { PL_TypeMismatch (messages, item, field->name, single->type, PL_Type (item)); return 0; } - plfield_t f = { 0, 0, single->type, single->parser, 0 }; + plfield_t f = { field->name, 0, single->type, single->parser, 0 }; void *value = vkparse_alloc (context, single->stride); memset (value, 0, single->stride); if (!single->parser (&f, item, value, messages, context)) { @@ -469,6 +476,8 @@ vkstrdup (parsectx_t *context, const char *str) return dup; } +static parse_string_t parse_string_array = { 0 }; + static int parse_string (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 05f875f98..41fa107f4 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -459,7 +459,12 @@ value = depth; }; preserve = { - type = (labeledarray, qfv_attachmentrefinfo_t, name); + type = (array, { + parse_type = QFString; + type = "char *"; + parser = parse_string; + data = parse_string_array; + }); size = num_preserve; values = preserve; }; From 345aa8e09447fe6496c1ae61873fef67c86ed81d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Feb 2023 02:35:54 +0900 Subject: [PATCH 3417/3664] [vkgen] Add support for directly scripted parsing It's very early, but it does the job for what I needed (storing the string item and line number). --- libs/video/renderer/vulkan/vkgen/vkstruct.r | 283 +++++++++++++------- 1 file changed, 186 insertions(+), 97 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index baec9cb8c..5b00d1026 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -7,6 +7,7 @@ #include #include "vkfielddef.h" +#include "vkfieldtype.h" #include "vkgen.h" #include "vkstruct.h" @@ -106,33 +107,124 @@ } } +static void +write_function_head (Struct *self) +{ + fprintf (output_file, "static int %s (const plfield_t *field," + " const plitem_t *item, void *data, plitem_t *messages," + " void *context)\n", + [self parseFunc]); + fprintf (output_file, "{\n"); +} + +static void +write_function_tail (Struct *self) +{ + fprintf (output_file, "}\n"); +} + +static void +write_type (Struct *self, PLItem *field_dict, string type) +{ + string key = nil; + switch (type) { + case "QFDictionary": key = ".dictionary"; break; + case "QFArray": key = ".array"; break; + case "QFBinary": key = ".binary"; break; + case "QFString": key = ".string"; break; + } + PLItem *type_obj = [field_dict getObjectForKey:key]; + int count = [type_obj numKeys]; + if (!count) { + //FIXME errors + return; + } + fprintf (output_file, "\tif (type == %s) {\n", type); + for (int i = 0; i < count; i++) { + string field = [type_obj keyAtIndex:i]; + PLItem *item = [type_obj getObjectForKey:field]; + string str = [item string]; + + switch (str) { + case "$item.string": + str = "vkstrdup (context, PL_String (item))"; + break; + case "$item.line": + str = "PL_Line (item)"; + break; + case "$name": + str = "vkstrdup (context, field->name)"; + break; + case "$index": + str = "field->offset"; + break; + } + fprintf (output_file, "\t\t((%s *) data)->%s = %s;\n", [self outname], + field, str); + } + fprintf (output_file, "\t\treturn 1;\n"); + fprintf (output_file, "\t}\n"); +} + +static void +write_cexpr (Struct *self, Array *field_defs) +{ + fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", + [self outname]); + if (field_defs) { + PLItem *field_def; + qfot_var_t *field; + + for (int i = [field_defs count]; i-- > 0; ) { + FieldDef *field_def = [field_defs objectAtIndex:i]; + [field_def writeSymbol]; + } + } else { + for (int i = 0; i < self.type.strct.num_fields; i++) { + qfot_var_t *field = &self.type.strct.fields[i]; + if (field.name == "sType" || field.name == "pNext") { + continue; + } + Type *field_type = [Type findType: field.type]; + fprintf (output_file, + "\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n", + field.name, [field_type cexprType], [self outname], + field.name); + } + } + fprintf (output_file, "\t{ }\n"); + fprintf (output_file, "};\n"); + + fprintf (output_file, "static exprtab_t %s_symtab = {\n", [self outname]); + fprintf (output_file, "\t%s_symbols,\n", [self outname]); + fprintf (output_file, "};\n"); + + fprintf (output_file, "exprtype_t %s_type = {\n", [self outname]); + fprintf (output_file, "\t.name = \"%s\",\n", [self outname]); + fprintf (output_file, "\t.size = sizeof (%s),\n", [self outname]); + fprintf (output_file, "\t.binops = cexpr_struct_binops,\n"); + fprintf (output_file, "\t.unops = 0,\n"); + fprintf (output_file, "\t.data = &%s_symtab,\n", [self outname]); + fprintf (output_file, "};\n"); + fprintf (output_file, "\n"); + fprintf (header_file, "extern exprtype_t %s_type;\n", [self outname]); +} + -(void) writeTable { - PLItem *field_dict = [parse getObjectForKey:[self name]]; - PLItem *new_name = [field_dict getObjectForKey:".name"]; - PLItem *only = [field_dict getObjectForKey:".only"]; - Array *field_defs = [Array array]; - int have_sType = 0; - int have_pNext = 0; - int readonly = [field_dict string] == "readonly"; - if ([parse string] == "skip") { return; } + + PLItem *field_dict = [parse getObjectForKey:[self name]]; + + PLItem *new_name = [field_dict getObjectForKey:".name"]; if (new_name) { outname = str_hold ([new_name string]); } - for (int i = 0; i < type.strct.num_fields; i++) { - qfot_var_t *field = &type.strct.fields[i]; - if (field.name == "sType") { - have_sType = 1; - } - if (field.name == "pNext") { - have_pNext = 1; - write_symtab = 1; - } - } + Array *field_defs = [Array array]; + PLItem *only = [field_dict getObjectForKey:".only"]; if (only) { string field_name = [only string]; qfot_var_t *field = nil; @@ -182,6 +274,44 @@ [field_defs addObject: field_def]; } } + + if ([field_dict getObjectForKey:".type"]) { + PLItem *type = [field_dict getObjectForKey:".type"]; + string str = [type string]; + + write_function_head (self); + fprintf (output_file, "\tpltype_t type = PL_Type (item);\n"); + if (str) { + write_type (self, field_dict, str); + } else { + for (int i = [type count]; i-- > 0; ) { + str = [[type getObjectAtIndex:i] string]; + write_type (self, field_dict, str); + } + } + fprintf (output_file, + "\tPL_TypeMismatch (messages, item, field->name, %s, type);\n", + parseItemType (type)); + fprintf (output_file, "\treturn 0;\n"); + write_function_tail (self); + write_cexpr (self, field_defs); + return; + } + + int have_sType = 0; + int have_pNext = 0; + int readonly = [field_dict string] == "readonly"; + + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *field = &type.strct.fields[i]; + if (field.name == "sType") { + have_sType = 1; + } + if (field.name == "pNext") { + have_pNext = 1; + write_symtab = 1; + } + } for (int i = [field_defs count]; i-- > 0; ) { FieldDef *field_def = [field_defs objectAtIndex:i]; [field_def writeParseData]; @@ -206,90 +336,49 @@ fprintf (output_file, "\t{ }\n"); fprintf (output_file, "};\n"); - fprintf (output_file, "static int %s (const plfield_t *field," - " const plitem_t *item, void *data, plitem_t *messages," - " void *context)\n", - [self parseFunc]); - fprintf (output_file, "{\n"); - if (have_sType) { - fprintf (output_file, "\t((%s *) data)->sType", [self outname]); - fprintf (output_file, " = %s;\n", [self sTypeName]); - } - if (label_field) { - fprintf (output_file, "\t((%s *) data)->%s", [self outname], - label_field); - fprintf (output_file, " = vkstrdup (context, field->name);\n"); - } - if (only) { - fprintf (output_file, "\tplfield_t *f = &%s_fields[0];\n", - [self outname]); - fprintf (output_file, - "\tif (!PL_CheckType (PL_Type (item), f->type)) {\n" - "\t\tPL_TypeMismatch (messages, item, " - "f->name, f->type, PL_Type (item));\n" - "\t\treturn 0;\n" - "\t}\n" - "\tvoid *flddata = (byte *)data + f->offset;\n" - "\treturn f->parser (f, item, flddata, messages, " - "context);\n"); - } else { - fprintf (output_file, - "\tif (PL_Type (item) == QFString\n" - "\t\t&& !(item = parse_reference (item, \"%s\", " - "messages, context))) {\n" - "\t\treturn 0;\n" - "\t}\n" - "\treturn PL_ParseStruct (%s_fields, item, data, " - "messages, context);\n", - [self outname], [self outname]); - } - fprintf (output_file, "}\n"); - if (have_pNext) { - fprintf (output_file, "static parserref_t %s_parser = ", - [self outname]); - fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", - [self outname], [self parseFunc], [self outname]); - } - } - - fprintf (output_file, "static exprsym_t %s_symbols[] = {\n", [self outname]); - if (field_defs) { - PLItem *field_def; - qfot_var_t *field; - - for (int i = [field_defs count]; i-- > 0; ) { - FieldDef *field_def = [field_defs objectAtIndex:i]; - [field_def writeSymbol]; + write_function_head (self); + if (have_sType) { + fprintf (output_file, "\t((%s *) data)->sType", [self outname]); + fprintf (output_file, " = %s;\n", [self sTypeName]); } - } else { - for (int i = 0; i < type.strct.num_fields; i++) { - qfot_var_t *field = &type.strct.fields[i]; - if (field.name == "sType" || field.name == "pNext") { - continue; - } - Type *field_type = [Type findType: field.type]; + if (label_field) { + fprintf (output_file, "\t((%s *) data)->%s", [self outname], + label_field); + fprintf (output_file, " = vkstrdup (context, field->name);\n"); + } + if (only) { + fprintf (output_file, "\tplfield_t *f = &%s_fields[0];\n", + [self outname]); fprintf (output_file, - "\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n", - field.name, [field_type cexprType], [self outname], - field.name); + "\tif (!PL_CheckType (PL_Type (item), f->type)) {\n" + "\t\tPL_TypeMismatch (messages, item, " + "f->name, f->type, PL_Type (item));\n" + "\t\treturn 0;\n" + "\t}\n" + "\tvoid *flddata = (byte *)data + f->offset;\n" + "\treturn f->parser (f, item, flddata, messages, " + "context);\n"); + } else { + fprintf (output_file, + "\tif (PL_Type (item) == QFString\n" + "\t\t&& !(item = parse_reference (item, \"%s\", " + "messages, context))) {\n" + "\t\treturn 0;\n" + "\t}\n" + "\treturn PL_ParseStruct (%s_fields, item, data, " + "messages, context);\n", + [self outname], [self outname]); + } + write_function_tail (self); + if (have_pNext) { + fprintf (output_file, "static parserref_t %s_parser = ", + [self outname]); + fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", + [self outname], [self parseFunc], [self outname]); } } - fprintf (output_file, "\t{ }\n"); - fprintf (output_file, "};\n"); - fprintf (output_file, "static exprtab_t %s_symtab = {\n", [self outname]); - fprintf (output_file, "\t%s_symbols,\n", [self outname]); - fprintf (output_file, "};\n"); - - fprintf (output_file, "exprtype_t %s_type = {\n", [self outname]); - fprintf (output_file, "\t.name = \"%s\",\n", [self outname]); - fprintf (output_file, "\t.size = sizeof (%s),\n", [self outname]); - fprintf (output_file, "\t.binops = cexpr_struct_binops,\n"); - fprintf (output_file, "\t.unops = 0,\n"); - fprintf (output_file, "\t.data = &%s_symtab,\n", [self outname]); - fprintf (output_file, "};\n"); - fprintf (output_file, "\n"); - fprintf (header_file, "extern exprtype_t %s_type;\n", [self outname]); + write_cexpr (self, field_defs); } -(void) writeSymtabInit From 728807bd7a2bb175b4e343e18084357b468ab3d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Feb 2023 02:40:52 +0900 Subject: [PATCH 3418/3664] [vulkan] Use references for views and pipelines I'm pretty sure I don't want to require views to be created and pipelines to be parsed just to parse the render pass info. --- include/QF/Vulkan/render.h | 17 ++++++++++++++-- libs/video/renderer/vulkan/vkparse.plist | 25 ++++++++++++++++++++---- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index bb45ed4ce..f71c868b9 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -8,6 +8,11 @@ #include "QF/simd/types.h" +typedef struct qfv_reference_s { + const char *name; + int line; +} qfv_reference_t; + typedef struct qfv_imageinfo_s { const char *name; VkImageCreateFlags flags; @@ -84,7 +89,7 @@ typedef struct qfv_attachmentsetinfo_s { typedef struct qfv_pipelineinfo_s { vec4f_t color; const char *name; - VkGraphicsPipelineCreateInfo *pipeline; + qfv_reference_t pipeline; uint32_t num_tasks; qfv_taskinfo_t *tasks; } qfv_pipelineinfo_t; @@ -100,11 +105,19 @@ typedef struct qfv_subpassinfo_s { qfv_pipelineinfo_t *pipelines; } qfv_subpassinfo_t; +typedef struct qfv_framebufferinfo_s { + qfv_reference_t *attachments; + uint32_t num_attachments; + uint32_t width; + uint32_t height; + uint32_t layers; +} qfv_framebufferinfo_t; + typedef struct qfv_renderpassinfo_s { const char *name; uint32_t num_attachments; qfv_attachmentinfo_t *attachments; - VkFramebufferCreateInfo framebuffer; + qfv_framebufferinfo_t framebuffer; uint32_t num_subpasses; qfv_subpassinfo_t *subpasses; } qfv_renderpassinfo_t; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 41fa107f4..d554e8f7c 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -43,6 +43,7 @@ qfv_taskinfo_t, qfv_pipelineinfo_t, qfv_subpassinfo_t, + qfv_framebufferinfo_t, qfv_renderpassinfo_t, qfv_renderinfo_t, ); @@ -476,10 +477,7 @@ type = string; string = name; }; - pipeline = { - type = (single, VkGraphicsPipelineCreateInfo); - value = pipeline; - }; + pipeline = auto; tasks = { type = (array, qfv_taskinfo_t); size = num_tasks; @@ -508,6 +506,25 @@ values = pipelines; }; }; + qfv_framebufferinfo_s = { + .name = qfv_framebufferinfo_t; + attachments = { + type = (array, qfv_reference_t); + size = num_attachments; + values = attachments; + }; + width = auto; + height = auto; + layers = auto; + }; + qfv_reference_s = { + .name = qfv_reference_t; + .type = QFString; + .string = { + name = $item.string; + line = $item.line; + }; + }; qfv_renderpassinfo_s = { .name = qfv_renderpassinfo_t; attachments = { From 3fea31875c98af5d1e1d991547b1f6f15a0c1953 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Feb 2023 02:43:38 +0900 Subject: [PATCH 3419/3664] [vulkan] Get render pass inheritance working Needed to add the render passes plitem to the cexr symbol table, too. All that remains is to figure out how to deal with multiview (or really @next) and get task parsing working. --- libs/video/renderer/vulkan/rp_main_def.plist | 2 +- libs/video/renderer/vulkan/vkparse.c | 23 ++++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 82c07e2b2..2419ed113 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -374,7 +374,7 @@ renderpasses = { }; }; deferred_cube = { - @inherit = deferred; + @inherit = $renderpasses.deferred; @next = (VkRenderPassMultiviewCreateInfo, { viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); viewOffsets = ( 0, 0, 0, 0, 0); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index fb11ad67d..6c7fa711a 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -2140,9 +2140,8 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) plitem_t *messages = PL_NewArray (); exprctx_t exprctx = { .symtab = &root_symtab }; parsectx_t parsectx = { &exprctx, ctx, properties }; - plitem_t *pl_items[num_keys + 2]; - exprsym_t var_syms[num_keys + 6 + 1]; - var_syms[num_keys + 6] = (exprsym_t) {}; + plitem_t *pl_items[num_keys + 3]; + exprsym_t var_syms[num_keys + 7 + 1]; exprtab_t vars_tab = { var_syms, 0 }; for (int i = 0; i < num_keys; i++) { @@ -2155,6 +2154,7 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) } pl_items[num_keys + 0] = PL_ObjectForKey (item, "images"); pl_items[num_keys + 1] = PL_ObjectForKey (item, "views"); + pl_items[num_keys + 2] = PL_ObjectForKey (item, "renderpasses"); var_syms[num_keys + 0] = (exprsym_t) { .name = "images", @@ -2167,25 +2167,31 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) .value = pl_items + num_keys + 1, }, var_syms[num_keys + 2] = (exprsym_t) { + .name = "renderpasses", + .type = &cexpr_plitem, + .value = pl_items + num_keys + 2, + }, + var_syms[num_keys + 3] = (exprsym_t) { .name = "output", .type = &qfv_output_t_type, .value = &sctx->output, }; - var_syms[num_keys + 3] = (exprsym_t) { + var_syms[num_keys + 4] = (exprsym_t) { .name = "frames", .type = &vulkan_frameset_t_type, .value = &ctx->frames, }; - var_syms[num_keys + 4] = (exprsym_t) { + var_syms[num_keys + 5] = (exprsym_t) { .name = "msaaSamples", .type = &VkSampleCountFlagBits_type, .value = &ctx->msaaSamples, }; - var_syms[num_keys + 5] = (exprsym_t) { + var_syms[num_keys + 6] = (exprsym_t) { .name = "physDevLimits", .type = &VkPhysicalDeviceLimits_type, .value = &ctx->device->physDev->properties->limits, }; + var_syms[num_keys + 7] = (exprsym_t) {}; exprctx.external_variables = &vars_tab; exprctx.messages = messages; @@ -2202,6 +2208,9 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) } Hash_DelTable (vars_tab.tab); PL_Free (messages); + if (!ri) { + delete_memsuper (memsuper); + } - return 0; + return ri; } From 2c3b89f722bb49eaecdfa885867bd2698560653a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Feb 2023 01:43:17 +0900 Subject: [PATCH 3420/3664] [vulkan] Implement task function parsing This just sets up the memory block and cexpr descriptors for the parameters, parameter parsing is separate (and next). The parameters are aligned to their size. --- include/QF/Vulkan/render.h | 7 +- libs/video/renderer/vulkan/render.c | 20 +++++- libs/video/renderer/vulkan/rp_main_def.plist | 6 +- libs/video/renderer/vulkan/vkparse.c | 74 +++++++++++++++++--- libs/video/renderer/vulkan/vkparse.h | 4 +- libs/video/renderer/vulkan/vkparse.plist | 4 +- 6 files changed, 98 insertions(+), 17 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index f71c868b9..9c5f35ef6 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -67,7 +67,8 @@ typedef struct qfv_attachmentinfo_s { typedef struct qfv_taskinfo_s { struct exprfunc_s *func; - void *params; + const struct exprval_s **params; + void *param_data; } qfv_taskinfo_t; typedef struct qfv_attachmentrefinfo_s { @@ -132,6 +133,10 @@ typedef struct qfv_renderinfo_s { qfv_renderpassinfo_t *renderpasses; } qfv_renderinfo_t; +typedef struct qfv_renderctx_s { + struct exprtab_s *task_functions; +} qfv_renderctx_t; + typedef struct qfv_label_s { vec4f_t color; const char *name; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 3bd36255b..eb5311c86 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -38,6 +38,7 @@ # include #endif +#include "QF/hash.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" @@ -124,10 +125,27 @@ QFV_RunRenderPass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) QFV_CmdEndLabel (device, cmd); } +static exprsym_t qfv_renderpass_task_symbols[] = { + + {} +}; + void QFV_LoadRenderPass (vulkan_ctx_t *ctx) { + + exprtab_t task_tab = { qfv_renderpass_task_symbols, 0 }; + exprctx_t ectx = { + .symtab = &task_tab, + .hashctx = &ctx->script_context->hashctx, + }; + cexpr_init_symtab (&task_tab, &ectx); + + qfv_renderctx_t rctx = { .task_functions = &task_tab }; + plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); - __auto_type ri = QFV_ParseRenderInfo (ctx, item); + __auto_type ri = QFV_ParseRenderInfo (ctx, item, &rctx); printf ("%p\n", ri); + + Hash_DelTable (task_tab.tab); } diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 2419ed113..7890652bc 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -366,19 +366,19 @@ renderpasses = { color = $color.compose; pipeline = compose; tasks = ( - { func = "lights_draw"; }, + { func = "compose_draw"; }, ); }; }; }; }; }; - deferred_cube = { +/* deferred_cube = { @inherit = $renderpasses.deferred; @next = (VkRenderPassMultiviewCreateInfo, { viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); viewOffsets = ( 0, 0, 0, 0, 0); }); - }; + };*/ }; }; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 6c7fa711a..e0ce60b6f 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -520,7 +520,7 @@ parse_inherit (const plfield_t *field, const plitem_t *item, ectx.result = &result; ectx.item = item; const char *inheritstr = PL_String (item); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_inherit: %s\n", inheritstr); + //Sys_MaskPrintf (SYS_vulkan_parse, "parse_inherit: %s\n", inheritstr); int ret = !cexpr_eval_string (inheritstr, &ectx); if (ret) { ret = PL_ParseStruct (field->data, inheritItem, data, messages, @@ -566,10 +566,10 @@ parse_RGBA (const plitem_t *item, void **data, ectx.result = &result; ectx.item = item; const char *valstr = PL_String (item); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_RGBA: %s\n", valstr); + //Sys_MaskPrintf (SYS_vulkan_parse, "parse_RGBA: %s\n", valstr); ret = !cexpr_eval_string (valstr, &ectx); - Sys_MaskPrintf (SYS_vulkan_parse, " "VEC4F_FMT"\n", - VEC4_EXP (*(vec4f_t *)data[0])); + //Sys_MaskPrintf (SYS_vulkan_parse, " "VEC4F_FMT"\n", + // VEC4_EXP (*(vec4f_t *)data[0])); return ret; } @@ -1085,8 +1085,58 @@ static int parse_task_function (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *pctx) { - PL_Message (messages, item, "parse_task_function: not implemented"); - return 0; + qfv_renderctx_t *rctx = pctx->data; + const char *fname = PL_String (item); + exprsym_t *fsym = Hash_Find (rctx->task_functions->tab, fname); + + if (!fsym) { + PL_Message (messages, item, "undefined task function %s", fname); + return 0; + } + if (fsym->type != &cexpr_function) { + PL_Message (messages, item, "not a function type %s", fname); + return 0; + } + exprfunc_t *func; + for (func = fsym->value; func->func; func++) { + if (!func->result) { + break; + } + } + if (!func->func) { + PL_Message (messages, item, "%s does not have a void implementation", + fname); + return 0; + } + size_t size = func->num_params * sizeof (exprval_t); + size += func->num_params * sizeof (exprval_t *); + size_t base = size; + for (int i = 0; i < func->num_params; i++) { + exprtype_t *type = func->param_types[i]; + size = ((size + type->size - 1) & ~(type->size - 1)); + if (i == 0) { + base = size; + } + } + exprval_t **param_ptrs = vkparse_alloc (pctx, size); + exprval_t *params = (exprval_t *) ¶m_ptrs[func->num_params]; + byte *param_data = (byte *) param_ptrs + base; + memset (params, 0, size); + size_t offs = 0; + for (int i = 0; i < func->num_params; i++) { + exprtype_t *type = func->param_types[i]; + param_ptrs[i] = ¶ms[i]; + params[i] = (exprval_t) { + .type = type, + .value = param_data + offs, + }; + offs = ((offs + type->size - 1) & ~(type->size - 1)); + offs += type->size; + } + *(exprfunc_t **) data[0] = func; + *(exprval_t ***) data[1] = param_ptrs; + *(void **) data[2] = param_data; + return 1; } static int @@ -2127,7 +2177,7 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) } qfv_renderinfo_t * -QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) +QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) { memsuper_t *memsuper = new_memsuper (); qfv_renderinfo_t *ri = cmemalloc (memsuper, sizeof (qfv_renderinfo_t)); @@ -2139,7 +2189,12 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) scriptctx_t *sctx = ctx->script_context; plitem_t *messages = PL_NewArray (); exprctx_t exprctx = { .symtab = &root_symtab }; - parsectx_t parsectx = { &exprctx, ctx, properties }; + parsectx_t parsectx = { + .ectx = &exprctx, + .vctx = ctx, + .properties = properties, + .data = rctx + }; plitem_t *pl_items[num_keys + 3]; exprsym_t var_syms[num_keys + 7 + 1]; exprtab_t vars_tab = { var_syms, 0 }; @@ -2208,8 +2263,9 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item) } Hash_DelTable (vars_tab.tab); PL_Free (messages); - if (!ri) { + if (!ret) { delete_memsuper (memsuper); + ri = 0; } return ri; diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 8b429fdaf..d92429332 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -77,6 +77,8 @@ int QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, plitem_t *properties); int QFV_ParseOutput (vulkan_ctx_t *ctx, qfv_output_t *output, plitem_t *plist, plitem_t *properties); +struct qfv_renderctx_s; struct qfv_renderinfo_s *QFV_ParseRenderInfo (vulkan_ctx_t *ctx, - plitem_t *item); + plitem_t *item, + struct qfv_renderctx_s *rctx); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index d554e8f7c..49fc3ca6a 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -427,11 +427,11 @@ .name = qfv_taskinfo_t; func = { type = (custom, QFString, parse_task_function); - fields = (func); + fields = (func, params, param_data); }; params = { type = (custom, QFArray, parse_task_params); - fields = (params, func); + fields = (func, params, param_data); }; }; qfv_attachmentrefinfo_s = { From 91d9d0b251f122e1e8a0c47d0d8a579f4ec66d1c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Feb 2023 11:30:14 +0900 Subject: [PATCH 3421/3664] [vulkan] Implement task parameter parsing This should fill in the task function's parameters nicely. The parameter count check is known to work. --- libs/video/renderer/vulkan/vkparse.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index e0ce60b6f..691325ee5 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1143,8 +1143,29 @@ static int parse_task_params (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *pctx) { - PL_Message (messages, item, "parse_task_params: not implemented"); - return 0; + exprfunc_t *func = *(exprfunc_t **) data[0]; + exprval_t **params = *(exprval_t ***) data[1]; + if (PL_A_NumObjects (item) != func->num_params) { + PL_Message (messages, item, "incorrect number of parameters"); + return 0; + } + for (int i = 0; i < func->num_params; i++) { + const char *paramstr = PL_String (PL_ObjectAtIndex (item, i)); + exprval_t *param = params[func->num_params - i - 1]; + exprctx_t ectx = *pctx->ectx; + if (param->type->data) { + ectx.parent = pctx->ectx; + ectx.symtab = ((exprenum_t *) param->type->data)->symtab; + } + // cexpr params are in reverse order + ectx.result = param; + + if (cexpr_eval_string (paramstr, &ectx)) { + PL_Message (messages, item, "error parsing param %d", i); + return 0; + } + } + return 1; } #include "libs/video/renderer/vulkan/vkparse.cinc" From f78aab1cb51c6d0c76592757469bfb5ee22dc68a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 13 Feb 2023 17:45:36 +0900 Subject: [PATCH 3422/3664] [vulkan] Create a render context This gets an empty (no tasks or pipelines connected) render context initialized and available for other subsystems to register their task functions. Nothing is using it yet, but the test parse of rp_main_def fails gracefully (needs those tasks). --- include/QF/Vulkan/render.h | 9 ++++--- include/vid_vulkan.h | 1 + libs/video/renderer/vid_render_vulkan.c | 2 ++ libs/video/renderer/vulkan/render.c | 33 +++++++++++-------------- libs/video/renderer/vulkan/vkparse.c | 6 ++++- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 9c5f35ef6..418b019fa 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -6,6 +6,7 @@ #endif #include +#include "QF/cexpr.h" #include "QF/simd/types.h" typedef struct qfv_reference_s { @@ -66,8 +67,8 @@ typedef struct qfv_attachmentinfo_s { } qfv_attachmentinfo_t; typedef struct qfv_taskinfo_s { - struct exprfunc_s *func; - const struct exprval_s **params; + exprfunc_t *func; + const exprval_t **params; void *param_data; } qfv_taskinfo_t; @@ -134,7 +135,8 @@ typedef struct qfv_renderinfo_s { } qfv_renderinfo_t; typedef struct qfv_renderctx_s { - struct exprtab_s *task_functions; + struct hashctx_s *hashctx; + exprtab_t task_functions; } qfv_renderctx_t; typedef struct qfv_label_s { @@ -191,5 +193,6 @@ typedef struct qfv_renderpass_s_ { void QFV_RunRenderPass (qfv_renderpass_t_ *rp, struct vulkan_ctx_s *ctx); void QFV_LoadRenderPass (struct vulkan_ctx_s *ctx); +void QFV_Render_Init (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_render_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 2a9936a99..f5d406de4 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -46,6 +46,7 @@ typedef struct vulkan_ctx_s { uint32_t swapImageIndex; struct scriptctx_s *script_context; + struct qfv_renderctx_s *render_context; struct texturectx_s *texture_context; struct matrixctx_s *matrix_context; struct translucentctx_s *translucent_context; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 701b39031..696e550a3 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -91,6 +91,8 @@ vulkan_ParticleSystem (void) static void vulkan_R_Init (void) { + QFV_Render_Init (vulkan_ctx); + Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx); Vulkan_Texture_Init (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index eb5311c86..9299ef4d3 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -125,27 +125,24 @@ QFV_RunRenderPass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) QFV_CmdEndLabel (device, cmd); } -static exprsym_t qfv_renderpass_task_symbols[] = { - - {} -}; - void QFV_LoadRenderPass (vulkan_ctx_t *ctx) { - - exprtab_t task_tab = { qfv_renderpass_task_symbols, 0 }; - exprctx_t ectx = { - .symtab = &task_tab, - .hashctx = &ctx->script_context->hashctx, - }; - cexpr_init_symtab (&task_tab, &ectx); - - qfv_renderctx_t rctx = { .task_functions = &task_tab }; + __auto_type rctx = ctx->render_context; plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); - __auto_type ri = QFV_ParseRenderInfo (ctx, item, &rctx); - printf ("%p\n", ri); - - Hash_DelTable (task_tab.tab); + QFV_ParseRenderInfo (ctx, item, rctx); +} + +void +QFV_Render_Init (vulkan_ctx_t *ctx) +{ + qfv_renderctx_t *rctx = calloc (1, sizeof (*rctx)); + ctx->render_context = rctx; + + exprctx_t ectx = { .hashctx = &rctx->hashctx }; + exprsym_t syms[] = { {} }; + rctx->task_functions.symbols = syms; + cexpr_init_symtab (&rctx->task_functions, &ectx); + rctx->task_functions.symbols = 0; } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 691325ee5..b0b256446 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1087,7 +1087,7 @@ parse_task_function (const plitem_t *item, void **data, { qfv_renderctx_t *rctx = pctx->data; const char *fname = PL_String (item); - exprsym_t *fsym = Hash_Find (rctx->task_functions->tab, fname); + exprsym_t *fsym = Hash_Find (rctx->task_functions.tab, fname); if (!fsym) { PL_Message (messages, item, "undefined task function %s", fname); @@ -1145,6 +1145,10 @@ parse_task_params (const plitem_t *item, void **data, { exprfunc_t *func = *(exprfunc_t **) data[0]; exprval_t **params = *(exprval_t ***) data[1]; + if (!func) { + PL_Message (messages, item, "task function not set"); + return 0; + } if (PL_A_NumObjects (item) != func->num_params) { PL_Message (messages, item, "incorrect number of parameters"); return 0; From 422aaf4bc6c2a72e8d61b3ecc857799c47a101f8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 14 Feb 2023 00:55:22 +0900 Subject: [PATCH 3423/3664] [vulkan] Register task functions for the pipelines They're currently just stubs, but this gets the render info loading working without any errors. The next step is to connect up pipelines and create the image resources, then implementing the task functions will have meaning. --- include/QF/Vulkan/render.h | 1 + libs/video/renderer/vid_render_vulkan.c | 3 +- libs/video/renderer/vulkan/render.c | 18 ++++++ libs/video/renderer/vulkan/vulkan_alias.c | 16 +++++ libs/video/renderer/vulkan/vulkan_bsp.c | 60 +++++++++++++++++++ libs/video/renderer/vulkan/vulkan_compose.c | 16 +++++ libs/video/renderer/vulkan/vulkan_iqm.c | 16 +++++ libs/video/renderer/vulkan/vulkan_lighting.c | 16 +++++ libs/video/renderer/vulkan/vulkan_particles.c | 16 +++++ libs/video/renderer/vulkan/vulkan_sprite.c | 16 +++++ 10 files changed, 177 insertions(+), 1 deletion(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 418b019fa..e115e0b1b 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -194,5 +194,6 @@ typedef struct qfv_renderpass_s_ { void QFV_RunRenderPass (qfv_renderpass_t_ *rp, struct vulkan_ctx_s *ctx); void QFV_LoadRenderPass (struct vulkan_ctx_s *ctx); void QFV_Render_Init (struct vulkan_ctx_s *ctx); +void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys); #endif//__QF_Vulkan_render_h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 696e550a3..7e80bc68d 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -101,7 +101,6 @@ vulkan_R_Init (void) Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); - QFV_LoadRenderPass (vulkan_ctx); Vulkan_CreateRenderPasses (vulkan_ctx); Vulkan_Output_Init (vulkan_ctx); @@ -117,6 +116,8 @@ vulkan_R_Init (void) Vulkan_Translucent_Init (vulkan_ctx); Vulkan_Compose_Init (vulkan_ctx); + QFV_LoadRenderPass (vulkan_ctx); + Skin_Init (); SCR_Init (); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 9299ef4d3..d183016e3 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -146,3 +146,21 @@ QFV_Render_Init (vulkan_ctx_t *ctx) cexpr_init_symtab (&rctx->task_functions, &ectx); rctx->task_functions.symbols = 0; } + +void +QFV_Render_AddTasks (vulkan_ctx_t *ctx, exprsym_t *task_syms) +{ + __auto_type rctx = ctx->render_context; + exprctx_t ectx = { .hashctx = &rctx->hashctx }; + for (exprsym_t *sym = task_syms; sym->name; sym++) { + Hash_Add (rctx->task_functions.tab, sym); + for (exprfunc_t *f = sym->value; f->func; f++) { + for (int i = 0; i < f->num_params; i++) { + exprenum_t *e = f->param_types[i]->data; + if (e && !e->symtab->tab) { + cexpr_init_symtab (e->symtab, &ectx); + } + } + } + } +} diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 9cf245fff..77634cfe8 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -48,6 +48,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -295,12 +296,27 @@ Vulkan_AliasRemoveSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) skin->descriptor = 0; } +static void +alias_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static exprfunc_t alias_draw_func[] = { + { .func = alias_draw }, + {} +}; +static exprsym_t alias_task_syms[] = { + { "alias_draw", &cexpr_function, alias_draw_func }, + {} +}; + void Vulkan_Alias_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfvPushDebug (ctx, "alias init"); + QFV_Render_AddTasks (ctx, alias_task_syms); aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); ctx->alias_context = actx; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 7a3ab9f99..76a782846 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -69,6 +69,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" @@ -1361,6 +1362,64 @@ create_notexture (vulkan_ctx_t *ctx) bctx->notexture.tex = Vulkan_LoadTexArray (ctx, tex, 2, 1, "notexture"); } +static void +bsp_draw_queue (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static exprenum_t bsp_stage_enum; +static exprtype_t bsp_stage_type = { + .name = "bsp_stage", + .size = sizeof (int), + .get_string = cexpr_enum_get_string, + .data = &bsp_stage_enum, +}; +static int bsp_stage_values[] = { 0, }; +static exprsym_t bsp_stage_symbols[] = { + {"main", &bsp_stage_type, bsp_stage_values + 0}, + {} +}; +static exprtab_t bsp_stage_symtab = { .symbols = bsp_stage_symbols }; +static exprenum_t bsp_stage_enum = { + &bsp_stage_type, + &bsp_stage_symtab, +}; + +static exprenum_t bsp_queue_enum; +static exprtype_t bsp_queue_type = { + .name = "bsp_queue", + .size = sizeof (int), + .get_string = cexpr_enum_get_string, + .data = &bsp_queue_enum, +}; +static int bsp_queue_values[] = { 0, 1, 2, 3, }; +static exprsym_t bsp_queue_symbols[] = { + {"solid", &bsp_queue_type, bsp_queue_values + 0}, + {"sky", &bsp_queue_type, bsp_queue_values + 1}, + {"translucent", &bsp_queue_type, bsp_queue_values + 2}, + {"turbulent", &bsp_queue_type, bsp_queue_values + 3}, + {} +}; +static exprtab_t bsp_queue_symtab = { .symbols = bsp_queue_symbols }; +static exprenum_t bsp_queue_enum = { + &bsp_queue_type, + &bsp_queue_symtab, +}; + +static exprtype_t *bsp_draw_queue_params[] = { + &bsp_queue_type, + &bsp_stage_type, +}; + +static exprfunc_t bsp_draw_queue_func[] = { + { 0, 2, bsp_draw_queue_params, bsp_draw_queue }, + {} +}; +static exprsym_t bsp_task_syms[] = { + { "bsp_draw_queue", &cexpr_function, bsp_draw_queue_func }, + {} +}; + void Vulkan_Bsp_Init (vulkan_ctx_t *ctx) { @@ -1368,6 +1427,7 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; qfvPushDebug (ctx, "bsp init"); + QFV_Render_AddTasks (ctx, bsp_task_syms); bspctx_t *bctx = calloc (1, sizeof (bspctx_t)); ctx->bsp_context = bctx; diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 172d69a0f..3d341ef35 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -52,6 +52,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -120,12 +121,27 @@ static VkWriteDescriptorSet base_image_write = { 0, 0, 0 }; +static void +compose_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static exprfunc_t compose_draw_func[] = { + { .func = compose_draw }, + {} +}; +static exprsym_t compose_task_syms[] = { + { "compose_draw", &cexpr_function, compose_draw_func }, + {} +}; + void Vulkan_Compose_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfvPushDebug (ctx, "compose init"); + QFV_Render_AddTasks (ctx, compose_task_syms); composectx_t *cctx = calloc (1, sizeof (composectx_t)); ctx->compose_context = cctx; diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 467b4546d..42f1486ea 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -48,6 +48,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/resource.h" +#include "QF/Vulkan/render.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -360,12 +361,27 @@ Vulkan_IQMRemoveSkin (vulkan_ctx_t *ctx, qfv_iqm_skin_t *skin) skin->descriptor = 0; } +static void +iqm_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static exprfunc_t iqm_draw_func[] = { + { .func = iqm_draw }, + {} +}; +static exprsym_t iqm_task_syms[] = { + { "iqm_draw", &cexpr_function, iqm_draw_func }, + {} +}; + void Vulkan_IQM_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfvPushDebug (ctx, "iqm init"); + QFV_Render_AddTasks (ctx, iqm_task_syms); iqmctx_t *ictx = calloc (1, sizeof (iqmctx_t)); ctx->iqm_context = ictx; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index a113b3cb2..4439d1d32 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -66,6 +66,7 @@ #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" #include "QF/Vulkan/staging.h" @@ -317,6 +318,20 @@ static VkWriteDescriptorSet base_image_write = { 0, 0, 0 }; +static void +lights_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static exprfunc_t lights_draw_func[] = { + { .func = lights_draw }, + {} +}; +static exprsym_t lighting_task_syms[] = { + { "lights_draw", &cexpr_function, lights_draw_func }, + {} +}; + void Vulkan_Lighting_Init (vulkan_ctx_t *ctx) { @@ -324,6 +339,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; qfvPushDebug (ctx, "lighting init"); + QFV_Render_AddTasks (ctx, lighting_task_syms); // lighting_context initialized in Vulkan_Lighting_CreateRenderPasses diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 5ccdcfe3d..02770a229 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -47,6 +47,7 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" #include "QF/Vulkan/staging.h" #include "QF/Vulkan/qf_matrices.h" @@ -272,6 +273,20 @@ create_buffers (vulkan_ctx_t *ctx) } } +static void +particles_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static exprfunc_t particles_draw_func[] = { + { .func = particles_draw }, + {} +}; +static exprsym_t particles_task_syms[] = { + { "particles_draw", &cexpr_function, particles_draw_func }, + {} +}; + void Vulkan_Particles_Init (vulkan_ctx_t *ctx) { @@ -279,6 +294,7 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; qfvPushDebug (ctx, "particles init"); + QFV_Render_AddTasks (ctx, particles_task_syms); particlectx_t *pctx = calloc (1, sizeof (particlectx_t)); ctx->particle_context = pctx; diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 95612b9b6..e33404806 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -63,6 +63,7 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -284,12 +285,27 @@ Vulkan_Sprint_FreeDescriptors (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) &sprite->descriptors); } +static void +sprite_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static exprfunc_t sprite_draw_func[] = { + { .func = sprite_draw }, + {} +}; +static exprsym_t sprite_task_syms[] = { + { "sprite_draw", &cexpr_function, sprite_draw_func }, + {} +}; + void Vulkan_Sprite_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfvPushDebug (ctx, "sprite init"); + QFV_Render_AddTasks (ctx, sprite_task_syms); spritectx_t *sctx = calloc (1, sizeof (spritectx_t)); ctx->sprite_context = sctx; From d89ad6b00fd84200bc6abfe2afdd21713519004f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Feb 2023 16:56:38 +0900 Subject: [PATCH 3424/3664] [plist] Fix a typo in the type mismatch message --- libs/util/plist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/plist.c b/libs/util/plist.c index 9f4ca3292..dbe20da60 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -1232,7 +1232,7 @@ PL_TypeMismatch (plitem_t *messages, const plitem_t *item, const char *name, const int num_types = sizeof (pl_types) / sizeof (pl_types[0]); if (field_type & QFMultiType) { PL_Message (messages, item, - "error: %s is the wrong type. Got %s, expected on of:", + "error: %s is the wrong type. Got %s, expected one of:", name, pl_types[item_type]); field_type &= ~QFMultiType; for (int type = 0; field_type && type < num_types; From 868db37461ae417cf66342c0af172147b8721360 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Feb 2023 17:00:52 +0900 Subject: [PATCH 3425/3664] [vkgen] Improve .type parse spec handling .dictionary can ask for standard parsing via a .parse key (value is ignored currently). Fields can use $auto to use standard parsing for that field. If either is used, the plist field descriptors are written. --- include/QF/Vulkan/render.h | 17 + libs/video/renderer/vulkan/pl_quake_def.plist | 10 - libs/video/renderer/vulkan/render.c | 2 +- libs/video/renderer/vulkan/rp_main_def.plist | 614 +++++++++++++++++- libs/video/renderer/vulkan/vkgen/vkstruct.r | 245 ++++--- libs/video/renderer/vulkan/vkparse.c | 15 +- libs/video/renderer/vulkan/vkparse.plist | 69 +- 7 files changed, 857 insertions(+), 115 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index e115e0b1b..0e2ed845c 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -75,6 +75,7 @@ typedef struct qfv_taskinfo_s { typedef struct qfv_attachmentrefinfo_s { const char *name; VkImageLayout layout; + VkPipelineColorBlendAttachmentState blend; } qfv_attachmentrefinfo_t; typedef struct qfv_attachmentsetinfo_s { @@ -94,6 +95,20 @@ typedef struct qfv_pipelineinfo_s { qfv_reference_t pipeline; uint32_t num_tasks; qfv_taskinfo_t *tasks; + + VkPipelineCreateFlags flags; + uint32_t num_graph_stages; + const VkPipelineShaderStageCreateInfo *graph_stages; + const VkPipelineVertexInputStateCreateInfo *vertexInput; + const VkPipelineInputAssemblyStateCreateInfo *inputAssembly; + const VkPipelineTessellationStateCreateInfo *tessellation; + const VkPipelineViewportStateCreateInfo *viewport; + const VkPipelineRasterizationStateCreateInfo *rasterization; + const VkPipelineMultisampleStateCreateInfo *multisample; + const VkPipelineDepthStencilStateCreateInfo *depthStencil; + const VkPipelineColorBlendStateCreateInfo *colorBlend; + const VkPipelineDynamicStateCreateInfo *dynamic; + qfv_reference_t *layout; } qfv_pipelineinfo_t; typedef struct qfv_subpassinfo_s { @@ -105,6 +120,7 @@ typedef struct qfv_subpassinfo_s { qfv_attachmentrefinfo_t *attachments; uint32_t num_pipelines; qfv_pipelineinfo_t *pipelines; + qfv_pipelineinfo_t *base_pipeline; } qfv_subpassinfo_t; typedef struct qfv_framebufferinfo_s { @@ -137,6 +153,7 @@ typedef struct qfv_renderinfo_s { typedef struct qfv_renderctx_s { struct hashctx_s *hashctx; exprtab_t task_functions; + qfv_renderinfo_t *renderinfo; } qfv_renderctx_t; typedef struct qfv_label_s { diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 729ebf01f..ec70028ac 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -1034,16 +1034,6 @@ }, ); vertexInput = $properties.vertexInput.iqm; - /*vertexInput = { - bindings = ( - "$properties.vertexInput.iqm.bindings[0]", - ); - attributes = ( - "$properties.vertexInput.iqm.attributes[0]", - "$properties.vertexInput.iqm.attributes[1]", - "$properties.vertexInput.iqm.attributes[2]", - ); - };*/ inputAssembly = $properties.inputAssembly.iqm; layout = iqm_layout; }; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index d183016e3..488db0eb8 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -131,7 +131,7 @@ QFV_LoadRenderPass (vulkan_ctx_t *ctx) __auto_type rctx = ctx->render_context; plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); - QFV_ParseRenderInfo (ctx, item, rctx); + rctx->renderinfo = QFV_ParseRenderInfo (ctx, item, rctx); } void diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 7890652bc..09e7652d3 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -69,6 +69,431 @@ properties = { finalLayout = color_attachment_optimal; clearValue = { color = "[0, 0, 0, 1]"; }; }; + + cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + counter_cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + depth_test_and_write = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + depth_test_only = { + depthTestEnable = true; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + depth_disable = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + blend_disable = { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + pipeline_base = { + viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0; }; + extent = { width = 640; height = 480; }; + }, + ); + }; + rasterization = $cw_cull_back; + multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; + }; + depthStencil = $depth_test_only; + colorBlend = { + logicOpEnable = false; + }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + }; + compose_base = { + @inherit = $pipeline_base; + vertexInput = { + bindings = (); + attributes = (); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + }; + + brush = { + shader = { + depth_vertex = { + stage = vertex; + name = main; + module = $builtin/bsp_depth.vert; + }; + gbuf_vertex = { + stage = vertex; + name = main; + module = $builtin/bsp_gbuf.vert; + }; + gbuf_geometry = { + stage = geometry; + name = main; + module = $builtin/bsp_gbuf.geom; + }; + gbuf_fragment = { + stage = fragment; + name = main; + module = $builtin/bsp_gbuf.frag; + }; + quake_vertex = { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }; + sky_specialization = { + mapEntries = ( + // doSkyBox + { size = 4; offset = 0; constantID = 0; }, + // doSkySheet + { size = 4; offset = 4; constantID = 1; }, + ); + }; + skybox_fragment = { + stage = fragment; + name = main; + module = $builtin/bsp_sky.frag; + specializationInfo = { + @inherit = $brush.shader.sky_specialization; + // doSkyBox, doSkySheet + data = "array(1, 0)"; + }; + }; + skysheet_fragment = { + stage = fragment; + name = main; + module = $builtin/bsp_sky.frag; + specializationInfo = { + @inherit = $brush.shader.sky_specialization; + // doSkyBox, doSkySheet + data = "array(0, 1)"; + }; + }; + turb_fragment = { + stage = fragment; + name = main; + module = $builtin/bsp_turb.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 1; stride = "4"; inputRate = instance; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 1; format = r32_uint; offset = 0; }, + ); + }; + inputAssembly = { + topology = triangle_fan; + primitiveRestartEnable = true; + }; + layout = { + setLayouts = (matrix_set, entity_set, oit_set, texture_set, texture_set); + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "4 * 4 + 4 + 4 + 4"; + }, + ); + }; + }; + alias = { + shader = { + depth_vertex = { + stage = vertex; + name = main; + module = $builtin/alias_depth.vert; + }; + gbuf_vertex = { + stage = vertex; + name = main; + module = $builtin/alias.vert; + }; + gbuf_fragment = { + stage = fragment; + name = main; + module = $builtin/alias_gbuf.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 1; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 2; stride = "2 * 4"; inputRate = instance; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 1; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 3; binding = 1; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 4; binding = 2; format = r32g32_sfloat; offset = 0; }, + ); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + layout = { + setLayouts = (matrix_set, texture_set, texture_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "3 * 4 + 2 * 4 * 4"; + }, + ); + }; + }; + iqm = { + shader = { + specialization = { + mapEntries = ( + // IQMDepthOnly + { size = 4; offset = 0; constantID = 0; }, + ); + }; + depth_vertex = { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + @inherit = $iqm.shader.specialization; + // IQMDepthOnly + data = "array(1)"; + }; + }; + gbuf_vertex = { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + @inherit = $iqm.shader.specialization; + // IQMDepthOnly + data = "array(0)"; + }; + }; + gbuf_fragment = { + stage = fragment; + name = main; + module = $builtin/iqm.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = 20; inputRate = vertex; }, + { binding = 1; stride = 40; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position + { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 12; }, // bonindices + { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 16; }, // boneweights + + { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord + { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal + { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent + { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color + + ); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + layout = { + setLayouts = (matrix_set, texture_set, bone_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "3 * 4 + 2 * 4 * 4 + 4"; + }, + ); + }; + }; + sprite = { + shader = { + depth_vertex = { + stage = vertex; + name = main; + module = $builtin/sprite_depth.vert; + }; + depth_fragment = { + stage = fragment; + name = main; + module = $builtin/sprite_depth.frag; + }; + gbuf_vertex = { + stage = vertex; + name = main; + module = $builtin/sprite_gbuf.vert; + }; + gbuf_fragment = { + stage = fragment; + name = main; + module = $builtin/sprite_gbuf.frag; + }; + }; + vertexInput = { + bindings = (); + attributes = (); + }; + inputAssembly = { + topology = triangle_strip; + // never draw more than 4 verts + primitiveRestartEnable = false; + }; + layout = { + setLayouts = (matrix_set, sprite_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + // note: overlap with fragment is for the frame number + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 64; + // note: overlap with vertex to share frame number + size = "2 * 4 + 2 * 4 + 4"; + }, + ); + }; + }; + particle = { + shader = { + vertex = { + stage = vertex; + name = main; + module = $builtin/particle.vert; + }; + geometry = { + stage = geometry; + name = main; + module = $builtin/particle.geom; + }; + fragment = { + stage = fragment; + name = main; + module = $builtin/particle.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = "4 * 4 * 4"; inputRate = instance; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 32; }, + { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 48; }, + ); + }; + inputAssembly = { + topology = point_list; + primitiveRestartEnable = false; + }; + layout = { + setLayouts = (matrix_set, texture_set, oit_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4"; + }, + ); + }; + }; + fstriangle = { + shader = { + vertex = { + stage = vertex; + name = main; + module = $builtin/fstriangle.vert; + }; + }; + }; + lighting = { + shader = { + fragment = { + stage = fragment; + name = main; + module = $builtin/lighting.frag; + }; + }; + }; + compose = { + shader = { + fragment = { + stage = fragment; + name = main; + module = $builtin/compose.frag; + }; + }; + } }; images = { depth = { @@ -194,37 +619,88 @@ renderpasses = { }; preserve = (color, emission, normal, position, output); }; + + base_pipeline = { + @inherit = $pipeline_base; + depthStencil = $depth_test_and_write; + }; pipelines = { bsp:depth = { color = $color.bsp; - pipeline = bsp_depth; tasks = ( { func = bsp_draw_queue; params = (main, solid); }, { func = bsp_draw_queue; params = (main, sky); }, ); + + stages = ( + $brush.shader.depth_vertex, + ); + vertexInput = { + bindings = ( + "$brush.vertexInput.bindings[0]", + "$brush.vertexInput.bindings[1]", + ); + attributes = ( + "$brush.vertexInput.attributes[0]", + "$brush.vertexInput.attributes[1]", + ); + }; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; }; alias:depth = { color = $color.alias; - pipeline = alias_depth; tasks = ( { func = "alias_draw"; }, ); + + stages = ( + $alias.shader.depth_vertex, + ); + vertexInput = { + // depth pass doesn't use UVs + bindings = ( + "$alias.vertexInput.bindings[0]", + "$alias.vertexInput.bindings[1]", + ); + attributes = ( + "$alias.vertexInput.attributes[0]", + "$alias.vertexInput.attributes[1]", + "$alias.vertexInput.attributes[2]", + "$alias.vertexInput.attributes[3]", + ); + }; + inputAssembly = $alias.inputAssembly; + layout = $alias.layout; }; iqm:depth = { color = $color.iqm; - pipeline = iqm_depth; tasks = ( { func = "iqm_draw"; }, ); + + stages = ( + $iqm.shader.depth_vertex, + ); + vertexInput = $iqm.vertexInput; + inputAssembly = $iqm.inputAssembly; + layout = $iqm.layout; }; sprite:depth = { color = $color.sprite; - pipeline = sprite_depth; tasks = ( { func = "sprite_draw"; }, ); + + stages = ( + $sprite.shader.depth_vertex, + $sprite.shader.depth_fragment, + ); + vertexInput = $sprite.vertexInput; + inputAssembly = $sprite.inputAssembly; + layout = $sprite.layout; }; }; }; @@ -239,32 +715,71 @@ renderpasses = { }; preserve = (color, emission, normal, position, output); }; + base_pipeline = $pipeline_base; pipelines = { - bsp:sky = { + bsp:skybox = { color = $color.bsp; - pipeline = $bsp_sky_pipeline; tasks = ( // FIXME sky should not use OIT { func = bsp_draw_queue; params = (main, sky); }, ); + + stages = ( + $brush.shader.quake_vertex, + $brush.shader.skybox_fragment, + ); + vertexInput = $brush.vertexInput; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; + }; + bsp:skysheet = { + color = $color.bsp; + tasks = ( + // FIXME sky should not use OIT + { func = bsp_draw_queue; + params = (main, sky); }, + ); + + stages = ( + $brush.shader.quake_vertex, + $brush.shader.skysheet_fragment, + ); + vertexInput = $brush.vertexInput; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; }; bsp:trans = { color = $color.bsp; - pipeline = bsp_turb; tasks = ( { func = bsp_draw_queue; params = (main, translucent); }, { func = bsp_draw_queue; params = (main, turbulent); }, ); + + stages = ( + $brush.shader.quake_vertex, + $brush.shader.turb_fragment, + ); + vertexInput = $brush.vertexInput; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; }; particles:trans = { color = $color.particles; - pipeline = partdraw; tasks = ( { func = particles_draw; }, ); + + stages = ( + $particle.shader.vertex, + $particle.shader.geometry, + $particle.shader.fragment, + ); + vertexInput = $particle.vertexInput; + inputAssembly = $particle.inputAssembly; + layout = $particle.layout; }; }; }; @@ -275,47 +790,89 @@ renderpasses = { }; attachments = { color = { - color = color_attachment_optimal; - emission = color_attachment_optimal; - normal = color_attachment_optimal; - position = color_attachment_optimal; + color = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; + emission = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; + normal = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; + position = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; }; depth = { depth = depth_stencil_read_only_optimal; }; preserve = (output); }; + base_pipeline = $pipeline_base; pipelines = { bsp:gbuffer = { color = $color.bsp; - pipeline = bsp_gbuf; tasks = ( { func = bsp_draw_queue; params = (main, solid); }, { func = bsp_draw_queue; params = (main, sky); }, ); + + stages = ( + $brush.shader.gbuf_vertex, + $brush.shader.gbuf_geometry, + $brush.shader.gbuf_fragment, + ); + vertexInput = $brush.vertexInput; + inputAssembly = $brush.inputAssembly; + layout = $brush.layout; }; alias:gbuffer = { color = $color.alias; - pipeline = alias_gbuf; tasks = ( { func = "alias_draw"; }, ); + + stages = ( + $alias.shader.gbuf_vertex, + $alias.shader.gbuf_fragment, + ); + vertexInput = $alias.vertexInput; + inputAssembly = $alias.inputAssembly; + layout = $alias.layout; }; iqm:gbuffer = { color = $color.iqm; - pipeline = iqm_gbuf; tasks = ( { func = "iqm_draw"; }, ); + + stages = ( + $iqm.shader.gbuf_vertex, + $iqm.shader.gbuf_fragment, + ); + vertexInput = $iqm.vertexInput; + inputAssembly = $iqm.inputAssembly; + layout = $iqm.layout; }; sprite:gbuffer = { color = $color.sprite; - pipeline = sprite_gbuf; tasks = ( { func = "sprite_draw"; }, ); + + stages = ( + $sprite.shader.gbuf_vertex, + $sprite.shader.gbuf_fragment, + ); + vertexInput = $sprite.vertexInput; + inputAssembly = $sprite.inputAssembly; + layout = $sprite.layout; }; }; }; @@ -333,17 +890,27 @@ renderpasses = { position = shader_read_only_optimal; }; color = { - opaque = color_attachment_optimal; + opaque = { + layout = color_attachment_optimal; + blend = $blend_disable; + }; }; preserve = (output); }; pipelines = { lights = { + @inherit = $compose_base; + color = $color.lights; - pipeline = lighting; tasks = ( { func = "lights_draw"; }, ); + + stages = ( + $fstriangle.shader.vertex, + $lighting.shader.fragment, + ); + layout = lighting.layout; }; }; }; @@ -363,17 +930,24 @@ renderpasses = { }; pipelines = { compose = { + @inherit = $compose_base; + color = $color.compose; - pipeline = compose; tasks = ( { func = "compose_draw"; }, ); + + stages = ( + $fstriangle.shader.vertex, + $compose.shader.fragment, + ); + layout = compose.layout; }; }; }; }; }; -/* deferred_cube = { + /*deferred_cube = { @inherit = $renderpasses.deferred; @next = (VkRenderPassMultiviewCreateInfo, { viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 5b00d1026..cacd19acc 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -123,6 +123,57 @@ write_function_tail (Struct *self) fprintf (output_file, "}\n"); } +static void +write_parse_type (Struct *self) +{ + fprintf (output_file, "\t\treturn PL_ParseStruct (%s_fields, item, data, " + "messages, context);\n", [self outname]); +} + +static void +write_auto_parse (Struct *self, string field) +{ + fprintf (output_file, "\t\tdo {\n"); + fprintf (output_file, "\t\t\tplfield_t *f = find_field (%s_fields, %s, " + "item, messages);\n", [self outname], sprintf ("\"%s\"", field)); + fprintf (output_file, "\t\t\tif (!f) {\n"); + fprintf (output_file, "\t\t\t\treturn 0;"); + fprintf (output_file, "\t\t\t};\n"); + fprintf (output_file, "\t\t\tf->parser (f, item, &%s, messages, context);\n", + sprintf ("((%s *) data)->%s", [self outname], field)); + fprintf (output_file, "\t\t} while (0);\n"); +} + +static int +check_need_table (Struct *self, PLItem *field_dict, string type) +{ + string key = nil; + switch (type) { + case "QFDictionary": key = ".dictionary"; break; + case "QFArray": key = ".array"; break; + case "QFBinary": key = ".binary"; break; + case "QFString": key = ".string"; break; + } + PLItem *type_obj = [field_dict getObjectForKey:key]; + int count = [type_obj numKeys]; + if (!count) { + return 0; + } + for (int i = 0; i < count; i++) { + string field = [type_obj keyAtIndex:i]; + PLItem *item = [type_obj getObjectForKey:field]; + string str = [item string]; + + if (field == ".parse") { + return 1; + } + if (str == "$auto") { + return 1; + } + } + return 0; +} + static void write_type (Struct *self, PLItem *field_dict, string type) { @@ -145,6 +196,11 @@ write_type (Struct *self, PLItem *field_dict, string type) PLItem *item = [type_obj getObjectForKey:field]; string str = [item string]; + if (field == ".parse") { + write_parse_type (self); + continue; + } + switch (str) { case "$item.string": str = "vkstrdup (context, PL_String (item))"; @@ -158,6 +214,9 @@ write_type (Struct *self, PLItem *field_dict, string type) case "$index": str = "field->offset"; break; + case "$auto": + write_auto_parse (self, field); + continue; } fprintf (output_file, "\t\t((%s *) data)->%s = %s;\n", [self outname], field, str); @@ -166,6 +225,45 @@ write_type (Struct *self, PLItem *field_dict, string type) fprintf (output_file, "\t}\n"); } +static void +write_parser (Struct *self, int have_sType, PLItem *only) +{ + write_function_head (self); + if (have_sType) { + fprintf (output_file, "\t((%s *) data)->sType", [self outname]); + fprintf (output_file, " = %s;\n", [self sTypeName]); + } + if (self.label_field) { + fprintf (output_file, "\t((%s *) data)->%s", [self outname], + self.label_field); + fprintf (output_file, " = vkstrdup (context, field->name);\n"); + } + if (only) { + fprintf (output_file, "\tplfield_t *f = &%s_fields[0];\n", + [self outname]); + fprintf (output_file, + "\tif (!PL_CheckType (PL_Type (item), f->type)) {\n" + "\t\tPL_TypeMismatch (messages, item, " + "f->name, f->type, PL_Type (item));\n" + "\t\treturn 0;\n" + "\t}\n" + "\tvoid *flddata = (byte *)data + f->offset;\n" + "\treturn f->parser (f, item, flddata, messages, " + "context);\n"); + } else { + fprintf (output_file, + "\tif (PL_Type (item) == QFString\n" + "\t\t&& !(item = parse_reference (item, \"%s\", " + "messages, context))) {\n" + "\t\treturn 0;\n" + "\t}\n" + "\treturn PL_ParseStruct (%s_fields, item, data, " + "messages, context);\n", + [self outname], [self outname]); + } + write_function_tail (self); +} + static void write_cexpr (Struct *self, Array *field_defs) { @@ -210,6 +308,61 @@ write_cexpr (Struct *self, Array *field_defs) fprintf (header_file, "extern exprtype_t %s_type;\n", [self outname]); } +static void +write_table (Struct *self, PLItem *field_dict, Array *field_defs, + PLItem *only, int need_parser) +{ + qfot_type_t *type = self.type; + int have_sType = 0; + int have_pNext = 0; + int readonly = [field_dict string] == "readonly"; + + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *field = &type.strct.fields[i]; + if (field.name == "sType") { + have_sType = 1; + } + if (field.name == "pNext") { + have_pNext = 1; + self.write_symtab = 1; + } + } + for (int i = [field_defs count]; i-- > 0; ) { + FieldDef *field_def = [field_defs objectAtIndex:i]; + [field_def writeParseData]; + } + if (!readonly) { + fprintf (output_file, "static plfield_t %s_fields[] = {\n", + [self outname]); + if (!only) { + fprintf (output_file, + "\t{\"@inherit\", 0, QFString, parse_inherit, " + "&%s_fields},\n", [self outname]); + } + if (have_pNext) { + fprintf (output_file, + "\t{\"@next\", field_offset (%s, pNext), " + "QFArray, parse_next, 0},", [self outname]); + } + for (int i = [field_defs count]; i-- > 0; ) { + FieldDef *field_def = [field_defs objectAtIndex:i]; + [field_def writeField]; + } + fprintf (output_file, "\t{ }\n"); + fprintf (output_file, "};\n"); + + if (need_parser) { + write_parser (self, have_sType, only); + } + if (have_pNext) { + fprintf (output_file, "static parserref_t %s_parser = ", + [self outname]); + fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", + [self outname], [self parseFunc], [self outname]); + } + } +} + -(void) writeTable { if ([parse string] == "skip") { @@ -278,7 +431,19 @@ write_cexpr (Struct *self, Array *field_defs) if ([field_dict getObjectForKey:".type"]) { PLItem *type = [field_dict getObjectForKey:".type"]; string str = [type string]; + int need_table = 0; + if (str) { + need_table |= check_need_table (self, field_dict, str); + } else { + for (int i = [type count]; i-- > 0; ) { + string str = [[type getObjectAtIndex:i] string]; + need_table |= check_need_table (self, field_dict, str); + } + } + if (need_table) { + write_table (self, field_dict, field_defs, only, 0); + } write_function_head (self); fprintf (output_file, "\tpltype_t type = PL_Type (item);\n"); if (str) { @@ -298,85 +463,7 @@ write_cexpr (Struct *self, Array *field_defs) return; } - int have_sType = 0; - int have_pNext = 0; - int readonly = [field_dict string] == "readonly"; - - for (int i = 0; i < type.strct.num_fields; i++) { - qfot_var_t *field = &type.strct.fields[i]; - if (field.name == "sType") { - have_sType = 1; - } - if (field.name == "pNext") { - have_pNext = 1; - write_symtab = 1; - } - } - for (int i = [field_defs count]; i-- > 0; ) { - FieldDef *field_def = [field_defs objectAtIndex:i]; - [field_def writeParseData]; - } - if (!readonly) { - fprintf (output_file, "static plfield_t %s_fields[] = {\n", - [self outname]); - if (!only) { - fprintf (output_file, - "\t{\"@inherit\", 0, QFString, parse_inherit, " - "&%s_fields},\n", [self outname]); - } - if (have_pNext) { - fprintf (output_file, - "\t{\"@next\", field_offset (%s, pNext), " - "QFArray, parse_next, 0},", [self outname]); - } - for (int i = [field_defs count]; i-- > 0; ) { - FieldDef *field_def = [field_defs objectAtIndex:i]; - [field_def writeField]; - } - fprintf (output_file, "\t{ }\n"); - fprintf (output_file, "};\n"); - - write_function_head (self); - if (have_sType) { - fprintf (output_file, "\t((%s *) data)->sType", [self outname]); - fprintf (output_file, " = %s;\n", [self sTypeName]); - } - if (label_field) { - fprintf (output_file, "\t((%s *) data)->%s", [self outname], - label_field); - fprintf (output_file, " = vkstrdup (context, field->name);\n"); - } - if (only) { - fprintf (output_file, "\tplfield_t *f = &%s_fields[0];\n", - [self outname]); - fprintf (output_file, - "\tif (!PL_CheckType (PL_Type (item), f->type)) {\n" - "\t\tPL_TypeMismatch (messages, item, " - "f->name, f->type, PL_Type (item));\n" - "\t\treturn 0;\n" - "\t}\n" - "\tvoid *flddata = (byte *)data + f->offset;\n" - "\treturn f->parser (f, item, flddata, messages, " - "context);\n"); - } else { - fprintf (output_file, - "\tif (PL_Type (item) == QFString\n" - "\t\t&& !(item = parse_reference (item, \"%s\", " - "messages, context))) {\n" - "\t\treturn 0;\n" - "\t}\n" - "\treturn PL_ParseStruct (%s_fields, item, data, " - "messages, context);\n", - [self outname], [self outname]); - } - write_function_tail (self); - if (have_pNext) { - fprintf (output_file, "static parserref_t %s_parser = ", - [self outname]); - fprintf (output_file, "{\"%s\", %s, sizeof(%s)};\n", - [self outname], [self parseFunc], [self outname]); - } - } + write_table (self, field_dict, field_defs, only, 1); write_cexpr (self, field_defs); } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index b0b256446..bfda002e5 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -152,6 +152,19 @@ typedef struct parse_custom_s { size_t num_offsets; } parse_custom_t; +static plfield_t *__attribute__((used)) +find_field (plfield_t *fields, const char *field_name, + const plitem_t *item, plitem_t *messages) +{ + for (plfield_t *f = fields; f->name; f++) { + if (strcmp (f->name, field_name) == 0) { + return f; + } + } + PL_Message (messages, item, "error: unknown field %s", field_name); + return 0; +} + static int parse_basic (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) @@ -355,7 +368,7 @@ parse_single (const plfield_t *field, const plitem_t *item, return 0; } - plfield_t f = { 0, 0, single->type, single->parser, 0 }; + plfield_t f = { field->name, 0, single->type, single->parser, 0 }; void *value = vkparse_alloc (context, single->stride); memset (value, 0, single->stride); if (!single->parser (&f, item, value, messages, context)) { diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 49fc3ca6a..45afa14ab 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -46,6 +46,7 @@ qfv_framebufferinfo_t, qfv_renderpassinfo_t, qfv_renderinfo_t, + qfv_pipelinespec_t, ); parse = { VkSubpassDescription = { @@ -436,7 +437,16 @@ }; qfv_attachmentrefinfo_s = { .name = qfv_attachmentrefinfo_t; - .only = layout; + .type = (QFString, QFDictionary); + .string = { + name = $name; + layout = $auto; + }; + .dictionary = { + .parse = auto; + }; + layout = auto; + blend = auto; }; qfv_attachmentsetinfo_s = { .name = qfv_attachmentsetinfo_t; @@ -477,12 +487,58 @@ type = string; string = name; }; - pipeline = auto; tasks = { type = (array, qfv_taskinfo_t); size = num_tasks; values = tasks; - } + }; + + flags = auto; + stages = { + type = (array, VkPipelineShaderStageCreateInfo); + size = num_graph_stages; + values = graph_stages; + }; + vertexInput = { + type = (single, VkPipelineVertexInputStateCreateInfo); + value = vertexInput; + }; + inputAssembly = { + type = (single, VkPipelineInputAssemblyStateCreateInfo); + value = inputAssembly; + }; + tessellation = { + type = (single, VkPipelineTessellationStateCreateInfo); + value = tessellation; + }; + viewport = { + type = (single, VkPipelineViewportStateCreateInfo); + value = viewport; + }; + rasterization = { + type = (single, VkPipelineRasterizationStateCreateInfo); + value = rasterization; + }; + multisample = { + type = (single, VkPipelineMultisampleStateCreateInfo); + value = multisample; + }; + depthStencil = { + type = (single, VkPipelineDepthStencilStateCreateInfo); + value = depthStencil; + }; + colorBlend = { + type = (single, VkPipelineColorBlendStateCreateInfo); + value = colorBlend; + }; + dynamic = { + type = (single, VkPipelineDynamicStateCreateInfo); + value = dynamic; + }; + layout = { + type = (single, qfv_reference_t); + value = layout; + }; }; qfv_subpassinfo_s = { .name = qfv_subpassinfo_t; @@ -505,6 +561,11 @@ size = num_pipelines; values = pipelines; }; + base_pipeline = { + //type = (labeledsingle, qfv_pipelineinfo_t, name); + type = (single, qfv_pipelineinfo_t, name); + value = base_pipeline; + }; }; qfv_framebufferinfo_s = { .name = qfv_framebufferinfo_t; @@ -557,6 +618,6 @@ size = num_renderpasses; values = renderpasses; }; - } + }; }; } From 105bbbc0f2d69dc0293606782cfec7128e3ffa50 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Feb 2023 17:16:50 +0900 Subject: [PATCH 3426/3664] [vulkan] Use correct type for subpass attachments Subpass attachments needs to be an attachment set, not just an array of refs. The parsing was correct. --- include/QF/Vulkan/render.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 0e2ed845c..e0cc7d624 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -116,8 +116,7 @@ typedef struct qfv_subpassinfo_s { const char *name; uint32_t num_dependencies; qfv_dependencyinfo_t *dependencies; - uint32_t num_attachments; - qfv_attachmentrefinfo_t *attachments; + qfv_attachmentsetinfo_t *attachments; uint32_t num_pipelines; qfv_pipelineinfo_t *pipelines; qfv_pipelineinfo_t *base_pipeline; From ed74a6420b064a99cea048e5f737ebf1f9e06975 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 18 Feb 2023 17:22:06 +0900 Subject: [PATCH 3427/3664] [vulkan] Set a reasonable default for color blend Vulkan requires color blend state is only for color attachments (ignored otherwise), but it shouldn't be necessary to actually specify the blend state and instead have it default to something reasonable. Unfortunately, colorWriteMask affects the output even if blending is disabled, so it must be initialized to something reasonable (r|g|b|a) for when the default is used. --- libs/video/renderer/vulkan/vkparse.plist | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 45afa14ab..693b15b39 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -441,6 +441,7 @@ .string = { name = $name; layout = $auto; + blend = "(VkPipelineColorBlendAttachmentState) { .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT }" }; .dictionary = { .parse = auto; From fd36147749a248bc5696c3d41402a386cca0415e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Feb 2023 12:25:13 +0900 Subject: [PATCH 3428/3664] [vulkan] Complete resource image and image view I don't remember why I kept the abbreviated configs for images and image views, but it because such that I need to be able to specify them completely. In addition, image views support external images. The rest was just cleaning up after the changes to qfv_resobj_t. --- include/QF/Vulkan/resource.h | 11 ++++- libs/models/iqm/vulkan_model_iqm.c | 6 ++- libs/video/renderer/vulkan/resource.c | 47 ++++++++++--------- libs/video/renderer/vulkan/vulkan_draw.c | 12 ++++- libs/video/renderer/vulkan/vulkan_lighting.c | 3 +- .../renderer/vulkan/vulkan_translucent.c | 6 ++- 6 files changed, 56 insertions(+), 29 deletions(-) diff --git a/include/QF/Vulkan/resource.h b/include/QF/Vulkan/resource.h index ac47d0609..74a5deb2e 100644 --- a/include/QF/Vulkan/resource.h +++ b/include/QF/Vulkan/resource.h @@ -31,23 +31,30 @@ typedef struct qfv_resobj_s { VkBufferView view; } buffer_view; struct { - int cubemap; + VkImageCreateFlags flags; VkImageType type; VkFormat format; VkExtent3D extent; uint32_t num_mipmaps; uint32_t num_layers; VkSampleCountFlags samples; + VkImageTiling tiling; VkImageUsageFlags usage; + VkSharingMode sharing; + uint32_t num_queue_inds; + const uint32_t *queue_inds; + VkImageLayout initialLayout; VkImage image; VkDeviceSize offset; } image; struct { unsigned image; + VkImage external_image; + VkImageViewCreateFlags flags; VkImageViewType type; VkFormat format; - VkImageAspectFlags aspect; VkComponentMapping components; + VkImageSubresourceRange subresourceRange; VkImageView view; } image_view; }; diff --git a/libs/models/iqm/vulkan_model_iqm.c b/libs/models/iqm/vulkan_model_iqm.c index 42f8f867b..b86e4108d 100644 --- a/libs/models/iqm/vulkan_model_iqm.c +++ b/libs/models/iqm/vulkan_model_iqm.c @@ -439,7 +439,11 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx) .image = image_ind, .type = VK_IMAGE_VIEW_TYPE_2D, .format = mesh->mesh->objects[image_ind].image.format, - .aspect = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = VK_REMAINING_MIP_LEVELS, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, }, }; } diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index 029081f71..b2b56deae 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -42,17 +42,25 @@ create_image (qfv_device_t *device, qfv_resobj_t *image_obj) { qfv_devfuncs_t *dfunc = device->funcs; __auto_type image = &image_obj->image; + if (image->image) { + // the image was created externally and is being + return; + } VkImageCreateInfo createInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 0, - image->cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, - image->type, image->format, image->extent, image->num_mipmaps, - image->num_layers, - image->samples, - VK_IMAGE_TILING_OPTIMAL, - image->usage, - VK_SHARING_MODE_EXCLUSIVE, - 0, 0, - VK_IMAGE_LAYOUT_UNDEFINED, + .flags = image->flags, + .imageType = image->type, + .format = image->format, + .extent = image->extent, + .mipLevels = image->num_mipmaps, + .arrayLayers = image->num_layers, + .samples = image->samples, + .tiling = image->tiling, + .usage = image->usage, + .sharingMode = image->sharing, + .queueFamilyIndexCount = image->num_queue_inds, + .pQueueFamilyIndices = image->queue_inds, + .initialLayout = image->initialLayout, }; dfunc->vkCreateImage (device->dev, &createInfo, 0, &image->image); } @@ -63,23 +71,17 @@ create_image_view (qfv_device_t *device, qfv_resobj_t *imgview_obj, { qfv_devfuncs_t *dfunc = device->funcs; __auto_type view = &imgview_obj->image_view; - __auto_type image = &imgobj->image; + VkImage image = view->external_image ? view->external_image + : imgobj->image.image; VkImageViewCreateInfo createInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0, - //FIXME flags should be input for both image and image view - .flags = image->cubemap ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, - .image = image->image, + .flags = view->flags, + .image = image, .viewType = view->type, .format = view->format, .components = view->components, - .subresourceRange = { - .aspectMask = view->aspect, - .baseMipLevel = 0, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, + .subresourceRange = view->subresourceRange, }; dfunc->vkCreateImageView (device->dev, &createInfo, 0, &view->view); } @@ -137,8 +139,9 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) { __auto_type imgview = &obj->image_view; __auto_type imgobj = &resource->objects[imgview->image]; - if (imgview->image >= resource->num_objects - || imgobj->type != qfv_res_image) { + if (!imgview->external_image + && (imgview->image >= resource->num_objects + || imgobj->type != qfv_res_image)) { Sys_Error ("%s:%s invalid image for view", resource->name, obj->name); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index ea0a10e3f..deaafb716 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -691,7 +691,11 @@ load_lmp (const char *path, vulkan_ctx_t *ctx) .image = 0, .type = VK_IMAGE_VIEW_TYPE_2D, .format = font->resource->glyph_image.image.format, - .aspect = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = VK_REMAINING_MIP_LEVELS, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, .components = { .r = VK_COMPONENT_SWIZZLE_IDENTITY, .g = VK_COMPONENT_SWIZZLE_IDENTITY, @@ -1649,7 +1653,11 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) .image = 2, .type = VK_IMAGE_VIEW_TYPE_2D, .format = font->resource->glyph_image.image.format, - .aspect = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = VK_REMAINING_MIP_LEVELS, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, .components = { .r = VK_COMPONENT_SWIZZLE_R, .g = VK_COMPONENT_SWIZZLE_R, diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 4439d1d32..33c8fc52b 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -790,11 +790,12 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx) .objects = (qfv_resobj_t *) &shad[1], }; for (int i = 0; i < numMaps; i++) { + int cube = maps[i].layers < 6 ? 0 : maps[i].cube; shad->objects[i] = (qfv_resobj_t) { .name = "map", .type = qfv_res_image, .image = { - .cubemap = maps[i].layers < 6 ? 0 : maps[i].cube, + .flags = cube ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, .type = VK_IMAGE_TYPE_2D, .format = VK_FORMAT_X8_D24_UNORM_PACK32, .extent = { maps[i].size, maps[i].size, 1 }, diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index e99fba25f..541485ea1 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -194,7 +194,11 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) .image = i, .type = VK_IMAGE_VIEW_TYPE_2D_ARRAY, .format = VK_FORMAT_R32_SINT, - .aspect = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = VK_REMAINING_MIP_LEVELS, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, }, }; buffer_objs[i] = (qfv_resobj_t) { From fc06547dd98e46f91619afe2a1ddbd3e44029b06 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Feb 2023 12:31:40 +0900 Subject: [PATCH 3429/3664] [vulkan] move qfv_output_t to render.h The plan is qf_renderpass.h (and vulkan_renderpass.c) will eventually disappear as they get absorbed by render.[ch]. --- include/QF/Vulkan/qf_renderpass.h | 12 ++---------- include/QF/Vulkan/render.h | 10 ++++++++++ libs/video/renderer/vulkan/render.c | 1 - libs/video/renderer/vulkan/vkgen/vulkan.r | 12 ------------ 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index 7528517ad..7f9d6961e 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -9,6 +9,8 @@ #include "QF/darray.h" #include "QF/simd/types.h" +#include "QF/Vulkan/render.h" + typedef struct qfv_framebufferset_s DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t; @@ -41,16 +43,6 @@ typedef struct clearvalueset_s typedef void (*qfv_draw_t) (qfv_renderframe_t *rFrame); -typedef struct qfv_output_s { - VkExtent2D extent; - VkImage image; // only if owned - VkImageView view; - VkFormat format; - uint32_t frames; - VkImageView *view_list; // per frame - VkImageLayout finalLayout; -} qfv_output_t; - typedef struct qfv_renderpass_s { struct vulkan_ctx_s *vulkan_ctx; vec4f_t color; // for debugging diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index e0cc7d624..565f91f4a 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -9,6 +9,16 @@ #include "QF/cexpr.h" #include "QF/simd/types.h" +typedef struct qfv_output_s { + VkExtent2D extent; + VkImage image; // only if owned + VkImageView view; + VkFormat format; + uint32_t frames; + VkImageView *view_list; // per frame + VkImageLayout finalLayout; +} qfv_output_t; + typedef struct qfv_reference_s { const char *name; int line; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 488db0eb8..3b269bf12 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -46,7 +46,6 @@ #include "QF/Vulkan/pipeline.h" #include "vid_vulkan.h" -#include "QF/Vulkan/qf_renderpass.h"//FIXME #include "vkparse.h" static void diff --git a/libs/video/renderer/vulkan/vkgen/vulkan.r b/libs/video/renderer/vulkan/vkgen/vulkan.r index c40e48098..0ac44aeda 100644 --- a/libs/video/renderer/vulkan/vkgen/vulkan.r +++ b/libs/video/renderer/vulkan/vkgen/vulkan.r @@ -11,15 +11,3 @@ typedef struct qfv_subpass_s { vec4 color; string name; } qfv_subpass_t; - -//FIXME copy of qfv_output_t in qf_renderpass.h -//except it doesn't really matter because a custom spec is used -typedef struct qfv_output_s { - VkExtent2D extent; - VkImage image; - VkImageView view; - VkFormat format; - uint32_t frames; - VkImageView *view_list; - VkImageLayout finalLayout; -} qfv_output_t; From 1ef658a2600126d076ba2b0ac7c34a3504a8a099 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Feb 2023 12:38:46 +0900 Subject: [PATCH 3430/3664] [vulkan] Add a function to config render output It just moves the already existing code from vulkan_main.c. --- include/QF/Vulkan/qf_vid.h | 4 ++++ libs/video/renderer/vulkan/vulkan_main.c | 11 +---------- libs/video/renderer/vulkan/vulkan_vid_common.c | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index ced3132e3..7360bbdab 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -80,6 +80,10 @@ void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); void Vulkan_Shutdown_Common (struct vulkan_ctx_s *ctx); void Vulkan_CreateStagingBuffers (struct vulkan_ctx_s *ctx); +struct qfv_output_s; +void Vulkan_ConfigOutput (struct vulkan_ctx_s *ctx, + struct qfv_output_s *output); + VkPipeline Vulkan_CreateComputePipeline (struct vulkan_ctx_s *ctx, const char *name); VkPipeline Vulkan_CreateGraphicsPipeline (struct vulkan_ctx_s *ctx, diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index f3d5084fa..06880ef02 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -177,16 +177,7 @@ void Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) { __auto_type rp = QFV_RenderPass_New (ctx, "deferred", main_draw); - rp->output = (qfv_output_t) { - .extent = ctx->swapchain->extent, - .frames = ctx->swapchain->numImages, - }; - if (vulkan_frame_width > 0) { - rp->output.extent.width = vulkan_frame_width; - } - if (vulkan_frame_height > 0) { - rp->output.extent.height = vulkan_frame_height; - } + Vulkan_ConfigOutput (ctx, &rp->output); QFV_RenderPass_CreateAttachments (rp); QFV_RenderPass_CreateRenderPass (rp); QFV_RenderPass_CreateFramebuffer (rp); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index acffbe622..965b7f1ae 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -280,3 +280,18 @@ Vulkan_BeginEntityLabel (vulkan_ctx_t *ctx, VkCommandBuffer cmd, entity_t ent) va (ctx->va_ctx, "ent %03x.%05x [%g, %g, %g]", entgen, entind, VectorExpand (pos)), color); } + +void +Vulkan_ConfigOutput (vulkan_ctx_t *ctx, qfv_output_t *output) +{ + *output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .frames = ctx->swapchain->numImages, + }; + if (vulkan_frame_width > 0) { + output->extent.width = vulkan_frame_width; + } + if (vulkan_frame_height > 0) { + output->extent.height = vulkan_frame_height; + } +} From 421467529f8e3028cf2837b8df3a83cc7e6d5f97 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 19 Feb 2023 12:53:02 +0900 Subject: [PATCH 3431/3664] [vulkan] Create the render images and views And tear them down again on shutdown. The images and views are in a qfv_resource_t block, making their management much easier. --- include/QF/Vulkan/render.h | 30 ++- libs/video/renderer/vid_render_vulkan.c | 5 +- libs/video/renderer/vulkan/render.c | 209 ++++++++++++++++++- libs/video/renderer/vulkan/rp_main_def.plist | 12 +- libs/video/renderer/vulkan/vkparse.plist | 1 + 5 files changed, 243 insertions(+), 14 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 565f91f4a..197a01573 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -41,8 +41,7 @@ typedef struct qfv_imageinfo_s { typedef struct qfv_imageviewinfo_s { const char *name; VkImageViewCreateFlags flags; - //VkImage image; - const char *image; + qfv_reference_t image; VkImageViewType viewType; VkFormat format; VkComponentMapping components; @@ -102,7 +101,6 @@ typedef struct qfv_attachmentsetinfo_s { typedef struct qfv_pipelineinfo_s { vec4f_t color; const char *name; - qfv_reference_t pipeline; uint32_t num_tasks; qfv_taskinfo_t *tasks; @@ -118,7 +116,7 @@ typedef struct qfv_pipelineinfo_s { const VkPipelineDepthStencilStateCreateInfo *depthStencil; const VkPipelineColorBlendStateCreateInfo *colorBlend; const VkPipelineDynamicStateCreateInfo *dynamic; - qfv_reference_t *layout; + qfv_reference_t layout; } qfv_pipelineinfo_t; typedef struct qfv_subpassinfo_s { @@ -157,14 +155,9 @@ typedef struct qfv_renderinfo_s { qfv_imageviewinfo_t *views; uint32_t num_renderpasses; qfv_renderpassinfo_t *renderpasses; + qfv_output_t output; } qfv_renderinfo_t; -typedef struct qfv_renderctx_s { - struct hashctx_s *hashctx; - exprtab_t task_functions; - qfv_renderinfo_t *renderinfo; -} qfv_renderctx_t; - typedef struct qfv_label_s { vec4f_t color; const char *name; @@ -217,9 +210,24 @@ typedef struct qfv_renderpass_s_ { qfv_subpass_t_ *subpasses; } qfv_renderpass_t_; +typedef struct qfv_render_s { + struct qfv_resource_s *resources; + struct qfv_resobj_s *images; + struct qfv_resobj_s *image_views; +} qfv_render_t; + +typedef struct qfv_renderctx_s { + struct hashctx_s *hashctx; + exprtab_t task_functions; + qfv_renderinfo_t *renderinfo; + qfv_render_t *render; +} qfv_renderctx_t; + void QFV_RunRenderPass (qfv_renderpass_t_ *rp, struct vulkan_ctx_s *ctx); -void QFV_LoadRenderPass (struct vulkan_ctx_s *ctx); +void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx); +void QFV_BuildRender (struct vulkan_ctx_s *ctx); void QFV_Render_Init (struct vulkan_ctx_s *ctx); +void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx); void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys); #endif//__QF_Vulkan_render_h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 7e80bc68d..25ada2b43 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -116,7 +116,8 @@ vulkan_R_Init (void) Vulkan_Translucent_Init (vulkan_ctx); Vulkan_Compose_Init (vulkan_ctx); - QFV_LoadRenderPass (vulkan_ctx); + QFV_LoadRenderInfo (vulkan_ctx); + QFV_BuildRender (vulkan_ctx); Skin_Init (); @@ -742,6 +743,8 @@ vulkan_vid_render_shutdown (void) Vulkan_Palette_Shutdown (vulkan_ctx); Vulkan_Texture_Shutdown (vulkan_ctx); + QFV_Render_Shutdown (vulkan_ctx); + QFV_DestroyStagingBuffer (vulkan_ctx->staging); df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 3b269bf12..cd4af8e80 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -38,11 +38,13 @@ # include #endif +#include "QF/cmem.h" #include "QF/hash.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/render.h" +#include "QF/Vulkan/resource.h" #include "QF/Vulkan/pipeline.h" #include "vid_vulkan.h" @@ -124,15 +126,201 @@ QFV_RunRenderPass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) QFV_CmdEndLabel (device, cmd); } +static qfv_output_t +get_output (vulkan_ctx_t *ctx, plitem_t *item) +{ + qfv_output_t output = {}; + Vulkan_ConfigOutput (ctx, &output); + + plitem_t *output_def = PL_ObjectForKey (item, "output"); + if (output_def) { + // QFV_ParseOutput clears the structure, but extent and frames need to + // be preserved + qfv_output_t o = output; + QFV_ParseOutput (ctx, &o, output_def, item); + output.format = o.format; + output.finalLayout = o.finalLayout; + } + return output; +} + void -QFV_LoadRenderPass (vulkan_ctx_t *ctx) +QFV_LoadRenderInfo (vulkan_ctx_t *ctx) { __auto_type rctx = ctx->render_context; plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); + __auto_type output = get_output (ctx, item); + Vulkan_Script_SetOutput (ctx, &output); rctx->renderinfo = QFV_ParseRenderInfo (ctx, item, rctx); } +typedef struct { + uint32_t num_images; + uint32_t num_views; + + uint32_t num_renderpasses; + uint32_t num_attachments; + uint32_t num_subpasses; + uint32_t num_dependencies; + uint32_t num_attachmentrefs; + uint32_t num_colorblend; + uint32_t num_preserve; + uint32_t num_pipelines; + uint32_t num_tasks; + uint32_t num_stages; +} objcount_t; + +static void +count_pl_stuff (qfv_pipelineinfo_t *pli, objcount_t *counts) +{ + counts->num_tasks += pli->num_tasks; + counts->num_stages += pli->num_graph_stages; +} + +static void +count_as_stuff (qfv_attachmentsetinfo_t *as, objcount_t *counts) +{ + counts->num_attachmentrefs += as->num_input; + counts->num_attachmentrefs += as->num_color; + counts->num_colorblend += as->num_color; + if (as->resolve) { + counts->num_attachmentrefs += as->num_color; + } + if (as->depth) { + counts->num_attachmentrefs += 1; + } + counts->num_preserve += as->num_preserve; +} + +static void +count_sp_stuff (qfv_subpassinfo_t *spi, objcount_t *counts) +{ + counts->num_dependencies += spi->num_dependencies; + if (spi->attachments) { + count_as_stuff (spi->attachments, counts); + } + counts->num_pipelines += spi->num_pipelines; + for (uint32_t i = 0; i < spi->num_pipelines; i++) { + count_pl_stuff (spi->pipelines, counts); + } +} + +static void +count_rp_stuff (qfv_renderpassinfo_t *rpi, objcount_t *counts) +{ + counts->num_attachments += rpi->num_attachments; + counts->num_subpasses += rpi->num_subpasses; + for (uint32_t i = 0; i < rpi->num_subpasses; i++) { + count_sp_stuff (&rpi->subpasses[i], counts); + } +} + +static void +count_stuff (qfv_renderinfo_t *renderinfo, objcount_t *counts) +{ + counts->num_images += renderinfo->num_images; + counts->num_views += renderinfo->num_views; + counts->num_renderpasses += renderinfo->num_renderpasses; + for (uint32_t i = 0; i < renderinfo->num_renderpasses; i++) { + count_rp_stuff (&renderinfo->renderpasses[i], counts); + } +} + +static void +create_resources (vulkan_ctx_t *ctx, objcount_t *counts) +{ + __auto_type rctx = ctx->render_context; + __auto_type rinfo = rctx->renderinfo; + __auto_type render = rctx->render; + + render->resources = malloc (sizeof(qfv_resource_t) + + counts->num_images * sizeof (qfv_resobj_t) + + counts->num_views * sizeof (qfv_resobj_t)); + render->images = (qfv_resobj_t *) &render->resources[1]; + render->image_views = &render->images[counts->num_images]; + + render->resources[0] = (qfv_resource_t) { + .name = "render", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = counts->num_images + counts->num_views, + .objects = render->images, + }; + for (uint32_t i = 0; i < counts->num_images; i++) { + __auto_type img = &rinfo->images[i]; + render->images[i] = (qfv_resobj_t) { + .name = img->name, + .type = qfv_res_image, + .image = { + .flags = img->flags, + .type = img->imageType, + .format = img->format, + .extent = img->extent, + .num_mipmaps = img->mipLevels, + .num_layers = img->arrayLayers, + .samples = img->samples, + .tiling = img->tiling, + .usage = img->usage, + .initialLayout = img->initialLayout, + }, + }; + } + int error = 0; + for (uint32_t i = 0; i < counts->num_views; i++) { + __auto_type view = &rinfo->views[i]; + render->image_views[i] = (qfv_resobj_t) { + .name = view->name, + .type = qfv_res_image_view, + .image_view = { + .flags = view->flags, + .type = view->viewType, + .format = view->format, + .components = view->components, + .subresourceRange = view->subresourceRange, + }, + }; + if (strcmp (view->image.name, "$output.image") == 0) { + __auto_type image = rinfo->output.image; + render->image_views[i].image_view.external_image = image; + render->image_views[i].image_view.image = -1; + } else { + qfv_resobj_t *img = 0; + for (uint32_t j = 0; j < rinfo->num_images; j++) { + if (strcmp (view->image.name, rinfo->images[j].name) == 0) { + img = &render->images[j]; + } + } + if (img) { + uint32_t ind = img - render->resources->objects; + render->image_views[i].image_view.image = ind; + } else { + Sys_Printf ("%d: unknown image reference: %s\n", + view->image.line, view->image.name); + error = 1; + } + } + } + if (error) { + free (render->resources); + render->resources = 0; + return; + } + QFV_CreateResource (ctx->device, render->resources); +} + +void +QFV_BuildRender (vulkan_ctx_t *ctx) +{ + __auto_type rctx = ctx->render_context; + + rctx->render = calloc (1, sizeof (qfv_render_t)); + + objcount_t counts = {}; + count_stuff (rctx->renderinfo, &counts); + create_resources (ctx, &counts); +} + void QFV_Render_Init (vulkan_ctx_t *ctx) { @@ -146,6 +334,25 @@ QFV_Render_Init (vulkan_ctx_t *ctx) rctx->task_functions.symbols = 0; } +void +QFV_Render_Shutdown (vulkan_ctx_t *ctx) +{ + __auto_type rctx = ctx->render_context; + if (rctx->render) { + if (rctx->render->resources) { + QFV_DestroyResource (ctx->device, rctx->render->resources); + free (rctx->render->resources); + } + free (rctx->render); + } + if (rctx->renderinfo) { + delete_memsuper (rctx->renderinfo->memsuper); + } + if (rctx->task_functions.tab) { + Hash_DelTable (rctx->task_functions.tab); + } +} + void QFV_Render_AddTasks (vulkan_ctx_t *ctx, exprsym_t *task_syms) { diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 09e7652d3..1ef3daee2 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -521,6 +521,11 @@ images = { @inherit = $image_base; format = r16g16b16a16_sfloat; }; + output = { + @inherit = $image_base; + usage = color_attachment|input_attachment|sampled; + format = $output.format; + }; }; views = { depth = { @@ -558,10 +563,15 @@ views = { }; output = { @inherit = $view_base; - image = $output.image; + image = output; format = $output.format; } }; +output = { + view = $output; + format = r16g16b16a16_sfloat; + finalLayout = shader_read_only_optimal; +}; renderpasses = { deferred = { attachments = { diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 693b15b39..70bdcc9ff 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -604,6 +604,7 @@ qfv_renderinfo_s = { .name = qfv_renderinfo_t; properties = ignore; + output = ignore; images = { type = (labeledarray, qfv_imageinfo_t, name); size = num_images; From f13bc4f4b1712e6152fa9e872dccf55127204d05 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Feb 2023 00:42:12 +0900 Subject: [PATCH 3432/3664] [vkgen] Allow mixed dictionary .type parsing --- libs/video/renderer/vulkan/vkgen/vkstruct.r | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index cacd19acc..0194aaeaa 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -126,8 +126,10 @@ write_function_tail (Struct *self) static void write_parse_type (Struct *self) { - fprintf (output_file, "\t\treturn PL_ParseStruct (%s_fields, item, data, " - "messages, context);\n", [self outname]); + fprintf (output_file, "\t\tif (!PL_ParseStruct (%s_fields, item, data, " + "messages, context)) {\n", [self outname]); + fprintf (output_file, "\t\t\treturn 0;\n"); + fprintf (output_file, "\t\t}\n"); } static void From 75e553ffa01c7caf36ae05e8b9d950c689dc17b6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Feb 2023 00:44:26 +0900 Subject: [PATCH 3433/3664] [vulkan] Try to create render passes and pipelines The render passes seem to be created successfully, but pipelines fail due to not having layout set, resulting in a segfault (bug in validation layers?). --- include/QF/Vulkan/render.h | 15 +- libs/video/renderer/vulkan/render.c | 407 ++++++++++++++++++- libs/video/renderer/vulkan/rp_main_def.plist | 1 - libs/video/renderer/vulkan/vkparse.c | 2 +- libs/video/renderer/vulkan/vkparse.plist | 15 +- 5 files changed, 416 insertions(+), 24 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 197a01573..86a33fa8a 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -61,7 +61,6 @@ typedef struct qfv_dependencyinfo_s { } qfv_dependencyinfo_t; typedef struct qfv_attachmentinfo_s { - vec4f_t color; const char *name; VkAttachmentDescriptionFlags flags; VkFormat format; @@ -83,6 +82,7 @@ typedef struct qfv_taskinfo_s { typedef struct qfv_attachmentrefinfo_s { const char *name; + int line; VkImageLayout layout; VkPipelineColorBlendAttachmentState blend; } qfv_attachmentrefinfo_t; @@ -95,7 +95,7 @@ typedef struct qfv_attachmentsetinfo_s { qfv_attachmentrefinfo_t *resolve; qfv_attachmentrefinfo_t *depth; uint32_t num_preserve; - const char **preserve; + qfv_reference_t *preserve; } qfv_attachmentsetinfo_t; typedef struct qfv_pipelineinfo_s { @@ -139,6 +139,7 @@ typedef struct qfv_framebufferinfo_s { } qfv_framebufferinfo_t; typedef struct qfv_renderpassinfo_s { + vec4f_t color; const char *name; uint32_t num_attachments; qfv_attachmentinfo_t *attachments; @@ -182,13 +183,16 @@ typedef struct qfv_pipeline_s { uint32_t num_descriptor_sets; uint32_t first_descriptor_set; VkDescriptorSet *descriptor_sets; + + uint32_t task_count; + qfv_taskinfo_t *tasks; } qfv_pipeline_t; typedef struct qfv_subpass_s_ { qfv_label_t label; VkCommandBufferBeginInfo beginInfo; VkCommandBuffer cmd; - uint32_t pipline_count; + uint32_t pipeline_count; qfv_pipeline_t *pipelines; } qfv_subpass_t_; @@ -214,6 +218,11 @@ typedef struct qfv_render_s { struct qfv_resource_s *resources; struct qfv_resobj_s *images; struct qfv_resobj_s *image_views; + VkRenderPass *renderpass_res; + VkPipeline *pipelines; + + uint32_t num_renderpasses; + qfv_renderpass_t_ *renderpasses; } qfv_render_t; typedef struct qfv_renderctx_s { diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index cd4af8e80..2cf423430 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -40,6 +40,7 @@ #include "QF/cmem.h" #include "QF/hash.h" +#include "QF/va.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" @@ -85,7 +86,7 @@ run_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx) QFV_duCmdBeginLabel (device, cmd, sp->label.name, {VEC4_EXP (sp->label.color)}); - for (uint32_t i = 0; i < sp->pipline_count; i++) { + for (uint32_t i = 0; i < sp->pipeline_count; i++) { __auto_type pipeline = &sp->pipelines[i]; run_pipeline (pipeline, cmd, ctx); } @@ -167,17 +168,8 @@ typedef struct { uint32_t num_colorblend; uint32_t num_preserve; uint32_t num_pipelines; - uint32_t num_tasks; - uint32_t num_stages; } objcount_t; -static void -count_pl_stuff (qfv_pipelineinfo_t *pli, objcount_t *counts) -{ - counts->num_tasks += pli->num_tasks; - counts->num_stages += pli->num_graph_stages; -} - static void count_as_stuff (qfv_attachmentsetinfo_t *as, objcount_t *counts) { @@ -201,9 +193,6 @@ count_sp_stuff (qfv_subpassinfo_t *spi, objcount_t *counts) count_as_stuff (spi->attachments, counts); } counts->num_pipelines += spi->num_pipelines; - for (uint32_t i = 0; i < spi->num_pipelines; i++) { - count_pl_stuff (spi->pipelines, counts); - } } static void @@ -309,6 +298,396 @@ create_resources (vulkan_ctx_t *ctx, objcount_t *counts) QFV_CreateResource (ctx->device, render->resources); } +static uint32_t __attribute__((pure)) +find_subpass (qfv_dependencyinfo_t *d, uint32_t spind, + qfv_subpassinfo_t *subpasses) +{ + if (strcmp (d->name, "$external") == 0) { + return VK_SUBPASS_EXTERNAL; + } + for (uint32_t i = 0; i <= spind; i++) { + __auto_type s = &subpasses[i]; + if (strcmp (d->name, s->name) == 0) { + return i; + } + } + Sys_Error ("invalid dependency: [%d] %s", spind, d->name); +} + +static void +init_plCreate (VkGraphicsPipelineCreateInfo *plc, const qfv_pipelineinfo_t *pli) +{ + if (pli->num_graph_stages) { + plc->stageCount = pli->num_graph_stages; + } + if (pli->graph_stages) { + plc->pStages = pli->graph_stages; + } + if (pli->vertexInput) { + plc->pVertexInputState = pli->vertexInput; + } + if (pli->inputAssembly) { + plc->pInputAssemblyState = pli->inputAssembly; + } + if (pli->tessellation) { + plc->pTessellationState = pli->tessellation; + } + if (pli->viewport) { + plc->pViewportState = pli->viewport; + } + if (pli->rasterization) { + plc->pRasterizationState = pli->rasterization; + } + if (pli->multisample) { + plc->pMultisampleState = pli->multisample; + } + if (pli->depthStencil) { + plc->pDepthStencilState = pli->depthStencil; + } + if (pli->colorBlend) { + VkPipelineColorBlendStateCreateInfo *cb; + cb = (VkPipelineColorBlendStateCreateInfo *) plc->pColorBlendState; + *cb = *pli->colorBlend; + } + if (pli->dynamic) { + plc->pDynamicState = pli->dynamic; + } + if (pli->layout.name) { + //plc->layout = find_layout (&pli->layoyout); + } +} + +typedef struct { + VkRenderPassCreateInfo *rpCreate; + VkAttachmentDescription *attach; + VkClearValue *clear; + VkSubpassDescription *subpass; + VkSubpassDependency *depend; + VkAttachmentReference *attachref; + VkPipelineColorBlendAttachmentState *cbAttach; + uint32_t *preserve; + VkGraphicsPipelineCreateInfo *plCreate; + VkPipelineColorBlendStateCreateInfo *cbState; +} objptr_t; + +typedef struct { + objcount_t inds; + objptr_t ptr; + qfv_renderpassinfo_t *rpi; + VkRenderPassCreateInfo *rpc; + qfv_subpassinfo_t *spi; + VkSubpassDescription *spc; + qfv_pipelineinfo_t *pli; + VkGraphicsPipelineCreateInfo *plc; +} objstate_t; + +static uint32_t __attribute__((pure)) +find_attachment (qfv_reference_t *ref, objstate_t *s) +{ + for (uint32_t i = 0; i < s->rpi->num_attachments; i++) { + __auto_type a = &s->rpi->attachments[i]; + if (strcmp (ref->name, a->name) == 0) { + return i; + } + } + Sys_Error ("%s.%s:%d: invalid attachment: %s", + s->rpi->name, s->spi->name, ref->line, ref->name); +} + +static void +init_arCreate (const qfv_attachmentrefinfo_t *ari, objstate_t *s) +{ + __auto_type arc = &s->ptr.attachref[s->inds.num_attachmentrefs]; + qfv_reference_t ref = { + .name = ari->name, + .line = ari->line, + }; + + *arc = (VkAttachmentReference) { + .attachment = find_attachment (&ref, s), + .layout = ari->layout, + }; +} + +static void +init_cbCreate (const qfv_attachmentrefinfo_t *ari, objstate_t *s) +{ + __auto_type cbc = &s->ptr.cbAttach[s->inds.num_colorblend]; + + *cbc = ari->blend; +} + +static void +init_spCreate (uint32_t index, qfv_subpassinfo_t *sub, objstate_t *s) +{ + s->spi = &sub[index]; + s->plc = &s->ptr.plCreate[s->inds.num_pipelines]; + s->spc = &s->ptr.subpass[s->inds.num_subpasses]; + + *s->spc = (VkSubpassDescription) { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + }; + for (uint32_t i = 0; i < s->spi->num_dependencies; i++) { + __auto_type d = &s->spi->dependencies[i]; + __auto_type dep = &s->ptr.depend[s->inds.num_dependencies++]; + *dep = (VkSubpassDependency) { + .srcSubpass = find_subpass (d, index, s->rpi->subpasses), + .dstSubpass = index, + .srcStageMask = d->src.stage, + .dstStageMask = d->dst.stage, + .srcAccessMask = d->src.access, + .dstAccessMask = d->dst.access, + .dependencyFlags = d->flags, + }; + } + + for (uint32_t i = 0; i < s->spi->num_pipelines; i++) { + s->plc[i] = (VkGraphicsPipelineCreateInfo) { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pColorBlendState = &s->ptr.cbState[s->inds.num_pipelines], + .subpass = index, + }; + if (s->spi->base_pipeline) { + init_plCreate (&s->plc[i], s->spi->base_pipeline); + } + init_plCreate (&s->plc[i], &s->spi->pipelines[i]); + s->inds.num_pipelines++; + } + + __auto_type att = s->spi->attachments; + if (!att) { + return; + } + s->spc->inputAttachmentCount = att->num_input; + s->spc->pInputAttachments = &s->ptr.attachref[s->inds.num_attachmentrefs]; + for (uint32_t i = 0; i < att->num_input; i++) { + init_arCreate (&att->input[i], s); + s->inds.num_attachmentrefs++; + } + s->spc->colorAttachmentCount = att->num_color; + s->spc->pColorAttachments = &s->ptr.attachref[s->inds.num_attachmentrefs]; + for (uint32_t i = 0; i < att->num_color; i++) { + init_arCreate (&att->color[i], s); + s->inds.num_attachmentrefs++; + init_cbCreate (&att->color[i], s); + s->inds.num_colorblend++; + } + if (att->resolve) { + s->spc->pResolveAttachments + = &s->ptr.attachref[s->inds.num_attachmentrefs]; + for (uint32_t i = 0; i < att->num_color; i++) { + init_arCreate (&att->resolve[i], s); + s->inds.num_attachmentrefs++; + } + } + if (att->depth) { + s->spc->pDepthStencilAttachment + = &s->ptr.attachref[s->inds.num_attachmentrefs]; + init_arCreate (att->depth, s); + s->inds.num_attachmentrefs++; + } + s->spc->preserveAttachmentCount = att->num_preserve; + s->spc->pPreserveAttachments = &s->ptr.preserve[s->inds.num_preserve]; + for (uint32_t i = 0; i < att->num_preserve; i++) { + s->ptr.preserve[s->inds.num_preserve] + = find_attachment (&att->preserve[i], s); + s->inds.num_preserve++; + } +} + +static void +init_atCreate (uint32_t index, qfv_attachmentinfo_t *attachments, objstate_t *s) +{ + __auto_type ati = &attachments[index]; + __auto_type atc = &s->ptr.attach[s->inds.num_attachments]; + __auto_type cvc = &s->ptr.clear[s->inds.num_attachments]; + + *atc = (VkAttachmentDescription) { + .flags = ati->flags, + .format = ati->format, + .samples = ati->samples, + .loadOp = ati->loadOp, + .storeOp = ati->storeOp, + .stencilLoadOp = ati->stencilLoadOp, + .stencilStoreOp = ati->stencilStoreOp, + .initialLayout = ati->initialLayout, + .finalLayout = ati->finalLayout, + }; + *cvc = ati->clearValue; +} + +static void +init_rpCreate (uint32_t index, const qfv_renderinfo_t *rinfo, objstate_t *s) +{ + s->rpi = &rinfo->renderpasses[index]; + s->rpc = &s->ptr.rpCreate[s->inds.num_renderpasses]; + + __auto_type attachments = &s->ptr.attach[s->inds.num_attachments]; + __auto_type subpasses = &s->ptr.subpass[s->inds.num_subpasses]; + __auto_type dependencies = &s->ptr.depend[s->inds.num_dependencies]; + + for (uint32_t i = 0; i < s->rpi->num_attachments; i++) { + init_atCreate (i, s->rpi->attachments, s); + s->inds.num_attachments++; + } + + uint32_t num_dependencies = s->inds.num_dependencies; + for (uint32_t i = 0; i < s->rpi->num_subpasses; i++) { + init_spCreate (i, s->rpi->subpasses, s); + s->inds.num_subpasses++; + } + num_dependencies = s->inds.num_dependencies - num_dependencies; + + *s->rpc = (VkRenderPassCreateInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = s->rpi->num_attachments, + .pAttachments = attachments, + .subpassCount = s->rpi->num_subpasses, + .pSubpasses = subpasses, + .dependencyCount = num_dependencies, + .pDependencies = dependencies, + }; +} + +static void +create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) +{ + __auto_type rctx = ctx->render_context; + __auto_type rinfo = rctx->renderinfo; + + size_t size = 0; +#if 0 + size += counts->num_renderpasses * sizeof (VkRenderPass); + size += counts->num_pipelines * sizeof (VkPipeline); + __auto_type rp = (VkRenderPass *) malloc (size); + __auto_type pl = (VkPipeline *) &rp[counts->num_renderpasses]; +#endif + + size = 0; + size += counts->num_renderpasses * sizeof (VkRenderPassCreateInfo); + size += counts->num_attachments * sizeof (VkAttachmentDescription); + size += counts->num_attachments * sizeof (VkClearValue); + size += counts->num_subpasses * sizeof (VkSubpassDescription); + size += counts->num_dependencies * sizeof (VkSubpassDependency); + size += counts->num_attachmentrefs * sizeof (VkAttachmentReference); + size += counts->num_colorblend*sizeof (VkPipelineColorBlendAttachmentState); + size += counts->num_preserve * sizeof (uint32_t); + size += counts->num_pipelines * sizeof (VkGraphicsPipelineCreateInfo); + size += counts->num_pipelines *sizeof (VkPipelineColorBlendStateCreateInfo); + + objstate_t s = { + .ptr = { + .rpCreate = alloca (size), + .attach = (void *) &s.ptr.rpCreate [counts->num_renderpasses], + .clear = (void *) &s.ptr.attach [counts->num_attachments], + .subpass = (void *) &s.ptr.clear [counts->num_attachments], + .depend = (void *) &s.ptr.subpass [counts->num_subpasses], + .attachref = (void *) &s.ptr.depend [counts->num_dependencies], + .cbAttach = (void *) &s.ptr.attachref[counts->num_attachmentrefs], + .preserve = (void *) &s.ptr.cbAttach [counts->num_colorblend], + .plCreate = (void *) &s.ptr.preserve [counts->num_preserve], + .cbState = (void *) &s.ptr.plCreate [counts->num_pipelines], + }, + }; + for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { + init_rpCreate (i, rinfo, &s); + s.inds.num_renderpasses++; + } + if (s.inds.num_renderpasses != counts->num_renderpasses + || s.inds.num_attachments != counts->num_attachments + || s.inds.num_subpasses != counts->num_subpasses + || s.inds.num_dependencies != counts->num_dependencies + || s.inds.num_attachmentrefs != counts->num_attachmentrefs + || s.inds.num_colorblend != counts->num_colorblend + || s.inds.num_preserve != counts->num_preserve + || s.inds.num_pipelines != counts->num_pipelines) { + Sys_Error ("create_renderpasses: something was missed"); + } + +#if 0 + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + uint32_t plInd = 0; + for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { + dfunc->vkCreateRenderPass (device->dev, &s.ptr.rpCreate[i], 0, &rp[i]); + __auto_type rpi = &rinfo->renderpasses[i]; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_RENDER_PASS, rp[i], + va (ctx->va_ctx, "renderpass:%s", rpi->name)); + for (uint32_t j = 0; j < rpi->num_subpasses; j++) { + __auto_type spi = &rpi->subpasses[j]; + for (uint32_t k = 0; k < spi->num_pipelines; k++) { + s.ptr.plCreate[plInd++].renderPass = rp[i]; + } + } + } + dfunc->vkCreateGraphicsPipelines (device->dev, 0, 1, + s.ptr.plCreate, 0, pl); +#endif +} + +static void +init_pipeline (qfv_pipeline_t *pl, vulkan_ctx_t *ctx, qfv_pipelineinfo_t *ipl, + objcount_t *inds) +{ + pl->label.name = ipl->name; + pl->label.color = ipl->color; + pl->task_count = ipl->num_tasks; + pl->tasks = ipl->tasks; +} + +static void +init_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx, qfv_subpassinfo_t *isp, + qfv_pipeline_t *pl, objcount_t *inds) +{ + sp->label.name = isp->name; + sp->label.color = isp->color; + sp->pipeline_count = isp->num_pipelines; + sp->pipelines = &pl[inds->num_pipelines]; + for (uint32_t i = 0; i < isp->num_pipelines; i++) { + init_pipeline (&sp->pipelines[i], ctx, &isp->pipelines[i], inds); + inds->num_pipelines++; + } +} + +static void +init_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx, + qfv_renderpassinfo_t *irp, + qfv_subpass_t_ *sp, qfv_pipeline_t *pl, objcount_t *inds) +{ + rp->vulkan_ctx = ctx; + rp->label.name = irp->name; + rp->label.color = irp->color; + rp->subpass_count = irp->num_subpasses; + rp->subpasses = &sp[inds->num_subpasses]; + for (uint32_t i = 0; i < irp->num_subpasses; i++) { + init_subpass (&rp->subpasses[i], ctx, &irp->subpasses[i], pl, inds); + inds->num_subpasses++; + } +} + +static void +init_render (vulkan_ctx_t *ctx, objcount_t *counts) +{ + __auto_type rctx = ctx->render_context; + __auto_type rinfo = rctx->renderinfo; + __auto_type render = rctx->render; + size_t size = 0; + size += counts->num_renderpasses * sizeof (qfv_renderpass_t_); + size += counts->num_subpasses * sizeof (qfv_subpass_t_); + size += counts->num_pipelines * sizeof (qfv_pipeline_t); + + __auto_type rp = (qfv_renderpass_t_ *) calloc (1, size); + __auto_type sp = (qfv_subpass_t_ *) &rp[counts->num_renderpasses]; + __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; + objcount_t inds = {}; + for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { + init_renderpass (&rp[i], ctx, &rinfo->renderpasses[i], sp, pl, &inds); + inds.num_renderpasses++; + } + + render->renderpasses = rp; +} + void QFV_BuildRender (vulkan_ctx_t *ctx) { @@ -319,6 +698,8 @@ QFV_BuildRender (vulkan_ctx_t *ctx) objcount_t counts = {}; count_stuff (rctx->renderinfo, &counts); create_resources (ctx, &counts); + create_renderpasses (ctx, &counts); + init_render (ctx, &counts); } void diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 1ef3daee2..125bc031a 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -586,7 +586,6 @@ renderpasses = { @inherit = $attachment_base; format = $images.color.format; loadOp = clear; - finalLayout = depth_stencil_attachment_optimal; }; emission = { @inherit = $attachment_base; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index bfda002e5..d8af9ab03 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -489,7 +489,7 @@ vkstrdup (parsectx_t *context, const char *str) return dup; } -static parse_string_t parse_string_array = { 0 }; +static __attribute__((used)) parse_string_t parse_string_array = { 0 }; static int parse_string (const plfield_t *field, const plitem_t *item, diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 70bdcc9ff..48122bccd 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -440,11 +440,14 @@ .type = (QFString, QFDictionary); .string = { name = $name; + line = $item.line; layout = $auto; blend = "(VkPipelineColorBlendAttachmentState) { .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT }" }; .dictionary = { .parse = auto; + name = $name; + line = $item.line; }; layout = auto; blend = auto; @@ -471,12 +474,7 @@ value = depth; }; preserve = { - type = (array, { - parse_type = QFString; - type = "char *"; - parser = parse_string; - data = parse_string_array; - }); + type = (array, qfv_reference_t); size = num_preserve; values = preserve; }; @@ -589,6 +587,11 @@ }; qfv_renderpassinfo_s = { .name = qfv_renderpassinfo_t; + name = { + type = string; + string = name; + }; + color = auto; attachments = { type = (labeledarray, qfv_attachmentinfo_t, name); size = num_attachments; From a907f7814385cf95664039eb3ab0c51128f6cff2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 13:51:24 +0900 Subject: [PATCH 3434/3664] [vulkan] Create a function for symtab creation Most importantly, this cleans up creation of self-referencing symbol tables from property lists, but adds in C-defined symbols as well. While QFV_ParseRenderInfo is currently the only the function that uses it, it might be helpful in the future, especially as I clean up the other parse support code. --- libs/video/renderer/vulkan/vkparse.c | 150 ++++++++++++++++----------- libs/video/renderer/vulkan/vkparse.h | 5 + 2 files changed, 92 insertions(+), 63 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index d8af9ab03..70afe9f5b 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -2214,6 +2214,69 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) return set; } +exprtab_t * +QFV_CreateSymtab (plitem_t *dict, const char *properties, + const char **extra_items, exprsym_t *extra_syms, + exprctx_t *ectx) +{ + plitem_t *props = PL_ObjectForKey (dict, properties); + int num_keys = PL_D_NumKeys (props); + int num_extra = 0; + int num_syms = 0; + + for (const char **e = extra_items; *e; e++) { + if (PL_ObjectForKey (dict, *e)) { + num_extra++; + } + } + for (exprsym_t *sym = extra_syms; sym->name; sym++, num_syms++) { } + + int total_items = num_keys + num_extra; + int total_syms = total_items + num_syms; + size_t size = (sizeof (exprtab_t) + + (total_syms + 1) * sizeof (exprsym_t) + + total_items * sizeof (plitem_t *)); + exprtab_t *symtab = malloc (size); + *symtab = (exprtab_t) { + .symbols = (exprsym_t *) &symtab[1], + }; + plitem_t **items = (plitem_t **) &symtab->symbols[total_syms + 1]; + for (int i = 0; i < num_keys; i++) { + symtab->symbols[i] = (exprsym_t) { + .name = PL_KeyAtIndex (props, i), + .type = &cexpr_plitem, + .value = items + i, + }; + items[i] = PL_ObjectForKey (props, symtab->symbols[i].name); + } + for (int i = 0, j = 0; extra_items[i]; i++) { + plitem_t *val = PL_ObjectForKey (dict, extra_items[i]); + if (val) { + symtab->symbols[num_keys + j] = (exprsym_t) { + .name = extra_items[i], + .type = &cexpr_plitem, + .value = items + num_keys + i, + }; + items[num_keys + j] = val; + j++; + } + } + for (int i = 0; i < num_syms; i++) { + symtab->symbols[total_items + i] = extra_syms[i]; + } + symtab->symbols[total_syms] = (exprsym_t) { }; + + cexpr_init_symtab (symtab, ectx); + return symtab; +} + +void +QFV_DestroySymtab (exprtab_t *tab) +{ + Hash_DelTable (tab->tab); + free (tab); +} + qfv_renderinfo_t * QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) { @@ -2221,77 +2284,38 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) qfv_renderinfo_t *ri = cmemalloc (memsuper, sizeof (qfv_renderinfo_t)); *ri = (qfv_renderinfo_t) { .memsuper = memsuper }; - plitem_t *properties = PL_ObjectForKey (item, "properties"); - int num_keys = PL_D_NumKeys (properties); - scriptctx_t *sctx = ctx->script_context; plitem_t *messages = PL_NewArray (); - exprctx_t exprctx = { .symtab = &root_symtab }; + + exprctx_t exprctx = { + .symtab = &root_symtab, + .messages = messages, + .hashctx = &sctx->hashctx, + .memsuper = memsuper, + }; parsectx_t parsectx = { .ectx = &exprctx, .vctx = ctx, - .properties = properties, - .data = rctx + .data = rctx, }; - plitem_t *pl_items[num_keys + 3]; - exprsym_t var_syms[num_keys + 7 + 1]; - exprtab_t vars_tab = { var_syms, 0 }; - for (int i = 0; i < num_keys; i++) { - var_syms[i] = (exprsym_t) { - .name = PL_KeyAtIndex (properties, i), - .type = &cexpr_plitem, - .value = pl_items + i, - }; - pl_items[i] = PL_ObjectForKey (properties, var_syms[i].name); - } - pl_items[num_keys + 0] = PL_ObjectForKey (item, "images"); - pl_items[num_keys + 1] = PL_ObjectForKey (item, "views"); - pl_items[num_keys + 2] = PL_ObjectForKey (item, "renderpasses"); - - var_syms[num_keys + 0] = (exprsym_t) { - .name = "images", - .type = &cexpr_plitem, - .value = pl_items + num_keys + 0, - }, - var_syms[num_keys + 1] = (exprsym_t) { - .name = "views", - .type = &cexpr_plitem, - .value = pl_items + num_keys + 1, - }, - var_syms[num_keys + 2] = (exprsym_t) { - .name = "renderpasses", - .type = &cexpr_plitem, - .value = pl_items + num_keys + 2, - }, - var_syms[num_keys + 3] = (exprsym_t) { - .name = "output", - .type = &qfv_output_t_type, - .value = &sctx->output, + static const char *extra_items[] = { + "images", + "view", + "renderpasses", + 0 }; - var_syms[num_keys + 4] = (exprsym_t) { - .name = "frames", - .type = &vulkan_frameset_t_type, - .value = &ctx->frames, + exprsym_t var_syms[] = { + {"output", &qfv_output_t_type, &sctx->output}, + {"frames", &vulkan_frameset_t_type, &ctx->frames}, + {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, + {"physDevLimits", &VkPhysicalDeviceLimits_type, + &ctx->device->physDev->properties->limits }, + {} }; - var_syms[num_keys + 5] = (exprsym_t) { - .name = "msaaSamples", - .type = &VkSampleCountFlagBits_type, - .value = &ctx->msaaSamples, - }; - var_syms[num_keys + 6] = (exprsym_t) { - .name = "physDevLimits", - .type = &VkPhysicalDeviceLimits_type, - .value = &ctx->device->physDev->properties->limits, - }; - var_syms[num_keys + 7] = (exprsym_t) {}; - - exprctx.external_variables = &vars_tab; - exprctx.messages = messages; - exprctx.hashctx = &sctx->hashctx; - exprctx.memsuper = memsuper; - - cexpr_init_symtab (&vars_tab, &exprctx); + exprctx.external_variables = QFV_CreateSymtab (item, "properties", + extra_items, var_syms, + &exprctx); int ret; if (!(ret = parse_qfv_renderinfo_t (0, item, ri, messages, &parsectx))) { @@ -2299,7 +2323,7 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } } - Hash_DelTable (vars_tab.tab); + QFV_DestroySymtab (exprctx.external_variables); PL_Free (messages); if (!ret) { delete_memsuper (memsuper); diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index d92429332..85eb7a00d 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -77,6 +77,11 @@ int QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, plitem_t *properties); int QFV_ParseOutput (vulkan_ctx_t *ctx, qfv_output_t *output, plitem_t *plist, plitem_t *properties); +exprtab_t *QFV_CreateSymtab (plitem_t *dict, const char *properties, + const char **extra_items, exprsym_t *extra_syms, + exprctx_t *ectx); +void QFV_DestroySymtab (exprtab_t *tab); + struct qfv_renderctx_s; struct qfv_renderinfo_s *QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, From e07f25e10fd558cd2ef4b5ac798edbb04881aeca Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 15:48:04 +0900 Subject: [PATCH 3435/3664] [qfcc] Add failing test for super dealloc While working on vkgen, I found a dealloc that wasn't calling [super dealloc] but qfcc hadn't noticed it. --- tools/qfcc/test/Makemodule.am | 4 +++ tools/qfcc/test/dealloc-warn4.r | 51 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tools/qfcc/test/dealloc-warn4.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 0d4fa5c2a..ea2ba9f70 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -81,6 +81,7 @@ test_build_errors=\ tools/qfcc/test/dealloc-warn.r \ tools/qfcc/test/dealloc-warn2.r \ tools/qfcc/test/dealloc-warn3.r \ + tools/qfcc/test/dealloc-warn4.r \ tools/qfcc/test/double-demote-float.r \ tools/qfcc/test/double-demote-float-ainit.r \ tools/qfcc/test/double-demote-float-ginit.r \ @@ -277,6 +278,9 @@ tools/qfcc/test/dealloc-warn2.run$(EXEEXT): tools/qfcc/test/dealloc-warn2.r $(qf tools/qfcc/test/dealloc-warn3.run$(EXEEXT): tools/qfcc/test/dealloc-warn3.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< +tools/qfcc/test/dealloc-warn4.run$(EXEEXT): tools/qfcc/test/dealloc-warn4.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + tools/qfcc/test/double-demote-int.run$(EXEEXT): tools/qfcc/test/double-demote-int.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/dealloc-warn4.r b/tools/qfcc/test/dealloc-warn4.r new file mode 100644 index 000000000..9962e19ca --- /dev/null +++ b/tools/qfcc/test/dealloc-warn4.r @@ -0,0 +1,51 @@ +#pragma warn error +#pragma optimize on + +void str_free(string str) +{ +} + +@interface Object +{ + Class isa; +} +-(void)dealloc; +@end + +@interface derived : Object +{ + int free; + string foo; + id bar; +} +@end + +@implementation Object +-(void) dealloc +{ + // this is the root of the hierarchy, so no super to call, thus + // must not check for [super dealloc] +} +-(void) release +{ +} +@end + +@implementation derived +-(void) dealloc +{ + // as this is a derived class, failure to call [super dealloc] will + // result in a memory leak (yes, there could be special allocators + // involved, in which case something will be needed to inform the + // compiler) + str_free (foo); +} +@end + +void __obj_exec_class (struct obj_module *msg) = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; + +int main () +{ + return 1; // test fails if compile succeeds (with -Werror) +} From b103709bfd392fab33568815e8a558f142c72e0b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 20:09:21 +0900 Subject: [PATCH 3436/3664] [qfcc] Fix incorrect build error in dealloc-warn2 It was dying due to an undefined symbol rather than the warning. --- tools/qfcc/test/dealloc-warn2.r | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/test/dealloc-warn2.r b/tools/qfcc/test/dealloc-warn2.r index 921db1566..533913da5 100644 --- a/tools/qfcc/test/dealloc-warn2.r +++ b/tools/qfcc/test/dealloc-warn2.r @@ -1,5 +1,9 @@ #pragma warn error +void __obj_exec_class (struct obj_module *msg) = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; +id obj_msgSend (Super *class, SEL op, ...) = #0; + @interface Object { Class isa; @@ -37,9 +41,6 @@ } @end -void __obj_exec_class (struct obj_module *msg) = #0; -id obj_msgSend_super (Super *class, SEL op, ...) = #0; - int main () { return 1; // test fails if compile succeeds (with -Werror) From 461bb9f434e8ff5085f643bb2d67634a1ab998c3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 20:36:53 +0900 Subject: [PATCH 3437/3664] [vkgen] Make labeled arrays independent of struct order It turns out labeled arrays don't work if structs aren't declared in the right order (no idea what that is, though) as the struct might not have been processed when the labeled array field is initialized. Thus, do a pro-processing pass to set up any parse data prior to writing the tables. --- .../renderer/vulkan/vkgen/vkfieldcustom.r | 3 ++- libs/video/renderer/vulkan/vkgen/vkgen.r | 1 + libs/video/renderer/vulkan/vkgen/vkstruct.h | 5 +++++ libs/video/renderer/vulkan/vkgen/vkstruct.r | 21 +++++++++++++++---- libs/video/renderer/vulkan/vkgen/vktype.h | 2 ++ libs/video/renderer/vulkan/vkgen/vktype.r | 4 ++++ 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r index 2f11e0987..2473a91db 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldcustom.r @@ -19,12 +19,13 @@ pltype = str_hold (parseItemType ([desc getObjectAtIndex:1])); parser = str_hold ([[desc getObjectAtIndex:2] string]); - fields = [item getObjectForKey:"fields"]; + fields = [[item getObjectForKey:"fields"] retain]; return self; } -(void)dealloc { + [fields release]; str_free (pltype); str_free (parser); [super dealloc]; diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index c938bbc5e..2f69d871a 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -226,6 +226,7 @@ main(int argc, string *argv) arp_start (); [obj writeForward]; + [obj initParse:[parse getObjectForKey:[obj name]]]; arp_end (); } for (int i = [output_types count]; i-- > 0; ) { diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index 095c22629..f2c86db29 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -13,6 +13,11 @@ string outname; string label_field; int write_symtab; + int skip; + + Array *field_defs; + PLItem *field_dict; + PLItem *only; } -(void) queueFieldTypes; -(qfot_var_t *)findField:(string) fieldName; diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 0194aaeaa..ab37159ca 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -15,8 +15,12 @@ -(void) dealloc { + [field_dict release]; + [field_defs release]; + [only release]; str_free (outname); str_free (label_field); + [super dealloc]; } -(string) name @@ -365,21 +369,23 @@ write_table (Struct *self, PLItem *field_dict, Array *field_defs, } } --(void) writeTable +-(void) initParse:(PLItem *)parse { if ([parse string] == "skip") { + skip = 1; return; } - PLItem *field_dict = [parse getObjectForKey:[self name]]; + field_dict = [parse retain]; PLItem *new_name = [field_dict getObjectForKey:".name"]; if (new_name) { outname = str_hold ([new_name string]); } - Array *field_defs = [Array array]; - PLItem *only = [field_dict getObjectForKey:".only"]; + field_defs = [[Array array] retain]; + + only = [[field_dict getObjectForKey:".only"] retain]; if (only) { string field_name = [only string]; qfot_var_t *field = nil; @@ -429,6 +435,13 @@ write_table (Struct *self, PLItem *field_dict, Array *field_defs, [field_defs addObject: field_def]; } } +} + +-(void) writeTable +{ + if (skip) { + return; + } if ([field_dict getObjectForKey:".type"]) { PLItem *type = [field_dict getObjectForKey:".type"]; diff --git a/libs/video/renderer/vulkan/vkgen/vktype.h b/libs/video/renderer/vulkan/vkgen/vktype.h index 66cab0d24..ed3965639 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.h +++ b/libs/video/renderer/vulkan/vkgen/vktype.h @@ -6,6 +6,7 @@ @class FieldDef; @class Struct; +@class PLItem; @interface Type: Object { @@ -21,6 +22,7 @@ -(string) name; -(void) setAlias: (Type *) alias; -(void) addToQueue; +-(void) initParse:(PLItem *)parse; -(Type *) resolveType; +(Type *) findType: (qfot_type_t *) type; +(Type *) lookup: (string) name; diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index d7d2a9a95..935279a76 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -110,6 +110,10 @@ static string get_type_key (void *type, void *unused) } } +-(void) initParse:(PLItem *)parse +{ +} + -(Type *) resolveType { return self; From 694c3ad5f5a049f6267354a4c1dec71652c71c43 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 20:39:10 +0900 Subject: [PATCH 3438/3664] [qfcc] Ensure params and arguments have unique flow addresses This fixes the false-negative in the dealloc-warn4.r test (and thus what I found in vkgen), and should stave off a few other issues. --- tools/qfcc/include/def.h | 4 ++- tools/qfcc/source/def.c | 12 ++++++++ tools/qfcc/source/flow.c | 52 ++++++++++++++++++++++++++++++---- tools/qfcc/source/statements.c | 2 +- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 6892b5d8a..a00758bdf 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -97,6 +97,7 @@ typedef struct def_s { unsigned external:1; ///< externally declared def unsigned local:1; ///< function local def unsigned param:1; ///< function param def + unsigned argument:1; ///< function argument def unsigned system:1; ///< system def unsigned nosave:1; ///< don't set DEF_SAVEGLOBAL @@ -117,7 +118,8 @@ typedef enum storage_class_e { sc_extern, ///< def is externally allocated sc_static, ///< def is private to the current unit sc_param, ///< def is an incoming function parameter - sc_local ///< def is local to the current function + sc_local, ///< def is local to the current function + sc_argument, ///< def is a function argument } storage_class_t; /** Create a new def. diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index f87803f2c..b745f2da3 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -76,30 +76,42 @@ set_storage_bits (def_t *def, storage_class_t storage) def->external = 0; def->local = 0; def->param = 0; + def->argument = 0; break; case sc_extern: def->global = 1; def->external = 1; def->local = 0; def->param = 0; + def->argument = 0; break; case sc_static: def->external = 0; def->global = 0; def->local = 0; def->param = 0; + def->argument = 0; break; case sc_local: def->external = 0; def->global = 0; def->local = 1; def->param = 0; + def->argument = 0; break; case sc_param: def->external = 0; def->global = 0; def->local = 1; def->param = 1; + def->argument = 0; + break; + case sc_argument: + def->external = 0; + def->global = 0; + def->local = 1; + def->param = 0; + def->argument = 1; break; } def->initialized = 0; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 4e86fc0c3..43768096a 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -227,7 +227,8 @@ flowvar_is_global (flowvar_t *var) * * For the flowvar to refer to a function parameter, the flowvar's operand * must be a def operand (but the def itself may be an alias of the real def) - * and the rel def must have both its def_t::local and def_t::param flags set. + * and the real def must have both its def_t::local and def_t::param flags + * set. * * Temp vars are are not represented by op_def, so no mistake can be made. */ @@ -248,16 +249,43 @@ flowvar_is_param (flowvar_t *var) return 1; } +/** Check if the flowvar refers to a function argument. + * + * For the flowvar to refer to a function argument, the flowvar's operand + * must be a def operand (but the def itself may be an alias of the real def) + * and the real def must have both its def_t::local and def_t::argument flags + * set. + * + * Temp vars are are not represented by op_def, so no mistake can be made. + */ +static int +flowvar_is_argument (flowvar_t *var) +{ + def_t *def; + + if (var->op->op_type != op_def) + return 0; + def = var->op->def; + if (def->alias) + def = def->alias; + if (!def->local) + return 0; + if (!def->argument) + return 0; + return 1; +} + /** Check if the flowvar refers to a local variable. * - * As this is simply "neither global nor pamam", all other flowvars are - * considered local, in particular actual non-staic function scope variables - * and temp vars. + * As this is simply "neither global nor pamam nor argument", all other + * flowvars are considered local, in particular actual non-staic function + * scope variables and temp vars. */ static int flowvar_is_local (flowvar_t *var) { - return !(flowvar_is_global (var) || flowvar_is_param (var)); + return !(flowvar_is_global (var) || flowvar_is_param (var) + || flowvar_is_argument (var)); } ///@} @@ -443,6 +471,13 @@ add_operand (function_t *func, operand_t *op) var->flowaddr = get_pseudo_address (func, 1); } else if (op->op_type == op_temp) { var->flowaddr = get_temp_address (func, op); + } else if (flowvar_is_param (var)) { + var->flowaddr = func->num_statements + def_offset (var->op->def); + var->flowaddr += func->locals->space->size; + } else if (flowvar_is_argument (var)) { + var->flowaddr = func->num_statements + def_offset (var->op->def); + var->flowaddr += func->locals->space->size; + var->flowaddr += func->parameters->space->size; } else if (flowvar_is_local (var)) { var->flowaddr = func->num_statements + def_offset (var->op->def); } @@ -609,7 +644,12 @@ flow_build_vars (function_t *func) // set up pseudo address space for temp vars so accessing tmp vars // though aliases analyses correctly - func->pseudo_addr = func->num_statements + func->locals->space->size; + func->pseudo_addr = func->num_statements; + func->pseudo_addr += func->locals->space->size; + func->pseudo_addr += func->parameters->space->size; + if (func->arguments) { + func->pseudo_addr += func->arguments->size; + } func->num_vars = 0; // incremented by add_operand // first, add .return and .param_[0-7] as they are always needed diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 3da2e12a5..a3b0a64fb 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1097,7 +1097,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) expr_t *a = args[i]; const char *arg_name = va (0, ".arg%d", arg_num++); def_t *def = new_def (arg_name, 0, current_func->arguments, - sc_local); + sc_argument); type_t *arg_type = get_type (a); int size = type_size (arg_type); int alignment = arg_type->alignment; From 44f058869f684789029a4244da429e5cb1b32384 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 20:53:02 +0900 Subject: [PATCH 3439/3664] [gamecode] Fix a doxygen warning --- include/QF/progs.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index adae471f9..8e3d07e69 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1131,7 +1131,6 @@ void PR_Undefined (progs_t *pr, const char *type, const char *name) __attribute_ /** \internal \param e pointer to the entity \param o field offset into entity data space - \param t typename prefix (see pr_type_u) \return lvalue of the appropriate type \hideinitializer From b10c8dc1a14c443647350c96c97c5cd2968f392c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 20:54:11 +0900 Subject: [PATCH 3440/3664] [vulkan] Parse in descriptor set layouts For now, just their create info is parsed, but they will be created on demand. Most importantly, they are named for ease of use in pipeline layouts. --- include/QF/Vulkan/render.h | 10 + libs/video/renderer/vulkan/rp_main_def.plist | 184 +++++++++++++++++++ libs/video/renderer/vulkan/vkparse.plist | 19 +- 3 files changed, 209 insertions(+), 4 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 86a33fa8a..6b057d210 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -24,6 +24,14 @@ typedef struct qfv_reference_s { int line; } qfv_reference_t; +typedef struct qfv_descriptorsetinfo_s { + const char *name; + VkDescriptorSetLayoutCreateFlags flags; + uint32_t num_bindings; + VkDescriptorSetLayoutBinding *bindings; + VkDescriptorSetLayout setLayout; +} qfv_descriptorsetinfo_t; + typedef struct qfv_imageinfo_s { const char *name; VkImageCreateFlags flags; @@ -157,6 +165,8 @@ typedef struct qfv_renderinfo_s { uint32_t num_renderpasses; qfv_renderpassinfo_t *renderpasses; qfv_output_t output; + uint32_t num_descriptorsets; + qfv_descriptorsetinfo_t *descriptorsets; } qfv_renderinfo_t; typedef struct qfv_label_s { diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 125bc031a..4205b7c8a 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -495,6 +495,190 @@ properties = { }; } }; +descriptorSetLayouts = { + matrix_set = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex|geometry; + }, + ); + }; + quad_data_set = { + bindings = ( + { + // glyph texture data + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + // glyph geometry data (offset and uv) + binding = 1; + descriptorType = uniform_texel_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; + texture_set = { + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment|vertex; + }, + ); + }; + oit_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 1; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = storage_image; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + entity_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; + bone_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; + sprite_set = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + binding = 1; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + lighting_attach = { + bindings = ( + { + binding = 0; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 1; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 3; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 4; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + lighting_lights = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + lighting_shadow = { + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 32; + stageFlags = fragment; + }, + ); + }; + compose_attach = { + bindings = ( + { + binding = 0; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + particle_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 1; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 2; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + ); + }; +}; images = { depth = { @inherit = $image_base; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 48122bccd..73f9db74c 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -34,6 +34,7 @@ qfv_subpass_t, qfv_output_t, + qfv_descriptorsetinfo_t, qfv_imageinfo_t, qfv_imageviewinfo_t, qfv_dependencyinfo_t, @@ -587,10 +588,6 @@ }; qfv_renderpassinfo_s = { .name = qfv_renderpassinfo_t; - name = { - type = string; - string = name; - }; color = auto; attachments = { type = (labeledarray, qfv_attachmentinfo_t, name); @@ -604,6 +601,15 @@ values = subpasses; }; }; + qfv_descriptorsetinfo_s = { + .name = qfv_descriptorsetinfo_t; + flags = auto; + bindings = { + type = (array, VkDescriptorSetLayoutBinding); + size = num_bindings; + values = bindings; + }; + }; qfv_renderinfo_s = { .name = qfv_renderinfo_t; properties = ignore; @@ -623,6 +629,11 @@ size = num_renderpasses; values = renderpasses; }; + descriptorSetLayouts = { + type = (labeledarray, qfv_descriptorsetinfo_t, name); + size = num_descriptorsets; + values = descriptorsets; + }; }; }; } From acf828baa3937735b757ecd4c64d9b5c9b1d2b99 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Feb 2023 02:53:03 +0900 Subject: [PATCH 3441/3664] [vulkan] Allow null extra items and symbols Don't want to have to pass empty lists. --- libs/video/renderer/vulkan/vkparse.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 70afe9f5b..cf430382d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -2224,12 +2224,16 @@ QFV_CreateSymtab (plitem_t *dict, const char *properties, int num_extra = 0; int num_syms = 0; - for (const char **e = extra_items; *e; e++) { - if (PL_ObjectForKey (dict, *e)) { - num_extra++; + if (extra_items) { + for (const char **e = extra_items; *e; e++) { + if (PL_ObjectForKey (dict, *e)) { + num_extra++; + } } } - for (exprsym_t *sym = extra_syms; sym->name; sym++, num_syms++) { } + if (extra_syms) { + for (exprsym_t *sym = extra_syms; sym->name; sym++, num_syms++) { } + } int total_items = num_keys + num_extra; int total_syms = total_items + num_syms; @@ -2249,7 +2253,7 @@ QFV_CreateSymtab (plitem_t *dict, const char *properties, }; items[i] = PL_ObjectForKey (props, symtab->symbols[i].name); } - for (int i = 0, j = 0; extra_items[i]; i++) { + for (int i = 0, j = 0; num_extra && extra_items[i]; i++) { plitem_t *val = PL_ObjectForKey (dict, extra_items[i]); if (val) { symtab->symbols[num_keys + j] = (exprsym_t) { From 918237507e5925d54e9c5b535881f3b02f04ab8d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Feb 2023 02:54:51 +0900 Subject: [PATCH 3442/3664] [vulkan] Support parsing pipeline layout info This is for the new system. --- libs/video/renderer/vulkan/vkparse.c | 36 ++++++++++++++++++++++++ libs/video/renderer/vulkan/vkparse.h | 4 +++ libs/video/renderer/vulkan/vkparse.plist | 19 ++++++++++--- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index cf430382d..5ac85421c 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -2336,3 +2336,39 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) return ri; } + +int +QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, memsuper_t *memsuper, + exprtab_t *symtab, const char *ref, + qfv_layoutinfo_t *layout) +{ + *layout = (qfv_layoutinfo_t) {}; + + scriptctx_t *sctx = ctx->script_context; + plitem_t *messages = PL_NewArray (); + + exprctx_t exprctx = { + .symtab = &root_symtab, + .messages = messages, + .hashctx = &sctx->hashctx, + .memsuper = memsuper, + .external_variables = symtab, + }; + parsectx_t parsectx = { + .ectx = &exprctx, + .vctx = ctx, + }; + + plitem_t *item = PL_NewString (ref); + int ret; + if (!(ret = parse_qfv_layoutinfo_t (0, item, layout, messages, + &parsectx))) { + for (int i = 0; i < PL_A_NumObjects (messages); i++) { + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + } + } + PL_Free (messages); + PL_Free (item); + + return ret; +} diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 85eb7a00d..95b669598 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -86,4 +86,8 @@ struct qfv_renderctx_s; struct qfv_renderinfo_s *QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, struct qfv_renderctx_s *rctx); +struct memsuper_s; +int QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, struct memsuper_s *memsuper, + exprtab_t *symtab, const char *ref, + qfv_layoutinfo_t *layout); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 73f9db74c..346305bf1 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -42,6 +42,7 @@ qfv_attachmentrefinfo_t, qfv_attachmentsetinfo_t, qfv_taskinfo_t, + qfv_layoutinfo_t, qfv_pipelineinfo_t, qfv_subpassinfo_t, qfv_framebufferinfo_t, @@ -480,6 +481,19 @@ values = preserve; }; }; + qfv_layoutinfo_s = { + .name = qfv_layoutinfo_t; + descriptorSets = { + type = (array, qfv_reference_t); + size = num_sets; + values = sets; + }; + pushConstantRanges = { + type = (array, VkPushConstantRange); + size = num_ranges; + values = ranges; + }; + }; qfv_pipelineinfo_s = { .name = qfv_pipelineinfo_t; color = auto; @@ -535,10 +549,7 @@ type = (single, VkPipelineDynamicStateCreateInfo); value = dynamic; }; - layout = { - type = (single, qfv_reference_t); - value = layout; - }; + layout = auto; }; qfv_subpassinfo_s = { .name = qfv_subpassinfo_t; From 0dccce6c519d1f36bd974c967fc49e10f03c8b5f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Feb 2023 03:00:14 +0900 Subject: [PATCH 3443/3664] [vulkan] Create render passes and pipelines There are many issues (in particular, shutdown doesn't clean up properly), but creation passes validation. --- include/QF/Vulkan/render.h | 10 ++ libs/video/renderer/vulkan/render.c | 134 ++++++++++++++----- libs/video/renderer/vulkan/rp_main_def.plist | 23 ++-- 3 files changed, 127 insertions(+), 40 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 6b057d210..efb468811 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -32,6 +32,15 @@ typedef struct qfv_descriptorsetinfo_s { VkDescriptorSetLayout setLayout; } qfv_descriptorsetinfo_t; +typedef struct qfv_layoutinfo_s { + const char *name; + uint32_t num_sets; + qfv_reference_t *sets; + uint32_t num_ranges; + VkPushConstantRange *ranges; + VkPipelineLayout layout; +} qfv_layoutinfo_t; + typedef struct qfv_imageinfo_s { const char *name; VkImageCreateFlags flags; @@ -158,6 +167,7 @@ typedef struct qfv_renderpassinfo_s { typedef struct qfv_renderinfo_s { struct memsuper_s *memsuper; + struct plitem_s *plitem; uint32_t num_images; qfv_imageinfo_t *images; uint32_t num_views; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 2cf423430..dd3a3f505 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -154,11 +154,15 @@ QFV_LoadRenderInfo (vulkan_ctx_t *ctx) __auto_type output = get_output (ctx, item); Vulkan_Script_SetOutput (ctx, &output); rctx->renderinfo = QFV_ParseRenderInfo (ctx, item, rctx); + if (rctx->renderinfo) { + rctx->renderinfo->plitem = item; + } } typedef struct { uint32_t num_images; uint32_t num_views; + uint32_t num_layouts; uint32_t num_renderpasses; uint32_t num_attachments; @@ -298,6 +302,34 @@ create_resources (vulkan_ctx_t *ctx, objcount_t *counts) QFV_CreateResource (ctx->device, render->resources); } +typedef struct { + VkRenderPassCreateInfo *rpCreate; + VkAttachmentDescription *attach; + VkClearValue *clear; + VkSubpassDescription *subpass; + VkSubpassDependency *depend; + VkAttachmentReference *attachref; + VkPipelineColorBlendAttachmentState *cbAttach; + uint32_t *preserve; + VkGraphicsPipelineCreateInfo *plCreate; + VkPipelineColorBlendStateCreateInfo *cbState; + qfv_layoutinfo_t *layouts; +} objptr_t; + +typedef struct { + objcount_t inds; + objptr_t ptr; + vulkan_ctx_t *ctx; + qfv_renderinfo_t *rinfo; + exprtab_t *symtab; + qfv_renderpassinfo_t *rpi; + VkRenderPassCreateInfo *rpc; + qfv_subpassinfo_t *spi; + VkSubpassDescription *spc; + qfv_pipelineinfo_t *pli; + VkGraphicsPipelineCreateInfo *plc; +} objstate_t; + static uint32_t __attribute__((pure)) find_subpass (qfv_dependencyinfo_t *d, uint32_t spind, qfv_subpassinfo_t *subpasses) @@ -314,8 +346,66 @@ find_subpass (qfv_dependencyinfo_t *d, uint32_t spind, Sys_Error ("invalid dependency: [%d] %s", spind, d->name); } +static VkDescriptorSetLayout +find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) +{ + for (uint32_t i = 0; i < s->rinfo->num_descriptorsets; i++) { + __auto_type ds = &s->rinfo->descriptorsets[i]; + if (strcmp (ds->name, ref->name) == 0) { + if (!ds->setLayout) { + VkDescriptorSetLayoutCreateInfo cInfo = { + .sType=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .flags = ds->flags, + .bindingCount = ds->num_bindings, + .pBindings = ds->bindings, + }; + qfv_device_t *device = s->ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, + &ds->setLayout); + } + return ds->setLayout; + } + } + Sys_Error ("%s.%s:%d: invalid descriptor set layout: %s", + s->rpi->name, s->spi->name, ref->line, ref->name); +} + +static VkPipelineLayout +find_layout (const qfv_reference_t *ref, objstate_t *s) +{ + for (uint32_t i = 0; i < s->inds.num_layouts; i++) { + if (strcmp (s->ptr.layouts[i].name, ref->name) == 0) { + return s->ptr.layouts[i].layout; + } + } + if (!QFV_ParseLayoutInfo (s->ctx, s->rinfo->memsuper, s->symtab, ref->name, + &s->ptr.layouts[s->inds.num_layouts])) { + Sys_Error ("%s.%s:%d: invalid layout: %s", + s->rpi->name, s->spi->name, ref->line, ref->name); + } + __auto_type li = &s->ptr.layouts[s->inds.num_layouts++]; + li->name = ref->name; + VkDescriptorSetLayout sets[li->num_sets]; + for (uint32_t i = 0; i < li->num_sets; i++) { + sets[i] = find_descriptorSet (&li->sets[i], s); + } + VkPipelineLayoutCreateInfo cInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = li->num_sets, + .pSetLayouts = sets, + .pushConstantRangeCount = li->num_ranges, + .pPushConstantRanges = li->ranges, + }; + qfv_device_t *device = s->ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &li->layout); + return li->layout; +} + static void -init_plCreate (VkGraphicsPipelineCreateInfo *plc, const qfv_pipelineinfo_t *pli) +init_plCreate (VkGraphicsPipelineCreateInfo *plc, const qfv_pipelineinfo_t *pli, + objstate_t *s) { if (pli->num_graph_stages) { plc->stageCount = pli->num_graph_stages; @@ -353,34 +443,10 @@ init_plCreate (VkGraphicsPipelineCreateInfo *plc, const qfv_pipelineinfo_t *pli) plc->pDynamicState = pli->dynamic; } if (pli->layout.name) { - //plc->layout = find_layout (&pli->layoyout); + plc->layout = find_layout (&pli->layout, s); } } -typedef struct { - VkRenderPassCreateInfo *rpCreate; - VkAttachmentDescription *attach; - VkClearValue *clear; - VkSubpassDescription *subpass; - VkSubpassDependency *depend; - VkAttachmentReference *attachref; - VkPipelineColorBlendAttachmentState *cbAttach; - uint32_t *preserve; - VkGraphicsPipelineCreateInfo *plCreate; - VkPipelineColorBlendStateCreateInfo *cbState; -} objptr_t; - -typedef struct { - objcount_t inds; - objptr_t ptr; - qfv_renderpassinfo_t *rpi; - VkRenderPassCreateInfo *rpc; - qfv_subpassinfo_t *spi; - VkSubpassDescription *spc; - qfv_pipelineinfo_t *pli; - VkGraphicsPipelineCreateInfo *plc; -} objstate_t; - static uint32_t __attribute__((pure)) find_attachment (qfv_reference_t *ref, objstate_t *s) { @@ -448,9 +514,9 @@ init_spCreate (uint32_t index, qfv_subpassinfo_t *sub, objstate_t *s) .subpass = index, }; if (s->spi->base_pipeline) { - init_plCreate (&s->plc[i], s->spi->base_pipeline); + init_plCreate (&s->plc[i], s->spi->base_pipeline, s); } - init_plCreate (&s->plc[i], &s->spi->pipelines[i]); + init_plCreate (&s->plc[i], &s->spi->pipelines[i], s); s->inds.num_pipelines++; } @@ -556,12 +622,10 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) __auto_type rinfo = rctx->renderinfo; size_t size = 0; -#if 0 size += counts->num_renderpasses * sizeof (VkRenderPass); size += counts->num_pipelines * sizeof (VkPipeline); __auto_type rp = (VkRenderPass *) malloc (size); __auto_type pl = (VkPipeline *) &rp[counts->num_renderpasses]; -#endif size = 0; size += counts->num_renderpasses * sizeof (VkRenderPassCreateInfo); @@ -574,7 +638,11 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) size += counts->num_preserve * sizeof (uint32_t); size += counts->num_pipelines * sizeof (VkGraphicsPipelineCreateInfo); size += counts->num_pipelines *sizeof (VkPipelineColorBlendStateCreateInfo); + size += counts->num_pipelines *sizeof (qfv_layoutinfo_t); + exprctx_t ectx = { + .hashctx = &ctx->script_context->hashctx, + }; objstate_t s = { .ptr = { .rpCreate = alloca (size), @@ -587,7 +655,11 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) .preserve = (void *) &s.ptr.cbAttach [counts->num_colorblend], .plCreate = (void *) &s.ptr.preserve [counts->num_preserve], .cbState = (void *) &s.ptr.plCreate [counts->num_pipelines], + .layouts = (void *) &s.ptr.cbState [counts->num_pipelines], }, + .ctx = ctx, + .rinfo = rinfo, + .symtab = QFV_CreateSymtab (rinfo->plitem, "properties", 0, 0, &ectx), }; for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { init_rpCreate (i, rinfo, &s); @@ -604,7 +676,6 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) Sys_Error ("create_renderpasses: something was missed"); } -#if 0 qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; uint32_t plInd = 0; @@ -622,7 +693,6 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) } dfunc->vkCreateGraphicsPipelines (device->dev, 0, 1, s.ptr.plCreate, 0, pl); -#endif } static void diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 4205b7c8a..59e5d71d5 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -240,7 +240,7 @@ properties = { primitiveRestartEnable = true; }; layout = { - setLayouts = (matrix_set, entity_set, oit_set, texture_set, texture_set); + descriptorSets = (matrix_set, entity_set, oit_set, texture_set, texture_set); pushConstantRanges = ( { stageFlags = fragment; @@ -287,7 +287,7 @@ properties = { primitiveRestartEnable = false; }; layout = { - setLayouts = (matrix_set, texture_set, texture_set); + descriptorSets = (matrix_set, texture_set, texture_set); pushConstantRanges = ( { stageFlags = vertex; @@ -358,7 +358,7 @@ properties = { primitiveRestartEnable = false; }; layout = { - setLayouts = (matrix_set, texture_set, bone_set); + descriptorSets = (matrix_set, texture_set, bone_set); pushConstantRanges = ( { stageFlags = vertex; @@ -406,7 +406,7 @@ properties = { primitiveRestartEnable = false; }; layout = { - setLayouts = (matrix_set, sprite_set); + descriptorSets = (matrix_set, sprite_set); pushConstantRanges = ( { stageFlags = vertex; @@ -457,7 +457,7 @@ properties = { primitiveRestartEnable = false; }; layout = { - setLayouts = (matrix_set, texture_set, oit_set); + descriptorSets = (matrix_set, texture_set, oit_set); pushConstantRanges = ( { stageFlags = vertex; @@ -484,6 +484,10 @@ properties = { module = $builtin/lighting.frag; }; }; + layout = { + descriptorSets = (lighting_attach, lighting_lights, + lighting_shadow); + }; }; compose = { shader = { @@ -493,6 +497,9 @@ properties = { module = $builtin/compose.frag; }; }; + layout = { + descriptorSets = (compose_attach, oit_set); + }; } }; descriptorSetLayouts = { @@ -837,7 +844,7 @@ renderpasses = { ); attributes = ( "$brush.vertexInput.attributes[0]", - "$brush.vertexInput.attributes[1]", + "$brush.vertexInput.attributes[2]", ); }; inputAssembly = $brush.inputAssembly; @@ -1103,7 +1110,7 @@ renderpasses = { $fstriangle.shader.vertex, $lighting.shader.fragment, ); - layout = lighting.layout; + layout = $lighting.layout; }; }; }; @@ -1134,7 +1141,7 @@ renderpasses = { $fstriangle.shader.vertex, $compose.shader.fragment, ); - layout = compose.layout; + layout = $compose.layout; }; }; }; From 3700321c5d65bc22892b96ae4a0a044a20564e29 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Feb 2023 14:15:28 +0900 Subject: [PATCH 3444/3664] [vulkan] Clean up the render objects on shutdown Not only does this quieten the validation layers, it ensures that all the object handles are named and where they need to be. Also fixes only one pipeline being created instead of the 15 or so. --- include/QF/Vulkan/render.h | 4 +- libs/video/renderer/vulkan/render.c | 263 +++++++++++++++++----------- 2 files changed, 166 insertions(+), 101 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index efb468811..1326c1431 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -177,6 +177,8 @@ typedef struct qfv_renderinfo_s { qfv_output_t output; uint32_t num_descriptorsets; qfv_descriptorsetinfo_t *descriptorsets; + uint32_t num_layouts; + qfv_layoutinfo_t *layouts; } qfv_renderinfo_t; typedef struct qfv_label_s { @@ -238,8 +240,6 @@ typedef struct qfv_render_s { struct qfv_resource_s *resources; struct qfv_resobj_s *images; struct qfv_resobj_s *image_views; - VkRenderPass *renderpass_res; - VkPipeline *pipelines; uint32_t num_renderpasses; qfv_renderpass_t_ *renderpasses; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index dd3a3f505..a54e0e95b 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -311,9 +311,13 @@ typedef struct { VkAttachmentReference *attachref; VkPipelineColorBlendAttachmentState *cbAttach; uint32_t *preserve; + const char **plName; VkGraphicsPipelineCreateInfo *plCreate; VkPipelineColorBlendStateCreateInfo *cbState; qfv_layoutinfo_t *layouts; + + VkPipeline *pl; + VkRenderPass *rp; } objptr_t; typedef struct { @@ -363,6 +367,11 @@ find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, &ds->setLayout); + QFV_duSetObjectName (device, + VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, + ds->setLayout, + va (s->ctx->va_ctx, "descriptorSet:%s", + ds->name)); } return ds->setLayout; } @@ -400,6 +409,8 @@ find_layout (const qfv_reference_t *ref, objstate_t *s) qfv_device_t *device = s->ctx->device; qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &li->layout); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, li->layout, + va (s->ctx->va_ctx, "layout:%s", li->name)); return li->layout; } @@ -489,6 +500,8 @@ init_spCreate (uint32_t index, qfv_subpassinfo_t *sub, objstate_t *s) s->spi = &sub[index]; s->plc = &s->ptr.plCreate[s->inds.num_pipelines]; s->spc = &s->ptr.subpass[s->inds.num_subpasses]; + __auto_type pln = &s->ptr.plName[s->inds.num_pipelines]; + __auto_type cbs = &s->ptr.cbState[s->inds.num_pipelines]; *s->spc = (VkSubpassDescription) { .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, @@ -510,13 +523,14 @@ init_spCreate (uint32_t index, qfv_subpassinfo_t *sub, objstate_t *s) for (uint32_t i = 0; i < s->spi->num_pipelines; i++) { s->plc[i] = (VkGraphicsPipelineCreateInfo) { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pColorBlendState = &s->ptr.cbState[s->inds.num_pipelines], + .pColorBlendState = &cbs[i], .subpass = index, }; if (s->spi->base_pipeline) { init_plCreate (&s->plc[i], s->spi->base_pipeline, s); } init_plCreate (&s->plc[i], &s->spi->pipelines[i], s); + pln[i] = s->spi->name; s->inds.num_pipelines++; } @@ -524,6 +538,10 @@ init_spCreate (uint32_t index, qfv_subpassinfo_t *sub, objstate_t *s) if (!att) { return; } + for (uint32_t i = 0; i < s->spi->num_pipelines; i++) { + cbs[i].attachmentCount = att->num_color; + cbs[i].pAttachments = &s->ptr.cbAttach[s->inds.num_colorblend]; + } s->spc->inputAttachmentCount = att->num_input; s->spc->pInputAttachments = &s->ptr.attachref[s->inds.num_attachmentrefs]; for (uint32_t i = 0; i < att->num_input; i++) { @@ -615,47 +633,123 @@ init_rpCreate (uint32_t index, const qfv_renderinfo_t *rinfo, objstate_t *s) }; } +static void +init_pipeline (qfv_pipeline_t *pl, vulkan_ctx_t *ctx, qfv_pipelineinfo_t *ipl, + objstate_t *s) +{ + *pl = (qfv_pipeline_t) { + .label = { + .name = ipl->name, + .color = ipl->color, + }, + .bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .pipeline = s->ptr.pl[s->inds.num_pipelines], + .layout = find_layout (&ipl->layout, s), + .task_count = ipl->num_tasks, + .tasks = ipl->tasks, + }; +} + +static void +init_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx, qfv_subpassinfo_t *isp, + qfv_pipeline_t *pl, objstate_t *s) +{ + sp->label.name = isp->name; + sp->label.color = isp->color; + sp->pipeline_count = isp->num_pipelines; + sp->pipelines = &pl[s->inds.num_pipelines]; + for (uint32_t i = 0; i < isp->num_pipelines; i++) { + init_pipeline (&sp->pipelines[i], ctx, &isp->pipelines[i], s); + s->inds.num_pipelines++; + } +} + +static void +init_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx, + qfv_renderpassinfo_t *irp, + qfv_subpass_t_ *sp, qfv_pipeline_t *pl, objstate_t *s) +{ + rp->vulkan_ctx = ctx; + rp->label.name = irp->name; + rp->label.color = irp->color; + rp->subpass_count = irp->num_subpasses; + rp->subpasses = &sp[s->inds.num_subpasses]; + rp->beginInfo = (VkRenderPassBeginInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = s->ptr.rp[s->inds.num_renderpasses], + }; + for (uint32_t i = 0; i < irp->num_subpasses; i++) { + init_subpass (&rp->subpasses[i], ctx, &irp->subpasses[i], pl, s); + s->inds.num_subpasses++; + } +} + +static void +init_render (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) +{ + __auto_type rctx = ctx->render_context; + __auto_type rinfo = rctx->renderinfo; + __auto_type render = rctx->render; + size_t size = 0; + size += counts->num_renderpasses * sizeof (qfv_renderpass_t_); + size += counts->num_subpasses * sizeof (qfv_subpass_t_); + size += counts->num_pipelines * sizeof (qfv_pipeline_t); + + __auto_type rp = (qfv_renderpass_t_ *) calloc (1, size); + __auto_type sp = (qfv_subpass_t_ *) &rp[counts->num_renderpasses]; + __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; + uint32_t num_layouts = s.inds.num_layouts; + s.inds = (objcount_t) {}; + s.inds.num_layouts = num_layouts; + for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { + init_renderpass (&rp[i], ctx, &rinfo->renderpasses[i], sp, pl, &s); + s.inds.num_renderpasses++; + } + + render->num_renderpasses = rinfo->num_renderpasses; + render->renderpasses = rp; +} + static void create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) { __auto_type rctx = ctx->render_context; __auto_type rinfo = rctx->renderinfo; - size_t size = 0; - size += counts->num_renderpasses * sizeof (VkRenderPass); - size += counts->num_pipelines * sizeof (VkPipeline); - __auto_type rp = (VkRenderPass *) malloc (size); - __auto_type pl = (VkPipeline *) &rp[counts->num_renderpasses]; - - size = 0; - size += counts->num_renderpasses * sizeof (VkRenderPassCreateInfo); - size += counts->num_attachments * sizeof (VkAttachmentDescription); - size += counts->num_attachments * sizeof (VkClearValue); - size += counts->num_subpasses * sizeof (VkSubpassDescription); - size += counts->num_dependencies * sizeof (VkSubpassDependency); - size += counts->num_attachmentrefs * sizeof (VkAttachmentReference); - size += counts->num_colorblend*sizeof (VkPipelineColorBlendAttachmentState); - size += counts->num_preserve * sizeof (uint32_t); - size += counts->num_pipelines * sizeof (VkGraphicsPipelineCreateInfo); - size += counts->num_pipelines *sizeof (VkPipelineColorBlendStateCreateInfo); - size += counts->num_pipelines *sizeof (qfv_layoutinfo_t); - exprctx_t ectx = { .hashctx = &ctx->script_context->hashctx, }; + + VkRenderPass rp[counts->num_renderpasses]; + VkPipeline pl[counts->num_pipelines]; + VkRenderPassCreateInfo rpCreate[counts->num_renderpasses]; + VkAttachmentDescription attach[counts->num_attachments]; + VkClearValue clear[counts->num_attachments]; + VkSubpassDescription subpass[counts->num_subpasses]; + VkSubpassDependency depend[counts->num_dependencies]; + VkAttachmentReference attachref[counts->num_attachmentrefs]; + VkPipelineColorBlendAttachmentState cbAttach[counts->num_colorblend]; + uint32_t preserve[counts->num_preserve]; + const char *plName[counts->num_pipelines]; + VkGraphicsPipelineCreateInfo plCreate[counts->num_pipelines]; + VkPipelineColorBlendStateCreateInfo cbState[counts->num_pipelines]; + qfv_layoutinfo_t layouts[counts->num_pipelines]; objstate_t s = { .ptr = { - .rpCreate = alloca (size), - .attach = (void *) &s.ptr.rpCreate [counts->num_renderpasses], - .clear = (void *) &s.ptr.attach [counts->num_attachments], - .subpass = (void *) &s.ptr.clear [counts->num_attachments], - .depend = (void *) &s.ptr.subpass [counts->num_subpasses], - .attachref = (void *) &s.ptr.depend [counts->num_dependencies], - .cbAttach = (void *) &s.ptr.attachref[counts->num_attachmentrefs], - .preserve = (void *) &s.ptr.cbAttach [counts->num_colorblend], - .plCreate = (void *) &s.ptr.preserve [counts->num_preserve], - .cbState = (void *) &s.ptr.plCreate [counts->num_pipelines], - .layouts = (void *) &s.ptr.cbState [counts->num_pipelines], + .rpCreate = rpCreate, + .attach = attach, + .clear = clear, + .subpass = subpass, + .depend = depend, + .attachref = attachref, + .cbAttach = cbAttach, + .preserve = preserve, + .plName = plName, + .plCreate = plCreate, + .cbState = cbState, + .layouts = layouts, + .rp = rp, + .pl = pl, }, .ctx = ctx, .rinfo = rinfo, @@ -680,8 +774,8 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) qfv_devfuncs_t *dfunc = device->funcs; uint32_t plInd = 0; for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { - dfunc->vkCreateRenderPass (device->dev, &s.ptr.rpCreate[i], 0, &rp[i]); __auto_type rpi = &rinfo->renderpasses[i]; + dfunc->vkCreateRenderPass (device->dev, &s.ptr.rpCreate[i], 0, &rp[i]); QFV_duSetObjectName (device, VK_OBJECT_TYPE_RENDER_PASS, rp[i], va (ctx->va_ctx, "renderpass:%s", rpi->name)); for (uint32_t j = 0; j < rpi->num_subpasses; j++) { @@ -691,71 +785,19 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) } } } - dfunc->vkCreateGraphicsPipelines (device->dev, 0, 1, + dfunc->vkCreateGraphicsPipelines (device->dev, 0, s.inds.num_pipelines, s.ptr.plCreate, 0, pl); -} - -static void -init_pipeline (qfv_pipeline_t *pl, vulkan_ctx_t *ctx, qfv_pipelineinfo_t *ipl, - objcount_t *inds) -{ - pl->label.name = ipl->name; - pl->label.color = ipl->color; - pl->task_count = ipl->num_tasks; - pl->tasks = ipl->tasks; -} - -static void -init_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx, qfv_subpassinfo_t *isp, - qfv_pipeline_t *pl, objcount_t *inds) -{ - sp->label.name = isp->name; - sp->label.color = isp->color; - sp->pipeline_count = isp->num_pipelines; - sp->pipelines = &pl[inds->num_pipelines]; - for (uint32_t i = 0; i < isp->num_pipelines; i++) { - init_pipeline (&sp->pipelines[i], ctx, &isp->pipelines[i], inds); - inds->num_pipelines++; - } -} - -static void -init_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx, - qfv_renderpassinfo_t *irp, - qfv_subpass_t_ *sp, qfv_pipeline_t *pl, objcount_t *inds) -{ - rp->vulkan_ctx = ctx; - rp->label.name = irp->name; - rp->label.color = irp->color; - rp->subpass_count = irp->num_subpasses; - rp->subpasses = &sp[inds->num_subpasses]; - for (uint32_t i = 0; i < irp->num_subpasses; i++) { - init_subpass (&rp->subpasses[i], ctx, &irp->subpasses[i], pl, inds); - inds->num_subpasses++; - } -} - -static void -init_render (vulkan_ctx_t *ctx, objcount_t *counts) -{ - __auto_type rctx = ctx->render_context; - __auto_type rinfo = rctx->renderinfo; - __auto_type render = rctx->render; - size_t size = 0; - size += counts->num_renderpasses * sizeof (qfv_renderpass_t_); - size += counts->num_subpasses * sizeof (qfv_subpass_t_); - size += counts->num_pipelines * sizeof (qfv_pipeline_t); - - __auto_type rp = (qfv_renderpass_t_ *) calloc (1, size); - __auto_type sp = (qfv_subpass_t_ *) &rp[counts->num_renderpasses]; - __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; - objcount_t inds = {}; - for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { - init_renderpass (&rp[i], ctx, &rinfo->renderpasses[i], sp, pl, &inds); - inds.num_renderpasses++; + for (uint32_t i = 0; i < s.inds.num_pipelines; i++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE, pl[i], + va (ctx->va_ctx, "pipeline:%s", s.ptr.plName[i])); } - render->renderpasses = rp; + rinfo->num_layouts = s.inds.num_layouts; + size_t layout_size = rinfo->num_layouts * sizeof (qfv_layoutinfo_t); + rinfo->layouts = cmemalloc (rinfo->memsuper, layout_size); + memcpy (rinfo->layouts, s.ptr.layouts, layout_size); + + init_render (ctx, counts, s); } void @@ -769,7 +811,6 @@ QFV_BuildRender (vulkan_ctx_t *ctx) count_stuff (rctx->renderinfo, &counts); create_resources (ctx, &counts); create_renderpasses (ctx, &counts); - init_render (ctx, &counts); } void @@ -788,16 +829,40 @@ QFV_Render_Init (vulkan_ctx_t *ctx) void QFV_Render_Shutdown (vulkan_ctx_t *ctx) { + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; __auto_type rctx = ctx->render_context; if (rctx->render) { - if (rctx->render->resources) { - QFV_DestroyResource (ctx->device, rctx->render->resources); - free (rctx->render->resources); + __auto_type r = rctx->render; + if (r->resources) { + QFV_DestroyResource (ctx->device, r->resources); + free (r->resources); + } + for (uint32_t i = 0; i < r->num_renderpasses; i++) { + __auto_type rp = &r->renderpasses[i]; + for (uint32_t j = 0; j < rp->subpass_count; j++) { + __auto_type sp = &rp->subpasses[j]; + for (uint32_t k = 0; k < sp->pipeline_count; k++) { + __auto_type pl = &sp->pipelines[k]; + dfunc->vkDestroyPipeline (device->dev, pl->pipeline, 0); + } + } + dfunc->vkDestroyRenderPass (device->dev, + rp->beginInfo.renderPass, 0); } free (rctx->render); } if (rctx->renderinfo) { - delete_memsuper (rctx->renderinfo->memsuper); + __auto_type rinfo = rctx->renderinfo; + for (uint32_t i = 0; i < rinfo->num_descriptorsets; i++) { + __auto_type setLayout = rinfo->descriptorsets[i].setLayout; + dfunc->vkDestroyDescriptorSetLayout (device->dev, setLayout, 0); + } + for (uint32_t i = 0; i < rinfo->num_layouts; i++) { + __auto_type layout = rinfo->layouts[i].layout; + dfunc->vkDestroyPipelineLayout (device->dev, layout, 0); + } + delete_memsuper (rinfo->memsuper); } if (rctx->task_functions.tab) { Hash_DelTable (rctx->task_functions.tab); From fdcd972ff9b8973f76198f6589aac75cb5bf7f59 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Feb 2023 15:00:40 +0900 Subject: [PATCH 3445/3664] [vulkan] Use correct index for pl item setup Due to a typo in the list of extra property list items to add to the symbol table (corrected), subsequent symbols were pointing to the wrong memory address. --- libs/video/renderer/vulkan/vkparse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 5ac85421c..6e43e2bb6 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -2259,7 +2259,7 @@ QFV_CreateSymtab (plitem_t *dict, const char *properties, symtab->symbols[num_keys + j] = (exprsym_t) { .name = extra_items[i], .type = &cexpr_plitem, - .value = items + num_keys + i, + .value = items + num_keys + j, }; items[num_keys + j] = val; j++; @@ -2305,7 +2305,7 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) static const char *extra_items[] = { "images", - "view", + "views", "renderpasses", 0 }; From 38c10f9c4f74b1b56170720d21ae3918dcb5ed84 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Feb 2023 15:02:48 +0900 Subject: [PATCH 3446/3664] [vulkan] Support chained render pass infos And thus the cube mapped render pass. --- include/QF/Vulkan/render.h | 1 + libs/video/renderer/vulkan/rp_main_def.plist | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 1326c1431..a44aef3a3 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -158,6 +158,7 @@ typedef struct qfv_framebufferinfo_s { typedef struct qfv_renderpassinfo_s { vec4f_t color; const char *name; + void *pNext; uint32_t num_attachments; qfv_attachmentinfo_t *attachments; qfv_framebufferinfo_t framebuffer; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 59e5d71d5..02d38b4ba 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1147,12 +1147,12 @@ renderpasses = { }; }; }; - /*deferred_cube = { + deferred_cube = { @inherit = $renderpasses.deferred; @next = (VkRenderPassMultiviewCreateInfo, { viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); viewOffsets = ( 0, 0, 0, 0, 0); }); - };*/ + }; }; }; From 9133c0ea3f89d515570d630765fb789cf55bb3a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Feb 2023 18:10:09 +0900 Subject: [PATCH 3447/3664] [vulkan] Initialize most of render pass and subpass state Render passes and subpasses are now mostly initialized, just command buffers and frame buffer related info to go (including view/scissor for pipelines). --- include/QF/Vulkan/render.h | 1 + libs/video/renderer/vulkan/render.c | 54 ++++++++++++++------ libs/video/renderer/vulkan/rp_main_def.plist | 1 + 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index a44aef3a3..b5c590c1c 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -213,6 +213,7 @@ typedef struct qfv_pipeline_s { typedef struct qfv_subpass_s_ { qfv_label_t label; + VkCommandBufferInheritanceInfo inherit; VkCommandBufferBeginInfo beginInfo; VkCommandBuffer cmd; uint32_t pipeline_count; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index a54e0e95b..cb7936ce7 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -654,10 +654,23 @@ static void init_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx, qfv_subpassinfo_t *isp, qfv_pipeline_t *pl, objstate_t *s) { - sp->label.name = isp->name; - sp->label.color = isp->color; - sp->pipeline_count = isp->num_pipelines; - sp->pipelines = &pl[s->inds.num_pipelines]; + *sp = (qfv_subpass_t_) { + .label = { + .name = isp->name, + .color = isp->color, + }, + .inherit = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, + }, + .beginInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, + .pInheritanceInfo = &sp->inherit, + }, + .pipeline_count = isp->num_pipelines, + .pipelines = &pl[s->inds.num_pipelines], + }; for (uint32_t i = 0; i < isp->num_pipelines; i++) { init_pipeline (&sp->pipelines[i], ctx, &isp->pipelines[i], s); s->inds.num_pipelines++; @@ -666,20 +679,28 @@ init_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx, qfv_subpassinfo_t *isp, static void init_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx, - qfv_renderpassinfo_t *irp, + qfv_renderpassinfo_t *irp, VkClearValue *cv, qfv_subpass_t_ *sp, qfv_pipeline_t *pl, objstate_t *s) { - rp->vulkan_ctx = ctx; - rp->label.name = irp->name; - rp->label.color = irp->color; - rp->subpass_count = irp->num_subpasses; - rp->subpasses = &sp[s->inds.num_subpasses]; - rp->beginInfo = (VkRenderPassBeginInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = s->ptr.rp[s->inds.num_renderpasses], + *rp = (qfv_renderpass_t_) { + .vulkan_ctx = ctx, + .label.name = irp->name, + .label.color = irp->color, + .subpass_count = irp->num_subpasses, + .subpasses = &sp[s->inds.num_subpasses], + .beginInfo = (VkRenderPassBeginInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = s->ptr.rp[s->inds.num_renderpasses], + .clearValueCount = irp->num_attachments, + .pClearValues = &cv[s->inds.num_attachments], + }, + .subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, }; + s->inds.num_attachments += irp->num_attachments; for (uint32_t i = 0; i < irp->num_subpasses; i++) { init_subpass (&rp->subpasses[i], ctx, &irp->subpasses[i], pl, s); + rp->subpasses[i].inherit.renderPass = rp->beginInfo.renderPass; + rp->subpasses[i].inherit.subpass = i; s->inds.num_subpasses++; } } @@ -692,17 +713,20 @@ init_render (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) __auto_type render = rctx->render; size_t size = 0; size += counts->num_renderpasses * sizeof (qfv_renderpass_t_); + size += counts->num_attachments * sizeof (VkClearValue); size += counts->num_subpasses * sizeof (qfv_subpass_t_); size += counts->num_pipelines * sizeof (qfv_pipeline_t); __auto_type rp = (qfv_renderpass_t_ *) calloc (1, size); - __auto_type sp = (qfv_subpass_t_ *) &rp[counts->num_renderpasses]; + __auto_type cv = (VkClearValue *) &rp[counts->num_renderpasses]; + __auto_type sp = (qfv_subpass_t_ *) &cv[counts->num_attachments]; __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; + memcpy (cv, s.ptr.clear, counts->num_attachments * sizeof (VkClearValue)); uint32_t num_layouts = s.inds.num_layouts; s.inds = (objcount_t) {}; s.inds.num_layouts = num_layouts; for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { - init_renderpass (&rp[i], ctx, &rinfo->renderpasses[i], sp, pl, &s); + init_renderpass (&rp[i], ctx, &rinfo->renderpasses[i], cv, sp, pl, &s); s.inds.num_renderpasses++; } diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 02d38b4ba..426360d1a 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -765,6 +765,7 @@ output = { }; renderpasses = { deferred = { + color = "[0, 1, 0, 1]"; attachments = { depth = { @inherit = $attachment_base; From 3b9e0a786eb0a394899479c6df7f780459204cf7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Feb 2023 18:44:21 +0900 Subject: [PATCH 3448/3664] [vkgen] Support renaming of auto fields --- libs/video/renderer/vulkan/vkgen/vkfieldauto.r | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldauto.r b/libs/video/renderer/vulkan/vkgen/vkfieldauto.r index ee3d79535..de4a347c9 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldauto.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldauto.r @@ -1,3 +1,5 @@ +#include + #include "vkfieldauto.h" #include "vkgen.h" #include "vkstruct.h" @@ -10,7 +12,8 @@ if (!self) { return self; } - field = [strct findField:field_name]; + string real_name = [[item getObjectForKey:"field"] string]; + field = [strct findField:real_name ? real_name : field_name]; return self; } @@ -25,7 +28,7 @@ { Type *field_type = [Type findType: field.type]; fprintf (output_file, "\t{\"%s\", field_offset (%s, %s), %s, %s, %s},\n", - field_name, struct_name, field_name, + field_name, struct_name, field.name, [field_type parseType], [field_type parseFunc], [field_type parseData]); return self; @@ -36,7 +39,7 @@ Type *field_type = [Type findType: field.type]; fprintf (output_file, "\t{\"%s\", &%s, (void *) field_offset (%s, %s)},\n", - field_name, [field_type cexprType], struct_name, field_name); + field_name, [field_type cexprType], struct_name, field.name); return self; } From 926e3b76b06279f08f6e093c18d4091767b79016 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Feb 2023 12:32:38 +0900 Subject: [PATCH 3449/3664] [gib] Clean up regex.c in anticipation of c23 I tried out -std=c2x (doesn't work due to typeof (gcc bug?)) and -sdt=gnu2x (still no #embed) and found that only regex.c was a problem (nice), and now it no longer is a problem. --- libs/gib/regex.c | 150 +++++++++++++++-------------------------------- 1 file changed, 47 insertions(+), 103 deletions(-) diff --git a/libs/gib/regex.c b/libs/gib/regex.c index 346c1fb8d..4b7817d4f 100644 --- a/libs/gib/regex.c +++ b/libs/gib/regex.c @@ -816,8 +816,7 @@ reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS; defined in regex.h. We return the old syntax. */ reg_syntax_t -re_set_syntax (syntax) - reg_syntax_t syntax; +re_set_syntax (reg_syntax_t syntax) { reg_syntax_t ret = re_syntax_options; @@ -1072,13 +1071,7 @@ typedef struct compile_stack_elt_t The `fastmap' and `newline_anchor' fields are neither examined nor set. */ -static reg_errcode_t regex_compile (const char *pattern, int size, reg_syntax_t syntax, struct re_pattern_buffer *bufp); -static reg_errcode_t -regex_compile (pattern, size, syntax, bufp) - const char *pattern; - int size; - reg_syntax_t syntax; - struct re_pattern_buffer *bufp; +static reg_errcode_t regex_compile (const char *pattern, int size, reg_syntax_t syntax, struct re_pattern_buffer *bufp) { /* We fetch characters from PATTERN here. Even though PATTERN is `char *' (i.e., signed), we declare these variables as unsigned, so @@ -2081,10 +2074,7 @@ regex_compile (pattern, size, syntax, bufp) /* Store OP at LOC followed by two-byte integer parameter ARG. */ static void -store_op1 (op, loc, arg) - re_opcode_t op; - unsigned char *loc; - int arg; +store_op1 (re_opcode_t op, unsigned char *loc, int arg) { *loc = (unsigned char) op; STORE_NUMBER (loc + 1, arg); @@ -2094,10 +2084,7 @@ store_op1 (op, loc, arg) /* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ static void -store_op2 (op, loc, arg1, arg2) - re_opcode_t op; - unsigned char *loc; - int arg1, arg2; +store_op2 (re_opcode_t op, unsigned char *loc, int arg1, int arg2) { *loc = (unsigned char) op; STORE_NUMBER (loc + 1, arg1); @@ -2109,11 +2096,7 @@ store_op2 (op, loc, arg1, arg2) for OP followed by two-byte integer parameter ARG. */ static void -insert_op1 (op, loc, arg, end) - re_opcode_t op; - unsigned char *loc; - int arg; - unsigned char *end; +insert_op1 (re_opcode_t op, unsigned char *loc, int arg, unsigned char *end) { register unsigned char *pfrom = end; register unsigned char *pto = end + 3; @@ -2128,11 +2111,7 @@ insert_op1 (op, loc, arg, end) /* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ static void -insert_op2 (op, loc, arg1, arg2, end) - re_opcode_t op; - unsigned char *loc; - int arg1, arg2; - unsigned char *end; +insert_op2 (re_opcode_t op, unsigned char *loc, int arg1, int arg2, unsigned char *end) { register unsigned char *pfrom = end; register unsigned char *pto = end + 5; @@ -2149,9 +2128,7 @@ insert_op2 (op, loc, arg1, arg2, end) least one character before the ^. */ static boolean -at_begline_loc_p (pattern, p, syntax) - const char *pattern, *p; - reg_syntax_t syntax; +at_begline_loc_p (const char *pattern, const char *p, reg_syntax_t syntax) { const char *prev = p - 2; boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; @@ -2168,9 +2145,7 @@ at_begline_loc_p (pattern, p, syntax) at least one character after the $, i.e., `P < PEND'. */ static boolean -at_endline_loc_p (p, pend, syntax) - const char *p, *pend; - int syntax; +at_endline_loc_p (const char *p, const char *pend, int syntax) { const char *next = p; boolean next_backslash = *next == '\\'; @@ -2190,9 +2165,7 @@ at_endline_loc_p (p, pend, syntax) false if it's not. */ static boolean -group_in_compile_stack (compile_stack, regnum) - compile_stack_type compile_stack; - regnum_t regnum; +group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum) { int this_element; @@ -2218,11 +2191,7 @@ group_in_compile_stack (compile_stack, regnum) `regex_compile' itself. */ static reg_errcode_t -compile_range (p_ptr, pend, translate, syntax, b) - const char **p_ptr, *pend; - char *translate; - reg_syntax_t syntax; - unsigned char *b; +compile_range (const char **p_ptr, const char *pend, char *translate, reg_syntax_t syntax, unsigned char *b) { int this_char; @@ -2550,8 +2519,7 @@ typedef struct Returns 0 if we succeed, -2 if an internal error. */ int -re_compile_fastmap (bufp) - struct re_pattern_buffer *bufp; +re_compile_fastmap (struct re_pattern_buffer *bufp) { int j, k; fail_stack_type fail_stack; @@ -2835,11 +2803,7 @@ re_compile_fastmap (bufp) freeing the old data. */ void -re_set_registers (bufp, regs, num_regs, starts, ends) - struct re_pattern_buffer *bufp; - struct re_registers *regs; - unsigned num_regs; - regoff_t *starts, *ends; +re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs, unsigned num_regs, regoff_t *starts, regoff_t *ends) { if (num_regs) { @@ -2862,11 +2826,7 @@ re_set_registers (bufp, regs, num_regs, starts, ends) doesn't let you say where to stop matching. */ int -re_search (bufp, string, size, startpos, range, regs) - struct re_pattern_buffer *bufp; - const char *string; - int size, startpos, range; - struct re_registers *regs; +re_search (struct re_pattern_buffer *bufp, const char *string, int size, int startpos, int range, struct re_registers *regs) { return re_search_2 (bufp, NULL, 0, string, size, startpos, range, regs, size); @@ -2895,14 +2855,7 @@ re_search (bufp, string, size, startpos, range, regs) stack overflow). */ int -re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; - int startpos; - int range; - struct re_registers *regs; - int stop; +re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int size1, const char *string2, int size2, int startpos, int range, struct re_registers *regs, int stop) { int val; register char *fastmap = bufp->fastmap; @@ -3154,12 +3107,8 @@ typedef union register_info_type /* re_match is like re_match_2 except it takes only a single string. */ int -re_match (bufp, string, size, pos, regs) - struct re_pattern_buffer *bufp; - const char *string; - int size, pos; - struct re_registers *regs; - { +re_match (struct re_pattern_buffer *bufp, const char *string, int size, int pos, struct re_registers *regs) +{ return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size); } #endif /* not emacs */ @@ -3179,13 +3128,7 @@ re_match (bufp, string, size, pos, regs) matched substring. */ int -re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - int size1, size2; - int pos; - struct re_registers *regs; - int stop; +re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int size1, const char *string2, int size2, int pos, struct re_registers *regs, int stop) { /* General temporaries. */ int mcnt; @@ -4379,9 +4322,10 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) We don't handle duplicates properly (yet). */ static boolean -group_match_null_string_p (p, end, reg_info) - unsigned char **p, *end; - register_info_type *reg_info; +group_match_null_string_p ( + unsigned char **p, + unsigned char *end, + register_info_type *reg_info) { int mcnt; /* Point to after the args to the start_memory. */ @@ -4488,9 +4432,10 @@ group_match_null_string_p (p, end, reg_info) byte past the last. The alternative can contain groups. */ static boolean -alt_match_null_string_p (p, end, reg_info) - unsigned char *p, *end; - register_info_type *reg_info; +alt_match_null_string_p ( + unsigned char *p, + unsigned char *end, + register_info_type *reg_info) { int mcnt; unsigned char *p1 = p; @@ -4525,9 +4470,10 @@ alt_match_null_string_p (p, end, reg_info) Sets P to one after the op and its arguments, if any. */ static boolean -common_op_match_null_string_p (p, end, reg_info) - unsigned char **p, *end; - register_info_type *reg_info; +common_op_match_null_string_p ( + unsigned char **p, + unsigned char *end, + register_info_type *reg_info) { int mcnt; boolean ret; @@ -4613,10 +4559,11 @@ common_op_match_null_string_p (p, end, reg_info) bytes; nonzero otherwise. */ static int -bcmp_translate (s1, s2, len, translate) - const unsigned char *s1, *s2; - register int len; - char *translate; +bcmp_translate ( + const unsigned char *s1, + const unsigned char *s2, + register int len, + char *translate) { register const unsigned char *p1 = s1, *p2 = s2; while (len) @@ -4639,10 +4586,10 @@ bcmp_translate (s1, s2, len, translate) We call regex_compile to do the actual compilation. */ const char * -re_compile_pattern (pattern, length, bufp) - const char *pattern; - int length; - struct re_pattern_buffer *bufp; +re_compile_pattern ( + const char *pattern, + int length, + struct re_pattern_buffer *bufp) { reg_errcode_t ret; @@ -4758,10 +4705,7 @@ re_exec (s) the return codes and their meanings.) */ int -regcomp (preg, pattern, cflags) - regex_t *preg; - const char *pattern; - int cflags; +regcomp (regex_t *preg, const char *pattern, int cflags) { reg_errcode_t ret; unsigned syntax @@ -4833,12 +4777,13 @@ regcomp (preg, pattern, cflags) We return 0 if we find a match and REG_NOMATCH if not. */ int -regexec (preg, string, nmatch, pmatch, eflags) - const regex_t *preg; - const char *string; - size_t nmatch; - regmatch_t pmatch[]; - int eflags; +regexec ( + const regex_t *preg, + const char *string, + size_t nmatch, + regmatch_t pmatch[], + int eflags + ) { int ret; struct re_registers regs; @@ -4937,8 +4882,7 @@ regerror (int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) { /* Free dynamically allocated space used by PREG. */ void -regfree (preg) - regex_t *preg; +regfree (regex_t *preg) { if (preg->buffer != NULL) free (preg->buffer); From 9d63d4901faf2b5396a893283cc51126c1b951b9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Mar 2023 18:33:16 +0900 Subject: [PATCH 3450/3664] [vulkan] Create a framebuffer for the first render pass Currently just the one framebuffer is created, but I want to get things running soon. --- include/QF/Vulkan/render.h | 3 + libs/video/renderer/vid_render_vulkan.c | 1 + libs/video/renderer/vulkan/render.c | 75 ++++++++++++++++++++ libs/video/renderer/vulkan/rp_main_def.plist | 9 ++- libs/video/renderer/vulkan/vkparse.plist | 5 -- 5 files changed, 86 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index b5c590c1c..9cfecdafe 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -89,6 +89,7 @@ typedef struct qfv_attachmentinfo_s { VkImageLayout initialLayout; VkImageLayout finalLayout; VkClearValue clearValue; + qfv_reference_t view; } qfv_attachmentinfo_t; typedef struct qfv_taskinfo_s { @@ -257,6 +258,8 @@ typedef struct qfv_renderctx_s { void QFV_RunRenderPass (qfv_renderpass_t_ *rp, struct vulkan_ctx_s *ctx); void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx); void QFV_BuildRender (struct vulkan_ctx_s *ctx); +void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx); +void QFV_DestroyFramebuffer (struct vulkan_ctx_s *ctx); void QFV_Render_Init (struct vulkan_ctx_s *ctx); void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx); void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 25ada2b43..419636f46 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -118,6 +118,7 @@ vulkan_R_Init (void) QFV_LoadRenderInfo (vulkan_ctx); QFV_BuildRender (vulkan_ctx); + QFV_CreateFramebuffer (vulkan_ctx); Skin_Init (); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index cb7936ce7..8bb8fe073 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -837,6 +837,80 @@ QFV_BuildRender (vulkan_ctx_t *ctx) create_renderpasses (ctx, &counts); } +static VkImageView +find_view (qfv_reference_t *ref, qfv_renderctx_t *rctx) +{ + __auto_type rinfo = rctx->renderinfo; + __auto_type render = rctx->render; + const char *name = ref->name; + + if (strncmp (name, "$views.", 7) == 0) { + name += 7; + } + + for (uint32_t i = 0; i < rinfo->num_views; i++) { + __auto_type vi = &rinfo->views[i]; + __auto_type vo = &render->image_views[i]; + if (strcmp (name, vi->name) == 0) { + return vo->image_view.view; + } + } + Sys_Error ("%d:invalid view: %s", ref->line, ref->name); +} + +void +QFV_DestroyFramebuffer (vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type rctx = ctx->render_context; + __auto_type render = rctx->render; + __auto_type rp = &render->renderpasses[0]; + + if (rp->beginInfo.framebuffer) { + VkFramebuffer framebuffer = rp->beginInfo.framebuffer; + rp->beginInfo.framebuffer = 0; + dfunc->vkDestroyFramebuffer (device->dev, framebuffer, 0); + } +} + +void +QFV_CreateFramebuffer (vulkan_ctx_t *ctx) +{ + __auto_type rctx = ctx->render_context; + __auto_type rinfo = rctx->renderinfo; + __auto_type render = rctx->render; + __auto_type rpInfo = &rinfo->renderpasses[0]; + __auto_type rp = &render->renderpasses[0]; + + VkImageView attachments[rpInfo->num_attachments]; + VkFramebufferCreateInfo cInfo = { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .attachmentCount = rpInfo->num_attachments, + .pAttachments = attachments, + .renderPass = rp->beginInfo.renderPass, + .width = rpInfo->framebuffer.width, + .height = rpInfo->framebuffer.height, + .layers = rpInfo->framebuffer.layers, + }; + for (uint32_t i = 0; i < rpInfo->num_attachments; i++) { + attachments[i] = find_view (&rpInfo->attachments[i].view, rctx); + } + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkFramebuffer framebuffer; + dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_FRAMEBUFFER, framebuffer, + va (ctx->va_ctx, "framebuffer:%s", rpInfo->name)); + + rp->beginInfo.framebuffer = framebuffer; + for (uint32_t i = 0; i < rp->subpass_count; i++) { + __auto_type sp = &rp->subpasses[i]; + sp->inherit.framebuffer = framebuffer; + } +} + void QFV_Render_Init (vulkan_ctx_t *ctx) { @@ -857,6 +931,7 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; __auto_type rctx = ctx->render_context; if (rctx->render) { + QFV_DestroyFramebuffer (ctx); //FIXME do properly __auto_type r = rctx->render; if (r->resources) { QFV_DestroyResource (ctx->device, r->resources); diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 426360d1a..73b6be1b5 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -773,28 +773,34 @@ renderpasses = { loadOp = clear; finalLayout = depth_stencil_attachment_optimal; clearValue = { depthStencil = { depth = 1; stencil = 0; }; }; + view = $views.depth; }; color = { @inherit = $attachment_base; format = $images.color.format; loadOp = clear; + view = $views.color; }; emission = { @inherit = $attachment_base; format = $images.emission.format; loadOp = clear; + view = $views.emission; }; normal = { @inherit = $attachment_base; format = $images.normal.format; + view = $views.normal; }; position = { @inherit = $attachment_base; format = $images.position.format; + view = $views.position; }; opaque = { @inherit = $attachment_base; format = $images.opaque.format; + view = $views.opaque; }; output = { @inherit = $attachment_base; @@ -802,11 +808,10 @@ renderpasses = { loadOp = clear; storeOp = store; finalLayout = $output.finalLayout; + view = $views.output; }; }; framebuffer = { - attachments = (depth, color, emission, normal, position, opaque, - $output.view); width = $output.extent.width; height = $output.extent.height; layers = 1; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 346305bf1..6fbcfa3dc 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -580,11 +580,6 @@ }; qfv_framebufferinfo_s = { .name = qfv_framebufferinfo_t; - attachments = { - type = (array, qfv_reference_t); - size = num_attachments; - values = attachments; - }; width = auto; height = auto; layers = auto; From c0048c14b3f5f756edc2905bd2ab2f1c6dfc063b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 2 Mar 2023 18:34:10 +0900 Subject: [PATCH 3451/3664] [vulkan] Fix a typo in a comment Double "the" --- libs/video/renderer/vulkan/vulkan_particles.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 02770a229..d6f1a7a70 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -428,8 +428,8 @@ particles_update (qfv_renderframe_t *rFrame) // two buffers over the system buffer. This avoids either buffer being // just past the end of the staging buffer (which the validation layers // (correctly) do not like). - // This is fine because the two buffers are only read by the the - // compute shader. + // This is fine because the two buffers are only read by the compute + // shader. partsize = paramsize = syssize; partoffs = paramoffs = 0; } From d0a3040b265558cd79242e661e883937f323c3a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Mar 2023 10:31:54 +0900 Subject: [PATCH 3452/3664] [vulkan] Fix a missed pure attribute I don't have a compile pre-push hook on my laptop. --- libs/video/renderer/vulkan/render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 8bb8fe073..9dbeccc35 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -837,7 +837,7 @@ QFV_BuildRender (vulkan_ctx_t *ctx) create_renderpasses (ctx, &counts); } -static VkImageView +static VkImageView __attribute__((pure)) find_view (qfv_reference_t *ref, qfv_renderctx_t *rctx) { __auto_type rinfo = rctx->renderinfo; From 9146860f7001a3f5572b2fb66d03b8d8640688ec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Mar 2023 14:47:38 +0900 Subject: [PATCH 3453/3664] [util] Add size limited find and hash functions Hash_nFind and Hash_nString work like Hash_Find and Hash_String, but take a maximum string length (like strncmp etc). --- include/QF/hash.h | 17 +++++++++++++++++ libs/util/hash.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/include/QF/hash.h b/include/QF/hash.h index d5367be15..8faa44aa5 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -119,6 +119,14 @@ int Hash_AddElement (hashtab_t *tab, void *ele); */ void *Hash_Find (hashtab_t *tab, const char *key); +/** find an element within a hash table. + \param tab the table to search + \param key the key string identifying the element being searched for + \param sz the maximum length of the key string + \return pointer to the element if found, otherwise 0. +*/ +void *Hash_nFind (hashtab_t *tab, const char *key, size_t sz); + /** find an element within a hash table. \param tab the table to search \param ele element with info identifying the element being searched for @@ -189,6 +197,15 @@ void Hash_Free (hashtab_t *tab, void *ele); */ uintptr_t Hash_String (const char *str) __attribute__((pure)); +/** hash a string. + \param str the string to hash + \param sz the maximum length of the string + \return the hash value of the string. + + this is the same function as used internally. +*/ +uintptr_t Hash_nString (const char *str, size_t sz) __attribute__((pure)); + /** hash a buffer. \param buf the buffer to hash \param len the size of the buffer diff --git a/libs/util/hash.c b/libs/util/hash.c index f1d3d3884..14f41623f 100644 --- a/libs/util/hash.c +++ b/libs/util/hash.c @@ -119,6 +119,32 @@ Hash_String (const char *str) #endif } +VISIBLE uintptr_t +Hash_nString (const char *str, size_t sz) +{ +#if 0 + uintptr_t h = 0; + while (*str && sz-- > 0) { + h = (h << 4) + (unsigned char)*str++; + if (h&0xf0000000) + h = (h ^ (h >> 24)) & 0xfffffff; + } + return h; +#else + // dx_hack_hash + // shamelessly stolen from Daniel Phillips + // from his post to lkml + uint32_t hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; + while (sz-- > 0 && *str) { + uint32_t hash = hash1 + (hash0 ^ ((unsigned char)*str++ * 71523)); + if (hash & 0x80000000) hash -= 0x7fffffff; + hash1 = hash0; + hash0 = hash; + } + return hash0; +#endif +} + VISIBLE uintptr_t Hash_Buffer (const void *_buf, int len) { @@ -289,6 +315,21 @@ Hash_Find (hashtab_t *tab, const char *key) return 0; } +VISIBLE void * +Hash_nFind (hashtab_t *tab, const char *key, size_t sz) +{ + uintptr_t h = Hash_nString (key, sz); + size_t ind = get_index (h, tab->tab_size, tab->size_bits); + hashlink_t *lnk = tab->tab[ind]; + + while (lnk) { + if (strncmp (key, tab->get_key (lnk->data, tab->user_data), sz) == 0) + return lnk->data; + lnk = lnk->next; + } + return 0; +} + VISIBLE void * Hash_FindElement (hashtab_t *tab, const void *ele) { From 70aa970c32c667e12322d3fb838706940d12502c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Mar 2023 19:36:28 +0900 Subject: [PATCH 3454/3664] [gamecode] Make modules responsible for freeing resources It should have been this way all along, and it seems I thought they were when I did rua_gui.c as it already freed its resource block, which would have been a double free (oops). Fixes an invalid write when shutting down progs in qwaq-cmd (relevant change not committed). --- libs/console/bi_inputline.c | 1 + libs/gamecode/pr_debug.c | 2 ++ libs/gamecode/pr_resource.c | 1 - libs/gamecode/pr_strings.c | 2 ++ libs/gib/bi_gib.c | 3 ++- libs/ruamoko/rua_cbuf.c | 1 + libs/ruamoko/rua_cmd.c | 1 + libs/ruamoko/rua_cvar.c | 1 + libs/ruamoko/rua_hash.c | 1 + libs/ruamoko/rua_input.c | 2 ++ libs/ruamoko/rua_mersenne.c | 1 + libs/ruamoko/rua_model.c | 1 + libs/ruamoko/rua_msgbuf.c | 1 + libs/ruamoko/rua_obj.c | 2 ++ libs/ruamoko/rua_plist.c | 1 + libs/ruamoko/rua_qfile.c | 1 + libs/ruamoko/rua_scene.c | 1 + libs/ruamoko/rua_script.c | 1 + libs/ruamoko/rua_set.c | 1 + libs/video/renderer/r_progs.c | 2 ++ ruamoko/qwaq/builtins/curses.c | 1 + ruamoko/qwaq/builtins/debug.c | 2 ++ ruamoko/qwaq/builtins/editbuffer.c | 1 + ruamoko/qwaq/builtins/main.c | 1 + ruamoko/qwaq/builtins/term-input.c | 1 + 25 files changed, 31 insertions(+), 2 deletions(-) diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index 9111945ea..4b6764e3a 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -105,6 +105,7 @@ bi_il_clear (progs_t *pr, void *_res) static void bi_il_destroy (progs_t *pr, void *_res) { + free (_res); } static il_data_t * __attribute__((pure)) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 7f62831fc..683fa4bf7 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -407,6 +407,8 @@ pr_debug_destroy (progs_t *pr, void *_res) Hash_DelTable (res->compunits); pr->pr_debug_resources = 0; + + free (res); } static file_t * diff --git a/libs/gamecode/pr_resource.c b/libs/gamecode/pr_resource.c index 0b0c52ec7..6b51a4f64 100644 --- a/libs/gamecode/pr_resource.c +++ b/libs/gamecode/pr_resource.c @@ -79,7 +79,6 @@ PR_Resources_Shutdown (progs_t *pr) while (res) { pr_resource_t *t = res->next; res->destroy (pr, res->data); - free (res->data); free (res); res = t; } diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index d4f423c4e..5bd8ad9c2 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -241,6 +241,8 @@ pr_strings_destroy (progs_t *pr, void *_res) dstring_delete (res->print_str); Hash_DelTable (res->strref_hash); pr->pr_string_resources = 0; + + free (res); } VISIBLE int diff --git a/libs/gib/bi_gib.c b/libs/gib/bi_gib.c index 0a55e8a2d..049507e16 100644 --- a/libs/gib/bi_gib.c +++ b/libs/gib/bi_gib.c @@ -116,8 +116,9 @@ bi_gib_builtin_clear (progs_t *progs, void *_res) static void bi_gib_builtin_destroy (progs_t *progs, void *_res) { - //bi_gib_resources_t *res = (bi_gib_resources_t *) _res; + bi_gib_resources_t *res = (bi_gib_resources_t *) _res; Hash_DelTable (bi_gib_builtins); + free (res); } static void diff --git a/libs/ruamoko/rua_cbuf.c b/libs/ruamoko/rua_cbuf.c index c727ae891..5380810b2 100644 --- a/libs/ruamoko/rua_cbuf.c +++ b/libs/ruamoko/rua_cbuf.c @@ -96,6 +96,7 @@ bi_cbuf_clear (progs_t *pr, void *data) static void bi_cbuf_destroy (progs_t *pr, void *data) { + free (data); } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index 50e4ba2eb..96025fc65 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -130,6 +130,7 @@ bi_cmd_destroy (progs_t *pr, void *data) if (!--bi_cmds_refs) { Hash_DelTable (bi_cmds); } + free (data); } static void diff --git a/libs/ruamoko/rua_cvar.c b/libs/ruamoko/rua_cvar.c index 716e16172..79ebffda2 100644 --- a/libs/ruamoko/rua_cvar.c +++ b/libs/ruamoko/rua_cvar.c @@ -79,6 +79,7 @@ bi_cvar_clear (progs_t *pr, void *_res) static void bi_cvar_destroy (progs_t *pr, void *_res) { + free (_res); } static void diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 8cb1e55a8..cd8e2b235 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -385,6 +385,7 @@ bi_hash_clear (progs_t *pr, void *_res) static void bi_hash_destroy (progs_t *pr, void *_res) { + free (_res); } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index c7e8e97bc..1c6153b55 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -486,6 +486,8 @@ bi_input_destroy (progs_t *pr, void *_res) input_resources_t *res = _res; Hash_DelTable (res->cookies); delete_memsuper (res->cookie_super); + + free (res); } static uintptr_t diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c index 632aa8ccc..15ce3e41c 100644 --- a/libs/ruamoko/rua_mersenne.c +++ b/libs/ruamoko/rua_mersenne.c @@ -150,6 +150,7 @@ bi_mtwist_clear (progs_t *pr, void *_res) static void bi_mtwist_destroy (progs_t *pr, void *_res) { + free (_res); } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} diff --git a/libs/ruamoko/rua_model.c b/libs/ruamoko/rua_model.c index 4ea5b564a..a19fa8f92 100644 --- a/libs/ruamoko/rua_model.c +++ b/libs/ruamoko/rua_model.c @@ -106,6 +106,7 @@ bi_rua_model_clear (progs_t *pr, void *_res) static void bi_rua_model_destroy (progs_t *pr, void *_res) { + free (_res); } static int diff --git a/libs/ruamoko/rua_msgbuf.c b/libs/ruamoko/rua_msgbuf.c index cf1db72e9..b8300d382 100644 --- a/libs/ruamoko/rua_msgbuf.c +++ b/libs/ruamoko/rua_msgbuf.c @@ -97,6 +97,7 @@ bi_msgbuf_clear (progs_t *pr, void *data) static void bi_msgbuf_destroy (progs_t *pr, void *_res) { + free (_res); } static int diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 1d0872798..15b4d114f 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -2332,6 +2332,8 @@ rua_obj_destroy (progs_t *pr, void *_res) Hash_DelTable (probj->classes); Hash_DelTable (probj->protocols); Hash_DelTable (probj->load_methods); + + free (probj); } void diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index f146dbb92..e3d5cb9eb 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -111,6 +111,7 @@ bi_plist_destroy (progs_t *pr, void *_res) { __auto_type res = (plist_resources_t *) _res; Hash_DelTable (res->plist_tab); + free (res); } static inline int diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index 98636cb36..c702cbb5a 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -98,6 +98,7 @@ bi_qfile_clear (progs_t *pr, void *_res) static void bi_qfile_destroy (progs_t *pr, void *_res) { + free (_res); } static int diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 0993480a2..384c3bfea 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -657,6 +657,7 @@ bi_scene_clear (progs_t *pr, void *_res) static void bi_scene_destroy (progs_t *pr, void *_res) { + free (_res); } void diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index d11b41b49..5bcc262f2 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -94,6 +94,7 @@ bi_script_clear (progs_t *pr, void *_res) static void bi_script_destroy (progs_t *pr, void *_res) { + free (_res); } static void diff --git a/libs/ruamoko/rua_set.c b/libs/ruamoko/rua_set.c index 4e7ea12b6..161cfa8c2 100644 --- a/libs/ruamoko/rua_set.c +++ b/libs/ruamoko/rua_set.c @@ -806,6 +806,7 @@ res_set_clear (progs_t *pr, void *_res) static void res_set_destroy (progs_t *pr, void *_res) { + free (_res); } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 2a22dd05d..4a295e4d8 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -491,6 +491,8 @@ bi_draw_destroy (progs_t *pr, void *_res) { draw_resources_t *res = (draw_resources_t *) _res; Hash_DelTable (res->pic_hash); + + free (res); } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} diff --git a/ruamoko/qwaq/builtins/curses.c b/ruamoko/qwaq/builtins/curses.c index 4c85b115a..e97e140db 100644 --- a/ruamoko/qwaq/builtins/curses.c +++ b/ruamoko/qwaq/builtins/curses.c @@ -1864,6 +1864,7 @@ bi_curses_clear (progs_t *pr, void *_res) static void bi_curses_destroy (progs_t *pr, void *_res) { + free (_res); } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} diff --git a/ruamoko/qwaq/builtins/debug.c b/ruamoko/qwaq/builtins/debug.c index 4e3420e1c..6148076bc 100644 --- a/ruamoko/qwaq/builtins/debug.c +++ b/ruamoko/qwaq/builtins/debug.c @@ -167,6 +167,7 @@ qwaq_debug_clear (progs_t *pr, void *_res) static void qwaq_debug_destroy (progs_t *pr, void *_res) { + free (_res); } static void @@ -181,6 +182,7 @@ qwaq_target_clear (progs_t *pr, void *_res) static void qwaq_target_destroy (progs_t *pr, void *_res) { + // no block to free } static int diff --git a/ruamoko/qwaq/builtins/editbuffer.c b/ruamoko/qwaq/builtins/editbuffer.c index f7f33db8e..0631d3c49 100644 --- a/ruamoko/qwaq/builtins/editbuffer.c +++ b/ruamoko/qwaq/builtins/editbuffer.c @@ -1020,6 +1020,7 @@ qwaq_ebresources_clear (progs_t *pr, void *_res) static void qwaq_ebresources_destroy (progs_t *pr, void *_res) { + free (_res); } #define bi(x,n,np,params...) {#x, bi_##x, n, np, {params}} diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 3ef07279f..9bab54404 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -200,6 +200,7 @@ qwaq_thread_clear (progs_t *pr, void *_thread) static void qwaq_thread_destroy (progs_t *pr, void *_res) { + // resource block is the thread data: don't own it } static progs_t * diff --git a/ruamoko/qwaq/builtins/term-input.c b/ruamoko/qwaq/builtins/term-input.c index 544cd3841..72de4fb74 100644 --- a/ruamoko/qwaq/builtins/term-input.c +++ b/ruamoko/qwaq/builtins/term-input.c @@ -892,6 +892,7 @@ bi_input_clear (progs_t *pr, void *_res) static void bi_input_destroy (progs_t *pr, void *_res) { + free (_res); } static void From b8bd83f5cd2939c76c2ee55bd86969b50565136f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 3 Mar 2023 22:07:27 +0900 Subject: [PATCH 3455/3664] [gamecode] Clean up a pile of memory leaks Usually doesn't matter, but it makes it easier to evaluate valgrind's output. --- include/QF/progs.h | 8 ++++++++ libs/gamecode/pr_builtins.c | 3 +++ libs/gamecode/pr_debug.c | 2 ++ libs/gamecode/pr_load.c | 9 +++++++++ libs/gamecode/pr_strings.c | 9 ++++++++- libs/ruamoko/rua_hash.c | 6 +++++- libs/ruamoko/rua_obj.c | 10 ++++++++++ libs/ruamoko/rua_plist.c | 3 +++ libs/ruamoko/rua_qfile.c | 6 +++++- 9 files changed, 53 insertions(+), 3 deletions(-) diff --git a/include/QF/progs.h b/include/QF/progs.h index 8e3d07e69..fddb57027 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1792,6 +1792,14 @@ void *PR_Resources_Find (progs_t *pr, const char *name); */ #define PR_RESMAP(type) struct { type *_free; type **_map; unsigned _size; } +#define PR_RESDELMAP(map) \ + do { \ + for (unsigned i = 0; i < (map)._size; i++) { \ + free ((map)._map[i]); \ + } \ + free ((map)._map); \ + } while (0) + /** Allocate a new resource from the resource map. \param map The resource map. diff --git a/libs/gamecode/pr_builtins.c b/libs/gamecode/pr_builtins.c index 2e9b9f60f..b8a922276 100644 --- a/libs/gamecode/pr_builtins.c +++ b/libs/gamecode/pr_builtins.c @@ -171,6 +171,9 @@ PR_Builtins_Shutdown (progs_t *pr) pr->builtin_hash = 0; Hash_DelTable (pr->builtin_num_hash); pr->builtin_num_hash = 0; + + free (pr->function_table); + pr->function_table = 0; } VISIBLE builtin_t * diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 683fa4bf7..e80cb72a7 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -406,6 +406,8 @@ pr_debug_destroy (progs_t *pr, void *_res) Hash_DelTable (res->debug_syms); Hash_DelTable (res->compunits); + PR_RESDELMAP (res->compmap); + pr->pr_debug_resources = 0; free (res); diff --git a/libs/gamecode/pr_load.c b/libs/gamecode/pr_load.c index 961bc1c7a..abde7ba06 100644 --- a/libs/gamecode/pr_load.c +++ b/libs/gamecode/pr_load.c @@ -569,6 +569,15 @@ PR_Shutdown (progs_t *pr) pr->global_hash = 0; pr->field_hash = 0; pr->type_hash = 0; + + if (pr->progs) { + pr->free_progs_mem (pr, pr->progs); + } + free (pr->pr_globaldefs); + free (pr->pr_fielddefs); + pr->progs = 0; + pr->pr_globaldefs = 0; + pr->pr_fielddefs = 0; } VISIBLE void diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 5bd8ad9c2..b4227fc64 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -240,8 +240,15 @@ pr_strings_destroy (progs_t *pr, void *_res) __auto_type res = (prstr_resources_t *) _res; dstring_delete (res->print_str); Hash_DelTable (res->strref_hash); - pr->pr_string_resources = 0; + free (res->static_strings); + res->static_strings = 0; + for (unsigned i = 0; i < res->dyn_str_size; i++) { + free (res->string_map[i]); + } + free (res->string_map); + + pr->pr_string_resources = 0; free (res); } diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index cd8e2b235..040d5dcaa 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -385,7 +385,11 @@ bi_hash_clear (progs_t *pr, void *_res) static void bi_hash_destroy (progs_t *pr, void *_res) { - free (_res); + hash_resources_t *res = _res; + + PR_RESDELMAP (res->table_map); + + free (res); } #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 15b4d114f..81c440924 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -2333,6 +2333,16 @@ rua_obj_destroy (progs_t *pr, void *_res) Hash_DelTable (probj->protocols); Hash_DelTable (probj->load_methods); + free (probj->selector_sels); + free (probj->selector_names); + free (probj->selector_argc); + //FIXME free (probj->obj_list_free_list); + + //FIXME free (class_tree_free_list); + //FIXME class_tree_free_list = 0; + + PR_RESDELMAP (probj->dtables); + free (probj); } diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index e3d5cb9eb..430971b05 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -111,6 +111,9 @@ bi_plist_destroy (progs_t *pr, void *_res) { __auto_type res = (plist_resources_t *) _res; Hash_DelTable (res->plist_tab); + + PR_RESDELMAP (res->plist_map); + free (res); } diff --git a/libs/ruamoko/rua_qfile.c b/libs/ruamoko/rua_qfile.c index c702cbb5a..4de8c55ad 100644 --- a/libs/ruamoko/rua_qfile.c +++ b/libs/ruamoko/rua_qfile.c @@ -98,7 +98,11 @@ bi_qfile_clear (progs_t *pr, void *_res) static void bi_qfile_destroy (progs_t *pr, void *_res) { - free (_res); + qfile_resources_t *res = _res; + + PR_RESDELMAP (res->handle_map); + + free (res); } static int From e57427142b42dda3be42082237ced73c5d685e79 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Mar 2023 00:38:32 +0900 Subject: [PATCH 3456/3664] [util] Clean up some memory leaks in cmd --- libs/util/cmd.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libs/util/cmd.c b/libs/util/cmd.c index 4b33673e4..6997b407d 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -310,6 +310,13 @@ Cmd_CompleteBuildList (const char *partial) } /* Hash table functions for aliases and commands */ +static void +cmd_free (void *_c, void *unused) +{ + cmd_function_t *cmd = _c; + free (cmd); +} + static void cmd_alias_free (void *_a, void *unused) { @@ -606,10 +613,20 @@ Cmd_StuffCmds_f (void) Cmd_StuffCmds (cbuf_active); } +static void +cmd_shutdown (void *data) +{ + Cbuf_Delete (cmd_cbuf); + Hash_DelTable (cmd_hash); + Hash_DelTable (cmd_alias_hash); + Hash_DelTable (cmd_provider_hash); +} + VISIBLE void Cmd_Init_Hash (void) { - cmd_hash = Hash_NewTable (1021, cmd_get_key, 0, 0, 0); + Sys_RegisterShutdown (cmd_shutdown, 0); + cmd_hash = Hash_NewTable (1021, cmd_get_key, cmd_free, 0, 0); cmd_alias_hash = Hash_NewTable (1021, cmd_alias_get_key, cmd_alias_free, 0, 0); cmd_provider_hash = Hash_NewTable(1021, cmd_provider_get_key, From 8b8bc42038928ec372503166ac28af02f477859b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Mar 2023 00:39:37 +0900 Subject: [PATCH 3457/3664] [ruamoko] Own created property list objects If the PLItem classes create a property list object, they own it. Plugs more leaks. --- ruamoko/lib/PropertyList.r | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ruamoko/lib/PropertyList.r b/ruamoko/lib/PropertyList.r index 65e3b9124..9feee810a 100644 --- a/ruamoko/lib/PropertyList.r +++ b/ruamoko/lib/PropertyList.r @@ -51,12 +51,16 @@ + (PLItem *) fromString:(string) str { - return [[PLItem itemClass: PL_GetPropertyList (str)] autorelease]; + PLItem *item = [[PLItem itemClass: PL_GetPropertyList (str)] autorelease]; + item.own = 1; + return item; } + (PLItem *) fromFile:(QFile) file { - return [[PLItem itemClass: PL_GetFromFile (file)] autorelease]; + PLItem *item = [[PLItem itemClass: PL_GetFromFile (file)] autorelease]; + item.own = 1; + return item; } - initWithItem:(plitem_t *) item @@ -211,7 +215,9 @@ - (PLItem *) allKeys { - return [[PLItem itemClass: PL_D_AllKeys (item)] autorelease]; + PLItem *item = [[PLItem itemClass: PL_D_AllKeys (item)] autorelease]; + item.own = 1; + return item; } - addKey:(string) key value:(PLItem *) value From c28ffbb766ba91a530e29ed473501ec3eb58cb37 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Mar 2023 00:41:38 +0900 Subject: [PATCH 3458/3664] [vkgen] Plug some memory leaks Not that they really matter, but it makes checking valgrind easier. --- libs/video/renderer/vulkan/vkgen/vkgen.r | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 2f69d871a..32901bfaa 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -255,5 +255,7 @@ main(int argc, string *argv) fprintf (output_file, "}\n"); Qclose (output_file); Qclose (header_file); + Hash_DelTable (available_types); + [plist release]; return 0; } From 44ad372adb13a66d65a3d4f919ce84df1a6004fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Mar 2023 00:50:27 +0900 Subject: [PATCH 3459/3664] [ruamoko] Clean up some memory leaks So many sieves. --- ruamoko/qwaq/builtins/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 9bab54404..2a4a98b76 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -317,6 +317,9 @@ run_progs (void *data) thread->pr->debug_handler (prd_terminate, &thread->return_code, thread->pr->debug_data); } + PR_Shutdown (thread->pr); + free (thread->pr); + thread->pr = 0; return thread; } @@ -473,6 +476,7 @@ main (int argc, char **argv) ret = thread_data.a[main_ind]->return_code; } + Cbuf_Delete (qwaq_cbuf); Sys_Shutdown (); return ret; } From be9e6893e5063e803a0cfa7da44f902c7f0ba708 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Mar 2023 02:07:31 +0900 Subject: [PATCH 3460/3664] [util] Free up hash links Finally, hash links can be freed when the hash context is no longer relevant. The context is created automatically when needed, and the owner can delete the context when its done with the relevant hash tables. --- include/QF/hash.h | 2 + libs/util/hash.c | 71 +++++++++++++++++++++++++++--------- ruamoko/qwaq/builtins/main.c | 3 ++ 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/include/QF/hash.h b/include/QF/hash.h index 8faa44aa5..df9773042 100644 --- a/include/QF/hash.h +++ b/include/QF/hash.h @@ -93,6 +93,8 @@ void Hash_SetHashCompare (hashtab_t *tab, uintptr_t (*gh)(const void*,void*), */ void Hash_DelTable (hashtab_t *tab); +void Hash_DelContext (hashctx_t *hashctx); + /** clean out all the entries from a hash table, starting over again. \param tab the table to be cleared */ diff --git a/libs/util/hash.c b/libs/util/hash.c index 14f41623f..d88f71aec 100644 --- a/libs/util/hash.c +++ b/libs/util/hash.c @@ -51,6 +51,15 @@ typedef struct hashlink_s { void *data; } hashlink_t; +typedef struct hlinkset_s { + struct hlinkset_s *next; +} hlinkset_t; + +struct hashctx_s { + hlinkset_t *linksets; + hashlink_t *free_hashlinks; +}; + struct hashtab_s { size_t tab_size; unsigned int size_bits; @@ -60,38 +69,41 @@ struct hashtab_s { uintptr_t (*get_hash)(const void*,void*); const char *(*get_key)(const void*,void*); void (*free_ele)(void*,void*); - hashlink_t **hashlink_freelist; + hashctx_t *hashctx; hashlink_t *tab[1]; // variable size }; static hashlink_t * -new_hashlink (hashlink_t **free_hashlinks) +new_hashlink (hashctx_t *hctx) { hashlink_t *link; - if (!*free_hashlinks) { + if (!hctx->free_hashlinks) { int i; - if (!(*free_hashlinks = calloc (1024, sizeof (hashlink_t)))) - return 0; - for (i = 0, link = *free_hashlinks; i < 1023; i++, link++) + hlinkset_t *linkset = malloc (sizeof (hlinkset_t) + + 1024 * sizeof (hashlink_t)); + linkset->next = hctx->linksets; + hctx->linksets = linkset; + hctx->free_hashlinks = (hashlink_t *) &linkset[1]; + for (i = 0, link = hctx->free_hashlinks; i < 1023; i++, link++) link->next = link + 1; link->next = 0; } - link = *free_hashlinks; - *free_hashlinks = link->next; + link = hctx->free_hashlinks; + hctx->free_hashlinks = link->next; link->next = 0; return link; } static void -free_hashlink (hashlink_t *link, hashlink_t **free_hashlinks) +free_hashlink (hashlink_t *link, hashctx_t *hctx) { - link->next = *free_hashlinks; - *free_hashlinks = link; + link->next = hctx->free_hashlinks; + hctx->free_hashlinks = link; } -static hashlink_t *default_hashlink_freelist; +static hashctx_t *default_hashctx; VISIBLE uintptr_t Hash_String (const char *str) @@ -208,6 +220,23 @@ get_index (uintptr_t hash, size_t size, size_t bits) #endif } +static void +hash_shutdown (void *data) +{ + Hash_DelContext (default_hashctx); +} + +VISIBLE void +Hash_DelContext (hashctx_t *hashctx) +{ + while (hashctx->linksets) { + hlinkset_t *l = hashctx->linksets->next; + free (hashctx->linksets); + hashctx->linksets = l; + } + free (hashctx); +} + VISIBLE hashtab_t * Hash_NewTable (int tsize, const char *(*gk)(const void*,void*), void (*f)(void*,void*), void *ud, hashctx_t **hctx) @@ -220,9 +249,15 @@ Hash_NewTable (int tsize, const char *(*gk)(const void*,void*), tab->get_key = gk; tab->free_ele = f; if (!hctx) { - hctx = (hashctx_t **) &default_hashlink_freelist; + hctx = &default_hashctx; + if (!default_hashctx) { + Sys_RegisterShutdown (hash_shutdown, 0); + } } - tab->hashlink_freelist = (hashlink_t **) hctx; + if (!*hctx) { + *hctx = calloc (1, sizeof (hashctx_t)); + } + tab->hashctx = *hctx; while (tsize) { tab->size_bits++; @@ -259,7 +294,7 @@ Hash_FlushTable (hashtab_t *tab) hashlink_t *t = tab->tab[i]->next; void *data = tab->tab[i]->data; - free_hashlink (tab->tab[i], tab->hashlink_freelist); + free_hashlink (tab->tab[i], tab->hashctx); tab->tab[i] = t; if (tab->free_ele) tab->free_ele (data, tab->user_data); @@ -272,7 +307,7 @@ static int hash_add_element (hashtab_t *tab, uintptr_t h, void *ele) { size_t ind = get_index (h, tab->tab_size, tab->size_bits); - hashlink_t *lnk = new_hashlink (tab->hashlink_freelist); + hashlink_t *lnk = new_hashlink (tab->hashctx); if (!lnk) return -1; @@ -415,7 +450,7 @@ Hash_Del (hashtab_t *tab, const char *key) if (lnk->next) lnk->next->prev = lnk->prev; *lnk->prev = lnk->next; - free_hashlink (lnk, tab->hashlink_freelist); + free_hashlink (lnk, tab->hashctx); tab->num_ele--; return data; } @@ -438,7 +473,7 @@ Hash_DelElement (hashtab_t *tab, void *ele) if (lnk->next) lnk->next->prev = lnk->prev; *lnk->prev = lnk->next; - free_hashlink (lnk, tab->hashlink_freelist); + free_hashlink (lnk, tab->hashctx); tab->num_ele--; return data; } diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 2a4a98b76..2533ab677 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -42,6 +42,7 @@ #include "QF/cmd.h" #include "QF/cvar.h" #include "QF/gib.h" +#include "QF/hash.h" #include "QF/idparse.h" #include "QF/keys.h" #include "QF/progs.h" @@ -320,6 +321,8 @@ run_progs (void *data) PR_Shutdown (thread->pr); free (thread->pr); thread->pr = 0; + Hash_DelContext (thread->hashctx); + thread->hashctx = 0; return thread; } From 161ccc282ff8d7c89cbcf899ca1add166e9dabd5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 4 Mar 2023 02:23:37 +0900 Subject: [PATCH 3461/3664] [ruamoko] Unlink passage nodes when deleting Fixes a segfault on shutdown after the memory leak changes. --- libs/ruamoko/rua_gui.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index 3b404071b..8bd59ad46 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -84,6 +84,10 @@ passage_new (gui_resources_t *res) static void passage_free (gui_resources_t *res, rua_passage_t *passage) { + if (passage->next) { + passage->next->prev = passage->prev; + } + *passage->prev = passage->next; PR_RESFREE (res->passage_map, passage); } @@ -192,8 +196,7 @@ bi_gui_clear (progs_t *pr, void *_res) { gui_resources_t *res = _res; - rua_passage_t *psg; - for (psg = res->passages; psg; psg = psg->next) { + for (rua_passage_t *psg = res->passages; psg; psg = psg->next) { Passage_Delete (psg->passage); } res->passages = 0; From 795021e2293385f45c3a0e664a91bf088334e560 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 16:26:37 +0900 Subject: [PATCH 3462/3664] [util] Record allocated blocs for ALLOC Recording the blocks makes it possible to free them later. As a convenience, ALLOC_STATE declares the freelist and blocks vars needed by ALLOC. --- include/QF/alloc.h | 18 +++++++++++++++++- include/QF/set.h | 3 +++ libs/image/convert.c | 4 ++-- libs/ui/txtbuffer.c | 2 +- libs/util/quakefs.c | 4 ++-- libs/util/segtext.c | 4 ++-- libs/util/set.c | 6 +++++- libs/util/sys.c | 11 +++++++++-- libs/video/renderer/glsl/glsl_shader.c | 2 +- tools/qfcc/source/attribute.c | 2 +- tools/qfcc/source/dags.c | 6 +++--- tools/qfcc/source/debug.c | 2 +- tools/qfcc/source/def.c | 2 +- tools/qfcc/source/defspace.c | 4 ++-- tools/qfcc/source/expr.c | 2 +- tools/qfcc/source/expr_compound.c | 2 +- tools/qfcc/source/flow.c | 8 ++++---- tools/qfcc/source/function.c | 4 ++-- tools/qfcc/source/grab.c | 2 +- tools/qfcc/source/linker.c | 2 +- tools/qfcc/source/pragma.c | 2 +- tools/qfcc/source/reloc.c | 2 +- tools/qfcc/source/statements.c | 8 ++++---- tools/qfcc/source/symtab.c | 4 ++-- tools/qfcc/source/type.c | 2 +- tools/qfcc/source/value.c | 2 +- 26 files changed, 70 insertions(+), 40 deletions(-) diff --git a/include/QF/alloc.h b/include/QF/alloc.h index f67fe7176..a22ad78eb 100644 --- a/include/QF/alloc.h +++ b/include/QF/alloc.h @@ -34,6 +34,8 @@ #include #include +#include "QF/darray.h" + /** \defgroup alloc High-tide allocator. \ingroup utils */ @@ -43,7 +45,8 @@ /** High-tide structure allocator for use in linked lists. Using a free-list with the name of \c NAME_freelist, return a single - element. + element. Also, the allocated blocks are recorded in a DARRAY with the name + of \c NAME_blocks. The type of the element must be a structure with a field named \c next. When the free-list is empty, memory is claimed from the system in blocks. Elements may be returned to the pool by linking them into the free-list. @@ -65,12 +68,25 @@ for (i = 0; i < (s) - 1; i++) \ n##_freelist[i].next = &n##_freelist[i + 1];\ n##_freelist[i].next = 0; \ + DARRAY_APPEND (&n##_blocks, n##_freelist); \ } \ v = n##_freelist; \ n##_freelist = n##_freelist->next; \ memset (v, 0, sizeof (*v)); \ } while (0) +#define ALLOC_STATE(t,n) \ +static t *n##_freelist; \ +static struct DARRAY_TYPE(t *) n##_blocks = DARRAY_STATIC_INIT(8) + +#define ALLOC_FREE_BLOCKS(n) \ + do { \ + for (size_t i = 0; i < n##_blocks.size; i++) { \ + free (n##_blocks.a[i]); \ + } \ + DARRAY_CLEAR (&n##_blocks); \ + } while (0) + /** Free a block allocated by #ALLOC \param n The \c NAME portion of the \c NAME_freelist free-list. diff --git a/include/QF/set.h b/include/QF/set.h index e7d75e4f5..dafba428c 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -32,6 +32,7 @@ #define __QF_set_h #include "QF/qtypes.h" +#include "QF/darray.h" /** \defgroup set Set handling \ingroup utils @@ -116,6 +117,8 @@ typedef struct set_iter_s { typedef struct set_pool_s { set_t *set_freelist; set_iter_t *set_iter_freelist; + struct DARRAY_TYPE (set_t *) set_blocks; + struct DARRAY_TYPE (set_iter_t *) set_iter_blocks; } set_pool_t; void set_pool_init (set_pool_t *set_pool); diff --git a/libs/image/convert.c b/libs/image/convert.c index cc49d6759..df5829f92 100644 --- a/libs/image/convert.c +++ b/libs/image/convert.c @@ -47,8 +47,8 @@ typedef struct colcache_color_s { byte col; } colcache_color_t; -static colcache_t *colcache_freelist; -static colcache_color_t *colcache_color_freelist; +ALLOC_STATE (colcache_t, colcache); +ALLOC_STATE (colcache_color_t, colcache_color); static colcache_color_t * colcache_new_color (const byte *rgb, byte ind) diff --git a/libs/ui/txtbuffer.c b/libs/ui/txtbuffer.c index 36c82afd6..b4d7e11d2 100644 --- a/libs/ui/txtbuffer.c +++ b/libs/ui/txtbuffer.c @@ -43,7 +43,7 @@ #include "compat.h" -static txtbuffer_t *txtbuffers_freelist; +ALLOC_STATE (txtbuffer_t, txtbuffers); static char * txtbuffer_open_gap (txtbuffer_t *buffer, size_t offset, size_t length) diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 333af44e7..530fcb03b 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -186,8 +186,8 @@ typedef struct int_findfile_s { int fname_index; } int_findfile_t; -static searchpath_t *searchpaths_freelist; -static vpath_t *vpaths_freelist; +ALLOC_STATE (searchpath_t, searchpaths); +ALLOC_STATE (vpath_t, vpaths); static vpath_t *qfs_vpaths; //QFS diff --git a/libs/util/segtext.c b/libs/util/segtext.c index ffee78d77..d215cda30 100644 --- a/libs/util/segtext.c +++ b/libs/util/segtext.c @@ -38,8 +38,8 @@ #include "QF/qtypes.h" #include "QF/segtext.h" -static segchunk_t *chunks_freelist; -static segtext_t *texts_freelist; +ALLOC_STATE (segchunk_t, chunks); +ALLOC_STATE (segtext_t, texts); static segchunk_t * new_chunk (void) diff --git a/libs/util/set.c b/libs/util/set.c index 9b59172a1..0fe8fe2ec 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -45,7 +45,11 @@ #include "QF/mathlib.h" #include "QF/set.h" -static set_pool_t static_set_pool = {0, 0}; +static set_pool_t static_set_pool = { + 0, 0, + DARRAY_STATIC_INIT (8), + DARRAY_STATIC_INIT (8), +}; static set_iter_t * new_setiter (set_pool_t *set_pool) diff --git a/libs/util/sys.c b/libs/util/sys.c index d4d6f23d3..64c8100b4 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -564,9 +564,15 @@ VISIBLE void Sys_PushErrorHandler (sys_error_t func, void *data) { error_handler_t *eh; - ALLOC (16, error_handler_t, error_handler, eh); + if (error_handler_freelist) { + eh = error_handler_freelist; + } else { + eh = malloc (sizeof (error_handler_t)); + eh->next = 0; + } eh->func = func; eh->data = data; + error_handler_freelist = eh->next; eh->next = error_handler; error_handler = eh; } @@ -581,7 +587,8 @@ Sys_PopErrorHandler (void) } eh = error_handler; error_handler = eh->next; - FREE (error_handler, eh); + eh->next = error_handler_freelist; + error_handler_freelist = eh; } diff --git a/libs/video/renderer/glsl/glsl_shader.c b/libs/video/renderer/glsl/glsl_shader.c index d7eace17a..535d63413 100644 --- a/libs/video/renderer/glsl/glsl_shader.c +++ b/libs/video/renderer/glsl/glsl_shader.c @@ -48,7 +48,7 @@ typedef struct glsl_effect_s { } glsl_effect_t; static hashtab_t *effect_tab; -static glsl_effect_t *effects_freelist; +ALLOC_STATE (glsl_effect_t, effects); static glsl_effect_t * new_effect (void) diff --git a/tools/qfcc/source/attribute.c b/tools/qfcc/source/attribute.c index b821124c1..a1cbe443d 100644 --- a/tools/qfcc/source/attribute.c +++ b/tools/qfcc/source/attribute.c @@ -38,7 +38,7 @@ #include "tools/qfcc/include/expr.h" #include "tools/qfcc/include/strpool.h" -static attribute_t *attributes_freelist; +ALLOC_STATE (attribute_t, attributes); attribute_t *new_attribute(const char *name, expr_t *value) { diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 1c3ad201f..9681587bc 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -60,9 +60,9 @@ #include "tools/qfcc/include/type.h" #include "tools/qfcc/include/value.h" -static daglabel_t *labels_freelist; -static dagnode_t *nodes_freelist; -static dag_t *dags_freelist; +ALLOC_STATE (daglabel_t, labels); +ALLOC_STATE (dagnode_t, nodes); +ALLOC_STATE (dag_t, dags); static daglabel_t *daglabel_chain; diff --git a/tools/qfcc/source/debug.c b/tools/qfcc/source/debug.c index 4afff69ee..f38952315 100644 --- a/tools/qfcc/source/debug.c +++ b/tools/qfcc/source/debug.c @@ -58,7 +58,7 @@ int lineno_base; -static srcline_t *srclines_freelist; +ALLOC_STATE (srcline_t, srclines); static void push_source_file (void) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index b745f2da3..55f470c8d 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -62,7 +62,7 @@ #include "tools/qfcc/include/type.h" #include "tools/qfcc/include/value.h" -static def_t *defs_freelist; +ALLOC_STATE (def_t, defs); static void set_storage_bits (def_t *def, storage_class_t storage) diff --git a/tools/qfcc/source/defspace.c b/tools/qfcc/source/defspace.c index 7858db746..97333dae6 100644 --- a/tools/qfcc/source/defspace.c +++ b/tools/qfcc/source/defspace.c @@ -54,8 +54,8 @@ typedef struct locref_s { int size; } locref_t; -static defspace_t *spaces_freelist; -static locref_t *locrefs_freelist; +ALLOC_STATE (defspace_t, spaces); +ALLOC_STATE (locref_t, locrefs); static locref_t * new_locref (int ofs, int size, locref_t *next) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 1fc1249d3..dbbee0ff8 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -65,7 +65,7 @@ #include "tools/qfcc/source/qc-parse.h" -static expr_t *exprs_freelist; +ALLOC_STATE (expr_t, exprs); void convert_name (expr_t *e) diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c index e8b81747d..2ba6f489a 100644 --- a/tools/qfcc/source/expr_compound.c +++ b/tools/qfcc/source/expr_compound.c @@ -51,7 +51,7 @@ #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" -static element_t *elements_freelist; +ALLOC_STATE (element_t, elements); element_t * new_element (expr_t *expr, symbol_t *symbol) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 43768096a..a8c94c952 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -80,10 +80,10 @@ static const int num_flow_params = sizeof(flow_params)/sizeof(flow_params[0]); /** \name Flow analysis memory management */ ///@{ -static flowvar_t *vars_freelist; ///< flowvar pool -static flowloop_t *loops_freelist; ///< flow loop pool -static flownode_t *nodes_freelist; ///< flow node pool -static flowgraph_t *graphs_freelist; ///< flow graph pool +ALLOC_STATE (flowvar_t, vars); ///< flowvar pool +ALLOC_STATE (flowloop_t, loops); ///< flow loop pool +ALLOC_STATE (flownode_t, nodes); ///< flow node pool +ALLOC_STATE (flowgraph_t, graphs); ///< flow graph pool /** Allocate a new flow var. * diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 296ecf9fe..45b1311eb 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -66,8 +66,8 @@ #include "tools/qfcc/include/type.h" #include "tools/qfcc/include/value.h" -static param_t *params_freelist; -static function_t *functions_freelist; +ALLOC_STATE (param_t, params); +ALLOC_STATE (function_t, functions); static hashtab_t *overloaded_functions; static hashtab_t *function_map; diff --git a/tools/qfcc/source/grab.c b/tools/qfcc/source/grab.c index 0d59c1217..7cad9cc62 100644 --- a/tools/qfcc/source/grab.c +++ b/tools/qfcc/source/grab.c @@ -64,7 +64,7 @@ typedef struct frame_s { int num; } frame_t; -static frame_t *frames_freelist; +ALLOC_STATE (frame_t, frames); static frame_t *frame_list; static frame_t **frame_tail = &frame_list; diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index e058f190d..8d04f4ef5 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -131,7 +131,7 @@ static builtin_sym_t builtin_symbols[] __attribute__ ((used)) = { static const unsigned num_builtins = sizeof (builtin_symbols) / sizeof (builtin_symbols[0]); -static defref_t *defrefs_freelist; +ALLOC_STATE (defref_t, defrefs); static hashtab_t *extern_data_defs; static hashtab_t *defined_data_defs; diff --git a/tools/qfcc/source/pragma.c b/tools/qfcc/source/pragma.c index 2ee208ca5..af6897c00 100644 --- a/tools/qfcc/source/pragma.c +++ b/tools/qfcc/source/pragma.c @@ -57,7 +57,7 @@ typedef struct pragma_arg_s { const char *arg; } pragma_arg_t; -static pragma_arg_t *pragma_args_freelist; +ALLOC_STATE (pragma_arg_t, pragma_args); static pragma_arg_t *pragma_args; static pragma_arg_t **pragma_args_tail = &pragma_args; diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index 252b8e404..eec081153 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -51,7 +51,7 @@ #include "tools/qfcc/include/qfcc.h" #include "tools/qfcc/include/reloc.h" -static reloc_t *refs_freelist; +ALLOC_STATE (reloc_t, refs); const char * const reloc_name[] = { "rel_none", diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index a3b0a64fb..833545c57 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -218,10 +218,10 @@ print_statement (statement_t *s) print_operand_chain ("kill", s->kill); } -static pseudoop_t *pseudoops_freelist; -static sblock_t *sblocks_freelist; -static statement_t *statements_freelist; -static operand_t *operands_freelist; +ALLOC_STATE (pseudoop_t, pseudoops); +ALLOC_STATE (sblock_t, sblocks); +ALLOC_STATE (statement_t, statements); +ALLOC_STATE (operand_t, operands); sblock_t * new_sblock (void) diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 6470d2682..4ad506955 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -49,8 +49,8 @@ #include "tools/qfcc/include/symtab.h" #include "tools/qfcc/include/type.h" -static symtab_t *symtabs_freelist; -static symbol_t *symbols_freelist; +ALLOC_STATE (symtab_t, symtabs); +ALLOC_STATE (symbol_t, symbols); static const char * const sy_type_names[] = { "sy_name", diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 99916d604..2894c71d3 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -161,7 +161,7 @@ int type_cast_map[ev_type_count] = { //[ev_bool64] = 7, }; -static type_t *types_freelist; +ALLOC_STATE (type_t, types); etype_t low_level_type (type_t *type) diff --git a/tools/qfcc/source/value.c b/tools/qfcc/source/value.c index b4633df74..14e891827 100644 --- a/tools/qfcc/source/value.c +++ b/tools/qfcc/source/value.c @@ -80,7 +80,7 @@ typedef struct { } immediate_t; static hashtab_t *value_table; -static ex_value_t *values_freelist; +ALLOC_STATE (ex_value_t, values); //FIXME this (to setup_value_progs) should be in its own file and more //general (good for constant folding, too, and maybe some others). From f9e442d323ad1c08a25d7bbc843f82efb134e8db Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 16:41:13 +0900 Subject: [PATCH 3463/3664] [util] Make sys globals all thread-local This was mainly for the shutdown functions, thus allowing Sys_Shutdown (and Sys_RegisterShutdown) to be per-thread, but it seemed like a good idea to make everything per-thread. --- libs/util/sys.c | 65 ++++++++++++++++++------------------ ruamoko/qwaq/builtins/main.c | 1 + 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/libs/util/sys.c b/libs/util/sys.c index 64c8100b4..6902525c7 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -138,8 +138,8 @@ static cvar_t sys_sleep_cvar = { int sys_checksum; -static sys_printf_t sys_std_printf_function = Sys_StdPrintf; -static sys_printf_t sys_err_printf_function = Sys_ErrPrintf; +static __thread sys_printf_t sys_std_printf_function = Sys_StdPrintf; +static __thread sys_printf_t sys_err_printf_function = Sys_ErrPrintf; typedef struct shutdown_list_s { struct shutdown_list_s *next; @@ -153,10 +153,10 @@ typedef struct error_handler_s { void *data; } error_handler_t; -static shutdown_list_t *shutdown_list; +static __thread shutdown_list_t *shutdown_list; -static error_handler_t *error_handler_freelist; -static error_handler_t *error_handler; +static __thread error_handler_t *error_handler_freelist; +static __thread error_handler_t *error_handler; #ifndef _WIN32 static int do_stdin = 1; @@ -301,26 +301,26 @@ Sys_SetErrPrintf (sys_printf_t func) return prev; } +static __thread dstring_t *sys_print_msg; void Sys_Print (FILE *stream, const char *fmt, va_list args) { - static dstring_t *msg; unsigned char *p; - if (!msg) - msg = dstring_new (); + if (!sys_print_msg) + sys_print_msg = dstring_new (); - dvsprintf (msg, fmt, args); + dvsprintf (sys_print_msg, fmt, args); if (stream == stderr) { #ifdef _WIN32 - MessageBox (NULL, msg->str, "Fatal Error", 0 /* MB_OK */ ); + MessageBox (NULL, sys_print_msg->str, "Fatal Error", 0 /* MB_OK */ ); #endif fputs ("Fatal Error: ", stream); } /* translate to ASCII instead of printing [xx] --KB */ - for (p = (unsigned char *) msg->str; *p; p++) + for (p = (unsigned char *) sys_print_msg->str; *p; p++) putc (sys_char_map[*p], stream); if (stream == stderr) { @@ -795,21 +795,22 @@ Sys_ProcessorCount (void) return cpus; } +static __thread dstring_t *sys_debuglog_data; VISIBLE void Sys_DebugLog (const char *file, const char *fmt, ...) { va_list args; - static dstring_t *data; int fd; - if (!data) - data = dstring_newstr (); + if (!sys_debuglog_data) + sys_debuglog_data = dstring_newstr (); va_start (args, fmt); - dvsprintf (data, fmt, args); + dvsprintf (sys_debuglog_data, fmt, args); va_end (args); if ((fd = open (file, O_WRONLY | O_CREAT | O_APPEND, 0644)) >= 0) { - if (write (fd, data->str, data->size - 1) != (ssize_t) (data->size - 1)) + if (write (fd, sys_debuglog_data->str, sys_debuglog_data->size - 1) + != (ssize_t) (sys_debuglog_data->size - 1)) Sys_Printf ("Error writing %s: %s\n", file, strerror(errno)); close (fd); } @@ -948,9 +949,9 @@ Sys_ConsoleInput (void) } #ifdef _WIN32 -static jmp_buf aiee_abort; +static __thread jmp_buf aiee_abort; #else -static sigjmp_buf aiee_abort; +static __thread sigjmp_buf aiee_abort; #endif typedef struct sh_stack_s { @@ -959,10 +960,10 @@ typedef struct sh_stack_s { void *data; } sh_stack_t; -static sh_stack_t *sh_stack; -static sh_stack_t *free_sh; -static int (*signal_hook)(int,void*); -static void *signal_hook_data; +static __thread sh_stack_t *sh_stack; +static __thread sh_stack_t *free_sh; +static __thread int (*signal_hook)(int,void*); +static __thread void *signal_hook_data; VISIBLE void Sys_PushSignalHook (int (*hook)(int, void *), void *data) @@ -1057,16 +1058,16 @@ hook_signlas (void) } #else -static struct sigaction save_hup; -static struct sigaction save_quit; -static struct sigaction save_trap; -static struct sigaction save_iot; -static struct sigaction save_bus; -static struct sigaction save_int; -static struct sigaction save_ill; -static struct sigaction save_segv; -static struct sigaction save_term; -static struct sigaction save_fpe; +static __thread struct sigaction save_hup; +static __thread struct sigaction save_quit; +static __thread struct sigaction save_trap; +static __thread struct sigaction save_iot; +static __thread struct sigaction save_bus; +static __thread struct sigaction save_int; +static __thread struct sigaction save_ill; +static __thread struct sigaction save_segv; +static __thread struct sigaction save_term; +static __thread struct sigaction save_fpe; static void signal_handler (int sig, siginfo_t *info, void *ucontext) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 2533ab677..090141414 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -323,6 +323,7 @@ run_progs (void *data) thread->pr = 0; Hash_DelContext (thread->hashctx); thread->hashctx = 0; + Sys_Shutdown (); return thread; } From 9193a92a811a424f00864253d14c79f0a3c6a3d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 16:44:19 +0900 Subject: [PATCH 3464/3664] [util] Make Hash_DelContext null-safe --- libs/util/hash.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/util/hash.c b/libs/util/hash.c index d88f71aec..1fb9cb643 100644 --- a/libs/util/hash.c +++ b/libs/util/hash.c @@ -229,6 +229,9 @@ hash_shutdown (void *data) VISIBLE void Hash_DelContext (hashctx_t *hashctx) { + if (!hashctx) { + return; + } while (hashctx->linksets) { hlinkset_t *l = hashctx->linksets->next; free (hashctx->linksets); From e2640d51a7d1465ec7112975be826c81e2334437 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 16:46:06 +0900 Subject: [PATCH 3465/3664] [gl_stub] Make some gen functions generate indices This makes gl_stub usable with valgrind (otherwise, the returned indices are uninitialized). --- tools/gl_stub/gls_norm.c | 14 ++++++++++++++ tools/gl_stub/gls_trace.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/tools/gl_stub/gls_norm.c b/tools/gl_stub/gls_norm.c index 0a0b55d55..75bf94ba8 100644 --- a/tools/gl_stub/gls_norm.c +++ b/tools/gl_stub/gls_norm.c @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -230,16 +232,19 @@ norm_glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderb void norm_glGenBuffers (GLsizei n, GLuint* buffers) { + memset (buffers, 0, n * sizeof (GLuint)); } void norm_glGenFramebuffers (GLsizei n, GLuint* framebuffers) { + memset (framebuffers, 0, n * sizeof (GLuint)); } void norm_glGenRenderbuffers (GLsizei n, GLuint* renderbuffers) { + memset (renderbuffers, 0, n * sizeof (GLuint)); } void @@ -281,11 +286,15 @@ norm_glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GL void norm_glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) { + if (bufsize > 0) { + *infolog = 0; + } } void norm_glGetProgramiv (GLuint program, GLenum pname, GLint* params) { + *params = 0; } void @@ -296,6 +305,9 @@ norm_glGetRenderbufferParameteriv (GLuint shader, GLenum pname, GLint* params) void norm_glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) { + if (bufsize > 0) { + *infolog = 0; + } } void @@ -311,6 +323,7 @@ norm_glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* void norm_glGetShaderiv (GLuint shader, GLenum pname, GLint* params) { + *params = 0; } int @@ -1111,6 +1124,7 @@ norm_glGenLists (GLsizei range) void norm_glGenTextures (GLsizei n, GLuint * textures) { + memset (textures, 0, n * sizeof (GLuint)); } void diff --git a/tools/gl_stub/gls_trace.c b/tools/gl_stub/gls_trace.c index bdc361249..e2d904a56 100644 --- a/tools/gl_stub/gls_trace.c +++ b/tools/gl_stub/gls_trace.c @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -260,18 +262,21 @@ void trace_glGenBuffers (GLsizei n, GLuint* buffers) { TRACE; + memset (buffers, 0, n * sizeof (GLuint)); } void trace_glGenFramebuffers (GLsizei n, GLuint* framebuffers) { TRACE; + memset (framebuffers, 0, n * sizeof (GLuint)); } void trace_glGenRenderbuffers (GLsizei n, GLuint* renderbuffers) { TRACE; + memset (renderbuffers, 0, n * sizeof (GLuint)); } void @@ -321,12 +326,16 @@ void trace_glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) { TRACE; + if (bufsize > 0) { + *infolog = 0; + } } void trace_glGetProgramiv (GLuint program, GLenum pname, GLint* params) { TRACE; + *params = 0; } void @@ -339,6 +348,9 @@ void trace_glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) { TRACE; + if (bufsize > 0) { + *infolog = 0; + } } void @@ -357,6 +369,7 @@ void trace_glGetShaderiv (GLuint shader, GLenum pname, GLint* params) { TRACE; + *params = 0; } int @@ -1312,6 +1325,7 @@ void trace_glGenTextures (GLsizei n, GLuint * textures) { TRACE; + memset (textures, 0, n * sizeof (GLuint)); } void From 9ad4f5734883ccc83921839f8e3c29b4f201e2d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 16:56:09 +0900 Subject: [PATCH 3466/3664] [glsl] Fix a pile of memory leaks For the most part harmless, but fixing the leaks has been uncovering bugs. --- include/QF/GLSL/qf_bsp.h | 1 + include/QF/GLSL/qf_lightmap.h | 2 +- include/QF/GLSL/qf_particles.h | 1 + include/QF/GLSL/qf_vid.h | 2 ++ include/QF/scene/entity.h | 1 + include/QF/screen.h | 1 + include/mod_internal.h | 1 + include/r_internal.h | 1 + include/vid_gl.h | 1 + include/vid_internal.h | 1 + libs/models/iqm/glsl_model_iqm.c | 1 + libs/models/skin.c | 6 ++++++ libs/scene/efrag.c | 10 ++++++++++ libs/video/renderer/glsl/glsl_bsp.c | 7 +++++++ libs/video/renderer/glsl/glsl_draw.c | 20 ++++++++++++++++++++ libs/video/renderer/glsl/glsl_lightmap.c | 9 +++++++++ libs/video/renderer/glsl/glsl_main.c | 12 ++++++++++++ libs/video/renderer/glsl/glsl_particles.c | 7 +++++++ libs/video/renderer/glsl/glsl_shader.c | 17 ++++++++++++++++- libs/video/renderer/glsl/vid_common_glsl.c | 6 ++++++ libs/video/renderer/r_init.c | 2 ++ libs/video/renderer/r_light.c | 2 +- libs/video/renderer/r_progs.c | 2 ++ libs/video/renderer/r_screen.c | 6 ++++++ libs/video/renderer/vid_render_glsl.c | 4 ++++ libs/video/targets/context_x11.c | 2 +- libs/video/targets/vid.c | 19 +++++++++++++++++++ libs/video/targets/vid_x11.c | 7 +++---- libs/video/targets/vid_x11_gl.c | 8 ++++++++ 29 files changed, 151 insertions(+), 8 deletions(-) diff --git a/include/QF/GLSL/qf_bsp.h b/include/QF/GLSL/qf_bsp.h index 582c0b025..c9648962c 100644 --- a/include/QF/GLSL/qf_bsp.h +++ b/include/QF/GLSL/qf_bsp.h @@ -73,6 +73,7 @@ void glsl_R_DrawWaterSurfaces (void); void glsl_R_RegisterTextures (struct model_s **models, int num_models); void glsl_R_BuildDisplayLists (struct model_s **models, int num_models); void glsl_R_InitBsp (void); +void glsl_R_ShutdownBsp (void); void glsl_R_LoadSkys (const char *sky); #endif//__QF_GLSL_qf_bsp_h diff --git a/include/QF/GLSL/qf_lightmap.h b/include/QF/GLSL/qf_lightmap.h index 2d2a22af2..0fbc62bd7 100644 --- a/include/QF/GLSL/qf_lightmap.h +++ b/include/QF/GLSL/qf_lightmap.h @@ -33,7 +33,7 @@ #define BLOCK_WIDTH 64 #define BLOCK_HEIGHT 64 -void glsl_lightmap_init (void); +void glsl_Lightmap_Shutdown (void); struct transform_s; void glsl_R_BuildLightmaps (struct model_s **models, int num_models); void glsl_R_CalcLightmaps (void); diff --git a/include/QF/GLSL/qf_particles.h b/include/QF/GLSL/qf_particles.h index 30d016d8e..a6a4111f8 100644 --- a/include/QF/GLSL/qf_particles.h +++ b/include/QF/GLSL/qf_particles.h @@ -42,5 +42,6 @@ struct psystem_s; void glsl_R_DrawParticles (struct psystem_s *psystem); void glsl_R_Particles_Init_Cvars (void); void glsl_R_InitParticles (void); +void glsl_R_ShutdownParticles (void); #endif//__QF_GLSL_qf_particles_h diff --git a/include/QF/GLSL/qf_vid.h b/include/QF/GLSL/qf_vid.h index 57f6e5313..d88dc234d 100644 --- a/include/QF/GLSL/qf_vid.h +++ b/include/QF/GLSL/qf_vid.h @@ -46,6 +46,7 @@ extern int glsl_palette; extern int glsl_colormap; void GLSL_Init_Common (void); +void GLSL_Shutdown_Common (void); int GLSL_CompileShader (const char *name, const shader_t *shader, int type); int GLSL_LinkProgram (const char *name, int vert, int frag); @@ -62,6 +63,7 @@ void GLSL_DumpAttribArrays (void); \return 0 for failure, 1 for success. */ int GLSL_RegisterEffect (const char *name, const char *src); +void GLSL_ShaderShutdown (void); /* Build a shader program script from a list of effect keys. diff --git a/include/QF/scene/entity.h b/include/QF/scene/entity.h index f0453e3d8..e2bc00ffa 100644 --- a/include/QF/scene/entity.h +++ b/include/QF/scene/entity.h @@ -151,6 +151,7 @@ Entity_Transform (entity_t ent) struct mod_brush_s; void R_AddEfrags (struct mod_brush_s *, entity_t ent); +void R_ShutdownEfrags (void); void R_ClearEfragChain (efrag_t *ef); ///@} diff --git a/include/QF/screen.h b/include/QF/screen.h index 0e4b8b548..255d371ae 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -34,6 +34,7 @@ struct transform_s; struct tex_s; void SCR_Init (void); +void SCR_Shutdown (void); typedef void (*SCR_Func)(void); // scr_funcs is a null terminated array diff --git a/include/mod_internal.h b/include/mod_internal.h index b809426fd..615b12e64 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -105,6 +105,7 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer, void Mod_LoadSpriteModel (model_t *mod, void *buffer); void Skin_Init (void); +void Skin_Shutdown (void); void Skin_Free (skin_t *skin); skin_t *Skin_SetColormap (skin_t *skin, int cmap); skin_t *Skin_SetSkin (skin_t *skin, int cmap, const char *skinname); diff --git a/include/r_internal.h b/include/r_internal.h index 0124a14d2..1c2c47f5a 100644 --- a/include/r_internal.h +++ b/include/r_internal.h @@ -29,6 +29,7 @@ void R_LineGraph (int x, int y, int *h_vals, int count, int height); void gl_R_Init (void); void glsl_R_Init (void); +void glsl_R_Shutdown (void); void sw_R_Init (void); void R_RenderFrame (SCR_Func *scr_funcs); void R_Init_Cvars (void); diff --git a/include/vid_gl.h b/include/vid_gl.h index c073837bc..e1bd68d2a 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -9,6 +9,7 @@ typedef struct GL_context *GL_context; typedef struct gl_ctx_s { GL_context context; void (*load_gl) (void); + void (*unload_gl) (struct gl_ctx_s *ctx); void (*choose_visual) (struct gl_ctx_s *ctx); void (*create_context) (struct gl_ctx_s *ctx, int core); void (*init_gl) (void); diff --git a/include/vid_internal.h b/include/vid_internal.h index 967c4eacc..dc9ca3177 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -6,6 +6,7 @@ typedef struct vid_system_s { void (*init) (byte *palette, byte *colormap); + void (*shutdown) (void); void (*set_palette) (byte *palette, byte *colormap); void (*init_cvars) (void); void (*update_fullscreen) (int fullscreen); diff --git a/libs/models/iqm/glsl_model_iqm.c b/libs/models/iqm/glsl_model_iqm.c index c8a82a112..9f7a75ee6 100644 --- a/libs/models/iqm/glsl_model_iqm.c +++ b/libs/models/iqm/glsl_model_iqm.c @@ -85,6 +85,7 @@ glsl_iqm_clear (model_t *mod, void *data) GLSL_ReleaseTexture (glsl->textures[i]); GLSL_ReleaseTexture (glsl->normmaps[i]); } + free (glsl->textures); free (glsl); Mod_FreeIQM (iqm); } diff --git a/libs/models/skin.c b/libs/models/skin.c index 0f1e1f7c9..93be64571 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -255,6 +255,12 @@ Skin_Init (void) m_funcs->Skin_InitTranslations (); } +void +Skin_Shutdown (void) +{ + Hash_DelTable (skin_cache); +} + VISIBLE int Skin_CalcTopColors (byte *out, const byte *in, size_t pixels, int stride) { diff --git a/libs/scene/efrag.c b/libs/scene/efrag.c index 898dd2c9b..41dec48b3 100644 --- a/libs/scene/efrag.c +++ b/libs/scene/efrag.c @@ -95,6 +95,16 @@ R_ClearEfrags (void) } } +void +R_ShutdownEfrags (void) +{ + while (efrag_list) { + t_efrag_list *efl = efrag_list->next; + free (efrag_list); + efrag_list = efl; + } +} + void R_ClearEfragChain (efrag_t *ef) { diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index e6aaf5ed5..1ebc39b59 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -1350,6 +1350,13 @@ glsl_R_InitBsp (void) GLSL_FreeShader (frag_shader); } +void +glsl_R_ShutdownBsp (void) +{ + free (r_texture_chains); + r_texture_chains = 0; +} + static inline __attribute__((const)) int is_pow2 (unsigned x) { diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 73a9b661e..1ee895fd7 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -483,6 +483,26 @@ glsl_Draw_Init (void) Cvar_Register (&glsl_conback_texnum_cvar, 0, 0); } +void +glsl_Draw_Shutdown (void) +{ + pic_free (conchars); + pic_free (crosshair_pic); + if (backtile_pic != white_pic) { + pic_free (backtile_pic); + } + pic_free (white_pic); + + dstring_delete (draw_queue); + dstring_delete (line_queue); + dstring_delete (glyph_queue); + + Hash_DelTable (pic_cache); + + GLSL_DestroyScrap (draw_scrap); + DARRAY_CLEAR (&glsl_fonts); +} + static inline void queue_character (int x, int y, byte chr) { diff --git a/libs/video/renderer/glsl/glsl_lightmap.c b/libs/video/renderer/glsl/glsl_lightmap.c index 30522a264..d324626ea 100644 --- a/libs/video/renderer/glsl/glsl_lightmap.c +++ b/libs/video/renderer/glsl/glsl_lightmap.c @@ -264,3 +264,12 @@ glsl_R_FlushLightmaps (void) { GLSL_ScrapFlush (light_scrap); } + +void +glsl_Lightmap_Shutdown (void) +{ + if (light_scrap) { + GLSL_DestroyScrap (light_scrap); + } + free (blocklights); +} diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index dec092b1c..e5128a229 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -191,6 +191,18 @@ glsl_R_Init (void) Skin_Init (); } +void +glsl_R_Shutdown (void) +{ + Skin_Shutdown(); + + glsl_R_ShutdownParticles (); + glsl_Lightmap_Shutdown (); + glsl_R_ShutdownBsp (); + SCR_Shutdown (); + glsl_Draw_Shutdown (); +} + void glsl_R_NewScene (scene_t *scene) { diff --git a/libs/video/renderer/glsl/glsl_particles.c b/libs/video/renderer/glsl/glsl_particles.c index fd1993bee..cf47429a4 100644 --- a/libs/video/renderer/glsl/glsl_particles.c +++ b/libs/video/renderer/glsl/glsl_particles.c @@ -162,6 +162,13 @@ glsl_particles_f (void *data, const cvar_t *cvar) alloc_arrays (&r_psystem);//FIXME } +void +glsl_R_ShutdownParticles (void) +{ + free (particleVertexArray); + free (pVAindices); +} + void glsl_R_InitParticles (void) { diff --git a/libs/video/renderer/glsl/glsl_shader.c b/libs/video/renderer/glsl/glsl_shader.c index 535d63413..251a93882 100644 --- a/libs/video/renderer/glsl/glsl_shader.c +++ b/libs/video/renderer/glsl/glsl_shader.c @@ -65,6 +65,21 @@ effect_get_key (const void *e, void *unused) return effect->name; } +static void +effect_free (void *e, void *unused) +{ + glsl_effect_t *effect = e; + free ((char *) effect->name); + Segtext_delete (effect->text); +} + +void +GLSL_ShaderShutdown (void) +{ + Hash_DelTable (effect_tab); + ALLOC_FREE_BLOCKS (effects); +} + int GLSL_RegisterEffect (const char *name, const char *src) { @@ -72,7 +87,7 @@ GLSL_RegisterEffect (const char *name, const char *src) segtext_t *text; if (!effect_tab) - effect_tab = Hash_NewTable (61, effect_get_key, 0, 0, 0); + effect_tab = Hash_NewTable (61, effect_get_key, effect_free, 0, 0); if (Hash_Find (effect_tab, name)) { Sys_Printf ("WARNING: ignoring duplicate '%s' effect\n", name); diff --git a/libs/video/renderer/glsl/vid_common_glsl.c b/libs/video/renderer/glsl/vid_common_glsl.c index 71e516cec..2fd29fc86 100644 --- a/libs/video/renderer/glsl/vid_common_glsl.c +++ b/libs/video/renderer/glsl/vid_common_glsl.c @@ -142,6 +142,12 @@ GLSL_SetPalette (void *data, const byte *palette) free (pal); } +void +GLSL_Shutdown_Common (void) +{ + GLSL_ShaderShutdown (); +} + void GLSL_Init_Common (void) { diff --git a/libs/video/renderer/r_init.c b/libs/video/renderer/r_init.c index 4a2f2d89a..ea4f7b353 100644 --- a/libs/video/renderer/r_init.c +++ b/libs/video/renderer/r_init.c @@ -76,6 +76,8 @@ static U void (*const r_scrapdelete)(rscrap_t *) = R_ScrapDelete; static void R_shutdown (void *data) { + R_ShutdownEfrags (); + R_MaxDlightsCheck (0); // frees memory PI_UnloadPlugin (vidrendmodule); } diff --git a/libs/video/renderer/r_light.c b/libs/video/renderer/r_light.c index 6875c8cbb..1b9cae06c 100644 --- a/libs/video/renderer/r_light.c +++ b/libs/video/renderer/r_light.c @@ -114,7 +114,7 @@ R_MaxDlightsCheck (int max_dlights) if (r_dlights) free (r_dlights); - r_dlights=0; + r_dlights = 0; if (r_maxdlights) r_dlights = (dlight_t *) calloc (r_maxdlights, sizeof (dlight_t)); diff --git a/libs/video/renderer/r_progs.c b/libs/video/renderer/r_progs.c index 4a295e4d8..cd065d3f7 100644 --- a/libs/video/renderer/r_progs.c +++ b/libs/video/renderer/r_progs.c @@ -491,6 +491,8 @@ bi_draw_destroy (progs_t *pr, void *_res) { draw_resources_t *res = (draw_resources_t *) _res; Hash_DelTable (res->pic_hash); + PR_RESDELMAP (res->qpic_map); + PR_RESDELMAP (res->charbuff_map); free (res); } diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index fbdc17611..5c900a8f0 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -475,6 +475,12 @@ SCR_Init (void) update_vrect (); } +void +SCR_Shutdown (void) +{ + EntQueue_Delete (r_ent_queue); +} + void SCR_NewScene (scene_t *scene) { diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index e299883f6..d7c9120b6 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -112,6 +112,10 @@ glsl_vid_render_init (void) static void glsl_vid_render_shutdown (void) { + glsl_R_Shutdown (); + GLSL_Shutdown_Common (); + + glsl_ctx->unload_gl (glsl_ctx); } static unsigned int GLErr_InvalidEnum; diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 93fac7372..1bd5f994d 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -342,8 +342,8 @@ X11_CreateNullCursor (void) return; cursormask = XCreatePixmap (x_disp, x_root, 1, 1, 1); - xgc.function = GXclear; + xgc.function = GXclear; gc = XCreateGC (x_disp, cursormask, GCFunction, &xgc); XFillRectangle (x_disp, cursormask, gc, 0, 0, 1, 1); diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index b413f224f..cca24b2af 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -316,9 +316,28 @@ VID_OnVidResize_RemoveListener (viddef_listener_t listener, void *data) } } +static void +VID_shutdown (void *data) +{ + if (vid_system.shutdown) { + vid_system.shutdown (); + } + free ((char *) vid_width_cvar.default_value); + free ((char *) vid_height_cvar.default_value); + free (viddef.gammatable); + free (viddef.palette); + free (viddef.palette32); + + DARRAY_CLEAR (viddef.onPaletteChanged); + DARRAY_CLEAR (viddef.onVidResize); + free (viddef.onPaletteChanged); + free (viddef.onVidResize); +} + VISIBLE void VID_Init (byte *palette, byte *colormap) { + Sys_RegisterShutdown (VID_shutdown, 0); vid_system.init (palette, colormap); } diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 324340270..be2449a28 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -82,9 +82,9 @@ D_EndDirectRect (int x, int y, int width, int height) } static void -VID_shutdown (void *data) +X11_VID_Shutdown (void) { - Sys_MaskPrintf (SYS_vid, "VID_shutdown\n"); + Sys_MaskPrintf (SYS_vid, "X11_VID_shutdown\n"); X11_CloseDisplay (); } @@ -109,8 +109,6 @@ X11_VID_SetPalette (byte *palette, byte *colormap) static void X11_VID_Init (byte *palette, byte *colormap) { - Sys_RegisterShutdown (VID_shutdown, 0); - vid_internal.gl_context = X11_GL_Context; vid_internal.sw_context = X11_SW_Context; #ifdef HAVE_VULKAN @@ -153,6 +151,7 @@ X11_VID_Init_Cvars (void) vid_system_t vid_system = { .init = X11_VID_Init, + .shutdown = X11_VID_Shutdown, .init_cvars = X11_VID_Init_Cvars, .update_fullscreen = X11_UpdateFullscreen, .set_palette = X11_VID_SetPalette, diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index 8679479a0..1da4b6c6c 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -248,11 +248,19 @@ glx_load_gl (void) qfglFinish = QFGL_ProcAddress ("glFinish", true); } +static void +glx_unload_gl (gl_ctx_t *ctx) +{ + dlclose (libgl_handle); + free (ctx); +} + gl_ctx_t * X11_GL_Context (void) { gl_ctx_t *ctx = calloc (1, sizeof (gl_ctx_t)); ctx->load_gl = glx_load_gl; + ctx->unload_gl = glx_unload_gl; ctx->choose_visual = glx_choose_visual; ctx->create_context = glx_create_context; ctx->get_proc_address = QFGL_ProcAddress; From 13f8f2b66b624268666ee868e8c1ca88e729f4d9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:04:52 +0900 Subject: [PATCH 3467/3664] [util] Fix a pile of memory leaks Some were actually legitimate (in that they'd cause problems in a long running game). --- libs/util/idparse.c | 15 +++++++ libs/util/qargs.c | 13 ++++++ libs/util/quakefs.c | 94 +++++++++++++++++++++++---------------- libs/util/segtext.c | 13 ++++++ libs/util/set.c | 13 ++++++ libs/util/sys.c | 58 +++++++++++++++++------- libs/util/test/test-seg.c | 3 ++ libs/util/va.c | 24 ++++++++-- 8 files changed, 175 insertions(+), 58 deletions(-) diff --git a/libs/util/idparse.c b/libs/util/idparse.c index 440f74029..24aac7c3f 100644 --- a/libs/util/idparse.c +++ b/libs/util/idparse.c @@ -40,6 +40,7 @@ #include "QF/cbuf.h" #include "QF/cmd.h" #include "QF/idparse.h" +#include "QF/sys.h" typedef struct idbuf_s { dstring_t *buf, *line; @@ -253,3 +254,17 @@ VISIBLE cbuf_interpreter_t id_interp = { COM_execute_sets, NULL }; + +static void +idparse_shutdown (void *data) +{ + if (_com_token) { + dstring_delete (_com_token); + } +} + +static void __attribute__((constructor)) +idparse_init (void) +{ + Sys_RegisterShutdown (idparse_shutdown, 0); +} diff --git a/libs/util/qargs.c b/libs/util/qargs.c index ad7eda0e7..d2103ab22 100644 --- a/libs/util/qargs.c +++ b/libs/util/qargs.c @@ -242,3 +242,16 @@ COM_ExecConfig (cbuf_t *cbuf, int skip_quakerc) } } } + +static void +qargs_shutdown (void *data) +{ + free (largv); + free ((char *) com_cmdline); +} + +static void __attribute__((constructor)) +qargs_init (void) +{ + Sys_RegisterShutdown (qargs_shutdown, 0); +} diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 530fcb03b..bc3b511fa 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -571,6 +571,42 @@ qfs_process_path (const char *path, const char *gamedir) } } +static void +qfs_free_gamedir (void) +{ + if (qfs_gamedir) { + if (qfs_gamedir->name) + free ((char *)qfs_gamedir->name); + if (qfs_gamedir->gamedir) + free ((char *)qfs_gamedir->gamedir); + if (qfs_gamedir->path) + free ((char *)qfs_gamedir->path); + if (qfs_gamedir->gamecode) + free ((char *)qfs_gamedir->gamecode); + if (qfs_gamedir->hudtype) + free ((char *)qfs_gamedir->hudtype); + if (qfs_gamedir->dir.def) + free ((char *)qfs_gamedir->dir.def); + if (qfs_gamedir->dir.skins) + free ((char *)qfs_gamedir->dir.skins); + if (qfs_gamedir->dir.models) + free ((char *)qfs_gamedir->dir.models); + if (qfs_gamedir->dir.sound) + free ((char *)qfs_gamedir->dir.sound); + if (qfs_gamedir->dir.maps) + free ((char *)qfs_gamedir->dir.maps); + if (qfs_gamedir->dir.shots) + free ((char *)qfs_gamedir->dir.shots); + free (qfs_gamedir); + } + + while (qfs_vpaths) { + vpath_t *next = qfs_vpaths->next; + delete_vpath (qfs_vpaths); + qfs_vpaths = next; + } +} + static void qfs_build_gamedir (const char **list) { @@ -584,33 +620,7 @@ qfs_build_gamedir (const char **list) qfs_set_var (vars, "game", qfs_game); - if (qfs_gamedir) { - if (qfs_gamedir->name) - free ((char *)qfs_gamedir->name); - if (qfs_gamedir->gamedir) - free ((char *)qfs_gamedir->gamedir); - if (qfs_gamedir->path) - free ((char *)qfs_gamedir->path); - if (qfs_gamedir->gamecode) - free ((char *)qfs_gamedir->gamecode); - if (qfs_gamedir->dir.def) - free ((char *)qfs_gamedir->dir.def); - if (qfs_gamedir->dir.skins) - free ((char *)qfs_gamedir->dir.skins); - if (qfs_gamedir->dir.models) - free ((char *)qfs_gamedir->dir.models); - if (qfs_gamedir->dir.sound) - free ((char *)qfs_gamedir->dir.sound); - if (qfs_gamedir->dir.maps) - free ((char *)qfs_gamedir->dir.maps); - free (qfs_gamedir); - } - - while (qfs_vpaths) { - vpath_t *next = qfs_vpaths->next; - delete_vpath (qfs_vpaths); - qfs_vpaths = next; - } + qfs_free_gamedir (); for (j = 0; list[j]; j++) ; @@ -829,13 +839,10 @@ QFS_WriteFile (const char *filename, const void *data, int len) Qclose (f); } -static int_findfile_t * -qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, - const char **fnames) +static int_findfile_t found; +static void +clear_findfile (void) { - static int_findfile_t found; - const char **fn; - found.ff.vpath = 0; found.ff.in_pak = false; found.pack = 0; @@ -849,6 +856,15 @@ qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, free ((char *) found.path); found.path = 0; } +} + +static int_findfile_t * +qfs_findfile_search (const vpath_t *vpath, const searchpath_t *sp, + const char **fnames) +{ + const char **fn; + + clear_findfile (); // is the element a pak file? if (sp->pack) { dpackfile_t *packfile = 0; @@ -1456,11 +1472,13 @@ qfs_path_cvar (void *data, const cvar_t *cvar) static void qfs_shutdown (void *data) { - while (qfs_vpaths) { - vpath_t *next = qfs_vpaths->next; - delete_vpath (qfs_vpaths); - qfs_vpaths = next; - } + clear_findfile (); + qfs_free_gamedir (); + PL_Free (qfs_gd_plist); + free ((char *) qfs_userpath); + free (gamedir_callbacks); + ALLOC_FREE_BLOCKS (vpaths); + ALLOC_FREE_BLOCKS (searchpaths); } VISIBLE void diff --git a/libs/util/segtext.c b/libs/util/segtext.c index d215cda30..812249811 100644 --- a/libs/util/segtext.c +++ b/libs/util/segtext.c @@ -213,3 +213,16 @@ Segtext_Find (const segtext_t *st, const char *tag) return chunk->text; return 0; } + +static void +segtext_shutdown (void *data) +{ + ALLOC_FREE_BLOCKS (chunks); + ALLOC_FREE_BLOCKS (texts); +} + +static void __attribute__((constructor)) +segtext_init (void) +{ + Sys_RegisterShutdown (segtext_shutdown, 0); +} diff --git a/libs/util/set.c b/libs/util/set.c index 0fe8fe2ec..20f92c01d 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -721,3 +721,16 @@ set_as_string (const set_t *set) dstring_clearstr (str); return set_to_dstring_r (&static_set_pool, str, set); } + +static void +set_shutdown (void *data) +{ + ALLOC_FREE_BLOCKS (static_set_pool.set); + ALLOC_FREE_BLOCKS (static_set_pool.set_iter); +} + +static void __attribute__((constructor)) +set_init (void) +{ + Sys_RegisterShutdown (set_shutdown, 0); +} diff --git a/libs/util/sys.c b/libs/util/sys.c index 6902525c7..a89053a6d 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -536,22 +536,6 @@ Sys_Init_Cvars (void) Cvar_Register (&sys_sleep_cvar, 0, 0); } -void -Sys_Shutdown (void) -{ - shutdown_list_t *t; - - while (shutdown_list) { - void (*func) (void *) = shutdown_list->func; - void *data = shutdown_list->data; - t = shutdown_list; - shutdown_list = shutdown_list->next; - free (t); - - func (data); - } -} - VISIBLE void Sys_Quit (void) { @@ -1231,3 +1215,45 @@ Sys_UniqueFile (dstring_t *name, const char *prefix, const char *suffix, seq++; } } + +void +Sys_Shutdown (void) +{ + shutdown_list_t *t; + + while (shutdown_list) { + void (*func) (void *) = shutdown_list->func; + void *data = shutdown_list->data; + t = shutdown_list; + shutdown_list = shutdown_list->next; + free (t); + + func (data); + } + while (free_sh) { + __auto_type t = free_sh->next; + free (free_sh); + free_sh = t; + } + while (sh_stack) { + __auto_type t = sh_stack->next; + free (sh_stack); + sh_stack = t; + } + while (error_handler_freelist) { + __auto_type t = error_handler_freelist->next; + free (error_handler_freelist); + error_handler_freelist = t; + } + while (error_handler) { + __auto_type t = error_handler->next; + free (error_handler); + error_handler = t; + } + if (sys_print_msg) { + dstring_delete (sys_print_msg); + } + if (sys_debuglog_data) { + dstring_delete (sys_debuglog_data); + } +} diff --git a/libs/util/test/test-seg.c b/libs/util/test/test-seg.c index d67001394..c898abcc6 100644 --- a/libs/util/test/test-seg.c +++ b/libs/util/test/test-seg.c @@ -11,6 +11,7 @@ #include #include "QF/segtext.h" +#include "QF/sys.h" static const char *test_string = "blah\n" @@ -83,5 +84,7 @@ main (int argc, const char **argv) res = 1; } } + Segtext_delete (st); + Sys_Shutdown (); return res; } diff --git a/libs/util/va.c b/libs/util/va.c index b47d5d2ba..98af3d8b0 100644 --- a/libs/util/va.c +++ b/libs/util/va.c @@ -38,6 +38,7 @@ #include #include "QF/dstring.h" +#include "QF/sys.h" #include "QF/va.h" struct va_ctx_s { @@ -46,6 +47,8 @@ struct va_ctx_s { int str_index; }; +static va_ctx_t *default_va_ctx; + VISIBLE va_ctx_t * va_create_context (int buffers) { @@ -74,15 +77,14 @@ va_destroy_context (va_ctx_t *ctx) VISIBLE const char * va (va_ctx_t *ctx, const char *fmt, ...) { - static va_ctx_t *_ctx; va_list args; dstring_t *dstr; if (!ctx) { - if (!_ctx) { - _ctx = va_create_context (4); + if (!default_va_ctx) { + default_va_ctx = va_create_context (4); } - ctx = _ctx; + ctx = default_va_ctx; } dstr = ctx->strings[ctx->str_index++ % ctx->num_strings]; @@ -107,3 +109,17 @@ nva (const char *fmt, ...) return dstring_freeze (string); } + +static void +va_shutdown (void *data) +{ + if (default_va_ctx) { + va_destroy_context (default_va_ctx); + } +} + +static void __attribute__((constructor)) +va_init (void) +{ + Sys_RegisterShutdown (va_shutdown, 0); +} From d8466b6ccad33b6ded5c8b15f8742252247f7191 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:06:30 +0900 Subject: [PATCH 3468/3664] [util] Fix a linked-list error in segtext Uncovered by the memory leak cleanup: the nodes were all being "linked" to the first node, those nodes in between the first and last were getting lost. --- libs/util/segtext.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/util/segtext.c b/libs/util/segtext.c index 812249811..a75a7c779 100644 --- a/libs/util/segtext.c +++ b/libs/util/segtext.c @@ -163,6 +163,7 @@ Segtext_new (const char *source_string) // If tags are duplicated, the first one takes precedence if ((*chunk)->tag && !Hash_Find (text->tab, (*chunk)->tag)) Hash_Add (text->tab, *chunk); + chunk = &(*chunk)->next; } return text; } @@ -177,8 +178,9 @@ Segtext_delete (segtext_t *st) while (st->chunk_list) { chunk = st->chunk_list; st->chunk_list = chunk->next; - if (chunk->tag) + if (chunk->tag) { free ((char *) chunk->tag); + } delete_chunk (chunk); } Hash_DelTable (st->tab); From 3d65376f877f5ea26f27231ac34d7f7badbdebea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:07:56 +0900 Subject: [PATCH 3469/3664] [cvar] Delete enum symbol tables on shutdown More memory leaks. Might need to make some soup. --- libs/util/cvar.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 155b6a78a..a192bab64 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -770,6 +770,11 @@ cvar_free_memory (void *ele, void *data) char **str_value = cvar->value.value; free (*str_value); *str_value = 0; + } else if (cvar->value.type->data) { + exprenum_t *enm = cvar->value.type->data; + if (enm->symtab && enm->symtab->tab) { + Hash_DelTable (enm->symtab->tab); + } } if (cvar->listeners) { From 3f9873a754babf86c5cba2a205af8fbfe9073f2a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:10:04 +0900 Subject: [PATCH 3470/3664] [console] Plug more memory leaks --- include/QF/console.h | 1 + libs/console/bi_inputline.c | 4 ++- libs/console/client.c | 53 +++++++++++++++++++++++--------- libs/console/console.c | 1 - libs/console/menu.c | 11 +++++-- ruamoko/qwaq/builtins/graphics.c | 1 + 6 files changed, 53 insertions(+), 18 deletions(-) diff --git a/include/QF/console.h b/include/QF/console.h index 0a0274664..161200fdf 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -110,6 +110,7 @@ void C_DrawInputLine (struct inputline_s *il); struct view_s; void Menu_Init (void); +void Menu_Shutdown (void); void Menu_Load (void); void Menu_Draw (struct view_s view); void Menu_Draw_Hud (struct view_s view); diff --git a/libs/console/bi_inputline.c b/libs/console/bi_inputline.c index 4b6764e3a..78cf923f3 100644 --- a/libs/console/bi_inputline.c +++ b/libs/console/bi_inputline.c @@ -105,7 +105,9 @@ bi_il_clear (progs_t *pr, void *_res) static void bi_il_destroy (progs_t *pr, void *_res) { - free (_res); + il_resources_t *res = _res; + PR_RESDELMAP (res->line_map); + free (res); } static il_data_t * __attribute__((pure)) diff --git a/libs/console/client.c b/libs/console/client.c index b2268be98..b274883ab 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -160,6 +160,10 @@ static int con_saved_focos; static qboolean con_debuglog; static qboolean chat_team; +static dstring_t *c_print_buffer; +static dstring_t *dlbar; +static dstring_t *old_gamedir = 0; + typedef struct { const char *prompt; @@ -448,26 +452,25 @@ static __attribute__((format(PRINTF, 1, 0))) void C_Print (const char *fmt, va_list args) { char *s; - static dstring_t *buffer; int mask, c; - if (!buffer) - buffer = dstring_new (); + if (!c_print_buffer) + c_print_buffer = dstring_new (); - dvsprintf (buffer, fmt, args); + dvsprintf (c_print_buffer, fmt, args); // log all messages to file if (con_debuglog) Sys_DebugLog (va (0, "%s/%s/qconsole.log", qfs_userpath,//FIXME - qfs_gamedir->dir.def), "%s", buffer->str); + qfs_gamedir->dir.def), "%s", c_print_buffer->str); if (!con_initialized) return; - s = buffer->str; + s = c_print_buffer->str; mask = 0; - if (buffer->str[0] == 1 || buffer->str[0] == 2) { + if (s[0] == 1 || s[0] == 2) { mask = 128; // go to colored text s++; } @@ -506,10 +509,10 @@ C_Print (const char *fmt, va_list args) // echo to debugging console // but don't print the highchars flag (leading \x01) - if ((byte)buffer->str[0] > 2) - fputs (buffer->str, stdout); - else if ((byte)buffer->str[0]) - fputs (buffer->str + 1, stdout); + if ((byte)c_print_buffer->str[0] > 2) + fputs (c_print_buffer->str, stdout); + else if ((byte)c_print_buffer->str[0]) + fputs (c_print_buffer->str + 1, stdout); } /* DRAWING */ @@ -582,7 +585,6 @@ resize_input (view_t view, view_pos_t len) static void update_download (void) { - static dstring_t *dlbar; const char *text; if (!dlbar) { @@ -815,8 +817,6 @@ C_DrawConsole (void) static void C_NewMap (void) { - static dstring_t *old_gamedir = 0; - if (!old_gamedir || !strequal (old_gamedir->str, qfs_gamedir->gamedir)) Menu_Load (); if (!old_gamedir) @@ -1193,7 +1193,32 @@ C_Init (void) static void C_shutdown (void) { + r_funcs->Draw_DestroyPic (conback); IE_Remove_Handler (con_event_id); + Menu_Shutdown (); + + Con_DestroyInputLine (cmd_line.input_line); + Con_DestroyInputLine (team_input); + Con_DestroyInputLine (chat_input); + Con_DestroyBuffer (con_main); + + if (download_buffer) { + Draw_DestroyBuffer (download_buffer); + } + Draw_DestroyBuffer (console_buffer); + Draw_DestroyBuffer (cmd_line.buffer); + Draw_DestroyBuffer (notify_buffer); + Draw_DestroyBuffer (say_line.buffer); + + if (c_print_buffer) { + dstring_delete (c_print_buffer); + } + if (dlbar) { + dstring_delete (dlbar); + } + if (old_gamedir) { + dstring_delete (old_gamedir); + } } static general_data_t plugin_info_general_data; diff --git a/libs/console/console.c b/libs/console/console.c index 43964db03..9c3fc8140 100644 --- a/libs/console/console.c +++ b/libs/console/console.c @@ -102,7 +102,6 @@ Con_shutdown (void *data) Sys_SetStdPrintf (saved_sys_printf); } if (con_module) { - con_module->functions->general->shutdown (); PI_UnloadPlugin (con_module); } } diff --git a/libs/console/menu.c b/libs/console/menu.c index c1c085a03..af64b90ba 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -99,7 +99,7 @@ static pr_func_t menu_quit; static pr_func_t menu_draw_hud; static pr_func_t menu_pre; static pr_func_t menu_post; -static const char *top_menu; +static char *top_menu; typedef struct menu_func_s { const char *name; @@ -365,7 +365,7 @@ bi_Menu_TopMenu (progs_t *pr, void *data) const char *name = P_GSTRING (pr, 0); if (top_menu) - free ((char *) top_menu); + free (top_menu); top_menu = strdup (name); } @@ -591,6 +591,13 @@ Menu_Next_f (void) Menu_KeyEvent (QFK_DOWN, '\0', true); } +void +Menu_Shutdown (void) +{ + PR_Shutdown (&menu_pr_state); + Hash_DelTable (menu_hash); + free (top_menu); +} void Menu_Init (void) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 49b87abe8..04f477064 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -161,6 +161,7 @@ event_handler (const IE_event_t *ie_event, void *_pr) static void BI_shutdown (void *data) { + ECS_DelRegistry (canvas_sys.reg); } static byte default_palette[256][3]; From 3e30b7b9e251f57cac4bd27e614d544677316298 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:14:25 +0900 Subject: [PATCH 3471/3664] [image] Allow color conversion caches to be cleaned up More leaks, but only ruamoko takes advantage of it so far. --- include/QF/image.h | 1 + libs/image/convert.c | 7 +++++++ ruamoko/qwaq/builtins/graphics.c | 1 + 3 files changed, 9 insertions(+) diff --git a/include/QF/image.h b/include/QF/image.h index d57b7253b..d93f65cc3 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -66,6 +66,7 @@ typedef struct colcache_s colcache_t; colcache_t *ColorCache_New (void); void ColorCache_Delete (colcache_t *cache); +void ColorCache_Shutdown (void); byte ConvertColor (const byte *rgb, const byte *pal, colcache_t *cache); tex_t *ConvertImage (const tex_t *tex, const byte *pal); diff --git a/libs/image/convert.c b/libs/image/convert.c index df5829f92..54133a9ed 100644 --- a/libs/image/convert.c +++ b/libs/image/convert.c @@ -105,6 +105,13 @@ ColorCache_Delete (colcache_t *cache) FREE (colcache, cache); } +void +ColorCache_Shutdown (void) +{ + ALLOC_FREE_BLOCKS (colcache); + ALLOC_FREE_BLOCKS (colcache_color); +} + byte ConvertColor (const byte *rgb, const byte *pal, colcache_t *cache) { diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 04f477064..631a2f690 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -162,6 +162,7 @@ static void BI_shutdown (void *data) { ECS_DelRegistry (canvas_sys.reg); + ColorCache_Shutdown (); } static byte default_palette[256][3]; From 9605de53d7bf8c20948d992fe77a6e702e3e4977 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:15:49 +0900 Subject: [PATCH 3472/3664] [audio] Plug yet more leaks What a sieve QF became. --- include/snd_internal.h | 1 + libs/audio/renderer/snd_dma.c | 1 + libs/audio/renderer/snd_sfx.c | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/include/snd_internal.h b/include/snd_internal.h index b1f23a3f1..61273211b 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -326,6 +326,7 @@ sfx_t *SND_LoadSound (snd_t *snd, const char *name); \param snd sound system state */ void SND_SFX_Init (snd_t *snd); +void SND_SFX_Shutdown (snd_t *snd); ///@} diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index ee432247c..91207a275 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -401,6 +401,7 @@ s_shutdown (void) sound_started = 0; snd_shutdown = 1; + SND_SFX_Shutdown (&snd); snd_output_funcs->shutdown (&snd); } diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 538c7aa58..2082db1e0 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -229,3 +229,9 @@ SND_SFX_Init (snd_t *snd) Cmd_AddCommand ("soundlist", s_soundlist_f, "Reports a list of loaded sounds"); } + +void +SND_SFX_Shutdown (snd_t *snd) +{ + Hash_DelTable (snd_sfx_hash); +} From f256ab167d16e40c80ad484d711a0c1199d6163a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:17:29 +0900 Subject: [PATCH 3473/3664] [gamecode] Yet more leaks --- libs/gamecode/pr_debug.c | 8 ++++++++ libs/gamecode/pr_strings.c | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index e80cb72a7..7b774e9b1 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -1988,9 +1988,17 @@ PR_Debug_Init (progs_t *pr) pr->pr_debug_resources = res; } +static void +pr_debug_shutdown (void *data) +{ + free (source_paths); + free (source_path_string); +} + void PR_Debug_Init_Cvars (void) { + Sys_RegisterShutdown (pr_debug_shutdown, 0); Cvar_Register (&pr_debug_cvar, 0, 0); Cvar_Register (&pr_source_path_cvar, source_path_f, 0); } diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index b4227fc64..5e00746ac 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -40,6 +40,7 @@ #include #include +#include "QF/darray.h" #include "QF/dstring.h" #include "QF/hash.h" #include "QF/progs.h" @@ -88,6 +89,7 @@ typedef struct prstr_resources_s { unsigned dyn_str_size; struct hashtab_s *strref_hash; int num_strings; + struct DARRAY_TYPE (fmt_item_t *) fmt_item_blocks; fmt_item_t *free_fmt_items; dstring_t *print_str; prstr_at_handler_t at_handler; @@ -248,6 +250,11 @@ pr_strings_destroy (progs_t *pr, void *_res) } free (res->string_map); + for (size_t i = 0; i < res->fmt_item_blocks.size; i++) { + free (res->fmt_item_blocks.a[i]); + } + DARRAY_CLEAR (&res->fmt_item_blocks); + pr->pr_string_resources = 0; free (res); } @@ -848,6 +855,7 @@ new_fmt_item (prstr_resources_t *res) for (i = 0; i < 15; i++) res->free_fmt_items[i].next = res->free_fmt_items + i + 1; res->free_fmt_items[i].next = 0; + DARRAY_APPEND (&res->fmt_item_blocks, res->free_fmt_items); } fi = res->free_fmt_items; @@ -1300,6 +1308,7 @@ PR_Strings_Init (progs_t *pr) res->print_str = dstring_new (); res->strref_hash = Hash_NewTable (1021, strref_get_key, strref_free, res, pr->hashctx); + DARRAY_INIT (&res->fmt_item_blocks, 8); PR_Resources_Register (pr, "Strings", res, pr_strings_clear, pr_strings_destroy); From 340127fff23971ce6eaa190510299e1c02c672e9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:20:04 +0900 Subject: [PATCH 3474/3664] [ruamoko] Plug yet more memory leaks Some of them, especially in rua_obj, were quite legitimate and even a problem for thread-safety (rua_cmd is currently not thread-safe, but it needs a lock, which I don't feel like doing at this stage). --- libs/ruamoko/rua_cmd.c | 5 +- libs/ruamoko/rua_gui.c | 40 ++++++++++++---- libs/ruamoko/rua_input.c | 3 +- libs/ruamoko/rua_model.c | 4 +- libs/ruamoko/rua_obj.c | 91 ++++++++++++++++++++++++++---------- libs/ruamoko/rua_scene.c | 5 +- ruamoko/qwaq/builtins/main.c | 6 +++ 7 files changed, 116 insertions(+), 38 deletions(-) diff --git a/libs/ruamoko/rua_cmd.c b/libs/ruamoko/rua_cmd.c index 96025fc65..c147b6990 100644 --- a/libs/ruamoko/rua_cmd.c +++ b/libs/ruamoko/rua_cmd.c @@ -58,6 +58,7 @@ typedef struct { } cmd_resources_t; static hashtab_t *bi_cmds; +static hashctx_t *bi_cmd_hashctx; static int bi_cmds_refs; static const char * @@ -129,6 +130,7 @@ bi_cmd_destroy (progs_t *pr, void *data) { if (!--bi_cmds_refs) { Hash_DelTable (bi_cmds); + Hash_DelContext (bi_cmd_hashctx); } free (data); } @@ -173,8 +175,9 @@ RUA_Cmd_Init (progs_t *pr, int secure) res->cmds = 0; if (!bi_cmds) { + //FIXME not thread-safe bi_cmds = Hash_NewTable (1021, bi_cmd_get_key, bi_cmd_free, 0, - pr->hashctx); + &bi_cmd_hashctx); } bi_cmds_refs++; diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index 8bd59ad46..98c201716 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -140,13 +140,13 @@ font_new (gui_resources_t *res) { return PR_RESNEW (res->font_map); } -/* + static void font_free (gui_resources_t *res, rua_font_t *font) { PR_RESFREE (res->font_map, font); } -*/ + static void font_reset (gui_resources_t *res) { @@ -168,16 +168,16 @@ font_index (gui_resources_t *res, rua_font_t *font) static int alloc_font (gui_resources_t *res, font_t *font) { - rua_font_t *psg = font_new (res); + rua_font_t *fnt = font_new (res); - psg->next = res->fonts; - psg->prev = &res->fonts; + fnt->next = res->fonts; + fnt->prev = &res->fonts; if (res->fonts) { - res->fonts->prev = &psg->next; + res->fonts->prev = &fnt->next; } - res->fonts = psg; - psg->font = font; - return font_index (res, psg); + res->fonts = fnt; + fnt->font = font; + return font_index (res, fnt); } static rua_font_t * __attribute__((pure)) @@ -215,6 +215,8 @@ bi_gui_destroy (progs_t *pr, void *_res) { gui_resources_t *res = _res; ECS_DelRegistry (res->reg); + PR_RESDELMAP (res->passage_map); + PR_RESDELMAP (res->font_map); free (res); } @@ -231,6 +233,15 @@ bi (Font_Load) R_INT (pr) = alloc_font (res, font); } +bi (Font_Free) +{ + gui_resources_t *res = _res; + rua_font_t *font = get_font (res, P_INT (pr, 0)); + + Font_Free (font->font); + font_free (res, font); +} + bi (Passage_New) { gui_resources_t *res = _res; @@ -361,6 +372,15 @@ bi (Text_Draw) } } +bi (View_Delete) +{ + gui_resources_t *res = _res; + uint32_t viewid = P_UINT (pr, 0); + view_t view = { .id = viewid, .reg = res->reg, + .comp = res->view_base + view_href }; + View_Delete (view); +} + bi (View_ChildCount) { gui_resources_t *res = _res; @@ -427,6 +447,7 @@ bi (View_UpdateHierarchy) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { bi(Font_Load, 2, p(string), p(int)), + bi(Font_Free, 2, p(int)), bi(Passage_New, 0), bi(Passage_ParseText, 2, p(ptr), p(string)), bi(Passage_Delete, 1, p(ptr)), @@ -436,6 +457,7 @@ static builtin_t builtins[] = { bi(Text_View, 2, p(ptr), p(int)), bi(Text_SetScript, 4, p(uint), p(string), p(int), p (int)), + bi(View_Delete, 1, p(uint)), bi(View_ChildCount, 1, p(uint)), bi(View_GetChild, 2, p(uint), p(uint)), bi(View_SetPos, 3, p(uint), p(int), p(int)), diff --git a/libs/ruamoko/rua_input.c b/libs/ruamoko/rua_input.c index 1c6153b55..df86bcec1 100644 --- a/libs/ruamoko/rua_input.c +++ b/libs/ruamoko/rua_input.c @@ -519,8 +519,7 @@ RUA_Input_Init (progs_t *pr, int secure) input_resources_t *res = calloc (sizeof (input_resources_t), 1); res->cookie_super = new_memsuper (); - res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, - &res->hashctx); + res->cookies = Hash_NewTable (251, 0, rua_in_free_cookie, res, pr->hashctx); Hash_SetHashCompare (res->cookies, rua_in_hash_cookie, rua_in_cmp_cookies); PR_Resources_Register (pr, "input", res, bi_input_clear, bi_input_destroy); diff --git a/libs/ruamoko/rua_model.c b/libs/ruamoko/rua_model.c index a19fa8f92..055462ec0 100644 --- a/libs/ruamoko/rua_model.c +++ b/libs/ruamoko/rua_model.c @@ -106,7 +106,9 @@ bi_rua_model_clear (progs_t *pr, void *_res) static void bi_rua_model_destroy (progs_t *pr, void *_res) { - free (_res); + rua_model_resources_t *res = _res; + PR_RESDELMAP (res->model_map); + free (res); } static int diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 81c440924..0e1a8ddb8 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -45,6 +45,7 @@ #include "qfalloca.h" #include "QF/cvar.h" +#include "QF/darray.h" #include "QF/dstring.h" #include "QF/hash.h" #include "QF/mathlib.h" @@ -99,6 +100,8 @@ typedef struct obj_list_s { void *data; } obj_list; +typedef struct listset_s DARRAY_TYPE (obj_list *) listset_t; + typedef struct dtable_s { struct dtable_s *next; struct dtable_s **prev; @@ -106,6 +109,13 @@ typedef struct dtable_s { pr_func_t *imp; } dtable_t; +typedef struct class_tree { + pr_class_t *class; + obj_list *subclasses; +} class_tree; + +typedef struct treeset_s DARRAY_TYPE (class_tree *) treeset_t; + typedef struct probj_resources_s { progs_t *pr; unsigned selector_index; @@ -124,6 +134,7 @@ typedef struct probj_resources_s { hashtab_t *classes; hashtab_t *protocols; hashtab_t *load_methods; + listset_t obj_list_sets; obj_list *obj_list_free_list; obj_list *unresolved_classes; obj_list *unclaimed_categories; @@ -131,6 +142,9 @@ typedef struct probj_resources_s { obj_list *unclaimed_proto_list; obj_list *module_list; obj_list *class_tree_list; + + class_tree *class_tree_free_list; + treeset_t class_tree_sets; } probj_t; static dtable_t * @@ -184,8 +198,11 @@ obj_list_new (probj_t *probj) if (!probj->obj_list_free_list) { probj->obj_list_free_list = calloc (128, sizeof (obj_list)); - for (i = 0; i < 127; i++) - probj->obj_list_free_list[i].next = &probj->obj_list_free_list[i + 1]; + for (i = 0; i < 127; i++) { + __auto_type next = &probj->obj_list_free_list[i + 1]; + probj->obj_list_free_list[i].next = next; + } + DARRAY_APPEND (&probj->obj_list_sets, probj->obj_list_free_list); } l = probj->obj_list_free_list; probj->obj_list_free_list = l->next; @@ -230,28 +247,22 @@ list_remove (probj_t *probj, obj_list **list) } } -typedef struct class_tree { - pr_class_t *class; - obj_list *subclasses; -} class_tree; - -class_tree *class_tree_free_list; - static class_tree * -class_tree_new (void) +class_tree_new (probj_t *probj) { int i; class_tree *t; - if (!class_tree_free_list) { - class_tree_free_list = calloc (128, sizeof (class_tree)); + if (!probj->class_tree_free_list) { + probj->class_tree_free_list = calloc (128, sizeof (class_tree)); for (i = 0; i < 127; i++) { - class_tree *x = &class_tree_free_list[i]; + class_tree *x = &probj->class_tree_free_list[i]; x->subclasses = (obj_list *) (x + 1); } + DARRAY_APPEND (&probj->class_tree_sets, probj->class_tree_free_list); } - t = class_tree_free_list; - class_tree_free_list = (class_tree *) t->subclasses; + t = probj->class_tree_free_list; + probj->class_tree_free_list = (class_tree *) t->subclasses; t->subclasses = 0; return t; } @@ -282,10 +293,10 @@ create_tree_of_subclasses_inherited_from (probj_t *probj, pr_class_t *bottom, superclass = bottom->super_class ? Hash_Find (probj->classes, super_class) : 0; - tree = prev = class_tree_new (); + tree = prev = class_tree_new (probj); prev->class = bottom; while (superclass != upper) { - tree = class_tree_new (); + tree = class_tree_new (probj); tree->class = superclass; tree->subclasses = list_cons (probj, prev, tree->subclasses); super_class = PR_GetString (pr, superclass->super_class); @@ -320,7 +331,7 @@ _obj_tree_insert_class (probj_t *probj, class_tree *tree, pr_class_t *class) return tree; list = list->next; } - node = class_tree_new (); + node = class_tree_new (probj); node->class = class; tree->subclasses = list_cons (probj, node, tree->subclasses); return tree; @@ -381,8 +392,8 @@ obj_create_classes_tree (probj_t *probj, pr_module_t *module) static void obj_destroy_class_tree_node (probj_t *probj, class_tree *tree, int level) { - tree->subclasses = (obj_list *) class_tree_free_list; - class_tree_free_list = tree; + tree->subclasses = (obj_list *) probj->class_tree_free_list; + probj->class_tree_free_list = tree; } static void @@ -1414,6 +1425,18 @@ rua_obj_error (progs_t *pr, void *data) int count = pr->pr_argc - 3; pr_type_t **args = &pr->pr_params[3]; + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 3); + count = va_list->count; + if (count) { + args = alloca (count * sizeof (pr_type_t *)); + for (int i = 0; i < count; i++) { + args[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + args = 0; + } + } obj_verror (probj, object, code, fmt, count, args); } @@ -2068,6 +2091,18 @@ rua__i_Object_error_error_ (progs_t *pr, void *data) int count = pr->pr_argc - 3; pr_type_t **args = &pr->pr_params[3]; + if (pr->progs->version == PROG_VERSION) { + __auto_type va_list = &P_PACKED (pr, pr_va_list_t, 3); + count = va_list->count; + if (count) { + args = alloca (count * sizeof (pr_type_t *)); + for (int i = 0; i < count; i++) { + args[i] = &pr->pr_globals[va_list->list + i * 4]; + } + } else { + args = 0; + } + } dsprintf (probj->msg, "error: %s (%s)\n%s", PR_GetString (pr, object_get_class_name (probj, self)), object_is_instance (probj, self) ? "instance" : "class", fmt); @@ -2336,10 +2371,16 @@ rua_obj_destroy (progs_t *pr, void *_res) free (probj->selector_sels); free (probj->selector_names); free (probj->selector_argc); - //FIXME free (probj->obj_list_free_list); - //FIXME free (class_tree_free_list); - //FIXME class_tree_free_list = 0; + for (size_t i = 0; i < probj->obj_list_sets.size; i++) { + free (probj->obj_list_sets.a[i]); + } + DARRAY_CLEAR (&probj->obj_list_sets); + + for (size_t i = 0; i < probj->class_tree_sets.size; i++) { + free (probj->class_tree_sets.a[i]); + } + DARRAY_CLEAR (&probj->class_tree_sets); PR_RESDELMAP (probj->dtables); @@ -2358,9 +2399,11 @@ RUA_Obj_Init (progs_t *pr, int secure) probj->protocols = Hash_NewTable (1021, protocol_get_key, 0, probj, pr->hashctx); probj->load_methods = Hash_NewTable (1021, 0, 0, probj, pr->hashctx); - probj->msg = dstring_newstr(); Hash_SetHashCompare (probj->load_methods, load_methods_get_hash, load_methods_compare); + probj->msg = dstring_newstr(); + DARRAY_INIT (&probj->obj_list_sets, 32); + DARRAY_INIT (&probj->class_tree_sets, 32); PR_Sprintf_SetAtHandler (pr, rua_at_handler, probj); diff --git a/libs/ruamoko/rua_scene.c b/libs/ruamoko/rua_scene.c index 384c3bfea..e0a8a023a 100644 --- a/libs/ruamoko/rua_scene.c +++ b/libs/ruamoko/rua_scene.c @@ -657,7 +657,10 @@ bi_scene_clear (progs_t *pr, void *_res) static void bi_scene_destroy (progs_t *pr, void *_res) { - free (_res); + rua_scene_resources_t *res = _res; + PR_RESDELMAP (res->scene_map); + PR_RESDELMAP (res->lighting_map); + free (res); } void diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 090141414..a0c291d79 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -480,6 +480,12 @@ main (int argc, char **argv) ret = thread_data.a[main_ind]->return_code; } + for (size_t i = 0; i < thread_data.size; i++) { + qwaq_thread_t *thread = thread_data.a[i]; + DARRAY_CLEAR (&thread->args); + free (thread_data.a[i]); + } + DARRAY_CLEAR (&thread_data); Cbuf_Delete (qwaq_cbuf); Sys_Shutdown (); return ret; From b84bf16cabd1d46a5725ad41ab80803569cfb706 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:23:11 +0900 Subject: [PATCH 3475/3664] [util] Add a function to reverse delete cbuf stacks I'm not 100% sure this is the best fix for the issue, but the way the cbuf interpreter stack works (especially in the console code) meant that the stack was built in the order opposite to how it could be safely deleted with the existing function. Yeah, more leaks :P --- include/QF/cbuf.h | 1 + libs/util/cbuf.c | 11 +++++++++++ ruamoko/qwaq/builtins/main.c | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/QF/cbuf.h b/include/QF/cbuf.h index 29a89588e..5566ee7aa 100644 --- a/include/QF/cbuf.h +++ b/include/QF/cbuf.h @@ -92,6 +92,7 @@ cbuf_t * Cbuf_New (cbuf_interpreter_t *interp); void Cbuf_Delete (cbuf_t *cbuf); void Cbuf_DeleteStack (cbuf_t *stack); +void Cbuf_DeleteStackReverse (cbuf_t *stack); void Cbuf_Reset (cbuf_t *cbuf); cbuf_t *Cbuf_PushStack (cbuf_interpreter_t *interp); void Cbuf_AddText (cbuf_t *cbuf, const char *text); diff --git a/libs/util/cbuf.c b/libs/util/cbuf.c index 2249499e7..36765daf2 100644 --- a/libs/util/cbuf.c +++ b/libs/util/cbuf.c @@ -123,6 +123,17 @@ Cbuf_DeleteStack (cbuf_t *stack) } } +VISIBLE void +Cbuf_DeleteStackReverse (cbuf_t *stack) +{ + cbuf_t *next; + + for (; stack; stack = next) { + next = stack->up; + Cbuf_Delete (stack); + } +} + void Cbuf_Reset (cbuf_t *cbuf) { diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index a0c291d79..8b9ff541c 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -486,7 +486,7 @@ main (int argc, char **argv) free (thread_data.a[i]); } DARRAY_CLEAR (&thread_data); - Cbuf_Delete (qwaq_cbuf); + Cbuf_DeleteStackReverse (qwaq_cbuf); Sys_Shutdown (); return ret; } From e81c3a6015e075c50df2aa0eda1ccc39c82fa871 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:26:03 +0900 Subject: [PATCH 3476/3664] [model] Plug more leaks --- libs/models/model.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libs/models/model.c b/libs/models/model.c index 86e4c7f5b..47a1b54bb 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -55,6 +55,7 @@ vid_model_funcs_t *mod_funcs; #define MOD_BLOCK 16 // allocate 16 models at a time static struct DARRAY_TYPE (model_t *) mod_known = {0, 0, MOD_BLOCK}; +static struct DARRAY_TYPE (model_t *) mod_blocks = {0, 0, MOD_BLOCK}; static size_t mod_numknown; VISIBLE texture_t *r_notexture_mip; @@ -99,6 +100,16 @@ static cvar_t gl_textures_external_cvar = { static void Mod_CallbackLoad (void *object, cache_allocator_t allocator); +static void +mod_shutdown (void *data) +{ + for (size_t i = 0; i < mod_blocks.size; i++) { + free (mod_blocks.a[i]); + } + DARRAY_CLEAR (&mod_known); + DARRAY_CLEAR (&mod_blocks); +} + VISIBLE void Mod_Init (void) { @@ -106,6 +117,8 @@ Mod_Init (void) int m, x, y; int mip0size = 16*16, mip1size = 8*8, mip2size = 4*4, mip3size = 2*2; + Sys_RegisterShutdown (mod_shutdown, 0); + r_notexture_mip = Hunk_AllocName (0, sizeof (texture_t) + mip0size + mip1size + mip2size + mip3size, "notexture"); @@ -187,6 +200,7 @@ Mod_FindName (const char *name) DARRAY_APPEND (&mod_known, &block[i]); } mod = &mod_known.a[mod_numknown]; + DARRAY_APPEND (&mod_blocks, block); } memset ((*mod), 0, sizeof (model_t)); strncpy ((*mod)->path, name, sizeof (*mod)->path - 1); From 004ebd40b860d8d1d4a46a224b57fc4711c4d7e5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 17:28:22 +0900 Subject: [PATCH 3477/3664] [ui] Fix more memory leaks The text passage component was a legitimate leak, but the rest just shutdown losses (ie, valgrind noise). --- libs/ui/font.c | 7 +++++++ libs/ui/text.c | 10 ++++++++++ libs/ui/vrect.c | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/libs/ui/font.c b/libs/ui/font.c index afb293670..9b02188f8 100644 --- a/libs/ui/font.c +++ b/libs/ui/font.c @@ -59,12 +59,19 @@ copy_glyph (vrect_t *rect, FT_GlyphSlot src_glyph, font_t *font) } } +static void +Font_shutdown (void *data) +{ + FT_Done_FreeType (ft); +} + VISIBLE void Font_Init (void) { if (FT_Init_FreeType (&ft)) { Sys_Error ("Could not init FreeType library"); } + Sys_RegisterShutdown (Font_shutdown, 0); } VISIBLE void diff --git a/libs/ui/text.c b/libs/ui/text.c index 3970b45a2..96abcc85c 100644 --- a/libs/ui/text.c +++ b/libs/ui/text.c @@ -43,6 +43,13 @@ #include "compat.h" +static void +text_passage_glyphs_destroy (void *_glyphset) +{ + glyphset_t *glyphset = _glyphset; + free (glyphset->glyphs); +} + static void text_features_create (void *_features) { @@ -61,6 +68,7 @@ const component_t text_components[text_comp_count] = { [text_passage_glyphs] = { .size = sizeof (glyphset_t), .name = "passage glyphs", + .destroy = text_passage_glyphs_destroy, }, [text_glyphs] = { .size = sizeof (glyphref_t), @@ -282,6 +290,8 @@ Text_View (ecs_system_t viewsys, font_t *font, passage_t *passage) .count = glyph_count, }; Ent_SetComponent (passage_view.id, text_passage_glyphs, reg, &glyphset); + hb_buffer_destroy (buffer); + hb_font_destroy (fnt); return passage_view; } diff --git a/libs/ui/vrect.c b/libs/ui/vrect.c index 226472d47..975bf4423 100644 --- a/libs/ui/vrect.c +++ b/libs/ui/vrect.c @@ -33,6 +33,7 @@ #include +#include "QF/darray.h" #include "QF/mathlib.h" #include "QF/ui/vrect.h" @@ -42,6 +43,7 @@ #define RECT_BLOCK 128 #ifndef TEST_MEMORY static vrect_t *free_rects; +static struct DARRAY_TYPE(vrect_t *) rect_sets = DARRAY_STATIC_INIT (32); #endif VISIBLE vrect_t * @@ -56,6 +58,7 @@ VRect_New (int x, int y, int width, int height) for (i = 0; i < RECT_BLOCK - 1; i++) free_rects[i].next = &free_rects[i + 1]; free_rects[i].next = 0; + DARRAY_APPEND (&rect_sets, free_rects); } r = free_rects; free_rects = free_rects->next; @@ -319,3 +322,20 @@ VRect_SubRect (const vrect_t *rect, int width, int height) VRect_Delete (r); return s; } + +#ifndef TEST_MEMORY +static void +vrect_shutdown (void *data) +{ + for (size_t i = 0; i < rect_sets.size; i++) { + free (rect_sets.a[i]); + } + DARRAY_CLEAR (&rect_sets); +} + +static void __attribute__((constructor)) +vrect_init (void) +{ + Sys_RegisterShutdown (vrect_shutdown, 0); +} +#endif From 24ac95ef6ec9c043d5eeffa8a2b27d641c585408 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 18:12:03 +0900 Subject: [PATCH 3478/3664] [cvar] Ensure enum cvars tables don't get double freed Currently doesn't happen, but all it takes is for two or more cvars to use the same enum type. --- libs/util/cvar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/util/cvar.c b/libs/util/cvar.c index a192bab64..66aaccdad 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -774,6 +774,7 @@ cvar_free_memory (void *ele, void *data) exprenum_t *enm = cvar->value.type->data; if (enm->symtab && enm->symtab->tab) { Hash_DelTable (enm->symtab->tab); + enm->symtab->tab = 0; } } From 370c36f6cc81fa9f7eb28fa50c77517290ef5cf5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 18:19:54 +0900 Subject: [PATCH 3479/3664] [vulkan] Fix some memory leaks And deal with a shutdown order issue causing cvars to crash on shutdown (due to the hash links being freed too early). --- libs/video/renderer/vid_render_vulkan.c | 2 +- libs/video/renderer/vulkan/render.c | 1 + libs/video/renderer/vulkan/vkparse.c | 29 +++++++++++++++++-- .../video/renderer/vulkan/vulkan_renderpass.c | 2 -- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 419636f46..a6c7f9950 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -724,7 +724,7 @@ vulkan_vid_render_shutdown (void) VkDevice dev = device->dev; QFV_DeviceWaitIdle (device); - Mod_ClearAll (); + SCR_Shutdown (); Vulkan_Compose_Shutdown (vulkan_ctx); Vulkan_Translucent_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 9dbeccc35..5b7a20753 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -966,6 +966,7 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) if (rctx->task_functions.tab) { Hash_DelTable (rctx->task_functions.tab); } + Hash_DelContext (rctx->hashctx); } void diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 6e43e2bb6..6779c7083 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1226,6 +1226,13 @@ parser_getkey (const void *e, void *unused) static exprtab_t root_symtab = { .symbols = cexpr_lib_symbols, }; + +static void +root_symtab_shutdown (void *data) +{ + Hash_DelTable (root_symtab.tab); +} + static void __attribute__((constructor)) root_symtab_init (void) { @@ -1233,6 +1240,7 @@ root_symtab_init (void) // main and thus before any possibility of threading. exprctx_t root_context = { .symtab = &root_symtab }; cexpr_init_symtab (&root_symtab, &root_context); + Sys_RegisterShutdown (root_symtab_shutdown, 0); } exprenum_t * @@ -1966,6 +1974,17 @@ build_configs (scriptctx_t *sctx) cexpr_init_symtab (&builtin_configs, &ectx); } +static void +delete_configs (void) +{ + int num_plists = 0; + for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { + PL_Free (builtin_plists[num_plists]); + num_plists++; + } + free (builtin_plists); +} + static plitem_t * qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) { @@ -2025,7 +2044,10 @@ void Vulkan_Script_Init (vulkan_ctx_t *ctx) exprctx_t ectx = {}; enum_symtab = Hash_NewTable (61, enum_symtab_getkey, 0, 0, &sctx->hashctx); parser_table = Hash_NewTable (61, parser_getkey, 0, 0, &sctx->hashctx); - ectx.hashctx = &sctx->hashctx; + //FIXME using the script context's hashctx causes the cvar system to access + //freed hash links due to shutdown order issues. The proper fix would be to + //create a symtabs shutdown (for thread safety), but this works for now. + ectx.hashctx = 0;//&sctx->hashctx; vkgen_init_symtabs (&ectx); cexpr_init_symtab (&qfv_output_t_symtab, &ectx); cexpr_init_symtab (&vulkan_frameset_t_symtab, &ectx); @@ -2055,13 +2077,16 @@ void Vulkan_Script_Shutdown (vulkan_ctx_t *ctx) { scriptctx_t *sctx = ctx->script_context; - PL_Free (sctx->pipelineDef); clear_table (&sctx->pipelineLayouts); clear_table (&sctx->setLayouts); clear_table (&sctx->shaderModules); clear_table (&sctx->descriptorPools); clear_table (&sctx->samplers); + delete_configs (); + + Hash_DelContext (sctx->hashctx); + free (sctx); } diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 98a388a78..f490f8228 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -367,8 +367,6 @@ QFV_RenderPass_Delete (qfv_renderpass_t *renderpass) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - PL_Free (renderpass->renderpassDef); - destroy_attachments (ctx, renderpass); dfunc->vkDestroyRenderPass (device->dev, renderpass->renderpass, 0); destroy_renderframes (ctx, renderpass); From 76ac446156096fb61336f3afd978e524d1df2706 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 15:22:01 +0900 Subject: [PATCH 3480/3664] [util] Fix an out-by-one in QF_bsearch_r And rename _bsearch to QF_bsearch_r since that's far less confusing. Also, update the test to make it possible for valgrind to detect the out-by-one. The problem was found when trying to remove components from an entity when using subpools. --- include/bsearch.h | 4 ++-- include/compat.h | 2 +- libs/util/bsearch.c | 7 +++---- libs/util/test/test-bsearch.c | 19 +++++++++++++------ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/bsearch.h b/include/bsearch.h index 0a3a507b4..db03d85ea 100644 --- a/include/bsearch.h +++ b/include/bsearch.h @@ -35,7 +35,7 @@ typedef int (*__compar_d_fn_t)(const void *, const void *, void *); #endif -void *_bsearch(const void *key, const void *base, size_t nmemb, size_t size, - __compar_d_fn_t cmp, void *arg); +void *QF_bsearch_r(const void *key, const void *base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg); #endif// quicksort_h diff --git a/include/compat.h b/include/compat.h index eaab8a6ba..07c871667 100644 --- a/include/compat.h +++ b/include/compat.h @@ -109,7 +109,7 @@ size_t strndup (const char *str, size_t len); #ifndef HAVE_BSEARCH_R # include "bsearch.h" -# define bsearch_r _bsearch +# define bsearch_r QF_bsearch_r #endif #ifndef HAVE_QSORT_R diff --git a/libs/util/bsearch.c b/libs/util/bsearch.c index 225f2623b..7114bf134 100644 --- a/libs/util/bsearch.c +++ b/libs/util/bsearch.c @@ -63,13 +63,12 @@ void *fbsearch_r (const void *key, const void *_base, size_t nmemb, size_t size, } void * -_bsearch(const void *key, const void *_base, size_t nmemb, size_t size, - __compar_d_fn_t cmp, void *arg) +QF_bsearch_r(const void *key, const void *_base, size_t nmemb, size_t size, + __compar_d_fn_t cmp, void *arg) { - // fuzzy bsearh const char *base = (const char *) _base; unsigned left = 0; - unsigned right = nmemb; + unsigned right = nmemb - 1; unsigned mid; const void *p = 0; int c; diff --git a/libs/util/test/test-bsearch.c b/libs/util/test/test-bsearch.c index 7723bddec..bbe1a81bc 100644 --- a/libs/util/test/test-bsearch.c +++ b/libs/util/test/test-bsearch.c @@ -29,16 +29,19 @@ #endif #include +#include +#include #include "QF/fbsearch.h" #include "bsearch.h" // will be prefix-summed -int data[] = { +int srcdata[] = { 2, 1, 3, 1, 2, 2, 5, 4, 2, 1, 3, 1, 2, 2, 5, 4, }; -#define nele ((int) (sizeof (data) / sizeof (data[0]))) +#define nele ((int) (sizeof (srcdata) / sizeof (srcdata[0]))) +int *data; static int compare (const void *a, const void *b) @@ -83,6 +86,9 @@ main(int argc, const char **argv) int ret = 0; int *p; + data = malloc (nele * sizeof (int)); + memcpy (data, srcdata, nele * sizeof (int)); + for (int i = 1; i < nele; i++) { data[i] += data[i - 1]; } @@ -99,18 +105,19 @@ main(int argc, const char **argv) ret |= 1; } if (p && i == *p) { - p = _bsearch (&i, data, nele, sizeof (int), compared, 0); + p = QF_bsearch_r (&i, data, nele, sizeof (int), compared, 0); if (!p || *p != i) { - printf ("_bsearch did not find %d, but should have\n", i); + printf ("QF_bsearch_r did not find %d, but should have\n", i); ret |= 1; } } else { - p = _bsearch (&i, data, nele, sizeof (int), compared, 0); + p = QF_bsearch_r (&i, data, nele, sizeof (int), compared, 0); if (p) { - printf ("_bsearch found %d, but should not have\n", i); + printf ("QF_bsearch_r found %d, but should not have\n", i); ret |= 1; } } } + free (data); return ret; } From 28226ac75cddc8128236a468f7548ae21f19a776 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 16:10:09 +0900 Subject: [PATCH 3481/3664] [ecs] Handle indices beyond the subpools It turns out that the bsearch bug was hiding incorrect handling of indices in the subpool beyond the last tracked subpool. In which case, a correctly working bsearch correctly fails to find the range, but the search can be skipped entirely. --- libs/ecs/entity.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index a5fc3112f..a9c54a58f 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -89,6 +89,7 @@ range_cmp (const void *_key, const void *_range, void *_subpool) const uint32_t *range = _range; ecs_subpool_t *subpool = _subpool; + // range is the first index for the next subpool range if (*key >= *range) { return 1; } @@ -117,8 +118,9 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) if (ind < pool->count && pool->dense[ind] == ent) { uint32_t last = pool->count - 1; Component_DestroyElements (c, pool->data, ind, 1); - if (subpool->num_ranges - subpool->available) { - uint32_t range_count = subpool->num_ranges - subpool->available; + uint32_t range_count = subpool->num_ranges - subpool->available; + // if ind >= the last range, then it is outside the subpools + if (range_count && ind < subpool->ranges[range_count - 1]) { uint32_t *range = find_range (subpool, ind); while (range - subpool->ranges < range_count) { uint32_t end = --*range; From 8efe8e63d3506d51a37692afa0594edbf12c945f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 21:29:26 +0900 Subject: [PATCH 3482/3664] [ecs] Plug a bunch of memory leaks The hierarchy leak was particularly troublesome to fix, but now the hierarchies get updated (and freed) automatically just by removing the hierarchy reference component from the entity. I suspect there will be issues with entities that are on multiple hierarchies, but I'll sort that out later. --- include/QF/ecs.h | 1 + include/QF/ecs/hierarchy.h | 2 ++ libs/console/server.c | 1 + libs/ecs/ecs.c | 20 +++++++++++++++++--- libs/ecs/entity.c | 4 ++++ libs/ecs/hierarchy.c | 34 ++++++++++++++++++++++++++++++++-- libs/ecs/test/test-hierarchy.c | 1 + libs/scene/scene.c | 1 + libs/ui/passage.c | 1 + libs/ui/test/test-flow-size.c | 1 + libs/ui/test/test-flow.c | 1 + libs/ui/view.c | 1 + 12 files changed, 63 insertions(+), 5 deletions(-) diff --git a/include/QF/ecs.h b/include/QF/ecs.h index c5402daaa..e321f663e 100644 --- a/include/QF/ecs.h +++ b/include/QF/ecs.h @@ -87,6 +87,7 @@ typedef struct ecs_registry_s { uint32_t max_entities; componentset_t components; PR_RESMAP (hierarchy_t) hierarchies;//FIXME find a better way + int locked; } ecs_registry_t; /** Tie an ECS system to a registry. diff --git a/include/QF/ecs/hierarchy.h b/include/QF/ecs/hierarchy.h index 6036a8f91..88e9c5665 100644 --- a/include/QF/ecs/hierarchy.h +++ b/include/QF/ecs/hierarchy.h @@ -77,6 +77,8 @@ void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index, hierref_t Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, hierarchy_t *src, uint32_t srcIndex); +void Hierref_DestroyComponent (void *href); + ///@} #endif//__QF_ecs_hierarchy_h diff --git a/libs/console/server.c b/libs/console/server.c index fc7e90d12..8a464dda7 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -224,6 +224,7 @@ static const component_t server_components[server_comp_count] = { [server_href] = { .size = sizeof (hierref_t), .name = "href", + .destroy = Hierref_DestroyComponent, }, [server_view] = { .size = sizeof (sv_view_t), diff --git a/libs/ecs/ecs.c b/libs/ecs/ecs.c index a53d83ae0..0a4afaa04 100644 --- a/libs/ecs/ecs.c +++ b/libs/ecs/ecs.c @@ -46,17 +46,26 @@ ECS_NewRegistry (void) VISIBLE void ECS_DelRegistry (ecs_registry_t *registry) { + registry->locked = 1; + for (uint32_t i = 0; i < registry->components.size; i++) { + __auto_type comp = ®istry->components.a[i]; + __auto_type pool = ®istry->comp_pools[i]; + Component_DestroyElements (comp, pool->data, 0, pool->count); + } free (registry->entities); for (uint32_t i = 0; i < registry->components.size; i++) { free (registry->comp_pools[i].sparse); free (registry->comp_pools[i].dense); free (registry->comp_pools[i].data); + free (registry->subpools[i].sorted); free (registry->subpools[i].ranges); free (registry->subpools[i].rangeids); } + DARRAY_CLEAR (®istry->components); free (registry->subpools); free (registry->comp_pools); + PR_RESDELMAP (registry->hierarchies); free (registry); } @@ -193,15 +202,20 @@ ECS_NewEntity (ecs_registry_t *registry) VISIBLE void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent) { + if (registry->locked) { + // the registry is being deleted and mass entity and component + // deletions are going on + return; + } uint32_t next = registry->next | Ent_NextGen (Ent_Generation (ent)); uint32_t id = Ent_Index (ent); - registry->entities[id] = next; - registry->next = id; - registry->available++; for (uint32_t i = 0; i < registry->components.size; i++) { Ent_RemoveComponent (ent, i, registry); } + registry->entities[id] = next; + registry->next = id; + registry->available++; } VISIBLE void diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index a9c54a58f..5fb7a395b 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -117,6 +117,10 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) component_t *c = ®istry->components.a[comp]; if (ind < pool->count && pool->dense[ind] == ent) { uint32_t last = pool->count - 1; + // invalidate the entity for this component to prevent the component + // being double-removed due to deletion of the component resulting + // in the entity being deleted (happens with hierarchies) + pool->dense[ind] = -1; Component_DestroyElements (c, pool->data, ind, 1); uint32_t range_count = subpool->num_ranges - subpool->available; // if ind >= the last range, then it is outside the subpools diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 19b8079fc..58caca7ff 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -58,6 +58,21 @@ hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, } } +static void +hierarchy_InvalidateReferences (hierarchy_t *hierarchy, uint32_t start, + uint32_t count) +{ + ecs_registry_t *reg = hierarchy->reg; + uint32_t href = hierarchy->href_comp; + for (size_t i = start; count-- > 0; i++) { + if (ECS_EntValid (hierarchy->ent[i], reg)) { + hierref_t *ref = Ent_GetComponent (hierarchy->ent[i], href, reg); + ref->hierarchy = 0; + ref->index = -1; + } + } +} + static void hierarchy_UpdateChildIndices (hierarchy_t *hierarchy, uint32_t start, int offset) @@ -165,7 +180,7 @@ hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, src->ent, srcIndex, count); // Actually move (as in C++ move semantics) source hierarchy object // references so that their indices do not get updated when the objects - // are removed from the source hierarcy + // are removed from the source hierarchy memset (&src->ent[srcIndex], nullent, count * sizeof(dst->ent[0])); for (uint32_t i = 0; i < count; i++) { @@ -325,6 +340,7 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index, hierarchy_remove_children (hierarchy, childIndex + i, delEntities); } if (delEntities) { + hierarchy_InvalidateReferences (hierarchy, childIndex, childCount); for (uint32_t i = 0; i < childCount; i++) { ECS_DelEntity (hierarchy->reg, hierarchy->ent[childIndex + i]); } @@ -349,6 +365,7 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index, hierarchy_remove_children (hierarchy, index, delEntities); if (delEntities) { + hierarchy_InvalidateReferences (hierarchy, index, 1); ECS_DelEntity (hierarchy->reg, hierarchy->ent[index]); } hierarchy_close (hierarchy, index, 1); @@ -386,6 +403,7 @@ Hierarchy_New (ecs_registry_t *reg, uint32_t href_comp, void Hierarchy_Delete (hierarchy_t *hierarchy) { + hierarchy_InvalidateReferences (hierarchy, 0, hierarchy->num_objects); free (hierarchy->ent); free (hierarchy->childCount); free (hierarchy->childIndex); @@ -440,7 +458,7 @@ Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, hierref_t r = {}; if (dst && dstParent != nullent) { if (dst->type != src->type) { - Sys_Error ("Can't set parent in hierarcy of different type"); + Sys_Error ("Can't set parent in hierarchy of different type"); } } else { if (!srcRoot) { @@ -458,3 +476,15 @@ Hierarchy_SetParent (hierarchy_t *dst, uint32_t dstParent, } return r; } + +void +Hierref_DestroyComponent (void *href) +{ + hierref_t ref = *(hierref_t *) href; + if (ref.hierarchy) { + Hierarchy_RemoveHierarchy (ref.hierarchy, ref.index, 1); + if (!ref.hierarchy->num_objects) { + Hierarchy_Delete (ref.hierarchy); + } + } +} diff --git a/libs/ecs/test/test-hierarchy.c b/libs/ecs/test/test-hierarchy.c index ad3aa28f3..3d9be814a 100644 --- a/libs/ecs/test/test-hierarchy.c +++ b/libs/ecs/test/test-hierarchy.c @@ -21,6 +21,7 @@ static const component_t test_components[] = { .size = sizeof (hierref_t), .create = 0,//create_href, .name = "href", + .destroy = Hierref_DestroyComponent, }, [test_name] = { .size = sizeof (const char *), diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 6704e7e48..d7cfa519f 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -99,6 +99,7 @@ static const component_t scene_components[scene_comp_count] = { .size = sizeof (hierref_t), .create = 0,//create_href, .name = "href", + .destroy = Hierref_DestroyComponent, }, [scene_animation] = { .size = sizeof (animation_t), diff --git a/libs/ui/passage.c b/libs/ui/passage.c index 089823267..d3c374d80 100644 --- a/libs/ui/passage.c +++ b/libs/ui/passage.c @@ -48,6 +48,7 @@ const component_t passage_components[passage_comp_count] = { [passage_href] = { .size = sizeof (hierref_t), .name = "passage href", + .destroy = Hierref_DestroyComponent, }, }; diff --git a/libs/ui/test/test-flow-size.c b/libs/ui/test/test-flow-size.c index 40c133aa8..2c6bbf092 100644 --- a/libs/ui/test/test-flow-size.c +++ b/libs/ui/test/test-flow-size.c @@ -18,6 +18,7 @@ static const component_t test_components[] = { .size = sizeof (hierref_t), .create = 0,//create_href, .name = "href", + .destroy = Hierref_DestroyComponent, }, }; diff --git a/libs/ui/test/test-flow.c b/libs/ui/test/test-flow.c index e082447d8..bbcfdeba2 100644 --- a/libs/ui/test/test-flow.c +++ b/libs/ui/test/test-flow.c @@ -18,6 +18,7 @@ static const component_t test_components[] = { .size = sizeof (hierref_t), .create = 0,//create_href, .name = "href", + .destroy = Hierref_DestroyComponent, }, }; diff --git a/libs/ui/view.c b/libs/ui/view.c index 70b8d8326..337cb53f6 100644 --- a/libs/ui/view.c +++ b/libs/ui/view.c @@ -94,6 +94,7 @@ const component_t view_components[view_comp_count] = { [view_href] = { .size = sizeof (hierref_t), .name = "view href", + .destroy = Hierref_DestroyComponent, }, }; From 9982eb629d83daad3029af8b3986408c78f8a6d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 22:41:59 +0900 Subject: [PATCH 3483/3664] [ruamoko] Plug another memory leak Now running vkgen is leak-free (and, by extension, qwaq-cmd, it seems). I'm really not sure why I used a dynamic array for that case. --- ruamoko/qwaq/builtins/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ruamoko/qwaq/builtins/main.c b/ruamoko/qwaq/builtins/main.c index 8b9ff541c..b71e5bef8 100644 --- a/ruamoko/qwaq/builtins/main.c +++ b/ruamoko/qwaq/builtins/main.c @@ -448,10 +448,8 @@ main (int argc, char **argv) COM_InitArgv (qargs->args.size, qargs->args.a); num_sys++; } else { - qwaq_thread_t qargs = {}; - DARRAY_INIT (&qargs.args, 2); - DARRAY_APPEND (&qargs.args, this_program); - COM_InitArgv (qargs.args.size, qargs.args.a); + const char *args[] = { this_program, 0 }; + COM_InitArgv (1, args); } init_qf (); From e19e7cad0c96227cb4a66baaa9ebc550e990affc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 5 Mar 2023 23:31:20 +0900 Subject: [PATCH 3484/3664] [ecs] Invalidate entity before removing components It turns out that the fixes for other problems related to removing hierarchy reference components fixed the problem moving the entity invalidation fixed, and invalidating the entity late somehow broke the sprite renderer (at least in glsl). --- libs/ecs/ecs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/ecs/ecs.c b/libs/ecs/ecs.c index 0a4afaa04..af9870219 100644 --- a/libs/ecs/ecs.c +++ b/libs/ecs/ecs.c @@ -209,13 +209,13 @@ ECS_DelEntity (ecs_registry_t *registry, uint32_t ent) } uint32_t next = registry->next | Ent_NextGen (Ent_Generation (ent)); uint32_t id = Ent_Index (ent); + registry->entities[id] = next; + registry->next = id; + registry->available++; for (uint32_t i = 0; i < registry->components.size; i++) { Ent_RemoveComponent (ent, i, registry); } - registry->entities[id] = next; - registry->next = id; - registry->available++; } VISIBLE void From d14162eed99ed8ab49de414c4124429bd350f4c4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Mar 2023 01:52:57 +0900 Subject: [PATCH 3485/3664] [model] Ensure all models are unloaded Cleans up not only vulkan (had to remove the clearing from vulkan to avoid a segfault). --- libs/models/model.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/models/model.c b/libs/models/model.c index 47a1b54bb..6e5aade5d 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -103,6 +103,7 @@ static void Mod_CallbackLoad (void *object, cache_allocator_t allocator); static void mod_shutdown (void *data) { + Mod_ClearAll (); for (size_t i = 0; i < mod_blocks.size; i++) { free (mod_blocks.a[i]); } From e079d95cb08c1dc27d1406c48e0aa38dc1cbac47 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Mar 2023 12:49:02 +0900 Subject: [PATCH 3486/3664] [vkgen] Add header guards to stdint.h Recent vulkan headers have added at least one more include of stdint.h, so need to protect against the double-inclusion. --- libs/video/renderer/vulkan/vkgen/stdint.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/video/renderer/vulkan/vkgen/stdint.h b/libs/video/renderer/vulkan/vkgen/stdint.h index 740574d18..77dce217f 100644 --- a/libs/video/renderer/vulkan/vkgen/stdint.h +++ b/libs/video/renderer/vulkan/vkgen/stdint.h @@ -1,3 +1,5 @@ +#ifndef __vkgen_stdint_h +#define __vkgen_stdint_h typedef int uint8_t; typedef int uint16_t; typedef int uint32_t; @@ -8,3 +10,4 @@ typedef int int32_t; typedef int int64_t; typedef int size_t; typedef struct char { int x; } char; +#endif//__vkgen_stdint_h From 45c0341dafa5a432fef499d824a8e0f5db937b39 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Mar 2023 13:06:05 +0900 Subject: [PATCH 3487/3664] [qfcc] Actually skip compile for -E etc The preprocess-only option wasn't being checked enough. --- tools/qfcc/source/qfcc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 98120e825..e0b15f04c 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -394,7 +394,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) } *yyin = preprocess_file (file, 0); - if (!*yyin) + if (options.preprocess_only || !*yyin) return !options.preprocess_only; InitData (); @@ -568,7 +568,7 @@ separate_compile (void) } dstring_delete (output_file); dstring_delete (extension); - if (!err && !options.compile) { + if (!err && !options.compile && !options.preprocess_only) { InitData (); chain_initial_types (); linker_begin (); @@ -659,7 +659,7 @@ compile_file (const char *filename) int (*yyparse) (void) = qc_yyparse; *yyin = preprocess_file (filename, 0); - if (!*yyin) + if (options.preprocess_only || !*yyin) return !options.preprocess_only; add_source_file (filename); @@ -717,6 +717,9 @@ progs_src_compile (void) exit (1); } } + if (options.preprocess_only) { + return 0; + } src = load_file (filename->str); if (!src) { From 488ccdc51233d7f54afac39d39d145371a476e0f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Mar 2023 18:21:13 +0900 Subject: [PATCH 3488/3664] [glsl] Be more null-safe for free/destroy functions --- libs/ecs/ecs.c | 3 +++ libs/scene/entity.c | 3 +++ libs/util/dstring.c | 3 +++ libs/util/hash.c | 3 +++ libs/video/renderer/glsl/glsl_draw.c | 4 ++++ libs/video/renderer/glsl/glsl_textures.c | 3 +++ libs/video/renderer/r_scrap.c | 3 +++ libs/video/targets/vid.c | 12 ++++++++---- 8 files changed, 30 insertions(+), 4 deletions(-) diff --git a/libs/ecs/ecs.c b/libs/ecs/ecs.c index af9870219..291271bd1 100644 --- a/libs/ecs/ecs.c +++ b/libs/ecs/ecs.c @@ -46,6 +46,9 @@ ECS_NewRegistry (void) VISIBLE void ECS_DelRegistry (ecs_registry_t *registry) { + if (!registry) { + return; + } registry->locked = 1; for (uint32_t i = 0; i < registry->components.size; i++) { __auto_type comp = ®istry->components.a[i]; diff --git a/libs/scene/entity.c b/libs/scene/entity.c index 8d88ea8c1..e984865f6 100644 --- a/libs/scene/entity.c +++ b/libs/scene/entity.c @@ -52,6 +52,9 @@ EntQueue_New (int num_queues) void EntQueue_Delete (entqueue_t *queue) { + if (!queue) { + return; + } for (int i = 0; i < queue->num_queues; i++) { DARRAY_CLEAR (&queue->ent_queues[i]); } diff --git a/libs/util/dstring.c b/libs/util/dstring.c index 035a5a42e..dc478b8c2 100644 --- a/libs/util/dstring.c +++ b/libs/util/dstring.c @@ -83,6 +83,9 @@ dstring_new (void) VISIBLE void dstring_delete (dstring_t *dstr) { + if (!dstr) { + return; + } if (dstr->str) dstr->mem->free (dstr->mem->data, dstr->str); dstr->mem->free (dstr->mem->data, dstr); diff --git a/libs/util/hash.c b/libs/util/hash.c index 1fb9cb643..28bf9a93f 100644 --- a/libs/util/hash.c +++ b/libs/util/hash.c @@ -283,6 +283,9 @@ Hash_SetHashCompare (hashtab_t *tab, uintptr_t (*gh)(const void*,void*), VISIBLE void Hash_DelTable (hashtab_t *tab) { + if (!tab) { + return; + } Hash_FlushTable (tab); free (tab); } diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 1ee895fd7..ca11b1689 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -168,6 +168,10 @@ make_glpic (const char *name, qpic_t *p) static void pic_free (qpic_t *pic) { + if (!pic) { + return; + } + subpic_t *subpic = *(subpic_t **) pic->data; GLSL_SubpicDelete (subpic); diff --git a/libs/video/renderer/glsl/glsl_textures.c b/libs/video/renderer/glsl/glsl_textures.c index 657ffa3f6..a33cb86fa 100644 --- a/libs/video/renderer/glsl/glsl_textures.c +++ b/libs/video/renderer/glsl/glsl_textures.c @@ -394,6 +394,9 @@ GLSL_ScrapClear (scrap_t *scrap) void GLSL_DestroyScrap (scrap_t *scrap) { + if (!scrap) { + return; + } scrap_t **s; for (s = &scrap_list; *s; s = &(*s)->next) { diff --git a/libs/video/renderer/r_scrap.c b/libs/video/renderer/r_scrap.c index 591720a8f..3c34f3670 100644 --- a/libs/video/renderer/r_scrap.c +++ b/libs/video/renderer/r_scrap.c @@ -65,6 +65,9 @@ R_ScrapInit (rscrap_t *scrap, int width, int height) VISIBLE void R_ScrapDelete (rscrap_t *scrap) { + if (!scrap) { + return; + } R_ScrapClear (scrap); VRect_Delete (scrap->free_rects); } diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index cca24b2af..388baee6d 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -328,10 +328,14 @@ VID_shutdown (void *data) free (viddef.palette); free (viddef.palette32); - DARRAY_CLEAR (viddef.onPaletteChanged); - DARRAY_CLEAR (viddef.onVidResize); - free (viddef.onPaletteChanged); - free (viddef.onVidResize); + if (viddef.onPaletteChanged) { + DARRAY_CLEAR (viddef.onPaletteChanged); + free (viddef.onPaletteChanged); + } + if (viddef.onVidResize) { + DARRAY_CLEAR (viddef.onVidResize); + free (viddef.onVidResize); + } } VISIBLE void From 5821ef8d1fbea3bbafae8a67cfde085dab9e5e53 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Mar 2023 21:04:00 +0900 Subject: [PATCH 3489/3664] [model] Reset mod_numknown when clearing models Vulkan actually needs Mod_ClearAll, and mod_numknown not getting reset was the actual cause of the segfault. --- libs/models/model.c | 1 + libs/video/renderer/vid_render_vulkan.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libs/models/model.c b/libs/models/model.c index 6e5aade5d..9258f6098 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -178,6 +178,7 @@ Mod_ClearAll (void) for (i = 0; i < mod_numknown; i++) { mod_unload_model (i); } + mod_numknown = 0; } model_t * diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a6c7f9950..17e73acb7 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -725,6 +725,7 @@ vulkan_vid_render_shutdown (void) QFV_DeviceWaitIdle (device); SCR_Shutdown (); + Mod_ClearAll (); Vulkan_Compose_Shutdown (vulkan_ctx); Vulkan_Translucent_Shutdown (vulkan_ctx); From f12b3ea134dd0f1d4df9f57166e44a71d638c364 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Mar 2023 21:15:15 +0900 Subject: [PATCH 3490/3664] [vid] Allow render systems to unload late This cleans up the tangled mess of attempting to unload the gl driver in X11: for whatever reason, the display gets tied in to the library. --- include/context_win.h | 7 ++++--- include/context_x11.h | 7 ++++--- include/vid_gl.h | 3 +-- include/vid_internal.h | 22 ++++++++++++---------- libs/video/renderer/sw/d_init.c | 4 ++-- libs/video/renderer/sw/draw.c | 2 +- libs/video/renderer/vid_render_gl.c | 14 +++++++------- libs/video/renderer/vid_render_glsl.c | 16 +++++++--------- libs/video/renderer/vid_render_sw.c | 3 +-- libs/video/renderer/vid_render_vulkan.c | 10 +++++----- libs/video/targets/vid.c | 4 ++-- libs/video/targets/vid_win.c | 2 +- libs/video/targets/vid_win_gl.c | 6 ++++-- libs/video/targets/vid_win_sw.c | 6 ++++-- libs/video/targets/vid_win_vulkan.c | 4 +++- libs/video/targets/vid_x11.c | 11 +++++++---- libs/video/targets/vid_x11_gl.c | 20 ++++++++++++++------ libs/video/targets/vid_x11_sw.c | 4 +++- libs/video/targets/vid_x11_vulkan.c | 4 +++- 19 files changed, 85 insertions(+), 64 deletions(-) diff --git a/include/context_win.h b/include/context_win.h index 4921ce24f..fdd068011 100644 --- a/include/context_win.h +++ b/include/context_win.h @@ -57,13 +57,14 @@ void Win_UpdateWindowStatus (int x, int y); void Win_SetCaption (const char *text); qboolean Win_SetGamma (double gamma); -struct gl_ctx_s *Win_GL_Context (void); +struct vid_internal_s; +struct gl_ctx_s *Win_GL_Context (struct vid_internal_s *); void Win_GL_Init_Cvars (void); -struct sw_ctx_s *Win_SW_Context (void); +struct sw_ctx_s *Win_SW_Context (struct vid_internal_s *); void Win_SW_Init_Cvars (void); -struct vulkan_ctx_s *Win_Vulkan_Context (void); +struct vulkan_ctx_s *Win_Vulkan_Context (struct vid_internal_s *); void Win_Vulkan_Init_Cvars (void); void IN_UpdateClipCursor (void); diff --git a/include/context_x11.h b/include/context_x11.h index 48e350826..77c913034 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -80,13 +80,14 @@ void X11_SaveMouseAcceleration (void); void X11_RemoveMouseAcceleration (void); void X11_RestoreMouseAcceleration (void); -struct gl_ctx_s *X11_GL_Context (void); +struct vid_internal_s; +struct gl_ctx_s *X11_GL_Context (struct vid_internal_s *); void X11_GL_Init_Cvars (void); -struct sw_ctx_s *X11_SW_Context (void); +struct sw_ctx_s *X11_SW_Context (struct vid_internal_s *); void X11_SW_Init_Cvars (void); -struct vulkan_ctx_s *X11_Vulkan_Context (void); +struct vulkan_ctx_s *X11_Vulkan_Context (struct vid_internal_s *); void X11_Vulkan_Init_Cvars (void); #endif // __context_x11_h_ diff --git a/include/vid_gl.h b/include/vid_gl.h index e1bd68d2a..a89264d13 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -8,8 +8,7 @@ typedef struct GL_context *GL_context; typedef struct gl_ctx_s { GL_context context; - void (*load_gl) (void); - void (*unload_gl) (struct gl_ctx_s *ctx); + void (*load_gl) (struct gl_ctx_s *ctx); void (*choose_visual) (struct gl_ctx_s *ctx); void (*create_context) (struct gl_ctx_s *ctx, int core); void (*init_gl) (void); diff --git a/include/vid_internal.h b/include/vid_internal.h index dc9ca3177..293098f1f 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -15,19 +15,21 @@ typedef struct vid_system_s { extern vid_system_t vid_system; typedef struct vid_internal_s { - void (*flush_caches) (void *data); - void (*init_buffers) (void *data); - void (*set_palette) (void *data, const byte *palette); - void (*set_colormap) (void *data, const byte *colormap); + void (*flush_caches) (void *ctx); + void (*init_buffers) (void *ctx); + void (*set_palette) (void *ctx, const byte *palette); + void (*set_colormap) (void *ctx, const byte *colormap); - void (*choose_visual) (void *data); - void (*create_context) (void *data); + void (*choose_visual) (void *ctx); + void (*create_context) (void *ctx); - void *data; + void *ctx; - struct gl_ctx_s *(*gl_context) (void); - struct sw_ctx_s *(*sw_context) (void); - struct vulkan_ctx_s *(*vulkan_context) (void); + struct gl_ctx_s *(*gl_context) (struct vid_internal_s *); + struct sw_ctx_s *(*sw_context) (struct vid_internal_s *); + struct vulkan_ctx_s *(*vulkan_context) (struct vid_internal_s *); + + void (*unload) (void *data); } vid_internal_t; extern int vid_fullscreen; diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index b7e475ac1..3aa563a20 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -55,12 +55,12 @@ d_vidsize_listener (void *data, const viddef_t *vid) int cachesize = D_SurfaceCacheForRes (vid->width, vid->height); if (surfcache) { - D_FlushCaches (vid->vid_internal->data); + D_FlushCaches (vid->vid_internal->ctx); free (surfcache); surfcache = 0; } surfcache = calloc (cachesize, 1); - vid->vid_internal->init_buffers (vid->vid_internal->data); + vid->vid_internal->init_buffers (vid->vid_internal->ctx); D_InitCaches (surfcache, cachesize); viddef.recalc_refdef = 1; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 7c19bc473..6a79f14b3 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -1019,7 +1019,7 @@ Draw_BlendScreen (quat_t color) newpal[2] = vid.gammatable[b]; newpal += 3; } - vid.vid_internal->set_palette (vid.vid_internal->data, pal); + vid.vid_internal->set_palette (vid.vid_internal->ctx, pal); } int diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 4a2cb08a3..c3870df6a 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -183,17 +183,17 @@ static vid_model_funcs_t model_funcs = { static void gl_vid_render_init (void) { - if (!vr_data.vid->vid_internal->sw_context) { + if (!vr_data.vid->vid_internal->gl_context) { Sys_Error ("Sorry, OpenGL not supported by this program."); } - gl_ctx = vr_data.vid->vid_internal->gl_context (); + vid_internal_t *vi = vr_data.vid->vid_internal; + gl_ctx = vi->gl_context (vi); gl_ctx->init_gl = GL_Init_Common; - gl_ctx->load_gl (); + gl_ctx->load_gl (gl_ctx); - vr_data.vid->vid_internal->data = gl_ctx; - vr_data.vid->vid_internal->set_palette = GL_SetPalette; - vr_data.vid->vid_internal->choose_visual = gl_vid_render_choose_visual; - vr_data.vid->vid_internal->create_context = gl_vid_render_create_context; + vi->set_palette = GL_SetPalette; + vi->choose_visual = gl_vid_render_choose_visual; + vi->create_context = gl_vid_render_create_context; vr_funcs = &gl_vid_render_funcs; m_funcs = &model_funcs; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index d7c9120b6..38318ab1d 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -94,17 +94,17 @@ static vid_model_funcs_t model_funcs = { static void glsl_vid_render_init (void) { - if (!vr_data.vid->vid_internal->sw_context) { + if (!vr_data.vid->vid_internal->gl_context) { Sys_Error ("Sorry, OpenGL (GLSL) not supported by this program."); } - glsl_ctx = vr_data.vid->vid_internal->gl_context (); + vid_internal_t *vi = vr_data.vid->vid_internal; + glsl_ctx = vi->gl_context (vi); glsl_ctx->init_gl = GLSL_Init_Common; - glsl_ctx->load_gl (); + glsl_ctx->load_gl (glsl_ctx); - vr_data.vid->vid_internal->data = glsl_ctx; - vr_data.vid->vid_internal->set_palette = GLSL_SetPalette; - vr_data.vid->vid_internal->choose_visual = glsl_vid_render_choose_visual; - vr_data.vid->vid_internal->create_context = glsl_vid_render_create_context; + vi->set_palette = GLSL_SetPalette; + vi->choose_visual = glsl_vid_render_choose_visual; + vi->create_context = glsl_vid_render_create_context; vr_funcs = &glsl_vid_render_funcs; m_funcs = &model_funcs; } @@ -114,8 +114,6 @@ glsl_vid_render_shutdown (void) { glsl_R_Shutdown (); GLSL_Shutdown_Common (); - - glsl_ctx->unload_gl (glsl_ctx); } static unsigned int GLErr_InvalidEnum; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 5838c5c40..660b0fa30 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -106,9 +106,8 @@ sw_vid_render_init (void) if (!vr_data.vid->vid_internal->sw_context) { Sys_Error ("Sorry, software rendering not supported by this program."); } - sw_ctx = vr_data.vid->vid_internal->sw_context (); + sw_ctx = vr_data.vid->vid_internal->sw_context (vr_data.vid->vid_internal); - vr_data.vid->vid_internal->data = sw_ctx; vr_data.vid->vid_internal->set_palette = sw_vid_render_set_palette; vr_data.vid->vid_internal->set_colormap = sw_vid_render_set_colormap; vr_data.vid->vid_internal->choose_visual = sw_vid_render_choose_visual; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 17e73acb7..75d963d31 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -699,15 +699,15 @@ vulkan_vid_render_init (void) if (!vr_data.vid->vid_internal->vulkan_context) { Sys_Error ("Sorry, Vulkan not supported by this program."); } - vulkan_ctx = vr_data.vid->vid_internal->vulkan_context (); + vid_internal_t *vi = vr_data.vid->vid_internal; + vulkan_ctx = vi->vulkan_context (vi); vulkan_ctx->load_vulkan (vulkan_ctx); Vulkan_Init_Common (vulkan_ctx); - vr_data.vid->vid_internal->data = vulkan_ctx; - vr_data.vid->vid_internal->set_palette = set_palette; - vr_data.vid->vid_internal->choose_visual = vulkan_vid_render_choose_visual; - vr_data.vid->vid_internal->create_context = vulkan_vid_render_create_context; + vi->set_palette = set_palette; + vi->choose_visual = vulkan_vid_render_choose_visual; + vi->create_context = vulkan_vid_render_create_context; vr_funcs = &vulkan_vid_render_funcs; m_funcs = &model_funcs; diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 388baee6d..67465191f 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -224,7 +224,7 @@ VID_UpdateGamma (void) } p32[-1] = 0; // color 255 is transparent // update with the new palette - vi->set_palette (vi->data, viddef.palette); + vi->set_palette (vi->ctx, viddef.palette); } } @@ -276,7 +276,7 @@ void VID_ClearMemory (void) { if (vi->flush_caches) { - vi->flush_caches (vi->data); + vi->flush_caches (vi->ctx); } } diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 492dfd8f8..8f1cd9289 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -123,7 +123,7 @@ Win_VID_SetPalette (byte *palette, byte *colormap) viddef.colormap8 = colormap; viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; if (vid_internal.set_colormap) { - vid_internal.set_colormap (vid_internal.data, colormap); + vid_internal.set_colormap (vid_internal.ctx, colormap); } VID_InitGamma (palette); diff --git a/libs/video/targets/vid_win_gl.c b/libs/video/targets/vid_win_gl.c index 8e5b9d07a..5e63c7fee 100644 --- a/libs/video/targets/vid_win_gl.c +++ b/libs/video/targets/vid_win_gl.c @@ -177,7 +177,7 @@ wgl_end_rendering (void) } static void -wgl_load_gl (void) +wgl_load_gl (gl_ctx_t *ctx) { libgl_handle = LoadLibrary (gl_driver); if (!libgl_handle) { @@ -198,7 +198,7 @@ wgl_load_gl (void) } gl_ctx_t * -Win_GL_Context (void) +Win_GL_Context (vid_internal_t *vi) { gl_ctx_t *ctx = calloc (1, sizeof (gl_ctx_t)); ctx->load_gl = wgl_load_gl; @@ -206,6 +206,8 @@ Win_GL_Context (void) ctx->create_context = wgl_create_context; ctx->get_proc_address = QFGL_ProcAddress; ctx->end_rendering = wgl_end_rendering; + + vi->ctx = ctx; return ctx; } diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index 052cad570..e338d2ede 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -233,7 +233,7 @@ VID_CreateGDIDriver (int width, int height, const byte *palette, byte **buffer, // create a palette VID_InitGamma (palette); - viddef.vid_internal->set_palette (viddef.vid_internal->data, palette); + viddef.vid_internal->set_palette (viddef.vid_internal->ctx, palette); } void @@ -478,13 +478,15 @@ win_create_context (sw_ctx_t *ctx) } sw_ctx_t * -Win_SW_Context (void) +Win_SW_Context (vid_internal_t *vi) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); ctx->set_palette = win_set_palette; ctx->choose_visual = win_choose_visual; ctx->create_context = win_create_context; ctx->update = win_sw_update; + + vi->ctx = ctx; return ctx; } diff --git a/libs/video/targets/vid_win_vulkan.c b/libs/video/targets/vid_win_vulkan.c index 5ae2c4d61..99ee645ab 100644 --- a/libs/video/targets/vid_win_vulkan.c +++ b/libs/video/targets/vid_win_vulkan.c @@ -174,7 +174,7 @@ win_vulkan_create_surface (vulkan_ctx_t *ctx) } vulkan_ctx_t * -Win_Vulkan_Context (void) +Win_Vulkan_Context (vid_internal_t *vi) { vulkan_ctx_t *ctx = calloc (1, sizeof (vulkan_ctx_t)); ctx->load_vulkan = load_vulkan_library; @@ -186,6 +186,8 @@ Win_Vulkan_Context (void) ctx->required_extensions = required_extensions; ctx->va_ctx = va_create_context (4); ctx->twod_scale = 1; + + vi->ctx = ctx; return ctx; } diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index be2449a28..53e03b82a 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -86,6 +86,9 @@ X11_VID_Shutdown (void) { Sys_MaskPrintf (SYS_vid, "X11_VID_shutdown\n"); X11_CloseDisplay (); + if (vid_internal.unload) { + vid_internal.unload (vid_internal.ctx); + } } static void @@ -94,11 +97,11 @@ X11_VID_SetPalette (byte *palette, byte *colormap) viddef.colormap8 = colormap; viddef.fullbright = 256 - viddef.colormap8[256 * VID_GRADES]; if (vid_internal.set_colormap) { - vid_internal.set_colormap (vid_internal.data, colormap); + vid_internal.set_colormap (vid_internal.ctx, colormap); } VID_InitGamma (palette); - vid_internal.set_palette (vid_internal.data, viddef.palette); + vid_internal.set_palette (vid_internal.ctx, viddef.palette); } /* @@ -123,11 +126,11 @@ X11_VID_Init (byte *palette, byte *colormap) VID_GetWindowSize (640, 480); X11_OpenDisplay (); - vid_internal.choose_visual (vid_internal.data); + vid_internal.choose_visual (vid_internal.ctx); X11_SetVidMode (viddef.width, viddef.height); X11_CreateWindow (viddef.width, viddef.height); X11_CreateNullCursor (); // hide mouse pointer - vid_internal.create_context (vid_internal.data); + vid_internal.create_context (vid_internal.ctx); X11_VID_SetPalette (palette, colormap); diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index 1da4b6c6c..9f4003667 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -103,6 +103,7 @@ static GLXContext (*qfglXCreateContextAttribsARB) (Display *dpy, GLXContext ctx, Bool direct, const int *attribs); +static void (*qfglXDestroyContext) ( Display *dpy, GLXContext ctx ); static GLXFBConfig *(*qfglXChooseFBConfig) (Display *dpy, int screen, const int *attribs, int *nitems); static XVisualInfo *(*qfglXGetVisualFromFBConfig) (Display *dpy, @@ -191,8 +192,8 @@ glx_choose_visual (gl_ctx_t *ctx) } Sys_MaskPrintf (SYS_vid, "Found %d matching FB configs.\n", fbcount); glx_cfg = fbc[0]; - XFree (fbc); x_visinfo = qfglXGetVisualFromFBConfig (x_disp, glx_cfg); + XFree (fbc); if (!x_visinfo) { Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth visual"); } @@ -225,7 +226,7 @@ glx_end_rendering (void) } static void -glx_load_gl (void) +glx_load_gl (gl_ctx_t *ctx) { libgl_handle = dlopen (gl_driver, RTLD_NOW); if (!libgl_handle) { @@ -241,6 +242,7 @@ glx_load_gl (void) qfglXGetVisualFromFBConfig = QFGL_ProcAddress ("glXGetVisualFromFBConfig", true); qfglXGetFBConfigAttrib = QFGL_ProcAddress ("glXGetFBConfigAttrib", true); qfglXCreateContextAttribsARB = QFGL_ProcAddress ("glXCreateContextAttribsARB", true); + qfglXDestroyContext = QFGL_ProcAddress ("glXDestroyContext", true); qfglXMakeCurrent = QFGL_ProcAddress ("glXMakeCurrent", true); use_gl_procaddress = 1; @@ -249,22 +251,28 @@ glx_load_gl (void) } static void -glx_unload_gl (gl_ctx_t *ctx) +glx_unload_gl (void *_ctx) { - dlclose (libgl_handle); + gl_ctx_t *ctx = _ctx; + if (libgl_handle) { + dlclose (libgl_handle); + libgl_handle = 0; + } free (ctx); } gl_ctx_t * -X11_GL_Context (void) +X11_GL_Context (vid_internal_t *vi) { gl_ctx_t *ctx = calloc (1, sizeof (gl_ctx_t)); ctx->load_gl = glx_load_gl; - ctx->unload_gl = glx_unload_gl; ctx->choose_visual = glx_choose_visual; ctx->create_context = glx_create_context; ctx->get_proc_address = QFGL_ProcAddress; ctx->end_rendering = glx_end_rendering; + + vi->unload = glx_unload_gl; + vi->ctx = ctx; return ctx; } diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 6d35fb443..636b7991b 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -693,13 +693,15 @@ x11_create_context (sw_ctx_t *ctx) } sw_ctx_t * -X11_SW_Context (void) +X11_SW_Context (vid_internal_t *vi) { sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); ctx->set_palette = x11_set_palette; ctx->choose_visual = x11_choose_visual; ctx->create_context = x11_create_context; ctx->update = x11_sw8_8_update; + + vi->ctx = ctx; return ctx; } diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index 66f15073a..66579b3ed 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -213,7 +213,7 @@ x11_vulkan_create_surface (vulkan_ctx_t *ctx) } vulkan_ctx_t * -X11_Vulkan_Context (void) +X11_Vulkan_Context (vid_internal_t *vi) { vulkan_ctx_t *ctx = calloc (1, sizeof (vulkan_ctx_t)); ctx->load_vulkan = load_vulkan_library; @@ -225,6 +225,8 @@ X11_Vulkan_Context (void) ctx->required_extensions = required_extensions; ctx->va_ctx = va_create_context (32); ctx->twod_scale = 1; + + vi->ctx = ctx; return ctx; } From 00d1ae0b91d30d27ea80ca201cab619711995ce7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 7 Mar 2023 02:00:19 +0900 Subject: [PATCH 3491/3664] [ecs] Invalidate entity in hierarchy before removal I'm not sure just what was going on other than *other* components were getting double-removed when the hierarchy reference component was removed when the entity was being deleted. This might even prevent issues with removing the hierarchy from an entity that's not being deleted as the pre-invalidation prevents the removal from deleting the entity. --- libs/ecs/ecs.c | 3 +++ libs/ecs/hierarchy.c | 1 + 2 files changed, 4 insertions(+) diff --git a/libs/ecs/ecs.c b/libs/ecs/ecs.c index 291271bd1..3466e4423 100644 --- a/libs/ecs/ecs.c +++ b/libs/ecs/ecs.c @@ -205,6 +205,9 @@ ECS_NewEntity (ecs_registry_t *registry) VISIBLE void ECS_DelEntity (ecs_registry_t *registry, uint32_t ent) { + if (!ECS_EntValid (ent, registry)) { + return; + } if (registry->locked) { // the registry is being deleted and mass entity and component // deletions are going on diff --git a/libs/ecs/hierarchy.c b/libs/ecs/hierarchy.c index 58caca7ff..58328978a 100644 --- a/libs/ecs/hierarchy.c +++ b/libs/ecs/hierarchy.c @@ -482,6 +482,7 @@ Hierref_DestroyComponent (void *href) { hierref_t ref = *(hierref_t *) href; if (ref.hierarchy) { + ref.hierarchy->ent[ref.index] = -1; Hierarchy_RemoveHierarchy (ref.hierarchy, ref.index, 1); if (!ref.hierarchy->num_objects) { Hierarchy_Delete (ref.hierarchy); From 549ffcd5347c4f69733910071bcc5ab82e113a57 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 7 Mar 2023 13:17:46 +0900 Subject: [PATCH 3492/3664] [qfcc] Add failing test for function/array pointers It turns out I broke the type system when it comes to pointers to functions and arrays. This test checks basic function and array pointers and passes with qfcc from before the type system rework. --- tools/qfcc/test/Makemodule.am | 11 ++++++ tools/qfcc/test/ptrfunc.r | 72 +++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 tools/qfcc/test/ptrfunc.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index ea2ba9f70..faf0eb9bb 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -42,6 +42,7 @@ test_progs_dat=\ tools/qfcc/test/paramret.dat \ tools/qfcc/test/postop.dat \ tools/qfcc/test/ptraliasenc.dat \ + tools/qfcc/test/ptrfunc.dat \ tools/qfcc/test/ptrstructcast.dat \ tools/qfcc/test/quaternion.dat \ tools/qfcc/test/return-ivar.dat \ @@ -517,6 +518,16 @@ tools/qfcc/test/ptraliasenc.run: $(qfcc_test_run_deps) include $(ptraliasenc_dep) # am--include-marker r_depfiles_remade += $(ptraliasenc_dep) +tools_qfcc_test_ptrfunc_dat_SOURCES=tools/qfcc/test/ptrfunc.r +ptrfunc_obj=$(tools_qfcc_test_ptrfunc_dat_SOURCES:.r=.o) +ptrfunc_dep=$(call qcautodep,$(tools_qfcc_test_ptrfunc_dat_SOURCES)) +tools/qfcc/test/ptrfunc.dat$(EXEEXT): $(ptrfunc_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(ptrfunc_obj) +tools/qfcc/test/ptrfunc.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(ptrfunc_dep) # am--include-marker +r_depfiles_remade += $(ptrfunc_dep) + tools_qfcc_test_ptrstructcast_dat_SOURCES=tools/qfcc/test/ptrstructcast.r ptrstructcast_obj=$(tools_qfcc_test_ptrstructcast_dat_SOURCES:.r=.o) ptrstructcast_dep=$(call qcautodep,$(tools_qfcc_test_ptrstructcast_dat_SOURCES)) diff --git a/tools/qfcc/test/ptrfunc.r b/tools/qfcc/test/ptrfunc.r new file mode 100644 index 000000000..12d4a77c7 --- /dev/null +++ b/tools/qfcc/test/ptrfunc.r @@ -0,0 +1,72 @@ +int func(string x) { return 1; } +int (*funcptr)(string); +int *(*ptrfuncptr)(string); +int array[7]; +int *ptrarray[7]; +int (*arrayptr)[7]; +int *(*ptrarrayptr)[7]; + +#include + +#include "test-harness.h" + +typedef struct xdef_s { + qfot_type_t *type; ///< pointer to type definition + void *ofs; ///< 32-bit version of ddef_t.ofs +} xdef_t; + +typedef struct xdefs_s { + xdef_t *xdefs; + unsigned num_xdefs; +} xdefs_t; + +void *PR_FindGlobal (string name) = #0; + +xdef_t * +find_xdef (void *varaddr) +{ + //FIXME need a simple way to get at a def's meta-data + xdefs_t *xdefs = PR_FindGlobal (".xdefs"); + xdef_t *xdef = xdefs.xdefs; + while (xdef - xdefs.xdefs < xdefs.num_xdefs && xdef.ofs != varaddr) { + xdef++; + } + if (xdef.ofs != varaddr) { + return nil; + } + return xdef; +} + +int +check_var (string name, string encoding) +{ + void *var = PR_FindGlobal (name); + if (!var) { + printf ("could not find var: %s\n", name); + return 0; + } + xdef_t *xdef = find_xdef (var); + if (!var) { + printf ("could not find xdef var: %s @ %p\n", name, var); + return 0; + } + int ok = xdef.type.encoding == encoding; + printf ("%s: %p %s %s %s\n", name, var, xdef.type.encoding, encoding, + ok ? "pass" : "fail"); + return ok; +} + +int +main (void) +{ + int ok = 1; + ok &= check_var ("PR_FindGlobal", "(^v*)"); + ok &= check_var ("func", "(i*)"); + ok &= check_var ("funcptr", "^(i*)"); + ok &= check_var ("ptrfuncptr", "^(^i*)"); + ok &= check_var ("array", "[7=i]"); + ok &= check_var ("ptrarray", "[7=^i]"); + ok &= check_var ("arrayptr", "^[7=i]"); + ok &= check_var ("ptrarrayptr", "^[7=^i]"); + return 1 & (!ok); +} From cee00c8243a1dbcdd32fddc40897b6ff64c3b9f5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Mar 2023 02:22:23 +0900 Subject: [PATCH 3493/3664] [qfcc] Fix declarators for pointers/functions/arrays I had messed up the handling of declarators for combinations of pointer, function, and array: the pointer would get lost (and presumably arrays of functions etc). I think I had gotten confused and thought things were a tree rather than a simple list, but Holub set me straight once again (I've never regretted getting that book). Once I understood that, it was just a matter of finding all the places that needed to be fixed. Nicely, most of the duplicated code has been refactored and should be easier to debug in the future. --- tools/qfcc/include/function.h | 1 - tools/qfcc/include/symtab.h | 1 + tools/qfcc/source/function.c | 20 --- tools/qfcc/source/qc-parse.y | 292 ++++++++++++++++++++-------------- tools/qfcc/source/symtab.c | 21 ++- tools/qfcc/source/type.c | 21 +-- 6 files changed, 206 insertions(+), 150 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index a82714259..af1f06bde 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -149,7 +149,6 @@ param_t *reverse_params (param_t *params); param_t *append_params (param_t *params, param_t *more_params); param_t *copy_params (param_t *params); struct type_s *parse_params (struct type_s *return_type, param_t *params); -struct specifier_s parse_qc_params (struct specifier_s spec, param_t *params); param_t *check_params (param_t *params); diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index 6dc2b2fa0..ad6204f8d 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -252,6 +252,7 @@ symbol_t *make_symbol (const char *name, struct type_s *type, struct specifier_s; symbol_t *declare_symbol (struct specifier_s spec, struct expr_s *init, symtab_t *symtab); +symbol_t *declare_field (struct specifier_s spec, symtab_t *symtab); ///@} diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 45b1311eb..b02dc30c4 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -218,26 +218,6 @@ parse_params (type_t *return_type, param_t *parms) return new; } -specifier_t -parse_qc_params (specifier_t spec, param_t *params) -{ - type_t **type; - // .float () foo; is a field holding a function variable rather - // than a function that returns a float field. - for (type = &spec.type; *type && is_field (*type); - type = &(*type)->t.fldptr.type) { - } - type_t *ret_type = *type; - *type = 0; - *type = parse_params (ret_type, params); - set_func_type_attrs ((*type), spec); - if (spec.type->type != ev_field) { - spec.is_function = 1; //FIXME do proper void(*)() -> ev_func - spec.params = params; - } - return spec; -} - param_t * check_params (param_t *params) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 427d0eb4a..ab955e9fa 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -168,7 +168,7 @@ int yylex (void); %type declarator notype_declarator after_type_declarator %type param_declarator param_declarator_starttypename %type param_declarator_nostarttypename -%type absdecl absdecl1 direct_absdecl typename ptr_spec +%type absdecl absdecl1 direct_absdecl typename ptr_spec copy_spec %type qc_comma %type attribute_list attribute @@ -307,6 +307,129 @@ spec_merge (specifier_t spec, specifier_t new) return spec; } +static specifier_t +typename_spec (specifier_t spec) +{ + spec = default_type (spec, 0); + spec.sym->type = find_type (append_type (spec.sym->type, spec.type)); + spec.type = spec.sym->type; + return spec; +} + +static specifier_t +function_spec (specifier_t spec, param_t *params) +{ + // empty param list in an abstract decle does not create a symbol + if (!spec.sym) { + spec.sym = new_symbol (0); + } + spec = default_type (spec, spec.sym); + spec.sym->params = params; + spec.sym->type = append_type (spec.sym->type, parse_params (0, params)); + spec.is_function = 1; //FIXME do proper void(*)() -> ev_func + return spec; +} + +static specifier_t +array_spec (specifier_t spec, unsigned size) +{ + spec = default_type (spec, spec.sym); + spec.sym->type = append_type (spec.sym->type, array_type (0, size)); + return spec; +} + +static specifier_t +pointer_spec (specifier_t quals, specifier_t spec) +{ + spec.sym->type = append_type (spec.sym->type, pointer_type (0)); + return spec; +} + +static specifier_t +parse_qc_params (specifier_t spec, param_t *params) +{ + type_t **type; + // .float () foo; is a field holding a function variable rather + // than a function that returns a float field. + for (type = &spec.type; *type && is_field (*type); + type = &(*type)->t.fldptr.type) { + } + type_t *ret_type = *type; + *type = 0; + + spec.sym = new_symbol (0); + spec.sym->type = spec.type; + spec.type = ret_type; + + spec = function_spec (spec, params); + return spec; +} + +static symbol_t * +funtion_sym_type (specifier_t spec, symbol_t *sym) +{ + sym->type = append_type (spec.sym->type, spec.type); + set_func_type_attrs (sym->type, spec); + sym->type = find_type (sym->type); + return sym; +} + +static symbol_t * +qc_nocode_symbol (specifier_t spec, symbol_t *sym) +{ + sym->params = spec.sym->params; + sym = funtion_sym_type (spec, sym); + return sym; +} + +static symbol_t * +qc_function_symbol (specifier_t spec, symbol_t *sym) +{ + sym = qc_nocode_symbol (spec, sym); + sym = function_symbol (sym, spec.is_overload, 1); + return sym; +} + +static param_t * +make_ellipsis (void) +{ + return new_param (0, 0, 0); +} + +static param_t * +make_param (specifier_t spec) +{ + spec = default_type (spec, spec.sym); + spec.type = find_type (append_type (spec.sym->type, spec.type)); + param_t *param = new_param (0, spec.type, spec.sym->name); + return param; +} + +static param_t * +make_selector (const char *selector, struct type_s *type, const char *name) +{ + param_t *param = new_param (selector, type, name); + return param; +} + +static param_t * +make_qc_param (specifier_t spec, symbol_t *sym) +{ + spec = default_type (spec, sym); + sym->type = spec.type; + param_t *param = new_param (0, sym->type, sym->name); + return param; +} + +static param_t * +make_qc_func_param (specifier_t spec, param_t *params, symbol_t *sym) +{ + spec = parse_qc_params (spec, params); + sym->type = append_type (spec.sym->type, spec.type); + param_t *param = new_param (0, sym->type, sym->name); + return param; +} + static int is_anonymous_struct (specifier_t spec) { @@ -428,8 +551,7 @@ datadef | declspecs_ts initdecls ';' | declspecs_ts qc_func_params { - specifier_t spec = default_type ($1, 0); - $$ = parse_qc_params (spec, $2); + $$ = parse_qc_params ($1, $2); } qc_func_decls | declspecs ';' @@ -464,31 +586,25 @@ qc_param_list qc_first_param : typespec identifier { - $$ = new_param (0, $1.type, $2->name); + $$ = make_qc_param ($1, $2); } | typespec_reserved qc_func_params identifier { - specifier_t spec = default_type ($1, 0); - spec = parse_qc_params (spec, $2); - - $$ = new_param (0, spec.type, $3->name); + $$ = make_qc_func_param ($1, $2, $3); } - | ELLIPSIS { $$ = new_param (0, 0, 0); } + | ELLIPSIS { $$ = make_ellipsis (); } ; qc_param : typespec identifier { - $$ = new_param (0, $1.type, $2->name); + $$ = make_qc_param ($1, $2); } | typespec qc_func_params identifier { - specifier_t spec = default_type ($1, 0); - spec = parse_qc_params (spec, $2); - - $$ = new_param (0, spec.type, $3->name); + $$ = make_qc_func_param ($1, $2, $3); } - | ELLIPSIS { $$ = new_param (0, 0, 0); } + | ELLIPSIS { $$ = make_ellipsis (); } ; /* This rule is used only to get an action before both qc_func_decl and @@ -525,9 +641,7 @@ qc_nocode_func specifier_t spec = $0; symbol_t *sym = $1; expr_t *expr = $4; - sym->params = spec.params; - sym->type = find_type (spec.type); - sym = function_symbol (sym, spec.is_overload, 1); + sym = qc_function_symbol (spec, sym); build_builtin_function (sym, expr, 0, spec.storage); } | identifier '=' expr @@ -543,12 +657,12 @@ qc_nocode_func { specifier_t spec = $0; symbol_t *sym = $1; - sym->type = find_type (spec.type); - if (!local_expr && sym->type->type != ev_field) { - sym->params = spec.params; - sym = function_symbol (sym, spec.is_overload, 1); + if (!local_expr && !is_field (spec.sym->type)) { + sym = qc_function_symbol (spec, sym); + } else { + sym = qc_nocode_symbol (spec, sym); } - if (!local_expr && sym->type->type != ev_field) { + if (!local_expr && !is_field (sym->type)) { // things might be a confused mess from earlier errors if (sym->sy_type == sy_func) make_function (sym, 0, sym->table->space, spec.storage); @@ -565,12 +679,10 @@ qc_code_func : identifier '=' optional_state_expr save_storage { + $$ = current_symtab; specifier_t spec = $0; symbol_t *sym = $1; - $$ = current_symtab; - sym->params = spec.params; - sym->type = find_type (spec.type); - sym = function_symbol (sym, spec.is_overload, 1); + sym = qc_function_symbol (spec, sym); current_func = begin_function (sym, 0, current_symtab, 0, spec.storage); current_symtab = current_func->locals; @@ -595,21 +707,15 @@ after_type_declarator : '(' copy_spec after_type_declarator ')' { $$ = $3; } | after_type_declarator function_params { - specifier_t spec = default_type ($1, $1.sym); - spec.sym->params = $2; - spec.type = parse_params (spec.type, $2); - spec.is_function = 1; //FIXME do proper void(*)() -> ev_func - $$ = spec; + $$ = function_spec ($1, $2); } | after_type_declarator array_decl { - specifier_t spec = default_type ($1, $1.sym); - spec.type = array_type (spec.type, $2); - $$ = spec; + $$ = array_spec ($1, $2); } | '*' ptr_spec after_type_declarator { - $$ = $3; + $$ = pointer_spec ($2, $3); } | TYPE_NAME { @@ -631,33 +737,22 @@ copy_spec ; ptr_spec - : /* empty */ - { - $$ = default_type ($-1, 0); - $$.type = pointer_type ($$.type); - } + : copy_spec // for when no qualifiers are present ; notype_declarator : '(' copy_spec notype_declarator ')' { $$ = $3; } | notype_declarator function_params { - //printf ("notype_declarator p %d\n", pr.source_line); - specifier_t spec = default_type ($1, $1.sym); - spec.sym->params = $2; - spec.type = parse_params (spec.type, $2); - spec.is_function = 1; //FIXME do proper void(*)() -> ev_func - $$ = spec; + $$ = function_spec ($1, $2); } | notype_declarator array_decl { - specifier_t spec = default_type ($1, $1.sym); - spec.type = array_type (spec.type, $2); - $$ = spec; + $$ = array_spec ($1, $2); } | '*' ptr_spec notype_declarator { - $$ = $3; + $$ = pointer_spec ($2, $3); } | NAME { @@ -862,10 +957,7 @@ function_body : ose { specifier_t spec = default_type ($0, $0.sym); - symbol_t *sym = spec.sym; - - set_func_type_attrs (spec.type, spec); - sym->type = find_type (spec.type); + symbol_t *sym = funtion_sym_type (spec, spec.sym); $$ = function_symbol (sym, spec.is_overload, 1); } save_storage @@ -886,10 +978,7 @@ function_body | '=' '#' expr ';' { specifier_t spec = default_type ($0, $0.sym); - symbol_t *sym = spec.sym; - - set_func_type_attrs (spec.type, spec); - sym->type = find_type (spec.type); + symbol_t *sym = funtion_sym_type (spec, spec.sym); sym = function_symbol (sym, spec.is_overload, 1); build_builtin_function (sym, $3, 0, spec.storage); } @@ -1080,15 +1169,7 @@ components component_declarator : declarator { - symbol_t *s = $1.sym; - specifier_t spec = default_type ($1, s); - s->type = find_type (spec.type); - s->sy_type = sy_var; - s->visibility = current_visibility; - symtab_addsymbol (current_symtab, s); - if (!s->table) { - error (0, "duplicate field `%s'", s->name); - } + declare_field ($1, current_symtab); } | declarator ':' expr | ':' expr @@ -1118,7 +1199,7 @@ param_list } | ELLIPSIS { - $$ = new_param (0, 0, 0); + $$ = make_ellipsis (); } ; @@ -1133,33 +1214,32 @@ parameter_list parameter : declspecs_ts param_declarator { - $2 = default_type ($2, $2.sym); - $$ = new_param (0, $2.type, $2.sym->name); + $$ = make_param ($2); } | declspecs_ts notype_declarator { - $2 = default_type ($2, $2.sym); - $$ = new_param (0, $2.type, $2.sym->name); + $$ = make_param ($2); } | declspecs_ts absdecl { - $2 = default_type ($2, $2.sym); - $$ = new_param (0, $2.type, 0); + $$ = make_param ($2); } | declspecs_nosc_nots notype_declarator { - $2 = default_type ($2, $2.sym); - $$ = new_param (0, $2.type, $2.sym->name); + $$ = make_param ($2); } | declspecs_nosc_nots absdecl { - $2 = default_type ($2, 0); - $$ = new_param (0, $2.type, 0); + $$ = make_param ($2); } ; absdecl - : /* empty */ { $$ = $0; } + : /* empty */ + { + $$ = $0; + $$.sym = new_symbol (0); + } | absdecl1 ; @@ -1167,7 +1247,7 @@ absdecl1 : direct_absdecl | '*' ptr_spec absdecl { - $$ = $3; + $$ = pointer_spec ($2, $3); } ; @@ -1175,27 +1255,19 @@ direct_absdecl : '(' copy_spec absdecl1 ')' { $$ = $3; } | direct_absdecl function_params { - specifier_t spec = $1; - spec.type = parse_params (spec.type, $2); - $$ = spec; + $$ = function_spec ($1, $2); } | direct_absdecl array_decl { - specifier_t spec = default_type ($1, 0); - spec.type = array_type (spec.type, $2); - $$ = spec; + $$ = array_spec ($1, $2); } | function_params { - specifier_t spec = default_type ($0, 0); - spec.type = parse_params (spec.type, $1); - $$ = spec; + $$ = function_spec ($0, $1); } | array_decl { - specifier_t spec = default_type ($0, 0); - spec.type = array_type (spec.type, $1); - $$ = spec; + $$ = array_spec ($0, $1); } ; @@ -1230,12 +1302,7 @@ param_declarator_nostarttypename typename : declspecs_nosc absdecl { - //printf ("%s:%d:typename %p %p\n", - // pr.strings->strings + pr.source_file, pr.source_line, - // $1.type, $2.type); - //if ($1.type) print_type ($1.type); - //if ($2.type) print_type ($2.type); - $$ = $2.type ? $2 : default_type ($1, 0); + $$ = typename_spec ($2); } ; @@ -1267,8 +1334,7 @@ decl } | declspecs_ts local_expr qc_func_params { - specifier_t spec = default_type ($1, 0); - $$ = parse_qc_params (spec, $3); + $$ = parse_qc_params ($1, $3); } qc_func_decls { @@ -2034,15 +2100,7 @@ notype_ivars ivar_declarator : declarator { - symbol_t *s = $1.sym; - specifier_t spec = default_type ($1, s); - s->type = find_type (spec.type); - s->sy_type = sy_var; - s->visibility = current_visibility; - symtab_addsymbol (current_symtab, s); - if (!s->table) { - error (0, "duplicate field `%s'", s->name); - } + declare_field ($1, current_symtab); } | declarator ':' expr | ':' expr @@ -2133,9 +2191,9 @@ methodproto $$ = $2; } | '-' error ';' - { $$ = new_method (&type_id, new_param ("", 0, 0), 0); } + { $$ = new_method (&type_id, make_selector ("", 0, 0), 0); } | '+' error ';' - { $$ = new_method (&type_id, new_param ("", 0, 0), 0); } + { $$ = new_method (&type_id, make_selector ("", 0, 0), 0); } | '-' methoddecl ';' { $2->instance = 1; @@ -2160,7 +2218,7 @@ optional_param_list ; unaryselector - : selector { $$ = new_param ($1->name, 0, 0); } + : selector { $$ = make_selector ($1->name, 0, 0); } ; keywordselector @@ -2202,13 +2260,13 @@ reserved_word keyworddecl : selector ':' '(' typename ')' identifier - { $$ = new_param ($1->name, $4.type, $6->name); } + { $$ = make_selector ($1->name, $4.type, $6->name); } | selector ':' identifier - { $$ = new_param ($1->name, &type_id, $3->name); } + { $$ = make_selector ($1->name, &type_id, $3->name); } | ':' '(' typename ')' identifier - { $$ = new_param ("", $3.type, $5->name); } + { $$ = make_selector ("", $3.type, $5->name); } | ':' identifier - { $$ = new_param ("", &type_id, $2->name); } + { $$ = make_selector ("", &type_id, $2->name); } ; obj_expr diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 4ad506955..47746710f 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -267,10 +267,10 @@ declare_symbol (specifier_t spec, expr_t *init, symtab_t *symtab) //FIXME is_function is bad (this whole implementation of handling //function prototypes is bad) - if (spec.is_function && is_func (spec.type)) { - set_func_type_attrs (spec.type, spec); + s->type = append_type (spec.sym->type, spec.type); + if (spec.is_function && is_func (s->type)) { + set_func_type_attrs (s->type, spec); } - s->type = spec.type; if (spec.is_typedef) { if (init) { @@ -297,3 +297,18 @@ declare_symbol (specifier_t spec, expr_t *init, symtab_t *symtab) } return s; } + +symbol_t * +declare_field (specifier_t spec, symtab_t *symtab) +{ + symbol_t *s = spec.sym; + spec = default_type (spec, s); + s->type = find_type (append_type (s->type, spec.type)); + s->sy_type = sy_var; + s->visibility = current_visibility; + symtab_addsymbol (current_symtab, s); + if (!s->table) { + error (0, "duplicate field `%s'", s->name); + } + return s; +} diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 2894c71d3..135b45ba7 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -862,15 +862,18 @@ print_type_str (dstring_t *str, const type_t *type) } return; case ev_ptr: - if (is_id (type)) { - dasprintf (str, "id"); - if (type->t.fldptr.type->protos) - print_protocollist (str, type->t.fldptr.type->protos); - return; - } - if (is_SEL(type)) { - dasprintf (str, "SEL"); - return; + if (type->t.fldptr.type) { + if (is_id (type)) { + __auto_type ptr = type->t.fldptr.type; + dasprintf (str, "id"); + if (ptr->protos) + print_protocollist (str, ptr->protos); + return; + } + if (is_SEL(type)) { + dasprintf (str, "SEL"); + return; + } } dasprintf (str, "(*"); print_type_str (str, type->t.fldptr.type); From faef61aab66f0c9c3faff52a428f3e9906b19b3d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Mar 2023 10:19:24 +0900 Subject: [PATCH 3494/3664] [vulkan] Ensure host-visible buffers are big enough to flush Flushing memory requires nonCoherentAtomSize alignment, but this can cause the flush range to go out of bounds of an improperly sized buffer. However, only host-visible (and probably really only cached, but all three covered) needs flushing, so no rounding up is done for device-local memory. --- libs/video/renderer/vulkan/resource.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libs/video/renderer/vulkan/resource.c b/libs/video/renderer/vulkan/resource.c index b2b56deae..9641e160d 100644 --- a/libs/video/renderer/vulkan/resource.c +++ b/libs/video/renderer/vulkan/resource.c @@ -28,6 +28,7 @@ # include "config.h" #endif +#include "QF/mathlib.h" #include "QF/va.h" #include "QF/Vulkan/buffer.h" @@ -91,10 +92,19 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) { qfv_devfuncs_t *dfunc = device->funcs; qfv_physdev_t *physdev = device->physDev; + size_t atom = physdev->properties->limits.nonCoherentAtomSize; VkPhysicalDeviceMemoryProperties *memprops = &physdev->memory_properties; VkMemoryRequirements req; VkDeviceSize size = 0; + if (!(resource->memory_properties + & (VK_MEMORY_PROPERTY_HOST_CACHED_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT))) { + // if the memory isn't host visible then there's no need to worry about + // alignment with nonCoherentAtomSize + atom = 0; + } for (unsigned i = 0; i < resource->num_objects; i++) { __auto_type obj = &resource->objects[i]; switch (obj->type) { @@ -151,6 +161,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) Sys_Error ("%s:%s invalid resource type %d", resource->name, obj->name, obj->type); } + req.alignment = max (req.alignment, atom); size = QFV_NextOffset (size, &req); size += QFV_NextOffset (req.size, &req); } @@ -199,6 +210,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) break; } + req.alignment = max (req.alignment, atom); offset = QFV_NextOffset (offset, &req); switch (obj->type) { case qfv_res_buffer: @@ -221,6 +233,7 @@ QFV_CreateResource (qfv_device_t *device, qfv_resource_t *resource) case qfv_res_image_view: break; } + req.alignment = max (req.alignment, atom); offset = QFV_NextOffset (offset, &req); offset += QFV_NextOffset (req.size, &req); } From a5f82004bc8ad6b17da14abbbc5ce87d8c3a6f91 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 15:48:04 +0900 Subject: [PATCH 3495/3664] [qfcc] Add failing test for super dealloc While working on vkgen, I found a dealloc that wasn't calling [super dealloc] but qfcc hadn't noticed it. --- tools/qfcc/test/Makemodule.am | 4 +++ tools/qfcc/test/dealloc-warn4.r | 51 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tools/qfcc/test/dealloc-warn4.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 0d4fa5c2a..ea2ba9f70 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -81,6 +81,7 @@ test_build_errors=\ tools/qfcc/test/dealloc-warn.r \ tools/qfcc/test/dealloc-warn2.r \ tools/qfcc/test/dealloc-warn3.r \ + tools/qfcc/test/dealloc-warn4.r \ tools/qfcc/test/double-demote-float.r \ tools/qfcc/test/double-demote-float-ainit.r \ tools/qfcc/test/double-demote-float-ginit.r \ @@ -277,6 +278,9 @@ tools/qfcc/test/dealloc-warn2.run$(EXEEXT): tools/qfcc/test/dealloc-warn2.r $(qf tools/qfcc/test/dealloc-warn3.run$(EXEEXT): tools/qfcc/test/dealloc-warn3.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< +tools/qfcc/test/dealloc-warn4.run$(EXEEXT): tools/qfcc/test/dealloc-warn4.r $(qfcc_fail_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< + tools/qfcc/test/double-demote-int.run$(EXEEXT): tools/qfcc/test/double-demote-int.r $(qfcc_fail_run_deps) @$(top_srcdir)/tools/qfcc/test/build-compile-fail-run $@ $(QFCC) $(QCFLAGS) $< diff --git a/tools/qfcc/test/dealloc-warn4.r b/tools/qfcc/test/dealloc-warn4.r new file mode 100644 index 000000000..9962e19ca --- /dev/null +++ b/tools/qfcc/test/dealloc-warn4.r @@ -0,0 +1,51 @@ +#pragma warn error +#pragma optimize on + +void str_free(string str) +{ +} + +@interface Object +{ + Class isa; +} +-(void)dealloc; +@end + +@interface derived : Object +{ + int free; + string foo; + id bar; +} +@end + +@implementation Object +-(void) dealloc +{ + // this is the root of the hierarchy, so no super to call, thus + // must not check for [super dealloc] +} +-(void) release +{ +} +@end + +@implementation derived +-(void) dealloc +{ + // as this is a derived class, failure to call [super dealloc] will + // result in a memory leak (yes, there could be special allocators + // involved, in which case something will be needed to inform the + // compiler) + str_free (foo); +} +@end + +void __obj_exec_class (struct obj_module *msg) = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; + +int main () +{ + return 1; // test fails if compile succeeds (with -Werror) +} From 1293fc5d0ed288617096bfe9325b9a26d465fcf0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 20:09:21 +0900 Subject: [PATCH 3496/3664] [qfcc] Fix incorrect build error in dealloc-warn2 It was dying due to an undefined symbol rather than the warning. --- tools/qfcc/test/dealloc-warn2.r | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/test/dealloc-warn2.r b/tools/qfcc/test/dealloc-warn2.r index 921db1566..533913da5 100644 --- a/tools/qfcc/test/dealloc-warn2.r +++ b/tools/qfcc/test/dealloc-warn2.r @@ -1,5 +1,9 @@ #pragma warn error +void __obj_exec_class (struct obj_module *msg) = #0; +id obj_msgSend_super (Super *class, SEL op, ...) = #0; +id obj_msgSend (Super *class, SEL op, ...) = #0; + @interface Object { Class isa; @@ -37,9 +41,6 @@ } @end -void __obj_exec_class (struct obj_module *msg) = #0; -id obj_msgSend_super (Super *class, SEL op, ...) = #0; - int main () { return 1; // test fails if compile succeeds (with -Werror) From 119001de6f90aba928d0d6a7e40a616a5a25cebd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Feb 2023 20:39:10 +0900 Subject: [PATCH 3497/3664] [qfcc] Ensure params and arguments have unique flow addresses This fixes the false-negative in the dealloc-warn4.r test (and thus what I found in vkgen), and should stave off a few other issues. --- tools/qfcc/include/def.h | 4 ++- tools/qfcc/source/def.c | 12 ++++++++ tools/qfcc/source/flow.c | 52 ++++++++++++++++++++++++++++++---- tools/qfcc/source/statements.c | 2 +- 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 6892b5d8a..a00758bdf 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -97,6 +97,7 @@ typedef struct def_s { unsigned external:1; ///< externally declared def unsigned local:1; ///< function local def unsigned param:1; ///< function param def + unsigned argument:1; ///< function argument def unsigned system:1; ///< system def unsigned nosave:1; ///< don't set DEF_SAVEGLOBAL @@ -117,7 +118,8 @@ typedef enum storage_class_e { sc_extern, ///< def is externally allocated sc_static, ///< def is private to the current unit sc_param, ///< def is an incoming function parameter - sc_local ///< def is local to the current function + sc_local, ///< def is local to the current function + sc_argument, ///< def is a function argument } storage_class_t; /** Create a new def. diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index f87803f2c..b745f2da3 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -76,30 +76,42 @@ set_storage_bits (def_t *def, storage_class_t storage) def->external = 0; def->local = 0; def->param = 0; + def->argument = 0; break; case sc_extern: def->global = 1; def->external = 1; def->local = 0; def->param = 0; + def->argument = 0; break; case sc_static: def->external = 0; def->global = 0; def->local = 0; def->param = 0; + def->argument = 0; break; case sc_local: def->external = 0; def->global = 0; def->local = 1; def->param = 0; + def->argument = 0; break; case sc_param: def->external = 0; def->global = 0; def->local = 1; def->param = 1; + def->argument = 0; + break; + case sc_argument: + def->external = 0; + def->global = 0; + def->local = 1; + def->param = 0; + def->argument = 1; break; } def->initialized = 0; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 4e86fc0c3..43768096a 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -227,7 +227,8 @@ flowvar_is_global (flowvar_t *var) * * For the flowvar to refer to a function parameter, the flowvar's operand * must be a def operand (but the def itself may be an alias of the real def) - * and the rel def must have both its def_t::local and def_t::param flags set. + * and the real def must have both its def_t::local and def_t::param flags + * set. * * Temp vars are are not represented by op_def, so no mistake can be made. */ @@ -248,16 +249,43 @@ flowvar_is_param (flowvar_t *var) return 1; } +/** Check if the flowvar refers to a function argument. + * + * For the flowvar to refer to a function argument, the flowvar's operand + * must be a def operand (but the def itself may be an alias of the real def) + * and the real def must have both its def_t::local and def_t::argument flags + * set. + * + * Temp vars are are not represented by op_def, so no mistake can be made. + */ +static int +flowvar_is_argument (flowvar_t *var) +{ + def_t *def; + + if (var->op->op_type != op_def) + return 0; + def = var->op->def; + if (def->alias) + def = def->alias; + if (!def->local) + return 0; + if (!def->argument) + return 0; + return 1; +} + /** Check if the flowvar refers to a local variable. * - * As this is simply "neither global nor pamam", all other flowvars are - * considered local, in particular actual non-staic function scope variables - * and temp vars. + * As this is simply "neither global nor pamam nor argument", all other + * flowvars are considered local, in particular actual non-staic function + * scope variables and temp vars. */ static int flowvar_is_local (flowvar_t *var) { - return !(flowvar_is_global (var) || flowvar_is_param (var)); + return !(flowvar_is_global (var) || flowvar_is_param (var) + || flowvar_is_argument (var)); } ///@} @@ -443,6 +471,13 @@ add_operand (function_t *func, operand_t *op) var->flowaddr = get_pseudo_address (func, 1); } else if (op->op_type == op_temp) { var->flowaddr = get_temp_address (func, op); + } else if (flowvar_is_param (var)) { + var->flowaddr = func->num_statements + def_offset (var->op->def); + var->flowaddr += func->locals->space->size; + } else if (flowvar_is_argument (var)) { + var->flowaddr = func->num_statements + def_offset (var->op->def); + var->flowaddr += func->locals->space->size; + var->flowaddr += func->parameters->space->size; } else if (flowvar_is_local (var)) { var->flowaddr = func->num_statements + def_offset (var->op->def); } @@ -609,7 +644,12 @@ flow_build_vars (function_t *func) // set up pseudo address space for temp vars so accessing tmp vars // though aliases analyses correctly - func->pseudo_addr = func->num_statements + func->locals->space->size; + func->pseudo_addr = func->num_statements; + func->pseudo_addr += func->locals->space->size; + func->pseudo_addr += func->parameters->space->size; + if (func->arguments) { + func->pseudo_addr += func->arguments->size; + } func->num_vars = 0; // incremented by add_operand // first, add .return and .param_[0-7] as they are always needed diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 3da2e12a5..a3b0a64fb 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1097,7 +1097,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) expr_t *a = args[i]; const char *arg_name = va (0, ".arg%d", arg_num++); def_t *def = new_def (arg_name, 0, current_func->arguments, - sc_local); + sc_argument); type_t *arg_type = get_type (a); int size = type_size (arg_type); int alignment = arg_type->alignment; From 99af93c6e66821794e8170b935280e8eeec1b13c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 6 Mar 2023 13:06:05 +0900 Subject: [PATCH 3498/3664] [qfcc] Actually skip compile for -E etc The preprocess-only option wasn't being checked enough. --- tools/qfcc/source/qfcc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 98120e825..e0b15f04c 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -394,7 +394,7 @@ compile_to_obj (const char *file, const char *obj, lang_t lang) } *yyin = preprocess_file (file, 0); - if (!*yyin) + if (options.preprocess_only || !*yyin) return !options.preprocess_only; InitData (); @@ -568,7 +568,7 @@ separate_compile (void) } dstring_delete (output_file); dstring_delete (extension); - if (!err && !options.compile) { + if (!err && !options.compile && !options.preprocess_only) { InitData (); chain_initial_types (); linker_begin (); @@ -659,7 +659,7 @@ compile_file (const char *filename) int (*yyparse) (void) = qc_yyparse; *yyin = preprocess_file (filename, 0); - if (!*yyin) + if (options.preprocess_only || !*yyin) return !options.preprocess_only; add_source_file (filename); @@ -717,6 +717,9 @@ progs_src_compile (void) exit (1); } } + if (options.preprocess_only) { + return 0; + } src = load_file (filename->str); if (!src) { From ae5dbdb7fb8d11461201fe135a94878f584aceae Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 7 Mar 2023 13:17:46 +0900 Subject: [PATCH 3499/3664] [qfcc] Add failing test for function/array pointers It turns out I broke the type system when it comes to pointers to functions and arrays. This test checks basic function and array pointers and passes with qfcc from before the type system rework. --- tools/qfcc/test/Makemodule.am | 11 ++++++ tools/qfcc/test/ptrfunc.r | 72 +++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 tools/qfcc/test/ptrfunc.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index ea2ba9f70..faf0eb9bb 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -42,6 +42,7 @@ test_progs_dat=\ tools/qfcc/test/paramret.dat \ tools/qfcc/test/postop.dat \ tools/qfcc/test/ptraliasenc.dat \ + tools/qfcc/test/ptrfunc.dat \ tools/qfcc/test/ptrstructcast.dat \ tools/qfcc/test/quaternion.dat \ tools/qfcc/test/return-ivar.dat \ @@ -517,6 +518,16 @@ tools/qfcc/test/ptraliasenc.run: $(qfcc_test_run_deps) include $(ptraliasenc_dep) # am--include-marker r_depfiles_remade += $(ptraliasenc_dep) +tools_qfcc_test_ptrfunc_dat_SOURCES=tools/qfcc/test/ptrfunc.r +ptrfunc_obj=$(tools_qfcc_test_ptrfunc_dat_SOURCES:.r=.o) +ptrfunc_dep=$(call qcautodep,$(tools_qfcc_test_ptrfunc_dat_SOURCES)) +tools/qfcc/test/ptrfunc.dat$(EXEEXT): $(ptrfunc_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(ptrfunc_obj) +tools/qfcc/test/ptrfunc.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(ptrfunc_dep) # am--include-marker +r_depfiles_remade += $(ptrfunc_dep) + tools_qfcc_test_ptrstructcast_dat_SOURCES=tools/qfcc/test/ptrstructcast.r ptrstructcast_obj=$(tools_qfcc_test_ptrstructcast_dat_SOURCES:.r=.o) ptrstructcast_dep=$(call qcautodep,$(tools_qfcc_test_ptrstructcast_dat_SOURCES)) diff --git a/tools/qfcc/test/ptrfunc.r b/tools/qfcc/test/ptrfunc.r new file mode 100644 index 000000000..12d4a77c7 --- /dev/null +++ b/tools/qfcc/test/ptrfunc.r @@ -0,0 +1,72 @@ +int func(string x) { return 1; } +int (*funcptr)(string); +int *(*ptrfuncptr)(string); +int array[7]; +int *ptrarray[7]; +int (*arrayptr)[7]; +int *(*ptrarrayptr)[7]; + +#include + +#include "test-harness.h" + +typedef struct xdef_s { + qfot_type_t *type; ///< pointer to type definition + void *ofs; ///< 32-bit version of ddef_t.ofs +} xdef_t; + +typedef struct xdefs_s { + xdef_t *xdefs; + unsigned num_xdefs; +} xdefs_t; + +void *PR_FindGlobal (string name) = #0; + +xdef_t * +find_xdef (void *varaddr) +{ + //FIXME need a simple way to get at a def's meta-data + xdefs_t *xdefs = PR_FindGlobal (".xdefs"); + xdef_t *xdef = xdefs.xdefs; + while (xdef - xdefs.xdefs < xdefs.num_xdefs && xdef.ofs != varaddr) { + xdef++; + } + if (xdef.ofs != varaddr) { + return nil; + } + return xdef; +} + +int +check_var (string name, string encoding) +{ + void *var = PR_FindGlobal (name); + if (!var) { + printf ("could not find var: %s\n", name); + return 0; + } + xdef_t *xdef = find_xdef (var); + if (!var) { + printf ("could not find xdef var: %s @ %p\n", name, var); + return 0; + } + int ok = xdef.type.encoding == encoding; + printf ("%s: %p %s %s %s\n", name, var, xdef.type.encoding, encoding, + ok ? "pass" : "fail"); + return ok; +} + +int +main (void) +{ + int ok = 1; + ok &= check_var ("PR_FindGlobal", "(^v*)"); + ok &= check_var ("func", "(i*)"); + ok &= check_var ("funcptr", "^(i*)"); + ok &= check_var ("ptrfuncptr", "^(^i*)"); + ok &= check_var ("array", "[7=i]"); + ok &= check_var ("ptrarray", "[7=^i]"); + ok &= check_var ("arrayptr", "^[7=i]"); + ok &= check_var ("ptrarrayptr", "^[7=^i]"); + return 1 & (!ok); +} From 98fb9e0942276d34105785857894dd06b1e15166 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Mar 2023 02:22:23 +0900 Subject: [PATCH 3500/3664] [qfcc] Fix declarators for pointers/functions/arrays I had messed up the handling of declarators for combinations of pointer, function, and array: the pointer would get lost (and presumably arrays of functions etc). I think I had gotten confused and thought things were a tree rather than a simple list, but Holub set me straight once again (I've never regretted getting that book). Once I understood that, it was just a matter of finding all the places that needed to be fixed. Nicely, most of the duplicated code has been refactored and should be easier to debug in the future. --- tools/qfcc/include/function.h | 1 - tools/qfcc/include/symtab.h | 1 + tools/qfcc/source/function.c | 20 --- tools/qfcc/source/qc-parse.y | 292 ++++++++++++++++++++-------------- tools/qfcc/source/symtab.c | 21 ++- tools/qfcc/source/type.c | 21 +-- 6 files changed, 206 insertions(+), 150 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index a82714259..af1f06bde 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -149,7 +149,6 @@ param_t *reverse_params (param_t *params); param_t *append_params (param_t *params, param_t *more_params); param_t *copy_params (param_t *params); struct type_s *parse_params (struct type_s *return_type, param_t *params); -struct specifier_s parse_qc_params (struct specifier_s spec, param_t *params); param_t *check_params (param_t *params); diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index 6dc2b2fa0..ad6204f8d 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -252,6 +252,7 @@ symbol_t *make_symbol (const char *name, struct type_s *type, struct specifier_s; symbol_t *declare_symbol (struct specifier_s spec, struct expr_s *init, symtab_t *symtab); +symbol_t *declare_field (struct specifier_s spec, symtab_t *symtab); ///@} diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 296ecf9fe..6ed067765 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -218,26 +218,6 @@ parse_params (type_t *return_type, param_t *parms) return new; } -specifier_t -parse_qc_params (specifier_t spec, param_t *params) -{ - type_t **type; - // .float () foo; is a field holding a function variable rather - // than a function that returns a float field. - for (type = &spec.type; *type && is_field (*type); - type = &(*type)->t.fldptr.type) { - } - type_t *ret_type = *type; - *type = 0; - *type = parse_params (ret_type, params); - set_func_type_attrs ((*type), spec); - if (spec.type->type != ev_field) { - spec.is_function = 1; //FIXME do proper void(*)() -> ev_func - spec.params = params; - } - return spec; -} - param_t * check_params (param_t *params) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 427d0eb4a..ab955e9fa 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -168,7 +168,7 @@ int yylex (void); %type declarator notype_declarator after_type_declarator %type param_declarator param_declarator_starttypename %type param_declarator_nostarttypename -%type absdecl absdecl1 direct_absdecl typename ptr_spec +%type absdecl absdecl1 direct_absdecl typename ptr_spec copy_spec %type qc_comma %type attribute_list attribute @@ -307,6 +307,129 @@ spec_merge (specifier_t spec, specifier_t new) return spec; } +static specifier_t +typename_spec (specifier_t spec) +{ + spec = default_type (spec, 0); + spec.sym->type = find_type (append_type (spec.sym->type, spec.type)); + spec.type = spec.sym->type; + return spec; +} + +static specifier_t +function_spec (specifier_t spec, param_t *params) +{ + // empty param list in an abstract decle does not create a symbol + if (!spec.sym) { + spec.sym = new_symbol (0); + } + spec = default_type (spec, spec.sym); + spec.sym->params = params; + spec.sym->type = append_type (spec.sym->type, parse_params (0, params)); + spec.is_function = 1; //FIXME do proper void(*)() -> ev_func + return spec; +} + +static specifier_t +array_spec (specifier_t spec, unsigned size) +{ + spec = default_type (spec, spec.sym); + spec.sym->type = append_type (spec.sym->type, array_type (0, size)); + return spec; +} + +static specifier_t +pointer_spec (specifier_t quals, specifier_t spec) +{ + spec.sym->type = append_type (spec.sym->type, pointer_type (0)); + return spec; +} + +static specifier_t +parse_qc_params (specifier_t spec, param_t *params) +{ + type_t **type; + // .float () foo; is a field holding a function variable rather + // than a function that returns a float field. + for (type = &spec.type; *type && is_field (*type); + type = &(*type)->t.fldptr.type) { + } + type_t *ret_type = *type; + *type = 0; + + spec.sym = new_symbol (0); + spec.sym->type = spec.type; + spec.type = ret_type; + + spec = function_spec (spec, params); + return spec; +} + +static symbol_t * +funtion_sym_type (specifier_t spec, symbol_t *sym) +{ + sym->type = append_type (spec.sym->type, spec.type); + set_func_type_attrs (sym->type, spec); + sym->type = find_type (sym->type); + return sym; +} + +static symbol_t * +qc_nocode_symbol (specifier_t spec, symbol_t *sym) +{ + sym->params = spec.sym->params; + sym = funtion_sym_type (spec, sym); + return sym; +} + +static symbol_t * +qc_function_symbol (specifier_t spec, symbol_t *sym) +{ + sym = qc_nocode_symbol (spec, sym); + sym = function_symbol (sym, spec.is_overload, 1); + return sym; +} + +static param_t * +make_ellipsis (void) +{ + return new_param (0, 0, 0); +} + +static param_t * +make_param (specifier_t spec) +{ + spec = default_type (spec, spec.sym); + spec.type = find_type (append_type (spec.sym->type, spec.type)); + param_t *param = new_param (0, spec.type, spec.sym->name); + return param; +} + +static param_t * +make_selector (const char *selector, struct type_s *type, const char *name) +{ + param_t *param = new_param (selector, type, name); + return param; +} + +static param_t * +make_qc_param (specifier_t spec, symbol_t *sym) +{ + spec = default_type (spec, sym); + sym->type = spec.type; + param_t *param = new_param (0, sym->type, sym->name); + return param; +} + +static param_t * +make_qc_func_param (specifier_t spec, param_t *params, symbol_t *sym) +{ + spec = parse_qc_params (spec, params); + sym->type = append_type (spec.sym->type, spec.type); + param_t *param = new_param (0, sym->type, sym->name); + return param; +} + static int is_anonymous_struct (specifier_t spec) { @@ -428,8 +551,7 @@ datadef | declspecs_ts initdecls ';' | declspecs_ts qc_func_params { - specifier_t spec = default_type ($1, 0); - $$ = parse_qc_params (spec, $2); + $$ = parse_qc_params ($1, $2); } qc_func_decls | declspecs ';' @@ -464,31 +586,25 @@ qc_param_list qc_first_param : typespec identifier { - $$ = new_param (0, $1.type, $2->name); + $$ = make_qc_param ($1, $2); } | typespec_reserved qc_func_params identifier { - specifier_t spec = default_type ($1, 0); - spec = parse_qc_params (spec, $2); - - $$ = new_param (0, spec.type, $3->name); + $$ = make_qc_func_param ($1, $2, $3); } - | ELLIPSIS { $$ = new_param (0, 0, 0); } + | ELLIPSIS { $$ = make_ellipsis (); } ; qc_param : typespec identifier { - $$ = new_param (0, $1.type, $2->name); + $$ = make_qc_param ($1, $2); } | typespec qc_func_params identifier { - specifier_t spec = default_type ($1, 0); - spec = parse_qc_params (spec, $2); - - $$ = new_param (0, spec.type, $3->name); + $$ = make_qc_func_param ($1, $2, $3); } - | ELLIPSIS { $$ = new_param (0, 0, 0); } + | ELLIPSIS { $$ = make_ellipsis (); } ; /* This rule is used only to get an action before both qc_func_decl and @@ -525,9 +641,7 @@ qc_nocode_func specifier_t spec = $0; symbol_t *sym = $1; expr_t *expr = $4; - sym->params = spec.params; - sym->type = find_type (spec.type); - sym = function_symbol (sym, spec.is_overload, 1); + sym = qc_function_symbol (spec, sym); build_builtin_function (sym, expr, 0, spec.storage); } | identifier '=' expr @@ -543,12 +657,12 @@ qc_nocode_func { specifier_t spec = $0; symbol_t *sym = $1; - sym->type = find_type (spec.type); - if (!local_expr && sym->type->type != ev_field) { - sym->params = spec.params; - sym = function_symbol (sym, spec.is_overload, 1); + if (!local_expr && !is_field (spec.sym->type)) { + sym = qc_function_symbol (spec, sym); + } else { + sym = qc_nocode_symbol (spec, sym); } - if (!local_expr && sym->type->type != ev_field) { + if (!local_expr && !is_field (sym->type)) { // things might be a confused mess from earlier errors if (sym->sy_type == sy_func) make_function (sym, 0, sym->table->space, spec.storage); @@ -565,12 +679,10 @@ qc_code_func : identifier '=' optional_state_expr save_storage { + $$ = current_symtab; specifier_t spec = $0; symbol_t *sym = $1; - $$ = current_symtab; - sym->params = spec.params; - sym->type = find_type (spec.type); - sym = function_symbol (sym, spec.is_overload, 1); + sym = qc_function_symbol (spec, sym); current_func = begin_function (sym, 0, current_symtab, 0, spec.storage); current_symtab = current_func->locals; @@ -595,21 +707,15 @@ after_type_declarator : '(' copy_spec after_type_declarator ')' { $$ = $3; } | after_type_declarator function_params { - specifier_t spec = default_type ($1, $1.sym); - spec.sym->params = $2; - spec.type = parse_params (spec.type, $2); - spec.is_function = 1; //FIXME do proper void(*)() -> ev_func - $$ = spec; + $$ = function_spec ($1, $2); } | after_type_declarator array_decl { - specifier_t spec = default_type ($1, $1.sym); - spec.type = array_type (spec.type, $2); - $$ = spec; + $$ = array_spec ($1, $2); } | '*' ptr_spec after_type_declarator { - $$ = $3; + $$ = pointer_spec ($2, $3); } | TYPE_NAME { @@ -631,33 +737,22 @@ copy_spec ; ptr_spec - : /* empty */ - { - $$ = default_type ($-1, 0); - $$.type = pointer_type ($$.type); - } + : copy_spec // for when no qualifiers are present ; notype_declarator : '(' copy_spec notype_declarator ')' { $$ = $3; } | notype_declarator function_params { - //printf ("notype_declarator p %d\n", pr.source_line); - specifier_t spec = default_type ($1, $1.sym); - spec.sym->params = $2; - spec.type = parse_params (spec.type, $2); - spec.is_function = 1; //FIXME do proper void(*)() -> ev_func - $$ = spec; + $$ = function_spec ($1, $2); } | notype_declarator array_decl { - specifier_t spec = default_type ($1, $1.sym); - spec.type = array_type (spec.type, $2); - $$ = spec; + $$ = array_spec ($1, $2); } | '*' ptr_spec notype_declarator { - $$ = $3; + $$ = pointer_spec ($2, $3); } | NAME { @@ -862,10 +957,7 @@ function_body : ose { specifier_t spec = default_type ($0, $0.sym); - symbol_t *sym = spec.sym; - - set_func_type_attrs (spec.type, spec); - sym->type = find_type (spec.type); + symbol_t *sym = funtion_sym_type (spec, spec.sym); $$ = function_symbol (sym, spec.is_overload, 1); } save_storage @@ -886,10 +978,7 @@ function_body | '=' '#' expr ';' { specifier_t spec = default_type ($0, $0.sym); - symbol_t *sym = spec.sym; - - set_func_type_attrs (spec.type, spec); - sym->type = find_type (spec.type); + symbol_t *sym = funtion_sym_type (spec, spec.sym); sym = function_symbol (sym, spec.is_overload, 1); build_builtin_function (sym, $3, 0, spec.storage); } @@ -1080,15 +1169,7 @@ components component_declarator : declarator { - symbol_t *s = $1.sym; - specifier_t spec = default_type ($1, s); - s->type = find_type (spec.type); - s->sy_type = sy_var; - s->visibility = current_visibility; - symtab_addsymbol (current_symtab, s); - if (!s->table) { - error (0, "duplicate field `%s'", s->name); - } + declare_field ($1, current_symtab); } | declarator ':' expr | ':' expr @@ -1118,7 +1199,7 @@ param_list } | ELLIPSIS { - $$ = new_param (0, 0, 0); + $$ = make_ellipsis (); } ; @@ -1133,33 +1214,32 @@ parameter_list parameter : declspecs_ts param_declarator { - $2 = default_type ($2, $2.sym); - $$ = new_param (0, $2.type, $2.sym->name); + $$ = make_param ($2); } | declspecs_ts notype_declarator { - $2 = default_type ($2, $2.sym); - $$ = new_param (0, $2.type, $2.sym->name); + $$ = make_param ($2); } | declspecs_ts absdecl { - $2 = default_type ($2, $2.sym); - $$ = new_param (0, $2.type, 0); + $$ = make_param ($2); } | declspecs_nosc_nots notype_declarator { - $2 = default_type ($2, $2.sym); - $$ = new_param (0, $2.type, $2.sym->name); + $$ = make_param ($2); } | declspecs_nosc_nots absdecl { - $2 = default_type ($2, 0); - $$ = new_param (0, $2.type, 0); + $$ = make_param ($2); } ; absdecl - : /* empty */ { $$ = $0; } + : /* empty */ + { + $$ = $0; + $$.sym = new_symbol (0); + } | absdecl1 ; @@ -1167,7 +1247,7 @@ absdecl1 : direct_absdecl | '*' ptr_spec absdecl { - $$ = $3; + $$ = pointer_spec ($2, $3); } ; @@ -1175,27 +1255,19 @@ direct_absdecl : '(' copy_spec absdecl1 ')' { $$ = $3; } | direct_absdecl function_params { - specifier_t spec = $1; - spec.type = parse_params (spec.type, $2); - $$ = spec; + $$ = function_spec ($1, $2); } | direct_absdecl array_decl { - specifier_t spec = default_type ($1, 0); - spec.type = array_type (spec.type, $2); - $$ = spec; + $$ = array_spec ($1, $2); } | function_params { - specifier_t spec = default_type ($0, 0); - spec.type = parse_params (spec.type, $1); - $$ = spec; + $$ = function_spec ($0, $1); } | array_decl { - specifier_t spec = default_type ($0, 0); - spec.type = array_type (spec.type, $1); - $$ = spec; + $$ = array_spec ($0, $1); } ; @@ -1230,12 +1302,7 @@ param_declarator_nostarttypename typename : declspecs_nosc absdecl { - //printf ("%s:%d:typename %p %p\n", - // pr.strings->strings + pr.source_file, pr.source_line, - // $1.type, $2.type); - //if ($1.type) print_type ($1.type); - //if ($2.type) print_type ($2.type); - $$ = $2.type ? $2 : default_type ($1, 0); + $$ = typename_spec ($2); } ; @@ -1267,8 +1334,7 @@ decl } | declspecs_ts local_expr qc_func_params { - specifier_t spec = default_type ($1, 0); - $$ = parse_qc_params (spec, $3); + $$ = parse_qc_params ($1, $3); } qc_func_decls { @@ -2034,15 +2100,7 @@ notype_ivars ivar_declarator : declarator { - symbol_t *s = $1.sym; - specifier_t spec = default_type ($1, s); - s->type = find_type (spec.type); - s->sy_type = sy_var; - s->visibility = current_visibility; - symtab_addsymbol (current_symtab, s); - if (!s->table) { - error (0, "duplicate field `%s'", s->name); - } + declare_field ($1, current_symtab); } | declarator ':' expr | ':' expr @@ -2133,9 +2191,9 @@ methodproto $$ = $2; } | '-' error ';' - { $$ = new_method (&type_id, new_param ("", 0, 0), 0); } + { $$ = new_method (&type_id, make_selector ("", 0, 0), 0); } | '+' error ';' - { $$ = new_method (&type_id, new_param ("", 0, 0), 0); } + { $$ = new_method (&type_id, make_selector ("", 0, 0), 0); } | '-' methoddecl ';' { $2->instance = 1; @@ -2160,7 +2218,7 @@ optional_param_list ; unaryselector - : selector { $$ = new_param ($1->name, 0, 0); } + : selector { $$ = make_selector ($1->name, 0, 0); } ; keywordselector @@ -2202,13 +2260,13 @@ reserved_word keyworddecl : selector ':' '(' typename ')' identifier - { $$ = new_param ($1->name, $4.type, $6->name); } + { $$ = make_selector ($1->name, $4.type, $6->name); } | selector ':' identifier - { $$ = new_param ($1->name, &type_id, $3->name); } + { $$ = make_selector ($1->name, &type_id, $3->name); } | ':' '(' typename ')' identifier - { $$ = new_param ("", $3.type, $5->name); } + { $$ = make_selector ("", $3.type, $5->name); } | ':' identifier - { $$ = new_param ("", &type_id, $2->name); } + { $$ = make_selector ("", &type_id, $2->name); } ; obj_expr diff --git a/tools/qfcc/source/symtab.c b/tools/qfcc/source/symtab.c index 6470d2682..8f705cd53 100644 --- a/tools/qfcc/source/symtab.c +++ b/tools/qfcc/source/symtab.c @@ -267,10 +267,10 @@ declare_symbol (specifier_t spec, expr_t *init, symtab_t *symtab) //FIXME is_function is bad (this whole implementation of handling //function prototypes is bad) - if (spec.is_function && is_func (spec.type)) { - set_func_type_attrs (spec.type, spec); + s->type = append_type (spec.sym->type, spec.type); + if (spec.is_function && is_func (s->type)) { + set_func_type_attrs (s->type, spec); } - s->type = spec.type; if (spec.is_typedef) { if (init) { @@ -297,3 +297,18 @@ declare_symbol (specifier_t spec, expr_t *init, symtab_t *symtab) } return s; } + +symbol_t * +declare_field (specifier_t spec, symtab_t *symtab) +{ + symbol_t *s = spec.sym; + spec = default_type (spec, s); + s->type = find_type (append_type (s->type, spec.type)); + s->sy_type = sy_var; + s->visibility = current_visibility; + symtab_addsymbol (current_symtab, s); + if (!s->table) { + error (0, "duplicate field `%s'", s->name); + } + return s; +} diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 99916d604..d811d94da 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -862,15 +862,18 @@ print_type_str (dstring_t *str, const type_t *type) } return; case ev_ptr: - if (is_id (type)) { - dasprintf (str, "id"); - if (type->t.fldptr.type->protos) - print_protocollist (str, type->t.fldptr.type->protos); - return; - } - if (is_SEL(type)) { - dasprintf (str, "SEL"); - return; + if (type->t.fldptr.type) { + if (is_id (type)) { + __auto_type ptr = type->t.fldptr.type; + dasprintf (str, "id"); + if (ptr->protos) + print_protocollist (str, ptr->protos); + return; + } + if (is_SEL(type)) { + dasprintf (str, "SEL"); + return; + } } dasprintf (str, "(*"); print_type_str (str, type->t.fldptr.type); From b9106c09cb5e70642d600c925f0a89cf75c24cc1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Mar 2023 13:33:49 +0900 Subject: [PATCH 3501/3664] [plist] Clean up string parsing I had looked into doing reference counting on the strings, but didn't like the implementation. However, it did make for better string handling in the property list parser. --- libs/util/plist.c | 54 ++++++++++++++++------------------------------- 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/libs/util/plist.c b/libs/util/plist.c index dbe20da60..9e21c2020 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -135,8 +135,8 @@ init_quotables (void) static plitem_t *pl_parsepropertylistitem (pldata_t *); static qboolean pl_skipspace (pldata_t *); -static char *pl_parsequotedstring (pldata_t *); -static char *pl_parseunquotedstring (pldata_t *); +static plitem_t *pl_parsequotedstring (pldata_t *); +static plitem_t *pl_parseunquotedstring (pldata_t *); static char *pl_parsedata (pldata_t *, int *); static const char * @@ -196,18 +196,20 @@ PL_NewData (void *data, size_t size) } static plitem_t * -new_string (char *str, int line) +new_string (const char *str, size_t len, pldata_t *pl) { plitem_t *item = pl_newitem (QFString); - item->data = str; - item->line = line; + item->data = malloc (len + 1); + memcpy (item->data, str, len); + ((char *) item->data)[len] = 0; + item->line = pl ? pl->line : 0; return item; } VISIBLE plitem_t * PL_NewString (const char *str) { - return new_string (strdup (str), 0); + return new_string (str, strlen (str), 0); } VISIBLE void @@ -595,7 +597,7 @@ pl_parsedata (pldata_t *pl, int *len) return NULL; } -static char * +static plitem_t * pl_parsequotedstring (pldata_t *pl) { unsigned int start = ++pl->pos; @@ -603,7 +605,7 @@ pl_parsequotedstring (pldata_t *pl) unsigned int shrink = 0; qboolean hex = false; qboolean long_string = false; - char *str; + plitem_t *str; if (pl->ptr[pl->pos] == '"' && pl->ptr[pl->pos + 1] == '"') { @@ -664,7 +666,7 @@ pl_parsequotedstring (pldata_t *pl) } if (pl->pos - start - shrink == 0) { - str = strdup (""); + str = new_string ("", 0, pl); } else { char *chars = alloca(pl->pos - start - shrink); unsigned int j; @@ -740,8 +742,7 @@ pl_parsequotedstring (pldata_t *pl) } } } - str = strncat (calloc ((pl->pos - start - shrink) + 1, 1), chars, - pl->pos - start - shrink); + str = new_string (chars, pl->pos - start - shrink, pl); } if (long_string) pl->pos += 2; @@ -749,20 +750,17 @@ pl_parsequotedstring (pldata_t *pl) return str; } -static char * +static plitem_t * pl_parseunquotedstring (pldata_t *pl) { unsigned int start = pl->pos; - char *str; while (pl->pos < pl->end) { if (is_quotable (pl->ptr[pl->pos])) break; pl->pos++; } - str = strncat (calloc ((pl->pos - start) + 1, 1), &pl->ptr[start], - pl->pos - start); - return str; + return new_string (&pl->ptr[start], pl->pos - start, pl); } static plitem_t * @@ -909,27 +907,11 @@ pl_parsepropertylistitem (pldata_t *pl) } } - case '"': { - int line = pl->line; - char *str = pl_parsequotedstring (pl); + case '"': + return pl_parsequotedstring (pl); - if (!str) { - return NULL; - } else { - return new_string (str, line); - } - } - - default: { - int line = pl->line; - char *str = pl_parseunquotedstring (pl); - - if (!str) { - return NULL; - } else { - return new_string (str, line); - } - } + default: + return pl_parseunquotedstring (pl); } // switch } From 374ca602a77096ac9b434d7c8a35e1c41600dfde Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 9 Mar 2023 15:32:52 +0900 Subject: [PATCH 3502/3664] [vkgen] Use designated init for fixed array data It seems I hadn't used fixed arrays for a while as the size field (which really should be count) had moved and its spot taken by a data pointer. --- libs/video/renderer/vulkan/vkgen/vkfixedarray.r | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkfixedarray.r b/libs/video/renderer/vulkan/vkgen/vkfixedarray.r index c467cde86..8f466bdf2 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfixedarray.r +++ b/libs/video/renderer/vulkan/vkgen/vkfixedarray.r @@ -45,15 +45,15 @@ { fprintf (output_file, "static parse_fixed_array_t parse_%s_data = {\n", [self name]); - fprintf (output_file, "\t%s,\n", [ele_type parseType]); - fprintf (output_file, "\tsizeof (%s),\n", [ele_type name]); - fprintf (output_file, "\t%s,\n", [ele_type parseFunc]); - fprintf (output_file, "\t%d,\n", ele_count); + fprintf (output_file, "\t.type = %s,\n", [ele_type parseType]); + fprintf (output_file, "\t.stride = sizeof (%s),\n", [ele_type name]); + fprintf (output_file, "\t.parser = %s,\n", [ele_type parseFunc]); + fprintf (output_file, "\t.size = %d,\n", ele_count); fprintf (output_file, "};\n"); fprintf (output_file, "exprarray_t %s_array = {\n", [self name]); - fprintf (output_file, "\t&%s,\n", [ele_type cexprType]); - fprintf (output_file, "\t%d,\n", ele_count); + fprintf (output_file, "\t.type = &%s,\n", [ele_type cexprType]); + fprintf (output_file, "\t.size = %d,\n", ele_count); fprintf (output_file, "};\n"); fprintf (output_file, "exprtype_t %s_type = {\n", [self name]); fprintf (output_file, "\t.name = \"%s[%d]\",\n", [ele_type name], From 4cf1c167bd36f16df3a3cd44faf6cea261a5cba1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 10 Mar 2023 19:47:40 +0900 Subject: [PATCH 3503/3664] [vulkan] Start work on a render job system The jobs will become the core of the renderer, with each job step being one of a render pass, compute pass, or processor (CPU-only) task. The steps support dependencies, which will allow for threading the system in the future. Currently, just the structures, parse support, and prototype job specification (render.plist) have been implemented. No conversion to working data is done yet, and many things, in particular resources, will need to be reworked, but this gets the basic design in. --- include/QF/Vulkan/render.h | 41 +++++++++++ libs/video/renderer/vulkan/render.c | 10 ++- libs/video/renderer/vulkan/render.plist | 91 ++++++++++++++++++++++++ libs/video/renderer/vulkan/vkparse.c | 56 +++++++++++++++ libs/video/renderer/vulkan/vkparse.h | 2 + libs/video/renderer/vulkan/vkparse.plist | 58 ++++++++++++++- 6 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 libs/video/renderer/vulkan/render.plist diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 9cfecdafe..1d088fec4 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -123,6 +123,9 @@ typedef struct qfv_pipelineinfo_s { qfv_taskinfo_t *tasks; VkPipelineCreateFlags flags; + VkPipelineShaderStageCreateInfo *compute_stage; + uint32_t dispatch[3]; + uint32_t num_graph_stages; const VkPipelineShaderStageCreateInfo *graph_stages; const VkPipelineVertexInputStateCreateInfo *vertexInput; @@ -167,7 +170,18 @@ typedef struct qfv_renderpassinfo_s { qfv_subpassinfo_t *subpasses; } qfv_renderpassinfo_t; +typedef struct qfv_computeinfo_s { + vec4f_t color; + const char *name; + + uint32_t num_pipelines; + qfv_pipelineinfo_t *pipelines; +} qfv_computeinfo_t; + typedef struct qfv_renderinfo_s { + vec4f_t color; + const char *name; + struct memsuper_s *memsuper; struct plitem_s *plitem; uint32_t num_images; @@ -183,6 +197,33 @@ typedef struct qfv_renderinfo_s { qfv_layoutinfo_t *layouts; } qfv_renderinfo_t; +typedef struct qfv_processinfo_s { + vec4f_t color; + const char *name; + + uint32_t num_tasks; + qfv_taskinfo_t *tasks; +} qfv_processinfo_t; + +typedef struct qfv_stepinfo_s { + vec4f_t color; + const char *name; + + uint32_t num_dependencies; + qfv_reference_t *dependencies; + + qfv_renderinfo_t *render; + qfv_computeinfo_t *compute; + qfv_processinfo_t *process; +} qfv_stepinfo_t; + +typedef struct qfv_jobinfo_s { + struct memsuper_s *memsuper; + + uint32_t num_steps; + qfv_stepinfo_t *steps; +} qfv_jobinfo_t; + typedef struct qfv_label_s { vec4f_t color; const char *name; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 5b7a20753..0282d9547 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -196,7 +196,15 @@ count_sp_stuff (qfv_subpassinfo_t *spi, objcount_t *counts) if (spi->attachments) { count_as_stuff (spi->attachments, counts); } - counts->num_pipelines += spi->num_pipelines; + for (uint32_t i = 0; i < spi->num_pipelines; i++) { + __auto_type pli = &spi->pipelines[i]; + if (pli->num_graph_stages && !pli->compute_stage) { + counts->num_pipelines++; + } else { + Sys_Error ("%s:%s: invalid graphics pipeline", + spi->name, pli->name); + } + } } static void diff --git a/libs/video/renderer/vulkan/render.plist b/libs/video/renderer/vulkan/render.plist new file mode 100644 index 000000000..977e4bef8 --- /dev/null +++ b/libs/video/renderer/vulkan/render.plist @@ -0,0 +1,91 @@ +properties = { + partphysics_layout = { + setLayouts = (particle_set); + pushConstantRanges = ( + { + stageFlags = compute; + offset = 0; + size = "4 * 4 + 4"; + }, + ); + }; + partupdate_layout = { + setLayouts = (particle_set, particle_set, particle_set); + }; +}; +descriptorSetLayouts = { + particle_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 1; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 2; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + ); + }; +}; +tasks = { + particles = { + compute = { + pipelines = { + part:update = { + color = "[0.3, 0.8, 0.9]"; + tasks = ( + { func = "update_particles"; } + ); + stage = { + name = main; + module = $builtin/partupdate.comp; + }; + layout = partupdate_layout; + }; + part:physics = { + color = "[0.6, 0.8, 0.9]"; + tasks = ( + { func = "particle_physics"; } + ); + stage = { + name = main; + module = $builtin/partphysics.comp; + }; + layout = partphysics_layout; + }; + }; + }; + }; + shadow = { + //currently empty + }; + translucent = { + tasks = ( + { func = "clear_translucent"; }, + ) + }; + main = { + depenencies = (particles, shadow, translucent); + renderpass = main_def; + }; + preoutput = { + tasks = ( + { func = "acquire_output"; }, + { func = "update_input"; }, + ); + }; + output = { + depenencies = (main, preoutput); + renderpass = output; + }; +}; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 6779c7083..e771b8759 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -2362,6 +2362,62 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) return ri; } +struct qfv_jobinfo_s * +QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) +{ + memsuper_t *memsuper = new_memsuper (); + qfv_jobinfo_t *ri = cmemalloc (memsuper, sizeof (qfv_jobinfo_t)); + *ri = (qfv_jobinfo_t) { .memsuper = memsuper }; + + scriptctx_t *sctx = ctx->script_context; + plitem_t *messages = PL_NewArray (); + + exprctx_t exprctx = { + .symtab = &root_symtab, + .messages = messages, + .hashctx = &sctx->hashctx, + .memsuper = memsuper, + }; + parsectx_t parsectx = { + .ectx = &exprctx, + .vctx = ctx, + .data = rctx, + }; + + static const char *extra_items[] = { + "images", + "views", + "renderpasses", + 0 + }; + exprsym_t var_syms[] = { + {"output", &qfv_output_t_type, &sctx->output}, + {"frames", &vulkan_frameset_t_type, &ctx->frames}, + {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, + {"physDevLimits", &VkPhysicalDeviceLimits_type, + &ctx->device->physDev->properties->limits }, + {} + }; + exprctx.external_variables = QFV_CreateSymtab (item, "properties", + extra_items, var_syms, + &exprctx); + + int ret; + if (!(ret = parse_qfv_jobinfo_t (0, item, ri, messages, &parsectx))) { + for (int i = 0; i < PL_A_NumObjects (messages); i++) { + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + } + } + QFV_DestroySymtab (exprctx.external_variables); + PL_Free (messages); + if (!ret) { + delete_memsuper (memsuper); + ri = 0; + } + + return ri; +} + int QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, memsuper_t *memsuper, exprtab_t *symtab, const char *ref, diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 95b669598..fcf547125 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -90,4 +90,6 @@ struct memsuper_s; int QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, struct memsuper_s *memsuper, exprtab_t *symtab, const char *ref, qfv_layoutinfo_t *layout); +struct qfv_jobinfo_s *QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, + struct qfv_renderctx_s *rctx); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 6fbcfa3dc..8cd137407 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -48,7 +48,10 @@ qfv_framebufferinfo_t, qfv_renderpassinfo_t, qfv_renderinfo_t, - qfv_pipelinespec_t, + qfv_computeinfo_t, + qfv_processinfo_t, + qfv_stepinfo_t, + qfv_jobinfo_t, ); parse = { VkSubpassDescription = { @@ -513,6 +516,11 @@ size = num_graph_stages; values = graph_stages; }; + stage = { + type = (single, VkPipelineShaderStageCreateInfo); + value = compute_stage; + }; + dispatch = auto; vertexInput = { type = (single, VkPipelineVertexInputStateCreateInfo); value = vertexInput; @@ -616,8 +624,18 @@ values = bindings; }; }; + qfv_computeinfo_s = { + .name = qfv_computeinfo_t; + color = auto; + pipelines = { + type = (labeledarray, qfv_pipelineinfo_t, name); + size = num_pipelines; + values = pipelines; + }; + }; qfv_renderinfo_s = { .name = qfv_renderinfo_t; + color = auto; properties = ignore; output = ignore; images = { @@ -641,5 +659,43 @@ values = descriptorsets; }; }; + qfv_processinfo_s = { + .name = qfv_processinfo_t; + color = auto; + tasks = { + type = (array, qfv_taskinfo_t); + size = num_tasks; + values = tasks; + }; + }; + qfv_stepinfo_s = { + .name = qfv_stepinfo_t; + color = auto; + dependencies = { + type = (array, qfv_reference_t); + size = num_dependencies; + values = dependencies; + }; + render = { + type = (single, qfv_renderinfo_t); + value = render; + }; + compute = { + type = (single, qfv_computeinfo_t); + value = compute; + }; + process = { + type = (single, qfv_processinfo_t); + value = process; + }; + }; + qfv_jobinfo_s = { + .name = qfv_jobinfo_t; + steps = { + type = (array, qfv_stepinfo_t); + size = num_steps; + values = steps; + }; + }; }; } From e57a06f37b3391682dbbb94097b18203c1db1f80 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Mar 2023 12:27:45 +0900 Subject: [PATCH 3504/3664] [plist] Refactor the dictionary and array parsing This makes it easier to reuse the code for parsing bare dictionaries and arrays. --- libs/util/plist.c | 366 ++++++++++++++++++++++++---------------------- 1 file changed, 191 insertions(+), 175 deletions(-) diff --git a/libs/util/plist.c b/libs/util/plist.c index 9e21c2020..ff1287773 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -44,7 +44,6 @@ #include "QF/plist.h" #include "QF/qtypes.h" #include "QF/sys.h" -#include "QF/va.h" /* Generic property list item. @@ -96,8 +95,7 @@ typedef struct pldata_s { // Unparsed property list string unsigned pos; unsigned line; unsigned line_start; - plitem_t *error; - va_ctx_t *va_ctx; + dstring_t *errmsg; hashctx_t **hashctx; } pldata_t; @@ -133,11 +131,7 @@ init_quotables (void) quotable_bitmap[*c / 8] &= ~(1 << (*c % 8)); } -static plitem_t *pl_parsepropertylistitem (pldata_t *); -static qboolean pl_skipspace (pldata_t *); -static plitem_t *pl_parsequotedstring (pldata_t *); -static plitem_t *pl_parseunquotedstring (pldata_t *); -static char *pl_parsedata (pldata_t *, int *); +static plitem_t *pl_parsepropertylistitem (pldata_t *pl); static const char * dict_get_key (const void *i, void *unused) @@ -489,8 +483,21 @@ PL_RemoveObjectAtIndex (plitem_t *array, int index) return item; } +static void __attribute__((format(printf, 2, 3))) +pl_error (pldata_t *pl, const char *fmt, ...) +{ + if (!pl->errmsg) { + pl->errmsg = dstring_new (); + } + + va_list args; + va_start (args, fmt); + dvsprintf (pl->errmsg, fmt, args); + va_end (args); +} + static qboolean -pl_skipspace (pldata_t *pl) +pl_skipspace (pldata_t *pl, int end_ok) { while (pl->pos < pl->end) { char c = pl->ptr[pl->pos]; @@ -508,7 +515,9 @@ pl_skipspace (pldata_t *pl) pl->pos++; } if (pl->pos >= pl->end) { - pl->error = PL_NewString ("Reached end of string in comment"); + // end of string in a single-line comment is always + // an error + pl_error (pl, "Reached end of string in comment"); return false; } } else if (pl->ptr[pl->pos + 1] == '*') { // "/*" comments @@ -528,7 +537,9 @@ pl_skipspace (pldata_t *pl) pl->pos++; } if (pl->pos >= pl->end) { - pl->error = PL_NewString ("Reached end of string in comment"); + // end of string in a multi-line comment is always + // an error + pl_error (pl, "Reached end of string in comment"); return false; } } else { @@ -544,10 +555,40 @@ pl_skipspace (pldata_t *pl) } pl->pos++; } - pl->error = PL_NewString ("Reached end of string"); + if (!end_ok) { + pl_error (pl, "Reached end of string"); + } return false; } +static int +pl_checknext (pldata_t *pl, const char *valid, int end_ok) +{ + if (!pl_skipspace (pl, end_ok)) { + return end_ok; + } + + char ch = pl->ptr[pl->pos]; + if (strchr (valid, ch)) { + return 1; + } + + size_t len = strlen (valid); + size_t size = 3 + (strlen (valid) - 1) * 7 + 1; + char expected[size], *p = expected; + p[0] = '\''; + p[1] = valid[0]; + p[2] = '\''; + p += 3; + for (size_t i = 1; i < len; i++, p++) { + memcpy (p, " or 'x'", 7); + p[5] = valid[i]; + } + p[0] = 0; + pl_error (pl, "Unexpected character %c (wanted %s)", ch, expected); + return 0; +} + static inline byte from_hex (byte a) { @@ -564,8 +605,122 @@ make_byte (byte h, byte l) return (from_hex (h) << 4) | from_hex (l); } -static char * -pl_parsedata (pldata_t *pl, int *len) +static int +pl_parsekeyvalue (pldata_t *pl, plitem_t *dict, int end_ok) +{ + plitem_t *key = 0; + plitem_t *value = 0; + + if (!(key = pl_parsepropertylistitem (pl))) { + return 0; + } + if (key->type != QFString) { + pl_error (pl, "Key is not a string"); + goto error; + } + + if (!pl_checknext (pl, "=", 0)) { + goto error; + } + pl->pos++; + + if (!(value = pl_parsepropertylistitem (pl))) { + goto error; + } + + if (!PL_D_AddObject (dict, PL_String (key), value)) { + goto error; + } + PL_Free (key); // don't need the key item + + if (!pl_checknext (pl, end_ok ? ";" : ";}", end_ok)) { + return 0; + } + + if (pl->ptr[pl->pos] == ';') { + pl->pos++; + } + return 1; +error: + PL_Free (key); + PL_Free (value); + return 0; +} + +static plitem_t * +pl_parsedictionary (pldata_t *pl) +{ + plitem_t *dict = PL_NewDictionary (pl->hashctx); + dict->line = pl->line; + + pl->pos++; // skip over opening { + while (pl_skipspace (pl, 0) && pl->ptr[pl->pos] != '}') { + if (!pl_parsekeyvalue (pl, dict, 0)) { + PL_Free (dict); + return NULL; + } + } + if (pl->pos >= pl->end) { + pl_error (pl, "Unexpected end of string when parsing dictionary"); + PL_Free (dict); + return NULL; + } + pl->pos++; // skip over closing } + + return dict; +} + +static int +pl_parsevalue (pldata_t *pl, plitem_t *array, int end_ok) +{ + plitem_t *value; + + if (!(value = pl_parsepropertylistitem (pl))) { + return 0; + } + if (!PL_A_AddObject (array, value)) { + pl_error (pl, "too many items in array"); + PL_Free (value); + return 0; + } + + if (!pl_checknext (pl, end_ok ? "," : ",)", end_ok)) { + return 0; + } + + if (pl->ptr[pl->pos] == ',') { + pl->pos++; + } + + return 1; +} + +static plitem_t * +pl_parsearray (pldata_t *pl) +{ + plitem_t *array = PL_NewArray (); + array->line = pl->line; + + pl->pos++; // skip over opening ( + + while (pl_skipspace (pl, 0) && pl->ptr[pl->pos] != ')') { + if (!pl_parsevalue (pl, array, 0)) { + PL_Free (array); + return NULL; + } + } + if (pl->pos >= pl->end) { + pl_error (pl, "Unexpected end of string when parsing array"); + PL_Free (array); + return NULL; + } + pl->pos++; // skip over opening ) + + return array; +} + +static plitem_t * +pl_parsebinary (pldata_t *pl) { unsigned start = ++pl->pos; int nibbles = 0, i; @@ -579,21 +734,23 @@ pl_parsedata (pldata_t *pl, int *len) } if (c == '>') { if (nibbles & 1) { - pl->error = PL_NewString ("invalid data, missing nibble"); + pl_error (pl, "invalid data, missing nibble"); return NULL; } - *len = nibbles / 2; - str = malloc (*len); - for (i = 0; i < *len; i++) + int len = nibbles / 2; + str = malloc (len); + for (i = 0; i < len; i++) { str[i] = make_byte (pl->ptr[start + i * 2], pl->ptr[start + i * 2 + 1]); - return str; + } + plitem_t *item = PL_NewData (str, len); + item->line = pl->line; + return item; } - pl->error = PL_NewString (va (pl->va_ctx, - "invalid character in data: %02x", c)); + pl_error (pl, "invalid character in data: %02x", c); return NULL; } - pl->error = PL_NewString ("Reached end of string while parsing data"); + pl_error (pl, "Reached end of string while parsing data"); return NULL; } @@ -661,7 +818,7 @@ pl_parsequotedstring (pldata_t *pl) } if (pl->pos >= pl->end) { - pl->error = PL_NewString ("Reached end of string while parsing quoted string"); + pl_error (pl, "Reached end of string while parsing quoted string"); return NULL; } @@ -766,153 +923,17 @@ pl_parseunquotedstring (pldata_t *pl) static plitem_t * pl_parsepropertylistitem (pldata_t *pl) { - plitem_t *item = NULL; - - if (!pl_skipspace (pl)) + if (!pl_skipspace (pl, 0)) { return NULL; + } switch (pl->ptr[pl->pos]) { - case '{': - { - item = PL_NewDictionary (pl->hashctx); - item->line = pl->line; - - pl->pos++; - - while (pl_skipspace (pl) && pl->ptr[pl->pos] != '}') { - plitem_t *key; - plitem_t *value; - - if (!(key = pl_parsepropertylistitem (pl))) { - PL_Free (item); - return NULL; - } - - if (!(pl_skipspace (pl))) { - PL_Free (key); - PL_Free (item); - return NULL; - } - - if (key->type != QFString) { - pl->error = PL_NewString ("Key is not a string"); - PL_Free (key); - PL_Free (item); - return NULL; - } - - if (pl->ptr[pl->pos] != '=') { - pl->error = PL_NewString (va (pl->va_ctx, "Unexpected character %c (expected '=')", pl->ptr[pl->pos])); - PL_Free (key); - PL_Free (item); - return NULL; - } - pl->pos++; - - // If there is no value, lose the key - if (!(value = pl_parsepropertylistitem (pl))) { - PL_Free (key); - PL_Free (item); - return NULL; - } - - if (!(pl_skipspace (pl))) { - PL_Free (key); - PL_Free (value); - PL_Free (item); - return NULL; - } - - if (pl->ptr[pl->pos] == ';') { - pl->pos++; - } else if (pl->ptr[pl->pos] != '}') { - pl->error = PL_NewString (va (pl->va_ctx, "Unexpected character %c (wanted ';' or '}')", pl->ptr[pl->pos])); - PL_Free (key); - PL_Free (value); - PL_Free (item); - return NULL; - } - - // Add the key/value pair to the dictionary - if (!PL_D_AddObject (item, PL_String (key), value)) { - PL_Free (key); - PL_Free (value); - PL_Free (item); - return NULL; - } - PL_Free (key); - } - - if (pl->pos >= pl->end) { // Catch the error - pl->error = PL_NewString ("Unexpected end of string when parsing dictionary"); - PL_Free (item); - return NULL; - } - pl->pos++; - - return item; + case '{': return pl_parsedictionary (pl); + case '(': return pl_parsearray (pl); + case '<': return pl_parsebinary (pl); + case '"': return pl_parsequotedstring (pl); + default: return pl_parseunquotedstring (pl); } - - case '(': { - item = PL_NewArray (); - item->line = pl->line; - - pl->pos++; - - while (pl_skipspace (pl) && pl->ptr[pl->pos] != ')') { - plitem_t *value; - - if (!(value = pl_parsepropertylistitem (pl))) { - PL_Free (item); - return NULL; - } - - if (!(pl_skipspace (pl))) { - PL_Free (value); - PL_Free (item); - return NULL; - } - - if (pl->ptr[pl->pos] == ',') { - pl->pos++; - } else if (pl->ptr[pl->pos] != ')') { - pl->error = PL_NewString (va (pl->va_ctx, "Unexpected character %c (wanted ',' or ')')", pl->ptr[pl->pos])); - PL_Free (value); - PL_Free (item); - return NULL; - } - - if (!PL_A_AddObject (item, value)) { - pl->error = PL_NewString ("Unexpected character (too many items in array)"); - PL_Free (value); - PL_Free (item); - return NULL; - } - } - pl->pos++; - - return item; - } - - case '<': { - int len; - char *str = pl_parsedata (pl, &len); - - if (!str) { - return NULL; - } else { - item = PL_NewData (str, len); - item->line = pl->line; - return item; - } - } - - case '"': - return pl_parsequotedstring (pl); - - default: - return pl_parseunquotedstring (pl); - } // switch } VISIBLE plitem_t * @@ -927,22 +948,17 @@ PL_GetPropertyList (const char *string, hashctx_t **hashctx) .ptr = string, .end = strlen (string), .line = 1, - .va_ctx = va_create_context (4), .hashctx = hashctx, }; if (!(newpl = pl_parsepropertylistitem (&pl))) { - if (pl.error) { - const char *error = PL_String (pl.error); - if (error[0]) { - Sys_Printf ("plist: %d,%d: %s\n", pl.line, - pl.pos - pl.line_start, error); - } - PL_Free (pl.error); + if (pl.errmsg) { + Sys_Printf ("plist: %d,%d: %s\n", pl.line, pl.pos - pl.line_start, + pl.errmsg->str); + dstring_delete (pl.errmsg); } return NULL; } - va_destroy_context (pl.va_ctx); return newpl; } From ea77df2daa09b9afdd32a7e17790e4a25e64f75b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Mar 2023 14:31:17 +0900 Subject: [PATCH 3505/3664] [plist] Add parsing for bare dictionaries and arrays Requiring top-level {} or () for (usually) hand-written files is awkward and even a little error prone, and certainly ugly at times. With this, loaders that expect a particular format can specify the format a little more directly. --- include/QF/plist.h | 30 +++++++++++++++++++-- libs/ruamoko/rua_plist.c | 56 ++++++++++++++++++++++++++++++++++---- libs/util/plist.c | 58 +++++++++++++++++++++++++++++++++++++--- libs/util/quakefs.c | 10 +++---- 4 files changed, 137 insertions(+), 17 deletions(-) diff --git a/include/QF/plist.h b/include/QF/plist.h index 46179bdc5..5ec11f849 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -143,8 +143,34 @@ typedef struct plelement_s { \return Returns an object equivalent to the passed-in string. \note You are responsible for freeing the returned object. */ -plitem_t *PL_GetPropertyList (const char *string, - struct hashctx_s **hashctx); +plitem_t *PL_GetPropertyList (const char *string, struct hashctx_s **hashctx); + +/** Create a property list from a bare dictionary list. + + The input is treated as a list of dictionary key-value pairs without the + enclosing { or }. + + \param string dicitionary list string. + \param hashctx Hashlink chain to use when creating dictionaries (see + Hash_NewTable()). May be null. + + \return Returns a dictionary object. + \note You are responsible for freeing the returned object. +*/ +plitem_t *PL_GetDictionary (const char *string, struct hashctx_s **hashctx); + +/** Create a property list from a bare array list. + + The input is treated as a list of array values without the enclosing ( or ). + + \param string array list string. + \param hashctx Hashlink chain to use when creating dictionaries (see + Hash_NewTable()). May be null. + + \return Returns an array object. + \note You are responsible for freeing the returned object. +*/ +plitem_t *PL_GetArray (const char *string, struct hashctx_s **hashctx); /** Create a property list string from the in-memory representation. diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 430971b05..304fe14b0 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -188,9 +188,9 @@ plist_retain (plist_resources_t *res, plitem_t *plitem) } static void -bi_PL_GetFromFile (progs_t *pr, void *_res) +bi_pl_getfromfile (progs_t *pr, plist_resources_t *res, + plitem_t *get (const char *, struct hashctx_s **)) { - plist_resources_t *res = _res; QFile *file = QFile_GetFile (pr, P_INT (pr, 0)); plitem_t *plitem; long offset; @@ -205,19 +205,61 @@ bi_PL_GetFromFile (progs_t *pr, void *_res) Qread (file, buf, len); buf[len] = 0; - plitem = PL_GetPropertyList (buf, pr->hashctx); + plitem = get (buf, pr->hashctx); free (buf); R_INT (pr) = plist_retain (res, plitem); } +static void +bi_pl_get (progs_t *pr, plist_resources_t *res, + plitem_t *get (const char *, struct hashctx_s **)) +{ + plitem_t *plitem = get (P_GSTRING (pr, 0), pr->hashctx); + + R_INT (pr) = plist_retain (res, plitem); +} + +static void +bi_PL_GetFromFile (progs_t *pr, void *_res) +{ + plist_resources_t *res = _res; + bi_pl_getfromfile (pr, res, PL_GetPropertyList); +} + static void bi_PL_GetPropertyList (progs_t *pr, void *_res) { plist_resources_t *res = _res; - plitem_t *plitem = PL_GetPropertyList (P_GSTRING (pr, 0), pr->hashctx); + bi_pl_get (pr, res, PL_GetPropertyList); +} - R_INT (pr) = plist_retain (res, plitem); +static void +bi_PL_GetDictionaryFromFile (progs_t *pr, void *_res) +{ + plist_resources_t *res = _res; + bi_pl_getfromfile (pr, res, PL_GetDictionary); +} + +static void +bi_PL_GetDictionary (progs_t *pr, void *_res) +{ + plist_resources_t *res = _res; + bi_pl_get (pr, res, PL_GetDictionary); +} + +static void +bi_PL_GetArrayFromFile (progs_t *pr, void *_res) +{ + plist_resources_t *res = _res; + bi_pl_getfromfile (pr, res, PL_GetArray); +} + +static void +bi_PL_GetArray (progs_t *pr, void *_res) +{ + plist_resources_t *res = _res; + bi_pl_get (pr, res, PL_GetArray); } static void @@ -481,6 +523,10 @@ plist_compare (const void *k1, const void *k2, void *unused) static builtin_t builtins[] = { bi(PL_GetFromFile, 1, p(ptr)), bi(PL_GetPropertyList, 1, p(string)), + bi(PL_GetDictionary, 1, p(string)), + bi(PL_GetDictionaryFromFile, 1, p(string)), + bi(PL_GetArray, 1, p(string)), + bi(PL_GetArrayFromFile, 1, p(string)), bi(PL_WritePropertyList, 1, p(ptr)), bi(PL_Type, 1, p(ptr)), bi(PL_Line, 1, p(ptr)), diff --git a/libs/util/plist.c b/libs/util/plist.c index ff1287773..475380dc3 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -936,8 +936,9 @@ pl_parsepropertylistitem (pldata_t *pl) } } -VISIBLE plitem_t * -PL_GetPropertyList (const char *string, hashctx_t **hashctx) +static plitem_t * +pl_parseitem (const char *string, hashctx_t **hashctx, + plitem_t *(*parse) (pldata_t *)) { plitem_t *newpl = NULL; @@ -951,7 +952,7 @@ PL_GetPropertyList (const char *string, hashctx_t **hashctx) .hashctx = hashctx, }; - if (!(newpl = pl_parsepropertylistitem (&pl))) { + if (!(newpl = parse (&pl))) { if (pl.errmsg) { Sys_Printf ("plist: %d,%d: %s\n", pl.line, pl.pos - pl.line_start, pl.errmsg->str); @@ -962,6 +963,57 @@ PL_GetPropertyList (const char *string, hashctx_t **hashctx) return newpl; } +VISIBLE plitem_t * +PL_GetPropertyList (const char *string, hashctx_t **hashctx) +{ + return pl_parseitem (string, hashctx, pl_parsepropertylistitem); +} + + +static plitem_t * +pl_getdictionary (pldata_t *pl) +{ + plitem_t *dict = PL_NewDictionary (pl->hashctx); + dict->line = pl->line; + + while (pl_skipspace (pl, 1)) { + if (!pl_parsekeyvalue (pl, dict, 1)) { + PL_Free (dict); + return NULL; + } + } + + return dict; +} + +VISIBLE plitem_t * +PL_GetDictionary (const char *string, hashctx_t **hashctx) +{ + return pl_parseitem (string, hashctx, pl_getdictionary); +} + +static plitem_t * +pl_getarray (pldata_t *pl) +{ + plitem_t *array = PL_NewArray (); + array->line = pl->line; + + while (pl_skipspace (pl, 1)) { + if (!pl_parsevalue (pl, array, 1)) { + PL_Free (array); + return NULL; + } + } + + return array; +} + +VISIBLE plitem_t * +PL_GetArray (const char *string, hashctx_t **hashctx) +{ + return pl_parseitem (string, hashctx, pl_getarray); +} + static void write_tabs (dstring_t *dstr, int num) { diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index bc3b511fa..6e4db10eb 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -700,18 +700,14 @@ qfs_load_config (void) goto no_config; len = Qfilesize (f); - buf = malloc (len + 3); // +3 for { } and \0 + buf = malloc (len + 1); // +1 for nul - Qread (f, buf + 1, len); + Qread (f, buf, len); Qclose (f); - // convert the config file to a plist dictionary - buf[0] = '{'; - buf[len + 1] = '}'; - buf[len + 2] = 0; if (qfs_gd_plist) PL_Free (qfs_gd_plist); - qfs_gd_plist = PL_GetPropertyList (buf, 0); + qfs_gd_plist = PL_GetDictionary (buf, 0); free (buf); if (qfs_gd_plist && PL_Type (qfs_gd_plist) == QFDictionary) return; // done From 8f874071333ed3a056405b2d86487d8b7574e9d8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Mar 2023 14:35:17 +0900 Subject: [PATCH 3506/3664] [ruamoko] Add wrappers for the new plist functions With both file and string versions (as per PL_GetPropertyList). --- ruamoko/include/PropertyList.h | 4 ++++ ruamoko/include/plist.h | 4 ++++ ruamoko/lib/PropertyList.r | 37 ++++++++++++++++++++++++++++------ ruamoko/lib/plist.r | 4 ++++ 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/ruamoko/include/PropertyList.h b/ruamoko/include/PropertyList.h index f6c059154..cc72dc3f4 100644 --- a/ruamoko/include/PropertyList.h +++ b/ruamoko/include/PropertyList.h @@ -49,10 +49,14 @@ @interface PLDictionary: PLItem + (PLDictionary *) new; ++ (PLItem *) fromString:(string) str; ++ (PLItem *) fromFile:(QFile) file; @end @interface PLArray: PLItem + (PLArray *) new; ++ (PLItem *) fromString:(string) str; ++ (PLItem *) fromFile:(QFile) file; @end @interface PLData: PLItem diff --git a/ruamoko/include/plist.h b/ruamoko/include/plist.h index 5482976fa..9b5817491 100644 --- a/ruamoko/include/plist.h +++ b/ruamoko/include/plist.h @@ -8,6 +8,10 @@ typedef enum {QFDictionary, QFArray, QFBinary, QFString} pltype_t; // possible t @extern plitem_t *PL_GetFromFile (QFile file); @extern plitem_t *PL_GetPropertyList (string str); +@extern plitem_t *PL_GetDictionaryFromFile (QFile file); +@extern plitem_t *PL_GetDictionary (string str); +@extern plitem_t *PL_GetArrayFromFile (QFile file); +@extern plitem_t *PL_GetArray (string str); @extern string PL_WritePropertyList (plitem_t *pl); @extern pltype_t PL_Type (plitem_t *str); @extern int PL_Line (plitem_t *str); diff --git a/ruamoko/lib/PropertyList.r b/ruamoko/lib/PropertyList.r index 9feee810a..02f28fb54 100644 --- a/ruamoko/lib/PropertyList.r +++ b/ruamoko/lib/PropertyList.r @@ -49,18 +49,23 @@ return [[class alloc] initWithItem: item]; } ++ (PLItem *) ownItemClass:(plitem_t *) item +{ + PLItem *plitem = [PLItem itemClass:item]; + if (plitem) { + plitem.own = 1; + } + return plitem; +} + + (PLItem *) fromString:(string) str { - PLItem *item = [[PLItem itemClass: PL_GetPropertyList (str)] autorelease]; - item.own = 1; - return item; + return [[PLItem ownItemClass: PL_GetPropertyList (str)] autorelease]; } + (PLItem *) fromFile:(QFile) file { - PLItem *item = [[PLItem itemClass: PL_GetFromFile (file)] autorelease]; - item.own = 1; - return item; + return [[PLItem ownItemClass: PL_GetFromFile (file)] autorelease]; } - initWithItem:(plitem_t *) item @@ -198,6 +203,16 @@ return [[PLDictionary alloc] initWithOwnItem: PL_NewDictionary ()]; } ++ (PLItem *) fromString:(string) str +{ + return [[PLItem ownItemClass: PL_GetDictionary (str)] autorelease]; +} + ++ (PLItem *) fromFile:(QFile) file +{ + return [[PLItem ownItemClass: PL_GetDictionaryFromFile (file)] autorelease]; +} + - (int) count { return PL_D_NumKeys (item); @@ -241,6 +256,16 @@ return [[PLArray alloc] initWithOwnItem: PL_NewArray ()]; } ++ (PLItem *) fromString:(string) str +{ + return [[PLItem ownItemClass: PL_GetArray (str)] autorelease]; +} + ++ (PLItem *) fromFile:(QFile) file +{ + return [[PLItem ownItemClass: PL_GetArrayFromFile (file)] autorelease]; +} + - (int) count { return PL_A_NumObjects (item); diff --git a/ruamoko/lib/plist.r b/ruamoko/lib/plist.r index 743602888..b961dc0d7 100644 --- a/ruamoko/lib/plist.r +++ b/ruamoko/lib/plist.r @@ -2,6 +2,10 @@ plitem_t *PL_GetFromFile (QFile file) = #0; plitem_t *PL_GetPropertyList (string str) = #0; +plitem_t *PL_GetDictionaryFromFile (QFile file) = #0; +plitem_t *PL_GetDictionary (string str) = #0; +plitem_t *PL_GetArrayFromFile (QFile file) = #0; +plitem_t *PL_GetArray (string str) = #0; string PL_WritePropertyList (plitem_t *pl) = #0; pltype_t PL_Type (plitem_t *str) = #0; int PL_Line (plitem_t *str) = #0; From 3cdcc2c62c69c96a156ecd0353093e6e947cc65e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Mar 2023 14:36:47 +0900 Subject: [PATCH 3507/3664] [vkgen] Switch to bare dictionary for parse spec This served as a nice test for the bare dictionary parsing (though quakefs.c did, too), and even found a bug in vkgen's error handling. --- libs/video/renderer/vulkan/vkgen/vkgen.r | 3 +- libs/video/renderer/vulkan/vkparse.plist | 1384 +++++++++++----------- 2 files changed, 693 insertions(+), 694 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 32901bfaa..bbad10551 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -160,7 +160,7 @@ main(int argc, string *argv) printf ("could not open property list file: %s\n", plist_filename); return 1; } - plist = [[PLItem fromFile: plist_file] retain]; + plist = [[PLDictionary fromFile: plist_file] retain]; if (!plist) { printf ("error parsing: %s\n", plist_filename); return 1; @@ -168,6 +168,7 @@ main(int argc, string *argv) Qclose (plist_file); if ([plist class] != [PLDictionary class]) { printf ("%s not a dictionary\n", plist_filename); + return 1; } search = [[plist getObjectForKey: "search"] retain]; handles = [[plist getObjectForKey: "handles"] retain]; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 8cd137407..4b84021ae 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -1,701 +1,699 @@ -{ - search = ( - VkAttachmentDescription, - VkDebugUtilsMessageSeverityFlagBitsEXT, - VkPresentModeKHR, - VkSubpassDescription, - VkSubpassDependency, - VkSpecializationInfo, - VkPipelineShaderStageCreateInfo, - VkPipelineVertexInputStateCreateInfo, - VkPipelineInputAssemblyStateCreateInfo, - VkPipelineViewportStateCreateInfo, - VkPipelineRasterizationStateCreateInfo, - VkPipelineMultisampleStateCreateInfo, - VkPipelineDepthStencilStateCreateInfo, - VkPipelineColorBlendStateCreateInfo, - VkPipelineDynamicStateCreateInfo, - VkDescriptorSetLayoutBinding, - VkDescriptorSetLayoutCreateInfo, - VkPushConstantRange, - VkPipelineLayoutCreateInfo, - VkGraphicsPipelineCreateInfo, - VkComputePipelineCreateInfo, - VkDescriptorPoolCreateInfo, - VkSamplerCreateInfo, - VkImageCreateInfo, - VkImageViewCreateInfo, - VkFramebufferCreateInfo, - VkClearValue, - VkPhysicalDeviceLimits, - VkRenderPassCreateInfo, - VkRenderPassMultiviewCreateInfo, +search = ( + VkAttachmentDescription, + VkDebugUtilsMessageSeverityFlagBitsEXT, + VkPresentModeKHR, + VkSubpassDescription, + VkSubpassDependency, + VkSpecializationInfo, + VkPipelineShaderStageCreateInfo, + VkPipelineVertexInputStateCreateInfo, + VkPipelineInputAssemblyStateCreateInfo, + VkPipelineViewportStateCreateInfo, + VkPipelineRasterizationStateCreateInfo, + VkPipelineMultisampleStateCreateInfo, + VkPipelineDepthStencilStateCreateInfo, + VkPipelineColorBlendStateCreateInfo, + VkPipelineDynamicStateCreateInfo, + VkDescriptorSetLayoutBinding, + VkDescriptorSetLayoutCreateInfo, + VkPushConstantRange, + VkPipelineLayoutCreateInfo, + VkGraphicsPipelineCreateInfo, + VkComputePipelineCreateInfo, + VkDescriptorPoolCreateInfo, + VkSamplerCreateInfo, + VkImageCreateInfo, + VkImageViewCreateInfo, + VkFramebufferCreateInfo, + VkClearValue, + VkPhysicalDeviceLimits, + VkRenderPassCreateInfo, + VkRenderPassMultiviewCreateInfo, - qfv_subpass_t, - qfv_output_t, + qfv_subpass_t, + qfv_output_t, - qfv_descriptorsetinfo_t, - qfv_imageinfo_t, - qfv_imageviewinfo_t, - qfv_dependencyinfo_t, - qfv_attachmentinfo_t, - qfv_attachmentrefinfo_t, - qfv_attachmentsetinfo_t, - qfv_taskinfo_t, - qfv_layoutinfo_t, - qfv_pipelineinfo_t, - qfv_subpassinfo_t, - qfv_framebufferinfo_t, - qfv_renderpassinfo_t, - qfv_renderinfo_t, - qfv_computeinfo_t, - qfv_processinfo_t, - qfv_stepinfo_t, - qfv_jobinfo_t, - ); - parse = { - VkSubpassDescription = { - flags = auto; - pipelineBindPoint = auto; - inputAttachments = { - type = (array, VkAttachmentReference); - size = inputAttachmentCount; - values = pInputAttachments; - }; - colorAttachments = { - type = (array, VkAttachmentReference); - size = colorAttachmentCount; - values = pColorAttachments; - }; - resolveAttachments = { - type = (array, VkAttachmentReference); - values = pResolveAttachments; - matchSize = colorAttachments; - }; - depthStencilAttachment = { - type = (single, VkAttachmentReference); - value = pDepthStencilAttachment; - }; - preserveAttachments = { - type = (array, uint32_t); - size = preserveAttachmentCount; - values = pPreserveAttachments; - }; + qfv_descriptorsetinfo_t, + qfv_imageinfo_t, + qfv_imageviewinfo_t, + qfv_dependencyinfo_t, + qfv_attachmentinfo_t, + qfv_attachmentrefinfo_t, + qfv_attachmentsetinfo_t, + qfv_taskinfo_t, + qfv_layoutinfo_t, + qfv_pipelineinfo_t, + qfv_subpassinfo_t, + qfv_framebufferinfo_t, + qfv_renderpassinfo_t, + qfv_renderinfo_t, + qfv_computeinfo_t, + qfv_processinfo_t, + qfv_stepinfo_t, + qfv_jobinfo_t, +); +parse = { + VkSubpassDescription = { + flags = auto; + pipelineBindPoint = auto; + inputAttachments = { + type = (array, VkAttachmentReference); + size = inputAttachmentCount; + values = pInputAttachments; }; - VkPhysicalDeviceLimits = readonly; - VkRenderPassCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - attachments = { - type = (array, VkAttachmentDescription); - size = attachmentCount; - values = pAttachments; - }; - subpasses = { - type = (array, VkSubpassDescription); - size = subpassCount; - values = pSubpasses; - }; - dependencies = { - type = (array, VkSubpassDependency); - size = dependencyCount; - values = pDependencies; - }; + colorAttachments = { + type = (array, VkAttachmentReference); + size = colorAttachmentCount; + values = pColorAttachments; }; - VkSpecializationInfo = { - mapEntries = { - type = (array, VkSpecializationMapEntry); - size = mapEntryCount; - values = pMapEntries; - }; - data = { - type = (custom, (QFBinary, QFString), - parse_specialization_data); - fields = (dataSize, pData); - }; + resolveAttachments = { + type = (array, VkAttachmentReference); + values = pResolveAttachments; + matchSize = colorAttachments; }; - VkPipelineShaderStageCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - stage = auto; - name = { - type = string; - string = pName; - }; - module = { - type = (custom, QFString, parse_VkShaderModule); - fields = (module); - }; - specializationInfo = { - type = (single, VkSpecializationInfo); - value = pSpecializationInfo; - }; + depthStencilAttachment = { + type = (single, VkAttachmentReference); + value = pDepthStencilAttachment; }; - VkShaderModuleCreateInfo = skip; - VkDescriptorSetLayoutBinding = { - binding = auto; - descriptorType = auto; - descriptorCount = auto; - stageFlags = auto; - // skip pImmutableSamplers (default to 0) until I know how it works - }; - VkDescriptorSetLayoutCreateInfo = { - flags = auto; - bindings = { - type = (array, VkDescriptorSetLayoutBinding); - size = bindingCount; - values = pBindings; - }; - }; - VkDescriptorPoolCreateInfo = { - flags = auto; - maxSets = auto; - bindings = { - type = (array, VkDescriptorPoolSize); - size = poolSizeCount; - values = pPoolSizes; - }; - }; - VkPipelineVertexInputStateCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - bindings = { - type = (array, VkVertexInputBindingDescription); - size = vertexBindingDescriptionCount; - values = pVertexBindingDescriptions; - }; - attributes = { - type = (array, VkVertexInputAttributeDescription); - size = vertexAttributeDescriptionCount; - values = pVertexAttributeDescriptions; - }; - }; - VkPipelineInputAssemblyStateCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - topology = auto; - primitiveRestartEnable = auto; - }; - VkPipelineViewportStateCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - //FIXME redo as one array - viewports = { - type = (array, VkViewport); - size = viewportCount; - values = pViewports; - }; - scissors = { - type = (array, VkRect2D); - size = scissorCount; - values = pScissors; - }; - }; - VkPipelineRasterizationStateCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - depthClampEnable = auto; - rasterizerDiscardEnable = auto; - polygonMode = auto; - cullMode = auto; - frontFace = auto; - depthBiasEnable = auto; - depthBiasConstantFactor = auto; - depthBiasClamp = auto; - depthBiasSlopeFactor = auto; - lineWidth = auto; - }; - VkPipelineMultisampleStateCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - rasterizationSamples = auto; - sampleShadingEnable = auto; - minSampleShading = auto; - //pSampleMask = auto; FIXME disabled until correct size is known - alphaToCoverageEnable = auto; - alphaToOneEnable = auto; - }; - VkPipelineDepthStencilStateCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - depthTestEnable = auto; - depthWriteEnable = auto; - depthCompareOp = auto; - depthBoundsTestEnable = auto; - stencilTestEnable = auto; - front = auto; - back = auto; - minDepthBounds = auto; - maxDepthBounds = auto; - }; - VkPipelineColorBlendStateCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - logicOpEnable = auto; - logicOp = auto; - attachments = { - type = (array, VkPipelineColorBlendAttachmentState); - size = attachmentCount; - values = pAttachments; - }; - blendConstants = { - type = (custom, QFString, parse_RGBA); - fields = (blendConstants); - }; - }; - VkPipelineDynamicStateCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - dynamicState = { - type = (array, VkDynamicState); - size = dynamicStateCount; - values = pDynamicStates; - }; - }; - VkPipelineLayoutCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - setLayouts = { - type = (array, { - parse_type = (QFDictionary, QFString); - type = VkDescriptorSetLayout; - parser = parse_VkDescriptorSetLayout; - }); - size = setLayoutCount; - values = pSetLayouts; - }; - pushConstantRanges = { - type = (array, VkPushConstantRange); - size = pushConstantRangeCount; - values = pPushConstantRanges; - }; - }; - VkPipelineTessellationStateCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - patchControlPoints = auto; - }; - VkGraphicsPipelineCreateInfo = { - flags = auto; - stages = { - type = (array, VkPipelineShaderStageCreateInfo); - size = stageCount; - values = pStages; - }; - vertexInput = { - type = (single, VkPipelineVertexInputStateCreateInfo); - value = pVertexInputState; - }; - inputAssembly = { - type = (single, VkPipelineInputAssemblyStateCreateInfo); - value = pInputAssemblyState; - }; - tessellation = { - type = (single, VkPipelineTessellationStateCreateInfo); - value = pTessellationState; - }; - viewport = { - type = (single, VkPipelineViewportStateCreateInfo); - value = pViewportState; - }; - rasterization = { - type = (single, VkPipelineRasterizationStateCreateInfo); - value = pRasterizationState; - }; - multisample = { - type = (single, VkPipelineMultisampleStateCreateInfo); - value = pMultisampleState; - }; - depthStencil = { - type = (single, VkPipelineDepthStencilStateCreateInfo); - value = pDepthStencilState; - }; - colorBlend = { - type = (single, VkPipelineColorBlendStateCreateInfo); - value = pColorBlendState; - }; - dynamic = { - type = (single, VkPipelineDynamicStateCreateInfo); - value = pDynamicState; - }; - layout = { - type = (custom, QFString, parse_VkPipelineLayout); - fields = (layout); - }; - renderPass = { - type = (custom, QFString, parse_VkRenderPass); - fields = (renderPass); - }; - subpass = auto; - basePipelineHandle = { - type = (custom, QFString, parse_BasePipeline); - fields = (basePipelineHandle); - }; - basePipelineIndex = auto; - }; - VkComputePipelineCreateInfo = { - flags = auto; - stage = auto; - layout = { - type = (custom, QFString, parse_VkPipelineLayout); - fields = (layout); - }; - basePipelineHandle = { - type = (custom, QFString, parse_BasePipeline); - fields = (basePipelineHandle); - }; - basePipelineIndex = auto; - }; - VkImageCreateInfo = { - flags = auto; - imageType = auto; - format = auto; - extent = auto; - mipLevels = auto; - arrayLayers = auto; - samples = auto; - tiling = auto; - usage = auto; - sharingMode = skip; // FIXME for now - queueFamilyIndexCount = skip; // FIXME for now - pQueueFamilyIndices = skip; // FIXME for now - initialLayout = auto; - }; - VkImageViewCreateInfo = { - flags = auto; - image = { - type = (custom, (QFDictionary, QFString), - parse_VkImage); - fields = (image); - }; - viewType = auto; - format = auto; - components = auto; - subresourceRange = auto; - }; - VkFramebufferCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - renderPass = { - type = (custom, QFString, parse_VkRenderPass); - fields = (renderPass); - }; - attachments = { - type = (array, VkImageView); - size = attachmentCount; - values = pAttachments; - }; - width = auto; - height = auto; - layers = auto; - }; - VkClearColorValue = skip; - VkClearValue = { - color = { - type = (custom, QFString, parse_RGBA); - fields = (color); - }; - depthStencil = auto; - }; - VkRenderPassMultiviewCreateInfo = { - viewMasks = { - type = (array, uint32_t); - size = subpassCount; - values = pViewMasks; - }; - viewOffsets = { - type = (array, int32_t); - size = dependencyCount; - values = pViewOffsets; - }; - correlationMasks = { - type = (array, uint32_t); - size = correlationMaskCount; - values = pCorrelationMasks; - }; - }; - - qfv_subpass_s = { - .name = qfv_subpass_t; - color = { - type = (custom, QFString, parse_RGBA); - fields = (color); - }; - name = { - type = string; - string = name; - }; - }; - qfv_output_s = { - .name = qfv_output_t; - extent = auto; - image = { - type = (readonly, VkImage); - value = image; - }; - view = { - type = (readonly, VkImageView); - value = view; - }; - format = auto; - frames = auto; - finalLayout = auto; - }; - - qfv_taskinfo_s = { - .name = qfv_taskinfo_t; - func = { - type = (custom, QFString, parse_task_function); - fields = (func, params, param_data); - }; - params = { - type = (custom, QFArray, parse_task_params); - fields = (func, params, param_data); - }; - }; - qfv_attachmentrefinfo_s = { - .name = qfv_attachmentrefinfo_t; - .type = (QFString, QFDictionary); - .string = { - name = $name; - line = $item.line; - layout = $auto; - blend = "(VkPipelineColorBlendAttachmentState) { .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT }" - }; - .dictionary = { - .parse = auto; - name = $name; - line = $item.line; - }; - layout = auto; - blend = auto; - }; - qfv_attachmentsetinfo_s = { - .name = qfv_attachmentsetinfo_t; - input = { - type = (labeledarray, qfv_attachmentrefinfo_t, name); - size = num_input; - values = input; - }; - color = { - type = (labeledarray, qfv_attachmentrefinfo_t, name); - size = num_color; - values = color; - }; - resolve = { - type = (labeledarray, qfv_attachmentrefinfo_t, name); - values = resolve; - matchSize = color; - }; - depth = { - type = (labeledsingle, qfv_attachmentrefinfo_t, name); - value = depth; - }; - preserve = { - type = (array, qfv_reference_t); - size = num_preserve; - values = preserve; - }; - }; - qfv_layoutinfo_s = { - .name = qfv_layoutinfo_t; - descriptorSets = { - type = (array, qfv_reference_t); - size = num_sets; - values = sets; - }; - pushConstantRanges = { - type = (array, VkPushConstantRange); - size = num_ranges; - values = ranges; - }; - }; - qfv_pipelineinfo_s = { - .name = qfv_pipelineinfo_t; - color = auto; - name = { - type = string; - string = name; - }; - tasks = { - type = (array, qfv_taskinfo_t); - size = num_tasks; - values = tasks; - }; - - flags = auto; - stages = { - type = (array, VkPipelineShaderStageCreateInfo); - size = num_graph_stages; - values = graph_stages; - }; - stage = { - type = (single, VkPipelineShaderStageCreateInfo); - value = compute_stage; - }; - dispatch = auto; - vertexInput = { - type = (single, VkPipelineVertexInputStateCreateInfo); - value = vertexInput; - }; - inputAssembly = { - type = (single, VkPipelineInputAssemblyStateCreateInfo); - value = inputAssembly; - }; - tessellation = { - type = (single, VkPipelineTessellationStateCreateInfo); - value = tessellation; - }; - viewport = { - type = (single, VkPipelineViewportStateCreateInfo); - value = viewport; - }; - rasterization = { - type = (single, VkPipelineRasterizationStateCreateInfo); - value = rasterization; - }; - multisample = { - type = (single, VkPipelineMultisampleStateCreateInfo); - value = multisample; - }; - depthStencil = { - type = (single, VkPipelineDepthStencilStateCreateInfo); - value = depthStencil; - }; - colorBlend = { - type = (single, VkPipelineColorBlendStateCreateInfo); - value = colorBlend; - }; - dynamic = { - type = (single, VkPipelineDynamicStateCreateInfo); - value = dynamic; - }; - layout = auto; - }; - qfv_subpassinfo_s = { - .name = qfv_subpassinfo_t; - name = { - type = string; - string = name; - }; - color = auto; - dependencies = { - type = (labeledarray, qfv_dependencyinfo_t, name); - size = num_dependencies; - values = dependencies; - }; - attachments = { - type = (single, qfv_attachmentsetinfo_t); - value = attachments; - }; - pipelines = { - type = (labeledarray, qfv_pipelineinfo_t, name); - size = num_pipelines; - values = pipelines; - }; - base_pipeline = { - //type = (labeledsingle, qfv_pipelineinfo_t, name); - type = (single, qfv_pipelineinfo_t, name); - value = base_pipeline; - }; - }; - qfv_framebufferinfo_s = { - .name = qfv_framebufferinfo_t; - width = auto; - height = auto; - layers = auto; - }; - qfv_reference_s = { - .name = qfv_reference_t; - .type = QFString; - .string = { - name = $item.string; - line = $item.line; - }; - }; - qfv_renderpassinfo_s = { - .name = qfv_renderpassinfo_t; - color = auto; - attachments = { - type = (labeledarray, qfv_attachmentinfo_t, name); - size = num_attachments; - values = attachments; - }; - framebuffer = auto; - subpasses = { - type = (labeledarray, qfv_subpassinfo_t, name); - size = num_subpasses; - values = subpasses; - }; - }; - qfv_descriptorsetinfo_s = { - .name = qfv_descriptorsetinfo_t; - flags = auto; - bindings = { - type = (array, VkDescriptorSetLayoutBinding); - size = num_bindings; - values = bindings; - }; - }; - qfv_computeinfo_s = { - .name = qfv_computeinfo_t; - color = auto; - pipelines = { - type = (labeledarray, qfv_pipelineinfo_t, name); - size = num_pipelines; - values = pipelines; - }; - }; - qfv_renderinfo_s = { - .name = qfv_renderinfo_t; - color = auto; - properties = ignore; - output = ignore; - images = { - type = (labeledarray, qfv_imageinfo_t, name); - size = num_images; - values = images; - }; - views = { - type = (labeledarray, qfv_imageviewinfo_t, name); - size = num_views; - values = views; - }; - renderpasses = { - type = (labeledarray, qfv_renderpassinfo_t, name); - size = num_renderpasses; - values = renderpasses; - }; - descriptorSetLayouts = { - type = (labeledarray, qfv_descriptorsetinfo_t, name); - size = num_descriptorsets; - values = descriptorsets; - }; - }; - qfv_processinfo_s = { - .name = qfv_processinfo_t; - color = auto; - tasks = { - type = (array, qfv_taskinfo_t); - size = num_tasks; - values = tasks; - }; - }; - qfv_stepinfo_s = { - .name = qfv_stepinfo_t; - color = auto; - dependencies = { - type = (array, qfv_reference_t); - size = num_dependencies; - values = dependencies; - }; - render = { - type = (single, qfv_renderinfo_t); - value = render; - }; - compute = { - type = (single, qfv_computeinfo_t); - value = compute; - }; - process = { - type = (single, qfv_processinfo_t); - value = process; - }; - }; - qfv_jobinfo_s = { - .name = qfv_jobinfo_t; - steps = { - type = (array, qfv_stepinfo_t); - size = num_steps; - values = steps; - }; + preserveAttachments = { + type = (array, uint32_t); + size = preserveAttachmentCount; + values = pPreserveAttachments; }; }; -} + VkPhysicalDeviceLimits = readonly; + VkRenderPassCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + attachments = { + type = (array, VkAttachmentDescription); + size = attachmentCount; + values = pAttachments; + }; + subpasses = { + type = (array, VkSubpassDescription); + size = subpassCount; + values = pSubpasses; + }; + dependencies = { + type = (array, VkSubpassDependency); + size = dependencyCount; + values = pDependencies; + }; + }; + VkSpecializationInfo = { + mapEntries = { + type = (array, VkSpecializationMapEntry); + size = mapEntryCount; + values = pMapEntries; + }; + data = { + type = (custom, (QFBinary, QFString), + parse_specialization_data); + fields = (dataSize, pData); + }; + }; + VkPipelineShaderStageCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + stage = auto; + name = { + type = string; + string = pName; + }; + module = { + type = (custom, QFString, parse_VkShaderModule); + fields = (module); + }; + specializationInfo = { + type = (single, VkSpecializationInfo); + value = pSpecializationInfo; + }; + }; + VkShaderModuleCreateInfo = skip; + VkDescriptorSetLayoutBinding = { + binding = auto; + descriptorType = auto; + descriptorCount = auto; + stageFlags = auto; + // skip pImmutableSamplers (default to 0) until I know how it works + }; + VkDescriptorSetLayoutCreateInfo = { + flags = auto; + bindings = { + type = (array, VkDescriptorSetLayoutBinding); + size = bindingCount; + values = pBindings; + }; + }; + VkDescriptorPoolCreateInfo = { + flags = auto; + maxSets = auto; + bindings = { + type = (array, VkDescriptorPoolSize); + size = poolSizeCount; + values = pPoolSizes; + }; + }; + VkPipelineVertexInputStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + bindings = { + type = (array, VkVertexInputBindingDescription); + size = vertexBindingDescriptionCount; + values = pVertexBindingDescriptions; + }; + attributes = { + type = (array, VkVertexInputAttributeDescription); + size = vertexAttributeDescriptionCount; + values = pVertexAttributeDescriptions; + }; + }; + VkPipelineInputAssemblyStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + topology = auto; + primitiveRestartEnable = auto; + }; + VkPipelineViewportStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + //FIXME redo as one array + viewports = { + type = (array, VkViewport); + size = viewportCount; + values = pViewports; + }; + scissors = { + type = (array, VkRect2D); + size = scissorCount; + values = pScissors; + }; + }; + VkPipelineRasterizationStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + depthClampEnable = auto; + rasterizerDiscardEnable = auto; + polygonMode = auto; + cullMode = auto; + frontFace = auto; + depthBiasEnable = auto; + depthBiasConstantFactor = auto; + depthBiasClamp = auto; + depthBiasSlopeFactor = auto; + lineWidth = auto; + }; + VkPipelineMultisampleStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + rasterizationSamples = auto; + sampleShadingEnable = auto; + minSampleShading = auto; + //pSampleMask = auto; FIXME disabled until correct size is known + alphaToCoverageEnable = auto; + alphaToOneEnable = auto; + }; + VkPipelineDepthStencilStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + depthTestEnable = auto; + depthWriteEnable = auto; + depthCompareOp = auto; + depthBoundsTestEnable = auto; + stencilTestEnable = auto; + front = auto; + back = auto; + minDepthBounds = auto; + maxDepthBounds = auto; + }; + VkPipelineColorBlendStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + logicOpEnable = auto; + logicOp = auto; + attachments = { + type = (array, VkPipelineColorBlendAttachmentState); + size = attachmentCount; + values = pAttachments; + }; + blendConstants = { + type = (custom, QFString, parse_RGBA); + fields = (blendConstants); + }; + }; + VkPipelineDynamicStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + dynamicState = { + type = (array, VkDynamicState); + size = dynamicStateCount; + values = pDynamicStates; + }; + }; + VkPipelineLayoutCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + setLayouts = { + type = (array, { + parse_type = (QFDictionary, QFString); + type = VkDescriptorSetLayout; + parser = parse_VkDescriptorSetLayout; + }); + size = setLayoutCount; + values = pSetLayouts; + }; + pushConstantRanges = { + type = (array, VkPushConstantRange); + size = pushConstantRangeCount; + values = pPushConstantRanges; + }; + }; + VkPipelineTessellationStateCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + patchControlPoints = auto; + }; + VkGraphicsPipelineCreateInfo = { + flags = auto; + stages = { + type = (array, VkPipelineShaderStageCreateInfo); + size = stageCount; + values = pStages; + }; + vertexInput = { + type = (single, VkPipelineVertexInputStateCreateInfo); + value = pVertexInputState; + }; + inputAssembly = { + type = (single, VkPipelineInputAssemblyStateCreateInfo); + value = pInputAssemblyState; + }; + tessellation = { + type = (single, VkPipelineTessellationStateCreateInfo); + value = pTessellationState; + }; + viewport = { + type = (single, VkPipelineViewportStateCreateInfo); + value = pViewportState; + }; + rasterization = { + type = (single, VkPipelineRasterizationStateCreateInfo); + value = pRasterizationState; + }; + multisample = { + type = (single, VkPipelineMultisampleStateCreateInfo); + value = pMultisampleState; + }; + depthStencil = { + type = (single, VkPipelineDepthStencilStateCreateInfo); + value = pDepthStencilState; + }; + colorBlend = { + type = (single, VkPipelineColorBlendStateCreateInfo); + value = pColorBlendState; + }; + dynamic = { + type = (single, VkPipelineDynamicStateCreateInfo); + value = pDynamicState; + }; + layout = { + type = (custom, QFString, parse_VkPipelineLayout); + fields = (layout); + }; + renderPass = { + type = (custom, QFString, parse_VkRenderPass); + fields = (renderPass); + }; + subpass = auto; + basePipelineHandle = { + type = (custom, QFString, parse_BasePipeline); + fields = (basePipelineHandle); + }; + basePipelineIndex = auto; + }; + VkComputePipelineCreateInfo = { + flags = auto; + stage = auto; + layout = { + type = (custom, QFString, parse_VkPipelineLayout); + fields = (layout); + }; + basePipelineHandle = { + type = (custom, QFString, parse_BasePipeline); + fields = (basePipelineHandle); + }; + basePipelineIndex = auto; + }; + VkImageCreateInfo = { + flags = auto; + imageType = auto; + format = auto; + extent = auto; + mipLevels = auto; + arrayLayers = auto; + samples = auto; + tiling = auto; + usage = auto; + sharingMode = skip; // FIXME for now + queueFamilyIndexCount = skip; // FIXME for now + pQueueFamilyIndices = skip; // FIXME for now + initialLayout = auto; + }; + VkImageViewCreateInfo = { + flags = auto; + image = { + type = (custom, (QFDictionary, QFString), + parse_VkImage); + fields = (image); + }; + viewType = auto; + format = auto; + components = auto; + subresourceRange = auto; + }; + VkFramebufferCreateInfo = { + //flags = auto; reserved for future use (Bits enum does not exist) + renderPass = { + type = (custom, QFString, parse_VkRenderPass); + fields = (renderPass); + }; + attachments = { + type = (array, VkImageView); + size = attachmentCount; + values = pAttachments; + }; + width = auto; + height = auto; + layers = auto; + }; + VkClearColorValue = skip; + VkClearValue = { + color = { + type = (custom, QFString, parse_RGBA); + fields = (color); + }; + depthStencil = auto; + }; + VkRenderPassMultiviewCreateInfo = { + viewMasks = { + type = (array, uint32_t); + size = subpassCount; + values = pViewMasks; + }; + viewOffsets = { + type = (array, int32_t); + size = dependencyCount; + values = pViewOffsets; + }; + correlationMasks = { + type = (array, uint32_t); + size = correlationMaskCount; + values = pCorrelationMasks; + }; + }; + + qfv_subpass_s = { + .name = qfv_subpass_t; + color = { + type = (custom, QFString, parse_RGBA); + fields = (color); + }; + name = { + type = string; + string = name; + }; + }; + qfv_output_s = { + .name = qfv_output_t; + extent = auto; + image = { + type = (readonly, VkImage); + value = image; + }; + view = { + type = (readonly, VkImageView); + value = view; + }; + format = auto; + frames = auto; + finalLayout = auto; + }; + + qfv_taskinfo_s = { + .name = qfv_taskinfo_t; + func = { + type = (custom, QFString, parse_task_function); + fields = (func, params, param_data); + }; + params = { + type = (custom, QFArray, parse_task_params); + fields = (func, params, param_data); + }; + }; + qfv_attachmentrefinfo_s = { + .name = qfv_attachmentrefinfo_t; + .type = (QFString, QFDictionary); + .string = { + name = $name; + line = $item.line; + layout = $auto; + blend = "(VkPipelineColorBlendAttachmentState) { .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT }" + }; + .dictionary = { + .parse = auto; + name = $name; + line = $item.line; + }; + layout = auto; + blend = auto; + }; + qfv_attachmentsetinfo_s = { + .name = qfv_attachmentsetinfo_t; + input = { + type = (labeledarray, qfv_attachmentrefinfo_t, name); + size = num_input; + values = input; + }; + color = { + type = (labeledarray, qfv_attachmentrefinfo_t, name); + size = num_color; + values = color; + }; + resolve = { + type = (labeledarray, qfv_attachmentrefinfo_t, name); + values = resolve; + matchSize = color; + }; + depth = { + type = (labeledsingle, qfv_attachmentrefinfo_t, name); + value = depth; + }; + preserve = { + type = (array, qfv_reference_t); + size = num_preserve; + values = preserve; + }; + }; + qfv_layoutinfo_s = { + .name = qfv_layoutinfo_t; + descriptorSets = { + type = (array, qfv_reference_t); + size = num_sets; + values = sets; + }; + pushConstantRanges = { + type = (array, VkPushConstantRange); + size = num_ranges; + values = ranges; + }; + }; + qfv_pipelineinfo_s = { + .name = qfv_pipelineinfo_t; + color = auto; + name = { + type = string; + string = name; + }; + tasks = { + type = (array, qfv_taskinfo_t); + size = num_tasks; + values = tasks; + }; + + flags = auto; + stages = { + type = (array, VkPipelineShaderStageCreateInfo); + size = num_graph_stages; + values = graph_stages; + }; + stage = { + type = (single, VkPipelineShaderStageCreateInfo); + value = compute_stage; + }; + dispatch = auto; + vertexInput = { + type = (single, VkPipelineVertexInputStateCreateInfo); + value = vertexInput; + }; + inputAssembly = { + type = (single, VkPipelineInputAssemblyStateCreateInfo); + value = inputAssembly; + }; + tessellation = { + type = (single, VkPipelineTessellationStateCreateInfo); + value = tessellation; + }; + viewport = { + type = (single, VkPipelineViewportStateCreateInfo); + value = viewport; + }; + rasterization = { + type = (single, VkPipelineRasterizationStateCreateInfo); + value = rasterization; + }; + multisample = { + type = (single, VkPipelineMultisampleStateCreateInfo); + value = multisample; + }; + depthStencil = { + type = (single, VkPipelineDepthStencilStateCreateInfo); + value = depthStencil; + }; + colorBlend = { + type = (single, VkPipelineColorBlendStateCreateInfo); + value = colorBlend; + }; + dynamic = { + type = (single, VkPipelineDynamicStateCreateInfo); + value = dynamic; + }; + layout = auto; + }; + qfv_subpassinfo_s = { + .name = qfv_subpassinfo_t; + name = { + type = string; + string = name; + }; + color = auto; + dependencies = { + type = (labeledarray, qfv_dependencyinfo_t, name); + size = num_dependencies; + values = dependencies; + }; + attachments = { + type = (single, qfv_attachmentsetinfo_t); + value = attachments; + }; + pipelines = { + type = (labeledarray, qfv_pipelineinfo_t, name); + size = num_pipelines; + values = pipelines; + }; + base_pipeline = { + //type = (labeledsingle, qfv_pipelineinfo_t, name); + type = (single, qfv_pipelineinfo_t, name); + value = base_pipeline; + }; + }; + qfv_framebufferinfo_s = { + .name = qfv_framebufferinfo_t; + width = auto; + height = auto; + layers = auto; + }; + qfv_reference_s = { + .name = qfv_reference_t; + .type = QFString; + .string = { + name = $item.string; + line = $item.line; + }; + }; + qfv_renderpassinfo_s = { + .name = qfv_renderpassinfo_t; + color = auto; + attachments = { + type = (labeledarray, qfv_attachmentinfo_t, name); + size = num_attachments; + values = attachments; + }; + framebuffer = auto; + subpasses = { + type = (labeledarray, qfv_subpassinfo_t, name); + size = num_subpasses; + values = subpasses; + }; + }; + qfv_descriptorsetinfo_s = { + .name = qfv_descriptorsetinfo_t; + flags = auto; + bindings = { + type = (array, VkDescriptorSetLayoutBinding); + size = num_bindings; + values = bindings; + }; + }; + qfv_computeinfo_s = { + .name = qfv_computeinfo_t; + color = auto; + pipelines = { + type = (labeledarray, qfv_pipelineinfo_t, name); + size = num_pipelines; + values = pipelines; + }; + }; + qfv_renderinfo_s = { + .name = qfv_renderinfo_t; + color = auto; + properties = ignore; + output = ignore; + images = { + type = (labeledarray, qfv_imageinfo_t, name); + size = num_images; + values = images; + }; + views = { + type = (labeledarray, qfv_imageviewinfo_t, name); + size = num_views; + values = views; + }; + renderpasses = { + type = (labeledarray, qfv_renderpassinfo_t, name); + size = num_renderpasses; + values = renderpasses; + }; + descriptorSetLayouts = { + type = (labeledarray, qfv_descriptorsetinfo_t, name); + size = num_descriptorsets; + values = descriptorsets; + }; + }; + qfv_processinfo_s = { + .name = qfv_processinfo_t; + color = auto; + tasks = { + type = (array, qfv_taskinfo_t); + size = num_tasks; + values = tasks; + }; + }; + qfv_stepinfo_s = { + .name = qfv_stepinfo_t; + color = auto; + dependencies = { + type = (array, qfv_reference_t); + size = num_dependencies; + values = dependencies; + }; + render = { + type = (single, qfv_renderinfo_t); + value = render; + }; + compute = { + type = (single, qfv_computeinfo_t); + value = compute; + }; + process = { + type = (single, qfv_processinfo_t); + value = process; + }; + }; + qfv_jobinfo_s = { + .name = qfv_jobinfo_t; + steps = { + type = (array, qfv_stepinfo_t); + size = num_steps; + values = steps; + }; + }; +}; From 45bcb3168456a0a7aa9b1f36890698bbc9cd7349 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Mar 2023 14:48:14 +0900 Subject: [PATCH 3508/3664] [vulkan] Use bare dictionaries for spec files Every time I created a new file from scratch, I always forgot the enclosing {}. Now I will probably include them by accident :P --- libs/video/renderer/vulkan/pl_output.plist | 494 ++-- libs/video/renderer/vulkan/pl_quake_def.plist | 2384 ++++++++--------- libs/video/renderer/vulkan/rp_defcube.plist | 648 +++-- libs/video/renderer/vulkan/rp_deferred.plist | 626 +++-- libs/video/renderer/vulkan/rp_forward.plist | 382 ++- libs/video/renderer/vulkan/rp_main_def.plist | 2 - libs/video/renderer/vulkan/rp_output.plist | 94 +- libs/video/renderer/vulkan/rp_shadow.plist | 100 +- libs/video/renderer/vulkan/vkparse.c | 2 +- 9 files changed, 2358 insertions(+), 2374 deletions(-) diff --git a/libs/video/renderer/vulkan/pl_output.plist b/libs/video/renderer/vulkan/pl_output.plist index ab3b2e029..a9a6198f2 100644 --- a/libs/video/renderer/vulkan/pl_output.plist +++ b/libs/video/renderer/vulkan/pl_output.plist @@ -1,260 +1,258 @@ -{ - samplers = { - linear = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 0; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; +samplers = { + linear = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 0; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; }; - descriptorPools = { - output_pool = { - flags = 0; - maxSets = "$frames.size * 2z"; - bindings = ( - { - type = combined_image_sampler; - descriptorCount = "$frames.size * 2z"; - }, - ); - }; - }; - setLayouts = { - matrix_set = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = vertex|geometry|fragment; - }, - ); - }; - output_set = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - }; - pipelineLayouts = { - output_layout = { - setLayouts = (matrix_set, output_set); - }; - waterwarp_layout = { - @inherit = $properties.pipelineLayouts.output_layout; - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "4"; - } - ); - }; - fisheye_layout = { - @inherit = $properties.pipelineLayouts.output_layout; - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "2 * 4"; - } - ); - }; - }; - - depthStencil = { - disable = { - depthTestEnable = false; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - }; - - inputAssembly = { - }; - - vertexInput = { - index_only = { - bindings = (); - attributes = (); - }; - }; - - rasterization = { - cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - counter_cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - }; - - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - - viewport = { - viewports = ( +}; +descriptorPools = { + output_pool = { + flags = 0; + maxSets = "$frames.size * 2z"; + bindings = ( { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; + type = combined_image_sampler; + descriptorCount = "$frames.size * 2z"; }, ); }; - - attachmentBlendOp = { - disabled = { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; - alpha_blend = { - blendEnable = true; - srcColorBlendFactor = one; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = one; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; +}; +setLayouts = { + matrix_set = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex|geometry|fragment; + }, + ); }; + output_set = { + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; +}; +pipelineLayouts = { + output_layout = { + setLayouts = (matrix_set, output_set); + }; + waterwarp_layout = { + @inherit = $properties.pipelineLayouts.output_layout; + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "4"; + } + ); + }; + fisheye_layout = { + @inherit = $properties.pipelineLayouts.output_layout; + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "2 * 4"; + } + ); + }; +}; - fstriangle = { - vertexStage = { - stage = vertex; - name = main; - module = $builtin/fstriangle.vert; - }; - vertexStageST = { - stage = vertex; - name = main; - module = $builtin/fstrianglest.vert; - }; - vertexInput = { - bindings = (); - attributes = (); - }; - inputAssembly = { - topology = triangle_list; - primitiveRestartEnable = false; - }; +depthStencil = { + disable = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; +}; + +inputAssembly = { +}; + +vertexInput = { + index_only = { + bindings = (); + attributes = (); + }; +}; + +rasterization = { + cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + counter_cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; +}; + +multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; +}; + +viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); +}; + +attachmentBlendOp = { + disabled = { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + alpha_blend = { + blendEnable = true; + srcColorBlendFactor = one; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = one; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; +}; + +fstriangle = { + vertexStage = { + stage = vertex; + name = main; + module = $builtin/fstriangle.vert; + }; + vertexStageST = { + stage = vertex; + name = main; + module = $builtin/fstrianglest.vert; + }; + vertexInput = { + bindings = (); + attributes = (); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.disabled); + }; +}; + +pipelines = { + base = { + viewport = $properties.viewport; + rasterization = $properties.rasterization.counter_cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.disable; colorBlend = { logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.disabled); + attachments = ( + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + ); }; + dynamic = { + dynamicState = ( viewport, scissor ); + }; + renderPass = output; }; - - pipelines = { - base = { - viewport = $properties.viewport; - rasterization = $properties.rasterization.counter_cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.disable; - colorBlend = { - logicOpEnable = false; - attachments = ( - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - ); - }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - renderPass = output; - }; - output_base = { - @inherit = $properties.pipelines.base; - vertexInput = $properties.fstriangle.vertexInput; - inputAssembly = $properties.fstriangle.inputAssembly; - colorBlend = $properties.fstriangle.colorBlend; - }; - output = { - @inherit = $properties.pipelines.output_base; - subpass = 0; - stages = ( - $properties.fstriangle.vertexStage, - { - stage = fragment; - name = main; - module = $builtin/output.frag; - }, - ); - layout = output_layout; - }; - waterwarp = { - @inherit = $properties.pipelines.output_base; - subpass = 0; - stages = ( - $properties.fstriangle.vertexStageST, - { - stage = fragment; - name = main; - module = $builtin/waterwarp.frag; - }, - ); - layout = waterwarp_layout; - }; - fisheye = { - @inherit = $properties.pipelines.output_base; - subpass = 0; - stages = ( - $properties.fstriangle.vertexStageST, - { - stage = fragment; - name = main; - module = $builtin/fisheye.frag; - }, - ); - layout = fisheye_layout; - }; + output_base = { + @inherit = $properties.pipelines.base; + vertexInput = $properties.fstriangle.vertexInput; + inputAssembly = $properties.fstriangle.inputAssembly; + colorBlend = $properties.fstriangle.colorBlend; }; -} + output = { + @inherit = $properties.pipelines.output_base; + subpass = 0; + stages = ( + $properties.fstriangle.vertexStage, + { + stage = fragment; + name = main; + module = $builtin/output.frag; + }, + ); + layout = output_layout; + }; + waterwarp = { + @inherit = $properties.pipelines.output_base; + subpass = 0; + stages = ( + $properties.fstriangle.vertexStageST, + { + stage = fragment; + name = main; + module = $builtin/waterwarp.frag; + }, + ); + layout = waterwarp_layout; + }; + fisheye = { + @inherit = $properties.pipelines.output_base; + subpass = 0; + stages = ( + $properties.fstriangle.vertexStageST, + { + stage = fragment; + name = main; + module = $builtin/fisheye.frag; + }, + ); + layout = fisheye_layout; + }; +}; diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index ec70028ac..72a104744 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -1,1213 +1,1211 @@ -{ - limits = { - //FIXME this really needs to be an external variable as the C code - //needs to agree on the size, so it might as well set maxSamplers - //directly (and any other such variable) - maxSamplers = "min (256u, $physDevLimits.maxPerStageDescriptorSamplers)"; +limits = { + //FIXME this really needs to be an external variable as the C code + //needs to agree on the size, so it might as well set maxSamplers + //directly (and any other such variable) + maxSamplers = "min (256u, $physDevLimits.maxPerStageDescriptorSamplers)"; +}; +samplers = { + quakepic = { + magFilter = nearest; + minFilter = nearest; + mipmapMode = nearest; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 0; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; }; - samplers = { - quakepic = { - magFilter = nearest; - minFilter = nearest; - mipmapMode = nearest; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 0; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - glyph = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 0; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - palette_sampler = { - magFilter = nearest; - minFilter = nearest; - mipmapMode = nearest; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 4; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - quakebsp_sampler = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = repeat; - addressModeV = repeat; - addressModeW = repeat; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 4; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - alias_sampler = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 1000; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - sprite_sampler = $properties.samplers.alias_sampler; - shadow_sampler = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = true; - compareOp = greater_or_equal; - minLod = 0; - maxLod = 1000; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; + glyph = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 0; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; }; - descriptorPools = { - matrix_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = uniform_buffer; - descriptorCount = $frames.size; - }, - ); - }; - quad_pool = { - maxSets = 64; - bindings = ( - { - // quad geometry data (offset and uv) - type = uniform_texel_buffer; - descriptorCount = 64; - }, - { - // quad texture data - type = combined_image_sampler; - descriptorCount = 64; - }, - ); - }; - entity_pool = { - flags = free_descriptor_set; - maxSets = 512; - bindings = ( - { - type = storage_buffer; - descriptorCount = $properties.descriptorPools.entity_pool.maxSets; - }, - ); - }; - bone_pool = { - flags = free_descriptor_set; - maxSets = 512; - bindings = ( - { - type = storage_buffer; - descriptorCount = $properties.descriptorPools.bone_pool.maxSets; - }, - ); - }; - texture_pool = { - flags = free_descriptor_set; - maxSets = 1024; - bindings = ( - { - type = combined_image_sampler; - descriptorCount = $properties.descriptorPools.texture_pool.maxSets; - }, - ); - }; - particle_pool = { - flags = 0; - maxSets = "3z * $frames.size"; - bindings = ( - { - type = storage_buffer; - descriptorCount = "3z * 3z * $frames.size"; - }, - ); - }; - sprite_pool = { - flags = free_descriptor_set; - maxSets = 64; //FIXME cvar? - bindings = ( - { - type = uniform_buffer; - descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; - }, - { - type = combined_image_sampler; - descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; - }, - ); - }; - //FIXME probably should just share a larger pool - alias_pool = $properties.descriptorPools.texture_pool; - quakebsp_pool = $properties.descriptorPools.texture_pool; - lighting_attach_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = input_attachment; - descriptorCount = "5z * $frames.size"; - }, - ); - }; - lighting_lights_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = uniform_buffer; - descriptorCount = $frames.size; - }, - ); - }; - lighting_shadow_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = combined_image_sampler; - descriptorCount = "$frames.size * size_t(32)"; - }, - ); - }; - oit_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = storage_buffer; - descriptorCount = "2z * $frames.size"; - }, - { - type = storage_image; - descriptorCount = "1z * $frames.size"; - }, - ); - }; - compose_attach_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = input_attachment; - descriptorCount = "2z * $frames.size"; - }, - ); - }; + palette_sampler = { + magFilter = nearest; + minFilter = nearest; + mipmapMode = nearest; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 4; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; }; - setLayouts = { - matrix_set = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = vertex|geometry; - }, - ); - }; - quad_data_set = { - bindings = ( - { - // glyph texture data - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - // glyph geometry data (offset and uv) - binding = 1; - descriptorType = uniform_texel_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, - ); - }; - texture_set = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment|vertex; - }, - ); - }; - oit_set = { - bindings = ( - { - binding = 0; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 1; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 2; - descriptorType = storage_image; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - entity_set = { - bindings = ( - { - binding = 0; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, - ); - }; - bone_set = { - bindings = ( - { - binding = 0; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, - ); - }; - sprite_set = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, - { - binding = 1; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - lighting_attach = { - bindings = ( - { - binding = 0; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 1; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 2; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 3; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 4; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - lighting_lights = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - lighting_shadow = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 32; - stageFlags = fragment; - }, - ); - }; - compose_attach = { - bindings = ( - { - binding = 0; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - particle_set = { - bindings = ( - { - binding = 0; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = compute; - }, - { - binding = 1; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = compute; - }, - { - binding = 2; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = compute; - }, - ); - }; + quakebsp_sampler = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = repeat; + addressModeV = repeat; + addressModeW = repeat; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 4; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; }; - pipelineLayouts = { - quad_layout = { - setLayouts = (matrix_set, quad_data_set); - }; - lines_layout = { - setLayouts = (matrix_set); - }; - quakebsp_layout = { - setLayouts = (matrix_set, entity_set, oit_set, texture_set, texture_set); - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "4 * 4 + 4 + 4 + 4"; - }, - ); - }; - alias_layout = { - setLayouts = (matrix_set, texture_set, texture_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 68; - size = "3 * 4 + 2 * 4 * 4"; - }, - ); - }; - iqm_layout = { - setLayouts = (matrix_set, texture_set, bone_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 68; - size = "3 * 4 + 2 * 4 * 4 + 4"; - }, - ); - }; - sprite_layout = { - setLayouts = (matrix_set, sprite_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 64; - size = "2 * 4 + 2 * 4 + 4 * 4"; - }, - ); - }; - lighting_layout = { - setLayouts = (lighting_attach, lighting_lights, lighting_shadow); - }; - compose_layout = { - setLayouts = (compose_attach, oit_set); - }; - partphysics_layout = { - setLayouts = (particle_set); - pushConstantRanges = ( - { - stageFlags = compute; - offset = 0; - size = "4 * 4 + 4"; - }, - ); - }; - partupdate_layout = { - setLayouts = (particle_set, particle_set, particle_set); - }; - partdraw_layout = { - setLayouts = (matrix_set, texture_set, oit_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4"; - }, - ); - }; + alias_sampler = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 1000; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; }; - - depthStencil = { - test_and_write = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - test_only = { - depthTestEnable = true; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - disable = { - depthTestEnable = false; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; + sprite_sampler = $properties.samplers.alias_sampler; + shadow_sampler = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = true; + compareOp = greater_or_equal; + minLod = 0; + maxLod = 1000; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; }; - - inputAssembly = { - alias = { - topology = triangle_list; - primitiveRestartEnable = false; - }; - brush = { - topology = triangle_fan; - primitiveRestartEnable = true; - }; - iqm = { - topology = triangle_list; - primitiveRestartEnable = false; - }; - lines = { - topology = line_list; - primitiveRestartEnable = false; - }; - sprite = { - topology = triangle_strip; - primitiveRestartEnable = true; - }; - point = { - topology = point_list; - primitiveRestartEnable = false; - }; - }; - - vertexInput = { - index_only = { - bindings = (); - attributes = (); - }; - alias = { - bindings = ( - { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, - { binding = 1; stride = "2 * 4 * 4"; inputRate = vertex; }, - { binding = 2; stride = "2 * 4"; inputRate = vertex; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, - { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 2; binding = 1; format = r32g32b32a32_sfloat; offset = 0; }, - { location = 3; binding = 1; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 4; binding = 2; format = r32g32_sfloat; offset = 0; }, - ); - }; - brush = { - bindings = ( - { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, - { binding = 1; stride = "4"; inputRate = instance; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, - { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 2; binding = 1; format = r32_uint; offset = 0; }, - ); - }; - slice = { - bindings = ( - { binding = 0; stride = "4 + 4 + 4 * 4"; inputRate = instance; }, - ); - attributes = ( - // 9-slice index - { location = 0; binding = 0; format = r32_uint; offset = 0; }, - // 9-slice color - { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, - // 9-slice position (2d) - { location = 2; binding = 0; format = r32g32_sfloat; offset = 8; }, - // 9-slice size delta (2d) - { location = 3; binding = 0; format = r32g32_sfloat; offset = 16; }, - ); - }; - glyph = { - bindings = ( - { binding = 0; stride = "4 + 4 + 2 * 4"; inputRate = instance; }, - ); - attributes = ( - // glyph index - { location = 0; binding = 0; format = r32_uint; offset = 0; }, - // glyph color - { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, - // glyph position (2d) - { location = 2; binding = 0; format = r32g32_sfloat; offset = 8; }, - ); - }; - iqm = { - bindings = ( - { binding = 0; stride = 20; inputRate = vertex; }, - { binding = 1; stride = 40; inputRate = vertex; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position - { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 12; }, // bonindices - { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 16; }, // boneweights - - { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord - { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal - { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent - { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color - - ); - }; - particle = { - bindings = ( - { binding = 0; stride = "4 * 4 * 4"; inputRate = instance; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, - { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 32; }, - { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 48; }, - ); - }; - lines = { - bindings = ( - { binding = 0; stride = "2 * 4 + 4"; inputRate = vertex; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32_sfloat; offset = 0; }, - { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 8; }, - ); - }; - }; - - rasterization = { - cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - counter_cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - }; - - multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; - }; - - viewport = { - viewports = ( +}; +descriptorPools = { + matrix_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; + type = uniform_buffer; + descriptorCount = $frames.size; }, ); }; - - attachmentBlendOp = { - disabled = { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; - alpha_blend = { - blendEnable = true; - srcColorBlendFactor = one; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = one; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; + quad_pool = { + maxSets = 64; + bindings = ( + { + // quad geometry data (offset and uv) + type = uniform_texel_buffer; + descriptorCount = 64; + }, + { + // quad texture data + type = combined_image_sampler; + descriptorCount = 64; + }, + ); }; + entity_pool = { + flags = free_descriptor_set; + maxSets = 512; + bindings = ( + { + type = storage_buffer; + descriptorCount = $properties.descriptorPools.entity_pool.maxSets; + }, + ); + }; + bone_pool = { + flags = free_descriptor_set; + maxSets = 512; + bindings = ( + { + type = storage_buffer; + descriptorCount = $properties.descriptorPools.bone_pool.maxSets; + }, + ); + }; + texture_pool = { + flags = free_descriptor_set; + maxSets = 1024; + bindings = ( + { + type = combined_image_sampler; + descriptorCount = $properties.descriptorPools.texture_pool.maxSets; + }, + ); + }; + particle_pool = { + flags = 0; + maxSets = "3z * $frames.size"; + bindings = ( + { + type = storage_buffer; + descriptorCount = "3z * 3z * $frames.size"; + }, + ); + }; + sprite_pool = { + flags = free_descriptor_set; + maxSets = 64; //FIXME cvar? + bindings = ( + { + type = uniform_buffer; + descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; + }, + { + type = combined_image_sampler; + descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; + }, + ); + }; + //FIXME probably should just share a larger pool + alias_pool = $properties.descriptorPools.texture_pool; + quakebsp_pool = $properties.descriptorPools.texture_pool; + lighting_attach_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = input_attachment; + descriptorCount = "5z * $frames.size"; + }, + ); + }; + lighting_lights_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = uniform_buffer; + descriptorCount = $frames.size; + }, + ); + }; + lighting_shadow_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = combined_image_sampler; + descriptorCount = "$frames.size * size_t(32)"; + }, + ); + }; + oit_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = storage_buffer; + descriptorCount = "2z * $frames.size"; + }, + { + type = storage_image; + descriptorCount = "1z * $frames.size"; + }, + ); + }; + compose_attach_pool = { + flags = 0; + maxSets = $frames.size; + bindings = ( + { + type = input_attachment; + descriptorCount = "2z * $frames.size"; + }, + ); + }; +}; +setLayouts = { + matrix_set = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex|geometry; + }, + ); + }; + quad_data_set = { + bindings = ( + { + // glyph texture data + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + { + // glyph geometry data (offset and uv) + binding = 1; + descriptorType = uniform_texel_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; + texture_set = { + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment|vertex; + }, + ); + }; + oit_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 1; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = storage_image; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + entity_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; + bone_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + ); + }; + sprite_set = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = vertex; + }, + { + binding = 1; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + lighting_attach = { + bindings = ( + { + binding = 0; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 1; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 2; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 3; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + { + binding = 4; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + lighting_lights = { + bindings = ( + { + binding = 0; + descriptorType = uniform_buffer; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + lighting_shadow = { + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 32; + stageFlags = fragment; + }, + ); + }; + compose_attach = { + bindings = ( + { + binding = 0; + descriptorType = input_attachment; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; + particle_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 1; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 2; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + ); + }; +}; +pipelineLayouts = { + quad_layout = { + setLayouts = (matrix_set, quad_data_set); + }; + lines_layout = { + setLayouts = (matrix_set); + }; + quakebsp_layout = { + setLayouts = (matrix_set, entity_set, oit_set, texture_set, texture_set); + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "4 * 4 + 4 + 4 + 4"; + }, + ); + }; + alias_layout = { + setLayouts = (matrix_set, texture_set, texture_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "3 * 4 + 2 * 4 * 4"; + }, + ); + }; + iqm_layout = { + setLayouts = (matrix_set, texture_set, bone_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 68; + size = "3 * 4 + 2 * 4 * 4 + 4"; + }, + ); + }; + sprite_layout = { + setLayouts = (matrix_set, sprite_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4 + 4"; + }, + { + stageFlags = fragment; + offset = 64; + size = "2 * 4 + 2 * 4 + 4 * 4"; + }, + ); + }; + lighting_layout = { + setLayouts = (lighting_attach, lighting_lights, lighting_shadow); + }; + compose_layout = { + setLayouts = (compose_attach, oit_set); + }; + partphysics_layout = { + setLayouts = (particle_set); + pushConstantRanges = ( + { + stageFlags = compute; + offset = 0; + size = "4 * 4 + 4"; + }, + ); + }; + partupdate_layout = { + setLayouts = (particle_set, particle_set, particle_set); + }; + partdraw_layout = { + setLayouts = (matrix_set, texture_set, oit_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4"; + }, + ); + }; +}; - fstriangle = { - vertexStage = { - stage = vertex; - name = main; - module = $builtin/fstriangle.vert; +depthStencil = { + test_and_write = { + depthTestEnable = true; + depthWriteEnable = true; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + test_only = { + depthTestEnable = true; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; + disable = { + depthTestEnable = false; + depthWriteEnable = false; + depthCompareOp = less_or_equal; + depthBoundsTestEnable = false; + stencilTestEnable = false; + }; +}; + +inputAssembly = { + alias = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + brush = { + topology = triangle_fan; + primitiveRestartEnable = true; + }; + iqm = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + lines = { + topology = line_list; + primitiveRestartEnable = false; + }; + sprite = { + topology = triangle_strip; + primitiveRestartEnable = true; + }; + point = { + topology = point_list; + primitiveRestartEnable = false; + }; +}; + +vertexInput = { + index_only = { + bindings = (); + attributes = (); + }; + alias = { + bindings = ( + { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 1; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 2; stride = "2 * 4"; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 1; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 3; binding = 1; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 4; binding = 2; format = r32g32_sfloat; offset = 0; }, + ); + }; + brush = { + bindings = ( + { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, + { binding = 1; stride = "4"; inputRate = instance; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 1; format = r32_uint; offset = 0; }, + ); + }; + slice = { + bindings = ( + { binding = 0; stride = "4 + 4 + 4 * 4"; inputRate = instance; }, + ); + attributes = ( + // 9-slice index + { location = 0; binding = 0; format = r32_uint; offset = 0; }, + // 9-slice color + { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, + // 9-slice position (2d) + { location = 2; binding = 0; format = r32g32_sfloat; offset = 8; }, + // 9-slice size delta (2d) + { location = 3; binding = 0; format = r32g32_sfloat; offset = 16; }, + ); + }; + glyph = { + bindings = ( + { binding = 0; stride = "4 + 4 + 2 * 4"; inputRate = instance; }, + ); + attributes = ( + // glyph index + { location = 0; binding = 0; format = r32_uint; offset = 0; }, + // glyph color + { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, + // glyph position (2d) + { location = 2; binding = 0; format = r32g32_sfloat; offset = 8; }, + ); + }; + iqm = { + bindings = ( + { binding = 0; stride = 20; inputRate = vertex; }, + { binding = 1; stride = 40; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position + { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 12; }, // bonindices + { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 16; }, // boneweights + + { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord + { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal + { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent + { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color + + ); + }; + particle = { + bindings = ( + { binding = 0; stride = "4 * 4 * 4"; inputRate = instance; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, + { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 32; }, + { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 48; }, + ); + }; + lines = { + bindings = ( + { binding = 0; stride = "2 * 4 + 4"; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 8; }, + ); + }; +}; + +rasterization = { + cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; + counter_cw_cull_back = { + depthClampEnable = false; + rasterizerDiscardEnable = false; + polygonMode = fill; + cullMode = back; + frontFace = counter_clockwise; + depthBiasEnable = false; + lineWidth = 1; + }; +}; + +multisample = { + rasterizationSamples = $msaaSamples; + sampleShadingEnable = false; + minSampleShading = 0.5f; + alphaToCoverageEnable = false; + alphaToOneEnable = false; +}; + +viewport = { + viewports = ( + { + x = 0; y = 0; + width = 640; height = 480; + minDepth = 0; maxDepth = 1; + } + ); + scissors = ( + { + offset = { x = 0; y = 0 }; + extent = { width = 640; height = 480; }; + }, + ); +}; + +attachmentBlendOp = { + disabled = { + blendEnable = false; + srcColorBlendFactor = src_alpha; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = src_alpha; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; + alpha_blend = { + blendEnable = true; + srcColorBlendFactor = one; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = one; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; +}; + +fstriangle = { + vertexStage = { + stage = vertex; + name = main; + module = $builtin/fstriangle.vert; + }; + vertexInput = { + bindings = (); + attributes = (); + }; + inputAssembly = { + topology = triangle_list; + primitiveRestartEnable = false; + }; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.disabled); + }; +}; + +pipelines = { + base = { + viewport = $properties.viewport; + rasterization = $properties.rasterization.counter_cw_cull_back; + multisample = $properties.multisample; + depthStencil = $properties.depthStencil.disable; + colorBlend = { + logicOpEnable = false; + attachments = ( + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + $properties.attachmentBlendOp.disabled, + ); }; - vertexInput = { - bindings = (); - attributes = (); - }; - inputAssembly = { - topology = triangle_list; - primitiveRestartEnable = false; + dynamic = { + dynamicState = ( viewport, scissor ); }; + renderPass = deferred; + }; + depth_base = { + @inherit = $properties.pipelines.base; + subpass = 0; + rasterization = $properties.rasterization.cw_cull_back; + depthStencil = $properties.depthStencil.test_and_write; + }; + trans_base = { + @inherit = $properties.pipelines.base; + subpass = 1; + rasterization = $properties.rasterization.cw_cull_back; + depthStencil = $properties.depthStencil.test_only; colorBlend = { logicOpEnable = false; attachments = ($properties.attachmentBlendOp.disabled); }; }; - - pipelines = { - base = { - viewport = $properties.viewport; - rasterization = $properties.rasterization.counter_cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.disable; - colorBlend = { - logicOpEnable = false; - attachments = ( - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - ); - }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - renderPass = deferred; - }; - depth_base = { - @inherit = $properties.pipelines.base; - subpass = 0; - rasterization = $properties.rasterization.cw_cull_back; - depthStencil = $properties.depthStencil.test_and_write; - }; - trans_base = { - @inherit = $properties.pipelines.base; - subpass = 1; - rasterization = $properties.rasterization.cw_cull_back; - depthStencil = $properties.depthStencil.test_only; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.disabled); - }; - }; - gbuf_base = { - @inherit = $properties.pipelines.base; - subpass = 2; - rasterization = $properties.rasterization.cw_cull_back; - depthStencil = $properties.depthStencil.test_only; - }; - comp_base = { - @inherit = $properties.pipelines.base; - vertexInput = $properties.fstriangle.vertexInput; - inputAssembly = $properties.fstriangle.inputAssembly; - colorBlend = $properties.fstriangle.colorBlend; - }; - shadow_base = { - @inherit = $properties.pipelines.depth_base; - renderPass = shadow; - }; - - alias_shadow = { - @inherit = $properties.pipelines.shadow_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/alias_shadow.vert; - }, - ); - vertexInput = { - bindings = ( - "$properties.vertexInput.alias.bindings[0]", - "$properties.vertexInput.alias.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.alias.attributes[0]", - "$properties.vertexInput.alias.attributes[1]", - "$properties.vertexInput.alias.attributes[2]", - "$properties.vertexInput.alias.attributes[3]", - ); - }; - inputAssembly = $properties.inputAssembly.alias; - layout = alias_layout; - }; - bsp_shadow = { - @inherit = $properties.pipelines.shadow_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/bsp_shadow.vert; - }, - ); - vertexInput = { - bindings = ( - "$properties.vertexInput.brush.bindings[0]", - ); - attributes = ( - "$properties.vertexInput.brush.attributes[0]", - ); - }; - inputAssembly = $properties.inputAssembly.brush; - }; - alias_depth = { - @inherit = $properties.pipelines.depth_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/alias_depth.vert; - }, - ); - vertexInput = { - // depth pass doesn't use UVs - bindings = ( - "$properties.vertexInput.alias.bindings[0]", - "$properties.vertexInput.alias.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.alias.attributes[0]", - "$properties.vertexInput.alias.attributes[1]", - "$properties.vertexInput.alias.attributes[2]", - "$properties.vertexInput.alias.attributes[3]", - ); - }; - inputAssembly = $properties.inputAssembly.alias; - layout = alias_layout; - }; - alias_gbuf = { - @inherit = $properties.pipelines.gbuf_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/alias.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/alias_gbuf.frag; - }, - ); - vertexInput = $properties.vertexInput.alias; - inputAssembly = $properties.inputAssembly.alias; - layout = alias_layout; - }; - bsp_depth = { - @inherit = $properties.pipelines.depth_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/bsp_depth.vert; - }, - ); - vertexInput = { - bindings = ( - "$properties.vertexInput.brush.bindings[0]", - "$properties.vertexInput.brush.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.brush.attributes[0]", - "$properties.vertexInput.brush.attributes[2]", - ); - }; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - bsp_gbuf = { - @inherit = $properties.pipelines.gbuf_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/bsp_gbuf.vert; - }, - { - stage = geometry; - name = main; - module = $builtin/bsp_gbuf.geom; - }, - { - stage = fragment; - name = main; - module = $builtin/bsp_gbuf.frag; - }, - ); - vertexInput = $properties.vertexInput.brush; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - bsp_skybox = { - @inherit = $properties.pipelines.trans_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/quakebsp.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/bsp_sky.frag; - specializationInfo = { - mapEntries = ( - // doSkyBox - { size = 4; offset = 0; constantID = 0; }, - // doSkySheet - { size = 4; offset = 4; constantID = 1; }, - ); - data = "array(1, 0)"; - }; - }, - ); - vertexInput = $properties.vertexInput.brush; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - bsp_skysheet = { - @inherit = $properties.pipelines.trans_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/quakebsp.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/bsp_sky.frag; - specializationInfo = { - mapEntries = ( - // doSkyBox - { size = 4; offset = 0; constantID = 0; }, - // doSkySheet - { size = 4; offset = 4; constantID = 1; }, - ); - data = "array(0, 1)"; - }; - }, - ); - vertexInput = $properties.vertexInput.brush; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - bsp_turb = { - @inherit = $properties.pipelines.trans_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/quakebsp.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/bsp_turb.frag; - }, - ); - vertexInput = $properties.vertexInput.brush; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - iqm_depth = { - @inherit = $properties.pipelines.depth_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm.vert; - specializationInfo = { - mapEntries = ( - // IQMDepthOnly - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(1)"; - }; - }, - ); - vertexInput = $properties.vertexInput.iqm; - inputAssembly = $properties.inputAssembly.iqm; - layout = iqm_layout; - }; - iqm_gbuf = { - @inherit = $properties.pipelines.gbuf_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm.vert; - specializationInfo = { - mapEntries = ( - // !IQMDepthOnly - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(0)"; - }; - }, - { - stage = fragment; - name = main; - module = $builtin/iqm.frag; - }, - ); - vertexInput = $properties.vertexInput.iqm; - inputAssembly = $properties.inputAssembly.iqm; - layout = iqm_layout; - }; - partdraw = { - @inherit = $properties.pipelines.trans_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/particle.vert; - }, - { - stage = geometry; - name = main; - module = $builtin/particle.geom; - }, - { - stage = fragment; - name = main; - module = $builtin/particle.frag; - }, - ); - vertexInput = $properties.vertexInput.particle; - inputAssembly = $properties.inputAssembly.point; - layout = partdraw_layout; - }; - sprite_gbuf = { - @inherit = $properties.pipelines.gbuf_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/sprite_gbuf.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/sprite_gbuf.frag; - }, - ); - vertexInput = $properties.vertexInput.index_only; - inputAssembly = $properties.inputAssembly.sprite; - layout = sprite_layout; - }; - sprite_depth = { - @inherit = $properties.pipelines.depth_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/sprite_depth.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/sprite_depth.frag; - }, - ); - vertexInput = $properties.vertexInput.index_only; - inputAssembly = $properties.inputAssembly.sprite; - layout = sprite_layout; - }; - slice = { - @inherit = $properties.pipelines.trans_base; - renderPass = output; - subpass = 0; - stages = ( - { stage = vertex; name = main; module = $builtin/slice.vert; }, - { stage = fragment; name = main; module = $builtin/twod.frag; }, - ); - vertexInput = $properties.vertexInput.slice; - inputAssembly = { - // slices are drawn using instanced slice triples - topology = triangle_strip; - primitiveRestartEnable = true; - }; - rasterization = $properties.rasterization.counter_cw_cull_back; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.alpha_blend); - }; - layout = quad_layout; - }; - lines = { - @inherit = $properties.pipelines.trans_base; - renderPass = output; - subpass = 0; - stages = ( - { stage = vertex; name = main; module = $builtin/line.vert; }, - { stage = fragment; name = main; module = $builtin/line.frag; }, - ); - vertexInput = $properties.vertexInput.lines; - rasterization = $properties.rasterization.counter_cw_cull_back; - depthStencil = $properties.depthStencil.disable; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.alpha_blend); - }; - inputAssembly = $properties.inputAssembly.lines; - layout = lines_layout; - }; - lighting = { - @inherit = $properties.pipelines.comp_base; - subpass = 3; - stages = ( - $properties.fstriangle.vertexStage, - { - stage = fragment; - name = main; - module = $builtin/lighting.frag; - //specializationInfo = { - // mapEntries = ( - // { size = 4; offset = 0; constantID = 0; }, - // ); - // data = "array(uint($properties.limits.maxSamplers))"; - //}; - }, - ); - layout = lighting_layout; - }; - compose = { - @inherit = $properties.pipelines.comp_base; - subpass = 4; - stages = ( - $properties.fstriangle.vertexStage, - { - stage = fragment; - name = main; - module = $builtin/compose.frag; - }, - ); - layout = compose_layout; - }; - - partphysics = { - stage = { - stage = compute; - name = main; - module = $builtin/partphysics.comp; - }; - layout = partphysics_layout; - }; - partupdate = { - stage = { - stage = compute; - name = main; - module = $builtin/partupdate.comp; - }; - layout = partupdate_layout; - }; + gbuf_base = { + @inherit = $properties.pipelines.base; + subpass = 2; + rasterization = $properties.rasterization.cw_cull_back; + depthStencil = $properties.depthStencil.test_only; }; -} + comp_base = { + @inherit = $properties.pipelines.base; + vertexInput = $properties.fstriangle.vertexInput; + inputAssembly = $properties.fstriangle.inputAssembly; + colorBlend = $properties.fstriangle.colorBlend; + }; + shadow_base = { + @inherit = $properties.pipelines.depth_base; + renderPass = shadow; + }; + + alias_shadow = { + @inherit = $properties.pipelines.shadow_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/alias_shadow.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.vertexInput.alias.bindings[0]", + "$properties.vertexInput.alias.bindings[1]", + ); + attributes = ( + "$properties.vertexInput.alias.attributes[0]", + "$properties.vertexInput.alias.attributes[1]", + "$properties.vertexInput.alias.attributes[2]", + "$properties.vertexInput.alias.attributes[3]", + ); + }; + inputAssembly = $properties.inputAssembly.alias; + layout = alias_layout; + }; + bsp_shadow = { + @inherit = $properties.pipelines.shadow_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/bsp_shadow.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.vertexInput.brush.bindings[0]", + ); + attributes = ( + "$properties.vertexInput.brush.attributes[0]", + ); + }; + inputAssembly = $properties.inputAssembly.brush; + }; + alias_depth = { + @inherit = $properties.pipelines.depth_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/alias_depth.vert; + }, + ); + vertexInput = { + // depth pass doesn't use UVs + bindings = ( + "$properties.vertexInput.alias.bindings[0]", + "$properties.vertexInput.alias.bindings[1]", + ); + attributes = ( + "$properties.vertexInput.alias.attributes[0]", + "$properties.vertexInput.alias.attributes[1]", + "$properties.vertexInput.alias.attributes[2]", + "$properties.vertexInput.alias.attributes[3]", + ); + }; + inputAssembly = $properties.inputAssembly.alias; + layout = alias_layout; + }; + alias_gbuf = { + @inherit = $properties.pipelines.gbuf_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/alias.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/alias_gbuf.frag; + }, + ); + vertexInput = $properties.vertexInput.alias; + inputAssembly = $properties.inputAssembly.alias; + layout = alias_layout; + }; + bsp_depth = { + @inherit = $properties.pipelines.depth_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/bsp_depth.vert; + }, + ); + vertexInput = { + bindings = ( + "$properties.vertexInput.brush.bindings[0]", + "$properties.vertexInput.brush.bindings[1]", + ); + attributes = ( + "$properties.vertexInput.brush.attributes[0]", + "$properties.vertexInput.brush.attributes[2]", + ); + }; + inputAssembly = $properties.inputAssembly.brush; + layout = quakebsp_layout; + }; + bsp_gbuf = { + @inherit = $properties.pipelines.gbuf_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/bsp_gbuf.vert; + }, + { + stage = geometry; + name = main; + module = $builtin/bsp_gbuf.geom; + }, + { + stage = fragment; + name = main; + module = $builtin/bsp_gbuf.frag; + }, + ); + vertexInput = $properties.vertexInput.brush; + inputAssembly = $properties.inputAssembly.brush; + layout = quakebsp_layout; + }; + bsp_skybox = { + @inherit = $properties.pipelines.trans_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/bsp_sky.frag; + specializationInfo = { + mapEntries = ( + // doSkyBox + { size = 4; offset = 0; constantID = 0; }, + // doSkySheet + { size = 4; offset = 4; constantID = 1; }, + ); + data = "array(1, 0)"; + }; + }, + ); + vertexInput = $properties.vertexInput.brush; + inputAssembly = $properties.inputAssembly.brush; + layout = quakebsp_layout; + }; + bsp_skysheet = { + @inherit = $properties.pipelines.trans_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/bsp_sky.frag; + specializationInfo = { + mapEntries = ( + // doSkyBox + { size = 4; offset = 0; constantID = 0; }, + // doSkySheet + { size = 4; offset = 4; constantID = 1; }, + ); + data = "array(0, 1)"; + }; + }, + ); + vertexInput = $properties.vertexInput.brush; + inputAssembly = $properties.inputAssembly.brush; + layout = quakebsp_layout; + }; + bsp_turb = { + @inherit = $properties.pipelines.trans_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/quakebsp.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/bsp_turb.frag; + }, + ); + vertexInput = $properties.vertexInput.brush; + inputAssembly = $properties.inputAssembly.brush; + layout = quakebsp_layout; + }; + iqm_depth = { + @inherit = $properties.pipelines.depth_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + mapEntries = ( + // IQMDepthOnly + { size = 4; offset = 0; constantID = 0; }, + ); + data = "array(1)"; + }; + }, + ); + vertexInput = $properties.vertexInput.iqm; + inputAssembly = $properties.inputAssembly.iqm; + layout = iqm_layout; + }; + iqm_gbuf = { + @inherit = $properties.pipelines.gbuf_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/iqm.vert; + specializationInfo = { + mapEntries = ( + // !IQMDepthOnly + { size = 4; offset = 0; constantID = 0; }, + ); + data = "array(0)"; + }; + }, + { + stage = fragment; + name = main; + module = $builtin/iqm.frag; + }, + ); + vertexInput = $properties.vertexInput.iqm; + inputAssembly = $properties.inputAssembly.iqm; + layout = iqm_layout; + }; + partdraw = { + @inherit = $properties.pipelines.trans_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/particle.vert; + }, + { + stage = geometry; + name = main; + module = $builtin/particle.geom; + }, + { + stage = fragment; + name = main; + module = $builtin/particle.frag; + }, + ); + vertexInput = $properties.vertexInput.particle; + inputAssembly = $properties.inputAssembly.point; + layout = partdraw_layout; + }; + sprite_gbuf = { + @inherit = $properties.pipelines.gbuf_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/sprite_gbuf.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/sprite_gbuf.frag; + }, + ); + vertexInput = $properties.vertexInput.index_only; + inputAssembly = $properties.inputAssembly.sprite; + layout = sprite_layout; + }; + sprite_depth = { + @inherit = $properties.pipelines.depth_base; + stages = ( + { + stage = vertex; + name = main; + module = $builtin/sprite_depth.vert; + }, + { + stage = fragment; + name = main; + module = $builtin/sprite_depth.frag; + }, + ); + vertexInput = $properties.vertexInput.index_only; + inputAssembly = $properties.inputAssembly.sprite; + layout = sprite_layout; + }; + slice = { + @inherit = $properties.pipelines.trans_base; + renderPass = output; + subpass = 0; + stages = ( + { stage = vertex; name = main; module = $builtin/slice.vert; }, + { stage = fragment; name = main; module = $builtin/twod.frag; }, + ); + vertexInput = $properties.vertexInput.slice; + inputAssembly = { + // slices are drawn using instanced slice triples + topology = triangle_strip; + primitiveRestartEnable = true; + }; + rasterization = $properties.rasterization.counter_cw_cull_back; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.alpha_blend); + }; + layout = quad_layout; + }; + lines = { + @inherit = $properties.pipelines.trans_base; + renderPass = output; + subpass = 0; + stages = ( + { stage = vertex; name = main; module = $builtin/line.vert; }, + { stage = fragment; name = main; module = $builtin/line.frag; }, + ); + vertexInput = $properties.vertexInput.lines; + rasterization = $properties.rasterization.counter_cw_cull_back; + depthStencil = $properties.depthStencil.disable; + colorBlend = { + logicOpEnable = false; + attachments = ($properties.attachmentBlendOp.alpha_blend); + }; + inputAssembly = $properties.inputAssembly.lines; + layout = lines_layout; + }; + lighting = { + @inherit = $properties.pipelines.comp_base; + subpass = 3; + stages = ( + $properties.fstriangle.vertexStage, + { + stage = fragment; + name = main; + module = $builtin/lighting.frag; + //specializationInfo = { + // mapEntries = ( + // { size = 4; offset = 0; constantID = 0; }, + // ); + // data = "array(uint($properties.limits.maxSamplers))"; + //}; + }, + ); + layout = lighting_layout; + }; + compose = { + @inherit = $properties.pipelines.comp_base; + subpass = 4; + stages = ( + $properties.fstriangle.vertexStage, + { + stage = fragment; + name = main; + module = $builtin/compose.frag; + }, + ); + layout = compose_layout; + }; + + partphysics = { + stage = { + stage = compute; + name = main; + module = $builtin/partphysics.comp; + }; + layout = partphysics_layout; + }; + partupdate = { + stage = { + stage = compute; + name = main; + module = $builtin/partupdate.comp; + }; + layout = partupdate_layout; + }; +}; diff --git a/libs/video/renderer/vulkan/rp_defcube.plist b/libs/video/renderer/vulkan/rp_defcube.plist index 062f12fca..3a4cd1089 100644 --- a/libs/video/renderer/vulkan/rp_defcube.plist +++ b/libs/video/renderer/vulkan/rp_defcube.plist @@ -1,330 +1,328 @@ -{ - flat_color_image_template = { - imageType = `2d; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 6; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; - }; - images = { - depth = { - @inherit = $properties.flat_color_image_template; - format = x8_d24_unorm_pack32; - usage = depth_stencil_attachment|input_attachment|transient_attachment; - }; - color = { - @inherit = $properties.flat_color_image_template; - format = r8g8b8a8_unorm; - }; - emission = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - normal = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - position = { - @inherit = $properties.flat_color_image_template; - format = r32g32b32a32_sfloat; - }; - opaque = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - }; - flat_color_view_template = { - viewType = `2d_array; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 6; - }; - }; - imageViews = { - depth = { - @inherit = $properties.flat_color_view_template; - image = depth; - format = $properties.images.depth.format; - subresourceRange = { - aspectMask = depth; - }; - }; - color = { - @inherit = $properties.flat_color_view_template; - image = color; - format = $properties.images.color.format; - }; - emission = { - @inherit = $properties.flat_color_view_template; - image = emission; - format = $properties.images.emission.format; - }; - normal = { - @inherit = $properties.flat_color_view_template; - image = normal; - format = $properties.images.normal.format; - }; - position = { - @inherit = $properties.flat_color_view_template; - image = position; - format = $properties.images.position.format; - }; - opaque = { - @inherit = $properties.flat_color_view_template; - image = opaque; - format = $properties.images.opaque.format; - }; - aview = { - @inherit = $properties.flat_color_view_template; - image = $output.image; - format = $output.format; - }; - }; - output = { - image = { - @inherit = $properties.flat_color_image_template; - flags = cube_compatible; - usage = color_attachment|input_attachment|sampled; - format = $output.format; - }; - view = { - @inherit = $properties.flat_color_view_template; - viewType = cube; - image = $output.image; - format = $output.format; - }; - format = r16g16b16a16_sfloat; - finalLayout = shader_read_only_optimal; - }; - framebuffer = { - renderPass = defcube; - attachments = (depth, color, emission, normal, position, opaque, - $properties.imageViews.aview); +flat_color_image_template = { + imageType = `2d; + samples = 1; + extent = { width = $output.extent.width; height = $output.extent.height; - layers = 1; + depth = 1; }; - clearValues = ( - { depthStencil = { depth = 1; stencil = 0; }; }, - { color = "[0, 0, 0, 1]"; }, // color - { color = "[0, 0, 0, 1]"; }, // emission - { color = "[0, 0, 0, 1]"; }, // normal - { color = "[0, 0, 0, 1]"; }, // position - { color = "[0, 0, 0, 1]"; }, // opaque - { color = "[0, 0, 0, 1]"; }, // output + mipLevels = 1; + arrayLayers = 6; + tiling = optimal; + usage = color_attachment|input_attachment|transient_attachment; + initialLayout = undefined; +}; +images = { + depth = { + @inherit = $properties.flat_color_image_template; + format = x8_d24_unorm_pack32; + usage = depth_stencil_attachment|input_attachment|transient_attachment; + }; + color = { + @inherit = $properties.flat_color_image_template; + format = r8g8b8a8_unorm; + }; + emission = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; + normal = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; + position = { + @inherit = $properties.flat_color_image_template; + format = r32g32b32a32_sfloat; + }; + opaque = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; +}; +flat_color_view_template = { + viewType = `2d_array; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 6; + }; +}; +imageViews = { + depth = { + @inherit = $properties.flat_color_view_template; + image = depth; + format = $properties.images.depth.format; + subresourceRange = { + aspectMask = depth; + }; + }; + color = { + @inherit = $properties.flat_color_view_template; + image = color; + format = $properties.images.color.format; + }; + emission = { + @inherit = $properties.flat_color_view_template; + image = emission; + format = $properties.images.emission.format; + }; + normal = { + @inherit = $properties.flat_color_view_template; + image = normal; + format = $properties.images.normal.format; + }; + position = { + @inherit = $properties.flat_color_view_template; + image = position; + format = $properties.images.position.format; + }; + opaque = { + @inherit = $properties.flat_color_view_template; + image = opaque; + format = $properties.images.opaque.format; + }; + aview = { + @inherit = $properties.flat_color_view_template; + image = $output.image; + format = $output.format; + }; +}; +output = { + image = { + @inherit = $properties.flat_color_image_template; + flags = cube_compatible; + usage = color_attachment|input_attachment|sampled; + format = $output.format; + }; + view = { + @inherit = $properties.flat_color_view_template; + viewType = cube; + image = $output.image; + format = $output.format; + }; + format = r16g16b16a16_sfloat; + finalLayout = shader_read_only_optimal; +}; +framebuffer = { + renderPass = defcube; + attachments = (depth, color, emission, normal, position, opaque, + $properties.imageViews.aview); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; +}; +clearValues = ( + { depthStencil = { depth = 1; stencil = 0; }; }, + { color = "[0, 0, 0, 1]"; }, // color + { color = "[0, 0, 0, 1]"; }, // emission + { color = "[0, 0, 0, 1]"; }, // normal + { color = "[0, 0, 0, 1]"; }, // position + { color = "[0, 0, 0, 1]"; }, // opaque + { color = "[0, 0, 0, 1]"; }, // output +); +attachment_template = { + samples = 1; + loadOp = dont_care; + storeOp = store; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; +}; +info = { + color = "[0, 1, 0, 1]"; + subpass_info = ( + { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, + { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, + { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, + { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, + { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, ); - attachment_template = { - samples = 1; - loadOp = dont_care; - storeOp = store; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; - }; - info = { - color = "[0, 1, 0, 1]"; - subpass_info = ( - { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, - { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, - { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, - { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, - { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, - ); - }; - renderpass = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $properties.images.depth.format; - loadOp = clear; - finalLayout = depth_stencil_attachment_optimal; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.color.format; - loadOp = clear; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.emission.format; - loadOp = clear; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.normal.format; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.position.format; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.opaque.format; - }, - { - @inherit = $properties.attachment_template; - format = $output.format; - loadOp = clear; - storeOp = store; - finalLayout = $output.finalLayout; - }, - ); - subpasses = ( - { // 0 depth - pipelineBindPoint = graphics; - depthStencilAttachment = { +}; +renderpass = { + attachments = ( + { + @inherit = $properties.attachment_template; + format = $properties.images.depth.format; + loadOp = clear; + finalLayout = depth_stencil_attachment_optimal; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.color.format; + loadOp = clear; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.emission.format; + loadOp = clear; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.normal.format; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.position.format; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.opaque.format; + }, + { + @inherit = $properties.attachment_template; + format = $output.format; + loadOp = clear; + storeOp = store; + finalLayout = $output.finalLayout; + }, + ); + subpasses = ( + { // 0 depth + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_attachment_optimal; + }; + }, + { // 1 translucent-frags + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_read_only_optimal; + }; + preserveAttachments = (1, 2, 3, 4, 5); + }, + { // 2 g-buffer generation + pipelineBindPoint = graphics; + colorAttachments = ( + { // color + attachment = 1; + layout = color_attachment_optimal; + }, + { // emission + attachment = 2; + layout = color_attachment_optimal; + }, + { // normal + attachment = 3; + layout = color_attachment_optimal; + }, + { // position + attachment = 4; + layout = color_attachment_optimal; + }, + ); + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_read_only_optimal; + }; + preserveAttachments = (6); + }, + { // 3 lighting + pipelineBindPoint = graphics; + inputAttachments = ( + { // depth attachment = 0; - layout = depth_stencil_attachment_optimal; - }; - }, - { // 1 translucent-frags - pipelineBindPoint = graphics; - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_read_only_optimal; - }; - preserveAttachments = (1, 2, 3, 4, 5); - }, - { // 2 g-buffer generation - pipelineBindPoint = graphics; - colorAttachments = ( - { // color - attachment = 1; - layout = color_attachment_optimal; - }, - { // emission - attachment = 2; - layout = color_attachment_optimal; - }, - { // normal - attachment = 3; - layout = color_attachment_optimal; - }, - { // position - attachment = 4; - layout = color_attachment_optimal; - }, - ); - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_read_only_optimal; - }; - preserveAttachments = (6); - }, - { // 3 lighting - pipelineBindPoint = graphics; - inputAttachments = ( - { // depth - attachment = 0; - layout = shader_read_only_optimal; - }, - { // color - attachment = 1; - layout = shader_read_only_optimal; - }, - { // emission - attachment = 2; - layout = shader_read_only_optimal; - }, - { // normal - attachment = 3; - layout = shader_read_only_optimal; - }, - { // position - attachment = 4; - layout = shader_read_only_optimal; - }, - ); - colorAttachments = ( - { // opaque - attachment = 5; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (6); - }, - { // 4 compose - pipelineBindPoint = graphics; - inputAttachments = ( - { // opaque - attachment = 5; - layout = shader_read_only_optimal; - }, - ); - colorAttachments = ( - { // output - attachment = 6; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (0, 1, 2, 3, 4); - }, - ); - dependencies = ( - { - srcSubpass = 0; // depth - dstSubpass = 1; // translucent - srcStageMask = late_fragment_tests; - dstStageMask = fragment_shader|early_fragment_tests; - srcAccessMask = depth_stencil_attachment_write; - dstAccessMask = input_attachment_read|depth_stencil_attachment_read; - dependencyFlags = by_region|view_local; - }, - { - srcSubpass = 0; // depth - dstSubpass = 2; // g-buffer - srcStageMask = late_fragment_tests; - dstStageMask = early_fragment_tests; - srcAccessMask = depth_stencil_attachment_write; - dstAccessMask = depth_stencil_attachment_read; - dependencyFlags = by_region|view_local; - }, - { - srcSubpass = 2; // g-buffer - dstSubpass = 3; // lighting - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region|view_local; - }, - { - srcSubpass = 3; // lighting - dstSubpass = 4; // compose - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region|view_local; - }, - { - srcSubpass = 1; // translucent-frags - dstSubpass = 4; // translucent-final/compose - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region|view_local; - }, - ); - @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); - viewOffsets = ( 0, 0, 0, 0, 0); - }); - }; -} + layout = shader_read_only_optimal; + }, + { // color + attachment = 1; + layout = shader_read_only_optimal; + }, + { // emission + attachment = 2; + layout = shader_read_only_optimal; + }, + { // normal + attachment = 3; + layout = shader_read_only_optimal; + }, + { // position + attachment = 4; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // opaque + attachment = 5; + layout = color_attachment_optimal; + }, + ); + preserveAttachments = (6); + }, + { // 4 compose + pipelineBindPoint = graphics; + inputAttachments = ( + { // opaque + attachment = 5; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // output + attachment = 6; + layout = color_attachment_optimal; + }, + ); + preserveAttachments = (0, 1, 2, 3, 4); + }, + ); + dependencies = ( + { + srcSubpass = 0; // depth + dstSubpass = 1; // translucent + srcStageMask = late_fragment_tests; + dstStageMask = fragment_shader|early_fragment_tests; + srcAccessMask = depth_stencil_attachment_write; + dstAccessMask = input_attachment_read|depth_stencil_attachment_read; + dependencyFlags = by_region|view_local; + }, + { + srcSubpass = 0; // depth + dstSubpass = 2; // g-buffer + srcStageMask = late_fragment_tests; + dstStageMask = early_fragment_tests; + srcAccessMask = depth_stencil_attachment_write; + dstAccessMask = depth_stencil_attachment_read; + dependencyFlags = by_region|view_local; + }, + { + srcSubpass = 2; // g-buffer + dstSubpass = 3; // lighting + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region|view_local; + }, + { + srcSubpass = 3; // lighting + dstSubpass = 4; // compose + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region|view_local; + }, + { + srcSubpass = 1; // translucent-frags + dstSubpass = 4; // translucent-final/compose + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region|view_local; + }, + ); + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); + viewOffsets = ( 0, 0, 0, 0, 0); + }); +}; diff --git a/libs/video/renderer/vulkan/rp_deferred.plist b/libs/video/renderer/vulkan/rp_deferred.plist index 13bf88cb8..9fb3845de 100644 --- a/libs/video/renderer/vulkan/rp_deferred.plist +++ b/libs/video/renderer/vulkan/rp_deferred.plist @@ -1,319 +1,317 @@ -{ - flat_color_image_template = { - imageType = `2d; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; - }; - images = { - depth = { - @inherit = $properties.flat_color_image_template; - format = x8_d24_unorm_pack32; - usage = depth_stencil_attachment|input_attachment|transient_attachment; - }; - color = { - @inherit = $properties.flat_color_image_template; - format = r8g8b8a8_unorm; - }; - emission = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - normal = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - position = { - @inherit = $properties.flat_color_image_template; - format = r32g32b32a32_sfloat; - }; - opaque = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - }; - flat_color_view_template = { - viewType = VK_IMAGE_VIEW_TYPE_2D; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; - }; - imageViews = { - depth = { - @inherit = $properties.flat_color_view_template; - image = depth; - format = $properties.images.depth.format; - subresourceRange = { - aspectMask = depth; - }; - }; - color = { - @inherit = $properties.flat_color_view_template; - image = color; - format = $properties.images.color.format; - }; - emission = { - @inherit = $properties.flat_color_view_template; - image = emission; - format = $properties.images.emission.format; - }; - normal = { - @inherit = $properties.flat_color_view_template; - image = normal; - format = $properties.images.normal.format; - }; - position = { - @inherit = $properties.flat_color_view_template; - image = position; - format = $properties.images.position.format; - }; - opaque = { - @inherit = $properties.flat_color_view_template; - image = opaque; - format = $properties.images.opaque.format; - }; - }; - output = { - image = { - @inherit = $properties.flat_color_image_template; - usage = color_attachment|input_attachment|sampled; - format = $output.format; - }; - view = { - @inherit = $properties.flat_color_view_template; - image = $output.image; - format = $output.format; - }; - format = r16g16b16a16_sfloat; - finalLayout = shader_read_only_optimal; - }; - framebuffer = { - renderPass = deferred; - attachments = (depth, color, emission, normal, position, opaque, - $output.view); +flat_color_image_template = { + imageType = `2d; + samples = 1; + extent = { width = $output.extent.width; height = $output.extent.height; - layers = 1; + depth = 1; }; - clearValues = ( - { depthStencil = { depth = 1; stencil = 0; }; }, - { color = "[0, 0, 0, 1]"; }, // color - { color = "[0, 0, 0, 1]"; }, // emission - { color = "[0, 0, 0, 1]"; }, // normal - { color = "[0, 0, 0, 1]"; }, // position - { color = "[0, 0, 0, 1]"; }, // opaque - { color = "[0, 0, 0, 1]"; }, // output + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|input_attachment|transient_attachment; + initialLayout = undefined; +}; +images = { + depth = { + @inherit = $properties.flat_color_image_template; + format = x8_d24_unorm_pack32; + usage = depth_stencil_attachment|input_attachment|transient_attachment; + }; + color = { + @inherit = $properties.flat_color_image_template; + format = r8g8b8a8_unorm; + }; + emission = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; + normal = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; + position = { + @inherit = $properties.flat_color_image_template; + format = r32g32b32a32_sfloat; + }; + opaque = { + @inherit = $properties.flat_color_image_template; + format = r16g16b16a16_sfloat; + }; +}; +flat_color_view_template = { + viewType = VK_IMAGE_VIEW_TYPE_2D; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; +}; +imageViews = { + depth = { + @inherit = $properties.flat_color_view_template; + image = depth; + format = $properties.images.depth.format; + subresourceRange = { + aspectMask = depth; + }; + }; + color = { + @inherit = $properties.flat_color_view_template; + image = color; + format = $properties.images.color.format; + }; + emission = { + @inherit = $properties.flat_color_view_template; + image = emission; + format = $properties.images.emission.format; + }; + normal = { + @inherit = $properties.flat_color_view_template; + image = normal; + format = $properties.images.normal.format; + }; + position = { + @inherit = $properties.flat_color_view_template; + image = position; + format = $properties.images.position.format; + }; + opaque = { + @inherit = $properties.flat_color_view_template; + image = opaque; + format = $properties.images.opaque.format; + }; +}; +output = { + image = { + @inherit = $properties.flat_color_image_template; + usage = color_attachment|input_attachment|sampled; + format = $output.format; + }; + view = { + @inherit = $properties.flat_color_view_template; + image = $output.image; + format = $output.format; + }; + format = r16g16b16a16_sfloat; + finalLayout = shader_read_only_optimal; +}; +framebuffer = { + renderPass = deferred; + attachments = (depth, color, emission, normal, position, opaque, + $output.view); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; +}; +clearValues = ( + { depthStencil = { depth = 1; stencil = 0; }; }, + { color = "[0, 0, 0, 1]"; }, // color + { color = "[0, 0, 0, 1]"; }, // emission + { color = "[0, 0, 0, 1]"; }, // normal + { color = "[0, 0, 0, 1]"; }, // position + { color = "[0, 0, 0, 1]"; }, // opaque + { color = "[0, 0, 0, 1]"; }, // output +); +attachment_template = { + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; +}; +info = { + color = "[0, 1, 0, 1]"; + subpass_info = ( + { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, + { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, + { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, + { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, + { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, ); - attachment_template = { - samples = 1; - loadOp = dont_care; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; - }; - info = { - color = "[0, 1, 0, 1]"; - subpass_info = ( - { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, - { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, - { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, - { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, - { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, - ); - }; - renderpass = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $properties.images.depth.format; - loadOp = clear; - finalLayout = depth_stencil_attachment_optimal; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.color.format; - loadOp = clear; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.emission.format; - loadOp = clear; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.normal.format; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.position.format; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.opaque.format; - }, - { - @inherit = $properties.attachment_template; - format = $output.format; - loadOp = clear; - storeOp = store; - finalLayout = $output.finalLayout; - }, - ); - subpasses = ( - { // 0 depth - pipelineBindPoint = graphics; - depthStencilAttachment = { +}; +renderpass = { + attachments = ( + { + @inherit = $properties.attachment_template; + format = $properties.images.depth.format; + loadOp = clear; + finalLayout = depth_stencil_attachment_optimal; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.color.format; + loadOp = clear; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.emission.format; + loadOp = clear; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.normal.format; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.position.format; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.opaque.format; + }, + { + @inherit = $properties.attachment_template; + format = $output.format; + loadOp = clear; + storeOp = store; + finalLayout = $output.finalLayout; + }, + ); + subpasses = ( + { // 0 depth + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_attachment_optimal; + }; + }, + { // 1 translucent-frags + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_read_only_optimal; + }; + preserveAttachments = (1, 2, 3, 4, 5); + }, + { // 2 g-buffer generation + pipelineBindPoint = graphics; + colorAttachments = ( + { // color + attachment = 1; + layout = color_attachment_optimal; + }, + { // emission + attachment = 2; + layout = color_attachment_optimal; + }, + { // normal + attachment = 3; + layout = color_attachment_optimal; + }, + { // position + attachment = 4; + layout = color_attachment_optimal; + }, + ); + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_read_only_optimal; + }; + preserveAttachments = (6); + }, + { // 3 lighting + pipelineBindPoint = graphics; + inputAttachments = ( + { // depth attachment = 0; - layout = depth_stencil_attachment_optimal; - }; - }, - { // 1 translucent-frags - pipelineBindPoint = graphics; - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_read_only_optimal; - }; - preserveAttachments = (1, 2, 3, 4, 5); - }, - { // 2 g-buffer generation - pipelineBindPoint = graphics; - colorAttachments = ( - { // color - attachment = 1; - layout = color_attachment_optimal; - }, - { // emission - attachment = 2; - layout = color_attachment_optimal; - }, - { // normal - attachment = 3; - layout = color_attachment_optimal; - }, - { // position - attachment = 4; - layout = color_attachment_optimal; - }, - ); - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_read_only_optimal; - }; - preserveAttachments = (6); - }, - { // 3 lighting - pipelineBindPoint = graphics; - inputAttachments = ( - { // depth - attachment = 0; - layout = shader_read_only_optimal; - }, - { // color - attachment = 1; - layout = shader_read_only_optimal; - }, - { // emission - attachment = 2; - layout = shader_read_only_optimal; - }, - { // normal - attachment = 3; - layout = shader_read_only_optimal; - }, - { // position - attachment = 4; - layout = shader_read_only_optimal; - }, - ); - colorAttachments = ( - { // opaque - attachment = 5; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (6); - }, - { // 4 compose - pipelineBindPoint = graphics; - inputAttachments = ( - { // opaque - attachment = 5; - layout = shader_read_only_optimal; - }, - ); - colorAttachments = ( - { // output - attachment = 6; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (0, 1, 2, 3, 4); - }, - ); - dependencies = ( - { - srcSubpass = 0; // depth - dstSubpass = 1; // translucent - srcStageMask = late_fragment_tests; - dstStageMask = fragment_shader|early_fragment_tests; - srcAccessMask = depth_stencil_attachment_write; - dstAccessMask = input_attachment_read|depth_stencil_attachment_read; - dependencyFlags = by_region; - }, - { - srcSubpass = 0; // depth - dstSubpass = 2; // g-buffer - srcStageMask = late_fragment_tests; - dstStageMask = early_fragment_tests; - srcAccessMask = depth_stencil_attachment_write; - dstAccessMask = depth_stencil_attachment_read; - dependencyFlags = by_region; - }, - { - srcSubpass = 2; // g-buffer - dstSubpass = 3; // lighting - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region; - }, - { - srcSubpass = 3; // lighting - dstSubpass = 4; // compose - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region; - }, - { - srcSubpass = 1; // translucent-frags - dstSubpass = 4; // translucent-final/compose - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region; - }, - ); - }; -} + layout = shader_read_only_optimal; + }, + { // color + attachment = 1; + layout = shader_read_only_optimal; + }, + { // emission + attachment = 2; + layout = shader_read_only_optimal; + }, + { // normal + attachment = 3; + layout = shader_read_only_optimal; + }, + { // position + attachment = 4; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // opaque + attachment = 5; + layout = color_attachment_optimal; + }, + ); + preserveAttachments = (6); + }, + { // 4 compose + pipelineBindPoint = graphics; + inputAttachments = ( + { // opaque + attachment = 5; + layout = shader_read_only_optimal; + }, + ); + colorAttachments = ( + { // output + attachment = 6; + layout = color_attachment_optimal; + }, + ); + preserveAttachments = (0, 1, 2, 3, 4); + }, + ); + dependencies = ( + { + srcSubpass = 0; // depth + dstSubpass = 1; // translucent + srcStageMask = late_fragment_tests; + dstStageMask = fragment_shader|early_fragment_tests; + srcAccessMask = depth_stencil_attachment_write; + dstAccessMask = input_attachment_read|depth_stencil_attachment_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 0; // depth + dstSubpass = 2; // g-buffer + srcStageMask = late_fragment_tests; + dstStageMask = early_fragment_tests; + srcAccessMask = depth_stencil_attachment_write; + dstAccessMask = depth_stencil_attachment_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 2; // g-buffer + dstSubpass = 3; // lighting + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 3; // lighting + dstSubpass = 4; // compose + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region; + }, + { + srcSubpass = 1; // translucent-frags + dstSubpass = 4; // translucent-final/compose + srcStageMask = color_attachment_output; + dstStageMask = fragment_shader; + srcAccessMask = color_attachment_write; + dstAccessMask = input_attachment_read; + dependencyFlags = by_region; + }, + ); +}; diff --git a/libs/video/renderer/vulkan/rp_forward.plist b/libs/video/renderer/vulkan/rp_forward.plist index e8c703a23..0e7366801 100644 --- a/libs/video/renderer/vulkan/rp_forward.plist +++ b/libs/video/renderer/vulkan/rp_forward.plist @@ -1,199 +1,197 @@ -{ - flat_color_image_template = { - imageType = `2d; - samples = $msaaSamples; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|transient_attachment; +flat_color_image_template = { + imageType = `2d; + samples = $msaaSamples; + extent = { + width = $output.extent.width; + height = $output.extent.height; + depth = 1; }; - images = { - depth = { - @inherit = @properties.flat_color_image_template; - format = x8_d24_unorm_pack32; - usage = depth_stencil_attachment|transient_attachment; - }; - color = { - @inherit = @properties.flat_color_image_template; - format = $output.format; - }; + mipLevels = 1; + arrayLayers = 1; + tiling = optimal; + usage = color_attachment|transient_attachment; +}; +images = { + depth = { + @inherit = @properties.flat_color_image_template; + format = x8_d24_unorm_pack32; + usage = depth_stencil_attachment|transient_attachment; }; - flat_color_view_template = { - viewType = `2d; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; + color = { + @inherit = @properties.flat_color_image_template; + format = $output.format; + }; +}; +flat_color_view_template = { + viewType = `2d; + components = { + r = identity; + g = identity; + b = identity; + a = identity; + }; + subresourceRange = { + aspectMask = color; + levelCount = 1; + layerCount = 1; + }; +}; +imageViews = { + depth = { + @inherit = $properties.flat_color_view_template; + image = depth; + format = $properties.images.depth.format; subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; + aspectMask = depth; }; }; - imageViews = { - depth = { - @inherit = $properties.flat_color_view_template; - image = depth; + color = { + @inherit = $properties.flat_color_view_template; + image = color; + format = $properties.images.color.format; + }; +}; +framebuffer = { + renderPass = $properties.renderpass; + attachment = ($output.view, depth); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; +}; +framebuffer_msaa = { + renderPass = $properties.renderpass_msaa; + attachment = ($output.view, depth, color); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; +}; +attachment_template = { + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; +}; +renderpass = { + attachments = ( + { + @inherit = $properties.attachment_template; + format = $output.format; + loadOp = clear; + storeOp = store; + finalLayout = present_src_khr; + }, + { + @inherit = $properties.attachment_template; format = $properties.images.depth.format; - subresourceRange = { - aspectMask = depth; + loadOp = clear; + finalLayout = depth_stencil_attachment_optimal; + }, + ); + subpasses = ( + { + pipelineBindPoint = graphics; + colorAttachments = ( + { + attachment = 0; + layout = color_attachment_optimal; + } + ); + depthStencilAttachment = { + attachment = 1; + layout = depth_stencil_attachment_optimal; }; - }; - color = { - @inherit = $properties.flat_color_view_template; - image = color; - format = $properties.images.color.format; - }; - }; - framebuffer = { - renderPass = $properties.renderpass; - attachment = ($output.view, depth); - width = $output.extent.width; - height = $output.extent.height; - layers = 1; - }; - framebuffer_msaa = { - renderPass = $properties.renderpass_msaa; - attachment = ($output.view, depth, color); - width = $output.extent.width; - height = $output.extent.height; - layers = 1; - }; - attachment_template = { - samples = 1; - loadOp = dont_care; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; - }; - renderpass = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $output.format; - loadOp = clear; - storeOp = store; - finalLayout = present_src_khr; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.depth.format; - loadOp = clear; - finalLayout = depth_stencil_attachment_optimal; - }, - ); - subpasses = ( - { - pipelineBindPoint = graphics; - colorAttachments = ( - { - attachment = 0; - layout = color_attachment_optimal; - } - ); - depthStencilAttachment = { - attachment = 1; - layout = depth_stencil_attachment_optimal; - }; - preserveAttachments = (); - }, - ); - dependencies = ( - { - srcSubpass = ~0u; // external - dstSubpass = 0; - srcStageMask = top_of_pipe; - dstStageMask = color_attachment_output; - srcAccessMask = memory_read; - dstAccessMask = color_attachment_write; - dependencyFlags = by_region; - }, - { - srcSubpass = 0; - dstSubpass = ~0u; // external - srcStageMask = color_attachment_output; - dstStageMask = bottom_of_pipe; - srcAccessMask = color_attachment_write; - dstAccessMask = memory_read; - dependencyFlags = by_region; - }, - ); - }; - renderpass_msaa = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $output.format; - storeOp = store; - finalLayout = present_src_khr; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.depth.format; - samples = $msaaSamples; - loadOp = clear; - storeOp = dont_care; - finalLayout = depth_stencil_attachment_optimal; - }, - { - @inherit = $properties.attachment_template; - format = $swapchain.format; - samples = $msaaSamples; - loadOp = clear; - storeOp = store;// dont_care? - finalLayout = color_attachment_optimal; - }, - ); - subpasses = ( - { - pipelineBindPoint = graphics; - colorAttachments = ( - { - attachment = 2; - layout = color_attachment_optimal; - } - ); - resolveAttachments = ( - { - attachment = 0; - layout = color_attachment_optimal; - } - ); - depthStencilAttachment = { - attachment = 1; - layout = depth_stencil_attachment_optimal; - }; - preserveAttachments = (); - }, - ); - dependencies = ( - { - srcSubpass = ~0u; // external - dstSubpass = 0; - srcStageMask = top_of_pipe; - dstStageMask = color_attachment_output; - srcAccessMask = memory_read; - dstAccessMask = color_attachment_write; - dependencyFlags = by_region; - }, - { - srcSubpass = 0; - dstSubpass = ~0u; // external - srcStageMask = color_attachment_output; - dstStageMask = bottom_of_pipe; - srcAccessMask = color_attachment_write; - dstAccessMask = memory_read; - dependencyFlags = by_region; - }, - ); - }; -} + preserveAttachments = (); + }, + ); + dependencies = ( + { + srcSubpass = ~0u; // external + dstSubpass = 0; + srcStageMask = top_of_pipe; + dstStageMask = color_attachment_output; + srcAccessMask = memory_read; + dstAccessMask = color_attachment_write; + dependencyFlags = by_region; + }, + { + srcSubpass = 0; + dstSubpass = ~0u; // external + srcStageMask = color_attachment_output; + dstStageMask = bottom_of_pipe; + srcAccessMask = color_attachment_write; + dstAccessMask = memory_read; + dependencyFlags = by_region; + }, + ); +}; +renderpass_msaa = { + attachments = ( + { + @inherit = $properties.attachment_template; + format = $output.format; + storeOp = store; + finalLayout = present_src_khr; + }, + { + @inherit = $properties.attachment_template; + format = $properties.images.depth.format; + samples = $msaaSamples; + loadOp = clear; + storeOp = dont_care; + finalLayout = depth_stencil_attachment_optimal; + }, + { + @inherit = $properties.attachment_template; + format = $swapchain.format; + samples = $msaaSamples; + loadOp = clear; + storeOp = store;// dont_care? + finalLayout = color_attachment_optimal; + }, + ); + subpasses = ( + { + pipelineBindPoint = graphics; + colorAttachments = ( + { + attachment = 2; + layout = color_attachment_optimal; + } + ); + resolveAttachments = ( + { + attachment = 0; + layout = color_attachment_optimal; + } + ); + depthStencilAttachment = { + attachment = 1; + layout = depth_stencil_attachment_optimal; + }; + preserveAttachments = (); + }, + ); + dependencies = ( + { + srcSubpass = ~0u; // external + dstSubpass = 0; + srcStageMask = top_of_pipe; + dstStageMask = color_attachment_output; + srcAccessMask = memory_read; + dstAccessMask = color_attachment_write; + dependencyFlags = by_region; + }, + { + srcSubpass = 0; + dstSubpass = ~0u; // external + srcStageMask = color_attachment_output; + dstStageMask = bottom_of_pipe; + srcAccessMask = color_attachment_write; + dstAccessMask = memory_read; + dependencyFlags = by_region; + }, + ); +}; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 73b6be1b5..99e67b79f 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1,4 +1,3 @@ -{ properties = { color = { bsp = "[0.0, 0.5, 0.6, 1]"; @@ -1161,4 +1160,3 @@ renderpasses = { }); }; }; -}; diff --git a/libs/video/renderer/vulkan/rp_output.plist b/libs/video/renderer/vulkan/rp_output.plist index f36286299..86e27a6f3 100644 --- a/libs/video/renderer/vulkan/rp_output.plist +++ b/libs/video/renderer/vulkan/rp_output.plist @@ -1,49 +1,47 @@ -{ - framebuffer = { - renderPass = output; - attachments = ($output.view); - width = $output.extent.width; - height = $output.extent.height; - layers = 1; - }; - clearValues = ( - { color = "[0, 0, 0, 1]"; }, // output +framebuffer = { + renderPass = output; + attachments = ($output.view); + width = $output.extent.width; + height = $output.extent.height; + layers = 1; +}; +clearValues = ( + { color = "[0, 0, 0, 1]"; }, // output +); +attachment_template = { + samples = 1; + loadOp = dont_care; + storeOp = dont_care; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = color_attachment_optimal; +}; +info = { + color = "[0.9, 0.9, 0.9, 1]"; + subpass_info = ( + { name = compose; color = "[ 0.9, 0.9, 0.9, 1]" }, ); - attachment_template = { - samples = 1; - loadOp = dont_care; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; - }; - info = { - color = "[0.9, 0.9, 0.9, 1]"; - subpass_info = ( - { name = compose; color = "[ 0.9, 0.9, 0.9, 1]" }, - ); - }; - renderpass = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $output.format; - loadOp = clear; - storeOp = store; - finalLayout = present_src_khr; - }, - ); - subpasses = ( - { // 0 output - pipelineBindPoint = graphics; - colorAttachments = ( - { // output - attachment = 0; - layout = color_attachment_optimal; - }, - ); - }, - ); - }; -} +}; +renderpass = { + attachments = ( + { + @inherit = $properties.attachment_template; + format = $output.format; + loadOp = clear; + storeOp = store; + finalLayout = present_src_khr; + }, + ); + subpasses = ( + { // 0 output + pipelineBindPoint = graphics; + colorAttachments = ( + { // output + attachment = 0; + layout = color_attachment_optimal; + }, + ); + }, + ); +}; diff --git a/libs/video/renderer/vulkan/rp_shadow.plist b/libs/video/renderer/vulkan/rp_shadow.plist index e2f6e5778..f56ad2270 100644 --- a/libs/video/renderer/vulkan/rp_shadow.plist +++ b/libs/video/renderer/vulkan/rp_shadow.plist @@ -1,52 +1,50 @@ -{ - clearValues = ( - { depthStencil = { depth = 1; stencil = 0; }; }, +clearValues = ( + { depthStencil = { depth = 1; stencil = 0; }; }, +); +info = { + color = "[0.2, 0.2, 0.2, 1]"; + subpass_info = ( + { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, ); - info = { - color = "[0.2, 0.2, 0.2, 1]"; - subpass_info = ( - { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, - ); - }; - renderpass_base = { - attachments = ( - { - format = $output.format; - samples = 1; - loadOp = dont_care; - storeOp = store; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = shader_read_only_optimal; - }, - ); - subpasses = ( - { // 0 depth - pipelineBindPoint = graphics; - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_attachment_optimal; - }; - } - ); - }; - renderpass_6 = { - @inherit = $properties.renderpass_base; - @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = (0x0000003fu); - }); - }; - renderpass_4 = { - @inherit = $properties.renderpass_base; - @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = (0x0000000fu); - }); - }; - renderpass_1 = { - @inherit = $properties.renderpass_base; - @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = (0x00000001u); - }); - }; -} +}; +renderpass_base = { + attachments = ( + { + format = $output.format; + samples = 1; + loadOp = dont_care; + storeOp = store; + stencilLoadOp = dont_care; + stencilStoreOp = dont_care; + initialLayout = undefined; + finalLayout = shader_read_only_optimal; + }, + ); + subpasses = ( + { // 0 depth + pipelineBindPoint = graphics; + depthStencilAttachment = { + attachment = 0; + layout = depth_stencil_attachment_optimal; + }; + } + ); +}; +renderpass_6 = { + @inherit = $properties.renderpass_base; + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0x0000003fu); + }); +}; +renderpass_4 = { + @inherit = $properties.renderpass_base; + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0x0000000fu); + }); +}; +renderpass_1 = { + @inherit = $properties.renderpass_base; + @next = (VkRenderPassMultiviewCreateInfo, { + viewMasks = (0x00000001u); + }); +}; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index e771b8759..23ac80d3f 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1960,7 +1960,7 @@ build_configs (scriptctx_t *sctx) builtin_plists = malloc (num_plists * sizeof (plitem_t *)); num_plists = 0; for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { - plitem_t *item = PL_GetPropertyList (sym->value, &sctx->hashctx); + plitem_t *item = PL_GetDictionary (sym->value, &sctx->hashctx); if (!item) { // Syntax errors in the compiled-in plists are unrecoverable Sys_Error ("Error parsing plist for %s", sym->name); From 7d4c1d79b18b576ade5cc03f8cf5a109f11577f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Mar 2023 15:17:28 +0900 Subject: [PATCH 3509/3664] [plist] Use reference counts for items This makes it much easier to share items between property lists (eg, targets and the main entity list in cl_light). --- include/QF/plist.h | 40 ++++++++----- libs/audio/cd_file.c | 4 +- libs/client/cl_input.c | 2 +- libs/client/cl_light.c | 7 +-- libs/client/cl_world.c | 2 +- libs/gamecode/pr_parse.c | 10 ++-- libs/input/in_binding.c | 2 +- libs/ruamoko/rua_plist.c | 74 +++++++++-------------- libs/util/plist.c | 87 ++++++++++++++++++---------- libs/util/quakefs.c | 8 +-- libs/util/test/test-plist.c | 2 +- libs/video/renderer/vulkan/vkparse.c | 14 ++--- nq/source/cl_main.c | 4 +- nq/source/host_cmd.c | 5 +- qw/source/cl_main.c | 4 +- ruamoko/include/PropertyList.h | 2 - ruamoko/include/plist.h | 7 ++- ruamoko/lib/Entity.r | 4 +- ruamoko/lib/PropertyList.r | 83 +++++--------------------- ruamoko/lib/plist.r | 7 ++- tools/qflight/source/entities.c | 2 +- 21 files changed, 166 insertions(+), 204 deletions(-) diff --git a/include/QF/plist.h b/include/QF/plist.h index 5ec11f849..884f6b9f3 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -238,11 +238,8 @@ plitem_t *PL_ObjectForKey (const plitem_t *dict, const char *key); \param dict The Dictionary to remove the value from \param key The unique key associated with the value to be removed - \return the value associated with the key, or NULL if not found or \a dict - isn't a dictionary (includes if \a dict is null). - \note You are responsible for freeing the returned object. */ -plitem_t *PL_RemoveObjectForKey (plitem_t *dict, const char *key); +void PL_RemoveObjectForKey (plitem_t *dict, const char *key); /** Retrieve a key from a dictionary object. @@ -332,15 +329,12 @@ int PL_A_NumObjects (const plitem_t *array) __attribute__((pure)); qboolean PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index); /** Remove a value from an array object. - The array items will be shuffled to fill the resulting hole. + The array items will be shifted to fill the resulting hole. \param array The array from which to remove the value \param index The index within the array to remove - \return the value associated with the index, or NULL if not found or array - is noll or an array. - \note You are responsible for freeing the returned object. */ -plitem_t *PL_RemoveObjectAtIndex (plitem_t *array, int index); +void PL_RemoveObjectAtIndex (plitem_t *array, int index); /** Create a new dictionary object. The dictionary will be empty. @@ -372,14 +366,32 @@ plitem_t *PL_NewData (void *data, size_t size); */ plitem_t *PL_NewString (const char *str); -/** Free a property list object. +/** Retain ownership of a property list object. - This function takes care of freeing any referenced property list data, so - call it only on top-level objects. Safe to call with a null argument. + Use prior to removal to ensure the property list object is not freed when + removed from an array or dictionary. Adding an object to a dictionary or + array automatically retains the object. - \param item the property list object to be freed + \param item the property list object to be retained + \return the item + \note item may be null, in which case nothing is done but to return null */ -void PL_Free (plitem_t *item); +plitem_t *PL_Retain (plitem_t *item); + +/** Release ownership of a property list object. + + If the number of owners is reduced to 0 (or is already 0) then the object + will be freed. If the object contains other objects, then those objects + will be released. + + \param item the property list object to be released + \return the item if it is still valid, otherwise null + \note item may be null, in which case nothing is done but to return null +*/ +plitem_t *PL_Release (plitem_t *item); + +void PL_SetUserData (plitem_t *item, void *data); +void *PL_GetUserData (plitem_t *item) __attribute__((pure)); int PL_CheckType (pltype_t field_type, pltype_t item_type) __attribute__((const)); void PL_TypeMismatch (plitem_t *messages, const plitem_t *item, diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index 8e027199a..b92c88644 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -142,7 +142,7 @@ I_OGGMus_Shutdown (void) { if (tracklist) { I_OGGMus_Stop (); - PL_Free (tracklist); + PL_Release (tracklist); tracklist = NULL; } mus_enabled = false; @@ -184,7 +184,7 @@ Load_Tracklist (void) buffile = calloc (size+10, sizeof (char)); Qread (oggfile, buffile, size); - PL_Free (tracklist); + PL_Release (tracklist); tracklist = PL_GetPropertyList (buffile, 0); if (!tracklist || PL_Type (tracklist) != QFDictionary) { Sys_Printf ("Malformed or empty tracklist file. check mus_ogglist\n"); diff --git a/libs/client/cl_input.c b/libs/client/cl_input.c index cb7812e60..1f288b6bd 100644 --- a/libs/client/cl_input.c +++ b/libs/client/cl_input.c @@ -495,7 +495,7 @@ CL_Legacy_Init (void) Cmd_AddCommand ("unbind", cl_unbind_f, "compatibility wrapper for in_bind"); plitem_t *cfg = PL_GetPropertyList (default_input_config, 0); IN_LoadConfig (cfg); - PL_Free (cfg); + PL_Release (cfg); } void diff --git a/libs/client/cl_light.c b/libs/client/cl_light.c index f1466f3c2..61c4df6b6 100644 --- a/libs/client/cl_light.c +++ b/libs/client/cl_light.c @@ -321,12 +321,7 @@ CL_LoadLights (plitem_t *entities, scene_t *scene) } } } - // targets does not own the objects, so need to remove them before - // freeing targets - for (int i = PL_D_NumKeys (targets); i-- > 0; ) { - PL_RemoveObjectForKey (targets, PL_KeyAtIndex (targets, i)); - } - PL_Free (targets); + PL_Release (targets); for (size_t i = 0; i < ldata->lights.size; i++) { dump_light (&ldata->lights.a[i], ldata->lightleafs.a[i]); diff --git a/libs/client/cl_world.c b/libs/client/cl_world.c index a6c245aa4..8b8303136 100644 --- a/libs/client/cl_world.c +++ b/libs/client/cl_world.c @@ -217,7 +217,7 @@ CL_World_NewMap (const char *mapname, const char *skyname) if (cl_world.models.a[1] && cl_world.models.a[1]->brush.entities) { if (cl_world.edicts) { - PL_Free (cl_world.edicts); + PL_Release (cl_world.edicts); } cl_world.edicts = map_ent (mapname); if (cl_world.edicts) { diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 94bff9f58..6ef2770f8 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -347,7 +347,7 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashctx_s **hashctx) value = PL_NewString (token); } PL_D_AddObject (ent, PL_String (key), value); - PL_Free (key); + PL_Release (key); } PL_A_AddObject (plist, ent); } @@ -356,7 +356,7 @@ ED_ConvertToPlist (script_t *script, int nohack, struct hashctx_s **hashctx) parse_error: Sys_Printf ("%s:%d: %s", script->file, script->line, msg); dstring_delete (dstr); - PL_Free (plist); + PL_Release (plist); return 0; } @@ -406,7 +406,7 @@ ED_InitGlobals (progs_t *pr, plitem_t *globals) if (!ED_ParseEpair (pr, pr->pr_globals, global, value)) PR_Error (pr, "ED_InitGlobals: parse error"); } - PL_Free (keys); + PL_Release (keys); } VISIBLE void @@ -437,7 +437,7 @@ ED_InitEntity (progs_t *pr, plitem_t *entity, edict_t *ent) } init = 1; } - PL_Free (keys); + PL_Release (keys); if (!init) ent->free = 1; } @@ -539,7 +539,7 @@ ED_LoadFromFile (progs_t *pr, const char *data) entity_list = ED_Parse (pr, data); if (entity_list) { ED_SpawnEntities (pr, entity_list); - PL_Free (entity_list); + PL_Release (entity_list); } } diff --git a/libs/input/in_binding.c b/libs/input/in_binding.c index 76ba7d521..9c8957975 100644 --- a/libs/input/in_binding.c +++ b/libs/input/in_binding.c @@ -462,7 +462,7 @@ in_bind_f (void) IMT_BindAxis (imt, dev->axis_imt_id + num, axis, &recipe); } Hash_DelTable (vars_tab.tab); - PL_Free (exprctx.messages); + PL_Release (exprctx.messages); delete_memsuper (exprctx.memsuper); } else { // the rest of the command line is the binding diff --git a/libs/ruamoko/rua_plist.c b/libs/ruamoko/rua_plist.c index 304fe14b0..972acb237 100644 --- a/libs/ruamoko/rua_plist.c +++ b/libs/ruamoko/rua_plist.c @@ -51,13 +51,12 @@ typedef struct bi_plist_s { struct bi_plist_s *next; struct bi_plist_s **prev; plitem_t *plitem; - int own; + int users; } bi_plist_t; typedef struct { PR_RESMAP (bi_plist_t) plist_map; bi_plist_t *plists; - hashtab_t *plist_tab; } plist_resources_t; static bi_plist_t * @@ -97,12 +96,10 @@ bi_plist_clear (progs_t *pr, void *_res) bi_plist_t *plist; for (plist = res->plists; plist; plist = plist->next) { - if (plist->own) - PL_Free (plist->plitem); + PL_Release (plist->plitem); } res->plists = 0; - Hash_FlushTable (res->plist_tab); plist_reset (res); } @@ -110,7 +107,6 @@ static void bi_plist_destroy (progs_t *pr, void *_res) { __auto_type res = (plist_resources_t *) _res; - Hash_DelTable (res->plist_tab); PR_RESDELMAP (res->plist_map); @@ -120,8 +116,7 @@ bi_plist_destroy (progs_t *pr, void *_res) static inline int plist_handle (plist_resources_t *res, plitem_t *plitem) { - bi_plist_t dummy = {0, 0, plitem, 0}; - bi_plist_t *plist = Hash_FindElement (res->plist_tab, &dummy); + bi_plist_t *plist = PL_GetUserData (plitem); if (plist) return plist_index (res, plist); @@ -137,16 +132,19 @@ plist_handle (plist_resources_t *res, plitem_t *plitem) res->plists->prev = &plist->next; res->plists = plist; + PL_Retain (plitem); plist->plitem = plitem; - Hash_AddElement (res->plist_tab, plist); + PL_SetUserData (plitem, plist); return plist_index (res, plist); } static inline void plist_free_handle (plist_resources_t *res, bi_plist_t *plist) { - Hash_DelElement (res->plist_tab, plist); + PL_SetUserData (plist->plitem, 0); + PL_Release (plist->plitem); + *plist->prev = plist->next; if (plist->next) plist->next->prev = plist->prev; @@ -168,7 +166,6 @@ static inline int plist_retain (plist_resources_t *res, plitem_t *plitem) { int handle; - bi_plist_t *plist; if (!plitem) return 0; @@ -178,12 +175,10 @@ plist_retain (plist_resources_t *res, plitem_t *plitem) // we're taking ownership of the plitem, but we have nowhere to store // it, so we have to lose it. However, in this situation, we have worse // things to worry about. - PL_Free (plitem); + PL_Release (plitem); return 0; } - plist = plist_get (res, handle); - plist->own = 1; return handle; } @@ -327,9 +322,7 @@ bi_PL_RemoveObjectForKey (progs_t *pr, void *_res) int handle = P_INT (pr, 0); bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); const char *key = P_GSTRING (pr, 1); - plitem_t *plitem = PL_RemoveObjectForKey (plist->plitem, key); - - R_INT (pr) = plist_retain (res, plitem); + PL_RemoveObjectForKey (plist->plitem, key); } static void @@ -390,7 +383,6 @@ bi_PL_D_AddObject (progs_t *pr, void *_res) const char *key = P_GSTRING (pr, 1); bi_plist_t *obj = get_plist (pr, res, __FUNCTION__, obj_handle); - obj->own = 0; R_INT (pr) = PL_D_AddObject (dict->plitem, key, obj->plitem); } @@ -403,7 +395,6 @@ bi_PL_A_AddObject (progs_t *pr, void *_res) bi_plist_t *arr = get_plist (pr, res, __FUNCTION__, arr_handle); bi_plist_t *obj = get_plist (pr, res, __FUNCTION__, obj_handle); - obj->own = 0; R_INT (pr) = PL_A_AddObject (arr->plitem, obj->plitem); } @@ -427,7 +418,6 @@ bi_PL_A_InsertObjectAtIndex (progs_t *pr, void *_res) bi_plist_t *obj = get_plist (pr, res, __FUNCTION__, obj_handle); int ind = P_INT (pr, 2); - obj->own = 0; R_INT (pr) = PL_A_InsertObjectAtIndex (arr->plitem, obj->plitem, ind); } @@ -438,9 +428,7 @@ bi_PL_RemoveObjectAtIndex (progs_t *pr, void *_res) int handle = P_INT (pr, 0); bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); int ind = P_INT (pr, 1); - plitem_t *plitem = PL_RemoveObjectAtIndex (plist->plitem, ind); - - R_INT (pr) = plist_retain (res, plitem); + PL_RemoveObjectAtIndex (plist->plitem, ind); } static void @@ -481,18 +469,28 @@ bi_PL_NewString (progs_t *pr, void *_res) } static void -bi_PL_Free (progs_t *pr, void *_res) +bi_PL_Release (progs_t *pr, void *_res) { plist_resources_t *res = _res; int handle = P_INT (pr, 0); bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); - if (!plist->own) - PR_RunError (pr, "attempt to free unowned plist"); + if (!(plist->users && --plist->users > 0)) { + plist_free_handle (res, plist); + handle = 0; + } + R_INT (pr) = handle; +} - PL_Free (plist->plitem); +static void +bi_PL_Retain (progs_t *pr, void *_res) +{ + plist_resources_t *res = _res; + int handle = P_INT (pr, 0); + bi_plist_t *plist = get_plist (pr, res, __FUNCTION__, handle); - plist_free_handle (res, plist); + plist->users++; + R_INT (pr) = handle; } plitem_t * @@ -503,21 +501,6 @@ Plist_GetItem (progs_t *pr, int handle) return plist->plitem; } -static uintptr_t -plist_get_hash (const void *key, void *unused) -{ - bi_plist_t *plist = (bi_plist_t *) key; - return (uintptr_t) plist->plitem; -} - -static int -plist_compare (const void *k1, const void *k2, void *unused) -{ - bi_plist_t *pl1 = (bi_plist_t *) k1; - bi_plist_t *pl2 = (bi_plist_t *) k2; - return pl1->plitem == pl2->plitem; -} - #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) static builtin_t builtins[] = { @@ -546,7 +529,8 @@ static builtin_t builtins[] = { bi(PL_NewArray, 0), bi(PL_NewData, 2, p(ptr), p(int)), bi(PL_NewString, 1, p(string)), - bi(PL_Free, 1, p(ptr)), + bi(PL_Release, 1, p(ptr)), + bi(PL_Retain, 1, p(ptr)), {0} }; @@ -554,8 +538,6 @@ void RUA_Plist_Init (progs_t *pr, int secure) { plist_resources_t *res = calloc (1, sizeof (plist_resources_t)); - res->plist_tab = Hash_NewTable (1021, 0, 0, 0, pr->hashctx); - Hash_SetHashCompare (res->plist_tab, plist_get_hash, plist_compare); PR_Resources_Register (pr, "plist", res, bi_plist_clear, bi_plist_destroy); PR_RegisterBuiltins (pr, builtins, res); diff --git a/libs/util/plist.c b/libs/util/plist.c index 475380dc3..9beda5a15 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -49,10 +49,12 @@ Generic property list item. */ struct plitem_s { - pltype_t type; + pltype_t type; + unsigned users; + void *data; + void *user_data; int line; - void *data; -}; +};//plitem_t /* Dictionaries @@ -146,7 +148,7 @@ dict_free (void *i, void *unused) dictkey_t *item = (dictkey_t *) i; free (item->key); if (item->value) // Make descended stuff get freed - PL_Free (item->value); + PL_Release (item->value); free (item); } @@ -206,14 +208,23 @@ PL_NewString (const char *str) return new_string (str, strlen (str), 0); } -VISIBLE void -PL_Free (plitem_t *item) +VISIBLE plitem_t * +PL_Retain (plitem_t *item) +{ + if (item) { + item->users++; + } + return item; +} + +VISIBLE plitem_t * +PL_Release (plitem_t *item) { pldict_t *dict; plarray_t *array; - if (!item) { - return; + if (!item || (item->users && --item->users > 0)) { + return item; } switch (item->type) { case QFDictionary: @@ -229,7 +240,7 @@ PL_Free (plitem_t *item) int i = array->numvals; while (i-- > 0) { - PL_Free (array->values[i]); + PL_Release (array->values[i]); } free (array->values); free (item->data); @@ -248,6 +259,19 @@ PL_Free (plitem_t *item) break; } free (item); + return 0; +} + +VISIBLE void +PL_SetUserData (plitem_t *item, void *data) +{ + item->user_data = data; +} + +VISIBLE void * +PL_GetUserData (plitem_t *item) +{ + return item->user_data; } VISIBLE size_t @@ -308,11 +332,11 @@ PL_KeyAtIndex (const plitem_t *item, int index) return dict->keys.a[index]->key; } -VISIBLE plitem_t * +VISIBLE void PL_RemoveObjectForKey (plitem_t *item, const char *key) { if (!item || item->type != QFDictionary) { - return NULL; + return; } pldict_t *dict = (pldict_t *) item->data; @@ -320,8 +344,9 @@ PL_RemoveObjectForKey (plitem_t *item, const char *key) plitem_t *value; k = (dictkey_t *) Hash_Del (dict->tab, key); - if (!k) - return NULL; + if (!k) { + return; + } value = k->value; k->value = 0; for (size_t i = 0; i < dict->keys.size; i++) { @@ -331,7 +356,7 @@ PL_RemoveObjectForKey (plitem_t *item, const char *key) } } dict_free (k, 0); - return value; + value->users--; } VISIBLE plitem_t * @@ -389,7 +414,8 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) dictkey_t *k; if ((k = Hash_Find (dict->tab, key))) { - PL_Free ((plitem_t *) k->value); + value->users++; + PL_Release (k->value); k->value = value; } else { k = malloc (sizeof (dictkey_t)); @@ -397,6 +423,7 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) if (!k) return false; + value->users++; k->key = strdup (key); k->value = value; @@ -438,6 +465,8 @@ PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index) memmove (arr->values + index + 1, arr->values + index, (arr->numvals - index) * sizeof (plitem_t *)); + + item->users++; arr->values[index] = item; arr->numvals++; return true; @@ -458,11 +487,11 @@ PL_A_NumObjects (const plitem_t *array) return ((plarray_t *) array->data)->numvals; } -VISIBLE plitem_t * +VISIBLE void PL_RemoveObjectAtIndex (plitem_t *array, int index) { if (!array || array->type != QFArray) { - return 0; + return; } plarray_t *arr; @@ -471,7 +500,7 @@ PL_RemoveObjectAtIndex (plitem_t *array, int index) arr = (plarray_t *)array->data; if (index < 0 || index >= arr->numvals) - return 0; + return; item = arr->values[index]; arr->numvals--; @@ -480,7 +509,7 @@ PL_RemoveObjectAtIndex (plitem_t *array, int index) index++; } - return item; + item->users--; } static void __attribute__((format(printf, 2, 3))) @@ -631,7 +660,7 @@ pl_parsekeyvalue (pldata_t *pl, plitem_t *dict, int end_ok) if (!PL_D_AddObject (dict, PL_String (key), value)) { goto error; } - PL_Free (key); // don't need the key item + PL_Release (key); // don't need the key item if (!pl_checknext (pl, end_ok ? ";" : ";}", end_ok)) { return 0; @@ -642,8 +671,8 @@ pl_parsekeyvalue (pldata_t *pl, plitem_t *dict, int end_ok) } return 1; error: - PL_Free (key); - PL_Free (value); + PL_Release (key); + PL_Release (value); return 0; } @@ -656,13 +685,13 @@ pl_parsedictionary (pldata_t *pl) pl->pos++; // skip over opening { while (pl_skipspace (pl, 0) && pl->ptr[pl->pos] != '}') { if (!pl_parsekeyvalue (pl, dict, 0)) { - PL_Free (dict); + PL_Release (dict); return NULL; } } if (pl->pos >= pl->end) { pl_error (pl, "Unexpected end of string when parsing dictionary"); - PL_Free (dict); + PL_Release (dict); return NULL; } pl->pos++; // skip over closing } @@ -680,7 +709,7 @@ pl_parsevalue (pldata_t *pl, plitem_t *array, int end_ok) } if (!PL_A_AddObject (array, value)) { pl_error (pl, "too many items in array"); - PL_Free (value); + PL_Release (value); return 0; } @@ -705,13 +734,13 @@ pl_parsearray (pldata_t *pl) while (pl_skipspace (pl, 0) && pl->ptr[pl->pos] != ')') { if (!pl_parsevalue (pl, array, 0)) { - PL_Free (array); + PL_Release (array); return NULL; } } if (pl->pos >= pl->end) { pl_error (pl, "Unexpected end of string when parsing array"); - PL_Free (array); + PL_Release (array); return NULL; } pl->pos++; // skip over opening ) @@ -978,7 +1007,7 @@ pl_getdictionary (pldata_t *pl) while (pl_skipspace (pl, 1)) { if (!pl_parsekeyvalue (pl, dict, 1)) { - PL_Free (dict); + PL_Release (dict); return NULL; } } @@ -1000,7 +1029,7 @@ pl_getarray (pldata_t *pl) while (pl_skipspace (pl, 1)) { if (!pl_parsevalue (pl, array, 1)) { - PL_Free (array); + PL_Release (array); return NULL; } } diff --git a/libs/util/quakefs.c b/libs/util/quakefs.c index 6e4db10eb..ae736d433 100644 --- a/libs/util/quakefs.c +++ b/libs/util/quakefs.c @@ -543,7 +543,7 @@ qfs_find_gamedir (const char *name, hashtab_t *dirs) } } free (list); - PL_Free (keys); + PL_Release (keys); } return gdpl; } @@ -706,7 +706,7 @@ qfs_load_config (void) Qclose (f); if (qfs_gd_plist) - PL_Free (qfs_gd_plist); + PL_Release (qfs_gd_plist); qfs_gd_plist = PL_GetDictionary (buf, 0); free (buf); if (qfs_gd_plist && PL_Type (qfs_gd_plist) == QFDictionary) @@ -714,7 +714,7 @@ qfs_load_config (void) Sys_Printf ("not a dictionary\n"); no_config: if (qfs_gd_plist) - PL_Free (qfs_gd_plist); + PL_Release (qfs_gd_plist); qfs_gd_plist = PL_GetPropertyList (qfs_default_dirconf, 0); } @@ -1470,7 +1470,7 @@ qfs_shutdown (void *data) { clear_findfile (); qfs_free_gamedir (); - PL_Free (qfs_gd_plist); + PL_Release (qfs_gd_plist); free ((char *) qfs_userpath); free (gamedir_callbacks); ALLOC_FREE_BLOCKS (vpaths); diff --git a/libs/util/test/test-plist.c b/libs/util/test/test-plist.c index d3ce32715..14b516d6c 100644 --- a/libs/util/test/test-plist.c +++ b/libs/util/test/test-plist.c @@ -28,7 +28,7 @@ test_string_io (const char *str) item = PL_NewString (str); saved = PL_WritePropertyList (item); - PL_Free (item); + PL_Release (item); item = PL_GetPropertyList (saved, 0); res = PL_String (item); if (!strcmp (str, res)) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 23ac80d3f..82ce59c61 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1283,7 +1283,7 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, return 0; } Hash_DelTable (vars_tab.tab); - PL_Free (messages); + PL_Release (messages); return 1; } @@ -1979,7 +1979,7 @@ delete_configs (void) { int num_plists = 0; for (exprsym_t *sym = builtin_plist_syms; sym->name; sym++) { - PL_Free (builtin_plists[num_plists]); + PL_Release (builtin_plists[num_plists]); num_plists++; } free (builtin_plists); @@ -2030,7 +2030,7 @@ Vulkan_GetConfig (vulkan_ctx_t *ctx, const char *name) dstring_delete (msg); config = 0; } - PL_Free (ectx.messages); + PL_Release (ectx.messages); delete_memsuper (ectx.memsuper); return config; } @@ -2353,7 +2353,7 @@ QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) } } QFV_DestroySymtab (exprctx.external_variables); - PL_Free (messages); + PL_Release (messages); if (!ret) { delete_memsuper (memsuper); ri = 0; @@ -2409,7 +2409,7 @@ QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) } } QFV_DestroySymtab (exprctx.external_variables); - PL_Free (messages); + PL_Release (messages); if (!ret) { delete_memsuper (memsuper); ri = 0; @@ -2448,8 +2448,8 @@ QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, memsuper_t *memsuper, Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } } - PL_Free (messages); - PL_Free (item); + PL_Release (messages); + PL_Release (item); return ret; } diff --git a/nq/source/cl_main.c b/nq/source/cl_main.c index fd8237a85..1316a051e 100644 --- a/nq/source/cl_main.c +++ b/nq/source/cl_main.c @@ -170,7 +170,7 @@ CL_WriteConfiguration (void) free (cfg); Qclose (f); } - PL_Free (config); + PL_Release (config); } } @@ -197,7 +197,7 @@ CL_ReadConfiguration (const char *cfg_name) Cvar_LoadConfig (config); IN_LoadConfig (config); - PL_Free (config); + PL_Release (config); return 1; } diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index a14149190..e6c8cf5c1 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -506,9 +506,10 @@ convert_to_game_dict (script_t *script) // load the edicts out of the savegame file list = ED_ConvertToPlist (script, 0, 0); - item = PL_RemoveObjectAtIndex (list, 0); + item = PL_ObjectAtIndex (list, 0); PL_D_AddObject (game, "globals", item); PL_D_AddObject (game, "entities", list); + PL_RemoveObjectAtIndex (list, 0); return game; } @@ -728,7 +729,7 @@ Host_Loadgame_f (void) } end: if (game) - PL_Free (game); + PL_Release (game); if (mapname) free (mapname); if (script) diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 6746301f0..8a07c30d5 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1734,7 +1734,7 @@ Host_WriteConfiguration (void) free (cfg); Qclose (f); } - PL_Free (config); + PL_Release (config); } } @@ -1761,7 +1761,7 @@ Host_ReadConfiguration (const char *cfg_name) Cvar_LoadConfig (config); IN_LoadConfig (config); - PL_Free (config); + PL_Release (config); return 1; } diff --git a/ruamoko/include/PropertyList.h b/ruamoko/include/PropertyList.h index cc72dc3f4..a2cca1fc6 100644 --- a/ruamoko/include/PropertyList.h +++ b/ruamoko/include/PropertyList.h @@ -30,7 +30,6 @@ @interface PLItem: Object { plitem_t *item; - int own; } + (PLItem *) newDictionary; + (PLItem *) newArray; @@ -40,7 +39,6 @@ + (PLItem *) fromFile:(QFile) file; - initWithItem:(plitem_t *) item; -- initWithOwnItem:(plitem_t *) item; - (plitem_t *) item; - (string) write; - (pltype_t) type; diff --git a/ruamoko/include/plist.h b/ruamoko/include/plist.h index 9b5817491..161a1a611 100644 --- a/ruamoko/include/plist.h +++ b/ruamoko/include/plist.h @@ -17,7 +17,7 @@ typedef enum {QFDictionary, QFArray, QFBinary, QFString} pltype_t; // possible t @extern int PL_Line (plitem_t *str); @extern string PL_String (plitem_t *str); @extern plitem_t *PL_ObjectForKey (plitem_t *item, string key); -@extern plitem_t *PL_RemoveObjectForKey (plitem_t *item, string key); +@extern void PL_RemoveObjectForKey (plitem_t *item, string key); @extern plitem_t *PL_ObjectAtIndex (plitem_t *item, int index); @extern plitem_t *PL_D_AllKeys (plitem_t *item); @extern string PL_KeyAtIndex (plitem_t *item, int index); @@ -26,11 +26,12 @@ typedef enum {QFDictionary, QFArray, QFBinary, QFString} pltype_t; // possible t @extern int PL_A_AddObject (plitem_t *array_item, plitem_t *item); @extern int PL_A_NumObjects (plitem_t *item); @extern int PL_A_InsertObjectAtIndex (plitem_t *array_item, plitem_t *item, int index); -@extern plitem_t *PL_RemoveObjectAtIndex (plitem_t *array_item, int index); +@extern void PL_RemoveObjectAtIndex (plitem_t *array_item, int index); @extern plitem_t *PL_NewDictionary (); @extern plitem_t *PL_NewArray (); @extern plitem_t *PL_NewData (void *data, int len); @extern plitem_t *PL_NewString (string str); -@extern void PL_Free (plitem_t *pl); +@extern plitem_t *PL_Retain (plitem_t *pl); +@extern plitem_t *PL_Release (plitem_t *pl); #endif//__ruamoko_plist_h diff --git a/ruamoko/lib/Entity.r b/ruamoko/lib/Entity.r index 12c465df8..9816d1fb9 100644 --- a/ruamoko/lib/Entity.r +++ b/ruamoko/lib/Entity.r @@ -99,7 +99,7 @@ int PR_SetField (entity ent, string field, string value) = #0; value = PL_String (PL_ObjectForKey (dict, field)); PR_SetField (ent, field, value); } - PL_Free (keys); + PL_Release (keys); if ((func = PR_FindFunction (classname))) { //dprint ("calling " + classname + "\n"); @self = ent; @@ -157,7 +157,7 @@ int PR_SetField (entity ent, string field, string value) = #0; else value = PL_NewString (token); PL_D_AddObject (ent, PL_String (key), value); - PL_Free (key); + PL_Release (key); } PL_A_AddObject (plist, ent); } diff --git a/ruamoko/lib/PropertyList.r b/ruamoko/lib/PropertyList.r index 02f28fb54..c165d7192 100644 --- a/ruamoko/lib/PropertyList.r +++ b/ruamoko/lib/PropertyList.r @@ -49,47 +49,28 @@ return [[class alloc] initWithItem: item]; } -+ (PLItem *) ownItemClass:(plitem_t *) item -{ - PLItem *plitem = [PLItem itemClass:item]; - if (plitem) { - plitem.own = 1; - } - return plitem; -} - + (PLItem *) fromString:(string) str { - return [[PLItem ownItemClass: PL_GetPropertyList (str)] autorelease]; + return [[PLItem itemClass: PL_GetPropertyList (str)] autorelease]; } + (PLItem *) fromFile:(QFile) file { - return [[PLItem ownItemClass: PL_GetFromFile (file)] autorelease]; + return [[PLItem itemClass: PL_GetFromFile (file)] autorelease]; } - initWithItem:(plitem_t *) item { if (!(self = [super init])) return self; + PL_Retain (item); self.item = item; - own = 0; - return self; -} - --initWithOwnItem:(plitem_t *) item -{ - if (!(self = [super init])) - return self; - self.item = item; - own = 1; return self; } - (void) dealloc { - if (own) - PL_Free (item); + PL_Release (item); [super dealloc]; } @@ -144,13 +125,7 @@ - addKey:(string) key value:(PLItem *) value { - if (!value.own) { - obj_error (self, 0, "add of unowned key/value to PLDictionary"); - return self; - } PL_D_AddObject (item, key, value.item); - value.own = 0; - [value release]; return self; } @@ -166,25 +141,13 @@ - addObject:(PLItem *) object { - if (!object.own) { - obj_error (self, 0, "add of unowned object to PLArray"); - return self; - } PL_A_AddObject (item, object.item); - object.own = 0; - [object release]; return self; } - insertObject:(PLItem *) object atIndex:(int) index { - if (!object.own) { - obj_error (self, 0, "add of unowned object to PLArray"); - return self; - } PL_A_InsertObjectAtIndex (item, object.item, index); - object.own = 0; - [object release]; return self; } @@ -200,17 +163,17 @@ + (PLDictionary *) new { - return [[PLDictionary alloc] initWithOwnItem: PL_NewDictionary ()]; + return [[PLDictionary alloc] initWithItem: PL_NewDictionary ()]; } + (PLItem *) fromString:(string) str { - return [[PLItem ownItemClass: PL_GetDictionary (str)] autorelease]; + return [[PLItem itemClass: PL_GetDictionary (str)] autorelease]; } + (PLItem *) fromFile:(QFile) file { - return [[PLItem ownItemClass: PL_GetDictionaryFromFile (file)] autorelease]; + return [[PLItem itemClass: PL_GetDictionaryFromFile (file)] autorelease]; } - (int) count @@ -230,20 +193,12 @@ - (PLItem *) allKeys { - PLItem *item = [[PLItem itemClass: PL_D_AllKeys (item)] autorelease]; - item.own = 1; - return item; + return [[PLItem itemClass: PL_D_AllKeys (item)] autorelease]; } - addKey:(string) key value:(PLItem *) value { - if (!value.own) { - obj_error (self, 0, "add of unowned key/value to PLDictionary"); - return self; - } PL_D_AddObject (item, key, value.item); - value.own = 0; - [value release]; return self; } @@ -253,17 +208,17 @@ + (PLArray *) new { - return [[PLArray alloc] initWithOwnItem: PL_NewArray ()]; + return [[PLArray alloc] initWithItem: PL_NewArray ()]; } + (PLItem *) fromString:(string) str { - return [[PLItem ownItemClass: PL_GetArray (str)] autorelease]; + return [[PLItem itemClass: PL_GetArray (str)] autorelease]; } + (PLItem *) fromFile:(QFile) file { - return [[PLItem ownItemClass: PL_GetArrayFromFile (file)] autorelease]; + return [[PLItem itemClass: PL_GetArrayFromFile (file)] autorelease]; } - (int) count @@ -283,25 +238,13 @@ - addObject:(PLItem *) object { - if (!object.own) { - obj_error (self, 0, "add of unowned object to PLArray"); - return self; - } PL_A_AddObject (item, object.item); - object.own = 0; - [object release]; return self; } - insertObject:(PLItem *) object atIndex:(int) index { - if (!object.own) { - obj_error (self, 0, "add of unowned object to PLArray"); - return self; - } PL_A_InsertObjectAtIndex (item, object.item, index); - object.own = 0; - [object release]; return self; } @@ -311,7 +254,7 @@ + (PLData *) new:(void*) data size:(int) len { - return [[PLData alloc] initWithOwnItem: PL_NewData (data, len)]; + return [[PLData alloc] initWithItem: PL_NewData (data, len)]; } @end @@ -320,7 +263,7 @@ + (PLString *) new: (string) str { - return [[PLString alloc] initWithOwnItem: PL_NewString (str)]; + return [[PLString alloc] initWithItem: PL_NewString (str)]; } - (string) string diff --git a/ruamoko/lib/plist.r b/ruamoko/lib/plist.r index b961dc0d7..724eac34c 100644 --- a/ruamoko/lib/plist.r +++ b/ruamoko/lib/plist.r @@ -11,7 +11,7 @@ pltype_t PL_Type (plitem_t *str) = #0; int PL_Line (plitem_t *str) = #0; string PL_String (plitem_t *str) = #0; plitem_t *PL_ObjectForKey (plitem_t *item, string key) = #0; -plitem_t *PL_RemoveObjectForKey (plitem_t *item, string key) = #0; +void PL_RemoveObjectForKey (plitem_t *item, string key) = #0; plitem_t *PL_ObjectAtIndex (plitem_t *item, int index) = #0; plitem_t *PL_D_AllKeys (plitem_t *item) = #0; string PL_KeyAtIndex (plitem_t *item, int index) = #0; @@ -20,9 +20,10 @@ int PL_D_AddObject (plitem_t *dict, string key, plitem_t *value) = #0; int PL_A_AddObject (plitem_t *array_item, plitem_t *item) = #0; int PL_A_NumObjects (plitem_t *item) = #0; int PL_A_InsertObjectAtIndex (plitem_t *array_item, plitem_t *item, int index) = #0; -plitem_t *PL_RemoveObjectAtIndex (plitem_t *array_item, int index) = #0; +void PL_RemoveObjectAtIndex (plitem_t *array_item, int index) = #0; plitem_t *PL_NewDictionary (void) = #0; plitem_t *PL_NewArray (void) = #0; plitem_t *PL_NewData (void *data, int len) = #0; plitem_t *PL_NewString (string str) = #0; -void PL_Free (plitem_t *pl) = #0; +plitem_t *PL_Retain (plitem_t *pl) = #0; +plitem_t *PL_Release (plitem_t *pl) = #0; diff --git a/tools/qflight/source/entities.c b/tools/qflight/source/entities.c index 0157014f8..26c61638f 100644 --- a/tools/qflight/source/entities.c +++ b/tools/qflight/source/entities.c @@ -274,7 +274,7 @@ LoadEntities (void) entity->persistence = 1; } } - PL_Free (dict); + PL_Release (dict); if (entity->light) { // convert to subtraction to the brightness for the whole light, From 68b5cd89d238f7f1cdff2a57156d7f82deefd6ac Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Mar 2023 18:30:21 +0900 Subject: [PATCH 3510/3664] [vkgen] Plug a pile of ruamoko memory leaks While the previous cleanup took care of the C side, it turns out vkgen was leaking property list items all over the place, but they were cleaned up by the shutdown code. --- libs/video/renderer/vulkan/vkgen/vkfieldarray.r | 13 +++++++++++-- libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r | 10 +++++++++- libs/video/renderer/vulkan/vkgen/vkfieldsingle.r | 10 +++++++++- libs/video/renderer/vulkan/vkgen/vkgen.r | 13 ++++++++++++- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldarray.r b/libs/video/renderer/vulkan/vkgen/vkfieldarray.r index 159a41ba3..b2900dfb5 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldarray.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldarray.r @@ -1,4 +1,5 @@ #include +#include #include "vkfieldarray.h" #include "vkfieldtype.h" @@ -17,11 +18,19 @@ PLItem *desc = [item getObjectForKey:"type"]; type = [[FieldType fieldType:[desc getObjectAtIndex:1]] retain]; - value_field = [[item getObjectForKey:"values"] string]; - size_field = [[item getObjectForKey:"size"] string]; + value_field = str_hold ([[item getObjectForKey:"values"] string]); + size_field = str_hold ([[item getObjectForKey:"size"] string]); return self; } +-(void) dealloc +{ + [type release]; + str_free (value_field); + str_free (size_field); + [super dealloc]; +} + -writeParseData { fprintf (output_file, "static parse_array_t parse_%s_%s_data = {\n", diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r b/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r index 0353db7a1..5ae8f7df3 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldreadonly.r @@ -1,4 +1,5 @@ #include +#include #include "vkfieldreadonly.h" #include "vkfieldtype.h" @@ -17,10 +18,17 @@ PLItem *desc = [item getObjectForKey:"type"]; type = [[FieldType fieldType:[desc getObjectAtIndex:1]] retain]; - value_field = [[item getObjectForKey:"value"] string]; + value_field = str_hold ([[item getObjectForKey:"value"] string]); return self; } +-(void) dealloc +{ + [type release]; + str_free (value_field); + [super dealloc]; +} + -writeParseData { return self; diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r index f1c4b4977..c09788a37 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldsingle.r @@ -1,4 +1,5 @@ #include +#include #include "vkfieldsingle.h" #include "vkfieldtype.h" @@ -17,10 +18,17 @@ PLItem *desc = [item getObjectForKey:"type"]; type = [[FieldType fieldType:[desc getObjectAtIndex:1]] retain]; - value_field = [[item getObjectForKey:"value"] string]; + value_field = str_hold ([[item getObjectForKey:"value"] string]); return self; } +-(void) dealloc +{ + [type release]; + str_free (value_field); + [super dealloc]; +} + -writeParseData { fprintf (output_file, "static parse_single_t parse_%s_%s_data = {\n", diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index bbad10551..1367524d7 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -131,6 +131,12 @@ get_object_key (void *obj, void *unused) return [(id)obj name]; } +static void +free_object (void *obj, void *unused) +{ + [(id)obj release]; +} + void usage (string name) { @@ -181,7 +187,7 @@ main(int argc, string *argv) } queue = [[Array array] retain]; output_types = [[Array array] retain]; - available_types = Hash_NewTable (127, get_object_key, nil, nil); + available_types = Hash_NewTable (127, get_object_key, free_object, nil); processed_types = Hash_NewTable (127, get_string_key, nil, nil); scan_types (); @@ -258,5 +264,10 @@ main(int argc, string *argv) Qclose (header_file); Hash_DelTable (available_types); [plist release]; + [search release]; + [handles release]; + [parse release]; + [queue release]; + [output_types release]; return 0; } From 5255c9c7a81b7aef444ebdcbb837177adc37a161 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Mar 2023 10:17:42 +0900 Subject: [PATCH 3511/3664] [set] Initialize pool's dynamic arrays Testing had missed this because qfvis is the main user of set pools. --- libs/util/set.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/util/set.c b/libs/util/set.c index 20f92c01d..06c67e5be 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -80,8 +80,10 @@ set_del_iter_r (set_pool_t *set_pool, set_iter_t *set_iter) void set_pool_init (set_pool_t *set_pool) { - set_pool->set_freelist = 0; - set_pool->set_iter_freelist = 0; + *set_pool = (set_pool_t) { + .set_blocks = DARRAY_STATIC_INIT (8), + .set_iter_blocks = DARRAY_STATIC_INIT (8), + }; } inline set_t * From 654b208641779b67e39acef47d5a4d0b223125a2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 Mar 2023 19:47:30 +0900 Subject: [PATCH 3512/3664] [plist] Add functions to extend dictionaries and arrays The idea is to make it easy (and efficient) to merge property list items. --- include/QF/plist.h | 26 +++++++++++++ libs/util/plist.c | 93 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 105 insertions(+), 14 deletions(-) diff --git a/include/QF/plist.h b/include/QF/plist.h index 884f6b9f3..942bdf8a3 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -294,6 +294,20 @@ int PL_D_NumKeys (const plitem_t *dict) __attribute__((pure)); */ qboolean PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value); +/** Copy contents of one dictionary into another. + + The contents of \a srcDict are added to \a dstDict without affecting + \a srcDict. Any collisions in \a dstDict result in those values in + \a dstDict being replaced by the the values from \a srcDict: the new + key-value pairs override the old. + + \param dstDict The dictionary to extend + \param srcDict The dictionary from which key-value pairs will be copied + \return true if values were copied, false if nothing was copied (either + dictionary is null, or not a dictionary, or if \a srcDict was empty) +*/ +qboolean PL_D_Extend (plitem_t *dstDict, plitem_t *srcDict); + /** Add an item to an array. \param array The array to which the item will be added @@ -306,6 +320,18 @@ qboolean PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value); */ qboolean PL_A_AddObject (plitem_t *array, plitem_t *item); +/** Append contents of one array to another. + + The contents of \a srcArray are added to \a dstArray without affecting + \a srcArray. Those values are appended to the destination array values. + + \param dstArray The array to extend + \param srcArray The array from which values will be copied + \return true if values were copied, false if nothing was copied (either + array is null, or not an array, or if \a srcArray was empty) +*/ +qboolean PL_A_Extend (plitem_t *dstArray, plitem_t *srcArray); + /** Retrieve the number of items in an array. \param array The array from which to get the number of objects diff --git a/libs/util/plist.c b/libs/util/plist.c index 9beda5a15..07a1faf6e 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -414,7 +414,7 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) dictkey_t *k; if ((k = Hash_Find (dict->tab, key))) { - value->users++; + PL_Retain (value); PL_Release (k->value); k->value = value; } else { @@ -423,7 +423,7 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) if (!k) return false; - value->users++; + PL_Retain (value); k->key = strdup (key); k->value = value; @@ -433,6 +433,60 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) return true; } +VISIBLE qboolean +PL_D_Extend (plitem_t *dstDict, plitem_t *srcDict) +{ + if (!dstDict || dstDict->type != QFDictionary + || !srcDict || srcDict->type != QFDictionary + || ((pldict_t *) srcDict->data)->keys.size < 1) { + return false; + } + pldict_t *dst = dstDict->data; + pldict_t *src = srcDict->data; + size_t count = dst->keys.size; + DARRAY_RESIZE (&dst->keys, dst->keys.size + src->keys.size);// open space + DARRAY_RESIZE (&dst->keys, count); // put size back so it's correct + for (size_t i = 0; i < src->keys.size; i++) { + dictkey_t *key = src->keys.a[i]; + dictkey_t *k; + if ((k = Hash_Find (dst->tab, key->key))) { + PL_Retain (key->value); + PL_Release (k->value); + k->value = key->value; + } else { + k = malloc (sizeof (dictkey_t)); + + if (!k) + return false; + + PL_Retain (key->value); + k->key = strdup (key->key); + k->value = key->value; + + Hash_Add (dst->tab, k); + DARRAY_APPEND (&dst->keys, k); + } + } + return true; +} + +static qboolean +check_array_size (plarray_t *arr, int count) +{ + if (count > arr->maxvals) { + int newmax = (count + 127) & ~127; + int size = newmax * sizeof (plitem_t *); + plitem_t **tmp = realloc (arr->values, size); + + if (!tmp) + return false; + + arr->maxvals = newmax; + arr->values = tmp; + } + return true; +} + VISIBLE qboolean PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index) { @@ -444,17 +498,8 @@ PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index) arr = (plarray_t *)array->data; - if (arr->numvals == arr->maxvals) { - int size = (arr->maxvals + 128) * sizeof (plitem_t *); - plitem_t **tmp = realloc (arr->values, size); - - if (!tmp) - return false; - - arr->maxvals += 128; - arr->values = tmp; - memset (arr->values + arr->numvals, 0, - (arr->maxvals - arr->numvals) * sizeof (plitem_t *)); + if (!check_array_size (arr, arr->numvals + 1)) { + return false; } if (index == -1) @@ -466,7 +511,7 @@ PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index) memmove (arr->values + index + 1, arr->values + index, (arr->numvals - index) * sizeof (plitem_t *)); - item->users++; + PL_Retain (item); arr->values[index] = item; arr->numvals++; return true; @@ -478,6 +523,26 @@ PL_A_AddObject (plitem_t *array, plitem_t *item) return PL_A_InsertObjectAtIndex (array, item, -1); } +VISIBLE qboolean +PL_A_Extend (plitem_t *dstArray, plitem_t *srcArray) +{ + if (!dstArray || dstArray->type != QFArray + || !srcArray || srcArray->type != QFArray + || ((plarray_t *) srcArray->data)->numvals < 1) { + return false; + } + plarray_t *dst = dstArray->data; + plarray_t *src = srcArray->data; + if (!check_array_size (dst, dst->numvals + src->numvals)) { + return false; + } + for (int i = 0; i < src->numvals; i++) { + PL_Retain (src->values[i]); + dst->values[dst->numvals++] = src->values[i]; + } + return true; +} + VISIBLE int PL_A_NumObjects (const plitem_t *array) { From 793525a50a9d03b7a539c7d5f5ad623e96c4dfaa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 20 Mar 2023 17:45:28 +0900 Subject: [PATCH 3513/3664] [sw] Free alias model cache memory when clearing models This fixes a Sys_Error when loading the level for the first demo (and probably many other times). It was mod_numknown getting set to 0 that triggered the issue, but that seems to be necessary for the other renderers. I think the whole model loading and caching system needs an overhaul as this doesn't feel quite right due to removing part of the advantage of caching the model data. --- include/mod_internal.h | 1 + libs/models/alias/sw_model_alias.c | 14 ++++++++++++++ libs/video/renderer/vid_render_sw.c | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/mod_internal.h b/include/mod_internal.h index 615b12e64..d643a31d8 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -73,6 +73,7 @@ void glsl_Mod_IQMFinish (model_t *mod); void sw_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int _s, int extra); void sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx); +void sw_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx); void sw_Mod_IQMFinish (model_t *mod); void gl_Mod_LoadLighting (model_t *mod, bsp_t *bsp); diff --git a/libs/models/alias/sw_model_alias.c b/libs/models/alias/sw_model_alias.c index 797ec38de..f1f104462 100644 --- a/libs/models/alias/sw_model_alias.c +++ b/libs/models/alias/sw_model_alias.c @@ -45,6 +45,14 @@ #include "d_iface.h" #include "mod_internal.h" +static void +sw_alias_clear (model_t *m, void *data) +{ + m->needload = true; + + Cache_Free (&m->cache); +} + // a pose is a single set of vertexes. a frame may be // an animating sequence of poses @@ -66,6 +74,12 @@ sw_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx) } } +void +sw_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx) +{ + alias_ctx->mod->clear = sw_alias_clear; +} + static void process_frame (mod_alias_ctx_t *alias_ctx, maliasframedesc_t *frame, int posenum, int extra) diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 660b0fa30..3602a2328 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -85,7 +85,7 @@ static vid_model_funcs_t model_funcs = { .Mod_MakeAliasModelDisplayLists = sw_Mod_MakeAliasModelDisplayLists, .Mod_LoadAllSkins = sw_Mod_LoadAllSkins, - .Mod_FinalizeAliasModel = 0, + .Mod_FinalizeAliasModel = sw_Mod_FinalizeAliasModel, .Mod_LoadExternalSkins = 0, .Mod_IQMFinish = sw_Mod_IQMFinish, .alias_cache = 1, From 3fbac33ee8d6c66656c13ee19aa3f33787eb4a50 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Mar 2023 13:18:16 +0900 Subject: [PATCH 3514/3664] [gl] Free alias model cache memory when clearing models Like sw, gl uses the cache for alias models and thus needs to free the cache memory when unloading the model. --- libs/models/alias/gl_model_alias.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index 5abc7e4d5..4dee2b98e 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -52,6 +52,14 @@ #include "compat.h" +static void +gl_alias_clear (model_t *m, void *data) +{ + m->needload = true; + + Cache_Free (&m->cache); +} + static void gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *texels, int snum, int gnum, maliasskindesc_t *skindesc) @@ -124,6 +132,8 @@ gl_Mod_FinalizeAliasModel (mod_alias_ctx_t *alias_ctx) header->mdl.scale_origin[2] -= (22 + 8); VectorScale (header->mdl.scale, 2, header->mdl.scale); } + + alias_ctx->mod->clear = gl_alias_clear; } static void From 2fbc27f6a0db5cc55e17fdddc42c04ef0f8221da Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 21 Mar 2023 17:53:55 +0900 Subject: [PATCH 3515/3664] [vkgen] Fix ignored field init and dealloc I had somehow missed vkfieldignore in a consistency pass, or just messed up its initialization (and thus deallocation) resulting in a double-free of the strings. --- libs/video/renderer/vulkan/vkgen/vkfieldignore.r | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldignore.r b/libs/video/renderer/vulkan/vkgen/vkfieldignore.r index dfbb71387..edd5e66a0 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldignore.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldignore.r @@ -9,14 +9,12 @@ -init:(PLItem *)item struct:(Struct *)strct field:(string)fname { - self = [super init]; + self = [super init:item struct:strct field:fname]; if (!self) { return self; } line = [item line]; - struct_name = str_hold ([strct outname]); - field_name = str_hold (fname); return self; } @@ -25,13 +23,6 @@ return self; } --(void)dealloc -{ - str_free (struct_name); - str_free (field_name); - [super dealloc]; -} - -writeParseData { return self; From a1c67ea24bdd08d62807210ad2b71cbe95b60eb5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Mar 2023 19:32:49 +0900 Subject: [PATCH 3516/3664] [vulkan] Implement most of the new job system There's still the actual job objects to create, but all the vulkan bits have been created and get destroyed on shutdown. --- include/QF/Vulkan/render.h | 33 +- libs/video/renderer/vulkan/render.c | 388 ++++++++++++------ libs/video/renderer/vulkan/render.plist | 91 ---- libs/video/renderer/vulkan/rp_main_def.plist | 252 +++++++++++- libs/video/renderer/vulkan/vkparse.c | 58 +-- libs/video/renderer/vulkan/vkparse.h | 3 - libs/video/renderer/vulkan/vkparse.plist | 44 +- libs/video/renderer/vulkan/vulkan_output.c | 35 ++ libs/video/renderer/vulkan/vulkan_particles.c | 20 + .../renderer/vulkan/vulkan_translucent.c | 15 + 10 files changed, 606 insertions(+), 333 deletions(-) delete mode 100644 libs/video/renderer/vulkan/render.plist diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 1d088fec4..3d8cb6b07 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -182,19 +182,9 @@ typedef struct qfv_renderinfo_s { vec4f_t color; const char *name; - struct memsuper_s *memsuper; - struct plitem_s *plitem; - uint32_t num_images; - qfv_imageinfo_t *images; - uint32_t num_views; - qfv_imageviewinfo_t *views; uint32_t num_renderpasses; qfv_renderpassinfo_t *renderpasses; qfv_output_t output; - uint32_t num_descriptorsets; - qfv_descriptorsetinfo_t *descriptorsets; - uint32_t num_layouts; - qfv_layoutinfo_t *layouts; } qfv_renderinfo_t; typedef struct qfv_processinfo_s { @@ -220,8 +210,17 @@ typedef struct qfv_stepinfo_s { typedef struct qfv_jobinfo_s { struct memsuper_s *memsuper; + struct plitem_s *plitem; uint32_t num_steps; qfv_stepinfo_t *steps; + + uint32_t num_images; + qfv_imageinfo_t *images; + uint32_t num_views; + qfv_imageviewinfo_t *views; + + uint32_t num_descriptorsets; + qfv_descriptorsetinfo_t *descriptorsets; } qfv_jobinfo_t; typedef struct qfv_label_s { @@ -280,20 +279,24 @@ typedef struct qfv_renderpass_s_ { qfv_subpass_t_ *subpasses; } qfv_renderpass_t_; -typedef struct qfv_render_s { +typedef struct qfv_job_s { struct qfv_resource_s *resources; struct qfv_resobj_s *images; struct qfv_resobj_s *image_views; uint32_t num_renderpasses; - qfv_renderpass_t_ *renderpasses; -} qfv_render_t; + uint32_t num_pipelines; + uint32_t num_layouts; + VkRenderPass *renderpasses; + VkPipeline *pipelines; + VkPipelineLayout *layouts; +} qfv_job_t; typedef struct qfv_renderctx_s { struct hashctx_s *hashctx; exprtab_t task_functions; - qfv_renderinfo_t *renderinfo; - qfv_render_t *render; + qfv_jobinfo_t *jobinfo; + qfv_job_t *job; } qfv_renderctx_t; void QFV_RunRenderPass (qfv_renderpass_t_ *rp, struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 0282d9547..758d4c84e 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -153,9 +153,9 @@ QFV_LoadRenderInfo (vulkan_ctx_t *ctx) plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); __auto_type output = get_output (ctx, item); Vulkan_Script_SetOutput (ctx, &output); - rctx->renderinfo = QFV_ParseRenderInfo (ctx, item, rctx); - if (rctx->renderinfo) { - rctx->renderinfo->plitem = item; + rctx->jobinfo = QFV_ParseJobInfo (ctx, item, rctx); + if (rctx->jobinfo) { + rctx->jobinfo->plitem = item; } } @@ -171,7 +171,8 @@ typedef struct { uint32_t num_attachmentrefs; uint32_t num_colorblend; uint32_t num_preserve; - uint32_t num_pipelines; + uint32_t num_graph_pipelines; + uint32_t num_comp_pipelines; } objcount_t; static void @@ -199,7 +200,7 @@ count_sp_stuff (qfv_subpassinfo_t *spi, objcount_t *counts) for (uint32_t i = 0; i < spi->num_pipelines; i++) { __auto_type pli = &spi->pipelines[i]; if (pli->num_graph_stages && !pli->compute_stage) { - counts->num_pipelines++; + counts->num_graph_pipelines++; } else { Sys_Error ("%s:%s: invalid graphics pipeline", spi->name, pli->name); @@ -218,13 +219,47 @@ count_rp_stuff (qfv_renderpassinfo_t *rpi, objcount_t *counts) } static void -count_stuff (qfv_renderinfo_t *renderinfo, objcount_t *counts) +count_comp_stuff (qfv_computeinfo_t *ci, objcount_t *counts) { - counts->num_images += renderinfo->num_images; - counts->num_views += renderinfo->num_views; - counts->num_renderpasses += renderinfo->num_renderpasses; - for (uint32_t i = 0; i < renderinfo->num_renderpasses; i++) { - count_rp_stuff (&renderinfo->renderpasses[i], counts); + for (uint32_t i = 0; i < ci->num_pipelines; i++) { + __auto_type pli = &ci->pipelines[i]; + if (!pli->num_graph_stages && pli->compute_stage) { + counts->num_comp_pipelines++; + } else { + Sys_Error ("%s:%s: invalid compute pipeline", + ci->name, pli->name); + } + } +} + +static void +count_step_stuff (qfv_stepinfo_t *step, objcount_t *counts) +{ + if ((step->render && step->compute) + || (step->render && step->process) + || (step->compute && step->process)) { + Sys_Error ("%s: invalid step: must be one of render/compute/process", + step->name); + } + if (step->render) { + __auto_type rinfo = step->render; + counts->num_renderpasses += rinfo->num_renderpasses; + for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { + count_rp_stuff (&rinfo->renderpasses[i], counts); + } + } + if (step->compute) { + count_comp_stuff (step->compute, counts); + } +} + +static void +count_stuff (qfv_jobinfo_t *jobinfo, objcount_t *counts) +{ + counts->num_images += jobinfo->num_images; + counts->num_views += jobinfo->num_views; + for (uint32_t i = 0; i < jobinfo->num_steps; i++) { + count_step_stuff (&jobinfo->steps[i], counts); } } @@ -232,25 +267,25 @@ static void create_resources (vulkan_ctx_t *ctx, objcount_t *counts) { __auto_type rctx = ctx->render_context; - __auto_type rinfo = rctx->renderinfo; - __auto_type render = rctx->render; + __auto_type jinfo = rctx->jobinfo; + __auto_type job = rctx->job; - render->resources = malloc (sizeof(qfv_resource_t) + job->resources = malloc (sizeof(qfv_resource_t) + counts->num_images * sizeof (qfv_resobj_t) + counts->num_views * sizeof (qfv_resobj_t)); - render->images = (qfv_resobj_t *) &render->resources[1]; - render->image_views = &render->images[counts->num_images]; + job->images = (qfv_resobj_t *) &job->resources[1]; + job->image_views = &job->images[counts->num_images]; - render->resources[0] = (qfv_resource_t) { + job->resources[0] = (qfv_resource_t) { .name = "render", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, .num_objects = counts->num_images + counts->num_views, - .objects = render->images, + .objects = job->images, }; for (uint32_t i = 0; i < counts->num_images; i++) { - __auto_type img = &rinfo->images[i]; - render->images[i] = (qfv_resobj_t) { + __auto_type img = &jinfo->images[i]; + job->images[i] = (qfv_resobj_t) { .name = img->name, .type = qfv_res_image, .image = { @@ -269,8 +304,8 @@ create_resources (vulkan_ctx_t *ctx, objcount_t *counts) } int error = 0; for (uint32_t i = 0; i < counts->num_views; i++) { - __auto_type view = &rinfo->views[i]; - render->image_views[i] = (qfv_resobj_t) { + __auto_type view = &jinfo->views[i]; + job->image_views[i] = (qfv_resobj_t) { .name = view->name, .type = qfv_res_image_view, .image_view = { @@ -282,19 +317,19 @@ create_resources (vulkan_ctx_t *ctx, objcount_t *counts) }, }; if (strcmp (view->image.name, "$output.image") == 0) { - __auto_type image = rinfo->output.image; - render->image_views[i].image_view.external_image = image; - render->image_views[i].image_view.image = -1; + //__auto_type image = jinfo->output.image; + //job->image_views[i].image_view.external_image = image; + //job->image_views[i].image_view.image = -1; } else { qfv_resobj_t *img = 0; - for (uint32_t j = 0; j < rinfo->num_images; j++) { - if (strcmp (view->image.name, rinfo->images[j].name) == 0) { - img = &render->images[j]; + for (uint32_t j = 0; j < jinfo->num_images; j++) { + if (strcmp (view->image.name, jinfo->images[j].name) == 0) { + img = &job->images[j]; } } if (img) { - uint32_t ind = img - render->resources->objects; - render->image_views[i].image_view.image = ind; + uint32_t ind = img - job->resources->objects; + job->image_views[i].image_view.image = ind; } else { Sys_Printf ("%d: unknown image reference: %s\n", view->image.line, view->image.name); @@ -303,11 +338,11 @@ create_resources (vulkan_ctx_t *ctx, objcount_t *counts) } } if (error) { - free (render->resources); - render->resources = 0; + free (job->resources); + job->resources = 0; return; } - QFV_CreateResource (ctx->device, render->resources); + QFV_CreateResource (ctx->device, job->resources); } typedef struct { @@ -319,11 +354,15 @@ typedef struct { VkAttachmentReference *attachref; VkPipelineColorBlendAttachmentState *cbAttach; uint32_t *preserve; + const char **rpName; const char **plName; - VkGraphicsPipelineCreateInfo *plCreate; + VkComputePipelineCreateInfo *cplCreate; + VkGraphicsPipelineCreateInfo *gplCreate; VkPipelineColorBlendStateCreateInfo *cbState; qfv_layoutinfo_t *layouts; + uint32_t *pl_counts; + VkPipeline *pl; VkRenderPass *rp; } objptr_t; @@ -331,8 +370,9 @@ typedef struct { typedef struct { objcount_t inds; objptr_t ptr; + vulkan_ctx_t *ctx; - qfv_renderinfo_t *rinfo; + qfv_jobinfo_t *jinfo; exprtab_t *symtab; qfv_renderpassinfo_t *rpi; VkRenderPassCreateInfo *rpc; @@ -361,8 +401,8 @@ find_subpass (qfv_dependencyinfo_t *d, uint32_t spind, static VkDescriptorSetLayout find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) { - for (uint32_t i = 0; i < s->rinfo->num_descriptorsets; i++) { - __auto_type ds = &s->rinfo->descriptorsets[i]; + for (uint32_t i = 0; i < s->jinfo->num_descriptorsets; i++) { + __auto_type ds = &s->jinfo->descriptorsets[i]; if (strcmp (ds->name, ref->name) == 0) { if (!ds->setLayout) { VkDescriptorSetLayoutCreateInfo cInfo = { @@ -396,7 +436,7 @@ find_layout (const qfv_reference_t *ref, objstate_t *s) return s->ptr.layouts[i].layout; } } - if (!QFV_ParseLayoutInfo (s->ctx, s->rinfo->memsuper, s->symtab, ref->name, + if (!QFV_ParseLayoutInfo (s->ctx, s->jinfo->memsuper, s->symtab, ref->name, &s->ptr.layouts[s->inds.num_layouts])) { Sys_Error ("%s.%s:%d: invalid layout: %s", s->rpi->name, s->spi->name, ref->line, ref->name); @@ -506,10 +546,12 @@ static void init_spCreate (uint32_t index, qfv_subpassinfo_t *sub, objstate_t *s) { s->spi = &sub[index]; - s->plc = &s->ptr.plCreate[s->inds.num_pipelines]; + s->plc = &s->ptr.gplCreate[s->inds.num_graph_pipelines]; s->spc = &s->ptr.subpass[s->inds.num_subpasses]; - __auto_type pln = &s->ptr.plName[s->inds.num_pipelines]; - __auto_type cbs = &s->ptr.cbState[s->inds.num_pipelines]; + __auto_type pln = &s->ptr.plName[s->inds.num_graph_pipelines]; + __auto_type cbs = &s->ptr.cbState[s->inds.num_graph_pipelines]; + + s->ptr.pl_counts[s->inds.num_renderpasses] += s->spi->num_pipelines; *s->spc = (VkSubpassDescription) { .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, @@ -539,7 +581,7 @@ init_spCreate (uint32_t index, qfv_subpassinfo_t *sub, objstate_t *s) } init_plCreate (&s->plc[i], &s->spi->pipelines[i], s); pln[i] = s->spi->name; - s->inds.num_pipelines++; + s->inds.num_graph_pipelines++; } __auto_type att = s->spi->attachments; @@ -613,6 +655,7 @@ init_rpCreate (uint32_t index, const qfv_renderinfo_t *rinfo, objstate_t *s) { s->rpi = &rinfo->renderpasses[index]; s->rpc = &s->ptr.rpCreate[s->inds.num_renderpasses]; + s->ptr.rpName[s->inds.num_renderpasses] = s->rpi->name; __auto_type attachments = &s->ptr.attach[s->inds.num_attachments]; __auto_type subpasses = &s->ptr.subpass[s->inds.num_subpasses]; @@ -651,7 +694,7 @@ init_pipeline (qfv_pipeline_t *pl, vulkan_ctx_t *ctx, qfv_pipelineinfo_t *ipl, .color = ipl->color, }, .bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .pipeline = s->ptr.pl[s->inds.num_pipelines], + .pipeline = s->ptr.pl[s->inds.num_graph_pipelines], .layout = find_layout (&ipl->layout, s), .task_count = ipl->num_tasks, .tasks = ipl->tasks, @@ -677,15 +720,15 @@ init_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx, qfv_subpassinfo_t *isp, .pInheritanceInfo = &sp->inherit, }, .pipeline_count = isp->num_pipelines, - .pipelines = &pl[s->inds.num_pipelines], + .pipelines = &pl[s->inds.num_graph_pipelines], }; for (uint32_t i = 0; i < isp->num_pipelines; i++) { init_pipeline (&sp->pipelines[i], ctx, &isp->pipelines[i], s); - s->inds.num_pipelines++; + s->inds.num_graph_pipelines++; } } -static void +static void __attribute__((used)) init_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx, qfv_renderpassinfo_t *irp, VkClearValue *cv, qfv_subpass_t_ *sp, qfv_pipeline_t *pl, objstate_t *s) @@ -716,14 +759,16 @@ init_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx, static void init_render (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) { +#if 0 __auto_type rctx = ctx->render_context; __auto_type rinfo = rctx->renderinfo; - __auto_type render = rctx->render; + __auto_type job = rctx->job; size_t size = 0; size += counts->num_renderpasses * sizeof (qfv_renderpass_t_); size += counts->num_attachments * sizeof (VkClearValue); size += counts->num_subpasses * sizeof (qfv_subpass_t_); - size += counts->num_pipelines * sizeof (qfv_pipeline_t); + size += counts->num_graph_pipelines * sizeof (qfv_pipeline_t); + size += counts->num_comp_pipelines * sizeof (qfv_pipeline_t); __auto_type rp = (qfv_renderpass_t_ *) calloc (1, size); __auto_type cv = (VkClearValue *) &rp[counts->num_renderpasses]; @@ -738,22 +783,73 @@ init_render (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) s.inds.num_renderpasses++; } - render->num_renderpasses = rinfo->num_renderpasses; - render->renderpasses = rp; + job->num_renderpasses = rinfo->num_renderpasses; + job->renderpasses = rp; +#endif } static void -create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) +create_step_render_objects (uint32_t index, const qfv_stepinfo_t *step, + objstate_t *s) +{ + __auto_type rinfo = step->render; + if (!rinfo) { + return; + } + for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { + s->ptr.pl_counts[s->inds.num_renderpasses] = 0; + init_rpCreate (i, rinfo, s); + s->inds.num_renderpasses++; + } +} + +static void +create_step_compute_objects (uint32_t index, const qfv_stepinfo_t *step, + objstate_t *s) +{ + __auto_type cinfo = step->compute; + if (!cinfo) { + return; + } + + uint32_t base = s->inds.num_graph_pipelines; + for (uint32_t i = 0; i < cinfo->num_pipelines; i++) { + __auto_type pli = &cinfo->pipelines[i]; + __auto_type plc = &s->ptr.cplCreate[s->inds.num_comp_pipelines]; + s->ptr.plName[base + s->inds.num_comp_pipelines] = pli->name; + *plc = (VkComputePipelineCreateInfo) { + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .flags = pli->flags, + .stage = *pli->compute_stage, + .layout = find_layout (&pli->layout, s), + }; + plc->stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; + s->inds.num_comp_pipelines++; + } +} + +static void +create_step_process_objects (uint32_t index, const qfv_stepinfo_t *step, + objstate_t *s) +{ + __auto_type pinfo = step->process; + if (!pinfo) { + return; + } + // nothing to create at this stage +} + +static void +create_objects (vulkan_ctx_t *ctx, objcount_t *counts) { __auto_type rctx = ctx->render_context; - __auto_type rinfo = rctx->renderinfo; + __auto_type jinfo = rctx->jobinfo; + __auto_type job = rctx->job; exprctx_t ectx = { .hashctx = &ctx->script_context->hashctx, }; - VkRenderPass rp[counts->num_renderpasses]; - VkPipeline pl[counts->num_pipelines]; VkRenderPassCreateInfo rpCreate[counts->num_renderpasses]; VkAttachmentDescription attach[counts->num_attachments]; VkClearValue clear[counts->num_attachments]; @@ -762,10 +858,15 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) VkAttachmentReference attachref[counts->num_attachmentrefs]; VkPipelineColorBlendAttachmentState cbAttach[counts->num_colorblend]; uint32_t preserve[counts->num_preserve]; - const char *plName[counts->num_pipelines]; - VkGraphicsPipelineCreateInfo plCreate[counts->num_pipelines]; - VkPipelineColorBlendStateCreateInfo cbState[counts->num_pipelines]; - qfv_layoutinfo_t layouts[counts->num_pipelines]; + const char *rpName[counts->num_renderpasses]; + const char *plName[counts->num_graph_pipelines + + counts->num_comp_pipelines]; + VkComputePipelineCreateInfo cplCreate[counts->num_comp_pipelines]; + VkGraphicsPipelineCreateInfo gplCreate[counts->num_graph_pipelines]; + VkPipelineColorBlendStateCreateInfo cbState[counts->num_graph_pipelines]; + qfv_layoutinfo_t layouts[counts->num_graph_pipelines + + counts->num_comp_pipelines]; + uint32_t pl_counts[counts->num_renderpasses]; objstate_t s = { .ptr = { .rpCreate = rpCreate, @@ -776,20 +877,28 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) .attachref = attachref, .cbAttach = cbAttach, .preserve = preserve, + .rpName = rpName, .plName = plName, - .plCreate = plCreate, + .cplCreate = cplCreate, + .gplCreate = gplCreate, .cbState = cbState, .layouts = layouts, - .rp = rp, - .pl = pl, + .pl_counts = pl_counts, + .rp = job->renderpasses, + .pl = job->pipelines, }, .ctx = ctx, - .rinfo = rinfo, - .symtab = QFV_CreateSymtab (rinfo->plitem, "properties", 0, 0, &ectx), + .jinfo = jinfo, + .symtab = QFV_CreateSymtab (jinfo->plitem, "properties", 0, 0, &ectx), }; - for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { - init_rpCreate (i, rinfo, &s); - s.inds.num_renderpasses++; + for (uint32_t i = 0; i < jinfo->num_steps; i++) { + create_step_render_objects (i, &jinfo->steps[i], &s); + } + for (uint32_t i = 0; i < jinfo->num_steps; i++) { + create_step_compute_objects (i, &jinfo->steps[i], &s); + } + for (uint32_t i = 0; i < jinfo->num_steps; i++) { + create_step_process_objects (i, &jinfo->steps[i], &s); } if (s.inds.num_renderpasses != counts->num_renderpasses || s.inds.num_attachments != counts->num_attachments @@ -798,38 +907,55 @@ create_renderpasses (vulkan_ctx_t *ctx, objcount_t *counts) || s.inds.num_attachmentrefs != counts->num_attachmentrefs || s.inds.num_colorblend != counts->num_colorblend || s.inds.num_preserve != counts->num_preserve - || s.inds.num_pipelines != counts->num_pipelines) { - Sys_Error ("create_renderpasses: something was missed"); + || s.inds.num_graph_pipelines != counts->num_graph_pipelines + || s.inds.num_comp_pipelines != counts->num_comp_pipelines) { + Sys_Error ("create_objects: something was missed"); } + job->num_renderpasses = counts->num_renderpasses; + job->num_pipelines = counts->num_graph_pipelines + + counts->num_comp_pipelines; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; uint32_t plInd = 0; - for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { - __auto_type rpi = &rinfo->renderpasses[i]; - dfunc->vkCreateRenderPass (device->dev, &s.ptr.rpCreate[i], 0, &rp[i]); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_RENDER_PASS, rp[i], - va (ctx->va_ctx, "renderpass:%s", rpi->name)); - for (uint32_t j = 0; j < rpi->num_subpasses; j++) { - __auto_type spi = &rpi->subpasses[j]; - for (uint32_t k = 0; k < spi->num_pipelines; k++) { - s.ptr.plCreate[plInd++].renderPass = rp[i]; - } + for (uint32_t i = 0; i < job->num_renderpasses; i++) { + dfunc->vkCreateRenderPass (device->dev, &s.ptr.rpCreate[i], 0, + &job->renderpasses[i]); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_RENDER_PASS, + job->renderpasses[i], + va (ctx->va_ctx, "renderpass:%s", rpName[i])); + for (uint32_t j = 0; j < pl_counts[i]; j++) { + s.ptr.gplCreate[plInd++].renderPass = job->renderpasses[i]; } } - dfunc->vkCreateGraphicsPipelines (device->dev, 0, s.inds.num_pipelines, - s.ptr.plCreate, 0, pl); - for (uint32_t i = 0; i < s.inds.num_pipelines; i++) { - QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE, pl[i], - va (ctx->va_ctx, "pipeline:%s", s.ptr.plName[i])); + if (s.inds.num_graph_pipelines) { + dfunc->vkCreateGraphicsPipelines (device->dev, 0, + s.inds.num_graph_pipelines, + s.ptr.gplCreate, 0, job->pipelines); } + if (s.inds.num_comp_pipelines) { + __auto_type p = &job->pipelines[s.inds.num_graph_pipelines]; + dfunc->vkCreateComputePipelines (device->dev, 0, + s.inds.num_comp_pipelines, + s.ptr.cplCreate, 0, p); + } + for (uint32_t i = 0; + i < s.inds.num_graph_pipelines + s.inds.num_comp_pipelines; i++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE, job->pipelines[i], + va (ctx->va_ctx, "pipeline:%s", plName[i])); + } + job->layouts = malloc (s.inds.num_layouts * sizeof (VkPipelineLayout)); + for (uint32_t i = 0; i < s.inds.num_layouts; i++) { + job->layouts[i] = layouts[i].layout; + } + job->num_layouts = s.inds.num_layouts; - rinfo->num_layouts = s.inds.num_layouts; - size_t layout_size = rinfo->num_layouts * sizeof (qfv_layoutinfo_t); - rinfo->layouts = cmemalloc (rinfo->memsuper, layout_size); - memcpy (rinfo->layouts, s.ptr.layouts, layout_size); +// rinfo->num_layouts = s.inds.num_layouts; +// size_t layout_size = rinfo->num_layouts * sizeof (qfv_layoutinfo_t); +// rinfo->layouts = cmemalloc (rinfo->memsuper, layout_size); +// memcpy (rinfo->layouts, s.ptr.layouts, layout_size); - init_render (ctx, counts, s); + if (0) init_render (ctx, counts, s); } void @@ -837,28 +963,37 @@ QFV_BuildRender (vulkan_ctx_t *ctx) { __auto_type rctx = ctx->render_context; - rctx->render = calloc (1, sizeof (qfv_render_t)); - objcount_t counts = {}; - count_stuff (rctx->renderinfo, &counts); + count_stuff (rctx->jobinfo, &counts); + + rctx->job = malloc (sizeof (qfv_job_t) + + counts.num_renderpasses * sizeof (VkRenderPass) + + counts.num_graph_pipelines * sizeof (VkPipeline) + + counts.num_comp_pipelines * sizeof (VkPipeline)); + __auto_type rp = (VkRenderPass *) &rctx->job[1]; + *rctx->job = (qfv_job_t) { + .renderpasses = rp, + .pipelines = (VkPipeline *) &rp[counts.num_renderpasses], + }; + create_resources (ctx, &counts); - create_renderpasses (ctx, &counts); + create_objects (ctx, &counts); } -static VkImageView __attribute__((pure)) +static VkImageView __attribute__((pure, used)) find_view (qfv_reference_t *ref, qfv_renderctx_t *rctx) { - __auto_type rinfo = rctx->renderinfo; - __auto_type render = rctx->render; + __auto_type jinfo = rctx->jobinfo; + __auto_type job = rctx->job; const char *name = ref->name; if (strncmp (name, "$views.", 7) == 0) { name += 7; } - for (uint32_t i = 0; i < rinfo->num_views; i++) { - __auto_type vi = &rinfo->views[i]; - __auto_type vo = &render->image_views[i]; + for (uint32_t i = 0; i < jinfo->num_views; i++) { + __auto_type vi = &jinfo->views[i]; + __auto_type vo = &job->image_views[i]; if (strcmp (name, vi->name) == 0) { return vo->image_view.view; } @@ -869,27 +1004,30 @@ find_view (qfv_reference_t *ref, qfv_renderctx_t *rctx) void QFV_DestroyFramebuffer (vulkan_ctx_t *ctx) { +#if 0 qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type rctx = ctx->render_context; - __auto_type render = rctx->render; - __auto_type rp = &render->renderpasses[0]; + __auto_type job = rctx->job; + __auto_type rp = &job->renderpasses[0]; if (rp->beginInfo.framebuffer) { VkFramebuffer framebuffer = rp->beginInfo.framebuffer; rp->beginInfo.framebuffer = 0; dfunc->vkDestroyFramebuffer (device->dev, framebuffer, 0); } +#endif } void QFV_CreateFramebuffer (vulkan_ctx_t *ctx) { +#if 0 __auto_type rctx = ctx->render_context; __auto_type rinfo = rctx->renderinfo; - __auto_type render = rctx->render; + __auto_type job = rctx->job; __auto_type rpInfo = &rinfo->renderpasses[0]; - __auto_type rp = &render->renderpasses[0]; + __auto_type rp = &job->renderpasses[0]; VkImageView attachments[rpInfo->num_attachments]; VkFramebufferCreateInfo cInfo = { @@ -917,6 +1055,7 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx) __auto_type sp = &rp->subpasses[i]; sp->inherit.framebuffer = framebuffer; } +#endif } void @@ -938,38 +1077,31 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type rctx = ctx->render_context; - if (rctx->render) { + if (rctx->job) { + __auto_type job = rctx->job; QFV_DestroyFramebuffer (ctx); //FIXME do properly - __auto_type r = rctx->render; - if (r->resources) { - QFV_DestroyResource (ctx->device, r->resources); - free (r->resources); + for (uint32_t i = 0; i < job->num_renderpasses; i++) { + dfunc->vkDestroyRenderPass (device->dev, job->renderpasses[i], 0); } - for (uint32_t i = 0; i < r->num_renderpasses; i++) { - __auto_type rp = &r->renderpasses[i]; - for (uint32_t j = 0; j < rp->subpass_count; j++) { - __auto_type sp = &rp->subpasses[j]; - for (uint32_t k = 0; k < sp->pipeline_count; k++) { - __auto_type pl = &sp->pipelines[k]; - dfunc->vkDestroyPipeline (device->dev, pl->pipeline, 0); - } - } - dfunc->vkDestroyRenderPass (device->dev, - rp->beginInfo.renderPass, 0); + for (uint32_t i = 0; i < job->num_pipelines; i++) { + dfunc->vkDestroyPipeline (device->dev, job->pipelines[i], 0); } - free (rctx->render); + for (uint32_t i = 0; i < job->num_layouts; i++) { + dfunc->vkDestroyPipelineLayout (device->dev, job->layouts[i], 0); + } + if (job->resources) { + QFV_DestroyResource (ctx->device, job->resources); + free (job->resources); + } + free (rctx->job); } - if (rctx->renderinfo) { - __auto_type rinfo = rctx->renderinfo; - for (uint32_t i = 0; i < rinfo->num_descriptorsets; i++) { - __auto_type setLayout = rinfo->descriptorsets[i].setLayout; + if (rctx->jobinfo) { + __auto_type jinfo = rctx->jobinfo; + for (uint32_t i = 0; i < jinfo->num_descriptorsets; i++) { + __auto_type setLayout = jinfo->descriptorsets[i].setLayout; dfunc->vkDestroyDescriptorSetLayout (device->dev, setLayout, 0); } - for (uint32_t i = 0; i < rinfo->num_layouts; i++) { - __auto_type layout = rinfo->layouts[i].layout; - dfunc->vkDestroyPipelineLayout (device->dev, layout, 0); - } - delete_memsuper (rinfo->memsuper); + delete_memsuper (jinfo->memsuper); } if (rctx->task_functions.tab) { Hash_DelTable (rctx->task_functions.tab); diff --git a/libs/video/renderer/vulkan/render.plist b/libs/video/renderer/vulkan/render.plist deleted file mode 100644 index 977e4bef8..000000000 --- a/libs/video/renderer/vulkan/render.plist +++ /dev/null @@ -1,91 +0,0 @@ -properties = { - partphysics_layout = { - setLayouts = (particle_set); - pushConstantRanges = ( - { - stageFlags = compute; - offset = 0; - size = "4 * 4 + 4"; - }, - ); - }; - partupdate_layout = { - setLayouts = (particle_set, particle_set, particle_set); - }; -}; -descriptorSetLayouts = { - particle_set = { - bindings = ( - { - binding = 0; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = compute; - }, - { - binding = 1; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = compute; - }, - { - binding = 2; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = compute; - }, - ); - }; -}; -tasks = { - particles = { - compute = { - pipelines = { - part:update = { - color = "[0.3, 0.8, 0.9]"; - tasks = ( - { func = "update_particles"; } - ); - stage = { - name = main; - module = $builtin/partupdate.comp; - }; - layout = partupdate_layout; - }; - part:physics = { - color = "[0.6, 0.8, 0.9]"; - tasks = ( - { func = "particle_physics"; } - ); - stage = { - name = main; - module = $builtin/partphysics.comp; - }; - layout = partphysics_layout; - }; - }; - }; - }; - shadow = { - //currently empty - }; - translucent = { - tasks = ( - { func = "clear_translucent"; }, - ) - }; - main = { - depenencies = (particles, shadow, translucent); - renderpass = main_def; - }; - preoutput = { - tasks = ( - { func = "acquire_output"; }, - { func = "update_input"; }, - ); - }; - output = { - depenencies = (main, preoutput); - renderpass = output; - }; -}; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 99e67b79f..971328dde 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -7,6 +7,10 @@ properties = { particles = "[0.4, 0.5, 0.8, 1]"; lights = "[0.8, 0.6, 0.2, 1]"; compose = "[0.7, 0.7, 0.7, 1]"; + + output = "[0.0, 0.7, 0.7, 1]"; + waterwarp = "[0.0, 0.7, 0.7, 1]"; + fisheye = "[0.0, 0.7, 0.7, 1]"; }; color_dependency = { src = { @@ -34,8 +38,8 @@ properties = { imageType = `2d; samples = 1; extent = { - width = $output.extent.width; - height = $output.extent.height; + width = $render_output.extent.width; + height = $render_output.extent.height; depth = 1; }; mipLevels = 1; @@ -152,6 +156,7 @@ properties = { }; compose_base = { @inherit = $pipeline_base; + rasterization = $counter_cw_cull_back; vertexInput = { bindings = (); attributes = (); @@ -456,14 +461,29 @@ properties = { primitiveRestartEnable = false; }; layout = { - descriptorSets = (matrix_set, texture_set, oit_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4"; - }, - ); + draw = { + descriptorSets = (matrix_set, texture_set, oit_set); + pushConstantRanges = ( + { + stageFlags = vertex; + offset = 0; + size = "16 * 4"; + }, + ); + }; + physics = { + descriptorSets = (particle_set); + pushConstantRanges = ( + { + stageFlags = compute; + offset = 0; + size = "4 * 4 + 4"; + }, + ); + }; + update = { + descriptorSets = (particle_set, particle_set, particle_set); + }; }; }; fstriangle = { @@ -499,7 +519,60 @@ properties = { layout = { descriptorSets = (compose_attach, oit_set); }; - } + }; + output = { + @inherit = $compose_base; + shader = { + fragment = { + stage = fragment; + name = main; + module = $builtin/output.frag; + }; + }; + layout = { + descriptorSets = (matrix_set, output_set); + }; + }; + waterwarp = { + @inherit = $compose_base; + shader = { + fragment = { + stage = fragment; + name = main; + module = $builtin/waterwarp.frag; + }; + }; + layout = { + descriptorSets = (matrix_set, output_set); + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "4"; + } + ); + }; + }; + fisheye = { + @inherit = $compose_base; + shader = { + fragment = { + stage = fragment; + name = main; + module = $builtin/fisheye.frag; + }; + }; + layout = { + descriptorSets = (matrix_set, output_set); + pushConstantRanges = ( + { + stageFlags = fragment; + offset = 0; + size = "2 * 4"; + } + ); + }; + }; }; descriptorSetLayouts = { matrix_set = { @@ -508,7 +581,7 @@ descriptorSetLayouts = { binding = 0; descriptorType = uniform_buffer; descriptorCount = 1; - stageFlags = vertex|geometry; + stageFlags = vertex|geometry|fragment; }, ); }; @@ -684,6 +757,38 @@ descriptorSetLayouts = { }, ); }; + particle_set = { + bindings = ( + { + binding = 0; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 1; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + { + binding = 2; + descriptorType = storage_buffer; + descriptorCount = 1; + stageFlags = compute; + }, + ); + }; + output_set = { + bindings = ( + { + binding = 0; + descriptorType = combined_image_sampler; + descriptorCount = 1; + stageFlags = fragment; + }, + ); + }; }; images = { depth = { @@ -714,7 +819,7 @@ images = { output = { @inherit = $image_base; usage = color_attachment|input_attachment|sampled; - format = $output.format; + format = $render_output.format; }; }; views = { @@ -754,7 +859,7 @@ views = { output = { @inherit = $view_base; image = output; - format = $output.format; + format = $render_output.format; } }; output = { @@ -803,16 +908,16 @@ renderpasses = { }; output = { @inherit = $attachment_base; - format = $output.format; + format = $render_output.format; loadOp = clear; storeOp = store; - finalLayout = $output.finalLayout; + finalLayout = $render_output.finalLayout; view = $views.output; }; }; framebuffer = { - width = $output.extent.width; - height = $output.extent.height; + width = $render_output.extent.width; + height = $render_output.extent.height; layers = 1; }; subpasses = { @@ -984,7 +1089,7 @@ renderpasses = { ); vertexInput = $particle.vertexInput; inputAssembly = $particle.inputAssembly; - layout = $particle.layout; + layout = $particle.layout.draw; }; }; }; @@ -1159,4 +1264,113 @@ renderpasses = { viewOffsets = ( 0, 0, 0, 0, 0); }); }; + output = { + color = "[0, 1, 1, 1]"; + attachments = { + output = { + @inherit = $attachment_base; + format = $render_output.format; + loadOp = clear; + storeOp = store; + finalLayout = present_src_khr; + view = $render_output.view; + }; + }; + framebuffer = { + width = $render_output.extent.width; + height = $render_output.extent.height; + layers = 1; + }; + subpasses = { + compose = { + color = "[ 0, 0.5, 0.5, 1]"; + attachments = { + color = { + output = color_attachment_optimal; + }; + }; + pipelines = { + output = { + @inherit = $compose_base; + + color = $color.output; + tasks = ( + { func = "output_draw"; }, + ); + + stages = ( + $fstriangle.shader.vertex, + $output.shader.fragment, + ); + layout = $output.layout; + }; + }; + }; + }; + }; +}; +steps = { + particles = { + compute = { + pipelines = { + part:update = { + color = "[0.3, 0.8, 0.9]"; + tasks = ( + { func = "update_particles"; } + ); + stage = { + name = main; + module = $builtin/partupdate.comp; + }; + layout = $particle.layout.update; + }; + part:physics = { + color = "[0.6, 0.8, 0.9]"; + tasks = ( + { func = "particle_physics"; } + ); + stage = { + name = main; + module = $builtin/partphysics.comp; + }; + layout = $particle.layout.physics; + }; + }; + }; + }; + shadow = { + //currently empty + }; + translucent = { + process = { + tasks = ( + { func = "clear_translucent"; }, + ); + }; + }; + main = { + dependencies = (particles, shadow, translucent); + render = { + renderpasses = { + deferred = $renderpasses.deferred; + deferred_cube = $renderpasses.deferred_cube; + }; + }; + }; + preoutput = { + process = { + tasks = ( + { func = "acquire_output"; }, + { func = "update_input"; }, + ); + }; + }; + output = { + dependencies = (main, preoutput); + render = { + renderpasses = { + output = $renderpasses.output; + }; + }; + }; }; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 82ce59c61..29f931fdc 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -2306,62 +2306,6 @@ QFV_DestroySymtab (exprtab_t *tab) free (tab); } -qfv_renderinfo_t * -QFV_ParseRenderInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) -{ - memsuper_t *memsuper = new_memsuper (); - qfv_renderinfo_t *ri = cmemalloc (memsuper, sizeof (qfv_renderinfo_t)); - *ri = (qfv_renderinfo_t) { .memsuper = memsuper }; - - scriptctx_t *sctx = ctx->script_context; - plitem_t *messages = PL_NewArray (); - - exprctx_t exprctx = { - .symtab = &root_symtab, - .messages = messages, - .hashctx = &sctx->hashctx, - .memsuper = memsuper, - }; - parsectx_t parsectx = { - .ectx = &exprctx, - .vctx = ctx, - .data = rctx, - }; - - static const char *extra_items[] = { - "images", - "views", - "renderpasses", - 0 - }; - exprsym_t var_syms[] = { - {"output", &qfv_output_t_type, &sctx->output}, - {"frames", &vulkan_frameset_t_type, &ctx->frames}, - {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, - {"physDevLimits", &VkPhysicalDeviceLimits_type, - &ctx->device->physDev->properties->limits }, - {} - }; - exprctx.external_variables = QFV_CreateSymtab (item, "properties", - extra_items, var_syms, - &exprctx); - - int ret; - if (!(ret = parse_qfv_renderinfo_t (0, item, ri, messages, &parsectx))) { - for (int i = 0; i < PL_A_NumObjects (messages); i++) { - Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); - } - } - QFV_DestroySymtab (exprctx.external_variables); - PL_Release (messages); - if (!ret) { - delete_memsuper (memsuper); - ri = 0; - } - - return ri; -} - struct qfv_jobinfo_s * QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) { @@ -2391,7 +2335,7 @@ QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) 0 }; exprsym_t var_syms[] = { - {"output", &qfv_output_t_type, &sctx->output}, + {"render_output", &qfv_output_t_type, &sctx->output}, {"frames", &vulkan_frameset_t_type, &ctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {"physDevLimits", &VkPhysicalDeviceLimits_type, diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index fcf547125..207fef028 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -83,9 +83,6 @@ exprtab_t *QFV_CreateSymtab (plitem_t *dict, const char *properties, void QFV_DestroySymtab (exprtab_t *tab); struct qfv_renderctx_s; -struct qfv_renderinfo_s *QFV_ParseRenderInfo (vulkan_ctx_t *ctx, - plitem_t *item, - struct qfv_renderctx_s *rctx); struct memsuper_s; int QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, struct memsuper_s *memsuper, exprtab_t *symtab, const char *ref, diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 4b84021ae..bab9ed226 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -635,28 +635,12 @@ parse = { qfv_renderinfo_s = { .name = qfv_renderinfo_t; color = auto; - properties = ignore; output = ignore; - images = { - type = (labeledarray, qfv_imageinfo_t, name); - size = num_images; - values = images; - }; - views = { - type = (labeledarray, qfv_imageviewinfo_t, name); - size = num_views; - values = views; - }; renderpasses = { type = (labeledarray, qfv_renderpassinfo_t, name); size = num_renderpasses; values = renderpasses; }; - descriptorSetLayouts = { - type = (labeledarray, qfv_descriptorsetinfo_t, name); - size = num_descriptorsets; - values = descriptorsets; - }; }; qfv_processinfo_s = { .name = qfv_processinfo_t; @@ -676,24 +660,44 @@ parse = { values = dependencies; }; render = { - type = (single, qfv_renderinfo_t); + type = (single, qfv_renderinfo_t, name); value = render; }; compute = { - type = (single, qfv_computeinfo_t); + type = (single, qfv_computeinfo_t, name); value = compute; }; process = { - type = (single, qfv_processinfo_t); + type = (single, qfv_processinfo_t, name); value = process; }; }; qfv_jobinfo_s = { .name = qfv_jobinfo_t; + properties = ignore; + output = ignore; + images = ignore; + views = ignore; + renderpasses = ignore; + images = { + type = (labeledarray, qfv_imageinfo_t, name); + size = num_images; + values = images; + }; + views = { + type = (labeledarray, qfv_imageviewinfo_t, name); + size = num_views; + values = views; + }; steps = { - type = (array, qfv_stepinfo_t); + type = (labeledarray, qfv_stepinfo_t, name); size = num_steps; values = steps; }; + descriptorSetLayouts = { + type = (labeledarray, qfv_descriptorsetinfo_t, name); + size = num_descriptorsets; + values = descriptorsets; + }; }; }; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index b6619d947..58b0b79cf 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -244,12 +244,47 @@ Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx) DARRAY_APPEND (&ctx->renderPasses, pre); } +static void +acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static void +_update_input (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static void +_output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static exprfunc_t acquire_output_func[] = { + { .func = acquire_output }, + {} +}; +static exprfunc_t update_input_func[] = { + { .func = _update_input }, + {} +}; +static exprfunc_t output_draw_func[] = { + { .func = _output_draw }, + {} +}; +static exprsym_t output_task_syms[] = { + { "acquire_output", &cexpr_function, acquire_output_func }, + { "update_input", &cexpr_function, update_input_func }, + { "output_draw", &cexpr_function, output_draw_func }, + {} +}; + void Vulkan_Output_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfvPushDebug (ctx, "output init"); + QFV_Render_AddTasks (ctx, output_task_syms); outputctx_t *octx = ctx->output_context; diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index d6f1a7a70..526eeb2e4 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -278,12 +278,32 @@ particles_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { } +static void +update_particles (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static void +particle_physics (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + static exprfunc_t particles_draw_func[] = { { .func = particles_draw }, {} }; +static exprfunc_t update_particles_func[] = { + { .func = update_particles }, + {} +}; +static exprfunc_t particle_physics_func[] = { + { .func = particle_physics }, + {} +}; static exprsym_t particles_task_syms[] = { { "particles_draw", &cexpr_function, particles_draw_func }, + { "update_particles", &cexpr_function, update_particles_func }, + { "particle_physics", &cexpr_function, particle_physics_func }, {} }; diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index 541485ea1..2cac52ee6 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -64,6 +64,20 @@ static const char * __attribute__((used)) translucent_pass_names[] = { "blend", }; +static void +clear_translucent (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ +} + +static exprfunc_t clear_translucent_func[] = { + { .func = clear_translucent }, + {} +}; +static exprsym_t translucent_task_syms[] = { + { "clear_translucent", &cexpr_function, clear_translucent_func }, + {} +}; + void Vulkan_Translucent_Init (vulkan_ctx_t *ctx) { @@ -73,6 +87,7 @@ Vulkan_Translucent_Init (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfvPushDebug (ctx, "translucent init"); + QFV_Render_AddTasks (ctx, translucent_task_syms); translucentctx_t *tctx = calloc (1, sizeof (translucentctx_t)); ctx->translucent_context = tctx; From 56344e478d10466bf495e709ae7c0729d8c4937a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 16:29:46 +0900 Subject: [PATCH 3517/3664] [simd] Improve portability for aarch64 No need for compiler flags for 64-bit arm, and the few intrinsics that are actually needed are in a different header. --- config.d/compiling.m4 | 64 ++++++++++++++++++++------------------ include/QF/simd/mat4f.h | 26 +++++++--------- include/QF/simd/types.h | 26 ---------------- include/QF/simd/vec2d.h | 8 +++++ include/QF/simd/vec2f.h | 8 +++++ include/QF/simd/vec2i.h | 8 ++--- include/QF/simd/vec4d.h | 4 +++ include/QF/simd/vec4f.h | 8 +++++ include/QF/simd/vec4i.h | 1 - tools/qfvis/source/qfvis.c | 7 ++--- 10 files changed, 80 insertions(+), 80 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 463dd8795..81cca85bf 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -98,37 +98,41 @@ AC_ARG_ENABLE(optimize, optimize=yes ) -AC_ARG_ENABLE(simd, - AS_HELP_STRING([--enable-simd@<:@=arg@:.@], - [enable SIMD support (default auto)]), - [], - [enable_simd=yes] -) +if test "x$host_cpu" = xaarch64; then + simd=neon +else + AC_ARG_ENABLE(simd, + AS_HELP_STRING([--enable-simd@<:@=arg@:.@], + [enable SIMD support (default auto)]), + [], + [enable_simd=yes] + ) -case "$enable_simd" in - no) - simd=no - ;; - sse|sse2|avx|avx2) - QF_CC_OPTION(-m$enable_simd) - simd=$enable_simd - ;; - yes) - for simd in avx2 avx sse2 sse; do - if lscpu | grep -q -w $simd; then - QF_CC_OPTION(-m$simd) - break - fi - done - ;; -esac -case "$simd" in - avx*) - ;; - *) - QF_CC_OPTION(-Wno-psabi) - ;; -esac + case "$enable_simd" in + no) + simd=no + ;; + sse|sse2|avx|avx2) + QF_CC_OPTION(-m$enable_simd) + simd=$enable_simd + ;; + yes) + for simd in avx2 avx sse2 sse; do + if lscpu | grep -q -w $simd; then + QF_CC_OPTION(-m$simd) + break + fi + done + ;; + esac + case "$simd" in + avx*) + ;; + *) + QF_CC_OPTION(-Wno-psabi) + ;; + esac +fi AC_MSG_CHECKING(for optimization) if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then diff --git a/include/QF/simd/mat4f.h b/include/QF/simd/mat4f.h index 981d71d22..ce061edd0 100644 --- a/include/QF/simd/mat4f.h +++ b/include/QF/simd/mat4f.h @@ -28,8 +28,6 @@ #ifndef __QF_simd_mat4f_h #define __QF_simd_mat4f_h -#include - #include "QF/simd/types.h" GNU89INLINE inline void maddf (mat4f_t c, const mat4f_t a, const mat4f_t b); @@ -172,27 +170,27 @@ mat4fquat (mat4f_t m, vec4f_t q) #undef m { vec4f_t a = xq; - vec4f_t b = _mm_xor_ps (shuff103 (yq), (__m128) mpm); - vec4f_t c = _mm_xor_ps (shuff230 (zq), (__m128) pmm); - vec4f_t d = _mm_xor_ps (shuff321 (wq), (__m128) mmp); + vec4f_t b = (vec4f_t) ((vec4i_t) shuff103 (yq) ^ mpm); + vec4f_t c = (vec4f_t) ((vec4i_t) shuff230 (zq) ^ pmm); + vec4f_t d = (vec4f_t) ((vec4i_t) shuff321 (wq) ^ mmp); // column: ww + xx - yy - zz // 2xy + 2wz // 2zx - 2wy // 0 - m[0] = _mm_and_ps (a + b - c - d, (__m128) mask); + m[0] = (vec4f_t) ((vec4i_t) (a + b - c - d) & mask); } { - vec4f_t a = _mm_xor_ps (shuff103 (xq), (__m128) mpm); + vec4f_t a = (vec4f_t) ((vec4i_t) shuff103 (xq) ^ mpm); vec4f_t b = yq; - vec4f_t c = _mm_xor_ps (shuff321 (zq), (__m128) mmp); - vec4f_t d = _mm_xor_ps (shuff230 (wq), (__m128) pmm); + vec4f_t c = (vec4f_t) ((vec4i_t) shuff321 (zq) ^ mmp); + vec4f_t d = (vec4f_t) ((vec4i_t) shuff230 (wq) ^ pmm); // column: 2xy - 2wz // ww - xx + yy - zz // 2yz + 2wx // 0 - m[1] = _mm_and_ps (b + c - a - d, (__m128) mask); + m[1] = (vec4f_t) ((vec4i_t) (b + c - a - d) & mask); } { - vec4f_t a = _mm_xor_ps (shuff230 (xq), (__m128) pmm); - vec4f_t b = _mm_xor_ps (shuff321 (yq), (__m128) mmp); + vec4f_t a = (vec4f_t) ((vec4i_t) shuff230 (xq) ^ pmm); + vec4f_t b = (vec4f_t) ((vec4i_t) shuff321 (yq) ^ mmp); vec4f_t c = zq; - vec4f_t d = _mm_xor_ps (shuff103 (wq), (__m128) mpm); + vec4f_t d = (vec4f_t) ((vec4i_t) shuff103 (wq) ^ mpm); // column: 2xz + 2wy // 2yz - 2wx // ww - xx - yy + zz // 0 - m[2] = _mm_and_ps (a - b + c - d, (__m128) mask); + m[2] = (vec4f_t) ((vec4i_t) (a - b + c - d) & mask); } m[3] = (vec4f_t) { 0, 0, 0, 1 }; } diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index 26aceccd0..c7c950fd0 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -105,30 +105,4 @@ typedef struct vspheref_s { float radius; } vspheref_t; -#include -#ifndef __SSE__ -#define _mm_xor_ps __qf_mm_xor_ps -#define _mm_and_ps __qf_mm_and_ps -GNU89INLINE inline __m128 _mm_xor_ps (__m128 a, __m128 b); -GNU89INLINE inline __m128 _mm_and_ps (__m128 a, __m128 b); -#ifndef IMPLEMENT_MAT4F_Funcs -GNU89INLINE inline -#else -VISIBLE -#endif -__m128 _mm_xor_ps (__m128 a, __m128 b) -{ - return (__m128) ((vec4i_t) a ^ (vec4i_t) b); -} -#ifndef IMPLEMENT_MAT4F_Funcs -GNU89INLINE inline -#else -VISIBLE -#endif -__m128 _mm_and_ps (__m128 a, __m128 b) -{ - return (__m128) ((vec4i_t) a & (vec4i_t) b); -} -#endif - #endif//__QF_simd_types_h diff --git a/include/QF/simd/vec2d.h b/include/QF/simd/vec2d.h index 86be9302b..25eb263bf 100644 --- a/include/QF/simd/vec2d.h +++ b/include/QF/simd/vec2d.h @@ -29,7 +29,11 @@ #ifndef __QF_simd_vec2d_h #define __QF_simd_vec2d_h +#ifdef __aarch64__ +#include +#else #include +#endif #include "QF/simd/types.h" @@ -50,7 +54,11 @@ VISIBLE vec2d_t vsqrt2d (vec2d_t v) { +#ifdef __aarch64__ + return vsqrtq_f64 (v); +#else return _mm_sqrt_pd (v); +#endif } #ifndef IMPLEMENT_VEC2D_Funcs diff --git a/include/QF/simd/vec2f.h b/include/QF/simd/vec2f.h index 1459dd37b..3dcc97ecc 100644 --- a/include/QF/simd/vec2f.h +++ b/include/QF/simd/vec2f.h @@ -29,7 +29,11 @@ #ifndef __QF_simd_vec2f_h #define __QF_simd_vec2f_h +#ifdef __aarch64__ +#include +#else #include +#endif #include #include "QF/simd/types.h" @@ -67,9 +71,13 @@ VISIBLE vec2f_t vsqrt2f (vec2f_t v) { +#ifdef __aarch64__ + return vsqrt_f32 (v); +#else vec4f_t t = { v[0], v[1], 0, 0 }; t = _mm_sqrt_ps (t); return (vec2f_t) { t[0], t[1] }; +#endif } #ifndef IMPLEMENT_VEC2F_Funcs diff --git a/include/QF/simd/vec2i.h b/include/QF/simd/vec2i.h index 29f2cc57c..0032e3e33 100644 --- a/include/QF/simd/vec2i.h +++ b/include/QF/simd/vec2i.h @@ -28,8 +28,6 @@ #ifndef __QF_simd_vec2i_h #define __QF_simd_vec2i_h -#include -#include #include "QF/simd/types.h" @@ -59,7 +57,7 @@ VISIBLE int any2i (vec2i_t v) { - vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); + vec2i_t t = v == (vec2i_t) {0, 0}; #ifndef __SSSE3__ return (t[0] + t[1]) > -2; #else @@ -75,7 +73,7 @@ VISIBLE int all2i (vec2i_t v) { - vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); + vec2i_t t = v == (vec2i_t) {0, 0}; #ifndef __SSSE3__ return (t[0] + t[1]) == 0; #else @@ -91,7 +89,7 @@ VISIBLE int none2i (vec2i_t v) { - vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); + vec2i_t t = v == (vec2i_t) {0, 0}; #ifndef __SSSE3__ return (t[0] + t[1]) == -2; #else diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 04e4b81a2..a56c70ab7 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -28,7 +28,11 @@ #ifndef __QF_simd_vec4d_h #define __QF_simd_vec4d_h +#ifdef __aarch64__ +#include +#else #include +#endif #include "QF/simd/types.h" #include "QF/simd/vec2d.h" diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index ee92d928e..effb32864 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -28,7 +28,11 @@ #ifndef __QF_simd_vec4f_h #define __QF_simd_vec4f_h +#ifdef __aarch64__ +#include +#else #include +#endif #include #include "QF/simd/types.h" @@ -121,12 +125,16 @@ VISIBLE vec4f_t vsqrt4f (vec4f_t v) { +#ifdef __aarch64__ + return vsqrtq_f32 (v); +#else #ifndef __SSE__ vec4f_t r = { sqrtf (v[0]), sqrtf (v[1]), sqrtf (v[2]), sqrtf (v[3]) }; return r; #else return _mm_sqrt_ps (v); #endif +#endif } #ifndef IMPLEMENT_VEC4F_Funcs diff --git a/include/QF/simd/vec4i.h b/include/QF/simd/vec4i.h index d3e4ac5dc..0e947a06a 100644 --- a/include/QF/simd/vec4i.h +++ b/include/QF/simd/vec4i.h @@ -28,7 +28,6 @@ #ifndef __QF_simd_vec4i_h #define __QF_simd_vec4i_h -#include #include #include "QF/simd/types.h" diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 2e64e9a0d..7630de93b 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -242,14 +242,13 @@ split_edge (const vec4f_t *points, const vec4f_t *dists, // "nan" because 0x7fffffff is nan when viewed as a float static const vec4i_t onenan = {0x3f800000,0x3f800000,0x3f800000,~0u >> 1}; static const vec4i_t nan = { ~0u >> 1, ~0u >> 1, ~0u >> 1, ~0u >> 1}; - vec4i_t x = _mm_and_ps (split, (__m128) nan) == (__m128) onenan; + vec4i_t x = ((vec4i_t) split & nan) == onenan; // plane vector has -dist in w - vec4f_t y = _mm_and_ps (split, (__m128) x) * -split[3]; + vec4f_t y = (vec4f_t) ((vec4i_t) split & x) * -split[3]; #ifdef __SSE3__ mid = _mm_blendv_ps (mid, y, (__m128) x); #else - mid = (vec4f_t) ((vec4i_t) _mm_and_ps (y, (__m128) x) | - (vec4i_t) _mm_and_ps (mid, (__m128) ~x)); + mid = (vec4f_t) (((vec4i_t) y & x) | ((vec4i_t) mid & ~x)); #endif // if (isnan (mid[0])) *(int *) 0 = 0; return mid; From ae9787228e008317210851f13a6104109ee2697b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 16:44:16 +0900 Subject: [PATCH 3518/3664] [util] Fix incorrect check for result of Qgetc Qgetc returns int, not char. Found via arm compile due to sign of bare char (or lack thereof). --- libs/util/quakeio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/quakeio.c b/libs/util/quakeio.c index f8e62df46..3de4d15b6 100644 --- a/libs/util/quakeio.c +++ b/libs/util/quakeio.c @@ -412,7 +412,7 @@ VISIBLE char * Qgets (QFile *file, char *buf, int count) { char *ret = buf; - char c; + int c; while (buf - ret < count - 1) { c = Qgetc (file); From b82174558b683ea1381972d983c39c1a3f59802a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 16:46:46 +0900 Subject: [PATCH 3519/3664] [gamecode] Fix a pile of UB in the test cases I always suspected the overflow conversions were UB, but with gcc doing different things on arm, I thought it was about time to abandon those particular tests. What I was not expecting was for the return value of strcmp to be "UB" (in that there's no guarantee of the exact value, just < = > 0). Fortunately, nothing actually relies on the value of the op other than the tests, so modify the test to make the behavior well defined. --- libs/gamecode/test/main.c | 4 ++-- libs/gamecode/test/test-conv0.c | 12 +++++------ libs/gamecode/test/test-conv2.c | 20 +++++++++--------- libs/gamecode/test/test-conv4.c | 28 ++++++++----------------- libs/gamecode/test/test-conv6.c | 35 +++++++++++++------------------- libs/gamecode/test/test-string.c | 8 ++++++-- 6 files changed, 46 insertions(+), 61 deletions(-) diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 6186c4ac9..4d4c31d1e 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -161,8 +161,8 @@ check_result (test_t *test) pr_ivec4_t *a = (pr_ivec4_t *) &test->expect_globals[i]; pr_ivec4_t *b = (pr_ivec4_t *) &test_pr.pr_globals[i]; if (memcmp (a, b, sizeof (pr_ivec4_t))) { - printf ("-%4x { %8x, %8x %8x %8x }\n", i, VEC4_EXP (*a)); - printf ("+%4x { %8x, %8x %8x %8x }\n", i, VEC4_EXP (*b)); + printf ("-%4x { %8x, %8x, %8x, %8x }\n", i, VEC4_EXP (*a)); + printf ("+%4x { %8x, %8x, %8x, %8x }\n", i, VEC4_EXP (*b)); } } } diff --git a/libs/gamecode/test/test-conv0.c b/libs/gamecode/test/test-conv0.c index 3b6e06359..d5153b5a4 100644 --- a/libs/gamecode/test/test-conv0.c +++ b/libs/gamecode/test/test-conv0.c @@ -4,11 +4,11 @@ static pr_ivec4_t int_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 0x3fc00000, 0xbfc00000, 0x40100000, 0xc0100000}, //float 1.5, -1.5, 2.25, -2.25 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x40020000, 0, 0xc0020000}, //double 2.25, -2.25 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -27,11 +27,11 @@ static pr_ivec4_t int_conv_init[] = { static pr_ivec4_t int_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 0x3fc00000, 0xbfc00000, 0x40100000, 0xc0100000}, //float 1.5, -1.5, 2.25, -2.25 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x40020000, 0, 0xc0020000}, //double 2.25, -2.25 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -39,9 +39,9 @@ static pr_ivec4_t int_conv_expect[] = { { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 { 5, -5, 0x80000000, 0x7fffffff}, // int - { 1, -1, 0x80000000, 0x80000000}, // float undef? + { 1, -1, 2, -2}, // float { 99, 0x80000000, 256, 0x7fffffff}, // long - { 0x80000000, 0x80000000, 1, -1}, // double undef? + { 1, -1, 2, -2}, // double { 5, -5, 0x80000000, 0x7fffffff}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong diff --git a/libs/gamecode/test/test-conv2.c b/libs/gamecode/test/test-conv2.c index 0dd4f5d41..647ea2ed4 100644 --- a/libs/gamecode/test/test-conv2.c +++ b/libs/gamecode/test/test-conv2.c @@ -4,11 +4,11 @@ static pr_ivec4_t long_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -35,11 +35,11 @@ static pr_ivec4_t long_conv_init[] = { static pr_ivec4_t long_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -48,12 +48,12 @@ static pr_ivec4_t long_conv_expect[] = { { 0, ~0, 0, 0}, //bool64 { 5, 0, -5, 0xffffffff}, // int { 0x80000000, 0xffffffff, 0x7fffffff, 0}, - { 1, 0, -1, -1}, // float - { 0, 0x80000000, 0, 0x80000000}, // undef? + { 1, 0, 2, 0}, // float + { 3, 0, 5, 0}, { 99, 0x80000000, 0x80000000, 99}, // long { 256, 0, 0x7fffffff, 0}, - { 0, 0x80000000, 0, 0x80000000}, // double undef? - { 1, 0, -1, -1}, + { 1, 0, 2, 0}, // double + { 3, 0, 5, 0}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool32 diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c index 35cc00979..ed455b02f 100644 --- a/libs/gamecode/test/test-conv4.c +++ b/libs/gamecode/test/test-conv4.c @@ -4,13 +4,11 @@ static pr_ivec4_t uint_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 - { 0x3fc00000, 0xbfc00000, 0, 0}, //float + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -27,23 +25,13 @@ static pr_ivec4_t uint_conv_init[] = { { 0, 0, 0, 0}, }; -/* Note that these tests (specifically 1, 3a and 3b) fail when compiled with - * clang and optimzing due to difference between clang and gcc, and more - * interestingly, within clang itself: with optimization enabled, the entries - * marked with "undef?" produce 0x80000000 instead of 0, but with optimization - * disabled, the expected 0 is produced. - * Inspecting the results, it seems that clang sets negative floats and doubles - * to 0 when casting to unsigned long, but not consistently. - */ static pr_ivec4_t uint_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float - { 0x3fc00000, 0xbfc00000, 0, 0}, //float + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -51,9 +39,9 @@ static pr_ivec4_t uint_conv_expect[] = { { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 { 5, -5, 0x80000000, 0x7fffffff}, // int - { 1, 0xffffffff, 0, 0}, // float undef? + { 1, 2, 3, 5}, // float { 99, 0x80000000, 256, 0x7fffffff}, // long - { 0, 0, 1, 0xffffffff}, // double undef? + { 1, 2, 3, 5}, // double { 5, -5, 0x80000000, 0x7fffffff}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c index 72f1c6b9f..5cfaab926 100644 --- a/libs/gamecode/test/test-conv6.c +++ b/libs/gamecode/test/test-conv6.c @@ -4,13 +4,11 @@ static pr_ivec4_t ulong_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 - { 0x3fc00000, 0xbfc00000, 0, 0}, //float 1e30, -1e30 + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -35,37 +33,32 @@ static pr_ivec4_t ulong_conv_init[] = { { 0, 0, 0, 0}, }; -/* Note that these tests fail when compiled with clang due to difference - * between clang and gcc. However, unlike test-conv4, the failure is - * consistent between optimized and unoptimized: all tests fail either way. - * Inspecting the results, it seems that clang sets negative floats and doubles - * to 0 when casting to unsigned long. - */ static pr_ivec4_t ulong_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 - { 0x3fc00000, 0xbfc00000, 0, 0}, //float 1e30, -1e30 + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong { 256, 0, 0x7fffffff, 0}, //ulong { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 + { 5, 0, -5, 0xffffffff}, // int { 0x80000000, 0xffffffff, 0x7fffffff, 0}, - { 1, 0, -1, -1}, // float - //XXX{ 0, 0, 0, 0x80000000}, // undef? - { 0, 0, 0, 0}, // undef? + { 1, 0, 2, 0}, // float + { 3, 0, 5, 0}, + { 99, 0x80000000, 0x80000000, 99}, // long { 256, 0, 0x7fffffff, 0}, - //XXX{ 0, 0, 0, 0x80000000}, // double undef? - { 0, 0, 0, 0}, // double undef? - { 1, 0, -1, -1}, + { 1, 0, 2, 0}, // double + { 3, 0, 5, 0}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool32 diff --git a/libs/gamecode/test/test-string.c b/libs/gamecode/test/test-string.c index ceb716570..955431d19 100644 --- a/libs/gamecode/test/test-string.c +++ b/libs/gamecode/test/test-string.c @@ -26,7 +26,7 @@ static pr_int_t string_globals_expect[] = { -1, 0, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, // eq 0, -1, -1, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, // lt 0, 0, 0, 0, -1, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, 0, // gt - 0,-97,-100,-97, 97, 0, -3, 0, 100, 3, 0, 3, 97, 0, -3, 0, // cmp + 0, -1, -1, -1, 1, 0, -1, 0, 1, 1, 0, 1, 1, 0, -1, 0, // cmp -1, 0, 0, 0, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, // ge -1, -1, -1, -1, 0, -1, -1, -1, 0, 0, -1, 0, 0, -1, -1, -1, // le -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // not @@ -59,18 +59,22 @@ static dstatement_t string_statements[] = { { OP(1, 2, 3, OP_LT_S), 0, 0, 16 }, { OP(1, 2, 3, OP_GT_S), 0, 0, 32 }, { OP(1, 2, 3, OP_CMP_S), 0, 0, 48 }, + { OP(3, 0, 0, OP_LT_I_1), 48, 0, 7 }, // convert < 0, 0, > 0 to -1, 0, 1 + { OP(3, 0, 3, OP_GT_I_1), 48, 0, 48 }, // ... + { OP(0, 3, 3, OP_SUB_I_1), 7, 48, 48 }, // ... { OP(1, 2, 3, OP_GE_S), 0, 0, 64 }, { OP(1, 2, 3, OP_LE_S), 0, 0, 80 }, { OP(1, 2, 3, OP_NOT_S), 0, 0, 96 }, // } - { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -16, 0, 0 }, // } }; test_t tests[] = { { .desc = "string", + .extra_globals = 4 * 1, .num_globals = num_globals (string_globals_init, string_globals_expect), .num_statements = num_statements (string_statements), .statements = string_statements, From 5f6c007c7c52db56892a831605edc501d719d5a2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 17:35:14 +0900 Subject: [PATCH 3520/3664] [util] Clean up some ULP errors in tests The problem with floating point in unit tests is, well, comparisons are finicky. --- libs/util/test/test-quat.c | 2 +- libs/util/test/test-simd.c | 40 +++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index 64a8cd75b..57e38f8dd 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -352,7 +352,7 @@ static struct { {0, 0, 1, 1, 0, 0, 0, 1, 0}}, -#if defined(__i686__) && defined(__OPTIMIZE__) +#if (defined(__i686__) || defined(__aarch64__)) && defined(__OPTIMIZE__) // the fp unit carries more precision than a 32-bit float, so // the close-to-zero errors are different {{s05, 0.0, 0.0, s05}, diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index 7cba48f3b..bc0c4c140 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -191,7 +191,11 @@ static vec4d_test_t vec4d_tests[] = { T(crossd, one, up, { 1, -1, 0} ), // This one fails when optimizing with -mfma (which is why fma is not // used): ulp errors in z and w - T(crossd, qtest, qtest, {0, 0, 0, 0} ), + T(crossd, qtest, qtest, {0, 0, 0, 0}, +#if defined(__aarch64__) + {0, 0, -2.1938006966593093e-17, 1.3322676295501878e-17}, +#endif + ), T(qmuld, qident, qident, qident ), T(qmuld, qident, right, right ), @@ -213,7 +217,11 @@ static vec4d_test_t vec4d_tests[] = { T(qmuld, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } ), // This one fails when optimizing with -mfma (which is why fma is not // used): ulp error in z - T(qmuld, qtest, qtest, {0.768, 0.576, 0, -0.28} ), + T(qmuld, qtest, qtest, {0.768, 0.576, 0, -0.28}, +#if defined(__aarch64__) + {0, 0, -2.1938006966593093e-17, 0}, +#endif + ), // The one vector is not unit (magnitude 2), so using it as a rotation // quaternion results in scaling by 4. However, it still has the effect @@ -316,12 +324,16 @@ static vec4f_test_t vec4f_tests[] = { T(crossf, one, right, { 0, 1, -1} ), T(crossf, one, forward, {-1, 0, 1} ), T(crossf, one, up, { 1, -1, 0} ), +#ifdef __aarch64__ + T(crossf, qtest, qtest, {0, 0, -1.47819534e-09, -1.43051153e-08} ), +#else #if !defined(__SSE__) && !defined(__OPTIMIZE__) // when not optimizing and SSE is not available (but ok when // optimizing) T(crossf, qtest, qtest, {0, 0, -1.47819534e-09, 0} ), #else T(crossf, qtest, qtest, {0, 0, 0, 0} ), +#endif #endif T(qmulf, qident, qident, qident ), @@ -343,14 +355,18 @@ static vec4f_test_t vec4f_tests[] = { T(qmulf, one, one, { 2, 2, 2, -2 } ), T(qmulf, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } ), T(qmulf, qtest, qtest, {0.768, 0.576, 0, -0.28}, +#ifdef __aarch64__ + {0, 6e-8, -1.47819534e-09, 2.98023224e-08} +#else #if !defined(__SSE__) && !defined(__OPTIMIZE__) // when not optimizing and SSE is not available (but ok when // optimizing) {0, 6e-8, -1.47819534e-09, 3e-8} -#elif !defined( __SSE__) +#elif !defined(__SSE__) {0, 6e-8, 0, 6e-8} #else {0, 6e-8, 0, 3e-8} +#endif #endif ), @@ -373,18 +389,18 @@ static vec4f_test_t vec4f_tests[] = { T(qvmulf, qtest, right, {0.5392, 0.6144, -0.576, 0}, {0, -5.9e-8, -6e-8, 0} ), T(qvmulf, qtest, forward, {0.6144, 0.1808, 0.768, 0}, -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +#if !(defined(__SSE__) || defined(__aarch64__)) && !defined(__OPTIMIZE__) {-5.9e-8, 0, 0, 0} -#elif !defined(__SSE__) +#elif !(defined(__SSE__) || defined(__aarch64__)) {-5.9e-8, 3e-8, 0, 0} #else {-5.9e-8, 1.5e-8, 0, 0} #endif ), T(qvmulf, qtest, up, {0.576, -0.768, -0.28, 0}, -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +#if !(defined(__SSE__) || defined(__aarch64__)) && !defined(__OPTIMIZE__) {6e-8, 0, 3e-8, 0} -#elif !defined(__SSE__) +#elif !(defined(__SSE__) || defined(__aarch64__)) {6e-8, 0, 6e-8, 0} #else {6e-8, 0, 3e-8, 0} @@ -393,18 +409,18 @@ static vec4f_test_t vec4f_tests[] = { T(vqmulf, right, qtest, {0.5392, 0.6144, 0.576, 0}, {0, -5.9e-8, 5.9e-8, 0} ), T(vqmulf, forward, qtest, {0.6144, 0.1808, -0.768, 0}, -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +#if !(defined(__SSE__) || defined(__aarch64__)) && !defined(__OPTIMIZE__) {-5.9e-8, 0, 0, 0} -#elif !defined(__SSE__) +#elif !(defined(__SSE__) || defined(__aarch64__)) {-5.9e-8, 3e-8, 0, 0} #else {-5.9e-8, 1.5e-8, 0, 0} #endif ), T(vqmulf, up, qtest, {-0.576, 0.768, -0.28, 0}, -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +#if !(defined(__SSE__) || defined(__aarch64__)) && !defined(__OPTIMIZE__) {-5.9e-8, 0, 3e-8, 0} -#elif !defined(__SSE__) +#elif !(defined(__SSE__) || defined(__aarch64__)) {-5.9e-8, 0, 6e-8, 0} #else {-5.9e-8, 0, 3e-8, 0} @@ -501,6 +517,7 @@ run_vec4d_tests (void) printf ("E: " VEC4D_FMT "\n", VEC4_EXP(expect)); printf ("e: " VEC4D_FMT "\n", VEC4_EXP(test->expect)); printf ("u: " VEC4D_FMT "\n", VEC4_EXP(test->ulp_errors)); + printf ("U: " VEC4D_FMT "\n", VEC4_EXP(result - test->expect)); } } return ret; @@ -526,6 +543,7 @@ run_vec4f_tests (void) printf ("E: " VEC4F_FMT "\n", VEC4_EXP(expect)); printf ("e: " VEC4F_FMT "\n", VEC4_EXP(test->expect)); printf ("u: " VEC4F_FMT "\n", VEC4_EXP(test->ulp_errors)); + printf ("U: " VEC4F_FMT "\n", VEC4_EXP(result - test->expect)); } } return ret; From 2dd3ea21825f3eaa22ffe6993ab31d96740c46c4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 18:39:46 +0900 Subject: [PATCH 3521/3664] [vulkan] Respect the VULKAN_SDK environment variable Thanks to Peter for the report and help in getting it working (I hope I got all the changes right). --- Makefile.am | 2 +- config.d/vulkan.m4 | 13 ++++++++++++- libs/video/renderer/vulkan/vkgen/Makemodule.am | 3 +-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 48847d9d2..5276ac096 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,7 @@ NOCONV_DIST= \ BUILT_SOURCES = $(top_srcdir)/.version #AM_CFLAGS= @PREFER_NON_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) $(FREETYPE_CFLAGS) $(HARFBUZZ_CFLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) $(FREETYPE_CFLAGS) $(HARFBUZZ_CFLAGS) $(VULKAN_CPPFLAGS) common_ldflags= -export-dynamic @STATIC@ @PTHREAD_LDFLAGS@ diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index e4a26581b..e175d1528 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -9,13 +9,24 @@ if test "x$HAVE_VULKAN" != xno; then LDFLAGS="$LDFLAGS -L$VULKAN_SDK/lib" glslangvalidator="$VULKAN_SDK/bin/glslangValidator" ], [glslangvalidator="glslangValidator"]) - AC_CHECK_HEADER([vulkan/vulkan.h], [HAVE_VULKAN=yes], [HAVE_VULKAN=no]) + AC_CHECK_HEADER([vulkan/vulkan.h], [ + HAVE_VULKAN=yes + AS_IF([test x"$VULKAN_SDK" != x], [ + VULKAN_CPPFLAGS="-I$VULKAN_SDK/include" + VULKAN_QCFLAGS="-I$VULKAN_SDK/include" + VULKAN_LDFLAGS="-L$VULKAN_SDK/lib" + ],[ + VULKAN_QCFLAGS="-I/usr/include" + ]) + ], [HAVE_VULKAN=no]) CPPFLAGS="$save_CPPFLAGS" fi if test "x$HAVE_VULKAN" = xyes; then AC_DEFINE([HAVE_VULKAN], [1], [Define if yhou have the Vulkan libs]) fi AC_SUBST(VULKAN_LIBS) +AC_SUBST(VULKAN_CPPFLAGS) +AC_SUBST(VULKAN_QCFLAGS) AC_SUBST(GLSLANGVALIDATOR, [$glslangvalidator]) AM_CONDITIONAL(X11_VULKAN, test "x$HAVE_VULKAN" = "xyes") diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index 8d8e11f4e..a96a627bc 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -21,8 +21,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vktype.r \ libs/video/renderer/vulkan/vkgen/vulkan.r -VKGENUSRINC = /usr/include -VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen -I$(VKGENUSRINC) +VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen $(VULKAN_QCFLAGS) vkgen_dat_SOURCES=$(vkgen_dat_src) vkgen_obj=$(vkgen_dat_SOURCES:.r=.o) From ef2793010c133709a5b28f77402807aaa6795a26 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 16:29:46 +0900 Subject: [PATCH 3522/3664] [simd] Improve portability for aarch64 No need for compiler flags for 64-bit arm, and the few intrinsics that are actually needed are in a different header. --- config.d/compiling.m4 | 64 ++++++++++++++++++++------------------ include/QF/simd/mat4f.h | 26 +++++++--------- include/QF/simd/types.h | 26 ---------------- include/QF/simd/vec2d.h | 8 +++++ include/QF/simd/vec2f.h | 8 +++++ include/QF/simd/vec2i.h | 8 ++--- include/QF/simd/vec4d.h | 4 +++ include/QF/simd/vec4f.h | 8 +++++ include/QF/simd/vec4i.h | 1 - tools/qfvis/source/qfvis.c | 7 ++--- 10 files changed, 80 insertions(+), 80 deletions(-) diff --git a/config.d/compiling.m4 b/config.d/compiling.m4 index 463dd8795..81cca85bf 100644 --- a/config.d/compiling.m4 +++ b/config.d/compiling.m4 @@ -98,37 +98,41 @@ AC_ARG_ENABLE(optimize, optimize=yes ) -AC_ARG_ENABLE(simd, - AS_HELP_STRING([--enable-simd@<:@=arg@:.@], - [enable SIMD support (default auto)]), - [], - [enable_simd=yes] -) +if test "x$host_cpu" = xaarch64; then + simd=neon +else + AC_ARG_ENABLE(simd, + AS_HELP_STRING([--enable-simd@<:@=arg@:.@], + [enable SIMD support (default auto)]), + [], + [enable_simd=yes] + ) -case "$enable_simd" in - no) - simd=no - ;; - sse|sse2|avx|avx2) - QF_CC_OPTION(-m$enable_simd) - simd=$enable_simd - ;; - yes) - for simd in avx2 avx sse2 sse; do - if lscpu | grep -q -w $simd; then - QF_CC_OPTION(-m$simd) - break - fi - done - ;; -esac -case "$simd" in - avx*) - ;; - *) - QF_CC_OPTION(-Wno-psabi) - ;; -esac + case "$enable_simd" in + no) + simd=no + ;; + sse|sse2|avx|avx2) + QF_CC_OPTION(-m$enable_simd) + simd=$enable_simd + ;; + yes) + for simd in avx2 avx sse2 sse; do + if lscpu | grep -q -w $simd; then + QF_CC_OPTION(-m$simd) + break + fi + done + ;; + esac + case "$simd" in + avx*) + ;; + *) + QF_CC_OPTION(-Wno-psabi) + ;; + esac +fi AC_MSG_CHECKING(for optimization) if test "x$optimize" = xyes -a "x$leave_cflags_alone" != "xyes"; then diff --git a/include/QF/simd/mat4f.h b/include/QF/simd/mat4f.h index 981d71d22..ce061edd0 100644 --- a/include/QF/simd/mat4f.h +++ b/include/QF/simd/mat4f.h @@ -28,8 +28,6 @@ #ifndef __QF_simd_mat4f_h #define __QF_simd_mat4f_h -#include - #include "QF/simd/types.h" GNU89INLINE inline void maddf (mat4f_t c, const mat4f_t a, const mat4f_t b); @@ -172,27 +170,27 @@ mat4fquat (mat4f_t m, vec4f_t q) #undef m { vec4f_t a = xq; - vec4f_t b = _mm_xor_ps (shuff103 (yq), (__m128) mpm); - vec4f_t c = _mm_xor_ps (shuff230 (zq), (__m128) pmm); - vec4f_t d = _mm_xor_ps (shuff321 (wq), (__m128) mmp); + vec4f_t b = (vec4f_t) ((vec4i_t) shuff103 (yq) ^ mpm); + vec4f_t c = (vec4f_t) ((vec4i_t) shuff230 (zq) ^ pmm); + vec4f_t d = (vec4f_t) ((vec4i_t) shuff321 (wq) ^ mmp); // column: ww + xx - yy - zz // 2xy + 2wz // 2zx - 2wy // 0 - m[0] = _mm_and_ps (a + b - c - d, (__m128) mask); + m[0] = (vec4f_t) ((vec4i_t) (a + b - c - d) & mask); } { - vec4f_t a = _mm_xor_ps (shuff103 (xq), (__m128) mpm); + vec4f_t a = (vec4f_t) ((vec4i_t) shuff103 (xq) ^ mpm); vec4f_t b = yq; - vec4f_t c = _mm_xor_ps (shuff321 (zq), (__m128) mmp); - vec4f_t d = _mm_xor_ps (shuff230 (wq), (__m128) pmm); + vec4f_t c = (vec4f_t) ((vec4i_t) shuff321 (zq) ^ mmp); + vec4f_t d = (vec4f_t) ((vec4i_t) shuff230 (wq) ^ pmm); // column: 2xy - 2wz // ww - xx + yy - zz // 2yz + 2wx // 0 - m[1] = _mm_and_ps (b + c - a - d, (__m128) mask); + m[1] = (vec4f_t) ((vec4i_t) (b + c - a - d) & mask); } { - vec4f_t a = _mm_xor_ps (shuff230 (xq), (__m128) pmm); - vec4f_t b = _mm_xor_ps (shuff321 (yq), (__m128) mmp); + vec4f_t a = (vec4f_t) ((vec4i_t) shuff230 (xq) ^ pmm); + vec4f_t b = (vec4f_t) ((vec4i_t) shuff321 (yq) ^ mmp); vec4f_t c = zq; - vec4f_t d = _mm_xor_ps (shuff103 (wq), (__m128) mpm); + vec4f_t d = (vec4f_t) ((vec4i_t) shuff103 (wq) ^ mpm); // column: 2xz + 2wy // 2yz - 2wx // ww - xx - yy + zz // 0 - m[2] = _mm_and_ps (a - b + c - d, (__m128) mask); + m[2] = (vec4f_t) ((vec4i_t) (a - b + c - d) & mask); } m[3] = (vec4f_t) { 0, 0, 0, 1 }; } diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index 26aceccd0..c7c950fd0 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -105,30 +105,4 @@ typedef struct vspheref_s { float radius; } vspheref_t; -#include -#ifndef __SSE__ -#define _mm_xor_ps __qf_mm_xor_ps -#define _mm_and_ps __qf_mm_and_ps -GNU89INLINE inline __m128 _mm_xor_ps (__m128 a, __m128 b); -GNU89INLINE inline __m128 _mm_and_ps (__m128 a, __m128 b); -#ifndef IMPLEMENT_MAT4F_Funcs -GNU89INLINE inline -#else -VISIBLE -#endif -__m128 _mm_xor_ps (__m128 a, __m128 b) -{ - return (__m128) ((vec4i_t) a ^ (vec4i_t) b); -} -#ifndef IMPLEMENT_MAT4F_Funcs -GNU89INLINE inline -#else -VISIBLE -#endif -__m128 _mm_and_ps (__m128 a, __m128 b) -{ - return (__m128) ((vec4i_t) a & (vec4i_t) b); -} -#endif - #endif//__QF_simd_types_h diff --git a/include/QF/simd/vec2d.h b/include/QF/simd/vec2d.h index 86be9302b..25eb263bf 100644 --- a/include/QF/simd/vec2d.h +++ b/include/QF/simd/vec2d.h @@ -29,7 +29,11 @@ #ifndef __QF_simd_vec2d_h #define __QF_simd_vec2d_h +#ifdef __aarch64__ +#include +#else #include +#endif #include "QF/simd/types.h" @@ -50,7 +54,11 @@ VISIBLE vec2d_t vsqrt2d (vec2d_t v) { +#ifdef __aarch64__ + return vsqrtq_f64 (v); +#else return _mm_sqrt_pd (v); +#endif } #ifndef IMPLEMENT_VEC2D_Funcs diff --git a/include/QF/simd/vec2f.h b/include/QF/simd/vec2f.h index 1459dd37b..3dcc97ecc 100644 --- a/include/QF/simd/vec2f.h +++ b/include/QF/simd/vec2f.h @@ -29,7 +29,11 @@ #ifndef __QF_simd_vec2f_h #define __QF_simd_vec2f_h +#ifdef __aarch64__ +#include +#else #include +#endif #include #include "QF/simd/types.h" @@ -67,9 +71,13 @@ VISIBLE vec2f_t vsqrt2f (vec2f_t v) { +#ifdef __aarch64__ + return vsqrt_f32 (v); +#else vec4f_t t = { v[0], v[1], 0, 0 }; t = _mm_sqrt_ps (t); return (vec2f_t) { t[0], t[1] }; +#endif } #ifndef IMPLEMENT_VEC2F_Funcs diff --git a/include/QF/simd/vec2i.h b/include/QF/simd/vec2i.h index 29f2cc57c..0032e3e33 100644 --- a/include/QF/simd/vec2i.h +++ b/include/QF/simd/vec2i.h @@ -28,8 +28,6 @@ #ifndef __QF_simd_vec2i_h #define __QF_simd_vec2i_h -#include -#include #include "QF/simd/types.h" @@ -59,7 +57,7 @@ VISIBLE int any2i (vec2i_t v) { - vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); + vec2i_t t = v == (vec2i_t) {0, 0}; #ifndef __SSSE3__ return (t[0] + t[1]) > -2; #else @@ -75,7 +73,7 @@ VISIBLE int all2i (vec2i_t v) { - vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); + vec2i_t t = v == (vec2i_t) {0, 0}; #ifndef __SSSE3__ return (t[0] + t[1]) == 0; #else @@ -91,7 +89,7 @@ VISIBLE int none2i (vec2i_t v) { - vec2i_t t = _m_pcmpeqd (v, (vec2i_t) {0, 0}); + vec2i_t t = v == (vec2i_t) {0, 0}; #ifndef __SSSE3__ return (t[0] + t[1]) == -2; #else diff --git a/include/QF/simd/vec4d.h b/include/QF/simd/vec4d.h index 04e4b81a2..a56c70ab7 100644 --- a/include/QF/simd/vec4d.h +++ b/include/QF/simd/vec4d.h @@ -28,7 +28,11 @@ #ifndef __QF_simd_vec4d_h #define __QF_simd_vec4d_h +#ifdef __aarch64__ +#include +#else #include +#endif #include "QF/simd/types.h" #include "QF/simd/vec2d.h" diff --git a/include/QF/simd/vec4f.h b/include/QF/simd/vec4f.h index ee92d928e..effb32864 100644 --- a/include/QF/simd/vec4f.h +++ b/include/QF/simd/vec4f.h @@ -28,7 +28,11 @@ #ifndef __QF_simd_vec4f_h #define __QF_simd_vec4f_h +#ifdef __aarch64__ +#include +#else #include +#endif #include #include "QF/simd/types.h" @@ -121,12 +125,16 @@ VISIBLE vec4f_t vsqrt4f (vec4f_t v) { +#ifdef __aarch64__ + return vsqrtq_f32 (v); +#else #ifndef __SSE__ vec4f_t r = { sqrtf (v[0]), sqrtf (v[1]), sqrtf (v[2]), sqrtf (v[3]) }; return r; #else return _mm_sqrt_ps (v); #endif +#endif } #ifndef IMPLEMENT_VEC4F_Funcs diff --git a/include/QF/simd/vec4i.h b/include/QF/simd/vec4i.h index d3e4ac5dc..0e947a06a 100644 --- a/include/QF/simd/vec4i.h +++ b/include/QF/simd/vec4i.h @@ -28,7 +28,6 @@ #ifndef __QF_simd_vec4i_h #define __QF_simd_vec4i_h -#include #include #include "QF/simd/types.h" diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 2e64e9a0d..7630de93b 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -242,14 +242,13 @@ split_edge (const vec4f_t *points, const vec4f_t *dists, // "nan" because 0x7fffffff is nan when viewed as a float static const vec4i_t onenan = {0x3f800000,0x3f800000,0x3f800000,~0u >> 1}; static const vec4i_t nan = { ~0u >> 1, ~0u >> 1, ~0u >> 1, ~0u >> 1}; - vec4i_t x = _mm_and_ps (split, (__m128) nan) == (__m128) onenan; + vec4i_t x = ((vec4i_t) split & nan) == onenan; // plane vector has -dist in w - vec4f_t y = _mm_and_ps (split, (__m128) x) * -split[3]; + vec4f_t y = (vec4f_t) ((vec4i_t) split & x) * -split[3]; #ifdef __SSE3__ mid = _mm_blendv_ps (mid, y, (__m128) x); #else - mid = (vec4f_t) ((vec4i_t) _mm_and_ps (y, (__m128) x) | - (vec4i_t) _mm_and_ps (mid, (__m128) ~x)); + mid = (vec4f_t) (((vec4i_t) y & x) | ((vec4i_t) mid & ~x)); #endif // if (isnan (mid[0])) *(int *) 0 = 0; return mid; From a058cff59f80cfa06af9de7f341ede55088cc83a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 16:44:16 +0900 Subject: [PATCH 3523/3664] [util] Fix incorrect check for result of Qgetc Qgetc returns int, not char. Found via arm compile due to sign of bare char (or lack thereof). --- libs/util/quakeio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/quakeio.c b/libs/util/quakeio.c index f8e62df46..3de4d15b6 100644 --- a/libs/util/quakeio.c +++ b/libs/util/quakeio.c @@ -412,7 +412,7 @@ VISIBLE char * Qgets (QFile *file, char *buf, int count) { char *ret = buf; - char c; + int c; while (buf - ret < count - 1) { c = Qgetc (file); From f18837f1955372b9fa0cb59fcd2cedb0e9d84f8f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 16:46:46 +0900 Subject: [PATCH 3524/3664] [gamecode] Fix a pile of UB in the test cases I always suspected the overflow conversions were UB, but with gcc doing different things on arm, I thought it was about time to abandon those particular tests. What I was not expecting was for the return value of strcmp to be "UB" (in that there's no guarantee of the exact value, just < = > 0). Fortunately, nothing actually relies on the value of the op other than the tests, so modify the test to make the behavior well defined. --- libs/gamecode/test/main.c | 4 ++-- libs/gamecode/test/test-conv0.c | 12 +++++------ libs/gamecode/test/test-conv2.c | 20 +++++++++--------- libs/gamecode/test/test-conv4.c | 28 ++++++++----------------- libs/gamecode/test/test-conv6.c | 35 +++++++++++++------------------- libs/gamecode/test/test-string.c | 8 ++++++-- 6 files changed, 46 insertions(+), 61 deletions(-) diff --git a/libs/gamecode/test/main.c b/libs/gamecode/test/main.c index 6186c4ac9..4d4c31d1e 100644 --- a/libs/gamecode/test/main.c +++ b/libs/gamecode/test/main.c @@ -161,8 +161,8 @@ check_result (test_t *test) pr_ivec4_t *a = (pr_ivec4_t *) &test->expect_globals[i]; pr_ivec4_t *b = (pr_ivec4_t *) &test_pr.pr_globals[i]; if (memcmp (a, b, sizeof (pr_ivec4_t))) { - printf ("-%4x { %8x, %8x %8x %8x }\n", i, VEC4_EXP (*a)); - printf ("+%4x { %8x, %8x %8x %8x }\n", i, VEC4_EXP (*b)); + printf ("-%4x { %8x, %8x, %8x, %8x }\n", i, VEC4_EXP (*a)); + printf ("+%4x { %8x, %8x, %8x, %8x }\n", i, VEC4_EXP (*b)); } } } diff --git a/libs/gamecode/test/test-conv0.c b/libs/gamecode/test/test-conv0.c index 3b6e06359..d5153b5a4 100644 --- a/libs/gamecode/test/test-conv0.c +++ b/libs/gamecode/test/test-conv0.c @@ -4,11 +4,11 @@ static pr_ivec4_t int_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 0x3fc00000, 0xbfc00000, 0x40100000, 0xc0100000}, //float 1.5, -1.5, 2.25, -2.25 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x40020000, 0, 0xc0020000}, //double 2.25, -2.25 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -27,11 +27,11 @@ static pr_ivec4_t int_conv_init[] = { static pr_ivec4_t int_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 0x3fc00000, 0xbfc00000, 0x40100000, 0xc0100000}, //float 1.5, -1.5, 2.25, -2.25 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x40020000, 0, 0xc0020000}, //double 2.25, -2.25 { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -39,9 +39,9 @@ static pr_ivec4_t int_conv_expect[] = { { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 { 5, -5, 0x80000000, 0x7fffffff}, // int - { 1, -1, 0x80000000, 0x80000000}, // float undef? + { 1, -1, 2, -2}, // float { 99, 0x80000000, 256, 0x7fffffff}, // long - { 0x80000000, 0x80000000, 1, -1}, // double undef? + { 1, -1, 2, -2}, // double { 5, -5, 0x80000000, 0x7fffffff}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong diff --git a/libs/gamecode/test/test-conv2.c b/libs/gamecode/test/test-conv2.c index 0dd4f5d41..647ea2ed4 100644 --- a/libs/gamecode/test/test-conv2.c +++ b/libs/gamecode/test/test-conv2.c @@ -4,11 +4,11 @@ static pr_ivec4_t long_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -35,11 +35,11 @@ static pr_ivec4_t long_conv_init[] = { static pr_ivec4_t long_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - { 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - { 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -48,12 +48,12 @@ static pr_ivec4_t long_conv_expect[] = { { 0, ~0, 0, 0}, //bool64 { 5, 0, -5, 0xffffffff}, // int { 0x80000000, 0xffffffff, 0x7fffffff, 0}, - { 1, 0, -1, -1}, // float - { 0, 0x80000000, 0, 0x80000000}, // undef? + { 1, 0, 2, 0}, // float + { 3, 0, 5, 0}, { 99, 0x80000000, 0x80000000, 99}, // long { 256, 0, 0x7fffffff, 0}, - { 0, 0x80000000, 0, 0x80000000}, // double undef? - { 1, 0, -1, -1}, + { 1, 0, 2, 0}, // double + { 3, 0, 5, 0}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool32 diff --git a/libs/gamecode/test/test-conv4.c b/libs/gamecode/test/test-conv4.c index 35cc00979..ed455b02f 100644 --- a/libs/gamecode/test/test-conv4.c +++ b/libs/gamecode/test/test-conv4.c @@ -4,13 +4,11 @@ static pr_ivec4_t uint_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 - { 0x3fc00000, 0xbfc00000, 0, 0}, //float + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -27,23 +25,13 @@ static pr_ivec4_t uint_conv_init[] = { { 0, 0, 0, 0}, }; -/* Note that these tests (specifically 1, 3a and 3b) fail when compiled with - * clang and optimzing due to difference between clang and gcc, and more - * interestingly, within clang itself: with optimization enabled, the entries - * marked with "undef?" produce 0x80000000 instead of 0, but with optimization - * disabled, the expected 0 is produced. - * Inspecting the results, it seems that clang sets negative floats and doubles - * to 0 when casting to unsigned long, but not consistently. - */ static pr_ivec4_t uint_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float - { 0x3fc00000, 0xbfc00000, 0, 0}, //float + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -51,9 +39,9 @@ static pr_ivec4_t uint_conv_expect[] = { { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 { 5, -5, 0x80000000, 0x7fffffff}, // int - { 1, 0xffffffff, 0, 0}, // float undef? + { 1, 2, 3, 5}, // float { 99, 0x80000000, 256, 0x7fffffff}, // long - { 0, 0, 1, 0xffffffff}, // double undef? + { 1, 2, 3, 5}, // double { 5, -5, 0x80000000, 0x7fffffff}, // uint { 1, 1, 1, 0}, // bool32 { 99, 0x80000000, 256, 0x7fffffff}, // ulong diff --git a/libs/gamecode/test/test-conv6.c b/libs/gamecode/test/test-conv6.c index 72f1c6b9f..5cfaab926 100644 --- a/libs/gamecode/test/test-conv6.c +++ b/libs/gamecode/test/test-conv6.c @@ -4,13 +4,11 @@ static pr_ivec4_t ulong_conv_init[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int - //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 - { 0x3fc00000, 0xbfc00000, 0, 0}, //float 1e30, -1e30 + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 { 99, 0x80000000, 0x80000000, 99}, //ulong @@ -35,37 +33,32 @@ static pr_ivec4_t ulong_conv_init[] = { { 0, 0, 0, 0}, }; -/* Note that these tests fail when compiled with clang due to difference - * between clang and gcc. However, unlike test-conv4, the failure is - * consistent between optimized and unoptimized: all tests fail either way. - * Inspecting the results, it seems that clang sets negative floats and doubles - * to 0 when casting to unsigned long. - */ static pr_ivec4_t ulong_conv_expect[] = { { 5, -5, 0x80000000, 0x7fffffff}, //int //XXX{ 0x3fc00000, 0xbfc00000, 0x7149f2ca, 0xf149f2ca}, //float 1e30, -1e30 - { 0x3fc00000, 0xbfc00000, 0, 0}, //float 1e30, -1e30 + { 0x3fc00000, 0x40100000, 0x40700000, 0x40a00000}, //float 1.5, 2.25, 3.75, 5 { 99, 0x80000000, 0x80000000, 99}, //long { 256, 0, 0x7fffffff, 0}, //long - //XXX{ 0x39a08cea, 0x46293e59, 0x39a08cea, 0xc6293e59}, //double 1e30, -1e30 - { 0, 0, 0, 0}, //double 1e30, -1e30 - { 0, 0x3ff80000, 0, 0xbff80000}, //double 1.5, -1.5 + + { 0, 0x3ff80000, 0, 0x40020000}, //double 1.5, 2.25, 3.75, 5 + { 0, 0x400e0000, 0, 0x40140000}, { 5, -5, 0x80000000, 0x7fffffff}, //uint { ~0, 1, 0x80000000, 0}, //bool32 + { 99, 0x80000000, 0x80000000, 99}, //ulong { 256, 0, 0x7fffffff, 0}, //ulong { ~0, ~0, ~0, 0}, //bool64 { 0, ~0, 0, 0}, //bool64 + { 5, 0, -5, 0xffffffff}, // int { 0x80000000, 0xffffffff, 0x7fffffff, 0}, - { 1, 0, -1, -1}, // float - //XXX{ 0, 0, 0, 0x80000000}, // undef? - { 0, 0, 0, 0}, // undef? + { 1, 0, 2, 0}, // float + { 3, 0, 5, 0}, + { 99, 0x80000000, 0x80000000, 99}, // long { 256, 0, 0x7fffffff, 0}, - //XXX{ 0, 0, 0, 0x80000000}, // double undef? - { 0, 0, 0, 0}, // double undef? - { 1, 0, -1, -1}, + { 1, 0, 2, 0}, // double + { 3, 0, 5, 0}, { 5, 0, -5, 0}, // uint { 0x80000000, 0, 0x7fffffff, 0}, { 1, 0, 1, 0}, // bool32 diff --git a/libs/gamecode/test/test-string.c b/libs/gamecode/test/test-string.c index ceb716570..955431d19 100644 --- a/libs/gamecode/test/test-string.c +++ b/libs/gamecode/test/test-string.c @@ -26,7 +26,7 @@ static pr_int_t string_globals_expect[] = { -1, 0, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, -1, 0, -1, // eq 0, -1, -1, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, // lt 0, 0, 0, 0, -1, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, 0, // gt - 0,-97,-100,-97, 97, 0, -3, 0, 100, 3, 0, 3, 97, 0, -3, 0, // cmp + 0, -1, -1, -1, 1, 0, -1, 0, 1, 1, 0, 1, 1, 0, -1, 0, // cmp -1, 0, 0, 0, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, // ge -1, -1, -1, -1, 0, -1, -1, -1, 0, 0, -1, 0, 0, -1, -1, -1, // le -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // not @@ -59,18 +59,22 @@ static dstatement_t string_statements[] = { { OP(1, 2, 3, OP_LT_S), 0, 0, 16 }, { OP(1, 2, 3, OP_GT_S), 0, 0, 32 }, { OP(1, 2, 3, OP_CMP_S), 0, 0, 48 }, + { OP(3, 0, 0, OP_LT_I_1), 48, 0, 7 }, // convert < 0, 0, > 0 to -1, 0, 1 + { OP(3, 0, 3, OP_GT_I_1), 48, 0, 48 }, // ... + { OP(0, 3, 3, OP_SUB_I_1), 7, 48, 48 }, // ... { OP(1, 2, 3, OP_GE_S), 0, 0, 64 }, { OP(1, 2, 3, OP_LE_S), 0, 0, 80 }, { OP(1, 2, 3, OP_NOT_S), 0, 0, 96 }, // } - { OP(0, 0, 0, OP_JUMP_A), -13, 0, 0 }, + { OP(0, 0, 0, OP_JUMP_A), -16, 0, 0 }, // } }; test_t tests[] = { { .desc = "string", + .extra_globals = 4 * 1, .num_globals = num_globals (string_globals_init, string_globals_expect), .num_statements = num_statements (string_statements), .statements = string_statements, From f098bbf48b8a0c845f91acf75fdd50cb3d1fe36a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 17:35:14 +0900 Subject: [PATCH 3525/3664] [util] Clean up some ULP errors in tests The problem with floating point in unit tests is, well, comparisons are finicky. --- libs/util/test/test-quat.c | 2 +- libs/util/test/test-simd.c | 40 +++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/libs/util/test/test-quat.c b/libs/util/test/test-quat.c index 64a8cd75b..57e38f8dd 100644 --- a/libs/util/test/test-quat.c +++ b/libs/util/test/test-quat.c @@ -352,7 +352,7 @@ static struct { {0, 0, 1, 1, 0, 0, 0, 1, 0}}, -#if defined(__i686__) && defined(__OPTIMIZE__) +#if (defined(__i686__) || defined(__aarch64__)) && defined(__OPTIMIZE__) // the fp unit carries more precision than a 32-bit float, so // the close-to-zero errors are different {{s05, 0.0, 0.0, s05}, diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index 7cba48f3b..bc0c4c140 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -191,7 +191,11 @@ static vec4d_test_t vec4d_tests[] = { T(crossd, one, up, { 1, -1, 0} ), // This one fails when optimizing with -mfma (which is why fma is not // used): ulp errors in z and w - T(crossd, qtest, qtest, {0, 0, 0, 0} ), + T(crossd, qtest, qtest, {0, 0, 0, 0}, +#if defined(__aarch64__) + {0, 0, -2.1938006966593093e-17, 1.3322676295501878e-17}, +#endif + ), T(qmuld, qident, qident, qident ), T(qmuld, qident, right, right ), @@ -213,7 +217,11 @@ static vec4d_test_t vec4d_tests[] = { T(qmuld, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } ), // This one fails when optimizing with -mfma (which is why fma is not // used): ulp error in z - T(qmuld, qtest, qtest, {0.768, 0.576, 0, -0.28} ), + T(qmuld, qtest, qtest, {0.768, 0.576, 0, -0.28}, +#if defined(__aarch64__) + {0, 0, -2.1938006966593093e-17, 0}, +#endif + ), // The one vector is not unit (magnitude 2), so using it as a rotation // quaternion results in scaling by 4. However, it still has the effect @@ -316,12 +324,16 @@ static vec4f_test_t vec4f_tests[] = { T(crossf, one, right, { 0, 1, -1} ), T(crossf, one, forward, {-1, 0, 1} ), T(crossf, one, up, { 1, -1, 0} ), +#ifdef __aarch64__ + T(crossf, qtest, qtest, {0, 0, -1.47819534e-09, -1.43051153e-08} ), +#else #if !defined(__SSE__) && !defined(__OPTIMIZE__) // when not optimizing and SSE is not available (but ok when // optimizing) T(crossf, qtest, qtest, {0, 0, -1.47819534e-09, 0} ), #else T(crossf, qtest, qtest, {0, 0, 0, 0} ), +#endif #endif T(qmulf, qident, qident, qident ), @@ -343,14 +355,18 @@ static vec4f_test_t vec4f_tests[] = { T(qmulf, one, one, { 2, 2, 2, -2 } ), T(qmulf, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } ), T(qmulf, qtest, qtest, {0.768, 0.576, 0, -0.28}, +#ifdef __aarch64__ + {0, 6e-8, -1.47819534e-09, 2.98023224e-08} +#else #if !defined(__SSE__) && !defined(__OPTIMIZE__) // when not optimizing and SSE is not available (but ok when // optimizing) {0, 6e-8, -1.47819534e-09, 3e-8} -#elif !defined( __SSE__) +#elif !defined(__SSE__) {0, 6e-8, 0, 6e-8} #else {0, 6e-8, 0, 3e-8} +#endif #endif ), @@ -373,18 +389,18 @@ static vec4f_test_t vec4f_tests[] = { T(qvmulf, qtest, right, {0.5392, 0.6144, -0.576, 0}, {0, -5.9e-8, -6e-8, 0} ), T(qvmulf, qtest, forward, {0.6144, 0.1808, 0.768, 0}, -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +#if !(defined(__SSE__) || defined(__aarch64__)) && !defined(__OPTIMIZE__) {-5.9e-8, 0, 0, 0} -#elif !defined(__SSE__) +#elif !(defined(__SSE__) || defined(__aarch64__)) {-5.9e-8, 3e-8, 0, 0} #else {-5.9e-8, 1.5e-8, 0, 0} #endif ), T(qvmulf, qtest, up, {0.576, -0.768, -0.28, 0}, -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +#if !(defined(__SSE__) || defined(__aarch64__)) && !defined(__OPTIMIZE__) {6e-8, 0, 3e-8, 0} -#elif !defined(__SSE__) +#elif !(defined(__SSE__) || defined(__aarch64__)) {6e-8, 0, 6e-8, 0} #else {6e-8, 0, 3e-8, 0} @@ -393,18 +409,18 @@ static vec4f_test_t vec4f_tests[] = { T(vqmulf, right, qtest, {0.5392, 0.6144, 0.576, 0}, {0, -5.9e-8, 5.9e-8, 0} ), T(vqmulf, forward, qtest, {0.6144, 0.1808, -0.768, 0}, -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +#if !(defined(__SSE__) || defined(__aarch64__)) && !defined(__OPTIMIZE__) {-5.9e-8, 0, 0, 0} -#elif !defined(__SSE__) +#elif !(defined(__SSE__) || defined(__aarch64__)) {-5.9e-8, 3e-8, 0, 0} #else {-5.9e-8, 1.5e-8, 0, 0} #endif ), T(vqmulf, up, qtest, {-0.576, 0.768, -0.28, 0}, -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +#if !(defined(__SSE__) || defined(__aarch64__)) && !defined(__OPTIMIZE__) {-5.9e-8, 0, 3e-8, 0} -#elif !defined(__SSE__) +#elif !(defined(__SSE__) || defined(__aarch64__)) {-5.9e-8, 0, 6e-8, 0} #else {-5.9e-8, 0, 3e-8, 0} @@ -501,6 +517,7 @@ run_vec4d_tests (void) printf ("E: " VEC4D_FMT "\n", VEC4_EXP(expect)); printf ("e: " VEC4D_FMT "\n", VEC4_EXP(test->expect)); printf ("u: " VEC4D_FMT "\n", VEC4_EXP(test->ulp_errors)); + printf ("U: " VEC4D_FMT "\n", VEC4_EXP(result - test->expect)); } } return ret; @@ -526,6 +543,7 @@ run_vec4f_tests (void) printf ("E: " VEC4F_FMT "\n", VEC4_EXP(expect)); printf ("e: " VEC4F_FMT "\n", VEC4_EXP(test->expect)); printf ("u: " VEC4F_FMT "\n", VEC4_EXP(test->ulp_errors)); + printf ("U: " VEC4F_FMT "\n", VEC4_EXP(result - test->expect)); } } return ret; From 86f2df4939b5ab00fb853c337dd12e713d9369b2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 18:39:46 +0900 Subject: [PATCH 3526/3664] [vulkan] Respect the VULKAN_SDK environment variable Thanks to Peter for the report and help in getting it working (I hope I got all the changes right). --- Makefile.am | 2 +- config.d/vulkan.m4 | 13 ++++++++++++- libs/video/renderer/vulkan/vkgen/Makemodule.am | 3 +-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index 48847d9d2..5276ac096 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,7 @@ NOCONV_DIST= \ BUILT_SOURCES = $(top_srcdir)/.version #AM_CFLAGS= @PREFER_NON_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) $(FREETYPE_CFLAGS) $(HARFBUZZ_CFLAGS) +AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) $(FREETYPE_CFLAGS) $(HARFBUZZ_CFLAGS) $(VULKAN_CPPFLAGS) common_ldflags= -export-dynamic @STATIC@ @PTHREAD_LDFLAGS@ diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index e4a26581b..e175d1528 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -9,13 +9,24 @@ if test "x$HAVE_VULKAN" != xno; then LDFLAGS="$LDFLAGS -L$VULKAN_SDK/lib" glslangvalidator="$VULKAN_SDK/bin/glslangValidator" ], [glslangvalidator="glslangValidator"]) - AC_CHECK_HEADER([vulkan/vulkan.h], [HAVE_VULKAN=yes], [HAVE_VULKAN=no]) + AC_CHECK_HEADER([vulkan/vulkan.h], [ + HAVE_VULKAN=yes + AS_IF([test x"$VULKAN_SDK" != x], [ + VULKAN_CPPFLAGS="-I$VULKAN_SDK/include" + VULKAN_QCFLAGS="-I$VULKAN_SDK/include" + VULKAN_LDFLAGS="-L$VULKAN_SDK/lib" + ],[ + VULKAN_QCFLAGS="-I/usr/include" + ]) + ], [HAVE_VULKAN=no]) CPPFLAGS="$save_CPPFLAGS" fi if test "x$HAVE_VULKAN" = xyes; then AC_DEFINE([HAVE_VULKAN], [1], [Define if yhou have the Vulkan libs]) fi AC_SUBST(VULKAN_LIBS) +AC_SUBST(VULKAN_CPPFLAGS) +AC_SUBST(VULKAN_QCFLAGS) AC_SUBST(GLSLANGVALIDATOR, [$glslangvalidator]) AM_CONDITIONAL(X11_VULKAN, test "x$HAVE_VULKAN" = "xyes") diff --git a/libs/video/renderer/vulkan/vkgen/Makemodule.am b/libs/video/renderer/vulkan/vkgen/Makemodule.am index dd2d82a63..8bec1de68 100644 --- a/libs/video/renderer/vulkan/vkgen/Makemodule.am +++ b/libs/video/renderer/vulkan/vkgen/Makemodule.am @@ -25,8 +25,7 @@ vkgen_dat_src= \ libs/video/renderer/vulkan/vkgen/vktype.r \ libs/video/renderer/vulkan/vkgen/vulkan.r -VKGENUSRINC = /usr/include -VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen -I$(VKGENUSRINC) +VKGENFLAGS = -I$(top_srcdir)/libs/video/renderer/vulkan/vkgen $(VULKAN_QCFLAGS) vkgen_dat_SOURCES=$(vkgen_dat_src) vkgen_obj=$(vkgen_dat_SOURCES:.r=.o) From c59840683d1824f60a058f701de654d8d70dcee3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 21:31:24 +0900 Subject: [PATCH 3527/3664] [plist] Use correct attribute for pl_error Because mxe builds need gnu_printf instead of printf, need to use PRINTF. I had forgotten that. --- libs/util/plist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/util/plist.c b/libs/util/plist.c index 07a1faf6e..2c985f601 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -577,7 +577,7 @@ PL_RemoveObjectAtIndex (plitem_t *array, int index) item->users--; } -static void __attribute__((format(printf, 2, 3))) +static void __attribute__((format(PRINTF, 2, 3))) pl_error (pldata_t *pl, const char *fmt, ...) { if (!pl->errmsg) { From a8efde1dd3b0b802d1a8a15e01338cd44410f16a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 21:36:45 +0900 Subject: [PATCH 3528/3664] Fix some mxe build issues --- config.d/vulkan.m4 | 2 +- libs/ecs/entity.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- tools/cross/mingw/cross-configure.sh | 1 + tools/cross/mingw64/cross-configure.sh | 2 ++ 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index e175d1528..c5baba273 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -16,7 +16,7 @@ if test "x$HAVE_VULKAN" != xno; then VULKAN_QCFLAGS="-I$VULKAN_SDK/include" VULKAN_LDFLAGS="-L$VULKAN_SDK/lib" ],[ - VULKAN_QCFLAGS="-I/usr/include" + VULKAN_QCFLAGS="-I${QCSYSPREFIX-/usr}/include" ]) ], [HAVE_VULKAN=no]) CPPFLAGS="$save_CPPFLAGS" diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index 5fb7a395b..1fd315538 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -126,7 +126,7 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) // if ind >= the last range, then it is outside the subpools if (range_count && ind < subpool->ranges[range_count - 1]) { uint32_t *range = find_range (subpool, ind); - while (range - subpool->ranges < range_count) { + while ((size_t) (range - subpool->ranges) < range_count) { uint32_t end = --*range; range++; if (ind < end) { diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index deaafb716..20e865b5f 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -72,7 +72,7 @@ #include "r_internal.h" #include "vid_vulkan.h" -static const char *draw_pass_names[] = { +static const char * __attribute__((used)) draw_pass_names[] = { "2d", }; diff --git a/tools/cross/mingw/cross-configure.sh b/tools/cross/mingw/cross-configure.sh index aae082435..869ec4851 100755 --- a/tools/cross/mingw/cross-configure.sh +++ b/tools/cross/mingw/cross-configure.sh @@ -14,6 +14,7 @@ export MINGW_USR=$MINGW/usr/i686-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH +export QCSYSPREFIX=$MINGW_USR ../../configure \ --host=i686-w64-mingw32.static \ --disable-shared \ diff --git a/tools/cross/mingw64/cross-configure.sh b/tools/cross/mingw64/cross-configure.sh index 7a886f631..f1945d685 100755 --- a/tools/cross/mingw64/cross-configure.sh +++ b/tools/cross/mingw64/cross-configure.sh @@ -5,6 +5,7 @@ cd native ../../configure \ --enable-silent-rules \ --disable-shared \ + --disable-optimize \ --without-clients \ --without-servers \ --with-tools=qfcc,pak,qwaq @@ -14,6 +15,7 @@ export MINGW_USR=$MINGW/usr/x86_64-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH +export QCSYSPREFIX=$MINGW_USR ../../configure \ --host=x86_64-w64-mingw32.static \ --disable-shared \ From c3558091ac738179a2cc5d01b48ab84bffc41d9c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 25 Mar 2023 21:36:45 +0900 Subject: [PATCH 3529/3664] Fix some mxe build issues --- config.d/vulkan.m4 | 2 +- libs/ecs/entity.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- tools/cross/mingw/cross-configure.sh | 1 + tools/cross/mingw64/cross-configure.sh | 2 ++ 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index e175d1528..c5baba273 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -16,7 +16,7 @@ if test "x$HAVE_VULKAN" != xno; then VULKAN_QCFLAGS="-I$VULKAN_SDK/include" VULKAN_LDFLAGS="-L$VULKAN_SDK/lib" ],[ - VULKAN_QCFLAGS="-I/usr/include" + VULKAN_QCFLAGS="-I${QCSYSPREFIX-/usr}/include" ]) ], [HAVE_VULKAN=no]) CPPFLAGS="$save_CPPFLAGS" diff --git a/libs/ecs/entity.c b/libs/ecs/entity.c index a5fc3112f..a2d337ed4 100644 --- a/libs/ecs/entity.c +++ b/libs/ecs/entity.c @@ -120,7 +120,7 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry) if (subpool->num_ranges - subpool->available) { uint32_t range_count = subpool->num_ranges - subpool->available; uint32_t *range = find_range (subpool, ind); - while (range - subpool->ranges < range_count) { + while ((size_t) (range - subpool->ranges) < range_count) { uint32_t end = --*range; range++; if (ind < end) { diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index ea0a10e3f..afe47ae02 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -72,7 +72,7 @@ #include "r_internal.h" #include "vid_vulkan.h" -static const char *draw_pass_names[] = { +static const char * __attribute__((used)) draw_pass_names[] = { "2d", }; diff --git a/tools/cross/mingw/cross-configure.sh b/tools/cross/mingw/cross-configure.sh index aae082435..869ec4851 100755 --- a/tools/cross/mingw/cross-configure.sh +++ b/tools/cross/mingw/cross-configure.sh @@ -14,6 +14,7 @@ export MINGW_USR=$MINGW/usr/i686-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH +export QCSYSPREFIX=$MINGW_USR ../../configure \ --host=i686-w64-mingw32.static \ --disable-shared \ diff --git a/tools/cross/mingw64/cross-configure.sh b/tools/cross/mingw64/cross-configure.sh index 7a886f631..f1945d685 100755 --- a/tools/cross/mingw64/cross-configure.sh +++ b/tools/cross/mingw64/cross-configure.sh @@ -5,6 +5,7 @@ cd native ../../configure \ --enable-silent-rules \ --disable-shared \ + --disable-optimize \ --without-clients \ --without-servers \ --with-tools=qfcc,pak,qwaq @@ -14,6 +15,7 @@ export MINGW_USR=$MINGW/usr/x86_64-w64-mingw32.static export PKG_CONFIG_LIBDIR=$MINGW_USR/lib/pkgconfig export PKG_CONFIG_PATH=$MINGW_USR/local/lib/pkgconfig export PATH=$MINGW/usr/bin:$PATH +export QCSYSPREFIX=$MINGW_USR ../../configure \ --host=x86_64-w64-mingw32.static \ --disable-shared \ From a1e15603a336ea8b28b7605355cdccaf2556cdeb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 26 Mar 2023 18:22:46 +0900 Subject: [PATCH 3530/3664] [vulkan] Implement job initialization The step dependencies are not handled yet as threading isn't used at this stage, but since I'll require dependencies to always come earlier, this shouldn't cause a problem. --- include/QF/Vulkan/render.h | 31 +++ libs/video/renderer/vulkan/render.c | 286 +++++++++++++++++++++------- 2 files changed, 246 insertions(+), 71 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 3d8cb6b07..e11550ec1 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -238,8 +238,10 @@ typedef struct qfv_bar_s { typedef struct qfv_pipeline_s { qfv_label_t label; VkPipelineBindPoint bindPoint; + uint32_t dispatch[3]; VkPipeline pipeline; VkPipelineLayout layout; + VkViewport viewport; VkRect2D scissor; struct qfv_push_constants_s *push_constants; @@ -279,7 +281,34 @@ typedef struct qfv_renderpass_s_ { qfv_subpass_t_ *subpasses; } qfv_renderpass_t_; +typedef struct qfv_render_s { + qfv_label_t label; + qfv_renderpass_t_ *active; + qfv_renderpass_t_ *renderpasses; + uint32_t num_renderpasses; +} qfv_render_t; + +typedef struct qfv_compute_s { + qfv_label_t label; + qfv_pipeline_t *pipelines; + uint32_t pipeline_count; +} qfv_compute_t; + +typedef struct qfv_process_s { + qfv_label_t label; + qfv_taskinfo_t *tasks; + uint32_t num_tasks; +} qfv_process_t; + +typedef struct qfv_step_s { + qfv_label_t label; + qfv_render_t *render; + qfv_compute_t *compute; + qfv_process_t *process; +} qfv_step_t; + typedef struct qfv_job_s { + qfv_label_t label; struct qfv_resource_s *resources; struct qfv_resobj_s *images; struct qfv_resobj_s *image_views; @@ -287,9 +316,11 @@ typedef struct qfv_job_s { uint32_t num_renderpasses; uint32_t num_pipelines; uint32_t num_layouts; + uint32_t num_steps; VkRenderPass *renderpasses; VkPipeline *pipelines; VkPipelineLayout *layouts; + qfv_step_t *steps; } qfv_job_t; typedef struct qfv_renderctx_s { diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 758d4c84e..456299161 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -164,6 +164,12 @@ typedef struct { uint32_t num_views; uint32_t num_layouts; + uint32_t num_steps; + uint32_t num_render; + uint32_t num_compute; + uint32_t num_process; + uint32_t num_tasks; + uint32_t num_renderpasses; uint32_t num_attachments; uint32_t num_subpasses; @@ -201,6 +207,7 @@ count_sp_stuff (qfv_subpassinfo_t *spi, objcount_t *counts) __auto_type pli = &spi->pipelines[i]; if (pli->num_graph_stages && !pli->compute_stage) { counts->num_graph_pipelines++; + counts->num_tasks += pli->num_tasks; } else { Sys_Error ("%s:%s: invalid graphics pipeline", spi->name, pli->name); @@ -225,6 +232,7 @@ count_comp_stuff (qfv_computeinfo_t *ci, objcount_t *counts) __auto_type pli = &ci->pipelines[i]; if (!pli->num_graph_stages && pli->compute_stage) { counts->num_comp_pipelines++; + counts->num_tasks += pli->num_tasks; } else { Sys_Error ("%s:%s: invalid compute pipeline", ci->name, pli->name); @@ -247,10 +255,17 @@ count_step_stuff (qfv_stepinfo_t *step, objcount_t *counts) for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { count_rp_stuff (&rinfo->renderpasses[i], counts); } + counts->num_render++; } if (step->compute) { count_comp_stuff (step->compute, counts); + counts->num_compute++; } + if (step->process) { + counts->num_process++; + counts->num_tasks += step->process->num_tasks; + } + counts->num_steps++; } static void @@ -363,7 +378,8 @@ typedef struct { uint32_t *pl_counts; - VkPipeline *pl; + VkPipeline *gpl; + VkPipeline *cpl; VkRenderPass *rp; } objptr_t; @@ -684,27 +700,46 @@ init_rpCreate (uint32_t index, const qfv_renderinfo_t *rinfo, objstate_t *s) }; } +typedef struct { + qfv_step_t *steps; + qfv_render_t *renders; + qfv_compute_t *computes; + qfv_process_t *processes; + qfv_renderpass_t_ *renderpasses; + VkClearValue *clearvalues; + qfv_subpass_t_ *subpasses; + qfv_pipeline_t *pipelines; + qfv_taskinfo_t *tasks; +} jobptr_t; + static void -init_pipeline (qfv_pipeline_t *pl, vulkan_ctx_t *ctx, qfv_pipelineinfo_t *ipl, - objstate_t *s) +init_pipeline (qfv_pipeline_t *pl, qfv_pipelineinfo_t *plinfo, + jobptr_t *jp, objstate_t *s, int is_compute) { *pl = (qfv_pipeline_t) { .label = { - .name = ipl->name, - .color = ipl->color, + .name = plinfo->name, + .color = plinfo->color, }, - .bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .pipeline = s->ptr.pl[s->inds.num_graph_pipelines], - .layout = find_layout (&ipl->layout, s), - .task_count = ipl->num_tasks, - .tasks = ipl->tasks, + .bindPoint = is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE + : VK_PIPELINE_BIND_POINT_GRAPHICS, + .pipeline = is_compute ? s->ptr.cpl[s->inds.num_comp_pipelines] + : s->ptr.gpl[s->inds.num_graph_pipelines], + .layout = find_layout (&plinfo->layout, s), + .task_count = plinfo->num_tasks, + .tasks = &jp->tasks[s->inds.num_tasks], }; + s->inds.num_tasks += plinfo->num_tasks; + for (uint32_t i = 0; i < pl->task_count; i++) { + pl->tasks[i] = plinfo->tasks[i]; + } } static void -init_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx, qfv_subpassinfo_t *isp, - qfv_pipeline_t *pl, objstate_t *s) +init_subpass (qfv_subpass_t_ *sp, qfv_subpassinfo_t *isp, + jobptr_t *jp, objstate_t *s) { + uint32_t np = s->inds.num_graph_pipelines + s->inds.num_comp_pipelines; *sp = (qfv_subpass_t_) { .label = { .name = isp->name, @@ -720,36 +755,35 @@ init_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx, qfv_subpassinfo_t *isp, .pInheritanceInfo = &sp->inherit, }, .pipeline_count = isp->num_pipelines, - .pipelines = &pl[s->inds.num_graph_pipelines], + .pipelines = &jp->pipelines[np], }; for (uint32_t i = 0; i < isp->num_pipelines; i++) { - init_pipeline (&sp->pipelines[i], ctx, &isp->pipelines[i], s); + init_pipeline (&sp->pipelines[i], &isp->pipelines[i], jp, s, 0); s->inds.num_graph_pipelines++; } } -static void __attribute__((used)) -init_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx, - qfv_renderpassinfo_t *irp, VkClearValue *cv, - qfv_subpass_t_ *sp, qfv_pipeline_t *pl, objstate_t *s) +static void +init_renderpass (qfv_renderpass_t_ *rp, qfv_renderpassinfo_t *rpinfo, + jobptr_t *jp, objstate_t *s) { *rp = (qfv_renderpass_t_) { - .vulkan_ctx = ctx, - .label.name = irp->name, - .label.color = irp->color, - .subpass_count = irp->num_subpasses, - .subpasses = &sp[s->inds.num_subpasses], + .vulkan_ctx = s->ctx, + .label.name = rpinfo->name, + .label.color = rpinfo->color, + .subpass_count = rpinfo->num_subpasses, + .subpasses = &jp->subpasses[s->inds.num_subpasses], .beginInfo = (VkRenderPassBeginInfo) { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .renderPass = s->ptr.rp[s->inds.num_renderpasses], - .clearValueCount = irp->num_attachments, - .pClearValues = &cv[s->inds.num_attachments], + .clearValueCount = rpinfo->num_attachments, + .pClearValues = &jp->clearvalues[s->inds.num_attachments], }, .subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, }; - s->inds.num_attachments += irp->num_attachments; - for (uint32_t i = 0; i < irp->num_subpasses; i++) { - init_subpass (&rp->subpasses[i], ctx, &irp->subpasses[i], pl, s); + s->inds.num_attachments += rpinfo->num_attachments; + for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) { + init_subpass (&rp->subpasses[i], &rpinfo->subpasses[i], jp, s); rp->subpasses[i].inherit.renderPass = rp->beginInfo.renderPass; rp->subpasses[i].inherit.subpass = i; s->inds.num_subpasses++; @@ -757,34 +791,161 @@ init_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx, } static void -init_render (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) +init_render (qfv_render_t *rend, qfv_renderinfo_t *rinfo, + jobptr_t *jp, objstate_t *s) +{ + *rend = (qfv_render_t) { + .label.color = rinfo->color, + .label.name = rinfo->name, + .num_renderpasses = rinfo->num_renderpasses, + .renderpasses = &jp->renderpasses[s->inds.num_renderpasses], + }; + s->inds.num_renderpasses += rinfo->num_renderpasses; + for (uint32_t i = 0; i < rend->num_renderpasses; i++) { + init_renderpass (&rend->renderpasses[i], &rinfo->renderpasses[i], + jp, s); + } +} + +static void +init_compute (qfv_compute_t *comp, qfv_computeinfo_t *cinfo, + jobptr_t *jp, objstate_t *s) +{ + uint32_t np = s->inds.num_graph_pipelines + s->inds.num_comp_pipelines; + *comp = (qfv_compute_t) { + .label.color = cinfo->color, + .label.name = cinfo->name, + .pipelines = &jp->pipelines[np], + .pipeline_count = cinfo->num_pipelines, + }; + for (uint32_t i = 0; i < cinfo->num_pipelines; i++) { + init_pipeline (&comp->pipelines[i], &cinfo->pipelines[i], jp, s, 1); + s->inds.num_comp_pipelines++; + } +} + +static void +init_process (qfv_process_t *proc, qfv_processinfo_t *pinfo, + jobptr_t *jp, objstate_t *s) +{ + *proc = (qfv_process_t) { + .label.color = pinfo->color, + .label.name = pinfo->name, + .tasks = &jp->tasks[s->inds.num_tasks], + .num_tasks = pinfo->num_tasks, + }; + s->inds.num_tasks += pinfo->num_tasks; + for (uint32_t i = 0; i < proc->num_tasks; i++) { + proc->tasks[i] = pinfo->tasks[i]; + } +} + +static void +init_step (uint32_t ind, jobptr_t *jp, objstate_t *s) +{ + __auto_type step = &jp->steps[s->inds.num_steps++]; + __auto_type sinfo = &s->jinfo->steps[ind]; + + *step = (qfv_step_t) { + .label.name = sinfo->name, + .label.color = sinfo->color, + }; + if (sinfo->render) { + step->render = &jp->renders[s->inds.num_render++]; + init_render (step->render, sinfo->render, jp, s); + } + if (sinfo->compute) { + step->compute = &jp->computes[s->inds.num_compute++]; + init_compute (step->compute, sinfo->compute, jp, s); + } + if (sinfo->process) { + step->process = &jp->processes[s->inds.num_process++]; + init_process (step->process, sinfo->process, jp, s); + } +} + +static void +init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) { -#if 0 __auto_type rctx = ctx->render_context; - __auto_type rinfo = rctx->renderinfo; - __auto_type job = rctx->job; - size_t size = 0; + + size_t size = sizeof (qfv_job_t); + + size += counts->num_renderpasses * sizeof (VkRenderPass); + size += counts->num_graph_pipelines * sizeof (VkPipeline); + size += counts->num_comp_pipelines * sizeof (VkPipeline); + size += s.inds.num_layouts * sizeof (VkPipelineLayout); + + size += counts->num_steps * sizeof (qfv_step_t); + size += counts->num_render * sizeof (qfv_render_t); + size += counts->num_compute * sizeof (qfv_compute_t); + size += counts->num_process * sizeof (qfv_process_t); size += counts->num_renderpasses * sizeof (qfv_renderpass_t_); size += counts->num_attachments * sizeof (VkClearValue); size += counts->num_subpasses * sizeof (qfv_subpass_t_); size += counts->num_graph_pipelines * sizeof (qfv_pipeline_t); size += counts->num_comp_pipelines * sizeof (qfv_pipeline_t); + size += counts->num_tasks * sizeof (qfv_taskinfo_t); - __auto_type rp = (qfv_renderpass_t_ *) calloc (1, size); + rctx->job = malloc (size); + __auto_type job = rctx->job; + *job = (qfv_job_t) { + .num_renderpasses = counts->num_renderpasses, + .num_pipelines = counts->num_graph_pipelines + + counts->num_comp_pipelines, + .num_layouts = s.inds.num_layouts, + .num_steps = counts->num_steps, + }; + job->renderpasses = (VkRenderPass *) &job[1]; + job->pipelines = (VkPipeline *) &job->renderpasses[job->num_renderpasses]; + job->layouts = (VkPipelineLayout *) &job->pipelines[job->num_pipelines]; + job->steps = (qfv_step_t *) &job->layouts[job->num_layouts]; + __auto_type rn = (qfv_render_t *) &job->steps[job->num_steps]; + __auto_type cp = (qfv_compute_t *) &rn[counts->num_render]; + __auto_type pr = (qfv_process_t *) &cp[counts->num_compute]; + __auto_type rp = (qfv_renderpass_t_ *) &pr[counts->num_process]; __auto_type cv = (VkClearValue *) &rp[counts->num_renderpasses]; __auto_type sp = (qfv_subpass_t_ *) &cv[counts->num_attachments]; __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; + __auto_type ti = (qfv_taskinfo_t *) &pl[job->num_pipelines]; + jobptr_t jp = { + .steps = job->steps, + .renders = rn, + .computes = cp, + .processes = pr, + .renderpasses = rp, + .clearvalues = cv, + .subpasses = sp, + .pipelines = pl, + .tasks = ti, + }; + + for (uint32_t i = 0; i < job->num_renderpasses; i++) { + job->renderpasses[i] = s.ptr.rp[i]; + } + for (uint32_t i = 0; i < job->num_pipelines; i++) { + // compute pipelines come immediately after the graphics pipelines + job->pipelines[i] = s.ptr.gpl[i]; + } + for (uint32_t i = 0; i < s.inds.num_layouts; i++) { + job->layouts[i] = s.ptr.layouts[i].layout; + } memcpy (cv, s.ptr.clear, counts->num_attachments * sizeof (VkClearValue)); + uint32_t num_layouts = s.inds.num_layouts; s.inds = (objcount_t) {}; s.inds.num_layouts = num_layouts; + for (uint32_t i = 0; i < job->num_steps; i++) { + init_step (i, &jp, &s); + } +#if 0 + __auto_type rinfo = rctx->renderinfo; + size_t size = 0; + for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { init_renderpass (&rp[i], ctx, &rinfo->renderpasses[i], cv, sp, pl, &s); s.inds.num_renderpasses++; } - - job->num_renderpasses = rinfo->num_renderpasses; - job->renderpasses = rp; #endif } @@ -844,12 +1005,10 @@ create_objects (vulkan_ctx_t *ctx, objcount_t *counts) { __auto_type rctx = ctx->render_context; __auto_type jinfo = rctx->jobinfo; - __auto_type job = rctx->job; - - exprctx_t ectx = { - .hashctx = &ctx->script_context->hashctx, - }; + VkRenderPass renderpasses[counts->num_renderpasses]; + VkPipeline pipelines[counts->num_graph_pipelines + + counts->num_comp_pipelines]; VkRenderPassCreateInfo rpCreate[counts->num_renderpasses]; VkAttachmentDescription attach[counts->num_attachments]; VkClearValue clear[counts->num_attachments]; @@ -867,6 +1026,8 @@ create_objects (vulkan_ctx_t *ctx, objcount_t *counts) qfv_layoutinfo_t layouts[counts->num_graph_pipelines + counts->num_comp_pipelines]; uint32_t pl_counts[counts->num_renderpasses]; + + exprctx_t ectx = { .hashctx = &ctx->script_context->hashctx }; objstate_t s = { .ptr = { .rpCreate = rpCreate, @@ -884,8 +1045,9 @@ create_objects (vulkan_ctx_t *ctx, objcount_t *counts) .cbState = cbState, .layouts = layouts, .pl_counts = pl_counts, - .rp = job->renderpasses, - .pl = job->pipelines, + .rp = renderpasses, + .gpl = pipelines, + .cpl = pipelines + counts->num_graph_pipelines, }, .ctx = ctx, .jinfo = jinfo, @@ -912,50 +1074,42 @@ create_objects (vulkan_ctx_t *ctx, objcount_t *counts) Sys_Error ("create_objects: something was missed"); } - job->num_renderpasses = counts->num_renderpasses; - job->num_pipelines = counts->num_graph_pipelines - + counts->num_comp_pipelines; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; uint32_t plInd = 0; - for (uint32_t i = 0; i < job->num_renderpasses; i++) { + for (uint32_t i = 0; i < counts->num_renderpasses; i++) { dfunc->vkCreateRenderPass (device->dev, &s.ptr.rpCreate[i], 0, - &job->renderpasses[i]); + &renderpasses[i]); QFV_duSetObjectName (device, VK_OBJECT_TYPE_RENDER_PASS, - job->renderpasses[i], + renderpasses[i], va (ctx->va_ctx, "renderpass:%s", rpName[i])); for (uint32_t j = 0; j < pl_counts[i]; j++) { - s.ptr.gplCreate[plInd++].renderPass = job->renderpasses[i]; + s.ptr.gplCreate[plInd++].renderPass = renderpasses[i]; } } if (s.inds.num_graph_pipelines) { dfunc->vkCreateGraphicsPipelines (device->dev, 0, s.inds.num_graph_pipelines, - s.ptr.gplCreate, 0, job->pipelines); + s.ptr.gplCreate, 0, pipelines); } if (s.inds.num_comp_pipelines) { - __auto_type p = &job->pipelines[s.inds.num_graph_pipelines]; + __auto_type p = &pipelines[s.inds.num_graph_pipelines]; dfunc->vkCreateComputePipelines (device->dev, 0, s.inds.num_comp_pipelines, s.ptr.cplCreate, 0, p); } for (uint32_t i = 0; i < s.inds.num_graph_pipelines + s.inds.num_comp_pipelines; i++) { - QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE, job->pipelines[i], + QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE, pipelines[i], va (ctx->va_ctx, "pipeline:%s", plName[i])); } - job->layouts = malloc (s.inds.num_layouts * sizeof (VkPipelineLayout)); - for (uint32_t i = 0; i < s.inds.num_layouts; i++) { - job->layouts[i] = layouts[i].layout; - } - job->num_layouts = s.inds.num_layouts; // rinfo->num_layouts = s.inds.num_layouts; // size_t layout_size = rinfo->num_layouts * sizeof (qfv_layoutinfo_t); // rinfo->layouts = cmemalloc (rinfo->memsuper, layout_size); // memcpy (rinfo->layouts, s.ptr.layouts, layout_size); - if (0) init_render (ctx, counts, s); + init_job (ctx, counts, s); } void @@ -966,18 +1120,8 @@ QFV_BuildRender (vulkan_ctx_t *ctx) objcount_t counts = {}; count_stuff (rctx->jobinfo, &counts); - rctx->job = malloc (sizeof (qfv_job_t) - + counts.num_renderpasses * sizeof (VkRenderPass) - + counts.num_graph_pipelines * sizeof (VkPipeline) - + counts.num_comp_pipelines * sizeof (VkPipeline)); - __auto_type rp = (VkRenderPass *) &rctx->job[1]; - *rctx->job = (qfv_job_t) { - .renderpasses = rp, - .pipelines = (VkPipeline *) &rp[counts.num_renderpasses], - }; - - create_resources (ctx, &counts); create_objects (ctx, &counts); + create_resources (ctx, &counts); } static VkImageView __attribute__((pure, used)) From aba057b827077f400d3dc6c6baf7e88915c521ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Mar 2023 23:50:57 +0900 Subject: [PATCH 3531/3664] [vulkan] Correct type of queue family No idea why I had int32_t instead of uint32_t. --- include/QF/Vulkan/device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/Vulkan/device.h b/include/QF/Vulkan/device.h index f93a8a5c2..8d10971dc 100644 --- a/include/QF/Vulkan/device.h +++ b/include/QF/Vulkan/device.h @@ -12,7 +12,7 @@ typedef struct qfv_devfuncs_s { typedef struct qfv_queue_s { struct qfv_device_s *device; - int32_t queueFamily; + uint32_t queueFamily; VkQueue queue; } qfv_queue_t; From 34ece7ad0368933eaace6e9e65526ced7a497705 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 00:12:13 +0900 Subject: [PATCH 3532/3664] [vulkan] Add buffer and buffer view support Not fully implemented, but the parsing is done. Needed image view refs to be renamed. --- include/QF/Vulkan/render.h | 25 +++++++++++++++-- libs/video/renderer/vulkan/render.c | 28 +++++++++++--------- libs/video/renderer/vulkan/rp_main_def.plist | 16 +++++------ libs/video/renderer/vulkan/vkparse.plist | 25 ++++++++++++++--- 4 files changed, 69 insertions(+), 25 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index e11550ec1..06b436b7c 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -65,6 +65,23 @@ typedef struct qfv_imageviewinfo_s { VkImageSubresourceRange subresourceRange; } qfv_imageviewinfo_t; +typedef struct qfv_bufferinfo_s { + const char *name; + VkBufferCreateFlags flags; + VkDeviceSize size; + VkBufferUsageFlags usage; + VkSharingMode sharingMode; +} qfv_bufferinfo_t; + +typedef struct qfv_bufferviewinfo_s { + const char *name; + VkBufferViewCreateFlags flags; + qfv_reference_t buffer; + VkFormat format; + VkDeviceSize offset; + VkDeviceSize range; +} qfv_bufferviewinfo_t; + typedef struct qfv_dependencymask_s { VkPipelineStageFlags stage; VkAccessFlags access; @@ -215,9 +232,13 @@ typedef struct qfv_jobinfo_s { qfv_stepinfo_t *steps; uint32_t num_images; + uint32_t num_imageviews; qfv_imageinfo_t *images; - uint32_t num_views; - qfv_imageviewinfo_t *views; + qfv_imageviewinfo_t *imageviews; + uint32_t num_buffers; + uint32_t num_bufferviews; + qfv_imageinfo_t *buffers; + qfv_imageviewinfo_t *bufferviews; uint32_t num_descriptorsets; qfv_descriptorsetinfo_t *descriptorsets; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 456299161..e3080354d 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -161,7 +161,9 @@ QFV_LoadRenderInfo (vulkan_ctx_t *ctx) typedef struct { uint32_t num_images; - uint32_t num_views; + uint32_t num_imageviews; + uint32_t num_buffers; + uint32_t num_bufferviews; uint32_t num_layouts; uint32_t num_steps; @@ -272,7 +274,9 @@ static void count_stuff (qfv_jobinfo_t *jobinfo, objcount_t *counts) { counts->num_images += jobinfo->num_images; - counts->num_views += jobinfo->num_views; + counts->num_imageviews += jobinfo->num_imageviews; + counts->num_buffers += jobinfo->num_buffers; + counts->num_bufferviews += jobinfo->num_bufferviews; for (uint32_t i = 0; i < jobinfo->num_steps; i++) { count_step_stuff (&jobinfo->steps[i], counts); } @@ -287,7 +291,7 @@ create_resources (vulkan_ctx_t *ctx, objcount_t *counts) job->resources = malloc (sizeof(qfv_resource_t) + counts->num_images * sizeof (qfv_resobj_t) - + counts->num_views * sizeof (qfv_resobj_t)); + + counts->num_imageviews * sizeof (qfv_resobj_t)); job->images = (qfv_resobj_t *) &job->resources[1]; job->image_views = &job->images[counts->num_images]; @@ -295,7 +299,7 @@ create_resources (vulkan_ctx_t *ctx, objcount_t *counts) .name = "render", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .num_objects = counts->num_images + counts->num_views, + .num_objects = counts->num_images + counts->num_imageviews, .objects = job->images, }; for (uint32_t i = 0; i < counts->num_images; i++) { @@ -318,8 +322,8 @@ create_resources (vulkan_ctx_t *ctx, objcount_t *counts) }; } int error = 0; - for (uint32_t i = 0; i < counts->num_views; i++) { - __auto_type view = &jinfo->views[i]; + for (uint32_t i = 0; i < counts->num_imageviews; i++) { + __auto_type view = &jinfo->imageviews[i]; job->image_views[i] = (qfv_resobj_t) { .name = view->name, .type = qfv_res_image_view, @@ -1125,24 +1129,24 @@ QFV_BuildRender (vulkan_ctx_t *ctx) } static VkImageView __attribute__((pure, used)) -find_view (qfv_reference_t *ref, qfv_renderctx_t *rctx) +find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx) { __auto_type jinfo = rctx->jobinfo; __auto_type job = rctx->job; const char *name = ref->name; - if (strncmp (name, "$views.", 7) == 0) { + if (strncmp (name, "$imageviews.", 7) == 0) { name += 7; } - for (uint32_t i = 0; i < jinfo->num_views; i++) { - __auto_type vi = &jinfo->views[i]; + for (uint32_t i = 0; i < jinfo->num_imageviews; i++) { + __auto_type vi = &jinfo->imageviews[i]; __auto_type vo = &job->image_views[i]; if (strcmp (name, vi->name) == 0) { return vo->image_view.view; } } - Sys_Error ("%d:invalid view: %s", ref->line, ref->name); + Sys_Error ("%d:invalid imageview: %s", ref->line, ref->name); } void @@ -1184,7 +1188,7 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx) .layers = rpInfo->framebuffer.layers, }; for (uint32_t i = 0; i < rpInfo->num_attachments; i++) { - attachments[i] = find_view (&rpInfo->attachments[i].view, rctx); + attachments[i] = find_imageview (&rpInfo->attachments[i].view, rctx); } qfv_device_t *device = ctx->device; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 971328dde..5f9ece858 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -822,7 +822,7 @@ images = { format = $render_output.format; }; }; -views = { +imageviews = { depth = { @inherit = $view_base; image = depth; @@ -877,34 +877,34 @@ renderpasses = { loadOp = clear; finalLayout = depth_stencil_attachment_optimal; clearValue = { depthStencil = { depth = 1; stencil = 0; }; }; - view = $views.depth; + view = $imageviews.depth; }; color = { @inherit = $attachment_base; format = $images.color.format; loadOp = clear; - view = $views.color; + view = $imageviews.color; }; emission = { @inherit = $attachment_base; format = $images.emission.format; loadOp = clear; - view = $views.emission; + view = $imageviews.emission; }; normal = { @inherit = $attachment_base; format = $images.normal.format; - view = $views.normal; + view = $imageviews.normal; }; position = { @inherit = $attachment_base; format = $images.position.format; - view = $views.position; + view = $imageviews.position; }; opaque = { @inherit = $attachment_base; format = $images.opaque.format; - view = $views.opaque; + view = $imageviews.opaque; }; output = { @inherit = $attachment_base; @@ -912,7 +912,7 @@ renderpasses = { loadOp = clear; storeOp = store; finalLayout = $render_output.finalLayout; - view = $views.output; + view = $imageviews.output; }; }; framebuffer = { diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index bab9ed226..a6a5f83f4 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -36,6 +36,8 @@ search = ( qfv_descriptorsetinfo_t, qfv_imageinfo_t, qfv_imageviewinfo_t, + qfv_bufferinfo_t, + qfv_bufferviewinfo_t, qfv_dependencyinfo_t, qfv_attachmentinfo_t, qfv_attachmentrefinfo_t, @@ -623,6 +625,13 @@ parse = { values = bindings; }; }; + qfv_bufferviewinfo_s = { + .name = qfv_bufferviewinfo_t; + buffer = auto; + format = auto; + offset = auto; + range = auto; + }; qfv_computeinfo_s = { .name = qfv_computeinfo_t; color = auto; @@ -684,10 +693,20 @@ parse = { size = num_images; values = images; }; - views = { + imageviews = { type = (labeledarray, qfv_imageviewinfo_t, name); - size = num_views; - values = views; + size = num_imageviews; + values = imageviews; + }; + buffers = { + type = (labeledarray, qfv_bufferinfo_t, name); + size = num_buffers; + values = buffers; + }; + bufferviews = { + type = (labeledarray, qfv_bufferviewinfo_t, name); + size = num_bufferviews; + values = bufferviews; }; steps = { type = (labeledarray, qfv_stepinfo_t, name); From 47bfa23d099b4ffdddbe27280c7bff62457e739c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 10:28:44 +0900 Subject: [PATCH 3533/3664] [vulkan] Stub out the basic job execution Really, a bit more than stub as the basic code is there, but nothing works properly yet due to missing resources (especially descriptor sets and pools), and the frame buffer creation is still disabled. --- include/QF/Vulkan/render.h | 24 +++- libs/video/renderer/vulkan/render.c | 205 +++++++++++++++++++++++----- 2 files changed, 190 insertions(+), 39 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 06b436b7c..a78f08f44 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -8,6 +8,9 @@ #include "QF/cexpr.h" #include "QF/simd/types.h" +#ifndef __QFCC__ +#include "QF/Vulkan/command.h" +#endif typedef struct qfv_output_s { VkExtent2D extent; @@ -244,6 +247,7 @@ typedef struct qfv_jobinfo_s { qfv_descriptorsetinfo_t *descriptorsets; } qfv_jobinfo_t; +#ifndef __QFCC__ typedef struct qfv_label_s { vec4f_t color; const char *name; @@ -267,9 +271,9 @@ typedef struct qfv_pipeline_s { VkRect2D scissor; struct qfv_push_constants_s *push_constants; uint32_t num_push_constants; - uint32_t num_descriptor_sets; - uint32_t first_descriptor_set; - VkDescriptorSet *descriptor_sets; + uint32_t num_descriptorsets; + uint32_t first_descriptorset; + VkDescriptorSet *descriptorsets; uint32_t task_count; qfv_taskinfo_t *tasks; @@ -279,7 +283,6 @@ typedef struct qfv_subpass_s_ { qfv_label_t label; VkCommandBufferInheritanceInfo inherit; VkCommandBufferBeginInfo beginInfo; - VkCommandBuffer cmd; uint32_t pipeline_count; qfv_pipeline_t *pipelines; } qfv_subpass_t_; @@ -288,7 +291,6 @@ typedef struct qfv_renderpass_s_ { struct vulkan_ctx_s *vulkan_ctx; qfv_label_t label; // for debugging - VkCommandBuffer cmd; VkRenderPassBeginInfo beginInfo; VkSubpassContents subpassContents; @@ -318,7 +320,7 @@ typedef struct qfv_compute_s { typedef struct qfv_process_s { qfv_label_t label; qfv_taskinfo_t *tasks; - uint32_t num_tasks; + uint32_t task_count; } qfv_process_t; typedef struct qfv_step_s { @@ -342,6 +344,8 @@ typedef struct qfv_job_s { VkPipeline *pipelines; VkPipelineLayout *layouts; qfv_step_t *steps; + qfv_cmdbufferset_t commands; + VkCommandPool command_pool; } qfv_job_t; typedef struct qfv_renderctx_s { @@ -351,7 +355,12 @@ typedef struct qfv_renderctx_s { qfv_job_t *job; } qfv_renderctx_t; -void QFV_RunRenderPass (qfv_renderpass_t_ *rp, struct vulkan_ctx_s *ctx); +typedef struct qfv_taskctx_s { + struct vulkan_ctx_s *ctx; + qfv_pipeline_t *pipeline; +} qfv_taskctx_t; + +void QFV_RunRenderJob (struct vulkan_ctx_s *ctx); void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx); void QFV_BuildRender (struct vulkan_ctx_s *ctx); void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx); @@ -359,5 +368,6 @@ void QFV_DestroyFramebuffer (struct vulkan_ctx_s *ctx); void QFV_Render_Init (struct vulkan_ctx_s *ctx); void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx); void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys); +#endif//__QFCC__ #endif//__QF_Vulkan_render_h diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index e3080354d..69a2987ee 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -51,6 +51,34 @@ #include "vkparse.h" +static VkCommandBuffer +get_cmd_buffer (vulkan_ctx_t *ctx, int secondary) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type rctx = ctx->render_context; + __auto_type job = rctx->job; + + VkCommandBufferAllocateInfo cinfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = job->command_pool, + .level = secondary ? VK_COMMAND_BUFFER_LEVEL_SECONDARY + : VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }; + VkCommandBuffer cmd; + dfunc->vkAllocateCommandBuffers (device->dev, &cinfo, &cmd); + return cmd; +} + +static void +run_tasks (uint32_t task_count, qfv_taskinfo_t *tasks, void *ctx) +{ + for (uint32_t i = 0; i < task_count; i++) { + tasks[i].func->func (tasks[i].params, 0, ctx); + } +} + static void run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) { @@ -59,12 +87,19 @@ run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) dfunc->vkCmdBindPipeline (cmd, pipeline->bindPoint, pipeline->pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &pipeline->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &pipeline->scissor); - if (pipeline->num_descriptor_sets) { + + qfv_taskctx_t taskctx = { + .ctx = ctx, + .pipeline = pipeline, + }; + run_tasks (pipeline->task_count, pipeline->tasks, &taskctx); + + if (pipeline->num_descriptorsets) { dfunc->vkCmdBindDescriptorSets (cmd, pipeline->bindPoint, pipeline->layout, - pipeline->first_descriptor_set, - pipeline->num_descriptor_sets, - pipeline->descriptor_sets, + pipeline->first_descriptorset, + pipeline->num_descriptorsets, + pipeline->descriptorsets, 0, 0); } if (pipeline->num_push_constants) { @@ -76,11 +111,10 @@ run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) // https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/ static void -run_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx) +run_subpass (qfv_subpass_t_ *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - __auto_type cmd = sp->cmd; dfunc->vkResetCommandBuffer (cmd, 0); dfunc->vkBeginCommandBuffer (cmd, &sp->beginInfo); QFV_duCmdBeginLabel (device, cmd, sp->label.name, @@ -95,13 +129,15 @@ run_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx) dfunc->vkEndCommandBuffer (cmd); } -void -QFV_RunRenderPass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) +static void +run_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) { + printf ("run_renderpass: %s\n", rp->label.name); + qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - __auto_type cmd = rp->cmd; + VkCommandBuffer cmd = get_cmd_buffer (ctx, 1); VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, }; @@ -112,8 +148,9 @@ QFV_RunRenderPass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) dfunc->vkCmdBeginRenderPass (cmd, &rp->beginInfo, rp->subpassContents); for (uint32_t i = 0; i < rp->subpass_count; i++) { __auto_type sp = &rp->subpasses[i]; - run_subpass (sp, ctx); - dfunc->vkCmdExecuteCommands (cmd, 1, &sp->cmd); + VkCommandBuffer subcmd = get_cmd_buffer (ctx, 1); + run_subpass (sp, subcmd, ctx); + dfunc->vkCmdExecuteCommands (cmd, 1, &subcmd); //FIXME comment is a bit off as exactly one buffer is always submitted // //Regardless of whether any commands were submitted for this @@ -127,6 +164,92 @@ QFV_RunRenderPass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) QFV_CmdEndLabel (device, cmd); } +static void +run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, + vulkan_ctx_t *ctx) +{ + printf ("run_compute_pipeline: %s\n", pipeline->label.name); + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + dfunc->vkCmdBindPipeline (cmd, pipeline->bindPoint, pipeline->pipeline); + + qfv_taskctx_t taskctx = { + .ctx = ctx, + .pipeline = pipeline, + }; + run_tasks (pipeline->task_count, pipeline->tasks, &taskctx); + + if (pipeline->num_descriptorsets) { + dfunc->vkCmdBindDescriptorSets (cmd, pipeline->bindPoint, + pipeline->layout, + pipeline->first_descriptorset, + pipeline->num_descriptorsets, + pipeline->descriptorsets, + 0, 0); + } + if (pipeline->num_push_constants) { + QFV_PushConstants (device, cmd, pipeline->layout, + pipeline->num_push_constants, + pipeline->push_constants); + } + uint32_t *d = pipeline->dispatch; + dfunc->vkCmdDispatch (cmd, d[0], d[1], d[2]); +} + +static void +run_compute (qfv_compute_t *comp, vulkan_ctx_t *ctx) +{ + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + __auto_type rctx = ctx->render_context; + __auto_type job = rctx->job; + + VkCommandBuffer cmd = get_cmd_buffer (ctx, 0); + + VkCommandBufferBeginInfo beginInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + for (uint32_t i = 0; i < comp->pipeline_count; i++) { + __auto_type pipeline = &comp->pipelines[i]; + run_compute_pipeline (pipeline, cmd, ctx); + } + dfunc->vkEndCommandBuffer (cmd); + DARRAY_APPEND (&job->commands, cmd); +} + +static void +run_process (qfv_process_t *proc, vulkan_ctx_t *ctx) +{ + qfv_taskctx_t taskctx = { + .ctx = ctx, + }; + run_tasks (proc->task_count, proc->tasks, &taskctx); +} + +void +QFV_RunRenderJob (vulkan_ctx_t *ctx) +{ + __auto_type rctx = ctx->render_context; + __auto_type job = rctx->job; + + for (uint32_t i = 0; i < job->num_steps; i++) { + __auto_type step = &job->steps[i]; + printf ("run_step: %s\n", step->label.name); + if (step->render) { + run_renderpass (step->render->active, ctx); + } + if (step->compute) { + run_compute (step->compute, ctx); + } + if (step->process) { + run_process (step->process, ctx); + } + } +} + static qfv_output_t get_output (vulkan_ctx_t *ctx, plitem_t *item) { @@ -181,6 +304,8 @@ typedef struct { uint32_t num_preserve; uint32_t num_graph_pipelines; uint32_t num_comp_pipelines; + + uint32_t num_descriptorsets; } objcount_t; static void @@ -448,12 +573,12 @@ find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) s->rpi->name, s->spi->name, ref->line, ref->name); } -static VkPipelineLayout +static qfv_layoutinfo_t * find_layout (const qfv_reference_t *ref, objstate_t *s) { for (uint32_t i = 0; i < s->inds.num_layouts; i++) { if (strcmp (s->ptr.layouts[i].name, ref->name) == 0) { - return s->ptr.layouts[i].layout; + return &s->ptr.layouts[i]; } } if (!QFV_ParseLayoutInfo (s->ctx, s->jinfo->memsuper, s->symtab, ref->name, @@ -479,7 +604,7 @@ find_layout (const qfv_reference_t *ref, objstate_t *s) dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &li->layout); QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, li->layout, va (s->ctx->va_ctx, "layout:%s", li->name)); - return li->layout; + return li; } static void @@ -522,7 +647,9 @@ init_plCreate (VkGraphicsPipelineCreateInfo *plc, const qfv_pipelineinfo_t *pli, plc->pDynamicState = pli->dynamic; } if (pli->layout.name) { - plc->layout = find_layout (&pli->layout, s); + __auto_type li = find_layout (&pli->layout, s); + plc->layout = li->layout; + s->inds.num_descriptorsets += li->num_sets; } } @@ -714,12 +841,14 @@ typedef struct { qfv_subpass_t_ *subpasses; qfv_pipeline_t *pipelines; qfv_taskinfo_t *tasks; + VkDescriptorSet *descriptorsets; } jobptr_t; static void init_pipeline (qfv_pipeline_t *pl, qfv_pipelineinfo_t *plinfo, jobptr_t *jp, objstate_t *s, int is_compute) { + __auto_type li = find_layout (&plinfo->layout, s); *pl = (qfv_pipeline_t) { .label = { .name = plinfo->name, @@ -729,11 +858,16 @@ init_pipeline (qfv_pipeline_t *pl, qfv_pipelineinfo_t *plinfo, : VK_PIPELINE_BIND_POINT_GRAPHICS, .pipeline = is_compute ? s->ptr.cpl[s->inds.num_comp_pipelines] : s->ptr.gpl[s->inds.num_graph_pipelines], - .layout = find_layout (&plinfo->layout, s), + .layout = li->layout, .task_count = plinfo->num_tasks, .tasks = &jp->tasks[s->inds.num_tasks], + .descriptorsets = &jp->descriptorsets[s->inds.num_descriptorsets], }; s->inds.num_tasks += plinfo->num_tasks; + s->inds.num_descriptorsets += li->num_sets; + for (uint32_t i = 0; i < li->num_sets; i++) { + pl->descriptorsets[i] = 0; + } for (uint32_t i = 0; i < pl->task_count; i++) { pl->tasks[i] = plinfo->tasks[i]; } @@ -809,6 +943,7 @@ init_render (qfv_render_t *rend, qfv_renderinfo_t *rinfo, init_renderpass (&rend->renderpasses[i], &rinfo->renderpasses[i], jp, s); } + rend->active = &rend->renderpasses[0]; } static void @@ -836,10 +971,10 @@ init_process (qfv_process_t *proc, qfv_processinfo_t *pinfo, .label.color = pinfo->color, .label.name = pinfo->name, .tasks = &jp->tasks[s->inds.num_tasks], - .num_tasks = pinfo->num_tasks, + .task_count = pinfo->num_tasks, }; s->inds.num_tasks += pinfo->num_tasks; - for (uint32_t i = 0; i < proc->num_tasks; i++) { + for (uint32_t i = 0; i < proc->task_count; i++) { proc->tasks[i] = pinfo->tasks[i]; } } @@ -890,6 +1025,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) size += counts->num_graph_pipelines * sizeof (qfv_pipeline_t); size += counts->num_comp_pipelines * sizeof (qfv_pipeline_t); size += counts->num_tasks * sizeof (qfv_taskinfo_t); + size += counts->num_descriptorsets * sizeof (VkDescriptorSet); rctx->job = malloc (size); __auto_type job = rctx->job; @@ -899,6 +1035,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) + counts->num_comp_pipelines, .num_layouts = s.inds.num_layouts, .num_steps = counts->num_steps, + .commands = DARRAY_STATIC_INIT (16), }; job->renderpasses = (VkRenderPass *) &job[1]; job->pipelines = (VkPipeline *) &job->renderpasses[job->num_renderpasses]; @@ -912,6 +1049,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) __auto_type sp = (qfv_subpass_t_ *) &cv[counts->num_attachments]; __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; __auto_type ti = (qfv_taskinfo_t *) &pl[job->num_pipelines]; + __auto_type ds = (VkDescriptorSet *) &ti[counts->num_tasks]; jobptr_t jp = { .steps = job->steps, .renders = rn, @@ -922,6 +1060,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) .subpasses = sp, .pipelines = pl, .tasks = ti, + .descriptorsets = ds, }; for (uint32_t i = 0; i < job->num_renderpasses; i++) { @@ -942,15 +1081,15 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) for (uint32_t i = 0; i < job->num_steps; i++) { init_step (i, &jp, &s); } -#if 0 - __auto_type rinfo = rctx->renderinfo; - size_t size = 0; - for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { - init_renderpass (&rp[i], ctx, &rinfo->renderpasses[i], cv, sp, pl, &s); - s.inds.num_renderpasses++; - } -#endif + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkCommandPoolCreateInfo poolCInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + .queueFamilyIndex = device->queue.queueFamily, + }; + dfunc->vkCreateCommandPool (device->dev, &poolCInfo, 0, &job->command_pool); } static void @@ -981,15 +1120,17 @@ create_step_compute_objects (uint32_t index, const qfv_stepinfo_t *step, for (uint32_t i = 0; i < cinfo->num_pipelines; i++) { __auto_type pli = &cinfo->pipelines[i]; __auto_type plc = &s->ptr.cplCreate[s->inds.num_comp_pipelines]; + __auto_type li = find_layout (&pli->layout, s); s->ptr.plName[base + s->inds.num_comp_pipelines] = pli->name; *plc = (VkComputePipelineCreateInfo) { .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, .flags = pli->flags, .stage = *pli->compute_stage, - .layout = find_layout (&pli->layout, s), + .layout = li->layout, }; plc->stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; s->inds.num_comp_pipelines++; + s->inds.num_descriptorsets += li->num_sets; } } @@ -1108,11 +1249,7 @@ create_objects (vulkan_ctx_t *ctx, objcount_t *counts) va (ctx->va_ctx, "pipeline:%s", plName[i])); } -// rinfo->num_layouts = s.inds.num_layouts; -// size_t layout_size = rinfo->num_layouts * sizeof (qfv_layoutinfo_t); -// rinfo->layouts = cmemalloc (rinfo->memsuper, layout_size); -// memcpy (rinfo->layouts, s.ptr.layouts, layout_size); - + counts->num_descriptorsets = s.inds.num_descriptorsets; init_job (ctx, counts, s); } @@ -1241,6 +1378,10 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) QFV_DestroyResource (ctx->device, job->resources); free (job->resources); } + if (job->command_pool) { + dfunc->vkDestroyCommandPool (device->dev, job->command_pool, 0); + } + DARRAY_CLEAR (&job->commands); free (rctx->job); } if (rctx->jobinfo) { From b1de1b87475715fb56b810fe7139aab8f268612a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 12:43:05 +0900 Subject: [PATCH 3534/3664] [util] Fix more ULP issues in the simd tests on arm This time for debug (unoptimized) builds. While I could just do an approximate check, I think it's better to document (as such) the expected errors. --- libs/util/test/test-simd.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index bc0c4c140..dd675ae77 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -193,7 +193,9 @@ static vec4d_test_t vec4d_tests[] = { // used): ulp errors in z and w T(crossd, qtest, qtest, {0, 0, 0, 0}, #if defined(__aarch64__) +# ifdef __OPTIMIZE__ {0, 0, -2.1938006966593093e-17, 1.3322676295501878e-17}, +# endif #endif ), @@ -219,7 +221,9 @@ static vec4d_test_t vec4d_tests[] = { // used): ulp error in z T(qmuld, qtest, qtest, {0.768, 0.576, 0, -0.28}, #if defined(__aarch64__) +# ifdef __OPTIMIZE__ {0, 0, -2.1938006966593093e-17, 0}, +# endif #endif ), @@ -325,15 +329,19 @@ static vec4f_test_t vec4f_tests[] = { T(crossf, one, forward, {-1, 0, 1} ), T(crossf, one, up, { 1, -1, 0} ), #ifdef __aarch64__ +# ifdef __OPTIMIZE__ T(crossf, qtest, qtest, {0, 0, -1.47819534e-09, -1.43051153e-08} ), +# else + T(crossf, qtest, qtest, {0, 0, 0, 0} ), +# endif #else -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +# if !defined(__SSE__) && !defined(__OPTIMIZE__) // when not optimizing and SSE is not available (but ok when // optimizing) T(crossf, qtest, qtest, {0, 0, -1.47819534e-09, 0} ), -#else +# else T(crossf, qtest, qtest, {0, 0, 0, 0} ), -#endif +# endif #endif T(qmulf, qident, qident, qident ), @@ -356,15 +364,19 @@ static vec4f_test_t vec4f_tests[] = { T(qmulf, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } ), T(qmulf, qtest, qtest, {0.768, 0.576, 0, -0.28}, #ifdef __aarch64__ +# ifdef __OPTIMIZE__ {0, 6e-8, -1.47819534e-09, 2.98023224e-08} +# else + {0, 5.96046448e-08, 0, 2.98023224e-08} +# endif #else -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +# if !defined(__SSE__) && !defined(__OPTIMIZE__) // when not optimizing and SSE is not available (but ok when // optimizing) {0, 6e-8, -1.47819534e-09, 3e-8} -#elif !defined(__SSE__) +# elif !defined(__SSE__) {0, 6e-8, 0, 6e-8} -#else +# else {0, 6e-8, 0, 3e-8} #endif #endif From 53ae2fe2237f3ebe2cabfcaa412016594cd9da6c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 12:43:05 +0900 Subject: [PATCH 3535/3664] [util] Fix more ULP issues in the simd tests on arm This time for debug (unoptimized) builds. While I could just do an approximate check, I think it's better to document (as such) the expected errors. --- libs/util/test/test-simd.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/libs/util/test/test-simd.c b/libs/util/test/test-simd.c index bc0c4c140..dd675ae77 100644 --- a/libs/util/test/test-simd.c +++ b/libs/util/test/test-simd.c @@ -193,7 +193,9 @@ static vec4d_test_t vec4d_tests[] = { // used): ulp errors in z and w T(crossd, qtest, qtest, {0, 0, 0, 0}, #if defined(__aarch64__) +# ifdef __OPTIMIZE__ {0, 0, -2.1938006966593093e-17, 1.3322676295501878e-17}, +# endif #endif ), @@ -219,7 +221,9 @@ static vec4d_test_t vec4d_tests[] = { // used): ulp error in z T(qmuld, qtest, qtest, {0.768, 0.576, 0, -0.28}, #if defined(__aarch64__) +# ifdef __OPTIMIZE__ {0, 0, -2.1938006966593093e-17, 0}, +# endif #endif ), @@ -325,15 +329,19 @@ static vec4f_test_t vec4f_tests[] = { T(crossf, one, forward, {-1, 0, 1} ), T(crossf, one, up, { 1, -1, 0} ), #ifdef __aarch64__ +# ifdef __OPTIMIZE__ T(crossf, qtest, qtest, {0, 0, -1.47819534e-09, -1.43051153e-08} ), +# else + T(crossf, qtest, qtest, {0, 0, 0, 0} ), +# endif #else -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +# if !defined(__SSE__) && !defined(__OPTIMIZE__) // when not optimizing and SSE is not available (but ok when // optimizing) T(crossf, qtest, qtest, {0, 0, -1.47819534e-09, 0} ), -#else +# else T(crossf, qtest, qtest, {0, 0, 0, 0} ), -#endif +# endif #endif T(qmulf, qident, qident, qident ), @@ -356,15 +364,19 @@ static vec4f_test_t vec4f_tests[] = { T(qmulf, one, { 2, 2, 2, -2 }, { 0, 0, 0, -8 } ), T(qmulf, qtest, qtest, {0.768, 0.576, 0, -0.28}, #ifdef __aarch64__ +# ifdef __OPTIMIZE__ {0, 6e-8, -1.47819534e-09, 2.98023224e-08} +# else + {0, 5.96046448e-08, 0, 2.98023224e-08} +# endif #else -#if !defined(__SSE__) && !defined(__OPTIMIZE__) +# if !defined(__SSE__) && !defined(__OPTIMIZE__) // when not optimizing and SSE is not available (but ok when // optimizing) {0, 6e-8, -1.47819534e-09, 3e-8} -#elif !defined(__SSE__) +# elif !defined(__SSE__) {0, 6e-8, 0, 6e-8} -#else +# else {0, 6e-8, 0, 3e-8} #endif #endif From 25c51e871192246d02629e013a1afc46ce1c2cf1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 13:20:29 +0900 Subject: [PATCH 3536/3664] [ruamoko] Handle missing fonts correctly Carrying on as if the missing font had been loaded leads to way too many issues for it to be a good thing (not that that really needs to be said). Fixes the segfaults in my test scene. --- libs/ruamoko/rua_gui.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index 3b404071b..41e8caf86 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -223,9 +223,13 @@ bi (Font_Load) const char *font_path = P_GSTRING (pr, 0); int font_size = P_INT (pr, 1); + R_INT (pr) = 0; + QFile *font_file = QFS_FOpenFile (font_path); font_t *font = Font_Load (font_file, font_size); - R_INT (pr) = alloc_font (res, font); + if (font) { + R_INT (pr) = alloc_font (res, font); + } } bi (Passage_New) From eb41231559244cdc62b98af5add754183295db7c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 13:21:57 +0900 Subject: [PATCH 3537/3664] [ruamoko] Avoid copying a block of memory to itself Not a big deal, but valgrind didn't like it. --- ruamoko/qwaq/builtins/graphics.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 49b87abe8..860242e4f 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -311,8 +311,10 @@ generate_colormap (void) } } } - // fullbrights - memcpy (colors[i][224], colors[31][224], 32 * 3); + // fullbrights, but avoid copying the source row to itself + if (i != 31) { + memcpy (colors[i][224], colors[31][224], 32 * 3); + } } tex_t *cmap = ConvertImage (&tex, default_palette[0]); // the colormap has an extra byte indicating the number of fullbright From 9317ce7358fc3b01e1fc0a0b3deb768572a43d9e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 13:20:29 +0900 Subject: [PATCH 3538/3664] [ruamoko] Handle missing fonts correctly Carrying on as if the missing font had been loaded leads to way too many issues for it to be a good thing (not that that really needs to be said). Fixes the segfaults in my test scene. --- libs/ruamoko/rua_gui.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/ruamoko/rua_gui.c b/libs/ruamoko/rua_gui.c index 98c201716..b3d222802 100644 --- a/libs/ruamoko/rua_gui.c +++ b/libs/ruamoko/rua_gui.c @@ -228,9 +228,13 @@ bi (Font_Load) const char *font_path = P_GSTRING (pr, 0); int font_size = P_INT (pr, 1); + R_INT (pr) = 0; + QFile *font_file = QFS_FOpenFile (font_path); font_t *font = Font_Load (font_file, font_size); - R_INT (pr) = alloc_font (res, font); + if (font) { + R_INT (pr) = alloc_font (res, font); + } } bi (Font_Free) From 451a98d3918304337246a3cdceb092757bc5177a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 13:21:57 +0900 Subject: [PATCH 3539/3664] [ruamoko] Avoid copying a block of memory to itself Not a big deal, but valgrind didn't like it. --- ruamoko/qwaq/builtins/graphics.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index 631a2f690..b1aaacd65 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -313,8 +313,10 @@ generate_colormap (void) } } } - // fullbrights - memcpy (colors[i][224], colors[31][224], 32 * 3); + // fullbrights, but avoid copying the source row to itself + if (i != 31) { + memcpy (colors[i][224], colors[31][224], 32 * 3); + } } tex_t *cmap = ConvertImage (&tex, default_palette[0]); // the colormap has an extra byte indicating the number of fullbright From d39f1307c549af3be261b9fb5c6ae5b262202b57 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 17:01:05 +0900 Subject: [PATCH 3540/3664] [set] Make static init sets compatible with normal When using SET_STATIC_INIT, the set size needs to be the same as what set_new() would create for the same number of bits, otherwise the set will possibly get resized incorrectly (which is bad news when the array was allocated using alloca). While this is really a symptom of set_bits_t not getting the right size, getting weird segfaults is not a good way to diagnose the problem, and set_bits_t being the wrong size is just a minor pessimism. --- include/QF/set.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/QF/set.h b/include/QF/set.h index dafba428c..20b94897c 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -51,6 +51,7 @@ typedef uint32_t set_bits_t; - sizeof (int) - sizeof (unsigned))\ / sizeof (set_bits_t)) #define SET_BITS (sizeof (set_bits_t) * 8) +#define SET_DEFMAP_BITS (SET_DEFMAP_SIZE * SET_BITS) //NOTE: x is the element number, so size is x + 1 #define SET_SIZE(x) (((x) + SET_BITS) & ~(SET_BITS - 1)) #define SET_WORDS_STATIC(x) (SET_SIZE (x) / SET_BITS) @@ -63,9 +64,11 @@ typedef uint32_t set_bits_t; (((byte *)(s)->map)[(x) / 8] |= (SET_ONE << ((x) % 8))) #define SET_REMOVE(s, x) \ (((byte *)(s)->map)[(x) / 8] &= ~(SET_ONE << ((x) % 8))) +#define SET_LARGE_SET(x) (SET_SIZE (x) > SET_DEFMAP_BITS) +#define SET_SAFE_SIZE(x) (SET_LARGE_SET (x) ? SET_SIZE (x) : SET_DEFMAP_BITS) #define SET_STATIC_INIT(x, alloc) { \ - .size = SET_SIZE (x), \ - .map = alloc (SET_SIZE (x) / 8), \ + .size = SET_SAFE_SIZE (x), \ + .map = alloc (SET_SAFE_SIZE (x) / 8), \ } #define SET_STATIC_ARRAY(array) { \ .size = 8 * __builtin_choose_expr ( \ From 511389a973077dfaab1062a0abed16ca5df3758d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 28 Mar 2023 17:10:55 +0900 Subject: [PATCH 3541/3664] [set] Use correct size for set_bits_t on arm64 --- include/QF/set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/QF/set.h b/include/QF/set.h index 20b94897c..0d3c9327e 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -40,7 +40,7 @@ ///@{ //FIXME other archs -#ifdef __x86_64__ +#if defined(__x86_64__) || defined(__aarch64__) typedef uint64_t set_bits_t; #else typedef uint32_t set_bits_t; From eb8fc0fb9adf10bd964242fef05fd3656266bf84 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 29 Mar 2023 09:45:17 +0900 Subject: [PATCH 3542/3664] [vulkan] Be clearer about descriptor set layouts vs sets This get pretty confusing when you refer to both the sets and the set layouts in close vicinity. --- include/QF/Vulkan/render.h | 8 ++++---- libs/video/renderer/vulkan/render.c | 8 ++++---- libs/video/renderer/vulkan/vkparse.plist | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index a78f08f44..4dc03496e 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -27,13 +27,13 @@ typedef struct qfv_reference_s { int line; } qfv_reference_t; -typedef struct qfv_descriptorsetinfo_s { +typedef struct qfv_descriptorsetlayoutinfo_s { const char *name; VkDescriptorSetLayoutCreateFlags flags; uint32_t num_bindings; VkDescriptorSetLayoutBinding *bindings; VkDescriptorSetLayout setLayout; -} qfv_descriptorsetinfo_t; +} qfv_descriptorsetlayoutinfo_t; typedef struct qfv_layoutinfo_s { const char *name; @@ -243,8 +243,8 @@ typedef struct qfv_jobinfo_s { qfv_imageinfo_t *buffers; qfv_imageviewinfo_t *bufferviews; - uint32_t num_descriptorsets; - qfv_descriptorsetinfo_t *descriptorsets; + uint32_t num_descriptorsetlayouts; + qfv_descriptorsetlayoutinfo_t *descriptorsetlayouts; } qfv_jobinfo_t; #ifndef __QFCC__ diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 69a2987ee..fcaa152c8 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -546,8 +546,8 @@ find_subpass (qfv_dependencyinfo_t *d, uint32_t spind, static VkDescriptorSetLayout find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) { - for (uint32_t i = 0; i < s->jinfo->num_descriptorsets; i++) { - __auto_type ds = &s->jinfo->descriptorsets[i]; + for (uint32_t i = 0; i < s->jinfo->num_descriptorsetlayouts; i++) { + __auto_type ds = &s->jinfo->descriptorsetlayouts[i]; if (strcmp (ds->name, ref->name) == 0) { if (!ds->setLayout) { VkDescriptorSetLayoutCreateInfo cInfo = { @@ -1386,8 +1386,8 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) } if (rctx->jobinfo) { __auto_type jinfo = rctx->jobinfo; - for (uint32_t i = 0; i < jinfo->num_descriptorsets; i++) { - __auto_type setLayout = jinfo->descriptorsets[i].setLayout; + for (uint32_t i = 0; i < jinfo->num_descriptorsetlayouts; i++) { + __auto_type setLayout = jinfo->descriptorsetlayouts[i].setLayout; dfunc->vkDestroyDescriptorSetLayout (device->dev, setLayout, 0); } delete_memsuper (jinfo->memsuper); diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index a6a5f83f4..019c27e70 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -33,7 +33,7 @@ search = ( qfv_subpass_t, qfv_output_t, - qfv_descriptorsetinfo_t, + qfv_descriptorsetlayoutinfo_t, qfv_imageinfo_t, qfv_imageviewinfo_t, qfv_bufferinfo_t, @@ -616,8 +616,8 @@ parse = { values = subpasses; }; }; - qfv_descriptorsetinfo_s = { - .name = qfv_descriptorsetinfo_t; + qfv_descriptorsetlayoutinfo_s = { + .name = qfv_descriptorsetlayoutinfo_t; flags = auto; bindings = { type = (array, VkDescriptorSetLayoutBinding); @@ -714,9 +714,9 @@ parse = { values = steps; }; descriptorSetLayouts = { - type = (labeledarray, qfv_descriptorsetinfo_t, name); - size = num_descriptorsets; - values = descriptorsets; + type = (labeledarray, qfv_descriptorsetlayoutinfo_t, name); + size = num_descriptorsetlayouts; + values = descriptorsetlayouts; }; }; }; From e2464ed8791aa3aea6581ca5dee0ba19c0d6888e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 20 Apr 2023 15:15:12 +0900 Subject: [PATCH 3543/3664] [build] Fix some library install issues Removed a bogus dependency from libQFecs, and fixed the order of ui libraries. This takes care of some first-time make install issues. Libtool needs the libraries to be specified in dependency order. --- libs/ecs/Makemodule.am | 2 +- libs/ui/Makemodule.am | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/ecs/Makemodule.am b/libs/ecs/Makemodule.am index 4fc6b63f3..141db3b62 100644 --- a/libs/ecs/Makemodule.am +++ b/libs/ecs/Makemodule.am @@ -1,6 +1,6 @@ include libs/ecs/test/Makemodule.am -ecs_deps=libs/models/libQFmodels.la libs/util/libQFutil.la +ecs_deps=libs/util/libQFutil.la lib_LTLIBRARIES += libs/ecs/libQFecs.la diff --git a/libs/ui/Makemodule.am b/libs/ui/Makemodule.am index b5d2188a3..d73d20d8e 100644 --- a/libs/ui/Makemodule.am +++ b/libs/ui/Makemodule.am @@ -1,8 +1,8 @@ include libs/ui/test/Makemodule.am lib_LTLIBRARIES += \ - libs/ui/libQFgui.la \ - libs/ui/libQFui.la + libs/ui/libQFui.la \ + libs/ui/libQFgui.la gui_deps = \ libs/ui/libQFui.la From ce6b27cfae76b48c42878101eccb030864af34d2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 May 2023 17:17:50 +0900 Subject: [PATCH 3544/3664] [qfcc] Add failing test for array life It seems that the optimizer keeps array assignments live when passing the array as a pointer, but not when passing the address of an element. Found when testing the following code: BasisBlade *pga_blades[16] = { blades[1], blades[2], blades[3], blades[4], blades[7], blades[6], blades[5], blades[0], blades[8], blades[9], blades[10], blades[15], blades[14], blades[13], blades[12], blades[11], }; BasisGroup *pga_groups[4] = { [BasisGroup new:4 basis:&pga_blades[ 0]], [BasisGroup new:4 basis:&pga_blades[ 4]], [BasisGroup new:4 basis:&pga_blades[ 8]], [BasisGroup new:4 basis:&pga_blades[12]], }; Only the first element of pga_blades is being assigned in the optimized code, but everything is correct when not optimizing. --- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/arraylife.r | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tools/qfcc/test/arraylife.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index faf0eb9bb..078fa5bfa 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -10,6 +10,7 @@ fail_bins= test_progs_dat=\ tools/qfcc/test/address-cast.dat \ tools/qfcc/test/alignment.dat \ + tools/qfcc/test/arraylife.dat \ tools/qfcc/test/assignchain.dat \ tools/qfcc/test/anonstruct.dat \ tools/qfcc/test/chewed-alias.dat \ @@ -157,6 +158,16 @@ tools/qfcc/test/anonstruct.run: $(qfcc_test_run_deps) include $(anonstruct_dep) # am--include-marker r_depfiles_remade += $(anonstruct_dep) +tools_qfcc_test_arraylife_dat_SOURCES=tools/qfcc/test/arraylife.r +arraylife_obj=$(tools_qfcc_test_arraylife_dat_SOURCES:.r=.o) +arraylife_dep=$(call qcautodep,$(tools_qfcc_test_arraylife_dat_SOURCES)) +tools/qfcc/test/arraylife.dat$(EXEEXT): $(arraylife_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(arraylife_obj) +tools/qfcc/test/arraylife.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(arraylife_dep) # am--include-marker +r_depfiles_remade += $(arraylife_dep) + tools_qfcc_test_assignchain_dat_SOURCES=tools/qfcc/test/assignchain.r assignchain_obj=$(tools_qfcc_test_assignchain_dat_SOURCES:.r=.o) assignchain_dep=$(call qcautodep,$(tools_qfcc_test_assignchain_dat_SOURCES)) diff --git a/tools/qfcc/test/arraylife.r b/tools/qfcc/test/arraylife.r new file mode 100644 index 000000000..7df0ea8a8 --- /dev/null +++ b/tools/qfcc/test/arraylife.r @@ -0,0 +1,20 @@ +vector +bar (float *v) +{ + return [v[0], v[1], v[2]]; +} + +vector +foo (float x, float y, float z) +{ + float v[3] = { x, y, z }; + return bar (&v[0]); +} + +int +main () +{ + int ret = 0; + ret |= foo(1,2,3) != [1, 2, 3]; + return ret; +} From 904b211576531f776879418566fe40752acfb9e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 May 2023 21:12:23 +0900 Subject: [PATCH 3545/3664] [qfcc] Fix some comment typos in the flow analyzer --- tools/qfcc/source/flow.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index a8c94c952..a2d815828 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -278,7 +278,7 @@ flowvar_is_argument (flowvar_t *var) /** Check if the flowvar refers to a local variable. * * As this is simply "neither global nor pamam nor argument", all other - * flowvars are considered local, in particular actual non-staic function + * flowvars are considered local, in particular actual non-static function * scope variables and temp vars. */ static int @@ -553,7 +553,7 @@ static int flow_def_clear_flowvars (def_t *def, void *data) * * # Local variable representation * Defined local vars add their address in local space to the number of - * statements in the function. Thus their flow analysis address in in the + * statements in the function. Thus their flow analysis address is in the * range: * * ([num_statements ... num_statements+localsize]) @@ -573,7 +573,7 @@ static int flow_def_clear_flowvars (def_t *def, void *data) * * # Pseudo Address Space * Temporary variables are _effectively_ local variables and thus will - * be treated as such by the analizer in that their addresses and sizes + * be treated as such by the analyzer in that their addresses and sizes * will be used to determine which and how many set elements to use. * * However, at this stage, temporary variables do not have any address @@ -642,7 +642,7 @@ flow_build_vars (function_t *func) stuse = set_new (); stdef = set_new (); - // set up pseudo address space for temp vars so accessing tmp vars + // set up the pseudo address space for temp vars so accessing tmp vars // though aliases analyses correctly func->pseudo_addr = func->num_statements; func->pseudo_addr += func->locals->space->size; @@ -667,7 +667,7 @@ flow_build_vars (function_t *func) add_operand_chain (func, s->kill); } // and set the use/def sets for the vars (has to be a separate pass - // because the allias handling reqruires the flow address to be valid + // because the alias handling reqruires the flow address to be valid // (ie, not -1) for (i = 0; i < func->num_statements; i++) { s = func->statements[i]; @@ -1701,7 +1701,7 @@ flow_make_node (sblock_t *sblock, int id, function_t *func) /** Build the flow graph for the function. * - * In addition to the nodes create by the statement blocks, there are two + * In addition to the nodes created by the statement blocks, there are two * dummy blocks: * * \dot @@ -1724,7 +1724,7 @@ flow_make_node (sblock_t *sblock, int id, function_t *func) * * The exit block, which also is empty of statements, has its live vars * \a use set initilized to the set of global defs, which are simply numbered - * by their index in the functions list of flowvars. All other exit node sets + * by their index in the function's list of flowvars. All other exit node sets * are initialized to empty. * \f[ use_{live}=globals \f] */ From 61d656881b514342b4de217244c9813f94cb6a53 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 13 May 2023 21:13:52 +0900 Subject: [PATCH 3546/3664] [qfcc] Improve readability of flow vars in live I could never remember what any of the numbers meant. While define is still a little fuzzy (they're (pseudo)statement numbers), at least now I'll always know that the numbers are the define set. Also, having the flow address of the variable helps with understanding the reaching defs output. --- tools/qfcc/source/dot_flow.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index ecfbcc01f..62b7fc836 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -204,10 +204,18 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) dasprintf (dstr, "%*sfv_%p [shape=none,label=<\n", indent, "", graph); dasprintf (dstr, "%*s\n", indent + 2, ""); + dasprintf (dstr, "%*s\n", + indent + 4, ""); + dasprintf (dstr, "%*s" + "\n", + indent + 4, ""); for (i = 0; i < graph->func->num_vars; i++) { var = graph->func->vars[i]; - dasprintf (dstr, "%*s\n", indent + 4, "", + dasprintf (dstr, "%*s" + "\n", + indent + 4, "", var->number, html_string(operand_string (var->op)), + var->flowaddr, set_as_string (var->define)); } dasprintf (dstr, "%*s
flow vars
#nameaddrdefine
(%d) %s %s
%d%s%d%s
>];\n", indent + 2, ""); From 717cbaff87b399d15e20dba63c6d051524ffae28 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 May 2023 12:32:35 +0900 Subject: [PATCH 3547/3664] [gamecode] Support offset for lea on globals Allows using `array + offset` addressing. Both constant and variable offsets are supported. --- libs/gamecode/opcodes.py | 25 ++++++++++++++++++++++--- libs/gamecode/pr_exec.c | 17 ++++++++++++++++- libs/gamecode/test/test-lea.c | 4 +++- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/libs/gamecode/opcodes.py b/libs/gamecode/opcodes.py index 79e1949d9..b9c316a1d 100644 --- a/libs/gamecode/opcodes.py +++ b/libs/gamecode/opcodes.py @@ -11,7 +11,7 @@ bitmap_txt = """ 0 1011 otss udivops 0 1111 s0mm load64 0 1111 s1mm store64 -0 1111 n000 +0 1111 m000 lea2 1 0ooo ttss mathops 1 011r tuss shiftops @@ -46,20 +46,24 @@ address_types = [ "ev_entity, ev_field", "ev_ptr, ev_short", "ev_ptr, ev_int", + "ev_void, ev_short", + "ev_void, ev_int", ] address_widths = [ [ "1, 0", "1, 1", "1, 0", "1, 1", ], [ "2, 0", "1, 1", "1, 0", "1, 1", ], [ "3, 0", "1, 1", "1, 0", "1, 1", ], [ "4, 0", "1, 1", "1, 0", "1, 1", ], - [ "-1, 0", "1, 1", "1, 0", "1, 1", ], + [ "-1, 0", "1, 1", "1, 0", "1, 1", "-1, 0", "-1, 1"], ] -#store, pop and lea +#store, pop, lea store_fmt = [ "%ga", "%Ga.%Gb(%Ea)", "*(%Ga + %sb)", "*(%Ga + %Gb)", + "%ga + %sb", + "%ga + %Gb", ] # load and push load_fmt = [ @@ -267,6 +271,20 @@ lea_formats = { "lea_widths": address_widths[4], }, } +lea2_formats = { + "opcode": "OP_LEA_{op_mode[m]}", + "mnemonic": "lea", + "opname": "lea", + "format": "{lea_fmt[m+4]}, %gc", + "widths": "{lea_widths[m+4]}, 1", + "types": "{lea_types[m+4]}, ev_ptr", + "args": { + "op_mode": "EF", + "lea_fmt": store_fmt, + "lea_types": address_types, + "lea_widths": address_widths[4], + }, +} load_formats = { "opcode": "OP_LOAD_{op_mode[mm]}_{ss+1}", "mnemonic": "load", @@ -579,6 +597,7 @@ group_map = { "hops": hops_formats, "jump": jump_formats, "lea": lea_formats, + "lea2": lea2_formats, "load": load_formats, "load64": load64_formats, "mathops": mathops_formats, diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index ee7c100f1..639416c37 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -1812,6 +1812,14 @@ pr_address_mode (progs_t *pr, const dstatement_t *st, int mm_ind) // variable indexed pointer: *a + *b (supports -ve offset) mm_offs = OPA(ptr) + OPB(int); break; + case 4: + // global access with constant offset (supports -ve offset) + mm_offs = op_a - pr->pr_globals + (short) st->b; + break; + case 5: + // global access with variable offset (supports -ve offset) + mm_offs = op_a - pr->pr_globals + OPB(int); + break; } return pr->pr_globals + mm_offs; } @@ -2346,6 +2354,10 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) // 0 1110 OP_cmp(LE, <=); // 0 1111 + case OP_LEA_E: + mm = pr_address_mode (pr, st, 4); + OPC(ptr) = mm - pr->pr_globals; + break; case OP_LOAD64_B_3: case OP_LOAD64_C_3: case OP_LOAD64_D_3: @@ -2359,6 +2371,10 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_3)); VectorCopy (&OPC(long), &MM(long)); break; + case OP_LEA_F: + mm = pr_address_mode (pr, st, 5); + OPC(ptr) = mm - pr->pr_globals; + break; case OP_LOAD64_B_4: case OP_LOAD64_C_4: case OP_LOAD64_D_4: @@ -2372,7 +2388,6 @@ pr_exec_ruamoko (progs_t *pr, int exitdepth) mm = pr_address_mode (pr, st, (st_op - OP_STORE64_A_4)); MM(lvec4) = OPC(lvec4); break; - // spare #define OP_op(OP, op) \ OP_op_T (OP, I, int, ivec2, ivec4, op); \ diff --git a/libs/gamecode/test/test-lea.c b/libs/gamecode/test/test-lea.c index 33e148c16..a99702144 100644 --- a/libs/gamecode/test/test-lea.c +++ b/libs/gamecode/test/test-lea.c @@ -13,7 +13,7 @@ static pr_int_t lea_globals_expect[] = { // pointers 24, 26, 28, 29, 32, -4, -2, 0, - 1, 4, 0xdeadbeef, 0xfeedf00d, + 1, 4, 6, 32, 7, 34, 26, 88, }; @@ -23,6 +23,8 @@ static dstatement_t lea_statements[] = { {OP(0, 0, 0, OP_LEA_C), 2, 6, 13}, {OP(0, 0, 0, OP_LEA_D), 2, 6, 14}, {OP(0, 0, 0, OP_LEA_B), 4, 2, 15}, + {OP(0, 0, 0, OP_LEA_E), 4, 2, 10}, + {OP(0, 0, 0, OP_LEA_F), 4, 2, 11}, }; test_t tests[] = { From 8e1883a3064abf8e4951c71d61cb752e24aeae91 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 May 2023 12:36:48 +0900 Subject: [PATCH 3548/3664] [qfcc] Allow assignment of arrays to void pointers I guess it just never came up until now. --- tools/qfcc/source/type.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 135b45ba7..6a4cb9f5e 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -1253,7 +1253,8 @@ type_assignable (const type_t *dst, const type_t *src) return 1; // pointer = array if (is_ptr (dst) && is_array (src)) { - if (dst->t.fldptr.type == src->t.array.type) + if (is_void (dst->t.fldptr.type) + || dst->t.fldptr.type == src->t.array.type) return 1; return 0; } From 4435db03297a4f45078b590f408857935de9bce0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 May 2023 12:39:11 +0900 Subject: [PATCH 3549/3664] [qfcc] Support pointer arithmetic on arrays That is, `array + offset`. This actually works around the bug highlighted by arraylife.r (because the array is explicitly used), but is not a proper solution, so that test still fails of course. However, with this, it's no longer necessary to use `&array[index]` instead of `array + index`. --- tools/qfcc/source/expr_binary.c | 8 ++++++++ tools/qfcc/source/statements.c | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index 8396d4149..c55182667 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -1119,6 +1119,14 @@ binary_expr (int op, expr_t *e1, expr_t *e2) t2 = &type_float; e2 = cast_expr (t2, e2); } + if (is_array (t1) && (is_ptr (t2) || is_integral (t2))) { + t1 = pointer_type (t1->t.array.type); + e1 = cast_expr (t1, e1); + } + if (is_array (t2) && (is_ptr (t1) || is_integral (t1))) { + t2 = pointer_type (t2->t.array.type); + e2 = cast_expr (t2, e2); + } et1 = low_level_type (t1); et2 = low_level_type (t2); diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 833545c57..018803d94 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -677,6 +677,11 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op) lvalue->e.alias.expr, expr_int (offset)); offset = 0; + } else if (offset && is_constant (offset)) { + int o = expr_int (offset); + if (o < 32768 && o >= -32768) { + offset = expr_file_line (new_short_expr (o), offset); + } } s = new_statement (st_address, "lea", e); From 7b7b2ef0009816e4e09c9d574f4cabb58e55f0b8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 14 May 2023 13:40:40 +0900 Subject: [PATCH 3550/3664] [qfcc] Add flow defs for parameters Needed for proper analysis (ud-chains etc). Of course, it was then necessary to remove the parameter defs from the uninitialized defs. Also, plug a couple of memory leaks (forgot to free some temporary sets). --- tools/qfcc/include/function.h | 1 + tools/qfcc/source/flow.c | 29 +++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index af1f06bde..8e322de25 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -117,6 +117,7 @@ typedef struct function_s { struct flowvar_s **vars; int num_vars; ///< total number of variables referenced struct set_s *global_vars;///< set indicating which vars are global + struct set_s *param_vars; ///< set indicating which vars are params struct statement_s **statements; int num_statements; int pseudo_addr;///< pseudo address space for flow analysis diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index a2d815828..4f6968213 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -545,6 +545,14 @@ static int flow_def_clear_flowvars (def_t *def, void *data) return 0; } +static void +add_var_addrs (set_t *set, flowvar_t *var) +{ + for (int i = 0; i < var->op->size; i++) { + set_add (set, var->flowaddr + i); + } +} + /** Build an array of all the variables used by a function * * The array exists so variables can be referenced by number and thus used @@ -682,23 +690,24 @@ flow_build_vars (function_t *func) } } func->global_vars = set_new (); - // mark all global vars (except .return and .param_N) + func->param_vars = set_new (); + // mark all global vars (except .return and .param_N), and param vars for (i = num_flow_params; i < func->num_vars; i++) { - if (flowvar_is_global (func->vars[i])) + if (flowvar_is_global (func->vars[i])) { set_add (func->global_vars, i); + } + if (flowvar_is_param (func->vars[i])) { + add_var_addrs (func->param_vars, func->vars[i]); + } } // Put the local varibals in their place (set var->defined to the addresses // spanned by the var) for (i = 0; i < func->num_vars; i++) { - int j; - var = func->vars[i]; - if (flowvar_is_global (var) || flowvar_is_param (var)) { + if (flowvar_is_global (var)) {// || flowvar_is_param (var)) { continue; } - for (j = 0; j < var->op->size; j++) { - set_add (var->define, var->flowaddr + j); - } + add_var_addrs (var->define, var); } set_delete (stuse); @@ -759,6 +768,7 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) } // merge the alias kills with the current def's kills set_union (kill, tmp); + set_delete (tmp); } /** Compute reaching defs @@ -1036,6 +1046,8 @@ flow_uninitialized (flowgraph_t *graph) uninitialized = set_new (); node = graph->nodes[graph->num_nodes]; set_assign (uninitialized, node->reaching_defs.out); + // parameters are, by definition, initialized + set_difference (uninitialized, graph->func->param_vars); defs = set_new (); for (i = 0; i < graph->num_nodes; i++) { @@ -1058,6 +1070,7 @@ flow_uninitialized (flowgraph_t *graph) flow_uninit_scan_statements (node, defs, uninitialized); } set_delete (defs); + set_delete (uninitialized); } static void From 0d78a865c6a9f93c9c1f2b30223c2e328d81e962 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 15 May 2023 11:08:23 +0900 Subject: [PATCH 3551/3664] [qfcc] Show flow vars and statements for reaching dot A bunch of nodes with a pile of numbers doesn't mean much without the context. --- tools/qfcc/source/dot_flow.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 62b7fc836..34c32f77d 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -317,7 +317,8 @@ static flow_print_t live_print[] = { { 0 } }; static flow_print_t reaching_print[] = { - { print_flow_node_reaching, print_flow_edge}, + { print_flow_node_reaching, print_flow_edge, print_flow_vars}, + { print_flow_node_statements, print_flow_edge_statements}, { 0 } }; static flow_print_t statements_print[] = { From 8d4602ec61f432616ae9db5316a25fd6f3522c23 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 17 May 2023 01:09:31 +0900 Subject: [PATCH 3552/3664] [qfcc] Fix indexed pointer vector indexing The array access code was loading the vector, modifying the element, then forgetting to write the modified vector back to whence it came. However, that would be rather sub-optimal, so now when the vector is accessed by a pointer, the array code switches to field access to get at the vector element thus avoiding the need to copy the whole vector. --- tools/qfcc/source/expr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index dbbee0ff8..130294ba7 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2503,6 +2503,11 @@ array_expr (expr_t *array, expr_t *index) base = new_int_expr (0); } else { ele_type = ev_types[array_type->type]; + if (array->type == ex_uexpr && array->e.expr.op == '.') { + expr_t *vec = offset_pointer_expr (array->e.expr.e1, index); + vec = cast_expr (pointer_type (ele_type), vec); + return unary_expr ('.', vec); + } base = new_int_expr (0); } scale = new_int_expr (type_size (ele_type)); From 5f75616655bf9075a5d1d2570815388180128ebe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 17 May 2023 21:09:00 +0900 Subject: [PATCH 3553/3664] [ruamoko] Implement -describe for Set Being able to use printf directly is nice :) --- ruamoko/lib/Set.r | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ruamoko/lib/Set.r b/ruamoko/lib/Set.r index 4786b71a7..f3234290e 100644 --- a/ruamoko/lib/Set.r +++ b/ruamoko/lib/Set.r @@ -80,6 +80,11 @@ string set_as_string (set_t *set) = #0; [super dealloc]; } +- (string) describe +{ + return set_as_string (set); +} + - (Set *) add: (unsigned) x = #0; - (Set *) remove: (unsigned) x = #0; - (Set *) invert = #0; From 3a9148a3e000a595b5cb68ffa162f475a84abbec Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 18 May 2023 20:53:04 +0900 Subject: [PATCH 3554/3664] [ruamoko] Return nil for %@ printf format Fixes a segfault when attempting to print a nil object. --- libs/ruamoko/rua_obj.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 0e1a8ddb8..24fab22e9 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1470,6 +1470,9 @@ rua_obj_set_error_handler (progs_t *pr, void *data) static const char * rua_at_handler (progs_t *pr, pr_ptr_t at_param, void *_probj) { + if (!at_param) { + return "nil"; + } probj_t *probj = _probj; pr_id_t *obj = &G_STRUCT (pr, pr_id_t, at_param); pr_class_t *class = &G_STRUCT (pr, pr_class_t, obj->class_pointer); From c1c77bd64ab411f702cd622d56987ce4894c78a0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 May 2023 00:34:05 +0900 Subject: [PATCH 3555/3664] [gatest] Add basic geometric algebra test This is for developing methods of implementing geometric algebra and eventually playing with it visually. --- ruamoko/Makemodule.am | 1 + ruamoko/gatest/Makemodule.am | 35 ++++++ ruamoko/gatest/algebra.h | 28 +++++ ruamoko/gatest/algebra.r | 135 +++++++++++++++++++++++ ruamoko/gatest/basisblade.h | 26 +++++ ruamoko/gatest/basisblade.r | 106 ++++++++++++++++++ ruamoko/gatest/basisgroup.h | 25 +++++ ruamoko/gatest/basisgroup.r | 69 ++++++++++++ ruamoko/gatest/basislayout.h | 28 +++++ ruamoko/gatest/basislayout.r | 111 +++++++++++++++++++ ruamoko/gatest/main.r | 98 +++++++++++++++++ ruamoko/gatest/metric.h | 16 +++ ruamoko/gatest/metric.r | 37 +++++++ ruamoko/gatest/multivector.h | 28 +++++ ruamoko/gatest/multivector.r | 201 +++++++++++++++++++++++++++++++++++ ruamoko/gatest/util.h | 11 ++ ruamoko/gatest/util.r | 40 +++++++ 17 files changed, 995 insertions(+) create mode 100644 ruamoko/gatest/Makemodule.am create mode 100644 ruamoko/gatest/algebra.h create mode 100644 ruamoko/gatest/algebra.r create mode 100644 ruamoko/gatest/basisblade.h create mode 100644 ruamoko/gatest/basisblade.r create mode 100644 ruamoko/gatest/basisgroup.h create mode 100644 ruamoko/gatest/basisgroup.r create mode 100644 ruamoko/gatest/basislayout.h create mode 100644 ruamoko/gatest/basislayout.r create mode 100644 ruamoko/gatest/main.r create mode 100644 ruamoko/gatest/metric.h create mode 100644 ruamoko/gatest/metric.r create mode 100644 ruamoko/gatest/multivector.h create mode 100644 ruamoko/gatest/multivector.r create mode 100644 ruamoko/gatest/util.h create mode 100644 ruamoko/gatest/util.r diff --git a/ruamoko/Makemodule.am b/ruamoko/Makemodule.am index 202fbffb6..c7f813b17 100644 --- a/ruamoko/Makemodule.am +++ b/ruamoko/Makemodule.am @@ -6,5 +6,6 @@ include ruamoko/lib/Makemodule.am include ruamoko/game/Makemodule.am include ruamoko/gui/Makemodule.am include ruamoko/cl_menu/Makemodule.am +include ruamoko/gatest/Makemodule.am include ruamoko/scheme/Makemodule.am include ruamoko/qwaq/Makemodule.am diff --git a/ruamoko/gatest/Makemodule.am b/ruamoko/gatest/Makemodule.am new file mode 100644 index 000000000..d1021be95 --- /dev/null +++ b/ruamoko/gatest/Makemodule.am @@ -0,0 +1,35 @@ +noinst_PROGRAMS += ruamoko/gatest/gatest.dat$(EXEEXT) + +gatest_dat_src= \ + ruamoko/gatest/algebra.r \ + ruamoko/gatest/basisblade.r \ + ruamoko/gatest/basisgroup.r \ + ruamoko/gatest/basislayout.r \ + ruamoko/gatest/main.r \ + ruamoko/gatest/metric.r \ + ruamoko/gatest/multivector.r \ + ruamoko/gatest/util.r + +ruamoko_gatest_gatest_dat_SOURCES=$(gatest_dat_src) +ruamoko_gatest_gatest_obj=$(ruamoko_gatest_gatest_dat_SOURCES:.r=.o) +ruamoko_gatest_gatest_dep=$(call qcautodep,$(ruamoko_gatest_gatest_dat_SOURCES:.o=.Qo)) +ruamoko/gatest/gatest.dat$(EXEEXT): $(ruamoko_gatest_gatest_obj) $(QFCC_DEP) $(libui) ruamoko/lib/libr.a + $(V_QFCCLD)$(QLINK) -o $@ $(ruamoko_gatest_gatest_obj) $(libui) -lr +include $(ruamoko_gatest_gatest_dep) # am--include-marker +r_depfiles_remade += $(ruamoko_gatest_gatest_dep) + +EXTRA_PROGRAMS += \ + ruamoko/gatest/gatest + +EXTRA_DIST += \ + $(gatest_dat_src) \ + ruamoko/gatest/algebra.h \ + ruamoko/gatest/basisblade.h \ + ruamoko/gatest/basisgroup.h \ + ruamoko/gatest/basislayout.h \ + ruamoko/gatest/metric.h \ + ruamoko/gatest/multivector.h \ + ruamoko/gatest/util.h +CLEANFILES += \ + ruamoko/gatest/*.dat \ + ruamoko/gatest/*.sym diff --git a/ruamoko/gatest/algebra.h b/ruamoko/gatest/algebra.h new file mode 100644 index 000000000..ded06d265 --- /dev/null +++ b/ruamoko/gatest/algebra.h @@ -0,0 +1,28 @@ +#ifndef __algebra_h +#define __algebra_h + +#include "Object.h" + +@class Metric; +@class BasisGroup; +@class BasisLayout; + +@interface Algebra : Object +{ + Metric *metric; + BasisGroup **grades; + BasisLayout *layout; + int num_components; + int dimension; +} ++(Algebra *) R:(int)p, int m, int z; ++(Algebra *) PGA:(int)n; +-(void) print; +-(BasisGroup *)grade:(int)k; +-(BasisLayout *)layout; +-(Metric *) metric; +-(int)count; +-(int)dimension; +@end + +#endif//__algebra_h diff --git a/ruamoko/gatest/algebra.r b/ruamoko/gatest/algebra.r new file mode 100644 index 000000000..6be0b8dc0 --- /dev/null +++ b/ruamoko/gatest/algebra.r @@ -0,0 +1,135 @@ +#include + +#include "algebra.h" +#include "metric.h" +#include "basisblade.h" +#include "basisgroup.h" +#include "basislayout.h" +#include "util.h" + +@implementation Algebra ++(Algebra *) R:(int)p, int m, int z +{ + Algebra *a = [[[Algebra alloc] init] autorelease]; + a.metric = [[Metric R:p, m, z] retain]; + + int d = p + m + z; + a.dimension = d; + a.num_components = 1 << d; + BasisBlade **blades = obj_malloc (a.num_components * sizeof (BasisBlade *)); + int *counts = binomial (d); + int *indices = obj_malloc ((d + 1) * sizeof (int)); + + indices[0] = 0; + for (int i = 0; i < d; i++) { + indices[i + 1] = counts[i]; + } + prefixsum (indices, d + 1); + for (int i = 0; i < a.num_components; i++) { + int grade = count_bits (i); + int ind = indices[grade]++; + blades[ind] = [BasisBlade basis:i]; + } + + a.grades = obj_malloc ((d + 1) * sizeof (BasisGroup *)); + for (int i = 0; i < d + 1; i++) { + int c = counts[i]; + int ind = indices[i]; + a.grades[i] = [BasisGroup new:c basis:blades + ind - c]; + } + + if (p == 3 && m == 0 && z == 1) { + // 3d PGA (w squares to 0, x y z square to +1): + // : x y z w + // : yz zx xy 1 + // : xw yw zw xyzw + // : zyw xzw yxw xyz + BasisBlade *pga_blades[16] = { + blades[1], blades[2], blades[3], blades[4], + blades[7], blades[6], blades[5], blades[0], + blades[8], blades[9], blades[10], blades[15], + blades[14], blades[13], blades[12], blades[11], + }; + BasisGroup *pga_groups[4] = { + [BasisGroup new:4 basis:pga_blades + 0], + [BasisGroup new:4 basis:pga_blades + 4], + [BasisGroup new:4 basis:pga_blades + 8], + [BasisGroup new:4 basis:pga_blades + 12], + }; + a.layout = [[BasisLayout new:4 groups: pga_groups] retain]; + } else if (p == 2 && m == 0 && z == 1) { + // 2d PGA (w squares to 0, x y square to +1): + // : x y w 1 + // : yw wx xy xyw + BasisBlade *pga_blades[8] = { + blades[1], blades[2], blades[3], blades[0], + blades[6], blades[5], blades[4], blades[7], + }; + BasisGroup *pga_groups[2] = { + [BasisGroup new:4 basis:pga_blades + 0], + [BasisGroup new:4 basis:pga_blades + 4], + }; + a.layout = [[BasisLayout new:2 groups: pga_groups] retain]; + } else { + // just use the grades as the default layout + a.layout = [[BasisLayout new:d + 1 groups: a.grades] retain]; + } + + obj_free (indices); + obj_free (counts); + obj_free (blades); + return a; +} + ++(Algebra *) PGA:(int)n +{ + return [Algebra R:n, 0, 1]; +} + +-(void)dealloc +{ + obj_free (grades); + [metric release]; + [layout release]; + [super dealloc]; +} + +-(BasisGroup *)grade:(int)k +{ + return grades[k]; +} + +-(BasisLayout *)layout +{ + return layout; +} + +-(Metric *) metric +{ + return metric; +} + +-(int)count +{ + return num_components; +} + +-(int)dimension +{ + return dimension; +} + +-(void) print +{ + int count = [layout count]; + for (int i = 0; i < count; i++) { + BasisGroup *g = [layout group:i]; + int c = [g count]; + printf ("%d %d %@\n", i, c, [g set]); + for (int j = 0; j < c; j++) { + printf (" %@\n", [g bladeAt:j]); + } + } +} + +@end diff --git a/ruamoko/gatest/basisblade.h b/ruamoko/gatest/basisblade.h new file mode 100644 index 000000000..115a81dee --- /dev/null +++ b/ruamoko/gatest/basisblade.h @@ -0,0 +1,26 @@ +#ifndef __basisblade_h +#define __basisblade_h +#include + +@class Metric; + +@interface BasisBlade : Object +{ + unsigned mask; + double scale; +} ++(BasisBlade *) scalar:(double) scale; ++(BasisBlade *) zero; ++(BasisBlade *) basis:(unsigned) mask; ++(BasisBlade *) basis:(unsigned) mask scale:(double) scale; +-(BasisBlade *) product:(BasisBlade *) b isOuter:(int)outer metric:(Metric *) m; +-(BasisBlade *) outerProduct:(BasisBlade *) b; +-(BasisBlade *) geometricProduct:(BasisBlade *) b metric:(Metric *) m; +-(BasisBlade *) geometricProduct:(BasisBlade *) b; +-(int) grade; +-(unsigned) mask; +-(double) scale; +-(string) name; +@end + +#endif//__basisblade_h diff --git a/ruamoko/gatest/basisblade.r b/ruamoko/gatest/basisblade.r new file mode 100644 index 000000000..2564d0fe2 --- /dev/null +++ b/ruamoko/gatest/basisblade.r @@ -0,0 +1,106 @@ +#include +#include "basisblade.h" +#include "metric.h" +#include "util.h" + +@implementation BasisBlade : Object +-(BasisBlade *) initWithMask:(unsigned) mask scale:(double) scale +{ + if (!(self = [super init])) { + return self; + } + self.mask = mask; + self.scale = scale; + return self; +} + ++(BasisBlade *) scalar:(double) scale +{ + return [[[BasisBlade alloc] initWithMask:0 scale:scale] autorelease]; +} + ++(BasisBlade *) zero +{ + return [[[BasisBlade alloc] initWithMask:0 scale:0] autorelease]; +} + ++(BasisBlade *) basis:(unsigned) mask +{ + return [[[BasisBlade alloc] initWithMask:mask scale:1] autorelease]; +} + ++(BasisBlade *) basis:(unsigned) mask scale:(double) scale +{ + return [[[BasisBlade alloc] initWithMask:mask scale:scale] autorelease]; +} + +-(BasisBlade *) product:(BasisBlade *) b isOuter:(int)outer metric:(Metric *)m +{ + if (outer && (mask & b.mask)) { + // the two blades share at least one basis vector + return [BasisBlade zero]; + } + if (!scale || !b.scale) { + return [BasisBlade zero]; + } + int sign = 1 - (-(count_flips (mask, b.mask) & 1) & 2); + double s = scale * b.scale * sign; + if (m) { + s *= [m apply: mask, b.mask]; + if (!s) { + return [BasisBlade zero]; + } + } + return [BasisBlade basis:(mask ^ b.mask) scale:s]; +} + +-(BasisBlade *) outerProduct:(BasisBlade *) b +{ + return [self product:b isOuter:1 metric:nil]; +} + +-(BasisBlade *) geometricProduct:(BasisBlade *) b metric:(Metric *) m +{ + return [self product:b isOuter:0 metric:m]; +} + +-(BasisBlade *) geometricProduct:(BasisBlade *) b +{ + return [self product:b isOuter:0 metric:nil]; +} + +-(int) grade +{ + return count_bits (mask); +} + +-(unsigned) mask +{ + return mask; +} + +-(double) scale +{ + return scale; +} + +-(string) name +{ + string basis = ""; + + for (int i = 0; i < 32; i++) { + if (mask & (1 << i)) { + basis += sprintf("%x", i + 1); + } + } + if (basis) { + basis = "e" + basis; + } + return basis; +} + +-(string) describe +{ + return sprintf ("%g%s", scale, [self name]); +} +@end diff --git a/ruamoko/gatest/basisgroup.h b/ruamoko/gatest/basisgroup.h new file mode 100644 index 000000000..e1ee77d17 --- /dev/null +++ b/ruamoko/gatest/basisgroup.h @@ -0,0 +1,25 @@ +#ifndef __basisgroup_h +#define __basisgroup_h +#include + +@class Metric; +@class BasisBlade; +@class Set; + +@interface BasisGroup : Object +{ + int count; + uivec2 range; + BasisBlade **blades; + int *map; + Set *set; +} ++(BasisGroup *) new:(int) count basis:(BasisBlade **)blades; +-(int)count; +-(uivec2)blade_range; +-(BasisBlade *) bladeAt:(int) ind; +-(BasisBlade *) blade:(unsigned) mask; +-(Set *) set; +@end + +#endif//__basisgroup_h diff --git a/ruamoko/gatest/basisgroup.r b/ruamoko/gatest/basisgroup.r new file mode 100644 index 000000000..abe18f4e1 --- /dev/null +++ b/ruamoko/gatest/basisgroup.r @@ -0,0 +1,69 @@ +#include +#include "basisblade.h" +#include "basisgroup.h" + +@implementation BasisGroup ++(BasisGroup *) new:(int) count basis:(BasisBlade **)blades +{ + BasisGroup *group = [[[BasisGroup alloc] init] autorelease]; + group.blades = obj_malloc (count * sizeof (BasisBlade *)); + group.set = [[Set set] retain]; + group.range = { ~0u, 0 }; + for (int i = 0; i < count; i++) { + group.blades[i] = [blades[i] retain]; + unsigned m = [blades[i] mask]; + if (m < group.range[0]) { + group.range[0] = m; + } + if (m > group.range[1]) { + group.range[1] = m; + } + [group.set add:m]; + } + int num = group.range[1] - group.range[0] + 1; + group.map = obj_malloc (num * sizeof (int)); + for (int i = 0; i < count; i++) { + group.map[[blades[i] mask] - group.range[0]] = i; + } + group.count = count; + return group; +} + +-(void)dealloc +{ + [set release]; + for (int i = 0; i < count; i++) { + [blades[i] release]; + } + obj_free (blades); + [super dealloc]; +} + +-(int)count +{ + return count; +} + +-(uivec2)blade_range +{ + return range; +} + +-(BasisBlade *) bladeAt:(int) ind +{ + return blades[ind]; +} + +-(BasisBlade *) blade:(unsigned) mask +{ + if (![set is_member:mask]) { + return nil; + } + return blades[map[mask - range[0]]]; +} + +-(Set *) set +{ + return set; +} +@end diff --git a/ruamoko/gatest/basislayout.h b/ruamoko/gatest/basislayout.h new file mode 100644 index 000000000..471a46316 --- /dev/null +++ b/ruamoko/gatest/basislayout.h @@ -0,0 +1,28 @@ +#ifndef __basislayout_h +#define __basislayout_h +#include + +@class BasisGroup; +@class Set; + +@interface BasisLayout : Object +{ + int count; + uivec2 range; + BasisGroup **groups; + ivec3 *group_map; + int *mask_map; + int blade_count; + Set *set; +} ++(BasisLayout *) new:(int) count groups:(BasisGroup **)groups; +-(int)count; +-(int)num_components; +-(int)blade_count; +-(BasisGroup *) group:(int) ind; +-(BasisBlade *) bladeAt:(int) ind; +-(int) bladeIndex:(unsigned) mask; +-(Set *) set; +@end + +#endif//__basislayout_h diff --git a/ruamoko/gatest/basislayout.r b/ruamoko/gatest/basislayout.r new file mode 100644 index 000000000..5bd1d452f --- /dev/null +++ b/ruamoko/gatest/basislayout.r @@ -0,0 +1,111 @@ +#include +#include +#include "basisblade.h" +#include "basisgroup.h" +#include "basislayout.h" +#include "util.h" + +@implementation BasisLayout ++(BasisLayout *) new:(int) count groups:(BasisGroup **)groups +{ + BasisLayout *layout = [[[BasisLayout alloc] init] autorelease]; + layout.count = count; + layout.groups = obj_malloc (count * sizeof (BasisGroup *)); + layout.set = [[Set set] retain]; + layout.range = { ~0u, 0 }; + int *group_base = obj_malloc ((count + 1) * sizeof (int)); + group_base[0] = 0; + int num_blades = 0; + for (int i = 0; i < count; i++) { + layout.groups[i] = [groups[i] retain]; + [layout.set union:[groups[i] set]]; + group_base[i + 1] = [groups[i] count]; + num_blades += group_base[i + 1]; + + uivec2 r = [groups[i] blade_range]; + if (r[0] < layout.range[0]) { + layout.range[0] = r[0]; + } + if (r[1] > layout.range[1]) { + layout.range[1] = r[1]; + } + } + prefixsum (group_base, count); + layout.blade_count = num_blades; + layout.group_map = obj_malloc (num_blades * sizeof (ivec3)); + + int num = layout.range[1] - layout.range[0] + 1; + layout.mask_map = obj_malloc (num * sizeof (int)); + int *group_inds = obj_malloc ((count + 1) * sizeof (int)); + for (int i = 0; i < count; i++) { + BasisGroup *g = groups[i]; + group_inds[i] = 0; + for (int j = 0; j < [g count]; j++) { + BasisBlade *b = [g bladeAt:j]; + layout.mask_map[[b mask] - layout.range[0]] = group_inds[count]; + layout.group_map[group_inds[count]][0] = i; + layout.group_map[group_inds[count]][1] = group_inds[i]++; + layout.group_map[group_inds[count]][2] = group_base[i]; + group_inds[count]++; + } + } + obj_free (group_inds); + return layout; +} + +-(void)dealloc +{ + [set release]; + for (int i = 0; i < count; i++) { + [groups[i] release]; + } + obj_free (groups); + obj_free (group_map); + [super dealloc]; +} + +-(int)count +{ + return count; +} + +-(int)num_components +{ + int num_components = 0; + // assumes there is no overlap + for (int i = 0; i < count; i++) { + num_components += [groups[i] count]; + } + return num_components; +} + +-(int)blade_count +{ + return blade_count; +} + +-(BasisGroup *) group:(int) ind +{ + return groups[ind]; +} + +-(BasisBlade *) bladeAt:(int) ind +{ + ivec3 gm = group_map[ind]; + BasisGroup *g = groups[gm[0]]; + return [g bladeAt:ind - gm[2]]; +} + +-(int) bladeIndex:(unsigned) mask +{ + if (![set is_member:mask]) { + return 0; + } + return mask_map[mask - range[0]]; +} + +-(Set *) set +{ + return set; +} +@end diff --git a/ruamoko/gatest/main.r b/ruamoko/gatest/main.r new file mode 100644 index 000000000..81087ef4a --- /dev/null +++ b/ruamoko/gatest/main.r @@ -0,0 +1,98 @@ +#include +#include "algebra.h" +#include "basisblade.h" +#include "basisgroup.h" +#include "metric.h" +#include "multivector.h" +#include "util.h" + +@static AutoreleasePool *autorelease_pool; +@static void +arp_start (void) +{ + autorelease_pool = [[AutoreleasePool alloc] init]; +} + +@static void +arp_end (void) +{ + [autorelease_pool release]; + autorelease_pool = nil; +} + +int +main () +{ + arp_start (); + + BasisBlade *a = [[BasisBlade basis:1] retain]; + BasisBlade *b = [[BasisBlade basis:2] retain]; + BasisBlade *c = [[BasisBlade basis:4] retain]; + BasisBlade *d = [[BasisBlade basis:8] retain]; + BasisBlade *blades[] = {a, b, c, d}; + static string names[] = {"a", "b", "c", "d"}; + +// printf ("a: %@\n", a); +// printf ("b: %@\n", b); +// printf ("c: %@\n", c); +// printf ("d: %@\n", d); + + arp_end (); +#if 0 + arp_start (); + for (int i = 0; i < 4; i++) { + arp_end (); + arp_start (); + BasisBlade *vec = blades[i]; + printf ("%s: %@\n", names[i], vec); + for (int j = 0; j < 4; j++) { + BasisBlade *bvec = [vec outerProduct:blades[j]]; + if (![bvec scale]) { + continue; + } + printf ("%s^%s: %@\n", names[i], names[j], bvec); + for (int k = 0; k < 4; k++) { + BasisBlade *tvec = [bvec outerProduct:blades[k]]; + if (![tvec scale]) { + continue; + } + printf ("%s^%s^%s: %@\n", names[i], names[j], names[k], + tvec); + for (int l = 0; l < 4; l++) { + BasisBlade *qvec = [tvec outerProduct:blades[l]]; + if (![qvec scale]) { + continue; + } + printf ("%s^%s^%s^%s: %@\n", + names[i], names[j], names[k], names[l], + qvec); + } + } + } + } + arp_end (); +#endif + arp_start (); + + Metric *m = [Metric R:3,0,1]; + BasisBlade *ad = [a geometricProduct:d metric:m]; + BasisBlade *prod = [ad geometricProduct:ad metric:m]; + printf ("%s%s %s%s: %@\n", + names[0], names[3], names[0], names[3], prod); + + Algebra *alg = [Algebra R:3, 0, 1]; + double vals1[32] = {1, 0, 0, 8}; + static double vals2[32] = {0, 1, 0, 8};//FIXME qfcc bug (static) + static double origin_vals[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + MultiVector *plane1 = [MultiVector new:alg values:vals1]; + MultiVector *plane2 = [MultiVector new:alg values:vals2]; + MultiVector *origin = [MultiVector new:alg values:origin_vals]; + + MultiVector *line = [plane1 wedge:plane2]; + MultiVector *point = [[line dot:origin] product:line]; + printf ("plane1:%@\nplane2:%@\nline:%@\norigin:%@\n", plane1, plane2, line, origin); + printf ("point:%@\n", point); + + arp_end (); + return 0; +} diff --git a/ruamoko/gatest/metric.h b/ruamoko/gatest/metric.h new file mode 100644 index 000000000..357ccab18 --- /dev/null +++ b/ruamoko/gatest/metric.h @@ -0,0 +1,16 @@ +#ifndef __metric_h +#define __metric_h + +#include + +@interface Metric : Object +{ + unsigned plus; // mask of elements that square to +1 + unsigned minus; // mask of elements that square to -1 + unsigned zero; // mask of elements that square to 0 +} ++(Metric *)R:(int)p, int m, int z; +-(double)apply:(unsigned) a, unsigned b; +@end + +#endif//__metric_h diff --git a/ruamoko/gatest/metric.r b/ruamoko/gatest/metric.r new file mode 100644 index 000000000..26e37e28e --- /dev/null +++ b/ruamoko/gatest/metric.r @@ -0,0 +1,37 @@ +#include "metric.h" + +@implementation Metric ++(Metric *)R:(int)p, int m, int z +{ + Metric *metric = [[[Metric alloc] init] autorelease]; + metric.plus = (1 << p) - 1; + metric.minus = ((1 << m) - 1) << p; + metric.zero = ((1 << z) - 1) << (p + m); + return metric; +} + +static double +count_minus (unsigned minus) +{ + double s = 1; + while (minus) { + if (minus & 1) { + s = -s; + } + minus >>= 1; + } + return s; +} + +-(double)apply:(unsigned) a, unsigned b +{ + // find all the squared elements + unsigned c = a & b; + // any elements that square to 0 result in 0 + if (c & zero) { + return 0; + } + return count_minus (c & minus); +} + +@end diff --git a/ruamoko/gatest/multivector.h b/ruamoko/gatest/multivector.h new file mode 100644 index 000000000..c17cebef6 --- /dev/null +++ b/ruamoko/gatest/multivector.h @@ -0,0 +1,28 @@ +#ifndef __multivector_h +#define __multivector_h +#include + +@class Algebra; +@class BasisLayout; + +@interface MultiVector : Object +{ + double *components; + Algebra *algebra; + BasisLayout *layout; + int num_components; +} ++(MultiVector *) new:(Algebra *) algebra; +// NOTE: values must have the same layout as algebra ++(MultiVector *) new:(Algebra *) algebra values:(double *) values; ++(MultiVector *) new:(Algebra *) algebra group:(BasisGroup *) group; +// NOTE: values must have the same layout as group ++(MultiVector *) new:(Algebra *) algebra group:(BasisGroup *) group values:(double *) values; ++(MultiVector *) copy:(MultiVector *) src; +-(MultiVector *) product:(MultiVector *) rhs; +-(MultiVector *) wedge:(MultiVector *) rhs; +-(MultiVector *) dot:(MultiVector *) rhs; +-(MultiVector *) dual; +@end + +#endif//__multivector_h diff --git a/ruamoko/gatest/multivector.r b/ruamoko/gatest/multivector.r new file mode 100644 index 000000000..a29dff8c2 --- /dev/null +++ b/ruamoko/gatest/multivector.r @@ -0,0 +1,201 @@ +#include +#include "algebra.h" +#include "basisblade.h" +#include "basislayout.h" +#include "multivector.h" +#include "util.h" + +@implementation MultiVector +static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) +{ + MultiVector *mv = [[[MultiVector alloc] init] autorelease]; + mv.algebra = [algebra retain]; + layout = layout ? layout : [algebra layout]; + mv.layout = [layout retain]; + mv.num_components = [layout num_components]; + mv.components = obj_malloc (mv.num_components * sizeof (double)); + return mv; +} + ++(MultiVector *) new:(Algebra *) algebra +{ + MultiVector *mv = new_mv (algebra, nil); + for (int i = 0; i < mv.num_components; i++) { + mv.components[i] = 0; + } + return mv; +} + ++(MultiVector *) new:(Algebra *) algebra values:(double *) values +{ + MultiVector *mv = new_mv (algebra, nil); + for (int i = 0; i < mv.num_components; i++) { + mv.components[i] = values[i]; + } + return mv; +} + ++(MultiVector *) new:(Algebra *) algebra group:(BasisGroup *) group +{ + BasisLayout *layout = [BasisLayout new:1 groups:&group]; + MultiVector *mv = new_mv (algebra, layout); + for (int i = 0; i < mv.num_components; i++) { + mv.components[i] = 0; + } + return mv; +} + ++(MultiVector *) new:(Algebra *) algebra group:(BasisGroup *) group values:(double *) values +{ + BasisLayout *layout = [BasisLayout new:1 groups:&group]; + MultiVector *mv = new_mv (algebra, layout); + for (int i = 0; i < mv.num_components; i++) { + mv.components[i] = values[i]; + } + return mv; +} + ++(MultiVector *) copy:(MultiVector *) src +{ + MultiVector *mv = new_mv (src.algebra, src.layout); + for (int i = 0; i < mv.num_components; i++) { + mv.components[i] = src.components[i]; + } + return mv; +} + +-(void)dealloc +{ + [algebra release]; + [layout release]; + obj_free (components); + [super dealloc]; +} + +-(string)describe +{ + string str = nil; + + for (int i = 0; i < num_components; i++) { + if (!components[i]) { + continue; + } + BasisBlade *b = [layout bladeAt:i]; + str = sprintf ("%s%s%g%s", str, str ? " + " : "", components[i], [b name]); + } + if (!str) { + str = "0"; + } + return str; +} + +-(MultiVector *) product:(MultiVector *) rhs +{ + MultiVector *prod = new_mv (algebra, nil); + for (int i = 0; i < num_components; i++) { + if (!components[i]) { + continue; + } + double lc = components[i]; + BasisBlade *lb = [layout bladeAt:i]; + for (int j = 0; j < rhs.num_components; j++) { + if (!rhs.components[j]) { + continue; + } + double rc = rhs.components[j]; + BasisBlade *rb = [rhs.layout bladeAt:j]; + BasisBlade *b = [lb geometricProduct:rb metric:[algebra metric]]; + double s = [b scale]; + if (!s) { + continue; + } + int ind = [rhs.layout bladeIndex:[b mask]]; + prod.components[ind] += s * lc * rc; + } + } + return prod; +} + +-(MultiVector *) wedge:(MultiVector *) rhs +{ + MultiVector *prod = new_mv (algebra, nil); + for (int i = 0; i < num_components; i++) { + if (!components[i]) { + continue; + } + double lc = components[i]; + BasisBlade *lb = [layout bladeAt:i]; + for (int j = 0; j < rhs.num_components; j++) { + if (!rhs.components[j]) { + continue; + } + double rc = rhs.components[j]; + BasisBlade *rb = [rhs.layout bladeAt:j]; + BasisBlade *b = [lb outerProduct:rb]; + double s = [b scale]; + if (!s) { + continue; + } + int ind = [rhs.layout bladeIndex:[b mask]]; + prod.components[ind] += s * lc * rc; + } + } + return prod; +} + +-(MultiVector *) dot:(MultiVector *) rhs +{ + MultiVector *prod = new_mv (algebra, nil); + for (int i = 0; i < num_components; i++) { + if (!components[i]) { + continue; + } + double lc = components[i]; + BasisBlade *lb = [layout bladeAt:i]; + int lg = [lb grade]; + for (int j = 0; j < rhs.num_components; j++) { + if (!rhs.components[j]) { + continue; + } + double rc = rhs.components[j]; + BasisBlade *rb = [rhs.layout bladeAt:j]; + int rg = [rb grade]; + BasisBlade *b = [lb geometricProduct:rb]; + int g = [b grade]; + if ((lg <= rg) && (g != rg - lg)) { + continue; + } + if ((lg > rg) && (g != lg - rg)) { + continue; + } + double s = [b scale]; + if (!s) { + continue; + } + int ind = [rhs.layout bladeIndex:[b mask]]; + prod.components[ind] += s * lc * rc; + } + } + return prod; +} + +-(MultiVector *) dual +{ + MultiVector *dual = new_mv (algebra, nil); + unsigned dual_mask = (1 << [algebra dimension]) - 1; + printf ("dual: %x %d\n", dual_mask, [algebra dimension]); + for (int i = 0; i < num_components; i++) { + if (!components[i]) { + continue; + } + double lc = components[i]; + BasisBlade *lb = [layout bladeAt:i]; + unsigned mask = [lb mask] ^ dual_mask; + double s = 1; + int ind = [layout bladeIndex:mask]; + printf (" : %x %d\n", mask, ind); + dual.components[ind] += s * lc; + } + return dual; +} +@end diff --git a/ruamoko/gatest/util.h b/ruamoko/gatest/util.h new file mode 100644 index 000000000..b80ca64db --- /dev/null +++ b/ruamoko/gatest/util.h @@ -0,0 +1,11 @@ +#ifndef __util_h +#define __util_h + +void printf(string fmt, ...); +void traceon(void); +void traceoff(void); +int *binomial (int n); +int count_bits (unsigned v); +int count_flips (unsigned a, unsigned b); + +#endif//__util_h diff --git a/ruamoko/gatest/util.r b/ruamoko/gatest/util.r new file mode 100644 index 000000000..a4716429d --- /dev/null +++ b/ruamoko/gatest/util.r @@ -0,0 +1,40 @@ +#include +#include "util.h" + +void printf(string fmt, ...) = #0; +void traceon(void) = #0; +void traceoff(void) = #0; + +int * +binomial (int n) +{ + int *coef = obj_malloc ((n + 1) * sizeof (int)); + int c = 1; + for (int i = 0; i < n + 1; i++) { + coef[i] = c; + c = (c * (n - i)) / (i + 1); + } + return coef; +} + +int +count_bits (unsigned v) +{ + int c = 0; + for (; v; c++) { + v &= v - 1u; //XXX bug in qfcc: just 1 results in extra temp + } + return c; +} + +int +count_flips (unsigned a, unsigned b) +{ + int c = 0; + a >>= 1; + while (a) { + c += count_bits (a & b); + a >>= 1; + } + return c; +} From 008a64ee9b0cbefa7ff509b194b7344202148427 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 May 2023 11:15:29 +0900 Subject: [PATCH 3556/3664] [gatest] Add multivector constructors to Algebra This makes it much easier to create vectors of a specific grade or grouping. It even found some mistakes in the multivector product implementations. --- ruamoko/gatest/algebra.h | 6 ++++++ ruamoko/gatest/algebra.r | 21 +++++++++++++++++++++ ruamoko/gatest/main.r | 8 ++++---- ruamoko/gatest/multivector.r | 6 +++--- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/ruamoko/gatest/algebra.h b/ruamoko/gatest/algebra.h index ded06d265..687a497f6 100644 --- a/ruamoko/gatest/algebra.h +++ b/ruamoko/gatest/algebra.h @@ -6,6 +6,7 @@ @class Metric; @class BasisGroup; @class BasisLayout; +@class MultiVector; @interface Algebra : Object { @@ -23,6 +24,11 @@ -(Metric *) metric; -(int)count; -(int)dimension; + +-(MultiVector *) group:(int)group; +-(MultiVector *) group:(int)group values:(double *)values; +-(MultiVector *) ofGrade:(int)grade; +-(MultiVector *) ofGrade:(int)grade values:(double *)values; @end #endif//__algebra_h diff --git a/ruamoko/gatest/algebra.r b/ruamoko/gatest/algebra.r index 6be0b8dc0..b53e5b0f8 100644 --- a/ruamoko/gatest/algebra.r +++ b/ruamoko/gatest/algebra.r @@ -5,6 +5,7 @@ #include "basisblade.h" #include "basisgroup.h" #include "basislayout.h" +#include "multivector.h" #include "util.h" @implementation Algebra @@ -119,6 +120,26 @@ return dimension; } +-(MultiVector *) group:(int)group +{ + return [MultiVector new:self group:[layout group:group]]; +} + +-(MultiVector *) group:(int)group values:(double *)values +{ + return [MultiVector new:self group:[layout group:group] values:values]; +} + +-(MultiVector *) ofGrade:(int)grade +{ + return [MultiVector new:self group:grades[grade]]; +} + +-(MultiVector *) ofGrade:(int)grade values:(double *)values +{ + return [MultiVector new:self group:grades[grade] values:values]; +} + -(void) print { int count = [layout count]; diff --git a/ruamoko/gatest/main.r b/ruamoko/gatest/main.r index 81087ef4a..43be58742 100644 --- a/ruamoko/gatest/main.r +++ b/ruamoko/gatest/main.r @@ -83,10 +83,10 @@ main () Algebra *alg = [Algebra R:3, 0, 1]; double vals1[32] = {1, 0, 0, 8}; static double vals2[32] = {0, 1, 0, 8};//FIXME qfcc bug (static) - static double origin_vals[32] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; - MultiVector *plane1 = [MultiVector new:alg values:vals1]; - MultiVector *plane2 = [MultiVector new:alg values:vals2]; - MultiVector *origin = [MultiVector new:alg values:origin_vals]; + static double origin_vals[32] = {0, 0, 0, 1}; + MultiVector *plane1 = [alg group:0 values:vals1]; + MultiVector *plane2 = [alg group:0 values:vals2]; + MultiVector *origin = [alg group:3 values:origin_vals]; MultiVector *line = [plane1 wedge:plane2]; MultiVector *point = [[line dot:origin] product:line]; diff --git a/ruamoko/gatest/multivector.r b/ruamoko/gatest/multivector.r index a29dff8c2..6c4c5d4a0 100644 --- a/ruamoko/gatest/multivector.r +++ b/ruamoko/gatest/multivector.r @@ -109,7 +109,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) if (!s) { continue; } - int ind = [rhs.layout bladeIndex:[b mask]]; + int ind = [prod.layout bladeIndex:[b mask]]; prod.components[ind] += s * lc * rc; } } @@ -136,7 +136,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) if (!s) { continue; } - int ind = [rhs.layout bladeIndex:[b mask]]; + int ind = [prod.layout bladeIndex:[b mask]]; prod.components[ind] += s * lc * rc; } } @@ -172,7 +172,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) if (!s) { continue; } - int ind = [rhs.layout bladeIndex:[b mask]]; + int ind = [prod.layout bladeIndex:[b mask]]; prod.components[ind] += s * lc * rc; } } From 95dd63cd6862067e3eb49f283a1f40cf685ed880 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 May 2023 16:42:13 +0900 Subject: [PATCH 3557/3664] [qfcc] Avoid defining whole def via alias A partial write to a def should not define the whole def, thus def_visit_all's overlap parameter now has a flag that prevents a visit to the main def when accessing the def from an alias def. This prevents a lot of spurious kills and defines in flow analysis. --- tools/qfcc/source/def.c | 3 ++- tools/qfcc/source/flow.c | 31 +++++++++++++------------------ 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 55f470c8d..99f8c9962 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -732,8 +732,9 @@ def_visit_all (def_t *def, int overlap, return ret; if (def->alias) { def = def->alias; - if ((ret = visit (def, data))) + if (!(overlap & 4) && (ret = visit (def, data))) return ret; + overlap &= ~4; } else { overlap = 0; } diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 4f6968213..5246e33f4 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -760,7 +760,7 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) if (op->op_type == op_temp) { tempop_visit_all (&op->tempop, 1, flow_tempop_kill_aliases, tmp); } else if (op->op_type == op_def) { - def_visit_all (op->def, 1, flow_def_kill_aliases, tmp); + def_visit_all (op->def, 4 | 1, flow_def_kill_aliases, tmp); } // don't allow aliases to kill definitions in the entry dummy block if (uninit) { @@ -1153,10 +1153,9 @@ flow_def_add_aliases (def_t *def, void *_set) } static void -flow_add_op_var (set_t *set, operand_t *op, int is_use) +flow_add_op_var (set_t *set, operand_t *op, int ol) { flowvar_t *var; - int ol = is_use ? 1 : 2; if (!set) return; @@ -1164,10 +1163,6 @@ flow_add_op_var (set_t *set, operand_t *op, int is_use) return; set_add (set, var->number); - // FIXME XXX I think the curent implementation will have problems - // for the def set when assigning to an alias as right now the real - // var is being treated as assigned as well. Want to handle partial - // defs properly, but I am as yet uncertain of how. if (op->op_type == op_temp) { tempop_visit_all (&op->tempop, ol, flow_tempop_add_aliases, set); } else if (op->op_type == op_def) { @@ -1191,7 +1186,7 @@ flow_analyze_pointer_operand (operand_t *ptrop, set_t *def) op = ptrop->value->v.pointer.tempop; } if (op) { - flow_add_op_var (def, op, 0); + flow_add_op_var (def, op, 6); } } return op; @@ -1217,13 +1212,13 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, if (def) { set_empty (def); for (operand_t *op = s->def; op; op = op->next) { - flow_add_op_var (def, op, 0); + flow_add_op_var (def, op, 6); } } if (kill) { set_empty (kill); for (operand_t *op = s->kill; op; op = op->next) { - flow_add_op_var (kill, op, 0); + flow_add_op_var (kill, op, 6); } } if (operands) { @@ -1239,7 +1234,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opb, 1); } - flow_add_op_var (def, s->opc, 0); + flow_add_op_var (def, s->opc, 6); if (operands) { operands[0] = s->opc; operands[1] = s->opa; @@ -1247,7 +1242,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_expr: - flow_add_op_var (def, s->opc, 0); + flow_add_op_var (def, s->opc, 6); flow_add_op_var (use, s->opa, 1); if (s->opb) flow_add_op_var (use, s->opb, 1); @@ -1258,7 +1253,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } break; case st_assign: - flow_add_op_var (def, s->opa, 0); + flow_add_op_var (def, s->opa, 6); flow_add_op_var (use, s->opc, 1); if (operands) { operands[0] = s->opa; @@ -1275,17 +1270,17 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, aux_op1 = s->opb; if (!strcmp (s->opcode, "move") || !strcmp (s->opcode, "memset")) { - flow_add_op_var (def, s->opc, 0); + flow_add_op_var (def, s->opc, 6); src_op = s->opa; res_op = s->opc; } else if (!strcmp (s->opcode, "movep")) { - flow_add_op_var (use, s->opc, 0); + flow_add_op_var (use, s->opc, 6); aux_op3 = flow_analyze_pointer_operand (s->opa, use); res_op = flow_analyze_pointer_operand (s->opc, def); src_op = s->opa; aux_op2 = s->opc; } else if (!strcmp (s->opcode, "memsetp")) { - flow_add_op_var (use, s->opc, 0); + flow_add_op_var (use, s->opc, 6); res_op = flow_analyze_pointer_operand (s->opc, def); src_op = s->opa; aux_op2 = s->opc; @@ -1346,7 +1341,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, // call uses opc to specify the destination of the return value // parameter usage is taken care of by the statement's use // list - flow_add_op_var (def, s->opc, 0); + flow_add_op_var (def, s->opc, 6); // don't want old argument processing calln = -1; if (operands && s->opc->op_type != op_value) { @@ -1372,7 +1367,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, } if (def) { for (i = 0; i < num_flow_params; i++) { - flow_add_op_var (def, &flow_params[i].op, 0); + flow_add_op_var (def, &flow_params[i].op, 6); } } if (kill) { From 74e15fc582e1ae9745fd95c7bc285c301c9643de Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 May 2023 17:48:47 +0900 Subject: [PATCH 3558/3664] [qfcc] Show var use in flow vars --- tools/qfcc/source/dot_flow.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 34c32f77d..0aa42f455 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -204,19 +204,19 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) dasprintf (dstr, "%*sfv_%p [shape=none,label=<\n", indent, "", graph); dasprintf (dstr, "%*s\n", indent + 2, ""); - dasprintf (dstr, "%*s\n", + dasprintf (dstr, "%*s\n", indent + 4, ""); dasprintf (dstr, "%*s" - "\n", + "\n", indent + 4, ""); for (i = 0; i < graph->func->num_vars; i++) { var = graph->func->vars[i]; - dasprintf (dstr, "%*s" - "\n", + dasprintf (dstr, "%*s", indent + 4, "", var->number, html_string(operand_string (var->op)), var->flowaddr, set_as_string (var->define)); + dasprintf (dstr, "\n", set_as_string (var->use)); } dasprintf (dstr, "%*s
flow vars
flow vars
#nameaddrdefine
addrdefineuse
%d%s%d%s
%d%s%d%s%s
>];\n", indent + 2, ""); } From 0c116b8ff09068b80f7ed9f426788a033884dd36 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 May 2023 17:50:19 +0900 Subject: [PATCH 3559/3664] [qfcc] Record actual statements in a function This is to help with building ud-chains as I suspect I won't be all that interested in defs from the dummy blocks. --- tools/qfcc/include/function.h | 1 + tools/qfcc/include/statements.h | 2 +- tools/qfcc/source/flow.c | 5 ++++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 8e322de25..c65432026 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -118,6 +118,7 @@ typedef struct function_s { int num_vars; ///< total number of variables referenced struct set_s *global_vars;///< set indicating which vars are global struct set_s *param_vars; ///< set indicating which vars are params + struct set_s *real_statements;///< actual statements for ud-chaining struct statement_s **statements; int num_statements; int pseudo_addr;///< pseudo address space for flow analysis diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 896732dda..979580d35 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -108,12 +108,12 @@ typedef enum { typedef struct statement_s { struct statement_s *next; st_type_t type; + int number; ///< number of this statement in function const char *opcode; operand_t *opa; operand_t *opb; operand_t *opc; struct expr_s *expr; ///< source expression for this statement - int number; ///< number of this statement in function operand_t *use; ///< list of auxiliary operands used operand_t *def; ///< list of auxiliary operands defined operand_t *kill; ///< list of auxiliary operands killed diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 5246e33f4..4475fbf98 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -530,9 +530,12 @@ flow_build_statements (function_t *func) func->statements = malloc (num_statements * sizeof (statement_t *)); func->num_statements = num_statements; + func->real_statements = set_new (); for (sblock = func->sblock; sblock; sblock = sblock->next) { - for (s = sblock->statements; s; s = s->next) + for (s = sblock->statements; s; s = s->next) { func->statements[s->number] = s; + set_add (func->real_statements, s->number); + } } } From 4b3b6d516abb6e629afbba93b1c1998e19e7ccc5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 19 May 2023 19:41:34 +0900 Subject: [PATCH 3560/3664] [qfcc] Use available functions for dealloc use/def I had written those use/def sets before creating the functions, and it turns out I had goofed slightly with the def chaining. --- tools/qfcc/source/statements.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 018803d94..8922432f1 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -2537,8 +2537,7 @@ search_for_super_dealloc (sblock_t *sblock) for (statement_t *st = sblock->statements; st; st = st->next) { if (statement_is_return (st)) { op = pseudo_operand (super_dealloc, st->expr); - op->next = st->use; - st->use = op; + statement_add_use (st, op); continue; } if (!statement_is_call (st)) { @@ -2559,8 +2558,7 @@ search_for_super_dealloc (sblock_t *sblock) selector_t *sel = get_selector (st->expr->e.branch.args); if (sel && strcmp (sel->name, "dealloc") == 0) { op = pseudo_operand (super_dealloc, st->expr); - op->next = st->use; - st->def = op; + statement_add_def (st, op); super_dealloc_found++; } } From 9247ab91fdd41a4d5bacfbedb85d6046cb027c70 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 May 2023 00:59:23 +0900 Subject: [PATCH 3561/3664] [qfcc] Calculate ud-chains The first use will be pointer analysis for function arguments where the argument points to an array to mark the array as live, but I'm sure there'll be plenty of other uses. --- tools/qfcc/include/flow.h | 7 ++ tools/qfcc/include/function.h | 2 + tools/qfcc/include/statements.h | 2 + tools/qfcc/source/dot_flow.c | 24 ++++- tools/qfcc/source/flow.c | 153 +++++++++++++++++++++++--------- 5 files changed, 145 insertions(+), 43 deletions(-) diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index f68c5d5cf..6f630c8a9 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -44,11 +44,18 @@ typedef struct flowvar_s { struct flowvar_s *next; ///< for ALLOC struct set_s *use; ///< set of statements that use this var struct set_s *define; ///< set of statements that define this var + struct set_s *udchains; ///< set of ud chains for this var struct operand_s *op; ///< an operand using this var int number; ///< number of variable in func's ref list int flowaddr; ///< psuedo address for local and temp vars } flowvar_t; +typedef struct udchain_s { + int var; + int usest; + int defst; +} udchain_t; + typedef struct flowloop_s { struct flowloop_s *next; unsigned head; diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index c65432026..4777d3668 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -121,6 +121,8 @@ typedef struct function_s { struct set_s *real_statements;///< actual statements for ud-chaining struct statement_s **statements; int num_statements; + int num_ud_chains; + struct udchain_s *ud_chains; int pseudo_addr;///< pseudo address space for flow analysis struct pseudoop_s *pseudo_ops;///< pseudo operands used by this function } function_t; diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 979580d35..d79f4d9d1 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -117,6 +117,8 @@ typedef struct statement_s { operand_t *use; ///< list of auxiliary operands used operand_t *def; ///< list of auxiliary operands defined operand_t *kill; ///< list of auxiliary operands killed + int first_use; + int num_use; } statement_t; typedef struct sblock_s { diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 0aa42f455..8440dd0d8 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -204,10 +204,10 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) dasprintf (dstr, "%*sfv_%p [shape=none,label=<\n", indent, "", graph); dasprintf (dstr, "%*s\n", indent + 2, ""); - dasprintf (dstr, "%*s\n", + dasprintf (dstr, "%*s\n", indent + 4, ""); dasprintf (dstr, "%*s" - "\n", + "\n", indent + 4, ""); for (i = 0; i < graph->func->num_vars; i++) { var = graph->func->vars[i]; @@ -216,7 +216,25 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) var->number, html_string(operand_string (var->op)), var->flowaddr, set_as_string (var->define)); - dasprintf (dstr, "\n", set_as_string (var->use)); + dasprintf (dstr, "", set_as_string (var->use)); + dasprintf (dstr, "", set_as_string (var->udchains)); + dasprintf (dstr, "\n"); + } + dasprintf (dstr, "%*s
flow vars
flow vars
#nameaddrdefineuse
addrdefineuseud
%s
%s%s
>];\n", indent + 2, ""); + + dasprintf (dstr, "%*sud_%p [shape=none,label=<\n", indent, "", graph); + dasprintf (dstr, "%*s\n", indent + 2, ""); + dasprintf (dstr, "%*s\n", + indent + 4, ""); + dasprintf (dstr, "%*s" + "\n", + indent + 4, ""); + for (i = 0; i < graph->func->num_ud_chains; i++) { + udchain_t ud = graph->func->ud_chains[i]; + dasprintf (dstr, "%*s" + "", + indent + 4, "", i, ud.var, ud.usest, ud.defst); } dasprintf (dstr, "%*s
ud chains
#varusedef
%d%d%d%d
>];\n", indent + 2, ""); } diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 4475fbf98..58ce1be58 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -96,6 +96,7 @@ new_flowvar (void) ALLOC (256, flowvar_t, vars, var); var->use = set_new (); var->define = set_new (); + var->udchains = set_new (); return var; } @@ -106,6 +107,7 @@ delete_flowvar (flowvar_t *var) { set_delete (var->use); set_delete (var->define); + set_delete (var->udchains); FREE (vars, var); } @@ -774,6 +776,37 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) set_delete (tmp); } +typedef struct { + set_t *gen; + set_t *kill; + set_t *stgen; + set_t *stkill; + set_t *stdef; + set_t *uninit; + flowvar_t **vars; +} reachint_t; + +static void +flow_statement_reaching (statement_t *st, reachint_t *r) +{ + set_empty (r->stgen); + set_empty (r->stkill); + + set_iter_t *var_i; + for (var_i = set_first (r->stdef); var_i; var_i = set_next (var_i)) { + flowvar_t *var = r->vars[var_i->element]; + flow_kill_aliases (r->stkill, var, r->uninit); + set_remove (r->stkill, st->number); + set_add (r->stgen, st->number); + } + + set_difference (r->gen, r->stkill); + set_union (r->gen, r->stgen); + + set_difference (r->kill, r->stgen); + set_union (r->kill, r->stkill); +} + /** Compute reaching defs */ static void @@ -783,12 +816,13 @@ flow_reaching_defs (flowgraph_t *graph) int changed; flownode_t *node; statement_t *st; - set_t *stdef = set_new (); - set_t *stgen = set_new (); - set_t *stkill = set_new (); - set_t *oldout = set_new (); - set_t *gen, *kill, *in, *out, *uninit; - set_iter_t *var_i; + reachint_t reach = { + .stgen = set_new (), + .stkill = set_new (), + .stdef = set_new (), + .vars = graph->func->vars, + }; + set_t *in, *out, *uninit; set_iter_t *pred_i; flowvar_t *var; @@ -808,10 +842,6 @@ flow_reaching_defs (flowgraph_t *graph) * * All other entry node sets are initialized to empty. */ - // kill represents the set of all statements in the function - kill = set_new (); - for (i = 0; i < graph->func->num_statements; i++) - set_add (kill, i); // uninit uninit = set_new (); for (i = 0; i < graph->func->num_vars; i++) { @@ -822,7 +852,8 @@ flow_reaching_defs (flowgraph_t *graph) * \a uninit set (which becomes the \a out set of the entry node's * reaching defs) in order to prevent them leaking into the real nodes. */ - set_difference (uninit, kill); // remove any gens from the function + // remove any gens from the function + set_difference (uninit, graph->func->real_statements); // initialize the reaching defs sets in the entry node graph->nodes[graph->num_nodes]->reaching_defs.out = uninit; graph->nodes[graph->num_nodes]->reaching_defs.in = set_new (); @@ -832,32 +863,21 @@ flow_reaching_defs (flowgraph_t *graph) // Calculate gen and kill for each block, and initialize in and out for (i = 0; i < graph->num_nodes; i++) { node = graph->nodes[i]; - gen = set_new (); - kill = set_new (); + reach.gen = set_new (); + reach.kill = set_new (); for (st = node->sblock->statements; st; st = st->next) { - flow_analyze_statement (st, 0, stdef, 0, 0); - set_empty (stgen); - set_empty (stkill); - for (var_i = set_first (stdef); var_i; var_i = set_next (var_i)) { - var = graph->func->vars[var_i->element]; - flow_kill_aliases (stkill, var, uninit); - set_remove (stkill, st->number); - set_add (stgen, st->number); - } - - set_difference (gen, stkill); - set_union (gen, stgen); - - set_difference (kill, stgen); - set_union (kill, stkill); + flow_analyze_statement (st, 0, reach.stdef, 0, 0); + flow_statement_reaching (st, &reach); } - node->reaching_defs.gen = gen; - node->reaching_defs.kill = kill; + node->reaching_defs.gen = reach.gen; + node->reaching_defs.kill = reach.kill; node->reaching_defs.in = set_new (); node->reaching_defs.out = set_new (); + reach.gen = reach.kill = 0; } changed = 1; + set_t *oldout = set_new (); while (changed) { changed = 0; // flow down the graph @@ -865,8 +885,6 @@ flow_reaching_defs (flowgraph_t *graph) node = graph->nodes[graph->depth_first[i]]; in = node->reaching_defs.in; out = node->reaching_defs.out; - gen = node->reaching_defs.gen; - kill = node->reaching_defs.kill; for (pred_i = set_first (node->predecessors); pred_i; pred_i = set_next (pred_i)) { flownode_t *pred = graph->nodes[pred_i->element]; @@ -874,16 +892,71 @@ flow_reaching_defs (flowgraph_t *graph) } set_assign (oldout, out); set_assign (out, in); - set_difference (out, kill); - set_union (out, gen); + set_difference (out, node->reaching_defs.kill); + set_union (out, node->reaching_defs.gen); if (!set_is_equivalent (out, oldout)) changed = 1; } } set_delete (oldout); - set_delete (stdef); - set_delete (stgen); - set_delete (stkill); + + reach.gen = set_new (); + reach.kill = set_new (); + set_t *use = set_new (); + set_t *tmp = set_new (); + int num_ud = 0; + for (i = 0; i < graph->num_nodes; i++) { + node = graph->nodes[i]; + set_empty (reach.kill); + set_assign (reach.gen, node->reaching_defs.in); + for (st = node->sblock->statements; st; st = st->next) { + flow_analyze_statement (st, use, reach.stdef, 0, 0); + set_empty (tmp); + for (set_iter_t *vi = set_first (use); vi; vi = set_next (vi)) { + flowvar_t *var = reach.vars[vi->element]; + set_assign (tmp, var->define); + set_intersection (tmp, reach.gen); + num_ud += set_count (tmp); + } + flow_statement_reaching (st, &reach); + } + } + graph->func->ud_chains = malloc (num_ud * sizeof (udchain_t)); + graph->func->num_ud_chains = num_ud; + num_ud = 0; + for (i = 0; i < graph->num_nodes; i++) { + node = graph->nodes[i]; + set_empty (reach.kill); + set_assign (reach.gen, node->reaching_defs.in); + for (st = node->sblock->statements; st; st = st->next) { + flow_analyze_statement (st, use, reach.stdef, 0, 0); + set_empty (tmp); + st->first_use = num_ud; + for (set_iter_t *vi = set_first (use); vi; vi = set_next (vi)) { + flowvar_t *var = reach.vars[vi->element]; + set_assign (tmp, var->define); + set_intersection (tmp, reach.gen); + for (set_iter_t *ud = set_first (tmp); ud; ud = set_next (ud)) { + set_add (var->udchains, num_ud); + udchain_t *udc = &graph->func->ud_chains[num_ud++]; + udc->var = vi->element; + udc->usest = st->number; + udc->defst = ud->element; + } + } + st->num_use = num_ud - st->first_use; + flow_statement_reaching (st, &reach); + } + } + set_delete (use); + set_delete (tmp); + set_delete (reach.gen); + set_delete (reach.kill); + reach.gen = reach.kill = 0; + + set_delete (reach.stdef); + set_delete (reach.stgen); + set_delete (reach.stkill); } /** Update the node's \a use set from the statement's \a use set @@ -1335,9 +1408,9 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, if (s->opa) { flow_add_op_var (use, s->opa, 1); } - } - if (use) { - flow_add_op_var (use, &flow_params[0].op, 1); + if (use) { + flow_add_op_var (use, &flow_params[0].op, 1); + } } } if (strcmp (s->opcode, "call") == 0) { From b5a57cd15c31f09ffb09667c2abf1a1e4c6aad4a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 May 2023 13:52:24 +0900 Subject: [PATCH 3562/3664] [qfcc] Use assign_statement for v6p call arguments I had written assign_statement a while after the call handling code and didn't think to modify the call code. This makes for more consistent code. --- tools/qfcc/source/statements.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 8922432f1..68bfd6b4e 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -751,6 +751,15 @@ static sblock_t *addressing_mode (sblock_t *sblock, expr_t *ref, static statement_t *lea_statement (operand_t *pointer, operand_t *offset, expr_t *e); +static statement_t * +assign_statement (operand_t *dst, operand_t *src, expr_t *e) +{ + statement_t *s = new_statement (st_assign, "assign", e); + s->opa = dst; + s->opc = src; + return s; +} + static sblock_t * expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) { @@ -796,7 +805,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) } if (!src) { // This is the very right-hand node of a non-nil assignment chain - // (there may be more chains somwhere within src_expr, but they + // (there may be more chains somewhere within src_expr, but they // are not part of this chain as they are separated by another // expression). sblock = statement_subexpr (sblock, src_expr, &src); @@ -837,6 +846,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) // FIXME this probably needs to be more agressive // shouldn't emit code... sblock = statement_subexpr (sblock, dst_expr, &def); + //FIXME is this even necessary? if it is, should use copy_operand sblock = statement_subexpr (sblock, dst_expr, &kill); } dst_expr = expr_file_line (address_expr (dst_expr, 0), e); @@ -1045,9 +1055,7 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) arg = p; sblock = statement_subexpr (sblock, a, &arg); if (arg != p) { - s = new_statement (st_assign, "assign", a); - s->opa = p; - s->opc = arg; + s = assign_statement (p, arg, a); sblock_add_statement (sblock, s); } } @@ -1503,15 +1511,6 @@ load_statement (operand_t *ptr, operand_t *offs, operand_t *op, expr_t *e) return s; } -static statement_t * -assign_statement (operand_t *dst, operand_t *src, expr_t *e) -{ - statement_t *s = new_statement (st_assign, "assign", e); - s->opa = dst; - s->opc = src; - return s; -} - static sblock_t * expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) { From 208359edc6f69693d2a4cd36d64940ec9e422760 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 20 May 2023 13:54:40 +0900 Subject: [PATCH 3563/3664] [qfcc] Ensure all operands are cleared before flow I had missed the flowvar clearing for auxiliary use/def/kill operands. It's possible it wasn't necessary at the time since the operands were added just for dealloc checking, but there's every reason it could become necessary. --- tools/qfcc/source/flow.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 58ce1be58..a9a805f00 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -550,6 +550,23 @@ static int flow_def_clear_flowvars (def_t *def, void *data) return 0; } +static void +clear_operand (operand_t *op) +{ + if (op && op->op_type == op_def) { + def_visit_all (op->def, 0, flow_def_clear_flowvars, 0); + } +} + +static void +clear_operand_chain (operand_t *op) +{ + while (op) { + clear_operand (op); + op = op->next; + } +} + static void add_var_addrs (set_t *set, flowvar_t *var) { @@ -622,11 +639,11 @@ flow_build_vars (function_t *func) s = func->statements[i]; flow_analyze_statement (s, 0, 0, 0, operands); for (j = 0; j < FLOW_OPERANDS; j++) { - if (operands[j] && operands[j]->op_type == op_def) { - def_visit_all (operands[j]->def, 0, - flow_def_clear_flowvars, 0); - } + clear_operand (operands[j]); } + clear_operand_chain (s->use); + clear_operand_chain (s->def); + clear_operand_chain (s->kill); } // count .return and .param_[0-7] as they are always needed for (i = 0; i < num_flow_params; i++) { From a5943c8a3b688f635d71e4790547477d049ef77f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 May 2023 10:03:57 +0900 Subject: [PATCH 3564/3664] [qfcc] Use statement use chain for v6 calls Def and kill are still handled in flow_analyze_statement, but this makes call meta data more consistent between v6 and ruamoko progs, allowing the statement use chain to be used for call argument analysis. It even found a bug in the extraction of param counts from the call instruction. --- tools/qfcc/source/flow.c | 24 +++++++----------------- tools/qfcc/source/statements.c | 14 +++++++++++--- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index a9a805f00..908729b5e 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1289,7 +1289,7 @@ void flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, operand_t *operands[FLOW_OPERANDS]) { - int i, start, calln = -1; + int i, calln = -1; operand_t *src_op = 0; operand_t *res_op = 0; operand_t *aux_op1 = 0; @@ -1441,33 +1441,23 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, operands[0] = s->opc; } } else if (strncmp (s->opcode, "call", 4) == 0) { - start = 0; - calln = s->opcode[5] - '0'; + calln = s->opcode[4] - '0'; flow_add_op_var (use, s->opa, 1); } else if (strncmp (s->opcode, "rcall", 5) == 0) { - start = 2; - calln = s->opcode[6] - '0'; + calln = s->opcode[5] - '0'; flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opb, 1); if (s->opc) flow_add_op_var (use, s->opc, 1); } if (calln >= 0) { - if (use) { - for (i = start; i < calln; i++) { - flow_add_op_var (use, &flow_params[i + 1].op, 1); - } - } if (def) { - for (i = 0; i < num_flow_params; i++) { - flow_add_op_var (def, &flow_params[i].op, 6); - } + flow_add_op_var (def, &flow_params[0].op, 6); } if (kill) { - for (i = 0; i < num_flow_params; i++) { - flow_kill_aliases (kill, - flow_get_var (&flow_params[i].op), - 0); + for (i = 1; i < num_flow_params; i++) { + flowvar_t *var = flow_get_var (&flow_params[i].op); + flow_kill_aliases (kill, var, 0); } } } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 68bfd6b4e..a1faf867a 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1012,6 +1012,7 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) const char *opcode; const char *pref = ""; statement_t *s; + operand_t *use = 0; // function arguments are in reverse order for (a = args; a; a = a->next) { @@ -1037,6 +1038,10 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) sblock = vector_call (sblock, a, param, ind, &arguments[ind]); else sblock = statement_subexpr (sblock, a, &arguments[ind]); + operand_t *p; + sblock = statement_subexpr (sblock, param, &p); + p->next = use; + use = p; continue; } if (is_struct (get_type (param))) { @@ -1045,13 +1050,13 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) mov->file = a->file; sblock = statement_slist (sblock, mov); } else { + operand_t *p = 0; + sblock = statement_subexpr (sblock, param, &p); if (options.code.vector_calls && a->type == ex_value && a->e.value->lltype == ev_vector) { sblock = vector_call (sblock, a, param, ind, 0); } else { - operand_t *p = 0; - operand_t *arg; - sblock = statement_subexpr (sblock, param, &p); + operand_t *arg = p; arg = p; sblock = statement_subexpr (sblock, a, &arg); if (arg != p) { @@ -1059,6 +1064,8 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) sblock_add_statement (sblock, s); } } + p->next = use; + use = p; } } opcode = va (0, "%scall%d", pref, count); @@ -1066,6 +1073,7 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) sblock = statement_subexpr (sblock, func, &s->opa); s->opb = arguments[0]; s->opc = arguments[1]; + s->use = use; if (op) { *op = return_operand (call->e.branch.ret_type, call); } From 7b6b25a751e308e85766a477b5f4dff011ef69af Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 May 2023 13:31:33 +0900 Subject: [PATCH 3565/3664] [qfcc] Find variables referenced by function arguments This takes advantage of the ud-chains to follow the trail of pointer assignments looking for an address. This gets array element assignments surviving across blocks when the array itself is passed to a function. It doesn't help when the address of the element is taken though. I think that's a dags problem and probably needs du-chains. Also, the ud-chain creation should probably be done in two passes so the newly found information can be recorded. --- tools/qfcc/source/flow.c | 180 ++++++++++++++++++++++++++++++--------- 1 file changed, 138 insertions(+), 42 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 908729b5e..ce0e3fe0f 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -87,7 +87,7 @@ ALLOC_STATE (flowgraph_t, graphs); ///< flow graph pool /** Allocate a new flow var. * - * The var's use and define sets are initialized to empty. + * The var's use, define and udchain sets are initialized to empty. */ static flowvar_t * new_flowvar (void) @@ -793,6 +793,139 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit) set_delete (tmp); } +static int +flow_tempop_add_aliases (tempop_t *tempop, void *_set) +{ + set_t *set = (set_t *) _set; + flowvar_t *var; + var = tempop->flowvar; + if (var) + set_add (set, var->number); + return 0; +} + +static int +flow_def_add_aliases (def_t *def, void *_set) +{ + set_t *set = (set_t *) _set; + flowvar_t *var; + var = def->flowvar; + if (var) + set_add (set, var->number); + return 0; +} + +static void +flow_add_op_var (set_t *set, operand_t *op, int ol) +{ + flowvar_t *var; + + if (!set) + return; + if (!(var = flow_get_var (op))) + return; + set_add (set, var->number); + + if (op->op_type == op_temp) { + tempop_visit_all (&op->tempop, ol, flow_tempop_add_aliases, set); + } else if (op->op_type == op_def) { + def_visit_all (op->def, ol, flow_def_add_aliases, set); + } +} + +static int +flowvar_def_add_use (def_t *def, void *data) +{ + statement_t *st = data; + flowvar_t *var = def->flowvar; + if (var) { + set_add (var->use, st->number); + } + return 0; +} + +static void +flowvar_add_use (flowvar_t *var, statement_t *st) +{ + set_add (var->use, st->number); + + if (var->op->op_type != op_def) { + return; + } + def_t *def = var->op->def->alias; + if (def && is_array (def->type)) { + def_visit_all (def, 0, flowvar_def_add_use, st); + } +} + +static void +follow_ud_chain (udchain_t ud, function_t *func, set_t *ptr, set_t *visited) +{ + statement_t *st = func->statements[ud.defst]; + if (set_is_member (visited, st->number)) { + return; + } + set_add (visited, st->number); + if (st->type == st_address) { + flowvar_t *var = flow_get_var (st->opa); + set_add (ptr, var->number); + return; + } + for (int j = 0; j < st->num_use; j++) { + udchain_t c = func->ud_chains[j + st->first_use]; + if (c.defst < func->num_statements) { + operand_t *op = func->vars[c.var]->op; + if (is_ptr (op->type)) { + follow_ud_chain (c, func, ptr, visited); + } else { + } + } + } +} + +static void +flow_check_params (statement_t *st, set_t *use, set_t *def, function_t *func) +{ + set_t *use_ptr = set_new (); + set_t *def_ptr = set_new (); + set_t *ptr = set_new (); + set_t *visited = set_new (); + + int have_use = 0; + for (operand_t *op = st->use; op; op = op->next) { + if (op->op_type == op_def && is_ptr (op->type)) { + flowvar_t *var = flow_get_var (op); + set_add (use_ptr, var->number); + have_use = 1; + const char *name = op->def->name; + if (!strncmp (name,".arg", 4) || !strncmp (name, ".param_", 7)) { + set_add (def_ptr, var->number); + } + } + } + if (have_use) { + for (int i = 0; i < st->num_use; i++) { + udchain_t ud = func->ud_chains[i + st->first_use]; + set_empty (visited); + set_add (visited, st->number); + if (set_is_member (use_ptr, ud.var)) { + set_empty (ptr); + follow_ud_chain (ud, func, ptr, visited); + for (set_iter_t *p = set_first (ptr); p; p = set_next (p)) { + flowvar_t *var = func->vars[p->element]; + flow_add_op_var (use, var->op, 0); + flowvar_add_use (var, st); + } + } + } + } + + set_delete (visited); + set_delete (use_ptr); + set_delete (def_ptr); + set_delete (ptr); +} + typedef struct { set_t *gen; set_t *kill; @@ -955,7 +1088,7 @@ flow_reaching_defs (flowgraph_t *graph) set_intersection (tmp, reach.gen); for (set_iter_t *ud = set_first (tmp); ud; ud = set_next (ud)) { set_add (var->udchains, num_ud); - udchain_t *udc = &graph->func->ud_chains[num_ud++]; + udchain_t *udc = &graph->func->ud_chains[num_ud++]; udc->var = vi->element; udc->usest = st->number; udc->defst = ud->element; @@ -1018,6 +1151,9 @@ flow_live_vars (flowgraph_t *graph) def = set_new (); for (st = node->sblock->statements; st; st = st->next) { flow_analyze_statement (st, stuse, stdef, 0, 0); + if (st->type == st_func && statement_is_call (st)) { + flow_check_params (st, stuse, stdef, graph->func); + } live_set_use (stuse, use, def); live_set_def (stdef, use, def); } @@ -1223,46 +1359,6 @@ flow_generate (flowgraph_t *graph) return code; } -static int -flow_tempop_add_aliases (tempop_t *tempop, void *_set) -{ - set_t *set = (set_t *) _set; - flowvar_t *var; - var = tempop->flowvar; - if (var) - set_add (set, var->number); - return 0; -} - -static int -flow_def_add_aliases (def_t *def, void *_set) -{ - set_t *set = (set_t *) _set; - flowvar_t *var; - var = def->flowvar; - if (var) - set_add (set, var->number); - return 0; -} - -static void -flow_add_op_var (set_t *set, operand_t *op, int ol) -{ - flowvar_t *var; - - if (!set) - return; - if (!(var = flow_get_var (op))) - return; - set_add (set, var->number); - - if (op->op_type == op_temp) { - tempop_visit_all (&op->tempop, ol, flow_tempop_add_aliases, set); - } else if (op->op_type == op_def) { - def_visit_all (op->def, ol, flow_def_add_aliases, set); - } -} - static operand_t * flow_analyze_pointer_operand (operand_t *ptrop, set_t *def) { From d01fc27dd524b0e23a036478825880822cd92205 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 21 May 2023 22:20:38 +0900 Subject: [PATCH 3566/3664] [gatest] Remove the workarounds for array lifetime Now that arrays work well enough for this case, no point in having the workarounds (other than they're actually faster, but I'd like to optimize *that* sometime). --- ruamoko/gatest/main.r | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ruamoko/gatest/main.r b/ruamoko/gatest/main.r index 43be58742..11ddeb2e7 100644 --- a/ruamoko/gatest/main.r +++ b/ruamoko/gatest/main.r @@ -81,11 +81,11 @@ main () names[0], names[3], names[0], names[3], prod); Algebra *alg = [Algebra R:3, 0, 1]; - double vals1[32] = {1, 0, 0, 8}; - static double vals2[32] = {0, 1, 0, 8};//FIXME qfcc bug (static) - static double origin_vals[32] = {0, 0, 0, 1}; - MultiVector *plane1 = [alg group:0 values:vals1]; - MultiVector *plane2 = [alg group:0 values:vals2]; + double plane1_vals[4] = {1, 0, 0, 8}; + double plane2_vals[4] = {0, 1, 0, 8}; + double origin_vals[4] = {0, 0, 0, 1}; + MultiVector *plane1 = [alg group:0 values:plane1_vals]; + MultiVector *plane2 = [alg group:0 values:plane2_vals]; MultiVector *origin = [alg group:3 values:origin_vals]; MultiVector *line = [plane1 wedge:plane2]; From 7c9b6aa0ccf9686adb2d454a1315e6a7f4af4f27 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 22 May 2023 13:03:35 +0900 Subject: [PATCH 3567/3664] [gatest] Use the metric when computing the dot product As the dot product is a metric product, using the metric is vital to getting the correct results. This fixes the calculation of the closest point on a line to a point other than the origin (and a whole pile of other issues, I imagine). --- ruamoko/gatest/multivector.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/gatest/multivector.r b/ruamoko/gatest/multivector.r index 6c4c5d4a0..a6a0f0b4a 100644 --- a/ruamoko/gatest/multivector.r +++ b/ruamoko/gatest/multivector.r @@ -160,7 +160,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) double rc = rhs.components[j]; BasisBlade *rb = [rhs.layout bladeAt:j]; int rg = [rb grade]; - BasisBlade *b = [lb geometricProduct:rb]; + BasisBlade *b = [lb geometricProduct:rb metric:[algebra metric]]; int g = [b grade]; if ((lg <= rg) && (g != rg - lg)) { continue; From 42b0608e653b85be907fd44ac004742fa7b8f490 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 May 2023 12:44:16 +0900 Subject: [PATCH 3568/3664] [qwaq] Get the console working for qwaq-x11 And other graphics versions too, of course. A lot of it feels rather like a hack, but I think the entire canvas/console setup and console related event handling may need a rethink (it's not horribly wrong, but it doesn't feel right), particularly the initial sizing and binding for toggling the console. --- ruamoko/qwaq/builtins/graphics.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/ruamoko/qwaq/builtins/graphics.c b/ruamoko/qwaq/builtins/graphics.c index b1aaacd65..3a9fb24cd 100644 --- a/ruamoko/qwaq/builtins/graphics.c +++ b/ruamoko/qwaq/builtins/graphics.c @@ -44,6 +44,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/draw.h" #include "QF/image.h" #include "QF/input.h" +#include "QF/keys.h" #include "QF/progs.h" #include "QF/quakefs.h" #include "QF/render.h" @@ -86,17 +87,20 @@ static progs_t *bi_rprogs; static pr_func_t qc2d; static int event_handler_id; static canvas_system_t canvas_sys; +static view_t screen_view; +static uint32_t canvas; static void bi_2d (void) { if (qc2d) PR_ExecuteProgram (bi_rprogs, qc2d); + Con_DrawConsole (); + Canvas_Draw (canvas_sys); } static SCR_Func bi_2dfuncs[] = { bi_2d, -// Con_DrawConsole, 0, }; @@ -155,6 +159,11 @@ static builtin_t builtins[] = { static int event_handler (const IE_event_t *ie_event, void *_pr) { + // FIXME rethink event handling for qwaq + if (ie_event->type == ie_key && ie_event->key.code == QFK_ESCAPE) { + Con_SetState (con_active); + return 1; + } return IN_Binding_HandleEvent (ie_event); } @@ -326,6 +335,12 @@ generate_colormap (void) free (cmap); } +static void +vidsize_listener (void *data, const viddef_t *vdef) +{ + Canvas_SetLen (canvas_sys, (view_pos_t) { vdef->width, vdef->height }); +} + void BI_Graphics_Init (progs_t *pr) { @@ -374,8 +389,19 @@ BI_Graphics_Init (progs_t *pr) cd->canvas_sys = &canvas_sys; } ECS_CreateComponentPools (reg); + + canvas = Canvas_New (canvas_sys); + screen_view = Canvas_GetRootView (canvas_sys, canvas); + View_SetPos (screen_view, 0, 0); + View_SetLen (screen_view, viddef.width, viddef.height); + View_SetGravity (screen_view, grav_northwest); + View_SetVisible (screen_view, 1); + + VID_OnVidResize_AddListener (vidsize_listener, 0); + //Key_SetKeyDest (key_game); Con_Init (); + vidsize_listener (0, &viddef); //FIXME this probably shouldn't be needed S_Init (0, &con_frametime); //CDAudio_Init (); From b9cff7aae0ad1999c067f04f8ffc6ae3efc6711b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 May 2023 18:25:47 +0900 Subject: [PATCH 3569/3664] [gatest] Implement and use multi-vector reverse This gives the resultant point the correct sign. Though the projective divide would take care of the sign, this makes reading the point a little less confusing (still need to sort out automatic blade reversals for the likes of e31). --- ruamoko/gatest/main.r | 2 +- ruamoko/gatest/multivector.h | 1 + ruamoko/gatest/multivector.r | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ruamoko/gatest/main.r b/ruamoko/gatest/main.r index 11ddeb2e7..2c195cb47 100644 --- a/ruamoko/gatest/main.r +++ b/ruamoko/gatest/main.r @@ -89,7 +89,7 @@ main () MultiVector *origin = [alg group:3 values:origin_vals]; MultiVector *line = [plane1 wedge:plane2]; - MultiVector *point = [[line dot:origin] product:line]; + MultiVector *point = [[line dot:origin] product:[line reverse]]; printf ("plane1:%@\nplane2:%@\nline:%@\norigin:%@\n", plane1, plane2, line, origin); printf ("point:%@\n", point); diff --git a/ruamoko/gatest/multivector.h b/ruamoko/gatest/multivector.h index c17cebef6..7b06b0695 100644 --- a/ruamoko/gatest/multivector.h +++ b/ruamoko/gatest/multivector.h @@ -23,6 +23,7 @@ -(MultiVector *) wedge:(MultiVector *) rhs; -(MultiVector *) dot:(MultiVector *) rhs; -(MultiVector *) dual; +-(MultiVector *) reverse; @end #endif//__multivector_h diff --git a/ruamoko/gatest/multivector.r b/ruamoko/gatest/multivector.r index a6a0f0b4a..19588085d 100644 --- a/ruamoko/gatest/multivector.r +++ b/ruamoko/gatest/multivector.r @@ -198,4 +198,22 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) } return dual; } + +-(MultiVector *) reverse +{ + MultiVector *reverse = new_mv (algebra, nil); + for (int i = 0; i < num_components; i++) { + if (!components[i]) { + continue; + } + double c = components[i]; + BasisBlade *b = [layout bladeAt:i]; + int g = [b grade]; + unsigned mask = [b mask]; + double s = g & 2 ? -1 : 1;//FIXME do in BasisBlade? + int ind = [layout bladeIndex:mask]; + reverse.components[ind] += s * c; + } + return reverse; +} @end From db9a6a9a5c6f0854753f4dcfb4b01de464ef7ffb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 May 2023 20:58:33 +0900 Subject: [PATCH 3570/3664] [ruamoko] Make cbuf functions take a cbuf param A nil param refers to the default cbuf if it has been set by the engine, otherwise it is invalid. This is the first step to fleshing out the cbuf API. --- libs/ruamoko/rua_cbuf.c | 50 ++++++++++++++++++----------------- ruamoko/cl_menu/client_menu.r | 24 ++++++++--------- ruamoko/cl_menu/options.r | 2 +- ruamoko/include/cbuf.h | 10 ++++--- ruamoko/lib/cbuf.r | 8 +++--- 5 files changed, 49 insertions(+), 45 deletions(-) diff --git a/libs/ruamoko/rua_cbuf.c b/libs/ruamoko/rua_cbuf.c index 5380810b2..91ad02405 100644 --- a/libs/ruamoko/rua_cbuf.c +++ b/libs/ruamoko/rua_cbuf.c @@ -38,7 +38,8 @@ #include "rua_internal.h" typedef struct { - cbuf_t *cbuf; + progs_t *pr; + cbuf_t *default_cbuf; } cbuf_resources_t; static cbuf_t * __attribute__((pure)) @@ -47,44 +48,43 @@ _get_cbuf (progs_t *pr, cbuf_resources_t *res, int arg, const char *func) cbuf_t *cbuf = 0; if (arg == 0) { - cbuf = res->cbuf; + // a nil cbuf is valid only if the default cbuf has been set + cbuf = res->default_cbuf; } else { - PR_RunError (pr, "%s: Invalid cbuf_t", func); } - if (!cbuf) - PR_RunError (pr, "Invalid cbuf_t"); + if (!cbuf) { + PR_RunError (pr, "%s: Invalid cbuf_t: %d", func, arg); + } return cbuf; } #define get_cbuf(pr, res, arg) _get_cbuf(pr, res, arg, __FUNCTION__) -static void -bi_Cbuf_AddText (progs_t *pr, void *data) +#define bi(n) static void bi_##n (progs_t *pr, void *data) + +bi(Cbuf_AddText) { - const char *text = P_GSTRING (pr, 0); - cbuf_t *cbuf = get_cbuf (pr, data, 0); + cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0)); + const char *text = P_GSTRING (pr, 1); Cbuf_AddText (cbuf, text); } -static void -bi_Cbuf_InsertText (progs_t *pr, void *data) +bi(Cbuf_InsertText) { - const char *text = P_GSTRING (pr, 0); - cbuf_t *cbuf = get_cbuf (pr, data, 0); + cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0)); + const char *text = P_GSTRING (pr, 1); Cbuf_InsertText (cbuf, text); } -static void -bi_Cbuf_Execute (progs_t *pr, void *data) +bi(Cbuf_Execute) { - cbuf_t *cbuf = get_cbuf (pr, data, 0); + cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0)); Cbuf_Execute (cbuf); } -static void -bi_Cbuf_Execute_Sets (progs_t *pr, void *data) +bi(Cbuf_Execute_Sets) { - cbuf_t *cbuf = get_cbuf (pr, data, 0); + cbuf_t *cbuf = get_cbuf (pr, data, P_INT (pr, 0)); Cbuf_Execute_Sets (cbuf); } @@ -99,14 +99,15 @@ bi_cbuf_destroy (progs_t *pr, void *data) free (data); } +#undef bi #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } static builtin_t builtins[] = { - bi(Cbuf_AddText, 1, p(string)), - bi(Cbuf_InsertText, 1, p(string)), - bi(Cbuf_Execute, 0), - bi(Cbuf_Execute_Sets, 0), + bi(Cbuf_AddText, 2, p(ptr), p(string)), + bi(Cbuf_InsertText, 2, p(ptr), p(string)), + bi(Cbuf_Execute, 1, p(ptr)), + bi(Cbuf_Execute_Sets, 1, p(ptr)), {0} }; @@ -114,6 +115,7 @@ void RUA_Cbuf_Init (progs_t *pr, int secure) { cbuf_resources_t *res = calloc (sizeof (cbuf_resources_t), 1); + res->pr = pr; PR_Resources_Register (pr, "Cbuf", res, bi_cbuf_clear, bi_cbuf_destroy); PR_RegisterBuiltins (pr, builtins, res); } @@ -122,5 +124,5 @@ VISIBLE void RUA_Cbuf_SetCbuf (progs_t *pr, cbuf_t *cbuf) { cbuf_resources_t *res = PR_Resources_Find (pr, "Cbuf"); - res->cbuf = cbuf; + res->default_cbuf = cbuf; } diff --git a/ruamoko/cl_menu/client_menu.r b/ruamoko/cl_menu/client_menu.r index 9a162e2a7..d0bef7345 100644 --- a/ruamoko/cl_menu/client_menu.r +++ b/ruamoko/cl_menu/client_menu.r @@ -247,7 +247,7 @@ int (int key, int unicode, int down) load_quickbup_keyevent = if (loadable[load_cursor]) { S_LocalSound ("misc/menu2.wav"); Menu_SelectMenu (nil); - Cbuf_AddText (sprintf ("load quick%i.sav\n", load_cursor)); + Cbuf_AddText (nil, sprintf ("load quick%i.sav\n", load_cursor)); load_cursor = MAX_SAVEGAMES; } return 1; @@ -279,7 +279,7 @@ int (int key, int unicode, int down) load_keyevent = } else if (loadable[load_cursor]) { S_LocalSound ("misc/menu2.wav"); Menu_SelectMenu (nil); - Cbuf_AddText (sprintf ("load s%i.sav\n", load_cursor)); + Cbuf_AddText (nil, sprintf ("load s%i.sav\n", load_cursor)); } return 1; } @@ -304,7 +304,7 @@ int (int key, int unicode, int down) save_keyevent = case QFK_RETURN: //case QFM_BUTTON1: Menu_SelectMenu (nil); - Cbuf_AddText (sprintf ("save s%i.sav\n", save_cursor)); + Cbuf_AddText (nil, sprintf ("save s%i.sav\n", save_cursor)); return 1; } return 0; @@ -398,15 +398,15 @@ void () quit_menu = int (string text, int key) sp_start = { Menu_SelectMenu (nil); - Cbuf_AddText ("disconnect\n"); - Cbuf_AddText ("maxplayers 1\n"); - Cbuf_AddText ("coop 0\n"); - Cbuf_AddText ("deathmatch 0\n"); - Cbuf_AddText ("teamplay 0\n"); - Cbuf_AddText ("listen 0\n"); - Cbuf_AddText ("noexit 0\n"); - Cbuf_AddText ("samelevel 0\n"); - Cbuf_AddText ("map start\n"); + Cbuf_AddText (nil, "disconnect\n"); + Cbuf_AddText (nil, "maxplayers 1\n"); + Cbuf_AddText (nil, "coop 0\n"); + Cbuf_AddText (nil, "deathmatch 0\n"); + Cbuf_AddText (nil, "teamplay 0\n"); + Cbuf_AddText (nil, "listen 0\n"); + Cbuf_AddText (nil, "noexit 0\n"); + Cbuf_AddText (nil, "samelevel 0\n"); + Cbuf_AddText (nil, "map start\n"); return 0; }; diff --git a/ruamoko/cl_menu/options.r b/ruamoko/cl_menu/options.r index a228b1062..c587c9ccd 100644 --- a/ruamoko/cl_menu/options.r +++ b/ruamoko/cl_menu/options.r @@ -436,7 +436,7 @@ int (string text, int key) op_goto_console = { Menu_SelectMenu (""); - Cbuf_AddText ("toggleconsole\n"); + Cbuf_AddText (nil, "toggleconsole\n"); return 0; }; diff --git a/ruamoko/include/cbuf.h b/ruamoko/include/cbuf.h index 1a2ef142f..92336e4cc 100644 --- a/ruamoko/include/cbuf.h +++ b/ruamoko/include/cbuf.h @@ -1,9 +1,11 @@ #ifndef __ruamoko_cbuf_h #define __ruamoko_cbuf_h -@extern void Cbuf_AddText (string text); -@extern void Cbuf_InsertText (string text); -@extern void Cbuf_Execute (void); -@extern void Cbuf_Execute_Sets (void); +typedef struct { int x; } cbuf_t; + +@extern void Cbuf_AddText (cbuf_t *cbuf, string text); +@extern void Cbuf_InsertText (cbuf_t *cbuf, string text); +@extern void Cbuf_Execute (cbuf_t *cbuf); +@extern void Cbuf_Execute_Sets (cbuf_t *cbuf); #endif//__ruamoko_cbuf_h diff --git a/ruamoko/lib/cbuf.r b/ruamoko/lib/cbuf.r index f22498f3c..a6fcb8599 100644 --- a/ruamoko/lib/cbuf.r +++ b/ruamoko/lib/cbuf.r @@ -1,6 +1,6 @@ #include -void (string text) Cbuf_AddText = #0; -void (string text) Cbuf_InsertText = #0; -void () Cbuf_Execute = #0; -void () Cbuf_Execute_Sets = #0; +void Cbuf_AddText (cbuf_t *cbuf, string text) = #0; +void Cbuf_InsertText (cbuf_t *cbuf, string text) = #0; +void Cbuf_Execute (cbuf_t *cbuf) = #0; +void Cbuf_Execute_Sets (cbuf_t *cbuf) = #0; From d07bd20552c603230bb6d6b422389201c5326053 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 24 May 2023 21:04:24 +0900 Subject: [PATCH 3571/3664] [gib] Correct the header in gib.h --- include/QF/gib.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/include/QF/gib.h b/include/QF/gib.h index ef1515388..9b08bd760 100644 --- a/include/QF/gib.h +++ b/include/QF/gib.h @@ -1,12 +1,9 @@ /* - #FILENAME# + gib.h - #DESCRIPTION# + GIB scripting language - Copyright (C) 2003 #AUTHOR# - - Author: #AUTHOR# - Date: #DATE# + Copyright (C) 2003 Brian Koropoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License From 6d5e8922a5f00f920be850ff8ad4f04092ca29ea Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 May 2023 10:41:28 +0900 Subject: [PATCH 3572/3664] [qfcc] Add a handle type for engine resources I never liked the various hacks I had come up with for representing resource handles in Ruamoko. Structs with an int were awkward to test, pointers and ints could be modified, etc etc. The new @handle keyword (@ used to keep handle free for use) works just like struct, union and enum in syntax, but creates an opaque type suitable for a 32-bit handle. The backing type is a function so v6 progs can use it without (all the necessary opcodes exist) and no modifications were needed for type-checking in binary expressions, but only assignment and comparisons are supported, and (of course) nil. Tested using cbuf_t and QFile: seems to work as desired. I had considered 64-bit handles, but really, if more than 4G resource objects are needed, I'm not sure QF can handle the game. However, that limit is per resource manager, not total. --- include/QF/progs/pr_type.h | 7 +++++++ libs/gamecode/pr_debug.c | 2 ++ libs/video/renderer/vulkan/vkgen/vkgen.r | 3 +++ libs/video/renderer/vulkan/vkgen/vktype.r | 2 ++ ruamoko/include/cbuf.h | 10 +++++----- ruamoko/include/qfile.h | 2 +- ruamoko/include/types.h | 7 +++++++ ruamoko/lib/cbuf.r | 8 ++++---- ruamoko/qwaq/debugger/typeencodings.r | 9 +++++++++ tools/qfcc/include/struct.h | 2 ++ tools/qfcc/source/dump_globals.c | 4 ++++ tools/qfcc/source/obj_file.c | 3 +++ tools/qfcc/source/obj_type.c | 14 ++++++++++++++ tools/qfcc/source/qc-lex.l | 1 + tools/qfcc/source/qc-parse.y | 15 ++++++++++++++- tools/qfcc/source/struct.c | 12 ++++++++++++ tools/qfcc/source/type.c | 15 +++++++++++++++ 17 files changed, 105 insertions(+), 11 deletions(-) diff --git a/include/QF/progs/pr_type.h b/include/QF/progs/pr_type.h index 7f117e7a3..a3c1528b1 100644 --- a/include/QF/progs/pr_type.h +++ b/include/QF/progs/pr_type.h @@ -48,6 +48,7 @@ typedef enum { ty_array, ty_class, ty_alias, + ty_handle, } ty_meta_e; typedef struct qfot_alias_s { @@ -57,6 +58,11 @@ typedef struct qfot_alias_s { pr_string_t name; ///< alias name, may be null } qfot_alias_t; +typedef struct qfot_handle_s { + etype_t type; + pr_string_t tag; +} qfot_handle_t; + typedef struct qfot_fldptr_s { etype_t type; ///< ev_field or ev_ptr pr_ptr_t aux_type; ///< referenced type @@ -119,6 +125,7 @@ typedef struct qfot_type_s { qfot_array_t array; ///< ty_array pr_string_t class; ///< ty_class qfot_alias_t alias; ///< ty_alias + qfot_handle_t handle; ///< ty_handle }; } qfot_type_t; diff --git a/libs/gamecode/pr_debug.c b/libs/gamecode/pr_debug.c index 7b774e9b1..74d1cfd0b 100644 --- a/libs/gamecode/pr_debug.c +++ b/libs/gamecode/pr_debug.c @@ -237,6 +237,7 @@ pr_debug_type_size (const progs_t *pr, const qfot_type_t *type) qfot_type_t *aux_type; switch (type->meta) { case ty_basic: + case ty_handle: return pr_type_size[type->type]; case ty_struct: case ty_union: @@ -1052,6 +1053,7 @@ static void value_string (pr_debug_data_t *data, qfot_type_t *type, pr_type_t *value) { switch (type->meta) { + case ty_handle: case ty_basic: switch (type->type) { #define EV_TYPE(t) \ diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index 1367524d7..dd68df56e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -95,6 +95,9 @@ void print_type (qfot_type_t *type) //printf (" %d %s ", type.alias.type, type.alias.name); print_type (type.alias.aux_type); break; + case ty_handle: + //printf (" %s\n", type.handle.tag); + break; } } diff --git a/libs/video/renderer/vulkan/vkgen/vktype.r b/libs/video/renderer/vulkan/vkgen/vktype.r index 935279a76..8c3d7f3f7 100644 --- a/libs/video/renderer/vulkan/vkgen/vktype.r +++ b/libs/video/renderer/vulkan/vkgen/vktype.r @@ -60,6 +60,8 @@ static string get_type_key (void *type, void *unused) return [[String alloc] initWithType: type]; } } + // fallthrough + case ty_handle: case ty_class: return [[Type alloc] initWithType: type]; case ty_array: diff --git a/ruamoko/include/cbuf.h b/ruamoko/include/cbuf.h index 92336e4cc..fa46a5efe 100644 --- a/ruamoko/include/cbuf.h +++ b/ruamoko/include/cbuf.h @@ -1,11 +1,11 @@ #ifndef __ruamoko_cbuf_h #define __ruamoko_cbuf_h -typedef struct { int x; } cbuf_t; +typedef @handle cbuf_h cbuf_t; -@extern void Cbuf_AddText (cbuf_t *cbuf, string text); -@extern void Cbuf_InsertText (cbuf_t *cbuf, string text); -@extern void Cbuf_Execute (cbuf_t *cbuf); -@extern void Cbuf_Execute_Sets (cbuf_t *cbuf); +@extern void Cbuf_AddText (cbuf_t cbuf, string text); +@extern void Cbuf_InsertText (cbuf_t cbuf, string text); +@extern void Cbuf_Execute (cbuf_t cbuf); +@extern void Cbuf_Execute_Sets (cbuf_t cbuf); #endif//__ruamoko_cbuf_h diff --git a/ruamoko/include/qfile.h b/ruamoko/include/qfile.h index 93fdbd9b3..8d3a9eddc 100644 --- a/ruamoko/include/qfile.h +++ b/ruamoko/include/qfile.h @@ -1,7 +1,7 @@ #ifndef __ruamoko_qfile_h #define __ruamoko_qfile_h -typedef struct _qfile_t *QFile; +typedef @handle _qfile_t QFile; @extern int Qrename (string old, string new); @extern int Qremove (string path); diff --git a/ruamoko/include/types.h b/ruamoko/include/types.h index 6316ecb12..d1405d2a9 100644 --- a/ruamoko/include/types.h +++ b/ruamoko/include/types.h @@ -16,6 +16,7 @@ typedef enum { ty_array, ty_class, ty_alias, + ty_handle, } ty_meta_e; typedef struct qfot_alias_s { @@ -25,6 +26,11 @@ typedef struct qfot_alias_s { string name; } qfot_alias_t; +typedef struct qfot_handle_s { + etype_t type; + string tag; +} qfot_handle_t; + typedef struct qfot_fldptr_s { etype_t type; struct qfot_type_s *aux_type; @@ -73,6 +79,7 @@ typedef struct qfot_type_s { qfot_array_t array; string class; qfot_alias_t alias; + qfot_handle_t handle; }; } qfot_type_t; diff --git a/ruamoko/lib/cbuf.r b/ruamoko/lib/cbuf.r index a6fcb8599..df00ccc81 100644 --- a/ruamoko/lib/cbuf.r +++ b/ruamoko/lib/cbuf.r @@ -1,6 +1,6 @@ #include -void Cbuf_AddText (cbuf_t *cbuf, string text) = #0; -void Cbuf_InsertText (cbuf_t *cbuf, string text) = #0; -void Cbuf_Execute (cbuf_t *cbuf) = #0; -void Cbuf_Execute_Sets (cbuf_t *cbuf) = #0; +void Cbuf_AddText (cbuf_t cbuf, string text) = #0; +void Cbuf_InsertText (cbuf_t cbuf, string text) = #0; +void Cbuf_Execute (cbuf_t cbuf) = #0; +void Cbuf_Execute_Sets (cbuf_t cbuf) = #0; diff --git a/ruamoko/qwaq/debugger/typeencodings.r b/ruamoko/qwaq/debugger/typeencodings.r index fe296a573..a3053e69d 100644 --- a/ruamoko/qwaq/debugger/typeencodings.r +++ b/ruamoko/qwaq/debugger/typeencodings.r @@ -53,6 +53,9 @@ static void type_free (void *t, void *unused) case ty_alias: str_free (type.alias.name); break; + case ty_handle: + str_free (type.handle.tag); + break; } obj_free (t); } @@ -179,6 +182,11 @@ static void type_free (void *t, void *unused) } type.alias.full_type = t; goto hash_type; + case ty_handle: + if (!(type.handle.tag = qdb_get_string (target, type.handle.tag))) { + goto error; + } + goto hash_type; } goto error; hash_type: @@ -197,6 +205,7 @@ error: int size = 0; switch (type.meta) { + case ty_handle: case ty_basic: size = pr_type_size[type.type]; break; diff --git a/tools/qfcc/include/struct.h b/tools/qfcc/include/struct.h index e55a75aee..3b1d14edb 100644 --- a/tools/qfcc/include/struct.h +++ b/tools/qfcc/include/struct.h @@ -43,6 +43,8 @@ typedef struct { void (*emit) (struct def_s *def, void *data, int index); } struct_def_t; +struct symbol_s *find_handle (struct symbol_s *tag, struct type_s *type); + struct symtab_s *start_struct (int *su, struct symbol_s *tag, struct symtab_s *parent); struct symbol_s *find_struct (int su, struct symbol_s *tag, diff --git a/tools/qfcc/source/dump_globals.c b/tools/qfcc/source/dump_globals.c index 3801bcc5d..895d95ce6 100644 --- a/tools/qfcc/source/dump_globals.c +++ b/tools/qfcc/source/dump_globals.c @@ -444,6 +444,7 @@ static const char *ty_meta_names[] = { "ty_array", "ty_class", "ty_alias", + "ty_handle", }; #define NUM_META ((int)(sizeof (ty_meta_names) / sizeof (ty_meta_names[0]))) const int vector_types = (1 << ev_float) @@ -531,6 +532,9 @@ dump_qfo_types (qfo_t *qfo, int base_address) type->alias.type, type->alias.aux_type, type->alias.full_type); break; + case ty_handle: + printf (" %-5x\n", type->handle.tag); + break; } } } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index c19520c46..3dc11fd7d 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -698,6 +698,7 @@ get_def_type (qfo_t *qfo, pr_ptr_t type) switch ((ty_meta_e)type_def->meta) { case ty_alias: //XXX case ty_basic: + case ty_handle: //XXX // field, pointer and function types store their basic type in // the same location. return type_def->type; @@ -726,6 +727,7 @@ get_type_size (qfo_t *qfo, pr_ptr_t type) switch ((ty_meta_e)type_def->meta) { case ty_alias: return get_type_size (qfo, type_def->alias.aux_type); + case ty_handle: //XXX case ty_basic: // field, pointer and function types store their basic type in // the same location. @@ -776,6 +778,7 @@ get_type_alignment_log (qfo_t *qfo, pr_ptr_t type) switch ((ty_meta_e)type_def->meta) { case ty_alias: return get_type_alignment_log (qfo, type_def->alias.aux_type); + case ty_handle: //XXX case ty_basic: // field, pointer and function types store their basic type in // the same location. diff --git a/tools/qfcc/source/obj_type.c b/tools/qfcc/source/obj_type.c index c00f2f43e..8e896b750 100644 --- a/tools/qfcc/source/obj_type.c +++ b/tools/qfcc/source/obj_type.c @@ -277,6 +277,19 @@ qfo_encode_alias (type_t *type, defspace_t *space) return def; } +static def_t * +qfo_encode_handle (type_t *type, defspace_t *space) +{ + qfot_type_t *enc; + def_t *def; + + def = qfo_new_encoding (type, sizeof (enc->handle), space); + enc = D_POINTER (qfot_type_t, def); + enc->handle.type = type->type; + ENC_STR (enc->handle.tag, type->name); + return def; +} + def_t * qfo_encode_type (type_t *type, defspace_t *space) { @@ -290,6 +303,7 @@ qfo_encode_type (type_t *type, defspace_t *space) qfo_encode_array, // ty_array qfo_encode_class, // ty_class qfo_encode_alias, // ty_alias + qfo_encode_handle, // ty_handle }; if (type->type_def && type->type_def->external) { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 20317e960..d5fbcb71e 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -449,6 +449,7 @@ static keyword_t keywords[] = { {"@system", SYSTEM, }, {"@overload", OVERLOAD, }, {"@attribute", ATTRIBUTE, }, + {"@handle", HANDLE, }, }; static const char * diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index ab955e9fa..f341a425f 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -153,7 +153,7 @@ int yylex (void); %token RETURN AT_RETURN ELLIPSIS %token NIL GOTO SWITCH CASE DEFAULT ENUM %token ARGS TYPEDEF EXTERN STATIC SYSTEM OVERLOAD NOT ATTRIBUTE -%token STRUCT +%token STRUCT HANDLE %token TYPE_SPEC TYPE_NAME TYPE_QUAL %token OBJECT_NAME %token CLASS DEFS ENCODE END IMPLEMENTATION INTERFACE PRIVATE @@ -1085,6 +1085,19 @@ struct_specifier symtab_addsymbol (tab, sym); } } + | HANDLE tag + { + symbol_t *sym = find_handle ($2, 0); + sym->type = find_type (sym->type); + $$ = make_spec (sym->type, 0, 0, 0); + if (!sym->table) { + symtab_t *tab = current_symtab; + while (tab->parent && tab->type == stab_struct) { + tab = tab->parent; + } + symtab_addsymbol (tab, sym); + } + } ; struct_list diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 8f4dc6b70..b8a90a358 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -125,6 +125,18 @@ start_struct (int *su, symbol_t *tag, symtab_t *parent) return new_symtab (parent, stab_struct); } +symbol_t * +find_handle (symbol_t *tag, type_t *type) +{ + symbol_t *sym = find_tag (ty_handle, tag, type); + if (sym->type->type == ev_invalid) { + sym->type->type = ev_func; + sym->type->width = 1; + sym->type->alignment = 1; + } + return sym; +} + symbol_t * find_struct (int su, symbol_t *tag, type_t *type) { diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 6a4cb9f5e..58c7083b1 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -308,6 +308,7 @@ copy_chain (type_t *type, type_t *append) case ty_enum: case ty_class: case ty_alias: //XXX is this correct? + case ty_handle: internal_error (0, "copy object type %d", type->meta); } } @@ -365,6 +366,7 @@ append_type (type_t *type, type_t *new) case ty_enum: case ty_class: case ty_alias: //XXX is this correct? + case ty_handle: internal_error (0, "append to object type"); } } @@ -432,6 +434,9 @@ types_same (type_t *a, type_t *b) return (a->name == b->name && a->t.alias.aux_type == b->t.alias.aux_type && a->t.alias.full_type == b->t.alias.full_type); + case ty_handle: + // names have gone through save_string + return a->name == b->name; } internal_error (0, "we be broke"); } @@ -560,6 +565,8 @@ find_type (type_t *type) case ty_alias: type->t.alias.aux_type = find_type (type->t.alias.aux_type); break; + case ty_handle: + break; } } @@ -807,6 +814,9 @@ print_type_str (dstring_t *str, const type_t *type) return; } switch (type->meta) { + case ty_handle: + dasprintf (str, " handle %s", type->name); + return; case ty_alias: dasprintf (str, "({%s=", type->name); print_type_str (str, type->t.alias.aux_type); @@ -996,6 +1006,9 @@ encode_type (dstring_t *encoding, const type_t *type) if (!type) return; switch (type->meta) { + case ty_handle: + dasprintf (encoding, "{%s$}", type->name); + return; case ty_alias: dasprintf (encoding, "{%s>", type->name ? type->name : ""); encode_type (encoding, type->t.alias.aux_type); @@ -1331,6 +1344,7 @@ int type_size (const type_t *type) { switch (type->meta) { + case ty_handle: case ty_basic: return pr_type_size[type->type] * type->width; case ty_struct: @@ -1373,6 +1387,7 @@ type_width (const type_t *type) return 4; } return type->width; + case ty_handle: case ty_struct: case ty_union: return 1; From d001473536e25bb9cf598295121980ac0765914e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 25 May 2023 21:22:50 +0900 Subject: [PATCH 3573/3664] [qfcc] Make is_struct struct-only And add is_union to handle unions. Sometimes it's necessary to check between the two. --- tools/qfcc/include/type.h | 1 + tools/qfcc/source/constfold.c | 2 ++ tools/qfcc/source/def.c | 6 ++---- tools/qfcc/source/expr.c | 4 ++-- tools/qfcc/source/qc-parse.y | 5 +++-- tools/qfcc/source/statements.c | 4 ++-- tools/qfcc/source/struct.c | 5 ++--- tools/qfcc/source/type.c | 18 ++++++++++++------ 8 files changed, 26 insertions(+), 19 deletions(-) diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index bf68f8ad4..0ddca9623 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -218,6 +218,7 @@ int is_scalar (const type_t *type) __attribute__((pure)); int is_nonscalar (const type_t *type) __attribute__((pure)); int is_math (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); +int is_union (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); int is_structural (const type_t *type) __attribute__((pure)); int type_compatible (const type_t *dst, const type_t *src) __attribute__((pure)); diff --git a/tools/qfcc/source/constfold.c b/tools/qfcc/source/constfold.c index e52294f05..18c3e1218 100644 --- a/tools/qfcc/source/constfold.c +++ b/tools/qfcc/source/constfold.c @@ -1013,6 +1013,8 @@ do_op_compound (int op, expr_t *e, expr_t *e1, expr_t *e2) type_t *t2 = get_type (e2); if (is_struct (t1) && is_struct (t2)) return do_op_struct (op, e, e1, e2); + if (is_union (t1) && is_union (t2)) + return do_op_struct (op, e, e1, e2); if (is_scalar (t1) && is_scalar (t2)) { if (is_enum (t1)) { if (t2->type == ev_double) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 99f8c9962..b314d20c1 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -605,10 +605,8 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space, convert_name (init); if (init->type == ex_error) return; - if ((is_array (sym->type) || is_struct (sym->type) - || is_nonscalar (sym->type)) - && ((init->type == ex_compound) - || init->type == ex_nil)) { + if ((is_structural (sym->type) || is_nonscalar (sym->type)) + && (init->type == ex_compound || init->type == ex_nil)) { init_elements (sym->s.def, init); sym->s.def->initialized = 1; } else { diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 130294ba7..deec20857 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1467,7 +1467,7 @@ field_expr (expr_t *e1, expr_t *e2) } } } else if (is_ptr (t1)) { - if (is_struct (t1->t.fldptr.type)) { + if (is_struct (t1->t.fldptr.type) || is_union (t1->t.fldptr.type)) { symbol_t *field; field = get_struct_field (t1->t.fldptr.type, e1, e2); @@ -1492,7 +1492,7 @@ field_expr (expr_t *e1, expr_t *e2) e1 = cast_expr (pointer_type (ivar->type), e1); return unary_expr ('.', e1); } - } else if (is_nonscalar (t1) || is_struct (t1)) { + } else if (is_nonscalar (t1) || is_struct (t1) || is_union (t1)) { symbol_t *field; field = get_struct_field (t1, e1, e2); diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index f341a425f..75df40e0f 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -436,7 +436,7 @@ is_anonymous_struct (specifier_t spec) if (spec.sym) { return 0; } - if (!is_struct (spec.type)) { + if (!is_struct (spec.type) && !is_union (spec.type)) { return 0; } if (!spec.type->t.symtab || spec.type->t.symtab->parent) { @@ -484,7 +484,8 @@ check_specifiers (specifier_t spec) if (is_anonymous_struct (spec)){ warning (0, "unnamed struct/union that defines " "no instances"); - } else if (!is_enum (spec.type) && !is_struct (spec.type)) { + } else if (!is_enum (spec.type) + && !is_struct (spec.type) && !is_union (spec.type)) { warning (0, "useless type name in empty declaration"); } } else if (!spec.type && spec.sym) { diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index a1faf867a..e5be663d9 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -1044,7 +1044,7 @@ expr_call_v6p (sblock_t *sblock, expr_t *call, operand_t **op) use = p; continue; } - if (is_struct (get_type (param))) { + if (is_struct (get_type (param)) || is_union (get_type (param))) { expr_t *mov = assign_expr (param, a); mov->line = a->line; mov->file = a->file; @@ -1946,7 +1946,7 @@ expr_nil (sblock_t *sblock, expr_t *e, operand_t **op) operand_t *size; statement_t *s; - if (!is_struct (nil) && !is_array (nil)) { + if (!is_structural (nil)) { *op = value_operand (new_nil_val (nil), e); return sblock; } diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index b8a90a358..eda541cb1 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -186,7 +186,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type, int base) symbol_t *t = s->next; int offset = s->s.offset; - if (!is_struct (s->type)) { + if (!is_struct (s->type) && !is_union (s->type)) { internal_error (0, "non-struct/union anonymous field"); } anonymous = s->type->t.symtab; @@ -362,8 +362,7 @@ emit_structure (const char *name, int su, struct_def_t *defs, type_t *type, name = save_string (name); if (!type) type = make_structure (0, su, defs, 0)->type; - if (!is_struct (type) || (su == 's' && type->meta != ty_struct) - || (su == 'u' && type->meta != ty_union)) + if ((su == 's' && !is_struct (type)) || (su == 'u' && !is_union (type))) internal_error (0, "structure %s type mismatch", name); for (i = 0, field_sym = type->t.symtab->symbols; field_sym; i++, field_sym = field_sym->next) { diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 58c7083b1..06cdf68df 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -174,9 +174,7 @@ low_level_type (type_t *type) return type->type; if (is_enum (type)) return type_default->type; - if (is_struct (type)) - return ev_void; - if (is_array (type)) + if (is_structural (type)) return ev_void; internal_error (0, "invalid complex type"); } @@ -1210,8 +1208,16 @@ int is_struct (const type_t *type) { type = unalias_type (type); - if (type->type == ev_invalid - && (type->meta == ty_struct || type->meta == ty_union)) + if (type->type == ev_invalid && type->meta == ty_struct) + return 1; + return 0; +} + +int +is_union (const type_t *type) +{ + type = unalias_type (type); + if (type->type == ev_invalid && type->meta == ty_union) return 1; return 0; } @@ -1229,7 +1235,7 @@ int is_structural (const type_t *type) { type = unalias_type (type); - return is_struct (type) || is_array (type); + return is_struct (type) || is_union (type) || is_array (type); } int From 89e60bd52162ca5a710184d3846f5c1884b898ff Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 May 2023 16:53:37 +0900 Subject: [PATCH 3574/3664] [set] Add functions to add and remove ranges It is often necessary to add or remove whole ranges of elements, but doing so one at a time can be quite inefficient. --- include/QF/set.h | 26 +++++++++++++++ libs/util/set.c | 67 +++++++++++++++++++++++++++++++++++++++ libs/util/test/test-set.c | 42 ++++++++++++++++++++++++ 3 files changed, 135 insertions(+) diff --git a/include/QF/set.h b/include/QF/set.h index 0d3c9327e..e0160c61c 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -198,6 +198,19 @@ void set_trim (set_t *set); */ set_t *set_add (set_t *set, unsigned x); +/** Add a range of elements to a set. + + It is not an error to add elements that are already members of the set. + + \note \a set is modified. + + \param set The set to which the element will be added. + \param start The first element to be added. + \param count The number of elements to be added. + \return The modified set. +*/ +set_t *set_add_range (set_t *set, unsigned start, unsigned count); + /** Remove an element from a set. It is not an error to remove an element that is not a member of the set. @@ -210,6 +223,19 @@ set_t *set_add (set_t *set, unsigned x); */ set_t *set_remove (set_t *set, unsigned x); +/** Remove a range of elements from a set. + + It is not an error to remove elements that not members of the set. + + \note \a set is modified. + + \param set The set from which the element will be removed. + \param start The first element to be removed. + \param count The number of elements to be removed. + \return The modified set. +*/ +set_t *set_remove_range (set_t *set, unsigned start, unsigned count); + /** Compute the inverse of a set. The computation is done as \a set = ~\a set. diff --git a/libs/util/set.c b/libs/util/set.c index 06c67e5be..c4dc8ab94 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -191,6 +191,53 @@ _set_remove (set_t *set, unsigned x) SET_REMOVE(set, x); } +static inline void +_set_add_range (set_t *set, unsigned start, unsigned count) +{ + if (!count || start + count > set->size) { + set_expand (set, start + count); + } + unsigned end = start + count - 1; + set_bits_t start_mask = (~SET_ZERO) << (start % SET_BITS); + set_bits_t end_mask = (~SET_ZERO) >> (SET_BITS - ((end + 1) % SET_BITS)); + unsigned start_ind = start / SET_BITS; + unsigned end_ind = end / SET_BITS; + if (start_ind == end_ind) { + set->map[start_ind] |= start_mask & end_mask; + } else { + set->map[start_ind] |= start_mask; + for (unsigned i = start_ind + 1; i < end_ind; i++) { + set->map[i] = ~SET_ZERO; + } + set->map[end_ind] |= end_mask; + } +} + +static inline void +_set_remove_range (set_t *set, unsigned start, unsigned count) +{ + if (!count || start >= set->size) { + return; + } + if (start + count > set->size) { + count = set->size - start; + } + unsigned end = start + count - 1; + set_bits_t start_mask = (~SET_ZERO) << (start % SET_BITS); + set_bits_t end_mask = (~SET_ZERO) >> (SET_BITS - ((end + 1) % SET_BITS)); + unsigned start_ind = start / SET_BITS; + unsigned end_ind = end / SET_BITS; + if (start_ind == end_ind) { + set->map[start_ind] &= ~(start_mask & end_mask); + } else { + set->map[start_ind] &= ~start_mask; + for (unsigned i = start_ind + 1; i < end_ind; i++) { + set->map[i] = SET_ZERO; + } + set->map[end_ind] &= ~end_mask; + } +} + set_t * set_add (set_t *set, unsigned x) { @@ -201,6 +248,16 @@ set_add (set_t *set, unsigned x) return set; } +set_t * +set_add_range (set_t *set, unsigned start, unsigned count) +{ + if (set->inverted) + _set_remove_range (set, start, count); + else + _set_add_range (set, start, count); + return set; +} + set_t * set_remove (set_t *set, unsigned x) { @@ -211,6 +268,16 @@ set_remove (set_t *set, unsigned x) return set; } +set_t * +set_remove_range (set_t *set, unsigned start, unsigned count) +{ + if (set->inverted) + _set_add_range (set, start, count); + else + _set_remove_range (set, start, count); + return set; +} + set_t * set_invert (set_t *set) { diff --git a/libs/util/test/test-set.c b/libs/util/test/test-set.c index 412517d22..4e214cae8 100644 --- a/libs/util/test/test-set.c +++ b/libs/util/test/test-set.c @@ -77,6 +77,28 @@ make_0_to_SIZEm1 (void) return set; } +static set_t * +make_range_0_SIZE (void) +{ + set_t *set = set_new (); + set_add_range (set, 0, SIZE); + return set; +} + +static set_t * +make_range_1_SIZE (void) +{ + set_t *set = set_new (); + set_add_range (set, 1, SIZE); + return set; +} + +static set_t * +remove_3_9 (set_t *set, const set_t *dummy) +{ + return set_remove_range (set, 3, 9); +} + static int check_size (const set_t *set, const set_t *unused) { @@ -274,6 +296,26 @@ struct { " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 65 ...}" }, {make_not_1_2, make_SIZE, set_reverse_difference, check_size, SIZE, "{}"}, + {make_range_0_SIZE, 0, 0, check_size, SIZE, + "{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63}" + }, + {make_range_1_SIZE, 0, 0, check_size, SIZE + SET_BITS, + "{1 2 3 4 5 6 7 8 9 10 11 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63" + " 64}" + }, + {make_everything, 0, remove_3_9, check_size, SIZE, "{0 1 2 12 ...}"}, + {make_range_0_SIZE, 0, remove_3_9, check_size, SIZE, + "{0 1 2 12 13 14 15" + " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" + " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47" + " 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63}" + }, }; #define num_tests (sizeof (tests) / sizeof (tests[0])) From d5156a23206ba7d096625a3bd220835512562cfc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 May 2023 21:46:34 +0900 Subject: [PATCH 3575/3664] [set] Add an edge detection iterator set_while checks the iterator's current element membership and skips to the first element with different membership. ie, if the current element is in the set, then set_while returns the next element *not* in the set, but if the current is not in the set, then set_while returns the next element that *is* in the set. Rather handy for dealing with clusters of set elements. --- include/QF/set.h | 3 +++ libs/util/set.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/QF/set.h b/include/QF/set.h index e0160c61c..0fc200cb5 100644 --- a/include/QF/set.h +++ b/include/QF/set.h @@ -428,6 +428,9 @@ set_iter_t *set_first_r (set_pool_t *set_pool, const set_t *set); set_iter_t *set_next (set_iter_t *set_iter); set_iter_t *set_next_r (set_pool_t *set_pool, set_iter_t *set_iter); +set_iter_t *set_while (set_iter_t *set_iter); +set_iter_t *set_while_r (set_pool_t *set_pool, set_iter_t *set_iter); + struct dstring_s; /** Return a human-readable string representing the set. diff --git a/libs/util/set.c b/libs/util/set.c index c4dc8ab94..e391583a6 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -734,6 +734,36 @@ set_next (set_iter_t *set_iter) return set_next_r (&static_set_pool, set_iter); } +set_iter_t * +set_while_r (set_pool_t *set_pool, set_iter_t *set_iter) +{ + unsigned x; + + if (_set_is_member (set_iter->set, set_iter->element)) { + for (x = set_iter->element + 1; x < set_iter->set->size; x++) { + if (!_set_is_member (set_iter->set, x)) { + set_iter->element = x; + return set_iter; + } + } + } else { + for (x = set_iter->element + 1; x < set_iter->set->size; x++) { + if (_set_is_member (set_iter->set, x)) { + set_iter->element = x; + return set_iter; + } + } + } + delete_setiter (set_pool, set_iter); + return 0; +} + +set_iter_t * +set_while (set_iter_t *set_iter) +{ + return set_while_r (&static_set_pool, set_iter); +} + const char * set_to_dstring_r (set_pool_t *set_pool, dstring_t *str, const set_t *set) { From 09a3e257e87045fd4c49d56b0e3459fe2f81d461 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 26 May 2023 21:56:19 +0900 Subject: [PATCH 3576/3664] [qfcc] Fully initialize local structural defs I think the current build_element_chain implementation does a reasonable job, but I'm in the process of getting designated initializers working, thus it will become important to ensure uninitialized members get initialized. --- tools/qfcc/include/expr.h | 3 ++- tools/qfcc/source/expr.c | 13 ++++++++++++- tools/qfcc/source/expr_compound.c | 21 +++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 43dc6a255..b2b7631f3 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -142,7 +142,6 @@ typedef struct ex_memset_s { struct expr_s *dst; struct expr_s *val; struct expr_s *count; - struct type_s *type; } ex_memset_t; /** State expression used for think function state-machines. @@ -778,6 +777,8 @@ expr_t *new_with_expr (int mode, int reg, expr_t *val); */ expr_t *new_param_expr (struct type_s *type, int num); +expr_t *new_memset_expr (expr_t *dst, expr_t *val, expr_t *count); + /** Convert a name to an expression of the appropriate type. Converts the expression in-place. If the exprssion is not a name diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index deec20857..3e25ee5b1 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -140,7 +140,7 @@ get_type (expr_t *e) case ex_with: return &type_void; case ex_memset: - return e->e.memset.type; + return 0; case ex_error: return 0; case ex_return: @@ -1374,6 +1374,17 @@ new_param_expr (type_t *type, int num) return param_expr (va (0, ".param_%d", num), type); } +expr_t * +new_memset_expr (expr_t *dst, expr_t *val, expr_t *count) +{ + expr_t *e = new_expr (); + e->type = ex_memset; + e->e.memset.dst = dst; + e->e.memset.val = val; + e->e.memset.count = count; + return e; +} + expr_t * append_expr (expr_t *block, expr_t *e) { diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c index 2ba6f489a..eb5dafae8 100644 --- a/tools/qfcc/source/expr_compound.c +++ b/tools/qfcc/source/expr_compound.c @@ -42,6 +42,7 @@ #include "QF/alloc.h" #include "QF/dstring.h" #include "QF/mathlib.h" +#include "QF/set.h" #include "QF/sys.h" #include "QF/va.h" @@ -189,6 +190,8 @@ assign_elements (expr_t *local_expr, expr_t *init, element_chain_t *element_chain) { element_t *element; + type_t *init_type = get_type (init); + set_t *initialized = set_new_size (type_size (init_type)); for (element = element_chain->head; element; element = element->next) { int offset = element->offset; @@ -206,7 +209,25 @@ assign_elements (expr_t *local_expr, expr_t *init, c = convert_nil (c, type); } append_expr (local_expr, assign_expr (alias, c)); + set_add_range (initialized, offset, type_size (type)); } + + unsigned start = 0; + for (set_iter_t *in = set_first (initialized); in; in = set_next (in)) { + unsigned end = in->element; + if (end > start) { + expr_t *dst = new_offset_alias_expr (&type_int, init, start); + expr_t *zero = new_int_expr (0); + expr_t *count = new_int_expr (end - start); + append_expr (local_expr, new_memset_expr (dst, zero, count)); + } + // skip over all the initialized locations + in = set_while (in); + if (in) { + start = in->element; + } + } + set_delete (initialized); } expr_t * From 04e26a7b9fca3d0d945f3d7640f5b92fa96c8247 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 May 2023 00:55:22 +0900 Subject: [PATCH 3577/3664] [set] Check for 0 count correctly I don't know what I was thinking when I checked for 0 count for resizing the set. Attempting to add/remove 0 elements results in adding/removing 4G elements. Oops. --- libs/util/set.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libs/util/set.c b/libs/util/set.c index e391583a6..71f1a82e9 100644 --- a/libs/util/set.c +++ b/libs/util/set.c @@ -194,7 +194,10 @@ _set_remove (set_t *set, unsigned x) static inline void _set_add_range (set_t *set, unsigned start, unsigned count) { - if (!count || start + count > set->size) { + if (!count) { + return; + } + if (start + count > set->size) { set_expand (set, start + count); } unsigned end = start + count - 1; @@ -216,7 +219,10 @@ _set_add_range (set_t *set, unsigned start, unsigned count) static inline void _set_remove_range (set_t *set, unsigned start, unsigned count) { - if (!count || start >= set->size) { + if (!count) { + return; + } + if (start >= set->size) { return; } if (start + count > set->size) { From 5d9823af30703f5b965a7739205d719e8bf05ce3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 May 2023 00:59:43 +0900 Subject: [PATCH 3578/3664] [qfcc] Implement designated initializers Conforms fairly closely to GCC's C implementation. --- tools/qfcc/include/expr.h | 11 +- tools/qfcc/include/symtab.h | 1 + tools/qfcc/source/expr.c | 2 +- tools/qfcc/source/expr_compound.c | 221 ++++++++++++++++++++++-------- tools/qfcc/source/qc-parse.y | 28 +++- tools/qfcc/source/struct.c | 1 + 6 files changed, 201 insertions(+), 63 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index b2b7631f3..c6f45c3dc 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -74,12 +74,18 @@ typedef struct { ex_label_t *label; } ex_labelref_t; +typedef struct designator_s { + struct designator_s *next; + struct expr_s *field; + struct expr_s *index; +} designator_t; + typedef struct element_s { struct element_s *next; ///< next in chain int offset; struct type_s *type; struct expr_s *expr; ///< initializer expression - struct symbol_s *symbol; ///< for labeled initializers + designator_t *designator; ///< for labeled initializers } element_t; typedef struct element_chain_s { @@ -448,7 +454,8 @@ expr_t *new_block_expr (void); */ expr_t *build_block_expr (expr_t *expr_list); -element_t *new_element (expr_t *expr, struct symbol_s *symbol); +designator_t *new_designator (expr_t *field, expr_t *index); +element_t *new_element (expr_t *expr, designator_t *designator); expr_t *new_compound_init (void); expr_t *append_element (expr_t *compound, element_t *element); expr_t *initialized_temp_expr (const struct type_s *type, expr_t *compound); diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index ad6204f8d..8d8943ef7 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -72,6 +72,7 @@ typedef struct symbol_s { sy_type_e sy_type; ///< symbol type struct type_s *type; ///< type of object to which symbol refers struct param_s *params; ///< the parameters if a function + unsigned no_auto_init; ///< skip for non-designated initializers union { int offset; ///< sy_var (in a struct/union) struct def_s *def; ///< sy_var diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 3e25ee5b1..6f84bfdea 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -370,7 +370,7 @@ copy_expr (expr_t *e) n = new_expr (); *n = *e; for (element_t *i = e->e.compound.head; i; i = i->next) { - append_element (n, new_element (i->expr, i->symbol)); + append_element (n, new_element (i->expr, i->designator)); } return n; case ex_memset: diff --git a/tools/qfcc/source/expr_compound.c b/tools/qfcc/source/expr_compound.c index eb5dafae8..df382809f 100644 --- a/tools/qfcc/source/expr_compound.c +++ b/tools/qfcc/source/expr_compound.c @@ -53,14 +53,31 @@ #include "tools/qfcc/include/type.h" ALLOC_STATE (element_t, elements); +ALLOC_STATE (designator_t, designators); + +designator_t * +new_designator (expr_t *field, expr_t *index) +{ + if ((!field && !index) || (field && index)) { + internal_error (0, "exactly one of field or index is required"); + } + if (field && field->type != ex_symbol) { + internal_error (field, "invalid field designator"); + } + designator_t *des; + ALLOC (256, designator_t, designators, des); + des->field = field; + des->index = index; + return des; +} element_t * -new_element (expr_t *expr, symbol_t *symbol) +new_element (expr_t *expr, designator_t *designator) { element_t *element; ALLOC (256, element_t, elements, element); element->expr = expr; - element->symbol = symbol; + element->designator = designator; return element; } @@ -83,29 +100,99 @@ new_compound_init (void) return c; } -static element_t * -build_array_element_chain(element_chain_t *element_chain, - int array_size, type_t *array_type, - element_t *ele, - int base_offset) +static symbol_t * +designator_field (const designator_t *des, const type_t *type) { - for (int i = 0; i < array_size; i++) { - int offset = base_offset + i * type_size (array_type); - if (ele && ele->expr && ele->expr->type == ex_compound) { - build_element_chain (element_chain, array_type, - ele->expr, offset); - } else { - element_t *element = new_element (0, 0); - element->type = array_type; - element->offset = offset; - element->expr = ele ? ele->expr : 0; // null -> nil - append_init_element (element_chain, element); - } - if (ele) { - ele = ele->next; - } + if (des->index) { + error (des->index, "designator index in non-array"); + return 0; } - return ele; + symtab_t *symtab = type->t.symtab; + symbol_t *sym = des->field->e.symbol; + symbol_t *field = symtab_lookup (symtab, sym->name);; + if (!field) { + const char *name = type->name; + if (!strncmp (name, "tag ", 4)) { + name += 4; + } + error (des->field, "'%s' has no member named '%s'", name, sym->name); + return 0; + } + return field; +} + +static int +designator_index (const designator_t *des, int ele_size, int array_size) +{ + if (des->field) { + error (des->field, "field designator in array initializer"); + return -1; + } else if (!is_constant (des->index)) { + error (des->index, "non-constant designator index"); + return -1; + } else if (!is_integral (get_type (des->index))) { + error (des->index, "invalid designator index type"); + return -1; + } + int index = expr_integral (des->index); + if (index <= 0 || index >= array_size) { + error (des->index, "designator index out of bounds"); + return -1; + } + return index * ele_size; +} + +typedef struct { + type_t *type; + symbol_t *field; + int offset; +} initstate_t; + +static initstate_t +get_designated_offset (const type_t *type, const designator_t *des) +{ + int offset = -1; + type_t *ele_type = 0; + symbol_t *field = 0; + + if (is_struct (type) || is_union (type)) { + field = designator_field (des, type); + offset = field->s.offset; + ele_type = field->type; + } else if (is_array (type)) { + int array_size = type->t.array.size; + ele_type = type->t.array.type; + offset = designator_index (des, type_size (ele_type), array_size); + } else if (is_nonscalar (type)) { + ele_type = ev_types[type->type]; + if (type->t.symtab && des->field) { + field = designator_field (des, type); + offset = field->s.offset; + } else { + int vec_width = type_width (type); + offset = designator_index (des, type_size (ele_type), vec_width); + } + } else { + error (0, "invalid initializer"); + } + if (ele_type && des->next) { + __auto_type state = get_designated_offset (ele_type, des->next); + ele_type = state.type; + offset += state.offset; + } + return (initstate_t) { .type = ele_type, .field = field, .offset = offset}; +} + +static int +skip_field (symbol_t *field) +{ + if (field->sy_type != sy_var) { + return 1; + } + if (field->no_auto_init) { + return 1; + } + return 0; } void @@ -116,50 +203,64 @@ build_element_chain (element_chain_t *element_chain, const type_t *type, type = unalias_type (type); - if (is_array (type)) { - type_t *array_type = type->t.array.type; - int array_size = type->t.array.size; - ele = build_array_element_chain (element_chain, array_size, array_type, - ele, base_offset); - } else if (is_struct (type) || (is_nonscalar (type) && type->t.symtab)) { - symtab_t *symtab = type->t.symtab; - symbol_t *field; + initstate_t state = {}; + if (is_struct (type) || is_union (type) + || (is_nonscalar (type) && type->t.symtab)) { + state.field = type->t.symtab->symbols; + while (skip_field (state.field)) { + state.field = state.field->next; + } + state.type = state.field->type; + state.offset = state.field->s.offset; + } else if (is_array (type)) { + state.type = type->t.array.type; + } else { + internal_error (eles, "invalid initialization"); + } + while (ele) { + if (ele->designator) { + state = get_designated_offset (type, ele->designator); + } + if (!state.type) { + break; + } - for (field = symtab->symbols; field; field = field->next) { - int offset = base_offset + field->s.offset; - if (field->sy_type != sy_var - || field->visibility == vis_anonymous) { - continue; + if (state.offset >= type_size (type)) { + if (options.warnings.initializer) { + warning (eles, "excessive elements in initializer"); } - if (ele && ele->expr && ele->expr->type == ex_compound) { - build_element_chain (element_chain, field->type, - ele->expr, offset); - } else { - element_t *element = new_element (0, 0); - element->type = field->type; - element->offset = offset; - element->expr = ele ? ele->expr : 0; // null -> nil - append_init_element (element_chain, element); + break; + } + + if (ele->expr && ele->expr->type == ex_compound) { + build_element_chain (element_chain, state.type, ele->expr, + state.offset); + } else { + element_t *element = new_element (0, 0); + element->type = state.type; + element->offset = base_offset + state.offset; + element->expr = ele->expr; // null -> nil + append_init_element (element_chain, element); + } + + state.offset += type_size (state.type); + if (state.field) { + state.field = state.field->next; + while (state.field && skip_field (state.field)) { + state.field = state.field->next; } - if (ele) { - ele = ele->next; + if (state.field) { + state.type = state.field->type; + state.offset = state.field->s.offset; } } - } else if (is_nonscalar (type)) { - // vector type with unnamed components - int vec_width = type_width (type); - type_t *vec_type = ev_types[type->type]; - ele = build_array_element_chain (element_chain, vec_width, vec_type, - ele, base_offset); - } else { - error (eles, "invalid initializer"); - } - if (ele && ele->next && options.warnings.initializer) { - warning (eles, "excessive elements in initializer"); + + ele = ele->next; } } -void free_element_chain (element_chain_t *element_chain) +void +free_element_chain (element_chain_t *element_chain) { *element_chain->tail = elements_freelist; elements_freelist = element_chain->head; @@ -200,6 +301,8 @@ assign_elements (expr_t *local_expr, expr_t *init, expr_t *c; + if (type_size (type) == 0) + internal_error (init, "wtf"); if (element->expr) { c = constant_expr (element->expr); } else { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 75df40e0f..26e053730 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -114,6 +114,7 @@ int yylex (void); struct symbol_s *symbol; struct symtab_s *symtab; struct attribute_s *attribute; + struct designator_s *designator; } // these tokens are common between qc and qp @@ -194,6 +195,7 @@ int yylex (void); %type opt_init_semi opt_expr comma_expr expr %type compound_init element_list +%type designator designator_spec %type element %type ose optional_state_expr texpr vector_expr %type statement statements compound_statement @@ -1146,6 +1148,9 @@ struct_defs component_decl_list : component_decl_list2 | component_decl_list2 component_decl + { + warning (0, "no semicolon at end of struct or union"); + } ; component_decl_list2 @@ -1405,10 +1410,31 @@ element_list ; element - : compound_init { $$ = new_element ($1, 0); } + : designator '=' compound_init { $$ = new_element ($3, $1); } + | designator '=' expr { $$ = new_element ($3, $1); } + | compound_init { $$ = new_element ($1, 0); } | expr { $$ = new_element ($1, 0); } ; +designator + : designator_spec + | designator designator_spec + { + designator_t *des = $1; + while (des->next) { + des = des->next; + } + des->next = $2; + $$ = $1; + } + ; + +designator_spec + : '.' ident_expr { $$ = new_designator ($2, 0); } + | '.' NAME { $$ = new_designator (new_symbol_expr ($2), 0); } + | '[' expr ']' { $$ = new_designator (0, $2); } + ; + optional_comma : /* empty */ | ',' diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index eda541cb1..80c14fb01 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -202,6 +202,7 @@ build_struct (int su, symbol_t *tag, symtab_t *symtab, type_t *type, int base) s = s->next; s->s.offset += offset; s->table = symtab; + s->no_auto_init = 1; Hash_Add (symtab->tab, s); } } From ac42bca98b82afddc0862b3192698bf020436cb2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 May 2023 12:19:04 +0900 Subject: [PATCH 3579/3664] [ruamoko] Support nil object in obj_error Segfaulting when trying to produce an error message doesn't help get the message out. Sure, `obj_error (nil...)` is a bit of an abuse, but it shouldn't segfault the engine. --- libs/ruamoko/rua_obj.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 24fab22e9..f1d54d346 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1100,10 +1100,14 @@ obj_verror (probj_t *probj, pr_id_t *object, int code, const char *fmt, int coun pr_type_t **args) { progs_t *pr = probj->pr; - __auto_type class = &G_STRUCT (pr, pr_class_t, object->class_pointer); + const char *name = "nil"; + if (object) { + __auto_type class = &G_STRUCT (pr, pr_class_t, object->class_pointer); + name = PR_GetString (pr, class->name); + } PR_Sprintf (pr, probj->msg, "obj_verror", fmt, count, args); - PR_RunError (pr, "%s: %s", PR_GetString (pr, class->name), probj->msg->str); + PR_RunError (pr, "%s: %s", name, probj->msg->str); } static void From a22c2224e01fdcd3c1f12f34346a4807a370e66b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 May 2023 12:23:02 +0900 Subject: [PATCH 3580/3664] [ruamoko] Fortify and extend the script api Meaning some leaks have been plugged, and some useful functions added: loading a file (avoids polluting progs memory), setting the single character lexeme string, and getting the line number. --- libs/ruamoko/rua_script.c | 88 +++++++++++++++++++++++++++++++++++---- ruamoko/include/script.h | 5 ++- ruamoko/lib/script.r | 4 ++ 3 files changed, 88 insertions(+), 9 deletions(-) diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c index 5bcc262f2..41e8cacd8 100644 --- a/libs/ruamoko/rua_script.c +++ b/libs/ruamoko/rua_script.c @@ -44,50 +44,59 @@ #include "rua_internal.h" -typedef struct { +typedef struct rua_script_s { + struct rua_script_s *next; + struct rua_script_s **prev; script_t script; + char *text; // only for Script_FromFile pr_string_t dstr; progs_t *pr; } rua_script_t; typedef struct { - PR_RESMAP(rua_script_t) scripts; + PR_RESMAP(rua_script_t) script_map; + rua_script_t *scripts; } script_resources_t; static rua_script_t * script_new (script_resources_t *res) { - return PR_RESNEW (res->scripts); + return PR_RESNEW (res->script_map); } static void script_free (script_resources_t *res, rua_script_t *script) { - PR_RESFREE (res->scripts, script); + PR_RESFREE (res->script_map, script); } static void script_reset (script_resources_t *res) { - PR_RESRESET (res->scripts); + PR_RESRESET (res->script_map); } static inline rua_script_t * script_get (script_resources_t *res, int index) { - return PR_RESGET(res->scripts, index); + return PR_RESGET(res->script_map, index); } static inline int __attribute__((pure)) script_index (script_resources_t *res, rua_script_t *script) { - return PR_RESINDEX(res->scripts, script); + return PR_RESINDEX(res->script_map, script); } static void bi_script_clear (progs_t *pr, void *_res) { script_resources_t *res = (script_resources_t *) _res; + for (rua_script_t *s = res->scripts; s; s = s->next) { + free ((char *) s->script.single); + free (s->text); + } + res->scripts = 0; script_reset (res); } @@ -109,6 +118,12 @@ bi_Script_New (progs_t *pr, void *_res) script->dstr = PR_NewMutableString (pr); script->script.token = PR_GetMutableString (pr, script->dstr); script->pr = pr; + script->next = res->scripts; + script->prev = &res->scripts; + if (res->scripts) { + res->scripts->prev = &script->next; + } + res->scripts = script; R_INT (pr) = script_index (res, script); } @@ -121,6 +136,12 @@ bi_Script_Delete (progs_t *pr, void *_res) if (!script) PR_RunError (pr, "invalid script handle"); PR_FreeString (pr, script->dstr); + free ((char *) script->script.single); + free (script->text); + if (script->next) { + script->next->prev = script->prev; + } + *script->prev = script->next; script_free (res, script); } @@ -136,6 +157,29 @@ bi_Script_Start (progs_t *pr, void *_res) R_STRING (pr) = script->dstr; } +static void +bi_Script_FromFile (progs_t *pr, void *_res) +{ + script_resources_t *res = _res; + rua_script_t *script = script_get (res, P_INT (pr, 0)); + if (!script) + PR_RunError (pr, "invalid script handle"); + QFile *file = QFile_GetFile (pr, P_INT (pr, 2)); + long offset; + long size; + long len; + + offset = Qtell (file); + size = Qfilesize (file); + len = size - offset; + script->text = malloc (len + 1); + Qread (file, script->text, len); + script->text[len] = 0; + + Script_Start (&script->script, P_GSTRING (pr, 1), script->text); + R_STRING (pr) = script->dstr; +} + static void bi_Script_TokenAvailable (progs_t *pr, void *_res) { @@ -177,7 +221,7 @@ bi_Script_Error (progs_t *pr, void *_res) if (!script) PR_RunError (pr, "invalid script handle"); - R_STRING (pr) = PR_SetString (pr, script->script.error); + RETURN_STRING (pr, script->script.error); script->script.error = 0; } @@ -193,17 +237,45 @@ bi_Script_NoQuoteLines (progs_t *pr, void *_res) script->script.no_quote_lines = P_INT (pr, 1); } +static void +bi_Script_SetSingle (progs_t *pr, void *_res) +{ + script_resources_t *res = _res; + rua_script_t *script = script_get (res, P_INT (pr, 0)); + if (!script) + PR_RunError (pr, "invalid script handle"); + free ((char *) script->script.single); + script->script.single = 0; + const char *single = P_GSTRING (pr, 1); + if (single) { + script->script.single = strdup (single); + } +} + +static void +bi_Script_GetLine (progs_t *pr, void *_res) +{ + script_resources_t *res = _res; + rua_script_t *script = script_get (res, P_INT (pr, 0)); + if (!script) + PR_RunError (pr, "invalid script handle"); + R_INT (pr) = script->script.line; +} + #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) static builtin_t builtins[] = { bi(Script_New, 0), bi(Script_Delete, 1, p(ptr)), bi(Script_Start, 3, p(ptr), p(string), p(string)), + bi(Script_FromFile, 3, p(ptr), p(string), p(ptr)), bi(Script_TokenAvailable, 2, p(ptr), p(int)), bi(Script_GetToken, 2, p(ptr), p(int)), bi(Script_UngetToken, 1, p(ptr)), bi(Script_Error, 1, p(ptr)), bi(Script_NoQuoteLines, 1, p(ptr)), + bi(Script_SetSingle, 2, p(ptr), p(string)), + bi(Script_GetLine, 1, p(ptr)), {0} }; diff --git a/ruamoko/include/script.h b/ruamoko/include/script.h index 2a394f058..b56f479ab 100644 --- a/ruamoko/include/script.h +++ b/ruamoko/include/script.h @@ -1,16 +1,19 @@ #ifndef __ruamoko_script_h #define __ruamoko_script_h -typedef struct rua_script *script_t; +typedef @handle rua_script script_t; @extern script_t Script_New (void); @extern void Script_Delete (script_t script); // returns the token string @extern string Script_Start (script_t script, string file, string data); +@extern string Script_FromFile (script_t script, string filename, @handle _qfile_t file); @extern int Script_TokenAvailable (script_t script, int crossline); @extern int Script_GetToken (script_t script, int crossline); @extern void Script_UngetToken (script_t script); @extern string Script_Error (script_t script); @extern int Script_NoQuoteLines (script_t script); +@extern void Script_SetSingle (script_t script, string single); +@extern int Script_GetLine (script_t script); #endif//__ruamoko_script_h diff --git a/ruamoko/lib/script.r b/ruamoko/lib/script.r index e72c4b72a..086dcdfb7 100644 --- a/ruamoko/lib/script.r +++ b/ruamoko/lib/script.r @@ -1,11 +1,15 @@ +#include #include script_t Script_New (void) = #0; void Script_Delete (script_t script) = #0; // returns the token string string Script_Start (script_t script, string file, string data) = #0; +string Script_FromFile (script_t script, string filename, QFile file) = #0; int Script_TokenAvailable (script_t script, int crossline) = #0; int Script_GetToken (script_t script, int crossline) = #0; void Script_UngetToken (script_t script) = #0; string Script_Error (script_t script) = #0; int Script_NoQuoteLines (script_t script) = #0; +void Script_SetSingle (script_t script, string single) = #0; +int Script_GetLine (script_t script) = #0; From 582423a019812ed54c57d266e2aa341ee124ea45 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 May 2023 12:30:06 +0900 Subject: [PATCH 3581/3664] [ruamoko] Extend the string api Wrap the strtod, strtof, strtol, strtoul functions, supporting the end pointer as well (if not nil, the int offset of the end pointer relative to the string start is returned). Also, str_unmutable creates a return string from a mutable string (copying it). --- libs/ruamoko/rua_string.c | 60 +++++++++++++++++++++++++++++++++++++++ ruamoko/include/string.h | 5 ++++ ruamoko/lib/string.r | 5 ++++ 3 files changed, 70 insertions(+) diff --git a/libs/ruamoko/rua_string.c b/libs/ruamoko/rua_string.c index 8977160a7..6e625fdf2 100644 --- a/libs/ruamoko/rua_string.c +++ b/libs/ruamoko/rua_string.c @@ -39,6 +39,7 @@ #endif #include #include +#include #include "qfalloca.h" @@ -119,6 +120,12 @@ bi_str_new (progs_t *pr, void *data) R_STRING (pr) = PR_NewMutableString (pr); } +static void +bi_str_unmutable (progs_t *pr, void *data) +{ + RETURN_STRING (pr, P_GSTRING (pr, 0)); +} + static void bi_str_free (progs_t *pr, void *data) { @@ -315,6 +322,54 @@ bi_str_upper (progs_t *pr, void *data) RETURN_STRING (pr, upper); } +static void +bi_strtod (progs_t *pr, void *data) +{ + const char *str = P_GSTRING (pr, 0); + pr_type_t *end = P_GPOINTER (pr, 1); + char *end_ptr; + R_DOUBLE (pr) = strtod (str, &end_ptr); + if (end) { + end->value = end_ptr - str; + } +} + +static void +bi_strtof (progs_t *pr, void *data) +{ + const char *str = P_GSTRING (pr, 0); + pr_type_t *end = P_GPOINTER (pr, 1); + char *end_ptr; + R_FLOAT (pr) = strtof (str, &end_ptr); + if (end) { + end->value = end_ptr - str; + } +} + +static void +bi_strtol (progs_t *pr, void *data) +{ + const char *str = P_GSTRING (pr, 0); + pr_type_t *end = P_GPOINTER (pr, 1); + char *end_ptr; + R_LONG (pr) = strtol (str, &end_ptr, P_INT (pr, 2)); + if (end) { + end->value = end_ptr - str; + } +} + +static void +bi_strtoul (progs_t *pr, void *data) +{ + const char *str = P_GSTRING (pr, 0); + pr_type_t *end = P_GPOINTER (pr, 1); + char *end_ptr; + R_ULONG (pr) = strtoul (str, &end_ptr, P_INT (pr, 2)); + if (end) { + end->value = end_ptr - str; + } +} + #define bi(x,np,params...) {#x, bi_##x, -1, np, {params}} #define p(type) PR_PARAM(type) #define P(a, s) { .size = (s), .alignment = BITOP_LOG2 (a), } @@ -323,6 +378,7 @@ static builtin_t builtins[] = { bi(sprintf, -2, p(string)), bi(vsprintf, 2, p(string), P(1, 2)), bi(str_new, 0), + bi(str_unmutable, 1, p(string)), bi(str_free, 1, p(string)), bi(str_hold, 1, p(string)), bi(str_valid, 1, p(string)), @@ -337,6 +393,10 @@ static builtin_t builtins[] = { bi(str_quote, 1, p(string)), bi(str_lower, 1, p(string)), bi(str_upper, 1, p(string)), + bi(strtod, 1, p(string)), + bi(strtof, 1, p(string)), + bi(strtol, 1, p(string)), + bi(strtoul, 1, p(string)), {0} }; diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index 3d978cfd5..e7ba66ba1 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -5,6 +5,7 @@ @extern string sprintf (string fmt, ...); @extern string vsprintf (string fmt, @va_list args); @extern string str_new (void); +@extern string str_unmutable (string str); @extern void str_free (string str); @extern string str_hold (string str); @extern int str_valid (string str); @@ -19,5 +20,9 @@ int str_str (string haystack, string needle); string str_quote (string str); string str_lower (string str); string str_upper (string str); +double strtod (string str, int *end); +float strtof (string str, int *end); +long strtol (string str, int *end); +unsigned long strtoul (string str, int *end); #endif//__ruamoko_string_h diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index 5169296a0..3780b5f03 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -4,6 +4,7 @@ int (string s) strlen = #0; string (string fmt, ...) sprintf = #0; string vsprintf (string fmt, @va_list args) = #0; string (void) str_new = #0; +string str_unmutable (string str) = #0; void (string str) str_free = #0; string str_hold (string str) = #0; int str_valid (string str) = #0; @@ -18,3 +19,7 @@ int str_char (string str, int ind) = #0; string str_quote (string str) = #0; string str_lower (string str) = #0; string str_upper (string str) = #0; +double strtod (string str, int *end) = #0; +float strtof (string str, int *end) = #0; +long strtol (string str, int *end) = #0; +unsigned long strtoul (string str, int *end) = #0; From 4e441d359aba2ed50c9f06bbbca349b2fb615fdb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 27 May 2023 12:39:13 +0900 Subject: [PATCH 3582/3664] [gatest] Write a simple parser for playing with GA Currently only PGA(3) is supported, but that's because the parser is rather simple (recursive descent with a lame lexer), but it works well enough for playing with geometric algebra without having to recompile every time. --- ruamoko/gatest/algebra.r | 2 +- ruamoko/gatest/main.r | 331 ++++++++++++++++++++++++++++++++++- ruamoko/gatest/multivector.h | 8 + ruamoko/gatest/multivector.r | 63 +++++++ 4 files changed, 401 insertions(+), 3 deletions(-) diff --git a/ruamoko/gatest/algebra.r b/ruamoko/gatest/algebra.r index b53e5b0f8..74cfcc68b 100644 --- a/ruamoko/gatest/algebra.r +++ b/ruamoko/gatest/algebra.r @@ -36,7 +36,7 @@ for (int i = 0; i < d + 1; i++) { int c = counts[i]; int ind = indices[i]; - a.grades[i] = [BasisGroup new:c basis:blades + ind - c]; + a.grades[i] = [[BasisGroup new:c basis:blades + ind - c] retain]; } if (p == 3 && m == 0 && z == 1) { diff --git a/ruamoko/gatest/main.r b/ruamoko/gatest/main.r index 2c195cb47..2341e8f03 100644 --- a/ruamoko/gatest/main.r +++ b/ruamoko/gatest/main.r @@ -1,4 +1,9 @@ #include +#include +#include +#include +#include + #include "algebra.h" #include "basisblade.h" #include "basisgroup.h" @@ -20,8 +25,8 @@ arp_end (void) autorelease_pool = nil; } -int -main () +static void +basic_test (void) { arp_start (); @@ -94,5 +99,327 @@ main () printf ("point:%@\n", point); arp_end (); +} + +typedef struct var_s { + string name; + MultiVector *value; +} var_t; + +static hashtab_t *symtab; + +typedef enum { + EOF, SEMI, + VAR, EQUAL, + ID, VALUE, + OPENP, CLOSEP, + OPENB, CLOSEB, + OPENS, CLOSES, + MUL, DIV, PLUS, MINUS, + WEDGE, ANTIWEDGE, DOT, + REVERSE, +} token_e; + +script_t script; +string token_str; +token_e lookahead = -1; + +typedef struct token_s { + token_e id; + union { + MultiVector *value; + string name; + }; +} token_t; + +static token_t +get_token () +{ + if (!Script_TokenAvailable (script, 1)) { + return {EOF, nil}; + } + Script_GetToken (script, 1); + switch (token_str) { + case "var": return {VAR, nil}; + case "=": return {EQUAL, nil}; + case ";": return {SEMI, nil}; + case "(": return {OPENP, nil}; + case ")": return {CLOSEP, nil}; + case "[": return {OPENB, nil}; + case "]": return {CLOSEB, nil}; + case "{": return {OPENS, nil}; + case "}": return {CLOSES, nil}; + case "*": return {MUL, nil}; + case "/": return {DIV, nil}; + case "+": return {PLUS, nil}; + case "-": return {MINUS, nil}; + case "^": return {WEDGE, nil}; + case "&": return {ANTIWEDGE, nil}; + case ".": return {DOT, nil}; + case "~": return {REVERSE, nil}; + } + return {ID, .name = token_str }; +} + +static void +syntax_error () +{ + obj_error (nil, 0, "syntax error: %d\n", Script_GetLine (script)); +} + +static int +match (token_e token) +{ + if (lookahead == -1) { + lookahead = get_token ().id; + } + return token == lookahead; +} + +static void +advance () +{ + lookahead = get_token ().id; +} + +static Algebra *algebra; +static MultiVector *minus_one; +static MultiVector *expression (); + +static int +is_digit (string x) +{ + return (x == "0" || x == "1" || x == "2" || x == "3" || + x == "4" || x == "5" || x == "6" || x == "7" || + x == "8" || x == "9"); +} + +static int +is_number (string x) +{ + return x == "." || is_digit (x); +} + +static MultiVector * +factor () +{ + MultiVector *vec; + if (match (REVERSE)) { + advance (); + vec = [expression () reverse]; + } else if (match (MINUS)) { + advance (); + vec = [minus_one product:expression ()]; + } else if (match (OPENP)) { + advance (); + vec = expression (); + if (!match (CLOSEP)) { + syntax_error (); + } + advance (); + } else if (match (ID)) { + if (is_digit (str_mid (token_str, 0, 1))) { + string num_str = nil; + string blade_str = nil; + int pos = 0; + while (is_number (str_mid (token_str, pos, pos + 1))) { + pos++; + } + num_str = str_mid (token_str, 0, pos); + if (str_mid (token_str, pos, pos + 1) == "e") { + blade_str = str_mid (token_str, ++pos); + } + BasisBlade *blade = [BasisBlade basis:0]; + pos = 0; + while (is_digit (str_mid (blade_str, pos, pos + 1))) { + int x = str_char (blade_str, pos++) - '1'; + BasisBlade *new = [BasisBlade basis:1 << x]; + blade = [blade outerProduct:new]; + } + + double num = strtod (num_str, nil) * [blade scale]; + vec = [algebra ofGrade:[blade grade]]; + *[vec componentFor:blade] = num; + } else { + var_t *var = Hash_Find (symtab, token_str); + if (!var) { + syntax_error (); + } + vec = var.value; + } + advance (); + } else { + syntax_error (); + vec = nil; + } + return vec; +} + +static MultiVector * +high_term () +{ + MultiVector *vec = nil; + SEL op = nil; + while (1) { + if (vec) { + vec = [vec performSelector:op withObject: factor()]; + } else { + vec = factor (); + } + if (match (WEDGE)) { + op = @selector(wedge:); + advance (); + } else if (match (DOT)) { + op = @selector(dot:); + advance (); + } else { + return vec; + } + } +} + +static MultiVector * +term () +{ + MultiVector *vec = nil; + SEL op = nil; + while (1) { + if (vec) { + vec = [vec performSelector:op withObject: high_term()]; + } else { + vec = high_term (); + } + if (match (REVERSE) || match (OPENP) || match (ID)) { + op = @selector(product:); +// } else if (match (DIV)) { +// advance (); + } else { + return vec; + } + } +} + +static MultiVector * +expression () +{ + MultiVector *vec = nil; + SEL op = nil; + while (1) { + if (vec) { + vec = [vec performSelector:op withObject: term()]; + } else { + vec = term (); + } + if (match (PLUS)) { + op = @selector(plus:); + advance (); + } else if (match (MINUS)) { + op = @selector(minus:); + advance (); + } else { + return vec; + } + } +} + +static var_t * +assignment () +{ + if (!match (ID) || is_digit (str_mid (token_str, 0, 1))) { + printf ("%s\n", token_str); + syntax_error (); + } + var_t *var = Hash_Find (symtab, token_str); + if (!var) { + syntax_error (); + } + advance (); + if (!match (EQUAL)) { + syntax_error (); + } + advance (); + var.value = [expression () retain]; + return var; +} + +static var_t * +declaration () +{ + if (!match (ID) || is_digit (str_mid (token_str, 0, 1))) { + syntax_error (); + } + if (Hash_Find (symtab, token_str)) { + syntax_error (); + } + var_t *var = obj_malloc (sizeof (var_t)); + var.name = str_hold (str_unmutable (token_str)); + Hash_Add (symtab, var); + assignment (); + return var; +} + +static int +parse_script (string name, QFile file) +{ + script = Script_New (); + Script_SetSingle (script, "()[]{}/+-^&.~=;"); + token_str = Script_FromFile (script, name, file); + + while (!match (EOF)) { + arp_end (); + arp_start (); + var_t *var; + if (match (VAR)) { + advance (); + var = declaration (); + printf ("var %s = %@\n", var.name, var.value); + } else { + var = assignment (); + printf ("%s = %@\n", var.name, var.value); + } + advance (); + } + + Script_Delete (script); + return 1; +} + +static string +get_symtab_key (void *var, void *unused) +{ + return ((var_t *) var).name; +} + +int +main (int argc, string *argv) +{ + symtab = Hash_NewTable (127, get_symtab_key, nil, nil); + if (argc < 2) { + basic_test (); + } else { + arp_start (); + algebra = [[Algebra PGA:3] retain]; + arp_end (); + arp_start (); + double m1 = -1; + minus_one = [[algebra ofGrade:0 values:&m1] retain]; + arp_end (); + arp_start (); + for (int i = 1; i < argc; i++) { + QFile file = Qopen (argv[i], "rt"); + if (file) { + arp_end (); + arp_start (); + int res = parse_script (argv[i], file); + Qclose (file); + if (!res) { + return 1; + } + } else { + printf ("%s: failed to open '%s'\n", argv[0], argv[i]); + return 1; + } + } + } return 0; } diff --git a/ruamoko/gatest/multivector.h b/ruamoko/gatest/multivector.h index 7b06b0695..dc596d1ce 100644 --- a/ruamoko/gatest/multivector.h +++ b/ruamoko/gatest/multivector.h @@ -4,6 +4,7 @@ @class Algebra; @class BasisLayout; +@class BasisBlase; @interface MultiVector : Object { @@ -19,9 +20,16 @@ // NOTE: values must have the same layout as group +(MultiVector *) new:(Algebra *) algebra group:(BasisGroup *) group values:(double *) values; +(MultiVector *) copy:(MultiVector *) src; + +-(double *) components; +-(int)indexFor:(unsigned)mask; +-(double *) componentFor:(BasisBlade *) blade; + -(MultiVector *) product:(MultiVector *) rhs; -(MultiVector *) wedge:(MultiVector *) rhs; -(MultiVector *) dot:(MultiVector *) rhs; +-(MultiVector *) plus:(MultiVector *) rhs; +-(MultiVector *) minus:(MultiVector *) rhs; -(MultiVector *) dual; -(MultiVector *) reverse; @end diff --git a/ruamoko/gatest/multivector.r b/ruamoko/gatest/multivector.r index 19588085d..4e22022c9 100644 --- a/ruamoko/gatest/multivector.r +++ b/ruamoko/gatest/multivector.r @@ -89,6 +89,21 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) return str; } +-(double *) components +{ + return components; +} + +-(int)indexFor:(unsigned)mask +{ + return [layout bladeIndex:mask]; +} + +-(double *) componentFor:(BasisBlade *) blade +{ + return &components[[layout bladeIndex:[blade mask]]]; +} + -(MultiVector *) product:(MultiVector *) rhs { MultiVector *prod = new_mv (algebra, nil); @@ -179,6 +194,54 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) return prod; } +-(MultiVector *) plus:(MultiVector *) rhs +{ + MultiVector *plus = new_mv (algebra, nil); + for (int i = 0; i < num_components; i++) { + double c = components[i]; + if (!c) { + continue; + } + BasisBlade *b = [layout bladeAt:i]; + int ind = [plus.layout bladeIndex:[b mask]]; + plus.components[ind] += c; + } + for (int i = 0; i < rhs.num_components; i++) { + double c = rhs.components[i]; + if (!c) { + continue; + } + BasisBlade *b = [rhs.layout bladeAt:i]; + int ind = [plus.layout bladeIndex:[b mask]]; + plus.components[ind] += c; + } + return plus; +} + +-(MultiVector *) minus:(MultiVector *) rhs +{ + MultiVector *minus = new_mv (algebra, nil); + for (int i = 0; i < num_components; i++) { + double c = components[i]; + if (!c) { + continue; + } + BasisBlade *b = [layout bladeAt:i]; + int ind = [minus.layout bladeIndex:[b mask]]; + minus.components[ind] += c; + } + for (int i = 0; i < rhs.num_components; i++) { + double c = rhs.components[i]; + if (!c) { + continue; + } + BasisBlade *b = [rhs.layout bladeAt:i]; + int ind = [minus.layout bladeIndex:[b mask]]; + minus.components[ind] -= c; + } + return minus; +} + -(MultiVector *) dual { MultiVector *dual = new_mv (algebra, nil); From 681629a5d15741c1e95e3e00baf50e30ba24fee8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 May 2023 09:52:10 +0900 Subject: [PATCH 3583/3664] [gatest] Parse division and dual operations --- ruamoko/gatest/main.r | 22 ++++++++++++++-------- ruamoko/gatest/multivector.h | 1 + ruamoko/gatest/multivector.r | 13 +++++++++++-- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/ruamoko/gatest/main.r b/ruamoko/gatest/main.r index 2341e8f03..ac101aa12 100644 --- a/ruamoko/gatest/main.r +++ b/ruamoko/gatest/main.r @@ -117,7 +117,7 @@ typedef enum { OPENS, CLOSES, MUL, DIV, PLUS, MINUS, WEDGE, ANTIWEDGE, DOT, - REVERSE, + REVERSE, DUAL, } token_e; script_t script; @@ -157,6 +157,7 @@ get_token () case "&": return {ANTIWEDGE, nil}; case ".": return {DOT, nil}; case "~": return {REVERSE, nil}; + case "!": return {DUAL, nil}; } return {ID, .name = token_str }; } @@ -164,7 +165,8 @@ get_token () static void syntax_error () { - obj_error (nil, 0, "syntax error: %d\n", Script_GetLine (script)); + obj_error (nil, 0, "syntax error before `%s': %d\n", token_str, + Script_GetLine (script)); } static int @@ -206,10 +208,13 @@ factor () MultiVector *vec; if (match (REVERSE)) { advance (); - vec = [expression () reverse]; + vec = [factor () reverse]; + } else if (match (DUAL)) { + advance (); + vec = [factor () dual]; } else if (match (MINUS)) { advance (); - vec = [minus_one product:expression ()]; + vec = [minus_one product:factor ()]; } else if (match (OPENP)) { advance (); vec = expression (); @@ -289,10 +294,11 @@ term () } else { vec = high_term (); } - if (match (REVERSE) || match (OPENP) || match (ID)) { + if (match (REVERSE) || match (DUAL) || match (OPENP) || match (ID)) { op = @selector(product:); -// } else if (match (DIV)) { -// advance (); + } else if (match (DIV)) { + op = @selector(divide:); + advance (); } else { return vec; } @@ -362,7 +368,7 @@ static int parse_script (string name, QFile file) { script = Script_New (); - Script_SetSingle (script, "()[]{}/+-^&.~=;"); + Script_SetSingle (script, "()[]{}/+-^&.~=;!"); token_str = Script_FromFile (script, name, file); while (!match (EOF)) { diff --git a/ruamoko/gatest/multivector.h b/ruamoko/gatest/multivector.h index dc596d1ce..a93fc2c90 100644 --- a/ruamoko/gatest/multivector.h +++ b/ruamoko/gatest/multivector.h @@ -26,6 +26,7 @@ -(double *) componentFor:(BasisBlade *) blade; -(MultiVector *) product:(MultiVector *) rhs; +-(MultiVector *) divide:(MultiVector *) rhs; -(MultiVector *) wedge:(MultiVector *) rhs; -(MultiVector *) dot:(MultiVector *) rhs; -(MultiVector *) plus:(MultiVector *) rhs; diff --git a/ruamoko/gatest/multivector.r b/ruamoko/gatest/multivector.r index 4e22022c9..beb54ea5b 100644 --- a/ruamoko/gatest/multivector.r +++ b/ruamoko/gatest/multivector.r @@ -131,6 +131,17 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) return prod; } +-(MultiVector *) divide:(MultiVector *) rhs +{ + MultiVector *sqr = [rhs product:rhs]; + double smag = sqr.components[[sqr indexFor:0]]; + MultiVector *div = [self product:rhs]; + for (int i = 0; i < div.num_components; i++) { + div.components[i] /= smag; + } + return div; +} + -(MultiVector *) wedge:(MultiVector *) rhs { MultiVector *prod = new_mv (algebra, nil); @@ -246,7 +257,6 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) { MultiVector *dual = new_mv (algebra, nil); unsigned dual_mask = (1 << [algebra dimension]) - 1; - printf ("dual: %x %d\n", dual_mask, [algebra dimension]); for (int i = 0; i < num_components; i++) { if (!components[i]) { continue; @@ -256,7 +266,6 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) unsigned mask = [lb mask] ^ dual_mask; double s = 1; int ind = [layout bladeIndex:mask]; - printf (" : %x %d\n", mask, ind); dual.components[ind] += s * lc; } return dual; From 6bd9aceb2829b9f5337e511df814707b446c139e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 May 2023 15:12:20 +0900 Subject: [PATCH 3584/3664] [ruamoko] Correct signatures of strtol and strtoul I had forgotten the base parameter in the ruamoko definitions (verified there in the C wrapper). --- ruamoko/include/string.h | 4 ++-- ruamoko/lib/string.r | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ruamoko/include/string.h b/ruamoko/include/string.h index e7ba66ba1..fab2daf6b 100644 --- a/ruamoko/include/string.h +++ b/ruamoko/include/string.h @@ -22,7 +22,7 @@ string str_lower (string str); string str_upper (string str); double strtod (string str, int *end); float strtof (string str, int *end); -long strtol (string str, int *end); -unsigned long strtoul (string str, int *end); +long strtol (string str, int *end, int base); +unsigned long strtoul (string str, int *end, int base); #endif//__ruamoko_string_h diff --git a/ruamoko/lib/string.r b/ruamoko/lib/string.r index 3780b5f03..0e0cb6b3b 100644 --- a/ruamoko/lib/string.r +++ b/ruamoko/lib/string.r @@ -21,5 +21,5 @@ string str_lower (string str) = #0; string str_upper (string str) = #0; double strtod (string str, int *end) = #0; float strtof (string str, int *end) = #0; -long strtol (string str, int *end) = #0; -unsigned long strtoul (string str, int *end) = #0; +long strtol (string str, int *end, int base) = #0; +unsigned long strtoul (string str, int *end, int base) = #0; From 65764a06c0e72ad308efe41805a68ad925840510 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 May 2023 15:13:27 +0900 Subject: [PATCH 3585/3664] [gatest] Don't lex . as a single character Lexing . as a single character makes it impossible to enter fractions. Unfortunately, this means that . as dot product requires white space on either side. --- ruamoko/gatest/main.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruamoko/gatest/main.r b/ruamoko/gatest/main.r index ac101aa12..a25457d4f 100644 --- a/ruamoko/gatest/main.r +++ b/ruamoko/gatest/main.r @@ -368,7 +368,7 @@ static int parse_script (string name, QFile file) { script = Script_New (); - Script_SetSingle (script, "()[]{}/+-^&.~=;!"); + Script_SetSingle (script, "()[]{}/+-^&~=;!"); token_str = Script_FromFile (script, name, file); while (!match (EOF)) { From d0e2c0a9d97636a2b5cd5a1944f2cb5b932593f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 29 May 2023 15:14:59 +0900 Subject: [PATCH 3586/3664] [gatest] Allow specifying the algebra on the command line Saves having to recompile for a different algebra. Right now, just `-a p,m,z` is supported. --- ruamoko/gatest/algebra.h | 1 + ruamoko/gatest/algebra.r | 9 +++++++++ ruamoko/gatest/main.r | 41 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/ruamoko/gatest/algebra.h b/ruamoko/gatest/algebra.h index 687a497f6..d6a773454 100644 --- a/ruamoko/gatest/algebra.h +++ b/ruamoko/gatest/algebra.h @@ -15,6 +15,7 @@ BasisLayout *layout; int num_components; int dimension; + int plus, minus, zero; } +(Algebra *) R:(int)p, int m, int z; +(Algebra *) PGA:(int)n; diff --git a/ruamoko/gatest/algebra.r b/ruamoko/gatest/algebra.r index 74cfcc68b..6db1b4ad6 100644 --- a/ruamoko/gatest/algebra.r +++ b/ruamoko/gatest/algebra.r @@ -1,4 +1,5 @@ #include +#include #include "algebra.h" #include "metric.h" @@ -14,6 +15,9 @@ Algebra *a = [[[Algebra alloc] init] autorelease]; a.metric = [[Metric R:p, m, z] retain]; + a.plus = p; + a.minus = m; + a.zero = z; int d = p + m + z; a.dimension = d; a.num_components = 1 << d; @@ -153,4 +157,9 @@ } } +-(string) describe +{ + return sprintf ("R(%d,%d,%d)", plus, minus, zero); +} + @end diff --git a/ruamoko/gatest/main.r b/ruamoko/gatest/main.r index a25457d4f..667b3c66d 100644 --- a/ruamoko/gatest/main.r +++ b/ruamoko/gatest/main.r @@ -396,6 +396,35 @@ get_symtab_key (void *var, void *unused) return ((var_t *) var).name; } +static Algebra * +parse_algebra (string spec) +{ + ivec3 R = {}; + string s = spec; + if (is_digit (str_mid (spec, 0, 1))) { + for (int i = 0; i < 3; i++) { + int end = 0; + R[i] = strtol (s, &end, 0); + string e = str_mid (s, end, end + 1); + if (!e) { + break; + } + if (e != ",") { + goto bad_spec; + } + s = str_mid (s, end + 1); + } + if (!R[0] && !R[1] && !R[2]) { + goto bad_spec; + } + return [Algebra R:R[0], R[1], R[2]]; + } else { + } +bad_spec: + printf ("bad algebra spec: %s\n", spec); + return nil; +} + int main (int argc, string *argv) { @@ -412,10 +441,22 @@ main (int argc, string *argv) arp_end (); arp_start (); for (int i = 1; i < argc; i++) { + if (argv[i] == "-a") { + Algebra *a = [parse_algebra (argv[++i]) retain]; + if (!a) { + return 1; + } + [algebra release]; + algebra = a; + [minus_one release]; + minus_one = [[algebra ofGrade:0 values:&m1] retain]; + continue; + } QFile file = Qopen (argv[i], "rt"); if (file) { arp_end (); arp_start (); + printf ("Using algebra %@\n", algebra); int res = parse_script (argv[i], file); Qclose (file); if (!res) { From 7149a092f668e49012685a3e5e8191da1b2449f2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Jun 2023 01:44:43 +0900 Subject: [PATCH 3587/3664] [qfcc] Create ud-chains more aggressively As certain statements (in particular, function calls) can use additional variables via pointer parameters, it's necessary to iterate ud-chain building until the count stabilizes. This should make live variable analysis much easier. --- tools/qfcc/source/flow.c | 174 ++++++++++++++++++++++++++------------- 1 file changed, 117 insertions(+), 57 deletions(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index ce0e3fe0f..b5320a93e 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -886,6 +886,9 @@ follow_ud_chain (udchain_t ud, function_t *func, set_t *ptr, set_t *visited) static void flow_check_params (statement_t *st, set_t *use, set_t *def, function_t *func) { + if (!func->ud_chains) { + return; + } set_t *use_ptr = set_new (); set_t *def_ptr = set_new (); set_t *ptr = set_new (); @@ -1050,60 +1053,6 @@ flow_reaching_defs (flowgraph_t *graph) } set_delete (oldout); - reach.gen = set_new (); - reach.kill = set_new (); - set_t *use = set_new (); - set_t *tmp = set_new (); - int num_ud = 0; - for (i = 0; i < graph->num_nodes; i++) { - node = graph->nodes[i]; - set_empty (reach.kill); - set_assign (reach.gen, node->reaching_defs.in); - for (st = node->sblock->statements; st; st = st->next) { - flow_analyze_statement (st, use, reach.stdef, 0, 0); - set_empty (tmp); - for (set_iter_t *vi = set_first (use); vi; vi = set_next (vi)) { - flowvar_t *var = reach.vars[vi->element]; - set_assign (tmp, var->define); - set_intersection (tmp, reach.gen); - num_ud += set_count (tmp); - } - flow_statement_reaching (st, &reach); - } - } - graph->func->ud_chains = malloc (num_ud * sizeof (udchain_t)); - graph->func->num_ud_chains = num_ud; - num_ud = 0; - for (i = 0; i < graph->num_nodes; i++) { - node = graph->nodes[i]; - set_empty (reach.kill); - set_assign (reach.gen, node->reaching_defs.in); - for (st = node->sblock->statements; st; st = st->next) { - flow_analyze_statement (st, use, reach.stdef, 0, 0); - set_empty (tmp); - st->first_use = num_ud; - for (set_iter_t *vi = set_first (use); vi; vi = set_next (vi)) { - flowvar_t *var = reach.vars[vi->element]; - set_assign (tmp, var->define); - set_intersection (tmp, reach.gen); - for (set_iter_t *ud = set_first (tmp); ud; ud = set_next (ud)) { - set_add (var->udchains, num_ud); - udchain_t *udc = &graph->func->ud_chains[num_ud++]; - udc->var = vi->element; - udc->usest = st->number; - udc->defst = ud->element; - } - } - st->num_use = num_ud - st->first_use; - flow_statement_reaching (st, &reach); - } - } - set_delete (use); - set_delete (tmp); - set_delete (reach.gen); - set_delete (reach.kill); - reach.gen = reach.kill = 0; - set_delete (reach.stdef); set_delete (reach.stgen); set_delete (reach.stkill); @@ -1129,6 +1078,119 @@ live_set_def (set_t *stdef, set_t *use, set_t *def) set_union (def, stdef); } +static void +flow_build_chains (flowgraph_t *graph) +{ + reachint_t reach = { + .stgen = set_new (), + .stkill = set_new (), + .stdef = set_new (), + .vars = graph->func->vars, + }; + statement_t *st; + + reach.gen = set_new (); + reach.kill = set_new (); + set_t *stuse = set_new (); + set_t *tmp = set_new (); + set_t *st_update = set_new (); + set_t *udchains[graph->func->num_vars]; + int first_use[graph->func->num_statements]; + int num_use[graph->func->num_statements]; + for (int i = 0; i < graph->func->num_vars; i++) { + udchains[i] = set_new (); + } + while (1) { + udchain_t *ud_chains = 0; + int num_ud_chains = 0; + + // count use-def chain elements + for (int i = 0; i < graph->num_nodes; i++) { + flownode_t *node = graph->nodes[i]; + set_empty (reach.kill); + set_assign (reach.gen, node->reaching_defs.in); + for (st = node->sblock->statements; st; st = st->next) { + flow_analyze_statement (st, stuse, reach.stdef, 0, 0); + if (st->type == st_func && statement_is_call (st)) { + // set def later? + flow_check_params (st, stuse, 0, graph->func); + } + set_empty (tmp); + for (set_iter_t *vi = set_first (stuse); vi; + vi = set_next (vi)) { + flowvar_t *var = reach.vars[vi->element]; + set_assign (tmp, var->define); + set_intersection (tmp, reach.gen); + num_ud_chains += set_count (tmp); + } + flow_statement_reaching (st, &reach); + } + } + if (num_ud_chains == graph->func->num_ud_chains) { + break; + } + ud_chains = malloc (num_ud_chains * sizeof (udchain_t)); + num_ud_chains = 0; + for (int i = 0; i < graph->func->num_vars; i++) { + set_empty (udchains[i]); + } + set_empty (st_update); + for (int i = 0; i < graph->num_nodes; i++) { + flownode_t *node = graph->nodes[i]; + set_empty (reach.kill); + set_assign (reach.gen, node->reaching_defs.in); + for (st = node->sblock->statements; st; st = st->next) { + flow_analyze_statement (st, stuse, reach.stdef, 0, 0); + if (st->type == st_func && statement_is_call (st)) { + // set def later? + flow_check_params (st, stuse, 0, graph->func); + } + set_empty (tmp); + first_use[st->number] = num_ud_chains; + num_use[st->number] = 0; + set_add (st_update, st->number); + for (set_iter_t *vi = set_first (stuse); vi; + vi = set_next (vi)) { + flowvar_t *var = reach.vars[vi->element]; + set_assign (tmp, var->define); + set_intersection (tmp, reach.gen); + for (set_iter_t *ud = set_first (tmp); ud; + ud = set_next (ud)) { + set_add (udchains[vi->element], num_ud_chains); + udchain_t *udc = &ud_chains[num_ud_chains++]; + udc->var = vi->element; + udc->usest = st->number; + udc->defst = ud->element; + } + } + num_use[st->number] = num_ud_chains - first_use[st->number]; + flow_statement_reaching (st, &reach); + } + } + for (set_iter_t *si = set_first (st_update); si; si = set_next (si)) { + st = graph->func->statements[si->element]; + st->first_use = first_use[si->element]; + st->num_use = num_use[si->element]; + } + for (int i = 0; i < graph->func->num_vars; i++) { + flowvar_t *var = reach.vars[i]; + set_assign (var->udchains, udchains[i]); + } + free (graph->func->ud_chains); + graph->func->ud_chains = ud_chains; + graph->func->num_ud_chains = num_ud_chains; + } + + for (int i = 0; i < graph->func->num_vars; i++) { + set_delete (udchains[i]); + } + set_delete (stuse); + set_delete (tmp); + set_delete (reach.gen); + set_delete (reach.kill); + set_delete (reach.stdef); +} + static void flow_live_vars (flowgraph_t *graph) { @@ -1151,9 +1213,6 @@ flow_live_vars (flowgraph_t *graph) def = set_new (); for (st = node->sblock->statements; st; st = st->next) { flow_analyze_statement (st, stuse, stdef, 0, 0); - if (st->type == st_func && statement_is_call (st)) { - flow_check_params (st, stuse, stdef, graph->func); - } live_set_use (stuse, use, def); live_set_def (stdef, use, def); } @@ -1968,6 +2027,7 @@ flow_data_flow (function_t *func) if (options.block_dot.statements) dump_dot ("statements", graph, dump_dot_flow_statements); flow_reaching_defs (graph); + flow_build_chains (graph); if (options.block_dot.reaching) dump_dot ("reaching", graph, dump_dot_flow_reaching); flow_live_vars (graph); From e2c1da9b6a4a32885330eb612a54bc839628bff7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Jun 2023 11:24:52 +0900 Subject: [PATCH 3588/3664] [qfcc] Create du-chains from ud-chains I'm not certain this is correct, but it seems to me that du-chains are the same information as ud-chains, but from the defining statement's point of view instead of that of the using statement. --- tools/qfcc/include/flow.h | 3 ++- tools/qfcc/include/function.h | 1 + tools/qfcc/include/statements.h | 2 ++ tools/qfcc/source/dot_flow.c | 23 ++++++++++++++++++--- tools/qfcc/source/flow.c | 36 ++++++++++++++++++++++++++++++--- 5 files changed, 58 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index 6f630c8a9..eb2d4ba20 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -44,7 +44,8 @@ typedef struct flowvar_s { struct flowvar_s *next; ///< for ALLOC struct set_s *use; ///< set of statements that use this var struct set_s *define; ///< set of statements that define this var - struct set_s *udchains; ///< set of ud chains for this var + struct set_s *udchains; ///< set of ud-chains for this var + struct set_s *duchains; ///< set of du-chains for this var struct operand_s *op; ///< an operand using this var int number; ///< number of variable in func's ref list int flowaddr; ///< psuedo address for local and temp vars diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 4777d3668..a6f6d9dca 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -123,6 +123,7 @@ typedef struct function_s { int num_statements; int num_ud_chains; struct udchain_s *ud_chains; + struct udchain_s *du_chains; int pseudo_addr;///< pseudo address space for flow analysis struct pseudoop_s *pseudo_ops;///< pseudo operands used by this function } function_t; diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index d79f4d9d1..fab423f0c 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -119,6 +119,8 @@ typedef struct statement_s { operand_t *kill; ///< list of auxiliary operands killed int first_use; int num_use; + int first_def; + int num_def; } statement_t; typedef struct sblock_s { diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 8440dd0d8..4a37156b4 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -204,11 +204,11 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) dasprintf (dstr, "%*sfv_%p [shape=none,label=<\n", indent, "", graph); dasprintf (dstr, "%*s\n", indent + 2, ""); - dasprintf (dstr, "%*s\n", + dasprintf (dstr, "%*s\n", indent + 4, ""); dasprintf (dstr, "%*s" - "\n", - indent + 4, ""); + "" + "\n", indent + 4, ""); for (i = 0; i < graph->func->num_vars; i++) { var = graph->func->vars[i]; dasprintf (dstr, "%*s", @@ -218,6 +218,7 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) set_as_string (var->define)); dasprintf (dstr, "", set_as_string (var->use)); dasprintf (dstr, "", set_as_string (var->udchains)); + dasprintf (dstr, "", set_as_string (var->duchains)); dasprintf (dstr, "\n"); } dasprintf (dstr, "%*s
flow vars
flow vars
#nameaddrdefineuseud
addrdefineuseuddu
%d%s%d%s%s%s%s
>];\n", indent + 2, ""); @@ -237,6 +238,22 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) indent + 4, "", i, ud.var, ud.usest, ud.defst); } dasprintf (dstr, "%*s>];\n", indent + 2, ""); + + dasprintf (dstr, "%*sdu_%p [shape=none,label=<\n", indent, "", graph); + dasprintf (dstr, "%*s\n", indent + 2, ""); + dasprintf (dstr, "%*s\n", + indent + 4, ""); + dasprintf (dstr, "%*s" + "\n", + indent + 4, ""); + for (i = 0; i < graph->func->num_ud_chains; i++) { + udchain_t du = graph->func->du_chains[i]; + dasprintf (dstr, "%*s" + "", + indent + 4, "", i, du.var, du.defst, du.usest); + } + dasprintf (dstr, "%*s
du chains
#vardefuse
%d%d%d%d
>];\n", indent + 2, ""); } static void diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index b5320a93e..8749e69db 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -40,7 +40,7 @@ #include #include "QF/alloc.h" -#include "QF/dstring.h" +#include "QF/heapsort.h" #include "QF/set.h" #include "QF/va.h" @@ -87,7 +87,7 @@ ALLOC_STATE (flowgraph_t, graphs); ///< flow graph pool /** Allocate a new flow var. * - * The var's use, define and udchain sets are initialized to empty. + * The var's use, define, udchain and duchain sets are initialized to empty. */ static flowvar_t * new_flowvar (void) @@ -97,6 +97,7 @@ new_flowvar (void) var->use = set_new (); var->define = set_new (); var->udchains = set_new (); + var->duchains = set_new (); return var; } @@ -108,6 +109,7 @@ delete_flowvar (flowvar_t *var) set_delete (var->use); set_delete (var->define); set_delete (var->udchains); + set_delete (var->duchains); FREE (vars, var); } @@ -1078,6 +1080,14 @@ live_set_def (set_t *stdef, set_t *use, set_t *def) set_union (def, stdef); } +static int +duchain_cmp (const void *_a, const void *_b) +{ + const udchain_t *a = _a; + const udchain_t *b = _b; + return a->defst - b->defst; +} + static void flow_build_chains (flowgraph_t *graph) { @@ -1100,9 +1110,10 @@ flow_build_chains (flowgraph_t *graph) for (int i = 0; i < graph->func->num_vars; i++) { udchains[i] = set_new (); } + int num_ud_chains; while (1) { udchain_t *ud_chains = 0; - int num_ud_chains = 0; + num_ud_chains = 0; // count use-def chain elements for (int i = 0; i < graph->num_nodes; i++) { @@ -1189,6 +1200,25 @@ flow_build_chains (flowgraph_t *graph) set_delete (reach.gen); set_delete (reach.kill); set_delete (reach.stdef); + + graph->func->du_chains = malloc (num_ud_chains * sizeof (udchain_t)); + memcpy (graph->func->du_chains, graph->func->ud_chains, + num_ud_chains * sizeof (udchain_t)); + heapsort (graph->func->du_chains, num_ud_chains, sizeof (udchain_t), + duchain_cmp); + for (int i = 0; i < num_ud_chains; i++) { + udchain_t du = graph->func->du_chains[i]; + + flowvar_t *var = graph->func->vars[du.var]; + set_add (var->duchains, i); + + if (du.defst < graph->func->num_statements) { + statement_t *st = graph->func->statements[du.defst]; + if (!st->num_def++) { + st->first_def = i; + } + } + } } static void From 8f6e1452572946b973e5140004ad31858c7f1e81 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 4 Jun 2023 11:45:35 +0900 Subject: [PATCH 3589/3664] [qfcc] Don't add target def for store statements Store statements dereference the pointer in target and thus don't modify target itself. --- tools/qfcc/source/statements.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index e5be663d9..1be1042d0 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -971,8 +971,10 @@ dereference_dst: s->opa = dst; s->opb = ofs; s->opc = src; - statement_add_def (s, copy_operand (target)); - statement_add_kill (s, target); + if (type != st_ptrassign) { + statement_add_def (s, copy_operand (target)); + statement_add_kill (s, target); + } sblock_add_statement (sblock, s); return sblock; } From 38fd09573f12af496a862340ab5ea8bde0786aaa Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Jun 2023 09:42:33 +0900 Subject: [PATCH 3590/3664] [qfcc] Avoid defining whole temp via alias Like defs, a partial write should not define the whole temp. Thus, copy the "don't visit main" behavior recently added to def_visit_all. Fixes missing ud-chains for component-by-component assignments to temporary vectors. --- tools/qfcc/source/statements.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 1be1042d0..a1c78f9d7 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -452,8 +452,9 @@ tempop_visit_all (tempop_t *tempop, int overlap, internal_error (top->expr, "temp alias of non-temp operand"); } tempop = &top->tempop; - if ((ret = visit (tempop, data))) + if (!(overlap & 4) && (ret = visit (tempop, data))) return ret; + overlap &= ~4; } else { overlap = 0; } From a5ed154cfe1b9aaee1625a8d2c449851a6318027 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Jun 2023 10:58:02 +0900 Subject: [PATCH 3591/3664] [qfcc] Add a second failing array lifetime test This one covers regular array references across function call. --- tools/qfcc/test/Makemodule.am | 11 +++++++++++ tools/qfcc/test/arraylife2.r | 30 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tools/qfcc/test/arraylife2.r diff --git a/tools/qfcc/test/Makemodule.am b/tools/qfcc/test/Makemodule.am index 078fa5bfa..daaacdcda 100644 --- a/tools/qfcc/test/Makemodule.am +++ b/tools/qfcc/test/Makemodule.am @@ -11,6 +11,7 @@ test_progs_dat=\ tools/qfcc/test/address-cast.dat \ tools/qfcc/test/alignment.dat \ tools/qfcc/test/arraylife.dat \ + tools/qfcc/test/arraylife2.dat \ tools/qfcc/test/assignchain.dat \ tools/qfcc/test/anonstruct.dat \ tools/qfcc/test/chewed-alias.dat \ @@ -168,6 +169,16 @@ tools/qfcc/test/arraylife.run: $(qfcc_test_run_deps) include $(arraylife_dep) # am--include-marker r_depfiles_remade += $(arraylife_dep) +tools_qfcc_test_arraylife2_dat_SOURCES=tools/qfcc/test/arraylife2.r +arraylife2_obj=$(tools_qfcc_test_arraylife2_dat_SOURCES:.r=.o) +arraylife2_dep=$(call qcautodep,$(tools_qfcc_test_arraylife2_dat_SOURCES)) +tools/qfcc/test/arraylife2.dat$(EXEEXT): $(arraylife2_obj) $(QFCC_DEP) + $(V_QFCCLD)$(QLINK) -o $@ $(arraylife2_obj) +tools/qfcc/test/arraylife2.run: $(qfcc_test_run_deps) + @$(top_srcdir)/tools/qfcc/test/build-run $@ +include $(arraylife2_dep) # am--include-marker +r_depfiles_remade += $(arraylife2_dep) + tools_qfcc_test_assignchain_dat_SOURCES=tools/qfcc/test/assignchain.r assignchain_obj=$(tools_qfcc_test_assignchain_dat_SOURCES:.r=.o) assignchain_dep=$(call qcautodep,$(tools_qfcc_test_assignchain_dat_SOURCES)) diff --git a/tools/qfcc/test/arraylife2.r b/tools/qfcc/test/arraylife2.r new file mode 100644 index 000000000..bd783aecd --- /dev/null +++ b/tools/qfcc/test/arraylife2.r @@ -0,0 +1,30 @@ +vector bar (float *v); +vector snafu (float *v); + +vector +foo (float x, float y, float z) +{ + float v[3] = { x, y, z }; + float w[3] = { x, y, z }; + snafu (v); + return bar (w); +} + +vector snafu (float *v) +{ + return nil; +} + +vector +bar (float *v) +{ + return [v[0], v[1], v[2]]; +} + +int +main () +{ + int ret = 0; + ret |= foo(1,2,3) != [1, 2, 3]; + return ret; +} From fb1b3e086903b0474e14d901f7cc82113f192bdd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Jun 2023 11:03:44 +0900 Subject: [PATCH 3592/3664] [qfcc] Use ud- and du-chains for block live analysis The ud- and du-chains include known side-effects of the instructions and thus depict a more accurate view of what operands an instruction uses or defines. Fixes the arraylife2 test. --- tools/qfcc/source/flow.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 8749e69db..e0d33346c 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1237,12 +1237,30 @@ flow_live_vars (flowgraph_t *graph) // first, calculate use and def for each block, and initialize the in and // out sets. + set_t *node_statements = set_new (); for (i = 0; i < graph->num_nodes; i++) { node = graph->nodes[i]; use = set_new (); def = set_new (); + set_empty (node_statements); for (st = node->sblock->statements; st; st = st->next) { - flow_analyze_statement (st, stuse, stdef, 0, 0); + set_add (node_statements, st->number); + } + for (st = node->sblock->statements; st; st = st->next) { + set_empty (stuse); + set_empty (stdef); + for (int i = 0; i < st->num_use; i++) { + udchain_t ud = graph->func->ud_chains[st->first_use + i]; + if (!set_is_member (node_statements, ud.defst)) { + set_add (stuse, ud.var); + } + } + for (int i = 0; i < st->num_def; i++) { + udchain_t du = graph->func->du_chains[st->first_def + i]; + if (!set_is_member (node_statements, du.usest)) { + set_add (stdef, du.var); + } + } live_set_use (stuse, use, def); live_set_def (stdef, use, def); } @@ -1251,6 +1269,7 @@ flow_live_vars (flowgraph_t *graph) node->live_vars.in = set_new (); node->live_vars.out = set_new (); } + set_delete (node_statements); // create in for the exit dummy block using the global vars used by the // function use = set_new (); From fe045f75fb8e1e439ab0542da70eb503170ab7c8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Jun 2023 17:20:12 +0900 Subject: [PATCH 3593/3664] [qfcc] Force live vars used by function statements This uses ud-chains for function statements (call/return) to force their arguments to be live (in particular, indirect references via pointers) this fixes the arraylife test. --- tools/qfcc/source/dags.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 9681587bc..71b564144 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -196,7 +196,7 @@ operand_label (dag_t *dag, operand_t *op) label->op = op; op->label->daglabel = label; } else { - internal_error (op->expr, "unexpected operand type: %d", op->op_type); + internal_error (op->expr, "unexpected operand type: %s", op_type_names[op->op_type]); } return label; } @@ -483,7 +483,18 @@ dagnode_set_edges (dag_t *dag, dagnode_t *n, statement_t *s) } label->live = 1; } - // ensure all operantions on global variables are completed before + for (int i = 0; i < s->num_use; i++) { + udchain_t ud = func->ud_chains[s->first_use + i]; + flowvar_t *var = func->vars[ud.var]; + if (var->op->op_type == op_pseudo) { + continue; + } + daglabel_t *l = operand_label (dag, var->op); + if (l) { + l->live = 1; + } + } + // ensure all operations on global variables are completed before // the st_func statement executes for (set_iter_t *g = set_first (func->global_vars); g; g = set_next (g)) { From 68ca8c701693edc4f94a98ad03746daca5f72357 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 Jun 2023 12:56:23 +0900 Subject: [PATCH 3594/3664] [gatest] Switch to using e0 for the null vector According to enki (bivector community) when there are more than one null vector in a geometry, usually all vectors are null, and it was what to do with multiple null vectors that caused me to balk at using e0 for the null vector. However, using e0 for the null vector makes life much easier, especially as that's what most of the literature does. There are plenty of places, particularly in layout handling, that still need adjustment for the change, but things seem to work (minus duals, but they were broken in the first place, thus the discussion with enki). --- ruamoko/gatest/basisblade.r | 2 +- ruamoko/gatest/main.r | 2 +- ruamoko/gatest/metric.r | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ruamoko/gatest/basisblade.r b/ruamoko/gatest/basisblade.r index 2564d0fe2..a3ad43a54 100644 --- a/ruamoko/gatest/basisblade.r +++ b/ruamoko/gatest/basisblade.r @@ -90,7 +90,7 @@ for (int i = 0; i < 32; i++) { if (mask & (1 << i)) { - basis += sprintf("%x", i + 1); + basis += sprintf("%x", i); } } if (basis) { diff --git a/ruamoko/gatest/main.r b/ruamoko/gatest/main.r index 667b3c66d..5b30ec26d 100644 --- a/ruamoko/gatest/main.r +++ b/ruamoko/gatest/main.r @@ -237,7 +237,7 @@ factor () BasisBlade *blade = [BasisBlade basis:0]; pos = 0; while (is_digit (str_mid (blade_str, pos, pos + 1))) { - int x = str_char (blade_str, pos++) - '1'; + int x = str_char (blade_str, pos++) - '0'; BasisBlade *new = [BasisBlade basis:1 << x]; blade = [blade outerProduct:new]; } diff --git a/ruamoko/gatest/metric.r b/ruamoko/gatest/metric.r index 26e37e28e..ac9fd305f 100644 --- a/ruamoko/gatest/metric.r +++ b/ruamoko/gatest/metric.r @@ -4,9 +4,9 @@ +(Metric *)R:(int)p, int m, int z { Metric *metric = [[[Metric alloc] init] autorelease]; - metric.plus = (1 << p) - 1; - metric.minus = ((1 << m) - 1) << p; - metric.zero = ((1 << z) - 1) << (p + m); + metric.plus = ((1 << p) - 1) << z; + metric.minus = ((1 << m) - 1) << (z + p); + metric.zero = (1 << z) - 1; return metric; } From 2858870153b1a21bdfb4bc29cb97b857728e61d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 Jun 2023 13:00:32 +0900 Subject: [PATCH 3595/3664] [gatest] Fix use of uninitialized multivector components I guess I had forgotten that new_mv() does *NOT* initialize the components. Things just happened to work (usually) because memory was not getting recycled. --- ruamoko/gatest/multivector.r | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ruamoko/gatest/multivector.r b/ruamoko/gatest/multivector.r index beb54ea5b..81a6b29d6 100644 --- a/ruamoko/gatest/multivector.r +++ b/ruamoko/gatest/multivector.r @@ -106,7 +106,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) -(MultiVector *) product:(MultiVector *) rhs { - MultiVector *prod = new_mv (algebra, nil); + MultiVector *prod = [MultiVector new:algebra]; for (int i = 0; i < num_components; i++) { if (!components[i]) { continue; @@ -144,7 +144,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) -(MultiVector *) wedge:(MultiVector *) rhs { - MultiVector *prod = new_mv (algebra, nil); + MultiVector *prod = [MultiVector new:algebra]; for (int i = 0; i < num_components; i++) { if (!components[i]) { continue; @@ -171,7 +171,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) -(MultiVector *) dot:(MultiVector *) rhs { - MultiVector *prod = new_mv (algebra, nil); + MultiVector *prod = [MultiVector new:algebra]; for (int i = 0; i < num_components; i++) { if (!components[i]) { continue; @@ -207,7 +207,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) -(MultiVector *) plus:(MultiVector *) rhs { - MultiVector *plus = new_mv (algebra, nil); + MultiVector *plus = [MultiVector new:algebra]; for (int i = 0; i < num_components; i++) { double c = components[i]; if (!c) { @@ -231,7 +231,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) -(MultiVector *) minus:(MultiVector *) rhs { - MultiVector *minus = new_mv (algebra, nil); + MultiVector *minus = [MultiVector new:algebra]; for (int i = 0; i < num_components; i++) { double c = components[i]; if (!c) { @@ -255,7 +255,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) -(MultiVector *) dual { - MultiVector *dual = new_mv (algebra, nil); + MultiVector *dual = [MultiVector new:algebra]; unsigned dual_mask = (1 << [algebra dimension]) - 1; for (int i = 0; i < num_components; i++) { if (!components[i]) { @@ -273,7 +273,7 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) -(MultiVector *) reverse { - MultiVector *reverse = new_mv (algebra, nil); + MultiVector *reverse = [MultiVector new:algebra]; for (int i = 0; i < num_components; i++) { if (!components[i]) { continue; From a40fee25131eae84b8f0c80db248ad14b70195b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 Jun 2023 13:02:13 +0900 Subject: [PATCH 3596/3664] [gatest] Calculate correct sign for duals I was aware in the beginning that the signs were probably incorrect, but I had left them as I wasn't sure how they worked. Thanks to enki (bivector community), I was pointed in the right direction for getting the calculations right: the product of a basis blade with its dual (x !x) must product the positive pseudo-scalar. --- ruamoko/gatest/multivector.r | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ruamoko/gatest/multivector.r b/ruamoko/gatest/multivector.r index 81a6b29d6..976879ca4 100644 --- a/ruamoko/gatest/multivector.r +++ b/ruamoko/gatest/multivector.r @@ -263,9 +263,11 @@ static MultiVector *new_mv (Algebra *algebra, BasisLayout *layout) } double lc = components[i]; BasisBlade *lb = [layout bladeAt:i]; - unsigned mask = [lb mask] ^ dual_mask; - double s = 1; - int ind = [layout bladeIndex:mask]; + unsigned lb_mask = [lb mask]; + unsigned mask = lb_mask ^ dual_mask; + double ls = [lb scale]; + double s = count_flips (lb_mask, mask) & 1 ? -1 : 1; + int ind = [dual.layout bladeIndex:mask]; dual.components[ind] += s * lc; } return dual; From 0fbcd90e37f014fa93ec393b5433b4a43f2078d5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 Jun 2023 22:13:23 +0900 Subject: [PATCH 3597/3664] [gatest] Fix up layout issues for null vectors e0 is created only if there are null vectors in the algebra, and the 3d and 2d basis groups have been rearranged to compensate in the changed ordering in the basis blade array. --- ruamoko/gatest/algebra.r | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/ruamoko/gatest/algebra.r b/ruamoko/gatest/algebra.r index 6db1b4ad6..d785754e9 100644 --- a/ruamoko/gatest/algebra.r +++ b/ruamoko/gatest/algebra.r @@ -33,6 +33,12 @@ for (int i = 0; i < a.num_components; i++) { int grade = count_bits (i); int ind = indices[grade]++; + unsigned mask = i; + if (!z) { + // e0 is best for the null vector, but this geometry has no null + // vectors, so skip it; + mask <<= 1; + } blades[ind] = [BasisBlade basis:i]; } @@ -47,13 +53,13 @@ // 3d PGA (w squares to 0, x y z square to +1): // : x y z w // : yz zx xy 1 - // : xw yw zw xyzw - // : zyw xzw yxw xyz + // : wx wy wz wxyz + // : wzy wxz wyx xyz BasisBlade *pga_blades[16] = { - blades[1], blades[2], blades[3], blades[4], - blades[7], blades[6], blades[5], blades[0], - blades[8], blades[9], blades[10], blades[15], - blades[14], blades[13], blades[12], blades[11], + blades[2], blades[3], blades[4], blades[1], + blades[10], blades[9], blades[7], blades[0], + blades[5], blades[6], blades[8], blades[15], + blades[13], blades[12], blades[11], blades[14], }; BasisGroup *pga_groups[4] = { [BasisGroup new:4 basis:pga_blades + 0], @@ -65,10 +71,10 @@ } else if (p == 2 && m == 0 && z == 1) { // 2d PGA (w squares to 0, x y square to +1): // : x y w 1 - // : yw wx xy xyw + // : yw wx xy wxy BasisBlade *pga_blades[8] = { - blades[1], blades[2], blades[3], blades[0], - blades[6], blades[5], blades[4], blades[7], + blades[2], blades[3], blades[1], blades[0], + blades[5], blades[4], blades[6], blades[7], }; BasisGroup *pga_groups[2] = { [BasisGroup new:4 basis:pga_blades + 0], From 331f3320e21351e4815f308b03fce589449dcd1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 Jun 2023 22:46:02 +0900 Subject: [PATCH 3598/3664] [gatest] Rearrange the 2d PGA groups Following the suggestions of Hamish Todd, group 0 forms the planar quaternions (with the "complex number" in the first two components) and transflections in group 1. --- ruamoko/gatest/algebra.r | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ruamoko/gatest/algebra.r b/ruamoko/gatest/algebra.r index d785754e9..7f8abcda6 100644 --- a/ruamoko/gatest/algebra.r +++ b/ruamoko/gatest/algebra.r @@ -70,11 +70,11 @@ a.layout = [[BasisLayout new:4 groups: pga_groups] retain]; } else if (p == 2 && m == 0 && z == 1) { // 2d PGA (w squares to 0, x y square to +1): - // : x y w 1 - // : yw wx xy wxy + // : 1 xy wx wy + // : x y w wxy BasisBlade *pga_blades[8] = { - blades[2], blades[3], blades[1], blades[0], - blades[5], blades[4], blades[6], blades[7], + blades[0], blades[6], blades[4], blades[5], + blades[2], blades[3], blades[1], blades[7], }; BasisGroup *pga_groups[2] = { [BasisGroup new:4 basis:pga_blades + 0], From 9871b44d681c97ca02ceed3ae05d3fb1e8355d14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Jun 2023 13:03:38 +0900 Subject: [PATCH 3599/3664] [build] Fix a warning in attribute const check The warning flag check worked too well: it enabled the warning and autoconf's default main wanted the const attribute. The bug has been floating around for a while, it seems. --- include/QF/Vulkan/image.h | 2 +- m4/quakeforge.m4 | 3 ++- tools/qfcc/include/class.h | 4 ++-- tools/qfcc/source/stub.c | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/QF/Vulkan/image.h b/include/QF/Vulkan/image.h index dd94d9e7d..0ae5217e9 100644 --- a/include/QF/Vulkan/image.h +++ b/include/QF/Vulkan/image.h @@ -110,6 +110,6 @@ int QFV_MipLevels (int width, int height) __attribute__((const)); * \note For tex_palette, VK_FORMAT_R8_UINT is returned. If \a format is * not a valid QFFormat, then VK_FORMAT_R8_SRGB is returned. */ -VkFormat QFV_ImageFormat (QFFormat format, int srgb); +VkFormat QFV_ImageFormat (QFFormat format, int srgb) __attribute__((const)); #endif//__QF_Vulkan_image_h diff --git a/m4/quakeforge.m4 b/m4/quakeforge.m4 index ea0d3eae9..c5cbc59e2 100644 --- a/m4/quakeforge.m4 +++ b/m4/quakeforge.m4 @@ -166,7 +166,8 @@ AC_MSG_CHECKING(whether $1 works) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $1" qf_opt_ok=no -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],[qf_opt_ok=yes +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[void func(void);]], [[func();]])], +[qf_opt_ok=yes AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) ]) CFLAGS="$save_CFLAGS" diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index ef223334f..217227a73 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -118,9 +118,9 @@ struct selector_s; int is_id (const struct type_s *type) __attribute__((pure)); int is_class (const struct type_s *type) __attribute__((pure)); -int is_Class (const struct type_s *type) __attribute__((pure)); +int is_Class (const struct type_s *type) __attribute__((const)); int is_classptr (const struct type_s *type) __attribute__((pure)); -int is_SEL (const struct type_s *type) __attribute__((pure)); +int is_SEL (const struct type_s *type) __attribute__((const)); int is_object (const struct type_s *type) __attribute__((const)); int is_method (const struct type_s *type) __attribute__((const)); int is_method_description (const struct type_s *type) __attribute__((const)); diff --git a/tools/qfcc/source/stub.c b/tools/qfcc/source/stub.c index 12b98e1e6..ac57d9b23 100644 --- a/tools/qfcc/source/stub.c +++ b/tools/qfcc/source/stub.c @@ -47,8 +47,8 @@ __attribute__((const)) def_t *qfo_encode_type (type_t *type, defspace_t *space) __attribute__((const)) int obj_types_assignable (const type_t *dst, const type_t *src) {return 0;} void print_protocollist (struct dstring_s *dstr, protocollist_t *protocollist) {} int is_id (const type_t *type){return type->type;} -int is_SEL (const type_t *type){return type->type;} -int is_Class (const type_t *type){return type->type;} +int is_SEL (const type_t *type){return 0;} +int is_Class (const type_t *type){return 0;} int compare_protocols (protocollist_t *protos1, protocollist_t *protos2){return protos1->count - protos2->count;} void dump_dot (const char *stage, void *data, void (*dump_func) (void *data, const char *fname)){} From dbd3d6502a6d3e61c462e9944c59e5cf4749bc1f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Jun 2023 18:06:11 +0900 Subject: [PATCH 3600/3664] Nuke qboolean from orbit I never liked it, but with C2x coming out, it's best to handle bools properly. I haven't gone through all the uses of int as bool (I'll leave that for fixing when I encounter them), but this gets QF working with both c2x (really, gnu2x because of raw strings). --- hw/source/master.c | 2 +- include/QF/GL/extensions.h | 2 +- include/QF/GL/funcs.h | 2 +- include/QF/GL/qf_draw.h | 2 +- include/QF/GL/qf_lightmap.h | 2 +- include/QF/GL/qf_sky.h | 2 +- include/QF/GL/qf_textures.h | 8 +- include/QF/GL/qf_vid.h | 8 +- include/QF/GLSL/funcs.h | 4 +- include/QF/GLSL/qf_draw.h | 2 +- include/QF/GLSL/qf_vid.h | 2 +- include/QF/Vulkan/qf_draw.h | 2 +- include/QF/cbuf.h | 2 +- include/QF/cdaudio.h | 2 +- include/QF/classes/ArrayList.h | 2 +- include/QF/classes/Collection.h | 4 +- include/QF/classes/Iterator.h | 2 +- include/QF/classes/List.h | 4 +- include/QF/cmd.h | 2 +- include/QF/console.h | 2 +- include/QF/cvar.h | 2 +- include/QF/draw.h | 2 +- include/QF/gib.h | 8 +- include/QF/info.h | 2 +- include/QF/input/imt.h | 4 +- include/QF/joystick.h | 4 +- include/QF/llist.h | 6 +- include/QF/mathlib.h | 8 +- include/QF/model.h | 10 +- include/QF/msg.h | 2 +- include/QF/object.h | 6 +- include/QF/pcx.h | 4 +- include/QF/plist.h | 10 +- include/QF/plugin.h | 2 +- include/QF/plugin/cd.h | 2 +- include/QF/plugin/vid_render.h | 8 +- include/QF/progs.h | 12 +-- include/QF/qendian.h | 2 +- include/QF/qtypes.h | 20 ++-- include/QF/quakefs.h | 4 +- include/QF/screen.h | 6 +- include/QF/script.h | 6 +- include/QF/sizebuf.h | 4 +- include/QF/skin.h | 2 +- include/QF/vid.h | 8 +- include/QF/winding.h | 2 +- include/QF/zone.h | 2 +- include/client/locs.h | 2 +- include/client/sbar.h | 2 +- include/client/temp_entities.h | 2 +- include/client/view.h | 4 +- include/context_win.h | 2 +- include/context_x11.h | 10 +- include/d_iface.h | 34 +++---- include/d_local.h | 2 +- include/dga_check.h | 4 +- include/gib_builtin.h | 2 +- include/gib_function.h | 2 +- include/gib_parse.h | 4 +- include/gib_vars.h | 6 +- include/in_win.h | 2 +- include/net_dgrm.h | 8 +- include/net_loop.h | 8 +- include/net_udp.h | 2 +- include/net_vcr.h | 6 +- include/net_wins.h | 2 +- include/netchan.h | 16 +-- include/netmain.h | 32 +++--- include/qw/pmove.h | 8 +- include/r_local.h | 14 +-- include/r_shared.h | 2 +- include/varrays.h | 2 +- include/vid_gl.h | 2 +- include/vid_internal.h | 2 +- include/winquake.h | 4 +- include/world.h | 10 +- libs/audio/cd.c | 2 +- libs/audio/cd_file.c | 10 +- libs/audio/cd_linux.c | 12 +-- libs/audio/cd_sdl.c | 10 +- libs/audio/cd_sgi.c | 8 +- libs/audio/cd_win.c | 16 +-- libs/audio/cd_xmms.c | 10 +- libs/audio/renderer/snd_channels.c | 2 +- libs/audio/targets/snd_alsa.c | 2 +- libs/audio/targets/snd_dx.c | 10 +- libs/audio/targets/snd_win.c | 6 +- libs/client/cl_temp_entities.c | 4 +- libs/client/cl_view.c | 2 +- libs/client/locs.c | 2 +- libs/client/sbar.c | 8 +- libs/console/client.c | 6 +- libs/console/server.c | 4 +- libs/gamecode/pr_edict.c | 2 +- libs/gamecode/pr_parse.c | 2 +- libs/gamecode/pr_strings.c | 6 +- libs/gib/gib_builtin.c | 4 +- libs/gib/gib_classes.c | 4 +- libs/gib/gib_execute.c | 2 +- libs/gib/gib_function.c | 4 +- libs/gib/gib_init.c | 2 +- libs/gib/gib_object.c | 2 +- libs/gib/gib_parse.c | 4 +- libs/gib/gib_thread.c | 2 +- libs/gib/gib_vars.c | 8 +- libs/image/pcx.c | 4 +- libs/input/in_imt.c | 4 +- libs/models/alias/gl_mesh.c | 6 +- libs/models/alias/vulkan_model_alias.c | 2 +- libs/models/gl_skin.c | 6 +- libs/models/iqm/model_iqm.c | 6 +- libs/models/model.c | 6 +- libs/models/test/testclip.c | 8 +- libs/models/test/trace-id.c | 2 +- libs/models/trace.c | 18 ++-- libs/models/winding.c | 2 +- libs/net/nc/net_udp.c | 8 +- libs/net/nc/net_udp6.c | 10 +- libs/net/net_chan.c | 8 +- libs/net/net_main.c | 18 ++-- libs/net/nm/net_dgrm.c | 12 +-- libs/net/nm/net_loop.c | 10 +- libs/net/nm/net_udp.c | 2 +- libs/net/nm/net_vcr.c | 8 +- libs/net/nm/net_wins.c | 4 +- libs/util/bspfile.c | 4 +- libs/util/cmd.c | 2 +- libs/util/cvar.c | 2 +- libs/util/info.c | 2 +- libs/util/llist.c | 2 +- libs/util/plist.c | 18 ++-- libs/util/plugin.c | 2 +- libs/util/qargs.c | 4 +- libs/util/qendian.c | 4 +- libs/util/script.c | 8 +- libs/util/sys.c | 4 +- libs/util/test/test-pqueue.c | 22 ++-- libs/util/zone.c | 8 +- libs/video/renderer/gl/gl_draw.c | 4 +- libs/video/renderer/gl/gl_lightmap.c | 2 +- libs/video/renderer/gl/gl_mod_alias.c | 2 +- libs/video/renderer/gl/gl_rsurf.c | 2 +- libs/video/renderer/gl/gl_sky.c | 2 +- libs/video/renderer/gl/gl_textures.c | 16 +-- libs/video/renderer/gl/qfgl_ext.c | 6 +- libs/video/renderer/gl/vid_common_gl.c | 14 +-- libs/video/renderer/glsl/glsl_bsp.c | 4 +- libs/video/renderer/glsl/glsl_draw.c | 2 +- libs/video/renderer/glsl/qfglsl.c | 2 +- libs/video/renderer/r_main.c | 10 +- libs/video/renderer/r_screen.c | 8 +- libs/video/renderer/sw/d_init.c | 2 +- libs/video/renderer/sw/d_modech.c | 2 +- libs/video/renderer/sw/d_surf.c | 2 +- libs/video/renderer/sw/draw.c | 2 +- libs/video/renderer/sw/sw_ralias.c | 4 +- libs/video/renderer/sw/sw_rbsp.c | 4 +- libs/video/renderer/sw/sw_rdraw.c | 10 +- libs/video/renderer/sw/sw_rmain.c | 12 +-- libs/video/renderer/vid_render_vulkan.c | 2 +- libs/video/renderer/vulkan/vulkan_draw.c | 2 +- libs/video/targets/context_sdl.c | 2 +- libs/video/targets/context_win.c | 26 ++--- libs/video/targets/context_x11.c | 20 ++-- libs/video/targets/dga_check.c | 4 +- libs/video/targets/in_win.c | 18 ++-- libs/video/targets/in_x11.c | 6 +- libs/video/targets/joy.c | 4 +- libs/video/targets/joy_win.c | 4 +- libs/video/targets/vid.c | 2 +- libs/video/targets/vid_3dfxsvga.c | 2 +- libs/video/targets/vid_fbdev.c | 2 +- libs/video/targets/vid_sdl_gl.c | 2 +- libs/video/targets/vid_svgalib.c | 2 +- libs/video/targets/vid_win.c | 2 +- libs/video/targets/vid_win_gl.c | 2 +- libs/video/targets/vid_x11.c | 2 +- libs/video/targets/vid_x11_gl.c | 2 +- libs/video/targets/vid_x11_sw.c | 2 +- nq/include/client.h | 12 +-- nq/include/game.h | 4 +- nq/include/host.h | 4 +- nq/include/server.h | 26 ++--- nq/include/sv_progs.h | 4 +- nq/source/cl_demo.c | 2 +- nq/source/cl_parse.c | 2 +- nq/source/game.c | 2 +- nq/source/host.c | 10 +- nq/source/host_cmd.c | 8 +- nq/source/sv_cl_phys.c | 2 +- nq/source/sv_main.c | 2 +- nq/source/sv_move.c | 10 +- nq/source/sv_phys.c | 6 +- nq/source/sv_pr_cmds.c | 2 +- nq/source/sv_user.c | 4 +- nq/source/sys_sdl.c | 2 +- nq/source/sys_unix.c | 2 +- nq/source/sys_unixd.c | 2 +- nq/source/sys_win.c | 6 +- nq/source/sys_wind.c | 2 +- nq/source/world.c | 2 +- qtv/include/client.h | 2 +- qtv/include/server.h | 2 +- qtv/source/client.c | 6 +- qw/include/cl_cam.h | 4 +- qw/include/cl_chat.h | 2 +- qw/include/cl_ents.h | 4 +- qw/include/cl_main.h | 2 +- qw/include/cl_parse.h | 4 +- qw/include/cl_pred.h | 2 +- qw/include/client.h | 18 ++-- qw/include/server.h | 31 +++--- qw/include/sv_progs.h | 2 +- qw/source/cl_cam.c | 14 +-- qw/source/cl_chat.c | 16 +-- qw/source/cl_entparse.c | 8 +- qw/source/cl_ents.c | 2 +- qw/source/cl_input.c | 2 +- qw/source/cl_main.c | 12 +-- qw/source/cl_parse.c | 6 +- qw/source/cl_pred.c | 2 +- qw/source/cl_sys_win.c | 2 +- qw/source/master.c | 4 +- qw/source/pmovetst.c | 2 +- qw/source/sv_ccmds.c | 8 +- qw/source/sv_demo.c | 6 +- qw/source/sv_ents.c | 6 +- qw/source/sv_main.c | 26 ++--- qw/source/sv_move.c | 10 +- qw/source/sv_phys.c | 6 +- qw/source/sv_qtv.c | 2 +- qw/source/sv_recorder.c | 2 +- qw/source/sv_send.c | 10 +- qw/source/sv_sys_win.c | 2 +- qw/source/sv_user.c | 6 +- qw/source/teamplay.c | 2 +- qw/source/world.c | 2 +- tools/carne/main.c | 2 +- tools/pak/pak.h | 4 +- tools/qfbsp/include/bsp5.h | 10 +- tools/qfbsp/include/map.h | 2 +- tools/qfbsp/include/options.h | 28 ++--- tools/qfbsp/include/outside.h | 2 +- tools/qfbsp/include/solidbsp.h | 2 +- tools/qfbsp/source/csg4.c | 6 +- tools/qfbsp/source/map.c | 2 +- tools/qfbsp/source/merge.c | 4 +- tools/qfbsp/source/outside.c | 12 +-- tools/qfbsp/source/qfbsp.c | 2 +- tools/qfbsp/source/region.c | 2 +- tools/qfbsp/source/solidbsp.c | 6 +- tools/qfbsp/source/tjunc.c | 2 +- tools/qfcc/include/expr.h | 2 +- tools/qfcc/include/options.h | 124 +++++++++++------------ tools/qfcc/source/dot_expr.c | 24 ++--- tools/qfcc/source/expr.c | 78 +++++++------- tools/qfcc/source/expr_bool.c | 32 +++--- tools/qfcc/source/options.c | 26 ++--- tools/qfcc/source/statements.c | 2 +- tools/qflight/include/light.h | 6 +- tools/qflight/source/entities.c | 2 +- tools/qflight/source/ltface.c | 2 +- tools/qflight/source/qflight.c | 2 +- tools/qflight/source/trace.c | 8 +- tools/qflmp/lmp.c | 8 +- tools/qflmp/lmp.h | 2 +- tools/qfmodelgen/source/modelgen.c | 2 +- tools/qfvis/include/options.h | 8 +- tools/qfvis/include/vis.h | 4 +- tools/qfvis/source/fatpvs.c | 2 +- tools/qfvis/source/qfvis.c | 6 +- tools/wad/script.c | 2 +- tools/wad/wad.h | 6 +- 273 files changed, 894 insertions(+), 897 deletions(-) diff --git a/hw/source/master.c b/hw/source/master.c index 15f5bdc10..83e91332c 100644 --- a/hw/source/master.c +++ b/hw/source/master.c @@ -69,7 +69,7 @@ static plugin_list_t server_plugin_list[] = { SERVER_PLUGIN_LIST }; -qboolean is_server = true; +bool is_server = true; static cbuf_t *mst_cbuf; diff --git a/include/QF/GL/extensions.h b/include/QF/GL/extensions.h index 2f667280d..5e76c1e35 100644 --- a/include/QF/GL/extensions.h +++ b/include/QF/GL/extensions.h @@ -326,7 +326,7 @@ typedef void *(GLAPIENTRY *QF_glXGetProcAddressARB) (const GLubyte *procName); typedef const GLubyte *(GLAPIENTRY *QF_wglGetExtensionsStringEXT) (void); /* QuakeForge extension functions */ -qboolean QFGL_ExtensionPresent (const char *); +bool QFGL_ExtensionPresent (const char *); void *QFGL_ExtensionAddress (const char *); #endif // __qfgl_ext_h_ diff --git a/include/QF/GL/funcs.h b/include/QF/GL/funcs.h index 765bb4bab..b02710ef1 100644 --- a/include/QF/GL/funcs.h +++ b/include/QF/GL/funcs.h @@ -42,6 +42,6 @@ #undef QFGL_NEED #undef QFGL_WANT -qboolean GLF_FindFunctions (void); +bool GLF_FindFunctions (void); #endif // __QF_GL_funcs_h_ diff --git a/include/QF/GL/qf_draw.h b/include/QF/GL/qf_draw.h index 9674594ba..a34bf6694 100644 --- a/include/QF/GL/qf_draw.h +++ b/include/QF/GL/qf_draw.h @@ -49,7 +49,7 @@ void gl_Draw_Line (int x0, int y0, int x1, int y1, int c); void gl_Draw_TextBox (int x, int y, int width, int lines, byte alpha); void gl_Draw_FadeScreen (void); void gl_Draw_BlendScreen (quat_t color); -struct qpic_s *gl_Draw_CachePic (const char *path, qboolean alpha); +struct qpic_s *gl_Draw_CachePic (const char *path, bool alpha); void gl_Draw_UncachePic (const char *path); struct qpic_s *gl_Draw_MakePic (int width, int height, const byte *data); void gl_Draw_DestroyPic (struct qpic_s *pic); diff --git a/include/QF/GL/qf_lightmap.h b/include/QF/GL/qf_lightmap.h index e40c50d2c..d5fa22586 100644 --- a/include/QF/GL/qf_lightmap.h +++ b/include/QF/GL/qf_lightmap.h @@ -43,7 +43,7 @@ extern int lm_src_blend, lm_dest_blend; extern model_t *gl_currentmodel; extern GLuint gl_lightmap_textures[MAX_LIGHTMAPS]; -extern qboolean gl_lightmap_modified[MAX_LIGHTMAPS]; +extern bool gl_lightmap_modified[MAX_LIGHTMAPS]; extern instsurf_t *gl_lightmap_polys; extern glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; diff --git a/include/QF/GL/qf_sky.h b/include/QF/GL/qf_sky.h index b7a0fc35a..1aea4ea6f 100644 --- a/include/QF/GL/qf_sky.h +++ b/include/QF/GL/qf_sky.h @@ -34,7 +34,7 @@ #define SKY_TEX 2000 // Quake 2 environment sky -extern qboolean gl_skyloaded; +extern bool gl_skyloaded; extern vec5_t gl_skyvec[6][4]; extern GLuint gl_solidskytexture; extern GLuint gl_alphaskytexture; diff --git a/include/QF/GL/qf_textures.h b/include/QF/GL/qf_textures.h index d5b832850..8ca16ebb5 100644 --- a/include/QF/GL/qf_textures.h +++ b/include/QF/GL/qf_textures.h @@ -38,14 +38,14 @@ extern int gl_solid_format; extern int gl_lightmap_format; extern int gl_filter_min; extern int gl_filter_max; -extern qboolean gl_Anisotropy; +extern bool gl_Anisotropy; extern float gl_aniso; extern GLuint gl_part_tex; struct tex_s; -void GL_Upload8 (const byte *data, int width, int height, qboolean mipmap, qboolean alpha); -void GL_Upload8_EXT (const byte *data, int width, int height, qboolean mipmap, qboolean alpha); -int GL_LoadTexture (const char *identifier, int width, int height, const byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel); +void GL_Upload8 (const byte *data, int width, int height, bool mipmap, bool alpha); +void GL_Upload8_EXT (const byte *data, int width, int height, bool mipmap, bool alpha); +int GL_LoadTexture (const char *identifier, int width, int height, const byte *data, bool mipmap, bool alpha, int bytesperpixel); int GL_LoadTex (const char *identifier, int mips, struct tex_s *tex); int GL_FindTexture (const char *identifier); diff --git a/include/QF/GL/qf_vid.h b/include/QF/GL/qf_vid.h index 6702c2a6e..ea86acc2a 100644 --- a/include/QF/GL/qf_vid.h +++ b/include/QF/GL/qf_vid.h @@ -39,13 +39,13 @@ extern QF_glActiveTexture qglActiveTexture; extern QF_glMultiTexCoord2f qglMultiTexCoord2f; extern QF_glMultiTexCoord2fv qglMultiTexCoord2fv; extern int gl_mtex_active_tmus; -extern qboolean gl_mtex_capable; -extern qboolean gl_mtex_fullbright; +extern bool gl_mtex_capable; +extern bool gl_mtex_fullbright; extern GLenum gl_mtex_enum; -extern qboolean gl_combine_capable; +extern bool gl_combine_capable; extern float gl_rgb_scale; -extern qboolean gl_feature_mach64; +extern bool gl_feature_mach64; extern float gldepthmin, gldepthmax; extern int gl_use_bgra; extern int gl_tess; diff --git a/include/QF/GLSL/funcs.h b/include/QF/GLSL/funcs.h index 19d1403a1..0f8a31092 100644 --- a/include/QF/GLSL/funcs.h +++ b/include/QF/GLSL/funcs.h @@ -43,7 +43,7 @@ #undef QFGL_NEED #undef QFGL_WANT -qboolean EGLF_FindFunctions (void); -void *QFEGL_ProcAddress (void *handle, const char *name, qboolean); +bool EGLF_FindFunctions (void); +void *QFEGL_ProcAddress (void *handle, const char *name, bool); #endif // __QF_GLSL_funcs_h_ diff --git a/include/QF/GLSL/qf_draw.h b/include/QF/GLSL/qf_draw.h index 3a8ea0276..1868dbccc 100644 --- a/include/QF/GLSL/qf_draw.h +++ b/include/QF/GLSL/qf_draw.h @@ -50,7 +50,7 @@ void glsl_LineGraph (int x, int y, int *h_vals, int count, int height); void glsl_Draw_TextBox (int x, int y, int width, int lines, byte alpha); void glsl_Draw_FadeScreen (void); void glsl_Draw_BlendScreen (quat_t color); -struct qpic_s *glsl_Draw_CachePic (const char *path, qboolean alpha); +struct qpic_s *glsl_Draw_CachePic (const char *path, bool alpha); void glsl_Draw_UncachePic (const char *path); struct qpic_s *glsl_Draw_MakePic (int width, int height, const byte *data); void glsl_Draw_DestroyPic (struct qpic_s *pic); diff --git a/include/QF/GLSL/qf_vid.h b/include/QF/GLSL/qf_vid.h index d88dc234d..b3578eb34 100644 --- a/include/QF/GLSL/qf_vid.h +++ b/include/QF/GLSL/qf_vid.h @@ -38,7 +38,7 @@ typedef struct shader_s { typedef struct shaderparam_s { const char *name; - qboolean uniform; + bool uniform; int location; } shaderparam_t; diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 8b65e114c..e2b93c6ad 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -66,7 +66,7 @@ void Vulkan_Draw_TextBox (int x, int y, int width, int lines, byte alpha, struct vulkan_ctx_s *ctx); void Vulkan_Draw_FadeScreen (struct vulkan_ctx_s *ctx); void Vulkan_Draw_BlendScreen (quat_t color, struct vulkan_ctx_s *ctx); -struct qpic_s *Vulkan_Draw_CachePic (const char *path, qboolean alpha, +struct qpic_s *Vulkan_Draw_CachePic (const char *path, bool alpha, struct vulkan_ctx_s *ctx); void Vulkan_Draw_UncachePic (const char *path, struct vulkan_ctx_s *ctx); struct qpic_s *Vulkan_Draw_MakePic (int width, int height, const byte *data, diff --git a/include/QF/cbuf.h b/include/QF/cbuf.h index 5566ee7aa..c6d6b01f9 100644 --- a/include/QF/cbuf.h +++ b/include/QF/cbuf.h @@ -65,7 +65,7 @@ typedef struct cbuf_s { } state; int (*unknown_command)(void); // handle unkown commands. !0 = handled - qboolean strict; // Should we tolerate unknown commands? + bool strict; // Should we tolerate unknown commands? double resumetime; // Time when stack can be executed again void *data; // Pointer to interpreter data diff --git a/include/QF/cdaudio.h b/include/QF/cdaudio.h index e265231db..0a326f8b3 100644 --- a/include/QF/cdaudio.h +++ b/include/QF/cdaudio.h @@ -31,7 +31,7 @@ #include "QF/qtypes.h" int CDAudio_Init(void); -void CDAudio_Play(int track, qboolean looping); +void CDAudio_Play(int track, bool looping); void CDAudio_Stop(void); void CDAudio_Pause(void); void CDAudio_Resume(void); diff --git a/include/QF/classes/ArrayList.h b/include/QF/classes/ArrayList.h index 78b4c8f1b..83eb0929f 100644 --- a/include/QF/classes/ArrayList.h +++ b/include/QF/classes/ArrayList.h @@ -44,7 +44,7 @@ classDecl (ArrayListIterator, Iterator, ArrayList *list; unsigned int pos; unsigned int smods; - qboolean alive; + bool alive; ObjRefs_t allrefs; ); #define ARRAYLISTITERATOR(o) ((ArrayListIterator *)(o)) diff --git a/include/QF/classes/Collection.h b/include/QF/classes/Collection.h index b867f9faa..88b2075c8 100644 --- a/include/QF/classes/Collection.h +++ b/include/QF/classes/Collection.h @@ -38,9 +38,9 @@ classDecl (Collection, Object, unsigned int count; Class *type; - qboolean methodDecl (Collection, add, Object *o); + bool methodDecl (Collection, add, Object *o); Object * methodDecl (Collection, remove, Object *o); - qboolean methodDecl (Collection, contains, Object *o); + bool methodDecl (Collection, contains, Object *o); Iterator * methodDecl (Collection, iterator); ); #define COLLECTION(o) ((Collection *)(o)) diff --git a/include/QF/classes/Iterator.h b/include/QF/classes/Iterator.h index bb5169a0d..c393de349 100644 --- a/include/QF/classes/Iterator.h +++ b/include/QF/classes/Iterator.h @@ -35,7 +35,7 @@ classDecl (Iterator, Object, Object * methodDecl (Iterator, next); - qboolean methodDecl (Iterator, hasNext); + bool methodDecl (Iterator, hasNext); ); #define ITERATOR(o) ((Iterator *)(o)) diff --git a/include/QF/classes/List.h b/include/QF/classes/List.h index 1cb2cb8e3..931944942 100644 --- a/include/QF/classes/List.h +++ b/include/QF/classes/List.h @@ -35,9 +35,9 @@ classDecl (List, Collection, unsigned int smods; - qboolean methodDecl (List, set, unsigned int index, Object *o); + bool methodDecl (List, set, unsigned int index, Object *o); Object * methodDecl (List, get, unsigned int index); - qboolean methodDecl (List, insertAt, unsigned int index, Object *o); + bool methodDecl (List, insertAt, unsigned int index, Object *o); Object * methodDecl (List, removeAt, unsigned int index); ); #define LIST(o) ((List *)(o)) diff --git a/include/QF/cmd.h b/include/QF/cmd.h index f9ae0c7b6..98199756c 100644 --- a/include/QF/cmd.h +++ b/include/QF/cmd.h @@ -65,7 +65,7 @@ int Cmd_AddDataCommand (const char *cmd_name, xdatacmd_t function, void *data, const char *description); int Cmd_RemoveCommand (const char *cmd_name); -qboolean Cmd_Exists (const char *cmd_name); +bool Cmd_Exists (const char *cmd_name); const char *Cmd_CompleteCommand (const char *partial) __attribute__((pure)); int Cmd_CompleteCountPossible (const char *partial) __attribute__((pure)); const char **Cmd_CompleteBuildList (const char *partial); diff --git a/include/QF/console.h b/include/QF/console.h index 161200fdf..f2be4a4c6 100644 --- a/include/QF/console.h +++ b/include/QF/console.h @@ -62,7 +62,7 @@ extern struct plugin_s *con_module; extern struct console_data_s con_data; //extern int con_totallines; -//extern qboolean con_initialized; +//extern bool con_initialized; //extern byte *con_chars; void Con_DrawConsole (void); diff --git a/include/QF/cvar.h b/include/QF/cvar.h index 850c87623..c023477bb 100644 --- a/include/QF/cvar.h +++ b/include/QF/cvar.h @@ -110,7 +110,7 @@ const char *Cvar_VarString (const cvar_t *var); // called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known // command. Returns true if the command was a variable reference that // was handled. (print or change) -qboolean Cvar_Command (void); +bool Cvar_Command (void); // Writes lines containing "set variable value" for all variables // with the archive flag set to true. diff --git a/include/QF/draw.h b/include/QF/draw.h index 82d0eee8a..9943967a5 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -206,7 +206,7 @@ void Draw_BlendScreen (quat_t color); \return pointer qpic data. \note Up to MAX_CACHED_PICS qpics can be loaded at a time this way */ -qpic_t *Draw_CachePic (const char *path, qboolean alpha); +qpic_t *Draw_CachePic (const char *path, bool alpha); /** Remove a qpic from the qpic cache. diff --git a/include/QF/gib.h b/include/QF/gib.h index 9b08bd760..da0247dfc 100644 --- a/include/QF/gib.h +++ b/include/QF/gib.h @@ -108,7 +108,7 @@ typedef struct gib_classdesc_s { (obj), (mesg))) void GIB_Class_Create (gib_classdesc_t *desc); -gib_object_t *GIB_Object_Create (const char *classname, qboolean classobj); +gib_object_t *GIB_Object_Create (const char *classname, bool classobj); void GIB_Object_Destroy (gib_object_t *obj); void GIB_Object_Incref (gib_object_t *obj); void GIB_Object_Decref (gib_object_t *obj); @@ -142,7 +142,7 @@ typedef struct gib_buffer_data_s { struct gib_script_s *script; struct gib_tree_s *program, *ip; struct dstring_s *arg_composite; - qboolean waitret; + bool waitret; struct gib_sstack_s { struct gib_dsarray_s { struct dstring_s **dstrs; @@ -179,7 +179,7 @@ struct dstring_s *GIB_Return (const char *str); void GIB_Error (const char *type, const char *fmt, ...) __attribute__((format(PRINTF, 2, 3))); void GIB_Builtin_Add (const char *name, void (*func) (void)); void GIB_Builtin_Remove (const char *name); -qboolean GIB_Builtin_Exists (const char *name); +bool GIB_Builtin_Exists (const char *name); // Event interface @@ -202,7 +202,7 @@ unsigned int GIB_Thread_Count (void) __attribute__((pure)); // Init interface -void GIB_Init (qboolean sandbox); +void GIB_Init (bool sandbox); // Handle interface diff --git a/include/QF/info.h b/include/QF/info.h index 7bf16b0ab..9b460917b 100644 --- a/include/QF/info.h +++ b/include/QF/info.h @@ -47,7 +47,7 @@ typedef struct info_key_s { const char *value; } info_key_t; -qboolean Info_FilterForKey (const char *key, const char **filter_list) __attribute__((pure)); +bool Info_FilterForKey (const char *key, const char **filter_list) __attribute__((pure)); void Info_Print (info_t *info); int Info_CurrentSize (info_t *info) __attribute__((pure)); diff --git a/include/QF/input/imt.h b/include/QF/input/imt.h index 5009a57da..642d24f4a 100644 --- a/include/QF/input/imt.h +++ b/include/QF/input/imt.h @@ -127,8 +127,8 @@ int IMT_CreateSwitcher (const char *switcher_name, void IMT_BindAxis (imt_t *imt, int axis_num, in_axis_t *axis, const in_recipe_t *recipe); void IMT_BindButton (imt_t *imt, int button, const char *binding); -qboolean IMT_ProcessAxis (int axis, int value); -qboolean IMT_ProcessButton (int button, int state); +bool IMT_ProcessAxis (int axis, int value); +bool IMT_ProcessButton (int button, int state); void IMT_Init (void); void IMT_Shutdown (void); struct plitem_s; diff --git a/include/QF/joystick.h b/include/QF/joystick.h index 2e23d39f7..8ec845e20 100644 --- a/include/QF/joystick.h +++ b/include/QF/joystick.h @@ -72,8 +72,8 @@ struct joy_axis { struct joy_axis_button *axis_buttons; // if axis button }; -extern qboolean joy_found; // Joystick present? -extern qboolean joy_active; // Joystick in use? +extern bool joy_found; // Joystick present? +extern bool joy_active; // Joystick in use? struct joy_button { int old; diff --git a/include/QF/llist.h b/include/QF/llist.h index e555c6bd6..922dc349b 100644 --- a/include/QF/llist.h +++ b/include/QF/llist.h @@ -50,12 +50,12 @@ typedef struct llist_s { /// \param element The item being deleted. /// \param userdata Pointer to user data supplied to llist_new(). void (*freedata)(void *element, void *userdata); - qboolean (*cmpdata)(const void *element, const void *comparison, + bool (*cmpdata)(const void *element, const void *comparison, void *userdata); void *userdata; } llist_t; -typedef qboolean (*llist_iterator_t)(void *element, llist_node_t *node); +typedef bool (*llist_iterator_t)(void *element, llist_node_t *node); #define LLIST_ICAST(x) (llist_iterator_t)(x) #define LLIST_DATA(node, type) ((type *)((node)->data)) @@ -73,7 +73,7 @@ typedef qboolean (*llist_iterator_t)(void *element, llist_node_t *node); passed to the other functions accessing the list. */ llist_t *llist_new (void (*freedata)(void *element, void *userdata), - qboolean (*cmpdata)(const void *element, + bool (*cmpdata)(const void *element, const void *comparison, void *userdata), void *userdata); diff --git a/include/QF/mathlib.h b/include/QF/mathlib.h index 645220b40..be3244c6a 100644 --- a/include/QF/mathlib.h +++ b/include/QF/mathlib.h @@ -173,15 +173,15 @@ void RotatePointAroundVector (vec3_t dst, const vec3_t axis, VectorNegate ((sp)->normal, (dp)->normal); \ } while (0) -GNU89INLINE inline qboolean R_CullBox (const plane_t *frustum, const vec3_t mins, const vec3_t maxs) __attribute__((pure)); -GNU89INLINE inline qboolean R_CullSphere (const plane_t *frustum, const vec3_t origin, const float radius); +GNU89INLINE inline bool R_CullBox (const plane_t *frustum, const vec3_t mins, const vec3_t maxs) __attribute__((pure)); +GNU89INLINE inline bool R_CullSphere (const plane_t *frustum, const vec3_t origin, const float radius); #ifndef IMPLEMENT_R_Cull GNU89INLINE inline #else VISIBLE #endif -qboolean +bool R_CullBox (const plane_t *frustum, const vec3_t mins, const vec3_t maxs) { int i; @@ -200,7 +200,7 @@ GNU89INLINE inline #else VISIBLE #endif -qboolean +bool R_CullSphere (const plane_t *frustum, const vec3_t origin, const float radius) { int i; diff --git a/include/QF/model.h b/include/QF/model.h index f36d23346..e8ad0cf47 100644 --- a/include/QF/model.h +++ b/include/QF/model.h @@ -161,7 +161,7 @@ typedef struct msurface_s { byte styles[MAXLIGHTMAPS]; int cached_light[MAXLIGHTMAPS]; // values currently used in lightmap - qboolean cached_dlight; // true if dynamic light in cache + bool cached_dlight; // true if dynamic light in cache int model_index; ///< < 0: instance, 0 main, > 0: sub } msurface_t; @@ -387,9 +387,9 @@ typedef struct model_s { char path[MAX_QPATH]; char name[MAX_QPATH]; const struct vpath_s *vpath;// virtual path where this model was found - qboolean needload; // bmodels and sprites don't cache normally + bool needload; // bmodels and sprites don't cache normally aliashdr_t *aliashdr; // if not null, alias model is not cached - qboolean hasfullbrights; + bool hasfullbrights; modtype_t type; int numframes; @@ -408,7 +408,7 @@ typedef struct model_s { vec3_t mins, maxs; // solid volume for clipping - qboolean clipbox; + bool clipbox; vec3_t clipmins, clipmaxs; // brush model @@ -428,7 +428,7 @@ typedef struct model_s { void Mod_Init (void); void Mod_Init_Cvars (void); void Mod_ClearAll (void); -model_t *Mod_ForName (const char *name, qboolean crash); +model_t *Mod_ForName (const char *name, bool crash); void Mod_TouchModel (const char *name); void Mod_UnloadModel (model_t *model); // brush specific diff --git a/include/QF/msg.h b/include/QF/msg.h index 3fb7a84a3..44b9122fb 100644 --- a/include/QF/msg.h +++ b/include/QF/msg.h @@ -59,7 +59,7 @@ void MSG_PokeLongBE (sizebuf_t *sb, unsigned offset, int c); typedef struct msg_s { unsigned readcount; - qboolean badread; // set if a read goes beyond end of message + bool badread; // set if a read goes beyond end of message sizebuf_t *message; size_t badread_string_size; char *badread_string; diff --git a/include/QF/object.h b/include/QF/object.h index f5c4f97f8..a722c42ee 100644 --- a/include/QF/object.h +++ b/include/QF/object.h @@ -81,7 +81,7 @@ typedef struct Object_s { struct Object_s *next; struct String_s * methodDecl(Object, toString); ObjRefs_t * methodDecl(Object, allRefs); - qboolean methodDecl(Object, finalize); + bool methodDecl(Object, finalize); void *data; } Object; @@ -103,11 +103,11 @@ classDecl (Class, Object, ); #define CLASS(o) ((Class *)(o)) -Object *Object_Create (Class *cl, qboolean perm); +Object *Object_Create (Class *cl, bool perm); void Object_Delete (Object *obj); Object *Object_Retain (Object *obj); Object *Object_Release (Object *obj); -qboolean Object_InstanceOf (Object *obj, Class *cl); +bool Object_InstanceOf (Object *obj, Class *cl); void Object_AddToRoot (Object *obj); void Object_RemoveFromRoot (Object *obj); void Object_Init (void); diff --git a/include/QF/pcx.h b/include/QF/pcx.h index b140dde8f..f4ce939d1 100644 --- a/include/QF/pcx.h +++ b/include/QF/pcx.h @@ -63,7 +63,7 @@ typedef struct \warning Uses Hunk_TempAlloc() to allocate the output PCX content. */ pcx_t *EncodePCX (const byte *data, int width, int height, int rowbytes, - const byte *palette, qboolean flip, int *length); + const byte *palette, bool flip, int *length); /** Load a texture from a PCX file. @@ -76,6 +76,6 @@ pcx_t *EncodePCX (const byte *data, int width, int height, int rowbytes, \return A pointer to the texture. \warning Uses Hunk_TempAlloc() to allocate the texture. */ -struct tex_s *LoadPCX (QFile *f, qboolean convert, const byte *pal, int load); +struct tex_s *LoadPCX (QFile *f, bool convert, const byte *pal, int load); #endif//__QF_pcx_h diff --git a/include/QF/plist.h b/include/QF/plist.h index 942bdf8a3..43f6a6f7e 100644 --- a/include/QF/plist.h +++ b/include/QF/plist.h @@ -292,7 +292,7 @@ int PL_D_NumKeys (const plitem_t *dict) __attribute__((pure)); \note the dictionary becomes the owner of the value. */ -qboolean PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value); +bool PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value); /** Copy contents of one dictionary into another. @@ -306,7 +306,7 @@ qboolean PL_D_AddObject (plitem_t *dict, const char *key, plitem_t *value); \return true if values were copied, false if nothing was copied (either dictionary is null, or not a dictionary, or if \a srcDict was empty) */ -qboolean PL_D_Extend (plitem_t *dstDict, plitem_t *srcDict); +bool PL_D_Extend (plitem_t *dstDict, plitem_t *srcDict); /** Add an item to an array. @@ -318,7 +318,7 @@ qboolean PL_D_Extend (plitem_t *dstDict, plitem_t *srcDict); \note the array becomes the owner of the added item. */ -qboolean PL_A_AddObject (plitem_t *array, plitem_t *item); +bool PL_A_AddObject (plitem_t *array, plitem_t *item); /** Append contents of one array to another. @@ -330,7 +330,7 @@ qboolean PL_A_AddObject (plitem_t *array, plitem_t *item); \return true if values were copied, false if nothing was copied (either array is null, or not an array, or if \a srcArray was empty) */ -qboolean PL_A_Extend (plitem_t *dstArray, plitem_t *srcArray); +bool PL_A_Extend (plitem_t *dstArray, plitem_t *srcArray); /** Retrieve the number of items in an array. @@ -352,7 +352,7 @@ int PL_A_NumObjects (const plitem_t *array) __attribute__((pure)); \note the array becomes the owner of the added item. */ -qboolean PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index); +bool PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index); /** Remove a value from an array object. The array items will be shifted to fill the resulting hole. diff --git a/include/QF/plugin.h b/include/QF/plugin.h index e5fee9fa9..7eb0e8d4d 100644 --- a/include/QF/plugin.h +++ b/include/QF/plugin.h @@ -104,7 +104,7 @@ extern char *fs_pluginpath; Function prototypes */ plugin_t *PI_LoadPlugin (const char *, const char *); -qboolean PI_UnloadPlugin (plugin_t *); +bool PI_UnloadPlugin (plugin_t *); void PI_RegisterPlugins (plugin_list_t *); void PI_Init (void); diff --git a/include/QF/plugin/cd.h b/include/QF/plugin/cd.h index 2eb0aa417..8976b3ecf 100644 --- a/include/QF/plugin/cd.h +++ b/include/QF/plugin/cd.h @@ -34,7 +34,7 @@ typedef struct cd_funcs_s { void (*init) (void); void (*cd_f) (void); // void (*pause) (void); - void (*play) (int, qboolean); + void (*play) (int, bool); void (*resume) (void); void (*update) (void); } cd_funcs_t; diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index b581692cb..c53bcfd86 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -104,7 +104,7 @@ typedef struct vid_render_funcs_s { void (*Draw_TextBox) (int x, int y, int width, int lines, byte alpha); void (*Draw_FadeScreen) (void); void (*Draw_BlendScreen) (quat_t color); - qpic_t *(*Draw_CachePic) (const char *path, qboolean alpha); + qpic_t *(*Draw_CachePic) (const char *path, bool alpha); void (*Draw_UncachePic) (const char *path); qpic_t *(*Draw_MakePic) (int width, int height, const byte *data); void (*Draw_DestroyPic) (qpic_t *pic); @@ -155,9 +155,9 @@ typedef struct vid_render_data_s { int *scr_viewsize; int *graphheight; float min_wateralpha; - qboolean force_fullscreen; - qboolean inhibit_viewmodel; - qboolean paused; + bool force_fullscreen; + bool inhibit_viewmodel; + bool paused; int lineadj; entity_t view_model; //FIXME still?!? double frametime; diff --git a/include/QF/progs.h b/include/QF/progs.h index fddb57027..800e03816 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -321,7 +321,7 @@ void PR_BoundsCheck (progs_t *pr, int addr, etype_t type); ///@{ struct edict_s { - qboolean free; + bool free; progs_t *pr; ///< progs owning this edict pr_uint_t entnum; ///< number of this entity pr_uint_t edict; ///< offset of this entity in pr_edict_area @@ -336,7 +336,7 @@ void ED_Free (progs_t *pr, edict_t *ed); edict_t *ED_EdictNum(progs_t *pr, pr_uint_t n) __attribute__((pure)); pr_uint_t ED_NumForEdict(progs_t *pr, edict_t *e) __attribute__((pure)); void ED_Count (progs_t *pr); -qboolean PR_EdictValid (progs_t *pr, pr_uint_t e) __attribute__((pure)); +bool PR_EdictValid (progs_t *pr, pr_uint_t e) __attribute__((pure)); // pr_debug.c void ED_Print (progs_t *pr, edict_t *ed, const char *fieldname); @@ -347,7 +347,7 @@ void ED_PrintNum (progs_t *pr, pr_int_t ent, const char *fieldname); struct script_s; struct plitem_s; struct hashctx_s; -qboolean ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, +bool ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s); struct plitem_s *ED_EntityDict (progs_t *pr, edict_t *ed); struct plitem_s *ED_GlobalsDict (progs_t *pr); @@ -1493,14 +1493,14 @@ int PR_LoadStrings (progs_t *pr); \param num string index to be validated \return true if the index is valid, false otherwise */ -qboolean PR_StringValid (progs_t *pr, pr_string_t num) __attribute__((pure)); +bool PR_StringValid (progs_t *pr, pr_string_t num) __attribute__((pure)); /** Check if a string is valid and mutable. \param pr pointer to ::progs_t VM struct \param num string index to be checked \return true if the string is valid and mutable, false otherwise */ -qboolean PR_StringMutable (progs_t *pr, pr_string_t num) __attribute__((pure)); +bool PR_StringMutable (progs_t *pr, pr_string_t num) __attribute__((pure)); /** Convert a string index to a C string. \param pr pointer to ::progs_t VM struct @@ -2170,7 +2170,7 @@ struct progs_s { ///@{ int pr_argc; //FIXME need a good way to ensure it is correct - qboolean pr_trace; + bool pr_trace; int pr_trace_depth; bfunction_t *pr_xfunction; int pr_xstatement; diff --git a/include/QF/qendian.h b/include/QF/qendian.h index 7c418be53..147ec4c75 100644 --- a/include/QF/qendian.h +++ b/include/QF/qendian.h @@ -73,7 +73,7 @@ #define LittleFloat FloatSwap #endif -extern qboolean bigendien; +extern bool bigendien; uint16_t _ShortSwap (uint16_t l) __attribute__((const)); uint16_t _ShortNoSwap (uint16_t l) __attribute__((const)); diff --git a/include/QF/qtypes.h b/include/QF/qtypes.h index 2c37c286b..b37874305 100644 --- a/include/QF/qtypes.h +++ b/include/QF/qtypes.h @@ -52,21 +52,19 @@ typedef uint8_t byte; #endif +#if __STDC_VERSION__ < 202000 #ifndef _DEF_BOOL_ # define _DEF_BOOL_ // KJB Undefined true and false defined in SciTech's DEBUG.H header -#ifdef __cplusplus -# define __bool_true_false_are_defined -#endif -# ifdef __bool_true_false_are_defined -typedef enum {q_false = false, q_true = true} qboolean; -//#define true q_true; -//#define false q_false; -# else -#undef true -#undef false -typedef enum {false, true} qboolean; +# ifdef __cplusplus +# define __bool_true_false_are_defined # endif +# ifndef __bool_true_false_are_defined +# undef true +# undef false +typedef enum {false, true} bool; +# endif +#endif #endif // From mathlib... diff --git a/include/QF/quakefs.h b/include/QF/quakefs.h index fdd73b6b4..91f7cb440 100644 --- a/include/QF/quakefs.h +++ b/include/QF/quakefs.h @@ -71,11 +71,11 @@ typedef struct vpath_s vpath_t; typedef struct findfile_s { const vpath_t *vpath; ///< vpath in which file was found - qboolean in_pak; ///< if true, path refers to a pak file rather - ///< than a directory const char *realname; ///< the name of the file as found (may have ///< .gz appended, or .ogg substituded for ///< .wav) does not include the path + bool in_pak; ///< if true, path refers to a pak file rather + ///< than a directory } findfile_t; /** Cached information about the current game directory. \see \ref dirconf. diff --git a/include/QF/screen.h b/include/QF/screen.h index 255d371ae..7608c3571 100644 --- a/include/QF/screen.h +++ b/include/QF/screen.h @@ -44,15 +44,15 @@ void SCR_UpdateScreen_legacy (struct transform_s camera, double realtime, SCR_Func *scr_funcs); void SCR_SetFOV (float fov); // control whether the 3d viewport is user-controlled or always fullscreen -void SCR_SetFullscreen (qboolean fullscreen); +void SCR_SetFullscreen (bool fullscreen); void SCR_SetBottomMargin (int lines); void SCR_NewScene (struct scene_s *scene); extern int r_timegraph; extern int r_zgraph; -extern int scr_copytop; -extern qboolean scr_skipupdate; +extern int scr_copytop; +extern bool scr_skipupdate; struct view_pos_s; void R_TimeGraph (struct view_pos_s abs, struct view_pos_s len); diff --git a/include/QF/script.h b/include/QF/script.h index 34e6f269a..540fb8db2 100644 --- a/include/QF/script.h +++ b/include/QF/script.h @@ -33,7 +33,7 @@ typedef struct script_s { /// The current (or next when unget is true) token struct dstring_s *token; /// True if the last token has been pushed back. - qboolean unget; + bool unget; /// current position within the script const char *p; /// name of the file being processed. used only for error reporting @@ -79,7 +79,7 @@ void Script_Start (script_t *script, const char *file, const char *data); \return True if a token is available, false if end of file or end of line (if crossline is false) has been hit */ -qboolean Script_TokenAvailable (script_t *script, qboolean crossline); +bool Script_TokenAvailable (script_t *script, bool crossline); /** Get the next token. Generates an error and exits the program if no token is available and crossline is false. @@ -87,7 +87,7 @@ qboolean Script_TokenAvailable (script_t *script, qboolean crossline); \param crossline True to allow passing \n \return True on success, false on failure (no token available) */ -qboolean Script_GetToken (script_t *script, qboolean crossline); +bool Script_GetToken (script_t *script, bool crossline); /** Unget the current token. Only one level of unget is supported. \param script The script_t object being parsed diff --git a/include/QF/sizebuf.h b/include/QF/sizebuf.h index c454cdc4c..752ab2b26 100644 --- a/include/QF/sizebuf.h +++ b/include/QF/sizebuf.h @@ -37,8 +37,8 @@ typedef struct sizebuf_s { - qboolean allowoverflow; // if false, do a Sys_Error - qboolean overflowed; // set to true if the buffer size failed + bool allowoverflow; // if false, do a Sys_Error + bool overflowed; // set to true if the buffer size failed byte *data; unsigned maxsize; unsigned cursize; diff --git a/include/QF/skin.h b/include/QF/skin.h index 7f520e1d6..75272a26a 100644 --- a/include/QF/skin.h +++ b/include/QF/skin.h @@ -50,7 +50,7 @@ typedef struct skin_s { const char *name; - qboolean valid; // the skin was found + bool valid; // the skin was found struct tex_s *texels; byte *colormap; int texnum; diff --git a/include/QF/vid.h b/include/QF/vid.h index 2f78d7945..7f15de0e8 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -35,8 +35,8 @@ #define VID_GRADES (1 << VID_CBITS) typedef struct { - qboolean initialized; - qboolean is8bit; + bool initialized; + bool is8bit; byte *gammatable; // 256 const byte *basepal; // 256 * 3 byte *palette; // 256 * 3 @@ -48,7 +48,7 @@ typedef struct { unsigned width; unsigned height; int numpages; - qboolean recalc_refdef; // if true, recalc vid-based stuff + bool recalc_refdef; // if true, recalc vid-based stuff struct vid_internal_s *vid_internal; struct viddef_listener_set_s *onPaletteChanged; @@ -63,7 +63,7 @@ typedef void (*viddef_listener_t) (void *data, const viddef_t *viddef); extern unsigned int d_8to24table[256]; //FIXME nq/qw uses -extern qboolean vid_gamma_avail; +extern bool vid_gamma_avail; void VID_Init_Cvars (void); diff --git a/include/QF/winding.h b/include/QF/winding.h index 5815ac793..52058b6fd 100644 --- a/include/QF/winding.h +++ b/include/QF/winding.h @@ -114,7 +114,7 @@ winding_t *WindingVectors (const winding_t *w, int unit); on the font side of the plane, or NULL if the winding has been clipped away. */ -winding_t *ClipWinding (winding_t *in, struct plane_s *split, qboolean keepon); +winding_t *ClipWinding (winding_t *in, struct plane_s *split, bool keepon); /** Divide a winding by a plane, producing one or two windings. diff --git a/include/QF/zone.h b/include/QF/zone.h index 96ba13a51..11c95b7f0 100644 --- a/include/QF/zone.h +++ b/include/QF/zone.h @@ -118,7 +118,7 @@ void Z_SetTag (memzone_t *zone, void *ptr, int tag); memhunk_t *Hunk_Init (void *buf, size_t size); -void Hunk_Print (memhunk_t *hunk, qboolean all); +void Hunk_Print (memhunk_t *hunk, bool all); void Hunk_Check (memhunk_t *hunk); void *Hunk_RawAlloc (memhunk_t *hunk, size_t size) __attribute__((nonnull(1))); void *Hunk_RawAllocName (memhunk_t *hunk, size_t size, const char *name) __attribute__((nonnull(1))); diff --git a/include/client/locs.h b/include/client/locs.h index ac0198d2d..d18e2b0dd 100644 --- a/include/client/locs.h +++ b/include/client/locs.h @@ -45,7 +45,7 @@ void locs_load(const char *filename); void locs_mark (vec4f_t loc, const char *desc); int locs_nearest (vec4f_t loc) __attribute__((pure)); void locs_reset (void); -void locs_save (const char *filename, qboolean gz); +void locs_save (const char *filename, bool gz); void map_to_loc (const char *mapname, char *filename); void locs_draw (double time, vec4f_t simorg); diff --git a/include/client/sbar.h b/include/client/sbar.h index 60766c3b1..ba10c8872 100644 --- a/include/client/sbar.h +++ b/include/client/sbar.h @@ -31,7 +31,7 @@ #ifndef __client_sbar_h #define __client_sbar_h -extern qboolean sbar_showscores; +extern bool sbar_showscores; struct player_info_s; void Sbar_Init (int *stats, float *item_gettime); diff --git a/include/client/temp_entities.h b/include/client/temp_entities.h index e6f3a8406..62e828d88 100644 --- a/include/client/temp_entities.h +++ b/include/client/temp_entities.h @@ -114,7 +114,7 @@ void CL_ParseTEnt_qw (struct msg_s *net_message, double time, TEntContext_t *ctx); void CL_ParseParticleEffect (struct msg_s *net_message); void CL_ClearProjectiles (void); -void CL_ParseProjectiles (struct msg_s *net_message, qboolean nail2, +void CL_ParseProjectiles (struct msg_s *net_message, bool nail2, TEntContext_t *ctx); #endif//__client_temp_entities_h diff --git a/include/client/view.h b/include/client/view.h index 366b641fe..4915b77cc 100644 --- a/include/client/view.h +++ b/include/client/view.h @@ -86,7 +86,7 @@ typedef struct viewstate_s { // pitch drifting vars float idealpitch; float pitchvel; - qboolean nodrift; + bool nodrift; float driftmove; double laststop; @@ -112,6 +112,6 @@ void V_SetContentsColor (viewstate_t *vs, int contents); void V_ParseDamage (struct msg_s *net_message, viewstate_t *vs); void V_PrepBlend (viewstate_t *vs); -extern qboolean noclip_anglehack; +extern bool noclip_anglehack; #endif // __client_view_h diff --git a/include/context_win.h b/include/context_win.h index fdd068011..513b0478a 100644 --- a/include/context_win.h +++ b/include/context_win.h @@ -55,7 +55,7 @@ void Win_CreateWindow (int width, int height); void Win_Init_Cvars (void); void Win_UpdateWindowStatus (int x, int y); void Win_SetCaption (const char *text); -qboolean Win_SetGamma (double gamma); +bool Win_SetGamma (double gamma); struct vid_internal_s; struct gl_ctx_s *Win_GL_Context (struct vid_internal_s *); diff --git a/include/context_x11.h b/include/context_x11.h index 77c913034..59e1e63f0 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -57,12 +57,12 @@ extern int x_height; extern int x_shmeventtype; extern Time x_time; extern Time x_mouse_time; -extern qboolean oktodraw; -extern qboolean x_have_focus; +extern bool oktodraw; +extern bool x_have_focus; -qboolean X11_AddEvent (int event, void (*event_handler)(XEvent *)); -qboolean X11_RemoveEvent (int event, void (*event_handler)(XEvent *)); -qboolean X11_SetGamma (double); +bool X11_AddEvent (int event, void (*event_handler)(XEvent *)); +bool X11_RemoveEvent (int event, void (*event_handler)(XEvent *)); +bool X11_SetGamma (double); void X11_CloseDisplay (void); void X11_CreateNullCursor (void); void X11_CreateWindow (int, int); diff --git a/include/d_iface.h b/include/d_iface.h index 7970064ed..9e7d6a6a5 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -113,23 +113,23 @@ typedef struct } zpointdesc_t; extern int r_drawflat; -extern int r_framecount; // sequence # of current frame since Quake - // started -extern qboolean r_drawpolys; // 1 if driver wants clipped polygons - // rather than a span list -extern qboolean r_drawculledpolys; // 1 if driver wants clipped polygons that - // have been culled by the edge list -extern qboolean r_worldpolysbacktofront; // 1 if driver wants polygons - // delivered back to front rather - // than front to back -extern qboolean r_recursiveaffinetriangles; // true if a driver wants to use - // recursive triangular subdivison - // and vertex drawing via - // D_PolysetDrawFinalVerts() past - // a certain distance (normally - // used only by the software - // driver) -extern qboolean r_dowarp; +extern int r_framecount; // sequence # of current frame since Quake + // started +extern bool r_drawpolys; // 1 if driver wants clipped polygons + // rather than a span list +extern bool r_drawculledpolys; // 1 if driver wants clipped polygons that + // have been culled by the edge list +extern bool r_worldpolysbacktofront; // 1 if driver wants polygons + // delivered back to front rather + // than front to back +extern bool r_recursiveaffinetriangles; // true if a driver wants to use + // recursive triangular subdivison + // and vertex drawing via + // D_PolysetDrawFinalVerts() past + // a certain distance (normally + // used only by the software + // driver) +extern bool r_dowarp; extern affinetridesc_t r_affinetridesc; extern spritedesc_t r_spritedesc; diff --git a/include/d_local.h b/include/d_local.h index 20ae2cb73..3a3594db2 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -65,7 +65,7 @@ typedef struct sspan_s { extern float scale_for_mip; -extern qboolean d_roverwrapped; +extern bool d_roverwrapped; extern surfcache_t *sc_rover; extern surfcache_t *d_initial_rover; diff --git a/include/dga_check.h b/include/dga_check.h index a56161c68..26f5a7dfb 100644 --- a/include/dga_check.h +++ b/include/dga_check.h @@ -38,7 +38,7 @@ Check for the presence of the XFree86-DGA support in the X server */ -qboolean VID_CheckDGA (Display *, int *, int *, int *) +bool VID_CheckDGA (Display *, int *, int *, int *) #ifndef HAVE_DGA // FIXME __attribute__((const)) #endif @@ -50,7 +50,7 @@ qboolean VID_CheckDGA (Display *, int *, int *, int *) Check for the presence of the XFree86-VMode X server extension */ -qboolean VID_CheckVMode (Display *, int *, int *) +bool VID_CheckVMode (Display *, int *, int *) #ifndef HAVE_DGA // FIXME __attribute__((const)) #endif diff --git a/include/gib_builtin.h b/include/gib_builtin.h index 4fc56c759..ed61e7f41 100644 --- a/include/gib_builtin.h +++ b/include/gib_builtin.h @@ -36,4 +36,4 @@ typedef struct gib_builtin_s { } gib_builtin_t; gib_builtin_t *GIB_Builtin_Find (const char *name); -void GIB_Builtin_Init (qboolean sandbox); +void GIB_Builtin_Init (bool sandbox); diff --git a/include/gib_function.h b/include/gib_function.h index ef9bb90c1..f8d3a21b1 100644 --- a/include/gib_function.h +++ b/include/gib_function.h @@ -44,7 +44,7 @@ typedef struct gib_function_s { struct hashtab_s *globals; struct llist_s *arglist; unsigned int minargs; - qboolean exported; + bool exported; } gib_function_t; gib_function_t *GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, gib_script_t *script, hashtab_t *globals); diff --git a/include/gib_parse.h b/include/gib_parse.h index 6c6ee06e4..970ef175f 100644 --- a/include/gib_parse.h +++ b/include/gib_parse.h @@ -30,7 +30,7 @@ #include "gib_tree.h" -qboolean GIB_Escaped (const char *str, int i); +bool GIB_Escaped (const char *str, int i); char GIB_Parse_Match_Brace (const char *str, unsigned int *i); char GIB_Parse_Match_Backtick (const char *str, unsigned int *i); @@ -41,7 +41,7 @@ char GIB_Parse_Match_Var (const char *str, unsigned int *i); gib_tree_t *GIB_Parse_Lines (const char *program, unsigned int pofs); gib_tree_t *GIB_Parse_Embedded (gib_tree_t *token); -extern qboolean gib_parse_error; +extern bool gib_parse_error; void GIB_Parse_Error (const char *msg, unsigned int pos); const char *GIB_Parse_ErrorMsg (void) __attribute__((pure)); unsigned int GIB_Parse_ErrorPos (void) __attribute__((pure)); diff --git a/include/gib_vars.h b/include/gib_vars.h index bd606fec4..eb6829501 100644 --- a/include/gib_vars.h +++ b/include/gib_vars.h @@ -48,9 +48,9 @@ typedef struct gib_domain_s { } gib_domain_t; gib_var_t *GIB_Var_Get (hashtab_t *first, hashtab_t *second, const char *key); -gib_var_t *GIB_Var_Get_Complex (hashtab_t **first, hashtab_t **second, char *key, unsigned int *ind, qboolean create); -gib_var_t *GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *key, unsigned int start, unsigned int *ind, qboolean create); -void GIB_Var_Assign (gib_var_t *var, unsigned int index, dstring_t **values, unsigned int numv, qboolean shrink); +gib_var_t *GIB_Var_Get_Complex (hashtab_t **first, hashtab_t **second, char *key, unsigned int *ind, bool create); +gib_var_t *GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *key, unsigned int start, unsigned int *ind, bool create); +void GIB_Var_Assign (gib_var_t *var, unsigned int index, dstring_t **values, unsigned int numv, bool shrink); hashtab_t *GIB_Domain_Get (const char *name); hashtab_t *GIB_Var_Hash_New (void); diff --git a/include/in_win.h b/include/in_win.h index a961e61e3..650b0ab2f 100644 --- a/include/in_win.h +++ b/include/in_win.h @@ -30,7 +30,7 @@ #include "QF/qtypes.h" -extern qboolean mouseactive; +extern bool mouseactive; extern float mouse_x, mouse_y; void IN_UpdateClipCursor (void); diff --git a/include/net_dgrm.h b/include/net_dgrm.h index 38c2f7e19..d9bab8c1c 100644 --- a/include/net_dgrm.h +++ b/include/net_dgrm.h @@ -43,7 +43,7 @@ int Datagram_Init (void); \param state True to enable, false to disable. */ -void Datagram_Listen (qboolean state); +void Datagram_Listen (bool state); /** Search for hosts (servers) on the local network. @@ -54,7 +54,7 @@ void Datagram_Listen (qboolean state); \param xmit True to send the broadcast, falst to only listen. */ -void Datagram_SearchForHosts (qboolean xmit); +void Datagram_SearchForHosts (bool xmit); /** Connect to the specified host. @@ -104,7 +104,7 @@ int Datagram_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); \param sock The socket to check. \return True if the packet can be sent. */ -qboolean Datagram_CanSendMessage (qsocket_t *sock); +bool Datagram_CanSendMessage (qsocket_t *sock); /** Check if an unreliable message can be sent to the socket. @@ -113,7 +113,7 @@ qboolean Datagram_CanSendMessage (qsocket_t *sock); \param sock The socket to check. \return True if the packet can be sent. */ -qboolean Datagram_CanSendUnreliableMessage (qsocket_t *sock); +bool Datagram_CanSendUnreliableMessage (qsocket_t *sock); /** Close the socket. diff --git a/include/net_loop.h b/include/net_loop.h index 9247f949e..c74683be8 100644 --- a/include/net_loop.h +++ b/include/net_loop.h @@ -37,15 +37,15 @@ ///@{ int Loop_Init (void); -void Loop_Listen (qboolean state); -void Loop_SearchForHosts (qboolean xmit); +void Loop_Listen (bool state); +void Loop_SearchForHosts (bool xmit); qsocket_t *Loop_Connect (const char *host); qsocket_t *Loop_CheckNewConnections (void); int Loop_GetMessage (qsocket_t *sock); int Loop_SendMessage (qsocket_t *sock, sizebuf_t *data); int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data); -qboolean Loop_CanSendMessage (qsocket_t *sock); -qboolean Loop_CanSendUnreliableMessage (qsocket_t *sock); +bool Loop_CanSendMessage (qsocket_t *sock); +bool Loop_CanSendUnreliableMessage (qsocket_t *sock); void Loop_Close (qsocket_t *sock); void Loop_Shutdown (void); diff --git a/include/net_udp.h b/include/net_udp.h index bd414513d..201342b12 100644 --- a/include/net_udp.h +++ b/include/net_udp.h @@ -55,7 +55,7 @@ void UDP_Shutdown (void); \param state True to open the socket, false to close it. */ -void UDP_Listen (qboolean state); +void UDP_Listen (bool state); /** Open a single socket on the specified port. diff --git a/include/net_vcr.h b/include/net_vcr.h index 9f5446453..527b2893b 100644 --- a/include/net_vcr.h +++ b/include/net_vcr.h @@ -38,13 +38,13 @@ #define VCR_MAX_MESSAGE 4 int VCR_Init (void); -void VCR_Listen (qboolean state); -void VCR_SearchForHosts (qboolean xmit); +void VCR_Listen (bool state); +void VCR_SearchForHosts (bool xmit); qsocket_t *VCR_Connect (const char *host); qsocket_t *VCR_CheckNewConnections (void); int VCR_GetMessage (qsocket_t *sock); int VCR_SendMessage (qsocket_t *sock, sizebuf_t *data); -qboolean VCR_CanSendMessage (qsocket_t *sock); +bool VCR_CanSendMessage (qsocket_t *sock); void VCR_Close (qsocket_t *sock); void VCR_Shutdown (void); diff --git a/include/net_wins.h b/include/net_wins.h index 56c7fdddb..a73a8b0fd 100644 --- a/include/net_wins.h +++ b/include/net_wins.h @@ -42,7 +42,7 @@ extern WSADATA winsockdata; int WINS_Init (void); void WINS_Shutdown (void); -void WINS_Listen (qboolean state); +void WINS_Listen (bool state); int WINS_OpenSocket (int port); int WINS_CloseSocket (int socket); int WINS_Connect (int socket, netadr_t *addr); diff --git a/include/netchan.h b/include/netchan.h index 94b56f954..ce1178540 100644 --- a/include/netchan.h +++ b/include/netchan.h @@ -92,7 +92,7 @@ void NET_Init (int port); \return True if successfully read, otherwise false. */ -qboolean NET_GetPacket (void); +bool NET_GetPacket (void); /** Send a data packet out to the network. @@ -110,7 +110,7 @@ void NET_SendPacket (int length, const void *data, netadr_t to); \param b The second address to compare. \return True of the addresses match, otherwise false. */ -qboolean NET_CompareAdr (netadr_t a, netadr_t b) __attribute__((const)); +bool NET_CompareAdr (netadr_t a, netadr_t b) __attribute__((const)); /** Compare two network addresses. @@ -120,7 +120,7 @@ qboolean NET_CompareAdr (netadr_t a, netadr_t b) __attribute__((const)); \param b The second address to compare. \return True of the addresses match, otherwise false. */ -qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) __attribute__((const)); +bool NET_CompareBaseAdr (netadr_t a, netadr_t b) __attribute__((const)); /** Convert an address to a string. @@ -157,7 +157,7 @@ const char *NET_BaseAdrToString (netadr_t a); \param[out] a The resulting address of the conversion. \return True if the conversion is successful, otherwise false. */ -qboolean NET_StringToAdr (const char *s, netadr_t *a); +bool NET_StringToAdr (const char *s, netadr_t *a); ///@} @@ -225,7 +225,7 @@ typedef enum { } ncqport_e; typedef struct netchan_s { - qboolean fatal_error; ///< True if the message overflowed + bool fatal_error; ///< True if the message overflowed double last_received; ///< Time the last packet was received. @@ -343,7 +343,7 @@ void Netchan_OutOfBandPrint (netadr_t adr, const char *format, ...) \param chan The netchan representing the connection. */ -qboolean Netchan_Process (netchan_t *chan); +bool Netchan_Process (netchan_t *chan); /** Initialize a new connection. @@ -360,7 +360,7 @@ void Netchan_Setup (netchan_t *chan, netadr_t adr, int qport, ncqport_e flags); \param chan The netchan representing the connection. \return True if the connection isn't chocked. */ -qboolean Netchan_CanPacket (netchan_t *chan) __attribute__((pure)); +bool Netchan_CanPacket (netchan_t *chan) __attribute__((pure)); /** Check if a reliable packet can be sent to the connection. @@ -368,7 +368,7 @@ qboolean Netchan_CanPacket (netchan_t *chan) __attribute__((pure)); \return True if there is no outstanding reliable packet and the connection isn't chocked. */ -qboolean Netchan_CanReliable (netchan_t *chan) __attribute__((pure)); +bool Netchan_CanReliable (netchan_t *chan) __attribute__((pure)); /** Send a packet. diff --git a/include/netmain.h b/include/netmain.h index dbf319914..e876f18b4 100644 --- a/include/netmain.h +++ b/include/netmain.h @@ -166,9 +166,9 @@ typedef struct qsocket_s { /// \name socket status //@{ - qboolean disconnected; ///< Socket is not in use. - qboolean canSend; ///< Socket can send a message. - qboolean sendNext; + bool disconnected; ///< Socket is not in use. + bool canSend; ///< Socket can send a message. + bool sendNext; //@} /// \name socket drivers @@ -296,7 +296,7 @@ struct qsocket_s *NET_Connect (const char *host); \param sock The qsocket representing the connection. \return True if the message can be sent. */ -qboolean NET_CanSendMessage (qsocket_t *sock); +bool NET_CanSendMessage (qsocket_t *sock); /** Read a single message from the connection into net_message. @@ -378,12 +378,12 @@ typedef struct _PollProcedure { */ void SchedulePollProcedure(PollProcedure *pp, double timeOffset); -extern qboolean tcpipAvailable; -extern char my_tcpip_address[NET_NAMELEN]; +extern bool tcpipAvailable; +extern char my_tcpip_address[NET_NAMELEN]; -extern qboolean slistInProgress; -extern qboolean slistSilent; -extern qboolean slistLocal; +extern bool slistInProgress; +extern bool slistSilent; +extern bool slistLocal; extern char *hostname; @@ -398,11 +398,11 @@ extern QFile *vcrFile; typedef struct { const char *name; - qboolean initialized; + bool initialized; int controlSock; int (*Init) (void); void (*Shutdown) (void); - void (*Listen) (qboolean state); + void (*Listen) (bool state); int (*OpenSocket) (int port); int (*CloseSocket) (int socket); int (*Connect) (int socket, netadr_t *addr); @@ -431,17 +431,17 @@ extern net_landriver_t net_landrivers[MAX_NET_DRIVERS]; typedef struct { const char *name; - qboolean initialized; + bool initialized; int (*Init) (void); - void (*Listen) (qboolean state); - void (*SearchForHosts) (qboolean xmit); + void (*Listen) (bool state); + void (*SearchForHosts) (bool xmit); qsocket_t *(*Connect) (const char *host); qsocket_t *(*CheckNewConnections) (void); int (*QGetMessage) (qsocket_t *sock); int (*QSendMessage) (qsocket_t *sock, sizebuf_t *data); int (*SendUnreliableMessage) (qsocket_t *sock, sizebuf_t *data); - qboolean (*CanSendMessage) (qsocket_t *sock); - qboolean (*CanSendUnreliableMessage) (qsocket_t *sock); + bool (*CanSendMessage) (qsocket_t *sock); + bool (*CanSendUnreliableMessage) (qsocket_t *sock); void (*Close) (qsocket_t *sock); void (*Shutdown) (void); int controlSock; diff --git a/include/qw/pmove.h b/include/qw/pmove.h index 20e68bb05..f30260d19 100644 --- a/include/qw/pmove.h +++ b/include/qw/pmove.h @@ -58,9 +58,9 @@ typedef struct { int oldbuttons; int oldonground; float waterjumptime; - qboolean dead; - qboolean flying; - qboolean add_grav; + bool dead; + bool flying; + bool add_grav; int spectator; // world state @@ -109,7 +109,7 @@ void Pmove_Init_Cvars (void); int PM_HullPointContents (hull_t *hull, int num, const vec3_t p) __attribute__((pure)); int PM_PointContents (const vec3_t point) __attribute__((pure)); -qboolean PM_TestPlayerPosition (const vec3_t point); +bool PM_TestPlayerPosition (const vec3_t point); trace_t PM_PlayerMove (const vec3_t start, const vec3_t stop); #endif // _PMOVE_H diff --git a/include/r_local.h b/include/r_local.h index 55b093513..c8bb871a7 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -131,14 +131,14 @@ void R_ClearPolyList (void); void R_DrawPolyList (void); // Surface cache related ========== -extern qboolean r_cache_thrash; // set if thrashing the surface cache +extern bool r_cache_thrash; // set if thrashing the surface cache // current entity info -extern qboolean insubmodel; -extern vec3_t r_worldmodelorg; +extern bool insubmodel; +extern vec3_t r_worldmodelorg; -extern mat4f_t glsl_projection; -extern mat4f_t glsl_view; +extern mat4f_t glsl_projection; +extern mat4f_t glsl_view; union refframe_s; void R_SetFrustum (plane_t *frustum, const union refframe_s *frame, @@ -245,7 +245,7 @@ extern auxvert_t *pauxverts; extern float ziscale; extern float aliastransform[3][4]; -qboolean R_AliasCheckBBox (struct entity_s ent); +bool R_AliasCheckBBox (struct entity_s ent); // turbulence stuff ======================================= @@ -290,7 +290,7 @@ void R_AliasClipTriangle (mtriangle_t *ptri); extern double r_time1; extern int r_frustum_indexes[4*6]; extern int r_maxsurfsseen, r_maxedgesseen; -extern qboolean r_dowarpold, r_viewchanged; +extern bool r_dowarpold, r_viewchanged; extern int r_clipflags; diff --git a/include/r_shared.h b/include/r_shared.h index 4d6205920..358ca1465 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -101,7 +101,7 @@ typedef struct surf_s { void *data; // associated data like msurface_t uint32_t render_id; float nearzi; // nearest 1/z on surface, for mipmapping - qboolean insubmodel; + bool insubmodel; float d_ziorigin, d_zistepu, d_zistepv; int pad[2]; // to 64 bytes (FIXME not for 64-bit) diff --git a/include/varrays.h b/include/varrays.h index 3116e3781..2e67a3167 100644 --- a/include/varrays.h +++ b/include/varrays.h @@ -47,7 +47,7 @@ typedef struct varray_t2f_c4f_n3f_v3f_s { GLfloat vertex[3]; } varray_t2f_c4f_n3f_v3f_t; -extern qboolean gl_va_capable; +extern bool gl_va_capable; extern int vaelements; extern varray_t2f_c4ub_v3f_t *gl_spriteVertexArray; diff --git a/include/vid_gl.h b/include/vid_gl.h index a89264d13..d23114a48 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -12,7 +12,7 @@ typedef struct gl_ctx_s { void (*choose_visual) (struct gl_ctx_s *ctx); void (*create_context) (struct gl_ctx_s *ctx, int core); void (*init_gl) (void); - void *(*get_proc_address) (const char *name, qboolean crit); + void *(*get_proc_address) (const char *name, bool crit); void (*end_rendering) (void); mat4f_t projection; diff --git a/include/vid_internal.h b/include/vid_internal.h index 293098f1f..ea45d2a13 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -40,7 +40,7 @@ void VID_GetWindowSize (int def_w, int def_h); void VID_SetWindowSize (int width, int height); void VID_InitGamma (const byte *); -qboolean VID_SetGamma (double); +bool VID_SetGamma (double); void VID_UpdateGamma (void); void VID_MakeColormaps (void); diff --git a/include/winquake.h b/include/winquake.h index 13c717363..ccb3d2db9 100644 --- a/include/winquake.h +++ b/include/winquake.h @@ -76,9 +76,9 @@ typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t; extern modestate_t modestate; -extern qboolean WinNT; +extern bool WinNT; -extern qboolean winsock_lib_initialized; +extern bool winsock_lib_initialized; #ifdef SPLASH_SCREEN extern HWND hwnd_dialog; diff --git a/include/world.h b/include/world.h index cab559011..69b7664b6 100644 --- a/include/world.h +++ b/include/world.h @@ -33,7 +33,7 @@ #include "QF/model.h" typedef struct { - qboolean present; + bool present; vec3_t laggedpos; } laggedentinfo_t; @@ -44,9 +44,9 @@ typedef enum { } trace_e; typedef struct trace_s { - qboolean allsolid; // if true, plane is not valid - qboolean startsolid; // if true, the initial point was in a solid area - qboolean inopen, inwater; + bool allsolid; // if true, plane is not valid + bool startsolid; // if true, the initial point was in a solid area + bool inopen, inwater; float fraction; // time completed, 1.0 = didn't hit anything vec3_t extents; // 1/2 size of traced box trace_e type; // type of trace to perform @@ -92,7 +92,7 @@ void SV_UnlinkEdict (struct edict_s *ent); // so it doesn't clip against itself // flags ent->v.modified -void SV_LinkEdict (struct edict_s *ent, qboolean touch_triggers); +void SV_LinkEdict (struct edict_s *ent, bool touch_triggers); // Needs to be called any time an entity changes origin, mins, maxs, or solid // flags ent->v.modified // sets ent->v.absmin and ent->v.absmax diff --git a/libs/audio/cd.c b/libs/audio/cd.c index 4ac01e361..ea28429d6 100644 --- a/libs/audio/cd.c +++ b/libs/audio/cd.c @@ -64,7 +64,7 @@ CDAudio_Pause (void) } VISIBLE void -CDAudio_Play (int track, qboolean looping) +CDAudio_Play (int track, bool looping) { if (cdmodule) cdmodule->functions->cd->play (track, looping); diff --git a/libs/audio/cd_file.c b/libs/audio/cd_file.c index b92c88644..530872376 100644 --- a/libs/audio/cd_file.c +++ b/libs/audio/cd_file.c @@ -71,10 +71,10 @@ static general_data_t plugin_info_general_data; static general_funcs_t plugin_info_general_funcs; /* global status variables. */ -static qboolean playing = false; -static qboolean wasPlaying = false; -static qboolean mus_enabled = false; -static qboolean ogglistvalid = false; +static bool playing = false; +static bool wasPlaying = false; +static bool mus_enabled = false; +static bool ogglistvalid = false; /* sound resources */ static channel_t *cd_channel; @@ -294,7 +294,7 @@ I_OGGMus_Resume (void) /* start playing, if we've got a play_list. * cry if we can't find a file to play */ static void -I_OGGMus_Play (int track, qboolean looping) +I_OGGMus_Play (int track, bool looping) { /* alrighty. grab the list, map track to filename. grab filename from data resources, attach sound to play, loop. */ diff --git a/libs/audio/cd_linux.c b/libs/audio/cd_linux.c index add4910be..23c93b01e 100644 --- a/libs/audio/cd_linux.c +++ b/libs/audio/cd_linux.c @@ -66,11 +66,11 @@ static general_data_t plugin_info_general_data; static general_funcs_t plugin_info_general_funcs; static cd_funcs_t plugin_info_cd_funcs; -static qboolean cdValid = false; -static qboolean playing = false; -static qboolean wasPlaying = false; -static qboolean mus_enabled = false; -static qboolean playLooping = false; +static bool cdValid = false; +static bool playing = false; +static bool wasPlaying = false; +static bool mus_enabled = false; +static bool playLooping = false; static float cdvolume; static byte remap[100]; static byte playTrack; @@ -174,7 +174,7 @@ I_CDAudio_Stop (void) } static void -I_CDAudio_Play (int track, qboolean looping) +I_CDAudio_Play (int track, bool looping) { struct cdrom_tocentry entry0; struct cdrom_tocentry entry1; diff --git a/libs/audio/cd_sdl.c b/libs/audio/cd_sdl.c index 2e90c342a..44fe6f01b 100644 --- a/libs/audio/cd_sdl.c +++ b/libs/audio/cd_sdl.c @@ -56,10 +56,10 @@ static general_data_t plugin_info_general_data; static general_funcs_t plugin_info_general_funcs; static cd_funcs_t plugin_info_cd_funcs; -static qboolean cdValid = false; -static qboolean initialized = false; -static qboolean enabled = true; -static qboolean playLooping = false; +static bool cdValid = false; +static bool initialized = false; +static bool enabled = true; +static bool playLooping = false; static SDL_CD *cd_id; static float cdvolume = 1.0; @@ -113,7 +113,7 @@ I_CDAudio_Stop (void) } static void -I_CDAudio_Play (int track, qboolean looping) +I_CDAudio_Play (int track, bool looping) { /* Initialize cd_stat to avoid warning */ /* XXX - Does this default value make sense? */ diff --git a/libs/audio/cd_sgi.c b/libs/audio/cd_sgi.c index 8e57bb9ed..c8e0f4065 100644 --- a/libs/audio/cd_sgi.c +++ b/libs/audio/cd_sgi.c @@ -53,9 +53,9 @@ static general_funcs_t plugin_info_general_funcs; static cd_funcs_t plugin_info_cd_funcs; -static qboolean initialized = false; -static qboolean enabled = true; -static qboolean playLooping = false; +static bool initialized = false; +static bool enabled = true; +static bool playLooping = false; static float cdvolume; static byte remap[100]; static byte playTrack; @@ -126,7 +126,7 @@ I_SGI_Pause (void) } void -I_SGI_Play (int track, qboolean looping) +I_SGI_Play (int track, bool looping) { int maxtrack = I_SGI_MaxTrack (); diff --git a/libs/audio/cd_win.c b/libs/audio/cd_win.c index 2d2aa59fe..1be03d248 100644 --- a/libs/audio/cd_win.c +++ b/libs/audio/cd_win.c @@ -48,12 +48,12 @@ static general_data_t plugin_info_general_data; static general_funcs_t plugin_info_general_funcs; static cd_funcs_t plugin_info_cd_funcs; -static qboolean cdValid = false; -static qboolean playing = false; -static qboolean wasPlaying = false; -static qboolean initialized = false; -static qboolean enabled = false; -static qboolean playLooping = false; +static bool cdValid = false; +static bool playing = false; +static bool wasPlaying = false; +static bool initialized = false; +static bool enabled = false; +static bool playLooping = false; static float cdvolume; static byte remap[100]; static byte playTrack; @@ -61,7 +61,7 @@ static byte maxTrack; static UINT wDeviceID; -static void I_CDAudio_Play (int track, qboolean looping); +static void I_CDAudio_Play (int track, bool looping); static void I_CDAudio_Stop (void); static float bgmvolume; @@ -201,7 +201,7 @@ I_CDAudio_Pause (void) } static void -I_CDAudio_Play (int track, qboolean looping) +I_CDAudio_Play (int track, bool looping) { DWORD dwReturn; MCI_PLAY_PARMS mciPlayParms; diff --git a/libs/audio/cd_xmms.c b/libs/audio/cd_xmms.c index b26fc1d86..3fa30a04e 100644 --- a/libs/audio/cd_xmms.c +++ b/libs/audio/cd_xmms.c @@ -79,15 +79,15 @@ static int sessionNo; //static int xmmsPid = '0'; //static int sigNo = '2'; -static qboolean playing = false; +static bool playing = false; // no idea why I have wasPlaying, pbly this code was based on cd_linux.c :/ -static qboolean wasPlaying = false; -static qboolean musEnabled = true; +static bool wasPlaying = false; +static bool musEnabled = true; static void I_XMMS_Running(void); static void I_XMMS_Stop(void); -static void I_XMMS_Play(int, qboolean); +static void I_XMMS_Play(int, bool); static void I_XMMS_Pause(void); static void I_XMMS_Resume(void); static void I_XMMS_Next(void); @@ -178,7 +178,7 @@ I_XMMS_Stop (void) // stop playing // Play // start it playing, (unless disabled) static void -I_XMMS_Play (int track, qboolean looping) // looping for compatability +I_XMMS_Play (int track, bool looping) // looping for compatability { if (!musEnabled) return; diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 1b2fb64ce..01e8d0c8a 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -89,7 +89,7 @@ static set_t static_channels = SET_STATIC_ARRAY (static_channel_bits); static channel_t *ambient_channels[NUM_AMBIENTS]; -static qboolean snd_ambient = 1; +static bool snd_ambient = 1; static sfx_t *ambient_sfx[NUM_AMBIENTS]; static vec_t sound_nominal_clip_dist = 1000.0; diff --git a/libs/audio/targets/snd_alsa.c b/libs/audio/targets/snd_alsa.c index 371ccba27..8c55c6005 100644 --- a/libs/audio/targets/snd_alsa.c +++ b/libs/audio/targets/snd_alsa.c @@ -99,7 +99,7 @@ static ret (*qf##func) params; #include "alsa_funcs_list.h" #undef QF_ALSA_NEED -static qboolean +static bool load_libasound (void) { if (!(alsa_handle = dlopen ("libasound.so.2", RTLD_GLOBAL | RTLD_NOW))) { diff --git a/libs/audio/targets/snd_dx.c b/libs/audio/targets/snd_dx.c index 610fc4616..291232720 100644 --- a/libs/audio/targets/snd_dx.c +++ b/libs/audio/targets/snd_dx.c @@ -51,9 +51,9 @@ HRESULT (WINAPI * pDirectSoundCreate) (GUID FAR * lpGUID, typedef enum { SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL } sndinitstat; -static qboolean dsound_init; -static qboolean snd_firsttime = true; -static qboolean primary_format_set; +static bool dsound_init; +static bool snd_firsttime = true; +static bool primary_format_set; static int sample16; @@ -111,7 +111,7 @@ static cvar_t snd_bits_cvar = { .value = { .type = &cexpr_int, .value = &snd_bits }, }; -static DWORD *DSOUND_LockBuffer (snd_t *snd, qboolean lockit); +static DWORD *DSOUND_LockBuffer (snd_t *snd, bool lockit); static void SNDDMA_Init_Cvars (void) @@ -436,7 +436,7 @@ SNDDMA_shutdown (snd_t *snd) } static DWORD * -DSOUND_LockBuffer (snd_t *snd, qboolean lockit) +DSOUND_LockBuffer (snd_t *snd, bool lockit) { int reps; diff --git a/libs/audio/targets/snd_win.c b/libs/audio/targets/snd_win.c index 42b23a820..3cc99aa83 100644 --- a/libs/audio/targets/snd_win.c +++ b/libs/audio/targets/snd_win.c @@ -45,7 +45,7 @@ typedef enum { SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL } sndinitstat; -static qboolean snd_firsttime = true; +static bool snd_firsttime = true; static int sample16; static int snd_sent, snd_completed; @@ -68,7 +68,7 @@ static HWAVEOUT hWaveOut; static DWORD gSndBufSize; -static qboolean SNDDMA_InitWav (snd_t *snd); +static bool SNDDMA_InitWav (snd_t *snd); static int snd_stereo; static cvar_t snd_stereo_cvar = { @@ -161,7 +161,7 @@ FreeSound (void) Crappy windows multimedia base */ -static qboolean +static bool SNDDMA_InitWav (snd_t *snd) { int i; diff --git a/libs/client/cl_temp_entities.c b/libs/client/cl_temp_entities.c index 9c93d9886..af70f6f82 100644 --- a/libs/client/cl_temp_entities.c +++ b/libs/client/cl_temp_entities.c @@ -227,7 +227,7 @@ beam_clear (beam_t *b) } static inline void -beam_setup (beam_t *b, qboolean settransform, double time, TEntContext_t *ctx) +beam_setup (beam_t *b, bool settransform, double time, TEntContext_t *ctx) { tent_t *tent; float d; @@ -688,7 +688,7 @@ CL_ClearProjectiles (void) Nails are passed as efficient temporary entities */ void -CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx) +CL_ParseProjectiles (qmsg_t *net_message, bool nail2, TEntContext_t *ctx) { tent_t *tent; tent_t *head = 0, **tail = &head; diff --git a/libs/client/cl_view.c b/libs/client/cl_view.c index 4951be9b8..2774f3ae3 100644 --- a/libs/client/cl_view.c +++ b/libs/client/cl_view.c @@ -638,7 +638,7 @@ V_PrepBlend (viewstate_t *vs) || (vs->force_cshifts & INFO_CSHIFT_POWERUP)) V_CalcPowerupCshift (vs); - qboolean cshift_changed = false; + bool cshift_changed = false; for (i = 0; i < NUM_CSHIFTS; i++) { if (vs->cshifts[i].percent != vs->prev_cshifts[i].percent) { diff --git a/libs/client/locs.c b/libs/client/locs.c index 9f98a7ce6..3ffd5f4ca 100644 --- a/libs/client/locs.c +++ b/libs/client/locs.c @@ -198,7 +198,7 @@ locs_reset (void) } void -locs_save (const char *filename, qboolean gz) +locs_save (const char *filename, bool gz) { int i; QFile *locfd; diff --git a/libs/client/sbar.c b/libs/client/sbar.c index 5cc348513..4e90f6072 100644 --- a/libs/client/sbar.c +++ b/libs/client/sbar.c @@ -332,14 +332,14 @@ static qpic_t *sb_face_quad; static qpic_t *sb_face_invuln; static qpic_t *sb_face_invis_invuln; -qboolean sbar_showscores; -static qboolean sbar_showteamscores; +bool sbar_showscores; +static bool sbar_showteamscores; static int sb_lines; // scan lines to draw static qpic_t *rsb_teambord; // PGM 01/19/97 - team color border -//static qboolean largegame = false; +//static bool largegame = false; char *fs_fraglog; static cvar_t fs_fraglog_cvar = { @@ -662,7 +662,7 @@ static draw_charbuffer_t *sb_spectator; int scoreboardlines, scoreboardteams; static void -Sbar_SortFrags (qboolean includespec) +Sbar_SortFrags (bool includespec) { int i, j, k; diff --git a/libs/console/client.c b/libs/console/client.c index b274883ab..446912ab6 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -158,8 +158,8 @@ static con_state_t con_state; static int con_event_id; static int con_saved_focos; -static qboolean con_debuglog; -static qboolean chat_team; +static bool con_debuglog; +static bool chat_team; static dstring_t *c_print_buffer; static dstring_t *dlbar; static dstring_t *old_gamedir = 0; @@ -226,7 +226,7 @@ static float notify_times[NOTIFY_LINES + 1]; static int notify_head; static int notify_tail; -static qboolean con_initialized; +static bool con_initialized; static inline void * con_getcomponent (view_t view, uint32_t comp) diff --git a/libs/console/server.c b/libs/console/server.c index 8a464dda7..f591f792b 100644 --- a/libs/console/server.c +++ b/libs/console/server.c @@ -137,7 +137,7 @@ static cvar_t sv_use_curses_cvar = { #ifdef HAVE_NCURSES -static void key_event (knum_t key, short unicode, qboolean down); +static void key_event (knum_t key, short unicode, bool down); enum { sv_resize_x = 1, @@ -563,7 +563,7 @@ process_input (void) } static void -key_event (knum_t key, short unicode, qboolean down) +key_event (knum_t key, short unicode, bool down) { int ovf = view_offset; sv_view_t *window; diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 174c61ab0..9a0479403 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -239,7 +239,7 @@ ED_NumForEdict (progs_t *pr, edict_t *e) return b; } -qboolean +bool PR_EdictValid (progs_t *pr, pr_uint_t e) { if (!pr->num_edicts) { diff --git a/libs/gamecode/pr_parse.c b/libs/gamecode/pr_parse.c index 6ef2770f8..56a01a37a 100644 --- a/libs/gamecode/pr_parse.c +++ b/libs/gamecode/pr_parse.c @@ -212,7 +212,7 @@ ED_NewString (progs_t *pr, const char *string) Can parse either fields or globals returns false if error */ -VISIBLE qboolean +VISIBLE bool ED_ParseEpair (progs_t *pr, pr_type_t *base, pr_def_t *key, const char *s) { pr_def_t *def; diff --git a/libs/gamecode/pr_strings.c b/libs/gamecode/pr_strings.c index 5e00746ac..7dac24ff7 100644 --- a/libs/gamecode/pr_strings.c +++ b/libs/gamecode/pr_strings.c @@ -377,7 +377,7 @@ get_string (progs_t *pr, pr_string_t num) } } -VISIBLE qboolean +VISIBLE bool PR_StringValid (progs_t *pr, pr_string_t num) { if (num >= 0) { @@ -386,7 +386,7 @@ PR_StringValid (progs_t *pr, pr_string_t num) return get_strref (pr->pr_string_resources, num) != 0; } -VISIBLE qboolean +VISIBLE bool PR_StringMutable (progs_t *pr, pr_string_t num) { strref_t *sr; @@ -770,7 +770,7 @@ I_DoPrint (dstring_t *tmp, dstring_t *result, fmt_item_t *formatting) fmt_item_t *current = formatting; while (current) { - qboolean doPrecision, doWidth; + bool doPrecision, doWidth; doPrecision = -1 != current->precision; doWidth = 0 != (current->flags & FMT_WIDTH); diff --git a/libs/gib/gib_builtin.c b/libs/gib/gib_builtin.c index 44e9c4cf2..eef664cc9 100644 --- a/libs/gib/gib_builtin.c +++ b/libs/gib/gib_builtin.c @@ -116,7 +116,7 @@ GIB_Builtin_Remove (const char *name) Hash_Free (gib_builtins, del); } -VISIBLE qboolean +VISIBLE bool GIB_Builtin_Exists (const char *name) { return Hash_Find (gib_builtins, name) ? true : false; @@ -1046,7 +1046,7 @@ gib_builtin_shutdown (void *data) } void -GIB_Builtin_Init (qboolean sandbox) +GIB_Builtin_Init (bool sandbox) { if (sandbox) diff --git a/libs/gib/gib_classes.c b/libs/gib/gib_classes.c index 3ec8b9f86..e02beada2 100644 --- a/libs/gib/gib_classes.c +++ b/libs/gib/gib_classes.c @@ -188,7 +188,7 @@ Object_Class_New_f (gib_object_t *obj, gib_method_t *method, void *data, static const char **g_occ_reply; static unsigned int g_occ_i = 0; -static qboolean occ_iterator (gib_class_t *class, void *unused) +static bool occ_iterator (gib_class_t *class, void *unused) { g_occ_reply[g_occ_i++] = class->name; return false; @@ -282,7 +282,7 @@ typedef struct Thread_class_s { typedef struct Thread_s { gib_object_t *obj; cbuf_t *thread; - qboolean ended; + bool ended; } Thread_t; static int diff --git a/libs/gib/gib_execute.c b/libs/gib/gib_execute.c index c93f91f31..a8d3138cb 100644 --- a/libs/gib/gib_execute.c +++ b/libs/gib/gib_execute.c @@ -203,7 +203,7 @@ GIB_Execute (cbuf_t * cbuf) unsigned int index; gib_var_t *var; int i; - qboolean super; + bool super; static const char **mesg = NULL; static int maxmesg = 0; diff --git a/libs/gib/gib_function.c b/libs/gib/gib_function.c index 09b662dec..b0141dca5 100644 --- a/libs/gib/gib_function.c +++ b/libs/gib/gib_function.c @@ -163,7 +163,7 @@ static unsigned int g_fpa_argc; static hashtab_t *g_fpa_zero = 0; static unsigned int g_fpa_i, g_fpa_ind; -static qboolean fpa_iterate (char *arg, llist_node_t *node) +static bool fpa_iterate (char *arg, llist_node_t *node) { gib_var_t *var = GIB_Var_Get_Complex (&GIB_DATA(g_fpa_cbuf)->locals, &g_fpa_zero, arg, &g_fpa_ind, true); @@ -210,7 +210,7 @@ static unsigned int g_fpad_argc; static hashtab_t *g_fpad_zero = 0; static unsigned int g_fpad_i, g_fpad_ind; -static qboolean fpad_iterate (char *arg, llist_node_t *node) +static bool fpad_iterate (char *arg, llist_node_t *node) { gib_var_t *var; diff --git a/libs/gib/gib_init.c b/libs/gib/gib_init.c index 668d2fb10..1730c550d 100644 --- a/libs/gib/gib_init.c +++ b/libs/gib/gib_init.c @@ -100,7 +100,7 @@ GIB_Exec_Override_f (void) } VISIBLE void -GIB_Init (qboolean sandbox) +GIB_Init (bool sandbox) { // Override the exec command with a GIB-aware one if (Cmd_Exists ("exec")) { diff --git a/libs/gib/gib_object.c b/libs/gib/gib_object.c index f73108d26..3ddad1a4f 100644 --- a/libs/gib/gib_object.c +++ b/libs/gib/gib_object.c @@ -193,7 +193,7 @@ GIB_Class_Create (gib_classdesc_t *desc) */ gib_object_t * -GIB_Object_Create (const char *classname, qboolean classobj) +GIB_Object_Create (const char *classname, bool classobj) { gib_class_t *temp, *class = Hash_Find (gib_classes, classname); gib_object_t *obj; diff --git a/libs/gib/gib_parse.c b/libs/gib/gib_parse.c index c0afaa8d5..fd0c34038 100644 --- a/libs/gib/gib_parse.c +++ b/libs/gib/gib_parse.c @@ -54,7 +54,7 @@ escaped with a backslash (and the backslash is not itself escaped). */ -inline qboolean +inline bool GIB_Escaped (const char *str, int i) { int n, c; @@ -186,7 +186,7 @@ GIB_Parse_Match_Var (const char *str, unsigned int *i) return 0; } -VISIBLE qboolean gib_parse_error; +VISIBLE bool gib_parse_error; unsigned int gib_parse_error_pos; const char *gib_parse_error_msg; diff --git a/libs/gib/gib_thread.c b/libs/gib/gib_thread.c index 01d1fd98f..f8679772c 100644 --- a/libs/gib/gib_thread.c +++ b/libs/gib/gib_thread.c @@ -83,7 +83,7 @@ GIB_Thread_Count (void) return llist_size (gib_threads); } -static qboolean te_iterator (cbuf_t *cbuf, llist_node_t *node) +static bool te_iterator (cbuf_t *cbuf, llist_node_t *node) { if (GIB_DATA(cbuf)->program) Cbuf_Execute_Stack (cbuf); diff --git a/libs/gib/gib_vars.c b/libs/gib/gib_vars.c index b03d53402..e1cccb9bf 100644 --- a/libs/gib/gib_vars.c +++ b/libs/gib/gib_vars.c @@ -95,7 +95,7 @@ GIB_Var_Get (hashtab_t * first, hashtab_t * second, const char *key) /* Alters key, but restores it */ gib_var_t * GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key, - unsigned int *ind, qboolean create) + unsigned int *ind, bool create) { static hashtab_t *zero = 0; unsigned int i, n, index = 0, len, start; @@ -155,7 +155,7 @@ GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key, /* Mangles the hell out of key */ gib_var_t * GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *key, unsigned int start, - unsigned int *ind, qboolean create) + unsigned int *ind, bool create) { static hashtab_t *zero = 0; hashtab_t *one = *first, *two = *second; @@ -164,7 +164,7 @@ GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *ke cvar_t *cvar; char c; const char *str; - qboolean done = false; + bool done = false; for (i = start, protect = 0; !done; i++) { if (key->str[i] == '.' || key->str[i] == 0) { @@ -244,7 +244,7 @@ GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *ke void GIB_Var_Assign (gib_var_t * var, unsigned int index, dstring_t ** values, - unsigned int numv, qboolean shrink) + unsigned int numv, bool shrink) { unsigned int i, len; diff --git a/libs/image/pcx.c b/libs/image/pcx.c index 250429502..031d8a1a0 100644 --- a/libs/image/pcx.c +++ b/libs/image/pcx.c @@ -47,7 +47,7 @@ VISIBLE tex_t * -LoadPCX (QFile *f, qboolean convert, const byte *pal, int load) +LoadPCX (QFile *f, bool convert, const byte *pal, int load) { pcx_t *pcx; size_t pcx_mark; @@ -154,7 +154,7 @@ LoadPCX (QFile *f, qboolean convert, const byte *pal, int load) VISIBLE pcx_t * EncodePCX (const byte *data, int width, int height, - int rowbytes, const byte *palette, qboolean flip, int *length) + int rowbytes, const byte *palette, bool flip, int *length) { int i, run, pix, size; pcx_t *pcx; diff --git a/libs/input/in_imt.c b/libs/input/in_imt.c index 02a7463c0..3a4f3488a 100644 --- a/libs/input/in_imt.c +++ b/libs/input/in_imt.c @@ -553,7 +553,7 @@ IMT_BindButton (imt_t *imt, int button, const char *binding) } } -qboolean +bool IMT_ProcessAxis (int axis, int value) { imt_t *imt = in_contexts.a[imt_current_context].active_imt; @@ -643,7 +643,7 @@ process_binding (int button, int state, const char *cmd) } } -qboolean +bool IMT_ProcessButton (int button, int state) { imt_t *imt = in_contexts.a[imt_current_context].active_imt; diff --git a/libs/models/alias/gl_mesh.c b/libs/models/alias/gl_mesh.c index 5c7b6a9ce..ef68d3e07 100644 --- a/libs/models/alias/gl_mesh.c +++ b/libs/models/alias/gl_mesh.c @@ -49,7 +49,7 @@ // ALIAS MODEL DISPLAY LIST GENERATION ======================================== -static qboolean *used; +static int *used; static int used_size; // the command list holds counts and s/t values that are valid for every frame @@ -344,8 +344,8 @@ gl_Mod_MakeAliasModelDisplayLists (mod_alias_ctx_t *alias_ctx, void *_m, int i, j; int *cmds; QFile *f; - qboolean remesh = true; - qboolean do_cache = false; + bool remesh = true; + bool do_cache = false; cache = dstring_new (); fullpath = dstring_new (); diff --git a/libs/models/alias/vulkan_model_alias.c b/libs/models/alias/vulkan_model_alias.c index 42c0945af..c39ee77d3 100644 --- a/libs/models/alias/vulkan_model_alias.c +++ b/libs/models/alias/vulkan_model_alias.c @@ -115,7 +115,7 @@ vulkan_alias_clear (model_t *m, void *data) static void * Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize, - int snum, int gnum, qboolean group, + int snum, int gnum, bool group, maliasskindesc_t *skindesc, vulkan_ctx_t *ctx) { qfvPushDebug (ctx, va (ctx->va_ctx, "alias.load_skin: %s", alias_ctx->mod->name)); diff --git a/libs/models/gl_skin.c b/libs/models/gl_skin.c index 96506fb65..b8b17c5e8 100644 --- a/libs/models/gl_skin.c +++ b/libs/models/gl_skin.c @@ -57,7 +57,7 @@ typedef struct { tex_t *tex; tex_t *fb_tex; - qboolean fb; + bool fb; } glskin_t; static GLuint skin_textures[MAX_TRANSLATIONS]; @@ -101,7 +101,7 @@ gl_Skin_SetPlayerSkin (int width, int height, const byte *data) static void build_skin_8 (tex_t *tex, int texnum, byte *translate, - unsigned scaled_width, unsigned scaled_height, qboolean alpha) + unsigned scaled_width, unsigned scaled_height, bool alpha) { // Improvements should be mirrored in GL_ResampleTexture in gl_textures.c byte *inrow; @@ -127,7 +127,7 @@ build_skin_8 (tex_t *tex, int texnum, byte *translate, static void build_skin_32 (tex_t *tex, int texnum, byte *translate, - unsigned scaled_width, unsigned scaled_height, qboolean alpha) + unsigned scaled_width, unsigned scaled_height, bool alpha) { // Improvements should be mirrored in GL_ResampleTexture in gl_textures.c byte *inrow; diff --git a/libs/models/iqm/model_iqm.c b/libs/models/iqm/model_iqm.c index de01e09a4..147bf8dba 100644 --- a/libs/models/iqm/model_iqm.c +++ b/libs/models/iqm/model_iqm.c @@ -140,7 +140,7 @@ get_joints (const iqmheader *hdr, byte *buffer) return joint; } -static qboolean +static bool load_iqm_vertex_arrays (model_t *mod, const iqmheader *hdr, byte *buffer) { iqm_t *iqm = (iqm_t *) mod->aliashdr; @@ -328,7 +328,7 @@ load_iqm_vertex_arrays (model_t *mod, const iqmheader *hdr, byte *buffer) return true; } -static qboolean +static bool load_iqm_meshes (model_t *mod, const iqmheader *hdr, byte *buffer) { iqm_t *iqm = (iqm_t *) mod->aliashdr; @@ -375,7 +375,7 @@ load_iqm_meshes (model_t *mod, const iqmheader *hdr, byte *buffer) return true; } -static qboolean +static bool load_iqm_anims (model_t *mod, const iqmheader *hdr, byte *buffer) { iqm_t *iqm = (iqm_t *) mod->aliashdr; diff --git a/libs/models/model.c b/libs/models/model.c index 9258f6098..729aa624d 100644 --- a/libs/models/model.c +++ b/libs/models/model.c @@ -215,7 +215,7 @@ Mod_FindName (const char *name) } static model_t * -Mod_RealLoadModel (model_t *mod, qboolean crash, cache_allocator_t allocator) +Mod_RealLoadModel (model_t *mod, bool crash, cache_allocator_t allocator) { uint32_t *buf; @@ -293,7 +293,7 @@ Mod_RealLoadModel (model_t *mod, qboolean crash, cache_allocator_t allocator) Loads a model into the cache */ static model_t * -Mod_LoadModel (model_t *mod, qboolean crash) +Mod_LoadModel (model_t *mod, bool crash) { if (!mod->needload) { if (mod->type == mod_alias && !mod->aliashdr) { @@ -325,7 +325,7 @@ Mod_CallbackLoad (void *object, cache_allocator_t allocator) Loads in a model for the given name */ VISIBLE model_t * -Mod_ForName (const char *name, qboolean crash) +Mod_ForName (const char *name, bool crash) { model_t *mod; diff --git a/libs/models/test/testclip.c b/libs/models/test/testclip.c index a5738f015..329f7124b 100644 --- a/libs/models/test/testclip.c +++ b/libs/models/test/testclip.c @@ -41,10 +41,10 @@ typedef struct { vec3_t end; struct { float frac; - qboolean allsolid; - qboolean startsolid; - qboolean inopen; - qboolean inwater; + bool allsolid; + bool startsolid; + bool inopen; + bool inwater; } expect; } test_t; diff --git a/libs/models/test/trace-id.c b/libs/models/test/trace-id.c index 52ccb2d37..799575818 100644 --- a/libs/models/test/trace-id.c +++ b/libs/models/test/trace-id.c @@ -34,7 +34,7 @@ HullPointContents (hull_t *hull, int num, const vec3_t p) #define DIST_EPSILON (0.03125) #endif -static qboolean +static bool SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, const vec3_t p1, const vec3_t p2, trace_t *trace) { dclipnode_t *node; diff --git a/libs/models/trace.c b/libs/models/trace.c index 2ee7cf7a4..be77f6157 100644 --- a/libs/models/trace.c +++ b/libs/models/trace.c @@ -64,9 +64,9 @@ typedef struct { } clipbox_t; typedef struct { - qboolean seen_empty; - qboolean seen_solid; - qboolean moved; + bool seen_empty; + bool seen_solid; + bool moved; plane_t *split_plane; vec3_t dist; const vec_t *origin; @@ -197,7 +197,7 @@ calc_offset (const trace_t *trace, const plane_t *plane) return d; } -static qboolean +static bool point_inside_portal (const clipport_t *portal, const plane_t *plane, const vec3_t p) { @@ -218,7 +218,7 @@ point_inside_portal (const clipport_t *portal, const plane_t *plane, return true; } -static qboolean +static bool edges_intersect (const vec3_t p1, const vec3_t p2, const vec3_t r1, const vec3_t r2) { @@ -242,7 +242,7 @@ edges_intersect (const vec3_t p1, const vec3_t p2, return true; } -static qboolean +static bool trace_hits_portal (const hull_t *hull, const trace_t *trace, clipport_t *portal, const vec3_t start, const vec3_t vel) { @@ -274,7 +274,7 @@ trace_hits_portal (const hull_t *hull, const trace_t *trace, return true; } -static qboolean +static bool trace_enters_leaf (hull_t *hull, trace_t *trace, clipleaf_t *leaf, plane_t *plane, const vec3_t vel, const vec3_t org) { @@ -529,7 +529,7 @@ finish_impact: } } -static qboolean +static bool portal_intersect (trace_t *trace, clipport_t *portal, plane_t *plane, const vec3_t origin) { @@ -670,7 +670,7 @@ trace_to_leaf (const hull_t *hull, clipleaf_t *leaf, int side; vec_t frac = 1; vec_t t1, t2, offset, f; - qboolean clipped = false; + bool clipped = false; clipleaf_t *l; trace_state_t lstate = *state; diff --git a/libs/models/winding.c b/libs/models/winding.c index 7c81b28bf..3186ba51a 100644 --- a/libs/models/winding.c +++ b/libs/models/winding.c @@ -155,7 +155,7 @@ WindingVectors (const winding_t *w, int unit) } winding_t * -ClipWinding (winding_t *in, plane_t *split, qboolean keepon) +ClipWinding (winding_t *in, plane_t *split, bool keepon) { int maxpts, i, j; int *sides; diff --git a/libs/net/nc/net_udp.c b/libs/net/nc/net_udp.c index 337bb914e..5d238bf37 100644 --- a/libs/net/nc/net_udp.c +++ b/libs/net/nc/net_udp.c @@ -163,7 +163,7 @@ SockadrToNetadr (AF_address_t *s, netadr_t *a) a->port = s->s4.sin_port; } -qboolean +bool NET_CompareBaseAdr (netadr_t a, netadr_t b) { if (memcmp (a.ip, b.ip, ADDR_SIZE) == 0) @@ -171,7 +171,7 @@ NET_CompareBaseAdr (netadr_t a, netadr_t b) return false; } -qboolean +bool NET_CompareAdr (netadr_t a, netadr_t b) { if (memcmp (a.ip, b.ip, ADDR_SIZE) == 0 && a.port == b.port) @@ -208,7 +208,7 @@ NET_BaseAdrToString (netadr_t a) 192.246.40.70 192.246.40.70:28000 */ -qboolean +bool NET_StringToAdr (const char *s, netadr_t *a) { static dstring_t *copy; @@ -246,7 +246,7 @@ NET_StringToAdr (const char *s, netadr_t *a) return true; } -qboolean +bool NET_GetPacket (void) { int ret; diff --git a/libs/net/nc/net_udp6.c b/libs/net/nc/net_udp6.c index f0e8109e5..98b2cd51d 100644 --- a/libs/net/nc/net_udp6.c +++ b/libs/net/nc/net_udp6.c @@ -221,7 +221,7 @@ SockadrToNetadr (AF_address_t *s, netadr_t *a) } /* -static qboolean +static bool NET_AdrIsLoopback (netadr_t a) { if (IN6_IS_ADDR_LOOPBACK ((struct in6_addr *) &a.ip)) @@ -234,7 +234,7 @@ NET_AdrIsLoopback (netadr_t a) } */ -qboolean +bool NET_CompareBaseAdr (netadr_t a, netadr_t b) { if (memcmp (a.ip, b.ip, sizeof (a.ip)) == 0) @@ -242,7 +242,7 @@ NET_CompareBaseAdr (netadr_t a, netadr_t b) return false; } -qboolean +bool NET_CompareAdr (netadr_t a, netadr_t b) { if (memcmp (a.ip, b.ip, sizeof (a.ip)) == 0 && a.port == b.port) @@ -321,7 +321,7 @@ NET_BaseAdrToString (netadr_t a) 192.246.40.70 192.246.40.70:28000 */ -qboolean +bool NET_StringToAdr (const char *s, netadr_t *a) { static dstring_t *copy; @@ -400,7 +400,7 @@ NET_StringToAdr (const char *s, netadr_t *a) return true; } -qboolean +bool NET_GetPacket (void) { int ret; diff --git a/libs/net/net_chan.c b/libs/net/net_chan.c index 13d4e5e9a..e596281a1 100644 --- a/libs/net/net_chan.c +++ b/libs/net/net_chan.c @@ -182,7 +182,7 @@ Netchan_Setup (netchan_t *chan, netadr_t adr, int qport, ncqport_e flags) Returns true if the bandwidth choke isn't active */ -qboolean +bool Netchan_CanPacket (netchan_t *chan) { if (chan->cleartime < *net_realtime + MAX_BACKUP * chan->rate) @@ -195,7 +195,7 @@ Netchan_CanPacket (netchan_t *chan) Returns true if the bandwidth choke isn't */ -qboolean +bool Netchan_CanReliable (netchan_t *chan) { if (chan->reliable_length) @@ -209,7 +209,7 @@ Netchan_Transmit (netchan_t *chan, unsigned length, byte *data) byte send_buf[MAX_MSGLEN + PACKET_HEADER]; int i; unsigned int w1, w2; - qboolean send_reliable; + bool send_reliable; sizebuf_t send; // check for message overflow @@ -288,7 +288,7 @@ Netchan_Transmit (netchan_t *chan, unsigned length, byte *data) } } -qboolean +bool Netchan_Process (netchan_t *chan) { unsigned int reliable_ack, reliable_message, sequence, sequence_ack; diff --git a/libs/net/net_main.c b/libs/net/net_main.c index 523366bc0..99a1f2c28 100644 --- a/libs/net/net_main.c +++ b/libs/net/net_main.c @@ -55,18 +55,18 @@ qsocket_t *net_activeSockets = NULL; qsocket_t *net_freeSockets = NULL; int net_numsockets = 0; -qboolean tcpipAvailable = false; +bool tcpipAvailable = false; int net_hostport; int DEFAULTnet_hostport = 26000; char my_tcpip_address[NET_NAMELEN]; -static qboolean listening = false; +static bool listening = false; -qboolean slistInProgress = false; -qboolean slistSilent = false; -qboolean slistLocal = true; +bool slistInProgress = false; +bool slistSilent = false; +bool slistLocal = true; static double slistStartTime; static int slistLastShown; @@ -106,7 +106,7 @@ static cvar_t hostname_cvar = { }; QFile *vcrFile; -qboolean recording = false; +bool recording = false; // these two macros are to make the code more readable #define sfunc net_drivers[sock->driver] @@ -698,7 +698,7 @@ NET_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) } -qboolean +bool NET_CanSendMessage (qsocket_t *sock) { int r; @@ -731,8 +731,8 @@ NET_SendToAll (sizebuf_t *data, double blocktime) double start; unsigned i; int count = 0; - qboolean state1[MAX_SCOREBOARD]; /* can we send */ - qboolean state2[MAX_SCOREBOARD]; /* did we send */ + bool state1[MAX_SCOREBOARD]; /* can we send */ + bool state2[MAX_SCOREBOARD]; /* did we send */ for (i = 0, host_client = svs.clients; i < svs.maxclients; i++, host_client++) { diff --git a/libs/net/nm/net_dgrm.c b/libs/net/nm/net_dgrm.c index 2e1264075..2832b418d 100644 --- a/libs/net/nm/net_dgrm.c +++ b/libs/net/nm/net_dgrm.c @@ -102,7 +102,7 @@ static qmsg_t dgrm_message = { // FIXME: MENUCODE //extern int m_return_state; //extern int m_state; -//extern qboolean m_return_onerror; +//extern bool m_return_onerror; //extern char m_return_reason[32]; @@ -271,7 +271,7 @@ ReSendMessage (qsocket_t *sock) } -qboolean +bool Datagram_CanSendMessage (qsocket_t *sock) { if (sock->sendNext) { @@ -282,7 +282,7 @@ Datagram_CanSendMessage (qsocket_t *sock) } -__attribute__((const)) qboolean +__attribute__((const)) bool Datagram_CanSendUnreliableMessage (qsocket_t *sock) { return true; @@ -573,7 +573,7 @@ Datagram_Close (qsocket_t *sock) void -Datagram_Listen (qboolean state) +Datagram_Listen (bool state) { int i; @@ -899,7 +899,7 @@ Datagram_CheckNewConnections (void) static void -_Datagram_SearchForHosts (qboolean xmit) +_Datagram_SearchForHosts (bool xmit) { int ret; netadr_t readaddr; @@ -973,7 +973,7 @@ _Datagram_SearchForHosts (qboolean xmit) } void -Datagram_SearchForHosts (qboolean xmit) +Datagram_SearchForHosts (bool xmit) { for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) { diff --git a/libs/net/nm/net_loop.c b/libs/net/nm/net_loop.c index 168cbe23e..d7e17c898 100644 --- a/libs/net/nm/net_loop.c +++ b/libs/net/nm/net_loop.c @@ -37,7 +37,7 @@ #include "../nq/include/server.h" -qboolean localconnectpending = false; +bool localconnectpending = false; qsocket_t *loop_client = NULL; qsocket_t *loop_server = NULL; @@ -57,13 +57,13 @@ Loop_Shutdown (void) void -Loop_Listen (qboolean state) +Loop_Listen (bool state) { } void -Loop_SearchForHosts (qboolean xmit) +Loop_SearchForHosts (bool xmit) { if (!sv.active) return; @@ -239,7 +239,7 @@ Loop_SendUnreliableMessage (qsocket_t * sock, sizebuf_t *data) } -__attribute__((pure)) qboolean +__attribute__((pure)) bool Loop_CanSendMessage (qsocket_t * sock) { if (!sock->driverdata) @@ -248,7 +248,7 @@ Loop_CanSendMessage (qsocket_t * sock) } -__attribute__((const)) qboolean +__attribute__((const)) bool Loop_CanSendUnreliableMessage (qsocket_t * sock) { return true; diff --git a/libs/net/nm/net_udp.c b/libs/net/nm/net_udp.c index e960d44eb..b7b5c4d68 100644 --- a/libs/net/nm/net_udp.c +++ b/libs/net/nm/net_udp.c @@ -292,7 +292,7 @@ UDP_Shutdown (void) } void -UDP_Listen (qboolean state) +UDP_Listen (bool state) { // enable listening if (state) { diff --git a/libs/net/nm/net_vcr.c b/libs/net/nm/net_vcr.c index f997d3034..56914d34f 100644 --- a/libs/net/nm/net_vcr.c +++ b/libs/net/nm/net_vcr.c @@ -79,7 +79,7 @@ VCR_ReadNext (void) void -VCR_Listen (qboolean state) +VCR_Listen (bool state) { } @@ -136,10 +136,10 @@ VCR_SendMessage (qsocket_t * sock, sizebuf_t *data) } -qboolean +bool VCR_CanSendMessage (qsocket_t * sock) { - qboolean ret; + bool ret; long *driverdata = (long *) (char *) &sock->driverdata; if (host_time != next.time || next.op != VCR_OP_CANSENDMESSAGE @@ -161,7 +161,7 @@ VCR_Close (qsocket_t * sock) void -VCR_SearchForHosts (qboolean xmit) +VCR_SearchForHosts (bool xmit) { } diff --git a/libs/net/nm/net_wins.c b/libs/net/nm/net_wins.c index c93229ca2..b86fc4bc0 100644 --- a/libs/net/nm/net_wins.c +++ b/libs/net/nm/net_wins.c @@ -73,7 +73,7 @@ static netadr_t broadcastaddr; static unsigned long myAddr; -qboolean winsock_lib_initialized; +bool winsock_lib_initialized; int (PASCAL FAR * pWSAStartup) (WORD wVersionRequired, @@ -318,7 +318,7 @@ WINS_Shutdown (void) //============================================================================= void -WINS_Listen (qboolean state) +WINS_Listen (bool state) { // enable listening if (state) { diff --git a/libs/util/bspfile.c b/libs/util/bspfile.c index 1b0e503b5..1cb36429d 100644 --- a/libs/util/bspfile.c +++ b/libs/util/bspfile.c @@ -703,7 +703,7 @@ LoadBSPMem (void *mem, size_t mem_size, void (*cb) (const bsp_t *, void *), { bsp_t *bsp; int version; - qboolean bsp2 = false; + bool bsp2 = false; bsp = calloc (sizeof (bsp_t), 1); @@ -942,7 +942,7 @@ do { \ VISIBLE void WriteBSPFile (const bsp_t *bsp, QFile *file) { - qboolean bsp2 = ( bsp->models[0].mins[0] < -32768.0f + bool bsp2 = ( bsp->models[0].mins[0] < -32768.0f || bsp->models[0].mins[1] < -32768.0f || bsp->models[0].mins[2] < -32768.0f || bsp->models[0].mins[0] >= 32768.0f diff --git a/libs/util/cmd.c b/libs/util/cmd.c index 6997b407d..f73d38d32 100644 --- a/libs/util/cmd.c +++ b/libs/util/cmd.c @@ -209,7 +209,7 @@ Cmd_RemoveCommand (const char *name) } /* Checks for the existance of a command */ -VISIBLE qboolean +VISIBLE bool Cmd_Exists (const char *cmd_name) { cmd_function_t *cmd; diff --git a/libs/util/cvar.c b/libs/util/cvar.c index 66aaccdad..d92ca8e05 100644 --- a/libs/util/cvar.c +++ b/libs/util/cvar.c @@ -429,7 +429,7 @@ Cvar_Set (const char *var_name, const char *value) Handles variable inspection and changing from the console */ -VISIBLE qboolean +VISIBLE bool Cvar_Command (void) { cvar_t *v; diff --git a/libs/util/info.c b/libs/util/info.c index 46c4743ed..187cc2531 100644 --- a/libs/util/info.c +++ b/libs/util/info.c @@ -56,7 +56,7 @@ struct info_s { Searches for key in the "client-needed" info string list */ -VISIBLE qboolean +VISIBLE bool Info_FilterForKey (const char *key, const char **filter_list) { const char **s; diff --git a/libs/util/llist.c b/libs/util/llist.c index cd4bfba99..0809f93cb 100644 --- a/libs/util/llist.c +++ b/libs/util/llist.c @@ -50,7 +50,7 @@ llist_newnode (llist_t *list, void *data) } VISIBLE llist_t * -llist_new (void (*freedata)(void *element, void *userdata), qboolean (*cmpdata)(const void *element, const void *comparison, void *userdata), void *userdata) +llist_new (void (*freedata)(void *element, void *userdata), bool (*cmpdata)(const void *element, const void *comparison, void *userdata), void *userdata) { llist_t *new = calloc (1, sizeof (llist_t)); diff --git a/libs/util/plist.c b/libs/util/plist.c index 2c985f601..1172a354c 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -403,7 +403,7 @@ PL_ObjectAtIndex (const plitem_t *array, int index) return index >= 0 && index < arr->numvals ? arr->values[index] : NULL; } -VISIBLE qboolean +VISIBLE bool PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) { if (!item || item->type != QFDictionary || !value) { @@ -433,7 +433,7 @@ PL_D_AddObject (plitem_t *item, const char *key, plitem_t *value) return true; } -VISIBLE qboolean +VISIBLE bool PL_D_Extend (plitem_t *dstDict, plitem_t *srcDict) { if (!dstDict || dstDict->type != QFDictionary @@ -470,7 +470,7 @@ PL_D_Extend (plitem_t *dstDict, plitem_t *srcDict) return true; } -static qboolean +static bool check_array_size (plarray_t *arr, int count) { if (count > arr->maxvals) { @@ -487,7 +487,7 @@ check_array_size (plarray_t *arr, int count) return true; } -VISIBLE qboolean +VISIBLE bool PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index) { if (!array || array->type != QFArray || !item) { @@ -517,13 +517,13 @@ PL_A_InsertObjectAtIndex (plitem_t *array, plitem_t *item, int index) return true; } -VISIBLE qboolean +VISIBLE bool PL_A_AddObject (plitem_t *array, plitem_t *item) { return PL_A_InsertObjectAtIndex (array, item, -1); } -VISIBLE qboolean +VISIBLE bool PL_A_Extend (plitem_t *dstArray, plitem_t *srcArray) { if (!dstArray || dstArray->type != QFArray @@ -590,7 +590,7 @@ pl_error (pldata_t *pl, const char *fmt, ...) va_end (args); } -static qboolean +static bool pl_skipspace (pldata_t *pl, int end_ok) { while (pl->pos < pl->end) { @@ -854,8 +854,8 @@ pl_parsequotedstring (pldata_t *pl) unsigned int start = ++pl->pos; unsigned int escaped = 0; unsigned int shrink = 0; - qboolean hex = false; - qboolean long_string = false; + bool hex = false; + bool long_string = false; plitem_t *str; if (pl->ptr[pl->pos] == '"' && diff --git a/libs/util/plugin.c b/libs/util/plugin.c index 366822d88..6145afd9f 100644 --- a/libs/util/plugin.c +++ b/libs/util/plugin.c @@ -393,7 +393,7 @@ PI_LoadPlugin (const char *type, const char *name) return plugin; } -VISIBLE qboolean +VISIBLE bool PI_UnloadPlugin (plugin_t *plugin) { // Remove the plugin from the set of loaded plugins to ensure that a diff --git a/libs/util/qargs.c b/libs/util/qargs.c index d2103ab22..11e97d15c 100644 --- a/libs/util/qargs.c +++ b/libs/util/qargs.c @@ -83,7 +83,7 @@ VISIBLE int com_argc; VISIBLE const char **com_argv; const char *com_cmdline; -VISIBLE qboolean nouse = false; // 1999-10-29 +USE fix by Maddes +VISIBLE bool nouse = false; // 1999-10-29 +USE fix by Maddes /* @@ -111,7 +111,7 @@ COM_CheckParm (const char *parm) VISIBLE void COM_InitArgv (int argc, const char **argv) { - qboolean safe; + bool safe; int i, len; char *cmdline; diff --git a/libs/util/qendian.c b/libs/util/qendian.c index 9858823be..d1bfbb56f 100644 --- a/libs/util/qendian.c +++ b/libs/util/qendian.c @@ -41,9 +41,9 @@ */ #ifndef WORDS_BIGENDIAN -VISIBLE qboolean bigendien = false; +VISIBLE bool bigendien = false; #else -VISIBLE qboolean bigendien = true; +VISIBLE bool bigendien = true; #endif diff --git a/libs/util/script.c b/libs/util/script.c index fa8b51ae0..1f9d5c037 100644 --- a/libs/util/script.c +++ b/libs/util/script.c @@ -59,8 +59,8 @@ Script_Start (script_t *script, const char *file, const char *data) script->error = 0; } -VISIBLE qboolean -Script_TokenAvailable (script_t *script, qboolean crossline) +VISIBLE bool +Script_TokenAvailable (script_t *script, bool crossline) { if (script->error) { return false; @@ -98,8 +98,8 @@ Script_TokenAvailable (script_t *script, qboolean crossline) return true; } -VISIBLE qboolean -Script_GetToken (script_t *script, qboolean crossline) +VISIBLE bool +Script_GetToken (script_t *script, bool crossline) { const char *token_p; diff --git a/libs/util/sys.c b/libs/util/sys.c index a89053a6d..2ae275748 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -160,7 +160,7 @@ static __thread error_handler_t *error_handler; #ifndef _WIN32 static int do_stdin = 1; -qboolean stdin_ready; +bool stdin_ready; #endif /* The translation table between the graphical font and plain ASCII --KB */ @@ -375,7 +375,7 @@ Sys_StartTime (void) VISIBLE int64_t Sys_LongTime (void) { - static qboolean first = true; + static bool first = true; #ifdef _WIN32 # if 0 static DWORD starttime; diff --git a/libs/util/test/test-pqueue.c b/libs/util/test/test-pqueue.c index 44aceb0c8..db1bd0b14 100644 --- a/libs/util/test/test-pqueue.c +++ b/libs/util/test/test-pqueue.c @@ -165,8 +165,8 @@ dump_queue (const int *data, size_t count) return 1; } -static int true = 1; -static int false = 0; +static int true_v = 1; +static int false_v = 0; static int data[] = { 3, 2, 5, 6, 8, 1, 9 }; static int data1[] = { 3, 7, 5, 6, 8, 1, 9 }; @@ -184,18 +184,18 @@ typedef struct { } test_t; static test_t tests[] = { - { &true, 1, test_is_empty }, - { &false, 1, test_is_full }, + { &true_v, 1, test_is_empty }, + { &false_v, 1, test_is_full }, { 0, 0, test_size }, { data + 0, 1, test_insert }, { 0, 1, test_size }, - { &false, 1, test_is_empty }, - { &false, 1, test_is_full }, + { &false_v, 1, test_is_empty }, + { &false_v, 1, test_is_full }, { data + 0, 1, test_peek }, { data + 0, 1, test_remove }, - { &true, 1, test_is_empty }, - { &false, 1, test_is_full }, + { &true_v, 1, test_is_empty }, + { &false_v, 1, test_is_full }, { 0, 0, test_size }, { data + 0, 3, test_insert }, @@ -204,12 +204,12 @@ static test_t tests[] = { { data + 2, 1, test_remove }, { data + 0, 1, test_remove }, { data + 1, 1, test_remove }, - { &true, 1, test_is_empty }, + { &true_v, 1, test_is_empty }, { data + 0, SIZEOF(data), test_insert }, { 0, SIZEOF(data), test_size }, - { &false, 1, test_is_empty }, - { &true, 1, test_is_full }, + { &false_v, 1, test_is_empty }, + { &true_v, 1, test_is_full }, { 0, 0, dump_queue }, { sort1 + 2, 3, test_adjust }, { 0, 0, dump_queue }, diff --git a/libs/util/zone.c b/libs/util/zone.c index 37f54e5b1..0b4833888 100644 --- a/libs/util/zone.c +++ b/libs/util/zone.c @@ -52,7 +52,7 @@ static void Cache_FreeLow (memhunk_t *hunk, size_t new_low_hunk); static void Cache_FreeHigh (memhunk_t *hunk, size_t new_high_hunk); static void Cache_Profile_r (memhunk_t *hunk); -static qboolean Cache_FreeLRU (memhunk_t *hunk); +static bool Cache_FreeLRU (memhunk_t *hunk); #define ZONEID 0x1d4a11 #define HUNK_SENTINAL 0x1df001ed @@ -521,7 +521,7 @@ struct memhunk_s { size_t low_used; size_t high_used; size_t tempmark; - qboolean tempactive; + bool tempactive; cache_system_t cache_head[1]; } __attribute__((aligned (64))); @@ -611,7 +611,7 @@ Hunk_Check (memhunk_t *hunk) */ VISIBLE void -Hunk_Print (memhunk_t *hunk, qboolean all) +Hunk_Print (memhunk_t *hunk, bool all) { if (!hunk) { hunk = global_hunk; } //FIXME clean up callers hunkblk_t *h, *next, *endlow, *starthigh, *endhigh; @@ -1065,7 +1065,7 @@ Cache_FreeHigh (memhunk_t *hunk, size_t new_high_hunk) } } -static qboolean +static bool Cache_FreeLRU (memhunk_t *hunk) { cache_system_t *cs; diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index 61ea1d9a7..3cc910b95 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -103,7 +103,7 @@ typedef struct { typedef struct cachepic_s { char name[MAX_QPATH]; - qboolean dirty; + bool dirty; union { qpic_t pic; byte padding[sizeof (qpic_t) + 32];// for appended glpic FIXME @@ -229,7 +229,7 @@ Draw_ClearCache (int phase, void *data) } qpic_t * -gl_Draw_CachePic (const char *path, qboolean alpha) +gl_Draw_CachePic (const char *path, bool alpha) { cachepic_t *pic; int i; diff --git a/libs/video/renderer/gl/gl_lightmap.c b/libs/video/renderer/gl/gl_lightmap.c index 4bbcd40b0..d74855567 100644 --- a/libs/video/renderer/gl/gl_lightmap.c +++ b/libs/video/renderer/gl/gl_lightmap.c @@ -71,7 +71,7 @@ static unsigned *blocklights; static int bl_extents[2]; static int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH]; -qboolean gl_lightmap_modified[MAX_LIGHTMAPS]; +bool gl_lightmap_modified[MAX_LIGHTMAPS]; instsurf_t *gl_lightmap_polys; glRect_t gl_lightmap_rectchange[MAX_LIGHTMAPS]; diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index 266140346..f3059637c 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -407,7 +407,7 @@ gl_R_DrawAliasModel (entity_t e) emission[4] = {0.0, 0.0, 0.0, 1.0}; int gl_light, texture; int fb_texture = 0, used_lights = 0; - qboolean is_fullbright = false; + bool is_fullbright = false; unsigned lnum; aliashdr_t *paliashdr; dlight_t *l; diff --git a/libs/video/renderer/gl/gl_rsurf.c b/libs/video/renderer/gl/gl_rsurf.c index 242c74d77..4f34a10ca 100644 --- a/libs/video/renderer/gl/gl_rsurf.c +++ b/libs/video/renderer/gl/gl_rsurf.c @@ -500,7 +500,7 @@ gl_R_DrawBrushModel (entity_t e) float dot, radius; transform_t transform = Entity_Transform (e); msurface_t *surf; - qboolean rotated; + bool rotated; vec3_t mins, maxs; mat4f_t worldMatrix; renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, e.reg); diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index a66261294..689dfc4a5 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -60,7 +60,7 @@ GLuint gl_solidskytexture; GLuint gl_alphaskytexture; // Set to true if a valid skybox is loaded --KB -qboolean gl_skyloaded = false; +bool gl_skyloaded = false; vec5_t gl_skyvec[6][4] = { diff --git a/libs/video/renderer/gl/gl_textures.c b/libs/video/renderer/gl/gl_textures.c index 80313dcd5..5cabff506 100644 --- a/libs/video/renderer/gl/gl_textures.c +++ b/libs/video/renderer/gl/gl_textures.c @@ -76,7 +76,7 @@ typedef struct { int width, height; int bytesperpixel; // int texelformat; // eventually replace bytesperpixel - qboolean mipmap; + bool mipmap; unsigned short crc; // LordHavoc: CRC for texure validation } gltexture_t; @@ -377,8 +377,8 @@ GL_MipMap8Bit (byte *in, int width, int height) } static void -GL_Upload32 (unsigned int *data, int width, int height, qboolean mipmap, - qboolean alpha) +GL_Upload32 (unsigned int *data, int width, int height, bool mipmap, + bool alpha) { int scaled_width, scaled_height, intformat; unsigned int *scaled; @@ -458,8 +458,8 @@ GL_Upload32 (unsigned int *data, int width, int height, qboolean mipmap, If we don't, this function does nothing. */ void -GL_Upload8_EXT (const byte *data, int width, int height, qboolean mipmap, - qboolean alpha) +GL_Upload8_EXT (const byte *data, int width, int height, bool mipmap, + bool alpha) { byte *scaled; int scaled_width, scaled_height; @@ -529,8 +529,8 @@ GL_Upload8_EXT (const byte *data, int width, int height, qboolean mipmap, } void -GL_Upload8 (const byte *data, int width, int height, qboolean mipmap, - qboolean alpha) +GL_Upload8 (const byte *data, int width, int height, bool mipmap, + bool alpha) { int i, s, p; unsigned int *trans; @@ -568,7 +568,7 @@ GL_Upload8 (const byte *data, int width, int height, qboolean mipmap, int GL_LoadTexture (const char *identifier, int width, int height, const byte *data, - qboolean mipmap, qboolean alpha, int bytesperpixel) + bool mipmap, bool alpha, int bytesperpixel) { int crc, i; gltexture_t *glt; diff --git a/libs/video/renderer/gl/qfgl_ext.c b/libs/video/renderer/gl/qfgl_ext.c index f012726de..e019fcc79 100644 --- a/libs/video/renderer/gl/qfgl_ext.c +++ b/libs/video/renderer/gl/qfgl_ext.c @@ -72,7 +72,7 @@ #undef QFGL_NEED #undef QFGL_WANT -qboolean +bool GLF_FindFunctions (void) { #define QFGL_WANT(ret, name, args) \ @@ -92,7 +92,7 @@ GLF_FindFunctions (void) It takes a bit of care to be fool-proof about parsing an OpenGL extensions string. Don't be fooled by sub-strings, etc. */ -static __attribute__((pure)) qboolean +static __attribute__((pure)) bool QFGL_ParseExtensionList (const GLubyte *list, const char *name) { const char *start; @@ -120,7 +120,7 @@ QFGL_ParseExtensionList (const GLubyte *list, const char *name) return 0; } -qboolean +bool QFGL_ExtensionPresent (const char *name) { static const GLubyte *gl_extensions = NULL; diff --git a/libs/video/renderer/gl/vid_common_gl.c b/libs/video/renderer/gl/vid_common_gl.c index 296c36ae0..83e6431b5 100644 --- a/libs/video/renderer/gl/vid_common_gl.c +++ b/libs/video/renderer/gl/vid_common_gl.c @@ -84,28 +84,28 @@ int gl_filter_max = GL_LINEAR; float gldepthmin, gldepthmax; // Multitexture -qboolean gl_mtex_capable = false; +bool gl_mtex_capable = false; static int gl_mtex_tmus = 0; GLenum gl_mtex_enum; int gl_mtex_active_tmus = 0; -qboolean gl_mtex_fullbright = false; +bool gl_mtex_fullbright = false; // Combine -qboolean gl_combine_capable = false; +bool gl_combine_capable = false; int lm_src_blend, lm_dest_blend; float gl_rgb_scale = 1.0; QF_glColorTableEXT qglColorTableEXT = NULL; -qboolean gl_feature_mach64 = false; +bool gl_feature_mach64 = false; // GL_EXT_texture_filter_anisotropic -qboolean gl_Anisotropy; +bool gl_Anisotropy; static float aniso_max; float gl_aniso; // GL_ATI_pn_triangles -static qboolean TruForm; +static bool TruForm; static int tess_max; int gl_tess; @@ -943,7 +943,7 @@ GL_SetPalette (void *data, const byte *palette) unsigned int r, g, b, v; unsigned short i; unsigned int *table; - static qboolean palflag = false; + static bool palflag = false; QFile *f; static int inited_8 = 0; diff --git a/libs/video/renderer/glsl/glsl_bsp.c b/libs/video/renderer/glsl/glsl_bsp.c index 1ebc39b59..6d16857e8 100644 --- a/libs/video/renderer/glsl/glsl_bsp.c +++ b/libs/video/renderer/glsl/glsl_bsp.c @@ -95,7 +95,7 @@ static GLuint bsp_vbo; static mat4f_t bsp_vp; static GLuint skybox_tex; -static qboolean skybox_loaded; +static bool skybox_loaded; static quat_t sky_rotation[2]; static quat_t sky_velocity; static quat_t sky_fix; @@ -657,7 +657,7 @@ R_DrawBrushModel (entity_t e) mod_brush_t *brush = &model->brush; plane_t *plane; msurface_t *surf; - qboolean rotated; + bool rotated; vec3_t mins, maxs; vec4f_t org; glslbspctx_t bctx = { diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index ca11b1689..2abe50b54 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -308,7 +308,7 @@ glsl_Draw_PicFromWad (const char *name) } qpic_t * -glsl_Draw_CachePic (const char *path, qboolean alpha) +glsl_Draw_CachePic (const char *path, bool alpha) { qpic_t *p, *pic; cachepic_t *cpic; diff --git a/libs/video/renderer/glsl/qfglsl.c b/libs/video/renderer/glsl/qfglsl.c index 0e48e9354..3860b1231 100644 --- a/libs/video/renderer/glsl/qfglsl.c +++ b/libs/video/renderer/glsl/qfglsl.c @@ -71,7 +71,7 @@ #undef QFGL_NEED #undef QFGL_WANT -qboolean +bool EGLF_FindFunctions (void) { #define QFGL_WANT(ret, name, args) \ diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index 06845c912..6e4dde6c1 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -45,15 +45,15 @@ #include "r_internal.h" -qboolean r_dowarp, r_dowarpold; -qboolean r_inhibit_viewmodel; -qboolean r_force_fullscreen; -qboolean r_paused; +bool r_dowarp, r_dowarpold; +bool r_inhibit_viewmodel; +bool r_force_fullscreen; +bool r_paused; double r_realtime; double r_frametime; double r_time1; int r_lineadj; -qboolean r_active; +bool r_active; int r_init; int r_visframecount; // bumped when going to a new PVS diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 5c900a8f0..caf91dfd1 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -59,13 +59,13 @@ // only the refresh window will be updated unless these variables are flagged int scr_copytop; byte *draw_chars; // 8*8 graphic characters FIXME location -qboolean r_cache_thrash; // set if surface cache is thrashing +bool r_cache_thrash; // set if surface cache is thrashing int *r_node_visframes; //FIXME per renderer int *r_leaf_visframes; //FIXME per renderer int *r_face_visframes; //FIXME per renderer -qboolean scr_skipupdate; -static qboolean scr_initialized;// ready to draw +bool scr_skipupdate; +static bool scr_initialized;// ready to draw static framebuffer_t *fisheye_cube_map; static framebuffer_t *warp_buffer; @@ -347,7 +347,7 @@ update_vrect (void) } void -SCR_SetFullscreen (qboolean fullscreen) +SCR_SetFullscreen (bool fullscreen) { if (r_data->force_fullscreen == fullscreen) { return; diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index 3aa563a20..52d6db6fa 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -39,7 +39,7 @@ #define NUM_MIPS 4 surfcache_t *d_initial_rover; -qboolean d_roverwrapped; +bool d_roverwrapped; int d_minmip; float d_scalemip[NUM_MIPS - 1]; diff --git a/libs/video/renderer/sw/d_modech.c b/libs/video/renderer/sw/d_modech.c index 0d17c2550..69dc349bf 100644 --- a/libs/video/renderer/sw/d_modech.c +++ b/libs/video/renderer/sw/d_modech.c @@ -51,7 +51,7 @@ D_Patch (void) #ifdef USE_INTEL_ASM - static qboolean protectset8 = false; + static bool protectset8 = false; if (!protectset8) { Sys_MakeCodeWriteable ((int) D_PolysetAff8Start, diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 2a867605f..4fb553979 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -135,7 +135,7 @@ static surfcache_t * D_SCAlloc (int width, int size) { surfcache_t *new; - qboolean wrapped_this_time; + bool wrapped_this_time; if ((width < 0) || (width > 512)) // FIXME shouldn't really have a max Sys_Error ("D_SCAlloc: bad cache width %d", width); diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index 6a79f14b3..ef63a04f6 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -127,7 +127,7 @@ Draw_PicFromWad (const char *name) qpic_t * -Draw_CachePic (const char *path, qboolean alpha) +Draw_CachePic (const char *path, bool alpha) { cachepic_t *pic; int i; diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 86e13dd7b..f0e51073b 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -85,7 +85,7 @@ static aedge_t aedges[12] = { static void R_AliasSetUpTransform (entity_t ent, int trivial_accept); -qboolean +bool R_AliasCheckBBox (entity_t ent) { int i, flags, frame, numv; @@ -94,7 +94,7 @@ R_AliasCheckBBox (entity_t ent) finalvert_t *pv0, *pv1, viewpts[16]; auxvert_t *pa0, *pa1, viewaux[16]; maliasframedesc_t *pframedesc; - qboolean zclipped, zfullyclipped; + bool zclipped, zfullyclipped; unsigned int anyclip, allclip; int minz; diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index a9a42a6c3..7fc2b467a 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -46,7 +46,7 @@ typedef struct glbspctx_s { } swbspctx_t; // current entity info -qboolean insubmodel; +bool insubmodel; vec3_t r_worldmodelorg; mvertex_t *r_pcurrentvertbase; static float entity_rotation[3][3]; @@ -67,7 +67,7 @@ static btofpoly_t *pbtofpolys; static mvertex_t *pfrontenter, *pfrontexit; -static qboolean makeclippededge; +static bool makeclippededge; static void diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index fc2ad1f7e..df778f1f5 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -51,9 +51,9 @@ clipplane_t view_clipplanes[4]; medge_t *r_pedge; // FIXME used by asm -qboolean r_leftclipped, r_rightclipped; -static qboolean makeleftedge, makerightedge; -qboolean r_nearzionly; +bool r_leftclipped, r_rightclipped; +static bool makeleftedge, makerightedge; +bool r_nearzionly; int sintable[SIN_BUFFER_SIZE]; int intsintable[SIN_BUFFER_SIZE]; @@ -71,7 +71,7 @@ float r_nearzi; float r_u1, r_v1, r_lzi1; int r_ceilv1; -qboolean r_lastvertvalid; +bool r_lastvertvalid; #ifdef PIC @@ -622,7 +622,7 @@ R_RenderPoly (uint32_t render_id, msurface_t *fa, int clipflags) mvertex_t verts[2][100]; // FIXME: do real number polyvert_t pverts[100]; // FIXME: do real number, safely int vertpage, newverts, newpage, lastvert; - qboolean visible; + bool visible; mod_brush_t *brush = *(mod_brush_t **) SW_COMP (scene_sw_brush, render_id); // FIXME: clean this up and make it faster diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index b97c798a1..f2a5f3fb3 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -56,20 +56,20 @@ const byte *r_colormap; int r_numallocatededges; -qboolean r_drawpolys; -qboolean r_drawculledpolys; -qboolean r_worldpolysbacktofront; -qboolean r_recursiveaffinetriangles = true; +bool r_drawpolys; +bool r_drawculledpolys; +bool r_worldpolysbacktofront; +bool r_recursiveaffinetriangles = true; int r_pixbytes = 1; int r_outofsurfaces; int r_outofedges; -qboolean r_viewchanged; +bool r_viewchanged; int c_surf; int r_maxsurfsseen, r_maxedgesseen; static int r_cnumsurfs; -static qboolean r_surfsonstack; +static bool r_surfsonstack; int r_clipflags; static byte *r_stack_start; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 75d963d31..ae6db3ebf 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -244,7 +244,7 @@ vulkan_Draw_BlendScreen (quat_t color) } static qpic_t * -vulkan_Draw_CachePic (const char *path, qboolean alpha) +vulkan_Draw_CachePic (const char *path, bool alpha) { return Vulkan_Draw_CachePic (path, alpha, vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 20e865b5f..6915e4f7e 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -761,7 +761,7 @@ load_lmp (const char *path, vulkan_ctx_t *ctx) } qpic_t * -Vulkan_Draw_CachePic (const char *path, qboolean alpha, vulkan_ctx_t *ctx) +Vulkan_Draw_CachePic (const char *path, bool alpha, vulkan_ctx_t *ctx) { cachepic_t *cpic; drawctx_t *dctx = ctx->draw_context; diff --git a/libs/video/targets/context_sdl.c b/libs/video/targets/context_sdl.c index a2464144b..2a0851a39 100644 --- a/libs/video/targets/context_sdl.c +++ b/libs/video/targets/context_sdl.c @@ -45,7 +45,7 @@ VID_SetCaption (const char *text) } } -qboolean +bool VID_SetGamma (double gamma) { return SDL_SetGamma((float) gamma, (float) gamma, (float) gamma); diff --git a/libs/video/targets/context_win.c b/libs/video/targets/context_win.c index 207278f0a..fb037692d 100644 --- a/libs/video/targets/context_win.c +++ b/libs/video/targets/context_win.c @@ -218,12 +218,12 @@ int win_center_x, win_center_y; RECT win_rect; DEVMODE win_gdevmode; -static qboolean startwindowed = 0; -//static qboolean windowed_mode_set; +static bool startwindowed = 0; +//static bool windowed_mode_set; //static int vid_fulldib_on_focus_mode; -static qboolean force_minimized; -static qboolean force_mode_set; -static qboolean vid_mode_set; +static bool force_minimized; +static bool force_mode_set; +static bool vid_mode_set; //static HICON hIcon; @@ -327,7 +327,7 @@ Win_UpdateWindowStatus (int window_x, int window_y) } -static qboolean +static bool VID_CheckAdequateMem (int width, int height) { // there will always be enough ;) @@ -512,7 +512,7 @@ VID_CheckModedescFixup (int mode) { } -static qboolean +static bool VID_SetWindowedMode (int modenum) { #if 0 @@ -588,7 +588,7 @@ VID_SetWindowedMode (int modenum) } -static qboolean +static bool VID_SetFullDIBMode (int modenum) { #if 0 @@ -657,7 +657,7 @@ VID_SetFullDIBMode (int modenum) static void VID_RestoreOldMode (int original_mode) { - static qboolean inerror = false; + static bool inerror = false; if (inerror) return; @@ -714,7 +714,7 @@ static int VID_SetMode (int modenum, const byte *palette) { int original_mode; // FIXME, temp; - qboolean stat; + bool stat; MSG msg; HDC hdc; @@ -894,7 +894,7 @@ VID_HandlePause ================ */ static void __attribute__ ((used)) -VID_HandlePause (qboolean pause) +VID_HandlePause (bool pause) { if ((modestate == MS_WINDOWED) && _windowed_mouse) { if (pause) { @@ -1030,7 +1030,7 @@ VID_DescribeModes_f (void) { int i, lnummodes; char *pinfo; - qboolean na; + bool na; vmode_t *pv; na = false; @@ -1119,7 +1119,7 @@ Win_SetCaption (const char *text) //static WORD systemgammaramps[3][256]; static WORD currentgammaramps[3][256]; -qboolean +bool Win_SetGamma (double gamma) { int i; diff --git a/libs/video/targets/context_x11.c b/libs/video/targets/context_x11.c index 1bd5f994d..63b66222d 100644 --- a/libs/video/targets/context_x11.c +++ b/libs/video/targets/context_x11.c @@ -74,7 +74,7 @@ #include "vid_internal.h" static void (*event_handlers[LASTEvent]) (XEvent *); -qboolean oktodraw = false; +bool oktodraw = false; int x_shmeventtype; static int x_disp_ref_count = 0; @@ -92,19 +92,19 @@ Colormap x_cmap; Time x_time; Time x_mouse_time; -qboolean x_have_focus = false; +bool x_have_focus = false; #ifdef HAVE_VIDMODE static XF86VidModeModeInfo **vidmodes; static int nummodes; static int original_mode = 0; static vec3_t x_gamma = {-1, -1, -1}; -static qboolean vidmode_avail = false; +static bool vidmode_avail = false; #endif -static qboolean vidmode_active = false; +static bool vidmode_active = false; -static qboolean vid_context_created = false; +static bool vid_context_created = false; static int pos_x, pos_y; #ifdef HAVE_VIDMODE @@ -114,7 +114,7 @@ static int xss_blanking; static int xss_exposures; #endif -static qboolean accel_saved = false; +static bool accel_saved = false; static int accel_numerator; static int accel_denominator; static int accel_threshold; @@ -191,7 +191,7 @@ configure_notify (XEvent *event) VID_SetWindowSize (c->width, c->height); } -qboolean +bool X11_AddEvent (int event, void (*event_handler) (XEvent *)) { if (event >= LASTEvent) { @@ -207,7 +207,7 @@ X11_AddEvent (int event, void (*event_handler) (XEvent *)) return true; } -qboolean +bool X11_RemoveEvent (int event, void (*event_handler) (XEvent *)) { if (event >= LASTEvent) @@ -425,7 +425,7 @@ X11_SetVidMode (int width, int height) if (vid_fullscreen && vidmode_avail) { int i, dotclock; int best_mode = 0; - qboolean found_mode = false; + bool found_mode = false; XF86VidModeModeLine orig_data; XF86VidModeGetAllModeLines (x_disp, x_screen, &nummodes, @@ -605,7 +605,7 @@ X11_ForceViewPort (void) #endif } -qboolean +bool X11_SetGamma (double gamma) { #ifdef HAVE_VIDMODE diff --git a/libs/video/targets/dga_check.c b/libs/video/targets/dga_check.c index d17c647b1..bc60af5cc 100644 --- a/libs/video/targets/dga_check.c +++ b/libs/video/targets/dga_check.c @@ -69,7 +69,7 @@ Check for the presence of the XFree86-DGA X server extension */ -qboolean +bool VID_CheckDGA (Display * dpy, int *maj_ver, int *min_ver, int *hasvideo) { #ifdef HAVE_DGA @@ -125,7 +125,7 @@ VID_CheckDGA (Display * dpy, int *maj_ver, int *min_ver, int *hasvideo) Check for the presence of the XFree86-VidMode X server extension */ -qboolean +bool VID_CheckVMode (Display * dpy, int *maj_ver, int *min_ver) { #ifdef HAVE_VIDMODE diff --git a/libs/video/targets/in_win.c b/libs/video/targets/in_win.c index 261173511..9de639f8a 100644 --- a/libs/video/targets/in_win.c +++ b/libs/video/targets/in_win.c @@ -63,12 +63,12 @@ HRESULT (WINAPI * pDirectInputCreate) (HINSTANCE hinst, DWORD dwVersion, static unsigned uiWheelMessage; static unsigned mouse_buttons; static POINT current_pos; -static qboolean mouseinitialized; -static qboolean restore_spi; +static bool mouseinitialized; +static bool restore_spi; static int originalmouseparms[3], newmouseparms[3] = { 0, 0, 1 }; -static qboolean mouseparmsvalid, mouseactivatetoggle; -static qboolean mouseshowtoggle = 1; -static qboolean dinput_acquired; +static bool mouseparmsvalid, mouseactivatetoggle; +static bool mouseshowtoggle = 1; +static bool dinput_acquired; static unsigned int mstate_di; // misc locals @@ -77,10 +77,10 @@ static LPDIRECTINPUTDEVICE g_pMouse; static HINSTANCE hInstDI; -static qboolean dinput; +static bool dinput; -static qboolean vid_wassuspended = false; -static qboolean win_in_game = false; +static bool vid_wassuspended = false; +static bool win_in_game = false; typedef struct win_device_s { const char *name; @@ -506,7 +506,7 @@ IN_DeactivateMouse (void) } } -static qboolean +static bool IN_InitDInput (void) { HRESULT hr; diff --git a/libs/video/targets/in_x11.c b/libs/video/targets/in_x11.c index 2b8d547e2..310ae91c7 100644 --- a/libs/video/targets/in_x11.c +++ b/libs/video/targets/in_x11.c @@ -170,8 +170,8 @@ static cvar_t in_mouse_accel_cvar = { .value = { .type = &cexpr_int, .value = &in_mouse_accel }, }; -static qboolean dga_avail; -static qboolean dga_active; +static bool dga_avail; +static bool dga_active; static IE_mouse_event_t x11_mouse; static IE_key_event_t x11_key; static int input_grabbed = 0; @@ -191,7 +191,7 @@ static int x11_have_xi; static int x11_fd; static int x11_driver_handle = -1; static int x11_event_handler_id; -static qboolean x11_have_pointer; +static bool x11_have_pointer; static void dga_on (void) diff --git a/libs/video/targets/joy.c b/libs/video/targets/joy.c index c08174a80..827f96574 100644 --- a/libs/video/targets/joy.c +++ b/libs/video/targets/joy.c @@ -79,8 +79,8 @@ static cvar_t joy_pre_amp_cvar = { .value = { .type = &cexpr_float, .value = &joy_pre_amp }, }; -qboolean joy_found = false; -qboolean joy_active = false; +bool joy_found = false; +bool joy_active = false; struct joy_axis joy_axes[JOY_MAX_AXES]; struct joy_button joy_buttons[JOY_MAX_BUTTONS]; diff --git a/libs/video/targets/joy_win.c b/libs/video/targets/joy_win.c index 56e8f49ce..3bc2c9d13 100644 --- a/libs/video/targets/joy_win.c +++ b/libs/video/targets/joy_win.c @@ -272,7 +272,7 @@ static cvar_t joy_debug_cvar = { .value = { .type = &cexpr_int, .value = &joy_debug }, }; -qboolean joy_advancedinit, joy_haspov; +bool joy_advancedinit, joy_haspov; DWORD joy_oldbuttonstate, joy_oldpovstate; int joy_id; DWORD joy_flags; @@ -298,7 +298,7 @@ RawValuePointer (int axis) return NULL; } -static qboolean +static bool _JOY_Read (void) { memset (&ji, 0, sizeof (ji)); diff --git a/libs/video/targets/vid.c b/libs/video/targets/vid.c index 67465191f..825433180 100644 --- a/libs/video/targets/vid.c +++ b/libs/video/targets/vid.c @@ -68,7 +68,7 @@ static cvar_t vid_system_gamma_cvar = { .flags = CVAR_ARCHIVE, .value = { .type = &cexpr_int, .value = &vid_system_gamma }, }; -qboolean vid_gamma_avail; // hardware gamma availability +bool vid_gamma_avail; // hardware gamma availability VISIBLE unsigned int d_8to24table[256]; diff --git a/libs/video/targets/vid_3dfxsvga.c b/libs/video/targets/vid_3dfxsvga.c index b5e449c60..a51dd09aa 100644 --- a/libs/video/targets/vid_3dfxsvga.c +++ b/libs/video/targets/vid_3dfxsvga.c @@ -339,7 +339,7 @@ VID_SetCaption (const char *text) { } -qboolean +bool VID_SetGamma (double gamma) { return true; diff --git a/libs/video/targets/vid_fbdev.c b/libs/video/targets/vid_fbdev.c index f43b29a07..bef6149c3 100644 --- a/libs/video/targets/vid_fbdev.c +++ b/libs/video/targets/vid_fbdev.c @@ -544,7 +544,7 @@ VID_SetCaption (const char *text) { } -qboolean +bool VID_SetGamma (double gamma) { return false; diff --git a/libs/video/targets/vid_sdl_gl.c b/libs/video/targets/vid_sdl_gl.c index 79d1fc47f..b47febbaa 100644 --- a/libs/video/targets/vid_sdl_gl.c +++ b/libs/video/targets/vid_sdl_gl.c @@ -77,7 +77,7 @@ static cvar_t gl_driver_cvar = { }; static void * -QFGL_ProcAddress (const char *name, qboolean crit) +QFGL_ProcAddress (const char *name, bool crit) { void *glfunc = NULL; diff --git a/libs/video/targets/vid_svgalib.c b/libs/video/targets/vid_svgalib.c index bfd490868..cd035228a 100644 --- a/libs/video/targets/vid_svgalib.c +++ b/libs/video/targets/vid_svgalib.c @@ -478,7 +478,7 @@ VID_SetCaption (const char *text) { } -qboolean +bool VID_SetGamma (double gamma) { return false; diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 8f1cd9289..ba530fc75 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -190,7 +190,7 @@ VID_SetCaption (const char *text) } } -qboolean +bool VID_SetGamma (double gamma) { return Win_SetGamma (gamma); diff --git a/libs/video/targets/vid_win_gl.c b/libs/video/targets/vid_win_gl.c index 5e63c7fee..f8c14f31d 100644 --- a/libs/video/targets/vid_win_gl.c +++ b/libs/video/targets/vid_win_gl.c @@ -77,7 +77,7 @@ QFGL_GetProcAddress (void *handle, const char *name) } static void * -QFGL_ProcAddress (const char *name, qboolean crit) +QFGL_ProcAddress (const char *name, bool crit) { void *glfunc = NULL; diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index 53e03b82a..50decd208 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -197,7 +197,7 @@ VID_SetCaption (const char *text) } } -qboolean +bool VID_SetGamma (double gamma) { return X11_SetGamma (gamma); diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c index 9f4003667..71dd105af 100644 --- a/libs/video/targets/vid_x11_gl.c +++ b/libs/video/targets/vid_x11_gl.c @@ -140,7 +140,7 @@ QFGL_GetProcAddress (void *handle, const char *name) } static void * -QFGL_ProcAddress (const char *name, qboolean crit) +QFGL_ProcAddress (const char *name, bool crit) { void *glfunc = NULL; diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index 636b7991b..010199951 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -71,7 +71,7 @@ int XShmGetEventBase (Display *x); // for broken X11 headers static GC x_gc; -static qboolean doShm; +static bool doShm; static XShmSegmentInfo x_shminfo[2]; static int current_framebuffer; diff --git a/nq/include/client.h b/nq/include/client.h index 59deeb9f5..0114410ef 100644 --- a/nq/include/client.h +++ b/nq/include/client.h @@ -93,11 +93,11 @@ typedef struct { char demos[MAX_DEMOS][MAX_DEMONAME]; // when not playing QFile *demofile; - qboolean demorecording; int demo_capture; - qboolean demoplayback; int forcetrack; // -1 = use normal cd track - qboolean timedemo; + bool demorecording; + bool demoplayback; + bool timedemo; int td_lastframe; // to meter out one message a frame int td_startframe; // host_framecount at start double td_starttime; // realtime at second frame of timedemo @@ -150,9 +150,9 @@ typedef struct client_state_s { movestate_t movestate; chasestate_t chasestate; - qboolean paused; // Sent over by server + bool paused; // Sent over by server + bool inwater; float crouch; // Local amount for smoothing stepups - qboolean inwater; int intermission; // Don't change view angle, full screen, etc int completed_time; // Latched from time at intermission start @@ -279,7 +279,7 @@ struct entity_s CL_GetEntity (int num); extern double realtime; -extern qboolean recording; +extern bool recording; struct cvar_s; void Cvar_Info (void *data, const struct cvar_s *cvar); diff --git a/nq/include/game.h b/nq/include/game.h index 47b33f421..bf7238efc 100644 --- a/nq/include/game.h +++ b/nq/include/game.h @@ -68,8 +68,8 @@ extern int current_skill; // skill level for currently loaded level (in case // the user changes the cvar while the level is // running, this reflects the level actually in use) -extern qboolean isDedicated; -extern qboolean standard_quake; +extern bool isDedicated; +extern bool standard_quake; struct memhunk_s; void Game_Init (struct memhunk_s *hunk); diff --git a/nq/include/host.h b/nq/include/host.h index ad6376c63..5a00843f8 100644 --- a/nq/include/host.h +++ b/nq/include/host.h @@ -47,7 +47,7 @@ extern int pausable; extern int viewentity; extern int host_speeds; -extern qboolean host_initialized; // true if into command execution +extern bool host_initialized; // true if into command execution extern double host_frametime; extern int host_framecount; // incremented every frame, never reset extern int host_in_game; // input focus goes to the game @@ -67,6 +67,6 @@ void Host_EndGame (const char *message, ...) __attribute__((format(PRINTF,1,2), void Host_Frame (float time); void Host_Quit_f (void) __attribute__((noreturn)); void Host_ClientCommands (const char *fmt, ...) __attribute__((format(PRINTF,1,2))); -void Host_ShutdownServer (qboolean crash); +void Host_ShutdownServer (bool crash); #endif // __host_h diff --git a/nq/include/server.h b/nq/include/server.h index d22a9b331..f2dca7e4b 100644 --- a/nq/include/server.h +++ b/nq/include/server.h @@ -49,7 +49,7 @@ typedef struct struct client_s *clients; // [maxclients] void (*phys_client) (struct edict_s *ent, int num); int serverflags; // episode completion information - qboolean changelevel_issued; // cleared when at SV_SpawnServer + bool changelevel_issued; // cleared when at SV_SpawnServer } server_static_t; //============================================================================= @@ -58,10 +58,10 @@ typedef enum {ss_loading, ss_active} server_state_t; typedef struct { - qboolean active; // false if only a net client + bool active; // false if only a net client - qboolean paused; - qboolean loadgame; // handle connections specially + bool paused; + bool loadgame; // handle connections specially double time; @@ -100,11 +100,11 @@ typedef struct typedef struct client_s { - qboolean active; // false = client is free - qboolean spawned; // false = don't send datagrams - qboolean dropasap; // has been told to go to another level - qboolean privileged; // can execute any host command - qboolean sendsignon; // valid only before spawned + bool active; // false = client is free + bool spawned; // false = don't send datagrams + bool dropasap; // has been told to go to another level + bool privileged; // can execute any host command + bool sendsignon; // valid only before spawned double last_message; // reliable messages must be sent // periodically @@ -249,7 +249,7 @@ void SV_StartParticle (const vec3_t org, const vec3_t dir, int color, void SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, float attenuation); -void SV_DropClient (qboolean crash); +void SV_DropClient (bool crash); void SV_SendClientMessages (void); void SV_ClearDatagram (void); @@ -270,7 +270,7 @@ struct trace_s SV_PushEntity (edict_t *ent, vec3_t push); int SV_EntCanSupportJump (edict_t *ent) __attribute__((pure)); int SV_FlyMove (edict_t *ent, float time, struct trace_s *steptrace); void SV_CheckVelocity (edict_t *ent); -qboolean SV_RunThink (edict_t *ent); +bool SV_RunThink (edict_t *ent); void SV_AddGravity (edict_t *ent); void SV_FinishGravity (edict_t *ent, vec3_t move); void SV_Physics_Toss (edict_t *ent); @@ -280,8 +280,8 @@ void SV_Physics_Init_Cvars (void); void SV_ProgStartFrame (void); void SV_RunNewmis (void); -qboolean SV_CheckBottom (edict_t *ent); -qboolean SV_movestep (edict_t *ent, const vec3_t move, qboolean relink); +bool SV_CheckBottom (edict_t *ent); +bool SV_movestep (edict_t *ent, const vec3_t move, bool relink); void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg); diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index 3849adf07..4521a49db 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -201,8 +201,8 @@ typedef struct sv_data_s { edict_leaf_t *leafs; entity_state_t state; byte alpha; - qboolean sendinterval; - qboolean add_grav; + bool sendinterval; + bool add_grav; } sv_data_t; #define SVdata(e) ((sv_data_t *) ((e)->edata)) diff --git a/nq/source/cl_demo.c b/nq/source/cl_demo.c index 603a21530..2dc647d9f 100644 --- a/nq/source/cl_demo.c +++ b/nq/source/cl_demo.c @@ -489,7 +489,7 @@ CL_StartDemo (void) { dstring_t *name; int c; - qboolean neg = false; + bool neg = false; // disconnect from server CL_Disconnect (); diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index f91a3b9c6..02eacdefa 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -396,7 +396,7 @@ CL_ParseUpdate (int bits) entity_state_t *baseline; entity_state_t *state; int modnum, num, i; - qboolean forcelink; + bool forcelink; if (cls.signon == so_begin) { // first update is the final signon stage diff --git a/nq/source/game.c b/nq/source/game.c index 7dd438660..e39e9ada4 100644 --- a/nq/source/game.c +++ b/nq/source/game.c @@ -38,7 +38,7 @@ #include "nq/include/game.h" #include "nq/include/server.h" -qboolean standard_quake = false; +bool standard_quake = false; float registered; static cvar_t registered_cvar = { diff --git a/nq/source/host.c b/nq/source/host.c index e6db77457..f155d2699 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -64,7 +64,7 @@ static plugin_list_t server_plugin_list[] = { SERVER_PLUGIN_LIST }; -qboolean host_initialized; // true if into command execution +bool host_initialized; // true if into command execution quakeparms_t host_parms; @@ -298,7 +298,7 @@ void Host_Error (const char *error, ...) { static dstring_t *str; - static qboolean inerror = false; + static bool inerror = false; va_list argptr; if (inerror) @@ -481,7 +481,7 @@ Host_ClientCommands (const char *fmt, ...) if (crash = true), don't bother sending signofs */ void -SV_DropClient (qboolean crash) +SV_DropClient (bool crash) { client_t *client; unsigned i; @@ -540,7 +540,7 @@ SV_DropClient (qboolean crash) This happens only at the end of a game, not between levels */ void -Host_ShutdownServer (qboolean crash) +Host_ShutdownServer (bool crash) { byte message[4]; double start; @@ -974,7 +974,7 @@ Host_Init (void) void Host_Shutdown (void *data) { - static qboolean isdown = false; + static bool isdown = false; if (isdown) { printf ("recursive shutdown\n"); diff --git a/nq/source/host_cmd.c b/nq/source/host_cmd.c index e6c8cf5c1..07d56104e 100644 --- a/nq/source/host_cmd.c +++ b/nq/source/host_cmd.c @@ -161,7 +161,7 @@ Host_Notarget_f (void) SV_ClientPrintf ("notarget ON\n"); } -qboolean noclip_anglehack; +bool noclip_anglehack; static void Host_Noclip_f (void) @@ -786,14 +786,14 @@ Host_Version_f (void) } static void -Host_Say (qboolean teamonly) +Host_Say (bool teamonly) { client_t *client; client_t *save; unsigned j; char *p; char text[64]; - qboolean fromServer = false; + bool fromServer = false; if (cmd_source == src_command) { if (net_is_dedicated) { @@ -1107,7 +1107,7 @@ Host_Kick_f (void) const char *message = NULL; client_t *save; unsigned i; - qboolean byNumber = false; + bool byNumber = false; if (cmd_source == src_command) { if (!sv.active) { diff --git a/nq/source/sv_cl_phys.c b/nq/source/sv_cl_phys.c index 20e5ee784..373f3f02c 100644 --- a/nq/source/sv_cl_phys.c +++ b/nq/source/sv_cl_phys.c @@ -83,7 +83,7 @@ SV_CheckStuck (edict_t *ent) Sys_MaskPrintf (SYS_dev, "player is stuck.\n"); } -static qboolean +static bool SV_CheckWater (edict_t *ent) { int cont; diff --git a/nq/source/sv_main.c b/nq/source/sv_main.c index 32315d6f5..b68af9659 100644 --- a/nq/source/sv_main.c +++ b/nq/source/sv_main.c @@ -774,7 +774,7 @@ SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) MSG_WriteByte (msg, SVdata (ent)->alpha); //for now, weaponalpha = client entity alpha } -static qboolean +static bool SV_SendClientDatagram (client_t *client) { byte buf[MAX_DATAGRAM]; diff --git a/nq/source/sv_move.c b/nq/source/sv_move.c index cb94c1c89..229307b57 100644 --- a/nq/source/sv_move.c +++ b/nq/source/sv_move.c @@ -44,7 +44,7 @@ int c_yes, c_no; Returns false if any part of the bottom of the entity is off an edge that is not a staircase. */ -qboolean +bool SV_CheckBottom (edict_t *ent) { float mid, bottom; @@ -113,8 +113,8 @@ SV_CheckBottom (edict_t *ent) possible, no move is done, false is returned, and pr_global_struct->trace_normal is set to the normal of the blocking wall */ -qboolean -SV_movestep (edict_t *ent, const vec3_t move, qboolean relink) +bool +SV_movestep (edict_t *ent, const vec3_t move, bool relink) { edict_t *enemy; float dz; @@ -222,7 +222,7 @@ SV_movestep (edict_t *ent, const vec3_t move, qboolean relink) Turns to the movement direction, and walks the current distance if facing it. */ -static qboolean +static bool SV_StepDirection (edict_t *ent, float yaw, float dist) { float delta; @@ -331,7 +331,7 @@ SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) SV_FixCheckBottom (actor); } -static qboolean +static bool SV_CloseEnough (edict_t *ent, edict_t *goal, float dist) { int i; diff --git a/nq/source/sv_phys.c b/nq/source/sv_phys.c index 6d8d1cecb..ed26fcad5 100644 --- a/nq/source/sv_phys.c +++ b/nq/source/sv_phys.c @@ -162,7 +162,7 @@ SV_CheckVelocity (edict_t *ent) in a frame. Not used for pushmove objects, because they must be exact. Returns false if the entity removed itself. */ -qboolean +bool SV_RunThink (edict_t *ent) { float thinktime; @@ -450,7 +450,7 @@ SV_PushEntity (edict_t *ent, vec3_t push) return trace; } -static qboolean +static bool SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) { float solid_save; @@ -805,7 +805,7 @@ SV_Physics_Toss (edict_t *ent) static void SV_Physics_Step (edict_t *ent) { - qboolean hitsound; + bool hitsound; // freefall if not on ground if (!((int) SVfloat (ent, flags) & (FL_ONGROUND | FL_FLY | FL_SWIM))) { diff --git a/nq/source/sv_pr_cmds.c b/nq/source/sv_pr_cmds.c index dfc0552fd..63c6fd3f0 100644 --- a/nq/source/sv_pr_cmds.c +++ b/nq/source/sv_pr_cmds.c @@ -144,7 +144,7 @@ PF_setorigin (progs_t *pr, void *data) static void SetMinMaxSize (progs_t *pr, edict_t *e, const vec3_t min, const vec3_t max, - qboolean rotate) + bool rotate) { float a; float bounds[2][3]; diff --git a/nq/source/sv_user.c b/nq/source/sv_user.c index f1470146d..c2473fabd 100644 --- a/nq/source/sv_user.c +++ b/nq/source/sv_user.c @@ -99,7 +99,7 @@ float *angles; float *origin; float *velocity; -qboolean onground; +bool onground; usercmd_t cmd; @@ -533,7 +533,7 @@ SV_ReadClientMove (usercmd_t *move) Returns false if the client should be killed */ -static qboolean +static bool SV_ReadClientMessage (void) { int cmd, ret; diff --git a/nq/source/sys_sdl.c b/nq/source/sys_sdl.c index 21a850023..b99dba284 100644 --- a/nq/source/sys_sdl.c +++ b/nq/source/sys_sdl.c @@ -59,7 +59,7 @@ #endif int qf_sdl_link; -qboolean isDedicated = false; +bool isDedicated = false; static void startup (void) diff --git a/nq/source/sys_unix.c b/nq/source/sys_unix.c index bcf8b801f..5a6e350c7 100644 --- a/nq/source/sys_unix.c +++ b/nq/source/sys_unix.c @@ -52,7 +52,7 @@ #include "nq/include/client.h" #include "nq/include/host.h" -qboolean isDedicated = false; +bool isDedicated = false; static void shutdown_f (void *data) diff --git a/nq/source/sys_unixd.c b/nq/source/sys_unixd.c index b444eb29b..e23a713a0 100644 --- a/nq/source/sys_unixd.c +++ b/nq/source/sys_unixd.c @@ -50,7 +50,7 @@ #include "nq/include/host.h" -qboolean isDedicated = true; +bool isDedicated = true; static void shutdown_f (void *data) diff --git a/nq/source/sys_win.c b/nq/source/sys_win.c index 99cb143dc..439458f7d 100644 --- a/nq/source/sys_win.c +++ b/nq/source/sys_win.c @@ -39,7 +39,7 @@ #include "nq/include/client.h" #include "nq/include/host.h" -qboolean isDedicated = false; +bool isDedicated = false; #define MINIMUM_WIN_MEMORY 0x0880000 #define MAXIMUM_WIN_MEMORY 0x1000000 @@ -49,8 +49,8 @@ qboolean isDedicated = false; #define PAUSE_SLEEP 50 // sleep time on pause or minimization #define NOT_FOCUS_SLEEP 20 // sleep time when not focus -qboolean ActiveApp, Minimized; -qboolean WinNT; +bool ActiveApp, Minimized; +bool WinNT; static double pfreq; static int lowshift; diff --git a/nq/source/sys_wind.c b/nq/source/sys_wind.c index 964e825bf..8ab700325 100644 --- a/nq/source/sys_wind.c +++ b/nq/source/sys_wind.c @@ -36,7 +36,7 @@ #include "nq/include/host.h" -qboolean isDedicated = true; +bool isDedicated = true; static void shutdown_f (void *data) diff --git a/nq/source/world.c b/nq/source/world.c index 6c76e7962..081cb28b1 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -443,7 +443,7 @@ SV_FindTouchedLeafs (edict_t *ent, int node_id) } void -SV_LinkEdict (edict_t *ent, qboolean touch_triggers) +SV_LinkEdict (edict_t *ent, bool touch_triggers) { areanode_t *node; diff --git a/qtv/include/client.h b/qtv/include/client.h index 1c130fcd0..fe0cb5cba 100644 --- a/qtv/include/client.h +++ b/qtv/include/client.h @@ -50,7 +50,7 @@ typedef struct client_s { backbuf_t backbuf; sizebuf_t datagram; byte datagram_buf[MAX_DATAGRAM]; - qboolean send_message; + bool send_message; frame_t frames[UPDATE_BACKUP]; entity_state_t packet_entities[UPDATE_BACKUP][MAX_PACKET_ENTITIES]; diff --git a/qtv/include/server.h b/qtv/include/server.h index 624fa82cf..8517a1672 100644 --- a/qtv/include/server.h +++ b/qtv/include/server.h @@ -52,7 +52,7 @@ typedef struct player_s { typedef struct frame_s { int delta_sequence; - qboolean invalid; + bool invalid; packet_players_t players; packet_entities_t entities; } frame_t; diff --git a/qtv/source/client.c b/qtv/source/client.c index 26eda3b92..ff59fa443 100644 --- a/qtv/source/client.c +++ b/qtv/source/client.c @@ -529,7 +529,7 @@ client_parse_message (client_t *cl) usercmd_t oldest, oldcmd, newcmd; byte checksum, calculatedChecksum; int checksumIndex, seq_hash; - qboolean move_issued = false; + bool move_issued = false; // make sure the reply sequence number matches the incoming // sequence number @@ -742,7 +742,7 @@ int numnails; int nailcount; static void -emit_nails (sizebuf_t *msg, qboolean recorder) +emit_nails (sizebuf_t *msg, bool recorder) { byte *buf; // [48 bits] xyzpy 12 12 12 4 8 int n, p, x, y, z, yaw; @@ -784,7 +784,7 @@ emit_nails (sizebuf_t *msg, qboolean recorder) #endif static void write_delta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, - qboolean force)//, int stdver) + bool force)//, int stdver) { int bits, i; float miss; diff --git a/qw/include/cl_cam.h b/qw/include/cl_cam.h index 0fbb1c0e7..cd7d7aeb2 100644 --- a/qw/include/cl_cam.h +++ b/qw/include/cl_cam.h @@ -44,8 +44,8 @@ extern int ideal_track; void Cam_Lock (int playernum); int Cam_TrackNum (void) __attribute__((pure)); -qboolean Cam_DrawViewModel(void) __attribute__((pure)); -qboolean Cam_DrawPlayer(int playernum) __attribute__((pure)); +bool Cam_DrawViewModel(void) __attribute__((pure)); +bool Cam_DrawPlayer(int playernum) __attribute__((pure)); void Cam_Track(usercmd_t *cmd); void Cam_FinishMove(usercmd_t *cmd); void Cam_Reset(void); diff --git a/qw/include/cl_chat.h b/qw/include/cl_chat.h index 2a26c075a..585c21b93 100644 --- a/qw/include/cl_chat.h +++ b/qw/include/cl_chat.h @@ -33,7 +33,7 @@ typedef struct ignore_s { const char *lastname; } ignore_t; -qboolean CL_Chat_Allow_Message (const char *str); +bool CL_Chat_Allow_Message (const char *str); void CL_Chat_User_Disconnected (int uid); void CL_Chat_Check_Name (const char *name, int slot); void CL_Chat_Flush_Ignores (void); diff --git a/qw/include/cl_ents.h b/qw/include/cl_ents.h index 23398273d..6aef9b6d6 100644 --- a/qw/include/cl_ents.h +++ b/qw/include/cl_ents.h @@ -33,11 +33,11 @@ void CL_SetSolidPlayers (int playernum); void CL_ClearPredict (void); -void CL_SetUpPlayerPrediction(qboolean dopred); +void CL_SetUpPlayerPrediction(bool dopred); void CL_ClearEnts (void); void CL_EmitEntities (void); void CL_ClearProjectiles (void); -void CL_ParsePacketEntities (qboolean delta); +void CL_ParsePacketEntities (bool delta); void CL_SetSolidEntities (void); void CL_ParsePlayerinfo (void); void CL_Ents_Init (void); diff --git a/qw/include/cl_main.h b/qw/include/cl_main.h index 9ed6667d9..1caf66067 100644 --- a/qw/include/cl_main.h +++ b/qw/include/cl_main.h @@ -41,7 +41,7 @@ void CL_EstablishConnection (const char *host); void CL_Disconnect (void); void CL_Disconnect_f (void); void CL_NextDemo (void); -qboolean CL_DemoBehind(void); +bool CL_DemoBehind(void); void CL_BeginServerConnect(void); diff --git a/qw/include/cl_parse.h b/qw/include/cl_parse.h index b624dd0d3..9c67e6aa9 100644 --- a/qw/include/cl_parse.h +++ b/qw/include/cl_parse.h @@ -50,8 +50,8 @@ int CL_CalcNet (void); void CL_ParseServerMessage (void); void CL_ParseClientdata (void); void CL_NewTranslation (int slot, struct skin_s *skin); -qboolean CL_CheckOrDownloadFile (const char *filename); -qboolean CL_IsUploading(void) __attribute__((pure)); +bool CL_CheckOrDownloadFile (const char *filename); +bool CL_IsUploading(void) __attribute__((pure)); void CL_NextUpload(void); void CL_FinishDownload (void); void CL_FailDownload (void); diff --git a/qw/include/cl_pred.h b/qw/include/cl_pred.h index 4136e9abd..e906f12a5 100644 --- a/qw/include/cl_pred.h +++ b/qw/include/cl_pred.h @@ -32,7 +32,7 @@ void CL_Prediction_Init_Cvars (void); void CL_PredictMove (void); -void CL_PredictUsercmd (player_state_t *from, player_state_t *to, usercmd_t *u, qboolean spectator); +void CL_PredictUsercmd (player_state_t *from, player_state_t *to, usercmd_t *u, bool spectator); #endif diff --git a/qw/include/client.h b/qw/include/client.h index b13125acf..2dd37c878 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -79,7 +79,7 @@ typedef struct { // reflects performing the // usercmd packet_entities_t packet_entities; - qboolean invalid; // true if the packet_entities delta was invalid + bool invalid; // true if the packet_entities delta was invalid } frame_t; #define MAX_DEMOS 8 @@ -135,16 +135,16 @@ typedef struct { char demos[MAX_DEMOS][MAX_DEMONAME]; // when not playing QFile *demofile; - qboolean demorecording; + bool demorecording; int demo_capture; - qboolean demoplayback; - qboolean demoplayback2; - qboolean findtrack; + bool demoplayback; + bool demoplayback2; + bool findtrack; int lastto; int lasttype; int prevtime; double basetime; - qboolean timedemo; + bool timedemo; double td_lastframe; // to meter out one message a frame int td_startframe; // host_framecount at start double td_starttime; // realtime at second frame of timedemo @@ -198,9 +198,9 @@ typedef struct client_state_s { movestate_t movestate; chasestate_t chasestate; - qboolean paused; // Sent over by server + bool paused; // Sent over by server float crouch; // Local amount for smoothing stepups - qboolean inwater; + bool inwater; int intermission; // Don't change view angle, full screen, etc int completed_time; // Latched from time at intermission start @@ -278,7 +278,7 @@ extern client_state_t cl; extern entity_t cl_entities[512]; extern byte cl_entity_valid[2][512]; -extern qboolean nomaster; +extern bool nomaster; extern char *server_version; // version of server we connected to extern double realtime; diff --git a/qw/include/server.h b/qw/include/server.h index 44f57e10d..a5d0be5f8 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -59,7 +59,7 @@ typedef enum { // initializing (precache commands, static sounds / objects, etc) typedef struct { - qboolean active; // false when server is going down + bool active; // false when server is going down server_state_t state; // precache commands are valid only during load double time; @@ -67,7 +67,7 @@ typedef struct { int lastcheck; // used by PF_checkclient double lastchecktime; // for monster ai - qboolean paused; // are we paused? + bool paused; // are we paused? //check player/eyes models for hacks unsigned int model_player_checksum; @@ -142,7 +142,7 @@ typedef struct { double senttime; float ping_time; vec3_t playerpositions[MAX_CLIENTS]; - qboolean playerpresent[MAX_CLIENTS]; + bool playerpresent[MAX_CLIENTS]; packet_entities_t entities; packet_players_t players; } client_frame_t; @@ -183,17 +183,17 @@ typedef enum { typedef struct client_s { sv_client_state_t state; int ping; // fake ping for server clients - qboolean prespawned; - qboolean spawned; + bool prespawned; + bool spawned; int spectator; // non-interactive - qboolean sendinfo; // at end of frame, send info to all + bool sendinfo; // at end of frame, send info to all // this prevents malicious multiple // broadcasts float lastnametime; // time of last name change int lastnamecount; // time of last name change - qboolean drop; // lose this guy next opportunity + bool drop; // lose this guy next opportunity int lossage; // loss percentage int userid; // identifying number @@ -223,7 +223,7 @@ typedef struct client_s { char stufftext_buf[MAX_STUFFTEXT]; double connection_started; // or time of disconnect for zombies - qboolean send_message; // set on frames a datagram arived on + bool send_message; // set on frames a datagram arived on //antilag stuff laggedentinfo_t laggedents[MAX_CLIENTS]; @@ -254,7 +254,7 @@ typedef struct client_s { struct dstring_s *uploadfn; int upload_started; netadr_t snap_from; - qboolean remote_snap; + bool remote_snap; //===== NETWORK ============ int chokecount; @@ -271,7 +271,7 @@ typedef struct client_s { // getting kicked off by the server operator // a program error, like an overflowed reliable buffer -extern qboolean rcon_from_user; // current command is a from a user +extern bool rcon_from_user; // current command is a from a user //============================================================================ @@ -503,9 +503,8 @@ void SV_FullClientUpdateToClient (client_t *client, backbuf_t *backbuf); int SV_ModelIndex (const char *name) __attribute__((pure)); -qboolean SV_CheckBottom (struct edict_s *ent); -qboolean SV_movestep (struct edict_s *ent, const vec3_t move, - qboolean relink); +bool SV_CheckBottom (struct edict_s *ent); +bool SV_movestep (struct edict_s *ent, const vec3_t move, bool relink); void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg); @@ -517,7 +516,7 @@ void SV_SaveSpawnparms (void); void SV_Physics_Client (struct edict_s *ent); void SV_PreRunCmd (void); -void SV_RunCmd (usercmd_t *ucmd, qboolean inside); +void SV_RunCmd (usercmd_t *ucmd, bool inside); void SV_PostRunCmd (void); void SV_SetupUserCommands (void); void SV_ExecuteUserCommand (const char *s); @@ -547,7 +546,7 @@ void SV_Physics_Init_Cvars (void); void SV_CheckVelocity (struct edict_s *ent); void SV_AddGravity (struct edict_s *ent); void SV_FinishGravity (struct edict_s *ent, vec3_t move); -qboolean SV_RunThink (struct edict_s *ent); +bool SV_RunThink (struct edict_s *ent); void SV_Physics_Toss (struct edict_s *ent); void SV_RunNewmis (void); void SV_SetMoveVars(void); @@ -663,7 +662,7 @@ extern int fp_messages; extern int fp_persecond; extern int fp_secondsdead; extern int pausable; -extern qboolean nouse; +extern bool nouse; extern char fp_msg[255]; diff --git a/qw/include/sv_progs.h b/qw/include/sv_progs.h index 47e6b1198..e50ff3b0e 100644 --- a/qw/include/sv_progs.h +++ b/qw/include/sv_progs.h @@ -207,7 +207,7 @@ typedef struct sv_data_s { link_t area; ///< linked to a division node or leaf edict_leaf_t *leafs; entity_state_t state; - qboolean add_grav; + bool add_grav; } sv_data_t; #define SVdata(e) ((sv_data_t *) ((e)->edata)) diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 02cc75b8d..bf6683a64 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -107,11 +107,11 @@ static cvar_t cl_camera_maxyaw_cvar = { }; static vec3_t desired_position; // where the camera wants to be -static qboolean locked = false; +static bool locked = false; static int oldbuttons; double cam_lastviewtime; -qboolean cam_forceview; +bool cam_forceview; vec3_t cam_viewangles; int spec_track = 0; // player# of who we are tracking @@ -148,7 +148,7 @@ vectoangles (vec3_t vec, vec3_t ang) } // returns true if weapon model should be drawn in camera mode -qboolean +bool Cam_DrawViewModel (void) { if (cl.viewstate.chase && chase_active) @@ -163,7 +163,7 @@ Cam_DrawViewModel (void) } // returns true if we should draw this player, we don't if we are chase camming -qboolean +bool Cam_DrawPlayer (int playernum) { if (playernum == cl.playernum) { // client player @@ -243,7 +243,7 @@ Cam_DoTrace (vec4f_t vec1, vec3_t vec2)//FIXME vec2 type // Returns distance or 9999 if invalid for some reason static float Cam_TryFlyby (player_state_t * self, player_state_t * player, vec3_t vec, - qboolean checkvis) + bool checkvis) { float len; trace_t trace; @@ -275,7 +275,7 @@ Cam_TryFlyby (player_state_t * self, player_state_t * player, vec3_t vec, } // Is player visible? -static qboolean +static bool Cam_IsVisible (player_state_t *player, vec3_t vec) { float d; @@ -292,7 +292,7 @@ Cam_IsVisible (player_state_t *player, vec3_t vec) return (d > 16.0); } -static qboolean +static bool InitFlyby (player_state_t * self, player_state_t * player, int checkvis) { float f, max; diff --git a/qw/source/cl_chat.c b/qw/source/cl_chat.c index 81e9c8b4b..ed5569fe4 100644 --- a/qw/source/cl_chat.c +++ b/qw/source/cl_chat.c @@ -60,13 +60,13 @@ CL_Ignore_Free (void *ele, void *unused) free (ig); } -static qboolean +static bool CL_Ignore_Compare (const void *ele, const void *cmp, void *unused) { return *(int *)cmp == ((ignore_t *) ele)->uid; } -static qboolean +static bool isc_iterator (ignore_t *ig, llist_node_t *node) { if (cl.players[ig->slot].userid != ig->uid) // We got out of sync somehow @@ -80,14 +80,14 @@ CL_Ignore_Sanity_Check (void) llist_iterate (ignore_list, LLIST_ICAST (isc_iterator)); } -static qboolean live_iterator (ignore_t *ig, llist_node_t *node) +static bool live_iterator (ignore_t *ig, llist_node_t *node) { Sys_Printf ("%5i - %s\n", ig->uid, Info_ValueForKey (cl.players[ig->slot].userinfo, "name")); return true; } -static qboolean dead_iterator (ignore_t *ig, llist_node_t *node) +static bool dead_iterator (ignore_t *ig, llist_node_t *node) { Sys_Printf ("%s\n", ig->lastname); return true; @@ -158,9 +158,9 @@ CL_Unignore_f (void) */ static const char *g_cam_str; static dstring_t *g_cam_test; -static qboolean g_cam_allowed; +static bool g_cam_allowed; -static qboolean cam_iterator (ignore_t *ig, llist_node_t *node) +static bool cam_iterator (ignore_t *ig, llist_node_t *node) { if (cl.players[ig->slot].userid != ig->uid) { // We got out of sync somehow llist_remove (node); @@ -174,7 +174,7 @@ static qboolean cam_iterator (ignore_t *ig, llist_node_t *node) return true; } -qboolean +bool CL_Chat_Allow_Message (const char *str) { g_cam_str = str; @@ -206,7 +206,7 @@ CL_Chat_User_Disconnected (int uid) static const char *g_ccn_name; static ignore_t *g_ccn_found; -static qboolean ccn_iterator (ignore_t *ig, llist_node_t *node) +static bool ccn_iterator (ignore_t *ig, llist_node_t *node) { if (!strcmp (ig->lastname, g_ccn_name)) { g_ccn_found = ig; diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index ad84c77f8..a8f454410 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -62,7 +62,7 @@ static struct predicted_player { int flags; - qboolean active; + bool active; vec3_t origin; // predicted origin } predicted_players[MAX_CLIENTS]; @@ -204,12 +204,12 @@ copy_state (packet_entities_t *newp, packet_entities_t *oldp, int newindex, } void -CL_ParsePacketEntities (qboolean delta) +CL_ParsePacketEntities (bool delta) { byte from; int oldindex, newindex, newnum, oldnum, oldpacket, word; packet_entities_t *oldp, *newp, dummy; - qboolean full; + bool full; cl.prev_sequence = cl.link_sequence; cl.link_sequence = cls.netchan.incoming_sequence; @@ -584,7 +584,7 @@ CL_ClearPredict (void) This sets up the first phase. */ void -CL_SetUpPlayerPrediction (qboolean dopred) +CL_SetUpPlayerPrediction (bool dopred) { double playertime; frame_t *frame; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index b1857f090..7a4be0705 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -404,7 +404,7 @@ CL_LinkPlayers (void) player_info_t *player; player_state_t exact; player_state_t *state; - qboolean clientplayer; + bool clientplayer; vec3_t ang = {0, 0, 0}; vec4f_t org; diff --git a/qw/source/cl_input.c b/qw/source/cl_input.c index f95e316bf..7096948ae 100644 --- a/qw/source/cl_input.c +++ b/qw/source/cl_input.c @@ -234,7 +234,7 @@ CL_SendCmd (void) { byte data[128]; int checksumIndex, lost, seq_hash, frame; - qboolean dontdrop; // FIXME: needed without cl_c2sImpulseBackup? + bool dontdrop; // FIXME: needed without cl_c2sImpulseBackup? sizebuf_t buf; usercmd_t *cmd, *oldcmd; diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 8a07c30d5..f6ada55eb 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -130,7 +130,7 @@ static plugin_list_t client_plugin_list[] = { // we need to declare some mouse variables here, because the menu system // references them even when on a unix system. -qboolean noclip_anglehack; // remnant from old quake +bool noclip_anglehack; // remnant from old quake cbuf_t *cl_cbuf; cbuf_t *cl_stbuf; @@ -344,7 +344,7 @@ static cvar_t cl_fb_players_cvar = { .value = { .type = &cexpr_float, .value = &cl_fb_players }, }; -static qboolean allowremotecmd = true; +static bool allowremotecmd = true; /* info mirrors */ char *password; @@ -422,8 +422,8 @@ entity_state_t cl_baselines[MAX_EDICTS]; double connect_time = -1; // for connection retransmits quakeparms_t host_parms; -qboolean host_initialized; // true if into command execution -qboolean nomaster; +bool host_initialized; // true if into command execution +bool nomaster; double host_frametime; double realtime; // without any filtering or bounding @@ -1415,7 +1415,7 @@ CL_SetState (cactive_t state) static void CL_Shutdown (void *data) { - static qboolean isdown = false; + static bool isdown = false; if (isdown) { printf ("recursive shutdown\n"); @@ -1687,7 +1687,7 @@ Host_EndGame (const char *message, ...) void Host_Error (const char *error, ...) { - static qboolean inerror = false; + static bool inerror = false; va_list argptr; if (inerror) diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index e3db33e5e..6e999d26c 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -210,7 +210,7 @@ CL_CalcNet (void) Returns true if the file exists, otherwise it attempts to start a download from the server. */ -qboolean +bool CL_CheckOrDownloadFile (const char *filename) { QFile *f; @@ -694,7 +694,7 @@ CL_StartUpload (byte * data, int size) CL_NextUpload (); } -qboolean +bool CL_IsUploading (void) { if (upload_data) @@ -734,7 +734,7 @@ CL_ParseServerData (void) { const char *str; int protover; - //FIXME qboolean cflag = false; + //FIXME bool cflag = false; Sys_MaskPrintf (SYS_dev, "Serverdata packet received.\n"); diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index d1219821d..2dbf45249 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -64,7 +64,7 @@ static cvar_t cl_pushlatency_cvar = { void CL_PredictUsercmd (player_state_t *from, player_state_t *to, usercmd_t *u, - qboolean clientplayer) + bool clientplayer) { if (!clientplayer) { if (VectorIsZero (from->pls.es.velocity)) { diff --git a/qw/source/cl_sys_win.c b/qw/source/cl_sys_win.c index fae730cfc..959a3b58a 100644 --- a/qw/source/cl_sys_win.c +++ b/qw/source/cl_sys_win.c @@ -44,7 +44,7 @@ // minimization #define NOT_FOCUS_SLEEP 20 // sleep time when not focus -qboolean ActiveApp, Minimized, WinNT; +bool ActiveApp, Minimized, WinNT; HWND hwnd_dialog; // startup dialog box diff --git a/qw/source/master.c b/qw/source/master.c index f8da82e2b..9cf03e390 100644 --- a/qw/source/master.c +++ b/qw/source/master.c @@ -161,12 +161,12 @@ typedef struct sockaddr_in msghdr_t; typedef struct { struct sockaddr_in addr; time_t updated; - qboolean notimeout; + bool notimeout; } server_t; static int QW_AddHeartbeat (server_t **servers_p, int slen, - struct sockaddr_in *addr, const char *buf, qboolean notimeout) + struct sockaddr_in *addr, const char *buf, bool notimeout) { server_t *servers = *servers_p; int freeslot = -1; diff --git a/qw/source/pmovetst.c b/qw/source/pmovetst.c index f545f7904..3dba93e1f 100644 --- a/qw/source/pmovetst.c +++ b/qw/source/pmovetst.c @@ -161,7 +161,7 @@ PM_PointContents (const vec3_t p) Returns false if the given player position is not valid (in solid) */ -qboolean +bool PM_TestPlayerPosition (const vec3_t pos) { hull_t *hull; diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index d48ae705f..5cefe76d7 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -58,7 +58,7 @@ #include "qw/include/sv_qtv.h" #include "qw/include/sv_recorder.h" -qboolean sv_allow_cheats; +bool sv_allow_cheats; int fp_messages = 4, fp_persecond = 4, fp_secondsdead = 10; char fp_msg[255] = { 0 }; @@ -72,7 +72,7 @@ static cvar_t sv_leetnickmatch_cvar = { .value = { .type = &cexpr_int, .value = &sv_leetnickmatch }, }; -static qboolean +static bool match_char (char a, char b) { a = tolower ((byte) sys_char_map[(byte) a]); @@ -272,7 +272,7 @@ SV_Fraglogfile_f (void) Sets host_client and sv_player to the player with idnum Cmd_Argv (1) */ -static qboolean +static bool SV_SetPlayer (void) { client_t *cl; @@ -631,7 +631,7 @@ SV_Punish (int mode) { int i; double mins = 0.5; - qboolean all = false, done = false; + bool all = false, done = false; client_t *cl = 0; dstring_t *text = dstring_new(); const char *cmd = 0; diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index 7ee4f4d4e..2996c149a 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -56,7 +56,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static QFile *demo_file; static byte *demo_mfile; -static qboolean demo_disk; +static bool demo_disk; static dstring_t *demo_name; // filename of mvd static dstring_t *demo_text; // filename of description file static void *demo_dest; @@ -334,7 +334,7 @@ SV_Cancel_f (void) SV_Stop (2); } -static qboolean +static bool SV_InitRecord (void) { if (!USECACHE) { @@ -783,7 +783,7 @@ Dem_Team (int num) { int i; static const char *lastteam[2]; - qboolean first = true; + bool first = true; client_t *client; static int index = 0; const char *team; diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index 83768fe84..d52401298 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -113,7 +113,7 @@ int numnails; int nailcount; -static qboolean +static bool SV_AddNailUpdate (edict_t *ent) { if (SVfloat (ent, modelindex) != sv_nailmodel @@ -127,7 +127,7 @@ SV_AddNailUpdate (edict_t *ent) } static void -SV_EmitNailUpdate (sizebuf_t *msg, qboolean recorder) +SV_EmitNailUpdate (sizebuf_t *msg, bool recorder) { byte *buf; // [48 bits] xyzpy 12 12 12 4 8 int n, p, x, y, z, yaw; @@ -175,7 +175,7 @@ SV_EmitNailUpdate (sizebuf_t *msg, qboolean recorder) */ static void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, - qboolean force, int stdver) + bool force, int stdver) { int bits, i; float miss; diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 8740de584..22af5c180 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -112,8 +112,8 @@ netadr_t master_adr[MAX_MASTERS]; // address of group servers quakeparms_t host_parms; -qboolean host_initialized; // true if into command execution -qboolean rcon_from_user; +bool host_initialized; // true if into command execution +bool rcon_from_user; // DoS protection // FLOOD_PING, FLOOD_LOG, FLOOD_CONNECT, FLOOD_STATUS, FLOOD_RCON, FLOOD_BAN @@ -574,7 +574,7 @@ SV_Shutdown (void *data) static __attribute__((format(PRINTF, 1, 0))) void SV_Error (const char *error, va_list argptr) { - static qboolean inerror = false; + static bool inerror = false; dstring_t *string; if (inerror) @@ -793,7 +793,7 @@ CheckForFlood (flood_enum_t cmdtype) static double lastmessagetime = 0; static flood_t floodstatus[DOSFLOODCMDS][DOSFLOODIP]; int oldest, i; - static qboolean firsttime = true; + static bool firsttime = true; if (!sv_netdosprotect) return 0; @@ -1080,7 +1080,7 @@ SVC_DirectConnect (void) int challenge, version, i, qtv = 0; int qport; netadr_t adr; - qboolean spectator; + bool spectator; client_frame_t *frames; if (CheckForFlood (FLOOD_CONNECT)) @@ -1305,8 +1305,8 @@ SVC_RemoteCommand (void) { const char *command; char *name; - qboolean admin_cmd = false; - qboolean do_cmd = false; + bool admin_cmd = false; + bool do_cmd = false; if (CheckForFlood (FLOOD_RCON)) return; @@ -1539,7 +1539,7 @@ SV_MaskIPTrim (byte *ip, int mask) } // assumes b has already been masked -static inline __attribute__((pure)) qboolean +static inline __attribute__((pure)) bool SV_MaskIPCompare (byte *a, byte *b, int mask) { int i; @@ -1562,7 +1562,7 @@ SV_MaskIPCompare (byte *a, byte *b, int mask) return true; } -static inline qboolean +static inline bool SV_IPCompare (byte *a, byte *b) { int i; @@ -1593,7 +1593,7 @@ SV_IPCopy (byte *dest, byte *src) ((unsigned int *)dest)[i] = ((unsigned int *)src)[i]; } -static qboolean +static bool SV_StringToFilter (const char *address, ipfilter_t *f) { #ifdef HAVE_IPV6 @@ -1976,7 +1976,7 @@ SV_SendBan (double till) // FIXME: this should send a disconnect to the client! } -static qboolean +static bool SV_FilterIP (byte *ip, double *until) { int i; @@ -2478,7 +2478,7 @@ Master_Heartbeat (void) } } -static inline qboolean +static inline bool iswhitespace (char c) { return c == ' ' || c == '\r' || c == '\n' || c == '\t'; @@ -2499,7 +2499,7 @@ SV_ExtractFromUserinfo (client_t *cl) char newname[MAX_NAME]; client_t *client; int i; - qboolean badname = false; + bool badname = false; // name from the info string val = Info_ValueForKey (cl->userinfo, "name"); diff --git a/qw/source/sv_move.c b/qw/source/sv_move.c index 9df58daa0..376c8389b 100644 --- a/qw/source/sv_move.c +++ b/qw/source/sv_move.c @@ -43,7 +43,7 @@ int c_yes, c_no; Returns false if any part of the bottom of the entity is off an edge that is not a staircase. */ -qboolean +bool SV_CheckBottom (edict_t *ent) { float mid, bottom; @@ -112,8 +112,8 @@ SV_CheckBottom (edict_t *ent) possible, no move is done, false is returned, and pr_global_struct->trace_normal is set to the normal of the blocking wall */ -qboolean -SV_movestep (edict_t *ent, const vec3_t move, qboolean relink) +bool +SV_movestep (edict_t *ent, const vec3_t move, bool relink) { edict_t *enemy; float dz; @@ -221,7 +221,7 @@ SV_movestep (edict_t *ent, const vec3_t move, qboolean relink) Turns to the movement direction, and walks the current distance if facing it. */ -static qboolean +static bool SV_StepDirection (edict_t *ent, float yaw, float dist) { float delta; @@ -330,7 +330,7 @@ SV_NewChaseDir (edict_t *actor, edict_t *enemy, float dist) SV_FixCheckBottom (actor); } -static qboolean +static bool SV_CloseEnough (edict_t *ent, edict_t *goal, float dist) { int i; diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index 560e84ed9..6b9d51bce 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -161,7 +161,7 @@ SV_CheckVelocity (edict_t *ent) in a frame. Not used for pushmove objects, because they must be exact. Returns false if the entity removed itself. */ -qboolean +bool SV_RunThink (edict_t *ent) { float thinktime; @@ -453,7 +453,7 @@ SV_PushEntity (edict_t *ent, vec3_t push, unsigned traceflags) return trace; } -static qboolean +static bool SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) { float solid_save; @@ -813,7 +813,7 @@ SV_Physics_Toss (edict_t *ent) static void SV_Physics_Step (edict_t *ent) { - qboolean hitsound; + bool hitsound; // freefall if not on ground if (!((int) SVfloat (ent, flags) & (FL_ONGROUND | FL_FLY | FL_SWIM))) { diff --git a/qw/source/sv_qtv.c b/qw/source/sv_qtv.c index 31306072b..95a1e5a04 100644 --- a/qw/source/sv_qtv.c +++ b/qw/source/sv_qtv.c @@ -58,7 +58,7 @@ typedef struct { backbuf_t backbuf; info_t *info; info_key_t *name_key; - qboolean packet; + bool packet; recorder_t *recorder; sizebuf_t datagram; byte datagram_buf[MAX_DATAGRAM]; diff --git a/qw/source/sv_recorder.c b/qw/source/sv_recorder.c index 517e981e6..927cd975f 100644 --- a/qw/source/sv_recorder.c +++ b/qw/source/sv_recorder.c @@ -467,7 +467,7 @@ sizebuf_t * SVR_WriteBegin (byte type, int to, unsigned size) { byte *p; - qboolean move = false; + bool move = false; // will it fit? while (rec.dbuf->bufsize + size + HEADER > rec.dbuf->sz.maxsize) { diff --git a/qw/source/sv_send.c b/qw/source/sv_send.c index 71e03d593..b53e37899 100644 --- a/qw/source/sv_send.c +++ b/qw/source/sv_send.c @@ -185,7 +185,7 @@ SV_Print (const char *fmt, va_list args) time_t mytime = 0; struct tm *local = NULL; - qboolean timestamps = false; + bool timestamps = false; char *in; @@ -298,7 +298,7 @@ SV_Multicast (const vec3_t origin, int to) client_t *client; int leafnum, j; mleaf_t *leaf; - qboolean reliable; + bool reliable; mod_brush_t *brush = &sv.worldmodel->brush; vec4f_t org = { VectorExpand (origin), 1 }; @@ -396,8 +396,8 @@ SV_StartSound (edict_t *entity, int channel, const char *sample, int volume, float attenuation) { int ent, sound_num, i; - qboolean use_phs; - qboolean reliable = false; + bool use_phs; + bool reliable = false; vec3_t origin; if (volume < 0 || volume > 255) @@ -613,7 +613,7 @@ SV_UpdateClientStats (client_t *client) } } -static qboolean +static bool SV_SendClientDatagram (client_t *client) { byte buf[MAX_DATAGRAM]; diff --git a/qw/source/sv_sys_win.c b/qw/source/sv_sys_win.c index f8c9dba1a..ed907dee9 100644 --- a/qw/source/sv_sys_win.c +++ b/qw/source/sv_sys_win.c @@ -38,7 +38,7 @@ #include "qw/include/server.h" -qboolean WinNT; +bool WinNT; server_static_t svs; static void diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 553ee274c..26b58a6a7 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -987,7 +987,7 @@ SV_BeginDownload_f (void *unused) //============================================================================= static void -SV_Say (qboolean team) +SV_Say (bool team) { char *i, *p; dstring_t *text; @@ -1823,7 +1823,7 @@ check_usecs (usercmd_t *ucmd) } void -SV_RunCmd (usercmd_t *ucmd, qboolean inside) +SV_RunCmd (usercmd_t *ucmd, bool inside) { int oldmsec, i, n; edict_t *ent; @@ -2024,7 +2024,7 @@ SV_ExecuteClientMessage (client_t *cl) client_frame_t *frame; int checksumIndex, seq_hash, c; usercmd_t oldest, oldcmd, newcmd; - qboolean move_issued = false; // allow only one move command + bool move_issued = false; // allow only one move command vec3_t o; // make sure the reply sequence number matches the incoming diff --git a/qw/source/teamplay.c b/qw/source/teamplay.c index f1c960bf3..386f30ddb 100644 --- a/qw/source/teamplay.c +++ b/qw/source/teamplay.c @@ -61,7 +61,7 @@ #include "qw/include/cl_input.h" #include "qw/include/client.h" -static qboolean died = false, recorded_location = false; +static bool died = false, recorded_location = false; static vec4f_t death_location, last_recorded_location; int cl_deadbodyfilter; diff --git a/qw/source/world.c b/qw/source/world.c index 1c7494ca0..1d032d5ba 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -443,7 +443,7 @@ SV_FindTouchedLeafs (edict_t *ent, int node_id) } void -SV_LinkEdict (edict_t *ent, qboolean touch_triggers) +SV_LinkEdict (edict_t *ent, bool touch_triggers) { areanode_t *node; diff --git a/tools/carne/main.c b/tools/carne/main.c index db45b88aa..36fc30e7b 100644 --- a/tools/carne/main.c +++ b/tools/carne/main.c @@ -21,7 +21,7 @@ #include "gib_thread.h" #include "gib_parse.h" -static qboolean carne_done = false; +static bool carne_done = false; static int carne_exitcode = 0; static void diff --git a/tools/pak/pak.h b/tools/pak/pak.h index 7099594de..7729aba39 100644 --- a/tools/pak/pak.h +++ b/tools/pak/pak.h @@ -46,8 +46,8 @@ typedef enum { typedef struct { pakmode_t mode; // see above int verbosity; // 0=silent - qboolean compress; // for the future - qboolean pad; // pad area of files to 4-byte boundary + bool compress; // for the future + bool pad; // pad area of files to 4-byte boundary char *packfile; // pak file to read/write/test } options_t; diff --git a/tools/qfbsp/include/bsp5.h b/tools/qfbsp/include/bsp5.h index 3585b2871..133587ae1 100644 --- a/tools/qfbsp/include/bsp5.h +++ b/tools/qfbsp/include/bsp5.h @@ -56,7 +56,7 @@ typedef struct visfacet_s { struct visfacet_s *original;///< face on node int outputnumber; ///< valid only for original faces after ///< write surfaces - qboolean detail; ///< is a detail face + bool detail; ///< is a detail face struct winding_s *points; int *edges; @@ -68,10 +68,10 @@ typedef struct surface_s { int planenum; int outputplanenum; ///< valid only after WriteSurfacePlanes vec3_t mins, maxs; - qboolean onnode; ///< true if surface has already been used + bool onnode; ///< true if surface has already been used ///< as a splitting node - qboolean has_detail; ///< true if the surface has detail brushes - qboolean has_struct; ///< true if the surface has non-detail + bool has_detail; ///< true if the surface has detail brushes + bool has_struct; ///< true if the surface has non-detail ///< brushes face_t *faces; ///< links to all the faces on either side ///< of the surf @@ -115,7 +115,7 @@ void qprintf (const char *fmt, ...) __attribute__ ((format (PRINTF, 1, 2))); extern int valid; -extern qboolean worldmodel; +extern bool worldmodel; // misc functions diff --git a/tools/qfbsp/include/map.h b/tools/qfbsp/include/map.h index 25c56d4ef..708405ae5 100644 --- a/tools/qfbsp/include/map.h +++ b/tools/qfbsp/include/map.h @@ -39,7 +39,7 @@ typedef struct mface_s { typedef struct mbrush_s { struct mbrush_s *next; mface_t *faces; - qboolean detail; ///< true if brush is detail brush + bool detail; ///< true if brush is detail brush } mbrush_t; typedef struct epair_s { diff --git a/tools/qfbsp/include/options.h b/tools/qfbsp/include/options.h index 5efdb3f73..a260037e3 100644 --- a/tools/qfbsp/include/options.h +++ b/tools/qfbsp/include/options.h @@ -37,20 +37,20 @@ typedef struct { int verbosity; // 0=silent - qboolean drawflag; - qboolean notjunc; - qboolean nofill; - qboolean noclip; - qboolean onlyents; - qboolean portal; - qboolean info; - qboolean extract; - qboolean extract_textures; - qboolean extract_entities; - qboolean extract_hull; - qboolean smart_leak; - qboolean usehulls; - qboolean watervis; + bool drawflag; + bool notjunc; + bool nofill; + bool noclip; + bool onlyents; + bool portal; + bool info; + bool extract; + bool extract_textures; + bool extract_entities; + bool extract_hull; + bool smart_leak; + bool usehulls; + bool watervis; int hullnum; int subdivide_size; char *mapfile; diff --git a/tools/qfbsp/include/outside.h b/tools/qfbsp/include/outside.h index e45e11496..cdf7ef3ef 100644 --- a/tools/qfbsp/include/outside.h +++ b/tools/qfbsp/include/outside.h @@ -39,7 +39,7 @@ struct node_s; \return \c true if the outside has been set solid, otherwise \c false. */ -qboolean FillOutside (struct node_s *node); +bool FillOutside (struct node_s *node); ///@} diff --git a/tools/qfbsp/include/solidbsp.h b/tools/qfbsp/include/solidbsp.h index 5a3d7fbe4..2dab71d3d 100644 --- a/tools/qfbsp/include/solidbsp.h +++ b/tools/qfbsp/include/solidbsp.h @@ -46,7 +46,7 @@ void CalcSurfaceInfo (struct surface_s *surf); \param midsplit If true, use the volume balancing heuristic rather than the split balancing heuristic (false). */ -struct node_s *SolidBSP (struct surface_s *surfhead, qboolean midsplit); +struct node_s *SolidBSP (struct surface_s *surfhead, bool midsplit); ///@} diff --git a/tools/qfbsp/source/csg4.c b/tools/qfbsp/source/csg4.c index 05c1b8034..150a39244 100644 --- a/tools/qfbsp/source/csg4.c +++ b/tools/qfbsp/source/csg4.c @@ -128,7 +128,7 @@ SplitFace (face_t *in, plane_t *split, face_t **front, face_t **back) \param precedence XXX */ static void -ClipInside (int splitplane, int frontside, qboolean precedence) +ClipInside (int splitplane, int frontside, bool precedence) { face_t *insidelist, *next, *f; face_t *frags[2]; @@ -176,7 +176,7 @@ ClipInside (int splitplane, int frontside, qboolean precedence) \param mirror If true, add extra faces that face the opposite direction. */ static void -SaveOutside (qboolean mirror) +SaveOutside (bool mirror) { face_t *f, *next, *newf; int planenum; @@ -298,7 +298,7 @@ CSGFaces (brushset_t *bs) brush_t *b1, *b2; face_t *f; int i; - qboolean overwrite; + bool overwrite; surface_t *surfhead; qprintf ("---- CSGFaces ----\n"); diff --git a/tools/qfbsp/source/map.c b/tools/qfbsp/source/map.c index a2490eb38..b8a16916b 100644 --- a/tools/qfbsp/source/map.c +++ b/tools/qfbsp/source/map.c @@ -449,7 +449,7 @@ ParseBrush (void) free (verts); } -static qboolean +static bool ParseEntity (void) { if (!Script_GetToken (map_script, true)) diff --git a/tools/qfbsp/source/merge.c b/tools/qfbsp/source/merge.c index 325353f19..e30addd79 100644 --- a/tools/qfbsp/source/merge.c +++ b/tools/qfbsp/source/merge.c @@ -56,7 +56,7 @@ TryMerge (const face_t *f1, const face_t *f2) face_t *newf; int i, j, k, l; plane_t *plane; - qboolean keep1, keep2; + bool keep1, keep2; vec3_t normal, delta, planenormal; vec_t dot; vec_t *p1, *p2, *p3, *p4, *back; @@ -151,7 +151,7 @@ found_edge: return newf; } -qboolean mergedebug; +bool mergedebug; face_t * MergeFaceToList (face_t *face, face_t *list) { diff --git a/tools/qfbsp/source/outside.c b/tools/qfbsp/source/outside.c index 81b8b0e30..80e3419a1 100644 --- a/tools/qfbsp/source/outside.c +++ b/tools/qfbsp/source/outside.c @@ -93,7 +93,7 @@ FloodEntDist_r (node_t *n, int dist) \param headnode The root of the map's bsp tree. \return true if the entity could be placed, false otherwise. */ -static qboolean +static bool PlaceOccupant (int num, const vec3_t point, node_t *headnode) { node_t *n; @@ -233,12 +233,12 @@ int hit_occupied; \return \c true if an occupied leaf is reached, otherwise \c false. */ -static qboolean -RecursiveFillOutside (node_t *l, qboolean fill) +static bool +RecursiveFillOutside (node_t *l, bool fill) { portal_t *p; int s; - qboolean res = false; + bool res = false; if (l->contents == CONTENTS_SOLID || l->contents == CONTENTS_SKY) return false; @@ -308,11 +308,11 @@ ClearOutFaces (node_t *node) node->faces = NULL; } -qboolean +bool FillOutside (node_t *node) { int i, s; - qboolean inside; + bool inside; vec_t *v; qprintf ("----- FillOutside ----\n"); diff --git a/tools/qfbsp/source/qfbsp.c b/tools/qfbsp/source/qfbsp.c index 308e5e5ef..d23f83f2c 100644 --- a/tools/qfbsp/source/qfbsp.c +++ b/tools/qfbsp/source/qfbsp.c @@ -70,7 +70,7 @@ int valid; char *argv0; // changed after fork(); -qboolean worldmodel; +bool worldmodel; int hullnum; diff --git a/tools/qfbsp/source/region.c b/tools/qfbsp/source/region.c index b8d5b8a1e..2db9e5173 100644 --- a/tools/qfbsp/source/region.c +++ b/tools/qfbsp/source/region.c @@ -81,7 +81,7 @@ AddFaceToRegionSize (face_t *f) AddPointToRegion (f->points->points[i]); } -static qboolean +static bool CanJoinFaces (face_t *f, face_t *f2) { int i; diff --git a/tools/qfbsp/source/solidbsp.c b/tools/qfbsp/source/solidbsp.c index 58cf56f62..830c35ce8 100644 --- a/tools/qfbsp/source/solidbsp.c +++ b/tools/qfbsp/source/solidbsp.c @@ -45,7 +45,7 @@ int splitnodes; int c_solid, c_empty, c_water; -qboolean usemidsplit; +bool usemidsplit; /** Determine on which side of the plane a face is. @@ -188,7 +188,7 @@ ChooseMidPlaneFromList (surface_t *surfaces, */ static __attribute__((pure)) surface_t * ChoosePlaneFromList (surface_t *surfaces, const vec3_t mins, const vec3_t maxs, - qboolean usefloors, qboolean usedetail) + bool usefloors, bool usedetail) { face_t *f; int j, k, l, ishint; @@ -674,7 +674,7 @@ PartitionSurfaces (surface_t *surfaces, node_t *node) } node_t * -SolidBSP (surface_t *surfhead, qboolean midsplit) +SolidBSP (surface_t *surfhead, bool midsplit) { int i; node_t *headnode; diff --git a/tools/qfbsp/source/tjunc.c b/tools/qfbsp/source/tjunc.c index 64588837d..e18ec33da 100644 --- a/tools/qfbsp/source/tjunc.c +++ b/tools/qfbsp/source/tjunc.c @@ -121,7 +121,7 @@ HashVec (const vec3_t vec) \param vec The vector to make canonical. \return false is the vector is (0, 0, 0), otherwise true. */ -static qboolean +static bool CanonicalVector (vec3_t vec) { vec_t len = _VectorNormalize (vec); diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index c6f45c3dc..19aa8060f 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -295,7 +295,7 @@ typedef struct expr_s { ex_label_t label; ///< label expression ex_labelref_t labelref; ///< label reference expression (&) ex_state_t state; ///< state expression - ex_bool_t bool; ///< boolean logic expression + ex_bool_t boolean; ///< boolean logic expression ex_block_t block; ///< statement block expression ex_expr_t expr; ///< binary or unary expression struct def_s *def; ///< def reference expression diff --git a/tools/qfcc/include/options.h b/tools/qfcc/include/options.h index 42b95c257..2dc5413a5 100644 --- a/tools/qfcc/include/options.h +++ b/tools/qfcc/include/options.h @@ -34,19 +34,19 @@ #include "QF/qtypes.h" typedef struct { - qboolean cow; // Turn constants into variables if written to - qboolean crc; // Write progsdef.h crc to progs.dat - qboolean debug; // Generate debug info for the engine - qboolean short_circuit; // short circuit logic for && and || - qboolean optimize; // perform optimizations - qboolean fast_float; // use floats directly in ifs - qboolean vector_calls; // use floats instead of vectors for constant function args - qboolean local_merging; // merge function locals into one block + bool cow; // Turn constants into variables if written to + bool crc; // Write progsdef.h crc to progs.dat + bool debug; // Generate debug info for the engine + bool short_circuit; // short circuit logic for && and || + bool optimize; // perform optimizations + bool fast_float; // use floats directly in ifs + bool vector_calls; // use floats instead of vectors for constant function args + bool local_merging; // merge function locals into one block unsigned progsversion; // Progs version to generate code for - qboolean vector_components; // add *_[xyz] symbols for vectors - qboolean ifstring; // expand if (str) to if (str != "") - qboolean const_initializers; // initialied globals are constant - qboolean promote_float; // promote float through ... + bool vector_components; // add *_[xyz] symbols for vectors + bool ifstring; // expand if (str) to if (str != "") + bool const_initializers; // initialied globals are constant + bool promote_float; // promote float through ... } code_options_t; typedef struct { @@ -54,73 +54,73 @@ typedef struct { } math_options_t; typedef struct { - qboolean promote; // Promote warnings to errors - qboolean cow; // Warn on copy-on-write detection - qboolean undefined_function; // Warn on undefined function use - qboolean uninited_variable; // Warn on use of uninitialized vars - qboolean vararg_integer; // Warn on passing an integer to vararg func - qboolean integer_divide; // Warn on integer constant division - qboolean interface_check; // Warn for methods not in interface - qboolean unused; // Warn on unused local variables - qboolean executable; // Warn on expressions with no effect - qboolean traditional; // Warn on bogus constructs allowed by qcc - qboolean precedence; // Warn on precedence issues - qboolean initializer; // Warn on excessive initializer elements - qboolean unimplemented; // Warn on unimplemented class methods - qboolean redeclared; // Warn on redeclared local variables - qboolean enum_switch; // Warn on unhandled enum values in switch + bool promote; // Promote warnings to errors + bool cow; // Warn on copy-on-write detection + bool undefined_function; // Warn on undefined function use + bool uninited_variable; // Warn on use of uninitialized vars + bool vararg_integer; // Warn on passing an integer to vararg func + bool integer_divide; // Warn on integer constant division + bool interface_check; // Warn for methods not in interface + bool unused; // Warn on unused local variables + bool executable; // Warn on expressions with no effect + bool traditional; // Warn on bogus constructs allowed by qcc + bool precedence; // Warn on precedence issues + bool initializer; // Warn on excessive initializer elements + bool unimplemented; // Warn on unimplemented class methods + bool redeclared; // Warn on redeclared local variables + bool enum_switch; // Warn on unhandled enum values in switch } warn_options_t; typedef struct { - qboolean promote; // Promote notices to warnings - qboolean silent; // don't even bother (overrides promote) + bool promote; // Promote notices to warnings + bool silent; // don't even bother (overrides promote) } notice_options_t; typedef struct { - qboolean promote; // Promote bugs to internal errors - qboolean silent; // don't even bother (overrides promote) + bool promote; // Promote bugs to internal errors + bool silent; // don't even bother (overrides promote) } bug_options_t; typedef struct { - qboolean initial; - qboolean thread; - qboolean dead; - qboolean final; - qboolean dags; - qboolean expr; - qboolean statements; - qboolean reaching; - qboolean live; - qboolean flow; - qboolean post; + bool initial; + bool thread; + bool dead; + bool final; + bool dags; + bool expr; + bool statements; + bool reaching; + bool live; + bool flow; + bool post; } blockdot_options_t; typedef struct { - code_options_t code; // Code generation options - math_options_t math; // Various math options - warn_options_t warnings; // Warning options + code_options_t code; // Code generation options + math_options_t math; // Various math options + warn_options_t warnings; // Warning options notice_options_t notices; // Notice options - bug_options_t bug; // Bug options + bug_options_t bug; // Bug options blockdot_options_t block_dot; // Statement block flow diagrams - int verbosity; // 0=silent, goes up to 2 currently - qboolean single_cpp; // process progs.src into a series of + int verbosity; // 0=silent, goes up to 2 currently + bool single_cpp; // process progs.src into a series of // #include directives and then compile // that - qboolean no_default_paths; // no default -I or -L - qboolean save_temps; // save temporary files - qboolean files_dat; // generate files.dat - qboolean frames_files; // generate .frame files - qboolean progdefs_h; // generate progdefs.h - qboolean qccx_escapes; // use qccx escapes instead of standard C - int traditional; // behave more like qcc - int advanced; // behold the power of Ruamoko - qboolean compile; // serparate compilation mode - qboolean partial_link; // partial linking - qboolean preprocess_only;// run only cpp, don't compile - qboolean gzip; // compress qfo files when writing - const char *output_file; - const char *debug_file; + bool no_default_paths; // no default -I or -L + bool save_temps; // save temporary files + bool files_dat; // generate files.dat + bool frames_files; // generate .frame files + bool progdefs_h; // generate progdefs.h + bool qccx_escapes; // use qccx escapes instead of standard C + int traditional; // behave more like qcc + int advanced; // behold the power of Ruamoko + bool compile; // serparate compilation mode + bool partial_link; // partial linking + bool preprocess_only; // run only cpp, don't compile + bool gzip; // compress qfo files when writing + const char *output_file; + const char *debug_file; } options_t; extern options_t options; diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index 8b5019898..5b8b5b0c2 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -141,20 +141,20 @@ print_bool (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) int indent = level * 2 + 2; int i, count; int tl_count = 0, fl_count = 0; - ex_bool_t *bool = &e->e.bool; + ex_bool_t *boolean = &e->e.boolean; dasprintf (dstr, "%*se_%p [shape=none,label=<\n", indent, "", e); dasprintf (dstr, "%*s\n", indent + 2, ""); - dasprintf (dstr, "%*s\n", + dasprintf (dstr, "%*s\n", indent + 4, "", e->line); dasprintf (dstr, "%*s\n", indent + 4, ""); - if (bool->true_list) - tl_count = bool->true_list->size; - if (bool->false_list) - fl_count = bool->false_list->size; + if (boolean->true_list) + tl_count = boolean->true_list->size; + if (boolean->false_list) + fl_count = boolean->false_list->size; count = min (tl_count, fl_count); for (i = 0; i < count; i++) dasprintf (dstr, "%*s" @@ -163,27 +163,27 @@ print_bool (dstring_t *dstr, expr_t *e, int level, int id, expr_t *next) dasprintf (dstr, "%*s%s\n", indent, "", i, i == count ? va (0, "", - bool->true_list->size - count) + boolean->true_list->size - count) : ""); for ( ; i < fl_count; i++) dasprintf (dstr, "%*s%s\n", indent, "", i == count ? va (0, "", - bool->false_list->size - count) + boolean->false_list->size - count) : "", i); dasprintf (dstr, "%*s
<bool>(%d)
<boolean>(%d)
truefalse
t
t
f
\n", indent + 2, ""); dasprintf (dstr, "%*s>];\n", indent, ""); if (e->next) next = e->next; - _print_expr (dstr, e->e.bool.e, level, id, next); + _print_expr (dstr, e->e.boolean.e, level, id, next); for (i = 0; i < tl_count; i++) dasprintf (dstr, "%*se_%p:t%d -> e_%p;\n", indent, "", e, i, - bool->true_list->e[i]); + boolean->true_list->e[i]); for (i = 0; i < fl_count; i++) dasprintf (dstr, "%*se_%p:f%d -> e_%p;\n", indent, "", e, i, - bool->false_list->e[i]); - dasprintf (dstr, "%*se_%p -> e_%p;\n", indent, "", e, e->e.bool.e); + boolean->false_list->e[i]); + dasprintf (dstr, "%*se_%p -> e_%p;\n", indent, "", e, e->e.boolean.e); } static void diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 6f84bfdea..ca30d3074 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -285,23 +285,23 @@ copy_expr (expr_t *e) *n = *e; n->line = pr.source_line; n->file = pr.source_file; - if (e->e.bool.true_list) { - int count = e->e.bool.true_list->size; + if (e->e.boolean.true_list) { + int count = e->e.boolean.true_list->size; size_t size = (size_t)&((ex_list_t *) 0)->e[count]; - n->e.bool.true_list = malloc (size); + n->e.boolean.true_list = malloc (size); while (count--) - n->e.bool.true_list->e[count] = - copy_expr (e->e.bool.true_list->e[count]); + n->e.boolean.true_list->e[count] = + copy_expr (e->e.boolean.true_list->e[count]); } - if (e->e.bool.false_list) { - int count = e->e.bool.false_list->size; + if (e->e.boolean.false_list) { + int count = e->e.boolean.false_list->size; size_t size = (size_t)&((ex_list_t *) 0)->e[count]; - n->e.bool.false_list = malloc (size); + n->e.boolean.false_list = malloc (size); while (count--) - n->e.bool.false_list->e[count] = - copy_expr (e->e.bool.false_list->e[count]); + n->e.boolean.false_list->e[count] = + copy_expr (e->e.boolean.false_list->e[count]); } - n->e.bool.e = copy_expr (e->e.bool.e); + n->e.boolean.e = copy_expr (e->e.boolean.e); return n; case ex_label: /// Create a fresh label @@ -491,9 +491,9 @@ new_bool_expr (ex_list_t *true_list, ex_list_t *false_list, expr_t *e) expr_t *b = new_expr (); b->type = ex_bool; - b->e.bool.true_list = true_list; - b->e.bool.false_list = false_list; - b->e.bool.e = e; + b->e.boolean.true_list = true_list; + b->e.boolean.false_list = false_list; + b->e.boolean.e = e; return b; } @@ -1570,7 +1570,7 @@ convert_from_bool (expr_t *e, type_t *type) one = new_uint_expr (1); zero = new_uint_expr (0); } else { - return error (e, "can't convert from bool value"); + return error (e, "can't convert from boolean value"); } cond = new_expr (); *cond = *e; @@ -1619,7 +1619,7 @@ has_function_call (expr_t *e) { switch (e->type) { case ex_bool: - return has_function_call (e->e.bool.e); + return has_function_call (e->e.boolean.e); case ex_block: if (e->e.block.is_call) return 1; @@ -1880,8 +1880,8 @@ unary_expr (int op, expr_t *e) case ex_args: internal_error (e, "unexpected expression type"); case ex_bool: - return new_bool_expr (e->e.bool.false_list, - e->e.bool.true_list, e); + return new_bool_expr (e->e.boolean.false_list, + e->e.boolean.true_list, e); case ex_block: if (!e->e.block.result) return error (e, "invalid type for unary !"); @@ -2415,12 +2415,12 @@ conditional_expr (expr_t *cond, expr_t *e1, expr_t *e2) if (cond->type == ex_error) return cond; - backpatch (cond->e.bool.true_list, tlabel); - backpatch (cond->e.bool.false_list, flabel); + backpatch (cond->e.boolean.true_list, tlabel); + backpatch (cond->e.boolean.false_list, flabel); block->e.block.result = (type1 == type2) ? new_temp_def_expr (type1) : 0; append_expr (block, cond); - append_expr (cond->e.bool.e, flabel); + append_expr (cond->e.boolean.e, flabel); if (block->e.block.result) append_expr (block, assign_expr (block->e.block.result, e2)); else @@ -2703,13 +2703,13 @@ build_if_statement (int not, expr_t *test, expr_t *s1, expr_t *els, expr_t *s2) test = convert_bool (test, 1); if (test->type != ex_error) { if (not) { - backpatch (test->e.bool.true_list, fl); - backpatch (test->e.bool.false_list, tl); + backpatch (test->e.boolean.true_list, fl); + backpatch (test->e.boolean.false_list, tl); } else { - backpatch (test->e.bool.true_list, tl); - backpatch (test->e.bool.false_list, fl); + backpatch (test->e.boolean.true_list, tl); + backpatch (test->e.boolean.false_list, fl); } - append_expr (test->e.bool.e, tl); + append_expr (test->e.boolean.e, tl); append_expr (if_expr, test); } append_expr (if_expr, s1); @@ -2759,13 +2759,13 @@ build_while_statement (int not, expr_t *test, expr_t *statement, test = convert_bool (test, 1); if (test->type != ex_error) { if (not) { - backpatch (test->e.bool.true_list, l2); - backpatch (test->e.bool.false_list, l1); + backpatch (test->e.boolean.true_list, l2); + backpatch (test->e.boolean.false_list, l1); } else { - backpatch (test->e.bool.true_list, l1); - backpatch (test->e.bool.false_list, l2); + backpatch (test->e.boolean.true_list, l1); + backpatch (test->e.boolean.false_list, l2); } - append_expr (test->e.bool.e, l2); + append_expr (test->e.boolean.e, l2); append_expr (while_expr, test); } @@ -2801,13 +2801,13 @@ build_do_while_statement (expr_t *statement, int not, expr_t *test, test = convert_bool (test, 1); if (test->type != ex_error) { if (not) { - backpatch (test->e.bool.true_list, break_label); - backpatch (test->e.bool.false_list, l1); + backpatch (test->e.boolean.true_list, break_label); + backpatch (test->e.boolean.false_list, l1); } else { - backpatch (test->e.bool.true_list, l1); - backpatch (test->e.bool.false_list, break_label); + backpatch (test->e.boolean.true_list, l1); + backpatch (test->e.boolean.false_list, break_label); } - append_expr (test->e.bool.e, break_label); + append_expr (test->e.boolean.e, break_label); append_expr (do_while_expr, test); } @@ -2856,9 +2856,9 @@ build_for_statement (expr_t *init, expr_t *test, expr_t *next, append_expr (for_expr, l1); test = convert_bool (test, 1); if (test->type != ex_error) { - backpatch (test->e.bool.true_list, tl); - backpatch (test->e.bool.false_list, fl); - append_expr (test->e.bool.e, fl); + backpatch (test->e.boolean.true_list, tl); + backpatch (test->e.boolean.false_list, fl); + append_expr (test->e.boolean.e, fl); append_expr (for_expr, test); } } else { diff --git a/tools/qfcc/source/expr_bool.c b/tools/qfcc/source/expr_bool.c index 9fd817dc2..52d377b75 100644 --- a/tools/qfcc/source/expr_bool.c +++ b/tools/qfcc/source/expr_bool.c @@ -228,16 +228,16 @@ bool_expr (int op, expr_t *label, expr_t *e1, expr_t *e2) switch (op) { case OR: - backpatch (e1->e.bool.false_list, label); - return new_bool_expr (merge (e1->e.bool.true_list, - e2->e.bool.true_list), - e2->e.bool.false_list, block); + backpatch (e1->e.boolean.false_list, label); + return new_bool_expr (merge (e1->e.boolean.true_list, + e2->e.boolean.true_list), + e2->e.boolean.false_list, block); break; case AND: - backpatch (e1->e.bool.true_list, label); - return new_bool_expr (e2->e.bool.true_list, - merge (e1->e.bool.false_list, - e2->e.bool.false_list), block); + backpatch (e1->e.boolean.true_list, label); + return new_bool_expr (e2->e.boolean.true_list, + merge (e1->e.boolean.false_list, + e2->e.boolean.false_list), block); break; } internal_error (e1, 0); @@ -273,12 +273,12 @@ convert_bool (expr_t *e, int block) b = convert_bool (tst, 1); if (b->type == ex_error) return b; - // insert the assignment into the bool's block - e->next = b->e.bool.e->e.block.head; - b->e.bool.e->e.block.head = e; - if (b->e.bool.e->e.block.tail == &b->e.bool.e->e.block.head) { + // insert the assignment into the boolean's block + e->next = b->e.boolean.e->e.block.head; + b->e.boolean.e->e.block.head = e; + if (b->e.boolean.e->e.block.tail == &b->e.boolean.e->e.block.head) { // shouldn't happen, but just in case - b->e.bool.e->e.block.tail = &e->next; + b->e.boolean.e->e.block.tail = &e->next; } return b; } @@ -315,10 +315,10 @@ convert_bool (expr_t *e, int block) make_list (b->e.block.head->next), b); } } - if (block && e->e.bool.e->type != ex_block) { + if (block && e->e.boolean.e->type != ex_block) { expr_t *block = new_block_expr (); - append_expr (block, e->e.bool.e); - e->e.bool.e = block; + append_expr (block, e->e.boolean.e); + e->e.boolean.e = block; } return e; } diff --git a/tools/qfcc/source/options.c b/tools/qfcc/source/options.c index 86586c375..fff369987 100644 --- a/tools/qfcc/source/options.c +++ b/tools/qfcc/source/options.c @@ -425,7 +425,7 @@ DecodeArgs (int argc, char **argv) char *temp = strtok (opts, ","); while (temp) { - qboolean flag = true; + bool flag = true; if (!strncasecmp (temp, "no-", 3)) { flag = false; @@ -485,7 +485,7 @@ DecodeArgs (int argc, char **argv) char *temp = strtok (opts, ","); while (temp) { - qboolean flag = true; + bool flag = true; if (!(strncasecmp (temp, "target=", 7))) { const char *tgt = temp + 7; @@ -576,7 +576,7 @@ DecodeArgs (int argc, char **argv) options.warnings.redeclared = false; options.warnings.enum_switch = false; } else { - qboolean flag = true; + bool flag = true; if (!strncasecmp (temp, "no-", 3)) { flag = false; @@ -715,13 +715,13 @@ DecodeArgs (int argc, char **argv) options.advanced = false; if (!options.code.progsversion) options.code.progsversion = PROG_ID_VERSION; - if (options.code.ifstring == (qboolean) -1) + if (options.code.ifstring == (bool) -1) options.code.ifstring = false; - if (options.code.short_circuit == (qboolean) -1) + if (options.code.short_circuit == (bool) -1) options.code.short_circuit = false; - if (options.code.local_merging == (qboolean) -1) + if (options.code.local_merging == (bool) -1) options.code.local_merging = false; - if (options.code.vector_components == (qboolean) -1) + if (options.code.vector_components == (bool) -1) options.code.vector_components = true; if (options.math.vector_mult == 0) options.math.vector_mult = DOT; @@ -733,13 +733,13 @@ DecodeArgs (int argc, char **argv) options.advanced = 2 - (options.code.progsversion < PROG_VERSION); const char *ruamoko = va (0, "-D__RUAMOKO__=%d", options.advanced); add_cpp_def (save_string (ruamoko)); - if (options.code.ifstring == (qboolean) -1) + if (options.code.ifstring == (bool) -1) options.code.ifstring = false; - if (options.code.short_circuit == (qboolean) -1) + if (options.code.short_circuit == (bool) -1) options.code.short_circuit = true; - if (options.code.local_merging == (qboolean) -1) + if (options.code.local_merging == (bool) -1) options.code.local_merging = true; - if (options.code.vector_components == (qboolean) -1) + if (options.code.vector_components == (bool) -1) options.code.vector_components = false; if (options.math.vector_mult == 0) options.math.vector_mult = options.advanced == 1 ? DOT : HADAMARD; @@ -749,10 +749,10 @@ DecodeArgs (int argc, char **argv) if (options.code.progsversion == PROG_ID_VERSION) { options.code.promote_float = 0; add_cpp_def ("-D__VERSION6__=1"); - if (options.code.crc == (qboolean) -1) + if (options.code.crc == (bool) -1) options.code.crc = true; } else { - if (options.code.crc == (qboolean) -1) + if (options.code.crc == (bool) -1) options.code.crc = false; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index a1c78f9d7..774afb2ca 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -2048,7 +2048,7 @@ build_bool_block (expr_t *block, expr_t *e) { switch (e->type) { case ex_bool: - build_bool_block (block, e->e.bool.e); + build_bool_block (block, e->e.boolean.e); return; case ex_label: e->next = 0; diff --git a/tools/qflight/include/light.h b/tools/qflight/include/light.h index f558f594d..b5de5e1c5 100644 --- a/tools/qflight/include/light.h +++ b/tools/qflight/include/light.h @@ -95,11 +95,11 @@ extern vec3_t bsp_origin; extern vec3_t bsp_xvector; extern vec3_t bsp_yvector; -extern qboolean extrasamples; +extern bool extrasamples; void LoadNodes (const char *file); -qboolean TestLine (lightinfo_t *l, const vec3_t start, const vec3_t stop); -qboolean TestSky (lightinfo_t *l, const vec3_t start, const vec3_t stop); +bool TestLine (lightinfo_t *l, const vec3_t start, const vec3_t stop); +bool TestSky (lightinfo_t *l, const vec3_t start, const vec3_t stop); void LightFace (lightinfo_t *l, int surfnum); void LightLeaf (dleaf_t *leaf); diff --git a/tools/qflight/source/entities.c b/tools/qflight/source/entities.c index 26c61638f..edc40a284 100644 --- a/tools/qflight/source/entities.c +++ b/tools/qflight/source/entities.c @@ -76,7 +76,7 @@ const char *lighttargets[32]; static int -LightStyleForTargetname (const char *targetname, qboolean alloc) +LightStyleForTargetname (const char *targetname, bool alloc) { int i; diff --git a/tools/qflight/source/ltface.c b/tools/qflight/source/ltface.c index 11204f555..64ea9d800 100644 --- a/tools/qflight/source/ltface.c +++ b/tools/qflight/source/ltface.c @@ -288,7 +288,7 @@ static void SingleLightFace (entity_t *light, lightinfo_t *l) { int mapnum, i; - qboolean hit; + bool hit; vec3_t incoming, spotvec; vec_t angle, dist, idist, lightfalloff, lightsubtract, spotcone; vec_t add = 0.0; diff --git a/tools/qflight/source/qflight.c b/tools/qflight/source/qflight.c index 4f13614f9..677dd439c 100644 --- a/tools/qflight/source/qflight.c +++ b/tools/qflight/source/qflight.c @@ -76,7 +76,7 @@ int bspfileent; // next entity to dispatch vec3_t bsp_origin; -qboolean extrasamples; +bool extrasamples; int GetFileSpace (int size) diff --git a/tools/qflight/source/trace.c b/tools/qflight/source/trace.c index aa5b4ce19..9b77e2849 100644 --- a/tools/qflight/source/trace.c +++ b/tools/qflight/source/trace.c @@ -142,9 +142,9 @@ MakeTnodes (dmodel_t *bm) #define TESTLINESTATE_EMPTY 1 #define TESTLINESTATE_SOLID 2 -static qboolean +static bool TestLineOrSky (lightinfo_t *l, const vec3_t start, const vec3_t end, - qboolean sky_test) + bool sky_test) { vec_t front, back; vec3_t frontpt, backpt; @@ -223,13 +223,13 @@ TestLineOrSky (lightinfo_t *l, const vec3_t start, const vec3_t end, } } -qboolean +bool TestLine (lightinfo_t *l, const vec3_t start, const vec3_t stop) { return TestLineOrSky (l, start, stop, false); } -qboolean +bool TestSky (lightinfo_t *l, const vec3_t start, const vec3_t dir) { vec3_t stop; diff --git a/tools/qflmp/lmp.c b/tools/qflmp/lmp.c index 06a77e370..88001cb2f 100644 --- a/tools/qflmp/lmp.c +++ b/tools/qflmp/lmp.c @@ -124,7 +124,7 @@ usage (int status) } -static qboolean +static bool exportFile (const char *inpath) { char *outpath = replaceExtension (inpath, "pcx"); @@ -136,7 +136,7 @@ exportFile (const char *inpath) int32_t width; int32_t height; void *data; - qboolean ret = false; + bool ret = false; if (options.verbosity > 1) Sys_Printf ("file size: %d\n", fsize); @@ -200,7 +200,7 @@ die: } -static qboolean +static bool importFile (const char *inpath) { char *outpath = replaceExtension (inpath, "lmp"); @@ -208,7 +208,7 @@ importFile (const char *inpath) QFile *outfile = Qopen (outpath, "wb"); int fsize = Qfilesize (infile); tex_t *lmp; - qboolean ret = false; + bool ret = false; if (options.verbosity > 1) Sys_Printf ("PCX file size: %d\n", fsize); diff --git a/tools/qflmp/lmp.h b/tools/qflmp/lmp.h index 4428da4c5..7098370b6 100644 --- a/tools/qflmp/lmp.h +++ b/tools/qflmp/lmp.h @@ -44,7 +44,7 @@ typedef struct { lmpmode_t mode; // see above int verbosity; // 0=silent char *palette; // palette file to read - qboolean raw; // don't read / write header + bool raw; // don't read / write header short width; // width of images short height; // height " " } options_t; diff --git a/tools/qfmodelgen/source/modelgen.c b/tools/qfmodelgen/source/modelgen.c index a4b18b1ac..b48934576 100644 --- a/tools/qfmodelgen/source/modelgen.c +++ b/tools/qfmodelgen/source/modelgen.c @@ -109,7 +109,7 @@ char cdpartial[256]; char cddir[256]; int framecount, skincount; -qboolean cdset; +bool cdset; int degeneratetris; int firstframe = 1; float totsize, averagesize; diff --git a/tools/qfvis/include/options.h b/tools/qfvis/include/options.h index dd84d17b9..a75d0da0e 100644 --- a/tools/qfvis/include/options.h +++ b/tools/qfvis/include/options.h @@ -33,10 +33,10 @@ typedef struct { int verbosity; // 0=silent int threads; - qboolean minimal; - qboolean no_auto_pvs; - qboolean fat_pvs; - qboolean utf8; + bool minimal; + bool no_auto_pvs; + bool fat_pvs; + bool utf8; int level; size_t portal_limit; struct dstring_s *bspfile; diff --git a/tools/qfvis/include/vis.h b/tools/qfvis/include/vis.h index 842ab03c7..9106dc67c 100644 --- a/tools/qfvis/include/vis.h +++ b/tools/qfvis/include/vis.h @@ -86,7 +86,7 @@ extern pthread_rwlock_t *stats_lock; typedef struct winding_s { struct winding_s *next; - qboolean original; // don't free, it's part of the portal + bool original; // don't free, it's part of the portal unsigned numpoints; int id; int thread; @@ -209,7 +209,7 @@ extern byte *uncompressed; winding_t *NewWinding (threaddata_t *thread, int points); winding_t *ClipWinding (threaddata_t *thread, winding_t *in, vec4f_t split, - qboolean keepon); + bool keepon); winding_t *CopyWinding (threaddata_t *thread, const winding_t *w); void ClusterFlow (int clusternum); diff --git a/tools/qfvis/source/fatpvs.c b/tools/qfvis/source/fatpvs.c index faabace0a..724e0d758 100644 --- a/tools/qfvis/source/fatpvs.c +++ b/tools/qfvis/source/fatpvs.c @@ -208,7 +208,7 @@ compress_thread (void *d) { fatstats_t stats = { }; int thread = (intptr_t) d; - qboolean rle = options.utf8; + bool rle = options.utf8; set_t vis = { }; if (num_leafs != num_clusters) { diff --git a/tools/qfvis/source/qfvis.c b/tools/qfvis/source/qfvis.c index 7630de93b..0aa29f973 100644 --- a/tools/qfvis/source/qfvis.c +++ b/tools/qfvis/source/qfvis.c @@ -325,7 +325,7 @@ test_point (vec4f_t split, const vec4f_t *points, int index, vec4f_t *dists, */ winding_t * ClipWinding (threaddata_t *thread, winding_t *in, vec4f_t split, - qboolean keepon) + bool keepon) { unsigned maxpts = 0; unsigned i; @@ -1112,7 +1112,7 @@ CalcClusterSpheres (void) } #if 0 -static qboolean +static bool PlaneCompare (plane_t *p1, plane_t *p2) { int i; @@ -1135,7 +1135,7 @@ FindPassages (winding_t *source, winding_t *pass) int i, j, k, l; int counts[3]; plane_t plane; - qboolean fliptest; + bool fliptest; sep_t *sep, *list; vec3_t v1, v2; diff --git a/tools/wad/script.c b/tools/wad/script.c index 43da05360..3b98e4c1b 100644 --- a/tools/wad/script.c +++ b/tools/wad/script.c @@ -52,7 +52,7 @@ #include "wad.h" static dstring_t destfile = {&dstring_default_mem}; -static qboolean savesingle = false; +static bool savesingle = false; static wad_t *wadfile; dstring_t *lumpname; tex_t *image; diff --git a/tools/wad/wad.h b/tools/wad/wad.h index d5e3d32fc..af850e202 100644 --- a/tools/wad/wad.h +++ b/tools/wad/wad.h @@ -46,9 +46,9 @@ typedef enum { typedef struct { wadmode_t mode; // see above int verbosity; // 0=silent - qboolean compress; // for the future - qboolean pad; // pad area of files to 4-byte boundary - qboolean nomip; // exclude mipmaps from output textures. + bool compress; // for the future + bool pad; // pad area of files to 4-byte boundary + bool nomip; // exclude mipmaps from output textures. char *wadfile; // wad file to read/write/test } options_t; From db889e5e54948a3736c458bb1e9944757196f2fc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Jun 2023 18:11:11 +0900 Subject: [PATCH 3601/3664] [util] Fix a local variable address warning Despite mdfour claiming not to be fast, it tried to avoid passing a pointer around via a global instead of parameters. Long obsolete and iffy to boot. --- libs/util/mdfour.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/libs/util/mdfour.c b/libs/util/mdfour.c index 61bc46e9a..f77fa0db7 100644 --- a/libs/util/mdfour.c +++ b/libs/util/mdfour.c @@ -42,8 +42,6 @@ It assumes that a int is at least 32 bits long */ -static struct mdfour *m; - #define F(X,Y,Z) (((X)&(Y)) | ((~(X))&(Z))) #define G(X,Y,Z) (((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z))) #define H(X,Y,Z) ((X)^(Y)^(Z)) @@ -61,7 +59,7 @@ static struct mdfour *m; /* this applies md4 to 64 byte chunks */ static void -mdfour64 (uint32_t * M) +mdfour64 (struct mdfour *m, uint32_t * M) { int j; uint32_t AA, BB, CC, DD; @@ -182,7 +180,7 @@ mdfour_begin (struct mdfour *md) } static void -mdfour_tail (const unsigned char *in, int n) +mdfour_tail (struct mdfour *m, const unsigned char *in, int n) { unsigned char buf[128]; uint32_t M[16]; @@ -200,13 +198,13 @@ mdfour_tail (const unsigned char *in, int n) if (n <= 55) { copy4 (buf + 56, b); copy64 (M, buf); - mdfour64 (M); + mdfour64 (m, M); } else { copy4 (buf + 120, b); copy64 (M, buf); - mdfour64 (M); + mdfour64 (m, M); copy64 (M, buf + 64); - mdfour64 (M); + mdfour64 (m, M); } } @@ -216,30 +214,26 @@ mdfour_update (struct mdfour *md, const unsigned char *in, int n) uint32_t M[16]; if (n == 0) - mdfour_tail (in, n); - - m = md; + mdfour_tail (md, in, n); while (n >= 64) { copy64 (M, in); - mdfour64 (M); + mdfour64 (md, M); in += 64; n -= 64; - m->totalN += 64; + md->totalN += 64; } - mdfour_tail (in, n); + mdfour_tail (md, in, n); } VISIBLE void mdfour_result (struct mdfour *md, unsigned char *out) { - m = md; - - copy4 (out, m->A); - copy4 (out + 4, m->B); - copy4 (out + 8, m->C); - copy4 (out + 12, m->D); + copy4 (out, md->A); + copy4 (out + 4, md->B); + copy4 (out + 8, md->C); + copy4 (out + 12, md->D); } VISIBLE void From 9d1c07d2ac55e21325855c8c1d6e6ae4a4b80a5c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 13 Jun 2023 18:13:23 +0900 Subject: [PATCH 3602/3664] Fix a few strict aliasing warnings gcc 13 got a little stricter on those (at least with gnu2x/c2x). --- libs/video/renderer/gl/gl_sky.c | 12 +++++----- libs/video/renderer/glsl/glsl_draw.c | 33 +++++++++++++++++----------- qw/source/master.c | 14 +++++++----- tools/qfmodelgen/source/trilib.c | 13 ++++++----- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/libs/video/renderer/gl/gl_sky.c b/libs/video/renderer/gl/gl_sky.c index 689dfc4a5..0a26adc7b 100644 --- a/libs/video/renderer/gl/gl_sky.c +++ b/libs/video/renderer/gl/gl_sky.c @@ -413,7 +413,7 @@ gl_R_InitSky (texture_t *mt) // make an average value for the back to avoid a fringe on the top level r = g = b = 0; - for (i = 0; i < 128; i++) + for (i = 0; i < 128; i++) { for (j = 0; j < 128; j++) { p = src[i * 256 + j + 128]; rgba = &d_8to24table[p]; @@ -422,11 +422,13 @@ gl_R_InitSky (texture_t *mt) g += ((byte *) rgba)[1]; b += ((byte *) rgba)[2]; } + } + r /= 128 * 128; + g /= 128 * 128; + b /= 128 * 128; - ((byte *) & transpix)[0] = r / (128 * 128); - ((byte *) & transpix)[1] = g / (128 * 128); - ((byte *) & transpix)[2] = b / (128 * 128); - ((byte *) & transpix)[3] = 0; + //FIXME assumes little endian + transpix = ((b << 16) | (g << 8) | (r << 0)) & 0x00ffffff; if (!gl_solidskytexture) { qfglGenTextures (1, &gl_solidskytexture); diff --git a/libs/video/renderer/glsl/glsl_draw.c b/libs/video/renderer/glsl/glsl_draw.c index 2abe50b54..2ac5ef635 100644 --- a/libs/video/renderer/glsl/glsl_draw.c +++ b/libs/video/renderer/glsl/glsl_draw.c @@ -57,6 +57,10 @@ #include "r_internal.h" +typedef struct pic_data_s { + subpic_t *subpic; +} picdata_t; + typedef struct cachepic_s { struct cachepic_s *next; char *name; @@ -155,12 +159,12 @@ make_glpic (const char *name, qpic_t *p) qpic_t *pic = 0; if (p) { - pic = malloc (sizeof (qpic_t) + sizeof (subpic_t *)); + pic = malloc (field_offset (qpic_t, data[sizeof (picdata_t)])); pic->width = p->width; pic->height = p->height; - subpic_t *sp = GLSL_ScrapSubpic (draw_scrap, pic->width, pic->height); - *(subpic_t **) pic->data = sp; - GLSL_SubpicUpdate (sp, p->data, 1); + __auto_type pd = (picdata_t *) pic->data; + pd->subpic = GLSL_ScrapSubpic (draw_scrap, pic->width, pic->height); + GLSL_SubpicUpdate (pd->subpic, p->data, 1); } return pic; } @@ -172,9 +176,9 @@ pic_free (qpic_t *pic) return; } - subpic_t *subpic = *(subpic_t **) pic->data; + __auto_type pd = (picdata_t *) pic->data; - GLSL_SubpicDelete (subpic); + GLSL_SubpicDelete (pd->subpic); free (pic); } @@ -225,7 +229,8 @@ make_quad (qpic_t *pic, float x, float y, int w, int h, int srcx, int srcy, int srcw, int srch, drawvert_t verts[6], float *color) { - subpic_t *sp = *(subpic_t **) pic->data; + __auto_type pd = (picdata_t *) pic->data; + subpic_t *sp = pd->subpic; float sl, sh, tl, th; srcx += sp->rect->x; @@ -749,11 +754,12 @@ void glsl_Draw_TileClear (int x, int y, int w, int h) { static quat_t color = { 1, 1, 1, 1 }; - vrect_t *tile_rect = VRect_New (x, y, w, h); - vrect_t *sub = VRect_New (0, 0, 0, 0); // filled in later; - subpic_t *sp = *(subpic_t **) backtile_pic->data; - int sub_sx, sub_sy, sub_ex, sub_ey; - int i, j; + vrect_t *tile_rect = VRect_New (x, y, w, h); + vrect_t *sub = VRect_New (0, 0, 0, 0); // filled in later; + __auto_type pd = (picdata_t *) backtile_pic->data; + subpic_t *sp = pd->subpic; + int sub_sx, sub_sy, sub_ex, sub_ey; + int i, j; sub_sx = x / sp->width; sub_sy = y / sp->height; @@ -792,7 +798,8 @@ glsl_Draw_Fill (int x, int y, int w, int h, int c) void glsl_Draw_Line (int x0, int y0, int x1, int y1, int c) { - subpic_t *sp = *(subpic_t **) white_pic->data; + __auto_type pd = (picdata_t *) white_pic->data; + subpic_t *sp = pd->subpic; float sl = sp->rect->x * sp->size; float sh = sp->rect->x * sp->size; float tl = sp->rect->y * sp->size; diff --git a/qw/source/master.c b/qw/source/master.c index 9cf03e390..f682f4467 100644 --- a/qw/source/master.c +++ b/qw/source/master.c @@ -288,12 +288,14 @@ QW_SendHearts (int sock, msghdr_t *msghdr, server_t *servers, int serverlen) for (i = 0; i < serverlen; i++) { if (servers[i].updated != 0) { unsigned char *p = out + (cpos * 6); - p[0] = ((unsigned char *) &servers[i].addr.sin_addr.s_addr)[0]; - p[1] = ((unsigned char *) &servers[i].addr.sin_addr.s_addr)[1]; - p[2] = ((unsigned char *) &servers[i].addr.sin_addr.s_addr)[2]; - p[3] = ((unsigned char *) &servers[i].addr.sin_addr.s_addr)[3]; - p[4] = (unsigned char) (ntohs (servers[i].addr.sin_port) >> 8); - p[5] = (unsigned char) (ntohs (servers[i].addr.sin_port) & 0xFF); + in_addr_t addr = ntohl (servers[i].addr.sin_addr.s_addr); + in_port_t port = ntohs (servers[i].addr.sin_port); + p[0] = addr >> 24; + p[1] = addr >> 16; + p[2] = addr >> 8; + p[3] = addr >> 0; + p[4] = port >> 8; + p[5] = port >> 0; ++cpos; } } diff --git a/tools/qfmodelgen/source/trilib.c b/tools/qfmodelgen/source/trilib.c index a22721192..da3ad6ea3 100644 --- a/tools/qfmodelgen/source/trilib.c +++ b/tools/qfmodelgen/source/trilib.c @@ -74,16 +74,17 @@ LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles) { QFile *input; char name[256], tex[256]; - float start, exitpattern, t; + float start, exitpattern; int count, iLevel, magic, i; tf_triangle tri; triangle_t *ptri; - t = -FLOAT_START; - *((unsigned char *) &exitpattern + 0) = *((unsigned char *) &t + 3); - *((unsigned char *) &exitpattern + 1) = *((unsigned char *) &t + 2); - *((unsigned char *) &exitpattern + 2) = *((unsigned char *) &t + 1); - *((unsigned char *) &exitpattern + 3) = *((unsigned char *) &t + 0); + // FIXME not sure if this should be BigFloat or FloatSwap + exitpattern = BigFloat (FLOAT_END); + //*((unsigned char *) &exitpattern + 0) = *((unsigned char *) &t + 3); + //*((unsigned char *) &exitpattern + 1) = *((unsigned char *) &t + 2); + //*((unsigned char *) &exitpattern + 2) = *((unsigned char *) &t + 1); + //*((unsigned char *) &exitpattern + 3) = *((unsigned char *) &t + 0); if ((input = Qopen(filename, "rb")) == 0) { fprintf (stderr,"reader: could not open file '%s'\n", filename); From 8ff60b4603348c37033c51a0a3c6072c9fdbda41 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Jun 2023 09:36:50 +0900 Subject: [PATCH 3603/3664] [simd] Add unsigned vector types Mostly as a convenience for working with very small arrays of unsigned ints. --- include/QF/simd/types.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/QF/simd/types.h b/include/QF/simd/types.h index c7c950fd0..bb04d2182 100644 --- a/include/QF/simd/types.h +++ b/include/QF/simd/types.h @@ -68,6 +68,7 @@ typedef float vec3f_t[3]; QF_VEC_TYPE (float, vec2f_t, 2); QF_VEC_TYPE (int, vec2i_t, 2); +QF_VEC_TYPE (unsigned, vec2u_t, 2); /** Four element vector type for horizontal (AOS) vector data. * @@ -84,14 +85,18 @@ QF_VEC_TYPE (float, vec4f_t, 4); */ QF_VEC_TYPE (int, vec4i_t, 4); +QF_VEC_TYPE (unsigned, vec4u_t, 4); + #define VEC2D_FMT "[%.17g, %.17g]" #define VEC2L_FMT "[%"PRIi64", %"PRIi64"]" #define VEC4D_FMT "[%.17g, %.17g, %.17g, %.17g]" #define VEC4L_FMT "[%"PRIi64", %"PRIi64", %"PRIi64", %"PRIi64"]" #define VEC2F_FMT "[%.9g, %.9g]" #define VEC2I_FMT "[%d, %d]" +#define VEC2U_FMT "[%u, %u]" #define VEC4F_FMT "[%.9g, %.9g, %.9g, %.9g]" #define VEC4I_FMT "[%d, %d, %d, %d]" +#define VEC4U_FMT "[%u, %u, %u, %u]" #define VEC2_EXP(v) (v)[0], (v)[1] #define VEC4_EXP(v) (v)[0], (v)[1], (v)[2], (v)[3] From 97f9fd81d643f865d61d45858b5b767218342e9e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Jun 2023 13:13:52 +0900 Subject: [PATCH 3604/3664] [vulkan] Switch around renderpass and subpass names The old structs will go away eventually, and I'm tired of seeing that _ tail. --- include/QF/Vulkan/qf_lighting.h | 2 +- include/QF/Vulkan/qf_renderpass.h | 24 +++++++++---------- include/QF/Vulkan/render.h | 14 +++++------ include/vid_vulkan.h | 4 ++-- libs/video/renderer/vulkan/render.c | 24 +++++++++---------- libs/video/renderer/vulkan/vkgen/vulkan.r | 4 ++-- libs/video/renderer/vulkan/vkparse.c | 4 ++-- libs/video/renderer/vulkan/vkparse.plist | 6 ++--- libs/video/renderer/vulkan/vulkan_compose.c | 2 +- libs/video/renderer/vulkan/vulkan_lighting.c | 2 +- .../video/renderer/vulkan/vulkan_renderpass.c | 22 ++++++++--------- .../video/renderer/vulkan/vulkan_vid_common.c | 6 ++--- 12 files changed, 57 insertions(+), 57 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 24296c9ff..2cf7c7e81 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -105,7 +105,7 @@ typedef struct lightingctx_s { qfv_imageset_t light_images; light_renderer_set_t light_renderers; - qfv_renderpass_t *qfv_renderpass; + qfv_orenderpass_t *qfv_renderpass; VkRenderPass renderpass_6; VkRenderPass renderpass_4; VkRenderPass renderpass_1; diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index 7f9d6961e..b07b72d7a 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -17,21 +17,21 @@ typedef struct qfv_framebufferset_s #define QFV_AllocFrameBuffers(num, allocator) \ DARRAY_ALLOCFIXED (qfv_framebufferset_t, num, allocator) -typedef struct qfv_subpass_s { +typedef struct qfv_osubpass_s { vec4f_t color; const char *name; -} qfv_subpass_t; +} qfv_osubpass_t; typedef struct qfv_subpassset_s - DARRAY_TYPE (qfv_subpass_t) qfv_subpassset_t; + DARRAY_TYPE (qfv_osubpass_t) qfv_subpassset_t; typedef struct qfv_renderframe_s { struct vulkan_ctx_s *vulkan_ctx; - struct qfv_renderpass_s *renderpass; + struct qfv_orenderpass_s *renderpass; VkSubpassContents subpassContents; VkFramebuffer framebuffer; int subpassCount; - qfv_subpass_t *subpassInfo; + qfv_osubpass_t *subpassInfo; struct qfv_cmdbufferset_s *subpassCmdSets; } qfv_renderframe_t; @@ -43,7 +43,7 @@ typedef struct clearvalueset_s typedef void (*qfv_draw_t) (qfv_renderframe_t *rFrame); -typedef struct qfv_renderpass_s { +typedef struct qfv_orenderpass_s { struct vulkan_ctx_s *vulkan_ctx; vec4f_t color; // for debugging const char *name; // for debugging @@ -67,14 +67,14 @@ typedef struct qfv_renderpass_s { qfv_renderframeset_t frames; qfv_draw_t draw; -} qfv_renderpass_t; +} qfv_orenderpass_t; -qfv_renderpass_t *QFV_RenderPass_New (struct vulkan_ctx_s *ctx, +qfv_orenderpass_t *QFV_RenderPass_New (struct vulkan_ctx_s *ctx, const char *name, qfv_draw_t draw); -void QFV_RenderPass_Delete (qfv_renderpass_t *renderpass); -void QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass); -void QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass); -void QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass); +void QFV_RenderPass_Delete (qfv_orenderpass_t *renderpass); +void QFV_RenderPass_CreateAttachments (qfv_orenderpass_t *renderpass); +void QFV_RenderPass_CreateRenderPass (qfv_orenderpass_t *renderpass); +void QFV_RenderPass_CreateFramebuffer (qfv_orenderpass_t *renderpass); #endif//__QF_Vulkan_qf_renderpass_h diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 4dc03496e..e9a0044b7 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -279,15 +279,15 @@ typedef struct qfv_pipeline_s { qfv_taskinfo_t *tasks; } qfv_pipeline_t; -typedef struct qfv_subpass_s_ { +typedef struct qfv_subpass_s { qfv_label_t label; VkCommandBufferInheritanceInfo inherit; VkCommandBufferBeginInfo beginInfo; uint32_t pipeline_count; qfv_pipeline_t *pipelines; -} qfv_subpass_t_; +} qfv_subpass_t; -typedef struct qfv_renderpass_s_ { +typedef struct qfv_renderpass_s { struct vulkan_ctx_s *vulkan_ctx; qfv_label_t label; // for debugging @@ -301,13 +301,13 @@ typedef struct qfv_renderpass_s_ { //qfv_output_t output; uint32_t subpass_count; - qfv_subpass_t_ *subpasses; -} qfv_renderpass_t_; + qfv_subpass_t *subpasses; +} qfv_renderpass_t; typedef struct qfv_render_s { qfv_label_t label; - qfv_renderpass_t_ *active; - qfv_renderpass_t_ *renderpasses; + qfv_renderpass_t *active; + qfv_renderpass_t *renderpasses; uint32_t num_renderpasses; } qfv_render_t; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index f5d406de4..02b696a6f 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -21,7 +21,7 @@ typedef struct vulkan_frameset_s DARRAY_TYPE (vulkan_frame_t) vulkan_frameset_t; typedef struct qfv_renderpassset_s - DARRAY_TYPE (struct qfv_renderpass_s *) qfv_renderpassset_t; + DARRAY_TYPE (struct qfv_orenderpass_s *) qfv_renderpassset_t; typedef struct vulkan_ctx_s { void (*load_vulkan) (struct vulkan_ctx_s *ctx); @@ -67,7 +67,7 @@ typedef struct vulkan_ctx_s { uint32_t curFrame; vulkan_frameset_t frames; qfv_renderpassset_t renderPasses; - struct qfv_renderpass_s *output_renderpass; + struct qfv_orenderpass_s *output_renderpass; struct qfv_capture_s *capture; void (*capture_callback) (const byte *data, int width, int height); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index fcaa152c8..5bca53e84 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -111,7 +111,7 @@ run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) // https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/ static void -run_subpass (qfv_subpass_t_ *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx) +run_subpass (qfv_subpass_t *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -130,7 +130,7 @@ run_subpass (qfv_subpass_t_ *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx) } static void -run_renderpass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx) +run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) { printf ("run_renderpass: %s\n", rp->label.name); @@ -836,9 +836,9 @@ typedef struct { qfv_render_t *renders; qfv_compute_t *computes; qfv_process_t *processes; - qfv_renderpass_t_ *renderpasses; + qfv_renderpass_t *renderpasses; VkClearValue *clearvalues; - qfv_subpass_t_ *subpasses; + qfv_subpass_t *subpasses; qfv_pipeline_t *pipelines; qfv_taskinfo_t *tasks; VkDescriptorSet *descriptorsets; @@ -874,11 +874,11 @@ init_pipeline (qfv_pipeline_t *pl, qfv_pipelineinfo_t *plinfo, } static void -init_subpass (qfv_subpass_t_ *sp, qfv_subpassinfo_t *isp, +init_subpass (qfv_subpass_t *sp, qfv_subpassinfo_t *isp, jobptr_t *jp, objstate_t *s) { uint32_t np = s->inds.num_graph_pipelines + s->inds.num_comp_pipelines; - *sp = (qfv_subpass_t_) { + *sp = (qfv_subpass_t) { .label = { .name = isp->name, .color = isp->color, @@ -902,10 +902,10 @@ init_subpass (qfv_subpass_t_ *sp, qfv_subpassinfo_t *isp, } static void -init_renderpass (qfv_renderpass_t_ *rp, qfv_renderpassinfo_t *rpinfo, +init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo, jobptr_t *jp, objstate_t *s) { - *rp = (qfv_renderpass_t_) { + *rp = (qfv_renderpass_t) { .vulkan_ctx = s->ctx, .label.name = rpinfo->name, .label.color = rpinfo->color, @@ -1019,9 +1019,9 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) size += counts->num_render * sizeof (qfv_render_t); size += counts->num_compute * sizeof (qfv_compute_t); size += counts->num_process * sizeof (qfv_process_t); - size += counts->num_renderpasses * sizeof (qfv_renderpass_t_); + size += counts->num_renderpasses * sizeof (qfv_renderpass_t); size += counts->num_attachments * sizeof (VkClearValue); - size += counts->num_subpasses * sizeof (qfv_subpass_t_); + size += counts->num_subpasses * sizeof (qfv_subpass_t); size += counts->num_graph_pipelines * sizeof (qfv_pipeline_t); size += counts->num_comp_pipelines * sizeof (qfv_pipeline_t); size += counts->num_tasks * sizeof (qfv_taskinfo_t); @@ -1044,9 +1044,9 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) __auto_type rn = (qfv_render_t *) &job->steps[job->num_steps]; __auto_type cp = (qfv_compute_t *) &rn[counts->num_render]; __auto_type pr = (qfv_process_t *) &cp[counts->num_compute]; - __auto_type rp = (qfv_renderpass_t_ *) &pr[counts->num_process]; + __auto_type rp = (qfv_renderpass_t *) &pr[counts->num_process]; __auto_type cv = (VkClearValue *) &rp[counts->num_renderpasses]; - __auto_type sp = (qfv_subpass_t_ *) &cv[counts->num_attachments]; + __auto_type sp = (qfv_subpass_t *) &cv[counts->num_attachments]; __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; __auto_type ti = (qfv_taskinfo_t *) &pl[job->num_pipelines]; __auto_type ds = (VkDescriptorSet *) &ti[counts->num_tasks]; diff --git a/libs/video/renderer/vulkan/vkgen/vulkan.r b/libs/video/renderer/vulkan/vkgen/vulkan.r index 0ac44aeda..e8e9a0470 100644 --- a/libs/video/renderer/vulkan/vkgen/vulkan.r +++ b/libs/video/renderer/vulkan/vkgen/vulkan.r @@ -7,7 +7,7 @@ typedef vec4 vec4f_t; //FIXME copy of qfv_subpass_t in qf_renderpass.h //except it doesn't really matter because a custom spec is used -typedef struct qfv_subpass_s { +typedef struct qfv_osubpass_s { vec4 color; string name; -} qfv_subpass_t; +} qfv_osubpass_t; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 29f931fdc..f319cde4d 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1735,9 +1735,9 @@ parse_subpassset (const plfield_t *field, const plitem_t *item, void *data, { plelement_t element = { QFDictionary, - sizeof (qfv_subpass_t), + sizeof (qfv_osubpass_t), vkparse_alloc, - parse_qfv_subpass_t, + parse_qfv_osubpass_t, 0, }; plfield_t f = { 0, 0, 0, 0, &element }; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 019c27e70..addd39ac8 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -30,7 +30,7 @@ search = ( VkRenderPassCreateInfo, VkRenderPassMultiviewCreateInfo, - qfv_subpass_t, + qfv_osubpass_t, qfv_output_t, qfv_descriptorsetlayoutinfo_t, @@ -403,8 +403,8 @@ parse = { }; }; - qfv_subpass_s = { - .name = qfv_subpass_t; + qfv_osubpass_s = { + .name = qfv_osubpass_t; color = { type = (custom, QFString, parse_RGBA); fields = (color); diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 3d341ef35..06d9240c3 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -63,7 +63,7 @@ Vulkan_Compose_Draw (qfv_renderframe_t *rFrame) vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - qfv_renderpass_t *renderpass = rFrame->renderpass; + qfv_orenderpass_t *renderpass = rFrame->renderpass; composectx_t *cctx = ctx->compose_context; composeframe_t *cframe = &cctx->frames.a[ctx->curFrame]; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 33c8fc52b..90eae7ea7 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -153,7 +153,7 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - qfv_renderpass_t *renderpass = rFrame->renderpass; + qfv_orenderpass_t *renderpass = rFrame->renderpass; lightingctx_t *lctx = ctx->lighting_context; if (!lctx->scene) { diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index f490f8228..7fadceb8b 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -43,7 +43,7 @@ #include "vkparse.h" static plitem_t * -get_rp_item (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, const char *name) +get_rp_item (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp, const char *name) { rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); @@ -72,7 +72,7 @@ get_image_size (VkImage image, qfv_device_t *device) } static void -destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +destroy_framebuffers (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -85,7 +85,7 @@ destroy_framebuffers (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } void -QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass) +QFV_RenderPass_CreateAttachments (qfv_orenderpass_t *renderpass) { vulkan_ctx_t *ctx = renderpass->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -195,7 +195,7 @@ QFV_RenderPass_CreateAttachments (qfv_renderpass_t *renderpass) } void -QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass) +QFV_RenderPass_CreateRenderPass (qfv_orenderpass_t *renderpass) { vulkan_ctx_t *ctx = renderpass->vulkan_ctx; __auto_type rp = renderpass; @@ -228,7 +228,7 @@ QFV_RenderPass_CreateRenderPass (qfv_renderpass_t *renderpass) } void -QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass) +QFV_RenderPass_CreateFramebuffer (qfv_orenderpass_t *renderpass) { vulkan_ctx_t *ctx = renderpass->vulkan_ctx; __auto_type rp = renderpass; @@ -256,7 +256,7 @@ QFV_RenderPass_CreateFramebuffer (qfv_renderpass_t *renderpass) } static void -init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, +init_renderframe (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp, qfv_renderframe_t *rFrame) { rFrame->vulkan_ctx = ctx; @@ -276,7 +276,7 @@ init_renderframe (vulkan_ctx_t *ctx, qfv_renderpass_t *rp, } static void -destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +destroy_attachments (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -308,7 +308,7 @@ destroy_attachments (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } static void -destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) +destroy_renderframes (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp) { for (size_t i = 0; i < rp->frames.size; i++) { __auto_type rFrame = &rp->frames.a[i]; @@ -319,10 +319,10 @@ destroy_renderframes (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } } -qfv_renderpass_t * +qfv_orenderpass_t * QFV_RenderPass_New (vulkan_ctx_t *ctx, const char *name, qfv_draw_t function) { - qfv_renderpass_t *rp = calloc (1, sizeof (qfv_renderpass_t)); + qfv_orenderpass_t *rp = calloc (1, sizeof (qfv_orenderpass_t)); rp->vulkan_ctx = ctx; rp->name = name; rp->draw = function; @@ -361,7 +361,7 @@ QFV_RenderPass_New (vulkan_ctx_t *ctx, const char *name, qfv_draw_t function) } void -QFV_RenderPass_Delete (qfv_renderpass_t *renderpass) +QFV_RenderPass_Delete (qfv_orenderpass_t *renderpass) { vulkan_ctx_t *ctx = renderpass->vulkan_ctx; qfv_device_t *device = ctx->device; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 965b7f1ae..a28c0f2f4 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -190,8 +190,8 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) static int renderpass_cmp (const void *_a, const void *_b) { - __auto_type a = (const qfv_renderpass_t **) _a; - __auto_type b = (const qfv_renderpass_t **) _b; + __auto_type a = (const qfv_orenderpass_t **) _a; + __auto_type b = (const qfv_orenderpass_t **) _b; return (*a)->order - (*b)->order; } @@ -205,7 +205,7 @@ Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) Vulkan_Translucent_CreateRenderPasses (ctx); heapsort (ctx->renderPasses.a, ctx->renderPasses.size, - sizeof (qfv_renderpass_t *), renderpass_cmp); + sizeof (qfv_orenderpass_t *), renderpass_cmp); } void From 3c65f1494b542636425122301f57e6b602884a18 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Jun 2023 15:17:39 +0900 Subject: [PATCH 3605/3664] [vulkan] Get some subsystems passing validation This is with the new render job scheme. I very much doubt it actually works (can't start testing until everything passes, and it's disabled for the moment (define in vid_render_vulkan.c)), but it's helping iron out what more is needed in the render system. --- include/QF/Vulkan/render.h | 5 +- libs/video/renderer/vid_render_vulkan.c | 13 ++- libs/video/renderer/vulkan/render.c | 28 +++-- libs/video/renderer/vulkan/rp_main_def.plist | 11 ++ libs/video/renderer/vulkan/vulkan_output.c | 19 ++++ libs/video/renderer/vulkan/vulkan_particles.c | 107 +++++++++++++++++- .../renderer/vulkan/vulkan_translucent.c | 51 +++++++++ 7 files changed, 221 insertions(+), 13 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index e9a0044b7..8c0469dfe 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -263,7 +263,7 @@ typedef struct qfv_bar_s { typedef struct qfv_pipeline_s { qfv_label_t label; VkPipelineBindPoint bindPoint; - uint32_t dispatch[3]; + vec4u_t dispatch; VkPipeline pipeline; VkPipelineLayout layout; @@ -360,6 +360,9 @@ typedef struct qfv_taskctx_s { qfv_pipeline_t *pipeline; } qfv_taskctx_t; +VkCommandBuffer QFV_GetCmdBufffer (struct vulkan_ctx_s *ctx, bool secondary); +void QFV_AppendCmdBuffer (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd); + void QFV_RunRenderJob (struct vulkan_ctx_s *ctx); void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx); void QFV_BuildRender (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index ae6db3ebf..a5b110146 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -308,7 +308,8 @@ vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c) { Vulkan_Draw_Glyph (x, y, fontid, glyphid, c, vulkan_ctx); } - +//#define TEST_RENDER +#ifndef TEST_RENDER static void vulkan_begin_frame (void) { @@ -479,10 +480,17 @@ vulkan_end_frame (void) vulkan_ctx->curFrame++; vulkan_ctx->curFrame %= vulkan_ctx->frames.size; } - +#endif static void vulkan_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) { +#ifdef TEST_RENDER + while (*scr_funcs) { + (*scr_funcs) (); + scr_funcs++; + } + QFV_RunRenderJob (vulkan_ctx); +#else EntQueue_Clear (r_ent_queue); vulkan_begin_frame (); vulkan_set_2d (1); @@ -492,6 +500,7 @@ vulkan_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) } vulkan_render_view (); vulkan_end_frame (); +#endif } static void diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 5bca53e84..21a71334f 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -51,8 +51,8 @@ #include "vkparse.h" -static VkCommandBuffer -get_cmd_buffer (vulkan_ctx_t *ctx, int secondary) +VkCommandBuffer +QFV_GetCmdBufffer (vulkan_ctx_t *ctx, bool secondary) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -71,11 +71,19 @@ get_cmd_buffer (vulkan_ctx_t *ctx, int secondary) return cmd; } +void +QFV_AppendCmdBuffer (vulkan_ctx_t *ctx, VkCommandBuffer cmd) +{ + __auto_type rctx = ctx->render_context; + __auto_type job = rctx->job; + DARRAY_APPEND (&job->commands, cmd); +} + static void -run_tasks (uint32_t task_count, qfv_taskinfo_t *tasks, void *ctx) +run_tasks (uint32_t task_count, qfv_taskinfo_t *tasks, qfv_taskctx_t *ctx) { for (uint32_t i = 0; i < task_count; i++) { - tasks[i].func->func (tasks[i].params, 0, ctx); + tasks[i].func->func (tasks[i].params, 0, (exprctx_t *) ctx); } } @@ -136,19 +144,20 @@ run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + __auto_type rctx = ctx->render_context; + __auto_type job = rctx->job; - VkCommandBuffer cmd = get_cmd_buffer (ctx, 1); + VkCommandBuffer cmd = QFV_GetCmdBufffer (ctx, false); VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, }; - dfunc->vkResetCommandBuffer (cmd, 0); dfunc->vkBeginCommandBuffer (cmd, &beginInfo); QFV_duCmdBeginLabel (device, cmd, rp->label.name, {VEC4_EXP (rp->label.color)}); dfunc->vkCmdBeginRenderPass (cmd, &rp->beginInfo, rp->subpassContents); for (uint32_t i = 0; i < rp->subpass_count; i++) { __auto_type sp = &rp->subpasses[i]; - VkCommandBuffer subcmd = get_cmd_buffer (ctx, 1); + VkCommandBuffer subcmd = QFV_GetCmdBufffer (ctx, true); run_subpass (sp, subcmd, ctx); dfunc->vkCmdExecuteCommands (cmd, 1, &subcmd); //FIXME comment is a bit off as exactly one buffer is always submitted @@ -162,6 +171,7 @@ run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) } } QFV_CmdEndLabel (device, cmd); + DARRAY_APPEND (&job->commands, cmd); } static void @@ -193,7 +203,7 @@ run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, pipeline->num_push_constants, pipeline->push_constants); } - uint32_t *d = pipeline->dispatch; + vec4u_t d = pipeline->dispatch; dfunc->vkCmdDispatch (cmd, d[0], d[1], d[2]); } @@ -205,7 +215,7 @@ run_compute (qfv_compute_t *comp, vulkan_ctx_t *ctx) __auto_type rctx = ctx->render_context; __auto_type job = rctx->job; - VkCommandBuffer cmd = get_cmd_buffer (ctx, 0); + VkCommandBuffer cmd = QFV_GetCmdBufffer (ctx, false); VkCommandBufferBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 5f9ece858..8fedad9d2 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1310,7 +1310,15 @@ renderpasses = { }; }; steps = { + wait_on_fence = { + process = { + tasks = ( + { func = "wait_on_fence"; }, + ); + }; + }; particles = { + dependencies = (wait_on_fence); compute = { pipelines = { part:update = { @@ -1339,9 +1347,11 @@ steps = { }; }; shadow = { + dependencies = (wait_on_fence); //currently empty }; translucent = { + dependencies = (wait_on_fence); process = { tasks = ( { func = "clear_translucent"; }, @@ -1358,6 +1368,7 @@ steps = { }; }; preoutput = { + dependencies = (wait_on_fence); process = { tasks = ( { func = "acquire_output"; }, diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 58b0b79cf..5c4d93f40 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -259,6 +259,20 @@ _output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { } +static void +wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + __auto_type taskctx = (qfv_taskctx_t *) ectx; + vulkan_ctx_t *ctx = taskctx->ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkDevice dev = device->dev; + + __auto_type frame = &ctx->frames.a[ctx->curFrame]; + + dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); +} + static exprfunc_t acquire_output_func[] = { { .func = acquire_output }, {} @@ -271,10 +285,15 @@ static exprfunc_t output_draw_func[] = { { .func = _output_draw }, {} }; +static exprfunc_t wait_on_fence_func[] = { + { .func = wait_on_fence }, + {} +}; static exprsym_t output_task_syms[] = { { "acquire_output", &cexpr_function, acquire_output_func }, { "update_input", &cexpr_function, update_input_func }, { "output_draw", &cexpr_function, output_draw_func }, + { "wait_on_fence", &cexpr_function, wait_on_fence_func }, {} }; diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 526eeb2e4..31a0305c6 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -276,16 +276,121 @@ create_buffers (vulkan_ctx_t *ctx) static void particles_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + puts ("particles_draw"); } static void -update_particles (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +update_particles (const exprval_t **_params, exprval_t *result, exprctx_t *ectx) { + __auto_type taskctx = (qfv_taskctx_t *) ectx; + vulkan_ctx_t *ctx = taskctx->ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; +// VkDevice dev = device->dev; + + particlectx_t *pctx = ctx->particle_context; + __auto_type pframe = &pctx->frames.a[ctx->curFrame]; + + qfv_packet_t *packet = QFV_PacketAcquire (pctx->stage); + + __auto_type limits = &device->physDev->properties->limits; + VkMemoryRequirements req = { + .alignment = limits->minStorageBufferOffsetAlignment + }; + uint32_t numParticles = min (MaxParticles, pctx->psystem->numparticles); + size_t syssize = sizeof (qfv_particle_system_t); + size_t partoffs = QFV_NextOffset (syssize, &req); + size_t partsize = sizeof (qfv_particle_t) * numParticles; + size_t paramoffs = QFV_NextOffset (partoffs + partsize, &req); + size_t paramsize = sizeof (qfv_parameters_t) * numParticles; + size_t size = paramoffs + paramsize; + + qfv_particle_system_t *system = QFV_PacketExtend (packet, size); + *system = (qfv_particle_system_t) { + .vertexCount = 1, + .particleCount = numParticles, + }; + __auto_type particles = (qfv_particle_t *) ((byte *)system + partoffs); + memcpy (particles, pctx->psystem->particles, partsize); + qfv_parameters_t *params = (qfv_parameters_t *)((byte *)system + paramoffs); + memcpy (params, pctx->psystem->partparams, paramsize); + + if (!numParticles) { + // if there are no particles, then no space for the particle states or + // parameters has been allocated in the staging buffer, so map the + // two buffers over the system buffer. This avoids either buffer being + // just past the end of the staging buffer (which the validation layers + // (correctly) do not like). + // This is fine because the two buffers are only read by the compute + // shader. + partsize = paramsize = syssize; + partoffs = paramoffs = 0; + } + + size_t sysoffs = packet->offset; + VkDescriptorBufferInfo bufferInfo[] = { + { packet->stage->buffer, sysoffs + partoffs, partsize}, + { packet->stage->buffer, sysoffs + paramoffs, paramsize}, + { packet->stage->buffer, sysoffs, syssize }, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + pframe->newDescriptors, 0, 0, 3, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .pBufferInfo = bufferInfo + }, + }; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); + + __auto_type pipeline = taskctx->pipeline; + pipeline->dispatch = (vec4u_t) {1, 1, 1}; + pipeline->num_descriptorsets = 3; + pipeline->descriptorsets[0] = pframe->curDescriptors; + pipeline->descriptorsets[1] = pframe->inDescriptors; + pipeline->descriptorsets[2] = pframe->newDescriptors; + + QFV_PacketSubmit (packet); + + pctx->psystem->numparticles = 0; } static void particle_physics (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + __auto_type taskctx = (qfv_taskctx_t *) ectx; + vulkan_ctx_t *ctx = taskctx->ctx; + + particlectx_t *pctx = ctx->particle_context; + __auto_type pframe = &pctx->frames.a[ctx->curFrame]; + + __auto_type pipeline = taskctx->pipeline; + pipeline->dispatch = (vec4u_t) {MaxParticles, 1, 1}; + pipeline->num_descriptorsets = 1; + pipeline->descriptorsets[0] = pframe->curDescriptors; + + struct { + qfv_push_constants_t push_constants[2]; + particle_push_constants_t constants; + } push = { + .push_constants = { + { VK_SHADER_STAGE_COMPUTE_BIT, + field_offset (particle_push_constants_t, gravity), + sizeof (vec4f_t), &push.constants.gravity }, + { VK_SHADER_STAGE_COMPUTE_BIT, + field_offset (particle_push_constants_t, dT), + sizeof (float), &push.constants.dT }, + }, + .constants = { + .gravity = pctx->psystem->gravity, + .dT = vr_data.frametime, + }, + }; + if (!pipeline->push_constants) { + //FIXME figure out something better for managing push constants + pipeline->push_constants = malloc (sizeof (push)); + } + memcpy (pipeline->push_constants, &push, sizeof (push)); + pipeline->num_push_constants = 2; } static exprfunc_t particles_draw_func[] = { diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index 2cac52ee6..f79bfccc6 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -67,6 +67,57 @@ static const char * __attribute__((used)) translucent_pass_names[] = { static void clear_translucent (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + __auto_type taskctx = (qfv_taskctx_t *) ectx; + vulkan_ctx_t *ctx = taskctx->ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + translucentctx_t *tctx = ctx->translucent_context; + __auto_type tframe = &tctx->frames.a[ctx->curFrame]; + + VkCommandBuffer cmd = QFV_GetCmdBufffer (ctx, false); + + VkCommandBufferInheritanceInfo inherit = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, + 0, 0, 0, + 0, 0, 0, + }; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, &inherit, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; + ib.barrier.image = tframe->heads; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + VkClearColorValue clear_color[] = { + { .int32 = {-1, -1, -1, -1} }, + }; + VkImageSubresourceRange ranges[] = { + { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, VK_REMAINING_ARRAY_LAYERS }, + }; + dfunc->vkCmdClearColorImage (cmd, tframe->heads, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + clear_color, 1, ranges); + ib = imageBarriers[qfv_LT_TransferDst_to_General]; + ib.barrier.image = tframe->heads; + ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, + 0, 0, 0, 0, 0, + 1, &ib.barrier); + + dfunc->vkEndCommandBuffer (cmd); + QFV_AppendCmdBuffer (ctx, cmd); + + qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); + qfv_transtate_t *state = QFV_PacketExtend (packet, 2 * sizeof (*state)); + *state = (qfv_transtate_t) { 0, tctx->maxFragments }; + __auto_type bb = &bufferBarriers[qfv_BB_TransferWrite_to_ShaderRW]; + QFV_PacketCopyBuffer (packet, tframe->state, 0, bb); + QFV_PacketSubmit (packet); } static exprfunc_t clear_translucent_func[] = { From 387051fedfe40241f9c459c8fc815794bd2a2c9f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 15 Jun 2023 17:29:41 +0900 Subject: [PATCH 3606/3664] [vulkan] Split up render job loading and running The creation of the render jobs doesn't really belong with the running of those jobs. This makes the code a little easier to navigate as it was too easy to lost between load-time and run-time code. --- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vulkan/render.c | 1036 -------------------- libs/video/renderer/vulkan/render_load.c | 1088 ++++++++++++++++++++++ 3 files changed, 1089 insertions(+), 1036 deletions(-) create mode 100644 libs/video/renderer/vulkan/render_load.c diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 52df27996..728c20e48 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -234,6 +234,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/pipeline.c \ libs/video/renderer/vulkan/projection.c \ libs/video/renderer/vulkan/render.c \ + libs/video/renderer/vulkan/render_load.c \ libs/video/renderer/vulkan/resource.c \ libs/video/renderer/vulkan/scrap.c \ libs/video/renderer/vulkan/shader.c \ diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 21a71334f..c2b98814c 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -260,1042 +260,6 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) } } -static qfv_output_t -get_output (vulkan_ctx_t *ctx, plitem_t *item) -{ - qfv_output_t output = {}; - Vulkan_ConfigOutput (ctx, &output); - - plitem_t *output_def = PL_ObjectForKey (item, "output"); - if (output_def) { - // QFV_ParseOutput clears the structure, but extent and frames need to - // be preserved - qfv_output_t o = output; - QFV_ParseOutput (ctx, &o, output_def, item); - output.format = o.format; - output.finalLayout = o.finalLayout; - } - return output; -} - -void -QFV_LoadRenderInfo (vulkan_ctx_t *ctx) -{ - __auto_type rctx = ctx->render_context; - - plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); - __auto_type output = get_output (ctx, item); - Vulkan_Script_SetOutput (ctx, &output); - rctx->jobinfo = QFV_ParseJobInfo (ctx, item, rctx); - if (rctx->jobinfo) { - rctx->jobinfo->plitem = item; - } -} - -typedef struct { - uint32_t num_images; - uint32_t num_imageviews; - uint32_t num_buffers; - uint32_t num_bufferviews; - uint32_t num_layouts; - - uint32_t num_steps; - uint32_t num_render; - uint32_t num_compute; - uint32_t num_process; - uint32_t num_tasks; - - uint32_t num_renderpasses; - uint32_t num_attachments; - uint32_t num_subpasses; - uint32_t num_dependencies; - uint32_t num_attachmentrefs; - uint32_t num_colorblend; - uint32_t num_preserve; - uint32_t num_graph_pipelines; - uint32_t num_comp_pipelines; - - uint32_t num_descriptorsets; -} objcount_t; - -static void -count_as_stuff (qfv_attachmentsetinfo_t *as, objcount_t *counts) -{ - counts->num_attachmentrefs += as->num_input; - counts->num_attachmentrefs += as->num_color; - counts->num_colorblend += as->num_color; - if (as->resolve) { - counts->num_attachmentrefs += as->num_color; - } - if (as->depth) { - counts->num_attachmentrefs += 1; - } - counts->num_preserve += as->num_preserve; -} - -static void -count_sp_stuff (qfv_subpassinfo_t *spi, objcount_t *counts) -{ - counts->num_dependencies += spi->num_dependencies; - if (spi->attachments) { - count_as_stuff (spi->attachments, counts); - } - for (uint32_t i = 0; i < spi->num_pipelines; i++) { - __auto_type pli = &spi->pipelines[i]; - if (pli->num_graph_stages && !pli->compute_stage) { - counts->num_graph_pipelines++; - counts->num_tasks += pli->num_tasks; - } else { - Sys_Error ("%s:%s: invalid graphics pipeline", - spi->name, pli->name); - } - } -} - -static void -count_rp_stuff (qfv_renderpassinfo_t *rpi, objcount_t *counts) -{ - counts->num_attachments += rpi->num_attachments; - counts->num_subpasses += rpi->num_subpasses; - for (uint32_t i = 0; i < rpi->num_subpasses; i++) { - count_sp_stuff (&rpi->subpasses[i], counts); - } -} - -static void -count_comp_stuff (qfv_computeinfo_t *ci, objcount_t *counts) -{ - for (uint32_t i = 0; i < ci->num_pipelines; i++) { - __auto_type pli = &ci->pipelines[i]; - if (!pli->num_graph_stages && pli->compute_stage) { - counts->num_comp_pipelines++; - counts->num_tasks += pli->num_tasks; - } else { - Sys_Error ("%s:%s: invalid compute pipeline", - ci->name, pli->name); - } - } -} - -static void -count_step_stuff (qfv_stepinfo_t *step, objcount_t *counts) -{ - if ((step->render && step->compute) - || (step->render && step->process) - || (step->compute && step->process)) { - Sys_Error ("%s: invalid step: must be one of render/compute/process", - step->name); - } - if (step->render) { - __auto_type rinfo = step->render; - counts->num_renderpasses += rinfo->num_renderpasses; - for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { - count_rp_stuff (&rinfo->renderpasses[i], counts); - } - counts->num_render++; - } - if (step->compute) { - count_comp_stuff (step->compute, counts); - counts->num_compute++; - } - if (step->process) { - counts->num_process++; - counts->num_tasks += step->process->num_tasks; - } - counts->num_steps++; -} - -static void -count_stuff (qfv_jobinfo_t *jobinfo, objcount_t *counts) -{ - counts->num_images += jobinfo->num_images; - counts->num_imageviews += jobinfo->num_imageviews; - counts->num_buffers += jobinfo->num_buffers; - counts->num_bufferviews += jobinfo->num_bufferviews; - for (uint32_t i = 0; i < jobinfo->num_steps; i++) { - count_step_stuff (&jobinfo->steps[i], counts); - } -} - -static void -create_resources (vulkan_ctx_t *ctx, objcount_t *counts) -{ - __auto_type rctx = ctx->render_context; - __auto_type jinfo = rctx->jobinfo; - __auto_type job = rctx->job; - - job->resources = malloc (sizeof(qfv_resource_t) - + counts->num_images * sizeof (qfv_resobj_t) - + counts->num_imageviews * sizeof (qfv_resobj_t)); - job->images = (qfv_resobj_t *) &job->resources[1]; - job->image_views = &job->images[counts->num_images]; - - job->resources[0] = (qfv_resource_t) { - .name = "render", - .va_ctx = ctx->va_ctx, - .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .num_objects = counts->num_images + counts->num_imageviews, - .objects = job->images, - }; - for (uint32_t i = 0; i < counts->num_images; i++) { - __auto_type img = &jinfo->images[i]; - job->images[i] = (qfv_resobj_t) { - .name = img->name, - .type = qfv_res_image, - .image = { - .flags = img->flags, - .type = img->imageType, - .format = img->format, - .extent = img->extent, - .num_mipmaps = img->mipLevels, - .num_layers = img->arrayLayers, - .samples = img->samples, - .tiling = img->tiling, - .usage = img->usage, - .initialLayout = img->initialLayout, - }, - }; - } - int error = 0; - for (uint32_t i = 0; i < counts->num_imageviews; i++) { - __auto_type view = &jinfo->imageviews[i]; - job->image_views[i] = (qfv_resobj_t) { - .name = view->name, - .type = qfv_res_image_view, - .image_view = { - .flags = view->flags, - .type = view->viewType, - .format = view->format, - .components = view->components, - .subresourceRange = view->subresourceRange, - }, - }; - if (strcmp (view->image.name, "$output.image") == 0) { - //__auto_type image = jinfo->output.image; - //job->image_views[i].image_view.external_image = image; - //job->image_views[i].image_view.image = -1; - } else { - qfv_resobj_t *img = 0; - for (uint32_t j = 0; j < jinfo->num_images; j++) { - if (strcmp (view->image.name, jinfo->images[j].name) == 0) { - img = &job->images[j]; - } - } - if (img) { - uint32_t ind = img - job->resources->objects; - job->image_views[i].image_view.image = ind; - } else { - Sys_Printf ("%d: unknown image reference: %s\n", - view->image.line, view->image.name); - error = 1; - } - } - } - if (error) { - free (job->resources); - job->resources = 0; - return; - } - QFV_CreateResource (ctx->device, job->resources); -} - -typedef struct { - VkRenderPassCreateInfo *rpCreate; - VkAttachmentDescription *attach; - VkClearValue *clear; - VkSubpassDescription *subpass; - VkSubpassDependency *depend; - VkAttachmentReference *attachref; - VkPipelineColorBlendAttachmentState *cbAttach; - uint32_t *preserve; - const char **rpName; - const char **plName; - VkComputePipelineCreateInfo *cplCreate; - VkGraphicsPipelineCreateInfo *gplCreate; - VkPipelineColorBlendStateCreateInfo *cbState; - qfv_layoutinfo_t *layouts; - - uint32_t *pl_counts; - - VkPipeline *gpl; - VkPipeline *cpl; - VkRenderPass *rp; -} objptr_t; - -typedef struct { - objcount_t inds; - objptr_t ptr; - - vulkan_ctx_t *ctx; - qfv_jobinfo_t *jinfo; - exprtab_t *symtab; - qfv_renderpassinfo_t *rpi; - VkRenderPassCreateInfo *rpc; - qfv_subpassinfo_t *spi; - VkSubpassDescription *spc; - qfv_pipelineinfo_t *pli; - VkGraphicsPipelineCreateInfo *plc; -} objstate_t; - -static uint32_t __attribute__((pure)) -find_subpass (qfv_dependencyinfo_t *d, uint32_t spind, - qfv_subpassinfo_t *subpasses) -{ - if (strcmp (d->name, "$external") == 0) { - return VK_SUBPASS_EXTERNAL; - } - for (uint32_t i = 0; i <= spind; i++) { - __auto_type s = &subpasses[i]; - if (strcmp (d->name, s->name) == 0) { - return i; - } - } - Sys_Error ("invalid dependency: [%d] %s", spind, d->name); -} - -static VkDescriptorSetLayout -find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) -{ - for (uint32_t i = 0; i < s->jinfo->num_descriptorsetlayouts; i++) { - __auto_type ds = &s->jinfo->descriptorsetlayouts[i]; - if (strcmp (ds->name, ref->name) == 0) { - if (!ds->setLayout) { - VkDescriptorSetLayoutCreateInfo cInfo = { - .sType=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .flags = ds->flags, - .bindingCount = ds->num_bindings, - .pBindings = ds->bindings, - }; - qfv_device_t *device = s->ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, - &ds->setLayout); - QFV_duSetObjectName (device, - VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, - ds->setLayout, - va (s->ctx->va_ctx, "descriptorSet:%s", - ds->name)); - } - return ds->setLayout; - } - } - Sys_Error ("%s.%s:%d: invalid descriptor set layout: %s", - s->rpi->name, s->spi->name, ref->line, ref->name); -} - -static qfv_layoutinfo_t * -find_layout (const qfv_reference_t *ref, objstate_t *s) -{ - for (uint32_t i = 0; i < s->inds.num_layouts; i++) { - if (strcmp (s->ptr.layouts[i].name, ref->name) == 0) { - return &s->ptr.layouts[i]; - } - } - if (!QFV_ParseLayoutInfo (s->ctx, s->jinfo->memsuper, s->symtab, ref->name, - &s->ptr.layouts[s->inds.num_layouts])) { - Sys_Error ("%s.%s:%d: invalid layout: %s", - s->rpi->name, s->spi->name, ref->line, ref->name); - } - __auto_type li = &s->ptr.layouts[s->inds.num_layouts++]; - li->name = ref->name; - VkDescriptorSetLayout sets[li->num_sets]; - for (uint32_t i = 0; i < li->num_sets; i++) { - sets[i] = find_descriptorSet (&li->sets[i], s); - } - VkPipelineLayoutCreateInfo cInfo = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = li->num_sets, - .pSetLayouts = sets, - .pushConstantRangeCount = li->num_ranges, - .pPushConstantRanges = li->ranges, - }; - qfv_device_t *device = s->ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &li->layout); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, li->layout, - va (s->ctx->va_ctx, "layout:%s", li->name)); - return li; -} - -static void -init_plCreate (VkGraphicsPipelineCreateInfo *plc, const qfv_pipelineinfo_t *pli, - objstate_t *s) -{ - if (pli->num_graph_stages) { - plc->stageCount = pli->num_graph_stages; - } - if (pli->graph_stages) { - plc->pStages = pli->graph_stages; - } - if (pli->vertexInput) { - plc->pVertexInputState = pli->vertexInput; - } - if (pli->inputAssembly) { - plc->pInputAssemblyState = pli->inputAssembly; - } - if (pli->tessellation) { - plc->pTessellationState = pli->tessellation; - } - if (pli->viewport) { - plc->pViewportState = pli->viewport; - } - if (pli->rasterization) { - plc->pRasterizationState = pli->rasterization; - } - if (pli->multisample) { - plc->pMultisampleState = pli->multisample; - } - if (pli->depthStencil) { - plc->pDepthStencilState = pli->depthStencil; - } - if (pli->colorBlend) { - VkPipelineColorBlendStateCreateInfo *cb; - cb = (VkPipelineColorBlendStateCreateInfo *) plc->pColorBlendState; - *cb = *pli->colorBlend; - } - if (pli->dynamic) { - plc->pDynamicState = pli->dynamic; - } - if (pli->layout.name) { - __auto_type li = find_layout (&pli->layout, s); - plc->layout = li->layout; - s->inds.num_descriptorsets += li->num_sets; - } -} - -static uint32_t __attribute__((pure)) -find_attachment (qfv_reference_t *ref, objstate_t *s) -{ - for (uint32_t i = 0; i < s->rpi->num_attachments; i++) { - __auto_type a = &s->rpi->attachments[i]; - if (strcmp (ref->name, a->name) == 0) { - return i; - } - } - Sys_Error ("%s.%s:%d: invalid attachment: %s", - s->rpi->name, s->spi->name, ref->line, ref->name); -} - -static void -init_arCreate (const qfv_attachmentrefinfo_t *ari, objstate_t *s) -{ - __auto_type arc = &s->ptr.attachref[s->inds.num_attachmentrefs]; - qfv_reference_t ref = { - .name = ari->name, - .line = ari->line, - }; - - *arc = (VkAttachmentReference) { - .attachment = find_attachment (&ref, s), - .layout = ari->layout, - }; -} - -static void -init_cbCreate (const qfv_attachmentrefinfo_t *ari, objstate_t *s) -{ - __auto_type cbc = &s->ptr.cbAttach[s->inds.num_colorblend]; - - *cbc = ari->blend; -} - -static void -init_spCreate (uint32_t index, qfv_subpassinfo_t *sub, objstate_t *s) -{ - s->spi = &sub[index]; - s->plc = &s->ptr.gplCreate[s->inds.num_graph_pipelines]; - s->spc = &s->ptr.subpass[s->inds.num_subpasses]; - __auto_type pln = &s->ptr.plName[s->inds.num_graph_pipelines]; - __auto_type cbs = &s->ptr.cbState[s->inds.num_graph_pipelines]; - - s->ptr.pl_counts[s->inds.num_renderpasses] += s->spi->num_pipelines; - - *s->spc = (VkSubpassDescription) { - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - }; - for (uint32_t i = 0; i < s->spi->num_dependencies; i++) { - __auto_type d = &s->spi->dependencies[i]; - __auto_type dep = &s->ptr.depend[s->inds.num_dependencies++]; - *dep = (VkSubpassDependency) { - .srcSubpass = find_subpass (d, index, s->rpi->subpasses), - .dstSubpass = index, - .srcStageMask = d->src.stage, - .dstStageMask = d->dst.stage, - .srcAccessMask = d->src.access, - .dstAccessMask = d->dst.access, - .dependencyFlags = d->flags, - }; - } - - for (uint32_t i = 0; i < s->spi->num_pipelines; i++) { - s->plc[i] = (VkGraphicsPipelineCreateInfo) { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pColorBlendState = &cbs[i], - .subpass = index, - }; - if (s->spi->base_pipeline) { - init_plCreate (&s->plc[i], s->spi->base_pipeline, s); - } - init_plCreate (&s->plc[i], &s->spi->pipelines[i], s); - pln[i] = s->spi->name; - s->inds.num_graph_pipelines++; - } - - __auto_type att = s->spi->attachments; - if (!att) { - return; - } - for (uint32_t i = 0; i < s->spi->num_pipelines; i++) { - cbs[i].attachmentCount = att->num_color; - cbs[i].pAttachments = &s->ptr.cbAttach[s->inds.num_colorblend]; - } - s->spc->inputAttachmentCount = att->num_input; - s->spc->pInputAttachments = &s->ptr.attachref[s->inds.num_attachmentrefs]; - for (uint32_t i = 0; i < att->num_input; i++) { - init_arCreate (&att->input[i], s); - s->inds.num_attachmentrefs++; - } - s->spc->colorAttachmentCount = att->num_color; - s->spc->pColorAttachments = &s->ptr.attachref[s->inds.num_attachmentrefs]; - for (uint32_t i = 0; i < att->num_color; i++) { - init_arCreate (&att->color[i], s); - s->inds.num_attachmentrefs++; - init_cbCreate (&att->color[i], s); - s->inds.num_colorblend++; - } - if (att->resolve) { - s->spc->pResolveAttachments - = &s->ptr.attachref[s->inds.num_attachmentrefs]; - for (uint32_t i = 0; i < att->num_color; i++) { - init_arCreate (&att->resolve[i], s); - s->inds.num_attachmentrefs++; - } - } - if (att->depth) { - s->spc->pDepthStencilAttachment - = &s->ptr.attachref[s->inds.num_attachmentrefs]; - init_arCreate (att->depth, s); - s->inds.num_attachmentrefs++; - } - s->spc->preserveAttachmentCount = att->num_preserve; - s->spc->pPreserveAttachments = &s->ptr.preserve[s->inds.num_preserve]; - for (uint32_t i = 0; i < att->num_preserve; i++) { - s->ptr.preserve[s->inds.num_preserve] - = find_attachment (&att->preserve[i], s); - s->inds.num_preserve++; - } -} - -static void -init_atCreate (uint32_t index, qfv_attachmentinfo_t *attachments, objstate_t *s) -{ - __auto_type ati = &attachments[index]; - __auto_type atc = &s->ptr.attach[s->inds.num_attachments]; - __auto_type cvc = &s->ptr.clear[s->inds.num_attachments]; - - *atc = (VkAttachmentDescription) { - .flags = ati->flags, - .format = ati->format, - .samples = ati->samples, - .loadOp = ati->loadOp, - .storeOp = ati->storeOp, - .stencilLoadOp = ati->stencilLoadOp, - .stencilStoreOp = ati->stencilStoreOp, - .initialLayout = ati->initialLayout, - .finalLayout = ati->finalLayout, - }; - *cvc = ati->clearValue; -} - -static void -init_rpCreate (uint32_t index, const qfv_renderinfo_t *rinfo, objstate_t *s) -{ - s->rpi = &rinfo->renderpasses[index]; - s->rpc = &s->ptr.rpCreate[s->inds.num_renderpasses]; - s->ptr.rpName[s->inds.num_renderpasses] = s->rpi->name; - - __auto_type attachments = &s->ptr.attach[s->inds.num_attachments]; - __auto_type subpasses = &s->ptr.subpass[s->inds.num_subpasses]; - __auto_type dependencies = &s->ptr.depend[s->inds.num_dependencies]; - - for (uint32_t i = 0; i < s->rpi->num_attachments; i++) { - init_atCreate (i, s->rpi->attachments, s); - s->inds.num_attachments++; - } - - uint32_t num_dependencies = s->inds.num_dependencies; - for (uint32_t i = 0; i < s->rpi->num_subpasses; i++) { - init_spCreate (i, s->rpi->subpasses, s); - s->inds.num_subpasses++; - } - num_dependencies = s->inds.num_dependencies - num_dependencies; - - *s->rpc = (VkRenderPassCreateInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = s->rpi->num_attachments, - .pAttachments = attachments, - .subpassCount = s->rpi->num_subpasses, - .pSubpasses = subpasses, - .dependencyCount = num_dependencies, - .pDependencies = dependencies, - }; -} - -typedef struct { - qfv_step_t *steps; - qfv_render_t *renders; - qfv_compute_t *computes; - qfv_process_t *processes; - qfv_renderpass_t *renderpasses; - VkClearValue *clearvalues; - qfv_subpass_t *subpasses; - qfv_pipeline_t *pipelines; - qfv_taskinfo_t *tasks; - VkDescriptorSet *descriptorsets; -} jobptr_t; - -static void -init_pipeline (qfv_pipeline_t *pl, qfv_pipelineinfo_t *plinfo, - jobptr_t *jp, objstate_t *s, int is_compute) -{ - __auto_type li = find_layout (&plinfo->layout, s); - *pl = (qfv_pipeline_t) { - .label = { - .name = plinfo->name, - .color = plinfo->color, - }, - .bindPoint = is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE - : VK_PIPELINE_BIND_POINT_GRAPHICS, - .pipeline = is_compute ? s->ptr.cpl[s->inds.num_comp_pipelines] - : s->ptr.gpl[s->inds.num_graph_pipelines], - .layout = li->layout, - .task_count = plinfo->num_tasks, - .tasks = &jp->tasks[s->inds.num_tasks], - .descriptorsets = &jp->descriptorsets[s->inds.num_descriptorsets], - }; - s->inds.num_tasks += plinfo->num_tasks; - s->inds.num_descriptorsets += li->num_sets; - for (uint32_t i = 0; i < li->num_sets; i++) { - pl->descriptorsets[i] = 0; - } - for (uint32_t i = 0; i < pl->task_count; i++) { - pl->tasks[i] = plinfo->tasks[i]; - } -} - -static void -init_subpass (qfv_subpass_t *sp, qfv_subpassinfo_t *isp, - jobptr_t *jp, objstate_t *s) -{ - uint32_t np = s->inds.num_graph_pipelines + s->inds.num_comp_pipelines; - *sp = (qfv_subpass_t) { - .label = { - .name = isp->name, - .color = isp->color, - }, - .inherit = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, - }, - .beginInfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, - .pInheritanceInfo = &sp->inherit, - }, - .pipeline_count = isp->num_pipelines, - .pipelines = &jp->pipelines[np], - }; - for (uint32_t i = 0; i < isp->num_pipelines; i++) { - init_pipeline (&sp->pipelines[i], &isp->pipelines[i], jp, s, 0); - s->inds.num_graph_pipelines++; - } -} - -static void -init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo, - jobptr_t *jp, objstate_t *s) -{ - *rp = (qfv_renderpass_t) { - .vulkan_ctx = s->ctx, - .label.name = rpinfo->name, - .label.color = rpinfo->color, - .subpass_count = rpinfo->num_subpasses, - .subpasses = &jp->subpasses[s->inds.num_subpasses], - .beginInfo = (VkRenderPassBeginInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = s->ptr.rp[s->inds.num_renderpasses], - .clearValueCount = rpinfo->num_attachments, - .pClearValues = &jp->clearvalues[s->inds.num_attachments], - }, - .subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, - }; - s->inds.num_attachments += rpinfo->num_attachments; - for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) { - init_subpass (&rp->subpasses[i], &rpinfo->subpasses[i], jp, s); - rp->subpasses[i].inherit.renderPass = rp->beginInfo.renderPass; - rp->subpasses[i].inherit.subpass = i; - s->inds.num_subpasses++; - } -} - -static void -init_render (qfv_render_t *rend, qfv_renderinfo_t *rinfo, - jobptr_t *jp, objstate_t *s) -{ - *rend = (qfv_render_t) { - .label.color = rinfo->color, - .label.name = rinfo->name, - .num_renderpasses = rinfo->num_renderpasses, - .renderpasses = &jp->renderpasses[s->inds.num_renderpasses], - }; - s->inds.num_renderpasses += rinfo->num_renderpasses; - for (uint32_t i = 0; i < rend->num_renderpasses; i++) { - init_renderpass (&rend->renderpasses[i], &rinfo->renderpasses[i], - jp, s); - } - rend->active = &rend->renderpasses[0]; -} - -static void -init_compute (qfv_compute_t *comp, qfv_computeinfo_t *cinfo, - jobptr_t *jp, objstate_t *s) -{ - uint32_t np = s->inds.num_graph_pipelines + s->inds.num_comp_pipelines; - *comp = (qfv_compute_t) { - .label.color = cinfo->color, - .label.name = cinfo->name, - .pipelines = &jp->pipelines[np], - .pipeline_count = cinfo->num_pipelines, - }; - for (uint32_t i = 0; i < cinfo->num_pipelines; i++) { - init_pipeline (&comp->pipelines[i], &cinfo->pipelines[i], jp, s, 1); - s->inds.num_comp_pipelines++; - } -} - -static void -init_process (qfv_process_t *proc, qfv_processinfo_t *pinfo, - jobptr_t *jp, objstate_t *s) -{ - *proc = (qfv_process_t) { - .label.color = pinfo->color, - .label.name = pinfo->name, - .tasks = &jp->tasks[s->inds.num_tasks], - .task_count = pinfo->num_tasks, - }; - s->inds.num_tasks += pinfo->num_tasks; - for (uint32_t i = 0; i < proc->task_count; i++) { - proc->tasks[i] = pinfo->tasks[i]; - } -} - -static void -init_step (uint32_t ind, jobptr_t *jp, objstate_t *s) -{ - __auto_type step = &jp->steps[s->inds.num_steps++]; - __auto_type sinfo = &s->jinfo->steps[ind]; - - *step = (qfv_step_t) { - .label.name = sinfo->name, - .label.color = sinfo->color, - }; - if (sinfo->render) { - step->render = &jp->renders[s->inds.num_render++]; - init_render (step->render, sinfo->render, jp, s); - } - if (sinfo->compute) { - step->compute = &jp->computes[s->inds.num_compute++]; - init_compute (step->compute, sinfo->compute, jp, s); - } - if (sinfo->process) { - step->process = &jp->processes[s->inds.num_process++]; - init_process (step->process, sinfo->process, jp, s); - } -} - -static void -init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) -{ - __auto_type rctx = ctx->render_context; - - size_t size = sizeof (qfv_job_t); - - size += counts->num_renderpasses * sizeof (VkRenderPass); - size += counts->num_graph_pipelines * sizeof (VkPipeline); - size += counts->num_comp_pipelines * sizeof (VkPipeline); - size += s.inds.num_layouts * sizeof (VkPipelineLayout); - - size += counts->num_steps * sizeof (qfv_step_t); - size += counts->num_render * sizeof (qfv_render_t); - size += counts->num_compute * sizeof (qfv_compute_t); - size += counts->num_process * sizeof (qfv_process_t); - size += counts->num_renderpasses * sizeof (qfv_renderpass_t); - size += counts->num_attachments * sizeof (VkClearValue); - size += counts->num_subpasses * sizeof (qfv_subpass_t); - size += counts->num_graph_pipelines * sizeof (qfv_pipeline_t); - size += counts->num_comp_pipelines * sizeof (qfv_pipeline_t); - size += counts->num_tasks * sizeof (qfv_taskinfo_t); - size += counts->num_descriptorsets * sizeof (VkDescriptorSet); - - rctx->job = malloc (size); - __auto_type job = rctx->job; - *job = (qfv_job_t) { - .num_renderpasses = counts->num_renderpasses, - .num_pipelines = counts->num_graph_pipelines - + counts->num_comp_pipelines, - .num_layouts = s.inds.num_layouts, - .num_steps = counts->num_steps, - .commands = DARRAY_STATIC_INIT (16), - }; - job->renderpasses = (VkRenderPass *) &job[1]; - job->pipelines = (VkPipeline *) &job->renderpasses[job->num_renderpasses]; - job->layouts = (VkPipelineLayout *) &job->pipelines[job->num_pipelines]; - job->steps = (qfv_step_t *) &job->layouts[job->num_layouts]; - __auto_type rn = (qfv_render_t *) &job->steps[job->num_steps]; - __auto_type cp = (qfv_compute_t *) &rn[counts->num_render]; - __auto_type pr = (qfv_process_t *) &cp[counts->num_compute]; - __auto_type rp = (qfv_renderpass_t *) &pr[counts->num_process]; - __auto_type cv = (VkClearValue *) &rp[counts->num_renderpasses]; - __auto_type sp = (qfv_subpass_t *) &cv[counts->num_attachments]; - __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; - __auto_type ti = (qfv_taskinfo_t *) &pl[job->num_pipelines]; - __auto_type ds = (VkDescriptorSet *) &ti[counts->num_tasks]; - jobptr_t jp = { - .steps = job->steps, - .renders = rn, - .computes = cp, - .processes = pr, - .renderpasses = rp, - .clearvalues = cv, - .subpasses = sp, - .pipelines = pl, - .tasks = ti, - .descriptorsets = ds, - }; - - for (uint32_t i = 0; i < job->num_renderpasses; i++) { - job->renderpasses[i] = s.ptr.rp[i]; - } - for (uint32_t i = 0; i < job->num_pipelines; i++) { - // compute pipelines come immediately after the graphics pipelines - job->pipelines[i] = s.ptr.gpl[i]; - } - for (uint32_t i = 0; i < s.inds.num_layouts; i++) { - job->layouts[i] = s.ptr.layouts[i].layout; - } - memcpy (cv, s.ptr.clear, counts->num_attachments * sizeof (VkClearValue)); - - uint32_t num_layouts = s.inds.num_layouts; - s.inds = (objcount_t) {}; - s.inds.num_layouts = num_layouts; - for (uint32_t i = 0; i < job->num_steps; i++) { - init_step (i, &jp, &s); - } - - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkCommandPoolCreateInfo poolCInfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - .queueFamilyIndex = device->queue.queueFamily, - }; - dfunc->vkCreateCommandPool (device->dev, &poolCInfo, 0, &job->command_pool); -} - -static void -create_step_render_objects (uint32_t index, const qfv_stepinfo_t *step, - objstate_t *s) -{ - __auto_type rinfo = step->render; - if (!rinfo) { - return; - } - for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { - s->ptr.pl_counts[s->inds.num_renderpasses] = 0; - init_rpCreate (i, rinfo, s); - s->inds.num_renderpasses++; - } -} - -static void -create_step_compute_objects (uint32_t index, const qfv_stepinfo_t *step, - objstate_t *s) -{ - __auto_type cinfo = step->compute; - if (!cinfo) { - return; - } - - uint32_t base = s->inds.num_graph_pipelines; - for (uint32_t i = 0; i < cinfo->num_pipelines; i++) { - __auto_type pli = &cinfo->pipelines[i]; - __auto_type plc = &s->ptr.cplCreate[s->inds.num_comp_pipelines]; - __auto_type li = find_layout (&pli->layout, s); - s->ptr.plName[base + s->inds.num_comp_pipelines] = pli->name; - *plc = (VkComputePipelineCreateInfo) { - .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - .flags = pli->flags, - .stage = *pli->compute_stage, - .layout = li->layout, - }; - plc->stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; - s->inds.num_comp_pipelines++; - s->inds.num_descriptorsets += li->num_sets; - } -} - -static void -create_step_process_objects (uint32_t index, const qfv_stepinfo_t *step, - objstate_t *s) -{ - __auto_type pinfo = step->process; - if (!pinfo) { - return; - } - // nothing to create at this stage -} - -static void -create_objects (vulkan_ctx_t *ctx, objcount_t *counts) -{ - __auto_type rctx = ctx->render_context; - __auto_type jinfo = rctx->jobinfo; - - VkRenderPass renderpasses[counts->num_renderpasses]; - VkPipeline pipelines[counts->num_graph_pipelines - + counts->num_comp_pipelines]; - VkRenderPassCreateInfo rpCreate[counts->num_renderpasses]; - VkAttachmentDescription attach[counts->num_attachments]; - VkClearValue clear[counts->num_attachments]; - VkSubpassDescription subpass[counts->num_subpasses]; - VkSubpassDependency depend[counts->num_dependencies]; - VkAttachmentReference attachref[counts->num_attachmentrefs]; - VkPipelineColorBlendAttachmentState cbAttach[counts->num_colorblend]; - uint32_t preserve[counts->num_preserve]; - const char *rpName[counts->num_renderpasses]; - const char *plName[counts->num_graph_pipelines - + counts->num_comp_pipelines]; - VkComputePipelineCreateInfo cplCreate[counts->num_comp_pipelines]; - VkGraphicsPipelineCreateInfo gplCreate[counts->num_graph_pipelines]; - VkPipelineColorBlendStateCreateInfo cbState[counts->num_graph_pipelines]; - qfv_layoutinfo_t layouts[counts->num_graph_pipelines - + counts->num_comp_pipelines]; - uint32_t pl_counts[counts->num_renderpasses]; - - exprctx_t ectx = { .hashctx = &ctx->script_context->hashctx }; - objstate_t s = { - .ptr = { - .rpCreate = rpCreate, - .attach = attach, - .clear = clear, - .subpass = subpass, - .depend = depend, - .attachref = attachref, - .cbAttach = cbAttach, - .preserve = preserve, - .rpName = rpName, - .plName = plName, - .cplCreate = cplCreate, - .gplCreate = gplCreate, - .cbState = cbState, - .layouts = layouts, - .pl_counts = pl_counts, - .rp = renderpasses, - .gpl = pipelines, - .cpl = pipelines + counts->num_graph_pipelines, - }, - .ctx = ctx, - .jinfo = jinfo, - .symtab = QFV_CreateSymtab (jinfo->plitem, "properties", 0, 0, &ectx), - }; - for (uint32_t i = 0; i < jinfo->num_steps; i++) { - create_step_render_objects (i, &jinfo->steps[i], &s); - } - for (uint32_t i = 0; i < jinfo->num_steps; i++) { - create_step_compute_objects (i, &jinfo->steps[i], &s); - } - for (uint32_t i = 0; i < jinfo->num_steps; i++) { - create_step_process_objects (i, &jinfo->steps[i], &s); - } - if (s.inds.num_renderpasses != counts->num_renderpasses - || s.inds.num_attachments != counts->num_attachments - || s.inds.num_subpasses != counts->num_subpasses - || s.inds.num_dependencies != counts->num_dependencies - || s.inds.num_attachmentrefs != counts->num_attachmentrefs - || s.inds.num_colorblend != counts->num_colorblend - || s.inds.num_preserve != counts->num_preserve - || s.inds.num_graph_pipelines != counts->num_graph_pipelines - || s.inds.num_comp_pipelines != counts->num_comp_pipelines) { - Sys_Error ("create_objects: something was missed"); - } - - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - uint32_t plInd = 0; - for (uint32_t i = 0; i < counts->num_renderpasses; i++) { - dfunc->vkCreateRenderPass (device->dev, &s.ptr.rpCreate[i], 0, - &renderpasses[i]); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_RENDER_PASS, - renderpasses[i], - va (ctx->va_ctx, "renderpass:%s", rpName[i])); - for (uint32_t j = 0; j < pl_counts[i]; j++) { - s.ptr.gplCreate[plInd++].renderPass = renderpasses[i]; - } - } - if (s.inds.num_graph_pipelines) { - dfunc->vkCreateGraphicsPipelines (device->dev, 0, - s.inds.num_graph_pipelines, - s.ptr.gplCreate, 0, pipelines); - } - if (s.inds.num_comp_pipelines) { - __auto_type p = &pipelines[s.inds.num_graph_pipelines]; - dfunc->vkCreateComputePipelines (device->dev, 0, - s.inds.num_comp_pipelines, - s.ptr.cplCreate, 0, p); - } - for (uint32_t i = 0; - i < s.inds.num_graph_pipelines + s.inds.num_comp_pipelines; i++) { - QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE, pipelines[i], - va (ctx->va_ctx, "pipeline:%s", plName[i])); - } - - counts->num_descriptorsets = s.inds.num_descriptorsets; - init_job (ctx, counts, s); -} - -void -QFV_BuildRender (vulkan_ctx_t *ctx) -{ - __auto_type rctx = ctx->render_context; - - objcount_t counts = {}; - count_stuff (rctx->jobinfo, &counts); - - create_objects (ctx, &counts); - create_resources (ctx, &counts); -} - -static VkImageView __attribute__((pure, used)) -find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx) -{ - __auto_type jinfo = rctx->jobinfo; - __auto_type job = rctx->job; - const char *name = ref->name; - - if (strncmp (name, "$imageviews.", 7) == 0) { - name += 7; - } - - for (uint32_t i = 0; i < jinfo->num_imageviews; i++) { - __auto_type vi = &jinfo->imageviews[i]; - __auto_type vo = &job->image_views[i]; - if (strcmp (name, vi->name) == 0) { - return vo->image_view.view; - } - } - Sys_Error ("%d:invalid imageview: %s", ref->line, ref->name); -} - void QFV_DestroyFramebuffer (vulkan_ctx_t *ctx) { diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c new file mode 100644 index 000000000..76a3aa64b --- /dev/null +++ b/libs/video/renderer/vulkan/render_load.c @@ -0,0 +1,1088 @@ +/* + render_load.c + + Vulkan render manager loading/creation + + Copyright (C) 2023 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_MATH_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/cmem.h" +#include "QF/hash.h" +#include "QF/va.h" +#include "QF/Vulkan/command.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/render.h" +#include "QF/Vulkan/resource.h" +#include "QF/Vulkan/pipeline.h" +#include "vid_vulkan.h" + +#include "vkparse.h" + +static qfv_output_t +get_output (vulkan_ctx_t *ctx, plitem_t *item) +{ + qfv_output_t output = {}; + Vulkan_ConfigOutput (ctx, &output); + + plitem_t *output_def = PL_ObjectForKey (item, "output"); + if (output_def) { + // QFV_ParseOutput clears the structure, but extent and frames need to + // be preserved + qfv_output_t o = output; + QFV_ParseOutput (ctx, &o, output_def, item); + output.format = o.format; + output.finalLayout = o.finalLayout; + } + return output; +} + +void +QFV_LoadRenderInfo (vulkan_ctx_t *ctx) +{ + __auto_type rctx = ctx->render_context; + + plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); + __auto_type output = get_output (ctx, item); + Vulkan_Script_SetOutput (ctx, &output); + rctx->jobinfo = QFV_ParseJobInfo (ctx, item, rctx); + if (rctx->jobinfo) { + rctx->jobinfo->plitem = item; + } +} + +typedef struct { + uint32_t num_images; + uint32_t num_imageviews; + uint32_t num_buffers; + uint32_t num_bufferviews; + uint32_t num_layouts; + + uint32_t num_steps; + uint32_t num_render; + uint32_t num_compute; + uint32_t num_process; + uint32_t num_tasks; + + uint32_t num_renderpasses; + uint32_t num_attachments; + uint32_t num_subpasses; + uint32_t num_dependencies; + uint32_t num_attachmentrefs; + uint32_t num_colorblend; + uint32_t num_preserve; + uint32_t num_graph_pipelines; + uint32_t num_comp_pipelines; + + uint32_t num_descriptorsets; +} objcount_t; + +static void +count_as_stuff (qfv_attachmentsetinfo_t *as, objcount_t *counts) +{ + counts->num_attachmentrefs += as->num_input; + counts->num_attachmentrefs += as->num_color; + counts->num_colorblend += as->num_color; + if (as->resolve) { + counts->num_attachmentrefs += as->num_color; + } + if (as->depth) { + counts->num_attachmentrefs += 1; + } + counts->num_preserve += as->num_preserve; +} + +static void +count_sp_stuff (qfv_subpassinfo_t *spi, objcount_t *counts) +{ + counts->num_dependencies += spi->num_dependencies; + if (spi->attachments) { + count_as_stuff (spi->attachments, counts); + } + for (uint32_t i = 0; i < spi->num_pipelines; i++) { + __auto_type pli = &spi->pipelines[i]; + if (pli->num_graph_stages && !pli->compute_stage) { + counts->num_graph_pipelines++; + counts->num_tasks += pli->num_tasks; + } else { + Sys_Error ("%s:%s: invalid graphics pipeline", + spi->name, pli->name); + } + } +} + +static void +count_rp_stuff (qfv_renderpassinfo_t *rpi, objcount_t *counts) +{ + counts->num_attachments += rpi->num_attachments; + counts->num_subpasses += rpi->num_subpasses; + for (uint32_t i = 0; i < rpi->num_subpasses; i++) { + count_sp_stuff (&rpi->subpasses[i], counts); + } +} + +static void +count_comp_stuff (qfv_computeinfo_t *ci, objcount_t *counts) +{ + for (uint32_t i = 0; i < ci->num_pipelines; i++) { + __auto_type pli = &ci->pipelines[i]; + if (!pli->num_graph_stages && pli->compute_stage) { + counts->num_comp_pipelines++; + counts->num_tasks += pli->num_tasks; + } else { + Sys_Error ("%s:%s: invalid compute pipeline", + ci->name, pli->name); + } + } +} + +static void +count_step_stuff (qfv_stepinfo_t *step, objcount_t *counts) +{ + if ((step->render && step->compute) + || (step->render && step->process) + || (step->compute && step->process)) { + Sys_Error ("%s: invalid step: must be one of render/compute/process", + step->name); + } + if (step->render) { + __auto_type rinfo = step->render; + counts->num_renderpasses += rinfo->num_renderpasses; + for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { + count_rp_stuff (&rinfo->renderpasses[i], counts); + } + counts->num_render++; + } + if (step->compute) { + count_comp_stuff (step->compute, counts); + counts->num_compute++; + } + if (step->process) { + counts->num_process++; + counts->num_tasks += step->process->num_tasks; + } + counts->num_steps++; +} + +static void +count_stuff (qfv_jobinfo_t *jobinfo, objcount_t *counts) +{ + counts->num_images += jobinfo->num_images; + counts->num_imageviews += jobinfo->num_imageviews; + counts->num_buffers += jobinfo->num_buffers; + counts->num_bufferviews += jobinfo->num_bufferviews; + for (uint32_t i = 0; i < jobinfo->num_steps; i++) { + count_step_stuff (&jobinfo->steps[i], counts); + } +} + +static void +create_resources (vulkan_ctx_t *ctx, objcount_t *counts) +{ + __auto_type rctx = ctx->render_context; + __auto_type jinfo = rctx->jobinfo; + __auto_type job = rctx->job; + + job->resources = malloc (sizeof(qfv_resource_t) + + counts->num_images * sizeof (qfv_resobj_t) + + counts->num_imageviews * sizeof (qfv_resobj_t)); + job->images = (qfv_resobj_t *) &job->resources[1]; + job->image_views = &job->images[counts->num_images]; + + job->resources[0] = (qfv_resource_t) { + .name = "render", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = counts->num_images + counts->num_imageviews, + .objects = job->images, + }; + for (uint32_t i = 0; i < counts->num_images; i++) { + __auto_type img = &jinfo->images[i]; + job->images[i] = (qfv_resobj_t) { + .name = img->name, + .type = qfv_res_image, + .image = { + .flags = img->flags, + .type = img->imageType, + .format = img->format, + .extent = img->extent, + .num_mipmaps = img->mipLevels, + .num_layers = img->arrayLayers, + .samples = img->samples, + .tiling = img->tiling, + .usage = img->usage, + .initialLayout = img->initialLayout, + }, + }; + } + int error = 0; + for (uint32_t i = 0; i < counts->num_imageviews; i++) { + __auto_type view = &jinfo->imageviews[i]; + job->image_views[i] = (qfv_resobj_t) { + .name = view->name, + .type = qfv_res_image_view, + .image_view = { + .flags = view->flags, + .type = view->viewType, + .format = view->format, + .components = view->components, + .subresourceRange = view->subresourceRange, + }, + }; + if (strcmp (view->image.name, "$output.image") == 0) { + //__auto_type image = jinfo->output.image; + //job->image_views[i].image_view.external_image = image; + //job->image_views[i].image_view.image = -1; + } else { + qfv_resobj_t *img = 0; + for (uint32_t j = 0; j < jinfo->num_images; j++) { + if (strcmp (view->image.name, jinfo->images[j].name) == 0) { + img = &job->images[j]; + } + } + if (img) { + uint32_t ind = img - job->resources->objects; + job->image_views[i].image_view.image = ind; + } else { + Sys_Printf ("%d: unknown image reference: %s\n", + view->image.line, view->image.name); + error = 1; + } + } + } + if (error) { + free (job->resources); + job->resources = 0; + return; + } + QFV_CreateResource (ctx->device, job->resources); +} + +typedef struct { + VkRenderPassCreateInfo *rpCreate; + VkAttachmentDescription *attach; + VkClearValue *clear; + VkSubpassDescription *subpass; + VkSubpassDependency *depend; + VkAttachmentReference *attachref; + VkPipelineColorBlendAttachmentState *cbAttach; + uint32_t *preserve; + const char **rpName; + const char **plName; + VkComputePipelineCreateInfo *cplCreate; + VkGraphicsPipelineCreateInfo *gplCreate; + VkPipelineColorBlendStateCreateInfo *cbState; + qfv_layoutinfo_t *layouts; + + uint32_t *pl_counts; + + VkPipeline *gpl; + VkPipeline *cpl; + VkRenderPass *rp; +} objptr_t; + +typedef struct { + objcount_t inds; + objptr_t ptr; + + vulkan_ctx_t *ctx; + qfv_jobinfo_t *jinfo; + exprtab_t *symtab; + qfv_renderpassinfo_t *rpi; + VkRenderPassCreateInfo *rpc; + qfv_subpassinfo_t *spi; + VkSubpassDescription *spc; + qfv_pipelineinfo_t *pli; + VkGraphicsPipelineCreateInfo *plc; +} objstate_t; + +static uint32_t __attribute__((pure)) +find_subpass (qfv_dependencyinfo_t *d, uint32_t spind, + qfv_subpassinfo_t *subpasses) +{ + if (strcmp (d->name, "$external") == 0) { + return VK_SUBPASS_EXTERNAL; + } + for (uint32_t i = 0; i <= spind; i++) { + __auto_type s = &subpasses[i]; + if (strcmp (d->name, s->name) == 0) { + return i; + } + } + Sys_Error ("invalid dependency: [%d] %s", spind, d->name); +} + +static VkDescriptorSetLayout +find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) +{ + for (uint32_t i = 0; i < s->jinfo->num_descriptorsetlayouts; i++) { + __auto_type ds = &s->jinfo->descriptorsetlayouts[i]; + if (strcmp (ds->name, ref->name) == 0) { + if (!ds->setLayout) { + VkDescriptorSetLayoutCreateInfo cInfo = { + .sType=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .flags = ds->flags, + .bindingCount = ds->num_bindings, + .pBindings = ds->bindings, + }; + qfv_device_t *device = s->ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, + &ds->setLayout); + QFV_duSetObjectName (device, + VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, + ds->setLayout, + va (s->ctx->va_ctx, "descriptorSet:%s", + ds->name)); + } + return ds->setLayout; + } + } + Sys_Error ("%s.%s:%d: invalid descriptor set layout: %s", + s->rpi->name, s->spi->name, ref->line, ref->name); +} + +static qfv_layoutinfo_t * +find_layout (const qfv_reference_t *ref, objstate_t *s) +{ + for (uint32_t i = 0; i < s->inds.num_layouts; i++) { + if (strcmp (s->ptr.layouts[i].name, ref->name) == 0) { + return &s->ptr.layouts[i]; + } + } + if (!QFV_ParseLayoutInfo (s->ctx, s->jinfo->memsuper, s->symtab, ref->name, + &s->ptr.layouts[s->inds.num_layouts])) { + Sys_Error ("%s.%s:%d: invalid layout: %s", + s->rpi->name, s->spi->name, ref->line, ref->name); + } + __auto_type li = &s->ptr.layouts[s->inds.num_layouts++]; + li->name = ref->name; + VkDescriptorSetLayout sets[li->num_sets]; + for (uint32_t i = 0; i < li->num_sets; i++) { + sets[i] = find_descriptorSet (&li->sets[i], s); + } + VkPipelineLayoutCreateInfo cInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = li->num_sets, + .pSetLayouts = sets, + .pushConstantRangeCount = li->num_ranges, + .pPushConstantRanges = li->ranges, + }; + qfv_device_t *device = s->ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &li->layout); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, li->layout, + va (s->ctx->va_ctx, "layout:%s", li->name)); + return li; +} + +static void +init_plCreate (VkGraphicsPipelineCreateInfo *plc, const qfv_pipelineinfo_t *pli, + objstate_t *s) +{ + if (pli->num_graph_stages) { + plc->stageCount = pli->num_graph_stages; + } + if (pli->graph_stages) { + plc->pStages = pli->graph_stages; + } + if (pli->vertexInput) { + plc->pVertexInputState = pli->vertexInput; + } + if (pli->inputAssembly) { + plc->pInputAssemblyState = pli->inputAssembly; + } + if (pli->tessellation) { + plc->pTessellationState = pli->tessellation; + } + if (pli->viewport) { + plc->pViewportState = pli->viewport; + } + if (pli->rasterization) { + plc->pRasterizationState = pli->rasterization; + } + if (pli->multisample) { + plc->pMultisampleState = pli->multisample; + } + if (pli->depthStencil) { + plc->pDepthStencilState = pli->depthStencil; + } + if (pli->colorBlend) { + VkPipelineColorBlendStateCreateInfo *cb; + cb = (VkPipelineColorBlendStateCreateInfo *) plc->pColorBlendState; + *cb = *pli->colorBlend; + } + if (pli->dynamic) { + plc->pDynamicState = pli->dynamic; + } + if (pli->layout.name) { + __auto_type li = find_layout (&pli->layout, s); + plc->layout = li->layout; + s->inds.num_descriptorsets += li->num_sets; + } +} + +static uint32_t __attribute__((pure)) +find_attachment (qfv_reference_t *ref, objstate_t *s) +{ + for (uint32_t i = 0; i < s->rpi->num_attachments; i++) { + __auto_type a = &s->rpi->attachments[i]; + if (strcmp (ref->name, a->name) == 0) { + return i; + } + } + Sys_Error ("%s.%s:%d: invalid attachment: %s", + s->rpi->name, s->spi->name, ref->line, ref->name); +} + +static void +init_arCreate (const qfv_attachmentrefinfo_t *ari, objstate_t *s) +{ + __auto_type arc = &s->ptr.attachref[s->inds.num_attachmentrefs]; + qfv_reference_t ref = { + .name = ari->name, + .line = ari->line, + }; + + *arc = (VkAttachmentReference) { + .attachment = find_attachment (&ref, s), + .layout = ari->layout, + }; +} + +static void +init_cbCreate (const qfv_attachmentrefinfo_t *ari, objstate_t *s) +{ + __auto_type cbc = &s->ptr.cbAttach[s->inds.num_colorblend]; + + *cbc = ari->blend; +} + +static void +init_spCreate (uint32_t index, qfv_subpassinfo_t *sub, objstate_t *s) +{ + s->spi = &sub[index]; + s->plc = &s->ptr.gplCreate[s->inds.num_graph_pipelines]; + s->spc = &s->ptr.subpass[s->inds.num_subpasses]; + __auto_type pln = &s->ptr.plName[s->inds.num_graph_pipelines]; + __auto_type cbs = &s->ptr.cbState[s->inds.num_graph_pipelines]; + + s->ptr.pl_counts[s->inds.num_renderpasses] += s->spi->num_pipelines; + + *s->spc = (VkSubpassDescription) { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + }; + for (uint32_t i = 0; i < s->spi->num_dependencies; i++) { + __auto_type d = &s->spi->dependencies[i]; + __auto_type dep = &s->ptr.depend[s->inds.num_dependencies++]; + *dep = (VkSubpassDependency) { + .srcSubpass = find_subpass (d, index, s->rpi->subpasses), + .dstSubpass = index, + .srcStageMask = d->src.stage, + .dstStageMask = d->dst.stage, + .srcAccessMask = d->src.access, + .dstAccessMask = d->dst.access, + .dependencyFlags = d->flags, + }; + } + + for (uint32_t i = 0; i < s->spi->num_pipelines; i++) { + s->plc[i] = (VkGraphicsPipelineCreateInfo) { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pColorBlendState = &cbs[i], + .subpass = index, + }; + if (s->spi->base_pipeline) { + init_plCreate (&s->plc[i], s->spi->base_pipeline, s); + } + init_plCreate (&s->plc[i], &s->spi->pipelines[i], s); + pln[i] = s->spi->name; + s->inds.num_graph_pipelines++; + } + + __auto_type att = s->spi->attachments; + if (!att) { + return; + } + for (uint32_t i = 0; i < s->spi->num_pipelines; i++) { + cbs[i].attachmentCount = att->num_color; + cbs[i].pAttachments = &s->ptr.cbAttach[s->inds.num_colorblend]; + } + s->spc->inputAttachmentCount = att->num_input; + s->spc->pInputAttachments = &s->ptr.attachref[s->inds.num_attachmentrefs]; + for (uint32_t i = 0; i < att->num_input; i++) { + init_arCreate (&att->input[i], s); + s->inds.num_attachmentrefs++; + } + s->spc->colorAttachmentCount = att->num_color; + s->spc->pColorAttachments = &s->ptr.attachref[s->inds.num_attachmentrefs]; + for (uint32_t i = 0; i < att->num_color; i++) { + init_arCreate (&att->color[i], s); + s->inds.num_attachmentrefs++; + init_cbCreate (&att->color[i], s); + s->inds.num_colorblend++; + } + if (att->resolve) { + s->spc->pResolveAttachments + = &s->ptr.attachref[s->inds.num_attachmentrefs]; + for (uint32_t i = 0; i < att->num_color; i++) { + init_arCreate (&att->resolve[i], s); + s->inds.num_attachmentrefs++; + } + } + if (att->depth) { + s->spc->pDepthStencilAttachment + = &s->ptr.attachref[s->inds.num_attachmentrefs]; + init_arCreate (att->depth, s); + s->inds.num_attachmentrefs++; + } + s->spc->preserveAttachmentCount = att->num_preserve; + s->spc->pPreserveAttachments = &s->ptr.preserve[s->inds.num_preserve]; + for (uint32_t i = 0; i < att->num_preserve; i++) { + s->ptr.preserve[s->inds.num_preserve] + = find_attachment (&att->preserve[i], s); + s->inds.num_preserve++; + } +} + +static void +init_atCreate (uint32_t index, qfv_attachmentinfo_t *attachments, objstate_t *s) +{ + __auto_type ati = &attachments[index]; + __auto_type atc = &s->ptr.attach[s->inds.num_attachments]; + __auto_type cvc = &s->ptr.clear[s->inds.num_attachments]; + + *atc = (VkAttachmentDescription) { + .flags = ati->flags, + .format = ati->format, + .samples = ati->samples, + .loadOp = ati->loadOp, + .storeOp = ati->storeOp, + .stencilLoadOp = ati->stencilLoadOp, + .stencilStoreOp = ati->stencilStoreOp, + .initialLayout = ati->initialLayout, + .finalLayout = ati->finalLayout, + }; + *cvc = ati->clearValue; +} + +static void +init_rpCreate (uint32_t index, const qfv_renderinfo_t *rinfo, objstate_t *s) +{ + s->rpi = &rinfo->renderpasses[index]; + s->rpc = &s->ptr.rpCreate[s->inds.num_renderpasses]; + s->ptr.rpName[s->inds.num_renderpasses] = s->rpi->name; + + __auto_type attachments = &s->ptr.attach[s->inds.num_attachments]; + __auto_type subpasses = &s->ptr.subpass[s->inds.num_subpasses]; + __auto_type dependencies = &s->ptr.depend[s->inds.num_dependencies]; + + for (uint32_t i = 0; i < s->rpi->num_attachments; i++) { + init_atCreate (i, s->rpi->attachments, s); + s->inds.num_attachments++; + } + + uint32_t num_dependencies = s->inds.num_dependencies; + for (uint32_t i = 0; i < s->rpi->num_subpasses; i++) { + init_spCreate (i, s->rpi->subpasses, s); + s->inds.num_subpasses++; + } + num_dependencies = s->inds.num_dependencies - num_dependencies; + + *s->rpc = (VkRenderPassCreateInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = s->rpi->num_attachments, + .pAttachments = attachments, + .subpassCount = s->rpi->num_subpasses, + .pSubpasses = subpasses, + .dependencyCount = num_dependencies, + .pDependencies = dependencies, + }; +} + +typedef struct { + qfv_step_t *steps; + qfv_render_t *renders; + qfv_compute_t *computes; + qfv_process_t *processes; + qfv_renderpass_t *renderpasses; + VkClearValue *clearvalues; + qfv_subpass_t *subpasses; + qfv_pipeline_t *pipelines; + qfv_taskinfo_t *tasks; + VkDescriptorSet *descriptorsets; +} jobptr_t; + +static void +init_pipeline (qfv_pipeline_t *pl, qfv_pipelineinfo_t *plinfo, + jobptr_t *jp, objstate_t *s, int is_compute) +{ + __auto_type li = find_layout (&plinfo->layout, s); + *pl = (qfv_pipeline_t) { + .label = { + .name = plinfo->name, + .color = plinfo->color, + }, + .bindPoint = is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE + : VK_PIPELINE_BIND_POINT_GRAPHICS, + .pipeline = is_compute ? s->ptr.cpl[s->inds.num_comp_pipelines] + : s->ptr.gpl[s->inds.num_graph_pipelines], + .layout = li->layout, + .task_count = plinfo->num_tasks, + .tasks = &jp->tasks[s->inds.num_tasks], + .descriptorsets = &jp->descriptorsets[s->inds.num_descriptorsets], + }; + s->inds.num_tasks += plinfo->num_tasks; + s->inds.num_descriptorsets += li->num_sets; + for (uint32_t i = 0; i < li->num_sets; i++) { + pl->descriptorsets[i] = 0; + } + for (uint32_t i = 0; i < pl->task_count; i++) { + pl->tasks[i] = plinfo->tasks[i]; + } +} + +static void +init_subpass (qfv_subpass_t *sp, qfv_subpassinfo_t *isp, + jobptr_t *jp, objstate_t *s) +{ + uint32_t np = s->inds.num_graph_pipelines + s->inds.num_comp_pipelines; + *sp = (qfv_subpass_t) { + .label = { + .name = isp->name, + .color = isp->color, + }, + .inherit = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, + }, + .beginInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, + .pInheritanceInfo = &sp->inherit, + }, + .pipeline_count = isp->num_pipelines, + .pipelines = &jp->pipelines[np], + }; + for (uint32_t i = 0; i < isp->num_pipelines; i++) { + init_pipeline (&sp->pipelines[i], &isp->pipelines[i], jp, s, 0); + s->inds.num_graph_pipelines++; + } +} + +static void +init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo, + jobptr_t *jp, objstate_t *s) +{ + *rp = (qfv_renderpass_t) { + .vulkan_ctx = s->ctx, + .label.name = rpinfo->name, + .label.color = rpinfo->color, + .subpass_count = rpinfo->num_subpasses, + .subpasses = &jp->subpasses[s->inds.num_subpasses], + .beginInfo = (VkRenderPassBeginInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = s->ptr.rp[s->inds.num_renderpasses], + .clearValueCount = rpinfo->num_attachments, + .pClearValues = &jp->clearvalues[s->inds.num_attachments], + }, + .subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, + }; + s->inds.num_attachments += rpinfo->num_attachments; + for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) { + init_subpass (&rp->subpasses[i], &rpinfo->subpasses[i], jp, s); + rp->subpasses[i].inherit.renderPass = rp->beginInfo.renderPass; + rp->subpasses[i].inherit.subpass = i; + s->inds.num_subpasses++; + } +} + +static void +init_render (qfv_render_t *rend, qfv_renderinfo_t *rinfo, + jobptr_t *jp, objstate_t *s) +{ + *rend = (qfv_render_t) { + .label.color = rinfo->color, + .label.name = rinfo->name, + .num_renderpasses = rinfo->num_renderpasses, + .renderpasses = &jp->renderpasses[s->inds.num_renderpasses], + }; + s->inds.num_renderpasses += rinfo->num_renderpasses; + for (uint32_t i = 0; i < rend->num_renderpasses; i++) { + init_renderpass (&rend->renderpasses[i], &rinfo->renderpasses[i], + jp, s); + } + rend->active = &rend->renderpasses[0]; +} + +static void +init_compute (qfv_compute_t *comp, qfv_computeinfo_t *cinfo, + jobptr_t *jp, objstate_t *s) +{ + uint32_t np = s->inds.num_graph_pipelines + s->inds.num_comp_pipelines; + *comp = (qfv_compute_t) { + .label.color = cinfo->color, + .label.name = cinfo->name, + .pipelines = &jp->pipelines[np], + .pipeline_count = cinfo->num_pipelines, + }; + for (uint32_t i = 0; i < cinfo->num_pipelines; i++) { + init_pipeline (&comp->pipelines[i], &cinfo->pipelines[i], jp, s, 1); + s->inds.num_comp_pipelines++; + } +} + +static void +init_process (qfv_process_t *proc, qfv_processinfo_t *pinfo, + jobptr_t *jp, objstate_t *s) +{ + *proc = (qfv_process_t) { + .label.color = pinfo->color, + .label.name = pinfo->name, + .tasks = &jp->tasks[s->inds.num_tasks], + .task_count = pinfo->num_tasks, + }; + s->inds.num_tasks += pinfo->num_tasks; + for (uint32_t i = 0; i < proc->task_count; i++) { + proc->tasks[i] = pinfo->tasks[i]; + } +} + +static void +init_step (uint32_t ind, jobptr_t *jp, objstate_t *s) +{ + __auto_type step = &jp->steps[s->inds.num_steps++]; + __auto_type sinfo = &s->jinfo->steps[ind]; + + *step = (qfv_step_t) { + .label.name = sinfo->name, + .label.color = sinfo->color, + }; + if (sinfo->render) { + step->render = &jp->renders[s->inds.num_render++]; + init_render (step->render, sinfo->render, jp, s); + } + if (sinfo->compute) { + step->compute = &jp->computes[s->inds.num_compute++]; + init_compute (step->compute, sinfo->compute, jp, s); + } + if (sinfo->process) { + step->process = &jp->processes[s->inds.num_process++]; + init_process (step->process, sinfo->process, jp, s); + } +} + +static void +init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) +{ + __auto_type rctx = ctx->render_context; + + size_t size = sizeof (qfv_job_t); + + size += counts->num_renderpasses * sizeof (VkRenderPass); + size += counts->num_graph_pipelines * sizeof (VkPipeline); + size += counts->num_comp_pipelines * sizeof (VkPipeline); + size += s.inds.num_layouts * sizeof (VkPipelineLayout); + + size += counts->num_steps * sizeof (qfv_step_t); + size += counts->num_render * sizeof (qfv_render_t); + size += counts->num_compute * sizeof (qfv_compute_t); + size += counts->num_process * sizeof (qfv_process_t); + size += counts->num_renderpasses * sizeof (qfv_renderpass_t); + size += counts->num_attachments * sizeof (VkClearValue); + size += counts->num_subpasses * sizeof (qfv_subpass_t); + size += counts->num_graph_pipelines * sizeof (qfv_pipeline_t); + size += counts->num_comp_pipelines * sizeof (qfv_pipeline_t); + size += counts->num_tasks * sizeof (qfv_taskinfo_t); + size += counts->num_descriptorsets * sizeof (VkDescriptorSet); + + rctx->job = malloc (size); + __auto_type job = rctx->job; + *job = (qfv_job_t) { + .num_renderpasses = counts->num_renderpasses, + .num_pipelines = counts->num_graph_pipelines + + counts->num_comp_pipelines, + .num_layouts = s.inds.num_layouts, + .num_steps = counts->num_steps, + .commands = DARRAY_STATIC_INIT (16), + }; + job->renderpasses = (VkRenderPass *) &job[1]; + job->pipelines = (VkPipeline *) &job->renderpasses[job->num_renderpasses]; + job->layouts = (VkPipelineLayout *) &job->pipelines[job->num_pipelines]; + job->steps = (qfv_step_t *) &job->layouts[job->num_layouts]; + __auto_type rn = (qfv_render_t *) &job->steps[job->num_steps]; + __auto_type cp = (qfv_compute_t *) &rn[counts->num_render]; + __auto_type pr = (qfv_process_t *) &cp[counts->num_compute]; + __auto_type rp = (qfv_renderpass_t *) &pr[counts->num_process]; + __auto_type cv = (VkClearValue *) &rp[counts->num_renderpasses]; + __auto_type sp = (qfv_subpass_t *) &cv[counts->num_attachments]; + __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; + __auto_type ti = (qfv_taskinfo_t *) &pl[job->num_pipelines]; + __auto_type ds = (VkDescriptorSet *) &ti[counts->num_tasks]; + jobptr_t jp = { + .steps = job->steps, + .renders = rn, + .computes = cp, + .processes = pr, + .renderpasses = rp, + .clearvalues = cv, + .subpasses = sp, + .pipelines = pl, + .tasks = ti, + .descriptorsets = ds, + }; + + for (uint32_t i = 0; i < job->num_renderpasses; i++) { + job->renderpasses[i] = s.ptr.rp[i]; + } + for (uint32_t i = 0; i < job->num_pipelines; i++) { + // compute pipelines come immediately after the graphics pipelines + job->pipelines[i] = s.ptr.gpl[i]; + } + for (uint32_t i = 0; i < s.inds.num_layouts; i++) { + job->layouts[i] = s.ptr.layouts[i].layout; + } + memcpy (cv, s.ptr.clear, counts->num_attachments * sizeof (VkClearValue)); + + uint32_t num_layouts = s.inds.num_layouts; + s.inds = (objcount_t) {}; + s.inds.num_layouts = num_layouts; + for (uint32_t i = 0; i < job->num_steps; i++) { + init_step (i, &jp, &s); + } + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkCommandPoolCreateInfo poolCInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + .queueFamilyIndex = device->queue.queueFamily, + }; + dfunc->vkCreateCommandPool (device->dev, &poolCInfo, 0, &job->command_pool); +} + +static void +create_step_render_objects (uint32_t index, const qfv_stepinfo_t *step, + objstate_t *s) +{ + __auto_type rinfo = step->render; + if (!rinfo) { + return; + } + for (uint32_t i = 0; i < rinfo->num_renderpasses; i++) { + s->ptr.pl_counts[s->inds.num_renderpasses] = 0; + init_rpCreate (i, rinfo, s); + s->inds.num_renderpasses++; + } +} + +static void +create_step_compute_objects (uint32_t index, const qfv_stepinfo_t *step, + objstate_t *s) +{ + __auto_type cinfo = step->compute; + if (!cinfo) { + return; + } + + uint32_t base = s->inds.num_graph_pipelines; + for (uint32_t i = 0; i < cinfo->num_pipelines; i++) { + __auto_type pli = &cinfo->pipelines[i]; + __auto_type plc = &s->ptr.cplCreate[s->inds.num_comp_pipelines]; + __auto_type li = find_layout (&pli->layout, s); + s->ptr.plName[base + s->inds.num_comp_pipelines] = pli->name; + *plc = (VkComputePipelineCreateInfo) { + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .flags = pli->flags, + .stage = *pli->compute_stage, + .layout = li->layout, + }; + plc->stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; + s->inds.num_comp_pipelines++; + s->inds.num_descriptorsets += li->num_sets; + } +} + +static void +create_step_process_objects (uint32_t index, const qfv_stepinfo_t *step, + objstate_t *s) +{ + __auto_type pinfo = step->process; + if (!pinfo) { + return; + } + // nothing to create at this stage +} + +static void +create_objects (vulkan_ctx_t *ctx, objcount_t *counts) +{ + __auto_type rctx = ctx->render_context; + __auto_type jinfo = rctx->jobinfo; + + VkRenderPass renderpasses[counts->num_renderpasses]; + VkPipeline pipelines[counts->num_graph_pipelines + + counts->num_comp_pipelines]; + VkRenderPassCreateInfo rpCreate[counts->num_renderpasses]; + VkAttachmentDescription attach[counts->num_attachments]; + VkClearValue clear[counts->num_attachments]; + VkSubpassDescription subpass[counts->num_subpasses]; + VkSubpassDependency depend[counts->num_dependencies]; + VkAttachmentReference attachref[counts->num_attachmentrefs]; + VkPipelineColorBlendAttachmentState cbAttach[counts->num_colorblend]; + uint32_t preserve[counts->num_preserve]; + const char *rpName[counts->num_renderpasses]; + const char *plName[counts->num_graph_pipelines + + counts->num_comp_pipelines]; + VkComputePipelineCreateInfo cplCreate[counts->num_comp_pipelines]; + VkGraphicsPipelineCreateInfo gplCreate[counts->num_graph_pipelines]; + VkPipelineColorBlendStateCreateInfo cbState[counts->num_graph_pipelines]; + qfv_layoutinfo_t layouts[counts->num_graph_pipelines + + counts->num_comp_pipelines]; + uint32_t pl_counts[counts->num_renderpasses]; + + exprctx_t ectx = { .hashctx = &ctx->script_context->hashctx }; + objstate_t s = { + .ptr = { + .rpCreate = rpCreate, + .attach = attach, + .clear = clear, + .subpass = subpass, + .depend = depend, + .attachref = attachref, + .cbAttach = cbAttach, + .preserve = preserve, + .rpName = rpName, + .plName = plName, + .cplCreate = cplCreate, + .gplCreate = gplCreate, + .cbState = cbState, + .layouts = layouts, + .pl_counts = pl_counts, + .rp = renderpasses, + .gpl = pipelines, + .cpl = pipelines + counts->num_graph_pipelines, + }, + .ctx = ctx, + .jinfo = jinfo, + .symtab = QFV_CreateSymtab (jinfo->plitem, "properties", 0, 0, &ectx), + }; + for (uint32_t i = 0; i < jinfo->num_steps; i++) { + create_step_render_objects (i, &jinfo->steps[i], &s); + } + for (uint32_t i = 0; i < jinfo->num_steps; i++) { + create_step_compute_objects (i, &jinfo->steps[i], &s); + } + for (uint32_t i = 0; i < jinfo->num_steps; i++) { + create_step_process_objects (i, &jinfo->steps[i], &s); + } + if (s.inds.num_renderpasses != counts->num_renderpasses + || s.inds.num_attachments != counts->num_attachments + || s.inds.num_subpasses != counts->num_subpasses + || s.inds.num_dependencies != counts->num_dependencies + || s.inds.num_attachmentrefs != counts->num_attachmentrefs + || s.inds.num_colorblend != counts->num_colorblend + || s.inds.num_preserve != counts->num_preserve + || s.inds.num_graph_pipelines != counts->num_graph_pipelines + || s.inds.num_comp_pipelines != counts->num_comp_pipelines) { + Sys_Error ("create_objects: something was missed"); + } + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + uint32_t plInd = 0; + for (uint32_t i = 0; i < counts->num_renderpasses; i++) { + dfunc->vkCreateRenderPass (device->dev, &s.ptr.rpCreate[i], 0, + &renderpasses[i]); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_RENDER_PASS, + renderpasses[i], + va (ctx->va_ctx, "renderpass:%s", rpName[i])); + for (uint32_t j = 0; j < pl_counts[i]; j++) { + s.ptr.gplCreate[plInd++].renderPass = renderpasses[i]; + } + } + if (s.inds.num_graph_pipelines) { + dfunc->vkCreateGraphicsPipelines (device->dev, 0, + s.inds.num_graph_pipelines, + s.ptr.gplCreate, 0, pipelines); + } + if (s.inds.num_comp_pipelines) { + __auto_type p = &pipelines[s.inds.num_graph_pipelines]; + dfunc->vkCreateComputePipelines (device->dev, 0, + s.inds.num_comp_pipelines, + s.ptr.cplCreate, 0, p); + } + for (uint32_t i = 0; + i < s.inds.num_graph_pipelines + s.inds.num_comp_pipelines; i++) { + QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE, pipelines[i], + va (ctx->va_ctx, "pipeline:%s", plName[i])); + } + + counts->num_descriptorsets = s.inds.num_descriptorsets; + init_job (ctx, counts, s); +} + +void +QFV_BuildRender (vulkan_ctx_t *ctx) +{ + __auto_type rctx = ctx->render_context; + + objcount_t counts = {}; + count_stuff (rctx->jobinfo, &counts); + + create_objects (ctx, &counts); + create_resources (ctx, &counts); +} + +static VkImageView __attribute__((pure, used)) +find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx) +{ + __auto_type jinfo = rctx->jobinfo; + __auto_type job = rctx->job; + const char *name = ref->name; + + if (strncmp (name, "$imageviews.", 7) == 0) { + name += 7; + } + + for (uint32_t i = 0; i < jinfo->num_imageviews; i++) { + __auto_type vi = &jinfo->imageviews[i]; + __auto_type vo = &job->image_views[i]; + if (strcmp (name, vi->name) == 0) { + return vo->image_view.view; + } + } + Sys_Error ("%d:invalid imageview: %s", ref->line, ref->name); +} From 57da924c1bfe1550220393d754a84e7fb9a06a01 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Jun 2023 18:47:24 +0900 Subject: [PATCH 3607/3664] [plist] Put quotes around the unknown field name I got rather confused by "unknown field type" when "type" was the field name. --- libs/util/plist.c | 2 +- libs/video/renderer/vulkan/vkparse.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/util/plist.c b/libs/util/plist.c index 1172a354c..db3c607ed 100644 --- a/libs/util/plist.c +++ b/libs/util/plist.c @@ -1433,7 +1433,7 @@ PL_ParseStruct (const plfield_t *fields, const plitem_t *item, void *data, } } if (!f->name) { - PL_Message (messages, item, "error: unknown field %s", + PL_Message (messages, item, "error: unknown field '%s'", current->key); result = 0; } diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index f319cde4d..875796779 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -161,7 +161,7 @@ find_field (plfield_t *fields, const char *field_name, return f; } } - PL_Message (messages, item, "error: unknown field %s", field_name); + PL_Message (messages, item, "error: unknown field '%s'", field_name); return 0; } From bcfb2ad18276998745a050c93c9270b1a7ba39cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Jun 2023 18:49:58 +0900 Subject: [PATCH 3608/3664] [vkgen] Shorten "qfv_*" enum names The up-coming changes to push constant handling has qfv_float etc type enum values and using "float" instead of "qfv_float" is highly desirable as the names match the glsl type names. --- libs/video/renderer/vulkan/vkgen/vkenum.r | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkenum.r b/libs/video/renderer/vulkan/vkgen/vkenum.r index 8b7bde8f5..1995426fa 100644 --- a/libs/video/renderer/vulkan/vkgen/vkenum.r +++ b/libs/video/renderer/vulkan/vkgen/vkenum.r @@ -22,13 +22,17 @@ typedef enum VkBool32 { end = "_FLAG_BITS_MAX_ENUM_EXT"; } else if (str_mid([self name], -3) == "KHR") { end = "_MAX_ENUM_KHR"; + } else if (str_mid([self name], 0, 4) == "qfv_") { + prefix = "qfv_"; } len = -strlen (end); - for (int i = 0; i < type.strct.num_fields; i++) { - qfot_var_t *var = &type.strct.fields[i]; - if (str_mid (var.name, len) == end) { - // len is negative so +1 consumes 1 more char (_) - prefix = str_hold (str_mid (var.name, 0, len + 1)); + if (!prefix) { + for (int i = 0; i < type.strct.num_fields; i++) { + qfot_var_t *var = &type.strct.fields[i]; + if (str_mid (var.name, len) == end) { + // len is negative so +1 consumes 1 more char (_) + prefix = str_hold (str_mid (var.name, 0, len + 1)); + } } } if (prefix) { From c1b85a3db79733512b1e21a882c915991435f19e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Jun 2023 18:53:37 +0900 Subject: [PATCH 3609/3664] [vkgen] Support custom parsing in multi-type fields This allows the likes of: qfv_pushconstantrangeinfo_s = { .name = qfv_pushconstantrangeinfo_t; .type = (QFDictionary); .dictionary = { .parse = { type = (labeledarray, qfv_pushconstantinfo_t, name); size = num_pushconstants; values = pushconstants; }; stageFlags = $name.auto; }; stageFlags = auto; }; Leading to: pushConstants = { vertex = { Model = mat4; blend = float; }; fragment = { colors = uint; base_color = vec4; fog = vec4; }; }; Where the label of the labeled array (which pushConstants is) is actually an enum flag and the dictionary value is another labeled array. --- libs/video/renderer/vulkan/vkgen/vkfielddef.h | 1 + libs/video/renderer/vulkan/vkgen/vkfielddef.r | 6 +++ .../vulkan/vkgen/vkfieldlabeledarray.r | 15 ++++++ libs/video/renderer/vulkan/vkgen/vkstruct.h | 2 + libs/video/renderer/vulkan/vkgen/vkstruct.r | 50 ++++++++++++++----- 5 files changed, 62 insertions(+), 12 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.h b/libs/video/renderer/vulkan/vkgen/vkfielddef.h index 747df01e6..328604c8e 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfielddef.h +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.h @@ -20,6 +20,7 @@ +fielddef:(PLItem *)item struct:(Struct *)strct field:(string)fname; -init:(PLItem *)item struct:(Struct *)strct field:(string)fname; -writeParseData; +-writeParse; -writeField; -writeSymbol; -(string) name; diff --git a/libs/video/renderer/vulkan/vkgen/vkfielddef.r b/libs/video/renderer/vulkan/vkgen/vkfielddef.r index 9638dd109..29e9e4867 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfielddef.r +++ b/libs/video/renderer/vulkan/vkgen/vkfielddef.r @@ -84,6 +84,12 @@ } -writeParseData +{ + fprintf (output_file, "undefined record type parse data: %d\n", line); + return self; +} + +-writeParse { fprintf (output_file, "undefined record type parse: %d\n", line); return self; diff --git a/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.r b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.r index efb02f782..14ade0186 100644 --- a/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.r +++ b/libs/video/renderer/vulkan/vkgen/vkfieldlabeledarray.r @@ -26,6 +26,21 @@ return self; } +-writeParse +{ + fprintf (output_file, "\t\tplfield_t %s_field = {\n", field_name); + fprintf (output_file, "\t\t\t.name = \"%s\",\n", field_name); + fprintf (output_file, "\t\t\t.type = QFDictionary,\n"); + fprintf (output_file, "\t\t\t.data = &parse_%s_%s_data,\n", + struct_name, field_name); + fprintf (output_file, "\t\t};\n"); + fprintf (output_file, "\t\tif (!parse_labeledarray (&%s_field, item, " + "data, messages, context)) {\n", field_name); + fprintf (output_file, "\t\t\treturn 0;\n"); + fprintf (output_file, "\t\t}\n"); + return self; +} + -writeField { fprintf (output_file, "\t{\"%s\", 0, %s, parse_%s, &parse_%s_%s_data},\n", diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.h b/libs/video/renderer/vulkan/vkgen/vkstruct.h index f2c86db29..5e3290379 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.h +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.h @@ -7,6 +7,7 @@ #include "vktype.h" @class PLItem; +@class FieldDef; @interface Struct: Type { @@ -16,6 +17,7 @@ int skip; Array *field_defs; + FieldDef *parse_def; PLItem *field_dict; PLItem *only; } diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index ab37159ca..1b8c9a1f2 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -17,6 +17,7 @@ { [field_dict release]; [field_defs release]; + [parse_def release]; [only release]; str_free (outname); str_free (label_field); @@ -128,25 +129,39 @@ write_function_tail (Struct *self) } static void -write_parse_type (Struct *self) +write_parse_type (Struct *self, PLItem *item) { - fprintf (output_file, "\t\tif (!PL_ParseStruct (%s_fields, item, data, " - "messages, context)) {\n", [self outname]); - fprintf (output_file, "\t\t\treturn 0;\n"); - fprintf (output_file, "\t\t}\n"); + if ([item string] == "auto") { + fprintf (output_file, "\t\tif (!PL_ParseStruct (%s_fields, item, " + "data, messages, context)) {\n", [self outname]); + fprintf (output_file, "\t\t\treturn 0;\n"); + fprintf (output_file, "\t\t}\n"); + } else { + //FieldDef *def = [FieldDef fielddef:item struct:self field:".parse"]; + [self.parse_def writeParse]; + } } static void -write_auto_parse (Struct *self, string field) +write_auto_parse (Struct *self, string field, int name) { + string item = name ? "name" : "item"; + fprintf (output_file, "\t\tdo {\n"); fprintf (output_file, "\t\t\tplfield_t *f = find_field (%s_fields, %s, " "item, messages);\n", [self outname], sprintf ("\"%s\"", field)); fprintf (output_file, "\t\t\tif (!f) {\n"); - fprintf (output_file, "\t\t\t\treturn 0;"); - fprintf (output_file, "\t\t\t};\n"); - fprintf (output_file, "\t\t\tf->parser (f, item, &%s, messages, context);\n", - sprintf ("((%s *) data)->%s", [self outname], field)); + fprintf (output_file, "\t\t\t\treturn 0;\n"); + fprintf (output_file, "\t\t\t}\n"); + if (name) { + fprintf (output_file, "\t\t\tplitem_t *name = " + "PL_NewString (field->name);\n"); + } + fprintf (output_file, "\t\t\tf->parser (f, %s, &%s, messages, context);\n", + item, sprintf ("((%s *) data)->%s", [self outname], field)); + if (name) { + fprintf (output_file, "\t\t\tPL_Release (name);\n"); + } fprintf (output_file, "\t\t} while (0);\n"); } @@ -171,6 +186,11 @@ check_need_table (Struct *self, PLItem *field_dict, string type) string str = [item string]; if (field == ".parse") { + if (str != "auto") { + self.parse_def = [[FieldDef fielddef:item + struct:self + field:"parse"] retain]; + } return 1; } if (str == "$auto") { @@ -203,7 +223,7 @@ write_type (Struct *self, PLItem *field_dict, string type) string str = [item string]; if (field == ".parse") { - write_parse_type (self); + write_parse_type (self, item); continue; } @@ -221,7 +241,10 @@ write_type (Struct *self, PLItem *field_dict, string type) str = "field->offset"; break; case "$auto": - write_auto_parse (self, field); + write_auto_parse (self, field, 0); + continue; + case "$name.auto": + write_auto_parse (self, field, 1); continue; } fprintf (output_file, "\t\t((%s *) data)->%s = %s;\n", [self outname], @@ -333,10 +356,13 @@ write_table (Struct *self, PLItem *field_dict, Array *field_defs, self.write_symtab = 1; } } + for (int i = [field_defs count]; i-- > 0; ) { FieldDef *field_def = [field_defs objectAtIndex:i]; [field_def writeParseData]; } + [self.parse_def writeParseData]; + if (!readonly) { fprintf (output_file, "static plfield_t %s_fields[] = {\n", [self outname]); From b0d1c0e75bb736913d8c060ef13c76b6b39c16fc Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Jun 2023 19:05:53 +0900 Subject: [PATCH 3610/3664] [vulkan] Make push constant ranges structured Being able to specify the types in the push constant ranges makes it a lot easier to get the specification correct. I never did like having to do the offsets and sizes by hand as it was quite error prone. Right now, float, int, uint, vec3, vec4 and mat4 are supported, and adheres to layout std430. --- include/QF/Vulkan/render.h | 27 +++- libs/video/renderer/vulkan/render_load.c | 66 +++++++++- libs/video/renderer/vulkan/rp_main_def.plist | 124 ++++++++----------- libs/video/renderer/vulkan/vkparse.plist | 45 ++++++- 4 files changed, 180 insertions(+), 82 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 8c0469dfe..3df588a41 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -35,12 +35,35 @@ typedef struct qfv_descriptorsetlayoutinfo_s { VkDescriptorSetLayout setLayout; } qfv_descriptorsetlayoutinfo_t; +typedef enum qfv_type_t { + qfv_float, + qfv_int, + qfv_uint, + qfv_vec3, + qfv_vec4, + qfv_mat4, +} qfv_type_t; + +typedef struct qfv_pushconstantinfo_s { + const char *name; + int line; + qfv_type_t type; + uint32_t offset; + uint32_t size; +} qfv_pushconstantinfo_t; + +typedef struct qfv_pushconstantrangeinfo_s { + VkShaderStageFlags stageFlags; + uint32_t num_pushconstants; + qfv_pushconstantinfo_t *pushconstants; +} qfv_pushconstantrangeinfo_t; + typedef struct qfv_layoutinfo_s { const char *name; uint32_t num_sets; qfv_reference_t *sets; - uint32_t num_ranges; - VkPushConstantRange *ranges; + uint32_t num_pushconstantranges; + qfv_pushconstantrangeinfo_t *pushconstantranges; VkPipelineLayout layout; } qfv_layoutinfo_t; diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 76a3aa64b..261587dfb 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -374,6 +374,61 @@ find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) s->rpi->name, s->spi->name, ref->line, ref->name); } +#define RUP(x,a) (((x) + ((a) - 1)) & ~((a) - 1)) + +static uint32_t +parse_pushconstantrange (VkPushConstantRange *range, + qfv_pushconstantrangeinfo_t *pushconstantrange, + uint32_t offset, objstate_t *s) +{ + uint32_t range_offset = ~0u; + for (uint32_t i = 0; i < pushconstantrange->num_pushconstants; i++) { + __auto_type pushconstant = & pushconstantrange->pushconstants[i]; + uint32_t size = 0; + if (pushconstant->offset != ~0u) { + offset = pushconstant->offset; + } + if (pushconstant->size != ~0u) { + size = pushconstant->size; + } else { + switch (pushconstant->type) { + case qfv_float: + case qfv_int: + case qfv_uint: + size = sizeof (int32_t); + offset = RUP (offset, sizeof (int32_t)); + break; + case qfv_vec3: + size = sizeof (vec3_t); + offset = RUP (offset, sizeof (vec4f_t)); + break; + case qfv_vec4: + size = sizeof (vec4f_t); + offset = RUP (offset, sizeof (vec4f_t)); + break; + case qfv_mat4: + size = sizeof (mat4f_t); + offset = RUP (offset, sizeof (vec4f_t)); + break; + default: + Sys_Error ("%s.%s:%s:%d invalid type: %d", + s->rpi->name, s->spi->name, pushconstant->name, + pushconstant->line, pushconstant->type); + } + } + if (range_offset == ~0u) { + range_offset = offset; + } + offset += size; + } + *range = (VkPushConstantRange) { + .stageFlags = pushconstantrange->stageFlags, + .offset = range_offset, + .size = offset - range_offset, + }; + return offset; +} + static qfv_layoutinfo_t * find_layout (const qfv_reference_t *ref, objstate_t *s) { @@ -393,12 +448,19 @@ find_layout (const qfv_reference_t *ref, objstate_t *s) for (uint32_t i = 0; i < li->num_sets; i++) { sets[i] = find_descriptorSet (&li->sets[i], s); } + VkPushConstantRange ranges[li->num_pushconstantranges]; + uint32_t offset = 0; + for (uint32_t i = 0; i < li->num_pushconstantranges; i++) { + offset = parse_pushconstantrange (&ranges[i], + &li->pushconstantranges[i], + offset, s); + } VkPipelineLayoutCreateInfo cInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = li->num_sets, .pSetLayouts = sets, - .pushConstantRangeCount = li->num_ranges, - .pPushConstantRanges = li->ranges, + .pushConstantRangeCount = li->num_pushconstantranges, + .pPushConstantRanges = ranges, }; qfv_device_t *device = s->ctx->device; qfv_devfuncs_t *dfunc = device->funcs; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 8fedad9d2..ce42ca3bd 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -244,14 +244,16 @@ properties = { primitiveRestartEnable = true; }; layout = { - descriptorSets = (matrix_set, entity_set, oit_set, texture_set, texture_set); - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "4 * 4 + 4 + 4 + 4"; - }, - ); + descriptorSets = (matrix_set, entity_set, oit_set, texture_set, + texture_set); + pushConstants = { + fragment = { + fog = vec4; + time = float; + alpha = float; + turb_scale = float; + }; + }; }; }; alias = { @@ -292,18 +294,10 @@ properties = { }; layout = { descriptorSets = (matrix_set, texture_set, texture_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 68; - size = "3 * 4 + 2 * 4 * 4"; - }, - ); + pushConstants = { + vertex = { Model = mat4; blend = float; }; + fragment = { colors = uint; base_color = vec4; fog = vec4; }; + }; }; }; iqm = { @@ -363,18 +357,18 @@ properties = { }; layout = { descriptorSets = (matrix_set, texture_set, bone_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 68; - size = "3 * 4 + 2 * 4 * 4 + 4"; - }, - ); + pushConstants = { + vertex = { + Model = mat4; + blend = float; + }; + fragment = { + colorA = uint; + colorB = uint; + base_color = vec4; + fog = vec4; + }; + }; }; }; sprite = { @@ -411,20 +405,18 @@ properties = { }; layout = { descriptorSets = (matrix_set, sprite_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - // note: overlap with fragment is for the frame number - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 64; - // note: overlap with vertex to share frame number - size = "2 * 4 + 2 * 4 + 4"; - }, - ); + pushConstants = { + vertex = { + Model = mat4; + frame = int; + }; + fragment = { + overlap = { offset = 64; type = int; }; + frame = int; + spriteind = int; + fog = vec4; + }; + }; }; }; particle = { @@ -463,23 +455,15 @@ properties = { layout = { draw = { descriptorSets = (matrix_set, texture_set, oit_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4"; - }, - ); + pushConstants = { + vertex = { Model = mat4; }; + }; }; physics = { descriptorSets = (particle_set); - pushConstantRanges = ( - { - stageFlags = compute; - offset = 0; - size = "4 * 4 + 4"; - }, - ); + pushConstants = { + compute = { gravity = vec4; dT = float; }; + }; }; update = { descriptorSets = (particle_set, particle_set, particle_set); @@ -544,13 +528,9 @@ properties = { }; layout = { descriptorSets = (matrix_set, output_set); - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "4"; - } - ); + pushConstants = { + fragment = { time = float; }; + }; }; }; fisheye = { @@ -564,13 +544,9 @@ properties = { }; layout = { descriptorSets = (matrix_set, output_set); - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "2 * 4"; - } - ); + pushConstants = { + fragment = { fov = float; aspect = float; }; + }; }; }; }; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index addd39ac8..977814651 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -43,6 +43,8 @@ search = ( qfv_attachmentrefinfo_t, qfv_attachmentsetinfo_t, qfv_taskinfo_t, + qfv_pushconstantinfo_t, + qfv_pushconstantrangeinfo_t, qfv_layoutinfo_t, qfv_pipelineinfo_t, qfv_subpassinfo_t, @@ -485,6 +487,41 @@ parse = { values = preserve; }; }; + qfv_pushconstantinfo_s = { + .name = qfv_pushconstantinfo_t; + .type = (QFString, QFDictionary); + .dictionary = { + offset = -1; + size = -1; + .parse = auto; + name = $name; + line = $item.line; + }; + .string = { + offset = -1; + size = -1; + name = $name; + line = $item.line; + type = $auto; + }; + type = auto; + //stageFlags = auto; + offset = auto; + size = auto; + }; + qfv_pushconstantrangeinfo_s = { + .name = qfv_pushconstantrangeinfo_t; + .type = (QFDictionary); + .dictionary = { + .parse = { + type = (labeledarray, qfv_pushconstantinfo_t, name); + size = num_pushconstants; + values = pushconstants; + }; + stageFlags = $name.auto; + }; + stageFlags = auto; + }; qfv_layoutinfo_s = { .name = qfv_layoutinfo_t; descriptorSets = { @@ -492,10 +529,10 @@ parse = { size = num_sets; values = sets; }; - pushConstantRanges = { - type = (array, VkPushConstantRange); - size = num_ranges; - values = ranges; + pushConstants = { + type = (labeledarray, qfv_pushconstantrangeinfo_t, stageFlags); + size = num_pushconstantranges; + values = pushconstantranges; }; }; qfv_pipelineinfo_s = { From 274e821c06e70b14d55ba0ac9f046603b6f9a7a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Jun 2023 22:34:08 +0900 Subject: [PATCH 3611/3664] [vulkan] Pass the current command buffer to tasks Compute and render tasks need to be able to submit commands. --- include/QF/Vulkan/render.h | 1 + libs/video/renderer/vulkan/render.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 3df588a41..94aa46a5d 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -381,6 +381,7 @@ typedef struct qfv_renderctx_s { typedef struct qfv_taskctx_s { struct vulkan_ctx_s *ctx; qfv_pipeline_t *pipeline; + VkCommandBuffer cmd; } qfv_taskctx_t; VkCommandBuffer QFV_GetCmdBufffer (struct vulkan_ctx_s *ctx, bool secondary); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index c2b98814c..7c0f583ed 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -99,6 +99,7 @@ run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) qfv_taskctx_t taskctx = { .ctx = ctx, .pipeline = pipeline, + .cmd = cmd, }; run_tasks (pipeline->task_count, pipeline->tasks, &taskctx); @@ -187,6 +188,7 @@ run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, qfv_taskctx_t taskctx = { .ctx = ctx, .pipeline = pipeline, + .cmd = cmd, }; run_tasks (pipeline->task_count, pipeline->tasks, &taskctx); From b33a897ae416eb86c626f0afc145046097c57b33 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Jun 2023 22:37:27 +0900 Subject: [PATCH 3612/3664] [vulkan] Submit particle physics push constants directly Trying to do it in the task system meant copying pointers in a larger buffer, which rarely ends well. --- libs/video/renderer/vulkan/vulkan_particles.c | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 31a0305c6..8cd78b56f 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -359,6 +359,7 @@ particle_physics (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { __auto_type taskctx = (qfv_taskctx_t *) ectx; vulkan_ctx_t *ctx = taskctx->ctx; + qfv_device_t *device = ctx->device; particlectx_t *pctx = ctx->particle_context; __auto_type pframe = &pctx->frames.a[ctx->curFrame]; @@ -368,29 +369,20 @@ particle_physics (const exprval_t **params, exprval_t *result, exprctx_t *ectx) pipeline->num_descriptorsets = 1; pipeline->descriptorsets[0] = pframe->curDescriptors; - struct { - qfv_push_constants_t push_constants[2]; - particle_push_constants_t constants; - } push = { - .push_constants = { - { VK_SHADER_STAGE_COMPUTE_BIT, - field_offset (particle_push_constants_t, gravity), - sizeof (vec4f_t), &push.constants.gravity }, - { VK_SHADER_STAGE_COMPUTE_BIT, - field_offset (particle_push_constants_t, dT), - sizeof (float), &push.constants.dT }, - }, - .constants = { - .gravity = pctx->psystem->gravity, - .dT = vr_data.frametime, - }, + particle_push_constants_t constants = { + .gravity = pctx->psystem->gravity, + .dT = vr_data.frametime, }; - if (!pipeline->push_constants) { - //FIXME figure out something better for managing push constants - pipeline->push_constants = malloc (sizeof (push)); - } - memcpy (pipeline->push_constants, &push, sizeof (push)); - pipeline->num_push_constants = 2; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_COMPUTE_BIT, + field_offset (particle_push_constants_t, gravity), + sizeof (vec4f_t), &constants.gravity }, + { VK_SHADER_STAGE_COMPUTE_BIT, + field_offset (particle_push_constants_t, dT), + sizeof (float), &constants.dT }, + }; + QFV_PushConstants (device, taskctx->cmd, pipeline->layout, + 2, push_constants); } static exprfunc_t particles_draw_func[] = { From 14b24e5b75bc47af167023161cb57bf0d0d0b98b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Jun 2023 22:39:49 +0900 Subject: [PATCH 3613/3664] [vulkan] Clean up job allocation size calculation It does the same thing, but it's just nicer to read (thanks for the idea, HomelikeBrick42). --- include/QF/Vulkan/render.h | 2 -- libs/video/renderer/vulkan/render.c | 10 -------- libs/video/renderer/vulkan/render_load.c | 30 ++++++++++++------------ 3 files changed, 15 insertions(+), 27 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 94aa46a5d..ef1b5ff45 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -292,8 +292,6 @@ typedef struct qfv_pipeline_s { VkViewport viewport; VkRect2D scissor; - struct qfv_push_constants_s *push_constants; - uint32_t num_push_constants; uint32_t num_descriptorsets; uint32_t first_descriptorset; VkDescriptorSet *descriptorsets; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 7c0f583ed..c03f04bcf 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -111,11 +111,6 @@ run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) pipeline->descriptorsets, 0, 0); } - if (pipeline->num_push_constants) { - QFV_PushConstants (device, cmd, pipeline->layout, - pipeline->num_push_constants, - pipeline->push_constants); - } } // https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/ @@ -200,11 +195,6 @@ run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, pipeline->descriptorsets, 0, 0); } - if (pipeline->num_push_constants) { - QFV_PushConstants (device, cmd, pipeline->layout, - pipeline->num_push_constants, - pipeline->push_constants); - } vec4u_t d = pipeline->dispatch; dfunc->vkCmdDispatch (cmd, d[0], d[1], d[2]); } diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 261587dfb..872d5aa92 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -873,22 +873,22 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) size_t size = sizeof (qfv_job_t); - size += counts->num_renderpasses * sizeof (VkRenderPass); - size += counts->num_graph_pipelines * sizeof (VkPipeline); - size += counts->num_comp_pipelines * sizeof (VkPipeline); - size += s.inds.num_layouts * sizeof (VkPipelineLayout); + size += sizeof (VkRenderPass [counts->num_renderpasses]); + size += sizeof (VkPipeline [counts->num_graph_pipelines]); + size += sizeof (VkPipeline [counts->num_comp_pipelines]); + size += sizeof (VkPipelineLayout [s.inds.num_layouts]); - size += counts->num_steps * sizeof (qfv_step_t); - size += counts->num_render * sizeof (qfv_render_t); - size += counts->num_compute * sizeof (qfv_compute_t); - size += counts->num_process * sizeof (qfv_process_t); - size += counts->num_renderpasses * sizeof (qfv_renderpass_t); - size += counts->num_attachments * sizeof (VkClearValue); - size += counts->num_subpasses * sizeof (qfv_subpass_t); - size += counts->num_graph_pipelines * sizeof (qfv_pipeline_t); - size += counts->num_comp_pipelines * sizeof (qfv_pipeline_t); - size += counts->num_tasks * sizeof (qfv_taskinfo_t); - size += counts->num_descriptorsets * sizeof (VkDescriptorSet); + size += sizeof (qfv_step_t [counts->num_steps]); + size += sizeof (qfv_render_t [counts->num_render]); + size += sizeof (qfv_compute_t [counts->num_compute]); + size += sizeof (qfv_process_t [counts->num_process]); + size += sizeof (qfv_renderpass_t [counts->num_renderpasses]); + size += sizeof (VkClearValue [counts->num_attachments]); + size += sizeof (qfv_subpass_t [counts->num_subpasses]); + size += sizeof (qfv_pipeline_t [counts->num_graph_pipelines]); + size += sizeof (qfv_pipeline_t [counts->num_comp_pipelines]); + size += sizeof (qfv_taskinfo_t [counts->num_tasks]); + size += sizeof (VkDescriptorSet [counts->num_descriptorsets]); rctx->job = malloc (size); __auto_type job = rctx->job; From 3235bb70c861c64a4df5394ed4caca3c6e8edfa5 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 17 Jun 2023 12:13:38 +0900 Subject: [PATCH 3614/3664] [vulkan] Move attachement specs into frambuffer This does a better job of keeping related data together. --- include/QF/Vulkan/render.h | 4 +- libs/video/renderer/vulkan/render_load.c | 16 +-- libs/video/renderer/vulkan/rp_main_def.plist | 110 +++++++++---------- libs/video/renderer/vulkan/vkparse.plist | 10 +- 4 files changed, 69 insertions(+), 71 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index ef1b5ff45..8adee7233 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -195,7 +195,7 @@ typedef struct qfv_subpassinfo_s { } qfv_subpassinfo_t; typedef struct qfv_framebufferinfo_s { - qfv_reference_t *attachments; + qfv_attachmentinfo_t *attachments; uint32_t num_attachments; uint32_t width; uint32_t height; @@ -206,8 +206,6 @@ typedef struct qfv_renderpassinfo_s { vec4f_t color; const char *name; void *pNext; - uint32_t num_attachments; - qfv_attachmentinfo_t *attachments; qfv_framebufferinfo_t framebuffer; uint32_t num_subpasses; qfv_subpassinfo_t *subpasses; diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 872d5aa92..105689446 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -146,7 +146,7 @@ count_sp_stuff (qfv_subpassinfo_t *spi, objcount_t *counts) static void count_rp_stuff (qfv_renderpassinfo_t *rpi, objcount_t *counts) { - counts->num_attachments += rpi->num_attachments; + counts->num_attachments += rpi->framebuffer.num_attachments; counts->num_subpasses += rpi->num_subpasses; for (uint32_t i = 0; i < rpi->num_subpasses; i++) { count_sp_stuff (&rpi->subpasses[i], counts); @@ -519,8 +519,8 @@ init_plCreate (VkGraphicsPipelineCreateInfo *plc, const qfv_pipelineinfo_t *pli, static uint32_t __attribute__((pure)) find_attachment (qfv_reference_t *ref, objstate_t *s) { - for (uint32_t i = 0; i < s->rpi->num_attachments; i++) { - __auto_type a = &s->rpi->attachments[i]; + for (uint32_t i = 0; i < s->rpi->framebuffer.num_attachments; i++) { + __auto_type a = &s->rpi->framebuffer.attachments[i]; if (strcmp (ref->name, a->name) == 0) { return i; } @@ -671,8 +671,8 @@ init_rpCreate (uint32_t index, const qfv_renderinfo_t *rinfo, objstate_t *s) __auto_type subpasses = &s->ptr.subpass[s->inds.num_subpasses]; __auto_type dependencies = &s->ptr.depend[s->inds.num_dependencies]; - for (uint32_t i = 0; i < s->rpi->num_attachments; i++) { - init_atCreate (i, s->rpi->attachments, s); + for (uint32_t i = 0; i < s->rpi->framebuffer.num_attachments; i++) { + init_atCreate (i, s->rpi->framebuffer.attachments, s); s->inds.num_attachments++; } @@ -685,7 +685,7 @@ init_rpCreate (uint32_t index, const qfv_renderinfo_t *rinfo, objstate_t *s) *s->rpc = (VkRenderPassCreateInfo) { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = s->rpi->num_attachments, + .attachmentCount = s->rpi->framebuffer.num_attachments, .pAttachments = attachments, .subpassCount = s->rpi->num_subpasses, .pSubpasses = subpasses, @@ -777,12 +777,12 @@ init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo, .beginInfo = (VkRenderPassBeginInfo) { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .renderPass = s->ptr.rp[s->inds.num_renderpasses], - .clearValueCount = rpinfo->num_attachments, + .clearValueCount = rpinfo->framebuffer.num_attachments, .pClearValues = &jp->clearvalues[s->inds.num_attachments], }, .subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, }; - s->inds.num_attachments += rpinfo->num_attachments; + s->inds.num_attachments += rpinfo->framebuffer.num_attachments; for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) { init_subpass (&rp->subpasses[i], &rpinfo->subpasses[i], jp, s); rp->subpasses[i].inherit.renderPass = rp->beginInfo.renderPass; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index ce42ca3bd..20f09c8a9 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -846,55 +846,55 @@ output = { renderpasses = { deferred = { color = "[0, 1, 0, 1]"; - attachments = { - depth = { - @inherit = $attachment_base; - format = $images.depth.format; - loadOp = clear; - finalLayout = depth_stencil_attachment_optimal; - clearValue = { depthStencil = { depth = 1; stencil = 0; }; }; - view = $imageviews.depth; - }; - color = { - @inherit = $attachment_base; - format = $images.color.format; - loadOp = clear; - view = $imageviews.color; - }; - emission = { - @inherit = $attachment_base; - format = $images.emission.format; - loadOp = clear; - view = $imageviews.emission; - }; - normal = { - @inherit = $attachment_base; - format = $images.normal.format; - view = $imageviews.normal; - }; - position = { - @inherit = $attachment_base; - format = $images.position.format; - view = $imageviews.position; - }; - opaque = { - @inherit = $attachment_base; - format = $images.opaque.format; - view = $imageviews.opaque; - }; - output = { - @inherit = $attachment_base; - format = $render_output.format; - loadOp = clear; - storeOp = store; - finalLayout = $render_output.finalLayout; - view = $imageviews.output; - }; - }; framebuffer = { width = $render_output.extent.width; height = $render_output.extent.height; layers = 1; + attachments = { + depth = { + @inherit = $attachment_base; + format = $images.depth.format; + loadOp = clear; + finalLayout = depth_stencil_attachment_optimal; + clearValue = { depthStencil = { depth = 1; stencil = 0; }; }; + view = $imageviews.depth; + }; + color = { + @inherit = $attachment_base; + format = $images.color.format; + loadOp = clear; + view = $imageviews.color; + }; + emission = { + @inherit = $attachment_base; + format = $images.emission.format; + loadOp = clear; + view = $imageviews.emission; + }; + normal = { + @inherit = $attachment_base; + format = $images.normal.format; + view = $imageviews.normal; + }; + position = { + @inherit = $attachment_base; + format = $images.position.format; + view = $imageviews.position; + }; + opaque = { + @inherit = $attachment_base; + format = $images.opaque.format; + view = $imageviews.opaque; + }; + output = { + @inherit = $attachment_base; + format = $render_output.format; + loadOp = clear; + storeOp = store; + finalLayout = $render_output.finalLayout; + view = $imageviews.output; + }; + }; }; subpasses = { depth = { @@ -1242,20 +1242,20 @@ renderpasses = { }; output = { color = "[0, 1, 1, 1]"; - attachments = { - output = { - @inherit = $attachment_base; - format = $render_output.format; - loadOp = clear; - storeOp = store; - finalLayout = present_src_khr; - view = $render_output.view; - }; - }; framebuffer = { width = $render_output.extent.width; height = $render_output.extent.height; layers = 1; + attachments = { + output = { + @inherit = $attachment_base; + format = $render_output.format; + loadOp = clear; + storeOp = store; + finalLayout = present_src_khr; + view = $render_output.view; + }; + }; }; subpasses = { compose = { diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 977814651..c53fa7a32 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -629,6 +629,11 @@ parse = { width = auto; height = auto; layers = auto; + attachments = { + type = (labeledarray, qfv_attachmentinfo_t, name); + size = num_attachments; + values = attachments; + }; }; qfv_reference_s = { .name = qfv_reference_t; @@ -641,11 +646,6 @@ parse = { qfv_renderpassinfo_s = { .name = qfv_renderpassinfo_t; color = auto; - attachments = { - type = (labeledarray, qfv_attachmentinfo_t, name); - size = num_attachments; - values = attachments; - }; framebuffer = auto; subpasses = { type = (labeledarray, qfv_subpassinfo_t, name); From 65b2e1750c83c18aa9c4bb0b176c74dae3f5b319 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Jun 2023 17:14:34 +0900 Subject: [PATCH 3615/3664] [build] Fix escaping of \ in plist to plc Quoting is hard. --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 5276ac096..b0f5d2f65 100644 --- a/Makefile.am +++ b/Makefile.am @@ -133,7 +133,7 @@ V_SED_1 = SUFFICES += .plist .plc .plist.plc: - $(V_SED)sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\ + $(V_SED)sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $< > $@.t &&\ $(am__mv) $@.t $@ %.spv: % From d8239bf9e23667ce0a70bdd149659087458a18e0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Jun 2023 17:16:58 +0900 Subject: [PATCH 3616/3664] [qtypes] Support auto in pre-c23 compilers I'm not yet ready to do a full-on transition to gcc-13 with -std=gnu2x, but I'm tired of __auto_type's ugliness. --- include/QF/qtypes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/QF/qtypes.h b/include/QF/qtypes.h index b37874305..5647f685b 100644 --- a/include/QF/qtypes.h +++ b/include/QF/qtypes.h @@ -53,6 +53,7 @@ typedef uint8_t byte; #endif #if __STDC_VERSION__ < 202000 +#define auto __auto_type #ifndef _DEF_BOOL_ # define _DEF_BOOL_ // KJB Undefined true and false defined in SciTech's DEBUG.H header From 8e25fb13d15b9b63ea73093cf292b6b455a941ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Jun 2023 17:20:38 +0900 Subject: [PATCH 3617/3664] [cexpr] Add string and voidptr types The string type is useful for passing around strings (the only thing that they can do, currently), particularly as arguments to functions. The voidptr type is (currently) never generated by the core cexpr system, but is useful for storing pointers via cexpr (probably a bit of a hack, but it seems to work well in my current use). --- include/QF/cexpr.h | 3 +++ libs/util/cexpr-lex.l | 16 ++++++++++++++++ libs/util/cexpr-type.c | 10 ++++++++++ 3 files changed, 29 insertions(+) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index 5935e37bb..b035275c7 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -151,6 +151,9 @@ extern exprtype_t cexpr_exprval; extern exprtype_t cexpr_field; extern exprtype_t cexpr_function; extern exprtype_t cexpr_plitem; +extern exprtype_t cexpr_string; +// generic pointer holder, never generated directly by cexpr +extern exprtype_t cexpr_voidptr; extern binop_t cexpr_array_binops[]; extern binop_t cexpr_struct_binops[]; diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index 88dced412..ef91d414d 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -76,6 +76,7 @@ static exprval_t *parse_uint (const char *str, exprctx_t *context); static exprval_t *parse_size_t (const char *str, exprctx_t *context); static exprval_t *parse_float (const char *str, exprctx_t *context); static exprval_t *parse_double (const char *str, exprctx_t *context); +static exprval_t *parse_string (const char *str, exprctx_t *context); static exprsym_t *parse_name (const char *str, exprctx_t *context); static exprval_t *parse_variable (const char *str, exprctx_t *context); @@ -174,6 +175,8 @@ STRING \"(\\.|[^"\\])*\" } {STRING} { + yylval->value = parse_string (yytext, context); + return VALUE; } @ return '@'; @@ -292,6 +295,19 @@ static exprval_t *parse_double (const char *str, exprctx_t *context) return val; } +static exprval_t *parse_string (const char *str, exprctx_t *context) +{ + exprval_t *val = cexpr_value (&cexpr_string, context); + // str includes the quotes, which add 2 to the length of the string, but + // only one byte is needed for the terminating nul + size_t size = strlen (str) - 1; + char *dup = cmemalloc (context->memsuper, size); + strncpy (dup, str + 1, size - 1); + dup[size - 1] = 0; + *(char **) val->value = dup; + return val; +} + static exprsym_t * parse_name (const char *name, exprctx_t *context) { diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 369195d05..656a36da7 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -774,6 +774,16 @@ exprtype_t cexpr_plitem = { .unops = 0, }; +exprtype_t cexpr_string = { + .name = "string", + .size = sizeof (char *), +}; + +exprtype_t cexpr_voidptr = { + .name = "voidptr", + .size = sizeof (void *), +}; + VISIBLE binop_t * cexpr_find_cast (exprtype_t *dst_type, exprtype_t *src_type) { From 2cadf040d338af4a529b3f0474a8d85d5b284e1e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Jun 2023 18:42:07 +0900 Subject: [PATCH 3618/3664] [vulkan] Add a step and task to create a framebuffer I don't like the current name (update_framebuffer), but if the referenced render pass doesn't have a framebuffer, one is created. The renderpass is referenced via the active renderpass of the named render step. Unfortunately, this has uncovered a bug in the setup of renderpass objects: main.deferred has output's renderpass, and main.deferred_cube and output have bogus renderpass objects. --- include/QF/Vulkan/render.h | 7 +- libs/video/renderer/vid_render_vulkan.c | 1 - libs/video/renderer/vulkan/render.c | 121 ++++++++++++++++--- libs/video/renderer/vulkan/render_load.c | 26 +--- libs/video/renderer/vulkan/rp_main_def.plist | 24 ++-- libs/video/renderer/vulkan/vulkan_output.c | 19 --- 6 files changed, 123 insertions(+), 75 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 8adee7233..f00da4ab8 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -313,10 +313,7 @@ typedef struct qfv_renderpass_s { VkRenderPassBeginInfo beginInfo; VkSubpassContents subpassContents; - //struct qfv_imageset_s *attachment_images; - //struct qfv_imageviewset_s *attachment_views; - //VkDeviceMemory attachmentMemory; - //size_t attachmentMemory_size; + qfv_framebufferinfo_t *framebufferinfo; //qfv_output_t output; uint32_t subpass_count; @@ -386,8 +383,6 @@ void QFV_AppendCmdBuffer (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd); void QFV_RunRenderJob (struct vulkan_ctx_s *ctx); void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx); void QFV_BuildRender (struct vulkan_ctx_s *ctx); -void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx); -void QFV_DestroyFramebuffer (struct vulkan_ctx_s *ctx); void QFV_Render_Init (struct vulkan_ctx_s *ctx); void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx); void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index a5b110146..e403394fa 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -118,7 +118,6 @@ vulkan_R_Init (void) QFV_LoadRenderInfo (vulkan_ctx); QFV_BuildRender (vulkan_ctx); - QFV_CreateFramebuffer (vulkan_ctx); Skin_Init (); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index c03f04bcf..d34c1fee3 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -252,10 +252,10 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) } } +#if 0 void QFV_DestroyFramebuffer (vulkan_ctx_t *ctx) { -#if 0 qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type rctx = ctx->render_context; @@ -267,31 +267,48 @@ QFV_DestroyFramebuffer (vulkan_ctx_t *ctx) rp->beginInfo.framebuffer = 0; dfunc->vkDestroyFramebuffer (device->dev, framebuffer, 0); } +} #endif + +static VkImageView __attribute__((pure)) +find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx) +{ + __auto_type jinfo = rctx->jobinfo; + __auto_type job = rctx->job; + const char *name = ref->name; + + if (strncmp (name, "$imageviews.", 7) == 0) { + name += 7; + } + + for (uint32_t i = 0; i < jinfo->num_imageviews; i++) { + __auto_type vi = &jinfo->imageviews[i]; + __auto_type vo = &job->image_views[i]; + if (strcmp (name, vi->name) == 0) { + return vo->image_view.view; + } + } + Sys_Error ("%d:invalid imageview: %s", ref->line, ref->name); } -void -QFV_CreateFramebuffer (vulkan_ctx_t *ctx) +static void +QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) { -#if 0 __auto_type rctx = ctx->render_context; - __auto_type rinfo = rctx->renderinfo; - __auto_type job = rctx->job; - __auto_type rpInfo = &rinfo->renderpasses[0]; - __auto_type rp = &job->renderpasses[0]; - VkImageView attachments[rpInfo->num_attachments]; + auto fb = rp->framebufferinfo; + VkImageView attachments[fb->num_attachments]; VkFramebufferCreateInfo cInfo = { .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .attachmentCount = rpInfo->num_attachments, + .attachmentCount = fb->num_attachments, .pAttachments = attachments, .renderPass = rp->beginInfo.renderPass, - .width = rpInfo->framebuffer.width, - .height = rpInfo->framebuffer.height, - .layers = rpInfo->framebuffer.layers, + .width = fb->width, + .height = fb->height, + .layers = fb->layers, }; - for (uint32_t i = 0; i < rpInfo->num_attachments; i++) { - attachments[i] = find_imageview (&rpInfo->attachments[i].view, rctx); + for (uint32_t i = 0; i < fb->num_attachments; i++) { + attachments[i] = find_imageview (&fb->attachments[i].view, rctx); } qfv_device_t *device = ctx->device; @@ -299,16 +316,82 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx) VkFramebuffer framebuffer; dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); QFV_duSetObjectName (device, VK_OBJECT_TYPE_FRAMEBUFFER, framebuffer, - va (ctx->va_ctx, "framebuffer:%s", rpInfo->name)); + va (ctx->va_ctx, "framebuffer:%s", rp->label.name)); rp->beginInfo.framebuffer = framebuffer; for (uint32_t i = 0; i < rp->subpass_count; i++) { __auto_type sp = &rp->subpasses[i]; sp->inherit.framebuffer = framebuffer; } -#endif } +static void +wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + __auto_type taskctx = (qfv_taskctx_t *) ectx; + vulkan_ctx_t *ctx = taskctx->ctx; + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + VkDevice dev = device->dev; + + __auto_type frame = &ctx->frames.a[ctx->curFrame]; + + dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); +} + +static void +update_framebuffer (const exprval_t **params, exprval_t *result, + exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto stepref = params[0]; + + // cache the render step referenced, using the parameter type as a flag + // for whether the caching has been performed. + if (stepref->type == &cexpr_string) { + if (cexpr_string.size != cexpr_voidptr.size) { + Sys_Error ("string and voidptr incompatible sizes"); + } + auto name = *(const char **)stepref->value; + ((exprval_t *) stepref)->type = &cexpr_voidptr; + *(void **)stepref->value = 0; + auto job = ctx->render_context->job; + for (uint32_t i = 0; i < job->num_steps; i++) { + auto step = &job->steps[i]; + if (!strcmp (step->label.name, name)) { + *(void **)stepref->value = step; + break; + } + } + } + auto step = *(qfv_step_t **)stepref->value; + auto render = step->render; + auto rp = render->active; + + if (!rp->beginInfo.framebuffer) { + QFV_CreateFramebuffer (ctx, rp); + } +} + +static exprfunc_t wait_on_fence_func[] = { + { .func = wait_on_fence }, + {} +}; + +static exprtype_t *update_framebuffer_params[] = { + &cexpr_string, +}; +static exprfunc_t update_framebuffer_func[] = { + { .func = update_framebuffer, .num_params = 1, update_framebuffer_params }, + {} +}; +static exprsym_t render_task_syms[] = { + { "wait_on_fence", &cexpr_function, wait_on_fence_func }, + { "update_framebuffer", &cexpr_function, update_framebuffer_func }, + {} +}; + void QFV_Render_Init (vulkan_ctx_t *ctx) { @@ -320,6 +403,8 @@ QFV_Render_Init (vulkan_ctx_t *ctx) rctx->task_functions.symbols = syms; cexpr_init_symtab (&rctx->task_functions, &ectx); rctx->task_functions.symbols = 0; + + QFV_Render_AddTasks (ctx, render_task_syms); } void @@ -330,7 +415,7 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) __auto_type rctx = ctx->render_context; if (rctx->job) { __auto_type job = rctx->job; - QFV_DestroyFramebuffer (ctx); //FIXME do properly + //QFV_DestroyFramebuffer (ctx); //FIXME do properly for (uint32_t i = 0; i < job->num_renderpasses; i++) { dfunc->vkDestroyRenderPass (device->dev, job->renderpasses[i], 0); } diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 105689446..d5e174f8c 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -772,15 +772,16 @@ init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo, .vulkan_ctx = s->ctx, .label.name = rpinfo->name, .label.color = rpinfo->color, - .subpass_count = rpinfo->num_subpasses, - .subpasses = &jp->subpasses[s->inds.num_subpasses], .beginInfo = (VkRenderPassBeginInfo) { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .renderPass = s->ptr.rp[s->inds.num_renderpasses], .clearValueCount = rpinfo->framebuffer.num_attachments, .pClearValues = &jp->clearvalues[s->inds.num_attachments], }, + .framebufferinfo = &rpinfo->framebuffer, .subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, + .subpass_count = rpinfo->num_subpasses, + .subpasses = &jp->subpasses[s->inds.num_subpasses], }; s->inds.num_attachments += rpinfo->framebuffer.num_attachments; for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) { @@ -1127,24 +1128,3 @@ QFV_BuildRender (vulkan_ctx_t *ctx) create_objects (ctx, &counts); create_resources (ctx, &counts); } - -static VkImageView __attribute__((pure, used)) -find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx) -{ - __auto_type jinfo = rctx->jobinfo; - __auto_type job = rctx->job; - const char *name = ref->name; - - if (strncmp (name, "$imageviews.", 7) == 0) { - name += 7; - } - - for (uint32_t i = 0; i < jinfo->num_imageviews; i++) { - __auto_type vi = &jinfo->imageviews[i]; - __auto_type vo = &job->image_views[i]; - if (strcmp (name, vi->name) == 0) { - return vo->image_view.view; - } - } - Sys_Error ("%d:invalid imageview: %s", ref->line, ref->name); -} diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 20f09c8a9..31444be67 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -857,34 +857,34 @@ renderpasses = { loadOp = clear; finalLayout = depth_stencil_attachment_optimal; clearValue = { depthStencil = { depth = 1; stencil = 0; }; }; - view = $imageviews.depth; + view = depth; }; color = { @inherit = $attachment_base; format = $images.color.format; loadOp = clear; - view = $imageviews.color; + view = color; }; emission = { @inherit = $attachment_base; format = $images.emission.format; loadOp = clear; - view = $imageviews.emission; + view = emission; }; normal = { @inherit = $attachment_base; format = $images.normal.format; - view = $imageviews.normal; + view = normal; }; position = { @inherit = $attachment_base; format = $images.position.format; - view = $imageviews.position; + view = position; }; opaque = { @inherit = $attachment_base; format = $images.opaque.format; - view = $imageviews.opaque; + view = opaque; }; output = { @inherit = $attachment_base; @@ -892,7 +892,7 @@ renderpasses = { loadOp = clear; storeOp = store; finalLayout = $render_output.finalLayout; - view = $imageviews.output; + view = output; }; }; }; @@ -1334,8 +1334,16 @@ steps = { ); }; }; + setup_main = { + process = { + tasks = ( + { func = "update_framebuffer"; + params = ("\"main\""); }, + ); + }; + }; main = { - dependencies = (particles, shadow, translucent); + dependencies = (setup_main, particles, shadow, translucent); render = { renderpasses = { deferred = $renderpasses.deferred; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 5c4d93f40..58b0b79cf 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -259,20 +259,6 @@ _output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { } -static void -wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx) -{ - __auto_type taskctx = (qfv_taskctx_t *) ectx; - vulkan_ctx_t *ctx = taskctx->ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkDevice dev = device->dev; - - __auto_type frame = &ctx->frames.a[ctx->curFrame]; - - dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); -} - static exprfunc_t acquire_output_func[] = { { .func = acquire_output }, {} @@ -285,15 +271,10 @@ static exprfunc_t output_draw_func[] = { { .func = _output_draw }, {} }; -static exprfunc_t wait_on_fence_func[] = { - { .func = wait_on_fence }, - {} -}; static exprsym_t output_task_syms[] = { { "acquire_output", &cexpr_function, acquire_output_func }, { "update_input", &cexpr_function, update_input_func }, { "output_draw", &cexpr_function, output_draw_func }, - { "wait_on_fence", &cexpr_function, wait_on_fence_func }, {} }; From 38453f3d2fd0bfe10ed00ec0b42e084853743e47 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Jun 2023 19:58:10 +0900 Subject: [PATCH 3619/3664] [vulkan] Increment render pass index one at a time This fixes the bogus render pass objects. --- libs/video/renderer/vulkan/render_load.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index d5e174f8c..52b82db9a 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -802,10 +802,10 @@ init_render (qfv_render_t *rend, qfv_renderinfo_t *rinfo, .num_renderpasses = rinfo->num_renderpasses, .renderpasses = &jp->renderpasses[s->inds.num_renderpasses], }; - s->inds.num_renderpasses += rinfo->num_renderpasses; for (uint32_t i = 0; i < rend->num_renderpasses; i++) { init_renderpass (&rend->renderpasses[i], &rinfo->renderpasses[i], jp, s); + s->inds.num_renderpasses++; } rend->active = &rend->renderpasses[0]; } From 7da8399220d86193479005449b9515048c8e6807 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 20 Jun 2023 15:18:58 +0900 Subject: [PATCH 3620/3664] [vulkan] Pass validation for the first frame The new render system now passes validation for the first frame (but no drawing is done by the various subsystems yet). Something is wrong with how swap chain semaphores are handled thus the second frame fails. Frame buffer attachments can now be defined externally, with "$swapchain" supported for now (in which case, the swap chain defines the size of the frame buffer). Also, render pass render areas and pipeline viewport and scissor rects are updated when necessary. --- include/QF/Vulkan/render.h | 14 +-- libs/video/renderer/vulkan/render.c | 99 +++++++++++++++----- libs/video/renderer/vulkan/render_load.c | 56 +++++++---- libs/video/renderer/vulkan/rp_main_def.plist | 46 ++++----- libs/video/renderer/vulkan/vkparse.plist | 25 +++++ libs/video/renderer/vulkan/vulkan_output.c | 87 +++++++++++++++-- 6 files changed, 240 insertions(+), 87 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index f00da4ab8..7526c2ee0 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -122,6 +122,7 @@ typedef struct qfv_dependencyinfo_s { typedef struct qfv_attachmentinfo_s { const char *name; + int line; VkAttachmentDescriptionFlags flags; VkFormat format; VkSampleCountFlagBits samples; @@ -133,6 +134,7 @@ typedef struct qfv_attachmentinfo_s { VkImageLayout finalLayout; VkClearValue clearValue; qfv_reference_t view; + const char *external; } qfv_attachmentinfo_t; typedef struct qfv_taskinfo_s { @@ -225,7 +227,6 @@ typedef struct qfv_renderinfo_s { uint32_t num_renderpasses; qfv_renderpassinfo_t *renderpasses; - qfv_output_t output; } qfv_renderinfo_t; typedef struct qfv_processinfo_s { @@ -274,13 +275,6 @@ typedef struct qfv_label_s { const char *name; } qfv_label_t; -typedef struct qfv_bar_s { - VkBuffer *buffers; - VkDeviceSize *offsets; - uint32_t firstBinding; - uint32_t bindingCount; -} qfv_bar_t; - typedef struct qfv_pipeline_s { qfv_label_t label; VkPipelineBindPoint bindPoint; @@ -314,7 +308,6 @@ typedef struct qfv_renderpass_s { VkSubpassContents subpassContents; qfv_framebufferinfo_t *framebufferinfo; - //qfv_output_t output; uint32_t subpass_count; qfv_subpass_t *subpasses; @@ -325,6 +318,7 @@ typedef struct qfv_render_s { qfv_renderpass_t *active; qfv_renderpass_t *renderpasses; uint32_t num_renderpasses; + qfv_output_t output; } qfv_render_t; typedef struct qfv_compute_s { @@ -386,6 +380,8 @@ void QFV_BuildRender (struct vulkan_ctx_s *ctx); void QFV_Render_Init (struct vulkan_ctx_s *ctx); void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx); void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys); + +qfv_step_t *QFV_GetStep (const exprval_t *param, qfv_job_t *job); #endif//__QFCC__ #endif//__QF_Vulkan_render_h diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index d34c1fee3..de3d774a7 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -44,9 +44,11 @@ #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/image.h" +#include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" -#include "QF/Vulkan/pipeline.h" +#include "QF/Vulkan/swapchain.h" #include "vid_vulkan.h" #include "vkparse.h" @@ -119,7 +121,6 @@ run_subpass (qfv_subpass_t *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkResetCommandBuffer (cmd, 0); dfunc->vkBeginCommandBuffer (cmd, &sp->beginInfo); QFV_duCmdBeginLabel (device, cmd, sp->label.name, {VEC4_EXP (sp->label.color)}); @@ -308,7 +309,17 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) .layers = fb->layers, }; for (uint32_t i = 0; i < fb->num_attachments; i++) { - attachments[i] = find_imageview (&fb->attachments[i].view, rctx); + if (fb->attachments[i].external) { + attachments[i] = 0; + if (!strcmp (fb->attachments[i].external, "$swapchain")) { + auto sc = ctx->swapchain; + attachments[i] = sc->imageViews->a[ctx->swapImageIndex]; + cInfo.width = sc->extent.width; + cInfo.height = sc->extent.height; + } + } else { + attachments[i] = find_imageview (&fb->attachments[i].view, rctx); + } } qfv_device_t *device = ctx->device; @@ -339,36 +350,49 @@ wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx) dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); } +static void +renderpass_update_viewper_sissor (qfv_renderpass_t *rp, + const qfv_output_t *output) +{ + rp->beginInfo.renderArea.extent = output->extent; + for (uint32_t i = 0; i < rp->subpass_count; i++) { + auto sp = &rp->subpasses[i]; + for (uint32_t j = 0; j < sp->pipeline_count; j++) { + auto pl = &sp->pipelines[j]; + pl->viewport.width = output->extent.width; + pl->viewport.height = output->extent.height; + pl->scissor.extent = output->extent; + } + } +} + +static void +update_viewport_scissor (qfv_render_t *render, const qfv_output_t *output) +{ + for (uint32_t i = 0; i < render->num_renderpasses; i++) { + renderpass_update_viewper_sissor (&render->renderpasses[i], output); + } +} + static void update_framebuffer (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { auto taskctx = (qfv_taskctx_t *) ectx; auto ctx = taskctx->ctx; - auto stepref = params[0]; - - // cache the render step referenced, using the parameter type as a flag - // for whether the caching has been performed. - if (stepref->type == &cexpr_string) { - if (cexpr_string.size != cexpr_voidptr.size) { - Sys_Error ("string and voidptr incompatible sizes"); - } - auto name = *(const char **)stepref->value; - ((exprval_t *) stepref)->type = &cexpr_voidptr; - *(void **)stepref->value = 0; - auto job = ctx->render_context->job; - for (uint32_t i = 0; i < job->num_steps; i++) { - auto step = &job->steps[i]; - if (!strcmp (step->label.name, name)) { - *(void **)stepref->value = step; - break; - } - } - } - auto step = *(qfv_step_t **)stepref->value; + auto job = ctx->render_context->job; + auto step = QFV_GetStep (params[0], job); auto render = step->render; auto rp = render->active; + qfv_output_t output = {}; + Vulkan_ConfigOutput (ctx, &output); + if (output.extent.width != render->output.extent.width + || output.extent.height != render->output.extent.height) { + //FIXME framebuffer image creation here + update_viewport_scissor (render, &output); + } + if (!rp->beginInfo.framebuffer) { QFV_CreateFramebuffer (ctx, rp); } @@ -466,3 +490,30 @@ QFV_Render_AddTasks (vulkan_ctx_t *ctx, exprsym_t *task_syms) } } } + +qfv_step_t * +QFV_GetStep (const exprval_t *param, qfv_job_t *job) +{ + // this is a little evil, but need to update the type after resolving + // the step name + auto stepref = (exprval_t *) param; + + // cache the render step referenced, using the parameter type as a flag + // for whether the caching has been performed. + if (stepref->type == &cexpr_string) { + if (cexpr_string.size != cexpr_voidptr.size) { + Sys_Error ("string and voidptr incompatible sizes"); + } + auto name = *(const char **)stepref->value; + stepref->type = &cexpr_voidptr; + *(void **)stepref->value = 0; + for (uint32_t i = 0; i < job->num_steps; i++) { + auto step = &job->steps[i]; + if (!strcmp (step->label.name, name)) { + *(void **)stepref->value = step; + break; + } + } + } + return *(qfv_step_t **)stepref->value; +} diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 52b82db9a..804e2d294 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -44,9 +44,10 @@ #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" -#include "QF/Vulkan/pipeline.h" +#include "QF/Vulkan/swapchain.h" #include "vid_vulkan.h" #include "vkparse.h" @@ -211,13 +212,15 @@ count_stuff (qfv_jobinfo_t *jobinfo, objcount_t *counts) static void create_resources (vulkan_ctx_t *ctx, objcount_t *counts) { - __auto_type rctx = ctx->render_context; - __auto_type jinfo = rctx->jobinfo; - __auto_type job = rctx->job; + auto rctx = ctx->render_context; + auto jinfo = rctx->jobinfo; + auto job = rctx->job; - job->resources = malloc (sizeof(qfv_resource_t) - + counts->num_images * sizeof (qfv_resobj_t) - + counts->num_imageviews * sizeof (qfv_resobj_t)); + size_t size = sizeof (qfv_resource_t); + size += sizeof (qfv_resobj_t [counts->num_images]); + size += sizeof (qfv_resobj_t [counts->num_imageviews]); + + job->resources = malloc (size); job->images = (qfv_resobj_t *) &job->resources[1]; job->image_views = &job->images[counts->num_images]; @@ -646,17 +649,32 @@ init_atCreate (uint32_t index, qfv_attachmentinfo_t *attachments, objstate_t *s) __auto_type atc = &s->ptr.attach[s->inds.num_attachments]; __auto_type cvc = &s->ptr.clear[s->inds.num_attachments]; - *atc = (VkAttachmentDescription) { - .flags = ati->flags, - .format = ati->format, - .samples = ati->samples, - .loadOp = ati->loadOp, - .storeOp = ati->storeOp, - .stencilLoadOp = ati->stencilLoadOp, - .stencilStoreOp = ati->stencilStoreOp, - .initialLayout = ati->initialLayout, - .finalLayout = ati->finalLayout, - }; + if (ati->external) { + if (!strcmp (ati->external, "$swapchain")) { + *atc = (VkAttachmentDescription) { + .format = s->ctx->swapchain->format, + .samples = 1, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + }; + } + } else { + *atc = (VkAttachmentDescription) { + .flags = ati->flags, + .format = ati->format, + .samples = ati->samples, + .loadOp = ati->loadOp, + .storeOp = ati->storeOp, + .stencilLoadOp = ati->stencilLoadOp, + .stencilStoreOp = ati->stencilStoreOp, + .initialLayout = ati->initialLayout, + .finalLayout = ati->finalLayout, + }; + } *cvc = ati->clearValue; } @@ -937,7 +955,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) for (uint32_t i = 0; i < s.inds.num_layouts; i++) { job->layouts[i] = s.ptr.layouts[i].layout; } - memcpy (cv, s.ptr.clear, counts->num_attachments * sizeof (VkClearValue)); + memcpy (cv, s.ptr.clear, sizeof (VkClearValue [counts->num_attachments ])); uint32_t num_layouts = s.inds.num_layouts; s.inds = (objcount_t) {}; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 31444be67..026274e23 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -939,7 +939,7 @@ renderpasses = { alias:depth = { color = $color.alias; tasks = ( - { func = "alias_draw"; }, + { func = alias_draw; }, ); stages = ( @@ -964,7 +964,7 @@ renderpasses = { iqm:depth = { color = $color.iqm; tasks = ( - { func = "iqm_draw"; }, + { func = iqm_draw; }, ); stages = ( @@ -977,7 +977,7 @@ renderpasses = { sprite:depth = { color = $color.sprite; tasks = ( - { func = "sprite_draw"; }, + { func = sprite_draw; }, ); stages = ( @@ -1121,7 +1121,7 @@ renderpasses = { alias:gbuffer = { color = $color.alias; tasks = ( - { func = "alias_draw"; }, + { func = alias_draw; }, ); stages = ( @@ -1135,7 +1135,7 @@ renderpasses = { iqm:gbuffer = { color = $color.iqm; tasks = ( - { func = "iqm_draw"; }, + { func = iqm_draw; }, ); stages = ( @@ -1149,7 +1149,7 @@ renderpasses = { sprite:gbuffer = { color = $color.sprite; tasks = ( - { func = "sprite_draw"; }, + { func = sprite_draw; }, ); stages = ( @@ -1189,7 +1189,7 @@ renderpasses = { color = $color.lights; tasks = ( - { func = "lights_draw"; }, + { func = lights_draw; }, ); stages = ( @@ -1220,7 +1220,7 @@ renderpasses = { color = $color.compose; tasks = ( - { func = "compose_draw"; }, + { func = compose_draw; }, ); stages = ( @@ -1243,18 +1243,9 @@ renderpasses = { output = { color = "[0, 1, 1, 1]"; framebuffer = { - width = $render_output.extent.width; - height = $render_output.extent.height; layers = 1; attachments = { - output = { - @inherit = $attachment_base; - format = $render_output.format; - loadOp = clear; - storeOp = store; - finalLayout = present_src_khr; - view = $render_output.view; - }; + output = $swapchain; }; }; subpasses = { @@ -1271,7 +1262,7 @@ renderpasses = { color = $color.output; tasks = ( - { func = "output_draw"; }, + { func = output_draw; }, ); stages = ( @@ -1289,7 +1280,7 @@ steps = { wait_on_fence = { process = { tasks = ( - { func = "wait_on_fence"; }, + { func = wait_on_fence; }, ); }; }; @@ -1300,7 +1291,7 @@ steps = { part:update = { color = "[0.3, 0.8, 0.9]"; tasks = ( - { func = "update_particles"; } + { func = update_particles; } ); stage = { name = main; @@ -1311,7 +1302,7 @@ steps = { part:physics = { color = "[0.6, 0.8, 0.9]"; tasks = ( - { func = "particle_physics"; } + { func = particle_physics; } ); stage = { name = main; @@ -1330,14 +1321,14 @@ steps = { dependencies = (wait_on_fence); process = { tasks = ( - { func = "clear_translucent"; }, + { func = clear_translucent; }, ); }; }; setup_main = { process = { tasks = ( - { func = "update_framebuffer"; + { func = update_framebuffer; params = ("\"main\""); }, ); }; @@ -1355,8 +1346,11 @@ steps = { dependencies = (wait_on_fence); process = { tasks = ( - { func = "acquire_output"; }, - { func = "update_input"; }, + { func = acquire_output; + params = ("\"output\""); }, + { func = update_framebuffer; + params = ("\"output\""); }, + { func = update_input; }, ); }; }; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index c53fa7a32..1b6fcb021 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -624,6 +624,31 @@ parse = { value = base_pipeline; }; }; + qfv_attachmentinfo_s = { + .name = qfv_attachmentinfo_t; + .type = (QFString, QFDictionary); + .string = { + name = $name; + line = $item.line; + external = $item.string; + }; + .dictionary = { + .parse = auto; + name = $name; + line = $item.line; + }; + flags = auto; + format = auto; + samples = auto; + loadOp = auto; + storeOp = auto; + stencilLoadOp = auto; + stencilStoreOp = auto; + initialLayout = auto; + finalLayout = auto; + clearValue = auto; + view = auto; + }; qfv_framebufferinfo_s = { .name = qfv_framebufferinfo_t; width = auto; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 58b0b79cf..1ddf1b8a2 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -103,7 +103,7 @@ acquire_image (qfv_renderframe_t *rFrame) } static void -update_input (qfv_renderframe_t *rFrame) +output_update_input (qfv_renderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -134,7 +134,7 @@ static void preoutput_draw (qfv_renderframe_t *rFrame) { acquire_image (rFrame); - update_input (rFrame); + output_update_input (rFrame); } static void @@ -212,7 +212,7 @@ process_input (qfv_renderframe_t *rFrame) } static void -output_draw (qfv_renderframe_t *rFrame) +draw_output (qfv_renderframe_t *rFrame) { process_input (rFrame); Vulkan_FlushText (rFrame); @@ -224,7 +224,7 @@ Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx) outputctx_t *octx = calloc (1, sizeof (outputctx_t)); ctx->output_context = octx; - __auto_type out = QFV_RenderPass_New (ctx, "output", output_draw); + __auto_type out = QFV_RenderPass_New (ctx, "output", draw_output); out->output = (qfv_output_t) { .extent = ctx->swapchain->extent, .format = ctx->swapchain->format, @@ -247,28 +247,97 @@ Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx) static void acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto frame = &ctx->frames.a[ctx->curFrame]; + + uint32_t imageIndex = 0; + while (!QFV_AcquireNextImage (ctx->swapchain, + frame->imageAvailableSemaphore, + 0, &imageIndex)) { + QFV_DeviceWaitIdle (device); + if (ctx->capture) { + QFV_DestroyCapture (ctx->capture); + } + Vulkan_CreateSwapchain (ctx); + Vulkan_CreateCapture (ctx); + + __auto_type out = ctx->output_renderpass; + out->output = (qfv_output_t) { + .extent = ctx->swapchain->extent, + .format = ctx->swapchain->format, + .frames = ctx->swapchain->numImages, + .view_list = ctx->swapchain->imageViews->a, + }; + out->viewport.width = out->output.extent.width; + out->viewport.height = out->output.extent.height; + out->scissor.extent = out->output.extent; + auto step = QFV_GetStep (params[0], ctx->render_context->job); + auto render = step->render; + for (uint32_t i = 0; i < render->num_renderpasses; i++) { + auto rp = &render->renderpasses[i]; + if (rp->beginInfo.framebuffer) { + dfunc->vkDestroyFramebuffer (device->dev, + rp->beginInfo.framebuffer, 0); + } + rp->beginInfo.framebuffer = 0; // leave for update_framebuffer + } + + dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore, + 0); + frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); + } + ctx->swapImageIndex = imageIndex; } static void -_update_input (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +update_input (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto octx = ctx->output_context; + auto oframe = &octx->frames.a[ctx->curFrame]; + + if (oframe->input == octx->input) { + return; + } + oframe->input = octx->input; + + VkDescriptorImageInfo imageInfo = { + octx->sampler, oframe->input, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + VkWriteDescriptorSet write[] = { + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + oframe->set, 0, 0, 1, + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + &imageInfo, 0, 0 } + }; + dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); } static void -_output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { } +static exprtype_t *stepref_param[] = { + &cexpr_string, +}; static exprfunc_t acquire_output_func[] = { - { .func = acquire_output }, + { .func = acquire_output, .num_params = 1, stepref_param }, {} }; static exprfunc_t update_input_func[] = { - { .func = _update_input }, + { .func = update_input, .num_params = 1, stepref_param }, {} }; static exprfunc_t output_draw_func[] = { - { .func = _output_draw }, + { .func = output_draw }, {} }; static exprsym_t output_task_syms[] = { From f0d32ba956ba80cd15f7d7757ec4d19dcbbc643f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Jun 2023 13:43:04 +0900 Subject: [PATCH 3621/3664] [vulkan] Rearrange allocations for alignment Interleaving Vulkan objects with stucts containing vec4f_t results in the vectors becoming unaligned when there is an odd number of objects in a set, thus producing a segfault. Putting all the structs first prevents any such issue. --- libs/video/renderer/vulkan/render_load.c | 37 ++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 804e2d294..f8ab1c14d 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -892,25 +892,25 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) size_t size = sizeof (qfv_job_t); - size += sizeof (VkRenderPass [counts->num_renderpasses]); - size += sizeof (VkPipeline [counts->num_graph_pipelines]); - size += sizeof (VkPipeline [counts->num_comp_pipelines]); - size += sizeof (VkPipelineLayout [s.inds.num_layouts]); - size += sizeof (qfv_step_t [counts->num_steps]); size += sizeof (qfv_render_t [counts->num_render]); size += sizeof (qfv_compute_t [counts->num_compute]); size += sizeof (qfv_process_t [counts->num_process]); size += sizeof (qfv_renderpass_t [counts->num_renderpasses]); - size += sizeof (VkClearValue [counts->num_attachments]); size += sizeof (qfv_subpass_t [counts->num_subpasses]); size += sizeof (qfv_pipeline_t [counts->num_graph_pipelines]); size += sizeof (qfv_pipeline_t [counts->num_comp_pipelines]); size += sizeof (qfv_taskinfo_t [counts->num_tasks]); + + size += sizeof (VkClearValue [counts->num_attachments]); + size += sizeof (VkRenderPass [counts->num_renderpasses]); + size += sizeof (VkPipeline [counts->num_graph_pipelines]); + size += sizeof (VkPipeline [counts->num_comp_pipelines]); + size += sizeof (VkPipelineLayout [s.inds.num_layouts]); size += sizeof (VkDescriptorSet [counts->num_descriptorsets]); rctx->job = malloc (size); - __auto_type job = rctx->job; + auto job = rctx->job; *job = (qfv_job_t) { .num_renderpasses = counts->num_renderpasses, .num_pipelines = counts->num_graph_pipelines @@ -919,19 +919,20 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) .num_steps = counts->num_steps, .commands = DARRAY_STATIC_INIT (16), }; - job->renderpasses = (VkRenderPass *) &job[1]; + job->steps = (qfv_step_t *) &job[1]; + auto rn = (qfv_render_t *) &job->steps[job->num_steps]; + auto cp = (qfv_compute_t *) &rn[counts->num_render]; + auto pr = (qfv_process_t *) &cp[counts->num_compute]; + auto rp = (qfv_renderpass_t *) &pr[counts->num_process]; + auto sp = (qfv_subpass_t *) &rp[counts->num_renderpasses]; + auto pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; + auto ti = (qfv_taskinfo_t *) &pl[job->num_pipelines]; + + auto cv = (VkClearValue *) &ti[counts->num_tasks]; + job->renderpasses = (VkRenderPass *) &cv[counts->num_attachments]; job->pipelines = (VkPipeline *) &job->renderpasses[job->num_renderpasses]; job->layouts = (VkPipelineLayout *) &job->pipelines[job->num_pipelines]; - job->steps = (qfv_step_t *) &job->layouts[job->num_layouts]; - __auto_type rn = (qfv_render_t *) &job->steps[job->num_steps]; - __auto_type cp = (qfv_compute_t *) &rn[counts->num_render]; - __auto_type pr = (qfv_process_t *) &cp[counts->num_compute]; - __auto_type rp = (qfv_renderpass_t *) &pr[counts->num_process]; - __auto_type cv = (VkClearValue *) &rp[counts->num_renderpasses]; - __auto_type sp = (qfv_subpass_t *) &cv[counts->num_attachments]; - __auto_type pl = (qfv_pipeline_t *) &sp[counts->num_subpasses]; - __auto_type ti = (qfv_taskinfo_t *) &pl[job->num_pipelines]; - __auto_type ds = (VkDescriptorSet *) &ti[counts->num_tasks]; + auto ds = (VkDescriptorSet *) &job->layouts[job->num_layouts]; jobptr_t jp = { .steps = job->steps, .renders = rn, From 503013dd38b964afc2ddcaf46697a8195afa477b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Jun 2023 13:46:29 +0900 Subject: [PATCH 3622/3664] [vulkan] Use per-frame command buffer pools Command buffer pools can't be reset until the commands have all been executed. Having per-frame pools makes keeping track of pool lifetime fairly easy. --- include/vid_vulkan.h | 1 + libs/video/renderer/vulkan/render_load.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 02b696a6f..e9e252511 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -15,6 +15,7 @@ typedef struct vulkan_frame_s { VkSemaphore imageAvailableSemaphore; VkSemaphore renderDoneSemaphore; VkCommandBuffer cmdBuffer; + VkCommandPool command_pool; } vulkan_frame_t; typedef struct vulkan_frameset_s diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index f8ab1c14d..25b1abcfb 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -964,15 +964,6 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) for (uint32_t i = 0; i < job->num_steps; i++) { init_step (i, &jp, &s); } - - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkCommandPoolCreateInfo poolCInfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - .queueFamilyIndex = device->queue.queueFamily, - }; - dfunc->vkCreateCommandPool (device->dev, &poolCInfo, 0, &job->command_pool); } static void @@ -1134,6 +1125,17 @@ create_objects (vulkan_ctx_t *ctx, objcount_t *counts) counts->num_descriptorsets = s.inds.num_descriptorsets; init_job (ctx, counts, s); + + for (uint32_t i = 0; i < ctx->frames.size; i++) { + VkCommandPoolCreateInfo poolCInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + .queueFamilyIndex = device->queue.queueFamily, + }; + auto frame = &ctx->frames.a[i]; + dfunc->vkCreateCommandPool (device->dev, &poolCInfo, 0, + &frame->command_pool); + } } void From 25cfef18d67d6e63723597e91ec09ed7f7359af8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Jun 2023 14:47:19 +0900 Subject: [PATCH 3623/3664] [vulkan] Use per-swapchain images for output framebuffers Imageless framebuffers would probably be easier and cleaner, but this takes care of the validation error attempting to present the second frame (because rendering was being done to the first frame's swapchain image instead of the second frame's). --- include/QF/Vulkan/qf_output.h | 1 + include/QF/Vulkan/render.h | 2 + libs/video/renderer/vulkan/render.c | 60 +++++++++++---- libs/video/renderer/vulkan/rp_main_def.plist | 2 - libs/video/renderer/vulkan/vulkan_output.c | 75 ++++++++++++++----- .../video/renderer/vulkan/vulkan_vid_common.c | 3 + 6 files changed, 108 insertions(+), 35 deletions(-) diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index ef4ea0b1b..d5436216d 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -53,6 +53,7 @@ typedef struct outputctx_s { VkPipelineLayout fish_layout; VkSampler sampler; VkImageView input; + VkFramebuffer *framebuffers; // one per swapchain image } outputctx_t; struct vulkan_ctx_s; diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 7526c2ee0..66114798f 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -381,6 +381,8 @@ void QFV_Render_Init (struct vulkan_ctx_s *ctx); void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx); void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys); +void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp); + qfv_step_t *QFV_GetStep (const exprval_t *param, qfv_job_t *job); #endif//__QFCC__ diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index de3d774a7..45ba7a887 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -137,7 +137,7 @@ run_subpass (qfv_subpass_t *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx) static void run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) { - printf ("run_renderpass: %s\n", rp->label.name); + printf ("%10.2f run_renderpass: %s\n", Sys_DoubleTime (), rp->label.name); qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -167,7 +167,9 @@ run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) dfunc->vkCmdNextSubpass (cmd, rp->subpassContents); } } + dfunc->vkCmdEndRenderPass (cmd); QFV_CmdEndLabel (device, cmd); + dfunc->vkEndCommandBuffer (cmd); DARRAY_APPEND (&job->commands, cmd); } @@ -235,12 +237,12 @@ run_process (qfv_process_t *proc, vulkan_ctx_t *ctx) void QFV_RunRenderJob (vulkan_ctx_t *ctx) { - __auto_type rctx = ctx->render_context; - __auto_type job = rctx->job; + auto rctx = ctx->render_context; + auto job = rctx->job; for (uint32_t i = 0; i < job->num_steps; i++) { __auto_type step = &job->steps[i]; - printf ("run_step: %s\n", step->label.name); + printf ("%10.2f run_step: %s\n", Sys_DoubleTime (), step->label.name); if (step->render) { run_renderpass (step->render->active, ctx); } @@ -251,6 +253,31 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) run_process (step->process, ctx); } } + + auto device = ctx->device; + auto dfunc = device->funcs; + auto queue = &device->queue; + auto frame = &ctx->frames.a[ctx->curFrame]; + VkPipelineStageFlags waitStage + = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + VkSubmitInfo submitInfo = { + VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, + 1, &frame->imageAvailableSemaphore, &waitStage, + job->commands.size, job->commands.a, + 1, &frame->renderDoneSemaphore, + }; + printf ("%10.2f submit for frame %d: %zd %p\n", Sys_DoubleTime (), + ctx->curFrame, job->commands.size, frame->imageAvailableSemaphore); + dfunc->vkResetFences (device->dev, 1, &frame->fence); + dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); + + VkPresentInfoKHR presentInfo = { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, + 1, &frame->renderDoneSemaphore, + 1, &ctx->swapchain->swapchain, &ctx->swapImageIndex, + 0 + }; + dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); } #if 0 @@ -292,7 +319,7 @@ find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx) Sys_Error ("%d:invalid imageview: %s", ref->line, ref->name); } -static void +void QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) { __auto_type rctx = ctx->render_context; @@ -339,15 +366,20 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) static void wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { - __auto_type taskctx = (qfv_taskctx_t *) ectx; - vulkan_ctx_t *ctx = taskctx->ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkDevice dev = device->dev; + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto dev = device->dev; __auto_type frame = &ctx->frames.a[ctx->curFrame]; dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); + + auto job = ctx->render_context->job; + job->command_pool = frame->command_pool; + dfunc->vkResetCommandPool (device->dev, job->command_pool, 0); + DARRAY_CLEAR (&job->commands); } static void @@ -453,12 +485,14 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) QFV_DestroyResource (ctx->device, job->resources); free (job->resources); } - if (job->command_pool) { - dfunc->vkDestroyCommandPool (device->dev, job->command_pool, 0); - } + job->command_pool = 0; DARRAY_CLEAR (&job->commands); free (rctx->job); } + for (uint32_t i = 0; i < ctx->frames.size; i++) { + auto frame = &ctx->frames.a[i]; + dfunc->vkDestroyCommandPool (device->dev, frame->command_pool, 0); + } if (rctx->jobinfo) { __auto_type jinfo = rctx->jobinfo; for (uint32_t i = 0; i < jinfo->num_descriptorsetlayouts; i++) { diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 026274e23..abe043d97 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1348,8 +1348,6 @@ steps = { tasks = ( { func = acquire_output; params = ("\"output\""); }, - { func = update_framebuffer; - params = ("\"output\""); }, { func = update_input; }, ); }; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 1ddf1b8a2..669997740 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -41,6 +41,7 @@ #include "QF/cvar.h" #include "QF/render.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_matrices.h" @@ -53,6 +54,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/swapchain.h" #include "r_local.h" @@ -63,14 +65,10 @@ static void acquire_image (qfv_renderframe_t *rFrame) { - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - __auto_type frame = &ctx->frames.a[ctx->curFrame]; - //outputctx_t *octx = ctx->output_context; - //uint32_t curFrame = ctx->curFrame; - //outputframe_t *oframe = &octx->frames.a[curFrame]; - //qfv_renderpass_t *rp = ctx->output_renderpass; + auto ctx = rFrame->vulkan_ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto frame = &ctx->frames.a[ctx->curFrame]; uint32_t imageIndex = 0; while (!QFV_AcquireNextImage (ctx->swapchain, @@ -98,6 +96,9 @@ acquire_image (qfv_renderframe_t *rFrame) dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore, 0); frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_SEMAPHORE, + frame->imageAvailableSemaphore, + va (ctx->va_ctx, "sc image:%d", ctx->curFrame)); } ctx->swapImageIndex = imageIndex; } @@ -252,16 +253,24 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto device = ctx->device; auto dfunc = device->funcs; auto frame = &ctx->frames.a[ctx->curFrame]; + auto octx = ctx->output_context; + auto sc = ctx->swapchain; + printf ("acquire_output: %d\n", ctx->curFrame); uint32_t imageIndex = 0; - while (!QFV_AcquireNextImage (ctx->swapchain, - frame->imageAvailableSemaphore, + while (!QFV_AcquireNextImage (sc, frame->imageAvailableSemaphore, 0, &imageIndex)) { QFV_DeviceWaitIdle (device); if (ctx->capture) { QFV_DestroyCapture (ctx->capture); } + for (uint32_t i = 0; i < sc->imageViews->size; i++) { + dfunc->vkDestroyFramebuffer (device->dev, + octx->framebuffers[i], 0); + } + octx->framebuffers = 0; Vulkan_CreateSwapchain (ctx); + sc = ctx->swapchain; Vulkan_CreateCapture (ctx); __auto_type out = ctx->output_renderpass; @@ -274,22 +283,48 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) out->viewport.width = out->output.extent.width; out->viewport.height = out->output.extent.height; out->scissor.extent = out->output.extent; - auto step = QFV_GetStep (params[0], ctx->render_context->job); - auto render = step->render; - for (uint32_t i = 0; i < render->num_renderpasses; i++) { - auto rp = &render->renderpasses[i]; - if (rp->beginInfo.framebuffer) { - dfunc->vkDestroyFramebuffer (device->dev, - rp->beginInfo.framebuffer, 0); - } - rp->beginInfo.framebuffer = 0; // leave for update_framebuffer - } dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore, 0); frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_SEMAPHORE, + frame->imageAvailableSemaphore, + va (ctx->va_ctx, "sc image:%d", ctx->curFrame)); + } + + //FIXME clean this up + auto step = QFV_GetStep (params[0], ctx->render_context->job); + auto render = step->render; + auto rp = &render->renderpasses[0]; + if (!octx->framebuffers) { + uint32_t count = ctx->swapchain->imageViews->size; + octx->framebuffers = malloc (sizeof (VkFramebuffer [count])); + for (uint32_t i = 0; i < count; i++) { + rp->beginInfo.framebuffer = 0; + //FIXME come up with a better mechanism + ctx->swapImageIndex = i; + QFV_CreateFramebuffer (ctx, rp); + octx->framebuffers[i] = rp->beginInfo.framebuffer; + QFV_duSetObjectName (device, VK_OBJECT_TYPE_FRAMEBUFFER, + octx->framebuffers[i], + va (ctx->va_ctx, "sc fb:%d", i)); + } + for (uint32_t i = 0; i < rp->subpass_count; i++) { + auto sp = &rp->subpasses[i]; + for (uint32_t j = 0; j < sp->pipeline_count; j++) { + auto pl = &sp->pipelines[j]; + pl->viewport.width = sc->extent.width; + pl->viewport.height = sc->extent.height; + pl->scissor.extent = sc->extent; + } + } } ctx->swapImageIndex = imageIndex; + rp->beginInfo.framebuffer = octx->framebuffers[imageIndex]; + for (uint32_t i = 0; i < rp->subpass_count; i++) { + auto sp = &rp->subpasses[i]; + sp->inherit.framebuffer = rp->beginInfo.framebuffer; + } } static void diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a28c0f2f4..43a74f918 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -236,6 +236,9 @@ Vulkan_CreateFrames (vulkan_ctx_t *ctx) __auto_type frame = &ctx->frames.a[i]; frame->fence = QFV_CreateFence (device, 1); frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_SEMAPHORE, + frame->imageAvailableSemaphore, + va (ctx->va_ctx, "sc image:%zd", i)); frame->renderDoneSemaphore = QFV_CreateSemaphore (device); frame->cmdBuffer = cmdBuffers->a[i]; } From 3de39f54088aa745ed6ee616c8e36a76b1d9cafb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Jun 2023 17:58:15 +0900 Subject: [PATCH 3624/3664] [vulkan] Destroy frame buffers on shutdown With this, the new render system, though not doing anything useful, at least passes validation. --- include/QF/Vulkan/render.h | 1 + libs/video/renderer/vulkan/render.c | 51 +++++++++++----------- libs/video/renderer/vulkan/vulkan_output.c | 9 ++++ 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 66114798f..c8c843988 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -384,6 +384,7 @@ void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys); void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp); qfv_step_t *QFV_GetStep (const exprval_t *param, qfv_job_t *job); +qfv_step_t *QFV_FindStep (const char *step, qfv_job_t *job) __attribute__((pure)); #endif//__QFCC__ #endif//__QF_Vulkan_render_h diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 45ba7a887..9c7e352f1 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -280,24 +280,6 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); } -#if 0 -void -QFV_DestroyFramebuffer (vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - __auto_type rctx = ctx->render_context; - __auto_type job = rctx->job; - __auto_type rp = &job->renderpasses[0]; - - if (rp->beginInfo.framebuffer) { - VkFramebuffer framebuffer = rp->beginInfo.framebuffer; - rp->beginInfo.framebuffer = 0; - dfunc->vkDestroyFramebuffer (device->dev, framebuffer, 0); - } -} -#endif - static VkImageView __attribute__((pure)) find_imageview (qfv_reference_t *ref, qfv_renderctx_t *rctx) { @@ -485,6 +467,18 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) QFV_DestroyResource (ctx->device, job->resources); free (job->resources); } + for (uint32_t i = 0; i < job->num_steps; i++) { + if (job->steps[i].render) { + auto render = job->steps[i].render; + for (uint32_t j = 0; j < render->num_renderpasses; j++) { + auto bi = &render->renderpasses[j].beginInfo; + if (bi->framebuffer) { + dfunc->vkDestroyFramebuffer (device->dev, + bi->framebuffer, 0); + } + } + } + } job->command_pool = 0; DARRAY_CLEAR (&job->commands); free (rctx->job); @@ -525,6 +519,18 @@ QFV_Render_AddTasks (vulkan_ctx_t *ctx, exprsym_t *task_syms) } } +qfv_step_t * +QFV_FindStep (const char *name, qfv_job_t *job) +{ + for (uint32_t i = 0; i < job->num_steps; i++) { + auto step = &job->steps[i]; + if (!strcmp (step->label.name, name)) { + return step; + } + } + return 0; +} + qfv_step_t * QFV_GetStep (const exprval_t *param, qfv_job_t *job) { @@ -540,14 +546,7 @@ QFV_GetStep (const exprval_t *param, qfv_job_t *job) } auto name = *(const char **)stepref->value; stepref->type = &cexpr_voidptr; - *(void **)stepref->value = 0; - for (uint32_t i = 0; i < job->num_steps; i++) { - auto step = &job->steps[i]; - if (!strcmp (step->label.name, name)) { - *(void **)stepref->value = step; - break; - } - } + *(qfv_step_t **)stepref->value = QFV_FindStep (name, job); } return *(qfv_step_t **)stepref->value; } diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 669997740..cc5058d20 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -442,6 +442,15 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; outputctx_t *octx = ctx->output_context; + for (uint32_t i = 0; i < ctx->swapchain->imageViews->size; i++) { + dfunc->vkDestroyFramebuffer (device->dev, octx->framebuffers[i], 0); + } + free (octx->framebuffers); + auto step = QFV_FindStep ("output", ctx->render_context->job); + auto render = step->render; + auto rp = &render->renderpasses[0]; + rp->beginInfo.framebuffer = 0; + dfunc->vkDestroyPipeline (device->dev, octx->output, 0); dfunc->vkDestroyPipeline (device->dev, octx->waterwarp, 0); dfunc->vkDestroyPipeline (device->dev, octx->fisheye, 0); From 6deeed1829467bee6b8925cb0a22e4b7be6e7e05 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 21 Jun 2023 23:31:08 +0900 Subject: [PATCH 3625/3664] [vulkan] Get the output step working for draw It leaks command buffers (due to a misunderstanding of vkResetCommandPool), but it seems 2d draw (sliced quads) is working nicely. --- include/QF/Vulkan/qf_draw.h | 2 - include/QF/Vulkan/qf_matrices.h | 2 - libs/video/renderer/vid_render_vulkan.c | 168 +--------- libs/video/renderer/vulkan/render.c | 12 +- libs/video/renderer/vulkan/rp_main_def.plist | 57 ++++ libs/video/renderer/vulkan/vulkan_draw.c | 336 +++++++++---------- libs/video/renderer/vulkan/vulkan_main.c | 1 - libs/video/renderer/vulkan/vulkan_matrices.c | 26 +- libs/video/renderer/vulkan/vulkan_output.c | 75 +---- 9 files changed, 236 insertions(+), 443 deletions(-) diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index e2b93c6ad..852a012be 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -87,8 +87,6 @@ int Vulkan_Draw_AddFont (struct font_s *font, struct vulkan_ctx_s *ctx); void Vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c, struct vulkan_ctx_s *ctx); -void Vulkan_FlushText (struct qfv_renderframe_s *rFrame); - void Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height, struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index 1eaeed2aa..011a69972 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -84,8 +84,6 @@ void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky); void Vulkan_Matrix_Init (struct vulkan_ctx_s *ctx); void Vulkan_Matrix_Shutdown (struct vulkan_ctx_s *ctx); -// "Draw" :) -void Vulkan_Matrix_Draw (struct qfv_renderframe_s *rFrame); VkDescriptorSet Vulkan_Matrix_Descriptors (struct vulkan_ctx_s *ctx, int frame) __attribute__((pure)); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index e403394fa..88f46c0a4 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -307,34 +307,6 @@ vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c) { Vulkan_Draw_Glyph (x, y, fontid, glyphid, c, vulkan_ctx); } -//#define TEST_RENDER -#ifndef TEST_RENDER -static void -vulkan_begin_frame (void) -{ - qfv_device_t *device = vulkan_ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - VkDevice dev = device->dev; - - __auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame]; - - dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); -} - -static void -vulkan_render_view (void) -{ - for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { - __auto_type rp = vulkan_ctx->renderPasses.a[i]; - __auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame]; - // swapImageIndex may be updated by a render pass - uint32_t imageIndex = vulkan_ctx->swapImageIndex; - if (rp->framebuffers) { - rpFrame->framebuffer = rp->framebuffers->a[imageIndex]; - } - rp->draw (rpFrame); - } -} static void vulkan_set_2d (int scaled) @@ -353,153 +325,15 @@ vulkan_set_2d (int scaled) mctx->dirty = mctx->frames.size; } -static void -vulkan_end_frame (void) -{ - qfv_device_t *device = vulkan_ctx->device; - VkDevice dev = device->dev; - qfv_devfuncs_t *dfunc = device->funcs; - qfv_queue_t *queue = &device->queue; - uint32_t curFrame = vulkan_ctx->curFrame; - __auto_type frame = &vulkan_ctx->frames.a[curFrame]; - uint32_t imageIndex = vulkan_ctx->swapImageIndex; - - VkCommandBufferBeginInfo beginInfo - = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; - - __auto_type cmdBufs = (qfv_cmdbufferset_t) DARRAY_STATIC_INIT (4); - DARRAY_APPEND (&cmdBufs, frame->cmdBuffer); - - dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); - for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) { - __auto_type rp = vulkan_ctx->renderPasses.a[i]; - __auto_type rpFrame = &rp->frames.a[curFrame]; - - if (rp->primary_commands) { - for (int j = 0; j < rpFrame->subpassCount; j++) { - __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; - size_t base = cmdBufs.size; - DARRAY_RESIZE (&cmdBufs, base + cmdSet->size); - memcpy (&cmdBufs.a[base], cmdSet->a, - cmdSet->size * sizeof (VkCommandBuffer)); - } - continue; - } - - QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color); - if (rpFrame->renderpass && rp->renderpass) { - VkRenderPassBeginInfo renderPassInfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = rp->renderpass, - .framebuffer = rp->framebuffers->a[imageIndex], - .renderArea = rp->renderArea, - .clearValueCount = rp->clearValues->size, - .pClearValues = rp->clearValues->a, - }; - - dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, - rpFrame->subpassContents); - - for (int j = 0; j < rpFrame->subpassCount; j++) { - __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; - if (cmdSet->size) { - QFV_CmdBeginLabel (device, frame->cmdBuffer, - rpFrame->subpassInfo[j].name, - rpFrame->subpassInfo[j].color); - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, - cmdSet->size, cmdSet->a); - QFV_CmdEndLabel (device, frame->cmdBuffer); - } - // reset for next time around - cmdSet->size = 0; - - //Regardless of whether any commands were submitted for this - //subpass, must step through each and every subpass, otherwise - //the attachments won't be transitioned correctly. - if (j < rpFrame->subpassCount - 1) { - dfunc->vkCmdNextSubpass (frame->cmdBuffer, - rpFrame->subpassContents); - } - } - dfunc->vkCmdEndRenderPass (frame->cmdBuffer); - } else { - for (int j = 0; j < rpFrame->subpassCount; j++) { - __auto_type cmdSet = &rpFrame->subpassCmdSets[j]; - if (cmdSet->size) { - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, - cmdSet->size, cmdSet->a); - } - // reset for next time around - cmdSet->size = 0; - } - } - QFV_CmdEndLabel (device, frame->cmdBuffer); - } - - if (vulkan_ctx->capture_callback) { - VkImage srcImage = vulkan_ctx->swapchain->images->a[imageIndex]; - VkCommandBuffer cmd = QFV_CaptureImage (vulkan_ctx->capture, srcImage, - curFrame); - dfunc->vkCmdExecuteCommands (frame->cmdBuffer, 1, &cmd); - } - dfunc->vkEndCommandBuffer (frame->cmdBuffer); - - VkPipelineStageFlags waitStage - = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - VkSubmitInfo submitInfo = { - VK_STRUCTURE_TYPE_SUBMIT_INFO, 0, - 1, &frame->imageAvailableSemaphore, &waitStage, - cmdBufs.size, cmdBufs.a, - 1, &frame->renderDoneSemaphore, - }; - dfunc->vkResetFences (dev, 1, &frame->fence); - dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); - - DARRAY_CLEAR (&cmdBufs); - - if (vulkan_ctx->capture_callback) { - //FIXME look into "threading" this rather than waiting here - dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE, - 1000000000ull); - vulkan_ctx->capture_callback (QFV_CaptureData (vulkan_ctx->capture, - curFrame), - vulkan_ctx->capture->extent.width, - vulkan_ctx->capture->extent.height); - vulkan_ctx->capture_callback = 0; - } - - VkPresentInfoKHR presentInfo = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0, - 1, &frame->renderDoneSemaphore, - 1, &vulkan_ctx->swapchain->swapchain, &imageIndex, - 0 - }; - dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); - - vulkan_ctx->curFrame++; - vulkan_ctx->curFrame %= vulkan_ctx->frames.size; -} -#endif static void vulkan_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) { -#ifdef TEST_RENDER + vulkan_set_2d (1);//FIXME while (*scr_funcs) { (*scr_funcs) (); scr_funcs++; } QFV_RunRenderJob (vulkan_ctx); -#else - EntQueue_Clear (r_ent_queue); - vulkan_begin_frame (); - vulkan_set_2d (1); - while (*scr_funcs) { - (*scr_funcs) (); - scr_funcs++; - } - vulkan_render_view (); - vulkan_end_frame (); -#endif } static void diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 9c7e352f1..82015188b 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -137,7 +137,7 @@ run_subpass (qfv_subpass_t *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx) static void run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) { - printf ("%10.2f run_renderpass: %s\n", Sys_DoubleTime (), rp->label.name); + //printf ("%10.2f run_renderpass: %s\n", Sys_DoubleTime (), rp->label.name); qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -177,7 +177,7 @@ static void run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) { - printf ("run_compute_pipeline: %s\n", pipeline->label.name); + //printf ("run_compute_pipeline: %s\n", pipeline->label.name); qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -242,7 +242,7 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) for (uint32_t i = 0; i < job->num_steps; i++) { __auto_type step = &job->steps[i]; - printf ("%10.2f run_step: %s\n", Sys_DoubleTime (), step->label.name); + //printf ("%10.2f run_step: %s\n", Sys_DoubleTime (), step->label.name); if (step->render) { run_renderpass (step->render->active, ctx); } @@ -266,8 +266,8 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) job->commands.size, job->commands.a, 1, &frame->renderDoneSemaphore, }; - printf ("%10.2f submit for frame %d: %zd %p\n", Sys_DoubleTime (), - ctx->curFrame, job->commands.size, frame->imageAvailableSemaphore); + //printf ("%10.2f submit for frame %d: %zd %p\n", Sys_DoubleTime (), + // ctx->curFrame, job->commands.size, frame->imageAvailableSemaphore); dfunc->vkResetFences (device->dev, 1, &frame->fence); dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); @@ -361,7 +361,7 @@ wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto job = ctx->render_context->job; job->command_pool = frame->command_pool; dfunc->vkResetCommandPool (device->dev, job->command_pool, 0); - DARRAY_CLEAR (&job->commands); + DARRAY_RESIZE (&job->commands, 0); } static void diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index abe043d97..e9ed4edf6 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -11,6 +11,7 @@ properties = { output = "[0.0, 0.7, 0.7, 1]"; waterwarp = "[0.0, 0.7, 0.7, 1]"; fisheye = "[0.0, 0.7, 0.7, 1]"; + slice = "[0.8, 0.7, 0.2, 1]"; }; color_dependency = { src = { @@ -549,6 +550,42 @@ properties = { }; }; }; + slice = { + shader = { + vertex = { + stage = vertex; + name = main; + module = $builtin/slice.vert; + }; + fragment = { + stage = fragment; + name = main; + module = $builtin/twod.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = "4 + 4 + 4*4"; inputRate = instance; }, + ); + attributes = ( + // 9-slice index + { location = 0; binding = 0; format = r32_uint; offset = 0; }, + // 9-slice color + { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, + // 9-slice position (2d) + { location = 2; binding = 0; format = r32g32_sfloat; offset = 8; }, + // 9-slice size delta (2d) + { location = 3; binding = 0; format = r32g32_sfloat; offset = 16; }, + ); + }; + inputAssembly = { + topology = triangle_strip; + primitiveRestartEnable = true; + }; + layout = { + descriptorSets = (matrix_set, quad_data_set); + }; + }; }; descriptorSetLayouts = { matrix_set = { @@ -1271,6 +1308,22 @@ renderpasses = { ); layout = $output.layout; }; + slice = { + @inherit = $compose_base; + + color = $color.slice; + tasks = ( + { func = slice_draw; }, + ); + + stages = ( + $slice.shader.vertex, + $slice.shader.fragment, + ); + vertexInput = $slice.vertexInput; + inputAssembly = $slice.inputAssembly; + layout = $slice.layout; + }; }; }; }; @@ -1281,9 +1334,11 @@ steps = { process = { tasks = ( { func = wait_on_fence; }, + { func = update_matrices; }, ); }; }; +/* particles = { dependencies = (wait_on_fence); compute = { @@ -1342,6 +1397,7 @@ steps = { }; }; }; +*/ preoutput = { dependencies = (wait_on_fence); process = { @@ -1349,6 +1405,7 @@ steps = { { func = acquire_output; params = ("\"output\""); }, { func = update_input; }, + { func = flush_draw; }, ); }; }; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 6915e4f7e..7539e9518 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -72,14 +72,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -static const char * __attribute__((used)) draw_pass_names[] = { - "2d", -}; - -static QFV_Subpass subpass_map[] = { - [QFV_draw2d] = 0, -}; - typedef struct pic_data_s { uint32_t vert_index; uint32_t slice_index; @@ -875,9 +867,161 @@ load_white_pic (vulkan_ctx_t *ctx) dctx->white_pic, ctx); } +static void +draw_quads (vulkan_ctx_t *ctx, VkCommandBuffer cmd) +{ + auto device = ctx->device; + auto dfunc = device->funcs; + auto dctx = ctx->draw_context; + auto dframe = &dctx->frames.a[ctx->curFrame]; + + VkBuffer instance_buffer = dframe->instance_buffer; + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &instance_buffer, offsets); + + VkBuffer ind_buffer = dctx->index_object[0].buffer.buffer; + dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); + + uint32_t inst_start = 0; + for (size_t i = 0; i < dframe->quad_batch.size; i++) { + int fontid = dframe->quad_batch.a[i].descid; + uint32_t inst_count = dframe->quad_batch.a[i].count; + uint32_t ind_count = inst_count >> 24; + inst_count &= 0xffffff; + VkDescriptorSet set[2] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + fontid < 0 ? dframe->dyn_descs.sets[~fontid] + : dctx->fonts.a[fontid].set, + }; + VkPipelineLayout layout = dctx->quad_layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + + dfunc->vkCmdDrawIndexed (cmd, ind_count, inst_count, 0, 0, inst_start); + inst_start += inst_count; + } + DARRAY_RESIZE (&dframe->quad_batch, 0); +} + +static void +draw_lines (vulkan_ctx_t *ctx, VkCommandBuffer cmd) +{ + auto device = ctx->device; + auto dfunc = device->funcs; + auto dctx = ctx->draw_context; + auto dframe = &dctx->frames.a[ctx->curFrame]; + + VkBuffer line_buffer = dframe->line_buffer; + VkDeviceSize offsets[] = {0}; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &line_buffer, offsets); + VkDescriptorSet set[1] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + }; + VkPipelineLayout layout = dctx->lines_layout; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 1, set, 0, 0); + dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE, + 1, 0, 0); +} + +static void +flush_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + flush_draw_scrap (ctx); +} + +static void +slice_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto dctx = ctx->draw_context; + auto dframe = &dctx->frames.a[ctx->curFrame]; + if (!dframe->quad_insts.count) { + return; + } + + VkDeviceMemory memory = dctx->draw_resource[1].memory; + size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; + size_t atom_mask = atom - 1; +#define a(x) (((x) + atom_mask) & ~atom_mask) + VkMappedMemoryRange ranges[] = { + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + memory, dframe->instance_offset, + a(dframe->quad_insts.count * BYTES_PER_QUAD) }, + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + memory, dframe->dvert_offset, + a(dframe->dvertex_index * sizeof (quadvert_t)) }, + }; +#undef a + dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); + + draw_quads (ctx, taskctx->cmd); + + dframe->quad_insts.count = 0; + dframe->dvertex_index = 0; + dframe->dyn_descs.in_use = 0; +} + +static void +line_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto dctx = ctx->draw_context; + auto dframe = &dctx->frames.a[ctx->curFrame]; + + if (!dframe->line_verts.count) { + return; + } + + VkDeviceMemory memory = dctx->draw_resource[1].memory; + size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; + size_t atom_mask = atom - 1; +#define a(x) (((x) + atom_mask) & ~atom_mask) + VkMappedMemoryRange ranges[] = { + { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + memory, dframe->line_offset, + a(dframe->line_verts.count * BYTES_PER_LINE) }, + }; +#undef a + dfunc->vkFlushMappedMemoryRanges (device->dev, 1, ranges); + + draw_lines (ctx, taskctx->cmd); + + dframe->line_verts.count = 0; +} + +static exprfunc_t flush_draw_func[] = { + { .func = flush_draw }, + {} +}; +static exprfunc_t slice_draw_func[] = { + { .func = slice_draw }, + {} +}; +static exprfunc_t line_draw_func[] = { + { .func = line_draw }, + {} +}; +static exprsym_t draw_task_syms[] = { + { "flush_draw", &cexpr_function, flush_draw_func }, + { "slice_draw", &cexpr_function, slice_draw_func }, + { "line_draw", &cexpr_function, line_draw_func }, + {} +}; + void Vulkan_Draw_Init (vulkan_ctx_t *ctx) { + QFV_Render_AddTasks (ctx, draw_task_syms); + qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -973,15 +1117,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&dframe->cmdSet, QFV_drawNumPasses); DARRAY_RESIZE (&dframe->cmdSet, QFV_drawNumPasses); dframe->cmdSet.grow = 0; - - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &dframe->cmdSet); - - for (int j = 0; j < QFV_drawNumPasses; j++) { - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - dframe->cmdSet.a[j], - va (ctx->va_ctx, "cmd:draw:%zd:%s", i, - draw_pass_names[j])); - } } qfvPopDebug (ctx); } @@ -1412,173 +1547,6 @@ Vulkan_Draw_FadeScreen (vulkan_ctx_t *ctx) draw_blendscreen (color, ctx); } -static void -draw_begin_subpass (QFV_DrawSubpass subpass, qfv_renderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - drawctx_t *dctx = ctx->draw_context; - drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = dframe->cmdSet.a[subpass]; - - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - rFrame->renderpass->renderpass, subpass_map[subpass], - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "draw:%s", - draw_pass_names[subpass]), - {0.5, 0.8, 0.1, 1}); -} - -static void -draw_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); -} - -static void -bind_pipeline (qfv_renderframe_t *rFrame, VkPipeline pipeline, - VkCommandBuffer cmd) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); -} - -static void -draw_quads (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - drawctx_t *dctx = ctx->draw_context; - drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - - VkBuffer instance_buffer = dframe->instance_buffer; - VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &instance_buffer, offsets); - - VkBuffer ind_buffer = dctx->index_object[0].buffer.buffer; - dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32); - - uint32_t inst_start = 0; - for (size_t i = 0; i < dframe->quad_batch.size; i++) { - int fontid = dframe->quad_batch.a[i].descid; - uint32_t inst_count = dframe->quad_batch.a[i].count; - uint32_t ind_count = inst_count >> 24; - inst_count &= 0xffffff; - VkDescriptorSet set[2] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - fontid < 0 ? dframe->dyn_descs.sets[~fontid] - : dctx->fonts.a[fontid].set, - }; - VkPipelineLayout layout = dctx->quad_layout; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); - - dfunc->vkCmdDrawIndexed (cmd, ind_count, inst_count, 0, 0, inst_start); - inst_start += inst_count; - } - DARRAY_RESIZE (&dframe->quad_batch, 0); -} - -static void -draw_lines (qfv_renderframe_t *rFrame, VkCommandBuffer cmd) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - drawctx_t *dctx = ctx->draw_context; - drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - - VkBuffer line_buffer = dframe->line_buffer; - VkDeviceSize offsets[] = {0}; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &line_buffer, offsets); - VkDescriptorSet set[1] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - }; - VkPipelineLayout layout = dctx->lines_layout; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 1, set, 0, 0); - dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE, - 1, 0, 0); -} - -void -Vulkan_FlushText (qfv_renderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - flush_draw_scrap (ctx); - - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - drawctx_t *dctx = ctx->draw_context; - drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; - - if (!dframe->quad_insts.count && !dframe->line_verts.count) { - return; - } - - VkDeviceMemory memory = dctx->draw_resource[1].memory; - size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; - size_t atom_mask = atom - 1; -#define a(x) (((x) + atom_mask) & ~atom_mask) - VkMappedMemoryRange ranges[] = { - { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - memory, dframe->instance_offset, - a(dframe->quad_insts.count * BYTES_PER_QUAD) }, - { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - memory, dframe->dvert_offset, - a(dframe->dvertex_index * sizeof (quadvert_t)) }, - { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - memory, dframe->line_offset, - a(dframe->line_verts.count * BYTES_PER_LINE) }, - }; -#undef a - dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); - - DARRAY_APPEND (&rFrame->subpassCmdSets[subpass_map[QFV_draw2d]], - dframe->cmdSet.a[QFV_draw2d]); - - draw_begin_subpass (QFV_draw2d, rFrame); - - if (dframe->quad_insts.count) { - bind_pipeline (rFrame, dctx->quad_pipeline, - dframe->cmdSet.a[QFV_draw2d]); - draw_quads (rFrame, dframe->cmdSet.a[QFV_draw2d]); - } - if (dframe->line_verts.count) { - bind_pipeline (rFrame, dctx->line_pipeline, - dframe->cmdSet.a[QFV_draw2d]); - draw_lines (rFrame, dframe->cmdSet.a[QFV_draw2d]); - } - - draw_end_subpass (dframe->cmdSet.a[QFV_draw2d], ctx); - - dframe->quad_insts.count = 0; - dframe->line_verts.count = 0; - dframe->dvertex_index = 0; - dframe->dyn_descs.in_use = 0; -} - void Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx) { diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 06880ef02..a4dbd0bfa 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -167,7 +167,6 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) static void main_draw (qfv_renderframe_t *rFrame) { - Vulkan_Matrix_Draw (rFrame); Vulkan_RenderView (rFrame); Vulkan_Lighting_Draw (rFrame); Vulkan_Compose_Draw (rFrame); diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 76d424711..3fb0daf1e 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -174,15 +174,15 @@ Vulkan_SetSkyMatrix (vulkan_ctx_t *ctx, mat4f_t sky) } } -void -Vulkan_Matrix_Draw (qfv_renderframe_t *rFrame) +static void +update_matrices (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - __auto_type mctx = ctx->matrix_context; - __auto_type mframe = &mctx->frames.a[ctx->curFrame]; + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto mctx = ctx->matrix_context; + auto mframe = &mctx->frames.a[ctx->curFrame]; setup_view (ctx); setup_sky (ctx); @@ -218,9 +218,19 @@ Vulkan_Matrix_Draw (qfv_renderframe_t *rFrame) QFV_PacketSubmit (packet); } +static exprfunc_t update_matrices_func[] = { + { .func = update_matrices }, + {} +}; +static exprsym_t matrix_task_syms[] = { + { "update_matrices", &cexpr_function, update_matrices_func }, + {} +}; + void Vulkan_Matrix_Init (vulkan_ctx_t *ctx) { + QFV_Render_AddTasks (ctx, matrix_task_syms); qfvPushDebug (ctx, "matrix init"); qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index cc5058d20..b84533b98 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -62,85 +62,15 @@ #include "vid_vulkan.h" #include "vkparse.h"//FIXME -static void -acquire_image (qfv_renderframe_t *rFrame) -{ - auto ctx = rFrame->vulkan_ctx; - auto device = ctx->device; - auto dfunc = device->funcs; - auto frame = &ctx->frames.a[ctx->curFrame]; - - uint32_t imageIndex = 0; - while (!QFV_AcquireNextImage (ctx->swapchain, - frame->imageAvailableSemaphore, - 0, &imageIndex)) { - QFV_DeviceWaitIdle (device); - if (ctx->capture) { - QFV_DestroyCapture (ctx->capture); - } - Vulkan_CreateSwapchain (ctx); - Vulkan_CreateCapture (ctx); - - __auto_type out = ctx->output_renderpass; - out->output = (qfv_output_t) { - .extent = ctx->swapchain->extent, - .format = ctx->swapchain->format, - .frames = ctx->swapchain->numImages, - .view_list = ctx->swapchain->imageViews->a, - }; - out->viewport.width = out->output.extent.width; - out->viewport.height = out->output.extent.height; - out->scissor.extent = out->output.extent; - QFV_RenderPass_CreateFramebuffer (out); - - dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore, - 0); - frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_SEMAPHORE, - frame->imageAvailableSemaphore, - va (ctx->va_ctx, "sc image:%d", ctx->curFrame)); - } - ctx->swapImageIndex = imageIndex; -} - -static void -output_update_input (qfv_renderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - outputctx_t *octx = ctx->output_context; - uint32_t curFrame = ctx->curFrame; - outputframe_t *oframe = &octx->frames.a[curFrame]; - - if (oframe->input == octx->input) { - return; - } - oframe->input = octx->input; - - VkDescriptorImageInfo imageInfo = { - octx->sampler, oframe->input, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }; - VkWriteDescriptorSet write[] = { - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - oframe->set, 0, 0, 1, - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - &imageInfo, 0, 0 } - }; - dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); -} - static void preoutput_draw (qfv_renderframe_t *rFrame) { - acquire_image (rFrame); - output_update_input (rFrame); } static void process_input (qfv_renderframe_t *rFrame) { + return; vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -216,7 +146,6 @@ static void draw_output (qfv_renderframe_t *rFrame) { process_input (rFrame); - Vulkan_FlushText (rFrame); } void @@ -256,7 +185,6 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto octx = ctx->output_context; auto sc = ctx->swapchain; - printf ("acquire_output: %d\n", ctx->curFrame); uint32_t imageIndex = 0; while (!QFV_AcquireNextImage (sc, frame->imageAvailableSemaphore, 0, &imageIndex)) { @@ -309,6 +237,7 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) octx->framebuffers[i], va (ctx->va_ctx, "sc fb:%d", i)); } + rp->beginInfo.renderArea.extent = sc->extent; for (uint32_t i = 0; i < rp->subpass_count; i++) { auto sp = &rp->subpasses[i]; for (uint32_t j = 0; j < sp->pipeline_count; j++) { From bba82d3da1e5e3de1b2123870630ef162e7cfc1b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jun 2023 16:44:05 +0900 Subject: [PATCH 3626/3664] [vulkan] Move frames from vulkan_ctx to renderctx Part of the command buffer fix, but also a step towards cleaning up vulkan_ctx. --- include/QF/Vulkan/qf_alias.h | 10 ++-- include/QF/Vulkan/qf_bsp.h | 8 +-- include/QF/Vulkan/qf_compose.h | 4 +- include/QF/Vulkan/qf_iqm.h | 8 +-- include/QF/Vulkan/qf_lighting.h | 4 +- include/QF/Vulkan/qf_main.h | 6 +-- include/QF/Vulkan/qf_particles.h | 4 +- include/QF/Vulkan/qf_renderpass.h | 12 ++--- include/QF/Vulkan/qf_sprite.h | 8 +-- include/QF/Vulkan/qf_translucent.h | 4 +- include/QF/Vulkan/qf_vid.h | 2 - include/QF/Vulkan/render.h | 11 ++++ include/vid_vulkan.h | 12 ----- libs/video/renderer/vid_render_vulkan.c | 1 - libs/video/renderer/vulkan/render.c | 41 +++++++++++++-- libs/video/renderer/vulkan/render_load.c | 11 ---- libs/video/renderer/vulkan/vkparse.c | 21 ++++---- libs/video/renderer/vulkan/vulkan_alias.c | 15 +++--- libs/video/renderer/vulkan/vulkan_bsp.c | 17 +++--- libs/video/renderer/vulkan/vulkan_compose.c | 5 +- libs/video/renderer/vulkan/vulkan_draw.c | 6 ++- libs/video/renderer/vulkan/vulkan_iqm.c | 13 ++--- libs/video/renderer/vulkan/vulkan_lighting.c | 7 +-- libs/video/renderer/vulkan/vulkan_main.c | 6 +-- libs/video/renderer/vulkan/vulkan_matrices.c | 3 +- libs/video/renderer/vulkan/vulkan_output.c | 12 +++-- libs/video/renderer/vulkan/vulkan_particles.c | 14 ++--- .../video/renderer/vulkan/vulkan_renderpass.c | 4 +- libs/video/renderer/vulkan/vulkan_scene.c | 4 +- libs/video/renderer/vulkan/vulkan_sprite.c | 13 ++--- .../renderer/vulkan/vulkan_translucent.c | 7 +-- .../video/renderer/vulkan/vulkan_vid_common.c | 52 ++----------------- 32 files changed, 166 insertions(+), 179 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 5c64d00b8..c1326e82a 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -89,7 +89,7 @@ typedef struct aliasctx_s { } aliasctx_t; struct vulkan_ctx_s; -struct qfv_renderframe_s; +struct qfv_orenderframe_s; struct entity_s; struct mod_alias_ctx_s; @@ -106,13 +106,13 @@ void Vulkan_Mod_MakeAliasModelDisplayLists (struct mod_alias_ctx_s *alias_ctx, void Vulkan_AliasAddSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); void Vulkan_AliasRemoveSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); -void Vulkan_AliasBegin (struct qfv_renderframe_s *rFrame); -void Vulkan_DrawAlias (struct entity_s ent, struct qfv_renderframe_s *rFrame); -void Vulkan_AliasEnd (struct qfv_renderframe_s *rFrame); +void Vulkan_AliasBegin (struct qfv_orenderframe_s *rFrame); +void Vulkan_DrawAlias (struct entity_s ent, struct qfv_orenderframe_s *rFrame); +void Vulkan_AliasEnd (struct qfv_orenderframe_s *rFrame); void Vulkan_Alias_Init (struct vulkan_ctx_s *ctx); void Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_AliasDepthRange (struct qfv_renderframe_s *rFrame, float n, float f); +void Vulkan_AliasDepthRange (struct qfv_orenderframe_s *rFrame, float n, float f); #endif//__QF_Vulkan_qf_alias_h diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 2e9441711..3e18774a6 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -386,10 +386,10 @@ typedef struct bspctx_s { } bspctx_t; struct vulkan_ctx_s; -struct qfv_renderframe_s; -void Vulkan_DrawWorld (struct qfv_renderframe_s *rFrame); -void Vulkan_DrawSky (struct qfv_renderframe_s *rFrame); -void Vulkan_DrawWaterSurfaces (struct qfv_renderframe_s *rFrame); +struct qfv_orenderframe_s; +void Vulkan_DrawWorld (struct qfv_orenderframe_s *rFrame); +void Vulkan_DrawSky (struct qfv_orenderframe_s *rFrame); +void Vulkan_DrawWaterSurfaces (struct qfv_orenderframe_s *rFrame); void Vulkan_Bsp_Flush (struct vulkan_ctx_s *ctx); void Vulkan_LoadSkys (const char *sky, struct vulkan_ctx_s *ctx); void Vulkan_RegisterTextures (model_t **models, int num_models, diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h index 001ee3e5c..9b40c14d0 100644 --- a/include/QF/Vulkan/qf_compose.h +++ b/include/QF/Vulkan/qf_compose.h @@ -54,10 +54,10 @@ typedef struct composectx_s { } composectx_t; struct vulkan_ctx_s; -struct qfv_renderframe_s; +struct qfv_orenderframe_s; void Vulkan_Compose_Init (struct vulkan_ctx_s *ctx); void Vulkan_Compose_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Compose_Draw (struct qfv_renderframe_s *rFrame); +void Vulkan_Compose_Draw (struct qfv_orenderframe_s *rFrame); #endif//__QF_Vulkan_qf_compose_h diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h index 2dde7cfb4..43c04302b 100644 --- a/include/QF/Vulkan/qf_iqm.h +++ b/include/QF/Vulkan/qf_iqm.h @@ -98,7 +98,7 @@ typedef struct iqmctx_s { } iqmctx_t; struct vulkan_ctx_s; -struct qfv_renderframe_s; +struct qfv_orenderframe_s; struct entity_s; struct mod_iqm_ctx_s; struct iqm_s; @@ -111,9 +111,9 @@ void Vulkan_IQMRemoveBones (struct vulkan_ctx_s *ctx, struct iqm_s *iqm); void Vulkan_IQMAddSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); void Vulkan_IQMRemoveSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); -void Vulkan_IQMBegin (struct qfv_renderframe_s *rFrame); -void Vulkan_DrawIQM (struct entity_s ent, struct qfv_renderframe_s *rFrame); -void Vulkan_IQMEnd (struct qfv_renderframe_s *rFrame); +void Vulkan_IQMBegin (struct qfv_orenderframe_s *rFrame); +void Vulkan_DrawIQM (struct entity_s ent, struct qfv_orenderframe_s *rFrame); +void Vulkan_IQMEnd (struct qfv_orenderframe_s *rFrame); void Vulkan_IQM_Init (struct vulkan_ctx_s *ctx); void Vulkan_IQM_Shutdown (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 2cf7c7e81..703cbb251 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -117,12 +117,12 @@ typedef struct lightingctx_s { } lightingctx_t; struct vulkan_ctx_s; -struct qfv_renderframe_s; +struct qfv_orenderframe_s; void Vulkan_Lighting_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Lighting_Draw (struct qfv_renderframe_s *rFrame); +void Vulkan_Lighting_Draw (struct qfv_orenderframe_s *rFrame); void Vulkan_LoadLights (struct scene_s *scene, struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_lighting_h diff --git a/include/QF/Vulkan/qf_main.h b/include/QF/Vulkan/qf_main.h index b666ce017..ba6659086 100644 --- a/include/QF/Vulkan/qf_main.h +++ b/include/QF/Vulkan/qf_main.h @@ -29,14 +29,14 @@ #define __QF_Vulkan_qf_main_h struct vulkan_ctx_s; -struct qfv_renderframe_s; +struct qfv_orenderframe_s; struct entqueue_s; struct scene_s; void Vulkan_Main_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_NewScene (struct scene_s *scene, struct vulkan_ctx_s *ctx); -void Vulkan_RenderView (struct qfv_renderframe_s *rFrame); +void Vulkan_RenderView (struct qfv_orenderframe_s *rFrame); void Vulkan_RenderEntities (struct entqueue_s *queue, - struct qfv_renderframe_s *rFrame); + struct qfv_orenderframe_s *rFrame); #endif//__QF_Vulkan_qf_main_h diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index a805dfdd8..8cef3fec0 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -74,12 +74,12 @@ typedef struct particlectx_s { struct cvar_s; struct vulkan_ctx_s; -struct qfv_renderframe_s; +struct qfv_orenderframe_s; struct psystem_s *Vulkan_ParticleSystem (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_DrawParticles (struct qfv_renderframe_s *rFrame); +void Vulkan_DrawParticles (struct qfv_orenderframe_s *rFrame); void Vulkan_Particles_CreateRenderPasses (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_particles_h diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h index b07b72d7a..41076d25c 100644 --- a/include/QF/Vulkan/qf_renderpass.h +++ b/include/QF/Vulkan/qf_renderpass.h @@ -25,7 +25,7 @@ typedef struct qfv_osubpass_s { typedef struct qfv_subpassset_s DARRAY_TYPE (qfv_osubpass_t) qfv_subpassset_t; -typedef struct qfv_renderframe_s { +typedef struct qfv_orenderframe_s { struct vulkan_ctx_s *vulkan_ctx; struct qfv_orenderpass_s *renderpass; VkSubpassContents subpassContents; @@ -33,15 +33,15 @@ typedef struct qfv_renderframe_s { int subpassCount; qfv_osubpass_t *subpassInfo; struct qfv_cmdbufferset_s *subpassCmdSets; -} qfv_renderframe_t; +} qfv_orenderframe_t; -typedef struct qfv_renderframeset_s - DARRAY_TYPE (qfv_renderframe_t) qfv_renderframeset_t; +typedef struct qfv_orenderframeset_s + DARRAY_TYPE (qfv_orenderframe_t) qfv_orenderframeset_t; typedef struct clearvalueset_s DARRAY_TYPE (VkClearValue) clearvalueset_t; -typedef void (*qfv_draw_t) (qfv_renderframe_t *rFrame); +typedef void (*qfv_draw_t) (qfv_orenderframe_t *rFrame); typedef struct qfv_orenderpass_s { struct vulkan_ctx_s *vulkan_ctx; @@ -64,7 +64,7 @@ typedef struct qfv_orenderpass_s { int primary_commands; size_t subpassCount; qfv_subpassset_t *subpass_info; - qfv_renderframeset_t frames; + qfv_orenderframeset_t frames; qfv_draw_t draw; } qfv_orenderpass_t; diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index 874cb0e3b..827c26216 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -77,7 +77,7 @@ typedef struct spritectx_s { } spritectx_t; struct vulkan_ctx_s; -struct qfv_renderframe_s; +struct qfv_orenderframe_s; struct entity_s; struct mod_sprite_ctx_s; @@ -88,9 +88,9 @@ void Vulkan_Sprite_DescriptorSet (struct vulkan_ctx_s *ctx, void Vulkan_Mod_SpriteLoadFrames (struct mod_sprite_ctx_s *sprite_ctx, struct vulkan_ctx_s *ctx); -void Vulkan_SpriteBegin (struct qfv_renderframe_s *rFrame); -void Vulkan_DrawSprite (struct entity_s ent, struct qfv_renderframe_s *rFrame); -void Vulkan_SpriteEnd (struct qfv_renderframe_s *rFrame); +void Vulkan_SpriteBegin (struct qfv_orenderframe_s *rFrame); +void Vulkan_DrawSprite (struct entity_s ent, struct qfv_orenderframe_s *rFrame); +void Vulkan_SpriteEnd (struct qfv_orenderframe_s *rFrame); void Vulkan_Sprite_Init (struct vulkan_ctx_s *ctx); void Vulkan_Sprite_Shutdown (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_translucent.h b/include/QF/Vulkan/qf_translucent.h index 1c6f72fed..cd35dc6a0 100644 --- a/include/QF/Vulkan/qf_translucent.h +++ b/include/QF/Vulkan/qf_translucent.h @@ -46,11 +46,11 @@ typedef struct translucentctx_s { } translucentctx_t; struct vulkan_ctx_s; -struct qfv_renderframe_s; +struct qfv_orenderframe_s; void Vulkan_Translucent_Init (struct vulkan_ctx_s *ctx); void Vulkan_Translucent_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Translucent_Draw (struct qfv_renderframe_s *rFrame); +void Vulkan_Translucent_Draw (struct qfv_orenderframe_s *rFrame); VkDescriptorSet Vulkan_Translucent_Descriptors (struct vulkan_ctx_s *ctx, int frame)__attribute__((pure)); void Vulkan_Translucent_CreateBuffers (struct vulkan_ctx_s *ctx, diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 7360bbdab..986bfc3a1 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -69,8 +69,6 @@ enum { }; struct vulkan_ctx_s; -void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx); -void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx); void Vulkan_CreateCapture (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPasses (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index c8c843988..67ead2d9a 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -358,11 +358,22 @@ typedef struct qfv_job_s { VkCommandPool command_pool; } qfv_job_t; +typedef struct qfv_renderframe_s { + VkFence fence; + VkSemaphore imageAvailableSemaphore; + VkSemaphore renderDoneSemaphore; + VkCommandPool command_pool; +} qfv_renderframe_t; + +typedef struct qfv_renderframeset_s + DARRAY_TYPE (qfv_renderframe_t) qfv_renderframeset_t; + typedef struct qfv_renderctx_s { struct hashctx_s *hashctx; exprtab_t task_functions; qfv_jobinfo_t *jobinfo; qfv_job_t *job; + qfv_renderframeset_t frames; } qfv_renderctx_t; typedef struct qfv_taskctx_s { diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index e9e252511..9041ac23d 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -10,17 +10,6 @@ #include "QF/qtypes.h" #include "QF/simd/types.h" -typedef struct vulkan_frame_s { - VkFence fence; - VkSemaphore imageAvailableSemaphore; - VkSemaphore renderDoneSemaphore; - VkCommandBuffer cmdBuffer; - VkCommandPool command_pool; -} vulkan_frame_t; - -typedef struct vulkan_frameset_s - DARRAY_TYPE (vulkan_frame_t) vulkan_frameset_t; - typedef struct qfv_renderpassset_s DARRAY_TYPE (struct qfv_orenderpass_s *) qfv_renderpassset_t; @@ -66,7 +55,6 @@ typedef struct vulkan_ctx_s { VkCommandPool cmdpool; struct qfv_stagebuf_s *staging; uint32_t curFrame; - vulkan_frameset_t frames; qfv_renderpassset_t renderPasses; struct qfv_orenderpass_s *output_renderpass; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 88f46c0a4..8e06409ea 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -94,7 +94,6 @@ vulkan_R_Init (void) QFV_Render_Init (vulkan_ctx); Vulkan_CreateStagingBuffers (vulkan_ctx); - Vulkan_CreateFrames (vulkan_ctx); Vulkan_Texture_Init (vulkan_ctx); Vulkan_Palette_Init (vulkan_ctx, vid.palette); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 82015188b..cbd3cc168 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -257,7 +257,7 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) auto device = ctx->device; auto dfunc = device->funcs; auto queue = &device->queue; - auto frame = &ctx->frames.a[ctx->curFrame]; + auto frame = &rctx->frames.a[ctx->curFrame]; VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submitInfo = { @@ -354,7 +354,8 @@ wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto dfunc = device->funcs; auto dev = device->dev; - __auto_type frame = &ctx->frames.a[ctx->curFrame]; + auto rctx = ctx->render_context; + auto frame = &rctx->frames.a[ctx->curFrame]; dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); @@ -443,6 +444,28 @@ QFV_Render_Init (vulkan_ctx_t *ctx) rctx->task_functions.symbols = 0; QFV_Render_AddTasks (ctx, render_task_syms); + + auto device = ctx->device; + size_t frames = vulkan_frame_count; + DARRAY_INIT (&rctx->frames, frames); + DARRAY_RESIZE (&rctx->frames, frames); + for (size_t i = 0; i < rctx->frames.size; i++) { + auto frame = &rctx->frames.a[i]; + frame->fence = QFV_CreateFence (device, 1); + frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_SEMAPHORE, + frame->imageAvailableSemaphore, + va (ctx->va_ctx, "sc image:%zd", i)); + frame->renderDoneSemaphore = QFV_CreateSemaphore (device); + VkCommandPoolCreateInfo poolCInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + .queueFamilyIndex = device->queue.queueFamily, + }; + auto dfunc = device->funcs; + dfunc->vkCreateCommandPool (device->dev, &poolCInfo, 0, + &frame->command_pool); + } } void @@ -483,10 +506,18 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) DARRAY_CLEAR (&job->commands); free (rctx->job); } - for (uint32_t i = 0; i < ctx->frames.size; i++) { - auto frame = &ctx->frames.a[i]; - dfunc->vkDestroyCommandPool (device->dev, frame->command_pool, 0); + + for (uint32_t i = 0; i < rctx->frames.size; i++) { + auto dev = device->dev; + auto df = dfunc; + auto frame = &rctx->frames.a[i]; + df->vkDestroyFence (dev, frame->fence, 0); + df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0); + df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); + df->vkDestroyCommandPool (dev, frame->command_pool, 0); } + DARRAY_CLEAR (&rctx->frames); + if (rctx->jobinfo) { __auto_type jinfo = rctx->jobinfo; for (uint32_t i = 0; i < jinfo->num_descriptorsetlayouts; i++) { diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 25b1abcfb..79bf1358b 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -1125,17 +1125,6 @@ create_objects (vulkan_ctx_t *ctx, objcount_t *counts) counts->num_descriptorsets = s.inds.num_descriptorsets; init_job (ctx, counts, s); - - for (uint32_t i = 0; i < ctx->frames.size; i++) { - VkCommandPoolCreateInfo poolCInfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - .queueFamilyIndex = device->queue.queueFamily, - }; - auto frame = &ctx->frames.a[i]; - dfunc->vkCreateCommandPool (device->dev, &poolCInfo, 0, - &frame->command_pool); - } } void diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 875796779..5c1b5ab5a 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1187,19 +1187,19 @@ parse_task_params (const plitem_t *item, void **data, #include "libs/video/renderer/vulkan/vkparse.cinc" -static exprsym_t vulkan_frameset_t_symbols[] = { - {"size", &cexpr_size_t, (void *)field_offset (vulkan_frameset_t, size)}, +static exprsym_t qfv_renderframeset_t_symbols[] = { + {"size", &cexpr_size_t, (void *)field_offset (qfv_renderframeset_t, size)}, { } }; -static exprtab_t vulkan_frameset_t_symtab = { - vulkan_frameset_t_symbols, +static exprtab_t qfv_renderframeset_t_symtab = { + qfv_renderframeset_t_symbols, }; -exprtype_t vulkan_frameset_t_type = { +exprtype_t qfv_renderframeset_t_type = { .name = "frameset", - .size = sizeof (vulkan_frameset_t *), + .size = sizeof (qfv_renderframeset_t *), .binops = cexpr_struct_binops, .unops = 0, - .data = &vulkan_frameset_t_symtab, + .data = &qfv_renderframeset_t_symtab, }; static hashtab_t * @@ -1257,9 +1257,10 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, plitem_t *messages = PL_NewArray (); exprctx_t exprctx = { .symtab = &root_symtab }; parsectx_t parsectx = { &exprctx, ctx, properties }; + auto rctx = ctx->render_context; exprsym_t var_syms[] = { {"output", &qfv_output_t_type, &sctx->output}, - {"frames", &vulkan_frameset_t_type, &ctx->frames}, + {"frames", &qfv_renderframeset_t_type, &rctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {"physDevLimits", &VkPhysicalDeviceLimits_type, &ctx->device->physDev->properties->limits }, @@ -2050,7 +2051,7 @@ void Vulkan_Script_Init (vulkan_ctx_t *ctx) ectx.hashctx = 0;//&sctx->hashctx; vkgen_init_symtabs (&ectx); cexpr_init_symtab (&qfv_output_t_symtab, &ectx); - cexpr_init_symtab (&vulkan_frameset_t_symtab, &ectx); + cexpr_init_symtab (&qfv_renderframeset_t_symtab, &ectx); cexpr_init_symtab (&data_array_symtab, &ectx); sctx->shaderModules = handlref_symtab (shaderModule_free, sctx); @@ -2336,7 +2337,7 @@ QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) }; exprsym_t var_syms[] = { {"render_output", &qfv_output_t_type, &sctx->output}, - {"frames", &vulkan_frameset_t_type, &ctx->frames}, + {"frames", &qfv_renderframeset_t_type, &rctx->frames}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {"physDevLimits", &VkPhysicalDeviceLimits_type, &ctx->device->physDev->properties->limits }, diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 77634cfe8..c41461775 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -77,7 +77,7 @@ static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_alias_skin_t *skin, uint32_t numPC, qfv_push_constants_t *constants, - aliashdr_t *hdr, qfv_renderframe_t *rFrame, entity_t ent) + aliashdr_t *hdr, qfv_orenderframe_t *rFrame, entity_t ent) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -117,7 +117,7 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, } void -Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) +Vulkan_DrawAlias (entity_t ent, qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; aliasctx_t *actx = ctx->alias_context; @@ -181,7 +181,7 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame) static void alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, - qfv_renderframe_t *rFrame) + qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -234,7 +234,7 @@ alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) } void -Vulkan_AliasBegin (qfv_renderframe_t *rFrame) +Vulkan_AliasBegin (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; aliasctx_t *actx = ctx->alias_context; @@ -251,7 +251,7 @@ Vulkan_AliasBegin (qfv_renderframe_t *rFrame) } void -Vulkan_AliasEnd (qfv_renderframe_t *rFrame) +Vulkan_AliasEnd (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; aliasctx_t *actx = ctx->alias_context; @@ -262,7 +262,7 @@ Vulkan_AliasEnd (qfv_renderframe_t *rFrame) } void -Vulkan_AliasDepthRange (qfv_renderframe_t *rFrame, +Vulkan_AliasDepthRange (qfv_orenderframe_t *rFrame, float minDepth, float maxDepth) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; @@ -321,7 +321,8 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); ctx->alias_context = actx; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&actx->frames, frames); DARRAY_RESIZE (&actx->frames, frames); actx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 76a782846..ce021a5e0 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -773,7 +773,7 @@ push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout, static void bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, - VkPipelineLayout layout, qfv_renderframe_t *rFrame) + VkPipelineLayout layout, qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -834,7 +834,7 @@ bsp_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) } static void -bsp_begin (qfv_renderframe_t *rFrame) +bsp_begin (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; bspctx_t *bctx = ctx->bsp_context; @@ -864,7 +864,7 @@ bsp_end (vulkan_ctx_t *ctx) } static void -turb_begin (qfv_renderframe_t *rFrame) +turb_begin (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; bspctx_t *bctx = ctx->bsp_context; @@ -889,7 +889,7 @@ turb_end (vulkan_ctx_t *ctx) } static void -sky_begin (qfv_renderframe_t *rFrame) +sky_begin (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; bspctx_t *bctx = ctx->bsp_context; @@ -1025,7 +1025,7 @@ ent_model_cmp (const void *_a, const void *_b) } void -Vulkan_DrawWorld (qfv_renderframe_t *rFrame) +Vulkan_DrawWorld (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -1127,7 +1127,7 @@ Vulkan_Bsp_Flush (vulkan_ctx_t *ctx) } void -Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) +Vulkan_DrawWaterSurfaces (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -1163,7 +1163,7 @@ Vulkan_DrawWaterSurfaces (qfv_renderframe_t *rFrame) } void -Vulkan_DrawSky (qfv_renderframe_t *rFrame) +Vulkan_DrawSky (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -1450,7 +1450,8 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&bctx->main_pass.draw_queues[i], 64); } - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&bctx->frames, frames); DARRAY_RESIZE (&bctx->frames, frames); bctx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 06d9240c3..550baade3 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -58,7 +58,7 @@ #include "vid_vulkan.h" void -Vulkan_Compose_Draw (qfv_renderframe_t *rFrame) +Vulkan_Compose_Draw (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -146,7 +146,8 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) composectx_t *cctx = calloc (1, sizeof (composectx_t)); ctx->compose_context = cctx; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&cctx->frames, frames); DARRAY_RESIZE (&cctx->frames, frames); cctx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 7539e9518..be42640ee 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -285,7 +285,8 @@ create_buffers (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; drawctx_t *dctx = ctx->draw_context; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; dctx->draw_resource = malloc (2 * sizeof (qfv_resource_t) // index buffer @@ -1030,7 +1031,8 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) drawctx_t *dctx = calloc (1, sizeof (drawctx_t)); ctx->draw_context = dctx; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&dctx->frames, frames); DARRAY_RESIZE (&dctx->frames, frames); dctx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 42f1486ea..92e3fd2e7 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -78,7 +78,7 @@ static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_iqm_skin_t *skins, uint32_t numPC, qfv_push_constants_t *constants, - iqm_t *iqm, qfv_renderframe_t *rFrame, entity_t ent) + iqm_t *iqm, qfv_orenderframe_t *rFrame, entity_t ent) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -127,7 +127,7 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, #define a(x) ((x) & ~0x3f) void -Vulkan_DrawIQM (entity_t ent, qfv_renderframe_t *rFrame) +Vulkan_DrawIQM (entity_t ent, qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -207,7 +207,7 @@ Vulkan_DrawIQM (entity_t ent, qfv_renderframe_t *rFrame) static void iqm_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, - qfv_renderframe_t *rFrame) + qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -258,7 +258,7 @@ iqm_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) } void -Vulkan_IQMBegin (qfv_renderframe_t *rFrame) +Vulkan_IQMBegin (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; iqmctx_t *ictx = ctx->iqm_context; @@ -275,7 +275,7 @@ Vulkan_IQMBegin (qfv_renderframe_t *rFrame) } void -Vulkan_IQMEnd (qfv_renderframe_t *rFrame) +Vulkan_IQMEnd (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; iqmctx_t *ictx = ctx->iqm_context; @@ -386,7 +386,8 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx) iqmctx_t *ictx = calloc (1, sizeof (iqmctx_t)); ctx->iqm_context = ictx; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&ictx->frames, frames); DARRAY_RESIZE (&ictx->frames, frames); ictx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 90eae7ea7..e736f22ba 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -148,7 +148,7 @@ update_lights (vulkan_ctx_t *ctx) } void -Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) +Vulkan_Lighting_Draw (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -220,7 +220,7 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame) } static void -lighting_draw_maps (qfv_renderframe_t *rFrame) +lighting_draw_maps (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -361,7 +361,8 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) DARRAY_INIT (&lctx->light_images, 16); DARRAY_INIT (&lctx->light_renderers, 16); - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&lctx->frames, frames); DARRAY_RESIZE (&lctx->frames, frames); lctx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index a4dbd0bfa..6ac19052d 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -69,7 +69,7 @@ #include "vid_vulkan.h" void -Vulkan_RenderEntities (entqueue_t *queue, qfv_renderframe_t *rFrame) +Vulkan_RenderEntities (entqueue_t *queue, qfv_orenderframe_t *rFrame) { if (!r_drawentities) return; @@ -123,7 +123,7 @@ Vulkan_DrawViewModel (vulkan_ctx_t *ctx) } void -Vulkan_RenderView (qfv_renderframe_t *rFrame) +Vulkan_RenderView (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; @@ -165,7 +165,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) } static void -main_draw (qfv_renderframe_t *rFrame) +main_draw (qfv_orenderframe_t *rFrame) { Vulkan_RenderView (rFrame); Vulkan_Lighting_Draw (rFrame); diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 3fb0daf1e..48986a299 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -238,7 +238,8 @@ Vulkan_Matrix_Init (vulkan_ctx_t *ctx) matrixctx_t *mctx = calloc (1, sizeof (matrixctx_t)); ctx->matrix_context = mctx; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&mctx->frames, frames); DARRAY_RESIZE (&mctx->frames, frames); mctx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index b84533b98..5581f78ec 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -63,12 +63,12 @@ #include "vkparse.h"//FIXME static void -preoutput_draw (qfv_renderframe_t *rFrame) +preoutput_draw (qfv_orenderframe_t *rFrame) { } static void -process_input (qfv_renderframe_t *rFrame) +process_input (qfv_orenderframe_t *rFrame) { return; vulkan_ctx_t *ctx = rFrame->vulkan_ctx; @@ -143,7 +143,7 @@ process_input (qfv_renderframe_t *rFrame) } static void -draw_output (qfv_renderframe_t *rFrame) +draw_output (qfv_orenderframe_t *rFrame) { process_input (rFrame); } @@ -181,7 +181,8 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto ctx = taskctx->ctx; auto device = ctx->device; auto dfunc = device->funcs; - auto frame = &ctx->frames.a[ctx->curFrame]; + auto rctx = ctx->render_context; + auto frame = &rctx->frames.a[ctx->curFrame]; auto octx = ctx->output_context; auto sc = ctx->swapchain; @@ -321,7 +322,8 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) outputctx_t *octx = ctx->output_context; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&octx->frames, frames); DARRAY_RESIZE (&octx->frames, frames); octx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 8cd78b56f..1a9b26cda 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -72,7 +72,7 @@ static const char * __attribute__((used)) particle_pass_names[] = { }; static void -particle_begin_subpass (VkPipeline pipeline, qfv_renderframe_t *rFrame) +particle_begin_subpass (VkPipeline pipeline, qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -121,7 +121,7 @@ particle_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) } void -Vulkan_DrawParticles (qfv_renderframe_t *rFrame) +Vulkan_DrawParticles (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -187,7 +187,8 @@ create_buffers (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; particlectx_t *pctx = ctx->particle_context; size_t mp = MaxParticles; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; pctx->resources = malloc (sizeof (qfv_resource_t) // states buffer @@ -417,7 +418,8 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) ctx->particle_context = pctx; pctx->psystem = &r_psystem; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&pctx->frames, frames); DARRAY_RESIZE (&pctx->frames, frames); pctx->frames.grow = 0; @@ -481,7 +483,7 @@ Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; particlectx_t *pctx = ctx->particle_context; - size_t frames = ctx->frames.size; + size_t frames = pctx->frames.size; for (size_t i = 0; i < frames; i++) { __auto_type pframe = &pctx->frames.a[i]; @@ -507,7 +509,7 @@ Vulkan_ParticleSystem (vulkan_ctx_t *ctx) } static void -particles_update (qfv_renderframe_t *rFrame) +particles_update (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c index 7fadceb8b..b911b1100 100644 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ b/libs/video/renderer/vulkan/vulkan_renderpass.c @@ -257,7 +257,7 @@ QFV_RenderPass_CreateFramebuffer (qfv_orenderpass_t *renderpass) static void init_renderframe (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp, - qfv_renderframe_t *rFrame) + qfv_orenderframe_t *rFrame) { rFrame->vulkan_ctx = ctx; rFrame->renderpass = rp; @@ -353,7 +353,7 @@ QFV_RenderPass_New (vulkan_ctx_t *ctx, const char *name, qfv_draw_t function) } DARRAY_INIT (&rp->frames, 4); - DARRAY_RESIZE (&rp->frames, ctx->frames.size); + //DARRAY_RESIZE (&rp->frames, ctx->frames.size); for (size_t i = 0; i < rp->frames.size; i++) { init_renderframe (ctx, rp, &rp->frames.a[i]); } diff --git a/libs/video/renderer/vulkan/vulkan_scene.c b/libs/video/renderer/vulkan/vulkan_scene.c index 0fb6cf3a9..80d2976e4 100644 --- a/libs/video/renderer/vulkan/vulkan_scene.c +++ b/libs/video/renderer/vulkan/vulkan_scene.c @@ -44,6 +44,7 @@ #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" #include "r_internal.h" @@ -143,7 +144,8 @@ Vulkan_Scene_Init (vulkan_ctx_t *ctx) ctx->scene_context = sctx; sctx->max_entities = qfv_max_entities; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&sctx->frames, frames); DARRAY_RESIZE (&sctx->frames, frames); sctx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index e33404806..3f11f58e4 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -83,7 +83,7 @@ static QFV_Subpass subpass_map[] = { static void emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, int numPC, qfv_push_constants_t *constants, - qfv_renderframe_t *rFrame, entity_t ent) + qfv_orenderframe_t *rFrame, entity_t ent) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -104,7 +104,7 @@ emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, } void -Vulkan_DrawSprite (entity_t ent, qfv_renderframe_t *rFrame) +Vulkan_DrawSprite (entity_t ent, qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; spritectx_t *sctx = ctx->sprite_context; @@ -142,7 +142,7 @@ Vulkan_DrawSprite (entity_t ent, qfv_renderframe_t *rFrame) static void sprite_begin_subpass (QFV_SpriteSubpass subpass, VkPipeline pipeline, - qfv_renderframe_t *rFrame) + qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; @@ -193,7 +193,7 @@ sprite_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) } void -Vulkan_SpriteBegin (qfv_renderframe_t *rFrame) +Vulkan_SpriteBegin (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; spritectx_t *sctx = ctx->sprite_context; @@ -210,7 +210,7 @@ Vulkan_SpriteBegin (qfv_renderframe_t *rFrame) } void -Vulkan_SpriteEnd (qfv_renderframe_t *rFrame) +Vulkan_SpriteEnd (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; spritectx_t *sctx = ctx->sprite_context; @@ -310,7 +310,8 @@ Vulkan_Sprite_Init (vulkan_ctx_t *ctx) spritectx_t *sctx = calloc (1, sizeof (spritectx_t)); ctx->sprite_context = sctx; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&sctx->frames, frames); DARRAY_RESIZE (&sctx->frames, frames); sctx->frames.grow = 0; diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index f79bfccc6..fc89a3087 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -143,7 +143,8 @@ Vulkan_Translucent_Init (vulkan_ctx_t *ctx) translucentctx_t *tctx = calloc (1, sizeof (translucentctx_t)); ctx->translucent_context = tctx; - size_t frames = ctx->frames.size; + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; DARRAY_INIT (&tctx->frames, frames); DARRAY_RESIZE (&tctx->frames, frames); tctx->frames.grow = 0; @@ -211,7 +212,7 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type tctx = ctx->translucent_context; - size_t frames = ctx->frames.size; + size_t frames = tctx->frames.size; if (tctx->resources) { QFV_DestroyResource (device, tctx->resources); @@ -314,7 +315,7 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) } static void -translucent_clear (qfv_renderframe_t *rFrame) +translucent_clear (qfv_orenderframe_t *rFrame) { vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 43a74f918..a7bef9bae 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -125,9 +125,6 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) if (ctx->capture) { QFV_DestroyCapture (ctx->capture); } - if (ctx->frames.size) { - Vulkan_DestroyFrames (ctx); - } if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } @@ -216,58 +213,15 @@ Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) } } -void -Vulkan_CreateFrames (vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - VkCommandPool cmdpool = ctx->cmdpool; - - if (!ctx->frames.grow) { - DARRAY_INIT (&ctx->frames, 4); - } - - DARRAY_RESIZE (&ctx->frames, vulkan_frame_count); - - __auto_type cmdBuffers = QFV_AllocCommandBufferSet (ctx->frames.size, - alloca); - QFV_AllocateCommandBuffers (device, cmdpool, 0, cmdBuffers); - - for (size_t i = 0; i < ctx->frames.size; i++) { - __auto_type frame = &ctx->frames.a[i]; - frame->fence = QFV_CreateFence (device, 1); - frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_SEMAPHORE, - frame->imageAvailableSemaphore, - va (ctx->va_ctx, "sc image:%zd", i)); - frame->renderDoneSemaphore = QFV_CreateSemaphore (device); - frame->cmdBuffer = cmdBuffers->a[i]; - } -} - void Vulkan_CreateCapture (vulkan_ctx_t *ctx) { - ctx->capture = QFV_CreateCapture (ctx->device, ctx->frames.size, + //FIXME this should be in render + auto rctx = ctx->render_context; + ctx->capture = QFV_CreateCapture (ctx->device, rctx->frames.size, ctx->swapchain, ctx->cmdpool); } -void -Vulkan_DestroyFrames (vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *df = device->funcs; - VkDevice dev = device->dev; - - for (size_t i = 0; i < ctx->frames.size; i++) { - __auto_type frame = &ctx->frames.a[i]; - df->vkDestroyFence (dev, frame->fence, 0); - df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0); - df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); - } - - DARRAY_CLEAR (&ctx->frames); -} - void Vulkan_BeginEntityLabel (vulkan_ctx_t *ctx, VkCommandBuffer cmd, entity_t ent) { From 12f1b317011b42536105aafca1604222496c49ee Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jun 2023 17:00:10 +0900 Subject: [PATCH 3627/3664] [vulkan] Use a command buffer pool manager Many thanks to Peter and Darian for clearing up my misunderstanding of how vkResetCommandPool works. The manager creates command buffers from the command pool on an as-needed basis (when the queue of available buffers is empty), and keeps track of those buffers in a queue. When the pool is reset, the queues (one each for primary and secondary command buffers) are reset such that the tracked buffers are available again. --- include/QF/Vulkan/command.h | 21 ++++- include/QF/Vulkan/render.h | 5 +- libs/video/renderer/vulkan/command.c | 86 ++++++++++++++++++- libs/video/renderer/vulkan/render.c | 42 +++------ .../renderer/vulkan/vulkan_translucent.c | 2 +- 5 files changed, 118 insertions(+), 38 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index 4820eb141..fbea477d9 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -7,6 +7,7 @@ #include #include "QF/darray.h" +#include "QF/qtypes.h" typedef struct qfv_cmdbufferset_s DARRAY_TYPE (VkCommandBuffer) qfv_cmdbufferset_t; @@ -29,8 +30,26 @@ typedef struct qfv_bufferimagecopy_s #define QFV_AllocBufferImageCopy(num, allocator) \ DARRAY_ALLOCFIXED (qfv_bufferimagecopy_t, num, allocator) +typedef struct qfv_cmdpoolmgr_s { + qfv_cmdbufferset_t primary; + qfv_cmdbufferset_t secondary; + size_t active_primary; + size_t active_secondary; + struct qfv_device_s *device; + VkCommandPool pool; +} qfv_cmdpoolmgr_t; + struct qfv_queue_s; -struct qfv_device_s; + +qfv_cmdpoolmgr_t *QFV_CmdPoolManager_Init (qfv_cmdpoolmgr_t *manager, + struct qfv_device_s *device); +qfv_cmdpoolmgr_t *QFV_CmdPoolManager_New (struct qfv_device_s *device); +void QFV_CmdPoolManager_Shutdown (qfv_cmdpoolmgr_t *manager); +void QFV_CmdPoolManager_Delete (qfv_cmdpoolmgr_t *manager); +void QFV_CmdPoolManager_Reset (qfv_cmdpoolmgr_t *manager); +VkCommandBuffer QFV_CmdPoolManager_CmdBuffer (qfv_cmdpoolmgr_t *manager, + bool secondary); + VkCommandPool QFV_CreateCommandPool (struct qfv_device_s *device, uint32_t queueFamily, int transient, int reset); diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 67ead2d9a..3be1a4fb2 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -355,14 +355,13 @@ typedef struct qfv_job_s { VkPipelineLayout *layouts; qfv_step_t *steps; qfv_cmdbufferset_t commands; - VkCommandPool command_pool; } qfv_job_t; typedef struct qfv_renderframe_s { VkFence fence; VkSemaphore imageAvailableSemaphore; VkSemaphore renderDoneSemaphore; - VkCommandPool command_pool; + qfv_cmdpoolmgr_t cmdpool; } qfv_renderframe_t; typedef struct qfv_renderframeset_s @@ -382,7 +381,7 @@ typedef struct qfv_taskctx_s { VkCommandBuffer cmd; } qfv_taskctx_t; -VkCommandBuffer QFV_GetCmdBufffer (struct vulkan_ctx_s *ctx, bool secondary); +VkCommandBuffer QFV_GetCmdBuffer (struct vulkan_ctx_s *ctx, bool secondary); void QFV_AppendCmdBuffer (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd); void QFV_RunRenderJob (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 5c64f851c..9708ead0e 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -27,10 +27,94 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif - +#include "QF/qtypes.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" +qfv_cmdpoolmgr_t * +QFV_CmdPoolManager_Init (qfv_cmdpoolmgr_t *manager, qfv_device_t *device) +{ + *manager = (qfv_cmdpoolmgr_t) { + .primary = DARRAY_STATIC_INIT (16), + .secondary = DARRAY_STATIC_INIT (16), + .device = device, + }; + auto dfunc = device->funcs; + + VkCommandPoolCreateInfo poolCInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + .queueFamilyIndex = device->queue.queueFamily, + }; + dfunc->vkCreateCommandPool (device->dev, &poolCInfo, 0, &manager->pool); + return manager; +} + +qfv_cmdpoolmgr_t * +QFV_CmdPoolManager_New (qfv_device_t *device) +{ + return QFV_CmdPoolManager_Init (malloc (sizeof (qfv_cmdpoolmgr_t)), device); +} + +void +QFV_CmdPoolManager_Shutdown (qfv_cmdpoolmgr_t *manager) +{ + auto device = manager->device; + auto dfunc = device->funcs; + dfunc->vkDestroyCommandPool (device->dev, manager->pool, 0); + DARRAY_CLEAR (&manager->primary); + DARRAY_CLEAR (&manager->secondary); +} + +void +QFV_CmdPoolManager_Delete (qfv_cmdpoolmgr_t *manager) +{ + QFV_CmdPoolManager_Shutdown (manager); + free (manager); +} + +void +QFV_CmdPoolManager_Reset (qfv_cmdpoolmgr_t *manager) +{ + auto device = manager->device; + auto dfunc = device->funcs; + dfunc->vkResetCommandPool (device->dev, manager->pool, 0); + manager->active_primary = 0; + manager->active_secondary = 0; +} + +VkCommandBuffer +QFV_CmdPoolManager_CmdBuffer (qfv_cmdpoolmgr_t *manager, bool secondary) +{ + auto device = manager->device; + auto dfunc = device->funcs; + + if (secondary) { + if (manager->active_secondary < manager->secondary.size) { + return manager->secondary.a[manager->active_secondary++]; + } + } else { + if (manager->active_primary < manager->primary.size) { + return manager->primary.a[manager->active_primary++]; + } + } + VkCommandBufferAllocateInfo cinfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = manager->pool, + .level = secondary ? VK_COMMAND_BUFFER_LEVEL_SECONDARY + : VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }; + VkCommandBuffer cmd; + dfunc->vkAllocateCommandBuffers (device->dev, &cinfo, &cmd); + if (secondary) { + DARRAY_APPEND (&manager->secondary, cmd); + } else { + DARRAY_APPEND (&manager->primary, cmd); + } + return cmd; +} + VkCommandPool QFV_CreateCommandPool (qfv_device_t *device, uint32_t queueFamily, int transient, int reset) diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index cbd3cc168..8e1c5fa37 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -54,23 +54,11 @@ #include "vkparse.h" VkCommandBuffer -QFV_GetCmdBufffer (vulkan_ctx_t *ctx, bool secondary) +QFV_GetCmdBuffer (vulkan_ctx_t *ctx, bool secondary) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - __auto_type rctx = ctx->render_context; - __auto_type job = rctx->job; - - VkCommandBufferAllocateInfo cinfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .commandPool = job->command_pool, - .level = secondary ? VK_COMMAND_BUFFER_LEVEL_SECONDARY - : VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = 1, - }; - VkCommandBuffer cmd; - dfunc->vkAllocateCommandBuffers (device->dev, &cinfo, &cmd); - return cmd; + auto rctx = ctx->render_context; + auto rframe = &rctx->frames.a[ctx->curFrame]; + return QFV_CmdPoolManager_CmdBuffer (&rframe->cmdpool, secondary); } void @@ -144,7 +132,7 @@ run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) __auto_type rctx = ctx->render_context; __auto_type job = rctx->job; - VkCommandBuffer cmd = QFV_GetCmdBufffer (ctx, false); + VkCommandBuffer cmd = QFV_GetCmdBuffer (ctx, false); VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, }; @@ -154,7 +142,7 @@ run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) dfunc->vkCmdBeginRenderPass (cmd, &rp->beginInfo, rp->subpassContents); for (uint32_t i = 0; i < rp->subpass_count; i++) { __auto_type sp = &rp->subpasses[i]; - VkCommandBuffer subcmd = QFV_GetCmdBufffer (ctx, true); + VkCommandBuffer subcmd = QFV_GetCmdBuffer (ctx, true); run_subpass (sp, subcmd, ctx); dfunc->vkCmdExecuteCommands (cmd, 1, &subcmd); //FIXME comment is a bit off as exactly one buffer is always submitted @@ -210,7 +198,7 @@ run_compute (qfv_compute_t *comp, vulkan_ctx_t *ctx) __auto_type rctx = ctx->render_context; __auto_type job = rctx->job; - VkCommandBuffer cmd = QFV_GetCmdBufffer (ctx, false); + VkCommandBuffer cmd = QFV_GetCmdBuffer (ctx, false); VkCommandBufferBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -353,15 +341,13 @@ wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto device = ctx->device; auto dfunc = device->funcs; auto dev = device->dev; - auto rctx = ctx->render_context; auto frame = &rctx->frames.a[ctx->curFrame]; dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000); + QFV_CmdPoolManager_Reset (&frame->cmdpool); auto job = ctx->render_context->job; - job->command_pool = frame->command_pool; - dfunc->vkResetCommandPool (device->dev, job->command_pool, 0); DARRAY_RESIZE (&job->commands, 0); } @@ -457,14 +443,7 @@ QFV_Render_Init (vulkan_ctx_t *ctx) frame->imageAvailableSemaphore, va (ctx->va_ctx, "sc image:%zd", i)); frame->renderDoneSemaphore = QFV_CreateSemaphore (device); - VkCommandPoolCreateInfo poolCInfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - .queueFamilyIndex = device->queue.queueFamily, - }; - auto dfunc = device->funcs; - dfunc->vkCreateCommandPool (device->dev, &poolCInfo, 0, - &frame->command_pool); + QFV_CmdPoolManager_Init (&frame->cmdpool, device); } } @@ -502,7 +481,6 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) } } } - job->command_pool = 0; DARRAY_CLEAR (&job->commands); free (rctx->job); } @@ -514,7 +492,7 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) df->vkDestroyFence (dev, frame->fence, 0); df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0); df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0); - df->vkDestroyCommandPool (dev, frame->command_pool, 0); + QFV_CmdPoolManager_Shutdown (&frame->cmdpool); } DARRAY_CLEAR (&rctx->frames); diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index fc89a3087..e69951df6 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -74,7 +74,7 @@ clear_translucent (const exprval_t **params, exprval_t *result, exprctx_t *ectx) translucentctx_t *tctx = ctx->translucent_context; __auto_type tframe = &tctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = QFV_GetCmdBufffer (ctx, false); + VkCommandBuffer cmd = QFV_GetCmdBuffer (ctx, false); VkCommandBufferInheritanceInfo inherit = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, From 3c9bd77346c20ebf157a8786431662702bb72de2 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jun 2023 17:15:40 +0900 Subject: [PATCH 3628/3664] [vulkan] Port line rendering to the new system I'd already done the programming side when doing slice rendering, but hadn't hooked up line rendering in the render spec. --- libs/video/renderer/vulkan/rp_main_def.plist | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index e9ed4edf6..a666ccb45 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -12,6 +12,7 @@ properties = { waterwarp = "[0.0, 0.7, 0.7, 1]"; fisheye = "[0.0, 0.7, 0.7, 1]"; slice = "[0.8, 0.7, 0.2, 1]"; + lines = "[0.8, 0.7, 0.4, 1]"; }; color_dependency = { src = { @@ -586,6 +587,36 @@ properties = { descriptorSets = (matrix_set, quad_data_set); }; }; + lines = { + shader = { + vertex = { + stage = vertex; + name = main; + module = $builtin/line.vert; + }; + fragment = { + stage = fragment; + name = main; + module = $builtin/line.frag; + }; + }; + vertexInput = { + bindings = ( + { binding = 0; stride = "2 * 4 + 4"; inputRate = vertex; }, + ); + attributes = ( + { location = 0; binding = 0; format = r32g32_sfloat; offset = 0; }, + { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, + ); + }; + inputAssembly = { + topology = line_list; + primitiveRestartEnable = false; + }; + layout = { + descriptorSets = (matrix_set); + }; + }; }; descriptorSetLayouts = { matrix_set = { @@ -1324,6 +1355,22 @@ renderpasses = { inputAssembly = $slice.inputAssembly; layout = $slice.layout; }; + lines = { + @inherit = $compose_base; + + color = $color.lines; + tasks = ( + { func = line_draw; }, + ); + + stages = ( + $lines.shader.vertex, + $lines.shader.fragment, + ); + vertexInput = $lines.vertexInput; + inputAssembly = $lines.inputAssembly; + layout = $lines.layout; + }; }; }; }; From 836290aa74461bf1148737c1d0d504aa4a086a62 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jun 2023 19:06:12 +0900 Subject: [PATCH 3629/3664] [vulkan] Update the active command buffer indices When creating a new command buffer and appending it to a queue, the active buffer count needs to be incremented too otherwise the new command buffer will be accidentally reused prematurely. Not noticed earlier because only one buffer was being created. --- libs/video/renderer/vulkan/command.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 9708ead0e..39b02e211 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -109,8 +109,10 @@ QFV_CmdPoolManager_CmdBuffer (qfv_cmdpoolmgr_t *manager, bool secondary) dfunc->vkAllocateCommandBuffers (device->dev, &cinfo, &cmd); if (secondary) { DARRAY_APPEND (&manager->secondary, cmd); + manager->active_secondary++; } else { DARRAY_APPEND (&manager->primary, cmd); + manager->active_primary++; } return cmd; } From 854b6125978a79e7aa6e4055ead128ee15ec6fd4 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jun 2023 20:00:50 +0900 Subject: [PATCH 3630/3664] [vulkan] Name the managed command buffer pool Not that it mattered in the end, but it helps with debugging (found the bug while doing the edits). --- include/QF/Vulkan/command.h | 6 ++++-- libs/video/renderer/vulkan/command.c | 8 +++++--- libs/video/renderer/vulkan/render.c | 3 ++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/QF/Vulkan/command.h b/include/QF/Vulkan/command.h index fbea477d9..d65d2ab74 100644 --- a/include/QF/Vulkan/command.h +++ b/include/QF/Vulkan/command.h @@ -42,8 +42,10 @@ typedef struct qfv_cmdpoolmgr_s { struct qfv_queue_s; qfv_cmdpoolmgr_t *QFV_CmdPoolManager_Init (qfv_cmdpoolmgr_t *manager, - struct qfv_device_s *device); -qfv_cmdpoolmgr_t *QFV_CmdPoolManager_New (struct qfv_device_s *device); + struct qfv_device_s *device, + const char *name); +qfv_cmdpoolmgr_t *QFV_CmdPoolManager_New (struct qfv_device_s *device, + const char *name); void QFV_CmdPoolManager_Shutdown (qfv_cmdpoolmgr_t *manager); void QFV_CmdPoolManager_Delete (qfv_cmdpoolmgr_t *manager); void QFV_CmdPoolManager_Reset (qfv_cmdpoolmgr_t *manager); diff --git a/libs/video/renderer/vulkan/command.c b/libs/video/renderer/vulkan/command.c index 39b02e211..73b443679 100644 --- a/libs/video/renderer/vulkan/command.c +++ b/libs/video/renderer/vulkan/command.c @@ -32,7 +32,8 @@ #include "QF/Vulkan/device.h" qfv_cmdpoolmgr_t * -QFV_CmdPoolManager_Init (qfv_cmdpoolmgr_t *manager, qfv_device_t *device) +QFV_CmdPoolManager_Init (qfv_cmdpoolmgr_t *manager, qfv_device_t *device, + const char *name) { *manager = (qfv_cmdpoolmgr_t) { .primary = DARRAY_STATIC_INIT (16), @@ -51,9 +52,10 @@ QFV_CmdPoolManager_Init (qfv_cmdpoolmgr_t *manager, qfv_device_t *device) } qfv_cmdpoolmgr_t * -QFV_CmdPoolManager_New (qfv_device_t *device) +QFV_CmdPoolManager_New (qfv_device_t *device, const char *name) { - return QFV_CmdPoolManager_Init (malloc (sizeof (qfv_cmdpoolmgr_t)), device); + return QFV_CmdPoolManager_Init (malloc (sizeof (qfv_cmdpoolmgr_t)), device, + name); } void diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 8e1c5fa37..3d4945863 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -443,7 +443,8 @@ QFV_Render_Init (vulkan_ctx_t *ctx) frame->imageAvailableSemaphore, va (ctx->va_ctx, "sc image:%zd", i)); frame->renderDoneSemaphore = QFV_CreateSemaphore (device); - QFV_CmdPoolManager_Init (&frame->cmdpool, device); + QFV_CmdPoolManager_Init (&frame->cmdpool, device, + va (ctx->va_ctx, "render pool:%zd", i)); } } From d2e85f775d1c9900c8b3a3ba0223694178586e8a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jun 2023 20:27:55 +0900 Subject: [PATCH 3631/3664] [vulkan] Get alias model rendering mostly working Mostly because no lighting or compositing to the output buffer is done, but the model is there in renderdoc's image viewer. --- include/QF/Vulkan/qf_alias.h | 6 - libs/video/renderer/vid_render_vulkan.c | 2 + libs/video/renderer/vulkan/rp_main_def.plist | 26 +- libs/video/renderer/vulkan/vulkan_alias.c | 225 +++++------------- libs/video/renderer/vulkan/vulkan_bsp.c | 25 +- libs/video/renderer/vulkan/vulkan_main.c | 12 +- libs/video/renderer/vulkan/vulkan_output.c | 4 +- libs/video/renderer/vulkan/vulkan_particles.c | 1 - .../renderer/vulkan/vulkan_translucent.c | 9 +- 9 files changed, 108 insertions(+), 202 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index c1326e82a..cdcc52a51 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -106,13 +106,7 @@ void Vulkan_Mod_MakeAliasModelDisplayLists (struct mod_alias_ctx_s *alias_ctx, void Vulkan_AliasAddSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); void Vulkan_AliasRemoveSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); -void Vulkan_AliasBegin (struct qfv_orenderframe_s *rFrame); -void Vulkan_DrawAlias (struct entity_s ent, struct qfv_orenderframe_s *rFrame); -void Vulkan_AliasEnd (struct qfv_orenderframe_s *rFrame); - void Vulkan_Alias_Init (struct vulkan_ctx_s *ctx); void Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_AliasDepthRange (struct qfv_orenderframe_s *rFrame, float n, float f); - #endif//__QF_Vulkan_qf_alias_h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 8e06409ea..cb81f7ddd 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -127,7 +127,9 @@ static void vulkan_R_ClearState (void) { QFV_DeviceWaitIdle (vulkan_ctx->device); + //FIXME clear scene correctly r_refdef.worldmodel = 0; + EntQueue_Clear (r_ent_queue); R_ClearDlights (); R_ClearParticles (); Vulkan_LoadLights (0, vulkan_ctx); diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index a666ccb45..dcecf51bd 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -280,7 +280,7 @@ properties = { bindings = ( { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, { binding = 1; stride = "2 * 4 * 4"; inputRate = vertex; }, - { binding = 2; stride = "2 * 4"; inputRate = instance; }, + { binding = 2; stride = "2 * 4"; inputRate = vertex; }, ); attributes = ( { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, @@ -983,9 +983,9 @@ renderpasses = { color = $color.bsp; tasks = ( { func = bsp_draw_queue; - params = (main, solid); }, + params = (main, solid, 0); }, { func = bsp_draw_queue; - params = (main, sky); }, + params = (main, sky, 0); }, ); stages = ( @@ -1007,7 +1007,8 @@ renderpasses = { alias:depth = { color = $color.alias; tasks = ( - { func = alias_draw; }, + { func = alias_draw; + params = (0); }, ); stages = ( @@ -1076,7 +1077,7 @@ renderpasses = { tasks = ( // FIXME sky should not use OIT { func = bsp_draw_queue; - params = (main, sky); }, + params = (main, sky, 1); }, ); stages = ( @@ -1092,7 +1093,7 @@ renderpasses = { tasks = ( // FIXME sky should not use OIT { func = bsp_draw_queue; - params = (main, sky); }, + params = (main, sky, 1); }, ); stages = ( @@ -1107,9 +1108,9 @@ renderpasses = { color = $color.bsp; tasks = ( { func = bsp_draw_queue; - params = (main, translucent); }, + params = (main, translucent, 2); }, { func = bsp_draw_queue; - params = (main, turbulent); }, + params = (main, turbulent, 2); }, ); stages = ( @@ -1172,9 +1173,9 @@ renderpasses = { color = $color.bsp; tasks = ( { func = bsp_draw_queue; - params = (main, solid); }, + params = (main, solid, 1); }, { func = bsp_draw_queue; - params = (main, sky); }, + params = (main, sky, 1); }, ); stages = ( @@ -1189,7 +1190,8 @@ renderpasses = { alias:gbuffer = { color = $color.alias; tasks = ( - { func = alias_draw; }, + { func = alias_draw; + params = (1); }, ); stages = ( @@ -1385,7 +1387,6 @@ steps = { ); }; }; -/* particles = { dependencies = (wait_on_fence); compute = { @@ -1444,7 +1445,6 @@ steps = { }; }; }; -*/ preoutput = { dependencies = (wait_on_fence); process = { diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index c41461775..ec0126624 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -43,7 +43,6 @@ #include "QF/Vulkan/qf_alias.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_palette.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" @@ -61,25 +60,12 @@ typedef struct { vec4f_t fog; } alias_push_constants_t; -static const char * __attribute__((used)) alias_pass_names[] = { - "depth", - "g-buffer", - "translucent", -}; - -static QFV_Subpass subpass_map[] = { - QFV_passDepth, // QFV_aliasDepth - QFV_passGBuffer, // QFV_aliasGBuffer - QFV_passTranslucentFrag,// QFV_aliasTranslucent -}; - static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_alias_skin_t *skin, uint32_t numPC, qfv_push_constants_t *constants, - aliashdr_t *hdr, qfv_orenderframe_t *rFrame, entity_t ent) + aliashdr_t *hdr, vulkan_ctx_t *ctx, entity_t ent) { - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; @@ -116,14 +102,41 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, QFV_CmdEndLabel (device, cmd); } -void -Vulkan_DrawAlias (entity_t ent, qfv_orenderframe_t *rFrame) +static void +alias_depth_range (qfv_taskctx_t *taskctx, float minDepth, float maxDepth) +{ + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + + auto viewport = taskctx->pipeline->viewport; + viewport.minDepth = minDepth; + viewport.maxDepth = maxDepth; + + dfunc->vkCmdSetViewport (taskctx->cmd, 0, 1, &viewport); +} + +void +Vulkan_AliasAddSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) { - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; aliasctx_t *actx = ctx->alias_context; - aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; + skin->descriptor = Vulkan_CreateCombinedImageSampler (ctx, skin->view, + actx->sampler); +} + +void +Vulkan_AliasRemoveSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) +{ + Vulkan_FreeTexture (ctx, skin->descriptor); + skin->descriptor = 0; +} + +static void +alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass) +{ + auto ctx = taskctx->ctx; renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); - model_t *model = renderer->model; + auto model = renderer->model; aliashdr_t *hdr; qfv_alias_skin_t *skin; alias_push_constants_t constants = {}; @@ -171,138 +184,52 @@ Vulkan_DrawAlias (entity_t ent, qfv_orenderframe_t *rFrame) } QuatZero (constants.fog); - emit_commands (aframe->cmdSet.a[QFV_aliasDepth], - animation->pose1, animation->pose2, - 0, 2, push_constants, hdr, rFrame, ent); - emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer], - animation->pose1, animation->pose2, - skin, 5, push_constants, hdr, rFrame, ent); + emit_commands (taskctx->cmd, animation->pose1, animation->pose2, + pass ? skin : 0, + pass ? 5 : 2, push_constants, + hdr, ctx, ent); } static void -alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline, - qfv_orenderframe_t *rFrame) +alias_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - aliasctx_t *actx = ctx->alias_context; - uint32_t curFrame = ctx->curFrame; - aliasframe_t *aframe = &actx->frames.a[curFrame]; - VkCommandBuffer cmd = aframe->cmdSet.a[subpass]; + auto taskctx = (qfv_taskctx_t *) ectx; + bool vmod = Entity_Valid (vr_data.view_model); + int pass = *(int *) params[0]->value; - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - rFrame->renderpass->renderpass, subpass_map[subpass], - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "alias:%s", - alias_pass_names[subpass]), - { 0.6, 0.5, 0, 1}); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto actx = ctx->alias_context; + auto cmd = taskctx->cmd; VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), Vulkan_Palette_Descriptor (ctx), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, actx->layout, 0, 2, sets, 0, 0); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - //XXX glsl_Fog_GetColor (fog); - //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; -} - -static void -alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); -} - -void -Vulkan_AliasBegin (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - aliasctx_t *actx = ctx->alias_context; - aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - - //XXX quat_t fog; - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], - aframe->cmdSet.a[QFV_aliasDepth]); - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], - aframe->cmdSet.a[QFV_aliasGBuffer]); - - alias_begin_subpass (QFV_aliasDepth, actx->depth, rFrame); - alias_begin_subpass (QFV_aliasGBuffer, actx->gbuf, rFrame); -} - -void -Vulkan_AliasEnd (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - aliasctx_t *actx = ctx->alias_context; - aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - - alias_end_subpass (aframe->cmdSet.a[QFV_aliasDepth], ctx); - alias_end_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], ctx); -} - -void -Vulkan_AliasDepthRange (qfv_orenderframe_t *rFrame, - float minDepth, float maxDepth) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - aliasctx_t *actx = ctx->alias_context; - aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; - - VkViewport viewport = rFrame->renderpass->viewport; - viewport.minDepth = minDepth; - viewport.maxDepth = maxDepth; - - dfunc->vkCmdSetViewport (aframe->cmdSet.a[QFV_aliasDepth], 0, 1, - &viewport); - dfunc->vkCmdSetViewport (aframe->cmdSet.a[QFV_aliasGBuffer], 0, 1, - &viewport); -} - -void -Vulkan_AliasAddSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) -{ - aliasctx_t *actx = ctx->alias_context; - skin->descriptor = Vulkan_CreateCombinedImageSampler (ctx, skin->view, - actx->sampler); -} - -void -Vulkan_AliasRemoveSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) -{ - Vulkan_FreeTexture (ctx, skin->descriptor); - skin->descriptor = 0; -} - -static void -alias_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) -{ + auto queue = r_ent_queue; //FIXME fetch from scene + for (size_t i = 0; i < queue->ent_queues[mod_alias].size; i++) { + entity_t ent = queue->ent_queues[mod_alias].a[i]; + // FIXME hack the depth range to prevent view model + // from poking into walls + if (vmod && ent.id == vr_data.view_model.id) { + alias_depth_range (taskctx, 0, 0.3); + } + alias_draw_ent (taskctx, ent, pass); + // unhack in case the view_model is not the last + if (vmod && ent.id == vr_data.view_model.id) { + alias_depth_range (taskctx, 0, 1); + } + } } +static exprtype_t *alias_draw_params[] = { + &cexpr_int, +}; static exprfunc_t alias_draw_func[] = { - { .func = alias_draw }, + { .func = alias_draw, .num_params = 1, .param_types = alias_draw_params }, {} }; static exprsym_t alias_task_syms[] = { @@ -313,8 +240,6 @@ static exprsym_t alias_task_syms[] = { void Vulkan_Alias_Init (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfvPushDebug (ctx, "alias init"); QFV_Render_AddTasks (ctx, alias_task_syms); @@ -331,23 +256,6 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) actx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "alias_gbuf"); actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); - - for (size_t i = 0; i < frames; i++) { - __auto_type aframe = &actx->frames.a[i]; - - DARRAY_INIT (&aframe->cmdSet, QFV_aliasNumPasses); - DARRAY_RESIZE (&aframe->cmdSet, QFV_aliasNumPasses); - aframe->cmdSet.grow = 0; - - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &aframe->cmdSet); - - for (int j = 0; j < QFV_aliasNumPasses; j++) { - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - aframe->cmdSet.a[j], - va (ctx->va_ctx, "cmd:alias:%zd:%s", i, - alias_pass_names[j])); - } - } qfvPopDebug (ctx); } @@ -358,11 +266,6 @@ Vulkan_Alias_Shutdown (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; - for (size_t i = 0; i < actx->frames.size; i++) { - __auto_type aframe = &actx->frames.a[i]; - free (aframe->cmdSet.a); - } - dfunc->vkDestroyPipeline (device->dev, actx->depth, 0); dfunc->vkDestroyPipeline (device->dev, actx->gbuf, 0); free (actx->frames.a); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index ce021a5e0..a680b37b0 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1365,6 +1365,28 @@ create_notexture (vulkan_ctx_t *ctx) static void bsp_draw_queue (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto bctx = ctx->bsp_context; + int pass = *(int *) params[2]->value; + if (!pass && r_refdef.worldmodel) { + bctx->main_pass.bsp_context = bctx; + bctx->main_pass.position = r_refdef.frame.position; + bctx->main_pass.vis_frame = r_visframecount; + bctx->main_pass.face_frames = r_face_visframes; + bctx->main_pass.leaf_frames = r_leaf_visframes; + bctx->main_pass.node_frames = r_node_visframes; + //bctx->main_pass.entid_data = bframe->entid_data; + //bctx->main_pass.entid_count = 0; + + clear_queues (bctx, &bctx->main_pass); // do this first for water and skys + entity_t worldent = nullentity; + int world_id = Vulkan_Scene_AddEntity (ctx, worldent); + bctx->main_pass.ent_frame = 0; // world is always frame 0 + bctx->main_pass.inst_id = world_id; + bctx->main_pass.brush = &r_refdef.worldmodel->brush; + R_VisitWorldNodes (&bctx->main_pass, ctx); + } } static exprenum_t bsp_stage_enum; @@ -1407,12 +1429,13 @@ static exprenum_t bsp_queue_enum = { }; static exprtype_t *bsp_draw_queue_params[] = { + &cexpr_int, &bsp_queue_type, &bsp_stage_type, }; static exprfunc_t bsp_draw_queue_func[] = { - { 0, 2, bsp_draw_queue_params, bsp_draw_queue }, + { 0, 3, bsp_draw_queue_params, bsp_draw_queue }, {} }; static exprsym_t bsp_task_syms[] = { diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 6ac19052d..43402179a 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -74,7 +74,6 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_orenderframe_t *rFrame) if (!r_drawentities) return; //FIXME need a better way (components? but HasComponent isn't free) - int vmod = Entity_Valid (vr_data.view_model); #define RE_LOOP(type_name, Type) \ do { \ int begun = 0; \ @@ -85,22 +84,12 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_orenderframe_t *rFrame) Vulkan_##Type##Begin (rFrame); \ begun = 1; \ } \ - /* FIXME hack the depth range to prevent view model */\ - /* from poking into walls */\ - if (vmod && ent.id == vr_data.view_model.id) { \ - Vulkan_AliasDepthRange (rFrame, 0, 0.3); \ - } \ Vulkan_Draw##Type (ent, rFrame); \ - /* unhack in case the view_model is not the last */\ - if (vmod && ent.id == vr_data.view_model.id) { \ - Vulkan_AliasDepthRange (rFrame, 0, 1); \ - } \ } \ if (begun) \ Vulkan_##Type##End (rFrame); \ } while (0) - RE_LOOP (alias, Alias); RE_LOOP (iqm, IQM); RE_LOOP (sprite, Sprite); } @@ -153,6 +142,7 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) } r_refdef.worldmodel = scene->worldmodel; + EntQueue_Clear (r_ent_queue); // Force a vis update R_MarkLeaves (0, 0, 0, 0); diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 5581f78ec..130441c65 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -294,11 +294,11 @@ static exprtype_t *stepref_param[] = { &cexpr_string, }; static exprfunc_t acquire_output_func[] = { - { .func = acquire_output, .num_params = 1, stepref_param }, + { .func = acquire_output, .num_params = 1, .param_types = stepref_param }, {} }; static exprfunc_t update_input_func[] = { - { .func = update_input, .num_params = 1, stepref_param }, + { .func = update_input, .num_params = 1, .param_types = stepref_param }, {} }; static exprfunc_t output_draw_func[] = { diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 1a9b26cda..6bd22a0c9 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -277,7 +277,6 @@ create_buffers (vulkan_ctx_t *ctx) static void particles_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { - puts ("particles_draw"); } static void diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index e69951df6..c533efe94 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -76,14 +76,9 @@ clear_translucent (const exprval_t **params, exprval_t *result, exprctx_t *ectx) VkCommandBuffer cmd = QFV_GetCmdBuffer (ctx, false); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - 0, 0, 0, - 0, 0, 0, - }; VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, &inherit, + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); From 2122d923d93ec3380ca9328dba6b98a82ff7873b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jun 2023 20:30:10 +0900 Subject: [PATCH 3632/3664] [vulkan] Move the subpass command labels out a layer Just for easier debugging in renderdoc. --- libs/video/renderer/vulkan/render.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 3d4945863..184244986 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -110,15 +110,12 @@ run_subpass (qfv_subpass_t *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkBeginCommandBuffer (cmd, &sp->beginInfo); - QFV_duCmdBeginLabel (device, cmd, sp->label.name, - {VEC4_EXP (sp->label.color)}); for (uint32_t i = 0; i < sp->pipeline_count; i++) { __auto_type pipeline = &sp->pipelines[i]; run_pipeline (pipeline, cmd, ctx); } - QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); } @@ -143,8 +140,11 @@ run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) for (uint32_t i = 0; i < rp->subpass_count; i++) { __auto_type sp = &rp->subpasses[i]; VkCommandBuffer subcmd = QFV_GetCmdBuffer (ctx, true); + QFV_duCmdBeginLabel (device, cmd, sp->label.name, + {VEC4_EXP (sp->label.color)}); run_subpass (sp, subcmd, ctx); dfunc->vkCmdExecuteCommands (cmd, 1, &subcmd); + QFV_duCmdEndLabel (device, cmd); //FIXME comment is a bit off as exactly one buffer is always submitted // //Regardless of whether any commands were submitted for this From 942b503486185afeb3eb728b79674696a93d609b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jun 2023 21:36:14 +0900 Subject: [PATCH 3633/3664] [vulkan] Get lighting mostly working Lights seem to be good in renderdoc, but still need to get the compose subpass working. --- include/QF/Vulkan/qf_lighting.h | 1 - include/QF/Vulkan/render.h | 14 ++- libs/video/renderer/vulkan/render.c | 35 +++--- libs/video/renderer/vulkan/render_load.c | 7 +- libs/video/renderer/vulkan/vulkan_lighting.c | 108 +++++++------------ libs/video/renderer/vulkan/vulkan_main.c | 1 - 6 files changed, 72 insertions(+), 94 deletions(-) diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 703cbb251..e314b3051 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -122,7 +122,6 @@ struct qfv_orenderframe_s; void Vulkan_Lighting_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Lighting_Draw (struct qfv_orenderframe_s *rFrame); void Vulkan_LoadLights (struct scene_s *scene, struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_lighting_h diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 3be1a4fb2..db79fbc7c 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -300,6 +300,14 @@ typedef struct qfv_subpass_s { qfv_pipeline_t *pipelines; } qfv_subpass_t; +typedef struct qfv_framebuffer_s { + uint32_t width; + uint32_t height; + uint32_t layers; + uint32_t num_attachments; + VkImageView *views; +} qfv_framebuffer_t; + typedef struct qfv_renderpass_s { struct vulkan_ctx_s *vulkan_ctx; qfv_label_t label; // for debugging @@ -307,10 +315,11 @@ typedef struct qfv_renderpass_s { VkRenderPassBeginInfo beginInfo; VkSubpassContents subpassContents; - qfv_framebufferinfo_t *framebufferinfo; - uint32_t subpass_count; qfv_subpass_t *subpasses; + + qfv_framebuffer_t framebuffer; + qfv_framebufferinfo_t *framebufferinfo; } qfv_renderpass_t; typedef struct qfv_render_s { @@ -378,6 +387,7 @@ typedef struct qfv_renderctx_s { typedef struct qfv_taskctx_s { struct vulkan_ctx_s *ctx; qfv_pipeline_t *pipeline; + qfv_renderpass_t *renderpass; VkCommandBuffer cmd; } qfv_taskctx_t; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 184244986..167b1727c 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -78,20 +78,17 @@ run_tasks (uint32_t task_count, qfv_taskinfo_t *tasks, qfv_taskctx_t *ctx) } static void -run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) +run_pipeline (qfv_pipeline_t *pipeline, qfv_taskctx_t *taskctx) { - qfv_device_t *device = ctx->device; + qfv_device_t *device = taskctx->ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + auto cmd = taskctx->cmd; dfunc->vkCmdBindPipeline (cmd, pipeline->bindPoint, pipeline->pipeline); dfunc->vkCmdSetViewport (cmd, 0, 1, &pipeline->viewport); dfunc->vkCmdSetScissor (cmd, 0, 1, &pipeline->scissor); - qfv_taskctx_t taskctx = { - .ctx = ctx, - .pipeline = pipeline, - .cmd = cmd, - }; - run_tasks (pipeline->task_count, pipeline->tasks, &taskctx); + taskctx->pipeline = pipeline; + run_tasks (pipeline->task_count, pipeline->tasks, taskctx); if (pipeline->num_descriptorsets) { dfunc->vkCmdBindDescriptorSets (cmd, pipeline->bindPoint, @@ -105,18 +102,18 @@ run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) // https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/ static void -run_subpass (qfv_subpass_t *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx) +run_subpass (qfv_subpass_t *sp, qfv_taskctx_t *taskctx) { - qfv_device_t *device = ctx->device; + qfv_device_t *device = taskctx->ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkBeginCommandBuffer (cmd, &sp->beginInfo); + dfunc->vkBeginCommandBuffer (taskctx->cmd, &sp->beginInfo); for (uint32_t i = 0; i < sp->pipeline_count; i++) { __auto_type pipeline = &sp->pipelines[i]; - run_pipeline (pipeline, cmd, ctx); + run_pipeline (pipeline, taskctx); } - dfunc->vkEndCommandBuffer (cmd); + dfunc->vkEndCommandBuffer (taskctx->cmd); } static void @@ -139,11 +136,15 @@ run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) dfunc->vkCmdBeginRenderPass (cmd, &rp->beginInfo, rp->subpassContents); for (uint32_t i = 0; i < rp->subpass_count; i++) { __auto_type sp = &rp->subpasses[i]; - VkCommandBuffer subcmd = QFV_GetCmdBuffer (ctx, true); QFV_duCmdBeginLabel (device, cmd, sp->label.name, {VEC4_EXP (sp->label.color)}); - run_subpass (sp, subcmd, ctx); - dfunc->vkCmdExecuteCommands (cmd, 1, &subcmd); + qfv_taskctx_t taskctx = { + .ctx = ctx, + .renderpass = rp, + .cmd = QFV_GetCmdBuffer (ctx, true), + }; + run_subpass (sp, &taskctx); + dfunc->vkCmdExecuteCommands (cmd, 1, &taskctx.cmd); QFV_duCmdEndLabel (device, cmd); //FIXME comment is a bit off as exactly one buffer is always submitted // @@ -295,7 +296,7 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) __auto_type rctx = ctx->render_context; auto fb = rp->framebufferinfo; - VkImageView attachments[fb->num_attachments]; + auto attachments = rp->framebuffer.views; VkFramebufferCreateInfo cInfo = { .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, .attachmentCount = fb->num_attachments, diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 79bf1358b..d2cec54cc 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -723,6 +723,7 @@ typedef struct { qfv_pipeline_t *pipelines; qfv_taskinfo_t *tasks; VkDescriptorSet *descriptorsets; + VkImageView *attachment_views; } jobptr_t; static void @@ -796,10 +797,11 @@ init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo, .clearValueCount = rpinfo->framebuffer.num_attachments, .pClearValues = &jp->clearvalues[s->inds.num_attachments], }, - .framebufferinfo = &rpinfo->framebuffer, .subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, .subpass_count = rpinfo->num_subpasses, .subpasses = &jp->subpasses[s->inds.num_subpasses], + .framebuffer.views = &jp->attachment_views[s->inds.num_attachments], + .framebufferinfo = &rpinfo->framebuffer, }; s->inds.num_attachments += rpinfo->framebuffer.num_attachments; for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) { @@ -908,6 +910,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) size += sizeof (VkPipeline [counts->num_comp_pipelines]); size += sizeof (VkPipelineLayout [s.inds.num_layouts]); size += sizeof (VkDescriptorSet [counts->num_descriptorsets]); + size += sizeof (VkImageView [counts->num_attachments]); rctx->job = malloc (size); auto job = rctx->job; @@ -933,6 +936,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) job->pipelines = (VkPipeline *) &job->renderpasses[job->num_renderpasses]; job->layouts = (VkPipelineLayout *) &job->pipelines[job->num_pipelines]; auto ds = (VkDescriptorSet *) &job->layouts[job->num_layouts]; + auto av = (VkImageView *) &ds[counts->num_descriptorsets]; jobptr_t jp = { .steps = job->steps, .renders = rn, @@ -944,6 +948,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) .pipelines = pl, .tasks = ti, .descriptorsets = ds, + .attachment_views = av, }; for (uint32_t i = 0; i < job->num_renderpasses; i++) { diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index e736f22ba..3ec57f952 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -147,78 +147,6 @@ update_lights (vulkan_ctx_t *ctx) QFV_PacketSubmit (packet); } -void -Vulkan_Lighting_Draw (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - qfv_orenderpass_t *renderpass = rFrame->renderpass; - lightingctx_t *lctx = ctx->lighting_context; - - if (!lctx->scene) { - return; - } - if (lctx->scene->lights) { - update_lights (ctx); - } - - lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = lframe->cmd; - - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passLighting], cmd); - - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - renderpass->renderpass, QFV_passLighting, - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - QFV_duCmdBeginLabel (device, cmd, "lighting", { 0.6, 0.5, 0.6, 1}); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - lctx->pipeline); - - lframe->bufferInfo[0].buffer = lframe->light_buffer; - lframe->attachInfo[0].imageView - = renderpass->attachment_views->a[QFV_attachDepth]; - lframe->attachInfo[1].imageView - = renderpass->attachment_views->a[QFV_attachColor]; - lframe->attachInfo[2].imageView - = renderpass->attachment_views->a[QFV_attachEmission]; - lframe->attachInfo[3].imageView - = renderpass->attachment_views->a[QFV_attachNormal]; - lframe->attachInfo[4].imageView - = renderpass->attachment_views->a[QFV_attachPosition]; - dfunc->vkUpdateDescriptorSets (device->dev, - LIGHTING_DESCRIPTORS, - lframe->descriptors, 0, 0); - - VkDescriptorSet sets[] = { - lframe->attachWrite[0].dstSet, - lframe->bufferWrite[0].dstSet, - lframe->shadowWrite.dstSet, - }; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - lctx->layout, 0, 3, sets, 0, 0); - - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - - dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); -} - static void lighting_draw_maps (qfv_orenderframe_t *rFrame) { @@ -321,6 +249,42 @@ static VkWriteDescriptorSet base_image_write = { static void lights_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto lctx = ctx->lighting_context; + auto cmd = taskctx->cmd; + + if (!lctx->scene) { + return; + } + if (lctx->scene->lights) { + update_lights (ctx); + } + + lightingframe_t *lframe = &lctx->frames.a[ctx->curFrame]; + + auto fb = &taskctx->renderpass->framebuffer; + lframe->bufferInfo[0].buffer = lframe->light_buffer; + lframe->attachInfo[0].imageView = fb->views[QFV_attachDepth]; + lframe->attachInfo[1].imageView = fb->views[QFV_attachColor]; + lframe->attachInfo[2].imageView = fb->views[QFV_attachEmission]; + lframe->attachInfo[3].imageView = fb->views[QFV_attachNormal]; + lframe->attachInfo[4].imageView = fb->views[QFV_attachPosition]; + dfunc->vkUpdateDescriptorSets (device->dev, + LIGHTING_DESCRIPTORS, + lframe->descriptors, 0, 0); + + VkDescriptorSet sets[] = { + lframe->attachWrite[0].dstSet, + lframe->bufferWrite[0].dstSet, + lframe->shadowWrite.dstSet, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + lctx->layout, 0, 3, sets, 0, 0); + + dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); } static exprfunc_t lights_draw_func[] = { diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 43402179a..53b8aa545 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -158,7 +158,6 @@ static void main_draw (qfv_orenderframe_t *rFrame) { Vulkan_RenderView (rFrame); - Vulkan_Lighting_Draw (rFrame); Vulkan_Compose_Draw (rFrame); } From 7eb14b0a32b2cd37e62cb637a32e5b7349837b9e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 22 Jun 2023 21:44:02 +0900 Subject: [PATCH 3634/3664] [vulkan] Get the compose subpass working That seems to be the main render pass working. Next is to get the output render pass to use the main render pass's output. --- include/QF/Vulkan/qf_compose.h | 1 - libs/video/renderer/vulkan/vulkan_compose.c | 76 ++++++--------------- libs/video/renderer/vulkan/vulkan_main.c | 1 - 3 files changed, 22 insertions(+), 56 deletions(-) diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h index 9b40c14d0..efb61b701 100644 --- a/include/QF/Vulkan/qf_compose.h +++ b/include/QF/Vulkan/qf_compose.h @@ -58,6 +58,5 @@ struct qfv_orenderframe_s; void Vulkan_Compose_Init (struct vulkan_ctx_s *ctx); void Vulkan_Compose_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Compose_Draw (struct qfv_orenderframe_s *rFrame); #endif//__QF_Vulkan_qf_compose_h diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 550baade3..cf4a70a1c 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -57,60 +57,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -void -Vulkan_Compose_Draw (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - qfv_orenderpass_t *renderpass = rFrame->renderpass; - - composectx_t *cctx = ctx->compose_context; - composeframe_t *cframe = &cctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = cframe->cmd; - - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passCompose], cmd); - - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - renderpass->renderpass, QFV_passCompose, - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - QFV_duCmdBeginLabel (device, cmd, "compose", { 0, 0.2, 0.6, 1}); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - cctx->pipeline); - - cframe->imageInfo[0].imageView - = renderpass->attachment_views->a[QFV_attachOpaque]; - dfunc->vkUpdateDescriptorSets (device->dev, COMPOSE_IMAGE_INFOS, - cframe->descriptors, 0, 0); - - VkDescriptorSet sets[] = { - cframe->descriptors[0].dstSet, - Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), - }; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - cctx->layout, 0, 2, sets, 0, 0); - - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - - dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); -} - static VkDescriptorImageInfo base_image_info = { 0, 0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; @@ -124,6 +70,28 @@ static VkWriteDescriptorSet base_image_write = { static void compose_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + + auto cctx = ctx->compose_context; + auto cframe = &cctx->frames.a[ctx->curFrame]; + auto cmd = taskctx->cmd; + + auto fb = &taskctx->renderpass->framebuffer; + cframe->imageInfo[0].imageView = fb->views[QFV_attachOpaque]; + dfunc->vkUpdateDescriptorSets (device->dev, COMPOSE_IMAGE_INFOS, + cframe->descriptors, 0, 0); + + VkDescriptorSet sets[] = { + cframe->descriptors[0].dstSet, + Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + cctx->layout, 0, 2, sets, 0, 0); + + dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); } static exprfunc_t compose_draw_func[] = { diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 53b8aa545..95816ecd2 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -158,7 +158,6 @@ static void main_draw (qfv_orenderframe_t *rFrame) { Vulkan_RenderView (rFrame); - Vulkan_Compose_Draw (rFrame); } void From a186df90f349db8ebb8cf69468f4642d3e252e42 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jun 2023 00:43:34 +0900 Subject: [PATCH 3635/3664] [vulkan] Connect the main and output render steps The output system's update_input takes a parameter specifying the render step from which it is to get the output view of that step and updates its descriptors as necessary. With this, the full render job is working for alias models (minus a few glitches). --- include/QF/Vulkan/render.h | 3 + libs/video/renderer/vulkan/render.c | 4 +- libs/video/renderer/vulkan/render_load.c | 6 +- libs/video/renderer/vulkan/rp_main_def.plist | 4 +- libs/video/renderer/vulkan/vkparse.plist | 2 +- libs/video/renderer/vulkan/vulkan_output.c | 119 ++++++++----------- 6 files changed, 62 insertions(+), 76 deletions(-) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index db79fbc7c..5f6071d4a 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -211,6 +211,7 @@ typedef struct qfv_renderpassinfo_s { qfv_framebufferinfo_t framebuffer; uint32_t num_subpasses; qfv_subpassinfo_t *subpasses; + qfv_reference_t output; } qfv_renderpassinfo_t; typedef struct qfv_computeinfo_s { @@ -320,6 +321,8 @@ typedef struct qfv_renderpass_s { qfv_framebuffer_t framebuffer; qfv_framebufferinfo_t *framebufferinfo; + VkImageView output; + qfv_reference_t outputref; } qfv_renderpass_t; typedef struct qfv_render_s { diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 167b1727c..f30d26009 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -317,6 +317,9 @@ QFV_CreateFramebuffer (vulkan_ctx_t *ctx, qfv_renderpass_t *rp) } } else { attachments[i] = find_imageview (&fb->attachments[i].view, rctx); + if (rp->outputref.name) { + rp->output = find_imageview (&rp->outputref, rctx); + } } } @@ -457,7 +460,6 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) __auto_type rctx = ctx->render_context; if (rctx->job) { __auto_type job = rctx->job; - //QFV_DestroyFramebuffer (ctx); //FIXME do properly for (uint32_t i = 0; i < job->num_renderpasses; i++) { dfunc->vkDestroyRenderPass (device->dev, job->renderpasses[i], 0); } diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index d2cec54cc..1e284f544 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -800,8 +800,12 @@ init_renderpass (qfv_renderpass_t *rp, qfv_renderpassinfo_t *rpinfo, .subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, .subpass_count = rpinfo->num_subpasses, .subpasses = &jp->subpasses[s->inds.num_subpasses], - .framebuffer.views = &jp->attachment_views[s->inds.num_attachments], + .framebuffer = { + .num_attachments = rpinfo->framebuffer.num_attachments, + .views = &jp->attachment_views[s->inds.num_attachments], + }, .framebufferinfo = &rpinfo->framebuffer, + .outputref = rpinfo->output, }; s->inds.num_attachments += rpinfo->framebuffer.num_attachments; for (uint32_t i = 0; i < rpinfo->num_subpasses; i++) { diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index dcecf51bd..2b229b51b 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1302,6 +1302,7 @@ renderpasses = { }; }; }; + output = output; }; deferred_cube = { @inherit = $renderpasses.deferred; @@ -1451,7 +1452,8 @@ steps = { tasks = ( { func = acquire_output; params = ("\"output\""); }, - { func = update_input; }, + { func = update_input; + params = ("\"main\""); }, { func = flush_draw; }, ); }; diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 1b6fcb021..530702856 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -677,6 +677,7 @@ parse = { size = num_subpasses; values = subpasses; }; + output = auto; }; qfv_descriptorsetlayoutinfo_s = { .name = qfv_descriptorsetlayoutinfo_t; @@ -706,7 +707,6 @@ parse = { qfv_renderinfo_s = { .name = qfv_renderinfo_t; color = auto; - output = ignore; renderpasses = { type = (labeledarray, qfv_renderpassinfo_t, name); size = num_renderpasses; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 130441c65..f1d9e9c3b 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -70,76 +70,6 @@ preoutput_draw (qfv_orenderframe_t *rFrame) static void process_input (qfv_orenderframe_t *rFrame) { - return; - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - outputctx_t *octx = ctx->output_context; - outputframe_t *oframe = &octx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = oframe->cmd; - - DARRAY_APPEND (&rFrame->subpassCmdSets[0], cmd); - - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - rFrame->renderpass->renderpass, 0, - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - QFV_duCmdBeginLabel (device, cmd, "output:output"); - - __auto_type pipeline = octx->output; - __auto_type layout = octx->output_layout; - if (scr_fisheye) { - pipeline = octx->fisheye; - layout = octx->fish_layout; - } else if (r_dowarp) { - pipeline = octx->waterwarp; - layout = octx->warp_layout; - } - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - - VkDescriptorSet set[] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - oframe->set, - }; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 2, set, 0, 0); - if (scr_fisheye) { - float width = r_refdef.vrect.width; - float height = r_refdef.vrect.height; - - float ffov = scr_ffov * M_PI / 360; - float aspect = height / width; - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &ffov }, - { VK_SHADER_STAGE_FRAGMENT_BIT, 4, sizeof (float), &aspect }, - }; - QFV_PushConstants (device, cmd, layout, 2, push_constants); - } else if (r_dowarp) { - float time = vr_data.realtime; - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &time }, - }; - QFV_PushConstants (device, cmd, layout, 1, push_constants); - } - - dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); - - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); - } static void @@ -266,11 +196,12 @@ update_input (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto dfunc = device->funcs; auto octx = ctx->output_context; auto oframe = &octx->frames.a[ctx->curFrame]; + auto input = QFV_GetStep (params[0], ctx->render_context->job); - if (oframe->input == octx->input) { + if (oframe->input == input->render->active->output) { return; } - oframe->input = octx->input; + oframe->input = input->render->active->output; VkDescriptorImageInfo imageInfo = { octx->sampler, oframe->input, @@ -288,6 +219,50 @@ update_input (const exprval_t **params, exprval_t *result, exprctx_t *ectx) static void output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto octx = ctx->output_context; + auto oframe = &octx->frames.a[ctx->curFrame]; + auto cmd = taskctx->cmd; + + auto layout = octx->output_layout; + //__auto_type pipeline = octx->output; + //if (scr_fisheye) { + // pipeline = octx->fisheye; + // layout = octx->fish_layout; + //} else if (r_dowarp) { + // pipeline = octx->waterwarp; + // layout = octx->warp_layout; + //} + + VkDescriptorSet set[] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + oframe->set, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 2, set, 0, 0); + if (scr_fisheye) { + float width = r_refdef.vrect.width; + float height = r_refdef.vrect.height; + + float ffov = scr_ffov * M_PI / 360; + float aspect = height / width; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &ffov }, + { VK_SHADER_STAGE_FRAGMENT_BIT, 4, sizeof (float), &aspect }, + }; + QFV_PushConstants (device, cmd, layout, 2, push_constants); + } else if (r_dowarp) { + float time = vr_data.realtime; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &time }, + }; + QFV_PushConstants (device, cmd, layout, 1, push_constants); + } + + dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); } static exprtype_t *stepref_param[] = { From a2a237b854ea7ae302a2db3d67166e8ee7f79e69 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jun 2023 00:50:27 +0900 Subject: [PATCH 3636/3664] [vulkan] Correct depth and winding issues Quake data needs clockwise winding, and both min and max depth of 0 makes for some very strange results. --- libs/video/renderer/vulkan/render.c | 8 ++++++-- libs/video/renderer/vulkan/rp_main_def.plist | 11 +++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index f30d26009..d8ec6ecc8 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -364,8 +364,12 @@ renderpass_update_viewper_sissor (qfv_renderpass_t *rp, auto sp = &rp->subpasses[i]; for (uint32_t j = 0; j < sp->pipeline_count; j++) { auto pl = &sp->pipelines[j]; - pl->viewport.width = output->extent.width; - pl->viewport.height = output->extent.height; + pl->viewport = (VkViewport) { + .width = output->extent.width, + .height = output->extent.height, + .minDepth = 0, + .maxDepth = 1, + }; pl->scissor.extent = output->extent; } } diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 2b229b51b..8b59fa1c1 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -977,6 +977,7 @@ renderpasses = { base_pipeline = { @inherit = $pipeline_base; depthStencil = $depth_test_and_write; + rasterization = $cw_cull_back; }; pipelines = { bsp:depth = { @@ -1070,7 +1071,10 @@ renderpasses = { }; preserve = (color, emission, normal, position, output); }; - base_pipeline = $pipeline_base; + base_pipeline = { + @inherit = $pipeline_base; + rasterization = $cw_cull_back; + }; pipelines = { bsp:skybox = { color = $color.bsp; @@ -1167,7 +1171,10 @@ renderpasses = { }; preserve = (output); }; - base_pipeline = $pipeline_base; + base_pipeline = { + @inherit = $pipeline_base; + rasterization = $cw_cull_back; + }; pipelines = { bsp:gbuffer = { color = $color.bsp; From 54712be41b6fb3a94f2499e79076b5328bfea62c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jun 2023 02:12:33 +0900 Subject: [PATCH 3637/3664] [vulkan] Enable alpha blend for the compose step Now the text looks good when over the player model. --- libs/video/renderer/vulkan/rp_main_def.plist | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 8b59fa1c1..f24a59163 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -124,6 +124,16 @@ properties = { alphaBlendOp = add; colorWriteMask = r|g|b|a; }; + alpha_blend = { + blendEnable = true; + srcColorBlendFactor = one; + dstColorBlendFactor = one_minus_src_alpha; + colorBlendOp = add; + srcAlphaBlendFactor = one; + dstAlphaBlendFactor = one_minus_src_alpha; + alphaBlendOp = add; + colorWriteMask = r|g|b|a; + }; pipeline_base = { viewport = { viewports = ( @@ -1331,7 +1341,10 @@ renderpasses = { color = "[ 0, 0.5, 0.5, 1]"; attachments = { color = { - output = color_attachment_optimal; + output = { + layout = color_attachment_optimal; + blend = $alpha_blend; + }; }; }; pipelines = { From 0ec2aa2bf73da057ec64a7ddb020392fe3c2398a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jun 2023 09:38:41 +0900 Subject: [PATCH 3638/3664] [vulkan] Get iqm rendering working again It turns out there was a bug in the old iqm push constants spec (I still need to figure out how to use layouts in the new system so I can completely delete the old). --- include/QF/Vulkan/qf_iqm.h | 4 - libs/video/renderer/vulkan/pl_quake_def.plist | 2 +- libs/video/renderer/vulkan/rp_main_def.plist | 6 +- libs/video/renderer/vulkan/vulkan_iqm.c | 311 ++++++------------ libs/video/renderer/vulkan/vulkan_main.c | 1 - 5 files changed, 112 insertions(+), 212 deletions(-) diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h index 43c04302b..83599625b 100644 --- a/include/QF/Vulkan/qf_iqm.h +++ b/include/QF/Vulkan/qf_iqm.h @@ -111,10 +111,6 @@ void Vulkan_IQMRemoveBones (struct vulkan_ctx_s *ctx, struct iqm_s *iqm); void Vulkan_IQMAddSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); void Vulkan_IQMRemoveSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); -void Vulkan_IQMBegin (struct qfv_orenderframe_s *rFrame); -void Vulkan_DrawIQM (struct entity_s ent, struct qfv_orenderframe_s *rFrame); -void Vulkan_IQMEnd (struct qfv_orenderframe_s *rFrame); - void Vulkan_IQM_Init (struct vulkan_ctx_s *ctx); void Vulkan_IQM_Shutdown (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index 72a104744..ed3caa0d5 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -474,7 +474,7 @@ pipelineLayouts = { { stageFlags = fragment; offset = 68; - size = "3 * 4 + 2 * 4 * 4 + 4"; + size = "3 * 4 + 2 * 4 * 4"; }, ); }; diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index f24a59163..067daa460 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1044,7 +1044,8 @@ renderpasses = { iqm:depth = { color = $color.iqm; tasks = ( - { func = iqm_draw; }, + { func = iqm_draw; + params = (0); }, ); stages = ( @@ -1222,7 +1223,8 @@ renderpasses = { iqm:gbuffer = { color = $color.iqm; tasks = ( - { func = iqm_draw; }, + { func = iqm_draw; + params = (1); }, ); stages = ( diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 92e3fd2e7..d6e40bb2d 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -62,30 +62,17 @@ typedef struct { vec4f_t fog; } iqm_push_constants_t; -static const char * __attribute__((used)) iqm_pass_names[] = { - "depth", - "g-buffer", - "translucent", -}; - -static QFV_Subpass subpass_map[] = { - QFV_passDepth, // QFV_iqmDepth - QFV_passGBuffer, // QFV_iqmGBuffer - QFV_passTranslucentFrag,// QFV_iqmTranslucent -}; - static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_iqm_skin_t *skins, uint32_t numPC, qfv_push_constants_t *constants, - iqm_t *iqm, qfv_orenderframe_t *rFrame, entity_t ent) + iqm_t *iqm, vulkan_ctx_t *ctx, entity_t ent) { - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - iqmctx_t *ictx = ctx->iqm_context; + auto device = ctx->device; + auto dfunc = device->funcs; + auto ictx = ctx->iqm_context; - __auto_type mesh = (qfv_iqm_t *) iqm->extra_data; + auto mesh = (qfv_iqm_t *) iqm->extra_data; VkDeviceSize offsets[] = { 0, 0, }; VkBuffer buffers[] = { @@ -124,167 +111,6 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, QFV_CmdEndLabel (device, cmd); } -#define a(x) ((x) & ~0x3f) - -void -Vulkan_DrawIQM (entity_t ent, qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - iqmctx_t *ictx = ctx->iqm_context; - iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); - model_t *model = renderer->model; - iqm_t *iqm = (iqm_t *) model->aliashdr; - qfv_iqm_t *mesh = iqm->extra_data; - qfv_iqm_skin_t *skins = mesh->skins; - iqm_push_constants_t constants = {}; - iqmframe_t *frame; - - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - ent.reg); - constants.blend = R_IQMGetLerpedFrames (animation, iqm); - frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2, - constants.blend, 0); - - vec4f_t *bone_data; - dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE, - 0, (void **)&bone_data); - for (int i = 0; i < iqm->num_joints; i++) { - vec4f_t *b = bone_data + (ctx->curFrame * iqm->num_joints + i) * 3; - mat4f_t f; - // R_IQMBlendFrames sets up the frame as a 4x4 matrix for m * v, but - // the shader wants a 3x4 (column x row) matrix for v * m, which is - // just a transpose (and drop of the 4th column) away. - mat4ftranspose (f, (vec4f_t *) &frame[i]); - // copy only the first 3 columns - memcpy (b, f, 3 * sizeof (vec4f_t)); - } - VkMappedMemoryRange range = { - VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, - mesh->bones->memory, - a(3 * ctx->curFrame * iqm->num_joints * sizeof (vec4f_t)), - a(3 * iqm->num_joints * sizeof (vec4f_t) + 0x3f), - }; - dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); - dfunc->vkUnmapMemory (device->dev, mesh->bones->memory); - - transform_t transform = Entity_Transform (ent); - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_VERTEX_BIT, - field_offset (iqm_push_constants_t, mat), - sizeof (mat4f_t), Transform_GetWorldMatrixPtr (transform) }, - { VK_SHADER_STAGE_VERTEX_BIT, - field_offset (iqm_push_constants_t, blend), - sizeof (float), &constants.blend }, - { VK_SHADER_STAGE_FRAGMENT_BIT, - field_offset (iqm_push_constants_t, colorA), - sizeof (constants.colorA), constants.colorA }, - { VK_SHADER_STAGE_FRAGMENT_BIT, - field_offset (iqm_push_constants_t, colorB), - sizeof (constants.colorB), constants.colorB }, - { VK_SHADER_STAGE_FRAGMENT_BIT, - field_offset (iqm_push_constants_t, base_color), - sizeof (constants.base_color), &constants.base_color }, - { VK_SHADER_STAGE_FRAGMENT_BIT, - field_offset (iqm_push_constants_t, fog), - sizeof (constants.fog), &constants.fog }, - }; - - QuatCopy (renderer->colormod, constants.base_color); - QuatCopy (skins[0].colora, constants.colorA); - QuatCopy (skins[0].colorb, constants.colorB); - QuatZero (constants.fog); - - emit_commands (aframe->cmdSet.a[QFV_iqmDepth], - animation->pose1, animation->pose2, - 0, 2, push_constants, iqm, rFrame, ent); - emit_commands (aframe->cmdSet.a[QFV_iqmGBuffer], - animation->pose1, animation->pose2, - skins, 6, push_constants, iqm, rFrame, ent); -} - -static void -iqm_begin_subpass (QFV_IQMSubpass subpass, VkPipeline pipeline, - qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - iqmctx_t *ictx = ctx->iqm_context; - iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = aframe->cmdSet.a[subpass]; - - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - rFrame->renderpass->renderpass, subpass_map[subpass], - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "iqm:%s", - iqm_pass_names[subpass]), - { 0.6, 0.5, 0, 1}); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - VkDescriptorSet sets[] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - }; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - ictx->layout, 0, 1, sets, 0, 0); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - - //XXX glsl_Fog_GetColor (fog); - //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; -} - -static void -iqm_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); -} - -void -Vulkan_IQMBegin (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - iqmctx_t *ictx = ctx->iqm_context; - iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; - - //XXX quat_t fog; - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], - aframe->cmdSet.a[QFV_iqmDepth]); - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], - aframe->cmdSet.a[QFV_iqmGBuffer]); - - iqm_begin_subpass (QFV_iqmDepth, ictx->depth, rFrame); - iqm_begin_subpass (QFV_iqmGBuffer, ictx->gbuf, rFrame); -} - -void -Vulkan_IQMEnd (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - iqmctx_t *ictx = ctx->iqm_context; - iqm_frame_t *aframe = &ictx->frames.a[ctx->curFrame]; - - iqm_end_subpass (aframe->cmdSet.a[QFV_iqmDepth], ctx); - iqm_end_subpass (aframe->cmdSet.a[QFV_iqmGBuffer], ctx); -} - static VkWriteDescriptorSet base_buffer_write = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, 0, 0, 0, 1, @@ -362,12 +188,112 @@ Vulkan_IQMRemoveSkin (vulkan_ctx_t *ctx, qfv_iqm_skin_t *skin) } static void -iqm_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass) { + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); + auto model = renderer->model; + auto iqm = (iqm_t *) model->aliashdr; + qfv_iqm_t *mesh = iqm->extra_data; + auto skins = mesh->skins; + iqm_push_constants_t constants = {}; + iqmframe_t *frame; + + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); + constants.blend = R_IQMGetLerpedFrames (animation, iqm); + frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2, + constants.blend, 0); + + vec4f_t *bone_data; + dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE, + 0, (void **)&bone_data); + for (int i = 0; i < iqm->num_joints; i++) { + vec4f_t *b = bone_data + (ctx->curFrame * iqm->num_joints + i) * 3; + mat4f_t f; + // R_IQMBlendFrames sets up the frame as a 4x4 matrix for m * v, but + // the shader wants a 3x4 (column x row) matrix for v * m, which is + // just a transpose (and drop of the 4th column) away. + mat4ftranspose (f, (vec4f_t *) &frame[i]); + // copy only the first 3 columns + memcpy (b, f, 3 * sizeof (vec4f_t)); + } +#define a(x) ((x) & ~0x3f) + VkMappedMemoryRange range = { + VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, + mesh->bones->memory, + a(3 * ctx->curFrame * iqm->num_joints * sizeof (vec4f_t)), + a(3 * iqm->num_joints * sizeof (vec4f_t) + 0x3f), + }; +#undef a + dfunc->vkFlushMappedMemoryRanges (device->dev, 1, &range); + dfunc->vkUnmapMemory (device->dev, mesh->bones->memory); + + transform_t transform = Entity_Transform (ent); + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_VERTEX_BIT, + field_offset (iqm_push_constants_t, mat), + sizeof (mat4f_t), Transform_GetWorldMatrixPtr (transform) }, + { VK_SHADER_STAGE_VERTEX_BIT, + field_offset (iqm_push_constants_t, blend), + sizeof (float), &constants.blend }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (iqm_push_constants_t, colorA), + sizeof (constants.colorA), constants.colorA }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (iqm_push_constants_t, colorB), + sizeof (constants.colorB), constants.colorB }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (iqm_push_constants_t, base_color), + sizeof (constants.base_color), &constants.base_color }, + { VK_SHADER_STAGE_FRAGMENT_BIT, + field_offset (iqm_push_constants_t, fog), + sizeof (constants.fog), &constants.fog }, + }; + + QuatCopy (renderer->colormod, constants.base_color); + QuatCopy (skins[0].colora, constants.colorA); + QuatCopy (skins[0].colorb, constants.colorB); + QuatZero (constants.fog); + + emit_commands (taskctx->cmd, animation->pose1, animation->pose2, + pass ? skins : 0, + pass ? 6 : 2, push_constants, + iqm, ctx, ent); } +static void +iqm_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + int pass = *(int *) params[0]->value; + + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto ictx = ctx->iqm_context; + auto cmd = taskctx->cmd; + + VkDescriptorSet sets[] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + ictx->layout, 0, 1, sets, 0, 0); + + auto queue = r_ent_queue; //FIXME fetch from scene + for (size_t i = 0; i < queue->ent_queues[mod_iqm].size; i++) { + entity_t ent = queue->ent_queues[mod_iqm].a[i]; + iqm_draw_ent (taskctx, ent, pass); + } +} + +static exprtype_t *iqm_draw_params[] = { + &cexpr_int, +}; static exprfunc_t iqm_draw_func[] = { - { .func = iqm_draw }, + { .func = iqm_draw, .num_params = 1, .param_types = iqm_draw_params }, {} }; static exprsym_t iqm_task_syms[] = { @@ -378,8 +304,6 @@ static exprsym_t iqm_task_syms[] = { void Vulkan_IQM_Init (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfvPushDebug (ctx, "iqm init"); QFV_Render_AddTasks (ctx, iqm_task_syms); @@ -400,22 +324,6 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx) ictx->bones_pool = Vulkan_CreateDescriptorPool (ctx, "bone_pool"); ictx->bones_setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "bone_set"); - for (size_t i = 0; i < frames; i++) { - __auto_type aframe = &ictx->frames.a[i]; - - DARRAY_INIT (&aframe->cmdSet, QFV_iqmNumPasses); - DARRAY_RESIZE (&aframe->cmdSet, QFV_iqmNumPasses); - aframe->cmdSet.grow = 0; - - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &aframe->cmdSet); - - for (int j = 0; j < QFV_iqmNumPasses; j++) { - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - aframe->cmdSet.a[j], - va (ctx->va_ctx, "cmd:iqm:%zd:%s", i, - iqm_pass_names[j])); - } - } qfvPopDebug (ctx); } @@ -426,11 +334,6 @@ Vulkan_IQM_Shutdown (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; iqmctx_t *ictx = ctx->iqm_context; - for (size_t i = 0; i < ictx->frames.size; i++) { - __auto_type aframe = &ictx->frames.a[i]; - free (aframe->cmdSet.a); - } - dfunc->vkDestroyPipeline (device->dev, ictx->depth, 0); dfunc->vkDestroyPipeline (device->dev, ictx->gbuf, 0); free (ictx->frames.a); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index 95816ecd2..bfccc3a4a 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -90,7 +90,6 @@ Vulkan_RenderEntities (entqueue_t *queue, qfv_orenderframe_t *rFrame) Vulkan_##Type##End (rFrame); \ } while (0) - RE_LOOP (iqm, IQM); RE_LOOP (sprite, Sprite); } From 6baab91863a9a890d6966b20b2b3c973d7350399 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jun 2023 17:58:44 +0900 Subject: [PATCH 3639/3664] [scene] Correct some mangled types It was harmless because memory was being over allocated, but it did cause a little confusion. --- libs/scene/efrag.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/scene/efrag.c b/libs/scene/efrag.c index 41dec48b3..45e2d8eb0 100644 --- a/libs/scene/efrag.c +++ b/libs/scene/efrag.c @@ -140,16 +140,16 @@ R_SplitEntityOnNode (mod_brush_t *brush, entity_t ent, uint32_t queue, int sides; efrag_t **lastlink; int *node_stack; - int *node_ptr; + int32_t *node_ptr; - node_stack = alloca ((brush->depth + 2) * sizeof (mnode_t *)); + node_stack = alloca ((brush->depth + 2) * sizeof (int32_t *)); node_ptr = node_stack; lastlink = &visibility->efrag; *node_ptr++ = brush->numnodes; - int node_id = 0; + int32_t node_id = 0; while (node_id != (int) brush->numnodes) { // add an efrag if the node is a leaf if (__builtin_expect (node_id < 0, 0)) { From e4df35ac489a14665f6e59ce146d0ca9069be436 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jun 2023 18:07:40 +0900 Subject: [PATCH 3640/3664] [vulkan] Move scr_funcs handling into vulkan_draw This was necessary to get the 2d elements drawn after the fence had been fired (thus indicating descriptors could be updated) but before actual rendering of the 2d elements (which is how it was done before the switch to the new system). --- include/QF/Vulkan/qf_draw.h | 3 ++ libs/video/renderer/vid_render_vulkan.c | 5 +-- libs/video/renderer/vulkan/rp_main_def.plist | 1 + libs/video/renderer/vulkan/vulkan_draw.c | 36 ++++++++++++++++++-- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 852a012be..7ef57dc82 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -28,6 +28,8 @@ #ifndef __QF_Vulkan_qf_draw_h #define __QF_Vulkan_qf_draw_h +#include "QF/screen.h" + typedef enum { QFV_draw2d, @@ -89,5 +91,6 @@ void Vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c, void Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height, struct vulkan_ctx_s *ctx); +void Vulkan_SetScrFuncs (SCR_Func *scr_funcs, struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_draw_h diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index cb81f7ddd..453132477 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -330,10 +330,7 @@ static void vulkan_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs) { vulkan_set_2d (1);//FIXME - while (*scr_funcs) { - (*scr_funcs) (); - scr_funcs++; - } + Vulkan_SetScrFuncs (scr_funcs, vulkan_ctx); QFV_RunRenderJob (vulkan_ctx); } diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 067daa460..56beb01ea 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1407,6 +1407,7 @@ steps = { tasks = ( { func = wait_on_fence; }, { func = update_matrices; }, + { func = draw_scr_funcs; }, ); }; }; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index be42640ee..d3b3d7411 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -207,6 +207,7 @@ typedef struct drawctx_s { VkDescriptorSet core_quad_set; drawframeset_t frames; drawfontset_t fonts; + SCR_Func *scr_funcs; } drawctx_t; #define MAX_QUADS (32768) @@ -229,7 +230,7 @@ get_dyn_descriptor (descpool_t *pool, qpic_t *pic, VkBufferView buffer_view, { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - __auto_type pd = (picdata_t *) pic->data; + auto pd = (picdata_t *) pic->data; uint32_t id = pd->descid; for (int i = 0; i < pool->in_use; i++) { if (pool->users[i] == id) { @@ -242,9 +243,9 @@ get_dyn_descriptor (descpool_t *pool, qpic_t *pic, VkBufferView buffer_view, int descid = pool->in_use++; pool->users[descid] = id; if (!pool->sets[descid]) { - __auto_type layout = QFV_AllocDescriptorSetLayoutSet (1, alloca); + auto layout = QFV_AllocDescriptorSetLayoutSet (1, alloca); layout->a[0] = pool->dctx->quad_data_set_layout; - __auto_type set = QFV_AllocateDescriptorSet (device, pool->pool, layout); + auto set = QFV_AllocateDescriptorSet (device, pool->pool, layout); pool->sets[descid] = set->a[0];; free (set);//FIXME allocation } @@ -999,6 +1000,23 @@ line_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) dframe->line_verts.count = 0; } +static void +draw_scr_funcs (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto dctx = ctx->draw_context; + auto scr_funcs = dctx->scr_funcs; + if (!scr_funcs) { + return; + } + while (*scr_funcs) { + (*scr_funcs) (); + scr_funcs++; + } + dctx->scr_funcs = 0; +} + static exprfunc_t flush_draw_func[] = { { .func = flush_draw }, {} @@ -1011,10 +1029,15 @@ static exprfunc_t line_draw_func[] = { { .func = line_draw }, {} }; +static exprfunc_t draw_scr_funcs_func[] = { + { .func = draw_scr_funcs }, + {} +}; static exprsym_t draw_task_syms[] = { { "flush_draw", &cexpr_function, flush_draw_func }, { "slice_draw", &cexpr_function, slice_draw_func }, { "line_draw", &cexpr_function, line_draw_func }, + { "draw_scr_funcs", &cexpr_function, draw_scr_funcs_func }, {} }; @@ -1737,3 +1760,10 @@ Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height, x++; } } + +void +Vulkan_SetScrFuncs (SCR_Func *scr_funcs, vulkan_ctx_t *ctx) +{ + auto dctx = ctx->draw_context; + dctx->scr_funcs = scr_funcs; +} From dbe00c3dfa4b8f8b9f5d9e0ce1aad7b27de8f625 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jun 2023 18:12:54 +0900 Subject: [PATCH 3641/3664] [vulkan] Clear the entity queues bsp_draw_queue isn't the right place, but it's just place-holder code to help get the rest of the renderers up and running before I tackle bsp rendering. Fixes the segfault in demo1 when the zombies get gibbed, resulting in zombie entities. --- libs/video/renderer/vulkan/vulkan_bsp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a680b37b0..6974c2254 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1379,6 +1379,7 @@ bsp_draw_queue (const exprval_t **params, exprval_t *result, exprctx_t *ectx) //bctx->main_pass.entid_data = bframe->entid_data; //bctx->main_pass.entid_count = 0; + EntQueue_Clear (r_ent_queue); clear_queues (bctx, &bctx->main_pass); // do this first for water and skys entity_t worldent = nullentity; int world_id = Vulkan_Scene_AddEntity (ctx, worldent); From 87356a52117abd5bdab546bedad887d622717343 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 23 Jun 2023 20:37:06 +0900 Subject: [PATCH 3642/3664] [vulkan] Hook up sprite rendering in the new system That one went smoothly for a change. --- include/QF/Vulkan/qf_main.h | 2 - include/QF/Vulkan/qf_sprite.h | 4 - libs/video/renderer/vulkan/vulkan_main.c | 26 --- libs/video/renderer/vulkan/vulkan_sprite.c | 205 +++++---------------- 4 files changed, 51 insertions(+), 186 deletions(-) diff --git a/include/QF/Vulkan/qf_main.h b/include/QF/Vulkan/qf_main.h index ba6659086..faf8f4b2b 100644 --- a/include/QF/Vulkan/qf_main.h +++ b/include/QF/Vulkan/qf_main.h @@ -36,7 +36,5 @@ struct scene_s; void Vulkan_Main_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_NewScene (struct scene_s *scene, struct vulkan_ctx_s *ctx); void Vulkan_RenderView (struct qfv_orenderframe_s *rFrame); -void Vulkan_RenderEntities (struct entqueue_s *queue, - struct qfv_orenderframe_s *rFrame); #endif//__QF_Vulkan_qf_main_h diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index 827c26216..6a7359942 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -88,10 +88,6 @@ void Vulkan_Sprite_DescriptorSet (struct vulkan_ctx_s *ctx, void Vulkan_Mod_SpriteLoadFrames (struct mod_sprite_ctx_s *sprite_ctx, struct vulkan_ctx_s *ctx); -void Vulkan_SpriteBegin (struct qfv_orenderframe_s *rFrame); -void Vulkan_DrawSprite (struct entity_s ent, struct qfv_orenderframe_s *rFrame); -void Vulkan_SpriteEnd (struct qfv_orenderframe_s *rFrame); - void Vulkan_Sprite_Init (struct vulkan_ctx_s *ctx); void Vulkan_Sprite_Shutdown (struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index bfccc3a4a..a7dc50fec 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -68,31 +68,6 @@ #include "r_internal.h" #include "vid_vulkan.h" -void -Vulkan_RenderEntities (entqueue_t *queue, qfv_orenderframe_t *rFrame) -{ - if (!r_drawentities) - return; - //FIXME need a better way (components? but HasComponent isn't free) -#define RE_LOOP(type_name, Type) \ - do { \ - int begun = 0; \ - for (size_t i = 0; i < queue->ent_queues[mod_##type_name].size; \ - i++) { \ - entity_t ent = queue->ent_queues[mod_##type_name].a[i]; \ - if (!begun) { \ - Vulkan_##Type##Begin (rFrame); \ - begun = 1; \ - } \ - Vulkan_Draw##Type (ent, rFrame); \ - } \ - if (begun) \ - Vulkan_##Type##End (rFrame); \ - } while (0) - - RE_LOOP (sprite, Sprite); -} - static void Vulkan_DrawViewModel (vulkan_ctx_t *ctx) { @@ -127,7 +102,6 @@ Vulkan_RenderView (qfv_orenderframe_t *rFrame) Vulkan_DrawWaterSurfaces (rFrame); Vulkan_DrawParticles (rFrame); Vulkan_Bsp_Flush (ctx); - Vulkan_RenderEntities (r_ent_queue, rFrame); Vulkan_Scene_Flush (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 3f11f58e4..51656b1d4 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -68,24 +68,11 @@ #include "r_internal.h" #include "vid_vulkan.h" -static const char * __attribute__((used)) sprite_pass_names[] = { - "depth", - "g-buffer", - "translucent", -}; - -static QFV_Subpass subpass_map[] = { - QFV_passDepth, // QFV_spriteDepth - QFV_passGBuffer, // QFV_spriteGBuffer - QFV_passTranslucentFrag,// QFV_spriteTranslucent -}; - static void emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, int numPC, qfv_push_constants_t *constants, - qfv_orenderframe_t *rFrame, entity_t ent) + vulkan_ctx_t *ctx, entity_t ent) { - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; spritectx_t *sctx = ctx->sprite_context; @@ -103,123 +90,6 @@ emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, QFV_CmdEndLabel (device, cmd); } -void -Vulkan_DrawSprite (entity_t ent, qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - spritectx_t *sctx = ctx->sprite_context; - spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); - model_t *model = renderer->model; - msprite_t *sprite = model->cache.data; - - mat4f_t mat = {}; - uint32_t frame; - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat), mat }, - { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, - 64, sizeof (frame), &frame }, - }; - - animation_t *animation = Ent_GetComponent (ent.id, scene_animation, - ent.reg); - frame = (ptrdiff_t) R_GetSpriteFrame (sprite, animation); - - transform_t transform = Entity_Transform (ent); - mat[3] = Transform_GetWorldPosition (transform); - vec4f_t cameravec = r_refdef.frame.position - mat[3]; - R_BillboardFrame (transform, sprite->type, cameravec, - &mat[2], &mat[1], &mat[0]); - mat[0] = -mat[0]; - - emit_commands (sframe->cmdSet.a[QFV_spriteDepth], - (qfv_sprite_t *) ((byte *) sprite + sprite->data), - 2, push_constants, rFrame, ent); - emit_commands (sframe->cmdSet.a[QFV_spriteGBuffer], - (qfv_sprite_t *) ((byte *) sprite + sprite->data), - 2, push_constants, rFrame, ent); -} - -static void -sprite_begin_subpass (QFV_SpriteSubpass subpass, VkPipeline pipeline, - qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - spritectx_t *sctx = ctx->sprite_context; - spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = sframe->cmdSet.a[subpass]; - - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - rFrame->renderpass->renderpass, subpass_map[subpass], - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "sprite:%s", - sprite_pass_names[subpass]), - { 0.6, 0.5, 0, 1}); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - VkDescriptorSet sets[] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - }; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - sctx->layout, 0, 1, sets, 0, 0); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - - //XXX glsl_Fog_GetColor (fog); - //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; -} - -static void -sprite_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); -} - -void -Vulkan_SpriteBegin (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - spritectx_t *sctx = ctx->sprite_context; - spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; - - //XXX quat_t fog; - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], - sframe->cmdSet.a[QFV_spriteDepth]); - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], - sframe->cmdSet.a[QFV_spriteGBuffer]); - - sprite_begin_subpass (QFV_spriteDepth, sctx->depth, rFrame); - sprite_begin_subpass (QFV_spriteGBuffer, sctx->gbuf, rFrame); -} - -void -Vulkan_SpriteEnd (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - spritectx_t *sctx = ctx->sprite_context; - spriteframe_t *sframe = &sctx->frames.a[ctx->curFrame]; - - sprite_end_subpass (sframe->cmdSet.a[QFV_spriteDepth], ctx); - sprite_end_subpass (sframe->cmdSet.a[QFV_spriteGBuffer], ctx); -} - static VkDescriptorBufferInfo base_buffer_info = { .range = VK_WHOLE_SIZE, }; @@ -285,9 +155,59 @@ Vulkan_Sprint_FreeDescriptors (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) &sprite->descriptors); } +static void +sprite_draw_ent (qfv_taskctx_t *taskctx, entity_t ent) +{ + auto ctx = taskctx->ctx; + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); + auto model = renderer->model; + msprite_t *sprite = model->cache.data; + + mat4f_t mat = {}; + uint32_t frame; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat), mat }, + { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + 64, sizeof (frame), &frame }, + }; + + animation_t *animation = Ent_GetComponent (ent.id, scene_animation, + ent.reg); + frame = (ptrdiff_t) R_GetSpriteFrame (sprite, animation); + + transform_t transform = Entity_Transform (ent); + mat[3] = Transform_GetWorldPosition (transform); + vec4f_t cameravec = r_refdef.frame.position - mat[3]; + R_BillboardFrame (transform, sprite->type, cameravec, + &mat[2], &mat[1], &mat[0]); + mat[0] = -mat[0]; + + emit_commands (taskctx->cmd, + (qfv_sprite_t *) ((byte *) sprite + sprite->data), + 2, push_constants, ctx, ent); +} + static void sprite_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto sctx = ctx->sprite_context; + auto cmd = taskctx->cmd; + + VkDescriptorSet sets[] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + sctx->layout, 0, 1, sets, 0, 0); + + auto queue = r_ent_queue; //FIXME fetch from scene + for (size_t i = 0; i < queue->ent_queues[mod_sprite].size; i++) { + entity_t ent = queue->ent_queues[mod_sprite].a[i]; + sprite_draw_ent (taskctx, ent); + } } static exprfunc_t sprite_draw_func[] = { @@ -302,8 +222,6 @@ static exprsym_t sprite_task_syms[] = { void Vulkan_Sprite_Init (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfvPushDebug (ctx, "sprite init"); QFV_Render_AddTasks (ctx, sprite_task_syms); @@ -324,22 +242,6 @@ Vulkan_Sprite_Init (vulkan_ctx_t *ctx) sctx->pool = Vulkan_CreateDescriptorPool (ctx, "sprite_pool"); sctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "sprite_set"); - for (size_t i = 0; i < frames; i++) { - __auto_type sframe = &sctx->frames.a[i]; - - DARRAY_INIT (&sframe->cmdSet, QFV_spriteNumPasses); - DARRAY_RESIZE (&sframe->cmdSet, QFV_spriteNumPasses); - sframe->cmdSet.grow = 0; - - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &sframe->cmdSet); - - for (int j = 0; j < QFV_spriteNumPasses; j++) { - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - sframe->cmdSet.a[j], - va (ctx->va_ctx, "cmd:sprite:%zd:%s", i, - sprite_pass_names[j])); - } - } qfvPopDebug (ctx); } @@ -350,11 +252,6 @@ Vulkan_Sprite_Shutdown (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; spritectx_t *sctx = ctx->sprite_context; - for (size_t i = 0; i < sctx->frames.size; i++) { - __auto_type sframe = &sctx->frames.a[i]; - free (sframe->cmdSet.a); - } - dfunc->vkDestroyPipeline (device->dev, sctx->depth, 0); dfunc->vkDestroyPipeline (device->dev, sctx->gbuf, 0); free (sctx->frames.a); From 41d69586d2473c673d7a1d1025ae72ab2b8f83a9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jun 2023 03:26:22 +0900 Subject: [PATCH 3643/3664] [vulkan] Get particles mostly working in the new system The particles die instantly due to curFrame not updating (next commit), but otherwise work nicely, especially sync is better (many thanks to Darian for his help with understanding sync scope). --- include/QF/Vulkan/qf_particles.h | 1 - libs/video/renderer/vulkan/render.c | 15 +- libs/video/renderer/vulkan/rp_main_def.plist | 1 + libs/video/renderer/vulkan/vulkan_main.c | 1 - libs/video/renderer/vulkan/vulkan_particles.c | 461 ++++++------------ 5 files changed, 174 insertions(+), 305 deletions(-) diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index 8cef3fec0..f1663b50c 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -79,7 +79,6 @@ struct qfv_orenderframe_s; struct psystem_s *Vulkan_ParticleSystem (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_DrawParticles (struct qfv_orenderframe_s *rFrame); void Vulkan_Particles_CreateRenderPasses (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_particles_h diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index d8ec6ecc8..d850ef5c7 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -127,6 +127,8 @@ run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) __auto_type job = rctx->job; VkCommandBuffer cmd = QFV_GetCmdBuffer (ctx, false); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, cmd, + va (ctx->va_ctx, "cmd:render:%s", rp->label.name)); VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, }; @@ -188,11 +190,13 @@ run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, 0, 0); } vec4u_t d = pipeline->dispatch; - dfunc->vkCmdDispatch (cmd, d[0], d[1], d[2]); + if (d[0] && d[1] && d[2]) { + dfunc->vkCmdDispatch (cmd, d[0], d[1], d[2]); + } } static void -run_compute (qfv_compute_t *comp, vulkan_ctx_t *ctx) +run_compute (qfv_compute_t *comp, vulkan_ctx_t *ctx, qfv_step_t *step) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -200,6 +204,10 @@ run_compute (qfv_compute_t *comp, vulkan_ctx_t *ctx) __auto_type job = rctx->job; VkCommandBuffer cmd = QFV_GetCmdBuffer (ctx, false); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, cmd, + va (ctx->va_ctx, "cmd:compute:%s", step->label.name)); + QFV_duCmdBeginLabel (device, cmd, step->label.name, + {VEC4_EXP (step->label.color)}); VkCommandBufferBeginInfo beginInfo = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -210,6 +218,7 @@ run_compute (qfv_compute_t *comp, vulkan_ctx_t *ctx) __auto_type pipeline = &comp->pipelines[i]; run_compute_pipeline (pipeline, cmd, ctx); } + QFV_duCmdEndLabel (device, cmd); dfunc->vkEndCommandBuffer (cmd); DARRAY_APPEND (&job->commands, cmd); } @@ -236,7 +245,7 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) run_renderpass (step->render->active, ctx); } if (step->compute) { - run_compute (step->compute, ctx); + run_compute (step->compute, ctx, step); } if (step->process) { run_process (step->process, ctx); diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 56beb01ea..b3dcce749 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1457,6 +1457,7 @@ steps = { tasks = ( { func = update_framebuffer; params = ("\"main\""); }, + { func = particle_wait_physics; }, ); }; }; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index a7dc50fec..d26af38aa 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -100,7 +100,6 @@ Vulkan_RenderView (qfv_orenderframe_t *rFrame) Vulkan_DrawViewModel (ctx); } Vulkan_DrawWaterSurfaces (rFrame); - Vulkan_DrawParticles (rFrame); Vulkan_Bsp_Flush (ctx); Vulkan_Scene_Flush (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 6bd22a0c9..a42a7d404 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -67,119 +67,6 @@ typedef struct { float dT; } particle_push_constants_t; -static const char * __attribute__((used)) particle_pass_names[] = { - "draw", -}; - -static void -particle_begin_subpass (VkPipeline pipeline, qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - particlectx_t *pctx = ctx->particle_context; - uint32_t curFrame = ctx->curFrame; - particleframe_t *pframe = &pctx->frames.a[curFrame]; - VkCommandBuffer cmd = pframe->cmdSet.a[0]; - - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - rFrame->renderpass->renderpass, QFV_passTranslucentFrag, - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "particles:%s", "draw"), - { 0.6, 0.5, 0, 1}); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - VkDescriptorSet sets[] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - Vulkan_Palette_Descriptor (ctx), - Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), - }; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - pctx->draw_layout, 0, 3, sets, 0, 0); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); -} - -static void -particle_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); -} - -void -Vulkan_DrawParticles (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - particlectx_t *pctx = ctx->particle_context; - uint32_t curFrame = ctx->curFrame; - particleframe_t *pframe = &pctx->frames.a[curFrame]; - VkCommandBuffer cmd = pframe->cmdSet.a[0]; - - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFrag], - pframe->cmdSet.a[0]); - - particle_begin_subpass (pctx->draw, rFrame); -/* - VkBufferMemoryBarrier barrier[] = { - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_SHADER_READ_BIT - | VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - 0, 0, - pframe->states, 0, VK_WHOLE_SIZE }, - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_SHADER_READ_BIT - | VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, - 0, 0, - pframe->params, 0, VK_WHOLE_SIZE }, - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_SHADER_READ_BIT - | VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_INDIRECT_COMMAND_READ_BIT, - 0, 0, - pframe->system, 0, VK_WHOLE_SIZE }, - }; - dfunc->vkCmdWaitEvents (cmd, 1, &pframe->physicsEvent, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT - | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - 0, 0, - 3, barrier, - 0, 0); -*/ - mat4f_t mat; - mat4fidentity (mat); - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat4f_t), &mat }, - }; - QFV_PushConstants (device, cmd, pctx->draw_layout, 1, push_constants); - VkDeviceSize offsets[] = { 0 }; - VkBuffer buffers[] = { - pframe->states, - }; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, buffers, offsets); - dfunc->vkCmdDrawIndirect (cmd, pframe->system, 0, 1, - sizeof (qfv_particle_system_t)); - particle_end_subpass (cmd, ctx); -} - static void create_buffers (vulkan_ctx_t *ctx) { @@ -187,8 +74,7 @@ create_buffers (vulkan_ctx_t *ctx) qfv_devfuncs_t *dfunc = device->funcs; particlectx_t *pctx = ctx->particle_context; size_t mp = MaxParticles; - auto rctx = ctx->render_context; - size_t frames = rctx->frames.size; + size_t frames = pctx->frames.size; pctx->resources = malloc (sizeof (qfv_resource_t) // states buffer @@ -209,7 +95,7 @@ create_buffers (vulkan_ctx_t *ctx) }; for (size_t i = 0; i < frames; i++) { state_objs[i] = (qfv_resobj_t) { - .name = "states", + .name = va (ctx->va_ctx, "states:%zd", i), .type = qfv_res_buffer, .buffer = { .size = mp * sizeof (qfv_particle_t), @@ -218,7 +104,7 @@ create_buffers (vulkan_ctx_t *ctx) }, }; param_objs[i] = (qfv_resobj_t) { - .name = "params", + .name = va (ctx->va_ctx, "param:%zd", i), .type = qfv_res_buffer, .buffer = { .size = mp * sizeof (qfv_parameters_t), @@ -226,7 +112,7 @@ create_buffers (vulkan_ctx_t *ctx) }, }; system_objs[i] = (qfv_resobj_t) { - .name = "system", + .name = va (ctx->va_ctx, "system:%zd", i), .type = qfv_res_buffer, .buffer = { .size = sizeof (qfv_particle_system_t), @@ -277,19 +163,46 @@ create_buffers (vulkan_ctx_t *ctx) static void particles_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto pctx = ctx->particle_context; + auto pframe = &pctx->frames.a[ctx->curFrame]; + auto cmd = taskctx->cmd; + + VkDescriptorSet sets[] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + Vulkan_Palette_Descriptor (ctx), + Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + pctx->draw_layout, 0, 3, sets, 0, 0); + + mat4f_t mat; + mat4fidentity (mat); + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat4f_t), &mat }, + }; + QFV_PushConstants (device, cmd, pctx->draw_layout, 1, push_constants); + VkDeviceSize offsets[] = { 0 }; + VkBuffer buffers[] = { + pframe->states, + }; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, buffers, offsets); + dfunc->vkCmdDrawIndirect (cmd, pframe->system, 0, 1, + sizeof (qfv_particle_system_t)); } static void -update_particles (const exprval_t **_params, exprval_t *result, exprctx_t *ectx) +update_particles (const exprval_t **p, exprval_t *result, exprctx_t *ectx) { - __auto_type taskctx = (qfv_taskctx_t *) ectx; - vulkan_ctx_t *ctx = taskctx->ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; -// VkDevice dev = device->dev; - - particlectx_t *pctx = ctx->particle_context; - __auto_type pframe = &pctx->frames.a[ctx->curFrame]; + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto pctx = ctx->particle_context; + auto pframe = &pctx->frames.a[ctx->curFrame]; qfv_packet_t *packet = QFV_PacketAcquire (pctx->stage); @@ -310,9 +223,9 @@ update_particles (const exprval_t **_params, exprval_t *result, exprctx_t *ectx) .vertexCount = 1, .particleCount = numParticles, }; - __auto_type particles = (qfv_particle_t *) ((byte *)system + partoffs); + auto particles = (qfv_particle_t *) ((byte *) system + partoffs); memcpy (particles, pctx->psystem->particles, partsize); - qfv_parameters_t *params = (qfv_parameters_t *)((byte *)system + paramoffs); + auto params = (qfv_parameters_t *) ((byte *) system + paramoffs); memcpy (params, pctx->psystem->partparams, paramsize); if (!numParticles) { @@ -342,32 +255,98 @@ update_particles (const exprval_t **_params, exprval_t *result, exprctx_t *ectx) }; dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); - __auto_type pipeline = taskctx->pipeline; - pipeline->dispatch = (vec4u_t) {1, 1, 1}; - pipeline->num_descriptorsets = 3; - pipeline->descriptorsets[0] = pframe->curDescriptors; - pipeline->descriptorsets[1] = pframe->inDescriptors; - pipeline->descriptorsets[2] = pframe->newDescriptors; + dfunc->vkResetEvent (device->dev, pframe->updateEvent); + VkBufferMemoryBarrier pl_barrier[] = { + { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, + .srcAccessMask = VK_ACCESS_HOST_WRITE_BIT, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .buffer = packet->stage->buffer, + .offset = sysoffs, + .size = paramoffs + paramsize, + }, + }; + dfunc->vkCmdPipelineBarrier (packet->cmd, + VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + 0, + 0, 0, + 1, pl_barrier, + 0, 0); + + dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, + pctx->update); + VkDescriptorSet set[3] = { + pframe->curDescriptors, + pframe->inDescriptors, + pframe->newDescriptors, + }; + dfunc->vkCmdBindDescriptorSets (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, + pctx->update_layout, 0, 3, set, 0, 0); + dfunc->vkCmdDispatch (packet->cmd, 1, 1, 1); + dfunc->vkCmdSetEvent (packet->cmd, pframe->updateEvent, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); QFV_PacketSubmit (packet); pctx->psystem->numparticles = 0; } +static void +wait_on_event (VkBuffer states, VkBuffer params, VkBuffer system, + VkEvent event, bool draw, VkCommandBuffer cmd, + qfv_devfuncs_t *dfunc) +{ + VkStructureType type = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; + VkAccessFlags srcAccess = draw + ? VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT + : VK_ACCESS_SHADER_WRITE_BIT; + VkAccessFlags dstAccess = draw + ? VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT + : VK_ACCESS_SHADER_READ_BIT + | VK_ACCESS_SHADER_WRITE_BIT; + VkBufferMemoryBarrier barrier[] = { + { .sType = type, + .srcAccessMask = srcAccess, .dstAccessMask = dstAccess, + .buffer = states, .offset = 0, .size = VK_WHOLE_SIZE }, + { .sType = type, + .srcAccessMask = srcAccess, .dstAccessMask = dstAccess, + .buffer = params, .offset = 0, .size = VK_WHOLE_SIZE }, + { .sType = type, + .srcAccessMask = srcAccess, .dstAccessMask = dstAccess, + .buffer = system, .offset = 0, .size = VK_WHOLE_SIZE }, + }; + VkAccessFlags srcStage = draw + ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT + : VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + VkAccessFlags dstStage = draw + ? VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT + | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT + : VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + dfunc->vkCmdWaitEvents (cmd, 1, &event, srcStage, dstStage, + 0, 0, 3, barrier, 0, 0); +} + static void particle_physics (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { - __auto_type taskctx = (qfv_taskctx_t *) ectx; - vulkan_ctx_t *ctx = taskctx->ctx; - qfv_device_t *device = ctx->device; + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto pctx = ctx->particle_context; + auto pframe = &pctx->frames.a[ctx->curFrame]; + auto cmd = taskctx->cmd; - particlectx_t *pctx = ctx->particle_context; - __auto_type pframe = &pctx->frames.a[ctx->curFrame]; + dfunc->vkResetEvent (device->dev, pframe->physicsEvent); + wait_on_event (pframe->states, pframe->params, pframe->system, + pframe->updateEvent, false, cmd, dfunc); - __auto_type pipeline = taskctx->pipeline; - pipeline->dispatch = (vec4u_t) {MaxParticles, 1, 1}; - pipeline->num_descriptorsets = 1; - pipeline->descriptorsets[0] = pframe->curDescriptors; + VkDescriptorSet set[] = { + pframe->curDescriptors, + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_COMPUTE, + pctx->physics_layout, 0, 1, set, 0, 0); particle_push_constants_t constants = { .gravity = pctx->psystem->gravity, @@ -381,8 +360,38 @@ particle_physics (const exprval_t **params, exprval_t *result, exprctx_t *ectx) field_offset (particle_push_constants_t, dT), sizeof (float), &constants.dT }, }; - QFV_PushConstants (device, taskctx->cmd, pipeline->layout, - 2, push_constants); + QFV_PushConstants (device, cmd, pctx->physics_layout, 2, push_constants); + dfunc->vkCmdDispatch (cmd, MaxParticles, 1, 1); + dfunc->vkCmdSetEvent (cmd, pframe->physicsEvent, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); +} + +static void +particle_wait_physics (const exprval_t **params, exprval_t *result, + exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto pctx = ctx->particle_context; + auto pframe = &pctx->frames.a[ctx->curFrame]; + + auto cmd = QFV_GetCmdBuffer (ctx, false); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, cmd, + va (ctx->va_ctx, "cmd:particle_wait_physics:%d", + ctx->curFrame)); + QFV_AppendCmdBuffer (ctx, cmd); + VkCommandBufferBeginInfo beginInfo = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + }; + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + wait_on_event (pframe->states, pframe->params, pframe->system, + pframe->physicsEvent, true, cmd, dfunc); + + dfunc->vkEndCommandBuffer (cmd); } static exprfunc_t particles_draw_func[] = { @@ -397,10 +406,15 @@ static exprfunc_t particle_physics_func[] = { { .func = particle_physics }, {} }; +static exprfunc_t particle_wait_physics_func[] = { + { .func = particle_wait_physics }, + {} +}; static exprsym_t particles_task_syms[] = { { "particles_draw", &cexpr_function, particles_draw_func }, { "update_particles", &cexpr_function, update_particles_func }, { "particle_physics", &cexpr_function, particle_physics_func }, + { "particle_wait_physics", &cexpr_function, particle_wait_physics_func }, {} }; @@ -417,8 +431,7 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) ctx->particle_context = pctx; pctx->psystem = &r_psystem; - auto rctx = ctx->render_context; - size_t frames = rctx->frames.size; + size_t frames = ctx->render_context->frames.size; DARRAY_INIT (&pctx->frames, frames); DARRAY_RESIZE (&pctx->frames, frames); pctx->frames.grow = 0; @@ -448,19 +461,6 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) pframe->inDescriptors = sets->a[i * 3 + 1]; pframe->newDescriptors = sets->a[i * 3 + 2]; - DARRAY_INIT (&pframe->cmdSet, QFV_particleNumPasses); - DARRAY_RESIZE (&pframe->cmdSet, QFV_particleNumPasses); - pframe->cmdSet.grow = 0; - - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &pframe->cmdSet); - - for (int j = 0; j < QFV_particleNumPasses; j++) { - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - pframe->cmdSet.a[j], - va (ctx->va_ctx, "cmd:particle:%zd:%s", i, - particle_pass_names[j])); - } - VkEventCreateInfo event = { VK_STRUCTURE_TYPE_EVENT_CREATE_INFO }; dfunc->vkCreateEvent (device->dev, &event, 0, &pframe->physicsEvent); dfunc->vkCreateEvent (device->dev, &event, 0, &pframe->updateEvent); @@ -510,145 +510,6 @@ Vulkan_ParticleSystem (vulkan_ctx_t *ctx) static void particles_update (qfv_orenderframe_t *rFrame) { - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - particlectx_t *pctx = ctx->particle_context; - __auto_type pframe = &pctx->frames.a[ctx->curFrame]; - - qfv_packet_t *packet = QFV_PacketAcquire (pctx->stage); - - __auto_type limits = &device->physDev->properties->limits; - VkMemoryRequirements req = { - .alignment = limits->minStorageBufferOffsetAlignment - }; - uint32_t numParticles = min (MaxParticles, pctx->psystem->numparticles); - size_t syssize = sizeof (qfv_particle_system_t); - size_t partoffs = QFV_NextOffset (syssize, &req); - size_t partsize = sizeof (qfv_particle_t) * numParticles; - size_t paramoffs = QFV_NextOffset (partoffs + partsize, &req); - size_t paramsize = sizeof (qfv_parameters_t) * numParticles; - size_t size = paramoffs + paramsize; - - qfv_particle_system_t *system = QFV_PacketExtend (packet, size); - *system = (qfv_particle_system_t) { - .vertexCount = 1, - .particleCount = numParticles, - }; - __auto_type particles = (qfv_particle_t *) ((byte *)system + partoffs); - memcpy (particles, pctx->psystem->particles, partsize); - qfv_parameters_t *params = (qfv_parameters_t *)((byte *)system + paramoffs); - memcpy (params, pctx->psystem->partparams, paramsize); - - if (!numParticles) { - // if there are no particles, then no space for the particle states or - // parameters has been allocated in the staging buffer, so map the - // two buffers over the system buffer. This avoids either buffer being - // just past the end of the staging buffer (which the validation layers - // (correctly) do not like). - // This is fine because the two buffers are only read by the compute - // shader. - partsize = paramsize = syssize; - partoffs = paramoffs = 0; - } - - size_t sysoffs = packet->offset; - VkDescriptorBufferInfo bufferInfo[] = { - { packet->stage->buffer, sysoffs + partoffs, partsize}, - { packet->stage->buffer, sysoffs + paramoffs, paramsize}, - { packet->stage->buffer, sysoffs, syssize }, - }; - VkWriteDescriptorSet write[] = { - { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - pframe->newDescriptors, 0, 0, 3, - VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - .pBufferInfo = bufferInfo - }, - }; - dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); - - dfunc->vkResetEvent (device->dev, pframe->updateEvent); - dfunc->vkResetEvent (device->dev, pframe->physicsEvent); - - VkBufferMemoryBarrier pl_barrier[] = { - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - 0, - VK_ACCESS_SHADER_READ_BIT, - 0, 0, - packet->stage->buffer, sysoffs, paramoffs + paramsize }, - }; - dfunc->vkCmdPipelineBarrier (packet->cmd, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - 0, - 0, 0, - 1, pl_barrier, - 0, 0); - - dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, - pctx->update); - VkDescriptorSet set[3] = { - pframe->curDescriptors, - pframe->inDescriptors, - pframe->newDescriptors, - }; - dfunc->vkCmdBindDescriptorSets (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, - pctx->update_layout, 0, 3, set, 0, 0); - dfunc->vkCmdDispatch (packet->cmd, 1, 1, 1); - dfunc->vkCmdSetEvent (packet->cmd, pframe->updateEvent, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - - VkBufferMemoryBarrier ev_barrier[] = { - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT - | VK_ACCESS_SHADER_WRITE_BIT, - 0, 0, - pframe->states, 0, VK_WHOLE_SIZE }, - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT - | VK_ACCESS_SHADER_WRITE_BIT, - 0, 0, - pframe->params, 0, VK_WHOLE_SIZE }, - { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 0, - VK_ACCESS_SHADER_WRITE_BIT, - VK_ACCESS_SHADER_READ_BIT - | VK_ACCESS_SHADER_WRITE_BIT, - 0, 0, - pframe->system, 0, VK_WHOLE_SIZE }, - }; - dfunc->vkCmdWaitEvents (packet->cmd, 1, &pframe->updateEvent, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - 0, 0, - 3, ev_barrier, - 0, 0); - dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, - pctx->physics); - dfunc->vkCmdBindDescriptorSets (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, - pctx->physics_layout, 0, 1, set, 0, 0); - - particle_push_constants_t constants = { - .gravity = pctx->psystem->gravity, - .dT = vr_data.frametime, - }; - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_COMPUTE_BIT, - field_offset (particle_push_constants_t, gravity), - sizeof (vec4f_t), &constants.gravity }, - { VK_SHADER_STAGE_COMPUTE_BIT, - field_offset (particle_push_constants_t, dT), - sizeof (float), &constants.dT }, - }; - QFV_PushConstants (device, packet->cmd, pctx->physics_layout, - 2, push_constants); - dfunc->vkCmdDispatch (packet->cmd, MaxParticles, 1, 1); - //dfunc->vkCmdSetEvent (packet->cmd, pframe->physicsEvent, - // VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); - QFV_PacketSubmit (packet); - - pctx->psystem->numparticles = 0; } void From 4abf316f6c9dc680c98376e7cbd5c659dd0896fe Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jun 2023 03:32:21 +0900 Subject: [PATCH 3644/3664] [vulkan] Update curFrame at end of render job This fixes the insta-death of particles. Interestingly, other than particles (due to the ring of buffers not being used correctly), everything else worked nicely, so I guess 1-frame rendering got tested. --- libs/video/renderer/vulkan/render.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index d850ef5c7..1767b76cb 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -276,6 +276,10 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) 0 }; dfunc->vkQueuePresentKHR (queue->queue, &presentInfo); + + if (++ctx->curFrame >= rctx->frames.size) { + ctx->curFrame = 0; + } } static VkImageView __attribute__((pure)) From 5140346c220ce43f57f5ceeb3c3b2ae18b7861e8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jun 2023 10:34:18 +0900 Subject: [PATCH 3645/3664] [vulkan] Nuke the old render pass code from orbit Gotta be sure :) With the new system mostly up and running (just bsp rendering and descriptor sets/layout handling to go, and they're independent of the old render pass system), the old system can finally be cleared out. --- include/QF/Makemodule.am | 1 - include/QF/Vulkan/qf_alias.h | 1 - include/QF/Vulkan/qf_bsp.h | 4 - include/QF/Vulkan/qf_compose.h | 1 - include/QF/Vulkan/qf_iqm.h | 1 - include/QF/Vulkan/qf_lighting.h | 4 - include/QF/Vulkan/qf_main.h | 3 - include/QF/Vulkan/qf_output.h | 1 - include/QF/Vulkan/qf_particles.h | 2 - include/QF/Vulkan/qf_renderpass.h | 80 ---- include/QF/Vulkan/qf_sprite.h | 1 - include/QF/Vulkan/qf_translucent.h | 11 - include/QF/Vulkan/qf_vid.h | 2 - include/vid_vulkan.h | 1 - libs/video/renderer/Makemodule.am | 1 - libs/video/renderer/vid_render_vulkan.c | 3 - libs/video/renderer/vulkan/rp_main_def.plist | 1 + libs/video/renderer/vulkan/vkparse.c | 76 ---- libs/video/renderer/vulkan/vkparse.h | 5 +- libs/video/renderer/vulkan/vkparse.plist | 1 - libs/video/renderer/vulkan/vulkan_alias.c | 2 - libs/video/renderer/vulkan/vulkan_bsp.c | 31 +- libs/video/renderer/vulkan/vulkan_compose.c | 2 - libs/video/renderer/vulkan/vulkan_draw.c | 5 +- libs/video/renderer/vulkan/vulkan_iqm.c | 3 - libs/video/renderer/vulkan/vulkan_lighting.c | 16 +- libs/video/renderer/vulkan/vulkan_main.c | 26 +- libs/video/renderer/vulkan/vulkan_matrices.c | 2 +- libs/video/renderer/vulkan/vulkan_output.c | 64 +-- libs/video/renderer/vulkan/vulkan_particles.c | 19 +- .../video/renderer/vulkan/vulkan_renderpass.c | 380 ------------------ libs/video/renderer/vulkan/vulkan_sprite.c | 3 - .../renderer/vulkan/vulkan_translucent.c | 86 +--- .../video/renderer/vulkan/vulkan_vid_common.c | 30 -- 34 files changed, 36 insertions(+), 833 deletions(-) delete mode 100644 include/QF/Vulkan/qf_renderpass.h delete mode 100644 libs/video/renderer/vulkan/vulkan_renderpass.c diff --git a/include/QF/Makemodule.am b/include/QF/Makemodule.am index 8957a39d8..bfeeaa4dd 100644 --- a/include/QF/Makemodule.am +++ b/include/QF/Makemodule.am @@ -208,7 +208,6 @@ include_qf_vulkan = \ include/QF/Vulkan/qf_output.h \ include/QF/Vulkan/qf_palette.h \ include/QF/Vulkan/qf_particles.h \ - include/QF/Vulkan/qf_renderpass.h \ include/QF/Vulkan/qf_scene.h \ include/QF/Vulkan/qf_sprite.h \ include/QF/Vulkan/qf_texture.h \ diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index cdcc52a51..a7f2cda41 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -89,7 +89,6 @@ typedef struct aliasctx_s { } aliasctx_t; struct vulkan_ctx_s; -struct qfv_orenderframe_s; struct entity_s; struct mod_alias_ctx_s; diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 3e18774a6..99a558dfc 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -386,10 +386,6 @@ typedef struct bspctx_s { } bspctx_t; struct vulkan_ctx_s; -struct qfv_orenderframe_s; -void Vulkan_DrawWorld (struct qfv_orenderframe_s *rFrame); -void Vulkan_DrawSky (struct qfv_orenderframe_s *rFrame); -void Vulkan_DrawWaterSurfaces (struct qfv_orenderframe_s *rFrame); void Vulkan_Bsp_Flush (struct vulkan_ctx_s *ctx); void Vulkan_LoadSkys (const char *sky, struct vulkan_ctx_s *ctx); void Vulkan_RegisterTextures (model_t **models, int num_models, diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h index efb61b701..d777080ce 100644 --- a/include/QF/Vulkan/qf_compose.h +++ b/include/QF/Vulkan/qf_compose.h @@ -54,7 +54,6 @@ typedef struct composectx_s { } composectx_t; struct vulkan_ctx_s; -struct qfv_orenderframe_s; void Vulkan_Compose_Init (struct vulkan_ctx_s *ctx); void Vulkan_Compose_Shutdown (struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h index 83599625b..88057f441 100644 --- a/include/QF/Vulkan/qf_iqm.h +++ b/include/QF/Vulkan/qf_iqm.h @@ -98,7 +98,6 @@ typedef struct iqmctx_s { } iqmctx_t; struct vulkan_ctx_s; -struct qfv_orenderframe_s; struct entity_s; struct mod_iqm_ctx_s; struct iqm_s; diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index e314b3051..b6c8437e8 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -35,7 +35,6 @@ #include "QF/modelgen.h" #include "QF/scene/light.h" #include "QF/Vulkan/qf_vid.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/image.h" #include "QF/simd/types.h" @@ -105,7 +104,6 @@ typedef struct lightingctx_s { qfv_imageset_t light_images; light_renderer_set_t light_renderers; - qfv_orenderpass_t *qfv_renderpass; VkRenderPass renderpass_6; VkRenderPass renderpass_4; VkRenderPass renderpass_1; @@ -117,9 +115,7 @@ typedef struct lightingctx_s { } lightingctx_t; struct vulkan_ctx_s; -struct qfv_orenderframe_s; -void Vulkan_Lighting_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_LoadLights (struct scene_s *scene, struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_main.h b/include/QF/Vulkan/qf_main.h index faf8f4b2b..d17053dca 100644 --- a/include/QF/Vulkan/qf_main.h +++ b/include/QF/Vulkan/qf_main.h @@ -29,12 +29,9 @@ #define __QF_Vulkan_qf_main_h struct vulkan_ctx_s; -struct qfv_orenderframe_s; struct entqueue_s; struct scene_s; -void Vulkan_Main_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_NewScene (struct scene_s *scene, struct vulkan_ctx_s *ctx); -void Vulkan_RenderView (struct qfv_orenderframe_s *rFrame); #endif//__QF_Vulkan_qf_main_h diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index d5436216d..c81495082 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -60,7 +60,6 @@ struct vulkan_ctx_s; void Vulkan_Output_Init (struct vulkan_ctx_s *ctx); void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Output_CreateRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_Output_SetInput (struct vulkan_ctx_s *ctx, VkImageView input); #endif//__QF_Vulkan_qf_output_h diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index f1663b50c..381a8edad 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -74,11 +74,9 @@ typedef struct particlectx_s { struct cvar_s; struct vulkan_ctx_s; -struct qfv_orenderframe_s; struct psystem_s *Vulkan_ParticleSystem (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Particles_CreateRenderPasses (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_particles_h diff --git a/include/QF/Vulkan/qf_renderpass.h b/include/QF/Vulkan/qf_renderpass.h deleted file mode 100644 index 41076d25c..000000000 --- a/include/QF/Vulkan/qf_renderpass.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef __QF_Vulkan_qf_renderpass_h -#define __QF_Vulkan_qf_renderpass_h - -#ifndef VK_NO_PROTOTYPES -#define VK_NO_PROTOTYPES -#endif -#include - -#include "QF/darray.h" -#include "QF/simd/types.h" - -#include "QF/Vulkan/render.h" - -typedef struct qfv_framebufferset_s - DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t; - -#define QFV_AllocFrameBuffers(num, allocator) \ - DARRAY_ALLOCFIXED (qfv_framebufferset_t, num, allocator) - -typedef struct qfv_osubpass_s { - vec4f_t color; - const char *name; -} qfv_osubpass_t; - -typedef struct qfv_subpassset_s - DARRAY_TYPE (qfv_osubpass_t) qfv_subpassset_t; - -typedef struct qfv_orenderframe_s { - struct vulkan_ctx_s *vulkan_ctx; - struct qfv_orenderpass_s *renderpass; - VkSubpassContents subpassContents; - VkFramebuffer framebuffer; - int subpassCount; - qfv_osubpass_t *subpassInfo; - struct qfv_cmdbufferset_s *subpassCmdSets; -} qfv_orenderframe_t; - -typedef struct qfv_orenderframeset_s - DARRAY_TYPE (qfv_orenderframe_t) qfv_orenderframeset_t; - -typedef struct clearvalueset_s - DARRAY_TYPE (VkClearValue) clearvalueset_t; - -typedef void (*qfv_draw_t) (qfv_orenderframe_t *rFrame); - -typedef struct qfv_orenderpass_s { - struct vulkan_ctx_s *vulkan_ctx; - vec4f_t color; // for debugging - const char *name; // for debugging - struct plitem_s *renderpassDef; - VkRenderPass renderpass; - clearvalueset_t *clearValues; - struct qfv_imageset_s *attachment_images; - struct qfv_imageviewset_s *attachment_views; - VkDeviceMemory attachmentMemory; - size_t attachmentMemory_size; - - qfv_output_t output; - qfv_framebufferset_t *framebuffers; - VkViewport viewport; - VkRect2D scissor; - VkRect2D renderArea; - int order; - int primary_commands; - size_t subpassCount; - qfv_subpassset_t *subpass_info; - qfv_orenderframeset_t frames; - - qfv_draw_t draw; -} qfv_orenderpass_t; - -qfv_orenderpass_t *QFV_RenderPass_New (struct vulkan_ctx_s *ctx, - const char *name, qfv_draw_t draw); -void QFV_RenderPass_Delete (qfv_orenderpass_t *renderpass); -void QFV_RenderPass_CreateAttachments (qfv_orenderpass_t *renderpass); -void QFV_RenderPass_CreateRenderPass (qfv_orenderpass_t *renderpass); -void QFV_RenderPass_CreateFramebuffer (qfv_orenderpass_t *renderpass); - - -#endif//__QF_Vulkan_qf_renderpass_h diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index 6a7359942..8e1fdf52f 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -77,7 +77,6 @@ typedef struct spritectx_s { } spritectx_t; struct vulkan_ctx_s; -struct qfv_orenderframe_s; struct entity_s; struct mod_sprite_ctx_s; diff --git a/include/QF/Vulkan/qf_translucent.h b/include/QF/Vulkan/qf_translucent.h index cd35dc6a0..a62ba8a57 100644 --- a/include/QF/Vulkan/qf_translucent.h +++ b/include/QF/Vulkan/qf_translucent.h @@ -18,18 +18,10 @@ typedef struct qfv_transtate_s { int32_t maxFragments; } qfv_transtate_t; -typedef enum { - QFV_translucentClear, - QFV_translucentBlend, - - QFV_translucentNumPasses -} QFV_TranslucentSubpass; - typedef struct translucentframe_s { VkDescriptorSet descriptors; VkImage heads; VkBuffer state; - qfv_cmdbufferset_t cmdSet; } translucentframe_t; typedef struct translucentframeset_s @@ -46,15 +38,12 @@ typedef struct translucentctx_s { } translucentctx_t; struct vulkan_ctx_s; -struct qfv_orenderframe_s; void Vulkan_Translucent_Init (struct vulkan_ctx_s *ctx); void Vulkan_Translucent_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Translucent_Draw (struct qfv_orenderframe_s *rFrame); VkDescriptorSet Vulkan_Translucent_Descriptors (struct vulkan_ctx_s *ctx, int frame)__attribute__((pure)); void Vulkan_Translucent_CreateBuffers (struct vulkan_ctx_s *ctx, VkExtent2D extent); -void Vulkan_Translucent_CreateRenderPasses (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_translucent_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index 986bfc3a1..cdfe24908 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -70,8 +70,6 @@ enum { struct vulkan_ctx_s; void Vulkan_CreateCapture (struct vulkan_ctx_s *ctx); -void Vulkan_CreateRenderPasses (struct vulkan_ctx_s *ctx); -void Vulkan_DestroyRenderPasses (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 9041ac23d..85eaaa22e 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -56,7 +56,6 @@ typedef struct vulkan_ctx_s { struct qfv_stagebuf_s *staging; uint32_t curFrame; qfv_renderpassset_t renderPasses; - struct qfv_orenderpass_s *output_renderpass; struct qfv_capture_s *capture; void (*capture_callback) (const byte *data, int width, int height); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 728c20e48..1183f8e94 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -254,7 +254,6 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vulkan_output.c \ libs/video/renderer/vulkan/vulkan_palette.c \ libs/video/renderer/vulkan/vulkan_particles.c \ - libs/video/renderer/vulkan/vulkan_renderpass.c \ libs/video/renderer/vulkan/vulkan_scene.c \ libs/video/renderer/vulkan/vulkan_sprite.c \ libs/video/renderer/vulkan/vulkan_texture.c \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 453132477..89ef8c021 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -53,7 +53,6 @@ #include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_particles.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_sprite.h" #include "QF/Vulkan/qf_texture.h" @@ -100,7 +99,6 @@ vulkan_R_Init (void) Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); - Vulkan_CreateRenderPasses (vulkan_ctx); Vulkan_Output_Init (vulkan_ctx); Vulkan_Matrix_Init (vulkan_ctx); @@ -579,7 +577,6 @@ vulkan_vid_render_shutdown (void) Vulkan_Scene_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx); - Vulkan_DestroyRenderPasses (vulkan_ctx); Vulkan_Output_Shutdown (vulkan_ctx); Vulkan_Palette_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index b3dcce749..e1f2a02ff 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1453,6 +1453,7 @@ steps = { }; }; setup_main = { + dependencies = (wait_on_fence); process = { tasks = ( { func = update_framebuffer; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 5c1b5ab5a..d635be753 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -45,8 +45,6 @@ #include "QF/Vulkan/render.h" #include "QF/Vulkan/shader.h" -#include "QF/Vulkan/qf_renderpass.h" - #include "vid_vulkan.h" #include "vkparse.h" @@ -1695,80 +1693,6 @@ QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) return framebuffer; } -static int -parse_clearvalueset (const plfield_t *field, const plitem_t *item, void *data, - plitem_t *messages, void *context) -{ - plelement_t element = { - QFDictionary, - sizeof (VkClearValue), - vkparse_alloc, - parse_VkClearValue, - 0, - }; - plfield_t f = { 0, 0, 0, 0, &element }; - - if (!PL_ParseArray (&f, item, data, messages, context)) { - return 0; - } - return 1; -} - -clearvalueset_t * -QFV_ParseClearValues (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) -{ - clearvalueset_t *cv = 0; - memsuper_t *memsuper = new_memsuper (); - clearvalueset_t *clearValues = 0; - - if (parse_object (ctx, memsuper, plist, parse_clearvalueset, &clearValues, - properties)) { - cv = DARRAY_ALLOCFIXED (clearvalueset_t, clearValues->size, malloc); - memcpy (cv->a, clearValues->a, cv->size * sizeof (cv->a[0])); - } - delete_memsuper (memsuper); - return cv; -} - -static int -parse_subpassset (const plfield_t *field, const plitem_t *item, void *data, - plitem_t *messages, void *context) -{ - plelement_t element = { - QFDictionary, - sizeof (qfv_osubpass_t), - vkparse_alloc, - parse_qfv_osubpass_t, - 0, - }; - plfield_t f = { 0, 0, 0, 0, &element }; - - if (!PL_ParseArray (&f, item, data, messages, context)) { - return 0; - } - return 1; -} - -qfv_subpassset_t * -QFV_ParseSubpasses (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) -{ - qfv_subpassset_t *sp = 0; - memsuper_t *memsuper = new_memsuper (); - qfv_subpassset_t *subpasses = 0; - - if (parse_object (ctx, memsuper, plist, parse_subpassset, &subpasses, - properties)) { - sp = DARRAY_ALLOCFIXED (qfv_subpassset_t, subpasses->size, malloc); - memcpy (sp->a, subpasses->a, sp->size * sizeof (sp->a[0])); - // the name is in memsuper which is about to be freed - for (size_t i = 0; i < sp->size; i++) { - sp->a[i].name = strdup (sp->a[i].name); - } - } - delete_memsuper (memsuper); - return sp; -} - static int parse_rgba (const plfield_t *field, const plitem_t *item, void *data, plitem_t *messages, void *context) diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index 207fef028..ebc1a691f 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -1,6 +1,8 @@ #ifndef __vkparse_h #define __vkparse_h +#include "QF/Vulkan/render.h" + typedef struct parsectx_s { struct exprctx_s *ectx; struct vulkan_ctx_s *vctx; @@ -66,9 +68,6 @@ struct qfv_imageviewset_s *QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *properties); VkFramebuffer QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties); -struct clearvalueset_s *QFV_ParseClearValues (vulkan_ctx_t *ctx, - plitem_t *plist, - plitem_t *properties); struct qfv_subpassset_s *QFV_ParseSubpasses (vulkan_ctx_t *ctx, plitem_t *plist, diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 530702856..9fac09874 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -30,7 +30,6 @@ search = ( VkRenderPassCreateInfo, VkRenderPassMultiviewCreateInfo, - qfv_osubpass_t, qfv_output_t, qfv_descriptorsetlayoutinfo_t, diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index ec0126624..3c68a55c9 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -252,8 +252,6 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&actx->frames, frames); actx->frames.grow = 0; - actx->depth = Vulkan_CreateGraphicsPipeline (ctx, "alias_depth"); - actx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "alias_gbuf"); actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); qfvPopDebug (ctx); diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 6974c2254..471172ded 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -57,7 +57,6 @@ #include "QF/Vulkan/qf_bsp.h" #include "QF/Vulkan/qf_lightmap.h" #include "QF/Vulkan/qf_matrices.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_translucent.h" @@ -88,20 +87,13 @@ typedef struct bsp_push_constants_s { float turb_scale; } bsp_push_constants_t; -static const char * __attribute__((used)) bsp_pass_names[] = { +static const char *bsp_pass_names[] = { "depth", "g-buffer", "sky", "turb", }; -static QFV_Subpass subpass_map[] = { - [QFV_bspDepth] = QFV_passDepth, - [QFV_bspGBuffer] = QFV_passGBuffer, - [QFV_bspSky] = QFV_passTranslucentFrag, - [QFV_bspTurb] = QFV_passTranslucentFrag, -}; - static void add_texture (texture_t *tx, vulkan_ctx_t *ctx) { @@ -586,7 +578,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } } - +#if 0 static int R_DrawBrushModel (entity_t ent, bsp_pass_t *pass, vulkan_ctx_t *ctx) { @@ -615,7 +607,7 @@ R_DrawBrushModel (entity_t ent, bsp_pass_t *pass, vulkan_ctx_t *ctx) renderer->render_id); return 1; } - +#endif static inline void visit_leaf (mleaf_t *leaf) { @@ -737,7 +729,7 @@ R_VisitWorldNodes (bsp_pass_t *pass, vulkan_ctx_t *ctx) break; } } - +#if 0 static void bind_texture (vulktex_t *tex, uint32_t setnum, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) @@ -916,7 +908,7 @@ sky_end (vulkan_ctx_t *ctx) bsp_end_subpass (bframe->cmdSet.a[QFV_bspSky], ctx); } - +#endif static void clear_queues (bspctx_t *bctx, bsp_pass_t *pass) { @@ -932,7 +924,7 @@ clear_queues (bspctx_t *bctx, bsp_pass_t *pass) } pass->index_count = 0; } - +#if 0 static void queue_faces (bsp_pass_t *pass, const bspctx_t *bctx, bspframe_t *bframe) { @@ -1092,7 +1084,7 @@ Vulkan_DrawWorld (qfv_orenderframe_t *rFrame) draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); bsp_end (ctx); } - +#endif void Vulkan_Bsp_Flush (vulkan_ctx_t *ctx) { @@ -1125,7 +1117,7 @@ Vulkan_Bsp_Flush (vulkan_ctx_t *ctx) }; dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); } - +#if 0 void Vulkan_DrawWaterSurfaces (qfv_orenderframe_t *rFrame) { @@ -1189,7 +1181,7 @@ Vulkan_DrawSky (qfv_orenderframe_t *rFrame) sky_end (ctx); } - +#endif static void create_default_skys (vulkan_ctx_t *ctx) { @@ -1480,11 +1472,6 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&bctx->frames, frames); bctx->frames.grow = 0; - bctx->depth = Vulkan_CreateGraphicsPipeline (ctx, "bsp_depth"); - bctx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "bsp_gbuf"); - bctx->skybox = Vulkan_CreateGraphicsPipeline (ctx, "bsp_skybox"); - bctx->skysheet = Vulkan_CreateGraphicsPipeline (ctx, "bsp_skysheet"); - bctx->turb = Vulkan_CreateGraphicsPipeline (ctx, "bsp_turb"); bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index cf4a70a1c..8aaa49dba 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -45,7 +45,6 @@ #include "QF/sys.h" #include "QF/Vulkan/qf_compose.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_translucent.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" @@ -120,7 +119,6 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&cctx->frames, frames); cctx->frames.grow = 0; - cctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "compose"); cctx->layout = Vulkan_CreatePipelineLayout (ctx, "compose_layout"); __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index d3b3d7411..3be6e00da 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -52,7 +52,6 @@ #include "compat.h" #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_matrices.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/barrier.h" @@ -63,6 +62,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" #include "QF/Vulkan/scrap.h" #include "QF/Vulkan/staging.h" @@ -1089,9 +1089,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); - dctx->quad_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "slice"); - dctx->line_pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lines"); - dctx->lines_layout = Vulkan_CreatePipelineLayout (ctx, "lines_layout"); dctx->quad_layout = Vulkan_CreatePipelineLayout (ctx, "quad_layout"); __auto_type sl = Vulkan_CreateDescriptorSetLayout (ctx, "quad_data_set"); diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index d6e40bb2d..b792446ec 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -41,7 +41,6 @@ #include "QF/Vulkan/qf_iqm.h" #include "QF/Vulkan/qf_matrices.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" @@ -316,8 +315,6 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&ictx->frames, frames); ictx->frames.grow = 0; - ictx->depth = Vulkan_CreateGraphicsPipeline (ctx, "iqm_depth"); - ictx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "iqm_gbuf"); ictx->layout = Vulkan_CreatePipelineLayout (ctx, "iqm_layout"); ictx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 3ec57f952..e70a4152f 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -56,7 +56,6 @@ #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_lighting.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" @@ -146,7 +145,7 @@ update_lights (vulkan_ctx_t *ctx) 0, 0, 0, 1, &bb.barrier, 0, 0); QFV_PacketSubmit (packet); } - +#if 0 static void lighting_draw_maps (qfv_orenderframe_t *rFrame) { @@ -207,8 +206,6 @@ lighting_draw_maps (qfv_orenderframe_t *rFrame) void Vulkan_Lighting_CreateRenderPasses (vulkan_ctx_t *ctx) { - lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); - ctx->lighting_context = lctx; // extents are dynamic and filled in for each light // frame buffers are highly dynamic @@ -220,7 +217,7 @@ Vulkan_Lighting_CreateRenderPasses (vulkan_ctx_t *ctx) lctx->qfv_renderpass = rp; } - +#endif static VkDescriptorBufferInfo base_buffer_info = { 0, 0, VK_WHOLE_SIZE }; @@ -302,6 +299,9 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; + lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); + ctx->lighting_context = lctx; + qfvPushDebug (ctx, "lighting init"); QFV_Render_AddTasks (ctx, lighting_task_syms); @@ -309,7 +309,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) Vulkan_Script_SetOutput (ctx, &(qfv_output_t) { .format = VK_FORMAT_X8_D24_UNORM_PACK32 }); - lightingctx_t *lctx = ctx->lighting_context; +#if 0 plitem_t *rp_def = lctx->qfv_renderpass->renderpassDef; plitem_t *rp_cfg = PL_ObjectForKey (rp_def, "renderpass_6"); lctx->renderpass_6 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def); @@ -317,7 +317,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lctx->renderpass_4 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def); rp_cfg = PL_ObjectForKey (rp_def, "renderpass_1"); lctx->renderpass_1 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def); - +#endif lctx->cmdpool = QFV_CreateCommandPool (device, device->queue.queueFamily, 1, 1); @@ -331,7 +331,6 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&lctx->frames, frames); lctx->frames.grow = 0; - lctx->pipeline = Vulkan_CreateGraphicsPipeline (ctx, "lighting"); lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout"); lctx->sampler = Vulkan_CreateSampler (ctx, "shadow_sampler"); @@ -611,6 +610,7 @@ create_view (const light_renderer_t *lr, int id, vulkan_ctx_t *ctx) static VkFramebuffer create_framebuffer (const light_renderer_t *lr, vulkan_ctx_t *ctx) { + return 0;//FIXME qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index d26af38aa..deb6e4cd5 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -57,7 +57,6 @@ #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_particles.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_scene.h" #include "QF/Vulkan/qf_sprite.h" #include "QF/Vulkan/qf_translucent.h" @@ -67,7 +66,7 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_vulkan.h" - +#if 0 static void Vulkan_DrawViewModel (vulkan_ctx_t *ctx) { @@ -103,7 +102,7 @@ Vulkan_RenderView (qfv_orenderframe_t *rFrame) Vulkan_Bsp_Flush (ctx); Vulkan_Scene_Flush (ctx); } - +#endif void Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) { @@ -125,24 +124,3 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) Vulkan_BuildDisplayLists (scene->models, scene->num_models, ctx); Vulkan_LoadLights (scene, ctx); } - -static void -main_draw (qfv_orenderframe_t *rFrame) -{ - Vulkan_RenderView (rFrame); -} - -void -Vulkan_Main_CreateRenderPasses (vulkan_ctx_t *ctx) -{ - __auto_type rp = QFV_RenderPass_New (ctx, "deferred", main_draw); - Vulkan_ConfigOutput (ctx, &rp->output); - QFV_RenderPass_CreateAttachments (rp); - QFV_RenderPass_CreateRenderPass (rp); - QFV_RenderPass_CreateFramebuffer (rp); - rp->order = QFV_rp_main; - DARRAY_APPEND (&ctx->renderPasses, rp); - - Vulkan_Output_SetInput (ctx, rp->output.view); - Vulkan_Translucent_CreateBuffers (ctx, rp->output.extent); -} diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 48986a299..0e9933f0d 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -43,7 +43,6 @@ #include "QF/sys.h" #include "QF/va.h" #include "QF/Vulkan/qf_matrices.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/debug.h" @@ -51,6 +50,7 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/staging.h" #include "r_internal.h" diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index f1d9e9c3b..9c0c50d42 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -46,7 +46,6 @@ #include "QF/Vulkan/qf_draw.h" #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_output.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/debug.h" @@ -62,48 +61,6 @@ #include "vid_vulkan.h" #include "vkparse.h"//FIXME -static void -preoutput_draw (qfv_orenderframe_t *rFrame) -{ -} - -static void -process_input (qfv_orenderframe_t *rFrame) -{ -} - -static void -draw_output (qfv_orenderframe_t *rFrame) -{ - process_input (rFrame); -} - -void -Vulkan_Output_CreateRenderPasses (vulkan_ctx_t *ctx) -{ - outputctx_t *octx = calloc (1, sizeof (outputctx_t)); - ctx->output_context = octx; - - __auto_type out = QFV_RenderPass_New (ctx, "output", draw_output); - out->output = (qfv_output_t) { - .extent = ctx->swapchain->extent, - .format = ctx->swapchain->format, - .frames = ctx->swapchain->numImages, - .view_list = ctx->swapchain->imageViews->a, - }; - QFV_RenderPass_CreateRenderPass (out); - QFV_RenderPass_CreateFramebuffer (out); - ctx->output_renderpass = out; - - - out->order = QFV_rp_output; - DARRAY_APPEND (&ctx->renderPasses, out); - - __auto_type pre = QFV_RenderPass_New (ctx, "preoutput", preoutput_draw); - pre->order = QFV_rp_preoutput; - DARRAY_APPEND (&ctx->renderPasses, pre); -} - static void acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { @@ -132,17 +89,6 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) sc = ctx->swapchain; Vulkan_CreateCapture (ctx); - __auto_type out = ctx->output_renderpass; - out->output = (qfv_output_t) { - .extent = ctx->swapchain->extent, - .format = ctx->swapchain->format, - .frames = ctx->swapchain->numImages, - .view_list = ctx->swapchain->imageViews->a, - }; - out->viewport.width = out->output.extent.width; - out->viewport.height = out->output.extent.height; - out->scissor.extent = out->output.extent; - dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore, 0); frame->imageAvailableSemaphore = QFV_CreateSemaphore (device); @@ -243,6 +189,7 @@ output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 2, set, 0, 0); +#if 0 if (scr_fisheye) { float width = r_refdef.vrect.width; float height = r_refdef.vrect.height; @@ -261,6 +208,7 @@ output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) }; QFV_PushConstants (device, cmd, layout, 1, push_constants); } +#endif dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); } @@ -292,11 +240,12 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; + outputctx_t *octx = calloc (1, sizeof (outputctx_t)); + ctx->output_context = octx; + qfvPushDebug (ctx, "output init"); QFV_Render_AddTasks (ctx, output_task_syms); - outputctx_t *octx = ctx->output_context; - auto rctx = ctx->render_context; size_t frames = rctx->frames.size; DARRAY_INIT (&octx->frames, frames); @@ -306,9 +255,6 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) __auto_type pld = ctx->script_context->pipelineDef;//FIXME ctx->script_context->pipelineDef = Vulkan_GetConfig (ctx, "qf_output"); - octx->output = Vulkan_CreateGraphicsPipeline (ctx, "output"); - octx->waterwarp = Vulkan_CreateGraphicsPipeline (ctx, "waterwarp"); - octx->fisheye = Vulkan_CreateGraphicsPipeline (ctx, "fisheye"); octx->output_layout = Vulkan_CreatePipelineLayout (ctx, "output_layout"); octx->warp_layout = Vulkan_CreatePipelineLayout (ctx, "waterwarp_layout"); octx->fish_layout = Vulkan_CreatePipelineLayout (ctx, "fisheye_layout"); diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index a42a7d404..6eac26572 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -53,7 +53,6 @@ #include "QF/Vulkan/qf_matrices.h" #include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_particles.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_translucent.h" #include "r_internal.h" @@ -275,7 +274,7 @@ update_particles (const exprval_t **p, exprval_t *result, exprctx_t *ectx) 0, 0); dfunc->vkCmdBindPipeline (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, - pctx->update); + taskctx->pipeline->pipeline); VkDescriptorSet set[3] = { pframe->curDescriptors, pframe->inDescriptors, @@ -436,9 +435,6 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&pctx->frames, frames); pctx->frames.grow = 0; - pctx->physics = Vulkan_CreateComputePipeline (ctx, "partphysics"); - pctx->update = Vulkan_CreateComputePipeline (ctx, "partupdate"); - pctx->draw = Vulkan_CreateGraphicsPipeline (ctx, "partdraw"); pctx->physics_layout = Vulkan_CreatePipelineLayout (ctx, "partphysics_layout"); pctx->update_layout = Vulkan_CreatePipelineLayout (ctx, @@ -506,16 +502,3 @@ Vulkan_ParticleSystem (vulkan_ctx_t *ctx) { return ctx->particle_context->psystem; //FIXME support more } - -static void -particles_update (qfv_orenderframe_t *rFrame) -{ -} - -void -Vulkan_Particles_CreateRenderPasses (vulkan_ctx_t *ctx) -{ - __auto_type rp = QFV_RenderPass_New (ctx, "particles", particles_update); - rp->order = QFV_rp_particles; - DARRAY_APPEND (&ctx->renderPasses, rp); -} diff --git a/libs/video/renderer/vulkan/vulkan_renderpass.c b/libs/video/renderer/vulkan/vulkan_renderpass.c deleted file mode 100644 index b911b1100..000000000 --- a/libs/video/renderer/vulkan/vulkan_renderpass.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - renderpass.c - - Vulkan render pass and frame buffer functions - - Copyright (C) 2020 Bill Currie - - 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 2 - 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, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "QF/cvar.h" -#include "QF/hash.h" -#include "QF/plist.h" -#include "QF/va.h" - -#include "QF/Vulkan/command.h" -#include "QF/Vulkan/debug.h" -#include "QF/Vulkan/device.h" -#include "QF/Vulkan/image.h" -#include "QF/Vulkan/qf_renderpass.h" - -#include "vid_vulkan.h" -#include "vkparse.h" - -static plitem_t * -get_rp_item (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp, const char *name) -{ - rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); - - plitem_t *item = rp->renderpassDef; - if (!item) { - Sys_Printf ("error loading %s\n", rp->name); - } else if ((item = PL_ObjectForKey (item, name))) { - Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name); - } - return item; -} - -static size_t -get_image_size (VkImage image, qfv_device_t *device) -{ - qfv_devfuncs_t *dfunc = device->funcs; - size_t size; - size_t align; - - VkMemoryRequirements requirements; - dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements); - size = requirements.size; - align = requirements.alignment - 1; - size = (size + align) & ~(align); - return size; -} - -static void -destroy_framebuffers (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - for (size_t i = 0; i < rp->framebuffers->size; i++) { - dfunc->vkDestroyFramebuffer (device->dev, rp->framebuffers->a[i], 0); - } - free (rp->framebuffers); - rp->framebuffers = 0; -} - -void -QFV_RenderPass_CreateAttachments (qfv_orenderpass_t *renderpass) -{ - vulkan_ctx_t *ctx = renderpass->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - __auto_type rp = renderpass; - - if (rp->output.image) { - // if output has an image, then the view is owned by the renderpass - dfunc->vkDestroyImageView (device->dev, rp->output.view, 0); - dfunc->vkDestroyImage (device->dev, rp->output.image, 0); - free (rp->output.view_list); - rp->output.view_list = 0; - rp->output.view = 0; - rp->output.image = 0; - } - if (rp->attachment_views) { - for (size_t i = 0; i < rp->attachment_views->size; i++) { - dfunc->vkDestroyImageView (device->dev, - rp->attachment_views->a[i], 0); - } - free (rp->attachment_views); - rp->attachment_views = 0; - } - if (rp->attachment_images) { - for (size_t i = 0; i < rp->attachment_images->size; i++) { - dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); - } - free (rp->attachment_images); - rp->attachment_images = 0; - } - - plitem_t *output_def = get_rp_item (ctx, rp, "output"); - plitem_t *images_def = get_rp_item (ctx, rp, "images"); - plitem_t *views_def = get_rp_item (ctx, rp, "imageViews"); - - plitem_t *rp_def = rp->renderpassDef; - - size_t memSize = 0; - VkImage ref_image = 0; - if (output_def) { - // QFV_ParseOutput clears the structure, but extent and frames need to - // be preserved - qfv_output_t output = rp->output; - QFV_ParseOutput (ctx, &output, output_def, rp_def); - rp->output.format = output.format; - rp->output.finalLayout = output.finalLayout; - - plitem_t *image = PL_ObjectForKey (output_def, "image"); - Vulkan_Script_SetOutput (ctx, &rp->output); - rp->output.image = QFV_ParseImage (ctx, image, rp_def); - memSize += get_image_size (rp->output.image, device); - ref_image = rp->output.image; - } - if (images_def) { - __auto_type images = QFV_ParseImageSet (ctx, images_def, rp_def); - rp->attachment_images = images; - ref_image = images->a[0]; - for (size_t i = 0; i < images->size; i++) { - memSize += get_image_size (images->a[i], device); - } - } - VkDeviceMemory mem = rp->attachmentMemory; - if (memSize > rp->attachmentMemory_size) { - if (rp->attachmentMemory) { - dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); - } - rp->attachmentMemory_size = memSize; - mem = QFV_AllocImageMemory (device, ref_image, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - memSize, 0); - rp->attachmentMemory = mem; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - mem, "memory:framebuffers"); - } - size_t offset = 0; - if (rp->output.image) { - QFV_BindImageMemory (device, rp->output.image, mem, offset); - offset += get_image_size (rp->output.image, device); - - plitem_t *view = PL_ObjectForKey (output_def, "view"); - Vulkan_Script_SetOutput (ctx, &rp->output); - rp->output.view = QFV_ParseImageView (ctx, view, rp_def); - rp->output.view_list = malloc (rp->output.frames - * sizeof (VkImageView)); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, - rp->output.image, - va (ctx->va_ctx, "image:%s:output", rp->name)); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_IMAGE_VIEW, - rp->output.view, - va (ctx->va_ctx, "iview:%s:output", rp->name)); - for (uint32_t i = 0; i < rp->output.frames; i++) { - rp->output.view_list[i] = rp->output.view; - } - } - if (rp->attachment_images) { - __auto_type images = rp->attachment_images; - for (size_t i = 0; i < images->size; i++) { - QFV_BindImageMemory (device, images->a[i], mem, offset); - offset += get_image_size (images->a[i], device); - } - } - - if (views_def) { - __auto_type views = QFV_ParseImageViewSet (ctx, views_def, rp_def); - rp->attachment_views = views; - } -} - -void -QFV_RenderPass_CreateRenderPass (qfv_orenderpass_t *renderpass) -{ - vulkan_ctx_t *ctx = renderpass->vulkan_ctx; - __auto_type rp = renderpass; - - plitem_t *rp_cfg = get_rp_item (ctx, rp, "renderpass"); - if (rp_cfg) { - hashtab_t *tab = ctx->script_context->renderpasses; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", rp->name); - __auto_type renderpass = (VkRenderPass) QFV_GetHandle (tab, path); - if (renderpass) { - rp->renderpass = renderpass; - } else { - Vulkan_Script_SetOutput (ctx, &rp->output); - rp->renderpass = QFV_ParseRenderPass (ctx, rp_cfg, - rp->renderpassDef); - QFV_AddHandle (tab, path, (uint64_t) rp->renderpass); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, - rp->renderpass, va (ctx->va_ctx, - "renderpass:%s", - rp->name)); - } - rp->subpassCount = PL_A_NumObjects (PL_ObjectForKey (rp_cfg, - "subpasses")); - } - - - plitem_t *item = get_rp_item (ctx, rp, "clearValues"); - rp->clearValues = QFV_ParseClearValues (ctx, item, rp->renderpassDef); -} - -void -QFV_RenderPass_CreateFramebuffer (qfv_orenderpass_t *renderpass) -{ - vulkan_ctx_t *ctx = renderpass->vulkan_ctx; - __auto_type rp = renderpass; - - if (renderpass->framebuffers) { - destroy_framebuffers (ctx, renderpass); - } - - plitem_t *fb_def = get_rp_item (ctx, rp, "framebuffer"); - plitem_t *rp_def = rp->renderpassDef; - if (fb_def) { - rp->framebuffers = QFV_AllocFrameBuffers (rp->output.frames, malloc); - for (size_t i = 0; i < rp->framebuffers->size; i++) { - rp->output.view = rp->output.view_list[i]; - Vulkan_Script_SetOutput (ctx, &rp->output); - rp->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, fb_def, rp_def); - } - } - - int width = rp->output.extent.width; - int height = rp->output.extent.height; - rp->viewport = (VkViewport) { 0, 0, width, height, 0, 1 }; - rp->scissor = (VkRect2D) { {0, 0}, {width, height} }; - rp->renderArea = (VkRect2D) { {0, 0}, {width, height} }; -} - -static void -init_renderframe (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp, - qfv_orenderframe_t *rFrame) -{ - rFrame->vulkan_ctx = ctx; - rFrame->renderpass = rp; - rFrame->subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS; - rFrame->framebuffer = 0; - rFrame->subpassCount = rp->subpassCount; - rFrame->subpassInfo = 0; - if (rp->subpass_info) { - rFrame->subpassInfo = rp->subpass_info->a; - } - rFrame->subpassCmdSets = malloc (rp->subpassCount - * sizeof (qfv_cmdbufferset_t)); - for (size_t j = 0; j < rp->subpassCount; j++) { - DARRAY_INIT (&rFrame->subpassCmdSets[j], 4); - } -} - -static void -destroy_attachments (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - if (rp->output.image) { - // if output has an image, then the view is owned by the renderpass - dfunc->vkDestroyImageView (device->dev, rp->output.view, 0); - dfunc->vkDestroyImage (device->dev, rp->output.image, 0); - free (rp->output.view_list); - rp->output.view_list = 0; - rp->output.view = 0; - rp->output.image = 0; - } - if (rp->attachment_views) { - for (size_t i = 0; i < rp->attachment_views->size; i++) { - dfunc->vkDestroyImageView (device->dev, - rp->attachment_views->a[i], 0); - } - } - if (rp->attachment_images) { - for (size_t i = 0; i < rp->attachment_images->size; i++) { - dfunc->vkDestroyImage (device->dev, rp->attachment_images->a[i], 0); - } - } - dfunc->vkFreeMemory (device->dev, rp->attachmentMemory, 0); - - free (rp->attachment_images); - free (rp->attachment_views); -} - -static void -destroy_renderframes (vulkan_ctx_t *ctx, qfv_orenderpass_t *rp) -{ - for (size_t i = 0; i < rp->frames.size; i++) { - __auto_type rFrame = &rp->frames.a[i]; - for (int j = 0; j < rFrame->subpassCount; j++) { - DARRAY_CLEAR (&rFrame->subpassCmdSets[j]); - } - free (rFrame->subpassCmdSets); - } -} - -qfv_orenderpass_t * -QFV_RenderPass_New (vulkan_ctx_t *ctx, const char *name, qfv_draw_t function) -{ - qfv_orenderpass_t *rp = calloc (1, sizeof (qfv_orenderpass_t)); - rp->vulkan_ctx = ctx; - rp->name = name; - rp->draw = function; - rp->renderpassDef = Vulkan_GetConfig (ctx, rp->name); - - plitem_t *rp_info = get_rp_item (ctx, rp, "info"); - if (rp_info) { - plitem_t *subpass_info = PL_ObjectForKey (rp_info, "subpass_info"); - if (subpass_info) { - rp->subpass_info = QFV_ParseSubpasses (ctx, subpass_info, - rp->renderpassDef); - if (rp->subpass_info->size < rp->subpassCount) { - Sys_Printf ("warning:%s:%d: insufficient entries in " - "subpass_info\n", rp->name, PL_Line (subpass_info)); - } - if (!rp->subpassCount) { - rp->subpassCount = rp->subpass_info->size; - } - } - - plitem_t *color = PL_ObjectForKey (rp_info, "color"); - if (color) { - QFV_ParseRGBA (ctx, (float *)&rp->color, color, rp->renderpassDef); - } - } - if (!rp->subpassCount) { - rp->subpassCount = 1; - } - - DARRAY_INIT (&rp->frames, 4); - //DARRAY_RESIZE (&rp->frames, ctx->frames.size); - for (size_t i = 0; i < rp->frames.size; i++) { - init_renderframe (ctx, rp, &rp->frames.a[i]); - } - return rp; -} - -void -QFV_RenderPass_Delete (qfv_orenderpass_t *renderpass) -{ - vulkan_ctx_t *ctx = renderpass->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - destroy_attachments (ctx, renderpass); - dfunc->vkDestroyRenderPass (device->dev, renderpass->renderpass, 0); - destroy_renderframes (ctx, renderpass); - if (renderpass->framebuffers) { - destroy_framebuffers (ctx, renderpass); - } - - DARRAY_CLEAR (&renderpass->frames); - free (renderpass->clearValues); - free (renderpass); -} diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 51656b1d4..be14aca7f 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -54,7 +54,6 @@ #include "QF/scene/entity.h" #include "QF/Vulkan/qf_matrices.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_sprite.h" #include "QF/Vulkan/qf_texture.h" #include "QF/Vulkan/buffer.h" @@ -234,8 +233,6 @@ Vulkan_Sprite_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&sctx->frames, frames); sctx->frames.grow = 0; - sctx->depth = Vulkan_CreateGraphicsPipeline (ctx, "sprite_depth"); - sctx->gbuf = Vulkan_CreateGraphicsPipeline (ctx, "sprite_gbuf"); sctx->layout = Vulkan_CreatePipelineLayout (ctx, "sprite_layout"); sctx->sampler = Vulkan_CreateSampler (ctx, "sprite_sampler"); diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index c533efe94..8ca44abe7 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -45,7 +45,6 @@ #include "QF/sys.h" #include "QF/va.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_translucent.h" #include "QF/Vulkan/barrier.h" #include "QF/Vulkan/debug.h" @@ -53,8 +52,10 @@ #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" #include "QF/Vulkan/staging.h" +#include "QF/Vulkan/swapchain.h" #include "r_internal.h" #include "vid_vulkan.h" @@ -154,24 +155,12 @@ Vulkan_Translucent_Init (vulkan_ctx_t *ctx) __auto_type sets = QFV_AllocateDescriptorSet (device, pool, setLayout); for (size_t i = 0; i < frames; i++) { - __auto_type tframe = &tctx->frames.a[i]; - - DARRAY_INIT (&tframe->cmdSet, QFV_translucentNumPasses); - DARRAY_RESIZE (&tframe->cmdSet, QFV_translucentNumPasses); - tframe->cmdSet.grow = 0; - - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &tframe->cmdSet); - - tframe->descriptors = sets->a[i]; - - for (int j = 0; j < QFV_translucentNumPasses; j++) { - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - tframe->cmdSet.a[j], - va (ctx->va_ctx, "cmd:translucent:%zd:%s", i, - translucent_pass_names[j])); - } + tctx->frames.a[i] = (translucentframe_t) { + .descriptors = sets->a[i], + }; } free (sets); + Vulkan_Translucent_CreateBuffers (ctx, ctx->swapchain->extent);//FIXME qfvPopDebug (ctx); } @@ -308,66 +297,3 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); } } - -static void -translucent_clear (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - translucentctx_t *tctx = ctx->translucent_context; - __auto_type tframe = &tctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = tframe->cmdSet.a[QFV_translucentClear]; - - DARRAY_APPEND (&rFrame->subpassCmdSets[0], cmd); - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - 0, 0, 0, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; - ib.barrier.image = tframe->heads; - ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, - 0, 0, 0, 0, 0, - 1, &ib.barrier); - VkClearColorValue clear_color[] = { - { .int32 = {-1, -1, -1, -1} }, - }; - VkImageSubresourceRange ranges[] = { - { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, VK_REMAINING_ARRAY_LAYERS }, - }; - dfunc->vkCmdClearColorImage (cmd, tframe->heads, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - clear_color, 1, ranges); - ib = imageBarriers[qfv_LT_TransferDst_to_General]; - ib.barrier.image = tframe->heads; - ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; - dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, - 0, 0, 0, 0, 0, - 1, &ib.barrier); - - dfunc->vkEndCommandBuffer (cmd); - - qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging); - qfv_transtate_t *state = QFV_PacketExtend (packet, 2 * sizeof (*state)); - *state = (qfv_transtate_t) { 0, tctx->maxFragments }; - __auto_type bb = &bufferBarriers[qfv_BB_TransferWrite_to_ShaderRW]; - QFV_PacketCopyBuffer (packet, tframe->state, 0, bb); - QFV_PacketSubmit (packet); -} - -void -Vulkan_Translucent_CreateRenderPasses (vulkan_ctx_t *ctx) -{ - __auto_type rp = QFV_RenderPass_New (ctx, "translucent", translucent_clear); - rp->order = QFV_rp_translucent; - DARRAY_APPEND (&ctx->renderPasses, rp); -} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index a7bef9bae..2b6987788 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -55,7 +55,6 @@ #include "QF/Vulkan/qf_main.h" #include "QF/Vulkan/qf_output.h" #include "QF/Vulkan/qf_particles.h" -#include "QF/Vulkan/qf_renderpass.h" #include "QF/Vulkan/qf_translucent.h" #include "QF/Vulkan/qf_vid.h" @@ -184,35 +183,6 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain); } -static int -renderpass_cmp (const void *_a, const void *_b) -{ - __auto_type a = (const qfv_orenderpass_t **) _a; - __auto_type b = (const qfv_orenderpass_t **) _b; - return (*a)->order - (*b)->order; -} - -void -Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx) -{ - Vulkan_Output_CreateRenderPasses (ctx); - Vulkan_Main_CreateRenderPasses (ctx); - Vulkan_Particles_CreateRenderPasses (ctx); - Vulkan_Lighting_CreateRenderPasses (ctx); - Vulkan_Translucent_CreateRenderPasses (ctx); - - heapsort (ctx->renderPasses.a, ctx->renderPasses.size, - sizeof (qfv_orenderpass_t *), renderpass_cmp); -} - -void -Vulkan_DestroyRenderPasses (vulkan_ctx_t *ctx) -{ - for (size_t i = 0; i < ctx->renderPasses.size; i++) { - QFV_RenderPass_Delete (ctx->renderPasses.a[i]); - } -} - void Vulkan_CreateCapture (vulkan_ctx_t *ctx) { From 92368eafb2b6157081a90b4faa35adbe1d41c26f Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jun 2023 11:47:01 +0900 Subject: [PATCH 3646/3664] [vulkan] Clean out old pipeline and layout refs It's not perfect as some subsystems still create resources from the old system (necessarily), but this cleans up a lot of the mess. --- include/QF/Vulkan/qf_alias.h | 11 ------ include/QF/Vulkan/qf_bsp.h | 1 - include/QF/Vulkan/qf_compose.h | 3 -- include/QF/Vulkan/qf_iqm.h | 3 -- include/QF/Vulkan/qf_lighting.h | 3 -- include/QF/Vulkan/qf_matrices.h | 3 -- include/QF/Vulkan/qf_output.h | 7 ---- include/QF/Vulkan/qf_particles.h | 9 ----- include/QF/Vulkan/qf_sprite.h | 11 ------ libs/video/renderer/vulkan/pl_quake_def.plist | 2 +- libs/video/renderer/vulkan/vulkan_alias.c | 34 +++++++------------ libs/video/renderer/vulkan/vulkan_bsp.c | 1 - libs/video/renderer/vulkan/vulkan_compose.c | 15 ++------ libs/video/renderer/vulkan/vulkan_iqm.c | 22 +++++------- libs/video/renderer/vulkan/vulkan_lighting.c | 10 ------ libs/video/renderer/vulkan/vulkan_output.c | 11 +----- libs/video/renderer/vulkan/vulkan_particles.c | 22 +++++------- libs/video/renderer/vulkan/vulkan_sprite.c | 32 ++++++----------- 18 files changed, 43 insertions(+), 157 deletions(-) diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index a7f2cda41..54c7c9e9c 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -70,21 +70,10 @@ typedef enum { QFV_aliasNumPasses } QFV_AliasSubpass; -typedef struct aliasframe_s { - qfv_cmdbufferset_t cmdSet; -} aliasframe_t; - -typedef struct aliasframeset_s - DARRAY_TYPE (aliasframe_t) aliasframeset_t; - typedef struct aliasindset_s DARRAY_TYPE (unsigned) aliasindset_t; typedef struct aliasctx_s { - aliasframeset_t frames; - VkPipeline depth; - VkPipeline gbuf; - VkPipelineLayout layout; VkSampler sampler; } aliasctx_t; diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 99a558dfc..0efc60eea 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -366,7 +366,6 @@ typedef struct bspctx_s { bsp_pass_t main_pass; ///< camera view depth, gbuffer, etc VkSampler sampler; - VkPipelineLayout layout; VkDeviceMemory texture_memory; VkPipeline depth; diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h index d777080ce..6364fa962 100644 --- a/include/QF/Vulkan/qf_compose.h +++ b/include/QF/Vulkan/qf_compose.h @@ -39,7 +39,6 @@ #define COMPOSE_IMAGE_INFOS 1 typedef struct composeframe_s { - VkCommandBuffer cmd; VkDescriptorImageInfo imageInfo[COMPOSE_IMAGE_INFOS]; VkWriteDescriptorSet descriptors[COMPOSE_IMAGE_INFOS]; } composeframe_t; @@ -49,8 +48,6 @@ typedef struct composeframeset_s typedef struct composectx_s { composeframeset_t frames; - VkPipeline pipeline; - VkPipelineLayout layout; } composectx_t; struct vulkan_ctx_s; diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h index 88057f441..1138eaa16 100644 --- a/include/QF/Vulkan/qf_iqm.h +++ b/include/QF/Vulkan/qf_iqm.h @@ -89,9 +89,6 @@ typedef struct iqmindset_s typedef struct iqmctx_s { iqm_frameset_t frames; - VkPipeline depth; - VkPipeline gbuf; - VkPipelineLayout layout; VkSampler sampler; VkDescriptorPool bones_pool; VkDescriptorSetLayout bones_setLayout; diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index b6c8437e8..469bb5b4c 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -61,7 +61,6 @@ typedef struct qfv_light_buffer_s { #define LIGHTING_DESCRIPTORS (LIGHTING_BUFFER_INFOS + LIGHTING_ATTACH_INFOS + 1) typedef struct lightingframe_s { - VkCommandBuffer cmd; VkBuffer light_buffer; VkDescriptorBufferInfo bufferInfo[LIGHTING_BUFFER_INFOS]; VkDescriptorImageInfo attachInfo[LIGHTING_ATTACH_INFOS]; @@ -108,8 +107,6 @@ typedef struct lightingctx_s { VkRenderPass renderpass_4; VkRenderPass renderpass_1; - VkCommandPool cmdpool; - struct lightingdata_s *ldata; struct scene_s *scene; } lightingctx_t; diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index 011a69972..057dd6d81 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -48,7 +48,6 @@ typedef struct qfv_matrix_buffer_s { } qfv_matrix_buffer_t; typedef struct matrixframe_s { - //VkCommandBuffer cmd; VkBuffer buffer; VkDescriptorSet descriptors; } matrixframe_t; @@ -58,8 +57,6 @@ typedef struct matrixframeset_s typedef struct matrixctx_s { matrixframeset_t frames; - VkPipeline pipeline; - VkPipelineLayout layout; VkDeviceMemory memory; qfv_matrix_buffer_t matrices; int dirty; diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index c81495082..aeaada73d 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -35,7 +35,6 @@ #include "QF/Vulkan/command.h" typedef struct outputframe_s { - VkCommandBuffer cmd; VkImageView input; VkDescriptorSet set; } outputframe_t; @@ -45,12 +44,6 @@ typedef struct outputframeset_s typedef struct outputctx_s { outputframeset_t frames; - VkPipeline output; - VkPipeline waterwarp; - VkPipeline fisheye; - VkPipelineLayout output_layout; - VkPipelineLayout warp_layout; - VkPipelineLayout fish_layout; VkSampler sampler; VkImageView input; VkFramebuffer *framebuffers; // one per swapchain image diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index 381a8edad..ba3d0d906 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -37,7 +37,6 @@ typedef enum { } QFV_ParticleSubpass; typedef struct particleframe_s { - VkCommandBuffer compute; VkEvent physicsEvent; VkEvent updateEvent; VkBuffer states; @@ -47,8 +46,6 @@ typedef struct particleframe_s { VkDescriptorSet curDescriptors; VkDescriptorSet inDescriptors; VkDescriptorSet newDescriptors; - - qfv_cmdbufferset_t cmdSet; } particleframe_t; typedef struct particleframeset_s @@ -56,18 +53,12 @@ typedef struct particleframeset_s typedef struct particlectx_s { particleframeset_t frames; - VkPipeline physics; - VkPipeline update; - VkPipeline draw; struct qfv_resource_s *resources; struct qfv_stagebuf_s *stage; VkDescriptorPool pool; VkDescriptorSetLayout setLayout; - VkPipelineLayout physics_layout; - VkPipelineLayout update_layout; - VkPipelineLayout draw_layout; psystem_t *psystem; } particlectx_t; diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index 8e1fdf52f..19c552397 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -58,20 +58,9 @@ typedef enum { QFV_spriteNumPasses } QFV_SpriteSubpass; -typedef struct spriteframe_s { - qfv_cmdbufferset_t cmdSet; -} spriteframe_t; - -typedef struct spriteframeset_s - DARRAY_TYPE (spriteframe_t) spriteframeset_t; - typedef struct spritectx_s { - spriteframeset_t frames; - VkPipeline depth; - VkPipeline gbuf; VkDescriptorPool pool; VkDescriptorSetLayout setLayout; - VkPipelineLayout layout; unsigned maxImages; VkSampler sampler; } spritectx_t; diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist index ed3caa0d5..be3764cc4 100644 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ b/libs/video/renderer/vulkan/pl_quake_def.plist @@ -254,7 +254,7 @@ setLayouts = { binding = 0; descriptorType = uniform_buffer; descriptorCount = 1; - stageFlags = vertex|geometry; + stageFlags = vertex|geometry|fragment; }, ); }; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index 3c68a55c9..bd61b454f 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -64,11 +64,12 @@ static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_alias_skin_t *skin, uint32_t numPC, qfv_push_constants_t *constants, - aliashdr_t *hdr, vulkan_ctx_t *ctx, entity_t ent) + aliashdr_t *hdr, qfv_taskctx_t *taskctx, entity_t ent) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - aliasctx_t *actx = ctx->alias_context; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto layout = taskctx->pipeline->layout; __auto_type mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands); @@ -89,13 +90,13 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, VK_INDEX_TYPE_UINT32); - QFV_PushConstants (device, cmd, actx->layout, numPC, constants); + QFV_PushConstants (device, cmd, layout, numPC, constants); if (skin) { VkDescriptorSet sets[] = { skin->descriptor, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, 2, 1, sets, 0, 0); + layout, 2, 1, sets, 0, 0); } dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); @@ -134,7 +135,6 @@ Vulkan_AliasRemoveSkin (vulkan_ctx_t *ctx, qfv_alias_skin_t *skin) static void alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass) { - auto ctx = taskctx->ctx; renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); auto model = renderer->model; aliashdr_t *hdr; @@ -187,7 +187,7 @@ alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass) emit_commands (taskctx->cmd, animation->pose1, animation->pose2, pass ? skin : 0, pass ? 5 : 2, push_constants, - hdr, ctx, ent); + hdr, taskctx, ent); } static void @@ -200,14 +200,14 @@ alias_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto ctx = taskctx->ctx; auto device = ctx->device; auto dfunc = device->funcs; - auto actx = ctx->alias_context; + auto layout = taskctx->pipeline->layout; auto cmd = taskctx->cmd; VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), Vulkan_Palette_Descriptor (ctx), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - actx->layout, 0, 2, sets, 0, 0); + layout, 0, 2, sets, 0, 0); auto queue = r_ent_queue; //FIXME fetch from scene for (size_t i = 0; i < queue->ent_queues[mod_alias].size; i++) { @@ -246,13 +246,6 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); ctx->alias_context = actx; - auto rctx = ctx->render_context; - size_t frames = rctx->frames.size; - DARRAY_INIT (&actx->frames, frames); - DARRAY_RESIZE (&actx->frames, frames); - actx->frames.grow = 0; - - actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); qfvPopDebug (ctx); } @@ -260,12 +253,9 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) void Vulkan_Alias_Shutdown (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; + //qfv_device_t *device = ctx->device; + //qfv_devfuncs_t *dfunc = device->funcs; aliasctx_t *actx = ctx->alias_context; - dfunc->vkDestroyPipeline (device->dev, actx->depth, 0); - dfunc->vkDestroyPipeline (device->dev, actx->gbuf, 0); - free (actx->frames.a); free (actx); } diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 471172ded..a88f9db54 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1472,7 +1472,6 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&bctx->frames, frames); bctx->frames.grow = 0; - bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); size_t entid_count = Vulkan_Scene_MaxEntities (ctx); diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index 8aaa49dba..a00141ed9 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -76,6 +76,7 @@ compose_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto cctx = ctx->compose_context; auto cframe = &cctx->frames.a[ctx->curFrame]; + auto layout = taskctx->pipeline->layout; auto cmd = taskctx->cmd; auto fb = &taskctx->renderpass->framebuffer; @@ -88,7 +89,7 @@ compose_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - cctx->layout, 0, 2, sets, 0, 0); + layout, 0, 2, sets, 0, 0); dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); } @@ -119,10 +120,6 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&cctx->frames, frames); cctx->frames.grow = 0; - cctx->layout = Vulkan_CreatePipelineLayout (ctx, "compose_layout"); - - __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); - __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); for (size_t i = 0; i < frames; i++) { attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, @@ -136,11 +133,6 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) for (size_t i = 0; i < frames; i++) { __auto_type cframe = &cctx->frames.a[i]; - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); - cframe->cmd = cmdSet->a[0]; - - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - cframe->cmd, "cmd:compose"); for (int j = 0; j < COMPOSE_IMAGE_INFOS; j++) { cframe->imageInfo[j] = base_image_info; cframe->imageInfo[j].sampler = 0; @@ -157,11 +149,8 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) void Vulkan_Compose_Shutdown (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; composectx_t *cctx = ctx->compose_context; - dfunc->vkDestroyPipeline (device->dev, cctx->pipeline, 0); free (cctx->frames.a); free (cctx); } diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index b792446ec..5ac1e0318 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -65,11 +65,12 @@ static void emit_commands (VkCommandBuffer cmd, int pose1, int pose2, qfv_iqm_skin_t *skins, uint32_t numPC, qfv_push_constants_t *constants, - iqm_t *iqm, vulkan_ctx_t *ctx, entity_t ent) + iqm_t *iqm, qfv_taskctx_t *taskctx, entity_t ent) { + auto ctx = taskctx->ctx; auto device = ctx->device; auto dfunc = device->funcs; - auto ictx = ctx->iqm_context; + auto layout = taskctx->pipeline->layout; auto mesh = (qfv_iqm_t *) iqm->extra_data; @@ -85,7 +86,7 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets); dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, VK_INDEX_TYPE_UINT16); - QFV_PushConstants (device, cmd, ictx->layout, numPC, constants); + QFV_PushConstants (device, cmd, layout, numPC, constants); for (int i = 0; i < iqm->num_meshes; i++) { if (skins) { VkDescriptorSet sets[] = { @@ -94,14 +95,14 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - ictx->layout, 1, 2, sets, 0, 0); + layout, 1, 2, sets, 0, 0); } else { VkDescriptorSet sets[] = { mesh->bones_descriptors[ctx->curFrame], }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - ictx->layout, 2, 1, sets, 0, 0); + layout, 2, 1, sets, 0, 0); } dfunc->vkCmdDrawIndexed (cmd, 3 * iqm->meshes[i].num_triangles, 1, 3 * iqm->meshes[i].first_triangle, 0, 0); @@ -260,7 +261,7 @@ iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass) emit_commands (taskctx->cmd, animation->pose1, animation->pose2, pass ? skins : 0, pass ? 6 : 2, push_constants, - iqm, ctx, ent); + iqm, taskctx, ent); } static void @@ -272,14 +273,14 @@ iqm_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto ctx = taskctx->ctx; auto device = ctx->device; auto dfunc = device->funcs; - auto ictx = ctx->iqm_context; + auto layout = taskctx->pipeline->layout; auto cmd = taskctx->cmd; VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - ictx->layout, 0, 1, sets, 0, 0); + layout, 0, 1, sets, 0, 0); auto queue = r_ent_queue; //FIXME fetch from scene for (size_t i = 0; i < queue->ent_queues[mod_iqm].size; i++) { @@ -315,7 +316,6 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&ictx->frames, frames); ictx->frames.grow = 0; - ictx->layout = Vulkan_CreatePipelineLayout (ctx, "iqm_layout"); ictx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); ictx->bones_pool = Vulkan_CreateDescriptorPool (ctx, "bone_pool"); @@ -327,12 +327,8 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx) void Vulkan_IQM_Shutdown (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; iqmctx_t *ictx = ctx->iqm_context; - dfunc->vkDestroyPipeline (device->dev, ictx->depth, 0); - dfunc->vkDestroyPipeline (device->dev, ictx->gbuf, 0); free (ictx->frames.a); free (ictx); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index e70a4152f..83c585572 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -318,8 +318,6 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) rp_cfg = PL_ObjectForKey (rp_def, "renderpass_1"); lctx->renderpass_1 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def); #endif - lctx->cmdpool = QFV_CreateCommandPool (device, device->queue.queueFamily, - 1, 1); DARRAY_INIT (&lctx->light_mats, 16); DARRAY_INIT (&lctx->light_images, 16); @@ -354,8 +352,6 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lctx->light_memory, "memory:lighting"); - __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); - __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); __auto_type lights = QFV_AllocDescriptorSetLayoutSet (frames, alloca); __auto_type shadow = QFV_AllocDescriptorSetLayoutSet (frames, alloca); @@ -394,16 +390,11 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) shadow_set->a[i], va (ctx->va_ctx, "lighting:shadow_set:%zd", i)); - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); - lframe->cmd = cmdSet->a[0]; - lframe->light_buffer = lbuffers->a[i]; QFV_BindBufferMemory (device, lbuffers->a[i], lctx->light_memory, light_offset); light_offset += light_size; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - lframe->cmd, "cmd:lighting"); for (int j = 0; j < LIGHTING_BUFFER_INFOS; j++) { lframe->bufferInfo[j] = base_buffer_info; lframe->bufferWrite[j] = base_buffer_write; @@ -466,7 +457,6 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx) clear_shadows (ctx); - dfunc->vkDestroyCommandPool (device->dev, lctx->cmdpool, 0); dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_6, 0); dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_4, 0); dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_1, 0); diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 9c0c50d42..9c51b49f5 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -171,9 +171,9 @@ output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto dfunc = device->funcs; auto octx = ctx->output_context; auto oframe = &octx->frames.a[ctx->curFrame]; + auto layout = taskctx->pipeline->layout; auto cmd = taskctx->cmd; - auto layout = octx->output_layout; //__auto_type pipeline = octx->output; //if (scr_fisheye) { // pipeline = octx->fisheye; @@ -255,9 +255,6 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) __auto_type pld = ctx->script_context->pipelineDef;//FIXME ctx->script_context->pipelineDef = Vulkan_GetConfig (ctx, "qf_output"); - octx->output_layout = Vulkan_CreatePipelineLayout (ctx, "output_layout"); - octx->warp_layout = Vulkan_CreatePipelineLayout (ctx, "waterwarp_layout"); - octx->fish_layout = Vulkan_CreatePipelineLayout (ctx, "fisheye_layout"); octx->sampler = Vulkan_CreateSampler (ctx, "linear"); __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); @@ -276,9 +273,6 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) oframe->set = sets->a[i]; QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); - oframe->cmd = cmdSet->a[0]; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, - oframe->cmd, "cmd:output"); } ctx->script_context->pipelineDef = pld; @@ -303,9 +297,6 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx) auto rp = &render->renderpasses[0]; rp->beginInfo.framebuffer = 0; - dfunc->vkDestroyPipeline (device->dev, octx->output, 0); - dfunc->vkDestroyPipeline (device->dev, octx->waterwarp, 0); - dfunc->vkDestroyPipeline (device->dev, octx->fisheye, 0); free (octx->frames.a); free (octx); } diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 6eac26572..963f8bda3 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -168,6 +168,7 @@ particles_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto dfunc = device->funcs; auto pctx = ctx->particle_context; auto pframe = &pctx->frames.a[ctx->curFrame]; + auto layout = taskctx->pipeline->layout; auto cmd = taskctx->cmd; VkDescriptorSet sets[] = { @@ -176,14 +177,14 @@ particles_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - pctx->draw_layout, 0, 3, sets, 0, 0); + layout, 0, 3, sets, 0, 0); mat4f_t mat; mat4fidentity (mat); qfv_push_constants_t push_constants[] = { { VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof (mat4f_t), &mat }, }; - QFV_PushConstants (device, cmd, pctx->draw_layout, 1, push_constants); + QFV_PushConstants (device, cmd, layout, 1, push_constants); VkDeviceSize offsets[] = { 0 }; VkBuffer buffers[] = { pframe->states, @@ -202,6 +203,7 @@ update_particles (const exprval_t **p, exprval_t *result, exprctx_t *ectx) auto dfunc = device->funcs; auto pctx = ctx->particle_context; auto pframe = &pctx->frames.a[ctx->curFrame]; + auto layout = taskctx->pipeline->layout; qfv_packet_t *packet = QFV_PacketAcquire (pctx->stage); @@ -281,7 +283,7 @@ update_particles (const exprval_t **p, exprval_t *result, exprctx_t *ectx) pframe->newDescriptors, }; dfunc->vkCmdBindDescriptorSets (packet->cmd, VK_PIPELINE_BIND_POINT_COMPUTE, - pctx->update_layout, 0, 3, set, 0, 0); + layout, 0, 3, set, 0, 0); dfunc->vkCmdDispatch (packet->cmd, 1, 1, 1); dfunc->vkCmdSetEvent (packet->cmd, pframe->updateEvent, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); @@ -335,6 +337,7 @@ particle_physics (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto dfunc = device->funcs; auto pctx = ctx->particle_context; auto pframe = &pctx->frames.a[ctx->curFrame]; + auto layout = taskctx->pipeline->layout; auto cmd = taskctx->cmd; dfunc->vkResetEvent (device->dev, pframe->physicsEvent); @@ -345,7 +348,7 @@ particle_physics (const exprval_t **params, exprval_t *result, exprctx_t *ectx) pframe->curDescriptors, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_COMPUTE, - pctx->physics_layout, 0, 1, set, 0, 0); + layout, 0, 1, set, 0, 0); particle_push_constants_t constants = { .gravity = pctx->psystem->gravity, @@ -359,7 +362,7 @@ particle_physics (const exprval_t **params, exprval_t *result, exprctx_t *ectx) field_offset (particle_push_constants_t, dT), sizeof (float), &constants.dT }, }; - QFV_PushConstants (device, cmd, pctx->physics_layout, 2, push_constants); + QFV_PushConstants (device, cmd, layout, 2, push_constants); dfunc->vkCmdDispatch (cmd, MaxParticles, 1, 1); dfunc->vkCmdSetEvent (cmd, pframe->physicsEvent, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); @@ -435,12 +438,6 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&pctx->frames, frames); pctx->frames.grow = 0; - pctx->physics_layout = Vulkan_CreatePipelineLayout (ctx, - "partphysics_layout"); - pctx->update_layout = Vulkan_CreatePipelineLayout (ctx, - "partupdate_layout"); - pctx->draw_layout = Vulkan_CreatePipelineLayout (ctx, "partdraw_layout"); - pctx->pool = Vulkan_CreateDescriptorPool (ctx, "particle_pool"); pctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "particle_set"); @@ -490,9 +487,6 @@ Vulkan_Particles_Shutdown (vulkan_ctx_t *ctx) QFV_DestroyResource (device, pctx->resources); free (pctx->resources); - dfunc->vkDestroyPipeline (device->dev, pctx->physics, 0); - dfunc->vkDestroyPipeline (device->dev, pctx->update, 0); - dfunc->vkDestroyPipeline (device->dev, pctx->draw, 0); free (pctx->frames.a); free (pctx); } diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index be14aca7f..984db3710 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -70,20 +70,21 @@ static void emit_commands (VkCommandBuffer cmd, qfv_sprite_t *sprite, int numPC, qfv_push_constants_t *constants, - vulkan_ctx_t *ctx, entity_t ent) + qfv_taskctx_t *taskctx, entity_t ent) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - spritectx_t *sctx = ctx->sprite_context; + auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; + auto layout = taskctx->pipeline->layout; Vulkan_BeginEntityLabel (ctx, cmd, ent); - QFV_PushConstants (device, cmd, sctx->layout, numPC, constants); + QFV_PushConstants (device, cmd, layout, numPC, constants); VkDescriptorSet sets[] = { sprite->descriptors, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - sctx->layout, 1, 1, sets, 0, 0); + layout, 1, 1, sets, 0, 0); dfunc->vkCmdDraw (cmd, 4, 1, 0, 0); QFV_CmdEndLabel (device, cmd); @@ -157,7 +158,6 @@ Vulkan_Sprint_FreeDescriptors (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) static void sprite_draw_ent (qfv_taskctx_t *taskctx, entity_t ent) { - auto ctx = taskctx->ctx; renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); auto model = renderer->model; msprite_t *sprite = model->cache.data; @@ -183,7 +183,7 @@ sprite_draw_ent (qfv_taskctx_t *taskctx, entity_t ent) emit_commands (taskctx->cmd, (qfv_sprite_t *) ((byte *) sprite + sprite->data), - 2, push_constants, ctx, ent); + 2, push_constants, taskctx, ent); } static void @@ -193,14 +193,14 @@ sprite_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto ctx = taskctx->ctx; auto device = ctx->device; auto dfunc = device->funcs; - auto sctx = ctx->sprite_context; + auto layout = taskctx->pipeline->layout; auto cmd = taskctx->cmd; VkDescriptorSet sets[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - sctx->layout, 0, 1, sets, 0, 0); + layout, 0, 1, sets, 0, 0); auto queue = r_ent_queue; //FIXME fetch from scene for (size_t i = 0; i < queue->ent_queues[mod_sprite].size; i++) { @@ -227,13 +227,6 @@ Vulkan_Sprite_Init (vulkan_ctx_t *ctx) spritectx_t *sctx = calloc (1, sizeof (spritectx_t)); ctx->sprite_context = sctx; - auto rctx = ctx->render_context; - size_t frames = rctx->frames.size; - DARRAY_INIT (&sctx->frames, frames); - DARRAY_RESIZE (&sctx->frames, frames); - sctx->frames.grow = 0; - - sctx->layout = Vulkan_CreatePipelineLayout (ctx, "sprite_layout"); sctx->sampler = Vulkan_CreateSampler (ctx, "sprite_sampler"); sctx->pool = Vulkan_CreateDescriptorPool (ctx, "sprite_pool"); @@ -245,12 +238,7 @@ Vulkan_Sprite_Init (vulkan_ctx_t *ctx) void Vulkan_Sprite_Shutdown (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; spritectx_t *sctx = ctx->sprite_context; - dfunc->vkDestroyPipeline (device->dev, sctx->depth, 0); - dfunc->vkDestroyPipeline (device->dev, sctx->gbuf, 0); - free (sctx->frames.a); free (sctx); } From 8470ae5a28be7bc8aca020018f713b4f310d9db0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jun 2023 14:55:46 +0900 Subject: [PATCH 3647/3664] [vulkan] Create a descriptor set manager The manager allows recycling of descriptor sets and takes care of creating pools as needed. --- include/QF/Vulkan/dsmanager.h | 37 +++++ include/QF/Vulkan/render.h | 14 +- libs/video/renderer/Makemodule.am | 1 + libs/video/renderer/vulkan/dsmanager.c | 166 +++++++++++++++++++++++ libs/video/renderer/vulkan/render.c | 32 +---- libs/video/renderer/vulkan/render_load.c | 89 +++++++----- libs/video/renderer/vulkan/vkparse.plist | 4 +- 7 files changed, 274 insertions(+), 69 deletions(-) create mode 100644 include/QF/Vulkan/dsmanager.h create mode 100644 libs/video/renderer/vulkan/dsmanager.c diff --git a/include/QF/Vulkan/dsmanager.h b/include/QF/Vulkan/dsmanager.h new file mode 100644 index 000000000..e152c5236 --- /dev/null +++ b/include/QF/Vulkan/dsmanager.h @@ -0,0 +1,37 @@ +#ifndef __QF_Vulkan_dsmanager_h +#define __QF_Vulkan_dsmanager_h + +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + +#include "QF/darray.h" +#include "QF/darray.h" + +typedef struct qfv_descriptorpoolset_s + DARRAY_TYPE (VkDescriptorPool) qfv_descriptorpoolset_t; +typedef struct qfv_descriptorsetset_s + DARRAY_TYPE (VkDescriptorSet) qfv_descriptorsetset_t; + +typedef struct qfv_dsmanager_s { + const char *name; + struct qfv_device_s *device; + VkDescriptorPoolCreateInfo poolCreateInfo; + VkDescriptorPool activePool; + qfv_descriptorpoolset_t freePools; + qfv_descriptorpoolset_t usedPools; + qfv_descriptorsetset_t freeSets; + VkDescriptorSetLayout layout; +} qfv_dsmanager_t; + +struct qfv_descriptorsetlayoutinfo_s; + +qfv_dsmanager_t * +QFV_DSManager_Create (const struct qfv_descriptorsetlayoutinfo_s *setLayoutInfo, + uint32_t maxSets, struct vulkan_ctx_s *ctx); +void QFV_DSManager_Destroy (qfv_dsmanager_t *setManager); +VkDescriptorSet QFV_DSManager_AllocSet (qfv_dsmanager_t *setManager); +void QFV_DSManager_FreeSet (qfv_dsmanager_t *setManager, VkDescriptorSet set); + +#endif//__QF_Vulkan_dsmanager_h diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 5f6071d4a..1acf2aa6f 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -8,7 +8,9 @@ #include "QF/cexpr.h" #include "QF/simd/types.h" + #ifndef __QFCC__ +#include "QF/darray.h" #include "QF/Vulkan/command.h" #endif @@ -266,8 +268,8 @@ typedef struct qfv_jobinfo_s { qfv_imageinfo_t *buffers; qfv_imageviewinfo_t *bufferviews; - uint32_t num_descriptorsetlayouts; - qfv_descriptorsetlayoutinfo_t *descriptorsetlayouts; + uint32_t num_dslayouts; + qfv_descriptorsetlayoutinfo_t *dslayouts; } qfv_jobinfo_t; #ifndef __QFCC__ @@ -285,9 +287,8 @@ typedef struct qfv_pipeline_s { VkViewport viewport; VkRect2D scissor; - uint32_t num_descriptorsets; - uint32_t first_descriptorset; - VkDescriptorSet *descriptorsets; + uint32_t num_indices; + uint32_t *ds_indices; uint32_t task_count; qfv_taskinfo_t *tasks; @@ -367,6 +368,8 @@ typedef struct qfv_job_s { VkPipelineLayout *layouts; qfv_step_t *steps; qfv_cmdbufferset_t commands; + uint32_t num_dsmanagers; + struct qfv_dsmanager_s **dsmanager; } qfv_job_t; typedef struct qfv_renderframe_s { @@ -408,6 +411,7 @@ void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp); qfv_step_t *QFV_GetStep (const exprval_t *param, qfv_job_t *job); qfv_step_t *QFV_FindStep (const char *step, qfv_job_t *job) __attribute__((pure)); + #endif//__QFCC__ #endif//__QF_Vulkan_render_h diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 1183f8e94..cddf9f20f 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -228,6 +228,7 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/debug.c \ libs/video/renderer/vulkan/descriptor.c \ libs/video/renderer/vulkan/device.c \ + libs/video/renderer/vulkan/dsmanager.c \ libs/video/renderer/vulkan/image.c \ libs/video/renderer/vulkan/instance.c \ libs/video/renderer/vulkan/memory.c \ diff --git a/libs/video/renderer/vulkan/dsmanager.c b/libs/video/renderer/vulkan/dsmanager.c new file mode 100644 index 000000000..b45485097 --- /dev/null +++ b/libs/video/renderer/vulkan/dsmanager.c @@ -0,0 +1,166 @@ +/* + dsmanager.c + + Vulkan descriptor set manager + + Copyright (C) 2023 Bill Currie + + 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 2 + 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, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/hash.h" +#include "QF/va.h" +#include "QF/Vulkan/debug.h" +#include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" +#include "QF/Vulkan/render.h" +#include "QF/Vulkan/resource.h" + +#include "vid_vulkan.h" + +qfv_dsmanager_t * +QFV_DSManager_Create (const qfv_descriptorsetlayoutinfo_t *setLayoutInfo, + uint32_t maxSets, vulkan_ctx_t *ctx) +{ + VkDescriptorPoolCreateFlags poolFlags = setLayoutInfo->flags + & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + size_t size = sizeof (qfv_dsmanager_t); + size += sizeof (VkDescriptorPoolSize[setLayoutInfo->num_bindings]); + qfv_dsmanager_t *setManager = malloc (size); + auto poolSizes = (VkDescriptorPoolSize *) &setManager[1]; + *setManager = (qfv_dsmanager_t) { + .name = setLayoutInfo->name, + .device = ctx->device, + .poolCreateInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = poolFlags, + .maxSets = maxSets, + .poolSizeCount = setLayoutInfo->num_bindings, + .pPoolSizes = poolSizes, + }, + .freePools = DARRAY_STATIC_INIT (4), + .usedPools = DARRAY_STATIC_INIT (4), + .freeSets = DARRAY_STATIC_INIT (4), + }; + for (uint32_t i = 0; i < setLayoutInfo->num_bindings; i++) { + auto binding = setLayoutInfo->bindings[i]; + poolSizes[i] = (VkDescriptorPoolSize) { + .type = binding.descriptorType, + .descriptorCount = maxSets * binding.descriptorCount, + }; + }; + + qfv_device_t *device = ctx->device; + qfv_devfuncs_t *dfunc = setManager->device->funcs; + + VkDescriptorSetLayoutCreateInfo cInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .flags = setLayoutInfo->flags, + .bindingCount = setLayoutInfo->num_bindings, + .pBindings = setLayoutInfo->bindings, + }; + dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, + &setManager->layout); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, + setManager->layout, + va (ctx->va_ctx, "descriptorSetLayout:%s", + setLayoutInfo->name)); + + return setManager; +} + +void +QFV_DSManager_Destroy (qfv_dsmanager_t *setManager) +{ + if (!setManager) { + return; + } + VkDevice dev = setManager->device->dev; + qfv_devfuncs_t *dfunc = setManager->device->funcs; + + for (size_t i = 0; i < setManager->freePools.size; i++) { + dfunc->vkDestroyDescriptorPool (dev, setManager->freePools.a[i], 0); + } + for (size_t i = 0; i < setManager->usedPools.size; i++) { + dfunc->vkDestroyDescriptorPool (dev, setManager->usedPools.a[i], 0); + } + if (setManager->activePool) { + dfunc->vkDestroyDescriptorPool (dev, setManager->activePool, 0); + } + DARRAY_CLEAR (&setManager->freePools); + DARRAY_CLEAR (&setManager->usedPools); + DARRAY_CLEAR (&setManager->freeSets); + + dfunc->vkDestroyDescriptorSetLayout (dev, setManager->layout, 0); + free (setManager); +} + +VkDescriptorSet +QFV_DSManager_AllocSet (qfv_dsmanager_t *setManager) +{ + if (setManager->freeSets.size) { + uint32_t ind = --setManager->freeSets.size; + return setManager->freeSets.a[ind]; + } + VkDevice dev = setManager->device->dev; + qfv_devfuncs_t *dfunc = setManager->device->funcs; + VkResult res; +retry: + if (setManager->activePool) { + VkDescriptorSet set; + VkDescriptorSetAllocateInfo aInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = setManager->activePool, + .descriptorSetCount = 1, + .pSetLayouts = &setManager->layout, + }; + res = dfunc->vkAllocateDescriptorSets (dev, &aInfo, &set); + if (res == VK_SUCCESS) { + return set; + } + if (res != VK_ERROR_OUT_OF_POOL_MEMORY) { + Sys_Error ("failed to allocate descriptor set: %d", res); + } + DARRAY_APPEND (&setManager->usedPools, setManager->activePool); + } + if (setManager->freePools.size) { + uint32_t ind = --setManager->freePools.size; + setManager->activePool = setManager->freePools.a[ind]; + goto retry; + } + + res = dfunc->vkCreateDescriptorPool (dev, &setManager->poolCreateInfo, 0, + &setManager->activePool); + if (res != VK_SUCCESS) { + Sys_Error ("failed to create descriptor set pool: %d", res); + } + goto retry; +} + +void +QFV_DSManager_FreeSet (qfv_dsmanager_t *setManager, VkDescriptorSet set) +{ + DARRAY_APPEND (&setManager->freeSets, set); +} diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 1767b76cb..71dbd2280 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -44,6 +44,7 @@ #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/render.h" @@ -89,15 +90,6 @@ run_pipeline (qfv_pipeline_t *pipeline, qfv_taskctx_t *taskctx) taskctx->pipeline = pipeline; run_tasks (pipeline->task_count, pipeline->tasks, taskctx); - - if (pipeline->num_descriptorsets) { - dfunc->vkCmdBindDescriptorSets (cmd, pipeline->bindPoint, - pipeline->layout, - pipeline->first_descriptorset, - pipeline->num_descriptorsets, - pipeline->descriptorsets, - 0, 0); - } } // https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/ @@ -119,8 +111,6 @@ run_subpass (qfv_subpass_t *sp, qfv_taskctx_t *taskctx) static void run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx) { - //printf ("%10.2f run_renderpass: %s\n", Sys_DoubleTime (), rp->label.name); - qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; __auto_type rctx = ctx->render_context; @@ -168,8 +158,6 @@ static void run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) { - //printf ("run_compute_pipeline: %s\n", pipeline->label.name); - qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkCmdBindPipeline (cmd, pipeline->bindPoint, pipeline->pipeline); @@ -181,14 +169,6 @@ run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, }; run_tasks (pipeline->task_count, pipeline->tasks, &taskctx); - if (pipeline->num_descriptorsets) { - dfunc->vkCmdBindDescriptorSets (cmd, pipeline->bindPoint, - pipeline->layout, - pipeline->first_descriptorset, - pipeline->num_descriptorsets, - pipeline->descriptorsets, - 0, 0); - } vec4u_t d = pipeline->dispatch; if (d[0] && d[1] && d[2]) { dfunc->vkCmdDispatch (cmd, d[0], d[1], d[2]); @@ -240,7 +220,6 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) for (uint32_t i = 0; i < job->num_steps; i++) { __auto_type step = &job->steps[i]; - //printf ("%10.2f run_step: %s\n", Sys_DoubleTime (), step->label.name); if (step->render) { run_renderpass (step->render->active, ctx); } @@ -264,8 +243,6 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx) job->commands.size, job->commands.a, 1, &frame->renderDoneSemaphore, }; - //printf ("%10.2f submit for frame %d: %zd %p\n", Sys_DoubleTime (), - // ctx->curFrame, job->commands.size, frame->imageAvailableSemaphore); dfunc->vkResetFences (device->dev, 1, &frame->fence); dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence); @@ -503,6 +480,9 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) } } DARRAY_CLEAR (&job->commands); + for (uint32_t i = 0; i < job->num_dsmanagers; i++) { + QFV_DSManager_Destroy (job->dsmanager[i]); + } free (rctx->job); } @@ -519,8 +499,8 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) if (rctx->jobinfo) { __auto_type jinfo = rctx->jobinfo; - for (uint32_t i = 0; i < jinfo->num_descriptorsetlayouts; i++) { - __auto_type setLayout = jinfo->descriptorsetlayouts[i].setLayout; + for (uint32_t i = 0; i < jinfo->num_dslayouts; i++) { + __auto_type setLayout = jinfo->dslayouts[i].setLayout; dfunc->vkDestroyDescriptorSetLayout (device->dev, setLayout, 0); } delete_memsuper (jinfo->memsuper); diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 1e284f544..ccc79e658 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -44,6 +44,7 @@ #include "QF/Vulkan/command.h" #include "QF/Vulkan/debug.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/pipeline.h" #include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" @@ -107,7 +108,7 @@ typedef struct { uint32_t num_graph_pipelines; uint32_t num_comp_pipelines; - uint32_t num_descriptorsets; + uint32_t num_ds_indices; } objcount_t; static void @@ -347,36 +348,42 @@ find_subpass (qfv_dependencyinfo_t *d, uint32_t spind, Sys_Error ("invalid dependency: [%d] %s", spind, d->name); } -static VkDescriptorSetLayout -find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) +static uint32_t __attribute__((pure)) +find_ds_index (const qfv_reference_t *ref, objstate_t *s) { - for (uint32_t i = 0; i < s->jinfo->num_descriptorsetlayouts; i++) { - __auto_type ds = &s->jinfo->descriptorsetlayouts[i]; + for (uint32_t i = 0; i < s->jinfo->num_dslayouts; i++) { + __auto_type ds = &s->jinfo->dslayouts[i]; if (strcmp (ds->name, ref->name) == 0) { - if (!ds->setLayout) { - VkDescriptorSetLayoutCreateInfo cInfo = { - .sType=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .flags = ds->flags, - .bindingCount = ds->num_bindings, - .pBindings = ds->bindings, - }; - qfv_device_t *device = s->ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, - &ds->setLayout); - QFV_duSetObjectName (device, - VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, - ds->setLayout, - va (s->ctx->va_ctx, "descriptorSet:%s", - ds->name)); - } - return ds->setLayout; + return i; } } Sys_Error ("%s.%s:%d: invalid descriptor set layout: %s", s->rpi->name, s->spi->name, ref->line, ref->name); } +static VkDescriptorSetLayout +find_descriptorSet (const qfv_reference_t *ref, objstate_t *s) +{ + auto ds = &s->jinfo->dslayouts[find_ds_index (ref, s)]; + if (ds->setLayout) { + return ds->setLayout; + } + + VkDescriptorSetLayoutCreateInfo cInfo = { + .sType=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .flags = ds->flags, + .bindingCount = ds->num_bindings, + .pBindings = ds->bindings, + }; + qfv_device_t *device = s->ctx->device; + qfv_devfuncs_t *dfunc = device->funcs; + dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, &ds->setLayout); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, + ds->setLayout, va (s->ctx->va_ctx, "descriptorSet:%s", + ds->name)); + return ds->setLayout; +} + #define RUP(x,a) (((x) + ((a) - 1)) & ~((a) - 1)) static uint32_t @@ -515,7 +522,7 @@ init_plCreate (VkGraphicsPipelineCreateInfo *plc, const qfv_pipelineinfo_t *pli, if (pli->layout.name) { __auto_type li = find_layout (&pli->layout, s); plc->layout = li->layout; - s->inds.num_descriptorsets += li->num_sets; + s->inds.num_ds_indices += li->num_sets; } } @@ -722,7 +729,7 @@ typedef struct { qfv_subpass_t *subpasses; qfv_pipeline_t *pipelines; qfv_taskinfo_t *tasks; - VkDescriptorSet *descriptorsets; + uint32_t *ds_indices; VkImageView *attachment_views; } jobptr_t; @@ -743,12 +750,13 @@ init_pipeline (qfv_pipeline_t *pl, qfv_pipelineinfo_t *plinfo, .layout = li->layout, .task_count = plinfo->num_tasks, .tasks = &jp->tasks[s->inds.num_tasks], - .descriptorsets = &jp->descriptorsets[s->inds.num_descriptorsets], + .num_indices = li->num_sets, + .ds_indices = &jp->ds_indices[s->inds.num_ds_indices], }; s->inds.num_tasks += plinfo->num_tasks; - s->inds.num_descriptorsets += li->num_sets; - for (uint32_t i = 0; i < li->num_sets; i++) { - pl->descriptorsets[i] = 0; + s->inds.num_ds_indices += li->num_sets; + for (uint32_t i = 0; i < pl->num_indices; i++) { + pl->ds_indices[i] = find_ds_index (&li->sets[i], s); } for (uint32_t i = 0; i < pl->task_count; i++) { pl->tasks[i] = plinfo->tasks[i]; @@ -894,7 +902,8 @@ init_step (uint32_t ind, jobptr_t *jp, objstate_t *s) static void init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) { - __auto_type rctx = ctx->render_context; + auto rctx = ctx->render_context; + auto jobinfo = rctx->jobinfo; size_t size = sizeof (qfv_job_t); @@ -913,8 +922,9 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) size += sizeof (VkPipeline [counts->num_graph_pipelines]); size += sizeof (VkPipeline [counts->num_comp_pipelines]); size += sizeof (VkPipelineLayout [s.inds.num_layouts]); - size += sizeof (VkDescriptorSet [counts->num_descriptorsets]); size += sizeof (VkImageView [counts->num_attachments]); + size += sizeof (qfv_dsmanager_t *[jobinfo->num_dslayouts]); + size += sizeof (uint32_t [counts->num_ds_indices]); rctx->job = malloc (size); auto job = rctx->job; @@ -925,6 +935,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) .num_layouts = s.inds.num_layouts, .num_steps = counts->num_steps, .commands = DARRAY_STATIC_INIT (16), + .num_dsmanagers = jobinfo->num_dslayouts, }; job->steps = (qfv_step_t *) &job[1]; auto rn = (qfv_render_t *) &job->steps[job->num_steps]; @@ -939,8 +950,10 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) job->renderpasses = (VkRenderPass *) &cv[counts->num_attachments]; job->pipelines = (VkPipeline *) &job->renderpasses[job->num_renderpasses]; job->layouts = (VkPipelineLayout *) &job->pipelines[job->num_pipelines]; - auto ds = (VkDescriptorSet *) &job->layouts[job->num_layouts]; - auto av = (VkImageView *) &ds[counts->num_descriptorsets]; + auto av = (VkImageView *) &job->layouts[s.inds.num_layouts]; + job->dsmanager = (qfv_dsmanager_t **) &av[counts->num_attachments]; + auto ds = (uint32_t *) &job->dsmanager[jobinfo->num_dslayouts]; + jobptr_t jp = { .steps = job->steps, .renders = rn, @@ -951,7 +964,7 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) .subpasses = sp, .pipelines = pl, .tasks = ti, - .descriptorsets = ds, + .ds_indices = ds, .attachment_views = av, }; @@ -973,6 +986,10 @@ init_job (vulkan_ctx_t *ctx, objcount_t *counts, objstate_t s) for (uint32_t i = 0; i < job->num_steps; i++) { init_step (i, &jp, &s); } + for (uint32_t i = 0; i < job->num_dsmanagers; i++) { + auto layoutInfo = &jobinfo->dslayouts[i]; + job->dsmanager[i] = QFV_DSManager_Create (layoutInfo, 16, ctx); + } } static void @@ -1013,7 +1030,7 @@ create_step_compute_objects (uint32_t index, const qfv_stepinfo_t *step, }; plc->stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; s->inds.num_comp_pipelines++; - s->inds.num_descriptorsets += li->num_sets; + s->inds.num_ds_indices += li->num_sets; } } @@ -1132,7 +1149,7 @@ create_objects (vulkan_ctx_t *ctx, objcount_t *counts) va (ctx->va_ctx, "pipeline:%s", plName[i])); } - counts->num_descriptorsets = s.inds.num_descriptorsets; + counts->num_ds_indices = s.inds.num_ds_indices; init_job (ctx, counts, s); } diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 9fac09874..cc0149e63 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -776,8 +776,8 @@ parse = { }; descriptorSetLayouts = { type = (labeledarray, qfv_descriptorsetlayoutinfo_t, name); - size = num_descriptorsetlayouts; - values = descriptorsetlayouts; + size = num_dslayouts; + values = dslayouts; }; }; }; From 6ce42fd3477f4264f01b7773955a007d21a743cb Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jun 2023 15:23:59 +0900 Subject: [PATCH 3648/3664] [vulkan] Document the texture sets I got tired of wondering what they were for. --- libs/video/renderer/vulkan/rp_main_def.plist | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index e1f2a02ff..6a4f39682 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -256,8 +256,9 @@ properties = { primitiveRestartEnable = true; }; layout = { - descriptorSets = (matrix_set, entity_set, oit_set, texture_set, - texture_set); + descriptorSets = (matrix_set, entity_set, oit_set, + // surface skybox + texture_set, texture_set); pushConstants = { fragment = { fog = vec4; @@ -305,6 +306,7 @@ properties = { primitiveRestartEnable = false; }; layout = { + // palette skin descriptorSets = (matrix_set, texture_set, texture_set); pushConstants = { vertex = { Model = mat4; blend = float; }; @@ -368,6 +370,7 @@ properties = { primitiveRestartEnable = false; }; layout = { + // skin descriptorSets = (matrix_set, texture_set, bone_set); pushConstants = { vertex = { @@ -466,6 +469,7 @@ properties = { }; layout = { draw = { + // palette descriptorSets = (matrix_set, texture_set, oit_set); pushConstants = { vertex = { Model = mat4; }; @@ -478,6 +482,7 @@ properties = { }; }; update = { + // cur in new descriptorSets = (particle_set, particle_set, particle_set); }; }; From b9bb84174404352ee06754bf68020bb3a0b08f23 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 24 Jun 2023 21:42:46 +0900 Subject: [PATCH 3649/3664] [vulkan] Use the descriptor set manager This cleans up a lot of ugly code that I always thought was rather dumb. --- include/QF/Vulkan/qf_bsp.h | 6 +- include/QF/Vulkan/qf_compose.h | 1 + include/QF/Vulkan/qf_draw.h | 8 +- include/QF/Vulkan/qf_iqm.h | 3 +- include/QF/Vulkan/qf_lighting.h | 2 +- include/QF/Vulkan/qf_matrices.h | 19 ++- include/QF/Vulkan/qf_output.h | 1 + include/QF/Vulkan/qf_particles.h | 11 +- include/QF/Vulkan/qf_scene.h | 3 +- include/QF/Vulkan/qf_sprite.h | 3 +- include/QF/Vulkan/qf_texture.h | 4 +- include/QF/Vulkan/qf_translucent.h | 4 +- include/QF/Vulkan/qf_vid.h | 10 -- include/QF/Vulkan/render.h | 4 + libs/video/renderer/vid_render_vulkan.c | 13 +- libs/video/renderer/vulkan/render.c | 13 ++ libs/video/renderer/vulkan/vkparse.c | 117 ------------------ libs/video/renderer/vulkan/vulkan_bsp.c | 21 ++-- libs/video/renderer/vulkan/vulkan_compose.c | 26 ++-- libs/video/renderer/vulkan/vulkan_draw.c | 110 ++++++---------- libs/video/renderer/vulkan/vulkan_iqm.c | 44 +++---- libs/video/renderer/vulkan/vulkan_lighting.c | 67 ++++------ libs/video/renderer/vulkan/vulkan_matrices.c | 87 ++++++------- libs/video/renderer/vulkan/vulkan_output.c | 44 +++---- libs/video/renderer/vulkan/vulkan_particles.c | 31 +++-- libs/video/renderer/vulkan/vulkan_scene.c | 28 ++--- libs/video/renderer/vulkan/vulkan_sprite.c | 22 +--- libs/video/renderer/vulkan/vulkan_texture.c | 36 +++--- .../renderer/vulkan/vulkan_translucent.c | 26 ++-- 29 files changed, 274 insertions(+), 490 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index 0efc60eea..b36c9697f 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -368,11 +368,6 @@ typedef struct bspctx_s { VkSampler sampler; VkDeviceMemory texture_memory; - VkPipeline depth; - VkPipeline gbuf; - VkPipeline skysheet; - VkPipeline skybox; - VkPipeline turb; size_t vertex_buffer_size; size_t index_buffer_size; VkBuffer vertex_buffer; @@ -392,6 +387,7 @@ void Vulkan_RegisterTextures (model_t **models, int num_models, void Vulkan_BuildDisplayLists (model_t **models, int num_models, struct vulkan_ctx_s *ctx); void Vulkan_Bsp_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Bsp_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx); ///@} diff --git a/include/QF/Vulkan/qf_compose.h b/include/QF/Vulkan/qf_compose.h index 6364fa962..cc59f8b63 100644 --- a/include/QF/Vulkan/qf_compose.h +++ b/include/QF/Vulkan/qf_compose.h @@ -53,6 +53,7 @@ typedef struct composectx_s { struct vulkan_ctx_s; void Vulkan_Compose_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Compose_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Compose_Shutdown (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_compose_h diff --git a/include/QF/Vulkan/qf_draw.h b/include/QF/Vulkan/qf_draw.h index 7ef57dc82..c7ba2b1d6 100644 --- a/include/QF/Vulkan/qf_draw.h +++ b/include/QF/Vulkan/qf_draw.h @@ -30,14 +30,7 @@ #include "QF/screen.h" -typedef enum { - QFV_draw2d, - - QFV_drawNumPasses -} QFV_DrawSubpass; - struct vulkan_ctx_s; -struct qfv_renderframe_s; struct qpic_s; struct font_s; struct draw_charbuffer_s; @@ -45,6 +38,7 @@ struct draw_charbuffer_s; void Vulkan_Draw_CharBuffer (int x, int y, struct draw_charbuffer_s *buffer, struct vulkan_ctx_s *ctx); void Vulkan_Draw_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Draw_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Draw_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Draw_Character (int x, int y, unsigned ch, struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h index 1138eaa16..537547147 100644 --- a/include/QF/Vulkan/qf_iqm.h +++ b/include/QF/Vulkan/qf_iqm.h @@ -90,8 +90,7 @@ typedef struct iqmindset_s typedef struct iqmctx_s { iqm_frameset_t frames; VkSampler sampler; - VkDescriptorPool bones_pool; - VkDescriptorSetLayout bones_setLayout; + struct qfv_dsmanager_s *dsmanager; } iqmctx_t; struct vulkan_ctx_s; diff --git a/include/QF/Vulkan/qf_lighting.h b/include/QF/Vulkan/qf_lighting.h index 469bb5b4c..54d4c3856 100644 --- a/include/QF/Vulkan/qf_lighting.h +++ b/include/QF/Vulkan/qf_lighting.h @@ -95,7 +95,6 @@ typedef struct light_renderer_set_s typedef struct lightingctx_s { lightingframeset_t frames; VkPipeline pipeline; - VkPipelineLayout layout; VkSampler sampler; VkDeviceMemory light_memory; struct qfv_resource_s *shadow_resources; @@ -114,6 +113,7 @@ typedef struct lightingctx_s { struct vulkan_ctx_s; void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Lighting_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_LoadLights (struct scene_s *scene, struct vulkan_ctx_s *ctx); diff --git a/include/QF/Vulkan/qf_matrices.h b/include/QF/Vulkan/qf_matrices.h index 057dd6d81..e1c41991f 100644 --- a/include/QF/Vulkan/qf_matrices.h +++ b/include/QF/Vulkan/qf_matrices.h @@ -36,15 +36,13 @@ #include "QF/Vulkan/image.h" #include "QF/simd/types.h" -typedef struct qfv_matrix_buffer_s { +typedef __attribute__((aligned(64))) struct qfv_matrix_buffer_s { // projection and view matrices (model is push constant) mat4f_t Projection3d; mat4f_t View[6]; mat4f_t Sky; mat4f_t Projection2d; vec2f_t ScreenSize; - vec2f_t pad; //FIXME shouldn't need this (for gpu align) - vec4f_t pad2[3]; } qfv_matrix_buffer_t; typedef struct matrixframe_s { @@ -56,22 +54,20 @@ typedef struct matrixframeset_s DARRAY_TYPE (matrixframe_t) matrixframeset_t; typedef struct matrixctx_s { - matrixframeset_t frames; - VkDeviceMemory memory; qfv_matrix_buffer_t matrices; - int dirty; - struct qfv_stagebuf_s *stage; - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; - vec4f_t sky_rotation[2]; vec4f_t sky_velocity; vec4f_t sky_fix; double sky_time; + int dirty; + + matrixframeset_t frames; + + struct qfv_resource_s *resource; + struct qfv_stagebuf_s *stage; } matrixctx_t; struct vulkan_ctx_s; -struct qfv_renderframe_s; void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx); void Vulkan_SetViewMatrices (struct vulkan_ctx_s *ctx, mat4f_t views[], @@ -80,6 +76,7 @@ void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky); void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky); void Vulkan_Matrix_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Matrix_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Matrix_Shutdown (struct vulkan_ctx_s *ctx); VkDescriptorSet Vulkan_Matrix_Descriptors (struct vulkan_ctx_s *ctx, int frame) __attribute__((pure)); diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index aeaada73d..17a31e8a5 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -52,6 +52,7 @@ typedef struct outputctx_s { struct vulkan_ctx_s; void Vulkan_Output_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Output_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx); void Vulkan_Output_SetInput (struct vulkan_ctx_s *ctx, VkImageView input); diff --git a/include/QF/Vulkan/qf_particles.h b/include/QF/Vulkan/qf_particles.h index ba3d0d906..72d07eee5 100644 --- a/include/QF/Vulkan/qf_particles.h +++ b/include/QF/Vulkan/qf_particles.h @@ -30,12 +30,6 @@ typedef struct qfv_particle_system_s { uint32_t firstInstance; // always 0 } qfv_particle_system_t; -typedef enum { - QFV_particleTranslucent, - - QFV_particleNumPasses -} QFV_ParticleSubpass; - typedef struct particleframe_s { VkEvent physicsEvent; VkEvent updateEvent; @@ -57,17 +51,14 @@ typedef struct particlectx_s { struct qfv_resource_s *resources; struct qfv_stagebuf_s *stage; - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; - psystem_t *psystem; } particlectx_t; -struct cvar_s; struct vulkan_ctx_s; struct psystem_s *Vulkan_ParticleSystem (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Particles_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Particles_Shutdown (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_particles_h diff --git a/include/QF/Vulkan/qf_scene.h b/include/QF/Vulkan/qf_scene.h index 428b5ceab..cd35abd1e 100644 --- a/include/QF/Vulkan/qf_scene.h +++ b/include/QF/Vulkan/qf_scene.h @@ -63,8 +63,6 @@ typedef struct scnframeset_s typedef struct scenectx_s { struct qfv_resource_s *entities; scnframeset_t frames; - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; int max_entities; } scenectx_t; @@ -72,6 +70,7 @@ struct vulkan_ctx_s; struct entity_s; void Vulkan_Scene_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Scene_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Scene_Shutdown (struct vulkan_ctx_s *ctx); int Vulkan_Scene_MaxEntities (struct vulkan_ctx_s *ctx) __attribute__((pure)); VkDescriptorSet Vulkan_Scene_Descriptors (struct vulkan_ctx_s *ctx) __attribute__((pure)); diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index 19c552397..1b2ab04bf 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -59,8 +59,7 @@ typedef enum { } QFV_SpriteSubpass; typedef struct spritectx_s { - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; + struct qfv_dsmanager_s *dsmanager; unsigned maxImages; VkSampler sampler; } spritectx_t; diff --git a/include/QF/Vulkan/qf_texture.h b/include/QF/Vulkan/qf_texture.h index 0253365b8..835ee624c 100644 --- a/include/QF/Vulkan/qf_texture.h +++ b/include/QF/Vulkan/qf_texture.h @@ -11,8 +11,7 @@ typedef struct qfv_tex_s { } qfv_tex_t; typedef struct texturectx_s { - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; + struct qfv_dsmanager_s *dsmanager; } texturectx_t; void Vulkan_ExpandPalette (byte *dst, const byte *src, const byte *palette, @@ -30,6 +29,7 @@ void Vulkan_UpdateTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex, tex_t *src, int x, int y, int layer, int mip); void Vulkan_UnloadTex (struct vulkan_ctx_s *ctx, qfv_tex_t *tex); void Vulkan_Texture_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Texture_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Texture_Shutdown (struct vulkan_ctx_s *ctx); VkDescriptorSet Vulkan_CreateCombinedImageSampler (struct vulkan_ctx_s *ctx, VkImageView view, diff --git a/include/QF/Vulkan/qf_translucent.h b/include/QF/Vulkan/qf_translucent.h index a62ba8a57..1e8079d32 100644 --- a/include/QF/Vulkan/qf_translucent.h +++ b/include/QF/Vulkan/qf_translucent.h @@ -29,17 +29,15 @@ typedef struct translucentframeset_s typedef struct translucentctx_s { translucentframeset_t frames; - struct qfv_resource_s *resources; int maxFragments; - VkDescriptorPool pool; - VkDescriptorSetLayout setLayout; } translucentctx_t; struct vulkan_ctx_s; void Vulkan_Translucent_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Translucent_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Translucent_Shutdown (struct vulkan_ctx_s *ctx); VkDescriptorSet Vulkan_Translucent_Descriptors (struct vulkan_ctx_s *ctx, int frame)__attribute__((pure)); diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index cdfe24908..a2c5d6007 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -80,17 +80,7 @@ struct qfv_output_s; void Vulkan_ConfigOutput (struct vulkan_ctx_s *ctx, struct qfv_output_s *output); -VkPipeline Vulkan_CreateComputePipeline (struct vulkan_ctx_s *ctx, - const char *name); -VkPipeline Vulkan_CreateGraphicsPipeline (struct vulkan_ctx_s *ctx, - const char *name); -VkDescriptorPool Vulkan_CreateDescriptorPool (struct vulkan_ctx_s *ctx, - const char *name); -VkPipelineLayout Vulkan_CreatePipelineLayout (struct vulkan_ctx_s *ctx, - const char *name); VkSampler Vulkan_CreateSampler (struct vulkan_ctx_s *ctx, const char *name); -VkDescriptorSetLayout Vulkan_CreateDescriptorSetLayout(struct vulkan_ctx_s*ctx, - const char *name); struct entity_s; void Vulkan_BeginEntityLabel (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd, diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 1acf2aa6f..5a6e9dc78 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -409,6 +409,10 @@ void QFV_Render_AddTasks (struct vulkan_ctx_s *ctx, exprsym_t *task_sys); void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp); +struct qfv_dsmanager_s * +QFV_Render_DSManager (struct vulkan_ctx_s *ctx, + const char *setName) __attribute__((pure)); + qfv_step_t *QFV_GetStep (const exprval_t *param, qfv_job_t *job); qfv_step_t *QFV_FindStep (const char *step, qfv_job_t *job) __attribute__((pure)); diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 89ef8c021..ab09f3cd4 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -94,7 +94,6 @@ vulkan_R_Init (void) Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_Texture_Init (vulkan_ctx); - Vulkan_Palette_Init (vulkan_ctx, vid.palette); Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateCapture (vulkan_ctx); @@ -116,6 +115,18 @@ vulkan_R_Init (void) QFV_LoadRenderInfo (vulkan_ctx); QFV_BuildRender (vulkan_ctx); + Vulkan_Texture_Setup (vulkan_ctx); + Vulkan_Palette_Init (vulkan_ctx, vid.palette); + Vulkan_Bsp_Setup (vulkan_ctx); + Vulkan_Matrix_Setup (vulkan_ctx); + Vulkan_Scene_Setup (vulkan_ctx); + Vulkan_Output_Setup (vulkan_ctx); + Vulkan_Compose_Setup (vulkan_ctx); + Vulkan_Draw_Setup (vulkan_ctx); + Vulkan_Particles_Setup (vulkan_ctx); + Vulkan_Translucent_Setup (vulkan_ctx); + Vulkan_Lighting_Setup (vulkan_ctx); + Skin_Init (); SCR_Init (); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 71dbd2280..9fdb6ba7d 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -560,3 +560,16 @@ QFV_GetStep (const exprval_t *param, qfv_job_t *job) } return *(qfv_step_t **)stepref->value; } + +qfv_dsmanager_t * +QFV_Render_DSManager (struct vulkan_ctx_s *ctx, const char *setName) +{ + auto job = ctx->render_context->job; + for (uint32_t i = 0; i < job->num_dsmanagers; i++) { + auto ds = job->dsmanager[i]; + if (!strcmp (ds->name, setName)) { + return ds; + } + } + return 0; +} diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index d635be753..56743ee25 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -2021,96 +2021,6 @@ void Vulkan_Script_SetOutput (vulkan_ctx_t *ctx, qfv_output_t *output) sctx->output = *output; } -VkPipeline -Vulkan_CreateComputePipeline (vulkan_ctx_t *ctx, const char *name) -{ - scriptctx_t *sctx = ctx->script_context; - plitem_t *item = qfv_load_pipeline (ctx, "pipelines"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading pipeline %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline def %s\n", name); - } - VkPipeline pipeline = QFV_ParseComputePipeline (ctx, item, - sctx->pipelineDef); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, - va (ctx->va_ctx, "pipeline:%s", name)); - return pipeline; -} - -VkPipeline -Vulkan_CreateGraphicsPipeline (vulkan_ctx_t *ctx, const char *name) -{ - scriptctx_t *sctx = ctx->script_context; - plitem_t *item = qfv_load_pipeline (ctx, "pipelines"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading pipeline %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline def %s\n", name); - } - VkPipeline pipeline = QFV_ParseGraphicsPipeline (ctx, item, - sctx->pipelineDef); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, - va (ctx->va_ctx, "pipeline:%s", name)); - return pipeline; -} - -VkDescriptorPool -Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name) -{ - scriptctx_t *sctx = ctx->script_context; - hashtab_t *tab = sctx->descriptorPools; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".descriptorPools.%s", name); - __auto_type pool = (VkDescriptorPool) QFV_GetHandle (tab, path); - if (pool) { - return pool; - } - - plitem_t *item = qfv_load_pipeline (ctx, "descriptorPools"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading descriptor pool %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found descriptor pool def %s\n", - name); - } - pool = QFV_ParseDescriptorPool (ctx, item, sctx->pipelineDef); - QFV_AddHandle (tab, path, (uint64_t) pool); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool, - va (ctx->va_ctx, "descriptor_pool:%s", name)); - return pool; -} - -VkPipelineLayout -Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name) -{ - scriptctx_t *sctx = ctx->script_context; - hashtab_t *tab = sctx->pipelineLayouts; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".pipelineLayouts.%s", name); - __auto_type layout = (VkPipelineLayout) QFV_GetHandle (tab, path); - if (layout) { - return layout; - } - - plitem_t *item = qfv_load_pipeline (ctx, "pipelineLayouts"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading pipeline layout %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found pipeline layout def %s\n", - name); - } - layout = QFV_ParsePipelineLayout (ctx, item, sctx->pipelineDef); - QFV_AddHandle (tab, path, (uint64_t) layout); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, - va (ctx->va_ctx, "pipeline_layout:%s", name)); - return layout; -} - VkSampler Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) { @@ -2137,33 +2047,6 @@ Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) return sampler; } -VkDescriptorSetLayout -Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name) -{ - scriptctx_t *sctx = ctx->script_context; - hashtab_t *tab = sctx->setLayouts; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".setLayouts.%s", name); - __auto_type set = (VkDescriptorSetLayout) QFV_GetHandle (tab, path); - if (set) { - return set; - } - - plitem_t *item = qfv_load_pipeline (ctx, "setLayouts"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading descriptor set %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found descriptor set def %s\n", - name); - } - set = QFV_ParseDescriptorSetLayout (ctx, item, sctx->pipelineDef); - QFV_AddHandle (tab, path, (uint64_t) set); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, - set, va (ctx->va_ctx, "descriptor_set:%s", name)); - return set; -} - exprtab_t * QFV_CreateSymtab (plitem_t *dict, const char *properties, const char **extra_items, exprsym_t *extra_syms, diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a88f9db54..a81147739 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1439,14 +1439,21 @@ static exprsym_t bsp_task_syms[] = { void Vulkan_Bsp_Init (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - qfvPushDebug (ctx, "bsp init"); QFV_Render_AddTasks (ctx, bsp_task_syms); bspctx_t *bctx = calloc (1, sizeof (bspctx_t)); ctx->bsp_context = bctx; +} + +void +Vulkan_Bsp_Setup (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "bsp init"); + + auto device = ctx->device; + auto dfunc = device->funcs; + + auto bctx = ctx->bsp_context; bctx->light_scrap = QFV_CreateScrap (device, "lightmap_atlas", 2048, tex_frgba, ctx->staging); @@ -1540,12 +1547,6 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) free (bframe->cmdSet.a); } - dfunc->vkDestroyPipeline (device->dev, bctx->depth, 0); - dfunc->vkDestroyPipeline (device->dev, bctx->gbuf, 0); - dfunc->vkDestroyPipeline (device->dev, bctx->skybox, 0); - dfunc->vkDestroyPipeline (device->dev, bctx->skysheet, 0); - dfunc->vkDestroyPipeline (device->dev, bctx->turb, 0); - DARRAY_CLEAR (&bctx->registered_textures); for (int i = 0; i < bctx->main_pass.num_queues; i++) { DARRAY_CLEAR (&bctx->main_pass.draw_queues[i]); diff --git a/libs/video/renderer/vulkan/vulkan_compose.c b/libs/video/renderer/vulkan/vulkan_compose.c index a00141ed9..9e96e2c95 100644 --- a/libs/video/renderer/vulkan/vulkan_compose.c +++ b/libs/video/renderer/vulkan/vulkan_compose.c @@ -49,6 +49,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/render.h" @@ -106,13 +107,18 @@ static exprsym_t compose_task_syms[] = { void Vulkan_Compose_Init (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - - qfvPushDebug (ctx, "compose init"); QFV_Render_AddTasks (ctx, compose_task_syms); composectx_t *cctx = calloc (1, sizeof (composectx_t)); ctx->compose_context = cctx; +} + +void +Vulkan_Compose_Setup (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "compose init"); + + auto cctx = ctx->compose_context; auto rctx = ctx->render_context; size_t frames = rctx->frames.size; @@ -120,16 +126,7 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&cctx->frames, frames); cctx->frames.grow = 0; - __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - for (size_t i = 0; i < frames; i++) { - attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, - "compose_attach"); - } - __auto_type attach_pool = Vulkan_CreateDescriptorPool (ctx, - "compose_attach_pool"); - - __auto_type attach_set = QFV_AllocateDescriptorSet (device, attach_pool, - attach); + auto dsmanager = QFV_Render_DSManager (ctx, "compose_attach"); for (size_t i = 0; i < frames; i++) { __auto_type cframe = &cctx->frames.a[i]; @@ -137,12 +134,11 @@ Vulkan_Compose_Init (vulkan_ctx_t *ctx) cframe->imageInfo[j] = base_image_info; cframe->imageInfo[j].sampler = 0; cframe->descriptors[j] = base_image_write; - cframe->descriptors[j].dstSet = attach_set->a[i]; + cframe->descriptors[j].dstSet = QFV_DSManager_AllocSet (dsmanager); cframe->descriptors[j].dstBinding = j; cframe->descriptors[j].pImageInfo = &cframe->imageInfo[j]; } } - free (attach_set); qfvPopDebug (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 3be6e00da..742d8c11f 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -60,6 +60,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/render.h" @@ -123,13 +124,11 @@ typedef struct cachepic_s { // core pic atlas + static verts #define CORE_DESC 0 -// FIXME must match pool size in pl_quake_def.plist descriptorPools.quad_pool -// should do some reflection +// FIXME make dynamic #define MAX_DESCIPTORS 64 typedef struct descpool_s { VkDescriptorSet sets[MAX_DESCIPTORS]; - VkDescriptorPool pool; struct drawctx_s *dctx; uint32_t users[MAX_DESCIPTORS];// picdata_t.descid int in_use; @@ -149,7 +148,6 @@ typedef struct drawframe_s { descbatchset_t quad_batch; quadqueue_t quad_insts; linequeue_t line_verts; - qfv_cmdbufferset_t cmdSet; descpool_t dyn_descs; } drawframe_t; @@ -190,6 +188,7 @@ typedef struct drawctx_s { memsuper_t *pic_memsuper; memsuper_t *string_memsuper; hashtab_t *pic_cache; + qfv_dsmanager_t *dsmanager; qfv_resource_t *draw_resource; qfv_resobj_t *index_object; qfv_resobj_t *svertex_objects; @@ -198,12 +197,6 @@ typedef struct drawctx_s { qfv_resobj_t *lvertex_objects; uint32_t svertex_index; uint32_t svertex_max; - VkPipeline quad_pipeline; - VkPipeline line_pipeline; - VkPipelineLayout lines_layout; - VkPipelineLayout quad_layout; - VkDescriptorSetLayout quad_data_set_layout; - VkDescriptorPool quad_pool; VkDescriptorSet core_quad_set; drawframeset_t frames; drawfontset_t fonts; @@ -228,10 +221,12 @@ static int get_dyn_descriptor (descpool_t *pool, qpic_t *pic, VkBufferView buffer_view, vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; + auto device = ctx->device; + auto dfunc = device->funcs; + auto dctx = ctx->draw_context; auto pd = (picdata_t *) pic->data; uint32_t id = pd->descid; + for (int i = 0; i < pool->in_use; i++) { if (pool->users[i] == id) { return ~i; @@ -243,11 +238,7 @@ get_dyn_descriptor (descpool_t *pool, qpic_t *pic, VkBufferView buffer_view, int descid = pool->in_use++; pool->users[descid] = id; if (!pool->sets[descid]) { - auto layout = QFV_AllocDescriptorSetLayoutSet (1, alloca); - layout->a[0] = pool->dctx->quad_data_set_layout; - auto set = QFV_AllocateDescriptorSet (device, pool->pool, layout); - pool->sets[descid] = set->a[0];; - free (set);//FIXME allocation + pool->sets[descid] = QFV_DSManager_AllocSet (dctx->dsmanager); } VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, @@ -716,11 +707,7 @@ load_lmp (const char *path, vulkan_ctx_t *ctx) &imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]); QFV_PacketSubmit (packet); - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "quad_data_set"); - __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool"); - __auto_type cache_sets = QFV_AllocateDescriptorSet (device, pool, layouts); - font->set = cache_sets->a[0]; + font->set = QFV_DSManager_AllocSet (dctx->dsmanager);; VkDescriptorImageInfo imageInfo = { dctx->pic_sampler, cache_iview->image_view.view, @@ -737,7 +724,6 @@ load_lmp (const char *path, vulkan_ctx_t *ctx) 0, 0, &dctx->svertex_objects[1].buffer_view.view }, }; dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); - free (cache_sets); qpic_t *pic; pic = cmemalloc (dctx->pic_memsuper, @@ -779,9 +765,8 @@ Vulkan_Draw_UncachePic (const char *path, vulkan_ctx_t *ctx) void Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - drawctx_t *dctx = ctx->draw_context; + auto device = ctx->device; + auto dctx = ctx->draw_context; QFV_DestroyResource (device, &dctx->draw_resource[0]); QFV_DestroyResource (device, &dctx->draw_resource[1]); @@ -792,8 +777,6 @@ Vulkan_Draw_Shutdown (vulkan_ctx_t *ctx) } } - dfunc->vkDestroyPipeline (device->dev, dctx->quad_pipeline, 0); - dfunc->vkDestroyPipeline (device->dev, dctx->line_pipeline, 0); Hash_DelTable (dctx->pic_cache); delete_memsuper (dctx->pic_memsuper); delete_memsuper (dctx->string_memsuper); @@ -870,12 +853,15 @@ load_white_pic (vulkan_ctx_t *ctx) } static void -draw_quads (vulkan_ctx_t *ctx, VkCommandBuffer cmd) +draw_quads (qfv_taskctx_t *taskctx) { + auto ctx = taskctx->ctx; auto device = ctx->device; auto dfunc = device->funcs; auto dctx = ctx->draw_context; auto dframe = &dctx->frames.a[ctx->curFrame]; + auto layout = taskctx->pipeline->layout; + auto cmd = taskctx->cmd; VkBuffer instance_buffer = dframe->instance_buffer; VkDeviceSize offsets[] = {0}; @@ -895,7 +881,6 @@ draw_quads (vulkan_ctx_t *ctx, VkCommandBuffer cmd) fontid < 0 ? dframe->dyn_descs.sets[~fontid] : dctx->fonts.a[fontid].set, }; - VkPipelineLayout layout = dctx->quad_layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 2, set, 0, 0); @@ -906,12 +891,15 @@ draw_quads (vulkan_ctx_t *ctx, VkCommandBuffer cmd) } static void -draw_lines (vulkan_ctx_t *ctx, VkCommandBuffer cmd) +draw_lines (qfv_taskctx_t *taskctx) { + auto ctx = taskctx->ctx; auto device = ctx->device; auto dfunc = device->funcs; auto dctx = ctx->draw_context; auto dframe = &dctx->frames.a[ctx->curFrame]; + auto layout = taskctx->pipeline->layout; + auto cmd = taskctx->cmd; VkBuffer line_buffer = dframe->line_buffer; VkDeviceSize offsets[] = {0}; @@ -919,7 +907,6 @@ draw_lines (vulkan_ctx_t *ctx, VkCommandBuffer cmd) VkDescriptorSet set[1] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), }; - VkPipelineLayout layout = dctx->lines_layout; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 1, set, 0, 0); dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE, @@ -962,7 +949,7 @@ slice_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) #undef a dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); - draw_quads (ctx, taskctx->cmd); + draw_quads (taskctx); dframe->quad_insts.count = 0; dframe->dvertex_index = 0; @@ -995,7 +982,7 @@ line_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) #undef a dfunc->vkFlushMappedMemoryRanges (device->dev, 1, ranges); - draw_lines (ctx, taskctx->cmd); + draw_lines (taskctx); dframe->line_verts.count = 0; } @@ -1046,13 +1033,20 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) { QFV_Render_AddTasks (ctx, draw_task_syms); - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - qfvPushDebug (ctx, "draw init"); - drawctx_t *dctx = calloc (1, sizeof (drawctx_t)); ctx->draw_context = dctx; +} + +void +Vulkan_Draw_Setup (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "draw init"); + + auto device = ctx->device; + auto dfunc = device->funcs; + auto dctx = ctx->draw_context; + + dctx->dsmanager = QFV_Render_DSManager (ctx, "quad_data_set"); auto rctx = ctx->render_context; size_t frames = rctx->frames.size; @@ -1089,17 +1083,7 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) flush_draw_scrap (ctx); - dctx->lines_layout = Vulkan_CreatePipelineLayout (ctx, "lines_layout"); - dctx->quad_layout = Vulkan_CreatePipelineLayout (ctx, "quad_layout"); - __auto_type sl = Vulkan_CreateDescriptorSetLayout (ctx, "quad_data_set"); - dctx->quad_data_set_layout = sl; - dctx->quad_pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool"); - // core set + dynamic sets - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1 + frames, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = dctx->quad_data_set_layout; - } VkDescriptorImageInfo imageInfo = { dctx->pic_sampler, @@ -1107,17 +1091,11 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, }; - __auto_type pool = dctx->quad_pool; - __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); - for (size_t i = 1; i < sets->size; i++) { - __auto_type frame = &dctx->frames.a[i - 1]; - frame->dyn_descs = (descpool_t) {}; - //FIXME returns same pool every time - frame->dyn_descs.pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool"); - frame->dyn_descs.dctx = dctx; + for (size_t i = 0; i < frames; i++) { + __auto_type frame = &dctx->frames.a[i]; + frame->dyn_descs = (descpool_t) { .dctx = dctx }; } - dctx->core_quad_set = sets->a[0]; - free (sets); + dctx->core_quad_set = QFV_DSManager_AllocSet (dctx->dsmanager); VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, @@ -1133,13 +1111,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx) DARRAY_APPEND (&dctx->fonts, (drawfont_t) { .set = dctx->core_quad_set }); - for (size_t i = 0; i < frames; i++) { - __auto_type dframe = &dctx->frames.a[i]; - - DARRAY_INIT (&dframe->cmdSet, QFV_drawNumPasses); - DARRAY_RESIZE (&dframe->cmdSet, QFV_drawNumPasses); - dframe->cmdSet.grow = 0; - } qfvPopDebug (ctx); } @@ -1701,11 +1672,7 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) &imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]); QFV_PacketSubmit (packet); - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "quad_data_set"); - __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "quad_pool"); - __auto_type glyph_sets = QFV_AllocateDescriptorSet (device, pool, layouts); - font->set = glyph_sets->a[0]; + font->set = QFV_DSManager_AllocSet (dctx->dsmanager);; VkDescriptorImageInfo imageInfo = { dctx->glyph_sampler, glyph_iview->image_view.view, @@ -1722,7 +1689,6 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx) 0, 0, &glyph_bview->buffer_view.view }, }; dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); - free (glyph_sets); return fontid; } diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 5ac1e0318..4908a0d06 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -45,6 +45,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/resource.h" #include "QF/Vulkan/render.h" @@ -123,26 +124,23 @@ Vulkan_IQMAddBones (vulkan_ctx_t *ctx, iqm_t *iqm) { qfvPushDebug (ctx, "Vulkan_IQMAddBones"); - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - iqmctx_t *ictx = ctx->iqm_context; - __auto_type mesh = (qfv_iqm_t *) iqm->extra_data; - int num_sets = ictx->frames.size; + auto device = ctx->device; + auto dfunc = device->funcs; + auto ictx = ctx->iqm_context; + auto mesh = (qfv_iqm_t *) iqm->extra_data; + int num_sets = ictx->frames.size; - //FIXME kinda dumb - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (num_sets, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = ictx->bones_setLayout; + if (!ictx->dsmanager) { + ictx->dsmanager = QFV_Render_DSManager (ctx, "bone_set"); } - __auto_type sets = QFV_AllocateDescriptorSet (device, ictx->bones_pool, - layouts); - for (size_t i = 0; i < sets->size; i++) { - mesh->bones_descriptors[i] = sets->a[i]; + + for (int i = 0; i < num_sets; i++) { + auto set = QFV_DSManager_AllocSet (ictx->dsmanager); + mesh->bones_descriptors[i] = set; } - free (sets); VkDescriptorBufferInfo bufferInfo[num_sets]; - size_t bones_size = iqm->num_joints * 3 * sizeof (vec4f_t); + size_t bones_size = sizeof (vec4f_t[iqm->num_joints * 3]); for (int i = 0; i < num_sets; i++) { bufferInfo[i].buffer = mesh->bones_buffer; bufferInfo[i].offset = i * bones_size; @@ -162,14 +160,13 @@ Vulkan_IQMAddBones (vulkan_ctx_t *ctx, iqm_t *iqm) void Vulkan_IQMRemoveBones (vulkan_ctx_t *ctx, iqm_t *iqm) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - iqmctx_t *ictx = ctx->iqm_context; - __auto_type mesh = (qfv_iqm_t *) iqm->extra_data; - int num_sets = ictx->frames.size; + auto ictx = ctx->iqm_context; + auto mesh = (qfv_iqm_t *) iqm->extra_data; + int num_sets = ictx->frames.size; - dfunc->vkFreeDescriptorSets (device->dev, ictx->bones_pool, num_sets, - mesh->bones_descriptors); + for (int i = 0; i < num_sets; i++) { + QFV_DSManager_FreeSet (ictx->dsmanager, mesh->bones_descriptors[i]); + } } void @@ -318,9 +315,6 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx) ictx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); - ictx->bones_pool = Vulkan_CreateDescriptorPool (ctx, "bone_pool"); - ictx->bones_setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "bone_set"); - qfvPopDebug (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 83c585572..5ed4b5f33 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -62,6 +62,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" @@ -252,6 +253,7 @@ lights_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto dfunc = device->funcs; auto lctx = ctx->lighting_context; auto cmd = taskctx->cmd; + auto layout = taskctx->pipeline->layout; if (!lctx->scene) { return; @@ -279,7 +281,7 @@ lights_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) lframe->shadowWrite.dstSet, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - lctx->layout, 0, 3, sets, 0, 0); + layout, 0, 3, sets, 0, 0); dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); } @@ -296,16 +298,20 @@ static exprsym_t lighting_task_syms[] = { void Vulkan_Lighting_Init (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t)); ctx->lighting_context = lctx; - qfvPushDebug (ctx, "lighting init"); QFV_Render_AddTasks (ctx, lighting_task_syms); +} - // lighting_context initialized in Vulkan_Lighting_CreateRenderPasses +void +Vulkan_Lighting_Setup (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "lighting init"); + + auto device = ctx->device; + auto dfunc = device->funcs; + auto lctx = ctx->lighting_context; Vulkan_Script_SetOutput (ctx, &(qfv_output_t) { .format = VK_FORMAT_X8_D24_UNORM_PACK32 }); @@ -329,7 +335,6 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&lctx->frames, frames); lctx->frames.grow = 0; - lctx->layout = Vulkan_CreatePipelineLayout (ctx, "lighting_layout"); lctx->sampler = Vulkan_CreateSampler (ctx, "shadow_sampler"); __auto_type lbuffers = QFV_AllocBufferSet (frames, alloca); @@ -352,42 +357,21 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lctx->light_memory, "memory:lighting"); - __auto_type attach = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - __auto_type lights = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - __auto_type shadow = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - for (size_t i = 0; i < frames; i++) { - attach->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, - "lighting_attach"); - lights->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, - "lighting_lights"); - shadow->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, - "lighting_shadow"); - } - __auto_type attach_pool = Vulkan_CreateDescriptorPool (ctx, - "lighting_attach_pool"); - __auto_type lights_pool = Vulkan_CreateDescriptorPool (ctx, - "lighting_lights_pool"); - __auto_type shadow_pool = Vulkan_CreateDescriptorPool (ctx, - "lighting_shadow_pool"); - - __auto_type attach_set = QFV_AllocateDescriptorSet (device, attach_pool, - attach); - __auto_type lights_set = QFV_AllocateDescriptorSet (device, lights_pool, - lights); - __auto_type shadow_set = QFV_AllocateDescriptorSet (device, shadow_pool, - shadow); + auto attach_mgr = QFV_Render_DSManager (ctx, "lighting_attach"); + auto lights_mgr = QFV_Render_DSManager (ctx, "lighting_lights"); + auto shadow_mgr = QFV_Render_DSManager (ctx, "lighting_shadow"); VkDeviceSize light_offset = 0; for (size_t i = 0; i < frames; i++) { __auto_type lframe = &lctx->frames.a[i]; - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, - attach_set->a[i], + auto attach = QFV_DSManager_AllocSet (attach_mgr); + auto lights = QFV_DSManager_AllocSet (lights_mgr); + auto shadow = QFV_DSManager_AllocSet (shadow_mgr); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, attach, va (ctx->va_ctx, "lighting:attach_set:%zd", i)); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, - lights_set->a[i], + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, lights, va (ctx->va_ctx, "lighting:lights_set:%zd", i)); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, - shadow_set->a[i], + QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET, shadow, va (ctx->va_ctx, "lighting:shadow_set:%zd", i)); lframe->light_buffer = lbuffers->a[i]; @@ -398,7 +382,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) for (int j = 0; j < LIGHTING_BUFFER_INFOS; j++) { lframe->bufferInfo[j] = base_buffer_info; lframe->bufferWrite[j] = base_buffer_write; - lframe->bufferWrite[j].dstSet = lights_set->a[i]; + lframe->bufferWrite[j].dstSet = lights; lframe->bufferWrite[j].dstBinding = j; lframe->bufferWrite[j].pBufferInfo = &lframe->bufferInfo[j]; } @@ -406,7 +390,7 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->attachInfo[j] = base_image_info; lframe->attachInfo[j].sampler = 0; lframe->attachWrite[j] = base_attachment_write; - lframe->attachWrite[j].dstSet = attach_set->a[i]; + lframe->attachWrite[j].dstSet = attach; lframe->attachWrite[j].dstBinding = j; lframe->attachWrite[j].pImageInfo = &lframe->attachInfo[j]; } @@ -416,14 +400,11 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx) lframe->shadowInfo[j].imageView = ctx->default_black->view; } lframe->shadowWrite = base_image_write; - lframe->shadowWrite.dstSet = shadow_set->a[i]; + lframe->shadowWrite.dstSet = shadow; lframe->shadowWrite.dstBinding = 0; lframe->shadowWrite.descriptorCount = LIGHTING_SHADOW_INFOS; lframe->shadowWrite.pImageInfo = lframe->shadowInfo; } - free (shadow_set); - free (attach_set); - free (lights_set); qfvPopDebug (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_matrices.c b/libs/video/renderer/vulkan/vulkan_matrices.c index 0e9933f0d..1555f0573 100644 --- a/libs/video/renderer/vulkan/vulkan_matrices.c +++ b/libs/video/renderer/vulkan/vulkan_matrices.c @@ -48,9 +48,11 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/projection.h" #include "QF/Vulkan/render.h" +#include "QF/Vulkan/resource.h" #include "QF/Vulkan/staging.h" #include "r_internal.h" @@ -231,57 +233,53 @@ void Vulkan_Matrix_Init (vulkan_ctx_t *ctx) { QFV_Render_AddTasks (ctx, matrix_task_syms); + + matrixctx_t *mctx = calloc (1, sizeof (matrixctx_t)); + ctx->matrix_context = mctx; +} + +void +Vulkan_Matrix_Setup (vulkan_ctx_t *ctx) +{ qfvPushDebug (ctx, "matrix init"); qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; - matrixctx_t *mctx = calloc (1, sizeof (matrixctx_t)); - ctx->matrix_context = mctx; - + auto mctx = ctx->matrix_context; auto rctx = ctx->render_context; size_t frames = rctx->frames.size; DARRAY_INIT (&mctx->frames, frames); DARRAY_RESIZE (&mctx->frames, frames); mctx->frames.grow = 0; - //__auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca); - //QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers); - - mctx->pool = Vulkan_CreateDescriptorPool (ctx, "matrix_pool"); - mctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "matrix_set"); - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = mctx->setLayout; - } - + mctx->resource = malloc (sizeof (qfv_resource_t) + + sizeof (qfv_resobj_t[frames])); // buffers + auto buffers = (qfv_resobj_t *) &mctx->resource[1]; + *mctx->resource = (qfv_resource_t) { + .name = "matrix", + .va_ctx = ctx->va_ctx, + .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + .num_objects = frames, + .objects = buffers, + }; for (size_t i = 0; i < frames; i++) { - __auto_type mframe = &mctx->frames.a[i]; - //mframe->cmd = cmdBuffers->a[i]; - mframe->buffer = QFV_CreateBuffer (device, sizeof (qfv_matrix_buffer_t), - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT - | VK_BUFFER_USAGE_TRANSFER_DST_BIT); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER, - mframe->buffer, va (ctx->va_ctx, - "buffer:matrices:%zd", i)); + buffers[i] = (qfv_resobj_t) { + .name = va (ctx->va_ctx, "%zd", i), + .type = qfv_res_buffer, + .buffer = { + .size = sizeof (qfv_matrix_buffer_t), + .usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + }, + }; } + QFV_CreateResource (device, mctx->resource); - VkMemoryRequirements req; - //offset = (offset + req.alignment - 1) & ~(req.alignment - 1); - dfunc->vkGetBufferMemoryRequirements (device->dev, - mctx->frames.a[0].buffer, &req); - mctx->memory = QFV_AllocBufferMemory (device, mctx->frames.a[0].buffer, - VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - frames * req.size, 0); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY, - mctx->memory, "memory:matrices"); - - __auto_type sets = QFV_AllocateDescriptorSet (device, mctx->pool, layouts); + auto dsmanager = QFV_Render_DSManager (ctx, "matrix_set"); for (size_t i = 0; i < frames; i++) { - __auto_type mframe = &mctx->frames.a[i]; - QFV_BindBufferMemory (device, mframe->buffer, mctx->memory, - i * req.size); - - mframe->descriptors = sets->a[i]; + auto mframe = &mctx->frames.a[i]; + mframe->buffer = buffers[i].buffer.buffer; + mframe->descriptors = QFV_DSManager_AllocSet (dsmanager); VkDescriptorBufferInfo bufferInfo = { mframe->buffer, 0, VK_WHOLE_SIZE }; @@ -293,7 +291,6 @@ Vulkan_Matrix_Init (vulkan_ctx_t *ctx) }; dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0); } - free (sets); mctx->sky_fix = (vec4f_t) { 0, 0, 1, 1 } * sqrtf (0.5); mctx->sky_rotation[0] = (vec4f_t) { 0, 0, 0, 1}; @@ -322,24 +319,18 @@ void Vulkan_Matrix_Shutdown (vulkan_ctx_t *ctx) { qfvPushDebug (ctx, "matrix shutdown"); - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - __auto_type mctx = ctx->matrix_context; + auto device = ctx->device; + auto mctx = ctx->matrix_context; QFV_DestroyStagingBuffer (mctx->stage); + QFV_DestroyResource (device, mctx->resource); - for (size_t i = 0; i < mctx->frames.size; i++) { - __auto_type mframe = &mctx->frames.a[i]; - dfunc->vkDestroyBuffer (device->dev, mframe->buffer, 0); - } - dfunc->vkFreeMemory (device->dev, mctx->memory, 0); qfvPopDebug (ctx); } VkDescriptorSet Vulkan_Matrix_Descriptors (vulkan_ctx_t *ctx, int frame) { - __auto_type mctx = ctx->matrix_context; + auto mctx = ctx->matrix_context; return mctx->frames.a[frame].descriptors; } diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 9c51b49f5..e8f3ec55b 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -51,6 +51,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/render.h" @@ -238,46 +239,41 @@ static exprsym_t output_task_syms[] = { void Vulkan_Output_Init (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - outputctx_t *octx = calloc (1, sizeof (outputctx_t)); ctx->output_context = octx; - qfvPushDebug (ctx, "output init"); QFV_Render_AddTasks (ctx, output_task_syms); + __auto_type pld = ctx->script_context->pipelineDef;//FIXME + ctx->script_context->pipelineDef = Vulkan_GetConfig (ctx, "qf_output"); + + qfvPushDebug (ctx, "output init"); + octx->sampler = Vulkan_CreateSampler (ctx, "linear"); + ctx->script_context->pipelineDef = pld; + qfvPopDebug (ctx); +} + +void +Vulkan_Output_Setup (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "output init"); + + auto octx = ctx->output_context; + auto rctx = ctx->render_context; size_t frames = rctx->frames.size; DARRAY_INIT (&octx->frames, frames); DARRAY_RESIZE (&octx->frames, frames); octx->frames.grow = 0; - __auto_type pld = ctx->script_context->pipelineDef;//FIXME - ctx->script_context->pipelineDef = Vulkan_GetConfig (ctx, "qf_output"); - - octx->sampler = Vulkan_CreateSampler (ctx, "linear"); - - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - layouts->a[0] = Vulkan_CreateDescriptorSetLayout (ctx, "output_set"); - for (size_t i = 0; i < frames; i++) { - layouts->a[i] = layouts->a[0]; - } - __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "output_pool"); - __auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); - __auto_type cmdSet = QFV_AllocCommandBufferSet (1, alloca); + auto dsmanager = QFV_Render_DSManager (ctx, "output_set"); for (size_t i = 0; i < frames; i++) { - __auto_type oframe = &octx->frames.a[i]; - + auto oframe = &octx->frames.a[i]; oframe->input = 0; - oframe->set = sets->a[i]; - - QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdSet); + oframe->set = QFV_DSManager_AllocSet (dsmanager); } - ctx->script_context->pipelineDef = pld; - - free (sets); qfvPopDebug (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_particles.c b/libs/video/renderer/vulkan/vulkan_particles.c index 963f8bda3..90e002c61 100644 --- a/libs/video/renderer/vulkan/vulkan_particles.c +++ b/libs/video/renderer/vulkan/vulkan_particles.c @@ -46,6 +46,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" @@ -423,36 +424,35 @@ static exprsym_t particles_task_syms[] = { void Vulkan_Particles_Init (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - qfvPushDebug (ctx, "particles init"); QFV_Render_AddTasks (ctx, particles_task_syms); particlectx_t *pctx = calloc (1, sizeof (particlectx_t)); ctx->particle_context = pctx; pctx->psystem = &r_psystem; +} + +void +Vulkan_Particles_Setup (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "particles init"); + + auto device = ctx->device; + auto dfunc = device->funcs; + auto pctx = ctx->particle_context; size_t frames = ctx->render_context->frames.size; DARRAY_INIT (&pctx->frames, frames); DARRAY_RESIZE (&pctx->frames, frames); pctx->frames.grow = 0; - pctx->pool = Vulkan_CreateDescriptorPool (ctx, "particle_pool"); - pctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "particle_set"); - - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (3 * frames, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = pctx->setLayout; - } - __auto_type sets = QFV_AllocateDescriptorSet (device, pctx->pool, layouts); + auto dsmanager = QFV_Render_DSManager (ctx, "particle_set"); for (size_t i = 0; i < frames; i++) { __auto_type pframe = &pctx->frames.a[i]; - pframe->curDescriptors = sets->a[i * 3 + 0]; - pframe->inDescriptors = sets->a[i * 3 + 1]; - pframe->newDescriptors = sets->a[i * 3 + 2]; + pframe->curDescriptors = QFV_DSManager_AllocSet (dsmanager); + pframe->inDescriptors = QFV_DSManager_AllocSet (dsmanager); + pframe->newDescriptors = QFV_DSManager_AllocSet (dsmanager); VkEventCreateInfo event = { VK_STRUCTURE_TYPE_EVENT_CREATE_INFO }; dfunc->vkCreateEvent (device->dev, &event, 0, &pframe->physicsEvent); @@ -464,7 +464,6 @@ Vulkan_Particles_Init (vulkan_ctx_t *ctx) pframe->updateEvent, va (ctx->va_ctx, "event:particle:update:%zd", i)); } - free (sets); create_buffers (ctx); qfvPopDebug (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_scene.c b/libs/video/renderer/vulkan/vulkan_scene.c index 80d2976e4..2f2fa901e 100644 --- a/libs/video/renderer/vulkan/vulkan_scene.c +++ b/libs/video/renderer/vulkan/vulkan_scene.c @@ -43,6 +43,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/render.h" #include "QF/Vulkan/resource.h" @@ -133,16 +134,22 @@ static VkWriteDescriptorSet base_buffer_write = { void Vulkan_Scene_Init (vulkan_ctx_t *ctx) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - qfvPushDebug (ctx, "scene init"); - scenectx_t *sctx = calloc (1, sizeof (scenectx_t) + sizeof (qfv_resource_t) + sizeof (qfv_resobj_t)); ctx->scene_context = sctx; sctx->max_entities = qfv_max_entities; +} + +void +Vulkan_Scene_Setup (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "scene init"); + + auto device = ctx->device; + auto dfunc = device->funcs; + + auto sctx = ctx->scene_context; auto rctx = ctx->render_context; size_t frames = rctx->frames.size; @@ -169,13 +176,7 @@ Vulkan_Scene_Init (vulkan_ctx_t *ctx) QFV_CreateResource (device, sctx->entities); - sctx->pool = Vulkan_CreateDescriptorPool (ctx, "entity_pool"); - sctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "entity_set"); - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = sctx->setLayout; - } - __auto_type sets = QFV_AllocateDescriptorSet (device, sctx->pool, layouts); + auto dsmanager = QFV_Render_DSManager (ctx, "entity_set"); entdata_t *entdata; dfunc->vkMapMemory (device->dev, sctx->entities->memory, 0, VK_WHOLE_SIZE, @@ -186,7 +187,7 @@ Vulkan_Scene_Init (vulkan_ctx_t *ctx) for (size_t i = 0; i < frames; i++) { __auto_type sframe = &sctx->frames.a[i]; - sframe->descriptors = sets->a[i]; + sframe->descriptors = QFV_DSManager_AllocSet (dsmanager);; VkDescriptorBufferInfo bufferInfo = { buffer, i * entdata_size, entdata_size }; @@ -202,7 +203,6 @@ Vulkan_Scene_Init (vulkan_ctx_t *ctx) }; sframe->pooled_entities = set_new (); } - free (sets); qfvPopDebug (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 984db3710..3289f10d3 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -61,6 +61,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/render.h" @@ -116,14 +117,10 @@ Vulkan_Sprite_DescriptorSet (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) qfv_devfuncs_t *dfunc = device->funcs; spritectx_t *sctx = ctx->sprite_context; - //FIXME kinda dumb - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = sctx->setLayout; + if (!sctx->dsmanager) { + sctx->dsmanager = QFV_Render_DSManager (ctx, "sprite_set"); } - __auto_type sets = QFV_AllocateDescriptorSet (device, sctx->pool, layouts); - sprite->descriptors = sets->a[0]; - free (sets); + sprite->descriptors = QFV_DSManager_AllocSet (sctx->dsmanager); VkDescriptorBufferInfo bufferInfo[1]; bufferInfo[0] = base_buffer_info; @@ -145,14 +142,10 @@ Vulkan_Sprite_DescriptorSet (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) } void -Vulkan_Sprint_FreeDescriptors (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) +Vulkan_Sprite_FreeDescriptors (vulkan_ctx_t *ctx, qfv_sprite_t *sprite) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; spritectx_t *sctx = ctx->sprite_context; - - dfunc->vkFreeDescriptorSets (device->dev, sctx->pool, 1, - &sprite->descriptors); + QFV_DSManager_FreeSet (sctx->dsmanager, sprite->descriptors); } static void @@ -229,9 +222,6 @@ Vulkan_Sprite_Init (vulkan_ctx_t *ctx) sctx->sampler = Vulkan_CreateSampler (ctx, "sprite_sampler"); - sctx->pool = Vulkan_CreateDescriptorPool (ctx, "sprite_pool"); - sctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "sprite_set"); - qfvPopDebug (ctx); } diff --git a/libs/video/renderer/vulkan/vulkan_texture.c b/libs/video/renderer/vulkan/vulkan_texture.c index 7a8c6a3ea..94b956d04 100644 --- a/libs/video/renderer/vulkan/vulkan_texture.c +++ b/libs/video/renderer/vulkan/vulkan_texture.c @@ -44,8 +44,10 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/staging.h" #include "vid_vulkan.h" @@ -508,13 +510,18 @@ static tex_t default_magenta_tex = { void Vulkan_Texture_Init (vulkan_ctx_t *ctx) { - qfvPushDebug (ctx, "texture init"); - texturectx_t *tctx = calloc (1, sizeof (texturectx_t)); ctx->texture_context = tctx; +} - tctx->pool = Vulkan_CreateDescriptorPool (ctx, "texture_pool"); - tctx->setLayout = Vulkan_CreateDescriptorSetLayout (ctx, "texture_set"); +void +Vulkan_Texture_Setup (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "texture init"); + + auto tctx = ctx->texture_context; + + tctx->dsmanager = QFV_Render_DSManager (ctx, "texture_set"); ctx->default_black = Vulkan_LoadTex (ctx, &default_black_tex, 1, "default_black"); @@ -560,18 +567,11 @@ Vulkan_CreateCombinedImageSampler (vulkan_ctx_t *ctx, VkImageView view, { qfvPushDebug (ctx, "Vulkan_CreateCombinedImageSampler"); - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - texturectx_t *tctx = ctx->texture_context; + auto device = ctx->device; + auto dfunc = device->funcs; + auto tctx = ctx->texture_context; - //FIXME kinda dumb - __auto_type layouts = QFV_AllocDescriptorSetLayoutSet (1, alloca); - for (size_t i = 0; i < layouts->size; i++) { - layouts->a[i] = tctx->setLayout; - } - __auto_type sets = QFV_AllocateDescriptorSet (device, tctx->pool, layouts); - VkDescriptorSet descriptor = sets->a[0]; - free (sets); + auto descriptor = QFV_DSManager_AllocSet (tctx->dsmanager); VkDescriptorImageInfo imageInfo[1]; imageInfo[0] = base_image_info; @@ -599,9 +599,7 @@ Vulkan_CreateTextureDescriptor (vulkan_ctx_t *ctx, qfv_tex_t *tex, void Vulkan_FreeTexture (vulkan_ctx_t *ctx, VkDescriptorSet texture) { - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - texturectx_t *tctx = ctx->texture_context; + auto tctx = ctx->texture_context; - dfunc->vkFreeDescriptorSets (device->dev, tctx->pool, 1, &texture); + QFV_DSManager_FreeSet (tctx->dsmanager, texture); } diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index 8ca44abe7..637df03bc 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -50,6 +50,7 @@ #include "QF/Vulkan/debug.h" #include "QF/Vulkan/descriptor.h" #include "QF/Vulkan/device.h" +#include "QF/Vulkan/dsmanager.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" #include "QF/Vulkan/render.h" @@ -128,16 +129,18 @@ static exprsym_t translucent_task_syms[] = { void Vulkan_Translucent_Init (vulkan_ctx_t *ctx) { - if (ctx->translucent_context) {//FIXME - return; - } - qfv_device_t *device = ctx->device; - - qfvPushDebug (ctx, "translucent init"); QFV_Render_AddTasks (ctx, translucent_task_syms); translucentctx_t *tctx = calloc (1, sizeof (translucentctx_t)); ctx->translucent_context = tctx; +} + +void +Vulkan_Translucent_Setup (vulkan_ctx_t *ctx) +{ + qfvPushDebug (ctx, "translucent init"); + + auto tctx = ctx->translucent_context; auto rctx = ctx->render_context; size_t frames = rctx->frames.size; @@ -147,19 +150,12 @@ Vulkan_Translucent_Init (vulkan_ctx_t *ctx) tctx->maxFragments = vulkan_oit_fragments * 1024 * 1024; - __auto_type setLayout = QFV_AllocDescriptorSetLayoutSet (frames, alloca); - for (size_t i = 0; i < frames; i++) { - setLayout->a[i] = Vulkan_CreateDescriptorSetLayout (ctx, "oit_set"); - } - __auto_type pool = Vulkan_CreateDescriptorPool (ctx, "oit_pool"); - - __auto_type sets = QFV_AllocateDescriptorSet (device, pool, setLayout); + auto dsmanager = QFV_Render_DSManager (ctx, "oit_set"); for (size_t i = 0; i < frames; i++) { tctx->frames.a[i] = (translucentframe_t) { - .descriptors = sets->a[i], + .descriptors = QFV_DSManager_AllocSet (dsmanager), }; } - free (sets); Vulkan_Translucent_CreateBuffers (ctx, ctx->swapchain->extent);//FIXME qfvPopDebug (ctx); } From 65a63e74236d34a218182b43cd82d4458dbdc76a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Jun 2023 00:20:19 +0900 Subject: [PATCH 3650/3664] [vulkan] Fix a silly typo Sprites seem to be rather slow to draw, so "sprint" makes even less sense. --- include/QF/Vulkan/qf_sprite.h | 2 +- libs/models/sprite/vulkan_model_sprite.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index 1b2ab04bf..8139c479c 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -68,7 +68,7 @@ struct vulkan_ctx_s; struct entity_s; struct mod_sprite_ctx_s; -void Vulkan_Sprint_FreeDescriptors (struct vulkan_ctx_s *ctx, +void Vulkan_Sprite_FreeDescriptors (struct vulkan_ctx_s *ctx, qfv_sprite_t *sprite); void Vulkan_Sprite_DescriptorSet (struct vulkan_ctx_s *ctx, qfv_sprite_t *sprite); diff --git a/libs/models/sprite/vulkan_model_sprite.c b/libs/models/sprite/vulkan_model_sprite.c index 09fecf76d..865d349ea 100644 --- a/libs/models/sprite/vulkan_model_sprite.c +++ b/libs/models/sprite/vulkan_model_sprite.c @@ -67,7 +67,7 @@ vulkan_sprite_clear (model_t *m, void *data) msprite_t *msprite = m->cache.data; __auto_type sprite = (qfv_sprite_t *) ((byte *) msprite + msprite->data); - Vulkan_Sprint_FreeDescriptors (ctx, sprite); + Vulkan_Sprite_FreeDescriptors (ctx, sprite); dfunc->vkDestroyBuffer (device->dev, sprite->verts, 0); dfunc->vkDestroyImageView (device->dev, sprite->view, 0); From eb176c37e2fca2abe6b233517a1264dc4a6142cd Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Jun 2023 00:22:03 +0900 Subject: [PATCH 3651/3664] [vulkan] Get brush models rendering again The new system seems to work quite nicely with brush models, which was the intent, but it's nice to see. Hopefully, it works well when it comes to shadows. There's still water warp and screen shots to fix, and fisheye to get working, as well. --- include/QF/Vulkan/qf_bsp.h | 9 +- libs/video/renderer/vulkan/rp_main_def.plist | 11 +- libs/video/renderer/vulkan/vulkan_bsp.c | 463 ++++++------------- 3 files changed, 160 insertions(+), 323 deletions(-) diff --git a/include/QF/Vulkan/qf_bsp.h b/include/QF/Vulkan/qf_bsp.h index b36c9697f..8f7df82db 100644 --- a/include/QF/Vulkan/qf_bsp.h +++ b/include/QF/Vulkan/qf_bsp.h @@ -316,13 +316,13 @@ typedef struct bsp_pass_s { /// \ingroup vulkan_bsp ///@{ typedef enum { - QFV_bspDepth, - QFV_bspGBuffer, + QFV_bspSolid, QFV_bspSky, - QFV_bspTurb, + QFV_bspTrans, // texture translucency + QFV_bspTurb, // also translucent via r_wateralpha QFV_bspNumPasses -} QFV_BspSubpass; +} QFV_BspQueue; typedef struct bspframe_s { uint32_t *index_data; // pointer into mega-buffer for this frame (c) @@ -380,7 +380,6 @@ typedef struct bspctx_s { } bspctx_t; struct vulkan_ctx_s; -void Vulkan_Bsp_Flush (struct vulkan_ctx_s *ctx); void Vulkan_LoadSkys (const char *sky, struct vulkan_ctx_s *ctx); void Vulkan_RegisterTextures (model_t **models, int num_models, struct vulkan_ctx_s *ctx); diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 6a4f39682..3a382881d 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1449,6 +1449,15 @@ steps = { dependencies = (wait_on_fence); //currently empty }; + world = { + dependencies = (wait_on_fence); + process = { + tasks = ( + { func = bsp_visit_world; + params = (main); }, + ); + }; + }; translucent = { dependencies = (wait_on_fence); process = { @@ -1468,7 +1477,7 @@ steps = { }; }; main = { - dependencies = (setup_main, particles, shadow, translucent); + dependencies = (setup_main, particles, shadow, world, translucent); render = { renderpasses = { deferred = $renderpasses.deferred; diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index a81147739..8e640de16 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -33,12 +33,7 @@ # include "config.h" #endif -#ifdef HAVE_STRING_H -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif +#include #include #include "qfalloca.h" @@ -578,7 +573,7 @@ Vulkan_BuildDisplayLists (model_t **models, int num_models, vulkan_ctx_t *ctx) } } -#if 0 + static int R_DrawBrushModel (entity_t ent, bsp_pass_t *pass, vulkan_ctx_t *ctx) { @@ -607,7 +602,7 @@ R_DrawBrushModel (entity_t ent, bsp_pass_t *pass, vulkan_ctx_t *ctx) renderer->render_id); return 1; } -#endif + static inline void visit_leaf (mleaf_t *leaf) { @@ -729,7 +724,7 @@ R_VisitWorldNodes (bsp_pass_t *pass, vulkan_ctx_t *ctx) break; } } -#if 0 + static void bind_texture (vulktex_t *tex, uint32_t setnum, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, VkCommandBuffer cmd) @@ -763,152 +758,6 @@ push_fragconst (bsp_push_constants_t *constants, VkPipelineLayout layout, QFV_PushConstants (device, cmd, layout, 4, push_constants); } -static void -bsp_begin_subpass (QFV_BspSubpass subpass, VkPipeline pipeline, - VkPipelineLayout layout, qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - VkCommandBuffer cmd = bframe->cmdSet.a[subpass]; - - dfunc->vkResetCommandBuffer (cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - rFrame->renderpass->renderpass, subpass_map[subpass], - rFrame->framebuffer, - 0, 0, 0, - }; - VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit, - }; - dfunc->vkBeginCommandBuffer (cmd, &beginInfo); - - QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "bsp:%s", - bsp_pass_names[subpass]), - {0, 0.5, 0.6, 1}); - - dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeline); - dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport); - dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor); - - VkBuffer buffers[] = { bctx->vertex_buffer, bctx->entid_buffer }; - VkDeviceSize offsets[] = { 0, bframe->entid_offset }; - dfunc->vkCmdBindVertexBuffers (cmd, 0, 2, buffers, offsets); - dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, - VK_INDEX_TYPE_UINT32); - - VkDescriptorSet sets[] = { - Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), - Vulkan_Scene_Descriptors (ctx), - Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), - }; - dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, - layout, 0, 3, sets, 0, 0); - - //XXX glsl_Fog_GetColor (fog); - //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; -} - -static void -bsp_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - QFV_duCmdEndLabel (device, cmd); - dfunc->vkEndCommandBuffer (cmd); -} - -static void -bsp_begin (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - bspctx_t *bctx = ctx->bsp_context; - //XXX quat_t fog; - - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passDepth], - bframe->cmdSet.a[QFV_bspDepth]); - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passGBuffer], - bframe->cmdSet.a[QFV_bspGBuffer]); - - qfvPushDebug (ctx, "bsp_begin_subpass"); - bsp_begin_subpass (QFV_bspDepth, bctx->depth, bctx->layout, rFrame); - bsp_begin_subpass (QFV_bspGBuffer, bctx->gbuf, bctx->layout, rFrame); - qfvPopDebug (ctx); -} - -static void -bsp_end (vulkan_ctx_t *ctx) -{ - bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - - bsp_end_subpass (bframe->cmdSet.a[QFV_bspDepth], ctx); - bsp_end_subpass (bframe->cmdSet.a[QFV_bspGBuffer], ctx); -} - -static void -turb_begin (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - bspctx_t *bctx = ctx->bsp_context; - - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFrag], - bframe->cmdSet.a[QFV_bspTurb]); - - qfvPushDebug (ctx, "bsp_begin_subpass"); - bsp_begin_subpass (QFV_bspTurb, bctx->turb, bctx->layout, rFrame); - qfvPopDebug (ctx); -} - -static void -turb_end (vulkan_ctx_t *ctx) -{ - bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - - bsp_end_subpass (bframe->cmdSet.a[QFV_bspTurb], ctx); -} - -static void -sky_begin (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - bspctx_t *bctx = ctx->bsp_context; - - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - - DARRAY_APPEND (&rFrame->subpassCmdSets[QFV_passTranslucentFrag], - bframe->cmdSet.a[QFV_bspSky]); - - qfvPushDebug (ctx, "bsp_begin_subpass"); - if (bctx->skybox_tex) { - bsp_begin_subpass (QFV_bspSky, bctx->skybox, bctx->layout, rFrame); - } else { - bsp_begin_subpass (QFV_bspSky, bctx->skysheet, bctx->layout, rFrame); - } - qfvPopDebug (ctx); -} - -static void -sky_end (vulkan_ctx_t *ctx) -{ - bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - - bsp_end_subpass (bframe->cmdSet.a[QFV_bspSky], ctx); -} -#endif static void clear_queues (bspctx_t *bctx, bsp_pass_t *pass) { @@ -924,19 +773,19 @@ clear_queues (bspctx_t *bctx, bsp_pass_t *pass) } pass->index_count = 0; } -#if 0 + static void queue_faces (bsp_pass_t *pass, const bspctx_t *bctx, bspframe_t *bframe) { pass->indices = bframe->index_data + bframe->index_count; for (size_t i = 0; i < bctx->registered_textures.size; i++) { - __auto_type queue = &pass->face_queue[i]; + auto queue = &pass->face_queue[i]; if (!queue->size) { continue; } for (size_t j = 0; j < queue->size; j++) { - __auto_type is = queue->a[j]; - __auto_type f = bctx->faces[is.face]; + auto is = queue->a[j]; + auto f = bctx->faces[is.face]; f.flags |= ((is.inst_id & INST_ALPHA) >> (BITOP_LOG2(INST_ALPHA) @@ -990,13 +839,13 @@ queue_faces (bsp_pass_t *pass, const bspctx_t *bctx, bspframe_t *bframe) } static void -draw_queue (bsp_pass_t *pass, int queue, VkPipelineLayout layout, +draw_queue (bsp_pass_t *pass, QFV_BspQueue queue, VkPipelineLayout layout, qfv_device_t *device, VkCommandBuffer cmd) { qfv_devfuncs_t *dfunc = device->funcs; for (size_t i = 0; i < pass->draw_queues[queue].size; i++) { - __auto_type d = pass->draw_queues[queue].a[i]; + auto d = pass->draw_queues[queue].a[i]; if (pass->textures) { vulktex_t *tex = pass->textures->a[d.tex_id]; bind_texture (tex, TEX_SET, layout, dfunc, cmd); @@ -1016,77 +865,8 @@ ent_model_cmp (const void *_a, const void *_b) return ra->model->render_id - rb->model->render_id; } -void -Vulkan_DrawWorld (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - //qfv_devfuncs_t *dfunc = device->funcs; - bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - - bctx->main_pass.bsp_context = bctx; - bctx->main_pass.position = r_refdef.frame.position; - bctx->main_pass.vis_frame = r_visframecount; - bctx->main_pass.face_frames = r_face_visframes; - bctx->main_pass.leaf_frames = r_leaf_visframes; - bctx->main_pass.node_frames = r_node_visframes; - bctx->main_pass.entid_data = bframe->entid_data; - bctx->main_pass.entid_count = 0; - - bctx->anim_index = r_data->realtime * 5; - - clear_queues (bctx, &bctx->main_pass); // do this first for water and skys - bframe->index_count = 0; - - entity_t worldent = nullentity; - - int world_id = Vulkan_Scene_AddEntity (ctx, worldent); - - bctx->main_pass.ent_frame = 0; // world is always frame 0 - bctx->main_pass.inst_id = world_id; - bctx->main_pass.brush = &r_refdef.worldmodel->brush; - if (bctx->main_pass.instances) { - DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, world_id); - } - R_VisitWorldNodes (&bctx->main_pass, ctx); - if (!bctx->vertex_buffer) { - return; - } - if (r_drawentities) { - heapsort (r_ent_queue->ent_queues[mod_brush].a, - r_ent_queue->ent_queues[mod_brush].size, - sizeof (entity_t), ent_model_cmp); - for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { - entity_t ent = r_ent_queue->ent_queues[mod_brush].a[i]; - if (!R_DrawBrushModel (ent, &bctx->main_pass, ctx)) { - Sys_Printf ("Too many entities!\n"); - break; - } - } - } - bframe->entid_count = bctx->main_pass.entid_count; - - queue_faces (&bctx->main_pass, bctx, bframe); - - bsp_begin (rFrame); - - bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; - push_fragconst (&frag_constants, bctx->layout, device, - bframe->cmdSet.a[QFV_bspGBuffer]); - VkPipelineLayout layout = bctx->layout; - - __auto_type pass = &bctx->main_pass; - pass->textures = 0; - draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspDepth]); - draw_queue (pass, 1, layout, device, bframe->cmdSet.a[QFV_bspDepth]); - pass->textures = &bctx->registered_textures; - draw_queue (pass, 0, layout, device, bframe->cmdSet.a[QFV_bspGBuffer]); - bsp_end (ctx); -} -#endif -void -Vulkan_Bsp_Flush (vulkan_ctx_t *ctx) +static void +bsp_flush (vulkan_ctx_t *ctx) { qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; @@ -1117,71 +897,7 @@ Vulkan_Bsp_Flush (vulkan_ctx_t *ctx) }; dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges); } -#if 0 -void -Vulkan_DrawWaterSurfaces (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - //qfv_devfuncs_t *dfunc = device->funcs; - bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - if (!bctx->main_pass.draw_queues[3].size) - return; - - turb_begin (rFrame); - - VkPipelineLayout layout = bctx->layout; - bsp_push_constants_t frag_constants = { - .time = vr_data.realtime, - .alpha = 1, - .turb_scale = 0, - }; - push_fragconst (&frag_constants, layout, device, - bframe->cmdSet.a[QFV_bspTurb]); - - __auto_type pass = &bctx->main_pass; - pass->textures = &bctx->registered_textures; - draw_queue (pass, 2, layout, device, bframe->cmdSet.a[QFV_bspTurb]); - - frag_constants.alpha = r_wateralpha; - frag_constants.turb_scale = 1; - push_fragconst (&frag_constants, bctx->layout, device, - bframe->cmdSet.a[QFV_bspTurb]); - draw_queue (pass, 3, layout, device, bframe->cmdSet.a[QFV_bspTurb]); - - turb_end (ctx); -} - -void -Vulkan_DrawSky (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - bspctx_t *bctx = ctx->bsp_context; - bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; - - if (!bctx->main_pass.draw_queues[1].size) - return; - - sky_begin (rFrame); - vulktex_t skybox = { .descriptor = bctx->skybox_descriptor }; - bind_texture (&skybox, SKYBOX_SET, bctx->layout, dfunc, - bframe->cmdSet.a[QFV_bspSky]); - bsp_push_constants_t frag_constants = { .time = vr_data.realtime }; - push_fragconst (&frag_constants, bctx->layout, device, - bframe->cmdSet.a[QFV_bspSky]); - - VkPipelineLayout layout = bctx->layout; - __auto_type pass = &bctx->main_pass; - pass->textures = &bctx->registered_textures; - draw_queue (pass, 1, layout, device, bframe->cmdSet.a[QFV_bspSky]); - - sky_end (ctx); -} -#endif static void create_default_skys (vulkan_ctx_t *ctx) { @@ -1359,27 +1075,126 @@ bsp_draw_queue (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { auto taskctx = (qfv_taskctx_t *) ectx; auto ctx = taskctx->ctx; + auto device = ctx->device; + auto dfunc = device->funcs; auto bctx = ctx->bsp_context; - int pass = *(int *) params[2]->value; - if (!pass && r_refdef.worldmodel) { - bctx->main_pass.bsp_context = bctx; - bctx->main_pass.position = r_refdef.frame.position; - bctx->main_pass.vis_frame = r_visframecount; - bctx->main_pass.face_frames = r_face_visframes; - bctx->main_pass.leaf_frames = r_leaf_visframes; - bctx->main_pass.node_frames = r_node_visframes; - //bctx->main_pass.entid_data = bframe->entid_data; - //bctx->main_pass.entid_count = 0; + auto layout = taskctx->pipeline->layout; + auto cmd = taskctx->cmd; - EntQueue_Clear (r_ent_queue); - clear_queues (bctx, &bctx->main_pass); // do this first for water and skys - entity_t worldent = nullentity; - int world_id = Vulkan_Scene_AddEntity (ctx, worldent); - bctx->main_pass.ent_frame = 0; // world is always frame 0 - bctx->main_pass.inst_id = world_id; - bctx->main_pass.brush = &r_refdef.worldmodel->brush; - R_VisitWorldNodes (&bctx->main_pass, ctx); + if (!bctx->vertex_buffer) { + return; } + + // params are in reverse order + auto stage = *(int *) params[2]->value; + auto queue = *(QFV_BspQueue *) params[1]->value; + auto pass = *(int *) params[0]->value; + + if (stage) { + Sys_Error ("bps stages not implemented"); + } + auto mpass = &bctx->main_pass; + if (!mpass->draw_queues[queue].size) { + return; + } + + auto bframe = &bctx->frames.a[ctx->curFrame]; + VkBuffer buffers[] = { bctx->vertex_buffer, bctx->entid_buffer }; + VkDeviceSize offsets[] = { 0, bframe->entid_offset }; + dfunc->vkCmdBindVertexBuffers (cmd, 0, 2, buffers, offsets); + dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset, + VK_INDEX_TYPE_UINT32); + + VkDescriptorSet sets[] = { + Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), + Vulkan_Scene_Descriptors (ctx), + Vulkan_Translucent_Descriptors (ctx, ctx->curFrame), + }; + dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + layout, 0, 3, sets, 0, 0); + + //XXX glsl_Fog_GetColor (fog); + //XXX fog[3] = glsl_Fog_GetDensity () / 64.0; + bsp_push_constants_t frag_constants = { + .time = vr_data.realtime, + .alpha = queue == QFV_bspTurb ? r_wateralpha : 1, + .turb_scale = queue == QFV_bspTurb ? 1 : 0, + }; + push_fragconst (&frag_constants, layout, device, cmd); + if (queue == QFV_bspSky) { + vulktex_t skybox = { .descriptor = bctx->skybox_descriptor }; + bind_texture (&skybox, SKYBOX_SET, layout, dfunc, cmd); + } + + mpass->textures = pass ? &bctx->registered_textures : 0; + draw_queue (mpass, queue, layout, device, cmd); +} + +static void +bsp_visit_world (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto stage = *(int *) params[0]->value; + + if (stage) { + Sys_Error ("bps stages not implemented"); + } + + EntQueue_Clear (r_ent_queue); + Vulkan_Scene_Flush (ctx); + + auto bctx = ctx->bsp_context; + clear_queues (bctx, &bctx->main_pass); // do this first for water and skys + + if (!r_refdef.worldmodel) { + return; + } + + auto bframe = &bctx->frames.a[ctx->curFrame]; + + bctx->main_pass.bsp_context = bctx; + bctx->main_pass.position = r_refdef.frame.position; + bctx->main_pass.vis_frame = r_visframecount; + bctx->main_pass.face_frames = r_face_visframes; + bctx->main_pass.leaf_frames = r_leaf_visframes; + bctx->main_pass.node_frames = r_node_visframes; + bctx->main_pass.entid_data = bframe->entid_data; + bctx->main_pass.entid_count = 0; + + bctx->anim_index = r_data->realtime * 5; + + bframe->index_count = 0; + + entity_t worldent = nullentity; + + int world_id = Vulkan_Scene_AddEntity (ctx, worldent); + + bctx->main_pass.ent_frame = 0; // world is always frame 0 + bctx->main_pass.inst_id = world_id; + bctx->main_pass.brush = &r_refdef.worldmodel->brush; + if (bctx->main_pass.instances) { + DARRAY_APPEND (&bctx->main_pass.instances[world_id].entities, world_id); + } + R_VisitWorldNodes (&bctx->main_pass, ctx); + + if (r_drawentities) { + heapsort (r_ent_queue->ent_queues[mod_brush].a, + r_ent_queue->ent_queues[mod_brush].size, + sizeof (entity_t), ent_model_cmp); + for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) { + entity_t ent = r_ent_queue->ent_queues[mod_brush].a[i]; + if (!R_DrawBrushModel (ent, &bctx->main_pass, ctx)) { + Sys_Printf ("Too many entities!\n"); + break; + } + } + } + bframe->entid_count = bctx->main_pass.entid_count; + + queue_faces (&bctx->main_pass, bctx, bframe); + + bsp_flush (ctx); } static exprenum_t bsp_stage_enum; @@ -1407,7 +1222,12 @@ static exprtype_t bsp_queue_type = { .get_string = cexpr_enum_get_string, .data = &bsp_queue_enum, }; -static int bsp_queue_values[] = { 0, 1, 2, 3, }; +static int bsp_queue_values[] = { + QFV_bspSolid, + QFV_bspSky, + QFV_bspTrans, + QFV_bspTurb, +}; static exprsym_t bsp_queue_symbols[] = { {"solid", &bsp_queue_type, bsp_queue_values + 0}, {"sky", &bsp_queue_type, bsp_queue_values + 1}, @@ -1421,17 +1241,26 @@ static exprenum_t bsp_queue_enum = { &bsp_queue_symtab, }; +static exprtype_t *bsp_visit_world_params[] = { + &bsp_stage_type, +}; + static exprtype_t *bsp_draw_queue_params[] = { &cexpr_int, &bsp_queue_type, &bsp_stage_type, }; +static exprfunc_t bsp_visit_world_func[] = { + { 0, 1, bsp_visit_world_params, bsp_visit_world }, + {} +}; static exprfunc_t bsp_draw_queue_func[] = { { 0, 3, bsp_draw_queue_params, bsp_draw_queue }, {} }; static exprsym_t bsp_task_syms[] = { + { "bsp_visit_world", &cexpr_function, bsp_visit_world_func }, { "bsp_draw_queue", &cexpr_function, bsp_draw_queue_func }, {} }; @@ -1505,7 +1334,7 @@ Vulkan_Bsp_Setup (vulkan_ctx_t *ctx) frames * entid_size, 0, (void **) &entid_data); for (size_t i = 0; i < frames; i++) { - __auto_type bframe = &bctx->frames.a[i]; + auto bframe = &bctx->frames.a[i]; DARRAY_INIT (&bframe->cmdSet, QFV_bspNumPasses); DARRAY_RESIZE (&bframe->cmdSet, QFV_bspNumPasses); @@ -1543,7 +1372,7 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx) bspctx_t *bctx = ctx->bsp_context; for (size_t i = 0; i < bctx->frames.size; i++) { - __auto_type bframe = &bctx->frames.a[i]; + auto bframe = &bctx->frames.a[i]; free (bframe->cmdSet.a); } From f2d2db9ef3dcf9a9067952e414520b9934fe9bba Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Jun 2023 21:01:34 +0900 Subject: [PATCH 3652/3664] [vulkan] Integrate screen capture in the new system This gets screenshots working again. As the implementation is now a (trivial) state machine, the pause when grabbing a screenshot is significantly reduced (it can be reduced even further by doing the png compression in a separate thread). --- include/QF/Vulkan/capture.h | 42 ++- include/QF/Vulkan/qf_vid.h | 1 - include/vid_vulkan.h | 6 +- libs/video/renderer/vid_render_vulkan.c | 51 +-- libs/video/renderer/vulkan/capture.c | 340 ++++++++++++------ libs/video/renderer/vulkan/rp_main_def.plist | 9 + libs/video/renderer/vulkan/vulkan_output.c | 5 +- .../video/renderer/vulkan/vulkan_vid_common.c | 12 - 8 files changed, 259 insertions(+), 207 deletions(-) diff --git a/include/QF/Vulkan/capture.h b/include/QF/Vulkan/capture.h index 7210154bc..605a940b3 100644 --- a/include/QF/Vulkan/capture.h +++ b/include/QF/Vulkan/capture.h @@ -9,40 +9,38 @@ #include "QF/darray.h" #include "QF/qtypes.h" -typedef struct qfv_capture_image_s { - VkCommandBuffer cmd; +struct vulkan_ctx_s; +struct tex_s; +typedef void (*capfunc_t) (struct tex_s *screencap, void *data); + +typedef struct qfv_capture_frame_s { VkBuffer buffer; byte *data; -} qfv_capture_image_t; -typedef struct qfv_capture_image_set_s - DARRAY_TYPE (qfv_capture_image_t) qfv_capture_image_set_t; + bool initiated; + capfunc_t callback; + void *callback_data; +} qfv_capture_frame_t; -#define QFV_AllocCaptureImageSet(num, allocator) \ - DARRAY_ALLOCFIXED (qfv_capture_image_set_t, num, allocator) +typedef struct qfv_capture_frame_set_s + DARRAY_TYPE (qfv_capture_frame_t) qfv_capture_frame_set_t; -typedef struct qfv_capture_s { +typedef struct qfv_capturectx_s { + qfv_capture_frame_set_t frames; struct qfv_device_s *device; - VkExtent2D extent; - qfv_capture_image_set_t *image_set; size_t imgsize; size_t memsize; byte *data; VkDeviceMemory memory; -} qfv_capture_t; +} qfv_capturectx_t; -struct qfv_swapchain_s; +struct vulkan_ctx_s; -qfv_capture_t *QFV_CreateCapture (struct qfv_device_s *device, int numframes, - struct qfv_swapchain_s *swapchain, - VkCommandPool cmdPool); -void QFV_RenewCapture (qfv_capture_t *capture, - struct qfv_swapchain_s *swapchain); -void QFV_DestroyCapture (qfv_capture_t *capture); - -VkCommandBuffer QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, - int frame); -const byte *QFV_CaptureData (qfv_capture_t *capture, int frame) __attribute__((pure)); +void QFV_Capture_Init (struct vulkan_ctx_s *ctx); +void QFV_Capture_Renew (struct vulkan_ctx_s *ctx); +void QFV_Capture_Shutdown (struct vulkan_ctx_s *ctx); +void QFV_Capture_Screen (struct vulkan_ctx_s *ctx, + capfunc_t callback, void *data); #endif//__QF_Vulkan_capture_h diff --git a/include/QF/Vulkan/qf_vid.h b/include/QF/Vulkan/qf_vid.h index a2c5d6007..8d6deb9bb 100644 --- a/include/QF/Vulkan/qf_vid.h +++ b/include/QF/Vulkan/qf_vid.h @@ -69,7 +69,6 @@ enum { }; struct vulkan_ctx_s; -void Vulkan_CreateCapture (struct vulkan_ctx_s *ctx); void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx); void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx); void Vulkan_Init_Common (struct vulkan_ctx_s *ctx); diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 85eaaa22e..fc6324162 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -37,6 +37,7 @@ typedef struct vulkan_ctx_s { struct scriptctx_s *script_context; struct qfv_renderctx_s *render_context; + struct qfv_capturectx_s *capture_context; struct texturectx_s *texture_context; struct matrixctx_s *matrix_context; struct translucentctx_s *translucent_context; @@ -57,11 +58,6 @@ typedef struct vulkan_ctx_s { uint32_t curFrame; qfv_renderpassset_t renderPasses; - struct qfv_capture_s *capture; - void (*capture_callback) (const byte *data, int width, int height); - // make a queue? - void *capture_complete;// really capfunc_t - void *capture_complete_data; struct qfv_tex_s *default_black; struct qfv_tex_s *default_white; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index ab09f3cd4..568ebaecc 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -96,8 +96,8 @@ vulkan_R_Init (void) Vulkan_Texture_Init (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx); - Vulkan_CreateCapture (vulkan_ctx); + QFV_Capture_Init (vulkan_ctx); Vulkan_Output_Init (vulkan_ctx); Vulkan_Matrix_Init (vulkan_ctx); @@ -357,56 +357,10 @@ vulkan_set_fov (float x, float y) mctx->dirty = mctx->frames.size; } -static int -is_bgr (VkFormat format) -{ - return (format >= VK_FORMAT_B8G8R8A8_UNORM - && format <= VK_FORMAT_B8G8R8A8_SRGB); -} - -static void -capture_screenshot (const byte *data, int width, int height) -{ - int count = width * height; - tex_t *tex = malloc (sizeof (tex_t) + count * 3); - - if (tex) { - tex->data = (byte *) (tex + 1); - tex->flagbits = 0; - tex->width = width; - tex->height = height; - tex->format = tex_rgb; - tex->palette = 0; - tex->flagbits = 0; - tex->loaded = 1; - - if (is_bgr (vulkan_ctx->swapchain->format)) { - tex->bgr = 1; - } - const byte *src = data; - byte *dst = tex->data; - for (int count = width * height; count-- > 0; ) { - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - src++; - } - } - capfunc_t callback = vulkan_ctx->capture_complete; - callback (tex, vulkan_ctx->capture_complete_data);; -} - static void vulkan_capture_screen (capfunc_t callback, void *data) { - if (!vulkan_ctx->capture) { - Sys_Printf ("Capture not supported\n"); - callback (0, data); - return; - } - vulkan_ctx->capture_callback = capture_screenshot; - vulkan_ctx->capture_complete = callback; - vulkan_ctx->capture_complete_data = data; + QFV_Capture_Screen (vulkan_ctx, callback, data); } static void @@ -588,6 +542,7 @@ vulkan_vid_render_shutdown (void) Vulkan_Scene_Shutdown (vulkan_ctx); Vulkan_Matrix_Shutdown (vulkan_ctx); + QFV_Capture_Shutdown (vulkan_ctx); Vulkan_Output_Shutdown (vulkan_ctx); Vulkan_Palette_Shutdown (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/capture.c b/libs/video/renderer/vulkan/capture.c index c61a139fb..b83f061a4 100644 --- a/libs/video/renderer/vulkan/capture.c +++ b/libs/video/renderer/vulkan/capture.c @@ -28,126 +28,51 @@ # include "config.h" #endif +#include "QF/cexpr.h" #include "QF/Vulkan/buffer.h" #include "QF/Vulkan/capture.h" #include "QF/Vulkan/command.h" #include "QF/Vulkan/device.h" #include "QF/Vulkan/image.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/swapchain.h" -qfv_capture_t * -QFV_CreateCapture (qfv_device_t *device, int numframes, - qfv_swapchain_t *swapchain, VkCommandPool cmdPool) -{ - qfv_instfuncs_t *ifunc = device->physDev->instance->funcs; - qfv_devfuncs_t *dfunc = device->funcs; - - VkFormatProperties format_props; - ifunc->vkGetPhysicalDeviceFormatProperties (device->physDev->dev, - swapchain->format, - &format_props); - if (!(swapchain->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) { - Sys_Printf ("Swapchain does not support reading. FIXME\n"); - return 0; - } - - qfv_capture_t *capture = malloc (sizeof (qfv_capture_t)); - capture->device = device; - capture->extent = swapchain->extent; - capture->image_set = QFV_AllocCaptureImageSet (numframes, malloc); - - __auto_type cmdset = QFV_AllocCommandBufferSet (numframes, alloca); - QFV_AllocateCommandBuffers (device, cmdPool, 1, cmdset); - - //FIXME assumes the swapchain is 32bpp - capture->imgsize = swapchain->extent.width * swapchain->extent.height * 4; - - for (int i = 0; i < numframes; i++) { - __auto_type image = &capture->image_set->a[i]; - image->buffer = QFV_CreateBuffer (device, capture->imgsize, - VK_BUFFER_USAGE_TRANSFER_DST_BIT); - } - VkMemoryRequirements req; - dfunc->vkGetBufferMemoryRequirements (device->dev, - capture->image_set->a[0].buffer, - &req); - capture->imgsize = QFV_NextOffset (capture->imgsize, &req); - capture->memsize = numframes * capture->imgsize; - capture->memory = QFV_AllocBufferMemory (device, - capture->image_set->a[0].buffer, - VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - capture->memsize, 0); - dfunc->vkMapMemory (device->dev, capture->memory, 0, capture->memsize, 0, - (void **) &capture->data); - - for (int i = 0; i < numframes; i++) { - __auto_type image = &capture->image_set->a[i]; - image->cmd = cmdset->a[i]; - image->data = capture->data + i * capture->imgsize; - QFV_BindBufferMemory (device, image->buffer, capture->memory, - i * capture->imgsize); - } - return capture; -} - -void -QFV_DestroyCapture (qfv_capture_t *capture) -{ - qfv_device_t *device = capture->device; - qfv_devfuncs_t *dfunc = device->funcs; - - for (size_t i = 0; i < capture->image_set->size; i++) { - __auto_type image = &capture->image_set->a[i]; - dfunc->vkDestroyBuffer (device->dev, image->buffer, 0); - } - dfunc->vkUnmapMemory (device->dev, capture->memory); - dfunc->vkFreeMemory (device->dev, capture->memory, 0); - free (capture->image_set); - free (capture); -} +#include "QF/plugin/vid_render.h" +#include "vid_vulkan.h" static void -copy_image (qfv_capture_t *capture, qfv_devfuncs_t *dfunc, - VkImage scImage, qfv_capture_image_t *image) +capture_initiate (const exprval_t **params, exprval_t *result, exprctx_t *ectx) { - VkBufferImageCopy copy = { - .bufferOffset = 0, - .bufferRowLength = 0, - .bufferImageHeight = 0, - .imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, - .imageOffset = { }, - .imageExtent = { capture->extent.width, capture->extent.height, 1 }, - }; - dfunc->vkCmdCopyImageToBuffer (image->cmd, scImage, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image->buffer, 1, ©); -} + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; -VkCommandBuffer -QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame) -{ - qfv_device_t *device = capture->device; - qfv_devfuncs_t *dfunc = device->funcs; - __auto_type image = &capture->image_set->a[frame]; + auto cap = ctx->capture_context; + auto frame = &cap->frames.a[ctx->curFrame]; - dfunc->vkResetCommandBuffer (image->cmd, 0); - VkCommandBufferInheritanceInfo inherit = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, - 0, 0, 0, 0, 0, 0, - }; + if (!frame->callback) { + return; + } + + auto device = ctx->device; + auto dfunc = device->funcs; + + auto cmd = QFV_GetCmdBuffer (ctx, false); VkCommandBufferBeginInfo beginInfo = { - VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0, - VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, &inherit, + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, }; - dfunc->vkBeginCommandBuffer (image->cmd, &beginInfo); + dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + + auto sc = ctx->swapchain; + auto scImage = sc->images->a[ctx->swapImageIndex]; VkBufferMemoryBarrier start_buffer_barriers[] = { { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .srcAccessMask = 0, .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .buffer = image->buffer, + .buffer = frame->buffer, .offset = 0, .size = VK_WHOLE_SIZE, }, @@ -168,7 +93,7 @@ QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame) .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT, - .buffer = image->buffer, + .buffer = frame->buffer, .offset = 0, .size = VK_WHOLE_SIZE, }, @@ -185,39 +110,224 @@ QFV_CaptureImage (qfv_capture_t *capture, VkImage scImage, int frame) }, }; - dfunc->vkCmdPipelineBarrier (image->cmd, + dfunc->vkCmdPipelineBarrier (cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, 0, 1, start_buffer_barriers, 1, start_image_barriers); - copy_image (capture, dfunc, scImage, image); + VkBufferImageCopy copy = { + .bufferOffset = 0, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }, + .imageOffset = { }, + .imageExtent = { cap->extent.width, cap->extent.height, 1 }, + }; + dfunc->vkCmdCopyImageToBuffer (cmd, scImage, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + frame->buffer, 1, ©); - dfunc->vkCmdPipelineBarrier (image->cmd, + dfunc->vkCmdPipelineBarrier (cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, 0, 1, end_buffer_barriers, 1, end_image_barriers); + dfunc->vkEndCommandBuffer (cmd); + QFV_AppendCmdBuffer (ctx, cmd); - dfunc->vkEndCommandBuffer (image->cmd); - - return image->cmd; + frame->initiated = true; + auto time = Sys_LongTime (); + printf ("capture_initiate: %zd.%03zd.%0zd\n", + time / 1000000, (time / 1000) % 1000, time % 1000); } -const byte * -QFV_CaptureData (qfv_capture_t *capture, int frame) +static int +is_bgr (VkFormat format) { - qfv_device_t *device = capture->device; - qfv_devfuncs_t *dfunc = device->funcs; - __auto_type image = &capture->image_set->a[frame]; + return (format >= VK_FORMAT_B8G8R8A8_UNORM + && format <= VK_FORMAT_B8G8R8A8_SRGB); +} + +static void +capture_finalize (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + + auto cap = ctx->capture_context; + auto frame = &cap->frames.a[ctx->curFrame]; + + if (!frame->callback || !frame->initiated) { + return; + } + auto time = Sys_LongTime (); + printf ("capture_finalize: %zd.%03zd.%0zd\n", + time / 1000000, (time / 1000) % 1000, time % 1000); + + auto device = ctx->device; + auto dfunc = device->funcs; + VkMappedMemoryRange range = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = capture->memory, - .offset = image->data - capture->data, - .size = capture->imgsize, + .memory = cap->memory, + .offset = frame->data - cap->data, + .size = cap->imgsize, }; dfunc->vkInvalidateMappedMemoryRanges (device->dev, 1, &range); - return image->data; + + int count = cap->extent.width * cap->extent.height; + tex_t *tex = malloc (sizeof (tex_t) + count * 3); + + if (tex) { + tex->data = (byte *) (tex + 1); + tex->flagbits = 0; + tex->width = cap->extent.width; + tex->height = cap->extent.height; + tex->format = tex_rgb; + tex->palette = 0; + tex->flagbits = 0; + tex->loaded = 1; + + if (is_bgr (ctx->swapchain->format)) { + tex->bgr = 1; + } + const byte *src = frame->data; + byte *dst = tex->data; + while (count-- > 0) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + src++; + } + } + + frame->callback (tex, frame->callback_data);; + frame->callback = 0; + frame->callback_data = 0; + frame->initiated = false; +} + +static exprfunc_t capture_initiate_func[] = { + { .func = capture_initiate }, + {} +}; +static exprfunc_t capture_finalize_func[] = { + { .func = capture_finalize }, + {} +}; +static exprsym_t capture_task_syms[] = { + { "capture_initiate", &cexpr_function, capture_initiate_func }, + { "capture_finalize", &cexpr_function, capture_finalize_func }, + {} +}; + +void +QFV_Capture_Init (vulkan_ctx_t *ctx) +{ + QFV_Render_AddTasks (ctx, capture_task_syms); + + qfvPushDebug (ctx, "capture init"); + + auto device = ctx->device; + auto ifunc = device->physDev->instance->funcs; + auto dfunc = device->funcs; + + ctx->capture_context = calloc (1, sizeof (qfv_capturectx_t)); + auto cap = ctx->capture_context; + + auto swapchain = ctx->swapchain; + VkFormatProperties format_props; + ifunc->vkGetPhysicalDeviceFormatProperties (device->physDev->dev, + swapchain->format, + &format_props); + if (!(swapchain->usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) { + Sys_Printf ("Swapchain does not support reading. FIXME\n"); + return; + } + + cap->device = device; + cap->extent = swapchain->extent; + + auto rctx = ctx->render_context; + size_t frames = rctx->frames.size; + DARRAY_INIT (&cap->frames, frames); + DARRAY_RESIZE (&cap->frames, frames); + cap->frames.grow = 0; + + //FIXME assumes the swapchain is 32bpp + cap->imgsize = swapchain->extent.width * swapchain->extent.height * 4; + + for (size_t i = 0; i < frames; i++) { + auto frame = &cap->frames.a[i]; + *frame = (qfv_capture_frame_t) { + .buffer = QFV_CreateBuffer (device, cap->imgsize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT), + }; + } + VkMemoryRequirements req; + dfunc->vkGetBufferMemoryRequirements (device->dev, + cap->frames.a[0].buffer, + &req); + cap->imgsize = QFV_NextOffset (cap->imgsize, &req); + cap->memsize = frames * cap->imgsize; + cap->memory = QFV_AllocBufferMemory (device, + cap->frames.a[0].buffer, + VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + cap->memsize, 0); + dfunc->vkMapMemory (device->dev, cap->memory, 0, cap->memsize, 0, + (void **) &cap->data); + + for (size_t i = 0; i < frames; i++) { + auto frame = &cap->frames.a[i]; + frame->data = cap->data + i * cap->imgsize; + QFV_BindBufferMemory (device, frame->buffer, cap->memory, + i * cap->imgsize); + } + qfvPopDebug (ctx); +} + +int shut_up_gcc = 1; +void +QFV_Capture_Renew (vulkan_ctx_t *ctx) +{ + if (shut_up_gcc) { + Sys_Error ("QFV_Capture_Renew not implemented"); + } +} + +void +QFV_Capture_Shutdown (vulkan_ctx_t *ctx) +{ + auto device = ctx->device; + auto dfunc = device->funcs; + auto cap = ctx->capture_context; + + for (size_t i = 0; i < cap->frames.size; i++) { + auto frame = &cap->frames.a[i]; + dfunc->vkDestroyBuffer (device->dev, frame->buffer, 0); + } + dfunc->vkUnmapMemory (device->dev, cap->memory); + dfunc->vkFreeMemory (device->dev, cap->memory, 0); + DARRAY_CLEAR (&cap->frames); + free (cap); +} + +void +QFV_Capture_Screen (vulkan_ctx_t *ctx, capfunc_t callback, void *data) +{ + auto cap = ctx->capture_context; + if (!cap->data) { + Sys_Printf ("Capture not supported\n"); + callback (0, data); + return; + } + auto frame = &cap->frames.a[ctx->curFrame]; + frame->callback = callback; + frame->callback_data = data; + auto time = Sys_LongTime (); + printf ("capture_request: %zd.%03zd.%0zd\n", + time / 1000000, (time / 1000) % 1000, time % 1000); } diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 3a382881d..1a1a33034 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1411,6 +1411,7 @@ steps = { process = { tasks = ( { func = wait_on_fence; }, + { func = capture_finalize; }, { func = update_matrices; }, { func = draw_scr_funcs; }, ); @@ -1505,4 +1506,12 @@ steps = { }; }; }; + capture = { + dependencies = (output); + process = { + tasks = ( + { func = capture_initiate; }, + ); + }; + }; }; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index e8f3ec55b..b20a60041 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -78,9 +78,6 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) while (!QFV_AcquireNextImage (sc, frame->imageAvailableSemaphore, 0, &imageIndex)) { QFV_DeviceWaitIdle (device); - if (ctx->capture) { - QFV_DestroyCapture (ctx->capture); - } for (uint32_t i = 0; i < sc->imageViews->size; i++) { dfunc->vkDestroyFramebuffer (device->dev, octx->framebuffers[i], 0); @@ -88,7 +85,7 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx) octx->framebuffers = 0; Vulkan_CreateSwapchain (ctx); sc = ctx->swapchain; - Vulkan_CreateCapture (ctx); + QFV_Capture_Renew (ctx); dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore, 0); diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 2b6987788..c11133339 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -121,9 +121,6 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx) void Vulkan_Shutdown_Common (vulkan_ctx_t *ctx) { - if (ctx->capture) { - QFV_DestroyCapture (ctx->capture); - } if (ctx->swapchain) { QFV_DestroySwapchain (ctx->swapchain); } @@ -183,15 +180,6 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx) ctx->swapchain = QFV_CreateSwapchain (ctx, old_swapchain); } -void -Vulkan_CreateCapture (vulkan_ctx_t *ctx) -{ - //FIXME this should be in render - auto rctx = ctx->render_context; - ctx->capture = QFV_CreateCapture (ctx->device, rctx->frames.size, - ctx->swapchain, ctx->cmdpool); -} - void Vulkan_BeginEntityLabel (vulkan_ctx_t *ctx, VkCommandBuffer cmd, entity_t ent) { From 17ee6911f9a1e33bcae1797280f5c6ed8f0edbf9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Jun 2023 23:33:47 +0900 Subject: [PATCH 3653/3664] [vulkan] Clean up the sampler config loading Samplers have no direct relation to render passes or pipelines, so should not necessarily be in the same config file. This makes all the old config files obsolete, and quite a bit of support code in vkparse.c. --- include/QF/Vulkan/qf_alias.h | 1 + include/QF/Vulkan/qf_iqm.h | 1 + include/QF/Vulkan/qf_sprite.h | 1 + include/QF/Vulkan/render.h | 34 ++++- libs/video/renderer/Makemodule.am | 4 + libs/video/renderer/vid_render_vulkan.c | 6 +- libs/video/renderer/vulkan/render.c | 60 +++++++- libs/video/renderer/vulkan/render_load.c | 20 ++- libs/video/renderer/vulkan/smp_quake.plist | 138 +++++++++++++++++++ libs/video/renderer/vulkan/vkparse.c | 60 +++++++- libs/video/renderer/vulkan/vkparse.h | 3 + libs/video/renderer/vulkan/vkparse.plist | 32 +++++ libs/video/renderer/vulkan/vulkan_alias.c | 8 +- libs/video/renderer/vulkan/vulkan_bsp.c | 4 +- libs/video/renderer/vulkan/vulkan_draw.c | 5 +- libs/video/renderer/vulkan/vulkan_iqm.c | 9 +- libs/video/renderer/vulkan/vulkan_lighting.c | 4 +- libs/video/renderer/vulkan/vulkan_output.c | 10 +- libs/video/renderer/vulkan/vulkan_palette.c | 4 +- libs/video/renderer/vulkan/vulkan_sprite.c | 9 +- 20 files changed, 380 insertions(+), 33 deletions(-) create mode 100644 libs/video/renderer/vulkan/smp_quake.plist diff --git a/include/QF/Vulkan/qf_alias.h b/include/QF/Vulkan/qf_alias.h index 54c7c9e9c..8893bd3a0 100644 --- a/include/QF/Vulkan/qf_alias.h +++ b/include/QF/Vulkan/qf_alias.h @@ -95,6 +95,7 @@ void Vulkan_AliasAddSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); void Vulkan_AliasRemoveSkin (struct vulkan_ctx_s *ctx, qfv_alias_skin_t *skin); void Vulkan_Alias_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Alias_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_alias_h diff --git a/include/QF/Vulkan/qf_iqm.h b/include/QF/Vulkan/qf_iqm.h index 537547147..d39051882 100644 --- a/include/QF/Vulkan/qf_iqm.h +++ b/include/QF/Vulkan/qf_iqm.h @@ -107,6 +107,7 @@ void Vulkan_IQMAddSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); void Vulkan_IQMRemoveSkin (struct vulkan_ctx_s *ctx, qfv_iqm_skin_t *skin); void Vulkan_IQM_Init (struct vulkan_ctx_s *ctx); +void Vulkan_IQM_Setup (struct vulkan_ctx_s *ctx); void Vulkan_IQM_Shutdown (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_iqm_h diff --git a/include/QF/Vulkan/qf_sprite.h b/include/QF/Vulkan/qf_sprite.h index 8139c479c..57520dbd6 100644 --- a/include/QF/Vulkan/qf_sprite.h +++ b/include/QF/Vulkan/qf_sprite.h @@ -76,6 +76,7 @@ void Vulkan_Mod_SpriteLoadFrames (struct mod_sprite_ctx_s *sprite_ctx, struct vulkan_ctx_s *ctx); void Vulkan_Sprite_Init (struct vulkan_ctx_s *ctx); +void Vulkan_Sprite_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Sprite_Shutdown (struct vulkan_ctx_s *ctx); #endif//__QF_Vulkan_qf_sprite_h diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 5a6e9dc78..10cb3b47e 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -272,6 +272,35 @@ typedef struct qfv_jobinfo_s { qfv_descriptorsetlayoutinfo_t *dslayouts; } qfv_jobinfo_t; +typedef struct qfv_samplercreateinfo_s { + const char *name; + VkSamplerCreateFlags flags; + VkFilter magFilter; + VkFilter minFilter; + VkSamplerMipmapMode mipmapMode; + VkSamplerAddressMode addressModeU; + VkSamplerAddressMode addressModeV; + VkSamplerAddressMode addressModeW; + float mipLodBias; + VkBool32 anisotropyEnable; + float maxAnisotropy; + VkBool32 compareEnable; + VkCompareOp compareOp; + float minLod; + float maxLod; + VkBorderColor borderColor; + VkBool32 unnormalizedCoordinates; + VkSampler sampler; +} qfv_samplercreateinfo_t; + +typedef struct qfv_samplerinfo_s { + struct memsuper_s *memsuper; + + struct plitem_s *plitem; + qfv_samplercreateinfo_t *samplers; + uint32_t num_samplers; +} qfv_samplerinfo_t; + #ifndef __QFCC__ typedef struct qfv_label_s { vec4f_t color; @@ -386,6 +415,7 @@ typedef struct qfv_renderctx_s { struct hashctx_s *hashctx; exprtab_t task_functions; qfv_jobinfo_t *jobinfo; + qfv_samplerinfo_t *samplerinfo; qfv_job_t *job; qfv_renderframeset_t frames; } qfv_renderctx_t; @@ -401,7 +431,8 @@ VkCommandBuffer QFV_GetCmdBuffer (struct vulkan_ctx_s *ctx, bool secondary); void QFV_AppendCmdBuffer (struct vulkan_ctx_s *ctx, VkCommandBuffer cmd); void QFV_RunRenderJob (struct vulkan_ctx_s *ctx); -void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx); +void QFV_LoadRenderInfo (struct vulkan_ctx_s *ctx, const char *name); +void QFV_LoadSamplerInfo (struct vulkan_ctx_s *ctx, const char *name); void QFV_BuildRender (struct vulkan_ctx_s *ctx); void QFV_Render_Init (struct vulkan_ctx_s *ctx); void QFV_Render_Shutdown (struct vulkan_ctx_s *ctx); @@ -412,6 +443,7 @@ void QFV_CreateFramebuffer (struct vulkan_ctx_s *ctx, qfv_renderpass_t *rp); struct qfv_dsmanager_s * QFV_Render_DSManager (struct vulkan_ctx_s *ctx, const char *setName) __attribute__((pure)); +VkSampler QFV_Render_Sampler (struct vulkan_ctx_s *ctx, const char *name); qfv_step_t *QFV_GetStep (const exprval_t *param, qfv_job_t *job); qfv_step_t *QFV_FindStep (const char *step, qfv_job_t *job) __attribute__((pure)); diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index cddf9f20f..9f5f16308 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -203,6 +203,8 @@ rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist rp_forward_gen = libs/video/renderer/vulkan/rp_forward.plc rp_main_def_src = libs/video/renderer/vulkan/rp_main_def.plist rp_main_def_gen = libs/video/renderer/vulkan/rp_main_def.plc +smp_quake_src = libs/video/renderer/vulkan/smp_quake.plist +smp_quake_gen = libs/video/renderer/vulkan/smp_quake.plc rp_output_src = libs/video/renderer/vulkan/rp_output.plist rp_output_gen = libs/video/renderer/vulkan/rp_output.plc rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist @@ -270,6 +272,7 @@ libs/video/renderer/vulkan/vkparse.lo: \ ${rp_deferred_gen} \ $(rp_forward_gen) \ $(rp_main_def_gen) \ + $(smp_quake_gen) $(rp_output_gen) \ ${rp_shadow_gen} @@ -530,6 +533,7 @@ EXTRA_DIST += \ $(rp_deferred_src) \ $(rp_forward_src) \ $(rp_main_def_src) \ + $(smp_quake_src) \ $(rp_output_src) \ $(rp_shadow_src) \ $(pl_quake_def_src) \ diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 568ebaecc..ac3dc3ad0 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -112,14 +112,18 @@ vulkan_R_Init (void) Vulkan_Translucent_Init (vulkan_ctx); Vulkan_Compose_Init (vulkan_ctx); - QFV_LoadRenderInfo (vulkan_ctx); + QFV_LoadRenderInfo (vulkan_ctx, "main_def"); + QFV_LoadSamplerInfo (vulkan_ctx, "smp_quake"); QFV_BuildRender (vulkan_ctx); Vulkan_Texture_Setup (vulkan_ctx); Vulkan_Palette_Init (vulkan_ctx, vid.palette); + Vulkan_Alias_Setup (vulkan_ctx); Vulkan_Bsp_Setup (vulkan_ctx); + Vulkan_IQM_Setup (vulkan_ctx); Vulkan_Matrix_Setup (vulkan_ctx); Vulkan_Scene_Setup (vulkan_ctx); + Vulkan_Sprite_Setup (vulkan_ctx); Vulkan_Output_Setup (vulkan_ctx); Vulkan_Compose_Setup (vulkan_ctx); Vulkan_Draw_Setup (vulkan_ctx); diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 9fdb6ba7d..05084d022 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -508,6 +508,15 @@ QFV_Render_Shutdown (vulkan_ctx_t *ctx) if (rctx->task_functions.tab) { Hash_DelTable (rctx->task_functions.tab); } + if (rctx->samplerinfo) { + auto si = rctx->samplerinfo; + for (uint32_t i = 0; i < si->num_samplers; i++) { + auto sci = &si->samplers[i]; + if (sci->sampler) { + dfunc->vkDestroySampler (device->dev, sci->sampler, 0); + } + } + } Hash_DelContext (rctx->hashctx); } @@ -562,7 +571,7 @@ QFV_GetStep (const exprval_t *param, qfv_job_t *job) } qfv_dsmanager_t * -QFV_Render_DSManager (struct vulkan_ctx_s *ctx, const char *setName) +QFV_Render_DSManager (vulkan_ctx_t *ctx, const char *setName) { auto job = ctx->render_context->job; for (uint32_t i = 0; i < job->num_dsmanagers; i++) { @@ -573,3 +582,52 @@ QFV_Render_DSManager (struct vulkan_ctx_s *ctx, const char *setName) } return 0; } + +static void +create_sampler (vulkan_ctx_t *ctx, qfv_samplercreateinfo_t *sampler) +{ + VkSamplerCreateInfo create = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .flags = sampler->flags, + .magFilter = sampler->magFilter, + .minFilter = sampler->minFilter, + .mipmapMode = sampler->mipmapMode, + .addressModeU = sampler->addressModeU, + .addressModeV = sampler->addressModeV, + .addressModeW = sampler->addressModeW, + .mipLodBias = sampler->mipLodBias, + .anisotropyEnable = sampler->anisotropyEnable, + .maxAnisotropy = sampler->maxAnisotropy, + .compareEnable = sampler->compareEnable, + .compareOp = sampler->compareOp, + .minLod = sampler->minLod, + .maxLod = sampler->maxLod, + .borderColor = sampler->borderColor, + .unnormalizedCoordinates = sampler->unnormalizedCoordinates, + }; + auto device = ctx->device; + auto dfunc = device->funcs; + dfunc->vkCreateSampler (device->dev, &create, 0, &sampler->sampler); + QFV_duSetObjectName (device, VK_OBJECT_TYPE_SAMPLER, sampler->sampler, + va (ctx->va_ctx, "sampler:%s", sampler->name)); +} + +VkSampler +QFV_Render_Sampler (vulkan_ctx_t *ctx, const char *name) +{ + auto si = ctx->render_context->samplerinfo; + if (!si) { + return 0; + } + for (uint32_t i = 0; i < si->num_samplers; i++) { + auto sci = &si->samplers[i]; + if (!strcmp (sci->name, name)) { + if (!sci->sampler) { + create_sampler (ctx, sci); + } + return sci->sampler; + } + } + printf ("sampler %s not found\n", name); + return 0; +} diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index ccc79e658..719473f87 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -72,12 +72,11 @@ get_output (vulkan_ctx_t *ctx, plitem_t *item) } void -QFV_LoadRenderInfo (vulkan_ctx_t *ctx) +QFV_LoadRenderInfo (vulkan_ctx_t *ctx, const char *name) { - __auto_type rctx = ctx->render_context; - - plitem_t *item = Vulkan_GetConfig (ctx, "main_def"); - __auto_type output = get_output (ctx, item); + auto rctx = ctx->render_context; + auto item = Vulkan_GetConfig (ctx, name); + auto output = get_output (ctx, item); Vulkan_Script_SetOutput (ctx, &output); rctx->jobinfo = QFV_ParseJobInfo (ctx, item, rctx); if (rctx->jobinfo) { @@ -85,6 +84,17 @@ QFV_LoadRenderInfo (vulkan_ctx_t *ctx) } } +void +QFV_LoadSamplerInfo (vulkan_ctx_t *ctx, const char *name) +{ + auto rctx = ctx->render_context; + auto item = Vulkan_GetConfig (ctx, name); + rctx->samplerinfo = QFV_ParseSamplerInfo (ctx, item, rctx); + if (rctx->samplerinfo) { + rctx->samplerinfo->plitem = item; + } +} + typedef struct { uint32_t num_images; uint32_t num_imageviews; diff --git a/libs/video/renderer/vulkan/smp_quake.plist b/libs/video/renderer/vulkan/smp_quake.plist new file mode 100644 index 000000000..0c4db686f --- /dev/null +++ b/libs/video/renderer/vulkan/smp_quake.plist @@ -0,0 +1,138 @@ +samplers = { + quakepic = { + magFilter = nearest; + minFilter = nearest; + mipmapMode = nearest; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 0; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; + glyph = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 0; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; + palette_sampler = { + magFilter = nearest; + minFilter = nearest; + mipmapMode = nearest; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 4; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; + quakebsp_sampler = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = repeat; + addressModeV = repeat; + addressModeW = repeat; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 4; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; + alias_sampler = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 1000; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; + sprite_sampler = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 1000; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; + shadow_sampler = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = true; + compareOp = greater_or_equal; + minLod = 0; + maxLod = 1000; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; + linear = { + magFilter = linear; + minFilter = linear; + mipmapMode = linear; + addressModeU = clamp_to_edge; + addressModeV = clamp_to_edge; + addressModeW = clamp_to_edge; + mipLodBias = 0; + anisotropyEnable = false; + maxAnisotropy = 0; + compareEnable = false; + compareOp = always; + minLod = 0; + maxLod = 0; + borderColor = float_transparent_black; + unnormalizedCoordinates = false; + }; +}; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 56743ee25..8f5d8bf6a 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1866,6 +1866,10 @@ static exprsym_t builtin_plist_syms[] = { .value = (void *) #include "libs/video/renderer/vulkan/rp_main_def.plc" }, + { .name = "smp_quake", + .value = (void *) +#include "libs/video/renderer/vulkan/smp_quake.plc" + }, { .name = "output", .value = (void *) #include "libs/video/renderer/vulkan/rp_output.plc" @@ -2118,8 +2122,8 @@ struct qfv_jobinfo_s * QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) { memsuper_t *memsuper = new_memsuper (); - qfv_jobinfo_t *ri = cmemalloc (memsuper, sizeof (qfv_jobinfo_t)); - *ri = (qfv_jobinfo_t) { .memsuper = memsuper }; + qfv_jobinfo_t *ji = cmemalloc (memsuper, sizeof (qfv_jobinfo_t)); + *ji = (qfv_jobinfo_t) { .memsuper = memsuper }; scriptctx_t *sctx = ctx->script_context; plitem_t *messages = PL_NewArray (); @@ -2155,7 +2159,7 @@ QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) &exprctx); int ret; - if (!(ret = parse_qfv_jobinfo_t (0, item, ri, messages, &parsectx))) { + if (!(ret = parse_qfv_jobinfo_t (0, item, ji, messages, &parsectx))) { for (int i = 0; i < PL_A_NumObjects (messages); i++) { Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); } @@ -2164,10 +2168,56 @@ QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) PL_Release (messages); if (!ret) { delete_memsuper (memsuper); - ri = 0; + ji = 0; } - return ri; + return ji; +} + +struct qfv_samplerinfo_s * +QFV_ParseSamplerInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) +{ + memsuper_t *memsuper = new_memsuper (); + qfv_samplerinfo_t *si = cmemalloc (memsuper, sizeof (qfv_samplerinfo_t)); + *si = (qfv_samplerinfo_t) { .memsuper = memsuper }; + + scriptctx_t *sctx = ctx->script_context; + plitem_t *messages = PL_NewArray (); + + exprctx_t exprctx = { + .symtab = &root_symtab, + .messages = messages, + .hashctx = &sctx->hashctx, + .memsuper = memsuper, + }; + parsectx_t parsectx = { + .ectx = &exprctx, + .vctx = ctx, + .data = rctx, + }; + + exprsym_t var_syms[] = { + {"physDevLimits", &VkPhysicalDeviceLimits_type, + &ctx->device->physDev->properties->limits }, + {} + }; + exprctx.external_variables = QFV_CreateSymtab (item, "properties", + 0, var_syms, &exprctx); + + int ret; + if (!(ret = parse_qfv_samplerinfo_t (0, item, si, messages, &parsectx))) { + for (int i = 0; i < PL_A_NumObjects (messages); i++) { + Sys_Printf ("%s\n", PL_String (PL_ObjectAtIndex (messages, i))); + } + } + QFV_DestroySymtab (exprctx.external_variables); + PL_Release (messages); + if (!ret) { + delete_memsuper (memsuper); + si = 0; + } + + return si; } int diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index ebc1a691f..a12be0701 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -88,4 +88,7 @@ int QFV_ParseLayoutInfo (vulkan_ctx_t *ctx, struct memsuper_s *memsuper, qfv_layoutinfo_t *layout); struct qfv_jobinfo_s *QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, struct qfv_renderctx_s *rctx); +struct qfv_samplerinfo_s *QFV_ParseSamplerInfo (vulkan_ctx_t *ctx, + plitem_t *item, + struct qfv_renderctx_s *rctx); #endif//__vkparse_h diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index cc0149e63..be33db563 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -54,6 +54,8 @@ search = ( qfv_processinfo_t, qfv_stepinfo_t, qfv_jobinfo_t, + qfv_samplercreateinfo_t, + qfv_samplerinfo_t, ); parse = { VkSubpassDescription = { @@ -779,5 +781,35 @@ parse = { size = num_dslayouts; values = dslayouts; }; + plitem = ignore; + }; + qfv_samplercreateinfo_s = { + .name = qfv_samplercreateinfo_t; + flags = auto; + magFilter = auto; + minFilter = auto; + mipmapMode = auto; + addressModeU = auto; + addressModeV = auto; + addressModeW = auto; + mipLodBias = auto; + anisotropyEnable = auto; + maxAnisotropy = auto; + compareEnable = auto; + compareOp = auto; + minLod = auto; + maxLod = auto; + borderColor = auto; + unnormalizedCoordinates = auto; + sampler = ignore; + }; + qfv_samplerinfo_s = { + .name = qfv_samplerinfo_t; + samplers = { + type = (labeledarray, qfv_samplercreateinfo_t, name); + size = num_samplers; + values = samplers; + }; + plitem = ignore; }; }; diff --git a/libs/video/renderer/vulkan/vulkan_alias.c b/libs/video/renderer/vulkan/vulkan_alias.c index bd61b454f..914e1ae28 100644 --- a/libs/video/renderer/vulkan/vulkan_alias.c +++ b/libs/video/renderer/vulkan/vulkan_alias.c @@ -246,10 +246,16 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx) aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); ctx->alias_context = actx; - actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); qfvPopDebug (ctx); } +void +Vulkan_Alias_Setup (vulkan_ctx_t *ctx) +{ + auto actx = ctx->alias_context; + actx->sampler = QFV_Render_Sampler (ctx, "alias_sampler"); +} + void Vulkan_Alias_Shutdown (vulkan_ctx_t *ctx) { diff --git a/libs/video/renderer/vulkan/vulkan_bsp.c b/libs/video/renderer/vulkan/vulkan_bsp.c index 8e640de16..7cfd3481f 100644 --- a/libs/video/renderer/vulkan/vulkan_bsp.c +++ b/libs/video/renderer/vulkan/vulkan_bsp.c @@ -1284,6 +1284,8 @@ Vulkan_Bsp_Setup (vulkan_ctx_t *ctx) auto bctx = ctx->bsp_context; + bctx->sampler = QFV_Render_Sampler (ctx, "quakebsp_sampler"); + bctx->light_scrap = QFV_CreateScrap (device, "lightmap_atlas", 2048, tex_frgba, ctx->staging); size_t size = QFV_ScrapSize (bctx->light_scrap); @@ -1308,8 +1310,6 @@ Vulkan_Bsp_Setup (vulkan_ctx_t *ctx) DARRAY_RESIZE (&bctx->frames, frames); bctx->frames.grow = 0; - bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); - size_t entid_count = Vulkan_Scene_MaxEntities (ctx); size_t entid_size = entid_count * sizeof (uint32_t); size_t atom = device->physDev->properties->limits.nonCoherentAtomSize; diff --git a/libs/video/renderer/vulkan/vulkan_draw.c b/libs/video/renderer/vulkan/vulkan_draw.c index 742d8c11f..80ce3d92a 100644 --- a/libs/video/renderer/vulkan/vulkan_draw.c +++ b/libs/video/renderer/vulkan/vulkan_draw.c @@ -1046,6 +1046,9 @@ Vulkan_Draw_Setup (vulkan_ctx_t *ctx) auto dfunc = device->funcs; auto dctx = ctx->draw_context; + dctx->pic_sampler = QFV_Render_Sampler (ctx, "quakepic"); + dctx->glyph_sampler = QFV_Render_Sampler (ctx, "glyph"); + dctx->dsmanager = QFV_Render_DSManager (ctx, "quad_data_set"); auto rctx = ctx->render_context; @@ -1069,8 +1072,6 @@ Vulkan_Draw_Setup (vulkan_ctx_t *ctx) ctx->cmdpool); dctx->scrap = QFV_CreateScrap (device, "draw_atlas", 2048, tex_rgba, dctx->stage); - dctx->pic_sampler = Vulkan_CreateSampler (ctx, "quakepic"); - dctx->glyph_sampler = Vulkan_CreateSampler (ctx, "glyph"); load_conchars (ctx); load_crosshairs (ctx); diff --git a/libs/video/renderer/vulkan/vulkan_iqm.c b/libs/video/renderer/vulkan/vulkan_iqm.c index 4908a0d06..1fc653a95 100644 --- a/libs/video/renderer/vulkan/vulkan_iqm.c +++ b/libs/video/renderer/vulkan/vulkan_iqm.c @@ -313,11 +313,16 @@ Vulkan_IQM_Init (vulkan_ctx_t *ctx) DARRAY_RESIZE (&ictx->frames, frames); ictx->frames.grow = 0; - ictx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); - qfvPopDebug (ctx); } +void +Vulkan_IQM_Setup (vulkan_ctx_t *ctx) +{ + auto ictx = ctx->iqm_context; + ictx->sampler = QFV_Render_Sampler (ctx, "alias_sampler"); +} + void Vulkan_IQM_Shutdown (vulkan_ctx_t *ctx) { diff --git a/libs/video/renderer/vulkan/vulkan_lighting.c b/libs/video/renderer/vulkan/vulkan_lighting.c index 5ed4b5f33..9249f46c5 100644 --- a/libs/video/renderer/vulkan/vulkan_lighting.c +++ b/libs/video/renderer/vulkan/vulkan_lighting.c @@ -313,6 +313,8 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx) auto dfunc = device->funcs; auto lctx = ctx->lighting_context; + lctx->sampler = QFV_Render_Sampler (ctx, "shadow_sampler"); + Vulkan_Script_SetOutput (ctx, &(qfv_output_t) { .format = VK_FORMAT_X8_D24_UNORM_PACK32 }); #if 0 @@ -335,8 +337,6 @@ Vulkan_Lighting_Setup (vulkan_ctx_t *ctx) DARRAY_RESIZE (&lctx->frames, frames); lctx->frames.grow = 0; - lctx->sampler = Vulkan_CreateSampler (ctx, "shadow_sampler"); - __auto_type lbuffers = QFV_AllocBufferSet (frames, alloca); for (size_t i = 0; i < frames; i++) { lbuffers->a[i] = QFV_CreateBuffer (device, sizeof (qfv_light_buffer_t), diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index b20a60041..513fc0603 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -240,14 +240,6 @@ Vulkan_Output_Init (vulkan_ctx_t *ctx) ctx->output_context = octx; QFV_Render_AddTasks (ctx, output_task_syms); - - __auto_type pld = ctx->script_context->pipelineDef;//FIXME - ctx->script_context->pipelineDef = Vulkan_GetConfig (ctx, "qf_output"); - - qfvPushDebug (ctx, "output init"); - octx->sampler = Vulkan_CreateSampler (ctx, "linear"); - ctx->script_context->pipelineDef = pld; - qfvPopDebug (ctx); } void @@ -263,6 +255,8 @@ Vulkan_Output_Setup (vulkan_ctx_t *ctx) DARRAY_RESIZE (&octx->frames, frames); octx->frames.grow = 0; + octx->sampler = QFV_Render_Sampler (ctx, "linear"); + auto dsmanager = QFV_Render_DSManager (ctx, "output_set"); for (size_t i = 0; i < frames; i++) { diff --git a/libs/video/renderer/vulkan/vulkan_palette.c b/libs/video/renderer/vulkan/vulkan_palette.c index 0b7ce791a..4d3712d3e 100644 --- a/libs/video/renderer/vulkan/vulkan_palette.c +++ b/libs/video/renderer/vulkan/vulkan_palette.c @@ -42,6 +42,7 @@ #include "QF/sys.h" #include "QF/va.h" #include "QF/Vulkan/instance.h" +#include "QF/Vulkan/render.h" #include "QF/Vulkan/qf_palette.h" #include "QF/Vulkan/qf_texture.h" @@ -69,7 +70,8 @@ Vulkan_Palette_Init (vulkan_ctx_t *ctx, const byte *palette) palettectx_t *pctx = calloc (1, sizeof (palettectx_t)); ctx->palette_context = pctx; - pctx->sampler = Vulkan_CreateSampler (ctx, "palette_sampler"); + pctx->sampler = QFV_Render_Sampler (ctx, "palette_sampler"); + tex_t tex = { .width = 16, .height = 16, diff --git a/libs/video/renderer/vulkan/vulkan_sprite.c b/libs/video/renderer/vulkan/vulkan_sprite.c index 3289f10d3..964920044 100644 --- a/libs/video/renderer/vulkan/vulkan_sprite.c +++ b/libs/video/renderer/vulkan/vulkan_sprite.c @@ -220,11 +220,16 @@ Vulkan_Sprite_Init (vulkan_ctx_t *ctx) spritectx_t *sctx = calloc (1, sizeof (spritectx_t)); ctx->sprite_context = sctx; - sctx->sampler = Vulkan_CreateSampler (ctx, "sprite_sampler"); - qfvPopDebug (ctx); } +void +Vulkan_Sprite_Setup (vulkan_ctx_t *ctx) +{ + auto sctx = ctx->sprite_context; + sctx->sampler = QFV_Render_Sampler (ctx, "sprite_sampler"); +} + void Vulkan_Sprite_Shutdown (vulkan_ctx_t *ctx) { From 05c17d724776c33c0262619c150aceef6d275b20 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 25 Jun 2023 23:40:28 +0900 Subject: [PATCH 3654/3664] [vulkan] Clean up the old config files --- libs/video/renderer/Makemodule.am | 28 - libs/video/renderer/vulkan/pl_output.plist | 258 ---- libs/video/renderer/vulkan/pl_quake_def.plist | 1211 ----------------- libs/video/renderer/vulkan/rp_defcube.plist | 328 ----- libs/video/renderer/vulkan/rp_deferred.plist | 317 ----- libs/video/renderer/vulkan/rp_forward.plist | 197 --- libs/video/renderer/vulkan/rp_output.plist | 47 - libs/video/renderer/vulkan/rp_shadow.plist | 50 - libs/video/renderer/vulkan/vkparse.c | 28 - 9 files changed, 2464 deletions(-) delete mode 100644 libs/video/renderer/vulkan/pl_output.plist delete mode 100644 libs/video/renderer/vulkan/pl_quake_def.plist delete mode 100644 libs/video/renderer/vulkan/rp_defcube.plist delete mode 100644 libs/video/renderer/vulkan/rp_deferred.plist delete mode 100644 libs/video/renderer/vulkan/rp_forward.plist delete mode 100644 libs/video/renderer/vulkan/rp_output.plist delete mode 100644 libs/video/renderer/vulkan/rp_shadow.plist diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index 9f5f16308..1cf860c7c 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -191,24 +191,10 @@ libs_video_renderer_librender_sw_la_SOURCES = \ libs/video/renderer/sw/transform.S \ libs/video/renderer/sw/vid_common_sw.c -pl_quake_def_src = libs/video/renderer/vulkan/pl_quake_def.plist -pl_quake_def_gen = libs/video/renderer/vulkan/pl_quake_def.plc -pl_output_src = libs/video/renderer/vulkan/pl_output.plist -pl_output_gen = libs/video/renderer/vulkan/pl_output.plc -rp_defcube_src = libs/video/renderer/vulkan/rp_defcube.plist -rp_defcube_gen = libs/video/renderer/vulkan/rp_defcube.plc -rp_deferred_src = libs/video/renderer/vulkan/rp_deferred.plist -rp_deferred_gen = libs/video/renderer/vulkan/rp_deferred.plc -rp_forward_src = libs/video/renderer/vulkan/rp_forward.plist -rp_forward_gen = libs/video/renderer/vulkan/rp_forward.plc rp_main_def_src = libs/video/renderer/vulkan/rp_main_def.plist rp_main_def_gen = libs/video/renderer/vulkan/rp_main_def.plc smp_quake_src = libs/video/renderer/vulkan/smp_quake.plist smp_quake_gen = libs/video/renderer/vulkan/smp_quake.plc -rp_output_src = libs/video/renderer/vulkan/rp_output.plist -rp_output_gen = libs/video/renderer/vulkan/rp_output.plc -rp_shadow_src = libs/video/renderer/vulkan/rp_shadow.plist -rp_shadow_gen = libs/video/renderer/vulkan/rp_shadow.plc video_renderer_vulkan_libs = \ libs/video/renderer/librender_vulkan.la \ @@ -266,15 +252,8 @@ libs_video_renderer_librender_vulkan_la_SOURCES = \ libs/video/renderer/vulkan/vkparse.lo: \ libs/video/renderer/vulkan/vkparse.c \ $(vkparse_src) \ - $(pl_quake_def_gen) \ - $(pl_output_gen) \ - ${rp_defcube_gen} \ - ${rp_deferred_gen} \ - $(rp_forward_gen) \ $(rp_main_def_gen) \ $(smp_quake_gen) - $(rp_output_gen) \ - ${rp_shadow_gen} libs/video/renderer/vulkan/shader.lo: \ libs/video/renderer/vulkan/shader.c \ @@ -529,15 +508,8 @@ BUILT_SOURCES += $(shader_gen) EXTRA_DIST += \ libs/video/renderer/vulkan/vkparse.plist \ libs/video/renderer/vulkan/vkparse.h \ - $(rp_defcube_src) \ - $(rp_deferred_src) \ - $(rp_forward_src) \ $(rp_main_def_src) \ $(smp_quake_src) \ - $(rp_output_src) \ - $(rp_shadow_src) \ - $(pl_quake_def_src) \ - $(pl_output_src) \ $(oit_blend) \ $(oit_store) \ $(oit_h) \ diff --git a/libs/video/renderer/vulkan/pl_output.plist b/libs/video/renderer/vulkan/pl_output.plist deleted file mode 100644 index a9a6198f2..000000000 --- a/libs/video/renderer/vulkan/pl_output.plist +++ /dev/null @@ -1,258 +0,0 @@ -samplers = { - linear = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 0; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; -}; -descriptorPools = { - output_pool = { - flags = 0; - maxSets = "$frames.size * 2z"; - bindings = ( - { - type = combined_image_sampler; - descriptorCount = "$frames.size * 2z"; - }, - ); - }; -}; -setLayouts = { - matrix_set = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = vertex|geometry|fragment; - }, - ); - }; - output_set = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; -}; -pipelineLayouts = { - output_layout = { - setLayouts = (matrix_set, output_set); - }; - waterwarp_layout = { - @inherit = $properties.pipelineLayouts.output_layout; - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "4"; - } - ); - }; - fisheye_layout = { - @inherit = $properties.pipelineLayouts.output_layout; - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "2 * 4"; - } - ); - }; -}; - -depthStencil = { - disable = { - depthTestEnable = false; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; -}; - -inputAssembly = { -}; - -vertexInput = { - index_only = { - bindings = (); - attributes = (); - }; -}; - -rasterization = { - cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - counter_cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; -}; - -multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; -}; - -viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); -}; - -attachmentBlendOp = { - disabled = { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; - alpha_blend = { - blendEnable = true; - srcColorBlendFactor = one; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = one; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; -}; - -fstriangle = { - vertexStage = { - stage = vertex; - name = main; - module = $builtin/fstriangle.vert; - }; - vertexStageST = { - stage = vertex; - name = main; - module = $builtin/fstrianglest.vert; - }; - vertexInput = { - bindings = (); - attributes = (); - }; - inputAssembly = { - topology = triangle_list; - primitiveRestartEnable = false; - }; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.disabled); - }; -}; - -pipelines = { - base = { - viewport = $properties.viewport; - rasterization = $properties.rasterization.counter_cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.disable; - colorBlend = { - logicOpEnable = false; - attachments = ( - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - ); - }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - renderPass = output; - }; - output_base = { - @inherit = $properties.pipelines.base; - vertexInput = $properties.fstriangle.vertexInput; - inputAssembly = $properties.fstriangle.inputAssembly; - colorBlend = $properties.fstriangle.colorBlend; - }; - output = { - @inherit = $properties.pipelines.output_base; - subpass = 0; - stages = ( - $properties.fstriangle.vertexStage, - { - stage = fragment; - name = main; - module = $builtin/output.frag; - }, - ); - layout = output_layout; - }; - waterwarp = { - @inherit = $properties.pipelines.output_base; - subpass = 0; - stages = ( - $properties.fstriangle.vertexStageST, - { - stage = fragment; - name = main; - module = $builtin/waterwarp.frag; - }, - ); - layout = waterwarp_layout; - }; - fisheye = { - @inherit = $properties.pipelines.output_base; - subpass = 0; - stages = ( - $properties.fstriangle.vertexStageST, - { - stage = fragment; - name = main; - module = $builtin/fisheye.frag; - }, - ); - layout = fisheye_layout; - }; -}; diff --git a/libs/video/renderer/vulkan/pl_quake_def.plist b/libs/video/renderer/vulkan/pl_quake_def.plist deleted file mode 100644 index be3764cc4..000000000 --- a/libs/video/renderer/vulkan/pl_quake_def.plist +++ /dev/null @@ -1,1211 +0,0 @@ -limits = { - //FIXME this really needs to be an external variable as the C code - //needs to agree on the size, so it might as well set maxSamplers - //directly (and any other such variable) - maxSamplers = "min (256u, $physDevLimits.maxPerStageDescriptorSamplers)"; -}; -samplers = { - quakepic = { - magFilter = nearest; - minFilter = nearest; - mipmapMode = nearest; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 0; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - glyph = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 0; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - palette_sampler = { - magFilter = nearest; - minFilter = nearest; - mipmapMode = nearest; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 4; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - quakebsp_sampler = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = repeat; - addressModeV = repeat; - addressModeW = repeat; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 4; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - alias_sampler = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = false; - compareOp = always; - minLod = 0; - maxLod = 1000; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; - sprite_sampler = $properties.samplers.alias_sampler; - shadow_sampler = { - magFilter = linear; - minFilter = linear; - mipmapMode = linear; - addressModeU = clamp_to_edge; - addressModeV = clamp_to_edge; - addressModeW = clamp_to_edge; - mipLodBias = 0; - anisotropyEnable = false; - maxAnisotropy = 0; - compareEnable = true; - compareOp = greater_or_equal; - minLod = 0; - maxLod = 1000; - borderColor = float_transparent_black; - unnormalizedCoordinates = false; - }; -}; -descriptorPools = { - matrix_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = uniform_buffer; - descriptorCount = $frames.size; - }, - ); - }; - quad_pool = { - maxSets = 64; - bindings = ( - { - // quad geometry data (offset and uv) - type = uniform_texel_buffer; - descriptorCount = 64; - }, - { - // quad texture data - type = combined_image_sampler; - descriptorCount = 64; - }, - ); - }; - entity_pool = { - flags = free_descriptor_set; - maxSets = 512; - bindings = ( - { - type = storage_buffer; - descriptorCount = $properties.descriptorPools.entity_pool.maxSets; - }, - ); - }; - bone_pool = { - flags = free_descriptor_set; - maxSets = 512; - bindings = ( - { - type = storage_buffer; - descriptorCount = $properties.descriptorPools.bone_pool.maxSets; - }, - ); - }; - texture_pool = { - flags = free_descriptor_set; - maxSets = 1024; - bindings = ( - { - type = combined_image_sampler; - descriptorCount = $properties.descriptorPools.texture_pool.maxSets; - }, - ); - }; - particle_pool = { - flags = 0; - maxSets = "3z * $frames.size"; - bindings = ( - { - type = storage_buffer; - descriptorCount = "3z * 3z * $frames.size"; - }, - ); - }; - sprite_pool = { - flags = free_descriptor_set; - maxSets = 64; //FIXME cvar? - bindings = ( - { - type = uniform_buffer; - descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; - }, - { - type = combined_image_sampler; - descriptorCount = $properties.descriptorPools.sprite_pool.maxSets; - }, - ); - }; - //FIXME probably should just share a larger pool - alias_pool = $properties.descriptorPools.texture_pool; - quakebsp_pool = $properties.descriptorPools.texture_pool; - lighting_attach_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = input_attachment; - descriptorCount = "5z * $frames.size"; - }, - ); - }; - lighting_lights_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = uniform_buffer; - descriptorCount = $frames.size; - }, - ); - }; - lighting_shadow_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = combined_image_sampler; - descriptorCount = "$frames.size * size_t(32)"; - }, - ); - }; - oit_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = storage_buffer; - descriptorCount = "2z * $frames.size"; - }, - { - type = storage_image; - descriptorCount = "1z * $frames.size"; - }, - ); - }; - compose_attach_pool = { - flags = 0; - maxSets = $frames.size; - bindings = ( - { - type = input_attachment; - descriptorCount = "2z * $frames.size"; - }, - ); - }; -}; -setLayouts = { - matrix_set = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = vertex|geometry|fragment; - }, - ); - }; - quad_data_set = { - bindings = ( - { - // glyph texture data - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - { - // glyph geometry data (offset and uv) - binding = 1; - descriptorType = uniform_texel_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, - ); - }; - texture_set = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment|vertex; - }, - ); - }; - oit_set = { - bindings = ( - { - binding = 0; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 1; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 2; - descriptorType = storage_image; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - entity_set = { - bindings = ( - { - binding = 0; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, - ); - }; - bone_set = { - bindings = ( - { - binding = 0; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, - ); - }; - sprite_set = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = vertex; - }, - { - binding = 1; - descriptorType = combined_image_sampler; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - lighting_attach = { - bindings = ( - { - binding = 0; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 1; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 2; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 3; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - { - binding = 4; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - lighting_lights = { - bindings = ( - { - binding = 0; - descriptorType = uniform_buffer; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - lighting_shadow = { - bindings = ( - { - binding = 0; - descriptorType = combined_image_sampler; - descriptorCount = 32; - stageFlags = fragment; - }, - ); - }; - compose_attach = { - bindings = ( - { - binding = 0; - descriptorType = input_attachment; - descriptorCount = 1; - stageFlags = fragment; - }, - ); - }; - particle_set = { - bindings = ( - { - binding = 0; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = compute; - }, - { - binding = 1; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = compute; - }, - { - binding = 2; - descriptorType = storage_buffer; - descriptorCount = 1; - stageFlags = compute; - }, - ); - }; -}; -pipelineLayouts = { - quad_layout = { - setLayouts = (matrix_set, quad_data_set); - }; - lines_layout = { - setLayouts = (matrix_set); - }; - quakebsp_layout = { - setLayouts = (matrix_set, entity_set, oit_set, texture_set, texture_set); - pushConstantRanges = ( - { - stageFlags = fragment; - offset = 0; - size = "4 * 4 + 4 + 4 + 4"; - }, - ); - }; - alias_layout = { - setLayouts = (matrix_set, texture_set, texture_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 68; - size = "3 * 4 + 2 * 4 * 4"; - }, - ); - }; - iqm_layout = { - setLayouts = (matrix_set, texture_set, bone_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 68; - size = "3 * 4 + 2 * 4 * 4"; - }, - ); - }; - sprite_layout = { - setLayouts = (matrix_set, sprite_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4 + 4"; - }, - { - stageFlags = fragment; - offset = 64; - size = "2 * 4 + 2 * 4 + 4 * 4"; - }, - ); - }; - lighting_layout = { - setLayouts = (lighting_attach, lighting_lights, lighting_shadow); - }; - compose_layout = { - setLayouts = (compose_attach, oit_set); - }; - partphysics_layout = { - setLayouts = (particle_set); - pushConstantRanges = ( - { - stageFlags = compute; - offset = 0; - size = "4 * 4 + 4"; - }, - ); - }; - partupdate_layout = { - setLayouts = (particle_set, particle_set, particle_set); - }; - partdraw_layout = { - setLayouts = (matrix_set, texture_set, oit_set); - pushConstantRanges = ( - { - stageFlags = vertex; - offset = 0; - size = "16 * 4"; - }, - ); - }; -}; - -depthStencil = { - test_and_write = { - depthTestEnable = true; - depthWriteEnable = true; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - test_only = { - depthTestEnable = true; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; - disable = { - depthTestEnable = false; - depthWriteEnable = false; - depthCompareOp = less_or_equal; - depthBoundsTestEnable = false; - stencilTestEnable = false; - }; -}; - -inputAssembly = { - alias = { - topology = triangle_list; - primitiveRestartEnable = false; - }; - brush = { - topology = triangle_fan; - primitiveRestartEnable = true; - }; - iqm = { - topology = triangle_list; - primitiveRestartEnable = false; - }; - lines = { - topology = line_list; - primitiveRestartEnable = false; - }; - sprite = { - topology = triangle_strip; - primitiveRestartEnable = true; - }; - point = { - topology = point_list; - primitiveRestartEnable = false; - }; -}; - -vertexInput = { - index_only = { - bindings = (); - attributes = (); - }; - alias = { - bindings = ( - { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, - { binding = 1; stride = "2 * 4 * 4"; inputRate = vertex; }, - { binding = 2; stride = "2 * 4"; inputRate = vertex; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, - { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 2; binding = 1; format = r32g32b32a32_sfloat; offset = 0; }, - { location = 3; binding = 1; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 4; binding = 2; format = r32g32_sfloat; offset = 0; }, - ); - }; - brush = { - bindings = ( - { binding = 0; stride = "2 * 4 * 4"; inputRate = vertex; }, - { binding = 1; stride = "4"; inputRate = instance; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, - { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 2; binding = 1; format = r32_uint; offset = 0; }, - ); - }; - slice = { - bindings = ( - { binding = 0; stride = "4 + 4 + 4 * 4"; inputRate = instance; }, - ); - attributes = ( - // 9-slice index - { location = 0; binding = 0; format = r32_uint; offset = 0; }, - // 9-slice color - { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, - // 9-slice position (2d) - { location = 2; binding = 0; format = r32g32_sfloat; offset = 8; }, - // 9-slice size delta (2d) - { location = 3; binding = 0; format = r32g32_sfloat; offset = 16; }, - ); - }; - glyph = { - bindings = ( - { binding = 0; stride = "4 + 4 + 2 * 4"; inputRate = instance; }, - ); - attributes = ( - // glyph index - { location = 0; binding = 0; format = r32_uint; offset = 0; }, - // glyph color - { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; }, - // glyph position (2d) - { location = 2; binding = 0; format = r32g32_sfloat; offset = 8; }, - ); - }; - iqm = { - bindings = ( - { binding = 0; stride = 20; inputRate = vertex; }, - { binding = 1; stride = 40; inputRate = vertex; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32_sfloat; offset = 0; }, // position - { location = 1; binding = 0; format = r8g8b8a8_uint; offset = 12; }, // bonindices - { location = 2; binding = 0; format = r8g8b8a8_unorm; offset = 16; }, // boneweights - - { location = 3; binding = 1; format = r32g32_sfloat; offset = 0; }, // texcoord - { location = 4; binding = 1; format = r32g32b32_sfloat; offset = 8; }, // normal - { location = 5; binding = 1; format = r32g32b32a32_sfloat; offset = 20; }, // tangent - { location = 6; binding = 1; format = r8g8b8a8_unorm; offset = 36; }, // color - - ); - }; - particle = { - bindings = ( - { binding = 0; stride = "4 * 4 * 4"; inputRate = instance; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32b32a32_sfloat; offset = 0; }, - { location = 1; binding = 0; format = r32g32b32a32_sfloat; offset = 16; }, - { location = 2; binding = 0; format = r32g32b32a32_sfloat; offset = 32; }, - { location = 3; binding = 0; format = r32g32b32a32_sfloat; offset = 48; }, - ); - }; - lines = { - bindings = ( - { binding = 0; stride = "2 * 4 + 4"; inputRate = vertex; }, - ); - attributes = ( - { location = 0; binding = 0; format = r32g32_sfloat; offset = 0; }, - { location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 8; }, - ); - }; -}; - -rasterization = { - cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; - counter_cw_cull_back = { - depthClampEnable = false; - rasterizerDiscardEnable = false; - polygonMode = fill; - cullMode = back; - frontFace = counter_clockwise; - depthBiasEnable = false; - lineWidth = 1; - }; -}; - -multisample = { - rasterizationSamples = $msaaSamples; - sampleShadingEnable = false; - minSampleShading = 0.5f; - alphaToCoverageEnable = false; - alphaToOneEnable = false; -}; - -viewport = { - viewports = ( - { - x = 0; y = 0; - width = 640; height = 480; - minDepth = 0; maxDepth = 1; - } - ); - scissors = ( - { - offset = { x = 0; y = 0 }; - extent = { width = 640; height = 480; }; - }, - ); -}; - -attachmentBlendOp = { - disabled = { - blendEnable = false; - srcColorBlendFactor = src_alpha; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = src_alpha; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; - alpha_blend = { - blendEnable = true; - srcColorBlendFactor = one; - dstColorBlendFactor = one_minus_src_alpha; - colorBlendOp = add; - srcAlphaBlendFactor = one; - dstAlphaBlendFactor = one_minus_src_alpha; - alphaBlendOp = add; - colorWriteMask = r|g|b|a; - }; -}; - -fstriangle = { - vertexStage = { - stage = vertex; - name = main; - module = $builtin/fstriangle.vert; - }; - vertexInput = { - bindings = (); - attributes = (); - }; - inputAssembly = { - topology = triangle_list; - primitiveRestartEnable = false; - }; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.disabled); - }; -}; - -pipelines = { - base = { - viewport = $properties.viewport; - rasterization = $properties.rasterization.counter_cw_cull_back; - multisample = $properties.multisample; - depthStencil = $properties.depthStencil.disable; - colorBlend = { - logicOpEnable = false; - attachments = ( - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - $properties.attachmentBlendOp.disabled, - ); - }; - dynamic = { - dynamicState = ( viewport, scissor ); - }; - renderPass = deferred; - }; - depth_base = { - @inherit = $properties.pipelines.base; - subpass = 0; - rasterization = $properties.rasterization.cw_cull_back; - depthStencil = $properties.depthStencil.test_and_write; - }; - trans_base = { - @inherit = $properties.pipelines.base; - subpass = 1; - rasterization = $properties.rasterization.cw_cull_back; - depthStencil = $properties.depthStencil.test_only; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.disabled); - }; - }; - gbuf_base = { - @inherit = $properties.pipelines.base; - subpass = 2; - rasterization = $properties.rasterization.cw_cull_back; - depthStencil = $properties.depthStencil.test_only; - }; - comp_base = { - @inherit = $properties.pipelines.base; - vertexInput = $properties.fstriangle.vertexInput; - inputAssembly = $properties.fstriangle.inputAssembly; - colorBlend = $properties.fstriangle.colorBlend; - }; - shadow_base = { - @inherit = $properties.pipelines.depth_base; - renderPass = shadow; - }; - - alias_shadow = { - @inherit = $properties.pipelines.shadow_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/alias_shadow.vert; - }, - ); - vertexInput = { - bindings = ( - "$properties.vertexInput.alias.bindings[0]", - "$properties.vertexInput.alias.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.alias.attributes[0]", - "$properties.vertexInput.alias.attributes[1]", - "$properties.vertexInput.alias.attributes[2]", - "$properties.vertexInput.alias.attributes[3]", - ); - }; - inputAssembly = $properties.inputAssembly.alias; - layout = alias_layout; - }; - bsp_shadow = { - @inherit = $properties.pipelines.shadow_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/bsp_shadow.vert; - }, - ); - vertexInput = { - bindings = ( - "$properties.vertexInput.brush.bindings[0]", - ); - attributes = ( - "$properties.vertexInput.brush.attributes[0]", - ); - }; - inputAssembly = $properties.inputAssembly.brush; - }; - alias_depth = { - @inherit = $properties.pipelines.depth_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/alias_depth.vert; - }, - ); - vertexInput = { - // depth pass doesn't use UVs - bindings = ( - "$properties.vertexInput.alias.bindings[0]", - "$properties.vertexInput.alias.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.alias.attributes[0]", - "$properties.vertexInput.alias.attributes[1]", - "$properties.vertexInput.alias.attributes[2]", - "$properties.vertexInput.alias.attributes[3]", - ); - }; - inputAssembly = $properties.inputAssembly.alias; - layout = alias_layout; - }; - alias_gbuf = { - @inherit = $properties.pipelines.gbuf_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/alias.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/alias_gbuf.frag; - }, - ); - vertexInput = $properties.vertexInput.alias; - inputAssembly = $properties.inputAssembly.alias; - layout = alias_layout; - }; - bsp_depth = { - @inherit = $properties.pipelines.depth_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/bsp_depth.vert; - }, - ); - vertexInput = { - bindings = ( - "$properties.vertexInput.brush.bindings[0]", - "$properties.vertexInput.brush.bindings[1]", - ); - attributes = ( - "$properties.vertexInput.brush.attributes[0]", - "$properties.vertexInput.brush.attributes[2]", - ); - }; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - bsp_gbuf = { - @inherit = $properties.pipelines.gbuf_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/bsp_gbuf.vert; - }, - { - stage = geometry; - name = main; - module = $builtin/bsp_gbuf.geom; - }, - { - stage = fragment; - name = main; - module = $builtin/bsp_gbuf.frag; - }, - ); - vertexInput = $properties.vertexInput.brush; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - bsp_skybox = { - @inherit = $properties.pipelines.trans_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/quakebsp.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/bsp_sky.frag; - specializationInfo = { - mapEntries = ( - // doSkyBox - { size = 4; offset = 0; constantID = 0; }, - // doSkySheet - { size = 4; offset = 4; constantID = 1; }, - ); - data = "array(1, 0)"; - }; - }, - ); - vertexInput = $properties.vertexInput.brush; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - bsp_skysheet = { - @inherit = $properties.pipelines.trans_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/quakebsp.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/bsp_sky.frag; - specializationInfo = { - mapEntries = ( - // doSkyBox - { size = 4; offset = 0; constantID = 0; }, - // doSkySheet - { size = 4; offset = 4; constantID = 1; }, - ); - data = "array(0, 1)"; - }; - }, - ); - vertexInput = $properties.vertexInput.brush; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - bsp_turb = { - @inherit = $properties.pipelines.trans_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/quakebsp.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/bsp_turb.frag; - }, - ); - vertexInput = $properties.vertexInput.brush; - inputAssembly = $properties.inputAssembly.brush; - layout = quakebsp_layout; - }; - iqm_depth = { - @inherit = $properties.pipelines.depth_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm.vert; - specializationInfo = { - mapEntries = ( - // IQMDepthOnly - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(1)"; - }; - }, - ); - vertexInput = $properties.vertexInput.iqm; - inputAssembly = $properties.inputAssembly.iqm; - layout = iqm_layout; - }; - iqm_gbuf = { - @inherit = $properties.pipelines.gbuf_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/iqm.vert; - specializationInfo = { - mapEntries = ( - // !IQMDepthOnly - { size = 4; offset = 0; constantID = 0; }, - ); - data = "array(0)"; - }; - }, - { - stage = fragment; - name = main; - module = $builtin/iqm.frag; - }, - ); - vertexInput = $properties.vertexInput.iqm; - inputAssembly = $properties.inputAssembly.iqm; - layout = iqm_layout; - }; - partdraw = { - @inherit = $properties.pipelines.trans_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/particle.vert; - }, - { - stage = geometry; - name = main; - module = $builtin/particle.geom; - }, - { - stage = fragment; - name = main; - module = $builtin/particle.frag; - }, - ); - vertexInput = $properties.vertexInput.particle; - inputAssembly = $properties.inputAssembly.point; - layout = partdraw_layout; - }; - sprite_gbuf = { - @inherit = $properties.pipelines.gbuf_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/sprite_gbuf.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/sprite_gbuf.frag; - }, - ); - vertexInput = $properties.vertexInput.index_only; - inputAssembly = $properties.inputAssembly.sprite; - layout = sprite_layout; - }; - sprite_depth = { - @inherit = $properties.pipelines.depth_base; - stages = ( - { - stage = vertex; - name = main; - module = $builtin/sprite_depth.vert; - }, - { - stage = fragment; - name = main; - module = $builtin/sprite_depth.frag; - }, - ); - vertexInput = $properties.vertexInput.index_only; - inputAssembly = $properties.inputAssembly.sprite; - layout = sprite_layout; - }; - slice = { - @inherit = $properties.pipelines.trans_base; - renderPass = output; - subpass = 0; - stages = ( - { stage = vertex; name = main; module = $builtin/slice.vert; }, - { stage = fragment; name = main; module = $builtin/twod.frag; }, - ); - vertexInput = $properties.vertexInput.slice; - inputAssembly = { - // slices are drawn using instanced slice triples - topology = triangle_strip; - primitiveRestartEnable = true; - }; - rasterization = $properties.rasterization.counter_cw_cull_back; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.alpha_blend); - }; - layout = quad_layout; - }; - lines = { - @inherit = $properties.pipelines.trans_base; - renderPass = output; - subpass = 0; - stages = ( - { stage = vertex; name = main; module = $builtin/line.vert; }, - { stage = fragment; name = main; module = $builtin/line.frag; }, - ); - vertexInput = $properties.vertexInput.lines; - rasterization = $properties.rasterization.counter_cw_cull_back; - depthStencil = $properties.depthStencil.disable; - colorBlend = { - logicOpEnable = false; - attachments = ($properties.attachmentBlendOp.alpha_blend); - }; - inputAssembly = $properties.inputAssembly.lines; - layout = lines_layout; - }; - lighting = { - @inherit = $properties.pipelines.comp_base; - subpass = 3; - stages = ( - $properties.fstriangle.vertexStage, - { - stage = fragment; - name = main; - module = $builtin/lighting.frag; - //specializationInfo = { - // mapEntries = ( - // { size = 4; offset = 0; constantID = 0; }, - // ); - // data = "array(uint($properties.limits.maxSamplers))"; - //}; - }, - ); - layout = lighting_layout; - }; - compose = { - @inherit = $properties.pipelines.comp_base; - subpass = 4; - stages = ( - $properties.fstriangle.vertexStage, - { - stage = fragment; - name = main; - module = $builtin/compose.frag; - }, - ); - layout = compose_layout; - }; - - partphysics = { - stage = { - stage = compute; - name = main; - module = $builtin/partphysics.comp; - }; - layout = partphysics_layout; - }; - partupdate = { - stage = { - stage = compute; - name = main; - module = $builtin/partupdate.comp; - }; - layout = partupdate_layout; - }; -}; diff --git a/libs/video/renderer/vulkan/rp_defcube.plist b/libs/video/renderer/vulkan/rp_defcube.plist deleted file mode 100644 index 3a4cd1089..000000000 --- a/libs/video/renderer/vulkan/rp_defcube.plist +++ /dev/null @@ -1,328 +0,0 @@ -flat_color_image_template = { - imageType = `2d; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 6; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; -}; -images = { - depth = { - @inherit = $properties.flat_color_image_template; - format = x8_d24_unorm_pack32; - usage = depth_stencil_attachment|input_attachment|transient_attachment; - }; - color = { - @inherit = $properties.flat_color_image_template; - format = r8g8b8a8_unorm; - }; - emission = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - normal = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - position = { - @inherit = $properties.flat_color_image_template; - format = r32g32b32a32_sfloat; - }; - opaque = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; -}; -flat_color_view_template = { - viewType = `2d_array; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 6; - }; -}; -imageViews = { - depth = { - @inherit = $properties.flat_color_view_template; - image = depth; - format = $properties.images.depth.format; - subresourceRange = { - aspectMask = depth; - }; - }; - color = { - @inherit = $properties.flat_color_view_template; - image = color; - format = $properties.images.color.format; - }; - emission = { - @inherit = $properties.flat_color_view_template; - image = emission; - format = $properties.images.emission.format; - }; - normal = { - @inherit = $properties.flat_color_view_template; - image = normal; - format = $properties.images.normal.format; - }; - position = { - @inherit = $properties.flat_color_view_template; - image = position; - format = $properties.images.position.format; - }; - opaque = { - @inherit = $properties.flat_color_view_template; - image = opaque; - format = $properties.images.opaque.format; - }; - aview = { - @inherit = $properties.flat_color_view_template; - image = $output.image; - format = $output.format; - }; -}; -output = { - image = { - @inherit = $properties.flat_color_image_template; - flags = cube_compatible; - usage = color_attachment|input_attachment|sampled; - format = $output.format; - }; - view = { - @inherit = $properties.flat_color_view_template; - viewType = cube; - image = $output.image; - format = $output.format; - }; - format = r16g16b16a16_sfloat; - finalLayout = shader_read_only_optimal; -}; -framebuffer = { - renderPass = defcube; - attachments = (depth, color, emission, normal, position, opaque, - $properties.imageViews.aview); - width = $output.extent.width; - height = $output.extent.height; - layers = 1; -}; -clearValues = ( - { depthStencil = { depth = 1; stencil = 0; }; }, - { color = "[0, 0, 0, 1]"; }, // color - { color = "[0, 0, 0, 1]"; }, // emission - { color = "[0, 0, 0, 1]"; }, // normal - { color = "[0, 0, 0, 1]"; }, // position - { color = "[0, 0, 0, 1]"; }, // opaque - { color = "[0, 0, 0, 1]"; }, // output -); -attachment_template = { - samples = 1; - loadOp = dont_care; - storeOp = store; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; -}; -info = { - color = "[0, 1, 0, 1]"; - subpass_info = ( - { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, - { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, - { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, - { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, - { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, - ); -}; -renderpass = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $properties.images.depth.format; - loadOp = clear; - finalLayout = depth_stencil_attachment_optimal; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.color.format; - loadOp = clear; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.emission.format; - loadOp = clear; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.normal.format; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.position.format; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.opaque.format; - }, - { - @inherit = $properties.attachment_template; - format = $output.format; - loadOp = clear; - storeOp = store; - finalLayout = $output.finalLayout; - }, - ); - subpasses = ( - { // 0 depth - pipelineBindPoint = graphics; - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_attachment_optimal; - }; - }, - { // 1 translucent-frags - pipelineBindPoint = graphics; - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_read_only_optimal; - }; - preserveAttachments = (1, 2, 3, 4, 5); - }, - { // 2 g-buffer generation - pipelineBindPoint = graphics; - colorAttachments = ( - { // color - attachment = 1; - layout = color_attachment_optimal; - }, - { // emission - attachment = 2; - layout = color_attachment_optimal; - }, - { // normal - attachment = 3; - layout = color_attachment_optimal; - }, - { // position - attachment = 4; - layout = color_attachment_optimal; - }, - ); - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_read_only_optimal; - }; - preserveAttachments = (6); - }, - { // 3 lighting - pipelineBindPoint = graphics; - inputAttachments = ( - { // depth - attachment = 0; - layout = shader_read_only_optimal; - }, - { // color - attachment = 1; - layout = shader_read_only_optimal; - }, - { // emission - attachment = 2; - layout = shader_read_only_optimal; - }, - { // normal - attachment = 3; - layout = shader_read_only_optimal; - }, - { // position - attachment = 4; - layout = shader_read_only_optimal; - }, - ); - colorAttachments = ( - { // opaque - attachment = 5; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (6); - }, - { // 4 compose - pipelineBindPoint = graphics; - inputAttachments = ( - { // opaque - attachment = 5; - layout = shader_read_only_optimal; - }, - ); - colorAttachments = ( - { // output - attachment = 6; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (0, 1, 2, 3, 4); - }, - ); - dependencies = ( - { - srcSubpass = 0; // depth - dstSubpass = 1; // translucent - srcStageMask = late_fragment_tests; - dstStageMask = fragment_shader|early_fragment_tests; - srcAccessMask = depth_stencil_attachment_write; - dstAccessMask = input_attachment_read|depth_stencil_attachment_read; - dependencyFlags = by_region|view_local; - }, - { - srcSubpass = 0; // depth - dstSubpass = 2; // g-buffer - srcStageMask = late_fragment_tests; - dstStageMask = early_fragment_tests; - srcAccessMask = depth_stencil_attachment_write; - dstAccessMask = depth_stencil_attachment_read; - dependencyFlags = by_region|view_local; - }, - { - srcSubpass = 2; // g-buffer - dstSubpass = 3; // lighting - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region|view_local; - }, - { - srcSubpass = 3; // lighting - dstSubpass = 4; // compose - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region|view_local; - }, - { - srcSubpass = 1; // translucent-frags - dstSubpass = 4; // translucent-final/compose - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region|view_local; - }, - ); - @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); - viewOffsets = ( 0, 0, 0, 0, 0); - }); -}; diff --git a/libs/video/renderer/vulkan/rp_deferred.plist b/libs/video/renderer/vulkan/rp_deferred.plist deleted file mode 100644 index 9fb3845de..000000000 --- a/libs/video/renderer/vulkan/rp_deferred.plist +++ /dev/null @@ -1,317 +0,0 @@ -flat_color_image_template = { - imageType = `2d; - samples = 1; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|input_attachment|transient_attachment; - initialLayout = undefined; -}; -images = { - depth = { - @inherit = $properties.flat_color_image_template; - format = x8_d24_unorm_pack32; - usage = depth_stencil_attachment|input_attachment|transient_attachment; - }; - color = { - @inherit = $properties.flat_color_image_template; - format = r8g8b8a8_unorm; - }; - emission = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - normal = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; - position = { - @inherit = $properties.flat_color_image_template; - format = r32g32b32a32_sfloat; - }; - opaque = { - @inherit = $properties.flat_color_image_template; - format = r16g16b16a16_sfloat; - }; -}; -flat_color_view_template = { - viewType = VK_IMAGE_VIEW_TYPE_2D; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; -}; -imageViews = { - depth = { - @inherit = $properties.flat_color_view_template; - image = depth; - format = $properties.images.depth.format; - subresourceRange = { - aspectMask = depth; - }; - }; - color = { - @inherit = $properties.flat_color_view_template; - image = color; - format = $properties.images.color.format; - }; - emission = { - @inherit = $properties.flat_color_view_template; - image = emission; - format = $properties.images.emission.format; - }; - normal = { - @inherit = $properties.flat_color_view_template; - image = normal; - format = $properties.images.normal.format; - }; - position = { - @inherit = $properties.flat_color_view_template; - image = position; - format = $properties.images.position.format; - }; - opaque = { - @inherit = $properties.flat_color_view_template; - image = opaque; - format = $properties.images.opaque.format; - }; -}; -output = { - image = { - @inherit = $properties.flat_color_image_template; - usage = color_attachment|input_attachment|sampled; - format = $output.format; - }; - view = { - @inherit = $properties.flat_color_view_template; - image = $output.image; - format = $output.format; - }; - format = r16g16b16a16_sfloat; - finalLayout = shader_read_only_optimal; -}; -framebuffer = { - renderPass = deferred; - attachments = (depth, color, emission, normal, position, opaque, - $output.view); - width = $output.extent.width; - height = $output.extent.height; - layers = 1; -}; -clearValues = ( - { depthStencil = { depth = 1; stencil = 0; }; }, - { color = "[0, 0, 0, 1]"; }, // color - { color = "[0, 0, 0, 1]"; }, // emission - { color = "[0, 0, 0, 1]"; }, // normal - { color = "[0, 0, 0, 1]"; }, // position - { color = "[0, 0, 0, 1]"; }, // opaque - { color = "[0, 0, 0, 1]"; }, // output -); -attachment_template = { - samples = 1; - loadOp = dont_care; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; -}; -info = { - color = "[0, 1, 0, 1]"; - subpass_info = ( - { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, - { name = translucent; color = "[ 0.25, 0.25, 0.6, 1]" }, - { name = g-buffef; color = "[ 0.3, 0.7, 0.3, 1]" }, - { name = lighting; color = "[ 0.8, 0.8, 0.8, 1]" }, - { name = compose; color = "[ 0.7, 0.3, 0.3, 1]" }, - ); -}; -renderpass = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $properties.images.depth.format; - loadOp = clear; - finalLayout = depth_stencil_attachment_optimal; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.color.format; - loadOp = clear; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.emission.format; - loadOp = clear; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.normal.format; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.position.format; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.opaque.format; - }, - { - @inherit = $properties.attachment_template; - format = $output.format; - loadOp = clear; - storeOp = store; - finalLayout = $output.finalLayout; - }, - ); - subpasses = ( - { // 0 depth - pipelineBindPoint = graphics; - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_attachment_optimal; - }; - }, - { // 1 translucent-frags - pipelineBindPoint = graphics; - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_read_only_optimal; - }; - preserveAttachments = (1, 2, 3, 4, 5); - }, - { // 2 g-buffer generation - pipelineBindPoint = graphics; - colorAttachments = ( - { // color - attachment = 1; - layout = color_attachment_optimal; - }, - { // emission - attachment = 2; - layout = color_attachment_optimal; - }, - { // normal - attachment = 3; - layout = color_attachment_optimal; - }, - { // position - attachment = 4; - layout = color_attachment_optimal; - }, - ); - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_read_only_optimal; - }; - preserveAttachments = (6); - }, - { // 3 lighting - pipelineBindPoint = graphics; - inputAttachments = ( - { // depth - attachment = 0; - layout = shader_read_only_optimal; - }, - { // color - attachment = 1; - layout = shader_read_only_optimal; - }, - { // emission - attachment = 2; - layout = shader_read_only_optimal; - }, - { // normal - attachment = 3; - layout = shader_read_only_optimal; - }, - { // position - attachment = 4; - layout = shader_read_only_optimal; - }, - ); - colorAttachments = ( - { // opaque - attachment = 5; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (6); - }, - { // 4 compose - pipelineBindPoint = graphics; - inputAttachments = ( - { // opaque - attachment = 5; - layout = shader_read_only_optimal; - }, - ); - colorAttachments = ( - { // output - attachment = 6; - layout = color_attachment_optimal; - }, - ); - preserveAttachments = (0, 1, 2, 3, 4); - }, - ); - dependencies = ( - { - srcSubpass = 0; // depth - dstSubpass = 1; // translucent - srcStageMask = late_fragment_tests; - dstStageMask = fragment_shader|early_fragment_tests; - srcAccessMask = depth_stencil_attachment_write; - dstAccessMask = input_attachment_read|depth_stencil_attachment_read; - dependencyFlags = by_region; - }, - { - srcSubpass = 0; // depth - dstSubpass = 2; // g-buffer - srcStageMask = late_fragment_tests; - dstStageMask = early_fragment_tests; - srcAccessMask = depth_stencil_attachment_write; - dstAccessMask = depth_stencil_attachment_read; - dependencyFlags = by_region; - }, - { - srcSubpass = 2; // g-buffer - dstSubpass = 3; // lighting - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region; - }, - { - srcSubpass = 3; // lighting - dstSubpass = 4; // compose - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region; - }, - { - srcSubpass = 1; // translucent-frags - dstSubpass = 4; // translucent-final/compose - srcStageMask = color_attachment_output; - dstStageMask = fragment_shader; - srcAccessMask = color_attachment_write; - dstAccessMask = input_attachment_read; - dependencyFlags = by_region; - }, - ); -}; diff --git a/libs/video/renderer/vulkan/rp_forward.plist b/libs/video/renderer/vulkan/rp_forward.plist deleted file mode 100644 index 0e7366801..000000000 --- a/libs/video/renderer/vulkan/rp_forward.plist +++ /dev/null @@ -1,197 +0,0 @@ -flat_color_image_template = { - imageType = `2d; - samples = $msaaSamples; - extent = { - width = $output.extent.width; - height = $output.extent.height; - depth = 1; - }; - mipLevels = 1; - arrayLayers = 1; - tiling = optimal; - usage = color_attachment|transient_attachment; -}; -images = { - depth = { - @inherit = @properties.flat_color_image_template; - format = x8_d24_unorm_pack32; - usage = depth_stencil_attachment|transient_attachment; - }; - color = { - @inherit = @properties.flat_color_image_template; - format = $output.format; - }; -}; -flat_color_view_template = { - viewType = `2d; - components = { - r = identity; - g = identity; - b = identity; - a = identity; - }; - subresourceRange = { - aspectMask = color; - levelCount = 1; - layerCount = 1; - }; -}; -imageViews = { - depth = { - @inherit = $properties.flat_color_view_template; - image = depth; - format = $properties.images.depth.format; - subresourceRange = { - aspectMask = depth; - }; - }; - color = { - @inherit = $properties.flat_color_view_template; - image = color; - format = $properties.images.color.format; - }; -}; -framebuffer = { - renderPass = $properties.renderpass; - attachment = ($output.view, depth); - width = $output.extent.width; - height = $output.extent.height; - layers = 1; -}; -framebuffer_msaa = { - renderPass = $properties.renderpass_msaa; - attachment = ($output.view, depth, color); - width = $output.extent.width; - height = $output.extent.height; - layers = 1; -}; -attachment_template = { - samples = 1; - loadOp = dont_care; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; -}; -renderpass = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $output.format; - loadOp = clear; - storeOp = store; - finalLayout = present_src_khr; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.depth.format; - loadOp = clear; - finalLayout = depth_stencil_attachment_optimal; - }, - ); - subpasses = ( - { - pipelineBindPoint = graphics; - colorAttachments = ( - { - attachment = 0; - layout = color_attachment_optimal; - } - ); - depthStencilAttachment = { - attachment = 1; - layout = depth_stencil_attachment_optimal; - }; - preserveAttachments = (); - }, - ); - dependencies = ( - { - srcSubpass = ~0u; // external - dstSubpass = 0; - srcStageMask = top_of_pipe; - dstStageMask = color_attachment_output; - srcAccessMask = memory_read; - dstAccessMask = color_attachment_write; - dependencyFlags = by_region; - }, - { - srcSubpass = 0; - dstSubpass = ~0u; // external - srcStageMask = color_attachment_output; - dstStageMask = bottom_of_pipe; - srcAccessMask = color_attachment_write; - dstAccessMask = memory_read; - dependencyFlags = by_region; - }, - ); -}; -renderpass_msaa = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $output.format; - storeOp = store; - finalLayout = present_src_khr; - }, - { - @inherit = $properties.attachment_template; - format = $properties.images.depth.format; - samples = $msaaSamples; - loadOp = clear; - storeOp = dont_care; - finalLayout = depth_stencil_attachment_optimal; - }, - { - @inherit = $properties.attachment_template; - format = $swapchain.format; - samples = $msaaSamples; - loadOp = clear; - storeOp = store;// dont_care? - finalLayout = color_attachment_optimal; - }, - ); - subpasses = ( - { - pipelineBindPoint = graphics; - colorAttachments = ( - { - attachment = 2; - layout = color_attachment_optimal; - } - ); - resolveAttachments = ( - { - attachment = 0; - layout = color_attachment_optimal; - } - ); - depthStencilAttachment = { - attachment = 1; - layout = depth_stencil_attachment_optimal; - }; - preserveAttachments = (); - }, - ); - dependencies = ( - { - srcSubpass = ~0u; // external - dstSubpass = 0; - srcStageMask = top_of_pipe; - dstStageMask = color_attachment_output; - srcAccessMask = memory_read; - dstAccessMask = color_attachment_write; - dependencyFlags = by_region; - }, - { - srcSubpass = 0; - dstSubpass = ~0u; // external - srcStageMask = color_attachment_output; - dstStageMask = bottom_of_pipe; - srcAccessMask = color_attachment_write; - dstAccessMask = memory_read; - dependencyFlags = by_region; - }, - ); -}; diff --git a/libs/video/renderer/vulkan/rp_output.plist b/libs/video/renderer/vulkan/rp_output.plist deleted file mode 100644 index 86e27a6f3..000000000 --- a/libs/video/renderer/vulkan/rp_output.plist +++ /dev/null @@ -1,47 +0,0 @@ -framebuffer = { - renderPass = output; - attachments = ($output.view); - width = $output.extent.width; - height = $output.extent.height; - layers = 1; -}; -clearValues = ( - { color = "[0, 0, 0, 1]"; }, // output -); -attachment_template = { - samples = 1; - loadOp = dont_care; - storeOp = dont_care; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = color_attachment_optimal; -}; -info = { - color = "[0.9, 0.9, 0.9, 1]"; - subpass_info = ( - { name = compose; color = "[ 0.9, 0.9, 0.9, 1]" }, - ); -}; -renderpass = { - attachments = ( - { - @inherit = $properties.attachment_template; - format = $output.format; - loadOp = clear; - storeOp = store; - finalLayout = present_src_khr; - }, - ); - subpasses = ( - { // 0 output - pipelineBindPoint = graphics; - colorAttachments = ( - { // output - attachment = 0; - layout = color_attachment_optimal; - }, - ); - }, - ); -}; diff --git a/libs/video/renderer/vulkan/rp_shadow.plist b/libs/video/renderer/vulkan/rp_shadow.plist deleted file mode 100644 index f56ad2270..000000000 --- a/libs/video/renderer/vulkan/rp_shadow.plist +++ /dev/null @@ -1,50 +0,0 @@ -clearValues = ( - { depthStencil = { depth = 1; stencil = 0; }; }, -); -info = { - color = "[0.2, 0.2, 0.2, 1]"; - subpass_info = ( - { name = depth; color = "[ 0.5, 0.5, 0.5, 1]" }, - ); -}; -renderpass_base = { - attachments = ( - { - format = $output.format; - samples = 1; - loadOp = dont_care; - storeOp = store; - stencilLoadOp = dont_care; - stencilStoreOp = dont_care; - initialLayout = undefined; - finalLayout = shader_read_only_optimal; - }, - ); - subpasses = ( - { // 0 depth - pipelineBindPoint = graphics; - depthStencilAttachment = { - attachment = 0; - layout = depth_stencil_attachment_optimal; - }; - } - ); -}; -renderpass_6 = { - @inherit = $properties.renderpass_base; - @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = (0x0000003fu); - }); -}; -renderpass_4 = { - @inherit = $properties.renderpass_base; - @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = (0x0000000fu); - }); -}; -renderpass_1 = { - @inherit = $properties.renderpass_base; - @next = (VkRenderPassMultiviewCreateInfo, { - viewMasks = (0x00000001u); - }); -}; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 8f5d8bf6a..516829da8 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1838,30 +1838,6 @@ Vulkan_Init_Cvars (void) } static exprsym_t builtin_plist_syms[] = { - { .name = "quake_deferred", - .value = (void *) -#include "libs/video/renderer/vulkan/pl_quake_def.plc" - }, - { .name = "qf_output", - .value = (void *) -#include "libs/video/renderer/vulkan/pl_output.plc" - }, - { .name = "defcube", - .value = (void *) -#include "libs/video/renderer/vulkan/rp_defcube.plc" - }, - { .name = "deferred", - .value = (void *) -#include "libs/video/renderer/vulkan/rp_deferred.plc" - }, - { .name = "shadow", - .value = (void *) -#include "libs/video/renderer/vulkan/rp_shadow.plc" - }, - { .name = "forward", - .value = (void *) -#include "libs/video/renderer/vulkan/rp_forward.plc" - }, { .name = "main_def", .value = (void *) #include "libs/video/renderer/vulkan/rp_main_def.plc" @@ -1870,10 +1846,6 @@ static exprsym_t builtin_plist_syms[] = { .value = (void *) #include "libs/video/renderer/vulkan/smp_quake.plc" }, - { .name = "output", - .value = (void *) -#include "libs/video/renderer/vulkan/rp_output.plc" - }, {} }; static plitem_t **builtin_plists; From f5e7d5fbbcc6fbb1c09779f300cfc6f052ca94ad Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 00:56:35 +0900 Subject: [PATCH 3655/3664] [vulkan] Clean out the old vkparse support functions Lots and lots of deletions. --- libs/video/renderer/vulkan/vkgen/vkalias.r | 10 +- libs/video/renderer/vulkan/vkgen/vkstruct.r | 2 +- libs/video/renderer/vulkan/vkparse.c | 683 -------------------- libs/video/renderer/vulkan/vkparse.h | 32 - libs/video/renderer/vulkan/vkparse.plist | 224 +------ 5 files changed, 10 insertions(+), 941 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index f6c2f17e4..91098ce83 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -47,11 +47,11 @@ if (!type) { // pointer to opaque struct. Probably // VK_DEFINE_NON_DISPATCHABLE_HANDLE or VK_DEFINE_HANDLE - string createInfo = name + "CreateInfo"; - id structObj = (id) Hash_Find (available_types, createInfo); - if (structObj) { - [structObj addToQueue]; - } + //string createInfo = name + "CreateInfo"; + //id structObj = (id) Hash_Find (available_types, createInfo); + //if (structObj) { + // [structObj addToQueue]; + //} } else if ([type class] == [Alias class]) { type = [type resolveType]; if ([type class] == [Struct class]) { diff --git a/libs/video/renderer/vulkan/vkgen/vkstruct.r b/libs/video/renderer/vulkan/vkgen/vkstruct.r index 1b8c9a1f2..f7257de8b 100644 --- a/libs/video/renderer/vulkan/vkgen/vkstruct.r +++ b/libs/video/renderer/vulkan/vkgen/vkstruct.r @@ -374,7 +374,7 @@ write_table (Struct *self, PLItem *field_dict, Array *field_defs, if (have_pNext) { fprintf (output_file, "\t{\"@next\", field_offset (%s, pNext), " - "QFArray, parse_next, 0},", [self outname]); + "QFArray, parse_next, 0},\n", [self outname]); } for (int i = [field_defs count]; i-- > 0; ) { FieldDef *field_def = [field_defs objectAtIndex:i]; diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 516829da8..d0e0d2609 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -603,55 +603,6 @@ QFV_AddHandle (hashtab_t *tab, const char *name, uint64_t handle) Hash_Add (tab, hr); } -static const char * -resource_path (vulkan_ctx_t *ctx, const char *prefix, const char *name) -{ - if (name[0] != '$') { - if (prefix) { - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s.%s", prefix, name); - } else { - name = va (ctx->va_ctx, "$"QFV_PROPERTIES".%s", name); - } - } - return name; -} - -static int -parse_VkRenderPass (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *pctx) -{ - __auto_type handle = (VkRenderPass *) data[0]; - int ret = 1; - exprctx_t ectx = *pctx->ectx; - vulkan_ctx_t *ctx = pctx->vctx; - scriptctx_t *sctx = ctx->script_context; - - const char *name = PL_String (item); - const char *path = resource_path (ctx, 0, name); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkRenderPass: %s\n", path); - - *handle = (VkRenderPass) QFV_GetHandle (sctx->renderpasses, path); - if (*handle) { - return 1; - } - - plitem_t *setItem = 0; - exprval_t result = { &cexpr_plitem, &setItem }; - ectx.result = &result; - ectx.item = item; - ret = !cexpr_eval_string (path, &ectx); - if (ret) { - VkRenderPass setLayout; - setLayout = QFV_ParseRenderPass (ctx, setItem, pctx->properties); - *handle = (VkRenderPass) setLayout; - - // path not guaranteed to survive cexpr_eval_string due to va - path = resource_path (ctx, 0, name); - QFV_AddHandle (sctx->renderpasses, path, (uint64_t) setLayout); - } - return ret; -} - static int parse_VkShaderModule (const plitem_t *item, void **data, plitem_t *messages, parsectx_t *pctx) @@ -677,81 +628,6 @@ parse_VkShaderModule (const plitem_t *item, void **data, return 1; } -static int -parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) -{ - __auto_type handle = (VkDescriptorSetLayout *) data; - int ret = 1; - parsectx_t *pctx = context; - exprctx_t ectx = *pctx->ectx; - vulkan_ctx_t *ctx = pctx->vctx; - scriptctx_t *sctx = ctx->script_context; - - const char *name = PL_String (item); - const char *path = resource_path (ctx, "setLayouts", name); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkDescriptorSetLayout: %s\n", - path); - - *handle = (VkDescriptorSetLayout) QFV_GetHandle (sctx->setLayouts, path); - if (*handle) { - return 1; - } - - plitem_t *setItem = 0; - exprval_t result = { &cexpr_plitem, &setItem }; - ectx.result = &result; - ectx.item = item; - ret = !cexpr_eval_string (path, &ectx); - if (ret) { - VkDescriptorSetLayout setLayout; - setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem, - pctx->properties); - *handle = (VkDescriptorSetLayout) setLayout; - - // path not guaranteed to survive cexpr_eval_string due to va - path = resource_path (ctx, "setLayouts", name); - QFV_AddHandle (sctx->setLayouts, path, (uint64_t) setLayout); - } - return ret; -} - -static int -parse_VkPipelineLayout (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *pctx) -{ - __auto_type handle = (VkPipelineLayout *) data[0]; - int ret = 1; - exprctx_t ectx = *pctx->ectx; - vulkan_ctx_t *ctx = pctx->vctx; - scriptctx_t *sctx = ctx->script_context; - - const char *name = PL_String (item); - const char *path = resource_path (ctx, "pipelineLayouts", name); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkPipelineLayout: %s\n", path); - - *handle = (VkPipelineLayout) QFV_GetHandle (sctx->pipelineLayouts, path); - if (*handle) { - return 1; - } - - plitem_t *setItem = 0; - exprval_t result = { &cexpr_plitem, &setItem }; - ectx.result = &result; - ectx.item = item; - ret = !cexpr_eval_string (path, &ectx); - if (ret) { - VkPipelineLayout layout; - layout = QFV_ParsePipelineLayout (ctx, setItem, pctx->properties); - *handle = (VkPipelineLayout) layout; - - // path not guaranteed to survive cexpr_eval_string due to va - path = resource_path (ctx, "pipelineLayouts", name); - QFV_AddHandle (sctx->pipelineLayouts, path, (uint64_t) layout); - } - return ret; -} - exprtype_t VkImage_type = { .name = "VkImage", .size = sizeof (VkImage), @@ -768,94 +644,6 @@ exprtype_t VkImageView_type = { .data = 0 }; -static int -parse_VkImage (const plitem_t *item, void **data, plitem_t *messages, - parsectx_t *pctx) -{ - __auto_type handle = (VkImage *) data[0]; - int ret = 1; - exprctx_t ectx = *pctx->ectx; - vulkan_ctx_t *ctx = pctx->vctx; - scriptctx_t *sctx = ctx->script_context; - - const char *name = PL_String (item); - const char *path = resource_path (ctx, "images", name); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImage: %s\n", path); - - *handle = (VkImage) QFV_GetHandle (sctx->images, path); - if (*handle) { - return 1; - } - - exprval_t result = { }; - ectx.result = &result; - ectx.item = item; - ret = !cexpr_eval_string (path, &ectx); - if (ret) { - if (result.type == &cexpr_plitem) { - plitem_t *imageItem = *(plitem_t **) result.value; - VkImage image; - image = QFV_ParseImage (ctx, imageItem, pctx->properties); - *handle = (VkImage) image; - - // path not guaranteed to survive cexpr_eval_string due to va - path = resource_path (ctx, "images", name); - QFV_AddHandle (sctx->images, path, (uint64_t) image); - } else if (result.type == &VkImage_type) { - *handle = *(VkImage *) result.value; - } else { - ret = 0; - } - } - return ret; -} - -static int -parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data, - plitem_t *messages, void *context) -{ - parsectx_t *pctx = context; - __auto_type handle = (VkImageView *) data; - int ret = 1; - exprctx_t ectx = *pctx->ectx; - vulkan_ctx_t *ctx = pctx->vctx; - scriptctx_t *sctx = ctx->script_context; - - const char *name = PL_String (item); - const char *path = resource_path (ctx, "imageViews", name); - Sys_MaskPrintf (SYS_vulkan_parse, "parse_VkImageView: %s\n", path); - - *handle = (VkImageView) QFV_GetHandle (sctx->imageViews, path); - if (*handle) { - return 1; - } - - exprval_t *value = 0; - exprval_t result = { &cexpr_exprval, &value }; - ectx.result = &result; - ectx.item = item; - ret = !cexpr_eval_string (path, &ectx); - - plitem_t *imageViewItem = 0; - if (ret) { - VkImageView imageView; - if (value->type == &VkImageView_type) { - imageView = *(VkImageView *) value->value; - } else if (value->type == &cexpr_plitem) { - imageView = QFV_ParseImageView (ctx, imageViewItem, - pctx->properties); - // path not guaranteed to survive cexpr_eval_string due to va - path = resource_path (ctx, "imageViews", name); - QFV_AddHandle (sctx->imageViews, path, (uint64_t) imageView); - } else { - PL_Message (messages, item, "not a VkImageView"); - return 0; - } - *handle = (VkImageView) imageView; - } - return ret; -} - static const char * handleref_getkey (const void *hr, void *unused) { @@ -1000,15 +788,6 @@ renderpass_free (void *hr, void *_ctx) static hashtab_t *enum_symtab; -static int -parse_BasePipeline (const plitem_t *item, void **data, - plitem_t *messages, parsectx_t *pctx) -{ - *(VkPipeline *) data = 0; - PL_Message (messages, item, "not implemented"); - return 0; -} - typedef struct data_array_s DARRAY_TYPE(byte) data_array_t; static void data_array (const exprval_t **params, exprval_t *result, exprctx_t *context) @@ -1287,239 +1066,6 @@ parse_object (vulkan_ctx_t *ctx, memsuper_t *memsuper, plitem_t *plist, return 1; } -VkRenderPass -QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) -{ - memsuper_t *memsuper = new_memsuper (); - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - - VkRenderPassCreateInfo cInfo = {}; - - if (!parse_object (ctx, memsuper, plist, parse_VkRenderPassCreateInfo, - &cInfo, properties)) { - delete_memsuper (memsuper); - return 0; - } - - VkRenderPass renderpass; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseRenderPass: %d", - PL_Line (plist))); - dfunc->vkCreateRenderPass (device->dev, &cInfo, 0, &renderpass); - qfvPopDebug (ctx); - - delete_memsuper (memsuper); - return renderpass; -} - -VkPipeline -QFV_ParseComputePipeline (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties) -{ - memsuper_t *memsuper = new_memsuper (); - qfv_device_t *device = ctx->device; - - __auto_type cInfo = QFV_AllocComputePipelineCreateInfoSet (1, alloca); - memset (&cInfo->a[0], 0, sizeof (cInfo->a[0])); - - if (!parse_object (ctx, memsuper, plist, parse_VkComputePipelineCreateInfo, - &cInfo->a[0], properties)) { - delete_memsuper (memsuper); - return 0; - } - - qfvPushDebug (ctx, va (ctx->va_ctx, - "QFV_ParseComputePipeline: %d", PL_Line (plist))); - - __auto_type plSet = QFV_CreateComputePipelines (device, 0, cInfo); - qfvPopDebug (ctx); - VkPipeline pipeline = plSet->a[0]; - free (plSet); - delete_memsuper (memsuper); - return pipeline; -} - -VkPipeline -QFV_ParseGraphicsPipeline (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties) -{ - memsuper_t *memsuper = new_memsuper (); - qfv_device_t *device = ctx->device; - - __auto_type cInfo = QFV_AllocGraphicsPipelineCreateInfoSet (1, alloca); - memset (&cInfo->a[0], 0, sizeof (cInfo->a[0])); - - if (!parse_object (ctx, memsuper, plist, parse_VkGraphicsPipelineCreateInfo, - &cInfo->a[0], properties)) { - delete_memsuper (memsuper); - return 0; - } - - qfvPushDebug (ctx, va (ctx->va_ctx, - "QFV_ParsePipeline: %d", PL_Line (plist))); - - __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); - qfvPopDebug (ctx); - VkPipeline pipeline = plSet->a[0]; - free (plSet); - delete_memsuper (memsuper); - return pipeline; -} - -VkDescriptorPool -QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - memsuper_t *memsuper = new_memsuper (); - - VkDescriptorPoolCreateInfo cInfo = {}; - - if (!parse_object (ctx, memsuper, plist, parse_VkDescriptorPoolCreateInfo, - &cInfo, properties)) { - delete_memsuper (memsuper); - return 0; - } - - VkDescriptorPool pool; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseDescriptorPool: %d", PL_Line (plist))); - dfunc->vkCreateDescriptorPool (device->dev, &cInfo, 0, &pool); - qfvPopDebug (ctx); - - delete_memsuper (memsuper); - return pool; -} - -VkDescriptorSetLayout -QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - memsuper_t *memsuper = new_memsuper (); - - VkDescriptorSetLayoutCreateInfo cInfo = {}; - - if (!parse_object (ctx, memsuper, plist, - parse_VkDescriptorSetLayoutCreateInfo, - &cInfo, properties)) { - delete_memsuper (memsuper); - return 0; - } - - VkDescriptorSetLayout setLayout; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseDescriptorSetLayout: %d", PL_Line (plist))); - dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, &setLayout); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, - setLayout, va (ctx->va_ctx, "descriptorSetLayout:%d", - PL_Line (plist))); - qfvPopDebug (ctx); - - delete_memsuper (memsuper); - return setLayout; -} - -VkPipelineLayout -QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - memsuper_t *memsuper = new_memsuper (); - - VkPipelineLayoutCreateInfo cInfo = {}; - - if (!parse_object (ctx, memsuper, plist, parse_VkPipelineLayoutCreateInfo, - &cInfo, properties)) { - delete_memsuper (memsuper); - return 0; - } - - VkPipelineLayout layout; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParsePipelineLayout: %d", PL_Line (plist))); - dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &layout); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, - layout, va (ctx->va_ctx, "pipelineLayout:%d", - PL_Line (plist))); - qfvPopDebug (ctx); - - delete_memsuper (memsuper); - return layout; -} - -VkSampler -QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - memsuper_t *memsuper = new_memsuper (); - - VkSamplerCreateInfo cInfo = {}; - - if (!parse_object (ctx, memsuper, plist, parse_VkSamplerCreateInfo, &cInfo, - properties)) { - delete_memsuper (memsuper); - return 0; - } - - VkSampler sampler; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseSampler: %d", PL_Line (plist))); - dfunc->vkCreateSampler (device->dev, &cInfo, 0, &sampler); - qfvPopDebug (ctx); - - delete_memsuper (memsuper); - return sampler; -} - -VkImage -QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - memsuper_t *memsuper = new_memsuper (); - - VkImageCreateInfo cInfo = {}; - - if (!parse_object (ctx, memsuper, plist, parse_VkImageCreateInfo, &cInfo, - properties)) { - delete_memsuper (memsuper); - return 0; - } - - VkImage image; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImage: %d", PL_Line (plist))); - dfunc->vkCreateImage (device->dev, &cInfo, 0, &image); - qfvPopDebug (ctx); - - delete_memsuper (memsuper); - return image; -} - -VkImageView -QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - memsuper_t *memsuper = new_memsuper (); - - VkImageViewCreateInfo cInfo = {}; - - if (!parse_object (ctx, memsuper, plist, parse_VkImageViewCreateInfo, - &cInfo, properties)) { - delete_memsuper (memsuper); - return 0; - } - - VkImageView imageView; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImageView: %d", PL_Line (plist))); - dfunc->vkCreateImageView (device->dev, &cInfo, 0, &imageView); - qfvPopDebug (ctx); - - delete_memsuper (memsuper); - return imageView; -} - typedef struct { uint32_t count; VkImageCreateInfo *info; @@ -1530,192 +1076,6 @@ typedef struct { VkImageViewCreateInfo *info; } imageviewcreate_t; -static plelement_t qfv_imagecreate_dict = { - QFDictionary, - sizeof (VkImageCreateInfo), - vkparse_alloc, - parse_VkImageCreateInfo, -}; - -static plelement_t qfv_imageviewcreate_dict = { - QFDictionary, - sizeof (VkImageViewCreateInfo), - vkparse_alloc, - parse_VkImageViewCreateInfo, -}; - -static int -parse_imagecreate_dict (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) -{ - plfield_t f = { "images", 0, QFArray, parse_array, - &qfv_imagecreate_dict }; - typedef struct arr_s DARRAY_TYPE(byte) arr_t; - arr_t *arr = 0; - int ret; - - if ((ret = PL_ParseLabeledArray (&f, item, &arr, messages, context))) { - imagecreate_t *imagecreate = data; - imagecreate->count = arr->size; - imagecreate->info = (VkImageCreateInfo *) arr->a; - } - return ret; -} - -static int -parse_imageviewcreate_dict (const plfield_t *field, const plitem_t *item, - void *data, plitem_t *messages, void *context) -{ - plfield_t f = { "images", 0, QFArray, parse_array, - &qfv_imageviewcreate_dict }; - typedef struct arr_s DARRAY_TYPE(byte) arr_t; - arr_t *arr = 0; - int ret; - - if ((ret = PL_ParseLabeledArray (&f, item, &arr, messages, context))) { - imageviewcreate_t *imageviewcreate = data; - imageviewcreate->count = arr->size; - imageviewcreate->info = (VkImageViewCreateInfo *) arr->a; - } else { - //FIXME leaky boat when succeeds - if (arr) { - free (arr); - } - } - return ret; -} - -qfv_imageset_t * -QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) -{ - scriptctx_t *sctx = ctx->script_context; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - memsuper_t *memsuper = new_memsuper (); - - imagecreate_t create = {}; - - pltype_t type = PL_Type (item); - - if (type == QFDictionary) { - if (!parse_object (ctx, memsuper, item, parse_imagecreate_dict, - &create, properties)) { - delete_memsuper (memsuper); - return 0; - } - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Neither array nor dictionary: %d\n", - PL_Line (item)); - delete_memsuper (memsuper); - return 0; - } - - __auto_type set = QFV_AllocImages (create.count, malloc); - for (uint32_t i = 0; i < create.count; i++) { - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImageSet: %d", PL_Line (item))); - dfunc->vkCreateImage (device->dev, &create.info[i], 0, &set->a[i]); - - const char *name = PL_KeyAtIndex (item, i); - QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, set->a[i], - va (ctx->va_ctx, "image:%s", name)); - qfvPopDebug (ctx); - name = resource_path (ctx, "images", name); - QFV_AddHandle (sctx->images, name, (uint64_t) set->a[i]); - } - - delete_memsuper (memsuper); - return set; -} - -qfv_imageviewset_t * -QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, - plitem_t *properties) -{ - scriptctx_t *sctx = ctx->script_context; - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - memsuper_t *memsuper = new_memsuper (); - - imageviewcreate_t create = {}; - - pltype_t type = PL_Type (item); - - if (type == QFDictionary) { - if (!parse_object (ctx, memsuper, item, parse_imageviewcreate_dict, - &create, properties)) { - delete_memsuper (memsuper); - return 0; - } - } else { - Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item)); - delete_memsuper (memsuper); - return 0; - } - - __auto_type set = QFV_AllocImageViews (create.count, malloc); - for (uint32_t i = 0; i < create.count; i++) { - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImageViewSet: %d", PL_Line (item))); - dfunc->vkCreateImageView (device->dev, &create.info[i], 0, &set->a[i]); - qfvPopDebug (ctx); - - const char *name = PL_KeyAtIndex (item, i); - name = resource_path (ctx, "imageViews", name); - QFV_AddHandle (sctx->imageViews, name, (uint64_t) set->a[i]); - } - - delete_memsuper (memsuper); - return set; -} - -VkFramebuffer -QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) -{ - qfv_device_t *device = ctx->device; - qfv_devfuncs_t *dfunc = device->funcs; - memsuper_t *memsuper = new_memsuper (); - - VkFramebufferCreateInfo cInfo = {}; - - if (!parse_object (ctx, memsuper, plist, parse_VkFramebufferCreateInfo, - &cInfo, properties)) { - delete_memsuper (memsuper); - return 0; - } - - VkFramebuffer framebuffer; - qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseFramebuffer: %d", PL_Line (plist))); - dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); - qfvPopDebug (ctx); - Sys_MaskPrintf (SYS_vulkan_parse, "framebuffer, renderPass: %#zx, %#zx\n", - (size_t) framebuffer, (size_t) cInfo.renderPass); - - delete_memsuper (memsuper); - return framebuffer; -} - -static int -parse_rgba (const plfield_t *field, const plitem_t *item, void *data, - plitem_t *messages, void *context) -{ - return parse_RGBA (item, &data, messages, context); -} - -int -QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, - plitem_t *properties) -{ - memsuper_t *memsuper = new_memsuper (); - int ret = 0; - vec4f_t color; - - if (parse_object (ctx, memsuper, plist, parse_rgba, &color, properties)) { - memcpy (rgba, &color, sizeof (color)); - ret = 1; - } - delete_memsuper (memsuper); - return ret; -} - int QFV_ParseOutput (vulkan_ctx_t *ctx, qfv_output_t *output, plitem_t *plist, plitem_t *properties) @@ -1886,23 +1246,6 @@ delete_configs (void) free (builtin_plists); } -static plitem_t * -qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name) -{ - scriptctx_t *sctx = ctx->script_context; - if (!sctx->pipelineDef) { - sctx->pipelineDef = Vulkan_GetConfig (ctx, "quake_deferred"); - } - - plitem_t *item = sctx->pipelineDef; - if (!item || !(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading %s\n", name); - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found %s def\n", name); - } - return item; -} - plitem_t * Vulkan_GetConfig (vulkan_ctx_t *ctx, const char *name) { @@ -1997,32 +1340,6 @@ void Vulkan_Script_SetOutput (vulkan_ctx_t *ctx, qfv_output_t *output) sctx->output = *output; } -VkSampler -Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name) -{ - scriptctx_t *sctx = ctx->script_context; - hashtab_t *tab = sctx->samplers; - const char *path; - path = va (ctx->va_ctx, "$"QFV_PROPERTIES".samplers.%s", name); - __auto_type sampler = (VkSampler) QFV_GetHandle (tab, path); - if (sampler) { - return sampler; - } - - plitem_t *item = qfv_load_pipeline (ctx, "samplers"); - if (!(item = PL_ObjectForKey (item, name))) { - Sys_Printf ("error loading sampler %s\n", name); - return 0; - } else { - Sys_MaskPrintf (SYS_vulkan_parse, "Found sampler def %s\n", name); - } - sampler = QFV_ParseSampler (ctx, item, sctx->pipelineDef); - QFV_AddHandle (tab, path, (uint64_t) sampler); - QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler, - va (ctx->va_ctx, "sampler:%s", name)); - return sampler; -} - exprtab_t * QFV_CreateSymtab (plitem_t *dict, const char *properties, const char **extra_items, exprsym_t *extra_syms, diff --git a/libs/video/renderer/vulkan/vkparse.h b/libs/video/renderer/vulkan/vkparse.h index a12be0701..edb86615a 100644 --- a/libs/video/renderer/vulkan/vkparse.h +++ b/libs/video/renderer/vulkan/vkparse.h @@ -42,38 +42,6 @@ exprenum_t *QFV_GetEnum (const char *name); uint64_t QFV_GetHandle (struct hashtab_s *tab, const char *name); void QFV_AddHandle (struct hashtab_s *tab, const char *name, uint64_t handle); -VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); -VkPipeline QFV_ParseComputePipeline (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); -VkPipeline QFV_ParseGraphicsPipeline (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); -VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); -VkDescriptorSetLayout QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, - plitem_t *plist, - plitem_t *properties); -VkPipelineLayout QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); -VkSampler QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); -VkImage QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); -VkImageView QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); -struct qfv_imageset_s *QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); -struct qfv_imageviewset_s *QFV_ParseImageViewSet (vulkan_ctx_t *ctx, - plitem_t *plist, - plitem_t *properties); -VkFramebuffer QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, - plitem_t *properties); - -struct qfv_subpassset_s *QFV_ParseSubpasses (vulkan_ctx_t *ctx, - plitem_t *plist, - plitem_t *properties); -int QFV_ParseRGBA (vulkan_ctx_t *ctx, float *rgba, plitem_t *plist, - plitem_t *properties); int QFV_ParseOutput (vulkan_ctx_t *ctx, qfv_output_t *output, plitem_t *plist, plitem_t *properties); exprtab_t *QFV_CreateSymtab (plitem_t *dict, const char *properties, diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index be33db563..7d8212c2f 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -1,9 +1,6 @@ search = ( - VkAttachmentDescription, VkDebugUtilsMessageSeverityFlagBitsEXT, VkPresentModeKHR, - VkSubpassDescription, - VkSubpassDependency, VkSpecializationInfo, VkPipelineShaderStageCreateInfo, VkPipelineVertexInputStateCreateInfo, @@ -15,19 +12,8 @@ search = ( VkPipelineColorBlendStateCreateInfo, VkPipelineDynamicStateCreateInfo, VkDescriptorSetLayoutBinding, - VkDescriptorSetLayoutCreateInfo, - VkPushConstantRange, - VkPipelineLayoutCreateInfo, - VkGraphicsPipelineCreateInfo, - VkComputePipelineCreateInfo, - VkDescriptorPoolCreateInfo, - VkSamplerCreateInfo, - VkImageCreateInfo, - VkImageViewCreateInfo, - VkFramebufferCreateInfo, VkClearValue, VkPhysicalDeviceLimits, - VkRenderPassCreateInfo, VkRenderPassMultiviewCreateInfo, qfv_output_t, @@ -58,53 +44,7 @@ search = ( qfv_samplerinfo_t, ); parse = { - VkSubpassDescription = { - flags = auto; - pipelineBindPoint = auto; - inputAttachments = { - type = (array, VkAttachmentReference); - size = inputAttachmentCount; - values = pInputAttachments; - }; - colorAttachments = { - type = (array, VkAttachmentReference); - size = colorAttachmentCount; - values = pColorAttachments; - }; - resolveAttachments = { - type = (array, VkAttachmentReference); - values = pResolveAttachments; - matchSize = colorAttachments; - }; - depthStencilAttachment = { - type = (single, VkAttachmentReference); - value = pDepthStencilAttachment; - }; - preserveAttachments = { - type = (array, uint32_t); - size = preserveAttachmentCount; - values = pPreserveAttachments; - }; - }; VkPhysicalDeviceLimits = readonly; - VkRenderPassCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - attachments = { - type = (array, VkAttachmentDescription); - size = attachmentCount; - values = pAttachments; - }; - subpasses = { - type = (array, VkSubpassDescription); - size = subpassCount; - values = pSubpasses; - }; - dependencies = { - type = (array, VkSubpassDependency); - size = dependencyCount; - values = pDependencies; - }; - }; VkSpecializationInfo = { mapEntries = { type = (array, VkSpecializationMapEntry); @@ -141,23 +81,6 @@ parse = { stageFlags = auto; // skip pImmutableSamplers (default to 0) until I know how it works }; - VkDescriptorSetLayoutCreateInfo = { - flags = auto; - bindings = { - type = (array, VkDescriptorSetLayoutBinding); - size = bindingCount; - values = pBindings; - }; - }; - VkDescriptorPoolCreateInfo = { - flags = auto; - maxSets = auto; - bindings = { - type = (array, VkDescriptorPoolSize); - size = poolSizeCount; - values = pPoolSizes; - }; - }; VkPipelineVertexInputStateCreateInfo = { //flags = auto; reserved for future use (Bits enum does not exist) bindings = { @@ -246,140 +169,10 @@ parse = { values = pDynamicStates; }; }; - VkPipelineLayoutCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - setLayouts = { - type = (array, { - parse_type = (QFDictionary, QFString); - type = VkDescriptorSetLayout; - parser = parse_VkDescriptorSetLayout; - }); - size = setLayoutCount; - values = pSetLayouts; - }; - pushConstantRanges = { - type = (array, VkPushConstantRange); - size = pushConstantRangeCount; - values = pPushConstantRanges; - }; - }; VkPipelineTessellationStateCreateInfo = { //flags = auto; reserved for future use (Bits enum does not exist) patchControlPoints = auto; }; - VkGraphicsPipelineCreateInfo = { - flags = auto; - stages = { - type = (array, VkPipelineShaderStageCreateInfo); - size = stageCount; - values = pStages; - }; - vertexInput = { - type = (single, VkPipelineVertexInputStateCreateInfo); - value = pVertexInputState; - }; - inputAssembly = { - type = (single, VkPipelineInputAssemblyStateCreateInfo); - value = pInputAssemblyState; - }; - tessellation = { - type = (single, VkPipelineTessellationStateCreateInfo); - value = pTessellationState; - }; - viewport = { - type = (single, VkPipelineViewportStateCreateInfo); - value = pViewportState; - }; - rasterization = { - type = (single, VkPipelineRasterizationStateCreateInfo); - value = pRasterizationState; - }; - multisample = { - type = (single, VkPipelineMultisampleStateCreateInfo); - value = pMultisampleState; - }; - depthStencil = { - type = (single, VkPipelineDepthStencilStateCreateInfo); - value = pDepthStencilState; - }; - colorBlend = { - type = (single, VkPipelineColorBlendStateCreateInfo); - value = pColorBlendState; - }; - dynamic = { - type = (single, VkPipelineDynamicStateCreateInfo); - value = pDynamicState; - }; - layout = { - type = (custom, QFString, parse_VkPipelineLayout); - fields = (layout); - }; - renderPass = { - type = (custom, QFString, parse_VkRenderPass); - fields = (renderPass); - }; - subpass = auto; - basePipelineHandle = { - type = (custom, QFString, parse_BasePipeline); - fields = (basePipelineHandle); - }; - basePipelineIndex = auto; - }; - VkComputePipelineCreateInfo = { - flags = auto; - stage = auto; - layout = { - type = (custom, QFString, parse_VkPipelineLayout); - fields = (layout); - }; - basePipelineHandle = { - type = (custom, QFString, parse_BasePipeline); - fields = (basePipelineHandle); - }; - basePipelineIndex = auto; - }; - VkImageCreateInfo = { - flags = auto; - imageType = auto; - format = auto; - extent = auto; - mipLevels = auto; - arrayLayers = auto; - samples = auto; - tiling = auto; - usage = auto; - sharingMode = skip; // FIXME for now - queueFamilyIndexCount = skip; // FIXME for now - pQueueFamilyIndices = skip; // FIXME for now - initialLayout = auto; - }; - VkImageViewCreateInfo = { - flags = auto; - image = { - type = (custom, (QFDictionary, QFString), - parse_VkImage); - fields = (image); - }; - viewType = auto; - format = auto; - components = auto; - subresourceRange = auto; - }; - VkFramebufferCreateInfo = { - //flags = auto; reserved for future use (Bits enum does not exist) - renderPass = { - type = (custom, QFString, parse_VkRenderPass); - fields = (renderPass); - }; - attachments = { - type = (array, VkImageView); - size = attachmentCount; - values = pAttachments; - }; - width = auto; - height = auto; - layers = auto; - }; VkClearColorValue = skip; VkClearValue = { color = { @@ -406,28 +199,19 @@ parse = { }; }; - qfv_osubpass_s = { - .name = qfv_osubpass_t; - color = { - type = (custom, QFString, parse_RGBA); - fields = (color); - }; - name = { - type = string; - string = name; - }; - }; qfv_output_s = { .name = qfv_output_t; extent = auto; - image = { + image = ignore; + view = ignore; +/* image = { type = (readonly, VkImage); value = image; }; view = { type = (readonly, VkImageView); value = view; - }; + };*/ format = auto; frames = auto; finalLayout = auto; From 0a50fb1bf12b82fdd0150fa962dcc95c0ee6f0a8 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 10:59:16 +0900 Subject: [PATCH 3656/3664] [cexpr] Add support for the bool type It's currently rather limited, but enough to make use of it in vkgen and vkparse. --- include/QF/cexpr.h | 2 ++ libs/util/cexpr-type.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/QF/cexpr.h b/include/QF/cexpr.h index b035275c7..0d08d5ead 100644 --- a/include/QF/cexpr.h +++ b/include/QF/cexpr.h @@ -140,6 +140,8 @@ void cexpr_init_symtab (exprtab_t *symtab, exprctx_t *ctx); char *cexpr_yyget_text (void *scanner); +extern exprenum_t cexpr_bool_enum; +extern exprtype_t cexpr_bool; extern exprtype_t cexpr_int; extern exprtype_t cexpr_uint; extern exprtype_t cexpr_size_t; diff --git a/libs/util/cexpr-type.c b/libs/util/cexpr-type.c index 656a36da7..3eff83c57 100644 --- a/libs/util/cexpr-type.c +++ b/libs/util/cexpr-type.c @@ -66,6 +66,57 @@ pre##_##opname (const exprval_t *a, exprval_t *b, exprctx_t *ctx) \ (*(type *) b->value) = op (*(type *) a->value); \ } +BINOP(bool, and, bool, &) +BINOP(bool, or, bool, |) +BINOP(bool, xor, bool, ^) + +UNOP(bool, not, bool, !) + +static const char * +bool_get_string (const exprval_t *val, va_ctx_t *va_ctx) +{ + return val->value ? "true" : "false"; +} + +binop_t bool_binops[] = { + { '&', &cexpr_bool, &cexpr_bool, bool_and }, + { '|', &cexpr_bool, &cexpr_bool, bool_or }, + { '^', &cexpr_bool, &cexpr_bool, bool_xor }, + { '=', &cexpr_plitem, &cexpr_bool, cexpr_cast_plitem }, + {} +}; + +unop_t bool_unops[] = { + { '!', &cexpr_bool, bool_not }, + {} +}; + +exprtype_t cexpr_bool = { + .name = "bool", + .size = sizeof (bool), + .binops = bool_binops, + .unops = bool_unops, + .data = &cexpr_bool_enum, + .get_string = bool_get_string, +}; + +static int bool_values[] = { + false, + true, +}; +static exprsym_t bool_symbols[] = { + {"false", &cexpr_bool, bool_values + 0}, + {"true", &cexpr_bool, bool_values + 1}, + {} +}; +static exprtab_t bool_symtab = { + bool_symbols, +}; +exprenum_t cexpr_bool_enum = { + &cexpr_bool, + &bool_symtab, +}; + BINOP(int, shl, int, <<) BINOP(int, shr, int, >>) BINOP(int, add, int, +) From 3e28ad62f4ec7467834d73cdbea437e197b018b7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 11:00:51 +0900 Subject: [PATCH 3657/3664] [vkgen] Add support for c23 bool Even though I'm not using c23 yet :P (properly). --- libs/video/renderer/vulkan/vkgen/stdint.h | 3 +- libs/video/renderer/vulkan/vkgen/vkalias.r | 56 ++++++++++++---------- libs/video/renderer/vulkan/vkgen/vkgen.r | 1 + 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/libs/video/renderer/vulkan/vkgen/stdint.h b/libs/video/renderer/vulkan/vkgen/stdint.h index 77dce217f..5b598953c 100644 --- a/libs/video/renderer/vulkan/vkgen/stdint.h +++ b/libs/video/renderer/vulkan/vkgen/stdint.h @@ -9,5 +9,6 @@ typedef int int16_t; typedef int int32_t; typedef int int64_t; typedef int size_t; -typedef struct char { int x; } char; +typedef struct char { int x; } char;//FIXME add char to qfcc +typedef struct bool { int x; } bool;//FIXME add bool to qfcc #endif//__vkgen_stdint_h diff --git a/libs/video/renderer/vulkan/vkgen/vkalias.r b/libs/video/renderer/vulkan/vkgen/vkalias.r index 91098ce83..477b3a455 100644 --- a/libs/video/renderer/vulkan/vkgen/vkalias.r +++ b/libs/video/renderer/vulkan/vkgen/vkalias.r @@ -77,6 +77,9 @@ id enumObj = [(id) Hash_Find (available_types, name) resolveType]; return [enumObj cexprType]; } + if (name == "bool") { + return "cexpr_bool"; + } if (name == "uint32_t") { return "cexpr_uint"; } @@ -101,12 +104,15 @@ return [enumObj parseType]; } } - if (name == "VkBool32") { - id enumObj = [(id) Hash_Find (available_types, name) resolveType]; - return [enumObj parseType]; - } - if (name == "uint32_t" || name == "size_t" || name == "vec4f_t") { - return "QFString"; + switch (name) { + case "VkBool32": + id enumObj = [(id) Hash_Find (available_types, name) resolveType]; + return [enumObj parseType]; + case "uint32_t": + case "size_t": + case "vec4f_t": + case "bool": + return "QFString"; } return [alias parseType]; } @@ -123,12 +129,14 @@ return [enumObj parseFunc]; } } - if (name == "VkBool32") { - id enumObj = [(id) Hash_Find (available_types, name) resolveType]; - return [enumObj parseFunc]; - } - if (name == "uint32_t") { - return "parse_uint32_t"; + switch (name) { + case "VkBool32": + id enumObj = [(id) Hash_Find (available_types, name) resolveType]; + return [enumObj parseFunc]; + case "bool": + return "parse_enum"; + case "uint32_t": + return "parse_uint32_t"; } return [alias parseFunc]; } @@ -145,18 +153,18 @@ return [enumObj parseData]; } } - if (name == "VkBool32") { - id enumObj = [(id) Hash_Find (available_types, name) resolveType]; - return [enumObj parseData]; - } - if (name == "uint32_t") { - return "0"; - } - if (name == "vec4f_t") { - return "&cexpr_vector"; - } - if (name == "size_t") { - return "&cexpr_size_t"; + switch (name) { + case "VkBool32": + id enumObj = [(id) Hash_Find (available_types, name) resolveType]; + return [enumObj parseData]; + case "uint32_t": + return "0"; + case "bool": + return "&cexpr_bool_enum"; + case "vec4f_t": + return "&cexpr_vector"; + case "size_t": + return "&cexpr_size_t"; } return [alias parseData]; } diff --git a/libs/video/renderer/vulkan/vkgen/vkgen.r b/libs/video/renderer/vulkan/vkgen/vkgen.r index dd68df56e..2c4618d8a 100644 --- a/libs/video/renderer/vulkan/vkgen/vkgen.r +++ b/libs/video/renderer/vulkan/vkgen/vkgen.r @@ -212,6 +212,7 @@ main(int argc, string *argv) if ([obj class] == [Struct class]) { string name = [obj name]; if (name == "char" // char type faked via a struct + || name == "bool" // bool type faked via a struct || [[parse getObjectForKey:name] string] == "skip") { continue; } From fc949de24fba5fa9670670f490fb2b1466681d14 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 11:51:12 +0900 Subject: [PATCH 3658/3664] [cexpr] Fall back to a linear search if no hash While hash tables are useful for large symbol tables, the bool "enum" is too small to justify one and even bsearch is too expensive (also, bsearch requires knowing the number of elements, which is a bit of a hassle currently). --- libs/util/cexpr-lex.l | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libs/util/cexpr-lex.l b/libs/util/cexpr-lex.l index ef91d414d..0bb03246d 100644 --- a/libs/util/cexpr-lex.l +++ b/libs/util/cexpr-lex.l @@ -326,7 +326,16 @@ parse_name (const char *name, exprctx_t *context) } prev_tab = symtab; - sym = Hash_Find (symtab->tab, name); + if (symtab->tab) { + sym = Hash_Find (symtab->tab, name); + } else { + for (exprsym_t *s = symtab->symbols; s->name; s++) { + if (!strcmp (s->name, name)) { + sym = s; + break; + } + } + } } if (!sym) { sym = cmemalloc (context->memsuper, sizeof (exprsym_t)); From 25dfa75505dc36da02739d8bde6044522d2af3a6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 11:54:28 +0900 Subject: [PATCH 3659/3664] [vulkan] Support disabling pipelines This is useful for selecting post-processing pipelines at run-time. --- include/QF/Vulkan/render.h | 2 ++ libs/video/renderer/vulkan/render.c | 6 ++++++ libs/video/renderer/vulkan/render_load.c | 1 + libs/video/renderer/vulkan/vkparse.plist | 1 + 4 files changed, 10 insertions(+) diff --git a/include/QF/Vulkan/render.h b/include/QF/Vulkan/render.h index 10cb3b47e..adc7b4fdb 100644 --- a/include/QF/Vulkan/render.h +++ b/include/QF/Vulkan/render.h @@ -166,6 +166,7 @@ typedef struct qfv_attachmentsetinfo_s { typedef struct qfv_pipelineinfo_s { vec4f_t color; const char *name; + bool disabled; uint32_t num_tasks; qfv_taskinfo_t *tasks; @@ -309,6 +310,7 @@ typedef struct qfv_label_s { typedef struct qfv_pipeline_s { qfv_label_t label; + bool disabled; VkPipelineBindPoint bindPoint; vec4u_t dispatch; VkPipeline pipeline; diff --git a/libs/video/renderer/vulkan/render.c b/libs/video/renderer/vulkan/render.c index 05084d022..9c8b6e95f 100644 --- a/libs/video/renderer/vulkan/render.c +++ b/libs/video/renderer/vulkan/render.c @@ -81,6 +81,9 @@ run_tasks (uint32_t task_count, qfv_taskinfo_t *tasks, qfv_taskctx_t *ctx) static void run_pipeline (qfv_pipeline_t *pipeline, qfv_taskctx_t *taskctx) { + if (pipeline->disabled) { + return; + } qfv_device_t *device = taskctx->ctx->device; qfv_devfuncs_t *dfunc = device->funcs; auto cmd = taskctx->cmd; @@ -158,6 +161,9 @@ static void run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx) { + if (pipeline->disabled) { + return; + } qfv_device_t *device = ctx->device; qfv_devfuncs_t *dfunc = device->funcs; dfunc->vkCmdBindPipeline (cmd, pipeline->bindPoint, pipeline->pipeline); diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index 719473f87..fa1bf3792 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -753,6 +753,7 @@ init_pipeline (qfv_pipeline_t *pl, qfv_pipelineinfo_t *plinfo, .name = plinfo->name, .color = plinfo->color, }, + .disabled = plinfo->disabled, .bindPoint = is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS, .pipeline = is_compute ? s->ptr.cpl[s->inds.num_comp_pipelines] diff --git a/libs/video/renderer/vulkan/vkparse.plist b/libs/video/renderer/vulkan/vkparse.plist index 7d8212c2f..2efc22846 100644 --- a/libs/video/renderer/vulkan/vkparse.plist +++ b/libs/video/renderer/vulkan/vkparse.plist @@ -327,6 +327,7 @@ parse = { type = string; string = name; }; + disabled = auto; tasks = { type = (array, qfv_taskinfo_t); size = num_tasks; From ab4ea1b33389925d4f87530c69b79b455709510c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 11:55:15 +0900 Subject: [PATCH 3660/3664] [vulkan] Fix incorrect reference to imageviews The old system used just "views", but I had at some time decided that I might want to support specifying buffers and buffer views, but forgot to change the name in vkparse.c. --- libs/video/renderer/vulkan/vkparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index d0e0d2609..2c395bee2 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -1431,7 +1431,7 @@ QFV_ParseJobInfo (vulkan_ctx_t *ctx, plitem_t *item, qfv_renderctx_t *rctx) static const char *extra_items[] = { "images", - "views", + "imageviews", "renderpasses", 0 }; From 7ba347cb6c87ae32d17c20170ae975aff7539ba9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 12:07:22 +0900 Subject: [PATCH 3661/3664] [vulkan] Get water warp and fisheye mostly working Water warp works quite well, but fisheye is having a little trouble (current issue is framebuffer size mismatch). --- libs/video/renderer/vulkan/rp_main_def.plist | 179 ++++++++++++++++++- libs/video/renderer/vulkan/vulkan_output.c | 140 +++++++++++---- 2 files changed, 285 insertions(+), 34 deletions(-) diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 1a1a33034..b48ae66b2 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -50,6 +50,15 @@ properties = { usage = color_attachment|input_attachment|transient_attachment; initialLayout = undefined; }; + cube_image_base = { + @inherit = $image_base; + extent = { + width = "min($render_output.extent.width,$render_output.extent.height)"; + height = "min($render_output.extent.width,$render_output.extent.height)"; + depth = 1; + }; + arrayLayers = 6; + }; view_base = { viewType = `2d; components = { @@ -64,6 +73,13 @@ properties = { layerCount = 1; }; }; + cube_view_base = { + @inherit = $view_base; + viewType = `2d_array; + subresourceRange = { + layerCount = 6; + }; + }; attachment_base = { samples = 1; loadOp = dont_care; @@ -494,6 +510,11 @@ properties = { name = main; module = $builtin/fstriangle.vert; }; + vertexst = { + stage = vertex; + name = main; + module = $builtin/fstrianglest.vert; + }; }; }; lighting = { @@ -880,6 +901,37 @@ images = { usage = color_attachment|input_attachment|sampled; format = $render_output.format; }; + cube_depth = { + @inherit = $cube_image_base; + format = x8_d24_unorm_pack32; + usage = depth_stencil_attachment|input_attachment|transient_attachment; + }; + cube_color = { + @inherit = $cube_image_base; + format = r8g8b8a8_unorm; + }; + cube_emission = { + @inherit = $cube_image_base; + format = r16g16b16a16_sfloat; + }; + cube_normal = { + @inherit = $cube_image_base; + format = r16g16b16a16_sfloat; + }; + cube_position = { + @inherit = $cube_image_base; + format = r32g32b32a32_sfloat; + }; + cube_opaque = { + @inherit = $cube_image_base; + format = r16g16b16a16_sfloat; + }; + cube_output = { + @inherit = $cube_image_base; + flags = cube_compatible; + usage = color_attachment|input_attachment|sampled; + format = $render_output.format; + }; }; imageviews = { depth = { @@ -919,7 +971,46 @@ imageviews = { @inherit = $view_base; image = output; format = $render_output.format; - } + }; + cube_depth = { + @inherit = $cube_view_base; + image = cube_depth; + format = $images.cube_depth.format; + subresourceRange = { + aspectMask = depth; + }; + }; + cube_color = { + @inherit = $cube_view_base; + image = cube_color; + format = $images.cube_color.format; + }; + cube_emission = { + @inherit = $cube_view_base; + image = cube_emission; + format = $images.cube_emission.format; + }; + cube_normal = { + @inherit = $cube_view_base; + image = cube_normal; + format = $images.cube_normal.format; + }; + cube_position = { + @inherit = $cube_view_base; + image = cube_position; + format = $images.cube_position.format; + }; + cube_opaque = { + @inherit = $cube_view_base; + image = cube_opaque; + format = $images.cube_opaque.format; + }; + cube_output = { + @inherit = $cube_view_base; + viewType = cube; + image = cube_output; + format = $render_output.format; + }; }; output = { view = $output; @@ -1334,6 +1425,56 @@ renderpasses = { viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); viewOffsets = ( 0, 0, 0, 0, 0); }); + framebuffer = { + width = $render_output.extent.width; + height = $render_output.extent.height; + layers = 1; + attachments = { + depth = { + @inherit = $attachment_base; + format = $images.cube_depth.format; + loadOp = clear; + finalLayout = depth_stencil_attachment_optimal; + clearValue = { depthStencil = { depth = 1; stencil = 0; }; }; + view = cube_depth; + }; + color = { + @inherit = $attachment_base; + format = $images.cube_color.format; + loadOp = clear; + view = cube_color; + }; + emission = { + @inherit = $attachment_base; + format = $images.cube_emission.format; + loadOp = clear; + view = cube_emission; + }; + normal = { + @inherit = $attachment_base; + format = $images.cube_normal.format; + view = cube_normal; + }; + position = { + @inherit = $attachment_base; + format = $images.cube_position.format; + view = cube_position; + }; + opaque = { + @inherit = $attachment_base; + format = $images.cube_opaque.format; + view = cube_opaque; + }; + output = { + @inherit = $attachment_base; + format = $render_output.format; + loadOp = clear; + storeOp = store; + finalLayout = $render_output.finalLayout; + view = cube_output; + }; + }; + }; }; output = { color = "[0, 1, 1, 1]"; @@ -1360,7 +1501,7 @@ renderpasses = { color = $color.output; tasks = ( - { func = output_draw; }, + { func = output_draw_flat; }, ); stages = ( @@ -1369,6 +1510,36 @@ renderpasses = { ); layout = $output.layout; }; + waterwarp = { + @inherit = $compose_base; + disabled = true; + + color = $color.output; + tasks = ( + { func = output_draw_waterwarp; }, + ); + + stages = ( + $fstriangle.shader.vertexst, + $waterwarp.shader.fragment, + ); + layout = $waterwarp.layout; + }; + fisheye = { + @inherit = $compose_base; + disabled = true; + + color = $color.output; + tasks = ( + { func = output_draw_fisheye; }, + ); + + stages = ( + $fstriangle.shader.vertexst, + $fisheye.shader.fragment, + ); + layout = $fisheye.layout; + }; slice = { @inherit = $compose_base; @@ -1471,6 +1642,8 @@ steps = { dependencies = (wait_on_fence); process = { tasks = ( + { func = output_select_renderpass; + params = ("\"main\""); }, { func = update_framebuffer; params = ("\"main\""); }, { func = particle_wait_physics; }, @@ -1494,6 +1667,8 @@ steps = { params = ("\"output\""); }, { func = update_input; params = ("\"main\""); }, + { func = output_select_pipeline; + params = ("\"output\""); }, { func = flush_draw; }, ); }; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index 513fc0603..d4af8b16c 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -161,9 +161,53 @@ update_input (const exprval_t **params, exprval_t *result, exprctx_t *ectx) } static void -output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +output_select_pipeline (const exprval_t **params, exprval_t *result, + exprctx_t *ectx) { auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto output = QFV_GetStep (params[0], ctx->render_context->job); + // FIXME the output render pass has only one subpass + auto sp = output->render->active->subpasses; + + // FIXME the output render pass pipelines are in the order + // output, waterwarp, fisheye, followed by any additional pipelines + if (scr_fisheye) { + sp->pipelines[0].disabled = true; + sp->pipelines[1].disabled = true; + sp->pipelines[2].disabled = false; + } else if (r_dowarp) { + sp->pipelines[0].disabled = true; + sp->pipelines[1].disabled = false; + sp->pipelines[2].disabled = true; + } else { + sp->pipelines[0].disabled = false; + sp->pipelines[1].disabled = true; + sp->pipelines[2].disabled = true; + } +} + +static void +output_select_renderpass (const exprval_t **params, exprval_t *result, + exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + auto ctx = taskctx->ctx; + auto main = QFV_GetStep (params[0], ctx->render_context->job); + // FIXME the main render step has only two renderpasses + auto render = main->render; + + if (scr_fisheye) { + render->active = &render->renderpasses[1]; + } else { + render->active = &render->renderpasses[0]; + } +} + +static void +output_draw (qfv_taskctx_t *taskctx, + int num_push_constants, qfv_push_constants_t *push_constants) +{ auto ctx = taskctx->ctx; auto device = ctx->device; auto dfunc = device->funcs; @@ -172,45 +216,54 @@ output_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx) auto layout = taskctx->pipeline->layout; auto cmd = taskctx->cmd; - //__auto_type pipeline = octx->output; - //if (scr_fisheye) { - // pipeline = octx->fisheye; - // layout = octx->fish_layout; - //} else if (r_dowarp) { - // pipeline = octx->waterwarp; - // layout = octx->warp_layout; - //} - VkDescriptorSet set[] = { Vulkan_Matrix_Descriptors (ctx, ctx->curFrame), oframe->set, }; dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, 2, set, 0, 0); -#if 0 - if (scr_fisheye) { - float width = r_refdef.vrect.width; - float height = r_refdef.vrect.height; - - float ffov = scr_ffov * M_PI / 360; - float aspect = height / width; - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &ffov }, - { VK_SHADER_STAGE_FRAGMENT_BIT, 4, sizeof (float), &aspect }, - }; - QFV_PushConstants (device, cmd, layout, 2, push_constants); - } else if (r_dowarp) { - float time = vr_data.realtime; - qfv_push_constants_t push_constants[] = { - { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &time }, - }; - QFV_PushConstants (device, cmd, layout, 1, push_constants); + if (num_push_constants) { + QFV_PushConstants (device, cmd, layout, + num_push_constants, push_constants); } -#endif dfunc->vkCmdDraw (cmd, 3, 1, 0, 0); } +static void +output_draw_flat (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + output_draw (taskctx, 0, 0); +} + +static void +output_draw_waterwarp (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + float time = vr_data.realtime; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &time }, + }; + output_draw (taskctx, 1, push_constants); +} + +static void +output_draw_fisheye (const exprval_t **params, exprval_t *result, exprctx_t *ectx) +{ + auto taskctx = (qfv_taskctx_t *) ectx; + float width = r_refdef.vrect.width; + float height = r_refdef.vrect.height; + + float ffov = scr_ffov * M_PI / 360; + float aspect = height / width; + qfv_push_constants_t push_constants[] = { + { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof (float), &ffov }, + { VK_SHADER_STAGE_FRAGMENT_BIT, 4, sizeof (float), &aspect }, + }; + output_draw (taskctx, 2, push_constants); +} + static exprtype_t *stepref_param[] = { &cexpr_string, }; @@ -222,14 +275,37 @@ static exprfunc_t update_input_func[] = { { .func = update_input, .num_params = 1, .param_types = stepref_param }, {} }; -static exprfunc_t output_draw_func[] = { - { .func = output_draw }, +static exprfunc_t output_select_pipeline_func[] = { + { .func = output_select_pipeline, + .num_params = 1, .param_types = stepref_param }, + {} +}; +static exprfunc_t output_select_renderpass_func[] = { + { .func = output_select_renderpass, + .num_params = 1, .param_types = stepref_param }, + {} +}; +static exprfunc_t output_draw_flat_func[] = { + { .func = output_draw_flat }, + {} +}; +static exprfunc_t output_draw_waterwarp_func[] = { + { .func = output_draw_waterwarp }, + {} +}; +static exprfunc_t output_draw_fisheye_func[] = { + { .func = output_draw_fisheye }, {} }; static exprsym_t output_task_syms[] = { { "acquire_output", &cexpr_function, acquire_output_func }, { "update_input", &cexpr_function, update_input_func }, - { "output_draw", &cexpr_function, output_draw_func }, + { "output_select_pipeline", &cexpr_function, output_select_pipeline_func }, + { "output_select_renderpass", &cexpr_function, + output_select_renderpass_func }, + { "output_draw_flat", &cexpr_function, output_draw_flat_func }, + { "output_draw_waterwarp", &cexpr_function, output_draw_waterwarp_func }, + { "output_draw_fisheye", &cexpr_function, output_draw_fisheye_func }, {} }; From 8f1de6865f77b4cf79dca8593c1d7595d11a9a85 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 14:03:19 +0900 Subject: [PATCH 3662/3664] [vulkan] Get fisheye working except for translucency The OIT heads buffer is only a single-layer image, which breaks cube map rendering, but once this is sorted, it looks like fisheye will work well. --- include/QF/Vulkan/qf_output.h | 1 - libs/video/renderer/vulkan/render_load.c | 1 + libs/video/renderer/vulkan/rp_main_def.plist | 6 +++--- libs/video/renderer/vulkan/vulkan_output.c | 7 ------- libs/video/renderer/vulkan/vulkan_vid_common.c | 6 ++++++ 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/include/QF/Vulkan/qf_output.h b/include/QF/Vulkan/qf_output.h index 17a31e8a5..7ddfaddbb 100644 --- a/include/QF/Vulkan/qf_output.h +++ b/include/QF/Vulkan/qf_output.h @@ -54,6 +54,5 @@ struct vulkan_ctx_s; void Vulkan_Output_Init (struct vulkan_ctx_s *ctx); void Vulkan_Output_Setup (struct vulkan_ctx_s *ctx); void Vulkan_Output_Shutdown (struct vulkan_ctx_s *ctx); -void Vulkan_Output_SetInput (struct vulkan_ctx_s *ctx, VkImageView input); #endif//__QF_Vulkan_qf_output_h diff --git a/libs/video/renderer/vulkan/render_load.c b/libs/video/renderer/vulkan/render_load.c index fa1bf3792..6e75292be 100644 --- a/libs/video/renderer/vulkan/render_load.c +++ b/libs/video/renderer/vulkan/render_load.c @@ -720,6 +720,7 @@ init_rpCreate (uint32_t index, const qfv_renderinfo_t *rinfo, objstate_t *s) *s->rpc = (VkRenderPassCreateInfo) { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .pNext = s->rpi->pNext, .attachmentCount = s->rpi->framebuffer.num_attachments, .pAttachments = attachments, .subpassCount = s->rpi->num_subpasses, diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index b48ae66b2..5b8dc0ab5 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1423,11 +1423,10 @@ renderpasses = { @inherit = $renderpasses.deferred; @next = (VkRenderPassMultiviewCreateInfo, { viewMasks = (0x3fu, 0x3fu, 0x3fu, 0x3fu, 0x3fu); - viewOffsets = ( 0, 0, 0, 0, 0); }); framebuffer = { - width = $render_output.extent.width; - height = $render_output.extent.height; + width = "min($render_output.extent.width,$render_output.extent.height)"; + height = "min($render_output.extent.width,$render_output.extent.height)"; layers = 1; attachments = { depth = { @@ -1475,6 +1474,7 @@ renderpasses = { }; }; }; + output = cube_output; }; output = { color = "[0, 1, 1, 1]"; diff --git a/libs/video/renderer/vulkan/vulkan_output.c b/libs/video/renderer/vulkan/vulkan_output.c index d4af8b16c..5306c3797 100644 --- a/libs/video/renderer/vulkan/vulkan_output.c +++ b/libs/video/renderer/vulkan/vulkan_output.c @@ -363,10 +363,3 @@ Vulkan_Output_Shutdown (vulkan_ctx_t *ctx) free (octx->frames.a); free (octx); } - -void -Vulkan_Output_SetInput (vulkan_ctx_t *ctx, VkImageView input) -{ - outputctx_t *octx = ctx->output_context; - octx->input = input; -} diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index c11133339..7cbb5a1cb 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -209,4 +209,10 @@ Vulkan_ConfigOutput (vulkan_ctx_t *ctx, qfv_output_t *output) if (vulkan_frame_height > 0) { output->extent.height = vulkan_frame_height; } + if (scr_fisheye) {//FIXME + auto w = output->extent.width; + auto h = output->extent.height; + output->extent.width = min (w, h); + output->extent.height = min (w, h); + } } From 614ca744abc9585b6b1f2a3880234cb2331e08d1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 18:00:46 +0900 Subject: [PATCH 3663/3664] [vulkan] Support multi-layer OIT rendering This fixes fisheye rendering. I'm not too happy with always allocating the cube OIT heads buffer, but that's for another day. --- include/QF/Vulkan/qf_translucent.h | 4 +- .../renderer/vulkan/vulkan_translucent.c | 72 +++++++++++++------ 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/include/QF/Vulkan/qf_translucent.h b/include/QF/Vulkan/qf_translucent.h index 1e8079d32..19003576c 100644 --- a/include/QF/Vulkan/qf_translucent.h +++ b/include/QF/Vulkan/qf_translucent.h @@ -19,8 +19,10 @@ typedef struct qfv_transtate_s { } qfv_transtate_t; typedef struct translucentframe_s { - VkDescriptorSet descriptors; + VkDescriptorSet flat; + VkDescriptorSet cube; VkImage heads; + VkImage cube_heads; VkBuffer state; } translucentframe_t; diff --git a/libs/video/renderer/vulkan/vulkan_translucent.c b/libs/video/renderer/vulkan/vulkan_translucent.c index 637df03bc..fdae8fc21 100644 --- a/libs/video/renderer/vulkan/vulkan_translucent.c +++ b/libs/video/renderer/vulkan/vulkan_translucent.c @@ -84,8 +84,9 @@ clear_translucent (const exprval_t **params, exprval_t *result, exprctx_t *ectx) }; dfunc->vkBeginCommandBuffer (cmd, &beginInfo); + auto image = scr_fisheye ? tframe->cube_heads : tframe->heads; qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst]; - ib.barrier.image = tframe->heads; + ib.barrier.image = image; ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, @@ -96,11 +97,11 @@ clear_translucent (const exprval_t **params, exprval_t *result, exprctx_t *ectx) VkImageSubresourceRange ranges[] = { { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, VK_REMAINING_ARRAY_LAYERS }, }; - dfunc->vkCmdClearColorImage (cmd, tframe->heads, + dfunc->vkCmdClearColorImage (cmd, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear_color, 1, ranges); ib = imageBarriers[qfv_LT_TransferDst_to_General]; - ib.barrier.image = tframe->heads; + ib.barrier.image = image; ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; dfunc->vkCmdPipelineBarrier (cmd, ib.srcStages, ib.dstStages, 0, 0, 0, 0, 0, @@ -153,7 +154,8 @@ Vulkan_Translucent_Setup (vulkan_ctx_t *ctx) auto dsmanager = QFV_Render_DSManager (ctx, "oit_set"); for (size_t i = 0; i < frames; i++) { tctx->frames.a[i] = (translucentframe_t) { - .descriptors = QFV_DSManager_AllocSet (dsmanager), + .flat = QFV_DSManager_AllocSet (dsmanager), + .cube = QFV_DSManager_AllocSet (dsmanager), }; } Vulkan_Translucent_CreateBuffers (ctx, ctx->swapchain->extent);//FIXME @@ -179,8 +181,9 @@ Vulkan_Translucent_Shutdown (vulkan_ctx_t *ctx) VkDescriptorSet Vulkan_Translucent_Descriptors (vulkan_ctx_t *ctx, int frame) { - __auto_type tctx = ctx->translucent_context; - return tctx->frames.a[frame].descriptors; + auto tctx = ctx->translucent_context; + auto tframe = &tctx->frames.a[frame]; + return scr_fisheye ? tframe->cube : tframe->flat; } void @@ -200,23 +203,25 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) tctx->resources = 0; } tctx->resources = malloc (sizeof (qfv_resource_t) - // heads image - + frames * sizeof (qfv_resobj_t) - // heads image view - + frames * sizeof (qfv_resobj_t) + // heads images (flat + cube) + + sizeof (qfv_resobj_t[frames]) * 2 + // heads image views (flat + cube) + + sizeof (qfv_resobj_t[frames]) * 2 // fragment buffer - + frames * sizeof (qfv_resobj_t) + + sizeof (qfv_resobj_t[frames]) // fragment count - + frames * sizeof (qfv_resobj_t)); - __auto_type heads_objs = (qfv_resobj_t *) &tctx->resources[1]; - __auto_type head_views_objs = &heads_objs[frames]; - __auto_type buffer_objs = &head_views_objs[frames]; - __auto_type count_objs = &buffer_objs[frames]; + + sizeof (qfv_resobj_t[frames])); + auto heads_objs = (qfv_resobj_t *) &tctx->resources[1]; + auto cube_heads_objs = &heads_objs[frames]; + auto head_views_objs = &cube_heads_objs[frames]; + auto cube_head_views_objs = &head_views_objs[frames]; + auto buffer_objs = &cube_head_views_objs[frames]; + auto count_objs = &buffer_objs[frames]; tctx->resources[0] = (qfv_resource_t) { .name = "oit", .va_ctx = ctx->va_ctx, .memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - .num_objects = 4 * frames, + .num_objects = 6 * frames, .objects = heads_objs, }; for (size_t i = 0; i < frames; i++) { @@ -234,8 +239,13 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) | VK_IMAGE_USAGE_TRANSFER_DST_BIT, }, }; + auto e = min (extent.width, extent.height); + cube_heads_objs[i] = heads_objs[i]; + cube_heads_objs[i].name = va (ctx->va_ctx, "cube_heads:%zd", i); + cube_heads_objs[i].image.extent = (VkExtent3D) { e, e, 1 }; + cube_heads_objs[i].image.num_layers = 6; head_views_objs[i] = (qfv_resobj_t) { - .name = "head view", + .name = heads_objs[i].name, .type = qfv_res_image_view, .image_view = { .image = i, @@ -248,6 +258,9 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) }, }, }; + cube_head_views_objs[i] = head_views_objs[i]; + cube_head_views_objs[i].name = cube_heads_objs[i].name; + cube_head_views_objs[i].image_view.image = i + frames; buffer_objs[i] = (qfv_resobj_t) { .name = va (ctx->va_ctx, "frags:%zd", i), .type = qfv_res_buffer, @@ -271,25 +284,38 @@ Vulkan_Translucent_CreateBuffers (vulkan_ctx_t *ctx, VkExtent2D extent) for (size_t i = 0; i < frames; i++) { __auto_type tframe = &tctx->frames.a[i]; tframe->heads = heads_objs[i].image.image; + tframe->cube_heads = cube_heads_objs[i].image.image; tframe->state = count_objs[i].buffer.buffer; - VkDescriptorImageInfo imageInfo[] = { + VkDescriptorImageInfo flat_imageInfo[] = { { 0, head_views_objs[i].image_view.view, VK_IMAGE_LAYOUT_GENERAL }, }; + VkDescriptorImageInfo cube_imageInfo[] = { + { 0, cube_head_views_objs[i].image_view.view, + VK_IMAGE_LAYOUT_GENERAL }, + }; VkDescriptorBufferInfo bufferInfo[] = { { count_objs[i].buffer.buffer, 0, VK_WHOLE_SIZE }, { buffer_objs[i].buffer.buffer, 0, VK_WHOLE_SIZE }, }; VkWriteDescriptorSet write[] = { { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - tframe->descriptors, 2, 0, 1, + tframe->flat, 2, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - .pImageInfo = imageInfo }, + .pImageInfo = flat_imageInfo }, { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, - tframe->descriptors, 0, 0, 2, + tframe->flat, 0, 0, 2, + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .pBufferInfo = bufferInfo }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + tframe->cube, 2, 0, 1, + VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .pImageInfo = cube_imageInfo }, + { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0, + tframe->cube, 0, 0, 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .pBufferInfo = bufferInfo }, }; - dfunc->vkUpdateDescriptorSets (device->dev, 2, write, 0, 0); + dfunc->vkUpdateDescriptorSets (device->dev, 4, write, 0, 0); } } From 4932987b0855f9268918b45ff60f634018db9e71 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 26 Jun 2023 18:14:38 +0900 Subject: [PATCH 3664/3664] [vulkan] Hook up the view model again And with that, the vulkan renderer is fully back to where it was before this mini-project (and even a little ahead). Time for shadows (finally). --- libs/video/renderer/vulkan/rp_main_def.plist | 1 + libs/video/renderer/vulkan/vulkan_main.c | 36 -------------------- libs/video/renderer/vulkan/vulkan_scene.c | 29 ++++++++++++++++ 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/libs/video/renderer/vulkan/rp_main_def.plist b/libs/video/renderer/vulkan/rp_main_def.plist index 5b8dc0ab5..b4ba6d4c3 100644 --- a/libs/video/renderer/vulkan/rp_main_def.plist +++ b/libs/video/renderer/vulkan/rp_main_def.plist @@ -1627,6 +1627,7 @@ steps = { tasks = ( { func = bsp_visit_world; params = (main); }, + { func = scene_draw_viewmodel; }, ); }; }; diff --git a/libs/video/renderer/vulkan/vulkan_main.c b/libs/video/renderer/vulkan/vulkan_main.c index deb6e4cd5..618da813a 100644 --- a/libs/video/renderer/vulkan/vulkan_main.c +++ b/libs/video/renderer/vulkan/vulkan_main.c @@ -66,43 +66,7 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_vulkan.h" -#if 0 -static void -Vulkan_DrawViewModel (vulkan_ctx_t *ctx) -{ - entity_t ent = vr_data.view_model; - if (!Entity_Valid (ent)) { - return; - } - renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); - if (vr_data.inhibit_viewmodel - || !r_drawviewmodel - || !r_drawentities - || !renderer->model) - return; - EntQueue_AddEntity (r_ent_queue, ent, renderer->model->type); -} - -void -Vulkan_RenderView (qfv_orenderframe_t *rFrame) -{ - vulkan_ctx_t *ctx = rFrame->vulkan_ctx; - - if (!r_refdef.worldmodel) { - return; - } - - Vulkan_DrawWorld (rFrame); - Vulkan_DrawSky (rFrame); - if (Entity_Valid (vr_data.view_model)) { - Vulkan_DrawViewModel (ctx); - } - Vulkan_DrawWaterSurfaces (rFrame); - Vulkan_Bsp_Flush (ctx); - Vulkan_Scene_Flush (ctx); -} -#endif void Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx) { diff --git a/libs/video/renderer/vulkan/vulkan_scene.c b/libs/video/renderer/vulkan/vulkan_scene.c index 2f2fa901e..67874fa26 100644 --- a/libs/video/renderer/vulkan/vulkan_scene.c +++ b/libs/video/renderer/vulkan/vulkan_scene.c @@ -131,9 +131,38 @@ static VkWriteDescriptorSet base_buffer_write = { 0, 0, 0 }; +static void +scene_draw_viewmodel (const exprval_t **params, exprval_t *result, + exprctx_t *ectx) +{ + entity_t ent = vr_data.view_model; + if (!Entity_Valid (ent)) { + return; + } + renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg); + if (vr_data.inhibit_viewmodel + || !r_drawviewmodel + || !r_drawentities + || !renderer->model) + return; + + EntQueue_AddEntity (r_ent_queue, ent, renderer->model->type); +} + +static exprfunc_t scene_draw_viewmodel_func[] = { + { .func = scene_draw_viewmodel }, + {} +}; +static exprsym_t scene_task_syms[] = { + { "scene_draw_viewmodel", &cexpr_function, scene_draw_viewmodel_func }, + {} +}; + void Vulkan_Scene_Init (vulkan_ctx_t *ctx) { + QFV_Render_AddTasks (ctx, scene_task_syms); + scenectx_t *sctx = calloc (1, sizeof (scenectx_t) + sizeof (qfv_resource_t) + sizeof (qfv_resobj_t));